Apply Marvell SDK patch 2.6.25-RC1.

tar xvzf SDK_2.6.25-RC1/Source/Kernel/linux_feroceon-KW2.tar.gz \
--strip-component=1.

NOTE: Ironically, SDK_2.6.25 is not necessarily later releate than
SDK_2.6.75. The kernel version of SDK_2.6.25 is newer while uboot
version is older. But for kernel of 88F6601 product line, Marvell
is settled on 2.6.32.

Change-Id: I2e8becf85c3955019c735cd8d5687fc77a1bd8f2
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..946c7ec
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,77 @@
+#
+# NOTE! Don't add files that are generated in specific
+# subdirectories here. Add them in the ".gitignore" file
+# in that subdirectory instead.
+#
+# NOTE! Please use 'git ls-files -i --exclude-standard'
+# command after changing this file, to see if there are
+# any tracked files which get ignored after the change.
+#
+# Normal rules
+#
+.*
+*.o
+*.o.*
+*.a
+*.s
+*.ko
+*.so
+*.so.dbg
+*.mod.c
+*.i
+*.lst
+*.symtypes
+*.order
+*.elf
+*.bin
+*.gz
+*.bz2
+*.lzma
+*.patch
+*.gcno
+
+#
+# Top-level generic files
+#
+tags
+TAGS
+vmlinux
+System.map
+Module.markers
+Module.symvers
+!.gitignore
+!.mailmap
+
+#
+# Generated include files
+#
+include/asm
+include/asm-*/asm-offsets.h
+include/config
+include/linux/autoconf.h
+include/linux/compile.h
+include/linux/version.h
+include/linux/utsrelease.h
+include/linux/bounds.h
+include/generated
+
+# stgit generated dirs
+patches-*
+
+# quilt's files
+patches
+series
+
+# cscope files
+cscope.*
+ncscope.*
+
+# gnu global files
+GPATH
+GRTAGS
+GSYMS
+GTAGS
+
+*.orig
+*~
+\#*#
diff --git a/LspReadme.txt b/LspReadme.txt
new file mode 100755
index 0000000..618e259
--- /dev/null
+++ b/LspReadme.txt
@@ -0,0 +1,739 @@
+
+General LSP information
+=================================================
+
+Contents:
+---------
+  1.  Default kernel configuration
+  2.  Marvell LSP File locations
+  3.  Procedure for Porting a new Customer Board (KW)
+  4.  MTD (Memory Technology Devices) Support
+  5.  Network
+    5.1 Network driver
+    5.2 Gateway driver 
+    5.3 eth-tool
+  6.  Phone driver
+  7.  SATA
+  8.  USB in HOST mode
+  9. Real Time Clock
+  10. CESA
+  11. Kernel configuration
+    11.1 General Configuration
+    11.2 Run-Time Configuration
+    11.3 Compile-Time Configuration 
+  12. Debugging Tools
+  13. CPUFREQ
+  14. CPU-Idle
+  15. UBIFS
+
+
+
+
+1.  Default kernel configuration
+---------------------------------
+
+	Board			Default Configuration
+==========================================================================================
+	DB-88F6500-BP		mv88f6500_defconfig
+	RD-88F6510-SFU		mv88f6500_defconfig
+	RD-88F6550-GW		mv88f6500_defconfig
+	RD-88F6530-MDU		mv88f6500_defconfig
+
+2.  Marvell LSP File locations
+-------------------------------
+    o  core directory: 
+       - /arch/arm/mach-feroceon-kw2/...
+
+    o drivers:  
+       - /arch/arm/plat-feroceon/...
+
+
+3.  Procedure for Porting a new Customer Board (relevant only for KW2)
+-----------------------------------------------
+The following are the steps for porting a new customer board to the Marvell LSP:
+
+    o Add the Board Specific configuration definitions:
+	File location:
+	~/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
+
+	- MPP pin configuration. Each pin is represented by a nible. Refer the
+	  SoC Datasheet for detailed information about the options and values
+	  per pin.
+
+	- MPP pin direction (input or output). Each MPP pin is represented
+	  with a single bit (1 for input and 0 for output).
+
+	- MPP pin level (default level, high or low) if the MPP pin is a GPIO
+	  and configured to output.
+
+	- Specify the Board ID. This is needed to identify the board. This is
+	  supposed to be synchronized with the board ID passed by the UBoot.
+
+    o Add the Board Specific configuration tables:
+	File location:
+	~/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
+
+	The following configuration options are listed in the order they are
+	present in the "MV_BOARD_INFO" structure.
+
+	- boardName: Set the board name string. This is displayed by both Uboot and Linux
+	  during the boot process.
+
+	- pBoardMppConfigValue (MV_BOARD_MPP_INFO): This structure arranges the MPP pins
+	  configuration. This is usually not modified.
+
+	- intsGppMask: Select MPP pins that are supposed to operate as
+	  interrupt lines.
+
+	- pDevCsInfo (MV_DEV_CS_INFO):Specify the devices connected on the device bus 
+	  with the Chip select configuration.
+
+	- pBoardPciIf (MV_BOARD_PCI_IF): This is the PCI Interface table with the PCI 
+	  device number and MPP pins assigned for each of the 4 interrupts A, B, C and D.
+
+	- pBoardTwsiDev (): List of I2C devices connected on the TWSI
+	  interface with the device ID Addressing mode (10 or 7 bit).
+
+	- pBoardMacInfo (MV_BOARD_MAC_INFO): Specifies the MAC speed and the Phy address
+  	  per Ethernet interface.
+
+	- pBoardGppInfo (): List of MPP pins configured as GPIO pins with special functionality.
+
+	- pLedGppPin (MV_U8): array of the MPP pins connected to LEDs.
+
+	- ledsPolarity: Bitmap specifying the MPP pins to be configured with
+	  reverse polarity.
+
+	- gppOutEnVal: This is usually defined in the mvCustomerBoardEnv.h
+	  specifying the direction of all MPP pins.
+
+	- gppPolarityVal: Not used.
+
+	Finally update all of the configuration table sizes (xxxxxxxxx_NUM definitions)
+  	according to the number of entries in the relevant table.
+
+    o  Specify the memory map of your new board. 
+	File location: ~/arch/arm/mach-feroceon-kw2/sysmap.c
+
+	The following configurations should be done:
+	- Look for the section in the file related to the SoC device you are using.
+
+	- Add a new table with Address Decoding information (MV_CPU_DEC_WIN) for your board.
+	  (Usually existing address decoding tables are compatible with most boards, the 
+	  changes might be only in the Device Chip selects only).
+
+	- In the function "mv_sys_map()", add a new "case:" statement (under the appropriate 
+	  SoC type) with the your newly added board ID mapping it to the appropriate Address 
+	  Decoding configuration table.
+
+
+4.  MTD (Memory Technology Devices) Support
+--------------------------------------------
+
+A new MTD map driver has been added, this driver automatically detects the existing Flash devices
+and mapps it into the Linux MTD subsystem. This new driver affect NOR flashes (CFI, SPI and Marvell). 
+NAND flashes are supported separately and not not part of this driver.
+
+The detection of MTD devices depends on the Linux kernel configuration options set (using the 
+"make menuconfig" or "make xconfig" tools).
+To have basic MTD Support the following options should be selected:
+	-> Device Drivers                                                                                                   
+          -> Memory Technology Devices (MTD)                                                                                
+            -> Memory Technology Device (MTD) support (MTD [=y])                                                            
+
+For CFI Flashes the following options should be selected
+	-> Device Drivers                                                                                                   
+          -> Memory Technology Devices (MTD)                                                                                
+            -> Memory Technology Device (MTD) support (MTD [=y])                                                            
+              -> RAM/ROM/Flash chip drivers 
+		-> Detect flash chips by Common Flash Interface (CFI) probe
+
+For Intel (and Intel compatible) Flashes the following options should be selected
+	-> Device Drivers                                                                                                   
+          -> Memory Technology Devices (MTD)                                                                                
+            -> Memory Technology Device (MTD) support (MTD [=y])                                                            
+              -> RAM/ROM/Flash chip drivers 
+		-> Support for Intel/Sharp flash chips
+
+For AMD (and AMD compatible) Flashes the following options should be selected
+	-> Device Drivers                                                                                                   
+          -> Memory Technology Devices (MTD)                                                                                
+            -> Memory Technology Device (MTD) support (MTD [=y])                                                            
+              -> RAM/ROM/Flash chip drivers 
+		->  Support for AMD/Fujitsu flash chips
+
+By default, the map driver maps the whole flash device as single mtd device (/dev/mtd0, /dev/mtd1, ..)
+unless differently specified from the UBoot using the partitioning mechanism.
+To use the flash partitioning you need to have this option selected in the kernel. To do this
+you will need the following option selected:
+ 	-> Device Drivers                                                                                                   
+          -> Memory Technology Devices (MTD)                                                                                
+            -> Memory Technology Device (MTD) support (MTD [=y])   
+	      -> MTD concatenating support
+
+The exact partitioning is specified from the UBoot arguments passed to the kernel. The following 
+is the syntax of the string to be added to the UBoot "booatargs" environment variable:
+
+       'mtdparts=<mtd-id>:7m@0(rootfs),1m@7(uboot)ro' 
+       where <mtd-id> can be one of options: 
+       1) M-Flash => "marvell_flash"
+       2) SPI-Flash => "spi_flash"
+       3) NOR-Flash => "cfi_flash"
+
+The latest release of the mtd-utils can be downloaded from http://www.linux-mtd.infradead.org.
+(The main page has a link to the latest release of the mtd-utils package).
+This package provides a set of sources that can be compiled and used to manage and debug MTD devices. 
+These tools can be used to erase, read and write MTD devices and to retrieve some basic information.
+
+The following is a list of useful commands:
+To see a list of MTD devices detect by the kernel: "cat /proc/mtd"
+To erase the whole MTD device: "./flash_eraseall /dev/mtd0"
+To erase the whole MTD device and format it with jffs2: "./flash_eraseall -j /dev/mtd1"
+To get device info (sectors size and count): "./flash_info /dev/mtd1"
+To create jffs2 image for NAND flash(with eraseblock size 0x20000): 
+           ./mkfs.jffs2 -l -e 0x20000 -n -d <path_to_fs> -o <output_file>
+
+for NOR flash only:
+===================
+To protect all sectors: "./flash_lock /dev/mtd1 0x0 -1"
+To unprotect all sectors: "./flash_unlock /dev/mtd1"
+
+  NAND ECC:
+  ========
+  The Linux support 1 bit SW ECC protection.
+  This release include support for 4 bit SW ECC Reed Solomon.
+  To enable this support set the relevant config under the feroceon MTD options and configure 
+  the U-Boot to use 4 bit ECC by setting the nandEcc env var to 4bit.
+
+5. network
+----------  
+
+  5.1 Network driver
+---------------------
+    The Network driver supports creating Linux netwrok interfaces over
+    Marvell SoC GbE ports.
+
+    o Configure whether a GbE port is "connected" to Linux (a Linux network
+      interface eth<i> is created) or "disconnected" from Linux (a Linux network
+      interface eth<i> is not created) using kernel command line parameters
+      which can be appended to the console parameter in U-Boot:
+        - mv_port0_config=disconnected
+        - mv_port1_config=disconnected
+        - mv_port2_config=disconnected
+      The default (if no parameter is passed) is that the port is connected.
+
+    o mv_neta_tool user-space application supports runtime configutration of
+      the driver supports displaying various statistics.
+
+    o Additional runtime driver configuration and debug is supported via
+      sysfs:
+        - mount -t sysfs sysfs /sys/
+        - cd /sys/devices/platform/neta/
+        - cd to desired directory (e.g. switch, gbe...)
+        - cat help to display options
+ 
+  5.2 Gateway driver
+---------------------
+    The Gateway driver supports configuring multiple Linux network interfaces
+    over a single GbE port.
+
+    o Gateway driver support depends on the following kernel configuration
+      options: 
+        - Enable CONFIG_MV_INCLUDE_SWITCH   (enabled by default)
+        - Enable CONFIG_MV_ETH_SWITCH       (enabled by default)
+
+	o Each GbE port can be connected to a Switch (internal or on-board Switch).
+	  The Gateway driver configuration is determined in boot time by a kernel command line parameter.
+	  When GbE#0 is connected to the Switch, this command line parameter is called mv_net_config.
+	  When GbE#1 is connected to the Switch, this command line parameter is called mv_net_config1.
+	  When both GbE ports are connected to the Switch, both mv_net_config and mv_net_config1 are used.
+	  If mv_net_config or mv_net_config1 are not passed from U-Boot as command line parameters, 
+	  a default is taken from the compile-time kernel configuration.
+
+    o Select working in Gateway mode / External Switch mode by setting the
+      mvNetConfig parameter in U-Boot.
+        - setenv mvNetConfig mv_net_config=0    means working in External
+          Switch mode (non-Gateway mode). In this mode, Gateway driver
+          features are not supported, and the Switch is not initialised by Linux. 
+          However, the Switch driver (QD HAL) is loaded to provide a handle for further QD driver API calls.
+          Link change prints for Switch ports are also supported.
+
+          Note: the Gateway driver can be used by up to one GbE port connected to the Switch.
+		  In a case when more than one GbE port is connected to the Switch, at least one of the 
+		  mv_net_config parameters must be configured to work in External Switch mode.
+
+          The rest of this section discusses working in Gateway driver mode.
+
+    o Configure network interface (VLANs) initial setup by setting the
+      mvNetConfig parameter in U-Boot:
+      Sysntax: setenv mvNetConfig mv_net_config=<max-ifs>,(<mac-addr>,<port-list>)(...),mtu=<mtu-value>
+      Example: setenv mvNetConfig mv_net_config=3,(00:aa:bb:cc:dd:ee,0:1)(00:11:22:33:44:55,2),mtu=1500
+      means the maximum number of interfaces on the Switch is 3, and currently
+      two interfaces are defined - the first includes ports 0 and 1 with MAC address 00:aa:bb:cc:dd:ee, 
+      and the second includes port 2 with MAC address 00:11:22:33:44:55. Both
+      interfaces share an MTU of 1500.
+
+      Notes: 
+        - Linux will create <max-ifs> network devices (in the example, eth0,
+          eth1 and eth2) for the Gateway interfaces, even if not all interfaces are
+          given a MAC address and port list. 
+        - <max-ifs> should be a number between 1 and 4 (0 is used to select
+          External Switch mode, see above). The Switch has maximum 4
+          "external" ports that can be connected to RJ45 connectors on the
+          board.
+
+    o Interface name format is "eth<i>", e.g., eth0, eth1.
+
+    o Runtime network interface (VLANs) configuration is supported via the
+      mv_neta_tool commands port_add and port_del.
+      Example: in the configuration example above, let's create a new netwrok
+      interface, eth2, which includes Switch port 1 only: 
+        - ifconfig down eth0
+        - mv_neta_tool -port_del eth0 1
+        - mv_neta_tool -port_add eth2 1
+        - ifconfig up eth0
+        - ifconfig eth2 192.168.0.1
+
+      Note: the port parameter is the "logical" port number, between 0 and 3.
+      Logical port numbering:
+      - The description below refers to the DB board and assumes the RJ45
+        connectors are facing to the right.
+      - When Switch is connected to the 3xFE PHYs: the connector at the bottom
+        is logical port 0, the one above it is logical port 1, and the one
+        above that is logical port 2. The top connector of the 4xRJ45
+        connector group is not connected to the Switch.
+        If Switch Port 4 is connected to the internal GbE PHY, then the
+        separate RJ45 connector of the GbE PHY is considered logical port 3.
+
+      Use the mv_neta_tool netdev_sts command to see network device status.
+
+    o Runtime MTU configuration for Gateway interfaces:
+        - Initial MTU value is set in U-Boot parameter mvNetConfig (default is
+          1500).
+        - MTU value must be shared between all Gateway interfaces.
+        - MTU value can be changed at runtime for all Gateway interfaces using
+          this procedure: 
+            - Down all Gateway interfaces using ifconfig eth<i> down.
+            - Change MTU for all Gateway interfaces to the same new MTU value
+              using ifconfig eth<i> mtu <value>.
+            - Up Gateway interfaces as required using ifconfig eth<i> up.
+
+    o Packets between the CPU and the Switch are controlled with Marvell Header.
+
+    o Link status indication is implemented using an ISR.
+
+    o Implementation: 
+        - ~/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/
+        - ~/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/
+
+  5.3 Ethtool support
+  -----------------------
+  This release introduces support for a standard ethtool. 
+  Please note that for non-raw registers dump command the latest ethtool user space utility with Marvell patches is needed.
+
+  The ethtool support should be enabled in kernel configuration:
+   CONFIG_MV_ETH_TOOL:                                                                                                        
+   -> System Type
+     -> Feroceon SoC options  
+       -> SoC Networking support 
+         -> Networking Support
+            -> Control and Statistics               
+
+  The following ethtool commands are supported in current release:
+
+  - ethtool DEVNAME                               Display standard information about device
+
+  - ethtool -s |--change DEVNAME             Change generic options
+            [ speed 10|100|1000 ]
+            [ duplex half|full ]
+            [ autoneg on|off ]
+
+  - ethtool -c|--show-coalesce DEVNAME     Show coalesce options
+
+  - ethtool -C|--coalesce DEVNAME             Set coalesce options
+            [rx-usecs N]
+            [tx-usecs N]
+
+  - ethtool -i|--driver DEVNAME                    Show driver information
+
+  - ethtool -d|--register-dump DEVNAME       Do a register dump
+            [ raw on|off ]
+
+  - ethtool -r|--negotiate DEVNAME              Restart N-WAY negotation
+
+  - ethtool -p|--identify DEVNAME                Show visible port identification (e.g. blinking)
+            [ TIME-IN-SECONDS ]
+
+  - ethtool -S|--statistics DEVNAME             Show adapter statistics
+
+6.  Phone driver
+-------------------
+	After boot process is completed, mv_phone.ko and phone_test.ko kernel modules are required in order to run
+	various voice tests.
+	The phone_test.ko module contains the following tests:
+	1 - Self echo on `line0_id`
+	2 - Loopback between 2 FXS ports(line0_id & line1_id)
+	3 - Loopback between FXS and FXO ports(line0_id & line1_id respectively)
+	4 - Ring on FXS line `line0_id`
+	5 - Generate SW tones(300Hz, 630Hz, 1000Hz) on FXS line `line0_id`
+	6 - Multi FXS loopback test between several pairs of lines(line0_id=<start_line> and line1_id=<end_line>)
+	7 - SLIC register read
+
+	For example, to run loopback test between 2 phones(using 2xFXS module), run the following commands:
+	 > insmod mv_phone.ko phone_config=dev[0-1]:fxs
+	 > insmod phone_test.ko line0_id=0 line1_id=1 test_id=2
+
+	In order to run different test, unload both modules using the standard Linux `rmmod` command and reload them again with
+	the requested `test_id` parameter.
+
+
+7. SATA 
+---------
+	TBD
+
+
+8.  USB in HOST mode
+---------------------
+
+The mode of the USB controller (device or host) is configured using the UBoot environment variables. 
+To work in USB HOST mode, set the UBoot variable "usb0Mode"/"usb1Mode" to "host".
+The USB driver uses the standart Linux ehci driver.
+
+
+9.  Real Time Clock
+---------------------
+
+  The driver is found under ~/arch/arm/mach-feroceon-xx/rtc.c
+To read the date and time from the integrated RTC unit, use the command "hwclock".
+To set the time in the RTC from the current Linux clock, use the command "hwclock --systohc"
+
+
+10.  CESA
+----------
+OpenSSL
+-------
+  see cesa/openssl/
+
+IPsec
+-----
+  see cesa/openswan/
+
+
+11. Kernel configuartion
+-------------------------
+
+ 11.1 General Configuration:
+ ---------------------------
+- This release has support for sending requests with length up to 1MB for the
+  SATA drives, in some cases, this feature can reduce the system performance,
+  for example, running Samba and a client that performs sequential reads.
+  Note that the user can modify the limit of the max request using the sysfs,
+  this parameter is per block device, and it's defined by special file called
+  'max_sectors_kb' under the queue directory of the block device under the sysfs.
+  for example, the /sys/block/sda/queue/max_sectors_kb is for the /dev/sda
+  device.
+
+- In order to use block devices that are larget then 2TB, CONFIG_LBD should be enabled.
+  fdisk doesn't support block devices that are larger then 2TB, instead 'parted' should be used.
+  The msdos partition table doesn't support >2TB , you need GPT support by the kernel:
+  File Systems
+    Partition Types
+      [*] Advanced partition selection
+      [*] EFI GUID Partition support
+
+ 11.2 Run-Time Configuration:
+ ----------------------------
+  The following features can be configured during run-time:
+    o  NFP mechanism:
+  	 echo D > /proc/net/mv_eth_tool (disable NFP)
+  	 echo E > /proc/net/mv_eth_tool (enable NFP)
+    o TX enable race:
+         mv_eth_tool -txen <port> 0/1 (0 - disable, 1 - enable)         
+    o SKB reuse mechanism:
+         mv_eth_tool -skb 0/1 (0 - disable, 1 - enable)
+    o LRO support:
+	 mv_eth_tool -lro <port> 0/1 (0 - disable, 1 - enable)
+ 
+  * for more ethernet run-time configurations, see egigatool help.
+  
+ 11.3 Compile-Time Configuration:
+ --------------------------------
+ The following features can be configured during compile-time only:   
+    o L2 cache support
+    o XOR offload for CPU tasks:
+       - memcpy
+       - copy from/to user
+       - RAID5 XOR calculation
+    o TSO
+    o Multi Q support - for mv_gateway driver only.
+    o CESA test tool support.   
+
+
+12.  Debugging  Tools
+----------------------
+
+    o  Runtime debugging is supported through the /proc virtual FS.
+       See ~/arch/arm/mach-feroceon-xx/proc.c
+
+    o  mv_shell: Access memory, SoC registers, and SMI registers from user space.
+       mv_eth_tool: Probe mv_ethernet driver for statistic counters.
+       mv_cesa_tool: Probe CESA driver for statistic counters.
+       These tools are found under ~/tools
+
+    o The LSP supports kernel debugging using KGDB. Refer to AN232 "Using GDB to Debug the 
+      Linux Kernel and Applications" for detailed information.
+
+    o Early boot debugging is supported by the LSP. To enable this option configure the following
+      settings in the kernel.
+	-> Kernel hacking
+	  -> Kernel low-level debugging functions
+      You have this option you need first to enable the "Kernel debugging" tab first.
+  
+      
+13. CPUFREQ
+-----------
+
+ 13.1 Introduction:
+ ------------------
+   The cpufreq driver allows the cpu frequency to be adjusted either manually from userspace or
+   automatically according to given policies. The available policies are defined when the kernel
+   is configured. In order to get/set cpu frequency parameters the cpufreq utils are used.
+
+ 13.2 cpufreq kernel driver:
+ -------------------------
+   The driver implements power save on/off according to the desired cpu frequency.      
+
+ 13.3 kernel configuration:
+ --------------------------
+	- Enable Cpu Frequency scaling and choose userspace governor as default governor
+	- Choose Default CPUFreq governor: userspace
+
+	CONFIG_CPU_FREQ=y
+	CONFIG_CPU_FREQ_TABLE=y
+	# CONFIG_CPU_FREQ_DEBUG is not set
+	CONFIG_CPU_FREQ_STAT=y
+	# CONFIG_CPU_FREQ_STAT_DETAILS is not set	
+	# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+	CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+	CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+	# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+	CONFIG_CPU_FREQ_GOV_USERSPACE=y
+	# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+	# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+	CONFIG_CPU_FREQ_FEROCEON_KW2=y
+
+
+ 13.4 cpufrequtils installation:
+ -------------------------------
+   On a debian system it suffices to say:
+   apt-get install cpufrequtils
+	
+
+ 13.5 Using the cpufreq utilties:
+ --------------------------------
+   -Display information:
+	% cpufreq-info -h
+
+	cpufrequtils 004: cpufreq-info (C) Dominik Brodowski 2004-2006	
+	Report errors and bugs to cpufreq@lists.linux.org.uk, please.
+	Usage: cpufreq-info [options]
+	Options:
+	  -c CPU, --cpu CPU    CPU number which information shall be determined about
+	  -e, --debug          Prints out debug information
+	  -f, --freq           Get frequency the CPU currently runs at, according
+	                       to the cpufreq core *
+	  -w, --hwfreq         Get frequency the CPU currently runs at, by reading
+	                       it from hardware (only available to root) *
+	  -l, --hwlimits       Determine the minimum and maximum CPU frequency allowed *
+	  -d, --driver         Determines the used cpufreq kernel driver *
+	  -p, --policy         Gets the currently used cpufreq policy *
+	  -g, --governors      Determines available cpufreq governors *
+	  -a, --affected-cpus  Determines which CPUs can only switch frequency at the
+	                       same time *
+	  -s, --stats          Shows cpufreq statistics if available
+	  -o, --proc           Prints out information like provided by the /proc/cpufreq
+	                       interface in 2.4. and early 2.6. kernels
+	  -m, --human          human-readable output for the -f, -w and -s parameters
+	  -h, --help           Prints out this screen
+
+	If no argument or only the -c, --cpu parameter is given, debug output about
+	cpufreq is printed which is useful e.g. for reporting bugs.
+	For the arguments marked with *, omitting the -c or --cpu argument is
+	equivalent to setting it to zero
+
+
+	Example Usage:
+	% cpufreq-info
+	cpufrequtils 004: cpufreq-info (C) Dominik Brodowski 2004-2006
+	Report errors and bugs to cpufreq@lists.linux.org.uk, please.
+	analyzing CPU 0:
+	  driver: kw_cpufreq
+	  CPUs which need to switch frequency at the same time: 0
+	  hardware limits: 400 MHz - 1.20 GHz
+	  available frequency steps: 400 MHz, 1.20 GHz
+	  available cpufreq governors: userspace, performance
+	  current policy: frequency should be within 400 MHz and 1.20 GHz.
+	                  The governor "userspace" may decide which speed to use
+	                  within this range.
+	  current CPU frequency is 1.20 GHz (asserted by call to hardware).
+	  cpufreq stats: 400 MHz:0.00%, 1.20 GHz:0.00%  (6)
+ 	
+
+
+   - Setting new cpu frequency:
+	% cpufreq-set -h
+
+	cpufrequtils 004: cpufreq-set (C) Dominik Brodowski 2004-2006
+	Report errors and bugs to cpufreq@lists.linux.org.uk, please.
+	Usage: cpufreq-set [options]
+	Options:	
+	  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be modified
+	  -d FREQ, --min FREQ      new minimum CPU frequency the governor may select
+	  -u FREQ, --max FREQ      new maximum CPU frequency the governor may select
+	  -g GOV, --governor GOV   new cpufreq governor
+	  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace
+	                           governor to be available and loaded
+	  -h, --help           Prints out this screen
+
+	Notes:
+	1. Omitting the -c or --cpu argument is equivalent to setting it to zero
+	2. The -f FREQ, --freq FREQ parameter cannot be combined with any other parameter
+	   except the -c CPU, --cpu CPU parameter
+	3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz
+	   by postfixing the value with the wanted unit name, without any space
+	   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).
+
+
+	Example usage:
+
+	% cpufreq-set -f 1.2GHz
+	% cpufreq-set -f 400MHz
+	
+
+
+ 13.6 Dynamic Frequency Scaling
+ ------------------------------
+   It is possible to let a background daemon (e.g. hald-addon-cpufreq) decide how to
+   scale the cpu frequency according to the system load. For this purpose proceed as follows:
+	- Configure kernel with "ondemand" governor.
+	- Set the default governor to be "userspace".
+	- The governor can also be set from userspace by "cpufreq-set -g"
+
+	- The behaviour of the hald-addon-cpufreq daemon can be configured through sysfs at
+	% ls /sys/devices/system/cpu/cpu0/cpufreq/ondemand/
+	  ignore_nice_load  sampling_rate      sampling_rate_min
+           powersave_bias    sampling_rate_max  up_threshold		
+
+ 13.7 Controlling CPU Freq through procfs
+ ----------------------------------------
+   Automatic CPU frequency scaling can be disabled / enabled using procfs:
+   echo disable > /proc/mv_pm/cpu_freq
+   echo enable > /proc/mv_pm/cpu_freq
+
+   While automatic CPU frequency scaling is disabled, it's possible to
+   change the CPU frequency to fast / slow mode:
+   echo fast > /proc/mv_pm/cpu_freq
+   echo slow > /proc/mv_pm/cpu_freq
+
+   Changing the CPU frequency manually will not update the BogoMIPS (in
+   /proc/cpuinfo).
+
+14. CPU-Idle
+------------
+   CPU Idle framework enables the kernel to select the idle mode in
+   which the system will be running.
+   In order to enable CPU-Idle framework select the following in the
+   kernel config:
+	CONFIG_CPU_IDLE=y
+
+   It's possible to enable / disable CPU-Idle framework from userspace
+   using the following commands:
+     - echo disable > /proc/mv_pm/cpu_idle
+     - echo enable > /proc/mv_pm/cpu_idle
+
+15. UBIFS
+----------
+
+  14.1 Getting the sources:
+  -------------------------
+	- mtd utils with ubifs support: git://git.infradead.org/mtd-utils.git
+	
+  14.2 Compiling mtd utils:
+  -------------------------
+
+	The mtd utils have to be compiled both for arm and for x86 since typically the
+	file system will be generated on a x86 system.
+	The lzo and uuid libraries are needed for compiling and for running the ubi utilities.
+
+  14.3 UBI utilities on the target system:
+  ----------------------------------------
+
+	The following utilities should be on the target system:
+	- ubiformat, ubinfo, ubimkvol, ubirmvol, ubiupdatevol, ubiattach, ubidetach
+
+
+  14.4 Building a ubifs root file system:
+  ---------------------------------------
+
+	- In the following I assume that the root file system is situated in the directory rootfs.
+ 	  Several of the parameters 
+  	  appearing in the following example need to be adjusted to the user's needs and only serve as examples.
+
+	- Create a configuration file ubinize.cfg with the following contents:
+
+	[ubifs]
+	mode=ubi
+	image=tmp_rootfs.img
+	vol_id=0
+	vol_size=90MiB
+	vol_type=dynamic
+	vol_name=rootfs
+	vol_flags=autoresize	
+
+
+	- Execute the following commands:
+
+  	% mkfs.ubifs -g 2 -v -r rootfs -m 2KiB -e 124KiB -c 2047 -o tmp_rootfs.img
+
+  	% ubinize -v -o rootfs_ubi.img -m 2KiB -p 128KiB -s 2048 -O 2048 ubinize.cfg
+  
+  	% rm tmp_rootfs.img
+
+
+	- The file rootfs_ubi.img contains the ubifs image of the root file system.
+
+
+  14.5 Burning ubifs image to flash:
+  ----------------------------------
+
+	Assume we would like to burn an image with the name /tmp/rootfs_ubi.img to the
+ 	mtd partition mtd2. For this purpose execute the following commands on the target system:
+
+	% ubiformat /dev/mtd2 -s 2048 -O 2048 -f /tmp/rootfs_ubi.img
+
+
+  14.6 Booting a ubifs root file system:
+  --------------------------------------
+
+	Assume that mtd2 contains the root file system in the ubivolume named rootfs. In this case
+ 	the following parameters have to be added to the bootargs:
+
+	ubi.mtd=2,2048 root=ubi0:rootfs rootfstype=ubifs
+
+
+ 14.7 Creating/mounting ubi partitions at run time:
+ --------------------------------------------------
+
+	Assume that we want to create a ubi file system with a size of 32MB on mtd2.
+	To this purpose execute the following commands:
+
+	% ubiformat /dev/mtd2 -s 2048
+
+	% ubiattach /dev/ubi_ctrl -m 2 -O 2048
+
+	% ubimkvol /dev/ubi0 -N some_name -s 32MiB
+
+	% mkdir -p /mnt/some_name
+
+	% mount -t ubifs ubi0:some_name /mnt/some_name
+
diff --git a/LspReleaseNotes_KW2.txt b/LspReleaseNotes_KW2.txt
new file mode 100755
index 0000000..c468ef0
--- /dev/null
+++ b/LspReleaseNotes_KW2.txt
@@ -0,0 +1,777 @@
+15/Jul/2012

+

+

+Release notes for KW2 LSP release 3.3.1-PQ

+==========================================

+

+Note: This LSP is compatible with U-Boot release 4.0.0 and above.

+-----

+

+Table of Contents

+-----------------

+

+1.  Contents of this Release

+2.  HowTo build

+3.  Changes from previous releases

+4.  Known Issues

+5.  Notes

+6.  Disclaimer

+

+

+1. Contents of This Release

+===========================

+

+	Included in current release :

+	- Support for ttyS0.

+	- Interrupts handling.

+	- L2 support + optimized cache opertaions.

+	- PEX support.

+	- Standard network interface support for the KW2 giga port.

+  	- Telephony driver.

+	- Legacy NAND flash driver.

+	- Memory transfer accelerations by using the XOR-DMA engine.

+        - RTC support.

+        - Support for passing Marvell Tag list from uboot.

+        - Reset support.

+        - MV shell Proc FS.

+	- PON drivers.

+	- USB host support.

+	- CESA support.

+	- SD/SDIO/MMC driver.

+	- Basic gateway network interface support for integrated switch.

+	- Initial support for COMM unit.

+	- Marvell SATA.

+	- SPI flash driver.

+

+	- This release is a patch to Linux 2.6.32.11 which can be download from

+          (www.kernel.org)

+

+	Binary drivers:

+	- The GPON/EPON drivers are provided as kernel objects

+	  (mv_gpon.ko and mv_epon.ko respectively).

+	  The files can be found under the binaries directory in the

+	  release source tree.

+	- Because of licensing issues, the Voice SLIC drivers cannot be provided 

+  	  in source code form. Thus, a precompiled library of the Slic

+	  drivers are provided under the mv_phone/objs direcotry.

+

+	Unsupported features:

+	- USB device support.

+	- Advanced Gateway (Switch) network interface features:

+	  + All-Multicast mode is not supported in network interfaces

+	    connected to the Switch.

+	  + L2 IGMP Snooping.

+	  + TSO.

+

+	Configuration:

+	--------------

+    	1. mv88f6500_defconfig

+	2. mv88f6500_gw_defconfig

+	3. mv88f6500_be_defconfig

+

+	Supported boards:

+	-----------------

+	1. DB-88F65XX-BP

+	2. RD-88F6510-SFU

+	3. RD-88F6560

+	4. DB-88F6601

+	5. RD-88F6601

+

+2. HowTo build

+===============

+	This release was built using SDK 3.2

+	get linux-2.6.32.11 from www.kernel.org

+	change its name to the release name (linux_feroceon_...).

+	unzip the release.zip in the directory where you put the kernel, say A to replace all.

+	define ARCH & CROSS_COMPILE env variables

+	'export ARCH=arm'

+	'export CROSS_COMPILE=<compiler name>'

+	cd to the kernel directory.

+	'make mrproper'

+	config the kernel:

+	'make <platform>_defconfig' 

+	'make uImage'

+	the kernel uImage will be found under arch/arm/boot/.

+

+3. Changes from previous releases

+=================================

+- Changes from version 3.3.0

+-----------------------------

+o Support both NAND and SPI flash devices in run time.

+o Support SPI flash MX25L25635E with 32bit address cycle mode.

+o Allocate 32MB window size for SPI flash access by CPU(memory mapped).

+

+- Changes from version 3.2.0

+-----------------------------

+o Avanta-MC SoC Support:

+  + Support 6601 device.

+  + Support new DB-88F6601 and RD-88F6601 boards.

+  + Support new SPI flash M25Q128

+  + Support 2 channels TDM

+o Networking:

+ + Fix Ethernet complex 2xMAC to Switch configuration

+ + Fix Switch port init

+ + Fix NETA rx tx special init

+ + PPPoE fixes

+ + Fix NETA BM for HWF only

+o Voice:

+ + Support Zarlink VE89116 single channel SLIC device

+

+- Changes from version 3.1.0

+-----------------------------

+o Networking:

+  + Fix 2 bugs related to link down in PON port.

+  + Add support for L2 deposit via compile-time flag.

+  + Add portMask and cpuMask arguments to mvSysNetaInit() function.

+  + Rearrange L2FW support.

+  + Add support for steering ingress packets to different RXQs according

+    to VLAN priority (with and without PnC).

+  + Fix bug in mv_eth_tx_policy() function.

+  + Fix GRO support.

+  + Fix bug in eth_tool dependencies check.

+  + Fix bug in BM support when only long pools are used.

+  + Check port validity in all functions called from sysfs.

+  + Add PNC support for DSCP and VLAN priority setting on per port base.

+  + Fix bug in WRR configuration.

+  + Change Kconfig defaults for PNC configuration, GRO and others.

+  + NFP changes:

+    ++ Align NFP sources to NFP drop5

+    ++ NFP as kernel module support for static learning mode only

+    ++ NFP classification support update:

+       +++ Add new priority based classification mode

+       +++ Update exact match classification mode

+    ++ Fix NFP support for external network drivers

+    ++ Fix bugs and cleanup

+o Voice:

+  + Support Zarlink SLIC driver for VE880 and VE792 devices in user space.

+  + Port Zarlink VP-API-II SLIC drivers to latest releases both for user and

+    kernel support.

+

+- Changes from version 3.0.0

+-----------------------------

+o Networking:

+  + Support new NFPv2 implementation(replaced NFPv1).

+  + PNC: 

+    ++ Change RINFO bits configuration. Sysfs command pnc/s_rinfo was changed.

+    ++ Add support for dispatching ingress packets to different RXQs accordingly with VLAN priority.

+    ++ Enable/Disable access to PNC from driver in run-time by new sysfs command gbe/pnc.

+    ++ Remove unused PNC features such: LLC/SNAP detection, IGMP detections, SWF support.

+  + mv_neta_tool support is removed.

+  + Change BM configuration framework (effect MTU change processing).

+  + Fix RX and TX coalescing configuration.

+  + Support connection of 2 giga ports to internal switch.

+  + Fix big-endian workaround for chip revision A0.

+  + Enable / disable NETA driver workarounds in compile time via menu "ERRATA / WA".

+  + Fix ethtool functionality.

+  + Add support for RX weight configuration.

+  + Fix TSO implementation: add gateway driver support.

+  + Merge with DSMP and KW40 projects:

+    ++ Multi NAPI and multi core support

+    ++ WoL support

+  + Fix link state processing for PON port

+  + Update transmitted bytes for PON port

+  + Bugs fixes and code cleanup

+o TDM/CommUnit:

+  + Support both 8-bit and 16-bit sample sizes.

+  + Support CommUnit on RD-6560 board.

+  + Fix legacy TDM error handling.

+  + Fix CommUnit data data coherency in Rx path.

+  + Add CommUnit support for Wideband mode.

+  + Fix CommUnit balancing and linear issues.

+  + Support Silicon Labs SLIC devices: 3226x and 3217x.

+  + Support TDM DCO clock.

+  + Support TDM FIQ registeration.

+o UART:

+  + Fix serial hang during kernel uncompressing.

+

+- Changes from version 2.1.0

+-----------------------------

+o Misc:

+  + Added support for thermal sensor (lm-sensors package can be used to retrieve temperature).

+  + Added support for PCI-E error interrupts reporting.

+  + Added option to disable L2 cache through Linux command line parameters (pass noL2 param as

+    part of the bootargs).

+  + Add support for connecting MAC0 & MAC1 to internal switch on DB board.

+  + Added option to disable modules auto-detection on DB board (By changing moduleAutoDetect field

+    in the boardSpec structure).

+  + Switch multi-address mode:

+    ++ Configure RD-SFU to work in multi-address mode for switch registers access.

+    ++ Add support for automatic configuration of switch multi-address mode on DB board, if Ethernet-complex

+       configuration allows.

+  + Fixed bug in MPP output driver configuration when using RGMII-B.

+  + Added support for configuring GE0 / GE1 into MII mode.

+  + Update eth-phy HAL to support initializing the QSGMII phy through the switch SMI bus.

+  + Added new APIs to GPP HAL to configure GPIO blink duration and counter association.

+  + Fix delay value in mvPexInit() from 500ms to 1ms.

+  + Fixed bug in serial driver that caused serial to hang under certain scenarios (implemented serial 

+    registers access limitations according to the spec).

+o Networking:

+  + Added L2 Forwarding demo support.

+  + Network driver is now a platform device driver.

+  + Support for NFP bridging.

+  + Network driver - support multi-core synchronization:

+    ++ New locking mechanism (global read/write lock and per-Tx queue locks).

+    ++ Use atomic bit operations for multi-core of port flags (when needed).

+  + Support removing (cleanup) and re-initialization of network driver in runtime.

+  + Gateway driver: support runtime VLAN configuration via sysfs commands.

+o CESA:

+  + Support Encryption/Authentication parallel mode.

+  + Enable SHA256 support thru ZDMA descriptor.

+  + Support Tunit clock frequency setting in run time(default to 400MHz).

+

+- Changes from version 2.0.5

+-----------------------------

+o Applied 16 patches on top of LSP version 2.0.5.

+o Support A0 chip revision.

+

+- Changes from version 2.0.4

+-----------------------------

+o Networking:

+  + Force modules detection in Linux (Do not rely on U-Boot scanning result).

+  + TxDone handling improvements:

+    ++ Divide TxDone and cleanup functionalities to two separate timers.

+    ++ Add timer(s) only when necessary (instead of always-present periodic timer).

+  + HAL API change:

+    ++ mvNetaTxqSentDescNumGet() - now it only reads counter without change it.

+    ++ To read and decrement together please call new API: mvNetaTxqSentDescProc().

+  + support buffer pool pre-defined size allocation.

+  + Tx and Rx Special processing support:

+  + support changing Tx and Rx ring size at runtime.

+  + Support changing number of buffers (short & long) for port at runtime

+  + Support new sysfs operations:

+    ++ rx_reset

+    ++ txp_reset

+    ++ buf_num

+  + Bug fixes:

+    ++ Fix NFP handling of FIB and NAT rules when using PnC.

+    ++ Fix NFP NAT rule aging.

+    ++ Fix SKB Recycle bug with fragmented packets.

+    ++ Fix tx_done when TX throughput less than RX.

+  + Support multi-cache-line operations (used in network driver / NFP).

+  + Support multi-core environment (synch with Armada XP code base).

+  + Support forcing link status, speed and duplex according to board environment.

+  + Coding style improvements.

+  + Add MH configuration HAL APIs for TPM

+  + Disappear error messages  for ISR error and Oversize packets (use counters)

+o TDM:

+  + Support PCM clock frequency configuration to 8MHz/4MHz/2MHz for bus master side

+    in compile time.

+  + Rearrange mv_phone files and folders to distinguish between TDM and SLIC source code.

+o CESA:

+  + Support SHA256 authentication algorithm.

+  + Support SHA256 tests in mv_cesa_tool.

+o PM:

+  + Support deep idle power up delay.

+

+- Changes from version 2.0.3

+-----------------------------

+o Support Linux Orion watchdog driver.

+o Change Analog Grp1 configuration register setting. 

+o Networking:

+  + Update sysfs commands for "tos to rxq" and "tos to txq" mapping:

+    echo p txq tos > tos_txq  - set <txq> for outgoing IP packets with <tos>, <tos> is decimal

+    changed to:

+    echo p txq tos > txq_tos  - set <txq> for outgoing IP packets with <tos>, <tos> is hexadecimal

+    

+    echo p rxq tos > tos_rxq  - set <rxq> for incoming IP packets with <tos>, <tos> is decimal

+    changed to:

+    echo p rxq tos > rxq_tos  - set <rxq> for incoming IP packets with <tos>, <tos> is hexadecimal

+  + Fix bug in SKB recycle (free pkt if recycle failed)

+  + Change implementation of mvNetaTxqSentDescNumGet() function, it decrements "transmitted" counter automatically.

+    mvNetaTxqSentDescDec() should not be called directly.

+  + Add functions for legacy parser TOS to RXQ mapping and others.

+  + Add debug messages for ISR and POLL.

+  + Disable update of TX descriptor by HW after transmit (save DRAM accesses) - set bit 12 in port configuration

+    register.

+  + Coding style fixes.

+  + Update code releated to PHY access using GbE SMI interface.

+  + Bug fix in Rx descriptors counters when I/F down during traffic.

+o NAND:

+  + Support new nand flash controller(NFC).

+o PM:

+  + Code tuned to support CPU frequency scaling and CPU deep idle simultaneously.

+o TDM:

+  + Support Rx/Tx voice processing in interrupt context - configurable in defcofig.

+  + Stop DMA engines once mvTdmPcmStop() is dispatched - for legacy unit only.

+  + Remove SLIC timer when all channels are disabled.

+

+- Changes from version 2.0.2

+----------------------------

+o Support RD-88F6560 board.

+o CESA:

+  + Support dual CESA engines.

+  + Support requests processing in chain-mode.

+o PM:

+  + Update CPU frequency parameter transition_latency to 5usec instead of 1ms.

+  + Support DRAM self refresh in deep idle mode.

+o PCIe:

+  + Update interface initialization sequence.

+o TDM:

+  + Support voice test application or MMP selection in run-time.

+o NAND:

+  + Relocate legacy NAND driver to arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/

+  + Integrated new NAND controller driver to LSP - not supported yet. 

+o Networking:

+  + Changed CPU performance counters implementation.

+  + NETA driver:

+    ++ FIx bug for TSO.

+    ++ Fix bug for RXQ with more than 255 descriptors.

+    ++ Change API of mvNetaRxDescFill() function.

+    ++ Merge with DSMP driver.

+    ++ Prevent some of ethtool configurations for Giga port connected to switch.

+    ++ Coding style changes.

+    ++ Double invalidate of RX descriptors and buffers to prevent speculative prefetch.

+  + NFP:

+    ++ Add ARP support.

+    ++ Fix mvNfpPnc crush when entry deleted during traffic.

+

+

+- Changes from version 2.0.1

+----------------------------

+o Support SDIO.

+o Support USB host.

+o Support CESA single engine:

+  + Ported IPSec support to OpenSWAN release 2.6.29.

+  + See Known Issues for more details.

+o Support CommUnit - See Known Issues for more details.

+o Remove old files releated to Orion, Disco-Duo and Kirkwood SoC projects.

+o Support 3 defconfig flavors: regular(performance oriented), GW(NAT) and big-endian.

+o TDM:

+  + Fix parallel SPI access bug in SLIC glue driver.

+  + Eliminate SLIC timer routine dispatching in case SLIC module is not exists.

+o PM:

+  + Added CPU Idle support. This enable Linux CPU-Idle framework to shutdown the CPU when it being idle.

+    See LspReadme.txt for more details.

+  + Added CPU frequency scaling support. Using this mechanism, the CPU frequency can be lowered to DDR frequency.

+    See LspReadme.txt for more details.

+o Networking:

+  + Update SKB headroom size to 96B.

+  + Enable SKB recycle.

+  + Don't allocate extrabuff for each TX descriptor if GSO is not supported.

+  + Fix bug in the function mvNetaMaxRxSizeSet().

+  + Add MaxTxSize configuration for TX shaping.

+  + Add new function: MV_STATUS mvNetaTxpMaxTxSizeSet(int port, int txp, int maxTxSize);

+  + Check that TXP and TXQ max burst configuration value must be larger than MaxTxSize.

+  + Update MaxTxSize when MTU changed.

+  + Fix PON MIB counters support:

+    ++ Default RX MIB set to 0.

+    ++ echo mib gp > mib_gpid       - MIB set <mib> for incoming packets with GemPID <gp>

+    ++ echo mib > mib_def           - MIB set <mib> for incoming packets not matched any GemPID

+  + Add new sysfs commands:

+    ++ echo {0|1} > gbe/skb         - enable / disable SKB recycle

+    ++ echo p txp > gbe/wrr_regs    - show WRR registers for <p/txp>

+    ++ echo p rxq v > gbe/rxq       - show RXQ descriptors ring for <p/rxq>. v=0-brief, v=1-full

+    ++ echo p txp txq v > gbe/txq   - show TXQ descriptors ring for <p/txp/txq>. v=0-brief, v=1-full

+  + Fix ethtool functionality:

+  + Fix TSO functionality.

+  + Fix SKB recycle bug.

+  + Fix bug in MTU change.

+  + Fix spinlock functionality.

+  + Add special spinlocks per pool.

+  + Fix PNC AInfo dump.

+  + Fix NFP IPv6 functionality.

+

+

+- Changes from version 2.0.0

+----------------------------

+ o Support big-endian Linux image(use mv88f6500_be_defconfig).

+ o Support NOR flash.

+ o Support SPI flash.

+ o Support 2xPCIe interfaces.

+ o Bug fix: I2C transactions from Linux are supported - eliminate use of

+	    summary bits for main interrupt cause high and main interrupt cause error registers.

+ o Update Marvell Linux I2C driver with following features:

+   + Combine access support.

+   + Add delay after stop.

+   + Port expander support.

+ o Change VMALLOC_END definition from (PAGE_OFFSET + 0x28000000) to (PAGE_OFFSET + 0x30000000) in

+   order to support larger memory range mapping.

+ o Decrease PCIe memory mapping to 16MB.

+ o Networking:

+   + Support Link Detection from QSGMII ports.

+   + Support Link Detection on switch port connected to the GE-PHY using interrupt.

+   + Changed API: mvBoardIsPhyToSwitchP0Connected() -> mvBoardGePhySwitchPortGet().

+   + New API: mvBoardRgmiiASwitchPortGet().

+   + TCAM driver: Fix bug in RXQ display

+   + NFP PMT and HWF support:

+     ++ Add new file mvNfpPmt.c .

+     ++ Add new Kconfig options.

+     ++ Add new sysfs command to allocate TXQ for NFP HWF between inport and outport:

+	echo "rxp p txp txq" > hwf  - use <txp/txq> for NFP HWF flows from <rxp> to <p>

+   + NETA driver(gbe):

+     ++ Set MBUS retry enable.

+   + mv_neta_tool:

+     ++ Add option to display GMAC registers:

+	mv_neta_tool -St gmac <port>

+

+- Changes from version 1.2.0

+----------------------------

+ o Remove Z1 chip revision support.

+ o Support Z2 chip revision.

+ o Support DB-88F65XX-BP and RD-88F6510-SFU boards(Z2).

+ o Networking:

+   + Update PMT entries to 4K.

+   + Update TXQ configuration for hardware forwarding.

+ o The following features are supported for the release:

+   + Support legacy NAND controller.

+   + Support legacy TDM unit(2-channels).

+   + Support single PCIe interface.

+   + Support standard MAC0/MAC1 ethernet complex configuration.

+   + Support new UART controller.

+

+- Changes from version 1.1.0

+----------------------------

+ o Networking:

+   + NFP PPPoE support (disabled by default).

+   + NFP IPv6 support (disabled by default).

+   + NFP choosing TXQ accordingly with TOS value (for IPv4)

+   + Added support for L2 PON special requrements

+	"echo p            > sh_show"    - show port configuration for special TX

+    	"echo p txp txq v  > sh_txq     - set txp/txq for special TX with signal header. txq=-1 means remove entry

+    	"echo p hex v      > sh_mh      - set 2 bytes of MH/GH for special TX with signal header <v>

+    	"echo p hex v      > sh_hw_cmd  - set 4 bytes of TX decriptor field for special TX with signal header <v>

+    	"echo p hex v      > sh_mod     - set 10 bits of modification command for special TX with signal header <v>, 

+					<hex> == 0xFFFF means remove entry.

+   + Run-time configuration of descriptor numbers for RX and TX queues

+	- "echo p txp txq v"	- set number of descriptors <v> for <port/txp/txq>.

+        - "echo p rxq v"	- set number of descriptors <v> for <port/rxq>

+   + NETA driver (neta/gbe)

+	- Change APIs of the following functions:

+		mvNetaPortDisable(MV_NETA_PORT_CTRL* pPortCtrl) => mvNetaPortDisable(int port);

+		mvNetaPortEnable(MV_NETA_PORT_CTRL* pPortCtrl)  => mvNetaPortEnable(int port);

+		mvNetaPortUp(MV_NETA_PORT_CTRL* pPortCtrl)      => mvNetaPortUp(int port);

+		mvNetaPortDown(MV_NETA_PORT_CTRL* pPortCtrl)   	=> mvNetaPortDown(int port);

+		mvNetaLinkStatus(MV_NETA_PORT_CTRL* pPortCtrl, MV_ETH_PORT_STATUS* pStatus); =>

+		  mvNetaLinkStatus(int port, MV_ETH_PORT_STATUS* pStatus) 

+		mvNetaDefaultsSet(MV_NETA_PORT_CTRL* pPortCtrl) => mvNetaDefaultsSet(int port);

+		mvEthTxPolicyRegs(int port, int txp) 		=> mvEthTxpWrrRegs(int port, int txp);

+		mvEthPortCounters(int port);			=> mvEthPortCounters(int port, int txp);

+		mvEthPortRmonCounters(int port);		=> mvEthPortRmonCounters(int port, int txp);

+  	- Move file mvPmt.c from directory neta/gbe to neta/pmt

+   	- Create new file mvPmt.h in the directory neta/pmt

+	- Fix bugs in noBM, noPNC mode

+

+   + PNC driver changes

+	- Change TCAM API

+	  	void sram_sw_set_addinfo(struct tcam_entry* te, unsigned int bit); =>

+		  void sram_sw_set_ainfo(struct tcam_entry* te, unsigned int bits, unsigned int mask);

+	- Change sysfs command

+	from 	- echo a 	> pnc/s_ainfo	- set ainfo bit <a>

+	to 	- echo a b 	> pnc/s_ainfo   - set ainfo value <a> with mask <b>

+	- Fix DSCP configuration

+	- Add IPv4 and IPv6 over PPPoE configuration.

+	- Add IPv6 2 tuple flow configuration.

+   + Performance improvements

+	- Use new file for function reordering (Routing).

+	- Put all debug code under compilation flag.

+

+ o TDM:

+   + Support new software telephony architecture based on TDM/SLIC management seperation.

+     The new model supports mapping of SLIC kernel stack APIs to user space call control

+     application, where TDM(data path) controlled by Marvell soft DSP engine(MMPv2).

+   + VE880/VE792 SLIC/s profile configuration files migrated from kernel space to user space.

+   + Remove support for Silabs 3215 SLIC and 3050 DAA due to new architecture redesign.

+   + Remove SLIC abstraction layer due to new architecture redesign.

+   + Support flexible TDM time slot configuration.         

+   + Support new user space voice test application under /tools/voice/.

+   + Remove support for kernel telephony test module.  

+

+

+- Changes from version 1.0.0-NQ

+-------------------------------

+ o Networking:

+   + Bug fixes:

+    - Fixed bug with promiscuous mode when a Gateway interface is down.

+	- Fixed bug with Tx statistics when using NFP with Gateway interfaces.

+	- Fixed bug with loading Switch driver even when Switch was not connected to any GbE port.

+   + Enabled flow control between GbE port and Switch CPU port.

+   + Added statistics for NFP IPv4 checksum error.

+ o Fixed bug in handling GPIO interrupts for GPP's larger then 31 and

+   smaller than 64.

+ o Fix HAL files copyright header.

+ o Fix bug in Pex clock Sample-At-Reset control functions.

+ o Update RD-88F6560-GW MPP configurations.

+ o Update RD-88F6530-MDU MPP configurations.

+ o Enable runtime detection of CPU to DRAM access configuration.

+

+

+- Changes from version 0.5.0-NQ

+-------------------------------

+ o Networking:

+   + Added RX and TX TOS based QoS support:

+	- Define TXQ for Linux generated traffic accordingly with TOS value in IP header.

+	- Enable up to CONFIG_MV_ETH_PNC_DSCP_PRIO (4) TCAM entries to map TOS value of incoming IP packets to RXQ.

+	- Show RXQ and TXQ TOS map using "sysfs" or "mv_neta_tool"

+   + Add some configurations options for PMT:

+	- Set ETH_TYPE registers.

+	- Set MH registers.

+   + Changed some "mv_neta_tool" and "sysfs" configuration commands:

+	- mv_neta_tool new supported commands:

+	  mv_neta_tool -St tos <port>

+  	  mv_neta_tool -tos <port> <rxq> <tos>

+	- sysfs deleted commands:

+	  echo p txp txq mod > txq_mod  - set owner of TX queue: 0-Free, 1-CPU, 2-HWF

+

+	- sysfs changed commands:

+	  echo a   > pnc/hw_inv_all  -  disable all tcam entries\n" replace "hw_invalidate_all" command

+	  echo a   > pnc/hw_inv      -  disable tcam entry <a>\n" replace "hw_invalidate" command

+	  echo p i > pmt/hw_inv      - disable entry <i> on port <p>\n" replace hw_invalidate command

+

+	- sysfs new commands:

+  	  echo p > gbe/tos             - show RX and TX TOS map for port <p>

+	  echo p > gbe/mac             - show MAC info for port <p>

+	  echo p rxq tos > gbe/tos_rxq - set <rxq> for incoming IP packets with <tos>

+	  echo p txq tos > gbe/tos_txq - set <txq> for outgoing IP packets with <tos>

+	  echo p txp > pmt/hw_regs     - show PM registers

+	  echo p txp i v > pmt/mh_reg  - set MH register <i=0..5> with value <v>

+	  echo p txp i v > pmt/eth_reg - set ETH register <i=0..3> with value <v>

+ o Enable CPU frequency scaling driver.

+ o Changed default NAND partitioning.

+ o Added "pon_type" procfs entry to retrieve board's PON configuration.

+ o Voice:

+   + Support 32 CommUnit channels.

+   + Support Zarlink VE792 SLIC device including power supply

+     initialization.

+   + Implemented CommUnit disable sequence - not fully stable.

+   + Support linear mode - not fully stable.

+   + Enable TDM error statistics monitoring under Linux proc FS.

+   + Fixed end-to-end delay for local call - update CommUnit Rx/Tx

+     interrupts synchronization

+ o Add support for dynamic initialization of EPON MAC address.

+

+

+- Changes from version 0.4.0-NQ

+-------------------------------

+ o Fix copy to user support code, now LSP uses kernel's code for

+   copy-to-user instead of marvell's developed code.

+ o Fixed bug in SDIO initialization.

+ o Fixed SATA host controller initialization for KW2 SoC's.

+ o Fixed bug in ethernet complex detection when SATA & 3xFE are used

+   simultaneously.

+ o Networking:

+   + Network driver printed messages cleanup.

+   + Drop flow control Pause frames in PnC.

+   + Switch: 

+	- Disabling all disconnected ports.

+	- Enabling Flow Control on external ports.

+	- Forcing link up, full-duplex, 1000Mbps speed and flow control for ports connected to a GMAC unit.

+	- Improved Switch state and statistics printout.

+   + Ethtools:

+   	- The interval for ethtool timeout autoneg (MV_ETH_TOOL_AN_TIMEOUT) 

+	  was changed to 5000 (5 seconds) instead of 2000 (2 seconds) due to a timeout

+	- When restaring autonegotioation with mvEthPhyRestarrAN().

+	- AutoNegotation restart was added to ethtools restore setting method and also

+	  in one case in set_pauseparam() (for "ethtool -K autoneg on tx on rx on").

+

+- Changes from version 0.3.0-NQ

+-------------------------------

+ o Added support for Integrated Sata controller.

+ o Add support for SPI flash.

+ o Add auto-detection for user-selected SDIO configuration on KW2-DB.

+ o Fixed issue with Gateway driver not receiving broadcast packets 

+   (packets with MAC broadcast destination address).

+ o Performing SMI accesses using GbE#1 registers.

+ o Fixed minor issue - previously tried to access Switch PHY on port 4 

+   even if port 4 is not connected.

+ o Enabled the Switch CPU port to send flow control PAUSE frames.

+   Notice: The Flow-control feature is still under development and is not 

+   fully supported in this version.

+ o Fixed issue with NFP not checking L4 checksum.

+ o NFP: Removed debug prints.

+

+- Changes from version 0.2.0-NQ

+-------------------------------

+ o Networking:

+   + Support init-time configuration of network ports to appear as Linux network

+     interfaces (e.g. eth0, eth1) or to be "disconnected" from Linux (See LSP Readme for further details).

+   + Support init-time configuration of working with the Switch in Gateway mode / External Switch mode (non-Gateway): 

+     - Separate Switch driver (QD HAL) load from Switch init function

+     - Select Gateway mode / External Switch mode according to the mvNetConfig

+       parameter in U-Boot. (See LSP Readme for further details).

+   + Added support for advanced Gateway driver features:

+     - Runtime VLAN configuration

+     - Promiscuous mode

+     - Adding / deleting specific multicast addresses

+     - NFP between two Gateway interfaces / between Gateway interface and

+       non-Gateway interface

+     - 802.1Q VLAN-tagged traffic

+     - Support QSGMII module

+   + Added Switch ports link change prints even when working in External Switch mode

+   + Added TX no queue feature (tx_noq command in mv_neta_tool).

+

+ o Configure UART driver to work in Polling mode. This might cause the

+   UART to work a little slower for applications with large amount of

+   printouts.

+ o Add support for SGMII output configuration.

+ o Minor data-type fixes in mvBoardTdmSpiCsGet() &

+   mvBoardTdmDevicesCountGet().

+ o Added the ability to connect switch port 5 to KW2 MAC 1 port.

+ o Changed RD-SFU board ethernet complex configuration as follows:

+   - MAC port 0 is connected to switch port 6.

+   - MAC port 1 is connected to switch port 5.

+   - Internal PHY is connected to switch port 4.

+ o Add support for RD-88F6536-MDU board.

+ o Updated Ethernet Complex initialization code to support SGMII,

+   QSGMII, Internal PHYs and switch.

+ o Cesa HAL code cleanup.

+ o TDM:

+   - Added support for CommUnit (Up to 4 channels are currently

+     supported).

+   - Only Zarlink-VE880 SLICs are currently supported.

+   - Added an option to compile the mv_phone.ko driver using a pre-built

+     SLIC drivers library (This is the default kernel setting).

+   - Updated SLIC electrical initialization parameters table (For

+     Zarlink-VE880).

+   - Fix SLIC initialization process.

+   - Enhanced phone_test utilitiy with capability to read SLIC

+     registers.

+

+

+- Changes from version 0.1.0-NQ

+-------------------------------

+ o Initial support for TDM-32 Channels unit.

+

+- Changes from version 0.0.5-NQ

+-------------------------------

+ o Updated LSP kernel version from 2.6.31.8 to 2.6.32.11.

+ o Minor syntax fixes for tools/Makefile file.

+ o Skip ethernet complex registers initialization in Linux, and rely on

+   Uboot's initialization.

+ o Integration of Cesa unit on KW2 Silicon.

+ o Fixed bug in spi HAL in baud-rate calculation function

+   (mvSpiBaudRateSet()).

+ o Updated PON drivers and HALs after KW2 Silicon bringup.

+ o Enable auto-detection of TDM modules.

+ o Provide PON mode according to Sample-At-Reset value.

+ o Enable CPU-Idle support.

+ o Change default NAND device partitioning.

+ o Fix Zarlink-VE880 SLIC timing configuration.

+ o Neta:

+ 	- Configure the number of TCONTS at boot time according to PON

+	  configuration in Sample-At-Reset register.

+	- Added GRO support.

+ o Added gateway support:

+	- Adaptation of switch drivers to support KW2 internal switch.

+ 	- Link detection.

+	- Interface configuration via mvNetConfig parameter in U-Boot:

+	  + setting MAC address and port(s) per interface.

+	  + setting interface MTU.

+	- Runtime configuration of interface's Unicast MAC address.

+	- HW L2 switching according to interface (VLAN) configuration.

+	- Routing between Switch and non-Switch interface.

+	- Change MTU at runtime.

+

+- Changes from version 0.0.4-NQ

+-------------------------------

+ o Add initial support for RD-88F6510-SFU board. Support for this board

+ is minimal and still not stable.

+ o TDM:

+ 	- Update support for Zarlink-VE880 SLIC.

+	- Fix new PLL(x58) support for legacy TDM unit.

+	- Update SPI baud rate for SLIC devices to 2M.

+ o Neta:

+ 	- Partial IGMP support.

+	- Fix scatter-gather bug in Tx path.

+	- Fixed bug in NFP NAT mode.

+	- Fixed Neta register defaults.

+ o Fixed phy register access from Linux.

+ o Add initial support for USB host in DB board.

+

+

+- Version 0.0.4-NQ

+------------------

+ o First LSP to support KW2 SoC.

+   This is a preliminary version intended for integration purposes.

+

+4. Known Issues

+===============

+Networking:

+- For getting GRO offload paramaters , you must have version

+  ethtool-2.6.33-pre1 or higher.

+- MTU change is not supported.

+- When working with QSGMII module connected to the Switch, flow control is not enabled on the Switch external ports.

+- Connecting Switch port 5 to RGMII or internal PHY is currently not supported.

+- Allmulticast mode is not supported for Gateway interfaces.

+- Cannot use Gateway mode for RD-SFU board, must select External Switch mode.

+

+Telephony/CommUnit:

+- No support for Linear mode(A-law/U-law only).

+- False MCSC/MCDMA parity error generation.

+- Zarlink SLIC/s initialization process may end up with false off-hook detection for part/all lines.

+- FSync signal is tied to the TDM enable - therefore all CommUnit blocks are functional prior to SLIC/s

+  initialization process.

+- Periodic interrupt counter drifts by one frame(125usec).

+- Re-enabling the CommUnit may end up with small sampling offset(1 or 2 samples) between voice channels.

+

+USB:

+- Linux doesn't handle well a case of 2 ISO devices(full speed) working

+  simultaneously through the high speed hub.

+

+NAND:

+- When working with 4bit ECC configuration, it is not recommended to perform

+  read from an erased page, since no ECC was calculated for this page.

+  In this case we compared the page data against 512 bytes of 0xFF and if we

+  get a match, then return gracefully, otherwise, there is an uncorrectable

+  error.

+

+CESA:

+- OpenSSL speed test multiple sessions cause to board terminal ,telnet and ssh

+  sessions to stop working.

+

+5. Notes

+========

+

+- This release support up to 512MB of DRAM with current memory layout definition.

+

+5. Disclaimer

+=============

+This document provides preliminary information about the products described, and such 

+information should not be used for purpose of final design. Visit the Marvell(r) web 

+site at www.marvell.com for the latest information on Marvell products.

+

+No part of this document may be reproduced or transmitted in any form or by any means, 

+electronic or mechanical, including photocopying and recording, for any purpose, 

+without the express written permission of Marvell. Marvell retains the right to make 

+changes to this document at any time, without notice. Marvell makes no warranty of 

+any kind, expressed or implied, with regard to any information contained in this 

+document, including, but not limited to, the implied warranties of merchantability 

+or fitness for any particular purpose. Further, Marvell does not warrant the accuracy 

+or completeness of the information, text, graphics, or other items contained within 

+this document. Marvell makes no commitment either to update or to keep current the 

+information contained in this document. Marvell products are not designed for use in 

+life-support equipment or applications that would cause a life-threatening situation 

+if any such products failed. Do not use Marvell products in these types of equipment 

+or applications. The user should contact Marvell to obtain the latest specifications 

+before finalizing a product design. Marvell assumes no responsibility, either for use 

+of these products or for any infringements of patents and trademarks, or other rights 

+of third parties resulting from its use. No license is granted under any patents, 

+patent rights, or trademarks of Marvell.These products may include one or more 

+optional functions. The user has the choice of implementing any particular optional 

+function. Should the user choose to implement any of these optional functions, it is 

+possible that the use could be subject to third party intellectual property rights. 

+Marvell recommends that the user investigate whether third party intellectual property 

+rights are relevant to the intended use of these products and obtain licenses as 

+appropriate under relevant intellectual property rights. 

+Marvell comprises Marvell Technology Group Ltd. (MTGL) and its subsidiaries, Marvell 

+International Ltd. (MIL), Marvell Semiconductor, Inc. (MSI), Marvell Asia Pte Ltd. (MAPL), 

+Marvell Japan K.K. (MJKK), Marvell Semiconductor Israel Ltd. (MSIL), SysKonnect GmbH, 

+and Radlan Computer Communications, Ltd.

+Export Controls.  With respect to any of Marvell's Information, the user or recipient, 

+in the absence of appropriate U.S. government authorization, agrees: 1) not to re-export 

+or release any such information consisting of technology, software or source code 

+controlled for national security reasons by the U.S. Export Control Regulations ("EAR"), 

+to a national of EAR Country Groups D:1 or E:2; 2) not to export the direct product of 

+such technology or such software, to EAR Country Groups D:1 or E:2, if such technology or 

+software and direct products thereof are controlled for national security reasons by the 

+EAR; and, 3) in the case of technology controlled for national security reasons under the 

+EAR where the direct product of the technology is a complete plant or component of a plant, 

+not to export to EAR Country Groups D:1 or E:2 the direct product of the plant or major 

+component thereof, if such direct product is controlled for national security reasons by 

+the EAR, or is subject to controls under the U.S. Munitions List  ("USML").  At all times 

+hereunder, the recipient of any such information agrees that they shall be deemed to have 

+manually signed this document in connection with their receipt of any such information. 

+Copyright (c) 2004.  Marvell.  All rights reserved.  Marvell, the Marvell logo, Moving 

+Forward Faster, Alaska, and GalNet are registered trademarks of Marvell.  Discovery, 

+Fastwriter, GalTis, Horizon, Libertas, Link Street, NetGX, PHY Advantage, Prestera, 

+Raising The Technology Bar, UniMAC, Virtual Cable Tester, and Yukon are trademarks of 

+Marvell.  All other trademarks are the property of their respective owners.

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
old mode 100644
new mode 100755
index 1c4119c..2fe864e
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -224,6 +224,44 @@
 	help
 	  Support for ARM's Integrator platform.
 
+config ARCH_FEROCEON_ORION
+        bool "Feroceon-Orion based"
+	select ARCH_FEROCEON
+        select PCI
+	select GENERIC_TIME
+        select GENERIC_CLOCKEVENTS
+
+config ARCH_FEROCEON_KW
+        bool "Feroceon-KW based"
+	select CPU_FEROCEON
+	select ARCH_FEROCEON
+	select ARCH_HAS_CPUFREQ
+	select PCI
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GENERIC_TIME
+        select GENERIC_CLOCKEVENTS
+
+config ARCH_FEROCEON_KW2
+        bool "Feroceon-KW2 based"
+	select CPU_FEROCEON
+	select ARCH_FEROCEON
+	select ARCH_HAS_CPUFREQ
+	select PCI
+	select ARCH_SUPPORTS_MSI
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GENERIC_TIME
+        select GENERIC_CLOCKEVENTS
+
+config ARCH_FEROCEON_MV78XX0
+        bool "Feroceon-MV78XX0 based"
+	select ARCH_FEROCEON
+	select PCI
+	select GENERIC_TIME
+        select GENERIC_CLOCKEVENTS
+
+	
 config ARCH_REALVIEW
 	bool "ARM Ltd. RealView family"
 	select ARM_AMBA
@@ -704,6 +742,10 @@
 
 endchoice
 
+if ARCH_FEROCEON
+source "arch/arm/plat-feroceon/Kconfig"
+endif
+
 source "arch/arm/mach-clps711x/Kconfig"
 
 source "arch/arm/mach-ep93xx/Kconfig"
@@ -814,6 +856,9 @@
 config PLAT_ORION
 	bool
 
+config ARCH_FEROCEON
+	bool
+
 config PLAT_PXA
 	bool
 
@@ -920,7 +965,7 @@
 	bool
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE
+	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_FEROCEON
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1095,6 +1140,14 @@
 
 config ARCH_HAS_HOLES_MEMORYMODEL
 	bool
+	default n
+config REORDER
+        bool "Function reordering"
+        default n
+        help
+          This option enables the toolchain to reorder functions for a more
+          optimal TLB/Icache usage. If you have pretty much any version of binutils,
+          this can increase your kernel build time by roughly one minute.
 
 # Discontigmem is deprecated
 config ARCH_DISCONTIGMEM_ENABLE
@@ -1147,7 +1200,8 @@
 		   ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
 		   ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
 		   ARCH_AT91 || ARCH_DAVINCI || \
-		   ARCH_KS8695 || MACH_RD88F5182 || ARCH_REALVIEW
+		   ARCH_KS8695 || MACH_RD88F5182 || ARCH_FEROCEON || \
+		   ARCH_REALVIEW
 	help
 	  If you say Y here, the LEDs on your machine will be used
 	  to provide useful information about your current system status.
@@ -1359,6 +1413,22 @@
 	bool "CPUfreq support for Samsung S3C64XX CPUs"
 	depends on CPU_FREQ && CPU_S3C6410
 
+config CPU_FREQ_FEROCEON_KW
+	tristate "CPUfreq driver for Kirkwood SoC"
+	depends on CPU_FREQ && ARCH_FEROCEON_KW
+	default n
+	help
+	  This enables the CPUfreq driver for Kirkwood SoC.
+	  If in doubt, say N.
+
+config CPU_FREQ_FEROCEON_KW2
+	tristate "CPUfreq driver for Kirkwood2 SoC"
+	depends on CPU_FREQ && ARCH_FEROCEON_KW2
+	default n
+	help
+	  This enables the CPUfreq driver for Kirkwood SoC.
+	  If in doubt, say N.
+
 config CPU_FREQ_S3C
 	bool
 	help
@@ -1465,6 +1535,18 @@
 
 	  Say N if your target does not have VFP hardware.
 
+config VFP_FASTVFP
+        bool "FastVFP"
+	depends on VFP
+        help
+          Say Y here to include the FAST Vector Floating Point in the kernel.
+	  This means the VFP co-processor runs in a determinable time without 
+	  support code assistance, regardless of the characteristics of the input data. 
+	  In RunFast mode, no user exception traps are available.
+
+	  It should be sufficient for most programs. It may be not suitable
+	  for scientific calculations, but you have to check this for yourself.
+
 config VFPv3
 	bool
 	depends on VFP
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
old mode 100644
new mode 100755
index a73caaf..9c6a0e2
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -15,11 +15,16 @@
 LDFLAGS_vmlinux	+= --be8
 endif
 
+NFPLIBCMD=$(AR) rcs arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/nfplib.a arch/arm/plat-feroceon/mv_hal/neta/nfp/*.o arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/nfp_mgr/*.o
+
 OBJCOPYFLAGS	:=-O binary -R .note -R .note.gnu.build-id -R .comment -S
 GZFLAGS		:=-9
 #KBUILD_CFLAGS	+=-pipe
 # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
 KBUILD_CFLAGS	+=$(call cc-option,-marm,)
+ifeq ($(CONFIG_REORDER),y)
+KBUILD_CFLAGS          += -ffunction-sections
+endif
 
 # Do not use arch/arm/defconfig - it's always outdated.
 # Select a platform tht is kept up-to-date
@@ -57,7 +62,11 @@
 ifeq ($(CONFIG_CPU_32v6),y)
 arch-$(CONFIG_CPU_32v6K)	:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
 endif
-arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
+ifneq ($(CONFIG_USE_DSP),y)
+arch-$(CONFIG_CPU_32v5)         :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5t)
+else
+arch-$(CONFIG_CPU_32v5)		    :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
+endif
 arch-$(CONFIG_CPU_32v4T)	:=-D__LINUX_ARM_ARCH__=4 -march=armv4t
 arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
 arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
@@ -76,11 +85,32 @@
 tune-$(CONFIG_CPU_ARM925T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_FA526)	:=-mtune=arm9tdmi
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+  #-KW
+  ifeq ($(CONFIG_ARCH_FEROCEON_KW),y)
+    tune-$(CONFIG_CPU_FEROCEON)	:=$(call cc-option,-mtune=arm9e,-mtune=xscale)
+  endif
+  #-KW2
+  ifeq ($(CONFIG_ARCH_FEROCEON_KW2),y)
+    tune-$(CONFIG_CPU_FEROCEON)	:=$(call cc-option,-mtune=marvell-f)
+  endif
+
+  #-6183
+  ifeq ($(CONFIG_ARCH_FEROCEON_ORION),y)
+    tune-$(CONFIG_CPU_FEROCEON)	:=$(call cc-option,-mtune=arm9e,-mtune=xscale)
+  endif
+  #-DD
+  ifeq ($(CONFIG_ARCH_FEROCEON_MV78XX0),y)
+    tune-$(CONFIG_CPU_FEROCEON)	:=$(call cc-option,-mtune=marvell-f,-mtune=xscale)
+  endif
+else
+  tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
+endif
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
 tune-$(CONFIG_CPU_XSCALE)	:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
 tune-$(CONFIG_CPU_XSC3)		:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
-tune-$(CONFIG_CPU_FEROCEON)	:=$(call cc-option,-mtune=marvell-f,-mtune=xscale)
+#tune-$(CONFIG_CPU_FEROCEON)	:=$(call cc-option,-mtune=marvell-f,-mtune=xscale)
 tune-$(CONFIG_CPU_V6)		:=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
 
 ifeq ($(CONFIG_AEABI),y)
@@ -134,6 +164,15 @@
 machine-$(CONFIG_ARCH_IXP23XX)		:= ixp23xx
 machine-$(CONFIG_ARCH_IXP4XX)		:= ixp4xx
 machine-$(CONFIG_ARCH_KIRKWOOD)		:= kirkwood
+machine-$(CONFIG_ARCH_FEROCEON_ORION)	:= feroceon-orion
+machine-$(CONFIG_ARCH_FEROCEON_KW)	:= feroceon-kw
+machine-$(CONFIG_ARCH_FEROCEON_KW2)	:= feroceon-kw2
+machine-$(CONFIG_ARCH_FEROCEON_MV78XX0)	:= feroceon-mv78xx0
+plat-$(CONFIG_ARCH_FEROCEON_KW)		:= feroceon
+plat-$(CONFIG_ARCH_FEROCEON_KW2)	:= feroceon
+
+
+
 machine-$(CONFIG_ARCH_KS8695)		:= ks8695
 machine-$(CONFIG_ARCH_L7200)		:= l7200
 machine-$(CONFIG_ARCH_LH7A40X)		:= lh7a40x
@@ -209,7 +248,7 @@
 KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs) $(platdirs))
 endif
 
-export	TEXT_OFFSET GZFLAGS MMUEXT
+export	TEXT_OFFSET GZFLAGS MMUEXT MACHINE
 
 # Do we have FASTFPE?
 FASTFPE		:=arch/arm/fastfpe
@@ -269,13 +308,20 @@
 bp:;	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/bootpImage
 i zi:;	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
+nfplib:
+ifeq ($(CONFIG_MV_ETH_NFP_LIB),y)
+	make -f scripts/Makefile.build NFPLIB=y obj=$(PWD)/arch/arm/mach-feroceon-kw2/
+	$(NFPLIBCMD)
+else
+	@echo "CONFIG_MV_ETH_NFP_LIB must be set for creating nfplib.a; exiting"
+endif
 
 define archhelp
   echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
   echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
   echo  '* xipImage      - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)'
   echo  '  uImage        - U-Boot wrapped zImage'
-  echo  '  bootpImage    - Combined zImage and initial RAM disk' 
+  echo  '  bootpImage    - Combined zImage and initial RAM disk'
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
index ce1c5ff..275c8ce 100644
--- a/arch/arm/boot/.gitignore
+++ b/arch/arm/boot/.gitignore
@@ -1,5 +1,4 @@
 Image
 zImage
-xipImage
-bootpImage
 uImage
+compressed/vmlinux.lds
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
old mode 100644
new mode 100755
index ab204db..aefee20
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -1,3 +1 @@
-font.c
 piggy.gz
-vmlinux.lds
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
old mode 100644
new mode 100755
index 3cb8fa3..30ae0ba
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -440,6 +440,18 @@
 		mov	r12, lr
 #ifdef CONFIG_MMU
 		bl	__setup_mmu
+#ifdef CONFIG_CACHE_FEROCEON_L2
+		/* Cancel L2 prefetch */
+		mrc	p15, 1, r0, c15, c1, 0	@ Read r15 register
+		orr	r0, #0x01000000		@ No prefetching
+		mcr	p15, 1, r0, c15, c1, 0	@ Write r15 register
+/*
+ * In this step, the I/DCaches are closed, but L2 cache might be present 
+ * containing valid data (from u-boot). We do not assume u-boot invalidates L2, 
+ * so we do it ourselves
+ */
+		mcr	p15, 1, r0, c15, c11, 0	@ Invalidate whole L2 
+#endif
 		mov	r0, #0
 		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
 		mcr	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
@@ -971,10 +983,20 @@
  THUMB(		add     r1, r1, r11		)
 		teq	r1, r2
 		bne	1b
+#ifdef CONFIG_ARCH_FEROCEON
+                /* 4 way cache, load of new cache lines won't be enough. */
+2:              mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
+                bne     2b
+#endif
 
 		mcr	p15, 0, r1, c7, c5, 0	@ flush I cache
 		mcr	p15, 0, r1, c7, c6, 0	@ flush D cache
 		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
+#ifdef CONFIG_CACHE_FEROCEON_L2
+		mcr	p15, 1, r1, c15, c9, 0	@ clean entire L2 cache
+		mcr	p15, 1, r1, c15, c11, 0	@ Invalidate entire L2 cache
+		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
+#endif
 		mov	pc, lr
 
 __armv3_mmu_cache_flush:
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
old mode 100644
new mode 100755
index 17153b5..7defd72
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -86,6 +86,7 @@
 #define flush()	do { } while (0)
 #endif
 
+#ifndef CONFIG_ARCH_FEROCEON
 static void putstr(const char *ptr)
 {
 	char c;
@@ -98,6 +99,7 @@
 
 	flush();
 }
+#endif
 
 #endif
 
diff --git a/arch/arm/configs/mv88f6500_be_defconfig b/arch/arm/configs/mv88f6500_be_defconfig
new file mode 100755
index 0000000..2e5b406
--- /dev/null
+++ b/arch/arm/configs/mv88f6500_be_defconfig
@@ -0,0 +1,2103 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32.11
+# Thu Jul 12 10:31:03 2012
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_FEROCEON_ORION is not set
+# CONFIG_ARCH_FEROCEON_KW is not set
+CONFIG_ARCH_FEROCEON_KW2=y
+# CONFIG_ARCH_FEROCEON_MV78XX0 is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+
+#
+# Feroceon SoC options
+#
+CONFIG_MV88F6500=y
+# CONFIG_JTAG_DEBUG is not set
+
+#
+# Feroceon SoC Included Features
+#
+CONFIG_MV_NAND_SUPPORT=y
+CONFIG_MV_INCLUDE_PEX=y
+CONFIG_MV_INCLUDE_USB=y
+CONFIG_MV_INCLUDE_XOR=y
+CONFIG_MV_INCLUDE_CESA=y
+# CONFIG_MV_INCLUDE_NFC is not set
+CONFIG_MV_INCLUDE_LEGACY_NAND=y
+CONFIG_MV_INCLUDE_INTEG_SATA=y
+CONFIG_MV_INCLUDE_TDM=y
+CONFIG_MV_INCLUDE_GIG_ETH=y
+CONFIG_MV_INCLUDE_SPI=y
+CONFIG_MV_INCLUDE_SDIO=y
+# CONFIG_MV_INCLUDE_TS is not set
+CONFIG_MV_INCLUDE_PON=y
+CONFIG_MV_INCLUDE_SWITCH=y
+CONFIG_MV_GPP_MAX_PINS=70
+CONFIG_MV_DCACHE_SIZE=0x4000
+CONFIG_MV_ICACHE_SIZE=0x4000
+
+#
+# Feroceon SoC MTD support
+#
+CONFIG_MV_FLASH_CTRL=y
+# CONFIG_MV_INCLUDE_NORFLASH_MTD is not set
+CONFIG_MV_INCLUDE_SFLASH_MTD=y
+CONFIG_MTD_NAND_LNC=y
+CONFIG_MTD_NAND_LNC_RS_ECC=y
+# CONFIG_MTD_NAND_LNC_8BYTE_READ is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+CONFIG_USE_DSP=y
+CONFIG_MV_SP_I_FTCH_DB_INV=y
+# CONFIG_MV_SP_I_FTCH_LCK_L2_ICACHE is not set
+# CONFIG_MV_SP_I_FTCH_NONE is not set
+# CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING is not set
+CONFIG_FEROCEON_PROC=y
+CONFIG_UBOOT_STRUCT=y
+# CONFIG_MV_DBG_TRACE is not set
+CONFIG_MV_REAL_TIME=y
+# CONFIG_MV_CPU_PERF_CNTRS is not set
+# CONFIG_MV_CPU_L2_PERF_CNTRS is not set
+
+#
+# Power-Management options
+#
+CONFIG_MV_PMU_PROC=y
+CONFIG_MV_PM_IDLE_WFI_SR=y
+# CONFIG_MV_PM_IDLE_DEEPIDLE_SR is not set
+
+#
+# Soc DMA accelerations
+#
+# CONFIG_MV_USE_XOR_ENGINE is not set
+
+#
+# SoC Networking support
+#
+CONFIG_MV_ETHERNET=y
+# CONFIG_MV_ETH_LEGACY is not set
+CONFIG_MV_ETH_NETA=y
+CONFIG_MV_ETH_PORTS_NUM=3
+CONFIG_MV_ETH_0_MTU=1500
+CONFIG_MV_ETH_0_MACADDR="00:00:00:00:00:80"
+CONFIG_MV_ETH_1_MTU=1500
+CONFIG_MV_ETH_1_MACADDR="00:00:00:00:00:81"
+CONFIG_MV_ETH_2_MTU=1500
+CONFIG_MV_ETH_2_MACADDR="00:00:00:00:00:82"
+CONFIG_MV_ETH_RXQ=8
+CONFIG_MV_ETH_TXQ=8
+CONFIG_MV_ETH_TSO=y
+CONFIG_MV_ETH_TOOL=y
+# CONFIG_MV_LINUX_COUNTERS_DISABLE is not set
+CONFIG_NET_SKB_HEADROOM=96
+CONFIG_NET_SKB_RECYCLE=y
+CONFIG_NET_SKB_RECYCLE_DEF=1
+# CONFIG_MV_ETH_NFP is not set
+
+#
+# BM configuration
+#
+CONFIG_MV_ETH_BM=y
+CONFIG_MV_ETH_BM_CPU=y
+CONFIG_MV_ETH_BM_0_PKT_SIZE=0
+CONFIG_MV_ETH_BM_1_PKT_SIZE=0
+CONFIG_MV_ETH_BM_2_PKT_SIZE=0
+CONFIG_MV_ETH_BM_3_PKT_SIZE=256
+CONFIG_MV_ETH_BM_PORT_0=y
+CONFIG_MV_ETH_BM_PORT_0_LONG_POOL=0
+CONFIG_MV_ETH_BM_PORT_0_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_0_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_0_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_BM_PORT_1=y
+CONFIG_MV_ETH_BM_PORT_1_LONG_POOL=1
+CONFIG_MV_ETH_BM_PORT_1_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_1_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_1_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_BM_PORT_2=y
+CONFIG_MV_ETH_BM_PORT_2_LONG_POOL=2
+CONFIG_MV_ETH_BM_PORT_2_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_2_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_2_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_PNC=y
+CONFIG_MV_PNC_TCAM_LINES=512
+CONFIG_MV_ETH_PNC_MCAST_NUM=8
+CONFIG_MV_ETH_PNC_VLAN_PRIO=7
+CONFIG_MV_ETH_PNC_ETYPE=0
+CONFIG_MV_ETH_PNC_DSCP_PRIO=16
+# CONFIG_MV_ETH_PNC_L3_FLOW is not set
+# CONFIG_MV_ETH_PNC_WOL is not set
+CONFIG_MV_ETH_HWF=y
+CONFIG_MV_ETH_HWF_TXQ_DROP=60
+CONFIG_MV_ETH_HWF_TXQ_DROP_RND=0
+CONFIG_MV_ETH_PMT=y
+CONFIG_MV_ETH_PMT_FLOWS=256
+CONFIG_MV_ETH_PMT_CMD_PER_FLOW=12
+
+#
+# Network Interface configuration
+#
+
+#
+# Rx/Tx Queue configuration
+#
+CONFIG_MV_ETH_RXQ_DESC=128
+CONFIG_MV_ETH_RXQ_DEF=0
+CONFIG_MV_ETH_TXQ_DESC=512
+CONFIG_MV_ETH_TXQ_DEF=0
+
+#
+# IP/TCP/UDP Offloading
+#
+CONFIG_MV_ETH_TX_CSUM_OFFLOAD=y
+CONFIG_MV_ETH_TX_CSUM_OFFLOAD_DEF=y
+CONFIG_MV_ETH_RX_CSUM_OFFLOAD=y
+CONFIG_MV_ETH_RX_CSUM_OFFLOAD_DEF=y
+CONFIG_MV_ETH_GRO=y
+# CONFIG_MV_ETH_GRO_DEF is not set
+# CONFIG_MV_ETH_TSO_DEF is not set
+
+#
+# Control and Statistics
+#
+CONFIG_MV_ETH_DEBUG_CODE=y
+CONFIG_MV_ETH_STAT_ERR=y
+CONFIG_MV_ETH_STAT_INF=y
+CONFIG_MV_ETH_STAT_DBG=y
+# CONFIG_MV_ETH_STAT_DIST is not set
+
+#
+# Advanced Features
+#
+CONFIG_MV_ETH_TX_DONE_TIMER_PERIOD=10
+CONFIG_MV_ETH_CLEANUP_TIMER_PERIOD=10
+# CONFIG_MV_ETH_TXDONE_ISR is not set
+CONFIG_MV_ETH_TXDONE_COAL_PKTS=16
+CONFIG_MV_ETH_RX_COAL_PKTS=32
+CONFIG_MV_ETH_RX_COAL_USEC=100
+# CONFIG_MV_ETH_RX_DESC_PREFETCH is not set
+# CONFIG_MV_ETH_RX_PKT_PREFETCH is not set
+CONFIG_MV_ETH_RX_SPECIAL=y
+CONFIG_MV_ETH_TX_SPECIAL=y
+# CONFIG_MV_ETH_L2FW is not set
+CONFIG_MV_ETH_RX_POLL_WEIGHT=64
+CONFIG_MV_ETH_EXTRA_BUF_SIZE=120
+CONFIG_MV_ETH_EXTRA_BUF_NUM=512
+
+#
+# NFP support
+#
+
+#
+# NAPI GROUPS
+#
+CONFIG_MV_ETH_NAPI_GROUPS=1
+
+#
+# Group 0
+#
+CONFIG_MV_ETH_GROUP0_CPU=0x1
+CONFIG_MV_ETH_GROUP0_RXQ=0xff
+
+#
+# PON support for Network driver
+#
+CONFIG_MV_PON=y
+CONFIG_MV_PON_TXP_DEF=0
+CONFIG_MV_PON_TXQ_DEF=0
+
+#
+# Switch support
+#
+CONFIG_MV_ETH_SWITCH=y
+CONFIG_MV_ETH_SWITCH_NETDEV_NUM=6
+CONFIG_MV_ETH_SWITCH_NETCONFIG_0="3,(00:11:66:11:66:11,0)(00:22:77:22:77:22,1:2:3:4),mtu=1500"
+CONFIG_MV_ETH_SWITCH_NETCONFIG_1="0"
+CONFIG_MV_ETH_SWITCH_LINK=y
+
+#
+# ERRATA / WA
+#
+# CONFIG_MV_ETH_BE_WA is not set
+
+#
+# Cesa options
+#
+CONFIG_MV_CESA=y
+CONFIG_MV_CESA_TOOL=y
+CONFIG_MV_CESA_CHANNELS=1
+# CONFIG_MV_CESA_CHAIN_MODE is not set
+CONFIG_MV_CESA_OCF=y
+# CONFIG_MV_CESA_TEST is not set
+
+#
+# Telephony options
+#
+# CONFIG_MV_PHONE is not set
+
+#
+# SoC PON support
+#
+CONFIG_MV_PON_TCONTS=8
+# CONFIG_MV_GPON is not set
+# CONFIG_MV_EPON is not set
+CONFIG_SCSI_MVSATA=y
+
+#
+# Sata options
+#
+CONFIG_MV_SATA_SUPPORT_ATAPI=y
+CONFIG_MV_SATA_ENABLE_1MB_IOS=y
+# CONFIG_SATA_NO_DEBUG is not set
+CONFIG_SATA_DEBUG_ON_ERROR=y
+# CONFIG_SATA_FULL_DEBUG is not set
+# CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT is not set
+# CONFIG_MV_UART_POLLING_MODE is not set
+# CONFIG_MV_PRINTK_SLICE_SUPPORT is not set
+CONFIG_ARCH_FEROCEON=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_FEROCEON=y
+# CONFIG_CPU_FEROCEON_OLD_ID is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_FEROCEON=y
+CONFIG_CPU_TLB_FEROCEON=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_ENDIAN_BE8 is not set
+CONFIG_CPU_ENDIAN_BE32=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_CACHE_FEROCEON_L2=y
+# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_ARMV5_L2_CACHE_COHERENCY_FIX=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+CONFIG_REORDER=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_FEROCEON_KW2=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_ADVANCED is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_FTP=y
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CT_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_NF_NAT_FTP=y
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_IP_NF_MANGLE is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_NF_CONNTRACK_IPV6 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=1
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+# CONFIG_MV_SCATTERED_SPINUP is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_SCSI_MV_THOR=m
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID456=y
+CONFIG_MD_RAID6_PQ=y
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=y
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000E=y
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_SK98LIN=y
+# CONFIG_SK98LIN_NAPI is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=y
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+CONFIG_PHONE=y
+# CONFIG_PHONE_IXJ is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_LANGWELL is not set
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+CONFIG_THERMAL_SENSOR_KW2=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_MIXER_OSS is not set
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+CONFIG_SND_PCM_XRUN_DEBUG=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=y
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PCI is not set
+# CONFIG_MMC_SDHCI_PLTFM is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_MVSDIO=y
+# CONFIG_MMC_CB710 is not set
+# CONFIG_MMC_VIA_SDMMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+CONFIG_JBD2=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=y
+CONFIG_ASYNC_CORE=y
+CONFIG_ASYNC_MEMCPY=y
+CONFIG_ASYNC_XOR=y
+CONFIG_ASYNC_PQ=y
+CONFIG_ASYNC_RAID6_RECOV=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+
+#
+# OCF Configuration
+#
+CONFIG_OCF_OCF=y
+# CONFIG_OCF_RANDOMHARVEST is not set
+CONFIG_OCF_CRYPTODEV=y
+CONFIG_OCF_CRYPTOSOFT=y
+# CONFIG_OCF_SAFE is not set
+# CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_HIFN is not set
+# CONFIG_OCF_HIFNHIPP is not set
+# CONFIG_OCF_TALITOS is not set
+# CONFIG_OCF_EP80579 is not set
+# CONFIG_OCF_OCFNULL is not set
+# CONFIG_OCF_BENCH is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/mv88f6500_defconfig b/arch/arm/configs/mv88f6500_defconfig
new file mode 100755
index 0000000..11798a2
--- /dev/null
+++ b/arch/arm/configs/mv88f6500_defconfig
@@ -0,0 +1,2110 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32.11
+# Thu Jul 12 10:29:40 2012
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_FEROCEON_ORION is not set
+# CONFIG_ARCH_FEROCEON_KW is not set
+CONFIG_ARCH_FEROCEON_KW2=y
+# CONFIG_ARCH_FEROCEON_MV78XX0 is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+
+#
+# Feroceon SoC options
+#
+CONFIG_MV88F6500=y
+# CONFIG_JTAG_DEBUG is not set
+
+#
+# Feroceon SoC Included Features
+#
+CONFIG_MV_NAND_SUPPORT=y
+CONFIG_MV_INCLUDE_PEX=y
+CONFIG_MV_INCLUDE_USB=y
+CONFIG_MV_INCLUDE_XOR=y
+CONFIG_MV_INCLUDE_CESA=y
+# CONFIG_MV_INCLUDE_NFC is not set
+CONFIG_MV_INCLUDE_LEGACY_NAND=y
+CONFIG_MV_INCLUDE_INTEG_SATA=y
+CONFIG_MV_INCLUDE_TDM=y
+CONFIG_MV_INCLUDE_GIG_ETH=y
+CONFIG_MV_INCLUDE_SPI=y
+CONFIG_MV_INCLUDE_SDIO=y
+# CONFIG_MV_INCLUDE_TS is not set
+CONFIG_MV_INCLUDE_PON=y
+CONFIG_MV_INCLUDE_SWITCH=y
+CONFIG_MV_GPP_MAX_PINS=70
+CONFIG_MV_DCACHE_SIZE=0x4000
+CONFIG_MV_ICACHE_SIZE=0x4000
+
+#
+# Feroceon SoC MTD support
+#
+CONFIG_MV_FLASH_CTRL=y
+# CONFIG_MV_INCLUDE_NORFLASH_MTD is not set
+CONFIG_MV_INCLUDE_SFLASH_MTD=y
+CONFIG_MTD_NAND_LNC=y
+CONFIG_MTD_NAND_LNC_RS_ECC=y
+# CONFIG_MTD_NAND_LNC_8BYTE_READ is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+CONFIG_USE_DSP=y
+CONFIG_MV_SP_I_FTCH_DB_INV=y
+# CONFIG_MV_SP_I_FTCH_LCK_L2_ICACHE is not set
+# CONFIG_MV_SP_I_FTCH_NONE is not set
+# CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING is not set
+CONFIG_FEROCEON_PROC=y
+CONFIG_UBOOT_STRUCT=y
+# CONFIG_MV_DBG_TRACE is not set
+CONFIG_MV_REAL_TIME=y
+# CONFIG_MV_CPU_PERF_CNTRS is not set
+# CONFIG_MV_CPU_L2_PERF_CNTRS is not set
+
+#
+# Power-Management options
+#
+CONFIG_MV_PMU_PROC=y
+CONFIG_MV_PM_IDLE_WFI_SR=y
+# CONFIG_MV_PM_IDLE_DEEPIDLE_SR is not set
+
+#
+# Soc DMA accelerations
+#
+# CONFIG_MV_USE_XOR_ENGINE is not set
+
+#
+# SoC Networking support
+#
+CONFIG_MV_ETHERNET=y
+# CONFIG_MV_ETH_LEGACY is not set
+CONFIG_MV_ETH_NETA=y
+CONFIG_MV_ETH_PORTS_NUM=3
+CONFIG_MV_ETH_0_MTU=1500
+CONFIG_MV_ETH_0_MACADDR="00:00:00:00:00:80"
+CONFIG_MV_ETH_1_MTU=1500
+CONFIG_MV_ETH_1_MACADDR="00:00:00:00:00:81"
+CONFIG_MV_ETH_2_MTU=1500
+CONFIG_MV_ETH_2_MACADDR="00:00:00:00:00:82"
+CONFIG_MV_ETH_RXQ=8
+CONFIG_MV_ETH_TXQ=8
+CONFIG_MV_ETH_TSO=y
+CONFIG_MV_ETH_TOOL=y
+# CONFIG_MV_LINUX_COUNTERS_DISABLE is not set
+CONFIG_NET_SKB_HEADROOM=96
+CONFIG_NET_SKB_RECYCLE=y
+CONFIG_NET_SKB_RECYCLE_DEF=1
+# CONFIG_MV_ETH_NFP is not set
+
+#
+# BM configuration
+#
+CONFIG_MV_ETH_BM=y
+CONFIG_MV_ETH_BM_CPU=y
+CONFIG_MV_ETH_BM_0_PKT_SIZE=0
+CONFIG_MV_ETH_BM_1_PKT_SIZE=0
+CONFIG_MV_ETH_BM_2_PKT_SIZE=0
+CONFIG_MV_ETH_BM_3_PKT_SIZE=256
+CONFIG_MV_ETH_BM_PORT_0=y
+CONFIG_MV_ETH_BM_PORT_0_LONG_POOL=0
+CONFIG_MV_ETH_BM_PORT_0_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_0_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_0_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_BM_PORT_1=y
+CONFIG_MV_ETH_BM_PORT_1_LONG_POOL=1
+CONFIG_MV_ETH_BM_PORT_1_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_1_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_1_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_BM_PORT_2=y
+CONFIG_MV_ETH_BM_PORT_2_LONG_POOL=2
+CONFIG_MV_ETH_BM_PORT_2_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_2_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_2_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_PNC=y
+CONFIG_MV_PNC_TCAM_LINES=512
+CONFIG_MV_ETH_PNC_MCAST_NUM=8
+CONFIG_MV_ETH_PNC_VLAN_PRIO=7
+CONFIG_MV_ETH_PNC_ETYPE=0
+CONFIG_MV_ETH_PNC_DSCP_PRIO=16
+# CONFIG_MV_ETH_PNC_L3_FLOW is not set
+# CONFIG_MV_ETH_PNC_WOL is not set
+CONFIG_MV_ETH_HWF=y
+CONFIG_MV_ETH_HWF_TXQ_DROP=60
+CONFIG_MV_ETH_HWF_TXQ_DROP_RND=0
+CONFIG_MV_ETH_PMT=y
+CONFIG_MV_ETH_PMT_FLOWS=256
+CONFIG_MV_ETH_PMT_CMD_PER_FLOW=12
+
+#
+# Network Interface configuration
+#
+
+#
+# Rx/Tx Queue configuration
+#
+CONFIG_MV_ETH_RXQ_DESC=128
+CONFIG_MV_ETH_RXQ_DEF=0
+CONFIG_MV_ETH_TXQ_DESC=512
+CONFIG_MV_ETH_TXQ_DEF=0
+
+#
+# IP/TCP/UDP Offloading
+#
+CONFIG_MV_ETH_TX_CSUM_OFFLOAD=y
+CONFIG_MV_ETH_TX_CSUM_OFFLOAD_DEF=y
+CONFIG_MV_ETH_RX_CSUM_OFFLOAD=y
+CONFIG_MV_ETH_RX_CSUM_OFFLOAD_DEF=y
+CONFIG_MV_ETH_GRO=y
+# CONFIG_MV_ETH_GRO_DEF is not set
+# CONFIG_MV_ETH_TSO_DEF is not set
+
+#
+# Control and Statistics
+#
+# CONFIG_MV_ETH_DEBUG_CODE is not set
+CONFIG_MV_ETH_STAT_ERR=y
+CONFIG_MV_ETH_STAT_INF=y
+# CONFIG_MV_ETH_STAT_DBG is not set
+# CONFIG_MV_ETH_STAT_DIST is not set
+
+#
+# Advanced Features
+#
+CONFIG_MV_ETH_TX_DONE_TIMER_PERIOD=10
+CONFIG_MV_ETH_CLEANUP_TIMER_PERIOD=10
+# CONFIG_MV_ETH_TXDONE_ISR is not set
+CONFIG_MV_ETH_TXDONE_COAL_PKTS=16
+CONFIG_MV_ETH_RX_COAL_PKTS=32
+CONFIG_MV_ETH_RX_COAL_USEC=100
+# CONFIG_MV_ETH_RX_DESC_PREFETCH is not set
+# CONFIG_MV_ETH_RX_PKT_PREFETCH is not set
+# CONFIG_MV_ETH_RX_SPECIAL is not set
+# CONFIG_MV_ETH_TX_SPECIAL is not set
+# CONFIG_MV_ETH_L2FW is not set
+CONFIG_MV_ETH_RX_POLL_WEIGHT=64
+CONFIG_MV_ETH_EXTRA_BUF_SIZE=120
+CONFIG_MV_ETH_EXTRA_BUF_NUM=512
+
+#
+# NFP support
+#
+
+#
+# NAPI GROUPS
+#
+CONFIG_MV_ETH_NAPI_GROUPS=1
+
+#
+# Group 0
+#
+CONFIG_MV_ETH_GROUP0_CPU=0x1
+CONFIG_MV_ETH_GROUP0_RXQ=0xff
+
+#
+# PON support for Network driver
+#
+CONFIG_MV_PON=y
+CONFIG_MV_PON_TXP_DEF=0
+CONFIG_MV_PON_TXQ_DEF=0
+
+#
+# Switch support
+#
+CONFIG_MV_ETH_SWITCH=y
+CONFIG_MV_ETH_SWITCH_NETDEV_NUM=6
+CONFIG_MV_ETH_SWITCH_NETCONFIG_0="3,(00:11:66:11:66:11,0)(00:22:77:22:77:22,1:2:3:4),mtu=1500"
+CONFIG_MV_ETH_SWITCH_NETCONFIG_1="0"
+CONFIG_MV_ETH_SWITCH_LINK=y
+
+#
+# ERRATA / WA
+#
+
+#
+# Cesa options
+#
+CONFIG_MV_CESA=y
+CONFIG_MV_CESA_TOOL=y
+CONFIG_MV_CESA_CHANNELS=1
+CONFIG_MV_CESA_CHAIN_MODE=y
+CONFIG_MV_CESA_OCF=y
+# CONFIG_MV_CESA_TEST is not set
+
+#
+# Telephony options
+#
+CONFIG_MV_PHONE=y
+CONFIG_MV_TDM_SUPPORT=y
+# CONFIG_MV_COMM_UNIT_SUPPORT is not set
+# CONFIG_SILABS_SLIC_SUPPORT is not set
+CONFIG_ZARLINK_SLIC_SUPPORT=y
+CONFIG_ZARLINK_SLIC_VE880=y
+# CONFIG_ZARLINK_SLIC_VE890 is not set
+# CONFIG_ZARLINK_SLIC_VE792 is not set
+CONFIG_MV_TDM_PCM_CLK_8MHZ=y
+# CONFIG_MV_TDM_PCM_CLK_4MHZ is not set
+# CONFIG_MV_TDM_PCM_CLK_2MHZ is not set
+CONFIG_MV_TDM_USE_INTERNAL_PCLK_SOURCE=y
+# CONFIG_MV_TDM_USE_EXTERNAL_PCLK_SOURCE is not set
+# CONFIG_MV_TDM_USE_DCO is not set
+CONFIG_MV_TDM_DUMMY=y
+# CONFIG_MV_PHONE_USE_IRQ_PROCESSING is not set
+# CONFIG_MV_PHONE_USE_FIQ_PROCESSING is not set
+CONFIG_MV_PHONE_USE_SLIC_LIBS=y
+
+#
+# SoC PON support
+#
+CONFIG_MV_PON_TCONTS=8
+# CONFIG_MV_GPON is not set
+# CONFIG_MV_EPON is not set
+CONFIG_SCSI_MVSATA=y
+
+#
+# Sata options
+#
+CONFIG_MV_SATA_SUPPORT_ATAPI=y
+CONFIG_MV_SATA_ENABLE_1MB_IOS=y
+# CONFIG_SATA_NO_DEBUG is not set
+CONFIG_SATA_DEBUG_ON_ERROR=y
+# CONFIG_SATA_FULL_DEBUG is not set
+# CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT is not set
+# CONFIG_MV_UART_POLLING_MODE is not set
+# CONFIG_MV_PRINTK_SLICE_SUPPORT is not set
+CONFIG_ARCH_FEROCEON=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_FEROCEON=y
+# CONFIG_CPU_FEROCEON_OLD_ID is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_FEROCEON=y
+CONFIG_CPU_TLB_FEROCEON=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_CACHE_FEROCEON_L2=y
+# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_ARMV5_L2_CACHE_COHERENCY_FIX=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+CONFIG_REORDER=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_FEROCEON_KW2=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_APM_EMULATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=1
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+# CONFIG_MV_SCATTERED_SPINUP is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_SCSI_MV_THOR=m
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID456=y
+CONFIG_MD_RAID6_PQ=y
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=y
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000E=y
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_SK98LIN=y
+# CONFIG_SK98LIN_NAPI is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=y
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+CONFIG_PHONE=y
+# CONFIG_PHONE_IXJ is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_LANGWELL is not set
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+CONFIG_THERMAL_SENSOR_KW2=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_MIXER_OSS is not set
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+CONFIG_SND_PCM_XRUN_DEBUG=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=y
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_AT91 is not set
+CONFIG_USB_GADGET_MRVL=y
+CONFIG_USB_MRVL=m
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PCI is not set
+# CONFIG_MMC_SDHCI_PLTFM is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_MVSDIO=y
+# CONFIG_MMC_CB710 is not set
+# CONFIG_MMC_VIA_SDMMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+CONFIG_JBD2=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=y
+CONFIG_ASYNC_CORE=y
+CONFIG_ASYNC_MEMCPY=y
+CONFIG_ASYNC_XOR=y
+CONFIG_ASYNC_PQ=y
+CONFIG_ASYNC_RAID6_RECOV=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+
+#
+# OCF Configuration
+#
+CONFIG_OCF_OCF=y
+# CONFIG_OCF_RANDOMHARVEST is not set
+CONFIG_OCF_CRYPTODEV=y
+CONFIG_OCF_CRYPTOSOFT=y
+# CONFIG_OCF_SAFE is not set
+# CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_HIFN is not set
+# CONFIG_OCF_HIFNHIPP is not set
+# CONFIG_OCF_TALITOS is not set
+# CONFIG_OCF_EP80579 is not set
+# CONFIG_OCF_OCFNULL is not set
+# CONFIG_OCF_BENCH is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/mv88f6500_gw_defconfig b/arch/arm/configs/mv88f6500_gw_defconfig
new file mode 100755
index 0000000..9826193
--- /dev/null
+++ b/arch/arm/configs/mv88f6500_gw_defconfig
@@ -0,0 +1,2161 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32.11
+# Thu Jul 12 10:30:22 2012
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_FEROCEON_ORION is not set
+# CONFIG_ARCH_FEROCEON_KW is not set
+CONFIG_ARCH_FEROCEON_KW2=y
+# CONFIG_ARCH_FEROCEON_MV78XX0 is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+
+#
+# Feroceon SoC options
+#
+CONFIG_MV88F6500=y
+# CONFIG_JTAG_DEBUG is not set
+
+#
+# Feroceon SoC Included Features
+#
+CONFIG_MV_NAND_SUPPORT=y
+CONFIG_MV_INCLUDE_PEX=y
+CONFIG_MV_INCLUDE_USB=y
+CONFIG_MV_INCLUDE_XOR=y
+CONFIG_MV_INCLUDE_CESA=y
+# CONFIG_MV_INCLUDE_NFC is not set
+CONFIG_MV_INCLUDE_LEGACY_NAND=y
+CONFIG_MV_INCLUDE_INTEG_SATA=y
+CONFIG_MV_INCLUDE_TDM=y
+CONFIG_MV_INCLUDE_GIG_ETH=y
+CONFIG_MV_INCLUDE_SPI=y
+CONFIG_MV_INCLUDE_SDIO=y
+# CONFIG_MV_INCLUDE_TS is not set
+CONFIG_MV_INCLUDE_PON=y
+CONFIG_MV_INCLUDE_SWITCH=y
+CONFIG_MV_GPP_MAX_PINS=70
+CONFIG_MV_DCACHE_SIZE=0x4000
+CONFIG_MV_ICACHE_SIZE=0x4000
+
+#
+# Feroceon SoC MTD support
+#
+CONFIG_MV_FLASH_CTRL=y
+# CONFIG_MV_INCLUDE_NORFLASH_MTD is not set
+CONFIG_MV_INCLUDE_SFLASH_MTD=y
+CONFIG_MTD_NAND_LNC=y
+CONFIG_MTD_NAND_LNC_RS_ECC=y
+# CONFIG_MTD_NAND_LNC_8BYTE_READ is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+CONFIG_USE_DSP=y
+CONFIG_MV_SP_I_FTCH_DB_INV=y
+# CONFIG_MV_SP_I_FTCH_LCK_L2_ICACHE is not set
+# CONFIG_MV_SP_I_FTCH_NONE is not set
+# CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING is not set
+CONFIG_FEROCEON_PROC=y
+CONFIG_UBOOT_STRUCT=y
+# CONFIG_MV_DBG_TRACE is not set
+CONFIG_MV_REAL_TIME=y
+# CONFIG_MV_CPU_PERF_CNTRS is not set
+# CONFIG_MV_CPU_L2_PERF_CNTRS is not set
+
+#
+# Power-Management options
+#
+CONFIG_MV_PMU_PROC=y
+CONFIG_MV_PM_IDLE_WFI_SR=y
+# CONFIG_MV_PM_IDLE_DEEPIDLE_SR is not set
+
+#
+# Soc DMA accelerations
+#
+# CONFIG_MV_USE_XOR_ENGINE is not set
+
+#
+# SoC Networking support
+#
+CONFIG_MV_ETHERNET=y
+# CONFIG_MV_ETH_LEGACY is not set
+CONFIG_MV_ETH_NETA=y
+CONFIG_MV_ETH_PORTS_NUM=3
+CONFIG_MV_ETH_0_MTU=1500
+CONFIG_MV_ETH_0_MACADDR="00:00:00:00:00:80"
+CONFIG_MV_ETH_1_MTU=1500
+CONFIG_MV_ETH_1_MACADDR="00:00:00:00:00:81"
+CONFIG_MV_ETH_2_MTU=1500
+CONFIG_MV_ETH_2_MACADDR="00:00:00:00:00:82"
+CONFIG_MV_ETH_RXQ=8
+CONFIG_MV_ETH_TXQ=8
+CONFIG_MV_ETH_TSO=y
+CONFIG_MV_ETH_TOOL=y
+# CONFIG_MV_LINUX_COUNTERS_DISABLE is not set
+CONFIG_NET_SKB_HEADROOM=96
+CONFIG_NET_SKB_RECYCLE=y
+CONFIG_NET_SKB_RECYCLE_DEF=1
+# CONFIG_MV_ETH_NFP is not set
+
+#
+# BM configuration
+#
+CONFIG_MV_ETH_BM=y
+CONFIG_MV_ETH_BM_CPU=y
+CONFIG_MV_ETH_BM_0_PKT_SIZE=0
+CONFIG_MV_ETH_BM_1_PKT_SIZE=0
+CONFIG_MV_ETH_BM_2_PKT_SIZE=0
+CONFIG_MV_ETH_BM_3_PKT_SIZE=256
+CONFIG_MV_ETH_BM_PORT_0=y
+CONFIG_MV_ETH_BM_PORT_0_LONG_POOL=0
+CONFIG_MV_ETH_BM_PORT_0_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_0_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_0_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_BM_PORT_1=y
+CONFIG_MV_ETH_BM_PORT_1_LONG_POOL=1
+CONFIG_MV_ETH_BM_PORT_1_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_1_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_1_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_BM_PORT_2=y
+CONFIG_MV_ETH_BM_PORT_2_LONG_POOL=2
+CONFIG_MV_ETH_BM_PORT_2_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_2_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_2_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_PNC=y
+CONFIG_MV_PNC_TCAM_LINES=512
+CONFIG_MV_ETH_PNC_MCAST_NUM=8
+CONFIG_MV_ETH_PNC_VLAN_PRIO=7
+CONFIG_MV_ETH_PNC_ETYPE=0
+CONFIG_MV_ETH_PNC_DSCP_PRIO=16
+# CONFIG_MV_ETH_PNC_L3_FLOW is not set
+# CONFIG_MV_ETH_PNC_WOL is not set
+CONFIG_MV_ETH_HWF=y
+CONFIG_MV_ETH_HWF_TXQ_DROP=60
+CONFIG_MV_ETH_HWF_TXQ_DROP_RND=0
+CONFIG_MV_ETH_PMT=y
+CONFIG_MV_ETH_PMT_FLOWS=256
+CONFIG_MV_ETH_PMT_CMD_PER_FLOW=12
+
+#
+# Network Interface configuration
+#
+
+#
+# Rx/Tx Queue configuration
+#
+CONFIG_MV_ETH_RXQ_DESC=128
+CONFIG_MV_ETH_RXQ_DEF=0
+CONFIG_MV_ETH_TXQ_DESC=512
+CONFIG_MV_ETH_TXQ_DEF=0
+
+#
+# IP/TCP/UDP Offloading
+#
+CONFIG_MV_ETH_TX_CSUM_OFFLOAD=y
+CONFIG_MV_ETH_TX_CSUM_OFFLOAD_DEF=y
+CONFIG_MV_ETH_RX_CSUM_OFFLOAD=y
+CONFIG_MV_ETH_RX_CSUM_OFFLOAD_DEF=y
+CONFIG_MV_ETH_GRO=y
+# CONFIG_MV_ETH_GRO_DEF is not set
+# CONFIG_MV_ETH_TSO_DEF is not set
+
+#
+# Control and Statistics
+#
+CONFIG_MV_ETH_DEBUG_CODE=y
+CONFIG_MV_ETH_STAT_ERR=y
+CONFIG_MV_ETH_STAT_INF=y
+CONFIG_MV_ETH_STAT_DBG=y
+# CONFIG_MV_ETH_STAT_DIST is not set
+
+#
+# Advanced Features
+#
+CONFIG_MV_ETH_TX_DONE_TIMER_PERIOD=10
+CONFIG_MV_ETH_CLEANUP_TIMER_PERIOD=10
+# CONFIG_MV_ETH_TXDONE_ISR is not set
+CONFIG_MV_ETH_TXDONE_COAL_PKTS=16
+CONFIG_MV_ETH_RX_COAL_PKTS=32
+CONFIG_MV_ETH_RX_COAL_USEC=100
+# CONFIG_MV_ETH_RX_DESC_PREFETCH is not set
+# CONFIG_MV_ETH_RX_PKT_PREFETCH is not set
+CONFIG_MV_ETH_RX_SPECIAL=y
+CONFIG_MV_ETH_TX_SPECIAL=y
+# CONFIG_MV_ETH_L2FW is not set
+CONFIG_MV_ETH_RX_POLL_WEIGHT=64
+CONFIG_MV_ETH_EXTRA_BUF_SIZE=120
+CONFIG_MV_ETH_EXTRA_BUF_NUM=512
+
+#
+# NFP support
+#
+
+#
+# NAPI GROUPS
+#
+CONFIG_MV_ETH_NAPI_GROUPS=1
+
+#
+# Group 0
+#
+CONFIG_MV_ETH_GROUP0_CPU=0x1
+CONFIG_MV_ETH_GROUP0_RXQ=0xff
+
+#
+# PON support for Network driver
+#
+CONFIG_MV_PON=y
+CONFIG_MV_PON_TXP_DEF=0
+CONFIG_MV_PON_TXQ_DEF=0
+
+#
+# Switch support
+#
+CONFIG_MV_ETH_SWITCH=y
+CONFIG_MV_ETH_SWITCH_NETDEV_NUM=6
+CONFIG_MV_ETH_SWITCH_NETCONFIG_0="3,(00:11:66:11:66:11,0)(00:22:77:22:77:22,1:2:3:4),mtu=1500"
+CONFIG_MV_ETH_SWITCH_NETCONFIG_1="0"
+CONFIG_MV_ETH_SWITCH_LINK=y
+
+#
+# ERRATA / WA
+#
+
+#
+# Cesa options
+#
+CONFIG_MV_CESA=y
+CONFIG_MV_CESA_TOOL=y
+CONFIG_MV_CESA_CHANNELS=2
+CONFIG_MV_CESA_CHAIN_MODE=y
+CONFIG_MV_CESA_OCF=y
+# CONFIG_MV_CESA_TEST is not set
+
+#
+# Telephony options
+#
+CONFIG_MV_PHONE=y
+# CONFIG_MV_TDM_SUPPORT is not set
+CONFIG_MV_COMM_UNIT_SUPPORT=y
+# CONFIG_SILABS_SLIC_SUPPORT is not set
+CONFIG_ZARLINK_SLIC_SUPPORT=y
+CONFIG_ZARLINK_SLIC_VE880=y
+# CONFIG_ZARLINK_SLIC_VE890 is not set
+# CONFIG_ZARLINK_SLIC_VE792 is not set
+CONFIG_MV_TDM_PCM_CLK_8MHZ=y
+# CONFIG_MV_TDM_PCM_CLK_4MHZ is not set
+# CONFIG_MV_TDM_PCM_CLK_2MHZ is not set
+CONFIG_MV_TDM_USE_INTERNAL_PCLK_SOURCE=y
+# CONFIG_MV_TDM_USE_EXTERNAL_PCLK_SOURCE is not set
+# CONFIG_MV_TDM_USE_DCO is not set
+CONFIG_MV_TDM_DUMMY=y
+# CONFIG_MV_PHONE_USE_IRQ_PROCESSING is not set
+# CONFIG_MV_PHONE_USE_FIQ_PROCESSING is not set
+CONFIG_MV_PHONE_USE_SLIC_LIBS=y
+
+#
+# SoC PON support
+#
+CONFIG_MV_PON_TCONTS=8
+# CONFIG_MV_GPON is not set
+# CONFIG_MV_EPON is not set
+CONFIG_SCSI_MVSATA=y
+
+#
+# Sata options
+#
+CONFIG_MV_SATA_SUPPORT_ATAPI=y
+CONFIG_MV_SATA_ENABLE_1MB_IOS=y
+# CONFIG_SATA_NO_DEBUG is not set
+CONFIG_SATA_DEBUG_ON_ERROR=y
+# CONFIG_SATA_FULL_DEBUG is not set
+# CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT is not set
+# CONFIG_MV_UART_POLLING_MODE is not set
+# CONFIG_MV_PRINTK_SLICE_SUPPORT is not set
+CONFIG_ARCH_FEROCEON=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_FEROCEON=y
+# CONFIG_CPU_FEROCEON_OLD_ID is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_FEROCEON=y
+CONFIG_CPU_TLB_FEROCEON=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_CACHE_FEROCEON_L2=y
+# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_ARMV5_L2_CACHE_COHERENCY_FIX=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+CONFIG_REORDER=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_FEROCEON_KW2=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_ADVANCED is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_FTP=y
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CT_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_NF_NAT_FTP=y
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_IP_NF_MANGLE is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+# CONFIG_IP6_NF_TARGET_NFP is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=1
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+# CONFIG_MV_SCATTERED_SPINUP is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_SCSI_MV_THOR=m
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID456=y
+CONFIG_MD_RAID6_PQ=y
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=y
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000E=y
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_SK98LIN=y
+# CONFIG_SK98LIN_NAPI is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=y
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+CONFIG_PHONE=y
+# CONFIG_PHONE_IXJ is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_LANGWELL is not set
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+CONFIG_THERMAL_SENSOR_KW2=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_MIXER_OSS is not set
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+CONFIG_SND_PCM_XRUN_DEBUG=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=y
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_AT91 is not set
+CONFIG_USB_GADGET_MRVL=y
+CONFIG_USB_MRVL=m
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PCI is not set
+# CONFIG_MMC_SDHCI_PLTFM is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_MVSDIO=y
+# CONFIG_MMC_CB710 is not set
+# CONFIG_MMC_VIA_SDMMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+CONFIG_JBD2=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=y
+CONFIG_ASYNC_CORE=y
+CONFIG_ASYNC_MEMCPY=y
+CONFIG_ASYNC_XOR=y
+CONFIG_ASYNC_PQ=y
+CONFIG_ASYNC_RAID6_RECOV=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+
+#
+# OCF Configuration
+#
+CONFIG_OCF_OCF=y
+# CONFIG_OCF_RANDOMHARVEST is not set
+CONFIG_OCF_CRYPTODEV=y
+CONFIG_OCF_CRYPTOSOFT=y
+# CONFIG_OCF_SAFE is not set
+# CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_HIFN is not set
+# CONFIG_OCF_HIFNHIPP is not set
+# CONFIG_OCF_TALITOS is not set
+# CONFIG_OCF_EP80579 is not set
+# CONFIG_OCF_OCFNULL is not set
+# CONFIG_OCF_BENCH is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/mv88f6500_gw_nfp_static_defconfig b/arch/arm/configs/mv88f6500_gw_nfp_static_defconfig
new file mode 100755
index 0000000..8481281
--- /dev/null
+++ b/arch/arm/configs/mv88f6500_gw_nfp_static_defconfig
@@ -0,0 +1,2174 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32.11
+# Wed Dec 28 03:36:25 2011
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_FEROCEON_ORION is not set
+# CONFIG_ARCH_FEROCEON_KW is not set
+CONFIG_ARCH_FEROCEON_KW2=y
+# CONFIG_ARCH_FEROCEON_MV78XX0 is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+
+#
+# Feroceon SoC options
+#
+CONFIG_MV88F6500=y
+# CONFIG_JTAG_DEBUG is not set
+
+#
+# Feroceon SoC Included Features
+#
+CONFIG_MV_NAND_SUPPORT=y
+CONFIG_MV_INCLUDE_PEX=y
+CONFIG_MV_INCLUDE_USB=y
+CONFIG_MV_INCLUDE_XOR=y
+CONFIG_MV_INCLUDE_CESA=y
+# CONFIG_MV_INCLUDE_NFC is not set
+CONFIG_MV_INCLUDE_LEGACY_NAND=y
+CONFIG_MV_INCLUDE_INTEG_SATA=y
+CONFIG_MV_INCLUDE_TDM=y
+CONFIG_MV_INCLUDE_GIG_ETH=y
+CONFIG_MV_INCLUDE_SPI=y
+CONFIG_MV_INCLUDE_SDIO=y
+# CONFIG_MV_INCLUDE_TS is not set
+CONFIG_MV_INCLUDE_PON=y
+CONFIG_MV_INCLUDE_SWITCH=y
+CONFIG_MV_GPP_MAX_PINS=70
+CONFIG_MV_DCACHE_SIZE=0x4000
+CONFIG_MV_ICACHE_SIZE=0x4000
+
+#
+# Feroceon SoC MTD support
+#
+# CONFIG_MV_FLASH_CTRL is not set
+# CONFIG_MV_INCLUDE_NORFLASH_MTD is not set
+# CONFIG_MV_INCLUDE_SFLASH_MTD is not set
+# CONFIG_MV_INCLUDE_MFLASH_MTD is not set
+CONFIG_MTD_NAND_LNC=y
+CONFIG_MTD_NAND_LNC_BOOT=y
+CONFIG_MTD_NAND_LNC_RS_ECC=y
+# CONFIG_MTD_NAND_LNC_8BYTE_READ is not set
+# CONFIG_MTD_NAND_NFC is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+CONFIG_USE_DSP=y
+CONFIG_MV_SP_I_FTCH_DB_INV=y
+# CONFIG_MV_SP_I_FTCH_LCK_L2_ICACHE is not set
+# CONFIG_MV_SP_I_FTCH_NONE is not set
+# CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING is not set
+CONFIG_FEROCEON_PROC=y
+CONFIG_UBOOT_STRUCT=y
+# CONFIG_MV_DBG_TRACE is not set
+CONFIG_MV_REAL_TIME=y
+# CONFIG_MV_CPU_PERF_CNTRS is not set
+# CONFIG_MV_CPU_L2_PERF_CNTRS is not set
+
+#
+# Power-Management options
+#
+CONFIG_MV_PMU_PROC=y
+CONFIG_MV_PM_IDLE_WFI_SR=y
+# CONFIG_MV_PM_IDLE_DEEPIDLE_SR is not set
+
+#
+# Soc DMA accelerations
+#
+# CONFIG_MV_USE_XOR_ENGINE is not set
+
+#
+# SoC Networking support
+#
+CONFIG_MV_ETHERNET=y
+# CONFIG_MV_ETH_LEGACY is not set
+CONFIG_MV_ETH_NETA=y
+CONFIG_MV_ETH_PORTS_NUM=3
+CONFIG_MV_ETH_0_MTU=1500
+CONFIG_MV_ETH_0_MACADDR="00:00:00:00:00:80"
+CONFIG_MV_ETH_1_MTU=1500
+CONFIG_MV_ETH_1_MACADDR="00:00:00:00:00:81"
+CONFIG_MV_ETH_2_MTU=1500
+CONFIG_MV_ETH_2_MACADDR="00:00:00:00:00:82"
+CONFIG_MV_ETH_RXQ=8
+CONFIG_MV_ETH_TXQ=8
+CONFIG_MV_ETH_TSO=y
+CONFIG_MV_ETH_TOOL=y
+# CONFIG_MV_LINUX_COUNTERS_DISABLE is not set
+CONFIG_NET_SKB_HEADROOM=96
+CONFIG_NET_SKB_RECYCLE=y
+CONFIG_NET_SKB_RECYCLE_DEF=1
+CONFIG_MV_ETH_NFP=y
+CONFIG_MV_ETH_NFP_DEF=0
+CONFIG_MV_ETH_NFP_FIB=y
+CONFIG_MV_ETH_NFP_NAT=y
+CONFIG_MV_ETH_NFP_PPP=y
+
+#
+# BM configuration
+#
+CONFIG_MV_ETH_BM=y
+CONFIG_MV_ETH_BM_CPU=y
+CONFIG_MV_ETH_BM_0_PKT_SIZE=0
+CONFIG_MV_ETH_BM_1_PKT_SIZE=0
+CONFIG_MV_ETH_BM_2_PKT_SIZE=0
+CONFIG_MV_ETH_BM_3_PKT_SIZE=256
+CONFIG_MV_ETH_BM_PORT_0=y
+CONFIG_MV_ETH_BM_PORT_0_LONG_POOL=0
+CONFIG_MV_ETH_BM_PORT_0_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_0_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_0_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_BM_PORT_1=y
+CONFIG_MV_ETH_BM_PORT_1_LONG_POOL=1
+CONFIG_MV_ETH_BM_PORT_1_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_1_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_1_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_BM_PORT_2=y
+CONFIG_MV_ETH_BM_PORT_2_LONG_POOL=2
+CONFIG_MV_ETH_BM_PORT_2_SHORT_POOL=3
+CONFIG_MV_ETH_BM_PORT_2_LONG_BUF_NUM=2048
+CONFIG_MV_ETH_BM_PORT_2_SHORT_BUF_NUM=4096
+CONFIG_MV_ETH_PNC=y
+CONFIG_MV_PNC_TCAM_LINES=512
+CONFIG_MV_ETH_PNC_MCAST_NUM=8
+CONFIG_MV_ETH_PNC_VLAN_PRIO=7
+CONFIG_MV_ETH_PNC_ETYPE=0
+CONFIG_MV_ETH_PNC_DSCP_PRIO=16
+# CONFIG_MV_ETH_PNC_L3_FLOW is not set
+# CONFIG_MV_ETH_PNC_WOL is not set
+CONFIG_MV_ETH_HWF=y
+CONFIG_MV_ETH_HWF_TXQ_DROP=60
+CONFIG_MV_ETH_HWF_TXQ_DROP_RND=0
+CONFIG_MV_ETH_PMT=y
+CONFIG_MV_ETH_PMT_FLOWS=256
+CONFIG_MV_ETH_PMT_CMD_PER_FLOW=12
+
+#
+# Network Interface configuration
+#
+
+#
+# Rx/Tx Queue configuration
+#
+CONFIG_MV_ETH_RXQ_DESC=128
+CONFIG_MV_ETH_RXQ_DEF=0
+CONFIG_MV_ETH_TXQ_DESC=512
+CONFIG_MV_ETH_TXQ_DEF=0
+
+#
+# IP/TCP/UDP Offloading
+#
+CONFIG_MV_ETH_TX_CSUM_OFFLOAD=y
+CONFIG_MV_ETH_TX_CSUM_OFFLOAD_DEF=y
+CONFIG_MV_ETH_RX_CSUM_OFFLOAD=y
+CONFIG_MV_ETH_RX_CSUM_OFFLOAD_DEF=y
+CONFIG_MV_ETH_GRO=y
+# CONFIG_MV_ETH_GRO_DEF is not set
+# CONFIG_MV_ETH_TSO_DEF is not set
+
+#
+# Control and Statistics
+#
+CONFIG_MV_ETH_DEBUG_CODE=y
+CONFIG_MV_ETH_STAT_ERR=y
+CONFIG_MV_ETH_STAT_INF=y
+CONFIG_MV_ETH_STAT_DBG=y
+# CONFIG_MV_ETH_STAT_DIST is not set
+
+#
+# Advanced Features
+#
+CONFIG_MV_ETH_TX_DONE_TIMER_PERIOD=10
+CONFIG_MV_ETH_CLEANUP_TIMER_PERIOD=10
+# CONFIG_MV_ETH_TXDONE_ISR is not set
+CONFIG_MV_ETH_TXDONE_COAL_PKTS=16
+CONFIG_MV_ETH_RX_COAL_PKTS=32
+CONFIG_MV_ETH_RX_COAL_USEC=100
+# CONFIG_MV_ETH_RX_DESC_PREFETCH is not set
+# CONFIG_MV_ETH_RX_PKT_PREFETCH is not set
+CONFIG_MV_ETH_RX_SPECIAL=y
+CONFIG_MV_ETH_TX_SPECIAL=y
+# CONFIG_MV_ETH_L2FW is not set
+CONFIG_MV_ETH_RX_POLL_WEIGHT=64
+CONFIG_MV_ETH_EXTRA_BUF_SIZE=120
+CONFIG_MV_ETH_EXTRA_BUF_NUM=512
+
+#
+# NFP support
+#
+CONFIG_MV_ETH_NFP_MODE_DEF=1
+# CONFIG_MV_ETH_NFP_EXT is not set
+CONFIG_MV_ETH_NFP_BRIDGE=y
+CONFIG_MV_ETH_NFP_FDB_MODE=y
+# CONFIG_MV_ETH_NFP_BRIDGE_MODE is not set
+# CONFIG_MV_ETH_NFP_FDB_LEARN is not set
+CONFIG_MV_ETH_NFP_VLAN=y
+# CONFIG_MV_ETH_NFP_VLAN_LEARN is not set
+# CONFIG_MV_ETH_NFP_FIB_LEARN is not set
+CONFIG_MV_ETH_NFP_CT=y
+# CONFIG_MV_ETH_NFP_CT_LEARN is not set
+# CONFIG_MV_ETH_NFP_LIMIT is not set
+CONFIG_MV_ETH_NFP_CLASSIFY=y
+# CONFIG_MV_ETH_NFP_PPP_LEARN is not set
+CONFIG_MV_ETH_NFP_STATS=y
+CONFIG_MV_ETH_NFP_DEBUG=y
+
+#
+# NAPI GROUPS
+#
+CONFIG_MV_ETH_NAPI_GROUPS=1
+
+#
+# Group 0
+#
+CONFIG_MV_ETH_GROUP0_CPU=0x1
+CONFIG_MV_ETH_GROUP0_RXQ=0xff
+
+#
+# PON support for Network driver
+#
+CONFIG_MV_PON=y
+CONFIG_MV_PON_TXP_DEF=0
+CONFIG_MV_PON_TXQ_DEF=0
+
+#
+# Switch support
+#
+CONFIG_MV_ETH_SWITCH=y
+CONFIG_MV_ETH_SWITCH_NETDEV_NUM=6
+CONFIG_MV_ETH_SWITCH_NETCONFIG_0="3,(00:11:66:11:66:11,0)(00:22:77:22:77:22,1:2:3:4),mtu=1500"
+CONFIG_MV_ETH_SWITCH_NETCONFIG_1="0"
+CONFIG_MV_ETH_SWITCH_LINK=y
+
+#
+# ERRATA / WA
+#
+
+#
+# Cesa options
+#
+CONFIG_MV_CESA=y
+CONFIG_MV_CESA_TOOL=y
+CONFIG_MV_CESA_CHANNELS=2
+CONFIG_MV_CESA_CHAIN_MODE=y
+CONFIG_MV_CESA_OCF=y
+# CONFIG_MV_CESA_TEST is not set
+
+#
+# Telephony options
+#
+CONFIG_MV_PHONE=y
+# CONFIG_MV_TDM_SUPPORT is not set
+CONFIG_MV_COMM_UNIT_SUPPORT=y
+# CONFIG_SILABS_SLIC_SUPPORT is not set
+CONFIG_ZARLINK_SLIC_SUPPORT=y
+CONFIG_ZARLINK_SLIC_VE880=y
+# CONFIG_ZARLINK_SLIC_VE792 is not set
+CONFIG_MV_TDM_PCM_CLK_8MHZ=y
+# CONFIG_MV_TDM_PCM_CLK_4MHZ is not set
+# CONFIG_MV_TDM_PCM_CLK_2MHZ is not set
+# CONFIG_MV_PHONE_USE_IRQ_PROCESSING is not set
+# CONFIG_MV_TDM_USE_EXTERNAL_PCLK_SOURCE is not set
+CONFIG_MV_PHONE_USE_SLIC_LIBS=y
+
+#
+# SoC PON support
+#
+CONFIG_MV_PON_TCONTS=8
+# CONFIG_MV_GPON is not set
+# CONFIG_MV_EPON is not set
+CONFIG_SCSI_MVSATA=y
+
+#
+# Sata options
+#
+CONFIG_MV_SATA_SUPPORT_ATAPI=y
+CONFIG_MV_SATA_ENABLE_1MB_IOS=y
+# CONFIG_SATA_NO_DEBUG is not set
+CONFIG_SATA_DEBUG_ON_ERROR=y
+# CONFIG_SATA_FULL_DEBUG is not set
+# CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT is not set
+# CONFIG_MV_UART_POLLING_MODE is not set
+# CONFIG_MV_PRINTK_SLICE_SUPPORT is not set
+CONFIG_ARCH_FEROCEON=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_FEROCEON=y
+# CONFIG_CPU_FEROCEON_OLD_ID is not set
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_FEROCEON=y
+CONFIG_CPU_TLB_FEROCEON=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_CACHE_FEROCEON_L2=y
+# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_ARMV5_L2_CACHE_COHERENCY_FIX=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+CONFIG_REORDER=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_FEROCEON_KW2=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_ADVANCED is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_FTP=y
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CT_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NFP=y
+CONFIG_NF_NAT_FTP=y
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_IP_NF_MANGLE is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_NF_CONNTRACK_IPV6 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=1
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+# CONFIG_MV_SCATTERED_SPINUP is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_SCSI_MV_THOR=m
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID456=y
+CONFIG_MD_RAID6_PQ=y
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=y
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000E=y
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_SK98LIN=y
+# CONFIG_SK98LIN_NAPI is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=y
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+CONFIG_PHONE=y
+# CONFIG_PHONE_IXJ is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_LANGWELL is not set
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+CONFIG_THERMAL_SENSOR_KW2=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_MIXER_OSS is not set
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+CONFIG_SND_PCM_XRUN_DEBUG=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=y
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_AT91 is not set
+CONFIG_USB_GADGET_MRVL=y
+CONFIG_USB_MRVL=m
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PCI is not set
+# CONFIG_MMC_SDHCI_PLTFM is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_MVSDIO=y
+# CONFIG_MMC_CB710 is not set
+# CONFIG_MMC_VIA_SDMMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+CONFIG_JBD2=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=y
+CONFIG_ASYNC_CORE=y
+CONFIG_ASYNC_MEMCPY=y
+CONFIG_ASYNC_XOR=y
+CONFIG_ASYNC_PQ=y
+CONFIG_ASYNC_RAID6_RECOV=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+
+#
+# OCF Configuration
+#
+CONFIG_OCF_OCF=y
+# CONFIG_OCF_RANDOMHARVEST is not set
+CONFIG_OCF_CRYPTODEV=y
+CONFIG_OCF_CRYPTOSOFT=y
+# CONFIG_OCF_SAFE is not set
+# CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_HIFN is not set
+# CONFIG_OCF_HIFNHIPP is not set
+# CONFIG_OCF_TALITOS is not set
+# CONFIG_OCF_EP80579 is not set
+# CONFIG_OCF_OCFNULL is not set
+# CONFIG_OCF_BENCH is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
old mode 100644
new mode 100755
index 00f46d9..3d4e8c5
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -49,7 +49,7 @@
 /*
  * Data preload for architectures that support it
  */
-#if __LINUX_ARM_ARCH__ >= 5
+#if __LINUX_ARM_ARCH__ >= 5 && defined(CONFIG_USE_DSP)
 #define PLD(code...)	code
 #else
 #define PLD(code...)
@@ -64,7 +64,7 @@
  *
  * On Feroceon there is much to gain however, regardless of cache mode.
  */
-#ifdef CONFIG_CPU_FEROCEON
+#if defined(CONFIG_CPU_FEROCEON) || defined(CONFIG_ARCH_FEROCEON)
 #define CALGN(code...) code
 #else
 #define CALGN(code...)
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
old mode 100644
new mode 100755
index 3d0cdd2..f6fbeaa
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -224,6 +224,26 @@
 	void (*flush_range)(unsigned long, unsigned long);
 };
 
+#ifdef CONFIG_MV_XOR_NET_DMA
+/* 
+ * Clean and Invalidate L1 cache w/o dsb()
+ * The call is intended for multiple calls and when dsb() on commit endpoint
+ * HW would align addresses. If 'end' was already aligned, put it 
+ * one cacheline up.
+ */
+static inline void flush_user_range_fast(unsigned long start, 
+										 unsigned long end, unsigned int vmflags)
+{
+	unsigned long flags;
+
+	raw_local_irq_save(flags);
+	__asm__("mcr p15, 5, %0, c15, c15, 0" : : "r" (start));
+	__asm__("mcr p15, 5, %0, c15, c15, 1" : : "r" (end-1));
+	raw_local_irq_restore(flags);
+
+	/* dsb();*/
+}
+#endif
 /*
  * Select the calling method
  */
@@ -441,6 +461,16 @@
 	if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page))
 		__cpuc_flush_dcache_page(page_address(page));
 }
+static inline void flush_kernel_dcache_addr(void *addr)
+{
+	if ((cache_is_vivt() || cache_is_vipt_aliasing()))
+		__cpuc_flush_dcache_page(addr);
+}
+static inline void invalidate_kernel_dcache_addr(void *addr)
+{
+	if ((cache_is_vivt() || cache_is_vipt_aliasing()))
+		__cpuc_flush_dcache_page(addr);
+}
 
 #define flush_dcache_mmap_lock(mapping) \
 	spin_lock_irq(&(mapping)->tree_lock)
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
old mode 100644
new mode 100755
index ff46dfa..4476ef2
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -194,6 +194,26 @@
 		void *, dma_addr_t, size_t);
 
 
+#ifdef	CONFIG_MV_SP_I_FTCH_DB_INV 
+extern void mv_l2_inv_range(const void *start, const void *end);
+static inline void mv_l2_sync(const void *start, size_t size, int direction)
+{
+	const void *end = start + size;
+
+	BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1));
+
+	switch (direction) {
+	case DMA_FROM_DEVICE:		/*  */
+	case DMA_BIDIRECTIONAL:		/*  */
+		mv_l2_inv_range(start, end);
+		break;
+	case DMA_TO_DEVICE:		/* */
+		break;
+	default:
+		BUG();
+	}
+}
+#endif
 #ifdef CONFIG_DMABOUNCE
 /*
  * For SA-1111, IXP425, and ADI systems  the dma-mapping functions are "magic"
@@ -302,7 +322,7 @@
 {
 	BUG_ON(!valid_dma_direction(dir));
 
-	if (!arch_is_coherent())
+	if (!arch_is_coherent() && (size > 0) )
 		dma_cache_maint(cpu_addr, size, dir);
 
 	return virt_to_dma(dev, cpu_addr);
@@ -350,7 +370,9 @@
 static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir)
 {
-	/* nothing to do */
+#ifdef CONFIG_MV_SP_I_FTCH_DB_INV
+	mv_l2_sync(phys_to_virt(handle), size, dir);
+#endif
 }
 #endif /* CONFIG_DMABOUNCE */
 
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 6d09974..b5f22ac 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -40,6 +40,21 @@
 	:							\
 	: "memory", "cc");					\
 	})
+/*
+ * Save the current interrupt enable state & disable IRQs
+ */
+#define raw_local_irq_fiq_save(x)				\
+	({							\
+		unsigned long temp;				\
+		(void) (&temp == &x);				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ local_irq_fiq_save\n"	\
+"	orr	%1, %0, #0xC0\n"				\
+"	msr	cpsr_c, %1"					\
+	: "=r" (x), "=r" (temp)					\
+	:							\
+	: "memory", "cc");					\
+	})
 	
 /*
  * Enable IRQs
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
old mode 100644
new mode 100755
index a38bdc7..987f878
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -37,6 +37,7 @@
 					/* IRQ mapping				*/
 	int		(*map_irq)(struct pci_dev *, u8, u8);
 	struct hw_pci	*hw;
+	int    mv_controller_num;
 };
 
 /*
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
old mode 100644
new mode 100755
index 6a89567..9771876
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -107,7 +107,7 @@
 /*
  * Prefetching support - only ARMv5.
  */
-#if __LINUX_ARM_ARCH__ >= 5
+#if __LINUX_ARM_ARCH__ >= 5 && defined(CONFIG_USE_DSP)
 
 #define ARCH_HAS_PREFETCH
 static inline void prefetch(const void *ptr)
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
old mode 100644
new mode 100755
index 5ccce0a..97dfbf6
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -143,6 +143,20 @@
 	__u32 fmemclk;
 };
 
+/* Marvell uboot parameters */
+#define ATAG_MV_UBOOT   	0x41000403
+#define MV_UBOOT_MAX_PORT	4
+struct tag_mv_uboot {
+	__u32 uboot_version;
+	__u32 tclk;
+	__u32 sysclk;
+	__u32 isUsbHost;
+	__u8  macAddr[MV_UBOOT_MAX_PORT][6];
+	__u16 mtu[MV_UBOOT_MAX_PORT];
+	__u32 nand_ecc;
+	__u32 mod_bitmask;
+};                     
+
 struct tag {
 	struct tag_header hdr;
 	union {
@@ -165,6 +179,11 @@
 		 * DC21285 specific
 		 */
 		struct tag_memclk	memclk;
+		 /*
+                 * Marvell specific
+                 */
+                struct tag_mv_uboot     mv_uboot;
+	
 	} u;
 };
 
diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
old mode 100644
new mode 100755
index cf4f3aa..91e4966
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -13,6 +13,11 @@
 extern char * strchr(const char * s, int c);
 
 #define __HAVE_ARCH_MEMCPY
+
+#if defined(CONFIG_MV_XOR_MEMCOPY) || defined(CONFIG_MV_IDMA_MEMCOPY)
+extern void * asm_memcpy(void *, const void*, __kernel_size_t);
+#endif
+
 extern void * memcpy(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMMOVE
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
old mode 100644
new mode 100755
index 1d6bd40..0e245ba
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -401,6 +401,42 @@
 extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count);
 extern unsigned long __must_check __strnlen_user(const char __user *s, long n);
 
+#if 0
+/*
+ * Hardware assistance
+ */
+#ifdef CONFIG_MV_XOR_COPY_FROM_USER
+extern unsigned long xor_copy_from_user(unsigned long to, unsigned long from, unsigned long n);
+#endif
+#ifdef CONFIG_MV_XOR_COPY_TO_USER
+extern unsigned long xor_copy_to_user(unsigned long to, unsigned long from, unsigned long n);
+#endif
+#ifdef CONFIG_MV_IDMA_COPYUSER
+extern unsigned long dma_copy_from_user(void *to, const void __user *from, unsigned long n);
+extern unsigned long dma_copy_to_user(void __user *to, const void *from, unsigned long n);
+#endif
+
+static inline unsigned long __arch_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+#ifdef CONFIG_MV_IDMA_COPYUSER    
+	if (n > CONFIG_MV_IDMA_COPYUSER_THRESHOLD)
+			return dma_copy_from_user(to,from,n);
+#endif
+
+#ifdef CONFIG_MV_XOR_COPY_FROM_USER
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	if (n > CONFIG_MV_XOR_COPY_FROM_USER_THRESHOLD)
+			return xor_copy_from_user((unsigned long)to, (unsigned long)from, n);
+#else
+#error "Kernel version >= 2,6,26 does not support xor_copy_from_user"
+#endif
+
+#endif
+
+	return __arch_copy_from_user(to, from, n);
+}
+#endif
+
 static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	if (access_ok(VERIFY_READ, from, n))
@@ -409,7 +445,30 @@
 		memset(to, 0, n);
 	return n;
 }
+#if 0
+static inline unsigned long __arch_copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+#ifdef CONFIG_MV_IDMA_COPYUSER    
+	if (n > CONFIG_MV_IDMA_COPYUSER_THRESHOLD)
+			return dma_copy_to_user(to,from,n);
+#endif
 
+#ifdef CONFIG_MV_XOR_COPY_TO_USER
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	if (n > CONFIG_MV_XOR_COPY_TO_USER_THRESHOLD)
+			return xor_copy_to_user((unsigned long)to, (unsigned long)from, n);
+#else
+#error "Kernel version >= 2,6,26 does not support xor_copy_to_user"
+#endif
+#endif
+
+#ifdef CONFIG_COPY_USER_MEMCPY 
+	return ___copy_to_user(to, from, n);
+#else
+	return __arch_copy_to_user(to, from, n);
+#endif
+}
+#endif
 static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
diff --git a/arch/arm/kernel/.gitignore b/arch/arm/kernel/.gitignore
old mode 100644
new mode 100755
index c5f676c..587cc87
--- a/arch/arm/kernel/.gitignore
+++ b/arch/arm/kernel/.gitignore
@@ -1 +1,2 @@
 vmlinux.lds
+asm-offsets.s
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index d2903e3..98d209a 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -1202,9 +1202,46 @@
  * get out of that mode without clobbering one register.
  */
 vector_fiq:
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	/* if no handler installed, bail out */
+	ldr	r9, 1f
+	ldr	r9, [r9]
+	movs	r9, r9
+	beq	fiq_ret
+
+	/* count fiq exceptions */
+	ldr	r11, 2f
+	ldr	r10, [r11]
+	add	r10, r10, #1
+	str	r10, [r11]
+
+	/* call C-language ISR */
+	stmdb	sp!, {r0-r7,r14}
+	mov	lr, pc
+	mov	pc, r9
+	ldmia	sp!, {r0-r7,r14}
+fiq_ret:
+	subs	pc, lr, #4
+
+1:	.long fiq_userptr
+2:	.long fiq_cnt
+
+.section .text
+.globl fiq_userptr
+fiq_userptr:
+	.long 0
+.globl fiq_cnt
+fiq_cnt:
+	.long 0
+.previous
+
+#else /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
 	disable_fiq
 	subs	pc, lr, #4
 
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
 /*=============================================================================
  * Address exception handler
  *-----------------------------------------------------------------------------
diff --git a/arch/arm/kernel/functionlist b/arch/arm/kernel/functionlist
new file mode 100755
index 0000000..64ca5da
--- /dev/null
+++ b/arch/arm/kernel/functionlist
@@ -0,0 +1,50 @@
+*(.text.__do_softirq)
+*(.text.net_rx_action)
+*(.text.net_tx_action)
+*(.text.mv_eth_poll)
+*(.text.mv_l2_inv_range)
+*(.text.mvNfpRx)
+*(.text.mvNfpPnc)
+*(.text.skb_put)
+*(.text.skb_push)
+*(.text.dev_kfree_skb_any)
+*(.text.__kfree_skb)
+*(.text.eth_type_trans)
+*(.text.skb_pull)
+*(.text.local_bh_disable)
+*(.text.local_bh_enable)
+*(.text.netif_receive_skb)
+*(.text.memset)
+*(.text.memcpy)
+*(.text.memmove)
+*(.text.__memzero)
+*(.text.ip_rcv)
+*(.text.ip_route_input)
+*(.text.ip_forward)
+*(.text.ip_output)
+*(.text.ip_finish_output)
+*(.text.ip_finish_output2)
+*(.text.sch_direct_xmit)
+*(.text.dev_queue_xmit)
+*(.text.dev_hard_start_xmit)
+*(.text.mv_eth_tx)
+*(.text.dst_release)
+*(.text.consume_skb)
+*(.text.dma_cache_maint)
+*(.text.feroceon_cache_fns)
+*(.text.feroceon_dma_inv_range)
+*(.text.feroceon_range_dma_inv_range)
+*(.text.feroceon_dma_clean_range)
+*(.text.feroceon_range_dma_clean_range)
+*(.text.feroceon_dma_flush_range)
+*(.text.feroceon_range_dma_flush_range)
+*(.text.outer_flush_range)
+*(.text.outer_clean_range)
+*(.text.outer_inv_range)
+*(.text.feroceon_l2_flush_range)
+*(.text.feroceon_l2_clean_range)
+*(.text.feroceon_l2_inv_range)
+*(.text.mv_eth_skb_recycle)
+*(.text.skb_recycle_check)
+*(.text.pfifo_fast_enqueue)
+*(.text.__qdisc_run)
diff --git a/arch/arm/kernel/functionlist_routing b/arch/arm/kernel/functionlist_routing
new file mode 100755
index 0000000..64ca5da
--- /dev/null
+++ b/arch/arm/kernel/functionlist_routing
@@ -0,0 +1,50 @@
+*(.text.__do_softirq)
+*(.text.net_rx_action)
+*(.text.net_tx_action)
+*(.text.mv_eth_poll)
+*(.text.mv_l2_inv_range)
+*(.text.mvNfpRx)
+*(.text.mvNfpPnc)
+*(.text.skb_put)
+*(.text.skb_push)
+*(.text.dev_kfree_skb_any)
+*(.text.__kfree_skb)
+*(.text.eth_type_trans)
+*(.text.skb_pull)
+*(.text.local_bh_disable)
+*(.text.local_bh_enable)
+*(.text.netif_receive_skb)
+*(.text.memset)
+*(.text.memcpy)
+*(.text.memmove)
+*(.text.__memzero)
+*(.text.ip_rcv)
+*(.text.ip_route_input)
+*(.text.ip_forward)
+*(.text.ip_output)
+*(.text.ip_finish_output)
+*(.text.ip_finish_output2)
+*(.text.sch_direct_xmit)
+*(.text.dev_queue_xmit)
+*(.text.dev_hard_start_xmit)
+*(.text.mv_eth_tx)
+*(.text.dst_release)
+*(.text.consume_skb)
+*(.text.dma_cache_maint)
+*(.text.feroceon_cache_fns)
+*(.text.feroceon_dma_inv_range)
+*(.text.feroceon_range_dma_inv_range)
+*(.text.feroceon_dma_clean_range)
+*(.text.feroceon_range_dma_clean_range)
+*(.text.feroceon_dma_flush_range)
+*(.text.feroceon_range_dma_flush_range)
+*(.text.outer_flush_range)
+*(.text.outer_clean_range)
+*(.text.outer_inv_range)
+*(.text.feroceon_l2_flush_range)
+*(.text.feroceon_l2_clean_range)
+*(.text.feroceon_l2_inv_range)
+*(.text.mv_eth_skb_recycle)
+*(.text.skb_recycle_check)
+*(.text.pfifo_fast_enqueue)
+*(.text.__qdisc_run)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
old mode 100644
new mode 100755
index c6c57b6..d503809
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -108,6 +108,9 @@
 	u32 irq[3];
 	u32 abt[3];
 	u32 und[3];
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	u32 fiq[4 * 1024];
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
 } ____cacheline_aligned;
 
 static struct stack stacks[NR_CPUS];
@@ -322,6 +325,18 @@
 {
 	unsigned int cpu = smp_processor_id();
 	struct stack *stk = &stacks[cpu];
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	/*
+	 * The add instruction with immediate addressing mode has
+	 * limited offset of 1024 words (2^12-1 bytes):
+	 * 	add "r" (stk), "I" (offsetof(struct stack, und[0]))
+	 * Hence, 'mov Rd, Rn' should be used with preloaded Rn.
+	 */
+	unsigned int irq_sp = (unsigned int)&stk->irq[0];
+	unsigned int abt_sp = (unsigned int)&stk->abt[0];
+	unsigned int und_sp = (unsigned int)&stk->und[0];
+	unsigned int fiq_sp = (unsigned int)&stk->fiq[4095];
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
 
 	if (cpu >= NR_CPUS) {
 		printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
@@ -341,6 +356,30 @@
 	/*
 	 * setup stacks for re-entrant exception handlers
 	 */
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	__asm__ (
+	"msr	cpsr_c, %1\n\t"
+	"mov	sp, %2\n\t"
+	"msr	cpsr_c, %3\n\t"
+	"mov	sp, %4\n\t"
+	"msr	cpsr_c, %5\n\t"
+	"mov	sp, %6\n\t"
+	"msr	cpsr_c, %7\n\t"
+	"mov	sp, %8\n\t"
+	"msr	cpsr_c, %9"
+	    :
+	    : "r" (stk),
+	      PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
+	      "r" (irq_sp),
+	      PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
+	      "r" (abt_sp),
+	      PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
+	      "r" (und_sp),
+	      PLC (PSR_F_BIT | PSR_I_BIT | FIQ_MODE),
+	      "r" (fiq_sp),
+	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
+	    : "r14");
+#else /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
 	__asm__ (
 	"msr	cpsr_c, %1\n\t"
 	"add	r14, %0, %2\n\t"
@@ -362,6 +401,7 @@
 	      "I" (offsetof(struct stack, und[0])),
 	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
 	    : "r14");
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
 }
 
 static struct machine_desc * __init setup_machine(unsigned int nr)
@@ -397,6 +437,7 @@
 	 * Ensure that start/size are aligned to a page boundary.
 	 * Size is appropriately rounded down, start is rounded up.
 	 */
+       if(size != 0) /* overcome bug in U-Boot */
 	size -= start & ~PAGE_MASK;
 	bank->start = PAGE_ALIGN(start);
 	bank->size  = size & PAGE_MASK;
@@ -743,6 +784,12 @@
 	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	parse_cmdline(cmdline_p, from);
 	paging_init(mdesc);
+#ifdef CONFIG_DEBUG_LL
+	{
+		extern int ll_debug;
+		ll_debug=1;
+	}
+#endif
 	request_standard_resources(&meminfo, mdesc);
 
 #ifdef CONFIG_SMP
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
old mode 100644
new mode 100755
index aecf87d..4c91d64
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -105,6 +105,9 @@
 			__exception_text_start = .;
 			*(.exception.text)
 			__exception_text_end = .;
+/* Then all the functions that are "hot" in profiles, to group them onto the same hugetlb entry */
+#include "functionlist"
+ /* Then the rest */
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S
old mode 100644
new mode 100755
index a9b9e22..b478dd5
--- a/arch/arm/lib/memcpy.S
+++ b/arch/arm/lib/memcpy.S
@@ -56,8 +56,16 @@
 
 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
 
+#if defined (CONFIG_MV_XOR_MEMCOPY) || defined (CONFIG_MV_IDMA_MEMCOPY)
+ENTRY(asm_memcpy)
+#else
 ENTRY(memcpy)
+#endif
 
 #include "copy_template.S"
 
+#if defined (CONFIG_MV_XOR_MEMCOPY) || defined (CONFIG_MV_IDMA_MEMCOPY)
+ENDPROC(asm_memcpy)
+#else
 ENDPROC(memcpy)
+#endif
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
old mode 100644
new mode 100755
index 6b967ff..38cae48
--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -49,13 +49,16 @@
 	return 1;
 }
 
-static unsigned long noinline
+#ifndef CONFIG_MV_XOR_MEMCOPY
+#define asm_memcpy memcpy
+#endif
+
 __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
 {
 	int atomic;
 
 	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
-		memcpy((void *)to, from, n);
+		asm_memcpy((void *)to, from, n);
 		return 0;
 	}
 
@@ -82,7 +85,7 @@
 		if (tocopy > n)
 			tocopy = n;
 
-		memcpy((void *)to, from, tocopy);
+		asm_memcpy((void *)to, from, tocopy);
 		to += tocopy;
 		from += tocopy;
 		n -= tocopy;
@@ -226,3 +229,33 @@
 subsys_initcall(test_size_treshold);
 
 #endif
+
+#ifdef CONFIG_MV_XOR_MEMCOPY
+//EXPORT_SYMBOL(asm_memcpy);
+
+extern void * xor_memcpy(void *, const void*, __kernel_size_t);
+extern void * asm_memcpy(void *, const void*, __kernel_size_t);
+
+void* memcpy(void * dest, const void * src, size_t n)
+{
+	if (n < CONFIG_MV_XOR_MEMCOPY_THRESHOLD) 
+		return asm_memcpy(dest, src, n);
+	return xor_memcpy(dest, src, n);
+}
+
+#elif defined (CONFIG_MV_IDMA_MEMCOPY)
+
+extern void * dma_memcpy(void *, const void*, __kernel_size_t);
+extern void * asm_memcpy(void *, const void *, __kernel_size_t);
+
+void* memcpy(void * dest, const void * src, size_t n)
+{
+	if (n < CONFIG_MV_IDMA_MEMCOPY_THRESHOLD) 
+		return asm_memcpy(dest, src, n);
+	return dma_memcpy(dest, src, n);
+}
+#endif
+
+
+
+
diff --git a/arch/arm/mach-feroceon-kw2/Kconfig b/arch/arm/mach-feroceon-kw2/Kconfig
new file mode 100755
index 0000000..2620b16
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/Kconfig
@@ -0,0 +1,14 @@
+if ARCH_FEROCEON_KW2
+
+choice
+	prompt "Feroceon-KW2 SoC type"
+	default MV88F6500
+
+config  MV88F6500
+	bool "88F6510/88F6530/88F6550/88F6560/ SoC"
+	---help---
+	Choosing this option will generate a linux kernel for the 88F6510/88F6530/88F6550/88F6560/ SoC
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-feroceon-kw2/Makefile b/arch/arm/mach-feroceon-kw2/Makefile
new file mode 100755
index 0000000..2368c22
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/Makefile
@@ -0,0 +1,244 @@
+#*******************************************************************************
+# Marvell GPL License Option
+#
+# If you received this File from Marvell, you may opt to use, redistribute and/or
+# modify this File in accordance with the terms and conditions of the General
+# Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+# available along with the File in the license.txt file or by writing to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+# on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+#
+# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+# DISCLAIMED.  The GPL License provides additional details about this warranty
+# disclaimer.
+#*******************************************************************************/
+include 	  $(srctree)/arch/arm/mach-feroceon-kw2/config/mvRules.mk
+
+ifdef CONFIG_MV_ETH_NFP
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/mv_nfp_mgr.o $(LSP_NFP_MGR_DIR)/nfp_sysfs.o  $(LSP_NFP_MGR_DIR)/mv_nfp_hooks.o \
+		$(LSP_NET_DEV_DIR)/mv_eth_nfp.o
+endif
+
+ifdef CONFIG_MV_ETH_NFP_FIB
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/nfp_fib_arp_sysfs.o
+ifdef CONFIG_IPV6
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/ipv6_parsing.o $(LSP_NFP_MGR_DIR)/nfp_fib6_arp_sysfs.o
+endif
+endif
+
+ifdef CONFIG_MV_ETH_NFP_CT
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/nfp_ct_sysfs.o
+ifdef CONFIG_IPV6
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/nfp_ct6_sysfs.o
+endif
+endif
+
+ifdef CONFIG_MV_ETH_NFP_CLASSIFY
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/nfp_classification_sysfs.o $(LSP_NFP_MGR_DIR)/nfp_exact_classification_sysfs.o \
+		   $(LSP_NFP_MGR_DIR)/nfp_prio_classification_sysfs.o
+endif
+
+ifdef CONFIG_MV_ETH_NFP_BRIDGE
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/nfp_bridge_sysfs.o
+endif
+
+ifdef CONFIG_MV_ETH_NFP_VLAN
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/nfp_vlan_sysfs.o
+endif
+
+ifdef CONFIG_MV_ETH_NFP_PPP
+	NFPOBJS += $(LSP_NFP_MGR_DIR)/nfp_ppp_sysfs.o
+endif
+
+ifdef CONFIG_MV_ETH_NFP
+	NFPOBJS += $(HAL_ETH_NFP_DIR)/mvNfp.o
+endif
+
+ifdef CONFIG_MV_ETH_NFP_CT
+	NFPOBJS += $(HAL_ETH_NFP_DIR)/mvNfpCt.o
+endif
+
+ifdef CONFIG_MV_ETH_NFP_BRIDGE
+ifdef CONFIG_MV_ETH_NFP_FDB_MODE
+	NFPOBJS += $(HAL_ETH_NFP_DIR)/mvNfpFdb.o
+else
+	NFPOBJS    += $(HAL_ETH_NFP_DIR)/mvNfpBridge.o
+endif
+endif
+
+ifdef CONFIG_MV_ETH_NFP_FIB
+	NFPOBJS += $(HAL_ETH_NFP_DIR)/mvNfpFib.o
+endif
+
+ifeq ($(CONFIG_MV_ETH_NFP),m)
+nfp-objs = $(NFPOBJS)
+obj-m := nfp.o
+endif
+
+# Objects list
+COMMON_OBJS	= $(COMMON_DIR)/mvDebug.o $(COMMON_DIR)/mvCommon.o $(COMMON_DIR)/mvStack.o $(COMMON_DIR)/mvList.o
+
+OSSERVICES_OBJS	= $(OSSERV_DIR)/mvOs.o
+
+HAL_OBJS	= $(HAL_RTC_DIR)/mvRtc.o  $(HAL_DRAM_SPD_DIR)/mvSpd.o		\
+                  $(HAL_CNTMR_DIR)/mvCntmr.o					\
+		  $(HAL_TWSI_DIR)/mvTwsi.o					\
+                  $(HAL_UART_DIR)/mvUart.o $(HAL_GPP_DIR)/mvGpp.o               \
+                  $(HAL_DRAM_DIR)/mvDramIf.o  					\
+		  $(HAL_IF_DIR)/mvSysDdr.o
+
+KW_FAM_OBJS	= $(BOARD_ENV_DIR)/mvBoardEnvSpec.o $(SOC_ENV_DIR)/mvCtrlEnvLib.o	\
+		  $(BOARD_ENV_DIR)/mvBoardEnvLib.o $(SOC_ENV_DIR)/mvCtrlEnvAddrDec.o 	\
+		  $(BOARD_ENV_DIR)/mvBoardEnvSysfs.o					\
+		  $(SOC_SYS_DIR)/mvAhbToMbus.o $(SOC_SYS_DIR)/mvCpuIf.o 		\
+		  $(SOC_CPU_DIR)/mvCpu.o $(SOC_DEVICE_DIR)/mvDevice.o			\
+		  $(SOC_ENV_DIR)/mvCtrlEthCompLib.o
+
+QD_OBJS		= $(HAL_QD_DIR)/src/driver/gtDrvConfig.o $(HAL_QD_DIR)/src/driver/gtDrvEvents.o \
+                  $(HAL_QD_DIR)/src/driver/gtHwCntl.o $(HAL_QD_DIR)/src/platform/gtMiiSmiIf.o	\
+                  $(HAL_QD_DIR)/src/platform/platformDeps.o $(HAL_QD_DIR)/src/platform/gtSem.o	\
+                  $(HAL_QD_DIR)/src/platform/gtDebug.o $(HAL_QD_DIR)/src/msapi/gtBrgFdb.o 	\
+                  $(HAL_QD_DIR)/src/msapi/gtBrgStp.o $(HAL_QD_DIR)/src/msapi/gtBrgVlan.o 	\
+                  $(HAL_QD_DIR)/src/msapi/gtEvents.o $(HAL_QD_DIR)/src/msapi/gtPortCtrl.o 	\
+                  $(HAL_QD_DIR)/src/msapi/gtPortStat.o $(HAL_QD_DIR)/src/msapi/gtPortStatus.o 	\
+                  $(HAL_QD_DIR)/src/msapi/gtQosMap.o $(HAL_QD_DIR)/src/msapi/gtPIRL.o  		\
+                  $(HAL_QD_DIR)/src/msapi/gtPhyCtrl.o $(HAL_QD_DIR)/src/msapi/gtPhyInt.o 	\
+                  $(HAL_QD_DIR)/src/msapi/gtSysConfig.o $(HAL_QD_DIR)/src/msapi/gtSysCtrl.o	\
+                  $(HAL_QD_DIR)/src/msapi/gtVersion.o $(HAL_QD_DIR)/src/msapi/gtUtils.o 	\
+                  $(HAL_QD_DIR)/src/msapi/gtBrgVtu.o $(HAL_QD_DIR)/src/msapi/gtPortRmon.o 	\
+                  $(HAL_QD_DIR)/src/msapi/gtSysStatus.o $(HAL_QD_DIR)/src/msapi/gtPortRateCtrl.o\
+                  $(HAL_QD_DIR)/src/msapi/gtPortPav.o $(HAL_QD_DIR)/src/msapi/gtVct.o		\
+		  $(HAL_QD_DIR)/src/msapi/gtPIRL2.o $(HAL_QD_DIR)/src/msapi/gtCCPVT.o		\
+		  $(HAL_QD_DIR)/src/msapi/gtPCSCtrl.o $(HAL_QD_DIR)/src/msapi/gtWeight.o
+
+NOR_OBJS	= $(HAL_NOR_DIR)/mvAmdFlash.o $(HAL_NOR_DIR)/mvFlash.o				\
+		  $(HAL_NOR_DIR)/mvFlashCom.o $(HAL_NOR_DIR)/mvIntelFlash.o
+
+LSP_OBJS        = $(LSP_DIR)/core.o $(LSP_DIR)/irq.o $(LSP_DIR)/time.o  	\
+                  $(LSP_DIR)/leds.o $(LSP_DIR)/sysmap.o  $(LSP_DIR)/rtc.o 	\
+		  $(LSP_DIR)/export.o $(LSP_DIR)/clock.o
+
+obj-y   				:=  feroceon.o
+feroceon-objs  				:=$(LSP_OBJS) $(COMMON_OBJS) $(OSSERVICES_OBJS) $(HAL_OBJS) 	\
+					  $(KW_FAM_OBJS) $(NOR_OBJS)
+
+feroceon-$(CONFIG_MV_INCLUDE_SDIO) 	+= $(HAL_SDMMC_DIR)/mvSdmmcAddrDec.o
+feroceon-$(CONFIG_MV_INCLUDE_XOR) 	+= $(HAL_XOR_DIR)/mvXor.o $(HAL_XOR_DIR)/mvXorAddrDec.o		\
+					   $(HAL_IF_DIR)/mvSysXor.o
+feroceon-$(CONFIG_MV_INCLUDE_PEX) 	+= $(HAL_PEX_DIR)/mvPex.o					\
+					   $(HAL_IF_DIR)/mvSysPex.o $(HAL_PEX_DIR)/mvPexAddrDec.o
+feroceon-$(CONFIG_MV_INCLUDE_USB) 	+= $(HAL_USB_DIR)/mvUsb.o $(HAL_USB_DIR)/mvUsbAddrDec.o		\
+					   $(HAL_IF_DIR)/mvSysUsb.o
+feroceon-y				+= $(HAL_ETHPHY_DIR)/mvEthPhy.o $(HAL_IF_DIR)/mvSysEthPhy.o
+
+ifneq ($(CONFIG_MV_ETH_NFP),m)
+	feroceon-y += $(NFPOBJS)
+endif
+
+# Legacy Giga driver
+ifeq ($(CONFIG_MV_ETH_LEGACY),y)
+feroceon-$(CONFIG_MV_ETH_LEGACY)	+= $(HAL_ETH_GBE_DIR)/mvEth.o $(HAL_ETH_GBE_DIR)/mvEthDebug.o \
+					   $(HAL_ETH_GBE_DIR)/mvEthAddrDec.o $(HAL_IF_DIR)/mvSysEth.o
+feroceon-$(CONFIG_MV_ETH_NFP)           += $(HAL_ETH_NFP_DIR)/mvNfp.o
+feroceon-$(CONFIG_MV_ETH_NFP_NAT) 	+= $(HAL_ETH_NFP_DIR)/mvNfpNat.o
+feroceon-$(CONFIG_MV_ETH_NFP_FDB) 	+= $(HAL_ETH_NFP_DIR)/mvNfpFdb.o
+feroceon-$(CONFIG_MV_ETH_NFP_PPP) 	+= $(HAL_ETH_NFP_DIR)/mvNfpPpp.o
+feroceon-$(CONFIG_MV_ETH_NFP_SEC)	+= $(HAL_ETH_NFP_DIR)/mvNfpSec.o
+endif
+
+# NETA Giga driver
+ifeq ($(CONFIG_MV_ETH_NETA),y)
+feroceon-$(CONFIG_MV_ETH_NETA)	        += $(HAL_ETH_GBE_DIR)/mvNeta.o $(HAL_ETH_GBE_DIR)/mvNetaDebug.o \
+					   $(HAL_ETH_GBE_DIR)/mvNetaAddrDec.o $(HAL_IF_DIR)/mvSysNeta.o
+feroceon-$(CONFIG_MV_ETH_PNC)    	+= $(HAL_ETH_PNC_DIR)/mvTcam.o  $(HAL_ETH_PNC_DIR)/mvPncAging.o \
+					$(HAL_ETH_PNC_DIR)/mvPnc.o $(HAL_ETH_PNC_DIR)/mvPncLb.o
+feroceon-$(CONFIG_MV_ETH_PNC_WOL)       += $(HAL_ETH_PNC_DIR)/mvPncWol.o
+feroceon-$(CONFIG_MV_ETH_BM) 	        += $(HAL_ETH_BM_DIR)/mvBm.o
+feroceon-$(CONFIG_MV_ETH_PMT)	        += $(HAL_ETH_PMT_DIR)/mvPmt.o
+feroceon-$(CONFIG_MV_ETH_HWF)           += $(HAL_ETH_GBE_DIR)/mvHwf.o
+endif
+
+feroceon-$(CONFIG_MV_INCLUDE_CESA) 	+= $(HAL_CESA_DIR)/mvCesa.o $(HAL_CESA_DIR)/mvCesaIf.o		 \
+					   $(HAL_CESA_DIR)/mvCesaDebug.o $(HAL_CESA_DIR)/mvCesaAddrDec.o \
+                        		   $(HAL_CESA_DIR)/mvMD5.o $(HAL_CESA_DIR)/mvSHA1.o 		 \
+					   $(HAL_CESA_DIR)/mvSHA256.o 					 \
+					   $(HAL_CESA_AES_DIR)/mvAesAlg.o $(HAL_CESA_AES_DIR)/mvAesApi.o \
+					   $(HAL_IF_DIR)/mvSysCesa.o
+feroceon-$(CONFIG_MV_CESA_TEST) 	+= $(HAL_CESA_DIR)/mvCesaTest.o
+feroceon-$(CONFIG_MV_INCLUDE_INTEG_SATA)+= $(HAL_IF_DIR)/mvSysSata.o $(HAL_SATA_DIR)/mvSataSoc.o	\
+					   $(HAL_SATA_DIR)/mvSataAddrDec.o
+feroceon-$(CONFIG_MV_INCLUDE_SPI) 	+= $(HAL_SPI_DIR)/mvSpi.o $(HAL_SPI_DIR)/mvSpiCmnd.o 		\
+                         		   $(HAL_SFLASH_DIR)/mvSFlash.o $(HAL_IF_DIR)/mvSysSFlash.o	\
+					   $(HAL_IF_DIR)/mvSysSpi.o
+feroceon-$(CONFIG_MV_INCLUDE_AUDIO) 	+= $(HAL_AUDIO_DIR)/mvAudio.o $(HAL_IF_DIR)/mvSysAudio.o	\
+					   $(HAL_AUDIO_DIR)/mvAudioAddrDec.o
+feroceon-$(CONFIG_MV_INCLUDE_TS) 	+= $(HAL_TS_DIR)/mvTsu.o $(HAL_IF_DIR)/mvSysTs.o		\
+					   $(HAL_TS_DIR)/mvTsuAddrDec.o
+feroceon-$(CONFIG_MV_CPU_PERF_CNTRS)    += $(HAL_CPU_DIR)/mvCpuCntrs.o $(HAL_CPU_DIR)/feroceon/mvFeroceonCntrs.o
+feroceon-$(CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT) += $(HAL_PEX_DIR)/mvVrtBrgPex.o
+feroceon-$(CONFIG_MV_CPU_L2_PERF_CNTRS) += $(HAL_CPU_DIR)/mvCpuL2Cntrs.o
+feroceon-$(CONFIG_MV_INCLUDE_NFC)       += $(HAL_NFC_DIR)/mvNfc.o
+#feroceon-$(CONFIG_MV_INCLUDE_PON)	+= $(HAL_PON_DIR)/mvPonOnuRegs.o $(HAL_PON_DIR)/mvPonOnuMac.o
+
+obj-$(CONFIG_MV_INCLUDE_SWITCH) 	+= $(QD_OBJS)
+
+# drivers part
+# Legacy Giga driver
+ifeq ($(CONFIG_MV_ETH_LEGACY),y)
+obj-$(CONFIG_MV_ETH_NFP) 	        += $(LSP_NFP_MGR_DIR)/mv_nfp_mgr.o
+obj-$(CONFIG_MV_ETH_NFP_SEC)            += $(LSP_NFP_MGR_DIR)/mv_nfp_sec.o
+endif
+
+ifeq ($(CONFIG_MV_ETH_NETA),y)
+obj-$(CONFIG_MV_ETH_PNC)                += $(LSP_PNC_DIR)/pnc_sysfs.o
+obj-$(CONFIG_MV_ETH_BM)                 += $(LSP_BM_DIR)/bm_sysfs.o  $(LSP_BM_DIR)/mv_eth_bm.o
+obj-$(CONFIG_MV_ETH_PNC_WOL)            += $(LSP_PNC_DIR)/wol_sysfs.o
+obj-$(CONFIG_MV_ETH_PMT)		+= $(LSP_PMT_DIR)/pmt_sysfs.o
+obj-$(CONFIG_MV_ETH_HWF)        	+= $(LSP_HWF_DIR)/hwf_sysfs.o
+ifndef CONFIG_MV_ETH_BM_CPU
+obj-$(CONFIG_MV_ETH_HWF)		+=  $(LSP_HWF_DIR)/hwf_bm.o
+endif
+obj-$(CONFIG_MV_ETH_L2FW)               += $(LSP_L2FW_DIR)/l2fw_sysfs.o $(LSP_L2FW_DIR)/mv_eth_l2fw.o
+obj-$(CONFIG_MV_ETH_L2SEC)              += $(LSP_L2FW_DIR)/mv_eth_l2sec.o
+endif
+
+obj-$(CONFIG_MV_USE_XOR_ENGINE) 	+= ../plat-feroceon/mv_drivers_lsp/mv_xor/
+obj-$(CONFIG_MV_CESA) 			+= ../plat-feroceon/mv_drivers_lsp/mv_cesa/
+obj-$(CONFIG_MV_TSU) 			+= ../plat-feroceon/mv_drivers_lsp/mv_tsu/
+#obj-y					+= ../plat-feroceon/mv_drivers_lsp/mv_btns/
+obj-y					+= ../plat-feroceon/mv_drivers_lsp/mv_gpio/
+obj-$(CONFIG_MV_DBG_TRACE)              += $(PLAT_DRIVERS)/mv_trace/
+obj-$(CONFIG_MV_INCLUDE_SWITCH)         += $(LSP_SWITCH_DIR)/
+
+#XML configuration support
+obj-y					+= ../plat-feroceon/mv_drivers_lsp/mv_ezxml/
+
+#PON
+obj-$(CONFIG_MV_GPON) += ../plat-feroceon/mv_drivers_lsp/mv_pon/
+obj-$(CONFIG_MV_EPON) += ../plat-feroceon/mv_drivers_lsp/mv_pon/
+
+#TPM
+obj-$(CONFIG_MV_TPM) += ../plat-feroceon/mv_drivers_lsp/mv_tpm/
+
+#CUST
+obj-$(CONFIG_MV_CUST) += ../plat-feroceon/mv_drivers_lsp/mv_cust/
+
+#MAC_LEARN
+obj-$(CONFIG_MV_MAC_LEARN) += ../plat-feroceon/mv_drivers_lsp/mv_mac_learn/
+
+# The rest of the drivers are compiled through the driver dir directly.
+
+
+# LSP part
+feroceon-$(CONFIG_MV_INCLUDE_USB)    	+= $(LSP_DIR)/usb.o
+feroceon-$(CONFIG_PCI)  		+= $(LSP_DIR)/pci.o
+feroceon-$(CONFIG_FEROCEON_PROC) 	+= ../plat-feroceon/mv_drivers_lsp/mv_proc/proc.o
+feroceon-$(CONFIG_CPU_FREQ_FEROCEON_KW2) += $(LSP_DIR)/cpufreq.o
+feroceon-$(CONFIG_CPU_IDLE)		+= $(LSP_DIR)/cpuidle.o
+feroceon-$(CONFIG_CPU_IDLE) 		+= $(LSP_DIR)/pm.o
+feroceon-$(CONFIG_CPU_IDLE) 		+= $(LSP_DIR)/sleep.o
+feroceon-$(CONFIG_MV_PHONE_USE_FIQ_PROCESSING) += $(LSP_DIR)/fiq.o
+feroceon-$(CONFIG_THERMAL_SENSOR_KW2)	+= hwmon.o
+
+
diff --git a/arch/arm/mach-feroceon-kw2/Makefile.boot b/arch/arm/mach-feroceon-kw2/Makefile.boot
new file mode 100755
index 0000000..c7e75ac
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/Makefile.boot
@@ -0,0 +1,4 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
+
diff --git a/arch/arm/mach-feroceon-kw2/clock.c b/arch/arm/mach-feroceon-kw2/clock.c
new file mode 100755
index 0000000..786de6f
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/clock.c
@@ -0,0 +1,61 @@
+/*
+ *  linux/arch/arm/mach-dove/clock.c
+ */
+
+/* TODO: Implement the functions below...	*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+
+#include "clock.h"
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+	return;
+}
+EXPORT_SYMBOL(clk_put);
+
+struct clk *clk_get_sys(const char *dev_id, const char *con_id)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_get_sys);
+
+void clks_register(struct clk *clks, size_t num)
+{
+}
+
+static int __init clk_init(void)
+{
+	/* TODO: Call clks_register with appropriate params. */
+	clks_register(NULL, 0);
+	return 0;
+}
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-feroceon-kw2/clock.h b/arch/arm/mach-feroceon-kw2/clock.h
new file mode 100755
index 0000000..3fd3a3b
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/clock.h
@@ -0,0 +1,5 @@
+struct clk {
+	unsigned int dummy;
+};
+
+void clks_register(struct clk *clks, size_t num);
diff --git a/arch/arm/mach-feroceon-kw2/config/mvRules.mk b/arch/arm/mach-feroceon-kw2/config/mvRules.mk
new file mode 100755
index 0000000..7c44a5d
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvRules.mk
@@ -0,0 +1,215 @@
+# This flags will be used only by the Marvell arch files compilation.
+
+###################################################################################################
+# General definitions
+###################################################################################################
+CPU_ARCH    = ARM
+CHIP        = 88F6500
+VENDOR      = Marvell
+ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+ENDIAN      = BE
+else
+ENDIAN      = LE
+endif
+
+###################################################################################################
+# directory structure
+###################################################################################################
+# Main directory structure
+SRC_PATH          = .
+PLAT_PATH	  = ../plat-feroceon
+PLAT_DRIVERS	  = $(PLAT_PATH)/mv_drivers_lsp
+HAL_DIR           = $(PLAT_PATH)/mv_hal
+COMMON_DIR        = $(PLAT_PATH)/common
+OSSERV_DIR        = $(PLAT_PATH)/linux_oss
+LSP_DIR           = $(SRC_PATH)
+CONFIG_DIR        = $(LSP_DIR)/config
+HAL_IF		  = $(LSP_DIR)/mv_hal_if
+
+# HALs
+HAL_ETHPHY_DIR    = $(HAL_DIR)/eth-phy
+HAL_FLASH_DIR     = $(HAL_DIR)/flash
+HAL_RTC_DIR       = $(HAL_DIR)/rtc/integ_rtc
+HAL_VOICEBAND     = $(HAL_DIR)/voiceband
+HAL_SLIC_DIR      = $(HAL_VOICEBAND)/slic
+HAL_DAA_DIR       = $(HAL_VOICEBAND)/daa
+HAL_SATA_DIR      = $(HAL_DIR)/sata/CoreDriver/
+HAL_QD_DIR        = $(HAL_DIR)/qd-dsdt
+HAL_SFLASH_DIR    = $(HAL_DIR)/sflash
+HAL_CNTMR_DIR     = $(HAL_DIR)/cntmr
+HAL_DRAM_DIR      = $(HAL_DIR)/ddr2
+HAL_DRAM_SPD_DIR  = $(HAL_DIR)/ddr2/spd
+HAL_DRAM_ARCH_DIR = $(HAL_DRAM_DIR)/Arch$(CPU_ARCH)
+HAL_GPP_DIR       = $(HAL_DIR)/gpp
+HAL_TWSI_DIR      = $(HAL_DIR)/twsi
+HAL_TWSI_ARCH_DIR = $(SOC_TWSI_DIR)/Arch$(CPU_ARCH)
+HAL_UART_DIR      = $(HAL_DIR)/uart
+HAL_NOR_DIR       = $(HAL_DIR)/norflash
+
+ifeq ($(CONFIG_MV_INCLUDE_PON),y)
+HAL_PON_DIR       = $(HAL_DIR)/pon
+LSP_EPON_CORE_DIR  = $(PLAT_DRIVERS)/mv_pon/core/epon
+LSP_GPON_CORE_DIR  = $(PLAT_DRIVERS)/mv_pon/core/gpon
+LSP_EPON_PERF_DIR  = $(PLAT_DRIVERS)/mv_pon/perf/epon
+LSP_GPON_PERF_DIR  = $(PLAT_DRIVERS)/mv_pon/perf/gpon
+LSP_EPON_PLAT_DIR  = $(PLAT_DRIVERS)/mv_pon/plat/epon
+LSP_GPON_PLAT_DIR  = $(PLAT_DRIVERS)/mv_pon/plat/gpon
+LSP_PON_PLAT_DIR   = $(PLAT_DRIVERS)/mv_pon/plat
+endif
+
+ifeq ($(CONFIG_MV_INCLUDE_TPM),y)
+LSP_TPM_CORE_DIR  = $(PLAT_DRIVERS)/mv_tpm/core
+LSP_TPM_PERF_DIR  = $(PLAT_DRIVERS)/mv_tpm/perf
+LSP_TPM_PLAT_DIR  = $(PLAT_DRIVERS)/mv_tpm/plat
+endif
+
+ifeq ($(CONFIG_MV_INCLUDE_CUST),y)
+LSP_CUST_CORE_DIR  = $(PLAT_DRIVERS)/mv_cust
+endif
+
+LSP_EZXML_DIR     = $(PLAT_DRIVERS)/mv_ezxml
+
+ifeq ($(CONFIG_MV_ETH_NETA),y)
+HAL_ETH_DIR       = $(HAL_DIR)/neta
+HAL_ETH_GBE_DIR   = $(HAL_DIR)/neta/gbe
+HAL_ETH_NFP_DIR   = $(HAL_DIR)/neta/nfp
+HAL_ETH_PNC_DIR   = $(HAL_DIR)/neta/pnc
+HAL_ETH_BM_DIR    = $(HAL_DIR)/neta/bm
+HAL_ETH_PMT_DIR   = $(HAL_DIR)/neta/pmt
+LSP_NETWORK_DIR   = $(PLAT_DRIVERS)/mv_neta
+LSP_NET_DEV_DIR   = $(LSP_NETWORK_DIR)/net_dev
+LSP_NFP_MGR_DIR   = $(LSP_NETWORK_DIR)/nfp_mgr
+LSP_PNC_DIR       = $(LSP_NETWORK_DIR)/pnc
+LSP_BM_DIR        = $(LSP_NETWORK_DIR)/bm
+LSP_PMT_DIR       = $(LSP_NETWORK_DIR)/pmt
+LSP_HWF_DIR       = $(LSP_NETWORK_DIR)/hwf
+LSP_L2FW_DIR      = $(LSP_NETWORK_DIR)/l2fw
+LSP_SWITCH_DIR    = $(PLAT_DRIVERS)/mv_switch
+endif
+
+ifeq ($(CONFIG_MV_ETH_LEGACY),y)
+HAL_ETH_DIR       = $(HAL_DIR)/eth
+HAL_ETH_GBE_DIR   = $(HAL_DIR)/eth/gbe
+HAL_ETH_NFP_DIR	  = $(HAL_DIR)/eth/nfp
+LSP_NETWORK_DIR   = $(PLAT_DRIVERS)/mv_network
+LSP_NET_DEV_DIR   = $(LSP_NETWORK_DIR)/mv_etherent
+LSP_NFP_MGR_DIR   = $(LSP_NETWORK_DIR)/nfp_mgr
+endif
+
+
+HAL_CPU_DIR       = $(HAL_DIR)/cpu
+HAL_SDMMC_DIR	  = $(HAL_DIR)/sdmmc
+ifeq ($(CONFIG_MV_INCLUDE_PEX),y)
+#HAL_PCIIF_DIR     = $(HAL_DIR)/pci-if
+HAL_PEX_DIR       = $(HAL_DIR)/pex
+endif
+ifeq ($(CONFIG_MV_INCLUDE_TDM),y)
+HAL_TDM_DIR       = $(HAL_DIR)/voiceband/tdm
+endif
+ifeq ($(CONFIG_MV_INCLUDE_USB),y)
+HAL_USB_DIR       = $(HAL_DIR)/usb
+endif
+ifeq ($(CONFIG_MV_INCLUDE_CESA),y)
+HAL_CESA_DIR	  = $(HAL_DIR)/cesa
+HAL_CESA_AES_DIR  = $(HAL_DIR)/cesa/AES
+endif
+ifeq ($(CONFIG_MV_INCLUDE_XOR),y)
+HAL_XOR_DIR       = $(HAL_DIR)/xor
+endif
+ifeq ($(CONFIG_MV_INCLUDE_SPI),y)
+HAL_SPI_DIR       = $(HAL_DIR)/spi
+endif
+ifeq ($(CONFIG_MV_INCLUDE_AUDIO),y)
+HAL_AUDIO_DIR     = $(HAL_DIR)/audio
+endif
+ifeq ($(CONFIG_MV_INCLUDE_TS),y)
+HAL_TS_DIR      = $(HAL_DIR)/ts
+endif
+ifeq ($(CONFIG_MV_INCLUDE_NFC),y)
+HAL_NFC_DIR     = $(HAL_DIR)/nfc
+endif
+
+LSP_TRACE_DIR   = $(PLAT_DRIVERS)/mv_trace
+
+# Environment components
+KW2_FAM_DIR	    = $(LSP_DIR)/kw2_family
+SOC_DEVICE_DIR      = $(KW2_FAM_DIR)/device
+SOC_CPU_DIR         = $(KW2_FAM_DIR)/cpu
+BOARD_ENV_DIR       = $(KW2_FAM_DIR)/boardEnv
+SOC_ENV_DIR         = $(KW2_FAM_DIR)/ctrlEnv
+SOC_SYS_DIR	    = $(KW2_FAM_DIR)/ctrlEnv/sys
+HAL_IF_DIR	    = $(LSP_DIR)/mv_hal_if
+
+#####################################################################################################
+# Include path
+###################################################################################################
+
+LSP_PATH_I      = $(srctree)/arch/arm/mach-feroceon-kw2
+PLAT_PATH_I	= $(srctree)/arch/arm/plat-feroceon
+
+HAL_PATH        = -I$(PLAT_PATH_I)/$(HAL_DIR) -I$(PLAT_PATH_I)/$(HAL_SATA_DIR) -I$(PLAT_PATH_I)/$(HAL_ETH_DIR) \
+		-I$(PLAT_PATH_I)/$(HAL_PON_DIR)
+KW2_FAM_PATH	= -I$(LSP_PATH_I)/$(KW2_FAM_DIR)
+QD_PATH         = -I$(PLAT_PATH_I)/$(HAL_QD_DIR)/Include  -I$(PLAT_PATH_I)/$(HAL_QD_DIR)/Include/h/msApi 	\
+                  -I$(PLAT_PATH_I)/$(HAL_QD_DIR)/Include/h/driver -I$(PLAT_PATH_I)/$(HAL_QD_DIR)/Include/h/platform
+
+COMMON_PATH   	= -I$(PLAT_PATH_I)/$(COMMON_DIR)
+
+OSSERV_PATH     = -I$(PLAT_PATH_I)/$(OSSERV_DIR)
+LSP_PATH        = -I$(LSP_PATH_I)/$(LSP_DIR)
+CONFIG_PATH     = -I$(LSP_PATH_I)/$(CONFIG_DIR)
+HAL_IF_PATH	= -I$(LSP_PATH_I)/$(HAL_IF)
+DRIVERS_LSP_PATH = -I$(PLAT_PATH_I)/$(PLAT_DRIVERS) -I$(PLAT_PATH_I)/$(LSP_NETWORK_DIR) -I$(PLAT_PATH_I)/$(LSP_SWITCH_DIR) \
+		   -I$(PLAT_PATH_I)/$(LSP_EPON_CORE_DIR) -I$(PLAT_PATH_I)/$(LSP_GPON_CORE_DIR) \
+		   -I$(PLAT_PATH_I)/$(LSP_EPON_PERF_DIR) -I$(PLAT_PATH_I)/$(LSP_GPON_PERF_DIR) \
+		   -I$(PLAT_PATH_I)/$(LSP_EPON_PLAT_DIR) -I$(PLAT_PATH_I)/$(LSP_GPON_PLAT_DIR) \
+		   -I$(PLAT_PATH_I)/$(LSP_PON_PLAT_DIR) \
+		   -I$(PLAT_PATH_I)/$(LSP_TPM_CORE_DIR) -I$(PLAT_PATH_I)/$(LSP_TPM_PLAT_DIR) -I$(PLAT_PATH_I)/$(LSP_TPM_PERF_DIR) \
+		   -I$(PLAT_PATH_I)/$(LSP_NET_DEV_DIR) -I$(PLAT_PATH_I)/$(LSP_EZXML_DIR) -I$(PLAT_PATH_I)/$(LSP_TRACE_DIR)
+
+EXTRA_INCLUDE  	= $(OSSERV_PATH) $(COMMON_PATH) $(HAL_PATH)  $(KW2_FAM_PATH) \
+                  $(LSP_PATH) $(CONFIG_PATH) $(DRIVERS_LSP_PATH) $(HAL_IF_PATH)
+
+###################################################################################################
+# defines
+###################################################################################################
+MV_DEFINE = -DMV_LINUX -DMV_CPU_$(ENDIAN) -DMV_$(CPU_ARCH)
+
+
+ifeq ($(CONFIG_MV_GATEWAY),y)
+EXTRA_INCLUDE	+= $(QD_PATH)
+EXTRA_CFLAGS    += -DLINUX
+endif
+
+ifeq ($(CONFIG_MV_INCLUDE_SWITCH),y)
+EXTRA_INCLUDE   += $(QD_PATH)
+EXTRA_CFLAGS    += -DLINUX
+endif
+
+ifeq ($(CONFIG_MV_CESA_TEST),y)
+EXTRA_CFLAGS 	+= -DCONFIG_MV_CESA_TEST
+endif
+
+ifeq ($(CONFIG_SATA_DEBUG_ON_ERROR),y)
+EXTRA_CFLAGS    += -DMV_LOG_ERROR
+endif
+
+ifeq ($(CONFIG_SATA_FULL_DEBUG),y)
+EXTRA_CFLAGS    += -DMV_LOG_DEBUG
+endif
+
+ifeq ($(CONFIG_MV_SATA_SUPPORT_ATAPI),y)
+EXTRA_CFLAGS    += -DMV_SUPPORT_ATAPI
+endif
+
+ifeq ($(CONFIG_MV_SATA_ENABLE_1MB_IOS),y)
+EXTRA_CFLAGS    += -DMV_SUPPORT_1MBYTE_IOS
+endif
+
+ifeq ($(CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT),y)
+EXTRA_CFLAGS    +=-DPCIE_VIRTUAL_BRIDGE_SUPPORT
+endif
+
+EXTRA_CFLAGS 	+= $(EXTRA_INCLUDE) $(MV_DEFINE)
+
+EXTRA_AFLAGS 	+= $(EXTRA_CFLAGS)
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysCesaConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysCesaConfig.h
new file mode 100755
index 0000000..c5921b2
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysCesaConfig.h
@@ -0,0 +1,89 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysCesaConfig.h - Marvell Cesa unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for cesa registers.
+*/
+#define MV_CESA_REGS_BASE(chan) 	(MV_CESA_REGS_OFFSET(chan))
+
+#define MV_CESA_TDMA_REGS_BASE(chan)	(MV_CESA_TDMA_REGS_OFFSET(chan))
+
+#define MV_CESA_CHANNELS		(CONFIG_MV_CESA_CHANNELS)
+
+#ifdef CONFIG_MV_CESA_CHAIN_MODE
+	#define MV_CESA_CHAIN_MODE
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysCntmrConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysCntmrConfig.h
new file mode 100755
index 0000000..378b1ef
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysCntmrConfig.h
@@ -0,0 +1,81 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysCntmrConfig.h - Marvell Counter Manager unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for counter manager registers.
+*/
+#define MV_CNTMR_REGS_BASE		(MV_CNTMR_REGS_OFFSET)
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysDdrConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysDdrConfig.h
new file mode 100755
index 0000000..02aac28
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysDdrConfig.h
@@ -0,0 +1,86 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysDdrConfig.h - Marvell DRAM controller unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for DDR registers.
+*/
+#define MV_DDR_REGS_BASE		(MV_DRAM_REGS_OFFSET)
+
+#ifndef MV_BOOTROM
+#define MV_STATIC_DRAM_ON_BOARD
+#endif
+
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysEthConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysEthConfig.h
new file mode 100755
index 0000000..62f898e
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysEthConfig.h
@@ -0,0 +1,198 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysEthConfig.h - Marvell Ethernet unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __mvSysEthConfig_h__
+#define __mvSysEthConfig_h__
+
+#include "mvSysHwConfig.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+/*
+** Base address for ethernet registers.
+*/
+#ifdef CONFIG_MV_PON
+#define MV_PON_PORT_ID_GET()	MV_PON_PORT_ID
+#define MV_PON_PORT(p)		((p) == MV_PON_PORT_ID)
+#define MV_PON_REG_BASE         MV_PON_REGS_OFFSET
+#define MV_ETH_REGS_BASE(p)	(MV_PON_PORT(p) ? MV_PON_REGS_OFFSET : MV_ETH_REGS_OFFSET(p))
+#else
+#define MV_PON_PORT(p)		MV_FALSE
+#define MV_ETH_REGS_BASE(p)	MV_ETH_REGS_OFFSET(p)
+#endif /* CONFIG_MV_PON */ 
+
+#define MV_BM_REG_BASE		MV_BM_REGS_OFFSET
+#define MV_PNC_REG_BASE         MV_PNC_REGS_OFFSET
+#define MV_ETH_COMPLEX_BASE		(MV_ETH_COMPLEX_OFFSET)
+#define MV_ETH_ONLY_REGS_BASE		(MV_ETH_ONLY_REGS_OFFSET)
+
+#if defined(CONFIG_MV_INCLUDE_GIG_ETH)
+
+/* put descriptors in uncached memory */
+/* #define ETH_DESCR_UNCACHED */
+
+/* port's default queueus */
+#define ETH_DEF_RXQ         0  
+
+#ifdef CONFIG_MV_ETH_LEGACY 
+
+#ifdef CONFIG_MV_NFP_STATS
+#define MV_FP_STATISTICS
+#else
+#undef MV_FP_STATISTICS
+#endif
+
+/* Default configuration for TX_EN workaround: 0 - Disabled, 1 - Enabled */
+#define MV_ETH_TX_EN_DEFAULT        0
+
+/* un-comment if you want to perform tx_done from within the poll function */
+/* #define ETH_TX_DONE_ISR */
+
+/* Descriptors location: DRAM/internal-SRAM */
+#define ETH_DESCR_IN_SDRAM
+#undef  ETH_DESCR_IN_SRAM    /* No integrated SRAM in 88Fxx81 devices */
+
+#if defined(ETH_DESCR_IN_SRAM)
+#if defined(ETH_DESCR_UNCACHED)
+ #define ETH_DESCR_CONFIG_STR    "Uncached descriptors in integrated SRAM"
+#else
+ #define ETH_DESCR_CONFIG_STR    "Cached descriptors in integrated SRAM"
+#endif
+#elif defined(ETH_DESCR_IN_SDRAM)
+#if defined(ETH_DESCR_UNCACHED)
+ #define ETH_DESCR_CONFIG_STR    "Uncached descriptors in DRAM"
+#else
+ #define ETH_DESCR_CONFIG_STR    "Cached descriptors in DRAM"
+#endif
+#else 
+ #error "Ethernet descriptors location undefined"
+#endif /* ETH_DESCR_IN_SRAM or ETH_DESCR_IN_SDRAM*/
+
+/* SW Sync-Barrier: not relevant for 88fxx81*/
+/* Reasnable to define this macro when descriptors in SRAM and buffers in DRAM */
+/* In RX the CPU theoretically might see himself as the descriptor owner,      */
+/* although the buffer hadn't been written to DRAM yet. Performance cost.      */
+/* #define INCLUDE_SYNC_BARR */
+
+/* Buffers cache coherency method (buffers in DRAM) */
+#ifndef MV_CACHE_COHER_SW
+/* Taken from mvCommon.h */
+/* Memory uncached, HW or SW cache coherency is not needed */
+#define MV_UNCACHED             0   
+/* Memory cached, HW cache coherency supported in WriteThrough mode */
+#define MV_CACHE_COHER_HW_WT    1
+/* Memory cached, HW cache coherency supported in WriteBack mode */
+#define MV_CACHE_COHER_HW_WB    2
+/* Memory cached, No HW cache coherency, Cache coherency must be in SW */
+#define MV_CACHE_COHER_SW       3
+
+#endif
+
+#define ETHER_DRAM_COHER    MV_CACHE_COHER_SW   /* No HW coherency in 88Fxx81 devices */
+
+#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB)
+ #define ETH_SDRAM_CONFIG_STR    "DRAM HW cache coherency (write-back)"
+#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT)
+ #define ETH_SDRAM_CONFIG_STR    "DRAM HW cache coherency (write-through)"
+#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW)
+ #define ETH_SDRAM_CONFIG_STR    "DRAM SW cache-coherency"
+#elif (ETHER_DRAM_COHER == MV_UNCACHED)
+#   define ETH_SDRAM_CONFIG_STR  "DRAM uncached"
+#else
+ #error "Ethernet-DRAM undefined"
+#endif /* ETHER_DRAM_COHER */
+
+
+/****************************************************************/
+/************* Ethernet driver configuration ********************/
+/****************************************************************/
+
+/* port's default queueus */
+#define ETH_DEF_TXQ         0
+
+#define MV_ETH_RX_Q_NUM     CONFIG_MV_ETH_RXQ
+#define MV_ETH_TX_Q_NUM     CONFIG_MV_ETH_TXQ
+
+/* interrupt coalescing setting */
+#define ETH_TX_COAL    		    200
+#define ETH_RX_COAL    		    200
+
+/* Checksum offloading */
+#define TX_CSUM_OFFLOAD
+#define RX_CSUM_OFFLOAD
+#endif /* CONFIG_MV_ETH_LEGACY */
+
+#endif /* CONFIG_MV_INCLUDE_GIG_ETH */
+
+#endif /* __mvSysEthConfig_h__ */
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysEthPhyConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysEthPhyConfig.h
new file mode 100755
index 0000000..9d19a95
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysEthPhyConfig.h
@@ -0,0 +1,77 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysEthPhyConfig.h - Marvell Ethernet-PHY specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysGppConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysGppConfig.h
new file mode 100755
index 0000000..274f31a
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysGppConfig.h
@@ -0,0 +1,82 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysGppConfig.h - Marvell GPP unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for GPP registers.
+*/
+#define MV_GPP_REGS_BASE(unit)		(MV_GPP_REGS_OFFSET(unit))
+#define MV_GPP_REGS_BASE_0		(MV_GPP_REGS_OFFSET_0)
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h
new file mode 100755
index 0000000..534528b
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h
@@ -0,0 +1,324 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysHwCfg.h - Marvell system HW configuration file
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __INCmvSysHwConfigh
+#define __INCmvSysHwConfigh
+
+#include "../../../../include/linux/autoconf.h"
+
+#define CONFIG_MARVELL	1
+
+/* includes */
+#define _1K         0x00000400
+#define _4K         0x00001000
+#define _8K         0x00002000
+#define _16K        0x00004000
+#define _32K        0x00008000
+#define _64K        0x00010000
+#define _128K       0x00020000
+#define _256K       0x00040000
+#define _512K       0x00080000
+
+#define _1M         0x00100000
+#define _2M         0x00200000
+#define _4M         0x00400000
+#define _8M         0x00800000
+#define _16M        0x01000000
+#define _32M        0x02000000
+#define _64M        0x04000000
+#define _128M       0x08000000
+#define _256M       0x10000000
+#define _512M       0x20000000
+
+#define _1G         0x40000000
+#define _2G         0x80000000
+
+/****************************************/
+/* Soc supporeted Units definitions	*/
+/****************************************/
+
+#ifdef CONFIG_MV_INCLUDE_PEX
+#define MV_INCLUDE_PEX
+#endif
+#ifdef CONFIG_MV_INCLUDE_TWSI
+#define MV_INCLUDE_TWSI
+#endif
+#ifdef CONFIG_MV_INCLUDE_CESA
+#define MV_INCLUDE_CESA
+#endif
+#ifdef CONFIG_MV_INCLUDE_GIG_ETH
+#define MV_INCLUDE_GIG_ETH
+#endif
+#ifdef CONFIG_MV_INCLUDE_INTEG_SATA
+#define MV_INCLUDE_INTEG_SATA
+#define MV_INCLUDE_SATA
+#endif
+#ifdef CONFIG_MV_INCLUDE_USB
+#define MV_INCLUDE_USB
+#define MV_USB_VOLTAGE_FIX
+#endif
+#ifdef CONFIG_MV_INCLUDE_LEGACY_NAND
+#define MV_INCLUDE_LEGACY_NAND
+#endif
+#ifdef CONFIG_MTD_NAND_NFC
+#define MTD_NAND_NFC
+#endif
+#ifdef CONFIG_MV_INCLUDE_PDMA
+#define MV_INCLUDE_PDMA
+#endif
+#ifdef CONFIG_MV_INCLUDE_TDM
+#define MV_INCLUDE_TDM
+#endif
+#ifdef CONFIG_MV_INCLUDE_XOR
+#define MV_INCLUDE_XOR
+#endif
+#ifdef CONFIG_MV_INCLUDE_TWSI
+#define MV_INCLUDE_TWSI
+#endif
+#ifdef CONFIG_MV_INCLUDE_UART
+#define MV_INCLUDE_UART
+#endif
+#ifdef CONFIG_MV_INCLUDE_SPI
+#define MV_INCLUDE_SPI
+#endif
+#ifdef CONFIG_MV_INCLUDE_AUDIO
+#define MV_INCLUDE_AUDIO
+#endif
+#ifdef CONFIG_MV_INCLUDE_TS
+#define MV_INCLUDE_TS
+#endif
+#ifdef CONFIG_MV_INCLUDE_SDIO
+#define MV_INCLUDE_SDIO
+#endif
+
+
+/* NAND flash stuff */
+#ifdef CONFIG_MTD_NAND_LNC
+#define MTD_NAND_LNC
+#endif
+
+/* SPI flash stuff */
+#ifdef CONFIG_MV_INCLUDE_SFLASH_MTD
+#define MV_INCLUDE_SFLASH_MTD
+#define MV_SPI
+#endif
+
+#ifdef CONFIG_MV_INCLUDE_NORFLASH_MTD
+#define MV_NOR
+#endif
+
+/****************************************************************/
+/************* General    configuration ********************/
+/****************************************************************/
+
+/* Enable Clock Power Control */
+#define MV_INCLUDE_CLK_PWR_CNTRL
+
+/* Disable the DEVICE BAR in the PEX */
+#define MV_DISABLE_PEX_DEVICE_BAR
+
+/* Allow the usage of early printings during initialization */
+#define MV_INCLUDE_EARLY_PRINTK
+
+/****************************************************************/
+/************* NFP configuration ********************************/
+/****************************************************************/
+#define MV_NFP_SEC_Q_SIZE		64
+#define MV_NFP_SEC_REQ_Q_SIZE		1000
+
+
+
+/****************************************************************/
+/************* CESA configuration ********************/
+/****************************************************************/
+
+#ifdef MV_INCLUDE_CESA
+
+/* Use 2K of SRAM */
+#define MV_CESA_MAX_BUF_SIZE           1600
+
+#endif /* MV_INCLUDE_CESA */
+
+/* DRAM cache coherency configuration */
+#define MV_CACHE_COHERENCY  MV_CACHE_COHER_SW
+
+
+
+/****************************************************************/
+/*************** Telephony configuration ************************/
+/****************************************************************/
+#if defined(CONFIG_MV_TDM_USE_EXTERNAL_PCLK_SOURCE)
+ #define MV_TDM_USE_EXTERNAL_PCLK_SOURCE
+#endif
+
+/* We use the following registers to store DRAM interface pre configuration   */
+/* auto-detection results													  */
+/* IMPORTANT: We are using mask register for that purpose. Before writing     */
+/* to units mask register, make sure main maks register is set to disable     */
+/* all interrupts.                                                            */
+#define DRAM_BUF_REG0   0x30810 /* sdram bank 0 size            */  
+#define DRAM_BUF_REG1   0x30820 /* sdram config                 */
+#define DRAM_BUF_REG2   0x30830 /* sdram mode                   */
+#define DRAM_BUF_REG3   0x308c4 /* dunit control low            */          
+#define DRAM_BUF_REG4   0x60a90 /* sdram address control        */
+#define DRAM_BUF_REG5   0x60a94 /* sdram timing control low     */
+#define DRAM_BUF_REG6   0x60a98 /* sdram timing control high    */
+#define DRAM_BUF_REG7   0x60a9c /* sdram ODT control low        */
+#define DRAM_BUF_REG8   0x60b90 /* sdram ODT control high       */
+#define DRAM_BUF_REG9   0x60b94 /* sdram Dunit ODT control      */
+#define DRAM_BUF_REG10  0x60b98 /* sdram Extended Mode          */
+#define DRAM_BUF_REG11  0x60b9c /* sdram Ddr2 Time Low Reg      */
+#define DRAM_BUF_REG12  0x60a00 /* sdram Ddr2 Time High Reg     */
+#define DRAM_BUF_REG13  0x60a04 /* dunit Ctrl High              */
+#define DRAM_BUF_REG14  0x60b00 /* sdram second DIMM exist      */
+
+/* Following the pre-configuration registers default values restored after    */
+/* auto-detection is done                                                     */
+#define DRAM_BUF_REG_DV 0
+
+/* System Mapping */
+#define SDRAM_CS0_BASE  0x00000000
+#define SDRAM_CS0_SIZE  _256M
+
+#define SDRAM_CS1_BASE  0x10000000
+#define SDRAM_CS1_SIZE  _256M
+
+#define SDRAM_CS2_BASE  0x20000000
+#define SDRAM_CS2_SIZE  _256M
+
+#define SDRAM_CS3_BASE  0x30000000
+#define SDRAM_CS3_SIZE  _256M
+
+/* PEX */
+#define PEX0_MEM_BASE		0xF3000000
+#define PEX0_MEM_SIZE		_16M
+
+#define PEX1_MEM_BASE		0xF4000000
+#define PEX1_MEM_SIZE		_16M
+
+#define CRYPT_ENG_BASE(chan) 		(0xF2200000 + (chan * 0x200000))
+#define CRYPT_ENG_SIZE	_2M
+
+/* Internal registers: size is defined in Controllerenvironment */
+#define INTER_REGS_BASE	0xF1000000
+
+#define DDR_OPERATION_BASE	(INTER_REGS_BASE | 0x1418)
+
+#define PEX0_IO_BASE	0xF2000000
+#define PEX0_IO_SIZE	_1M
+
+#define PEX1_IO_BASE		0xF2100000
+#define PEX1_IO_SIZE		_1M
+
+#define SPI_CS_BASE		0xF6000000
+#define SPI_CS_SIZE		_32M
+
+#define PNC_BM_PHYS_BASE	0xF5000000
+#define PNC_BM_SIZE		_1M
+
+#define PMT_GIGA_PHYS_BASE      0xf5100000
+#define PMT_PON_PHYS_BASE       0xf5200000
+#define PMT_MEM_SIZE            _1M
+
+/* Device Chip Selects */
+#define BOOTDEV_CS_BASE	0xFF800000
+#define BOOTDEV_CS_SIZE _8M
+
+/* NAND/NOR Flash */
+#define NAND_NOR_CS_BASE	0xF8000000
+#define NAND_CS_SIZE		_2M
+#define NOR_CS_SIZE		_128M
+
+/* CS2 - BOOTROM */
+#define DEVICE_CS2_BASE 0xFF900000
+#define DEVICE_CS2_SIZE _1M
+
+
+/* DRAM detection stuff */
+#define MV_DRAM_AUTO_SIZE
+
+/* Board clock detection */
+#define TCLK_AUTO_DETECT    	/* Use Tclk auto detection   */
+#define SYSCLK_AUTO_DETECT	/* Use SysClk auto detection */
+#define PCLCK_AUTO_DETECT  	/* Use PClk auto detection   */
+#define L2CLK_AUTO_DETECT 	/* Use L2Clk auto detection   */
+
+/* PEX-PCI\PCI-PCI Bridge*/
+#define PCI0_IF_PTP		0		/* Bridge exist on pciIf0*/
+
+ 
+
+#endif /* __INCmvSysHwConfigh */
+
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysNfcConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysNfcConfig.h
new file mode 100755
index 0000000..d72b7f8
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysNfcConfig.h
@@ -0,0 +1,36 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvSysNfcConfig.h - Marvell NAND flash conroller unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for Nand Controller registers.
+*/
+#define MV_NFC_REGS_BASE		(MV_NFC_REGS_OFFSET + INTER_REGS_BASE)
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysPexConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysPexConfig.h
new file mode 100755
index 0000000..b1891ab
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysPexConfig.h
@@ -0,0 +1,113 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysPciIfConfig.h - Marvell PCI / Pex units specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for Pex registers.
+*/
+#define MV_PEX_IF_REGS_BASE(unit) 		(MV_PEX_IF_REGS_OFFSET(unit))
+
+/* PEX-PCI\PCI-PCI Bridge*/
+#define PCI0_IF_PTP		0		/* no Bridge on pciIf0*/
+#define PCI1_IF_PTP		0		/* no Bridge on pciIf1*/
+
+
+#if defined (MV_INCLUDE_PEX)
+#define PCI_IF0_MEM0_BASE 	PEX0_MEM_BASE
+#define PCI_IF0_MEM0_SIZE 	PEX0_MEM_SIZE
+#define PCI_IF0_IO_BASE 	PEX0_IO_BASE
+#define PCI_IF0_IO_SIZE 	PEX0_IO_SIZE
+
+#define PCI_IF1_MEM0_BASE 	PEX1_MEM_BASE
+#define PCI_IF1_MEM0_SIZE 	PEX1_MEM_SIZE
+#define PCI_IF1_IO_BASE 	PEX1_IO_BASE
+#define PCI_IF1_IO_SIZE 	PEX1_IO_SIZE
+#endif
+
+
+/* PEX Work arround */
+/* the target we will use for the workarround */
+#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM
+/*a flag that indicates if we are going to use the 
+size and base of the target we using for the workarround
+window */
+#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1
+/* if the above flag is 0 then the following values
+will be used for the workarround window base and size,
+otherwise the following defines will be ignored */
+#define PEX_CONFIG_RW_WA_BASE 0xF3000000
+#define PEX_CONFIG_RW_WA_SIZE _16M
+
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysPonConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysPonConfig.h
new file mode 100755
index 0000000..b64a787
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysPonConfig.h
@@ -0,0 +1,83 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysDdrConfig.h - Marvell DRAM controller unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for PON registers.
+*/
+#define MV_EPON_MAC_REGS_BASE		(MV_PON_MAC_REGS_OFFSET)
+#define MV_GPON_MAC_REGS_BASE		(MV_PON_MAC_REGS_OFFSET)
+
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysRtcConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysRtcConfig.h
new file mode 100755
index 0000000..f36df4a
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysRtcConfig.h
@@ -0,0 +1,81 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysRtcConfig.h - Marvell Real-Time clock unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for RTC registers.
+*/
+#define MV_RTC_REGS_BASE		(MV_RTC_REGS_OFFSET)
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysSataConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysSataConfig.h
new file mode 100755
index 0000000..6521613
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysSataConfig.h
@@ -0,0 +1,81 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysSataConfig.h - Marvell Sata unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for SPI registers.
+*/
+#define MV_SATA_REGS_BASE		(MV_SATA_REGS_OFFSET)
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysSdmmcConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysSdmmcConfig.h
new file mode 100755
index 0000000..b38d8ac
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysSdmmcConfig.h
@@ -0,0 +1,81 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvSysSdmmcConfig.h - Marvell SDMMC unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for audio registers.
+*/
+#define MV_SDMMC_REGS_BASE		(MV_SDMMC_REGS_OFFSET)
+
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysSpiConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysSpiConfig.h
new file mode 100755
index 0000000..2eb6ade
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysSpiConfig.h
@@ -0,0 +1,81 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysSpiConfig.h - Marvell SPI unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for SPI registers.
+*/
+#define MV_SPI_REGS_BASE(unit)		(MV_SPI_REGS_OFFSET(unit))
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysTdmConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysTdmConfig.h
new file mode 100755
index 0000000..630dcdf
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysTdmConfig.h
@@ -0,0 +1,127 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysTdmConfig.h - Marvell TDM unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvOs.h"
+
+/****************************************************************/
+/*************** Telephony configuration ************************/
+/****************************************************************/
+#if defined(CONFIG_MV_TDM_SUPPORT)
+	#define MV_TDM_SUPPORT
+	#define MV_TDM_REGS_BASE	MV_TDM_REGS_OFFSET
+#elif defined(CONFIG_MV_COMM_UNIT_SUPPORT)
+	#define MV_COMM_UNIT_SUPPORT
+	#define MV_COMM_UNIT_REGS_BASE	MV_COMM_UNIT_REGS_OFFSET
+#endif
+
+#ifdef CONFIG_MV_TDM_USE_DCO
+	#define MV_TDM_USE_DCO
+#endif
+
+/* SLIC vendor */
+#if defined(CONFIG_SILABS_SLIC_SUPPORT)
+	#define SILABS_SLIC_SUPPORT
+	#if defined(CONFIG_SILABS_SLIC_3215)
+		#define SILABS_SLIC_3215
+	#elif defined(CONFIG_SILABS_SLIC_3217)
+		#define SILABS_SLIC_3217
+	#elif defined(CONFIG_SILAB_SLIC_SI3226)
+		#define SI3226X
+	#endif
+#else /* CONFIG_ZARLINK_SLIC_SUPPORT) */
+	#define ZARLINK_SLIC_SUPPORT
+	#define SLIC_TIMER_EVENT_SUPPORT
+	#if defined(CONFIG_ZARLINK_SLIC_VE880)
+		#define ZARLINK_SLIC_VE880
+	#elif defined(CONFIG_ZARLINK_SLIC_VE890)
+		#define ZARLINK_SLIC_VE890
+	#elif defined(CONFIG_ZARLINK_SLIC_VE792)
+		#define ZARLINK_SLIC_VE792
+	#endif
+#endif
+
+#if defined(CONFIG_MV_TDM_USE_EXTERNAL_PCLK_SOURCE)
+	#define MV_TDM_USE_EXTERNAL_PCLK_SOURCE
+#endif
+
+#if defined(CONFIG_MV_TDM_PCM_CLK_8MHZ)
+	#define MV_TDM_PCM_CLK_8MHZ
+#elif defined(CONFIG_MV_TDM_PCM_CLK_4MHZ)
+	#define MV_TDM_PCM_CLK_4MHZ
+#elif defined(CONFIG_MV_TDM_PCM_CLK_2MHZ)
+	#define MV_TDM_PCM_CLK_2MHZ
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysTsConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysTsConfig.h
new file mode 100755
index 0000000..08aab56
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysTsConfig.h
@@ -0,0 +1,84 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysTsConfig.h - Marvell TS unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for TS registers.
+*/
+#define MV_TSU_GLOBAL_REGS_BASE		(MV_TSU_GLOBAL_REGS_OFFSET)
+#define MV_TSU_REGS_BASE(port)		(MV_TSU_REGS_OFFSET(port))
+
+
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysTwsiConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysTwsiConfig.h
new file mode 100755
index 0000000..7262d13
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysTwsiConfig.h
@@ -0,0 +1,86 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysTwsiConfig.h - Marvell TWSI unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+/*
+** Base address for TWSI registers.
+*/
+#define MV_TWSI_SLAVE_REGS_BASE(unit) 	(MV_TWSI_SLAVE_REGS_OFFSET(unit))
+
+/*
+** Specific definition for Main CPU interrupt cause register.
+** Needed for TWSI operation completion monitoring.
+*/
+#define MV_TWSI_CPU_MAIN_INT_CASUE(chanNum)	(TWSI_CPU_HIGH_INT_CAUSE_REG)
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysUsbConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysUsbConfig.h
new file mode 100755
index 0000000..fbad137
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysUsbConfig.h
@@ -0,0 +1,81 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvSysUsbConfig.h - Marvell USB unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for USB registers.
+*/
+#define MV_USB_REGS_BASE(unit) 		(MV_USB_REGS_OFFSET(unit))
diff --git a/arch/arm/mach-feroceon-kw2/config/mvSysXorConfig.h b/arch/arm/mach-feroceon-kw2/config/mvSysXorConfig.h
new file mode 100755
index 0000000..15b1ba2
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/config/mvSysXorConfig.h
@@ -0,0 +1,80 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvSysXorConfig.h - Marvell XOR unit specific configurations
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvSysHwConfig.h"
+
+/*
+** Base address for XOR registers.
+*/
+#define MV_XOR_REGS_BASE(unit)		(MV_XOR_REGS_OFFSET(unit))
diff --git a/arch/arm/mach-feroceon-kw2/core.c b/arch/arm/mach-feroceon-kw2/core.c
new file mode 100755
index 0000000..a5cf6c7
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/core.c
@@ -0,0 +1,643 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+#include <asm/mach/time.h>
+#include <linux/clocksource.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <mach/system.h>
+
+#include <linux/tty.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
+#include <plat/cache-feroceon-l2.h>
+#include <linux/proc_fs.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
+#include <mach/serial.h>
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/mvCtrlEthCompLib.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "cpu/mvCpu.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "mvDebug.h"
+#include "mvSysHwConfig.h"
+#include "pex/mvPexRegs.h"
+#include "cntmr/mvCntmr.h"
+#include "gpp/mvGpp.h"
+#include "plat/gpio.h"
+#ifdef CONFIG_MTD_NAND_NFC
+#include "mv_mtd/nand_nfc.h"
+#endif
+#if defined(CONFIG_MV_INCLUDE_SDIO)
+#include "sdmmc/mvSdmmc.h"
+#include <plat/mvsdio.h>
+#endif
+#if defined(CONFIG_MV_INCLUDE_CESA)
+#include "cesa/mvCesa.h"
+#endif
+
+/* WD */
+#include <plat/orion_wdt.h>
+
+/* I2C */
+#include <linux/i2c.h>	
+#include <linux/mv643xx_i2c.h>
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+/* SPI */
+#include "mvSysSpiApi.h"
+
+
+/* Eth Phy */
+#include "mvSysEthPhyApi.h"
+
+extern unsigned int irq_int_type[];
+
+/* for debug putstr */
+#include <mach/uncompress.h> 
+static char arr[256];
+
+#ifdef MV_INCLUDE_EARLY_PRINTK
+extern void putstr(const char *ptr);
+void mv_early_printk(char *fmt,...)
+{
+	va_list args;
+	va_start(args, fmt);
+	vsprintf(arr,fmt,args);
+	va_end(args);
+	putstr(arr);
+}
+#endif
+
+
+extern void __init mv_map_io(void);
+extern void __init mv_init_irq(void);
+extern struct sys_timer mv_timer;
+extern MV_CPU_DEC_WIN* mv_sys_map(void);
+#if defined(CONFIG_MV_INCLUDE_CESA)
+extern u32 mv_crypto_base_get(void);
+#endif
+unsigned int support_wait_for_interrupt = 0x1;
+
+#ifdef CONFIG_MV_PMU_PROC
+struct proc_dir_entry *mv_pm_proc_entry;
+#endif /* CONFIG_MV_PMU_PROC */
+
+u32 mvTclk = 166666667;
+u32 mvSysclk = 200000000;
+u32 mvIsUsbHost = 1;
+u32 mod_config = 0;
+
+#ifdef CONFIG_MV_INCLUDE_GIG_ETH
+u8	mvMacAddr[CONFIG_MV_ETH_PORTS_NUM][6];
+u16	mvMtu[CONFIG_MV_ETH_PORTS_NUM] = {0};
+#endif
+extern MV_U32 gBoardId; 
+extern unsigned int elf_hwcap;
+
+#ifdef CONFIG_MTD_NAND_LNC
+extern unsigned int mv_nand_ecc;
+#endif
+
+static int noL2 = 0;
+static int __init noL2_setup(char *__unused)
+{
+	noL2 = 1;
+	return 1;
+}
+__setup("noL2", noL2_setup);
+
+
+static int __init parse_tag_mv_uboot(const struct tag *tag)
+{
+    	unsigned int mvUbootVer = 0;
+	int i = 0;
+ 
+	mvUbootVer = tag->u.mv_uboot.uboot_version;
+	mvIsUsbHost = tag->u.mv_uboot.isUsbHost;
+
+        printk("Using UBoot passing parameters structure\n");
+  
+	gBoardId =  (mvUbootVer & 0xff);
+#ifdef CONFIG_MV_INCLUDE_GIG_ETH
+	for (i = 0; i < CONFIG_MV_ETH_PORTS_NUM; i++) {
+#if defined (CONFIG_OVERRIDE_ETH_CMDLINE)
+		memset(mvMacAddr[i], 0, 6);
+		mvMtu[i] = 0;
+#else
+		memcpy(mvMacAddr[i], tag->u.mv_uboot.macAddr[i], 6);
+		mvMtu[i] = tag->u.mv_uboot.mtu[i];
+#endif
+	}
+#endif
+#ifdef CONFIG_MTD_NAND_LNC
+               /* get NAND ECC type(1-bit or 4-bit) */
+               if((mvUbootVer >> 8) >= 0x3040c)
+                       mv_nand_ecc = tag->u.mv_uboot.nand_ecc;
+               else
+                       mv_nand_ecc = 1; /* fallback to 1-bit ECC */
+#endif
+
+	mod_config = tag->u.mv_uboot.mod_bitmask;
+
+	return 0;
+}
+
+__tagtable(ATAG_MV_UBOOT, parse_tag_mv_uboot);
+
+#ifdef CONFIG_MV_INCLUDE_CESA
+unsigned char*  mv_sram_usage_get(int* sram_size_ptr)
+{
+	int used_size = 0;
+
+#if defined(CONFIG_MV_CESA)
+	used_size = sizeof(MV_CESA_SRAM_MAP);
+#endif
+
+	if(sram_size_ptr != NULL)
+		*sram_size_ptr = _8K - used_size;
+
+	return (char *)(mv_crypto_base_get() + used_size);
+}
+#endif
+
+
+void print_board_info(void)
+{
+	char name_buff[50];
+	printk("\n  Marvell Development Board (LSP Version %s_%s)", LSP_VERSION, UPON_SDK_VERSION);
+
+	mvBoardNameGet(name_buff);
+	printk("-- %s ",name_buff);
+
+	mvCtrlModelRevNameGet(name_buff);
+	printk(" Soc: %s",  name_buff);
+#if defined(MV_CPU_LE)
+	printk(" LE");
+#else
+	printk(" BE");
+#endif
+	printk("\n\n");
+	printk(" Detected Tclk %d and SysClk %d \n",mvTclk, mvSysclk);
+}
+
+/*****************************************************************************
+ * I2C(TWSI)
+ ****************************************************************************/
+
+/* Platform devices list */
+
+static struct mv64xxx_i2c_pdata kw_i2c_pdata = {
+       .freq_m         = 8, /* assumes 166 MHz TCLK */
+       .freq_n         = 3,
+       .timeout        = 1000, /* Default timeout of 1 second */
+};
+
+static struct resource kw_i2c_resources[] = {
+       {
+               .name   = "i2c base",
+               .start  = INTER_REGS_BASE + MV_TWSI_SLAVE_REGS_OFFSET(0),
+               .end    = INTER_REGS_BASE + MV_TWSI_SLAVE_REGS_OFFSET(0) + 0x20 -1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "i2c irq",
+               .start  = TWSI_IRQ_NUM(0),
+               .end    = TWSI_IRQ_NUM(0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device kw_i2c = {
+       .name           = MV64XXX_I2C_CTLR_NAME,
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(kw_i2c_resources),
+       .resource       = kw_i2c_resources,
+       .dev            = {
+               .platform_data = &kw_i2c_pdata,
+       },
+};
+
+#ifdef CONFIG_MTD_NAND_NFC
+/*****************************************************************************
+ * NAND controller
+ ****************************************************************************/
+static struct resource kw2_nfc_resources[] = {
+       {
+               .start  = INTER_REGS_BASE + MV_NFC_REGS_OFFSET,
+               .end    = INTER_REGS_BASE + MV_NFC_REGS_OFFSET + 0x400 -1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+#endif
+
+#if 0
+struct mtd_partition nand_parts_info[] = {
+	{ .name = "uboot",
+	  .offset = 0,
+	  .size = 2 * 1024 * 1024 },
+	{ .name = "uimageU",
+	  .offset = MTDPART_OFS_NXTBLK,
+	  .size = 4 * 1024 * 1024 },
+	{ .name = "rootfsU",
+	  .offset = MTDPART_OFS_NXTBLK,
+	  .size = MTDPART_SIZ_FULL },
+};
+int nand_parts_num = 3;
+#endif
+
+struct mtd_partition nand_parts_info[] = {
+	{ .name = "uboot",
+	  .offset = 0,
+	  .size = 2 * 1024 * 1024 },
+	{ .name = "uimageU",
+	  .offset = MTDPART_OFS_NXTBLK,
+	  .size = 4 * 1024 * 1024 },
+	{ .name = "rootfsU",
+	  .offset = MTDPART_OFS_NXTBLK,
+        .size = 94 * 1024 * 1024 },
+	{ .name = "spacer",
+	  .offset = MTDPART_OFS_NXTBLK,
+	  .size = 2 * 1024 * 1024 },
+	{ .name = "uimageB",
+	  .offset = MTDPART_OFS_NXTBLK,
+	  .size = 4 * 1024 * 1024 },
+	{ .name = "rootfsB",
+	  .offset = MTDPART_OFS_NXTBLK,
+	  .size = MTDPART_SIZ_FULL },
+};
+int nand_parts_num = 6;
+
+
+#ifdef CONFIG_MTD_NAND_NFC
+static struct nfc_platform_data kw2_nfc_data = {
+	.nfc_width	= 8,
+	.num_devs	= 1,
+	.num_cs		= 1,
+	.use_dma	= 0,
+	.ecc_type	= MV_NFC_ECC_BCH_2K,
+	.parts		= nand_parts_info,
+	.nr_parts	= 3,
+};
+
+static struct platform_device kw2_nfc = {
+       .name           = "orion-nfc-hal",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(kw2_nfc_resources),
+       .resource       = kw2_nfc_resources,
+       .dev            = {
+               .platform_data = &kw2_nfc_data,
+       },
+};
+#endif
+
+/*****************************************************************************
+ * UART
+ ****************************************************************************/
+static struct resource mv_uart0_resources[] = {
+	{
+		.start		= PORT0_BASE,
+		.end		= PORT0_BASE + 0xff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+#ifdef CONFIG_MV_UART_POLLING_MODE
+		.start          = 0,
+		.end            = 0,
+#else
+		.start          = UART_IRQ_NUM(0),
+		.end            = UART_IRQ_NUM(0),
+#endif
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+
+#if 0
+static struct resource mv_uart1_resources[] = {
+	{
+		.start		= PORT1_BASE,
+		.end		= PORT1_BASE + 0xff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start          = UART_IRQ_NUM(1),
+		.end            = UART_IRQ_NUM(1),
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+#endif
+
+static struct plat_serial8250_port mv_uart0_data[] = {
+	{
+		.mapbase	= PORT0_BASE,
+		.membase	= (char *)PORT0_BASE,
+#ifdef CONFIG_MV_UART_POLLING_MODE
+		.irq		= 0, //UART_IRQ_NUM(0),
+#else
+		.irq		= UART_IRQ_NUM(0),
+#endif
+		.flags		= UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_DWAPB,
+		.private_data	= (void *)0xf101207c,
+		.type           = PORT_16550A,
+		.regshift	= 2,
+	},
+	{ },
+};
+
+static struct plat_serial8250_port mv_uart1_data[] = {
+	{
+		.mapbase	= PORT1_BASE,
+		.membase	= (char *)PORT1_BASE,
+		.irq		= UART_IRQ_NUM(1),
+		.flags		= UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_DWAPB,
+		.private_data	= (void *)0xf101217c,
+		.type           = PORT_16550A,
+		.regshift	= 2,
+	},
+	{ },
+};
+
+static struct platform_device mv_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= mv_uart0_data,
+	},
+	.num_resources		= 2, /*ARRAY_SIZE(mv_uart_resources),*/
+	.resource		= mv_uart0_resources,
+};
+
+
+static void serial_initialize(void)
+{
+	mv_uart0_data[0].uartclk = mv_uart1_data[0].uartclk = mvTclk;
+	platform_device_register(&mv_uart);
+}
+
+#if defined(CONFIG_MV_INCLUDE_SDIO)
+
+static struct resource mvsdio_resources[] = {
+	[0] = {
+		.start	= INTER_REGS_BASE + MV_SDMMC_REGS_OFFSET,
+		.end	= INTER_REGS_BASE + MV_SDMMC_REGS_OFFSET + SZ_1K -1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= SDIO_IRQ_NUM,
+		.end	= SDIO_IRQ_NUM,
+		.flags	= IORESOURCE_IRQ,
+	},
+
+};
+
+static u64 mvsdio_dmamask = 0xffffffffUL;
+
+static struct mvsdio_platform_data mvsdio_data = {
+	.gpio_write_protect	= 0,
+	.gpio_card_detect	= 0,
+	.dram			= NULL,
+};
+
+static struct platform_device mv_sdio_plat = {
+	.name		= "mvsdio",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &mvsdio_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+		.platform_data	= &mvsdio_data,
+	},
+	.num_resources	= ARRAY_SIZE(mvsdio_resources),
+	.resource	= mvsdio_resources,
+};
+
+
+#endif /* #if defined(CONFIG_MV_INCLUDE_SDIO) */
+
+#ifdef CONFIG_MV_ETHERNET
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+#if defined(CONFIG_MV_ETH_LEGACY)
+static struct platform_device mv88fx_eth = {
+	.name		= "mv88fx_eth",
+	.id		= 0,
+	.num_resources	= 0,
+};
+#elif defined(CONFIG_MV_ETH_NETA)
+static struct platform_device mv88fx_neta = {
+	.name		= "mv88fx_neta",
+	.id		= 0,
+	.num_resources	= 0,
+};
+#else
+
+#error "Ethernet Mode is not defined (should be Legacy or NETA)"
+
+#endif /* Ethernet mode: legacy or NETA */
+
+#endif /* CONFIG_MV_ETHERNET */
+
+/*****************************************************************************
+ * WATCHDOG
+ ****************************************************************************/
+
+/* the orion watchdog device data structure */
+static struct orion_wdt_platform_data mv_wdt_data = {
+       .tclk           = 0,
+};
+
+/* the watchdog device structure */
+static struct platform_device mv_wdt_device = {
+       .name           = "orion_wdt",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &mv_wdt_data,
+       },
+       .num_resources  = 0,
+};
+
+/* init the watchdog device */
+static void __init mv_wdt_init(void)
+{
+       mv_wdt_data.tclk = mvTclk;
+       platform_device_register(&mv_wdt_device);
+}
+
+
+static void __init kirkwood_l2_init(void)
+{
+#ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH
+	MV_REG_BIT_SET(CPU_L2_CONFIG_REG, 0x10);
+	feroceon_l2_init(1);
+#else
+	MV_REG_BIT_RESET(CPU_L2_CONFIG_REG, 0x10);
+	feroceon_l2_init(0);
+#endif
+}
+
+static void __init mv_init(void)
+{
+	MV_U32 boardId;
+
+#ifdef CONFIG_CACHE_FEROCEON_L2
+	if ((noL2 == 0) && (mvCpuL2Exists() == MV_TRUE))
+		kirkwood_l2_init();
+	else
+		printk("No L2-Cache.\n");
+#endif
+
+        /* init the Board environment */
+       	mvBoardEnvInit();
+
+        /* init the controller environment */
+        if( mvCtrlEnvInit() ) {
+            printk( "Controller env initialization failed.\n" );
+            return;
+        }
+
+	/* Init the CPU windows setting and the access protection windows. */
+	if( mvCpuIfInit(mv_sys_map()) ) {
+
+		printk( "Cpu Interface initialization failed.\n" );
+		return;
+	}
+
+    	/* Init Tclk & SysClk */
+    	mvTclk = mvBoardTclkGet();
+   	mvSysclk = mvBoardSysClkGet();
+
+        support_wait_for_interrupt = 1;
+
+#ifdef CONFIG_JTAG_DEBUG
+	support_wait_for_interrupt = 0; /*  for Lauterbach */
+#endif
+
+	elf_hwcap &= ~HWCAP_JAVA;
+
+	serial_initialize();
+
+	/* At this point, the CPU windows are configured according to default definitions in mvSysHwConfig.h */
+	/* and cpuAddrWinMap table in mvCpuIf.c. Now it's time to change defaults for each platform.         */
+	mvCpuIfAddDecShow();
+
+	print_board_info();
+
+	mv_gpio_init();
+
+#ifdef CONFIG_MV_INCLUDE_SPI
+	/* SPI */
+	mvSysSpiInit(0, _16M);
+#endif
+
+	/* ETH-PHY */
+	mvSysEthPhyInit();
+
+	/* I2C */
+	platform_device_register(&kw_i2c);
+
+#ifdef CONFIG_MV_PMU_PROC
+	mv_pm_proc_entry = proc_mkdir("mv_pm", NULL);
+#endif /* CONFIG_MV_PMU_PROC */
+
+#if defined(CONFIG_MV_INCLUDE_SDIO)
+	if (mvCtrlSdioSupport()) {
+		if (MV_TRUE == mvCtrlPwrClckGet(SDIO_UNIT_ID, 0)) {
+			int irq_detect = mvBoardSDIOGpioPinGet(BOARD_GPP_SDIO_DETECT);
+			MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	
+			if (irq_detect != MV_ERROR) {
+				mvsdio_data.gpio_card_detect = mvBoardSDIOGpioPinGet(BOARD_GPP_SDIO_DETECT);
+				irq_int_type[mvBoardSDIOGpioPinGet(BOARD_GPP_SDIO_DETECT)+IRQ_GPP_START] = GPP_IRQ_TYPE_CHANGE_LEVEL;
+			}
+	
+			if (mvBoardSDIOGpioPinGet(BOARD_GPP_SDIO_WP) != MV_ERROR)
+				mvsdio_data.gpio_write_protect = mvBoardSDIOGpioPinGet(BOARD_GPP_SDIO_WP);
+	
+			if (MV_OK == mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1))
+				if (MV_OK == mvSdmmcWinInit(addrWinMap))
+					mvsdio_data.clock = 200000000; //mvBoardTclkGet();
+			platform_device_register(&mv_sdio_plat);
+		}
+	}
+#endif
+
+#ifdef CONFIG_MV_ETHERNET
+	/* Ethernet */
+#if defined(CONFIG_MV_ETH_LEGACY)
+	platform_device_register(&mv88fx_eth);
+#elif defined(CONFIG_MV_ETH_NETA)
+	mv88fx_neta.dev.platform_data = NULL;
+	platform_device_register(&mv88fx_neta);
+#endif /* Ethernet mode: legacy or NETA */
+#endif /* CONFIG_MV_ETHERNET */
+
+#ifdef CONFIG_THERMAL_SENSOR_KW2
+	/* SoC hwmon Thermal Sensor */
+	platform_device_register_simple("KW2Thermal", 0, NULL, 0);
+#endif
+
+#ifdef CONFIG_MTD_NAND_NFC
+	kw2_nfc_data.tclk = mvTclk;
+	platform_device_register(&kw2_nfc);
+#endif
+
+       /* WATCHDOG */
+       mv_wdt_init();
+
+	/* CPU Idle driver. */
+	boardId = mvBoardIdGet();
+	if ((boardId == DB_88F6535_BP_ID) || (boardId == RD_88F6560_GW_ID))
+		platform_device_register_simple("kw_cpuidle", 0, NULL, 0);
+
+	return;
+}
+
+
+MACHINE_START(FEROCEON_KW2 ,"Feroceon-KW2")
+	/* MAINTAINER("MARVELL") */
+	.phys_io = 0xf1000000,
+	.io_pg_offst = ((0xf1000000) >> 18) & 0xfffc,
+	.boot_params = 0x00000100,
+	.map_io = mv_map_io,
+	.init_irq = mv_init_irq,
+	.timer = &mv_timer,
+	.init_machine = mv_init,
+MACHINE_END
+
diff --git a/arch/arm/mach-feroceon-kw2/cpufreq.c b/arch/arm/mach-feroceon-kw2/cpufreq.c
new file mode 100755
index 0000000..e9a8750
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/cpufreq.c
@@ -0,0 +1,244 @@
+/*
+ * arch/arm/mach-kirkwood/cpufreq.c
+ *
+ * Clock scaling for Kirkwood SoC
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/io.h>
+#include <linux/proc_fs.h>
+#include <config/mvSysHwConfig.h>
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "cpu/mvCpu.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+extern struct proc_dir_entry *mv_pm_proc_entry;
+
+enum kw_cpufreq_range {
+	KW_CPUFREQ_LOW 		= 0,
+	KW_CPUFREQ_HIGH 	= 1
+};
+
+static struct cpufreq_frequency_table kw_freqs[] = {
+	{ KW_CPUFREQ_LOW, 0                  },
+	{ KW_CPUFREQ_HIGH, 0                  },
+	{ 0, CPUFREQ_TABLE_END  }
+};
+
+
+/*
+ * Power management function: set or unset powersave mode
+ */
+static inline void kw_set_powersave(u8 on)
+{
+	DB(printk(KERN_DEBUG "cpufreq: Setting PowerSaveState to %s\n", on ? "on" : "off"));
+
+	if (on)
+		mvCtrlPwrSaveOn();
+	else
+		mvCtrlPwrSaveOff();
+}
+
+static int kw_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	if (unlikely(!cpu_online(policy->cpu)))
+		return -ENODEV;
+
+	return cpufreq_frequency_table_verify(policy, kw_freqs);
+}
+
+/*
+ * Get the current frequency for a given cpu.
+ */
+static unsigned int kw_cpufreq_get(unsigned int cpu)
+{
+	unsigned int freq;
+	u32 reg;
+
+	if (unlikely(!cpu_online(cpu)))
+		return -ENODEV;
+
+	/* To get the current frequency, we have to check if
+	* the powersave mode is set. */
+	reg = MV_REG_READ(POWER_MNG_CTRL_REG);
+
+	if (reg & PMC_POWERSAVE_EN)
+		freq = kw_freqs[KW_CPUFREQ_LOW].frequency;
+	else
+		freq = kw_freqs[KW_CPUFREQ_HIGH].frequency;
+
+	return freq;
+}
+
+/*
+ * Set the frequency for a given cpu.
+ */
+static int kw_cpufreq_target(struct cpufreq_policy *policy,
+		unsigned int target_freq, unsigned int relation)
+{
+	unsigned int index;
+	struct cpufreq_freqs freqs;
+
+	if (unlikely(!cpu_online(policy->cpu)))
+		return -ENODEV;
+
+	/* Lookup the next frequency */
+	if (unlikely(cpufreq_frequency_table_target(policy,
+		kw_freqs, target_freq, relation, &index)))
+		return -EINVAL;
+
+
+	freqs.old = policy->cur;
+	freqs.new = kw_freqs[index].frequency;
+	freqs.cpu = policy->cpu;
+
+	DB(printk(KERN_DEBUG "cpufreq: Setting CPU Frequency to %u KHz\n",freqs.new));
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* Interruptions will be disabled in the low level power mode
+	* functions. */
+	if (index == KW_CPUFREQ_LOW)
+		kw_set_powersave(1);
+	else if (index == KW_CPUFREQ_HIGH)
+		kw_set_powersave(0);
+	else
+		return -EINVAL;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+static int kw_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	if (unlikely(!cpu_online(policy->cpu)))
+		return -ENODEV;
+
+	kw_freqs[KW_CPUFREQ_HIGH].frequency = mvCpuPclkGet()/1000;
+	/* CPU low frequency is the DDR frequency. */
+	kw_freqs[KW_CPUFREQ_LOW].frequency  = mvBoardSysClkGet()/1000;
+
+	printk(KERN_DEBUG
+			"cpufreq: High frequency: %uKHz - Low frequency: %uKHz\n",
+			kw_freqs[KW_CPUFREQ_HIGH].frequency,
+			kw_freqs[KW_CPUFREQ_LOW].frequency);
+
+	policy->cpuinfo.transition_latency = 5000;
+	policy->cur = kw_cpufreq_get(0);
+	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+	cpufreq_frequency_table_get_attr(kw_freqs, policy->cpu);
+
+	return cpufreq_frequency_table_cpuinfo(policy, kw_freqs);
+}
+
+
+static int kw_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	return 0;
+}
+
+static struct freq_attr *kw_freq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+
+static struct cpufreq_driver kw_freq_driver = {
+	.owner          = THIS_MODULE,
+	.name           = "kw_cpufreq",
+	.init           = kw_cpufreq_cpu_init,
+	.verify         = kw_cpufreq_verify,
+	.exit		= kw_cpufreq_cpu_exit,
+	.target         = kw_cpufreq_target,
+	.get            = kw_cpufreq_get,
+	.attr           = kw_freq_attr,
+};
+
+#ifdef CONFIG_MV_PMU_PROC
+static int mv_cpu_freq_write(struct file *file, const char *buffer,
+		unsigned long count, void *data)
+{
+	struct cpufreq_policy policy;
+
+	/* Reading / Writing from system controller internal registers */
+	if (!strncmp (buffer, "enable", strlen("enable"))) {
+		cpufreq_register_driver(&kw_freq_driver);
+	} else if (!strncmp (buffer, "disable", strlen("disable"))) {
+		cpufreq_get_policy(&policy, smp_processor_id());
+		kw_cpufreq_target(&policy, kw_freqs[KW_CPUFREQ_HIGH].frequency, CPUFREQ_RELATION_H);
+		cpufreq_unregister_driver(&kw_freq_driver);
+	} else if (!strncmp (buffer, "fast", strlen("fast"))) {
+		mvCtrlPwrSaveOff();
+	} else if (!strncmp (buffer, "slow", strlen("slow"))) {
+		mvCtrlPwrSaveOn();
+	}
+
+	return count;
+}
+
+
+static int mv_cpu_freq_read(char *buffer, char **buffer_location, off_t offset,
+		int buffer_length, int *zero, void *ptr)
+{
+	if (offset > 0)
+		return 0;
+	return sprintf(buffer, "enable - Enable CPU-Freq framework.\n"
+				"disable - Disable CPU-Freq framework.\n"
+				"fast - Manually set the CPU to fast frequency mode (in Disable mode).\n"
+				"slow - Manually set the CPU to slow frequency mode (in Disable mode).\n");
+}
+
+#endif /* CONFIG_MV_PMU_PROC */
+
+static int __init kw_cpufreq_init(void)
+{
+#ifdef CONFIG_MV_PMU_PROC
+	struct proc_dir_entry *cpu_freq_proc;
+#endif /* CONFIG_MV_PMU_PROC */
+
+	if (MV_6601_DEV_ID == mvCtrlModelGet())
+		return 0;
+
+	printk(KERN_INFO "cpufreq: Init kirkwood cpufreq driver\n");
+
+#ifdef CONFIG_MV_PMU_PROC
+	/* Create proc entry. */
+	cpu_freq_proc = create_proc_entry("cpu_freq", 0666, mv_pm_proc_entry);
+	cpu_freq_proc->read_proc = mv_cpu_freq_read;
+	cpu_freq_proc->write_proc = mv_cpu_freq_write;
+	cpu_freq_proc->nlink = 1;
+#endif /* CONFIG_MV_PMU_PROC */
+
+	return cpufreq_register_driver(&kw_freq_driver);
+}
+
+static void __exit kw_cpufreq_exit(void)
+{
+	cpufreq_unregister_driver(&kw_freq_driver);
+}
+
+
+MODULE_AUTHOR("Marvell Semiconductors ltd.");
+MODULE_DESCRIPTION("CPU frequency scaling for Kirkwood SoC");
+MODULE_LICENSE("GPL");
+module_init(kw_cpufreq_init);
+module_exit(kw_cpufreq_exit);
+
diff --git a/arch/arm/mach-feroceon-kw2/cpuidle.c b/arch/arm/mach-feroceon-kw2/cpuidle.c
new file mode 100755
index 0000000..6a49111
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/cpuidle.c
@@ -0,0 +1,281 @@
+/*
+ * arch/arm/mach-feroceon-kw/cpuidle.c
+ *
+ * CPU idle Marvell Kirkwood SoCs
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The cpu idle uses wait-for-interrupt and DDR self refresh in order
+ * to implement two idle states -
+ * #1 wait-for-interrupt
+ * #2 wait-for-interrupt and DDR self refresh
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+#include <asm/proc-fns.h>
+#include <linux/proc_fs.h>
+#include <config/mvSysHwConfig.h>
+#include "mvCommon.h"
+#include "mvOs.h"
+
+#define CONFIG_CPUFREQ_TOGGLE_ON_DEEPIDLE
+
+#ifdef CONFIG_CPUFREQ_TOGGLE_ON_DEEPIDLE
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#endif
+
+#define KIRKWOOD_MAX_STATES	2
+
+extern void mv_kw2_cpu_idle_enter(void);
+
+#ifdef CONFIG_MV_PMU_PROC
+extern struct proc_dir_entry *mv_pm_proc_entry;
+struct proc_dir_entry *cpu_idle_proc;
+#endif /* CONFIG_MV_PMU_PROC */
+
+static struct cpuidle_device *kirkwood_cpu_idle_device;
+
+static struct cpuidle_driver kirkwood_idle_driver = {
+	.name =         "kirkwood_idle",
+	.owner =        THIS_MODULE,
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
+
+static int device_registered;
+int support_dram_self_refresh = 0;
+
+/* Actual code that puts the SoC in different idle states */
+static int kirkwood_enter_idle(struct cpuidle_device *dev,
+			       struct cpuidle_state *state)
+{
+	struct timeval before, after;
+	int idle_time;
+	MV_BOOL pwr_save_on;
+
+#ifdef CONFIG_JTAG_DEBUG
+	local_irq_enable(); 
+	return 0;
+#endif
+
+#ifdef CONFIG_CPUFREQ_TOGGLE_ON_DEEPIDLE
+	/* Set CPU to fast frequency */
+	pwr_save_on = mvCtrlIsPwrSaveOn();
+	mvCtrlPwrSaveOff();
+#endif /* CONFIG_CPUFREQ_TOGGLE_ON_DEEPIDLE */
+
+	local_irq_disable();
+	do_gettimeofday(&before);
+	if (state == &dev->states[0]) {
+		/* Wait for interrupt state */
+		cpu_do_idle();
+	} else if (state == &dev->states[1]) {
+#ifdef CONFIG_MV_PM_IDLE_WFI_SR
+		/*
+		 * Following write will put DDR in self refresh.
+		 * Note that we have 256 cycles before DDR puts it
+		 * self in self-refresh, so the wait-for-interrupt
+		 * call afterwards won't get the DDR from self refresh
+		 * mode.
+		 */
+		writel(0x7, DDR_OPERATION_BASE);
+		cpu_do_idle();
+#endif
+#ifdef CONFIG_MV_PM_IDLE_DEEPIDLE_SR
+		/*
+		 * Following write will put DDR in self refresh.
+		 * Note that we have 256 cycles before DDR puts it
+		 * self in self-refresh, so the wait-for-interrupt
+		 * call afterwards won't get the DDR from self refresh
+		 * mode.
+		 */
+		mv_kw2_cpu_idle_enter();
+#endif
+	}
+	do_gettimeofday(&after);
+	local_irq_enable();
+
+#ifdef CONFIG_CPUFREQ_TOGGLE_ON_DEEPIDLE
+	/* Set CPU to fast frequency */
+	if (pwr_save_on == MV_TRUE)
+		mvCtrlPwrSaveOn();
+#endif /* CONFIG_CPUFREQ_TOGGLE_ON_DEEPIDLE */
+
+	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+			(after.tv_usec - before.tv_usec);
+	return idle_time;
+}
+
+#ifdef CONFIG_MV_PMU_PROC
+static int mv_cpu_idle_write(struct file *file, const char *buffer,
+		unsigned long count, void *data)
+{
+	MV_U32	regs[4];
+
+	/* Reading / Writing from system controller internal registers */
+	if (!strncmp (buffer, "enable", strlen("enable"))) {
+		if(device_registered == 0) {
+			device_registered = 1;
+			if (cpuidle_register_device(kirkwood_cpu_idle_device)) {
+				printk(KERN_ERR "mv_cpu_idle_write: Failed registering\n");
+				return -EIO;
+			}
+		}
+		cpuidle_enable_device(kirkwood_cpu_idle_device);
+	} else if (!strncmp (buffer, "disable", strlen("disable"))) {
+		cpuidle_disable_device(kirkwood_cpu_idle_device);
+	} else if (!strncmp (buffer, "test", strlen("test"))) {
+
+		buffer += strlen("test ");
+		/* Store Interrupt mask registers. */
+		regs[0] = MV_REG_READ(MV_IRQ_MASK_LOW_REG);
+		regs[1] = MV_REG_READ(MV_IRQ_MASK_HIGH_REG);
+		regs[2] = MV_REG_READ(MV_IRQ_MASK_ERROR_REG);
+
+		/* Disable all interrupts . */
+		MV_REG_WRITE(MV_IRQ_MASK_LOW_REG, 0x0);
+		MV_REG_WRITE(MV_IRQ_MASK_HIGH_REG, 0x0);
+		MV_REG_WRITE(MV_IRQ_MASK_ERROR_REG, 0x0);
+
+		/* Enable only the UART interrupt. */
+		MV_REG_BIT_SET(MV_IRQ_MASK_HIGH_REG, 1 << (UART_IRQ_NUM(0) - 32));
+		
+		if (!strncmp (buffer, "idle", strlen("idle"))) {
+			printk(KERN_INFO "Press any key to leave deep idle:");
+			mv_kw2_cpu_idle_enter();
+		} else if (!strncmp (buffer, "wfi", strlen("wfi"))) {
+			printk(KERN_INFO "Press any key to leave WFI:");
+			cpu_do_idle();
+		}
+
+		/* Restore Interrupt mask registers. */
+		MV_REG_WRITE(MV_IRQ_MASK_LOW_REG, regs[0]);
+		MV_REG_WRITE(MV_IRQ_MASK_HIGH_REG, regs[1]);
+		MV_REG_WRITE(MV_IRQ_MASK_ERROR_REG, regs[2]);
+	} else if (!strncmp (buffer, "sr_enable", strlen("sr_enable"))) {
+		local_irq_disable();
+		support_dram_self_refresh = 1;
+		local_irq_enable();
+	} else if (!strncmp (buffer, "sr_disable", strlen("sr_disable"))) {
+		local_irq_disable();
+		support_dram_self_refresh = 0;
+		local_irq_enable();
+	}
+
+
+	return count;
+}
+
+
+static int mv_cpu_idle_read(char *buffer, char **buffer_location, off_t offset,
+		int buffer_length, int *zero, void *ptr)
+{
+	if (offset > 0)
+		return 0;
+	return sprintf(buffer, "enable - Enable CPU Idle framework.\n"
+				"disable - Disable CPU idle framework.\n"
+				"test (idle / wfi) - Manually enter CPU Idle state, exit by key stroke (DEBUG ONLY).\n"
+				"sr_enable / sr_disable - Enable / Disable DRAM Self-Refresh when entering deel-idle.\n");
+	
+}
+
+#endif /* CONFIG_MV_PMU_PROC */
+
+/* Initialize CPU idle by registering the idle states */
+static int kw_cpuidle_probe(struct platform_device *pdev)
+{
+	struct cpuidle_device *device;
+
+	cpuidle_register_driver(&kirkwood_idle_driver);
+
+	device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
+	device->state_count = KIRKWOOD_MAX_STATES;
+
+	/* Wait for interrupt state */
+	device->states[0].enter = kirkwood_enter_idle;
+	device->states[0].exit_latency = 1;
+	device->states[0].target_residency = 100;
+	device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(device->states[0].name, "WFI");
+	strcpy(device->states[0].desc, "Wait for interrupt");
+
+#ifdef CONFIG_MV_PM_IDLE_WFI_SR
+	/* Wait for interrupt and DDR self refresh state */
+	device->states[1].enter = kirkwood_enter_idle;
+	device->states[1].exit_latency = 10;
+	device->states[1].target_residency = 1000;
+	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(device->states[1].name, "DDR SR");
+	strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+#endif
+
+#ifdef CONFIG_MV_PM_IDLE_DEEPIDLE_SR
+	/* CPU Deep Idle state */
+	device->states[1].enter = kirkwood_enter_idle;
+	device->states[1].exit_latency = 10;
+	device->states[1].target_residency = 5000;
+	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(device->states[1].name, "DEEP IDLE");
+	strcpy(device->states[1].desc, "CPU Deep Idle");
+#endif
+
+#if 0
+	if (cpuidle_register_device(device)) {
+		printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
+		return -EIO;
+	}
+#endif
+	kirkwood_cpu_idle_device = device;
+
+#ifdef CONFIG_MV_PMU_PROC
+	/* Create proc entry. */
+	cpu_idle_proc = create_proc_entry("cpu_idle", 0666, mv_pm_proc_entry);
+	cpu_idle_proc->read_proc = mv_cpu_idle_read;
+	cpu_idle_proc->write_proc = mv_cpu_idle_write;
+	cpu_idle_proc->nlink = 1;
+#endif /* CONFIG_MV_PMU_PROC */
+
+	return 0;
+}
+
+static int kw_cpuidle_remove(struct platform_device *pdev)
+{
+#ifdef CONFIG_MV_PMU_PROC
+	remove_proc_entry("cpu_idle", cpu_idle_proc);
+#endif
+	cpuidle_unregister_device(kirkwood_cpu_idle_device);
+	return 0;
+}
+
+struct platform_driver kw_cpuidle_driver = {
+	.probe		= kw_cpuidle_probe,
+	.remove		= kw_cpuidle_remove,
+	.driver		= {
+		.name	= "kw_cpuidle",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init kw_cpuidle_drv_init(void)
+{
+	if (MV_6601_DEV_ID == mvCtrlModelGet())
+		return 0;
+
+	device_registered = 0;
+	return platform_driver_register(&kw_cpuidle_driver);
+
+}
+
+static void __exit kw_cpuidle_drv_cleanup(void)
+{
+	platform_driver_unregister(&kw_cpuidle_driver);
+}
+
+module_init(kw_cpuidle_drv_init);
+module_exit(kw_cpuidle_drv_cleanup);
diff --git a/arch/arm/mach-feroceon-kw2/export.c b/arch/arm/mach-feroceon-kw2/export.c
new file mode 100755
index 0000000..a8aed97
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/export.c
@@ -0,0 +1,417 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "mvDebug.h"
+#include "mvSysHwConfig.h"
+#include "pex/mvPexRegs.h"
+#include "cntmr/mvCntmr.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "pnc/mvPnc.h"
+#include "mvOs.h"
+
+#include "mv_neta/net_dev/mv_netdev.h"
+
+/*************************************************************************************************************
+ * Environment
+ *************************************************************************************************************/
+extern u32 mvTclk;
+extern u32 mvSysclk;
+extern u8  mvMacAddr[CONFIG_MV_ETH_PORTS_NUM][6];
+
+#include "mv_neta/net_dev/mv_netdev.h"
+
+EXPORT_SYMBOL(pnc_mh_omci);
+EXPORT_SYMBOL(pnc_eoam);
+EXPORT_SYMBOL(pnc_default_init);
+EXPORT_SYMBOL(pnc_def_entry_init);
+EXPORT_SYMBOL(mv_eth_dev_name_by_portid);
+EXPORT_SYMBOL(mv_eth_port_ifname_print);
+EXPORT_SYMBOL(mv_eth_pon_ifname_dump);
+EXPORT_SYMBOL(mvNetaMaxCheck);
+EXPORT_SYMBOL(mv_eth_rx_special_proc_func);
+EXPORT_SYMBOL(mvNetaTxpCheck);
+EXPORT_SYMBOL(mv_eth_port_by_id);
+EXPORT_SYMBOL(mv_eth_tx_special_check_func);
+
+EXPORT_SYMBOL(mv_early_printk);
+EXPORT_SYMBOL(mvCtrlPwrClckGet);
+EXPORT_SYMBOL(mvCtrlModelRevGet);
+EXPORT_SYMBOL(mvTclk);
+EXPORT_SYMBOL(mvSysclk);
+EXPORT_SYMBOL(mvCtrlModelGet);
+EXPORT_SYMBOL(mvCtrlRevGet);
+EXPORT_SYMBOL(mvOsIoUncachedMalloc);
+EXPORT_SYMBOL(mvOsIoUncachedFree);
+EXPORT_SYMBOL(mvOsIoCachedMalloc);
+EXPORT_SYMBOL(mvOsIoCachedFree);
+EXPORT_SYMBOL(mvDebugMemDump);
+EXPORT_SYMBOL(mvHexToBin);
+EXPORT_SYMBOL(mvBinToHex);
+EXPORT_SYMBOL(mvSizePrint);
+EXPORT_SYMBOL(mvDebugPrintMacAddr);
+EXPORT_SYMBOL(mvCtrlEthMaxPortGet);
+EXPORT_SYMBOL(mvCtrlTargetNameGet);
+EXPORT_SYMBOL(mvBoardIdGet);
+EXPORT_SYMBOL(mvBoardPhyAddrGet);
+EXPORT_SYMBOL(mvCpuIfTargetWinGet);
+EXPORT_SYMBOL(mvMacStrToHex);
+EXPORT_SYMBOL(mvBoardTclkGet);
+EXPORT_SYMBOL(mvBoardMacSpeedGet);
+#ifdef CONFIG_MV_INCLUDE_TDM
+EXPORT_SYMBOL(mvCtrlTdmClkCtrlConfig);
+#if defined(MV_TDM_USE_DCO)
+EXPORT_SYMBOL(mvCtrlTdmClkCtrlGet);
+EXPORT_SYMBOL(mvCtrlTdmClkCtrlSet);
+#endif
+#endif
+EXPORT_SYMBOL(mvCtrlTdmUnitIrqGet);
+EXPORT_SYMBOL(mvWinOverlapTest);
+EXPORT_SYMBOL(mvCtrlTdmUnitTypeGet);
+EXPORT_SYMBOL(mvCtrlAddrWinMapBuild);
+EXPORT_SYMBOL(mvBoardTdmSpiModeGet);
+EXPORT_SYMBOL(mvBoardTdmSpiCsGet);
+EXPORT_SYMBOL(mvBoardTdmDevicesCountGet);
+EXPORT_SYMBOL(mvMacAddr);
+#ifdef CONFIG_MV_INCLUDE_SPI
+#include "spi/mvSpiCmnd.h"
+EXPORT_SYMBOL(mvSpiWriteThenWrite);
+EXPORT_SYMBOL(mvSpiWriteThenRead);
+#include "spi/mvSpi.h"
+EXPORT_SYMBOL(mvSpiParamsSet);
+#endif
+#include "gpp/mvGpp.h"
+EXPORT_SYMBOL(mvGppValueSet);
+/*************************************************************************************************************
+ * Audio
+ *************************************************************************************************************/
+#ifdef CONFIG_MV_INCLUDE_AUDIO
+#include "audio/mvAudio.h"
+#include "mvSysAudioApi.h"
+EXPORT_SYMBOL(mvSPDIFRecordTclockSet);
+EXPORT_SYMBOL(mvSPDIFPlaybackCtrlSet);
+EXPORT_SYMBOL(mvI2SPlaybackCtrlSet);
+EXPORT_SYMBOL(mvAudioPlaybackControlSet);
+EXPORT_SYMBOL(mvAudioDCOCtrlSet);
+EXPORT_SYMBOL(mvI2SRecordCntrlSet);
+EXPORT_SYMBOL(mvAudioRecordControlSet);
+EXPORT_SYMBOL(mvSysAudioInit);
+EXPORT_SYMBOL(mvBoardA2DTwsiAddrGet);
+EXPORT_SYMBOL(mvBoardA2DTwsiAddrTypeGet);
+#endif
+
+/*************************************************************************************************************
+ * USB
+ *************************************************************************************************************/
+#ifdef CONFIG_MV_INCLUDE_USB
+extern u32 mvIsUsbHost;
+
+#include "usb/mvUsb.h"
+EXPORT_SYMBOL(mvIsUsbHost);
+EXPORT_SYMBOL(mvCtrlUsbMaxGet);
+EXPORT_SYMBOL(mvUsbGetCapRegAddr);
+#ifdef MV_USB_VOLTAGE_FIX
+EXPORT_SYMBOL(mvUsbGppInit);
+EXPORT_SYMBOL(mvUsbBackVoltageUpdate);
+#endif
+#endif /* CONFIG_MV_INCLUDE_USB */
+
+/*************************************************************************************************************
+ * CESA
+ *************************************************************************************************************/
+#ifdef CONFIG_MV_INCLUDE_CESA
+#include "mvSysCesaApi.h"
+#include "cesa/mvCesa.h"
+#include "cesa/mvMD5.h"
+#include "cesa/mvSHA1.h"
+extern unsigned char *mv_sram_usage_get(int *sram_size_ptr);
+
+EXPORT_SYMBOL(mvSysCesaInit);
+EXPORT_SYMBOL(mvCesaSessionOpen);
+EXPORT_SYMBOL(mvCesaSessionClose);
+EXPORT_SYMBOL(mvCesaAction);
+EXPORT_SYMBOL(mvCesaReadyGet);
+EXPORT_SYMBOL(mvCesaCopyFromMbuf);
+EXPORT_SYMBOL(mvCesaCopyToMbuf);
+EXPORT_SYMBOL(mvCesaMbufCopy);
+EXPORT_SYMBOL(mvCesaCryptoIvSet);
+EXPORT_SYMBOL(mvMD5);
+EXPORT_SYMBOL(mvSHA1);
+
+EXPORT_SYMBOL(mvCesaDebugQueue);
+EXPORT_SYMBOL(mvCesaDebugSram);
+EXPORT_SYMBOL(mvCesaDebugSAD);
+EXPORT_SYMBOL(mvCesaDebugStatus);
+EXPORT_SYMBOL(mvCesaDebugMbuf);
+EXPORT_SYMBOL(mvCesaDebugSA);
+EXPORT_SYMBOL(mv_sram_usage_get);
+
+extern u32 mv_crypto_base_get(void);
+EXPORT_SYMBOL(mv_crypto_base_get);
+EXPORT_SYMBOL(cesaReqResources);
+EXPORT_SYMBOL(mvCesaFinish);
+
+#endif
+
+/*************************************************************************************************************
+ * Flashes
+ *************************************************************************************************************/
+#if defined (CONFIG_MV_INCLUDE_SPI)
+#include <sflash/mvSFlash.h>
+#include <sflash/mvSFlashSpec.h>
+EXPORT_SYMBOL(mvSFlashInit);
+EXPORT_SYMBOL(mvSFlashSectorErase);
+EXPORT_SYMBOL(mvSFlashChipErase);
+EXPORT_SYMBOL(mvSFlashBlockRd);
+EXPORT_SYMBOL(mvSFlashBlockWr);
+EXPORT_SYMBOL(mvSFlashIdGet);
+EXPORT_SYMBOL(mvSFlashWpRegionSet);
+EXPORT_SYMBOL(mvSFlashWpRegionGet);
+EXPORT_SYMBOL(mvSFlashStatRegLock);
+EXPORT_SYMBOL(mvSFlashSizeGet);
+EXPORT_SYMBOL(mvSFlashPowerSaveEnter);
+EXPORT_SYMBOL(mvSFlashPowerSaveExit);
+EXPORT_SYMBOL(mvSFlashModelGet);
+#endif
+
+
+/*************************************************************************************************************
+ * SATA
+ *************************************************************************************************************/
+#ifdef CONFIG_MV_INCLUDE_INTEG_SATA
+#include <sata/CoreDriver/mvSata.h>
+EXPORT_SYMBOL(mvSataWinInit);
+#endif
+
+/*************************************************************************************************************
+ * DMA/XOR
+ *************************************************************************************************************/
+#if defined(CONFIG_MV_XOR_MEMCOPY) || defined(CONFIG_MV_IDMA_MEMCOPY)
+EXPORT_SYMBOL(asm_memcpy);
+#endif
+
+#ifdef CONFIG_MV_SP_I_FTCH_DB_INV
+EXPORT_SYMBOL(mv_l2_inv_range);
+#endif
+
+/*************************************************************************************************************
+ * PON
+ *************************************************************************************************************/
+#ifdef CONFIG_MV_PON
+EXPORT_SYMBOL(mv_pon_link_state_register);
+EXPORT_SYMBOL(mvGppBlinkEn);
+EXPORT_SYMBOL(mvGppTypeSet);
+EXPORT_SYMBOL(mvBoarGpioPinNumGet);
+#endif /* CONFIG_MV_PON */
+
+/*************************************************************************************************************
+ * Marvell TRACE
+ *************************************************************************************************************/
+#ifdef CONFIG_MV_DBG_TRACE
+#include "dbg-trace.h"
+EXPORT_SYMBOL(TRC_INIT);
+EXPORT_SYMBOL(TRC_REC);
+EXPORT_SYMBOL(TRC_OUTPUT);
+EXPORT_SYMBOL(TRC_START);
+EXPORT_SYMBOL(TRC_RELEASE);
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_MODULE
+#ifdef CONFIG_MV_ETH_BM
+#include "bm/mvBm.h"
+EXPORT_SYMBOL(mvBmVirtBase);
+#endif
+#include "mvList.h"
+EXPORT_SYMBOL(mvListCreate);
+EXPORT_SYMBOL(mvListDestroy);
+#endif
+
+
+/*************************************************************************************************************
+ * TPM
+ *************************************************************************************************************/
+#ifdef CONFIG_MV_INCLUDE_TPM
+#include "net_dev/mv_netdev.h"
+
+#include "pnc/mvTcam.h"
+#include "pmt/mvPmt.h"
+#include "gbe/mvNeta.h"
+#include "msApiTypes.h"
+#include "msApiDefs.h"
+#include "mv_switch.h"
+#include "mv_switch_wrap.h"
+#include "boardEnv/mvBoardEnvLib.h"
+
+
+EXPORT_SYMBOL(tcam_hw_inv);
+EXPORT_SYMBOL(tcam_hw_read);
+EXPORT_SYMBOL(tcam_hw_write);
+EXPORT_SYMBOL(tcam_sw_set_lookup);
+EXPORT_SYMBOL(tcam_sw_set_port);
+EXPORT_SYMBOL(tcam_sw_set_byte);
+EXPORT_SYMBOL(tcam_sw_set_ainfo);
+EXPORT_SYMBOL(tcam_sw_set_mask);
+EXPORT_SYMBOL(tcam_sw_clear);
+EXPORT_SYMBOL(tcam_hw_init);
+
+EXPORT_SYMBOL(sram_sw_set_lookup_done);
+EXPORT_SYMBOL(sram_sw_set_next_lookup_shift);
+EXPORT_SYMBOL(sram_sw_set_next_lookup);
+
+#ifdef CONFIG_MV_TPM_Z1_VER
+EXPORT_SYMBOL(sram_sw_set_flowid_hi);
+EXPORT_SYMBOL(sram_sw_set_flowid_lo);
+#elif CONFIG_MV_TPM_Z2_VER
+EXPORT_SYMBOL(sram_sw_set_flowid);
+#endif
+EXPORT_SYMBOL(sram_sw_set_rxq);
+EXPORT_SYMBOL(sram_sw_set_rinfo);
+EXPORT_SYMBOL(sram_sw_set_ainfo);
+EXPORT_SYMBOL(sram_sw_set_shift_update);
+
+EXPORT_SYMBOL(mvNetaTxMhRegSet);
+EXPORT_SYMBOL(mvNetaPmtInit);
+EXPORT_SYMBOL(mvNetaPmtClear);
+EXPORT_SYMBOL(mvNetaPmtRead);
+EXPORT_SYMBOL(mvNetaPmtWrite);
+EXPORT_SYMBOL(mvNetaTxpRateSet);
+EXPORT_SYMBOL(mvNetaTxqRateSet);
+EXPORT_SYMBOL(mvNetaTxqWrrPrioSet);
+EXPORT_SYMBOL(mvNetaTxqFixPrioSet);
+EXPORT_SYMBOL(mvNetaHwfMhSelSet);
+EXPORT_SYMBOL(mvNetaHwfMhSrcSet);
+EXPORT_SYMBOL(mv_eth_set_mtu);
+EXPORT_SYMBOL(mv_eth_get_mtu);
+#ifdef CONFIG_MV_TPM_Z2_VER
+EXPORT_SYMBOL(mvNetaTxpBurstSet);
+EXPORT_SYMBOL(mvNetaTxqBurstSet);
+#endif
+EXPORT_SYMBOL(mvNetaHwfTxqEnable);
+EXPORT_SYMBOL(mvNetaVlanEtySet);
+
+EXPORT_SYMBOL(mv_eth_ctrl_port_buf_num_set);
+EXPORT_SYMBOL(mv_eth_ctrl_txq_hwf_own);
+EXPORT_SYMBOL(mv_eth_ctrl_txq_size_set);
+EXPORT_SYMBOL(mv_eth_ctrl_rxq_size_set);
+EXPORT_SYMBOL(mv_eth_ctrl_port_started_get);
+EXPORT_SYMBOL(mv_eth_ctrl_flag);
+EXPORT_SYMBOL(mv_eth_ctrl_tx_mh);
+EXPORT_SYMBOL(mv_switch_reg_write);
+EXPORT_SYMBOL(mv_switch_reg_read);
+
+EXPORT_SYMBOL(mv_switch_mac_addr_set);
+EXPORT_SYMBOL(mv_switch_add_static_mac);
+EXPORT_SYMBOL(mv_switch_del_static_mac);
+EXPORT_SYMBOL(mv_switch_set_port_max_macs);
+EXPORT_SYMBOL(mv_switch_get_port_max_macs);
+EXPORT_SYMBOL(mv_switch_clear_dynamic_mac);
+EXPORT_SYMBOL(mv_switch_set_mirror);
+EXPORT_SYMBOL(mv_switch_get_mirror);
+EXPORT_SYMBOL(mv_switch_set_mtu);
+EXPORT_SYMBOL(mv_switch_get_mtu);
+//EXPORT_SYMBOL(mv_switch_set_port_flooding);
+//EXPORT_SYMBOL(mv_switch_get_port_flooding);
+EXPORT_SYMBOL(mv_switch_set_port_tagged);
+EXPORT_SYMBOL(mv_switch_get_port_tagged);
+EXPORT_SYMBOL(mv_switch_set_port_untagged);
+EXPORT_SYMBOL(mv_switch_get_port_untagged);
+EXPORT_SYMBOL(mv_switch_set_port_def_vlan);
+EXPORT_SYMBOL(mv_switch_get_port_def_vlan);
+EXPORT_SYMBOL(mv_switch_set_port_def_pri);
+EXPORT_SYMBOL(mv_switch_get_port_def_pri);
+EXPORT_SYMBOL(mv_switch_port_add_vid);
+EXPORT_SYMBOL(mv_switch_prv_port_add_vid);
+EXPORT_SYMBOL(mv_switch_del_vid_per_port);
+EXPORT_SYMBOL(mv_switch_prv_del_vid_per_port);
+EXPORT_SYMBOL(mv_switch_set_port_vid_egress_mode);
+EXPORT_SYMBOL(mv_switch_prv_set_secure_mode);
+EXPORT_SYMBOL(mv_switch_prv_set_fallback_mode);
+EXPORT_SYMBOL(mv_switch_set_vid_filter_per_port);
+EXPORT_SYMBOL(mv_switch_get_vid_filter_per_port);
+EXPORT_SYMBOL(mv_switch_set_port_sched_mode);
+EXPORT_SYMBOL(mv_switch_set_uni_q_weight);
+EXPORT_SYMBOL(mv_switch_set_uni_ingr_police_rate);
+EXPORT_SYMBOL(mv_switch_get_uni_ingr_police_rate);
+EXPORT_SYMBOL(mv_switch_set_uni_tc_ingr_police_rate);
+EXPORT_SYMBOL(mv_switch_get_uni_tc_ingr_police_rate);
+EXPORT_SYMBOL(mv_switch_set_uni_egr_rate_limit);
+EXPORT_SYMBOL(mv_switch_get_uni_egr_rate_limit);
+EXPORT_SYMBOL(mv_switch_set_age_time);
+EXPORT_SYMBOL(mv_switch_get_age_time);
+EXPORT_SYMBOL(mv_switch_set_mac_learn);
+EXPORT_SYMBOL(mv_switch_get_mac_learn);
+EXPORT_SYMBOL(mv_switch_set_port_vlan_ports);
+EXPORT_SYMBOL(mv_switch_get_port_vlan_ports);
+EXPORT_SYMBOL(mv_switch_set_ingress_limit_mode);
+EXPORT_SYMBOL(mv_switch_get_ingress_limit_mode);
+EXPORT_SYMBOL(mv_switch_get_port_los_alarm);
+EXPORT_SYMBOL(mv_switch_set_priority_selection);
+EXPORT_SYMBOL(mv_switch_get_priority_selection);
+EXPORT_SYMBOL(mv_switch_set_tag_pri_mapping);
+EXPORT_SYMBOL(mv_switch_get_tag_pri_mapping);
+EXPORT_SYMBOL(mv_switch_set_ip_pri_mapping);
+EXPORT_SYMBOL(mv_switch_get_ip_pri_mapping);
+EXPORT_SYMBOL(mv_switch_set_unknown_unicast_flood);
+EXPORT_SYMBOL(mv_switch_get_unknown_unicast_flood);
+EXPORT_SYMBOL(mv_switch_set_unknown_multicast_flood);
+EXPORT_SYMBOL(mv_switch_get_unknown_multicast_flood);
+EXPORT_SYMBOL(mv_switch_set_broadcast_flood);
+EXPORT_SYMBOL(mv_switch_get_broadcast_flood);
+EXPORT_SYMBOL(mv_switch_set_marvell_header_mode);
+EXPORT_SYMBOL(mv_switch_get_marvell_header_mode);
+EXPORT_SYMBOL(mv_switch_set_port_autoneg_mode);
+EXPORT_SYMBOL(mv_switch_get_port_autoneg_mode);
+EXPORT_SYMBOL(mv_switch_restart_port_autoneg);
+EXPORT_SYMBOL(mv_switch_set_phy_port_state);
+EXPORT_SYMBOL(mv_switch_get_phy_port_state);
+EXPORT_SYMBOL(mv_switch_get_port_link_status);
+EXPORT_SYMBOL(mv_switch_get_port_duplex_status);
+EXPORT_SYMBOL(mv_switch_get_port_speed_mode);
+EXPORT_SYMBOL(mv_switch_set_port_pause);
+EXPORT_SYMBOL(mv_switch_get_port_pause);
+EXPORT_SYMBOL(mv_switch_get_port_pause_state);
+EXPORT_SYMBOL(mv_switch_set_port_loopback);
+EXPORT_SYMBOL(mv_switch_get_port_loopback);
+EXPORT_SYMBOL(mv_switch_set_port_line_loopback);
+EXPORT_SYMBOL(mv_switch_get_port_line_loopback);
+EXPORT_SYMBOL(mv_switch_set_port_duplex_mode);
+EXPORT_SYMBOL(mv_switch_get_port_duplex_mode);
+EXPORT_SYMBOL(mv_switch_set_port_speed);
+EXPORT_SYMBOL(mv_switch_get_port_speed);
+/*EXPORT_SYMBOL(mv_switch_set_port_state);
+EXPORT_SYMBOL(mv_switch_get_port_state);*/
+EXPORT_SYMBOL(mv_switch_set_global_reg);
+EXPORT_SYMBOL(mv_switch_get_global_reg);
+EXPORT_SYMBOL(mv_switch_set_port_reg);
+EXPORT_SYMBOL(mv_switch_get_port_reg);
+EXPORT_SYMBOL(mv_switch_port_print_vid);
+EXPORT_SYMBOL(mv_switch_print_fdb);
+EXPORT_SYMBOL(mv_switch_drv_init);
+EXPORT_SYMBOL(mv_switch_clear_port_counters);
+EXPORT_SYMBOL(mv_switch_print_port_counters);
+//EXPORT_SYMBOL(mv_switch_get_port_counters_sh);
+EXPORT_SYMBOL(mv_switch_get_port_counters);
+EXPORT_SYMBOL(mv_switch_get_port_drop_counters);
+EXPORT_SYMBOL(mv_switch_clean_port_counters);
+EXPORT_SYMBOL(mvBoardMppModuleTypePrint);
+EXPORT_SYMBOL(mvBoardIsInternalSwitchConnected);
+EXPORT_SYMBOL(mvBoardEthComplexConfigGet);
+#endif /* CONFIG_MV_INCLUDE_TPM */
+
diff --git a/arch/arm/mach-feroceon-kw2/fiq.c b/arch/arm/mach-feroceon-kw2/fiq.c
new file mode 100755
index 0000000..1349168
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/fiq.c
@@ -0,0 +1,194 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "gpp/mvGpp.h"
+#include "mvOs.h"
+
+/*
+ * Note: FIQ mask registers are IRQ mask registers + 4 bytes.
+ */
+
+unsigned int fiq_int_type[NR_IRQS];
+
+void mv_mask_fiq(unsigned int irq)
+{
+	if (irq < 32) {
+		MV_REG_BIT_RESET(MV_FIQ_MASK_LOW_REG, (1 << irq) );
+	} else if(irq < 64) {		/* (irq > 32 && irq < 64) */
+		MV_REG_BIT_RESET(MV_FIQ_MASK_HIGH_REG, (1 << (irq - 32)) );
+	} else if(irq < 96) {		/* (irq > 64 && irq < 96) */
+		MV_REG_BIT_RESET(MV_FIQ_MASK_ERROR_REG, (1 << (irq - 64)) );
+	} else if(irq < NR_IRQS) {	/* (irq > 96 && irq < NR_IRQS) */
+		MV_U32 bitmask = 1 << (irq & 0x1F);
+		MV_U32 reg = (irq - IRQ_GPP_START) >> 5;
+		MV_REG_BIT_RESET(MV_GPP_IRQ_MASK_REG(reg), bitmask);
+	} else
+		printk("mv_mask_fiq: ERR, irq-%u out of scope\n",irq);
+}
+
+void mv_unmask_fiq(unsigned int irq)
+{
+	if (irq < 32) {
+		MV_REG_BIT_SET(MV_FIQ_MASK_LOW_REG, (1 << irq) );
+	} else if(irq < 64) {		/* (irq > 32 && irq < 64) */
+		MV_REG_BIT_SET(MV_FIQ_MASK_HIGH_REG, (1 << (irq - 32)) );
+	} else if(irq < 96) {		/* (irq > 64 && irq < 96) */
+		MV_REG_BIT_SET(MV_FIQ_MASK_ERROR_REG, (1 << (irq - 64)) );
+	} else if(irq < NR_IRQS) {
+		MV_U32 bitmask = 1 << (irq & 0x1F);
+		MV_U32 reg = (irq - IRQ_GPP_START) >> 5;
+		MV_REG_BIT_SET(MV_GPP_IRQ_MASK_REG(reg), bitmask);
+		if (fiq_int_type[irq] == GPP_IRQ_TYPE_CHANGE_LEVEL) {
+			(MV_REG_READ(MV_GPP_IRQ_POLARITY(reg)) & bitmask)?
+				MV_REG_BIT_RESET(MV_GPP_IRQ_POLARITY(reg), bitmask):
+				MV_REG_BIT_SET(MV_GPP_IRQ_POLARITY(reg), bitmask);
+		}
+	} else
+		printk("mv_unmask_fiq: ERR, irq-%u out of scope\n",irq);
+}
+
+irq_handler_t fiq_handlers[NR_IRQS] = {
+	[0 ... NR_IRQS-1] = NULL,
+};
+
+static inline int find_fiq_bit(void)
+{
+	int bit, high_cause_sum_bit;
+	MV_U32 mask;
+	unsigned long cause;
+
+	/*
+	 * Handle Low Cause interrupts
+	 */
+	cause = MV_REG_READ(MV_IRQ_CAUSE_LOW_REG);
+
+	/* Save High Cause Summary bit to save access to Cause register. */
+	high_cause_sum_bit = cause & 0x1;
+
+	cause &= MV_REG_READ(MV_FIQ_MASK_LOW_REG);
+	bit = find_first_bit(&cause, 32);
+	if (bit < 32)
+		goto out;
+
+	/*
+	 * Handle High Cause interrupts
+	 */
+	if (!high_cause_sum_bit)
+		goto check_cause_error;
+	cause = MV_REG_READ(MV_IRQ_CAUSE_HIGH_REG);
+	cause &= MV_REG_READ(MV_FIQ_MASK_HIGH_REG);
+	bit = find_first_bit(&cause, 32);
+	if (bit >= 32)
+		goto check_cause_error;
+	if (bit >= 4 && bit <= 15) {
+		/* Handle GPIO case */
+		bit = (bit - 4) * 8 + IRQ_GPP_START;
+		if (bit > IRQ_GPP_START + 88) {
+			/* Print some info in the future.
+			 * Currently, this case may be traced
+			 * only through FIQ exception counter
+			 * (cat /proc/fiq_dump).
+			 */
+			goto err_out;
+		}
+	} else
+		bit += 32;
+	goto out;
+
+	/*
+	 * Handle Error Cause interrupts
+	 */
+check_cause_error:
+	mask  = MV_REG_READ(MV_FIQ_MASK_ERROR_REG);
+	cause = mask & MV_REG_READ(MV_IRQ_CAUSE_ERROR_REG);
+	bit = find_first_bit(&cause, 32);
+	if (bit < 32)
+		goto out;
+
+err_out:
+	/* No interrupt found. */
+	return -1;
+
+out:
+	return bit;
+}
+
+typedef void (*fiq_handler_t)(void);
+extern fiq_handler_t fiq_userptr;
+
+void handle_all_fiqs(void)
+{
+	irq_handler_t handler;
+	int fiq = find_fiq_bit();
+
+	handler = fiq_handlers[fiq];
+	if (handler)
+		handler(fiq, NULL);
+}
+
+int __must_check
+request_fiq(unsigned int irq, irq_handler_t handler, unsigned long flags,
+	    const char *name, void *dev)
+{
+	if ((irq < 0) | (irq >= NR_IRQS))
+		return -EINVAL;
+
+	/*
+	 * if (flags & IRQF_DISABLED)
+	 *	return -EINVAL;
+	 */
+
+	mv_mask_fiq(irq);
+
+	if (!fiq_userptr)
+		fiq_userptr = handle_all_fiqs;
+
+	if (fiq_handlers[irq])
+		return -EINVAL;
+
+	fiq_handlers[irq] = handler;
+	mv_unmask_fiq(irq);
+	return 0;
+}
+
+void free_fiq(unsigned int irq, void *dev_id)
+{
+	mv_mask_fiq(irq);
+	fiq_handlers[irq] = NULL;
+}
+
+
+
diff --git a/arch/arm/mach-feroceon-kw2/flashmap.c b/arch/arm/mach-feroceon-kw2/flashmap.c
new file mode 100755
index 0000000..e16d06b
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/flashmap.c
@@ -0,0 +1,274 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/version.h>
+#include "mvSysHwConfig.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+
+/*#define MTD_FLASH_MAP_DEBUG*/
+
+#ifdef MTD_FLASH_MAP_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+#define MTD_MAX_FLASH_NUMBER	4
+#define MTD_DUMMY_BANK_WIDTH	2
+
+struct maps_init_info
+{
+	struct map_info mapInfo;
+	char ** mtdDrv;
+	struct mtd_info * mtdInfo;
+	char name[32];
+};	
+
+static struct maps_init_info maps[MTD_MAX_FLASH_NUMBER];
+static unsigned int mapsNum = 0;
+
+#if defined (CONFIG_MTD_CFI) || defined (CONFIG_MTD_JEDECPROBE)
+static char * cfiDev = "cfi_flash";
+static char * cfiMtdList[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
+#endif
+
+#ifdef CONFIG_MV_INCLUDE_SFLASH_MTD
+static char * sflashDev = "spi_flash";
+static char * sflashMtdList[] = {"sflash", NULL};
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition *mtd_parts;
+static int                   mtd_parts_nb;
+static const char *part_probes[] __initdata = {"cmdlinepart", NULL};
+#endif /* CONFIG_MTD_PARTITIONS */
+
+static int flashInfoFill(void)
+{
+	int expectedDevs = 0;
+	int devs, i;
+
+	/* clear the whole array */
+	memset((void*)maps, 0x0, sizeof(maps));
+
+#if defined (CONFIG_MTD_CFI) || defined (CONFIG_MTD_JEDECPROBE)
+	/* gather the CFI and JEDEC NOR flash devices information */
+	devs = mvBoardGetDevicesNumber(BOARD_DEV_NOR_FLASH);
+
+	for(i=0; i<devs; i++)
+	{
+		if (expectedDevs >= MTD_MAX_FLASH_NUMBER)
+		{
+			printk(KERN_NOTICE "\nERROR: %s - Exceeded MAX MTD flash devices number", __FUNCTION__);		
+			break;	
+		}
+		maps[expectedDevs].mtdDrv = cfiMtdList;	
+		sprintf(maps[expectedDevs].name, "%s_%d", cfiDev, i);
+		maps[expectedDevs].mapInfo.name = maps[expectedDevs].name;
+		maps[expectedDevs].mapInfo.phys = mvBoardGetDeviceBaseAddr(i, BOARD_DEV_NOR_FLASH);
+		maps[expectedDevs].mapInfo.size = mvBoardGetDeviceWinSize(i, BOARD_DEV_NOR_FLASH);
+		maps[expectedDevs].mapInfo.bankwidth = (mvBoardGetDeviceBusWidth(i, BOARD_DEV_NOR_FLASH) / 8);
+		
+		if ((maps[expectedDevs].mapInfo.phys != 0xFFFFFFFF) && 
+		    (maps[expectedDevs].mapInfo.size != 0xFFFFFFFF))
+		{
+			DB(printk("\nINFO: Found %s %d - base 0x%08x, size 0x%x", maps[expectedDevs].mapInfo.name, i,
+   	          (unsigned int)maps[expectedDevs].mapInfo.phys, (unsigned int)maps[expectedDevs].mapInfo.size));
+   			++expectedDevs;
+		}
+		else
+		{
+			printk(KERN_NOTICE "\nERROR: %s - Failed to get Device Base address and Size (%s %d)", __FUNCTION__, maps[expectedDevs].mapInfo.name, i);
+		}
+	}
+#endif
+	
+#ifdef CONFIG_MV_INCLUDE_SFLASH_MTD
+	/* gather the SPI flash devices information */
+	devs = mvBoardGetDevicesNumber(BOARD_DEV_SPI_FLASH);
+
+	for(i=0; i<devs; i++)
+	{
+		if (expectedDevs >= MTD_MAX_FLASH_NUMBER)
+		{
+			printk(KERN_NOTICE "\nERROR: %s - Exceeded MAX MTD flash devices number", __FUNCTION__);		
+			break;	
+		}
+		maps[expectedDevs].mtdDrv = sflashMtdList;	
+		maps[expectedDevs].mapInfo.name = sflashDev;
+		maps[expectedDevs].mapInfo.phys = mvBoardGetDeviceBaseAddr(i, BOARD_DEV_SPI_FLASH);
+		maps[expectedDevs].mapInfo.size = mvBoardGetDeviceWinSize(i, BOARD_DEV_SPI_FLASH);
+		maps[expectedDevs].mapInfo.bankwidth = MTD_DUMMY_BANK_WIDTH;
+
+		if ((maps[expectedDevs].mapInfo.phys != 0xFFFFFFFF) && 
+		    (maps[expectedDevs].mapInfo.size != 0xFFFFFFFF))
+		{
+			DB(printk("\nINFO: Found %s %d - base 0x%08x, size 0x%x", maps[expectedDevs].mapInfo.name, i,
+						(unsigned int)maps[expectedDevs].mapInfo.phys,
+						(unsigned int)maps[expectedDevs].mapInfo.size));
+			++expectedDevs;
+		}
+		else
+		{
+			printk(KERN_NOTICE "\nERROR: %s - Failed to get Device Base address and Size (%s %d)",
+					__FUNCTION__, maps[expectedDevs].mapInfo.name, i);
+		}
+	}
+#endif
+
+	DB(printk("\nINFO: %s - Found %d Flash Devices", __FUNCTION__, expectedDevs));
+	return expectedDevs;
+}
+
+static int flashProbe(char ** mtdDrv, struct map_info * map, struct mtd_info ** mtd)
+{
+	if ((mtdDrv == NULL) || (map == NULL) || (mtd == NULL))
+	{
+		printk(KERN_NOTICE "\nERROR: NULL pointer parameter at %s entry", __FUNCTION__);
+		return -EINVAL;	
+	}
+
+	/* remap the physical address to a virtual address */
+	map->virt = ioremap(map->phys, map->size);	
+	if (!map->virt) 
+	{
+		printk(KERN_NOTICE "\nERROR: Failed to ioremap Flash device at physical base 0x%x.", (unsigned int)map->phys);
+		return -EIO;
+	}
+	
+	DB(printk("\nINFO: Io remapped successfully - phy addr = 0x%08x, virt addr = 0x%08x",
+				(unsigned int)map->phys, (unsigned int)map->virt));
+
+	simple_map_init(map);
+
+	*mtd = NULL;
+	for(; (!(*mtd) && *mtdDrv); mtdDrv++) 
+	{
+		DB(printk("\nINFO: Using %s to probe %s at address 0x%08x, size 0x%x, width %dm", 
+					*mtdDrv, map->name, (unsigned int)map->phys,
+					(unsigned int)map->size, map->bankwidth));
+		if ((*mtd = do_map_probe(*mtdDrv, map)))
+		{
+			DB(printk(" - detected OK"));
+			/*map->size = (*mtd)->size;*/
+			(*mtd)->owner = THIS_MODULE;
+
+#ifdef CONFIG_MTD_PARTITIONS
+			mtd_parts_nb = parse_mtd_partitions(*mtd, part_probes, &mtd_parts, 0, "");
+
+			if (mtd_parts_nb > 0)
+			{
+				add_mtd_partitions (*mtd, mtd_parts, mtd_parts_nb);
+				return 0;
+			}
+#endif
+
+			if (add_mtd_device(*mtd) != 0)
+			{
+				printk(KERN_NOTICE "\nERROR: %s - Failed to add the mtd device", __FUNCTION__);
+				iounmap((void *)map->virt);
+				map->virt = 0;
+				return -ENXIO;
+			}
+
+			return 0;
+		} 
+		else 
+		{
+			DB(printk(" - Not detected"));
+		}
+	}
+ 
+	iounmap((void *)map->virt);
+	map->virt = 0;
+	return -ENXIO;
+}
+	
+static int __init flash_map_init(void)
+{	
+	int i;
+
+	mapsNum = flashInfoFill();
+	DB(printk("\nINFO: flash_map_init - detected %d devices",  mapsNum));
+
+	for (i=0; i<mapsNum; i++)
+	{
+		DB(printk("MTD: Initialize the %s device at address 0x%08x", maps[i].mapInfo.name, (unsigned int)maps[i].mapInfo.phys));
+		if (flashProbe(maps[i].mtdDrv, &maps[i].mapInfo, &maps[i].mtdInfo) == 0)
+		{
+			DB(printk(" - OK.\n"));
+		}
+		else
+		{
+			maps[i].mtdInfo = NULL;
+			DB(printk(" - FAILED!\n"));
+		}
+	}
+	
+	return 0;
+}
+
+static void __exit flash_map_exit(void)
+{
+	int i;
+
+	for (i=0; i<mapsNum; i++)
+	{
+		if (maps[i].mtdInfo)
+		{
+			del_mtd_device(maps[i].mtdInfo);
+			map_destroy(maps[i].mtdInfo);
+		}
+
+		if (maps[i].mapInfo.virt)
+		{
+			iounmap((void *)maps[i].mapInfo.virt);
+			maps[i].mapInfo.virt = 0;
+		}
+	}
+}
+
+module_init(flash_map_init);
+module_exit(flash_map_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MTD map driver for Marvell platforms");
diff --git a/arch/arm/mach-feroceon-kw2/hwmon.c b/arch/arm/mach-feroceon-kw2/hwmon.c
new file mode 100755
index 0000000..42a04a1
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/hwmon.c
@@ -0,0 +1,166 @@
+/*
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/cpu.h>
+#include <asm/io.h>
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+
+#define TIMEOUT 10000
+#define KW2_OVERHEAT_TEMP	105000		/* milidegree Celsius */
+#define KW2_OVERCOOL_TEMP	10000		/* milidegree Celsius */
+
+
+#define THERMAL_STATUS_REG 0x184d8
+#define THERMAL_CALIBRATION_BIT 0
+#define THERMAL_CALIBRATION_MASK (1 << THERMAL_CALIBRATION_BIT)
+#define THERMAL_VALID_BIT 9
+#define THERMAL_VALID_MASK (1 << THERMAL_VALID_BIT)
+#define THERMAL_TEMPERATURE_OFFSET 10
+#define THERMAL_TEMPERATURE_MASK (0x1FF << THERMAL_TEMPERATURE_OFFSET)
+
+#define STABILITY_ITERATIONS 4
+
+#define RAW_TO_TEMP(x) ((((322 - x) * 10000)/13625)*1000)
+
+typedef enum { 
+	SHOW_TEMP, 
+	TEMP_MAX,
+	TEMP_MIN,
+	SHOW_NAME } SHOW;
+
+static struct device *hwmon_dev;
+
+
+
+/* attributes methods */
+static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "kw2Thermal\n");
+}
+
+
+static ssize_t show_temp(struct device *dev,
+			 struct device_attribute *devattr, char *buf) {
+	int ret;
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+	if (attr->index == SHOW_TEMP)
+		ret = sprintf(buf, "%d\n", mvCtrlTemperatureGet()*1000); /* lm sensors uses mili celsius! */
+	else if (attr->index == TEMP_MAX)
+		ret = sprintf(buf, "%d\n", KW2_OVERHEAT_TEMP);
+	else if (attr->index == TEMP_MIN)
+		ret = sprintf(buf, "%d\n", KW2_OVERCOOL_TEMP);
+	else
+		ret = sprintf(buf, "%d\n", -1);
+
+	return ret;
+}
+
+
+
+
+/* sysfs attributes define */
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, SHOW_TEMP);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRWXUGO, show_temp, NULL, TEMP_MAX);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IRWXUGO, show_temp, NULL, TEMP_MIN);
+
+static struct attribute *kw2ThermalAttributes[] = {
+	&sensor_dev_attr_name.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group kw2_thermal_group = {
+	.attrs	= kw2ThermalAttributes,
+};
+
+
+
+/* sysfs  group create, and register hwmon driver */
+static int kw2_thermal_probe(struct platform_device * plat_dev)
+{
+	int err;
+	/* init_thermal_sensor(); */
+	
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&plat_dev->dev.kobj, &kw2_thermal_group);
+	if (err)
+		goto exit;
+
+	/* Register a new directory entry with module sensors */
+	hwmon_dev = hwmon_device_register(&plat_dev->dev);
+	if (IS_ERR(hwmon_dev)) {
+		printk("hwmon device register failed\n");
+		goto exit_remove_group;
+	}
+
+	return 0;
+
+exit_remove_group:
+	sysfs_remove_group(&plat_dev->dev.kobj, &kw2_thermal_group);
+exit:
+	return err;
+}
+
+
+
+static int __devexit kw2_thermal_remove(struct platform_device *plat_dev)
+{
+	hwmon_device_unregister(hwmon_dev);
+	sysfs_remove_group(&plat_dev->dev.kobj, &kw2_thermal_group);
+	return 0;
+}
+
+
+static struct platform_driver kw2_thermal_driver = {
+	.probe		= kw2_thermal_probe,
+	.remove		= __devexit_p(kw2_thermal_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "KW2Thermal",
+	},
+};
+
+static int __init thermal_init(void)
+{
+	return platform_driver_register(&kw2_thermal_driver);
+}
+
+static void __exit thermal_exit(void)
+{
+	platform_driver_unregister(&kw2_thermal_driver);
+}
+
+module_init(thermal_init);
+module_exit(thermal_exit);
+
+MODULE_AUTHOR("Marvell Semiconductors");
+MODULE_DESCRIPTION("KW2 - Thermal sensor");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/bridge-regs.h b/arch/arm/mach-feroceon-kw2/include/mach/bridge-regs.h
new file mode 100755
index 0000000..88397b0
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/bridge-regs.h
@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+
+/*
+ * arch/arm/mach-feroceon-kw/include/mach/bridge-regs.h
+ *
+ * Mbus-L to Mbus Bridge Registers
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASM_ARCH_BRIDGE_REGS_H
+#define __ASM_ARCH_BRIDGE_REGS_H
+
+
+#include "ctrlEnv/sys/mvCpuIfRegs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+
+#define FEROCEON_REGS_VIRT_BASE        (INTER_REGS_BASE | MAX_AHB_TO_MBUS_REG_BASE)
+
+#define CPU_CONTROL                    (FEROCEON_REGS_VIRT_BASE | CPU_CTRL_STAT_REG)
+#define TIMER_VIRT_BASE                (FEROCEON_REGS_VIRT_BASE | MV_CNTMR_REGS_OFFSET)
+#define RSTOUTn_MASK                   (FEROCEON_REGS_VIRT_BASE | CPU_RSTOUTN_MASK_REG)
+#define BRIDGE_CAUSE                   (FEROCEON_REGS_VIRT_BASE | CPU_AHB_MBUS_CAUSE_INT_REG)
+
+#define WDT_RESET_OUT_EN               0x00000002
+#define WDT_INT_REQ                    0x0008
+
+
+#endif
+
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/debug-macro.S b/arch/arm/mach-feroceon-kw2/include/mach/debug-macro.S
new file mode 100755
index 0000000..8c0d442
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/debug-macro.S
@@ -0,0 +1,26 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Assembler-only file 
+ */
+         .macro  addruart,rx
+         mov   \rx, #0xf1000000
+         orr   \rx, \rx, #0x00012000
+         .endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>
+
+
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/dma.h b/arch/arm/mach-feroceon-kw2/include/mach/dma.h
new file mode 100755
index 0000000..4d2d66a
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/dma.h
@@ -0,0 +1,24 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS		0xffffffff
+
+#define MAX_DMA_CHANNELS	0
+
+#endif /* _ASM_ARCH_DMA_H */
+
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/entry-macro.S b/arch/arm/mach-feroceon-kw2/include/mach/entry-macro.S
new file mode 100755
index 0000000..771c697
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/entry-macro.S
@@ -0,0 +1,150 @@
+/*
+ * include/asm-arm/arch-feroceon-kw/entry-macro.S
+ *
+ * Low-level IRQ helper macros for Integrator platforms
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+
+        .macro  disable_fiq
+        .endm
+        
+        .macro  get_irqnr_preamble, base, tmp
+        .endm
+
+         .macro  arch_ret_to_user, tmp1, tmp2
+         .endm
+
+#if defined(CONFIG_CPU_BIG_ENDIAN)
+        	.macro	HTOLL sr, tt		@ sr   = A  ,B  ,C  ,D    
+        	eor \tt, \sr, \sr, ror #16 ;    @ temp = A^C,B^	  
+        	bic \tt, \tt, #0xff0000 ;       @ temp = A^C,0  ,C^A,D^B
+        	mov \sr, \sr, ror #8 ;          @ sr   = D  ,A  ,B  ,C
+        	eor \sr, \sr, \tt, lsr #8       @ sr   = D  ,C  ,B  ,A
+        	.endm
+#else		
+        	.macro	HTOLL sr, tt	
+        	.endm
+#endif
+
+                /*
+                 * This macro should return the follows:
+                 *      irqnr - the number of the received irq
+                 *      eq flag - not set if succeed and set if fail.
+                 */
+
+                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+                ldr     \base, =MV_ASM_IRQ_MASK_LOW_REG
+                ldr     \tmp, [\base]    			        @ get low mask
+                ldr	\base, =MV_ASM_IRQ_CAUSE_LOW_REG
+                ldr     \irqstat, [\base]                		@ get low cause
+                ands    \irqstat, \irqstat, \tmp                        @ and mask and cause
+		beq     1001f
+		HTOLL	\irqstat, \tmp
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr, \base, \irqnr
+                beq     1001f                                           @ bit0 is set - jump to 1001
+		teq     \irqnr, #32                                     @ if irq isn't 32 unset the flag
+		b 	1006f
+1001:
+		ldr     \base, =MV_ASM_IRQ_MASK_HIGH_REG
+                ldr     \tmp, [\base]    			        @ get mask
+                ldr	\base, =MV_ASM_IRQ_CAUSE_HIGH_REG
+                ldr     \irqstat, [\base]                		@ get cause
+                ands    \irqstat, \irqstat, \tmp                        @ and mask and cause
+		beq	1002f						@ no bit is set - jump to 1002
+		HTOLL	\irqstat, \tmp
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr, \base, \irqnr
+		cmp	\irqnr, #4					@ GPP LOW 0-7
+		beq	1003f
+		cmp	\irqnr, #5					@ GPP LOW 8-15
+		beq	1003f
+		cmp	\irqnr, #6					@ GPP LOW 16-23
+		beq	1003f
+		cmp	\irqnr, #7					@ GPP LOW 24-31
+		beq	1003f
+		cmp	\irqnr, #8					@ GPP MID 0-7
+		beq	1004f
+		cmp	\irqnr, #9					@ GPP MID 8-15
+		beq	1004f
+		cmp	\irqnr, #10					@ GPP MID 16-23
+		beq	1004f
+		cmp	\irqnr, #11					@ GPP MID 24-31
+		beq	1004f
+		cmp	\irqnr, #12					@ GPP HIGH 0-7
+		beq	1005f
+		cmp	\irqnr, #13					@ GPP HIGH 8-15
+		beq	1005f
+		cmp	\irqnr, #14					@ GPP HIGH 16-23
+		beq	1005f
+		cmp	\irqnr, #15					@ GPP HIGH 24
+		beq	1005f
+		add	\irqnr,\irqnr,#32				@ add 32 so (32 <= irqnr < 64)
+		teq     \irqnr, #64                                     @ if irq isn't 64 unset the flag
+		b	1006f						@ update irqnr and return
+1002:
+		ldr     \base, =MV_ASM_IRQ_MASK_ERROR_REG
+                ldr     \tmp, [\base]    				@ get error mask
+                ldr	\base, =MV_ASM_IRQ_CAUSE_ERROR_REG
+                ldr     \irqstat, [\base]                		@ get error cause
+                ands    \irqstat, \irqstat, \tmp                        @ and mask and cause
+		beq	1006f						@ if eq to 0 jump to 1006
+		HTOLL	\irqstat, \tmp
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr, \base, \irqnr
+		add	\irqnr,\irqnr, #64
+		teq     \irqnr, #96                                     @ if irq isn't 96 unset the flag
+		b	1006f						@ update irqnr and return
+1003:
+		ldr     \base, =MV_ASM_GPP_IRQ_MASK_REG
+                ldr     \tmp, [\base]    				@ get gpp mask
+                ldr	\base, =MV_ASM_GPP_IRQ_CAUSE_REG
+                ldr     \irqstat, [\base]                		@ get gpp data in (cause)
+                ands    \irqstat, \irqstat, \tmp                        @ and mask and cause
+		beq	1006f						@ if eq to 0 jump to 1006
+		HTOLL	\irqstat, \tmp
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr, \base, \irqnr
+		add	\irqnr,\irqnr, #96
+		teq     \irqnr, #128                                    @ if irq isn't 128 unset the flag
+		b	1006f						@ update irqnr and return 
+1004:
+		ldr     \base, =MV_ASM_GPP_IRQ_MID_MASK_REG
+                ldr     \tmp, [\base]    				@ get gpp mask
+                ldr	\base, =MV_ASM_GPP_IRQ_MID_CAUSE_REG
+                ldr     \irqstat, [\base]                		@ get gpp data in (cause)
+                ands    \irqstat, \irqstat, \tmp                        @ and mask and cause
+		beq	1006f						@ if eq to 0 jump to 1006
+		HTOLL	\irqstat, \tmp
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr, \base, \irqnr
+		add	\irqnr,\irqnr, #128
+		teq     \irqnr, #160					@ if irq isn't 160 unset the flag
+		b	1006f						@ update irqnr and return	
+1005:
+		ldr     \base, =MV_ASM_GPP_IRQ_HIGH_MASK_REG
+                ldr     \tmp, [\base]    				@ get gpp mask
+                ldr	\base, =MV_ASM_GPP_IRQ_HIGH_CAUSE_REG
+                ldr     \irqstat, [\base]                		@ get gpp data in (cause)
+                ands    \irqstat, \irqstat, \tmp                        @ and mask and cause
+		beq	1006f						@ if eq to 0 jump to 1006
+		HTOLL	\irqstat, \tmp
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr, \base, \irqnr
+		add	\irqnr,\irqnr, #160
+		teq     \irqnr, #192					@ if irq isn't 192 unset the flag
+		b	1006f						@ update irqnr and return	
+1006:
+                .endm
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/gpio.h b/arch/arm/mach-feroceon-kw2/include/mach/gpio.h
new file mode 100755
index 0000000..f9df3e5
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/gpio.h
@@ -0,0 +1,26 @@
+/*
+ * arch/asm-arm/mach-feroceon-kw2/include/mach/gpio.h
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#include <mach/irqs.h>
+#include <plat/gpio.h>
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+static inline int gpio_to_irq(int pin)
+{
+	return pin + IRQ_GPP_START;
+}
+
+static inline int irq_to_gpio(int irq)
+{
+	return irq - IRQ_GPP_START;
+}
+#endif
+
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/hardware.h b/arch/arm/mach-feroceon-kw2/include/mach/hardware.h
new file mode 100755
index 0000000..f591ae7
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/hardware.h
@@ -0,0 +1,34 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#include "../arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h"
+
+
+#define PCI_MEMORY_VADDR        PEX0_MEM_BASE	/* PCI MEM Vaddr */
+#define PCI_IO_VADDR            PEX0_IO_BASE	/* PCI IO Vadder */
+
+#define pcibios_assign_all_busses()     1	/* assign a bus number over the bridge while scanning it */
+                                                                                                                             
+#define PCIBIOS_MIN_IO          0x1000		/* min IO allocate for PCI dev */
+#define PCIBIOS_MIN_MEM         0x01000000	/* min MEM allocate for PCI dev */
+
+#define PCIMEM_BASE             PCI_MEMORY_VADDR /* mem base for VGA use*/
+
+#endif
+
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/ide.h b/arch/arm/mach-feroceon-kw2/include/mach/ide.h
new file mode 100755
index 0000000..04e0bca
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/ide.h
@@ -0,0 +1,15 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/io.h b/arch/arm/mach-feroceon-kw2/include/mach/io.h
new file mode 100755
index 0000000..eb7e99f
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/io.h
@@ -0,0 +1,26 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+#define IO_SPACE_REMAP 0xf2000000
+
+#define __io(a)			(a + IO_SPACE_REMAP)
+#define __mem_pci(a)		((unsigned long)(a))
+#define __mem_isa(a)		(a)
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/irqs.h b/arch/arm/mach-feroceon-kw2/include/mach/irqs.h
new file mode 100755
index 0000000..07413f2
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/irqs.h
@@ -0,0 +1,185 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/autoconf.h>
+
+#include "../arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h"
+
+/* for Asm only */
+#define MV_ASM_BRIDGE_INT_CAUSE_REG	(INTER_REGS_BASE + 0x20110)
+#define MV_ASM_BRIDGE_INT_MASK_REG    	(INTER_REGS_BASE + 0x20114)
+
+#define MV_ASM_IRQ_CAUSE_LOW_REG	(INTER_REGS_BASE + 0x20200)
+#define MV_ASM_IRQ_CAUSE_HIGH_REG	(INTER_REGS_BASE + 0x20210)
+
+#define MV_ASM_IRQ_MASK_LOW_REG		(INTER_REGS_BASE + 0x20204)
+#define MV_ASM_IRQ_MASK_HIGH_REG	(INTER_REGS_BASE + 0x20214)
+
+#define MV_ASM_IRQ_CAUSE_ERROR_REG	(INTER_REGS_BASE + 0x20220)
+#define MV_ASM_IRQ_MASK_ERROR_REG	(INTER_REGS_BASE + 0x20224)
+
+#define MV_ASM_GPP_IRQ_CAUSE_REG	(INTER_REGS_BASE + 0x18110) /* use data in for cause in case of level interrupts */
+#define MV_ASM_GPP_IRQ_MID_CAUSE_REG	(INTER_REGS_BASE + 0x18150) /* use mid data in for cause in case of level interrupts */ 
+#define MV_ASM_GPP_IRQ_HIGH_CAUSE_REG	(INTER_REGS_BASE + 0x18190) /* use high data in for cause in case of level interrupts */ 
+ 
+#define MV_ASM_GPP_IRQ_MASK_REG        	(INTER_REGS_BASE + 0x1811c)	/* level low mask */
+#define MV_ASM_GPP_IRQ_MID_MASK_REG	(INTER_REGS_BASE + 0x1815c)	/* level mid mask */
+#define MV_ASM_GPP_IRQ_HIGH_MASK_REG    (INTER_REGS_BASE + 0x1819c)	/* level high mask */
+
+/* for c */
+#define MV_IRQ_CAUSE_LOW_REG		0x20200
+#define MV_IRQ_CAUSE_HIGH_REG		0x20210
+#define MV_IRQ_CAUSE_ERROR_REG		0x20220
+
+#define MV_IRQ_MASK_LOW_REG		0x20204
+#define MV_FIQ_MASK_LOW_REG		0x20208
+#define MV_IRQ_MASK_HIGH_REG		0x20214
+#define MV_FIQ_MASK_HIGH_REG		0x20218
+#define MV_IRQ_MASK_ERROR_REG		0x20224
+#define MV_FIQ_MASK_ERROR_REG		0x20228
+
+/* Doorbell interrupt support */
+#define MV_IN_DRBELL_CAUSE_REG		0x20400
+#define MV_IN_DRBELL_MASK_REG		0x20404
+
+#define MV_GPP_IRQ_CAUSE_REG(id)	(0x18114 + (0x40 * (id)))
+
+#define MV_GPP_IRQ_EDGE_REG(id)		(0x18118 + (0x40 * (id)))
+
+#define MV_GPP_IRQ_MASK_REG(id)        	(0x1811c + (0x40 * (id)))
+
+#define MV_GPP_IRQ_POLARITY(id)		(0x1810c + (0x40 * (id)))
+
+#if 0
+#define MV_AHBTOMBUS_IRQ_CAUSE_REG 	0x20114
+#endif
+
+#define MV_PCI_MASK_REG(unit)		((unit == 0) ? 0x41910 : 0x45910)
+#define MV_PCI_IRQ_CAUSE_REG(pciIf)    (0x41900 + (pciIf * 0x4000))
+#define MV_PCI_MASK_ABCD		(BIT24 | BIT25 | BIT26 | BIT27 )
+
+/* Description for bit from PCI Express Interrupt Mask Register 
+** BIT3 - Erroneous Write Attempt to Internal Register
+** BIT4 - Hit Default Window Error
+** BIT9 and BIT10 - Non Fatal and Fatal Error Detected
+** BIT14 - Flow Control Protocol Error
+** BIT23 - Link Failure Indication
+*/
+#define MV_PCI_MASK_ERR                        (BIT3 | BIT4 | BIT9 | BIT10 | BIT14 | BIT23)
+
+#define GPP_IRQ_TYPE_LEVEL		0
+#define GPP_IRQ_TYPE_CHANGE_LEVEL	1
+
+
+/* 
+ *  Interrupt numbers
+ */
+#define IRQ_HIGH(x)			(32 + (x))
+#define IRQ_ERROR(x)			(64 + (x))
+#define IRQ_START			0
+
+/* Main Low */
+#define IRQ_MAIN_HIGH_SUM		0
+#define BRIDGE_IRQ_NUM			1
+#define IN_DRBELL_IRQ_NUM		2 /* Host-to-CPU doorbell */
+#define IRQ_MAIN_ERROR_SUM		4
+#define NET_MISC_IRQ_NUM(x)		(5 + ((x) * 4))
+#define NET_RXTX_IRQ_NUM(x)		(6 + ((x) * 4))
+#define NET_TH_RXTX_IRQ_NUM(x)		(7 + ((x) * 4))
+#define NET_WAKEUP_IRQ_NUM(x)		(8 + ((x) * 4))
+#define NETPON_MISC_IRQ_NUM		13
+#define NETPON_RXTX_IRQ_NUM		14
+#define NETPON_TH_RXTX_IRQ_NUM		15
+#define NETPON_WAKEUP_IRQ_NUM		16
+#define SDIO_IRQ_NUM			18
+#define SPI_IRQ_NUM(x)			((x == 0) ? 19 : IRQ_HIGH(17))
+#define TDM_2CH_IRQ_NUM			19
+#define CESA_IRQ_NUM(chan)		((chan == 0) ? 21 : 17)
+#define SATA_IRQ_NUM			22
+#define USB_IRQ_NUM			23
+#define PEX1_IRQ_NUM			24
+#define PEX0_IRQ_NUM			25
+#define XOR0_IRQ_NUM			26
+#define XOR1_IRQ_NUM			27
+#define BM_IRQ_NUM			28
+#define ETH_COMP_IRQ_NUM		29
+#define TDM_IRQ_NUM			30
+#define GPON_MAC_IRQ_NUM		31
+
+/* Main High */
+#define RTC_IRQ_NUM			IRQ_HIGH(0)
+#define UART_IRQ_NUM(x)			IRQ_HIGH(1 + x)
+#define DYNGASP_IRQ_NUM			IRQ_HIGH(3)
+#define GPP_LOW_0_7_IRQ_NUM		IRQ_HIGH(4)
+#define GPP_LOW_8_15_IRQ_NUM		IRQ_HIGH(5)
+#define GPP_LOW_16_23_IRQ_NUM		IRQ_HIGH(6)
+#define GPP_LOW_24_31_IRQ_NUM		IRQ_HIGH(7)
+#define GPP_MID_0_7_IRQ_NUM		IRQ_HIGH(8)
+#define GPP_MID_8_15_IRQ_NUM		IRQ_HIGH(9)
+#define GPP_MID_16_23_IRQ_NUM		IRQ_HIGH(10)
+#define GPP_MID_24_31_IRQ_NUM		IRQ_HIGH(11)
+#define GPP_HIGH_0_7_IRQ_NUM		IRQ_HIGH(12)
+#define GPP_HIGH_8_15_IRQ_NUM		IRQ_HIGH(13)
+#define GPP_HIGH_16_23_IRQ_NUM		IRQ_HIGH(14)
+#define GPP_HIGH_24_IRQ_NUM		IRQ_HIGH(15)
+#define NET_LEGACY_TX_IRQ_NUM(x)	IRQ_HIGH(19 + (3 * x))
+#define NET_LEGACY_RX_IRQ_NUM(x)	IRQ_HIGH(20 + (3 * x))
+#define NET_LEGACY_SUM_IRQ_NUM(x)	IRQ_HIGH(21 + (3 * x))
+#define NF_IRQ_NUM			IRQ_HIGH(16)
+#define TWSI_IRQ_NUM(x)			((x == 0) ? IRQ_HIGH(18) : IRQ_HIGH(25))
+
+/* Main Error */
+#define NET_ERR_IRQ_NUM(x)		IRQ_ERROR(0 + x)
+#define PON_ERR_IRQ_NUM			IRQ_ERROR(2)
+#define L2C_TAG_PAR_ERR_IRQ_NUM		IRQ_ERROR(3)
+#define L2C_UNCOR_ERR_IRQ_NUM		IRQ_ERROR(4)
+#define L2C_COR_ERR_IRQ_NUM		IRQ_ERROR(5)
+#define TDM_ERROR			IRQ_ERROR(6)
+#define DEVBUS_IRQ_NUM			IRQ_ERROR(7)
+#define L1C_UNREC_PAR_IRQ_NUM		IRQ_ERROR(8)
+#define XOR_ERR_IRQ_NUM			IRQ_ERROR(9)
+#define BM_ERR_IRQ_NUM			IRQ_ERROR(10)
+#define PNC_ERR_IRQ_NUM			IRQ_ERROR(11)
+#define USB_ERR_IRQ_NUM			IRQ_ERROR(12)
+#define PEX1_ERR_IRQ_NUM		IRQ_ERROR(13)
+#define PEX0_ERR_IRQ_NUM		IRQ_ERROR(14)
+#define CESA_ERR_IRQ_NUM		IRQ_ERROR(16)
+
+#define PEX_ERR_IRQ_NUM(pciIf)             ((pciIf == 0) ? PEX0_ERR_IRQ_NUM : PEX1_ERR_IRQ_NUM)
+
+#define IRQ_GPP_START			96
+#define NR_GPIO_IRQS			96 /* only 89 irqs are valid, but just to be aligned */
+#define IRQ_ASM_GPP_START               96
+#define IRQ_GPP_ID(idx)			(96 + (idx))
+
+/*
+ * MSI interrupts
+ */
+#define NR_MSI_IRQS			16
+#define IRQ_MSI_START			(IRQ_GPP_START + NR_GPIO_IRQS)
+#define NR_IRQS				(IRQ_GPP_START + NR_GPIO_IRQS + NR_MSI_IRQS)
+
+/*********** timer **************/
+
+#define TIME_IRQ        	IRQ_BRIDGE
+#define BRIDGE_INT_CAUSE_REG	0x20110
+#define BRIDGE_INT_MASK_REG    	0x20114
+#define TIMER_BIT_MASK(x)	(1<<(x+1))
+
+#define ETH_PORT_IRQ_NUM(dev)   NET_LEGACY_SUM_IRQ_NUM(dev) 
+
+#define IRQ_USB_CTRL(dev)	USB_IRQ_NUM
+#define CESA_IRQ(chan)		CESA_IRQ_NUM(chan)
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/kw_macro.h b/arch/arm/mach-feroceon-kw2/include/mach/kw_macro.h
new file mode 100755
index 0000000..9e0525a
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/kw_macro.h
@@ -0,0 +1,39 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Assembler-only file 
+ */
+
+
+support_wait_for_interrupt_address:
+        .word   support_wait_for_interrupt
+
+/* rd, rs, rt, re - are temp registers that will b used (non are input/output) */
+.macro mv_flush_all, rd, rs, rt, re
+	mov     \re, #0
+
+        mov     \rd, #(4 - 1) << 30      @ 4 way cache
+        mov     \rs, #(256 * CACHE_DLINESIZE)
+
+1:      orr     \rt, \re, \rd
+2:      mcr     p15, 0, \rt, c7, c14, 2          @ clean & invalidate D index
+        subs    \rt, \rt, #1 << 30
+        bcs     2b                              @ entries 3 to 0
+        add     \re, \re, #32
+        cmp     \re, \rs
+        bne     1b
+
+/* exit */	
+	.endm
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/memory.h b/arch/arm/mach-feroceon-kw2/include/mach/memory.h
new file mode 100755
index 0000000..6e585a3
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/memory.h
@@ -0,0 +1,10 @@
+/*
+ * arch/arm/mach-feroceon-kw2/include/mach/memory.h
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET		UL(0x00000000)
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/msi.h b/arch/arm/mach-feroceon-kw2/include/mach/msi.h
new file mode 100644
index 0000000..2b8c103
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/msi.h
@@ -0,0 +1,13 @@
+#ifndef _FEROCEON_KW2_MSI_H_
+#define _FEROCEON_KW2_MSI_H_
+
+#ifdef CONFIG_PCI_MSI
+void kw2_msi_init(void);
+#else
+static inline void kw2_msi_init(void)
+{
+	return;
+}
+#endif
+
+#endif /* _FEROCEON_KW2_MSI_H_ */
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/param.h b/arch/arm/mach-feroceon-kw2/include/mach/param.h
new file mode 100755
index 0000000..04e0bca
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/param.h
@@ -0,0 +1,15 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/serial.h b/arch/arm/mach-feroceon-kw2/include/mach/serial.h
new file mode 100755
index 0000000..877e46f
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/serial.h
@@ -0,0 +1,41 @@
+/*
+ *  linux/include/asm-arm/arch-integrator/serial.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#include <asm/irq.h>
+#include <linux/autoconf.h>
+
+#include "../arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h"
+
+extern unsigned int mvTclk;
+
+#undef  BASE_BAUD
+#define BASE_BAUD (mvTclk / 16)
+
+#define PORT0_BASE	(INTER_REGS_BASE + 0x12000) /* port 0 base */
+#define PORT1_BASE 	(INTER_REGS_BASE + 0x12100) /* port 1 base */
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST /* | ASYNC_SPD_VHI  115200 */ )
+
+#define STD_SERIAL_PORT_DEFNS
+#define EXTRA_SERIAL_PORT_DEFNS
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/system.h b/arch/arm/mach-feroceon-kw2/include/mach/system.h
new file mode 100755
index 0000000..38c484d
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/system.h
@@ -0,0 +1,54 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+#include <asm/proc-fns.h>
+
+#include "../arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h"
+
+#define LSP_VERSION "KW2_LSP_3.3.1_p4_PQ"
+
+
+static inline void arch_idle(void)
+{
+	/*
+	 * This should do all the clock switching
+	 * and wait for interrupt tricks
+	 */
+	cpu_do_idle();
+}
+
+#define UPON_SDK_VERSION "uPON_2.6.25_RC1"
+
+#ifdef __BIG_ENDIAN
+#define MV_ARM_32BIT_LE(X) ((((X)&0xff)<<24) |                       \
+                               (((X)&0xff00)<<8) |                      \
+                               (((X)&0xff0000)>>8) |                    \
+                               (((X)&0xff000000)>>24))
+#else
+#define MV_ARM_32BIT_LE(X) (X)
+#endif
+
+
+void mvBoardReset(void);
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	printk("Reseting !! \n");
+	mvBoardReset();
+}
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/timex.h b/arch/arm/mach-feroceon-kw2/include/mach/timex.h
new file mode 100755
index 0000000..f3d5b15
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/timex.h
@@ -0,0 +1,21 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This is the core clock rate and it must be used as a define,
+ * it is used for the jiffies calculation.
+ */
+#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/uncompress.h b/arch/arm/mach-feroceon-kw2/include/mach/uncompress.h
new file mode 100755
index 0000000..9a14a1f
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/uncompress.h
@@ -0,0 +1,94 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/autoconf.h>
+#include "../arch/arm/mach-feroceon-kw2/config/mvSysHwConfig.h"
+#include <linux/serial_reg.h>
+#define MV_UART0_LSR 	(*(volatile unsigned char *)(INTER_REGS_BASE + 0x12000 + 0x14))
+#define MV_UART0_THR	(*(volatile unsigned char *)(INTER_REGS_BASE + 0x12000 + 0x0 ))	 
+
+#define MV_UART1_LSR    (*(volatile unsigned char *)(INTER_REGS_BASE + 0x12100 + 0x14))
+#define MV_UART1_THR    (*(volatile unsigned char *)(INTER_REGS_BASE + 0x12100 + 0x0 ))
+#define MV_SERIAL_BASE ((unsigned char *)(INTER_REGS_BASE + 0x12000 + 0x0 ))
+
+#define DEV_REG		(*(volatile unsigned int *)(INTER_REGS_BASE + 0x40000))
+#define CLK_REG         (*(volatile unsigned int *)(INTER_REGS_BASE + 0x1821C))
+/*
+ * This does not append a newline
+ */
+static void putstr(const char *s)
+{
+#if 0
+	unsigned int model;
+	
+	/* Get dev ID, make sure pex clk is on */
+	if((CLK_REG & 0x4) == 0)
+	{
+		CLK_REG = CLK_REG | 0x4;
+		model = (DEV_REG >> 16) & 0xffff;
+		CLK_REG = CLK_REG & ~0x4;
+	}
+	else
+		model = (DEV_REG >> 16) & 0xffff;
+#endif
+        while (*s) {
+		while ((MV_UART0_LSR & UART_LSR_THRE) == 0);
+		MV_UART0_THR = *s;
+		
+                if (*s == '\n') {
+                        while ((MV_UART0_LSR & UART_LSR_THRE) == 0); 
+                        MV_UART0_THR = '\r';
+                }
+                s++;
+        }
+}
+
+#if 0
+static void putc(const char c)
+{
+	unsigned char *base = MV_SERIAL_BASE;
+	int i;
+
+	for (i = 0; i < 0x1000; i++) {
+		if (base[UART_LSR << 2] & UART_LSR_THRE)
+			break;
+		barrier();
+	}
+
+	base[UART_TX << 2] = c;
+}
+#endif
+#if 0
+static void flush(void)
+{
+	unsigned char *base = MV_SERIAL_BASE;
+	unsigned char mask;
+	int i;
+
+	mask = UART_LSR_TEMT | UART_LSR_THRE;
+
+	for (i = 0; i < 0x1000; i++) {
+		if ((base[UART_LSR << 2] & mask) == mask)
+			break;
+		barrier();
+	}
+}
+#endif
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-feroceon-kw2/include/mach/vmalloc.h b/arch/arm/mach-feroceon-kw2/include/mach/vmalloc.h
new file mode 100755
index 0000000..fdb58a4
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/include/mach/vmalloc.h
@@ -0,0 +1,28 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+
+/* pay notice: we have up to (3x256M) of Dram and Vmalloc area together,
+   the dram comes on the expense of the vmalloc */
+#define VMALLOC_END       (PAGE_OFFSET + 0x30000000)
diff --git a/arch/arm/mach-feroceon-kw2/irq.c b/arch/arm/mach-feroceon-kw2/irq.c
new file mode 100755
index 0000000..cdebee0
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/irq.c
@@ -0,0 +1,172 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+
+#include <mach/hardware.h>
+#include <mach/msi.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "gpp/mvGpp.h"
+#include "mvOs.h"
+
+
+unsigned int  irq_int_type[NR_IRQS];
+
+static void mv_mask_irq(unsigned int irq)
+{
+	if(irq < 32) {
+		MV_REG_BIT_RESET(MV_IRQ_MASK_LOW_REG, (1 << irq) );
+	} else if(irq < 64) {		/* (irq > 32 && irq < 64) */
+		MV_REG_BIT_RESET(MV_IRQ_MASK_HIGH_REG, (1 << (irq - 32)) );
+	} else if(irq < 96) { /* (irq > 64 && irq < 96) */
+		MV_REG_BIT_RESET(MV_IRQ_MASK_ERROR_REG, (1 << (irq - 64)) );
+	} else if(irq < IRQ_MSI_START) {
+		MV_U32 bitmask = 1 << (irq & 0x1F);
+		MV_U32 reg = (irq - IRQ_GPP_START) >> 5;
+		MV_REG_BIT_RESET(MV_GPP_IRQ_MASK_REG(reg), bitmask);
+	} else if(irq < NR_IRQS) {
+		/* Doorbell interrupts are handled in PCIe MSI related code. */
+		printk("mv_unmask_irq: ERR, irq-%u out of scope\n",irq);
+	} else
+		printk("mv_mask_irq: ERR, irq-%u out of scope\n",irq);
+}
+
+
+static void mv_unmask_irq(unsigned int irq)
+{
+	if(irq < 32) {
+		MV_REG_BIT_SET(MV_IRQ_MASK_LOW_REG, (1 << irq) );
+	} else if(irq < 64) {	/* (irq > 32 && irq < 64) */
+		MV_REG_BIT_SET(MV_IRQ_MASK_HIGH_REG, (1 << (irq - 32)) );
+	} else if(irq < 96) { /* (irq > 64 && irq < 96) */
+		MV_REG_BIT_SET(MV_IRQ_MASK_ERROR_REG, (1 << (irq - 64)) );
+	} else if(irq < IRQ_MSI_START) {
+		MV_U32 bitmask = 1 << (irq & 0x1F);
+		MV_U32 reg = (irq - IRQ_GPP_START) >> 5;
+		MV_REG_BIT_SET(MV_GPP_IRQ_MASK_REG(reg), bitmask);
+		if (irq_int_type[irq] == GPP_IRQ_TYPE_CHANGE_LEVEL) {
+			(MV_REG_READ(MV_GPP_IRQ_POLARITY(reg)) & bitmask)?
+				MV_REG_BIT_RESET(MV_GPP_IRQ_POLARITY(reg), bitmask):
+				MV_REG_BIT_SET(MV_GPP_IRQ_POLARITY(reg), bitmask);
+		}
+	} else if(irq < NR_IRQS) {
+		/* Doorbell interrupts are handled in PCIe MSI related code. */
+		printk("mv_unmask_irq: ERR, irq-%u out of scope\n",irq);
+	} else
+		printk("mv_unmask_irq: ERR, irq-%u out of scope\n",irq);
+}
+
+struct irq_chip mv_chip = {
+	.ack	= mv_mask_irq,
+	.mask	= mv_mask_irq,
+	.unmask = mv_unmask_irq,
+};
+
+void __init mv_init_irq(void)
+{
+	u32 i;
+	MV_U32 gppMask;
+	MV_U32 maxGppGroup;
+
+	if (MV_6601_DEV_ID == mvCtrlModelGet())
+		maxGppGroup = 2;
+	else
+		maxGppGroup = 3;
+
+	/* Disable all interrupts initially. */
+	MV_REG_WRITE(MV_IRQ_MASK_LOW_REG, 0x0);
+	MV_REG_WRITE(MV_FIQ_MASK_LOW_REG, 0x0);
+	MV_REG_WRITE(MV_IRQ_MASK_HIGH_REG, 0x0);
+	MV_REG_WRITE(MV_FIQ_MASK_HIGH_REG, 0x0);
+	MV_REG_WRITE(MV_IRQ_MASK_ERROR_REG, 0x0);
+	MV_REG_WRITE(MV_FIQ_MASK_ERROR_REG, 0x0);
+
+	for(i = 0; i < maxGppGroup; i++) {
+		MV_REG_WRITE(MV_GPP_IRQ_MASK_REG(i), 0x0);
+		MV_REG_WRITE(MV_GPP_IRQ_EDGE_REG(i), 0x0);
+	}
+
+	/* Set gpp interrupts as needed */
+	for(i = 0; i < maxGppGroup; i++) {
+		gppMask = mvBoardGpioIntMaskGet(i);
+		mvGppTypeSet(i, gppMask , (MV_GPP_IN & gppMask));
+		mvGppPolaritySet(i, gppMask , (MV_GPP_IN_INVERT & gppMask));
+	}
+
+	/* enable GPP in the main mask high */
+	if (MV_6601_DEV_ID == mvCtrlModelGet()) {
+		MV_REG_BIT_SET(MV_IRQ_MASK_HIGH_REG, 
+			MV_BIT_MASK(GPP_LOW_0_7_IRQ_NUM - 32)    |
+			MV_BIT_MASK(GPP_LOW_8_15_IRQ_NUM - 32)   |
+			MV_BIT_MASK(GPP_LOW_16_23_IRQ_NUM - 32)  |
+			MV_BIT_MASK(GPP_LOW_24_31_IRQ_NUM - 32)  |
+			MV_BIT_MASK(GPP_MID_0_7_IRQ_NUM	- 32));
+	} else {
+		MV_REG_BIT_SET(MV_IRQ_MASK_HIGH_REG, 
+			MV_BIT_MASK(GPP_LOW_0_7_IRQ_NUM - 32)    |
+			MV_BIT_MASK(GPP_LOW_8_15_IRQ_NUM - 32)   |
+			MV_BIT_MASK(GPP_LOW_16_23_IRQ_NUM - 32)  |
+			MV_BIT_MASK(GPP_LOW_24_31_IRQ_NUM - 32)  |
+			MV_BIT_MASK(GPP_MID_0_7_IRQ_NUM	- 32)    |
+			MV_BIT_MASK(GPP_MID_8_15_IRQ_NUM - 32)   |
+			MV_BIT_MASK(GPP_MID_16_23_IRQ_NUM - 32)  |
+			MV_BIT_MASK(GPP_MID_24_31_IRQ_NUM - 32)  |
+			MV_BIT_MASK(GPP_HIGH_0_7_IRQ_NUM - 32)   |
+			MV_BIT_MASK(GPP_HIGH_8_15_IRQ_NUM - 32)  |
+			MV_BIT_MASK(GPP_HIGH_16_23_IRQ_NUM - 32) |
+			MV_BIT_MASK(GPP_HIGH_24_IRQ_NUM - 32));
+	}
+
+	/* clear all int */
+	MV_REG_WRITE(MV_IRQ_CAUSE_LOW_REG, 0x0);
+	MV_REG_WRITE(MV_IRQ_CAUSE_HIGH_REG, 0x0);
+	MV_REG_WRITE(MV_IRQ_CAUSE_ERROR_REG, 0x0);
+
+	for(i = 0; i < maxGppGroup; i++)
+		MV_REG_WRITE(MV_GPP_IRQ_CAUSE_REG(i), 0x0);
+
+	/* Do the core module ones */
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_chip(i, &mv_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* init GPP IRQs in default level mode*/
+	for (i = 0; i < NR_IRQS; i++)
+		irq_int_type[i] = GPP_IRQ_TYPE_LEVEL;
+
+	/* TBD. Add support for error interrupts */
+
+	kw2_msi_init();
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.c b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.c
new file mode 100755
index 0000000..cd03ca2
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.c
@@ -0,0 +1,3541 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    * 	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    * 	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "cpu/mvCpu.h"
+#include "cntmr/mvCntmr.h"
+#include "gpp/mvGpp.h"
+#include "twsi/mvTwsi.h"
+#include "pex/mvPex.h"
+#include "device/mvDevice.h"
+#include "gpp/mvGppRegs.h"
+#include "ctrlEnv/mvCtrlEthCompLib.h"
+
+#if defined(CONFIG_MV_ETH_LEGACY)
+#include "eth/gbe/mvEthGbe.h"
+#else
+#include "neta/gbe/mvNeta.h"
+#endif /* CONFIG_MV_ETH_LEGACY or CONFIG_MV_ETH_NETA */
+
+/* defines  */
+/* #define MV_DEBUG */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+extern MV_CPU_ARM_CLK _cpuARMDDRCLK[];
+
+
+extern MV_BOARD_INFO *boardInfoTbl[];
+#define BOARD_INFO(boardId)	boardInfoTbl[boardId - BOARD_ID_BASE]
+
+/* Locals */
+static MV_DEV_CS_INFO *boardGetDevEntry(MV_32 devNum, MV_BOARD_DEV_CLASS devClass);
+
+MV_U32 tClkRate = -1;
+
+#define MV_BRD_MODULE_CFG_BUILD(ethCfg, tdmCfg)	((tdmCfg << 24) | ethCfg)
+#define MV_BRD_MODULE_CFG_ETH_GET(config)	(config & 0xFFFFFF)
+#define MV_BRD_MODULE_CFG_TDM_GET(config)	(MV_8)(config >> 24)
+
+static MV_BOOL mvBoardStaticModuleConfig = MV_FALSE;
+static MV_U32 mvBoardModuleConfig = 0;
+
+/*******************************************************************************
+* mvBoardEnvInit - Init board
+*
+* DESCRIPTION:
+*		In this function the board environment take care of device bank
+*		initialization.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvBoardEnvInit(MV_VOID)
+{
+	MV_U32 boardId = mvBoardIdGet();
+	MV_U32 nandDev;
+	MV_32 width;
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardEnvInit:Board unknown.\n");
+		return;
+	}
+	nandDev = boardGetDevCSNum(0, BOARD_DEV_NAND_FLASH);
+	if (nandDev != 0xFFFFFFFF) {
+		/* Set NAND interface access parameters */
+		nandDev = BOOT_CS;
+		if (BOARD_INFO(boardId)->nandFlashParamsValid == MV_TRUE) {
+			MV_REG_WRITE(DEV_BANK_PARAM_REG(nandDev), BOARD_INFO(boardId)->nandFlashReadParams);
+			MV_REG_WRITE(DEV_BANK_PARAM_REG_WR(nandDev), BOARD_INFO(boardId)->nandFlashWriteParams);
+			MV_REG_WRITE(DEV_NAND_CTRL_REG, BOARD_INFO(boardId)->nandFlashControl);
+		}
+	}
+
+	width = mvBoardGetDeviceWidth(0, BOARD_DEV_NOR_FLASH);
+	if (width != 0xFFFFFFFF)
+		mvDevWidthSet(BOOT_CS, width);
+
+	/* Set GPP Out value */
+	MV_REG_WRITE(GPP_DATA_OUT_REG(0), BOARD_INFO(boardId)->gppOutValLow);
+	MV_REG_WRITE(GPP_DATA_OUT_REG(1), BOARD_INFO(boardId)->gppOutValMid);
+	if ((boardId != DB_88F6601_BP_ID) && (boardId != RD_88F6601_MC_ID))
+		MV_REG_WRITE(GPP_DATA_OUT_REG(2), BOARD_INFO(boardId)->gppOutValHigh);
+
+	/* set GPP polarity */
+	mvGppPolaritySet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValLow);
+	mvGppPolaritySet(1, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValMid);
+	if ((boardId != DB_88F6601_BP_ID) && (boardId != RD_88F6601_MC_ID))
+		mvGppPolaritySet(2, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValHigh);
+
+	/* Set GPP Out Enable */
+	mvGppTypeSet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValLow);
+	mvGppTypeSet(1, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValMid);
+	if ((boardId != DB_88F6601_BP_ID) && (boardId != RD_88F6601_MC_ID))
+		mvGppTypeSet(2, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValHigh);
+
+	/* Nand CE */
+#if 0
+	if (nandDev != 0xFFFFFFFF)
+		mvDevNandDevCsSet(nandDev, MV_TRUE);
+#endif
+}
+
+/*******************************************************************************
+* mvBoardModelGet - Get Board model
+*
+* DESCRIPTION:
+*       This function returns 16bit describing board model.
+*       Board model is constructed of one byte major and minor numbers in the
+*       following manner:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       String describing board model.
+*
+*******************************************************************************/
+MV_U16 mvBoardModelGet(MV_VOID)
+{
+	return (mvBoardIdGet() >> 16);
+}
+
+/*******************************************************************************
+* mbBoardRevlGet - Get Board revision
+*
+* DESCRIPTION:
+*       This function returns a 32bit describing the board revision.
+*       Board revision is constructed of 4bytes. 2bytes describes major number
+*       and the other 2bytes describes minor munber.
+*       For example for board revision 3.4 the function will return
+*       0x00030004.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       String describing board model.
+*
+*******************************************************************************/
+MV_U16 mvBoardRevGet(MV_VOID)
+{
+	return (mvBoardIdGet() & 0xFFFF);
+}
+
+/*******************************************************************************
+* mvBoardNameGet - Get Board name
+*
+* DESCRIPTION:
+*       This function returns a string describing the board model and revision.
+*       String is extracted from board I2C EEPROM.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       pNameBuff - Buffer to contain board name string. Minimum size 32 chars.
+*
+* RETURN:
+*
+*       MV_ERROR if informantion can not be read.
+*******************************************************************************/
+MV_STATUS mvBoardNameGet(char *pNameBuff)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsSPrintf(pNameBuff, "Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	mvOsSPrintf(pNameBuff, "%s", BOARD_INFO(boardId)->boardName);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvBoardSpecInitGet -
+*
+* DESCRIPTION:
+*       This routine returns the board specific initializtion information.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       A pointer to the array holding the board specific initializations.
+*
+*******************************************************************************/
+MV_BOARD_SPEC_INIT *mvBoardSpecInitGet(MV_VOID)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSpecInitGet: Board unknown.\n");
+		return NULL;
+	}
+
+	return BOARD_INFO(boardId)->pBoardSpecInit;
+}
+
+/*******************************************************************************
+* mvBoardPwrUpDelayGet -
+*
+* DESCRIPTION:
+*       This routine returns the power up delay in clock cycles.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       The power up delay or 0 in case of failure.
+*
+*******************************************************************************/
+MV_U32 mvBoardPwrUpDelayGet(MV_VOID)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardPwrUpDelayGet: Board unknown.\n");
+		return 0;
+	}
+
+	return BOARD_INFO(boardId)->deepIdlePwrUpDelay;
+}
+
+
+/*******************************************************************************
+* mvBoardIsPortInSgmii -
+*
+* DESCRIPTION:
+*       This routine returns MV_TRUE for port number works in SGMII or MV_FALSE
+*	For all other options.
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE - port in SGMII.
+*       MV_FALSE - other.
+*
+*******************************************************************************/
+MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum)
+{
+	MV_U32 ethCompOpt;
+
+	if (ethPortNum >= BOARD_ETH_PORT_NUM) {
+		mvOsPrintf("Invalid portNo=%d\n", ethPortNum);
+		return MV_FALSE;
+	}
+	ethCompOpt = mvBoardEthComplexConfigGet();
+	if (DB_88F6601_BP_ID == mvBoardIdGet()) {
+		if (ethPortNum == 0) {
+			if (ethCompOpt & ESC_OPT_GEPHY_MAC0)
+				return MV_FALSE;
+			return MV_TRUE;
+		}
+		if (ethCompOpt & ESC_OPT_GEPHY_MAC0)
+			return MV_TRUE;
+		return MV_FALSE;
+	}
+	if (RD_88F6601_MC_ID == mvBoardIdGet())
+		return MV_FALSE;
+
+	if ((ethPortNum > 0) || (ethCompOpt & ESC_OPT_SGMII_2_SW_P1))
+		return MV_FALSE;
+
+	return ((ethCompOpt & (ESC_OPT_SGMII | ESC_OPT_SGMII_2_5)) ? MV_TRUE : MV_FALSE);
+}
+
+/*******************************************************************************
+* mvBoardIsPortInRgmii -
+*
+* DESCRIPTION:
+*       This routine returns MV_TRUE for port number works in RGMII or MV_FALSE
+*	for all other options.
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE - port in RGMII.
+*       MV_FALSE - other.
+*
+*******************************************************************************/
+MV_BOOL mvBoardIsPortInRgmii(MV_U32 ethPortNum)
+{
+	MV_U32 ethCompOpt;
+
+	if (ethPortNum >= BOARD_ETH_PORT_NUM) {
+		mvOsPrintf("Invalid portNo=%d\n", ethPortNum);
+		return MV_FALSE;
+	}
+
+	ethCompOpt = mvBoardEthComplexConfigGet();
+
+	if (ethPortNum == 0)
+		return (ethCompOpt & (ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIB_MAC0)) ? MV_TRUE : MV_FALSE;
+	else if (ethPortNum == 1)
+		return (ethCompOpt & ESC_OPT_RGMIIA_MAC1) ? MV_TRUE : MV_FALSE;
+	else
+		return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvBoardEthPortsModeGet -
+*
+* DESCRIPTION:
+*       This routine returns a bitmask of the ethernet ports MAC mode (RGMII /
+*	MII ...).
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Bitmask of ethernet ports mode.
+*
+*******************************************************************************/
+MV_U32 mvBoardEthPortsModeGet(void)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardPhyAddrGet: Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	return BOARD_INFO(boardId)->pBoardMppTypeValue->ethPortsMode;
+}
+
+#if 0
+/*******************************************************************************
+* mvBoardIsPortInGmii -
+*
+* DESCRIPTION:
+*       This routine returns MV_TRUE for port number works in GMII or MV_FALSE
+*	For all other options.
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE - port in GMII.
+*       MV_FALSE - other.
+*
+*******************************************************************************/
+MV_BOOL mvBoardIsPortInGmii(MV_VOID)
+{
+	MV_U32 devClassId, devClass = 0;
+	if (mvBoardMppGroupTypeGet(devClass) == MV_BOARD_AUTO) {
+		/* Get MPP module ID */
+		devClassId = mvBoarModuleTypeGet(devClass);
+		if (MV_BOARD_MODULE_GMII_ID == devClassId)
+			return MV_TRUE;
+	} else if (mvBoardMppGroupTypeGet(devClass) == MV_BOARD_GMII)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+#endif /* 0 */
+
+/*******************************************************************************
+* mvBoardPhyAddrGet - Get the phy address
+*
+* DESCRIPTION:
+*       This routine returns the Phy address of a given ethernet port.
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit describing Phy address, -1 if the port number is wrong.
+*
+*******************************************************************************/
+MV_32 mvBoardPhyAddrGet(MV_U32 ethPortNum)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardPhyAddrGet: Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	return BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardEthSmiAddr;
+}
+
+/*******************************************************************************
+* mvBoardPhyAddrSet
+*
+* DESCRIPTION:
+*       Set the PHY address for a given ethernet port in the board
+*	specification structure.
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*	phyAddr - The PHY address to set.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success.
+*
+*******************************************************************************/
+MV_STATUS mvBoardPhyAddrSet(MV_U32 ethPortNum, MV_32 phyAddr)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardPhyAddrGet: Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardEthSmiAddr = phyAddr;
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvBoardMacSpeedGet - Get the Mac speed
+*
+* DESCRIPTION:
+*       This routine returns the Mac speed if pre define of a given ethernet port.
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BOARD_MAC_SPEED, -1 if the port number is wrong.
+*
+*******************************************************************************/
+MV_BOARD_MAC_SPEED mvBoardMacSpeedGet(MV_U32 ethPortNum)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardMacSpeedGet: Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	if (ethPortNum >= BOARD_INFO(boardId)->numBoardMacInfo) {
+		mvOsPrintf("mvBoardMacSpeedGet: illegal port number\n");
+		return MV_ERROR;
+	}
+
+	return BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardMacSpeed;
+}
+
+/*******************************************************************************
+* mvBoardMacSpeedSet
+*
+* DESCRIPTION:
+*       This routine sets the Mac speed of a given ethernet port.
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*	speed - Port speed to be set.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success.
+*
+*******************************************************************************/
+MV_STATUS mvBoardMacSpeedSet(MV_U32 ethPortNum, MV_BOARD_MAC_SPEED speed)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardMacSpeedGet: Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardMacSpeed = speed;
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvBoardIsInternalSwitchConnected
+*
+* DESCRIPTION:
+*       This routine returns port's connection status
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       1 - if ethPortNum is connected to switch, 0 otherwise
+*
+*******************************************************************************/
+MV_STATUS mvBoardIsInternalSwitchConnected(MV_U32 ethPortNum)
+{
+	MV_U32 boardId = mvBoardIdGet();
+	MV_U32 ethCompOpt;
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardIsInternalSwitchConnected: Board unknown.\n");
+		return MV_FALSE;
+	}
+
+	if (ethPortNum >= BOARD_INFO(boardId)->numBoardMacInfo) {
+		mvOsPrintf("mvBoardIsSwitchConnected: Illegal port number(%u)\n", ethPortNum);
+		return MV_FALSE;
+	}
+
+	/* Check if internal switch is connected */
+	ethCompOpt = mvBoardEthComplexConfigGet();
+	if ((ethPortNum == 0) && (ethCompOpt & ESC_OPT_MAC0_2_SW_P4))
+		return MV_TRUE;
+	else if ((ethPortNum == 1) && (ethCompOpt & ESC_OPT_MAC1_2_SW_P5))
+		return MV_TRUE;
+	else
+		return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvBoardSwitchNumPortsGet
+*
+* DESCRIPTION:
+*       This routine returns the number of switch ports.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Number of switch ports, 0 - if no switch is connected.
+*
+*******************************************************************************/
+MV_32 mvBoardSwitchNumPortsGet(MV_VOID)
+{
+	MV_U32 boardId = mvBoardIdGet();
+	MV_U32 ethCompOpt;
+	MV_U32 numPorts = 0;
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSwitchNumPortsGet: Board unknown.\n");
+		return MV_ERROR;
+	}
+	if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId))
+	{
+		return 0;
+	}
+
+
+	/* Check if internal switch is connected */
+	ethCompOpt = mvBoardEthComplexConfigGet();
+
+	if (ethCompOpt & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5)) {
+		if (ethCompOpt & ESC_OPT_FE3PHY)
+			numPorts += 3;
+		if (ethCompOpt & ESC_OPT_QSGMII)
+			numPorts += 4;
+		if (ethCompOpt & (ESC_OPT_GEPHY_SW_P0 | ESC_OPT_GEPHY_SW_P5))
+			numPorts += 1;
+		if (ethCompOpt & (ESC_OPT_RGMIIA_SW_P5 | ESC_OPT_RGMIIA_SW_P6))
+			numPorts += 1;
+		if (ethCompOpt & ESC_OPT_SGMII_2_SW_P1)
+			numPorts += 1;
+	}
+
+	return numPorts;
+}
+
+/*******************************************************************************
+* mvBoardIsQsgmiiModuleConnected
+*
+* DESCRIPTION:
+*       This routine returns whether the QSGMII module is connected or not.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if QSGMII module is connected, MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_BOOL mvBoardIsQsgmiiModuleConnected(MV_VOID)
+{
+	MV_U32 ethCompOpt;
+
+	/* Check if internal switch is connected */
+	ethCompOpt = mvBoardEthComplexConfigGet();
+
+	if (ethCompOpt & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5)) {
+		if (ethCompOpt & ESC_OPT_QSGMII)
+			return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvBoardGePhySwitchPortGet
+*
+* DESCRIPTION:
+*       This routine returns whether the internal GE PHY is connected to
+*	Switch Port 0, Switch port 5 or not connected to any Switch port.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       0 if the internal GE PHY is connected to Switch Port 0,
+*	5 if the internal GE PHY is connected to Switch Port 5,
+*	-1 otherwise.
+*
+*******************************************************************************/
+MV_32 mvBoardGePhySwitchPortGet(MV_VOID)
+{
+	MV_U32 ethCompOpt;
+
+	/* Check if internal switch is connected */
+	ethCompOpt = mvBoardEthComplexConfigGet();
+	if (ethCompOpt & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5)) {
+		if (ethCompOpt & ESC_OPT_GEPHY_SW_P0)
+			return 0;
+		if (ethCompOpt & ESC_OPT_GEPHY_SW_P5)
+			return 5;
+	}
+	return -1;
+}
+
+/*******************************************************************************
+* mvBoardRgmiiASwitchPortGet
+*
+* DESCRIPTION:
+*       This routine returns whether RGMII-A is connected to
+*	Switch Port 5, Switch port 6 or not connected to any Switch port.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       5 if the internal GE PHY is connected to Switch Port 5,
+*	6 if the internal GE PHY is connected to Switch Port 6,
+*	-1 otherwise.
+*
+*******************************************************************************/
+MV_32 mvBoardRgmiiASwitchPortGet(MV_VOID)
+{
+	MV_U32 ethCompOpt;
+
+	/* Check if internal switch is connected */
+	ethCompOpt = mvBoardEthComplexConfigGet();
+	if (ethCompOpt & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5)) {
+		if (ethCompOpt & ESC_OPT_RGMIIA_SW_P5)
+			return 5;
+		if (ethCompOpt & ESC_OPT_RGMIIA_SW_P6)
+			return 6;
+	}
+	return -1;
+}
+
+/*******************************************************************************
+* mvBoardSwitchInfoUpdate
+*
+* DESCRIPTION:
+*	Update switch information structure according to modules detection
+*	result.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK - on success,
+*	MV_ERROR - On failure.
+*
+*******************************************************************************/
+MV_STATUS mvBoardSwitchInfoUpdate(MV_VOID)
+{
+	MV_U32 boardId = mvBoardIdGet();
+	MV_U32 ethCompOpt;
+	MV_U32 i;
+	MV_U32 swIdx = 0;
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSwitchInfoUpdate: Board unknown.\n");
+		return MV_ERROR;
+	}
+    if (MV_6601_DEV_ID == mvCtrlModelGet()){ /* no switch on A-MC */
+		BOARD_INFO(boardId)->switchInfoNum = 0;
+			return MV_OK;
+	}
+
+	if (!mvBoardModuleAutoDetectEnabled())
+		return MV_OK;
+
+	if ((!mvBoardIsInternalSwitchConnected(0)) && (!mvBoardIsInternalSwitchConnected(1))) {
+		BOARD_INFO(boardId)->switchInfoNum = 0;
+		return MV_OK;
+	}
+
+	ethCompOpt = mvBoardEthComplexConfigGet();
+
+	/* Update the cpuPort & connectedPort fields */
+	BOARD_INFO(boardId)->pSwitchInfo[swIdx].cpuPort = -1;
+	for (i = 0; i < MV_ETH_MAX_PORTS; i++)
+		BOARD_INFO(boardId)->pSwitchInfo[swIdx].connectedPort[i] = -1;
+
+	/* Check if port 4 connected to MAC0 */
+	if (ethCompOpt & ESC_OPT_MAC0_2_SW_P4) {
+		BOARD_INFO(boardId)->pSwitchInfo[swIdx].cpuPort = 4;
+		BOARD_INFO(boardId)->pSwitchInfo[swIdx].connectedPort[0] = 4;
+	}
+
+	/* Check if port 5 connected to MAC1 */
+	if (ethCompOpt & ESC_OPT_MAC1_2_SW_P5) {
+		BOARD_INFO(boardId)->pSwitchInfo[swIdx].cpuPort = 5;
+		BOARD_INFO(boardId)->pSwitchInfo[swIdx].connectedPort[1] = 5;
+	}
+
+	i = 0;
+	if (ethCompOpt & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5)) {
+
+		if (ethCompOpt & ESC_OPT_QSGMII) {
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[0] = 0;
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[1] = 1;
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[2] = 2;
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[3] = 3;
+			i = 4;
+		} else if (ethCompOpt & ESC_OPT_FE3PHY) {
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[0] = 1;
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[1] = 2;
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[2] = 3;
+			i = 3;
+		}
+		else if (ethCompOpt & ESC_OPT_SGMII_2_SW_P1) {
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[0] = 1;
+			i = 1;
+		}
+
+		if (ethCompOpt & ESC_OPT_GEPHY_SW_P0)
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[i++] = 0;
+		else if (ethCompOpt & ESC_OPT_GEPHY_SW_P5)
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[i++] = 5;
+
+		if (ethCompOpt & ESC_OPT_RGMIIA_SW_P6)
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[i++] = 6;
+	}
+
+
+	/* Set all unused switch ports to -1 */
+	for (; i < BOARD_ETH_SWITCH_PORT_NUM; i++)
+		BOARD_INFO(boardId)->pSwitchInfo[swIdx].switchPort[i] = -1;
+
+	/* Set number of switch entries */
+	BOARD_INFO(boardId)->switchInfoNum = 1;
+
+	if (mvBoardSwitchSnglChipAddModeGet() == MV_TRUE) {
+		/* Set switch access mode according to number of SMI clients. */
+		if (!(ethCompOpt & (ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIA_MAC1 |
+				ESC_OPT_RGMIIB_MAC0 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_SGMII | ESC_OPT_SGMII_2_5))) {
+			BOARD_INFO(boardId)->pSwitchInfo[swIdx].smiScanMode = 1;
+			/* Set switch PHY address to 0x0 to indicate single-address
+			** mode.
+			*/
+			if (ethCompOpt & ESC_OPT_MAC0_2_SW_P4)
+				mvBoardPhyAddrSet(0, 0x0);
+			else if (ethCompOpt & ESC_OPT_MAC1_2_SW_P5)
+				mvBoardPhyAddrSet(1, 0x0);
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvBoardSwitchSnlgChipAddModeGet
+*
+* DESCRIPTION:
+*	Check if this board enables single-chip address mode for switch registers
+*	access.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_TRUE - If single-chip address mode is enabled.
+*	MV_FALSE - If disabled.
+*
+*******************************************************************************/
+MV_BOOL mvBoardSwitchSnglChipAddModeGet(MV_VOID)
+{
+	MV_U8 temp;
+
+	temp = mvBoardTwsiSatRGet(MV_BOARD_SWITCH_SCAN_MODE_SATR_IDX, 1);
+	if (MV_BOARD_SWITCH_SCAN_MODE(temp))
+		return MV_TRUE;
+	else
+		return MV_FALSE;
+}
+
+
+/*******************************************************************************
+* mvBoardSwitchSnglChipAddModeSet
+*
+* DESCRIPTION:
+*	Enabled / Disable single-chip address mode for switch registers access.
+*
+* INPUT:
+*       enable - MV_TRUE to enable, MV_FALSE to disable.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvBoardSwitchSnglChipAddModeSet(MV_BOOL enable)
+{
+	MV_U8 temp;
+
+	temp = mvBoardTwsiSatRGet(MV_BOARD_SWITCH_SCAN_MODE_SATR_IDX, 1);
+	temp &= ~MV_BOARD_SWITCH_SCAN_MODE_MASK;
+	if (enable == MV_TRUE)
+		temp |= 1;
+
+	return mvBoardTwsiSatRSet(MV_BOARD_SWITCH_SCAN_MODE_SATR_IDX, 1, temp);
+}
+
+
+/*******************************************************************************
+* mvBoardSwitchIrqGet - Get the IRQ number for the link status indication
+*
+* DESCRIPTION:
+*       This routine returns the IRQ number for the link status indication.
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	the number of the IRQ for the link status indication, -1 if the port
+*	number is wrong or if not relevant.
+*
+*******************************************************************************/
+MV_32 mvBoardSwitchIrqGet(MV_VOID)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardLinkStatusIrqGet: Board unknown.\n");
+		return -1;
+	}
+	if (BOARD_INFO(boardId)->switchInfoNum == 0)
+		return -1;
+
+	return BOARD_INFO(boardId)->pSwitchInfo[0].switchIrq;
+}
+
+/*******************************************************************************
+* mvBoardSwitchConnectedPortGet -
+*
+* DESCRIPTION:
+*       This routine returns the switch port connected to the ethPort
+*
+* INPUT:
+*       ethPortNum - Ethernet port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_32 mvBoardSwitchConnectedPortGet(MV_U32 ethPort)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSwitchConnectedPortGet: Board unknown.\n");
+		return -1;
+	}
+	if (BOARD_INFO(boardId)->switchInfoNum == 0)
+		return -1;
+
+	return BOARD_INFO(boardId)->pSwitchInfo[0].connectedPort[ethPort];
+}
+
+/*******************************************************************************
+* mvBoardSwitchPortGet - Get the mapping between the board connector and the
+*                        Ethernet Switch port
+*
+* DESCRIPTION:
+*       This routine returns the matching Switch port.
+*
+* INPUT:
+*	    boardPortNum - logical number of the connector on the board
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       the matching Switch port, -1 if the port number is wrong or if not relevant.
+*
+*******************************************************************************/
+MV_32 mvBoardSwitchPortGet(MV_U32 switchIdx, MV_U32 boardPortNum)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSwitchPortGet: Board unknown.\n");
+		return -1;
+	}
+	if (boardPortNum >= BOARD_ETH_SWITCH_PORT_NUM) {
+		mvOsPrintf("mvBoardSwitchPortGet: Illegal board port number.\n");
+		return -1;
+	}
+	if ((BOARD_INFO(boardId)->switchInfoNum == 0) || (switchIdx >= BOARD_INFO(boardId)->switchInfoNum))
+		return -1;
+
+	return BOARD_INFO(boardId)->pSwitchInfo[switchIdx].switchPort[boardPortNum];
+}
+
+/*******************************************************************************
+* mvBoardSwitchPortMap
+*
+* DESCRIPTION:
+*	Map front panel connector number to switch port number.
+*
+* INPUT:
+*	switchIdx - The switch index.
+*	switchPortNum - The switch port number to get the mapping for.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	The switch port mapping.
+*	OR -1 if the port number is wrong or if not relevant.
+*
+*******************************************************************************/
+MV_32 mvBoardSwitchPortMap(MV_U32 switchIdx, MV_U32 switchPortNum)
+{
+	int i;
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSwitchPortMap: Board unknown.\n");
+		return -1;
+	}
+	if ((BOARD_INFO(boardId)->switchInfoNum == 0) || (switchIdx >= BOARD_INFO(boardId)->switchInfoNum))
+		return -1;
+
+	for (i = 0; i < BOARD_ETH_SWITCH_PORT_NUM; i++) {
+		if (BOARD_INFO(boardId)->pSwitchInfo[switchIdx].switchPort[i] == switchPortNum)
+			return i;
+	}
+	return -1;
+}
+
+/*******************************************************************************
+* mvBoardSwitchCpuPortGet - Get the the Ethernet Switch CPU port
+*
+* DESCRIPTION:
+*       This routine returns the Switch CPU port.
+*
+* INPUT:
+*       switchIdx - index of the switch. Only 0 is supported.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       the Switch CPU port, -1 if the switch is not connected.
+*
+*******************************************************************************/
+MV_32 mvBoardSwitchCpuPortGet(MV_U32 switchIdx)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSwitchCpuPortGet: Board unknown.\n");
+		return -1;
+	}
+	if ((BOARD_INFO(boardId)->switchInfoNum == 0) || (switchIdx >= BOARD_INFO(boardId)->switchInfoNum))
+		return -1;
+
+	return BOARD_INFO(boardId)->pSwitchInfo[switchIdx].cpuPort;
+}
+
+
+/*******************************************************************************
+* mvBoardSwitchPortForceLinkGet
+*
+* DESCRIPTION:
+*       Return the switch ports force link bitmask.
+*
+* INPUT:
+*       switchIdx - index of the switch. Only 0 is supported.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       the ports bitmask, -1 if the switch is not connected.
+*
+*******************************************************************************/
+MV_U32 mvBoardSwitchPortForceLinkGet(MV_U32 switchIdx)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSwitchCpuPortGet: Board unknown.\n");
+		return -1;
+	}
+	if ((BOARD_INFO(boardId)->switchInfoNum == 0) || (switchIdx >= BOARD_INFO(boardId)->switchInfoNum))
+		return -1;
+
+	return BOARD_INFO(boardId)->pSwitchInfo[switchIdx].forceLinkMask;
+}
+
+/*******************************************************************************
+* mvBoardSmiScanModeGet - Get Switch SMI scan mode
+*
+* DESCRIPTION:
+*       This routine returns Switch SMI scan mode.
+*
+* INPUT:
+*       switchIdx - index of the switch. Only 0 is supported.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       1 for SMI_MANUAL_MODE, -1 if the port number is wrong or if not relevant.
+*
+*******************************************************************************/
+MV_32 mvBoardSmiScanModeGet(MV_U32 switchIdx)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardSmiScanModeGet: Board unknown.\n");
+		return -1;
+	}
+	if ((BOARD_INFO(boardId)->switchInfoNum == 0) || (switchIdx >= BOARD_INFO(boardId)->switchInfoNum))
+		return -1;
+
+	return BOARD_INFO(boardId)->pSwitchInfo[switchIdx].smiScanMode;
+}
+
+/*******************************************************************************
+* mvBoardQuadPhyAddrGet - Get QUAD phy SMI address.
+*
+* DESCRIPTION:
+*       This routine returns the external QUAD phy address.
+*
+* INPUT:
+*       switchIdx - index of the switch. Only 0 is supported.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       The QUAD phy start address or -1 if error.
+*
+*******************************************************************************/
+MV_32 mvBoardQuadPhyAddrGet(MV_U32 switchIdx)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardQuadPhyAddrGet: Board unknown.\n");
+		return -1;
+	}
+
+	if ((BOARD_INFO(boardId)->switchInfoNum == 0) || (switchIdx >= BOARD_INFO(boardId)->switchInfoNum))
+		return -1;
+
+	return BOARD_INFO(boardId)->pSwitchInfo[switchIdx].quadPhyAddr;
+
+}
+
+/*******************************************************************************
+* mvBoardPhySpecInitGet -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN: Return MV_TRUE and parameters in case board need spesific phy init,
+*        otherwise return MV_FALSE.
+*
+*
+*******************************************************************************/
+MV_BOOL mvBoardPhySpecInitGet(MV_U32 *regOff, MV_U32 *data)
+{
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvBoardTclkGet - Get the board Tclk (Controller clock)
+*
+* DESCRIPTION:
+*       This routine extract the controller core clock.
+*       This function uses the controller counters to make identification.
+*		Note: In order to avoid interference, make sure task context switch
+*		and interrupts will not occure during this function operation
+*
+* INPUT:
+*       countNum - Counter number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit clock cycles in Hertz.
+*
+*******************************************************************************/
+MV_U32 mvBoardTclkGet(MV_VOID)
+{
+#if defined(TCLK_AUTO_DETECT)
+	MV_U32 tmpTClkRate = MV_BOARD_TCLK_166MHZ;
+	MV_U32 boardId = mvBoardIdGet();
+
+	tmpTClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
+	if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)){
+		tmpTClkRate &= MSAR_TCLCK_6601_MASK;
+		if (tmpTClkRate ) 
+			return MV_BOARD_TCLK_200MHZ;
+		else
+			return MV_BOARD_TCLK_166MHZ;
+	} else {
+		tmpTClkRate &= MSAR_TCLCK_MASK;
+
+		switch (tmpTClkRate) {
+		case MSAR_TCLCK_166:
+			return MV_BOARD_TCLK_166MHZ;
+			break;
+		case MSAR_TCLCK_200:
+			return MV_BOARD_TCLK_200MHZ;
+			break;
+		default:
+			return -1;
+		}
+	}
+#else
+	return MV_BOARD_TCLK_200MHZ;
+#endif
+}
+
+/*******************************************************************************
+* mvBoardSysClkGet - Get the board SysClk (CPU bus clock)
+*
+* DESCRIPTION:
+*       This routine extract the CPU bus clock.
+*
+* INPUT:
+*       countNum - Counter number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit clock cycles in Hertz.
+*
+*******************************************************************************/
+MV_U32 mvBoardSysClkGet(MV_VOID)
+{
+#ifdef SYSCLK_AUTO_DETECT
+	MV_U32 i, res = -1;
+	MV_U32 sar0;
+	MV_U32 clockSatr;
+	MV_CPU_ARM_CLK cpuDdrL2Tbl[] = MV_CPU_DDR_L2_CLCK_TBL;
+	MV_CPU_ARM_CLK cpuDdrTbl6601[] = MV6601_CPU_DDR_CLCK_TBL;
+	MV_U32 boardId = mvBoardIdGet();
+
+	/* Read S@R registers value */
+	sar0 = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
+	clockSatr = MSAR_CPU_DDR_L2_CLCK_EXTRACT(sar0);
+	i = 0;
+	if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)){
+		while (cpuDdrTbl6601[i].satrValue != -1) {
+			if (cpuDdrTbl6601[i].satrValue == clockSatr) {
+				res = i;
+				break;
+			}
+			i++;
+		}
+		if (res == 0xFFFFFFFF)
+			return 0;
+		else
+			return cpuDdrTbl6601[i].ddrClk;
+	} else {
+
+		/* Search for a matching entry */
+		while (cpuDdrL2Tbl[i].satrValue != -1) {
+			if (cpuDdrL2Tbl[i].satrValue == clockSatr) {
+				res = i;
+				break;
+			}
+			i++;
+		}
+		if (res == 0xFFFFFFFF)
+			return 0;
+		else
+			return cpuDdrL2Tbl[i].ddrClk;
+	}
+#else
+	return MV_BOARD_DEFAULT_SYSCLK;
+#endif
+}
+
+/*******************************************************************************
+* mvBoardDebugLedNumGet - Get number of debug Leds
+*
+* DESCRIPTION:
+* INPUT:
+*       boardId
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_U32 mvBoardDebugLedNumGet(MV_U32 boardId)
+{
+	return BOARD_INFO(boardId)->activeLedsNumber;
+}
+
+/*******************************************************************************
+* mvBoardDebugLeg - Set the board debug Leds
+*
+* DESCRIPTION: turn on/off status leds.
+*
+*
+* INPUT:
+*       hexNum - Number to be displied in hex by Leds.
+*		 Note: assuming all debug leds reside within same group.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvBoardDebugLed(MV_U32 hexNum)
+{
+	MV_U32 val = 0, totalMask, currentBitMask = 1, i;
+	MV_U8 group = 0;
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (BOARD_INFO(boardId)->pLedGppPin == NULL)
+		return;
+
+	totalMask = (1 << BOARD_INFO(boardId)->activeLedsNumber) - 1;
+	hexNum &= totalMask;
+	totalMask = 0;
+	group = (BOARD_INFO(boardId)->pLedGppPin[0] / 32);
+
+	for (i = 0; i < BOARD_INFO(boardId)->activeLedsNumber; i++) {
+		if (hexNum & currentBitMask)
+			val |= (1 << (BOARD_INFO(boardId)->pLedGppPin[i] % 32));
+		totalMask |= (1 << (BOARD_INFO(boardId)->pLedGppPin[i] % 32));
+		currentBitMask = (currentBitMask << 1);
+	}
+
+	if (BOARD_INFO(boardId)->ledsPolarity)
+		mvGppValueSet(group, totalMask, val);
+	else
+		mvGppValueSet(group, totalMask, ~val);
+}
+
+/*******************************************************************************
+* mvBoarGpioPinGet - mvBoarGpioPinGet
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		gppClass - MV_BOARD_GPP_CLASS enum.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       GPIO pin number. The function return -1 for bad parameters.
+*
+*******************************************************************************/
+MV_32 mvBoarGpioPinNumGet(MV_BOARD_GPP_CLASS gppClass, MV_U32 index)
+{
+	MV_U32 boardId, i;
+	MV_U32 indexFound = 0;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardRTCGpioPinGet:Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	for (i = 0; i < BOARD_INFO(boardId)->numBoardGppInfo; i++) {
+		if (BOARD_INFO(boardId)->pBoardGppInfo[i].devClass == gppClass) {
+			if (indexFound == index)
+				return (MV_U32) BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum;
+			indexFound++;
+		}
+	}
+	return MV_ERROR;
+}
+
+/*******************************************************************************
+* mvBoardReset - mvBoardReset
+*
+* DESCRIPTION:
+*			Reset the board
+* INPUT:
+*		None.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvBoardReset(MV_VOID)
+{
+	MV_32 resetPin;
+
+	/* Get gpp reset pin if define */
+	resetPin = mvBoardResetGpioPinGet();
+	if (resetPin != MV_ERROR) {
+		MV_REG_BIT_RESET(GPP_DATA_OUT_REG(0), (1 << resetPin));
+		MV_REG_BIT_RESET(GPP_DATA_OUT_EN_REG(0), (1 << resetPin));
+	} else {
+		/* No gpp reset pin was found, try to reset ussing
+		 ** system reset out */
+		MV_REG_BIT_SET(CPU_RSTOUTN_MASK_REG, BIT2);
+		MV_REG_BIT_SET(CPU_SYS_SOFT_RST_REG, BIT0);
+	}
+}
+
+/*******************************************************************************
+* mvBoardResetGpioPinGet - mvBoardResetGpioPinGet
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		None.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       GPIO pin number. The function return -1 for bad parameters.
+*
+*******************************************************************************/
+MV_32 mvBoardResetGpioPinGet(MV_VOID)
+{
+	return mvBoarGpioPinNumGet(BOARD_GPP_RESET, 0);
+}
+
+/*******************************************************************************
+* mvBoardSDIOGpioPinGet - mvBoardSDIOGpioPinGet
+*
+* DESCRIPTION:
+*	used for hotswap detection
+* INPUT:
+*	type - Type of SDIO GPP to get.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       GPIO pin number. The function return -1 for bad parameters.
+*
+*******************************************************************************/
+MV_32 mvBoardSDIOGpioPinGet(MV_BOARD_GPP_CLASS type)
+{
+	if ((type != BOARD_GPP_SDIO_POWER) && (type != BOARD_GPP_SDIO_DETECT) && (type != BOARD_GPP_SDIO_WP))
+		return MV_FAIL;
+
+	return mvBoarGpioPinNumGet(type, 0);
+}
+
+/*******************************************************************************
+* mvBoardUSBVbusGpioPinGet - return Vbus input GPP
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		int  devNo.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       GPIO pin number. The function return -1 for bad parameters.
+*
+*******************************************************************************/
+MV_32 mvBoardUSBVbusGpioPinGet(MV_32 devId)
+{
+	return mvBoarGpioPinNumGet(BOARD_GPP_USB_VBUS, devId);
+}
+
+/*******************************************************************************
+* mvBoardUSBVbusEnGpioPinGet - return Vbus Enable output GPP
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		int  devNo.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       GPIO pin number. The function return -1 for bad parameters.
+*
+*******************************************************************************/
+MV_32 mvBoardUSBVbusEnGpioPinGet(MV_32 devId)
+{
+	return mvBoarGpioPinNumGet(BOARD_GPP_USB_VBUS_EN, devId);
+}
+
+/*******************************************************************************
+* mvBoardGpioIntMaskGet - Get GPIO mask for interrupt pins
+*
+* DESCRIPTION:
+*		This function returns a 32-bit mask of GPP pins that connected to
+*		interrupt generating sources on board.
+*		For example if UART channel A is hardwired to GPP pin 8 and
+*		UART channel B is hardwired to GPP pin 4 the fuinction will return
+*		the value 0x000000110
+*
+* INPUT:
+*		None.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*		See description. The function return -1 if board is not identified.
+*
+*******************************************************************************/
+MV_U32 mvBoardGpioIntMaskGet(MV_U32 gppGrp)
+{
+	MV_U32 boardId;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardGpioIntMaskGet:Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	switch (gppGrp) {
+	case (0):
+		return BOARD_INFO(boardId)->intsGppMaskLow;
+		break;
+	case (1):
+		return BOARD_INFO(boardId)->intsGppMaskMid;
+		break;
+	case (2):
+		return BOARD_INFO(boardId)->intsGppMaskHigh;
+		break;
+	default:
+		return MV_ERROR;
+	}
+}
+
+/*******************************************************************************
+* mvBoardMppGet - Get board dependent MPP register value
+*
+* DESCRIPTION:
+*		MPP settings are derived from board design.
+*		MPP group consist of 8 MPPs. An MPP group represent MPP
+*		control register.
+*       This function retrieves board dependend MPP register value.
+*
+* INPUT:
+*       mppGroupNum - MPP group number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit value describing MPP control register value.
+*
+*******************************************************************************/
+MV_32 mvBoardMppGet(MV_U32 mppGroupNum)
+{
+	MV_U32 boardId;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardMppGet:Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	return BOARD_INFO(boardId)->pBoardMppConfigValue[0].mppGroup[mppGroupNum];
+}
+
+/*******************************************************************************
+* mvBoardEthComplexConfigGet - Return ethernet complex board configuration.
+*
+* DESCRIPTION:
+*	Returns the ethernet / Sata complex configuration from the board spec
+*	structure.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit value describing the ethernet complex config.
+*
+*******************************************************************************/
+MV_U32 mvBoardEthComplexConfigGet(MV_VOID)
+{
+	MV_U32 boardId;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardEthComplexConfigGet: Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	return BOARD_INFO(boardId)->pBoardMppTypeValue->ethSataComplexOpt;
+}
+
+/*******************************************************************************
+* mvBoardEthComplexConfigSet - Set ethernet complex board configuration.
+*
+* DESCRIPTION:
+*	Sets the ethernet / Sata complex configuration in the board spec
+*	structure.
+*
+* INPUT:
+*       ethConfig - 32bit value describing the ethernet complex config.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvBoardEthComplexConfigSet(MV_U32 ethConfig)
+{
+	MV_U32 boardId;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardEthComplexConfigSet: Board unknown.\n");
+		return;
+	}
+
+	/* Set ethernet complex configuration. */
+	BOARD_INFO(boardId)->pBoardMppTypeValue->ethSataComplexOpt = ethConfig;
+
+	if ((boardId != DB_88F6601_BP_ID) && (boardId != RD_88F6601_MC_ID))
+	{	/* KW2 only */
+		/* Update link speed for MAC0 / 1 */
+		/* If MAC 0 is connected to switch, then set to speed 1000Mbps */
+		if (mvBoardIsInternalSwitchConnected(0))
+			BOARD_INFO(boardId)->pBoardMacInfo[0].boardMacSpeed = BOARD_MAC_SPEED_1000M;
+		if (mvBoardIsInternalSwitchConnected(1))
+			BOARD_INFO(boardId)->pBoardMacInfo[1].boardMacSpeed = BOARD_MAC_SPEED_1000M;
+	}
+	return;
+}
+
+/*******************************************************************************
+* mvBoardPonConfigGet
+*
+* DESCRIPTION:
+*	Returns the PON port configuration from the board spec structure.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit value describing the PON port configuration.
+*
+*****************************************************************************/
+MV_U32 mvBoardPonConfigGet(MV_VOID)
+{
+	MV_U32 boardId;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardPonConfigGet:Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	return BOARD_INFO(boardId)->ponConfigValue;
+}
+
+/*******************************************************************************
+* mvBoardPonConfigSet
+*
+* DESCRIPTION:
+*	Set the PON port configuration from the board spec structure.
+*
+* INPUT:
+*       ponConfig - 32bit value describing the PON port configuration.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvBoardPonConfigSet(MV_U32 ponConfig)
+{
+	MV_U32 boardId;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardPonConfigSet:Board unknown.\n");
+		return;
+	}
+
+	BOARD_INFO(boardId)->ponConfigValue = ponConfig;
+	return;
+}
+
+/*******************************************************************************
+* mvBoardGppConfigGet
+*
+* DESCRIPTION:
+*	Get board configuration according to the input configuration GPP's.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	The value of the board configuration GPP's.
+*
+*******************************************************************************/
+MV_U32 mvBoardGppConfigGet(MV_VOID)
+{
+	MV_U32 boardId, i;
+	MV_U32 result = 0;
+	MV_U32 gpp;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardGppConfigGet: Board unknown.\n");
+		return 0;
+	}
+
+	for (i = 0; i < BOARD_INFO(boardId)->numBoardGppInfo; i++) {
+		if (BOARD_INFO(boardId)->pBoardGppInfo[i].devClass == BOARD_GPP_CONF) {
+			gpp = BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum;
+			result <<= 1;
+			result |= (mvGppValueGet(gpp >> 5, 1 << (gpp & 0x1F)) >> (gpp & 0x1F));
+		}
+	}
+	return result;
+
+}
+
+
+/*******************************************************************************
+* mvBoardModuleConfigSet
+*
+* DESCRIPTION:
+*	Set modules scan result, in order to skip scanning opration if needed.
+*
+* INPUT:
+*	modConfig - Bitmask including the scan result of the ethernet complex
+*		    and the TDM modules.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvBoardModuleConfigSet(MV_U32 modConfig)
+{
+	mvBoardStaticModuleConfig = MV_TRUE;
+	mvBoardModuleConfig = modConfig;
+	return;
+}
+
+/*******************************************************************************
+* mvBoardModuleConfigGet
+*
+* DESCRIPTION:
+*	Get modules scan result.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	modConfig - Bitmask including the scan result of the ethernet complex
+*		    and the TDM modules.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvBoardModuleConfigGet(MV_U32 *modConfig)
+{
+	MV_U32 ethCompCfg;
+	MV_8 tdmCfg;
+	MV_U32 boardId = mvBoardIdGet();
+
+	ethCompCfg = mvBoardEthComplexConfigGet();
+	tdmCfg = BOARD_INFO(boardId)->boardTdmInfoIndex;
+
+	*modConfig = MV_BRD_MODULE_CFG_BUILD(ethCompCfg, tdmCfg);
+
+	return;
+}
+
+
+/*******************************************************************************
+* mvBoardMppIdUpdate - Update MPP ID's according to modules auto-detection.
+*
+* DESCRIPTION:
+*	Update MPP ID's according to on-board modules as detected using TWSI bus.
+*
+* INPUT:
+*	ethSrc	- Sources for the rgmiiA & fe/Ge interfaces. might be needed in
+*		case where modules detection is not sufficient to configure
+*		internal Mux'es.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvBoardMppIdUpdate(MV_VOID)
+{
+	MV_U32 devId;
+	MV_U32 ethComplexOpt;
+	MV_U32 brdModules = 0;
+	MV_U32 ethConfig;
+	MV_U32 ponOpt;
+	MV_ETH_COMPLEX_IF_SOURCES ethCfgSrc;
+
+	devId = mvCtrlModelGet();
+
+	/* Setup ethernet / sata complex configuration. */
+	ethComplexOpt = mvBoardEthComplexConfigGet();
+	if (ethComplexOpt == ESC_OPT_AUTO) {
+		if (mvBoardStaticModuleConfig == MV_FALSE) {
+			mvBoardEthSataModulesScan(&brdModules, &ethCfgSrc);
+			mvCtrlEthSataComplexBuildConfig(brdModules, &ethCfgSrc, &ethConfig);
+		} else {
+			ethConfig = MV_BRD_MODULE_CFG_ETH_GET(mvBoardModuleConfig);
+		}
+		mvBoardEthComplexConfigSet(ethConfig);
+		mvBoardSwitchInfoUpdate();
+	} else if (mvBoardIdGet() == RD_88F6560_GW_ID) {
+		/* Check the board configuration GPP's to see if Sata port is
+		 ** enabled.
+		 */
+		if (mvBoardGppConfigGet() == 1) {
+			ethConfig = mvBoardEthComplexConfigGet();
+			ethConfig &= ~ESC_OPT_QSGMII;
+			ethConfig |= (ESC_OPT_SATA | ESC_OPT_FE3PHY);
+			mvBoardEthComplexConfigSet(ethConfig);
+		}
+	}
+
+	/* Setup TDM configuration. */
+    if (MV_6601_DEV_ID == devId){
+		MV_U32 boardId = mvBoardIdGet();
+		if (brdModules & MV_BOARD_MODULE_TDM_1_ID) {
+
+			/* Perform scan only for DB board. */
+			if (!mvBoardModuleAutoDetectEnabled())
+				BOARD_INFO(boardId)->boardTdmInfoIndex = -1; /* We have only a single Slic config for RD boards. */
+			else
+				BOARD_INFO(boardId)->boardTdmInfoIndex = BOARD_TDM_SLIC_880;
+		} else {
+			BOARD_INFO(boardId)->boardTdmInfoIndex = -1; /* no TDM */
+			BOARD_INFO(boardId)->numBoardTdmInfo[BOARD_TDM_SLIC_880] = 0;
+		}
+	} else {
+		mvBoardTdmModulesScan();
+
+		/* Setup xPON complex configuration */
+		ponOpt = mvBoardPonConfigGet();
+		if (ponOpt == BOARD_PON_AUTO) {
+			mvBoardPonModulesScan(&ponOpt);
+			mvBoardPonConfigSet(ponOpt);
+		}
+	}
+
+	ethConfig = mvBoardEthComplexConfigGet();
+    if (MV_6601_DEV_ID == devId){
+		if (ethConfig & ESC_OPT_GEPHY_MAC0) {
+			mvBoardPhyAddrSet(0,0);
+			mvBoardPhyAddrSet(1,1);
+		}
+		else {
+			mvBoardPhyAddrSet(0,1);
+			mvBoardPhyAddrSet(1,0x1f);
+		}
+	}
+	/* Update MPP output voltage for RGMIIB & RGMII2 to 1.8V */
+	if (ethConfig & (ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_RGMIIA_SW_P5 | ESC_OPT_RGMIIA_SW_P6)) {
+		/* Set GE_A & GE_B output voltage to 1.8V */
+		MV_REG_BIT_SET(MPP_OUTPUT_DRIVE_REG, MPP_GE_A_1_8_OUTPUT_DRIVE | MPP_GE_B_1_8_OUTPUT_DRIVE);
+	} else if (ethConfig & ESC_OPT_RGMIIB_MAC0) {
+		/* Set GE_A output voltage to 1.8V */
+		MV_REG_BIT_SET(MPP_OUTPUT_DRIVE_REG, MPP_GE_B_1_8_OUTPUT_DRIVE);
+	}
+
+#if defined(CONFIG_MV_ETH_LEGACY)
+	{
+		MV_U32 portMode;
+
+		/* Set port to MII for MII module */
+		portMode = mvBoardEthPortsModeGet();
+		ethConfig = mvBoardEthComplexConfigGet();
+		if ((ethConfig & ESC_OPT_RGMIIA_MAC1) && (!(portMode & EPM_MAC1_MII)))
+			mvEthGmacRgmiiSet(1, 1);
+		if ((ethConfig & (ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC0)) &&
+		    (!(portMode & EPM_MAC0_MII)))
+			mvEthGmacRgmiiSet(0, 1);
+
+		if (ethConfig & ESC_OPT_MAC0_2_SW_P4)
+			mvEthGmacRgmiiSet(0, 0);
+		if (ethConfig & (ESC_OPT_GEPHY_MAC1 | ESC_OPT_MAC1_2_SW_P5))
+			mvEthGmacRgmiiSet(1, 0);
+	}
+#endif /* CONFIG_MV_ETH_LEGACY */
+
+	return;
+}
+
+/*******************************************************************************
+* mvBoardMppGroupTypeGet
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       mppGroupClass - MPP group number 0  for MPP[35:20] or 1 for MPP[49:36].
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_BOARD_MPP_TYPE_CLASS mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass)
+{
+	MV_U32 boardId;
+	MV_U32 ethCompCfg;
+	MV_BOARD_MPP_TYPE_CLASS result = MV_BOARD_OTHER;
+
+	boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardMppGet:Board unknown.\n");
+		return MV_ERROR;
+	}
+
+	if (!mvBoardModuleAutoDetectEnabled())
+		return MV_BOARD_OTHER;
+
+	switch (mppGroupClass) {
+	case (MV_BOARD_MPP_GROUP_1):
+		/* Get TDM / TDU MPP type.      */
+#ifdef MV_INCLUDE_TDM
+		if (mvBoardTdmDevicesCountGet() > 0) {
+			if (mvCtrlTdmUnitTypeGet() == TDM_2CH_UNIT_ID)
+				result = MV_BOARD_TDM_2CH;
+			else
+				result = MV_BOARD_TDM_32CH;
+		}
+#endif
+		break;
+	case (MV_BOARD_MPP_GROUP_2):
+		/* Get GE0 MPP type.    */
+		ethCompCfg = BOARD_INFO(boardId)->pBoardMppTypeValue->ethSataComplexOpt;
+		if (ethCompCfg & ESC_OPT_RGMIIB_MAC0)
+			result = MV_BOARD_GE0;
+		if (result == MV_BOARD_OTHER) {
+#ifdef MV_INCLUDE_TDM
+			/* Get TDM / TDU MPP type.      */
+			if ((mvBoardTdmDevicesCountGet() > 0) && (mvCtrlTdmUnitTypeGet() == TDM_32CH_UNIT_ID))
+				result = MV_BOARD_TDM_32CH;
+#endif
+		}
+		break;
+	case (MV_BOARD_MPP_GROUP_3):
+		/* Get GE0 / GE1 / SW_P5 MPP type. */
+		ethCompCfg = BOARD_INFO(boardId)->pBoardMppTypeValue->ethSataComplexOpt;
+		if (ethCompCfg & ESC_OPT_RGMIIA_MAC0)
+			result = MV_BOARD_GE0;
+		else if (ethCompCfg & ESC_OPT_RGMIIA_MAC1)
+			result = MV_BOARD_GE1;
+		else if (ethCompCfg & ESC_OPT_RGMIIA_SW_P5)
+			result = MV_BOARD_SW_P5;
+		else if (ethCompCfg & ESC_OPT_RGMIIA_SW_P6)
+			result = MV_BOARD_SW_P6;
+		else
+			result = MV_BOARD_OTHER;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+* mvBoardTdmSpiModeGet - return SLIC/DAA connection
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_32 mvBoardTdmSpiModeGet(MV_VOID)
+{
+	return DUAL_CHIP_SELECT_MODE;
+}
+
+/*******************************************************************************
+* mvBoardTdmDevicesCountGet
+*
+* DESCRIPTION:
+*	Return the number of TDM devices on board.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	Number of devices.
+*
+*******************************************************************************/
+MV_U8 mvBoardTdmDevicesCountGet(MV_VOID)
+{
+	MV_U32 boardId = mvBoardIdGet();
+	MV_8 index;
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardTdmDevicesCountGet: Board unknown.\n");
+		return 0;
+	}
+
+	index = BOARD_INFO(boardId)->boardTdmInfoIndex;
+	if (index == (MV_8)-1)
+		return 0;
+
+	return BOARD_INFO(boardId)->numBoardTdmInfo[(MV_U8)index];
+}
+
+/*******************************************************************************
+* mvBoardTdmSpiCsGet
+*
+* DESCRIPTION:
+*	Return the SPI Chip-select number for a given device.
+*
+* INPUT:
+*	devId	- The Slic device ID to get the SPI CS for.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	The SPI CS if found, -1 otherwise.
+*
+*******************************************************************************/
+MV_U8 mvBoardTdmSpiCsGet(MV_U8 devId)
+{
+	MV_U32 boardId = mvBoardIdGet();
+	MV_8 index;
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardTdmDevicesCountGet: Board unknown.\n");
+		return -1;
+	}
+
+	index = BOARD_INFO(boardId)->boardTdmInfoIndex;
+	if (index == (MV_8)-1)
+		return 0;
+
+	if (devId >= BOARD_INFO(boardId)->numBoardTdmInfo[(MV_U8)index])
+		return -1;
+
+	return BOARD_INFO(boardId)->pBoardTdmInt2CsInfo[(MV_U8)index][devId].spiCs;
+}
+
+/*******************************************************************************
+* mvBoardTdmSpiIdGet
+*
+* DESCRIPTION:
+*	Return SPI port ID per board.
+*
+* INPUT:
+*	None
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	SPI port ID.
+*
+*******************************************************************************/
+MV_U8 mvBoardTdmSpiIdGet(MV_VOID)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardTdmSpiIdGet: Board unknown.\n");
+		return -1;
+	}
+
+	return BOARD_INFO(boardId)->pBoardTdmSpiInfo[0].spiId;
+}
+
+/*******************************************************************************
+* mvBoardModuleTypePrint
+*
+* DESCRIPTION:
+*	Print on-board detected modules.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvBoardMppModuleTypePrint(MV_VOID)
+{
+	MV_U32 ethConfig;
+	MV_U32 ponOpt;
+
+	mvOsOutput("Modules Detected:\n");
+	/* GPON / EPON */
+	ponOpt = mvBoardPonConfigGet();
+	if (ponOpt == BOARD_EPON_CONFIG)
+		mvOsOutput("       EPON module detected.\n");
+	else if (ponOpt == BOARD_GPON_CONFIG)
+		mvOsOutput("       GPON module detected.\n");
+	else
+		mvOsOutput("       No PON module.\n");
+
+	/* TDM */
+	if (mvBoardTdmDevicesCountGet() > 0)
+		mvOsOutput("       TDM module.\n");
+
+	ethConfig = mvBoardEthComplexConfigGet();
+
+	if (ethConfig & ESC_OPT_ILLEGAL) {
+		mvOsOutput("       Illegal configuration detected!\n");
+		return;
+	}
+	/* Sata */
+	if (ethConfig & ESC_OPT_SATA)
+		mvOsOutput("       Sata module detected.\n");
+
+	/* Ethernet Complex */
+
+	/* RGMIIA */
+	if (ethConfig & ESC_OPT_RGMIIA_MAC0)
+		mvOsOutput("       RGMIIA Module on MAC0.\n");
+	if (ethConfig & ESC_OPT_RGMIIA_MAC1)
+		mvOsOutput("       RGMIIA Module on MAC1.\n");
+	if (ethConfig & ESC_OPT_RGMIIA_SW_P5)
+		mvOsOutput("       RGMIIA Module on Switch port #5.\n");
+	if (ethConfig & ESC_OPT_RGMIIA_SW_P6)
+		mvOsOutput("       RGMIIA Module on Switch port #6.\n");
+
+	/* RGMIIB */
+	if (ethConfig & ESC_OPT_RGMIIB_MAC0)
+		mvOsOutput("       RGMIIB Module on MAC0.\n");
+
+	/* Ethernet Switch */
+	if (ethConfig & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5)) {
+		if (ethConfig & ESC_OPT_MAC0_2_SW_P4)
+			mvOsOutput("       Ethernet Switch on MAC0.\n");
+		if (ethConfig & ESC_OPT_MAC1_2_SW_P5)
+			mvOsOutput("       Ethernet Switch on MAC1\n");
+
+		if (mvBoardSmiScanModeGet(0) == 1)
+			mvOsOutput("       Switch in Single-Chip Address Mode.\n");
+	}
+
+	/* 3xFE PHY */
+	if (ethConfig & ESC_OPT_FE3PHY)
+		mvOsOutput("       3xFE PHY Module.\n");
+
+	/* Internal FE/GE Phy */
+	if (ethConfig & (ESC_OPT_GEPHY_MAC0 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_GEPHY_SW_P5 )) {
+		if (ethConfig & ESC_OPT_GEPHY_MAC0) 
+			mvOsOutput("       GE-PHY on MAC0.\n");
+		if (ethConfig & ESC_OPT_GEPHY_MAC1)
+			mvOsOutput("       GE-PHY on MAC1.\n");
+		if (ethConfig & ESC_OPT_GEPHY_SW_P0)
+			mvOsOutput("       GE-PHY on Switch port #0.\n");
+		if (ethConfig & ESC_OPT_GEPHY_SW_P5)
+			mvOsOutput("       GE-PHY on Switch port #5.\n");
+	}
+
+	/* QSGMII */
+	if (ethConfig & ESC_OPT_QSGMII)
+		mvOsOutput("       QSGMII Module.\n");
+
+	/* SGMII */
+	if (ethConfig & ESC_OPT_SGMII) {
+		if (ethConfig & ESC_OPT_SGMII_2_SW_P1)
+			mvOsOutput("       SGMII Module on Switch port #1.\n");
+		else
+			mvOsOutput("       SGMII Module on MAC0.\n");
+	}
+
+	/* SGMII-2.5G */
+	if (ethConfig & ESC_OPT_SGMII_2_5)
+		mvOsOutput("       SGMII-2.5G Module.\n");
+
+	/* LP SERDES  for DB 6601 */
+	if (DB_88F6601_BP_ID == mvBoardIdGet()) {
+		if (ethConfig & ESC_OPT_GEPHY_MAC0) 
+			mvOsOutput("       LP SERDES on MAC1.\n");
+		else
+			mvOsOutput("       LP SERDES on MAC0.\n");
+	}
+
+
+	return;
+}
+
+
+/*******************************************************************************
+* mvBoardIsGbEPortConnected
+*
+* DESCRIPTION:
+*	Checks if a given GbE port is actually connected to the GE-PHY, internal Switch or any RGMII module.
+*
+* INPUT:
+*	port - GbE port number (0 or 1).
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	MV_TRUE if port is connected, MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_BOOL mvBoardIsGbEPortConnected(MV_U32 ethPortNum)
+{
+	MV_U32 ethConfig;
+
+	ethConfig = mvBoardEthComplexConfigGet();
+
+	if (ethConfig & ESC_OPT_ILLEGAL)
+		return MV_FALSE;
+
+	if (DB_88F6601_BP_ID == mvBoardIdGet()) {
+		if (ethPortNum == 0)
+			return MV_TRUE;
+		if (ethConfig & ESC_OPT_GEPHY_MAC0)
+			return MV_TRUE;
+		return MV_FALSE;
+	}
+	if (RD_88F6601_MC_ID == mvBoardIdGet()) {
+		if (ethPortNum == 0)
+			return MV_TRUE;
+		return MV_FALSE;
+	}
+
+	if (ethPortNum == 0) {
+		if (ethConfig & (ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC0_2_SW_P4))
+			return MV_TRUE;
+		else
+			return MV_FALSE;
+	}
+
+	if (ethPortNum == 1) {
+		if (ethConfig & (ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_MAC1))
+			return MV_TRUE;
+		else
+			return MV_FALSE;
+	}
+
+	mvOsPrintf("mvBoardIsGbEPortConnected: unknown port %d\n", ethPortNum);
+	return MV_FALSE;
+}
+
+
+/* Board devices API managments */
+
+/*******************************************************************************
+* mvBoardGetDeviceNumber - Get number of device of some type on the board
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		devType - The device type ( Flash,RTC , etc .. )
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       If the device is found on the board the then the functions returns the
+*		number of those devices else the function returns 0
+*
+*
+*******************************************************************************/
+MV_32 mvBoardGetDevicesNumber(MV_BOARD_DEV_CLASS devClass)
+{
+	MV_U32 foundIndex = 0, devNum;
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("mvBoardGetDeviceNumber:Board unknown.\n");
+		return 0xFFFFFFFF;
+	}
+
+	for (devNum = START_DEV_CS; devNum < BOARD_INFO(boardId)->numBoardDeviceIf; devNum++) {
+		if (BOARD_INFO(boardId)->pDevCsInfo[devNum].devClass == devClass)
+			foundIndex++;
+	}
+
+	return foundIndex;
+}
+
+/*******************************************************************************
+* mvBoardGetDeviceBaseAddr - Get base address of a device existing on the board
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       devIndex - The device sequential number on the board
+*		devType - The device type ( Flash,RTC , etc .. )
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       If the device is found on the board the then the functions returns the
+*	Base address else the function returns 0xffffffff
+*
+*
+*******************************************************************************/
+MV_32 mvBoardGetDeviceBaseAddr(MV_32 devNum, MV_BOARD_DEV_CLASS devClass)
+{
+	MV_DEV_CS_INFO *devEntry;
+
+	devEntry = boardGetDevEntry(devNum, devClass);
+	if (devEntry != NULL)
+		return mvCpuIfTargetWinBaseLowGet(DEV_TO_TARGET(devEntry->deviceCS));
+
+	return 0xFFFFFFFF;
+}
+
+/*******************************************************************************
+* mvBoardGetDeviceBusWidth - Get Bus width of a device existing on the board
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       devIndex - The device sequential number on the board
+*		devType - The device type ( Flash,RTC , etc .. )
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       If the device is found on the board the then the functions returns the
+*		Bus width else the function returns 0xffffffff
+*
+*
+*******************************************************************************/
+MV_32 mvBoardGetDeviceBusWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass)
+{
+	MV_DEV_CS_INFO *devEntry;
+
+	devEntry = boardGetDevEntry(devNum, devClass);
+	if (devEntry != NULL)
+		return devEntry->devWidth;
+
+	return 0xFFFFFFFF;
+}
+
+/*******************************************************************************
+* mvBoardGetDeviceWidth - Get dev width of a device existing on the board
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       devIndex - The device sequential number on the board
+*		devType - The device type ( Flash,RTC , etc .. )
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       If the device is found on the board the then the functions returns the
+*		dev width else the function returns 0xffffffff
+*
+*
+*******************************************************************************/
+MV_32 mvBoardGetDeviceWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass)
+{
+	MV_DEV_CS_INFO *devEntry;
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("Board unknown.\n");
+		return 0xFFFFFFFF;
+	}
+
+	devEntry = boardGetDevEntry(devNum, devClass);
+	if (devEntry != NULL)
+		return devEntry->devWidth;
+
+	return MV_ERROR;
+}
+
+/*******************************************************************************
+* mvBoardGetDeviceWinSize - Get the window size of a device existing on the board
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       devIndex - The device sequential number on the board
+*		devType - The device type ( Flash,RTC , etc .. )
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       If the device is found on the board the then the functions returns the
+*		window size else the function returns 0xffffffff
+*
+*
+*******************************************************************************/
+MV_32 mvBoardGetDeviceWinSize(MV_32 devNum, MV_BOARD_DEV_CLASS devClass)
+{
+	MV_DEV_CS_INFO *devEntry;
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("Board unknown.\n");
+		return 0xFFFFFFFF;
+	}
+
+	devEntry = boardGetDevEntry(devNum, devClass);
+	if (devEntry != NULL)
+		return mvCpuIfTargetWinSizeGet(DEV_TO_TARGET(devEntry->deviceCS));
+
+	return 0xFFFFFFFF;
+}
+
+/*******************************************************************************
+* boardGetDevEntry - returns the entry pointer of a device on the board
+*
+* DESCRIPTION:
+*
+* INPUT:
+*	devIndex - The device sequential number on the board
+*	devType - The device type ( Flash,RTC , etc .. )
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	If the device is found on the board the then the functions returns the
+*	dev number else the function returns 0x0
+*
+*******************************************************************************/
+static MV_DEV_CS_INFO *boardGetDevEntry(MV_32 devNum, MV_BOARD_DEV_CLASS devClass)
+{
+	MV_U32 foundIndex = 0, devIndex;
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("boardGetDevEntry: Board unknown.\n");
+		return NULL;
+	}
+
+	for (devIndex = START_DEV_CS; devIndex < BOARD_INFO(boardId)->numBoardDeviceIf; devIndex++) {
+		if (BOARD_INFO(boardId)->pDevCsInfo[devIndex].devClass == devClass) {
+			if (foundIndex == devNum)
+				return &(BOARD_INFO(boardId)->pDevCsInfo[devIndex]);
+			foundIndex++;
+		}
+	}
+
+	/* device not found */
+	return NULL;
+}
+
+/*******************************************************************************
+* boardGetDevCSNum
+*
+* DESCRIPTION:
+*	Return the device's chip-select number.
+*
+* INPUT:
+*	devIndex - The device sequential number on the board
+*	devType - The device type ( Flash,RTC , etc .. )
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	If the device is found on the board the then the functions returns the
+*	dev number else the function returns 0x0
+*
+*******************************************************************************/
+MV_U32 boardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devClass)
+{
+	MV_DEV_CS_INFO *devEntry;
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID))) {
+		mvOsPrintf("Board unknown.\n");
+		return 0xFFFFFFFF;
+	}
+
+	devEntry = boardGetDevEntry(devNum, devClass);
+	if (devEntry != NULL)
+		return devEntry->deviceCS;
+
+	return 0xFFFFFFFF;
+}
+
+/*******************************************************************************
+* mvBoardTwsiAddrTypeGet -
+*
+* DESCRIPTION:
+*	Return the TWSI address type for a given twsi device class.
+*
+* INPUT:
+*	twsiClass - The TWSI device to return the address type for.
+*	index	  - The TWSI device index (Pass 0 in case of a single
+*		    device)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	The TWSI address type.
+*
+*******************************************************************************/
+MV_U8 mvBoardTwsiAddrTypeGet(MV_BOARD_TWSI_CLASS twsiClass, MV_U32 index)
+{
+	int i;
+	MV_U32 indexFound = 0;
+	MV_U32 boardId = mvBoardIdGet();
+
+	for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) {
+		if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == twsiClass) {
+			if (indexFound == index)
+				return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType;
+			indexFound++;
+		}
+	}
+	return (MV_ERROR);
+}
+
+/*******************************************************************************
+* mvBoardTwsiAddrGet -
+*
+* DESCRIPTION:
+*	Return the TWSI address for a given twsi device class.
+*
+* INPUT:
+*	twsiClass - The TWSI device to return the address type for.
+*	index	  - The TWSI device index (Pass 0 in case of a single
+*		    device)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	The TWSI address.
+*
+*******************************************************************************/
+MV_U8 mvBoardTwsiAddrGet(MV_BOARD_TWSI_CLASS twsiClass, MV_U32 index)
+{
+	int i;
+	MV_U32 indexFound = 0;
+	MV_U32 boardId = mvBoardIdGet();
+
+	for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) {
+		if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == twsiClass) {
+			if (indexFound == index)
+				return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr;
+			indexFound++;
+		}
+	}
+	return (0xFF);
+}
+
+/*******************************************************************************
+* mvBoardNandWidthGet -
+*
+* DESCRIPTION: Get the width of the first NAND device in byte.
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN: 1, 2, 4 or MV_ERROR
+*
+*
+*******************************************************************************/
+MV_32 mvBoardNandWidthGet(MV_VOID)
+{
+	MV_U32 devNum;
+	MV_U32 devWidth;
+	MV_U32 boardId = mvBoardIdGet();
+
+	for (devNum = START_DEV_CS; devNum < BOARD_INFO(boardId)->numBoardDeviceIf; devNum++) {
+		devWidth = mvBoardGetDeviceWidth(devNum, BOARD_DEV_NAND_FLASH);
+		if (devWidth != MV_ERROR)
+			return (devWidth / 8);
+	}
+
+	/* NAND wasn't found */
+	return MV_ERROR;
+}
+
+MV_U32 gBoardId = -1;
+
+/*******************************************************************************
+* mvBoardIdGet - Get Board model
+*
+* DESCRIPTION:
+*       This function returns board ID.
+*       Board ID is 32bit word constructed of board model (16bit) and
+*       board revision (16bit) in the following way: 0xMMMMRRRR.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit board ID number, '-1' if board is undefined.
+*
+*******************************************************************************/
+MV_U32 mvBoardIdGet(MV_VOID)
+{
+	MV_U32 tmpBoardId = -1;
+
+	if (gBoardId == -1) {
+#if defined(DB_88F6500)
+		tmpBoardId = DB_88F6535_BP_ID;
+#elif defined(RD_88F6510)
+		tmpBoardId = RD_88F6510_SFU_ID;
+#elif defined(RD_88F6530)
+		tmpBoardId = RD_88F6530_MDU_ID;
+#elif defined(RD_88F6560)
+		tmpBoardId = RD_88F6560_GW_ID;
+#elif defined(DB_88F6560_PCAC)
+		tmpBoardId = DB_88F6560_PCAC_ID;
+#elif defined(DB_88F6601)
+		tmpBoardId = DB_88F6601_BP_ID;
+#elif defined(RD_88F6601)
+		tmpBoardId = RD_88F6601_MC_ID;
+#elif defined(DB_CUSTOMER)
+		tmpBoardId = DB_CUSTOMER_ID;
+#endif
+		gBoardId = tmpBoardId;
+	}
+
+	return gBoardId;
+}
+
+/*******************************************************************************
+* mvBoardTwsiSatRGet -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*	device num - one of three devices
+*	reg num - 0 or 1
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*		reg value
+*
+*******************************************************************************/
+MV_U8 mvBoardTwsiSatRGet(MV_U8 devNum, MV_U8 regNum)
+{
+	MV_TWSI_SLAVE twsiSlave;
+	MV_TWSI_ADDR slave;
+	MV_U8 data;
+
+	/* TWSI init */
+	slave.type = ADDR7_BIT;
+	slave.address = 0;
+	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
+
+	/* Read MPP module ID */
+	DB(mvOsPrintf("Board: Read S@R device read\n"));
+	twsiSlave.slaveAddr.address = mvBoardTwsiAddrGet(BOARD_DEV_TWSI_SATR, devNum);
+	twsiSlave.slaveAddr.type = mvBoardTwsiAddrTypeGet(BOARD_DEV_TWSI_SATR, devNum);
+
+	twsiSlave.validOffset = MV_TRUE;
+	/* Use offset as command */
+	twsiSlave.offset = regNum;
+	twsiSlave.moreThen256 = MV_FALSE;
+
+	if (MV_OK != mvTwsiRead(0, &twsiSlave, &data, 1)) {
+		DB(mvOsPrintf("Board: Read S@R fail\n"));
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Board: Read S@R succeded\n"));
+
+	return data;
+}
+
+/*******************************************************************************
+* mvBoardTwsiSatRSet -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*	devNum - one of three devices
+*	regNum - 0 or 1
+*	regVal - value
+*
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*		reg value
+*
+*******************************************************************************/
+MV_STATUS mvBoardTwsiSatRSet(MV_U8 devNum, MV_U8 regNum, MV_U8 regVal)
+{
+	MV_TWSI_SLAVE twsiSlave;
+	MV_TWSI_ADDR slave;
+
+	/* TWSI init */
+	slave.type = ADDR7_BIT;
+	slave.address = 0;
+	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
+
+	/* Read MPP module ID */
+	twsiSlave.slaveAddr.address = mvBoardTwsiAddrGet(BOARD_DEV_TWSI_SATR, devNum);
+	twsiSlave.slaveAddr.type = mvBoardTwsiAddrTypeGet(BOARD_DEV_TWSI_SATR, devNum);
+	twsiSlave.validOffset = MV_TRUE;
+	DB(mvOsPrintf("Board: Write S@R device addr %x, type %x, data %x\n",
+		      twsiSlave.slaveAddr.address, twsiSlave.slaveAddr.type, regVal));
+	/* Use offset as command */
+	twsiSlave.offset = regNum;
+	twsiSlave.moreThen256 = MV_FALSE;
+	if (MV_OK != mvTwsiWrite(0, &twsiSlave, &regVal, 1)) {
+		DB(mvOsPrintf("Board: Write S@R fail\n"));
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Board: Write S@R succeded\n"));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* SatR Configuration functions
+*******************************************************************************/
+MV_U8 mvBoardFreqGet(MV_VOID)
+{
+	MV_U8 sar0, sar1;
+
+	sar0 = mvBoardTwsiSatRGet(0, 0);
+    	if (MV_6601_DEV_ID == mvCtrlModelGet()) /* A-MC */
+		return MSAR6601_CPU_DDR_CLCK_TWSI_EXTRACT(sar0);
+
+	sar1 = mvBoardTwsiSatRGet(2, 0);
+
+	return MSAR_CPU_DDR_L2_CLCK_TWSI_EXTRACT(sar0, sar1);
+}
+
+MV_STATUS mvBoardFreqSet(MV_U8 freqVal)
+{
+	MV_U8 sar0, sar1;
+
+    	if (MV_6601_DEV_ID == mvCtrlModelGet()){ /*  A-MC */
+		sar0 = mvBoardTwsiSatRGet(0, 0) & ~0x07;
+		sar0 |= freqVal & 0x7;
+		if (MV_OK != mvBoardTwsiSatRSet(0, 0, sar0)) {
+			DB(mvOsPrintf("Board: Write S@R fail\n"));
+			return MV_ERROR;
+		}
+	}
+	else
+	{
+		sar0 = freqVal & 0x1f;
+		if (MV_OK != mvBoardTwsiSatRSet(0, 0, sar0)) {
+			DB(mvOsPrintf("Board: Write S@R fail\n"));
+			return MV_ERROR;
+		}
+		sar1 = mvBoardTwsiSatRGet(2, 0);
+		sar1 = MV_SET_BIT(sar1, 4, MV_GET_BIT(freqVal, 5));
+		if (MV_OK != mvBoardTwsiSatRSet(2, 0, sar1)) {
+			DB(mvOsPrintf("Board: Write S@R fail\n"));
+			return MV_ERROR;
+		}
+	}
+
+	DB(mvOsPrintf("Board: Write Freq S@R succeeded\n"));
+	return MV_OK;
+}
+
+MV_U8 mvBoardSSCGGet(MV_VOID)
+{
+	MV_U8 sar;
+
+    	if (MV_6601_DEV_ID == mvCtrlModelGet()){ /*  A-MC */
+			sar = mvBoardTwsiSatRGet(0, 0) & 0x10;
+			return (sar>>4);
+	}
+	sar = mvBoardTwsiSatRGet(1, 0);
+	return MV_GET_BIT(sar, 2);
+}
+
+MV_STATUS mvBoardSSCGSet(MV_U8 val)
+{
+	MV_U8 sar;
+    	if (MV_6601_DEV_ID == mvCtrlModelGet()){ /*  A-MC */
+			sar = mvBoardTwsiSatRGet(0, 0) & ~0x10;
+			if (val)
+				sar |=0x10;
+			if (MV_OK != mvBoardTwsiSatRSet(0, 0, sar)) {
+				DB(mvOsPrintf("Board: Write S@R fail\n"));
+				return MV_ERROR;
+			}
+	}
+	else {
+		sar = mvBoardTwsiSatRGet(1, 0);
+		sar = MV_SET_BIT(sar, 2, (val & 0x1));
+		if (MV_OK != mvBoardTwsiSatRSet(1, 0, sar)) {
+			DB(mvOsPrintf("Board: Write S@R fail\n"));
+			return MV_ERROR;
+		}
+	}
+
+	DB(mvOsPrintf("Board: Write Freq S@R succeeded\n"));
+	return MV_OK;
+}
+
+MV_U8 mvBoardPexClkGet(MV_U8 pexIf)
+{
+	MV_U8 sar;
+	MV_U8 sarDev;
+	MV_U8 bit;
+
+	if (pexIf == 0) {
+		sarDev = 2;
+		bit = 2;
+	} else {
+		sarDev = 3;
+		bit = 0;
+	}
+
+	sar = mvBoardTwsiSatRGet(sarDev, 0);
+	return MV_GET_BIT(sar, bit);
+}
+
+MV_STATUS mvBoardPexClkSet(MV_U8 pexIf, MV_U8 val)
+{
+	MV_U8 sar;
+	MV_U8 sarDev;
+	MV_U8 bit;
+
+	if (pexIf == 0) {
+		sarDev = 2;
+		bit = 2;
+	} else {
+		sarDev = 3;
+		bit = 0;
+	}
+
+	sar = mvBoardTwsiSatRGet(sarDev, 0);
+	sar = MV_SET_BIT(sar, bit, (val & 0x1));
+	if (MV_OK != mvBoardTwsiSatRSet(sarDev, 0, sar)) {
+		DB(mvOsPrintf("Board: Write S@R fail\n"));
+		return MV_ERROR;
+	}
+
+	DB(mvOsPrintf("Board: Write Pex Clock S@R succeeded\n"));
+	return MV_OK;
+}
+
+MV_U8 mvBoardSaRL2ExistGet(MV_VOID)
+{
+	MV_U8 sar;
+
+	sar = mvBoardTwsiSatRGet(3, 0);
+	return MV_GET_BIT(sar, 3);
+}
+
+MV_U8 mvBoardSaRL2ExistSet(MV_U8 val)
+{
+	MV_U8 sar;
+	MV_U8 sarDev;
+	MV_U8 bit;
+
+	sarDev = 3;
+	bit = 3;
+
+	sar = mvBoardTwsiSatRGet(sarDev, 0);
+	sar = MV_SET_BIT(sar, bit, (val & 0x1));
+	if (MV_OK != mvBoardTwsiSatRSet(sarDev, 0, sar)) {
+		DB(mvOsPrintf("Board: Write S@R fail\n"));
+		return MV_ERROR;
+	}
+
+	DB(mvOsPrintf("Board: Write L2-Exist S@R succeeded\n"));
+	return MV_OK;
+}
+
+
+MV_U8 mvBoardPonGet(MV_VOID)
+{
+	MV_U8 sar;
+
+	sar = mvBoardTwsiSatRGet(3, 0);
+	return MV_GET_BIT(sar, 4);
+}
+
+MV_STATUS mvBoardPonSet(MV_U8 val)
+{
+	MV_U8 sar;
+
+	sar = mvBoardTwsiSatRGet(3, 0);
+	sar = MV_SET_BIT(sar, 4, (val & 0x1));
+	if (MV_OK != mvBoardTwsiSatRSet(3, 0, sar)) {
+		DB(mvOsPrintf("Board: Write S@R fail\n"));
+		return MV_ERROR;
+	}
+
+	DB(mvOsPrintf("Board: Write Freq S@R succeeded\n"));
+	return MV_OK;
+}
+
+MV_U8 mvBoardTClkGet(MV_VOID)
+{
+	MV_U8 sar;
+	if (MV_6601_DEV_ID == mvCtrlModelGet()){ /*  A-MC */
+		sar = mvBoardTwsiSatRGet(0, 0);
+		return ((sar & 0x8))>>3;
+	}
+	sar = mvBoardTwsiSatRGet(1, 0);
+	return (sar & 0x3);
+}
+
+MV_STATUS mvBoardTClkSet(MV_U8 val)
+{
+	MV_U8 sar;
+
+    	if (MV_6601_DEV_ID == mvCtrlModelGet()){ /*  A-MC */
+		sar = mvBoardTwsiSatRGet(0, 0) & ~8;
+		if (val)
+			sar |=0x8;
+		if (MV_OK != mvBoardTwsiSatRSet(0, 0, sar)) {
+			DB(mvOsPrintf("Board: Write S@R fail\n"));
+			return MV_ERROR;
+		}
+	}
+	else {
+		sar = mvBoardTwsiSatRGet(1, 0);
+		sar = ((sar & ~(0x3)) | (val & 0x3));
+		if (MV_OK != mvBoardTwsiSatRSet(1, 0, sar)) {
+			DB(mvOsPrintf("Board: Write S@R fail\n"));
+			return MV_ERROR;
+		}
+	}
+
+	DB(mvOsPrintf("Board: Write Freq S@R succeeded\n"));
+	return MV_OK;
+}
+
+/*******************************************************************************
+* End of SatR Configuration functions
+*******************************************************************************/
+
+/*******************************************************************************
+* mvBoardEthSataModulesScan
+*
+* DESCRIPTION:
+*	Scan the on-board ethernet & Sata complex modules, and return a
+*	list of all available modules.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	modules - A bitmask of all modules detected on board
+*	(bitwise or from MV_BOARD_MODULE_ID_CLASS)
+*
+* RETURN:
+*       MV_STATUS - MV_OK, MV_ERROR.
+*
+*******************************************************************************/
+MV_STATUS mvBoardEthSataModulesScan(MV_U32 *modules, MV_ETH_COMPLEX_IF_SOURCES *ethSrcCfg)
+{
+	MV_U32 result = 0;
+	MV_U8 cfg, boardCfg;
+	MV_STATUS status;
+	MV_TWSI_SLAVE twsiSlave;
+	MV_TWSI_ADDR slave;
+
+	if (!mvBoardModuleAutoDetectEnabled())
+		return MV_OK;
+
+	/* Go over all possible modules and check for existence */
+
+	slave.type = ADDR7_BIT;
+	slave.address = 0;
+	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
+	/* Read the board config EEPROM */
+	twsiSlave.slaveAddr.address = MV_BOARD_EEPROM_MODULE_ADDR;
+	twsiSlave.slaveAddr.type = MV_BOARD_EEPROM_MODULE_ADDR_TYPE;
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = 0;
+	twsiSlave.moreThen256 = MV_FALSE;
+	status = mvTwsiRead(0, &twsiSlave, &boardCfg, 1);
+	if (status != MV_OK) {
+		mvOsPrintf(" mvBoardEthSataModulesScan: Error on mvTwsiRead\n");
+		*modules = 0;
+		return status;
+	}
+	/* Avanta-MC */
+	mvOsPrintf(" mvBoardEthSataModulesScan: mvTwsiRead return jumper = 0x%x\n",boardCfg );
+    	if (DB_88F6601_BP_ID == mvBoardIdGet()) {
+		MV_U8 xcvrValue = 0x4;
+		if (0 == MV_BOARD_6601_CFG_MAC_SRC(boardCfg))
+			ethSrcCfg->feGeSrc = EC_MAC0_SRC;   /* MAC0 --> GbE PHY, MAC1 --> LP SERDES */ 
+		else
+			ethSrcCfg->feGeSrc = EC_SRC_NONE;   /* MAC0 --> LP SERDES, MAC1 --> NONE */ 
+
+		*modules = 0;
+			/* JP2	LP SerDes connection */
+		if (MV_BOARD_6601_CFG_LP_SERDES_CON_MASK == MV_BOARD_6601_CFG_LP_SERDES_CON(boardCfg)) {
+			MV_U32 gppVal = mvGppValueGet(1, MV_GPP0);
+			if (gppVal == 0){
+				mvGppValueSet(0, MV_GPP31, 0);
+				*modules |= MV_BOARD_MODULE_GE_SFP_ID;   
+			}
+			else {
+				mvGppValueSet(0, MV_GPP31, MV_GPP31);
+				mvOsPrintf("mvBoardEthSataModulesScan: Error illegal SFP module configuration\n");
+			}
+		} else {
+			mvGppValueSet(0, MV_GPP31, MV_GPP31);
+			*modules |= MV_BOARD_MODULE_FE_GE_PHY_ID;
+		}
+
+			/* JP3	LP SerDes mode 2.5G /1.25G */
+		if (MV_BOARD_6601_CFG_LP_SERDES_MODE_MASK == MV_BOARD_6601_CFG_LP_SERDES_MODE(boardCfg))
+			ethSrcCfg->macType = EC_SGMII_2_5G;
+		else
+			ethSrcCfg->macType = EC_SGMII_1_25G;   
+
+		/* JP4	FXS presence */
+		if (0 == MV_BOARD_6601_CFG_FXS(boardCfg))
+			*modules |= MV_BOARD_MODULE_TDM_1_ID;
+
+		/* Configure XCVR mux */
+		twsiSlave.slaveAddr.address = MV_BOARD_XCVR_MUX_ADDR;
+		twsiSlave.slaveAddr.type = MV_BOARD_XCVR_MUX_ADDR_TYPE;
+		twsiSlave.validOffset = MV_TRUE;
+		twsiSlave.offset = 0;
+		twsiSlave.moreThen256 = MV_FALSE;
+		mvTwsiWrite(0, &twsiSlave, &xcvrValue , 1); 
+
+		return MV_OK;
+	}
+
+	/* KW2 */
+	switch (MV_BOARD_CFG_SW_SRC(boardCfg)) {
+	case 1:
+		ethSrcCfg->swSrc = EC_MAC1_SRC;
+		break;
+	case 2:
+		ethSrcCfg->swSrc = EC_MAC0_SRC;
+		break;
+	case 3:
+		ethSrcCfg->swSrc = EC_MAC0_MAC1_SRC;
+		break;
+	case 0:
+	default:
+		ethSrcCfg->swSrc = EC_SRC_NONE;
+		break;
+	}
+
+	switch (MV_BOARD_CFG_RGMIIA_SRC(boardCfg)) {
+	case 0:
+		ethSrcCfg->rgmiiASrc = EC_SW_P6_SRC;
+		break;
+	case 1:
+		ethSrcCfg->rgmiiASrc = EC_MAC0_SRC;
+		break;
+	case 2:
+		ethSrcCfg->rgmiiASrc = EC_MAC1_SRC;
+		break;
+	case 3:
+		ethSrcCfg->rgmiiASrc = EC_SW_P5_SRC;
+		break;
+	default:
+		ethSrcCfg->rgmiiASrc = EC_SRC_NONE;
+		break;
+	}
+
+	switch (MV_BOARD_CFG_FEGEPHY_SRC(boardCfg)) {
+	case 1:
+		ethSrcCfg->feGeSrc = EC_MAC1_SRC;
+		break;
+	case 2:
+		ethSrcCfg->feGeSrc = EC_SW_P0_SRC;
+		break;
+	case 3:
+		ethSrcCfg->feGeSrc = EC_SW_P5_SRC;
+		break;
+	case 0:
+	default:
+		ethSrcCfg->feGeSrc = EC_SRC_NONE;
+		break;
+	}
+
+	/* Sata / QSGMII / SGMII */
+	switch (MV_BOARD_CFG_SERDES_SRC(boardCfg)) {
+	case 1:
+		result |= MV_BOARD_MODULE_SATA_ID;
+		break;
+	case 2:
+		result |= MV_BOARD_MODULE_SGMII_ID;
+		break;
+	case 3:
+		result |= MV_BOARD_MODULE_SDIO_ID;
+		break;
+	case 0:
+	default:
+		break;
+	}
+
+	/* FEGE PHY */
+	switch (MV_BOARD_CFG_FEGEPHY_SRC(boardCfg)) {
+	case 1:
+	case 2:
+	case 3:
+		result |= MV_BOARD_MODULE_FE_GE_PHY_ID;
+		break;
+	case 0:
+	default:
+		break;
+	}
+
+	/* RGMII 0 */
+	twsiSlave.slaveAddr.address = MV_BOARD_RGMIIA_MODULE_ADDR;
+	twsiSlave.slaveAddr.type = MV_BOARD_RGMIIA_MODULE_ADDR_TYPE;
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = 0;
+	twsiSlave.moreThen256 = MV_FALSE;
+	if (mvBoardTwsiReadByteThruMux(MV_BOARD_RGMIIA_MODULE_MUX_CHNUM, 0, &twsiSlave, &cfg) == MV_OK) {
+		if (cfg == 0x3)
+			result |= MV_BOARD_MODULE_RGMIIA_ID;
+		else if (cfg == 0x6)
+			result |= MV_BOARD_MODULE_MIIA_ID;
+	}
+
+	/* RGMII 1 */
+	twsiSlave.slaveAddr.address = MV_BOARD_RGMIIB_MODULE_ADDR;
+	twsiSlave.slaveAddr.type = MV_BOARD_RGMIIB_MODULE_ADDR_TYPE;
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = 0;
+	twsiSlave.moreThen256 = MV_FALSE;
+	if (mvBoardTwsiReadByteThruMux(MV_BOARD_RGMIIB_MODULE_MUX_CHNUM, 0, &twsiSlave, &cfg) == MV_OK) {
+		if (cfg == 0x3)
+			result |= MV_BOARD_MODULE_RGMIIB_ID;
+		else if (cfg == 0x6)
+			result |= MV_BOARD_MODULE_MIIB_ID;
+	}
+
+	/* QSGMII */
+	twsiSlave.slaveAddr.address = MV_BOARD_QSGMII_MODULE_ADDR;
+	twsiSlave.slaveAddr.type = MV_BOARD_QSGMII_MODULE_ADDR_TYPE;
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = 0;
+	twsiSlave.moreThen256 = MV_FALSE;
+	if (mvBoardTwsiReadByteThruMux(MV_BOARD_QSGMII_MODULE_MUX_CHNUM, 0, &twsiSlave, &cfg) == MV_OK) {
+		if (((cfg & 0xf) == 0x8) || ((cfg & 0xf) == 0xb))
+			result |= MV_BOARD_MODULE_QSGMII_ID;
+	}
+
+	if ((!(result & MV_BOARD_MODULE_QSGMII_ID)) &&
+	    (!((result & MV_BOARD_MODULE_SGMII_ID) && (ethSrcCfg->swSrc == EC_MAC0_SRC))) &&
+	    (!((result & MV_BOARD_MODULE_SGMII_ID) && (ethSrcCfg->swSrc == EC_MAC0_MAC1_SRC))) &&
+	    (ethSrcCfg->swSrc != EC_SRC_NONE))
+		result |= MV_BOARD_MODULE_4FE_PHY_ID;
+
+	/* GE SFP */
+	twsiSlave.slaveAddr.address = MV_BOARD_GE_SFP_MODULE_ADDR;
+	twsiSlave.slaveAddr.type = MV_BOARD_GE_SFP_MODULE_ADDR_TYPE;
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = 0;
+	twsiSlave.moreThen256 = MV_FALSE;
+	if (mvBoardTwsiReadByteThruMux(MV_BOARD_GE_SFP_MODULE_MUX_CHNUM, 0, &twsiSlave, &cfg) == MV_OK)
+		result |= MV_BOARD_MODULE_GE_SFP_ID;
+
+	*modules = result;
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvBoardIsSdioEnabled
+*
+* DESCRIPTION:
+*	Check if SDIO is enabled on KW2-DB board.
+*	the check is done by reading the on-board EEPROM.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_TRUE if SDIO is enabled,
+*	MV_FALSE otherwise.
+*	On all boards except DB this function will return MV_TRUE.
+*
+*******************************************************************************/
+MV_STATUS mvBoardIsSdioEnabled(MV_VOID)
+{
+	MV_U8 boardCfg;
+	MV_TWSI_SLAVE twsiSlave;
+	MV_TWSI_ADDR slave;
+
+    	if (MV_6601_DEV_ID == mvCtrlModelGet()) /* no sdio on A-MC */
+		return MV_FALSE;
+	if (!mvBoardModuleAutoDetectEnabled())
+		return MV_TRUE;
+
+	/* Go over all possible modules and check for existence */
+
+	slave.type = ADDR7_BIT;
+	slave.address = 0;
+	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
+
+	/* Read the board config EEPROM */
+	twsiSlave.slaveAddr.address = MV_BOARD_EEPROM_MODULE_ADDR;
+	twsiSlave.slaveAddr.type = MV_BOARD_EEPROM_MODULE_ADDR_TYPE;
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = 0;
+	twsiSlave.moreThen256 = MV_FALSE;
+	if (mvTwsiRead(0, &twsiSlave, &boardCfg, 1) != MV_OK)
+		return MV_FALSE;
+
+	if (MV_BOARD_CFG_SERDES_SRC(boardCfg) == 3)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvBoardTdmModulesScan
+*
+* DESCRIPTION:
+*	Scan the on-board TDM modules.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	modules - A bitmask of all modules detected on board
+*	(bitwise or from MV_BOARD_MODULE_ID_CLASS)
+*
+* RETURN:
+*       MV_STATUS - MV_OK, MV_ERROR.
+*
+*******************************************************************************/
+MV_STATUS mvBoardTdmModulesScan(MV_VOID)
+{
+	MV_U32 result = 0;
+	MV_U8 cfg;
+	MV_TWSI_SLAVE twsiSlave;
+	MV_U32 boardId = mvBoardIdGet();
+
+	/* Perform scan only for DB board. */
+	if (!mvBoardModuleAutoDetectEnabled()) {
+		/* We have only a single Slic config for RD boards. */
+		BOARD_INFO(boardId)->boardTdmInfoIndex = 0;
+		return MV_OK;
+	}
+
+	if (mvBoardStaticModuleConfig == MV_TRUE) {
+		BOARD_INFO(boardId)->boardTdmInfoIndex = MV_BRD_MODULE_CFG_TDM_GET(mvBoardModuleConfig);
+		result = 1;
+	}
+    if (MV_6601_DEV_ID == mvCtrlModelGet()) /* detect the TDM in A-MC in mvBoardMppIdUpdate */
+		return MV_OK;
+
+	/* TDM-3215 */
+	if (result == 0) {
+		twsiSlave.slaveAddr.address = MV_BOARD_TDM_3215_MODULE_ADDR;
+		twsiSlave.slaveAddr.type = MV_BOARD_TDM_MODULE_ADDR_TYPE;
+		twsiSlave.validOffset = MV_TRUE;
+		twsiSlave.offset = 0;
+		twsiSlave.moreThen256 = MV_FALSE;
+		if (mvBoardTwsiReadByteThruMux(MV_BOARD_TDM_MODULE_MUX_CHNUM, 0, &twsiSlave, &cfg) == MV_OK) {
+			BOARD_INFO(boardId)->boardTdmInfoIndex = BOARD_TDM_SLIC_3215;
+			result = 1;
+		}
+	}
+
+	/* TDM-880 */
+	if (result == 0) {
+		twsiSlave.slaveAddr.address = MV_BOARD_TDM_880_MODULE_ADDR;
+		twsiSlave.slaveAddr.type = MV_BOARD_TDM_MODULE_ADDR_TYPE;
+		twsiSlave.validOffset = MV_TRUE;
+		twsiSlave.offset = 0;
+		twsiSlave.moreThen256 = MV_FALSE;
+		if (mvBoardTwsiReadByteThruMux(MV_BOARD_TDM_MODULE_MUX_CHNUM, 0, &twsiSlave, &cfg) == MV_OK) {
+			BOARD_INFO(boardId)->boardTdmInfoIndex = BOARD_TDM_SLIC_880;
+			result = 1;
+		}
+	}
+
+	/* TDM-792 Adapter */
+	if (result == 0) {
+		twsiSlave.slaveAddr.address = MV_BOARD_TDM_792_ADAPT_MODULE_ADDR;
+		twsiSlave.slaveAddr.type = MV_BOARD_TDM_MODULE_ADDR_TYPE;
+		twsiSlave.validOffset = MV_TRUE;
+		twsiSlave.offset = 0;
+		twsiSlave.moreThen256 = MV_FALSE;
+		if (mvBoardTwsiReadByteThruMux(MV_BOARD_TDM_MODULE_MUX_CHNUM, 0, &twsiSlave, &cfg) == MV_OK) {
+			BOARD_INFO(boardId)->boardTdmInfoIndex = BOARD_TDM_SLIC_792;
+			result = 1;
+		}
+	}
+
+#if 0
+	/* TDM-890 - no auto detection */
+	BOARD_INFO(boardId)->boardTdmInfoIndex = BOARD_TDM_SLIC_890;
+	result = 1;
+
+#endif
+	if (result == 0) {
+		/* No device is found */
+		BOARD_INFO(boardId)->boardTdmInfoIndex = (MV_8)-1;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvBoardPonModulesScan
+*
+* DESCRIPTION:
+*	Scan the on-board PON modules.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	modules - A bitmask of all modules detected on board
+*	(bitwise or from MV_BOARD_MODULE_ID_CLASS)
+*
+* RETURN:
+*       MV_STATUS - MV_OK, MV_ERROR.
+*
+*******************************************************************************/
+MV_STATUS mvBoardPonModulesScan(MV_U32 *modules)
+{
+	MV_U32 result = 0;
+
+	/* GPON / EPON */
+	if (mvCtrlIsGponMode() == MV_TRUE)
+		result |= BOARD_GPON_CONFIG;
+	else
+		result |= BOARD_EPON_CONFIG;
+
+	*modules = result;
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvBoardTwsiMuxChannelSet
+*
+* DESCRIPTION:
+*	Set the channel number of the on-board TWSI mux.
+*
+* INPUT:
+*	chNum	- The channel number to set.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_STATUS - MV_OK, MV_ERROR.
+*
+*******************************************************************************/
+MV_STATUS mvBoardTwsiMuxChannelSet(MV_U8 muxChNum)
+{
+	static MV_U8 currChNum = 0xFF;
+	MV_TWSI_SLAVE twsiSlave;
+	MV_TWSI_ADDR slave;
+
+	if (currChNum == muxChNum)
+		return MV_OK;
+
+	slave.type = ADDR7_BIT;
+	slave.address = 0;
+	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
+
+	twsiSlave.slaveAddr.address = mvBoardTwsiAddrGet(BOARD_TWSI_MUX, 0);
+	twsiSlave.slaveAddr.type = mvBoardTwsiAddrTypeGet(BOARD_TWSI_MUX, 0);
+	twsiSlave.validOffset = 0;
+	twsiSlave.offset = 0;
+	twsiSlave.moreThen256 = MV_FALSE;
+	muxChNum += 4;
+	return mvTwsiWrite(0, &twsiSlave, &muxChNum, 1);
+}
+
+/*******************************************************************************
+* mvBoardTwsiReadByteThruMux
+*
+* DESCRIPTION:
+*	Read a single byte from a TWSI device through the TWSI Mux.
+*
+* INPUT:
+*	muxChNum	- The Twsi Mux channel number to read through.
+*	chNum		- The TWSI channel number.
+*	pTwsiSlave	- The TWSI slave address.
+*	data		- Buffer to read into (1 byte).
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_STATUS - MV_OK, MV_ERROR.
+*
+*******************************************************************************/
+MV_STATUS mvBoardTwsiReadByteThruMux(MV_U8 muxChNum, MV_U8 chNum, MV_TWSI_SLAVE *pTwsiSlave, MV_U8 *data)
+{
+	MV_STATUS res;
+
+	/* Set Mux channel */
+	res = mvBoardTwsiMuxChannelSet(muxChNum);
+	if (res == MV_OK)
+		res = mvTwsiRead(chNum, pTwsiSlave, data, 1);
+
+	return res;
+}
+
+
+/*******************************************************************************
+* mvBoardModuleAutoDetectEnabled
+*
+* DESCRIPTION:
+*	Indicate if the board supports auto configuration and detection of
+*	modules. This is usually enabled for DB boards only.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_TRUE if auto-config/detection is enabled.
+*	MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_BOOL mvBoardModuleAutoDetectEnabled(void)
+{
+	MV_U32 boardId = mvBoardIdGet();
+
+	if (!((boardId >= BOARD_ID_BASE) && (boardId < MV_MAX_BOARD_ID)))
+		return MV_FALSE;
+
+	return BOARD_INFO(boardId)->moduleAutoDetect;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.h b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.h
new file mode 100755
index 0000000..1a2df45
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvLib.h
@@ -0,0 +1,569 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCmvBoardEnvLibh
+#define __INCmvBoardEnvLibh
+
+/* defines */
+/* The below constant macros defines the board I2C EEPROM data offsets */
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mvSysHwConfig.h"
+#include "boardEnv/mvBoardEnvSpec.h"
+#include "twsi/mvTwsi.h"
+
+/* DUART stuff for Tclk detection only */
+#define DUART_BAUD_RATE			115200
+#define MAX_CLOCK_MARGINE		5000000	/* Maximum detected clock margine */
+
+/* Voice devices assembly modes */
+#define DAISY_CHAIN_MODE	1
+#define DUAL_CHIP_SELECT_MODE   0
+#define INTERRUPT_TO_MPP        1
+#define INTERRUPT_TO_TDM	0
+
+#define BOARD_ETH_PORT_NUM  MV_ETH_MAX_PORTS
+#define BOARD_ETH_SWITCH_PORT_NUM	8
+#define BOARD_ETH_SWITCH_CPUPORT_NUM	2
+
+#define	MV_BOARD_MAX_USB_IF		1
+#define MV_BOARD_MAX_MPP		12
+#define MV_BOARD_NAME_LEN  		0x20
+
+/*
+#define MV_BOARD_CFG_IS_GPON_EN(cfg)	(cfg & 0x1)
+#define MV_BOARD_CFG_IS_EPON_EN(cfg)	(!MV_BOARD_CFG_IS_EPON(cfg))
+#define MV_BOARD_CFG_IS_QSGMII_EN(cfg)	((cfg & 0x8) && (cfg & 0x10))
+#define MV_BOARD_CFG_IS_SGMII_EN(cfg)	((cfg & 0x8) && (!(cfg & 0x10)))
+#define MV_BOARD_CFG_IS_SATA_EN(cfg)	(!(cfg & 0x8))
+#define MV_BOARD_CFG_IS_3FE_1GE_EN(cfg)	(cfg & 0x20)
+#define MV_BOARD_CFG_IS_4FE_EN(cfg)	(!MV_BOARD_CFG_IS_3FE_1GE_EN(cfg))
+*/
+/* DB_88F6601  Avanta board configuration */
+/* JP0		MAC connection 	0 – MAC0 connected to GBE PHY and MAC1  connected to LP SerDes
+							1 – MAC0 connected to LP SerDes */
+#define MV_BOARD_6601_CFG_MAC_SRC(cfg)	(cfg & 0x1)
+/* JP1	Ethernet capacity	0 – single Ethernet channel (GBE only)
+							1 – dual Eth. channels */
+#define MV_BOARD_6601_CFG_ETH_CAP(cfg)	(cfg & 0x2)
+/* JP2	LP SerDes connection	0 -  LP SerDes connected to GBE PHY
+								1 -  LP SerDes connected to SFP	*/
+#define MV_BOARD_6601_CFG_LP_SERDES_CON_MASK	0x4
+#define MV_BOARD_6601_CFG_LP_SERDES_CON(cfg)	(cfg & MV_BOARD_6601_CFG_LP_SERDES_CON_MASK)
+/* JP3	LP SerDes mode	0 -  LP SerDes at 1.25G mode
+						1 -  LP SerDes at 2.5G mode     */
+#define MV_BOARD_6601_CFG_LP_SERDES_MODE_MASK	0x8
+#define MV_BOARD_6601_CFG_LP_SERDES_MODE(cfg)	(cfg & MV_BOARD_6601_CFG_LP_SERDES_MODE_MASK)
+/* JP4	FXS presence 	0 – FXS presented
+						1 – FXS missing 			*/
+#define MV_BOARD_6601_CFG_FXS_MASK	0x10
+#define MV_BOARD_6601_CFG_FXS(cfg)	(cfg & MV_BOARD_6601_CFG_FXS_MASK)
+/* JP5	PON BEN polarity	0 – BEN active low
+							1 – BEN active high		*/
+#define MV_BOARD_6601_CFG_PON_POLARITY(cfg)	(cfg & 0x20)
+
+/* EPPROM Modules detection information */
+#define MV_BOARD_CFG_SW_SRC(cfg)	(cfg & 0x3)
+/* SW_SRC
+JP5 JP6
+ 0   0
+	If QSGMII module present: MAC0 => Switch => QSGMII
+ 0   1
+	If QSGMII module present: MAC1 => Switch => QSGMII
+	If QSGMII module not present: MAC0 => Switch => 3xFE
+ 1   0
+	If QSGMII module present: MAC0 => Switch => QSGMII.
+	If QSGMII module not present: MAC1 => Switch => 3xFE.
+ 1   1
+	If QSGMII module present: (MAC0 + MAC1) => Switch => QSGMII
+	If QSGMII module not present: (MAC0 + MAC1) => Switch => 3xFE
+*/
+#define MV_BOARD_CFG_SERDES_SRC(cfg)	((cfg & 0xC)>>2)
+/* SERDES_SRC
+JP8 JP10
+ 0   0    None
+ 1   0    SATA
+ 0   1    SGMII
+ 1   1    N/A
+*/
+#define MV_BOARD_CFG_RGMIIA_SRC(cfg)	((cfg & 0x30)>>4)
+/* RGMIIA_SRC
+JP11 JP12
+ 0    0   None
+ 1    0   MAC0 source
+ 0    1   MAC1 source
+ 1    1   Switch port 5 source
+*/
+#define MV_BOARD_CFG_FEGEPHY_SRC(cfg)	((cfg & 0xC0)>>6)
+/* GEPHY_SRC
+JP17 JP18
+ 0    0   None
+ 1    0   MAC1 source
+ 0    1   Switch port 4 source
+ 1    1   Switch port 5 source
+*/
+
+#define MV_BOARD_EEPROM_MODULE_ADDR		0x24
+#define MV_BOARD_EEPROM_MODULE_ADDR_TYPE	ADDR7_BIT
+
+#define MV_BOARD_RGMIIA_MODULE_ADDR		0x22
+#define MV_BOARD_RGMIIA_MODULE_ADDR_TYPE	ADDR7_BIT
+#define MV_BOARD_RGMIIA_MODULE_MUX_CHNUM	1
+
+#define MV_BOARD_RGMIIB_MODULE_ADDR		0x20
+#define MV_BOARD_RGMIIB_MODULE_ADDR_TYPE	ADDR7_BIT
+#define MV_BOARD_RGMIIB_MODULE_MUX_CHNUM	1
+
+#define MV_BOARD_QSGMII_MODULE_ADDR		0x23
+#define MV_BOARD_QSGMII_MODULE_ADDR_TYPE	ADDR7_BIT
+#define MV_BOARD_QSGMII_MODULE_MUX_CHNUM	1
+
+#define MV_BOARD_GE_SFP_MODULE_ADDR		0x50
+#define MV_BOARD_GE_SFP_MODULE_ADDR_TYPE	ADDR7_BIT
+#define MV_BOARD_GE_SFP_MODULE_MUX_CHNUM	1
+
+#define MV_BOARD_XCVR_MUX_ADDR			0x70
+#define MV_BOARD_XCVR_MUX_ADDR_TYPE		ADDR7_BIT
+
+#define MV_BOARD_TDM_792_ADAPT_MODULE_ADDR	0x27
+#define MV_BOARD_TDM_880_MODULE_ADDR		0x26
+#define MV_BOARD_TDM_3215_MODULE_ADDR		0x23
+#define MV_BOARD_TDM_MODULE_ADDR_TYPE		ADDR7_BIT
+#define MV_BOARD_TDM_MODULE_MUX_CHNUM		0
+
+#define MV_BOARD_SWITCH_SCAN_MODE_SATR_IDX	0
+#define MV_BOARD_SWITCH_SCAN_MODE(x)		((x & 1) == 1)
+#define MV_BOARD_SWITCH_SCAN_MODE_MASK		0x1
+
+
+typedef struct _boardData {
+	MV_U32 magic;
+	MV_U16 boardId;
+	MV_U8 boardVer;
+	MV_U8 boardRev;
+	MV_U32 reserved1;
+	MV_U32 reserved2;
+} BOARD_DATA;
+
+typedef enum _devBoardMppGroupClass {
+	MV_BOARD_MPP_GROUP_1,
+	MV_BOARD_MPP_GROUP_2,
+	MV_BOARD_MPP_GROUP_3,
+	MV_BOARD_MAX_MPP_GROUP
+} MV_BOARD_MPP_GROUP_CLASS;
+
+typedef enum _devBoardMppTypeClass {
+	MV_BOARD_AUTO,
+	MV_BOARD_TDM_2CH,
+	MV_BOARD_TDM_32CH,
+	MV_BOARD_GE0,
+	MV_BOARD_GE1,
+	MV_BOARD_SW_P5,
+	MV_BOARD_SW_P6,
+	MV_BOARD_OTHER
+} MV_BOARD_MPP_TYPE_CLASS;
+
+#ifdef MV_TDM_2CHANNELS
+#define MV_BOARD_TDM 	MV_BOARD_TDM_2CH
+#else
+#define MV_BOARD_TDM	MV_BOARD_TDM_32CH
+#endif
+
+typedef enum {
+	MV_BOARD_MODULE_TS_ID = 0x00001,
+	MV_BOARD_MODULE_QSGMII_ID = 0x00002,
+	MV_BOARD_MODULE_SGMII_ID = 0x00004,
+	MV_BOARD_MODULE_GE_SFP_ID = 0x00008,
+	MV_BOARD_MODULE_RGMIIA_ID = 0x00010,
+	MV_BOARD_MODULE_RGMIIB_ID = 0x00020,
+	MV_BOARD_MODULE_MIIA_ID = 0x00040,
+	MV_BOARD_MODULE_MIIB_ID = 0x00080,
+	MV_BOARD_MODULE_TDM_1_ID = 0x00100,
+	MV_BOARD_MODULE_TDM_2_ID = 0x00200,
+	MV_BOARD_MODULE_TDM_3_ID = 0x00400,
+	MV_BOARD_MODULE_TDM_4_ID = 0x00800,
+	MV_BOARD_MODULE_GPON_ID = 0x01000,
+	MV_BOARD_MODULE_EPON_ID = 0x02000,
+	MV_BOARD_MODULE_4FE_PHY_ID = 0x04000,
+	MV_BOARD_MODULE_FE_GE_PHY_ID = 0x08000,
+	MV_BOARD_MODULE_SATA_ID = 0x10000,
+	MV_BOARD_MODULE_SDIO_ID = 0x20000,
+	MV_BOARD_MODULE_OTHER_ID = 0x80000
+} MV_BOARD_MODULE_ID_CLASS;
+
+typedef struct _boardMppTypeInfo {
+	MV_BOARD_MPP_TYPE_CLASS boardMppTdm;
+
+	/* Ethernet / Sata complex                      */
+	/* A bitmask of MV_ETH_SATA_COMPLEX_OPTIONS     */
+	MV_U32 ethSataComplexOpt;
+	MV_U32 ethPortsMode;	/* bitmask of MV_ETH_PORT_MODE */
+} MV_BOARD_MPP_TYPE_INFO;
+
+typedef enum _devBoardClass {
+	BOARD_DEV_NOR_FLASH,
+	BOARD_DEV_NAND_FLASH,
+	BOARD_DEV_SEVEN_SEG,
+	BOARD_DEV_FPGA,
+	BOARD_DEV_SRAM,
+	BOARD_DEV_SPI_FLASH,
+	BOARD_DEV_OTHER,
+} MV_BOARD_DEV_CLASS;
+
+typedef enum _devTwsiBoardClass {
+	BOARD_TWSI_RTC,
+	BOARD_DEV_TWSI_EXP,
+	BOARD_DEV_TWSI_SATR,
+	BOARD_TWSI_MUX,
+	BOARD_TWSI_AUDIO_DEC,
+	BOARD_TWSI_OTHER
+} MV_BOARD_TWSI_CLASS;
+
+typedef enum _devGppBoardClass {
+	BOARD_GPP_RTC,
+	BOARD_GPP_MV_SWITCH,
+	BOARD_GPP_USB_VBUS,
+	BOARD_GPP_USB_VBUS_EN,
+	BOARD_GPP_USB_OC,
+	BOARD_GPP_USB_HOST_DEVICE,
+	BOARD_GPP_REF_CLCK,
+	BOARD_GPP_VOIP_SLIC,
+	BOARD_GPP_LIFELINE,
+	BOARD_GPP_BUTTON,
+	BOARD_GPP_TS_BUTTON_C,
+	BOARD_GPP_TS_BUTTON_U,
+	BOARD_GPP_TS_BUTTON_D,
+	BOARD_GPP_TS_BUTTON_L,
+	BOARD_GPP_TS_BUTTON_R,
+	BOARD_GPP_POWER_BUTTON,
+	BOARD_GPP_RESTOR_BUTTON,
+	BOARD_GPP_WPS_BUTTON,
+	BOARD_GPP_HDD0_POWER,
+	BOARD_GPP_HDD1_POWER,
+	BOARD_GPP_FAN_POWER,
+	BOARD_GPP_RESET,
+	BOARD_GPP_POWER_ON_LED,
+	BOARD_GPP_HDD_POWER,
+	BOARD_GPP_SDIO_POWER,
+	BOARD_GPP_SDIO_DETECT,
+	BOARD_GPP_SDIO_WP,
+	BOARD_GPP_SWITCH_PHY_INT,
+	BOARD_GPP_TSU_DIRCTION,
+	BOARD_GPP_PEX_RESET,
+	BOARD_GPP_CONF,
+	BOARD_GPP_PON_XVR_TX,
+	BOARD_GPP_SYS_LED,
+	BOARD_GPP_PON_LED,
+	BOARD_GPP_PON_XVR_TX_POWER,
+	BOARD_GPP_PON_XVR_TX_IND,
+	BOARD_GPP_OTHER
+} MV_BOARD_GPP_CLASS;
+
+typedef struct _devCsInfo {
+	MV_U8 deviceCS;
+	MV_U32 params;
+	MV_U32 devClass;	/* MV_BOARD_DEV_CLASS */
+	MV_U8 devWidth;
+} MV_DEV_CS_INFO;
+
+typedef struct _boardSwitchInfo {
+	MV_32 switchIrq;
+	MV_32 switchPort[BOARD_ETH_SWITCH_PORT_NUM];
+	MV_32 cpuPort;
+	MV_32 connectedPort[MV_ETH_MAX_PORTS];
+	MV_32 smiScanMode;
+	MV_32 quadPhyAddr;
+	MV_U32 forceLinkMask; /* Bitmask of switch ports to have force link (1Gbps) */
+} MV_BOARD_SWITCH_INFO;
+
+typedef struct _boardLedInfo {
+	MV_U8 activeLedsNumber;
+	MV_U8 ledsPolarity;	/* '0' or '1' to turn on led */
+	MV_U8 *gppPinNum;	/* Pointer to GPP values */
+} MV_BOARD_LED_INFO;
+
+typedef struct _boardGppInfo {
+	MV_BOARD_GPP_CLASS devClass;
+	MV_U8 gppPinNum;
+} MV_BOARD_GPP_INFO;
+
+typedef struct _boardTwsiInfo {
+	MV_BOARD_TWSI_CLASS devClass;
+	MV_U8 twsiDevAddr;
+	MV_U8 twsiDevAddrType;
+} MV_BOARD_TWSI_INFO;
+
+typedef enum _boardMacSpeed {
+	BOARD_MAC_SPEED_10M,
+	BOARD_MAC_SPEED_100M,
+	BOARD_MAC_SPEED_1000M,
+	BOARD_MAC_SPEED_AUTO,
+} MV_BOARD_MAC_SPEED;
+
+typedef struct _boardMacInfo {
+	MV_BOARD_MAC_SPEED boardMacSpeed;
+	MV_U8 boardEthSmiAddr;
+} MV_BOARD_MAC_INFO;
+
+typedef struct _boardMppInfo {
+	MV_U32 mppGroup[MV_BOARD_MAX_MPP];
+} MV_BOARD_MPP_INFO;
+
+typedef enum {
+	BOARD_EPON_CONFIG,
+	BOARD_GPON_CONFIG,
+	BOARD_PON_NONE,
+	BOARD_PON_AUTO
+} MV_BOARD_PON_CONFIG;
+
+typedef struct {
+	MV_U8 spiCs;
+} MV_BOARD_TDM_INFO;
+
+typedef struct {
+	MV_U8 spiId;
+} MV_BOARD_TDM_SPI_INFO;
+
+typedef enum {
+	BOARD_TDM_SLIC_880 = 0,
+	BOARD_TDM_SLIC_792,
+	BOARD_TDM_SLIC_3215,
+	BOARD_TDM_SLIC_890,
+	BOARD_TDM_SLIC_OTHER,
+	BOARD_TDM_SLIC_COUNT
+} MV_BOARD_TDM_SLIC_TYPE;
+
+typedef struct {
+	MV_U32	reg;
+	MV_U32	mask;
+	MV_U32	val;
+} MV_BOARD_SPEC_INIT;
+
+typedef struct _boardInfo {
+	char boardName[MV_BOARD_NAME_LEN];
+	MV_U8 numBoardMppTypeValue;
+	MV_BOARD_MPP_TYPE_INFO *pBoardMppTypeValue;
+	MV_U8 numBoardMppConfigValue;
+	MV_BOARD_MPP_INFO *pBoardMppConfigValue;
+	MV_U32 intsGppMaskLow;
+	MV_U32 intsGppMaskMid;
+	MV_U32 intsGppMaskHigh;
+	MV_U8 numBoardDeviceIf;
+	MV_DEV_CS_INFO *pDevCsInfo;
+	MV_U8 numBoardTwsiDev;
+	MV_BOARD_TWSI_INFO *pBoardTwsiDev;
+	MV_U8 numBoardMacInfo;
+	MV_BOARD_MAC_INFO *pBoardMacInfo;
+	MV_U8 numBoardGppInfo;
+	MV_BOARD_GPP_INFO *pBoardGppInfo;
+	MV_U8 activeLedsNumber;
+	MV_U8 *pLedGppPin;
+	MV_U8 ledsPolarity;	/* '0' or '1' to turn on led */
+
+	/* GPP values */
+	MV_U32 gppOutEnValLow;
+	MV_U32 gppOutEnValMid;
+	MV_U32 gppOutEnValHigh;
+	MV_U32 gppOutValLow;
+	MV_U32 gppOutValMid;
+	MV_U32 gppOutValHigh;
+	MV_U32 gppPolarityValLow;
+	MV_U32 gppPolarityValMid;
+	MV_U32 gppPolarityValHigh;
+
+	/* External Switch Configuration */
+	MV_BOARD_SWITCH_INFO *pSwitchInfo;
+	MV_U32 switchInfoNum;
+
+	/* PON configuration. */
+	MV_BOARD_PON_CONFIG ponConfigValue;
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	MV_U8 numBoardTdmInfo[BOARD_TDM_SLIC_COUNT];
+	MV_BOARD_TDM_INFO *pBoardTdmInt2CsInfo[BOARD_TDM_SLIC_COUNT];
+	MV_8 boardTdmInfoIndex;
+
+	/* Board specific initialization. Performed before initializing the
+	** SoC. */
+	MV_BOARD_SPEC_INIT	*pBoardSpecInit;
+
+	/* Deep-Idle power up delay */
+	MV_U32 deepIdlePwrUpDelay;
+
+	/* NAND init params */
+	MV_BOOL nandFlashParamsValid;
+	MV_U32 nandFlashReadParams;
+	MV_U32 nandFlashWriteParams;
+	MV_U32 nandFlashControl;
+	MV_BOARD_TDM_SPI_INFO *pBoardTdmSpiInfo;
+
+	/* Indicates if auto-detection of modules is enabled on this board. */
+	/* Set to MV_FALSE for any board that is not a DB. */
+	MV_BOOL	moduleAutoDetect;
+} MV_BOARD_INFO;
+
+/* For backward compatability with Legacy mode */
+#define mvBoardIsSwitchConnected(port)  (mvBoardSwitchConnectedPortGet(port) != -1)
+#define mvBoardLinkStatusIrqGet(port)   mvBoardSwitchIrqGet()
+
+MV_VOID mvBoardEnvInit(MV_VOID);
+MV_U16 mvBoardModelGet(MV_VOID);
+MV_U16 mvBoardRevGet(MV_VOID);
+MV_STATUS mvBoardNameGet(char *pNameBuff);
+MV_BOARD_SPEC_INIT *mvBoardSpecInitGet(MV_VOID);
+MV_U32 mvBoardPwrUpDelayGet(MV_VOID);
+MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum);
+MV_BOOL mvBoardIsPortInRgmii(MV_U32 ethPortNum);
+MV_U32 mvBoardEthPortsModeGet(void);
+MV_32 mvBoardPhyAddrGet(MV_U32 ethPortNum);
+MV_STATUS mvBoardPhyAddrSet(MV_U32 ethPortNum, MV_32 phyAddr);
+
+MV_BOOL mvBoardSwitchSnglChipAddModeGet(MV_VOID);
+MV_STATUS mvBoardSwitchSnglChipAddModeSet(MV_BOOL enable);
+MV_32 mvBoardSwitchIrqGet(MV_VOID);
+MV_32 mvBoardSwitchConnectedPortGet(MV_U32 ethPortNum);
+/* Map front panel connector number to switch port number */
+MV_32 mvBoardSwitchPortGet(MV_U32 switchIdx, MV_U32 boardPortNum);
+MV_STATUS mvBoardSwitchInfoUpdate(MV_VOID);
+/* Map front panel connector number to switch port number */
+MV_32 mvBoardSwitchPortMap(MV_U32 switchIdx, MV_U32 switchPortNum);
+MV_32 mvBoardSwitchCpuPortGet(MV_U32 switchIdx);
+MV_U32 mvBoardSwitchPortForceLinkGet(MV_U32 switchIdx);
+MV_32 mvBoardSmiScanModeGet(MV_U32 switchIdx);
+MV_32 mvBoardQuadPhyAddrGet(MV_U32 switchIdx);
+MV_32 mvBoardSwitchNumPortsGet(MV_VOID);
+MV_BOOL mvBoardIsQsgmiiModuleConnected(MV_VOID);
+MV_32 mvBoardGePhySwitchPortGet(MV_VOID);
+MV_32 mvBoardRgmiiASwitchPortGet(MV_VOID);
+MV_BOOL mvBoardPhySpecInitGet(MV_U32 *regOff, MV_U32 *data);
+MV_U32 mvBoardTclkGet(MV_VOID);
+MV_U32 mvBoardSysClkGet(MV_VOID);
+MV_U32 mvBoardDebugLedNumGet(MV_U32 boardId);
+MV_VOID mvBoardDebugLed(MV_U32 hexNum);
+MV_32 mvBoarGpioPinNumGet(MV_BOARD_GPP_CLASS class, MV_U32 index);
+MV_VOID mvBoardReset(MV_VOID);
+MV_32 mvBoardResetGpioPinGet(MV_VOID);
+MV_32 mvBoardSDIOGpioPinGet(MV_BOARD_GPP_CLASS type);
+MV_32 mvBoardUSBVbusGpioPinGet(MV_32 devId);
+MV_32 mvBoardUSBVbusEnGpioPinGet(MV_32 devId);
+MV_U32 mvBoardGpioIntMaskGet(MV_U32 gppGrp);
+MV_32 mvBoardMppGet(MV_U32 mppGroupNum);
+MV_U32 mvBoardEthComplexConfigGet(MV_VOID);
+MV_VOID mvBoardEthComplexConfigSet(MV_U32 ethConfig);
+MV_U32 mvBoardPonConfigGet(MV_VOID);
+MV_VOID mvBoardPonConfigSet(MV_U32 ponConfig);
+MV_U32 mvBoardGppConfigGet(MV_VOID);
+MV_VOID mvBoardModuleConfigSet(MV_U32 modConfig);
+MV_VOID mvBoardModuleConfigGet(MV_U32 *modConfig);
+MV_VOID mvBoardMppIdUpdate(MV_VOID);
+MV_32 mvBoardTdmSpiModeGet(MV_VOID);
+MV_U8 mvBoardTdmDevicesCountGet(MV_VOID);
+MV_U8 mvBoardTdmSpiCsGet(MV_U8 devId);
+MV_U8 mvBoardTdmSpiIdGet(MV_VOID);
+MV_VOID mvBoardMppModuleTypePrint(MV_VOID);
+MV_BOOL mvBoardIsGbEPortConnected(MV_U32 ethPortNum);
+MV_32 mvBoardGetDevicesNumber(MV_BOARD_DEV_CLASS devClass);
+MV_32 mvBoardGetDeviceBaseAddr(MV_32 devNum, MV_BOARD_DEV_CLASS devClass);
+MV_32 mvBoardGetDeviceBusWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass);
+MV_32 mvBoardGetDeviceWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass);
+MV_32 mvBoardGetDeviceWinSize(MV_32 devNum, MV_BOARD_DEV_CLASS devClass);
+MV_U32 boardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devClass);
+MV_U8 mvBoardTwsiAddrTypeGet(MV_BOARD_TWSI_CLASS twsiClass, MV_U32 index);
+MV_U8 mvBoardTwsiAddrGet(MV_BOARD_TWSI_CLASS twsiClass, MV_U32 index);
+MV_32 mvBoardNandWidthGet(MV_VOID);
+MV_U32 mvBoardIdGet(MV_VOID);
+
+MV_U8 mvBoardTwsiSatRGet(MV_U8 devNum, MV_U8 regNum);
+MV_STATUS mvBoardTwsiSatRSet(MV_U8 devNum, MV_U8 regNum, MV_U8 regVal);
+MV_U8 mvBoardFreqGet(MV_VOID);
+MV_STATUS mvBoardFreqSet(MV_U8 freqVal);
+MV_U8 mvBoardSSCGGet(MV_VOID);
+MV_STATUS mvBoardSSCGSet(MV_U8 val);
+MV_U8 mvBoardTClkGet(MV_VOID);
+MV_STATUS mvBoardTClkSet(MV_U8 val);
+MV_U8 mvBoardPexClkGet(MV_U8 pexIf);
+MV_STATUS mvBoardPexClkSet(MV_U8 pexIf, MV_U8 val);
+MV_U8 mvBoardSaRL2ExistGet(MV_VOID);
+MV_U8 mvBoardSaRL2ExistSet(MV_U8 val);
+MV_U8 mvBoardPonGet(MV_VOID);
+MV_STATUS mvBoardPonSet(MV_U8 val);
+
+MV_STATUS mvBoardEthSataModulesScan(MV_U32 *modules, MV_ETH_COMPLEX_IF_SOURCES *ethSrcCfg);
+MV_STATUS mvBoardIsSdioEnabled(MV_VOID);
+MV_STATUS mvBoardTdmModulesScan(MV_VOID);
+MV_STATUS mvBoardPonModulesScan(MV_U32 *modules);
+MV_STATUS mvBoardTwsiMuxChannelSet(MV_U8 muxChNum);
+MV_STATUS mvBoardTwsiReadByteThruMux(MV_U8 muxChNum, MV_U8 chNum, MV_TWSI_SLAVE *pTwsiSlave, MV_U8 *data);
+MV_BOARD_MAC_SPEED mvBoardMacSpeedGet(MV_U32 ethPortNum);
+MV_STATUS mvBoardMacSpeedSet(MV_U32 ethPortNum, MV_BOARD_MAC_SPEED speed);
+MV_STATUS mvBoardIsInternalSwitchConnected(MV_U32 ethPortNum);
+MV_BOARD_MPP_TYPE_CLASS mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass);
+MV_BOOL mvBoardModuleAutoDetectEnabled(void);
+#endif /* __INCmvBoardEnvLibh */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
new file mode 100755
index 0000000..7d320f0
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.c
@@ -0,0 +1,1191 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include "mvCommon.h"
+#include "mvBoardEnvLib.h"
+#include "mvBoardEnvSpec.h"
+#include "twsi/mvTwsi.h"
+
+/***************************************************************************
+** RD-88F6510-SFU
+****************************************************************************/
+
+#define RD_88F6510_BOARD_NAND_READ_PARAMS	0x000C0282
+#define RD_88F6510_BOARD_NAND_WRITE_PARAMS	0x00010305
+/* NAND care support for small page chips */
+#define RD_88F6510_BOARD_NAND_CONTROL		0x01c00543
+
+MV_BOARD_TWSI_INFO rd88f6510InfoBoardTwsiDev[] = {
+	/* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+};
+
+MV_BOARD_MAC_INFO rd88f6510InfoBoardMacInfo[] = {
+	/* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */
+	{BOARD_MAC_SPEED_1000M, 0x0}
+	,
+	{BOARD_MAC_SPEED_1000M, 0x9},
+	{N_A,N_A}
+
+/* 	{BOARD_MAC_SPEED_AUTO, 0x9} */
+
+};
+
+MV_BOARD_MPP_TYPE_INFO rd88f6510InfoBoardMppTypeInfo[] = {
+	{
+	 .boardMppTdm = MV_BOARD_TDM_2CH,
+	 .ethSataComplexOpt = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_FE3PHY | ESC_OPT_GEPHY_SW_P0,
+	 .ethPortsMode = 0x0
+	 }
+};
+
+MV_BOARD_GPP_INFO rd88f6510InfoBoardGppInfo[] = {
+	/* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */
+	{BOARD_GPP_SYS_LED, 44},
+	{BOARD_GPP_PON_LED, 45},
+	{BOARD_GPP_PEX_RESET, 67},
+	{BOARD_GPP_PON_XVR_TX, 68}
+};
+
+MV_DEV_CS_INFO rd88f6510InfoBoardDeCsInfo[] = {
+	/*{deviceCS, params, devType, devWidth} */
+#if defined(MTD_NAND_LNC)
+	{NAND_NOR_CS, N_A, BOARD_DEV_NAND_FLASH, 8},	/* NAND DEV */
+#endif
+#if defined(MV_SPI)
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},		/* SPI DEV */
+#endif
+#if !defined(MTD_NAND_LNC) && !defined(MV_SPI)
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO rd88f6510InfoBoardMppConfigValue[] = {
+	{{
+		RD_88F6510_MPP0_7,
+		RD_88F6510_MPP8_15,
+		RD_88F6510_MPP16_23,
+		RD_88F6510_MPP24_31,
+		RD_88F6510_MPP32_39,
+		RD_88F6510_MPP40_47,
+		RD_88F6510_MPP48_55,
+		RD_88F6510_MPP56_63,
+		RD_88F6510_MPP64_71,
+		RD_88F6510_MPP72_79,
+		RD_88F6510_MPP80_87,
+		RD_88F6510_MPP88_88
+	  }
+	 }
+};
+
+MV_BOARD_SWITCH_INFO rd88f6510InfoBoardSwitchValue[] = {
+	{
+	 .switchIrq = 29,	/* set to -1 for timer operation */
+	 .switchPort = {1, 2, 3, 0, -1, -1, -1, -1},
+	 .cpuPort = 4,
+	 .connectedPort = {4, 5, -1},
+	 .smiScanMode = 1,
+	 .quadPhyAddr = 0,
+	 .forceLinkMask = 0x0
+	 }
+};
+
+MV_BOARD_TDM_INFO rd88f6510Tdm880[] = { {1} };
+
+MV_BOARD_TDM_SPI_INFO rd88f6510TdmSpiInfo[] = { {0} };
+
+MV_BOARD_INFO rd88f6510Info = {
+	.boardName = "RD-88F6510-SFU",
+	.numBoardMppTypeValue = MV_ARRAY_SIZE(rd88f6510InfoBoardMppTypeInfo),
+	.pBoardMppTypeValue = rd88f6510InfoBoardMppTypeInfo,
+	.numBoardMppConfigValue = MV_ARRAY_SIZE(rd88f6510InfoBoardMppConfigValue),
+	.pBoardMppConfigValue = rd88f6510InfoBoardMppConfigValue,
+	.intsGppMaskLow = 0,
+	.intsGppMaskMid = 0,
+	.intsGppMaskHigh = 0,
+	.numBoardDeviceIf = MV_ARRAY_SIZE(rd88f6510InfoBoardDeCsInfo),
+	.pDevCsInfo = rd88f6510InfoBoardDeCsInfo,
+	.numBoardTwsiDev = MV_ARRAY_SIZE(rd88f6510InfoBoardTwsiDev),
+	.pBoardTwsiDev = rd88f6510InfoBoardTwsiDev,
+	.numBoardMacInfo = MV_ARRAY_SIZE(rd88f6510InfoBoardMacInfo),
+	.pBoardMacInfo = rd88f6510InfoBoardMacInfo,
+	.numBoardGppInfo = MV_ARRAY_SIZE(rd88f6510InfoBoardGppInfo),
+	.pBoardGppInfo = rd88f6510InfoBoardGppInfo,
+	.activeLedsNumber = 0,
+	.pLedGppPin = NULL,
+	.ledsPolarity = 0,
+
+	/* GPP values */
+	.gppOutEnValLow = RD_88F6510_GPP_OUT_ENA_LOW,
+	.gppOutEnValMid = RD_88F6510_GPP_OUT_ENA_MID,
+	.gppOutEnValHigh = RD_88F6510_GPP_OUT_ENA_HIGH,
+	.gppOutValLow = RD_88F6510_GPP_OUT_VAL_LOW,
+	.gppOutValMid = RD_88F6510_GPP_OUT_VAL_MID,
+	.gppOutValHigh = RD_88F6510_GPP_OUT_VAL_HIGH,
+	.gppPolarityValLow = RD_88F6510_GPP_POL_LOW,
+	.gppPolarityValMid = RD_88F6510_GPP_POL_MID,
+	.gppPolarityValHigh = RD_88F6510_GPP_POL_HIGH,
+
+	/* External Switch Configuration */
+	.pSwitchInfo = rd88f6510InfoBoardSwitchValue,
+	.switchInfoNum = MV_ARRAY_SIZE(rd88f6510InfoBoardSwitchValue),
+
+	/* PON configuration. */
+	.ponConfigValue = BOARD_PON_AUTO,
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	.numBoardTdmInfo = {1}
+	,
+	.pBoardTdmInt2CsInfo = {rd88f6510Tdm880,
+				}
+	,
+	.boardTdmInfoIndex = 0,
+
+	.deepIdlePwrUpDelay = 0x80000,
+
+	/* NAND init params */
+	.nandFlashParamsValid = MV_TRUE,
+	.nandFlashReadParams = RD_88F6510_BOARD_NAND_READ_PARAMS,
+	.nandFlashWriteParams = RD_88F6510_BOARD_NAND_WRITE_PARAMS,
+	.nandFlashControl = RD_88F6510_BOARD_NAND_CONTROL,
+	.pBoardTdmSpiInfo = rd88f6510TdmSpiInfo,
+
+	/* Disable modules auto-detection. */
+	.moduleAutoDetect = MV_FALSE
+};
+
+/***************************************************************************
+** RD-88F6560-GW
+****************************************************************************/
+
+#define RD_88F6560_BOARD_NAND_READ_PARAMS	0x000C0282
+#define RD_88F6560_BOARD_NAND_WRITE_PARAMS	0x00010305
+/* NAND care support for small page chips */
+#define RD_88F6560_BOARD_NAND_CONTROL		0x01c00543
+
+MV_BOARD_TWSI_INFO rd88f6560InfoBoardTwsiDev[] = {
+	/* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+};
+
+MV_BOARD_MAC_INFO rd88f6560InfoBoardMacInfo[] = {
+	/* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */
+	{BOARD_MAC_SPEED_1000M, 0x8}
+	,
+	{BOARD_MAC_SPEED_AUTO, 0x9},
+	{N_A,N_A}
+};
+
+MV_BOARD_MPP_TYPE_INFO rd88f6560InfoBoardMppTypeInfo[] = {
+	{
+	 .boardMppTdm = MV_BOARD_TDM_2CH,
+	 .ethSataComplexOpt = ESC_OPT_QSGMII | ESC_OPT_GEPHY_MAC1 | ESC_OPT_MAC0_2_SW_P4,
+	 .ethPortsMode = 0x0
+	}
+};
+
+MV_BOARD_GPP_INFO rd88f6560InfoBoardGppInfo[] = {
+	/* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */
+	{BOARD_GPP_SDIO_WP, 31},
+	{BOARD_GPP_HDD_POWER, 37},
+    {BOARD_GPP_PON_XVR_TX, 37},
+	{BOARD_GPP_FAN_POWER, 40},
+	{BOARD_GPP_WPS_BUTTON, 47},
+	{BOARD_GPP_SDIO_DETECT, 48},
+	{BOARD_GPP_PON_LED, 49},
+	{BOARD_GPP_USB_VBUS, 58},
+	{BOARD_GPP_USB_OC, 59},
+	{BOARD_GPP_CONF, 60},
+	{BOARD_GPP_CONF, 61},
+	{BOARD_GPP_CONF, 62},
+	{BOARD_GPP_SYS_LED, 68},
+	{BOARD_GPP_PEX_RESET, 77}
+};
+
+MV_DEV_CS_INFO rd88f6560InfoBoardDeCsInfo[] = {
+	/*{deviceCS, params, devType, devWidth} */
+#if defined(MTD_NAND_LNC)
+	{NAND_NOR_CS, N_A, BOARD_DEV_NAND_FLASH, 8},	/* NAND DEV */
+#endif
+#if defined(MV_SPI)
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},	/* SPI DEV */
+#endif
+#if !defined(MTD_NAND_LNC) && !defined(MV_SPI)
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO rd88f6560InfoBoardMppConfigValue[] = {
+	{{
+	  RD_88F6560_MPP0_7,
+	  RD_88F6560_MPP8_15,
+	  RD_88F6560_MPP16_23,
+	  RD_88F6560_MPP24_31,
+	  RD_88F6560_MPP32_39,
+	  RD_88F6560_MPP40_47,
+	  RD_88F6560_MPP48_55,
+	  RD_88F6560_MPP56_63,
+	  RD_88F6560_MPP64_71,
+	  RD_88F6560_MPP72_79,
+	  RD_88F6560_MPP80_87,
+	  RD_88F6560_MPP88_88
+	  }
+	 }
+};
+
+MV_BOARD_SWITCH_INFO rd88f6560InfoBoardSwitchValue[] = {
+	{
+	 .switchIrq = 29,	/* set to -1 for timer operation */
+	 .switchPort = {1, 2, 3, 0, -1, -1, -1, -1},
+	 .cpuPort = 4,
+	 .connectedPort = {4, -1, -1},
+	 .smiScanMode = 2,
+	 .quadPhyAddr = 0,
+	 .forceLinkMask = 0x0
+	 }
+};
+
+MV_U8 rd88f6560LedGppPin[] = { 68 };
+
+MV_BOARD_TDM_INFO rd88f6560Tdm880[] = { {0}, {1} };
+
+MV_BOARD_TDM_SPI_INFO rd88f6560TdmSpiInfo[] = { {1} };
+
+MV_BOARD_SPEC_INIT rd88f6560BoardSpecInit[] = {
+	{
+		.reg = PMU_POWER_IF_POLARITY_REG,
+		.mask = (BIT1),
+		.val = 0
+	},
+	{
+		.reg = TBL_TERM,
+		.val = TBL_TERM
+	}
+};
+
+MV_BOARD_INFO rd88f6560Info = {
+	.boardName = "RD-88F6560-GW",
+	.numBoardMppTypeValue = MV_ARRAY_SIZE(rd88f6560InfoBoardMppTypeInfo),
+	.pBoardMppTypeValue = rd88f6560InfoBoardMppTypeInfo,
+	.numBoardMppConfigValue = MV_ARRAY_SIZE(rd88f6560InfoBoardMppConfigValue),
+	.pBoardMppConfigValue = rd88f6560InfoBoardMppConfigValue,
+	.intsGppMaskLow = 0,
+	.intsGppMaskMid = 0,
+	.intsGppMaskHigh = 0,
+	.numBoardDeviceIf = MV_ARRAY_SIZE(rd88f6560InfoBoardDeCsInfo),
+	.pDevCsInfo = rd88f6560InfoBoardDeCsInfo,
+	.numBoardTwsiDev = MV_ARRAY_SIZE(rd88f6560InfoBoardTwsiDev),
+	.pBoardTwsiDev = rd88f6560InfoBoardTwsiDev,
+	.numBoardMacInfo = MV_ARRAY_SIZE(rd88f6560InfoBoardMacInfo),
+	.pBoardMacInfo = rd88f6560InfoBoardMacInfo,
+	.numBoardGppInfo = MV_ARRAY_SIZE(rd88f6560InfoBoardGppInfo),
+	.pBoardGppInfo = rd88f6560InfoBoardGppInfo,
+	.activeLedsNumber = MV_ARRAY_SIZE(rd88f6560LedGppPin),
+	.pLedGppPin = rd88f6560LedGppPin,
+	.ledsPolarity = 0,
+
+	/* GPP values */
+	.gppOutEnValLow = RD_88F6560_GPP_OUT_ENA_LOW,
+	.gppOutEnValMid = RD_88F6560_GPP_OUT_ENA_MID,
+	.gppOutEnValHigh = RD_88F6560_GPP_OUT_ENA_HIGH,
+	.gppOutValLow = RD_88F6560_GPP_OUT_VAL_LOW,
+	.gppOutValMid = RD_88F6560_GPP_OUT_VAL_MID,
+	.gppOutValHigh = RD_88F6560_GPP_OUT_VAL_HIGH,
+	.gppPolarityValLow = RD_88F6560_GPP_POL_LOW,
+	.gppPolarityValMid = RD_88F6560_GPP_POL_MID,
+	.gppPolarityValHigh = RD_88F6560_GPP_POL_HIGH,
+
+	/* External Switch Configuration */
+	.pSwitchInfo = rd88f6560InfoBoardSwitchValue,
+	.switchInfoNum = MV_ARRAY_SIZE(rd88f6560InfoBoardSwitchValue),
+
+	/* PON configuration. */
+	.ponConfigValue = BOARD_GPON_CONFIG,
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	.numBoardTdmInfo = {2},
+	.pBoardTdmInt2CsInfo = { rd88f6560Tdm880 },
+	.boardTdmInfoIndex = 0,
+
+	.pBoardSpecInit = rd88f6560BoardSpecInit,
+
+	.deepIdlePwrUpDelay = 2400, /* 12 uS */
+
+	/* NAND init params */
+	.nandFlashParamsValid = MV_TRUE,
+	.nandFlashReadParams = RD_88F6560_BOARD_NAND_READ_PARAMS,
+	.nandFlashWriteParams = RD_88F6560_BOARD_NAND_WRITE_PARAMS,
+	.nandFlashControl = RD_88F6560_BOARD_NAND_CONTROL,
+	.pBoardTdmSpiInfo = rd88f6560TdmSpiInfo,
+
+	/* Disable modules auto-detection. */
+	.moduleAutoDetect = MV_FALSE
+};
+
+/***************************************************************************
+** RD-88F6530-MDU
+****************************************************************************/
+#define RD_88F6530_BOARD_NAND_READ_PARAMS	0x000C0282
+#define RD_88F6530_BOARD_NAND_WRITE_PARAMS	0x00010305
+#define RD_88F6530_BOARD_NAND_CONTROL		0x01c00543
+
+MV_BOARD_TWSI_INFO rd88f6530InfoBoardTwsiDev[] = {
+	/* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+};
+
+MV_BOARD_MAC_INFO rd88f6530InfoBoardMacInfo[] = {
+	/* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */
+	{BOARD_MAC_SPEED_1000M, 0x8}
+	,			/* This connected to SGMII to xcat ,right now forced SGMII 1G */
+	{BOARD_MAC_SPEED_AUTO, 0x9},
+	{N_A,N_A}
+
+};
+
+MV_BOARD_MPP_TYPE_INFO rd88f6530InfoBoardMppTypeInfo[] = {
+	{
+	 .boardMppTdm = MV_BOARD_TDM_2CH,
+	 .ethSataComplexOpt = ESC_OPT_SGMII | ESC_OPT_GEPHY_MAC1,
+	 .ethPortsMode = 0x0
+	}
+};
+
+MV_BOARD_GPP_INFO rd88f6530InfoBoardGppInfo[] = {
+	/* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */
+};
+
+MV_DEV_CS_INFO rd88f6530InfoBoardDeCsInfo[] = {
+	/*{deviceCS, params, devType, devWidth} */
+#if defined(MTD_NAND_LNC)
+	{NAND_NOR_CS, N_A, BOARD_DEV_NAND_FLASH, 8},	/* NAND DEV */
+#endif
+#if defined(MV_SPI)
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},	/* SPI DEV */
+#endif
+#if !defined(MTD_NAND_LNC) && !defined(MV_SPI)
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO rd88f6530InfoBoardMppConfigValue[] = {
+	{{
+	  RD_88F6530_MPP0_7,
+	  RD_88F6530_MPP8_15,
+	  RD_88F6530_MPP16_23,
+	  RD_88F6530_MPP24_31,
+	  RD_88F6530_MPP32_39,
+	  RD_88F6530_MPP40_47,
+	  RD_88F6530_MPP48_55,
+	  RD_88F6530_MPP56_63,
+	  RD_88F6530_MPP64_69,
+	  RD_88F6530_MPP72_79,
+	  RD_88F6530_MPP80_87,
+	  RD_88F6530_MPP88_88
+	  }
+	 }
+};
+
+MV_BOARD_TDM_INFO rd88f6530Tdm880[] = { {1}
+};
+
+MV_BOARD_TDM_SPI_INFO rd88f6530TdmSpiInfo[] = { {0} };
+
+MV_BOARD_INFO rd88f6530Info = {
+	.boardName = "RD-88F6530-MDU",
+	.numBoardMppTypeValue = MV_ARRAY_SIZE(rd88f6530InfoBoardMppTypeInfo),
+	.pBoardMppTypeValue = rd88f6530InfoBoardMppTypeInfo,
+	.numBoardMppConfigValue = MV_ARRAY_SIZE(rd88f6530InfoBoardMppConfigValue),
+	.pBoardMppConfigValue = rd88f6530InfoBoardMppConfigValue,
+	.intsGppMaskLow = 0,
+	.intsGppMaskMid = 0,
+	.intsGppMaskHigh = 0,
+	.numBoardDeviceIf = MV_ARRAY_SIZE(rd88f6530InfoBoardDeCsInfo),
+	.pDevCsInfo = rd88f6530InfoBoardDeCsInfo,
+	.numBoardTwsiDev = MV_ARRAY_SIZE(rd88f6530InfoBoardTwsiDev),
+	.pBoardTwsiDev = rd88f6530InfoBoardTwsiDev,
+	.numBoardMacInfo = MV_ARRAY_SIZE(rd88f6530InfoBoardMacInfo),
+	.pBoardMacInfo = rd88f6530InfoBoardMacInfo,
+	.numBoardGppInfo = MV_ARRAY_SIZE(rd88f6530InfoBoardGppInfo),
+	.pBoardGppInfo = rd88f6530InfoBoardGppInfo,
+	.activeLedsNumber = 0,
+	.pLedGppPin = NULL,
+	.ledsPolarity = 0,
+
+	/* GPP values */
+	.gppOutEnValLow = RD_88F6530_GPP_OUT_ENA_LOW,
+	.gppOutEnValMid = RD_88F6530_GPP_OUT_ENA_MID,
+	.gppOutEnValHigh = RD_88F6530_GPP_OUT_ENA_HIGH,
+	.gppOutValLow = RD_88F6530_GPP_OUT_VAL_LOW,
+	.gppOutValMid = RD_88F6530_GPP_OUT_VAL_MID,
+	.gppOutValHigh = RD_88F6530_GPP_OUT_VAL_HIGH,
+	.gppPolarityValLow = RD_88F6530_GPP_POL_LOW,
+	.gppPolarityValMid = RD_88F6530_GPP_POL_MID,
+	.gppPolarityValHigh = RD_88F6530_GPP_POL_HIGH,
+
+	/* External Switch Configuration */
+	.pSwitchInfo = NULL,
+	.switchInfoNum = 0,
+
+	/* PON configuration. */
+	.ponConfigValue = BOARD_GPON_CONFIG,
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	.numBoardTdmInfo = {1}
+	,
+	.pBoardTdmInt2CsInfo = {rd88f6530Tdm880,
+				}
+	,
+	.boardTdmInfoIndex = 0,
+
+	.deepIdlePwrUpDelay = 0x80000,
+
+	/* NAND init params */
+	.nandFlashParamsValid = MV_TRUE,
+	.nandFlashReadParams = RD_88F6530_BOARD_NAND_READ_PARAMS,
+	.nandFlashWriteParams = RD_88F6530_BOARD_NAND_WRITE_PARAMS,
+	.nandFlashControl = RD_88F6530_BOARD_NAND_CONTROL,
+	.pBoardTdmSpiInfo = rd88f6530TdmSpiInfo,
+
+	/* Disable modules auto-detection. */
+	.moduleAutoDetect = MV_FALSE
+};
+
+/***************************************************************************
+** DB-88F6560-PCAC
+****************************************************************************/
+
+#define DB_88F6560_PCAC_BOARD_NAND_READ_PARAMS	0x000C0282
+#define DB_88F6560_PCAC_BOARD_NAND_WRITE_PARAMS	0x00010305
+/* NAND care support for small page chips */
+#define DB_88F6560_PCAC_BOARD_NAND_CONTROL	0x01c00543
+
+MV_BOARD_TWSI_INFO db88f6560PcacInfoBoardTwsiDev[] = {
+	/* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+};
+
+MV_BOARD_MAC_INFO db88f6560PcacInfoBoardMacInfo[] = {
+	/* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */
+	{BOARD_MAC_SPEED_AUTO, 0x8},
+	{BOARD_MAC_SPEED_AUTO, 0x9},
+	{N_A,N_A}
+};
+
+MV_BOARD_MPP_TYPE_INFO db88f6560PcacInfoBoardMppTypeInfo[] = {
+	{
+	 .boardMppTdm = MV_BOARD_OTHER,
+	 .ethSataComplexOpt = ESC_OPT_GEPHY_MAC1,
+	 .ethPortsMode = 0x0
+	}
+};
+
+MV_BOARD_GPP_INFO db88f6560PcacInfoBoardGppInfo[] = {
+	/* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */
+	{BOARD_GPP_USB_VBUS, 58}
+};
+
+MV_DEV_CS_INFO db88f6560PcacInfoBoardDeCsInfo[] = {
+	/*{deviceCS, params, devType, devWidth} */
+#if defined(MTD_NAND_LNC)
+	{NAND_NOR_CS, N_A, BOARD_DEV_NAND_FLASH, 8},	/* NAND DEV */
+#endif
+#if defined(MV_SPI)
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},	/* SPI DEV */
+#endif
+#if !defined(MTD_NAND_LNC) && !defined(MV_SPI)
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO db88f6560PcacInfoBoardMppConfigValue[] = {
+	{ {
+		 DB_88F6560_PCAC_MPP0_7,
+		 DB_88F6560_PCAC_MPP8_15,
+		 DB_88F6560_PCAC_MPP16_23,
+		 DB_88F6560_PCAC_MPP24_31,
+		 DB_88F6560_PCAC_MPP32_39,
+		 DB_88F6560_PCAC_MPP40_47,
+		 DB_88F6560_PCAC_MPP48_55,
+		 DB_88F6560_PCAC_MPP56_63,
+		 DB_88F6560_PCAC_MPP64_71,
+		 DB_88F6560_PCAC_MPP72_79,
+		 DB_88F6560_PCAC_MPP80_87,
+		 DB_88F6560_PCAC_MPP88_88
+	 } }
+};
+
+MV_U8 db88f6560PcacLedGppPin[] = { 68, 69, 70, 71};
+
+MV_BOARD_TDM_SPI_INFO db88f6560PcacTdmSpiInfo[] = { {0} };
+
+MV_BOARD_SPEC_INIT db88f6560PcacBoardSpecInit[] = {
+	{
+		.reg = TBL_TERM,
+		.val = TBL_TERM
+	}
+};
+
+MV_BOARD_INFO db88f6560PCACPInfo = {
+	.boardName = "DB-88F6560-PCAC",
+	.numBoardMppTypeValue = MV_ARRAY_SIZE(db88f6560PcacInfoBoardMppTypeInfo),
+	.pBoardMppTypeValue = db88f6560PcacInfoBoardMppTypeInfo,
+	.numBoardMppConfigValue = MV_ARRAY_SIZE(db88f6560PcacInfoBoardMppConfigValue),
+	.pBoardMppConfigValue = db88f6560PcacInfoBoardMppConfigValue,
+	.intsGppMaskLow = 0,
+	.intsGppMaskMid = 0,
+	.intsGppMaskHigh = 0,
+	.numBoardDeviceIf = MV_ARRAY_SIZE(db88f6560PcacInfoBoardDeCsInfo),
+	.pDevCsInfo = db88f6560PcacInfoBoardDeCsInfo,
+	.numBoardTwsiDev = MV_ARRAY_SIZE(db88f6560PcacInfoBoardTwsiDev),
+	.pBoardTwsiDev = db88f6560PcacInfoBoardTwsiDev,
+	.numBoardMacInfo = MV_ARRAY_SIZE(db88f6560PcacInfoBoardMacInfo),
+	.pBoardMacInfo = db88f6560PcacInfoBoardMacInfo,
+	.numBoardGppInfo = MV_ARRAY_SIZE(db88f6560PcacInfoBoardGppInfo),
+	.pBoardGppInfo = db88f6560PcacInfoBoardGppInfo,
+	.activeLedsNumber = MV_ARRAY_SIZE(db88f6560PcacLedGppPin),
+	.pLedGppPin = db88f6560PcacLedGppPin,
+	.ledsPolarity = 0,
+
+	/* GPP values */
+	.gppOutEnValLow = DB_88F6560_PCAC_GPP_OUT_ENA_LOW,
+	.gppOutEnValMid = DB_88F6560_PCAC_GPP_OUT_ENA_MID,
+	.gppOutEnValHigh = DB_88F6560_PCAC_GPP_OUT_ENA_HIGH,
+	.gppOutValLow = DB_88F6560_PCAC_GPP_OUT_VAL_LOW,
+	.gppOutValMid = DB_88F6560_PCAC_GPP_OUT_VAL_MID,
+	.gppOutValHigh = DB_88F6560_PCAC_GPP_OUT_VAL_HIGH,
+	.gppPolarityValLow = DB_88F6560_PCAC_GPP_POL_LOW,
+	.gppPolarityValMid = DB_88F6560_PCAC_GPP_POL_MID,
+	.gppPolarityValHigh = DB_88F6560_PCAC_GPP_POL_HIGH,
+
+	/* External Switch Configuration */
+	.pSwitchInfo = NULL,
+	.switchInfoNum = 0,
+
+	/* PON configuration. */
+	.ponConfigValue = BOARD_PON_NONE,
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	.numBoardTdmInfo = {0},
+	.pBoardTdmInt2CsInfo = {NULL},
+	.boardTdmInfoIndex = -1,
+
+	.pBoardSpecInit = db88f6560PcacBoardSpecInit,
+
+	.deepIdlePwrUpDelay = 2400, /* 12 uS */
+
+	/* NAND init params */
+	.nandFlashParamsValid = MV_TRUE,
+	.nandFlashReadParams = DB_88F6560_PCAC_BOARD_NAND_READ_PARAMS,
+	.nandFlashWriteParams = DB_88F6560_PCAC_BOARD_NAND_WRITE_PARAMS,
+	.nandFlashControl = DB_88F6560_PCAC_BOARD_NAND_CONTROL,
+	.pBoardTdmSpiInfo = db88f6560PcacTdmSpiInfo,
+
+	/* Disable modules auto-detection. */
+	.moduleAutoDetect = MV_FALSE
+};
+
+/***************************************************************************
+** DB-88F6560-BP
+****************************************************************************/
+#define DB_88F6535_BOARD_NAND_READ_PARAMS	0x000C0282
+#define DB_88F6535_BOARD_NAND_WRITE_PARAMS	0x00010305
+/* NAND care support for small page chips */
+#define DB_88F6535_BOARD_NAND_CONTROL		0x01c00543
+
+MV_BOARD_TWSI_INFO db88f6535InfoBoardTwsiDev[] = {
+	/* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+	{BOARD_DEV_TWSI_SATR, 0x4C, ADDR7_BIT},
+	{BOARD_DEV_TWSI_SATR, 0x4D, ADDR7_BIT},
+	{BOARD_DEV_TWSI_SATR, 0x4E, ADDR7_BIT},
+	{BOARD_DEV_TWSI_SATR, 0x4F, ADDR7_BIT},
+	{BOARD_TWSI_MUX, 0x70, ADDR7_BIT}
+};
+
+MV_BOARD_MAC_INFO db88f6535InfoBoardMacInfo[] = {
+	/* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */
+	{BOARD_MAC_SPEED_AUTO, 0x8},
+	{BOARD_MAC_SPEED_AUTO, 0x9},
+	{N_A,N_A}
+};
+
+MV_BOARD_MPP_TYPE_INFO db88f6535InfoBoardMppTypeInfo[] = {
+	{
+		.boardMppTdm = MV_BOARD_AUTO,
+		.ethSataComplexOpt = ESC_OPT_AUTO,
+		.ethPortsMode = 0x0
+	}
+};
+
+MV_BOARD_GPP_INFO db88f6535InfoBoardGppInfo[] = {
+	/* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */
+	{BOARD_GPP_PON_XVR_TX, 17},
+	{BOARD_GPP_USB_VBUS, 31},
+	{BOARD_GPP_PEX_RESET, 67},
+	{BOARD_GPP_SDIO_DETECT, 68},
+	{BOARD_GPP_SDIO_WP, 69},
+};
+
+MV_DEV_CS_INFO db88f6535InfoBoardDeCsInfo[] = {
+	/*{deviceCS, params, devType, devWidth} */
+#ifdef MTD_NAND_LNC
+	{NAND_NOR_CS, N_A, BOARD_DEV_NAND_FLASH, 8},	/* NAND DEV */
+#endif
+#ifdef MV_SPI
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},		/* SPI DEV */
+#endif
+#ifdef MV_NOR
+	{NAND_NOR_CS, N_A, BOARD_DEV_NOR_FLASH, 16},	/* NOR DEV */
+#endif
+#if !defined(MTD_NAND_LNC) && !defined(MV_SPI) && !defined(MV_NOR)
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO db88f6535InfoBoardMppConfigValue[] = {
+	{{
+	  DB_88F6535_MPP0_7,
+	  DB_88F6535_MPP8_15,
+	  DB_88F6535_MPP16_23,
+	  DB_88F6535_MPP24_31,
+	  DB_88F6535_MPP32_39,
+	  DB_88F6535_MPP40_47,
+	  DB_88F6535_MPP48_55,
+	  DB_88F6535_MPP56_63,
+	  DB_88F6535_MPP64_71,
+	  DB_88F6535_MPP72_79,
+	  DB_88F6535_MPP80_87,
+	  DB_88F6535_MPP88_88
+	  }
+	 }
+};
+
+MV_BOARD_SWITCH_INFO db88f6535InfoBoardSwitchValue[] = {
+	{
+	 .switchIrq = 29,	/* set to -1 for timer operation */
+	 .switchPort = {1, 2, 3, 0, -1, -1, -1, -1},
+	 .cpuPort = 4,
+	 .connectedPort = {4, 5, -1},
+	 .smiScanMode = 2,
+	 .quadPhyAddr = 0,
+	 .forceLinkMask = 0x0
+	 }
+};
+
+MV_BOARD_TDM_INFO db88f6535Tdm880[] = {
+	{1},
+	{2}
+};
+
+MV_BOARD_TDM_INFO db88f6535Tdm890[] = {
+	{2}
+};
+
+MV_BOARD_TDM_INFO db88f6535Tdm792[] = {
+	{1},
+	{2},
+	{3},
+	{4},
+	{6},
+	{7}
+};
+
+MV_BOARD_TDM_INFO db88f6535Tdm3215[] = { {1} };
+
+MV_BOARD_TDM_SPI_INFO db88f6535TdmSpiInfo[] = { {0} };
+
+MV_BOARD_SPEC_INIT db88f6535BoardSpecInit[] = {
+	{
+		.reg = PMU_POWER_IF_POLARITY_REG,
+		.mask = (BIT1),
+		.val = 0
+	},
+	{
+		.reg = TBL_TERM,
+		.val = TBL_TERM
+	}
+};
+
+MV_BOARD_INFO db88f6535Info = {
+	.boardName = "DB-88F6560-BP",
+	.numBoardMppTypeValue = MV_ARRAY_SIZE(db88f6535InfoBoardMppTypeInfo),
+	.pBoardMppTypeValue = db88f6535InfoBoardMppTypeInfo,
+	.numBoardMppConfigValue = MV_ARRAY_SIZE(db88f6535InfoBoardMppConfigValue),
+	.pBoardMppConfigValue = db88f6535InfoBoardMppConfigValue,
+	.intsGppMaskLow = 0,
+	.intsGppMaskMid = 0,
+	.intsGppMaskHigh = 0,
+	.numBoardDeviceIf = MV_ARRAY_SIZE(db88f6535InfoBoardDeCsInfo),
+	.pDevCsInfo = db88f6535InfoBoardDeCsInfo,
+	.numBoardTwsiDev = MV_ARRAY_SIZE(db88f6535InfoBoardTwsiDev),
+	.pBoardTwsiDev = db88f6535InfoBoardTwsiDev,
+	.numBoardMacInfo = MV_ARRAY_SIZE(db88f6535InfoBoardMacInfo),
+	.pBoardMacInfo = db88f6535InfoBoardMacInfo,
+	.numBoardGppInfo = MV_ARRAY_SIZE(db88f6535InfoBoardGppInfo),
+	.pBoardGppInfo = db88f6535InfoBoardGppInfo,
+	.activeLedsNumber = 0,
+	.pLedGppPin = NULL,
+	.ledsPolarity = 0,
+
+	/* GPP values */
+	.gppOutEnValLow = DB_88F6535_GPP_OUT_ENA_LOW,
+	.gppOutEnValMid = DB_88F6535_GPP_OUT_ENA_MID,
+	.gppOutEnValHigh = DB_88F6535_GPP_OUT_ENA_HIGH,
+	.gppOutValLow = DB_88F6535_GPP_OUT_VAL_LOW,
+	.gppOutValMid = DB_88F6535_GPP_OUT_VAL_MID,
+	.gppOutValHigh = DB_88F6535_GPP_OUT_VAL_HIGH,
+	.gppPolarityValLow = DB_88F6535_GPP_POL_LOW,
+	.gppPolarityValMid = DB_88F6535_GPP_POL_MID,
+	.gppPolarityValHigh = DB_88F6535_GPP_POL_HIGH,
+
+	/* External Switch Configuration */
+	.pSwitchInfo = db88f6535InfoBoardSwitchValue,
+	.switchInfoNum = MV_ARRAY_SIZE(db88f6535InfoBoardSwitchValue),
+
+	/* PON configuration. */
+	.ponConfigValue = BOARD_PON_AUTO,
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	.numBoardTdmInfo = {2, 6, 1, 1},
+	.pBoardTdmInt2CsInfo = {db88f6535Tdm880,
+				db88f6535Tdm792,
+				db88f6535Tdm3215,
+				db88f6535Tdm890},
+	.boardTdmInfoIndex = -1,
+
+	.pBoardSpecInit = db88f6535BoardSpecInit,
+
+	.deepIdlePwrUpDelay = 2400,	/* 12uS */
+
+	/* NAND init params */
+	.nandFlashParamsValid = MV_TRUE,
+	.nandFlashReadParams = DB_88F6535_BOARD_NAND_READ_PARAMS,
+	.nandFlashWriteParams = DB_88F6535_BOARD_NAND_WRITE_PARAMS,
+	.nandFlashControl = DB_88F6535_BOARD_NAND_CONTROL,
+	.pBoardTdmSpiInfo = db88f6535TdmSpiInfo,
+
+	/* Enable modules auto-detection. */
+	.moduleAutoDetect = MV_TRUE
+};
+
+/***************************************************************************
+** RD-88F6601 Avanta
+****************************************************************************/
+/* NAND not supported  */
+
+MV_BOARD_TWSI_INFO rd88f6601InfoBoardTwsiDev[] = {
+	/* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+};
+
+MV_BOARD_MAC_INFO rd88f6601InfoBoardMacInfo[] = {
+	/* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */
+	{BOARD_MAC_SPEED_AUTO, 0x0},
+	{BOARD_MAC_SPEED_AUTO, 0x1},
+	{N_A,N_A}
+};
+
+MV_BOARD_MPP_TYPE_INFO rd88f6601InfoBoardMppTypeInfo[] = {
+	{
+		.boardMppTdm = MV_BOARD_AUTO,
+		.ethSataComplexOpt = ESC_OPT_GEPHY_MAC0,
+		.ethPortsMode = 0x0
+	}
+};
+
+MV_BOARD_GPP_INFO rd88f6601InfoBoardGppInfo[] = {
+	/* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */
+	{BOARD_GPP_PON_XVR_TX, 17},
+	{BOARD_GPP_PON_XVR_TX_POWER, 37},
+	{BOARD_GPP_PON_XVR_TX_IND, 24},
+};
+
+MV_DEV_CS_INFO rd88f6601InfoBoardDeCsInfo[] = {
+	/*{deviceCS, params, devType, devWidth} */
+#ifdef MV_SPI
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},		/* SPI DEV */
+#endif
+#if !defined(MV_SPI) 
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO rd88f6601InfoBoardMppConfigValue[] = {
+	{{
+	  RD_88F6601_MPP0_7,
+	  RD_88F6601_MPP8_15,
+	  RD_88F6601_MPP16_23,
+	  RD_88F6601_MPP24_31,
+	  RD_88F6601_MPP32_37
+	  }
+	 }
+};
+
+/*
+MV_BOARD_SPEC_INIT rd88f6601BoardSpecInit[] = {
+	{
+		.reg = PMU_POWER_IF_POLARITY_REG,
+		.mask = (BIT1),
+		.val = 0
+	},
+	{
+		.reg = TBL_TERM,
+		.val = TBL_TERM
+	}
+};
+*/
+MV_BOARD_INFO rd88f6601Info = {
+	.boardName = "RD-88F6601-BP",
+	.numBoardMppTypeValue = MV_ARRAY_SIZE(rd88f6601InfoBoardMppTypeInfo),
+	.pBoardMppTypeValue = rd88f6601InfoBoardMppTypeInfo,
+	.numBoardMppConfigValue = MV_ARRAY_SIZE(rd88f6601InfoBoardMppConfigValue),
+	.pBoardMppConfigValue = rd88f6601InfoBoardMppConfigValue,
+	.intsGppMaskLow = 0,
+	.intsGppMaskMid = 0,
+	.intsGppMaskHigh = 0,
+	.numBoardDeviceIf = MV_ARRAY_SIZE(rd88f6601InfoBoardDeCsInfo),
+	.pDevCsInfo = rd88f6601InfoBoardDeCsInfo,
+	.numBoardTwsiDev = MV_ARRAY_SIZE(rd88f6601InfoBoardTwsiDev),
+	.pBoardTwsiDev = rd88f6601InfoBoardTwsiDev,
+	.numBoardMacInfo = MV_ARRAY_SIZE(rd88f6601InfoBoardMacInfo),
+	.pBoardMacInfo = rd88f6601InfoBoardMacInfo,
+	.numBoardGppInfo = MV_ARRAY_SIZE(rd88f6601InfoBoardGppInfo),
+	.pBoardGppInfo = rd88f6601InfoBoardGppInfo,
+	.activeLedsNumber = 0,
+	.pLedGppPin = NULL,
+	.ledsPolarity = 0,
+
+	/* GPP values */
+	.gppOutEnValLow = RD_88F6601_GPP_OUT_ENA_LOW,
+	.gppOutEnValMid = RD_88F6601_GPP_OUT_ENA_MID,
+	.gppOutEnValHigh = 0,
+	.gppOutValLow = RD_88F6601_GPP_OUT_VAL_LOW,
+	.gppOutValMid = RD_88F6601_GPP_OUT_VAL_MID,
+	.gppOutValHigh = 0,
+	.gppPolarityValLow = RD_88F6601_GPP_POL_LOW,
+	.gppPolarityValMid = RD_88F6601_GPP_POL_MID,
+	.gppPolarityValHigh = 0,
+
+	/* External Switch Configuration */
+	.pSwitchInfo = NULL,
+	.switchInfoNum = 0,
+
+	/* PON configuration. */
+	.ponConfigValue = BOARD_GPON_CONFIG,
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	.numBoardTdmInfo = {0},
+	.pBoardTdmInt2CsInfo = {NULL},
+	.boardTdmInfoIndex = -1,
+
+	.pBoardSpecInit = NULL,			/* rd88f6601BoardSpecInit, */
+
+	.deepIdlePwrUpDelay = 2400,	/* 12uS */
+
+	/* NAND init params */
+	.nandFlashParamsValid = MV_FALSE,
+	.nandFlashReadParams = 0,
+	.nandFlashWriteParams = 0,
+	.nandFlashControl = 0,
+	.pBoardTdmSpiInfo = NULL,
+
+	/* Enable modules auto-detection. */
+	.moduleAutoDetect = MV_FALSE
+};
+
+/***************************************************************************
+** DB-88F6601-BP Avanta
+****************************************************************************/
+/* NAND not supported  */
+
+MV_BOARD_TWSI_INFO db88f6601InfoBoardTwsiDev[] = {
+	/* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+	{BOARD_DEV_TWSI_SATR, 0x4C, ADDR7_BIT},
+	{BOARD_TWSI_MUX, 0x70, ADDR7_BIT}
+};
+
+MV_BOARD_MAC_INFO db88f6601InfoBoardMacInfo[] = {
+	/* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */
+	{BOARD_MAC_SPEED_AUTO, 0x0},
+	{BOARD_MAC_SPEED_AUTO, 0x1},
+	{N_A, N_A}
+};
+
+MV_BOARD_MPP_TYPE_INFO db88f6601InfoBoardMppTypeInfo[] = {
+	{
+		.boardMppTdm = MV_BOARD_AUTO,
+		.ethSataComplexOpt = ESC_OPT_AUTO,
+		.ethPortsMode = 0x0
+	}
+};
+
+MV_BOARD_GPP_INFO db88f6601InfoBoardGppInfo[] = {
+	/* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */
+	{BOARD_GPP_PON_XVR_TX, 17},
+	{BOARD_GPP_PON_XVR_TX_POWER, 37},
+	{BOARD_GPP_PON_XVR_TX_IND, 19},
+
+};
+
+MV_DEV_CS_INFO db88f6601InfoBoardDeCsInfo[] = {
+	/*{deviceCS, params, devType, devWidth} */
+#ifdef MV_SPI
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},		/* SPI DEV */
+#endif
+#if !defined(MV_SPI) 
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO db88f6601InfoBoardMppConfigValue[] = {
+	{{
+	  DB_88F6601_MPP0_7,
+	  DB_88F6601_MPP8_15,
+	  DB_88F6601_MPP16_23,
+	  DB_88F6601_MPP24_31,
+	  DB_88F6601_MPP32_37
+	  }
+	 }
+};
+
+
+MV_BOARD_TDM_INFO db88f6601Tdm880[] = { {0} };
+
+MV_BOARD_TDM_SPI_INFO db88f6601TdmSpiInfo[] = { {1} };
+
+MV_BOARD_INFO db88f6601Info = {
+	.boardName = "DB-88F6601-BP",
+	.numBoardMppTypeValue = MV_ARRAY_SIZE(db88f6601InfoBoardMppTypeInfo),
+	.pBoardMppTypeValue = db88f6601InfoBoardMppTypeInfo,
+	.numBoardMppConfigValue = MV_ARRAY_SIZE(db88f6601InfoBoardMppConfigValue),
+	.pBoardMppConfigValue = db88f6601InfoBoardMppConfigValue,
+	.intsGppMaskLow = 0,
+	.intsGppMaskMid = 0,
+	.intsGppMaskHigh = 0,
+	.numBoardDeviceIf = MV_ARRAY_SIZE(db88f6601InfoBoardDeCsInfo),
+	.pDevCsInfo = db88f6601InfoBoardDeCsInfo,
+	.numBoardTwsiDev = MV_ARRAY_SIZE(db88f6601InfoBoardTwsiDev),
+	.pBoardTwsiDev = db88f6601InfoBoardTwsiDev,
+	.numBoardMacInfo = MV_ARRAY_SIZE(db88f6601InfoBoardMacInfo),
+	.pBoardMacInfo = db88f6601InfoBoardMacInfo,
+	.numBoardGppInfo = MV_ARRAY_SIZE(db88f6601InfoBoardGppInfo),
+	.pBoardGppInfo = db88f6601InfoBoardGppInfo,
+	.activeLedsNumber = 0,
+	.pLedGppPin = NULL,
+	.ledsPolarity = 0,
+
+	/* GPP values */
+	.gppOutEnValLow = DB_88F6601_GPP_OUT_ENA_LOW,
+	.gppOutEnValMid = DB_88F6601_GPP_OUT_ENA_MID,
+	.gppOutEnValHigh = 0,	
+	.gppOutValLow = DB_88F6601_GPP_OUT_VAL_LOW,
+	.gppOutValMid = DB_88F6601_GPP_OUT_VAL_MID,
+	.gppOutValHigh = 0,
+	.gppPolarityValLow = DB_88F6601_GPP_POL_LOW,
+	.gppPolarityValMid = DB_88F6601_GPP_POL_MID,
+	.gppPolarityValHigh = 0,
+
+	/* External Switch Configuration */
+	.pSwitchInfo = NULL,
+	.switchInfoNum = 0,
+
+	/* PON configuration. */
+	.ponConfigValue = BOARD_GPON_CONFIG,
+
+	/* TDM configuration */
+	/* We hold a different configuration array for each possible slic that
+	 ** can be connected to board.
+	 ** When modules are scanned, then we select the index of the relevant
+	 ** slic's information array.
+	 ** For RD and Customers boards we only need to initialize a single
+	 ** entry of the arrays below, and set the boardTdmInfoIndex to 0.
+	 */
+	.numBoardTdmInfo = {1},
+	.pBoardTdmInt2CsInfo = {db88f6601Tdm880},
+	.boardTdmInfoIndex = 0,
+
+	.pBoardSpecInit = NULL,
+
+	.deepIdlePwrUpDelay = 2400,	/* 12uS */
+
+	/* NAND init params */
+	.nandFlashParamsValid = MV_FALSE,
+	.nandFlashReadParams = 0,
+	.nandFlashWriteParams = 0,
+	.nandFlashControl = 0,
+	.pBoardTdmSpiInfo = db88f6601TdmSpiInfo,
+
+	/* Enable modules auto-detection. */
+	.moduleAutoDetect = MV_TRUE
+};
+
+/***************************************************************************
+** Customer board place holder
+****************************************************************************/
+
+#define DB_CUSTOMER_BOARD_PCI_IF_NUM		        0x0
+#define DB_CUSTOMER_BOARD_TWSI_DEF_NUM		        0x0
+#define DB_CUSTOMER_BOARD_MAC_INFO_NUM		        0x0
+#define DB_CUSTOMER_BOARD_GPP_INFO_NUM		        0x0
+#define DB_CUSTOMER_BOARD_MPP_GROUP_TYPE_NUN        0x0
+#define DB_CUSTOMER_BOARD_MPP_CONFIG_NUM		    0x0
+#define DB_CUSTOMER_BOARD_DEVICE_CONFIG_NUM	    	0x0
+#define DB_CUSTOMER_BOARD_DEBUG_LED_NUM				0x0
+#define DB_CUSTOMER_BOARD_NAND_READ_PARAMS		    0x000E02C2
+#define DB_CUSTOMER_BOARD_NAND_WRITE_PARAMS		    0x00010305
+#define DB_CUSTOMER_BOARD_NAND_CONTROL		        0x01c00543
+
+MV_U8 dbCustomerInfoBoardDebugLedIf[] = { 0 };
+
+MV_BOARD_MAC_INFO dbCustomerInfoBoardMacInfo[] =
+    /* {{MV_BOARD_MAC_SPEED     boardMacSpeed,  MV_U8   boardEthSmiAddr}} */
+{ {BOARD_MAC_SPEED_AUTO, 0x0}
+};
+
+MV_BOARD_TWSI_INFO dbCustomerInfoBoardTwsiDev[] =
+    /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */
+{ {BOARD_TWSI_OTHER, 0x0, ADDR7_BIT}
+};
+
+MV_BOARD_MPP_TYPE_INFO dbCustomerInfoBoardMppTypeInfo[] = { {MV_BOARD_OTHER, MV_BOARD_OTHER, 0x0}
+};
+
+MV_DEV_CS_INFO dbCustomerInfoBoardDeCsInfo[] = {
+	/*{deviceCS, params, devType, devWidth} */
+#if defined(MTD_NAND_LNC)
+	{NAND_NOR_CS, N_A, BOARD_DEV_NAND_FLASH, 8},	/* NAND DEV */
+#endif
+#if defined(MV_SPI)
+	{SPI_CS0, N_A, BOARD_DEV_SPI_FLASH, 8},	/* SPI DEV */
+#endif
+#if !defined(MTD_NAND_LNC) && !defined(MV_SPI)
+	{N_A, N_A, N_A, N_A}			/* No device */
+#endif
+};
+
+MV_BOARD_MPP_INFO dbCustomerInfoBoardMppConfigValue[] = {
+	{
+		{
+			DB_CUSTOMER_MPP0_7,
+			DB_CUSTOMER_MPP8_15,
+			DB_CUSTOMER_MPP16_23,
+			DB_CUSTOMER_MPP24_31,
+			DB_CUSTOMER_MPP32_39,
+			DB_CUSTOMER_MPP40_47,
+			DB_CUSTOMER_MPP48_55
+		}
+	}
+};
+
+MV_BOARD_INFO dbCustomerInfo = { };
+
+
+
+MV_BOARD_INFO *boardInfoTbl[] = {
+	&db88f6535Info,
+	&rd88f6510Info,
+	&rd88f6560Info,
+	&rd88f6530Info,
+	&db88f6560PCACPInfo,
+	&db88f6601Info,
+	&rd88f6601Info,
+	&dbCustomerInfo,
+};
+
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
new file mode 100755
index 0000000..ffe4375
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSpec.h
@@ -0,0 +1,465 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvBoardEnvSpech
+#define __INCmvBoardEnvSpech
+
+#include "mvSysHwConfig.h"
+
+/* For future use */
+#define BD_ID_DATA_START_OFFS			0x0
+#define BD_DETECT_SEQ_OFFS			0x0
+#define BD_SYS_NUM_OFFS				0x4
+#define BD_NAME_OFFS				0x8
+
+/* I2C bus addresses */
+#define MV_BOARD_CTRL_I2C_ADDR			0x0	/* Controller slave addr */
+#define MV_BOARD_CTRL_I2C_ADDR_TYPE 		ADDR7_BIT
+#define MV_BOARD_DIMM0_I2C_ADDR			0x56
+#define MV_BOARD_DIMM0_I2C_ADDR_TYPE 		ADDR7_BIT
+#define MV_BOARD_DIMM1_I2C_ADDR			0x54
+#define MV_BOARD_DIMM1_I2C_ADDR_TYPE 		ADDR7_BIT
+#define MV_BOARD_EEPROM_I2C_ADDR	    	0x51
+#define MV_BOARD_EEPROM_I2C_ADDR_TYPE 		ADDR7_BIT
+#define MV_BOARD_MAIN_EEPROM_I2C_ADDR	   	0x50
+#define MV_BOARD_MAIN_EEPROM_I2C_ADDR_TYPE 	ADDR7_BIT
+#define MV_BOARD_MUX_I2C_ADDR_ENTRY		0x2
+#define MV_BOARD_DIMM_I2C_CHANNEL		0x0
+
+#define BOOT_FLASH_INDEX		0
+#define MAIN_FLASH_INDEX		1
+
+#define BOARD_ETH_START_PORT_NUM	0
+
+/* Board specific configuration */
+/* ============================ */
+
+/* boards ID numbers */
+
+#define BOARD_ID_BASE			0x20
+
+/* New board ID numbers */
+#define DB_88F6535_BP_ID		(BOARD_ID_BASE)
+#define RD_88F6510_SFU_ID		(BOARD_ID_BASE+0x1)
+#define RD_88F6560_GW_ID		(BOARD_ID_BASE+0x2)
+#define RD_88F6530_MDU_ID		(BOARD_ID_BASE+0x3)
+#define DB_88F6560_PCAC_ID		(BOARD_ID_BASE+0x4)
+#define DB_88F6601_BP_ID		(BOARD_ID_BASE+0x5)
+#define RD_88F6601_MC_ID		(BOARD_ID_BASE+0x6)
+#define DB_CUSTOMER_ID			(BOARD_ID_BASE+0x7)
+#define MV_MAX_BOARD_ID			(DB_CUSTOMER_ID + 1)
+
+/***************************************************************************
+** RD-88F6510-SFU
+****************************************************************************/
+#define RD_88F6510_MPP0_7		0x11111111
+#define RD_88F6510_MPP8_15		0x31111111
+#define RD_88F6510_MPP16_23		0x20000003
+#define RD_88F6510_MPP24_31		0x06622222
+#define RD_88F6510_MPP32_39		0x00044444
+#define RD_88F6510_MPP40_47		0x00006660
+#define RD_88F6510_MPP48_55		0x00000460
+#define RD_88F6510_MPP56_63		0x00000000
+#define RD_88F6510_MPP64_71		0x00500000
+#define RD_88F6510_MPP72_79		0x00000000
+#define RD_88F6510_MPP80_87		0x00000000
+#define RD_88F6510_MPP88_88		0x00000000
+
+/* GPPs
+MPP#	NAME			IN/OUT
+--------------------------------------
+17		WiFi_Host2WLAN	OUT
+18		free		free
+19		WiFi_WLAN2Host	IN
+20		WiFi_PDn	OUT
+21		WiFi_PWR	IN/OUT?
+22		WiFi_RSTn	OUT
+31		free		free
+37		NF&SPI_WP	OUT
+39		free (ground)	free
+40		free (3.3V)	free
+44		LED_SYS		OUT
+45		LED_PON		OUT
+46		LED_Phone	OUT
+47		LED_PWR		OUT
+48		free		free
+51		free		free
+52		free		free
+53		free		free
+54		free		free
+55		free		free
+56		free (ground)	free
+57		free		free
+58		free		free
+59		free		free
+60		free		free
+61		free		free
+62		free		free
+63		free		free
+64		free		free
+65		free		free
+66		PB		IN
+67		free		free
+68		TXfault_RST	IN/OUT?
+*/
+#define RD_88F6510_GPP_OUT_ENA_LOW	0x0
+#define RD_88F6510_GPP_OUT_ENA_MID	0x0
+#define RD_88F6510_GPP_OUT_ENA_HIGH	(BIT2 | BIT4)
+
+#define RD_88F6510_GPP_OUT_VAL_LOW	0x0
+#define RD_88F6510_GPP_OUT_VAL_MID	(BIT5)
+#define RD_88F6510_GPP_OUT_VAL_HIGH	0
+
+#define RD_88F6510_GPP_POL_LOW		0x0
+#define RD_88F6510_GPP_POL_MID		0x0
+#define RD_88F6510_GPP_POL_HIGH		0x0
+
+/***************************************************************************
+** RD-88F6560-GW
+****************************************************************************/
+#define RD_88F6560_MPP0_7		0x11111111
+#define RD_88F6560_MPP8_15		0x31111111
+#define RD_88F6560_MPP16_23		0x11111113
+#define RD_88F6560_MPP24_31		0x04411001
+#define RD_88F6560_MPP32_39		0x60004444
+#define RD_88F6560_MPP40_47		0x04006060
+#define RD_88F6560_MPP48_55		0x00000460
+#define RD_88F6560_MPP56_63		0x00000000
+#define RD_88F6560_MPP64_71		0x90500000
+#define RD_88F6560_MPP72_79		0x00044444
+#define RD_88F6560_MPP80_87		0x10000000
+#define RD_88F6560_MPP88_88		0x00000000
+
+/* GPPs
+MPP#	NAME			IN/OUT
+--------------------------------------
+24		TDM_Reset	OUT
+25		TDM_INTm0	IN
+31		SD_WP		IN
+37		HDD_PWR_CTRL	OUT
+38		free		free
+40		Fan_PWR_CTRL	OUT
+44		Phy_INTn	IN
+45		FXO_CTRL	OUT
+47		WPS_Switch	IN
+48		SD_Status	IN
+51		TDM_INTn1	IN
+52		Phone_Led	OUT
+53		free		free
+54		free		free
+55		free		free
+56		free		free
+57		free		free
+58		USB_Dev_Vbus	IN
+59		USB_OC		IN
+60		GP0		IN
+61		GP1		IN
+62		GP2		IN
+63		free		free
+64		free		free
+65		free		free
+66		free		free
+68		SYS_LED		OUT
+77		RST_PEX#	OUT
+*/
+#define RD_88F6560_GPP_OUT_ENA_LOW	BIT31
+#define RD_88F6560_GPP_OUT_ENA_MID	(BIT5 | BIT12 | BIT15 | BIT16 | BIT19 | BIT26 | BIT27 | BIT28 | BIT29 | BIT30)
+#define RD_88F6560_GPP_OUT_ENA_HIGH	0x0
+
+#define RD_88F6560_GPP_OUT_VAL_LOW	0x0
+#define RD_88F6560_GPP_OUT_VAL_MID	(BIT20)
+#define RD_88F6560_GPP_OUT_VAL_HIGH	(BIT13)
+
+#define RD_88F6560_GPP_POL_LOW		0x0
+#define RD_88F6560_GPP_POL_MID		(BIT19)
+#define RD_88F6560_GPP_POL_HIGH		0x0
+
+/***************************************************************************
+** RD-88F6530-MDU
+****************************************************************************/
+#define RD_88F6530_MPP0_7		0x11111111
+#define RD_88F6530_MPP8_15		0x31111111
+#define RD_88F6530_MPP16_23		0x00005003
+#define RD_88F6530_MPP24_31		0x04422222
+#define RD_88F6530_MPP32_39		0x00444444
+#define RD_88F6530_MPP40_47		0x00044400
+#define RD_88F6530_MPP48_55		0x00000000
+#define RD_88F6530_MPP56_63		0x00000000
+#define RD_88F6530_MPP64_69		0x00000000
+#define RD_88F6530_MPP72_79		0x00000000
+#define RD_88F6530_MPP80_87		0x00000000
+#define RD_88F6530_MPP88_88		0x00000000
+
+/* GPPs
+MPP#	NAME			IN/OUT
+-------------------------------
+*/
+/*the output GPIO is 17, 21, 23, 59, 60 */
+/*61,62,63 as INPUT pin */
+
+#define RD_88F6530_GPP_OUT_ENA_LOW	0xff5dffff
+#define RD_88F6530_GPP_OUT_ENA_MID	0xffffffff
+#define RD_88F6530_GPP_OUT_ENA_HIGH	0xffffffff
+
+/*the output default value = 1 */
+#define RD_88F6530_GPP_OUT_VAL_LOW	0x00A20000
+#define RD_88F6530_GPP_OUT_VAL_MID	0x00000000
+#define RD_88F6530_GPP_OUT_VAL_HIGH	(BIT4)
+
+#define RD_88F6530_GPP_POL_LOW		0x0
+#define RD_88F6530_GPP_POL_MID		0x0
+#define RD_88F6530_GPP_POL_HIGH		0x0
+
+/***************************************************************************
+** RD-88F6560-PCAC
+****************************************************************************/
+#define DB_88F6560_PCAC_MPP0_7		0x99999999
+#define DB_88F6560_PCAC_MPP8_15		0x31199999
+#define DB_88F6560_PCAC_MPP16_23	0x00000003
+#define DB_88F6560_PCAC_MPP24_31	0x00000000
+#define DB_88F6560_PCAC_MPP32_39	0x66004444
+#define DB_88F6560_PCAC_MPP40_47	0x00006666
+#define DB_88F6560_PCAC_MPP48_55	0x00000300
+#define DB_88F6560_PCAC_MPP56_63	0x00000000
+#define DB_88F6560_PCAC_MPP64_71	0x00000000
+#define DB_88F6560_PCAC_MPP72_79	0x00000000
+#define DB_88F6560_PCAC_MPP80_87	0x10000000
+#define DB_88F6560_PCAC_MPP88_88	0x00000000
+
+/* GPPs
+MPP#	NAME			IN/OUT
+--------------------------------------
+58		USB_Dev_Vbus	IN
+68		7-Seg		OUT
+69		7-Seg		OUT
+70		7-Seg		OUT
+71		7-Seg		OUT
+*/
+#define DB_88F6560_PCAC_GPP_OUT_ENA_LOW		0x0
+#define DB_88F6560_PCAC_GPP_OUT_ENA_MID		(BIT26)
+#define DB_88F6560_PCAC_GPP_OUT_ENA_HIGH	0x0
+
+#define DB_88F6560_PCAC_GPP_OUT_VAL_LOW		0x0
+#define DB_88F6560_PCAC_GPP_OUT_VAL_MID		0x0
+#define DB_88F6560_PCAC_GPP_OUT_VAL_HIGH	0x0
+
+#define DB_88F6560_PCAC_GPP_POL_LOW		0x0
+#define DB_88F6560_PCAC_GPP_POL_MID		0x0
+#define DB_88F6560_PCAC_GPP_POL_HIGH		0x0
+
+/***************************************************************************
+** DB-88F6560-BP
+****************************************************************************/
+#define DB_88F6535_MPP0_7		0x11111111
+#define DB_88F6535_MPP8_15		0x31111111
+#define DB_88F6535_MPP16_23		0x03555603
+#define DB_88F6535_MPP24_31		0x04400000
+#define DB_88F6535_MPP32_39		0x00444444
+#define DB_88F6535_MPP40_47		0x00000000
+#define DB_88F6535_MPP48_55		0x00000000
+#define DB_88F6535_MPP56_63		0x00000000
+#define DB_88F6535_MPP64_71		0x90000000
+#define DB_88F6535_MPP72_79		0x00000000
+#define DB_88F6535_MPP80_87		0x90000000
+#define DB_88F6535_MPP88_88		0x00000000
+
+/* GPPs
+MPP#	NAME			IN/OUT
+--------------------------------------
+17		XVR_TXfault_RST	IN/OUT?
+31		UsbDevice_Vbus	IN
+68		SD_Status	IN
+67		PEX_VCC_OFF	OUT
+69		SD_WP		IN
+*/
+#define DB_88F6535_GPP_OUT_ENA_LOW	(BIT31 | BIT23 | BIT17)
+#define DB_88F6535_GPP_OUT_ENA_MID	0x0
+#define DB_88F6535_GPP_OUT_ENA_HIGH	(BIT5 | BIT23)
+
+#define DB_88F6535_GPP_OUT_VAL_LOW	0x0
+#define DB_88F6535_GPP_OUT_VAL_MID	0x0
+#define DB_88F6535_GPP_OUT_VAL_HIGH	(BIT3)
+
+#define DB_88F6535_GPP_POL_LOW		(BIT23)
+#define DB_88F6535_GPP_POL_MID		0x0
+#define DB_88F6535_GPP_POL_HIGH		0x0
+
+
+/***************************************************************************
+** DB-CUSTOMER
+****************************************************************************/
+#define DB_CUSTOMER_MPP0_7		0x21111111
+#define DB_CUSTOMER_MPP8_15		0x00003311
+#define DB_CUSTOMER_MPP16_23		0x00001100
+#define DB_CUSTOMER_MPP24_31		0x00000000
+#define DB_CUSTOMER_MPP32_39		0x00000000
+#define DB_CUSTOMER_MPP40_47		0x00000000
+#define DB_CUSTOMER_MPP48_55		0x00000000
+#define DB_CUSTOMER_OE_LOW		0x0
+#define DB_CUSTOMER_OE_HIGH		(~((BIT6) | (BIT7) | (BIT8) | (BIT9)))
+#define DB_CUSTOMER_OE_VAL_LOW		0x0
+#define DB_CUSTOMER_OE_VAL_HIGH		0x0
+
+/***************************************************************************
+** DB-88F6601-BP
+****************************************************************************/
+#define DB_88F6601_MPP0_7		0x22222220
+#define DB_88F6601_MPP8_15		0x52222222
+#define DB_88F6601_MPP16_23		0x55520555
+#define DB_88F6601_MPP24_31		0x04445555
+#define DB_88F6601_MPP32_37		0x00050040
+
+/* GPPs
+ 0 GPIO[0] (inout) P_INT_S_TX_Fault
+ 1 SPI0_MOSI (out)
+ 2 SPI0_SCK (out)
+ 3 SPI0_CSn[0] (out)
+ 4 SPI0_MISO (in)
+ 5 I2C0_SDA (inout)
+ 6 I2C0_SCK (inout)
+ 7 UA0_TXD (out)
+ 8 UA0_RXD (in)
+ 9 TDM2C_CODEC_INTn (in)
+10 TDM2C_CODEC_RSTn (out)
+11 TDM2C_PCLK (inout)
+12 TDM2C_FS (inout)
+13 TDM2C_DRX (in)
+14 TDM2C_DTX (out)
+15 SPI1_CSn[0] (out)
+16 SPI1_MOSI (out)
+17 SPI1_SCK (out)
+18 SPI1_MISO (in)
+19 GPIO[19] (inout) SFP_LOS
+20 DYING_GASP (in)
+21 P3_LED (out)
+22 P0_LED (out)
+23 P1_LED (out)
+24 P2_LED (out)
+25 C0_LED (out)
+26 C1_LED (out)
+27 C2_LED (out)
+28 GE_MDC (out)
+29 GE_MDIO (inout)
+30 XVR_SD (in)
+31  GPIO[31] (inout) SFP_Dis
+32  GPIO[32] (inout) SFP_Present
+33  PON_BEN (out)
+34  GPIO[34] (inout) XVR_TX_Ind
+35  GPIO[35] (inout) XVR_TXfault_RST
+36  PON_BEN (out)
+37  TX_PD (out)
+*/
+#define DB_88F6601_GPP_OUT_ENA_LOW	(BIT0 | BIT19)
+#define DB_88F6601_GPP_OUT_ENA_MID	(BIT0 | BIT2  | BIT3 )
+
+#define DB_88F6601_GPP_OUT_VAL_LOW	0x0
+#define DB_88F6601_GPP_OUT_VAL_MID	0x0
+
+#define DB_88F6601_GPP_POL_LOW		0x0
+#define DB_88F6601_GPP_POL_MID		0x0
+
+
+
+
+/***************************************************************************
+** RD-88F6601
+****************************************************************************/
+#define RD_88F6601_MPP0_7		0x22222220
+#define RD_88F6601_MPP8_15		0x00000002
+#define RD_88F6601_MPP16_23		0x00400000
+#define RD_88F6601_MPP24_31		0x00200650
+#define RD_88F6601_MPP32_37		0x00000000
+
+/* GPPs
+ 1 SPI0_MOSI (out)
+ 2 SPI0_SCK (out)	
+ 3 SPI0_CSn[0] (out)
+ 4 SPI0_MISO (in)
+ 5 I2C0_SDA (inout)
+ 6 I2C0_SCK (inout)
+ 7 UA0_TXD (out)
+ 8 UA0_RXD (in)
+20 LED_PON
+21 PON_BEN (out)
+24 XVR_Tx_IND
+25 LED_G
+26 LED_Y 
+28 NF&SPI_WP
+29 XVR_SD (in)
+33 TX_Fault/TX_indication
+37 TX_PD
+
+
+*/
+#define RD_88F6601_GPP_OUT_ENA_LOW	(BIT0 | BIT13 | BIT14 | BIT16 | BIT17 | BIT18 | BIT19 | BIT22 | BIT23 | BIT24 | BIT27| BIT30 | BIT31) 
+#define RD_88F6601_GPP_OUT_ENA_MID	(BIT0 | BIT3 | BIT4)
+
+#define RD_88F6601_GPP_OUT_VAL_LOW	0x0
+#define RD_88F6601_GPP_OUT_VAL_MID	0x0
+
+#define RD_88F6601_GPP_POL_LOW		(BIT23)
+#define RD_88F6601_GPP_POL_MID		0x0
+
+
+#endif /* __INCmvBoardEnvSpech */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSysfs.c b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSysfs.c
new file mode 100755
index 0000000..fcb50c8
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/boardEnv/mvBoardEnvSysfs.c
@@ -0,0 +1,135 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+
+#include "boardEnv/mvBoardEnvLib.h"
+
+static ssize_t mvPonType(char *buf)
+{
+  MV_U32 ponType;
+  int    off = 0;
+
+  ponType = mvBoardPonConfigGet();
+
+  if (ponType == BOARD_EPON_CONFIG) 
+    off += sprintf(buf+off, "epon\n");
+  else if (ponType == BOARD_GPON_CONFIG) 
+    off += sprintf(buf+off, "gpon\n");
+
+  return off;
+}
+
+static ssize_t mvBoardType(char *buf)
+{
+  MV_U32 boardType;
+  int    off = 0;
+
+  boardType = mvBoardIdGet();
+
+  if (boardType == DB_88F6535_BP_ID) 
+    off += sprintf(buf+off, "db_board\n");
+  else if (boardType == RD_88F6510_SFU_ID) 
+    off += sprintf(buf+off, "rd_board\n");
+  
+  return off;
+}
+
+static ssize_t mvBoardEnvShow(struct device *dev, 
+				              struct device_attribute *attr, char *buf)
+{
+  const char*     name = attr->attr.name;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  if (!strcmp(name, "pon_type")) 
+    return(mvPonType(buf));
+  else if (!strcmp(name, "board_type")) 
+    return(mvBoardType(buf));
+
+  return(0);
+}
+
+static ssize_t mvBoardEnvStore(struct device *dev, 
+                               struct device_attribute *attr, 
+                               const char *buf, size_t len)
+{
+  return(0);
+}
+
+static DEVICE_ATTR(pon_type,   S_IRUSR, mvBoardEnvShow, mvBoardEnvStore);
+static DEVICE_ATTR(board_type, S_IRUSR, mvBoardEnvShow, mvBoardEnvStore);
+
+static struct attribute *mvBoardEnvAttrs[] = {
+	&dev_attr_pon_type.attr,
+    &dev_attr_board_type.attr,
+	NULL
+};
+
+static struct attribute_group mvBoardEnvGroup = {
+	.name = "board",
+	.attrs = mvBoardEnvAttrs,
+};
+
+int __devinit mvBoardEnvSysfsInit(void)
+{
+		int err;
+		struct device *pd;
+
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "boardEnv");
+		if (!pd) {
+			platform_device_register_simple("boardEnv", -1, NULL, 0);
+			pd = bus_find_device_by_name(&platform_bus_type, NULL, "boardEnv");
+		}
+
+		if (!pd) {
+			printk(KERN_ERR"%s: cannot find board device\n", __FUNCTION__);
+			pd = &platform_bus;
+		}
+
+		err = sysfs_create_group(&pd->kobj, &mvBoardEnvGroup);
+		if (err) {
+			printk(KERN_INFO "sysfs group failed %d\n", err);
+			goto out;
+		}
+out:
+		return err;
+}
+
+module_init(mvBoardEnvSysfsInit); 
+
+MODULE_AUTHOR("Oren Ben-Hayun");
+MODULE_DESCRIPTION("sysfs for Marvell Board Env");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.c b/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.c
new file mode 100755
index 0000000..0e34d43
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.c
@@ -0,0 +1,382 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "cpu/mvCpu.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvRegs.h"
+#include "ctrlEnv/sys/mvCpuIfRegs.h"
+#include "boardEnv/mvBoardEnvSpec.h"
+#include "boardEnv/mvBoardEnvLib.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/* locals */
+
+/*******************************************************************************
+* mvCpuClockEntryGet - Get the CPU / DDR / L2 entry index from the
+*			frequncies table.
+*
+* DESCRIPTION:
+*       This routine searches for a matching entry in the CPU / DDR / L2
+*	frequencies table according to the S@R value.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Index of matching entry, or 0xFFFFFFFF if S@R value is not valid.
+*
+*******************************************************************************/
+static MV_U32 mvCpuClockEntryGet(MV_VOID)
+{
+	MV_U32 i, res = -1;
+	MV_U32 sar0;
+	MV_U32 clockSatr;
+	MV_CPU_ARM_CLK cpuDdrL2Tbl[] = MV_CPU_DDR_L2_CLCK_TBL;
+	MV_CPU_ARM_CLK cpuDdrTbl6601[] = MV6601_CPU_DDR_CLCK_TBL;
+	MV_U32 boardId = mvBoardIdGet();
+
+	/* Read S@R registers value */
+	sar0 = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
+	clockSatr = MSAR_CPU_DDR_L2_CLCK_EXTRACT(sar0);
+
+	/* Search for a matching entry */
+	i = 0;
+	if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId)){
+		while (cpuDdrTbl6601[i].satrValue != -1) {
+			if (cpuDdrTbl6601[i].satrValue == clockSatr) {
+				res = i;
+				break;
+			}
+			i++;
+		}
+	} else {
+		while (cpuDdrL2Tbl[i].satrValue != -1) {
+			if (cpuDdrL2Tbl[i].satrValue == clockSatr) {
+				res = i;
+				break;
+			}
+			i++;
+		}
+	}
+	return res;
+}
+
+/*******************************************************************************
+* mvCpuPclkGet - Get the CPU pClk (pipe clock)
+*
+* DESCRIPTION:
+*       This routine extract the CPU core clock.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit clock cycles in MHertz.
+*
+*******************************************************************************/
+MV_U32 mvCpuPclkGet(MV_VOID)
+{
+#if defined(PCLCK_AUTO_DETECT)
+	MV_U32 idx;
+	MV_CPU_ARM_CLK cpuDdrL2Tbl[] = MV_CPU_DDR_L2_CLCK_TBL;
+	MV_CPU_ARM_CLK cpuDdrTbl6601[] = MV6601_CPU_DDR_CLCK_TBL;
+	MV_U32 boardId = mvBoardIdGet();
+
+	idx = mvCpuClockEntryGet();
+	if (idx == 0xFFFFFFFF)
+		return 0;
+	else {
+		if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId))
+			return cpuDdrTbl6601[idx].cpuClk;
+		else
+			return cpuDdrL2Tbl[idx].cpuClk;
+	}
+
+#else
+	return MV_DEFAULT_PCLK
+#endif
+}
+
+/*******************************************************************************
+* mvCpuL2ClkGet - Get the CPU L2 (CPU bus clock)
+*
+* DESCRIPTION:
+*       This routine extract the CPU L2 clock.
+*
+* RETURN:
+*       32bit clock cycles in Hertz.
+*
+*******************************************************************************/
+MV_U32 mvCpuL2ClkGet(MV_VOID)
+{
+#ifdef L2CLK_AUTO_DETECT
+	MV_U32 idx;
+	MV_CPU_ARM_CLK cpuDdrL2Tbl[] = MV_CPU_DDR_L2_CLCK_TBL;
+	MV_CPU_ARM_CLK cpuDdrTbl6601[] = MV6601_CPU_DDR_CLCK_TBL;
+	MV_U32 boardId = mvBoardIdGet();
+
+	idx = mvCpuClockEntryGet();
+	if (idx == 0xFFFFFFFF)
+		return 0;
+	else {
+		if ((RD_88F6601_MC_ID == boardId) || (DB_88F6601_BP_ID == boardId))
+			return cpuDdrTbl6601[idx].l2Clk;
+		else
+			return cpuDdrL2Tbl[idx].l2Clk;
+	}
+#else
+	return MV_BOARD_DEFAULT_L2CLK;
+#endif
+}
+
+/*******************************************************************************
+* mvCpuL2Exists
+*
+* DESCRIPTION:
+*       This routine checks if L2 exists according to reset strap.
+*
+* RETURN:
+*       MV_TRUE if L2 exists,
+*	MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_BOOL mvCpuL2Exists(MV_VOID)
+{
+	MV_U32 sar0;
+	MV_U32 mvBoardId = mvBoardIdGet();
+
+	if ((RD_88F6510_SFU_ID == mvBoardId) ||
+		(RD_88F6601_MC_ID == mvBoardId) ||
+		(DB_88F6601_BP_ID == mvBoardId))
+		return MV_FALSE;
+
+	/* Read S@R register value */
+	sar0 = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
+	if (sar0 & MSAR_L2EXIST_MASK)
+		return MV_TRUE;
+	else
+		return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvCpuNameGet - Get CPU name
+*
+* DESCRIPTION:
+*       This function returns a string describing the CPU model and revision.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       pNameBuff - Buffer to contain board name string. Minimum size 32 chars.
+*
+* RETURN:
+*       None.
+*******************************************************************************/
+MV_VOID mvCpuNameGet(char *pNameBuff)
+{
+	MV_U32 cpuModel;
+
+	cpuModel = mvOsCpuPartGet();
+
+	/* The CPU module is indicated in the Processor Version Register (PVR) */
+	switch (cpuModel) {
+	case CPU_PART_MRVL131:
+		mvOsSPrintf(pNameBuff, "%s (Rev %d)", "Marvell Feroceon", mvOsCpuRevGet());
+		break;
+	case CPU_PART_ARM926:
+		mvOsSPrintf(pNameBuff, "%s (Rev %d)", "ARM926", mvOsCpuRevGet());
+		break;
+	case CPU_PART_ARM946:
+		mvOsSPrintf(pNameBuff, "%s (Rev %d)", "ARM946", mvOsCpuRevGet());
+		break;
+	default:
+		mvOsSPrintf(pNameBuff, "??? (0x%04x) (Rev %d)", cpuModel, mvOsCpuRevGet());
+		break;
+	}			/* switch  */
+
+	return;
+}
+
+#define MV_PROC_STR_SIZE 50
+
+static void mvCpuIfGetL2EccMode(MV_8 *buf)
+{
+	MV_U32 regVal = MV_REG_READ(CPU_L2_CONFIG_REG);
+
+	if (regVal & BIT2)
+		mvOsSPrintf(buf, "L2 ECC Enabled");
+	else
+		mvOsSPrintf(buf, "L2 ECC Disabled");
+}
+
+static void mvCpuIfGetL2Mode(MV_8 *buf)
+{
+	MV_U32 regVal = 0;
+
+	__asm volatile ("mrc	p15, 1, %0, c15, c1, 0" : "=r" (regVal));	/* Read Marvell extra features register */
+	if (regVal & BIT22)
+		mvOsSPrintf(buf, "L2 Enabled");
+	else
+		mvOsSPrintf(buf, "L2 Disabled");
+}
+
+static void mvCpuIfGetL2PrefetchMode(MV_8 *buf)
+{
+	MV_U32 regVal = 0;
+
+	__asm volatile ("mrc	p15, 1, %0, c15, c1, 0" : "=r" (regVal));	/* Read Marvell extra features register */
+	if (regVal & BIT24)
+		mvOsSPrintf(buf, "L2 Prefetch Disabled");
+	else
+		mvOsSPrintf(buf, "L2 Prefetch Enabled");
+}
+
+static void mvCpuIfGetWriteAllocMode(MV_8 *buf)
+{
+	MV_U32 regVal = 0;
+	__asm volatile ("mrc	p15, 1, %0, c15, c1, 0" : "=r" (regVal));	/* Read Marvell extra features register */
+	if (regVal & BIT28)
+		mvOsSPrintf(buf, "Write Allocate Enabled");
+	else
+		mvOsSPrintf(buf, "Write Allocate Disabled");
+}
+
+static void mvCpuIfGetCpuStreamMode(MV_8 *buf)
+{
+	MV_U32 regVal = 0;
+	__asm volatile ("mrc	p15, 1, %0, c15, c1, 0" : "=r" (regVal));	/* Read Marvell extra features register */
+	if (regVal & BIT29)
+		mvOsSPrintf(buf, "CPU Streaming Enabled");
+	else
+		mvOsSPrintf(buf, "CPU Streaming Disabled");
+}
+
+static void mvCpuIfPrintCpuRegs(void)
+{
+	MV_U32 regVal = 0;
+
+	__asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal));	/* Read Marvell extra features register */
+	mvOsPrintf("Extra Feature Reg = 0x%x\n", regVal);
+
+	__asm volatile ("mrc	p15, 0, %0, c1, c0, 0" : "=r" (regVal));	/* Read Control register */
+	mvOsPrintf("Control Reg = 0x%x\n", regVal);
+
+	__asm volatile ("mrc	p15, 0, %0, c0, c0, 0" : "=r" (regVal));	/* Read ID Code register */
+	mvOsPrintf("ID Code Reg = 0x%x\n", regVal);
+
+	__asm volatile ("mrc	p15, 0, %0, c0, c0, 1" : "=r" (regVal));	/* Read Cache Type register */
+	mvOsPrintf("Cache Type Reg = 0x%x\n", regVal);
+
+}
+
+MV_U32 mvCpuIfPrintSystemConfig(MV_8 *buffer, MV_U32 index)
+{
+	MV_U32 count = 0;
+
+	MV_8 L2_ECC_str[MV_PROC_STR_SIZE];
+	MV_8 L2_En_str[MV_PROC_STR_SIZE];
+	MV_8 L2_Prefetch_str[MV_PROC_STR_SIZE];
+	MV_8 Write_Alloc_str[MV_PROC_STR_SIZE];
+	MV_8 Cpu_Stream_str[MV_PROC_STR_SIZE];
+
+	if (mvCtrlModelGet() != MV_6601_DEV_ID) {
+		mvCpuIfGetL2Mode(L2_En_str);
+		mvCpuIfGetL2EccMode(L2_ECC_str);
+		mvCpuIfGetL2PrefetchMode(L2_Prefetch_str);
+	}
+	mvCpuIfGetWriteAllocMode(Write_Alloc_str);
+	mvCpuIfGetCpuStreamMode(Cpu_Stream_str);
+	mvCpuIfPrintCpuRegs();
+
+	if (mvCtrlModelGet() != MV_6601_DEV_ID) {
+		count += mvOsSPrintf(buffer + count + index, "%s\n", L2_En_str);
+		count += mvOsSPrintf(buffer + count + index, "%s\n", L2_ECC_str);
+		count += mvOsSPrintf(buffer + count + index, "%s\n", L2_Prefetch_str);
+	}
+	count += mvOsSPrintf(buffer + count + index, "%s\n", Write_Alloc_str);
+	count += mvOsSPrintf(buffer + count + index, "%s\n", Cpu_Stream_str);
+	count += mvOsSPrintf(buffer + count + index, "CPU Config Reg = 0x%08x\n", MV_REG_READ(CPU_CONFIG_REG));
+	if (mvCtrlModelGet() != MV_6601_DEV_ID)
+		count += mvOsSPrintf(buffer + count + index, "L2 Config Reg = 0x%08x\n", MV_REG_READ(CPU_L2_CONFIG_REG));
+
+	return count;
+}
+
+MV_U32 whoAmI(MV_VOID)
+{
+	return 0;
+}
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.h b/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.h
new file mode 100755
index 0000000..470eb83
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/cpu/mvCpu.h
@@ -0,0 +1,99 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCpuh
+#define __INCmvCpuh
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+#define MASTER_CPU 0
+/* defines */
+#define CPU_PART_MRVL131      0x131
+#define CPU_PART_ARM926       0x926
+#define CPU_PART_ARM946       0x946
+#define MV_CPU_ARM_CLK_ELM_SIZE	    12
+#define MV_CPU_ARM_CLK_RATIO_OFF    8
+#define MV_CPU_ARM_CLK_DDR_OFF	    4
+
+#ifndef MV_ASMLANGUAGE
+typedef struct _mvCpuArmClk {
+	MV_U32 satrValue;	/* Sample @ Reset register value */
+	MV_U32 cpuClk;		/* CPU clock in MHz */
+	MV_U32 ddrClk;		/* DDR clock in MHz */
+	MV_U32 l2Clk;		/* CPU DDR clock ratio */
+
+} MV_CPU_ARM_CLK;
+
+MV_U32 mvCpuPclkGet(MV_VOID);
+MV_VOID mvCpuNameGet(char *pNameBuff);
+MV_U32 mvCpuL2ClkGet(MV_VOID);
+MV_BOOL mvCpuL2Exists(MV_VOID);
+MV_U32 mvCpuIfPrintSystemConfig(MV_8 *buffer, MV_U32 index);
+MV_U32 whoAmI(MV_VOID);
+
+#endif /* MV_ASMLANGUAGE */
+
+#endif /* __INCmvCpuh */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAddrDec.c b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAddrDec.c
new file mode 100755
index 0000000..30817b4
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAddrDec.c
@@ -0,0 +1,263 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvCtrlEnvAddrDec.h - Marvell controller address decode library
+*
+* DESCRIPTION:
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "sys/mvCpuIf.h"
+
+#undef MV_DEBUG
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/* Default Attributes array */
+MV_TARGET_ATTRIB mvTargetDefaultsArray[] = TARGETS_DEF_ARRAY;
+extern MV_TARGET sampleAtResetTargetArray[];
+
+/*******************************************************************************
+* mvCtrlAttribGet -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+/* TODO: Done. */
+MV_STATUS mvCtrlAttribGet(MV_TARGET target, MV_TARGET_ATTRIB *targetAttrib)
+{
+	targetAttrib->attrib = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].attrib;
+	targetAttrib->targetId = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].targetId;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCtrlGetAttrib -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+/* TODO: Done. */
+MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib)
+{
+	MV_TARGET target;
+	MV_TARGET x;
+	for (target = SDRAM_CS0; target < MAX_TARGETS; target++) {
+		x = MV_CHANGE_BOOT_CS(target);
+		if ((mvTargetDefaultsArray[x].attrib == targetAttrib->attrib) &&
+		    (mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].targetId == targetAttrib->targetId)) {
+			/* found it */
+			break;
+		}
+	}
+
+	return target;
+}
+
+/* TODO: Done. */
+MV_TARGET mvCtrlTargetByWinInfoGet(MV_UNIT_WIN_INFO *unitWinInfo)
+{
+	MV_TARGET target;
+	MV_TARGET x;
+	for (target = SDRAM_CS0; target < MAX_TARGETS; target++) {
+		x = MV_CHANGE_BOOT_CS(target);
+		if ((mvTargetDefaultsArray[x].attrib == unitWinInfo->attrib) &&
+		    (mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].targetId == unitWinInfo->targetId)) {
+			/* found it */
+			break;
+		}
+	}
+
+	return target;
+}
+
+/*******************************************************************************
+* mvCtrlAddrWinMapBuild
+*
+* DESCRIPTION:
+*	Build the windows address decoding table, to be used for initializing
+*	the unit's address decoding windows.
+*
+* INPUT:
+*	pAddrWinMap: An array to hold the address decoding windows parameters.
+*	len: Number of entries in pAddrWinMap.
+*
+* OUTPUT:
+*	pAddrWinMap: Address window information.
+*
+* RETURN:
+*	MV_BAD_PARAM: input array is smaller than needed to store all window
+*	addresses.
+*	MV_ERROR: Otherwise.
+*
+*******************************************************************************/
+/* TODO: Done. */
+MV_STATUS mvCtrlAddrWinMapBuild(MV_UNIT_WIN_INFO *pAddrWinMap, MV_U32 len)
+{
+	MV_CPU_DEC_WIN cpuAddrDecWin;
+	MV_U32 i;
+	MV_TARGET_ATTRIB targetAttrib;
+	MV_STATUS status;
+
+	/* Check size of CPU address win table */
+	if (len <= MAX_TARGETS) {
+		mvOsPrintf("mvCtrlAddrWinMapBuild() - Table size too small.\n");
+		return MV_BAD_PARAM;
+	}
+
+	/* Fill in the pAddrWinMap fields       */
+	for (i = 0; i < MAX_TARGETS; i++) {
+		status = mvCpuIfTargetWinGet(i, &cpuAddrDecWin);
+		if (status != MV_OK) {
+			if (status == MV_NO_SUCH) {
+				pAddrWinMap[i].enable = MV_FALSE;
+				continue;
+			} else {
+				mvOsPrintf("mvCtrlAddrWinMapBuild() - mvCpuIfTargetWinGet() failed.\n");
+				return MV_ERROR;
+			}
+		}
+
+		pAddrWinMap[i].addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow;
+		pAddrWinMap[i].addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
+		pAddrWinMap[i].addrWin.size = cpuAddrDecWin.addrWin.size;
+		pAddrWinMap[i].enable = cpuAddrDecWin.enable;
+
+		if (mvCtrlAttribGet(i, &targetAttrib) != MV_OK) {
+			mvOsPrintf("mvCtrlAddrWinMapBuild() - mvCtrlAttribGet() failed.\n");
+			return MV_ERROR;
+		}
+		pAddrWinMap[i].attrib = targetAttrib.attrib;
+		pAddrWinMap[i].targetId = targetAttrib.targetId;
+	}
+	pAddrWinMap[i].addrWin.baseLow = TBL_TERM;
+	pAddrWinMap[i].addrWin.baseHigh = TBL_TERM;
+	pAddrWinMap[i].addrWin.size = TBL_TERM;
+	pAddrWinMap[i].enable = TBL_TERM;
+	pAddrWinMap[i].attrib = TBL_TERM;
+	pAddrWinMap[i].targetId = TBL_TERM;
+
+	return MV_OK;
+}
+
+MV_STATUS mvCtrlAddrWinInfoGet(MV_UNIT_WIN_INFO *pAddrWinInfo, MV_ULONG physAddr)
+{
+	MV_CPU_DEC_WIN cpuAddrDecWin;
+	MV_U32 i;
+	MV_TARGET_ATTRIB targetAttrib;
+	MV_STATUS status;
+
+	for (i = 0; i < MAX_TARGETS; i++) {
+		status = mvCpuIfTargetWinGet(i, &cpuAddrDecWin);
+		if (status != MV_OK)
+			continue;
+		if (physAddr >= cpuAddrDecWin.addrWin.baseLow) {
+			if (physAddr < cpuAddrDecWin.addrWin.baseLow + cpuAddrDecWin.addrWin.size) {
+				/* Found */
+				pAddrWinInfo->addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow;
+				pAddrWinInfo->addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
+				pAddrWinInfo->addrWin.size = cpuAddrDecWin.addrWin.size;
+
+				if (mvCtrlAttribGet(i, &targetAttrib) != MV_OK) {
+					mvOsPrintf("mvCtrlAddrWinMapBuild() - mvCtrlAttribGet() failed.\n");
+					return MV_ERROR;
+				}
+				pAddrWinInfo->attrib = targetAttrib.attrib;
+				pAddrWinInfo->targetId = targetAttrib.targetId;
+				return MV_OK;
+			}
+		}
+	}
+	/* not found */
+	return MV_NOT_FOUND;
+}
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAddrDec.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAddrDec.h
new file mode 100755
index 0000000..c096296
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAddrDec.h
@@ -0,0 +1,186 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCtrlEnvAddrDech
+#define __INCmvCtrlEnvAddrDech
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+/* includes */
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvRegs.h"
+
+/* defines  */
+/* DUnit attributes */
+#define ATMWCR_WIN_DUNIT_CS0_OFFS		0
+#define ATMWCR_WIN_DUNIT_CS0_MASK		BIT0
+#define ATMWCR_WIN_DUNIT_CS0_REQ		(0 << ATMWCR_WIN_DUNIT_CS0_OFFS)
+
+#define ATMWCR_WIN_DUNIT_CS1_OFFS		1
+#define ATMWCR_WIN_DUNIT_CS1_MASK		BIT1
+#define ATMWCR_WIN_DUNIT_CS1_REQ 		(0 << ATMWCR_WIN_DUNIT_CS1_OFFS)
+
+#define ATMWCR_WIN_DUNIT_CS2_OFFS		2
+#define ATMWCR_WIN_DUNIT_CS2_MASK		BIT2
+#define ATMWCR_WIN_DUNIT_CS2_REQ 		(0 << ATMWCR_WIN_DUNIT_CS2_OFFS)
+
+#define ATMWCR_WIN_DUNIT_CS3_OFFS		3
+#define ATMWCR_WIN_DUNIT_CS3_MASK		BIT3
+#define ATMWCR_WIN_DUNIT_CS3_REQ 		(0 << ATMWCR_WIN_DUNIT_CS3_OFFS)
+
+/* RUnit (Device)  attributes */
+#define ATMWCR_WIN_RUNIT_DEVCS0_OFFS		0
+#define ATMWCR_WIN_RUNIT_DEVCS0_MASK		BIT0
+#define ATMWCR_WIN_RUNIT_DEVCS0_REQ		(0 << ATMWCR_WIN_RUNIT_DEVCS0_OFFS)
+
+#define ATMWCR_WIN_RUNIT_DEVCS1_OFFS		1
+#define ATMWCR_WIN_RUNIT_DEVCS1_MASK		BIT1
+#define ATMWCR_WIN_RUNIT_DEVCS1_REQ 		(0 << ATMWCR_WIN_RUNIT_DEVCS1_OFFS)
+
+#define ATMWCR_WIN_RUNIT_DEVCS2_OFFS		2
+#define ATMWCR_WIN_RUNIT_DEVCS2_MASK		BIT2
+#define ATMWCR_WIN_RUNIT_DEVCS2_REQ 		(0 << ATMWCR_WIN_RUNIT_DEVCS2_OFFS)
+
+#define ATMWCR_WIN_RUNIT_BOOTCS_OFFS		4
+#define ATMWCR_WIN_RUNIT_BOOTCS_MASK		BIT4
+#define ATMWCR_WIN_RUNIT_BOOTCS_REQ 		(0 << ATMWCR_WIN_RUNIT_BOOTCS_OFFS)
+
+/* LMaster (PCI)  attributes */
+#define ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS		0
+#define ATMWCR_WIN_LUNIT_BYTE_SWP_MASK		BIT0
+#define ATMWCR_WIN_LUNIT_BYTE_SWP		(0 << ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS)
+#define ATMWCR_WIN_LUNIT_BYTE_NO_SWP		(1 << ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS)
+
+#define ATMWCR_WIN_LUNIT_WORD_SWP_OFFS		1
+#define ATMWCR_WIN_LUNIT_WORD_SWP_MASK		BIT1
+#define ATMWCR_WIN_LUNIT_WORD_SWP		(0 << ATMWCR_WIN_LUNIT_WORD_SWP_OFFS)
+#define ATMWCR_WIN_LUNIT_WORD_NO_SWP		(1 << ATMWCR_WIN_LUNIT_WORD_SWP_OFFS)
+
+#define ATMWCR_WIN_LUNIT_NO_SNOOP		BIT2
+
+#define ATMWCR_WIN_LUNIT_TYPE_OFFS		3
+#define ATMWCR_WIN_LUNIT_TYPE_MASK		BIT3
+#define ATMWCR_WIN_LUNIT_TYPE_IO		(0 << ATMWCR_WIN_LUNIT_TYPE_OFFS)
+#define ATMWCR_WIN_LUNIT_TYPE_MEM		(1 << ATMWCR_WIN_LUNIT_TYPE_OFFS)
+
+#define ATMWCR_WIN_LUNIT_FORCE64_OFFS		4
+#define ATMWCR_WIN_LUNIT_FORCE64_MASK		BIT4
+#define ATMWCR_WIN_LUNIT_FORCE64		(0 << ATMWCR_WIN_LUNIT_FORCE64_OFFS)
+
+#define ATMWCR_WIN_LUNIT_ORDERING_OFFS		6
+#define ATMWCR_WIN_LUNIT_ORDERING_MASK		BIT6
+#define ATMWCR_WIN_LUNIT_ORDERING		(1 << ATMWCR_WIN_LUNIT_FORCE64_OFFS)
+
+/* PEX Attributes */
+#define ATMWCR_WIN_PEX_TYPE_OFFS		3
+#define ATMWCR_WIN_PEX_TYPE_MASK		BIT3
+#define ATMWCR_WIN_PEX_TYPE_IO			(0 << ATMWCR_WIN_PEX_TYPE_OFFS)
+#define ATMWCR_WIN_PEX_TYPE_MEM			(1 << ATMWCR_WIN_PEX_TYPE_OFFS)
+
+/* typedefs */
+
+/* Unsupported attributes for address decode:                               */
+/* 2) PCI0/1_REQ64n control                                                 */
+
+typedef struct _mvTargetAttrib {
+	MV_U8 attrib;		/* chip select attributes */
+	MV_TARGET_ID targetId;	/* Target Id of this MV_TARGET */
+} MV_TARGET_ATTRIB;
+
+/* This structure describes address decode window                           */
+typedef struct _mvDecWin {
+	MV_TARGET target;	/* Target for addr decode window        */
+	MV_ADDR_WIN addrWin;	/* Address window of target             */
+	MV_BOOL enable;		/* Window enable/disable                */
+} MV_DEC_WIN;
+
+typedef struct _mvDecWinParams {
+	MV_TARGET_ID targetId;	/* Target ID field */
+	MV_U8 attrib;		/* Attribute field */
+	MV_U32 baseAddr;	/* Base address in register format */
+	MV_U32 size;		/* Size in register format */
+} MV_DEC_WIN_PARAMS;
+
+/* mvCtrlEnvAddrDec API list */
+
+MV_STATUS mvCtrlAttribGet(MV_TARGET target, MV_TARGET_ATTRIB *targetAttrib);
+
+MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib);
+MV_TARGET mvCtrlTargetByWinInfoGet(MV_UNIT_WIN_INFO *unitWinInfo);
+
+MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, MV_DEC_WIN_PARAMS * pWinParam);
+
+MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam, MV_DEC_WIN * pAddrDecWin);
+
+MV_STATUS mvCtrlAddrWinMapBuild(MV_UNIT_WIN_INFO *pAddrWinMap, MV_U32 len);
+
+MV_STATUS mvCtrlAddrWinInfoGet(MV_UNIT_WIN_INFO *pAddrWinInfo, MV_ULONG physAddr);
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif /* __INCmvCtrlEnvAddrDech */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAsm.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAsm.h
new file mode 100755
index 0000000..cb13691
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvAsm.h
@@ -0,0 +1,97 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCtrlEnvAsmh
+#define __INCmvCtrlEnvAsmh
+#include "pex/mvPexRegs.h"
+
+#define CHIP_BOND_REG			0x18238
+#define PCKG_OPT_MASK_AS 		#3
+#define PXCCARI_REVID_MASK_AS           #PXCCARI_REVID_MASK
+
+/* Read device ID into toReg bits 15:0 from 0xd0000000 */
+/* defines  */
+#define MV_DV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \
+	MV_DV_REG_READ_ASM(toReg, tmpReg, CHIP_BOND_REG);\
+	and     toReg, toReg, PCKG_OPT_MASK_AS	/* Mask for package ID */
+
+/* Read device ID into toReg bits 15:0 from 0xf1000000*/
+#define MV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \
+	MV_REG_READ_ASM(toReg, tmpReg, CHIP_BOND_REG);\
+	and     toReg, toReg, PCKG_OPT_MASK_AS	/* Mask for package ID */
+
+/* Read Revision into toReg bits 7:0 0xd0000000*/
+#define MV_DV_CTRL_REV_GET_ASM(toReg, tmpReg)	\
+	/* Read device revision */			\
+	MV_DV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0, PEX_CLASS_CODE_AND_REVISION_ID));\
+	and     toReg, toReg, PXCCARI_REVID_MASK_AS	/* Mask for calss ID */
+
+/* Read Revision into toReg bits 7:0 0xf1000000*/
+#define MV_CTRL_REV_GET_ASM(toReg, tmpReg)	\
+	/* Read device revision */			\
+	MV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0, PEX_CLASS_CODE_AND_REVISION_ID));\
+	and     toReg, toReg, PXCCARI_REVID_MASK_AS	/* Mask for calss ID */
+#endif /* __INCmvCtrlEnvAsmh */
+
+
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvLib.c b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvLib.c
new file mode 100755
index 0000000..ea655ab
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvLib.c
@@ -0,0 +1,2772 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* includes */
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ctrlEnv/mvCtrlEthCompLib.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "gpp/mvGpp.h"
+#include "cpu/mvCpu.h"
+
+#if defined(MV_INCLUDE_PEX)
+#include "pci-if/mvPciIf.h"
+#include "pex/mvPex.h"
+#include "pex/mvPexRegs.h"
+#endif
+
+#if defined(MV_INCLUDE_GIG_ETH)
+#if defined(CONFIG_MV_ETH_LEGACY)
+#include "eth/mvEth.h"
+#else
+#include "neta/gbe/mvNeta.h"
+#endif /* CONFIG_MV_ETH_LEGACY or CONFIG_MV_ETH_NETA */
+#endif
+
+#if defined(MV_INCLUDE_XOR)
+#include "xor/mvXor.h"
+#endif
+
+#if defined(MV_INCLUDE_SATA)
+#include "sata/CoreDriver/mvSata.h"
+#endif
+
+#if defined(MV_INCLUDE_USB)
+#include "usb/mvUsb.h"
+#endif
+
+#if defined(MV_INCLUDE_AUDIO)
+#include "audio/mvAudio.h"
+#endif
+
+#if defined(MV_INCLUDE_PDMA)
+#include "ctrlEnv/sys/mvSysPdmaApi.h"
+#endif
+
+#if defined(MV_INCLUDE_TS)
+#include "ts/mvTsu.h"
+#endif
+
+#if defined(MV_INCLUDE_TDM)
+#include "mvSysTdmConfig.h"
+#endif
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+#if defined(MV_INCLUDE_TDM)
+MV_VOID mvCtrlTdmClkCtrlConfig(MV_VOID);
+#if defined(MV_TDM_USE_DCO)
+MV_32 mvCtrlTdmClkCtrlGet(MV_VOID);
+MV_VOID mvCtrlTdmClkCtrlSet(MV_32 correction);
+#endif
+#endif
+
+#if defined(MV_INCLUDE_CESA)
+static MV_VOID mvCtrlCesaDivClkConfig(MV_VOID);
+#endif
+
+
+/*******************************************************************************
+* mvCtrlEnvInit - Initialize Marvell controller environment.
+*
+* DESCRIPTION:
+*       This function get environment information and initialize controller
+*       internal/external environment. For example
+*       1) MPP settings according to board MPP macros.
+*		NOTE: It is the user responsibility to shut down all DMA channels
+*		in device and disable controller sub units interrupts during
+*		boot process.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_STATUS mvCtrlEnvInit(MV_VOID)
+{
+	MV_U32 mppGroup;
+	MV_U32 devId;
+	MV_U32 boardId;
+	MV_U32 i;
+	MV_U32 mppVal = 0;
+	MV_U32 bootVal = 0;
+	MV_U32 mppGroupType = 0;
+	MV_U32 mppGroup1[][3] = MPP_GROUP_1_TYPE;
+	MV_U32 mppGroup2[][3] = MPP_GROUP_2_TYPE;
+	MV_U32 mppGroup3[][3] = MPP_GROUP_3_TYPE;
+	MV_U32 mppG1Mask[] = MPP_GROUP_1_MASK;
+	MV_U32 mppG2Mask[] = MPP_GROUP_2_MASK;
+	MV_U32 mppG3Mask[] = MPP_GROUP_3_MASK;
+	MV_U32 ethCompOpt;
+	MV_BOARD_SPEC_INIT *boardSpec;
+	MV_U32 autoMppConfig;
+
+	boardSpec = mvBoardSpecInitGet();
+	if (boardSpec != NULL) {
+		MV_U32 reg;
+		i = 0;
+		while (boardSpec[i].reg != TBL_TERM) {
+			reg = MV_REG_READ(boardSpec[i].reg);
+			reg &= ~boardSpec[i].mask;
+			reg |= (boardSpec[i].val & boardSpec[i].mask);
+			MV_REG_WRITE(boardSpec[i].reg, reg);
+			i++;
+		}
+	}
+	boardId 	= mvBoardIdGet();
+	devId 		= mvCtrlModelGet();
+	if (MV_6601_DEV_ID != devId){
+		if (mvCpuL2Exists() == MV_TRUE)
+			MV_REG_BIT_RESET(PMU_POWER_IF_POLARITY_REG, BIT0);
+		else
+			MV_REG_BIT_SET(PMU_POWER_IF_POLARITY_REG, BIT0);
+	}
+
+	autoMppConfig = ((mvBoardModuleAutoDetectEnabled() == MV_TRUE) ? 1 : 0);
+
+	/* MPP Init */
+	/* We split mpp init to 3 phases:
+	 * 1. We init mpp[19:0] from the board info. mpp[23:20] will be overwritten
+	 * in phase 2.
+	 * 2. We detect the mpp group type and according the mpp values [35:20].
+	 * 3. We detect the mpp group type and according the mpp values [49:36].
+	 */
+	/* Mpp phase 1 mpp[22:0] */
+	/* Read MPP group from board level and assign to MPP register */
+	for (mppGroup = 0; mppGroup < 3; mppGroup++) {
+		mppVal = mvBoardMppGet(mppGroup);
+		if (mppGroup == 0) {
+				bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+			if (mvCtrlIsBootFromNAND() || mvCtrlIsBootFromNOR()) {
+				mppVal &= ~0xffffffff;
+				bootVal &= 0xffffffff;
+				mppVal |= bootVal;
+			}
+		}
+		if (mppGroup == 1) {
+				bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+			if (mvCtrlIsBootFromNAND()) {
+				mppVal &= ~0xfffff;
+				bootVal &= 0xfffff;
+				mppVal |= bootVal;
+			}
+		}
+
+		MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal);
+	}
+
+	/* only for CV checks, setting the SW_PPU_MDC & SW_PPU_MDIO MPPs */
+	/* MV_REG_WRITE(mvCtrlMppRegGet(3), 0x03300000); - we need to support this in the future! */
+
+	/* Identify MPPs group */
+	mvBoardMppIdUpdate();
+
+	if (MV_6601_DEV_ID == devId) {
+				MV_REG_WRITE(mvCtrlMppRegGet(3), mvBoardMppGet(3));
+				MV_REG_WRITE(mvCtrlMppRegGet(4), mvBoardMppGet(4));
+		} else {
+				/* Update the MPP & Internal Mux configurations according to the
+				   MPP group detection results. */
+
+				mppGroupType = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_1);
+				/* Mpp phase 2 */
+				/* Read MPP group from board level and assign to MPP register */
+				i = 0;
+				for (mppGroup = 2; mppGroup < 5; mppGroup++) {
+						if (mppGroupType == MV_BOARD_OTHER) {
+								mppVal = mvBoardMppGet(mppGroup);
+						} else {
+								mppVal = mvBoardMppGet(mppGroup);
+								mppVal &= ~mppG1Mask[i];
+								mppVal |= mppGroup1[mppGroupType][i];
+								i++;
+						}
+
+						if (mppGroup == 4) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								if (mvCtrlIsBootFromSPI()) {
+										mppVal &= ~0xffff;
+										bootVal &= 0xffff;
+										mppVal |= bootVal;
+								} else if (mvCtrlIsBootFromNOR() == MV_NOR_LOW_MPPS) {
+										mppVal &= ~0xff000000;
+										bootVal &= 0xff000000;
+										mppVal |= bootVal;
+								}
+						}
+
+						if (mppGroup == 3) {
+								ethCompOpt = mvBoardEthComplexConfigGet();
+								/* DB settings only: MDC/MDIO - do we need to set it to SW or to GW?? */
+								if (autoMppConfig && ((mppVal & 0xFF00000) == 0x4400000)) {
+										/* Note: we only get here if the MPPs are not for TDM comm unit */
+										if ((ethCompOpt & (ESC_OPT_RGMIIA_SW_P5 | ESC_OPT_RGMIIA_SW_P6)) ||
+											(mvBoardSmiScanModeGet(0) == 1)) {
+												mppVal &= ~0xFF00000;
+												mppVal |= 0x3300000;
+										}
+								}
+						}
+
+						/* Group 2 is shared mpp[23:23] */
+						if (mppGroup == 2) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								mppVal &= ~0x0fffffff;
+								bootVal &= 0x0fffffff;
+								mppVal |= bootVal;
+								/* SDIO support */
+								if (autoMppConfig && (mvBoardIsSdioEnabled() == MV_TRUE)) {
+										mppVal &= ~0x0FFFFFF0;
+										mppVal |= 0x01111110;
+								}
+						}
+						MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal);
+				}
+
+				/* Mpp phase 3 RGMII1 */
+				mppGroupType = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_2);
+				/* Read MPP group from board level and assign to MPP register */
+				i = 0;
+				for (mppGroup = 4; mppGroup < 7; mppGroup++) {
+						if (mppGroupType == MV_BOARD_OTHER)
+								mppVal = mvBoardMppGet(mppGroup);
+						else {
+								mppVal = mvBoardMppGet(mppGroup);
+								mppVal &= ~mppG2Mask[i];
+								mppVal |= mppGroup2[mppGroupType][i];
+								i++;
+						}
+
+						/* Group 4 is shared mpp[37:32] */
+						if (mppGroup == 4) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								if (mvCtrlIsBootFromNOR() == MV_NOR_LOW_MPPS) {
+										mppVal &= ~0xff000000;
+										bootVal &= 0xff000000;
+										mppVal |= bootVal;
+								}
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								mppVal &= ~0x00ffffff;
+								bootVal &= 0x00ffffff;
+								mppVal |= bootVal;
+						}
+
+						if (mppGroup == 5) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								if (mvCtrlIsBootFromNOR() == MV_NOR_LOW_MPPS) {
+										mppVal &= ~0xffffffff;
+										bootVal &= 0xffffffff;
+										mppVal |= bootVal;
+								}
+						}
+
+						if (mppGroup == 6) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								if (mvCtrlIsBootFromNOR() == MV_NOR_LOW_MPPS) {
+										mppVal &= ~0x000fffff;
+										bootVal &= 0x000fffff;
+										mppVal |= bootVal;
+								}
+						}
+
+						MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal);
+				}
+
+				/* Mpp phase 4 */
+				mppGroupType = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_3);
+				/* Read MPP group from board level and assign to MPP register */
+				i = 0;
+				for (mppGroup = 6; mppGroup < 9; mppGroup++) {
+						if (mppGroupType == MV_BOARD_OTHER)
+								mppVal = mvBoardMppGet(mppGroup);
+						else {
+								mppVal = mvBoardMppGet(mppGroup);
+								mppVal &= ~mppG3Mask[i];
+								mppVal |= mppGroup3[mppGroupType][i];
+								i++;
+						}
+
+						/* Group 6 is shared mpp[52:48] */
+						if (mppGroup == 6) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								mppVal &= ~0x000fffff;
+								bootVal &= 0x000fffff;
+								mppVal |= bootVal;
+						}
+
+						if (mppGroup == 8) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								if (mvCtrlIsBootFromNOR() == MV_NOR_LOW_MPPS) {
+										mppVal &= ~0xff00;
+										bootVal &= 0xff00;
+										mppVal |= bootVal;
+								}
+						}
+
+						MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal);
+				}
+
+				/* Mpp phase 5 */
+				for (mppGroup = 9; mppGroup < 12; mppGroup++) {
+						mppVal = mvBoardMppGet(mppGroup);
+						if (mppGroup == 9) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								if (mvCtrlIsBootFromNOR() == MV_NOR_HIGH_MPPS) {
+										mppVal &= ~0xffffffff;
+										bootVal &= 0xffffffff;
+										mppVal |= bootVal;
+								}
+						}
+						if (mppGroup == 10) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								if (mvCtrlIsBootFromNOR() == MV_NOR_HIGH_MPPS) {
+										mppVal &= ~0xffffffff;
+										bootVal &= 0xffffffff;
+										mppVal |= bootVal;
+								}
+						}
+						if (mppGroup == 11) {
+								bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+								if (mvCtrlIsBootFromNOR() == MV_NOR_HIGH_MPPS) {
+										mppVal &= ~0xf;
+										bootVal &= 0xf;
+										mppVal |= bootVal;
+								}
+						}
+						MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal);
+				}
+		}
+	
+
+	mvEthernetComplexInit();
+#if defined(MV_INCLUDE_TDM)
+	mvCtrlTdmClkCtrlConfig();
+#endif
+
+#if defined(MV_INCLUDE_CESA)
+	mvCtrlCesaDivClkConfig();
+#endif
+
+	if ((mvCtrlRevGet() < 2) && ((MV_65XX_DEV_ID == (mvCtrlModelGet() & 0xff00)))) {
+		/* Setup Ana-Grp1 config register. */
+		MV_REG_WRITE(ANA_GRP1_CONFIG_REG, ANA_GRP1_CFG_DEF_VAL);
+	}
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvCtrlEthComplexMppUpdate
+*
+* DESCRIPTION:
+*	Update the MPP registers following a change in ethernet complex
+*	configuration.
+*
+* INPUT:
+*	ethCompOpt - The ethernet complex option that was removed / inserted.
+*	addRem - MV_TRUE if this ethernet complex option was added.
+*		 MV_FALSE if this ethernet complex option was removed.
+*
+* OUTPUT:
+*
+* RETURN:
+*       MV_STATUS - MV_OK, MV_ERROR.
+*
+*******************************************************************************/
+MV_STATUS mvCtrlEthComplexMppUpdate(MV_U32 ethCompOpt, MV_BOOL addRem)
+{
+	MV_U32 mppGroup2[][3] = MPP_GROUP_2_TYPE;
+	MV_U32 mppGroup3[][3] = MPP_GROUP_3_TYPE;
+	MV_U32 mppG2Mask[] = MPP_GROUP_2_MASK;
+	MV_U32 mppG3Mask[] = MPP_GROUP_3_MASK;
+	MV_U32 *mppGroupVal = NULL;
+	MV_U32 *mppGroupMask = NULL;
+	MV_U32 mppGroup = 0, mppGrpStart = 0, mppGrpEnd = 0;
+	MV_U32 i, mppGrpType = 0;
+	MV_U32 reg;
+
+	if (ethCompOpt == ESC_OPT_RGMIIB_MAC0) {
+		mppGrpStart = 4;
+		mppGrpEnd = 7;
+		mppGrpType = MV_BOARD_GE0;
+		mppGroupVal = mppGroup2[mppGrpType];
+		mppGroupMask = mppG2Mask;
+	} else if ((ethCompOpt & (ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIA_MAC1 |
+				ESC_OPT_RGMIIA_SW_P5 | ESC_OPT_RGMIIA_SW_P6)) == ethCompOpt) {
+		mppGrpStart = 6;
+		mppGrpEnd = 9;
+		if (ethCompOpt == ESC_OPT_RGMIIA_MAC0)
+			mppGrpType = MV_BOARD_GE0;
+		else if (ethCompOpt == ESC_OPT_RGMIIA_MAC1)
+			mppGrpType = MV_BOARD_GE1;
+		else if (ethCompOpt == ESC_OPT_RGMIIA_SW_P5)
+			mppGrpType = MV_BOARD_SW_P5;
+		else if (ethCompOpt == ESC_OPT_RGMIIA_SW_P6)
+			mppGrpType = MV_BOARD_SW_P6;
+		mppGroupVal = mppGroup3[mppGrpType];
+		mppGroupMask = mppG3Mask;
+	}
+
+	/* Read MPP group from board level and assign to MPP register */
+	i = 0;
+	for (mppGroup = mppGrpStart; mppGroup < mppGrpEnd; mppGroup++) {
+		reg = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
+		reg &= ~mppGroupMask[i];
+		if (addRem == MV_TRUE)
+			reg |= mppGroupVal[i];
+		i++;
+
+		MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), reg);
+	}
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvCtrlEthSataComplexBuildConfig
+*
+* DESCRIPTION:
+*	Build the Ethernet / Sata comples configuration according to the
+*	on-board modules.
+*
+* INPUT:
+*	brdModules - A bitmask of the on-board modules.
+*
+* OUTPUT:
+*	ethConfig - A bitmask representing the ethernet complex configuration.
+*
+* RETURN:
+*       MV_STATUS - MV_OK, MV_ERROR.
+*
+*******************************************************************************/
+MV_STATUS mvCtrlEthSataComplexBuildConfig(MV_U32 brdModules, MV_ETH_COMPLEX_IF_SOURCES *ifSrc, MV_U32 *ethConfig)
+{
+	MV_U32 enabled = 0;
+	MV_U32 mask = ESC_OPT_ALL;
+	MV_U8 swExist = 0;
+	MV_U32 tmpMask;
+	/* Avanta-MC */
+	if (MV_6601_DEV_ID == mvCtrlModelGet()) {
+		if (ifSrc->feGeSrc == EC_MAC0_SRC)   /* MAC0 --> GbE PHY, MAC1 --> LP SERDES */ 
+			enabled |= ESC_OPT_GEPHY_MAC0;
+
+		if (brdModules & MV_BOARD_MODULE_FE_GE_PHY_ID)
+			enabled |= ESC_OPT_LP_SERDES_FE_GE_PHY;
+
+		if (ifSrc->macType == EC_SGMII_2_5G)
+			enabled |= ESC_OPT_SGMII_2_5; 	/* SGMII 2.5 MAC0 */
+		else
+			enabled |= ESC_OPT_SGMII;
+
+	}
+	/* Sata */
+	if (brdModules & MV_BOARD_MODULE_SATA_ID) {
+		if (brdModules & MV_BOARD_MODULE_QSGMII_ID)
+			enabled |= ESC_OPT_ILLEGAL;
+		else {
+			enabled |= ESC_OPT_SATA;
+			mask &= ~(ESC_OPT_QSGMII | ESC_OPT_SGMII);
+		}
+	}
+
+	/* QSGMII */
+	if (brdModules & MV_BOARD_MODULE_QSGMII_ID) {
+		if (brdModules & (MV_BOARD_MODULE_SATA_ID | MV_BOARD_MODULE_4FE_PHY_ID))
+			enabled |= ESC_OPT_ILLEGAL;
+		else {
+			enabled |= ESC_OPT_QSGMII;
+			mask &= ~(ESC_OPT_SATA | ESC_OPT_FE3PHY | ESC_OPT_SGMII);
+			swExist = 1;
+		}
+	}
+
+	/* 3xFE */
+	if (brdModules & MV_BOARD_MODULE_4FE_PHY_ID) {
+		if (brdModules & MV_BOARD_MODULE_QSGMII_ID)
+			enabled |= ESC_OPT_ILLEGAL;
+		else {
+			enabled |= ESC_OPT_FE3PHY;
+			mask &= ~(ESC_OPT_QSGMII);
+			swExist = 1;
+		}
+	}
+
+	if (!swExist) {
+		mask &= ~(ESC_OPT_RGMIIA_SW_P5 | ESC_OPT_RGMIIA_SW_P6 |
+			  ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_GEPHY_SW_P5);
+	}
+
+	/* RGMIIB */
+	if (brdModules & (MV_BOARD_MODULE_RGMIIB_ID | MV_BOARD_MODULE_MIIB_ID)) {
+		enabled |= ESC_OPT_RGMIIB_MAC0;
+		mask &= ~ESC_OPT_RGMIIB_MAC0;
+	}
+
+	/* RGMIIA */
+	if (brdModules & (MV_BOARD_MODULE_RGMIIA_ID | MV_BOARD_MODULE_MIIA_ID)) {
+		tmpMask = (ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_RGMIIA_SW_P5 | ESC_OPT_RGMIIA_SW_P6);
+		tmpMask &= mask;
+		if (MV_IS_POWER_OF_2(tmpMask))	/* RMGII0 source is well defined. */
+			enabled |= tmpMask;
+		/* Need to use external info to figure out RGMIIA source. */
+		else if (ifSrc->rgmiiASrc == EC_MAC0_SRC) {
+			enabled |= ESC_OPT_RGMIIA_MAC0;
+			mask &= ~(tmpMask ^ ESC_OPT_RGMIIA_MAC0);
+		} else if (ifSrc->rgmiiASrc == EC_MAC1_SRC) {
+			enabled |= ESC_OPT_RGMIIA_MAC1;
+			mask &= ~ESC_OPT_GEPHY_MAC1;
+			mask &= ~(tmpMask ^ ESC_OPT_RGMIIA_MAC1);
+		} else if (ifSrc->rgmiiASrc == EC_SW_P5_SRC) {
+			enabled |= ESC_OPT_RGMIIA_SW_P5;
+			mask &= ~(ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIA_MAC1);
+			mask &= ~(tmpMask ^ ESC_OPT_RGMIIA_SW_P5);
+		} else if (ifSrc->rgmiiASrc == EC_SW_P6_SRC) {
+			enabled |= ESC_OPT_RGMIIA_SW_P6;
+			mask &= ~(ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIA_MAC1);
+			mask &= ~(tmpMask ^ ESC_OPT_RGMIIA_SW_P6);
+		}
+	}
+
+	/* FE / GE PHY */
+	if (brdModules & MV_BOARD_MODULE_FE_GE_PHY_ID) {
+/*  		tmpMask = ESC_OPT_GEPHY_MAC1 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_GEPHY_SW_P5; */
+/*  		tmpMask &= mask; */
+		/*  		if(MV_IS_POWER_OF_2(tmpMask))*//* FE/GE source is well defined. */
+/*  			enabled |= tmpMask; */
+		/* Need to use external info to figure out GE/FE source. */
+		if (ifSrc->feGeSrc == EC_MAC1_SRC) {
+			enabled |= ESC_OPT_GEPHY_MAC1;
+			mask &= ~(tmpMask ^ ESC_OPT_GEPHY_MAC1);
+		} else if (ifSrc->feGeSrc == EC_SW_P0_SRC) {
+			enabled |= ESC_OPT_GEPHY_SW_P0;
+			mask &= ~(tmpMask ^ ESC_OPT_GEPHY_SW_P0);
+		} else if (ifSrc->feGeSrc == EC_SW_P5_SRC) {
+			enabled |= ESC_OPT_GEPHY_SW_P5;
+			mask &= ~(tmpMask ^ ESC_OPT_GEPHY_SW_P5);
+		}
+	}
+
+	/* SGMII */
+	if (brdModules & MV_BOARD_MODULE_SGMII_ID) {
+		enabled |= ESC_OPT_SGMII;
+
+		/* SGMII on Switch Port #1 */
+		if ((ifSrc->swSrc == EC_MAC0_SRC) || (ifSrc->swSrc == EC_MAC0_MAC1_SRC)) {
+			enabled |= ESC_OPT_SGMII_2_SW_P1;
+			swExist = 1;
+		}
+	}
+
+	if (swExist) {
+		if ((!(enabled & (ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIB_MAC0))) &&
+		    ((ifSrc->swSrc == EC_SRC_NONE) || (ifSrc->swSrc == EC_MAC0_SRC) ||
+		     (ifSrc->swSrc == EC_MAC0_MAC1_SRC)))
+			enabled |= ESC_OPT_MAC0_2_SW_P4;
+		if ((!(enabled & (ESC_OPT_GEPHY_SW_P5 | ESC_OPT_RGMIIA_SW_P5 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_GEPHY_MAC1))) &&
+			 ((ifSrc->swSrc == EC_MAC1_SRC) || (ifSrc->swSrc == EC_MAC0_MAC1_SRC)))
+			enabled |= ESC_OPT_MAC1_2_SW_P5;
+
+		if (!(enabled & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5)))
+			enabled |= ESC_OPT_ILLEGAL;
+	}
+
+	*ethConfig = enabled;
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvCtrlMppRegGet - return reg address of mpp group
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       mppGroup - MPP group.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_U32 - Register address.
+*
+*******************************************************************************/
+MV_U32 mvCtrlMppRegGet(MV_U32 mppGroup)
+{
+	MV_U32 ret;
+
+	if (mppGroup >= MV_65XX_MPP_MAX_GROUP)
+		mppGroup = 0;
+
+	ret = MPP_CONTROL_REG(mppGroup);
+
+	return ret;
+}
+
+#if defined(MV_INCLUDE_PEX)
+/*******************************************************************************
+* mvCtrlPexMaxIfGet - Get Marvell controller number of PEX interfaces.
+*
+* DESCRIPTION:
+*       This function returns Marvell controller number of PEX interfaces.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Marvell controller number of PEX interfaces. If controller
+*		ID is undefined the function returns '0'.
+*
+*******************************************************************************/
+MV_U32 mvCtrlPexMaxIfGet(MV_VOID)
+{
+	MV_U32 devId;
+
+	devId = mvCtrlModelGet();
+
+	switch (devId) {
+	case MV_6510_DEV_ID:
+		return MV_PEX_MAX_IF_6510;
+		break;
+	case MV_6601_DEV_ID:
+			return 0;
+	default:
+		return MV_PEX_MAX_IF;
+		break;
+	}
+}
+#endif
+
+/*******************************************************************************
+* mvCtrlEthMaxPortGet - Get Marvell controller number of etherent ports.
+*
+* DESCRIPTION:
+*       This function returns Marvell controller number of etherent port.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Marvell controller number of etherent port.
+*
+*******************************************************************************/
+MV_U32 mvCtrlEthMaxPortGet(MV_VOID)
+{
+	MV_U32 res = 0;
+
+	res = MV_ETH_MAX_PORTS;
+	return res;
+}
+
+/*******************************************************************************
+* mvCtrlEthMaxCPUsGet - Get Marvell controller number of CPUs.
+*
+* DESCRIPTION:
+*       This function returns Marvell controller number of CPUs.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Marvell controller number of CPUs.
+*
+*******************************************************************************/
+MV_U8 mvCtrlEthMaxCPUsGet(MV_VOID)
+{
+	return 1;
+}
+
+#if defined(MV_INCLUDE_SATA)
+/*******************************************************************************
+* mvCtrlSataMaxPortGet - Get Marvell controller number of Sata ports.
+*
+* DESCRIPTION:
+*       This function returns Marvell controller number of Sata ports.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Marvell controller number of Sata ports.
+*
+*******************************************************************************/
+MV_U32 mvCtrlSataMaxPortGet(MV_VOID)
+{
+	MV_U32 devId;
+	MV_U32 res = 0;
+
+	devId = mvCtrlModelGet();
+
+	switch (devId) {
+	case MV_6510_DEV_ID:
+	case MV_6530_DEV_ID:
+		res = MV_SATA_6510_6530_MAX_CHAN;
+		break;
+	case MV_6550_DEV_ID:
+	case MV_6560_DEV_ID:
+		res = MV_SATA_6550_6560_MAX_CHAN;
+		break;
+	case MV_6601_DEV_ID:
+		res=0;
+		break;
+	}
+	return res;
+}
+#endif
+
+#if defined(MV_INCLUDE_XOR)
+/*******************************************************************************
+* mvCtrlXorMaxChanGet - Get Marvell controller number of XOR channels.
+*
+* DESCRIPTION:
+*       This function returns Marvell controller number of XOR channels.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Marvell controller number of XOR channels.
+*
+*******************************************************************************/
+MV_U32 mvCtrlXorMaxChanGet(MV_VOID)
+{
+	MV_U32 devId;
+	MV_U32 res = 0;
+
+	devId = mvCtrlModelGet();
+
+	switch (devId) {
+	case MV_6510_DEV_ID:
+	case MV_6530_DEV_ID:
+		res = MV_XOR_6510_6530_MAX_CHAN;
+		break;
+	case MV_6601_DEV_ID:
+		res=0;
+		break;
+	default:
+		res = MV_XOR_MAX_CHAN;
+		break;
+	}
+	return res;
+}
+
+/*******************************************************************************
+* mvCtrlXorMaxUnitGet - Get Marvell controller number of XOR units.
+*
+* DESCRIPTION:
+*       This function returns Marvell controller number of XOR units.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Marvell controller number of XOR units.
+*
+*******************************************************************************/
+MV_U32 mvCtrlXorMaxUnitGet(MV_VOID)
+{
+	MV_U32 devId;
+	MV_U32 res = 0;
+
+	devId = mvCtrlModelGet();
+
+	switch (devId) {
+	case MV_6510_DEV_ID:
+	case MV_6530_DEV_ID:
+		res = MV_XOR_6510_6530_MAX_UNIT;
+		break;
+	case MV_6601_DEV_ID:
+		break; /* alredy init res = 0; */
+	default:
+		res = MV_XOR_MAX_UNIT;
+		break;
+	}
+	return res;
+}
+
+#endif
+
+#if defined(MV_INCLUDE_USB)
+/*******************************************************************************
+* mvCtrlUsbHostMaxGet - Get number of Marvell Usb  controllers
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       returns number of Marvell USB  controllers.
+*
+*******************************************************************************/
+MV_U32 mvCtrlUsbMaxGet(void)
+{
+	MV_U32 devId;
+	MV_U32 res = 0;
+
+	devId = mvCtrlModelGet();
+
+	switch (devId) {
+	case MV_6510_DEV_ID:
+	case MV_6530_DEV_ID:
+		res = MV_USB_6510_6530_MAX_PORTS;
+		break;
+	case MV_6601_DEV_ID:
+		res=0;
+		break;
+	default:
+		res = MV_USB_MAX_PORTS;
+		break;
+	}
+
+	return res;
+}
+#endif
+
+#if defined(MV_INCLUDE_LEGACY_NAND)
+/*******************************************************************************
+* mvCtrlNandSupport - Return if this controller has integrated NAND flash support
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if NAND is supported and MV_FALSE otherwise
+*
+*******************************************************************************/
+MV_U32 mvCtrlNandSupport(MV_VOID)
+{
+	return MV_65XX_NAND;
+}
+#endif
+
+#if defined(MV_INCLUDE_SDIO)
+/*******************************************************************************
+* mvCtrlSdioSupport - Return if this controller has integrated SDIO flash support
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if SDIO is supported and MV_FALSE otherwise
+*
+*******************************************************************************/
+MV_U32 mvCtrlSdioSupport(MV_VOID)
+{
+	MV_U32 devId;
+	MV_U32 res = 0;
+
+	devId = mvCtrlModelGet();
+
+	switch (devId) {
+	case MV_6510_DEV_ID:
+	case MV_6530_DEV_ID:
+		res = MV_6510_6530_SDIO;
+		break;
+	case MV_6550_DEV_ID:
+	case MV_6560_DEV_ID:
+		res = MV_6550_6560_SDIO;
+		break;
+	case MV_6601_DEV_ID:
+		res=0;
+		break;
+	}
+	return res;
+}
+#endif
+
+#if defined(MV_INCLUDE_TS)
+/*******************************************************************************
+* mvCtrlTsSupport - Return if this controller has integrated TS flash support
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if TS is supported and MV_FALSE otherwise
+*
+*******************************************************************************/
+MV_U32 mvCtrlTsSupport(MV_VOID)
+{
+	return MV_65XX_TS;
+}
+#endif
+
+#if defined(MV_INCLUDE_TDM)
+/*******************************************************************************
+* mvCtrlTdmClkCtrlSet - Set TDM Clock Out Divider Control register
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvCtrlTdmClkCtrlConfig(MV_VOID)
+{
+	MV_U32 clkReg, pcmClkFreq;
+#if defined(MV_TDM_USE_DCO)
+
+#if defined(MV_TDM_PCM_CLK_8MHZ)
+	pcmClkFreq = DCO_CLK_DIV_RATIO_8M;
+#elif defined(MV_TDM_PCM_CLK_4MHZ)
+	pcmClkFreq = DCO_CLK_DIV_RATIO_4M;
+#elif defined(MV_TDM_PCM_CLK_2MHZ)
+	pcmClkFreq = DCO_CLK_DIV_RATIO_2M;
+#else
+	pcmClkFreq = 0x0;
+#endif
+
+	/* Set DCO as source for PCLK */
+	DB(mvOsPrintf("TDM pclk will be sourced from DCO-PLL IR[%x]=[%x]\n",TDM_PON_CLK_OUT_DIV_CONTROL_REG, MV_REG_READ(TDM_PON_CLK_OUT_DIV_CONTROL_REG));)
+
+	clkReg = MV_REG_READ(TDM_PON_CLK_OUT_DIV_CONTROL_REG);
+	MV_REG_WRITE(TDM_PON_CLK_OUT_DIV_CONTROL_REG,
+		     clkReg | ((clkReg & TDM_CLK_SRC_SEL_MASK) | TDM_CLK_SRC_SEL_MASK));
+	mvOsUDelay(1);
+
+	/* Reload new DCO source ratio */
+	clkReg = MV_REG_READ(CORE_DIVCLK_CTRL_REG);
+	MV_REG_WRITE(CORE_DIVCLK_CTRL_REG,
+		     MV_BIT_CLEAR(clkReg, DCO_CLK_DIV_MOD_OFFS));
+	mvOsUDelay(1);
+
+	clkReg = MV_REG_READ(CORE_DIVCLK_CTRL_REG);
+	MV_REG_WRITE(CORE_DIVCLK_CTRL_REG,
+		     MV_BIT_SET(clkReg, DCO_CLK_DIV_MOD_OFFS));
+	mvOsUDelay(1);
+
+	clkReg = MV_REG_READ(CORE_DIVCLK_CTRL_REG);
+	MV_REG_WRITE(CORE_DIVCLK_CTRL_REG,
+		     MV_BIT_CLEAR(clkReg, DCO_CLK_DIV_MOD_OFFS));
+	mvOsUDelay(1);
+
+	clkReg = MV_REG_READ(CORE_DIVCLK_CTRL_REG);
+	MV_REG_WRITE(CORE_DIVCLK_CTRL_REG,
+		     MV_BIT_SET(clkReg, DCO_CLK_DIV_RESET_OFFS));
+	mvOsUDelay(1);
+
+	/* Set DCO correction to 0PPM */
+	clkReg = MV_REG_READ(DCO_MOD_CTRL_REG);
+	MV_REG_WRITE(DCO_MOD_CTRL_REG,
+		     (clkReg & ~DCO_MOD_CTRL_MASK) | DCO_MOD_CTRL_BASE_VAL);
+	mvOsUDelay(1);
+
+	/* Set DCO source ratio */
+	clkReg = MV_REG_READ(CORE_DIVCLK_CTRL_REG);
+	MV_REG_WRITE(CORE_DIVCLK_CTRL_REG,
+		     (clkReg & ~DCO_CLK_DIV_RATIO_MASK) | pcmClkFreq);
+	mvOsUDelay(1);
+
+	DB(mvOsPrintf("TDM pclk now sourced from DCO-PLL IR[%x]=[%x]\n",TDM_PON_CLK_OUT_DIV_CONTROL_REG, MV_REG_READ(TDM_PON_CLK_OUT_DIV_CONTROL_REG));)
+#else /* MV_TDM_USE_DCO */
+
+	DB(mvOsPrintf("TDM pclk will be sourced from PLL IR[%x]=[%x]\n",TDM_PON_CLK_OUT_DIV_CONTROL_REG, MV_REG_READ(TDM_PON_CLK_OUT_DIV_CONTROL_REG));)
+#if defined(MV_TDM_PCM_CLK_8MHZ)
+	pcmClkFreq = TDM_CLK_DIV_RATIO_8M;
+#elif defined(MV_TDM_PCM_CLK_4MHZ)
+	pcmClkFreq = TDM_CLK_DIV_RATIO_4M;
+#elif defined(MV_TDM_PCM_CLK_2MHZ)
+	pcmClkFreq = TDM_CLK_DIV_RATIO_2M;
+#else
+	pcmClkFreq = 0x0;
+#endif
+	clkReg = MV_REG_READ(TDM_PON_CLK_OUT_DIV_CONTROL_REG);
+	clkReg = clkReg & ~(TDM_CLK_DIV_RATIO_MASK | TDM_CLK_SRC_SEL_MASK);
+	MV_REG_WRITE(TDM_PON_CLK_OUT_DIV_CONTROL_REG,
+		     (clkReg | pcmClkFreq | TDM_LOAD_RATIO_MASK | PLL_MODE));
+	mvOsUDelay(1);
+	MV_REG_WRITE(TDM_PON_CLK_OUT_DIV_CONTROL_REG, (clkReg | pcmClkFreq | PLL_MODE));
+
+	DB(mvOsPrintf("TDM pclk now sourced from PLL IR[%x]=[%x]\n",TDM_PON_CLK_OUT_DIV_CONTROL_REG, MV_REG_READ(TDM_PON_CLK_OUT_DIV_CONTROL_REG));)
+#endif /* MV_TDM_USE_DCO */
+}
+
+#if defined(MV_TDM_USE_DCO)
+/*******************************************************************************
+* mvCtrlTdmClkCtrlGet - Get DCO correction ratio
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_32 mvCtrlTdmClkCtrlGet(MV_VOID)
+{
+	/* Get DCO correction */
+	return ((((MV_REG_READ(DCO_MOD_CTRL_REG)) & DCO_MOD_CTRL_MASK) >> DCO_MOD_CTRL_OFFS) - DCO_MOD_CTRL_BASE);
+}
+
+/*******************************************************************************
+* mvCtrlTdmClkCtrlSet - Set DCO correction ratio
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Current DCO correction.
+*
+*******************************************************************************/
+MV_VOID mvCtrlTdmClkCtrlSet(MV_32 correction)
+{
+	/* Set DCO correction to correction * 1PPM */
+	MV_REG_WRITE(DCO_MOD_CTRL_REG,
+		     ((MV_REG_READ(DCO_MOD_CTRL_REG) & ~DCO_MOD_CTRL_MASK) |
+		     (((DCO_MOD_CTRL_BASE_VAL >> DCO_MOD_CTRL_OFFS) + correction) << DCO_MOD_CTRL_OFFS)));
+}
+#endif /* MV_TDM_USE_DCO */
+
+#if defined(MV_INCLUDE_CESA)
+/*******************************************************************************
+* mvCtrlCesaDivClkConfig - Config clock divider ratio from PLL frequency to
+* 			   Tunit zclk.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID mvCtrlCesaDivClkConfig(MV_VOID)
+{
+	MV_U32 miscPLLCtrlReg, coreDivClkCtrlReg;
+
+	/* KW2/A0 and up */
+	if (((mvCtrlRevGet() < 2) && ((MV_65XX_DEV_ID == (mvCtrlModelGet() & 0xff00)))) ||
+		(MV_6601_DEV_ID == mvCtrlModelGet()))
+		return;
+
+	/* 1 */
+	miscPLLCtrlReg = MV_REG_READ(MISC_PLL_CTRL_REG);
+	miscPLLCtrlReg |= 0x1f;
+	MV_REG_WRITE(MISC_PLL_CTRL_REG, miscPLLCtrlReg);
+
+	/* 2 */
+	miscPLLCtrlReg &= ~MISC_APLL_DIV_RELOAD_EN_MASK;
+	miscPLLCtrlReg |= (2 << MISC_APLL_DIV_RELOAD_EN_OFFS);
+	MV_REG_WRITE(MISC_PLL_CTRL_REG, miscPLLCtrlReg);
+
+	/* 3 */
+	coreDivClkCtrlReg = MV_REG_READ(CORE_DIVCLK_CTRL_REG);
+	coreDivClkCtrlReg &= ~MISC_CORE_APLL_CLKDIV_RATIO_MASK;
+	coreDivClkCtrlReg |= CORE_DIVCLK_400MHZ;
+	MV_REG_WRITE(CORE_DIVCLK_CTRL_REG, coreDivClkCtrlReg);
+
+	/* 4 */
+	MV_REG_BIT_SET(MISC_PLL_CTRL_REG, MISC_APLL_DIV_RELOAD_CMD_MASK);
+
+	/* 5 */
+	mvOsUDelay(1);
+
+	/* 6 */
+	MV_REG_BIT_RESET(MISC_PLL_CTRL_REG, MISC_APLL_DIV_RELOAD_CMD_MASK);
+
+	/* 7 */
+	miscPLLCtrlReg |= (0x1f << MISC_APLL_DIV_RELOAD_EN_OFFS);
+	MV_REG_WRITE(MISC_PLL_CTRL_REG, miscPLLCtrlReg);
+
+	/* 8 */
+	mvOsUDelay(10);
+
+	/* 9 */
+	miscPLLCtrlReg = MV_REG_READ(MISC_PLL_CTRL_REG);
+	miscPLLCtrlReg &= ~MISC_APLL_N_RESET_MASK_MASK;
+	MV_REG_WRITE(MISC_PLL_CTRL_REG, miscPLLCtrlReg);
+}
+#endif
+
+/*******************************************************************************
+* mvCtrlTdmSupport - Return if this controller has integrated TDM flash support
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if TDM is supported and MV_FALSE otherwise
+*
+*******************************************************************************/
+MV_U32 mvCtrlTdmSupport(MV_VOID)
+{
+	return MV_65XX_TDM;
+}
+
+/*******************************************************************************
+* mvCtrlTdmMaxGet - Return the maximum number of TDM ports.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       The number of TDM ports in device.
+*
+*******************************************************************************/
+MV_U32 mvCtrlTdmMaxGet(MV_VOID)
+{
+	MV_U32 devId;
+	MV_U32 res = 0;
+
+	devId = mvCtrlModelGet();
+
+	switch (devId) {
+	case MV_6510_DEV_ID:
+		res = MV_6510_TDM_MAX_PORTS;
+		break;
+	case MV_6530_DEV_ID:
+		res = MV_6530_TDM_MAX_PORTS;
+		break;
+	case MV_6550_DEV_ID:
+		res = MV_6550_TDM_MAX_PORTS;
+		break;
+	case MV_6560_DEV_ID:
+		res = MV_6560_TDM_MAX_PORTS;
+		break;
+	case MV_6601_DEV_ID:
+		res = MV_6601_TDM_MAX_PORTS;
+		break;
+	}
+	return res;
+}
+
+/*******************************************************************************
+* mvCtrlTdmTypeGet
+*
+* DESCRIPTION:
+*	Return the TDM unit type being compiled in.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	The TDM unit type.
+*
+*******************************************************************************/
+MV_UNIT_ID mvCtrlTdmUnitTypeGet(MV_VOID)
+{
+#ifdef MV_TDM_SUPPORT
+	return TDM_2CH_UNIT_ID;
+#else
+	return TDM_32CH_UNIT_ID;
+#endif
+}
+
+/*******************************************************************************
+* mvCtrlTdmUnitIrqGet
+*
+* DESCRIPTION:
+*	Return the TDM unit IRQ number depending on the TDM unit compilation
+*	options.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	None.
+******************************************************************************/
+MV_U32 mvCtrlTdmUnitIrqGet(MV_VOID)
+{
+#ifdef MV_TDM_SUPPORT
+	return MV_TDM_2CH_IRQ_NUM;
+#else
+	return MV_TDM_IRQ_NUM;
+#endif
+}
+
+#endif
+
+/*******************************************************************************
+* mvCtrlModelGet - Get Marvell controller device model (Id)
+*
+* DESCRIPTION:
+*       This function returns 16bit describing the device model (ID) as defined
+*       in PCI Device and Vendor ID configuration register offset 0x0.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       16bit desscribing Marvell controller ID
+*
+*******************************************************************************/
+MV_U16 mvCtrlModelGet(MV_VOID)
+{
+	MV_U32 devId, reg;
+	MV_U16 model = 0;
+
+	/* for device 6601 read device id from reg (PEX not supported) */
+	devId = MV_REG_READ(DEVICE_VENDOR_ID_REG);
+	if (devId == 0) {
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+		/* Check pex power state */
+		reg = MV_REG_READ(POWER_MNG_CTRL_REG) & PMC_PEXSTOPCLOCK_MASK(0);
+		if (reg == PMC_PEXSTOPCLOCK_STOP(0))
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK(0));
+#endif
+		devId = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0, PEX_DEVICE_AND_VENDOR_ID));
+
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+		/* Return to power off state */
+		if (reg  == PMC_PEXSTOPCLOCK_STOP(0))
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK(0));
+#endif
+	}
+
+	model = (MV_U16) ((devId >> 16) & 0xFFFF);
+	return model;
+}
+
+/*******************************************************************************
+* mvCtrlRevGet - Get Marvell controller device revision number
+*
+* DESCRIPTION:
+*       This function returns 8bit describing the device revision as defined
+*       in PCI Express Class Code and Revision ID Register.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       8bit desscribing Marvell controller revision number
+*
+*******************************************************************************/
+MV_U8 mvCtrlRevGet(MV_VOID)
+{
+	MV_U8 revNum;
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+	MV_U32 pexPower;
+#endif
+
+	/* for device 6601 read device id from reg (PEX not supported) */
+    if (MV_6601_DEV_ID == mvCtrlModelGet())
+    {
+	    MV_U32 temp;
+	    temp = (CBR_VERION_ID_MASK & MV_REG_READ(CHIP_BOND_REG));
+	    revNum = (MV_U8)(temp >> CBR_VERION_ID_OFFS) ;
+	    return revNum;  /* MV_6601_A0_REV; */
+    }
+
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+	/* Check pex power state */
+	pexPower = mvCtrlPwrClckGet(PEX_UNIT_ID, 0);
+	if (pexPower == MV_FALSE)
+		mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_TRUE);
+#endif
+	revNum = (MV_U8) MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0, PCI_CLASS_CODE_AND_REVISION_ID));
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+	/* Return to power off state */
+	if (pexPower == MV_FALSE)
+		mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_FALSE);
+#endif
+	return ((revNum & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS);
+}
+
+/*******************************************************************************
+* mvCtrlNameGet - Get Marvell controller name
+*
+* DESCRIPTION:
+*       This function returns a string describing the device model and revision.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       pNameBuff - Buffer to contain device name string. Minimum size 30 chars.
+*
+* RETURN:
+*
+*       MV_ERROR if informantion can not be read.
+*******************************************************************************/
+MV_STATUS mvCtrlNameGet(char *pNameBuff)
+{
+	mvOsSPrintf(pNameBuff, "%s%x Rev %d", SOC_NAME_PREFIX, mvCtrlModelGet(), mvCtrlRevGet());
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCtrlModelRevGet - Get Controller Model (Device ID) and Revision
+*
+* DESCRIPTION:
+*       This function returns 32bit value describing both Device ID and Revision
+*       as defined in PCI Express Device and Vendor ID Register and device revision
+*	    as defined in PCI Express Class Code and Revision ID Register.
+
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit describing both controller device ID and revision number
+*
+*******************************************************************************/
+MV_U32 mvCtrlModelRevGet(MV_VOID)
+{
+	return ((mvCtrlModelGet() << 16) | mvCtrlRevGet());
+}
+
+/*******************************************************************************
+* mvCtrlModelRevNameGet - Get Marvell controller name
+*
+* DESCRIPTION:
+*       This function returns a string describing the device model and revision.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       pNameBuff - Buffer to contain device name string. Minimum size 30 chars.
+*
+* RETURN:
+*
+*       MV_ERROR if informantion can not be read.
+*******************************************************************************/
+MV_STATUS mvCtrlModelRevNameGet(char *pNameBuff)
+{
+	switch (mvCtrlModelRevGet()) {
+	case MV_6510_Z2_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6510_Z2_NAME);
+		break;
+	case MV_6530_Z2_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6530_Z2_NAME);
+		break;
+	case MV_6550_Z2_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6550_Z2_NAME);
+		break;
+	case MV_6560_Z2_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6560_Z2_NAME);
+		break;
+	case MV_6510_A0_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6510_A0_NAME);
+		break;
+	case MV_6530_A0_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6530_A0_NAME);
+		break;
+	case MV_6550_A0_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6550_A0_NAME);
+		break;
+	case MV_6560_A0_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6560_A0_NAME);
+		break;
+	case MV_6601_A0_ID:
+		mvOsSPrintf(pNameBuff, "%s", MV_6601_A0_NAME);
+		break;
+
+	default:
+		mvCtrlNameGet(pNameBuff);
+		break;
+	}
+
+	return MV_OK;
+}
+
+static const char *cntrlName[] = TARGETS_NAME_ARRAY;
+
+/*******************************************************************************
+* mvCtrlTargetNameGet - Get Marvell controller target name
+*
+* DESCRIPTION:
+*       This function convert the trget enumeration to string.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Target name (const MV_8 *)
+*******************************************************************************/
+const MV_8 *mvCtrlTargetNameGet(MV_TARGET target)
+{
+	if (target >= MAX_TARGETS)
+		return "target unknown";
+
+	return cntrlName[target];
+}
+
+/*******************************************************************************
+* mvCtrlPexAddrDecShow - Print the PEX address decode map (BARs and windows).
+*
+* DESCRIPTION:
+*		This function print the PEX address decode map (BARs and windows).
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID mvCtrlPexAddrDecShow(MV_VOID)
+{
+	MV_PEX_BAR pexBar;
+	MV_PEX_DEC_WIN win;
+	MV_U32 pexIf;
+	MV_U32 bar, winNum;
+
+	for (pexIf = 0; pexIf < mvCtrlPexMaxIfGet(); pexIf++) {
+		if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf))
+			continue;
+		mvOsOutput("\n");
+		mvOsOutput("PEX%d:\n", pexIf);
+		mvOsOutput("-----\n");
+
+		mvOsOutput("\nPex Bars \n\n");
+
+		for (bar = 0; bar < PEX_MAX_BARS; bar++) {
+			memset(&pexBar, 0, sizeof(MV_PEX_BAR));
+
+			mvOsOutput("%s ", pexBarNameGet(bar));
+
+			if (mvPexBarGet(pexIf, bar, &pexBar) == MV_OK) {
+				if (pexBar.enable) {
+					mvOsOutput("base %08x, ", pexBar.addrWin.baseLow);
+					mvSizePrint(pexBar.addrWin.size);
+					mvOsOutput("\n");
+				} else
+					mvOsOutput("disable\n");
+			}
+		}
+		mvOsOutput("\nPex Decode Windows\n\n");
+
+		for (winNum = 0; winNum < PEX_MAX_TARGET_WIN - 2; winNum++) {
+			memset(&win, 0, sizeof(MV_PEX_DEC_WIN));
+
+			mvOsOutput("win%d - ", winNum);
+
+			if (mvPexTargetWinRead(pexIf, winNum, &win) == MV_OK) {
+				if (win.winInfo.enable) {
+					mvOsOutput("%s base %08x, ",
+						   mvCtrlTargetNameGet(mvCtrlTargetByWinInfoGet(&win.winInfo)),
+						   win.winInfo.addrWin.baseLow);
+					mvOsOutput("....");
+					mvSizePrint(win.winInfo.addrWin.size);
+
+					mvOsOutput("\n");
+				} else
+					mvOsOutput("disable\n");
+			}
+		}
+
+		memset(&win, 0, sizeof(MV_PEX_DEC_WIN));
+
+		mvOsOutput("default win - ");
+
+		if (mvPexTargetWinRead(pexIf, MV_PEX_WIN_DEFAULT, &win) == MV_OK) {
+			mvOsOutput("%s ", mvCtrlTargetNameGet(win.target));
+			mvOsOutput("\n");
+		}
+		memset(&win, 0, sizeof(MV_PEX_DEC_WIN));
+
+		mvOsOutput("Expansion ROM - ");
+
+		if (mvPexTargetWinRead(pexIf, MV_PEX_WIN_EXP_ROM, &win) == MV_OK) {
+			mvOsOutput("%s ", mvCtrlTargetNameGet(win.target));
+			mvOsOutput("\n");
+		}
+	}
+}
+
+/*******************************************************************************
+* mvUnitAddrDecShow - Print the Unit's address decode map.
+*
+* DESCRIPTION:
+*       This is a generic function for printing the different unit's address
+*	decode map.
+*
+* INPUT:
+*       unit	- The unit to print the address decode for.
+*	name	- The unit's name.
+*	winGetFuncPtr - A pointer to the HAL's window get function.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static void mvUnitAddrDecShow(MV_U8 numUnits, MV_UNIT_ID unitId, const char *name, MV_WIN_GET_FUNC_PTR winGetFuncPtr)
+{
+	MV_UNIT_WIN_INFO win;
+	MV_U32 unit, i;
+
+	for (unit = 0; unit < numUnits; unit++) {
+
+		if (MV_FALSE == mvCtrlPwrClckGet(unitId, unit))
+			continue;
+		mvOsOutput("\n");
+		mvOsOutput("%s %d:\n", name, unit);
+		mvOsOutput("----\n");
+
+		for (i = 0; i < 16; i++) {
+			memset(&win, 0, sizeof(MV_UNIT_WIN_INFO));
+
+			mvOsOutput("win%d - ", i);
+
+			if (winGetFuncPtr(unit, i, &win) == MV_OK) {
+				if (win.enable) {
+					mvOsOutput("%s base %08x, ",
+						   mvCtrlTargetNameGet(mvCtrlTargetByWinInfoGet(&win)),
+						   win.addrWin.baseLow);
+					mvOsOutput("....");
+					mvSizePrint(win.addrWin.size);
+					mvOsOutput("\n");
+				} else
+					mvOsOutput("disable\n");
+			}
+		}
+	}
+	return;
+}
+
+/*******************************************************************************
+* mvCtrlAddrDecShow - Print the Controller units address decode map.
+*
+* DESCRIPTION:
+*		This function the Controller units address decode map.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvCtrlAddrDecShow(MV_VOID)
+{
+	mvCpuIfAddDecShow();
+	mvAhbToMbusAddDecShow();
+#if defined(MV_INCLUDE_PEX)
+	mvCtrlPexAddrDecShow();
+#endif
+#if defined(MV_INCLUDE_USB)
+	mvUnitAddrDecShow(mvCtrlUsbMaxGet(), USB_UNIT_ID, "USB", mvUsbWinRead);
+#endif
+
+#if defined(MV_INCLUDE_GIG_ETH)
+#if defined(CONFIG_MV_ETH_LEGACY)
+	mvUnitAddrDecShow(mvCtrlEthMaxPortGet(), ETH_GIG_UNIT_ID, "ETH", mvEthWinRead);
+#else
+	mvUnitAddrDecShow(mvCtrlEthMaxPortGet(), ETH_GIG_UNIT_ID, "ETH", mvNetaWinRead);
+#endif /* CONFIG_MV_ETH_LEGACY */
+#endif /* MV_INCLUDE_GIG_ETH */
+
+#if defined(MV_INCLUDE_XOR)
+	mvUnitAddrDecShow(mvCtrlXorMaxChanGet(), XOR_UNIT_ID, "XOR", mvXorTargetWinRead);
+#endif
+#if defined(MV_INCLUDE_SATA)
+	mvUnitAddrDecShow(mvCtrlSataMaxPortGet(), SATA_UNIT_ID, "Sata", mvSataWinRead);
+#endif
+#if defined(MV_INCLUDE_TS)
+	mvUnitAddrDecShow(1, TS_UNIT_ID, "TS", mvTsuWinRead);
+#endif
+}
+
+/*******************************************************************************
+* ctrlSizeToReg - Extract size value for register assignment.
+*
+* DESCRIPTION:
+*       Address decode size parameter must be programed from LSB to MSB as
+*       sequence of 1's followed by sequence of 0's. The number of 1's
+*       specifies the size of the window in 64 KB granularity (e.g. a
+*       value of 0x00ff specifies 256x64k = 16 MB).
+*       This function extract the size value from the size parameter according
+*		to given aligment paramter. For example for size 0x1000000 (16MB) and
+*		aligment 0x10000 (64KB) the function will return 0x00FF.
+*
+* INPUT:
+*       size - Size.
+*		alignment - Size alignment.	Note that alignment must be power of 2!
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit describing size register value correspond to size parameter.
+*		If value is '-1' size parameter or aligment are invalid.
+*******************************************************************************/
+MV_U32 ctrlSizeToReg(MV_U32 size, MV_U32 alignment)
+{
+	MV_U32 retVal;
+
+	/* Check size parameter alignment               */
+	if ((0 == size) || (MV_IS_NOT_ALIGN(size, alignment))) {
+		DB(mvOsPrintf("ctrlSizeToReg: ERR. Size is zero or not aligned.\n"));
+		return -1;
+	}
+
+	/* Take out the "alignment" portion out of the size parameter */
+	alignment--;		/* Now the alignmet is a sequance of '1' (e.g. 0xffff)          */
+	/* and size is 0x1000000 (16MB) for example     */
+	while (alignment & 1) {	/* Check that alignmet LSB is set       */
+		size = (size >> 1);	/* If LSB is set, move 'size' one bit to right      */
+		alignment = (alignment >> 1);
+	}
+
+	/* If after the alignment first '0' was met we still have '1' in                */
+	/* it then aligment is invalid (not power of 2)                                 */
+	if (alignment) {
+		DB(mvOsPrintf("ctrlSizeToReg: ERR. Alignment parameter 0x%x invalid.\n", (MV_U32) alignment));
+		return -1;
+	}
+
+	/* Now the size is shifted right according to aligment: 0x0100                  */
+	size--;			/* Now the size is a sequance of '1': 0x00ff                    */
+	retVal = size;
+
+	/* Check that LSB to MSB is sequence of 1's followed by sequence of 0's         */
+	while (size & 1)	/* Check that LSB is set    */
+		size = (size >> 1);	/* If LSB is set, move one bit to the right         */
+
+	if (size) {		/* Sequance of 1's is over. Check that we have no other 1's         */
+		DB(mvOsPrintf("ctrlSizeToReg: ERR. Size parameter 0x%x invalid.\n", size));
+		return -1;
+	}
+	return retVal;
+}
+
+/*******************************************************************************
+* ctrlRegToSize - Extract size value from register value.
+*
+* DESCRIPTION:
+*       This function extract a size value from the register size parameter
+*		according to given aligment paramter. For example for register size
+*		value 0xff and aligment 0x10000 the function will return 0x01000000.
+*
+* INPUT:
+*       regSize   - Size as in register format.	See ctrlSizeToReg.
+*		alignment - Size alignment.	Note that alignment must be power of 2!
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit describing size.
+*		If value is '-1' size parameter or aligment are invalid.
+*******************************************************************************/
+MV_U32 ctrlRegToSize(MV_U32 regSize, MV_U32 alignment)
+{
+	MV_U32 temp;
+
+	/* Check that LSB to MSB is sequence of 1's followed by sequence of 0's         */
+	temp = regSize;		/* Now the size is a sequance of '1': 0x00ff            */
+
+	while (temp & 1)	/* Check that LSB is set                                    */
+		temp = (temp >> 1);	/* If LSB is set, move one bit to the right         */
+
+	if (temp) {		/* Sequance of 1's is over. Check that we have no other 1's         */
+		DB(mvOsPrintf("ctrlRegToSize: ERR. Size parameter 0x%x invalid.\n", regSize));
+		return -1;
+	}
+
+	/* Check that aligment is a power of two                                        */
+	temp = alignment - 1;	/* Now the alignmet is a sequance of '1' (0xffff)          */
+
+	while (temp & 1)	/* Check that alignmet LSB is set                           */
+		temp = (temp >> 1);	/* If LSB is set, move 'size' one bit to right      */
+
+	/* If after the 'temp' first '0' was met we still have '1' in 'temp'            */
+	/* then 'temp' is invalid (not power of 2)                                      */
+	if (temp) {
+		DB(mvOsPrintf("ctrlSizeToReg: ERR. Alignment parameter 0x%x invalid.\n", alignment));
+		return -1;
+	}
+
+	regSize++;		/* Now the size is 0x0100                                       */
+
+	/* Add in the "alignment" portion to the register size parameter                */
+	alignment--;		/* Now the alignmet is a sequance of '1' (e.g. 0xffff)          */
+
+	while (alignment & 1) {	/* Check that alignmet LSB is set                       */
+		regSize = (regSize << 1);	/* LSB is set, move 'size' one bit left     */
+		alignment = (alignment >> 1);
+	}
+
+	return regSize;
+}
+
+/*******************************************************************************
+* ctrlSizeRegRoundUp - Round up given size
+*
+* DESCRIPTION:
+*       This function round up a given size to a size that fits the
+*       restrictions of size format given an aligment parameter.
+*		to given aligment paramter. For example for size parameter 0xa1000 and
+*		aligment 0x1000 the function will return 0xFF000.
+*
+* INPUT:
+*       size - Size.
+*		alignment - Size alignment.	Note that alignment must be power of 2!
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit describing size value correspond to size in register.
+*******************************************************************************/
+MV_U32 ctrlSizeRegRoundUp(MV_U32 size, MV_U32 alignment)
+{
+	MV_U32 msbBit = 0;
+	MV_U32 retSize;
+
+	/* Check if size parameter is already comply with restriction   */
+	if (!(-1 == ctrlSizeToReg(size, alignment)))
+		return size;
+
+	while (size) {
+		size = (size >> 1);
+		msbBit++;
+	}
+
+	retSize = (1 << msbBit);
+
+	if (retSize < alignment)
+		return alignment;
+	else
+		return retSize;
+}
+
+/*******************************************************************************
+* mvCtrlIsBootFromSPI
+*
+* DESCRIPTION:
+*       Check if device is configured to boot from SPI flash according to the
+*	SAR registers.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if device boot from SPI.
+*******************************************************************************/
+MV_BOOL mvCtrlIsBootFromSPI(MV_VOID)
+{
+	MV_U32 satr;
+
+	satr = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
+
+	satr = (satr & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS;
+	satr = (1 << satr);
+	if (satr & MSAR_BOOT_SPI_W_BOOTROM_MASK)
+		return MV_TRUE;
+	else
+		return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvCtrlIsBootFromNAND
+*
+* DESCRIPTION:
+*       Check if device is confiogured to boot from NAND flash according to the SAR
+*	registers.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if device boot from NAND.
+*******************************************************************************/
+MV_BOOL mvCtrlIsBootFromNAND(MV_VOID)
+{
+	MV_U32 satr;
+	MV_U32 i;
+	MV_U32 satrList[] = MSAR_BOOT_NAND_W_BOOTROM_LIST;
+	MV_U32 satrListLegacy[] = MSAR_BOOT_NAND_LEG_W_BOOTROM_LIST;
+
+    if (MV_6601_DEV_ID == mvCtrlModelGet())
+		return MV_FALSE;
+
+	
+	satr = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
+
+	satr = (satr & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS;
+	for (i = 0; i < MV_ARRAY_SIZE(satrList); i++) {
+		if (satrList[i] == satr)
+			return MV_TRUE;
+	}
+
+	for (i = 0; i < MV_ARRAY_SIZE(satrListLegacy); i++) {
+		if (satrListLegacy[i] == satr)
+			return MV_TRUE;
+	}
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvCtrlIsBootFromNOR
+*
+* DESCRIPTION:
+*       Check if device is confiogured to boot from NOR flash according to the SAR
+*	registers.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if device is booting from NOR.
+*******************************************************************************/
+MV_BOOL mvCtrlIsBootFromNOR(MV_VOID)
+{
+	MV_U32 satr;
+	MV_U32 i;
+	MV_U32 satrList[] = MSAR_BOOT_NOR_W_BOOTROM_LIST;
+
+    if (MV_6601_DEV_ID == mvCtrlModelGet())
+		return MV_FALSE;
+
+	satr = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
+
+	satr = (satr & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS;
+	for (i = 0; i < MV_ARRAY_SIZE(satrList); i++) {
+		if (satrList[i] == satr) {
+			if ((satr >> 4) == 0x1)
+				return MV_NOR_LOW_MPPS;
+			if ((satr >> 4) == 0x2)
+				return MV_NOR_HIGH_MPPS;
+		}
+	}
+	return MV_FALSE;
+}
+
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+/*******************************************************************************
+* mvCtrlPwrSaveOn - Set Power save mode
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*******************************************************************************/
+MV_VOID mvCtrlPwrSaveOn(MV_VOID)
+{
+	unsigned long old, temp;
+	MV_U32 reg;
+
+	/* Disable int */
+	__asm__ __volatile__("mrs %0, cpsr\n" "orr %1, %0, #0xc0\n" "msr cpsr_c, %1" : "=r"(old), "=r"(temp)
+			     : : "memory");
+
+	MV_REG_BIT_SET(CPU_CTRL_STAT_REG, CCSR_CPU_SW_INT_BLK_MASK);
+
+	reg = MV_REG_READ(POWER_MNG_CTRL_REG);
+
+	if (!(reg & PMC_POWERSAVE_MASK)) {
+		/* Set SoC in power save */
+		MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_POWERSAVE_MASK);
+
+		/* Wait for int */
+		__asm__ __volatile__("mcr    p15, 0, r0, c7, c0, 4");
+	}
+
+	MV_REG_BIT_RESET(CPU_CTRL_STAT_REG, CCSR_CPU_SW_INT_BLK_MASK);
+
+	/* Enabled int */
+	__asm__ __volatile__("msr cpsr_c, %0" : : "r"(old)
+			     : "memory");
+}
+
+
+/*******************************************************************************
+* mvCtrlPwrSaveOff - Go out of power save mode
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*******************************************************************************/
+MV_VOID mvCtrlPwrSaveOff(MV_VOID)
+{
+	unsigned long old, temp;
+	MV_U32 reg;
+
+	/* Disable int */
+	__asm__ __volatile__("mrs %0, cpsr\n" "orr %1, %0, #0xc0\n" "msr cpsr_c, %1" : "=r"(old), "=r"(temp)
+			     : : "memory");
+	MV_REG_BIT_SET(CPU_CTRL_STAT_REG, CCSR_CPU_SW_INT_BLK_MASK);
+
+	reg = MV_REG_READ(POWER_MNG_CTRL_REG);
+
+	if (reg & PMC_POWERSAVE_MASK) {
+		/* Set SoC in power save */
+		MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_POWERSAVE_MASK);
+
+		/* Wait for int */
+		__asm__ __volatile__("mcr    p15, 0, r0, c7, c0, 4");
+	}
+
+	MV_REG_BIT_RESET(CPU_CTRL_STAT_REG, CCSR_CPU_SW_INT_BLK_MASK);
+
+	/* Enabled int */
+	__asm__ __volatile__("msr cpsr_c, %0" : : "r"(old)
+			     : "memory");
+
+}
+
+/*******************************************************************************
+* mvCtrlIsPwrSaveOn - Get current power save state.
+*
+* DESCRIPTION:
+*	Return the current power-save state.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	MV_TRUE if CPU is currently in power-save mode.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_U32 mvCtrlIsPwrSaveOn(MV_VOID)
+{
+	MV_U32 reg;
+
+	reg = MV_REG_READ(POWER_MNG_CTRL_REG);
+	if (reg & PMC_POWERSAVE_MASK)
+		return MV_TRUE;
+	else
+		return MV_FALSE;
+}
+
+
+/*******************************************************************************
+* mvCtrlPwrClckSet - Set Power State for specific Unit
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*******************************************************************************/
+MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable)
+{
+	MV_U32 devId = mvCtrlModelGet();
+
+	if (MV_6601_DEV_ID == devId) {
+		switch (unitId) {
+	#if defined(MV_INCLUDE_GIG_ETH)
+		case ETH_GIG_UNIT_ID:
+			if (enable == MV_FALSE)
+				MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_GESTOPCLOCK_MASK(index));
+			else
+				MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_GESTOPCLOCK_MASK(index));
+			break;
+	#endif
+	#if defined(MV_INCLUDE_TDM)
+		case TDM_2CH_UNIT_ID:
+			if (enable == MV_FALSE)
+				MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_TDMSTOPCLOCK_MASK);
+			else
+				MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_TDMSTOPCLOCK_MASK);
+			break;
+	#endif
+	#if defined(MV_INCLUDE_PON)
+		case XPON_UNIT_ID:
+			if (enable == MV_FALSE)
+				MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_PONSTOPCLOCK_MASK);
+			else
+				MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_PONSTOPCLOCK_MASK);
+			break;
+	#endif
+		case PEX_UNIT_ID:
+		case CESA_UNIT_ID:
+		case SATA_UNIT_ID:
+		case USB_UNIT_ID:
+		case SDIO_UNIT_ID:
+		case NFC_UNIT_ID:
+		case TDM_32CH_UNIT_ID:
+		default:
+			break;       /* return for unsupported units */ 
+		}
+		return;
+	}
+	switch (unitId) {
+#if defined(MV_INCLUDE_PEX)
+	case PEX_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK(index));
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK(index));
+		break;
+#endif
+#if defined(MV_INCLUDE_GIG_ETH)
+	case ETH_GIG_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_GESTOPCLOCK_MASK(index));
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_GESTOPCLOCK_MASK(index));
+		break;
+#endif
+#if defined(MV_INCLUDE_INTEG_SATA)
+	case SATA_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SATASTOPCLOCK_MASK);
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SATASTOPCLOCK_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_CESA)
+	case CESA_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SESTOPCLOCK_MASK);
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SESTOPCLOCK_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_USB)
+	case USB_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_USBSTOPCLOCK_MASK);
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_USBSTOPCLOCK_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_SDIO)
+	case SDIO_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SDIOSTOPCLOCK_MASK);
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SDIOSTOPCLOCK_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_TDM)
+	case TDM_2CH_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_TDMSTOPCLOCK_MASK);
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_TDMSTOPCLOCK_MASK);
+		break;
+	case TDM_32CH_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_COMMSTOPCLOCK_MASK);
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_COMMSTOPCLOCK_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_PON)
+	case XPON_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_PONSTOPCLOCK_MASK);
+		else
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_PONSTOPCLOCK_MASK);
+		break;
+#endif
+	case NFC_UNIT_ID:
+		if (enable == MV_FALSE) {
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_NFCSTOPCLOCK_MASK);
+			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_NFECCSTOPCLOCK_MASK);
+		} else {
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_NFCSTOPCLOCK_MASK);
+			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_NFECCSTOPCLOCK_MASK);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+/*******************************************************************************
+* mvCtrlPwrClckGet - Get Power State of specific Unit
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+******************************************************************************/
+MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index)
+{
+	MV_U32 reg = MV_REG_READ(POWER_MNG_CTRL_REG);
+	MV_BOOL state = MV_TRUE;
+	MV_U32 devId = mvCtrlModelGet();
+	if (MV_6601_DEV_ID == devId)
+	{
+		switch (unitId) {
+		case USB_UNIT_ID:
+		case CESA_UNIT_ID:
+		case SATA_UNIT_ID:
+		case SDIO_UNIT_ID:
+		case NFC_UNIT_ID:
+		case PEX_UNIT_ID:
+		case TDM_32CH_UNIT_ID:
+		case TS_UNIT_ID:
+		case IDMA_UNIT_ID:
+		case XOR_UNIT_ID:
+			state = MV_FALSE;
+			break;
+		case ETH_GIG_UNIT_ID:
+#if defined(MV_INCLUDE_GIG_ETH)
+			if ((reg & PMC_GESTOPCLOCK_MASK(index)) == PMC_GESTOPCLOCK_STOP(index))
+				state = MV_FALSE;
+			else
+				state = MV_TRUE;
+			break;
+#endif
+#if defined(MV_INCLUDE_TDM)
+		case TDM_2CH_UNIT_ID:
+			if ((reg & PMC_TDMSTOPCLOCK_MASK) == PMC_TDMSTOPCLOCK_STOP)
+				state = MV_FALSE;
+			else
+				state = MV_TRUE;
+			break;
+#endif
+#if defined(MV_INCLUDE_PON)
+		case XPON_UNIT_ID:
+			if ((reg & PMC_PONSTOPCLOCK_MASK) == PMC_PONSTOPCLOCK_STOP)
+				state = MV_FALSE;
+			else
+				state = MV_TRUE;
+			break;
+#endif
+		case DRAM_UNIT_ID:
+		case UART_UNIT_ID:
+		case SPI_UNIT_ID:
+		case AUDIO_UNIT_ID:
+		case BM_UNIT_ID:
+		case PNC_UNIT_ID:
+			state = MV_TRUE;
+		break;
+
+		default:
+			state = MV_TRUE;
+			break;
+		}
+		return state;
+	}
+
+	switch (unitId) {
+#if defined(MV_INCLUDE_PEX)
+	case PEX_UNIT_ID:
+		if ((reg & PMC_PEXSTOPCLOCK_MASK(index)) == PMC_PEXSTOPCLOCK_STOP(index))
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_GIG_ETH)
+	case ETH_GIG_UNIT_ID:
+		if ((reg & PMC_GESTOPCLOCK_MASK(index)) == PMC_GESTOPCLOCK_STOP(index))
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_SATA)
+	case SATA_UNIT_ID:
+		if ((reg & PMC_SATASTOPCLOCK_MASK) == PMC_SATASTOPCLOCK_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_CESA)
+	case CESA_UNIT_ID:
+		if ((reg & PMC_SESTOPCLOCK_MASK) == PMC_SESTOPCLOCK_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_USB)
+	case USB_UNIT_ID:
+		if ((reg & PMC_USBSTOPCLOCK_MASK) == PMC_USBSTOPCLOCK_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_SDIO)
+	case SDIO_UNIT_ID:
+		if ((reg & PMC_SDIOSTOPCLOCK_MASK) == PMC_SDIOSTOPCLOCK_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_TDM)
+	case TDM_2CH_UNIT_ID:
+		if ((reg & PMC_TDMSTOPCLOCK_MASK) == PMC_TDMSTOPCLOCK_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+
+	case TDM_32CH_UNIT_ID:
+		if ((reg & PMC_COMMSTOPCLOCK_MASK) == PMC_COMMSTOPCLOCK_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_PON)
+	case XPON_UNIT_ID:
+		if ((reg & PMC_PONSTOPCLOCK_MASK) == PMC_PONSTOPCLOCK_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+	case NFC_UNIT_ID:
+		if ((reg & PMC_NFCSTOPCLOCK_MASK) == PMC_NFCSTOPCLOCK_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+	default:
+		state = MV_TRUE;
+		break;
+	}
+
+	return state;
+}
+
+/*******************************************************************************
+* mvCtrlPwrMemSet - Set Power State for memory on specific Unit
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*******************************************************************************/
+MV_VOID mvCtrlPwrMemSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable)
+{
+	MV_U32 devId = mvCtrlModelGet();
+	if (MV_6601_DEV_ID == devId) {
+
+		switch (unitId) {
+	#if defined(MV_INCLUDE_GIG_ETH)
+		case ETH_GIG_UNIT_ID:
+			if (enable == MV_FALSE)
+				MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_GESTOPMEM_MASK(index));
+			else
+				MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_GESTOPMEM_MASK(index));
+			break;
+	#endif
+	#if defined(MV_INCLUDE_PON)
+		case XPON_UNIT_ID:
+			if (enable == MV_FALSE)
+				MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_PONSTOPMEM_MASK);
+			else
+				MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_PONSTOPMEM_MASK);
+			break;
+	#endif
+	#if defined(MV_INCLUDE_BM)
+		case BM_UNIT_ID:
+			if (enable == MV_FALSE)
+				MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_BMSTOPMEM_MASK);
+			else
+				MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_BMSTOPMEM_MASK);
+			break;
+	#endif
+	#if defined(MV_INCLUDE_PNC)
+		case PNC_UNIT_ID:
+			if (enable == MV_FALSE)
+				MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_PNCSTOPMEM_MASK);
+			else
+				MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_PNCSTOPMEM_MASK);
+			break;
+	#endif
+		case PEX_UNIT_ID:
+		case SATA_UNIT_ID:
+		case CESA_UNIT_ID:
+		case USB_UNIT_ID:
+		case XOR_UNIT_ID:
+		default:
+			break;
+		}
+		return;
+	}
+
+    switch (unitId) {
+#if defined(MV_INCLUDE_PEX)
+	case PEX_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_PEXSTOPMEM_MASK(index));
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_PEXSTOPMEM_MASK(index));
+		break;
+#endif
+#if defined(MV_INCLUDE_GIG_ETH)
+	case ETH_GIG_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_GESTOPMEM_MASK(index));
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_GESTOPMEM_MASK(index));
+		break;
+#endif
+#if defined(MV_INCLUDE_INTEG_SATA)
+	case SATA_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_SATASTOPMEM_MASK);
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_SATASTOPMEM_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_CESA)
+	case CESA_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_SESTOPMEM_MASK);
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_SESTOPMEM_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_USB)
+	case USB_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_USBSTOPMEM_MASK);
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_USBSTOPMEM_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_XOR)
+	case XOR_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_XORSTOPMEM_MASK(index));
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_XORSTOPMEM_MASK(index));
+		break;
+#endif
+#if defined(MV_INCLUDE_PON)
+	case XPON_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_PONSTOPMEM_MASK);
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_PONSTOPMEM_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_BM)
+	case BM_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_BMSTOPMEM_MASK);
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_BMSTOPMEM_MASK);
+		break;
+#endif
+#if defined(MV_INCLUDE_PNC)
+	case PNC_UNIT_ID:
+		if (enable == MV_FALSE)
+			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_PNCSTOPMEM_MASK);
+		else
+			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_PNCSTOPMEM_MASK);
+		break;
+#endif
+	default:
+		break;
+	}
+}
+
+/*******************************************************************************
+* mvCtrlPwrMemGet - Get Power State of memory on specific Unit
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+******************************************************************************/
+MV_BOOL mvCtrlPwrMemGet(MV_UNIT_ID unitId, MV_U32 index)
+{
+	MV_U32 reg = MV_REG_READ(POWER_MNG_MEM_CTRL_REG);
+	MV_BOOL state = MV_TRUE;
+	MV_U32 devId = mvCtrlModelGet();
+
+	if (MV_6601_DEV_ID == devId) {
+		switch (unitId) {
+
+	#if defined(MV_INCLUDE_GIG_ETH)
+		case ETH_GIG_UNIT_ID:
+			if ((reg & PMC_GESTOPMEM_MASK(index)) == PMC_GESTOPMEM_STOP(index))
+				state = MV_FALSE;
+			else
+				state = MV_TRUE;
+			break;
+	#endif
+		case SATA_UNIT_ID:
+		case PEX_UNIT_ID:
+		case USB_UNIT_ID:
+		case XOR_UNIT_ID:
+		case CESA_UNIT_ID:
+				state = MV_FALSE;
+			break;
+	#if defined(MV_INCLUDE_PON)
+		case XPON_UNIT_ID:
+			if ((reg & PMC_PONSTOPMEM_MASK) == PMC_PONSTOPMEM_STOP)
+				state = MV_FALSE;
+			else
+				state = MV_TRUE;
+			break;
+	#endif
+	#if defined(MV_INCLUDE_BM)
+		case BM_UNIT_ID:
+			if ((reg & PMC_BMSTOPMEM_MASK) == PMC_BMSTOPMEM_STOP)
+				state = MV_FALSE;
+			else
+				state = MV_TRUE;
+			break;
+	#endif
+	#if defined(MV_INCLUDE_PNC)
+		case PNC_UNIT_ID:
+			if ((reg & PMC_PNCSTOPMEM_MASK) == PMC_PNCSTOPMEM_STOP)
+				state = MV_FALSE;
+			else
+				state = MV_TRUE;
+			break;
+	#endif
+		default:
+			state = MV_TRUE;
+			break;
+		}
+
+		return state;
+	}
+
+	switch (unitId) {
+#if defined(MV_INCLUDE_PEX)
+	case PEX_UNIT_ID:
+		if ((reg & PMC_PEXSTOPMEM_MASK(index)) == PMC_PEXSTOPMEM_STOP(index))
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_GIG_ETH)
+	case ETH_GIG_UNIT_ID:
+		if ((reg & PMC_GESTOPMEM_MASK(index)) == PMC_GESTOPMEM_STOP(index))
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_SATA)
+	case SATA_UNIT_ID:
+		if ((reg & PMC_SATASTOPMEM_MASK) == PMC_SATASTOPMEM_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_CESA)
+	case CESA_UNIT_ID:
+		if ((reg & PMC_SESTOPMEM_MASK) == PMC_SESTOPMEM_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_USB)
+	case USB_UNIT_ID:
+		if ((reg & PMC_USBSTOPMEM_MASK) == PMC_USBSTOPMEM_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_XOR)
+	case XOR_UNIT_ID:
+		if ((reg & PMC_XORSTOPMEM_MASK(index)) == PMC_XORSTOPMEM_STOP(index))
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_PON)
+	case XPON_UNIT_ID:
+		if ((reg & PMC_PONSTOPMEM_MASK) == PMC_PONSTOPMEM_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_BM)
+	case BM_UNIT_ID:
+		if ((reg & PMC_BMSTOPMEM_MASK) == PMC_BMSTOPMEM_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+#if defined(MV_INCLUDE_PNC)
+	case PNC_UNIT_ID:
+		if ((reg & PMC_PNCSTOPMEM_MASK) == PMC_PNCSTOPMEM_STOP)
+			state = MV_FALSE;
+		else
+			state = MV_TRUE;
+		break;
+#endif
+	default:
+		state = MV_TRUE;
+		break;
+	}
+
+	return state;
+}
+#else
+MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable)
+{
+	return;
+}
+
+MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index)
+{
+	return MV_TRUE;
+}
+#endif /* #if defined(MV_INCLUDE_CLK_PWR_CNTRL) */
+
+/*******************************************************************************
+* mvCtrlIsGponMode
+*
+* DESCRIPTION:
+*	returns the GPON/EPON mode select.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_TRUE - GPON.
+*	MV_FALSE - EPON.
+******************************************************************************/
+MV_BOOL mvCtrlIsGponMode(void)
+{
+	MV_U32 reg;
+
+	if (MV_6601_DEV_ID == mvCtrlModelGet())
+		return MV_TRUE;	/* 0 - GPON mode */
+
+	reg = MV_REG_READ(MPP_SAMPLE_AT_RESET(0));
+	if (MV_GET_BIT(reg, MPP_GPON_MODE_SEL_OFFS) == 0)
+		return MV_TRUE;	/* 0 - GPON mode */
+
+	return MV_FALSE;	/* 1 - EPON mode */
+}
+/*******************************************************************************
+* mvCtrlTemperatureGet
+*
+* DESCRIPTION:
+*	Get KW2 Thermal Sensor's temperature.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	Temperature measured by Thermal Sensor.
+*	Negative number in case of an invalid or unstable temperature.
+******************************************************************************/
+#define RAW_TO_TEMP(x) (((322 - x) * 10000)/13625)
+#define STABILITY_ITERATIONS 4
+#define STABILITY_MAX_VALUE 3
+
+int mvCtrlTemperatureGet(MV_VOID)
+{
+	MV_U32 regVal;
+	int temp, i, prev;
+	regVal =  MV_REG_READ(THERMAL_STATUS_REG);
+	if (!(regVal & THERMAL_VALID_MASK))
+		return -1;
+	prev = (regVal & THERMAL_TEMPERATURE_MASK) >> THERMAL_TEMPERATURE_OFFSET;
+	for (i = 0; i < STABILITY_ITERATIONS; i++) {
+		regVal =  MV_REG_READ(THERMAL_STATUS_REG);
+		temp = (regVal & THERMAL_TEMPERATURE_MASK) >> THERMAL_TEMPERATURE_OFFSET;
+		if ((temp ^ prev) > STABILITY_MAX_VALUE)
+			return -1;
+		prev = temp;
+	}
+	return RAW_TO_TEMP(temp);
+}
+
+
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvLib.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvLib.h
new file mode 100755
index 0000000..257dffe
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvLib.h
@@ -0,0 +1,243 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCtrlEnvLibh
+#define __INCmvCtrlEnvLibh
+
+/* includes */
+#include "mvSysHwConfig.h"
+#include "mvSysTdmConfig.h"
+#include "mvCommon.h"
+#include "mvTypes.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ctrlEnv/mvCtrlEnvRegs.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+/* #include "boardEnv/mvBoardEnvLib.h" */
+
+/* 0 for Auto scan mode, 1 for manual. */
+#define MV_INTERNAL_SWITCH_SMI_SCAN_MODE	0
+
+/* typedefs */
+typedef MV_STATUS(*MV_WIN_GET_FUNC_PTR) (MV_U32, MV_U32, MV_UNIT_WIN_INFO*);
+
+/* This enumerator describes the possible HW cache coherency policies the   */
+/* controllers supports.                                                    */
+typedef enum _mvCachePolicy {
+	NO_COHERENCY,		/* No HW cache coherency support                        */
+	WT_COHERENCY,		/* HW cache coherency supported in Write Through policy */
+	WB_COHERENCY		/* HW cache coherency supported in Write Back policy    */
+} MV_CACHE_POLICY;
+
+/* The swapping is referred to a 64-bit words (as this is the controller    */
+/* internal data path width). This enumerator describes the possible        */
+/* data swap types. Below is an example of the data 0x0011223344556677      */
+typedef enum _mvSwapType {
+	MV_BYTE_SWAP,		/* Byte Swap                77 66 55 44 33 22 11 00 */
+	MV_NO_SWAP,		/* No swapping              00 11 22 33 44 55 66 77 */
+	MV_BYTE_WORD_SWAP,	/* Both byte and word swap  33 22 11 00 77 66 55 44 */
+	MV_WORD_SWAP,		/* Word swap                44 55 66 77 00 11 22 33 */
+	SWAP_TYPE_MAX		/* Delimiter for this enumerator                                        */
+} MV_SWAP_TYPE;
+
+/*
+** Define the different Ethernet complex sources for the RGMIIA/B and
+** the FE/GE phy interfaces.
+*/
+typedef enum {
+	EC_MAC0_SRC = 1,
+	EC_MAC1_SRC,
+	EC_MAC0_MAC1_SRC,
+	EC_SW_P0_SRC,
+	EC_SW_P1_SRC,
+	EC_SW_P4_SRC,
+	EC_SW_P5_SRC,
+	EC_SW_P6_SRC,
+	EC_SRC_NONE
+} MV_ETH_COMPLEX_MUX_SOURCES;
+typedef enum {
+	EC_SGMII_1_25G = 1,
+	EC_SGMII_2_5G,
+} MV_ETH_COMPLEX_MAC_TYPE;
+
+typedef struct {
+	MV_ETH_COMPLEX_MUX_SOURCES feGeSrc;
+	MV_ETH_COMPLEX_MUX_SOURCES rgmiiASrc;
+	MV_ETH_COMPLEX_MUX_SOURCES swSrc;
+	MV_ETH_COMPLEX_MAC_TYPE    macType;
+} MV_ETH_COMPLEX_IF_SOURCES;
+
+/* Define the different Ethernet & Sata complex connection options */
+typedef enum {
+	ESC_OPT_RGMIIA_MAC0 = 0x00001,		/* RGMIIA originated from MAC0 */
+	ESC_OPT_RGMIIA_MAC1 = 0x00002,		/* RGMIIA originated from MAC1 */
+	ESC_OPT_RGMIIA_SW_P5 = 0x00004,		/* RGMIIA originated from switch port 5. */
+	ESC_OPT_RGMIIA_SW_P6 = 0x00008,		/* RGMIIA originated from switch port 6. */
+	ESC_OPT_RGMIIB_MAC0 = 0x00010,		/* RGMIIB originated from MAC0 */
+	ESC_OPT_MAC0_2_SW_P4 = 0x00020,		/* MAC0 connected to switch port 4. */
+	ESC_OPT_MAC1_2_SW_P5 = 0x00040,		/* MAC1 connected to switch port 5. */
+	ESC_OPT_GEPHY_MAC1 = 0x00080,		/* GE/FE Phy originated from MAC1 */
+	ESC_OPT_GEPHY_SW_P0 = 0x00100,		/* GE/FE Phy originated from switch port 0 */
+	ESC_OPT_GEPHY_SW_P5 = 0x00200,		/* GE/FE Phy originated from switch port 5 */
+	ESC_OPT_FE3PHY = 0x00400,		/* 3xFE switch phys */
+	ESC_OPT_SGMII_2_SW_P1 = 0x00800,	/* SGMII from switch port 1 */
+	ESC_OPT_SGMII = 0x01000,		/* SGMII from MAC0 */
+	ESC_OPT_QSGMII = 0x02000,		/* QSGMII option */
+	ESC_OPT_SATA = 0x04000,			/* Sata option */
+	ESC_OPT_SGMII_2_5 = 0x08000,		/* SGMII from MAC0 */
+	ESC_OPT_GEPHY_MAC0 = 0x10000,		/* Avanta-MC GE/FE Phy originated from MAC0 */ 
+	ESC_OPT_LP_SERDES_FE_GE_PHY = 0x20000,	/* Avanta-MC LP_SERDES Phy connected to onboard phy */
+	ESC_OPT_AUTO = 0x40000,
+	ESC_OPT_ILLEGAL = 0x80000,
+	ESC_OPT_ALL = 0xFFFFF
+} MV_ETH_SATA_COMPLEX_OPTIONS;
+
+typedef enum {
+	EPM_DEFAULT = 0x0,	/* RGMII */
+	EPM_MAC0_MII = 0x01,
+	EPM_MAC1_MII = 0x10,
+	EPM_SW_PORT_5_MII = 0x100,
+	EPM_SW_PORT_6_MII = 0x1000
+} MV_ETH_PORT_MODE;
+
+/* mcspLib.h API list */
+MV_STATUS mvCtrlEnvEthSrcCfgSet(MV_ETH_COMPLEX_IF_SOURCES *ethSrc);
+
+MV_STATUS mvCtrlEnvInit(MV_VOID);
+MV_STATUS mvCtrlEthComplexMppUpdate(MV_U32 ethCompOpt, MV_BOOL addRem);
+MV_U32 mvCtrlMppRegGet(MV_U32 mppGroup);
+
+#if defined(MV_INCLUDE_PEX)
+MV_U32 mvCtrlPexMaxIfGet(MV_VOID);
+#else
+#define   mvCtrlPexMaxIfGet()	(0)
+#endif
+
+#define   mvCtrlPciIfMaxIfGet()	(mvCtrlPexMaxIfGet())
+
+MV_U32 mvCtrlEthMaxPortGet(MV_VOID);
+MV_U8	  mvCtrlEthMaxCPUsGet(MV_VOID);
+#if defined(MV_INCLUDE_XOR)
+MV_U32 mvCtrlXorMaxChanGet(MV_VOID);
+MV_U32 mvCtrlXorMaxUnitGet(MV_VOID);
+#endif
+#if defined(MV_INCLUDE_USB)
+MV_U32 mvCtrlUsbMaxGet(MV_VOID);
+#endif
+#if defined(MV_INCLUDE_LEGACY_NAND)
+MV_U32 mvCtrlNandSupport(MV_VOID);
+#endif
+#if defined(MV_INCLUDE_SDIO)
+MV_U32 mvCtrlSdioSupport(MV_VOID);
+#endif
+#if defined(MV_INCLUDE_TDM)
+MV_U32 mvCtrlTdmSupport(MV_VOID);
+MV_U32 mvCtrlTdmMaxGet(MV_VOID);
+MV_UNIT_ID mvCtrlTdmUnitTypeGet(MV_VOID);
+MV_U32 mvCtrlTdmUnitIrqGet(MV_VOID);
+
+MV_VOID mvCtrlTdmClkCtrlConfig(MV_VOID);
+#if defined(MV_TDM_USE_DCO)
+MV_32 mvCtrlTdmClkCtrlGet(MV_VOID);
+MV_VOID mvCtrlTdmClkCtrlSet(MV_32 correction);
+#endif
+#endif
+
+MV_U16 mvCtrlModelGet(MV_VOID);
+MV_U8 mvCtrlRevGet(MV_VOID);
+MV_STATUS mvCtrlNameGet(char *pNameBuff);
+MV_U32 mvCtrlModelRevGet(MV_VOID);
+MV_STATUS mvCtrlModelRevNameGet(char *pNameBuff);
+MV_VOID mvCtrlAddrDecShow(MV_VOID);
+const MV_8 *mvCtrlTargetNameGet(MV_TARGET target);
+MV_U32 ctrlSizeToReg(MV_U32 size, MV_U32 alignment);
+MV_U32 ctrlRegToSize(MV_U32 regSize, MV_U32 alignment);
+MV_U32 ctrlSizeRegRoundUp(MV_U32 size, MV_U32 alignment);
+MV_U32 mvCtrlSysRstLengthCounterGet(MV_VOID);
+MV_STATUS ctrlWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2);
+MV_STATUS ctrlWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2);
+
+MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable);
+MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index);
+MV_VOID mvCtrlPwrMemSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable);
+MV_BOOL mvCtrlIsBootFromSPI(MV_VOID);
+MV_BOOL mvCtrlIsBootFromSPIUseNAND(MV_VOID);
+MV_BOOL mvCtrlIsBootFromNAND(MV_VOID);
+MV_BOOL mvCtrlIsBootFromNOR(MV_VOID);
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+MV_VOID mvCtrlPwrSaveOn(MV_VOID);
+MV_VOID mvCtrlPwrSaveOff(MV_VOID);
+MV_U32 mvCtrlIsPwrSaveOn(MV_VOID);
+#endif
+MV_BOOL mvCtrlPwrMemGet(MV_UNIT_ID unitId, MV_U32 index);
+MV_VOID mvMPPConfigToSPI(MV_VOID);
+MV_VOID mvMPPConfigToDefault(MV_VOID);
+MV_STATUS mvCtrlEthSataComplexBuildConfig(MV_U32 brdModules, MV_ETH_COMPLEX_IF_SOURCES *ifSrc, MV_U32 *ethConfig);
+MV_U32 mvCtrlSataMaxPortGet(MV_VOID);
+
+MV_BOOL mvCtrlIsGponMode(void);
+
+int mvCtrlTemperatureGet(MV_VOID);
+
+#endif /* __INCmvCtrlEnvLibh */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvRegs.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvRegs.h
new file mode 100755
index 0000000..c36c68e
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvRegs.h
@@ -0,0 +1,527 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCtrlEnvRegsh
+#define __INCmvCtrlEnvRegsh
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* CV Support */
+#define PEX0_MEM0 	PEX0_MEM
+#define PCI0_MEM0	PEX0_MEM
+#define PEX1_MEM0 	PEX1_MEM
+#define PCI1_MEM0	PEX1_MEM
+
+/* Controller revision info */
+#define PCI_CLASS_CODE_AND_REVISION_ID			    0x008
+#define PCCRIR_REVID_OFFS				    0		/* Revision ID */
+#define PCCRIR_REVID_MASK				    (0xff << PCCRIR_REVID_OFFS)
+
+/* Controler environment registers offsets */
+#define MV_TDM_2CH_IRQ_NUM	20
+#define MV_TDM_IRQ_NUM		30
+
+/* Power Management Memory Power Down Register	*/
+#define POWER_MNG_MEM_CTRL_REG			0x18218
+
+#define PMC_COMMSTOPMEM_OFFS			0
+#define PMC_COMMSTOPMEM_MASK			(1 << PMC_COMMSTOPMEM_OFFS)
+#define PMC_COMMSTOPMEM_EN			(0 << PMC_COMMSTOPMEM_OFFS)
+#define PMC_COMMSTOPMEM_STOP			(1 << PMC_COMMSTOPMEM_OFFS)
+
+#define PMC_PEXSTOPMEM_OFFS(id)			(1 + (id * 8))
+#define PMC_PEXSTOPMEM_MASK(id)			(1 << PMC_PEXSTOPMEM_OFFS(id))
+#define PMC_PEXSTOPMEM_EN(id)			(0 << PMC_PEXSTOPMEM_OFFS(id))
+#define PMC_PEXSTOPMEM_STOP(id)			(1 << PMC_PEXSTOPMEM_OFFS(id))
+
+#define PMC_USBSTOPMEM_OFFS			2
+#define PMC_USBSTOPMEM_MASK			(1 << PMC_USBSTOPMEM_OFFS)
+#define PMC_USBSTOPMEM_EN			(0 << PMC_USBSTOPMEM_OFFS)
+#define PMC_USBSTOPMEM_STOP			(1 << PMC_USBSTOPMEM_OFFS)
+
+#define PMC_DUNITSTOPMEM_OFFS			3
+#define PMC_DUNITSTOPMEM_MASK			(1 << PMC_DUNITSTOPMEM_OFFS)
+#define PMC_DUNITSTOPMEM_EN			(0 << PMC_DUNITSTOPMEM_OFFS)
+#define PMC_DUNITSTOPMEM_STOP			(1 << PMC_DUNITSTOPMEM_OFFS)
+
+#define PMC_RUNITSTOPMEM_OFFS			4
+#define PMC_RUNITSTOPMEM_MASK			(1 << PMC_RUNITSTOPMEM_OFFS)
+#define PMC_RUNITSTOPMEM_EN			(0 << PMC_RUNITSTOPMEM_OFFS)
+#define PMC_RUNITSTOPMEM_STOP			(1 << PMC_RUNITSTOPMEM_OFFS)
+
+#define PMC_XORSTOPMEM_OFFS(port)		(5+(port*2))
+#define PMC_XORSTOPMEM_MASK(port)		(1 << PMC_XORSTOPMEM_OFFS(port))
+#define PMC_XORSTOPMEM_EN(port)			(0 << PMC_XORSTOPMEM_OFFS(port))
+#define PMC_XORSTOPMEM_STOP(port)		(1 << PMC_XORSTOPMEM_OFFS(port))
+
+#define PMC_SATASTOPMEM_OFFS			6
+#define PMC_SATASTOPMEM_MASK			(1 << PMC_SATASTOPMEM_OFFS)
+#define PMC_SATASTOPMEM_EN			(0 << PMC_SATASTOPMEM_OFFS)
+#define PMC_SATASTOPMEM_STOP			(1 << PMC_SATASTOPMEM_OFFS)
+
+#define PMC_SESTOPMEM_OFFS			8
+#define PMC_SESTOPMEM_MASK			(1 << PMC_SESTOPMEM_OFFS)
+#define PMC_SESTOPMEM_EN			(0 << PMC_SESTOPMEM_OFFS)
+#define PMC_SESTOPMEM_STOP			(1 << PMC_SESTOPMEM_OFFS)
+
+#define PMC_NFCSTOPMEM_OFFS			10
+#define PMC_NFCSTOPMEM_MASK			(1 << PMC_NFCSTOPMEM_OFFS)
+#define PMC_NFCSTOPMEM_EN			(0 << PMC_NFCSTOPMEM_OFFS)
+#define PMC_NFCSTOPMEM_STOP			(1 << PMC_NFCSTOPMEM_OFFS)
+
+#define PMC_GESTOPMEM_OFFS(port)		(16 + (port))
+#define PMC_GESTOPMEM_MASK(port)		(1 << PMC_GESTOPMEM_OFFS(port))
+#define PMC_GESTOPMEM_EN(port)			(0 << PMC_GESTOPMEM_OFFS(port))
+#define PMC_GESTOPMEM_STOP(port)		(1 << PMC_GESTOPMEM_OFFS(port))
+
+#define PMC_GUNITSTOPMEM_OFFS			18
+#define PMC_GUNITSTOPMEM_MASK			(1 << PMC_GUNITSTOPMEM_OFFS)
+#define PMC_GUNITSTOPMEM_EN			(0 << PMC_GUNITSTOPMEM_OFFS)
+#define PMC_GUNITSTOPMEM_STOP			(1 << PMC_GUNITSTOPMEM_OFFS)
+
+#define PMC_PNCSTOPMEM_OFFS			19
+#define PMC_PNCSTOPMEM_MASK			(1 << PMC_PNCSTOPMEM_OFFS)
+#define PMC_PNCSTOPMEM_EN			(0 << PMC_PNCSTOPMEM_OFFS)
+#define PMC_PNCSTOPMEM_STOP			(1 << PMC_PNCSTOPMEM_OFFS)
+
+#define PMC_BMSTOPMEM_OFFS			20
+#define PMC_BMSTOPMEM_MASK			(1 << PMC_BMSTOPMEM_OFFS)
+#define PMC_BMSTOPMEM_EN			(0 << PMC_BMSTOPMEM_OFFS)
+#define PMC_BMSTOPMEM_STOP			(1 << PMC_BMSTOPMEM_OFFS)
+
+#define PMC_PONSTOPMEM_OFFS			21
+#define PMC_PONSTOPMEM_MASK			(1 << PMC_PONSTOPMEM_OFFS)
+#define PMC_PONSTOPMEM_EN			(0 << PMC_PONSTOPMEM_OFFS)
+#define PMC_PONSTOPMEM_STOP			(1 << PMC_PONSTOPMEM_OFFS)
+
+#define PMC_GPNMCSTOPMEM_OFFS			22
+#define PMC_GPNMCSTOPMEM_MASK			(1 << PMC_GPNMCSTOPMEM_OFFS)
+#define PMC_GPNMCSTOPMEM_EN			(0 << PMC_GPNMCSTOPMEM_OFFS)
+#define PMC_GPNMCSTOPMEM_STOP			(1 << PMC_GPNMCSTOPMEM_OFFS)
+
+
+/*  Power Management Clock Gating Control Register	*/
+#define POWER_MNG_CTRL_REG			0x1821C
+
+#define PMC_TDMSTOPCLOCK_OFFS			0
+#define PMC_TDMSTOPCLOCK_MASK			(1 << PMC_TDMSTOPCLOCK_OFFS)
+#define PMC_TDMSTOPCLOCK_EN			(1 << PMC_TDMSTOPCLOCK_OFFS)
+#define PMC_TDMSTOPCLOCK_STOP			(0 << PMC_TDMSTOPCLOCK_OFFS)
+
+#define PMC_PEXPHYSTOPCLOCK_OFFS		1
+#define PMC_PEXPHYSTOPCLOCK_MASK		(1 << PMC_PEXPHYSTOPCLOCK_OFFS)
+#define PMC_PEXPHYSTOPCLOCK_EN			(1 << PMC_PEXPHYSTOPCLOCK_OFFS)
+#define PMC_PEXPHYSTOPCLOCK_STOP		(0 << PMC_PEXPHYSTOPCLOCK_OFFS)
+
+#define PMC_PEXSTOPCLOCK_OFFS(id)		(2 + (16 * id))
+#define PMC_PEXSTOPCLOCK_MASK(id)		(1 << PMC_PEXSTOPCLOCK_OFFS(id))
+#define PMC_PEXSTOPCLOCK_EN(id)			(1 << PMC_PEXSTOPCLOCK_OFFS(id))
+#define PMC_PEXSTOPCLOCK_STOP(id)		(0 << PMC_PEXSTOPCLOCK_OFFS(id))
+
+#define PMC_USBSTOPCLOCK_OFFS			3
+#define PMC_USBSTOPCLOCK_MASK			(1 << PMC_USBSTOPCLOCK_OFFS)
+#define PMC_USBSTOPCLOCK_EN			(1 << PMC_USBSTOPCLOCK_OFFS)
+#define PMC_USBSTOPCLOCK_STOP			(0 << PMC_USBSTOPCLOCK_OFFS)
+
+#define PMC_SDIOSTOPCLOCK_OFFS			4
+#define PMC_SDIOSTOPCLOCK_MASK			(1 << PMC_SDIOSTOPCLOCK_OFFS)
+#define PMC_SDIOSTOPCLOCK_EN			(1 << PMC_SDIOSTOPCLOCK_OFFS)
+#define PMC_SDIOSTOPCLOCK_STOP			(0 << PMC_SDIOSTOPCLOCK_OFFS)
+
+#define PMC_COMMSTOPCLOCK_OFFS			5
+#define PMC_COMMSTOPCLOCK_MASK			(1 << PMC_COMMSTOPCLOCK_OFFS)
+#define PMC_COMMSTOPCLOCK_EN			(1 << PMC_COMMSTOPCLOCK_OFFS)
+#define PMC_COMMSTOPCLOCK_STOP			(0 << PMC_COMMSTOPCLOCK_OFFS)
+
+#define PMC_RUNITSTOPCLOCK_OFFS			7
+#define PMC_RUNITSTOPCLOCK_MASK			(1 << PMC_RUNITSTOPCLOCK_OFFS)
+#define PMC_RUNITSTOPCLOCK_EN			(1 << PMC_RUNITSTOPCLOCK_OFFS)
+#define PMC_RUNITSTOPCLOCK_STOP			(0 << PMC_RUNITSTOPCLOCK_OFFS)
+
+#define PMC_XORSTOPCLOCK_OFFS(unit)		(8 + (unit))
+#define PMC_XORSTOPCLOCK_MASK(unit)		(1 << PMC_XORSTOPCLOCK_OFFS(unit))
+#define PMC_XORSTOPCLOCK_EN(unit)		(1 << PMC_XORSTOPCLOCK_OFFS(unit))
+#define PMC_XORSTOPCLOCK_STOP(unit)		(0 << PMC_XORSTOPCLOCK_OFFS(unit))
+
+#define PMC_POWERSAVE_OFFS			11
+#define PMC_POWERSAVE_MASK			(1 << PMC_POWERSAVE_OFFS)
+#define PMC_POWERSAVE_EN			(1 << PMC_POWERSAVE_OFFS)
+#define PMC_POWERSAVE_STOP			(0 << PMC_POWERSAVE_OFFS)
+
+#define PMC_SATASTOPCLOCK_OFFS			(14)
+#define PMC_SATASTOPCLOCK_MASK			(1 << PMC_SATASTOPCLOCK_OFFS)
+#define PMC_SATASTOPCLOCK_EN			(1 << PMC_SATASTOPCLOCK_OFFS)
+#define PMC_SATASTOPCLOCK_STOP			(0 << PMC_SATASTOPCLOCK_OFFS)
+
+#define PMC_SESTOPCLOCK_OFFS			(15)
+#define PMC_SESTOPCLOCK_MASK			(1 << PMC_SESTOPCLOCK_OFFS)
+#define PMC_SESTOPCLOCK_EN			(1 << PMC_SESTOPCLOCK_OFFS)
+#define PMC_SESTOPCLOCK_STOP			(0 << PMC_SESTOPCLOCK_OFFS)
+
+#define PMC_NFECCSTOPCLOCK_OFFS			(16)
+#define PMC_NFECCSTOPCLOCK_MASK			(1 << PMC_NFECCSTOPCLOCK_OFFS)
+#define PMC_NFECCSTOPCLOCK_EN			(1 << PMC_NFECCSTOPCLOCK_OFFS)
+#define PMC_NFECCSTOPCLOCK_STOP			(0 << PMC_NFECCSTOPCLOCK_OFFS)
+
+#define PMC_NFCSTOPCLOCK_OFFS			(17)
+#define PMC_NFCSTOPCLOCK_MASK			(1 << PMC_NFCSTOPCLOCK_OFFS)
+#define PMC_NFCSTOPCLOCK_EN			(1 << PMC_NFCSTOPCLOCK_OFFS)
+#define PMC_NFCSTOPCLOCK_STOP			(0 << PMC_NFCSTOPCLOCK_OFFS)
+
+#define PMC_GESTOPCLOCK_OFFS(port)		(24 + (port))
+#define PMC_GESTOPCLOCK_MASK(port)		(1 << PMC_GESTOPCLOCK_OFFS(port))
+#define PMC_GESTOPCLOCK_EN(port)		(1 << PMC_GESTOPCLOCK_OFFS(port))
+#define PMC_GESTOPCLOCK_STOP(port)		(0 << PMC_GESTOPCLOCK_OFFS(port))
+
+#define PMC_PONSTOPCLOCK_OFFS			(28)
+#define PMC_PONSTOPCLOCK_MASK			(1 << PMC_PONSTOPCLOCK_OFFS)
+#define PMC_PONSTOPCLOCK_EN			(1 << PMC_PONSTOPCLOCK_OFFS)
+#define PMC_PONSTOPCLOCK_STOP			(0 << PMC_PONSTOPCLOCK_OFFS)
+
+#define PMC_SWITCHSTOPCLOCK_OFFS		(30)
+#define PMC_SWITCHSTOPCLOCK_MASK		(1 << PMC_SWITCHSTOPCLOCK_OFFS)
+#define PMC_SWITCHSTOPCLOCK_EN			(1 << PMC_SWITCHSTOPCLOCK_OFFS)
+#define PMC_SWITCHSTOPCLOCK_STOP		(0 << PMC_SWITCHSTOPCLOCK_OFFS)
+
+/* Software Reset Control Register */
+#define SOFT_RESET_CTRL_REG			0x18220
+#define SRC_XORSWRSTN_OFFSET			0
+#define SRC_XORSWRSTN_MASK			(0x1 << SRC_XORSWRSTN_OFFSET)
+#define SRC_CRYPTOSWRSTN_OFFSET			1
+#define SRC_CRYPTOSWRSTN_MASK			(0x1 << SRC_CRYPTOSWRSTN_OFFSET)
+#define SRC_TDMSWRSTN_OFFSET			2
+#define SRC_TDMSWRSTN_MASK			(0x1 << SRC_TDMSWRSTN_OFFSET)
+#define SRC_USBSWRSTN_OFFSET			3
+#define SRC_USBSWRSTN_MASK			(0x1 << SRC_USBSWRSTN_OFFSET)
+#define SRC_SDIOSWRSTN_OFFSET			4
+#define SRC_SDIOSWRSTN_MASK			(0x1 << SRC_SDIOSWRSTN_OFFSET)
+#define SRC_COMMSWRSTN_OFFSET			5
+#define SRC_COMMSWRSTN_MASK			(0x1 << SRC_COMMSWRSTN_OFFSET)
+#define SRC_G01SWRSTN_OFFSET			8
+#define SRC_G01SWRSTN_MASK			(0x1 << SRC_G01SWRSTN_OFFSET)
+#define SRC_GPONSWRSTN_OFFSET			10
+#define SRC_GPONSWRSTN_MASK			(0x1 << SRC_GPONSWRSTN_OFFSET)
+#define SRC_SATASWRSTN_OFFSET			12
+#define SRC_SATASWRSTN_MASK			(0x1 << SRC_SATASWRSTN_OFFSET)
+#define SRC_NFCSWRSTN_OFFSET			14
+#define SRC_NFCSWRSTN_MASK			(0x1 << SRC_NFCSWRSTN_OFFSET)
+#define SRC_LPSRDSSWRSTN_OFFSET			24
+#define SRC_LPSRDSSWRSTN_MASK			(0x1 << SRC_LPSRDSSWRSTN_OFFSET)
+
+/* Core DivClk Control Register */
+#define CORE_DIVCLK_CTRL_REG			0x18730
+#define MISC_CORE_APLL_CLKDIV_RATIO_OFFS	8
+#define MISC_CORE_APLL_CLKDIV_RATIO_MASK	(0x3f << MISC_CORE_APLL_CLKDIV_RATIO_OFFS)
+#define CORE_DIVCLK_400MHZ			(5 << MISC_CORE_APLL_CLKDIV_RATIO_OFFS)
+#define CORE_DIVCLK_333MHZ			(6 << MISC_CORE_APLL_CLKDIV_RATIO_OFFS)
+
+/* TDM and PON Clock Out Divider Control Register */
+#define TDM_PON_CLK_OUT_DIV_CONTROL_REG		0x18740
+#define TDM_CLK_DIV_RATIO_OFFS			0
+#define TDM_CLK_DIV_RATIO_MASK			(0x3f << TDM_CLK_DIV_RATIO_OFFS)
+#define TDM_CLK_DIV_RATIO_8M			(0x3 << TDM_CLK_DIV_RATIO_OFFS)
+#define TDM_CLK_DIV_RATIO_4M			(0x6 << TDM_CLK_DIV_RATIO_OFFS)
+#define TDM_CLK_DIV_RATIO_2M			(0xc << TDM_CLK_DIV_RATIO_OFFS)
+#define TDM_LOAD_RATIO_OFFS			9
+#define TDM_LOAD_RATIO_MASK			(1 << TDM_LOAD_RATIO_OFFS)
+#define TDM_CLK_SRC_SEL_OFFS			14
+#define TDM_CLK_SRC_SEL_MASK			(3 << TDM_CLK_SRC_SEL_OFFS)
+#define PLL_MODE				(0 << TDM_CLK_SRC_SEL_OFFS)
+#define EXT_XTAL_MODE				(1 << TDM_CLK_SRC_SEL_OFFS)
+#define EXT_REF_MODE				(2 << TDM_CLK_SRC_SEL_OFFS)
+
+/* DCO clock apply/reset bits */
+#define DCO_CLK_DIV_MOD_OFFS			24
+#define DCO_CLK_DIV_APPLY			(0x1 << DCO_CLK_DIV_MOD_OFFS)
+#define DCO_CLK_DIV_RESET_OFFS			25
+#define DCO_CLK_DIV_RESET			(0x1 << DCO_CLK_DIV_RESET_OFFS)
+
+/* DCO clock ratio is 48Mhz/x */
+#define DCO_CLK_DIV_RATIO_OFFS			26
+#define DCO_CLK_DIV_RATIO_MASK			(BIT26 | BIT27 | BIT28 | BIT29 | BIT30 | BIT31)
+#define DCO_CLK_DIV_RATIO_8M			(0x6 << DCO_CLK_DIV_RATIO_OFFS)
+#define DCO_CLK_DIV_RATIO_4M			(0xc << DCO_CLK_DIV_RATIO_OFFS)
+#define DCO_CLK_DIV_RATIO_2M			(0x18 << DCO_CLK_DIV_RATIO_OFFS)
+
+/* DCO Control Register [13:2], Value range: 0x20-0xFE0, 0x1 = 1.27PPM */
+#define DCO_MOD_CTRL_REG			0x19904
+#define DCO_MOD_CTRL_MASK			(BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | BIT13)
+#define DCO_MOD_CTRL_OFFS			0x2
+#define DCO_MOD_CTRL_BASE			0x800
+#define DCO_MOD_CTRL_BASE_VAL			(0x800 << DCO_MOD_CTRL_OFFS)
+
+/* Misc PLL Control Register */
+#define MISC_PLL_CTRL_REG			0x18750
+#define MISC_APLL_N_RESET_MASK_OFFS		0
+#define MISC_APLL_N_RESET_MASK_MASK		(0x1f << MISC_APLL_N_RESET_MASK_OFFS)
+#define MISC_APLL_DIV_RELOAD_CMD_OFFS		5
+#define MISC_APLL_DIV_RELOAD_CMD_MASK		(1 << MISC_APLL_DIV_RELOAD_CMD_OFFS)
+#define MISC_APLL_DIV_RELOAD_EN_OFFS		6
+#define MISC_APLL_DIV_RELOAD_EN_MASK		(0x1f << MISC_APLL_DIV_RELOAD_EN_OFFS)
+#define MISC_APLL_CLKDIV_RATIO_OFFS		11
+#define MISC_APLL_CLKDIV_RATIO_MASK		(0x1f << MISC_APLL_CLKDIV_RATIO_OFFS)
+
+/*  Ana Grp1 Config Register	*/
+#define ANA_GRP1_CONFIG_REG			0x18480
+#define ANA_GRP1_CFG_DEF_VAL			0x68
+
+/* Controler environment registers offsets */
+#define MPP_CONTROL_REG(id)			(0x18000 + (id * 4))
+
+#define DEVICE_VENDOR_ID_REG		0x18200		/*  device and vendor id for 6601 device */
+/* Sample at Reset */
+#define MPP_SAMPLE_AT_RESET(id)			(0x18230 + (id * 4))
+
+#define MPP_GPON_MODE_SEL_OFFS			27
+#define MPP_GPON_MODE_SEL_MASK			(0x1 << MPP_GPON_MODE_SEL_OFFS)
+
+/* SYSRSTn Length Counter */
+#define SYSRST_LENGTH_COUNTER_REG		0x18250
+#define SLCR_COUNT_OFFS				0
+#define SLCR_COUNT_MASK				(0x1FFFFFFF << SLCR_COUNT_OFFS)
+#define SLCR_CLR_OFFS				31
+#define SLCR_CLR_MASK				(1 << SLCR_CLR_OFFS)
+
+#define LED_MATRIX_CTRL_REG(id)			(0x18280 + (id * 4))
+
+/* Device ID */
+#define CHIP_BOND_REG				0x18238
+#define CBR_VERION_ID_OFFS			18
+#define CBR_VERION_ID_MASK			(0xF << CBR_VERION_ID_OFFS)
+
+#define PCKG_OPT_MASK				0x3
+#define IO_CONFIG_0_REG				0x184e0
+#define MPP_OUTPUT_DRIVE_REG			0x184E4
+#define MPP_GE_A_OUTPUT_DRIVE_OFFS		6
+#define MPP_GE_A_1_8_OUTPUT_DRIVE		(0x1 << MPP_GE_A_OUTPUT_DRIVE_OFFS)
+#define MPP_GE_A_2_5_OUTPUT_DRIVE		(0x2 << MPP_GE_A_OUTPUT_DRIVE_OFFS)
+#define MPP_GE_B_OUTPUT_DRIVE_OFFS		14
+#define MPP_GE_B_1_8_OUTPUT_DRIVE		(0x1 << MPP_GE_B_OUTPUT_DRIVE_OFFS)
+#define MPP_GE_B_2_5_OUTPUT_DRIVE		(0x2 << MPP_GE_B_OUTPUT_DRIVE_OFFS)
+
+/* Sample At Reset bits */
+#define MSAR_BOOT_MODE_OFFS			11
+#define MSAR_BOOT_MODE_MASK			(0x3f << MSAR_BOOT_MODE_OFFS)
+#define MSAR_BOOT_SPI_W_BOOTROM_MASK		(1 << 8)
+#define MSAR_BOOT_SPI_W_BOOTROM_LIST		{ 8 }
+#define MSAR_BOOT_NAND_LEG_W_BOOTROM_LIST	{ 0x4, 0x5, 0x6, 0x7, 0x9, 0xF }
+#define MSAR_BOOT_NAND_W_BOOTROM_LIST		{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,	\
+						  0x37, 0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x3F }
+#if 0
+#define MSAR_BOOT_NOR_W_BOOTROM_LIST_LOW	{ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,	\
+						  0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1E, 0x1F }
+#define MSAR_BOOT_NOR_W_BOOTROM_LIST_HIGH	{ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,	\
+						  0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2E, 0x2F }
+#endif
+#define MSAR_BOOT_NOR_W_BOOTROM_LIST		{ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,	\
+						  0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1E, 0x1F,	\
+						  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,	\
+						  0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2E, 0x2F }
+
+#define MSAR_TCLCK_OFFS				9
+#define MSAR_TCLCK_MASK				(0x3 << MSAR_TCLCK_OFFS)
+#define MSAR_TCLCK_6601_MASK			(0x1 << MSAR_TCLCK_OFFS)
+
+#define MSAR_TCLCK_166				(0x1 << MSAR_TCLCK_OFFS)
+#define MSAR_TCLCK_200				(0x2 << MSAR_TCLCK_OFFS)
+
+#define MSAR_L2EXIST_OFFS			30
+#define MSAR_L2EXIST_MASK			(1 << MSAR_L2EXIST_OFFS)
+
+#define MV_NOR_LOW_MPPS		2
+#define MV_NOR_HIGH_MPPS	3
+
+/* Extract CPU, L2, DDR clocks SAR value from
+** bits 56,39,34,33,40,28
+*/
+#define MSAR_CPU_DDR_L2_CLCK_EXTRACT(sar0)	((sar0 >> 1) & 0x3F)
+
+#define MSAR_CPU_DDR_L2_CLCK_TWSI_EXTRACT(sar0, sar1)	(((sar0  & 0x1F) | ((sar1 & 0x10) << 1)))
+#define MSAR6601_CPU_DDR_CLCK_TWSI_EXTRACT(sar0)	(sar0  & 0x7)
+
+#define PMU_POWER_IF_POLARITY_REG		(MV_DEV_PMU_REGS_OFFSET + 0x4)
+
+#ifndef MV_ASMLANGUAGE
+
+#define CLCK_TBL_SAT_IDX	0
+#define CLCK_TBL_CPU_IDX	1
+#define CLCK_TBL_DDR_IDX	2
+#define CLCK_TBL_L2_IDX		3
+
+/*	satr	CPU		SysClock/DDR	L2		*/
+#define MV_CPU_DDR_L2_CLCK_TBL    { \
+	{31,    1200000000,     400000000,      480000000       },\
+	{32,	1200000000,	400000000,	400000000	},\
+	{36,	1600000000,	533000000,	533000000	},\
+	{37,	1600000000,	400000000,	533000000	},\
+	{21,    800000000,      400000000,      400000000       },\
+	{24,    1000000000,     400000000,      400000000       },\
+	{35,    1500000000,     500000000,      500000000       },\
+	{(MV_U32)-1, (MV_U32)-1, (MV_U32)-1,	(MV_U32)-1	} \
+}
+
+/*	satr	CPU		    DDR	*/
+#define MV6601_CPU_DDR_CLCK_TBL    { \
+	{0, 200000000, 200000000,0 },\
+	{1, 266000000, 266000000,0 },\
+	{2, 266000000, 400000000,0 },\
+	{3, 200000000, 400000000,0 },\
+	{4, 400000000, 400000000,0 },\
+	{5, 333000000, 333000000,0 },\
+	{6, 400000000, 400000000,0 },\
+	{7, 400000000, 400000000,0 },\
+	{(MV_U32)-1, (MV_U32)-1, (MV_U32)-1,	(MV_U32)-1	} \
+}
+
+
+/* These macros help units to identify a target Mbus Arbiter group */
+#define MV_TARGET_IS_DRAM(target)   \
+			((target >= SDRAM_CS0) && (target <= SDRAM_CS3))
+
+#define MV_TARGET_IS_PEX0(target)	\
+			((target >= PEX0_MEM) && (target <= PEX0_IO))
+
+#define MV_TARGET_IS_PEX1(target)	\
+			((target >= PEX1_MEM) && (target <= PEX1_IO))
+
+#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target))
+
+#define MV_TARGET_IS_DEVICE(target) \
+			((target >= DEVICE_CS0) && (target <= DEVICE_CS3))
+
+#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar)   0
+
+#define	MV_TARGET_IS_AS_BOOT(target) ((target) == BOOT_ROM_CS)
+
+#define MV_CHANGE_BOOT_CS(target)	(((target) == DEV_BOOCS) ? BOOT_ROM_CS : (target))
+#if 0
+		sampleAtResetTargetArray[((MV_REG_READ(MPP_SAMPLE_AT_RESET(0)) & MSAR_BOOT_MODE_MASK)	\
+			>> MSAR_BOOT_MODE_OFFS)] : (target))
+#endif
+
+#define TCLK_TO_COUNTER_RATIO   1   /* counters running in Tclk */
+
+
+#define BOOT_TARGETS_NAME_ARRAY {	\
+	TBL_TERM,			\
+	TBL_TERM,			\
+	TBL_TERM,			\
+	TBL_TERM,			\
+	BOOT_ROM_CS,			\
+	BOOT_ROM_CS,			\
+	BOOT_ROM_CS,			\
+	BOOT_ROM_CS,			\
+	BOOT_ROM_CS,			\
+	BOOT_ROM_CS,			\
+	TBL_TERM,			\
+	TBL_TERM,			\
+	TBL_TERM,			\
+	TBL_TERM,			\
+	TBL_TERM,			\
+	BOOT_ROM_CS			\
+}
+
+/* For old competability */
+/*#define MV_BOOTDEVICE_INDEX   	0*/
+
+#define START_DEV_CS   		DEV_CS0
+#define DEV_TO_TARGET(dev)	((dev) + START_DEV_CS)
+
+#define PCI_IF0_MEM0		PEX0_MEM
+#define PCI_IF0_IO		PEX0_IO
+#define PCI_IF1_MEM0		PEX1_MEM
+#define PCI_IF1_IO		PEX1_IO
+
+/* This enumerator defines the Marvell controller target ID      */
+typedef enum _mvTargetId {
+	DRAM_TARGET_ID  = 0,	/* Port 0 -> DRAM interface	*/
+	DEV_TARGET_ID   = 1,	/* Port 1 -> Legacy Nand/SPI	*/
+	CRYPT_TARGET_ID = 3,	/* Port 3 --> Crypto Engine	*/
+	PEX0_TARGET_ID  = 4,	/* Port 4 -> PCI Express0	*/
+	ETH_TARGET_ID = 7,	/* Port 7 -> ETH0/1		*/
+	PON_TARGET_ID   = 10,	/* PON unit */
+	PNC_BM_TARGET_ID = 12, 	/* Port 12 -> PNC + BM Unit	*/
+	NFC_TARGET_ID = 0xF,	/* Port 15 -> NFC		*/
+	MAX_TARGETS_ID
+} MV_TARGET_ID;
+
+
+/* thermal sensor */
+#define THERMAL_STATUS_REG 0x184d8
+#define THERMAL_CALIBRATION_BIT 0
+#define THERMAL_CALIBRATION_MASK (1 << THERMAL_CALIBRATION_BIT)
+#define THERMAL_VALID_BIT 9
+#define THERMAL_VALID_MASK (1 << THERMAL_VALID_BIT)
+#define THERMAL_TEMPERATURE_OFFSET 10
+#define THERMAL_TEMPERATURE_MASK (0x1FF << THERMAL_TEMPERATURE_OFFSET)
+
+#endif /* MV_ASMLANGUAGE */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvSpec.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvSpec.h
new file mode 100755
index 0000000..eed78d3
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEnvSpec.h
@@ -0,0 +1,454 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCtrlEnvSpech
+#define __INCmvCtrlEnvSpech
+
+#include "mvDeviceId.h"
+#include "mvSysHwConfig.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define MV_ARM_SOC
+#define SOC_NAME_PREFIX			"MV88F"
+
+/* units base and port numbers */
+#ifdef MV_ASMLANGUAGE
+#define MV_XOR_REGS_OFFSET(unit)	0x60800
+#else
+#define MV_XOR0_REGS_OFFSET		0x60800
+#define MV_XOR_REGS_OFFSET(unit)	0x60800
+#endif
+
+#define MV_DRAM_REGS_OFFSET			0x0
+#define MV_DEV_BUS_REGS_OFFSET			0x10000
+#define MV_RTC_REGS_OFFSET			0x10300
+#define MV_SPI_REGS_OFFSET(unit)		(0x10600 + (unit * 0x80))
+#define MV_TWSI_SLAVE_REGS_OFFSET(chanNum)	(0x11000 + (chanNum * 0x100))
+#define MV_UART_REGS_OFFSET(chanNum)		(0x12000 + (chanNum * 0x100))
+#define MV_MPP_REGS_OFFSET			0x18000
+#define MV_GPP_REGS_OFFSET_0			0x18100
+#define MV_GPP_REGS_OFFSET(unit)	   ((MV_6601_DEV_ID == mvCtrlModelGet()) ? (0x18100 + ((unit) * 0x24)) : \
+										(0x18100 + ((unit) * 0x40)))
+#define MV_ETH_COMPLEX_OFFSET			0x18800
+#define MV_CPUIF_REGS_OFFSET			0x20000
+#define MAX_AHB_TO_MBUS_REG_BASE		0x20000
+#define MV_CNTMR_REGS_OFFSET			0x20300
+#define MV_DEV_PMU_REGS_OFFSET			0x1C000
+#define MV_PMU_REGS_OFFSET			0x28000
+#define MV_CESA_TDMA_REGS_OFFSET(chanNum)	(0x30000 + (chanNum * 0x2000))
+#define MV_CESA_REGS_OFFSET(chanNum)		(0x3D000 + (chanNum * 0x2000))
+#define MV_PEX_IF_REGS_OFFSET(pexIf)      	(0x40000 + (0x4000 * pexIf))
+#define MV_USB_REGS_OFFSET(dev)       		0x50000
+
+#if defined(CONFIG_MV_ETH_LEGACY)
+#define MV_ETH_REGS_OFFSET(port)      		(((port) == 0) ? 0x72000 : 0x76000)
+#else
+#define MV_ETH_REGS_OFFSET(port)      		(((port) == 0) ? 0x70000 : 0x74000)
+#endif /* CONFIG_MV_ETH_LEGACY */
+
+#define MV_ETH_ONLY_REGS_OFFSET			0x72000
+#define MV_SATA_REGS_OFFSET			0x80000
+#define MV_SDMMC_REGS_OFFSET			0x90000
+#define MV_PON_REGS_OFFSET			0xA0000
+#define MV_PON_MAC_REGS_OFFSET			0xAC000
+#define MV_BM_REGS_OFFSET			0xC0000
+#define MV_PNC_REGS_OFFSET			0xC8000
+#define MV_TDM_REGS_OFFSET			0xD0000
+#define MV_COMM_UNIT_REGS_OFFSET		0xB0000
+#define MV_NFC_REGS_OFFSET			0xF0000
+
+#define MV_ETH_SMI_PORT				1
+
+/*#define MV_PDMA_REGS_BASE			0x0 */ /* Unused, for compilation purposes only */
+
+#define INTER_REGS_SIZE				_1M
+
+/* This define describes the TWSI interrupt bit and location */
+#define TWSI_CPU_MAIN_INT_CAUSE_REG	0x20200
+#define TWSI_CPU_HIGH_INT_CAUSE_REG	0x20210
+#define TWSI0_CPU_MAIN_INT_BIT(ch)	((ch == 0) ? (1 << 18) : (1 << 25))
+#define TWSI_SPEED			100000
+
+#define MV_GPP_MAX_PINS			96
+#define MV_GPP_MAX_GROUP    		3
+#define MV_CNTMR_MAX_COUNTER 		2
+#define MV_UART_MAX_CHAN		2
+
+#define MV_XOR_6510_6530_MAX_UNIT	0
+#define MV_XOR_6510_6530_MAX_CHAN	0
+#define MV_XOR_MAX_UNIT			1
+#define MV_XOR_MAX_CHAN         	2 /* total channels for all units together*/
+#define MV_XOR_MAX_CHAN_PER_UNIT       	2 /* channels for units */
+
+#define MV_SATA_6510_6530_MAX_CHAN	0
+#define MV_SATA_6550_6560_MAX_CHAN	1
+
+#define MV_6510_MPP_MAX_GROUP    	12
+#define MV_6530_MPP_MAX_GROUP    	12
+#define MV_6550_MPP_MAX_GROUP    	12
+#define MV_6560_MPP_MAX_GROUP    	12
+#define MV_65XX_MPP_MAX_GROUP		12
+#define MV_6601_MPP_MAX_GROUP    	5
+
+#define MV_DRAM_MAX_CS      		4
+#define MV_SPI_MAX_CS			8
+/* This define describes the maximum number of supported PCI\PCIX Interfaces*/
+#define MV_PCI_MAX_IF		0
+#define MV_PCI_START_IF		0
+
+/* This define describes the maximum number of supported PEX Interfaces 	*/
+#define MV_INCLUDE_PEX0
+#define MV_DISABLE_PEX_DEVICE_BAR
+#define MV_PEX_MAX_IF			2
+#define MV_PEX_MAX_IF_6510		0
+#define MV_PEX_START_IF			MV_PCI_MAX_IF
+
+/* This define describes the maximum number of supported PCI Interfaces 	*/
+#define MV_PCI_IF_MAX_IF		(MV_PEX_MAX_IF + MV_PCI_MAX_IF)
+
+#define MV_IDMA_MAX_CHAN    		0
+
+#define MV_USB_6510_6530_MAX_PORTS	0
+#define MV_USB_MAX_PORTS		1
+
+#define MV_65XX_NAND			1
+
+#define MV_6510_6530_SDIO		0
+#define MV_6550_6560_SDIO		1
+
+#define MV_65XX_TS			0
+
+#define MV_6510_TDM_MAX_PORTS		2
+#define MV_6530_TDM_MAX_PORTS		32
+#define MV_6550_TDM_MAX_PORTS		8
+#define MV_6560_TDM_MAX_PORTS		8
+#define MV_6601_TDM_MAX_PORTS		2
+#define MV_65XX_TDM			1
+
+#define MV_DEVICE_MAX_CS      		4
+
+/* Others */
+#define PEX_HOST_BUS_NUM(pciIf)		(pciIf)
+#define PEX_HOST_DEV_NUM(pciIf)		0
+
+#define PCI_IO(pciIf)		((pciIf == 0) ? PEX0_IO : PEX1_IO)
+#define PCI_MEM(pciIf, memNum)  ((pciIf == 0) ? PEX0_MEM0 : PEX1_MEM0)
+
+/* CESA version #3: One channel, 2KB SRAM, TDMA, CHAIN Mode support */
+#define MV_CESA_VERSION                 3
+#define MV_CESA_SRAM_SIZE               (2 * 1024)
+
+#define MV_ETH_VERSION 	                4 /* for Legacy mode */
+#define MV_ETH_MAX_PORTS                3 /* This define describes the maximum number of supported Ethernet ports */
+#define MV_ETH_MAX_RXQ                  8
+#define MV_ETH_MAX_TXQ                  8
+#define MV_ETH_TX_CSUM_MAX_SIZE         1600
+#define MV_PNC_TCAM_LINES               512 /* TCAM num of entries */
+
+#define MV_INCLUDE_ETH_COMPLEX
+
+/* New GMAC module is used */
+#define MV_ETH_GMAC_NEW
+
+/* New WRR/EJP module is used */
+#define MV_ETH_WRR_NEW
+
+/*  L2/3/4 PMT module */
+#define MV_ETH_PMT_NEW
+
+/* New PNC module - extra fields */
+#define MV_ETH_PNC_NEW
+
+/* PNC Aging counters support */
+#define MV_ETH_PNC_AGING
+
+#ifdef CONFIG_MV_PON
+/* Suport MIB counters for PON port */
+#define MV_PON_MIB_SUPPORT
+#endif /* CONFIG_MV_PON */
+
+#define MV_PON_PORT_ID                  2
+#define MV_ETH_PMT_SIZE                 (4*1024) /* PMT entires */
+
+/* This define describes the the support of USB 	*/
+#define MV_USB_VERSION  		1
+
+#define MV_SPI_VERSION			2
+
+#define MV_INCLUDE_SDRAM_CS0
+#define MV_INCLUDE_SDRAM_CS1
+#define MV_INCLUDE_SDRAM_CS2
+#define MV_INCLUDE_SDRAM_CS3
+
+#define MV_INCLUDE_DEVICE_CS0
+#define MV_INCLUDE_DEVICE_CS1
+#define MV_INCLUDE_DEVICE_CS2
+#define MV_INCLUDE_DEVICE_CS3
+
+#define MPP_GROUP_1_MASK {\
+	0xF0FFF000,	0x00FFFFFF,	0x00F00000	\
+}
+
+#define MPP_GROUP_1_TYPE {\
+	{0,		0,		0},		/* Reserved for AUTO */ \
+	{0x20000000,	0x00422222,	0x00000000},	/* TDM_2CH */ \
+	{0x10555000,	0x00111301,	0x00400000},	/* TDM_32CH */ \
+	{0x0,		0x0,		0x0},		/* MAC0 */ \
+	{0x0,		0x0,		0x0},		/* MAC1 */ \
+	{0x0,		0x0,		0x0},		/* SW_P5 */ \
+	{0x0,		0x0,		0x0},		/* SW_P6 */ \
+}
+
+#define MPP_GROUP_2_MASK {\
+	0xFF000000,	0xFFFFFFFF,	0x000FFFFF	\
+}
+#define MPP_GROUP_2_TYPE {\
+	{0,		0,		0},		/* Reserved for AUTO */ \
+	{0x0,		0x0,		0x0},		/* TDM_2CH */ \
+	{0x0,		0x0,		0x00044000},	/* TDM_32CH */ \
+	{0x22000000,	0x22222222,	0x00022222},	/* MAC0 */ \
+	{0x0,		0x0,		0x0},		/* MAC1 */ \
+	{0x0,		0x0,		0x0},		/* SW_P5 */ \
+	{0x0,		0x0,		0x0},		/* SW_P6 */ \
+}
+
+#define MPP_GROUP_3_MASK {\
+	0xFFF00000,	0xFFFFFFFF,	0x00000FFF	\
+}
+#define MPP_GROUP_3_TYPE {\
+	{0, 0, 0},					/* Reserved for AUTO */ \
+	{0x0,		0x0,		0x0},		/* TDM_2CH */ \
+	{0x0,		0x0,		0x0},		/* TDM_32CH */ \
+	{0x22200000,	0x22222222,	0x00000222},	/* MAC0 */ \
+	{0x33300000,	0x33333333,	0x00000333},	/* MAC1 */ \
+	{0x44400000,	0x44444444,	0x00000444},	/* SW_P5 */ \
+	{0x88800000,	0x88888888,	0x00000888},	/* SW_P6 */ \
+}
+
+
+#ifndef MV_ASMLANGUAGE
+
+#define TBL_UNUSED	0	/* Used to mark unused entry */
+
+/* This enumerator defines the Marvell Units ID      */
+typedef enum _mvUnitId {
+	DRAM_UNIT_ID,
+	PEX_UNIT_ID,
+	ETH_GIG_UNIT_ID,
+	USB_UNIT_ID,
+	IDMA_UNIT_ID,
+	XOR_UNIT_ID,
+	SATA_UNIT_ID,
+	TDM_2CH_UNIT_ID,
+	TDM_32CH_UNIT_ID,
+	UART_UNIT_ID,
+	CESA_UNIT_ID,
+	SPI_UNIT_ID,
+	AUDIO_UNIT_ID,
+	SDIO_UNIT_ID,
+	TS_UNIT_ID,
+	XPON_UNIT_ID,
+	BM_UNIT_ID,
+	PNC_UNIT_ID,
+	NFC_UNIT_ID,
+	MAX_UNITS_ID
+} MV_UNIT_ID;
+
+/* This enumerator describes the Marvell controller possible devices that   */
+/* can be connected to its device interface.                                */
+typedef enum _mvDevice {
+#if defined(MV_INCLUDE_DEVICE_CS0)
+	DEV_CS0 = 0,    /* Device connected to dev CS[0]    */
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS1)
+	DEV_CS1 = 1,        /* Device connected to dev CS[1]    */
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS2)
+	DEV_CS2 = 2,        /* Device connected to dev CS[2]    */
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS3)
+	DEV_CS3 = 3,        /* Device connected to dev CS[2]    */
+#endif
+	BOOT_CS,        /* Device connected to BOOT dev    */
+	MV_DEV_MAX_CS = MV_DEVICE_MAX_CS
+} MV_DEVICE;
+
+/* This enumerator described the possible Controller paripheral targets.    */
+/* Controller peripherals are designated memory/IO address spaces that the  */
+/* controller can access. They are also refered as "targets"                */
+typedef enum _mvTarget {
+	TBL_TERM = -1, 	/* none valid target, used as targets list terminator*/
+	SDRAM_CS0,	/* SDRAM chip select 0		*/
+	SDRAM_CS1,	/* SDRAM chip select 1		*/
+	SDRAM_CS2,	/* SDRAM chip select 2		*/
+	SDRAM_CS3,	/* SDRAM chip select 3		*/
+	DEVICE_CS0,	/* Device chip select 0		*/
+	DEVICE_CS1,	/* Device chip select 1		*/
+	DEVICE_CS2,	/* Device chip select 2		*/
+	DEVICE_CS3,	/* Device chip select 3		*/
+	PEX0_MEM,	/* PCI Express 0 Memory		*/
+	PEX0_IO,	/* PCI Express 0 IO		*/
+	PEX1_MEM,	/* PCI Express 1 Memory		*/
+	PEX1_IO,	/* PCI Express 1 IO		*/
+	INTER_REGS,	/* Internal registers		*/
+	NAND_NOR_CS,	/* NAND_NOR_CS			*/
+	SPI_CS0,	/* SPI_CS0			*/
+	SPI_CS1,	/* SPI_CS1			*/
+	SPI_CS2,	/* SPI_CS2			*/
+	SPI_CS3,	/* SPI_CS3			*/
+	SPI_CS4,	/* SPI_CS4			*/
+	SPI_CS5,	/* SPI_CS5			*/
+	SPI_CS6,	/* SPI_CS6			*/
+	SPI_CS7,	/* SPI_CS7			*/
+	SPI_B_CS0,	/* SPI_B_CS0			*/
+	BOOT_ROM_CS,	/* BOOT_ROM_CS			*/
+	DEV_BOOCS,	/* DEV_BOOCS			*/
+	CRYPT1_ENG,	/* Crypto1 Engine		*/
+	CRYPT2_ENG,	/* Crypto2 Engine		*/
+	PNC_BM,	        /* PNC + BM 		        */
+	ETH_CTRL,	/* ETH Controller		*/
+	PON_CTRL,	/* PON Controller		*/
+	NFC_CTRL,	/* NAND flash controller	*/
+	MAX_TARGETS
+} MV_TARGET;
+
+#define TARGETS_DEF_ARRAY	{			\
+	{0x0E, DRAM_TARGET_ID }, /* SDRAM_CS0 */	\
+	{0x0D, DRAM_TARGET_ID }, /* SDRAM_CS1 */	\
+	{0x0B, DRAM_TARGET_ID }, /* SDRAM_CS0 */	\
+	{0x07, DRAM_TARGET_ID }, /* SDRAM_CS1 */	\
+	{0x3E, DEV_TARGET_ID},   /* DEVICE_CS0 */	\
+	{0x3D, DEV_TARGET_ID},   /* DEVICE_CS1 */	\
+	{0x3D, DEV_TARGET_ID},   /* DEVICE_CS2 */	\
+	{0x3D, DEV_TARGET_ID},   /* DEVICE_CS3 */	\
+	{0xE8, PEX0_TARGET_ID }, /* PEX0_MEM */		\
+	{0xE0, PEX0_TARGET_ID }, /* PEX0_IO */		\
+	{0xD8, PEX0_TARGET_ID }, /* PEX1_MEM */		\
+	{0xD0, PEX0_TARGET_ID }, /* PEX1_IO */		\
+	{0xFF, 0xFF           }, /* INTER_REGS */	\
+	{0x2F, DEV_TARGET_ID  }, /* NAND_NOR_CS */	\
+	{0x1E, DEV_TARGET_ID  }, /* SPI_CS0 */		\
+	{0x5E, DEV_TARGET_ID  }, /* SPI_CS1 */		\
+	{0x9E, DEV_TARGET_ID  }, /* SPI_CS2 */		\
+	{0xDE, DEV_TARGET_ID  }, /* SPI_CS3 */		\
+	{0x1F, DEV_TARGET_ID  }, /* SPI_CS4 */		\
+	{0x5F, DEV_TARGET_ID  }, /* SPI_CS5 */		\
+	{0x9F, DEV_TARGET_ID  }, /* SPI_CS6 */		\
+	{0xDF, DEV_TARGET_ID  }, /* SPI_CS7 */		\
+	{0x1A, DEV_TARGET_ID},	 /* SPI_B_CS0 */	\
+	{0x1D, DEV_TARGET_ID  }, /* BOOT_ROM_CS */	\
+	{0x1E, DEV_TARGET_ID  }, /* DEV_BOOCS */	\
+	{0x01, CRYPT_TARGET_ID}, /* CRYPT1_ENG */	\
+	{0x05, CRYPT_TARGET_ID}, /* CRYPT2_ENG */	\
+	{0x00, PNC_BM_TARGET_ID},/* PNC_BM */		\
+	{0x00, ETH_TARGET_ID},	 /* ETH */		\
+	{0x00, PON_TARGET_ID},	 /* PON */		\
+	{0x00, NFC_TARGET_ID},	 /* NFC */		\
+}
+
+
+#define TARGETS_NAME_ARRAY	{		\
+	"SDRAM_CS0",    /* SDRAM_CS0 */		\
+	"SDRAM_CS1",    /* SDRAM_CS1 */		\
+	"SDRAM_CS2",    /* SDRAM_CS1 */		\
+	"SDRAM_CS3",    /* SDRAM_CS1 */		\
+	"DEVICE_CS0",	/* DEVICE_CS0 */	\
+	"DEVICE_CS1",	/* DEVICE_CS1 */	\
+	"DEVICE_CS2",	/* DEVICE_CS2 */	\
+	"DEVICE_CS3",	/* DEVICE_CS3 */	\
+	"PEX0_MEM",	/* PEX0_MEM */		\
+	"PEX0_IO",	/* PEX0_IO */		\
+	"PEX1_MEM",	/* PEX1_MEM */		\
+	"PEX1_IO",	/* PEX1_IO */		\
+	"INTER_REGS",	/* INTER_REGS */	\
+	"NAND_NOR_CS",	/* NAND_NOR_CS */	\
+	"SPI_CS0",	/* SPI_CS0 */		\
+	"SPI_CS1",	/* SPI_CS1 */		\
+	"SPI_CS2",	/* SPI_CS2 */		\
+	"SPI_CS3",	/* SPI_CS3 */		\
+	"SPI_CS4",	/* SPI_CS4 */		\
+	"SPI_CS5",	/* SPI_CS5 */		\
+	"SPI_CS6",	/* SPI_CS6 */		\
+	"SPI_CS7",	/* SPI_CS7 */		\
+	"SPI_B_CS0",	/* SPI_B_CS0 */		\
+	"BOOT_ROM_CS",	/* BOOT_ROM_CS */	\
+	"DEV_BOOTCS",	/* DEV_BOOCS */		\
+	"CRYPT1_ENG",	/* CRYPT1_ENG */	\
+	"CRYPT2_ENG",	/* CRYPT2_ENG */	\
+	"PNC_BM",	/* PNC_BM */		\
+	"ETH_CTRL",	/* ETH_CTRL */		\
+	"PON_CTRL",	/* PON_CTRL */		\
+	"NFC_CTRL",	/* NFC_CTRL */		\
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCmvCtrlEnvSpech */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEthCompLib.c b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEthCompLib.c
new file mode 100755
index 0000000..dc7c5b6
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEthCompLib.c
@@ -0,0 +1,1668 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <mvCommon.h>
+#include <mvOs.h>
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ctrlEnv/mvCtrlEthCompLib.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "neta/gbe/mvEthRegs.h"
+
+static MV_STATUS mvEthCompSerdesConfig(MV_U32 ethCompCfg);
+static void mvEthCompSerdesRegWrite(MV_U32 regaddr, MV_U16 value);
+static MV_U16 mvEthCompSerdesRegRead(MV_U32 regaddr);
+
+static MV_BOOL gEthComplexSkipInit = MV_FALSE;
+
+typedef struct {
+	MV_U32 reg;
+	MV_U16 val;
+	MV_U16 mask;
+} MV_SERDES_CFG;
+
+static MV_SERDES_CFG serdesDefVal[] = {
+	{0x22, 0x1046, 0xFFFF},
+	{0x01, 0xF803, 0xFEFF},
+	{0x02, 0x0140, 0x83F0},
+	{0x03, 0x3600, 0xFF0F},
+	{0x04, 0x600C, 0xF0FF},
+	{0x05, 0x0000, 0xFFFF},
+	{0x06, 0x3377, 0xBFFF},
+	{0x07, 0x0200, 0xFFFF},
+	{0x0D, 0xC958, 0xFFFF},
+	{0x0E, 0x9000, 0xFFFF},
+	{0x0F, 0xAA62, 0xFFFF},
+	{0x10, 0x9000, 0xFFFF},
+	{0x11, 0x0BEB, 0xFFFF},
+	{0x12, 0x9055, 0xFFFF},
+	{0x13, 0x0BEB, 0xFFFF},
+	{0x14, 0x5055, 0xFFFF},
+	{0x15, 0x0000, 0xCFFF},
+	{0x16, 0x0000, 0xFFFF},
+	{0x17, 0x0000, 0xFFFF},
+	{0x18, 0x0000, 0xFFFF},
+	{0x19, 0x0000, 0xFFFF},
+	{0x1A, 0x0000, 0xFFFF},
+	{0x1B, 0x0000, 0xFFFF},
+	{0x1C, 0x0000, 0x0000},
+	{0x1D, 0x0000, 0x0000},
+	{0x1E, 0x0000, 0x0000},
+	{0x1F, 0x0000, 0x0000},
+	{0x20, 0x0000, 0x0000},
+	{0x21, 0x0030, 0xFFFF},
+	{0x23, 0x0800, 0xFFFF},
+	{0x24, 0x4243, 0xDFFF},
+	{0x25, 0x03FF, 0xFFFF},
+	{0x26, 0x0100, 0xFFFF},
+	{0x27, 0x0519, 0xFFFF},
+	{0x28, 0x5502, 0xFFFF},
+	{0x29, 0x5555, 0xFFFF},
+	{0x3A, 0x0000, 0xFFFF},
+	{0x4D, 0x2195, 0xFFFF},
+	{0x4F, 0x6000, 0xFBFF},
+	{0x50, 0x0040, 0xFFFF},
+	{0x51, 0x0280, 0xFFFF},
+	{0x51, 0x0280, 0xFFFF},
+	{0x52, 0xE008, 0xFFFF},
+	{0x53, 0x24B1, 0xFFFF},
+	{0x54, 0x0045, 0xFFFF},
+	{0x55, 0x4100, 0xCFFF},
+	{0x56, 0x0000, 0xFF0C},
+	{0x57, 0x0000, 0xFFE0},
+	{0x58, 0xB200, 0xFFE0},
+	{0x59, 0x0000, 0xFFE0},
+	{0x5A, 0x3000, 0x7F8F},
+	{0x5B, 0x0000, 0xFFE0},
+	{0x60, 0x0180, 0xFFF0},
+	{0x61, 0x0000, 0x0040},
+	{0x62, 0x0500, 0x8FFF},
+	{0x63, 0xFC00, 0xFFFF},
+	{0x64, 0x0150, 0xFFFF},
+	{0x65, 0x0280, 0xFFFF},
+	{0x66, 0x2400, 0xFFFF},
+	{0x67, 0x000F, 0xFFFF},
+	{0x68, 0x0466, 0xFFFF},
+	{0x69, 0x2860, 0xFFFF},
+	{0x6A, 0x00F0, 0xFFFF},
+	{0x6B, 0x0000, 0xD800},
+	{0x6C, 0x0000, 0xFFFF},
+	{0x6D, 0x1400, 0x7FFF},
+	{0x75, 0x0080, 0x00FF},
+	{0x79, 0x0000, 0xFFFF},
+	{0x7A, 0x0000, 0x0000},
+	{0x7B, 0x0000, 0xFFFF},
+	{0x7C, 0x0000, 0xFFFF},
+	{0x7D, 0x0000, 0xFFFF},
+	{0x7E, 0x0022, 0xFFFF},
+	{0x7F, 0x0000, 0x00FF}
+};
+
+static void mvEthCompSetSerdesDefaults(void)
+{
+	MV_U32 i;
+	MV_U32 size = sizeof(serdesDefVal) / sizeof(serdesDefVal[0]);
+	MV_SERDES_CFG *srdsCfg;
+	MV_U16 val;
+
+	for (i = 0; i < size; i++) {
+		srdsCfg = &serdesDefVal[i];
+		if (srdsCfg->mask == 0x0)
+			continue;
+		val = mvEthCompSerdesRegRead(srdsCfg->reg);
+		val &= ~srdsCfg->mask;
+		val |= srdsCfg->val;
+		mvEthCompSerdesRegWrite(srdsCfg->reg, val);
+	}
+	return;
+}
+
+/******************************************************************************
+* mvEthCompSkipInitSet
+*
+* DESCRIPTION:
+*	Configure the eth-complex to skip initialization.
+*
+* INPUT:
+*	skip - MV_TRUE to skip initialization.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	None.
+*******************************************************************************/
+void mvEthCompSkipInitSet(MV_BOOL skip)
+{
+	gEthComplexSkipInit = skip;
+	return;
+}
+
+/******************************************************************************
+* mvEthCompMac2SwitchConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for MAC0/1 to switch ports 5/6 mode.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*	muxCfgOnly - MV_TRUE: Configure only the ethernet complex mux'es and
+*		     skip other switch reset configurations.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompMac2SwitchConfig(MV_U32 ethCompCfg, MV_BOOL muxCfgOnly)
+{
+	MV_U32 reg, portEnabled = 0;
+
+	if (!(ethCompCfg & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5)))
+		return MV_OK;
+
+	/* GbE-MAC-0 to Switch P4 (1000Mbps)    */
+	/* GbE-MAC-1 to Switch P5 (1000Mbps)    */
+
+	/* Force switch reset to load updated configuration */
+	if (MV_REG_READ(MV_ETHCOMP_CTRL_REG(1)) & ETHCC_SWTCH_RESET_MASK) {
+		MV_REG_BIT_RESET(MV_ETHCOMP_CTRL_REG(1), ETHCC_SWTCH_RESET_MASK);
+		mvOsDelay(10);
+	}
+
+	if (muxCfgOnly == MV_FALSE) {
+		/* Set switch phy address */
+		reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(1));
+		reg &= ~ETHCC_SWTCH_ADDR_MASK;
+		if (ethCompCfg & ESC_OPT_MAC0_2_SW_P4)
+			reg |= (mvBoardPhyAddrGet(0) << ETHCC_SWTCH_ADDR_OFFSET);
+		else
+			reg |= (mvBoardPhyAddrGet(1) << ETHCC_SWTCH_ADDR_OFFSET);
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(1), reg);
+
+		/*
+		 * 3.1.2. Switch power-on configurations:
+		 * 3.1.2.1. Activate Switch ports 1-6 (1 bit per port): set Regunit
+		 * Ethernet_Complex_Control_2 register, field SwitchPortState, to 0x7E.
+		 */
+		reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(2));
+		reg &= ~ETHCC_SW_PRT_STATE_MASK;
+
+		if (ethCompCfg & ESC_OPT_RGMIIA_SW_P5)
+			portEnabled |= BIT5;
+		if (ethCompCfg & ESC_OPT_RGMIIA_SW_P6)
+			portEnabled |= BIT6;
+		if (ethCompCfg & ESC_OPT_MAC0_2_SW_P4)
+			portEnabled |= BIT4;
+		if (ethCompCfg & ESC_OPT_MAC1_2_SW_P5)
+			portEnabled |= BIT5;
+		if (ethCompCfg & ESC_OPT_GEPHY_SW_P0)
+			portEnabled |= BIT0;
+		if (ethCompCfg & ESC_OPT_GEPHY_SW_P5)
+			portEnabled |= BIT5;
+		if (ethCompCfg & ESC_OPT_FE3PHY)
+			portEnabled |= BIT1 | BIT2 | BIT3;
+		if (ethCompCfg & ESC_OPT_QSGMII)
+			portEnabled |= BIT0 | BIT1 | BIT2 | BIT3;
+		if (ethCompCfg & ESC_OPT_SGMII_2_SW_P1)
+			portEnabled |= BIT1; 
+		portEnabled |= BIT4 | BIT5;
+
+		reg |= (portEnabled << ETHCC_SW_PRT_STATE_OFFSET);	/* 0x7E */
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(2), reg);
+
+		/* 3.1.3. Ethernet-Complex configuration:
+		 * 3.1.3.1. Configure Switch 125Mhz clock source: set
+		 * Regunit Ethernet_Complex_Control_0 register, field SwFi125ClkSrc to
+		 * MiscPLL (0x1).
+		 */
+		MV_REG_BIT_RESET(MV_ETHCOMP_CTRL_REG(0), ETHCC_SW_FI_125_CLK_MASK);
+		MV_REG_BIT_SET(MV_ETHCOMP_CTRL_REG(0), (1 << ETHCC_SW_FI_125_CLK_OFFSET));
+	}
+
+	/* 3.1.3.2. Configure G-0 connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field Gport0Source to
+	 * "SwitchPort6" (0x1).
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+	if (ethCompCfg & ESC_OPT_MAC0_2_SW_P4) {
+		reg &= ~ETHCC_GPORT_0_SRC_MASK;
+		reg |= (0x1 << ETHCC_GPORT_0_SRC_OFFSET);
+	}
+
+	/* 3.2.3.2. Configure G-1 connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field Gport1Source to
+	 * SwitchPort5" (0x1).
+	 */
+	if (ethCompCfg & ESC_OPT_MAC1_2_SW_P5) {
+		reg &= ~ETHCC_GPORT_1_SRC_MASK;
+		reg |= (0x1 << ETHCC_GPORT_1_SRC_OFFSET);
+	}
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	/* 3.2.3.3. Configure Switch P5 connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field SwitchPort5Source to
+	 * "Gport1" (0x1).
+	 */
+	if (ethCompCfg & ESC_OPT_MAC1_2_SW_P5) {
+		reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+		reg &= ~ETHCC_SW_PORT_5_SRC_MASK;
+		reg |= (0x1 << ETHCC_SW_PORT_5_SRC_OFFSET);
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+	}
+
+	/* 3.1.4.2. Wait for Switch, Switch Global Status Register, field
+	 * EEInt to be set to 0x1.
+	 */
+	mvOsDelay(100);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSwitchReset
+*
+* DESCRIPTION:
+*	Reset switch device after being configured by ethernet complex functions.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompSwitchReset(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+	MV_U32 i;
+
+	if (!(ethCompCfg & (ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5))) {
+		/* If no switch is connected, then we need to enable the 25MHz
+		 ** clock, and get the switch out of reset
+		 */
+
+		/* Set switch phy address so it does not collide with other
+		 ** addresses.
+		 */
+		reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(1));
+		reg &= ~ETHCC_SWTCH_ADDR_MASK;
+		reg |= (0xF << ETHCC_SWTCH_ADDR_OFFSET);
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(1), reg);
+		MV_REG_BIT_SET(MV_ETHCOMP_CTRL_REG(0), (1 << ETHCC_SW_FI_125_CLK_OFFSET));
+		MV_REG_BIT_SET(MV_ETHCOMP_CTRL_REG(1), ETHCC_SWTCH_RESET_MASK);
+		return MV_OK;
+	}
+
+	/* Disable polling on MAC ports. */
+	if (ethCompCfg & ESC_OPT_MAC0_2_SW_P4)
+		MV_REG_BIT_RESET(ETH_UNIT_CONTROL_REG(0), BIT1);
+	if (ethCompCfg & ESC_OPT_MAC1_2_SW_P5)
+		MV_REG_BIT_RESET(ETH_UNIT_CONTROL_REG(1), BIT1);
+
+	/*
+	 * 3.1.4. Reset de-assertion:
+	 * 3.1.4.1. De-assert Switch reset: set Regunit
+	 * Ethernet_Complex_Control_1 register, field SwitchReset to 0x1.
+	 */
+	MV_REG_BIT_SET(MV_ETHCOMP_CTRL_REG(1), ETHCC_SWTCH_RESET_MASK);
+
+#warning "Fix this to poll the Switch EEInt after reset"
+	mvOsDelay(100);
+
+	/* 10Mbps support */
+	for (i = 1; i < 4; i++) {
+		reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(3));
+		reg |= ETHCC_SW_PX_FRC_MII_SPD_MASK(i);
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(3), reg);
+		mvOsDelay(1);
+		reg |= ETHCC_SW_PX_FRC_SPD_MASK(i);
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(3), reg);
+		mvOsDelay(1);
+		reg &= ~ETHCC_SW_PX_FRC_MII_SPD_MASK(i);
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(3), reg);
+		mvOsDelay(1);
+		reg &= ~ETHCC_SW_PX_FRC_SPD_MASK(i);
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(3), reg);
+		mvOsDelay(1);
+	}
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompMac2RgmiiConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for MAC0/1 to RGMII output.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompMac2RgmiiConfig(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+
+	/* 3.3. GbE-MAC-0/1 to MII (10Mbps/ 100 Mbps) or RGMII
+	 * (10Mbps/ 100Mbps/ 1000Mbps).
+	 */
+
+	/* 3.3.2. Ethernet-Complex configuration:
+	 * 3.3.2.1. Configure G-0/1 connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field Gport1Source or
+	 * Gport0Source to "ExtRGMIIA/B" (0x0).
+	 */
+	if (mvBoardIsPortInRgmii(0)) {
+		reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+		reg &= ~ETHCC_GPORT_0_SRC_MASK;
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+	}
+
+	if (mvBoardIsPortInRgmii(1)) {
+		reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+		reg &= ~ETHCC_GPORT_1_SRC_MASK;
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+	}
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompMac0ToGePhyConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for MAC0 to integrated GE PHY mode.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*	smiAddr - SMI address to assign for the integrated GE phy.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompMac0ToGePhyConfig(MV_U32 ethCompCfg, MV_U32 smiAddr)
+{
+	MV_U32 reg;
+
+	if (!(ethCompCfg & ESC_OPT_GEPHY_MAC0))
+		return MV_OK;
+
+	/* Ethernet-Complex configuration:
+	 * Configure LpPhyMode: set Regunit
+	 * Ethernet_Complex_Control_0 register, field LpPhyMode to 0x1.
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+	reg &= ~ETHCC_LPPHYMODE_MASK;
+	reg |= (0x1 << ETHCC_LPPHYMODE_OFFSET);
+
+	/* Configure GbE-Phy SMI address: set Regunit
+	 * Ethernet_Complex_Control_0 register, field GbEPhySMIAddress, to
+	 * the selected GbE-PHY SMI address.
+	 */
+	reg &= ~ETHCC_GBE_PHY_SMI_ADD_MASK;
+	reg |= (smiAddr << ETHCC_GBE_PHY_SMI_ADD_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	/* 3.4.3. Power-on configurations:
+	 * 3.4.3.1. Configure GbE-PHY capabilities to advertise: set Regunit
+	 * GbE Phy Control register, field ConfAnegAdvertise to 0x3.
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_GE_PHY_CTRL_REG);
+	reg &= ~PHYCTRL_CFG_ANEG_ADV_MASK;
+	reg |= (0x3 << PHYCTRL_CFG_ANEG_ADV_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_GE_PHY_CTRL_REG, reg);
+
+	reg = MV_REG_READ(MV_ETHCOMP_GE_PHY_CTRL1_REG);
+	reg |= PHYCTRL_PS_ENA_XC_A_MASK;
+	MV_REG_WRITE(MV_ETHCOMP_GE_PHY_CTRL1_REG, reg);
+
+#if 0
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(3));
+	reg &= ~ETHCC_GEPHY_TX_DATA_SMPL_MASK;
+	reg |= (0x2 << ETHCC_GEPHY_TX_DATA_SMPL_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(3), reg);
+#endif
+	/* Reset de-assertion:
+	 * De-assert GbE-PHY reset: set Regunit GbE Phy Control
+	 * register, field Reset to 0x1.
+	 */
+	MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_DPLL_RESET_MASK);
+	MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_RESET_MASK);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompMac1ToGePhyConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for MAC1 to integrated GE PHY mode.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*	smiAddr - SMI address to assign for the integrated GE phy.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompMac1ToGePhyConfig(MV_U32 ethCompCfg, MV_U32 smiAddr)
+{
+	MV_U32 reg;
+
+	if (!(ethCompCfg & ESC_OPT_GEPHY_MAC1))
+		return MV_OK;
+
+	/* 3.4. GPHY to GbE-MAC-1 (10Mbps/ 100Mbps/ 1000Mbps)
+	 * Select a unique SMI address (0x0-0x1F, excluding 0x7, 0x8) for the
+	 * GbE-PHY.
+	 */
+
+	/* 3.4.2. Ethernet-Complex configuration:
+	 * 3.4.2.1. Configure G-1 connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field Gport1Source to 0x0.
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+	reg &= ~ETHCC_GPORT_1_SRC_MASK;
+	reg |= (0x2 << ETHCC_GPORT_1_SRC_OFFSET);
+
+	/* 3.4.2.2. Configure GbE-PHY connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field GePhySource to "Gport1 " (0x1).
+	 */
+	reg &= ~ETHCC_BGE_PHY_SRC_MASK;
+	reg |= (0x1 << ETHCC_BGE_PHY_SRC_OFFSET);
+
+	/* 3.4.2.3. Configure GbE-Phy SMI master: set Regunit
+	 * Ethernet_Complex_Control_0 register, field GePhySmiSource to "Gport0 " (0x1).
+	 */
+	reg &= ~ETHCC_GBE_PHY_SMI_SRC_MASK;
+	reg |= (0x1 << ETHCC_GBE_PHY_SMI_SRC_OFFSET);
+
+	/* 3.4.2.4. Configure GbE-Phy SMI address: set Regunit
+	 * Ethernet_Complex_Control_0 register, field GbEPhySMIAddress, to
+	 * the selected GbE-PHY SMI address.
+	 */
+	reg &= ~ETHCC_GBE_PHY_SMI_ADD_MASK;
+	reg |= (smiAddr << ETHCC_GBE_PHY_SMI_ADD_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	/* 3.4.3. Power-on configurations:
+	 * 3.4.3.1. Configure GbE-PHY capabilities to advertise: set Regunit
+	 * GbE Phy Control register, field ConfAnegAdvertise to 0x3.
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_GE_PHY_CTRL_REG);
+	reg &= ~PHYCTRL_CFG_ANEG_ADV_MASK;
+	reg |= (0x3 << PHYCTRL_CFG_ANEG_ADV_OFFSET);
+	reg |= PHYCTRL_XOVER_EN_MASK;
+	MV_REG_WRITE(MV_ETHCOMP_GE_PHY_CTRL_REG, reg);
+#if 0
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(3));
+	reg &= ~ETHCC_GEPHY_TX_DATA_SMPL_MASK;
+	reg |= (0x2 << ETHCC_GEPHY_TX_DATA_SMPL_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(3), reg);
+#endif
+	/* 3.4.4. Reset de-assertion:
+	 * 3.4.4.1. De-assert GbE-PHY reset: set Regunit GbE Phy Control
+	 * register, field Reset to 0x1.
+	 */
+	MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_DPLL_RESET_MASK);
+	MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_RESET_MASK);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSwP05ToGePhyConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for Switch port 4/5 to integrated GE PHY.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompSwP05ToGePhyConfig(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+	MV_U32 smiAddr = 0;
+
+	if (!(ethCompCfg & (ESC_OPT_GEPHY_SW_P0 | ESC_OPT_GEPHY_SW_P5)))
+		return MV_OK;
+
+	/* 3.5. GPHY to Switch P4/P5 (10Mbps/ 100Mbps/ 1000Mbps) */
+	/* Select a unique SMI address (0x0-0x1F, excluding 0x7, 0x8) for the
+	 * GbE-PHY.
+	 */
+
+	/* 3.5.2.2. Configure Switch P5/P4 connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field
+	 * "SwitchPort4Source"/" SwitchPort5Source" to GbEPHY (0x2).
+	 * 3.5.2.3. Configure GbE-PHY connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field GePhySource to
+	 * SwitchPort4 (0x2) or SwitchPort5 (0x0).
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+	if (ethCompCfg & ESC_OPT_GEPHY_SW_P0) {
+		reg &= ~ETHCC_SW_PORT_0_SRC_MASK;
+		reg |= (0x2 << ETHCC_SW_PORT_0_SRC_OFFSET);
+		reg &= ~ETHCC_BGE_PHY_SRC_MASK;
+		reg |= (0x2 << ETHCC_BGE_PHY_SRC_OFFSET);
+		smiAddr = 0x0;
+	}
+	if (ethCompCfg & ESC_OPT_GEPHY_SW_P5) {
+		reg &= ~ETHCC_SW_PORT_5_SRC_MASK;
+		reg |= (0x2 << ETHCC_SW_PORT_5_SRC_OFFSET);
+		reg &= ~ETHCC_BGE_PHY_SRC_MASK;
+		reg |= (0x0 << ETHCC_BGE_PHY_SRC_OFFSET);
+		smiAddr = 0x5;
+	}
+
+	/* 3.5.2.4. Configure GbE-Phy SMI master: set Regunit
+	 * Ethernet_Complex_Control_0 register, field GePhySmiSource to
+	 * Switch (0x0).
+	 */
+	reg &= ~ETHCC_GBE_PHY_SMI_SRC_MASK;
+
+	/* 3.5.2.5. Configure GbE-Phy SMI address: set Regunit
+	 * Ethernet_Complex_Control_0 register, field GbEPhySMIAddress, to
+	 * the selected GbE-PHY SMI address.
+	 */
+	reg &= ~ETHCC_GBE_PHY_SMI_ADD_MASK;
+	reg |= (smiAddr << ETHCC_GBE_PHY_SMI_ADD_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	reg = MV_REG_READ(MV_ETHCOMP_GE_PHY_CTRL_REG);
+	reg &= ~PHYCTRL_CFG_ANEG_ADV_MASK;
+	reg |= (0x3 << PHYCTRL_CFG_ANEG_ADV_OFFSET);
+	reg |= PHYCTRL_XOVER_EN_MASK;
+	MV_REG_WRITE(MV_ETHCOMP_GE_PHY_CTRL_REG, reg);
+#if 0
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(3));
+	reg &= ~ETHCC_GEPHY_TX_DATA_SMPL_MASK;
+	reg |= (0x2 << ETHCC_GEPHY_TX_DATA_SMPL_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(3), reg);
+#endif
+	/* 3.5.3.2. De-assert GbE-PHY reset: set Regunit GbE Phy Control
+	 * register, field Reset to 0x1.
+	 */
+	MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_DPLL_RESET_MASK);
+	MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_RESET_MASK);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSwP56ToRgmiiConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for Switch port 5 or 6 to RGMII output.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompSwP56ToRgmiiConfig(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+	MV_U32 portMode;
+
+	if (!(ethCompCfg & (ESC_OPT_RGMIIA_SW_P5 | ESC_OPT_RGMIIA_SW_P6)))
+		return MV_OK;
+
+	portMode = mvBoardEthPortsModeGet();
+
+	/* 3.6. Switch P5 to MII (10Mbps/ 100 Mbps) or RGMII (10Mbps/
+	 * 100Mbps/ 1000Mbps)
+	 */
+
+	/* 3.6.3. Ethernet-Complex configuration:
+	 * 3.6.3.2. Configure Switch P5 connection: set Regunit
+	 * Ethernet_Complex_Control_0 register, field SwitchPort5Source to
+	 * "ExtRGMIIB" (0x0).
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+	if (ethCompCfg & ESC_OPT_RGMIIA_SW_P5)
+		reg &= ~ETHCC_SW_PORT_5_SRC_MASK;
+
+	/* 3.6.3.3. Configure MII mode or RGMII mode: set Regunit
+	 * Ethernet_Complex_Control_0 register, field SwitchPort5MppMode,
+	 * to RGMII (0x0) or MII (0x1).
+	 */
+	if (ethCompCfg & ESC_OPT_RGMIIA_SW_P5) {
+		if (portMode & EPM_SW_PORT_5_MII)
+			reg |= ETHCC_SW_PORT5_MPP_MASK;
+		else
+			reg &= ~ETHCC_SW_PORT5_MPP_MASK;
+	} else if (ethCompCfg & ESC_OPT_RGMIIA_SW_P6) {
+		if (portMode & EPM_SW_PORT_6_MII)
+			reg |= ETHCC_SW_PORT6_MPP_MASK;
+		else
+			reg &= ~ETHCC_SW_PORT6_MPP_MASK;
+	}
+
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(1));
+	if (ethCompCfg & ESC_OPT_RGMIIA_SW_P5) {
+		reg &= ~ETHCC_SWTCH_P5_MODE_MASK;
+		if (portMode & EPM_SW_PORT_5_MII)
+			reg |= (2 << ETHCC_SWTCH_P5_MODE_OFFSET);
+	} else if (ethCompCfg & ESC_OPT_RGMIIA_SW_P6) {
+		reg &= ~ETHCC_SWTCH_P6_MODE_MASK;
+		if (portMode & EPM_SW_PORT_6_MII)
+			reg |= (2 << ETHCC_SWTCH_P6_MODE_OFFSET);
+	}
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(1), reg);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSwTo3FePhyConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for Switch ports 1-4 to 3xFE output.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompSwTo3FePhyConfig(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+	MV_U32 i;
+
+	if (!(ethCompCfg & ESC_OPT_FE3PHY))
+		return MV_OK;
+
+	/* 3.7. Switch P1,2 & 3 to FE-PHY (10Mbps/ 100 Mbps) */
+	/* 3.7.2. Ethernet-Complex configuration :
+	 * 3.7.2.2. Connect Switch ports 1,2 & 3 to FE-PPHY ports 0,1 & 2: set
+	 * Regunit Ethernet_Complex_Control_0 register, field
+	 * SwitchPort123Source to "FEPHY" (0x1).
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+	reg &= ~ETHCC_SW_PORT_123_SRC_MASK;
+	reg |= (0x1 << ETHCC_SW_PORT_123_SRC_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	/* 3.7.2.3. Enable Switch and FE-PHY TX clock, by setting speed to 25MHz
+	 * (this is needed due to design bug): set Regunit Ethernet Complex
+	 * Control 3 register, fields "SwPort1ForceSpeed",
+	 * "SwPort1ForceMiiSpeed", "SwPort2ForceSpeed", "SwPort2ForceMiiSpeed",
+	 * "SwPort3ForceSpeed" and  "SwPort3ForceMiiSpeed" to force MII-100,
+	 * i.e. 25MHz TX clock. All these fields should be set to 0x1.
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(3));
+	for (i = 1; i < 4; i++) {
+		reg &= ~ETHCC_SW_PX_FRC_SPD_MASK(i);
+/* 		reg |= ETHCC_SW_PX_FRC_MII_SPD_MASK(i); */
+	}
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(3), reg);
+
+	/* 3.7.3. Reset de-assertion:
+	 * 3.7.3.1. De-assert F-PHY reset: set Regunit FE PHY Control 0
+	 * register, field "fe_phy_pd_reset_a" to Normal mode (0x1).
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_FE_PHY_CTRL_REG);
+	for (i = 0; i < 3; i++)
+		reg |= (0x3 << ETHCC_FE_PHY_AN_MODE_OFFSET(i));
+
+	MV_REG_BIT_RESET(MV_ETHCOMP_CTRL_REG(3), ETHCC_FEPHY_TX_DATA_SMPL_MASK);
+
+	/* Enable FE Phy Crossover */
+	reg |= (0x1 << ETHCC_FE_PHY_XOVER_EN_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_FE_PHY_CTRL_REG, reg);
+
+	MV_REG_BIT_RESET(MV_ETHCOMP_FE_PHY_CTRL_REG, ETHCC_FE_PHY_RESET_MASK);
+	mvOsDelay(100);
+	MV_REG_BIT_SET(MV_ETHCOMP_FE_PHY_CTRL_REG, ETHCC_FE_PHY_RESET_MASK);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSataConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for sata port output.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompSataConfig(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+	MV_U32 tmp;
+	MV_U16 serdesReg;
+
+	if (!(ethCompCfg & ESC_OPT_SATA))
+		return MV_OK;
+
+	/* 3.8.3. LP_SERDES_PHY initialization:
+	 * 3.8.3.1. Set LP_SERDES to reset: set Regunit Software Reset Control
+	 * register to Reset (0x1).
+	 */
+	MV_REG_BIT_SET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);
+
+	/* 3.8.3.2. De-assert LP_SERDES reset: set Regunit Software Reset
+	 * Control register to 0x0.
+	 */
+	MV_REG_BIT_RESET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);
+
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+
+	/* 3.8.2.4. Connect LP_SERDES_PHY to required source: set Regunit
+	 * Ethernet_Complex_Control_0 register, field "LpphyMode" to "lpphyMode".
+	 */
+	tmp = 0x1;
+
+	reg &= ~ETHCC_LPPHYMODE_MASK;
+	reg |= (tmp << ETHCC_LPPHYMODE_OFFSET);
+	reg |= ETHCC_LP_SERDES_DATA_SWAP_TX_MASK | ETHCC_LP_SERDES_DATA_SWAP_RX_MASK;
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	mvEthCompSetSerdesDefaults();
+
+	/* 3.8.3.3. Power up LP_SERDES: set Gunit Serdes Configuration
+	 * (SERDESCFG) register, fields "PU_TX", "PU_RX, "PU_PLL" (bits 1,2,3)
+	 * to Enable (0x1)
+	 */
+	reg = MV_REG_READ(MV_SATACOMP_SERDESCFG_REG);
+	reg &= ~SERDES_CFG_PU_TX_MASK;
+	reg &= ~SERDES_CFG_PU_RX_MASK;
+	reg &= ~SERDES_CFG_PU_PLL_MASK;
+	MV_REG_WRITE(MV_SATACOMP_SERDESCFG_REG, reg);
+
+	/* 3.8.3.4. Configuring the LP_SERDES to Reference clock 25M, and
+	 * PHY_MODE to SERDES APB3 Reg 0x1. Access to LP_SERDES registers is
+	 * done by accessing Gunit0, base address
+	 * (0xE00 + (Serdes Reg Address << 2)) 0xE00 + 0x1<<2 = 0x4 + 0xE00 = 0xE04.
+	 * Configure to -0xF88.
+	 */
+	mvEthCompSerdesRegWrite(0x1, 0xF801);
+
+	/* 3.8.3.5. Configyre LP_SERED data rate, by setting Gunit Serdes
+	 * Configuration (SERDESCFG) register, fields "PIN_PHY_GEN_TX" and
+	 * "PIN_PHY_GEN_RX" to 5Gbps (0xA).
+	 */
+	tmp = 0x1;
+
+	reg = MV_REG_READ(MV_SATACOMP_SERDESCFG_REG);
+	reg &= ~SERDES_CFG_PHY_GEN_RX_MASK;
+	reg |= (tmp << SERDES_CFG_PHY_GEN_RX_OFFSET);
+	reg &= ~SERDES_CFG_PHY_GEN_TX_MASK;
+	reg |= (tmp << SERDES_CFG_PHY_GEN_TX_OFFSET);
+	MV_REG_WRITE(MV_SATACOMP_SERDESCFG_REG, reg);
+
+	/* Set PHY Gen Tx & Rx to 0xA, Same as in reg MV_ETHCOMP_SERDESCFG_REG
+	 ** Bit[9] - Dig_test_bus_en.
+	 */
+	mvEthCompSerdesRegWrite(0x26, 0x111);
+
+	/* 3.8.3.6. Configuring the LP_SERDES to 10 bit interface, by setting
+	 * its internal register 0x23[11:10] to 0x1. Access to LP_SERDES
+	 * registers is done by accessing Gunit0, base address
+	 * (0xE00 + (Serdes Reg Address << 2)) = 0xE00 + 0x23<<2 =  0xE00 + 0x8c = 0xE8c.
+	 */
+	serdesReg = mvEthCompSerdesRegRead(0x23);
+	serdesReg &= ~(0x3 << 10);
+
+	if ((ethCompCfg & ESC_OPT_SATA) || (ethCompCfg & ESC_OPT_QSGMII))
+		serdesReg |= (0x1 << 10);
+
+	mvEthCompSerdesRegWrite(0x23, serdesReg);
+
+	/* 3.8.3.7. Wait for LP_SERDES pin "PLL_READY" to be 0x1. This pin is
+	 * reflected in Gunit Serdes Status (SERDESSTS) register, bit[2].
+	 */
+	do {
+		reg = MV_REG_READ(MV_SATACOMP_SERDESSTS_REG);
+	} while ((reg & (1 << 2)) == 0);
+
+	/* 3.8.3.8. Set PIN_RX_INIT to 1b1 for at least 16 TXDCLK cycles. Set
+	 * Gunit Serdes Configuration (SERDESCFG) register, field "PIN_RX_INIT"
+	 * to Enable (0x1).
+	 */
+	MV_REG_BIT_SET(MV_SATACOMP_SERDESCFG_REG, SERDES_CFG_RX_INIT_MASK);
+	mvOsSleep(10);
+
+	/* 3.8.3.9. Wait for LP_SERDES pin "PIN_RX_INIT_DONE" to be 0x1. This
+	 * pin is reflected in Gunit Serdes Status (SERDESSTS) register, bit[0].
+	 */
+	do {
+		reg = MV_REG_READ(MV_SATACOMP_SERDESSTS_REG);
+	} while ((reg & 0x1) == 0);
+
+	/* 3.8.3.10. Set PIN_RX_INIT back to 0x0. Set Gunit Serdes Configuration
+	 * (SERDESCFG) register; field "PIN_RX_INIT" to Enable (0x0).
+	 */
+	MV_REG_BIT_RESET(MV_SATACOMP_SERDESCFG_REG, SERDES_CFG_RX_INIT_MASK);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSwToQsgmiiPhyConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for Switch ports 1-3 to QSGMII output.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompSwToQsgmiiPhyConfig(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+	MV_U32 i;
+
+	if (!(ethCompCfg & ESC_OPT_QSGMII))
+		return MV_OK;
+
+	/* 3.8. Switch P1-4 to LP_SERDES_PHY, using QSGMII (10Mbps/ 100Mbps/ 1000Mbps) */
+	/* 3.8.2. Ethernet-Complex configuration :
+	 * 3.8.2.1. Configure Switch 125Mhz clock source: set Regunit
+	 * Ethernet_Complex_Control_0 register, field SwFi125ClkSrc to QSGMII (0x0).
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+	reg &= ~ETHCC_SW_FI_125_CLK_MASK;
+
+	/* 3.8.2.2. Connect Switch ports 1,2 & 3 to PCS-0,1 & 2: set Regunit
+	 * Ethernet_Complex_Control_0 register, field SwitchPort123Source to PCS (0x0)
+	 */
+	reg &= ~ETHCC_SW_PORT_123_SRC_MASK;
+
+	/* 3.8.2.3. Connect Switch ports 0 to PCS-3: set Regunit
+	 * Ethernet_Complex_Control_0 register, field SwitchPort123Source to PCS (0x0).
+	 */
+	reg &= ~ETHCC_SW_PORT_0_SRC_MASK;
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	/* Initialize Serdes. */
+	mvEthCompSerdesConfig(ethCompCfg);
+
+	/* 3.8.4. Reset de-assertion:
+	 * 3.8.4.1. De-assert QSGMII reset: set Regunit QSGMII Control 1
+	 * register, field QsgmiiRstn to 0x1.
+	 */
+	MV_REG_BIT_SET(MV_ETHCOMP_QSGMII_CONTROL_REG(1), QSGCTRL_RESETN_MASK);
+
+	/* 3.8.4.2. De-assert all PCSs reset: set registers PCS_0_Control,
+	 * PCS_1_Control PCS_2_Control and PCS_3_Control, fields PCS<i>_Port_Reset to 0x0.
+	 */
+	for (i = 0; i < 4; i++)
+		MV_REG_BIT_RESET(MV_ETHCOMP_PCS_CTRL_REG(i), PCSCTRL_PORT_RESET_MASK);
+
+	/* 3.8.5. PCS configurations (for PCSs 01,2 & 3):
+	 * 3.8.5.1. Enable PCS ports: set Regunit PCS<i>Control register,
+	 * fields Pcs<i>PortActive and Pcs<i>En to active (0x1)
+	 */
+	for (i = 0; i < 4; i++) {
+		reg = MV_REG_READ(MV_ETHCOMP_PCS_CTRL_REG(i));
+		reg |= ((0x1 << PCSCTRL_PORT_ACTIVE_OFFSET) |
+			(0x1 << PCSCTRL_PORT_ANEG_AN_OFFSET) |
+			(0x1 << PCSCTRL_PORT_RESTART_AN_OFFSET) |
+			(0x1 << PCSCTRL_PORT_ADV_PAUSE_OFFSET) |
+			(0x1 << PCSCTRL_PORT_ADV_ASM_PAUSE_OFFSET) |
+			(0x1 << PCSCTRL_PORT_ANEG_DUPLEX_AN_OFFSET) |
+			(0x1 << PCSCTRL_PORT_FC_AN_OFFSET) | (0x1 << PCSCTRL_PORT_SPEED_AN_OFFSET));
+		MV_REG_WRITE(MV_ETHCOMP_PCS_CTRL_REG(i), reg);
+	}
+
+	/* Enable PCS */
+	for (i = 0; i < 4; i++)
+		MV_REG_BIT_SET(MV_ETHCOMP_PCS_CTRL_REG(i), PCSCTRL_PORT_EN_MASK);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompMac0ToSgmiiConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for MAC0 to SGMII output.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompMac0ToSgmiiConfig(MV_U32 ethCompCfg)
+{
+	if (!(ethCompCfg & (ESC_OPT_SGMII | ESC_OPT_SGMII_2_5)))
+		return MV_OK;
+	MV_REG_BIT_SET(MV_MAC_SERIAL_CTRL0_REG, BIT23 | BIT22 | BIT21 | BIT13 | BIT4 | BIT3 | BIT2);
+	MV_REG_WRITE(MV_MAC_SERIAL_CTRL1_REG,
+		     (MV_REG_READ(MV_MAC_SERIAL_CTRL1_REG) & ~(BIT6 | BIT3)) | (BIT12 | BIT7 | BIT2));
+	MV_REG_BIT_SET(MV_MAC_SERIAL_CTRL0_REG, BIT1 | BIT10);
+
+/* 	MV_REG_BIT_SET(MV_MAC_SERIAL_CTRL1_REG, BIT12 | BIT7 | BIT2); */
+
+	/* 3.8.3. LP_SERDES_PHY initialization:
+	 * 3.8.3.1. Set LP_SERDES to reset: set Regunit Software Reset Control
+	 * register to Reset (0x1).
+	 */
+	MV_REG_BIT_SET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);
+
+	/* 3.8.3.2. De-assert LP_SERDES reset: set Regunit Software Reset
+	 * Control register to 0x0.
+	 */
+	MV_REG_BIT_RESET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);
+
+	/* 3.9. GbE-MAC-0 to LP_SERDES_PHY, using SSGMII
+	 * 3.9.1. Ethernet-Complex configuration:
+	 */
+	/* Initialize Serdes. */
+	mvEthCompSerdesConfig(ethCompCfg);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSwP1ToSgmiiConfig
+*
+* DESCRIPTION:
+*	Configure ethernet complex for Switch port1 to SGMII output.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthCompSwP1ToSgmiiConfig(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+
+	if (!(ethCompCfg & ESC_OPT_SGMII_2_SW_P1))
+		return MV_OK;
+
+	/* 3.10. Switch P1 to LP_SERDES_PHY, using TBI
+	 * 3.10.2. Ethernet-Complex configuration:
+	 * 3.10.2.1. Configure Switch 125Mhz clock source: set Regunit
+	 * Ethernet_Complex_Control_0 register, field SwFi125ClkSrc to LpSERDES (0x2).
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+	reg &= ~ETHCC_SW_FI_125_CLK_MASK;
+	reg |= (0x2 << ETHCC_SW_FI_125_CLK_OFFSET);
+
+	/* 3.10.2.2. Connect Switch ports 1 to PCS-0: set Regunit
+	 * Ethernet_Complex_Control_0 register, field SwitchPort0123Source to PCS (0x0)
+	 */
+	reg &= ~(ETHCC_SW_PORT_0_SRC_MASK | ETHCC_SW_PORT_123_SRC_MASK);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	/* Initialize Serdes. */
+	mvEthCompSerdesConfig(ethCompCfg);
+
+	/* 3.10.4. Reset de-assertion:
+	 * 3.10.4.1. De-assert all PCSs reset: set registers PCS_0_Control,
+	 * PCS_1_Control PCS_2_Control and PCS_3_Control, fields PCS<i>_Port_Reset to 0x0.
+	 */
+	MV_REG_BIT_RESET(MV_ETHCOMP_PCS_CTRL_REG(1), PCSCTRL_PORT_RESET_MASK);
+
+	/* 3.10.5. PCS-0 configurations:
+	 * OPEN: This section was never tried on our test-plan. We should ramp
+	 * up this test!!! The following sections are written based on section. (QSGMII)
+	 * 3.10.5.1. Enable PCS ports: set Regunit PCS0Control register, fields
+	 * Pcs0PortActive and Pcs0En to active (0x1)
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_PCS_CTRL_REG(1));
+	reg |= ((0x1 << PCSCTRL_PORT_ACTIVE_OFFSET) |
+		(0x1 << PCSCTRL_PORT_ANEG_AN_OFFSET) |
+		(0x1 << PCSCTRL_PORT_RESTART_AN_OFFSET) |
+		(0x1 << PCSCTRL_PORT_ADV_PAUSE_OFFSET) |
+		(0x1 << PCSCTRL_PORT_ADV_ASM_PAUSE_OFFSET) |
+		(0x1 << PCSCTRL_PORT_ANEG_DUPLEX_AN_OFFSET) |
+		(0x1 << PCSCTRL_PORT_FC_AN_OFFSET) |
+		(0x1 << PCSCTRL_PORT_SPEED_AN_OFFSET));
+	MV_REG_WRITE(MV_ETHCOMP_PCS_CTRL_REG(1), reg);
+
+	/* Enable PCS */
+	MV_REG_BIT_SET(MV_ETHCOMP_PCS_CTRL_REG(1), PCSCTRL_PORT_EN_MASK);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSerdesConfig
+*
+* DESCRIPTION:
+*	Initialize serdes according to require PHY mode.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration bitmap.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+static MV_STATUS mvEthCompSerdesConfig(MV_U32 ethCompCfg)
+{
+	MV_U32 reg;
+	MV_U32 tmp;
+	MV_U16 serdesReg;
+
+	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+
+	/* 3.8.2.4. Connect LP_SERDES_PHY to required source: set Regunit
+	 * Ethernet_Complex_Control_0 register, field "LpphyMode" to "lpphyMode".
+	 */
+	if ((ethCompCfg & (ESC_OPT_SGMII | ESC_OPT_SGMII_2_5)) &&
+	    (!(ethCompCfg & ESC_OPT_SGMII_2_SW_P1)))
+		tmp = 0x0;
+	else if (ethCompCfg & ESC_OPT_QSGMII)
+		tmp = 0x2;
+	else if (ethCompCfg & ESC_OPT_SATA)
+		tmp = 0x1;
+	else
+		tmp = 0x3;
+
+	if (mvCtrlModelGet() == MV_6601_DEV_ID) {
+		if (ethCompCfg & ESC_OPT_GEPHY_MAC0)
+			tmp = 0x1;
+		else
+			tmp = 0x0;	
+	}
+
+	reg &= ~ETHCC_LPPHYMODE_MASK;
+	reg |= (tmp << ETHCC_LPPHYMODE_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+
+	/* 3.8.2.5. Change signal detect indication polarity: set Regunit
+	 * QSGMII Control 1 register, field "QsgmiiInvSigdet" to 0x1.
+	 */
+	if (ethCompCfg & ESC_OPT_QSGMII) {
+		reg = MV_REG_READ(MV_ETHCOMP_QSGMII_CONTROL_REG(1));
+		reg &= ~QSGCTRL_INV_SIG_DET_MASK;
+		reg |= (0x1 << QSGCTRL_INV_SIG_DET_OFFSET);
+		MV_REG_WRITE(MV_ETHCOMP_QSGMII_CONTROL_REG(1), reg);
+	}
+
+	/* 3.8.3. LP_SERDES_PHY initialization:
+	 * 3.8.3.1. Set LP_SERDES to reset: set Regunit Software Reset Control
+	 * register to Reset (0x1).
+	 */
+	MV_REG_BIT_SET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);
+
+	/* 3.8.3.2. De-assert LP_SERDES reset: set Regunit Software Reset
+	 * Control register to 0x0.
+	 */
+	MV_REG_BIT_RESET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);
+
+	mvEthCompSetSerdesDefaults();
+	if (ethCompCfg & ESC_OPT_QSGMII) {
+		mvEthCompSerdesRegWrite(0x25, 0x0);
+		mvEthCompSerdesRegWrite(0x24, mvEthCompSerdesRegRead(0x24) | 0x8000);
+		mvEthCompSerdesRegWrite(0xD, 0x0BE0);
+		mvEthCompSerdesRegWrite(0xE, 0x5055);
+	} else if (ethCompCfg & ESC_OPT_SGMII_2_5) {
+		mvEthCompSerdesRegWrite(0xD, 0x0BEF);
+		mvEthCompSerdesRegWrite(0xE, 0x9055);
+	} else if (ethCompCfg & ESC_OPT_SGMII) {
+		mvEthCompSerdesRegWrite(0xD, 0x0430);
+		mvEthCompSerdesRegWrite(0xE, 0x0080);
+	}
+
+	/* 3.8.3.3. Power up LP_SERDES: set Gunit Serdes Configuration
+	 * (SERDESCFG) register, fields "PU_TX", "PU_RX, "PU_PLL" (bits 1,2,3)
+	 * to Enable (0x1)
+	 */
+	reg = MV_REG_READ(MV_ETHCOMP_SERDESCFG_REG);
+	reg &= ~SERDES_CFG_PU_TX_MASK;
+	reg &= ~SERDES_CFG_PU_RX_MASK;
+	reg &= ~SERDES_CFG_PU_PLL_MASK;
+	MV_REG_WRITE(MV_ETHCOMP_SERDESCFG_REG, reg);
+
+	/* 3.8.3.4. Configuring the LP_SERDES to Reference clock 25M, and
+	 * PHY_MODE to SERDES APB3 Reg 0x1. Access to LP_SERDES registers is
+	 * done by accessing Gunit0, base address
+	 * (0xE00 + (Serdes Reg Address << 2)) 0xE00 + 0x1<<2 = 0x4 + 0xE00 = 0xE04.
+	 * Configure to -0xF88.
+	 */
+	mvEthCompSerdesRegWrite(0x1, 0xF880);	/* Was 0xF881 */
+
+	/* 3.8.3.5. Configyre LP_SERED data rate, by setting Gunit Serdes
+	 * Configuration (SERDESCFG) register, fields "PIN_PHY_GEN_TX" and
+	 * "PIN_PHY_GEN_RX" to 5Gbps (0xA).
+	 */
+	tmp = 0x4;
+	if (ethCompCfg & ESC_OPT_QSGMII)
+		tmp = 0xA;
+	if (ethCompCfg & ESC_OPT_SATA)
+		tmp = 0x1;
+
+	reg = MV_REG_READ(MV_ETHCOMP_SERDESCFG_REG);
+	reg &= ~SERDES_CFG_PHY_GEN_RX_MASK;
+	reg |= (tmp << SERDES_CFG_PHY_GEN_RX_OFFSET);
+	reg &= ~SERDES_CFG_PHY_GEN_TX_MASK;
+	reg |= (tmp << SERDES_CFG_PHY_GEN_TX_OFFSET);
+	MV_REG_WRITE(MV_ETHCOMP_SERDESCFG_REG, reg);
+
+	/* Set PHY Gen Tx & Rx to 0xA, Same as in reg MV_ETHCOMP_SERDESCFG_REG
+	 ** Bit[9] - Dig_test_bus_en.
+	 */
+	if (ethCompCfg & ESC_OPT_QSGMII)
+		mvEthCompSerdesRegWrite(0x26, 0x3AA);
+
+	if (ethCompCfg & ESC_OPT_SGMII)
+		mvEthCompSerdesRegWrite(0x26, 0x144);
+
+	if (ethCompCfg & ESC_OPT_SGMII_2_5)
+		mvEthCompSerdesRegWrite(0x26, 0x8166);
+
+	if (ethCompCfg & ESC_OPT_SATA)
+		mvEthCompSerdesRegWrite(0x26, 0x111);
+
+	/* 3.8.3.6. Configuring the LP_SERDES to 10 bit interface, by setting
+	 * its internal register 0x23[11:10] to 0x1. Access to LP_SERDES
+	 * registers is done by accessing Gunit0, base address
+	 * (0xE00 + (Serdes Reg Address << 2)) = 0xE00 + 0x23<<2 =  0xE00 + 0x8c = 0xE8c.
+	 */
+	serdesReg = mvEthCompSerdesRegRead(0x23);
+	serdesReg &= ~(0x3 << 10);
+
+	if ((ethCompCfg & ESC_OPT_SATA) || (ethCompCfg & ESC_OPT_QSGMII))
+		serdesReg |= (0x1 << 10);
+
+/* 	serdesReg |= (0x1 << 10); */
+/* 	serdesReg |= (0x1 << 12); */
+/* 	serdesReg |= (0x1 << 13); // Analog loopback. */
+	mvEthCompSerdesRegWrite(0x23, serdesReg);
+
+#if 0
+	serdesReg = mvEthCompSerdesRegRead(0x51);
+	serdesReg |= (0x1 << 9);
+	mvEthCompSerdesRegWrite(0x51, serdesReg);
+#endif
+
+	/* 3.8.3.7. Wait for LP_SERDES pin "PLL_READY" to be 0x1. This pin is
+	 * reflected in Gunit Serdes Status (SERDESSTS) register, bit[2].
+	 */
+	do {
+		reg = MV_REG_READ(MV_ETHCOMP_SERDESSTS_REG);
+	} while ((reg & (1 << 2)) == 0);
+
+	/* 3.8.3.8. Set PIN_RX_INIT to 1b1 for at least 16 TXDCLK cycles. Set
+	 * Gunit Serdes Configuration (SERDESCFG) register, field "PIN_RX_INIT"
+	 * to Enable (0x1).
+	 */
+	MV_REG_BIT_SET(MV_ETHCOMP_SERDESCFG_REG, SERDES_CFG_RX_INIT_MASK);
+	mvOsSleep(10);
+
+	/* 3.8.3.9. Wait for LP_SERDES pin "PIN_RX_INIT_DONE" to be 0x1. This
+	 * pin is reflected in Gunit Serdes Status (SERDESSTS) register, bit[0].
+	 */
+	do {
+		reg = MV_REG_READ(MV_ETHCOMP_SERDESSTS_REG);
+	} while ((reg & 0x1) == 0);
+
+	/* 3.8.3.10. Set PIN_RX_INIT back to 0x0. Set Gunit Serdes Configuration
+	 * (SERDESCFG) register; field "PIN_RX_INIT" to Enable (0x0).
+	 */
+	MV_REG_BIT_RESET(MV_ETHCOMP_SERDESCFG_REG, SERDES_CFG_RX_INIT_MASK);
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthCompSerdesRegWrite
+*
+* DESCRIPTION:
+*	Write to a serdes register.
+*	The Serdes register address is calculated as follows:
+*		GPORT-0 Base + 0xE00 + (regAddr << 2)
+*
+* INPUT:
+*	regAddr - The serdes register to write to.
+*	value - Value to be written.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	None.
+*******************************************************************************/
+static void mvEthCompSerdesRegWrite(MV_U32 regAddr, MV_U16 value)
+{
+	MV_U32 ethCompCfg = mvBoardEthComplexConfigGet();
+
+	if (ethCompCfg & ESC_OPT_SATA) {
+		MV_REG_WRITE(0x82800 + (regAddr << 2), value);
+		/* MV_REG_WRITE(0x72E00 + (regAddr << 2), value); */
+	} else {
+		MV_REG_WRITE(0x72E00 + (regAddr << 2), value);
+	}
+	return;
+}
+
+/******************************************************************************
+* mvEthCompSerdesRegRead
+*
+* DESCRIPTION:
+*	Read a serdes register.
+*	The Serdes register address is calculated as follows:
+*		GPORT-0 Base + 0xE00 + (regAddr << 2)
+*
+* INPUT:
+*	regAddr - The serdes register to read.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	The register's value.
+*******************************************************************************/
+static MV_U16 mvEthCompSerdesRegRead(MV_U32 regAddr)
+{
+	MV_U16 data;
+	MV_U32 data32;
+	MV_U32 ethCompCfg = mvBoardEthComplexConfigGet();
+
+	if (ethCompCfg & ESC_OPT_SATA) {
+		data32 = MV_REG_READ(0x82800 + (regAddr << 2));
+		data = (MV_U16) (data32 & 0xFFFF);
+/*		data32 = MV_REG_READ(0x72E00 + (regAddr << 2));
+		data = (MV_U16)(data32 & 0xFFFF);*/
+	} else {
+		data32 = MV_REG_READ(0x72E00 + (regAddr << 2));
+		data = (MV_U16) (data32 & 0xFFFF);
+	}
+	return data;
+}
+
+/******************************************************************************
+* mvEthernetComplexShutdownIf
+*
+* DESCRIPTION:
+*	Shutdown ethernet complex interfaces.
+*
+* INPUT:
+*	integSwitch	- MV_TRUE to shutdown the integrated switch.
+*	gePhy		- MV_TRUE to shutdown the GE-PHY
+*	fePhy		- MV_TRUE to shutdown the 3xFE PHY.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthernetComplexShutdownIf(MV_BOOL integSwitch, MV_BOOL gePhy, MV_BOOL fePhy)
+{
+	if (gePhy == MV_TRUE) {
+		MV_REG_BIT_RESET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_PHY_PWR_DOWN_MASK);
+		MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_EXT_PWR_DOWN_SRC_MASK);
+		MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_PHY_PWR_DOWN_MASK);
+	}
+
+	if (fePhy == MV_TRUE) {
+		MV_REG_BIT_RESET(MV_ETHCOMP_FE_PHY_CTRL_REG, ETHCC_FE_PHY_RESET_MASK);
+		MV_REG_BIT_RESET(MV_ETHCOMP_FE_PHY_CTRL_REG, ETHCC_FE_PHY_EXT_PWR_DOWM_MASK);
+	}
+
+	return MV_OK;
+}
+
+/******************************************************************************
+* mvEthernetComplexPreInit
+*
+* DESCRIPTION:
+*	Perform basic setup that is needed before configuring the eth-complex
+*	registers.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+static MV_STATUS mvEthernetComplexPreInit(MV_U32 ethCompCfg)
+{
+	MV_U32 reg, port;
+
+	/* Disable Polling mode. */
+	MV_REG_BIT_RESET(ETH_UNIT_CONTROL_REG(0), BIT1);
+	MV_REG_BIT_RESET(ETH_UNIT_CONTROL_REG(1), BIT1);
+
+	if (mvCtrlModelGet() == MV_6601_DEV_ID) {
+
+		/* Port 0 */
+		port = 0;
+		reg = MV_REG_READ(ETH_PHY_ADDR_REG(port));
+		reg &= ~ETH_PHY_ADDR_MASK;
+		reg |= mvBoardPhyAddrGet(port);
+		MV_REG_WRITE(ETH_PHY_ADDR_REG(port), reg);
+
+		/* Port 1 */
+		port = 1;
+		reg = MV_REG_READ(ETH_PHY_ADDR_REG(port));
+		reg &= ~ETH_PHY_ADDR_MASK;
+		reg |= mvBoardPhyAddrGet(port);
+		MV_REG_WRITE(ETH_PHY_ADDR_REG(port), reg);
+
+
+	} else {
+		/* Set PHY address for MAC ports to 8 & 9 accordingly. */
+		/* The MAC Phy addresses need to be set before we enable the internal
+	 	** PHY / switch.
+	 	*/
+		if (ethCompCfg & (ESC_OPT_RGMIIA_MAC0 | ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC0_2_SW_P4)) {
+			port = 0;
+			reg = MV_REG_READ(ETH_PHY_ADDR_REG(port));
+			reg &= ~ETH_PHY_ADDR_MASK;
+			reg |= mvBoardPhyAddrGet(port);
+			MV_REG_WRITE(ETH_PHY_ADDR_REG(port), reg);
+		}
+
+		MV_REG_WRITE(ETH_PHY_ADDR_REG(1), 0x9);
+		if (ethCompCfg & (ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_MAC1)) {
+			port = 1;
+			reg = MV_REG_READ(ETH_PHY_ADDR_REG(port));
+			reg &= ~ETH_PHY_ADDR_MASK;
+			reg |= mvBoardPhyAddrGet(port);
+			MV_REG_WRITE(ETH_PHY_ADDR_REG(port), reg);
+		}
+	}
+
+	return MV_OK;
+}
+
+
+/******************************************************************************
+* mvEthernetComplexPostInit
+*
+* DESCRIPTION:
+*	Perform basic setup that is needed after configuring the eth-complex
+*	registers.
+*
+* INPUT:
+*	ethCompCfg - Ethernet complex configuration.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+static MV_STATUS mvEthernetComplexPostInit(MV_U32 ethCompCfg)
+{
+	/* Re-enable polling mode if port is not connected to switch. */
+	if (!(ethCompCfg & ESC_OPT_MAC0_2_SW_P4))
+		MV_REG_BIT_SET(ETH_UNIT_CONTROL_REG(0), BIT1);
+	if (!(ethCompCfg & ESC_OPT_MAC1_2_SW_P5))
+		MV_REG_BIT_SET(ETH_UNIT_CONTROL_REG(1), BIT1);
+
+	return MV_OK;
+}
+
+
+/******************************************************************************
+* mvEthernetComplexInit
+*
+* DESCRIPTION:
+*	Initialize the ethernet complex according to the boardEnv setup.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthernetComplexInit(void)
+{
+	MV_U32 ethCompCfg = mvBoardEthComplexConfigGet();
+
+	if (gEthComplexSkipInit == MV_TRUE)
+		return MV_OK;
+
+	mvEthernetComplexPreInit(ethCompCfg);
+
+	if (mvCtrlModelGet() == MV_6601_DEV_ID) {
+		
+		/*  MAC0 to GE PHY. */
+		mvEthCompMac0ToGePhyConfig(ethCompCfg, mvBoardPhyAddrGet(0));
+
+		/*  MAC0/1 to SGMII. */
+		mvEthCompMac0ToSgmiiConfig(ethCompCfg);
+
+	} else {
+
+		/*  First, initialize the switch. */
+		mvEthCompMac2SwitchConfig(ethCompCfg, MV_FALSE);
+
+		/*  MAC0 / 1 to RGMII. */
+		mvEthCompMac2RgmiiConfig(ethCompCfg);
+
+		/*  MAC1 to GE PHY. */
+		mvEthCompMac1ToGePhyConfig(ethCompCfg, mvBoardPhyAddrGet(1));
+
+		/*  Switch Port0/5 to GE PHY. */
+		mvEthCompSwP05ToGePhyConfig(ethCompCfg);
+
+		/*  Switch Port5 to RGMII. */
+		mvEthCompSwP56ToRgmiiConfig(ethCompCfg);
+
+		/*  Switch to 3xFE phy. */
+		mvEthCompSwTo3FePhyConfig(ethCompCfg);
+
+		/*  Sata. */
+		mvEthCompSataConfig(ethCompCfg);
+
+		/*  Switch to QSGMII. */
+		mvEthCompSwToQsgmiiPhyConfig(ethCompCfg);
+
+		/* SGMII */
+		if (ethCompCfg & (ESC_OPT_SGMII | ESC_OPT_SGMII_2_5)) {
+			if (ethCompCfg & ESC_OPT_SGMII_2_SW_P1) {
+				/*  Switch port 1 to SGMII. */
+				mvEthCompSwP1ToSgmiiConfig(ethCompCfg);
+			} else {
+				/*  MAC0 to SGMII. */
+				mvEthCompMac0ToSgmiiConfig(ethCompCfg);
+			}
+		}
+
+		/*  Reset the switch after all configurations are done. */
+		mvEthCompSwitchReset(ethCompCfg);
+
+#if 0
+		/*  Re-reset the PHY in case it's connected to MAC1. */
+		if (ethCompCfg & ESC_OPT_GEPHY_MAC1) {
+			MV_REG_BIT_RESET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_RESET_MASK);
+			MV_REG_BIT_SET(MV_ETHCOMP_GE_PHY_CTRL_REG, PHYCTRL_RESET_MASK);
+		}
+#endif
+	}
+
+	mvEthernetComplexPostInit(ethCompCfg);
+
+	return MV_OK;
+}
+
+
+/******************************************************************************
+* mvEthernetComplexChangeMode
+*
+* DESCRIPTION:
+*	Change the ethernet complex configuration at runtime.
+*	Meanwhile the function supports only the following mode changes:
+*		- Moving the switch between MAC0 & MAC1.
+*		- Connect / Disconnect GE-PHY to MAC1.
+*		- Connect / Disconnect RGMII-B to MAC0.
+*
+* INPUT:
+*	oldCfg	- The old ethernet complex configuration.
+*	newCfg	- The new ethernet complex configuration to switch to.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*******************************************************************************/
+MV_STATUS mvEthernetComplexChangeMode(MV_U32 oldCfg, MV_U32 newCfg)
+{
+	MV_U32 cfgDiff;
+	MV_U32 reg;
+
+	if (oldCfg == newCfg)
+		return MV_OK;
+
+	mvEthernetComplexPreInit(newCfg);
+
+	cfgDiff = (oldCfg & ~newCfg);
+
+	/* Set new configuration for the switch */
+	mvEthCompMac2SwitchConfig(newCfg, MV_TRUE);
+
+	mvEthCompMac2RgmiiConfig(newCfg);
+
+	mvEthCompMac1ToGePhyConfig(newCfg, mvBoardPhyAddrGet(1));
+	if (!(newCfg & ESC_OPT_GEPHY_MAC1)) {
+		reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));
+		reg &= ~ETHCC_BGE_PHY_SRC_MASK;
+		reg |= (0x3 << ETHCC_BGE_PHY_SRC_OFFSET);
+		MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);
+	}
+
+	mvEthernetComplexPostInit(newCfg);
+
+	return MV_OK;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEthCompLib.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEthCompLib.h
new file mode 100755
index 0000000..e10ac91
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/mvCtrlEthCompLib.h
@@ -0,0 +1,303 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCtrlEthCompLibh
+#define __INCmvCtrlEthCompLibh
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysEthConfig.h"
+
+/* QSGMII Control 0/1 Register. */
+#define MV_ETHCOMP_QSGMII_CONTROL_REG(id)	(MV_ETH_COMPLEX_BASE + (id * 4))
+/* QSGMII Control 1 Register. */
+#define QSGCTRL_INV_SIG_DET_OFFSET		25
+#define QSGCTRL_INV_SIG_DET_MASK		(0x1 << QSGCTRL_INV_SIG_DET_OFFSET)
+#define QSGCTRL_RESETN_OFFSET			31
+#define QSGCTRL_RESETN_MASK			(0x1 << QSGCTRL_RESETN_OFFSET)
+
+#define MV_ETHCOMP_QSGMII_STATUS_REG		(MV_ETH_COMPLEX_BASE + 0x8)
+
+#define MV_ETHCOMP_CTRL_REG(id)			(MV_ETH_COMPLEX_BASE + 0x10 + (id * 4))
+
+/* Ethernet Complex Control 0 */
+#define ETHCC_LPPHYMODE_OFFSET			0
+#define ETHCC_LPPHYMODE_MASK			(0x3 << ETHCC_LPPHYMODE_OFFSET)
+#define ETHCC_GBE_PHY_SMI_SRC_OFFSET		2
+#define ETHCC_GBE_PHY_SMI_SRC_MASK		(0x1 << ETHCC_GBE_PHY_SMI_SRC_OFFSET)
+#define ETHCC_SW_PORT6_MPP_OFFSET		3
+#define ETHCC_SW_PORT6_MPP_MASK			(0x1 << ETHCC_SW_PORT6_MPP_OFFSET)
+#define ETHCC_SW_PORT_0_SRC_OFFSET		4
+#define ETHCC_SW_PORT_0_SRC_MASK		(0x3 << ETHCC_SW_PORT_0_SRC_OFFSET)
+#define ETHCC_SW_PORT_123_SRC_OFFSET		6
+#define ETHCC_SW_PORT_123_SRC_MASK		(0x1 << ETHCC_SW_PORT_123_SRC_OFFSET)
+#define ETHCC_SW_PORT_5_SRC_OFFSET		8
+#define ETHCC_SW_PORT_5_SRC_MASK		(0x3 << ETHCC_SW_PORT_5_SRC_OFFSET)
+#define ETHCC_GPORT_0_SRC_OFFSET		10
+#define ETHCC_GPORT_0_SRC_MASK			(0x3 << ETHCC_GPORT_0_SRC_OFFSET)
+#define ETHCC_GPORT_1_SRC_OFFSET		12
+#define ETHCC_GPORT_1_SRC_MASK			(0x3 << ETHCC_GPORT_1_SRC_OFFSET)
+#define ETHCC_BGE_PHY_SRC_OFFSET		14
+#define ETHCC_BGE_PHY_SRC_MASK			(0x3 << ETHCC_BGE_PHY_SRC_OFFSET)
+#define ETHCC_SW_PORT5_MPP_OFFSET		16
+#define ETHCC_SW_PORT5_MPP_MASK			(0x1 << ETHCC_SW_PORT5_MPP_OFFSET)
+#define ETHCC_SW_FI_125_CLK_OFFSET		17
+#define ETHCC_SW_FI_125_CLK_MASK		(0x3 << ETHCC_SW_FI_125_CLK_OFFSET)
+#define ETHCC_GBE_PHY_SMI_ADD_OFFSET		19
+#define ETHCC_GBE_PHY_SMI_ADD_MASK		(0x1F << ETHCC_GBE_PHY_SMI_ADD_OFFSET)
+#define ETHCC_SW_P5_INBAND_SRC_OFFSET		24
+#define ETHCC_SW_P5_INBAND_SRC_MASK		(0x1 << ETHCC_SW_P5_INBAND_SRC_OFFSET)
+#define ETHCC_RFU2SW_P5_INBAND_OFFSET		25
+#define ETHCC_RFU2SW_P5_INBAND_MASK		(0xF << ETHCC_RFU2SW_P5_INBAND_OFFSET)
+#define ETHCC_LP_SERDES_DATA_SWAP_TX_OFFSET	29
+#define ETHCC_LP_SERDES_DATA_SWAP_TX_MASK	(0x1 << ETHCC_LP_SERDES_DATA_SWAP_TX_OFFSET)
+#define ETHCC_LP_SERDES_DATA_SWAP_RX_OFFSET	30
+#define ETHCC_LP_SERDES_DATA_SWAP_RX_MASK	(0x1 << ETHCC_LP_SERDES_DATA_SWAP_RX_OFFSET)
+#define ETHCC_SWP5_GBEPHY_TC_CLK_OFFSET		31
+#define ETHCC_SWP5_GBEPHY_TC_CLK_MASK		(0x1 << ETHCC_SWP5_GBEPHY_TC_CLK_OFFSET)
+
+/* Ethernet Complex Control 1 */
+#define ETHCC_SWTCH_RESET_OFFSET		0
+#define ETHCC_SWTCH_RESET_MASK			(0x1 << ETHCC_SWTCH_RESET_OFFSET)
+#define ETHCC_SWTCH_MODE_OFFSET			8
+#define ETHCC_SWTCH_MODE_MASK			(0xF << ETHCC_SWTCH_MODE_OFFSET)
+#define ETHCC_SWTCH_CHIP_TYPE_OFFSET		12
+#define ETHCC_SWTCH_CHIP_TYPE_MASK		(0xF << ETHCC_SWTCH_CHIP_TYPE_OFFSET)
+#define ETHCC_SWTCH_P5_MODE_OFFSET		16
+#define ETHCC_SWTCH_P5_MODE_MASK           	(0x7 << ETHCC_SWTCH_P5_MODE_OFFSET)
+#define ETHCC_SWTCH_P5_HD_OFFSET		19
+#define ETHCC_SWTCH_P5_HD_MASK			(0x1 << ETHCC_SWTCH_P5_HD_OFFSET)
+#define ETHCC_SWTCH_P6_MODE_OFFSET		20
+#define ETHCC_SWTCH_P6_MODE_MASK		(0x7 << ETHCC_SWTCH_P6_MODE_OFFSET)
+#define ETHCC_SWTCH_P6_HD_OFFSET		23
+#define ETHCC_SWTCH_P6_HD_MASK			(0x1 << ETHCC_SWTCH_P6_HD_OFFSET)
+#define ETHCC_SWTCH_PTP_EXT_CLK_OFFSET		24
+#define ETHCC_SWTCH_PTP_EXT_CLK_MASK		(0x1 << ETHCC_SWTCH_PTP_EXT_CLK_OFFSET)
+#define ETHCC_SWTCH_ADDR_OFFSET			25
+#define ETHCC_SWTCH_ADDR_MASK	        	(0x1F << ETHCC_SWTCH_ADDR_OFFSET)
+#define ETHCC_SWTCH_JUMBO_EN_OFFSET		30
+#define ETHCC_SWTCH_JUMBO_EN_MASK		(0x1 << ETHCC_SWTCH_JUMBO_EN_OFFSET)
+#define ETHCC_SWTCH_DIS_AUTO_MED_OFFSET		31
+#define ETHCC_SWTCH_DIS_AUTO_MED_MASK		(0x1 << ETHCC_SWTCH_DIS_AUTO_MED_OFFSET)
+
+/* Ethernet Complex Control 2 */
+#define ETHCC_SW_USE_EEPROM_OFFSET		8
+#define ETHCC_SW_USE_EEPROM_MASK		(0x1 << ETHCC_SW_USE_EEPROM_OFFSET)
+#define ETHCC_SW_FD_FLOW_DIS_OFFSET		9
+#define ETHCC_SW_FD_FLOW_DIS_MASK		(0x1 << ETHCC_SW_FD_FLOW_DIS_OFFSET)
+#define ETHCC_SW_HD_FLOW_DIS_OFFSET		10
+#define ETHCC_SW_HD_FLOW_DIS_MASK		(0x1 << ETHCC_SW_HD_FLOW_DIS_OFFSET)
+#define ETHCC_SW_100FX_MODE_OFFSET		11
+#define ETHCC_SW_100FX_MODE_MASK		(0x7F << ETHCC_SW_100FX_MODE_OFFSET)
+#define ETHCC_SW_PRT_STATE_OFFSET		18
+#define ETHCC_SW_PRT_STATE_MASK			(0x7F << ETHCC_SW_PRT_STATE_OFFSET)
+#define ETHCC_SW_CLK_125_OFFSET			25
+#define ETHCC_SW_CLK_125_MASK			(0x1 << ETHCC_SW_CLK_125_OFFSET)
+
+/* Ethernet Complex Control 3 */
+#define ETHCC_SW_PX_FRC_SPD_OFFSET(prt)		(prt * 4)
+#define ETHCC_SW_PX_FRC_SPD_MASK(prt)		(0x1 << ETHCC_SW_PX_FRC_SPD_OFFSET(prt))
+#define ETHCC_SW_PX_FRC_GMII_SPD_OFFSET(prt)	((prt * 4) + 1)
+#define ETHCC_SW_PX_FRC_GMII_SPD_MASK(prt)	(0x1 << ETHCC_SW_PX_FRC_GMII_SPD_OFFSET(prt))
+#define ETHCC_SW_PX_FRC_MII_SPD_OFFSET(prt)	((prt * 4) + 2)
+#define ETHCC_SW_PX_FRC_MII_SPD_MASK(prt)	(0x1 << ETHCC_SW_PX_FRC_MII_SPD_OFFSET(prt))
+#define ETHCC_FEPHY_TX_DATA_SMPL_OFFSET		26
+#define ETHCC_FEPHY_TX_DATA_SMPL_MASK		(0x1 << ETHCC_FEPHY_TX_DATA_SMPL_OFFSET)
+#define ETHCC_GEPHY_TX_DATA_SMPL_OFFSET		28
+#define ETHCC_GEPHY_TX_DATA_SMPL_MASK		(0x3 << ETHCC_GEPHY_TX_DATA_SMPL_OFFSET)
+
+/* PCSn Control Register. */
+#define MV_ETHCOMP_PCS_CTRL_REG(id)		(MV_ETH_COMPLEX_BASE + 0x30 + (id * 4))
+#define PCSCTRL_PORT_ANEG_AN_OFFSET		1
+#define PCSCTRL_PORT_RESTART_AN_OFFSET		2
+#define PCSCTRL_PORT_ADV_PAUSE_OFFSET		3
+#define PCSCTRL_PORT_ADV_ASM_PAUSE_OFFSET	10
+#define PCSCTRL_PORT_ANEG_DUPLEX_AN_OFFSET	17
+#define PCSCTRL_PORT_FC_AN_OFFSET		19
+#define PCSCTRL_PORT_SPEED_AN_OFFSET		21
+#define PCSCTRL_PORT_ACTIVE_OFFSET		25
+#define PCSCTRL_PORT_ACTIVE_MASK		(0x1 << PCSCTRL_PORT_ACTIVE_OFFSET)
+#define PCSCTRL_PORT_EN_OFFSET			26
+#define PCSCTRL_PORT_EN_MASK			(0x1 << PCSCTRL_PORT_EN_OFFSET)
+#define PCSCTRL_PORT_RESET_OFFSET		27
+#define PCSCTRL_PORT_RESET_MASK			(0x1 << PCSCTRL_PORT_RESET_OFFSET)
+
+#define MV_ETHCOMP_PCS_STATUS_REG(id)		(MV_ETH_COMPLEX_BASE + 0x40 + (id * 4))
+#define MV_ETHCOMP_INT_MAIN_CAUSE_REG		(MV_ETH_COMPLEX_BASE + 0x50)
+#define MV_ETHCOMP_INT_MAIN_MASK_REG		(MV_ETH_COMPLEX_BASE + 0x54)
+#define MV_ETHCOMP_FE_PHY_CTRL_REG		(MV_ETH_COMPLEX_BASE + 0x80)
+
+#define MV_ETHCOMP_SWITCH_INT_OFFSET		0
+#define MV_ETHCOMP_SWITCH_INT_MASK		    (0x1 << MV_ETHCOMP_SWITCH_INT_OFFSET)
+#define MV_ETHCOMP_PCS0_LINK_INT_OFFSET		1
+#define MV_ETHCOMP_PCS0_LINK_INT_MASK		(0x1 << MV_ETHCOMP_PCS0_LINK_INT_OFFSET)
+#define MV_ETHCOMP_PCS1_LINK_INT_OFFSET		4
+#define MV_ETHCOMP_PCS1_LINK_INT_MASK		(0x1 << MV_ETHCOMP_PCS1_LINK_INT_OFFSET)
+#define MV_ETHCOMP_PCS2_LINK_INT_OFFSET		7
+#define MV_ETHCOMP_PCS2_LINK_INT_MASK		(0x1 << MV_ETHCOMP_PCS2_LINK_INT_OFFSET)
+#define MV_ETHCOMP_PCS3_LINK_INT_OFFSET		10
+#define MV_ETHCOMP_PCS3_LINK_INT_MASK		(0x1 << MV_ETHCOMP_PCS3_LINK_INT_OFFSET)
+#define MV_ETHCOMP_GEPHY_INT_OFFSET		13
+#define MV_ETHCOMP_GEPHY_INT_MASK		(0x1 << MV_ETHCOMP_GEPHY_INT_OFFSET)
+
+/* FE PHY Control Register. */
+#define MV_ETHCOMP_FE_PHY_STATUS_REG		(MV_ETH_COMPLEX_BASE + 0x84)
+#define ETHCC_FE_PHY_AN_MODE_OFFSET(prt)	((prt + 1) * 3)
+#define ETHCC_FE_PHY_AN_MODE_MASK(prt)		(0xF << ETHCC_FE_PHY_AN_MODE_OFFSET(prt))
+#define ETHCC_FE_PHY_XOVER_EN_OFFSET		14
+#define ETHCC_FE_PHY_XOVER_EN_MASK		(1 << ETHCC_FE_PHY_XOVER_EN_OFFSET)
+#define ETHCC_FE_PHY_RESET_OFFSET		15
+#define ETHCC_FE_PHY_RESET_MASK			(0x1 << ETHCC_FE_PHY_RESET_OFFSET)
+#define ETHCC_FE_PHY_EXT_PWR_DOWM_OFFSET	16
+#define ETHCC_FE_PHY_EXT_PWR_DOWM_MASK		(0x7 << ETHCC_FE_PHY_EXT_PWR_DOWM_OFFSET)
+
+#define MV_ETHCOMP_LP_SERDES_CTRL_REG		(MV_ETH_COMPLEX_BASE + 0x94)
+
+/* GbE PHY Control Register. */
+#define MV_ETHCOMP_GE_PHY_CTRL_REG		(MV_ETH_COMPLEX_BASE + 0xA0)
+#define MV_ETHCOMP_RSRVD_CTRL_REG		(MV_ETH_COMPLEX_BASE + 0xA4)
+
+#define PHYCTRL_ENRGY_DETECT_OFFSET		0x0
+#define PHYCTRL_ENRGY_DETECT_MASK		(0x1 << PHYCTRL_ENRGY_DETECT_OFFSET)
+#define PHYCTRL_CFG_ANEG_ADV_OFFSET		1
+#define PHYCTRL_CFG_ANEG_ADV_MASK		(0x3 << PHYCTRL_CFG_ANEG_ADV_OFFSET)
+#define PHYCTRL_CONF_MSTR_SLAVE_OFFSET		3
+#define PHYCTRL_CONF_MSTR_SLAVE_MASK		(0x1 << PHYCTRL_CONF_MSTR_SLAVE_OFFSET)
+#define PHYCTRL_XOVER_EN_OFFSET			4
+#define PHYCTRL_XOVER_EN_MASK			(0x1 << PHYCTRL_XOVER_EN_OFFSET)
+#define PHYCTRL_PHY_PWR_DOWN_OFFSET		5
+#define PHYCTRL_PHY_PWR_DOWN_MASK		(0x1 << PHYCTRL_PHY_PWR_DOWN_OFFSET)
+#define PHYCTRL_PG_PORT_NUM_OFFSET		6
+#define PHYCTRL_PG_PORT_NUM_MASK		(0x7 << PHYCTRL_PG_PORT_NUM_OFFSET)
+#define PHYCTRL_CONF_ADV_EEE_OFFSET		9
+#define PHYCTRL_CONF_ADV_EEE_MASK		(0x1 << PHYCTRL_CONF_ADV_EEE_OFFSET)
+#define PHYCTRL_CONF_NORMAL_MODE_OFFSET		10
+#define PHYCTRL_CONF_NORMAL_MODE_MASK		(0x1 << PHYCTRL_CONF_NORMAL_MODE_OFFSET)
+#define PHYCTRL_THERM_SENS_EN_OFFSET		11
+#define PHYCTRL_THERM_SENS_EN_MASK		(0x1 << PHYCTRL_THERM_SENS_EN_OFFSET)
+#define PHYCTRL_RESET_OFFSET			14
+#define PHYCTRL_RESET_MASK			(0x1 << PHYCTRL_RESET_OFFSET)
+#define PHYCTRL_DPLL_RESET_OFFSET		16
+#define PHYCTRL_DPLL_RESET_MASK			(0x1 << PHYCTRL_DPLL_RESET_OFFSET)
+#define PHYCTRL_CLCK125_EN_OFFSET		17
+#define PHYCTRL_CLCK125_EN_MASK			(0x1 << PHYCTRL_CLCK125_EN_OFFSET)
+#define PHYCTRL_CLCK50_EN_OFFSET		18
+#define PHYCTRL_CLCK50_EN_MASK			(0x1 << PHYCTRL_CLCK50_EN_OFFSET)
+#define PHYCTRL_EXT_PWR_DOWN_SRC_OFFSET		25
+#define PHYCTRL_EXT_PWR_DOWN_SRC_MASK		(0x1 << PHYCTRL_EXT_PWR_DOWN_SRC_OFFSET)
+
+#define MV_ETHCOMP_GE_PHY_CTRL1_REG		(MV_ETH_COMPLEX_BASE + 0xA4)
+#define PHYCTRL_PS_ENA_XC_A_OFFSET		12
+#define PHYCTRL_PS_ENA_XC_A_MASK		(0x3 << PHYCTRL_PS_ENA_XC_A_OFFSET)
+
+
+#define MV_ETHCOMP_GE_PHY_STATUS_REG		(MV_ETH_COMPLEX_BASE + 0xA8)
+
+/* Serdes Configuration Register */
+#define MV_ETHCOMP_SERDESCFG_REG		(MV_ETH_ONLY_REGS_BASE + 0x4A0)
+#define MV_SATACOMP_SERDESCFG_REG		(MV_SATA_REGS_OFFSET + 0x2058)
+
+#define SERDES_CFG_PU_PLL_OFFSET		0
+#define SERDES_CFG_PU_PLL_MASK			(0x1 << SERDES_CFG_PU_PLL_OFFSET)
+#define SERDES_CFG_PU_RX_OFFSET			1
+#define SERDES_CFG_PU_RX_MASK			(0x1 << SERDES_CFG_PU_RX_OFFSET)
+#define SERDES_CFG_PU_TX_OFFSET			2
+#define SERDES_CFG_PU_TX_MASK			(0x1 << SERDES_CFG_PU_TX_OFFSET)
+#define SERDES_CFG_TX_IDLE_OFFSET		3
+#define SERDES_CFG_TX_IDLE_MASK			(0x1 << SERDES_CFG_TX_IDLE_OFFSET)
+#define SERDES_CFG_RX_INIT_OFFSET		4
+#define SERDES_CFG_RX_INIT_MASK			(0x1 << SERDES_CFG_RX_INIT_OFFSET)
+#define SERDES_CFG_PHY_GEN_TX_OFFSET		5
+#define SERDES_CFG_PHY_GEN_TX_MASK		(0xF << SERDES_CFG_PHY_GEN_TX_OFFSET)
+#define SERDES_CFG_PHY_GEN_RX_OFFSET		9
+#define SERDES_CFG_PHY_GEN_RX_MASK		(0xF << SERDES_CFG_PHY_GEN_RX_OFFSET)
+#define SERDES_CFG_DIG_TEST_EN_OFFSET		13
+#define SERDES_CFG_DIG_TEST_EN_MASK		(0x1 << SERDES_CFG_DIG_TEST_EN_OFFSET)
+#define SERDES_CFG_IDDQ_OFFSET			14
+#define SERDES_CFG_IDDQ_MASK			(0x1 << SERDES_CFG_IDDQ_OFFSET)
+
+/* MAC Configuration Register */
+#define MV_MAC_SERIAL_CTRL1_REG		(MV_ETH_ONLY_REGS_BASE + 0x44C)
+#define MV_MAC_SERIAL_CTRL0_REG		(MV_ETH_ONLY_REGS_BASE + 0x43C)
+
+/* Serdes Status Register */
+#define MV_ETHCOMP_SERDESSTS_REG		(MV_ETH_ONLY_REGS_BASE + 0x4A4)
+#define MV_SATACOMP_SERDESSTS_REG		(MV_SATA_REGS_OFFSET + 0x205C)
+
+void mvEthCompSkipInitSet(MV_BOOL skip);
+MV_STATUS mvEthCompMac2SwitchConfig(MV_U32 ethCompCfg, MV_BOOL muxCfgOnly);
+MV_STATUS mvEthCompSwitchReset(MV_U32 ethCompCfg);
+MV_STATUS mvEthCompMac2RgmiiConfig(MV_U32 ethCompCfg);
+MV_STATUS mvEthCompMac1ToGePhyConfig(MV_U32 ethCompCfg, MV_U32 smiAddr);
+MV_STATUS mvEthCompSwP45ToGePhyConfig(MV_U32 ethCompCfg);
+MV_STATUS mvEthCompSwP5ToRgmiiConfig(MV_U32 ethCompCfg);
+MV_STATUS mvEthCompSwTo3FePhyConfig(MV_U32 ethCompCfg);
+MV_STATUS mvEthCompSataConfig(MV_U32 ethCompCfg);
+MV_STATUS mvEthCompSwToQsgmiiPhyConfig(MV_U32 ethCompCfg);
+MV_STATUS mvEthCompMac0ToSgmiiConfig(MV_U32 ethCompCfg);
+MV_STATUS mvEthCompSwP1ToSgmiiConfig(MV_U32 ethCompCfg);
+MV_STATUS mvEthernetComplexShutdownIf(MV_BOOL integSwitch, MV_BOOL gePhy, MV_BOOL fePhy);
+MV_STATUS mvEthernetComplexInit(void);
+MV_STATUS mvEthernetComplexChangeMode(MV_U32 oldCfg, MV_U32 newCfg);
+
+#endif /* __INCmvCtrlEthCompLibh */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbus.c b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbus.c
new file mode 100755
index 0000000..38f2d3d
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbus.c
@@ -0,0 +1,747 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* includes */
+#include "ctrlEnv/sys/mvAhbToMbus.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+#include "mvCpuIfRegs.h"
+
+#undef MV_DEBUG
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/* typedefs */
+
+/* CPU address remap registers offsets are inconsecutive. This struct		*/
+/* describes address remap register offsets					*/
+typedef struct _ahbToMbusRemapRegOffs {
+	MV_U32 lowRegOffs;	/* Low 32-bit remap register offset             */
+	MV_U32 highRegOffs;	/* High 32 bit remap register offset            */
+} AHB_TO_MBUS_REMAP_REG_OFFS;
+
+/* locals   */
+static MV_STATUS ahbToMbusRemapRegOffsGet(MV_U32 winNum, AHB_TO_MBUS_REMAP_REG_OFFS *pRemapRegs);
+
+/*******************************************************************************
+* mvAhbToMbusInit - Initialize Ahb To Mbus Address Map !
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK laways.
+*
+*******************************************************************************/
+MV_STATUS mvAhbToMbusInit(void)
+{
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvAhbToMbusWinSet - Set CPU-to-peripheral winNum address window
+*
+* DESCRIPTION:
+*       This function sets
+*       address window, also known as address decode window.
+*       A new address decode window is set for specified winNum address window.
+*       If address decode window parameter structure enables the window,
+*       the routine will also enable the winNum window, allowing CPU to access
+*       the winNum window.
+*
+* INPUT:
+*       winNum      - Windows number.
+*       pAddrDecWin - CPU winNum window data structure.
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_OK if CPU winNum window was set correctly, MV_ERROR in case of
+*       address window overlapps with other active CPU winNum window or
+*		trying to assign 36bit base address while CPU does not support that.
+*       The function returns MV_NOT_SUPPORTED, if the winNum is unsupported.
+*
+*******************************************************************************/
+MV_STATUS mvAhbToMbusWinSet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin)
+{
+	MV_TARGET_ATTRIB targetAttribs;
+	MV_DEC_REGS decRegs;
+	MV_U32 sizeToReg;
+
+	/* Parameter checking   */
+	if (winNum >= MAX_AHB_TO_MBUS_WINS) {
+		mvOsPrintf("mvAhbToMbusWinSet: ERR. Invalid winNum %d\n", winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	/* read base register */
+	if (winNum != MV_AHB_TO_MBUS_INTREG_WIN)
+		decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum));
+	else
+		decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG);
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) {
+		mvOsPrintf("mvAhbToMbusWinSet:Error setting AHB to MBUS window %d to "
+			   "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n",
+			   winNum,
+			   mvCtrlTargetNameGet(pAddrDecWin->target),
+			   pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	/* read control register */
+	if (winNum != MV_AHB_TO_MBUS_INTREG_WIN)
+		decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum));
+
+	/* Write to address decode Base Address Register        */
+	decRegs.baseReg &= ~ATMWCR_WIN_BASE_MASK;
+	decRegs.baseReg |= (pAddrDecWin->addrWin.baseLow & ATMWCR_WIN_BASE_MASK);
+
+	/* Size parameter validity check.                       */
+	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.size, ATMWCR_WIN_SIZE_ALIGNMENT)) {
+		mvOsPrintf("mvAhbToMbusWinSet: Failed, size not aligned to 0x%x.\n", ATMWCR_WIN_SIZE_ALIGNMENT);
+		return MV_BAD_PARAM;
+	}
+
+	/* Get size register value according to window size     */
+	sizeToReg = (pAddrDecWin->addrWin.size / ATMWCR_WIN_SIZE_ALIGNMENT) - 1;
+
+	/* set size                                             */
+	decRegs.sizeReg = (sizeToReg << ATMWCR_WIN_SIZE_OFFS);
+
+	/* enable\Disable */
+	if (MV_TRUE == pAddrDecWin->enable)
+		decRegs.sizeReg |= ATMWCR_WIN_ENABLE;
+	else
+		decRegs.sizeReg &= ~ATMWCR_WIN_ENABLE;
+
+	mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs);
+
+	/* set attributes */
+	decRegs.sizeReg &= ~ATMWCR_WIN_ATTR_MASK;
+	decRegs.sizeReg |= targetAttribs.attrib << ATMWCR_WIN_ATTR_OFFS;
+	/* set target ID */
+	decRegs.sizeReg &= ~ATMWCR_WIN_TARGET_MASK;
+	decRegs.sizeReg |= targetAttribs.targetId << ATMWCR_WIN_TARGET_OFFS;
+
+#if !defined(MV_RUN_FROM_FLASH)
+	/* To be on the safe side we disable the window before writing the  */
+	/* new values.                                                      */
+	if (winNum != MV_AHB_TO_MBUS_INTREG_WIN)
+		mvAhbToMbusWinEnable(winNum, MV_FALSE);
+#endif
+
+	/* 3) Write to address decode Base Address Register                   */
+	if (winNum != MV_AHB_TO_MBUS_INTREG_WIN)
+		MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), decRegs.baseReg);
+	else
+		MV_REG_WRITE(AHB_TO_MBUS_WIN_INTEREG_REG, decRegs.baseReg);
+
+	/* Internal register space have no size */
+	/* register. Do not perform size register assigment for those targets   */
+	if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) {
+		/* Write to address decode Size Register                                */
+		MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), decRegs.sizeReg);
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAhbToMbusWinGet - Get CPU-to-peripheral winNum address window
+*
+* DESCRIPTION:
+*		Get the CPU peripheral winNum address window.
+*
+* INPUT:
+*       winNum - Peripheral winNum enumerator
+*
+* OUTPUT:
+*       pAddrDecWin - CPU winNum window information data structure.
+*
+* RETURN:
+*       MV_OK if winNum exist, MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvAhbToMbusWinGet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin)
+{
+	MV_DEC_REGS decRegs;
+	MV_TARGET_ATTRIB targetAttrib;
+	MV_U32 sizeRegVal;
+
+	/* Parameter checking   */
+	if (winNum >= MAX_AHB_TO_MBUS_WINS) {
+		mvOsPrintf("mvAhbToMbusWinGet: ERR. Invalid winNum %d\n", winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	/* Internal register space size have no size register */
+	if (winNum != MV_AHB_TO_MBUS_INTREG_WIN)
+		decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum));
+	else
+		decRegs.sizeReg = 0;
+
+	/* Read base and size   */
+	if (winNum != MV_AHB_TO_MBUS_INTREG_WIN)
+		decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum));
+	else
+		decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG);
+
+	pAddrDecWin->addrWin.baseHigh = 0;
+	pAddrDecWin->addrWin.baseLow = decRegs.baseReg & ATMWCR_WIN_BASE_MASK;
+	sizeRegVal = (decRegs.sizeReg & ATMWCR_WIN_SIZE_MASK) >> ATMWCR_WIN_SIZE_OFFS;
+	pAddrDecWin->addrWin.size = (sizeRegVal + 1) * ATMWCR_WIN_SIZE_ALIGNMENT;
+
+	if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) {
+		pAddrDecWin->addrWin.size = INTER_REGS_SIZE;
+		pAddrDecWin->target = INTER_REGS;
+		pAddrDecWin->enable = MV_TRUE;
+
+		return MV_OK;
+	}
+
+	if (decRegs.sizeReg & ATMWCR_WIN_ENABLE)
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+
+	if (-1 == pAddrDecWin->addrWin.size)
+		return MV_ERROR;
+
+	/* attrib and targetId */
+	targetAttrib.attrib = (decRegs.sizeReg & ATMWCR_WIN_ATTR_MASK) >> ATMWCR_WIN_ATTR_OFFS;
+	targetAttrib.targetId = (decRegs.sizeReg & ATMWCR_WIN_TARGET_MASK) >> ATMWCR_WIN_TARGET_OFFS;
+
+	pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAhbToMbusWinTargetGet - Get Window number associated with target
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_U32 mvAhbToMbusWinTargetGet(MV_TARGET target)
+{
+	MV_AHB_TO_MBUS_DEC_WIN decWin;
+	MV_U32 winNum;
+
+	/* Check parameters */
+	if (target >= MAX_TARGETS) {
+		mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is illegal\n", target);
+		return 0xffffffff;
+	}
+
+	if (INTER_REGS == target)
+		return MV_AHB_TO_MBUS_INTREG_WIN;
+
+	for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS; winNum++) {
+		if (winNum == MV_AHB_TO_MBUS_INTREG_WIN)
+			continue;
+
+		if (mvAhbToMbusWinGet(winNum, &decWin) != MV_OK) {
+			mvOsPrintf("mvAhbToMbusWinTargetGet: mvAhbToMbusWinGet fail\n");
+			return 0xffffffff;
+		}
+
+		if (decWin.enable == MV_TRUE) {
+			if (decWin.target == target)
+				return winNum;
+		}
+	}
+
+	return 0xFFFFFFFF;
+
+}
+
+/*******************************************************************************
+* mvAhbToMbusWinAvailGet - Get First Available window number.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_U32 mvAhbToMbusWinAvailGet(MV_VOID)
+{
+	MV_AHB_TO_MBUS_DEC_WIN decWin;
+	MV_U32 winNum;
+
+	for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS; winNum++) {
+		if (winNum == MV_AHB_TO_MBUS_INTREG_WIN)
+			continue;
+
+		if (mvAhbToMbusWinGet(winNum, &decWin) != MV_OK) {
+			mvOsPrintf("mvAhbToMbusWinTargetGet: mvAhbToMbusWinGet fail\n");
+			return 0xffffffff;
+		}
+
+		if (decWin.enable == MV_FALSE)
+			return winNum;
+	}
+
+	return 0xFFFFFFFF;
+}
+
+/*******************************************************************************
+* mvAhbToMbusWinEnable - Enable/disable a CPU address decode window
+*
+* DESCRIPTION:
+*       This function enable/disable a CPU address decode window.
+*       if parameter 'enable' == MV_TRUE the routine will enable the
+*       window, thus enabling CPU accesses (before enabling the window it is
+*       tested for overlapping). Otherwise, the window will be disabled.
+*
+* INPUT:
+*       winNum - Peripheral winNum enumerator.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_ERROR if protection window number was wrong, or the window
+*       overlapps other winNum window.
+*
+*******************************************************************************/
+MV_STATUS mvAhbToMbusWinEnable(MV_U32 winNum, MV_BOOL enable)
+{
+
+	/* Parameter checking   */
+	if (winNum >= MAX_AHB_TO_MBUS_WINS) {
+		mvOsPrintf("mvAhbToMbusWinEnable: ERR. Invalid winNum %d\n", winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	/* Internal registers bar can't be disable or enabled */
+	if (winNum == MV_AHB_TO_MBUS_INTREG_WIN)
+		return (enable ? MV_OK : MV_ERROR);
+
+	if (enable == MV_TRUE) {
+		/* enable the window */
+		MV_REG_BIT_SET(AHB_TO_MBUS_WIN_CTRL_REG(winNum), ATMWCR_WIN_ENABLE);
+	} else {
+		/* Disable address decode winNum window                             */
+		MV_REG_BIT_RESET(AHB_TO_MBUS_WIN_CTRL_REG(winNum), ATMWCR_WIN_ENABLE);
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAhbToMbusWinRemap - Set CPU remap register for address windows.
+*
+* DESCRIPTION:
+*       After a CPU address hits one of PCI address decode windows there is an
+*       option to remap the address to a different one. For example, CPU
+*       executes a read from PCI winNum window address 0x1200.0000. This
+*       can be modified so the address on the PCI bus would be 0x1400.0000
+*       Using the PCI address remap mechanism.
+*
+* INPUT:
+*       winNum      - Peripheral winNum enumerator. Must be a PCI winNum.
+*       pAddrDecWin - CPU winNum window information data structure.
+*                     Note that caller has to fill in the base field only. The
+*                     size field is ignored.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if winNum is not a PCI one, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_U32 mvAhbToMbusWinRemap(MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 baseAddr;
+	AHB_TO_MBUS_REMAP_REG_OFFS remapRegOffs;
+
+	MV_U32 effectiveBaseAddress = 0, baseAddrValue = 0, windowSizeValue = 0;
+
+	/* Get registers offsets of given winNum                */
+	if (MV_NO_SUCH == ahbToMbusRemapRegOffsGet(winNum, &remapRegOffs))
+		return 0xffffffff;
+
+	/* 1) Set address remap low */
+	baseAddr = pAddrWin->baseLow;
+
+	/* Check base address aligment                                  */
+	/*
+	   if (MV_IS_NOT_ALIGN(baseAddr, ATMWRLR_REMAP_LOW_ALIGNMENT))
+	   {
+	   mvOsPrintf("mvAhbToMbusPciRemap: Warning. Target base 0x%x unaligned\n",
+	   baseAddr);
+	   return MV_ERROR;
+	   }
+	 */
+
+	/* BaseLow[31:16] => base register [31:16]              */
+	baseAddr = baseAddr & ATMWRLR_REMAP_LOW_MASK;
+
+	MV_REG_WRITE(remapRegOffs.lowRegOffs, baseAddr);
+	MV_REG_WRITE(remapRegOffs.highRegOffs, pAddrWin->baseHigh);
+
+	baseAddrValue = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum));
+	windowSizeValue = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum));
+
+	baseAddrValue &= ATMWBR_BASE_MASK;
+	windowSizeValue &= ATMWCR_WIN_SIZE_MASK;
+
+	/* Start calculating the effective Base Address */
+	effectiveBaseAddress = baseAddrValue;
+
+	/* The effective base address will be combined from the chopped (if any)
+	   remap value (according to the size value and remap mechanism) and the
+	   window's base address */
+	effectiveBaseAddress |= (((windowSizeValue) | 0xffff) & pAddrWin->baseLow);
+	/* If the effectiveBaseAddress exceed the window boundaries return an
+	   invalid value. */
+
+	if (effectiveBaseAddress > (baseAddrValue + (windowSizeValue | 0xffff))) {
+		mvOsPrintf("mvAhbToMbusPciRemap: Error\n");
+		return 0xffffffff;
+	}
+
+	return effectiveBaseAddress;
+}
+
+
+/*******************************************************************************
+* mvAhbToMbusWinRemapGet - Get CPU remap register for address windows.
+*
+* DESCRIPTION:
+*	Get CPU address decode windows remap window configuration for a given
+*	windows index.
+*
+* INPUT:
+*	winNum	- Peripheral winNum enumerator.
+*
+* OUTPUT:
+*	pAddrDecWin - CPU winNum window information data structure.
+*
+* RETURN:
+*	MV_ERROR if windows is not a valid remap window,
+*	MV_OK otherwise.
+*
+*******************************************************************************/
+MV_U32 mvAhbToMbusWinRemapGet(MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	AHB_TO_MBUS_REMAP_REG_OFFS remapRegOffs;
+
+	/* Get registers offsets of given winNum                */
+	if (MV_NO_SUCH == ahbToMbusRemapRegOffsGet(winNum, &remapRegOffs))
+		return 0xffffffff;
+
+	pAddrWin->baseLow = MV_REG_READ(remapRegOffs.lowRegOffs) & ATMWRLR_REMAP_LOW_MASK;
+	pAddrWin->baseHigh = MV_REG_READ(remapRegOffs.highRegOffs);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvAhbToMbusWinTargetSwap - Swap AhbToMbus windows between targets
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       target1      - CPU Interface target 1
+*       target2      - CPU Interface target 2
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if targets are illigal, or if one of the targets is not
+*	    associated to a valid window .
+*       MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvAhbToMbusWinTargetSwap(MV_TARGET target1, MV_TARGET target2)
+{
+	MV_U32 winNum1, winNum2;
+	MV_AHB_TO_MBUS_DEC_WIN winDec1, winDec2, winDecTemp;
+	AHB_TO_MBUS_REMAP_REG_OFFS remapRegs1, remapRegs2;
+	MV_U32 remapBaseLow1 = 0, remapBaseLow2 = 0;
+	MV_U32 remapBaseHigh1 = 0, remapBaseHigh2 = 0;
+
+	/* Check parameters */
+	if (target1 >= MAX_TARGETS) {
+		mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is illegal\n", target1);
+		return MV_ERROR;
+	}
+
+	if (target2 >= MAX_TARGETS) {
+		mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is illegal\n", target1);
+		return MV_ERROR;
+	}
+
+	/* get window associated with this target */
+	winNum1 = mvAhbToMbusWinTargetGet(target1);
+
+	if (winNum1 == 0xffffffff) {
+		mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d has illigal win %d\n", target1, winNum1);
+		return MV_ERROR;
+	}
+
+	/* get window associated with this target */
+	winNum2 = mvAhbToMbusWinTargetGet(target2);
+	if (winNum2 == 0xffffffff) {
+		mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d has illigal win %d\n", target2, winNum2);
+		return MV_ERROR;
+	}
+
+	/* now Get original values of both Windows */
+	if (MV_OK != mvAhbToMbusWinGet(winNum1, &winDec1)) {
+		mvOsPrintf("mvAhbToMbusWinTargetSwap: mvAhbToMbusWinGet failed win %d\n", winNum1);
+		return MV_ERROR;
+	}
+	if (MV_OK != mvAhbToMbusWinGet(winNum2, &winDec2)) {
+		mvOsPrintf("mvAhbToMbusWinTargetSwap: mvAhbToMbusWinGet failed win %d\n", winNum2);
+		return MV_ERROR;
+	}
+
+	/* disable both windows */
+	if (MV_OK != mvAhbToMbusWinEnable(winNum1, MV_FALSE)) {
+		mvOsPrintf("mvAhbToMbusWinTargetSwap: failed to enable window %d\n", winNum1);
+		return MV_ERROR;
+	}
+	if (MV_OK != mvAhbToMbusWinEnable(winNum2, MV_FALSE)) {
+		mvOsPrintf("mvAhbToMbusWinTargetSwap: failed to enable windo %d\n", winNum2);
+		return MV_ERROR;
+	}
+
+	/* now swap targets */
+
+	/* first save winDec2 values */
+	winDecTemp.addrWin.baseHigh = winDec2.addrWin.baseHigh;
+	winDecTemp.addrWin.baseLow = winDec2.addrWin.baseLow;
+	winDecTemp.addrWin.size = winDec2.addrWin.size;
+	winDecTemp.enable = winDec2.enable;
+	winDecTemp.target = winDec2.target;
+
+	/* winDec2 = winDec1 */
+	winDec2.addrWin.baseHigh = winDec1.addrWin.baseHigh;
+	winDec2.addrWin.baseLow = winDec1.addrWin.baseLow;
+	winDec2.addrWin.size = winDec1.addrWin.size;
+	winDec2.enable = winDec1.enable;
+	winDec2.target = winDec1.target;
+
+	/* winDec1 = winDecTemp */
+	winDec1.addrWin.baseHigh = winDecTemp.addrWin.baseHigh;
+	winDec1.addrWin.baseLow = winDecTemp.addrWin.baseLow;
+	winDec1.addrWin.size = winDecTemp.addrWin.size;
+	winDec1.enable = winDecTemp.enable;
+	winDec1.target = winDecTemp.target;
+
+	/* now set the new values */
+	mvAhbToMbusWinSet(winNum1, &winDec1);
+	mvAhbToMbusWinSet(winNum2, &winDec2);
+
+	/* now we will treat the remap windows if exist */
+
+	/* now check if one or both windows has a remap window
+	   as well after the swap ! */
+
+	/* if a window had a remap value differnt than the base value
+	   before the swap , then after the swap the remap value will be
+	   equal to the base value unless both windows has a remap windows */
+
+	/* first get old values */
+	if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum1, &remapRegs1)) {
+		remapBaseLow1 = MV_REG_READ(remapRegs1.lowRegOffs);
+		remapBaseHigh1 = MV_REG_READ(remapRegs1.highRegOffs);
+	}
+	if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2, &remapRegs2)) {
+		remapBaseLow2 = MV_REG_READ(remapRegs2.lowRegOffs);
+		remapBaseHigh2 = MV_REG_READ(remapRegs2.highRegOffs);
+	}
+
+	/* now do the swap */
+	if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum1, &remapRegs1)) {
+		if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2, &remapRegs2)) {
+			/* Two windows has a remap !!! so swap */
+
+			MV_REG_WRITE(remapRegs2.highRegOffs, remapBaseHigh1);
+			MV_REG_WRITE(remapRegs2.lowRegOffs, remapBaseLow1);
+
+			MV_REG_WRITE(remapRegs1.highRegOffs, remapBaseHigh2);
+			MV_REG_WRITE(remapRegs1.lowRegOffs, remapBaseLow2);
+		} else {
+			/* remap == base */
+			MV_REG_WRITE(remapRegs1.highRegOffs, winDec1.addrWin.baseHigh);
+			MV_REG_WRITE(remapRegs1.lowRegOffs, winDec1.addrWin.baseLow);
+		}
+	} else if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2, &remapRegs2)) {
+		/* remap == base */
+		MV_REG_WRITE(remapRegs2.highRegOffs, winDec2.addrWin.baseHigh);
+		MV_REG_WRITE(remapRegs2.lowRegOffs, winDec2.addrWin.baseLow);
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* ahbToMbusRemapRegOffsGet - Get CPU address remap register offsets
+*
+* DESCRIPTION:
+* 		CPU to PCI address remap registers offsets are inconsecutive.
+*		This function returns PCI address remap registers offsets.
+*
+* INPUT:
+*       winNum - Address decode window number. See MV_U32 enumerator.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*		MV_ERROR if winNum is not a PCI one.
+*
+*******************************************************************************/
+static MV_STATUS ahbToMbusRemapRegOffsGet(MV_U32 winNum, AHB_TO_MBUS_REMAP_REG_OFFS *pRemapRegs)
+{
+	switch (winNum) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 11:
+	case 12:
+		pRemapRegs->lowRegOffs = AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum);
+		pRemapRegs->highRegOffs = AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum);
+		break;
+	default:
+		pRemapRegs->lowRegOffs = 0;
+		pRemapRegs->highRegOffs = 0;
+		DB(mvOsPrintf("ahbToMbusRemapRegOffsGet: ERR. Invalid winNum %d\n", winNum));
+		return MV_NO_SUCH;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAhbToMbusAddDecShow - Print the AHB to MBus bridge address decode map.
+*
+* DESCRIPTION:
+*		This function print the CPU address decode map.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvAhbToMbusAddDecShow(MV_VOID)
+{
+	MV_AHB_TO_MBUS_DEC_WIN win;
+	MV_U32 winNum;
+	mvOsOutput("\n");
+	mvOsOutput("AHB To MBUS Bridge:\n");
+	mvOsOutput("-------------------\n");
+
+	for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS; winNum++) {
+		memset(&win, 0, sizeof(MV_AHB_TO_MBUS_DEC_WIN));
+
+		mvOsOutput("win%d - ", winNum);
+
+		if (mvAhbToMbusWinGet(winNum, &win) == MV_OK) {
+			if (win.enable) {
+				mvOsOutput("%s base %08x, ", mvCtrlTargetNameGet(win.target), win.addrWin.baseLow);
+				mvOsOutput("....");
+				mvSizePrint(win.addrWin.size);
+
+				mvOsOutput("\n");
+			} else
+				mvOsOutput("disable\n");
+		}
+	}
+}
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbus.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbus.h
new file mode 100755
index 0000000..a6301a4
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbus.h
@@ -0,0 +1,96 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvAhbToMbush
+#define __INCmvAhbToMbush
+
+/* includes */
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/sys/mvAhbToMbusRegs.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+
+/* defines  */
+
+typedef struct _mvAhbtoMbusDecWin {
+	MV_TARGET target;
+	MV_ADDR_WIN addrWin;	/* An address window */
+	MV_BOOL enable;		/* Address decode window is enabled/disabled    */
+
+} MV_AHB_TO_MBUS_DEC_WIN;
+
+/* mvAhbToMbus.h API list */
+
+MV_STATUS mvAhbToMbusInit(MV_VOID);
+MV_STATUS mvAhbToMbusWinSet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin);
+MV_STATUS mvAhbToMbusWinGet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin);
+MV_STATUS mvAhbToMbusWinEnable(MV_U32 winNum, MV_BOOL enable);
+MV_U32 mvAhbToMbusWinRemap(MV_U32 winNum, MV_ADDR_WIN *pAddrDecWin);
+MV_U32 mvAhbToMbusWinRemapGet(MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
+MV_U32 mvAhbToMbusWinTargetGet(MV_TARGET target);
+MV_U32 mvAhbToMbusWinAvailGet(MV_VOID);
+MV_STATUS mvAhbToMbusWinTargetSwap(MV_TARGET target1, MV_TARGET target2);
+
+MV_VOID mvAhbToMbusAddDecShow(MV_VOID);
+
+#endif /* __INCmvAhbToMbush */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbusRegs.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbusRegs.h
new file mode 100755
index 0000000..fdd0c5e
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvAhbToMbusRegs.h
@@ -0,0 +1,143 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvAhbToMbusRegsh
+#define __INCmvAhbToMbusRegsh
+
+/******************************/
+/* ARM Address Map Registers  */
+/******************************/
+
+#define MAX_AHB_TO_MBUS_WINS		15
+#define MV_AHB_TO_MBUS_INTREG_WIN	14
+
+#define AHB_TO_MBUS_WIN_CTRL_REG(winNum)		(MV_CPUIF_REGS_BASE + 0x0 +	\
+								(((winNum) == 14) ? 0xF0 : ((winNum)*0x10)))
+#define AHB_TO_MBUS_WIN_BASE_REG(winNum)		(MV_CPUIF_REGS_BASE + 0x04 +	\
+								(((winNum) == 14) ? 0xF0 : ((winNum)*0x10)))
+#define AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum)		(MV_CPUIF_REGS_BASE + 0x08 +	\
+								(((winNum) == 14) ? 0xF0 : ((winNum)*0x10)))
+#define AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum)		(MV_CPUIF_REGS_BASE + 0x0C +	\
+								(((winNum) == 14) ? 0xF0 : ((winNum)*0x10)))
+#define AHB_TO_MBUS_WIN_INTEREG_REG			(MV_CPUIF_REGS_BASE + 0xF0)
+
+/* Window Control Register      */
+/* AHB_TO_MBUS_WIN_CTRL_REG (ATMWCR)*/
+#define ATMWCR_WIN_ENABLE			BIT0	/* Window Enable */
+
+#define ATMWCR_WIN_TARGET_OFFS			4	/* The target interface associated with this window. */
+#define ATMWCR_WIN_TARGET_MASK			(0xf << ATMWCR_WIN_TARGET_OFFS)
+
+#define ATMWCR_WIN_ATTR_OFFS			8	/* The target interface attributes
+							   Associated with this window */
+#define ATMWCR_WIN_ATTR_MASK			(0xff << ATMWCR_WIN_ATTR_OFFS)
+#define ATMWCR_WIN_BASE_OFFS			16
+#define ATMWCR_WIN_BASE_MASK			(0xffff << ATMWCR_WIN_BASE_OFFS)
+
+/*
+Used with the Base register to set the address window size and location
+Must be programed from LSB to MSB as sequence of 1s followed
+by sequence of 0s. The number of 1s specifies the size of the window
+in 64 KB granularity (e.g. a value of 0x00FF specifies 256 = 16 MB).
+
+NOTE: A value of 0x0 specifies 64KB size.
+*/
+#define ATMWCR_WIN_SIZE_OFFS			16	/* Window Size */
+#define ATMWCR_WIN_SIZE_MASK			(0xffff << ATMWCR_WIN_SIZE_OFFS)
+#define ATMWCR_WIN_SIZE_ALIGNMENT		0x10000
+
+/*  Window Base Register     */
+/* AHB_TO_MBUS_WIN_BASE_REG (ATMWBR) */
+
+/*
+Used with the size field to set the address window size and location.
+Corresponds to transaction address[31:16]
+*/
+#define ATMWBR_BASE_OFFS			16	/* Base Address */
+#define ATMWBR_BASE_MASK			(0xffff << 	ATMWBR_BASE_OFFS)
+#define ATMWBR_BASE_ALIGNMENT			0x10000
+
+/*  Window Remap Low Register   */
+/* AHB_TO_MBUS_WIN_REMAP_LOW_REG (ATMWRLR) */
+
+/*
+Used with the size field to specifies address bits[31:0] to be driven to
+the target interface.:
+target_addr[31:16] = (addr[31:16] & size[15:0]) | (remap[31:16] & ~size[15:0])
+*/
+#define ATMWRLR_REMAP_LOW_OFFS			16	/* Remap Address */
+#define ATMWRLR_REMAP_LOW_MASK			(0xffff << ATMWRLR_REMAP_LOW_OFFS)
+#define ATMWRLR_REMAP_LOW_ALIGNMENT		0x10000
+
+/* Window Remap High Register   */
+/* AHB_TO_MBUS_WIN_REMAP_HIGH_REG (ATMWRHR) */
+
+/*
+Specifies address bits[63:32] to be driven to the target interface.
+target_addr[63:32] = (RemapHigh[31:0]
+*/
+#define ATMWRHR_REMAP_HIGH_OFFS			0	/* Remap Address */
+#define ATMWRHR_REMAP_HIGH_MASK			(0xffffffff << ATMWRHR_REMAP_HIGH_OFFS)
+
+#endif /* __INCmvAhbToMbusRegsh */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIf.c b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIf.c
new file mode 100755
index 0000000..d9be3f2
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIf.c
@@ -0,0 +1,892 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* includes */
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "ctrlEnv/sys/mvAhbToMbusRegs.h"
+#include "cpu/mvCpu.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mvSysHwConfig.h"
+#include "ddr2/mvDramIf.h"
+#include "pex/mvPexRegs.h"
+
+/*#define MV_DEBUG*/
+/* defines  */
+
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/* locals   */
+/* static functions */
+static MV_BOOL cpuTargetWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin);
+
+MV_TARGET sampleAtResetTargetArray[] = BOOT_TARGETS_NAME_ARRAY;
+/*******************************************************************************
+* mvCpuIfInit - Initialize Controller CPU interface
+*
+* DESCRIPTION:
+*       This function initialize Controller CPU interface:
+*       1. Set CPU interface configuration registers.
+*       2. Set CPU master Pizza arbiter control according to static
+*          configuration described in configuration file.
+*       3. Opens CPU address decode windows. DRAM windows are assumed to be
+*		   already set (auto detection).
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap)
+{
+	MV_U32 regVal;
+	MV_TARGET target;
+	MV_ADDR_WIN addrWin;
+
+	if (cpuAddrWinMap == NULL) {
+		DB(mvOsPrintf("mvCpuIfInit:ERR. cpuAddrWinMap == NULL\n"));
+		return MV_ERROR;
+	}
+
+	/* Set ARM Configuration register */
+	regVal = MV_REG_READ(CPU_CONFIG_REG);
+	regVal &= ~CPU_CONFIG_DEFAULT_MASK;
+	regVal |= CPU_CONFIG_DEFAULT;
+	MV_REG_WRITE(CPU_CONFIG_REG, regVal);
+
+	/* First disable all CPU target windows  */
+	for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) {
+		if ((MV_TARGET_IS_DRAM(target)) || (target == INTER_REGS))
+			continue;
+
+#if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA)
+		/* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */
+		if (MV_TARGET_IS_PCI(target))
+			continue;
+#endif
+
+#if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA)
+		/* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */
+		if (MV_TARGET_IS_PEX(target))
+			continue;
+#endif
+#if defined(MV_RUN_FROM_FLASH)
+		/* Don't disable the boot device.                               */
+		if (target == DEV_BOOCS)
+			continue;
+#endif /* MV_RUN_FROM_FLASH */
+		mvCpuIfTargetWinEnable(MV_CHANGE_BOOT_CS(target), MV_FALSE);
+	}
+
+#if defined(MV_RUN_FROM_FLASH)
+	/* Resize the bootcs windows before other windows, because this     */
+	/* window is enabled and will cause an overlap if not resized.      */
+	target = DEV_BOOCS;
+
+	if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) {
+		DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n"));
+		return MV_ERROR;
+	}
+
+	addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow;
+	addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh;
+	if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum, &addrWin)) {
+		DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n",
+			      cpuAddrWinMap[target].winNum));
+	}
+#endif /* MV_RUN_FROM_FLASH */
+
+	/* Go through all targets in user table until table terminator                  */
+	for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) {
+
+#if defined(MV_RUN_FROM_FLASH)
+		if (target == DEV_BOOCS)
+			continue;
+#endif /* MV_RUN_FROM_FLASH */
+
+		/* if DRAM auto sizing is used do not initialized DRAM target windows,  */
+		/* assuming this already has been done earlier.                         */
+#ifdef	MV_DRAM_AUTO_SIZE
+		if (MV_TARGET_IS_DRAM(target))
+			continue;
+#endif
+
+#if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA)
+		/* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */
+		if (MV_TARGET_IS_PCI(target))
+			continue;
+#endif
+
+#if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA)
+		/* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */
+		if (MV_TARGET_IS_PEX(target))
+			continue;
+#endif
+		/* If the target attribute is the same as the boot device attribute */
+		/* then it's stays disable */
+		if (MV_TARGET_IS_AS_BOOT(target))
+			continue;
+
+		if ((0 == cpuAddrWinMap[target].addrWin.size) || (DIS == cpuAddrWinMap[target].enable)) {
+			if (MV_OK != mvCpuIfTargetWinEnable(target, MV_FALSE)) {
+				DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinEnable fail\n"));
+				return MV_ERROR;
+			}
+		} else {
+			if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) {
+				DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n"));
+				return MV_ERROR;
+			}
+
+			addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow;
+			addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh;
+			if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum, &addrWin)) {
+				DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n",
+					      cpuAddrWinMap[target].winNum));
+			}
+		}
+	}
+
+#ifdef MV_INCLUDE_PEX
+/*	mvCpuIfEnablePex(0); */
+/*	mvCpuIfEnablePex(1); */
+#endif
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCpuIfTargetWinSet - Set CPU-to-peripheral target address window
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI0_MEM0)
+*       address window, also known as address decode window.
+*       A new address decode window is set for specified target address window.
+*       If address decode window parameter structure enables the window,
+*       the routine will also enable the target window, allowing CPU to access
+*       the target window.
+*
+* INPUT:
+*       target      - Peripheral target enumerator.
+*       pAddrDecWin - CPU target window data structure.
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_OK if CPU target window was set correctly, MV_ERROR in case of
+*       address window overlapps with other active CPU target window or
+*		trying to assign 36bit base address while CPU does not support that.
+*       The function returns MV_NOT_SUPPORTED, if the target is unsupported.
+*
+*******************************************************************************/
+MV_STATUS mvCpuIfTargetWinSet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin)
+{
+	MV_AHB_TO_MBUS_DEC_WIN decWin;
+	MV_U32 existingWinNum;
+	MV_DRAM_DEC_WIN addrDecWin;
+
+	target = MV_CHANGE_BOOT_CS(target);
+
+	/* Check parameters */
+	if (target >= MAX_TARGETS) {
+		mvOsPrintf("mvCpuIfTargetWinSet: target %d is illegal\n", target);
+		return MV_ERROR;
+	}
+
+	/* 2) Check if the requested window overlaps with current windows               */
+	if (MV_TRUE == cpuTargetWinOverlap(target, &pAddrDecWin->addrWin)) {
+		mvOsPrintf("mvCpuIfTargetWinSet: ERR. Target %d overlap\n", target);
+		return MV_BAD_PARAM;
+	}
+
+	if (MV_TARGET_IS_DRAM(target)) {
+		/* copy relevant data to MV_DRAM_DEC_WIN structure */
+		addrDecWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh;
+		addrDecWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow;
+		addrDecWin.addrWin.size = pAddrDecWin->addrWin.size;
+		addrDecWin.enable = pAddrDecWin->enable;
+
+		if (mvDramIfWinSet(target, &addrDecWin) != MV_OK) {
+			mvOsPrintf("mvCpuIfTargetWinSet: mvDramIfWinSet Failed\n");
+			return MV_ERROR;
+		}
+	} else {
+		/* copy relevant data to MV_AHB_TO_MBUS_DEC_WIN structure */
+		decWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow;
+		decWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh;
+		decWin.addrWin.size = pAddrDecWin->addrWin.size;
+		decWin.enable = pAddrDecWin->enable;
+		decWin.target = target;
+
+		existingWinNum = mvAhbToMbusWinTargetGet(target);
+
+		/* check if there is already another Window configured
+		   for this target */
+		if ((existingWinNum < MAX_AHB_TO_MBUS_WINS) && (existingWinNum != pAddrDecWin->winNum)) {
+			/* if we want to enable the new window number
+			   passed by the user , then the old one should
+			   be disabled */
+			if (MV_TRUE == pAddrDecWin->enable) {
+				/* be sure it is disabled */
+				mvAhbToMbusWinEnable(existingWinNum, MV_FALSE);
+			}
+		}
+
+		if (mvAhbToMbusWinSet(pAddrDecWin->winNum, &decWin) != MV_OK) {
+			mvOsPrintf("mvCpuIfTargetWinSet: mvAhbToMbusWinSet Failed\n");
+			return MV_ERROR;
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCpuIfTargetWinGet - Get CPU-to-peripheral target address window
+*
+* DESCRIPTION:
+*		Get the CPU peripheral target address window.
+*
+* INPUT:
+*       target - Peripheral target enumerator
+*
+* OUTPUT:
+*       pAddrDecWin - CPU target window information data structure.
+*
+* RETURN:
+*       MV_OK if target exist, MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin)
+{
+	MV_U32 winNum = 0xffffffff;
+	MV_AHB_TO_MBUS_DEC_WIN decWin;
+	MV_DRAM_DEC_WIN addrDecWin;
+	MV_U32 dramEn = 0;
+	MV_TARGET i;
+
+	target = MV_CHANGE_BOOT_CS(target);
+
+	/* Check parameters */
+	if (target >= MAX_TARGETS) {
+		mvOsPrintf("mvCpuIfTargetWinGet: target %d is illegal\n", target);
+		return MV_ERROR;
+	}
+
+	if (MV_TARGET_IS_DRAM(target)) {
+		/* If none of the DRAM windows is enabled, then the CPU DRAM
+		 ** access is going through the XBAR.
+		 */
+		for (i = SDRAM_CS0; i < SDRAM_CS3; i++) {
+			if (mvDramIfWinGet(target, &addrDecWin) != MV_OK) {
+				mvOsPrintf("mvCpuIfTargetWinGet: Failed to get window target %d\n", i);
+				return MV_ERROR;
+			}
+			if (addrDecWin.enable == MV_TRUE)
+				dramEn = 1;
+		}
+	}
+
+	if ((dramEn == 1) && (MV_TARGET_IS_DRAM(target))) {
+		if (mvDramIfWinGet(target, &addrDecWin) != MV_OK) {
+			mvOsPrintf("mvCpuIfTargetWinGet: Failed to get window target %d\n", target);
+			return MV_ERROR;
+		}
+
+		/* copy relevant data to MV_CPU_DEC_WIN structure */
+		pAddrDecWin->addrWin.baseLow = addrDecWin.addrWin.baseLow;
+		pAddrDecWin->addrWin.baseHigh = addrDecWin.addrWin.baseHigh;
+		pAddrDecWin->addrWin.size = addrDecWin.addrWin.size;
+		pAddrDecWin->enable = addrDecWin.enable;
+		pAddrDecWin->winNum = 0xffffffff;
+	} else {
+		/* get the Window number associated with this target */
+		winNum = mvAhbToMbusWinTargetGet(target);
+		if (winNum >= MAX_AHB_TO_MBUS_WINS)
+			return MV_NO_SUCH;
+
+		if (mvAhbToMbusWinGet(winNum, &decWin) != MV_OK) {
+			mvOsPrintf("%s: mvAhbToMbusWinGet Failed at winNum = %d\n", __func__, winNum);
+			return MV_ERROR;
+		}
+
+		/* copy relevant data to MV_CPU_DEC_WIN structure */
+		pAddrDecWin->addrWin.baseLow = decWin.addrWin.baseLow;
+		pAddrDecWin->addrWin.baseHigh = decWin.addrWin.baseHigh;
+		pAddrDecWin->addrWin.size = decWin.addrWin.size;
+		pAddrDecWin->enable = decWin.enable;
+		pAddrDecWin->winNum = winNum;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCpuIfTargetWinEnable - Enable/disable a CPU address decode window
+*
+* DESCRIPTION:
+*       This function enable/disable a CPU address decode window.
+*       if parameter 'enable' == MV_TRUE the routine will enable the
+*       window, thus enabling CPU accesses (before enabling the window it is
+*       tested for overlapping). Otherwise, the window will be disabled.
+*
+* INPUT:
+*       target - Peripheral target enumerator.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_ERROR if protection window number was wrong, or the window
+*       overlapps other target window.
+*
+*******************************************************************************/
+MV_STATUS mvCpuIfTargetWinEnable(MV_TARGET target, MV_BOOL enable)
+{
+	MV_U32 winNum, temp;
+	MV_CPU_DEC_WIN addrDecWin;
+
+	target = MV_CHANGE_BOOT_CS(target);
+
+	/* Check parameters */
+	if (target >= MAX_TARGETS) {
+		mvOsPrintf("mvCpuIfTargetWinEnable: target %d is illegal\n", target);
+		return MV_ERROR;
+	}
+
+	/* get the window and check if it exist */
+	temp = mvCpuIfTargetWinGet(target, &addrDecWin);
+	if (MV_NO_SUCH == temp) {
+		return (enable ? MV_ERROR : MV_OK);
+	} else if (MV_OK != temp) {
+		mvOsPrintf("%s: ERR. Getting target %d failed.\n", __func__, target);
+		return MV_ERROR;
+	}
+
+	/* check overlap */
+	if (MV_TRUE == enable) {
+		if (MV_TRUE == cpuTargetWinOverlap(target, &addrDecWin.addrWin)) {
+			DB(mvOsPrintf("%s: ERR. Target %d overlap\n", __func__, target));
+			return MV_ERROR;
+		}
+	}
+
+	if (MV_TARGET_IS_DRAM(target)) {
+		if (mvDramIfWinEnable(target, enable) != MV_OK) {
+			mvOsPrintf("mvCpuIfTargetWinGet: mvDramIfWinEnable Failed at \n");
+			return MV_ERROR;
+		}
+	} else {
+		/* get the Window number associated with this target */
+		winNum = mvAhbToMbusWinTargetGet(target);
+
+		if (winNum >= MAX_AHB_TO_MBUS_WINS)
+			return (enable ? MV_ERROR : MV_OK);
+
+		if (mvAhbToMbusWinEnable(winNum, enable) != MV_OK) {
+			mvOsPrintf("mvCpuIfTargetWinGet: Failed to enable window = %d\n", winNum);
+			return MV_ERROR;
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCpuIfTargetWinSizeGet - Get CPU target address window size
+*
+* DESCRIPTION:
+*		Get the size of CPU-to-peripheral target window.
+*
+* INPUT:
+*       target - Peripheral target enumerator
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit size. Function also returns '0' if window is closed.
+*		Function returns 0xFFFFFFFF in case of an error.
+*
+*******************************************************************************/
+MV_U32 mvCpuIfTargetWinSizeGet(MV_TARGET target)
+{
+	MV_CPU_DEC_WIN addrDecWin;
+
+	target = MV_CHANGE_BOOT_CS(target);
+
+	/* Check parameters */
+	if (target >= MAX_TARGETS) {
+		mvOsPrintf("mvCpuIfTargetWinSizeGet: target %d is illegal\n", target);
+		return 0;
+	}
+
+	/* Get the winNum window */
+	if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) {
+		mvOsPrintf("mvCpuIfTargetWinSizeGet:ERR. Getting target %d failed.\n", target);
+		return 0;
+	}
+
+	/* Check if window is enabled   */
+	if (addrDecWin.enable == MV_TRUE)
+		return (addrDecWin.addrWin.size);
+	else
+		return 0;	/* Window disabled. return 0 */
+}
+
+/*******************************************************************************
+* mvCpuIfTargetWinBaseLowGet - Get CPU target address window base low
+*
+* DESCRIPTION:
+*       CPU-to-peripheral target address window base is constructed of
+*       two parts: Low and high.
+*		This function gets the CPU peripheral target low base address.
+*
+* INPUT:
+*       target - Peripheral target enumerator
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit low base address.
+*
+*******************************************************************************/
+MV_U32 mvCpuIfTargetWinBaseLowGet(MV_TARGET target)
+{
+	MV_CPU_DEC_WIN addrDecWin;
+
+	target = MV_CHANGE_BOOT_CS(target);
+
+	/* Check parameters */
+	if (target >= MAX_TARGETS) {
+		mvOsPrintf("mvCpuIfTargetWinBaseLowGet: target %d is illegal\n", target);
+		return 0xffffffff;
+	}
+
+	/* Get the target window */
+	if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) {
+		mvOsPrintf("mvCpuIfTargetWinBaseLowGet:ERR. Getting target %d failed.\n", target);
+		return 0xffffffff;
+	}
+
+	if (MV_FALSE == addrDecWin.enable)
+		return 0xffffffff;
+
+	return (addrDecWin.addrWin.baseLow);
+}
+
+/*******************************************************************************
+* mvCpuIfTargetWinBaseHighGet - Get CPU target address window base high
+*
+* DESCRIPTION:
+*       CPU-to-peripheral target address window base is constructed of
+*       two parts: Low and high.
+*		This function gets the CPU peripheral target high base address.
+*
+* INPUT:
+*       target - Peripheral target enumerator
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit high base address.
+*
+*******************************************************************************/
+MV_U32 mvCpuIfTargetWinBaseHighGet(MV_TARGET target)
+{
+	MV_CPU_DEC_WIN addrDecWin;
+
+	target = MV_CHANGE_BOOT_CS(target);
+
+	/* Check parameters */
+	if (target >= MAX_TARGETS) {
+		mvOsPrintf("mvCpuIfTargetWinBaseLowGet: target %d is illegal\n", target);
+		return 0xffffffff;
+	}
+
+	/* Get the target window */
+	if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) {
+		mvOsPrintf("mvCpuIfTargetWinBaseHighGet:ERR. Getting target %d failed.\n", target);
+		return 0xffffffff;
+	}
+
+	if (MV_FALSE == addrDecWin.enable)
+		return 0;
+
+	return (addrDecWin.addrWin.baseHigh);
+}
+
+#if defined(MV_INCLUDE_PEX)
+/*******************************************************************************
+* mvCpuIfPexRemap - Set CPU remap register for address windows.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pexTarget   - Peripheral target enumerator. Must be a PEX target.
+*       pAddrDecWin - CPU target window information data structure.
+*                     Note that caller has to fill in the base field only. The
+*                     size field is ignored.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if target is not a PEX one, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin)
+{
+	MV_U32 winNum;
+
+	/* Check parameters */
+	if (mvCtrlPexMaxIfGet() > 1) {
+		if ((!MV_TARGET_IS_PEX1(pexTarget)) && (!MV_TARGET_IS_PEX0(pexTarget))) {
+			mvOsPrintf("mvCpuIfPexRemap: target %d is illegal\n", pexTarget);
+			return 0xffffffff;
+		}
+	} else {
+		if (!MV_TARGET_IS_PEX0(pexTarget)) {
+			mvOsPrintf("mvCpuIfPexRemap: target %d is illegal\n", pexTarget);
+			return 0xffffffff;
+		}
+	}
+
+	/* get the Window number associated with this target */
+	winNum = mvAhbToMbusWinTargetGet(pexTarget);
+
+	if (winNum >= MAX_AHB_TO_MBUS_WINS) {
+		mvOsPrintf("mvCpuIfPexRemap: mvAhbToMbusWinTargetGet Failed\n");
+		return 0xffffffff;
+	}
+
+	return mvAhbToMbusWinRemap(winNum, pAddrDecWin);
+}
+
+#endif
+
+#if defined(MV_INCLUDE_PCI)
+/*******************************************************************************
+* mvCpuIfPciRemap - Set CPU remap register for address windows.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pciTarget   - Peripheral target enumerator. Must be a PCI target.
+*       pAddrDecWin - CPU target window information data structure.
+*                     Note that caller has to fill in the base field only. The
+*                     size field is ignored.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if target is not a PCI one, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_U32 mvCpuIfPciRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin)
+{
+	MV_U32 winNum;
+
+	/* Check parameters */
+	if (!MV_TARGET_IS_PCI(pciTarget)) {
+		mvOsPrintf("mvCpuIfPciRemap: target %d is illegal\n", pciTarget);
+		return 0xffffffff;
+	}
+
+	/* get the Window number associated with this target */
+	winNum = mvAhbToMbusWinTargetGet(pciTarget);
+
+	if (winNum >= MAX_AHB_TO_MBUS_WINS) {
+		mvOsPrintf("mvCpuIfPciRemap: mvAhbToMbusWinTargetGet Failed\n");
+		return 0xffffffff;
+	}
+
+	return mvAhbToMbusWinRemap(winNum, pAddrDecWin);
+}
+#endif /* MV_INCLUDE_PCI */
+
+/*******************************************************************************
+* mvCpuIfPciIfRemap - Set CPU remap register for address windows.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pciTarget   - Peripheral target enumerator. Must be a PCI target.
+*       pAddrDecWin - CPU target window information data structure.
+*                     Note that caller has to fill in the base field only. The
+*                     size field is ignored.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if target is not a PCI one, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciIfTarget, MV_ADDR_WIN *pAddrDecWin)
+{
+#if defined(MV_INCLUDE_PEX)
+	if (MV_TARGET_IS_PEX(pciIfTarget))
+		return mvCpuIfPexRemap(pciIfTarget, pAddrDecWin);
+
+#endif
+#if defined(MV_INCLUDE_PCI)
+
+	if (MV_TARGET_IS_PCI(pciIfTarget))
+		return mvCpuIfPciRemap(pciIfTarget, pAddrDecWin);
+#endif
+	return 0;
+}
+
+/*******************************************************************************
+* mvCpuIfTargetOfBaseAddressGet - Get the target according to base address
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       baseAddress -  base address to be checked
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       the target number that baseAddress belongs to or MAX_TARGETS is not
+*       found
+*
+*******************************************************************************/
+MV_TARGET mvCpuIfTargetOfBaseAddressGet(MV_U32 baseAddress)
+{
+	MV_CPU_DEC_WIN win;
+	MV_U32 target;
+
+	for (target = 0; target < MAX_TARGETS; target++) {
+		if (mvCpuIfTargetWinGet(target, &win) == MV_OK) {
+			if (win.enable) {
+				if ((baseAddress >= win.addrWin.baseLow) &&
+				    (baseAddress < win.addrWin.baseLow + win.addrWin.size))
+					break;
+			}
+		} else
+			return MAX_TARGETS;
+	}
+
+	return target;
+}
+
+/*******************************************************************************
+* cpuTargetWinOverlap - Detect CPU address decode windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviur is expected in case CPU address decode
+*       windows overlapps.
+*       This function detects CPU address decode windows overlapping of a
+*       specified target. The function does not check the target itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       target      - Peripheral target enumerator.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlaps current address
+*       decode map, MV_FALSE otherwise.
+*
+*******************************************************************************/
+static MV_BOOL cpuTargetWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 targetNum;
+	MV_CPU_DEC_WIN addrDecWin;
+	MV_STATUS status;
+
+	for (targetNum = 0; targetNum < MAX_TARGETS; targetNum++) {
+#if defined(MV_RUN_FROM_FLASH)
+		if (MV_TARGET_IS_AS_BOOT(target)) {
+			if (MV_CHANGE_BOOT_CS(targetNum) == target)
+				continue;
+		}
+#endif /* MV_RUN_FROM_FLASH */
+
+		/* don't check our target or illegal targets */
+		if (targetNum == target)
+			continue;
+
+		/* Get window parameters        */
+		status = mvCpuIfTargetWinGet(targetNum, &addrDecWin);
+		if (MV_NO_SUCH == status)
+			continue;
+
+		if (MV_OK != status) {
+			DB(mvOsPrintf("cpuTargetWinOverlap: ERR. TargetWinGet failed\n"));
+			return MV_TRUE;
+		}
+
+		/* Do not check disabled windows        */
+		if (MV_FALSE == addrDecWin.enable)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) {
+			DB(mvOsPrintf("cpuTargetWinOverlap: Required target %d overlap current %d\n",
+				      target, targetNum));
+			return MV_TRUE;
+		}
+	}
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvCpuIfAddDecShow - Print the CPU address decode map.
+*
+* DESCRIPTION:
+*		This function print the CPU address decode map.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvCpuIfAddDecShow(MV_VOID)
+{
+	MV_CPU_DEC_WIN win;
+	MV_U32 target;
+
+	mvOsOutput("\n");
+	mvOsOutput("CPU Interface\n");
+	mvOsOutput("-------------\n");
+
+	for (target = 0; target < MAX_TARGETS; target++) {
+		memset(&win, 0, sizeof(MV_CPU_DEC_WIN));
+
+		mvOsOutput("%s ", mvCtrlTargetNameGet(target));
+		mvOsOutput("....");
+
+		if (mvCpuIfTargetWinGet(target, &win) == MV_OK) {
+			if (win.enable == MV_TRUE) {
+				mvOsOutput("base %08x, ", win.addrWin.baseLow);
+				mvSizePrint(win.addrWin.size);
+				mvOsOutput("\n");
+			} else
+				mvOsOutput("disable\n");
+		} else if (mvCpuIfTargetWinGet(target, &win) == MV_NO_SUCH) {
+			mvOsOutput("no such\n");
+		}
+	}
+}
+
+#if defined(MV_INCLUDE_PEX)
+/*******************************************************************************
+* mvCpuIfEnablePex - Enable PCI Express.
+*
+* DESCRIPTION:
+*	This function enables PCI Express access to the device address
+*	space.
+*
+* INPUT:
+*	pexIf - The PCI-E interface to enable.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvCpuIfEnablePex(MV_U32 pexIf)
+{
+	MV_U32 reg;
+
+	if (mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf) == MV_TRUE) {
+		if (pexIf == 0) {
+			reg = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0, PEX_LINK_CAPABILITY_REG));
+			reg &= ~PXLC_MAX_LNK_SPEED_MASK;
+			reg |= (0x1 << PXLC_MAX_LNK_SPEED_OFFS);
+			MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(0, PEX_LINK_CAPABILITY_REG), reg);
+		}
+
+		/* CPU config register Pex enable */
+		MV_REG_BIT_SET(CPU_CTRL_STAT_REG, CCSR_PCI_ACCESS_MASK(pexIf));
+	}
+}
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIf.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIf.h
new file mode 100755
index 0000000..0df8f7d
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIf.h
@@ -0,0 +1,119 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCpuIfh
+#define __INCmvCpuIfh
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+/* includes */
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/sys/mvCpuIfRegs.h"
+#include "ctrlEnv/sys/mvAhbToMbus.h"
+#include "ddr2/mvDramIf.h"
+#if defined(MV_INCLUDE_PEX)
+#include "pci-if/mvPciIf.h"
+#include "pex/mvPex.h"
+#endif
+
+/* defines  */
+
+/* typedefs */
+/* This structure describes CPU interface address decode window	*/
+typedef struct _mvCpuIfDecWin {
+	MV_ADDR_WIN addrWin;	/* An address window */
+	MV_U32 winNum;		/* Window Number in the AHB To Mbus bridge */
+	MV_BOOL enable;		/* Address decode window is enabled/disabled */
+} MV_CPU_DEC_WIN;
+
+/* mvCpuIfLib.h API list */
+
+/* mvCpuIfLib.h API list */
+
+MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap);
+MV_STATUS mvCpuIfTargetWinSet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin);
+MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin);
+MV_STATUS mvCpuIfTargetWinEnable(MV_TARGET target, MV_BOOL enable);
+MV_U32 mvCpuIfTargetWinSizeGet(MV_TARGET target);
+MV_U32 mvCpuIfTargetWinBaseLowGet(MV_TARGET target);
+MV_U32 mvCpuIfTargetWinBaseHighGet(MV_TARGET target);
+MV_TARGET mvCpuIfTargetOfBaseAddressGet(MV_U32 baseAddress);
+#if defined(MV_INCLUDE_PEX)
+MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin);
+MV_VOID mvCpuIfEnablePex(MV_U32 pexIf);
+#endif
+#if defined(MV_INCLUDE_PCI)
+MV_U32 mvCpuIfPciRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin);
+#endif
+MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin);
+
+MV_VOID mvCpuIfAddDecShow(MV_VOID);
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif /* __INCmvCpuIfh */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIfInit.S b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIfInit.S
new file mode 100755
index 0000000..2426ad6
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIfInit.S
@@ -0,0 +1,145 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#define MV_ASMLANGUAGE
+#include "mvCommon.h"
+#include "mvOsAsm.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvDeviceId.h"
+#include "mvCtrlEnvRegs.h"
+#include "mvCpuIfRegs.h"
+#include "mvCtrlEnvAsm.h"
+
+/*******************************************************************************
+* mvCpuIfPreInit - Make early initialization of CPU interface.
+*
+* DESCRIPTION:
+*       The function will initialize the CPU interface parameters that must
+*       be initialize before any BUS activity towards the DDR interface,
+*       which means it must be executed from ROM. Because of that, the function
+*       is implemented in assembly code.
+*       The function configure the following CPU config register parameters:
+*       1) CPU2MbusLTickDrv
+*       2) CPU2MbusLTickSample.
+*       NOTE: This function must be called AFTER the internal register
+*       base is modified to INTER_REGS_BASE.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*       r11 holds return function address.
+*******************************************************************************/
+#define MV88F6281_PCKG_OPT	2
+#define MV88F6192_PCKG_OPT	1
+#define MV88F6180_PCKG_OPT	0
+
+.global _mvCpuIfPreInit
+
+_mvCpuIfPreInit:
+
+mov r11, LR			/* Save link register */
+    b done
+#if 0
+    /* Read device ID  */
+MV_CTRL_MODEL_GET_ASM(r4, r5);
+
+	/* goto calcConfigReg if device is 6281/6282 */
+ldr r5, = MV88F6281_PCKG_OPT cmp r4, r5 beq calcConfigReg
+    /* goto calcConfigReg if device is 6192/6190 */
+    ldr r5, = MV88F6192_PCKG_OPT cmp r4, r5 beq calcConfigReg
+    /* Else 6180 */
+    /* Get the "sample on reset" register */
+MV_REG_READ_ASM(r4, r5, MPP_SAMPLE_AT_RESET)
+ldr r5, = MSAR_CPUCLCK_MASK_6180 and r5, r4, r5 mov r5, r5, lsr
+#MSAR_CPUCLCK_OFFS_6180
+    ldr r4, = CPU_2_MBUSL_DDR_CLK_1x3 cmp r5,
+#CPU_2_DDR_CLK_1x3_1
+    beq setConfigReg ldr r4, = CPU_2_MBUSL_DDR_CLK_1x4 cmp r5,
+#CPU_2_DDR_CLK_1x4_1
+beq setConfigReg b setConfigReg calcConfigReg:
+	/* Get the "sample on reset" register */
+MV_REG_READ_ASM(r4, r5, MPP_SAMPLE_AT_RESET)
+ldr r5, = MSAR_DDRCLCK_RTIO_MASK and r5, r4, r5 mov r5, r5, lsr
+#MSAR_DDRCLCK_RTIO_OFFS
+    ldr r4, = CPU_2_MBUSL_DDR_CLK_1x3 cmp r5,
+#CPU_2_DDR_CLK_1x3
+    beq setConfigReg ldr r4, = CPU_2_MBUSL_DDR_CLK_1x4 cmp r5,
+#CPU_2_DDR_CLK_1x4
+    beq setConfigReg
+    /* Else */
+ldr r4, = 0 setConfigReg:
+	/* Read CPU Config register */
+MV_REG_READ_ASM(r7, r5, CPU_CONFIG_REG)
+    ldr r5, = ~(CCR_CPU_2_MBUSL_TICK_DRV_MASK | CCR_CPU_2_MBUSL_TICK_SMPL_MASK)
+and r7, r7, r5			/* Clear register fields */
+ orr r7, r7, r4			/* Set the values according to the findings */
+MV_REG_WRITE_ASM(r7, r5, CPU_CONFIG_REG)
+#endif
+done:mov PC, r11		/* r11 is saved link register */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIfRegs.h b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIfRegs.h
new file mode 100755
index 0000000..e60b5f1
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/ctrlEnv/sys/mvCpuIfRegs.h
@@ -0,0 +1,301 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCpuIfRegsh
+#define __INCmvCpuIfRegsh
+
+/****************************************/
+/* ARM Control and Status Registers Map */
+/****************************************/
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ctrlEnv/mvCtrlEnvRegs.h"
+
+#define MV_CPUIF_REGS_BASE			(MV_CPUIF_REGS_OFFSET)
+
+#define CPU_CONFIG_REG				(MV_CPUIF_REGS_BASE + 0x100)
+#define CPU_CTRL_STAT_REG			(MV_CPUIF_REGS_BASE + 0x104)
+#define CPU_RSTOUTN_MASK_REG			(MV_CPUIF_REGS_BASE + 0x108)
+#define CPU_SYS_SOFT_RST_REG			(MV_CPUIF_REGS_BASE + 0x10C)
+#define CPU_AHB_MBUS_CAUSE_INT_REG		(MV_CPUIF_REGS_BASE + 0x110)
+#define CPU_AHB_MBUS_MASK_INT_REG		(MV_CPUIF_REGS_BASE + 0x114)
+#define CPU_FTDLL_CONFIG_REG			(MV_CPUIF_REGS_BASE + 0x120)
+#define CPU_L2_CONFIG_REG			(MV_CPUIF_REGS_BASE + 0x128)
+
+/*
+#define AXI_P_D_CTRL_REG			(MV_MISC_REGS_BASE + 0x224)
+#define CPU_CONTROL_REG				(MV_MISC_REGS_BASE + 0x25C)
+#define CPU_CTRL_PMU_CPU_RST_EN_OFFS		1
+#define CPU_CTRL_PMU_CPU_RST_EN_MASK		(0x1 << CPU_CTRL_PMU_CPU_RST_EN_OFFS)
+*/
+
+/* ARM Configuration register */
+/* CPU_CONFIG_REG (CCR) */
+
+/* Reset vector location */
+#define CCR_VEC_INIT_LOC_OFFS			1
+#define CCR_VEC_INIT_LOC_MASK			BIT1
+/* reset at 0x00000000 */
+#define CCR_VEC_INIT_LOC_0000			(0 << CCR_VEC_INIT_LOC_OFFS)
+/* reset at 0xFFFF0000 */
+#define CCR_VEC_INIT_LOC_FF00			(1 << CCR_VEC_INIT_LOC_OFFS)
+
+#define CCR_AHB_ERROR_PROP_OFFS			2
+#define CCR_AHB_ERROR_PROP_MASK			BIT2
+/* Erros are not propogated to AHB */
+#define CCR_AHB_ERROR_PROP_NO_INDICATE		(0 << CCR_AHB_ERROR_PROP_OFFS)
+/* Erros are propogated to AHB */
+#define CCR_AHB_ERROR_PROP_INDICATE		(1 << CCR_AHB_ERROR_PROP_OFFS)
+
+#define CCR_ENDIAN_INIT_OFFS			3
+#define CCR_ENDIAN_INIT_MASK			BIT3
+#define CCR_ENDIAN_INIT_LITTLE			(0 << CCR_ENDIAN_INIT_OFFS)
+#define CCR_ENDIAN_INIT_BIG			(1 << CCR_ENDIAN_INIT_OFFS)
+
+#define CCR_INCR_EN_OFFS			4
+#define CCR_INCR_EN_MASK			BIT4
+#define CCR_INCR_EN				BIT4
+
+#define CCR_NCB_BLOCKING_OFFS			5
+#define CCR_NCB_BLOCKING_MASK			(1 << CCR_NCB_BLOCKING_OFFS)
+#define CCR_NCB_BLOCKING_NON			(0 << CCR_NCB_BLOCKING_OFFS)
+#define CCR_NCB_BLOCKING_EN			(1 << CCR_NCB_BLOCKING_OFFS)
+
+#define CCR_CPU_2_MBUSL_TICK_DRV_OFFS		8
+#define CCR_CPU_2_MBUSL_TICK_DRV_MASK		(0xF << CCR_CPU_2_MBUSL_TICK_DRV_OFFS)
+#define CCR_CPU_2_MBUSL_TICK_SMPL_OFFS		12
+#define CCR_CPU_2_MBUSL_TICK_SMPL_MASK		(0xF << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS)
+#define CCR_ICACH_PREF_BUF_ENABLE		BIT16
+#define CCR_DCACH_PREF_BUF_ENABLE		BIT17
+
+/* Ratio options for CPU to DDR for 6281/6192/6190 */
+#define CPU_2_DDR_CLK_1x3	    4
+#define CPU_2_DDR_CLK_1x4	    6
+
+/* Ratio options for CPU to DDR for 6281 only */
+#define CPU_2_DDR_CLK_2x9	    7
+#define CPU_2_DDR_CLK_1x5	    8
+#define CPU_2_DDR_CLK_1x6	    9
+
+/* Ratio options for CPU to DDR for 6180 only */
+#define CPU_2_DDR_CLK_1x3_1	    0x5
+#define CPU_2_DDR_CLK_1x4_1	    0x6
+
+/* Default values for CPU to Mbus-L DDR Interface Tick Driver and 	*/
+/* CPU to Mbus-L Tick Sample fields in CPU config register		*/
+
+#define TICK_DRV_1x1	0
+#define TICK_DRV_1x2	0
+#define TICK_DRV_1x3	1
+#define TICK_DRV_1x4	2
+#define TICK_SMPL_1x1	0
+#define TICK_SMPL_1x2	1
+#define TICK_SMPL_1x3	0
+#define TICK_SMPL_1x4	0
+
+#define CPU_2_MBUSL_DDR_CLK_1x2						\
+		 ((TICK_DRV_1x2  << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | 	\
+		  (TICK_SMPL_1x2 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS))
+#define CPU_2_MBUSL_DDR_CLK_1x3						\
+		 ((TICK_DRV_1x3  << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | 	\
+		  (TICK_SMPL_1x3 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS))
+#define CPU_2_MBUSL_DDR_CLK_1x4						\
+		 ((TICK_DRV_1x4  << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | 	\
+		  (TICK_SMPL_1x4 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS))
+
+/* ARM Control and Status register */
+/* CPU_CTRL_STAT_REG (CCSR) */
+
+/*
+This is used to block PCI express\PCI from access Socrates/Feroceon GP
+while ARM boot is still in progress
+*/
+
+#define CCSR_PCI_ACCESS_OFFS(id)		((id == 0) ? 0 : 3)
+#define CCSR_PCI_ACCESS_MASK(id)		((id == 0) ? BIT0 : BIT3)
+#define CCSR_PCI_ACCESS_ENABLE(id)		(0 << CCSR_PCI_ACCESS_OFFS(id))
+#define CCSR_PCI_ACCESS_DISBALE(id)		(1 << CCSR_PCI_ACCESS_OFFS(id))
+
+#define CCSR_ARM_RESET				BIT1
+#define CCSR_SELF_INT				BIT2
+#define CCSR_BIG_ENDIAN				BIT15
+
+#define CCSR_CPU_SW_INT_BLK_OFFSET		28
+#define CCSR_CPU_SW_INT_BLK_MASK		(1 << CCSR_CPU_SW_INT_BLK_OFFSET)
+
+/* RSTOUTn Mask Register */
+/* CPU_RSTOUTN_MASK_REG (CRMR) */
+
+#define CRMR_PEX_RST_OUT_OFFS			0
+#define CRMR_PEX_RST_OUT_MASK			BIT0
+#define CRMR_PEX_RST_OUT_ENABLE			(1 << CRMR_PEX_RST_OUT_OFFS)
+#define CRMR_PEX_RST_OUT_DISABLE		(0 << CRMR_PEX_RST_OUT_OFFS)
+
+#define CRMR_WD_RST_OUT_OFFS			1
+#define CRMR_WD_RST_OUT_MASK			BIT1
+#define CRMR_WD_RST_OUT_ENABLE			(1 << CRMR_WD_RST_OUT_OFFS)
+#define CRMR_WD_RST_OUT_DISBALE			(0 << CRMR_WD_RST_OUT_OFFS)
+
+#define CRMR_SOFT_RST_OUT_OFFS			2
+#define CRMR_SOFT_RST_OUT_MASK			BIT2
+#define CRMR_SOFT_RST_OUT_ENABLE		(1 << CRMR_SOFT_RST_OUT_OFFS)
+#define CRMR_SOFT_RST_OUT_DISBALE		(0 << CRMR_SOFT_RST_OUT_OFFS)
+
+/* System Software Reset Register */
+/* CPU_SYS_SOFT_RST_REG (CSSRR) */
+
+#define CSSRR_SYSTEM_SOFT_RST			BIT0
+
+/* AHB to Mbus Bridge Interrupt Cause Register*/
+/* CPU_AHB_MBUS_CAUSE_INT_REG (CAMCIR) */
+
+#define CAMCIR_ARM_SELF_INT			BIT0
+#define CAMCIR_ARM_TIMER0_INT_REQ		BIT1
+#define CAMCIR_ARM_TIMER1_INT_REQ		BIT2
+#define CAMCIR_ARM_WD_TIMER_INT_REQ		BIT3
+
+/* AHB to Mbus Bridge Interrupt Mask Register*/
+/* CPU_AHB_MBUS_MASK_INT_REG (CAMMIR) */
+
+#define CAMCIR_ARM_SELF_INT_OFFS		0
+#define CAMCIR_ARM_SELF_INT_MASK		BIT0
+#define CAMCIR_ARM_SELF_INT_EN			(1 << CAMCIR_ARM_SELF_INT_OFFS)
+#define CAMCIR_ARM_SELF_INT_DIS			(0 << CAMCIR_ARM_SELF_INT_OFFS)
+
+#define CAMCIR_ARM_TIMER0_INT_REQ_OFFS		1
+#define CAMCIR_ARM_TIMER0_INT_REQ_MASK		BIT1
+#define CAMCIR_ARM_TIMER0_INT_REQ_EN		(1 << CAMCIR_ARM_TIMER0_INT_REQ_OFFS)
+#define CAMCIR_ARM_TIMER0_INT_REQ_DIS		(0 << CAMCIR_ARM_TIMER0_INT_REQ_OFFS)
+
+#define CAMCIR_ARM_TIMER1_INT_REQ_OFFS		2
+#define CAMCIR_ARM_TIMER1_INT_REQ_MASK		BIT2
+#define CAMCIR_ARM_TIMER1_INT_REQ_EN		(1 << CAMCIR_ARM_TIMER1_INT_REQ_OFFS)
+#define CAMCIR_ARM_TIMER1_INT_REQ_DIS		(0 << CAMCIR_ARM_TIMER1_INT_REQ_OFFS)
+
+#define CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS 	3
+#define CAMCIR_ARM_WD_TIMER_INT_REQ_MASK 	BIT3
+#define CAMCIR_ARM_WD_TIMER_INT_REQ_EN	 	(1 << CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS)
+#define CAMCIR_ARM_WD_TIMER_INT_REQ_DIS	 	(0 << CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS)
+
+/* CPU FTDLL Config register (CFCR) fields */
+#define CFCR_FTDLL_ICACHE_TAG_OFFS		0
+#define CFCR_FTDLL_ICACHE_TAG_MASK		(0x7F << CFCR_FTDLL_ICACHE_TAG_OFFS)
+#define CFCR_FTDLL_DCACHE_TAG_OFFS		8
+#define CFCR_FTDLL_DCACHE_TAG_MASK		(0x7F << CFCR_FTDLL_DCACHE_TAG_OFFS)
+#define CFCR_FTDLL_OVERWRITE_ENABLE		(1 << 15)
+/* For Orion 2 D2 only */
+#define CFCR_MRVL_CPU_ID_OFFS			16
+#define CFCR_MRVL_CPU_ID_MASK			(0x1 << CFCR_MRVL_CPU_ID_OFFS)
+#define CFCR_ARM_CPU_ID				(0x0 << CFCR_MRVL_CPU_ID_OFFS)
+#define CFCR_MRVL_CPU_ID			(0x1 << CFCR_MRVL_CPU_ID_OFFS)
+#define CFCR_VFP_SUB_ARC_NUM_OFFS		7
+#define CFCR_VFP_SUB_ARC_NUM_MASK		(0x1 << CFCR_VFP_SUB_ARC_NUM_OFFS)
+#define CFCR_VFP_SUB_ARC_NUM_1			(0x0 << CFCR_VFP_SUB_ARC_NUM_OFFS)
+#define CFCR_VFP_SUB_ARC_NUM_2			(0x1 << CFCR_VFP_SUB_ARC_NUM_OFFS)
+
+/* CPU_L2_CONFIG_REG fields */
+#ifdef MV_CPU_LE
+#define CL2CR_L2_ECC_EN_OFFS			2
+#define CL2CR_L2_WT_MODE_OFFS			4
+#else
+#define CL2CR_L2_ECC_EN_OFFS			26
+#define CL2CR_L2_WT_MODE_OFFS			28
+#endif
+
+#define CL2CR_L2_ECC_EN_MASK			(1 << CL2CR_L2_ECC_EN_OFFS)
+#define CL2CR_L2_WT_MODE_MASK			(1 << CL2CR_L2_WT_MODE_OFFS)
+
+/*******************************************/
+/* Main Interrupt Controller Registers Map */
+/*******************************************/
+
+#define CPU_MAIN_INT_CAUSE_REG			(MV_CPUIF_REGS_BASE + 0x200)
+#define CPU_MAIN_IRQ_MASK_REG			(MV_CPUIF_REGS_BASE + 0x204)
+#define CPU_MAIN_FIQ_MASK_REG			(MV_CPUIF_REGS_BASE + 0x208)
+#define CPU_ENPOINT_MASK_REG			(MV_CPUIF_REGS_BASE + 0x20C)
+#define CPU_MAIN_INT_CAUSE_HIGH_REG		(MV_CPUIF_REGS_BASE + 0x210)
+#define CPU_MAIN_IRQ_MASK_HIGH_REG		(MV_CPUIF_REGS_BASE + 0x214)
+#define CPU_MAIN_FIQ_MASK_HIGH_REG		(MV_CPUIF_REGS_BASE + 0x218)
+#define CPU_ENPOINT_MASK_HIGH_REG		(MV_CPUIF_REGS_BASE + 0x21C)
+
+/*******************************************/
+/* ARM Doorbell Registers Map		   */
+/*******************************************/
+
+#define CPU_HOST_TO_ARM_DRBL_REG		(MV_CPUIF_REGS_BASE + 0x400)
+#define CPU_HOST_TO_ARM_MASK_REG		(MV_CPUIF_REGS_BASE + 0x404)
+#define CPU_ARM_TO_HOST_DRBL_REG		(MV_CPUIF_REGS_BASE + 0x408)
+#define CPU_ARM_TO_HOST_MASK_REG		(MV_CPUIF_REGS_BASE + 0x40C)
+
+/* CPU control register map */
+/* Set bits means value is about to change according to new value */
+#define CPU_CONFIG_DEFAULT_MASK         	(CCR_VEC_INIT_LOC_MASK  | CCR_AHB_ERROR_PROP_MASK)
+
+#define CPU_CONFIG_DEFAULT                      (CCR_VEC_INIT_LOC_FF00)
+
+/* CPU Control and status defaults */
+#define CPU_CTRL_STAT_DEFAULT_MASK              (CCSR_PCI_ACCESS_MASK)
+
+#define CPU_CTRL_STAT_DEFAULT                   (CCSR_PCI_ACCESS_ENABLE)
+
+#endif /* __INCmvCpuIfRegsh */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDevice.c b/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDevice.c
new file mode 100755
index 0000000..6f5cc5e
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDevice.c
@@ -0,0 +1,398 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include "mvTypes.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "device/mvDevice.h"
+
+/* defines  */
+#ifdef DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/*******************************************************************************
+* mvDevPramSet - Set device interface bank parameters
+*
+* DESCRIPTION:
+*       This function sets a device bank parameters to a given device.
+*
+* INPUT:
+*       device      - Device number. See MV_DEVICE enumerator.
+*       *pDevParams - Device bank parameter struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvDevIfPramSet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams)
+{
+	MV_U32 devParam = 0;
+	/* check parameters */
+	if (device >= MV_DEV_MAX_CS) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device));
+		return MV_BAD_PARAM;
+
+	}
+	if (pDevParams->turnOff > MAX_DBP_TURNOFF) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->turnOff out of range\n"));
+		return MV_ERROR;
+	}
+	if (pDevParams->acc2First > MAX_DBP_ACC2FIRST) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->acc2First out of range\n"));
+		return MV_ERROR;
+	}
+	if (pDevParams->acc2Next > MAX_DBP_ACC2NEXT) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->acc2Next out of range\n"));
+		return MV_ERROR;
+	}
+	if (pDevParams->ale2Wr > MAX_DBP_ALE2WR) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->ale2Wr out of range\n"));
+		return MV_ERROR;
+	}
+	if (pDevParams->wrLow > MAX_DBP_WRLOW) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->ale2Wr out of range\n"));
+		return MV_ERROR;
+	}
+	if (pDevParams->wrHigh > MAX_DBP_WRHIGH) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->ale2Wr out of range\n"));
+		return MV_ERROR;
+	}
+	if ((pDevParams->badrSkew << DBP_BADRSKEW_OFFS) > DBP_BADRSKEW_2CYCLE) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->badrSkew out of range\n"));
+		return MV_ERROR;
+	}
+	if ((pDevParams->deviceWidth != 8) && (pDevParams->deviceWidth != 16)) {
+		if (pDevParams->deviceWidth != 32) {
+			DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->deviceWidth out of range\n"));
+			return MV_ERROR;
+		}
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->deviceWidth out of range\n"));
+		return MV_ERROR;
+	}
+
+	/* devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device)); */
+	/* Bit 31 must be 1 */
+#if !defined(MV78XX0)
+	devParam = DEV_BANK_PARAM_REG_DV;
+#endif
+	/* setting values */
+	devParam |= DBP_TURNOFF_SET(pDevParams->turnOff);
+	devParam |= DBP_ACC2FIRST_SET(pDevParams->acc2First);
+	devParam |= DBP_ACC2NEXT_SET(pDevParams->acc2Next);
+#if !defined(MV78XX0)
+	devParam |= DBP_ALE2WR_SET(pDevParams->ale2Wr);
+	devParam |= DBP_WRLOW_SET(pDevParams->wrLow);
+	devParam |= DBP_WRHIGH_SET(pDevParams->wrHigh);
+#endif
+	devParam |= ((pDevParams->badrSkew & DBP_BADRSKEW_MASK) << DBP_BADRSKEW_OFFS);
+
+	switch (pDevParams->deviceWidth) {
+	case 8:
+		devParam |= DBP_DEVWIDTH_8BIT;
+		break;
+	case 16:
+		devParam |= DBP_DEVWIDTH_16BIT;
+		break;
+	case 32:
+		devParam |= DBP_DEVWIDTH_32BIT;
+		break;
+	default:
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->deviceWidth non valid value\n"));
+		return MV_ERROR;
+		break;
+	}
+
+	MV_REG_WRITE(DEV_BANK_PARAM_REG(device), devParam);
+
+#if defined(MV78XX0)
+	devParam = 0;
+	devParam |= DBP_ALE2WR_SET(pDevParams->ale2Wr);
+	devParam |= DBP_WRLOW_SET(pDevParams->wrLow);
+	devParam |= DBP_WRHIGH_SET(pDevParams->wrHigh);
+	MV_REG_WRITE(DEV_BANK_PARAM_REG_WR(device), devParam);
+#endif
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDevPramget - Get device interface bank parameters
+*
+* DESCRIPTION:
+*       This function retrieves a device bank parameter settings.
+*
+* INPUT:
+*       device      - Device number. See MV_DEVICE enumerator.
+*
+* OUTPUT:
+*       *pDevParams - Device bank parameter struct.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvDevPramGet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams)
+{
+	MV_U32 devParam = 0;
+
+	/* check parameters */
+	if (device >= MV_DEV_MAX_CS) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device));
+		return MV_BAD_PARAM;
+
+	}
+
+	devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device));
+
+	pDevParams->turnOff = DBP_TURNOFF_GET(devParam);
+	pDevParams->acc2First = DBP_ACC2FIRST_GET(devParam);
+	pDevParams->acc2Next = DBP_ACC2NEXT_GET(devParam);
+#if !defined(MV78XX0)
+	pDevParams->ale2Wr = DBP_ALE2WR_GET(devParam);
+	pDevParams->wrLow = DBP_WRLOW_GET(devParam);
+	pDevParams->wrHigh = DBP_WRHIGH_GET(devParam);
+#endif
+	pDevParams->badrSkew = (devParam & DBP_BADRSKEW_MASK) >> DBP_BADRSKEW_OFFS;
+
+	switch (devParam & DBP_DEVWIDTH_MASK) {
+	case DBP_DEVWIDTH_8BIT:
+		pDevParams->deviceWidth = 8;
+		break;
+	case DBP_DEVWIDTH_16BIT:
+		pDevParams->deviceWidth = 16;
+		break;
+	case DBP_DEVWIDTH_32BIT:
+		pDevParams->deviceWidth = 32;
+		break;
+	default:
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->deviceWidth non valid value\n"));
+		return MV_ERROR;
+		break;
+	}
+
+#if defined(MV78XX0)
+	devParam = MV_REG_READ(DEV_BANK_PARAM_REG_WR(device));
+	pDevParams->ale2Wr = DBP_ALE2WR_GET(devParam);
+	pDevParams->wrLow = DBP_WRLOW_GET(devParam);
+	pDevParams->wrHigh = DBP_WRHIGH_GET(devParam);
+#endif
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDevWidthGet - Get device width parameter
+*
+* DESCRIPTION:
+*       This function gets width parameter of a given device.
+*
+* INPUT:
+*       device - Device number. See MV_DEVICE enumerator.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Device width in bytes.
+*
+*******************************************************************************/
+MV_U32 mvDevWidthGet(MV_DEVICE device)
+{
+	MV_U32 devParam;
+
+	/* check parameters */
+	if (device >= MV_DEV_MAX_CS) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device));
+		return MV_BAD_PARAM;
+	}
+
+	devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device));
+
+	devParam = (devParam & DBP_DEVWIDTH_MASK) >> DBP_DEVWIDTH_OFFS;
+
+	return (MV_U32) (0x8 << devParam);
+}
+
+/*******************************************************************************
+* mvDevWidthSet - Set device width parameter
+*
+* DESCRIPTION:
+*       This function sets width parameter of a given device.
+*
+* INPUT:
+*       device - Device number. See MV_DEVICE enumerator.
+*	width - Device bus width in bits.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Device width in bytes.
+*
+*******************************************************************************/
+MV_STATUS mvDevWidthSet(MV_DEVICE device, MV_U32 width)
+{
+	MV_U32 devParam;
+
+	/* check parameters */
+	if (device >= MV_DEV_MAX_CS) {
+		DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device));
+		return MV_BAD_PARAM;
+	}
+
+	devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device));
+	devParam &= ~DBP_DEVWIDTH_MASK;
+
+	switch (width) {
+	case 8:
+		devParam |= DBP_DEVWIDTH_8BIT;
+		break;
+	case 16:
+		devParam |= DBP_DEVWIDTH_16BIT;
+		break;
+	case 32:
+		devParam |= DBP_DEVWIDTH_32BIT;
+		break;
+	default:
+		DB(mvOsPrintf("mvDevWidthSet: ERR. pDevParams->deviceWidth non valid value\n"));
+		return MV_ERROR;
+	}
+
+	MV_REG_WRITE(DEV_BANK_PARAM_REG(device), devParam);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDevNandDevCsSet - Set NAND chip-select, care mode and init sequence
+*
+* DESCRIPTION:
+*	This function set the NAND flash controller registers with NAND
+*       device chip-select.
+*
+* INPUT:
+*       devNum   - Device number. See MV_DEVICE enumerator.
+*       careMode - NAND device care mode (0 = Don't care, '1' = care).
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvDevNandDevCsSet(MV_DEVICE device, MV_BOOL careMode)
+{
+	MV_U32 nfCtrlReg;	/* NAND Flash Control Register */
+
+	/* Set chip select */
+	nfCtrlReg = MV_REG_READ(DEV_NAND_CTRL_REG);
+
+	nfCtrlReg |= (DINFCR_NF_CS_MASK(device));
+
+	if (careMode)
+		nfCtrlReg |= (DINFCR_NF_ACT_CE_MASK(device));
+	else
+		nfCtrlReg &= ~(DINFCR_NF_ACT_CE_MASK(device));
+
+	MV_REG_WRITE(DEV_NAND_CTRL_REG, nfCtrlReg);
+}
+
+#if 0
+/* This function is not being used. */
+/*******************************************************************************
+* mvDevNandDevCsGet - Get NAND chip-select.
+*
+* DESCRIPTION:
+*	This function get the NAND flash chip-select.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*         Nand device chip-select.
+*
+*******************************************************************************/
+MV_32 mvDevNandDevCsGet(MV_VOID)
+{
+	MV_U32 nfCtrlReg;	/* NAND Flash Control Register */
+
+	nfCtrlReg = MV_REG_READ(DEV_NAND_CTRL_REG);
+
+	nfCtrlReg &= (DINFCR_NF_CS_MASK(MV_NAND_CS));
+
+	if (nfCtrlReg)
+		return MV_NAND_CS;
+	else
+		return 0xffffffff;
+}
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDevice.h b/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDevice.h
new file mode 100755
index 0000000..1625347
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDevice.h
@@ -0,0 +1,103 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCmvDeviceH
+#define __INCmvDeviceH
+
+#include "device/mvDeviceRegs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+
+/* This structure describes device interface parameters to be assigned to   */
+/* device bank parameter                                                    */
+typedef struct _mvDeviceParam {	/* boundary values */
+	MV_U32 turnOff;		/* 0x0 - 0xf       */
+	MV_U32 acc2First;	/* 0x0 - 0x1f      */
+	MV_U32 acc2Next;	/* 0x0 - 0x1f      */
+	MV_U32 ale2Wr;		/* 0x0 - 0xf       */
+	MV_U32 wrLow;		/* 0x0 - 0xf       */
+	MV_U32 wrHigh;		/* 0x0 - 0xf       */
+	MV_U32 badrSkew;	/* 0x0 - 0x2       */
+	MV_U32 deviceWidth;	/* in Bytes        */
+} MV_DEVICE_PARAM;
+
+/* mvDevPramSet - Set device interface bank parameters */
+MV_STATUS mvDevIfPramSet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams);
+
+/* mvDevPramget - Get device interface bank parameters */
+MV_STATUS mvDevPramGet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams);
+
+/* mvDevWidthGet - Get device width parameter*/
+MV_U32 mvDevWidthGet(MV_DEVICE device);
+
+/* mvDevWidthSet - Set device width parameter*/
+MV_STATUS mvDevWidthSet(MV_DEVICE device, MV_U32 width);
+
+/* mvDevNandDevCsSet - Set the NAND flash control registers with NAND device- */
+/* select and care mode */
+MV_VOID mvDevNandDevCsSet(MV_DEVICE device, MV_BOOL careMode);
+
+/* mvDevNandDevCsGet - Get the NAND flash chip-select */
+MV_32 mvDevNandDevCsGet(MV_VOID);
+
+#endif /* #ifndef __INCmvDeviceH */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDeviceRegs.h b/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDeviceRegs.h
new file mode 100755
index 0000000..3df65a2
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/device/mvDeviceRegs.h
@@ -0,0 +1,222 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * 	Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *	Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *	Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCmvDeviceRegsH
+#define __INCmvDeviceRegsH
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+#define MV_DEVICE_MAX_XBAR_TIMEOUT  0x0FFF
+#define DEV_BANK_PARAM_REG_DV	    0x80000000
+/* registers offsets */
+
+static INLINE MV_U32 DEV_BANK_PARAM_REG(int num)
+{
+	switch (num) {
+	case (BOOT_CS):
+		return MV_DEV_BUS_REGS_OFFSET + 0x400;
+	case (DEV_CS0):
+		return MV_DEV_BUS_REGS_OFFSET + 0x408;
+	case (DEV_CS1):
+		return MV_DEV_BUS_REGS_OFFSET + 0x410;
+#ifdef MV_INCLUDE_DEVICE_CS2
+	case (DEV_CS2):
+		return MV_DEV_BUS_REGS_OFFSET + 0x418;
+#endif
+#ifdef MV_INCLUDE_DEVICE_CS3
+	case (DEV_CS3):
+		return MV_DEV_BUS_REGS_OFFSET + 0x420;
+#endif
+	default:
+		return 0xFFFFFFFF;
+	}
+}
+
+#define DEV_BANK_PARAM_REG_WR(num)	(DEV_BANK_PARAM_REG(num)+0x4)
+#define DEV_NAND_CTRL_REG		(MV_DEV_BUS_REGS_OFFSET + 0x0470)
+/* Device Bank Parameters register fields (DBP_REG)*/
+/* Boot Device Bank Parameters (DBP) register fields (DEV_BOOT_BANK_PARAM_REG)*/
+/* DBP_XXX_MASK_HIGH is the offset of the extend bit from the msb of the input value */
+#define DBP_TURNOFF_OFFS_LOW		0
+#define DBP_TURNOFF_MASK_LOW		0x3F
+#define MAX_DBP_TURNOFF			0xf
+#define DBP_TURNOFF_SET(value)			\
+((value & DBP_TURNOFF_MASK_LOW) << DBP_TURNOFF_OFFS_LOW)
+#define DBP_TURNOFF_GET(value)			\
+((value >> DBP_TURNOFF_OFFS_LOW) & DBP_TURNOFF_MASK_LOW)
+#define DBP_ACC2FIRST_OFFS_LOW		6
+#define DBP_ACC2FIRST_MASK_LOW		0x3f
+#define MAX_DBP_ACC2FIRST		0x3f
+#define DBP_ACC2FIRST_SET(value)			\
+((value & DBP_ACC2FIRST_MASK_LOW) << DBP_ACC2FIRST_OFFS_LOW)
+#define DBP_ACC2FIRST_GET(value)			\
+((value >> DBP_ACC2FIRST_OFFS_LOW) & DBP_ACC2FIRST_MASK_LOW)
+#define DBP_ACC2NEXT_OFFS_LOW		17
+#define DBP_ACC2NEXT_MASK_LOW		0x3f
+#define MAX_DBP_ACC2NEXT		0x3f
+#define DBP_ACC2NEXT_SET(value)			\
+((value & DBP_ACC2FIRST_MASK_LOW) << DBP_ACC2FIRST_OFFS_LOW)
+#define DBP_ACC2NEXT_GET(value)			\
+((value >> DBP_ACC2NEXT_OFFS_LOW) & DBP_ACC2NEXT_MASK_LOW)
+#define DBP_DEVWIDTH_OFFS		30	/* Device Width */
+#define DBP_DEVWIDTH_MASK		(0x3 << DBP_DEVWIDTH_OFFS)
+#define DBP_DEVWIDTH_8BIT		(0x0 << DBP_DEVWIDTH_OFFS)
+#define DBP_DEVWIDTH_16BIT		(0x1 << DBP_DEVWIDTH_OFFS)
+#define DBP_DEVWIDTH_32BIT		(0x2 << DBP_DEVWIDTH_OFFS)
+#define DBP_BADRSKEW_OFFS		28
+#define DBP_BADRSKEW_MASK		(0x3 << DBP_BADRSKEW_OFFS)
+#define DBP_BADRSKEW_NOGAP		(0x0 << DBP_BADRSKEW_OFFS)
+#define DBP_BADRSKEW_1CYCLE		(0x1 << DBP_BADRSKEW_OFFS)
+#define DBP_BADRSKEW_2CYCLE		(0x2 << DBP_BADRSKEW_OFFS)
+#define DBP_ALE2WR_OFFS_LOW		0
+#define DBP_ALE2WR_MASK_LOW		0x3f
+#define MAX_DBP_ALE2WR			0x3F
+#define DBP_ALE2WR_SET(value)			\
+((value & DBP_ALE2WR_MASK_LOW) << DBP_ALE2WR_OFFS_LOW)
+#define DBP_ALE2WR_GET(value)			\
+((value >> DBP_ALE2WR_OFFS_LOW) & DBP_ALE2WR_MASK_LOW)
+#define DBP_WRLOW_OFFS_LOW		8
+#define DBP_WRLOW_MASK_LOW		0x3F
+#define MAX_DBP_WRLOW			0x3F
+#define DBP_WRLOW_SET(value)			\
+((value & DBP_WRLOW_MASK_LOW) << DBP_WRLOW_OFFS_LOW)
+#define DBP_WRLOW_GET(value)			\
+((value >> DBP_WRLOW_OFFS_LOW) & DBP_WRLOW_MASK_LOW)
+#define DBP_WRHIGH_OFFS_LOW		16
+#define DBP_WRHIGH_MASK_LOW		0x3F
+#define MAX_DBP_WRHIGH			0x3F
+#define DBP_WRHIGH_SET(value)			\
+((value & DBP_WRHIGH_MASK_LOW) << DBP_WRHIGH_OFFS_LOW)
+#define DBP_WRHIGH_GET(value)			\
+((value >> DBP_WRHIGH_OFFS_LOW) & DBP_WRHIGH_MASK_LOW)
+/* Device Interface Control register fields (DIC) (DIC_REG)*/
+#define DIC_TIMEOUT_OFFS 	0	/* Timeout Timer Preset Value. */
+#define DIC_TIMEOUT_MASK 	(0xffff << DIC_TIMEOUT_OFFS)
+#define MAX_DIC_TIMEOUT		0xffff
+/* NAND Flash Control register fields (NF) (NF_REG)*/
+#define NF_BOOTCS_OFFS			0	/* Define if BOOTCS is connected to NAND Flash */
+#define NF_BOOT_MASK			(1 << NF_BOOTCS_OFFS)
+#define NF_BOOT_NC			(0 << NF_BOOTCS_OFFS)
+#define NF_BOOT_C			(1 << NF_BOOTCS_OFFS)
+#define NF_BOOTCS_CE_ACT_OFFS		1	/* Define if NAND Flash on BOOTCS is CE care or CE don't care */
+#define NF_BOOTCS_CE_ACT_MASK 		(1 << NF_BOOTCS_CE_ACT_OFFS)
+#define NF_BOOTCS_CE_ACT_NCARE		(0 << NF_BOOTCS_CE_ACT_OFFS)
+#define NF_BOOTCS_CE_ACT_CARE		(1 << NF_BOOTCS_CE_ACT_OFFS)
+#define NF_CS0_OFFS			2	/* Define if CS0 is connected to NAND Flash */
+#define NF_CS0_MASK			(1 << NF_CS0_OFFS)
+#define NF_CS0_NC			(0 << NF_CS0_OFFS)
+#define NF_CS0_C			(1 << NF_CS0_OFFS)
+#define NF_CS0_CE_ACT_OFFS		3	/* Define if NAND Flash on CS0 is CE care or CE don't care */
+#define NF_CS0_CE_ACT_MASK 		(1 << NF_CS0_CE_ACT_OFFS)
+#define NF_CS0_CE_ACT_NCARE		(0 << NF_CS0_CE_ACT_OFFS)
+#define NF_CS0_CE_ACT_CARE		(1 << NF_CS0_CE_ACT_OFFS)
+#define NF_CS1_OFFS			4	/* Define if CS1 is connected to NAND Flash */
+#define NF_CS1_MASK			(1 << NF_CS1_OFFS)
+#define NF_CS1_NC			(0 << NF_CS1_OFFS)
+#define NF_CS1_C			(1 << NF_CS1_OFFS)
+#define NF_CS1_CE_ACT_OFFS		5	/* Define if NAND Flash on CS1 is CE care or CE don't care */
+#define NF_CS1_CE_ACT_MASK		(1 << NF_CS1_CE_ACT_OFFS)
+#define NF_CS1_CE_ACT_NCARE		(0 << NF_CS1_CE_ACT_OFFS)
+#define NF_CS1_CE_ACT_CARE		(1 << NF_CS1_CE_ACT_OFFS)
+#define NF_CS2_OFFS			6	/* Define if CS2 is connected to NAND Flash */
+#define NF_CS2_MASK			(1 << NF_CS2_OFFS)
+#define NF_CS2_NC			(0 << NF_CS2_OFFS)
+#define NF_CS2_C			(1 << NF_CS2_OFFS)
+#define NF_CS2_CE_ACT_OFFS		7	/* Define if NAND Flash on CS2 is CE care or CE don't care */
+#define NF_CS2_CE_ACT_MASK		(1 << NF_CS2_CE_ACT_OFFS)
+#define NF_CS2_CE_ACT_NCARE		(0 << NF_CS2_CE_ACT_OFFS)
+#define NF_CS2_CE_ACT_CARE		(1 << NF_CS2_CE_ACT_OFFS)
+#define NF_INIT_SEQ_OFFS		8	/* NAND Flash initialization sequence */
+#define NF_INIT_SEQ_MASK		(1 << NF_INIT_SEQ_OFFS)
+#define NF_INIT_SEQ_EN			(0 << NF_INIT_SEQ_OFFS)
+#define NF_INIT_SEQ_DIS			(1 << NF_INIT_SEQ_OFFS)
+#define NF_OE_HIGHW_OFFS		9	/* NAND Flash OE high width in core clocks units (value + 1) */
+#define NF_OE_HIGHW_MASK		(0x1f << NF_OE_HIGHW_OFFS)
+#define MAX_OE_HIGHW			(0x1f << NF_OE_HIGHW_OFFS)
+#define NF_TREADY_OFFS			14	/* NAND Flash time ready in core clocks units (value + 1) */
+#define NF_TREADY_MASK			(0x1f << NF_TREADY_OFFS)
+#define MAX_TREADY			(0x1f << NF_TREADY_OFFS)
+#define NF_OE_TCTRL_OFFS		19	/* NAND Flash OE toggle control */
+#define NF_OE_TCTRL_MASK		(1 << NF_OE_TCTRL_OFFS)
+#define NF_OE_TCTRL_1_CYC_AFT		(0 << NF_OE_TCTRL_OFFS)
+#define NF_OE_TCTRL_SAME_CYC		(1 << NF_OE_TCTRL_OFFS)
+#define NF_CS3_OFFS			20	/* Define if CS3 is connected to NAND Flash */
+#define NF_CS3_MASK			(1 << NF_CS3_OFFS)
+#define NF_CS3_NC			(0 << NF_CS3_OFFS)
+#define NF_CS3_C			(1 << NF_CS3_OFFS)
+#define NF_CS3_CE_ACT_OFFS		21	/* Define if NAND Flash on CS3 is CE care or CE don't care */
+#define NF_CS3_CE_ACT_MASK		(1 << NF_CS3_CE_ACT_OFFS)
+#define NF_CS3_CE_ACT_NCARE		(0 << NF_CS3_CE_ACT_OFFS)
+#define NF_CS3_CE_ACT_CARE		(1 << NF_CS3_CE_ACT_OFFS)
+/* Device Interface NAND Flash Control Register (DINFCR) */
+#define DINFCR_NF_CS_MASK(csNum)         \
+(csNum == BOOT_CS) ?  0x1 : ((csNum == DEV_CS3) ? (0x1 << 20) : (0x1 << (((csNum+1) % MV_DEV_MAX_CS) * 2)))
+#define DINFCR_NF_ACT_CE_MASK(csNum)     \
+(csNum == DEV_CS3) ? (0x2 << 20) : (0x2 << (((csNum+1) % MV_DEV_MAX_CS) * 2))
+#define NAND_ACTCEBOOT_BIT	BIT1
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+#endif				/* #ifndef __INCmvDeviceRegsH */
diff --git a/arch/arm/mach-feroceon-kw2/kw2_family/mvCompVer.txt b/arch/arm/mach-feroceon-kw2/kw2_family/mvCompVer.txt
new file mode 100755
index 0000000..4053116
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/kw2_family/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.5

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/mach-feroceon-kw2/leds.c b/arch/arm/mach-feroceon-kw2/leds.c
new file mode 100755
index 0000000..66639b2
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/leds.c
@@ -0,0 +1,49 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include "boardEnv/mvBoardEnvLib.h"
+
+static	u32		last_jiffies = 0;
+static	u32		led_val = 0;
+
+
+void mv_leds_hearbeat(void)
+{
+	u32 sec = jiffies_to_msecs(jiffies - last_jiffies) / 1000;
+	
+	if (!sec)
+		return;
+
+	led_val = (led_val % (1 << mvBoardDebugLedNumGet(mvBoardIdGet())));
+	mvBoardDebugLed(led_val);
+	led_val++;
+	last_jiffies = jiffies;
+}
+
+static int __init leds_init(void)
+{
+	return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysCesa.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysCesa.c
new file mode 100755
index 0000000..a04b701
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysCesa.c
@@ -0,0 +1,118 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "cesa/mvCesaIf.h"
+
+extern u32 mv_crypto_base_get(u8 chan);
+
+/*******************************************************************************
+* mvSysCesaInit - Initialize the Cesa subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_STATUS mvSysCesaInit(int numOfSession, int queueDepth, void *osHandle)
+{
+	MV_CESA_HAL_DATA halData;
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+	MV_U8 chan;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+
+	if(status == MV_OK) {
+		for(chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+			status = mvCesaIfTdmaWinInit(chan, addrWinMap);
+			
+			if(status != MV_OK) {
+				mvOsPrintf("Error, unable to initialize CESA windows for channel(%d)\n", chan);
+				break;
+			}
+			halData.sramPhysBase[chan] = (MV_ULONG)mv_crypto_base_get(chan);
+			halData.sramVirtBase[chan] = (MV_U8*)mv_crypto_base_get(chan);
+			halData.sramOffset[chan] = 0;
+		}
+
+		if(status == MV_OK) {
+		halData.ctrlModel = mvCtrlModelGet();
+		halData.ctrlRev = mvCtrlRevGet();
+			status = mvCesaIfHalInit (numOfSession, queueDepth, 
+					osHandle, &halData);
+	}
+	}
+
+	return status;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysCesaApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysCesaApi.h
new file mode 100755
index 0000000..ce8aa9b
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysCesaApi.h
@@ -0,0 +1,71 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_CESA_API_H__
+#define __MV_SYS_CESA_API_H__
+
+
+MV_STATUS mvSysCesaInit (int numOfSession, int queueDepth, void *osHandle);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysDdr.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysDdr.c
new file mode 100755
index 0000000..38dc444
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysDdr.c
@@ -0,0 +1,134 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "boardEnv/mvBoardEnvSpec.h"
+#include "twsi/mvTwsi.h"
+
+
+/*******************************************************************************
+* mvSysDdrSpdRead
+*
+* DESCRIPTION:
+*	System interface for reading DDR SPD contents.
+*
+* INPUT:
+*       data:	Buffer to read data into.
+*       size:	Number of bytes to read.
+*
+* OUTPUT:
+*       data:	SPD data.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysDdrSpdRead(MV_U8 *data, MV_U32 size)
+{
+	MV_TWSI_SLAVE slave;
+
+	slave.slaveAddr.address = MV_BOARD_DIMM0_I2C_ADDR;
+	slave.slaveAddr.type = ADDR7_BIT;
+	slave.validOffset = MV_TRUE;
+	slave.offset = 0;
+	slave.moreThen256 = MV_FALSE;
+
+	return mvTwsiRead(MV_BOARD_DIMM_I2C_CHANNEL, &slave, data, size);
+}
+
+
+/*******************************************************************************
+* mvSysDdrSpdWrite
+*
+* DESCRIPTION:
+*	System interface for writing DDR SPD contents.
+*
+* INPUT:
+*       data:	Buffer holding the data to be written.
+*       size:	Number of bytes to write.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysDdrSpdWrite(MV_U8 *data, MV_U32 size)
+{
+	MV_TWSI_SLAVE slave;
+
+	slave.slaveAddr.address = MV_BOARD_DIMM0_I2C_ADDR;
+	slave.slaveAddr.type = ADDR7_BIT;
+	slave.validOffset = MV_TRUE;
+	slave.offset = 0;
+	slave.moreThen256 = MV_FALSE;
+
+	return	mvTwsiWrite(MV_BOARD_DIMM_I2C_CHANNEL, &slave, data, size);
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEth.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEth.c
new file mode 100755
index 0000000..f8b64b6
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEth.c
@@ -0,0 +1,132 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "cpu/mvCpu.h"
+#include "eth/mvEth.h"
+
+
+/*******************************************************************************
+* mvSysEthInit - Initialize the Eth subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvSysEthInit(MV_VOID)
+{
+	MV_ETH_HAL_DATA halData;
+	MV_U32 port;
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+	if(status != MV_OK)
+		return;
+
+	{
+		int i;
+		for(i = 0; i < MAX_TARGETS; i++) {
+			if(addrWinMap[i].enable == MV_FALSE)
+				continue;
+			printk("%d - Base 0x%08x , Size = 0x%08x.\n", i,
+					addrWinMap[i].addrWin.baseLow,
+					addrWinMap[i].addrWin.size);
+		}
+	}
+	halData.maxPortNum = mvCtrlEthMaxPortGet();
+	halData.cpuPclk = mvCpuPclkGet();
+	halData.tclk = mvBoardTclkGet();
+#ifdef ETH_DESCR_IN_SRAM
+	halData.sramSize = mvCtrlSramSizeGet();
+#endif
+
+	for (port=0;port < halData.maxPortNum;port++) {
+		if(mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port) == MV_FALSE) {
+			halData.portData[port].powerOn = MV_FALSE;
+			continue;
+		}
+		status = mvEthWinInit(port, addrWinMap);
+		if(status == MV_OK) {
+			halData.portData[port].powerOn = MV_TRUE;
+			halData.portData[port].phyAddr = mvBoardPhyAddrGet(port);
+			halData.portData[port].isSgmii = mvBoardIsPortInSgmii(port);
+			halData.portData[port].macSpeed = mvBoardMacSpeedGet(port);
+		}
+	}
+
+	mvEthHalInit(&halData);
+
+	return;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthApi.h
new file mode 100755
index 0000000..e1016e4
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthApi.h
@@ -0,0 +1,71 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_ETH_API_H__
+#define __MV_SYS_ETH_API_H__
+
+
+MV_VOID mvSysEthInit(void);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthPhy.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthPhy.c
new file mode 100755
index 0000000..cefe4a1
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthPhy.c
@@ -0,0 +1,107 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "eth-phy/mvEthPhy.h"
+#if defined(MV_ETH_LEGACY)
+#include "eth/gbe/mvEthRegs.h"
+#else
+#include "neta/gbe/mvEthRegs.h"
+#endif
+
+
+/*******************************************************************************
+* mvSysEthPhyInit - Initialize the EthPhy subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_STATUS mvSysEthPhyInit(void)
+{
+	MV_ETHPHY_HAL_DATA halData;
+	MV_U32 port;
+
+	for (port=0; port < mvCtrlEthMaxPortGet(); port++) {
+		halData.phyAddr[port] = mvBoardPhyAddrGet(port);
+		halData.boardSpecInit = MV_FALSE;
+	}
+
+	halData.ethPhySmiReg = ETH_SMI_REG(MV_ETH_SMI_PORT); 
+	halData.mvExtPhyWriteFunc = NULL; 
+	halData.mvExtPhyReadFunc = NULL; 
+
+	halData.ctrlRevId = mvCtrlRevGet();
+	return mvEthPhyHalInit(&halData);
+}
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthPhyApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthPhyApi.h
new file mode 100755
index 0000000..eab268a
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysEthPhyApi.h
@@ -0,0 +1,71 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_ETHPHY_API_H__
+#define __MV_SYS_ETHPHY_API_H__
+
+
+MV_STATUS mvSysEthPhyInit(void);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysNeta.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysNeta.c
new file mode 100755
index 0000000..f31901b
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysNeta.c
@@ -0,0 +1,150 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "cpu/mvCpu.h"
+#include "neta/gbe/mvNeta.h"
+
+
+/*******************************************************************************
+* mvSysNetaInit - Initialize the Eth subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+void 	mvSysNetaInit(MV_U32 portMask, MV_U32 cpuMask)
+{
+	MV_NETA_HAL_DATA halData;
+	MV_U32 port;
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+	int i;
+
+	memset(&halData, 0, sizeof(halData));
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+	if (status != MV_OK)
+		return;
+
+	for (i = 0; i < MAX_TARGETS; i++) {
+		if (addrWinMap[i].enable == MV_FALSE)
+			continue;
+
+#ifdef CONFIG_MV_SUPPORT_L2_DEPOSIT
+		/* Setting DRAM windows attribute to :
+		   0x3 - Shared transaction + L2 write allocate (L2 Deposit) */
+		if (MV_TARGET_IS_DRAM(i)) {
+			addrWinMap[i].attrib &= ~(0x30);
+			addrWinMap[i].attrib |= 0x30;
+		}
+#endif
+		mvOsPrintf("%d - Base 0x%08x , Size = 0x%08x.\n", i,
+                                addrWinMap[i].addrWin.baseLow,
+                                addrWinMap[i].addrWin.size);
+	}
+	halData.portMask = portMask;
+	halData.cpuMask  = cpuMask;
+
+	halData.maxPort = mvCtrlEthMaxPortGet();
+	halData.pClk = mvCpuPclkGet();
+	halData.tClk = mvBoardTclkGet();
+	halData.maxCPUs = mvCtrlEthMaxCPUsGet();
+	halData.iocc = arch_is_coherent();
+	halData.ctrlModel = mvCtrlModelGet();
+	halData.ctrlRev = mvCtrlRevGet();
+#ifdef CONFIG_MV_ETH_BM
+	halData.bmPhysBase = PNC_BM_PHYS_BASE;
+	halData.bmVirtBase = (MV_U8 *)ioremap(PNC_BM_PHYS_BASE, PNC_BM_SIZE);
+#endif /* CONFIG_MV_ETH_BM */
+
+#ifdef CONFIG_MV_ETH_PNC
+	halData.pncPhysBase = PNC_BM_PHYS_BASE;
+	halData.pncVirtBase = (MV_U8 *)ioremap(PNC_BM_PHYS_BASE, PNC_BM_SIZE);
+#endif /* CONFIG_MV_ETH_PNC */
+
+	for (port = 0; port < halData.maxPort; port++) {
+		if (!(MV_BIT_CHECK(portMask, port)))
+			continue;
+		if (mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port) == MV_FALSE)
+			continue;
+
+		mvNetaPortPowerUp(port, mvBoardIsPortInSgmii(port), mvBoardIsPortInRgmii(port));
+		status = mvNetaWinInit(port, addrWinMap);
+		if (status != MV_OK)
+			continue;
+	}
+	mvNetaHalInit(&halData);
+
+	return;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysNetaApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysNetaApi.h
new file mode 100755
index 0000000..2c4a08d
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysNetaApi.h
@@ -0,0 +1,71 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_NETA_API_H__
+#define __MV_SYS_NETA_API_H__
+
+
+void mvSysNetaInit(MV_U32 portMask, MV_U32 cpuMask);
+
+#endif /* __MV_SYS_NETA_API_H__ */
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysPex.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysPex.c
new file mode 100755
index 0000000..9f62414
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysPex.c
@@ -0,0 +1,129 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "pex/mvPex.h"
+#include "pex/mvPexRegs.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+
+MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pAddrDecWin);
+
+
+/*******************************************************************************
+* mvSysPexInit - Initialize the Pex subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_STATUS mvSysPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType)
+{
+	MV_PEX_HAL_DATA halData;
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+	if(status == MV_OK)
+		status = mvPexWinInit(pexIf, pexType, addrWinMap);
+
+	if(status == MV_OK) {
+		halData.ctrlModel = mvCtrlModelGet();
+		halData.maxPexIf = mvCtrlPexMaxIfGet();
+		status = mvPexInit(pexIf, pexType, &halData);
+	}
+
+	return status;
+}
+
+/*******************************************************************************
+* mvSysPexCpuIfEnable -
+*
+* DESCRIPTION:
+*       Enable PCI-E in CPU subsystem.
+*
+* INPUT:
+*       pexIf - The PCI-E Interface number to enable.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvSysPexCpuIfEnable(MV_U32 pexIf)
+{
+        mvCpuIfEnablePex(pexIf);
+        return;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysPexApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysPexApi.h
new file mode 100755
index 0000000..1b6a6bf
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysPexApi.h
@@ -0,0 +1,71 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_PEX_API_H__
+#define __MV_SYS_PEX_API_H__
+
+
+MV_STATUS mvSysPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSFlash.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSFlash.c
new file mode 100755
index 0000000..724ba4e
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSFlash.c
@@ -0,0 +1,225 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "spi/mvSpi.h"
+#include "spi/mvSpiCmnd.h"
+#include "sflash/mvSysSFlash.h"
+#include "sflash/mvSFlashSpec.h"
+
+static struct {
+	MV_U8 buf[MV_SFLASH_MAX_CMND_LENGTH];
+	MV_U32 bufLen;
+	MV_U8  transType;
+} mvSysSflashCmd;
+
+/*******************************************************************************
+* mvSysSflashCommandSet
+*
+* DESCRIPTION:
+*	System interface for sending a command to the SPI flash.
+*
+* INPUT:
+*       flashHandle: Handle passed by OS glue by which an SPI flash is
+*		     identified.
+*      	cmdBuff:     Command data to be written.
+*	cmdLen:	     Command length in bytes.
+*	transType:   Bitmask describing the transaction type, see 
+*		     SYS_SFLASH_TRANS_XX for details.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSflashCommandSet(MV_VOID *flashHandle, MV_U8* cmdBuff, MV_U32 cmdLen,
+		MV_U8 transType)
+{
+	if (cmdLen > MV_SFLASH_MAX_CMND_LENGTH)
+		return MV_ERROR;
+
+	if (!(transType & SYS_SFLASH_TRANS_START) || (mvSysSflashCmd.transType != 0))
+		return MV_ERROR;	
+
+	mvSpiParamsSet(0, 0, SPI_TYPE_FLASH);
+
+	memcpy(mvSysSflashCmd.buf,cmdBuff,cmdLen);	
+	mvSysSflashCmd.bufLen = cmdLen;
+	mvSysSflashCmd.transType = transType;
+
+	if (transType & SYS_SFLASH_TRANS_END)
+		return mvSysSflashDataWrite(flashHandle, NULL, 0, transType);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvSysSflashDataRead
+*
+* DESCRIPTION:
+*	System interface for reading SPI flash data.
+*
+* INPUT:
+*       flashHandle: Handle passed by OS glue by which an SPI flash is
+*		     identified.
+*	dataBuff:    Buffer to read the data into.
+*	dataLen:     Number of bytes to read.
+*	dummyBytes:  Number of dummy bytes to read before reading the real
+*		     data.
+*	transType:   Bitmask describing the transaction type, see 
+*		     SYS_SFLASH_TRANS_XX for details.
+*
+* OUTPUT:
+*	dataBuff: The data as read from flash.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSflashDataRead(MV_VOID *flashHandle, MV_U8* dataBuff, MV_U32 dataLen,
+		MV_U32 dummyBytes, MV_U8 transType)
+{
+	MV_STATUS  ret;	
+
+	if (!(mvSysSflashCmd.transType & SYS_SFLASH_TRANS_START))
+		return MV_ERROR;
+
+
+	ret = mvSpiWriteThenRead (0, mvSysSflashCmd.buf, mvSysSflashCmd.bufLen,
+			dataBuff, dataLen, dummyBytes);
+	if (transType & SYS_SFLASH_TRANS_END)
+		memset(&mvSysSflashCmd,0,sizeof(mvSysSflashCmd));
+	return ret;
+}
+
+
+/*******************************************************************************
+* mvSysSflashDataWrite
+*
+* DESCRIPTION:
+*	System interface for writing SPI flash data.
+*
+* INPUT:
+*       flashHandle: Handle passed by OS glue by which an SPI flash is
+*		     identified.
+*	dataBuff:    Buffer holding the data to be written.
+*	dataLen:     Number of bytes to write.
+*	transType:   Bitmask describing the transaction type, see 
+*		     SYS_SFLASH_TRANS_XX for details.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSflashDataWrite(MV_VOID *flashHandle, MV_U8* dataBuff, MV_U32 dataLen,
+		MV_U8 transType)
+{
+	MV_STATUS ret;
+
+	if (!(mvSysSflashCmd.transType & SYS_SFLASH_TRANS_START))
+		return MV_ERROR;
+
+	ret = mvSpiWriteThenWrite (0, mvSysSflashCmd.buf, mvSysSflashCmd.bufLen, dataBuff, dataLen);
+	if (transType & SYS_SFLASH_TRANS_END)
+		memset(&mvSysSflashCmd,0,sizeof(mvSysSflashCmd));
+	return ret;
+}
+
+
+/*******************************************************************************
+* mvSysSflashFreqSet
+*
+* DESCRIPTION:
+*	System interface for controlling the SPI interface frequency.
+*
+* INPUT:
+*       flashHandle: Handle passed by OS glue by which an SPI flash is
+*		     identified.
+*	freq:	     The new frequency to be configured for the SPI IF.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSflashFreqSet(MV_VOID *flashHandle, MV_U32 freq)
+{
+
+	return mvSpiBaudRateSet(0, freq);
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSata.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSata.c
new file mode 100755
index 0000000..a0317c9
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSata.c
@@ -0,0 +1,82 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "sata/CoreDriver/mvSata.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+
+MV_STATUS mvSysSataWinInit(MV_VOID)
+{
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+	if(status == MV_OK)
+		status = mvSataWinInit(addrWinMap);
+
+	return status;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSataApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSataApi.h
new file mode 100755
index 0000000..575a8d6
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSataApi.h
@@ -0,0 +1,71 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_SATA_API_H__
+#define __MV_SYS_SATA_API_H__
+
+MV_STATUS mvSysSataWinInit(MV_VOID);
+
+#endif 
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSpi.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSpi.c
new file mode 100755
index 0000000..b407634
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSpi.c
@@ -0,0 +1,126 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "spi/mvSpi.h"
+#include "spi/mvSysSpi.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+
+/*******************************************************************************
+* mvSysSpiInit - Initialize the SPI subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_STATUS   mvSysSpiInit(MV_U8 spiId, MV_U32 serialBaudRate)
+{
+	MV_SPI_HAL_DATA halData;
+
+	halData.ctrlModel = mvCtrlModelGet();
+	halData.tclk = mvBoardTclkGet();
+
+	return mvSpiInit(spiId, serialBaudRate, &halData);
+}
+
+
+/*******************************************************************************
+* mvSysSpiMppConfig
+*
+* DESCRIPTION:
+*	System interface for configuring the MPP's configuration to enable /
+*	disable SPI mode.
+*
+* INPUT:
+*      	mode:	The mode to be set into MPP unit.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSpiMppConfig(MV_U8 mode)
+{
+#if 0
+	if(mode == SYS_SPI_MPP_ENABLE)
+		mvMPPConfigToSPI();
+	else
+		mvMPPConfigToDefault();
+#endif
+	return MV_OK;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSpiApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSpiApi.h
new file mode 100755
index 0000000..80888c0
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysSpiApi.h
@@ -0,0 +1,70 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_SPI_API_H__
+#define __MV_SYS_SPI_API_H__
+
+MV_STATUS   mvSysSpiInit(MV_U8 spi_id, MV_U32 serialBaudRate);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTdm.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTdm.c
new file mode 100755
index 0000000..911c476
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTdm.c
@@ -0,0 +1,245 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#ifdef CONFIG_MV_TDM_SUPPORT
+#include "voiceband/tdm/mvTdm.h"
+#else
+ #include "voiceband/commUnit/mvCommUnit.h"
+ #include "gpp/mvGpp.h"
+#endif
+#include "voiceband/mvSysTdmSpi.h"
+#include "spi/mvSpiCmnd.h"
+#include "spi/mvSpi.h"
+
+#define MAX_DATA_LENGTH		255
+
+/*******************************************************************************
+* mvSysTdmInit - Initialize the TDM subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_STATUS mvSysTdmInit(MV_TDM_PARAMS* tdmParams)
+{
+	MV_TDM_HAL_DATA halData;
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+	if(status == MV_OK)
+#ifdef MV_TDM_SUPPORT
+		status = mvTdmWinInit(addrWinMap);
+#else
+		status = mvCommUnitWinInit(addrWinMap);
+#endif
+
+	if(status == MV_OK) {
+		halData.spiMode = mvBoardTdmSpiModeGet();
+		halData.model = mvCtrlModelGet();
+		halData.ctrlRev = mvCtrlRevGet();
+#if defined(MV_TDM_PCM_CLK_8MHZ)
+		halData.frameTs = MV_FRAME_128TS;
+#elif defined(MV_TDM_PCM_CLK_4MHZ)
+		halData.frameTs = MV_FRAME_64TS;
+#else /* MV_TDM_PCM_CLK_2MHZ */
+		halData.frameTs = MV_FRAME_32TS;
+#endif
+
+#ifdef MV_TDM_SUPPORT
+		status = mvTdmHalInit (tdmParams, &halData);
+#else
+		halData.maxCs = mvBoardTdmDevicesCountGet();
+		status = mvCommUnitHalInit (tdmParams, &halData);
+		
+		/* Issue SLIC reset */
+		mvGppValueSet(0, BIT25, 0);
+		mvOsUDelay(60);
+		mvGppValueSet(0, BIT25, BIT25);
+#endif
+	}
+
+	return status;
+}
+
+MV_VOID mvSysTdmSpiRead(MV_U16 lineId, MV_U8* cmdBuff, MV_U8 cmdSize, MV_U8* dataBuff, MV_U8 dataSize)
+{
+#if defined(MV_TDM_SUPPORT) && !defined(ZARLINK_SLIC_SUPPORT) && !defined(SILABS_SLIC_SUPPORT)
+
+	if((cmdSize > 4) || (dataSize > MAX_DATA_LENGTH))
+	{
+		mvOsPrintf("Error, exceeded max size of command(%d) or data(%d)\n", cmdSize, dataSize);
+		return;
+	}
+
+	mvTdmSpiRead(cmdBuff, cmdSize, dataBuff, dataSize, lineId);
+
+#else /* MV_COMM_UNIT_SUPPORT || ZARLINK_SLIC_SUPPORT || SILABS_SLIC_SUPPORT */
+
+	/* Set SPI parameters(lineId = devId) */
+	mvSpiParamsSet(mvBoardTdmSpiIdGet(), mvBoardTdmSpiCsGet(lineId), SPI_TYPE_SLIC);
+	
+	if(MV_OK != mvSpiWriteThenRead (mvBoardTdmSpiIdGet(), cmdBuff, cmdSize, dataBuff, dataSize, 0))
+		printk("SPI read failed !!!\n");
+
+#endif /* MV_TDM_SUPPORT */
+}
+
+/*******************************************************************************
+* mvSysTdmSpiWrite - telephony register write via SPI interface
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvSysTdmSpiWrite(MV_U16 lineId, MV_U8* cmdBuff, MV_U8 cmdSize, MV_U8* dataBuff, MV_U8 dataSize)
+{
+#if defined(MV_TDM_SUPPORT) && !defined(ZARLINK_SLIC_SUPPORT) && !defined(SILABS_SLIC_SUPPORT)
+
+	if((cmdSize > 3) || (dataSize > MAX_DATA_LENGTH))
+	{
+		mvOsPrintf("Error, exceeded max size of command(%d) or data(%d)\n", cmdSize, dataSize);
+		return;
+	}
+
+	mvTdmSpiWrite(cmdBuff, cmdSize, dataBuff, dataSize, lineId);
+
+#else /* MV_COMM_UNIT_SUPPORT || ZARLINK_SLIC_SUPPORT || SILABS_SLIC_SUPPORT*/
+	
+	/* Set SPI parameters(lineId = devId) */
+	mvSpiParamsSet(mvBoardTdmSpiIdGet(), mvBoardTdmSpiCsGet(lineId), SPI_TYPE_SLIC);
+
+	if(MV_OK != mvSpiWriteThenWrite (mvBoardTdmSpiIdGet(), cmdBuff, cmdSize, dataBuff, dataSize))
+		printk("SPI write failed !!!\n");
+
+#endif /* MV_TDM_SUPPORT */
+}
+
+/*******************************************************************************
+* mvSysTdmIntEnable - Enable CSLAC device interrupts. 
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       Device ID
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvSysTdmIntEnable(MV_U8 deviceId)
+{
+#if defined(MV_TDM_SUPPORT)
+
+	mvTdmIntEnable();
+
+#else /* MV_COMM_UNIT_SUPPORT */
+
+	mvCommUnitIntEnable(deviceId);
+
+#endif
+}
+
+/*******************************************************************************
+* mvSysTdmIntDisable - Disable CSLAC device interrupts. 
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       Device ID
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvSysTdmIntDisable(MV_U8 deviceId)
+{
+#if defined(MV_TDM_SUPPORT)
+
+	mvTdmIntDisable();
+
+#else /* MV_COMM_UNIT_SUPPORT */
+
+	mvCommUnitIntDisable(deviceId);
+
+#endif
+}
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTdmApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTdmApi.h
new file mode 100755
index 0000000..74ca023
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTdmApi.h
@@ -0,0 +1,78 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_TDM_API_H__
+#define __MV_SYS_TDM_API_H__
+
+#include "mvSysTdmConfig.h"
+
+#ifdef MV_TDM_SUPPORT
+#include "voiceband/tdm/mvTdm.h"
+#else
+  #include "voiceband/commUnit/mvCommUnit.h"
+#endif
+
+MV_STATUS mvSysTdmInit (MV_TDM_PARAMS* tdmParams);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTs.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTs.c
new file mode 100755
index 0000000..79ea4e8
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTs.c
@@ -0,0 +1,87 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ts/mvTsu.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ts/mvTsuRegs.h"
+
+MV_STATUS mvSysTsuInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode,
+		void *osHandle)
+{
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+	if(status == MV_OK)
+		status = mvTsuWinInit(addrWinMap);
+
+	if(status == MV_OK)
+		status = mvTsuHalInit(coreClock, mode, osHandle);
+	return status;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTsApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTsApi.h
new file mode 100755
index 0000000..837782d
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysTsApi.h
@@ -0,0 +1,73 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_TS_API_H__
+#define __MV_SYS_TS_API_H__
+
+#include "ts/mvTsu.h"
+
+MV_STATUS mvSysTsuInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode,
+		void *osHandle);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysUsb.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysUsb.c
new file mode 100755
index 0000000..f84e065
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysUsb.c
@@ -0,0 +1,103 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "usb/mvUsb.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+#include "usb/mvUsbRegs.h"
+
+/*******************************************************************************
+* mvSysUsbHalInit - Initialize the USB subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_STATUS   mvSysUsbInit(MV_U32 dev, MV_BOOL isHost)
+{
+	MV_USB_HAL_DATA halData;
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+	if(status == MV_OK)
+		status = mvUsbWinInit(dev, addrWinMap);
+
+	if(status == MV_OK) {
+		halData.ctrlModel = mvCtrlModelGet();
+		halData.ctrlRev = mvCtrlRevGet();
+		status = mvUsbHalInit(dev, isHost, &halData);
+	}
+
+	return status;
+}
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysUsbApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysUsbApi.h
new file mode 100755
index 0000000..675b608
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysUsbApi.h
@@ -0,0 +1,70 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_USB_API_H__
+#define __MV_SYS_USB_API_H__
+
+MV_STATUS   mvSysUsbInit(MV_U32 dev, MV_BOOL isHost);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysXor.c b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysXor.c
new file mode 100755
index 0000000..20acd3e
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysXor.c
@@ -0,0 +1,87 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "xor/mvXor.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "xor/mvXorRegs.h"
+
+MV_VOID mvSysXorInit (void)
+{
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+	if(status == MV_OK)
+		status = mvXorWinInit(addrWinMap);
+
+	if(status == MV_OK)
+		mvXorHalInit(MV_XOR_MAX_CHAN);
+	return;
+}
+
+
diff --git a/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysXorApi.h b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysXorApi.h
new file mode 100755
index 0000000..fb2b06d
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/mv_hal_if/mvSysXorApi.h
@@ -0,0 +1,70 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_XOR_API_H__
+#define __MV_SYS_XOR_API_H__
+
+MV_VOID mvSysXorInit (void);
+
+#endif
diff --git a/arch/arm/mach-feroceon-kw2/pci.c b/arch/arm/mach-feroceon-kw2/pci.c
new file mode 100755
index 0000000..d63a3d2
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/pci.c
@@ -0,0 +1,406 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+                                                                                                                             
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <mach/irqs.h>
+
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "pex/mvPex.h"
+#include "pex/mvPexRegs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mvSysPexApi.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#	define DB(x) x
+#else
+#	define DB(x) 
+#endif
+
+#define PCI_ERR_NAME_LEN 12
+#define MV_MAX_PEX_IF_NUMBER 2
+
+static int __init mv_map_irq_0(struct pci_dev *dev, u8 slot, u8 pin);
+static int __init mv_map_irq_1(struct pci_dev *dev, u8 slot, u8 pin);
+
+void mv_pci_error_init(u32 pciIf);
+static irqreturn_t pex_error_interrupt(int irq, void *dev_id);
+
+static struct pex_if_error {
+	MV_8 irq_name[PCI_ERR_NAME_LEN];
+	MV_U32 ifNumber;
+} pex_err[MV_MAX_PEX_IF_NUMBER];
+
+
+void __init mv_pci_preinit(void)
+{
+	MV_ADDR_WIN win;
+	MV_STATUS retval;
+	u32 pciIf;
+	u32 maxif = mvCtrlPexMaxIfGet();
+
+	/* Check Power State */
+	if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, 0))	
+		return;
+
+	for (pciIf = 0; pciIf < maxif; pciIf++) 
+        {
+
+		retval = mvSysPexInit(pciIf, MV_PEX_ROOT_COMPLEX);
+
+		if(retval == MV_NO_SUCH){
+			//printk("pci_init:no such calling mvPexInit for PEX-%x\n",pciIf);
+			continue;
+		}
+
+        	if (retval != MV_OK)
+        	{
+               		printk("pci_init:Error calling mvPexInit for PEX-%x\n",pciIf);
+			continue;
+        	}
+
+		/* unmask inter A/B/C/D */
+		//printk("writing %x tp %x \n",MV_PCI_MASK_ABCD, MV_PCI_MASK_REG(pciIf) );
+		MV_REG_WRITE(MV_PCI_MASK_REG(pciIf), MV_PCI_MASK_ABCD );
+
+		/* init PCI express error handling */
+		mv_pci_error_init(pciIf);
+
+		/* remmap IO !! */
+		win.baseLow = (pciIf? PEX1_IO_BASE : PEX0_IO_BASE) - IO_SPACE_REMAP;
+		win.baseHigh = 0x0;
+		win.size = pciIf? PEX1_IO_SIZE : PEX0_IO_SIZE;
+		mvCpuIfPciIfRemap((pciIf? PCI_IF1_IO : PCI_IF0_IO), &win);
+	}
+}
+
+/**
+* mv_pci_error_init
+* DESCRIPTION: init PCI express error handling
+* INPUTS:      pciIf - number of pex device
+* OUTPUTS:     N/A
+* RETURNS:     N/A
+**/
+void mv_pci_error_init(u32 pciIf)
+{
+	MV_U32      reg_val;
+
+	/* enable PCI express error handling */
+	MV_REG_BIT_SET(MV_IRQ_MASK_ERROR_REG, (1 << (PEX_ERR_IRQ_NUM(pciIf) - IRQ_ERROR(0))));
+
+	/* init pex_err structure per each pex */
+	pex_err[pciIf].ifNumber = pciIf;
+	snprintf(pex_err[pciIf].irq_name, PCI_ERR_NAME_LEN, "error_pex%d", pciIf);
+
+	/* register interrupt for PCI express error */
+	if (request_irq(PEX_ERR_IRQ_NUM(pciIf), pex_error_interrupt, IRQF_DISABLED,
+				(const char*)pex_err[pciIf].irq_name, &pex_err[pciIf].ifNumber) < 0) {
+		panic("Could not allocate IRQ for PCI express error!");
+	}
+
+	/* init PCI Express Interrupt Mask Register */
+
+	/* get current value of Interrupt Mask Register */
+	reg_val = MV_REG_READ(MV_PCI_MASK_REG(pciIf));
+
+	/* set relevant mask to Interrupt Mask Register */
+	MV_REG_WRITE(MV_PCI_MASK_REG(pciIf), (reg_val | MV_PCI_MASK_ERR));
+}
+
+/* Currentlly the PCI config read/write are implemented as read modify write
+   to 32 bit.
+   TBD: adjust it to realy use 1/2/4 byte(partial) read/write, after the pex
+	read config WA will be removed.
+*/
+static int mv_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+                          int size, u32 *val)
+{
+
+        MV_U32 bus_num,func,regOff,dev_no,temp;
+	MV_U32 localBus;
+	struct pci_sys_data *sysdata = (struct pci_sys_data *)bus->sysdata;     
+        u32 pciIf = sysdata->mv_controller_num; 
+ 
+	*val = 0xffffffff;
+
+	/* Check Power State */
+	if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, 0))
+		return 0;
+
+        bus_num = bus->number;
+        dev_no = PCI_SLOT(devfn);
+ 
+	/* don't return for our device */
+	localBus = mvPexLocalBusNumGet(pciIf);
+	if((dev_no == 0) && ( bus_num == localBus))
+	{
+		DB(printk("PCI %x read from our own dev return 0xffffffff \n", pciIf));
+		return 0xffffffff;
+	}
+
+        func = PCI_FUNC(devfn); 
+        regOff = (MV_U32)where & PXCAR_REG_NUM_MASK;
+
+#if PCI0_IF_PTP
+	/* WA: use only the first function of the bridge and te first bus*/
+	if( (bus_num == mvPexLocalBusNumGet(pciIf)) && (dev_no == 1) && (func != 0) )
+	{
+		DB(printk("PCI %x read from bridge func != 0 return 0xffffffff \n",pciIf));
+		return 0xffffffff;
+	}
+#endif
+	if ((func == 0)&&(dev_no < 2))
+	{
+		DB(printk("PCI %x read: bus = %x dev = %x func = %x regOff = %x ",pciIf, bus_num,dev_no,func,regOff));
+	}
+	
+
+        temp = (u32) mvPexConfigRead(pciIf, bus_num, dev_no, func, regOff);
+
+        switch (size) {
+        case 1:
+                temp = (temp >>  (8*(where & 0x3))) & 0xff;
+                break;
+ 
+        case 2:
+                temp = (temp >>  (8*(where & 0x2))) & 0xffff;
+                break;
+ 
+        default:
+                break;
+        }
+	
+	
+	*val = temp;
+
+	if ((func == 0)&&(dev_no < 2))
+	{
+		DB(printk(" got %x \n",temp));
+	}
+	
+        return 0;
+}
+
+static int mv_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+                           int size, u32 val)
+{
+        MV_U32 bus_num,func,regOff,dev_no,temp, mask , shift;
+        struct pci_sys_data *sysdata = (struct pci_sys_data *)bus->sysdata;     
+        u32 pciIf = sysdata->mv_controller_num;          
+
+	bus_num = bus->number;
+	dev_no = PCI_SLOT(devfn); 
+	func = PCI_FUNC(devfn); 
+	regOff = (MV_U32)where & PXCAR_REG_NUM_MASK;
+
+	DB(printk("PCI %x: writing data %x size %x to bus %x dev %x func %x offs %x \n",pciIf, val,size,bus_num,dev_no,func,regOff));
+	if( size != 4)
+	{
+        	temp = (u32) mvPexConfigRead(pciIf, bus_num, dev_no, func, regOff);
+	}
+	else
+	{
+		temp = val;
+	}
+
+        switch (size) {
+        case 1:
+		shift = (8*(where & 0x3));
+		mask = 0xff;
+                break;
+ 
+        case 2:
+		shift = (8*(where & 0x2));
+                mask = 0xffff; 
+                break;
+ 
+        default:
+		shift = 0;
+		mask = 0xffffffff;
+                break;
+        }
+	
+	temp = (temp & (~(mask<<shift))) | ((val & mask) << shift);
+	mvPexConfigWrite(pciIf,bus_num,dev_no,func,regOff,temp);
+
+        return 0;
+
+}
+
+
+
+
+static struct pci_ops mv_pci_ops = {
+        .read   = mv_pci_read_config,
+        .write  = mv_pci_write_config,
+};
+
+
+int __init mv_pci_setup(int nr, struct pci_sys_data *sys)
+{
+        struct resource *res;
+
+        switch (nr) {
+        case 0:
+                sys->map_irq = mv_map_irq_0;
+                break;
+        case 1:
+                sys->map_irq = mv_map_irq_1;
+                break;
+        default:
+		printk("mv_pci_setup: nr(%d) out of scope\n",nr);
+                return 0;
+        }
+
+	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+        if (!res)
+                panic("PCI: unable to alloc resources");
+                                                                                                                             
+        memset(res, 0, sizeof(struct resource) * 2);
+
+	if(!nr) {                                                                                                                             
+        	res[0].start = PEX0_IO_BASE - IO_SPACE_REMAP;
+        	res[0].end   = PEX0_IO_BASE - IO_SPACE_REMAP + PEX0_IO_SIZE - 1;
+        	res[0].name  = "PEX0 IO";
+        	res[0].flags = IORESOURCE_IO;
+                                                                                                                             
+        	res[1].start = PEX0_MEM_BASE;
+        	res[1].end   = PEX0_MEM_BASE + PEX0_MEM_SIZE - 1;
+        	res[1].name  = "PEX0 Memory";
+        	res[1].flags = IORESOURCE_MEM;
+	} else {
+        	res[0].start = PEX1_IO_BASE - IO_SPACE_REMAP;
+        	res[0].end   = PEX1_IO_BASE - IO_SPACE_REMAP + PEX1_IO_SIZE - 1;
+        	res[0].name  = "PEX1 IO";
+        	res[0].flags = IORESOURCE_IO;
+                                                                                                                             
+        	res[1].start = PEX1_MEM_BASE;
+        	res[1].end   = PEX1_MEM_BASE + PEX1_MEM_SIZE - 1;
+        	res[1].name  = "PEX1 Memory";
+        	res[1].flags = IORESOURCE_MEM;
+	}
+     
+        if (request_resource(&ioport_resource, &res[0]))
+	{	
+		printk ("IO Request resource failed - Pci If %x\n",nr);
+	}
+	if (request_resource(&iomem_resource, &res[1]))
+	{	
+		printk ("Memory Request resource failed - Pci If %x\n",nr);
+	}
+ 
+        sys->resource[0] = &res[0];
+        sys->resource[1] = &res[1];
+        sys->resource[2] = NULL;
+        sys->io_offset   = 0x0;
+	sys->mv_controller_num = nr;
+ 
+        return 1;
+
+}
+
+struct pci_bus *mv_pci_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	struct pci_ops *ops = &mv_pci_ops;
+	struct pci_bus *bus;
+
+      	bus = pci_scan_bus(sys->busnr, ops, sys);
+
+	if(sys->mv_controller_num == 0)
+        	mvPexLocalBusNumSet(1, 
+                	bus->number + bus->subordinate - bus->secondary + 1); 
+ 
+        return bus;
+}
+
+/**
+* pex_error_interrupt
+* DESCRIPTION: PCI express error interrupt  routine
+* INPUTS:      @irq: irq number
+               @dev_id: device id - ignored
+* OUTPUTS:     kernel error message
+* RETURNS:     IRQ_HANDLED
+**/
+static irqreturn_t pex_error_interrupt(int irq, void *dev_id)
+{
+	MV_U32  reg_val;
+	MV_U32 ifPexNumber=*(MV_U32 *)dev_id;
+
+	/* get current value of Interrupt Cause Register */
+	reg_val = MV_REG_READ(MV_PCI_IRQ_CAUSE_REG(ifPexNumber));
+	printk(KERN_ERR "PCI express error: irq - %d, Pex number: %d, "
+			"Interrupt Cause Register value: %x  \n", irq, ifPexNumber, reg_val);
+	MV_REG_WRITE(MV_PCI_IRQ_CAUSE_REG(ifPexNumber), ~reg_val);
+	return IRQ_HANDLED;
+}
+
+
+static int __init mv_map_irq_0(struct pci_dev *dev, u8 slot, u8 pin)
+{       
+        return PEX0_IRQ_NUM;
+}
+
+static int __init mv_map_irq_1(struct pci_dev *dev, u8 slot, u8 pin)
+{
+        return PEX1_IRQ_NUM;
+}
+
+
+static struct hw_pci mv_pci __initdata = {
+	.swizzle        	= pci_std_swizzle,
+        .map_irq                = mv_map_irq_0,
+        .setup                  = mv_pci_setup,
+        .scan                   = mv_pci_scan_bus,
+        .preinit                = mv_pci_preinit,
+};
+ 
+static int __init mv_pci_init(void)
+{
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+	/* Check pex power state */
+	MV_U32 pexPower;
+	pexPower = mvCtrlPwrClckGet(PEX_UNIT_ID,0);
+	if (pexPower == MV_FALSE)
+	{
+		printk("\nWarning PCI-E is Powered Off\n");
+		return 0;
+	}
+#endif
+
+    mv_pci.nr_controllers = mvCtrlPexMaxIfGet(); 
+    pci_common_init(&mv_pci);
+
+    return 0;
+}
+
+
+subsys_initcall(mv_pci_init);
+
diff --git a/arch/arm/mach-feroceon-kw2/pm.c b/arch/arm/mach-feroceon-kw2/pm.c
new file mode 100755
index 0000000..c9b7158
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/pm.c
@@ -0,0 +1,198 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+//#define DEBUG
+#include <linux/suspend.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+
+#include <asm/mach/time.h>
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "gpp/mvGpp.h"
+#include "device/mvDeviceRegs.h"
+#include "cntmr/mvCntmrRegs.h"
+#include "cpu/mvCpu.h"
+
+#define	MV_PMU_REGS_BASE	MV_PMU_REGS_OFFSET
+
+#define PMU_L2C_CTRL_AND_CONF	(MV_PMU_REGS_BASE + 0x004)
+#define PMU_L2C_EVENT_STATUS	(MV_PMU_REGS_BASE + 0x020)
+#define PMU_CPU_CTRL_AND_CONF	(MV_PMU_REGS_BASE + 0x104)
+#define PMU_CPU_STATUS_MASK	(MV_PMU_REGS_BASE + 0x10C)
+#define PMU_CPU_EVENT_STATUS	(MV_PMU_REGS_BASE + 0x120)
+#define PMU_CPU_BOOT_ADDR	(MV_PMU_REGS_BASE + 0x124)
+#define PMU_PWR_UP_DELAY	(MV_DEV_PMU_REGS_OFFSET + 0x014)
+
+static unsigned int   	count_standby;
+
+extern int kw2_cpu_suspend(void);
+extern int kw2_cpu_resume(void);
+extern MV_CPU_DEC_WIN* mv_sys_map(void);
+
+static int mv_pm_enter(suspend_state_t state);
+
+static MV_AHB_TO_MBUS_DEC_WIN ahbAddrDecWin[MAX_AHB_TO_MBUS_WINS];
+static MV_ADDR_WIN ahbAddrWinRemap[MAX_AHB_TO_MBUS_WINS];
+
+#define CONFIG_PMU_PROC
+
+void mv_kw2_cpu_idle_enter(void)
+{
+	mv_pm_enter(PM_SUSPEND_STANDBY);
+	return;
+}
+
+
+static void save_kw2_cpu_win_state(void)
+{
+	u32 i;
+	MV_AHB_TO_MBUS_DEC_WIN	winInfo;
+
+	/* Save CPU windows state, and enable access for Bootrom	*
+	** according to SoC default address decoding windows.		*/
+	for(i = 0; i < MAX_AHB_TO_MBUS_WINS; i++) {
+		mvAhbToMbusWinGet(i, &ahbAddrDecWin[i]);
+		mvAhbToMbusWinRemapGet(i, &ahbAddrWinRemap[i]);
+		
+		/* Disable the window */
+		mvAhbToMbusWinEnable(i, MV_FALSE);
+	}
+
+	/* Open default windows for Bootrom, PnC and internal regs.	*/
+	/* Bootrom */
+	winInfo.target = BOOT_ROM_CS;
+	winInfo.addrWin.baseLow = 0xF8000000;
+	winInfo.addrWin.baseHigh = 0x0;
+	winInfo.addrWin.size = _128M;
+	winInfo.enable = MV_TRUE;
+	mvAhbToMbusWinSet(7, &winInfo);
+
+	/* PnC */
+	winInfo.target = PNC_BM;
+	winInfo.addrWin.baseLow = 0xC0060000;
+	winInfo.addrWin.baseHigh = 0x0;
+	winInfo.addrWin.size = _64K;
+	winInfo.enable = MV_TRUE;
+	mvAhbToMbusWinSet(6, &winInfo);
+#if 0
+	/* Internal regs */
+	winInfo.target = INTER_REGS;
+	winInfo.addrWin.baseLow = 0xD0000000;
+	winInfo.addrWin.baseHigh = 0x0;
+	winInfo.addrWin.size = _1M;
+	winInfo.enable = MV_TRUE;
+	mvAhbToMbusWinSet(MV_AHB_TO_MBUS_INTREG_WIN, &winInfo);
+#endif
+	/* Cesa SRAM */
+	winInfo.target = CRYPT1_ENG;
+	winInfo.addrWin.baseLow = 0xC8010000;
+	winInfo.addrWin.baseHigh = 0x0;
+	winInfo.addrWin.size = _64K;
+	winInfo.enable = MV_TRUE;
+	mvAhbToMbusWinSet(4, &winInfo);
+
+}
+
+
+static void restore_kw2_cpu_win_state(void)
+{
+	mvCpuIfInit(mv_sys_map());
+}
+
+unsigned long suspend_phys_addr(void * physaddr)
+{
+	return virt_to_phys(physaddr);
+}
+
+static void mv_enter_standby(void)
+{
+	u32 reg;
+	static MV_U32 pwrUpDelay = 0;
+	
+
+	pr_debug("kw2_standby: Entering STANDBY mode.\n");
+	
+	if (pwrUpDelay == 0)
+		pwrUpDelay = mvBoardPwrUpDelayGet();
+
+	count_standby++;
+
+	save_kw2_cpu_win_state();
+
+	/* Prepare resume PC */
+	MV_REG_WRITE(PMU_CPU_BOOT_ADDR, virt_to_phys(kw2_cpu_resume));
+
+	MV_REG_WRITE(PMU_PWR_UP_DELAY, pwrUpDelay);
+
+	MV_REG_WRITE(PMU_CPU_STATUS_MASK, 0x00310000);
+
+	/* L2 Power down enable */
+	if (mvCpuL2Exists())
+		MV_REG_BIT_SET(PMU_L2C_CTRL_AND_CONF, BIT20);
+
+	/* CPU Power down enable */
+	MV_REG_BIT_SET(PMU_CPU_CTRL_AND_CONF, BIT20);
+
+	/* CPU Power down request */
+	MV_REG_BIT_SET(PMU_CPU_CTRL_AND_CONF, BIT16);
+
+	/* Suspend the CPU only */
+	if (kw2_cpu_suspend() == 0)
+		cpu_init();
+
+	restore_kw2_cpu_win_state();
+
+	reg = MV_REG_READ(PMU_CPU_STATUS_MASK);
+	reg &= ~0x3310000;
+	MV_REG_WRITE(PMU_CPU_STATUS_MASK, reg);
+
+	pr_debug("kw2_standby: Exiting STANDBY mode.\n");	
+}
+
+
+static int mv_pm_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		mv_enter_standby();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+
+int __init mv_pm_init(void)
+{
+	if (MV_6601_DEV_ID == mvCtrlModelGet())
+		return 0;
+
+	printk(KERN_INFO "Marvell Kirkwood2 Power Management Initializing\n");
+
+	return 0;
+}
+
+late_initcall(mv_pm_init);
+
diff --git a/arch/arm/mach-feroceon-kw2/rtc.c b/arch/arm/mach-feroceon-kw2/rtc.c
new file mode 100755
index 0000000..e26dcae
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/rtc.c
@@ -0,0 +1,157 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <linux/rtc.h>
+
+#include "mvCommon.h"
+#include "rtc/integ_rtc/mvRtc.h"
+
+#define FEBRUARY                2
+#define STARTOFTIME             1970
+#define SECDAY                  86400L
+#define SECYR                   (SECDAY * 365)
+                                                                                                                             
+/*
+ * Note: this is wrong for 2100, but our signed 32-bit time_t will
+ * have overflowed long before that, so who cares.  -- paulus
+ */
+#define leapyear(year)          ((year) % 4 == 0)
+#define days_in_year(a)         (leapyear(a) ? 366 : 365)
+#define days_in_month(a)        (month_days[(a) - 1])
+
+static int month_days[12] = {
+        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+void to_tm(int tim, MV_RTC_TIME *tm)
+{
+        register int i;
+        register long hms, day, gday;
+ 
+        gday = day = tim / SECDAY;
+        hms = tim % SECDAY;
+        /* Hours, minutes, seconds are easy */
+        tm->hours = hms / 3600;
+        tm->minutes = (hms % 3600) / 60;
+        tm->seconds = (hms % 3600) % 60;
+ 
+        /* Number of years in days */
+        for (i = STARTOFTIME; day >= days_in_year(i); i++)
+                day -= days_in_year(i);
+        tm->year = i;
+ 
+        /* Number of months in days left */
+        if (leapyear(tm->year))
+                days_in_month(FEBRUARY) = 29;
+        for (i = 1; day >= days_in_month(i); i++)
+                day -= days_in_month(i);
+        days_in_month(FEBRUARY) = 28;
+        tm->month = i;
+ 
+        /* Days are what is left over (+1) from all that. */
+        tm->date = day + 1;
+ 
+        /*
+         * Determine the day of week. Jan. 1, 1970 was a Thursday.
+         */
+        tm->day = (gday + 4) % 7;
+}
+
+
+static int mv_set_rtc(void)
+{
+	MV_RTC_TIME time;
+	to_tm(xtime.tv_sec, &time);
+	time.year -= 2000;
+	mvRtcTimeSet(&time);
+
+	return 1;
+}
+
+
+extern int (*set_rtc)(void);
+
+static inline int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	MV_RTC_TIME time;
+	unsigned long temp_t;
+
+	rtc_tm_to_time(tm, &temp_t);
+	to_tm(temp_t, &time);
+	/* same as in the U-Boot we use the year for century 20 only */
+	time.year -= 2000;
+	mvRtcTimeSet(&time);
+
+	return 0;
+}
+
+static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	MV_RTC_TIME time;
+	unsigned long temp_t;
+
+	mvRtcTimeGet(&time);
+	/* same as in the U-Boot we use the year for century 20 only */
+	temp_t = mktime ( time.year + 2000, time.month,
+        			time.date, time.hours,
+        			time.minutes, time.seconds);
+	rtc_time_to_tm(temp_t, tm);
+	
+	return 0;
+}
+
+static struct rtc_class_ops rtc_ops = {
+        .read_time      = mv_rtc_read_time,
+        .set_time       = mv_rtc_set_time,
+};
+
+static int mv_rtc_init(void)
+{
+	MV_RTC_TIME time;
+	struct timespec tv;
+	struct device *dev;
+
+	mvRtcTimeGet(&time);
+	dev = device_create(rtc_class, NULL, -1, NULL, "mv_rtc");
+
+	/* Date which is not in the 21 century will stop the RTC on
+ 	   00:00:00 - 01/01/2000, write operation will trigger it */
+	if ((time.year == 0) && (time.month == 1)  && (time.date == 1)) {
+		mvRtcTimeSet(&time);
+		printk(KERN_INFO "RTC has been updated!!!\n");
+	}
+
+	tv.tv_nsec = 0;
+	/* same as in the U-Boot we use the year for century 20 only */
+	tv.tv_sec = mktime ( time.year + 2000, time.month,
+			time.date, time.hours,
+			time.minutes, time.seconds);
+	do_settimeofday(&tv);	
+	set_rtc = mv_set_rtc;
+
+	rtc_device_register("kw-rtc", dev, &rtc_ops, THIS_MODULE);
+	printk("RTC registered\n");
+
+	return 0;
+}
+__initcall(mv_rtc_init);
diff --git a/arch/arm/mach-feroceon-kw2/sleep.S b/arch/arm/mach-feroceon-kw2/sleep.S
new file mode 100755
index 0000000..04cbc89
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/sleep.S
@@ -0,0 +1,203 @@
+/*
+ * arch/arm/mach-feroceon-kw/sleep.S
+ *
+ * Lower level support for Marvell Orion System On Chip
+ *
+ * Maintainer: Tawfik Bayouk <tawfik@marvell.com>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/domain.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/system.h>
+#include "config/mvSysHwConfig.h"
+
+
+	.text
+
+support_dram_self_refresh_address:
+        .word   support_dram_self_refresh
+
+#define	FUNC(x) ENTRY(x)
+
+#define	FUNC_END(x)
+
+#define CHANGE_MODE(x) \
+	mov	r1, r0		; \
+	bic	r1, r1, #0x1f	; \
+	orr	r1, r1, #0x##x	; \
+	msr	cpsr_c, r1
+
+# r0 - The address to map 0xF1000000 to.
+FUNC(kw2_cpu_map_regs)
+	stmfd	sp!, {lr}
+	mrc 	p15, 0, r1, c2, c0, 0		@ Get TTBR
+	ldr	r2, =INTER_REGS_BASE
+	lsr	r2, r2, #18
+	orr	r2, r2, #0xC0000000		@ Add kernel virtual Base.
+	orr	r1, r1, r2			@ Add TTBR base.
+	ldr	r2, [r1]
+	ldr	r3, =0xFFF
+	and	r2, r2, r3
+	orr	r0, r0, r2
+	str	r0, [r1]
+	# Flush Caches So that all is writen back to DRAM
+	bl	feroceon_flush_kern_cache_all
+#if defined(CONFIG_L2_CACHE_ENABLE) || defined(CONFIG_CACHE_FEROCEON_L2)
+	mov	r0, #0
+	mcr	p15, 1, r0, c15, c9, 0		@ clean entire L2 cache
+	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
+#endif
+#ifdef CONFIG_MMU
+	mcr	p15, 0, r0, c8, c7, 0		@ invalidate I,D TLBs on v4
+#endif
+
+	ldmfd	sp!, {pc}
+FUNC_END(kw2_cpu_suspend)
+
+/*
+ * Suspend execution and enter STANDBY or SLEEP mode
+ */
+FUNC(kw2_cpu_suspend)
+	stmfd	sp!, {r4-r12, lr}		@ save general regs
+	mrc 	p15, 0, r2, c1, c0, 0		@ save CP15 - CR
+	mrc 	p15, 0, r3, c3, c0, 0		@ save CP15 - DACR
+	mrc 	p15, 0, r4, c13, c0, 0		@ save CP15 - FCSE
+	mrc 	p15, 0, r5, c2, c0, 0		@ save CP15 - TTBR
+	mov	r6, r13				@ save resume SP
+	mrc	p15, 1, r7, c15, c1, 0		@ save Marvell extra features
+	ldr	r0, =(INTER_REGS_BASE + 0x20128)@ save L2 Config Reg
+	ldr	r8, [r0]
+	stmfd	sp!, {r2-r8}
+
+	/*
+	 * Save the physical address of the resume SP
+	 */
+	mov	r0, sp
+	bl	suspend_phys_addr
+	ldr	r1, =suspend_saved_sp
+	str	r0, [r1]
+
+	/*
+	 * Flush Caches So that all is writen back to DRAM
+	 */
+	bl	feroceon_flush_kern_cache_all
+
+#if defined(CONFIG_L2_CACHE_ENABLE) || defined(CONFIG_CACHE_FEROCEON_L2)
+	mov	r0, #0
+	mcr	p15, 1, r0, c15, c9, 0		@ clean entire L2 cache
+	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
+#endif
+
+	ldr	r1, =(INTER_REGS_BASE + 0x200F0)
+	ldr	r2, =(0xD0000000)
+#	str	r2, [r1]
+
+	ldr	r3, =(INTER_REGS_BASE + 0x1418)
+	mov 	r4, #0x7
+	mov	r0, #0x0
+	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
+
+	/*
+	** Check if dram_self_refresh is enabled.
+	*/
+        ldr     r0, support_dram_self_refresh_address
+        ldr     r0, [r0]
+        cmp     r0, #1				@ Do we support SR?
+        bne     2f				@ if yes, then go to WFI.
+	b	1f				@ if no, enable SR.
+
+	.align 5
+1:	str	r4, [r3]			@ Self refresh command
+2:	str	r2, [r1]			@ Regs base to 0xD0000000
+	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
+
+	# We returned immediately from suspend, restore internal regs base &
+	# stack pointer.
+	ldr	r0, =0xD0000000
+	bl	kw2_cpu_map_regs		@ Map 0xF1000000 --> 0xD0000000 in MMU.
+
+	ldr	r0, =(INTER_REGS_BASE + 0x200F0)
+	ldr	r1, =INTER_REGS_BASE
+	str	r1, [r0]			@ restore regs base addr
+
+	ldr	r0, =INTER_REGS_BASE
+	bl	kw2_cpu_map_regs		@ Map 0xF1000000 --> 0xF1000000 in MMU.
+
+##	ldr	r3, =(INTER_REGS_BASE + 0x1418)
+##	mov	r4, #0x0
+##	str	r4, [r3]			@ Self refresh command
+
+##	ldr	r0, =(INTER_REGS_BASE + 0x12000)
+##	mov	r1, #'F'
+##	str	r1, [r0]
+
+	mov	r0, #1
+	ldmfd	sp!, {r2-r8}
+	ldmfd	sp!, {r4-r12, pc}
+
+FUNC_END(kw2_cpu_suspend)
+
+
+/*
+ * Resume from SLEEP or STANDBY suspend
+ */
+	.data
+	.align 5
+FUNC(kw2_cpu_resume)
+	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+##	ldr	r0, =(0xD0000000 + 0x12000)
+##	mov	r1, #'O'
+##	str	r1, [r0]
+
+	ldr	r0, =0xD00200F0
+	ldr	r1, =INTER_REGS_BASE
+	str	r1, [r0]			@ restore regs base addr
+
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0		@ invalidate I,D caches on v4
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer on v4
+#ifdef CONFIG_MMU
+	mcr	p15, 0, r0, c8, c7, 0		@ invalidate I,D TLBs on v4
+#endif
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mov	r0, #4				@ disable write-back on caches explicitly
+	mcr	p15, 7, r0, c15, c0, 0
+#endif 
+
+	ldr	r0, suspend_saved_sp		@ stack phys addr
+	ldmfd	r0, {r2-r8}
+	ldr	r0, =(INTER_REGS_BASE + 0x20128)
+	str	r8, [r0]			@ restorem L2 Config Reg
+	mcr	p15, 1, r7, c15, c1, 0		@ restore Marvell Extra Features
+	mcr 	p15, 0, r5, c2, c0, 0		@ restore CP15 - TTBR
+	mcr 	p15, 0, r4, c13, c0, 0		@ restore CP15 - FCSE
+	mcr 	p15, 0, r3, c3, c0, 0		@ restore CP15 - DACR
+	ldr	r3, =resume_after_mmu		@ virtual address jump
+	b	resume_turn_on_mmu		@ cache align
+
+	.align 5
+resume_turn_on_mmu:
+	mcr 	p15, 0, r2, c1, c0, 0		@ restore CP15 - CR
+	nop
+	mov	pc, r3				@ jump to virtual addr
+	nop
+	nop
+	nop
+
+suspend_saved_sp:
+	.word	0				@ physical SP saved here
+
+	.text
+resume_after_mmu:
+	mov	r13, r6				@ restore virtual SP
+	mov	r0, #0x0
+	ldmfd	sp!, {r4-r12, pc}		@ restore SVC registers
+FUNC_END(kw2_cpu_resume)
+
+	.end
diff --git a/arch/arm/mach-feroceon-kw2/sysmap.c b/arch/arm/mach-feroceon-kw2/sysmap.c
new file mode 100755
index 0000000..8bf1f24
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/sysmap.c
@@ -0,0 +1,264 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "mvSysHwConfig.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include <asm/mach/map.h>
+
+/* for putstr */
+/* #include <asm/arch/uncompress.h> */
+
+MV_CPU_DEC_WIN* mv_sys_map(void);
+
+#if defined(CONFIG_MV_INCLUDE_CESA)
+u32 mv_crypto_base_get(u8 chan);
+#endif
+
+#if defined(CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING)
+
+/* need to make sure it is big enough to hold all mapping entries */
+#define MEM_TABLE_MAX_ENTRIES	30
+
+/* default mapped entries */
+#define MEM_TABLE_ENTRIES	6
+
+/* number of entries to map */
+volatile u32 entries = MEM_TABLE_ENTRIES;
+
+struct _mv_internal_regs_map {
+	MV_UNIT_ID id;
+	u32 index;
+	u32 offset;
+	u32 size;
+};
+
+/* Internal registers mapping table */
+struct _mv_internal_regs_map mv_internal_regs_map[] = {
+	{DRAM_UNIT_ID,		0,	MV_DRAM_REGS_OFFSET,		SZ_64K},
+	{CESA_UNIT_ID,		0,	MV_CESA_TDMA_REGS_OFFSET,	SZ_64K},
+	{USB_UNIT_ID,		0,	MV_USB_REGS_OFFSET(0),		SZ_64K},
+	{XOR_UNIT_ID,		0,	MV_XOR_REGS_OFFSET,		SZ_64K},
+	{ETH_GIG_UNIT_ID,	0,	MV_ETH_REGS_OFFSET(0),		SZ_8K},  /* GbE port0 registers */
+	{ETH_GIG_UNIT_ID,	1,	MV_ETH_REGS_OFFSET(1),		SZ_8K},  /* GbE port1 registers */
+	{SATA_UNIT_ID,		0,	(MV_SATA_REGS_OFFSET + 0x2000),	SZ_8K }, /* SATA port0 registers */
+	{SDIO_UNIT_ID,		0,	MV_SDIO_REGS_OFFSET,		SZ_64K},
+	{TDM_UNIT_ID,		0,	MV_TDM_REGS_OFFSET,		SZ_64K},
+	{XPON_UNIT_ID,		0,	MV_PON_REGS_OFFSET,		SZ_64K},
+	{BM_UNIT_ID,		0,	MV_BM_REGS_OFFSET,		SZ_64K},
+	{PNC_UNIT_ID,		0,	MV_PNC_REGS_OFFSET,		SZ_64K}
+};
+
+/* AHB to MBUS mapping entry */
+struct map_desc AHB_TO_MBUS_MAP[] = {
+	{(INTER_REGS_BASE + MAX_AHB_TO_MBUS_REG_BASE), __phys_to_pfn(INTER_REGS_BASE + MAX_AHB_TO_MBUS_REG_BASE),
+		SZ_64K, MT_DEVICE},
+};
+
+struct map_desc  MEM_TABLE[MEM_TABLE_MAX_ENTRIES] = {
+	{(INTER_REGS_BASE + MV_MPP_REGS_OFFSET),
+		__phys_to_pfn(INTER_REGS_BASE + MV_MPP_REGS_OFFSET),  		SZ_64K,			MT_DEVICE},
+	{(INTER_REGS_BASE + MV_SATA_REGS_OFFSET),
+		__phys_to_pfn(INTER_REGS_BASE + MV_SATA_REGS_OFFSET),		SZ_8K,			MT_DEVICE},
+	{(INTER_REGS_BASE + MV_PEX_IF_REGS_OFFSET(0)),
+		__phys_to_pfn(INTER_REGS_BASE + MV_PEX_IF_REGS_OFFSET(0)),	SZ_64K,			MT_DEVICE},
+	{ PEX0_IO_BASE,			__phys_to_pfn(PEX0_IO_BASE),		PEX0_IO_SIZE,		MT_DEVICE},
+	{ PEX1_IO_BASE,			__phys_to_pfn(PEX1_IO_BASE),		PEX1_IO_SIZE,		MT_DEVICE},
+	{ SPI_CS_BASE,			__phys_to_pfn(SPI_CS_BASE),		SPI_CS_SIZE,		MT_DEVICE},
+	{ CRYPT_ENG_BASE(0),		__phys_to_pfn(CRYPT_ENG_BASE(0)),	CRYPT_ENG_SIZE,		MT_DEVICE},
+	{ CRYPT_ENG_BASE(1),		__phys_to_pfn(CRYPT_ENG_BASE(1)),	CRYPT_ENG_SIZE,		MT_DEVICE},
+	{ PNC_BM_PHYS_BASE,		__phys_to_pfn(PNC_BM_PHYS_BASE),	PNC_BM_SIZE,	        MV_DEVICE}
+};
+
+#else
+
+struct map_desc  MEM_TABLE_88F6500[] =	{
+	/* no use for pex mem remap */	
+	/*{ PEX0_MEM_BASE,  		__phys_to_pfn(PEX0_MEM_BASE),   	PEX0_MEM_SIZE,  	MT_DEVICE},*/
+	/* Internal Regs were mapped earlier */
+/*	{ INTER_REGS_BASE, 		__phys_to_pfn(INTER_REGS_BASE), 	SZ_1M,  	     	MT_DEVICE}, */
+	{ PEX0_IO_BASE,   		__phys_to_pfn(PEX0_IO_BASE),   	 	PEX0_IO_SIZE,  		MT_DEVICE},
+	{ PEX1_IO_BASE,			__phys_to_pfn(PEX1_IO_BASE),		PEX1_IO_SIZE,		MT_DEVICE},
+	{ SPI_CS_BASE,			__phys_to_pfn(SPI_CS_BASE),		SPI_CS_SIZE,		MT_DEVICE},
+	{ CRYPT_ENG_BASE(0),		__phys_to_pfn(CRYPT_ENG_BASE(0)),	CRYPT_ENG_SIZE,		MT_DEVICE},
+	{ CRYPT_ENG_BASE(1),		__phys_to_pfn(CRYPT_ENG_BASE(1)),	CRYPT_ENG_SIZE,		MT_DEVICE},
+	{ PNC_BM_PHYS_BASE,		__phys_to_pfn(PNC_BM_PHYS_BASE),	PNC_BM_SIZE,		MT_DEVICE}
+};
+
+/* Internal registers mapping entry */
+struct map_desc INTER_REGS_MAP[] = {
+		{ INTER_REGS_BASE, __phys_to_pfn(INTER_REGS_BASE), SZ_1M, MT_DEVICE},
+};
+
+struct map_desc  MEM_TABLE_88F6601[] =	{
+	/* Internal Regs were mapped earlier */
+/*	{ INTER_REGS_BASE, 		__phys_to_pfn(INTER_REGS_BASE), 	SZ_1M,  	     	MT_DEVICE}, */
+	{ SPI_CS_BASE,			__phys_to_pfn(SPI_CS_BASE),		SPI_CS_SIZE,		MT_DEVICE},
+	{ PNC_BM_PHYS_BASE,		__phys_to_pfn(PNC_BM_PHYS_BASE),	PNC_BM_SIZE,		MT_DEVICE}
+};
+
+#endif /* CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING */
+
+MV_CPU_DEC_WIN SYSMAP_88F6500[] = {
+	/* base low        base high    size       		WinNum     	enable */
+	{{SDRAM_CS0_BASE,	0,	SDRAM_CS0_SIZE	},	0xFFFFFFFF,	DIS},	/* SDRAM_CS0 */
+	{{SDRAM_CS1_BASE,	0,	SDRAM_CS1_SIZE	},	0xFFFFFFFF,	DIS},	/* SDRAM_CS1 */
+	{{SDRAM_CS2_BASE,	0,	SDRAM_CS2_SIZE	},	0xFFFFFFFF,	DIS},	/* SDRAM_CS2 */
+	{{SDRAM_CS3_BASE,	0,	SDRAM_CS3_SIZE	},	0xFFFFFFFF,	DIS},	/* SDRAM_CS3 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* DEVICE_CS0 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* DEVICE_CS1 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* DEVICE_CS2 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* DEVICE_CS3 */
+	{{PEX0_MEM_BASE,	0,	PEX0_MEM_SIZE	},	0x1,		EN},	/* PEX0_MEM */
+	{{PEX0_IO_BASE,		0,	PEX0_IO_SIZE	},	0x0,		EN},	/* PEX0_IO */
+	{{PEX1_MEM_BASE,	0,	PEX1_MEM_SIZE	},	0x3,		EN},	/* PEX1_MEM */
+	{{PEX1_IO_BASE,		0,	PEX1_IO_SIZE	},	0x2,		EN},	/* PEX1_IO */
+	{{INTER_REGS_BASE,	0,	INTER_REGS_SIZE	},	0xe,		EN},	/* INTER_REGS */
+#ifdef CONFIG_MV_INCLUDE_NORFLASH_MTD
+       	{{NAND_NOR_CS_BASE,	0,	NOR_CS_SIZE	},	0x4,		EN},	/* NOR_CS */
+#else
+	{{NAND_NOR_CS_BASE,	0,	NAND_CS_SIZE	},	0x4,		EN},	/* NAND_CS */
+#endif
+	{{SPI_CS_BASE,		0,	SPI_CS_SIZE	},	0x5,		EN},	/* SPI_CS0 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* SPI_CS1 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* SPI_CS2 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* SPI_CS3 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* SPI_CS4 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* SPI_CS5 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* SPI_CS6 */
+        {{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* SPI_CS7 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* SPI_B_CS0 */
+	{{DEVICE_CS2_BASE,	0,	DEVICE_CS2_SIZE	},	0x6,		DIS},	/* BOOT_ROM_CS */
+ 	{{BOOTDEV_CS_BASE,	0,	BOOTDEV_CS_SIZE	},	0x7,		DIS},	/* DEV_BOOCS */
+	{{CRYPT_ENG_BASE(0),	0,	CRYPT_ENG_SIZE	},	0x8,		EN},	/* CRYPT1_ENG */
+#if (CONFIG_MV_CESA_CHANNELS > 1)
+	{{CRYPT_ENG_BASE(1),	0,	CRYPT_ENG_SIZE	},	0x9,		EN},	/* CRYPT2_ENG */
+#else
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* CRYPT2_ENG */
+#endif
+	{{PNC_BM_PHYS_BASE,	0,	PNC_BM_SIZE	},	0xa,		EN},	/* PNC_BM */
+	{{PMT_GIGA_PHYS_BASE,	0,	PMT_MEM_SIZE	},	0xb,		EN},	/* PMT_GIGA */
+	{{PMT_PON_PHYS_BASE,	0,	PMT_MEM_SIZE	},	0xc,		EN},	/* PMT_PON */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,	DIS},	/* NFC_CTRL */
+	{{TBL_TERM,		TBL_TERM, TBL_TERM	},	TBL_TERM,	TBL_TERM}
+};
+
+MV_CPU_DEC_WIN SYSMAP_88F6601[] = {
+	/* base low        base high    size       		WinNum     	enable */
+	{{SDRAM_CS0_BASE,	0,	SDRAM_CS0_SIZE	},	0xFFFFFFFF,		DIS},	/* SDRAM_CS0 */
+	{{SDRAM_CS1_BASE,	0,	SDRAM_CS1_SIZE	},	0xFFFFFFFF,		DIS},	/* SDRAM_CS1 */
+	{{SDRAM_CS2_BASE,	0,	SDRAM_CS2_SIZE	},	0xFFFFFFFF,		DIS},	/* SDRAM_CS2 */
+	{{SDRAM_CS3_BASE,	0,	SDRAM_CS3_SIZE	},	0xFFFFFFFF,		DIS},	/* SDRAM_CS3 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* DEVICE_CS0 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* DEVICE_CS1 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* DEVICE_CS2 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* DEVICE_CS3 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED	},	TBL_UNUSED,		DIS},	/* PEX0_MEM */
+	{{TBL_UNUSED,		0,	TBL_UNUSED	},	TBL_UNUSED,		DIS},	/* PEX0_IO */
+	{{TBL_UNUSED,		0,	TBL_UNUSED	},	TBL_UNUSED,		DIS},	/* PEX1_MEM */
+	{{TBL_UNUSED,		0,	TBL_UNUSED	},	TBL_UNUSED,		DIS},	/* PEX1_IO */
+	{{INTER_REGS_BASE,	0,	INTER_REGS_SIZE	},	0xe,			EN},	/* INTER_REGS */
+	{{TBL_UNUSED,		0,	TBL_UNUSED	},	TBL_UNUSED,		DIS},	/* NAND_CS */
+	{{SPI_CS_BASE,		0,	SPI_CS_SIZE	},	0x5,			EN},	/* SPI_CS0 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* SPI_CS1 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* SPI_CS2 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* SPI_CS3 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* SPI_CS4 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* SPI_CS5 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* SPI_CS6 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* SPI_CS7 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* SPI_B_CS0 */
+	{{TBL_UNUSED,		0,	TBL_UNUSED	},	TBL_UNUSED,		DIS},	/* BOOT_ROM_CS */
+ 	{{TBL_UNUSED,		0,	TBL_UNUSED	},	TBL_UNUSED,		DIS},	/* DEV_BOOCS */
+	{{TBL_UNUSED,		0,	TBL_UNUSED	},	TBL_UNUSED,		DIS},	/* CRYPT1_ENG */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* CRYPT2_ENG */
+	{{PNC_BM_PHYS_BASE,	0,	PNC_BM_SIZE	},	0xa,			EN},	/* PNC_BM */
+	{{PMT_GIGA_PHYS_BASE,	0,	PMT_MEM_SIZE	},	0xb,			EN},	/* PMT_GIGA */
+	{{PMT_PON_PHYS_BASE,	0,	PMT_MEM_SIZE	},	0xc,			EN},	/* PMT_PON */
+	{{TBL_UNUSED,		0,	TBL_UNUSED,	},	TBL_UNUSED,		DIS},	/* NFC_CTRL */
+	{{TBL_TERM,		TBL_TERM, TBL_TERM	},	TBL_TERM,		TBL_TERM}
+};
+
+#if defined(CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING)
+
+void __init mv_build_map_table(void)
+{
+	u32 unit;
+	
+	/* prepare consecutive mapping table */
+	for(unit = 0; unit < ARRAY_SIZE(mv_internal_regs_map); unit++) {
+		if(MV_TRUE == mvCtrlPwrClckGet(mv_internal_regs_map[unit].id, mv_internal_regs_map[unit].index)) {
+			MEM_TABLE_88F6500[entries].virtual = (INTER_REGS_BASE + mv_internal_regs_map[unit].offset);
+			MEM_TABLE_88F6500[entries].pfn = __phys_to_pfn(INTER_REGS_BASE + mv_internal_regs_map[unit].offset);
+			MEM_TABLE_88F6500[entries].length = mv_internal_regs_map[unit].size;
+			MEM_TABLE_88F6500[entries].type = MT_DEVICE;
+			entries++;
+		}
+	}
+}
+
+#endif /* CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING */
+
+MV_CPU_DEC_WIN* mv_sys_map(void)
+{
+	switch(mvBoardIdGet()) {
+		case DB_88F6535_BP_ID:
+		case RD_88F6510_SFU_ID:
+		case RD_88F6560_GW_ID:
+		case RD_88F6530_MDU_ID:
+			return SYSMAP_88F6500;
+ 		case DB_88F6601_BP_ID:
+		case RD_88F6601_MC_ID:
+			return SYSMAP_88F6601;
+		default:
+			printk("ERROR: can't find system address map\n");
+			return NULL;
+        }
+}
+
+#if defined(CONFIG_MV_INCLUDE_CESA)
+u32 mv_crypto_base_get(u8 chan)
+{
+	return CRYPT_ENG_BASE(chan);
+}
+#endif
+
+void __init mv_map_io(void)
+{
+#if defined(CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING)
+	/* first, mappping AHB to MBUS entry for mvCtrlPwrClckGet access */
+	iotable_init(AHB_TO_MBUS_MAP, ARRAY_SIZE(AHB_TO_MBUS_MAP));
+
+	/* build dynamic mapping table  */
+	mv_build_map_table();
+
+	iotable_init(MEM_TABLE_88F6500, entries);
+#else
+	/* first, mappping Internal registers to MBUS entry for mvCtrlModelGet access */
+	iotable_init(INTER_REGS_MAP, ARRAY_SIZE(INTER_REGS_MAP));
+
+	if (MV_6601_DEV_ID == mvCtrlModelGet())
+		iotable_init(MEM_TABLE_88F6601, ARRAY_SIZE(MEM_TABLE_88F6601));
+	else
+		iotable_init(MEM_TABLE_88F6500, ARRAY_SIZE(MEM_TABLE_88F6500));
+		
+	return;
+
+#endif /* CONFIG_MV_INTERNAL_REGS_SELECTIVE_MAPPING */	
+}
+
+
diff --git a/arch/arm/mach-feroceon-kw2/time.c b/arch/arm/mach-feroceon-kw2/time.c
new file mode 100755
index 0000000..8920b88
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/time.c
@@ -0,0 +1,194 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/mach/time.h>
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "cntmr/mvCntmrRegs.h"
+
+/*
+ * Timer0: clock_event_device, Tick.
+ * Timer1: clocksource, Free running.
+ * WatchDog: Not used.
+ *
+ * Timers are counting down.
+ */
+#define CLOCKEVENT	0
+#define CLOCKSOURCE	1
+
+/*
+ * Timers bits
+ */
+#define BRIDGE_INT_TIMER(x)	(1 << ((x) + 1))
+#define TIMER_EN(x)		(1 << ((x) * 2))
+#define TIMER_RELOAD_EN(x)	(1 << (((x) * 2) + 1))
+#define BRIDGE_INT_TIMER_WD	(1 << 3)
+#define TIMER_WD_EN		(1 << 4)
+#define TIMER_WD_RELOAD_EN	(1 << 5)
+
+static cycle_t kw_clksrc_read(struct clocksource *cs)
+{
+	return (0xffffffff - MV_REG_READ(CNTMR_VAL_REG(CLOCKSOURCE)));
+}
+
+static struct clocksource kw_clksrc = {
+	.name		= "kw_clocksource",
+	.shift		= 20,
+	.rating		= 300,
+	.read		= kw_clksrc_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int
+kw_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
+{
+	unsigned long flags;
+
+	if (delta == 0)
+		return -ETIME;
+
+	local_irq_save(flags);
+
+	/*
+	 * Clear and enable timer interrupt bit
+	 */
+	MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+	MV_REG_BIT_SET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKEVENT));
+
+	/*
+	 * Setup new timer value
+	 */
+	MV_REG_WRITE(CNTMR_VAL_REG(CLOCKEVENT), delta);
+
+	/*
+	 * Disable auto reload and kickoff the timer
+	 */
+	MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKEVENT));
+	MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_EN(CLOCKEVENT));
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static void
+kw_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	if (mode == CLOCK_EVT_MODE_PERIODIC) {
+		/*
+		 * Setup latch cycles in timer and enable reload interrupt.
+		 */
+		MV_REG_WRITE(CNTMR_RELOAD_REG(CLOCKEVENT), ((mvBoardTclkGet() + HZ/2) / HZ));
+		MV_REG_WRITE(CNTMR_VAL_REG(CLOCKEVENT), ((mvBoardTclkGet() + HZ/2) / HZ));
+		MV_REG_BIT_SET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKEVENT));
+		MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKEVENT) |
+					  TIMER_EN(CLOCKEVENT));
+	} else {
+		/*
+		 * Disable timer and interrupt
+		 */
+		MV_REG_BIT_RESET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKEVENT));
+		MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+		MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKEVENT) |
+					  TIMER_EN(CLOCKEVENT));
+	}
+
+	local_irq_restore(flags);
+}
+
+static struct clock_event_device kw_clkevt = {
+	.name		= "kw_tick",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.rating		= 300,
+	.set_next_event	= kw_clkevt_next_event,
+	.set_mode	= kw_clkevt_mode,
+};
+
+extern void mv_leds_hearbeat(void);
+static irqreturn_t kw_timer_interrupt(int irq, void *dev_id)
+{
+	/*
+	 * Clear cause bit and do event
+	 */
+	MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+	kw_clkevt.event_handler(&kw_clkevt);
+	mv_leds_hearbeat();
+	return IRQ_HANDLED;
+}
+
+static struct irqaction kw_timer_irq = {
+	.name		= "kw_tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.handler	= kw_timer_interrupt
+};
+
+static void mv_init_timer(void)
+{
+	/*
+	 * Setup clocksource free running timer (no interrupt on reload)
+	 */
+ 	MV_REG_WRITE(CNTMR_VAL_REG(CLOCKSOURCE), 0xffffffff);
+	MV_REG_WRITE(CNTMR_RELOAD_REG(CLOCKSOURCE), 0xffffffff);
+	MV_REG_BIT_RESET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKSOURCE));
+	MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKSOURCE) |
+				  TIMER_EN(CLOCKSOURCE));
+
+	kw_clkevt.cpumask = cpumask_of(0);
+
+	/*
+	 * Register clocksource
+	 */
+	kw_clksrc.mult =
+		clocksource_hz2mult(mvBoardTclkGet(), kw_clksrc.shift);
+
+	clocksource_register(&kw_clksrc);
+
+	/*
+	 * Connect and enable tick handler
+	 */
+	setup_irq(BRIDGE_IRQ_NUM, &kw_timer_irq);
+
+	/*
+	 * Register clockevent
+	 */
+	kw_clkevt.mult =
+		div_sc(mvBoardTclkGet(), NSEC_PER_SEC, kw_clkevt.shift);
+	kw_clkevt.max_delta_ns =
+		clockevent_delta2ns(0xfffffffe, &kw_clkevt);
+	kw_clkevt.min_delta_ns =
+		clockevent_delta2ns(1, &kw_clkevt);
+
+	/*
+	 * Setup clockevent timer (interrupt-driven.)
+	 */
+	clockevents_register_device(&kw_clkevt);
+}
+
+struct sys_timer mv_timer = {
+        .init           = mv_init_timer,
+};
+
diff --git a/arch/arm/mach-feroceon-kw2/usb.c b/arch/arm/mach-feroceon-kw2/usb.c
new file mode 100755
index 0000000..a07ff64
--- /dev/null
+++ b/arch/arm/mach-feroceon-kw2/usb.c
@@ -0,0 +1,151 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+                                                                                                                             
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "mvCommon.h"
+#include "mvDebug.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mvSysUsbApi.h"
+#include "usb/mvUsbRegs.h"
+#include "usb/mvUsb.h"
+
+extern u32 mvIsUsbHost;
+
+#define MV_USB_DMA_MASK     0xffffffff
+
+static char usb_dev_name[]  = "mv_udc";
+static char usb_host_name[] = "ehci_marvell";
+static char usb_bus_name[]  = "platform";
+
+
+static void mv_usb_release(struct device *dev)
+{
+    struct platform_device  *pdev = to_platform_device(dev); 
+
+    /* normally not freed */
+    printk("mv_usb_release\n");
+
+    kfree(pdev->resource);
+    kfree(pdev->dev.dma_mask);
+    kfree(pdev);
+} 
+
+
+static int __init   mv_usb_init(void)
+{
+	int                     status, dev, num, isHost;
+	char*                   name_ptr;
+	struct platform_device* mv_usb_dev_ptr;
+
+	num = mvCtrlUsbMaxGet(); 
+	for(dev=0; dev<num; dev++)
+	{
+		if (MV_FALSE == mvCtrlPwrClckGet(USB_UNIT_ID, dev))
+		{
+			printk("\nWarning Integrated USB %d is Powered Off\n",dev);
+			continue;	    
+		}
+
+		isHost = mvIsUsbHost & (1 << dev);
+
+		if(isHost)
+			name_ptr = usb_host_name;
+		else
+			name_ptr = usb_dev_name;
+
+		status = mvSysUsbInit(dev, isHost);
+
+		mv_usb_dev_ptr = kmalloc(sizeof(struct platform_device), GFP_KERNEL);
+		if(mv_usb_dev_ptr == NULL)
+		{
+			printk("Can't allocate platform_device structure - %d bytes\n",
+					sizeof(struct platform_device) );
+			return 1;
+		}
+		memset(mv_usb_dev_ptr, 0, sizeof(struct platform_device) );
+
+		mv_usb_dev_ptr->name               = name_ptr;
+		mv_usb_dev_ptr->id                 = PCI_VENDOR_ID_MARVELL | (MV_USB_VERSION << 16) | (dev << 24);
+
+		mv_usb_dev_ptr->num_resources  = 2;
+
+		mv_usb_dev_ptr->resource = (struct resource*)kmalloc(2*sizeof(struct resource), GFP_KERNEL);
+		if(mv_usb_dev_ptr->resource == NULL)
+		{
+			printk("Can't allocate 2 resource structure - %d bytes\n",
+					2*sizeof(struct resource) );
+			kfree(mv_usb_dev_ptr);
+			return 1;
+		}
+		memset(mv_usb_dev_ptr->resource, 0, 2*sizeof(struct resource));
+
+		mv_usb_dev_ptr->resource[0].start =
+			( INTER_REGS_BASE | MV_USB_CORE_CAP_LENGTH_REG(dev));
+		mv_usb_dev_ptr->resource[0].end   =
+			((INTER_REGS_BASE | MV_USB_CORE_CAP_LENGTH_REG(dev)) + 4096);
+		mv_usb_dev_ptr->resource[0].flags = IORESOURCE_DMA;
+
+		mv_usb_dev_ptr->resource[1].start = USB_IRQ_NUM;
+		mv_usb_dev_ptr->resource[1].flags = IORESOURCE_IRQ;
+
+		mv_usb_dev_ptr->dev.dma_mask           = kmalloc(sizeof(u64), GFP_KERNEL);
+		*mv_usb_dev_ptr->dev.dma_mask          = MV_USB_DMA_MASK;
+
+		mv_usb_dev_ptr->dev.coherent_dma_mask  = ~0;
+		mv_usb_dev_ptr->dev.release            = mv_usb_release;
+		dev_set_name(&mv_usb_dev_ptr->dev, "%s", usb_bus_name);
+
+		printk("Marvell USB %s controller #%d: %p\n",
+				isHost ? "EHCI Host" : "Gadget", dev, mv_usb_dev_ptr);
+
+		status = platform_device_register(mv_usb_dev_ptr);
+		if (status)
+		{
+			printk("Can't register Marvell USB EHCI controller #%d, status=%d\n", 
+					dev, status);
+			return status;
+		}
+	}
+	return 0;
+}
+
+subsys_initcall(mv_usb_init);
+
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
old mode 100644
new mode 100755
index 9264d81..6d985f6
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -742,7 +742,7 @@
 
 config CACHE_FEROCEON_L2
 	bool "Enable the Feroceon L2 cache controller"
-	depends on ARCH_KIRKWOOD || ARCH_MV78XX0
+	depends on ARCH_KIRKWOOD || ARCH_MV78XX0 || ARCH_FEROCEON_KW || ARCH_FEROCEON_KW2
 	default y
 	select OUTER_CACHE
 	help
@@ -776,3 +776,12 @@
 	int
 	default 6 if ARCH_OMAP3
 	default 5
+
+config ARM_ARMV5_L2_CACHE_COHERENCY_FIX
+	bool "Enable L2 coherency problem fix on ARMv5"
+	depends on OUTER_CACHE && CPU_CACHE_VIVT
+	default y
+	help
+	Fixes coherency problems on ARM systems that have
+	a non-disableable VIVT L1 cache and a PIPT L2 one.
+
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
old mode 100644
new mode 100755
index 055cb2a..f37b0ec
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -1,6 +1,10 @@
 #
 # Makefile for the linux arm-specific parts of the memory manager.
 #
+     
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
 
 obj-y				:= dma-mapping.o extable.o fault.o init.o \
 				   iomap.o
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
old mode 100644
new mode 100755
index b270d62..d3cdb4f
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -75,7 +75,7 @@
 static unsigned long ai_word;
 static unsigned long ai_dword;
 static unsigned long ai_multi;
-static int ai_usermode;
+static int ai_usermode = 2;
 
 #define UM_WARN		(1 << 0)
 #define UM_FIXUP	(1 << 1)
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c
old mode 100644
new mode 100755
index 6e77c04..04e14f7
--- a/arch/arm/mm/cache-feroceon-l2.c
+++ b/arch/arm/mm/cache-feroceon-l2.c
@@ -76,7 +76,7 @@
 	 */
 	BUG_ON((start ^ end) >> PAGE_SHIFT);
 
-	raw_local_irq_save(flags);
+	raw_local_irq_fiq_save(flags);
 	va_start = l2_start_va(start);
 	va_end = va_start + (end - start);
 	__asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
@@ -106,7 +106,7 @@
 	 */
 	BUG_ON((start ^ end) >> PAGE_SHIFT);
 
-	raw_local_irq_save(flags);
+	raw_local_irq_fiq_save(flags);
 	va_start = l2_start_va(start);
 	va_end = va_start + (end - start);
 	__asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
@@ -128,11 +128,11 @@
  * inclusive start and end addresses.
  */
 #define CACHE_LINE_SIZE		32
-#define MAX_RANGE_SIZE		1024
+#define MAX_RANGE_SIZE		PAGE_SIZE
 
 static int l2_wt_override;
 
-static unsigned long calc_range_end(unsigned long start, unsigned long end)
+static inline unsigned long calc_range_end(unsigned long start, unsigned long end)
 {
 	unsigned long range_end;
 
@@ -239,7 +239,7 @@
 	if (cr & CR_C) {
 		unsigned long flags;
 
-		raw_local_irq_save(flags);
+		raw_local_irq_fiq_save(flags);
 		flush_cache_all();
 		set_cr(cr & ~CR_C);
 		raw_local_irq_restore(flags);
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
old mode 100644
new mode 100755
index d0d17b6..1775062
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -34,7 +34,8 @@
  * Therefore those configurations which might call adjust_pte (those
  * without CONFIG_CPU_CACHE_VIPT) cannot support split page_table_lock.
  */
-static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
+static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
+		int update, int only_shared)
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
@@ -65,7 +66,9 @@
 	 * If this page isn't present, or is already setup to
 	 * fault (ie, is old), we can safely ignore any issues.
 	 */
-	if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) {
+	if (ret &&
+	    (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask &&
+	    update) {
 		unsigned long pfn = pte_pfn(entry);
 		flush_cache_page(vma, address, pfn);
 		outer_flush_range((pfn << PAGE_SHIFT),
@@ -74,7 +77,14 @@
 		pte_val(entry) |= shared_pte_mask;
 		set_pte_at(vma->vm_mm, address, pte, entry);
 		flush_tlb_page(vma, address);
+		printk(KERN_DEBUG "Uncached vma %08x "
+			"(addr %08lx flags %08lx phy %08x) from pid %d\n",
+			(unsigned int) vma, vma->vm_start, vma->vm_flags,
+			(unsigned int) (pfn << PAGE_SHIFT),
+			current->pid);
 	}
+	if (only_shared && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask)
+		ret = 0;
 	pte_unmap(pte);
 	return ret;
 
@@ -100,6 +110,9 @@
 	unsigned long offset;
 	pgoff_t pgoff;
 	int aliases = 0;
+#ifdef CONFIG_ARM_ARMV5_L2_CACHE_COHERENCY_FIX
+	int run;
+#endif
 
 	pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
 
@@ -109,6 +122,39 @@
 	 * cache coherency.
 	 */
 	flush_dcache_mmap_lock(mapping);
+#ifdef CONFIG_ARM_ARMV5_L2_CACHE_COHERENCY_FIX
+	/*
+	 * In the first run we just check if we have to make some
+	 * address space uncacheable because of L1 VIVT. In the second
+	 * we check if there is an uncached map in other processes.  If
+	 * one of the previous condition is true we proceed to make
+	 * *all* (both in current process VMA and that of others) of
+	 * them so. This should solve both cases of multiple shared
+	 * memories attached in the same process but not impact the
+	 * common case of just one mapping per process.
+	 */
+	for (run = 0; run < 3; run++) {
+		vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap,
+				pgoff, pgoff) {
+			if ((mpnt->vm_mm != mm || mpnt == vma) && run == 0)
+				continue;
+			if (!(mpnt->vm_flags & VM_MAYSHARE) &&
+				run != 2) /* update all mappings */
+				continue;
+			offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
+			aliases += adjust_pte(mpnt, mpnt->vm_start + offset,
+					/* update only on the last run */
+					run == 2,
+					/*
+					 * on the second run
+					 * catch shared in other procs
+					 */
+					run == 1);
+		}
+		if (aliases == 0 && run == 1)
+			break;
+	}
+#else
 	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		/*
 		 * If this VMA is not in our MM, we can ignore it.
@@ -120,11 +166,12 @@
 		if (!(mpnt->vm_flags & VM_MAYSHARE))
 			continue;
 		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
-		aliases += adjust_pte(mpnt, mpnt->vm_start + offset);
+		aliases += adjust_pte(mpnt, mpnt->vm_start + offset, 1, 0);
 	}
+#endif
 	flush_dcache_mmap_unlock(mapping);
 	if (aliases)
-		adjust_pte(vma, addr);
+		adjust_pte(vma, addr, 1, 0);
 	else
 		flush_cache_page(vma, addr, pfn);
 }
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
old mode 100644
new mode 100755
index 7f294f3..78867c2
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -209,6 +209,13 @@
 			__flush_dcache_aliases(mapping, page);
 		else if (mapping)
 			__flush_icache_all();
+#ifdef CONFIG_ARM_ARMV5_L2_CACHE_COHERENCY_FIX
+		{
+			unsigned long pfn = page_to_pfn(page);
+			outer_flush_range((pfn << PAGE_SHIFT),
+				(pfn << PAGE_SHIFT) + PAGE_SIZE);
+		}
+#endif
 	}
 }
 EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
old mode 100644
new mode 100755
index d0d7795..0c3e2ae
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -29,6 +29,10 @@
 #include <asm/ptrace.h>
 #include "proc-macros.S"
 
+#ifdef CONFIG_ARCH_FEROCEON
+#include <mach/kw_macro.h>
+#endif
+
 /*
  * This is the maximum size of an area which will be invalidated
  * using the single invalidate entry instructions.  Anything larger
@@ -54,6 +58,40 @@
 	.word	__cache_params_loc
 
 /*
+ *      mv_l2_inv_range(start, end)
+ *
+ *      Invalidate (discard) the specified virtual address range on L2.
+ *      May not write back any entries.  If 'start' or 'end'
+ *      are not cache line aligned, those lines must be written
+ *      back.
+ *
+ *      - start - virtual start address
+ *      - end   - virtual end address
+ *
+ */
+#ifdef CONFIG_CACHE_FEROCEON_L2
+ENTRY(mv_l2_inv_range)
+#ifndef CONFIG_CPU_L2_DCACHE_WRITETHROUGH
+        tst     r0, #CACHE_DLINESIZE - 1
+        mcrne   p15, 1, r0, c15, c9, 1          @ clean L2 entry
+        tst     r1, #CACHE_DLINESIZE - 1
+        mcrne   p15, 1, r1, c15, c9, 1          @ clean L2 entry
+        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+#endif
+        cmp     r1, r0
+        subne   r1, r1, #1                      @ Prevent cleaning of top address
+                                                @ cache line when top is cache line aligned
+        mrs     r2, cpsr
+        orr     r3, r2, #PSR_F_BIT | PSR_I_BIT
+        msr     cpsr_c, r3                      @ Disable interrupts
+        mcr     p15, 1, r0, c15, c11, 4         @ L2 invalidation zone start addr
+        mcr     p15, 1, r1, c15, c11, 5         @ L2 invalidation zone end addr and
+                                                @ invalidate procedure trigger
+        msr     cpsr_c, r2                      @ Restore interrupts
+        mov     pc, lr
+#endif
+
+/*
  * cpu_feroceon_proc_init()
  */
 ENTRY(cpu_feroceon_proc_init)
@@ -123,9 +161,16 @@
  */
 	.align	5
 ENTRY(cpu_feroceon_do_idle)
+#ifdef CONFIG_ARCH_FEROCEON
+        ldr     r0, support_wait_for_interrupt_address /* this variable set in core.c*/
+        ldr     r0, [r0]
+        cmp     r0, #1    /* check if the device doesn't support wait for interrupt*/
+        bne     1f        /* if yes, then go out*/
+#endif
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
+1:
 	mov	pc, lr
 
 /*
@@ -249,7 +294,7 @@
 ENTRY(feroceon_range_flush_kern_dcache_page)
 	mrs	r2, cpsr
 	add	r1, r0, #PAGE_SZ - CACHE_DLINESIZE	@ top addr is inclusive
-	orr	r3, r2, #PSR_I_BIT
+	orr	r3, r2, #PSR_I_BIT | PSR_F_BIT
 	msr	cpsr_c, r3			@ disable interrupts
 	mcr	p15, 5, r0, c15, c15, 0		@ D clean/inv range start
 	mcr	p15, 5, r1, c15, c15, 1		@ D clean/inv range top
@@ -295,7 +340,7 @@
 	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
 	cmp	r1, r0
 	subne	r1, r1, #1			@ top address is inclusive
-	orr	r3, r2, #PSR_I_BIT
+	orr	r3, r2, #PSR_I_BIT | PSR_F_BIT
 	msr	cpsr_c, r3			@ disable interrupts
 	mcr	p15, 5, r0, c15, c14, 0		@ D inv range start
 	mcr	p15, 5, r1, c15, c14, 1		@ D inv range top
@@ -327,7 +372,7 @@
 	mrs	r2, cpsr
 	cmp	r1, r0
 	subne	r1, r1, #1			@ top address is inclusive
-	orr	r3, r2, #PSR_I_BIT
+	orr	r3, r2, #PSR_I_BIT | PSR_F_BIT
 	msr	cpsr_c, r3			@ disable interrupts
 	mcr	p15, 5, r0, c15, c13, 0		@ D clean range start
 	mcr	p15, 5, r1, c15, c13, 1		@ D clean range top
@@ -358,7 +403,7 @@
 	mrs	r2, cpsr
 	cmp	r1, r0
 	subne	r1, r1, #1			@ top address is inclusive
-	orr	r3, r2, #PSR_I_BIT
+	orr	r3, r2, #PSR_I_BIT | PSR_F_BIT
 	msr	cpsr_c, r3			@ disable interrupts
 	mcr	p15, 5, r0, c15, c15, 0		@ D clean/inv range start
 	mcr	p15, 5, r1, c15, c15, 1		@ D clean/inv range top
diff --git a/arch/arm/plat-feroceon/Kconfig b/arch/arm/plat-feroceon/Kconfig
new file mode 100755
index 0000000..27399df
--- /dev/null
+++ b/arch/arm/plat-feroceon/Kconfig
@@ -0,0 +1,458 @@
+if ARCH_FEROCEON
+
+menu "Feroceon SoC options"
+	depends on ARCH_FEROCEON
+
+#since the Kconfig parser dispatch all source commands, we call the machines Kconfigs from here and
+#not vice versa because otherwise the plat-feroceon Kconfig will be dispatched twice.     
+if ARCH_FEROCEON_KW2
+source "arch/arm/mach-feroceon-kw2/Kconfig"
+endif
+
+config JTAG_DEBUG
+        bool "Enable JTAG by disable \"wait for interrupt\"."
+	depends on MV88F6500 || MV88F6281 || MV78XX0
+        default n
+        ---help---
+           Enable the JTAG debugger taking over the CPU by disabling "wait for interrupt" idle loop."
+
+
+menu "Feroceon SoC Included Features"
+
+config MV_NAND_SUPPORT
+	bool
+	default n
+
+config MV_INCLUDE_PEX
+	bool "PCI Express Support"
+	depends on PCI && MV88F6500 || MV88F6281 || MV78XX0
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_USB
+	bool "USB Support"
+	depends on MV88F6500 || MV88F6281 || MV78XX0
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_XOR
+	bool "XOR Support"
+	depends on MV88F6500 || MV88F6281 || MV78XX0 
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_CESA
+	bool "CESA Support"
+	depends on MV88F6500 || MV88F6082 || MV88F6183 || MV88F6281 || MV78XX0
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_NFC
+        bool "Nand Flash Controller Support"
+	select MV_NAND_SUPPORT
+        depends on MV88F6500
+        default n
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_LEGACY_NAND
+	bool "Legacy NAND Support"
+	select MV_NAND_SUPPORT
+	depends on MV88F6500 || MV88F6281 || MV78XX0
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_INTEG_SATA
+	bool "Integrated SATA Support"
+	depends on MV88F6500 || MV88F6281 || MV78XX0
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_TDM
+	bool "Integrated TDM Support"
+	depends on MV88F6500 || MV88F6281 || MV78XX0 
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_GIG_ETH
+	bool "Giga Ethernet Support"
+	depends on MV88F6500 || MV88F6281 || MV78XX0
+	default y
+
+config MV_INCLUDE_SPI
+	bool "SPI Support"
+	depends on MV88F6500 || MV88F6281 || (MV78XX0 && !MV78XX0_Z0)
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_SDIO
+	bool "SDIO Support"
+	depends on MV88F6500 || MV88F6281
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_TS
+	bool "TSU Support"
+	depends on MV88F6500 || MV88F6281
+	default n
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_PON
+	bool "PON Support"
+	depends on MV88F6500
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_TPM
+	bool "TPM Support"
+	depends on MV88F6500
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_CUST
+	bool "Customer driver Support"
+	depends on MV88F6500
+	default y
+        ---help---
+        Please don't change this configs unless you know what you are doing.
+
+config MV_INCLUDE_SWITCH
+        bool "Ethernet Switch Support"
+        depends on MV88F6500 || MV88F6281 || MV78XX0
+        default y
+
+endmenu
+
+config MV_GPP_MAX_PINS
+	int
+	default 32 if MV78XX0
+	default 64 if MV88F6281
+	default 70 if MV88F6500
+
+	
+config MV_DCACHE_SIZE
+	hex
+	default 0x8000 if MV78XX0
+	default 0x4000 if MV88F6500 || MV88F6281
+
+config MV_ICACHE_SIZE
+	hex
+	default 0x8000 if MV78XX0
+	default 0x4000 if MV88F6500 || MV88F6281
+	          
+menu "Feroceon SoC MTD support"
+
+config MV_FLASH_CTRL
+	bool
+	default n
+
+config MV_INCLUDE_NORFLASH_MTD
+    bool "Marvell support for MTD NOR flash device"
+    select MV_FLASH_CTRL
+    depends on MTD_CFI
+    default n
+
+config MV_INCLUDE_SFLASH_MTD
+    bool "Marvell support for MTD SPI flash device"
+    select MV_FLASH_CTRL
+    depends on MV_INCLUDE_SPI
+    default y
+
+config MTD_NAND_LNC
+	bool "Marvell support for legacy NAND controller"
+	depends on MV_INCLUDE_LEGACY_NAND
+	
+config MTD_NAND_LNC_RS_ECC
+	bool "Support Reed-Solomon 4-bit ECC algorithm"
+	depends on MTD_NAND_LNC
+	default y
+	---help---
+	Choose this option to support Reed-Solomon 4-bit ECC algorithm.
+	Note this option also requires support by low-level boot loader.
+
+config MTD_NAND_LNC_8BYTE_READ
+	bool "Support NAND 8 Byte Read burst algorithm"
+	depends on MTD_NAND_LNC
+	---help---
+	Choose this option to support NAND 8 Byte Read burst algorithm.
+
+config MTD_NAND_NFC
+        tristate "MTD driver for the MV88F6500 Nand Flash Controller"
+        depends on MV_INCLUDE_NFC
+        help
+          This enables the driver for the NAND flash controller found in
+          the Marvell MV88F6500 SoC devices.
+
+config MTD_NAND_NFC_GANG_SUPPORT
+        bool "NAND Ganged mode support for the NFC"
+        depends on MTD_NAND_NFC
+        default y
+        help
+          This option enables the support for 2x8bit ganged mode in
+          Marvell's NFC HAL driver and the MTD stack.
+
+config MTD_NAND_NFC_MLC_SUPPORT
+        bool "NAND MLC devices support for the NFC"
+        depends on MTD_NAND_NFC
+        default y
+        help
+          This option allows support for Nand devices with non-standard
+          page/oob layout. These devices are detected incorrectly with
+          standard autodetection mechanism based on the READ_ID command.
+
+config MTD_NAND_NFC_INIT_RESET
+        bool "NAND Enable Reset on Initialization"
+        depends on MTD_NAND_NFC
+        default n
+        help
+          This option forces NAND reset command on initialization. This
+          is required by certain NAND vendors (Micron).
+
+endmenu
+
+choice
+	prompt "SoC USB Mode"
+	depends on MV_INCLUDE_USB && !UBOOT_STRUCT
+	default MV_USB_HOST
+
+config MV_USB_HOST
+	bool "Support for USB Host"
+	---help---
+	Choosing this option will configure on chip USB Controller to work in Host mode
+
+config MV_USB_DEVICE
+	bool "Support for USB Device"
+	---help---
+	Choosing this option will configure on chip USB Controller to work in Device mode
+endchoice
+
+
+config ARCH_SUPPORTS_BIG_ENDIAN
+	bool
+	default y
+
+config USE_DSP
+	bool "Use pld/ldrd/strd arm DSP instructions"
+	default n
+
+choice
+	prompt "Protect from speculative instruction prefetch"
+	depends on CACHE_FEROCEON_L2
+	default MV_SP_I_FTCH_DB_INV
+
+config MV_SP_I_FTCH_DB_INV
+	bool "Double invalidate for DMA buffers"
+	---help---
+	Choosing this option will add L2 invalidate for DMA recieved buffers before processing it,
+	This is done through the pci_unmap_sg/page/single APIs.
+
+config MV_SP_I_FTCH_LCK_L2_ICACHE
+	bool "Lock L2 I-cache"
+	---help---
+	Choosing this option will lock L2 Icache.
+
+config MV_SP_I_FTCH_NONE
+	bool "Ignore"
+
+endchoice
+
+config MV_INTERNAL_REGS_SELECTIVE_MAPPING
+	bool "Internal registers selective mapping"
+	default n
+	---help---
+	Choosing this option enables selective address mapping for each unit,
+        in the internal registers address space.
+
+
+config  FEROCEON_PROC
+	bool "Support for MV-shell proc file system"
+	depends on PROC_FS
+	---help---	
+	  Choosing this option will enable you to use the MV-shell through the Proc
+	  File system.
+	  The MV-shell is a debug utility which can be run from the shell.
+
+config  UBOOT_STRUCT
+	bool "Use UBoot Marvell tag structure"
+	---help---
+	  Choosing this option will cause the linux to extract the Tclk, Sysclk and
+	  the uboot version from the Tag list passed by the uboot.
+
+config  MV_DBG_TRACE
+	bool "Enable tracing utility"
+	default n
+	---help---
+	  Choosing this debug option will cause some kernel modules to log operations into
+	  a cyclic buffer and dump them on failures. Enabling this feature decreases performance.
+
+config  MV_REAL_TIME
+	bool "Real Time softirq support"
+	default n
+	---help---
+	Choosing this option will give more CPU time for user space processes
+
+config  MV_CPU_PERF_CNTRS
+        bool "CPU Performance counters support"
+        default n
+        ---help---
+        Choosing this option will enable you to use CPU Performance counters
+
+config  MV_CPU_L2_PERF_CNTRS
+        bool "CPU L2 Performance counters support"
+        default n
+        ---help---
+        Choosing this option will enable you to use CPU L2 Performance counters
+
+menu "Power-Management options"
+
+config	MV_PMU_PROC
+	bool "Support procfs control on Power-Management features"
+	depends on PROC_FS
+	---help---	
+	  Choose this option to enable control over the power-management features through
+	  the proc file-system.
+
+choice 
+        prompt "Idle Mode"
+	depends on CPU_IDLE
+        default MV_PM_IDLE_WFI_SR
+
+config	MV_PM_IDLE_WFI_SR
+	bool "Support WFI and DRAM SR for CPU-Idle driver"
+	---help---
+	  Choosing this option will cause the CPU-Idle driver to enter WFI w/ DRAM Self-Refresh
+	  when system is idle.
+
+config  MV_PM_IDLE_DEEPIDLE_SR
+	bool "Support Deep-Idle and DRAM SR for CPU-Idle driver"
+	depends on MV_CESA_TOOL 
+	---help---
+	  Choosing this option will cause the CPU-Idle driver to enter Deep-Idle w/ DRAM Self-Refresh
+	  when system is idle.
+endchoice
+endmenu
+
+
+menu "Soc DMA accelerations"
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/Kconfig
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/Kconfig
+
+endmenu
+
+
+menu "SoC Networking support"
+depends on MV_INCLUDE_GIG_ETH
+
+config MV_ETHERNET
+        bool "Networking support"
+	depends on MV_INCLUDE_GIG_ETH
+	default y
+        ---help---
+        Choose this option to support Marvell Gigabit Ethernet Controller 
+
+if MV_ETHERNET
+
+choice 
+        prompt "GbE Mode"
+        depends on MV_INCLUDE_GIG_ETH 
+        default MV_ETH_LEGACY
+
+config MV_ETH_LEGACY
+        bool "Legacy mode "
+        ---help---
+
+config MV_ETH_NETA
+        bool "Acceleration mode "
+	depends on ARCH_FEROCEON_KW2
+        ---help---
+
+endchoice
+
+
+if MV_ETH_LEGACY
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/Kconfig
+endif
+
+if MV_ETH_NETA
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/Kconfig
+endif
+
+endif # MV_ETHERNET
+endmenu # "SoC Networking support"
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/Kconfig
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Kconfig
+
+
+#source arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/Kconfig
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/Kconfig
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Kconfig
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/Kconfig
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/Kconfig
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/Kconfig
+
+
+config  SCSI_MVSATA
+	tristate "Support for Marvell Sata Adapters"
+	depends on ( MV_INCLUDE_INTEG_SATA && SCSI ) || ( PCI && SCSI )
+	---help---
+	  Choosing this option will enable you to use the Marvell Sata
+	  adapters support with emulation as SCSI adapters.
+	  Note that the kernel scsi subsystem must be chosen too.
+
+source arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/Kconfig
+
+config PCIE_VIRTUAL_BRIDGE_SUPPORT
+        bool "Enable virtual bridge on PCIe"
+        depends on PCI
+        ---help---
+        Enable virtual bridge module to support PCIe switches
+
+config MV_UART_POLLING_MODE
+        bool "Enable Polling mode for UART driver"
+        depends on ARCH_FEROCEON_KW2
+	default y
+        ---help---
+        Configure UART driver to work in polling mode.
+
+config MV_PRINTK_SLICE_SUPPORT
+        bool "Support printk buffer slicing"
+        depends on ARCH_FEROCEON_KW2 && PRINTK
+	default n
+        ---help---
+        Enable printk buffer chunks slicing to reduce interrupts locking periods.
+
+config MV_PRINTK_CHUNK_SIZE
+        int "Support printk buffer slicing"
+        depends on MV_PRINTK_SLICE_SUPPORT
+	default 16
+        ---help---
+        Select printk buffer chunk granularity.
+
+
+endmenu
+
+
+endif
+
+
diff --git a/arch/arm/plat-feroceon/Makefile b/arch/arm/plat-feroceon/Makefile
new file mode 100755
index 0000000..5b76349
--- /dev/null
+++ b/arch/arm/plat-feroceon/Makefile
@@ -0,0 +1,6 @@
+include 	  $(srctree)/$(MACHINE)/config/mvRules.mk
+
+# This will never compile, because DUMMY will never by defined.
+obj-$(DUMMY)   				:= dummy.o
+obj-$(CONFIG_PCI_MSI)			+= msi.o
+
diff --git a/arch/arm/plat-feroceon/common/mv802_3.h b/arch/arm/plat-feroceon/common/mv802_3.h
new file mode 100755
index 0000000..5723310
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mv802_3.h
@@ -0,0 +1,269 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmv802_3h
+#define __INCmv802_3h
+
+/* includes */
+#include "mvTypes.h"
+
+/* Defines */
+#define MV_MAX_ETH_DATA     1500
+
+/* 802.3 types */
+#define MV_IP_TYPE                  0x0800
+#define MV_IP_ARP_TYPE              0x0806
+#define MV_IP6_TYPE                 0x86dd
+#define MV_APPLE_TALK_ARP_TYPE      0x80F3
+#define MV_NOVELL_IPX_TYPE          0x8137
+#define MV_EAPOL_TYPE               0x888e
+#define MV_VLAN_TYPE                0x8100
+#define MV_PPPOE_TYPE               0x8864
+
+/* PPPoE protocol type */
+#define MV_IP_PPP  0x0021
+#define MV_IP6_PPP 0x0057
+/* Encapsulation header for RFC1042 and Ethernet_tunnel */
+
+#define MV_RFC1042_SNAP_HEADER     {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}
+
+#define MV_ETH_SNAP_LSB             0xF8
+
+#define	MV_MAC_ADDR_SIZE	(6)
+#define MV_MAC_STR_SIZE		(20)
+#define MV_LLC_HLEN		(6)
+#define MV_VLAN_HLEN		(4)
+#define MV_ETH_TYPE_LEN     (2)
+#define MV_ETH_ALEN         (MV_MAC_ADDR_SIZE + MV_MAC_ADDR_SIZE + MV_ETH_TYPE_LEN)
+#define MV_PPP_HDR_SIZE     (2)
+#define MV_PPPOE_HDR_SIZE   (8)	/* PPP header is 2, PPPoE header is 6 */
+
+/* This macro checks for a multicast mac address    */
+#define MV_IS_MULTICAST_MAC(mac)  (((mac)[0] & 0x1) == 1)
+
+/* IPv4 */
+#define MV_INET 2
+/* IPv6 */
+#define MV_INET6 10
+
+#define MV_MAX_IPV4_ADDR_SIZE	(4)
+#define MV_MAX_L3_ADDR_SIZE	(16)	/* IPv4: 4, IPv6: 16 */
+
+/* This macro checks for an broadcast mac address     */
+#define MV_IS_BROADCAST_MAC(mac)            \
+	(((mac)[0] == 0xFF) &&       \
+	 ((mac)[1] == 0xFF) &&       \
+	 ((mac)[2] == 0xFF) &&       \
+	 ((mac)[3] == 0xFF) &&       \
+	 ((mac)[4] == 0xFF) &&       \
+	 ((mac)[5] == 0xFF))
+
+/* Typedefs */
+typedef struct {
+	MV_U8 pDA[MV_MAC_ADDR_SIZE];
+	MV_U8 pSA[MV_MAC_ADDR_SIZE];
+	MV_U16 typeOrLen;
+
+} MV_802_3_HEADER;
+
+/* 8 bytes - PPPoE header + PPP header */
+typedef struct {
+	MV_U8 version;
+	MV_U8 code;
+	MV_U16 session;
+	MV_U16 len;
+	MV_U16 proto;
+} PPPoE_HEADER;
+
+enum {
+	MV_IP_PROTO_NULL = 0,	/* Dummy protocol for TCP               */
+	MV_IP_PROTO_ICMP = 1,	/* Internet Control Message Protocol    */
+	MV_IP_PROTO_IGMP = 2,	/* Internet Group Management Protocol   */
+	MV_IP_PROTO_IPIP = 4,	/* IPIP tunnels (older KA9Q tunnels use 94) */
+	MV_IP_PROTO_TCP = 6,	/* Transmission Control Protocol        */
+	MV_IP_PROTO_EGP = 8,	/* Exterior Gateway Protocol            */
+	MV_IP_PROTO_PUP = 12,	/* PUP protocol                         */
+	MV_IP_PROTO_UDP = 17,	/* User Datagram Protocol               */
+	MV_IP_PROTO_IDP = 22,	/* XNS IDP protocol                     */
+	MV_IP_PROTO_DCCP = 33,	/* Datagram Congestion Control Protocol */
+	MV_IP_PROTO_IPV6 = 41,	/* IPv6-in-IPv4 tunnelling              */
+	MV_IP_PROTO_RSVP = 46,	/* RSVP protocol                        */
+	MV_IP_PROTO_GRE = 47,	/* Cisco GRE tunnels (rfc 1701,1702)    */
+	MV_IP_PROTO_ESP = 50,	/* Encapsulation Security Payload protocol */
+	MV_IP_PROTO_AH = 51,	/* Authentication Header protocol       */
+	MV_IP_PROTO_BEETPH = 94,	/* IP option pseudo header for BEET     */
+	MV_IP_PROTO_PIM = 103,
+	MV_IP_PROTO_COMP = 108,	/* Compression Header protocol          */
+	MV_IP_PROTO_ZERO_HOP = 114,	/* Any 0 hop protocol (IANA)            */
+	MV_IP_PROTO_SCTP = 132,	/* Stream Control Transport Protocol    */
+	MV_IP_PROTO_UDPLITE = 136,	/* UDP-Lite (RFC 3828)                  */
+
+	MV_IP_PROTO_RAW = 255,	/* Raw IP packets                       */
+	MV_IP_PROTO_MAX
+};
+
+#define MV_IP4_FRAG_OFFSET_MASK 0x1FFF
+#define MV_IP4_DF_FLAG_MASK     0x4000
+#define MV_IP4_MF_FLAG_MASK     0x2000
+
+
+typedef struct {
+	MV_U8 version;
+	MV_U8 tos;
+	MV_U16 totalLength;
+	MV_U16 identifier;
+	MV_U16 fragmentCtrl;
+	MV_U8 ttl;
+	MV_U8 protocol;
+	MV_U16 checksum;
+	MV_U32 srcIP;
+	MV_U32 dstIP;
+
+} MV_IP_HEADER;
+
+typedef struct {
+	MV_U32 verClassFlow;
+	MV_U16 payloadLength;
+	MV_U8 protocol;
+	MV_U8 hoplimit;
+	MV_U8 srcAddr[16];
+	MV_U8 dstAddr[16];
+
+} MV_IP6_HEADER;
+
+typedef struct {
+	int    family;
+	int    ipOffset;
+	int    ipHdrLen;
+	MV_U16 ipLen;
+	MV_U8  ipProto;
+	MV_U8  reserved;
+	union {
+		char          *l3;
+		MV_IP_HEADER  *ip4;
+		MV_IP6_HEADER *ip6;
+	} ip_hdr;
+} MV_IP_HEADER_INFO;
+
+typedef struct {
+	MV_U8  protocol;
+	MV_U8  length;
+	MV_U16 reserverd;
+	MV_U32 spi;
+	MV_U32 seqNum;
+} MV_AH_HEADER;
+
+
+typedef struct {
+	MV_U32 spi;
+	MV_U32 seqNum;
+} MV_ESP_HEADER;
+
+#define MV_ICMP_ECHOREPLY          0	/* Echo Reply                   */
+#define MV_ICMP_DEST_UNREACH       3	/* Destination Unreachable      */
+#define MV_ICMP_SOURCE_QUENCH      4	/* Source Quench                */
+#define MV_ICMP_REDIRECT           5	/* Redirect (change route)      */
+#define MV_ICMP_ECHO               8	/* Echo Request                 */
+#define MV_ICMP_TIME_EXCEEDED      11	/* Time Exceeded                */
+#define MV_ICMP_PARAMETERPROB      12	/* Parameter Problem            */
+#define MV_ICMP_TIMESTAMP          13	/* Timestamp Request            */
+#define MV_ICMP_TIMESTAMPREPLY     14	/* Timestamp Reply              */
+#define MV_ICMP_INFO_REQUEST       15	/* Information Request          */
+#define MV_ICMP_INFO_REPLY         16	/* Information Reply            */
+#define MV_ICMP_ADDRESS            17	/* Address Mask Request         */
+#define MV_ICMP_ADDRESSREPLY       18	/* Address Mask Reply           */
+
+typedef struct {
+	MV_U8 type;
+	MV_U8 code;
+	MV_U16 checksum;
+	MV_U16 id;
+	MV_U16 sequence;
+
+} MV_ICMP_ECHO_HEADER;
+
+#define MV_TCP_FLAG_FIN		(1 << 0)
+#define MV_TCP_FLAG_RST		(1 << 2)
+
+typedef struct {
+	MV_U16 source;
+	MV_U16 dest;
+	MV_U32 seq;
+	MV_U32 ack_seq;
+	MV_U16 flags;
+	MV_U16 window;
+	MV_U16 chksum;
+	MV_U16 urg_offset;
+
+} MV_TCP_HEADER;
+
+typedef struct {
+	MV_U16 source;
+	MV_U16 dest;
+	MV_U16 len;
+	MV_U16 check;
+
+} MV_UDP_HEADER;
+
+#endif /* __INCmv802_3h */
diff --git a/arch/arm/plat-feroceon/common/mvCommon.c b/arch/arm/plat-feroceon/common/mvCommon.c
new file mode 100755
index 0000000..22eb180
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvCommon.c
@@ -0,0 +1,355 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+
+int mvCharToHex(char ch)
+{
+	if ((ch >= '0') && (ch <= '9'))
+		return (ch - '0');
+
+	if ((ch >= 'a') && (ch <= 'f'))
+		return (ch - 'a') + 10;
+
+	if ((ch >= 'A') && (ch <= 'F'))
+		return (ch - 'A') + 10;
+
+	return -1;
+}
+
+int mvCharToDigit(char ch)
+{
+	if ((ch >= '0') && (ch <= '9'))
+		return (ch - '0');
+
+	return -1;
+}
+
+/*******************************************************************************
+* mvMacStrToHex - Convert MAC format string to hex.
+*
+* DESCRIPTION:
+*		This function convert MAC format string to hex.
+*
+* INPUT:
+*       macStr - MAC address string. Fornat of address string is
+*                uu:vv:ww:xx:yy:zz, where ":" can be any delimiter.
+*
+* OUTPUT:
+*       macHex - MAC in hex format.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_STATUS mvMacStrToHex(const char *macStr, MV_U8 *macHex)
+{
+	int i;
+	char tmp[3];
+
+	for (i = 0; i < MV_MAC_ADDR_SIZE; i++) {
+		tmp[0] = macStr[(i * 3) + 0];
+		tmp[1] = macStr[(i * 3) + 1];
+		tmp[2] = '\0';
+		macHex[i] = (MV_U8) (strtol(tmp, NULL, 16));
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvMacHexToStr - Convert MAC in hex format to string format.
+*
+* DESCRIPTION:
+*		This function convert MAC in hex format to string format.
+*
+* INPUT:
+*       macHex - MAC in hex format.
+*
+* OUTPUT:
+*       macStr - MAC address string. String format is uu:vv:ww:xx:yy:zz.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_STATUS mvMacHexToStr(MV_U8 *macHex, char *macStr)
+{
+	int i;
+
+	for (i = 0; i < MV_MAC_ADDR_SIZE; i++)
+		mvOsSPrintf(&macStr[i * 3], "%02x:", macHex[i]);
+
+	macStr[(i * 3) - 1] = '\0';
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSizePrint - Print the given size with size unit description.
+*
+* DESCRIPTION:
+*		This function print the given size with size unit description.
+*       FOr example when size paramter is 0x180000, the function prints:
+*       "size 1MB+500KB"
+*
+* INPUT:
+*       size - Size in bytes.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvSizePrint(MV_U32 size)
+{
+	mvOsOutput("size ");
+
+	if (size >= _1G) {
+		mvOsOutput("%3dGB ", size / _1G);
+		size %= _1G;
+		if (size)
+			mvOsOutput("+");
+	}
+	if (size >= _1M) {
+		mvOsOutput("%3dMB ", size / _1M);
+		size %= _1M;
+		if (size)
+			mvOsOutput("+");
+	}
+	if (size >= _1K) {
+		mvOsOutput("%3dKB ", size / _1K);
+		size %= _1K;
+		if (size)
+			mvOsOutput("+");
+	}
+	if (size > 0)
+		mvOsOutput("%3dB ", size);
+
+}
+
+/*******************************************************************************
+* mvHexToBin - Convert hex to binary
+*
+* DESCRIPTION:
+*		This function Convert hex to binary.
+*
+* INPUT:
+*       pHexStr - hex buffer pointer.
+*       size    - Size to convert.
+*
+* OUTPUT:
+*       pBin - Binary buffer pointer.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvHexToBin(const char *pHexStr, MV_U8 *pBin, int size)
+{
+	int j, i;
+	char tmp[3];
+	MV_U8 byte;
+
+	for (j = 0, i = 0; j < size; j++, i += 2) {
+		tmp[0] = pHexStr[i];
+		tmp[1] = pHexStr[i + 1];
+		tmp[2] = '\0';
+		byte = (MV_U8) (strtol(tmp, NULL, 16) & 0xFF);
+		pBin[j] = byte;
+	}
+}
+
+void mvAsciiToHex(const char *asciiStr, char *hexStr)
+{
+	int i = 0;
+
+	while (asciiStr[i] != 0) {
+		mvOsSPrintf(&hexStr[i * 2], "%02x", asciiStr[i]);
+		i++;
+	}
+	hexStr[i * 2] = 0;
+}
+
+void mvBinToHex(const MV_U8 *bin, char *hexStr, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		mvOsSPrintf(&hexStr[i * 2], "%02x", bin[i]);
+
+	hexStr[i * 2] = '\0';
+}
+
+void mvBinToAscii(const MV_U8 *bin, char *asciiStr, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		mvOsSPrintf(&asciiStr[i * 2], "%c", bin[i]);
+
+	asciiStr[i * 2] = '\0';
+}
+
+/*******************************************************************************
+* mvLog2 -
+*
+* DESCRIPTION:
+*	Calculate the Log2 of a given number.
+*
+* INPUT:
+*       num - A number to calculate the Log2 for.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Log 2 of the input number, or 0xFFFFFFFF if input is 0.
+*
+*******************************************************************************/
+MV_U32 mvLog2(MV_U32 num)
+{
+	MV_U32 result = 0;
+	if (num == 0)
+		return 0xFFFFFFFF;
+	while (num != 1) {
+		num = num >> 1;
+		result++;
+	}
+	return result;
+}
+
+/*******************************************************************************
+* mvWinOverlapTest
+*
+* DESCRIPTION:
+*       This function checks the given two address windows for overlaping.
+*
+* INPUT:
+*       pAddrWin1 - Address window 1.
+*       pAddrWin2 - Address window 2.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if address window overlaps, MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2)
+{
+	MV_U32 winBase1, winBase2;
+	MV_U32 winTop1, winTop2;
+
+	/* check if we have overflow than 4G */
+	if (((0xffffffff - pAddrWin1->baseLow) < pAddrWin1->size - 1) ||
+	    ((0xffffffff - pAddrWin2->baseLow) < pAddrWin2->size - 1)) {
+		return MV_TRUE;
+	}
+
+	winBase1 = pAddrWin1->baseLow;
+	winBase2 = pAddrWin2->baseLow;
+	winTop1 = winBase1 + pAddrWin1->size - 1;
+	winTop2 = winBase2 + pAddrWin2->size - 1;
+
+	if (((winBase1 <= winTop2) && (winTop2 <= winTop1)) || ((winBase1 <= winBase2) && (winBase2 <= winTop1)))
+		return MV_TRUE;
+	else
+		return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvWinWithinWinTest
+*
+* DESCRIPTION:
+*       This function checks the given win1 boundries is within win2 boundries.
+*
+* INPUT:
+*       pAddrWin1 - Address window 1.
+*       pAddrWin2 - Address window 2.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if found win1 inside win2, MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2)
+{
+	MV_U32 winBase1, winBase2;
+	MV_U32 winTop1, winTop2;
+
+	winBase1 = pAddrWin1->baseLow;
+	winBase2 = pAddrWin2->baseLow;
+	winTop1 = winBase1 + pAddrWin1->size - 1;
+	winTop2 = winBase2 + pAddrWin2->size - 1;
+
+	if (((winBase1 >= winBase2) && (winBase1 <= winTop2)) || ((winTop1 >= winBase2) && (winTop1 <= winTop2)))
+		return MV_TRUE;
+	else
+		return MV_FALSE;
+}
diff --git a/arch/arm/plat-feroceon/common/mvCommon.h b/arch/arm/plat-feroceon/common/mvCommon.h
new file mode 100755
index 0000000..1301e01
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvCommon.h
@@ -0,0 +1,397 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCommonh
+#define __INCmvCommonh
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+#include "mvTypes.h"
+#include "mvDeviceId.h"
+#ifndef MV_ASMLANGUAGE
+#include "mv802_3.h"
+#include "mvVideo.h"
+
+/* The golden ration: an arbitrary value */
+#define MV_JHASH_GOLDEN_RATIO           0x9e3779b9
+
+#define MV_JHASH_MIX(a, b, c)        \
+{                                   \
+    a -= b; a -= c; a ^= (c>>13);   \
+    b -= c; b -= a; b ^= (a<<8);    \
+    c -= a; c -= b; c ^= (b>>13);   \
+    a -= b; a -= c; a ^= (c>>12);   \
+    b -= c; b -= a; b ^= (a<<16);   \
+    c -= a; c -= b; c ^= (b>>5);    \
+    a -= b; a -= c; a ^= (c>>3);    \
+    b -= c; b -= a; b ^= (a<<10);   \
+    c -= a; c -= b; c ^= (b>>15);   \
+}
+
+static inline MV_U32 mv_jhash_3words(MV_U32 a, MV_U32 b, MV_U32 c, MV_U32 initval)
+{
+	a += MV_JHASH_GOLDEN_RATIO;
+	b += MV_JHASH_GOLDEN_RATIO;
+	c += initval;
+	MV_JHASH_MIX(a, b, c);
+
+	return c;
+}
+#endif
+
+
+/* Swap tool */
+
+/* 16bit nibble swap. For example 0x1234 -> 0x2143                          */
+#define MV_NIBBLE_SWAP_16BIT(X)        (((X&0xf) << 4) |     \
+					((X&0xf0) >> 4) |    \
+					((X&0xf00) << 4) |   \
+					((X&0xf000) >> 4))
+
+/* 32bit nibble swap. For example 0x12345678 -> 0x21436587                  */
+#define MV_NIBBLE_SWAP_32BIT(X)		(((X&0xf) << 4) |       \
+					((X&0xf0) >> 4) |      \
+					((X&0xf00) << 4) |     \
+					((X&0xf000) >> 4) |    \
+					((X&0xf0000) << 4) |   \
+					((X&0xf00000) >> 4) |  \
+					((X&0xf000000) << 4) | \
+					((X&0xf0000000) >> 4))
+
+/* 16bit byte swap. For example 0x1234->0x3412                             */
+#define MV_BYTE_SWAP_16BIT(X) ((((X)&0xff)<<8) | (((X)&0xff00)>>8))
+
+/* 32bit byte swap. For example 0x12345678->0x78563412                    */
+#define MV_BYTE_SWAP_32BIT(X)  ((((X)&0xff)<<24) |                       \
+				(((X)&0xff00)<<8) |                      \
+				(((X)&0xff0000)>>8) |                    \
+				(((X)&0xff000000)>>24))
+
+/* 64bit byte swap. For example 0x11223344.55667788 -> 0x88776655.44332211  */
+#define MV_BYTE_SWAP_64BIT(X) ((l64) ((((X)&0xffULL)<<56) |             \
+				      (((X)&0xff00ULL)<<40) |           \
+				      (((X)&0xff0000ULL)<<24) |         \
+				      (((X)&0xff000000ULL)<<8) |        \
+				      (((X)&0xff00000000ULL)>>8) |      \
+				      (((X)&0xff0000000000ULL)>>24) |   \
+				      (((X)&0xff000000000000ULL)>>40) | \
+				      (((X)&0xff00000000000000ULL)>>56)))
+
+/* Endianess macros.                                                        */
+#if defined(MV_CPU_LE)
+#define MV_16BIT_LE(X)  (X)
+#define MV_32BIT_LE(X)  (X)
+#define MV_64BIT_LE(X)  (X)
+#define MV_16BIT_BE(X)  MV_BYTE_SWAP_16BIT(X)
+#define MV_32BIT_BE(X)  MV_BYTE_SWAP_32BIT(X)
+#define MV_64BIT_BE(X)  MV_BYTE_SWAP_64BIT(X)
+#elif defined(MV_CPU_BE)
+#define MV_16BIT_LE(X)  MV_BYTE_SWAP_16BIT(X)
+#define MV_32BIT_LE(X)  MV_BYTE_SWAP_32BIT(X)
+#define MV_64BIT_LE(X)  MV_BYTE_SWAP_64BIT(X)
+#define MV_16BIT_BE(X)  (X)
+#define MV_32BIT_BE(X)  (X)
+#define MV_64BIT_BE(X)  (X)
+#else
+#error "CPU endianess isn't defined!\n"
+#endif
+
+/* Bit field definitions */
+#define NO_BIT      0x00000000
+
+/* avoid redefinition of bits */
+#ifndef BIT0
+
+#define BIT0        0x00000001
+#define BIT1        0x00000002
+#define BIT2        0x00000004
+#define BIT3        0x00000008
+#define BIT4        0x00000010
+#define BIT5        0x00000020
+#define BIT6        0x00000040
+#define BIT7        0x00000080
+#define BIT8        0x00000100
+#define BIT9        0x00000200
+#define BIT10       0x00000400
+#define BIT11       0x00000800
+#define BIT12       0x00001000
+#define BIT13       0x00002000
+#define BIT14       0x00004000
+#define BIT15       0x00008000
+#define BIT16       0x00010000
+#define BIT17       0x00020000
+#define BIT18       0x00040000
+#define BIT19       0x00080000
+#define BIT20       0x00100000
+#define BIT21       0x00200000
+#define BIT22       0x00400000
+#define BIT23       0x00800000
+#define BIT24       0x01000000
+#define BIT25       0x02000000
+#define BIT26       0x04000000
+#define BIT27       0x08000000
+#define BIT28       0x10000000
+#define BIT29       0x20000000
+#define BIT30       0x40000000
+#define BIT31       0x80000000
+
+#endif /* BIT0 */
+/* Handy sizes */
+#define _1K         0x00000400
+#define _2K         0x00000800
+#define _4K         0x00001000
+#define _8K         0x00002000
+#define _16K        0x00004000
+#define _32K        0x00008000
+#define _64K        0x00010000
+#define _128K       0x00020000
+#define _256K       0x00040000
+#define _512K       0x00080000
+
+#define _1M         0x00100000
+#define _2M         0x00200000
+#define _4M         0x00400000
+#define _8M         0x00800000
+#define _16M        0x01000000
+#define _32M        0x02000000
+#define _64M        0x04000000
+#define _128M       0x08000000
+#define _256M       0x10000000
+#define _512M       0x20000000
+
+#define _1G         0x40000000
+#define _2G         0x80000000
+
+/* Tclock and Sys clock define */
+#define _100MHz     100000000
+#define _125MHz     125000000
+#define _133MHz     133333334
+#define _150MHz     150000000
+#define _160MHz     160000000
+#define _166MHz     166666667
+#define _175MHz     175000000
+#define _178MHz     178000000
+#define _183MHz     183333334
+#define _187MHz     187000000
+#define _192MHz     192000000
+#define _194MHz     194000000
+#define _200MHz     200000000
+#define _233MHz     233333334
+#define _250MHz     250000000
+#define _266MHz     266666667
+#define _300MHz     300000000
+
+/* Supported clocks */
+#define MV_BOARD_TCLK_100MHZ	100000000
+#define MV_BOARD_TCLK_125MHZ	125000000
+#define MV_BOARD_TCLK_133MHZ	133333333
+#define MV_BOARD_TCLK_150MHZ	150000000
+#define MV_BOARD_TCLK_166MHZ	166666667
+#define MV_BOARD_TCLK_200MHZ	200000000
+#define MV_BOARD_TCLK_250MHZ	250000000
+
+#define MV_BOARD_SYSCLK_100MHZ	100000000
+#define MV_BOARD_SYSCLK_125MHZ	125000000
+#define MV_BOARD_SYSCLK_133MHZ	133333333
+#define MV_BOARD_SYSCLK_150MHZ	150000000
+#define MV_BOARD_SYSCLK_166MHZ	166666667
+#define MV_BOARD_SYSCLK_200MHZ	200000000
+#define MV_BOARD_SYSCLK_233MHZ	233333333
+#define MV_BOARD_SYSCLK_250MHZ	250000000
+#define MV_BOARD_SYSCLK_267MHZ	266666667
+#define MV_BOARD_SYSCLK_300MHZ	300000000
+#define MV_BOARD_SYSCLK_333MHZ	333333334
+#define MV_BOARD_SYSCLK_400MHZ	400000000
+
+#define MV_BOARD_REFCLK_25MHZ	 25000000
+
+/* For better address window table readability */
+#define EN			MV_TRUE
+#define DIS			MV_FALSE
+#define N_A			-1	/* Not applicable */
+
+/* Cache configuration options for memory (DRAM, SRAM, ... ) */
+
+/* Memory uncached, HW or SW cache coherency is not needed */
+#define MV_UNCACHED             0
+/* Memory cached, HW cache coherency supported in WriteThrough mode */
+#define MV_CACHE_COHER_HW_WT    1
+/* Memory cached, HW cache coherency supported in WriteBack mode */
+#define MV_CACHE_COHER_HW_WB    2
+/* Memory cached, No HW cache coherency, Cache coherency must be in SW */
+#define MV_CACHE_COHER_SW       3
+
+/* Macro for testing aligment. Positive if number is NOT aligned   */
+#define MV_IS_NOT_ALIGN(number, align)      ((number) & ((align) - 1))
+
+/* Macro for alignment up. For example, MV_ALIGN_UP(0x0330, 0x20) = 0x0340   */
+#define MV_ALIGN_UP(number, align)                                          \
+(((number) & ((align) - 1)) ? (((number) + (align)) & ~((align)-1)) : (number))
+
+/* Macro for alignment down. For example, MV_ALIGN_UP(0x0330, 0x20) = 0x0320 */
+#define MV_ALIGN_DOWN(number, align) ((number) & ~((align)-1))
+
+/* This macro returns absolute value                                        */
+#define MV_ABS(number)  (((int)(number) < 0) ? -(int)(number) : (int)(number))
+
+/* Bit fields manipulation macros                                           */
+
+/* An integer word which its 'x' bit is set                                 */
+#define MV_BIT_MASK(bitNum)         (1 << (bitNum))
+
+/* Checks wheter bit 'x' in integer word is set                             */
+#define MV_BIT_CHECK(word, bitNum)  ((word) & MV_BIT_MASK(bitNum))
+
+/* Clear (reset) bit 'x' in integer word (RMW - Read-Modify-Write)          */
+#define MV_BIT_CLEAR(word, bitNum)  ((word) &= ~(MV_BIT_MASK(bitNum)))
+
+/* Set bit 'x' in integer word (RMW)                                        */
+#define MV_BIT_SET(word, bitNum)    ((word) |= MV_BIT_MASK(bitNum))
+
+/* Invert bit 'x' in integer word (RMW)                                     */
+#define MV_BIT_INV(word, bitNum)    ((word) ^= MV_BIT_MASK(bitNum))
+
+/* Get the min between 'a' or 'b'                                           */
+#define MV_MIN(a, b)    (((a) < (b)) ? (a) : (b))
+
+/* Get the max between 'a' or 'b'                                           */
+#define MV_MAX(a, b)    (((a) < (b)) ? (b) : (a))
+
+#define mvOsDivide(num, div)	\
+({				\
+	int i = 0, rem = (num);	\
+	while (rem >= (div)) {	\
+		rem -= (div);	\
+		i++;		\
+	}			\
+	(i);			\
+})
+
+#define mvOsReminder(num, div)	\
+({				\
+	int rem = (num);	\
+	while (rem >= (div))	\
+		rem -= (div);	\
+	(rem);			\
+})
+
+#define MV_MACQUAD_FMT "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x"
+
+#define MV_MACQUAD(addr) \
+	((unsigned char *)addr)[0], \
+	((unsigned char *)addr)[1], \
+	((unsigned char *)addr)[2], \
+	((unsigned char *)addr)[3], \
+	((unsigned char *)addr)[4], \
+	((unsigned char *)addr)[5]
+
+#define MV_IPQUAD_FMT         "%u.%u.%u.%u"
+#define MV_IPQUAD(ip)         ip[0], ip[1], ip[2], ip[3]
+
+#define MV_IP_QUAD(ipAddr)    ((ipAddr >> 24) & 0xFF), ((ipAddr >> 16) & 0xFF), \
+				((ipAddr >> 8) & 0xFF), ((ipAddr >> 0) & 0xFF)
+
+#define MV_IP6_FMT		"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+#define MV_IP6_ARG(L3)		L3[0], L3[1], L3[2], L3[3],	\
+				L3[4], L3[5], L3[6], L3[7],	\
+				L3[8], L3[9], L3[10], L3[11],	\
+				L3[12], L3[13], L3[14], L3[15]
+
+#define MV_IS_POWER_OF_2(num) ((num != 0) && ((num & (num - 1)) == 0))
+
+#define MV_GET_BIT(word, bitNum) (((word) & (1 << (bitNum))) >> (bitNum))
+
+#define MV_SET_BIT(word, bitNum, bitVal) (((word) & ~(1 << (bitNum))) | (bitVal << bitNum))
+
+#define MV_ARRAY_SIZE(a)                    ((sizeof(a)) / (sizeof(a[0])))
+
+#ifndef MV_ASMLANGUAGE
+/* mvCommon API list */
+
+int mvCharToHex(char ch);
+int mvCharToDigit(char ch);
+
+MV_VOID mvHexToBin(const char *pHexStr, MV_U8 *pBin, int size);
+void mvAsciiToHex(const char *asciiStr, char *hexStr);
+void mvBinToHex(const MV_U8 *bin, char *hexStr, int size);
+void mvBinToAscii(const MV_U8 *bin, char *asciiStr, int size);
+
+MV_STATUS mvMacStrToHex(const char *macStr, MV_U8 *macHex);
+MV_STATUS mvMacHexToStr(MV_U8 *macHex, char *macStr);
+void mvSizePrint(MV_U32);
+
+MV_U32 mvLog2(MV_U32 num);
+
+MV_STATUS mvWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2);
+MV_STATUS mvWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2);
+
+#endif /* MV_ASMLANGUAGE */
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif /* __INCmvCommonh */
diff --git a/arch/arm/plat-feroceon/common/mvCompVer.txt b/arch/arm/plat-feroceon/common/mvCompVer.txt
new file mode 100755
index 0000000..16d2fa4
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvCompVer.txt
@@ -0,0 +1,2 @@
+Global HAL Version:FEROCEON_HAL_3_1_7
+    Unit HAL Version:3.1 .4 Description:This component includes an implementation of the unit HAL drivers
diff --git a/arch/arm/plat-feroceon/common/mvDebug.c b/arch/arm/plat-feroceon/common/mvDebug.c
new file mode 100755
index 0000000..e2eea49
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvDebug.c
@@ -0,0 +1,275 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* includes */
+#include "mv802_3.h"
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvDebug.h"
+
+/* Global variables effect on behave MV_DEBUG_PRINT and MV_DEBUG_CODE macros
+ * mvDebug  - map of bits (one for each module) bit=1 means enable
+ *          debug code and messages for this module
+ * mvModuleDebug - array of 32 bits varables one for each module
+ */
+MV_U32 mvDebug = 0;
+MV_U32 mvDebugModules[MV_MODULE_MAX];
+
+/* Init mvModuleDebug array to default values */
+void mvDebugInit(void)
+{
+	int bit;
+
+	mvDebug = 0;
+	for (bit = 0; bit < MV_MODULE_MAX; bit++) {
+		mvDebugModules[bit] = MV_DEBUG_FLAG_ERR | MV_DEBUG_FLAG_STATS;
+		mvDebug |= MV_BIT_MASK(bit);
+	}
+}
+
+void mvDebugModuleEnable(MV_MODULE_ID module, MV_BOOL isEnable)
+{
+	if (isEnable)
+		MV_BIT_SET(mvDebug, module);
+	else
+		MV_BIT_CLEAR(mvDebug, module);
+}
+
+void mvDebugModuleSetFlags(MV_MODULE_ID module, MV_U32 flags)
+{
+	mvDebugModules[module] |= flags;
+}
+
+void mvDebugModuleClearFlags(MV_MODULE_ID module, MV_U32 flags)
+{
+	mvDebugModules[module] &= ~flags;
+}
+
+/* Dump memory in specific format:
+ * address: X1X1X1X1 X2X2X2X2 ... X8X8X8X8
+ */
+void mvDebugMemDump(void *addr, int size, int access)
+{
+	int i, j;
+	MV_U32 memAddr = (MV_U32) addr;
+
+	if (access == 0)
+		access = 1;
+
+	if ((access != 4) && (access != 2) && (access != 1)) {
+		mvOsPrintf("%d wrong access size. Access must be 1 or 2 or 4\n", access);
+		return;
+	}
+	memAddr = MV_ALIGN_DOWN((unsigned int)addr, 4);
+	size = MV_ALIGN_UP(size, 4);
+	addr = (void *)MV_ALIGN_DOWN((unsigned int)addr, access);
+	while (size > 0) {
+		mvOsPrintf("%08x: ", memAddr);
+		i = 0;
+		/* 32 bytes in the line */
+		while (i < 32) {
+			if (memAddr >= (MV_U32) addr) {
+				switch (access) {
+				case 1:
+					mvOsPrintf("%02x ", MV_MEMIO8_READ(memAddr));
+					break;
+
+				case 2:
+					mvOsPrintf("%04x ", MV_MEMIO16_READ(memAddr));
+					break;
+
+				case 4:
+					mvOsPrintf("%08x ", MV_MEMIO32_READ(memAddr));
+					break;
+				}
+			} else {
+				for (j = 0; j < (access * 2 + 1); j++)
+					mvOsPrintf(" ");
+			}
+			i += access;
+			memAddr += access;
+			size -= access;
+			if (size <= 0)
+				break;
+		}
+		mvOsPrintf("\n");
+	}
+}
+
+void mvDebugPrintBufInfo(BUF_INFO *pBufInfo, int size, int access)
+{
+	if (pBufInfo == NULL) {
+		mvOsPrintf("\n!!! pBufInfo = NULL\n");
+		return;
+	}
+	mvOsPrintf("\n*** pBufInfo=0x%x, cmdSts=0x%08x, pBuf=0x%x, bufSize=%d\n",
+		   (unsigned int)pBufInfo,
+		   (unsigned int)pBufInfo->cmdSts, (unsigned int)pBufInfo->pBuff, (unsigned int)pBufInfo->bufSize);
+	mvOsPrintf("pData=0x%x, byteCnt=%d, pNext=0x%x, uInfo1=0x%x, uInfo2=0x%x\n",
+		   (unsigned int)pBufInfo->pData,
+		   (unsigned int)pBufInfo->byteCnt,
+		   (unsigned int)pBufInfo->pNextBufInfo,
+		   (unsigned int)pBufInfo->userInfo1, (unsigned int)pBufInfo->userInfo2);
+	if (pBufInfo->pData != NULL) {
+		if (size > pBufInfo->byteCnt)
+			size = pBufInfo->byteCnt;
+		mvDebugMemDump(pBufInfo->pData, size, access);
+	}
+}
+
+void mvDebugPrintPktInfo(MV_PKT_INFO *pPktInfo, int size, int access)
+{
+	int frag, len;
+
+	if (pPktInfo == NULL) {
+		mvOsPrintf("\n!!! pPktInfo = NULL\n");
+		return;
+	}
+	mvOsPrintf("\npPkt=%p, stat=0x%08x, numFr=%d, size=%d, pFr=%p, osInfo=0x%lx\n",
+		   pPktInfo, pPktInfo->status, pPktInfo->numFrags, pPktInfo->pktSize,
+		   pPktInfo->pFrags, pPktInfo->osInfo);
+
+	for (frag = 0; frag < pPktInfo->numFrags; frag++) {
+		mvOsPrintf("#%2d. bufVirt=%p, bufSize=%d\n",
+			   frag, pPktInfo->pFrags[frag].bufVirtPtr, pPktInfo->pFrags[frag].bufSize);
+		if (size > 0) {
+			len = MV_MIN((int)pPktInfo->pFrags[frag].bufSize, size);
+			mvDebugMemDump(pPktInfo->pFrags[frag].bufVirtPtr, len, access);
+			size -= len;
+		}
+	}
+
+}
+
+void mvDebugPrintIpAddr(MV_U32 ipAddr)
+{
+	mvOsPrintf("%d.%d.%d.%d", ((ipAddr >> 24) & 0xFF), ((ipAddr >> 16) & 0xFF),
+		   ((ipAddr >> 8) & 0xFF), ((ipAddr >> 0) & 0xFF));
+}
+
+void mvDebugPrintMacAddr(const MV_U8 *pMacAddr)
+{
+	int i;
+
+	mvOsPrintf("%02x", (unsigned int)pMacAddr[0]);
+	for (i = 1; i < MV_MAC_ADDR_SIZE; i++)
+		mvOsPrintf(":%02x", pMacAddr[i]);
+
+	/* mvOsPrintf("\n"); */
+}
+
+/******* There are three functions deals with MV_DEBUG_TIMES structure ********/
+
+/* Reset MV_DEBUG_TIMES entry */
+void mvDebugResetTimeEntry(MV_DEBUG_TIMES *pTimeEntry, int count, char *pName)
+{
+	pTimeEntry->begin = 0;
+	pTimeEntry->count = count;
+	pTimeEntry->end = 0;
+	pTimeEntry->left = pTimeEntry->count;
+	pTimeEntry->total = 0;
+	pTimeEntry->min = 0xFFFFFFFF;
+	pTimeEntry->max = 0x0;
+	strncpy(pTimeEntry->name, pName, sizeof(pTimeEntry->name) - 1);
+	pTimeEntry->name[sizeof(pTimeEntry->name) - 1] = '\0';
+}
+
+/* Print out MV_DEBUG_TIMES entry */
+void mvDebugPrintTimeEntry(MV_DEBUG_TIMES *pTimeEntry, MV_BOOL isTitle)
+{
+	int num;
+
+	if (isTitle == MV_TRUE)
+		mvOsPrintf("Event         NumOfEvents       TotalTime         Average       Min       Max\n");
+
+	num = pTimeEntry->count - pTimeEntry->left;
+	if (num > 0) {
+		mvOsPrintf("%-11s     %6u          0x%08lx        %6lu     %6lu    %6lu\n",
+			   pTimeEntry->name, num, pTimeEntry->total, pTimeEntry->total / num,
+			   pTimeEntry->min, pTimeEntry->max);
+	}
+}
+
+/* Update MV_DEBUG_TIMES entry */
+void mvDebugUpdateTimeEntry(MV_DEBUG_TIMES *pTimeEntry)
+{
+	MV_U32 delta;
+
+	if (pTimeEntry->left > 0) {
+		if (pTimeEntry->end <= pTimeEntry->begin)
+			delta = pTimeEntry->begin - pTimeEntry->end;
+		else
+			delta = ((MV_U32) 0x10000 - pTimeEntry->end) + pTimeEntry->begin;
+
+		pTimeEntry->total += delta;
+
+		if (delta < pTimeEntry->min)
+			pTimeEntry->min = delta;
+
+		if (delta > pTimeEntry->max)
+			pTimeEntry->max = delta;
+
+		pTimeEntry->left--;
+	}
+}
diff --git a/arch/arm/plat-feroceon/common/mvDebug.h b/arch/arm/plat-feroceon/common/mvDebug.h
new file mode 100755
index 0000000..595054e
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvDebug.h
@@ -0,0 +1,169 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvDebugh
+#define __INCmvDebugh
+
+/* includes */
+#include "mvTypes.h"
+
+typedef enum {
+	MV_MODULE_INVALID = -1,
+	MV_MODULE_ETH = 0,
+	MV_MODULE_IDMA,
+	MV_MODULE_XOR,
+	MV_MODULE_TWASI,
+	MV_MODULE_MGI,
+	MV_MODULE_USB,
+	MV_MODULE_CESA,
+
+	MV_MODULE_MAX
+} MV_MODULE_ID;
+
+/* Define generic flags useful for most of modules */
+#define MV_DEBUG_FLAG_ALL   (0)
+#define MV_DEBUG_FLAG_INIT  (1 << 0)
+#define MV_DEBUG_FLAG_RX    (1 << 1)
+#define MV_DEBUG_FLAG_TX    (1 << 2)
+#define MV_DEBUG_FLAG_ERR   (1 << 3)
+#define MV_DEBUG_FLAG_TRACE (1 << 4)
+#define MV_DEBUG_FLAG_DUMP  (1 << 5)
+#define MV_DEBUG_FLAG_CACHE (1 << 6)
+#define MV_DEBUG_FLAG_IOCTL (1 << 7)
+#define MV_DEBUG_FLAG_STATS (1 << 8)
+
+extern MV_U32 mvDebug;
+extern MV_U32 mvDebugModules[MV_MODULE_MAX];
+
+#ifdef MV_DEBUG
+# define MV_DEBUG_PRINT(module, flags, msg)     mvOsPrintf msg
+# define MV_DEBUG_CODE(module, flags, code)     code
+#elif defined(MV_RT_DEBUG)
+# define MV_DEBUG_PRINT(module, flags, msg)                    \
+    if ((mvDebug & (1<<(module))) &&                           \
+	((mvDebugModules[(module)] & (flags)) == (flags)))     \
+	mvOsPrintf msg
+# define MV_DEBUG_CODE(module, flags, code)                    \
+    if ((mvDebug & (1<<(module))) &&                           \
+	((mvDebugModules[(module)] & (flags)) == (flags)))     \
+	code
+#else
+# define MV_DEBUG_PRINT(module, flags, msg)
+# define MV_DEBUG_CODE(module, flags, code)
+#endif
+
+/* typedefs */
+
+/*  time measurement structure used to check how much time pass between
+ *  two points
+ */
+typedef struct {
+	char name[20];		/* name of the entry */
+	unsigned long begin;	/* time measured on begin point */
+	unsigned long end;	/* time measured on end point */
+	unsigned long total;	/* Accumulated time */
+	unsigned long left;	/* The rest measurement actions */
+	unsigned long count;	/* Maximum measurement actions */
+	unsigned long min;	/* Minimum time from begin to end */
+	unsigned long max;	/* Maximum time from begin to end */
+} MV_DEBUG_TIMES;
+
+/* mvDebug.h API list */
+
+/****** Error Recording ******/
+
+/* Dump memory in specific format:
+ * address: X1X1X1X1 X2X2X2X2 ... X8X8X8X8
+ */
+void mvDebugMemDump(void *addr, int size, int access);
+
+void mvDebugPrintBufInfo(BUF_INFO *pBufInfo, int size, int access);
+
+void mvDebugPrintPktInfo(MV_PKT_INFO *pPktInfo, int size, int access);
+
+void mvDebugPrintIpAddr(MV_U32 ipAddr);
+
+void mvDebugPrintMacAddr(const MV_U8 *pMacAddr);
+
+/**** There are three functions deals with MV_DEBUG_TIMES structure ****/
+
+/* Reset MV_DEBUG_TIMES entry */
+void mvDebugResetTimeEntry(MV_DEBUG_TIMES *pTimeEntry, int count, char *name);
+
+/* Update MV_DEBUG_TIMES entry */
+void mvDebugUpdateTimeEntry(MV_DEBUG_TIMES *pTimeEntry);
+
+/* Print out MV_DEBUG_TIMES entry */
+void mvDebugPrintTimeEntry(MV_DEBUG_TIMES *pTimeEntry, MV_BOOL isTitle);
+
+/******** General ***********/
+
+/* Change value of mvDebugPrint global variable */
+
+void mvDebugInit(void);
+void mvDebugModuleEnable(MV_MODULE_ID module, MV_BOOL isEnable);
+void mvDebugModuleSetFlags(MV_MODULE_ID module, MV_U32 flags);
+void mvDebugModuleClearFlags(MV_MODULE_ID module, MV_U32 flags);
+
+#endif /* __INCmvDebug.h */
diff --git a/arch/arm/plat-feroceon/common/mvDeviceId.h b/arch/arm/plat-feroceon/common/mvDeviceId.h
new file mode 100755
index 0000000..4ab4ecd
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvDeviceId.h
@@ -0,0 +1,277 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvDeviceIdh
+#define __INCmvDeviceIdh
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+/* defines  */
+#define MARVELL_VEN_ID		    0x11ab
+
+/* Disco-3 */
+#define MV64460_DEV_ID          	0x6480
+#define MV64460B_DEV_ID         	0x6485
+#define MV64430_DEV_ID          	0x6420
+
+/* Disco-5 */
+#define MV64560_DEV_ID          	0x6450
+
+/* Disco-6 */
+#define MV64660_DEV_ID          	0x6460
+
+/* Orion */
+#define MV_1181_DEV_ID          	0x1181
+#define MV_5181_DEV_ID          	0x5181
+#define MV_5281_DEV_ID          	0x5281
+#define MV_5182_DEV_ID          	0x5182
+#define MV_8660_DEV_ID          	0x8660
+#define MV_5180_DEV_ID          	0x5180
+#define MV_5082_DEV_ID          	0x5082
+#define MV_1281_DEV_ID          	0x1281
+#define MV_6082_DEV_ID          	0x6082
+#define MV_6183_DEV_ID          	0x6183
+#define MV_6183L_DEV_ID          	0x6083
+
+#define MV_5281_D0_REV          	0x4
+#define MV_5281_D0_ID           	((MV_5281_DEV_ID << 16) | MV_5281_D0_REV)
+#define MV_5281_D0_NAME         "88F5281 D0"
+
+#define MV_5281_D1_REV          	0x5
+#define MV_5281_D1_ID           	((MV_5281_DEV_ID << 16) | MV_5281_D1_REV)
+#define MV_5281_D1_NAME         "88F5281 D1"
+
+#define MV_5281_D2_REV          	0x6
+#define MV_5281_D2_ID           	((MV_5281_DEV_ID << 16) | MV_5281_D2_REV)
+#define MV_5281_D2_NAME         "88F5281 D2"
+
+#define MV_5181L_A0_REV         	0x8	/* need for PCIE Er */
+#define MV_5181_A1_REV          	0x1	/* for USB Er .. */
+#define MV_5181_B0_REV          	0x2
+#define MV_5181_B1_REV          	0x3
+#define MV_5182_A1_REV          	0x1
+#define MV_5180N_B1_REV         	0x3
+#define MV_5181L_A0_ID          	((MV_5181_DEV_ID << 16) | MV_5181L_A0_REV)
+
+/* kw */
+#define MV_6281_DEV_ID          	0x6281
+#define MV_6282_DEV_ID          	0x1155
+#define MV_6192_DEV_ID          	0x6192
+#define MV_6190_DEV_ID          	0x6190
+#define MV_6180_DEV_ID          	0x6180
+#define MV_6280_DEV_ID          	0x6280
+
+#define MV_6281_A0_REV         		0x2
+#define MV_6281_A0_ID          		((MV_6281_DEV_ID << 16) | MV_6281_A0_REV)
+#define MV_6281_A0_NAME         	"88F6281 A0"
+
+#define MV_6192_A0_REV         		0x2
+#define MV_6192_A0_ID          		((MV_6192_DEV_ID << 16) | MV_6192_A0_REV)
+#define MV_6192_A0_NAME         	"88F6192 A0"
+
+#define MV_6190_A0_REV         		0x2
+#define MV_6190_A0_ID          		((MV_6190_DEV_ID << 16) | MV_6190_A0_REV)
+#define MV_6190_A0_NAME         	"88F6190 A0"
+
+#define MV_6180_A0_REV         		0x2
+#define MV_6180_A0_ID          		((MV_6180_DEV_ID << 16) | MV_6180_A0_REV)
+#define MV_6180_A0_NAME         	"88F6180 A0"
+
+#define MV_6281_A1_REV              0x3
+#define MV_6281_A1_ID               ((MV_6281_DEV_ID << 16) | MV_6281_A1_REV)
+#define MV_6281_A1_NAME             "88F6281 A1"
+
+#define MV_6282_A1_REV              0x3
+#define MV_6282_A1_ID               ((MV_6282_DEV_ID << 16) | MV_6282_A1_REV)
+#define MV_6282_A1_NAME             "88F6282 A1"
+
+#define MV_6280_A1_REV         		0x3
+#define MV_6280_A1_ID          		((MV_6280_DEV_ID << 16) | MV_6280_A0_REV)
+#define MV_6280_A1_NAME         	"88F6280 A1"
+
+#define MV_6192_A1_REV              0x3
+#define MV_6192_A1_ID               ((MV_6192_DEV_ID << 16) | MV_6192_A1_REV)
+#define MV_6192_A1_NAME             "88F6192 A1"
+
+#define MV_6190_A1_REV              0x3
+#define MV_6190_A1_ID               ((MV_6190_DEV_ID << 16) | MV_6190_A1_REV)
+#define MV_6190_A1_NAME             "88F6190 A1"
+
+#define MV_6180_A1_REV              0x3
+#define MV_6180_A1_ID               ((MV_6180_DEV_ID << 16) | MV_6180_A1_REV)
+#define MV_6180_A1_NAME             "88F6180 A1"
+
+#define MV_88F6XXX_A0_REV         	0x2
+#define MV_88F6XXX_A1_REV         	0x3
+/* Disco-Duo */
+#define MV_78XX0_ZY_DEV_ID       0x6381
+#define MV_78XX0_ZY_NAME         "MV78X00"
+
+#define MV_78XX0_Z0_REV         0x1
+#define MV_78XX0_Z0_ID          ((MV_78XX0_ZY_DEV_ID << 16) | MV_78XX0_Z0_REV)
+#define MV_78XX0_Z0_NAME        "78X00 Z0"
+
+#define MV_78XX0_Y0_REV         0x2
+#define MV_78XX0_Y0_ID          ((MV_78XX0_ZY_DEV_ID << 16) | MV_78XX0_Y0_REV)
+#define MV_78XX0_Y0_NAME        "78X00 Y0"
+
+#define MV_78XX0_DEV_ID       	0x7800
+#define MV_78XX0_NAME         	"MV78X00"
+
+#define MV_76100_DEV_ID      	0x7610
+#define MV_78200_DEV_ID      	0x7820
+#define MV_78100_DEV_ID      	0x7810
+#define MV_78XX0_A0_REV		0x1
+#define MV_78XX0_A1_REV		0x2
+
+#define MV_76100_NAME		"MV76100"
+#define MV_78100_NAME		"MV78100"
+#define MV_78200_NAME		"MV78200"
+
+#define MV_76100_A0_ID		((MV_76100_DEV_ID << 16) | MV_78XX0_A0_REV)
+#define MV_78100_A0_ID		((MV_78100_DEV_ID << 16) | MV_78XX0_A0_REV)
+#define MV_78200_A0_ID		((MV_78200_DEV_ID << 16) | MV_78XX0_A0_REV)
+
+#define MV_76100_A1_ID		((MV_76100_DEV_ID << 16) | MV_78XX0_A1_REV)
+#define MV_78100_A1_ID		((MV_78100_DEV_ID << 16) | MV_78XX0_A1_REV)
+#define MV_78200_A1_ID		((MV_78200_DEV_ID << 16) | MV_78XX0_A1_REV)
+
+#define MV_76100_A0_NAME	"MV76100 A0"
+#define MV_78100_A0_NAME	"MV78100 A0"
+#define MV_78200_A0_NAME	"MV78200 A0"
+#define MV_78XX0_A0_NAME	"MV78XX0 A0"
+
+#define MV_76100_A1_NAME	"MV76100 A1"
+#define MV_78100_A1_NAME	"MV78100 A1"
+#define MV_78200_A1_NAME	"MV78200 A1"
+#define MV_78XX0_A1_NAME	"MV78XX0 A1"
+
+/*MV88F632X family*/
+#define MV_6321_DEV_ID      	0x6321
+#define MV_6322_DEV_ID      	0x6322
+#define MV_6323_DEV_ID      	0x6323
+
+#define MV_6321_NAME		"88F6321"
+#define MV_6322_NAME		"88F6322"
+#define MV_6323_NAME		"88F6323"
+
+#define MV_632X_A1_REV		0x2
+
+#define MV_6321_A1_ID		((MV_6321_DEV_ID << 16) | MV_632X_A1_REV)
+#define MV_6322_A1_ID		((MV_6322_DEV_ID << 16) | MV_632X_A1_REV)
+#define MV_6323_A1_ID		((MV_6323_DEV_ID << 16) | MV_632X_A1_REV)
+
+#define MV_6321_A1_NAME		"88F6321 A1"
+#define MV_6322_A1_NAME		"88F6322 A1"
+#define MV_6323_A1_NAME		"88F6323 A1"
+
+/*MV88F6500 family*/
+#define MV_65XX_DEV_ID		0x6500
+#define MV_6510_DEV_ID		0x6510
+#define MV_6530_DEV_ID		0x6530
+#define MV_6550_DEV_ID		0x6550
+#define MV_6560_DEV_ID		0x6560
+#define MV_6601_DEV_ID		0x6601
+
+#define MV_6510_Z2_REV         		0x1
+#define MV_6510_Z2_ID          		((MV_6510_DEV_ID << 16) | MV_6510_Z2_REV)
+#define MV_6510_Z2_NAME         	"88F6510 Z2"
+
+#define MV_6530_Z2_REV         		0x1
+#define MV_6530_Z2_ID          		((MV_6530_DEV_ID << 16) | MV_6530_Z2_REV)
+#define MV_6530_Z2_NAME         	"88F6530 Z2"
+
+#define MV_6550_Z2_REV         		0x1
+#define MV_6550_Z2_ID          		((MV_6550_DEV_ID << 16) | MV_6550_Z2_REV)
+#define MV_6550_Z2_NAME         	"88F6550 Z2"
+
+#define MV_6560_Z2_REV         		0x1
+#define MV_6560_Z2_ID          		((MV_6560_DEV_ID << 16) | MV_6560_Z2_REV)
+#define MV_6560_Z2_NAME         	"88F6560 Z2"
+
+#define MV_6510_A0_REV         		0x2
+#define MV_6510_A0_ID          		((MV_6510_DEV_ID << 16) | MV_6510_A0_REV)
+#define MV_6510_A0_NAME         	"88F6510 A0"
+
+#define MV_6530_A0_REV         		0x2
+#define MV_6530_A0_ID          		((MV_6530_DEV_ID << 16) | MV_6530_A0_REV)
+#define MV_6530_A0_NAME         	"88F6530 A0"
+
+#define MV_6550_A0_REV         		0x2
+#define MV_6550_A0_ID          		((MV_6550_DEV_ID << 16) | MV_6550_A0_REV)
+#define MV_6550_A0_NAME         	"88F6550 A0"
+
+#define MV_6560_A0_REV         		0x2
+#define MV_6560_A0_ID          		((MV_6560_DEV_ID << 16) | MV_6560_A0_REV)
+#define MV_6560_A0_NAME         	"88F6560 A0"
+
+#define MV_6601_A0_REV         		0x0
+#define MV_6601_A0_ID          		((MV_6601_DEV_ID << 16) | MV_6601_A0_REV)
+#define MV_6601_A0_NAME         	"88F6601 A0"
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+#endif				/* __INCmvDeviceIdh */
diff --git a/arch/arm/plat-feroceon/common/mvHalVer.h b/arch/arm/plat-feroceon/common/mvHalVer.h
new file mode 100755
index 0000000..e6f3906
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvHalVer.h
@@ -0,0 +1,72 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvHalVerh
+#define __INCmvHalVerh
+
+/* Defines */
+#define MV_HAL_VERSION			"FEROCEON_HAL_3_1_7"
+#define MV_RELEASE_BASELINE		"SoCandControllers_FEROCEON_RELEASE_7_9_2009_KW_4_3_4_DD_2_1_4_6183_1_1_4"
+
+#endif /* __INCmvHalVerh */
diff --git a/arch/arm/plat-feroceon/common/mvList.c b/arch/arm/plat-feroceon/common/mvList.c
new file mode 100755
index 0000000..5d7928f
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvList.c
@@ -0,0 +1,127 @@
+/*******************************************************************************
+*                   Copyright 2003, Marvell Semiconductor Israel LTD.          *
+* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.                      *
+* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT  *
+* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE        *
+* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.     *
+* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED,       *
+* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.   *
+*                                                                              *
+* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, *
+* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL    *
+* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.  *
+* (MJKK), MARVELL SEMICONDUCTOR ISRAEL LTD (MSIL).                             *
+********************************************************************************
+* mvList.c - Implementation File for Linked List.
+*
+* DESCRIPTION:
+*     This file implements basic Linked List functionality.
+*
+*******************************************************************************/
+
+#include "mvList.h"
+
+/* Create a Linked List by allocating the list head */
+/* Returns the head of the list if successful, NULL otherwise */
+MV_LIST_ELEMENT *mvListCreate(MV_VOID)
+{
+	MV_LIST_ELEMENT *head = (MV_LIST_ELEMENT *)mvOsMalloc(sizeof(MV_LIST_ELEMENT));
+
+	if (head) {
+		head->prev = NULL;
+		head->next = NULL;
+		head->data = 0;
+	}
+
+#ifdef MV_LIST_SANITY_CHECKS
+	if (!head)
+		mvOsPrintf("%s ERROR: memory allocation for new list failed\n", __func__);
+#endif /* MV_LIST_SANITY_CHECKS */
+
+	return head;
+}
+
+/* Delete all elements in a given list and free the list head */
+MV_STATUS mvListDestroy(MV_LIST_ELEMENT *head)
+{
+	MV_LIST_ELEMENT *curr, *tmp;
+
+#ifdef MV_LIST_SANITY_CHECKS
+	/* sanity check */
+	if (!head) {
+		mvOsPrintf("%s ERROR: trying to destroy uninitialized list\n", __func__);
+		return MV_ERROR;
+	}
+#endif /* MV_LIST_SANITY_CHECKS */
+
+	/* delete all elements in the list */
+	/* skip list head, it never contains real data */
+	curr = head->next;
+	while (curr) {
+		tmp = curr;
+		curr = curr->next;
+		mvListDel(tmp);
+	}
+
+	/* free the list head */
+	mvOsFree(head);
+
+	return MV_OK;
+}
+
+/* Count the number of elements in the list (not including the head) */
+MV_LONG mvListElementsCount(MV_LIST_ELEMENT *head)
+{
+	MV_LONG count = 0;
+	MV_LIST_ELEMENT *curr;
+
+#ifdef MV_LIST_SANITY_CHECKS
+	/* sanity check */
+	if (!head) {
+		mvOsPrintf("%s ERROR: trying to count elements in an uninitialized list\n", __func__);
+		return -1;
+	}
+#endif /* MV_LIST_SANITY_CHECKS */
+
+	/* skip list head, it's not a real element */
+	for (curr = head->next; curr != NULL; curr = curr->next)
+		count++;
+
+	return count;
+}
+
+/* Print all list elements */
+MV_VOID mvListPrint(MV_LIST_ELEMENT *head)
+{
+	MV_LIST_ELEMENT *curr;
+
+	/* skip list head, it never contains real data */
+	for (curr = head->next; curr != NULL; curr = curr->next) {
+		mvOsPrintf("%lu ", curr->data);
+		MV_LIST_DBG("element = %p, prev = %p, next = %p, data = %lu\n", curr, curr->prev, curr->next, curr->data);
+	}
+	mvOsPrintf("\n");
+}
+
+/* simple self-contained test */
+MV_VOID mvListTest(MV_VOID)
+{
+	int i;
+	MV_LIST_ELEMENT *list_elements[10];
+	MV_LIST_ELEMENT *head = mvListCreate();
+
+	mvOsPrintf("\n\n----- mvListTest -----\n\n");
+
+	for (i = 0; i < 10; i++)
+		list_elements[i] = mvListAddHead(head, i);
+
+	mvListPrint(head);
+
+	mvListDel(list_elements[0]);
+	mvListDel(list_elements[9]);
+	mvListDel(list_elements[4]);
+
+	mvListPrint(head);
+
+	mvListDestroy(head);
+}
diff --git a/arch/arm/plat-feroceon/common/mvList.h b/arch/arm/plat-feroceon/common/mvList.h
new file mode 100755
index 0000000..9050b9e
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvList.h
@@ -0,0 +1,138 @@
+/*******************************************************************************
+*                   Copyright 2003, Marvell Semiconductor Israel LTD.          *
+* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.                      *
+* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT  *
+* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE        *
+* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.     *
+* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED,       *
+* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.   *
+*                                                                              *
+* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, *
+* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL    *
+* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.  *
+* (MJKK), MARVELL SEMICONDUCTOR ISRAEL LTD (MSIL).                             *
+********************************************************************************
+* mvList.h - Header File for Linked List.
+*
+* DESCRIPTION:
+*     This file defines basic Linked List functionality.
+*
+*******************************************************************************/
+
+#ifndef __mvList_h__
+#define __mvList_h__
+
+#include "mvCommon.h"
+#include "mvOs.h"
+
+/* Un-comment the next line to use sanity checks in the code */
+/* #define MV_LIST_SANITY_CHECKS */
+
+/* Un-comment the next line to enable debug prints */
+/* #define MV_LIST_DEBUG */
+
+#ifdef MV_LIST_DEBUG
+#define MV_LIST_DBG(fmt, arg...) mvOsPrintf(fmt, ##arg)
+#else
+#define MV_LIST_DBG(fmt, arg...)
+#endif
+
+typedef struct mv_list_element {
+	struct mv_list_element *prev;
+	struct mv_list_element *next;
+	MV_ULONG data;
+
+} MV_LIST_ELEMENT;
+
+/* Returns the first matching element in the list, NULL if not found */
+static INLINE MV_LIST_ELEMENT *mvListFind(MV_LIST_ELEMENT *head, MV_ULONG data)
+{
+	MV_LIST_ELEMENT *curr;
+
+	/* skip list head, it never contains real data */
+	for (curr = head->next; curr != NULL; curr = curr->next) {
+		if (curr->data == data)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Add a new element at the top of the list (right after head) */
+/* The list head will point to this new element */
+/* Returns pointer to new element if successful, NULL otherwise */
+static INLINE MV_LIST_ELEMENT *mvListAddHead(MV_LIST_ELEMENT *head, MV_ULONG data)
+{
+	MV_LIST_ELEMENT *element;
+
+#ifdef MV_LIST_SANITY_CHECKS
+	/* sanity check */
+	if (!head) {
+		mvOsPrintf("%s ERROR: trying to add an element to an uninitialized list\n", __func__);
+		return NULL;
+	}
+#endif /* MV_LIST_SANITY_CHECKS */
+
+	element = mvOsMalloc(sizeof(MV_LIST_ELEMENT));
+	if (element) {
+		element->data = data;
+		element->next = head->next;
+		element->prev = head;
+		if (head->next)
+			head->next->prev = element;
+
+		head->next = element;
+
+		MV_LIST_DBG("Adding new element %p: data = %lu, next = %p, prev = %p\n",
+				element, element->data, element->next, element->prev);
+	}
+
+#ifdef MV_LIST_SANITY_CHECKS
+	if (!element)
+		mvOsPrintf("%s ERROR: memory allocation for new element failed\n", __func__);
+#endif /* MV_LIST_SANITY_CHECKS */
+
+	return element;
+}
+
+/* Delete an element from a list */
+/* Return the deleted element data */
+static INLINE MV_ULONG mvListDel(MV_LIST_ELEMENT *element)
+{
+	MV_LIST_ELEMENT *prev;
+	MV_LIST_ELEMENT *next;
+	MV_ULONG data;
+
+#ifdef MV_LIST_SANITY_CHECKS
+	/* sanity check */
+	if (!element) {
+		mvOsPrintf("%s ERROR: trying to delete a NULL element\n", __func__);
+		return 0;
+	}
+#endif /* MV_LIST_SANITY_CHECKS */
+
+	prev = element->prev;
+	next = element->next;
+	data = element->data;
+
+	MV_LIST_DBG("Deleting element %p, data = %lu, prev = %p, next = %p\n", element, element->data, prev, next);
+
+	mvOsFree(element);
+
+	if (prev)
+		prev->next = next;
+	else
+		mvOsPrintf("%s ERROR: trying to delete an element when prev == NULL\n", __func__);
+
+	if (next)
+		next->prev = prev;
+
+	return data;
+}
+
+MV_LIST_ELEMENT *mvListCreate(MV_VOID);
+MV_STATUS mvListDestroy(MV_LIST_ELEMENT *head);
+MV_LONG mvListElementsCount(MV_LIST_ELEMENT *head);
+MV_VOID mvListPrint(MV_LIST_ELEMENT *head);
+MV_VOID mvListTest(MV_VOID);
+
+#endif /* __mvList_h__ */
diff --git a/arch/arm/plat-feroceon/common/mvStack.c b/arch/arm/plat-feroceon/common/mvStack.c
new file mode 100755
index 0000000..696cb06
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvStack.c
@@ -0,0 +1,96 @@
+/*******************************************************************************
+*                   Copyright 2003, Marvell Semiconductor Israel LTD.          *
+* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.                      *
+* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT  *
+* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE        *
+* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.     *
+* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED,       *
+* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.   *
+*                                                                              *
+* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, *
+* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL    *
+* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.  *
+* (MJKK), MARVELL SEMICONDUCTOR ISRAEL LTD (MSIL).                             *
+********************************************************************************
+* mvQueue.c
+*
+* FILENAME:    $Workfile: mvStack.c $
+* LAST UPDATE: $Modtime:  $
+*
+* DESCRIPTION:
+*     This file implements simple Stack LIFO functionality.
+*******************************************************************************/
+
+/* includes */
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvTypes.h"
+#include "mvDebug.h"
+#include "mvStack.h"
+
+/* defines  */
+
+/* Public functions */
+
+/* Purpose: Create new stack
+ * Inputs:
+ *	- MV_U32	noOfElements	- maximum number of elements in the stack.
+ *                              Each element 4 bytes size
+ * Return: void* - pointer to created stack.
+ */
+void *mvStackCreate(int numOfElements)
+{
+	MV_STACK *pStack;
+	MV_U32 *pStackElements;
+
+	pStack = (MV_STACK *)mvOsMalloc(sizeof(MV_STACK));
+	pStackElements = (MV_U32 *)mvOsMalloc(numOfElements * sizeof(MV_U32));
+	if ((pStack == NULL) || (pStackElements == NULL)) {
+		mvOsPrintf("mvStack: Can't create new stack\n");
+		if (pStack)
+			mvOsFree(pStack);
+		if (pStackElements)
+			mvOsFree(pStackElements);
+		return NULL;
+	}
+	memset(pStackElements, 0, numOfElements * sizeof(MV_U32));
+	pStack->numOfElements = numOfElements;
+	pStack->stackIdx = 0;
+	pStack->stackElements = pStackElements;
+
+	return pStack;
+}
+
+/* Purpose: Delete existing stack
+ * Inputs:
+ *	- void* 	stackHndl 	- Stack handle as returned by "mvStackCreate()" function
+ *
+ * Return: MV_STATUS  	MV_NOT_FOUND - Failure. StackHandle is not valid.
+ *			MV_OK        - Success.
+ */
+MV_STATUS mvStackDelete(void *stackHndl)
+{
+	MV_STACK *pStack = (MV_STACK *) stackHndl;
+
+	if ((pStack == NULL) || (pStack->stackElements == NULL))
+		return MV_NOT_FOUND;
+
+	mvOsFree(pStack->stackElements);
+	mvOsFree(pStack);
+
+	return MV_OK;
+}
+
+/* PrintOut status of the stack */
+void mvStackStatus(void *stackHndl, MV_BOOL isPrintElements)
+{
+	int i;
+	MV_STACK *pStack = (MV_STACK *) stackHndl;
+
+	mvOsPrintf("StackHandle=%p, pElements=%p, numElements=%d, stackIdx=%d\n",
+		   stackHndl, pStack->stackElements, pStack->numOfElements, pStack->stackIdx);
+	if (isPrintElements == MV_TRUE) {
+		for (i = 0; i < pStack->stackIdx; i++)
+			mvOsPrintf("%3d. Value=0x%x\n", i, pStack->stackElements[i]);
+	}
+}
diff --git a/arch/arm/plat-feroceon/common/mvStack.h b/arch/arm/plat-feroceon/common/mvStack.h
new file mode 100755
index 0000000..e7ff74b
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvStack.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+*                   Copyright 2003, Marvell Semiconductor Israel LTD.          *
+* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.                      *
+* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT  *
+* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE        *
+* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.     *
+* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED,       *
+* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.   *
+*                                                                              *
+* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, *
+* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL    *
+* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.  *
+* (MJKK), MARVELL SEMICONDUCTOR ISRAEL LTD (MSIL).                             *
+********************************************************************************
+* mvStack.h - Header File for :
+*
+* FILENAME:    $Workfile: mvStack.h $
+* LAST UPDATE: $Modtime:  $
+*
+* DESCRIPTION:
+*     This file defines simple Stack (LIFO) functionality.
+*
+*******************************************************************************/
+
+#ifndef __mvStack_h__
+#define __mvStack_h__
+
+/* includes */
+#include "mvTypes.h"
+
+/* defines  */
+
+/* typedefs */
+/* Data structure describes general purpose Stack */
+typedef struct {
+	int stackIdx;
+	int numOfElements;
+	MV_U32 *stackElements;
+} MV_STACK;
+
+static INLINE MV_BOOL mvStackIsFull(void *stackHndl)
+{
+	MV_STACK *pStack = (MV_STACK *) stackHndl;
+
+	if (pStack->stackIdx == pStack->numOfElements)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+static INLINE MV_BOOL mvStackIsEmpty(void *stackHndl)
+{
+	MV_STACK *pStack = (MV_STACK *) stackHndl;
+
+	if (pStack->stackIdx == 0)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+/* Purpose: Push new element to stack
+ * Inputs:
+ *	- void* 	stackHndl 	- Stack handle as returned by "mvStackCreate()" function.
+ *	- MV_U32	value		- New element.
+ *
+ * Return: MV_STATUS  	MV_FULL - Failure. Stack is full.
+ *						MV_OK   - Success. Element is put to stack.
+ */
+static INLINE void mvStackPush(void *stackHndl, MV_U32 value)
+{
+	MV_STACK *pStack = (MV_STACK *) stackHndl;
+
+#ifdef MV_RT_DEBUG
+	if (pStack->stackIdx == pStack->numOfElements) {
+		mvOsPrintf("mvStackPush: Stack is FULL\n");
+		return;
+	}
+#endif /* MV_RT_DEBUG */
+
+	pStack->stackElements[pStack->stackIdx] = value;
+	pStack->stackIdx++;
+}
+
+/* Purpose: Pop element from the top of stack and copy it to "pValue"
+ * Inputs:
+ *	- void* 	stackHndl 	- Stack handle as returned by "mvStackCreate()" function.
+ *	- MV_U32	value		- Element in the top of stack.
+ *
+ * Return: MV_STATUS  	MV_EMPTY - Failure. Stack is empty.
+ *						MV_OK    - Success. Element is removed from the stack and
+ *									copied to pValue argument
+ */
+static INLINE MV_U32 mvStackPop(void *stackHndl)
+{
+	MV_STACK *pStack = (MV_STACK *) stackHndl;
+
+#ifdef MV_RT_DEBUG
+	if (pStack->stackIdx == 0) {
+		mvOsPrintf("mvStackPop: Stack is EMPTY\n");
+		return 0;
+	}
+#endif /* MV_RT_DEBUG */
+
+	pStack->stackIdx--;
+	return pStack->stackElements[pStack->stackIdx];
+}
+
+static INLINE int mvStackIndex(void *stackHndl)
+{
+	MV_STACK *pStack = (MV_STACK *) stackHndl;
+
+	return pStack->stackIdx;
+}
+
+static INLINE int mvStackFreeElements(void *stackHndl)
+{
+	MV_STACK *pStack = (MV_STACK *) stackHndl;
+
+	return (pStack->numOfElements - pStack->stackIdx);
+}
+
+/* mvStack.h API list */
+
+/* Create new Stack */
+void *mvStackCreate(int numOfElements);
+
+/* Delete existing stack */
+MV_STATUS mvStackDelete(void *stackHndl);
+
+/* Print status of the stack */
+void mvStackStatus(void *stackHndl, MV_BOOL isPrintElements);
+
+#endif /* __mvStack_h__ */
diff --git a/arch/arm/plat-feroceon/common/mvTypes.h b/arch/arm/plat-feroceon/common/mvTypes.h
new file mode 100755
index 0000000..6f221f3
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvTypes.h
@@ -0,0 +1,270 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvTypesh
+#define __INCmvTypesh
+
+/* Defines */
+
+/* The following is a list of Marvell status    */
+#define MV_ERROR		    (-1)
+#define MV_OK			    (0)	/* Operation succeeded                   */
+#define MV_FAIL			    (1)	/* Operation failed                      */
+#define MV_BAD_VALUE        (2)	/* Illegal value (general)               */
+#define MV_OUT_OF_RANGE     (3)	/* The value is out of range             */
+#define MV_BAD_PARAM        (4)	/* Illegal parameter in function called  */
+#define MV_BAD_PTR          (5)	/* Illegal pointer value                 */
+#define MV_BAD_SIZE         (6)	/* Illegal size                          */
+#define MV_BAD_STATE        (7)	/* Illegal state of state machine        */
+#define MV_SET_ERROR        (8)	/* Set operation failed                  */
+#define MV_GET_ERROR        (9)	/* Get operation failed                  */
+#define MV_CREATE_ERROR     (10)	/* Fail while creating an item           */
+#define MV_NOT_FOUND        (11)	/* Item not found                        */
+#define MV_NO_MORE          (12)	/* No more items found                   */
+#define MV_NO_SUCH          (13)	/* No such item                          */
+#define MV_TIMEOUT          (14)	/* Time Out                              */
+#define MV_NO_CHANGE        (15)	/* Parameter(s) is already in this value */
+#define MV_NOT_SUPPORTED    (16)	/* This request is not support           */
+#define MV_NOT_IMPLEMENTED  (17)	/* Request supported but not implemented */
+#define MV_NOT_INITIALIZED  (18)	/* The item is not initialized           */
+#define MV_NO_RESOURCE      (19)	/* Resource not available (memory ...)   */
+#define MV_FULL             (20)	/* Item is full (Queue or table etc...)  */
+#define MV_EMPTY            (21)	/* Item is empty (Queue or table etc...) */
+#define MV_INIT_ERROR       (22)	/* Error occured while INIT process      */
+#define MV_HW_ERROR         (23)	/* Hardware error                        */
+#define MV_TX_ERROR         (24)	/* Transmit operation not succeeded      */
+#define MV_RX_ERROR         (25)	/* Recieve operation not succeeded       */
+#define MV_NOT_READY	    (26)	/* The other side is not ready yet       */
+#define MV_ALREADY_EXIST    (27)	/* Tried to create existing item         */
+#define MV_OUT_OF_CPU_MEM   (28)	/* Cpu memory allocation failed.         */
+#define MV_NOT_STARTED      (29)	/* Not started yet                       */
+#define MV_BUSY             (30)	/* Item is busy.                         */
+#define MV_TERMINATE        (31)	/* Item terminates it's work.            */
+#define MV_NOT_ALIGNED      (32)	/* Wrong alignment                       */
+#define MV_NOT_ALLOWED      (33)	/* Operation NOT allowed                 */
+#define MV_WRITE_PROTECT    (34)	/* Write protected                       */
+#define MV_DROPPED          (35)	/* Packet dropped                        */
+#define MV_STOLEN           (36)	/* Packet stolen */
+#define MV_CONTINUE         (37)	/* Continue */
+#define MV_RETRY            (38)	/* Operation failed need retry           */
+
+#define MV_INVALID  (int)(-1)
+
+#define MV_FALSE	0
+#define MV_TRUE     (!(MV_FALSE))
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#ifndef MV_ASMLANGUAGE
+/* typedefs */
+
+typedef char MV_8;
+typedef unsigned char MV_U8;
+
+typedef int MV_32;
+typedef unsigned int MV_U32;
+
+typedef short MV_16;
+typedef unsigned short MV_U16;
+
+#ifdef MV_PPC64
+typedef long MV_64;
+typedef unsigned long MV_U64;
+#else
+typedef long long MV_64;
+typedef unsigned long long MV_U64;
+#endif
+
+typedef long MV_LONG;		/* 32/64 */
+typedef unsigned long MV_ULONG;	/* 32/64 */
+
+typedef int MV_STATUS;
+typedef int MV_BOOL;
+typedef void MV_VOID;
+typedef float MV_FLOAT;
+
+typedef int (*MV_FUNCPTR) (void);	/* ptr to function returning int   */
+typedef void (*MV_VOIDFUNCPTR) (void);	/* ptr to function returning void  */
+typedef double (*MV_DBLFUNCPTR) (void);	/* ptr to function returning double */
+typedef float (*MV_FLTFUNCPTR) (void);	/* ptr to function returning float */
+
+typedef MV_U32 MV_KHZ;
+typedef MV_U32 MV_MHZ;
+typedef MV_U32 MV_HZ;
+
+/* This enumerator describes the set of commands that can be applied on   	*/
+/* an engine (e.g. IDMA, XOR). Appling a comman depends on the current   	*/
+/* status (see MV_STATE enumerator)                      					*/
+/* Start can be applied only when status is IDLE                         */
+/* Stop can be applied only when status is IDLE, ACTIVE or PAUSED        */
+/* Pause can be applied only when status is ACTIVE                          */
+/* Restart can be applied only when status is PAUSED                        */
+typedef enum _mvCommand {
+	MV_START,		/* Start     */
+	MV_STOP,		/* Stop     */
+	MV_PAUSE,		/* Pause    */
+	MV_RESTART		/* Restart  */
+} MV_COMMAND;
+
+/* This enumerator describes the set of state conditions.					*/
+/* Moving from one state to other is stricted.   							*/
+typedef enum _mvState {
+	MV_IDLE,
+	MV_ACTIVE,
+	MV_PAUSED,
+	MV_UNDEFINED_STATE
+} MV_STATE;
+
+typedef enum {
+	ETH_MAC_SPEED_10M,
+	ETH_MAC_SPEED_100M,
+	ETH_MAC_SPEED_1000M,
+	ETH_MAC_SPEED_AUTO,
+
+} MV_ETH_MAC_SPEED;
+
+/* This structure describes address space window. Window base can be        */
+/* 64 bit, window size up to 4GB                                            */
+typedef struct _mvAddrWin {
+	MV_U32 baseLow;		/* 32bit base low       */
+	MV_U32 baseHigh;	/* 32bit base high      */
+	MV_U32 size;		/* 32bit size           */
+} MV_ADDR_WIN;
+
+/* This binary enumerator describes protection attribute status             */
+typedef enum _mvProtRight {
+	ALLOWED,		/* Protection attribute allowed                         */
+	FORBIDDEN		/* Protection attribute forbidden                       */
+} MV_PROT_RIGHT;
+
+/* Unified struct for Rx and Tx packet operations. The user is required to 	*/
+/* be familier only with Tx/Rx descriptor command status.               	*/
+typedef struct _bufInfo {
+	MV_U32 cmdSts;		/* Tx/Rx command status                                     */
+	MV_U16 byteCnt;		/* Size of valid data in the buffer     */
+	MV_U16 bufSize;		/* Total size of the buffer             */
+	MV_U8 *pBuff;		/* Pointer to Buffer                    */
+	MV_U8 *pData;		/* Pointer to data in the Buffer        */
+	MV_U32 userInfo1;	/* Tx/Rx attached user information 1    */
+	MV_U32 userInfo2;	/* Tx/Rx attached user information 2    */
+	struct _bufInfo *pNextBufInfo;	/* Next buffer in packet            */
+} BUF_INFO;
+
+/* This structure contains information describing one of buffers
+ * (fragments) they are built Ethernet packet.
+ */
+typedef struct {
+	MV_U8 *bufVirtPtr;
+	MV_ULONG bufPhysAddr;
+	MV_U32 bufSize;
+	MV_U32 dataSize;
+	MV_U32 memHandle;
+	MV_32 bufAddrShift;
+} MV_BUF_INFO;
+
+/* This structure contains information describing Ethernet packet.
+ * The packet can be divided for few buffers (fragments)
+ */
+typedef struct {
+	MV_ULONG osInfo;
+	MV_BUF_INFO *pFrags;
+	MV_U32 status;
+	MV_U16 pktSize;
+	MV_U16 numFrags;
+	MV_U32 ownerId;
+	MV_U32 fragIP;
+	MV_U32 txq;
+} MV_PKT_INFO;
+
+/* This structure describes SoC units address decode window	*/
+typedef struct {
+	MV_ADDR_WIN addrWin;	/* An address window */
+	MV_BOOL enable;		/* Address decode window is enabled/disabled    */
+	MV_U8 attrib;		/* chip select attributes */
+	MV_U8 targetId;		/* Target Id of this MV_TARGET */
+} MV_UNIT_WIN_INFO;
+
+/* This structure describes access rights for Access protection windows     */
+/* that can be found in IDMA, XOR, Ethernet and MPSC units.                 */
+/* Note that the permission enumerator coresponds to its register format.   */
+/* For example, Read only premission is presented as "1" in register field. */
+typedef enum _mvAccessRights {
+	NO_ACCESS_ALLOWED = 0,	/* No access allowed            */
+	READ_ONLY = 1,		/* Read only permission         */
+	ACC_RESERVED = 2,	/* Reserved access right                */
+	FULL_ACCESS = 3,	/* Read and Write permission    */
+	MAX_ACC_RIGHTS
+} MV_ACCESS_RIGHTS;
+
+typedef struct _mvDecRegs {
+	MV_U32 baseReg;
+	MV_U32 baseRegHigh;
+	MV_U32 sizeReg;
+} MV_DEC_REGS;
+
+#endif /* MV_ASMLANGUAGE */
+
+#endif /* __INCmvTypesh */
diff --git a/arch/arm/plat-feroceon/common/mvVideo.h b/arch/arm/plat-feroceon/common/mvVideo.h
new file mode 100755
index 0000000..e9918b1
--- /dev/null
+++ b/arch/arm/plat-feroceon/common/mvVideo.h
@@ -0,0 +1,121 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCmvVideoh
+#define __INCmvVideoh
+
+/* includes */
+
+/* Defines */
+
+typedef struct mvVideoResolution {
+	MV_U32 width;
+	MV_U32 height;
+	char *name;
+} MV_VIDEO_RESOLUTION;
+
+/*
+ * Basic window sizes.
+ */
+
+#define VGA_WIDTH	640
+#define VGA_HEIGHT	480
+#define QVGA_WIDTH	320
+#define QVGA_HEIGHT	240
+#define CIF_WIDTH	352
+#define CIF_HEIGHT	288
+#define QCIF_WIDTH	176
+#define	QCIF_HEIGHT	144
+
+#define MV_VIDEO_RESOLUTION_VGA {VGA_WIDTH, VGA_HEIGHT, "VGA"}
+#define MV_VIDEO_RESOLUTION_QVGA {QVGA_WIDTH, QVGA_HEIGHT, "QVGA"}
+#define MV_VIDEO_RESOLUTION_CIF {CIF_WIDTH, CIF_HEIGHT, "CIF"}
+#define MV_VIDEO_RESOLUTION_QCIF {QCIF_WIDTH, QCIF_HEIGHT, "QCIF"}
+
+/* Pixel format */
+typedef enum mvPixFormatId {
+	MV_PIX_FORMAT_ID_RGB444 = 0x444,
+	MV_PIX_FORMAT_ID_RGB555 = 0x555,
+	MV_PIX_FORMAT_ID_RGB565 = 0x565,
+	MV_PIX_FORMAT_ID_YUV422 = 0x422,
+	MV_PIX_FORMAT_ID_RAW_BAYER = 0x111,
+} MV_PIX_FORMAT_ID;
+
+typedef struct mvPixelFormat {
+	MV_PIX_FORMAT_ID id;
+	char *name;
+} MV_PIXEL_FORMAT;
+
+/* known formats */
+#define MV_PIXEL_FORMAT_RGB444	{MV_PIX_FORMAT_ID_RGB444, "RGB444"}
+#define MV_PIXEL_FORMAT_RGB555  {MV_PIX_FORMAT_ID_RGB555, "RGB555"}
+#define MV_PIXEL_FORMAT_RGB565  {MV_PIX_FORMAT_ID_RGB565, "RGB565"}
+#define MV_PIXEL_FORMAT_YUV422  {MV_PIX_FORMAT_ID_YUV422, "YUV422"}
+#define MV_PIXEL_FORMAT_RAW_BAYER  {MV_PIX_FORMAT_ID_RAW_BAYER, "RAW BAYER"}
+
+typedef struct {
+	MV_PIXEL_FORMAT pixelFormat;
+	MV_VIDEO_RESOLUTION resolution;
+} MV_IMAGE_FORMAT;
+
+#endif /* __INCmvVideoh */
diff --git a/arch/arm/plat-feroceon/include/plat/cache-feroceon-l2.h b/arch/arm/plat-feroceon/include/plat/cache-feroceon-l2.h
new file mode 100755
index 0000000..06f982d
--- /dev/null
+++ b/arch/arm/plat-feroceon/include/plat/cache-feroceon-l2.h
@@ -0,0 +1,11 @@
+/*
+ * arch/arm/plat-orion/include/plat/cache-feroceon-l2.h
+ *
+ * Copyright (C) 2008 Marvell Semiconductor
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+extern void __init feroceon_l2_init(int l2_wt_override);
diff --git a/arch/arm/plat-feroceon/include/plat/gpio.h b/arch/arm/plat-feroceon/include/plat/gpio.h
new file mode 100755
index 0000000..e336005
--- /dev/null
+++ b/arch/arm/plat-feroceon/include/plat/gpio.h
@@ -0,0 +1,26 @@
+/*
+ * arch/arm/plat-feroceon/include/plat/gpio.h
+ *
+ * Marvell Feroceon SoC GPIO handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_GPIO_H
+#define __PLAT_GPIO_H
+
+#include <linux/init.h>
+
+#define gpio_get_value  __gpio_get_value
+#define gpio_set_value  __gpio_set_value
+#define gpio_cansleep   __gpio_cansleep
+
+#define GPIO_INPUT_OK		(1 << 0)
+#define GPIO_OUTPUT_OK		(1 << 1)
+
+/* Initialize gpiolib. */
+void __init mv_gpio_init(void);
+
+#endif
diff --git a/arch/arm/plat-feroceon/include/plat/i2s-orion.h b/arch/arm/plat-feroceon/include/plat/i2s-orion.h
new file mode 100755
index 0000000..4ae4edf
--- /dev/null
+++ b/arch/arm/plat-feroceon/include/plat/i2s-orion.h
@@ -0,0 +1,23 @@
+/*
+ * include/asm-arm/plat-orion/i2s-orion.h
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASM_PLAT_ORION_I2S_ORION_H
+#define __ASM_PLAT_ORION_I2S_ORION_H
+
+#include <linux/mbus.h>
+
+struct orion_i2s_platform_data {
+	struct mbus_dram_target_info	*dram;
+	int	spdif_rec;
+	int	spdif_play;
+	int	i2s_rec;
+	int	i2s_play;
+};
+
+
+#endif
diff --git a/arch/arm/plat-feroceon/include/plat/mvsdio.h b/arch/arm/plat-feroceon/include/plat/mvsdio.h
new file mode 100755
index 0000000..14ca886
--- /dev/null
+++ b/arch/arm/plat-feroceon/include/plat/mvsdio.h
@@ -0,0 +1,21 @@
+/*
+ * arch/arm/plat-orion/include/plat/mvsdio.h
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_MVSDIO_H
+#define __MACH_MVSDIO_H
+
+#include <linux/mbus.h>
+
+struct mvsdio_platform_data {
+	struct mbus_dram_target_info *dram;
+	unsigned int clock;
+	int gpio_card_detect;
+	int gpio_write_protect;
+};
+
+#endif
diff --git a/arch/arm/plat-feroceon/include/plat/orion_wdt.h b/arch/arm/plat-feroceon/include/plat/orion_wdt.h
new file mode 100755
index 0000000..a7d5814
--- /dev/null
+++ b/arch/arm/plat-feroceon/include/plat/orion_wdt.h
@@ -0,0 +1,18 @@
+/*
+ * arch/arm/plat-feroceon/include/plat/orion_wdt.h
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_ORION_WDT_H
+#define __PLAT_ORION_WDT_H
+
+struct orion_wdt_platform_data {
+	u32	tclk;		/* no <linux/clk.h> support yet */
+};
+
+
+#endif
+
diff --git a/arch/arm/plat-feroceon/include/plat/xor.h b/arch/arm/plat-feroceon/include/plat/xor.h
new file mode 100755
index 0000000..d730e02
--- /dev/null
+++ b/arch/arm/plat-feroceon/include/plat/xor.h
@@ -0,0 +1,26 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+#include <asm/mach/time.h>
+
+int xor_memxor(unsigned int src_count, unsigned int bytes, void *dest, void **srcs);
diff --git a/arch/arm/plat-feroceon/linux_oss/mvOs.c b/arch/arm/plat-feroceon/linux_oss/mvOs.c
new file mode 100755
index 0000000..6b7c2ca
--- /dev/null
+++ b/arch/arm/plat-feroceon/linux_oss/mvOs.c
@@ -0,0 +1,211 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvOsCpuArchLib.c - Marvell CPU architecture library
+*
+* DESCRIPTION:
+*       This library introduce Marvell API for OS dependent CPU architecture 
+*       APIs. This library introduce single CPU architecture services APKI 
+*       cross OS.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+/* includes */
+#include <asm/processor.h>
+#include "mvOs.h"
+
+static MV_U32 read_p15_c0 (void);
+
+/* defines  */
+#define ARM_ID_REVISION_OFFS	0
+#define ARM_ID_REVISION_MASK	(0xf << ARM_ID_REVISION_OFFS)
+
+#define ARM_ID_PART_NUM_OFFS	4
+#define ARM_ID_PART_NUM_MASK	(0xfff << ARM_ID_PART_NUM_OFFS)
+
+#define ARM_ID_ARCH_OFFS	16
+#define ARM_ID_ARCH_MASK	(0xf << ARM_ID_ARCH_OFFS)
+
+#define ARM_ID_VAR_OFFS		20
+#define ARM_ID_VAR_MASK		(0xf << ARM_ID_VAR_OFFS)
+
+#define ARM_ID_ASCII_OFFS	24
+#define ARM_ID_ASCII_MASK	(0xff << ARM_ID_ASCII_OFFS)
+
+
+
+void* mvOsIoCachedMalloc( void* osHandle, MV_U32 size, MV_ULONG* pPhyAddr,
+			  MV_U32 *memHandle)
+{
+    void *p = kmalloc( size, GFP_ATOMIC );
+    *pPhyAddr = pci_map_single( osHandle, p, 0, PCI_DMA_BIDIRECTIONAL );
+    return p;
+}
+void* mvOsIoUncachedMalloc( void* osHandle, MV_U32 size, MV_ULONG* pPhyAddr,
+			    MV_U32 *memHandle)
+{
+    return pci_alloc_consistent( osHandle, size, (dma_addr_t *)pPhyAddr );
+}
+ 
+void mvOsIoUncachedFree( void* osHandle, MV_U32 size, MV_ULONG phyAddr, void* pVirtAddr,
+			 MV_U32 memHandle)
+{
+    return pci_free_consistent( osHandle, size, pVirtAddr, (dma_addr_t)phyAddr );
+} 
+                                                                                                                                               
+void mvOsIoCachedFree( void* osHandle, MV_U32 size, MV_ULONG phyAddr, void* pVirtAddr,
+		       MV_U32 memHandle )
+{
+    return kfree( pVirtAddr );
+}
+ 
+int mvOsRand(void)
+{
+    int rand;
+    get_random_bytes(&rand, sizeof(rand) );
+    return rand;
+}
+
+/*******************************************************************************
+* mvOsCpuVerGet() - 
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit CPU Revision
+*
+*******************************************************************************/
+MV_U32 mvOsCpuRevGet( MV_VOID )
+{
+	return ((read_p15_c0() & ARM_ID_REVISION_MASK ) >> ARM_ID_REVISION_OFFS);
+}
+/*******************************************************************************
+* mvOsCpuPartGet() - 
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit CPU Part number
+*
+*******************************************************************************/
+MV_U32 mvOsCpuPartGet( MV_VOID )
+{
+	return ((read_p15_c0() & ARM_ID_PART_NUM_MASK ) >> ARM_ID_PART_NUM_OFFS);
+}
+/*******************************************************************************
+* mvOsCpuArchGet() - 
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit CPU Architicture number
+*
+*******************************************************************************/
+MV_U32 mvOsCpuArchGet( MV_VOID )
+{
+    return ((read_p15_c0() & ARM_ID_ARCH_MASK ) >> ARM_ID_ARCH_OFFS);
+}
+/*******************************************************************************
+* mvOsCpuVarGet() - 
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit CPU Variant number
+*
+*******************************************************************************/
+MV_U32 mvOsCpuVarGet( MV_VOID )
+{
+    return ((read_p15_c0() & ARM_ID_VAR_MASK ) >> ARM_ID_VAR_OFFS);
+}
+/*******************************************************************************
+* mvOsCpuAsciiGet() - 
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit CPU Variant number
+*
+*******************************************************************************/
+MV_U32 mvOsCpuAsciiGet( MV_VOID )
+{
+    return ((read_p15_c0() & ARM_ID_ASCII_MASK ) >> ARM_ID_ASCII_OFFS);
+}
+
+
+
+/*
+static unsigned long read_p15_c0 (void)
+*/
+/* read co-processor 15, register #0 (ID register) */
+static MV_U32 read_p15_c0 (void)
+{
+	MV_U32 value;
+
+	__asm__ __volatile__(
+		"mrc	p15, 0, %0, c0, c0, 0   @ read control reg\n"
+		: "=r" (value)
+		:
+		: "memory");
+
+	return value;
+}
+
diff --git a/arch/arm/plat-feroceon/linux_oss/mvOs.h b/arch/arm/plat-feroceon/linux_oss/mvOs.h
new file mode 100755
index 0000000..634fb39
--- /dev/null
+++ b/arch/arm/plat-feroceon/linux_oss/mvOs.h
@@ -0,0 +1,542 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#ifndef _MV_OS_LNX_H_
+#define _MV_OS_LNX_H_
+
+#ifdef __KERNEL__
+/* for kernel space */
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/hardirq.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+
+#include <linux/random.h>
+
+#include "dbg-trace.h"
+
+extern void mv_early_printk(char *fmt, ...);
+
+#define MV_ASM              __asm__ __volatile__
+#define INLINE              inline
+#define _INIT				__init
+#define MV_TRC_REC	        TRC_REC
+#define mvOsPrintf          printk
+#define mvOsEarlyPrintf	    mv_early_printk
+#define mvOsOutput          printk
+#define mvOsSPrintf         sprintf
+#define mvOsMalloc(_size_)  kmalloc(_size_, GFP_ATOMIC)
+#define mvOsFree            kfree
+#define mvOsMemcpy          memcpy
+#define mvOsMemset          memset
+#define mvOsSleep(_mils_)   mdelay(_mils_)
+#define mvOsTaskLock()
+#define mvOsTaskUnlock()
+#define strtol              simple_strtoul
+#define mvOsDelay(x)        mdelay(x)
+#define mvOsUDelay(x)       udelay(x)
+#define mvCopyFromOs        copy_from_user
+#define mvCopyToOs          copy_to_user
+#define mvOsWarning()       WARN_ON(1)
+#define mvOsGetTicks()      jiffies
+#define mvOsGetTicksFreq()  HZ
+
+#include "mvTypes.h"
+#include "mvCommon.h"
+
+#ifdef MV_NDEBUG
+#define mvOsAssert(cond)
+#else
+#define mvOsAssert(cond) { do { if (!(cond)) { BUG(); } } while (0); }
+#endif /* MV_NDEBUG */
+
+#else /* __KERNEL__ */
+
+/* for user space applications */
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#define INLINE inline
+#define mvOsPrintf printf
+#define mvOsOutput printf
+#define mvOsMalloc(_size_) malloc(_size_)
+#define mvOsFree free
+#define mvOsAssert(cond) assert(cond)
+
+#endif /* __KERNEL__ */
+
+#define mvOsIoVirtToPhy(pDev, pVirtAddr)        virt_to_dma((pDev), (pVirtAddr))
+/*    pci_map_single((pDev), (pVirtAddr), 0, PCI_DMA_BIDIRECTIONAL) */
+
+#define mvOsIoVirtToPhys(pDev, pVirtAddr)       virt_to_dma((pDev), (pVirtAddr))
+
+#define mvOsCacheFlushInv(pDev, p, size)                            \
+	pci_map_single((pDev), (p), (size), PCI_DMA_BIDIRECTIONAL)
+/*
+ * This was omitted because as of 2.6.35 the Biderection performs only
+ * flush for outer cache because of the speculative issues.
+ * This should be replaced by Flush then invalidate
+ *
+#define mvOsCacheClear(pDev, p, size )                              \
+	pci_map_single((pDev), (p), (size), PCI_DMA_BIDIRECTIONAL)
+*/
+
+#define mvOsCacheFlush(pDev, p, size)                              \
+	pci_map_single((pDev), (p), (size), PCI_DMA_TODEVICE)
+
+#define mvOsCacheInvalidate(pDev, p, size)                          \
+	pci_map_single((pDev), (p), (size), PCI_DMA_FROMDEVICE)
+
+#define mvOsCacheUnmap(pDev, phys, size)                          \
+	pci_unmap_single((pDev), (dma_addr_t)(phys), (size), PCI_DMA_FROMDEVICE)
+
+#define CPU_PHY_MEM(x)              (MV_U32)x
+#define CPU_MEMIO_CACHED_ADDR(x)    (void *)x
+#define CPU_MEMIO_UNCACHED_ADDR(x)  (void *)x
+
+
+/* CPU architecture dependent 32, 16, 8 bit read/write IO addresses */
+#define MV_MEMIO32_WRITE(addr, data)    \
+	((*((volatile unsigned int *)(addr))) = ((unsigned int)(data)))
+
+#define MV_MEMIO32_READ(addr)           \
+	((*((volatile unsigned int *)(addr))))
+
+#define MV_MEMIO16_WRITE(addr, data)    \
+	((*((volatile unsigned short *)(addr))) = ((unsigned short)(data)))
+
+#define MV_MEMIO16_READ(addr)           \
+	((*((volatile unsigned short *)(addr))))
+
+#define MV_MEMIO8_WRITE(addr, data)     \
+	((*((volatile unsigned char *)(addr))) = ((unsigned char)(data)))
+
+#define MV_MEMIO8_READ(addr)            \
+	((*((volatile unsigned char *)(addr))))
+
+
+/* No Fast Swap implementation (in assembler) for ARM */
+#define MV_32BIT_LE_FAST(val)            MV_32BIT_LE(val)
+#define MV_16BIT_LE_FAST(val)            MV_16BIT_LE(val)
+#define MV_32BIT_BE_FAST(val)            MV_32BIT_BE(val)
+#define MV_16BIT_BE_FAST(val)            MV_16BIT_BE(val)
+
+/* 32 and 16 bit read/write in big/little endian mode */
+
+/* 16bit write in little endian mode */
+#define MV_MEMIO_LE16_WRITE(addr, data) \
+	MV_MEMIO16_WRITE(addr, MV_16BIT_LE_FAST(data))
+
+/* 16bit read in little endian mode */
+static inline MV_U16 MV_MEMIO_LE16_READ(MV_U32 addr)
+{
+	MV_U16 data;
+
+	data = (MV_U16)MV_MEMIO16_READ(addr);
+
+	return (MV_U16)MV_16BIT_LE_FAST(data);
+}
+
+/* 32bit write in little endian mode */
+#define MV_MEMIO_LE32_WRITE(addr, data) \
+	MV_MEMIO32_WRITE(addr, MV_32BIT_LE_FAST(data))
+
+/* 32bit read in little endian mode */
+static inline MV_U32 MV_MEMIO_LE32_READ(MV_U32 addr)
+{
+	MV_U32 data;
+
+	data = (MV_U32)MV_MEMIO32_READ(addr);
+
+	return (MV_U32)MV_32BIT_LE_FAST(data);
+}
+
+static inline void mvOsBCopy(char *srcAddr, char *dstAddr, int byteCount)
+{
+	while (byteCount != 0) {
+		*dstAddr = *srcAddr;
+		dstAddr++;
+		srcAddr++;
+		byteCount--;
+	}
+}
+
+static INLINE MV_U64 mvOsDivMod64(MV_U64 divided, MV_U64 divisor, MV_U64 *modulu)
+{
+	MV_U64  division = 0;
+
+	if (divisor == 1)
+		return divided;
+
+	while (divided >= divisor) {
+		division++;
+		divided -= divisor;
+	}
+	if (modulu != NULL)
+		*modulu = divided;
+
+	return division;
+}
+
+#if defined(MV_BRIDGE_SYNC_REORDER)
+extern MV_U32 *mvUncachedParam;
+
+static inline void mvOsBridgeReorderWA(void)
+{
+	volatile MV_U32 val = 0;
+
+	val = mvUncachedParam[0];
+}
+#endif
+
+
+/* Flash APIs */
+#define MV_FL_8_READ            MV_MEMIO8_READ
+#define MV_FL_16_READ           MV_MEMIO_LE16_READ
+#define MV_FL_32_READ           MV_MEMIO_LE32_READ
+#define MV_FL_8_DATA_READ       MV_MEMIO8_READ
+#define MV_FL_16_DATA_READ      MV_MEMIO16_READ
+#define MV_FL_32_DATA_READ      MV_MEMIO32_READ
+#define MV_FL_8_WRITE           MV_MEMIO8_WRITE
+#define MV_FL_16_WRITE          MV_MEMIO_LE16_WRITE
+#define MV_FL_32_WRITE          MV_MEMIO_LE32_WRITE
+#define MV_FL_8_DATA_WRITE      MV_MEMIO8_WRITE
+#define MV_FL_16_DATA_WRITE     MV_MEMIO16_WRITE
+#define MV_FL_32_DATA_WRITE     MV_MEMIO32_WRITE
+
+
+/* CPU cache information */
+#define CPU_I_CACHE_LINE_SIZE   32    /* 2do: replace 32 with linux core macro */
+#define CPU_D_CACHE_LINE_SIZE   32    /* 2do: replace 32 with linux core macro */
+
+/* Support both 2.6.30.x and 2.6.22 LSP's */
+/* Dummy - not needed in s/w cache coherency */
+#define mvOsCacheIoSync()
+
+/*************************************/
+/* FLUSH & INVALIDATE single D$ line */
+/*************************************/
+#if defined(CONFIG_L2_CACHE_ENABLE) || defined(CONFIG_CACHE_FEROCEON_L2)
+#define mvOsCacheLineFlushInv(handle, addr)                     \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c14, 1" : : "r" (addr));\
+	__asm__ __volatile__ ("mcr p15, 1, %0, c15, c10, 1" : : "r" (addr));\
+	__asm__ __volatile__ ("mcr p15, 0, r0, c7, c10, 4");		\
+}
+#elif defined(CONFIG_CACHE_AURORA_L2)
+#define mvOsCacheLineFlushInv(handle, addr)                     \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c14, 1" : : "r" (addr));  /* Clean and Inv D$ by MVA to PoC */ \
+	writel(__virt_to_phys((int)(((int)addr) & ~0x1f)), (INTER_REGS_BASE + MV_AURORA_L2_REGS_OFFSET + 0x7F0)); /*L2_FLUSH_PA*/ \
+	writel(0x0, (INTER_REGS_BASE + MV_AURORA_L2_REGS_OFFSET + 0x700)); /*L2_SYNC*/ \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (addr)); /* DSB */ \
+}
+#else
+#define mvOsCacheLineFlushInv(handle, addr)                     \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c14, 1" : : "r" (addr));\
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (addr)); \
+}
+#endif
+
+/*****************************/
+/* INVALIDATE single D$ line */
+/*****************************/
+#if defined(CONFIG_L2_CACHE_ENABLE) || defined(CONFIG_CACHE_FEROCEON_L2)
+#define mvOsCacheLineInv(handle, addr)                          \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c6, 1" : : "r" (addr)); \
+	__asm__ __volatile__ ("mcr p15, 1, %0, c15, c11, 1" : : "r" (addr)); \
+}
+#elif defined(CONFIG_CACHE_AURORA_L2)
+#define mvOsCacheLineInv(handle, addr)                          \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c6, 1" : : "r" (addr)); /* Invalidate D$ by MVA to PoC */ \
+	writel(__virt_to_phys(((int)addr) & ~0x1f), (INTER_REGS_BASE + MV_AURORA_L2_REGS_OFFSET + 0x770)); /*L2_INVALIDATE_PA*/ \
+	writel(0x0, (INTER_REGS_BASE + MV_AURORA_L2_REGS_OFFSET + 0x700)); /*L2_SYNC*/ \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (addr));  /* DSB */ \
+}
+#else
+#define mvOsCacheLineInv(handle, addr)                          \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c6, 1" : : "r" (addr)); \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (addr)); \
+}
+#endif
+
+/************************/
+/* FLUSH single D$ line */
+/************************/
+#if defined(CONFIG_L2_CACHE_ENABLE) || defined(CONFIG_CACHE_FEROCEON_L2)
+#define mvOsCacheLineFlush(handle, addr)                     \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 1" : : "r" (addr));\
+	__asm__ __volatile__ ("mcr p15, 1, %0, c15, c9, 1" : : "r" (addr));\
+	__asm__ __volatile__ ("mcr p15, 0, r0, c7, c10, 4");          \
+}
+#elif defined(CONFIG_CACHE_AURORA_L2)
+#define mvOsCacheLineFlush(handle, addr)                     \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 1" : : "r" (addr)); /* Clean D$ line by MVA to PoC */ \
+
+	writel(__virt_to_phys(((int)addr) & ~0x1f), (INTER_REGS_BASE + MV_AURORA_L2_REGS_OFFSET + 0x7B0)); /*L2_CLEAN_PA*/ \
+	writel(0x0, (INTER_REGS_BASE + MV_AURORA_L2_REGS_OFFSET + 0x700)); /*L2_SYNC*/ \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (addr)); /* DSB */ \
+}
+#else
+#define mvOsCacheLineFlush(handle, addr)                     \
+{                                                               \
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 1" : : "r" (addr));\
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (addr)); \
+}
+#endif
+
+#define MV_OS_CACHE_MULTI_THRESH	256
+
+/* Flush multiple cache lines using mvOsCacheLineFlush to improve performance.              */
+/* addr is the pointer to start the flush operation from. It will be aligned to             */
+/* the beginning of the cache line automatically and the size will be adjusted accordingly. */
+static inline void mvOsCacheMultiLineFlush(void *handle, void *addr, int size)
+{
+	if (size <= MV_OS_CACHE_MULTI_THRESH) {
+		int shift = ((MV_ULONG)(addr) & (CPU_D_CACHE_LINE_SIZE - 1));
+		if (shift) {
+			addr -= shift; /* align address back to the beginning of a cache line */
+			size += shift;
+		}
+		while (size > 0) {
+			mvOsCacheLineFlush(handle, addr);
+			size -= CPU_D_CACHE_LINE_SIZE;
+			addr += CPU_D_CACHE_LINE_SIZE;
+		}
+	} else
+		pci_map_single(handle, addr, size, PCI_DMA_TODEVICE);
+}
+
+/* Invalidate multiple cache lines using mvOsCacheLineInv to improve performance.           */
+/* addr is the pointer to start the invalidate operation from. It will be aligned to        */
+/* the beginning of the cache line automatically and the size will be adjusted accordingly. */
+/* IMPORTANT: this function assumes the invalidate operation on partial lines does not      */
+/* interfere with the data written there.                                                   */
+/* DO NOT USE this function unless you are certain of this!                                 */
+static inline void mvOsCacheMultiLineInv(void *handle, void *addr, int size)
+{
+	if (size <= MV_OS_CACHE_MULTI_THRESH) {
+		int shift = ((MV_ULONG)(addr) & (CPU_D_CACHE_LINE_SIZE - 1));
+		if (shift) {
+			addr -= shift; /* align address back to the beginning of a cache line */
+			size += shift;
+		}
+		while (size > 0) {
+			mvOsCacheLineInv(handle, addr);
+			size -= CPU_D_CACHE_LINE_SIZE;
+			addr += CPU_D_CACHE_LINE_SIZE;
+		}
+	} else
+		pci_map_single(handle, addr, size, PCI_DMA_FROMDEVICE);
+}
+
+/* Flush and invalidate multiple cache lines using mvOsCacheLineFlushInv to improve performance. */
+/* addr is the pointer to start the flush and invalidate operation from. It will be aligned to   */
+/* the beginning of the cache line automatically and the size will be adjusted accordingly.      */
+static inline void mvOsCacheMultiLineFlushInv(void *handle, void *addr, int size)
+{
+	if (size <= MV_OS_CACHE_MULTI_THRESH) {
+		int shift = ((MV_ULONG)(addr) & (CPU_D_CACHE_LINE_SIZE - 1));
+		if (shift) {
+			addr -= shift; /* align address back to the beginning of a cache line */
+			size += shift;
+		}
+		while (size > 0) {
+			mvOsCacheLineFlushInv(handle, addr);
+			size -= CPU_D_CACHE_LINE_SIZE;
+			addr += CPU_D_CACHE_LINE_SIZE;
+		}
+	} else
+		pci_map_single(handle, addr, size, PCI_DMA_BIDIRECTIONAL);
+}
+
+static inline void mvOsPrefetch(const void *ptr)
+{
+#ifdef CONFIG_USE_DSP
+	__asm__ __volatile__(
+		"pld\t%0"
+		:
+		: "o" (*(char *)ptr)
+		: "cc");
+#else
+	return;
+#endif
+}
+
+
+/* Flush CPU pipe */
+#define CPU_PIPE_FLUSH
+
+
+
+
+
+/* register manipulations  */
+
+/******************************************************************************
+* This debug function enable the write of each register that u-boot access to
+* to an array in the DRAM, the function record only MV_REG_WRITE access.
+* The function could not be operate when booting from flash.
+* In order to print the array we use the printreg command.
+******************************************************************************/
+/* #define REG_DEBUG */
+#if defined(REG_DEBUG)
+extern int reg_arry[2048][2];
+extern int reg_arry_index;
+#endif
+
+/* Marvell controller register read/write macros */
+#define MV_REG_VALUE(offset)          \
+	(MV_MEMIO32_READ((INTER_REGS_BASE | (offset))))
+
+#define MV_REG_READ(offset)             \
+	(MV_MEMIO_LE32_READ(INTER_REGS_BASE | (offset)))
+
+#if defined(REG_DEBUG)
+#define MV_REG_WRITE(offset, val)    \
+	MV_MEMIO_LE32_WRITE((INTER_REGS_BASE | (offset)), (val)); \
+	{ \
+		reg_arry[reg_arry_index][0] = (INTER_REGS_BASE | (offset));\
+		reg_arry[reg_arry_index][1] = (val);\
+		reg_arry_index++;\
+	}
+#else
+#define MV_REG_WRITE(offset, val)    \
+	MV_MEMIO_LE32_WRITE((INTER_REGS_BASE | (offset)), (val))
+#endif
+
+#define MV_REG_BYTE_READ(offset)        \
+	(MV_MEMIO8_READ((INTER_REGS_BASE | (offset))))
+
+#if defined(REG_DEBUG)
+#define MV_REG_BYTE_WRITE(offset, val)  \
+	MV_MEMIO8_WRITE((INTER_REGS_BASE | (offset)), (val)); \
+	{ \
+		reg_arry[reg_arry_index][0] = (INTER_REGS_BASE | (offset));\
+		reg_arry[reg_arry_index][1] = (val);\
+		reg_arry_index++;\
+	}
+#else
+#define MV_REG_BYTE_WRITE(offset, val)  \
+	MV_MEMIO8_WRITE((INTER_REGS_BASE | (offset)), (val))
+#endif
+
+#if defined(REG_DEBUG)
+#define MV_REG_BIT_SET(offset, bitMask)                 \
+	(MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \
+	(MV_MEMIO32_READ(INTER_REGS_BASE | (offset)) | \
+	MV_32BIT_LE_FAST(bitMask)))); \
+	{ \
+		reg_arry[reg_arry_index][0] = (INTER_REGS_BASE | (offset));\
+		reg_arry[reg_arry_index][1] = (MV_MEMIO32_READ(INTER_REGS_BASE | (offset)));\
+		reg_arry_index++;\
+	}
+#else
+#define MV_REG_BIT_SET(offset, bitMask)                 \
+	(MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \
+	(MV_MEMIO32_READ(INTER_REGS_BASE | (offset)) | \
+	MV_32BIT_LE_FAST(bitMask))))
+#endif
+
+#if defined(REG_DEBUG)
+#define MV_REG_BIT_RESET(offset, bitMask)                \
+	(MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \
+	(MV_MEMIO32_READ(INTER_REGS_BASE | (offset)) & \
+	MV_32BIT_LE_FAST(~bitMask)))); \
+	{ \
+		reg_arry[reg_arry_index][0] = (INTER_REGS_BASE | (offset));\
+		reg_arry[reg_arry_index][1] = (MV_MEMIO32_READ(INTER_REGS_BASE | (offset)));\
+		reg_arry_index++;\
+	}
+#else
+#define MV_REG_BIT_RESET(offset, bitMask)                \
+		(MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \
+		(MV_MEMIO32_READ(INTER_REGS_BASE | (offset)) & \
+		MV_32BIT_LE_FAST(~bitMask))))
+#endif
+
+/* Assembly functions */
+
+/*
+** MV_ASM_READ_CPU_EXTRA_FEATURES
+** Read Marvell extra features register.
+*/
+#define MV_ASM_READ_EXTRA_FEATURES(x) __asm__ volatile("mrc  p15, 1, %0, c15, c1, 0" : "=r" (x));
+
+/*
+** MV_ASM_WAIT_FOR_INTERRUPT
+** Wait for interrupt.
+*/
+#define MV_ASM_WAIT_FOR_INTERRUPT      __asm__ volatile("mcr  p15, 0, r0, c7, c0, 4");
+
+
+/* ARM architecture APIs */
+MV_U32  mvOsCpuRevGet(MV_VOID);
+MV_U32  mvOsCpuPartGet(MV_VOID);
+MV_U32  mvOsCpuArchGet(MV_VOID);
+MV_U32  mvOsCpuVarGet(MV_VOID);
+MV_U32  mvOsCpuAsciiGet(MV_VOID);
+
+/*  Other APIs  */
+void *mvOsIoCachedMalloc(void *osHandle, MV_U32 size, MV_ULONG *pPhyAddr, MV_U32 *memHandle);
+void *mvOsIoUncachedMalloc(void *osHandle, MV_U32 size, MV_ULONG *pPhyAddr, MV_U32 *memHandle);
+void mvOsIoUncachedFree(void *osHandle, MV_U32 size, MV_ULONG phyAddr, void *pVirtAddr, MV_U32 memHandle);
+void mvOsIoCachedFree(void *osHandle, MV_U32 size, MV_ULONG phyAddr, void *pVirtAddr, MV_U32 memHandle);
+int  mvOsRand(void);
+
+#endif /* _MV_OS_LNX_H_ */
+
+
diff --git a/arch/arm/plat-feroceon/linux_oss/mvOsSata.h b/arch/arm/plat-feroceon/linux_oss/mvOsSata.h
new file mode 100755
index 0000000..c925a9e
--- /dev/null
+++ b/arch/arm/plat-feroceon/linux_oss/mvOsSata.h
@@ -0,0 +1,158 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvOsLinux.h - O.S. interface header file for Linux  
+*
+* DESCRIPTION:
+*       This header file contains OS dependent definition under Linux
+*
+* DEPENDENCIES:
+*       Linux kernel header files.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1.1 $
+*******************************************************************************/
+
+#ifndef __INCmvOsLinuxh
+#define __INCmvOsLinuxh
+
+/* Includes */
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include "mvOs.h"
+
+
+/* Definitions */
+#define MV_DEFAULT_QUEUE_DEPTH 2
+#define MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION
+#define MV_SATA_SUPPORT_GEN2E_128_QUEUE_LEN
+
+#ifdef CONFIG_MV88F6082
+ #define MV_SATA_OVERRIDE_SW_QUEUE_SIZE
+ #define MV_SATA_REQUESTED_SW_QUEUE_SIZE 2
+ #undef MV_SATA_SUPPORT_GEN2E_128_QUEUE_LEN
+#endif
+
+/* System dependent macro for flushing CPU write cache */
+#if defined (MV_BRIDGE_SYNC_REORDER)
+#define MV_CPU_WRITE_BUFFER_FLUSH()	do {	\
+						wmb();	\
+						mvOsBridgeReorderWA();	\
+					} while (0)
+#else
+#define MV_CPU_WRITE_BUFFER_FLUSH()     wmb()
+#endif /* CONFIG_MV78XX0 */
+
+/* System dependent little endian from / to CPU conversions */
+#define MV_CPU_TO_LE16(x)   cpu_to_le16(x)
+#define MV_CPU_TO_LE32(x)   cpu_to_le32(x)
+
+#define MV_LE16_TO_CPU(x)   le16_to_cpu(x)
+#define MV_LE32_TO_CPU(x)   le32_to_cpu(x)
+
+#ifdef __BIG_ENDIAN_BITFIELD
+#define MV_BIG_ENDIAN_BITFIELD
+#endif
+
+/* System dependent register read / write in byte/word/dword variants */
+#define MV_REG_WRITE_BYTE(base, offset, val)    writeb(val, base + offset)
+#define MV_REG_WRITE_WORD(base, offset, val)    writew(val, base + offset)
+#define MV_REG_WRITE_DWORD(base, offset, val)   writel(val, base + offset)
+#define MV_REG_READ_BYTE(base, offset)          readb(base + offset)
+#define MV_REG_READ_WORD(base, offset)          readw(base + offset)
+#define MV_REG_READ_DWORD(base, offset)         readl(base + offset)
+
+
+/* Typedefs    */
+
+/* System dependant typedefs */
+typedef void            *MV_VOID_PTR;
+typedef u32             *MV_U32_PTR;
+typedef u16             *MV_U16_PTR;
+typedef u8              *MV_U8_PTR;
+typedef char            *MV_CHAR_PTR;
+typedef void            *MV_BUS_ADDR_T;
+typedef unsigned long   MV_CPU_FLAGS;
+
+
+/* Structures  */
+/* System dependent structure */
+typedef struct mvOsSemaphore
+{
+  int notUsed;
+} MV_OS_SEMAPHORE;
+
+
+/* Functions (User implemented)*/
+
+/* Semaphore init, take and release */
+#define mvOsSemInit(x) MV_TRUE
+#define mvOsSemTake(x)
+#define mvOsSemRelease(x)
+
+/* Interrupt masking and unmasking functions */
+MV_CPU_FLAGS mvOsSaveFlagsAndMaskCPUInterrupts(MV_VOID);
+MV_VOID      mvOsRestoreFlags(MV_CPU_FLAGS);
+
+/* Delay function in micro seconds resolution */
+void mvMicroSecondsDelay(MV_VOID_PTR, MV_U32);
+
+/* Typedefs    */
+typedef enum mvBoolean
+{
+    MV_SFALSE, MV_STRUE
+} MV_BOOLEAN;
+
+/* System logging function */
+#include "mvLog.h"
+/* Enable READ/WRITE Long SCSI command only when driver is compiled for debugging */
+#ifdef MV_LOGGER
+#define MV_SATA_SUPPORT_READ_WRITE_LONG
+#endif
+
+#define MV_IAL_LOG_ID       3
+
+#endif /* __INCmvOsLinuxh */
diff --git a/arch/arm/plat-feroceon/msi.c b/arch/arm/plat-feroceon/msi.c
new file mode 100644
index 0000000..aae30bb
--- /dev/null
+++ b/arch/arm/plat-feroceon/msi.c
@@ -0,0 +1,124 @@
+/*
+ * arch/arm/plat-feroceon/msi.c
+ *
+ * Marvell KW2 SoC MSI, MSI-X handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include "mvOs.h"
+
+static DECLARE_BITMAP(msi_irq_in_use, NR_MSI_IRQS);
+
+void msi_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int b;
+	unsigned long status;
+
+	/* Read Inbound Doorbell (Host-to-CPU) register and
+	 * call ISR for each active interrupt.
+	 */
+	/* status = MV_REG_READ(MV_IN_DRBELL_CAUSE_REG) & 0xFFFF0000; */
+	status = MV_REG_READ(MV_IN_DRBELL_CAUSE_REG);
+	if (!status)
+		return;
+
+	b = find_first_bit(&status, 32);
+
+	/* write back to clear bit (to acknowledge interrupt) */
+	MV_REG_WRITE(MV_IN_DRBELL_CAUSE_REG, ~(1 << b));
+	status = MV_REG_READ(MV_IN_DRBELL_CAUSE_REG);
+
+	generic_handle_irq(IRQ_MSI_START + b);
+}
+
+void __init kw2_msi_init(void)
+{
+	unsigned long temp;
+
+	set_irq_chained_handler(IN_DRBELL_IRQ_NUM, msi_irq_handler);
+
+	/* Unmask private doorbells 16-31 */
+	/* temp = MV_REG_READ(MV_IN_DRBELL_MASK_REG) | (0xFFFF0000); */
+	temp = MV_REG_READ(MV_IN_DRBELL_MASK_REG) | 0xFFFFFFFF;
+	MV_REG_WRITE(MV_IN_DRBELL_MASK_REG, temp);
+}
+
+/*
+ * Dynamic irq allocation and deallocation
+ */
+int create_irq(void)
+{
+	int irq, pos;
+
+again:
+	pos = find_first_zero_bit(msi_irq_in_use, NR_MSI_IRQS);
+	irq = IRQ_MSI_START + pos;
+	if (irq > NR_IRQS)
+		return -ENOSPC;
+	/* test_and_set_bit operates on 32-bits at a time */
+	if (test_and_set_bit(pos, msi_irq_in_use))
+		goto again;
+
+	dynamic_irq_init(irq);
+	/* irq_clear_status_flags(irq, IRQ_NOREQUEST); */
+	irq_desc[irq].status |= IRQ_LEVEL;
+	set_irq_flags(irq, IRQF_VALID);
+
+	return irq;
+}
+
+void destroy_irq(unsigned int irq)
+{
+	int pos = irq - IRQ_MSI_START;
+	dynamic_irq_cleanup(irq);
+	clear_bit(pos, msi_irq_in_use);
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	destroy_irq(irq);
+}
+
+static void msi_nop(unsigned int irq)
+{
+	return;
+}
+
+struct irq_chip msi_irq_chip = {
+	.name			= "kw2_msi_irq",
+	.ack			= msi_nop,
+	.enable			= unmask_msi_irq,
+	.disable		= mask_msi_irq,
+	.mask			= mask_msi_irq,
+	.unmask			= unmask_msi_irq,
+};
+
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+	int irq;
+	int msi_irq;
+	struct msi_msg msg;
+
+	irq = create_irq();
+	if (irq < 0)
+		return irq;
+	set_irq_msi(irq, desc);
+
+	msi_irq = irq - IRQ_MSI_START;
+
+	msg.address_hi = 0x0;
+	msg.address_lo = (INTER_REGS_BASE | MV_IN_DRBELL_CAUSE_REG);
+	msg.data = (0x1 << msi_irq);
+
+	write_msi_msg(irq, &msg);
+	set_irq_chip_and_handler(irq, &msi_irq_chip, handle_edge_irq);
+
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/Makefile
new file mode 100755
index 0000000..fbc00f0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/Makefile
@@ -0,0 +1,11 @@
+#

+# Makefile for the Marvell Audio ALSA Device Driver

+#

+ifeq ($(CONFIG_ARCH_FEROCEON),y)

+	include $(srctree)/$(MACHINE)/config/mvRules.mk

+endif

+

+obj-$(CONFIG_SND_MRVL_AUDIO) += snd-mv88fx.o

+#snd-mv88fx-objs		     += mv_snd.o ../../../../../sound/arm/devdma.o

+snd-mv88fx-objs		     += mv88fx-pcm.o  cs42l51-hal.o mv88fx-hal.o #../../../../../sound/arm/devdma.o

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/cs42l51-hal.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/cs42l51-hal.c
new file mode 100755
index 0000000..7416632
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/cs42l51-hal.c
@@ -0,0 +1,178 @@
+/*

+ *

+ *	Marvell Orion Alsa Sound driver

+ *

+ *	Author: Maen Suleiman

+ *	Copyright (C) 2008 Marvell Ltd.

+ *

+ *

+ * This program is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License version 2 as

+ * published by the Free Software Foundation.

+ *

+ */

+#include <linux/ioport.h>

+#include <linux/interrupt.h>

+#include <sound/driver.h>

+#include <linux/platform_device.h>

+#include <linux/init.h>

+#include <linux/slab.h>

+#include <linux/version.h>

+#include <sound/core.h>

+#include <sound/initval.h>

+#include <sound/control.h>

+#include <sound/pcm.h>

+#include <sound/asoundef.h>

+#include <sound/asound.h>

+

+#include "twsi/mvTwsi.h"

+#include "audio/dac/mvCLAudioCodec.h"

+#include "boardEnv/mvBoardEnvLib.h"

+

+

+

+/*

+ * Initialize the audio decoder.

+ */

+int

+cs42l51_init(void)

+{

+    MV_AUDIO_CODEC_DEV codec_params;

+    unsigned char reg_data;

+    

+

+    codec_params.ADCMode = MV_I2S_MODE;

+    codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;

+    codec_params.twsiSlave.moreThen256 = MV_FALSE;

+    codec_params.twsiSlave.validOffset = MV_TRUE;

+    codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet();

+    codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet();

+    if(mvCLAudioCodecInit(&codec_params) == MV_FALSE)

+    {

+        printk("Error - Cannot initialize audio decoder.at address =0x%x",

+				codec_params.twsiSlave.slaveAddr.address);

+        return -1;

+    }

+

+    /* Use the signal processor.               */

+    mvCLAudioCodecRegSet(&codec_params,0x9,0x40);

+    

+    /* Unmute PCM-A & PCM-B and set default      */

+    mvCLAudioCodecRegSet(&codec_params,0x10,0x60);

+    mvCLAudioCodecRegSet(&codec_params,0x11,0x60);

+

+    /* default for AOUTx*/

+    mvCLAudioCodecRegSet(&codec_params,0x16,0x05);

+    mvCLAudioCodecRegSet(&codec_params,0x17,0x05);

+

+    /* swap channels */

+    mvCLAudioCodecRegSet(&codec_params,0x18,0xff);

+    if (0) {

+	    int i;

+	    for (i=1; i<= 0x21 ; i++) {

+		    reg_data = mvCLAudioCodecRegGet(&codec_params,i);

+		    printk("CLS reg=0x%02x val=0x%02x\n",i,reg_data);

+	    }

+	    

+    }

+    

+    return 0;

+}

+

+#define MVAUD_NUM_VOLUME_STEPS  (40)

+static MV_U8 auddec_volume_mapping[MVAUD_NUM_VOLUME_STEPS] =

+{

+	0x19,	0xB2,	0xB7,	0xBD,	0xC3,	0xC9,	0xCF,	0xD5,

+	0xD8,	0xE1,	0xE7,	0xED,	0xF3,	0xF9,	0xFF,	0x00,	

+	0x01,	0x02,	0x03,	0x04,	0x05,	0x06,	0x07,	0x08,	

+	0x09,	0x0A,	0x0B,	0x0C,	0x0D,	0x0E,	0x0F,	0x10,	

+	0x11,	0x12,	0x13,	0x14,	0x15,	0x16,	0x17,	0x18

+};

+

+

+/*

+ * Get the audio decoder volume for both channels.

+ * 0 is lowest volume, MVAUD_NUM_VOLUME_STEPS-1 is the highest volume.

+ */

+

+void

+cs42l51_vol_get(MV_U8 *vol_list)

+{

+    MV_AUDIO_CODEC_DEV  codec_params;

+    MV_U8   reg_data;

+    MV_U32  i;

+    MV_U32  vol_idx;

+

+    codec_params.ADCMode = MV_I2S_MODE;

+    codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;

+    codec_params.twsiSlave.moreThen256 = MV_FALSE;

+    codec_params.twsiSlave.validOffset = MV_TRUE;

+	codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet();

+	codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet();

+

+

+    for(vol_idx = 0; vol_idx < 2; vol_idx++)

+    {

+        reg_data = mvCLAudioCodecRegGet(&codec_params,0x16 + vol_idx);

+

+       /*printk("\tVolume was get: 0x%x.\n",

+                                reg_data);*/

+

+        /* Look for the index that mapps to this dB value.  */

+        for(i = 0; i < MVAUD_NUM_VOLUME_STEPS; i++)

+        {

+		if (reg_data == auddec_volume_mapping[i])

+			break;

+		if (( auddec_volume_mapping[i] > auddec_volume_mapping[MVAUD_NUM_VOLUME_STEPS-1]) 

+					&& (reg_data > auddec_volume_mapping[i]) 

+					&& (reg_data < auddec_volume_mapping[i+1]))

+			break;

+		 

+        }

+

+        vol_list[vol_idx] = i;

+       /*printk("\tvol_list[%d] = %d.\n",vol_idx,

+                                vol_list[vol_idx]);*/

+

+    }

+

+    return;

+}

+

+

+/*

+ * Set the audio decoder volume for both channels.

+ * 0 is lowest volume, MVAUD_NUM_VOLUME_STEPS-1 is the highest volume.

+ */

+void

+cs42l51_vol_set(MV_U8 *vol_list)

+{

+    MV_AUDIO_CODEC_DEV  codec_params;

+    MV_U32  vol_idx;

+

+    codec_params.ADCMode = MV_I2S_MODE;

+    codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;

+    codec_params.twsiSlave.moreThen256 = MV_FALSE;

+    codec_params.twsiSlave.validOffset = MV_TRUE;

+    codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet();

+    codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet();

+

+   

+    for(vol_idx = 0; vol_idx < 2; vol_idx++)

+    {

+        /*printk("\tvol_list[%d] = %d.\n",vol_idx,

+                                vol_list[vol_idx]);*/

+

+        if(vol_list[vol_idx] >= MVAUD_NUM_VOLUME_STEPS)

+		vol_list[vol_idx] = MVAUD_NUM_VOLUME_STEPS -1;

+

+        mvCLAudioCodecRegSet(&codec_params,0x16 + vol_idx,

+                             auddec_volume_mapping[vol_list[vol_idx]]);

+

+        /*printk("\tVolume was set to 0x%x.\n",

+                                auddec_volume_mapping[vol_list[vol_idx]]);*/

+    }

+

+    return;

+}

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-hal.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-hal.c
new file mode 100755
index 0000000..0dd0b2d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-hal.c
@@ -0,0 +1,342 @@
+/*

+ *

+ *	Marvell Orion Alsa Sound driver

+ *

+ *	Author: Maen Suleiman

+ *	Copyright (C) 2008 Marvell Ltd.

+ *

+ *

+ * This program is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License version 2 as

+ * published by the Free Software Foundation.

+ *

+ */

+

+#include <linux/ioport.h>

+#include <linux/interrupt.h>

+#include <sound/driver.h>

+#include <linux/platform_device.h>

+#include <linux/init.h>

+#include <linux/slab.h>

+#include <linux/version.h>

+#include <sound/core.h>

+#include <sound/initval.h>

+#include <sound/control.h>

+#include <sound/pcm.h>

+#include <sound/asoundef.h>

+#include <sound/asound.h>

+#include <asm/dma.h>

+#include <asm/io.h>

+#include <asm/scatterlist.h>

+#include <asm/sizes.h>

+

+#include "mv88fx-pcm.h"

+/*#define AUDIO_REG_BASE	0x0*/

+#include "audio/mvAudio.h"

+#include "ctrlEnv/sys/mvSysAudio.h"

+

+int cs42l51_init(void);

+

+int mv88fx_snd_hw_init(struct mv88fx_snd_chip	*chip)

+{

+	if((chip->audio_info->i2s_rec) || (chip->audio_info->i2s_play)) {

+	/* Clear ints */

+	cs42l51_init();

+	}

+		

+        mv88fx_snd_writel(chip, MV_AUDIO_INT_CAUSE_REG(0), 0xffffffff);

+        mv88fx_snd_writel(chip, MV_AUDIO_INT_MASK_REG(0), 0);

+        mv88fx_snd_writel(chip, MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG(0), 

+				0);

+	

+	if (MV_OK != mvAudioInit())

+		return EIO;

+

+        /* Disable all playback/recording */

+	mv88fx_snd_bitreset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),

+			    (APCR_PLAY_I2S_ENABLE_MASK | 

+			     APCR_PLAY_SPDIF_ENABLE_MASK));

+

+	mv88fx_snd_bitreset(chip, MV_AUDIO_RECORD_CTRL_REG(0),

+			    (ARCR_RECORD_SPDIF_EN_MASK | 

+			     ARCR_RECORD_I2S_EN_MASK));

+	

+	if (MV_OK != mvSPDIFRecordTclockSet(0)) {

+		mv88fx_snd_debug("Marvell ALSA driver ERR. mvSPDIFRecordTclockSet failed\n");

+                return -ENOMEM;

+	}

+

+        return 0;

+}

+

+int mv88fx_snd_hw_playback_set(struct mv88fx_snd_chip	*chip)

+{

+        struct mv88fx_snd_stream *audio_stream = 

+		chip->stream[PLAYBACK]; 

+	struct snd_pcm_substream *substream = audio_stream->substream;

+	struct snd_pcm_runtime *runtime = substream->runtime;

+        

+	MV_AUDIO_PLAYBACK_CTRL	pcm_play_ctrl;

+	MV_I2S_PLAYBACK_CTRL	i2s_play_ctrl;

+	MV_SPDIF_PLAYBACK_CTRL	spdif_play_ctrl;

+	MV_AUDIO_FREQ_DATA 	dco_ctrl;

+

+

+	dco_ctrl.offset = chip->dco_ctrl_offst;

+	

+	switch(audio_stream->rate) {

+	case 44100:

+		dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH;

+		break;

+	case 48000:

+		dco_ctrl.baseFreq = AUDIO_FREQ_48KH;

+		break;

+	case 96000:

+		dco_ctrl.baseFreq = AUDIO_FREQ_96KH;

+		break;

+	default:

+		snd_printk("Requested rate %d is not supported\n", 

+				runtime->rate); return -1;

+	}

+

+	pcm_play_ctrl.burst = (chip->burst == 128)?AUDIO_128BYTE_BURST:

+				AUDIO_32BYTE_BURST;

+	

+	pcm_play_ctrl.loopBack = chip->loopback;

+	

+	if (audio_stream->stereo) {

+		pcm_play_ctrl.monoMode = AUDIO_PLAY_MONO_OFF;

+	}

+	else {

+		switch (audio_stream->mono_mode) {

+		case MONO_LEFT:

+			pcm_play_ctrl.monoMode = AUDIO_PLAY_LEFT_MONO;

+			break;

+		case MONO_RIGHT:

+			pcm_play_ctrl.monoMode = AUDIO_PLAY_RIGHT_MONO;

+			break;

+		case MONO_BOTH:

+		default:

+			pcm_play_ctrl.monoMode = AUDIO_PLAY_BOTH_MONO;

+			break;

+		}

+	}

+	

+	if (audio_stream->format == SAMPLE_16IN16) {

+		pcm_play_ctrl.sampleSize = SAMPLE_16BIT;

+		i2s_play_ctrl.sampleSize = SAMPLE_16BIT;

+	}

+	else if (audio_stream->format == SAMPLE_24IN32) {

+		pcm_play_ctrl.sampleSize = SAMPLE_24BIT;

+		i2s_play_ctrl.sampleSize = SAMPLE_24BIT;

+		

+	}

+	else if (audio_stream->format == SAMPLE_32IN32) {

+		pcm_play_ctrl.sampleSize = SAMPLE_32BIT;

+		i2s_play_ctrl.sampleSize = SAMPLE_32BIT;

+	}

+	else {

+		snd_printk("Requested format %d is not supported\n", runtime->format);

+		return -1;

+	}

+

+	/* buffer and period sizes in frame */

+	pcm_play_ctrl.bufferPhyBase = audio_stream->dma_addr;

+	pcm_play_ctrl.bufferSize = audio_stream->dma_size;

+	pcm_play_ctrl.intByteCount = audio_stream->period_size;

+

+	/* I2S playback streem stuff */

+	/*i2s_play_ctrl.sampleSize = pcm_play_ctrl.sampleSize;*/

+	i2s_play_ctrl.justification = I2S_JUSTIFIED;

+	i2s_play_ctrl.sendLastFrame = 0;

+

+	spdif_play_ctrl.nonPcm = MV_FALSE;

+	

+	spdif_play_ctrl.validity = chip->ch_stat_valid;

+

+	if (audio_stream->stat_mem) {

+		spdif_play_ctrl.userBitsFromMemory = MV_TRUE;

+		spdif_play_ctrl.validityFromMemory = MV_TRUE;

+		spdif_play_ctrl.blockStartInternally = MV_FALSE;

+	} else {

+		spdif_play_ctrl.userBitsFromMemory = MV_FALSE;

+		spdif_play_ctrl.validityFromMemory = MV_FALSE;

+		spdif_play_ctrl.blockStartInternally = MV_TRUE;

+	}

+

+	/* If this is non-PCM sound, mute I2S channel */

+	spin_lock_irq(&chip->reg_lock);

+

+	if (!(mv88fx_snd_readl(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0)) & 

+			(APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))) {

+

+	if (MV_OK != mvAudioDCOCtrlSet(0, &dco_ctrl)) {

+		snd_printk("Failed to initialize DCO clock control.\n");

+		return -1;

+	}

+	}

+

+	if (audio_stream->clock_src == DCO_CLOCK)

+		while ((mv88fx_snd_readl(chip, MV_AUDIO_SPCR_DCO_STATUS_REG(0)) & 

+			ASDSR_DCO_LOCK_MASK) == 0);

+	else if (audio_stream->clock_src == SPCR_CLOCK)

+		while ((mv88fx_snd_readl(chip, MV_AUDIO_SPCR_DCO_STATUS_REG(0)) & 

+			ASDSR_SPCR_LOCK_MASK) == 0);

+			

+	if (MV_OK != mvAudioPlaybackControlSet(0, &pcm_play_ctrl)) {

+		snd_printk("Failed to initialize PCM playback control.\n");

+		return -1;

+	}

+

+	if (MV_OK != mvI2SPlaybackCtrlSet(0, &i2s_play_ctrl)) {

+		snd_printk("Failed to initialize I2S playback control.\n");

+		return -1;

+	}

+

+	mvSPDIFPlaybackCtrlSet(0, &spdif_play_ctrl);

+

+	spin_unlock_irq(&chip->reg_lock);

+

+#if 0 

+	mv88fx_snd_debug("runtime->xfer_align=%d\n",(int)runtime->xfer_align);

+	mv88fx_snd_debug("runtime->format=%d\n",runtime->format);

+	mv88fx_snd_debug("runtime->channels=%d\n",runtime->channels);

+	mv88fx_snd_debug("runtime->rate=%d\n",runtime->rate);

+	mv88fx_snd_debug("runtime->dma_addr=0x%x\n",runtime->dma_addr);

+

+	mv88fx_snd_debug("runtime->dma_area=0x%x\n",(unsigned int)runtime->dma_area);

+	mv88fx_snd_debug("runtime->frame_bits=0x%x\n",runtime->frame_bits);

+	mv88fx_snd_debug("runtime->period_size=0x%x\n",

+		   (unsigned int)runtime->period_size);

+	mv88fx_snd_debug("runtime->buffer_size=0x%x\n",

+		   (unsigned int)runtime->buffer_size); 

+	mv88fx_snd_debug("bufferPhyBase=0x%x\n",runtime->dma_addr);

+	mv88fx_snd_debug("bufferSize=0x%x\n",pcm_play_ctrl.bufferSize);

+	mv88fx_snd_debug("intByteCount=0x%x.\n",pcm_play_ctrl.intByteCount);

+

+#endif

+	

+	return 0;

+}

+

+

+int mv88fx_snd_hw_capture_set(struct mv88fx_snd_chip	*chip)

+{

+        struct mv88fx_snd_stream *audio_stream = 

+		chip->stream[CAPTURE]; 

+	struct snd_pcm_substream *substream = audio_stream->substream;

+	struct snd_pcm_runtime *runtime = substream->runtime;

+	

+	MV_AUDIO_RECORD_CTRL 	pcm_rec_ctrl;

+	MV_I2S_RECORD_CTRL	i2s_rec_ctrl;

+	MV_AUDIO_FREQ_DATA	dco_ctrl;

+

+

+	dco_ctrl.offset = chip->dco_ctrl_offst;

+

+	switch(audio_stream->rate) {

+	case 44100:

+		dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH;

+		break;

+	case 48000:

+		dco_ctrl.baseFreq = AUDIO_FREQ_48KH;

+		break;

+	case 96000:

+		dco_ctrl.baseFreq = AUDIO_FREQ_96KH;

+		break;

+	default:

+		snd_printk("Requested rate %d is not supported\n", 

+				runtime->rate); return -1;

+	}

+	

+	pcm_rec_ctrl.burst = (chip->burst == 128)?AUDIO_128BYTE_BURST:

+				AUDIO_32BYTE_BURST;

+

+	if (audio_stream->format == SAMPLE_16IN16) {

+		pcm_rec_ctrl.sampleSize = SAMPLE_16BIT;

+	}

+	else if (audio_stream->format == SAMPLE_24IN32) {

+		pcm_rec_ctrl.sampleSize = SAMPLE_24BIT;

+	}

+	else if (audio_stream->format == SAMPLE_32IN32) {

+		pcm_rec_ctrl.sampleSize = SAMPLE_32BIT;

+	}

+	else {

+		snd_printk("Requested format %d is not supported\n", runtime->format);

+		return -1;

+	}

+

+	pcm_rec_ctrl.mono = (audio_stream->stereo) ? MV_FALSE : MV_TRUE;

+

+	if (pcm_rec_ctrl.mono) {

+		switch (audio_stream->mono_mode) {

+		case MONO_LEFT:

+			pcm_rec_ctrl.monoChannel = AUDIO_REC_LEFT_MONO;

+			break;

+		default:

+		case MONO_RIGHT:

+			pcm_rec_ctrl.monoChannel = AUDIO_REC_RIGHT_MONO;

+			break;

+		}

+		

+	}

+	else pcm_rec_ctrl.monoChannel = AUDIO_REC_LEFT_MONO;

+		

+

+	pcm_rec_ctrl.bufferPhyBase = audio_stream->dma_addr;

+	pcm_rec_ctrl.bufferSize = audio_stream->dma_size;

+	

+	pcm_rec_ctrl.intByteCount = audio_stream->period_size;

+

+	/* I2S record streem stuff */

+	i2s_rec_ctrl.sample = pcm_rec_ctrl.sampleSize;

+	i2s_rec_ctrl.justf = I2S_JUSTIFIED;

+

+	spin_lock_irq(&chip->reg_lock);

+

+	/* set clock only if record is not enabled*/

+	if (!(mv88fx_snd_readl(chip, MV_AUDIO_RECORD_CTRL_REG(0)) & 

+			(ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK))) {

+

+	if (MV_OK != mvAudioDCOCtrlSet(0, &dco_ctrl)) {

+		snd_printk("Failed to initialize DCO clock control.\n");

+		return -1;

+	}

+	}

+	

+	if (MV_OK != mvAudioRecordControlSet(0, &pcm_rec_ctrl)) {

+		snd_printk("Failed to initialize PCM record control.\n");

+		return -1;

+	}

+

+	if (MV_OK != mvI2SRecordCntrlSet(0, &i2s_rec_ctrl)) {

+		snd_printk("Failed to initialize I2S record control.\n");

+		return -1;

+	}

+	spin_unlock_irq(&chip->reg_lock);

+

+#if 0

+

+	mv88fx_snd_debug("pcm_rec_ctrl.bufferSize=0x%x\n",(int)pcm_rec_ctrl.bufferSize);

+	mv88fx_snd_debug("pcm_rec_ctrl.intByteCount=0x%x\n",(int)pcm_rec_ctrl.intByteCount);

+

+	mv88fx_snd_debug("runtime->xfer_align=%d\n",(int)runtime->xfer_align);

+	mv88fx_snd_debug("runtime->format=%d\n",runtime->format);

+	mv88fx_snd_debug("runtime->channels=%d\n",runtime->channels);

+	mv88fx_snd_debug("runtime->rate=%d\n",runtime->rate);

+	mv88fx_snd_debug("runtime->dma_addr=0x%x\n",runtime->dma_addr);

+

+	mv88fx_snd_debug("runtime->dma_area=0x%x\n",(unsigned int)runtime->dma_area);

+	mv88fx_snd_debug("runtime->frame_bits=0x%x\n",runtime->frame_bits);

+	mv88fx_snd_debug("runtime->period_size=0x%x\n",

+		   (unsigned int)runtime->period_size);

+	mv88fx_snd_debug("runtime->buffer_size=0x%x\n",

+		   (unsigned int)runtime->buffer_size); 

+	mv88fx_snd_debug("bufferPhyBase=0x%x\n",runtime->dma_addr);

+

+#endif

+	

+

+	return 0;

+

+}

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-pcm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-pcm.c
new file mode 100755
index 0000000..6c764f0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-pcm.c
@@ -0,0 +1,1678 @@
+/*
+ *
+ *	Marvell Orion Alsa Sound driver
+ *
+ *	Author: Maen Suleiman
+ *	Copyright (C) 2008 Marvell Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <sound/driver.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/asoundef.h>
+#include <sound/asound.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <asm/sizes.h>
+#include "mv88fx-pcm.h"
+/*#define AUDIO_REG_BASE	0x0*/
+#include "audio/mvAudioRegs.h"
+
+
+int mv88fx_snd_hw_init(struct mv88fx_snd_chip	*chip);
+int mv88fx_snd_hw_playback_set(struct mv88fx_snd_chip	*chip);
+int mv88fx_snd_hw_capture_set(struct mv88fx_snd_chip	*chip);
+
+struct mv88fx_snd_chip	*chip = NULL;
+/*
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+*/
+int test_memory(struct mv88fx_snd_chip *chip,
+		unsigned int base,
+		unsigned int size)
+{
+	unsigned int i;
+
+	for (i=0; i<6; i++) {
+
+		/* check if we get to end */
+		if ((chip->audio_info->mem_array[i].base == 0) && 
+		   (chip->audio_info->mem_array[i].size == 0)) 
+			break;
+
+		/* check if we fit into one memory window only */
+		if ((base >= chip->audio_info->mem_array[i].base) &&
+		   ((base + size) <=  chip->audio_info->mem_array[i].base + chip->audio_info->mem_array[i].size))
+			return 1;
+
+	}
+
+	return 0;
+}
+
+/*
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+*/
+
+
+
+void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+
+	if (runtime->dma_area == NULL)
+		return;
+
+	if (buf != &substream->dma_buffer) {
+		kfree(runtime->dma_buffer_p);
+	}
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+}
+
+int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); 
+
+	int ret = 0;
+
+	if (buf) {
+		if (buf->bytes >= size) {
+			mv88fx_snd_debug(KERN_ERR "devdma_hw_alloc:buf->bytes >= size\n");
+			goto out;
+		}
+		devdma_hw_free(dev, substream);
+	}
+
+	if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
+		buf = &substream->dma_buffer;
+	} else {
+		buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
+		if (!buf) {
+			mv88fx_snd_debug(KERN_ERR "devdma_hw_alloc:buf == NULL\n");
+			goto nomem;
+		}
+
+		buf->dev.type = SNDRV_DMA_TYPE_DEV;
+		buf->dev.dev = dev;
+		buf->area = audio_stream->area;
+		buf->addr = audio_stream->addr;
+		buf->bytes = size;
+		buf->private_data = NULL;
+
+		if (!buf->area) {
+			mv88fx_snd_debug(KERN_ERR "devdma_hw_alloc:buf->area == NULL\n");
+			goto free;
+		}
+	}
+	snd_pcm_set_runtime_buffer(substream, buf);
+	ret = 1;
+ out:
+	runtime->dma_bytes = size;
+	return ret;
+
+ free:
+	kfree(buf);
+ nomem:
+	return -ENOMEM;
+}
+
+int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+}
+
+
+/*
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+*/
+
+/*
+ * hw preparation for spdif
+ */
+
+
+static int mv88fx_snd_spdif_mask_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int mv88fx_snd_spdif_mask_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.iec958.status[0] = 0xff;
+	ucontrol->value.iec958.status[1] = 0xff;
+	ucontrol->value.iec958.status[2] = 0xff;
+	ucontrol->value.iec958.status[3] = 0xff;
+	return 0;
+}
+
+static struct snd_kcontrol_new mv88fx_snd_spdif_mask  =
+{
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+	.info =		mv88fx_snd_spdif_mask_info,
+	.get =		mv88fx_snd_spdif_mask_get,
+};
+
+static int mv88fx_snd_spdif_stream_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int mv88fx_snd_spdif_stream_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
+	int i,word;
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	spin_lock_irq(&chip->reg_lock);
+	for (word=0 ; word < 4; word++) {
+		chip->stream[PLAYBACK]->spdif_status[word] = 
+		mv88fx_snd_readl(chip,
+				 MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(0, word));
+		for (i = 0; i < 4; i++)
+			ucontrol->value.iec958.status[word + i] = 
+			(chip->stream[PLAYBACK]->spdif_status[word] >>
+								(i * 8)) & 0xff;
+
+	}
+	spin_unlock_irq(&chip->reg_lock);
+	return 0;
+}
+
+static int mv88fx_snd_spdif_stream_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
+	int i, change =0 , word;
+	unsigned int val;
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+        val = 0;
+	spin_lock_irq(&chip->reg_lock);
+	for (word=0 ; word < 4; word++) {
+		for (i = 0; i < 4; i++){
+                        chip->stream[PLAYBACK]->spdif_status[word] |= 
+			ucontrol->value.iec958.status[word + i] << (i * 8);
+		}
+		 mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(0, word),
+			chip->stream[PLAYBACK]->spdif_status[word]);
+		 
+		 mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(0, word),
+			chip->stream[PLAYBACK]->spdif_status[word]);
+
+	}
+	
+	if (chip->stream[PLAYBACK]->spdif_status[0] & IEC958_AES0_NONAUDIO) {
+                chip->pcm_mode = NON_PCM;
+	}
+	spin_unlock_irq(&chip->reg_lock);
+	return change;
+}
+
+static struct snd_kcontrol_new mv88fx_snd_spdif_stream  =
+{
+	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | 
+			SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
+	.info =		mv88fx_snd_spdif_stream_info,
+	.get =		mv88fx_snd_spdif_stream_get,
+	.put =		mv88fx_snd_spdif_stream_put
+};
+
+
+static int mv88fx_snd_spdif_default_info(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_info *uinfo)
+{
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int mv88fx_snd_spdif_default_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
+	int i,word;
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	spin_lock_irq(&chip->reg_lock);
+	for (word=0 ; word < 4; word++) {
+		chip->stream_defaults[PLAYBACK]->spdif_status[word] = 
+		mv88fx_snd_readl(chip,
+				 MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(0, word));
+		
+                for (i = 0; i < 4; i++)
+			ucontrol->value.iec958.status[word + i] = 
+			(chip->stream_defaults[PLAYBACK]->spdif_status[word] >> 
+								(i * 8)) & 0xff;
+
+	}
+	spin_unlock_irq(&chip->reg_lock);
+	return 0;
+}
+
+static int mv88fx_snd_spdif_default_put(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
+	int i, change = 0, word;
+	unsigned int val;
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+        val = 0;
+	spin_lock_irq(&chip->reg_lock);
+	for (word=0 ; word < 4; word++) {
+		for (i = 0; i < 4; i++){
+                        chip->stream_defaults[PLAYBACK]->spdif_status[word] |= 
+			ucontrol->value.iec958.status[word + i] << (i * 8);
+		}
+		 mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(0, word),
+			chip->stream_defaults[PLAYBACK]->spdif_status[word]);
+		 mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(0, word),
+			chip->stream_defaults[PLAYBACK]->spdif_status[word]);
+		 
+		 
+	}
+	if (chip->stream_defaults[PLAYBACK]->spdif_status[0] & 
+				IEC958_AES0_NONAUDIO) {
+		chip->pcm_mode = NON_PCM;
+	}
+	
+	spin_unlock_irq(&chip->reg_lock);
+	return change;
+}
+static struct snd_kcontrol_new mv88fx_snd_spdif_default __devinitdata =
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+	.info =		mv88fx_snd_spdif_default_info,
+	.get =		mv88fx_snd_spdif_default_get,
+	.put =		mv88fx_snd_spdif_default_put
+};
+
+
+
+
+/*
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+*/
+void cs42l51_vol_get(unsigned char *vol_list);
+void cs42l51_vol_set(unsigned char *vol_list);
+
+unsigned char mv88fx_snd_vol[2];
+
+static int mv88fx_snd_mixer_vol_info(struct snd_kcontrol *kcontrol, 
+			       struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 39;
+	return 0;
+}
+
+static int mv88fx_snd_mixer_vol_get(struct snd_kcontrol *kcontrol, 
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	cs42l51_vol_get(mv88fx_snd_vol);
+	ucontrol->value.integer.value[0] = (long)mv88fx_snd_vol[0];
+	ucontrol->value.integer.value[1] = (long)mv88fx_snd_vol[1];
+	return 0;
+}
+
+static int mv88fx_snd_mixer_vol_put(struct snd_kcontrol *kcontrol, 
+				    struct snd_ctl_elem_value *ucontrol) {
+	
+	mv88fx_snd_vol[0] = (unsigned char)ucontrol->value.integer.value[0];
+	mv88fx_snd_vol[1] = (unsigned char)ucontrol->value.integer.value[1];
+	cs42l51_vol_set(mv88fx_snd_vol);
+
+	return 0;
+}
+
+static struct snd_kcontrol_new mv88fx_snd_dac_vol =
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =		"Playback DAC Volume",
+	.info =		mv88fx_snd_mixer_vol_info,
+	.get =		mv88fx_snd_mixer_vol_get,
+	.put =		mv88fx_snd_mixer_vol_put
+};
+
+
+/*
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+*/
+
+
+struct mv88fx_snd_mixer_enum {
+	char 	**names;	/* enum names*/
+	int	*values;	/* values to be updated*/
+	int 	count;		/* number of elements */
+	void*	rec;		/* field to be updated*/
+};
+
+
+int mv88fx_snd_mixer_enum_info (struct snd_kcontrol * kcontrol, 
+			       struct snd_ctl_elem_info * uinfo)
+{
+	struct mv88fx_snd_mixer_enum	*mixer_enum = 
+		(struct mv88fx_snd_mixer_enum*)kcontrol->private_value;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = mixer_enum->count;
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+
+	strcpy(uinfo->value.enumerated.name,
+	       mixer_enum->names[uinfo->value.enumerated.item]);
+
+	return 0;
+}
+int mv88fx_snd_mixer_enum_get (struct snd_kcontrol * kcontrol, 
+			      struct snd_ctl_elem_value * ucontrol)
+{
+	struct mv88fx_snd_mixer_enum	*mixer_enum = 
+		(struct mv88fx_snd_mixer_enum*)kcontrol->private_value;
+	int i;
+	unsigned int val;
+
+	val = *(unsigned int*)mixer_enum->rec;
+	
+	for (i=0 ; i<mixer_enum->count ; i++) {
+		
+		if (val ==  (unsigned int)mixer_enum->values[i]) {
+			ucontrol->value.enumerated.item[0] = i;
+			break;
+		}
+	}
+	
+	return 0;
+}
+
+int mv88fx_snd_mixer_enum_put (struct snd_kcontrol * kcontrol, 
+			      struct snd_ctl_elem_value * ucontrol)
+{
+	unsigned int val,*rec;
+	struct mv88fx_snd_mixer_enum	*mixer_enum = 
+		(struct mv88fx_snd_mixer_enum*)kcontrol->private_value;
+	int i;
+
+	rec = (unsigned int*)mixer_enum->rec;
+	val = ucontrol->value.enumerated.item[0];
+
+	if (val < 0)
+		val = 0;
+	if (val > mixer_enum->count)
+		val = mixer_enum->count;
+
+	for (i=0 ; i<mixer_enum->count ; i++) {
+
+		if (val ==  i) {
+			*rec = (unsigned int)mixer_enum->values[i];
+			break;
+		}
+	}
+	
+	return 0;
+}
+
+
+
+#define MV88FX_PCM_MIXER_ENUM(xname, xindex, value)	\
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .info = mv88fx_snd_mixer_enum_info, \
+  .get = mv88fx_snd_mixer_enum_get, \
+  .put = mv88fx_snd_mixer_enum_put, \
+  .private_value = (unsigned long)value,	\
+}
+
+char *playback_src_mixer_names[] = {"SPDIF","I2S", "SPDIF And I2S"};
+int playback_src_mixer_values[] = { SPDIF, I2S, (SPDIF|I2S)};
+
+struct mv88fx_snd_mixer_enum playback_src_mixer	= 
+{
+	.names	= playback_src_mixer_names,
+	.values	= playback_src_mixer_values,
+	.count	= 3,
+};
+
+char *playback_mono_mixer_names[] = {"Mono Both","Mono Left", "Mono Right"};
+int playback_mono_mixer_values[] = { MONO_BOTH, MONO_LEFT, MONO_RIGHT};
+
+struct mv88fx_snd_mixer_enum playback_mono_mixer	= 
+{
+	.names	= playback_mono_mixer_names,
+	.values	= playback_mono_mixer_values,
+	.count	= 3,
+};
+
+
+
+
+char *capture_src_mixer_names[] = {"SPDIF","I2S"};
+int capture_src_mixer_values[] = { SPDIF, I2S};
+
+struct mv88fx_snd_mixer_enum capture_src_mixer	= 
+{
+	.names	= capture_src_mixer_names,
+	.values	= capture_src_mixer_values,
+	.count	= 2,
+};
+
+char *capture_mono_mixer_names[] = {"Mono Left", "Mono Right"};
+int capture_mono_mixer_values[] = { MONO_LEFT, MONO_RIGHT};
+
+struct mv88fx_snd_mixer_enum capture_mono_mixer	= 
+{
+	.names	= capture_mono_mixer_names,
+	.values	= capture_mono_mixer_values,
+	.count	= 2,
+};
+
+
+static struct snd_kcontrol_new mv88fx_snd_mixers[] = {
+	MV88FX_PCM_MIXER_ENUM("Playback output type", 0,
+				    &playback_src_mixer), 
+
+	MV88FX_PCM_MIXER_ENUM("Playback mono type", 0,
+				    &playback_mono_mixer), 
+
+	MV88FX_PCM_MIXER_ENUM("Capture input Type", 0,
+				    &capture_src_mixer),
+	
+	MV88FX_PCM_MIXER_ENUM("Capture mono type", 0,
+				    &capture_mono_mixer), 
+
+};
+
+#define	PLAYBACK_MIX_INDX	0
+#define PLAYBACK_MONO_MIX_INDX	1
+#define CAPTURE_MIX_INDX	2
+#define	CAPTURE_MONO_MIX_INDX	3
+
+static int
+mv88fx_snd_ctrl_new(struct snd_card *card)
+{
+	int err=0;
+
+	playback_src_mixer.rec = &chip->stream_defaults[PLAYBACK]->dig_mode;
+	playback_mono_mixer.rec = &chip->stream_defaults[PLAYBACK]->mono_mode;
+	
+	capture_src_mixer.rec = &chip->stream_defaults[CAPTURE]->dig_mode;
+	capture_mono_mixer.rec = &chip->stream_defaults[CAPTURE]->mono_mode;
+
+	if((chip->audio_info->i2s_play) && (chip->audio_info->spdif_play)) {
+		err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_mixers[PLAYBACK_MIX_INDX],
+						     chip));
+		if (err < 0)
+			return err;
+	}
+
+	err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_mixers[PLAYBACK_MONO_MIX_INDX],
+						     chip));
+	if (err < 0)
+		return err;
+
+	if((chip->audio_info->i2s_rec) && (chip->audio_info->spdif_rec)) {
+		err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_mixers[CAPTURE_MIX_INDX],
+							     chip));
+		if (err < 0)
+			return err;
+	}
+	
+	err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_mixers[CAPTURE_MONO_MIX_INDX],
+						     chip));
+	if (err < 0)
+		return err;
+
+	if(chip->audio_info->i2s_play) {
+	err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_dac_vol,
+					     chip));
+	if (err < 0)
+		return err;
+	}
+		
+	err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_mask,
+					     chip));
+	if (err < 0)
+		return err;
+
+	err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_default,
+					     chip));
+	if (err < 0)
+		return err;
+
+	err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_stream,
+					     chip));
+	if (err < 0)
+		return err;
+	
+	
+
+	return err;
+}
+
+
+/*
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+*/
+
+
+
+static struct snd_pcm_hardware mv88fx_snd_capture_hw =
+{
+	.info =			(SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_MMAP |
+				 SNDRV_PCM_INFO_MMAP_VALID |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_PAUSE ), 
+	.formats =		(SNDRV_PCM_FMTBIT_S16_LE |
+				 SNDRV_PCM_FMTBIT_S24_LE |
+				 SNDRV_PCM_FMTBIT_S32_LE),
+	.rates =		(SNDRV_PCM_RATE_44100 |
+				 SNDRV_PCM_RATE_48000 |
+				 SNDRV_PCM_RATE_96000),
+	.rate_min =		44100,
+	.rate_max =		96000,
+	.channels_min =		1,
+	.channels_max =		2,
+	.buffer_bytes_max =	(16*1024*1024),
+	.period_bytes_min =	MV88FX_SND_MIN_PERIOD_BYTES,
+	.period_bytes_max =	MV88FX_SND_MAX_PERIOD_BYTES,
+	.periods_min =		MV88FX_SND_MIN_PERIODS,
+	.periods_max =		MV88FX_SND_MAX_PERIODS,
+	.fifo_size =		0,
+
+};
+
+
+
+static int
+mv88fx_snd_capture_open(struct snd_pcm_substream * substream)
+{
+	int err;
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	chip->stream_defaults[CAPTURE]->substream = substream;
+	chip->stream_defaults[CAPTURE]->direction = CAPTURE;
+	substream->private_data = chip->stream_defaults[CAPTURE];
+	substream->runtime->hw = mv88fx_snd_capture_hw;
+
+	if (chip->stream_defaults[CAPTURE]->dig_mode & SPDIF) {
+		substream->runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_S32_LE;
+	}
+	
+	/* check if playback is already running with specific rate */
+	if (chip->stream[PLAYBACK]->rate) {
+		switch 	(chip->stream[PLAYBACK]->rate) {
+			case 44100:
+				substream->runtime->hw.rates = SNDRV_PCM_RATE_44100;
+				break;
+			case 48000:
+				substream->runtime->hw.rates = SNDRV_PCM_RATE_48000;
+				break;
+			case 96000:
+				substream->runtime->hw.rates = SNDRV_PCM_RATE_96000;
+				break;
+
+		}
+	}
+	
+	
+	err = snd_pcm_hw_constraint_minmax(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+					   chip->burst * 2, 
+					   AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
+        if (err < 0)
+                return err;
+	
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+					 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+					 chip->burst); 
+        if (err < 0)
+                return err;
+	
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0, 
+					 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+					 chip->burst);
+        if (err < 0)
+                return err;
+
+	err = snd_pcm_hw_constraint_minmax(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_PERIODS,
+					   MV88FX_SND_MIN_PERIODS, 
+					   MV88FX_SND_MAX_PERIODS);
+        if (err < 0)
+                return err;
+	
+        err = snd_pcm_hw_constraint_integer(substream->runtime, 
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+        if (err < 0)
+                return err;
+        
+	return 0;
+
+}
+
+static int
+mv88fx_snd_capture_close(struct snd_pcm_substream * substream)
+{
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	chip->stream_defaults[CAPTURE]->substream = NULL;
+	memset(chip->stream[CAPTURE] , 
+		0, 
+		sizeof(struct mv88fx_snd_stream));
+
+	return 0;
+}
+static int
+mv88fx_snd_capture_hw_params(struct snd_pcm_substream * substream,
+					struct snd_pcm_hw_params* params)
+{
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); int err = 0; 
+	
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	
+        err = devdma_hw_alloc(audio_stream->dev, substream,
+			      params_buffer_bytes(params));
+	return err;
+}
+
+static int
+mv88fx_snd_capture_hw_free(struct snd_pcm_substream * substream)
+{
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); 
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	/*
+	 * Clear out the DMA and any allocated buffers.
+	 */
+	devdma_hw_free(audio_stream->dev, substream);
+	return 0;
+	
+}
+
+static int
+mv88fx_snd_capture_prepare(struct snd_pcm_substream * substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); 
+
+
+	audio_stream->rate = runtime->rate;
+        audio_stream->stereo= (runtime->channels == 1) ? 0 : 1;
+
+	if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
+		audio_stream->format = SAMPLE_16IN16;
+	} else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) {
+		audio_stream->format = SAMPLE_24IN32;
+	} else if (runtime->format == SNDRV_PCM_FORMAT_S32_LE) {
+		audio_stream->format = SAMPLE_32IN32;
+	} else {
+		mv88fx_snd_debug("Requested format %d is not supported\n", 
+			   runtime->format);
+		return -1;
+	}
+
+	/* buffer and period sizes in frame */
+	audio_stream->dma_addr = runtime->dma_addr;
+	audio_stream->dma_size = 
+		frames_to_bytes(runtime, runtime->buffer_size);
+	audio_stream->period_size = 
+		frames_to_bytes(runtime, runtime->period_size);
+
+	memcpy(chip->stream[CAPTURE], 
+	       chip->stream_defaults[CAPTURE],
+	       sizeof(struct mv88fx_snd_stream));
+	return mv88fx_snd_hw_capture_set(chip);
+}
+
+static int
+mv88fx_snd_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); 
+	int result = 0;
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	
+	spin_lock(chip->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* FIXME: should check if busy before */
+
+		/* make sure the dma in pause state*/
+		mv88fx_snd_bitset(chip, MV_AUDIO_RECORD_CTRL_REG(0),
+				  ARCR_RECORD_PAUSE_MASK);
+
+		/* enable interrupt */
+		mv88fx_snd_bitset(chip, MV_AUDIO_INT_MASK_REG(0), 
+				  AICR_RECORD_BYTES_INT);
+
+
+		/* enable dma */
+		if (audio_stream->dig_mode & I2S)
+			mv88fx_snd_bitset(chip, MV_AUDIO_RECORD_CTRL_REG(0),
+					  ARCR_RECORD_I2S_EN_MASK);
+
+		if (audio_stream->dig_mode & SPDIF)
+			mv88fx_snd_bitset(chip, MV_AUDIO_RECORD_CTRL_REG(0),
+					  ARCR_RECORD_SPDIF_EN_MASK);
+
+		/* start dma */
+		mv88fx_snd_bitreset(chip, MV_AUDIO_RECORD_CTRL_REG(0),
+				  ARCR_RECORD_PAUSE_MASK);
+		
+		
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+
+		/* make sure the dma in pause state*/
+		mv88fx_snd_bitset(chip, MV_AUDIO_RECORD_CTRL_REG(0),
+				  ARCR_RECORD_PAUSE_MASK);
+		
+                /* disable interrupt */
+		mv88fx_snd_bitreset(chip, MV_AUDIO_INT_MASK_REG(0), 
+				  AICR_RECORD_BYTES_INT);
+
+		
+		/* always stop both I2S and SPDIF*/
+		mv88fx_snd_bitreset(chip, MV_AUDIO_RECORD_CTRL_REG(0),
+				    (ARCR_RECORD_I2S_EN_MASK | 
+				     ARCR_RECORD_SPDIF_EN_MASK));
+		
+                /* FIXME: should check if busy after */
+		
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		mv88fx_snd_bitset(chip, MV_AUDIO_RECORD_CTRL_REG(0),
+				  ARCR_RECORD_PAUSE_MASK);
+		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		mv88fx_snd_bitreset(chip, MV_AUDIO_RECORD_CTRL_REG(0),
+				    ARCR_RECORD_PAUSE_MASK);
+
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+	spin_unlock(&chip->reg_lock);
+	return result;
+}
+
+
+static snd_pcm_uframes_t 
+mv88fx_snd_capture_pointer(struct snd_pcm_substream * substream)
+{
+	return bytes_to_frames(substream->runtime, 
+			       (ssize_t)mv88fx_snd_readl(chip, 
+		       		MV_AUDIO_RECORD_BUF_BYTE_CNTR_REG(0)));
+}
+
+int 
+mv88fx_snd_capture_mmap(struct snd_pcm_substream *substream, 
+			 struct vm_area_struct *vma)
+{
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	return devdma_mmap(NULL, substream, vma);	
+	
+}
+
+static struct snd_pcm_ops mv88fx_snd_capture_ops = {
+	.open			= mv88fx_snd_capture_open,
+	.close			= mv88fx_snd_capture_close,
+	.ioctl			= snd_pcm_lib_ioctl,
+	.hw_params	        = mv88fx_snd_capture_hw_params,
+	.hw_free	        = mv88fx_snd_capture_hw_free,
+	.prepare		= mv88fx_snd_capture_prepare,
+	.trigger		= mv88fx_snd_capture_trigger,
+	.pointer		= mv88fx_snd_capture_pointer,
+	.mmap 			= mv88fx_snd_capture_mmap,
+};
+
+/*
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+*/
+
+
+
+struct snd_pcm_hardware mv88fx_snd_playback_hw =
+{
+	.info =			(SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_MMAP |
+				 SNDRV_PCM_INFO_MMAP_VALID |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_PAUSE ), 
+	.formats =		(SNDRV_PCM_FMTBIT_S16_LE |
+				 SNDRV_PCM_FMTBIT_S24_LE |
+				 SNDRV_PCM_FMTBIT_S32_LE),
+	.rates =		(SNDRV_PCM_RATE_44100 |
+				 SNDRV_PCM_RATE_48000 |
+				 SNDRV_PCM_RATE_96000),
+	.rate_min =		44100,
+	.rate_max =		96000,
+	.channels_min =		1,
+	.channels_max =		2,
+	.buffer_bytes_max =	(16*1024*1024),
+	.period_bytes_min =	MV88FX_SND_MIN_PERIOD_BYTES,
+	.period_bytes_max =	MV88FX_SND_MAX_PERIOD_BYTES,
+	.periods_min =		MV88FX_SND_MIN_PERIODS,
+	.periods_max =		MV88FX_SND_MAX_PERIODS,
+	.fifo_size =		0,
+
+};
+
+static int
+mv88fx_snd_playback_open(struct snd_pcm_substream * substream)
+{
+	int err = 0; 
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	chip->stream_defaults[PLAYBACK]->substream = substream;
+	chip->stream_defaults[PLAYBACK]->direction = PLAYBACK;
+	substream->private_data = chip->stream_defaults[PLAYBACK];
+	substream->runtime->hw = mv88fx_snd_playback_hw;
+
+	if (chip->stream_defaults[PLAYBACK]->dig_mode & SPDIF) {
+		substream->runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_S32_LE;
+	}
+
+	/* check if capture is already running with specific rate */
+	if (chip->stream[CAPTURE]->rate) {
+		switch 	(chip->stream[CAPTURE]->rate) {
+			case 44100:
+				substream->runtime->hw.rates = SNDRV_PCM_RATE_44100;
+				break;
+			case 48000:
+				substream->runtime->hw.rates = SNDRV_PCM_RATE_48000;
+				break;
+			case 96000:
+				substream->runtime->hw.rates = SNDRV_PCM_RATE_96000;
+				break;
+
+		}
+	}
+
+	err = snd_pcm_hw_constraint_minmax(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+					   chip->burst * 2, 
+					   AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
+        if (err < 0)
+                return err;
+	
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+					 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+					 chip->burst); 
+        if (err < 0)
+                return err;
+	
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0, 
+					 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+					 chip->burst);
+        if (err < 0)
+                return err;
+
+	err = snd_pcm_hw_constraint_minmax(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_PERIODS,
+					   MV88FX_SND_MIN_PERIODS, 
+					   MV88FX_SND_MAX_PERIODS);
+        if (err < 0)
+                return err;
+	
+        err = snd_pcm_hw_constraint_integer(substream->runtime, 
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+
+        if (err < 0)
+                return err;
+        
+	return 0;
+
+}
+
+static int
+mv88fx_snd_playback_close(struct snd_pcm_substream * substream)
+{
+	int i;
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	chip->stream_defaults[PLAYBACK]->substream = NULL;
+
+	chip->pcm_mode = PCM;
+
+	for (i=0; i<4 ; i++) {
+		chip->stream_defaults[PLAYBACK]->spdif_status[i] = 0;
+		chip->stream[PLAYBACK]->spdif_status[i] = 0;
+
+		 mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(0, i),
+			chip->stream_defaults[PLAYBACK]->spdif_status[i]);
+		 mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(0, i),
+			chip->stream_defaults[PLAYBACK]->spdif_status[i]);
+
+	}
+
+	memset(chip->stream[PLAYBACK] , 
+		0, 
+		sizeof(struct mv88fx_snd_stream));
+
+	
+	return 0;
+}
+static int
+mv88fx_snd_playback_hw_params(struct snd_pcm_substream * substream,
+					struct snd_pcm_hw_params* params)
+{
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); int err = 0; 
+	
+	
+        err = devdma_hw_alloc(audio_stream->dev, substream,
+			      params_buffer_bytes(params));
+
+	//mv88fx_snd_debug("=>%s addr=0x%x size=0x%x\n",__FUNCTION__,
+	//	   substream->runtime->dma_addr,
+	//	   frames_to_bytes(substream->runtime, 
+	//			   substream->runtime->buffer_size));
+	
+
+	return err;
+}
+
+static int
+mv88fx_snd_playback_hw_free(struct snd_pcm_substream * substream)
+{
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); 
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	/*
+	 * Clear out the DMA and any allocated buffers.
+	 */
+	devdma_hw_free(audio_stream->dev, substream);
+	return 0;
+	
+}
+
+static int
+mv88fx_snd_playback_prepare(struct snd_pcm_substream * substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); 
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+        if ((audio_stream->dig_mode == I2S) && 
+	    (chip->pcm_mode == NON_PCM))
+		return -1;
+
+	audio_stream->rate = runtime->rate;
+        audio_stream->stereo= (runtime->channels == 1) ? 0 : 1;
+
+	if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
+		audio_stream->format = SAMPLE_16IN16;
+	} else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) {
+		audio_stream->format = SAMPLE_24IN32;
+	} else if (runtime->format == SNDRV_PCM_FORMAT_S32_LE) {
+		audio_stream->format = SAMPLE_32IN32;
+	} else {
+		mv88fx_snd_debug("Requested format %d is not supported\n", 
+			   runtime->format);
+		return -1;
+	}
+
+	/* buffer and period sizes in frame */
+	audio_stream->dma_addr = runtime->dma_addr;
+	audio_stream->dma_size = 
+		frames_to_bytes(runtime, runtime->buffer_size);
+	audio_stream->period_size = 
+		frames_to_bytes(runtime, runtime->period_size);
+
+	memcpy(chip->stream[PLAYBACK], 
+	       chip->stream_defaults[PLAYBACK],
+	       sizeof(struct mv88fx_snd_stream));
+	
+	return mv88fx_snd_hw_playback_set(chip);
+}
+
+static int
+mv88fx_snd_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct mv88fx_snd_stream *audio_stream = 
+		snd_pcm_substream_chip(substream); 
+	int result = 0;
+
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	
+	spin_lock(chip->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* enable interrupt */
+		mv88fx_snd_bitset(chip, MV_AUDIO_INT_MASK_REG(0), 
+				  AICR_PLAY_BYTES_INT);
+
+		/* make sure the dma in pause state*/
+		mv88fx_snd_bitset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),
+				  APCR_PLAY_PAUSE_MASK);
+
+		/* enable dma */
+                if ((audio_stream->dig_mode & I2S) && 
+		    (chip->pcm_mode == PCM))
+			mv88fx_snd_bitset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),
+					  APCR_PLAY_I2S_ENABLE_MASK);
+		
+		if (audio_stream->dig_mode & SPDIF)
+			mv88fx_snd_bitset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),
+					  APCR_PLAY_SPDIF_ENABLE_MASK);
+
+		/* start dma */
+		mv88fx_snd_bitreset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),
+				    APCR_PLAY_PAUSE_MASK);
+		
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		
+                /* disable interrupt */
+		mv88fx_snd_bitreset(chip, MV_AUDIO_INT_MASK_REG(0), 
+				  AICR_PLAY_BYTES_INT);
+
+
+		/* make sure the dma in pause state*/
+		mv88fx_snd_bitset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),
+				  APCR_PLAY_PAUSE_MASK);
+		
+		/* always stop both I2S and SPDIF*/
+		mv88fx_snd_bitreset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),
+				    (APCR_PLAY_I2S_ENABLE_MASK | 
+				     APCR_PLAY_SPDIF_ENABLE_MASK));
+
+		/* check if busy twice*/
+		while (mv88fx_snd_readl(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0)) & 
+		       APCR_PLAY_BUSY_MASK);
+		
+		while (mv88fx_snd_readl(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0)) & 
+		       APCR_PLAY_BUSY_MASK);
+		
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		mv88fx_snd_bitset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),
+				  APCR_PLAY_PAUSE_MASK);
+		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		mv88fx_snd_bitreset(chip, MV_AUDIO_PLAYBACK_CTRL_REG(0),
+				    APCR_PLAY_PAUSE_MASK);
+
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+	spin_unlock(&chip->reg_lock);
+	return result;
+}
+
+
+static snd_pcm_uframes_t 
+mv88fx_snd_playback_pointer(struct snd_pcm_substream * substream)
+{
+	return bytes_to_frames(substream->runtime, 
+			       (ssize_t)mv88fx_snd_readl(chip, 
+		       		MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG(0)));
+}
+
+int 
+mv88fx_snd_playback_mmap(struct snd_pcm_substream *substream, 
+			 struct vm_area_struct *vma)
+{
+	//mv88fx_snd_debug("=>%s\n",__FUNCTION__);
+	return devdma_mmap(NULL, substream, vma);	
+	
+}
+
+
+static struct snd_pcm_ops mv88fx_snd_playback_ops = {
+	.open			= mv88fx_snd_playback_open,
+	.close			= mv88fx_snd_playback_close,
+	.ioctl			= snd_pcm_lib_ioctl,
+	.hw_params	        = mv88fx_snd_playback_hw_params,
+	.hw_free	        = mv88fx_snd_playback_hw_free,
+	.prepare		= mv88fx_snd_playback_prepare,
+	.trigger		= mv88fx_snd_playback_trigger,
+	.pointer		= mv88fx_snd_playback_pointer,
+	.mmap 			= mv88fx_snd_playback_mmap,
+};
+
+
+/*
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+*/
+
+
+static int __init 
+mv88fx_snd_pcm_new(struct snd_card *card)
+{
+	struct snd_pcm *pcm;
+	int err, i;
+
+	mv88fx_snd_debug("=>%s card->dev=0x%x\n",__FUNCTION__, 
+		   (unsigned int)card->dev);
+	
+	if ((err = snd_pcm_new(card, "Marvell mv88fx_snd IEC958 and I2S", 
+			       0, 1, 1, &pcm)) < 0) 
+		return err;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 
+			&mv88fx_snd_playback_ops);
+	
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 
+			&mv88fx_snd_capture_ops);
+	if((chip->audio_info->i2s_play) && (chip->audio_info->spdif_play))	
+	chip->stream_defaults[PLAYBACK]->dig_mode = (SPDIF | I2S);
+	else if((chip->audio_info->i2s_play))
+		chip->stream_defaults[PLAYBACK]->dig_mode = I2S;
+	else if((chip->audio_info->spdif_play))
+		chip->stream_defaults[PLAYBACK]->dig_mode = SPDIF;
+	else
+		chip->stream_defaults[PLAYBACK]->dig_mode = 0;
+	chip->stream_defaults[PLAYBACK]->mono_mode = MONO_BOTH;
+	chip->pcm_mode = PCM;
+	chip->stream_defaults[PLAYBACK]->stat_mem = 0;
+	chip->stream_defaults[PLAYBACK]->clock_src = DCO_CLOCK;
+
+	if((chip->audio_info->i2s_rec))
+	chip->stream_defaults[CAPTURE]->dig_mode = I2S;
+	else if((chip->audio_info->spdif_rec))
+		chip->stream_defaults[CAPTURE]->dig_mode = SPDIF;
+	else
+		chip->stream_defaults[CAPTURE]->dig_mode = 0;
+
+	chip->stream_defaults[CAPTURE]->mono_mode = MONO_LEFT;
+	chip->pcm_mode = PCM;
+	chip->stream_defaults[CAPTURE]->stat_mem = 0;
+	chip->stream_defaults[CAPTURE]->clock_src = DCO_CLOCK;
+
+	for (i=0; i<4 ; i++) {
+		chip->stream_defaults[PLAYBACK]->spdif_status[i] = 0;
+		chip->stream[PLAYBACK]->spdif_status[i] = 0;
+		
+		mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(0, i),
+			chip->stream_defaults[PLAYBACK]->spdif_status[i]);
+		mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(0, i),
+			chip->stream_defaults[PLAYBACK]->spdif_status[i]);
+		mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_USR_BITS_LEFT_REG(0, i),
+			0);
+		mv88fx_snd_writel(chip, 
+			MV_AUDIO_SPDIF_PLAY_USR_BITS_RIGHT_REG(0, i),
+			0);
+		
+	}
+	
+
+	pcm->private_data = chip;
+	pcm->info_flags = 0;
+        strcpy(pcm->name, "Marvell mv88fx_snd IEC958 and I2S");
+
+	return 0;
+}
+
+static irqreturn_t
+mv88fx_snd_interrupt(int irq, void *dev_id)
+{
+	struct mv88fx_snd_chip *chip = dev_id;
+	struct mv88fx_snd_stream *play_stream =
+		chip->stream_defaults[PLAYBACK];
+	struct mv88fx_snd_stream *capture_stream =
+		chip->stream_defaults[CAPTURE];
+	
+			
+	unsigned int status, mask;
+
+	spin_lock(&chip->reg_lock);
+	
+	/* read the active interrupt */
+	mask = mv88fx_snd_readl(chip, MV_AUDIO_INT_MASK_REG(0));
+	status = mv88fx_snd_readl(chip, MV_AUDIO_INT_CAUSE_REG(0)) & mask;
+
+	do {
+	
+
+		if (status & ~(AICR_RECORD_BYTES_INT|AICR_PLAY_BYTES_INT)) {
+	
+	                spin_unlock(&chip->reg_lock);
+			snd_BUG(); /* FIXME: should enable error interrupts*/
+			return IRQ_NONE;
+		}
+	
+		/* acknowledge interrupt */
+		mv88fx_snd_writel(chip, MV_AUDIO_INT_CAUSE_REG(0), status);
+	
+		/* This is record event */
+		if (status & AICR_RECORD_BYTES_INT) {
+	
+			snd_pcm_period_elapsed(capture_stream->substream);
+			//printk("int:capture_stream=0x%x rec_count=0x%x\n",(unsigned int)capture_stream, mv88fx_snd_readl(chip, 
+			  //     		MV_AUDIO_RECORD_BUF_BYTE_CNTR_REG));
+		}
+		/* This is play event */
+		if (status & AICR_PLAY_BYTES_INT) {
+			
+			snd_pcm_period_elapsed(play_stream->substream);
+			//printk("int:play_stream=0x%x rec_count=0x%x\n",(unsigned int)play_stream, mv88fx_snd_readl(chip, 
+			  //     		MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG));
+		
+		}
+	
+		/* read the active interrupt */
+		mask = mv88fx_snd_readl(chip, MV_AUDIO_INT_MASK_REG(0));
+		status = mv88fx_snd_readl(chip, MV_AUDIO_INT_CAUSE_REG(0)) & mask;
+
+	} while(status);
+
+	spin_unlock(&chip->reg_lock);
+
+	return IRQ_HANDLED;
+}
+
+static void 
+mv88fx_snd_free(struct snd_card *card)
+{
+	struct mv88fx_snd_chip *chip = card->private_data;
+
+	mv88fx_snd_debug("=>%s chip=0x%x\n",__FUNCTION__,(unsigned int)chip);
+	
+	/* free irq */
+	free_irq(chip->irq, (void *)chip);
+
+	mv88fx_snd_debug(KERN_ERR "chip->res =0x%x\n", (unsigned int)chip->res);
+
+	if (chip->base)
+		iounmap(chip->base);
+	
+	if (chip->res) 
+		release_resource(chip->res);
+	
+	chip->res = NULL;
+	
+		
+	/* Free memory allocated for streems */
+	if (chip->stream_defaults[PLAYBACK]) {
+		kfree(chip->stream_defaults[PLAYBACK]);
+		chip->stream_defaults[PLAYBACK] = NULL;
+	}
+	if (chip->stream[PLAYBACK]) {
+		kfree(chip->stream[PLAYBACK]);
+		chip->stream[PLAYBACK] = NULL;
+	}	
+	if (chip->stream_defaults[CAPTURE]) {
+		kfree(chip->stream_defaults[CAPTURE]);
+		chip->stream_defaults[CAPTURE] = NULL;
+	}
+	if (chip->stream[CAPTURE]) {
+		kfree(chip->stream[CAPTURE]);
+		chip->stream[CAPTURE] = NULL;
+	}
+
+	if (chip->stream_defaults[PLAYBACK]->area)
+		dma_free_coherent(chip->dev, 
+				MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES, 
+				chip->stream_defaults[PLAYBACK]->area, 
+				chip->stream_defaults[PLAYBACK]->addr);	
+
+	if (chip->stream_defaults[CAPTURE]->area)
+		dma_free_coherent(chip->dev, 
+				MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES, 
+				chip->stream_defaults[CAPTURE]->area, 
+				chip->stream_defaults[CAPTURE]->addr);	
+
+
+	chip = NULL;
+}
+
+static int mv88fx_snd_probe(struct platform_device *dev)
+{
+	int err = 0, irq = NO_IRQ;	
+	struct snd_card *card = NULL;
+	struct resource *r = NULL;	
+	static struct snd_device_ops ops = {
+		.dev_free =	NULL,
+	};
+	
+	mv88fx_snd_debug("=>%s", __FUNCTION__);
+
+
+        card = snd_card_new(-1, "mv88fx_snd", THIS_MODULE, 
+			    sizeof(struct mv88fx_snd_chip));
+
+	if (card == NULL) {
+		mv88fx_snd_debug(KERN_ERR "snd_card_new failed\n");
+		return -ENOMEM;
+	}
+
+        chip = card->private_data;
+	card->dev = &dev->dev;
+        chip->dev = &dev->dev;
+	chip->audio_info = (_audio_info*)dev->dev.platform_data;
+	card->private_free = mv88fx_snd_free;
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!r) {
+		mv88fx_snd_debug(KERN_ERR "platform_get_resource failed\n");
+		err = -ENXIO;
+		goto error;
+	}
+
+	
+        mv88fx_snd_debug(KERN_ERR "chip->res =0x%x\n", (unsigned int)chip->res);
+	
+	r = request_mem_region(r->start, SZ_16K, DRIVER_NAME);
+	if (!r){
+		mv88fx_snd_debug(KERN_ERR "request_mem_region failed\n");
+		err = -EBUSY;
+		goto error;
+	} 
+	chip->res = r;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq == NO_IRQ){
+		mv88fx_snd_debug(KERN_ERR "platform_get_irq failed\n");
+		err = -ENXIO;
+		goto error;
+	}
+
+        
+	mv88fx_snd_debug("%s card = 0x%x card->dev 0x%x\n",__FUNCTION__,
+						(unsigned int)card,
+						(unsigned int)card->dev);
+        chip->base = ioremap(r->start, SZ_16K);
+
+	if (!chip->base) {
+		mv88fx_snd_debug(KERN_ERR "ioremap failed\n");
+		err = -ENOMEM;
+                goto error;
+	}
+
+	mv88fx_snd_debug("%s: chip->base=0x%x r->start0x%x\n",__FUNCTION__,
+		   (unsigned int)chip->base,r->start);
+
+	chip->pdata = (struct mv88fx_snd_platform_data*) dev->dev.platform_data;
+		
+        strncpy(card->driver, dev->dev.driver->name, 
+		sizeof(card->driver));	
+	
+        
+	/* Allocate memory for our device */
+	chip->stream_defaults[PLAYBACK] = 
+		kzalloc(sizeof(struct mv88fx_snd_stream), GFP_KERNEL);
+	
+        if (chip->stream_defaults[PLAYBACK] == NULL) {
+		mv88fx_snd_debug(KERN_ERR "kzalloc failed for default playback\n");
+		err = -ENOMEM;
+		goto error;
+	}
+	chip->stream_defaults[PLAYBACK]->direction = PLAYBACK;
+	chip->stream_defaults[PLAYBACK]->dev = card->dev;
+
+	chip->stream[PLAYBACK] = kzalloc(sizeof(struct mv88fx_snd_stream),
+					 GFP_KERNEL);
+
+	if (chip->stream[PLAYBACK] == NULL) {
+		mv88fx_snd_debug(KERN_ERR "kzalloc failed for runtime playback\n");
+		err = -ENOMEM;
+		goto error;
+	}
+	
+	
+	chip->stream_defaults[CAPTURE] = 
+		kzalloc(sizeof(struct mv88fx_snd_stream), GFP_KERNEL);
+	
+	if (chip->stream_defaults[CAPTURE] == NULL) {
+		mv88fx_snd_debug(KERN_ERR "kzalloc failed for capture\n");
+		err = -ENOMEM;
+		goto error;
+	}
+	chip->stream_defaults[CAPTURE]->direction = CAPTURE;
+        chip->stream_defaults[CAPTURE]->dev = card->dev;
+
+	chip->stream[CAPTURE] = kzalloc(sizeof(struct mv88fx_snd_stream),
+					 GFP_KERNEL);
+
+	if (chip->stream[CAPTURE] == NULL) {
+		mv88fx_snd_debug(KERN_ERR "kzalloc failed for runtime capture\n");
+		err = -ENOMEM;
+		goto error;
+	}
+	
+	chip->irq = irq;
+	chip->stream_defaults[PLAYBACK]->area = 
+		dma_alloc_coherent(chip->dev,
+				MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES, 
+				&chip->stream_defaults[PLAYBACK]->addr, 
+				GFP_KERNEL);
+
+	if (!chip->stream_defaults[PLAYBACK]->area) {
+		mv88fx_snd_debug(KERN_ERR "dma_alloc_coherent failed for playback buffer\n");
+		err = -ENOMEM;
+		goto error;
+	}
+
+	if (0 == test_memory(chip, 
+			(unsigned int)chip->stream_defaults[PLAYBACK]->addr, 
+			(unsigned int)MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES)) {
+
+		mv88fx_snd_debug(KERN_ERR "error: playback buffer not in one memory window\n");
+		err = -ENOMEM;
+		goto error;
+
+	}
+	
+	chip->stream_defaults[CAPTURE]->area = 
+		dma_alloc_coherent(chip->dev,	
+				MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES, 
+				&chip->stream_defaults[CAPTURE]->addr, 
+				GFP_KERNEL);
+
+	if (!chip->stream_defaults[CAPTURE]->area) {
+		mv88fx_snd_debug(KERN_ERR "dma_alloc_coherent failed for capture buffer\n");
+		err = -ENOMEM;
+		goto error;
+	}
+
+	if (0 == test_memory(chip, 
+			(unsigned int)chip->stream_defaults[CAPTURE]->addr, 
+			(unsigned int)MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES)) {
+
+		mv88fx_snd_debug(KERN_ERR "error: playback buffer not in one memory window\n");
+		err = -ENOMEM;
+		goto error;
+
+	}
+
+	if (request_irq(chip->irq, mv88fx_snd_interrupt, 0, DRIVER_NAME, 
+			(void *)chip)) {
+		
+		mv88fx_snd_debug("Unable to grab IRQ %d\n", chip->irq);
+		err = -ENOMEM;
+		goto error;
+	}
+
+	chip->ch_stat_valid = 1; 
+	chip->burst = 128;	
+        chip->loopback = 0; 
+        chip->dco_ctrl_offst = 0x800;
+	
+	err = mv88fx_snd_hw_init(chip);
+
+	if (err != 0) {
+		mv88fx_snd_debug(KERN_ERR "mv88fx_snd_hw_init failed\n");
+		err = -ENOMEM;
+		goto error;
+	}
+	
+	/* Set default values */
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+		mv88fx_snd_debug(KERN_ERR "Creating chip device failed.\n");
+		err = -ENOMEM;
+		goto error;
+	}
+	
+	/* create pcm devices */
+	if ((err = mv88fx_snd_pcm_new(card)) < 0) {
+		mv88fx_snd_debug(KERN_ERR "Creating PCM device failed.\n");
+		err = -ENOMEM;
+		goto error;
+	}
+	/* create controll interfaces & switches */
+	if ((err = mv88fx_snd_ctrl_new(card)) < 0) {
+		mv88fx_snd_debug(KERN_ERR "Creating non-PCM device failed.\n");
+		err = -ENOMEM;
+		goto error;
+	}
+	
+	strcpy(card->driver, "mv88fx_snd");
+	strcpy(card->shortname, "Marvell mv88fx_snd");
+	sprintf(card->longname, "Marvell mv88fx_snd ALSA driver");
+
+	
+	if ((err = snd_card_register(card)) < 0) {
+		mv88fx_snd_debug("Card registeration failed.\n");
+		err = -ENOMEM;
+		goto error;
+	}
+
+	if (dma_set_mask(&dev->dev, 0xFFFFFFUL) < 0)
+		goto error;
+	
+	platform_set_drvdata(dev, card);
+	return 0;
+error:
+	if (card) 
+                snd_card_free(card);
+	platform_set_drvdata(dev, NULL);
+	return err;
+}
+
+static int mv88fx_snd_remove(struct platform_device *dev)
+{
+	struct snd_card *card = platform_get_drvdata(dev);
+	
+	mv88fx_snd_debug("=>%s", __FUNCTION__);
+
+	if (card)
+		snd_card_free(card);
+        platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+#define mv88fx_snd_resume	NULL
+#define mv88fx_snd_suspend	NULL
+
+static struct platform_driver mv88fx_snd_driver = {
+	.probe		= mv88fx_snd_probe,
+	.remove		= mv88fx_snd_remove,
+	.suspend	= mv88fx_snd_suspend,
+	.resume		= mv88fx_snd_resume,
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+
+};
+
+static int __init 
+mv88fx_snd_init(void)
+{
+	mv88fx_snd_debug("=>%s\n", __FUNCTION__);
+	return platform_driver_register(&mv88fx_snd_driver);
+}
+
+static void __exit mv88fx_snd_exit(void)
+{
+	mv88fx_snd_debug("=>%s\n", __FUNCTION__);
+	platform_driver_unregister(&mv88fx_snd_driver);	
+        
+}
+
+MODULE_AUTHOR("Maen Suleiman <maen@marvell.com>");
+MODULE_DESCRIPTION("Marvell MV88Fx Alsa Sound driver");
+MODULE_LICENSE("GPL");
+
+module_init(mv88fx_snd_init);
+module_exit(mv88fx_snd_exit);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-pcm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-pcm.h
new file mode 100755
index 0000000..ad6ad4e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio/mv88fx-pcm.h
@@ -0,0 +1,124 @@
+/*

+ *

+ *	Marvell Orion Alsa Sound driver

+ *

+ *	Author: Maen Suleiman

+ *	Copyright (C) 2008 Marvell Ltd.

+ *

+ *

+ * This program is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License version 2 as

+ * published by the Free Software Foundation.

+ *

+ */

+#define DRIVER_NAME	"mv88fx_snd"

+

+#undef MV88FX_SND_DEBUG
+#ifdef MV88FX_SND_DEBUG

+#define mv88fx_snd_debug(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)

+#else

+	#define mv88fx_snd_debug(a...)

+#endif

+

+typedef struct {

+	unsigned int base;

+	unsigned int size;

+} _audio_mem_info;

+

+typedef struct {

+ 	u32 spdif_rec;

+ 	u32 spdif_play;

+ 	u32 i2s_rec;

+ 	u32 i2s_play;

+ 	_audio_mem_info mem_array[5]; 

+} _audio_info;

+

+

+struct mv88fx_snd_stream {

+	struct snd_pcm_substream	*substream;

+        struct device*		dev;

+	int 	direction; 	/* playback or capture */ 

+	#define PLAYBACK	0

+	#define CAPTURE		1

+	unsigned int	dig_mode;	/* i2s,spdif,both*/ 

+	#define I2S		1

+	#define SPDIF		2

+        int	stereo;		/* mono , stereo*/

+        int	mono_mode;	/* both mono, left mono, right mono*/

+	#define MONO_BOTH	0

+	#define MONO_LEFT	1

+	#define MONO_RIGHT	2

+	int	clock_src;

+	#define DCO_CLOCK	0

+	#define SPCR_CLOCK	1

+	#define EXTERN_CLOCK	2

+	int	rate;		

+	int	stat_mem;	/* Channel status source*/

+	int	format;

+        #define SAMPLE_32IN32	0

+	#define SAMPLE_24IN32	1

+	#define SAMPLE_20IN32	2

+	#define SAMPLE_16IN32	3

+	#define SAMPLE_16IN16	4

+	unsigned int	dma_addr;

+	unsigned int	dma_size;

+	unsigned int	period_size;

+	unsigned int spdif_status[4];	/* SPDIF status */

+	unsigned char 	*area;	/* virtual pointer */

+	dma_addr_t 	addr;	/* physical address */

+

+	

+};

+

+struct mv88fx_snd_chip {

+	struct snd_card *card;

+	struct device	*dev;

+	struct mv88fx_snd_platform_data	*pdata;	/* platform dara*/

+	struct mv88fx_snd_stream	*stream[2];	/* run time values*/

+	struct mv88fx_snd_stream	*stream_defaults[2]; /* default values*/

+        spinlock_t	reg_lock;	/* Register access spinlock */

+	struct resource	*res;		/* resource for IRQ and base*/

+	void __iomem	*base;		/* base address of the host */

+	int	irq;

+	int	loopback;		/* When Loopback is enabled, playback 

+					  data is looped back to be recorded */

+	int	ch_stat_valid;		/* Playback SPDIF channel validity bit 

+					value when REG selected */

+        int	burst;			/* DMA Burst Size */

+

+	#define SPDIF_MEM_STAT		0

+	#define SPDIF_REG_STAT		1

+	unsigned int dco_ctrl_offst;

+	int	pcm_mode;	/* pcm, nonpcm*/

+	#define PCM		0

+	#define NON_PCM		1

+	_audio_info	*audio_info;

+	

+};

+

+#define MV88FX_SND_MIN_PERIODS		8

+#define MV88FX_SND_MAX_PERIODS		16

+#define	MV88FX_SND_MIN_PERIOD_BYTES	0x4000

+#define	MV88FX_SND_MAX_PERIOD_BYTES	0x4000

+

+

+/* read/write registers */

+

+#define mv88fx_snd_writel(chip, offs, val)	\

+		writel((val), (0xf1000000 + offs))

+

+static inline unsigned int mv88fx_snd_readl(struct mv88fx_snd_chip *chip, 

+					   unsigned int offs)

+{

+	unsigned int val = readl((0xf1000000 + offs));

+	return (val);

+}

+#define mv88fx_snd_bitset(chip, offs, bitmask)	\

+		writel( (readl(0xf1000000 + offs) | (bitmask)),	\

+			0xf1000000 + offs)

+

+#define mv88fx_snd_bitreset(chip, offs, bitmask)	\

+		writel( (readl(0xf1000000 + offs) & (~(bitmask))), \

+			0xf1000000 + offs)

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/Makefile
new file mode 100755
index 0000000..0fef522
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Marvell Audio ALSA Device Driver
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+obj-$(CONFIG_SND_MRVL_AUDIO) += snd-mv88fx-soc.o
+obj-$(CONFIG_SND_MRVL_AUDIO) += snd-mv88fx-i2s-soc.o
+obj-$(CONFIG_SND_MRVL_AUDIO) += snd-mv88fx-pcm-soc.o
+
+snd-mv88fx-i2s-soc-objs               += mv88fx-i2s.o
+snd-mv88fx-pcm-soc-objs		      += mv88fx-pcm.o
+
+#snd-mv88fx-soc-objs                  += cs42l51-hal.o
+snd-mv88fx-soc-objs                  += mv88fx.o
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-i2s.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-i2s.c
new file mode 100755
index 0000000..4c51970
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-i2s.c
@@ -0,0 +1,827 @@
+/*
+ *
+ *	Marvell Orion Alsa SOC Sound driver
+ *
+ *	Author: Yuval Elmaliah
+ *	Copyright (C) 2008 Marvell Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <linux/platform_device.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <asm/sizes.h>
+#include <linux/io.h>
+#include <plat/i2s-orion.h>
+#include <asm/dma.h>
+#include <linux/scatterlist.h>
+#include <asm/sizes.h>
+#include <mvTypes.h>
+#include "mv88fx-pcm.h"
+#include "audio/mvAudioRegs.h"
+#include "audio/mvAudio.h"
+#include "mvSysAudioApi.h"
+
+#ifdef CONFIG_MACH_DOVE_RD_AVNG
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#endif
+
+
+struct mv88fx_i2s_info {
+	int		port;
+	void __iomem	*base;	/* base address of the host */
+	u32		irq_mask;
+	u32		playback_cntrl_reg;
+	u32		capture_cntrl_reg;
+};
+
+static struct mv88fx_i2s_info mv88fx_i2s_info;
+
+
+static int mv88fx_i2_hw_init(void)
+{
+	mv88fx_snd_debug("");
+
+	mv88fx_snd_writel(mv88fx_i2s_info.base,
+		MV_AUDIO_INT_CAUSE_REG(mv88fx_i2s_info.port), 0xffffffff);
+	mv88fx_snd_writel(mv88fx_i2s_info.base,
+		MV_AUDIO_INT_MASK_REG(mv88fx_i2s_info.port), 0);
+	mv88fx_snd_writel(mv88fx_i2s_info.base,
+		MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG(mv88fx_i2s_info.port), 0);
+
+//	if (MV_OK != mvAudioInit(mv88fx_i2s_info.port))
+//		return -EIO;
+	mvSysAudioInit(mv88fx_i2s_info.port);
+
+	/* Disable all playback/recording */
+	mv88fx_snd_bitreset(mv88fx_i2s_info.base,
+		MV_AUDIO_PLAYBACK_CTRL_REG(mv88fx_i2s_info.port),
+		(APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK));
+
+	mv88fx_snd_bitreset(mv88fx_i2s_info.base,
+		MV_AUDIO_RECORD_CTRL_REG(mv88fx_i2s_info.port),
+		(ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK));
+
+	if (MV_OK != mvSPDIFRecordTclockSet(mv88fx_i2s_info.port)) {
+		mv88fx_snd_error("mvSPDIFRecordTclockSet failed");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+
+static int mv88fx_i2s_snd_hw_playback_set(struct mv88fx_snd_chip *chip,
+					  struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mv88fx_snd_stream *audio_stream = runtime->private_data;
+	MV_AUDIO_PLAYBACK_CTRL pcm_play_ctrl;
+	MV_I2S_PLAYBACK_CTRL i2s_play_ctrl;
+	MV_SPDIF_PLAYBACK_CTRL spdif_play_ctrl;
+	MV_AUDIO_FREQ_DATA dco_ctrl;
+
+	mv88fx_snd_debug("chip=%p chip->base=%p", chip, chip->base);
+
+	memset(&pcm_play_ctrl, 0, sizeof(pcm_play_ctrl));
+	memset(&dco_ctrl, 0, sizeof(dco_ctrl));
+	memset(&i2s_play_ctrl, 0, sizeof(i2s_play_ctrl));
+	memset(&spdif_play_ctrl, 0, sizeof(spdif_play_ctrl));
+
+	dco_ctrl.offset = chip->dco_ctrl_offst;
+
+	mv88fx_snd_debug("rate: %u	", runtime->rate);
+	switch (runtime->rate) {
+	case 44100:
+		dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH;
+		break;
+	case 48000:
+		dco_ctrl.baseFreq = AUDIO_FREQ_48KH;
+		break;
+	case 96000:
+		dco_ctrl.baseFreq = AUDIO_FREQ_96KH;
+		break;
+	default:
+		mv88fx_snd_error("Requested rate %d is not supported",
+				 runtime->rate);
+		return -1;
+	}
+
+	pcm_play_ctrl.burst = (chip->burst == 128) ? AUDIO_128BYTE_BURST :
+	    AUDIO_32BYTE_BURST;
+
+	pcm_play_ctrl.loopBack = chip->loopback;
+
+	if (mv88fx_pcm_is_stereo(runtime)) {
+		pcm_play_ctrl.monoMode = AUDIO_PLAY_MONO_OFF;
+	} else {
+
+		switch (audio_stream->mono_mode) {
+		case MONO_LEFT:
+			pcm_play_ctrl.monoMode = AUDIO_PLAY_LEFT_MONO;
+			break;
+		case MONO_RIGHT:
+			pcm_play_ctrl.monoMode = AUDIO_PLAY_RIGHT_MONO;
+			break;
+		case MONO_BOTH:
+		default:
+			pcm_play_ctrl.monoMode = AUDIO_PLAY_BOTH_MONO;
+			break;
+		}
+	}
+
+	if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
+		pcm_play_ctrl.sampleSize = SAMPLE_16BIT;
+		i2s_play_ctrl.sampleSize = SAMPLE_16BIT;
+	} else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) {
+		pcm_play_ctrl.sampleSize = SAMPLE_24BIT;
+		i2s_play_ctrl.sampleSize = SAMPLE_24BIT;
+
+	} else if (runtime->format == SNDRV_PCM_FORMAT_S32_LE) {
+		pcm_play_ctrl.sampleSize = SAMPLE_32BIT;
+		i2s_play_ctrl.sampleSize = SAMPLE_32BIT;
+	} else {
+		mv88fx_snd_error("Requested format %d is not supported",
+				 runtime->format);
+		return -1;
+	}
+
+	/* buffer and period sizes in frame */
+	pcm_play_ctrl.bufferPhyBase = runtime->dma_addr;
+	pcm_play_ctrl.bufferSize =
+	    frames_to_bytes(runtime, runtime->buffer_size);
+	pcm_play_ctrl.intByteCount =
+	    frames_to_bytes(runtime, runtime->period_size);
+
+	/* I2S playback streem stuff */
+	/*i2s_play_ctrl.sampleSize = pcm_play_ctrl.sampleSize; */
+	i2s_play_ctrl.justification = I2S_JUSTIFIED;
+	i2s_play_ctrl.sendLastFrame = 0;
+
+	spdif_play_ctrl.nonPcm = MV_FALSE;
+
+	spdif_play_ctrl.validity = chip->ch_stat_valid;
+
+	if (audio_stream->stat_mem) {
+		spdif_play_ctrl.userBitsFromMemory = MV_TRUE;
+		spdif_play_ctrl.validityFromMemory = MV_TRUE;
+		spdif_play_ctrl.blockStartInternally = MV_FALSE;
+	} else {
+		spdif_play_ctrl.userBitsFromMemory = MV_FALSE;
+		spdif_play_ctrl.validityFromMemory = MV_FALSE;
+		spdif_play_ctrl.blockStartInternally = MV_TRUE;
+	}
+
+	mv88fx_snd_debug("");
+	/* If this is non-PCM sound, mute I2S channel */
+	spin_lock_irq(&chip->reg_lock);
+
+	mv88fx_snd_debug("chip=%p chip->base=%p port=%d", chip, chip->base,
+			 chip->port);
+
+	if (!(mv88fx_snd_readl(chip->base,
+		MV_AUDIO_PLAYBACK_CTRL_REG(chip->port)) &
+		(APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))) {
+
+		mv88fx_snd_debug("");
+
+		if (MV_OK != mvAudioDCOCtrlSet(chip->port, &dco_ctrl)) {
+			mv88fx_snd_error
+			    ("Failed to initialize DCO clock control.");
+			return -1;
+			mv88fx_snd_debug("");
+
+		}
+	}
+
+	mv88fx_snd_debug("");
+
+	if (audio_stream->clock_src == DCO_CLOCK)
+		while ((mv88fx_snd_readl(chip->base,
+			 MV_AUDIO_SPCR_DCO_STATUS_REG(chip->port)) &
+			ASDSR_DCO_LOCK_MASK) == 0)
+			;
+	else if (audio_stream->clock_src == SPCR_CLOCK)
+		while ((mv88fx_snd_readl(chip->base,
+			 MV_AUDIO_SPCR_DCO_STATUS_REG(chip->port)) &
+			ASDSR_SPCR_LOCK_MASK) == 0)
+			;
+
+	mv88fx_snd_debug("");
+
+	if (MV_OK != mvAudioPlaybackControlSet(chip->port, &pcm_play_ctrl)) {
+		mv88fx_snd_error("Failed to initialize PCM playback control.");
+		return -1;
+	}
+	mv88fx_snd_debug("");
+
+	if (MV_OK != mvI2SPlaybackCtrlSet(chip->port, &i2s_play_ctrl)) {
+		mv88fx_snd_error("Failed to initialize I2S playback control.");
+		return -1;
+	}
+	mv88fx_snd_debug("");
+
+	mvSPDIFPlaybackCtrlSet(chip->port, &spdif_play_ctrl);
+
+	mv88fx_snd_debug("");
+
+	spin_unlock_irq(&chip->reg_lock);
+
+	return 0;
+}
+
+static int mv88fx_i2s_snd_hw_capture_set(struct mv88fx_snd_chip *chip,
+					 struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mv88fx_snd_stream *audio_stream = runtime->private_data;
+	MV_AUDIO_RECORD_CTRL pcm_rec_ctrl;
+	MV_I2S_RECORD_CTRL i2s_rec_ctrl;
+	MV_AUDIO_FREQ_DATA dco_ctrl;
+
+#ifdef CONFIG_MACH_DOVE_RD_AVNG
+	int phoneInDetected;
+#endif
+
+	mv88fx_snd_debug("chip=%p chip->base=%p", chip, chip->base);
+
+	dco_ctrl.offset = chip->dco_ctrl_offst;
+
+	switch (runtime->rate) {
+	case 44100:
+		dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH;
+		break;
+	case 48000:
+		dco_ctrl.baseFreq = AUDIO_FREQ_48KH;
+		break;
+	case 96000:
+		dco_ctrl.baseFreq = AUDIO_FREQ_96KH;
+		break;
+	default:
+		mv88fx_snd_debug("ERROR");
+		mv88fx_snd_error("Requested rate %d is not supported",
+				 runtime->rate);
+		return -1;
+	}
+
+	pcm_rec_ctrl.burst = (chip->burst == 128) ? AUDIO_128BYTE_BURST :
+	    AUDIO_32BYTE_BURST;
+
+	if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
+		pcm_rec_ctrl.sampleSize = SAMPLE_16BIT;
+	} else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) {
+		pcm_rec_ctrl.sampleSize = SAMPLE_24BIT;
+	} else if (runtime->format == SNDRV_PCM_FORMAT_S32_LE) {
+		pcm_rec_ctrl.sampleSize = SAMPLE_32BIT;
+	} else {
+		mv88fx_snd_error("Requested format %d is not supported",
+				 runtime->format);
+		return -1;
+	}
+
+	pcm_rec_ctrl.mono =
+	    (mv88fx_pcm_is_stereo(runtime)) ? MV_FALSE : MV_TRUE;
+
+	if (pcm_rec_ctrl.mono) {
+		switch (audio_stream->mono_mode) {
+		case MONO_LEFT:
+			pcm_rec_ctrl.monoChannel = AUDIO_REC_LEFT_MONO;
+			break;
+		default:
+		case MONO_RIGHT:
+			pcm_rec_ctrl.monoChannel = AUDIO_REC_RIGHT_MONO;
+			break;
+		}
+
+	} else
+		pcm_rec_ctrl.monoChannel = AUDIO_REC_LEFT_MONO;
+
+	pcm_rec_ctrl.bufferPhyBase = runtime->dma_addr;
+	pcm_rec_ctrl.bufferSize =
+	    frames_to_bytes(runtime, runtime->buffer_size);
+	pcm_rec_ctrl.intByteCount =
+	    frames_to_bytes(runtime, runtime->period_size);
+
+	/* I2S record streem stuff */
+	i2s_rec_ctrl.sample = pcm_rec_ctrl.sampleSize;
+	i2s_rec_ctrl.justf = I2S_JUSTIFIED;
+
+	spin_lock_irq(&chip->reg_lock);
+
+	/* set clock only if record is not enabled */
+	if (!(mv88fx_snd_readl(chip->base,
+		MV_AUDIO_RECORD_CTRL_REG(chip->port)) &
+		(ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK))) {
+
+		if (MV_OK != mvAudioDCOCtrlSet(chip->port, &dco_ctrl)) {
+			mv88fx_snd_debug("ERROR");
+			mv88fx_snd_error
+			    ("Failed to initialize DCO clock control.");
+			return -1;
+		}
+	}
+	mv88fx_snd_debug("");
+	if (MV_OK != mvAudioRecordControlSet(chip->port, &pcm_rec_ctrl)) {
+		mv88fx_snd_error("Failed to initialize PCM record control.");
+		return -1;
+	}
+
+	if (MV_OK != mvI2SRecordCntrlSet(chip->port, &i2s_rec_ctrl)) {
+		mv88fx_snd_error("Failed to initialize I2S record control.");
+		return -1;
+	}
+	mv88fx_snd_debug("");
+
+#ifdef CONFIG_MACH_DOVE_RD_AVNG
+	if (machine_is_dove_rd_avng()) {
+		phoneInDetected = gpio_get_value(53);
+
+		if (phoneInDetected < 0)
+			mv88fx_snd_error("Failed to detect phone-in.");
+		else {
+			int input_type;
+			mv88fx_snd_error("detect phone-in.");
+			if (!phoneInDetected)
+				input_type = 2;	/* external MIC */
+			else
+				input_type = 1;	/* internal MIC */
+		}
+	}
+#endif
+	mv88fx_snd_debug("");
+
+	spin_unlock_irq(&chip->reg_lock);
+
+	mv88fx_snd_debug("");
+
+	return 0;
+
+}
+
+static int mv88fx_i2s_capture_trigger(struct snd_pcm_substream *substream,
+				      int cmd)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mv88fx_snd_stream *audio_stream = runtime->private_data;
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+	int result = 0;
+
+	mv88fx_snd_debug("substream=%p cmd=%d audio_stream=%p", substream, cmd,
+			 audio_stream);
+
+	spin_lock(&chip->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* FIXME: should check if busy before */
+		mv88fx_snd_debug("");
+		/* make sure the dma in pause state */
+		mv88fx_snd_bitset(chip->base,
+			MV_AUDIO_RECORD_CTRL_REG(chip->port),
+			ARCR_RECORD_PAUSE_MASK);
+
+		/* enable interrupt */
+		mv88fx_snd_bitset(chip->base, MV_AUDIO_INT_MASK_REG(chip->port),
+				  AICR_RECORD_BYTES_INT);
+
+		/* enable dma */
+		mv88fx_snd_debug("dig_mode=%x", audio_stream->dig_mode);
+		if (audio_stream->dig_mode & I2S) {
+			mv88fx_snd_debug("enable dma");
+			mv88fx_snd_bitset(chip->base,
+					  MV_AUDIO_RECORD_CTRL_REG(chip->port),
+					  ARCR_RECORD_I2S_EN_MASK);
+		}
+
+		if (audio_stream->dig_mode & SPDIF) {
+			mv88fx_snd_debug("enable spdif dma");
+			mv88fx_snd_bitset(chip->base,
+					  MV_AUDIO_RECORD_CTRL_REG(chip->port),
+					  ARCR_RECORD_SPDIF_EN_MASK);
+		}
+
+		/* start dma */
+		mv88fx_snd_bitreset(chip->base,
+			MV_AUDIO_RECORD_CTRL_REG(chip->port),
+			ARCR_RECORD_PAUSE_MASK);
+
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+
+		/* make sure the dma in pause state */
+		mv88fx_snd_bitset(chip->base,
+			MV_AUDIO_RECORD_CTRL_REG(chip->port),
+			ARCR_RECORD_PAUSE_MASK);
+
+		/* disable interrupt */
+		mv88fx_snd_bitreset(chip->base,
+			MV_AUDIO_INT_MASK_REG(chip->port),
+			AICR_RECORD_BYTES_INT);
+
+		/* always stop both I2S and SPDIF */
+		mv88fx_snd_bitreset(chip->base,
+			MV_AUDIO_RECORD_CTRL_REG(chip->port),
+			(ARCR_RECORD_I2S_EN_MASK | ARCR_RECORD_SPDIF_EN_MASK));
+
+		/* FIXME: should check if busy after */
+
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		mv88fx_snd_bitset(chip->base,
+			MV_AUDIO_RECORD_CTRL_REG(chip->port),
+			ARCR_RECORD_PAUSE_MASK);
+		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		mv88fx_snd_bitreset(chip->base,
+			MV_AUDIO_RECORD_CTRL_REG(chip->port),
+			ARCR_RECORD_PAUSE_MASK);
+
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+	spin_unlock(&chip->reg_lock);
+	mv88fx_snd_debug("result=%d", result);
+	return result;
+}
+
+static int mv88fx_i2s_playback_trigger(struct snd_pcm_substream *substream,
+				       int cmd)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mv88fx_snd_stream *audio_stream = runtime->private_data;
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+	int result = 0;
+
+	mv88fx_snd_debug("substream=%p cmd=%d audio_stream=%p", substream, cmd,
+			 audio_stream);
+
+	spin_lock(&chip->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+
+		mv88fx_snd_debug("");
+		/* enable interrupt */
+		mv88fx_snd_bitset(chip->base, MV_AUDIO_INT_MASK_REG(chip->port),
+				  AICR_PLAY_BYTES_INT);
+
+		/* make sure the dma in pause state */
+		mv88fx_snd_bitset(chip->base,
+			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+			APCR_PLAY_PAUSE_MASK);
+
+		/* enable dma */
+		if ((audio_stream->dig_mode & I2S) && (chip->pcm_mode == PCM))
+			mv88fx_snd_bitset(chip->base,
+				MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+				APCR_PLAY_I2S_ENABLE_MASK);
+
+		if (audio_stream->dig_mode & SPDIF)
+			mv88fx_snd_bitset(chip->base,
+				MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+				APCR_PLAY_SPDIF_ENABLE_MASK);
+
+		/* start dma */
+		mv88fx_snd_bitreset(chip->base,
+				    MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+				    APCR_PLAY_PAUSE_MASK);
+
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+
+		mv88fx_snd_debug("");
+
+		/* disable interrupt */
+		mv88fx_snd_bitreset(chip->base,
+			MV_AUDIO_INT_MASK_REG(chip->port),
+			AICR_PLAY_BYTES_INT);
+
+		/* make sure the dma in pause state */
+		mv88fx_snd_bitset(chip->base,
+			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+			APCR_PLAY_PAUSE_MASK);
+
+		/* always stop both I2S and SPDIF */
+		mv88fx_snd_bitreset(chip->base,
+				    MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+				    (APCR_PLAY_I2S_ENABLE_MASK |
+				     APCR_PLAY_SPDIF_ENABLE_MASK));
+
+		/* check if busy twice */
+		while (mv88fx_snd_readl(chip->base,
+			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port)) &
+		       APCR_PLAY_BUSY_MASK)
+			;
+
+		while (mv88fx_snd_readl(chip->base,
+			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port)) &
+		       APCR_PLAY_BUSY_MASK)
+			;
+
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		mv88fx_snd_debug("");
+
+		mv88fx_snd_bitset(chip->base,
+			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+			APCR_PLAY_PAUSE_MASK);
+		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		mv88fx_snd_debug("");
+
+		mv88fx_snd_bitreset(chip->base,
+				    MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+				    APCR_PLAY_PAUSE_MASK);
+
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+	spin_unlock(&chip->reg_lock);
+	mv88fx_snd_debug("result=%d", result);
+	return result;
+}
+
+static int mv88fx_i2s_startup(struct snd_pcm_substream *stream,
+				struct snd_soc_dai *dai)
+{
+	mv88fx_snd_debug("");
+
+	return 0;
+}
+
+static void mv88fx_i2s_shutdown(struct snd_pcm_substream *stream,
+				struct snd_soc_dai *dai)
+{
+	mv88fx_snd_debug("");
+}
+
+static int mv88fx_i2s_hw_params(struct snd_pcm_substream *stream,
+				struct snd_pcm_hw_params *hw_params,
+				struct snd_soc_dai *dai)
+{
+	mv88fx_snd_debug("");
+
+	return 0;
+}
+
+static int mv88fx_i2s_hw_free(struct snd_pcm_substream *stream,
+				struct snd_soc_dai *dai)
+{
+	mv88fx_snd_debug("");
+
+	return 0;
+}
+
+static int mv88fx_i2s_prepare(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+	mv88fx_snd_debug("");
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		return mv88fx_i2s_snd_hw_capture_set(chip, substream);
+	else
+		return mv88fx_i2s_snd_hw_playback_set(chip, substream);
+
+}
+
+static int mv88fx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+				struct snd_soc_dai *dai)
+{
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		return mv88fx_i2s_capture_trigger(substream, cmd);
+	else
+		return mv88fx_i2s_playback_trigger(substream, cmd);
+}
+
+static int mv88fx_i2s_set_sysclk(struct snd_soc_dai *codec_dai,
+				 int clk_id, unsigned int freq, int dir)
+{
+	mv88fx_snd_debug("");
+
+	return 0;
+}
+
+static int mv88fx_i2s_set_fmt(struct snd_soc_dai *codec_dai,
+			      unsigned int fmt)
+{
+	mv88fx_snd_debug("");
+
+	return 0;
+}
+
+static int mv88fx_i2s_dai_probe(struct platform_device *pdev,
+				struct snd_soc_dai *dai)
+{
+	struct mv88fx_snd_machine_data *machine_data = pdev->dev.platform_data;
+
+	mv88fx_snd_debug("");
+
+	mv88fx_i2s_info.base = machine_data->base;
+	mv88fx_i2s_info.port = machine_data->port;
+
+
+	mv88fx_i2_hw_init();
+
+
+	return 0;
+}
+
+static void mv88fx_i2s_dai_remove(struct platform_device *pdev,
+				struct snd_soc_dai *dai)
+{
+	mv88fx_snd_debug("");
+
+}
+
+
+static int mv88fx_i2s_suspend(struct snd_soc_dai *cpu_dai)
+{
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+
+	mv88fx_snd_debug("");
+
+	if (!cpu_dai->active)
+		return 0;
+
+
+	spin_lock(&chip->reg_lock);
+
+	/* save registers */
+	mv88fx_i2s_info.irq_mask = mv88fx_snd_readl(chip->base,
+			MV_AUDIO_INT_MASK_REG(chip->port));
+	mv88fx_i2s_info.capture_cntrl_reg = mv88fx_snd_readl(chip->base,
+			MV_AUDIO_RECORD_CTRL_REG(chip->port));
+	mv88fx_i2s_info.playback_cntrl_reg = mv88fx_snd_readl(chip->base,
+			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port));
+
+	/* clear all interrupts */
+	mv88fx_snd_writel(chip->base,
+		MV_AUDIO_INT_CAUSE_REG(chip->port), 0xffffffff);
+	/* disable all interrupts */
+	mv88fx_snd_writel(chip->base,
+		MV_AUDIO_INT_MASK_REG(chip->port), 0);
+	/* pause dma */
+	mv88fx_snd_bitset(chip->base,
+		MV_AUDIO_RECORD_CTRL_REG(chip->port), ARCR_RECORD_PAUSE_MASK);
+	mv88fx_snd_bitset(chip->base,
+		MV_AUDIO_PLAYBACK_CTRL_REG(chip->port), APCR_PLAY_PAUSE_MASK);
+
+
+	spin_unlock(&chip->reg_lock);
+
+	return 0;
+}
+
+
+
+static int mv88fx_i2s_resume(struct snd_soc_dai *cpu_dai)
+{
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+
+	mv88fx_snd_debug("");
+
+	if (!cpu_dai->active)
+		return 0;
+
+	mv88fx_i2_hw_init();
+
+	spin_lock(&chip->reg_lock);
+
+	mv88fx_snd_writel(chip->base,
+		MV_AUDIO_INT_CAUSE_REG(chip->port), 0xffffffff);
+	/* restore registers */
+	mv88fx_snd_writel(chip->base,
+		MV_AUDIO_RECORD_CTRL_REG(chip->port),
+		mv88fx_i2s_info.capture_cntrl_reg);
+	mv88fx_snd_writel(chip->base,
+		MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
+		mv88fx_i2s_info.playback_cntrl_reg);
+	/* enable interrupts */
+	mv88fx_snd_writel(chip->base,
+		MV_AUDIO_INT_MASK_REG(chip->port),
+		mv88fx_i2s_info.irq_mask);
+
+	spin_unlock(&chip->reg_lock);
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops mv88fx_i2s_dai_ops = {
+	.startup = mv88fx_i2s_startup,
+	.shutdown = mv88fx_i2s_shutdown,
+	.hw_params = mv88fx_i2s_hw_params,
+	.hw_free = mv88fx_i2s_hw_free,
+	.prepare = mv88fx_i2s_prepare,
+	.trigger = mv88fx_i2s_trigger,
+	.hw_params = mv88fx_i2s_hw_params,
+	.set_sysclk = mv88fx_i2s_set_sysclk,
+	.set_fmt = mv88fx_i2s_set_fmt,
+};
+
+struct snd_soc_dai mv88fx_i2s_dai = {
+	.name = "mv88fx-i2s",
+	.id = 0,
+	.probe = mv88fx_i2s_dai_probe,
+	.remove = mv88fx_i2s_dai_remove,
+	.suspend = mv88fx_i2s_suspend,
+	.resume = mv88fx_i2s_resume,
+	.ops = &mv88fx_i2s_dai_ops,
+	.capture = {
+		    .stream_name = "i2s-capture",
+		    .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S24_LE |
+				SNDRV_PCM_FMTBIT_S32_LE),
+		    .rate_min = 44100,
+		    .rate_max = 96000,
+		    .rates = (SNDRV_PCM_RATE_44100 |
+			      SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000),
+		    .channels_min = 1,
+		    .channels_max = 2,
+		    },
+	.playback = {
+		     .stream_name = "i2s-playback",
+		     .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				 SNDRV_PCM_FMTBIT_S24_LE |
+				 SNDRV_PCM_FMTBIT_S32_LE),
+		     .rate_min = 44100,
+		     .rate_max = 96000,
+		     .rates = (SNDRV_PCM_RATE_44100 |
+			       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000),
+		     .channels_min = 1,
+		     .channels_max = 2,
+		     },
+
+	.runtime = NULL,
+	.active = 0,
+	.dma_data = NULL,
+	.private_data = NULL,
+};
+EXPORT_SYMBOL_GPL(mv88fx_i2s_dai);
+
+
+
+
+
+static int mv88fx_i2s_probe(struct platform_device *pdev)
+{
+	mv88fx_snd_debug("");
+	mv88fx_i2s_dai.dev = &pdev->dev;
+	return snd_soc_register_dai(&mv88fx_i2s_dai);
+}
+
+static int __devexit mv88fx_i2s_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_dai(&mv88fx_i2s_dai);
+	return 0;
+}
+
+static struct platform_driver mv88fx_i2s_driver = {
+	.probe = mv88fx_i2s_probe,
+	.remove = __devexit_p(mv88fx_i2s_remove),
+
+	.driver = {
+		.name = "mv88fx-i2s",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mv88fx_i2s_init(void)
+{
+	mv88fx_snd_debug("");
+	return platform_driver_register(&mv88fx_i2s_driver);
+}
+
+static void __exit mv88fx_i2s_exit(void)
+{
+	mv88fx_snd_debug("");
+	platform_driver_unregister(&mv88fx_i2s_driver);
+}
+
+module_init(mv88fx_i2s_init);
+module_exit(mv88fx_i2s_exit);
+
+
+/* Module information */
+MODULE_AUTHOR("Yuval Elmaliah <eyuval@marvell.com>");
+MODULE_DESCRIPTION("mv88fx I2S SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-i2s.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-i2s.h
new file mode 100755
index 0000000..6b7912c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-i2s.h
@@ -0,0 +1,20 @@
+/*
+ *
+ *	Marvell Orion Alsa SOC Sound driver
+ *
+ *	Author: Yuval Elmaliah
+ *	Copyright (C) 2008 Marvell Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _MV88FX_I2S_H
+#define _MV88FX_I2S_H
+
+extern struct snd_soc_dai mv88fx_i2s_dai;
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-pcm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-pcm.c
new file mode 100755
index 0000000..498a962
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-pcm.c
@@ -0,0 +1,617 @@
+/*
+ *
+ *	Marvell Orion Alsa SOC Sound driver
+ *
+ *	Author: Yuval Elmaliah
+ *	Copyright (C) 2008 Marvell Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <linux/platform_device.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/mbus.h>
+#include <linux/irqreturn.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <asm/dma.h>
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <asm/sizes.h>
+#include <mvTypes.h>
+#include <plat/i2s-orion.h>
+#include "audio/mvAudioRegs.h"
+#include "mv88fx-pcm.h"
+
+#include "audio/mvAudio.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+#ifdef CONFIG_MACH_DOVE_RD_AVNG
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#endif
+
+struct mv88fx_snd_chip *mv88fx_pcm_snd_chip;
+EXPORT_SYMBOL_GPL(mv88fx_pcm_snd_chip);
+
+static struct snd_pcm_hardware mv88fx_pcm_hardware = {
+	.info = (SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_MMAP |
+		 SNDRV_PCM_INFO_MMAP_VALID |
+		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE),
+	.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+		    SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE),
+	.rates = (SNDRV_PCM_RATE_44100 |
+		  SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000),
+	.rate_min = 44100,
+	.rate_max = 96000,
+	.channels_min = 1,
+	.channels_max = 2,
+	.buffer_bytes_max = (16 * 1024 * 1024),
+	.period_bytes_min = MV88FX_SND_MIN_PERIOD_BYTES,
+	.period_bytes_max = MV88FX_SND_MAX_PERIOD_BYTES,
+	.periods_min = MV88FX_SND_MIN_PERIODS,
+	.periods_max = MV88FX_SND_MAX_PERIODS,
+	.fifo_size = 0,
+
+};
+
+static void mv88fx_pcm_init_stream(struct mv88fx_snd_chip *chip,
+				   struct mv88fx_snd_stream *stream,
+				   int stream_id)
+{
+	memset(stream, 0, sizeof(*stream));
+	if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
+		stream->dig_mode = 0;
+		if (chip->pdata->i2s_play)
+			stream->dig_mode |= I2S;
+		if (chip->pdata->spdif_play)
+			stream->dig_mode |= SPDIF;
+
+		stream->mono_mode = MONO_BOTH;
+		stream->stat_mem = 0;
+		stream->clock_src = DCO_CLOCK;
+	} else {
+		if (chip->pdata->i2s_rec)
+			stream->dig_mode = I2S;
+		else if (chip->pdata->spdif_rec)
+			stream->dig_mode = SPDIF;
+
+		stream->mono_mode = MONO_LEFT;
+		stream->stat_mem = 0;
+		stream->clock_src = DCO_CLOCK;
+	}
+}
+
+
+
+static int mv88fx_find_dram_cs(struct mbus_dram_target_info *dram,
+			       u32 base, u32 size)
+{
+	int i;
+
+	mv88fx_snd_debug("base=0x%x size=%u dram=%p", base, size, dram);
+
+	for (i = 0; i < dram->num_cs; i++) {
+		struct mbus_dram_window *cs = dram->cs + i;
+		/* check if we fit into one memory window only */
+		if ((base >= cs->base) &&
+		    ((base + size) <= cs->base + cs->size))
+			return i;
+
+	}
+
+	mv88fx_snd_error("");
+	return -1;
+}
+static int mv88fx_config_dma_window(struct mv88fx_snd_chip *chip,
+				    int dma, struct mbus_dram_target_info *dram)
+{
+	struct mbus_dram_window *cs;
+	struct snd_pcm_substream *substream = chip->pcm->streams[dma].substream;
+
+	int win;
+
+#define WINDOW_CTRL(dma)		(0xA0C - ((dma) << 3))
+#define WINDOW_BASE(dma)		(0xA08 - ((dma) << 3))
+
+	mv88fx_snd_debug("");
+	/*
+	 * we have one window for each dma (playback dma and recording),
+	 * confiure it to point to the dram window where the buffer falls in
+	 */
+	win = mv88fx_find_dram_cs(dram,
+				  (u32) substream->dma_buffer.addr,
+				  (u32) MV88FX_SND_MAX_PERIODS *
+				  MV88FX_SND_MAX_PERIOD_BYTES);
+	if (win < 0)
+		return -1;
+
+	cs = dram->cs + win;
+	writel(((cs->size - 1) & 0xffff0000) |
+	       (cs->mbus_attr << 8) |
+	       (dram->mbus_dram_target_id << 4) | 1,
+	       chip->base + MV_AUDIO_REGS_OFFSET(chip->port) + WINDOW_CTRL(dma));
+	writel(cs->base,
+	       chip->base + MV_AUDIO_REGS_OFFSET(chip->port) + WINDOW_BASE(dma));
+
+
+#undef WINDOW_CTRL
+#undef WINDOW_BASE
+
+	return win;
+}
+static int mv88fx_conf_mbus_windows(struct mv88fx_snd_chip *chip,
+				    struct mbus_dram_target_info *dram)
+{
+	mv88fx_snd_debug("");
+	/*
+	 * we have one window for playback and one for recording
+	 */
+	if (mv88fx_config_dma_window(chip, SNDRV_PCM_STREAM_PLAYBACK, dram) < 0)
+		return -1;
+
+	if (mv88fx_config_dma_window(chip, SNDRV_PCM_STREAM_CAPTURE, dram) < 0)
+		return -1;
+	return 0;
+}
+
+
+static irqreturn_t mv88fx_pcm_dma_interrupt(int irq, void *dev_id)
+{
+	struct mv88fx_snd_chip *chip = dev_id;
+	struct snd_pcm_substream *play_stream =
+	    chip->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct snd_pcm_substream *capture_stream =
+	    chip->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+	unsigned int status, mask;
+
+	mv88fx_snd_debug("");
+
+	spin_lock(&chip->reg_lock);
+
+	/* read the active interrupt */
+	mask = mv88fx_snd_readl(chip->base,
+			MV_AUDIO_INT_MASK_REG(chip->port));
+	status = mv88fx_snd_readl(chip->base,
+			MV_AUDIO_INT_CAUSE_REG(chip->port)) & mask;
+
+	do {
+
+		if (status & ~(AICR_RECORD_BYTES_INT | AICR_PLAY_BYTES_INT)) {
+			spin_unlock(&chip->reg_lock);
+			snd_BUG();/* FIXME: should enable error interrupts */
+			return IRQ_NONE;
+		}
+
+		/* acknowledge interrupt */
+		mv88fx_snd_writel(chip->base,
+			MV_AUDIO_INT_CAUSE_REG(chip->port), status);
+
+		/* This is record event */
+		if (status & AICR_RECORD_BYTES_INT) {
+			mv88fx_snd_debug("capture");
+			spin_unlock(&chip->reg_lock);
+			if (capture_stream)
+				snd_pcm_period_elapsed(capture_stream);
+			spin_lock(&chip->reg_lock);
+		}
+		/* This is play event */
+		if (status & AICR_PLAY_BYTES_INT) {
+			mv88fx_snd_debug("playback");
+			spin_unlock(&chip->reg_lock);
+			if (play_stream)
+				snd_pcm_period_elapsed(play_stream);
+			spin_lock(&chip->reg_lock);
+
+		}
+
+		/* read the active interrupt */
+		mask = mv88fx_snd_readl(chip->base,
+				MV_AUDIO_INT_MASK_REG(chip->port));
+		status = mv88fx_snd_readl(chip->base,
+				MV_AUDIO_INT_CAUSE_REG(chip->port)) & mask;
+
+	} while (status);
+
+	spin_unlock(&chip->reg_lock);
+	return IRQ_HANDLED;
+
+}
+
+static int mv88fx_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err = 0;
+
+	mv88fx_snd_debug("substream=%p", substream);
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	runtime->dma_bytes = params_buffer_bytes(params);
+	return err;
+
+}
+
+static int mv88fx_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+
+	mv88fx_snd_debug("");
+
+	if (runtime->dma_area == NULL)
+		return 0;
+
+	if (buf != &substream->dma_buffer)
+		kfree(runtime->dma_buffer_p);
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+	return 0;
+}
+
+static int mv88fx_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mv88fx_snd_stream *audio_stream = runtime->private_data;
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+
+	mv88fx_snd_debug("substream=%p chip=%p,chip->base=%p audio_stream=%p",
+			 substream, chip, chip->base, audio_stream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		if ((audio_stream->dig_mode == I2S) &&
+		    (chip->pcm_mode == NON_PCM)) {
+			mv88fx_snd_error("");
+			return -1;
+		}
+
+	return 0;
+}
+
+static int mv88fx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	mv88fx_snd_debug("");
+	return 0;
+}
+
+static snd_pcm_uframes_t mv88fx_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	snd_pcm_uframes_t offset;
+	ssize_t size;
+
+	mv88fx_snd_debug("");
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		size = (ssize_t) mv88fx_snd_readl(chip->base,
+		       MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG(chip->port));
+		offset = bytes_to_frames(substream->runtime, size);
+	} else {
+		size = (ssize_t) mv88fx_snd_readl(chip->base,
+			MV_AUDIO_RECORD_BUF_BYTE_CNTR_REG(chip->port));
+		offset = bytes_to_frames(substream->runtime, size);
+	}
+	if (offset >= runtime->buffer_size)
+		offset = 0;
+
+	return offset;
+}
+
+static int mv88fx_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err = 0;
+
+	mv88fx_snd_debug("");
+
+	runtime->private_data = &chip->stream[substream->stream];
+
+	snd_soc_set_runtime_hwparams(substream, &mv88fx_pcm_hardware);
+
+	err = snd_pcm_hw_constraint_minmax(runtime,
+					   SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+					   chip->burst * 2,
+					   AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
+	if (err < 0)
+		return err;
+
+	err = snd_pcm_hw_constraint_step(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+					 chip->burst);
+	if (err < 0)
+		return err;
+
+	err = snd_pcm_hw_constraint_step(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+					 chip->burst);
+	if (err < 0)
+		return err;
+
+	err = snd_pcm_hw_constraint_minmax(runtime,
+					   SNDRV_PCM_HW_PARAM_PERIODS,
+					   MV88FX_SND_MIN_PERIODS,
+					   MV88FX_SND_MAX_PERIODS);
+	if (err < 0)
+		return err;
+
+	err = snd_pcm_hw_constraint_integer(runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static void mv88fx_pcm_reset_spdif_status(struct mv88fx_snd_chip *chip,
+					  int usr_bits)
+{
+	int i;
+
+	mv88fx_snd_debug("");
+
+	for (i = 0; i < 4; i++) {
+		chip->stream[SNDRV_PCM_STREAM_PLAYBACK].spdif_status[i] = 0;
+
+		mv88fx_snd_writel(chip->base,
+				  MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(chip->
+									 port,
+									 i), 0);
+		mv88fx_snd_writel(chip->base,
+				  MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(chip->
+									  port,
+									  i),
+				  0);
+		if (usr_bits) {
+			mv88fx_snd_writel(chip->base,
+					  MV_AUDIO_SPDIF_PLAY_USR_BITS_LEFT_REG
+					  (chip->port, i), 0);
+			mv88fx_snd_writel(chip->base,
+					  MV_AUDIO_SPDIF_PLAY_USR_BITS_RIGHT_REG
+					  (chip->port, i), 0);
+		}
+	}
+
+}
+
+static int mv88fx_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+
+	mv88fx_snd_debug("");
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		chip->pcm_mode = PCM;
+		mv88fx_pcm_reset_spdif_status(chip, 0);
+	}
+	return 0;
+}
+
+static int mv88fx_pcm_mmap(struct snd_pcm_substream *substream,
+			   struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	mv88fx_snd_debug("");
+
+	return dma_mmap_coherent(NULL, vma, runtime->dma_area,
+				 runtime->dma_addr, runtime->dma_bytes);
+}
+
+struct snd_pcm_ops mv88fx_pcm_ops = {
+	.open = mv88fx_pcm_open,
+	.close = mv88fx_pcm_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = mv88fx_pcm_hw_params,
+	.hw_free = mv88fx_pcm_hw_free,
+	.prepare = mv88fx_pcm_prepare,
+	.trigger = mv88fx_pcm_trigger,
+	.pointer = mv88fx_pcm_pointer,
+	.mmap = mv88fx_pcm_mmap,
+};
+
+static int mv88fx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES;
+
+	mv88fx_snd_debug("");
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_coherent(pcm->card->dev,
+				       size, &buf->addr, GFP_KERNEL);
+	if (!buf->area) {
+		mv88fx_snd_error("unable to allocate");
+		return -ENOMEM;
+	}
+	buf->bytes = size;
+	return 0;
+}
+
+static struct mv88fx_snd_chip *mv88fx_pcm_init(struct snd_pcm *pcm,
+					       struct platform_device *pdev,
+					       struct mv88fx_snd_machine_data
+					       *machine_data)
+{
+	struct mv88fx_snd_chip *chip;
+
+	mv88fx_snd_debug("");
+	chip = mv88fx_pcm_snd_chip =
+	    kzalloc(sizeof(struct mv88fx_snd_chip), GFP_KERNEL);
+	if (!chip)
+		return NULL;
+
+	chip->base = machine_data->base;
+
+	spin_lock_init(&chip->reg_lock);
+	chip->dev = &pdev->dev;
+	chip->port = machine_data->port;
+	chip->pcm = pcm;
+	chip->pdata = machine_data->pdata;
+	chip->ch_stat_valid = 1;
+	chip->burst = 128;
+	chip->loopback = 0;
+	chip->dco_ctrl_offst = 0x800;
+	chip->irq = machine_data->irq;
+
+	if (request_irq(machine_data->irq, mv88fx_pcm_dma_interrupt,
+		0, DRIVER_NAME, (void *)chip)) {
+		mv88fx_snd_error("");
+		goto error;
+	}
+	if (chip->pdata->dram != NULL)
+		if (mv88fx_conf_mbus_windows(chip, chip->pdata->dram)) {
+			mv88fx_snd_error("");
+			goto error;
+
+		}
+
+
+	mv88fx_pcm_init_stream(chip, &chip->stream[SNDRV_PCM_STREAM_PLAYBACK],
+			       SNDRV_PCM_STREAM_PLAYBACK);
+	mv88fx_pcm_init_stream(chip, &chip->stream[SNDRV_PCM_STREAM_CAPTURE],
+			       SNDRV_PCM_STREAM_CAPTURE);
+	chip->pcm_mode = PCM;
+
+	mv88fx_pcm_reset_spdif_status(chip, 1);
+
+	return chip;
+error:
+	free_irq(chip->irq, chip);
+	kfree(chip);
+	mv88fx_pcm_snd_chip = NULL;
+	return NULL;
+}
+
+static int mv88fx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
+			  struct snd_pcm *pcm)
+{
+	static u64 mv88fx_pcm_dmamask = DMA_BIT_MASK(32);
+	int ret = 0;
+	struct platform_device *pdev = to_platform_device(card->dev);
+	struct mv88fx_snd_machine_data *machine_data = pdev->dev.platform_data;
+	struct mv88fx_snd_chip *chip;
+
+	mv88fx_snd_debug("");
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &mv88fx_pcm_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	if (dai->playback.channels_min) {
+		ret = mv88fx_pcm_preallocate_dma_buffer(pcm,
+					SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret) {
+			mv88fx_snd_error("");
+			goto out;
+		}
+	}
+
+	if (dai->capture.channels_min) {
+		ret = mv88fx_pcm_preallocate_dma_buffer(pcm,
+					SNDRV_PCM_STREAM_CAPTURE);
+		if (ret) {
+			mv88fx_snd_error("");
+			goto out;
+		}
+	}
+	chip = mv88fx_pcm_init(pcm, pdev, machine_data);
+	if (!chip)
+		return -ENOMEM;
+
+	return 0;
+out:
+	return ret;
+}
+
+static void mv88fx_pcm_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+	int stream;
+
+	mv88fx_snd_debug("");
+
+	for (stream = 0; stream < ARRAY_SIZE(pcm->streams); stream++) {
+		substream = pcm->streams[stream].substream;
+		if (!substream)
+			continue;
+
+		buf = &substream->dma_buffer;
+		if (!buf->area)
+			continue;
+		dma_free_coherent(pcm->card->dev,
+				  buf->bytes, buf->area, buf->addr);
+		buf->area = NULL;
+		buf->addr = 0;
+	}
+	free_irq(mv88fx_pcm_snd_chip->irq, mv88fx_pcm_snd_chip);
+	kfree(mv88fx_pcm_snd_chip);
+	mv88fx_pcm_snd_chip = NULL;
+}
+
+
+static int mv88fx_pcm_suspend(struct snd_soc_dai *cpu_dai)
+{
+	mv88fx_snd_debug("");
+
+
+	return 0;
+}
+
+
+
+static int mv88fx_pcm_resume(struct snd_soc_dai *cpu_dai)
+{
+	mv88fx_snd_debug("");
+
+
+	return 0;
+}
+
+
+
+struct snd_soc_platform mv88fx_soc_platform = {
+	.name = DRIVER_NAME,
+	.pcm_new = mv88fx_pcm_new,
+	.pcm_free = mv88fx_pcm_free,
+	.suspend  = mv88fx_pcm_suspend,
+	.resume   = mv88fx_pcm_resume,
+	.pcm_ops = &mv88fx_pcm_ops,
+};
+EXPORT_SYMBOL_GPL(mv88fx_soc_platform);
+
+
+static int __init mv88fx_soc_platform_init(void)
+{
+	return snd_soc_register_platform(&mv88fx_soc_platform);
+}
+module_init(mv88fx_soc_platform_init);
+
+static void __exit mv88fx_soc_platform_exit(void)
+{
+	snd_soc_unregister_platform(&mv88fx_soc_platform);
+}
+module_exit(mv88fx_soc_platform_exit);
+
+
+
+
+MODULE_AUTHOR("Yuval Elmaliah <eyuval@marvell.com>");
+MODULE_DESCRIPTION("mv88fx ASoc Platform driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-pcm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-pcm.h
new file mode 100755
index 0000000..9443823
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-pcm.h
@@ -0,0 +1,126 @@
+/*
+ *
+ *	Marvell Orion Alsa SOC Sound driver
+ *
+ *	Author: Yuval Elmaliah
+ *	Copyright (C) 2008 Marvell Ltd
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ *
+ */
+
+
+#ifndef _MV88FX_PCM_H
+#define _MV88FX_PCM_H
+
+#define DRIVER_NAME	"mv88fx_snd"
+
+#ifdef MV88FX_SND_DEBUG
+#define mv88fx_snd_debug(format, args...) \
+	printk(KERN_DEBUG "%s(%d): "format"\n", __func__, __LINE__, ##args)
+#else
+#define mv88fx_snd_debug(a...)
+#endif
+#define mv88fx_snd_error(format, args...) \
+	printk(KERN_ERR "%s(%d): "format"\n", __func__, __LINE__, ##args)
+
+
+struct mv88fx_snd_stream {
+
+unsigned int dig_mode;	/* i2s,spdif,both */
+
+#define I2S		1
+#define SPDIF		2
+	int mono_mode;	/* both mono, left mono, right mono */
+#define MONO_BOTH	0
+#define MONO_LEFT	1
+#define MONO_RIGHT	2
+	int clock_src;
+
+#define DCO_CLOCK	0
+#define SPCR_CLOCK	1
+#define EXTERN_CLOCK	2
+	int stat_mem;	/* Channel status source */
+
+ unsigned int spdif_status[4];	/* SPDIF status */
+
+};
+
+
+struct mv88fx_snd_chip {
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	struct device *dev;
+	int port;
+	struct orion_i2s_platform_data *pdata;	/* platform dara */
+	struct mv88fx_snd_stream stream[2];	/* run time values */
+	spinlock_t reg_lock;	/* Register access spinlock */
+	void __iomem *base;	/* base address of the host */
+	int loopback;		/* When Loopback is enabled, playback
+				data is looped back to be recorded */
+	int ch_stat_valid;	/* Playback SPDIF channel validity bit
+				   value when REG selected */
+	int burst;		/* DMA Burst Size */
+#define SPDIF_MEM_STAT		0
+#define SPDIF_REG_STAT		1
+	unsigned int dco_ctrl_offst;
+	int pcm_mode;		/* pcm, nonpcm */
+#define PCM		0
+#define NON_PCM		1
+	int irq;
+
+};
+
+
+
+struct mv88fx_snd_machine_data {
+	struct platform_device *snd_dev;
+	int port;
+	void __iomem *base;	/* base address of the host */
+	int irq;
+	struct resource *res;	/* resource for IRQ and base */
+	struct orion_i2s_platform_data *pdata;	/* platform dara */
+#if defined(CONFIG_HAVE_CLK)
+	struct clk		*clk;
+#endif
+};
+
+
+#define MV88FX_SND_MIN_PERIODS		8
+#define MV88FX_SND_MAX_PERIODS		16
+#define	MV88FX_SND_MIN_PERIOD_BYTES	0x4000
+#define	MV88FX_SND_MAX_PERIOD_BYTES	0x4000
+
+
+/* read/write registers */
+#define mv88fx_snd_writel(base, offs, val)	\
+	writel((val), (base + offs))
+
+#define mv88fx_snd_readl(base, offs)	\
+	readl(base + offs)
+
+#define mv88fx_snd_bitset(base, offs, bitmask)	\
+	writel((readl(base + offs) | (bitmask)),	\
+	base + offs)
+
+#define mv88fx_snd_bitreset(base, offs, bitmask) \
+	writel((readl(base + offs) & (~(bitmask))), \
+	base + offs)
+
+
+
+
+extern struct mv88fx_snd_chip *mv88fx_pcm_snd_chip;
+
+#define mv88fx_pcm_get_chip() mv88fx_pcm_snd_chip
+#define mv88fx_pcm_is_stereo(runtime)        ((runtime)->channels != 1)
+
+
+extern struct snd_soc_platform mv88fx_soc_platform;
+
+
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-rt5623.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-rt5623.c
new file mode 100755
index 0000000..6f45b59
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx-rt5623.c
@@ -0,0 +1,359 @@
+/*
+ *
+ *	Marvell Orion Alsa SOC Sound driver
+ *
+ *	Author: Yuval Elmaliah
+ *	Author: Ethan Ku
+ *	Copyright (C) 2008 Marvell Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/asoundef.h>
+#include <asm/mach-types.h>
+//#include <asm/arch/hardware.h>
+#include "../sound/soc/codecs/rt5623.h"
+#include <linux/mbus.h>
+#include <asm/setup.h>
+#include <asm/mach/arch.h>
+#include <../arch/arm/mach-dove/common.h>
+//#include <asm/plat-orion/i2s-orion.h>
+#include "mv88fx-pcm.h"
+#include "mv88fx-i2s.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "audio/mvAudioRegs.h"
+
+extern int mvmpp_gpio_get_value(unsigned int);
+extern int mvmpp_gpio_set_value(unsigned int,int);
+
+static struct mv88fx_snd_machine_data mv88fx_machine_data;
+static struct rt5623_setup_data rt5623_setup;
+
+
+static int mv88fx_machine_startup(struct snd_pcm_substream *substream)
+{
+//	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+//	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+//	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+//	int ret;
+#if 0
+	int phoneInDetected;
+
+//	printk("%s\n",__func__);
+
+	/* check the jack status at stream startup */
+	phoneInDetected = mvmpp_gpio_get_value(MPP_PhLine_IN);
+
+	if (phoneInDetected < 0) {
+		snd_printk("Failed to detect phone-in.\n");
+	} else {
+
+		if (! phoneInDetected) {
+			rt5623_setup.mic2_input = 0;
+		} else {
+			rt5623_setup.mic2_input = 1;
+		}
+	}
+#endif
+	return 0;
+
+}
+
+
+static void mv88fx_machine_shutdown(struct snd_pcm_substream *substream)
+{
+//	printk("%s\n",__func__);
+}
+
+
+
+static int mv88fx_machine_hw_params(struct snd_pcm_substream *substream,	
+				   struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+	unsigned int clk = 0;
+	int ret = 0;
+	unsigned int format;
+
+//	printk("%s\n",__func__);
+	/* set codec DAI configuration */
+
+
+	switch (params_rate(params)) {
+	case 44100:
+		clk = 11289600;
+		break;
+	case 48000:
+		clk = 12288000;
+		break;
+	case 96000:
+		clk = 24576000;
+		break;
+	}
+
+	format = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF;
+	ret = codec_dai->ops->set_fmt(codec_dai, format);
+	if (ret < 0)
+		return ret;
+
+	/* set cpu DAI configuration */
+	ret = cpu_dai->ops->set_fmt(cpu_dai, format);
+	if (ret < 0)
+		return ret;
+
+	/* cpu clock is the mv88fx master clock sent to codec */
+	ret = cpu_dai->ops->set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	/* codec system clock is supplied by mv88fx*/
+	ret = codec_dai->ops->set_sysclk(codec_dai, 0, clk, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mv88fx_machine_trigger(struct snd_pcm_substream *substream,int cmd)
+{
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		if(substream->stream==SNDRV_PCM_STREAM_PLAYBACK)
+		{
+//			mvmpp_gpio_set_value(MPP_Amp_PwrDn,1);
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		if(substream->stream==SNDRV_PCM_STREAM_PLAYBACK)
+		{
+//			mvmpp_gpio_set_value(MPP_Amp_PwrDn,0);
+		}
+		break;
+
+	}
+	return 0;
+}
+
+static int mv88fx_rt5623_init(struct snd_soc_codec *codec)
+{
+	mv88fx_snd_debug("");
+//	mvmpp_gpio_set_value(MPP_Amp_PwrDn,0);
+	return 0;
+}
+
+
+/* machine stream operations */
+static struct snd_soc_ops mv88fx_rt5623_machine_ops =
+{
+	.startup = mv88fx_machine_startup,
+	.shutdown = mv88fx_machine_shutdown,
+	.hw_params = mv88fx_machine_hw_params,
+	.trigger = mv88fx_machine_trigger,
+
+};
+
+
+
+static struct snd_soc_dai_link mv88fx_dai = {
+	.name = "RT5623",
+	.stream_name = "RT5623",
+	.cpu_dai = &mv88fx_i2s_dai,
+	.codec_dai = &rt5623_dai,
+	.ops = &mv88fx_rt5623_machine_ops,
+	.init = mv88fx_rt5623_init,
+};
+
+static int mv88fx_probe(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int mv88fx_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct snd_soc_card dove = {
+	.name = "Dove",
+	.platform = &mv88fx_soc_platform,
+	.probe = mv88fx_probe,
+	.remove = mv88fx_remove,
+
+	/* CPU <--> Codec DAI links */
+	.dai_link = &mv88fx_dai,
+	.num_links = 1,
+};
+
+static struct rt5623_setup_data rt5623_setup = {
+	.i2c_address = 0x1a,
+	.mic2_input = 1,
+};
+
+
+static struct snd_soc_device mv88fx_snd_devdata = {
+	.card = &dove,
+	.codec_dev = &soc_codec_dev_rt5623,
+	.codec_data = &rt5623_setup,
+};
+
+static int mv88fx_initalize_machine_data(struct platform_device *pdev)
+{
+	struct resource *r = NULL;
+	int err = 0;
+
+	mv88fx_snd_debug("");
+
+	mv88fx_machine_data.port = pdev->id;
+	mv88fx_machine_data.pdata =
+		(struct orion_i2s_platform_data *)pdev->dev.platform_data;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		err = -ENXIO;
+		goto error;
+	}
+	r = request_mem_region(r->start, SZ_16K, DRIVER_NAME);
+	if (!r) {
+		err = -EBUSY;
+		goto error;
+	}
+	mv88fx_machine_data.res = r;
+	mv88fx_machine_data.base = ioremap(r->start, SZ_16K);
+
+	if (!mv88fx_machine_data.base) {
+		mv88fx_snd_error("ioremap failed");
+		err = -ENOMEM;
+		goto error;
+	}
+	mv88fx_machine_data.base -= MV_AUDIO_REGS_OFFSET(mv88fx_machine_data.port);
+
+	mv88fx_machine_data.irq = platform_get_irq(pdev, 0);
+	if (mv88fx_machine_data.irq == NO_IRQ) {
+		err = -ENXIO;
+		goto error;
+	}
+#if defined(CONFIG_HAVE_CLK)
+	mv88fx_machine_data.clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mv88fx_machine_data.clk))
+		dev_notice(&pdev->dev, "cannot get clkdev\n");
+	else
+		clk_enable(mv88fx_machine_data.clk);
+#endif
+	return 0;
+error:
+	if (mv88fx_machine_data.base) {
+		iounmap(mv88fx_machine_data.base);
+		mv88fx_machine_data.base = NULL;
+	}
+	release_mem_region(mv88fx_machine_data.res->start, SZ_16K);
+	return err;
+}
+
+static int mv88fx_snd_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	mv88fx_snd_debug("");
+
+	if (mv88fx_initalize_machine_data(pdev) != 0)
+		goto error;
+
+	mv88fx_machine_data.snd_dev = platform_device_alloc("soc-audio", -1);
+	if (!mv88fx_machine_data.snd_dev) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	platform_set_drvdata(mv88fx_machine_data.snd_dev, &mv88fx_snd_devdata);
+	mv88fx_snd_devdata.dev = &mv88fx_machine_data.snd_dev->dev;
+
+	mv88fx_machine_data.snd_dev->dev.platform_data = &mv88fx_machine_data;
+
+	ret = platform_device_add(mv88fx_machine_data.snd_dev);
+
+	if(ret)
+	{
+                platform_device_put(mv88fx_machine_data.snd_dev);
+	}
+
+	return ret;
+error:
+	mv88fx_snd_error("");
+#if defined(CONFIG_HAVE_CLK)
+	if (!IS_ERR(mv88fx_machine_data.clk)) {
+		clk_disable(mv88fx_machine_data.clk);
+		clk_put(mv88fx_machine_data.clk);
+	}
+#endif
+	if (mv88fx_machine_data.snd_dev)
+		platform_device_unregister(mv88fx_machine_data.snd_dev);
+	return ret;
+
+}
+
+static int mv88fx_snd_remove(struct platform_device *dev)
+{
+	mv88fx_snd_debug("");
+#if defined(CONFIG_HAVE_CLK)
+	if (!IS_ERR(mv88fx_machine_data.clk)) {
+		clk_disable(mv88fx_machine_data.clk);
+		clk_put(mv88fx_machine_data.clk);
+	}
+#endif
+	mv88fx_machine_data.snd_dev->dev.platform_data = NULL;
+	platform_device_unregister(mv88fx_machine_data.snd_dev);
+	release_mem_region(mv88fx_machine_data.res->start, SZ_16K);
+	return 0;
+}
+
+static struct platform_driver mv88fx_snd_driver = {
+	.probe = mv88fx_snd_probe,
+	.remove = mv88fx_snd_remove,
+	.suspend = NULL,
+	.resume = NULL,
+	.driver = {
+		   .name = DRIVER_NAME,
+		   },
+
+};
+
+static int __init mv88fx_snd_init(void)
+{
+	if (!machine_is_dove_rd_avng())
+		return -ENODEV;
+
+	mv88fx_snd_debug("");
+	return platform_driver_register(&mv88fx_snd_driver);
+}
+
+static void __exit mv88fx_snd_exit(void)
+{
+	mv88fx_snd_debug("");
+	platform_driver_unregister(&mv88fx_snd_driver);
+
+}
+
+module_init(mv88fx_snd_init);
+module_exit(mv88fx_snd_exit);
+
+/* Module information */
+MODULE_AUTHOR("Yuval Elmaliah <eyuval@marvell.com>");
+MODULE_AUTHOR("Ethan Ku <eku@marvell.com>");
+MODULE_DESCRIPTION("ALSA SoC Dove");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx.c
new file mode 100755
index 0000000..239394e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/mv88fx.c
@@ -0,0 +1,648 @@
+/*
+ *
+ *	Marvell Orion Alsa SOC Sound driver
+ *
+ *	Author: Yuval Elmaliah
+ *	Copyright (C) 2008 Marvell Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+#include <sound/asoundef.h>
+#include <asm/mach-types.h>
+#include "../sound/soc/codecs/cs42l51.h"
+#include <linux/mbus.h>
+#include <asm/setup.h>
+#include <asm/mach/arch.h>
+//#include <../arch/arm/mach-dove/common.h>
+#include <plat/i2s-orion.h>
+#include "mv88fx-pcm.h"
+#include "mv88fx-i2s.h"
+#include "audio/mvAudioRegs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+static struct mv88fx_snd_machine_data mv88fx_machine_data;
+
+static int mv88fx_snd_spdif_mask_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int mv88fx_snd_spdif_mask_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.iec958.status[0] = 0xff;
+	ucontrol->value.iec958.status[1] = 0xff;
+	ucontrol->value.iec958.status[2] = 0xff;
+	ucontrol->value.iec958.status[3] = 0xff;
+	return 0;
+}
+
+static struct snd_kcontrol_new mv88fx_snd_spdif_mask = {
+	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+	.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
+	.info = mv88fx_snd_spdif_mask_info,
+	.get = mv88fx_snd_spdif_mask_get,
+};
+
+static int mv88fx_snd_spdif_stream_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	mv88fx_snd_debug("");
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int mv88fx_snd_spdif_stream_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
+	int i, word;
+
+	mv88fx_snd_debug("");
+	spin_lock_irq(&chip->reg_lock);
+	for (word = 0; word < 4; word++) {
+		chip->stream[SNDRV_PCM_STREAM_PLAYBACK].spdif_status[word] =
+		    mv88fx_snd_readl(chip->base,
+		     MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(chip->port, word));
+		for (i = 0; i < 4; i++)
+			ucontrol->value.iec958.status[word + i] =
+			    (chip->stream[SNDRV_PCM_STREAM_PLAYBACK].
+			     spdif_status[word] >> (i * 8)) & 0xff;
+
+	}
+	spin_unlock_irq(&chip->reg_lock);
+	return 0;
+}
+
+static int mv88fx_snd_spdif_stream_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
+	int i, change = 0, word;
+	unsigned int val;
+	struct mv88fx_snd_stream *pbstream =
+		&chip->stream[SNDRV_PCM_STREAM_PLAYBACK];
+	int port = chip->port;
+
+	mv88fx_snd_debug("");
+	val = 0;
+	port = port;
+	spin_lock_irq(&chip->reg_lock);
+	for (word = 0; word < 4; word++) {
+		for (i = 0; i < 4; i++) {
+			chip->stream[SNDRV_PCM_STREAM_PLAYBACK].
+			    spdif_status[word] |=
+			    ucontrol->value.iec958.status[word + i] << (i * 8);
+		}
+		mv88fx_snd_writel(chip->base,
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(port, word),
+			pbstream->spdif_status[word]);
+
+		mv88fx_snd_writel(chip->base,
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(port, word),
+			pbstream->spdif_status[word]);
+
+	}
+
+	if (pbstream->spdif_status[0] & IEC958_AES0_NONAUDIO)
+		chip->pcm_mode = NON_PCM;
+
+	spin_unlock_irq(&chip->reg_lock);
+	return change;
+}
+
+static struct snd_kcontrol_new mv88fx_snd_spdif_stream = {
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+	    SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+	.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
+	.info = mv88fx_snd_spdif_stream_info,
+	.get = mv88fx_snd_spdif_stream_get,
+	.put = mv88fx_snd_spdif_stream_put
+};
+
+static int mv88fx_snd_spdif_default_info(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_info *uinfo)
+{
+	mv88fx_snd_debug("");
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int mv88fx_snd_spdif_default_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
+	struct mv88fx_snd_stream *pbstream =
+		&chip->stream[SNDRV_PCM_STREAM_PLAYBACK];
+	int port = chip->port;
+	int i, word;
+
+	mv88fx_snd_debug("");
+
+	port = port;
+	spin_lock_irq(&chip->reg_lock);
+	for (word = 0; word < 4; word++) {
+		pbstream->spdif_status[word] =
+		    mv88fx_snd_readl(chip->base,
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(port, word));
+
+		for (i = 0; i < 4; i++)
+			ucontrol->value.iec958.status[word + i] =
+			(pbstream->spdif_status[word] >> (i * 8)) & 0xff;
+
+	}
+	spin_unlock_irq(&chip->reg_lock);
+	return 0;
+}
+
+static int mv88fx_snd_spdif_default_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
+	struct mv88fx_snd_stream *pbstream =
+		&chip->stream[SNDRV_PCM_STREAM_PLAYBACK];
+	int port = chip->port;
+	int i, change = 0, word;
+	unsigned int val;
+
+	mv88fx_snd_debug("");
+
+	port = port;
+	val = 0;
+	spin_lock_irq(&chip->reg_lock);
+	for (word = 0; word < 4; word++) {
+		for (i = 0; i < 4; i++) {
+			pbstream->spdif_status[word] |=
+			    ucontrol->value.iec958.status[word + i] << (i * 8);
+		}
+		mv88fx_snd_writel(chip->base,
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(port, word),
+			pbstream->spdif_status[word]);
+		mv88fx_snd_writel(chip->base,
+			MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(port, word),
+			pbstream->spdif_status[word]);
+
+	}
+	if (pbstream->spdif_status[0] & IEC958_AES0_NONAUDIO)
+		chip->pcm_mode = NON_PCM;
+
+
+	spin_unlock_irq(&chip->reg_lock);
+	return change;
+}
+static struct snd_kcontrol_new mv88fx_snd_spdif_default = {
+	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+	.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+	.info = mv88fx_snd_spdif_default_info,
+	.get = mv88fx_snd_spdif_default_get,
+	.put = mv88fx_snd_spdif_default_put
+};
+
+struct mv88fx_snd_mixer_enum {
+	char **names;		/* enum names */
+	int *values;		/* values to be updated */
+	int count;		/* number of elements */
+	void *rec;		/* field to be updated */
+};
+
+int mv88fx_snd_mixer_enum_info(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_info *uinfo)
+{
+	struct mv88fx_snd_mixer_enum *mixer_enum =
+	    (struct mv88fx_snd_mixer_enum *)kcontrol->private_value;
+
+	mv88fx_snd_debug("");
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = mixer_enum->count;
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+
+	strcpy(uinfo->value.enumerated.name,
+	       mixer_enum->names[uinfo->value.enumerated.item]);
+
+	return 0;
+}
+int mv88fx_snd_mixer_enum_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct mv88fx_snd_mixer_enum *mixer_enum =
+	    (struct mv88fx_snd_mixer_enum *)kcontrol->private_value;
+	int i;
+	unsigned int val;
+
+	mv88fx_snd_debug("");
+
+	val = *(unsigned int *)mixer_enum->rec;
+
+	for (i = 0; i < mixer_enum->count; i++) {
+
+		if (val == (unsigned int)mixer_enum->values[i]) {
+			ucontrol->value.enumerated.item[0] = i;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+int mv88fx_snd_mixer_enum_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	unsigned int val, *rec;
+	struct mv88fx_snd_mixer_enum *mixer_enum =
+	    (struct mv88fx_snd_mixer_enum *)kcontrol->private_value;
+	int i;
+
+	mv88fx_snd_debug("");
+
+	rec = (unsigned int *)mixer_enum->rec;
+	val = ucontrol->value.enumerated.item[0];
+
+	if (val < 0)
+		val = 0;
+	if (val > mixer_enum->count)
+		val = mixer_enum->count;
+
+	for (i = 0; i < mixer_enum->count; i++) {
+
+		if (val == i) {
+			*rec = (unsigned int)mixer_enum->values[i];
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#define MV88FX_PCM_MIXER_ENUM(xname, xindex, value)	\
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .info = mv88fx_snd_mixer_enum_info, \
+  .get = mv88fx_snd_mixer_enum_get, \
+  .put = mv88fx_snd_mixer_enum_put, \
+  .private_value = (unsigned long)value,	\
+}
+
+char *playback_src_mixer_names[] = { "SPDIF", "I2S", "SPDIF And I2S" };
+int playback_src_mixer_values[] = { SPDIF, I2S, (SPDIF | I2S) };
+
+struct mv88fx_snd_mixer_enum playback_src_mixer = {
+	.names = playback_src_mixer_names,
+	.values = playback_src_mixer_values,
+	.count = 3,
+};
+
+char *playback_mono_mixer_names[] = { "Mono Both", "Mono Left", "Mono Right" };
+int playback_mono_mixer_values[] = { MONO_BOTH, MONO_LEFT, MONO_RIGHT };
+
+struct mv88fx_snd_mixer_enum playback_mono_mixer = {
+	.names = playback_mono_mixer_names,
+	.values = playback_mono_mixer_values,
+	.count = 3,
+};
+
+char *capture_src_mixer_names[] = { "SPDIF", "I2S" };
+int capture_src_mixer_values[] = { SPDIF, I2S };
+
+struct mv88fx_snd_mixer_enum capture_src_mixer = {
+	.names = capture_src_mixer_names,
+	.values = capture_src_mixer_values,
+	.count = 2,
+};
+
+char *capture_mono_mixer_names[] = { "Mono Left", "Mono Right" };
+int capture_mono_mixer_values[] = { MONO_LEFT, MONO_RIGHT };
+
+struct mv88fx_snd_mixer_enum capture_mono_mixer = {
+	.names = capture_mono_mixer_names,
+	.values = capture_mono_mixer_values,
+	.count = 2,
+};
+
+static struct snd_kcontrol_new mv88fx_snd_mixers[] = {
+	MV88FX_PCM_MIXER_ENUM("Playback output type", 0,
+			      &playback_src_mixer),
+
+	MV88FX_PCM_MIXER_ENUM("Playback mono type", 0,
+			      &playback_mono_mixer),
+
+	MV88FX_PCM_MIXER_ENUM("Capture input Type", 0,
+			      &capture_src_mixer),
+
+	MV88FX_PCM_MIXER_ENUM("Capture mono type", 0,
+			      &capture_mono_mixer),
+
+};
+
+#define	PLAYBACK_MIX_INDX	0
+#define PLAYBACK_MONO_MIX_INDX	1
+#define CAPTURE_MIX_INDX	2
+#define	CAPTURE_MONO_MIX_INDX	3
+
+static int mv88fx_snd_ctrl_new(struct snd_card *card)
+{
+	int err = 0;
+	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();
+
+	playback_src_mixer.rec =
+	    &chip->stream[SNDRV_PCM_STREAM_PLAYBACK].dig_mode;
+	playback_mono_mixer.rec =
+	    &chip->stream[SNDRV_PCM_STREAM_PLAYBACK].mono_mode;
+
+	capture_src_mixer.rec =
+	    &chip->stream[SNDRV_PCM_STREAM_CAPTURE].dig_mode;
+	capture_mono_mixer.rec =
+	    &chip->stream[SNDRV_PCM_STREAM_CAPTURE].mono_mode;
+
+	if (chip->pdata->i2s_play && chip->pdata->spdif_play) {
+		err =
+		    snd_ctl_add(card,
+				snd_ctl_new1(&mv88fx_snd_mixers
+					     [PLAYBACK_MIX_INDX], chip));
+		if (err < 0)
+			return err;
+	}
+
+	if (chip->pdata->i2s_play || chip->pdata->spdif_play) {
+		err =
+		    snd_ctl_add(card,
+				snd_ctl_new1(&mv88fx_snd_mixers
+					     [PLAYBACK_MONO_MIX_INDX], chip));
+		if (err < 0)
+			return err;
+	}
+
+	if (chip->pdata->i2s_rec && chip->pdata->spdif_rec) {
+		err =
+		    snd_ctl_add(card,
+				snd_ctl_new1(&mv88fx_snd_mixers
+					     [CAPTURE_MIX_INDX], chip));
+		if (err < 0)
+			return err;
+	}
+
+	if (chip->pdata->i2s_rec || chip->pdata->spdif_rec) {
+		err =
+		    snd_ctl_add(card,
+				snd_ctl_new1(&mv88fx_snd_mixers
+					     [CAPTURE_MONO_MIX_INDX], chip));
+		if (err < 0)
+			return err;
+	}
+
+	if (chip->pdata->spdif_play) {
+		err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_mask,
+						     chip));
+		if (err < 0)
+			return err;
+	}
+	if (chip->pdata->spdif_play) {
+		err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_default,
+						     chip));
+		if (err < 0)
+			return err;
+	}
+	if (chip->pdata->spdif_play) {
+		err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_stream,
+						     chip));
+		if (err < 0)
+			return err;
+	}
+
+	return err;
+}
+
+
+static int mv88fx_cs42l51_init(struct snd_soc_codec *codec)
+{
+	mv88fx_snd_debug("");
+
+#ifdef CONFIG_MACH_DOVE_RD_AVNG
+	/* Default Gain */
+	snd_soc_update_bits(codec, CS42L51_REG_DAC_OUTPUT_CTRL, 0xE0, 0xE0);
+
+#endif
+
+	mv88fx_snd_ctrl_new(codec->card);
+
+	return 0;
+}
+
+static struct snd_soc_dai_link mv88fx_dai[] = {
+	{
+	 .name = "CS42L51",
+	 .stream_name = "CS42L51",
+	 .cpu_dai = &mv88fx_i2s_dai,
+	 .codec_dai = &cs42l51_dai,
+	 .init = mv88fx_cs42l51_init,
+	 },
+};
+
+static int mv88fx_probe(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int mv88fx_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct snd_soc_card mv_i2s = {
+	.name = "mv_i2s",
+	.platform = &mv88fx_soc_platform,
+	.probe = mv88fx_probe,
+	.remove = mv88fx_remove,
+	/* CPU <--> Codec DAI links */
+	.dai_link = mv88fx_dai,
+	.num_links = ARRAY_SIZE(mv88fx_dai),
+};
+
+struct cs42l51_setup_data mv88fx_codec_setup_data = {
+	.i2c_address = 0x4A,
+};
+
+static struct snd_soc_device mv88fx_snd_devdata = {
+	.card = &mv_i2s,
+	.codec_dev = &soc_codec_dev_cs42l51,
+	.codec_data = &mv88fx_codec_setup_data,
+};
+
+static int mv88fx_initalize_machine_data(struct platform_device *pdev)
+{
+	struct resource *r = NULL;
+	int err = 0;
+
+	mv88fx_snd_debug("");
+
+	mv88fx_machine_data.port = pdev->id;
+	mv88fx_machine_data.pdata =
+	    (struct orion_i2s_platform_data *)pdev->dev.platform_data;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		mv88fx_snd_error("");
+		err = -ENXIO;
+		goto error;
+	}
+	r = request_mem_region(r->start, SZ_16K, DRIVER_NAME);
+	if (!r) {
+		mv88fx_snd_error("");
+		err = -EBUSY;
+		goto error;
+	}
+	mv88fx_machine_data.res = r;
+	mv88fx_machine_data.base = ioremap(r->start, SZ_16K);
+
+	if (!mv88fx_machine_data.base) {
+		mv88fx_snd_error("ioremap failed");
+		err = -ENOMEM;
+		goto error;
+	}
+	mv88fx_machine_data.base -= MV_AUDIO_REGS_OFFSET(mv88fx_machine_data.port);
+
+	mv88fx_machine_data.irq = platform_get_irq(pdev, 0);
+	if (mv88fx_machine_data.irq == NO_IRQ) {
+		mv88fx_snd_error("");
+		err = -ENXIO;
+		goto error;
+	}
+#if defined(CONFIG_HAVE_CLK)
+	mv88fx_machine_data.clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mv88fx_machine_data.clk))
+		dev_notice(&pdev->dev, "cannot get clkdev\n");
+	else
+		clk_enable(mv88fx_machine_data.clk);
+#endif
+
+	return 0;
+error:
+	if (mv88fx_machine_data.base) {
+		iounmap(mv88fx_machine_data.base);
+		mv88fx_machine_data.base = NULL;
+	}
+	release_mem_region(mv88fx_machine_data.res->start, SZ_16K);
+	return err;
+}
+
+static int mv88fx_snd_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	mv88fx_snd_debug("");
+
+	if (mv88fx_initalize_machine_data(pdev) != 0)
+		goto error;
+	mv88fx_machine_data.snd_dev = platform_device_alloc("soc-audio", 1);
+	if (!mv88fx_machine_data.snd_dev) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	platform_set_drvdata(mv88fx_machine_data.snd_dev, &mv88fx_snd_devdata);
+	mv88fx_snd_devdata.dev = &mv88fx_machine_data.snd_dev->dev;
+
+	mv88fx_machine_data.snd_dev->dev.platform_data = &mv88fx_machine_data;
+
+	ret = platform_device_add(mv88fx_machine_data.snd_dev);
+
+	mv88fx_snd_debug("");
+
+	return 0;
+error:
+	mv88fx_snd_error("");
+
+#if defined(CONFIG_HAVE_CLK)
+	if (!IS_ERR(mv88fx_machine_data.clk)) {
+		clk_disable(mv88fx_machine_data.clk);
+		clk_put(mv88fx_machine_data.clk);
+	}
+#endif
+
+	if (mv88fx_machine_data.snd_dev)
+		platform_device_unregister(mv88fx_machine_data.snd_dev);
+	return ret;
+
+}
+
+static int mv88fx_snd_remove(struct platform_device *dev)
+{
+	mv88fx_snd_debug("");
+
+#if defined(CONFIG_HAVE_CLK)
+	if (!IS_ERR(mv88fx_machine_data.clk)) {
+		clk_disable(mv88fx_machine_data.clk);
+		clk_put(mv88fx_machine_data.clk);
+	}
+#endif
+	mv88fx_machine_data.snd_dev->dev.platform_data = NULL;
+	platform_device_unregister(mv88fx_machine_data.snd_dev);
+	release_mem_region(mv88fx_machine_data.res->start, SZ_16K);
+	return 0;
+}
+
+static struct platform_driver mv88fx_snd_driver = {
+	.probe = mv88fx_snd_probe,
+	.remove = mv88fx_snd_remove,
+	.suspend = NULL,
+	.resume = NULL,
+	.driver = {
+		   .name = DRIVER_NAME,
+		   },
+
+};
+
+static int __init mv88fx_snd_init(void)
+{
+#ifdef CONFIG_ARCH_DOVE
+	if (!machine_is_dove_db() && !machine_is_dove_db_z0())
+		return -ENODEV;
+#endif
+
+	mv88fx_snd_debug("");
+	return platform_driver_register(&mv88fx_snd_driver);
+}
+
+static void __exit mv88fx_snd_exit(void)
+{
+	mv88fx_snd_debug("");
+	platform_driver_unregister(&mv88fx_snd_driver);
+
+}
+
+module_init(mv88fx_snd_init);
+module_exit(mv88fx_snd_exit);
+
+/* Module information */
+MODULE_AUTHOR("Yuval Elmaliah <eyuval@marvell.com>");
+MODULE_DESCRIPTION("ALSA Marvell SoC");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/Makefile
new file mode 100755
index 0000000..bc266eb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/Makefile
@@ -0,0 +1,8 @@
+#

+# Makefile for the Marvell btns Driver

+#

+ifeq ($(CONFIG_ARCH_FEROCEON),y)

+	include $(srctree)/$(MACHINE)/config/mvRules.mk

+endif

+

+obj-y += btns_driver.o

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/btns_driver.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/btns_driver.c
new file mode 100755
index 0000000..8f89f04
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/btns_driver.c
@@ -0,0 +1,360 @@
+/*******************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include "btns_dev.h"
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "gpp/mvGpp.h"
+#include "gpp/mvGppRegs.h"
+#include "btns_driver.h"
+
+
+/* MACROS */
+#define GPP_GROUP(gpp) 	gpp/32
+#define GPP_ID(gpp)   	gpp%32
+#define GPP_BIT(gpp)	0x1 << GPP_ID(gpp)
+
+/* waiting Q */
+wait_queue_head_t btns_waitq;
+
+/*
+ * common debug for all
+ */
+#undef DEBUG
+
+#ifdef DEBUG
+#define dprintk   printk
+#else
+#define dprintk(a...)
+#endif
+
+/* At GPP initialization, this strucure is filled with what       
+ * operation will be monitored for each button (Push and/or          
+ * Release) */ 
+BTN_OP 	btn_op_cfg[CONFIG_MV_GPP_MAX_PINS] = {BTN_NO_OP};
+
+/* At GPP initialization, this strucure is filled with what       
+ * operation will be monitored for each button (Push and/or          
+ * Release) */ 
+u32 	gpp_default_val_cfg[CONFIG_MV_GPP_MAX_PINS] = {-1};
+
+/* This structures monitors how many time each button was 	  
+ * Push/Released since the last time it was sampled */ 
+BTN		btns_status[CONFIG_MV_GPP_MAX_PINS];
+
+u32		is_opend = 0;
+u32		gpp_changed = 0;
+u32		gpp_changed_id = -1;
+
+
+/*
+ * Get GPP real value....
+ * When Gpp is input:
+ * Since reading GPP_DATA_IN_REG return the GPP real value after considering the active polarity
+ * active low = 1, active high = 0
+ * we will use: val^0 -> val, val^1->not(val)
+ * when output don't consider the active polarity
+ */
+static unsigned int 
+mv_gpp_value_real_get(unsigned int gpp_group, unsigned int mask)
+{
+        unsigned int temp, in_out, gpp_val;
+        /* in ->1,  out -> 0 */
+        in_out = MV_REG_READ(GPP_DATA_OUT_EN_REG(gpp_group)) & mask;
+
+	gpp_val = MV_REG_READ(GPP_DATA_IN_REG(gpp_group)) & mask;
+
+        /* outputs values */
+        temp = (gpp_val & ~in_out);
+
+        /* input */
+        temp |= (( gpp_val ^ MV_REG_READ(GPP_DATA_IN_POL_REG(gpp_group)) ) & in_out) & mask;
+
+        return temp;
+}
+
+
+static irqreturn_t
+mv_btns_handler(int irq , void *dev_id)
+{
+	u32 gpp = (u32) irq - IRQ_GPP_START;
+	u32 gpp_level, gppVal;
+	BTN_OP btn_op;
+	
+	/* get gpp real val */
+	gppVal = mv_gpp_value_real_get(GPP_GROUP(gpp), GPP_BIT(gpp));
+
+	dprintk("Gpp value was changed: ");
+        if (btn_op_cfg[gpp] != BTN_NO_OP) {
+                dprintk("gpp %d has changed. now it's %x \n",gpp,
+				mv_gpp_value_real_get(GPP_GROUP(gpp), GPP_BIT(gpp)) );
+		
+		/* Count button Pushes/Releases
+		 * mv_gpp_value_real_get == gpp_default_val_cfg[gpp] --> Button push, 
+		 * else --> Button release
+		 */
+		btn_op = (gppVal == gpp_default_val_cfg[gpp]) ? BTN_PUSH : BTN_RELEASE;
+
+		if(btn_op == BTN_RELEASE)
+		{
+			dprintk("button (of gpp %d) was released \n",gpp);
+
+			btns_status[gpp].btn_release_cntr++;
+		} else {
+			dprintk("button (of gpp %d) was pressed \n",gpp);
+			
+			btns_status[gpp].btn_push_cntr++;
+		}
+		
+                /* change polarity */
+                gpp_level = MV_REG_READ(GPP_DATA_IN_POL_REG(GPP_GROUP(gpp)));
+                gpp_level = gpp_level^GPP_BIT(gpp);
+                MV_REG_WRITE(GPP_DATA_IN_POL_REG(GPP_GROUP(gpp)), gpp_level);
+
+		/* Check if current botton operation should be monitored */
+		if(btn_op_cfg[gpp] == btn_op || btn_op_cfg[gpp] == BTN_CHANGE)
+		{
+			gpp_changed = 1;
+			gpp_changed_id = gpp;
+			wake_up_interruptible(&btns_waitq);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int
+btnsdev_ioctl(
+        struct inode *inode,
+        struct file *filp,
+        unsigned int cmd,
+        unsigned long arg)
+{
+	unsigned int btn_id;
+	BTN btn_sts;
+	BTN_PTR user_btn_sts_ptr;
+	unsigned int error = 0;
+	int i;	
+
+        dprintk("%s()\n", __FUNCTION__);
+
+        switch (cmd) {
+        case CIOCWAIT_P:
+		/* Haim - Is the condition here correct? */
+            	error = wait_event_interruptible(btns_waitq, gpp_changed);
+		/* Reset Wait Q condition */
+		gpp_changed = 0;
+
+		if(error < 0)
+			dprintk("%s(CIOCWAIT_P) - got interrupted\n", __FUNCTION__);
+		
+		/* Set information for user*/
+		btn_sts.btn_id = gpp_changed_id;
+		btn_sts.btn_push_cntr   =btns_status[gpp_changed_id].btn_push_cntr;
+		btn_sts.btn_release_cntr=btns_status[gpp_changed_id].btn_release_cntr;
+		
+		dprintk("Button ID %d was pressed %d and released %d\n",gpp_changed_id,
+			btns_status[gpp_changed_id].btn_push_cntr,btns_status[gpp_changed_id].btn_release_cntr);
+
+		user_btn_sts_ptr = &(((BTNS_STS_PTR)arg)->btns[0]);
+		if ( copy_to_user((void*)user_btn_sts_ptr, &btn_sts,  sizeof(BTN)) ) {
+                        dprintk("%s(CIOCWAIT_P) - bad copy\n", __FUNCTION__);
+                        error = EFAULT;
+                }
+
+		/* Reset changed button operations counters*/
+		btns_status[gpp_changed_id].btn_push_cntr = 0;
+		btns_status[gpp_changed_id].btn_release_cntr = 0;
+
+                break;
+	case CIOCNOWAIT_P:
+		/* Eventhough we don't monitor for a button status change, we need to 
+ 			reset the indication of a change in case it happend */
+		gpp_changed = 0;
+
+		dprintk("There are %d buttons to be checked\n", ((BTNS_STS_PTR)arg)->btns_number);
+
+		/* Set information for user*/
+		for (i=0; i<((BTNS_STS_PTR)arg)->btns_number; i++)
+		{
+			btn_id = ((BTNS_STS_PTR)arg)->btns[i].btn_id;
+
+			/* initialize temp strucure which will be copied to user */
+			btn_sts.btn_id = btn_id;
+			btn_sts.btn_push_cntr = btns_status[btn_id].btn_push_cntr;
+			btn_sts.btn_release_cntr = btns_status[btn_id].btn_release_cntr;
+
+			/* Reset button's operations counters*/
+			btns_status[btn_id].btn_push_cntr = 0;
+			btns_status[btn_id].btn_release_cntr = 0;
+
+			/* Copy temp structure to user */
+			user_btn_sts_ptr = &(((BTNS_STS_PTR)arg)->btns[i]);
+
+			if ( copy_to_user((void*)user_btn_sts_ptr, &btn_sts,  sizeof(BTN)) ) {
+				dprintk("%s(CIOCNOWAIT_P) - bad copy\n", __FUNCTION__);
+				error = EFAULT;
+			}
+		}
+		
+		break;
+        default:
+                dprintk("%s(unknown ioctl 0x%x)\n", __FUNCTION__, cmd);
+                error = EINVAL;
+                break;
+        }
+        return(-error);
+}
+
+/*
+ * btn_gpp_init
+ * initialize on button's GPP and registers its IRQ
+ *
+ */
+static int  
+btn_gpp_init(unsigned int gpp, unsigned int default_gpp_val, BTN_OP btn_op, char* btn_name)
+{
+	unsigned int pol;
+	/* Set Polarity bit */
+	pol = MV_REG_READ(GPP_DATA_IN_POL_REG(GPP_GROUP(gpp)));
+	pol |= GPP_BIT(gpp);
+	MV_REG_WRITE(GPP_DATA_IN_POL_REG(GPP_GROUP(gpp)), pol);
+	
+	/* Set which button operation should be monitored */
+	btn_op_cfg[gpp] = btn_op;
+
+	/* Set GPP default value*/
+	gpp_default_val_cfg[gpp] = default_gpp_val;
+
+	/* Register IRQ */
+	if( request_irq( IRQ_GPP_START + gpp, mv_btns_handler,
+		IRQF_DISABLED, btn_name, NULL ) ) 
+	{
+		printk( KERN_ERR "btnsdev:  can't get irq for button %s (GPP %d)\n",btn_name,gpp );
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+btnsdev_open(struct inode *inode, struct file *filp)
+{
+        dprintk("%s()\n", __FUNCTION__);
+
+	if(!is_opend) {
+		is_opend = 1;
+		
+		/* Reset button operations counters*/
+		memset(&btns_status,0,CONFIG_MV_GPP_MAX_PINS);
+	}
+
+        return(0);
+}
+
+static int
+btnsdev_release(struct inode *inode, struct file *filp)
+{
+        dprintk("%s()\n", __FUNCTION__);
+        return(0);
+}
+
+
+static struct file_operations btnsdev_fops = {
+        .open = btnsdev_open,
+        .release = btnsdev_release,
+        .ioctl = btnsdev_ioctl,
+};
+
+static struct miscdevice btnsdev = {
+        .minor = BTNSDEV_MINOR,
+        .name = "btns",
+        .fops = &btnsdev_fops,
+};
+
+
+static int 
+btns_probe(struct platform_device *pdev)
+{
+        struct btns_platform_data *btns_data = pdev->dev.platform_data;
+        int ret, i;
+	
+	dprintk("%s\n", __FUNCTION__);
+	printk(KERN_NOTICE "MV Buttons Driver Load\n");
+
+        for (i = 0; i < btns_data->btns_num; i++) {
+		ret = btn_gpp_init(btns_data->btns_data_arr[i].gpp_id, btns_data->btns_data_arr[i].default_gpp_val, 
+					btns_data->btns_data_arr[i].btn_op, btns_data->btns_data_arr[i].btn_name);
+
+		if (ret != 0) {
+			return ret;
+		}
+        }
+
+        return 0;
+}
+
+
+static struct platform_driver btns_driver = {
+	.probe          = btns_probe,
+	.driver  = {
+        	.name		= MV_BTNS_NAME,
+	},
+};
+
+
+static int __init
+btnsdev_init(void)
+{
+	int rc;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	/* Initialize Wait Q*/
+	init_waitqueue_head(&btns_waitq);
+	
+	/* Register btns device */
+	if (misc_register(&btnsdev)) 
+        {
+            printk(KERN_ERR "btnsdev: registration of /dev/btnsdev failed\n");
+            return -1;
+        }
+
+	/* Register platform driver*/
+	rc = platform_driver_register(&btns_driver);
+	if (rc) {
+		printk(KERN_ERR "btnsdev: registration of platform driver failed\n");
+		return rc;
+	}
+
+        return 0;
+}
+
+static void __exit
+btnsdev_exit(void)
+{
+	dprintk("%s() should never be called.\n", __FUNCTION__);
+}
+
+module_init(btnsdev_init);
+module_exit(btnsdev_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ronen Shitrit & Haim Boot");
+MODULE_DESCRIPTION("PH: Buttons press handling.");
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/btns_driver.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/btns_driver.h
new file mode 100755
index 0000000..31876cf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_btns/btns_driver.h
@@ -0,0 +1,60 @@
+/*******************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#ifndef _BTNS_DRIVER_H_
+#define _BTNS_DRIVER_H_
+
+typedef enum
+{
+	BTN_NO_OP,
+	BTN_PUSH,
+	BTN_RELEASE,
+	BTN_CHANGE /* Both Push & Release will be monitored */
+} BTN_OP;
+
+
+typedef struct {
+        unsigned int btn_id;
+        unsigned int btn_push_cntr;
+        unsigned int btn_release_cntr;
+} BTN, *BTN_PTR;
+
+
+typedef struct {
+	unsigned int btns_number;
+        BTN* btns;
+} BTNS_STS, *BTNS_STS_PTR;
+
+#define MV_BTNS_NAME       "BTNS"
+
+
+struct btn_data {
+        unsigned int    gpp_id;
+        unsigned int    default_gpp_val;
+        BTN_OP          btn_op;
+        char            *btn_name;
+};
+
+
+/*
+ *  done against open of /dev/gpp, to get a cloned descriptor.
+ */
+#define CIOCWAIT_P       _IOWR('c', 150, BTNS_STS)
+#define CIOCNOWAIT_P     _IOWR('c', 151, BTNS_STS)
+
+
+#endif /* _BTNS_DRIVER_H_ */
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/Kconfig
new file mode 100755
index 0000000..8df7c1c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/Kconfig
@@ -0,0 +1,51 @@
+menu "Cesa options"
+	depends on MV_INCLUDE_CESA
+
+config  MV_CESA
+	bool "Support for Marvell Cryptographic Engine and Security Acceleration"
+	default y
+
+config  MV_CESA_TOOL
+	tristate "Support for Marvell CESA Tool"
+	depends on MV_CESA
+	---help---
+
+config MV_CESA_CHANNELS
+	int "Total CESA HW channels supported"
+        depends on MV_CESA
+	range 1 2
+        default 1
+         ---help---
+	Select the number of CESA channels to be used for crypto operations acceleration.
+
+config MV_CESA_CHAIN_MODE
+	bool "Support CESA chain-mode"
+        depends on MV_CESA
+        default n
+         ---help---
+        Choosing this option will enable crypto engine(CESA) chain mode support.
+	Warning: currently this feature is supported only by NFP-IPSec.
+
+choice 
+        prompt "CESA Mode"
+        depends on MV_CESA
+        default MV_CESA_OCF
+
+config	MV_CESA_OCF
+	bool "Support for Marvell CESA OCF driver"
+	depends on OCF_OCF
+	---help---
+	  Choosing this option will enable you to use the Marvell Cryptographic Engine and
+	  Security Accelerator, under the OCF package.
+
+config  MV_CESA_TEST
+	bool "Support for Marvell CESA test driver"
+	depends on MV_CESA_TOOL 
+	---help---
+	  Choosing this option will enable you to use the Marvell Cryptographic Engine and
+	  Security Accelerator, with the mv_cesa_tool in test mode.
+endchoice
+
+endmenu
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/Makefile
new file mode 100755
index 0000000..0db08c1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the Marvell CESA driver
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifeq ($(CONFIG_MV_CESA_OCF),y)
+EXTRA_CFLAGS    += -I$(srctree)/crypto/ocf
+endif
+
+obj-$(CONFIG_MV_CESA_TOOL) += cesa_dev.o
+obj-$(CONFIG_MV_CESA_OCF)  += cesa_ocf_drv.o
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_dev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_dev.c
new file mode 100755
index 0000000..f473e1e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_dev.c
@@ -0,0 +1,272 @@
+#include <linux/autoconf.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/unistd.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/miscdevice.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+
+#include "cesa_dev.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
+#include <linux/syscalls.h>
+#endif
+#include "mvOs.h"
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "cesa/mvCesa.h" 
+#include "mvSysCesaApi.h"
+
+
+static int debug = 1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug,
+	   "Enable debug");
+
+#ifdef CONFIG_MV_CESA_TEST
+
+static int buf_size = 20000;
+/*MODULE_PARM(buf_size, "i");*/
+module_param(buf_size,int,0644);
+MODULE_PARM_DESC(buf_size, "Size of each data buffer");
+
+static int buf_num = 1;
+/*MODULE_PARM(buf_num, "i");*/
+module_param(buf_num,int,0644);
+
+MODULE_PARM_DESC(buf_num, "Number of data buffers for each request");
+
+extern void cesaTestStart(int bufNum, int bufSize);
+extern void cesaTestStop(void);
+extern void cesaTest(int iter, int reqSize, int checkMode);
+extern void combiTest(int iter, int reqSize, int checkMode);
+extern void cesaOneTest(int testIdx, int caseIdx, int iter, int reqSize, int checkMode);
+extern void multiSizeTest(int idx, int checkMode, int iter, char* inputData);
+extern void aesTest(int iter, int reqSize, int checkMode);
+extern void desTest(int iter, int reqSize, int checkMode);
+extern void tripleDesTest(int iter, int reqSize, int checkMode);
+extern void mdTest(int iter, int reqSize, int checkMode);
+extern void sha1Test(int iter, int reqSize, int checkMode);
+extern void sha2Test(int iter, int reqSize, int checkMode);
+
+int run_cesa_test(CESA_TEST *cesa_test)
+{
+	switch(cesa_test->test){
+		case(MULTI):
+			combiTest(cesa_test->iter, cesa_test->req_size, cesa_test->checkmode);
+			break;
+		case(SIZE):
+                        multiSizeTest(cesa_test->req_size, cesa_test->iter, cesa_test->checkmode, NULL);
+			break;
+		case(SINGLE):
+			cesaOneTest(cesa_test->session_id, cesa_test->data_id, cesa_test->iter, 
+					cesa_test->req_size, cesa_test->checkmode);
+			break;
+		case(AES):
+			aesTest(cesa_test->iter, cesa_test->req_size, cesa_test->checkmode);		
+			break;
+		case(DES):
+			desTest(cesa_test->iter, cesa_test->req_size, cesa_test->checkmode);
+			break;
+		case(TRI_DES):
+			tripleDesTest(cesa_test->iter, cesa_test->req_size, cesa_test->checkmode);
+			break;
+		case(MD5):
+                        mdTest(cesa_test->iter, cesa_test->req_size, cesa_test->checkmode);
+                        break;
+		case(SHA1):
+                        sha1Test(cesa_test->iter, cesa_test->req_size, cesa_test->checkmode);
+                        break;
+		case(SHA2):
+                        sha2Test(cesa_test->iter, cesa_test->req_size, cesa_test->checkmode);
+                        break;
+
+		default:
+			dprintk("%s(unknown test 0x%x)\n", __FUNCTION__, cesa_test->test);
+			return -EINVAL;
+	}
+	return 0;
+}
+#endif /* CONFIG_MV_CESA_TEST */
+
+extern void    		mvCesaDebugSAD(int mode);
+extern void    		mvCesaDebugSA(short sid, int mode);
+extern void    		mvCesaDebugQueue(int mode);
+extern void    		mvCesaDebugStatus(void);
+extern void    		mvCesaDebugSram(int mode);
+extern void    		cesaTestPrintReq(int req, int offset, int size);
+extern void	   	    cesaTestPrintSession(int idx);
+extern void	   	    cesaTestPrintStatus(void);
+
+
+int run_cesa_debug(CESA_DEBUG *cesa_debug)
+{
+	int error = 0;
+	switch(cesa_debug->debug){
+		case(STATUS):
+			mvCesaDebugStatus();
+			break;
+		case(QUEUE):
+			mvCesaDebugQueue(cesa_debug->mode);
+			break;
+		case(SA):
+			mvCesaDebugSA(cesa_debug->index, cesa_debug->mode);
+			break;
+		case(SRAM):
+			mvCesaDebugSram(cesa_debug->mode);
+			break;
+		case(SAD):
+			mvCesaDebugSAD(cesa_debug->mode);
+			break;
+
+#ifdef CONFIG_MV_CESA_TEST
+		case(TST_REQ):
+			cesaTestPrintReq(cesa_debug->index, 0, cesa_debug->size);
+			break;
+		case(TST_SES):
+			cesaTestPrintSession(cesa_debug->index);
+			break;
+        case(TST_STATS):
+            cesaTestPrintStatus();
+            break;
+#endif /* CONFIG_MV_CESA_TEST */
+
+		default:
+			dprintk("%s(unknown debug 0x%x)\n", __FUNCTION__, cesa_debug->debug);
+			error = EINVAL;
+			break;
+
+	}
+
+	return(-error);
+}
+
+
+static int
+cesadev_ioctl(
+	struct inode *inode,
+	struct file *filp,
+	unsigned int cmd,
+	unsigned long arg)
+{	
+	CESA_DEBUG cesa_debug;
+	u32 error = 0;
+
+	dprintk("%s: cmd=0x%x, CIOCDEBUG=0x%x, CIOCTEST=0x%x\n", 
+                __FUNCTION__, cmd, CIOCDEBUG, CIOCTEST);
+
+	switch (cmd) {
+	case CIOCDEBUG:
+		if(copy_from_user(&cesa_debug, (void*)arg, sizeof(CESA_DEBUG)))
+				error = -EFAULT;
+		dprintk("%s(CIOCDEBUG): debug %d index %d mode %d size %d\n", 
+			__FUNCTION__, cesa_debug.debug, cesa_debug.index, cesa_debug.mode, cesa_debug.size);
+		error = run_cesa_debug(&cesa_debug);
+		break;
+
+#ifdef CONFIG_MV_CESA_TEST
+    case CIOCTEST:
+		{
+		CESA_TEST cesa_test;
+
+		if(copy_from_user(&cesa_test, (void*)arg, sizeof(CESA_TEST)))
+			error = -EFAULT;
+		dprintk("%s(CIOCTEST): test %d iter %d req_size %d checkmode %d sess_id %d data_id %d \n", 
+			__FUNCTION__, cesa_test.test, cesa_test.iter, cesa_test.req_size, cesa_test.checkmode,
+			cesa_test.session_id, cesa_test.data_id );
+		error = run_cesa_test(&cesa_test);
+		}
+		break;
+#endif /* CONFIG_MV_CESA_TEST */
+
+	default:
+		dprintk("%s (unknown ioctl 0x%x)\n", __FUNCTION__, cmd);
+		error = EINVAL;
+		break;
+	}
+	return(-error);
+}
+
+
+static int
+cesadev_open(struct inode *inode, struct file *filp)
+{
+	dprintk("%s()\n", __FUNCTION__);
+	return(0);
+}
+
+static int
+cesadev_release(struct inode *inode, struct file *filp)
+{
+	dprintk("%s()\n", __FUNCTION__);
+	return(0);
+}
+
+
+static struct file_operations cesadev_fops = {
+	.owner = THIS_MODULE,
+	.open = cesadev_open,
+	.release = cesadev_release,
+	.ioctl = cesadev_ioctl,
+};
+
+static struct miscdevice cesadev = {
+	.minor = CESADEV_MINOR,
+	.name = "cesa",
+	.fops = &cesadev_fops,
+};
+
+static int __init
+cesadev_init(void)
+{
+	int rc;
+
+	if (mvCtrlPwrClckGet(CESA_UNIT_ID, 0) == MV_FALSE)
+		return 0;
+
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+	if (MV_FALSE == mvSocUnitIsMappedToThisCpu(CESA))
+	{
+		dprintk("CESA is not mapped to this CPU\n");
+		return -ENODEV;
+	}		
+#endif
+
+#ifdef CONFIG_MV_CESA_TEST
+    cesaTestStart(buf_num, buf_size);
+#endif
+
+	dprintk("%s(%p)\n", __FUNCTION__, cesadev_init);
+	rc = misc_register(&cesadev);
+	if (rc) {
+		printk(KERN_ERR "cesadev: registration of /dev/cesadev failed\n");
+		return(rc);
+	}
+	return(0);
+}
+
+static void __exit
+cesadev_exit(void)
+{
+#ifdef CONFIG_MV_CESA_TEST
+	cesaTestStop();
+#endif
+	dprintk("%s()\n", __FUNCTION__);
+	misc_deregister(&cesadev);
+}
+
+module_init(cesadev_init);
+module_exit(cesadev_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ronen Shitrit");
+MODULE_DESCRIPTION("Cesadev (user interface to CESA)");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_dev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_dev.h
new file mode 100755
index 0000000..c426623
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_dev.h
@@ -0,0 +1,63 @@
+#ifndef _CESA_DEV_H_
+#define _CESA_DEV_H_
+
+/*
+ * common debug for all
+ */
+#if 1
+#define dprintk(a...)	if (debug) { printk(a); } else
+#else
+#define dprintk(a...)
+#endif
+
+typedef enum {
+	MULTI = 0,
+	SIZE,
+	SINGLE,
+	AES,
+	DES,
+	TRI_DES,
+	MD5,
+	SHA1,
+	SHA2,
+	MAX_CESA_TEST_TYPE	
+} CESA_TEST_TYPE;
+
+typedef struct {
+	CESA_TEST_TYPE 		test;
+	unsigned int	  	iter;		/* How many interation to run */
+	unsigned int	  	req_size;	/* request buffer size */
+	unsigned int		checkmode;	/* check mode: verify or not */
+	unsigned int		session_id; 	/* relevant only for single test */
+	unsigned int		data_id;   	/* relevant only for single test */
+} CESA_TEST;
+
+typedef enum {
+	STATUS = 0,
+	CHAN,
+	QUEUE,
+	SA,
+	CACHE_IDX,
+	SRAM,
+	SAD,
+	TST_REQ,
+	TST_SES,
+    TST_STATS,
+	MAX_CESA_DEBUG_TYPE
+} CESA_DEBUG_TYPE;
+
+typedef struct {
+	CESA_DEBUG_TYPE	debug;
+	unsigned int	index; /* general index */
+	unsigned int	mode;  /* verbos mode */
+	unsigned int 	size;  /* size of buffer */
+} CESA_DEBUG;
+
+
+/*
+ * done against open of /dev/cesa, to get a cloned descriptor.
+ */
+#define	CIOCDEBUG	_IOWR('c', 150, CESA_DEBUG)
+#define	CIOCTEST	_IOWR('c', 151, CESA_TEST)
+
+#endif /* _CESA_DEV_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_ocf_drv.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_ocf_drv.c
new file mode 100755
index 0000000..000cc8c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/cesa_ocf_drv.c
@@ -0,0 +1,1241 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <asm/scatterlist.h>
+#include <linux/spinlock.h>
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "cesa/mvCesaIf.h" /* moved here before cryptodev.h due to include dependencies */
+#include "mvSysCesaApi.h"
+#include <cryptodev.h>
+#include <uio.h>
+
+#include "mvDebug.h"
+
+#include "cesa/mvMD5.h"
+#include "cesa/mvSHA1.h"
+
+#include "cesa/mvCesaRegs.h"
+#include "cesa/AES/mvAes.h"
+#include "cesa/mvLru.h"
+
+
+#undef RT_DEBUG
+#ifdef RT_DEBUG
+static int debug = 1;
+module_param(debug, int, 1);
+MODULE_PARM_DESC(debug, "Enable debug");
+#undef dprintk
+#define dprintk(a...)	if (debug) { printk(a); } else
+#else
+static int debug = 0;
+#undef dprintk
+#define dprintk(a...)
+#endif
+
+/* interrupt handling */
+#undef CESA_OCF_TASKLET
+
+extern int cesaReqResources[MV_CESA_CHANNELS];
+/* support for spliting action into 2 actions */
+#define CESA_OCF_SPLIT
+
+/* general defines */
+#define CESA_OCF_MAX_SES 	128
+#define CESA_Q_SIZE	 	64
+#define CESA_RESULT_Q_SIZE	1024
+
+/* data structures */
+struct cesa_ocf_data {
+        int                                      cipher_alg;
+        int                                      auth_alg;
+	int					 encrypt_tn_auth;
+#define  auth_tn_decrypt  encrypt_tn_auth
+	int					 ivlen;
+	int 					 digestlen;
+	short					 sid_encrypt;
+	short					 sid_decrypt;
+	/* fragment workaround sessions */
+	short					 frag_wa_encrypt;
+	short					 frag_wa_decrypt;
+	short					 frag_wa_auth;
+};
+
+#define DIGEST_BUF_SIZE	32
+struct cesa_ocf_process {
+	MV_CESA_COMMAND 			cesa_cmd;
+	MV_CESA_MBUF 				cesa_mbuf;	
+	MV_BUF_INFO  				cesa_bufs[MV_CESA_MAX_MBUF_FRAGS];
+	char					digest[DIGEST_BUF_SIZE];
+	int					digest_len;
+	struct cryptop 				*crp;
+	int 					need_cb;
+	int					valid;
+};
+
+/* global variables */
+static int32_t			cesa_ocf_id 		= -1;
+static struct cesa_ocf_data 	**cesa_ocf_sessions = NULL;
+static u_int32_t		cesa_ocf_sesnum = 0;
+static DEFINE_SPINLOCK(cesa_lock);
+static atomic_t res_count;
+static struct cesa_ocf_process *res_array[CESA_RESULT_Q_SIZE];
+unsigned int res_empty;
+unsigned int res_ready;
+
+/* static APIs */
+static int 		cesa_ocf_process	(device_t, struct cryptop *, int);
+static int 		cesa_ocf_newsession	(device_t, u_int32_t *, struct cryptoini *);
+static int 		cesa_ocf_freesession	(device_t, u_int64_t);
+static inline void 	cesa_callback		(unsigned long);
+static irqreturn_t	cesa_interrupt_handler	(int, void *);
+static int		cesa_ocf_init		(void);
+static void		cesa_ocf_exit		(void);
+#ifdef CESA_OCF_TASKLET
+static struct tasklet_struct cesa_ocf_tasklet;
+#endif
+
+static struct timeval          tt_start;
+static struct timeval          tt_end;
+static struct cesa_ocf_process *cesa_ocf_pool = NULL;
+static int proc_empty;
+/*
+ * dummy device structure
+ */
+static struct {
+	softc_device_decl	sc_dev;
+} mv_cesa_dev;
+
+static device_method_t mv_cesa_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,	cesa_ocf_newsession),
+	DEVMETHOD(cryptodev_freesession,cesa_ocf_freesession),
+	DEVMETHOD(cryptodev_process,	cesa_ocf_process),
+	DEVMETHOD(cryptodev_kprocess,	NULL),
+};
+
+unsigned int
+get_usec(unsigned int start)
+{
+	if(start) {
+		do_gettimeofday (&tt_start);
+		return 0;
+	}
+	else {
+        	do_gettimeofday (&tt_end);
+        	tt_end.tv_sec -= tt_start.tv_sec;
+        	tt_end.tv_usec -= tt_start.tv_usec;
+        	if (tt_end.tv_usec < 0) {
+                	tt_end.tv_usec += 1000 * 1000;
+                	tt_end.tv_sec -= 1;
+        	}
+	}
+	printk("time taken is  %d\n", (unsigned int)(tt_end.tv_usec + tt_end.tv_sec * 1000000));
+	return (tt_end.tv_usec + tt_end.tv_sec * 1000000);
+}
+
+static void
+skb_copy_bits_back(struct sk_buff *skb, int offset, caddr_t cp, int len)
+{
+        int i;
+        if (offset < skb_headlen(skb)) {
+                memcpy(skb->data + offset, cp, min_t(int, skb_headlen(skb), len));
+                len -= skb_headlen(skb);
+                cp += skb_headlen(skb);
+        }
+        offset -= skb_headlen(skb);
+        for (i = 0; len > 0 && i < skb_shinfo(skb)->nr_frags; i++) {
+                if (offset < skb_shinfo(skb)->frags[i].size) {
+                        memcpy(page_address(skb_shinfo(skb)->frags[i].page) +
+                                        skb_shinfo(skb)->frags[i].page_offset,
+                                        cp, min_t(int, skb_shinfo(skb)->frags[i].size, len));
+                        len -= skb_shinfo(skb)->frags[i].size;
+                        cp += skb_shinfo(skb)->frags[i].size;
+                }
+                offset -= skb_shinfo(skb)->frags[i].size;
+        }
+}
+
+
+#ifdef RT_DEBUG
+/* 
+ * check that the crp action match the current session
+ */
+static int 
+ocf_check_action(struct cryptop *crp, struct cesa_ocf_data *cesa_ocf_cur_ses) {
+	int count = 0;
+	int encrypt = 0, decrypt = 0, auth = 0;
+	struct cryptodesc *crd;
+
+        /* Go through crypto descriptors, processing as we go */
+        for (crd = crp->crp_desc; crd; crd = crd->crd_next, count++) {
+		if(count > 2) {
+			printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
+			return 1;
+		}
+		
+		/* Encryption /Decryption */
+		if(crd->crd_alg == cesa_ocf_cur_ses->cipher_alg) {
+			/* check that the action is compatible with session */
+			if(encrypt || decrypt) {
+				printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
+				return 1;
+			}
+
+			if(crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
+				if( (count == 2) && (cesa_ocf_cur_ses->encrypt_tn_auth) ) {
+					printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
+					return 1;
+				}
+				encrypt++;
+			}
+			else { 					/* decrypt */
+				if( (count == 2) && !(cesa_ocf_cur_ses->auth_tn_decrypt) ) {
+					printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
+					return 1;
+				}
+				decrypt++;
+			}
+
+		}
+		/* Authentication */
+		else if(crd->crd_alg == cesa_ocf_cur_ses->auth_alg) {
+			/* check that the action is compatible with session */
+			if(auth) {
+				printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
+				return 1;
+			}
+			if( (count == 2) && (decrypt) && (cesa_ocf_cur_ses->auth_tn_decrypt)) {
+				printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
+				return 1;
+			}
+			if( (count == 2) && (encrypt) && !(cesa_ocf_cur_ses->encrypt_tn_auth)) {
+				printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
+				return 1;
+			}
+			auth++;
+		} 
+		else {
+			printk("%s,%d: Alg isn't supported by this session.\n", __FILE__, __LINE__);
+			return 1;
+		}
+	}
+	return 0;
+
+}
+#endif
+
+static inline struct cesa_ocf_process* cesa_ocf_alloc(void)
+{
+	int proc = 0;
+	unsigned long flags;
+	
+	spin_lock_irqsave(&cesa_lock, flags);
+
+	if(cesa_ocf_pool[proc_empty].valid != 0) {
+		spin_unlock_irqrestore(&cesa_lock, flags);
+		printk("%s,%d: Error, entry is overrided in cesa_ocf_pool(%d)\n", __FILE__, __LINE__,proc_empty);
+		return NULL;
+	}
+
+	cesa_ocf_pool[proc_empty].valid = 1;
+	proc = proc_empty;
+	proc_empty = ((proc_empty+1) % (CESA_Q_SIZE * MV_CESA_CHANNELS * 2));
+	spin_unlock_irqrestore(&cesa_lock, flags);
+
+	return &cesa_ocf_pool[proc];
+}
+
+static inline void cesa_ocf_free(struct cesa_ocf_process *ocf_process_p)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cesa_lock, flags);
+	ocf_process_p->valid = 0;
+	spin_unlock_irqrestore(&cesa_lock, flags);
+}
+
+
+/*
+ * Process a request.
+ */
+static int 
+cesa_ocf_process(device_t dev, struct cryptop *crp, int hint)
+{
+	struct cesa_ocf_process *cesa_ocf_cmd = NULL;
+	struct cesa_ocf_process *cesa_ocf_cmd_wa = NULL;
+	MV_CESA_COMMAND	*cesa_cmd;
+	struct cryptodesc *crd;
+	struct cesa_ocf_data *cesa_ocf_cur_ses;
+	int sid = 0, temp_len = 0, i;
+	int encrypt = 0, decrypt = 0, auth = 0;
+	int  status, free_resrc = 0;
+	struct sk_buff *skb = NULL;
+	struct uio *uiop = NULL;
+	unsigned char *ivp;
+	MV_BUF_INFO *p_buf_info;	
+	MV_CESA_MBUF *p_mbuf_info;
+	unsigned long flags;
+	unsigned char chan = 0;
+	
+
+        dprintk("%s()\n", __func__);
+
+	for(chan = 0; chan < MV_CESA_CHANNELS; chan++)
+		free_resrc += cesaReqResources[chan];
+
+		if (free_resrc == 0) {
+                	dprintk("%s,%d: ERESTART\n", __FILE__, __LINE__);
+                	return ERESTART;
+		}
+
+#ifdef RT_DEBUG
+        /* Sanity check */
+        if (crp == NULL) {
+                printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+                return EINVAL;
+        }
+
+        if (crp->crp_desc == NULL || crp->crp_buf == NULL ) {
+                printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+                crp->crp_etype = EINVAL;
+                return EINVAL;
+        }
+
+        sid = crp->crp_sid & 0xffffffff;
+        if ((sid >= cesa_ocf_sesnum) || (cesa_ocf_sessions[sid] == NULL)) {
+                crp->crp_etype = ENOENT;
+                printk("%s,%d: ENOENT session %d \n", __FILE__, __LINE__, sid);
+                return EINVAL;
+        }
+#endif
+
+	sid = crp->crp_sid & 0xffffffff;
+	crp->crp_etype = 0;
+	cesa_ocf_cur_ses = cesa_ocf_sessions[sid];
+
+#ifdef RT_DEBUG
+	if(ocf_check_action(crp, cesa_ocf_cur_ses)){
+		goto p_error;
+	}
+#endif
+
+	/* Allocate new cesa process from local pool */	
+	cesa_ocf_cmd = cesa_ocf_alloc();
+	if (cesa_ocf_cmd == NULL) {
+            	printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
+            	goto p_error;
+      	}
+
+	/* init cesa_process */
+	cesa_ocf_cmd->crp = crp;
+	/* always call callback */
+	cesa_ocf_cmd->need_cb = 1;
+
+	/* init cesa_cmd for usage of the HALs */
+	cesa_cmd = &cesa_ocf_cmd->cesa_cmd;
+	cesa_cmd->pReqPrv = (void *)cesa_ocf_cmd;
+	cesa_cmd->sessionId = cesa_ocf_cur_ses->sid_encrypt; /* defualt use encrypt */
+
+	/* prepare src buffer 	*/
+	/* we send the entire buffer to the HAL, even if only part of it should be encrypt/auth.  */
+	/* if not using seesions for both encrypt and auth, then it will be wiser to to copy only */
+	/* from skip to crd_len. 								  */
+	p_buf_info = cesa_ocf_cmd->cesa_bufs;	
+	p_mbuf_info = &cesa_ocf_cmd->cesa_mbuf;
+
+	p_buf_info += 2; /* save 2 first buffers for IV and digest - 
+			    we won't append them to the end since, they 
+			    might be places in an unaligned addresses. */
+	
+	p_mbuf_info->pFrags = p_buf_info;
+	temp_len = 0;
+
+	/* handle SKB */
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		
+		dprintk("%s,%d: handle SKB.\n", __FILE__, __LINE__);
+		skb = (struct sk_buff *) crp->crp_buf;
+
+                if (skb_shinfo(skb)->nr_frags >= (MV_CESA_MAX_MBUF_FRAGS - 1)) {
+                        printk("%s,%d: %d nr_frags > MV_CESA_MAX_MBUF_FRAGS", __FILE__, __LINE__, skb_shinfo(skb)->nr_frags);
+                        goto p_error;
+                }
+
+		p_mbuf_info->mbufSize = skb->len;
+		temp_len = skb->len;
+        	/* first skb fragment */
+        	p_buf_info->bufSize = skb_headlen(skb);
+        	p_buf_info->bufVirtPtr = skb->data;
+		p_buf_info++;
+
+        	/* now handle all other skb fragments */
+        	for ( i = 0; i < skb_shinfo(skb)->nr_frags; i++ ) {
+            		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+            		p_buf_info->bufSize = frag->size;
+            		p_buf_info->bufVirtPtr = page_address(frag->page) + frag->page_offset;
+            		p_buf_info++;
+        	}
+        	p_mbuf_info->numFrags = skb_shinfo(skb)->nr_frags + 1;
+	}
+	/* handle UIO */
+	else if(crp->crp_flags & CRYPTO_F_IOV) {
+	
+		dprintk("%s,%d: handle UIO.\n", __FILE__, __LINE__);
+		uiop = (struct uio *) crp->crp_buf;
+
+                if (uiop->uio_iovcnt > (MV_CESA_MAX_MBUF_FRAGS - 1)) {
+                        printk("%s,%d: %d uio_iovcnt > MV_CESA_MAX_MBUF_FRAGS \n", __FILE__, __LINE__, uiop->uio_iovcnt);
+                        goto p_error;
+                }
+
+		p_mbuf_info->mbufSize = crp->crp_ilen;
+		p_mbuf_info->numFrags = uiop->uio_iovcnt;
+		for(i = 0; i < uiop->uio_iovcnt; i++) {
+			p_buf_info->bufVirtPtr = uiop->uio_iov[i].iov_base;
+			p_buf_info->bufSize = uiop->uio_iov[i].iov_len;
+			temp_len += p_buf_info->bufSize;
+			dprintk("%s,%d: buf %x-> addr %x, size %x \n"
+				, __FILE__, __LINE__, i, (unsigned int)p_buf_info->bufVirtPtr, p_buf_info->bufSize);
+			p_buf_info++;			
+		}
+
+	}
+	/* handle CONTIG */
+	else {
+		dprintk("%s,%d: handle CONTIG.\n", __FILE__, __LINE__); 
+		p_mbuf_info->numFrags = 1;
+		p_mbuf_info->mbufSize = crp->crp_ilen;
+		p_buf_info->bufVirtPtr = crp->crp_buf;
+		p_buf_info->bufSize = crp->crp_ilen;
+		temp_len = crp->crp_ilen;
+		p_buf_info++;
+	}
+	
+	/* Support up to 64K why? cause! */
+	if(crp->crp_ilen > 64*1024) {
+		printk("%s,%d: buf too big %x \n", __FILE__, __LINE__, crp->crp_ilen);
+		goto p_error;
+	}
+
+	if( temp_len != crp->crp_ilen ) {
+		printk("%s,%d: warning size don't match.(%x %x) \n", __FILE__, __LINE__, temp_len, crp->crp_ilen);
+	}	
+
+	cesa_cmd->pSrc = p_mbuf_info;
+	cesa_cmd->pDst = p_mbuf_info;
+	
+	/* restore p_buf_info to point to first available buf */
+	p_buf_info = cesa_ocf_cmd->cesa_bufs;	
+	p_buf_info += 1; 
+
+
+        /* Go through crypto descriptors, processing as we go */
+        for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+		
+		/* Encryption /Decryption */
+		if(crd->crd_alg == cesa_ocf_cur_ses->cipher_alg) {
+
+			dprintk("%s,%d: cipher", __FILE__, __LINE__);
+
+			cesa_cmd->cryptoOffset = crd->crd_skip;
+    	              	cesa_cmd->cryptoLength = crd->crd_len;
+
+			if(crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
+				dprintk(" encrypt \n");
+				encrypt++;
+
+				/* handle IV */
+				if (crd->crd_flags & CRD_F_IV_EXPLICIT) {  /* IV from USER */
+					dprintk("%s,%d: IV from USER (offset %x) \n", __FILE__, __LINE__, crd->crd_inject);
+					cesa_cmd->ivFromUser = 1;
+					ivp = crd->crd_iv;
+
+                                	/*
+                                 	 * do we have to copy the IV back to the buffer ?
+                                 	 */
+                                	if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
+						dprintk("%s,%d: copy the IV back to the buffer\n", __FILE__, __LINE__);
+						cesa_cmd->ivOffset = crd->crd_inject;
+                                        	if (crp->crp_flags & CRYPTO_F_SKBUF)
+                                                	skb_copy_bits_back(skb, crd->crd_inject, ivp, cesa_ocf_cur_ses->ivlen);
+                                        	else if (crp->crp_flags & CRYPTO_F_IOV)
+                                                	cuio_copyback(uiop,crd->crd_inject, cesa_ocf_cur_ses->ivlen,(caddr_t)ivp);
+						else
+							memcpy(crp->crp_buf + crd->crd_inject, ivp, cesa_ocf_cur_ses->ivlen);
+                                	}
+					else {
+						dprintk("%s,%d: don't copy the IV back to the buffer \n", __FILE__, __LINE__);
+						p_mbuf_info->numFrags++;
+						p_mbuf_info->mbufSize += cesa_ocf_cur_ses->ivlen; 
+						p_mbuf_info->pFrags = p_buf_info;
+
+						p_buf_info->bufVirtPtr = ivp;
+						p_buf_info->bufSize = cesa_ocf_cur_ses->ivlen; 
+						p_buf_info--;
+
+						/* offsets */
+						cesa_cmd->ivOffset = 0;
+						cesa_cmd->cryptoOffset += cesa_ocf_cur_ses->ivlen;
+						if(auth) {
+							cesa_cmd->macOffset += cesa_ocf_cur_ses->ivlen;
+							cesa_cmd->digestOffset += cesa_ocf_cur_ses->ivlen; 
+						}	
+					}
+                                }
+				else {					/* random IV */
+					dprintk("%s,%d: random IV \n", __FILE__, __LINE__);
+					cesa_cmd->ivFromUser = 0;
+
+                                	/*
+                                 	 * do we have to copy the IV back to the buffer ?
+                                 	 */
+					/* in this mode the HAL will always copy the IV */
+					/* given by the session to the ivOffset  	*/
+					if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
+						cesa_cmd->ivOffset = crd->crd_inject;
+					} 
+					else {
+						/* if IV isn't copy, then how will the user know which IV did we use??? */
+						printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+						goto p_error; 
+					}
+				}
+			}
+			else { 					/* decrypt */
+				dprintk(" decrypt \n");
+				decrypt++;
+				cesa_cmd->sessionId = cesa_ocf_cur_ses->sid_decrypt;
+
+				/* handle IV */
+				if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
+					dprintk("%s,%d: IV from USER \n", __FILE__, __LINE__);
+					/* append the IV buf to the mbuf */
+					cesa_cmd->ivFromUser = 1;	
+					p_mbuf_info->numFrags++;
+					p_mbuf_info->mbufSize += cesa_ocf_cur_ses->ivlen; 
+					p_mbuf_info->pFrags = p_buf_info;
+
+					p_buf_info->bufVirtPtr = crd->crd_iv;
+					p_buf_info->bufSize = cesa_ocf_cur_ses->ivlen; 
+					p_buf_info--;
+
+					/* offsets */
+					cesa_cmd->ivOffset = 0;
+					cesa_cmd->cryptoOffset += cesa_ocf_cur_ses->ivlen;
+					if(auth) {
+						cesa_cmd->macOffset += cesa_ocf_cur_ses->ivlen;
+						cesa_cmd->digestOffset += cesa_ocf_cur_ses->ivlen; 
+					}
+                                }
+				else {
+					dprintk("%s,%d: IV inside the buffer \n", __FILE__, __LINE__);
+					cesa_cmd->ivFromUser = 0;
+					cesa_cmd->ivOffset = crd->crd_inject;
+				}
+			}
+
+		}
+		/* Authentication */
+		else if(crd->crd_alg == cesa_ocf_cur_ses->auth_alg) {
+			dprintk("%s,%d:  Authentication \n", __FILE__, __LINE__);
+			auth++;
+			cesa_cmd->macOffset = crd->crd_skip;
+			cesa_cmd->macLength = crd->crd_len;
+
+			/* digest + mac */
+			cesa_cmd->digestOffset = crd->crd_inject;
+		} 
+		else {
+			printk("%s,%d: Alg isn't supported by this session.\n", __FILE__, __LINE__);
+			goto p_error;
+		}
+	}
+
+	dprintk("\n");
+	dprintk("%s,%d: Sending Action: \n", __FILE__, __LINE__);
+	dprintk("%s,%d: IV from user: %d. IV offset %x \n",  __FILE__, __LINE__, cesa_cmd->ivFromUser, cesa_cmd->ivOffset);
+	dprintk("%s,%d: crypt offset %x len %x \n", __FILE__, __LINE__, cesa_cmd->cryptoOffset, cesa_cmd->cryptoLength);
+	dprintk("%s,%d: Auth offset %x len %x \n", __FILE__, __LINE__, cesa_cmd->macOffset, cesa_cmd->macLength);
+	dprintk("%s,%d: set digest in offset %x . \n", __FILE__, __LINE__, cesa_cmd->digestOffset);
+	if(debug) {
+		mvCesaIfDebugMbuf("SRC BUFFER", cesa_cmd->pSrc, 0, cesa_cmd->pSrc->mbufSize);
+	}
+
+	cesa_cmd->split = MV_CESA_SPLIT_NONE;
+	
+	/* send action to HAL */
+	spin_lock_irqsave(&cesa_lock, flags);
+	status = mvCesaIfAction(cesa_cmd);
+	spin_unlock_irqrestore(&cesa_lock, flags);
+
+	/* action not allowed */
+	if(status == MV_NOT_ALLOWED) {
+#ifdef CESA_OCF_SPLIT
+		/* if both encrypt and auth try to split */
+		if(auth && (encrypt || decrypt)) {
+			MV_CESA_COMMAND	*cesa_cmd_wa;
+
+			/* Allocate new cesa process from local pool and initialize it */	
+			cesa_ocf_cmd_wa = cesa_ocf_alloc();
+	
+        		if (cesa_ocf_cmd_wa == NULL) {
+            			printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
+            			goto p_error;
+      			}
+			memcpy(cesa_ocf_cmd_wa, cesa_ocf_cmd, sizeof(struct cesa_ocf_process));
+			cesa_cmd_wa = &cesa_ocf_cmd_wa->cesa_cmd;
+			cesa_cmd_wa->pReqPrv = (void *)cesa_ocf_cmd_wa;
+			cesa_ocf_cmd_wa->need_cb = 0;
+			cesa_cmd_wa->split = MV_CESA_SPLIT_FIRST;
+			cesa_cmd->split = MV_CESA_SPLIT_SECOND;
+
+			/* break requests to two operation, first operation completion won't call callback */
+			if((decrypt) && (cesa_ocf_cur_ses->auth_tn_decrypt)) {
+				cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
+				cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_decrypt;
+			}
+			else if((decrypt) && !(cesa_ocf_cur_ses->auth_tn_decrypt)) {
+				cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_decrypt;
+				cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
+			}
+			else if((encrypt) && (cesa_ocf_cur_ses->encrypt_tn_auth)) {
+				cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_encrypt;
+				cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
+			}
+			else if((encrypt) && !(cesa_ocf_cur_ses->encrypt_tn_auth)){
+				cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
+				cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_encrypt;
+			}
+			else {
+				printk("%s,%d: Unsupporterd fragment wa mode \n", __FILE__, __LINE__);
+            			goto p_error;
+			}
+
+			/* send the 2 actions to the HAL */
+			spin_lock_irqsave(&cesa_lock, flags);
+			status = mvCesaIfAction(cesa_cmd_wa);
+			spin_unlock_irqrestore(&cesa_lock, flags);
+
+			if((status != MV_NO_MORE) && (status != MV_OK)) {
+				printk("%s,%d: cesa action failed, status = 0x%x\n", __FILE__, __LINE__, status);
+				goto p_error;
+			}
+			spin_lock_irqsave(&cesa_lock, flags);
+			status = mvCesaIfAction(cesa_cmd);
+			spin_unlock_irqrestore(&cesa_lock, flags);
+
+		}
+		/* action not allowed and can't split */
+		else 
+#endif
+		{
+			goto p_error;
+		}
+	}
+
+	/* Hal Q is full, send again. This should never happen */
+	if(status == MV_NO_RESOURCE) {
+		printk("%s,%d: cesa no more resources \n", __FILE__, __LINE__);
+		if(cesa_ocf_cmd)
+			cesa_ocf_free(cesa_ocf_cmd);
+		if(cesa_ocf_cmd_wa)
+			cesa_ocf_free(cesa_ocf_cmd_wa);
+		
+		return ERESTART;
+	} 
+	else if((status != MV_NO_MORE) && (status != MV_OK)) {
+                printk("%s,%d: cesa action failed, status = 0x%x\n", __FILE__, __LINE__, status);
+		goto p_error;
+        }
+
+	return 0;
+p_error:
+	crp->crp_etype = EINVAL;
+	if(cesa_ocf_cmd)
+		cesa_ocf_free(cesa_ocf_cmd);
+	if(cesa_ocf_cmd_wa)
+		cesa_ocf_free(cesa_ocf_cmd_wa);
+       	return EINVAL;
+}
+
+/*
+ * cesa callback. 
+ */
+static inline void
+cesa_callback(unsigned long dummy)
+{
+	struct cesa_ocf_process *cesa_ocf_cmd = NULL;
+	struct cryptop 		*crp = NULL;
+
+	dprintk("%s()\n", __func__);
+
+	while (atomic_read(&res_count) != 0) {
+		cesa_ocf_cmd = res_array[res_ready];
+		crp = cesa_ocf_cmd->crp; 
+
+		if (cesa_ocf_cmd->need_cb) {
+			if (debug) {
+				mvCesaIfDebugMbuf("DST BUFFER", cesa_ocf_cmd->cesa_cmd.pDst, 0,
+							cesa_ocf_cmd->cesa_cmd.pDst->mbufSize);
+			}
+			crypto_done(crp);
+		}
+	
+		cesa_ocf_free(cesa_ocf_cmd);
+		res_ready = ((res_ready + 1) % CESA_RESULT_Q_SIZE);
+		atomic_dec(&res_count);
+	}
+
+	return;
+}
+
+/*
+ * cesa Interrupt Service Routine.
+ */
+static irqreturn_t
+cesa_interrupt_handler(int irq, void *arg)
+{
+	MV_CESA_RESULT  	result;
+	MV_STATUS               status;
+        u32 cause;
+	u8 chan;
+
+	dprintk("%s()\n", __func__);
+
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+
+  		/* Read cause register */
+		cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG(chan));
+
+    		if (likely((cause & MV_CESA_CAUSE_ACC_DMA_MASK) != 0)) {
+			
+			/* clear interrupts */
+    			MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+
+			while (1) {
+				if(likely(atomic_read(&res_count) < CESA_RESULT_Q_SIZE)) {
+					/* Get Ready requests */
+					spin_lock(&cesa_lock);
+					status = mvCesaIfReadyGet(chan, &result);
+					spin_unlock(&cesa_lock);
+					if(likely(status == MV_OK)) {
+						res_array[res_empty] = (struct cesa_ocf_process *)result.pReqPrv;
+						res_empty = ((res_empty + 1) % CESA_RESULT_Q_SIZE);
+						atomic_inc(&res_count);
+						continue;
+					} else
+						break;
+				} else {
+					/* In case reaching this point -res_array should be tuned   */
+					printk("%s: Error: Q request is full(chan=%d)\n", __func__, chan);
+					return IRQ_HANDLED;
+				}
+			}
+		}
+	}
+
+	if(likely(atomic_read(&res_count) > 0))
+#ifdef CESA_OCF_TASKLET	
+		tasklet_hi_schedule(&cesa_ocf_tasklet);
+#else
+		cesa_callback(0);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Open a session.
+ */
+static int 
+/*cesa_ocf_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)*/
+cesa_ocf_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
+{
+	u32 status = 0, i = 0;
+	unsigned long flags = 0;
+	u32 count = 0, auth = 0, encrypt =0;
+	struct cesa_ocf_data *cesa_ocf_cur_ses;
+	MV_CESA_OPEN_SESSION cesa_session;
+	MV_CESA_OPEN_SESSION *cesa_ses = &cesa_session;
+
+
+        dprintk("%s()\n", __func__);
+        if (sid == NULL || cri == NULL) {
+                printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+                return EINVAL;
+        }
+
+	if (cesa_ocf_sessions) {
+		for (i = 1; i < cesa_ocf_sesnum; i++)
+			if (cesa_ocf_sessions[i] == NULL)
+				break;
+	} else
+		i = 1;
+
+	if (cesa_ocf_sessions == NULL || i == cesa_ocf_sesnum) {
+		struct cesa_ocf_data **cesa_ocf_new_sessions;
+
+		if (cesa_ocf_sessions == NULL) {
+			i = 1; /* We leave cesa_ocf_sessions[0] empty */
+			cesa_ocf_sesnum = CESA_OCF_MAX_SES;
+		}
+		else
+			cesa_ocf_sesnum *= 2;
+
+		cesa_ocf_new_sessions = kmalloc(cesa_ocf_sesnum * sizeof(struct cesa_ocf_data *), SLAB_ATOMIC);
+		if (cesa_ocf_new_sessions == NULL) {
+			/* Reset session number */
+			if (cesa_ocf_sesnum == CESA_OCF_MAX_SES)
+				cesa_ocf_sesnum = 0;
+			else
+				cesa_ocf_sesnum /= 2;
+			printk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+			return ENOBUFS;
+		}
+		memset(cesa_ocf_new_sessions, 0, cesa_ocf_sesnum * sizeof(struct cesa_ocf_data *));
+
+		/* Copy existing sessions */
+		if (cesa_ocf_sessions) {
+			memcpy(cesa_ocf_new_sessions, cesa_ocf_sessions,
+			    (cesa_ocf_sesnum / 2) * sizeof(struct cesa_ocf_data *));
+			kfree(cesa_ocf_sessions);
+		}
+
+		cesa_ocf_sessions = cesa_ocf_new_sessions;
+	}
+
+	cesa_ocf_sessions[i] = (struct cesa_ocf_data *) kmalloc(sizeof(struct cesa_ocf_data),
+			SLAB_ATOMIC);
+	if (cesa_ocf_sessions[i] == NULL) {
+		cesa_ocf_freesession(NULL, i);
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return ENOBUFS;
+	}
+
+	dprintk("%s,%d: new session %d \n", __FILE__, __LINE__, i);
+	
+        *sid = i;
+        cesa_ocf_cur_ses = cesa_ocf_sessions[i];
+        memset(cesa_ocf_cur_ses, 0, sizeof(struct cesa_ocf_data));
+	cesa_ocf_cur_ses->sid_encrypt = -1;
+	cesa_ocf_cur_ses->sid_decrypt = -1;
+	cesa_ocf_cur_ses->frag_wa_encrypt = -1;
+	cesa_ocf_cur_ses->frag_wa_decrypt = -1;
+	cesa_ocf_cur_ses->frag_wa_auth = -1;
+
+	/* init the session */	
+	memset(cesa_ses, 0, sizeof(MV_CESA_OPEN_SESSION));
+	count = 1;
+        while (cri) {	
+		if(count > 2) {
+        		printk("%s,%d: don't support more then 2 operations\n", __FILE__, __LINE__);
+        		goto error;
+		}
+                switch (cri->cri_alg) {
+		case CRYPTO_AES_CBC:
+			dprintk("%s,%d: (%d) AES CBC \n", __FILE__, __LINE__, count);
+			cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
+			cesa_ocf_cur_ses->ivlen = MV_CESA_AES_BLOCK_SIZE;
+			cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_AES;
+			cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
+			if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
+        			printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
+        			goto error;
+			}
+			memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
+			dprintk("%s,%d: key length %d \n", __FILE__, __LINE__, cri->cri_klen/8);
+			cesa_ses->cryptoKeyLength = cri->cri_klen/8;
+			encrypt += count;
+			break;
+                case CRYPTO_3DES_CBC:
+			dprintk("%s,%d: (%d) 3DES CBC \n", __FILE__, __LINE__, count);
+			cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
+			cesa_ocf_cur_ses->ivlen = MV_CESA_3DES_BLOCK_SIZE;
+			cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_3DES;
+			cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
+			if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
+        			printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
+        			goto error;
+			}
+			memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
+			cesa_ses->cryptoKeyLength = cri->cri_klen/8;
+			encrypt += count;
+			break;
+                case CRYPTO_DES_CBC:
+			dprintk("%s,%d: (%d) DES CBC \n", __FILE__, __LINE__, count);
+			cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
+			cesa_ocf_cur_ses->ivlen = MV_CESA_DES_BLOCK_SIZE;
+			cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_DES;
+			cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
+			if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
+        			printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
+        			goto error;
+			}
+			memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
+			cesa_ses->cryptoKeyLength = cri->cri_klen/8;
+			encrypt += count;
+			break;
+                case CRYPTO_MD5:
+                case CRYPTO_MD5_HMAC:
+			dprintk("%s,%d: (%d) %sMD5 CBC \n", __FILE__, __LINE__, count, (cri->cri_alg != CRYPTO_MD5)? "H-":" ");
+                        cesa_ocf_cur_ses->auth_alg = cri->cri_alg;
+			cesa_ocf_cur_ses->digestlen = (cri->cri_alg == CRYPTO_MD5)? MV_CESA_MD5_DIGEST_SIZE : 12;
+			cesa_ses->macMode = (cri->cri_alg == CRYPTO_MD5)? MV_CESA_MAC_MD5 : MV_CESA_MAC_HMAC_MD5;
+			if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
+        			printk("%s,%d: MAC key too long. \n", __FILE__, __LINE__);
+        			goto error;
+			}
+			cesa_ses->macKeyLength = cri->cri_klen/8;
+			memcpy(cesa_ses->macKey, cri->cri_key, cri->cri_klen/8);
+			cesa_ses->digestSize = cesa_ocf_cur_ses->digestlen; 
+			auth += count;
+			break;
+                case CRYPTO_SHA1:
+                case CRYPTO_SHA1_HMAC:
+			dprintk("%s,%d: (%d) %sSHA1 CBC \n", __FILE__, __LINE__, count, (cri->cri_alg != CRYPTO_SHA1)? "H-":" ");
+                        cesa_ocf_cur_ses->auth_alg = cri->cri_alg;
+			cesa_ocf_cur_ses->digestlen = (cri->cri_alg == CRYPTO_SHA1)? MV_CESA_SHA1_DIGEST_SIZE : 12; 
+			cesa_ses->macMode = (cri->cri_alg == CRYPTO_SHA1)? MV_CESA_MAC_SHA1 : MV_CESA_MAC_HMAC_SHA1;
+			if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
+        			printk("%s,%d: MAC key too long. \n", __FILE__, __LINE__);
+        			goto error;
+			}
+			cesa_ses->macKeyLength = cri->cri_klen/8;
+			memcpy(cesa_ses->macKey, cri->cri_key, cri->cri_klen/8);
+			cesa_ses->digestSize = cesa_ocf_cur_ses->digestlen;
+			auth += count;
+			break;
+                default:
+                        printk("%s,%d: unknown algo 0x%x\n", __FILE__, __LINE__, cri->cri_alg);
+                        goto error;
+                }
+                cri = cri->cri_next;
+		count++;
+        }
+
+	if((encrypt > 2) || (auth > 2)) {
+		printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
+                goto error;
+	}
+
+	/* create new sessions in HAL */
+	if(encrypt) {
+		cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
+		/* encrypt session */
+		if(auth == 1) {
+			cesa_ses->operation = MV_CESA_MAC_THEN_CRYPTO;
+		}
+		else if(auth == 2) {
+			cesa_ses->operation = MV_CESA_CRYPTO_THEN_MAC;
+			cesa_ocf_cur_ses->encrypt_tn_auth = 1;
+		}
+		else {
+			cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
+		}
+		cesa_ses->direction = MV_CESA_DIR_ENCODE;
+		spin_lock_irqsave(&cesa_lock, flags);
+		status = mvCesaIfSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_encrypt);
+		spin_unlock_irqrestore(&cesa_lock, flags);
+    		if(status != MV_OK) {
+        		printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
+        		goto error;
+    		}	
+		/* decrypt session */
+		if( cesa_ses->operation == MV_CESA_MAC_THEN_CRYPTO ) {
+			cesa_ses->operation = MV_CESA_CRYPTO_THEN_MAC;
+		}
+		else if( cesa_ses->operation == MV_CESA_CRYPTO_THEN_MAC ) {
+			cesa_ses->operation = MV_CESA_MAC_THEN_CRYPTO;
+		}
+		cesa_ses->direction = MV_CESA_DIR_DECODE;
+		spin_lock_irqsave(&cesa_lock, flags);
+		status = mvCesaIfSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_decrypt);
+		spin_unlock_irqrestore(&cesa_lock, flags);
+		if(status != MV_OK) {
+        		printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
+        		goto error;
+    		}
+
+		/* preapre one action sessions for case we will need to split an action */
+#ifdef CESA_OCF_SPLIT
+		if(( cesa_ses->operation == MV_CESA_MAC_THEN_CRYPTO ) || 
+			( cesa_ses->operation == MV_CESA_CRYPTO_THEN_MAC )) {
+			/* open one session for encode and one for decode */
+			cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
+			cesa_ses->direction = MV_CESA_DIR_ENCODE;
+			spin_lock_irqsave(&cesa_lock, flags);
+			status = mvCesaIfSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_encrypt);
+			spin_unlock_irqrestore(&cesa_lock, flags);
+    			if(status != MV_OK) {
+        			printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
+        			goto error;
+    			}
+
+			cesa_ses->direction = MV_CESA_DIR_DECODE;
+			spin_lock_irqsave(&cesa_lock, flags);
+			status = mvCesaIfSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_decrypt);
+			spin_unlock_irqrestore(&cesa_lock, flags);
+    			if(status != MV_OK) {
+        			printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
+        			goto error;
+    			}
+			/* open one session for auth */	
+			cesa_ses->operation = MV_CESA_MAC_ONLY;
+			cesa_ses->direction = MV_CESA_DIR_ENCODE;
+			spin_lock_irqsave(&cesa_lock, flags);
+			status = mvCesaIfSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_auth);
+			spin_unlock_irqrestore(&cesa_lock, flags);
+			if(status != MV_OK) {
+        			printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
+				goto error;
+    			}
+		}
+#endif
+	}
+	else { /* only auth */
+		cesa_ses->operation = MV_CESA_MAC_ONLY;
+		cesa_ses->direction = MV_CESA_DIR_ENCODE;
+		spin_lock_irqsave(&cesa_lock, flags);
+        	status = mvCesaIfSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_encrypt);
+		spin_unlock_irqrestore(&cesa_lock, flags);
+		if(status != MV_OK) {
+        		printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
+			goto error;
+    		}
+	}
+
+	return 0;
+error:
+     	cesa_ocf_freesession(NULL, *sid);
+      	return EINVAL;	
+
+}
+
+
+/*
+ * Free a session.
+ */
+static int
+cesa_ocf_freesession(device_t dev, u_int64_t tid)
+{
+        struct cesa_ocf_data *cesa_ocf_cur_ses;
+        u_int32_t sid = CRYPTO_SESID2LID(tid);
+	unsigned long flags = 0;
+
+        dprintk("%s() %d \n", __func__, sid);
+	if (sid > cesa_ocf_sesnum || cesa_ocf_sessions == NULL ||
+			cesa_ocf_sessions[sid] == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+        /* Silently accept and return */
+        if (sid == 0)
+                return(0);
+
+	/* release session from HAL */
+	cesa_ocf_cur_ses = cesa_ocf_sessions[sid];
+     	if (cesa_ocf_cur_ses->sid_encrypt != -1) {
+		spin_lock_irqsave(&cesa_lock, flags);
+		mvCesaIfSessionClose(cesa_ocf_cur_ses->sid_encrypt);
+		spin_unlock_irqrestore(&cesa_lock, flags);
+	}
+	if (cesa_ocf_cur_ses->sid_decrypt != -1) {
+		spin_lock_irqsave(&cesa_lock, flags);
+		mvCesaIfSessionClose(cesa_ocf_cur_ses->sid_decrypt);
+		spin_unlock_irqrestore(&cesa_lock, flags);
+	}
+     	if (cesa_ocf_cur_ses->frag_wa_encrypt != -1) {
+		spin_lock_irqsave(&cesa_lock, flags);
+		mvCesaIfSessionClose(cesa_ocf_cur_ses->frag_wa_encrypt);
+		spin_unlock_irqrestore(&cesa_lock, flags);
+	}
+	if (cesa_ocf_cur_ses->frag_wa_decrypt != -1) {
+		spin_lock_irqsave(&cesa_lock, flags);
+		mvCesaIfSessionClose(cesa_ocf_cur_ses->frag_wa_decrypt);
+		spin_unlock_irqrestore(&cesa_lock, flags);
+	}
+	if (cesa_ocf_cur_ses->frag_wa_auth != -1) {
+		spin_lock_irqsave(&cesa_lock, flags);
+		mvCesaIfSessionClose(cesa_ocf_cur_ses->frag_wa_auth);
+		spin_unlock_irqrestore(&cesa_lock, flags);
+	}
+
+      	kfree(cesa_ocf_cur_ses);
+	cesa_ocf_sessions[sid] = NULL;
+
+        return 0;
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30))
+extern int crypto_init(void);
+#endif
+
+/*
+ * our driver startup and shutdown routines
+ */
+static int
+cesa_ocf_init(void)
+{
+	u8 chan = 0;
+	const char *irq_str[] = {"cesa0","cesa1"};
+
+	if (mvCtrlPwrClckGet(CESA_UNIT_ID, 0) == MV_FALSE)
+		return 0;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30))
+	crypto_init();
+#endif
+
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+	if (MV_FALSE == mvSocUnitIsMappedToThisCpu(CESA))
+	{
+		dprintk("CESA is not mapped to this CPU\n");
+		return -ENODEV;
+	}		
+#endif
+
+	dprintk("%s\n", __func__);
+
+	res_empty = 0;
+	res_ready = 0;
+
+	/* The pool size here is twice the requests queue size due to reordering */
+	cesa_ocf_pool = (struct cesa_ocf_process*)kmalloc((sizeof(struct cesa_ocf_process) * 
+					CESA_Q_SIZE * MV_CESA_CHANNELS * 2), GFP_ATOMIC);
+	if (cesa_ocf_pool == NULL) {
+            	printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
+            	return EINVAL;
+      	}
+
+	proc_empty = 0;
+	memset(cesa_ocf_pool, 0, (sizeof(struct cesa_ocf_process) * CESA_Q_SIZE * MV_CESA_CHANNELS * 2));
+	memset(&mv_cesa_dev, 0, sizeof(mv_cesa_dev));
+	softc_device_init(&mv_cesa_dev, "MV CESA", 0, mv_cesa_methods);
+	cesa_ocf_id = crypto_get_driverid(softc_get_device(&mv_cesa_dev),CRYPTOCAP_F_HARDWARE);
+
+	if (cesa_ocf_id < 0)
+		panic("MV CESA crypto device cannot initialize!");
+
+	dprintk("%s,%d: cesa ocf device id is %d \n", __FILE__, __LINE__, cesa_ocf_id);
+
+	/* CESA unit is auto power on off */
+#if 0
+	if (MV_FALSE == mvCtrlPwrClckGet(CESA_UNIT_ID,0))
+	{
+		printk("\nWarning CESA %d is Powered Off\n",0);
+		return EINVAL;
+	}
+#endif
+
+	if( MV_OK != mvSysCesaInit(CESA_OCF_MAX_SES*5, CESA_Q_SIZE, NULL) ) {
+            	printk("%s,%d: mvCesaInit Failed. \n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	for(chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+
+		/* clear and unmask Int */
+		MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG(chan), 0);
+    		MV_REG_WRITE( MV_CESA_ISR_MASK_REG(chan), MV_CESA_CAUSE_ACC_DMA_MASK);
+
+		/* register interrupt */
+		if( request_irq( CESA_IRQ(chan), cesa_interrupt_handler,
+                             	(IRQF_DISABLED) , irq_str[chan], &cesa_ocf_id) < 0) {
+            		printk("%s,%d: cannot assign irq %x\n", __FILE__, __LINE__, CESA_IRQ(chan));
+			return EINVAL;
+        	}
+	}
+
+#ifdef CESA_OCF_TASKLET
+	tasklet_init(&cesa_ocf_tasklet, cesa_callback, (unsigned int) 0);
+#endif
+
+
+#define	REGISTER(alg) \
+	crypto_register(cesa_ocf_id, alg, 0,0)
+	REGISTER(CRYPTO_AES_CBC);
+	REGISTER(CRYPTO_DES_CBC);
+	REGISTER(CRYPTO_3DES_CBC);
+	REGISTER(CRYPTO_MD5);
+	REGISTER(CRYPTO_MD5_HMAC);
+	REGISTER(CRYPTO_SHA1);
+	REGISTER(CRYPTO_SHA1_HMAC);
+#undef REGISTER
+
+	return 0;
+}
+
+static void
+cesa_ocf_exit(void)
+{
+	u8 chan = 0;
+
+	dprintk("%s()\n", __func__);
+
+	crypto_unregister_all(cesa_ocf_id);
+	cesa_ocf_id = -1;
+	kfree(cesa_ocf_pool);
+
+	for(chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+		free_irq(CESA_IRQ(chan), NULL);
+	
+		/* mask and clear Int */
+		MV_REG_WRITE( MV_CESA_ISR_MASK_REG(chan), 0);
+		MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG(chan), 0);
+    	
+	}
+
+	if( MV_OK != mvCesaIfFinish() ) {
+            	printk("%s,%d: mvCesaFinish Failed. \n", __FILE__, __LINE__);
+		return;
+	}
+}
+
+module_init(cesa_ocf_init);
+module_exit(cesa_ocf_exit);
+
+MODULE_LICENSE("Marvell/GPL");
+MODULE_AUTHOR("Ronen Shitrit");
+MODULE_DESCRIPTION("OCF module for Marvell CESA based SoC");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Kconfig
new file mode 100755
index 0000000..401c3b7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Kconfig
@@ -0,0 +1,24 @@
+menu "SoC CUST support"
+depends on MV_INCLUDE_CUST
+
+config  MV_CUST
+	bool "Support for Marvell Customer Driver"
+      	default y
+	---help---
+
+config  MV_CUST_IGMP_HANDLE
+        bool "Enable MV_CUST IGMP handling"
+        default y
+        ---help---
+
+config  MV_CUST_UDP_SAMPLE_HANDLE
+        bool "Enable MV_CUST sample UDP handling"
+        default n
+        ---help---
+
+config  MV_CUST_FLOW_MAP_HANDLE
+        bool "Enable MV_CUST flow mapping handling"
+        default y
+        ---help---        
+
+endmenu
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Makefile
new file mode 100755
index 0000000..0fd28b0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the Marvell Customer driver
+#
+
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifdef CONFIG_MV_HAL_RULES_PATH
+include $(srctree)/include/config/auto.conf
+include $(srctree)/$(subst ",,$(CONFIG_MV_HAL_RULES_PATH))
+endif
+
+CUST_OBJS += 	mv_cust_dev.o \
+		mv_cust_mod.o \
+		mv_cust_flow_map.o \
+		mv_cust_netdev.o \
+		mv_cust_sysfs.o
+                                
+mv_cust-objs := $(CUST_OBJS)
+obj-$(CONFIG_MV_CUST) += mv_cust.o
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.c
new file mode 100755
index 0000000..2f78724
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.c
@@ -0,0 +1,370 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+* 
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+* 
+*********************************************************************************
+* Marvell GPL License Option
+* 
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+* 
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_dev.c
+*
+* DESCRIPTION:
+*       
+* 
+*******************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/poll.h>
+#include <linux/clk.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+
+#include "mv_cust_dev.h"
+#include "mv_cust_netdev.h"
+#include "mv_cust_flow_map.h"
+#include "mv_cust_mng_if.h"
+
+
+/* Used to prevent multiple access to device */
+static int               mvcust_device_open = 0;
+static struct miscdevice mvcust_misc_dev;
+
+/*******************************************************************************
+**
+**  mvcust_dev_open
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function execute device open actions
+**
+**  PARAMETERS:  
+**               
+**               
+**               
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+static int mvcust_dev_open(struct inode *inode, struct file *file)
+{
+	MVCUST_DEBUG_PRINT("Enter");
+
+   // if (mvcust_device_open > 0)
+   //     return -EBUSY;
+
+	mvcust_device_open++;
+
+	return 0;
+}
+
+/*******************************************************************************
+**
+**  mvcust_dev_release
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function execute device release actions
+**
+**  PARAMETERS:  
+**               
+**               
+**               
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+static int mvcust_dev_release(struct inode *inode, struct file *file)
+{
+    MVCUST_DEBUG_PRINT("Enter");
+
+   // if (mvcust_device_open > 0)
+   //     mvcust_device_open--;
+
+	return 0;
+}
+
+/*******************************************************************************
+**
+**  mv_cust_dev_ioctl
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function execute IO commands
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**               unsigned int cmd
+**               unsigned long arg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+static int mvcust_dev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+    mv_cust_ioctl_omci_set_t      cust_omci_set;
+    mv_cust_ioctl_llid_set_t      cust_llid_set;
+    mv_cust_ioctl_flow_map_t      cust_flow_map;
+    mv_cust_ioctl_dscp_map_t      cust_dscp_map;    
+    int                           enable;
+    int                           rc;
+
+  int  ret = -EINVAL;
+
+    MVCUST_DEBUG_PRINT("Enter");
+
+  switch(cmd)
+  {
+      case MV_CUST_IOCTL_OMCI_SET:
+
+          if(copy_from_user(&cust_omci_set, (mv_cust_ioctl_omci_set_t*)arg, sizeof(mv_cust_ioctl_omci_set_t)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+
+          rc = mv_cust_omci_set(cust_omci_set.tcont, cust_omci_set.txq, cust_omci_set.gemport, cust_omci_set.keep_rx_mh);
+          if (rc != 0) {
+              MVCUST_ERR_PRINT("mv_cust_omci_set failed\n");
+          }
+          ret = 0;
+          break;
+
+      case MV_CUST_IOCTL_OMCI_ENABLE:
+
+          if(copy_from_user(&enable, (int *)arg, sizeof(int)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+          mv_cust_omci_enable(enable);
+          ret = 0;
+          break;
+
+      case MV_CUST_IOCTL_EOAM_ENABLE:
+
+          if(copy_from_user(&enable, (int *)arg, sizeof(int)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+          mv_cust_eoam_enable(enable);
+          ret = 0;
+          break;
+
+      case MV_CUST_IOCTL_EOAM_LLID_SET:
+          if(copy_from_user(&cust_llid_set, (int *)arg, sizeof(mv_cust_ioctl_llid_set_t)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+
+          mv_cust_eoam_llid_set(cust_llid_set.llid, &(cust_llid_set.llid_mac[0]), cust_llid_set.txq);
+          ret = 0;
+          break;
+
+      case MV_CUST_IOCTL_MAP_RULE_SET:
+          if(copy_from_user(&cust_flow_map, (mv_cust_ioctl_flow_map_t *)arg, sizeof(mv_cust_ioctl_flow_map_t)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+
+          ret = mv_cust_map_rule_set(&cust_flow_map);
+          break;
+
+      case MV_CUST_IOCTL_DSCP_MAP_SET:
+          if(copy_from_user(&cust_dscp_map, (mv_cust_ioctl_dscp_map_t *)arg, sizeof(mv_cust_ioctl_dscp_map_t)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+
+          ret = mv_cust_dscp_map_set(&cust_dscp_map.dscp_map);
+          break;          
+
+      case MV_CUST_IOCTL_MAP_RULE_DEL:
+          if(copy_from_user(&cust_flow_map, (mv_cust_ioctl_flow_map_t *)arg, sizeof(mv_cust_ioctl_flow_map_t)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+
+          ret = mv_cust_map_rule_del((uint16_t)cust_flow_map.vid, (uint8_t)cust_flow_map.pbits, cust_flow_map.dir);
+          break; 
+
+      case MV_CUST_IOCTL_DSCP_MAP_DEL:
+
+          ret = mv_cust_dscp_map_del();
+          break; 
+          
+      case MV_CUST_IOCTL_MAP_RULE_CLEAR:
+      
+          ret = mv_cust_map_rule_clear();
+          break; 
+          
+      case MV_CUST_IOCTL_TAG_MAP_RULE_GET:
+          if(copy_from_user(&cust_flow_map, (mv_cust_ioctl_flow_map_t *)arg, sizeof(mv_cust_ioctl_flow_map_t)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+      
+          ret = mv_cust_tag_map_rule_get(&cust_flow_map);
+
+          if(ret != MV_CUST_OK)
+            goto ioctlErr;
+
+          if(copy_to_user((mv_cust_ioctl_flow_map_t*)arg, &cust_flow_map, sizeof(mv_cust_ioctl_flow_map_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }          
+          break;
+
+      case MV_CUST_IOCTL_UNTAG_MAP_RULE_GET:
+          if(copy_from_user(&cust_flow_map, (mv_cust_ioctl_flow_map_t *)arg, sizeof(mv_cust_ioctl_flow_map_t)))
+          {
+            MVCUST_ERR_PRINT("copy_from_user failed\n");
+            goto ioctlErr;
+          }
+      
+          ret = mv_cust_untag_map_rule_get(&cust_flow_map);
+
+          if(ret != MV_CUST_OK)
+            goto ioctlErr;
+
+          if(copy_to_user((mv_cust_ioctl_flow_map_t*)arg, &cust_flow_map, sizeof(mv_cust_ioctl_flow_map_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }          
+          break;
+
+      default:
+          ret = -EINVAL;
+  }
+
+ioctlErr:
+    return(ret);
+}
+
+
+static const struct file_operations mvcust_dev_fops = 
+{
+	.open    = mvcust_dev_open,
+	.release = mvcust_dev_release,
+	.ioctl   = mvcust_dev_ioctl,
+};
+
+/*******************************************************************************
+**
+**  mvcust_dev_init
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: 
+**
+**  PARAMETERS:  
+**               
+**               
+**               
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+int32_t mvcust_dev_init(void)
+{
+    int rc;
+
+    MVCUST_DEBUG_PRINT("Enter");
+    
+    mvcust_misc_dev.minor = MISC_DYNAMIC_MINOR;
+    mvcust_misc_dev.name  = MVCUST_DEVICE_NAME;
+    mvcust_misc_dev.fops  = &mvcust_dev_fops;
+
+    rc = misc_register(&mvcust_misc_dev);
+    if (rc != 0) 
+    {
+        MVCUST_ERR_PRINT("rc=%d",rc);
+        return rc;
+    }
+
+    rc = mvcust_netdev_init();
+    if (rc != 0) 
+    {
+        MVCUST_ERR_PRINT("rc=%d",rc);
+        return rc;
+    }
+
+    rc = mvcust_sysfs_init();
+    if (rc != 0) 
+    {
+        MVCUST_ERR_PRINT("rc=%d",rc);
+        return rc;
+    }
+
+    printk("MVCUST: misc device %s registered with minor: %d\n", MVCUST_DEVICE_NAME, mvcust_misc_dev.minor);
+    return 0;
+}
+
+
+/*******************************************************************************
+**
+**  mvcust_dev_shutdown
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: 
+**
+**  PARAMETERS:  
+**               
+**               
+**               
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+void mvcust_dev_shutdown(void)
+{
+	MVCUST_DEBUG_PRINT("Enter");
+
+    mvcust_sysfs_delete();
+
+    misc_deregister(&mvcust_misc_dev);
+}
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.h
new file mode 100755
index 0000000..ee49477
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_dev.h
@@ -0,0 +1,88 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_dev.h
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+
+#ifndef __MV_CUST_DEV_H__
+#define __MV_CUST_DEV_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define MV_CUST_VERSION     "V2.6.25"
+#define MVCUST_DEVICE_NAME  "cust"
+#define MV_CUST_IOCTL_MAGIC ('C')
+
+#ifdef MV_CUST_DEBUG
+#define MVCUST_DEBUG_PRINT(format, ...)   printk("%s(%d):  "format,__FUNCTION__,__LINE__, ##__VA_ARGS__)
+#else
+#define MVCUST_DEBUG_PRINT(format, ...)
+#endif
+
+#define MVCUST_ERR_PRINT(format, ...)     printk("%s(%d) ERROR:  "format,__FUNCTION__,__LINE__, ##__VA_ARGS__)
+
+extern struct bus_type platform_bus_type;
+
+/******************************************************
+ * Function prototypes --                             *
+*******************************************************/
+int32_t mvcust_dev_init        (void);
+void    mvcust_dev_shutdown    (void);
+
+int     mvcust_netdev_init     (void);
+int     mvcust_sysfs_init      (void);
+void    mvcust_sysfs_delete    (void);
+
+void    mv_cust_omci_print         (void);
+void    mv_cust_eoam_print         (void);
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+void    mv_cust_igmp_print         (void);
+#endif
+void    mv_cust_loopdet_print      (void);
+
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+void    mv_cust_udp_spec_print_all (void);
+#endif
+void    mv_cust_debug_info_set     (int val);
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+void mv_cust_flow_map_print(void);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__MV_CUST_DEV_H__*/
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.c
new file mode 100755
index 0000000..a50854c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.c
@@ -0,0 +1,998 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_flow_map.c
+*
+* DESCRIPTION:
+*   Victor  - initial version created.   12/Dec/2011 
+*
+*******************************************************************************/
+#include <mvCommon.h>
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+
+#include <mvOs.h>
+#include <ctrlEnv/mvCtrlEnvLib.h>
+
+#include "mv_cust_dev.h"
+#include "mv_cust_netdev.h"
+#include "mv_cust_flow_map.h"
+#include "mv_cust_mng_if.h"
+
+/****************************************************************************** 
+*                           Global Data Definitions                                                                                                                                  
+******************************************************************************/
+static mv_cust_vid_index_t  gs_vid_index_table[MV_CUST_FLOW_DIR_NUM];
+static mv_cust_pbits_map_t  gs_pbits_map_table[MV_CUST_FLOW_DIR_NUM][MV_CUST_MAX_PBITS_MAP_TABLE_SIZE];
+static mv_cust_dscp_pbits_t gs_dscp_map_table;
+
+static uint32_t gs_mv_cust_trace_flag = 0;
+
+
+/****************************************************************************** 
+*                           External Declarations                                                                                                                                 
+******************************************************************************/
+
+
+
+/****************************************************************************** 
+*                           Function Definitions                                                                                                                                  
+******************************************************************************/
+/*******************************************************************************
+**
+**    mv_cust_set_trace_flag
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function sets mv_cust trace flag.
+**
+**    INPUTS:
+**      enTrace     - Enable or disable mv_cust trace.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/    
+int mv_cust_set_trace_flag(uint32_t enTrace)
+{
+    gs_mv_cust_trace_flag = enTrace;
+    
+    return MV_CUST_OK;
+}
+
+/*******************************************************************************
+**
+**    mv_cust_valid_pbits_table_get
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function gets available P-bits mapping table.
+**
+**    INPUTS:
+**      None.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      Available P-bits mapping table index.  
+**
+*******************************************************************************/    
+uint32_t mv_cust_valid_pbits_table_get(mv_cust_flow_dir_e dir)
+{
+    uint32_t table_idx = 0;
+
+    /* Table index MV_CUST_MAX_PBITS_MAP_TABLE_SIZE is reserved for tagged default packets */
+    for (table_idx=0; table_idx<MV_CUST_MAX_PBITS_MAP_TABLE_SIZE-1; table_idx++) {
+    
+       if (gs_pbits_map_table[dir][table_idx].in_use == 0)
+           return table_idx;
+    }
+    
+    return MV_CUST_INVALID_PBITS_TABLE_INDEX;
+}
+
+/*******************************************************************************
+**
+**    mv_cust_pbits_table_status_get
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function gets P-bits mapping table status.
+**
+**    INPUTS:
+**      pbits_map   - P-bits mapping table.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      0:No P-bits mapping rule exist in current table, 1: still exists P-bits mapping rule.  
+**
+*******************************************************************************/    
+uint32_t mv_cust_pbits_table_status_get(mv_cust_pbits_map_t *pbits_map)
+{
+    uint32_t pbits_idx = 0;
+
+    for (pbits_idx=0; pbits_idx<MV_CUST_PBITS_MAP_MAX_ENTRY_NUM; pbits_idx++) {
+    
+       if (pbits_map->pkt_fwd[pbits_idx].in_use != 0)
+           return MV_CUST_OK;
+    }
+    
+    return MV_CUST_FAIL;
+}
+
+/*******************************************************************************
+**
+**    mv_cust_map_rule_set
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function sets GPON flow mapping rules
+**
+**    INPUTS:
+**      cust_flow  - VLAN ID, 802.1p value, pkt_fwd information.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_map_rule_set(mv_cust_ioctl_flow_map_t *cust_flow)
+{
+    uint8_t              *pVidEntry  = NULL;
+    mv_cust_pbits_map_t  *pPbitsMap  = NULL;
+    uint32_t              pbitsIndex = 0;
+    uint32_t              index      = 0;
+    uint32_t              vid        = 0;
+    uint32_t              pbits      = 0;
+    uint32_t              mod_vid    = 0;
+    uint32_t              mod_pbits  = 0;   
+    mv_cust_flow_dir_e    dir        = MV_CUST_FLOW_DIR_US;    
+    mv_cust_pkt_frwd_t   *pkt_fwd    = NULL;
+
+    /* Get input information: VID, P-bits... */
+    if (cust_flow == NULL) {
+        MVCUST_ERR_PRINT(KERN_ERR "cust_flow is NULL \n\r");
+        return MV_CUST_FAIL;
+    } 
+    vid       =  cust_flow->vid;
+    pbits     =  cust_flow->pbits;
+    mod_vid   =  cust_flow->mod_vid;
+    mod_pbits =  cust_flow->mod_pbits;    
+    pkt_fwd   = &cust_flow->pkt_frwd;
+    dir       =  cust_flow->dir;
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO 
+                           "==ENTER==%s: vid[%d], pbits[%d], mod_vid[%d], mod_pbits[%d], T-CONT[%d], SWF queue[%d], HWF queue[%d], GEM port[%d], dir[%d]\n\r",
+                            __FUNCTION__, vid, pbits, mod_vid, mod_pbits,
+                           ((pkt_fwd!= NULL)? pkt_fwd->trg_port:0), 
+                           ((pkt_fwd!= NULL)? pkt_fwd->trg_queue:0), 
+                           ((pkt_fwd!= NULL)? pkt_fwd->trg_hwf_queue:0),                            
+                           ((pkt_fwd!= NULL)? pkt_fwd->gem_port:0),
+                           cust_flow->dir);
+    }
+
+    /* Check VID */
+    if (vid > (MV_CUST_VID_INDEX_TABLE_MAX_SIZE - 1)) {
+        MVCUST_ERR_PRINT(KERN_ERR "vid[%d] exceeds maximum value[%d] \n\r", vid, (MV_CUST_VID_INDEX_TABLE_MAX_SIZE - 1));
+        return MV_CUST_FAIL;
+    }
+    
+    /* Check P-bits */
+    if (pbits > MV_CUST_PBITS_NOT_CARE_VALUE) {
+        MVCUST_ERR_PRINT(KERN_ERR "P-bits[%d] exceeds maximum value[%d] \n\r", pbits, MV_CUST_PBITS_NOT_CARE_VALUE);
+        return MV_CUST_FAIL;
+    }
+
+    /* Check mod VID */
+    if (mod_vid > (MV_CUST_VID_INDEX_TABLE_MAX_SIZE - 1)) {
+        MVCUST_ERR_PRINT(KERN_ERR "mod_vid[%d] exceeds maximum value[%d] \n\r", mod_vid, (MV_CUST_VID_INDEX_TABLE_MAX_SIZE - 1));
+        return MV_CUST_FAIL;
+    }
+    
+    /* Check mod P-bits */
+    if (mod_pbits > MV_CUST_PBITS_NOT_CARE_VALUE) {
+        MVCUST_ERR_PRINT(KERN_ERR "mod_pbits[%d] exceeds maximum value[%d] \n\r", mod_pbits, MV_CUST_PBITS_NOT_CARE_VALUE);
+        return MV_CUST_FAIL;
+    }
+
+    /* Check dir */
+    if (dir >= MV_CUST_FLOW_DIR_NUM) {
+        MVCUST_ERR_PRINT(KERN_ERR "dir[%d] exceeds maximum value[%d] \n\r", dir, MV_CUST_FLOW_DIR_NUM-1);
+        return MV_CUST_FAIL;
+    }    
+
+    /* Check target port/queue/GEM port */ 
+    if (pkt_fwd->trg_port > MV_CUST_MAX_TRG_PORT_VALUE) {
+        MVCUST_ERR_PRINT(KERN_ERR "trg_port[%d] exceeds maximum value[%d] \n\r", pkt_fwd->trg_port, MV_CUST_MAX_TRG_PORT_VALUE);
+        return MV_CUST_FAIL;
+    }
+
+    if (pkt_fwd->trg_queue > MV_CUST_MAX_TRG_QUEUE_VALUE) {
+        MVCUST_ERR_PRINT(KERN_ERR "SWF trg_queue[%d] exceeds maximum value[%d] \n\r", pkt_fwd->trg_queue, MV_CUST_MAX_TRG_QUEUE_VALUE);
+        return MV_CUST_FAIL;
+    }   
+
+    if (pkt_fwd->trg_hwf_queue > MV_CUST_MAX_TRG_QUEUE_VALUE) {
+        MVCUST_ERR_PRINT(KERN_ERR "HWF trg_queue[%d] exceeds maximum value[%d] \n\r", pkt_fwd->trg_queue, MV_CUST_MAX_TRG_QUEUE_VALUE);
+        return MV_CUST_FAIL;
+    }       
+
+    if (pkt_fwd->gem_port > MV_CUST_MAX_GEM_PORT_VALUE) {
+        MVCUST_ERR_PRINT(KERN_ERR "trg_queue[%d] exceeds maximum value[%d] \n\r", pkt_fwd->gem_port, MV_CUST_MAX_GEM_PORT_VALUE);
+        return MV_CUST_FAIL;
+    }          
+ 
+    
+    /* Find VID index entry by VID */    
+    pVidEntry = &gs_vid_index_table[dir].pbits_map_index[vid];
+
+    /* Get P-bits mapping table */
+    /* If this VID index entry does not point to any P-bits mapping table,
+       need to search for an available P-bits mapping table             */
+    if (*pVidEntry >= MV_CUST_MAX_PBITS_MAP_TABLE_SIZE) {
+        /* Reserved for default tagged rule */
+        if (vid == MV_CUST_DEFAULT_SINGLE_TAG_RULE)
+            pbitsIndex = MV_CUST_MAX_PBITS_MAP_TABLE_SIZE - 1;
+        else
+            pbitsIndex = mv_cust_valid_pbits_table_get(dir);
+        
+        if (pbitsIndex >= MV_CUST_MAX_PBITS_MAP_TABLE_SIZE) {
+            MVCUST_ERR_PRINT(KERN_ERR " %d P-bits mapping table has used out\n\r", MV_CUST_INVALID_PBITS_TABLE_INDEX);
+            return MV_CUST_FAIL;     
+        }            
+    }
+    /* In case that the VID index already points to a P-bits mapping table,
+       Need to replace the forwarding information of this P-bit mapping table */
+    else {
+        pbitsIndex = *pVidEntry;
+    }
+    pPbitsMap = &gs_pbits_map_table[dir][pbitsIndex];
+
+    /* If legal P-bits is configured */
+    if (pbits < MV_CUST_PBITS_NOT_CARE_VALUE) {
+        /* In case to enable packet forwarding */
+        if (pkt_fwd->in_use != 0) {
+        
+            /* Save forwarding information */        
+            pPbitsMap->pkt_fwd[pbits].trg_port      = pkt_fwd->trg_port;
+            pPbitsMap->pkt_fwd[pbits].trg_queue     = pkt_fwd->trg_queue;
+            pPbitsMap->pkt_fwd[pbits].trg_hwf_queue = pkt_fwd->trg_hwf_queue;
+            pPbitsMap->pkt_fwd[pbits].gem_port      = pkt_fwd->gem_port;
+
+            /* Save mod_vid mod_pbits */
+            pPbitsMap->mod_vid[pbits]           = mod_vid;
+            pPbitsMap->mod_pbits[pbits]         = mod_pbits;
+
+            /* Enable in_use flag */
+            pPbitsMap->pkt_fwd[pbits].in_use    = 1;
+            pPbitsMap->in_use                   = 1;
+
+            /* Save P-bit mapping table index in VID index table */
+            *pVidEntry = pbitsIndex;                
+        }
+        /* In case to disable packet forwarding */
+        else {
+            /* CLear forwarding information */        
+            pPbitsMap->pkt_fwd[pbits].trg_port      = 0;
+            pPbitsMap->pkt_fwd[pbits].trg_queue     = 0;
+            pPbitsMap->pkt_fwd[pbits].trg_hwf_queue = 0;
+            pPbitsMap->pkt_fwd[pbits].gem_port      = 0;
+
+            /* Clear mod_vid mod_pbits */
+            pPbitsMap->mod_vid[pbits]           = 0;
+            pPbitsMap->mod_pbits[pbits]         = 0;          
+
+            /* Disable in_use flag */
+            pPbitsMap->pkt_fwd[pbits].in_use    = 0;
+            if (mv_cust_pbits_table_status_get(pPbitsMap) != MV_CUST_OK) {
+                pPbitsMap->in_use               = 0;
+                *pVidEntry                      = MV_CUST_INVALID_PBITS_TABLE_INDEX;
+            }
+            else {
+                pPbitsMap->in_use               = 1;
+                *pVidEntry                      = pbitsIndex;
+            }
+        }
+    }
+    /* If does not care for P-bits, each P-bits mapping entry should be set */
+    else if (pbits == MV_CUST_PBITS_NOT_CARE_VALUE) {
+
+        index = MV_CUST_PBITS_NOT_CARE_VALUE;
+
+        /* In case to enable packet forwarding */
+        if (pkt_fwd->in_use != 0) {
+            
+            /* Save forwarding information */        
+            pPbitsMap->pkt_fwd[index].trg_port      = pkt_fwd->trg_port;
+            pPbitsMap->pkt_fwd[index].trg_queue     = pkt_fwd->trg_queue;
+            pPbitsMap->pkt_fwd[pbits].trg_hwf_queue = pkt_fwd->trg_hwf_queue;
+            pPbitsMap->pkt_fwd[index].gem_port      = pkt_fwd->gem_port;
+            pPbitsMap->pkt_fwd[index].in_use        = 1;
+            
+            /* Save mod_vid mod_pbits */
+            pPbitsMap->mod_vid[index]           = mod_vid;
+            pPbitsMap->mod_pbits[index]         = mod_pbits;           
+
+            /* Enable in_use flag */
+            pPbitsMap->in_use = 1;
+
+            /* Save P-bit mapping table index in VID index table */
+            *pVidEntry = pbitsIndex;                
+        }
+        /* In case to disable packet forwarding */
+        else { 
+            
+            /* Clear forwarding information */        
+            pPbitsMap->pkt_fwd[index].trg_port      = 0;
+            pPbitsMap->pkt_fwd[index].trg_queue     = 0;
+            pPbitsMap->pkt_fwd[pbits].trg_hwf_queue = 0;
+            pPbitsMap->pkt_fwd[index].gem_port      = 0;
+            pPbitsMap->pkt_fwd[index].in_use        = 0;
+            /* clear mod_vid mod_pbits */
+            pPbitsMap->mod_vid[index]           = 0;
+            pPbitsMap->mod_pbits[index]         = 0;
+
+            /* Disable in_use flag */
+            if (mv_cust_pbits_table_status_get(pPbitsMap) != MV_CUST_OK) {
+                pPbitsMap->in_use               = 0;
+                *pVidEntry                      = MV_CUST_INVALID_PBITS_TABLE_INDEX;
+            }
+            else {
+                pPbitsMap->in_use               = 1;
+                *pVidEntry                      = pbitsIndex;
+            }
+        }        
+    }
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO
+                           "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return MV_CUST_OK;   
+}
+
+/*******************************************************************************
+**
+**    mv_cust_dscp_map_set
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function sets GPON DSCP to P-bits mapping rules
+**
+**    INPUTS:
+**      dscp_map     - DSCP to P-bits mapping rules.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_dscp_map_set(mv_cust_dscp_pbits_t *dscp_map)
+{
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO 
+                           "==ENTER==%s: in_use[%d]\n\r", __FUNCTION__,
+                           ((dscp_map!= NULL)? dscp_map->in_use:0));
+    }
+
+    if (dscp_map == NULL) {
+        MVCUST_ERR_PRINT(KERN_ERR "Input dscp_map is NULL\n\r");
+        return MV_CUST_FAIL;
+    }
+
+    /* Case 1: to enable DSCP to P-bits mapping */
+    if (dscp_map->in_use != 0) {
+        memcpy(&gs_dscp_map_table.pbits[0], &dscp_map->pbits[0], sizeof(gs_dscp_map_table.pbits));
+        gs_dscp_map_table.in_use = 1;
+    
+    }
+    /* Case 2: to disable DSCP to P-bits mapping */
+    else {
+        memset((uint8_t *)&gs_dscp_map_table, 0, sizeof(gs_dscp_map_table));
+        gs_dscp_map_table.in_use = 0;
+    }
+    
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO
+                           "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+    
+    return MV_CUST_OK;   
+}
+
+/*******************************************************************************
+**
+**    mv_cust_map_rule_del
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function deletes GPON flow mapping rules
+**
+**    INPUTS:
+**      vid         - VLAN ID.
+**      pbits      - 802.1p value.
+**
+**    OUTPUTS:
+**      None 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_map_rule_del(uint16_t vid, uint8_t pbits, mv_cust_flow_dir_e dir)
+{
+    uint8_t              *pVidEntry  = NULL;
+    mv_cust_pbits_map_t  *pPbitsMap  = NULL;
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO 
+                           "==ENTER==: vid[%d],pbits[%d]\n\r", vid, pbits);
+    }
+
+    /* Check VID */
+    if (vid > (MV_CUST_VID_INDEX_TABLE_MAX_SIZE - 1)) {
+        MVCUST_ERR_PRINT(KERN_ERR "vid[%d] exceeds maximum value[%d] \n\r", vid, (MV_CUST_VID_INDEX_TABLE_MAX_SIZE - 1));
+        return MV_CUST_FAIL;
+    }
+    
+    /* Check P-bits */
+    if (pbits > MV_CUST_PBITS_NOT_CARE_VALUE) {
+        MVCUST_ERR_PRINT(KERN_ERR "P-bits[%d] exceeds maximum value[%d] \n\r", pbits, MV_CUST_PBITS_NOT_CARE_VALUE);
+        return MV_CUST_FAIL;
+    }
+
+    /* Check dir */
+    if (dir >= MV_CUST_FLOW_DIR_NUM) {
+        MVCUST_ERR_PRINT(KERN_ERR "dir[%d] exceeds maximum value[%d] \n\r", dir, MV_CUST_FLOW_DIR_NUM-1);
+        return MV_CUST_FAIL;
+    }   
+
+    /* Find VID index entry by VID */    
+    pVidEntry = &gs_vid_index_table[dir].pbits_map_index[vid];
+
+    if (*pVidEntry >= MV_CUST_MAX_PBITS_MAP_TABLE_SIZE) {
+         MVCUST_TRACE_PRINT(KERN_INFO "%s, pVidEntry[%d], does not need to delete \n\r",__FUNCTION__, *pVidEntry);    
+        return MV_CUST_OK;                      
+    }
+
+    /* Find P-bits mapping table */
+    pPbitsMap = &gs_pbits_map_table[dir][*pVidEntry];
+
+    /* Delete P-bits mapping rule */
+    pPbitsMap->pkt_fwd[pbits].trg_port   = 0;
+    pPbitsMap->pkt_fwd[pbits].trg_queue  = 0;
+    pPbitsMap->pkt_fwd[pbits].gem_port   = 0;
+    pPbitsMap->pkt_fwd[pbits].in_use     = 0;
+    pPbitsMap->mod_vid[pbits]            = 0;
+    pPbitsMap->mod_pbits[pbits]          = 0;          
+    
+    /* Disable in_use flag */
+    if (mv_cust_pbits_table_status_get(pPbitsMap)!= MV_CUST_OK) {
+        pPbitsMap->in_use                = 0;
+        *pVidEntry                       = MV_CUST_INVALID_PBITS_TABLE_INDEX;
+    }
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO
+                           "==EXIT==:\n\r");
+    }
+
+    return MV_CUST_OK;  
+}
+
+/*******************************************************************************
+**
+**    mv_cust_dscp_map_del
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function deletes DSCP to P-bits mapping rules
+**
+**    INPUTS:
+**      None.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_dscp_map_del(void)
+{
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO 
+                           "==ENTER==\n\r");
+    }
+
+    /* Clear DSCP to P-bits mapping */
+    else {
+        memset((uint8_t *)&gs_dscp_map_table, 0, sizeof(gs_dscp_map_table));
+        gs_dscp_map_table.in_use = 0;
+    }
+    
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO
+                           "==EXIT==\n\r");
+    }
+    
+    return MV_CUST_OK;
+}
+
+/*******************************************************************************
+**
+**    mv_cust_map_rule_clear
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function clears all GPON flow mapping rules
+**
+**    INPUTS:
+**      None.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_map_rule_clear(void)
+{
+    uint32_t pbits_index = 0;
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO 
+                           "==ENTER==\n\r");
+    }
+
+    /* Clear VID index table              */
+    memset((uint8_t *)&gs_vid_index_table, MV_CUST_INVALID_PBITS_TABLE_INDEX, sizeof(gs_vid_index_table));
+
+    /* Clear P-bits mapping tables        */
+    for (pbits_index=0; pbits_index<MV_CUST_MAX_PBITS_MAP_TABLE_SIZE; pbits_index++) {
+        memset((uint8_t *)&gs_pbits_map_table[MV_CUST_FLOW_DIR_US][pbits_index], 0, sizeof(mv_cust_pbits_map_t));
+        gs_pbits_map_table[MV_CUST_FLOW_DIR_US][pbits_index].in_use = 0;
+        memset((uint8_t *)&gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][pbits_index], 0, sizeof(mv_cust_pbits_map_t));
+        gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][pbits_index].in_use = 0;        
+    }
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO
+                           "==EXIT==\n\r");
+    }
+
+    return MV_CUST_OK;  
+}
+
+/*******************************************************************************
+**
+**    mv_cust_tag_map_rule_get
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function gets GPON flow mapping rule for tagged frames.
+**
+**  INPUTS:
+**    cust_flow  - parsing vid, pbits, dir
+**
+**  OUTPUTS:
+**    cust_flow  - out packet forwarding information, including GEM port, T-CONT, queue.
+**                 and packet modification for VID, P-bits
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_tag_map_rule_get(mv_cust_ioctl_flow_map_t *cust_flow)
+{
+    uint8_t              *pVidEntry  = NULL;
+    mv_cust_pbits_map_t  *pPbitsMap  = NULL;
+    mv_cust_pkt_frwd_t   *pPktFrwd   = NULL;
+    uint32_t              vid        = 0;
+    uint32_t              pbits      = 0;  
+    mv_cust_flow_dir_e    dir        = MV_CUST_FLOW_DIR_US;     
+    mv_cust_pkt_frwd_t   *pkt_fwd    = NULL;
+    uint32_t              index      = 0;    
+
+    /* Get input parameters */
+    vid     = cust_flow->vid;
+    pbits   = cust_flow->pbits;
+    dir     = cust_flow->dir;
+    pkt_fwd = &cust_flow->pkt_frwd;
+    
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO 
+                           "==ENTER==: vid[%d], pbits[%d], dir[%d]\n\r", vid, pbits, dir);
+    }
+
+    /* Check VID */
+    if (vid > (MV_CUST_VID_INDEX_TABLE_MAX_SIZE - 1)) {
+        MVCUST_ERR_PRINT(KERN_ERR "vid[%d] exceeds maximum value[%d] \n\r", vid, (MV_CUST_VID_INDEX_TABLE_MAX_SIZE - 1));
+        return MV_CUST_FAIL;
+    }
+    
+    /* Check P-bits */
+    if (pbits > MV_CUST_PBITS_NOT_CARE_VALUE) {
+        MVCUST_ERR_PRINT(KERN_ERR "P-bits[%d] exceeds maximum value[%d] \n\r", pbits, MV_CUST_PBITS_NOT_CARE_VALUE);
+        return MV_CUST_FAIL;
+    }
+
+    /* Check dir */
+    if (dir >= MV_CUST_FLOW_DIR_NUM) {
+        MVCUST_ERR_PRINT(KERN_ERR "dir[%d] exceeds maximum value[%d] \n\r", dir, MV_CUST_FLOW_DIR_NUM-1);
+        return MV_CUST_FAIL;
+    }    
+
+    /* Set default values */
+    cust_flow->mod_vid   = MV_CUST_VID_NOT_CARE_VALUE;
+    cust_flow->mod_pbits = MV_CUST_PBITS_NOT_CARE_VALUE; 
+    
+    /* Find VID index entry by VID */    
+    pVidEntry = &gs_vid_index_table[dir].pbits_map_index[vid];
+
+    if (*pVidEntry >= MV_CUST_MAX_PBITS_MAP_TABLE_SIZE) {
+         //MVCUST_ERR_PRINT(KERN_ERR "%s, pVidEntry[%d], No matched P-bits mapping table \n\r",__FUNCTION__, *pVidEntry);    
+
+        pkt_fwd->in_use = 0;
+        if (gs_mv_cust_trace_flag) {
+            MVCUST_TRACE_PRINT(KERN_INFO
+                               "==EXIT==\n\r");
+        }
+
+        return MV_CUST_FAIL;                      
+    }
+
+    /* Find P-bits mapping table */
+    pPbitsMap = &gs_pbits_map_table[dir][*pVidEntry];    
+
+    /* Get packet forwarding information */
+    index = pbits;
+
+    pPktFrwd = &pPbitsMap->pkt_fwd[index];
+
+    /* If specific flow mapping rule exists */
+    if (pPktFrwd->in_use != 0) { 
+        pkt_fwd->trg_port      = pPktFrwd->trg_port;
+        pkt_fwd->trg_queue     = pPktFrwd->trg_queue;
+        pkt_fwd->trg_hwf_queue = pPktFrwd->trg_hwf_queue;
+        pkt_fwd->gem_port      = pPktFrwd->gem_port;
+        cust_flow->mod_vid     = pPbitsMap->mod_vid[index];
+        cust_flow->mod_pbits   = pPbitsMap->mod_pbits[index];       
+        pkt_fwd->in_use        = 1;
+        
+        if (gs_mv_cust_trace_flag) {
+            MVCUST_TRACE_PRINT(KERN_INFO
+                               "trg_port(%d), trg_queue(%d) trg_hwf_queue(%d) gem_port(%d), mod_vid(%d), mod_pbits(%d)\n\r",
+                                cust_flow->pkt_frwd.trg_port, cust_flow->pkt_frwd.trg_queue, cust_flow->pkt_frwd.trg_hwf_queue, 
+                                cust_flow->pkt_frwd.gem_port, cust_flow->mod_vid, cust_flow->mod_pbits);
+        }
+        
+    }
+    /* If specific flow mapping rule does not exist, look for default rule */
+    else {
+        index = MV_CUST_PBITS_NOT_CARE_VALUE;
+        pPktFrwd = &pPbitsMap->pkt_fwd[index];
+
+        /* If default flow mapping rule exists */
+        if (pPktFrwd->in_use != 0) { 
+            pkt_fwd->trg_port      = pPktFrwd->trg_port;
+            pkt_fwd->trg_queue     = pPktFrwd->trg_queue;
+            pkt_fwd->trg_hwf_queue = pPktFrwd->trg_hwf_queue;
+            pkt_fwd->gem_port      = pPktFrwd->gem_port;
+            cust_flow->mod_vid     = pPbitsMap->mod_vid[index];
+            cust_flow->mod_pbits   = pPbitsMap->mod_pbits[index];       
+            pkt_fwd->in_use        = 1;
+            
+            if (gs_mv_cust_trace_flag) {
+                MVCUST_TRACE_PRINT(KERN_INFO
+                                   "trg_port(%d), trg_queue(%d) trg_hwf_queue(%d) gem_port(%d), mod_vid(%d), mod_pbits(%d)\n\r",
+                                    cust_flow->pkt_frwd.trg_port, cust_flow->pkt_frwd.trg_queue, cust_flow->pkt_frwd.trg_hwf_queue, 
+                                    cust_flow->pkt_frwd.gem_port, cust_flow->mod_vid, cust_flow->mod_pbits);
+            }
+            
+        }
+        else {
+        
+            pkt_fwd->in_use      = 0;
+            if (gs_mv_cust_trace_flag) {
+                MVCUST_TRACE_PRINT(KERN_INFO
+                                   "==EXIT==\n\r");
+            }        
+            return MV_CUST_FAIL;
+        }
+    }
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO
+                           "==EXIT==\n\r");
+    }
+
+    return MV_CUST_OK;
+}
+
+/*******************************************************************************
+**
+**    mv_cust_untag_map_rule_get
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function gets GPON flow mapping rule for untagged frames.
+**
+**    INPUTS:
+**      dscp         - DSCP value.
+**
+**    OUTPUTS:
+**      cust_flow    - packet forwarding information, including GEM port, T-CONT, queue.
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_untag_map_rule_get(mv_cust_ioctl_flow_map_t *cust_flow)
+{
+    uint8_t              *pVidEntry  = NULL;
+    mv_cust_pbits_map_t  *pPbitsMap  = NULL;
+    mv_cust_pkt_frwd_t   *pPktFrwd   = NULL;
+    uint32_t              pbitsIndex = MV_CUST_PBITS_NOT_CARE_VALUE;
+    mv_cust_flow_dir_e    dir        = MV_CUST_FLOW_DIR_US;
+    uint32_t              dscp       = 0;
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO 
+                           "==ENTER==: dscp[%d] \n\r", dscp);
+    }
+
+    /* Check target port/queue/GEM port */
+    if (cust_flow == NULL) {
+        MVCUST_ERR_PRINT(KERN_ERR "cust_flow is NULL \n\r");
+        return MV_CUST_FAIL;
+    }
+
+    /* Set forwarding flag to false at first */
+    cust_flow->pkt_frwd.in_use = 0;
+    cust_flow->mod_vid         = MV_CUST_VID_NOT_CARE_VALUE;
+    cust_flow->mod_pbits       = MV_CUST_PBITS_NOT_CARE_VALUE; 
+
+    dir  = cust_flow->dir;  
+    dscp = cust_flow->dscp;  
+
+    /* Check DSCP */
+    if (dscp < MV_CUST_DSCP_PBITS_TABLE_MAX_SIZE) {
+        if (gs_dscp_map_table.in_use != 0) {
+            pbitsIndex = gs_dscp_map_table.pbits[dscp];
+        }
+    }
+
+    if(pbitsIndex > MV_CUST_PBITS_NOT_CARE_VALUE){
+        //MVCUST_ERR_PRINT(KERN_ERR "pbitsIndex[%d] is illegal \n\r", pbitsIndex);
+        return MV_CUST_FAIL;
+    }
+
+    /* Find P-bits mapping table */
+    pVidEntry = &gs_vid_index_table[dir].pbits_map_index[MV_CUST_DEFAULT_UNTAG_RULE];
+
+    if (*pVidEntry >= MV_CUST_MAX_PBITS_MAP_TABLE_SIZE) {
+        //MVCUST_TRACE_PRINT(KERN_INFO "%s, pVidEntry[%d], does not exist \n\r",__FUNCTION__, *pVidEntry);                 
+    }
+    else {
+        
+        pPbitsMap = &gs_pbits_map_table[dir][*pVidEntry];
+
+        if (pPbitsMap->in_use != 0) {
+
+            pPktFrwd  = &pPbitsMap->pkt_fwd[pbitsIndex];
+            if (pPktFrwd->in_use != 0) {
+                cust_flow->pkt_frwd.trg_port      = pPktFrwd->trg_port;
+                cust_flow->pkt_frwd.trg_queue     = pPktFrwd->trg_queue;
+                cust_flow->pkt_frwd.trg_hwf_queue = pPktFrwd->trg_hwf_queue;
+                cust_flow->pkt_frwd.gem_port      = pPktFrwd->gem_port;
+                cust_flow->mod_vid                = pPbitsMap->mod_vid[pbitsIndex];
+                cust_flow->mod_pbits              = pPbitsMap->mod_pbits[pbitsIndex];
+                cust_flow->pkt_frwd.in_use        = 1;
+                
+                if (gs_mv_cust_trace_flag) {
+                    MVCUST_TRACE_PRINT(KERN_INFO
+                                       "trg_port(%d), trg_queue(%d), trg_hwf_queue(%d), gem_port(%d), mod_vid(%d), mod_pbits(%d)\n\r",
+                                        cust_flow->pkt_frwd.trg_port, cust_flow->pkt_frwd.trg_queue, cust_flow->pkt_frwd.trg_hwf_queue,
+                                        cust_flow->pkt_frwd.gem_port, cust_flow->mod_vid, cust_flow->mod_pbits);
+                    MVCUST_TRACE_PRINT(KERN_INFO
+                                       "==EXIT==:\n\r");                                            
+                }
+                
+                return MV_CUST_OK;
+            }             
+        }          
+    }
+
+    if (gs_mv_cust_trace_flag) {
+        MVCUST_TRACE_PRINT(KERN_INFO
+                           "==EXIT==:\n\r");
+    }
+
+    return MV_CUST_FAIL;
+}
+
+/*******************************************************************************
+**
+**    mv_cust_map_table_print
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function displays valid GPON flow mapping tables and DSCP 
+**                 to P-bits mapping tablefor untagged frames.
+**
+**    INPUTS:
+**      None.
+**
+**    OUTPUTS:
+**      None.
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_map_table_print(void)
+{
+    uint32_t  index = 0;
+    uint32_t  table_index = 0;
+
+    //MVCUST_TRACE_PRINT(KERN_INFO "==ENTER==\n\r");
+
+    /* Print Valid VID index entries */
+    printk(KERN_INFO "In Upstream Direction      \n----------------------------------\n"); 
+    printk(KERN_INFO "MV_CUST VLAN ID Index Table\n----------------------------------\n");         
+    printk(KERN_INFO "VID   P-bits_table_index\n");
+    for (index=0; index<MV_CUST_VID_INDEX_TABLE_MAX_SIZE; index++) {
+        if(gs_vid_index_table[MV_CUST_FLOW_DIR_US].pbits_map_index[index] < MV_CUST_MAX_PBITS_MAP_TABLE_SIZE)
+            printk(KERN_INFO "%4.4d   %d\n", index, gs_vid_index_table[MV_CUST_FLOW_DIR_US].pbits_map_index[index]);    
+    }
+    printk(KERN_INFO "\n\n");
+
+    /* Print P-bits mapping tables */
+    printk(KERN_INFO "MV_CUST P-bits Flow Mapping Tables\n----------------------------------\n\n");  
+    for (table_index=0; table_index<MV_CUST_MAX_PBITS_MAP_TABLE_SIZE; table_index++) {
+        if(gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].in_use != 0) {
+                printk(KERN_INFO "P-bits Flow Mapping Table %d\n----------------------------\n", table_index); 
+                printk(KERN_INFO "P-bits  in_use  mod_vid mod_pbits trg_port  trg_queue  trg_hwf_queue  gem_port\n"); 
+                for (index=0; index<MV_CUST_PBITS_MAP_MAX_ENTRY_NUM; index++) 
+                    printk(KERN_INFO "%1.1d       %3.3s     %4.4d    %1.1d          %2.2d        %2.2d         %2.2d            %4.4d\n", 
+                                       index,
+                                       (gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].pkt_fwd[index].in_use!=0)? "YES":"",
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].mod_vid[index],
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].mod_pbits[index],
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].pkt_fwd[index].trg_port, 
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].pkt_fwd[index].trg_queue,
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].pkt_fwd[index].trg_hwf_queue,
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].pkt_fwd[index].gem_port);    
+        
+        }
+    }
+    printk(KERN_INFO "\n\n");
+
+    printk(KERN_INFO "In Downstream Direction    \n----------------------------------\n"); 
+    printk(KERN_INFO "MV_CUST VLAN ID Index Table\n----------------------------------\n");         
+    printk(KERN_INFO "VID   P-bits_table_index\n");
+    for (index=0; index<MV_CUST_VID_INDEX_TABLE_MAX_SIZE; index++) {
+        if(gs_vid_index_table[MV_CUST_FLOW_DIR_DS].pbits_map_index[index] < MV_CUST_MAX_PBITS_MAP_TABLE_SIZE)
+            printk(KERN_INFO "%4.4d   %d\n", index, gs_vid_index_table[MV_CUST_FLOW_DIR_DS].pbits_map_index[index]);    
+    }
+    printk(KERN_INFO "\n\n");
+
+    /* Print P-bits mapping tables */
+    printk(KERN_INFO "MV_CUST P-bits Flow Mapping Tables\n----------------------------------\n\n");  
+    for (table_index=0; table_index<MV_CUST_MAX_PBITS_MAP_TABLE_SIZE; table_index++) {
+        if(gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].in_use != 0) {
+                printk(KERN_INFO "P-bits Flow Mapping Table %d\n----------------------------\n", table_index); 
+                printk(KERN_INFO "P-bits  in_use  mod_vid mod_pbits trg_port  trg_queue  trg_hwf_queue  gem_port\n"); 
+                for (index=0; index<MV_CUST_PBITS_MAP_MAX_ENTRY_NUM; index++) 
+                    printk(KERN_INFO "%1.1d       %3.3s     %4.4d    %1.1d        %2.2d        %2.2d         %2.2d              %4.4d\n", 
+                                       index,
+                                       (gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].in_use!=0)? "YES":"",
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].mod_vid[index],
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].mod_pbits[index],
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].trg_port, 
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].trg_queue,
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_US][table_index].pkt_fwd[index].trg_hwf_queue,
+                                       gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][table_index].pkt_fwd[index].gem_port);    
+        
+        }
+    }
+    printk(KERN_INFO "\n\n");    
+
+    /* Print DSCP to P-bits mapping table */
+    printk(KERN_INFO "MV_CUST DSCP to P-bits Mapping Table\n----------------------------------\n");  
+    if (gs_dscp_map_table.in_use == 0) {
+        printk(KERN_INFO "No DSCP to P-bits mapping\n");
+    }
+    else {
+        
+        printk(KERN_INFO "DSCP  Pbits\n"); 
+        for (index=0; index<MV_CUST_PBITS_MAP_MAX_ENTRY_NUM; index++)
+            printk(KERN_INFO "%2.2d     %1.1d\n", 
+                   index, gs_dscp_map_table.pbits[index]);    
+    }
+    printk(KERN_INFO "\n\n");
+
+    //MVCUST_TRACE_PRINT(KERN_INFO "==EXIT==\n\r");    
+    return MV_CUST_OK; 
+}
+
+/*******************************************************************************
+**
+**    mv_cust_flow_map_init
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function initializes mv_cust flow mapping data structure.
+**
+**    INPUTS:
+**      None.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/    
+int mv_cust_flow_map_init(void)
+{
+    uint32_t pbits_index = 0;
+    
+    /* Initializes VID index table              */
+    memset((uint8_t *)&gs_vid_index_table, MV_CUST_INVALID_PBITS_TABLE_INDEX, sizeof(gs_vid_index_table));
+
+    /* Initializes P-bits mapping tables        */
+    for (pbits_index=0; pbits_index<MV_CUST_MAX_PBITS_MAP_TABLE_SIZE; pbits_index++) {
+        memset((uint8_t *)&gs_pbits_map_table[MV_CUST_FLOW_DIR_US][pbits_index], 0, sizeof(mv_cust_pbits_map_t));
+        gs_pbits_map_table[MV_CUST_FLOW_DIR_US][pbits_index].in_use = 0;
+        memset((uint8_t *)&gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][pbits_index], 0, sizeof(mv_cust_pbits_map_t));
+        gs_pbits_map_table[MV_CUST_FLOW_DIR_DS][pbits_index].in_use = 0;        
+    }
+
+    /* Initializes DSCP to P-bits mapping table */
+    memset((uint8_t *)&gs_dscp_map_table, 0, sizeof(mv_cust_dscp_pbits_t));
+    gs_dscp_map_table.in_use = 0;
+    
+    return MV_CUST_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.h
new file mode 100755
index 0000000..5880b9a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_flow_map.h
@@ -0,0 +1,318 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_flow_map.h
+*
+* DESCRIPTION:
+*   Victor  - initial version created.   12/Dec/2011 
+*
+*******************************************************************************/
+#ifndef __mv_cust_flow_map_h__
+#define __mv_cust_flow_map_h__
+
+
+/****************************************************************************** 
+ *                        Data Enum and Structure                                                                                                                                  
+ ******************************************************************************/
+#define MVCUST_TRACE_PRINT(format, ...)   printk("%s(%d):  "format,__FUNCTION__,__LINE__, ##__VA_ARGS__)
+
+#define MV_CUST_OK                        (0)
+#define MV_CUST_FAIL                      (1)
+
+
+#define MV_CUST_VID_NOT_CARE_VALUE        (4096) /* Does not care for VID    */
+#define MV_CUST_PBITS_NOT_CARE_VALUE      (8)     /* Does not care for P-bits */
+#define MV_CUST_DSCP_NOT_CARE_VALUE       (64)     /* Does not care for DSCP   */
+
+#define MV_CUST_MAX_TRG_PORT_VALUE        (2+8-1)/* Maximum target port value, T-CONT7 */
+#define MV_CUST_MAX_TRG_QUEUE_VALUE       (7)    /* Maximum target queue value         */
+#define MV_CUST_MAX_GEM_PORT_VALUE        (4095) /* Maximum GEM port value             */
+
+#define MV_CUST_INVALID_PBITS_TABLE_INDEX (0xff) /* Invalid Pbits table index value in VID index table*/
+
+#define MV_CUST_DEFAULT_UNTAG_RULE        (4096+1)/* Default untagged  rule        */
+#define MV_CUST_DEFAULT_SINGLE_TAG_RULE   (4096+2)/* Default sinlge tagged  rule   */
+#define MV_CUST_DEFAULT_DOUBLE_UNTAG_RULE (4096+3)/* Default double tagged  rule   */
+
+/* VLAN ID index table definition for flow mapping */
+#define MV_CUST_VID_INDEX_TABLE_MAX_SIZE  (4096+4)
+typedef struct {
+    uint8_t pbits_map_index[MV_CUST_VID_INDEX_TABLE_MAX_SIZE];
+} mv_cust_vid_index_t;
+
+/* P-bits flow mapping table definition */
+typedef uint32_t mv_cust_trg_port_type_t;
+typedef uint32_t mv_cust_gem_port_key_t;
+typedef struct mv_cust_pkt_frwd {
+    uint32_t                in_use;
+    mv_cust_trg_port_type_t trg_port;                                         
+    uint32_t                trg_queue;                      
+    uint32_t                trg_hwf_queue;    
+    mv_cust_gem_port_key_t  gem_port;
+} mv_cust_pkt_frwd_t;
+
+#define MV_CUST_PBITS_MAP_MAX_ENTRY_NUM   (8+1)
+#define MV_CUST_MAX_PBITS_MAP_TABLE_SIZE  (64)
+
+typedef struct {
+    uint32_t           in_use;
+    int                mod_vid[MV_CUST_PBITS_MAP_MAX_ENTRY_NUM];
+    int                mod_pbits[MV_CUST_PBITS_MAP_MAX_ENTRY_NUM];    
+    mv_cust_pkt_frwd_t pkt_fwd[MV_CUST_PBITS_MAP_MAX_ENTRY_NUM];
+} mv_cust_pbits_map_t;
+
+/* DSCP to P-bits mapping table definition */
+#define MV_CUST_DSCP_PBITS_TABLE_MAX_SIZE  (64)
+typedef struct {
+    uint32_t in_use;
+    uint8_t  pbits[MV_CUST_DSCP_PBITS_TABLE_MAX_SIZE];
+} mv_cust_dscp_pbits_t;
+ 
+typedef enum
+{
+    MV_CUST_FLOW_DIR_US   = 0,
+    MV_CUST_FLOW_DIR_DS   = 1,
+    MV_CUST_FLOW_DIR_NUM  = 2
+} mv_cust_flow_dir_e;
+
+typedef struct
+{
+    mv_cust_flow_dir_e dir;
+    int                vid;
+    int                pbits;
+    int                dscp;  
+    int                mod_vid;
+    int                mod_pbits;
+    mv_cust_pkt_frwd_t pkt_frwd;
+} mv_cust_ioctl_flow_map_t;
+
+/****************************************************************************** 
+ *                        Function Declaration                                                                                                                                  
+ ******************************************************************************/
+/*******************************************************************************
+**
+**    mv_cust_set_trace_flag
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function sets mv_cust trace flag.
+**
+**    INPUTS:
+**      enTrace     - Enable or disable mv_cust trace.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/    
+int mv_cust_set_trace_flag(uint32_t enTrace);
+
+/*******************************************************************************
+**
+**    mv_cust_map_rule_set
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function sets GPON flow mapping rules
+**
+**    INPUTS:
+**      cust_flow  - VLAN ID, 802.1p value, pkt_fwd information.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_map_rule_set(mv_cust_ioctl_flow_map_t *cust_flow);
+
+/*******************************************************************************
+**
+**    mv_cust_dscp_map_set
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function sets GPON DSCP to P-bits mapping rules
+**
+**  INPUTS:
+**    dscp_map   - DSCP to P-bits mapping rules.
+**
+**  OUTPUTS:
+**    None. 
+**
+**    RETURNS:     
+**    On success, the function returns (0). On error different types are 
+**  returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_dscp_map_set(mv_cust_dscp_pbits_t *dscp_map);
+
+/*******************************************************************************
+**
+**    mv_cust_map_rule_del
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function deletes GPON flow mapping rules
+**
+**    INPUTS:
+**      vid         - VLAN ID.
+**      pbits      - 802.1p value.
+**
+**    OUTPUTS:
+**      None 
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_map_rule_del(uint16_t vid, uint8_t pbits, mv_cust_flow_dir_e dir);
+
+/*******************************************************************************
+**
+**    mv_cust_dscp_map_del
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function deletes DSCP to P-bits mapping rules
+**
+**  INPUTS:
+**    None.
+**
+**  OUTPUTS:
+**    None. 
+**
+**    RETURNS:     
+**    On success, the function returns (0). On error different types are 
+**  returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_dscp_map_del(void);
+
+/*******************************************************************************
+**
+**    mv_cust_map_rule_clear
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function clears all GPON flow mapping rules
+**
+**  INPUTS:
+**    None.
+**
+**  OUTPUTS:
+**    None. 
+**
+**    RETURNS:     
+**    On success, the function returns (0). On error different types are 
+**  returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_map_rule_clear(void);
+
+/*******************************************************************************
+**
+**    mv_cust_tag_map_rule_get
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function gets GPON flow mapping rule for tagged frames.
+**
+**  INPUTS:
+**    cust_flow  - parsing vid, pbits, dir
+**
+**  OUTPUTS:
+**    cust_flow  - out packet forwarding information, including GEM port, T-CONT, queue.
+**                 and packet modification for VID, P-bits
+**
+**    RETURNS:     
+**    On success, the function returns (0). On error different types are 
+**  returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_tag_map_rule_get(mv_cust_ioctl_flow_map_t *cust_flow);
+
+/*******************************************************************************
+**
+**    mv_cust_untag_map_rule_get
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function gets GPON flow mapping rule for untagged frames.
+**
+**    INPUTS:
+**      dscp         - DSCP value.
+**
+**    OUTPUTS:
+**      cust_flow    - packet forwarding information, including GEM port, T-CONT, queue.
+**
+**    RETURNS:     
+**      On success, the function returns (MV_CUST_OK). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_untag_map_rule_get(mv_cust_ioctl_flow_map_t *cust_flow);
+
+/*******************************************************************************
+**
+**    mv_cust_map_table_print
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function displays valid GPON flow mapping tables and DSCP 
+**               to P-bits mapping tablefor untagged frames.
+**
+**  INPUTS:
+**    None.
+**
+**  OUTPUTS:
+**    None.
+**
+**    RETURNS:     
+**    On success, the function returns (0). On error different types are 
+**  returned according to the case.  
+**
+*******************************************************************************/
+int mv_cust_map_table_print(void);
+
+/*******************************************************************************
+**
+**    mv_cust_flow_map_init
+**    ___________________________________________________________________________
+**
+**    DESCRIPTION: The function initializes mv_cust flow mapping data structure.
+**
+**    INPUTS:
+**      None.
+**
+**    OUTPUTS:
+**      None. 
+**
+**    RETURNS:     
+**      On success, the function returns (0). On error different types are 
+**    returned according to the case.  
+**
+*******************************************************************************/    
+int mv_cust_flow_map_init(void);
+
+
+#endif /* __mv_cust_flow_map_h__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mng_if.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mng_if.h
new file mode 100755
index 0000000..9556bfe
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mng_if.h
@@ -0,0 +1,127 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+* 
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+* 
+*********************************************************************************
+* Marvell GPL License Option
+* 
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+* 
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_mng_if.h                                           
+*                                                                           
+* DESCRIPTION : This file contains ONU MV CUST Management Interface        
+********************************************************************************/
+#ifndef _MV_CUST_MNG_IF_H_
+#define _MV_CUST_MNG_IF_H_
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include <linux/cdev.h>
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define MV_CUST_IOCTL_OMCI_SET                _IOW(MV_CUST_IOCTL_MAGIC,  1,  unsigned int)
+#define MV_CUST_IOCTL_EOAM_LLID_SET           _IOW(MV_CUST_IOCTL_MAGIC,  2,  unsigned int)
+#define MV_CUST_IOCTL_EOAM_ENABLE             _IOW(MV_CUST_IOCTL_MAGIC,  3,  unsigned int)
+#define MV_CUST_IOCTL_OMCI_ENABLE             _IOW(MV_CUST_IOCTL_MAGIC,  4,  unsigned int)
+#define MV_CUST_IOCTL_MAP_RULE_SET            _IOW(MV_CUST_IOCTL_MAGIC,  5,  unsigned int)
+#define MV_CUST_IOCTL_DSCP_MAP_SET            _IOW(MV_CUST_IOCTL_MAGIC,  6,  unsigned int)
+#define MV_CUST_IOCTL_MAP_RULE_DEL            _IOW(MV_CUST_IOCTL_MAGIC,  7,  unsigned int)
+#define MV_CUST_IOCTL_DSCP_MAP_DEL            _IOW(MV_CUST_IOCTL_MAGIC,  8,  unsigned int)
+#define MV_CUST_IOCTL_MAP_RULE_CLEAR          _IOW(MV_CUST_IOCTL_MAGIC,  9,  unsigned int)
+#define MV_CUST_IOCTL_TAG_MAP_RULE_GET        _IOR(MV_CUST_IOCTL_MAGIC,  10, unsigned int)
+#define MV_CUST_IOCTL_UNTAG_MAP_RULE_GET      _IOR(MV_CUST_IOCTL_MAGIC,  11, unsigned int)
+
+
+
+
+
+/* Enums
+------------------------------------------------------------------------------*/
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+typedef struct
+{
+    int                tcont;
+    int                txq;
+    int                gemport;
+    int                keep_rx_mh;
+} mv_cust_ioctl_omci_set_t;
+
+typedef struct
+{
+    int                llid;
+    int                txq;
+    uint8_t            llid_mac[6];
+} mv_cust_ioctl_llid_set_t;
+
+typedef struct
+{
+    mv_cust_dscp_pbits_t dscp_map;
+} mv_cust_ioctl_dscp_map_t;
+
+/* MV_CUST Char Device Structure */
+/* ========================= */
+typedef struct
+{
+  mv_cust_ioctl_omci_set_t      mv_cust_ioctl_omci_set;
+  mv_cust_ioctl_llid_set_t      mv_cust_ioctl_llid_set;
+  mv_cust_ioctl_flow_map_t      mv_cust_ioctl_flow_map;
+  mv_cust_ioctl_dscp_map_t      mv_cust_ioctl_dscp_map;
+
+  struct cdev  cdev;
+} mv_cust_cdev_t;
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _MV_CUST_MNG_IF_H_ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mod.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mod.c
new file mode 100755
index 0000000..4ce9218
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_mod.c
@@ -0,0 +1,63 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+* 
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+* 
+*********************************************************************************
+* Marvell GPL License Option
+* 
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+* 
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_mod.c
+*
+* DESCRIPTION:
+*       
+* 
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include "mv_cust_dev.h"
+
+
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+static void __exit mv_cust_mod_exit(void)
+{
+    mvcust_dev_shutdown();
+}
+module_exit(mv_cust_mod_exit);
+
+
+static int __init mv_cust_mod_init(void)
+{
+    if (mvcust_dev_init() != 0)
+    {
+        //mv_cust_mod_exit();
+        printk(KERN_ERR "\nMV_CUST module initialization failed \n\n");
+        return -1;
+    }
+
+    printk(KERN_INFO "\nMV_CUST module inserted - %s\n\n",MV_CUST_VERSION);
+
+    return 0;
+}
+
+//module_init(mv_cust_mod_init);
+device_initcall_sync(mv_cust_mod_init);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.c
new file mode 100755
index 0000000..7c9055b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.c
@@ -0,0 +1,1252 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_netdev.c
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#include <mvCommon.h>
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+
+#include <mvOs.h>
+#include <ctrlEnv/mvCtrlEnvLib.h>
+
+#include "mv_cust_dev.h"
+#include "mv_cust_netdev.h"
+#include "mv_cust_flow_map.h"
+#include "mv_cust_mng_if.h"
+
+/* YUVAL - update to pnc define */
+#define     MH_GEM_PORT_MASK                (0x0FFF)
+#define     MH_EPON_OAM_TYPE                (0x8809)
+#define     ETY_IPV4                        (0x0800)
+#define     IPV4_PROTO_OFFSET               (9)
+
+#define     CUST_TBL_NUM_ENTRIES(a)         (sizeof(a)/sizeof(a[0]))
+
+/*Static Declarations */
+static int    mv_eth_ports_num = 0;
+static int    mv_cust_omci_gemport = 0;
+
+static int    mv_cust_omci_valid = 0;
+static int    mv_cust_eoam_valid = 0;
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+static int    mv_cust_igmp_detect = 1;
+static uint16_t mv_cust_igmp_type;
+static struct mv_eth_tx_spec     igmp_tx_spec = {0, MV_ETH_F_MH, 0, 0};
+#endif
+static int    mv_cust_port_loopback_detect = 1;
+static int    mv_cust_debug_code = 0;
+static int    mv_cust_xpon_oam_rx_gh = 0;
+
+static uint16_t mv_cust_xpon_oam_type;
+static uint16_t mv_cust_loopdet_type;
+
+/* Protocol definitions */
+static struct mv_eth_tx_spec     omci_mgmt_tx_spec = {0};
+static struct mv_eoam_llid_spec  epon_mgmt_tx_spec[MV_CUST_NUM_LLID];
+
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+static struct mv_port_tx_spec    port_spec_cfg[CONFIG_MV_ETH_PORTS_NUM];
+#endif
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+static int    mv_cust_flow_map = 0;
+static int    mv_cust_flow_map_parse(uint8_t *data, uint16_t *vlan, uint8_t *pbits, uint8_t dir);
+static int    mv_cust_flow_map_mod(uint8_t *data, uint16_t vid, uint8_t pbits, uint8_t dir);
+#endif
+
+
+#define     PORT_ENTRIES                    CUST_TBL_NUM_ENTRIES(port_spec_cfg)
+#define     EPON_MGMT_ENTRIES               CUST_TBL_NUM_ENTRIES(epon_mgmt_tx_spec)
+
+
+void mv_cust_omci_print(void)
+{
+    printk("************* OMCI Configuration *****************\n\n");
+    printk("OMCI: valid = %d, gemport = %d, ethtype = 0x%04x, gh_keep = %d\n",
+           mv_cust_omci_valid, mv_cust_omci_gemport, ntohs(mv_cust_xpon_oam_type), mv_cust_xpon_oam_rx_gh);
+    printk("OMCI: txp   = %d, txq = %d, hw_cmd = 0x%08x, flags = 0x%04x on TX \n",
+           omci_mgmt_tx_spec.txp, omci_mgmt_tx_spec.txq, omci_mgmt_tx_spec.hw_cmd, omci_mgmt_tx_spec.flags);
+    printk("\n");
+}
+
+
+void mv_cust_eoam_print(void)
+{
+    int i;
+    printk("************* eOAM Configuration *****************\n\n");
+    printk("EOAM: valid = %d, ethtype = 0x%04x, gh_keep = %d\n",
+           mv_cust_eoam_valid, ntohs(mv_cust_xpon_oam_type), mv_cust_xpon_oam_rx_gh);
+    for (i=0;i <(EPON_MGMT_ENTRIES);i++) {
+        printk("llid%d: mac=%02x:%02x:%02x:%02x:%02x:%02x, txp=%d, txq=%d, hw_cmd=0x%08x, flags = 0x%04x\n",
+               i,
+               epon_mgmt_tx_spec[i].llid_mac_address[0],epon_mgmt_tx_spec[i].llid_mac_address[1],
+               epon_mgmt_tx_spec[i].llid_mac_address[2],epon_mgmt_tx_spec[i].llid_mac_address[3],
+               epon_mgmt_tx_spec[i].llid_mac_address[4],epon_mgmt_tx_spec[i].llid_mac_address[5],
+               epon_mgmt_tx_spec[i].tx_spec.txp, epon_mgmt_tx_spec[i].tx_spec.txq,
+               epon_mgmt_tx_spec[i].tx_spec.hw_cmd, epon_mgmt_tx_spec[i].tx_spec.flags);
+        printk("\n");
+    }
+}
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+void mv_cust_igmp_print(void)
+{
+    printk("************* IGMP Configuration *****************\n\n");
+    printk("IGMP valid = %d,  ethtype = 0x%04x, on RX\n",
+           mv_cust_igmp_detect, ntohs(mv_cust_igmp_type));
+    printk("IGMP txp = %d, txq = %d, , hw_cmd = 0x%08x on TX\n",
+           igmp_tx_spec.txp, igmp_tx_spec.txq, igmp_tx_spec.hw_cmd);
+    printk("\n");
+}
+#endif
+
+void mv_cust_loopdet_print(void)
+{
+    printk("************* Port Loopback Configuration *****************\n\n");
+    printk("Port Loopback valid = %d,  ethtype = 0x%04x, on RX\n",
+           mv_cust_port_loopback_detect, ntohs(mv_cust_loopdet_type));
+}
+
+
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+int mv_cust_udp_spec_print(int port)
+{
+    int i;
+    struct eth_port *pp = mv_eth_port_by_id(port);
+    struct mv_udp_port_tx_spec *udp_spec;
+
+    if (!pp)
+        return -ENODEV;
+
+    udp_spec = &(port_spec_cfg[port].udp_dst[0]);
+
+    printk("\n**** port #%d - TX UDP Dest Port configuration *****\n", port);
+    printk("----------------------------------------------------\n");
+    printk("ID udp_dst   txp    txq    flags    hw_cmd     func_add\n");
+    for (i = 0; i < sizeof(port_spec_cfg[port].udp_dst)/sizeof(port_spec_cfg[port].udp_dst[0]); i++) {
+        if (udp_spec[i].tx_spec.txq != MV_ETH_TXQ_INVALID)
+            printk("%2d   %04d      %d      %d     0x%04x   0x%08x   0x%p\n",
+                   i, ntohs(udp_spec[i].udp_port),
+                   udp_spec[i].tx_spec.txp, udp_spec[i].tx_spec.txq,
+                   udp_spec[i].tx_spec.flags, udp_spec[i].tx_spec.hw_cmd,
+                   udp_spec[i].tx_spec.tx_func);
+    }
+    printk("-----------------------------------------------------\n");
+
+    udp_spec = &(port_spec_cfg[port].udp_src[0]);
+
+    printk("**** port #%d - TX UDP Source Port configuration *****\n", port);
+    printk("-----------------------------------------------------\n");
+    printk("ID udp_src   txp    txq     flags    hw_cmd     func_add\n");
+    for (i = 0; i < sizeof(port_spec_cfg[port].udp_src)/sizeof(port_spec_cfg[port].udp_src[0]); i++) {
+        if (udp_spec[i].tx_spec.txq != MV_ETH_TXQ_INVALID)
+            printk("%2d   %04d      %d      %d     0x%04x   0x%08x   0x%p\n",
+                   i, ntohs(udp_spec[i].udp_port),
+                   udp_spec[i].tx_spec.txp, udp_spec[i].tx_spec.txq,
+                   udp_spec[i].tx_spec.flags, udp_spec[i].tx_spec.hw_cmd,
+                   udp_spec[i].tx_spec.tx_func);
+    }
+    printk("**************************************************************\n");
+
+
+    return 0;
+}
+
+void mv_cust_udp_spec_print_all(void)
+{
+    int port;
+
+    for (port=0;port < CONFIG_MV_ETH_PORTS_NUM ;port++) {
+        mv_cust_udp_spec_print(port);
+    }
+}
+#endif
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+void mv_cust_flow_map_print(void)
+{
+    printk("************* Flow Mapping Configuration *****************\n\n");
+    printk("FLow mapping valid = %d\n", mv_cust_flow_map);
+}
+#endif
+
+void mv_cust_omci_hw_cmd_set(uint32_t hw_cmd)
+{
+    omci_mgmt_tx_spec.hw_cmd = hw_cmd;
+}
+EXPORT_SYMBOL(mv_cust_omci_hw_cmd_set);
+
+int mv_cust_omci_tx_set(int tcont, int txq)
+{
+    if (mvNetaTxpCheck(MV_PON_PORT_ID, tcont)) {
+        return -EINVAL;
+    }
+
+    if (txq<0 || txq>CONFIG_MV_ETH_TXQ) {
+        return -EINVAL;
+    }
+
+    omci_mgmt_tx_spec.txp = tcont;
+    omci_mgmt_tx_spec.txq = txq;
+
+    return 0;
+}
+
+
+int mv_cust_omci_set(int tcont, int txq, int gem_port, int keep_rx_mh)
+{
+    int ret, hw_cmd;
+
+    omci_mgmt_tx_spec.tx_func = NULL;
+    omci_mgmt_tx_spec.flags = MV_ETH_F_NO_PAD | MV_ETH_F_MH;
+
+    ret = mv_cust_omci_tx_set(tcont, txq);
+    if (ret) {
+        MVCUST_ERR_PRINT("mv_cust_omci_tx_set - ret(%d)  \n", ret);
+        return ret;
+    }
+
+    mv_cust_omci_gemport_set(gem_port);
+    hw_cmd = ((gem_port << 8) | 0x0010);
+    mv_cust_omci_hw_cmd_set(hw_cmd);
+    mv_cust_xpon_oam_rx_gh_set(keep_rx_mh);
+
+    mv_cust_omci_enable(1);
+
+    return 0;
+}
+EXPORT_SYMBOL(mv_cust_omci_set);
+
+
+int mv_cust_eoam_llid_set(int llid, uint8_t *llid_mac, int txq)
+{
+
+    if (mvNetaTxpCheck(MV_PON_PORT_ID, llid))
+        return -EINVAL;
+
+    if (txq<0 || txq>CONFIG_MV_ETH_TXQ) {
+            return -EINVAL;
+    }
+    if (!llid_mac) {
+        return -EINVAL;
+    }
+    memcpy((void *) &(epon_mgmt_tx_spec[llid].llid_mac_address), (void *) llid_mac, ETH_ALEN);
+
+    epon_mgmt_tx_spec[llid].tx_spec.txq = txq;
+
+    return 0;
+}
+EXPORT_SYMBOL(mv_cust_eoam_llid_set);
+
+
+MV_STATUS mv_cust_omci_enable(int enable)
+{
+    if (enable) {
+
+        if (mv_cust_eoam_valid) {
+            MVCUST_ERR_PRINT("EPON is already valid\n");
+            return MV_ERROR;
+        }
+        mv_cust_omci_valid = 1;
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+        mv_cust_flow_map   = 1;
+#endif
+    }
+    else {
+        mv_cust_omci_valid = 0;
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+        mv_cust_flow_map   = 0;
+#endif
+    }
+
+    return MV_OK;
+}
+
+
+void mv_cust_eoam_init(void)
+{
+    int i;
+
+    for (i=0;i <(EPON_MGMT_ENTRIES);i++) {
+        memset(&epon_mgmt_tx_spec[i],0, sizeof(struct mv_eoam_llid_spec));
+
+        /* Each table entry (i) a-priori corresponds to LLID (i) */
+        epon_mgmt_tx_spec[i].tx_spec.txp = i;
+
+        /* The mv_neta driver will add the default MH. The MH value has no significance in EPON Upstream */
+        epon_mgmt_tx_spec[i].tx_spec.flags = MV_ETH_F_MH;
+    }
+
+    /* In Rx, keep the MH for EOAM */
+    mv_cust_xpon_oam_rx_gh_set(1);
+    return ;
+}
+EXPORT_SYMBOL(mv_cust_eoam_init);
+
+
+MV_STATUS mv_cust_eoam_enable(int enable)
+{
+
+    if(mv_cust_debug_code)
+        printk("%s: enable = %d\n", __func__, enable);
+
+    if (enable) {
+        if (mv_cust_omci_valid) {
+            MVCUST_ERR_PRINT("OMCI is already valid\n");
+            return MV_ERROR;
+        }
+        mv_cust_eoam_valid = 1;
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+        mv_cust_flow_map   = 0;
+#endif
+    }
+    else {
+        mv_cust_eoam_valid = 0;
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+        mv_cust_flow_map   = 0;
+#endif
+    }
+
+    return MV_OK;
+}
+EXPORT_SYMBOL(mv_cust_eoam_enable);
+
+#if 0
+MV_STATUS mv_cust_eoam_tx_func_set(void (*tx_func) (uint8_t *data, int size, struct mv_eth_tx_spec *tx_spec))
+{
+
+    if (mv_cust_debug_code)
+        printk("%s: \n", __func__);
+
+    /* System cannot be OMCI_valid */
+    if (mv_cust_omci_valid) {
+        MVCUST_ERR_PRINT("EPON is valid\n");
+        return MV_ERROR;
+    }
+    /*Pointer cannot be null */
+    if (!tx_func) {
+        MVCUST_ERR_PRINT("NULL pointer\n");
+    }
+
+    xpon_mgmt_tx_spec.tx_func = tx_func;
+
+    return MV_OK;
+}
+EXPORT_SYMBOL(mv_cust_eoam_tx_func_set);
+#endif
+
+static inline void mv_cust_copy_tx_spec(struct mv_eth_tx_spec * tx_spec,
+                                        uint8_t txp, uint8_t txq,
+                                        uint16_t flags, uint32_t hw_cmd)
+{
+    tx_spec->txp = txp;
+    tx_spec->txq = txq;
+    tx_spec->hw_cmd = hw_cmd;
+    tx_spec->flags = flags;
+}
+
+
+
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+MV_STATUS  mv_cust_udp_int_spec_set(struct mv_udp_port_tx_spec *udp_spec, uint16_t udp_port, int table_size,
+                                    uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd)
+{
+    int i;
+
+    /* Check if already exists */
+    for (i=0; i < table_size;i++) {
+        if (udp_spec[i].udp_port == htons(udp_port) &&
+            udp_spec[i].tx_spec.txq != MV_ETH_TXQ_INVALID) {
+            mv_cust_copy_tx_spec(&(udp_spec[i].tx_spec), txp, txq, flags, hw_cmd);
+            return MV_OK;
+        }
+    }
+    /* Check empty */
+    for (i=0; i < table_size;i++) {
+        if (udp_spec[i].tx_spec.txq == MV_ETH_TXQ_INVALID) {
+            udp_spec[i].udp_port = htons(udp_port);
+            mv_cust_copy_tx_spec(&(udp_spec[i].tx_spec), txp, txq, flags, hw_cmd);
+            return MV_OK;
+        }
+    }
+
+    return(MV_FULL);
+}
+
+
+MV_STATUS  mv_cust_udp_src_spec_set(int tx_port, uint16_t udp_src_port, uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd)
+{
+    struct eth_port *pp = mv_eth_port_by_id(tx_port);
+    struct mv_udp_port_tx_spec *udp_src_spec = port_spec_cfg[tx_port].udp_src;
+    MV_STATUS mv_status;
+
+    if (!pp)
+        return -ENODEV;
+
+    mv_status = mv_cust_udp_int_spec_set(udp_src_spec, udp_src_port,
+                                         sizeof(port_spec_cfg[tx_port].udp_src)/sizeof(port_spec_cfg[tx_port].udp_src[0]),
+                                         txp, txq, flags, hw_cmd);
+
+    if (mv_status != MV_OK)
+        printk("%s: UDP Special Source Port Table is full\n", __func__);
+
+    return(mv_status);
+}
+EXPORT_SYMBOL(mv_cust_udp_src_spec_set);
+
+
+MV_STATUS  mv_cust_udp_dest_spec_set(int tx_port, uint16_t udp_dest_port, uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd)
+{
+    struct eth_port *pp = mv_eth_port_by_id(tx_port);
+    struct mv_udp_port_tx_spec *udp_dst_spec = port_spec_cfg[tx_port].udp_dst;
+    MV_STATUS mv_status;
+
+    if (!pp)
+        return -ENODEV;
+
+    mv_status = mv_cust_udp_int_spec_set(udp_dst_spec, udp_dest_port,
+                                         sizeof(port_spec_cfg[tx_port].udp_dst)/sizeof(port_spec_cfg[tx_port].udp_dst[0]),
+                                         txp, txq, flags, hw_cmd);
+
+    if (mv_status != MV_OK)
+        printk("%s: UDP Special Dest. Port Table is full\n", __func__);
+
+    return(mv_status);
+}
+EXPORT_SYMBOL(mv_cust_udp_dest_spec_set);
+
+
+void  mv_cust_udp_table_del(void)
+{
+    int num_ports = PORT_ENTRIES;
+    int tx_port, i;
+
+    if (num_ports > mv_eth_ports_num)
+        num_ports = mv_eth_ports_num;
+
+
+    for (tx_port=0; tx_port<num_ports;tx_port++) {
+
+        /* Invalidate UDP Dest ports, set txq=invalid  */
+        for (i=0;i<(sizeof(port_spec_cfg[tx_port].udp_dst)/sizeof(port_spec_cfg[tx_port].udp_dst[0]));i++) {
+            memset(&(port_spec_cfg[tx_port].udp_dst[i]), 0, sizeof(struct mv_udp_port_tx_spec));
+            port_spec_cfg[tx_port].udp_dst[i].tx_spec.txq = MV_ETH_TXQ_INVALID;
+        }
+
+        /* Invalidate UDP Source ports, , set txq=invalid */
+        for (i=0;i<(sizeof(port_spec_cfg[tx_port].udp_src)/sizeof(port_spec_cfg[tx_port].udp_src[0]));i++) {
+            memset(&(port_spec_cfg[tx_port].udp_src[i]), 0, sizeof(struct mv_udp_port_tx_spec));
+            port_spec_cfg[tx_port].udp_src[i].tx_spec.txq = MV_ETH_TXQ_INVALID;
+        }
+
+    }
+    return;
+}
+#endif
+
+int mv_cust_omci_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                   struct mv_eth_tx_spec *tx_spec_out)
+{
+    if ( (skb->protocol == mv_cust_xpon_oam_type)
+        && mv_cust_omci_valid
+        && port == MV_PON_PORT_ID) {
+        memcpy (tx_spec_out, &omci_mgmt_tx_spec, sizeof(struct mv_eth_tx_spec));
+        if(mv_cust_debug_code)
+            printk("%s", __func__);
+        return 1;
+    }
+    return 0;
+}
+
+
+int mv_cust_eoam_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                    struct mv_eth_tx_spec *tx_spec_out)
+{
+    int mac_match, i;
+
+    if (skb->protocol == mv_cust_xpon_oam_type
+        && mv_cust_eoam_valid
+        && port == MV_PON_PORT_ID) {
+        /* Lookup MAC Address */
+        for (i=0; i<(EPON_MGMT_ENTRIES);i++) {
+            mac_match = memcmp((void *) &(epon_mgmt_tx_spec[i].llid_mac_address[0]),
+                               (void *)(skb->data + /*MV_ETH_MH_SIZE +*/ ETH_ALEN),
+                               ETH_ALEN);
+            if (!mac_match) {
+                memcpy (tx_spec_out, &epon_mgmt_tx_spec[i].tx_spec, sizeof(struct mv_eth_tx_spec));
+                if(mv_cust_debug_code)
+                    printk("%s, llid = %d", __func__, i);
+                return 1;
+            }
+        }
+        /* Source MAC Address not found */
+        if(mv_cust_debug_code) {
+            printk("(%s)Input Packet first bytes:\n", __func__);
+            for (i=0;i<24;i++) {
+                if (i%8== 0)
+                    printk("\n");
+                printk ("%02x ", *(skb->data + i));
+            }
+        }
+    }
+    return 0;
+}
+
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+int mv_cust_igmp_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                    struct mv_eth_tx_spec *tx_spec_out)
+{
+    if (mv_cust_igmp_detect) {
+        /* Check Tx XPON Type */
+        if (skb->protocol == mv_cust_igmp_type) {
+            memcpy (tx_spec_out, &igmp_tx_spec, sizeof(struct mv_eth_tx_spec));
+
+            /* MH should not be set */
+            tx_spec_out->flags = 0;
+            if (2 == port)
+            {
+                tx_spec_out->txp = skb->data[0];
+                tx_spec_out->hw_cmd = ((skb->data[2] << 8) | skb->data[3]) << 8;
+                skb->data[2] |= 0x80;
+            }
+            tx_spec_out->txq = skb->data[1];
+
+            skb_pull(skb, 2);
+
+            return 1;
+        }
+    }
+    return 0;
+}
+#endif
+
+
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+int mv_cust_udp_port_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                        struct mv_eth_tx_spec *tx_spec_out)
+{
+    struct iphdr  * iphdrp   = NULL;
+    struct udphdr * udphdrp  = NULL;
+    int i;
+
+    if (port > CONFIG_MV_ETH_PORTS_NUM) {
+        printk("Port Error\n");
+        return(0);
+    }
+
+    if (skb->protocol == ETY_IPV4) {
+        /* Get UDP Port */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+	iphdrp = skb->nh.iph;
+#else
+	iphdrp = ip_hdr(skb);
+#endif
+
+        if ((iphdrp) && (iphdrp->protocol == IPPROTO_UDP)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+	    udphdrp = skb->h.uh;
+#else
+        udphdrp = udp_hdr(skb);
+#endif
+            if (udphdrp) {
+                if (udphdrp == (struct udphdr *)iphdrp) {
+                    udphdrp = (struct udphdr *)((char *)udphdrp + (4*(iphdrp->ihl)));
+                }
+                /* Find configured UDP Source Port*/
+                for (i=0; i < sizeof(port_spec_cfg[port].udp_src)/sizeof(port_spec_cfg[port].udp_src[0]);i++) {
+                    if ((udphdrp->source == port_spec_cfg[port].udp_src[i].udp_port) &&
+                        (port_spec_cfg[port].udp_src[i].tx_spec.txq != MV_ETH_TXQ_INVALID)) {
+                        memcpy (tx_spec_out, &(port_spec_cfg[port].udp_src[i].tx_spec), sizeof(struct mv_eth_tx_spec));
+                        if (mv_cust_debug_code)
+                            printk("%s: found udp_src 0x(%04x)\n", __func__, ntohs(udphdrp->source));
+                        return 1;
+                    }
+                }
+                /* Find configured UDP Dest. Port*/
+                for (i=0; i < sizeof(port_spec_cfg[port].udp_dst)/sizeof(port_spec_cfg[port].udp_dst[0]);i++) {
+                    if ((udphdrp->dest == port_spec_cfg[port].udp_dst[i].udp_port) &&
+                        (port_spec_cfg[port].udp_src[i].tx_spec.txq != MV_ETH_TXQ_INVALID)) {
+                        memcpy (tx_spec_out, &(port_spec_cfg[port].udp_dst[i].tx_spec), sizeof(struct mv_eth_tx_spec));
+                        if (mv_cust_debug_code)
+                            printk("%s: found udp_dst 0x(%04x)\n", __func__, ntohs(udphdrp->dest));
+                        return 1;
+                    }
+                }
+
+        if ( (port == MV_PON_PORT_ID) && mv_cust_debug_code) {
+            printk("%s:DEBUG : Packet UDP, udp source or dest port not found udp_src(%x)x udp_dst(%x)x\n",
+                   __func__,ntohs(udphdrp->source), ntohs(udphdrp->dest));
+        }
+
+            }
+        }
+        else if ( (port == MV_PON_PORT_ID) && mv_cust_debug_code )
+            printk("%s:DEBUG : NOT UDP, ip_proto(%d) \n", __func__, iphdrp->protocol);
+    }
+    else if ( (port == MV_PON_PORT_ID) && mv_cust_debug_code )
+        printk("%s:DEBUG : NOT IP, proto(%d) \n", __func__, skb->protocol);
+
+    return 0;
+
+}
+#endif
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+int mv_cust_flow_map_tx(int port, struct net_device *dev, struct sk_buff *skb,
+                        struct mv_eth_tx_spec *tx_spec_out)
+{
+    struct iphdr *iphdrp = NULL;
+    uint16_t vlan        = 0;
+    uint8_t  pbits       = 0;
+    int      btag        = 0;
+    int      ret         = 0;
+    mv_cust_ioctl_flow_map_t cust_flow;
+
+    if (MV_PON_PORT_ID != port)
+        return 0;
+
+    if (mv_cust_flow_map) {
+
+        cust_flow.dir  = MV_CUST_FLOW_DIR_US;
+
+        /* Parse packets to check whether it is tagged or untagged, and get vlan and pbits in tagged mode */
+        btag = mv_cust_flow_map_parse(skb->data, &vlan, &pbits, MV_CUST_FLOW_DIR_US);
+
+        //printk(KERN_ERR " %s TX packet 1 btag[%d] vlan[%d]  pbits[%d]\n", __func__, btag, vlan, pbits);
+
+        /* The frame is tagged */
+        if (btag == 1) {
+            cust_flow.vid    = vlan;
+            cust_flow.pbits  = pbits;
+
+            ret = mv_cust_tag_map_rule_get(&cust_flow);
+            //printk(KERN_ERR " %s TX packet 2 trg_port[%d] trg_queue[%d]  gem_port[%d]\n", __func__, pkt_fwd.trg_port, pkt_fwd.trg_queue, pkt_fwd.gem_port);
+
+            /* Set GEM port, target port and queue */
+            if (ret == MV_CUST_OK) {
+                    tx_spec_out->txp     = (u8)cust_flow.pkt_frwd.trg_port;
+                    tx_spec_out->txq     = (u8)cust_flow.pkt_frwd.trg_queue;
+                    tx_spec_out->hw_cmd  = ((cust_flow.pkt_frwd.gem_port << 8)|0x0010);
+                    tx_spec_out->tx_func = NULL;
+                    tx_spec_out->flags   = MV_ETH_F_MH;
+
+                    /* modify VID and P-bits if needed */
+                    ret = mv_cust_flow_map_mod(skb->data, cust_flow.mod_vid, cust_flow.mod_pbits, MV_CUST_FLOW_DIR_US);
+                    return 1;
+            }
+            else /* Look for rules that does not care VLAN */
+            {
+                cust_flow.vid   = MV_CUST_DEFAULT_SINGLE_TAG_RULE;
+                ret = mv_cust_tag_map_rule_get(&cust_flow);
+
+                /* Set GEM port, target port and queue */
+                if (ret == MV_CUST_OK) {
+                        tx_spec_out->txp     = (u8)cust_flow.pkt_frwd.trg_port;
+                        tx_spec_out->txq     = (u8)cust_flow.pkt_frwd.trg_queue;
+                        tx_spec_out->hw_cmd  = ((cust_flow.pkt_frwd.gem_port << 8)|0x0010);
+                        tx_spec_out->tx_func = NULL;
+                        tx_spec_out->flags   = MV_ETH_F_MH;
+
+                        /* modify VID and P-bits if needed */
+                        ret = mv_cust_flow_map_mod(skb->data, cust_flow.mod_vid, cust_flow.mod_pbits, MV_CUST_FLOW_DIR_US);
+                        return 1;
+                }
+            }
+        }
+        /* The frame is untagged, try to get DSCP value */
+        else {
+            if (skb->protocol == ETY_IPV4) {
+                /* Get UDP Port */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+                iphdrp = skb->nh.iph;
+#else
+                iphdrp = ip_hdr(skb);
+#endif
+                cust_flow.dscp  = (iphdrp->tos >> 2) & 0x3f;
+                cust_flow.dir   = MV_CUST_FLOW_DIR_US;
+
+                ret = mv_cust_untag_map_rule_get(&cust_flow);
+                /* Set GEM port, target port and queue */
+                if (ret == MV_CUST_OK) {
+                        tx_spec_out->txp     = cust_flow.pkt_frwd.trg_port;
+                        tx_spec_out->txq     = cust_flow.pkt_frwd.trg_queue;
+                        tx_spec_out->hw_cmd  = ((cust_flow.pkt_frwd.gem_port << 8)|0x0010);
+                        tx_spec_out->tx_func = NULL;
+                        tx_spec_out->flags   = MV_ETH_F_MH;;
+
+                        return 1;
+                }
+            }
+            else
+            {
+                cust_flow.dscp  = 0;
+                cust_flow.dir   = MV_CUST_FLOW_DIR_US;
+
+                ret = mv_cust_untag_map_rule_get(&cust_flow);
+                /* Set GEM port, target port and queue */
+                if (ret == MV_CUST_OK) {
+                        tx_spec_out->txp     = cust_flow.pkt_frwd.trg_port;
+                        tx_spec_out->txq     = cust_flow.pkt_frwd.trg_queue;
+                        tx_spec_out->hw_cmd  = ((cust_flow.pkt_frwd.gem_port << 8)|0x0010);
+                        tx_spec_out->tx_func = NULL;
+                        tx_spec_out->flags   = MV_ETH_F_MH;;
+
+                        return 1;
+                }
+            }
+        }
+    }
+    return 0;
+}
+#endif
+
+void mv_cust_debug_info_set(int val)
+{
+    mv_cust_debug_code = val;
+    return;
+}
+
+void mv_cust_omci_type_set(uint16_t type)
+{
+    mv_cust_xpon_oam_type = htons(type);
+    return;
+}
+EXPORT_SYMBOL(mv_cust_omci_type_set);
+
+void mv_cust_epon_oam_type_set(uint16_t type)
+{
+    mv_cust_xpon_oam_type = htons(type);
+    return;
+}
+EXPORT_SYMBOL(mv_cust_epon_oam_type_set);
+
+
+void mv_cust_xpon_oam_rx_gh_set(int val)
+{
+    mv_cust_xpon_oam_rx_gh = val;
+    return;
+}
+EXPORT_SYMBOL(mv_cust_xpon_oam_rx_gh_set);
+
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+void mv_cust_igmp_type_set(uint16_t type)
+{
+    mv_cust_igmp_type = htons(type);
+    return;
+}
+EXPORT_SYMBOL(mv_cust_igmp_type_set);
+#endif
+
+void mv_cust_loopdet_type_set(uint16_t type)
+{
+    mv_cust_loopdet_type = htons(type);
+    return;
+}
+EXPORT_SYMBOL(mv_cust_loopdet_type_set);
+
+
+void mv_cust_omci_gemport_set(int gemport)
+{
+    mv_cust_omci_gemport = gemport;
+    return;
+}
+EXPORT_SYMBOL(mv_cust_omci_gemport_set);
+
+
+static int mv_cust_omci_gem_parse(uint8_t *data)
+{
+    uint16_t gh;
+
+    gh = ntohs(*(uint16_t *)data);
+
+    if(mv_cust_debug_code)
+        printk("%s:gh= 0x(%04x) - mv_cust_omci_gemport= 0x(%04x)  \n", __func__, gh, mv_cust_omci_gemport);
+
+    /* Compare GH for omci_gemport */
+    if ( (gh & MH_GEM_PORT_MASK) != mv_cust_omci_gemport ) {
+        if(mv_cust_debug_code)
+            printk("%s: compare GH for OMCI_gemport failed: gh= 0x(%04x) - mv_cust_omci_gemport= 0x(%04x)  \n", __func__, gh, mv_cust_omci_gemport);
+        return(0);
+    }
+
+    return(1);
+}
+
+static int mv_cust_eoam_type_parse(uint8_t *data)
+{
+    uint16_t ety;
+
+    ety = ntohs(*(uint16_t *)(data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN));
+
+    if(mv_cust_debug_code)
+        printk("%s: ety 0x(%04x)\n", __func__, ety);
+
+    /* Compare EPON OAM ether_type */
+    if (ety == MH_EPON_OAM_TYPE)
+        return(1);
+
+    return(0);
+}
+
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+static int mv_cust_igmp_parse(uint8_t *data)
+{
+    uint16_t ety;
+    uint8_t  proto;
+    uint8_t *fieldp = data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN;
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    while (ety == 0x8100 || ety == 0x88A8) {
+        fieldp+= VLAN_HLEN;
+        ety = ntohs(*(uint16_t *)fieldp);
+    }
+
+    if(mv_cust_debug_code)
+        printk("%s:ety 0x(%04x)\n", __func__, ety);
+
+    if (ety == ETY_IPV4) {
+	    fieldp+= 2;
+        fieldp+= IPV4_PROTO_OFFSET;
+        proto = *fieldp;
+        if (mv_cust_debug_code)
+            printk("%s:proto 0x(%02x)\n", __func__, proto);
+
+        if (proto == IPPROTO_IGMP)
+            return(1);
+    }
+
+    return(0);
+}
+#endif
+
+static int mv_cust_loopdet_parse(uint8_t *data)
+{
+    uint16_t ety;
+    uint8_t *fieldp = data + MV_ETH_MH_SIZE + ETH_ALEN + ETH_ALEN;
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    while (ety == 0x8100 || ety == 0x88A8) {
+        fieldp+= VLAN_HLEN;
+        ety = ntohs(*(uint16_t *)fieldp);
+    }
+    if(mv_cust_debug_code)
+        printk("%s: ety 0x(%04x)\n", __func__, ety);
+
+    /* Compare EPON OAM ether_type */
+    if (ety == mv_cust_loopdet_type)
+        return(1);
+
+    return(0);
+}
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+static int mv_cust_flow_map_parse(uint8_t *data, uint16_t *vlan, uint8_t *pbits, uint8_t dir)
+{
+    uint16_t ety;
+    uint8_t *fieldp;
+
+    if (MV_CUST_FLOW_DIR_US == dir)
+        fieldp = data + ETH_ALEN + ETH_ALEN;
+    else if (MV_CUST_FLOW_DIR_DS == dir)
+        fieldp = data + ETH_ALEN + ETH_ALEN + MV_ETH_MH_SIZE;
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    if (ety == 0x8100 || ety == 0x88A8 || ety == 0x9100) {
+        fieldp += 2;
+        *vlan  = ntohs(*(uint16_t *)fieldp);
+        *pbits = (*vlan >> 13 ) & 0x7;
+        *vlan  = (*vlan) & 0xfff;
+        return(1);
+    }
+    else {
+        return(0);
+    }
+
+    return(0);
+}
+
+static int mv_cust_flow_map_mod(uint8_t *data, uint16_t vid, uint8_t pbits, uint8_t dir)
+{
+    uint16_t ety  = 0;
+    uint16_t vlan = 0;
+    uint8_t *fieldp;
+
+    if (MV_CUST_FLOW_DIR_US == dir)
+        fieldp = data + ETH_ALEN + ETH_ALEN;
+    else if (MV_CUST_FLOW_DIR_DS == dir)
+        fieldp = data + ETH_ALEN + ETH_ALEN + MV_ETH_MH_SIZE;
+
+    /* If not need to modify VID or P-bits */
+    if((vid == MV_CUST_VID_NOT_CARE_VALUE) &&
+       (pbits == MV_CUST_PBITS_NOT_CARE_VALUE))
+        return (1);
+
+    /* Loop through VLAN tags */
+    ety = ntohs(*(uint16_t *)fieldp);
+    if (ety == 0x8100 || ety == 0x88A8 || ety == 0x9100) {
+        fieldp += 2;
+
+        vlan = ntohs(*(uint16_t *)fieldp);
+
+        if (vid < MV_CUST_VID_NOT_CARE_VALUE)
+            vlan = (vlan & 0xf000) | (vid & 0xfff);
+        if (pbits < MV_CUST_PBITS_NOT_CARE_VALUE)
+            vlan = (vlan & 0x0fff) | ((pbits & 0x7) << 13);
+
+        *(uint16_t *)fieldp = htons(vlan);
+        return(1);
+    }
+    else {
+        return(0);
+    }
+
+    return(0);
+}
+
+#endif
+
+void mv_cust_rec_skb(int port, struct sk_buff *skb)
+{
+    uint32_t rx_status;
+    struct eth_port *pp;
+
+    rx_status = netif_receive_skb(skb);
+    pp = mv_eth_port_by_id(port);
+    STAT_DBG(if (rx_status) (pp->stats.rx_drop_sw++));
+}
+
+
+static int mv_cust_omci_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_omci_gem_parse(skb->data))
+        return 0;
+    if (mv_cust_xpon_oam_rx_gh) {
+        rx_bytes = rx_desc->dataSize;
+    }
+    else {
+        skb->data += MV_ETH_MH_SIZE;
+        rx_bytes = rx_desc->dataSize - MV_ETH_MH_SIZE;
+    }
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = mv_cust_xpon_oam_type;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+    mv_cust_rec_skb(port, skb);
+
+    return 1;
+}
+
+static int mv_cust_epon_oam_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_eoam_type_parse(skb->data))
+        return 0;
+
+    if (mv_cust_xpon_oam_rx_gh) {
+        rx_bytes = rx_desc->dataSize;
+    }
+    else {
+        skb->data += MV_ETH_MH_SIZE;
+        rx_bytes = rx_desc->dataSize - MV_ETH_MH_SIZE;
+    }
+
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = mv_cust_xpon_oam_type;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+    mv_cust_rec_skb(port, skb);
+
+    return 1;
+}
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+static int mv_cust_igmp_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_igmp_parse(skb->data))
+        return 0;
+
+    /* To Indicate the source GMAC */
+    skb->data[0] = port;
+
+    rx_bytes = rx_desc->dataSize;
+
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = mv_cust_igmp_type;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+    mv_cust_rec_skb(port, skb);
+
+    return 1;
+}
+#endif
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+static int mv_cust_flow_map_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+    uint16_t vlan        = 0;
+    uint8_t  pbits       = 0;
+    int      btag        = 0;
+    int      ret         = 0;
+    mv_cust_ioctl_flow_map_t cust_flow;
+
+    if (MV_PON_PORT_ID != port)
+        return 0;
+
+    if (mv_cust_flow_map) {
+
+        /* Parse packets to check whether it is tagged or untagged, and get vlan and pbits in tagged mode */
+        btag = mv_cust_flow_map_parse(skb->data, &vlan, &pbits, MV_CUST_FLOW_DIR_DS);
+        //printk(KERN_ERR " %s TX packet 1 btag[%d] vlan[%d]  pbits[%d]\n", __func__, btag, vlan, pbits);
+
+        /* The frame is tagged */
+        if (btag == 1) {
+            cust_flow.vid    = vlan;
+            cust_flow.pbits  = pbits;
+            cust_flow.dir    = MV_CUST_FLOW_DIR_DS;
+
+            ret = mv_cust_tag_map_rule_get(&cust_flow);
+            //printk(KERN_ERR " %s TX packet 2 trg_port[%d] trg_queue[%d]  gem_port[%d]\n", __func__, pkt_fwd.trg_port, pkt_fwd.trg_queue, pkt_fwd.gem_port);
+
+            /* Modify VID and P-bits if needed */
+            if (ret == MV_CUST_OK) {
+
+                /* modify VID and P-bits if needed */
+                ret = mv_cust_flow_map_mod(skb->data, cust_flow.mod_vid, cust_flow.mod_pbits, MV_CUST_FLOW_DIR_DS);
+            }
+        }
+    }
+
+    return 1;
+}
+#endif
+
+static int mv_cust_loopdet_rx(int port, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t rx_bytes;
+
+    if (!mv_cust_loopdet_parse(skb->data))
+        return 0;
+
+    rx_bytes = rx_desc->dataSize;
+
+    skb->tail += rx_bytes;
+    skb->len = rx_bytes;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->protocol = mv_cust_loopdet_type;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    skb->dev = dev;
+#endif
+    mv_cust_rec_skb(port, skb);
+
+    return 1;
+}
+
+void mv_cust_rx_func(int port, int rxq, struct net_device *dev,
+                     struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+    uint32_t i;
+
+    if(mv_cust_debug_code)
+        printk("%s\n", __func__);
+
+    if (dev == NULL || skb == NULL || rx_desc == NULL) {
+        printk("%s: NULL Pointer dev(%p) skb(%p) rx_desc(%p)\n",
+               __func__, dev, skb, rx_desc);
+        return;
+    }
+
+    if (rx_desc->pncInfo & NETA_PNC_RX_SPECIAL)
+    {
+        if (mv_cust_omci_valid) {
+            if (mv_cust_omci_rx(port, dev, skb, rx_desc)) {
+                if(mv_cust_debug_code)
+                    printk("%s omci_packet\n", __func__);
+                return;
+            }
+        }
+        else{
+            if (mv_cust_eoam_valid) {
+                if (mv_cust_epon_oam_rx(port, dev, skb, rx_desc)) {
+                    if (mv_cust_debug_code)
+                        printk("%s eoam_packet\n", __func__);
+                    return;
+                }
+            }
+        }
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+        if (mv_cust_igmp_detect) {
+            if (mv_cust_igmp_rx(port, dev, skb, rx_desc)) {
+                if(mv_cust_debug_code)
+                    printk("%s igmp_packet\n", __func__);
+                return;
+            }
+        }
+#endif
+
+        if (mv_cust_port_loopback_detect) {
+            if (mv_cust_loopdet_rx(port, dev, skb, rx_desc)) {
+                if(mv_cust_debug_code)
+                    printk("%s loop_det_packet\n", __func__);
+                return;
+            }
+        }
+
+        MVCUST_ERR_PRINT("Special pkt arrived from port(%d), was not handled. \n", port);
+        dev_kfree_skb_any(skb);
+        if(mv_cust_debug_code) {
+            printk("Input Packet first bytes:\n");
+            for (i=0;i<24;i++) {
+                if (i%8== 0)
+                    printk("\n");
+                printk ("%02x ", *(skb->data + i));
+            }
+        }
+        
+    }
+    else
+    {
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+        if (mv_cust_flow_map) {
+            if (mv_cust_flow_map_rx(port, dev, skb, rx_desc)) {
+                if(mv_cust_debug_code)
+                    printk("%s flow map\n", __func__);
+            }
+        }
+        return;
+#endif
+    }
+
+    return;
+}
+
+int mv_cust_tx_func(int port, struct net_device *dev, struct sk_buff *skb,
+                    struct mv_eth_tx_spec *tx_spec_out)
+{
+    if (mv_cust_omci_tx(port, dev, skb, tx_spec_out))
+        return 1;
+
+    if (mv_cust_eoam_tx(port, dev, skb, tx_spec_out))
+        return 1;
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+    if (mv_cust_flow_map_tx(port, dev, skb, tx_spec_out))
+        return 1;
+#endif
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+    if (mv_cust_igmp_tx(port, dev, skb, tx_spec_out))
+        return 1;
+#endif
+
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+    /* Simple example for UDP Source Port or Dest Port Parsing */
+    /* Per UDP source or dest port configuration */
+    if (mv_cust_udp_port_tx(port, dev, skb, tx_spec_out))
+        return 1;
+#endif
+
+    return 0;
+}
+
+int mvcust_netdev_init(void)
+{
+    uint32_t port_i;
+
+    /* Retrieve num_ports, as in mv_eth_init_module*/
+    mv_eth_ports_num = mvCtrlEthMaxPortGet();
+
+    if (mv_eth_ports_num > CONFIG_MV_ETH_PORTS_NUM)
+        mv_eth_ports_num = CONFIG_MV_ETH_PORTS_NUM;
+
+    mv_cust_eoam_init();
+
+/* Initialize flow mapping data structure */
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+    mv_cust_flow_map_init();
+#endif
+
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+    mv_cust_udp_table_del();
+#endif
+
+    /* Register special receive check function */
+#ifdef CONFIG_MV_ETH_RX_SPECIAL
+    for (port_i=0;port_i< mv_eth_ports_num;port_i++) {
+        mv_eth_rx_special_proc_func(port_i, mv_cust_rx_func);
+    }
+#endif /* CONFIG_MV_ETH_RX_SPECIAL */
+
+
+    /* Register special transmit check function */
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+    for (port_i=0;port_i< mv_eth_ports_num;port_i++) {
+        mv_eth_tx_special_check_func(port_i, mv_cust_tx_func);
+    }
+#endif /* CONFIG_MV_ETH_TX_SPECIAL */
+
+    /* Set global constants */
+    mv_cust_xpon_oam_type = htons(0xBABA);
+
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+    mv_cust_igmp_type     = htons(0xA000);
+#endif
+    mv_cust_loopdet_type  = htons(0xA0A0);
+
+    return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.h
new file mode 100755
index 0000000..ac34927
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_netdev.h
@@ -0,0 +1,96 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_netdev.h
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#ifndef __mv_cust_netdev_h__
+#define __mv_cust_netdev_h__
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+
+#include <mvCommon.h>
+#include <mvOs.h>
+#include <mv_neta/net_dev/mv_netdev.h>
+
+
+#define MV_CUST_MAS_UDP_SRC_PORT          8
+#define MV_CUST_MAS_UDP_DST_PORT          8
+#define MV_CUST_NUM_LLID                  8
+
+
+struct mv_udp_port_tx_spec {
+	__be16	udp_port;
+	struct mv_eth_tx_spec tx_spec;
+};
+
+struct mv_port_tx_spec {
+	struct mv_udp_port_tx_spec udp_src[MV_CUST_MAS_UDP_SRC_PORT];
+	struct mv_udp_port_tx_spec udp_dst[MV_CUST_MAS_UDP_DST_PORT];
+};
+
+
+struct mv_eoam_llid_spec {
+	uint8_t llid_mac_address[6];
+	struct  mv_eth_tx_spec tx_spec;
+};
+
+
+
+/******************************************************
+ * Function prototypes --                             *
+*******************************************************/
+void        mv_cust_omci_hw_cmd_set(unsigned int hw_cmd);
+int         mv_cust_omci_tx_set(int tcont, int txq);
+//int         mv_cust_eoam_tx_set(int txp, int txq);
+MV_STATUS   mv_cust_omci_enable(int enable);
+MV_STATUS   mv_cust_eoam_enable(int enable);
+//MV_STATUS   mv_cust_eoam_tx_func_set(void (*tx_func) (uint8_t *data, int size, struct mv_eth_tx_spec *tx_spec));
+#ifdef  CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+MV_STATUS   mv_cust_udp_src_spec_set(int tx_port, uint16_t udp_src_port, uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd);
+MV_STATUS   mv_cust_udp_dest_spec_set(int tx_port, uint16_t udp_dest_port, uint8_t txp, uint8_t txq, uint16_t flags, uint32_t hw_cmd);
+#endif
+void        mv_cust_omci_type_set(unsigned short int type);
+void        mv_cust_xpon_oam_rx_gh_set(int val);
+void        mv_cust_epon_oam_type_set(unsigned short int type);
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+void        mv_cust_igmp_type_set(unsigned short int type);
+#endif
+void        mv_cust_omci_gemport_set(int gemport);
+void        mv_cust_loopdet_type_set(unsigned short int type);
+int         mv_cust_omci_set(int tcont, int txq, int gemport, int keep_rx_mh);
+int         mv_cust_eoam_llid_set(int llid, uint8_t *llid_mac, int txq);
+
+
+
+
+
+#endif /* __mv_cust_netdev_h__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_sysfs.c
new file mode 100755
index 0000000..395c59c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cust/mv_cust_sysfs.c
@@ -0,0 +1,574 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_cust_sysfs.c
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+
+#include <gbe/mvNeta.h>
+#include <pnc/mvPnc.h>
+
+#include "mv_cust_dev.h"
+#include "mv_cust_netdev.h"
+#include "mv_cust_flow_map.h"
+#include "mv_cust_mng_if.h"
+
+static int      eoam_txq = 0;
+static uint8_t  eoam_mac[6] = {0};
+
+
+static ssize_t mv_cust_spec_proc_help(char *buf)
+{
+    int off = 0;
+    off += sprintf(buf+off, "cat help                               - show this help\n");
+    off += sprintf(buf+off, "cat omci                               - show OMCI configuration\n");
+    off += sprintf(buf+off, "cat eoam                               - show eoam configuration\n");
+    off += sprintf(buf+off, "cat loopdet                            - show loop detect configuration\n");
+    off += sprintf(buf+off, "cat udp_ports                          - show special udp source and dest. port configuration\n");
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+    off += sprintf(buf+off, "cat flow_map                           - show flow mapping configuration\n");        
+    off += sprintf(buf+off, "cat flow_map_show                      - show flow mapping rules \n");    
+    off += sprintf(buf+off, "cat flow_map_clear                     - clear all flow mapping rules\n");
+    off += sprintf(buf+off, "cat dscp_map_del                       - delete DSCP to P-bits mapping rules\n");    
+#endif
+    off += sprintf(buf+off, "cat igmp                               - show igmp configuration\n");
+    off += sprintf(buf+off, "echo hex                > debug        - Set Customized module debug information \n");
+    off += sprintf(buf+off, "echo hex                > omci_type    - Set OMCI ethertype\n");
+    off += sprintf(buf+off, "echo tc txq gem keep_mh > omci_set     - set udp source port special Tx behavior\n");
+    off += sprintf(buf+off, "echo hex                > omci_ena     - Disable/Enable OMCI packet detection\n");
+    //off += sprintf(buf+off, "echo txp txq > omci_txq      - set T-CONT and TX queue for outgoing OMCI packet\n");
+    //off += sprintf(buf+off, "echo hex     > omci_cmd      - 4B of tx desc offset 0xc\n");
+    //off += sprintf(buf+off, "echo hex     > omci_gemp     - gemportid to detect OMCI packets\n");
+    off += sprintf(buf+off, "echo hex                > eoam_type    - Set EPON EOAM ethertype\n");
+    off += sprintf(buf+off, "echo txq                > eoam_txq     - set TX queue into sw_buffer for EOAM llid command\n");
+    off += sprintf(buf+off, "echo mac[0]-mac[5]      > eoam_mac     - set LLID mac into sw_buffer for EOAM llid command\n");
+    off += sprintf(buf+off, "echo llid               > eoam_write   - Write EOAM txq and mac address from sw_buffer into LLID\n");
+    off += sprintf(buf+off, "echo hex                > eoam_enable  - Disable/Enable eOAM packet detection\n");
+    //off += sprintf(buf+off, "echo hex                > igmp_type    - Set IGMP ethertype\n");
+    off += sprintf(buf+off, "echo hex                > loopdet_type - Set Port Loopback Detect ethertype\n");
+    off += sprintf(buf+off, "echo p udp_src(dec) txp txq flags hw_cmd  > udp_src - set udp source port special Tx behavior\n");
+    off += sprintf(buf+off, "echo p udp_dst(dec) txp txq flags hw_cmd  > udp_dst - set udp dest.  port special Tx behavior\n");
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+    off += sprintf(buf+off, "echo hex                                  > flow_map_debug  - Set flow mapping debug flag, 1:enable, 0:disable \n");    
+    off += sprintf(buf+off, "echo vid pbits mod_vid mod_pbits trg_port trg_queue trg_hwf_queue gem_port  > flow_map_us_set - set U/S flow mapping rule\n");
+    off += sprintf(buf+off, "echo vid pbits mod_vid mod_pbits          > flow_map_ds_set - set D/S flow mapping rule\n");    
+    off += sprintf(buf+off, "echo pbits0 pbits1 ... pbits62 pbits63    > dscp_map_set    - set DSCP to P-bits mapping rules\n");    
+    off += sprintf(buf+off, "echo vlan pbits dir(0:U/S, 1:D/S)         > flow_map_del    - delete flow mapping rule\n");
+    off += sprintf(buf+off, "echo vlan pbits dir(0:U/S, 1:D/S)         > tag_flow_get    - get tagged flow mapping rule\n");
+    off += sprintf(buf+off, "echo dscp dir(0:U/S, 1:D/S)               > untag_flow_get  - get untagged flow mapping rule\n");
+#endif        
+
+    return off;
+}
+
+
+static ssize_t mv_cust_spec_proc_show(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
+{
+    int off = 0;
+    const char*     name = attr->attr.name;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    if (!strcmp(name, "help") ) {
+        off = mv_cust_spec_proc_help(buf);
+    }
+    else if (!strcmp(name, "omci")) {
+        mv_cust_omci_print();
+    }
+    else if (!strcmp(name, "eoam")) {
+        mv_cust_eoam_print();
+    }
+    else if (!strcmp(name, "igmp")) {
+#ifdef CONFIG_MV_CUST_IGMP_HANDLE
+        mv_cust_igmp_print();
+#else
+        printk("mv_cust module was not compiled with IGMP Support\n");
+#endif
+
+    }
+    else if (!strcmp(name, "loopdet")) {
+        mv_cust_loopdet_print();
+    }
+    else if (!strcmp(name, "udp_ports")) {
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+        mv_cust_udp_spec_print_all();
+#else
+        printk("mv_cust module was not compiled with UDP SAMPLE Config Support\n");
+#endif
+    }
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE       
+    else if (!strcmp(name, "flow_map")) { 
+        mv_cust_flow_map_print();
+    }     
+    else if (!strcmp(name, "flow_map_show")) {
+        mv_cust_map_table_print();
+    } 
+    else if (!strcmp(name, "flow_map_clear")) {
+        mv_cust_map_rule_clear();
+    }  
+    else if (!strcmp(name, "dscp_map_del")) {
+        mv_cust_dscp_map_del();
+    }     
+#endif    
+    else
+        off = mv_cust_spec_proc_help(buf);
+
+    return off;
+}
+
+
+
+static ssize_t mv_cust_spec_proc_1_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t len)
+{
+    const char*     name = attr->attr.name;
+    unsigned int    v;
+    unsigned long   flags;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    /* Read input */
+    v = 0;
+
+    sscanf(buf, "%x", &v);
+
+    raw_local_irq_save(flags);
+
+    if (!strcmp(name, "debug")) {
+        mv_cust_debug_info_set(v);
+    }
+    else if (!strcmp(name, "omci_type")) {
+        mv_cust_omci_type_set(v);
+    }
+    else if (!strcmp(name, "eoam_type")) {
+        mv_cust_epon_oam_type_set(v);
+    }
+    else if (!strcmp(name, "eoam_txq")) {
+        eoam_txq = v;
+    }
+    else if (!strcmp(name, "eoam_write")) {
+        mv_cust_eoam_llid_set((int)v, &eoam_mac[0], eoam_txq);
+    }
+    /*
+    else if (!strcmp(name, "omci_cmd")) {
+        mv_cust_omci_hw_cmd_set(v);
+    }
+    */
+    /*
+    else if (!strcmp(name, "omci_gemp")) {
+        mv_cust_omci_gemport_set(v);
+    }
+    */
+    /*
+    else if (!strcmp(name, "omci_gh_keep")) {
+        mv_cust_xpon_oam_rx_gh_set(v);
+    }
+    */
+    else if (!strcmp(name, "eoam_gh_keep")) {
+        mv_cust_xpon_oam_rx_gh_set(v);
+    }
+    else if (!strcmp(name, "loopdet_type")) {
+        mv_cust_loopdet_type_set(v);
+    }
+    else if (!strcmp(name, "omci_enable")) {
+        mv_cust_omci_enable(v);
+    }
+    else if (!strcmp(name, "eoam_enable")) {
+        mv_cust_eoam_enable(v);
+    }
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+    raw_local_irq_restore(flags);
+
+    return len;
+}
+
+#if 0
+static ssize_t mv_cust_spec_proc_2_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t len)
+{
+    const char*     name = attr->attr.name;
+    unsigned int    p, v;
+    unsigned long   flags;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    /* Read input */
+    v = 0;
+    sscanf(buf, "%d %x", &p, &v);
+
+    raw_local_irq_save(flags);
+    /*
+    if (!strcmp(name, "omci_txq")) {
+        mv_cust_omci_tx_set(p, v);
+    }
+    */
+    /*
+    else if (!strcmp(name, "eoam_txq")) {
+        mv_cust_eoam_tx_set(p, v);
+    }
+    */
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+    raw_local_irq_restore(flags);
+
+    return len;
+}
+#endif
+
+
+static ssize_t mv_cust_spec_proc_6_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t len)
+{
+    const char*     name = attr->attr.name;
+    unsigned int    p, v1=0, v2=0, v3=0, v4=0, v5=0;
+    unsigned long   flags;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    /* Read input */
+    sscanf(buf, "%d %d %x %x %x %x", &p, &v1, &v2, &v3, &v4, &v5);
+
+    raw_local_irq_save(flags);
+
+    if (!strcmp(name, "udp_src")) {
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+        mv_cust_udp_src_spec_set(p, v1, v2, v3, v4, v5);
+#else
+        printk("mv_cust module was not compiled with UDP SAMPLE Config Support\n");
+#endif
+    }
+    else if (!strcmp(name, "udp_dst")) {
+#ifdef CONFIG_MV_CUST_UDP_SAMPLE_HANDLE
+        mv_cust_udp_dest_spec_set(p, v1, v2, v3, v4, v5);
+#else
+        printk("mv_cust module was not compiled with UDP SAMPLE Config Support\n");
+#endif
+    }
+    else if (!strcmp(name, "omci_set")) {
+        mv_cust_omci_set(p, v1, v2, v3);
+    }
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+    raw_local_irq_restore(flags);
+
+    return len;
+}
+
+static ssize_t mv_cust_spec_proc_flow_store(struct device *dev,
+                                            struct device_attribute *attr,
+                                            const char *buf, size_t len)
+{
+    const char*        name = attr->attr.name;
+    unsigned int       v1=0, v2=0, v3=0, v4=0, v5=0, v6=0, v7=0, v8=0;
+    unsigned long      flags;
+    mv_cust_ioctl_flow_map_t cust_flow;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    /* Read input */
+    sscanf(buf, "%d %d %d %d %d %d %d %d", &v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8);
+
+    raw_local_irq_save(flags);
+
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE   
+
+    if (!strcmp(name, "flow_map_debug")) {
+        mv_cust_set_trace_flag((uint32_t)v1);
+    }
+    else if (!strcmp(name, "flow_map_us_set")) {
+        memset(&cust_flow, 0, sizeof(cust_flow));
+        cust_flow.dir       = MV_CUST_FLOW_DIR_US;
+        cust_flow.vid       = v1;
+        cust_flow.pbits     = v2;
+        cust_flow.mod_vid   = v3;
+        cust_flow.mod_pbits = v4;
+        
+        cust_flow.pkt_frwd.in_use        = 1;
+        cust_flow.pkt_frwd.trg_port      = (mv_cust_trg_port_type_t)v5;
+        cust_flow.pkt_frwd.trg_queue     = (uint32_t)v6;
+        cust_flow.pkt_frwd.trg_hwf_queue = (uint32_t)v7;        
+        cust_flow.pkt_frwd.gem_port      = (mv_cust_gem_port_key_t)v8;
+        
+        mv_cust_map_rule_set(&cust_flow);
+    }
+    else if (!strcmp(name, "flow_map_ds_set")) {
+        memset(&cust_flow, 0, sizeof(cust_flow));
+        cust_flow.dir       = MV_CUST_FLOW_DIR_DS;
+        cust_flow.vid       = v1;
+        cust_flow.pbits     = v2;
+        cust_flow.mod_vid   = v3;
+        cust_flow.mod_pbits = v4;
+        cust_flow.pkt_frwd.in_use    = 1;
+        
+        mv_cust_map_rule_set(&cust_flow);
+    }    
+    else if (!strcmp(name, "flow_map_del")) {
+        mv_cust_map_rule_del((uint16_t)v1, (uint8_t)v2, (mv_cust_flow_dir_e)v3);
+    }
+    else if (!strcmp(name, "tag_flow_get")) {
+        memset(&cust_flow, 0, sizeof(cust_flow));
+        cust_flow.vid   = v1;
+        cust_flow.pbits = v2;   
+        cust_flow.dir   = (mv_cust_flow_dir_e)v3;        
+        mv_cust_tag_map_rule_get(&cust_flow);
+        printk("in_use[%d], mod_vid[%d] mod_pbits[%d] trg_port[%d], trg_queue[%d], gem_port[%d]\r\n",
+                cust_flow.pkt_frwd.in_use, cust_flow.mod_vid, 
+                cust_flow.mod_pbits, cust_flow.pkt_frwd.trg_port, 
+                cust_flow.pkt_frwd.trg_queue, cust_flow.pkt_frwd.gem_port);
+    }    
+    else if (!strcmp(name, "untag_flow_get")) {
+        memset(&cust_flow, 0, sizeof(cust_flow));
+        cust_flow.dscp  =  v1;
+        cust_flow.dir   = (mv_cust_flow_dir_e)v2;        
+        mv_cust_untag_map_rule_get(&cust_flow);    
+        printk("in_use[%d], mod_vid[%d] mod_pbits[%d] trg_port[%d], trg_queue[%d], gem_port[%d]\r\n", 
+                cust_flow.pkt_frwd.in_use, cust_flow.mod_vid, 
+                cust_flow.mod_pbits, cust_flow.pkt_frwd.trg_port, 
+                cust_flow.pkt_frwd.trg_queue, cust_flow.pkt_frwd.gem_port);        
+    }      
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+#endif
+
+    raw_local_irq_restore(flags);
+
+    return len;
+}
+
+static ssize_t mv_cust_spec_proc_6h_store(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf, size_t len)
+{
+    const char*     name = attr->attr.name;
+    unsigned int    v1=0, v2=0, v3=0, v4=0, v5=0, v6=0;
+    unsigned long   flags;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    /* Read input */
+    sscanf(buf, "%x %x %x %x %x %x", &v1, &v2, &v3, &v4, &v5, &v6);
+
+    raw_local_irq_save(flags);
+
+    if (!strcmp(name, "eoam_mac")) {
+        eoam_mac[0] = (uint8_t)v1;
+        eoam_mac[1] = (uint8_t)v2;
+        eoam_mac[2] = (uint8_t)v3;
+        eoam_mac[3] = (uint8_t)v4;
+        eoam_mac[4] = (uint8_t)v5;
+        eoam_mac[5] = (uint8_t)v6;
+    }
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+    raw_local_irq_restore(flags);
+
+    return len;
+}
+
+static ssize_t mv_cust_spec_proc_64_store(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf, size_t len)
+{
+    const char*          name = attr->attr.name;
+    unsigned int         v[64];
+    unsigned int         index = 0;
+    unsigned long        flags;
+    mv_cust_dscp_pbits_t dscp_map;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    /* Read input */
+    for (index=0; index<64; index++) {
+        sscanf(buf, "%d", &v[index]);
+        dscp_map.pbits[index] = (uint8_t)v[index];
+    }
+    dscp_map.in_use = 1;
+
+    raw_local_irq_save(flags);
+
+    if (!strcmp(name, "dscp_map_set")) {
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE       
+        mv_cust_dscp_map_set(&dscp_map);
+#endif        
+    }
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+    raw_local_irq_restore(flags);
+
+    return len;
+}
+
+static DEVICE_ATTR(debug,          S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+//static DEVICE_ATTR(omci_cmd,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+//static DEVICE_ATTR(omci_gemp,      S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(omci_type,      S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+//static DEVICE_ATTR(omci_gh_keep,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(loopdet_type,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(omci_ena,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(omci_set,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_6_store);
+static DEVICE_ATTR(eoam_enable,    S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(eoam_type,      S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(eoam_gh_keep,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+//static DEVICE_ATTR(omci_txq,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_2_store);
+static DEVICE_ATTR(eoam_txq,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(eoam_write,     S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_1_store);
+static DEVICE_ATTR(eoam_mac,       S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_6h_store);
+static DEVICE_ATTR(udp_src,        S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_6_store);
+static DEVICE_ATTR(udp_dst,        S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_6_store);
+static DEVICE_ATTR(flow_map_debug, S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(flow_map_us_set,S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(flow_map_ds_set,S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+
+static DEVICE_ATTR(dscp_map_set,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_64_store);
+static DEVICE_ATTR(flow_map_del,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(tag_flow_get,   S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(untag_flow_get, S_IWUSR, mv_cust_spec_proc_show, mv_cust_spec_proc_flow_store);
+static DEVICE_ATTR(omci,           S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(eoam,           S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(igmp,           S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(loopdet,        S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(udp_ports,      S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(flow_map,       S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(flow_map_show,  S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(flow_map_clear, S_IRUSR, mv_cust_spec_proc_show, NULL);
+static DEVICE_ATTR(dscp_map_del,   S_IRUSR, mv_cust_spec_proc_show, NULL);
+
+
+
+static DEVICE_ATTR(help,         S_IRUSR, mv_cust_spec_proc_show, NULL);
+
+static struct attribute *mv_cust_spec_proc_attrs[] = {
+    &dev_attr_debug.attr,
+    //&dev_attr_omci_cmd.attr,
+    //&dev_attr_omci_gemp.attr,
+    &dev_attr_omci_type.attr,
+    //&dev_attr_omci_gh_keep.attr,
+    //&dev_attr_omci_txq.attr,
+    &dev_attr_omci_ena.attr,
+    &dev_attr_omci_set.attr,
+    &dev_attr_eoam_type.attr,
+    &dev_attr_eoam_gh_keep.attr,
+    &dev_attr_eoam_enable.attr,
+    &dev_attr_eoam_txq.attr,
+    &dev_attr_eoam_write.attr,
+    &dev_attr_eoam_mac.attr,
+    &dev_attr_loopdet_type.attr,
+    &dev_attr_udp_src.attr,
+    &dev_attr_udp_dst.attr,
+    &dev_attr_flow_map_debug.attr,
+    &dev_attr_flow_map_us_set.attr,
+    &dev_attr_flow_map_ds_set.attr,    
+    &dev_attr_dscp_map_set.attr,
+    &dev_attr_flow_map_del.attr,
+    &dev_attr_tag_flow_get.attr,
+    &dev_attr_untag_flow_get.attr,    
+    &dev_attr_omci.attr,
+    &dev_attr_eoam.attr,
+    &dev_attr_igmp.attr,
+    &dev_attr_loopdet.attr,
+    &dev_attr_udp_ports.attr,
+    &dev_attr_flow_map.attr,    
+    &dev_attr_flow_map_show.attr,     
+    &dev_attr_flow_map_clear.attr,   
+    &dev_attr_dscp_map_del.attr,       
+    &dev_attr_help.attr,
+    NULL
+};
+
+static struct attribute_group mv_cust_spec_proc_group = {
+    .name = "proto",
+    .attrs = mv_cust_spec_proc_attrs,
+};
+
+int mvcust_sysfs_init(void)
+{
+    int err;
+    struct device *pd;
+
+    pd = bus_find_device_by_name(&platform_bus_type, NULL, "cust");
+    if (!pd) {
+        platform_device_register_simple("cust", -1, NULL, 0);
+        pd = bus_find_device_by_name(&platform_bus_type, NULL, "cust");
+    }
+
+    if (!pd) {
+        printk(KERN_ERR"%s: cannot find cust device\n", __FUNCTION__);
+        pd = &platform_bus;
+    }
+
+    err = sysfs_create_group(&pd->kobj, &mv_cust_spec_proc_group);
+    if (err) {
+        printk(KERN_INFO "sysfs group failed %d\n", err);
+        goto out;
+    }
+
+    printk(KERN_INFO "= CUST Module SYS FS Init ended successfully =\n");
+    out:
+    return err;
+}
+
+void mvcust_sysfs_delete(void)
+{
+    struct device *pd;
+
+    pd = bus_find_device_by_name(&platform_bus_type, NULL, "cust");
+    if (!pd)
+    {
+        printk(KERN_ERR"%s: cannot find CUST device\n", __FUNCTION__);
+        return;
+    }
+
+    sysfs_remove_group(&pd->kobj, &mv_cust_spec_proc_group);
+
+    printk(KERN_INFO "= CUST Module SYS FS Remove ended successfully =\n");
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/Kconfig
new file mode 100755
index 0000000..85bcaf6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/Kconfig
@@ -0,0 +1,55 @@
+config MV_USE_IDMA_ENGINE
+        bool "Use the IDMA engine to offload CPU tasks"   
+        depends on (MV_INCLUDE_IDMA && !MV_USE_XOR_ENGINE) && EXPERIMENTAL
+        default n
+        help
+            Say Y of you want to use the IDMA engine to offload some of the 
+            CPU tasks.
+
+config MV_IDMA_COPYUSER
+        bool "Use the IDMA enignes to accelerate the copy_to_user() and copy_from_user functions"
+        depends on (MV_USE_IDMA_ENGINE) && !MV_USE_XOR_COPY_TO_USER && !MV_USE_XOR_COPY_FROM_USER
+        default n
+        help
+          Say Y here if you want to use the IDMA engine to perform
+          copy_to_user() and copy_from_user() functionality.
+
+config MV_IDMA_COPYUSER_THRESHOLD
+        int "Minimum number of bytes to use IDMA acceleration for copy_to_user() and copy_from_user()"
+        depends on MV_IDMA_COPYUSER
+        default "1260"
+        help
+          This is the minimum buffer size needed in order to operate the IDMA engine
+          for accelerating the copy_to_user() and copy_from_user() operations
+
+config MV_IDMA_MEMZERO
+        bool "Use the IDMA to accelerate memzero"
+        depends on (MV_USE_IDMA_ENGINE) && 0
+        default n
+        help
+          Say Y here if you want to use the IDMA engine to perform the memzero. (not supported)
+
+config MV_IDMA_MEMZERO_THRESHOLD
+        int "Minimum number of bytes to use IDMA acceleration for memzero()"
+        depends on MV_IDMA_MEMZERO
+        default "192"
+        help
+          This is the minimum buffer size needed in order to operate the IDMA engine
+          for accelerating the memzero operation
+
+config MV_IDMA_MEMCOPY
+        bool "Use the IDMA to accelerate memcpy and memmove"
+        depends on (MV_USE_IDMA_ENGINE) && !MV_XOR_MEMCOPY
+        default n
+        help
+          Say Y here if you want to use the IDMA engine to perform the memcpy 
+          and memmove.
+
+config MV_IDMA_MEMCOPY_THRESHOLD
+        int "Minimum number of bytes to use IDMA acceleration for memcpy()"
+        depends on MV_IDMA_MEMCOPY
+        default "128"
+        help
+          This is the minimum buffer size needed in order to operate the IDMA engine
+          for accelerating the memcpy() and memmove() operations
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/Makefile
new file mode 100755
index 0000000..dac1ba7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/Makefile
@@ -0,0 +1,10 @@
+#

+# Makefile for the Marvell DMA Driver

+#

+ifeq ($(CONFIG_ARCH_FEROCEON),y)

+	include $(srctree)/$(MACHINE)/config/mvRules.mk

+endif

+

+obj-$(CONFIG_MV_USE_IDMA_ENGINE) += mv_dma.o 

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/mv_dma.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/mv_dma.c
new file mode 100755
index 0000000..509aca2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_dma/mv_dma.c
@@ -0,0 +1,798 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+#include <asm/mach/time.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+
+#include "idma/mvIdma.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#if defined (CONFIG_MV_XOR_MEMCOPY) || defined (CONFIG_MV_IDMA_MEMCOPY)
+#define memcpy asm_memcpy
+#define asm_memmove memmove
+#endif
+
+#ifndef COPYUSER_MIN_SIZE
+#define COPYUSER_MIN_SIZE	CONFIG_MV_IDMA_COPYUSER_THRESHOLD
+#endif
+
+#undef DEBUG
+//#define DEBUG
+
+#ifdef DEBUG
+	#define DPRINTK(s, args...)  printk("MV_DMA: " s, ## args)
+#else
+	#define DPRINTK(s, args...)
+#endif
+
+#undef CPY_USE_DESC
+#undef RT_DEBUG
+#define RT_DEBUG
+
+#define CPY_IDMA_CTRL_LOW_VALUE      ICCLR_DST_BURST_LIM_128BYTE   \
+                                    | ICCLR_SRC_BURST_LIM_128BYTE   \
+                                    | ICCLR_INT_MODE_MASK           \
+                                    | ICCLR_BLOCK_MODE              \
+                                    | ICCLR_CHAN_ENABLE             \
+                                    | ICCLR_DESC_MODE_16M
+
+#define CPY_CHAN1	2
+#define CPY_CHAN2	3
+
+#define CPY_DMA_TIMEOUT	0x100000
+
+#define NEXT_CHANNEL(channel) ((CPY_CHAN1 + CPY_CHAN2) - (channel))
+#define PREV_CHANNEL(channel) NEXT_CHANNEL(channel)
+static MV_U32 current_dma_channel =  CPY_CHAN1;
+static int idma_init = 0;
+static int idma_busy = 0;
+
+#ifdef RT_DEBUG
+static int dma_wait_loops = 0;
+#endif
+
+#ifdef CONFIG_MV_IDMA_MEMZERO
+#define	DMA_MEMZERO_CHUNK    0x80 /*128*/    /* this is based on the size of the DST and SRC burst limits */
+static MV_U8	dmaMemInitBuff[DMA_MEMZERO_CHUNK] __attribute__(( aligned(128) ));
+#endif
+
+#define IDMA_MIN_COPY_CHUNK CONFIG_MV_IDMA_COPYUSER_THRESHOLD
+
+static inline u32 page_remainder(u32 virt)
+{
+	return PAGE_SIZE - (virt & ~PAGE_MASK);
+}
+
+/*
+ * map a kernel virtual address or kernel logical address to a phys address
+ */
+static inline u32 physical_address(u32 virt, int write)
+{
+    struct page *page;
+       /* kernel static-mapped address */
+    DPRINTK(" get physical address: virt %x , write %d\n", virt, write);
+    if (virt_addr_valid(virt)) 
+    {
+        return __pa((u32) virt);
+    }
+    if (virt >= high_memory)
+	    return 0;
+    
+    if (virt >= TASK_SIZE)
+    {
+        page = follow_page(find_extend_vma(&init_mm, virt), (u32) virt, write);
+    }
+    else
+    {
+        page = follow_page(find_extend_vma(current->mm, virt), (u32) virt, write);
+    }
+    
+    if (pfn_valid(page_to_pfn(page)))
+    {
+        return ((page_to_pfn(page) << PAGE_SHIFT) |
+                       ((u32) virt & (PAGE_SIZE - 1)));
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+unsigned int wait_for_idma(MV_U32   channel)
+{
+	u32 timeout = 0;
+
+	/* wait for completion */
+        while( mvDmaStateGet(channel) != MV_IDLE )
+	{
+		DPRINTK(" ctrl low is %x \n", MV_REG_READ(IDMA_CTRL_LOW_REG(channel)));
+		//udelay(1);
+#ifdef RT_DEBUG
+                dma_wait_loops++; 
+#endif
+		if(timeout++ > CPY_DMA_TIMEOUT)
+                {
+		    printk("dma_copy: IDMA %d timed out , ctrl low is %x \n",
+                    channel, MV_REG_READ(IDMA_CTRL_LOW_REG(channel)));
+                    return 1;
+                }		
+	}
+	DPRINTK("IDMA complete in %x \n", timeout);
+	return 0;
+}
+
+static struct proc_dir_entry *dma_proc_entry;
+static int dma_to_user = 0;
+static int dma_from_user = 0;
+static int dma_memcpy_cnt = 0;
+static int dma_memzero_cnt = 0;
+#ifdef RT_DEBUG
+static int dma_activations = 0;
+#endif
+static int dma_read_proc(char *, char **, off_t, int, int *, void *);
+
+static int dma_read_proc(char *buf, char **start, off_t offset, int len,
+						 int *eof, void *data)
+{
+	len = 0;
+#ifdef CONFIG_MV_IDMA_COPYUSER
+        len += sprintf(buf + len, "DMA min buffer size for copy to/from user %d\n", COPYUSER_MIN_SIZE);
+#endif
+#ifdef CONFIG_MV_IDMA_MEMCOPY
+	len += sprintf(buf + len, "DMA min buffer size for memcpy and memmove %d\n", CONFIG_MV_IDMA_MEMCOPY_THRESHOLD);
+#endif
+#ifdef CONFIG_MV_IDMA_MEMZERO
+	len += sprintf(buf + len, "DMA min buffer size for memzero %d\n", CONFIG_MV_IDMA_MEMZERO_THRESHOLD);
+#endif
+	len += sprintf(buf + len, "Number of DMA copy to user %d copy from user %d \n", dma_to_user, dma_from_user);
+	len += sprintf(buf + len, "Number of DMA memzero %d \n", dma_memzero_cnt);
+	len += sprintf(buf + len, "Number of DMA memcpy %d \n", dma_memcpy_cnt);
+#ifdef RT_DEBUG
+	len += sprintf(buf + len, "Number of dma activations %d\n", dma_activations);
+	len += sprintf(buf + len, "Number of wait for dma loops %d\n", dma_wait_loops);
+#endif
+        
+	return len;
+}
+#ifdef CONFIG_MV_IDMA_COPYUSER
+#warning "no protection from speculative I fetch"
+//probably not needed since operation is closed in spin_lock_irq 
+/*=======================================================================*/
+/*  Procedure:  dma_copy()                                               */
+/*                                                                       */
+/*  Description:    DMA-based copy_to_user.                              */
+/*                                                                       */
+/*  Parameters:  to: destination address                                 */
+/*               from: source address                                    */
+/*               n: number of bytes to transfer (n must be greater       */
+/*                   equal than 64)                                     */
+/*		 to_user: (1) Copy TO user (0) Copy FROM user	 	 */
+/*                                                                       */
+/*  Returns:     unsigned long: number of bytes NOT copied               */
+/*                                                                       */
+/*=======================================================================*/
+static unsigned long dma_copy(void *to, const void *from, unsigned long n, unsigned int to_user)
+{
+	u32 chunk,i;
+	u32 k_chunk = 0;
+	u32 u_chunk = 0;
+	u32 phys_from, phys_to;
+	
+        unsigned long flags;
+	u32 unaligned_to;
+	u32 index = 0;
+        u32 temp;
+
+        unsigned long uaddr, kaddr;
+        unsigned char kaddr_kernel_static = 0;
+	DPRINTK("dma_copy: entering\n");
+
+
+	/* 
+      	 * The unaligned is taken care seperatly since the dst might be part of a cache line that is changed 
+	 * by other process -> we must not invalidate this cache lines and we can't also flush it, since other 
+	 * process (or the exception handler) might fetch the cache line before we copied it. 
+	 */
+
+	/*
+	 * Ok, start addr is not cache line-aligned, so we need to make it so.
+	 */
+	unaligned_to = (u32)to & 31;
+	if(unaligned_to)
+	{
+		DPRINTK("Fixing up starting address %d bytes\n", 32 - unaligned_to);
+
+		if(to_user)
+			__arch_copy_to_user(to, from, 32 - unaligned_to);
+		else
+			__arch_copy_from_user(to, from, 32 - unaligned_to);
+
+		temp = (u32)to + (32 - unaligned_to);
+		to = (void *)temp;
+		temp = (u32)from + (32 - unaligned_to);
+		from = (void *)temp;
+
+                /*it's ok, n supposed to be greater than 32 bytes at this point*/
+		n -= (32 - unaligned_to);
+	}
+
+	/*
+	 * Ok, we're aligned at the top, now let's check the end
+	 * of the buffer and align that. After this we should have
+	 * a block that is a multiple of cache line size.
+	 */
+	unaligned_to = ((u32)to + n) & 31;
+	if(unaligned_to)
+	{	
+		u32 tmp_to = (u32)to + (n - unaligned_to);
+		u32 tmp_from = (u32)from + (n - unaligned_to);
+		DPRINTK("Fixing ending alignment %d bytes\n", unaligned_to);
+
+		if(to_user)
+			__arch_copy_to_user((void *)tmp_to, (void *)tmp_from, unaligned_to);
+		else
+			__arch_copy_from_user((void *)tmp_to, (void *)tmp_from, unaligned_to);
+
+                /*it's ok, n supposed to be greater than 32 bytes at this point*/
+		n -= unaligned_to;
+	}
+
+        if(to_user)
+        {
+            uaddr = (unsigned long)to;  
+            kaddr = (unsigned long)from;
+        }
+        else
+        {
+             uaddr = (unsigned long)from;
+             kaddr = (unsigned long)to;
+        }
+        if(virt_addr_valid(kaddr))
+        {
+            kaddr_kernel_static = 1;
+            k_chunk = n;
+        }
+	else
+	{
+		DPRINTK("kernel address is not linear, fall back\n");
+		goto exit_dma;
+	}
+         
+        spin_lock_irqsave(&current->mm->page_table_lock, flags);
+	if (idma_busy)
+	{
+	    BUG();
+	}
+	idma_busy = 1;
+     
+        i = 0;
+	while(n > 0)
+	{
+	    if(k_chunk == 0)
+	    {
+                /* virtual address */
+	        k_chunk = page_remainder((u32)kaddr);
+		DPRINTK("kaddr reminder %d \n",k_chunk);
+	    }
+
+	    if(u_chunk == 0)
+	    {
+                u_chunk = page_remainder((u32)uaddr);
+                DPRINTK("uaddr reminder %d \n", u_chunk);
+            }
+        
+            chunk = ((u_chunk < k_chunk) ? u_chunk : k_chunk);
+            if(n < chunk)
+	    {
+		chunk = n;
+	    }
+
+	    if(chunk == 0)
+	    {
+	    	break;
+	    }
+            phys_from = physical_address((u32)from, 0);
+            phys_to = physical_address((u32)to, 1);
+	    DPRINTK("choose chunk %d \n",chunk);
+	    /*
+	     *  Prepare the IDMA.
+	     */
+            if (chunk < IDMA_MIN_COPY_CHUNK)
+            {
+        	DPRINTK(" chunk %d too small , use memcpy \n",chunk);
+                /* the "to" address might cross cache line boundary, so part of the line*/  
+                /* may be subject to DMA, so we need to wait to last DMA engine to finish */
+                if (index > 0)
+                {
+                    if(wait_for_idma(PREV_CHANNEL(current_dma_channel)))
+                    {
+	                BUG();
+                    }
+                }
+                
+        	if(to_user)
+	       	    __arch_copy_to_user((void *)to, (void *)from, chunk);
+	        else
+		    __arch_copy_from_user((void *)to, (void *)from, chunk);
+            }
+            else if ((!phys_from) || (!phys_to))
+            {
+                /* The requested page isn't available, fall back to */
+                DPRINTK(" no physical address, fall back: from %p , to %p \n", from, to);
+                goto wait_for_idmas;
+   
+            }
+            else
+            {
+                /* 
+	 	 * Ensure that the cache is clean:
+	 	 *      - from range must be cleaned
+        	 *      - to range must be invalidated
+	         */
+		dmac_flush_range(from, from + chunk);
+		dmac_inv_range(to, to + chunk);
+               
+               	    if(index > 1)
+		    {
+		        if(wait_for_idma(current_dma_channel))
+                        {
+		            BUG(); 
+                            goto unlock_dma;
+                        }
+                    }
+		    /* Start DMA */
+                    DPRINTK(" activate DMA: channel %d from %x to %x len %x\n",
+                            current_dma_channel, phys_from, phys_to, chunk);
+		    mvDmaTransfer(current_dma_channel, phys_from, phys_to, chunk, 0);
+                    current_dma_channel = NEXT_CHANNEL(current_dma_channel); 
+#ifdef RT_DEBUG
+                    dma_activations++;
+#endif
+		    index++;
+                }
+                
+
+		/* go to next chunk */
+		from += chunk;
+		to += chunk;
+                kaddr += chunk;
+                uaddr += chunk;
+		n -= chunk;
+		u_chunk -= chunk;
+		k_chunk -= chunk;		
+	}
+        
+wait_for_idmas:
+        if (index > 1)
+        {
+	    if(wait_for_idma(current_dma_channel))
+            {
+	        BUG(); 
+            }
+        }
+
+        if (index > 0)
+        {
+            if(wait_for_idma(PREV_CHANNEL(current_dma_channel)))
+            {
+	        BUG();
+            }
+        }
+
+unlock_dma:    
+	idma_busy = 0;    
+        spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
+ exit_dma:
+        
+        DPRINTK("dma_copy(0x%x, 0x%x, %lu): exiting\n", (u32) to,
+                (u32) from, n);
+       
+
+        if(n != 0)
+        {
+       	    if(to_user)
+                return __arch_copy_to_user((void *)to, (void *)from, n);
+	            else
+                return __arch_copy_from_user((void *)to, (void *)from, n);
+        }
+        return 0;
+}
+
+/*=======================================================================*/
+/*  Procedure:  dma_copy_to_user()                                       */
+/*                                                                       */
+/*  Description:    DMA-based copy_to_user.                              */
+/*                                                                       */
+/*  Parameters:  to: destination address                                 */
+/*               from: source address                                    */
+/*               n: number of bytes to transfer                          */
+/*                                                                       */
+/*  Returns:     unsigned long: number of bytes NOT copied               */
+/*                                                                       */
+/*  Notes/Assumptions:                                                   */
+/*              Assumes that kernel physical memory is contiguous, i.e., */
+/*              the physical addresses of contiguous virtual addresses   */
+/*              are also contiguous.                                     */
+/*              Assumes that kernel memory doesn't get paged.            */
+/*              Assumes that to/from memory regions cannot overlap       */
+/*                                                                       */
+/*=======================================================================*/
+unsigned long dma_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	if(!idma_init)
+    		return __arch_copy_to_user((void *)to, (void *)from, n);
+
+     	dma_to_user++;
+     	DPRINTK(KERN_CRIT "dma_copy_to_user(%#10x, 0x%#10x, %lu): entering\n", (u32) to, (u32) from, n);
+    
+        return  dma_copy(to, from, n, 1);
+}
+
+/*=======================================================================*/
+/*  Procedure:  dma_copy_from_user()                                     */
+/*                                                                       */
+/*  Description:    DMA-based copy_from_user.                            */
+/*                                                                       */
+/*  Parameters:  to: destination address                                 */
+/*               from: source address                                    */
+/*               n: number of bytes to transfer                          */
+/*                                                                       */
+/*  Returns:     unsigned long: number of bytes NOT copied               */
+/*                                                                       */
+/*  Notes/Assumptions:                                                   */
+/*              Assumes that kernel virtual memory is contiguous, i.e.,  */
+/*              the physical addresses of contiguous virtual addresses   */
+/*              are also contiguous.                                     */
+/*              Assumes that kernel memory doesn't get paged.            */
+/*              Assumes that to/from memory regions cannot overlap       */
+/*              XXX this one doesn't quite work right yet                */
+/*                                                                       */
+/*=======================================================================*/
+unsigned long dma_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	if(!idma_init)
+		return __arch_copy_from_user((void *)to, (void *)from, n);
+
+	dma_from_user++;
+	DPRINTK(KERN_CRIT "dma_copy_from_user(0x%x, 0x%x, %lu): entering\n", (u32) to, (u32) from, n);
+	return  dma_copy(to, from, n, 0);
+}
+
+#endif /* CONFIG_MV_IDMA_COPYUSER */
+
+#ifdef CONFIG_MV_IDMA_MEMZERO
+/*=======================================================================*/
+/*  Procedure:  dma_memzero()                                             */
+/*                                                                       */
+/*  Description:    DMA-based in-kernel memzero.                          */
+/*                                                                       */
+/*  Parameters:  to: destination address                                 */
+/*               n: number of bytes to transfer                          */
+/*                                                                       */
+/*  Notes/Assumptions:                                                   */
+/*              Assumes that kernel physical memory is contiguous, i.e., */
+/*              the physical addresses of contiguous virtual addresses   */
+/*              are also contiguous.                                     */
+/*              Assumes that kernel memory doesn't get paged.            */
+/*              The DMA is polling                                       */
+/*                                                                       */
+/*=======================================================================*/
+void dma_memzero(void *to, __kernel_size_t n)
+{
+	u32 phys_from, phys_to;	
+	u32 unaligned_to;
+	unsigned long flags;	
+
+	DPRINTK("dma_memcopy: entering\n");
+
+	/* This is used in the very early stages */
+	if(!idma_init)
+    		return asm_memzero(to ,n);
+
+	/* Fallback for the case that one or both buffers are not physically contiguous  */
+	if(!virt_addr_valid(to))
+        {
+		DPRINTK("Failing back to asm_memzero because of limitations\n");
+            return asm_memzero(to ,n);
+        }	
+
+	++dma_memzero_cnt;	
+
+	/*
+	 * If buffer start addr is not cache line-aligned, so we need to make it so.
+	 */
+	unaligned_to = (u32)to & 31;
+	if(unaligned_to)
+	{
+		DPRINTK("Fixing up starting address %d bytes\n", 32 - unaligned_to);
+
+		asm_memzero(to, 32 - unaligned_to);
+
+		to = (void*)((u32)to + (32 - unaligned_to));
+
+                /*it's ok, n supposed to be greater than 32 bytes at this point*/
+		n -= (32 - unaligned_to);
+	}	
+
+	/*
+	 * If buffer end addr is not cache line-aligned, so we need to make it so.
+	 */
+	unaligned_to = ((u32)to + n) & 31;
+	if(unaligned_to)
+	{	
+		u32 tmp_to = (u32)to + (n - unaligned_to);
+		DPRINTK("Fixing ending alignment %d bytes\n", unaligned_to);
+
+		asm_memzero((void *)tmp_to, unaligned_to);
+
+                /*it's ok, n supposed to be greater than 32 bytes at this point*/
+		n -= unaligned_to;
+	}
+
+	phys_from = physical_address((u32)dmaMemInitBuff, 0);
+        phys_to = physical_address((u32)to, 1);
+
+	/*
+	 *  Prepare the IDMA.
+	 */
+	if ((!phys_from) || (!phys_to))
+        {
+	    /* The requested page isn't available, fall back to */
+            DPRINTK(" no physical address, fall back: to %p \n", to);
+            return asm_memzero(to,n);
+        }
+
+        spin_lock_irqsave(&current->mm->page_table_lock, flags);
+	if (idma_busy)
+	{
+	    BUG();
+	}
+	idma_busy = 1;
+
+	/* Ensure that the destination revion is invalidated */
+	mvOsCacheInvalidate(NULL, (void *)to, n);
+	
+	/* Start DMA */
+        DPRINTK(" activate DMA: channel %d from %x with source hold to %x len %x\n",CPY_CHAN1, phys_from, phys_to, n);
+     	mvDmaMemInit(CPY_CHAN1, phys_from, phys_to, n);
+	
+#ifdef RT_DEBUG
+	dma_activations++;
+#endif
+        
+	if(wait_for_idma(CPY_CHAN1))
+        {
+	    BUG(); 
+	}	
+
+	dma_unmap_single(NULL, virt_to_phys(to), n, DMA_FROM_DEVICE);
+
+        DPRINTK("dma_memzero(0x%x, %lu): exiting\n", (u32) to, n);
+
+	idma_busy = 0;
+	spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
+}
+#endif  /* CONFIG_MV_IDMA_MEMZERO */
+
+#ifdef CONFIG_MV_IDMA_MEMCOPY
+//*=======================================================================*/
+/*  Procedure:  dma_memcpy()                                             */
+/*                                                                       */
+/*  Description:    DMA-based in-kernel memcpy.                          */
+/*                                                                       */
+/*  Parameters:  to: destination address                                 */
+/*               from: source address                                    */
+/*               n: number of bytes to transfer                          */
+/*                                                                       */
+/*  Returns:     void*: to                                               */
+/*                                                                       */
+/*  Notes/Assumptions:                                                   */
+/*              Assumes that kernel physical memory is contiguous, i.e., */
+/*              the physical addresses of contiguous virtual addresses   */
+/*              are also contiguous.                                     */
+/*              Assumes that kernel memory doesn't get paged.            */
+/*              The DMA is polling                                       */
+/*		source and destination buffers can overlap(like memmove) */
+/*                                                                       */
+/*=======================================================================*/
+void *dma_memcpy(void *to, const void *from, __kernel_size_t n)
+{
+	u32 phys_from, phys_to;	
+	u32 unaligned_to;
+	unsigned long flags;
+
+	DPRINTK("dma_memcopy: entering\n");
+
+	/* This is used in the very early stages */
+	if(!idma_init)
+    		return asm_memmove(to, from,n);
+
+	/* Fallback for the case that one or both buffers are not physically contiguous  */
+	if(!virt_addr_valid(to) || !virt_addr_valid(from))
+        {
+		DPRINTK("Failing back to asm_memmove because of limitations\n");
+            return asm_memmove(to,from,n);
+        }	
+
+	/* Check for Overlap */
+	if (((to + n > from) && (to < from)) ||((from < to) && (from + n > to))) 
+	{
+		DPRINTK("overlapping copy region (0x%x, 0x%x, %lu), falling back\n",
+		     to, from, (unsigned long)n);
+		return asm_memmove(to, from, n);
+	}
+
+	++dma_memcpy_cnt;
+
+	/*
+	 * Ok, start addr is not cache line-aligned, so we need to make it so.
+	 */
+	unaligned_to = (u32)to & 31;
+	if(unaligned_to)
+	{
+		DPRINTK("Fixing up starting address %d bytes\n", 32 - unaligned_to);
+
+		asm_memmove(to, from, 32 - unaligned_to);
+
+		to = (void*)((u32)to + (32 - unaligned_to));
+		from = (void*)((u32)from + (32 - unaligned_to));
+
+                /*it's ok, n supposed to be greater than 32 bytes at this point*/
+		n -= (32 - unaligned_to);
+	}	
+
+        spin_lock_irqsave(&current->mm->page_table_lock, flags);
+	if (idma_busy)
+	{
+	    BUG();
+	}
+	idma_busy = 1;
+     
+        phys_from = physical_address((u32)from, 0);
+        phys_to = physical_address((u32)to, 1);
+	
+    	/*
+	 *  Prepare the IDMA.
+	 */
+	if ((!phys_from) || (!phys_to))
+        {
+	    /* The requested page isn't available, fall back to */
+            DPRINTK(" no physical address, fall back: from %p , to %p \n", from, to);
+	    idma_busy = 0;
+	    spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
+            return asm_memmove(to, from,n);
+        }
+        else
+        {
+	    /* 
+	     * Ensure that the cache is clean:
+	     *      - from range must be cleaned
+	     *      - to range must be invalidated
+	     */
+		dmac_flush_range(from, from + n);
+		dmac_inv_range(to, to + n);
+
+               
+	    /* Start DMA */
+            DPRINTK(" activate DMA: channel %d from %x to %x len %x\n",CPY_CHAN1, phys_from, phys_to, n);
+	    mvDmaTransfer(CPY_CHAN1, phys_from, phys_to, n, 0);
+#ifdef RT_DEBUG
+                    dma_activations++;
+#endif
+	}
+        
+	if(wait_for_idma(CPY_CHAN1))
+        {
+	    BUG(); 
+	}	
+
+	dma_unmap_single(NULL, virt_to_phys(to), n, DMA_FROM_DEVICE);
+
+        DPRINTK("dma_memcopy(0x%x, 0x%x, %lu): exiting\n", (u32) to, (u32) from, n);
+
+	idma_busy = 0;
+	spin_unlock_irqrestore(&current->mm->page_table_lock, flags);
+       
+        return 0;
+}
+
+#endif  /* CONFIG_MV_IDMA_MEMCOPY */
+
+int mv_dma_init(void)
+{
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+	if (MV_FALSE == mvSocUnitIsMappedToThisCpu(IDMA))
+	{
+		printk(KERN_INFO"IDMA is not mapped to this CPU\n");
+		return -ENODEV;
+	}
+#endif
+	printk(KERN_INFO "Use IDMA channels %d and %d for enhancing the following function:\n",
+                CPY_CHAN1, CPY_CHAN2);
+#ifdef CONFIG_MV_IDMA_COPYUSER
+        printk(KERN_INFO "  o Copy From/To user space operations.\n");
+#endif
+#ifdef CONFIG_MV_IDMA_MEMCOPY
+	printk(KERN_INFO "  o memcpy() and memmove() operations.\n");
+#endif
+#ifdef CONFIG_MV_IDMA_MEMZERO
+	printk(KERN_INFO "  o memzero() operations.\n");
+#endif
+
+#ifdef CONFIG_MV_IDMA_MEMZERO
+	DPRINTK(KERN_ERR "ZERO buffer address 0x%08x\n", (u32)dmaMemInitBuff);
+	
+	asm_memzero(dmaMemInitBuff, sizeof(dmaMemInitBuff));
+	dmac_flush_range(dmaMemInitBuff, dmaMemInitBuff + sizeof(dmaMemInitBuff));
+#endif
+
+        MV_REG_WRITE(IDMA_BYTE_COUNT_REG(CPY_CHAN1), 0);
+        MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(CPY_CHAN1), 0);
+        MV_REG_WRITE(IDMA_CTRL_HIGH_REG(CPY_CHAN1), ICCHR_ENDIAN_LITTLE 
+#ifdef MV_CPU_LE
+      		| ICCHR_DESC_BYTE_SWAP_EN
+#endif
+		 );
+        MV_REG_WRITE(IDMA_CTRL_LOW_REG(CPY_CHAN1), CPY_IDMA_CTRL_LOW_VALUE);
+
+        MV_REG_WRITE(IDMA_BYTE_COUNT_REG(CPY_CHAN2), 0);
+        MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(CPY_CHAN2), 0);
+        MV_REG_WRITE(IDMA_CTRL_HIGH_REG(CPY_CHAN2), ICCHR_ENDIAN_LITTLE 
+#ifdef MV_CPU_LE
+      		| ICCHR_DESC_BYTE_SWAP_EN
+#endif
+		 );
+        MV_REG_WRITE(IDMA_CTRL_LOW_REG(CPY_CHAN2), CPY_IDMA_CTRL_LOW_VALUE);
+
+        current_dma_channel = CPY_CHAN1;
+	dma_proc_entry = create_proc_entry("dma_copy", S_IFREG | S_IRUGO, 0);
+	dma_proc_entry->read_proc = dma_read_proc;
+//	dma_proc_entry->write_proc = dma_write_proc;
+	dma_proc_entry->nlink = 1;
+
+	idma_init = 1;
+
+	return 0;
+}
+
+void mv_dma_exit(void)
+{
+}
+
+module_init(mv_dma_init);
+module_exit(mv_dma_exit);
+MODULE_LICENSE(GPL);
+
+#ifdef CONFIG_MV_IDMA_MEMCOPY
+EXPORT_SYMBOL(dma_memcpy);
+#endif
+
+#ifdef CONFIG_MV_IDMA_MEMZERO
+EXPORT_SYMBOL(dma_memzero);
+#endif
+
+#ifdef CONFIG_MV_IDMA_COPYUSER
+EXPORT_SYMBOL(dma_copy_to_user);
+EXPORT_SYMBOL(dma_copy_from_user);			
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/Makefile
new file mode 100755
index 0000000..57fc545
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Marvell EZXML driver
+#
+
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifdef CONFIG_MV_HAL_RULES_PATH
+include $(srctree)/include/config/auto.conf
+include $(srctree)/$(subst ",,$(CONFIG_MV_HAL_RULES_PATH))
+endif
+
+obj-y += ezxml.o
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/ezxml.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/ezxml.c
new file mode 100755
index 0000000..13c237d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/ezxml.c
@@ -0,0 +1,1184 @@
+/* ezxml.c
+ *
+ * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+*/
+#include "../../linux_oss/mvOs.h"
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/byteorder/generic.h>
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include "linux/fs.h"
+#include "asm/uaccess.h"
+
+#include "ezxml.h"
+
+void* ezxml_realloc(void *p, size_t new_size);
+
+#define malloc(SIZE) kmalloc((SIZE), GFP_KERNEL)
+#define realloc(PTR, SIZE) ezxml_realloc((PTR), (SIZE))
+#define free kfree
+#define stat kstat
+
+
+#define EZXML_WS   "\t\r\n "  // whitespace
+#define EZXML_ERRL 128        // maximum error string length
+
+typedef struct ezxml_root *ezxml_root_t;
+struct ezxml_root {       // additional data for the root tag
+    struct ezxml xml;     // is a super-struct built on top of ezxml struct
+    ezxml_t cur;          // current xml tree insertion point
+    char *m;              // original xml string
+    size_t len;           // length of allocated memory for mmap, -1 for malloc
+    char *u;              // UTF-8 conversion of string if original was UTF-16
+    char *s;              // start of work area
+    char *e;              // end of work area
+    char **ent;           // general entities (ampersand sequences)
+    char ***attr;         // default attributes
+    char ***pi;           // processing instructions
+    short standalone;     // non-zero if <?xml standalone="yes"?>
+    char err[EZXML_ERRL]; // error string
+};
+
+char *EZXML_NIL[] = { NULL }; // empty, null terminated array of strings
+
+char *strdup(const char  *pString)
+{
+    char  *pMemory = NULL;
+    size_t size = 0;
+
+    if( !pString )
+        return(NULL);
+
+    size = strlen(pString) + 1;
+
+    if( (pMemory = malloc(size)) )
+    {
+        strcpy(pMemory, pString);
+        return pMemory;
+    }
+
+    return NULL;
+}
+
+// returns the first child tag with the given name or NULL if not found
+ezxml_t ezxml_child(ezxml_t xml, const char *name)
+{
+    xml = (xml) ? xml->child : NULL;
+    while (xml && strcmp(name, xml->name)) xml = xml->sibling;
+    return xml;
+}
+
+// returns the Nth tag with the same name in the same subsection or NULL if not
+// found
+ezxml_t ezxml_idx(ezxml_t xml, int idx)
+{
+    for (; xml && idx; idx--) xml = xml->next;
+    return xml;
+}
+
+// returns the value of the requested tag attribute or NULL if not found
+const char *ezxml_attr(ezxml_t xml, const char *attr)
+{
+    int i = 0, j = 1;
+    ezxml_root_t root = (ezxml_root_t)xml;
+
+    if (! xml || ! xml->attr) return NULL;
+    while (xml->attr[i] && strcmp(attr, xml->attr[i])) i += 2;
+    if (xml->attr[i]) return xml->attr[i + 1]; // found attribute
+
+    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag
+    for (i = 0; root->attr[i] && strcmp(xml->name, root->attr[i][0]); i++);
+    if (! root->attr[i]) return NULL; // no matching default attributes
+    while (root->attr[i][j] && strcmp(attr, root->attr[i][j])) j += 3;
+    return (root->attr[i][j]) ? root->attr[i][j + 1] : NULL; // found default
+}
+
+// same as ezxml_get but takes an already initialized va_list
+ezxml_t ezxml_vget(ezxml_t xml, va_list ap)
+{
+    char *name = va_arg(ap, char *);
+    int idx = -1;
+ 
+    if (name && *name) {
+        idx = va_arg(ap, int);  
+        xml = ezxml_child(xml, name);
+    }
+    return (idx < 0)? xml : ezxml_vget(ezxml_idx(xml, idx), ap);
+}
+
+// Traverses the xml tree to retrieve a specific subtag. Takes a variable
+// length list of tag names and indexes. The argument list must be terminated
+// by either an index of -1 or an empty string tag name. Example: 
+// title = ezxml_get(library, "shelf", 0, "book", 2, "title", -1);
+// This retrieves the title of the 3rd book on the 1st shelf of library.
+// Returns NULL if not found.
+ezxml_t ezxml_get(ezxml_t xml, ...)
+{
+    va_list ap;
+    ezxml_t r;
+
+
+    va_start(ap, xml);
+    r = ezxml_vget(xml, ap);
+    va_end(ap);
+    return r;
+}
+
+// returns a null terminated array of processing instructions for the given
+// target
+const char **ezxml_pi(ezxml_t xml, const char *target)
+{
+    ezxml_root_t root = (ezxml_root_t)xml;
+    int i = 0;
+
+    if (! root) return (const char **)EZXML_NIL;
+    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag
+    while (root->pi[i] && strcmp(target, root->pi[i][0])) i++; // find target
+    return (const char **)((root->pi[i]) ? root->pi[i] + 1 : EZXML_NIL);
+}
+
+// set an error string and return root
+ezxml_t ezxml_err(ezxml_root_t root, char *s, const char *err, ...)
+{
+    va_list ap;
+    int line = 1;
+    char *t, fmt[EZXML_ERRL];
+    
+    for (t = root->s; t < s; t++) if (*t == '\n') line++;
+    snprintf(fmt, EZXML_ERRL, "[error near line %d]: %s", line, err);
+
+    va_start(ap, err);
+    vsnprintf(root->err, EZXML_ERRL, fmt, ap);
+    va_end(ap);
+
+    return &root->xml;
+}
+
+// Recursively decodes entity and character references and normalizes new lines
+// ent is a null terminated array of alternating entity names and values. set t
+// to '&' for general entity decoding, '%' for parameter entity decoding, 'c'
+// for cdata sections, ' ' for attribute normalization, or '*' for non-cdata
+// attribute normalization. Returns s, or if the decoded string is longer than
+// s, returns a malloced string that must be freed.
+char *ezxml_decode(char *s, char **ent, char t)
+{
+    char *e, *r = s, *m = s;
+    long b, c, d, l;
+
+    for (; *s; s++) { // normalize line endings
+        while (*s == '\r') {
+            *(s++) = '\n';
+            if (*s == '\n') memmove(s, (s + 1), strlen(s));
+        }
+    }
+    
+    for (s = r; ; ) {
+        while (*s && *s != '&' && (*s != '%' || t != '%') && !isspace(*s)) s++;
+
+        if (! *s) break;
+        else if (t != 'c' && ! strncmp(s, "&#", 2)) { // character reference
+            if (s[2] == 'x') c = strtol(s + 3, &e, 16); // base 16
+            else c = strtol(s + 2, &e, 10); // base 10
+            if (! c || *e != ';') { s++; continue; } // not a character ref
+
+            if (c < 0x80) *(s++) = c; // US-ASCII subset
+            else { // multi-byte UTF-8 sequence
+                for (b = 0, d = c; d; d /= 2) b++; // number of bits in c
+                b = (b - 2) / 5; // number of bytes in payload
+                *(s++) = (0xFF << (7 - b)) | (c >> (6 * b)); // head
+                while (b) *(s++) = 0x80 | ((c >> (6 * --b)) & 0x3F); // payload
+            }
+
+            memmove(s, strchr(s, ';') + 1, strlen(strchr(s, ';')));
+        }
+        else if ((*s == '&' && (t == '&' || t == ' ' || t == '*')) ||
+                 (*s == '%' && t == '%')) { // entity reference
+            for (b = 0; ent[b] && strncmp(s + 1, ent[b], strlen(ent[b]));
+                 b += 2); // find entity in entity list
+
+            if (ent[b++]) { // found a match
+                if ((c = strlen(ent[b])) - 1 > (e = strchr(s, ';')) - s) {
+                    l = (d = (s - r)) + c + strlen(e); // new length
+                    r = (r == m) ? strcpy(malloc(l), r) : realloc(r, l);
+                    e = strchr((s = r + d), ';'); // fix up pointers
+                }
+
+                memmove(s + c, e + 1, strlen(e)); // shift rest of string
+                strncpy(s, ent[b], c); // copy in replacement text
+            }
+            else s++; // not a known entity
+        }
+        else if ((t == ' ' || t == '*') && isspace(*s)) *(s++) = ' ';
+        else s++; // no decoding needed
+    }
+
+    if (t == '*') { // normalize spaces for non-cdata attributes
+        for (s = r; *s; s++) {
+            if ((l = strspn(s, " "))) memmove(s, s + l, strlen(s + l) + 1);
+            while (*s && *s != ' ') s++;
+        }
+        if (--s >= r && *s == ' ') *s = '\0'; // trim any trailing space
+    }
+    return r;
+}
+
+// called when parser finds start of new tag
+void ezxml_open_tag(ezxml_root_t root, char *name, char **attr)
+{
+    ezxml_t xml = root->cur;
+    
+    if (xml->name) xml = ezxml_add_child(xml, name, strlen(xml->txt));
+    else xml->name = name; // first open tag
+
+    xml->attr = attr;
+    root->cur = xml; // update tag insertion point
+}
+
+// called when parser finds character content between open and closing tag
+void ezxml_char_content(ezxml_root_t root, char *s, size_t len, char t)
+{
+    ezxml_t xml = root->cur;
+    char *m = s;
+    size_t l;
+
+    if (! xml || ! xml->name || ! len) return; // sanity check
+
+    s[len] = '\0'; // null terminate text (calling functions anticipate this)
+    len = strlen(s = ezxml_decode(s, root->ent, t)) + 1;
+
+    if (! *(xml->txt)) xml->txt = s; // initial character content
+    else { // allocate our own memory and make a copy
+        xml->txt = (xml->flags & EZXML_TXTM) // allocate some space
+                   ? realloc(xml->txt, (l = strlen(xml->txt)) + len)
+                   : strcpy(malloc((l = strlen(xml->txt)) + len), xml->txt);
+        strcpy(xml->txt + l, s); // add new char content
+        if (s != m) free(s); // free s if it was malloced by ezxml_decode()
+    }
+
+    if (xml->txt != m) ezxml_set_flag(xml, EZXML_TXTM);
+}
+
+// called when parser finds closing tag
+ezxml_t ezxml_close_tag(ezxml_root_t root, char *name, char *s)
+{
+    if (! root->cur || ! root->cur->name || strcmp(name, root->cur->name))
+        return ezxml_err(root, s, "unexpected closing tag </%s>", name);
+
+    root->cur = root->cur->parent;
+    return NULL;
+}
+
+// checks for circular entity references, returns non-zero if no circular
+// references are found, zero otherwise
+int ezxml_ent_ok(char *name, char *s, char **ent)
+{
+    int i;
+
+    for (; ; s++) {
+        while (*s && *s != '&') s++; // find next entity reference
+        if (! *s) return 1;
+        if (! strncmp(s + 1, name, strlen(name))) return 0; // circular ref.
+        for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2);
+        if (ent[i] && ! ezxml_ent_ok(name, ent[i + 1], ent)) return 0;
+    }
+}
+
+// called when the parser finds a processing instruction
+void ezxml_proc_inst(ezxml_root_t root, char *s, size_t len)
+{
+    int i = 0, j = 1;
+    char *target = s;
+
+    s[len] = '\0'; // null terminate instruction
+    if (*(s += strcspn(s, EZXML_WS))) {
+        *s = '\0'; // null terminate target
+        s += strspn(s + 1, EZXML_WS) + 1; // skip whitespace after target
+    }
+
+    if (! strcmp(target, "xml")) { // <?xml ... ?>
+        if ((s = strstr(s, "standalone")) && ! strncmp(s + strspn(s + 10,
+            EZXML_WS "='\"") + 10, "yes", 3)) root->standalone = 1;
+        return;
+    }
+
+    if (! root->pi[0]) *(root->pi = malloc(sizeof(char **))) = NULL; //first pi
+
+    while (root->pi[i] && strcmp(target, root->pi[i][0])) i++; // find target
+    if (! root->pi[i]) { // new target
+        root->pi = realloc(root->pi, sizeof(char **) * (i + 2));
+        root->pi[i] = malloc(sizeof(char *) * 3);
+        root->pi[i][0] = target;
+        root->pi[i][1] = (char *)(root->pi[i + 1] = NULL); // terminate pi list
+        root->pi[i][2] = strdup(""); // empty document position list
+    }
+
+    while (root->pi[i][j]) j++; // find end of instruction list for this target
+    root->pi[i] = realloc(root->pi[i], sizeof(char *) * (j + 3));
+    root->pi[i][j + 2] = realloc(root->pi[i][j + 1], j + 1);
+    strcpy(root->pi[i][j + 2] + j - 1, (root->xml.name) ? ">" : "<");
+    root->pi[i][j + 1] = NULL; // null terminate pi list for this target
+    root->pi[i][j] = s; // set instruction
+}
+
+// called when the parser finds an internal doctype subset
+short ezxml_internal_dtd(ezxml_root_t root, char *s, size_t len)
+{
+    char q, *c, *t, *n = NULL, *v, **ent, **pe;
+    int i, j;
+    
+    pe = memcpy(malloc(sizeof(EZXML_NIL)), EZXML_NIL, sizeof(EZXML_NIL));
+
+    for (s[len] = '\0'; s; ) {
+        while (*s && *s != '<' && *s != '%') s++; // find next declaration
+
+        if (! *s) break;
+        else if (! strncmp(s, "<!ENTITY", 8)) { // parse entity definitions
+            c = s += strspn(s + 8, EZXML_WS) + 8; // skip white space separator
+            n = s + strspn(s, EZXML_WS "%"); // find name
+            *(s = n + strcspn(n, EZXML_WS)) = ';'; // append ; to name
+
+            v = s + strspn(s + 1, EZXML_WS) + 1; // find value
+            if ((q = *(v++)) != '"' && q != '\'') { // skip externals
+                s = strchr(s, '>');
+                continue;
+            }
+
+            for (i = 0, ent = (*c == '%') ? pe : root->ent; ent[i]; i++);
+            ent = realloc(ent, (i + 3) * sizeof(char *)); // space for next ent
+            if (*c == '%') pe = ent;
+            else root->ent = ent;
+
+            *(++s) = '\0'; // null terminate name
+            if ((s = strchr(v, q))) *(s++) = '\0'; // null terminate value
+            ent[i + 1] = ezxml_decode(v, pe, '%'); // set value
+            ent[i + 2] = NULL; // null terminate entity list
+            if (! ezxml_ent_ok(n, ent[i + 1], ent)) { // circular reference
+                if (ent[i + 1] != v) free(ent[i + 1]);
+                ezxml_err(root, v, "circular entity declaration &%s", n);
+                break;
+            }
+            else ent[i] = n; // set entity name
+        }
+        else if (! strncmp(s, "<!ATTLIST", 9)) { // parse default attributes
+            t = s + strspn(s + 9, EZXML_WS) + 9; // skip whitespace separator
+            if (! *t) { ezxml_err(root, t, "unclosed <!ATTLIST"); break; }
+            if (*(s = t + strcspn(t, EZXML_WS ">")) == '>') continue;
+            else *s = '\0'; // null terminate tag name
+            for (i = 0; root->attr[i] && strcmp(n, root->attr[i][0]); i++);
+
+            while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') {
+                if (*(s = n + strcspn(n, EZXML_WS))) *s = '\0'; // attr name
+                else { ezxml_err(root, t, "malformed <!ATTLIST"); break; }
+
+                s += strspn(s + 1, EZXML_WS) + 1; // find next token
+                c = (strncmp(s, "CDATA", 5)) ? "*" : " "; // is it cdata?
+                if (! strncmp(s, "NOTATION", 8))
+                    s += strspn(s + 8, EZXML_WS) + 8;
+                s = (*s == '(') ? strchr(s, ')') : s + strcspn(s, EZXML_WS);
+                if (! s) { ezxml_err(root, t, "malformed <!ATTLIST"); break; }
+
+                s += strspn(s, EZXML_WS ")"); // skip white space separator
+                if (! strncmp(s, "#FIXED", 6))
+                    s += strspn(s + 6, EZXML_WS) + 6;
+                if (*s == '#') { // no default value
+                    s += strcspn(s, EZXML_WS ">") - 1;
+                    if (*c == ' ') continue; // cdata is default, nothing to do
+                    v = NULL;
+                }
+                else if ((*s == '"' || *s == '\'')  &&  // default value
+                         (s = strchr(v = s + 1, *s))) *s = '\0';
+                else { ezxml_err(root, t, "malformed <!ATTLIST"); break; }
+
+                if (! root->attr[i]) { // new tag name
+                    root->attr = (! i) ? malloc(2 * sizeof(char **))
+                                       : realloc(root->attr,
+                                                 (i + 2) * sizeof(char **));
+                    root->attr[i] = malloc(2 * sizeof(char *));
+                    root->attr[i][0] = t; // set tag name
+                    root->attr[i][1] = (char *)(root->attr[i + 1] = NULL);
+                }
+
+                for (j = 1; root->attr[i][j]; j += 3); // find end of list
+                root->attr[i] = realloc(root->attr[i],
+                                        (j + 4) * sizeof(char *));
+
+                root->attr[i][j + 3] = NULL; // null terminate list
+                root->attr[i][j + 2] = c; // is it cdata?
+                root->attr[i][j + 1] = (v) ? ezxml_decode(v, root->ent, *c)
+                                           : NULL;
+                root->attr[i][j] = n; // attribute name 
+            }
+        }
+        else if (! strncmp(s, "<!--", 4)) s = strstr(s + 4, "-->"); // comments
+        else if (! strncmp(s, "<?", 2)) { // processing instructions
+            if ((s = strstr(c = s + 2, "?>")))
+                ezxml_proc_inst(root, c, s++ - c);
+        }
+        else if (*s == '<') s = strchr(s, '>'); // skip other declarations
+        else if (*(s++) == '%' && ! root->standalone) break;
+    }
+
+    free(pe);
+    return ! *root->err;
+}
+
+// Converts a UTF-16 string to UTF-8. Returns a new string that must be freed
+// or NULL if no conversion was needed.
+char *ezxml_str2utf8(char **s, size_t *len)
+{
+    char *u;
+    size_t l = 0, sl, max = *len;
+    long c, d;
+    int b, be = (**s == '\xFE') ? 1 : (**s == '\xFF') ? 0 : -1;
+
+    if (be == -1) return NULL; // not UTF-16
+
+    u = malloc(max);
+    for (sl = 2; sl < *len - 1; sl += 2) {
+        c = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF)  //UTF-16BE
+                 : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); //UTF-16LE
+        if (c >= 0xD800 && c <= 0xDFFF && (sl += 2) < *len - 1) { // high-half
+            d = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF)
+                     : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF);
+            c = (((c & 0x3FF) << 10) | (d & 0x3FF)) + 0x10000;
+        }
+
+        while (l + 6 > max) u = realloc(u, max += EZXML_BUFSIZE);
+        if (c < 0x80) u[l++] = c; // US-ASCII subset
+        else { // multi-byte UTF-8 sequence
+            for (b = 0, d = c; d; d /= 2) b++; // bits in c
+            b = (b - 2) / 5; // bytes in payload
+            u[l++] = (0xFF << (7 - b)) | (c >> (6 * b)); // head
+            while (b) u[l++] = 0x80 | ((c >> (6 * --b)) & 0x3F); // payload
+        }
+    }
+    return *s = realloc(u, *len = l);
+}
+
+// frees a tag attribute list
+void ezxml_free_attr(char **attr) {
+    int i = 0;
+    char *m;
+    
+    if (! attr || attr == EZXML_NIL) return; // nothing to free
+    while (attr[i]) i += 2; // find end of attribute list
+    m = attr[i + 1]; // list of which names and values are malloced
+    for (i = 0; m[i]; i++) {
+        if (m[i] & EZXML_NAMEM) free(attr[i * 2]);
+        if (m[i] & EZXML_TXTM) free(attr[(i * 2) + 1]);
+    }
+    free(m);
+    free(attr);
+}
+
+// parse the given xml string and return an ezxml structure
+ezxml_t ezxml_parse_str(char *s, size_t len)
+{
+    ezxml_root_t root = (ezxml_root_t)ezxml_new(NULL);
+    char q, e, *d, **attr, **a = NULL; // initialize a to avoid compile warning
+    int l, i, j;
+
+    root->m = s;
+    if (! len) return ezxml_err(root, NULL, "root tag missing");
+    root->u = ezxml_str2utf8(&s, &len); // convert utf-16 to utf-8
+    root->e = (root->s = s) + len; // record start and end of work area
+    
+    e = s[len - 1]; // save end char
+    s[len - 1] = '\0'; // turn end char into null terminator
+
+    while (*s && *s != '<') s++; // find first tag
+    if (! *s) return ezxml_err(root, s, "root tag missing");
+
+    for (; ; ) {
+        attr = (char **)EZXML_NIL;
+        d = ++s;
+        
+        if (isalpha(*s) || *s == '_' || *s == ':' || *s < '\0') { // new tag
+            if (! root->cur)
+                return ezxml_err(root, d, "markup outside of root element");
+
+            s += strcspn(s, EZXML_WS "/>");
+            while (isspace(*s)) *(s++) = '\0'; // null terminate tag name
+  
+            if (*s && *s != '/' && *s != '>') // find tag in default attr list
+                for (i = 0; (a = root->attr[i]) && strcmp(a[0], d); i++);
+
+            for (l = 0; *s && *s != '/' && *s != '>'; l += 2) { // new attrib
+                attr = (l) ? realloc(attr, (l + 4) * sizeof(char *))
+                           : malloc(4 * sizeof(char *)); // allocate space
+                attr[l + 3] = (l) ? realloc(attr[l + 1], (l / 2) + 2)
+                                  : malloc(2); // mem for list of maloced vals
+                strcpy(attr[l + 3] + (l / 2), " "); // value is not malloced
+                attr[l + 2] = NULL; // null terminate list
+                attr[l + 1] = ""; // temporary attribute value
+                attr[l] = s; // set attribute name
+
+                s += strcspn(s, EZXML_WS "=/>");
+                if (*s == '=' || isspace(*s)) { 
+                    *(s++) = '\0'; // null terminate tag attribute name
+                    q = *(s += strspn(s, EZXML_WS "="));
+                    if (q == '"' || q == '\'') { // attribute value
+                        attr[l + 1] = ++s;
+                        while (*s && *s != q) s++;
+                        if (*s) *(s++) = '\0'; // null terminate attribute val
+                        else {
+                            ezxml_free_attr(attr);
+                            return ezxml_err(root, d, "missing %c", q);
+                        }
+
+                        for (j = 1; a && a[j] && strcmp(a[j], attr[l]); j +=3);
+                        attr[l + 1] = ezxml_decode(attr[l + 1], root->ent, (a
+                                                   && a[j]) ? *a[j + 2] : ' ');
+                        if (attr[l + 1] < d || attr[l + 1] > s)
+                            attr[l + 3][l / 2] = EZXML_TXTM; // value malloced
+                    }
+                }
+                while (isspace(*s)) s++;
+            }
+
+            if (*s == '/') { // self closing tag
+                *(s++) = '\0';
+                if ((*s && *s != '>') || (! *s && e != '>')) {
+                    if (l) ezxml_free_attr(attr);
+                    return ezxml_err(root, d, "missing >");
+                }
+                ezxml_open_tag(root, d, attr);
+                ezxml_close_tag(root, d, s);
+            }
+            else if ((q = *s) == '>' || (! *s && e == '>')) { // open tag
+                *s = '\0'; // temporarily null terminate tag name
+                ezxml_open_tag(root, d, attr);
+                *s = q;
+            }
+            else {
+                if (l) ezxml_free_attr(attr);
+                return ezxml_err(root, d, "missing >"); 
+            }
+        }
+        else if (*s == '/') { // close tag
+            s += strcspn(d = s + 1, EZXML_WS ">") + 1;
+            if (! (q = *s) && e != '>') return ezxml_err(root, d, "missing >");
+            *s = '\0'; // temporarily null terminate tag name
+            if (ezxml_close_tag(root, d, s)) return &root->xml;
+            if (isspace(*s = q)) s += strspn(s, EZXML_WS);
+        }
+        else if (! strncmp(s, "!--", 3)) { // xml comment
+            if (! (s = strstr(s + 3, "--")) || (*(s += 2) != '>' && *s) ||
+                (! *s && e != '>')) return ezxml_err(root, d, "unclosed <!--");
+        }
+        else if (! strncmp(s, "![CDATA[", 8)) { // cdata
+            if ((s = strstr(s, "]]>")))
+                ezxml_char_content(root, d + 8, (s += 2) - d - 10, 'c');
+            else return ezxml_err(root, d, "unclosed <![CDATA[");
+        }
+        else if (! strncmp(s, "!DOCTYPE", 8)) { // dtd
+            for (l = 0; *s && ((! l && *s != '>') || (l && (*s != ']' || 
+                 *(s + strspn(s + 1, EZXML_WS) + 1) != '>')));
+                 l = (*s == '[') ? 1 : l) s += strcspn(s + 1, "[]>") + 1;
+            if (! *s && e != '>')
+                return ezxml_err(root, d, "unclosed <!DOCTYPE");
+            d = (l) ? strchr(d, '[') + 1 : d;
+            if (l && ! ezxml_internal_dtd(root, d, s++ - d)) return &root->xml;
+        }
+        else if (*s == '?') { // <?...?> processing instructions
+            do { s = strchr(s, '?'); } while (s && *(++s) && *s != '>');
+            if (! s || (! *s && e != '>')) 
+                return ezxml_err(root, d, "unclosed <?");
+            else ezxml_proc_inst(root, d + 1, s - d - 2);
+        }
+        else return ezxml_err(root, d, "unexpected <");
+        
+        if (! s || ! *s) break;
+        *s = '\0';
+        d = ++s;
+        if (*s && *s != '<') { // tag character content
+            while (*s && *s != '<') s++;
+            if (*s) ezxml_char_content(root, d, s - d, '&');
+            else break;
+        }
+        else if (! *s) break;
+    }
+
+    if (! root->cur) return &root->xml;
+    else if (! root->cur->name) return ezxml_err(root, d, "root tag missing");
+    else return ezxml_err(root, d, "unclosed tag <%s>", root->cur->name);
+}
+
+// Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire
+// stream into memory and then parses it. For xml files, use ezxml_parse_file()
+// or ezxml_parse_fd()
+#if 0
+ezxml_t ezxml_parse_fp(FILE *fp)
+{
+    ezxml_root_t root;
+    size_t l, len = 0;
+    char *s;
+
+    if (! (s = malloc(EZXML_BUFSIZE))) return NULL;
+    do {
+        len += (l = fread((s + len), 1, EZXML_BUFSIZE, fp));
+        if (l == EZXML_BUFSIZE) s = realloc(s, len + EZXML_BUFSIZE);
+    } while (s && l == EZXML_BUFSIZE);
+
+    if (! s) return NULL;
+    root = (ezxml_root_t)ezxml_parse_str(s, len);
+    root->len = -1; // so we know to free s in ezxml_free()
+    return &root->xml;
+}
+#endif
+
+// A wrapper for ezxml_parse_str() that accepts a file descriptor. First
+// attempts to mem map the file. Failing that, reads the file into memory.
+// Returns NULL on failure.
+ezxml_t ezxml_parse_fd(FILE *fd )
+{
+    ezxml_root_t root;
+    struct stat st;
+    size_t l;
+    void *m;
+    int err;
+    mm_segment_t fs; 
+    loff_t pos; 
+
+    if (!fd || !fd->f_op || !fd->f_op->read)
+    {
+        printk("WARNING: File (read) object is a null pointer!!!\n");
+        return NULL;
+    }
+   
+    err = vfs_getattr(fd->f_vfsmnt,fd->f_dentry,&st);
+    if(err)
+    {
+        printk("can't get state of file err=%d\n",err);
+        return NULL;
+    }    
+     
+    m = malloc(st.size);
+    fs = get_fs();
+    set_fs(KERNEL_DS);
+    pos = 0;
+    l = vfs_read(fd, m, st.size, &pos);
+    set_fs(fs);
+    //l = read(fd, m , st.size);
+
+    root = (ezxml_root_t)ezxml_parse_str(m, l);
+   
+    root->len = -1; // so we know to free s in ezxml_free()
+    return &root->xml;
+}
+
+// a wrapper for ezxml_parse_fd that accepts a file name
+ezxml_t ezxml_parse_file(char *name)
+{
+    FILE *fd = filp_open(name, O_RDONLY, 0);
+	ezxml_t xml;
+
+    if (IS_ERR(fd))
+        return NULL;
+     
+    xml = ezxml_parse_fd(fd);
+  
+    if (fd >= 0) filp_close(fd, 0);
+    return xml;
+}
+
+// Encodes ampersand sequences appending the results to *dst, reallocating *dst
+// if length excedes max. a is non-zero for attribute encoding. Returns *dst
+char *ezxml_ampencode(const char *s, size_t len, char **dst, size_t *dlen,
+                      size_t *max, short a)
+{
+    const char *e;
+    
+    for (e = s + len; s != e; s++) {
+        while (*dlen + 10 > *max) *dst = realloc(*dst, *max += EZXML_BUFSIZE);
+
+        switch (*s) {
+        case '\0': return *dst;
+        case '&': *dlen += sprintf(*dst + *dlen, "&amp;"); break;
+        case '<': *dlen += sprintf(*dst + *dlen, "&lt;"); break;
+        case '>': *dlen += sprintf(*dst + *dlen, "&gt;"); break;
+        case '"': *dlen += sprintf(*dst + *dlen, (a) ? "&quot;" : "\""); break;
+        case '\n': *dlen += sprintf(*dst + *dlen, (a) ? "&#xA;" : "\n"); break;
+        case '\t': *dlen += sprintf(*dst + *dlen, (a) ? "&#x9;" : "\t"); break;
+        case '\r': *dlen += sprintf(*dst + *dlen, "&#xD;"); break;
+        default: (*dst)[(*dlen)++] = *s;
+        }
+    }
+    return *dst;
+}
+
+// Recursively converts each tag to xml appending it to *s. Reallocates *s if
+// its length excedes max. start is the location of the previous tag in the
+// parent tag's character content. Returns *s.
+char *ezxml_toxml_r(ezxml_t xml, char **s, size_t *len, size_t *max,
+                    size_t start, char ***attr)
+{
+    int i, j;
+    char *txt = (xml->parent) ? xml->parent->txt : "";
+    size_t off = 0;
+
+    // parent character content up to this tag
+    *s = ezxml_ampencode(txt + start, xml->off - start, s, len, max, 0);
+
+    while (*len + strlen(xml->name) + 4 > *max) // reallocate s
+        *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+    *len += sprintf(*s + *len, "<%s", xml->name); // open tag
+    for (i = 0; xml->attr[i]; i += 2) { // tag attributes
+        if (ezxml_attr(xml, xml->attr[i]) != xml->attr[i + 1]) continue;
+        while (*len + strlen(xml->attr[i]) + 7 > *max) // reallocate s
+            *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+        *len += sprintf(*s + *len, " %s=\"", xml->attr[i]);
+        ezxml_ampencode(xml->attr[i + 1], -1, s, len, max, 1);
+        *len += sprintf(*s + *len, "\"");
+    }
+
+    for (i = 0; attr[i] && strcmp(attr[i][0], xml->name); i++);
+    for (j = 1; attr[i] && attr[i][j]; j += 3) { // default attributes
+        if (! attr[i][j + 1] || ezxml_attr(xml, attr[i][j]) != attr[i][j + 1])
+            continue; // skip duplicates and non-values
+        while (*len + strlen(attr[i][j]) + 7 > *max) // reallocate s
+            *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+        *len += sprintf(*s + *len, " %s=\"", attr[i][j]);
+        ezxml_ampencode(attr[i][j + 1], -1, s, len, max, 1);
+        *len += sprintf(*s + *len, "\"");
+    }
+    *len += sprintf(*s + *len, ">");
+
+    *s = (xml->child) ? ezxml_toxml_r(xml->child, s, len, max, 0, attr) //child
+                      : ezxml_ampencode(xml->txt, -1, s, len, max, 0);  //data
+    
+    while (*len + strlen(xml->name) + 4 > *max) // reallocate s
+        *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+    *len += sprintf(*s + *len, "</%s>", xml->name); // close tag
+
+    while (txt[off] && off < xml->off) off++; // make sure off is within bounds
+    return (xml->ordered) ? ezxml_toxml_r(xml->ordered, s, len, max, off, attr)
+                          : ezxml_ampencode(txt + off, -1, s, len, max, 0);
+}
+
+// Converts an ezxml structure back to xml. Returns a string of xml data that
+// must be freed.
+char *ezxml_toxml(ezxml_t xml)
+{
+    ezxml_t p = (xml) ? xml->parent : NULL, o = (xml) ? xml->ordered : NULL;
+    ezxml_root_t root = (ezxml_root_t)xml;
+    size_t len = 0, max = EZXML_BUFSIZE;
+    char *s = strcpy(malloc(max), ""), *t, *n;
+    int i, j, k;
+
+    if (! xml || ! xml->name) return realloc(s, len + 1);
+    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag
+
+    for (i = 0; ! p && root->pi[i]; i++) { // pre-root processing instructions
+        for (k = 2; root->pi[i][k - 1]; k++);
+        for (j = 1; (n = root->pi[i][j]); j++) {
+            if (root->pi[i][k][j - 1] == '>') continue; // not pre-root
+            while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max)
+                s = realloc(s, max += EZXML_BUFSIZE);
+            len += sprintf(s + len, "<?%s%s%s?>\n", t, *n ? " " : "", n);
+        }
+    }
+
+    xml->parent = xml->ordered = NULL;
+    s = ezxml_toxml_r(xml, &s, &len, &max, 0, root->attr);
+    xml->parent = p;
+    xml->ordered = o;
+
+    for (i = 0; ! p && root->pi[i]; i++) { // post-root processing instructions
+        for (k = 2; root->pi[i][k - 1]; k++);
+        for (j = 1; (n = root->pi[i][j]); j++) {
+            if (root->pi[i][k][j - 1] == '<') continue; // not post-root
+            while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max)
+                s = realloc(s, max += EZXML_BUFSIZE);
+            len += sprintf(s + len, "\n<?%s%s%s?>", t, *n ? " " : "", n);
+        }
+    }
+    return realloc(s, len + 1);
+}
+
+// free the memory allocated for the ezxml structure
+void ezxml_free(ezxml_t xml)
+{
+    ezxml_root_t root = (ezxml_root_t)xml;
+    int i, j;
+    char **a, *s;
+
+    if (! xml) return;
+    ezxml_free(xml->child);
+    ezxml_free(xml->ordered);
+
+    if (! xml->parent) { // free root tag allocations
+        for (i = 10; root->ent[i]; i += 2) // 0 - 9 are default entites (<>&"')
+            if ((s = root->ent[i + 1]) < root->s || s > root->e) free(s);
+        free(root->ent); // free list of general entities
+
+        for (i = 0; (a = root->attr[i]); i++) {
+            for (j = 1; a[j++]; j += 2) // free malloced attribute values
+                if (a[j] && (a[j] < root->s || a[j] > root->e)) free(a[j]);
+            free(a);
+        }
+        if (root->attr[0]) free(root->attr); // free default attribute list
+
+        for (i = 0; root->pi[i]; i++) {
+            for (j = 1; root->pi[i][j]; j++);
+            free(root->pi[i][j + 1]);
+            free(root->pi[i]);
+        }            
+        if (root->pi[0]) free(root->pi); // free processing instructions
+
+        if (root->len == -1) free(root->m); // malloced xml data
+        if (root->u) free(root->u); // utf8 conversion
+    }
+
+    ezxml_free_attr(xml->attr); // tag attributes
+    if ((xml->flags & EZXML_TXTM)) free(xml->txt); // character content
+    if ((xml->flags & EZXML_NAMEM)) free(xml->name); // tag name
+    free(xml);
+}
+
+// return parser error message or empty string if none
+const char *ezxml_error(ezxml_t xml)
+{
+    while (xml && xml->parent) xml = xml->parent; // find root tag
+    return (xml) ? ((ezxml_root_t)xml)->err : "";
+}
+
+// returns a new empty ezxml structure with the given root tag name
+ezxml_t ezxml_new(const char *name)
+{
+    static char *ent[] = { "lt;", "&#60;", "gt;", "&#62;", "quot;", "&#34;",
+                           "apos;", "&#39;", "amp;", "&#38;", NULL };
+    ezxml_root_t root = (ezxml_root_t)memset(malloc(sizeof(struct ezxml_root)), 
+                                             '\0', sizeof(struct ezxml_root));
+    root->xml.name = (char *)name;
+    root->cur = &root->xml;
+    strcpy(root->err, root->xml.txt = "");
+    root->ent = memcpy(malloc(sizeof(ent)), ent, sizeof(ent));
+    root->attr = root->pi = (char ***)(root->xml.attr = EZXML_NIL);
+    return &root->xml;
+}
+
+// inserts an existing tag into an ezxml structure
+ezxml_t ezxml_insert(ezxml_t xml, ezxml_t dest, size_t off)
+{
+    ezxml_t cur, prev, head;
+
+    xml->next = xml->sibling = xml->ordered = NULL;
+    xml->off = off;
+    xml->parent = dest;
+
+    if ((head = dest->child)) { // already have sub tags
+        if (head->off <= off) { // not first subtag
+            for (cur = head; cur->ordered && cur->ordered->off <= off;
+                 cur = cur->ordered);
+            xml->ordered = cur->ordered;
+            cur->ordered = xml;
+        }
+        else { // first subtag
+            xml->ordered = head;
+            dest->child = xml;
+        }
+
+        for (cur = head, prev = NULL; cur && strcmp(cur->name, xml->name);
+             prev = cur, cur = cur->sibling); // find tag type
+        if (cur && cur->off <= off) { // not first of type
+            while (cur->next && cur->next->off <= off) cur = cur->next;
+            xml->next = cur->next;
+            cur->next = xml;
+        }
+        else { // first tag of this type
+            if (prev && cur) prev->sibling = cur->sibling; // remove old first
+            xml->next = cur; // old first tag is now next
+            for (cur = head, prev = NULL; cur && cur->off <= off;
+                 prev = cur, cur = cur->sibling); // new sibling insert point
+            xml->sibling = cur;
+            if (prev) prev->sibling = xml;
+        }
+    }
+    else dest->child = xml; // only sub tag
+
+    return xml;
+}
+
+// Adds a child tag. off is the offset of the child tag relative to the start
+// of the parent tag's character content. Returns the child tag.
+ezxml_t ezxml_add_child(ezxml_t xml, const char *name, size_t off)
+{
+    ezxml_t child;
+
+    if (! xml) return NULL;
+    child = (ezxml_t)memset(malloc(sizeof(struct ezxml)), '\0',
+                            sizeof(struct ezxml));
+    child->name = (char *)name;
+    child->attr = EZXML_NIL;
+    child->txt = "";
+
+    return ezxml_insert(child, xml, off);
+}
+
+// sets the character content for the given tag and returns the tag
+ezxml_t ezxml_set_txt(ezxml_t xml, const char *txt)
+{
+    if (! xml) return NULL;
+    if (xml->flags & EZXML_TXTM) free(xml->txt); // existing txt was malloced
+    xml->flags &= ~EZXML_TXTM;
+    xml->txt = (char *)txt;
+    return xml;
+}
+
+// Sets the given tag attribute or adds a new attribute if not found. A value
+// of NULL will remove the specified attribute. Returns the tag given.
+ezxml_t ezxml_set_attr(ezxml_t xml, const char *name, const char *value)
+{
+    int l = 0, c;
+
+    if (! xml) return NULL;
+    while (xml->attr[l] && strcmp(xml->attr[l], name)) l += 2;
+    if (! xml->attr[l]) { // not found, add as new attribute
+        if (! value) return xml; // nothing to do
+        if (xml->attr == EZXML_NIL) { // first attribute
+            xml->attr = malloc(4 * sizeof(char *));
+            xml->attr[1] = strdup(""); // empty list of malloced names/vals
+        }
+        else xml->attr = realloc(xml->attr, (l + 4) * sizeof(char *));
+
+        xml->attr[l] = (char *)name; // set attribute name
+        xml->attr[l + 2] = NULL; // null terminate attribute list
+        xml->attr[l + 3] = realloc(xml->attr[l + 1],
+                                   (c = strlen(xml->attr[l + 1])) + 2);
+        strcpy(xml->attr[l + 3] + c, " "); // set name/value as not malloced
+        if (xml->flags & EZXML_DUP) xml->attr[l + 3][c] = EZXML_NAMEM;
+    }
+    else if (xml->flags & EZXML_DUP) free((char *)name); // name was strduped
+
+    for (c = l; xml->attr[c]; c += 2); // find end of attribute list
+    if (xml->attr[c + 1][l / 2] & EZXML_TXTM) free(xml->attr[l + 1]); //old val
+    if (xml->flags & EZXML_DUP) xml->attr[c + 1][l / 2] |= EZXML_TXTM;
+    else xml->attr[c + 1][l / 2] &= ~EZXML_TXTM;
+
+    if (value) xml->attr[l + 1] = (char *)value; // set attribute value
+    else { // remove attribute
+        if (xml->attr[c + 1][l / 2] & EZXML_NAMEM) free(xml->attr[l]);
+        memmove(xml->attr + l, xml->attr + l + 2, (c - l + 2) * sizeof(char*));
+        xml->attr = realloc(xml->attr, (c + 2) * sizeof(char *));
+        memmove(xml->attr[c + 1] + (l / 2), xml->attr[c + 1] + (l / 2) + 1,
+                (c / 2) - (l / 2)); // fix list of which name/vals are malloced
+    }
+    xml->flags &= ~EZXML_DUP; // clear strdup() flag
+    return xml;
+}
+
+// sets a flag for the given tag and returns the tag
+ezxml_t ezxml_set_flag(ezxml_t xml, short flag)
+{
+    if (xml) xml->flags |= flag;
+    return xml;
+}
+
+// removes a tag along with its subtags without freeing its memory
+ezxml_t ezxml_cut(ezxml_t xml)
+{
+    ezxml_t cur;
+
+    if (! xml) return NULL; // nothing to do
+    if (xml->next) xml->next->sibling = xml->sibling; // patch sibling list
+
+    if (xml->parent) { // not root tag
+        cur = xml->parent->child; // find head of subtag list
+        if (cur == xml) xml->parent->child = xml->ordered; // first subtag
+        else { // not first subtag
+            while (cur->ordered != xml) cur = cur->ordered;
+            cur->ordered = cur->ordered->ordered; // patch ordered list
+
+            cur = xml->parent->child; // go back to head of subtag list
+            if (strcmp(cur->name, xml->name)) { // not in first sibling list
+                while (strcmp(cur->sibling->name, xml->name))
+                    cur = cur->sibling;
+                if (cur->sibling == xml) { // first of a sibling list
+                    cur->sibling = (xml->next) ? xml->next
+                                               : cur->sibling->sibling;
+                }
+                else cur = cur->sibling; // not first of a sibling list
+            }
+
+            while (cur->next && cur->next != xml) cur = cur->next;
+            if (cur->next) cur->next = cur->next->next; // patch next list
+        }        
+    }
+    xml->ordered = xml->sibling = xml->next = NULL;
+    return xml;
+}
+
+void* ezxml_realloc(void *p, size_t new_size)
+{
+	void    *ret;
+    size_t  ks = 0;
+
+	if (!new_size)
+        return NULL;
+
+    if (p)
+        ks = ksize(p);
+
+    if (ks < new_size) {
+        ret = malloc(new_size);
+        if (ret && p)
+        {
+            memcpy(ret, p, new_size);
+            free(p); 
+        }
+    }
+    else
+        ret = p;
+
+	return ret;
+} 
+
+#if 0 /* Example */
+E_ErrorCodes        startupCFGModuleInit(void)
+{
+    ezxml_t xml;
+    ezxml_t xmlHead;
+    ezxml_t xmlElement;
+    ezxml_t xmlElement1;
+    ezxml_t xmlElement_childLoop;
+    
+   
+   
+    xmlHead = ezxml_parse_file();
+    xml = xmlHead;
+
+     
+    /*simple get child value example*/
+    xmlElement = ezxml_child(xml, "board_type");
+    if (xmlElement) {
+        printf("%s tag value  = %s\n",xmlElement->name, xmlElement->txt); 
+    }
+    else{
+        printf("board_type tag was not found\n");
+        xml = xmlHead;
+    }
+
+    /*get consecutive child value example*/
+    xmlElement = ezxml_child(xml, "IP_host_supported");
+    if (xmlElement) {
+        printf("%s tag value  = %s\n",xmlElement->name, xmlElement->txt); 
+    }
+    else{
+        xml = xmlHead;
+        printf("IP_host_supported tag was not found\n");
+        
+    }
+
+    xml = xmlHead;
+    /*get consecutive child attribute example, return the first occurance of this tag*/
+    xmlElement = ezxml_get(xml,"port_init",0,"pots_ports",-1 );
+    if (xmlElement) {
+        printf("%s tag id attribute = %s\n",xmlElement->name,xmlElement->txt); 
+    }
+    else{
+        xml = xmlHead;
+        printf("No pots_ports tag was found\n");
+    }
+
+ 
+    /*get size attribute of the first queue from the second TCONT*/
+    xmlElement = ezxml_get(xml,"port_init",0,"TCONT_parameters",0, "TCONT",1,"queue_map",0,"queue",-1 );
+    if (xmlElement) {
+        printf("Second TCONCT, first %s tag size attribute = %s\n",xmlElement->name, ezxml_attr(xmlElement, "size")); 
+    }
+    else{
+        xml = xmlHead;
+        printf("The first queue from the second TCONT tag was not found\n");
+    }
+
+    /*point the the next occurance of this tag since xml propoagte internally*/
+    xmlElement = xmlElement->next;
+    if (xmlElement) {
+        printf("Second TCONCT, second %s tag weight attribute = %s\n",xmlElement->name, ezxml_attr(xmlElement, "weight")); 
+    }
+    else{
+        xml = xmlHead;
+        printf("Next queue tag was not found\n");
+    }
+
+  /*get speed attribute of the first ethernet */
+    xml = xmlHead;
+    xmlElement = ezxml_get(xml,"port_init",0,"Ethernet_parameters",0,"Ethernet",-1 );
+    if (xmlElement) {
+        printf("First ethernet %s tag speed attribute = %s\n",xmlElement->name, ezxml_attr(xmlElement, "speed")); 
+    }
+    else{
+        xml = xmlHead;
+        printf("The first ethernet tag was not found\n");
+    }
+    /*loop on all ethernets and get attributes*/
+    /*first set pointer to top of the XML tree*/
+    xml = xmlHead;
+    /*second set pointer to top of the relative hierarcy*/
+    xml = ezxml_get(xml,"port_init",0,"Ethernet_parameters",-1 );
+    for (xmlElement = ezxml_child(xml, "Ethernet"); xmlElement; xmlElement = xmlElement->next) {
+         printf("%s tag switch_port attribute = %s\n",xmlElement->name, ezxml_attr(xmlElement, "switch_port")); 
+        }
+   
+    
+    /*loop on all TCONT & queues and get attributes*/
+    /*first set pointer to top of the XML tree*/
+    xml = xmlHead;
+    /*second set pointer to top of the relative hierarcy*/
+    xml = ezxml_get(xml,"port_init",0,"TCONT_parameters",-1 );
+    for (xmlElement = ezxml_child(xml, "TCONT"); xmlElement; xmlElement = xmlElement->next) {
+         printf("%s tag id attribute = %s\n",xmlElement->name, ezxml_attr(xmlElement, "id")); 
+         xmlElement1 = ezxml_child(xmlElement, "scheduler_method"); 
+         printf("%s tag value  = %s\n",xmlElement1->name, xmlElement1->txt); 
+         xmlElement1 = ezxml_child(xmlElement, "queue_map");
+         for (xmlElement_childLoop = ezxml_child(xmlElement1, "queue"); xmlElement_childLoop; xmlElement_childLoop = xmlElement_childLoop->next){
+              printf("%s tag weight attribute = %s\n",xmlElement_childLoop->name, ezxml_attr(xmlElement_childLoop, "weight")); 
+        }
+
+    }
+    ezxml_free(xmlHead); 
+    return (IAMBA_OK);
+}
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/ezxml.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/ezxml.h
new file mode 100755
index 0000000..1eac50f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_ezxml/ezxml.h
@@ -0,0 +1,169 @@
+/* ezxml.h

+ *

+ * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org>

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining

+ * a copy of this software and associated documentation files (the

+ * "Software"), to deal in the Software without restriction, including

+ * without limitation the rights to use, copy, modify, merge, publish,

+ * distribute, sublicense, and/or sell copies of the Software, and to

+ * permit persons to whom the Software is furnished to do so, subject to

+ * the following conditions:

+ *

+ * The above copyright notice and this permission notice shall be included

+ * in all copies or substantial portions of the Software.

+ *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,

+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY

+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,

+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE

+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ */

+

+#ifndef _EZXML_H

+#define _EZXML_H

+

+

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#define EZXML_BUFSIZE 1024 // size of internal memory buffers

+#define EZXML_NAMEM   0x80 // name is malloced

+#define EZXML_TXTM    0x40 // txt is malloced

+#define EZXML_DUP     0x20 // attribute name and value are strduped

+

+typedef struct file FILE;

+

+typedef struct ezxml *ezxml_t;

+struct ezxml {

+    char *name;      // tag name

+    char **attr;     // tag attributes { name, value, name, value, ... NULL }

+    char *txt;       // tag character content, empty string if none

+    size_t off;      // tag offset from start of parent tag character content

+    ezxml_t next;    // next tag with same name in this section at this depth

+    ezxml_t sibling; // next tag with different name in same section and depth

+    ezxml_t ordered; // next tag, same section and depth, in original order

+    ezxml_t child;   // head of sub tag list, NULL if none

+    ezxml_t parent;  // parent tag, NULL if current tag is root tag

+    short flags;     // additional information

+};

+

+// Given a string of xml data and its length, parses it and creates an ezxml

+// structure. For efficiency, modifies the data by adding null terminators

+// and decoding ampersand sequences. If you don't want this, copy the data and

+// pass in the copy. Returns NULL on failure.

+ezxml_t ezxml_parse_str(char *s, size_t len);

+

+

+ezxml_t ezxml_parse_file( char *file);

+#ifdef EZXML_TEST

+// A wrapper for ezxml_parse_str() that accepts a file descriptor. First

+// attempts to mem map the file. Failing that, reads the file into memory.

+// Returns NULL on failure.

+ezxml_t ezxml_parse_fd(int fd);

+

+// a wrapper for ezxml_parse_fd() that accepts a file name

+    

+// Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire

+// stream into memory and then parses it. For xml files, use ezxml_parse_file()

+// or ezxml_parse_fd()

+ezxml_t ezxml_parse_fp(FILE *fp);

+#endif

+

+// returns the first child tag (one level deeper) with the given name or NULL

+// if not found

+ezxml_t ezxml_child(ezxml_t xml, const char *name);

+

+// returns the next tag of the same name in the same section and depth or NULL

+// if not found

+#define ezxml_next(xml) ((xml) ? xml->next : NULL)

+

+// Returns the Nth tag with the same name in the same section at the same depth

+// or NULL if not found. An index of 0 returns the tag given.

+ezxml_t ezxml_idx(ezxml_t xml, int idx);

+

+// returns the name of the given tag

+#define ezxml_name(xml) ((xml) ? xml->name : NULL)

+

+// returns the given tag's character content or empty string if none

+#define ezxml_txt(xml) ((xml) ? xml->txt : "")

+

+// returns the value of the requested tag attribute, or NULL if not found

+const char *ezxml_attr(ezxml_t xml, const char *attr);

+

+// Traverses the ezxml sturcture to retrieve a specific subtag. Takes a

+// variable length list of tag names and indexes. The argument list must be

+// terminated by either an index of -1 or an empty string tag name. Example: 

+// title = ezxml_get(library, "shelf", 0, "book", 2, "title", -1);

+// This retrieves the title of the 3rd book on the 1st shelf of library.

+// Returns NULL if not found.

+ezxml_t ezxml_get(ezxml_t xml, ...);

+

+// Converts an ezxml structure back to xml. Returns a string of xml data that

+// must be freed.

+char *ezxml_toxml(ezxml_t xml);

+

+// returns a NULL terminated array of processing instructions for the given

+// target

+const char **ezxml_pi(ezxml_t xml, const char *target);

+

+// frees the memory allocated for an ezxml structure

+void ezxml_free(ezxml_t xml);

+    

+// returns parser error message or empty string if none

+const char *ezxml_error(ezxml_t xml);

+

+// returns a new empty ezxml structure with the given root tag name

+ezxml_t ezxml_new(const char *name);

+

+// wrapper for ezxml_new() that strdup()s name

+#define ezxml_new_d(name) ezxml_set_flag(ezxml_new(MMP_OS_STRDUP(name)), EZXML_NAMEM)

+

+// Adds a child tag. off is the offset of the child tag relative to the start

+// of the parent tag's character content. Returns the child tag.

+ezxml_t ezxml_add_child(ezxml_t xml, const char *name, size_t off);

+

+// wrapper for ezxml_add_child() that strdup()s name

+#define ezxml_add_child_d(xml, name, off) \

+    ezxml_set_flag(ezxml_add_child(xml, MMP_OS_STRDUP(name), off), EZXML_NAMEM)

+

+// sets the character content for the given tag and returns the tag

+ezxml_t ezxml_set_txt(ezxml_t xml, const char *txt);

+

+// wrapper for ezxml_set_txt() that strdup()s txt

+#define ezxml_set_txt_d(xml, txt) \

+    ezxml_set_flag(ezxml_set_txt(xml, MMP_OS_STRDUP(txt)), EZXML_TXTM)

+

+// Sets the given tag attribute or adds a new attribute if not found. A value

+// of NULL will remove the specified attribute. Returns the tag given.

+ezxml_t ezxml_set_attr(ezxml_t xml, const char *name, const char *value);

+

+// Wrapper for ezxml_set_attr() that strdup()s name/value. Value cannot be NULL

+#define ezxml_set_attr_d(xml, name, value) \

+    ezxml_set_attr(ezxml_set_flag(xml, EZXML_DUP), MMP_OS_STRDUP(name), MMP_OS_STRDUP(value))

+

+// sets a flag for the given tag and returns the tag

+ezxml_t ezxml_set_flag(ezxml_t xml, short flag);

+

+// removes a tag along with its subtags without freeing its memory

+ezxml_t ezxml_cut(ezxml_t xml);

+

+// inserts an existing tag into an ezxml structure

+ezxml_t ezxml_insert(ezxml_t xml, ezxml_t dest, size_t off);

+

+// Moves an existing tag to become a subtag of dest at the given offset from

+// the start of dest's character content. Returns the moved tag.

+#define ezxml_move(xml, dest, off) ezxml_insert(ezxml_cut(xml), dest, off)

+

+// removes a tag along with all its subtags

+#define ezxml_remove(xml) ezxml_free(ezxml_cut(xml))

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // _EZXML_H

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_gpio/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_gpio/Makefile
new file mode 100755
index 0000000..bbca51a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_gpio/Makefile
@@ -0,0 +1,8 @@
+#

+# Makefile for the Marvell GPIO Driver

+#

+ ifeq ($(CONFIG_ARCH_FEROCEON),y)

+	include $(srctree)/$(MACHINE)/config/mvRules.mk

+endif

+

+obj-y += mv_gpio.o

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_gpio/mv_gpio.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_gpio/mv_gpio.c
new file mode 100755
index 0000000..1d92103
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_gpio/mv_gpio.c
@@ -0,0 +1,160 @@
+/*
+ * arch/arm/plat-feroceon/mv_drivers_lsp/mv_gpio/mv_gpio.c
+ *
+ * Marvell Feroceon SoC GPIO handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "gpp/mvGpp.h"
+#include "gpp/mvGppRegs.h"
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+static inline void __set_direction(unsigned pin, int input)
+{
+	u32 grp = pin >> 5;
+	u32 mask = (1 << (pin & 0x1F));
+
+	if (input)
+		mvGppTypeSet(grp, mask, MV_GPP_IN & mask);
+	else
+		mvGppTypeSet(grp, mask, MV_GPP_OUT & mask);
+}
+
+static void __set_level(unsigned pin, int high)
+{
+	u32 grp = pin >> 5;
+	u32 mask = (1 << (pin & 0x1F));
+
+	if (high)
+		mvGppValueSet (grp, mask, mask);
+	else
+		mvGppValueSet (grp, mask, 0);
+}
+
+static inline void __set_blinking(unsigned pin, int blink)
+{
+	u32 grp = pin >> 5;
+	u32 mask = (1 << (pin & 0x1F));
+
+	if (blink)
+		mvGppBlinkEn(grp, mask, mask);
+	else
+		mvGppBlinkEn(grp, mask, 0);
+}
+
+static inline int mv_gpio_is_valid(unsigned pin, int mode)
+{
+	return true;
+}
+
+/*
+ * GENERIC_GPIO primitives.
+ */
+static int mv_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
+{
+	unsigned long flags;
+
+	if (!mv_gpio_is_valid(pin, GPIO_INPUT_OK))
+		return -EINVAL;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	/* Configure GPIO direction. */
+	__set_direction(pin, 1);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	return 0;
+}
+
+static int mv_gpio_get_value(struct gpio_chip *chip, unsigned pin)
+{
+	u32 val;
+	u32 grp = pin >> 5;
+	u32 mask = (1 << (pin & 0x1F));
+
+	if (MV_REG_READ(GPP_DATA_OUT_EN_REG(grp)) & mask)
+		val = mvGppValueGet(grp, mask) ^ mvGppPolarityGet(grp, mask);
+	else
+		val = MV_REG_READ(GPP_DATA_OUT_REG(grp));
+
+	return (val >> (pin & 31)) & 1;
+}
+
+static int mv_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	unsigned long flags;
+
+	if (!mv_gpio_is_valid(pin, GPIO_OUTPUT_OK))
+		return -EINVAL;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	/* Disable blinking. */
+	__set_blinking(pin, 0);
+
+	/* Configure GPIO output value. */
+	__set_level(pin, value);
+
+	/* Configure GPIO direction. */
+	__set_direction(pin, 0);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	return 0;
+}
+
+static void mv_gpio_set_value(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	/* Configure GPIO output value. */
+	__set_level(pin, value);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+}
+
+static int mv_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	if (mv_gpio_is_valid(pin, GPIO_INPUT_OK) ||
+	    mv_gpio_is_valid(pin, GPIO_OUTPUT_OK))
+		return 0;
+	return -EINVAL;
+}
+
+static struct gpio_chip mv_gpiochip = {
+	.label			= "mv_gpio",
+	.direction_input	= mv_gpio_direction_input,
+	.get			= mv_gpio_get_value,
+	.direction_output	= mv_gpio_direction_output,
+	.set			= mv_gpio_set_value,
+	.request		= mv_gpio_request,
+	.base			= 0,
+	.ngpio			= MV_GPP_MAX_PINS,
+	.can_sleep		= 0,
+};
+
+void __init mv_gpio_init(void)
+{
+	gpiochip_add(&mv_gpiochip);
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/Kconfig
new file mode 100755
index 0000000..d976694
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/Kconfig
@@ -0,0 +1,9 @@
+menu "SoC MAC learning support"
+depends on MV_INCLUDE_TPM
+
+config  MV_MAC_LEARN
+	bool "Support for MAC learning through PnC"
+      	default n
+	---help---
+
+endmenu
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/Makefile
new file mode 100755
index 0000000..26d5bd7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the Marvell MAC learn module
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifdef CONFIG_MV_HAL_RULES_PATH
+include $(srctree)/include/config/auto.conf
+include $(srctree)/$(subst ",,$(CONFIG_MV_HAL_RULES_PATH))
+endif
+
+MAC_LEARN_OBJS += mv_mac_learn_mod.o \
+		  mv_mac_learn_netdev.o \
+		  mv_mac_learn_logic.o \
+		  mv_mac_learn_db.o \
+		  mv_mac_learn_api.o \
+		  mv_mac_learn_sysfs.o
+
+mv_mac_learn-objs := $(MAC_LEARN_OBJS)
+obj-$(CONFIG_MV_MAC_LEARN) += mv_mac_learn.o
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.c
new file mode 100755
index 0000000..aa904f7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.c
@@ -0,0 +1,284 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_api.c
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+#include "mv_mac_learn_header.h"
+
+/***********************************************************
+* mv_mac_learn_static_entry_add
+* API for adding static learn entry
+* input:
+*	static_mac_addr: source MAC address
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+***********************************************************/
+int32_t mv_mac_learn_static_entry_add(char *static_mac_addr)
+{
+	int32_t ret;
+
+	ret = mv_mac_learn_logic_static_add(static_mac_addr);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn static entry adding failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_static_entry_add);
+
+/***********************************************************
+* mv_mac_learn_static_entry_del
+* API for del static learn entry
+* input:
+*	static_mac_addr: source MAC address
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_static_entry_del(char *static_mac_addr)
+{
+	int32_t ret;
+
+	ret = mv_mac_learn_logic_static_del(static_mac_addr);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn static entry del failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_static_entry_del);
+
+/***********************************************************
+* mv_mac_learn_enable_set
+* API for set MAC leaning enable state
+* input:
+*	enable: enable state, true: enable, false: disable
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_enable_set(bool enable)
+{
+	int32_t ret;
+
+	ret = mv_mac_learn_op_enable_set(enable);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn enable operation failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_enable_set);
+
+/***********************************************************
+* mv_mac_learn_enable_get
+* API for get MAC leaning enable state
+* output:
+*	enable: enable state, true: enable, false: disable
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_enable_get(bool *enable)
+{
+	int32_t ret;
+
+	ret = mv_mac_learn_op_enable_get(enable);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn enable operation failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_enable_get);
+
+/***********************************************************
+* mv_mac_learn_overwrite_enable_set
+* API for set MAC leaning overwrite enable state if FDB is full
+* input:
+*	enable: enable state, true: enable, false: disable
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_overwrite_enable_set(bool enable)
+{
+	int32_t ret;
+
+	ret = mv_mac_learn_op_overwrite_set(enable);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn overwrite enable operation failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_overwrite_enable_set);
+
+/***********************************************************
+* mv_mac_learn_overwrite_enable_get
+* API for get MAC leaning overwrite enable state
+* output:
+*	enable: enable state, true: enable, false: disable
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_overwrite_enable_get(bool *enable)
+{
+	int32_t ret;
+
+	ret = mv_mac_learn_op_overwrite_get(enable);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn overwrite enable operation failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_overwrite_enable_get);
+
+/***********************************************************
+* mv_mac_learn_max_count_set
+* API for set MAX count of MAC learning entry supported
+* input:
+*	max_count: max count
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_max_count_set(uint32_t max_count)
+{
+	int32_t ret;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)) {
+		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	if (max_count > (range_conf.api_end - range_conf.api_start + 1)) {
+		MVMACLEARN_ERR_PRINT("MAC learn max count larger than PNC range size\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	if (max_count > MAC_LEARN_FDB_MAX_COUNT)
+		max_count = MAC_LEARN_FDB_MAX_COUNT;
+
+	ret = mv_mac_learn_op_max_count_set(max_count);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn max count set failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_max_count_set);
+
+/***********************************************************
+* mv_mac_learn_max_count_get
+* API for get MAX count of MAC leaning entry supported
+* output:
+*	max_count: max count
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_max_count_get(uint32_t *max_count)
+{
+	int32_t ret;
+
+	ret = mv_mac_learn_op_max_count_get(max_count);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn max count get failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_max_count_get);
+
+/***********************************************************
+* mv_mac_learn_expire_time_set
+* API for set expired time of MAC leaning non-static entry
+* input:
+*	expire_time: expire time, unit: second
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_expire_time_set(uint32_t expire_time)
+{
+	int32_t ret;
+
+	/*input check*/
+	if (expire_time == 0) {
+		MVMACLEARN_ERR_PRINT("MAC learn expire time invalid(%d)\n", expire_time);
+		return MAC_LEARN_FAIL;
+	}
+
+	ret = mv_mac_learn_op_expire_set(expire_time);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn expire time set failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_expire_time_set);
+
+/***********************************************************
+* mv_mac_learn_expire_time_get
+* API for get expired time of MAC leaning non-static entry
+* output:
+*	expire_time: expire time, unit: second
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_expire_time_get(uint32_t *expire_time)
+{
+	int32_t ret;
+
+	ret = mv_mac_learn_op_expire_get(expire_time);
+	if (ret) {
+		MVMACLEARN_ERR_PRINT("MAC learn expire time get failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+EXPORT_SYMBOL(mv_mac_learn_expire_time_get);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.h
new file mode 100755
index 0000000..9f1d9ac
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_api.h
@@ -0,0 +1,154 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_api.h
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#ifndef __mv_mac_learn_api_h__
+#define __mv_mac_learn_api_h__
+
+/* MACRO
+------------------------------------------------------------------------------*/
+#define MAC_LEARN_OK 0
+#define MAC_LEARN_FAIL 1
+
+/* Function protype
+------------------------------------------------------------------------------*/
+
+/***********************************************************
+* mv_mac_learn_static_entry_add
+* API for adding static learn entry
+* input:
+*	static_mac_addr: source MAC address
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+***********************************************************/
+int32_t mv_mac_learn_static_entry_add(char *static_mac_addr);
+
+
+/***********************************************************
+* mv_mac_learn_static_entry_del
+* API for del static learn entry
+* input:
+*	static_mac_addr: source MAC address
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_static_entry_del(char *static_mac_addr);
+
+/***********************************************************
+* mv_mac_learn_enable_set
+* API for set MAC leaning enable state
+* input:
+*	enable: enable state, true: enable, false: disable
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_enable_set(bool enable);
+
+/***********************************************************
+* mv_mac_learn_enable_get
+* API for get MAC leaning enable state
+* output:
+*	enable: enable state, true: enable, false: disable
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_enable_get(bool *enable);
+
+/***********************************************************
+* mv_mac_learn_overwrite_enable_set
+* API for set MAC leaning overwrite enable state if FDB is full
+* input:
+*	enable: enable state, true: enable, false: disable
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_overwrite_enable_set(bool enable);
+
+/***********************************************************
+* mv_mac_learn_overwrite_enable_get
+* API for get MAC leaning overwrite enable state
+* output:
+*	enable: enable state, true: enable, false: disable
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_overwrite_enable_get(bool *enable);
+
+/***********************************************************
+* mv_mac_learn_max_count_set
+* API for set MAX count of MAC learning entry supported
+* input:
+*	max_count: max count
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_max_count_set(uint32_t max_count);
+
+/***********************************************************
+* mv_mac_learn_max_count_get
+* API for get MAX count of MAC leaning entry supported
+* output:
+*	max_count: max count
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_max_count_get(uint32_t *max_count);
+
+/***********************************************************
+* mv_mac_learn_expire_time_set
+* API for set expired time of MAC leaning non-static entry
+* input:
+*	expire_time: expire time, unit: second
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_expire_time_set(uint32_t expire_time);
+
+/***********************************************************
+* mv_mac_learn_expire_time_get
+* API for get expired time of MAC leaning non-static entry
+* output:
+*	expire_time: expire time, unit: second
+* return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+************************************************************/
+int32_t mv_mac_learn_expire_time_get(uint32_t *expire_time);
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.c
new file mode 100755
index 0000000..b911039
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.c
@@ -0,0 +1,584 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_db.c
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+#include "mv_mac_learn_header.h"
+
+/*Global variable*/
+mac_learn_fdb_t mac_learn_fdb;
+
+/************************************************************************************
+*mac_learn_db_nohit_time_clear
+* clearn no hit time to 0 for all non-static entry in FDB
+*return:
+*	success--MAC_LEARN_FDB_OK
+************************************************************************************/
+int32_t mac_learn_db_nohit_time_clear(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		/*Get spin lock*/
+		spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+		if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[i].valid &&
+		    MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[i].state)
+			mac_learn_fdb.mac_learn_db_entry[i].no_hit_time = 0;
+		/* Release spin lock */
+		spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+	}
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+*mac_learn_db_reset
+* Reset FDB and delete all MAC learning PNC entry, including non-static and static
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_reset(void)
+{
+	tpm_l2_acl_key_t del_mac_key;
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+	uint32_t i;
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		/*Get spin lock*/
+		spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+		if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[i].valid) {
+			memset(&del_mac_key, 0, sizeof(tpm_l2_acl_key_t));
+			memset(del_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
+			memcpy(del_mac_key.mac.mac_sa, mac_learn_fdb.mac_learn_db_entry[i].src_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE);
+			/*Get spin lock*/
+			mac_learn_tpm_api_lock_get(MAC_LEARN_TPM_API_LOCK_DEL);
+			if (!tpm_del_mac_learn_rule(tpm_owner_id, &del_mac_key)) {
+				/* Release spin lock */
+				mac_learn_tpm_api_lock_release(MAC_LEARN_TPM_API_LOCK_DEL);
+				/*invalid FDB entry*/
+				mac_learn_fdb.mac_learn_db_entry[i].valid = MAC_LEARN_FDB_INVALID;
+				atomic_dec(&mac_learn_fdb.fdb_valid_count);
+				if (MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[i].state)
+					atomic_dec(&mac_learn_fdb.fdb_non_static_count);
+			} else {
+				MVMACLEARN_ERR_PRINT("TPM entry delete failed\n");
+				/* Release spin lock */
+				mac_learn_tpm_api_lock_release(MAC_LEARN_TPM_API_LOCK_DEL);
+				spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+
+				return MAC_LEARN_FDB_FAIL;
+			}
+		}
+		/* Release spin lock */
+		spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+	}
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+*mac_learn_db_nonstatic_clear
+* Clearn all non-static entry in PNC and FDB
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_nonstatic_clear()
+{
+	tpm_l2_acl_key_t del_mac_key;
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+	uint32_t pnc_idx = 1;
+	uint32_t i;
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		/*Get spin lock*/
+		spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+		if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[i].valid &&
+		    MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[i].state) {
+			memset(&del_mac_key, 0, sizeof(tpm_l2_acl_key_t));
+			memset(del_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
+			memcpy(del_mac_key.mac.mac_sa, mac_learn_fdb.mac_learn_db_entry[i].src_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE);
+			pnc_idx = mac_learn_fdb.mac_learn_db_entry[i].pnc_idx;
+			if (!tpm_del_mac_learn_rule(tpm_owner_id, &del_mac_key)) {
+				/*invalid FDB entry*/
+				mac_learn_fdb.mac_learn_db_entry[i].valid = MAC_LEARN_FDB_INVALID;
+				atomic_dec(&mac_learn_fdb.fdb_valid_count);
+				if (MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[i].state)
+					atomic_dec(&mac_learn_fdb.fdb_non_static_count);
+			} else {
+				MVMACLEARN_ERR_PRINT("TPM entry delete failed\n");
+				/* Release spin lock */
+				spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+
+				return MAC_LEARN_FDB_FAIL;
+			}
+		}
+		/* Release spin lock */
+		spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+		if (mac_learn_db_pncidx_update(0, pnc_idx)) {
+			MVMACLEARN_ERR_PRINT("TPM PNC index update failed(%d)\n", i);
+			return MAC_LEARN_FDB_FAIL;
+		}
+	}
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+*mac_learn_db_no_hit_time_get
+* Get no-hit time for a non-static MAC learning entry
+* input:
+*	fdb_idx: entry index in FDB
+*output:
+*	no_hit_time: no hit time, unit: second
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_no_hit_time_get(uint32_t fdb_idx, uint32_t *no_hit_time)
+{
+	spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+	if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[fdb_idx].valid) {
+		if (MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[fdb_idx].state) {
+			*no_hit_time = mac_learn_fdb.mac_learn_db_entry[fdb_idx].no_hit_time;
+
+			spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+			return MAC_LEARN_FDB_OK;
+		}
+	}
+	spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+	*no_hit_time = 0;
+
+	return MAC_LEARN_FDB_FAIL;
+}
+
+/************************************************************************************
+*mac_learn_db_no_time_clear_update_hit
+* Clear no-hit time for a non-static MAC learning entry and update its pnc hit count
+* input:
+*	fdb_idx: entry index in FDB
+*	hit_count: new pnc hit count for non-static entry
+*return:
+*	void
+************************************************************************************/
+void mac_learn_db_no_time_clear_update_hit(uint32_t fdb_idx, uint32_t hit_count)
+{
+	spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+	if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[fdb_idx].valid) {
+		if (MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[fdb_idx].state) {
+			mac_learn_fdb.mac_learn_db_entry[fdb_idx].hit_count = hit_count;
+			mac_learn_fdb.mac_learn_db_entry[fdb_idx].no_hit_time = 0;
+		}
+	}
+	spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+}
+
+/************************************************************************************
+*mac_learn_db_no_time_clear_update_hit
+* Clear no-hit time for a non-static MAC learning entry and update its pnc hit count
+* input:
+*	fdb_idx: entry index in FDB
+*	hit_count: new pnc hit count for non-static entry
+*return:
+*	void
+************************************************************************************/
+void mac_learn_db_no_hit_time_inc_read(uint32_t fdb_idx, mac_learn_db_entry_t *mac_learn_db_entry)
+{
+	spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+	if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[fdb_idx].valid) {
+		if (MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[fdb_idx].state) {
+			mac_learn_fdb.mac_learn_db_entry[fdb_idx].no_hit_time++;
+			memcpy(mac_learn_db_entry, &mac_learn_fdb.mac_learn_db_entry[fdb_idx], sizeof(mac_learn_db_entry_t));
+		}
+	}
+	spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+}
+
+/************************************************************************************
+*mac_learn_db_nonstatic_pnc_get_by_fdbidx
+* Clear no-hit time for a non-static MAC learning entry and update its pnc hit count
+* input:
+*	fdb_idx: entry index in FDB
+* output:
+*	pnc_idx: the PNC index in TCAM of MAC learning entry
+*	hit_count: current hit count of non-static entry
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_nonstatic_pnc_get_by_fdbidx(uint32_t fdb_idx, uint32_t *pnc_idx, uint32_t *hit_count)
+{
+	/* Input check */
+	if (NULL == pnc_idx || NULL == hit_count)
+		return MAC_LEARN_FDB_FAIL;
+
+	spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+	if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[fdb_idx].valid) {
+		if (MAC_LEARN_FDB_NON_STATIC == mac_learn_fdb.mac_learn_db_entry[fdb_idx].state) {
+			*pnc_idx = mac_learn_fdb.mac_learn_db_entry[fdb_idx].pnc_idx;
+			*hit_count = mac_learn_fdb.mac_learn_db_entry[fdb_idx].hit_count;
+
+			spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+			return MAC_LEARN_FDB_OK;
+		}
+	}
+	spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[fdb_idx]);
+
+	*pnc_idx = MAC_LEARN_FDB_INVALID_PNC;
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_find_mac_addr
+* Find a source MAC address exist in FDB or not, if exist return info of related entry
+* input:
+*	src_mac_key: TPM L2 key contain souce MAC address
+* output:
+*	addr_exist: Indicate the MAC exist in FDB or not; 1--exist, 0--non-exist
+*	mac_learn_db_entry: related MAC learning entry info if MAC exist
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_find_mac_addr(tpm_l2_acl_key_t *src_mac_key, int32_t *addr_exist, mac_learn_db_entry_t *mac_learn_db_entry)
+{
+	uint32_t i;
+
+	if (NULL == src_mac_key)
+		return MAC_LEARN_FDB_FAIL;
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		/*Get spin lock*/
+		spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+		if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[i].valid) {
+			if (!memcmp(src_mac_key->mac.mac_sa, mac_learn_fdb.mac_learn_db_entry[i].src_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE)) {
+				if (addr_exist)
+					*addr_exist = 1;
+				if (mac_learn_db_entry)
+					memcpy(mac_learn_db_entry, &mac_learn_fdb.mac_learn_db_entry[i], sizeof(mac_learn_db_entry_t));
+				/* Release spin lock */
+				spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+				break;
+			}
+		}
+		/* Release spin lock */
+		spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+	}
+	if (i == MAC_LEARN_FDB_MAX_COUNT) {
+		if (addr_exist)
+			*addr_exist = 0;
+	}
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_pncidx_update
+* Update PnC index when PNC entry changed in MAC learn range
+* input:
+*	rule_add: update reason; 1--rule add, 0--rule delete
+*	pnc_index: current PNC index before update
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_pncidx_update(uint8_t rule_add, uint32_t pnc_index)
+{
+	uint32_t i;
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		/*Get spin lock*/
+		spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+		if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[i].valid) {
+			if (rule_add) {
+				if (pnc_index <= mac_learn_fdb.mac_learn_db_entry[i].pnc_idx)
+					mac_learn_fdb.mac_learn_db_entry[i].pnc_idx++;
+			} else {
+				if (pnc_index < mac_learn_fdb.mac_learn_db_entry[i].pnc_idx)
+					mac_learn_fdb.mac_learn_db_entry[i].pnc_idx--;
+			}
+		}
+		/* Release spin lock */
+		spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+	}
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_free_inx_get
+* Get the free FDB entry, the first entry find in FDB
+* output:
+*	free_idx: Free FBD index find
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_free_inx_get(uint32_t *free_idx)
+{
+	uint32_t i;
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		/*Get spin lock*/
+		spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+		if (MAC_LEARN_FDB_INVALID == mac_learn_fdb.mac_learn_db_entry[i].valid) {
+			mac_learn_fdb.mac_learn_db_entry[i].valid = MAC_LEARN_FDB_RESERVED;
+			*free_idx = i;
+			/* Release spin lock */
+			spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+			break;
+		}
+		/* Release spin lock */
+		spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+	}
+
+	if(i == MAC_LEARN_FDB_MAX_COUNT) {
+		*free_idx = 0xFFFF;
+		return MAC_LEARN_FDB_FAIL;
+	}
+	else
+		return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_entry_info_by_pncidx
+* Get the info the a valid FDB entry by its PNC index
+* input:
+*	pnc_idx: PnC index of MAC learning entry
+* output:
+*	free_idx: Free FBD index find
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_entry_info_by_pncidx(uint32_t pnc_idx, uint32_t *fdb_idx, mac_learn_db_entry_t *mac_learn_db_entry)
+{
+	uint32_t i;
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		/*Get spin lock*/
+		spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+		if (MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[i].valid) {
+			if (mac_learn_fdb.mac_learn_db_entry[i].pnc_idx == pnc_idx) {
+				if (NULL != fdb_idx)
+					*fdb_idx = i;
+				if (NULL != mac_learn_db_entry)
+					memcpy(mac_learn_db_entry, &mac_learn_fdb.mac_learn_db_entry[i], sizeof(mac_learn_db_entry_t));
+				/* Release spin lock */
+				spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+				break;
+			}
+		}
+		/* Release spin lock */
+		spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+	}
+
+	if(i == MAC_LEARN_FDB_MAX_COUNT)
+		return MAC_LEARN_FDB_FAIL;
+	else
+		return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_entry_add
+* Add a new entry to FDB
+* input:
+*	mac_learn_db_entry: FDB entry to add
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_entry_add(mac_learn_db_entry_t *mac_learn_db_entry)
+{
+	uint32_t free_idx;
+	if (mac_learn_db_free_inx_get(&free_idx)) {
+		MVMACLEARN_ERR_PRINT("No Free FDB entry\n");
+		return MAC_LEARN_FDB_FAIL;
+	}
+	/*Get spin lock*/
+	spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[free_idx]);
+	memcpy(&mac_learn_fdb.mac_learn_db_entry[free_idx], mac_learn_db_entry, sizeof(mac_learn_db_entry_t));
+	/* Release spin lock */
+	spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[free_idx]);
+	/* Increase valid count */
+	atomic_inc(&mac_learn_fdb.fdb_valid_count);
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_entry_add
+* Delete an existing entry in FDB
+* input:
+*	del_idx: FDB index to delete
+*return:
+*	success--MAC_LEARN_FDB_OK
+*	failed --MAC_LEARN_FDB_FAIL
+************************************************************************************/
+int32_t mac_learn_db_entry_del(uint32_t del_idx)
+{
+	if (del_idx >= MAC_LEARN_FDB_MAX_COUNT) {
+		MVMACLEARN_ERR_PRINT("Invalid input\n");
+		return MAC_LEARN_FDB_FAIL;
+	}
+
+	/*Get spin lock*/
+	spin_lock(&mac_learn_fdb.mac_learn_db_entry_lock[del_idx]);
+	mac_learn_fdb.mac_learn_db_entry[del_idx].valid = MAC_LEARN_FDB_INVALID;
+	/* Release spin lock */
+	spin_unlock(&mac_learn_fdb.mac_learn_db_entry_lock[del_idx]);
+	/* Decrease valid count */
+	atomic_dec(&mac_learn_fdb.fdb_valid_count);
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_valid_count_get
+* Get the count of valid entry in FDB
+* output:
+*	valid_ount: valid entry count
+*return:
+*	success--MAC_LEARN_FDB_OK
+************************************************************************************/
+int32_t mac_learn_db_valid_count_get(uint32_t *valid_ount)
+{
+	*valid_ount = atomic_read(&mac_learn_fdb.fdb_valid_count);
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_nonstatic_count_inc
+* Increase count of non-static entry in FDB by 1
+*return:
+*	void
+************************************************************************************/
+void mac_learn_db_nonstatic_count_inc(void)
+{
+	atomic_inc(&mac_learn_fdb.fdb_non_static_count);
+}
+
+/************************************************************************************
+* mac_learn_db_nonstatic_count_dec
+* Decrease count of non-static entry in FDB by 1
+*return:
+*	void
+************************************************************************************/
+void mac_learn_db_nonstatic_count_dec(void)
+{
+	atomic_dec(&mac_learn_fdb.fdb_non_static_count);
+}
+
+/************************************************************************************
+* mac_learn_db_nonstatic_count_get
+* Get count of non-static entry in FDB
+*return:
+*	success--MAC_LEARN_FDB_OK
+************************************************************************************/
+int32_t mac_learn_db_nonstatic_count_get(uint32_t *nonstatic_ount)
+{
+	*nonstatic_ount = atomic_read(&mac_learn_fdb.fdb_non_static_count);
+
+	return MAC_LEARN_FDB_OK;
+}
+
+/************************************************************************************
+* mac_learn_db_valid_print
+* Print current all valid MAC learning entry in FDB
+*return:
+*	void
+************************************************************************************/
+void mac_learn_db_valid_print(void)
+{
+	uint32_t i, j;
+	char entry_state[11];
+
+	/*print header*/
+	printk("+--------------+---------------------+--------------+\n");
+	printk("+-----State----+-----Source_MAC------+---PNC_Idex---+\n");
+	printk("+--------------+---------------------+--------------+\n");
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		if(MAC_LEARN_FDB_VALID == mac_learn_fdb.mac_learn_db_entry[i].valid) {
+			if (MAC_LEARN_FDB_STATIC == mac_learn_fdb.mac_learn_db_entry[i].state)
+				strcpy(entry_state, "Static    ");
+			else
+				strcpy(entry_state, "Non-Static");
+			printk("+--%s--+--", entry_state);
+			for (j = 0; j < 6; j++)
+				printk("%2.2x ", mac_learn_fdb.mac_learn_db_entry[i].src_mac_addr[j]);
+			printk("-+------%2d------+\n", mac_learn_fdb.mac_learn_db_entry[i].pnc_idx);
+		}
+	}
+	printk("+--------------+---------------------+--------------+\n");
+}
+
+/***************************************************************************************************************
+* mac_learn_fdb_init()
+*
+* DESCRIPTION: Perform DB Initialization. Set all structures to 0, and all valid fields to MAC_LEARN_FDB_INVALID
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns MAC_LEARN_FDB_OK. On error different types are returned
+*
+* COMMENTS:
+*
+******************************************************************************************************************/
+int32_t mac_learn_fdb_init(void)
+{
+	uint32_t i;
+
+	/* Erase DB */
+	memset(&mac_learn_fdb, 0, sizeof(mac_learn_fdb_t));
+
+	/*init valid_count*/
+	atomic_set(&mac_learn_fdb.fdb_valid_count, 0);
+	atomic_set(&mac_learn_fdb.fdb_non_static_count, 0);
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		/* Invalid all FDB entry */
+		mac_learn_fdb.mac_learn_db_entry[i].valid = MAC_LEARN_FDB_INVALID;
+		/* Init Spinlock for each entry */
+		spin_lock_init(&mac_learn_fdb.mac_learn_db_entry_lock[i]);
+	}
+
+	mac_learn_fdb.mac_learn_fdb_init = true;
+
+	return MAC_LEARN_FDB_OK;
+}
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.h
new file mode 100755
index 0000000..6f31b92
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_db.h
@@ -0,0 +1,93 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_db.h
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#ifndef __mv_mac_learn_db_h__
+#define __mv_mac_learn_db_h__
+
+/* MACRO
+------------------------------------------------------------------------------*/
+#define MAC_LEARN_FDB_MAX_COUNT 32
+
+#define MAC_LEARN_FDB_OK 0
+#define MAC_LEARN_FDB_FAIL 1
+
+#define MAC_LEARN_FDB_INVALID 0xDE
+#define MAC_LEARN_FDB_VALID 0x01
+#define MAC_LEARN_FDB_RESERVED 0xCE
+
+#define MAC_LEARN_FDB_STATIC 0x0
+#define MAC_LEARN_FDB_NON_STATIC 0x1
+
+#define MAC_LEARN_FDB_INVALID_PNC 0xFFFF
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+typedef struct {
+	uint8_t valid;
+	uint8_t state;
+	uint8_t port;
+	uint8_t src_mac_addr[6];
+	uint32_t pnc_idx;
+	uint32_t hit_count;
+	uint32_t no_hit_time;/* unit:s */
+} mac_learn_db_entry_t;
+
+typedef struct {
+	bool mac_learn_fdb_init;/* indicate whether db is init or not */
+	atomic_t fdb_valid_count;
+	atomic_t fdb_non_static_count;
+	spinlock_t mac_learn_db_entry_lock[MAC_LEARN_FDB_MAX_COUNT];
+	mac_learn_db_entry_t mac_learn_db_entry[MAC_LEARN_FDB_MAX_COUNT];
+} mac_learn_fdb_t;
+
+/* Function protype
+------------------------------------------------------------------------------*/
+int32_t mac_learn_db_nohit_time_clear(void);
+int32_t mac_learn_db_reset(void);
+int32_t mac_learn_db_nonstatic_clear(void);
+int32_t mac_learn_db_no_hit_time_get(uint32_t fdb_idx, uint32_t *no_hit_time);
+void mac_learn_db_no_time_clear_update_hit(uint32_t fdb_idx, uint32_t hit_count);
+void mac_learn_db_no_hit_time_inc_read(uint32_t fdb_idx, mac_learn_db_entry_t *mac_learn_db_entry);
+int32_t mac_learn_db_nonstatic_pnc_get_by_fdbidx(uint32_t fdb_idx, uint32_t *pnc_idx, uint32_t *hit_count);
+int32_t mac_learn_db_find_mac_addr(tpm_l2_acl_key_t *src_mac_key, int32_t *addr_exist, mac_learn_db_entry_t *mac_learn_db_entry);
+int32_t mac_learn_db_pncidx_update(uint8_t rule_add, uint32_t pnc_index);
+int32_t mac_learn_db_free_inx_get(uint32_t *free_idx);
+int32_t mac_learn_db_entry_info_by_pncidx(uint32_t pnc_idx, uint32_t *fdb_idx, mac_learn_db_entry_t *mac_learn_db_entry);
+int32_t mac_learn_db_entry_add(mac_learn_db_entry_t *mac_learn_db_entry);
+int32_t mac_learn_db_entry_del(uint32_t del_idx);
+int32_t mac_learn_db_valid_count_get(uint32_t *valid_ount);
+void mac_learn_db_nonstatic_count_inc(void);
+void mac_learn_db_nonstatic_count_dec(void);
+int32_t mac_learn_db_nonstatic_count_get(uint32_t *nonstatic_ount);
+void mac_learn_db_valid_print(void);
+int32_t mac_learn_fdb_init(void);
+
+#endif
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_header.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_header.h
new file mode 100755
index 0000000..6516584
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_header.h
@@ -0,0 +1,44 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_header.h
+*
+* DESCRIPTION: Include all mac learn header files needed
+*
+*
+*******************************************************************************/
+#ifndef __mv_mac_learn_header_h__
+#define __mv_mac_learn_header_h__
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "mv_mac_learn_mod.h"
+#include "mv_mac_learn_api.h"
+#include "mv_mac_learn_netdev.h"
+#include "mv_mac_learn_logic.h"
+#include "mv_mac_learn_db.h"
+#include "mv_mac_learn_sysfs.h"
+
+#endif /* __mv_mac_learn_header_h__ */
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.c
new file mode 100755
index 0000000..0685b5a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.c
@@ -0,0 +1,585 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_logic.c
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "mvOs.h"
+#include "mv_mac_learn_header.h"
+
+/************************************************************************************
+* mv_mac_learn_get_lu_hw()
+* Get LU of MAC leanring PnC entry; but this function is NOT used for long time delay
+*************************************************************************************/
+int32_t mv_mac_learn_get_lu_hw(uint32_t *pnc_idx)
+{
+	uint32_t i = 0;
+	uint32_t w32,tid;
+	tpm_api_lu_conf_t lu_conf;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	if (tpm_db_pnc_get_lu_conf(TPM_PNC_MAC_LEARN, &lu_conf)) {
+		MVMACLEARN_ERR_PRINT("TPM lookup conf get failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	i = 0;
+	while (i < CONFIG_MV_PNC_TCAM_LINES) {
+		w32 = mvPncAgingLogEntryRead(lu_conf.cntr_grp, 0);
+		if ((w32 & PNC_AGING_LOG_VALID_MASK) == 0) {
+			MVMACLEARN_WARN_PRINT("LU Read ivalid\n");
+			tid = range_conf.range_start + range_conf.api_end;
+			break;
+		}
+		mvOsDelay(20);
+		tid = w32 & PNC_AGING_LOG_CNTR_IDX_MASK;
+		if (tid >= (range_conf.range_start + range_conf.api_start) && tid <= (range_conf.range_start + range_conf.api_end))
+			break;
+		i++;
+
+		if(!(i%8))
+			mvPncAgingTrigerSet();
+	}
+
+	if (CONFIG_MV_PNC_TCAM_LINES == i) {
+		MVMACLEARN_WARN_PRINT("LU Read failed\n");
+		tid = range_conf.range_start + range_conf.api_end;
+	}
+
+	*pnc_idx = tid;
+
+	return MAC_LEARN_OK;
+}
+
+/************************************************************************************
+* mv_mac_learn_get_lu
+* Get LU of MAC leanring PnC entry
+*output:
+*	pnc_idx: PNC index of LU entry
+*return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+*************************************************************************************/
+int32_t mv_mac_learn_get_lu(uint32_t *pnc_idx)
+{
+	int32_t i;
+	uint32_t hit_count = 0, temp;
+	uint32_t lu_idx = 0;
+	uint32_t first_lu = 0;
+	mac_learn_db_entry_t mac_learn_db_entry;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	/* If only one API entry */
+	if (range_conf.api_start == range_conf.api_end) {
+		*pnc_idx = range_conf.range_start + range_conf.api_start;
+		return MAC_LEARN_OK;
+	}
+
+	for (i = range_conf.range_start + range_conf.api_start; i <= range_conf.range_start + range_conf.api_end; i++) {
+		/* Static entry not be replaced */
+		if (!mac_learn_db_entry_info_by_pncidx(i, NULL, &mac_learn_db_entry)) {
+			if (mac_learn_db_entry.state == MAC_LEARN_FDB_STATIC)
+				continue;
+		} else {
+			continue;
+		}
+		if (first_lu == 0) {
+			lu_idx = i;
+			hit_count = mvPncAgingCntrRead(lu_idx) & PNC_AGING_CNTR_MASK;
+			first_lu = 1;
+		} else {
+			temp = mvPncAgingCntrRead(i) & PNC_AGING_CNTR_MASK;
+			if (hit_count > temp) {
+				hit_count = temp;
+				lu_idx = i;
+			}
+		}
+	}
+
+	/* All entries are static, can not replace */
+	if (first_lu == 0)
+		return MAC_LEARN_FAIL;
+
+	*pnc_idx = lu_idx;
+
+	return MAC_LEARN_OK;
+}
+
+/************************************************************************************
+* mv_mac_learn_aging
+* MAC learning aging function for aging timer
+*input:
+*	mac_learn_aging: pointer of global variable
+*return:
+*	void
+*************************************************************************************/
+void mv_mac_learn_aging(unsigned long mac_learn_aging)
+{
+	uint32_t i;
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+	uint32_t pnc_idx, read_count,hit_count = 0;
+	uint32_t fdb_valid_count;
+	tpm_l2_acl_key_t del_mac_key;
+	mac_learn_db_entry_t mac_learn_db_entry;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	mac_learn_t *mac_learn_age = (mac_learn_t *)mac_learn_aging;
+
+	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+		return;
+	}
+
+	for (i = 0; i < MAC_LEARN_FDB_MAX_COUNT; i++) {
+		if (!mac_learn_db_nonstatic_pnc_get_by_fdbidx(i, &pnc_idx, &hit_count)) {
+			if (MAC_LEARN_FDB_INVALID_PNC == pnc_idx)
+				continue;
+			/*check whether PnC hit in last 1s*/
+			read_count = mvPncAgingCntrRead(pnc_idx);
+			if (read_count & PNC_AGING_CNTR_MASK) {
+				/*clear no hit time*/
+				mac_learn_db_no_time_clear_update_hit(i, read_count & PNC_AGING_CNTR_MASK);
+				/*clear hit counter, avoid overflow*/
+				mvPncAgingCntrWrite(pnc_idx, read_count & (~PNC_AGING_CNTR_MASK));
+			} else {
+				/* Increase No hit time and read it */
+				mac_learn_db_no_hit_time_inc_read(i, &mac_learn_db_entry);
+				if (mac_learn_db_entry.no_hit_time >= mac_learn_age->mac_learn_expire_time) {
+					memset(&del_mac_key, 0, sizeof(tpm_l2_acl_key_t));
+					memset(del_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
+					memcpy(del_mac_key.mac.mac_sa, mac_learn_db_entry.src_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE);
+					/*Get tpm del lock*/
+					spin_lock(&mac_learn_age->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_DEL]);
+					if (!tpm_del_mac_learn_rule(tpm_owner_id, &del_mac_key)) {
+						/*release lock*/
+						spin_unlock(&mac_learn_age->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_DEL]);
+						/*Update FDB first*/
+						if (TPM_RANGE_TYPE_ACL == range_conf.range_type)
+							mac_learn_db_pncidx_update(0, pnc_idx);
+						if (mac_learn_db_entry_del(i)) {
+							MVMACLEARN_ERR_PRINT("MAC learn FDB del failed\n");
+							continue;
+						} else {
+							/* dec non static entry count */
+							mac_learn_db_nonstatic_count_dec();
+							mac_learn_db_valid_count_get(&fdb_valid_count);
+							/* start MAC learn again */
+							if ((mac_learn_age->mac_learn_max_count - fdb_valid_count == 1) &&
+							    (false == mac_learn_age->mac_learn_overwrite_enable)) {
+								/* Trap packet with new address to CPU again */
+								if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_TRAP)) {
+									MVMACLEARN_ERR_PRINT("MAC learn default rule action set failed\n");
+									continue;
+								}
+							}
+						}
+					} else {
+						/*release lock*/
+						spin_unlock(&mac_learn_age->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_DEL]);
+						MVMACLEARN_ERR_PRINT("TPM MAC learn entry del failed\n");
+						continue;
+					}
+				}
+			}
+		}
+	}
+
+	/*Continue time*/
+	mod_timer(&mac_learn_age->mac_learn_timer, jiffies + HZ);
+}
+
+/************************************************************************************
+* mv_mac_learn_pnc_rule_add
+* Function to add new MAC leanring entry automatic in system
+*input:
+*	work: work queue the function on
+*return:
+*	void
+*************************************************************************************/
+void mv_mac_learn_pnc_rule_add(struct work_struct *work)
+{
+	tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_l2_acl_key_t src_mac_key, del_mac_key;
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+	uint32_t valid_count, nonstatic_count;
+	mac_learn_db_entry_t mac_learn_db_entry;
+	int32_t addr_exist = 0;
+	int32_t fdb_addr_exist = 0;
+	uint32_t rule_num, pnc_idx;
+	uint32_t fdb_idx;
+	mac_learn_t *src_mac = container_of(work, mac_learn_t, mac_learn_work);
+
+	/*check mac learn enable state*/
+	if (false == src_mac->mac_learn_enable)
+		return;
+
+	/* Get pnc_mac_learn_enable from TPM XML */
+	if (tpm_db_pnc_mac_learn_enable_get(&pnc_mac_learn_enable))
+		return;
+	if (TPM_PNC_MAC_LEARN_DISABLED == pnc_mac_learn_enable) {
+		MVMACLEARN_ERR_PRINT("TPM PNC mac learn disabled\n");
+		return;
+	}
+
+	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+		return;
+	}
+
+	memset(&src_mac_key, 0, sizeof(tpm_l2_acl_key_t));
+	memset(src_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
+	memset(&mac_learn_db_entry, 0, sizeof(mac_learn_db_entry_t));
+	/*Get source MAC address*/
+	if (mv_mac_learn_queue_read(src_mac_key.mac.mac_sa))
+		return;
+	
+	/* Check the src mac exist in FDB or not*/
+	if (mac_learn_db_find_mac_addr(&src_mac_key, &fdb_addr_exist, NULL))
+		return;
+	/* If Addr exist in FDB, return */
+	if (fdb_addr_exist == 1)
+		return;
+
+	/* Get valid entry count currently */
+	if (mac_learn_db_valid_count_get(&valid_count) || mac_learn_db_nonstatic_count_get(&nonstatic_count)) {
+		MVMACLEARN_ERR_PRINT("Get valid count or nonstatic count failed\n");
+		return;
+	}
+
+	/* Check non-static Full or not */
+	if (src_mac->mac_learn_max_count == nonstatic_count) {
+		if (true == src_mac->mac_learn_overwrite_enable) {
+			/* Interval less than 0.2s, overwrite is forbidden*/
+			if (time_after(jiffies, (unsigned long)src_mac->mac_learn_overwrite_time))
+				src_mac->mac_learn_overwrite_time  = jiffies + HZ / 5;/*update overwrite time*/
+			else
+				return;/*return from here, no any operation*/
+			/* Overwrite LU entry */
+			if (!mv_mac_learn_get_lu(&pnc_idx)) {
+				MVMACLEARN_DEBUG_PRINT("PnC index need to be overwritten: %d\n", pnc_idx);
+				/* Delete LU in PnC first */
+				if (!mac_learn_db_entry_info_by_pncidx(pnc_idx, &fdb_idx, &mac_learn_db_entry)) {
+					memset(&del_mac_key, 0, sizeof(tpm_l2_acl_key_t));
+					memset(del_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
+					memcpy(del_mac_key.mac.mac_sa, mac_learn_db_entry.src_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE);
+					/*get lock*/
+					spin_lock(&src_mac->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_DEL]);
+					if (!tpm_del_mac_learn_rule(tpm_owner_id, &del_mac_key)) {
+						/*release lock*/
+						spin_unlock(&src_mac->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_DEL]);
+						/*Update FDB first*/
+						if (TPM_RANGE_TYPE_ACL == range_conf.range_type)
+							mac_learn_db_pncidx_update(0, pnc_idx);
+						if (mac_learn_db_entry_del(fdb_idx)) {
+							MVMACLEARN_ERR_PRINT("MAC learn FDB del failed\n");
+							return;
+						} else {
+							mac_learn_db_nonstatic_count_dec();
+						}
+					} else {
+						/*release lock*/
+						spin_unlock(&src_mac->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_DEL]);
+						MVMACLEARN_ERR_PRINT("TPM MAC learn entry del failed\n");
+						return;
+					}
+				} else {
+					MVMACLEARN_ERR_PRINT("MAC learn FDB info get failed\n");
+					return;
+				}
+			}else {
+				MVMACLEARN_ERR_PRINT("LU MAC learn entry get failed\n");
+				return;
+			}
+		} else {
+			/* Discarded packet with new address */
+			if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_DROP)) {
+				MVMACLEARN_ERR_PRINT("MAC learn default rule action set failed\n");
+				return;
+			}
+			/* Return from here */
+			return;
+		}
+	}
+
+	/*get lock*/
+	spin_lock(&src_mac->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_ADD]);
+	if (!tpm_add_mac_learn_rule(tpm_owner_id, &src_mac_key)) {
+		/*Release lock*/
+		spin_unlock(&src_mac->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_ADD]);
+		if (fdb_addr_exist == 0) {
+			/* Get PnC index */
+			if (!tpm_proc_find_mac_addr_db(&src_mac_key, &addr_exist, &rule_num, &pnc_idx)) {
+				if (addr_exist) {
+					memset(&mac_learn_db_entry, 0, sizeof(mac_learn_db_entry_t));
+					mac_learn_db_entry.valid = MAC_LEARN_FDB_VALID;
+					mac_learn_db_entry.state = MAC_LEARN_FDB_NON_STATIC;
+					mac_learn_db_entry.port = MAC_LEARN_ON_GMAC;
+					mac_learn_db_entry.pnc_idx = range_conf.range_start + range_conf.api_start + pnc_idx;
+					mac_learn_db_entry.hit_count = 0;
+					mac_learn_db_entry.no_hit_time = 0;
+					memcpy(mac_learn_db_entry.src_mac_addr, src_mac_key.mac.mac_sa, sizeof(char) * MV_MAC_ADDR_SIZE);
+					MVMACLEARN_DEBUG_PRINT("New non-static MAC learn entry adding, PnC idex: %d\n",mac_learn_db_entry.pnc_idx);
+					/*Update FDB first*/
+					if (TPM_RANGE_TYPE_ACL == range_conf.range_type)
+						mac_learn_db_pncidx_update(1, mac_learn_db_entry.pnc_idx);
+					/* Write to FDB */
+					if (!mac_learn_db_entry_add(&mac_learn_db_entry))
+						mac_learn_db_nonstatic_count_inc();
+				}
+			}
+		}
+	} else {
+		/*Release lock*/
+		spin_unlock(&src_mac->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_ADD]);
+	}
+}
+
+/************************************************************************************
+* mv_mac_learn_logic_static_add
+* Function to add new MAC leanring entry mannuly in system
+*input:
+*	static_mac_addr: source MAC address
+*return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+*************************************************************************************/
+int32_t mv_mac_learn_logic_static_add(char *static_mac_addr)
+{
+	tpm_l2_acl_key_t src_mac_key;
+	mac_learn_db_entry_t mac_learn_db_entry;
+	tpm_db_pnc_range_conf_t range_conf;
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+	int32_t addr_exist = 0;
+	int32_t fdb_addr_exist = 0;
+	uint32_t rule_num, pnc_idx, pnc_max_count, valid_count, non_static_count, non_static_max;
+	bool mac_learn_enable = false;
+
+	if (mv_mac_learn_op_enable_get(&mac_learn_enable))
+		return MAC_LEARN_FAIL;
+	if (false == mac_learn_enable) {
+		MVMACLEARN_ERR_PRINT("MAC learn disabled\n\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	/*Input check*/
+	if (NULL == static_mac_addr) {
+		MVMACLEARN_ERR_PRINT("Invalid input\n");
+		return MAC_LEARN_FAIL;
+	}
+	MVMACLEARN_DEBUG_PRINT("MAC addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", static_mac_addr[0], static_mac_addr[1], static_mac_addr[2],
+									    static_mac_addr[3], static_mac_addr[4], static_mac_addr[5]);
+	/*init src_mac_key*/
+	memset(&src_mac_key, 0, sizeof(tpm_l2_acl_key_t));
+	memset(src_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
+	memcpy(src_mac_key.mac.mac_sa, static_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE);
+
+	/* Check the src mac exist in FDB or not*/
+	if (mac_learn_db_find_mac_addr(&src_mac_key, &fdb_addr_exist, NULL)) {
+		MVMACLEARN_ERR_PRINT("mac_learn_db_find_mac_addr failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	/* If Addr exist in FDB, return OK*/
+	if (fdb_addr_exist == 1) {
+		MVMACLEARN_WARN_PRINT("Entry already exist\n");
+		return MAC_LEARN_OK;
+	}
+	/*Get MAC learn range info*/
+	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	/*check whether static free entry enough or not*/
+	pnc_max_count = range_conf.api_end - range_conf.api_start + 1;
+	if (mac_learn_db_valid_count_get(&valid_count) ||
+	    mac_learn_db_nonstatic_count_get(&non_static_count) ||
+	    mv_mac_learn_op_max_count_get(&non_static_max))
+		return MAC_LEARN_FAIL;
+	if ((valid_count - non_static_count) >= (pnc_max_count - non_static_max)) {
+		MVMACLEARN_ERR_PRINT("No free entry for static entry\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	/*Add entry through TPM API*/
+	/*get lock*/
+	mac_learn_tpm_api_lock_get(MAC_LEARN_TPM_API_LOCK_ADD);
+	if (!tpm_add_mac_learn_rule(tpm_owner_id, &src_mac_key)) {
+		/*release lock*/
+		mac_learn_tpm_api_lock_release(MAC_LEARN_TPM_API_LOCK_ADD);
+		/* Get PnC index */
+		if (!tpm_proc_find_mac_addr_db(&src_mac_key, &addr_exist, &rule_num, &pnc_idx)) {
+			/*Update FDB*/
+			if (addr_exist) {
+				memset(&mac_learn_db_entry, 0, sizeof(mac_learn_db_entry_t));
+				mac_learn_db_entry.valid = MAC_LEARN_FDB_VALID;
+				mac_learn_db_entry.state = MAC_LEARN_FDB_STATIC;
+				mac_learn_db_entry.port = MAC_LEARN_ON_GMAC;
+				mac_learn_db_entry.pnc_idx = range_conf.range_start + range_conf.api_start + pnc_idx;
+				mac_learn_db_entry.hit_count = 0;
+				memcpy(mac_learn_db_entry.src_mac_addr, src_mac_key.mac.mac_sa, sizeof(char) * MV_MAC_ADDR_SIZE);
+				MVMACLEARN_DEBUG_PRINT("New static MAC learn  entry adding, PnC idex: %d\n",mac_learn_db_entry.pnc_idx);
+				/*Update FDB first*/
+				if (TPM_RANGE_TYPE_ACL == range_conf.range_type)
+					mac_learn_db_pncidx_update(1, mac_learn_db_entry.pnc_idx);
+				/* Write to FDB */
+				if (mac_learn_db_entry_add(&mac_learn_db_entry)) {
+					MVMACLEARN_ERR_PRINT("mac_learn_db_entry_add failed\n");
+					return MAC_LEARN_FAIL;
+				}
+			}
+		} else {
+			MVMACLEARN_ERR_PRINT("tpm_proc_find_mac_addr_db failed\n");
+			return MAC_LEARN_FAIL;
+		}
+		return MAC_LEARN_OK;
+	} else {
+		/*release lock*/
+		mac_learn_tpm_api_lock_release(MAC_LEARN_TPM_API_LOCK_ADD);
+		MVMACLEARN_ERR_PRINT("tpm_add_mac_learn_rule failed\n");
+		return MAC_LEARN_FAIL;
+	}
+}
+
+/************************************************************************************
+* mv_mac_learn_logic_static_add
+* Function to delete a MAC leanring entry mannuly in system
+*input:
+*	static_mac_addr: source MAC address
+*return:
+*	success--MAC_LEARN_OK
+*	failed --MAC_LEARN_FAIL
+*************************************************************************************/
+int32_t mv_mac_learn_logic_static_del(char *static_mac_addr)
+{
+	tpm_l2_acl_key_t del_mac_key;
+	tpm_db_pnc_range_conf_t range_conf;
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+	int32_t addr_exist = 0;
+	int32_t fdb_addr_exist = 1;
+	uint32_t rule_num, pnc_idx;
+	uint32_t fdb_idx;
+	bool mac_learn_enable = false;
+	mac_learn_db_entry_t mac_learn_db_entry_info;
+
+	if (mv_mac_learn_op_enable_get(&mac_learn_enable))
+		return MAC_LEARN_FAIL;
+	if (false == mac_learn_enable) {
+		MVMACLEARN_ERR_PRINT("MAC learn disabled\n\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	/*Input check*/
+	if (NULL == static_mac_addr) {
+		MVMACLEARN_ERR_PRINT("Invalid input\n");
+		return MAC_LEARN_FAIL;
+	}
+	MVMACLEARN_DEBUG_PRINT("MAC addr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", static_mac_addr[0], static_mac_addr[1], static_mac_addr[2],
+									    static_mac_addr[3], static_mac_addr[4], static_mac_addr[5]);
+	/*init src_mac_key*/
+	memset(&del_mac_key, 0, sizeof(tpm_l2_acl_key_t));
+	memset(del_mac_key.mac.mac_sa_mask, 0xff, sizeof(u8)*MV_MAC_ADDR_SIZE);
+	memcpy(del_mac_key.mac.mac_sa, static_mac_addr, sizeof(char) * MV_MAC_ADDR_SIZE);
+
+	/* Check the src mac exist in FDB or not*/
+	if (mac_learn_db_find_mac_addr(&del_mac_key, &fdb_addr_exist, &mac_learn_db_entry_info)) {
+		MVMACLEARN_ERR_PRINT("mac_learn_db_find_mac_addr failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	/* If Addr non-exist in FDB, return OK*/
+	if (fdb_addr_exist == 0) {
+		MVMACLEARN_ERR_PRINT("Entry non-exist\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	/* If exist, check it is static mac or non-static, only static mac allow to del with API */
+	if (mac_learn_db_entry_info.state == MAC_LEARN_FDB_NON_STATIC) {
+		MVMACLEARN_ERR_PRINT("Non-static MAC, not allowed to del with static API\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+		MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	/* Get PnC index */
+	if (!tpm_proc_find_mac_addr_db(&del_mac_key, &addr_exist, &rule_num, &pnc_idx)) {
+		if (addr_exist == 0) {
+			MVMACLEARN_ERR_PRINT("TPM DB inconsistent with MAC learn FDB\n");
+			return MAC_LEARN_FAIL;
+		}
+		pnc_idx = range_conf.range_start + range_conf.api_start + pnc_idx;
+		MVMACLEARN_DEBUG_PRINT("PnC index: %d\n", pnc_idx);
+		/*Get FDB entry by PnCidx*/
+		if (!mac_learn_db_entry_info_by_pncidx(pnc_idx, &fdb_idx, NULL)) {
+			MVMACLEARN_DEBUG_PRINT("FDB index: %d\n", fdb_idx);
+			/*get lock*/
+			mac_learn_tpm_api_lock_get(MAC_LEARN_TPM_API_LOCK_DEL);
+			if (!tpm_del_mac_learn_rule(tpm_owner_id, &del_mac_key)) {
+				/*release lock*/
+				mac_learn_tpm_api_lock_release(MAC_LEARN_TPM_API_LOCK_DEL);
+				/*Update FDB first*/
+				if (TPM_RANGE_TYPE_ACL == range_conf.range_type)
+					mac_learn_db_pncidx_update(0, pnc_idx);
+				if (mac_learn_db_entry_del(fdb_idx)) {
+					MVMACLEARN_ERR_PRINT("MAC learn FDB del failed\n");
+					return MAC_LEARN_FAIL;
+				} else {
+					/*start learn again, if fdb full, maybe learn is disabled*/
+					if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_TRAP)) {
+						MVMACLEARN_ERR_PRINT("MAC learn default rule action set failed\n");
+						return MAC_LEARN_FAIL;
+					}
+				}
+			} else {
+				/*release lock*/
+				mac_learn_tpm_api_lock_release(MAC_LEARN_TPM_API_LOCK_DEL);
+				MVMACLEARN_ERR_PRINT("tpm_del_mac_learn_rule failed\n");
+				return MAC_LEARN_FAIL;
+			}
+		} else {
+			MVMACLEARN_ERR_PRINT("mac_learn_db_entry_info_by_pncidx failed\n");
+			return MAC_LEARN_FAIL;
+		}
+		/*del success*/
+		return MAC_LEARN_OK;
+	} else {
+		MVMACLEARN_ERR_PRINT("tpm_proc_find_mac_addr_db failed\n");
+		return MAC_LEARN_FAIL;
+	}
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.h
new file mode 100755
index 0000000..6f3a682
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_logic.h
@@ -0,0 +1,46 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_logic.h
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#ifndef __mv_mac_learn_logic_h__
+#define __mv_mac_learn_logic_h__
+
+/* GMAC MAC leanring ON
+------------------------------------------------------------------------------*/
+#define MAC_LEARN_ON_GMAC 0
+
+/* Function protype
+------------------------------------------------------------------------------*/
+void mv_mac_learn_aging(unsigned long mac_learn_aging);
+void mv_mac_learn_pnc_rule_add(struct work_struct *work);
+int32_t mv_mac_learn_logic_static_add(char *static_mac_addr);
+int32_t mv_mac_learn_logic_static_del(char *static_mac_addr);
+
+#endif
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.c
new file mode 100755
index 0000000..cd20927
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.c
@@ -0,0 +1,678 @@
+/*******************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : mv_mac_learn_mod.c                                         **
+**                                                                           **
+**  DESCRIPTION : This file implements MAC learn module init                 **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   12June2012  Evan Wang   created                                           *
+* =========================================================================== *
+******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+#include "mv_mac_learn_header.h"
+
+/* Global variable */
+mac_learn_t mc_mac_learn;
+uint32_t mac_learn_glob_trace = 0;
+
+/*******************************************************************************
+* mac_learn_queue_work_insert()
+*
+* DESCRIPTION:  Insert a work into work queue for mac learning.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* void
+* COMMENTS:
+*
+*******************************************************************************/
+int mac_learn_queue_work_insert(void)
+{
+	if (true == mc_mac_learn.queue_init)
+		return queue_work(mc_mac_learn.mac_learn_queue, &mc_mac_learn.mac_learn_work);
+	return 0;
+}
+
+/*******************************************************************************
+* mac_learn_tpm_api_lock_get()
+*
+* DESCRIPTION:  Get spin lock for tpm api.
+*
+* INPUTS:
+* lock_type: TPM api, add or del
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* void
+* COMMENTS:
+*
+*******************************************************************************/
+void mac_learn_tpm_api_lock_get(mac_learn_tpm_lock_t lock_type)
+{
+	/*get lock*/
+	spin_lock(&mc_mac_learn.tpm_api_lock[lock_type]);
+}
+
+/*******************************************************************************
+* mac_learn_tpm_api_lock_release()
+*
+* DESCRIPTION:  Release spin lock for tpm api.
+*
+* INPUTS:
+* lock_type: TPM api, add or del
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* void
+* COMMENTS:
+*
+*******************************************************************************/
+void mac_learn_tpm_api_lock_release(mac_learn_tpm_lock_t lock_type)
+{
+	/*release lock*/
+	spin_unlock(&mc_mac_learn.tpm_api_lock[lock_type]);
+}
+
+/*******************************************************************************
+* mv_mac_learn_queue_write()
+*
+* DESCRIPTION:  Write the mac address to learn into buffer queue.
+*
+* INPUTS:
+* src_mac: pointer to mac address to learn
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* failed --MAC_LEARN_FAIL
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_queue_write(char *src_mac)
+{
+	uint32_t i;
+
+	if (down_trylock(&mc_mac_learn.sc_mac_queue.queue_sem))
+		return MAC_LEARN_FAIL;
+
+	for (i = 0; i < MAC_LEARN_QUEUE_SIZE; i ++) {
+		if (!memcmp(mc_mac_learn.sc_mac_queue.mc_src_mac[i].mac_addr_entry, src_mac, MV_MAC_ADDR_SIZE)) {
+			up(&mc_mac_learn.sc_mac_queue.queue_sem);
+			return MAC_LEARN_FAIL;
+		}
+	}
+
+	if (mc_mac_learn.sc_mac_queue.queue_full) {
+		up(&mc_mac_learn.sc_mac_queue.queue_sem);
+		return MAC_LEARN_FAIL;
+	}
+
+	memcpy(mc_mac_learn.sc_mac_queue.mc_src_mac[mc_mac_learn.sc_mac_queue.wr_idx].mac_addr_entry,
+	       src_mac, sizeof(char) * MV_MAC_ADDR_SIZE);
+
+	/* insert work queue, if failed remove MAC from cycle buffer */
+	if (1 != mac_learn_queue_work_insert()) {
+		memset(mc_mac_learn.sc_mac_queue.mc_src_mac[mc_mac_learn.sc_mac_queue.wr_idx].mac_addr_entry, 0,
+		       sizeof(char) * MV_MAC_ADDR_SIZE);
+		up(&mc_mac_learn.sc_mac_queue.queue_sem);
+		return MAC_LEARN_FAIL;
+	}
+
+	mc_mac_learn.sc_mac_queue.wr_idx++;
+	if (mc_mac_learn.sc_mac_queue.wr_idx == MAC_LEARN_QUEUE_SIZE)
+		mc_mac_learn.sc_mac_queue.wr_idx = 0;
+	if (mc_mac_learn.sc_mac_queue.wr_idx == mc_mac_learn.sc_mac_queue.rd_idx)
+		mc_mac_learn.sc_mac_queue.queue_full = true;
+
+	if (mc_mac_learn.sc_mac_queue.queue_empty)
+		mc_mac_learn.sc_mac_queue.queue_empty = false;
+
+	up(&mc_mac_learn.sc_mac_queue.queue_sem);
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_queue_read()
+*
+* DESCRIPTION:  Read the mac address to learn in buffer queue.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* src_mac: pointer to mac address to learn
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* failed --MAC_LEARN_FAIL
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_queue_read(char *src_mac)
+{
+	if (down_interruptible(&mc_mac_learn.sc_mac_queue.queue_sem))
+		return MAC_LEARN_FAIL;
+
+	if (mc_mac_learn.sc_mac_queue.queue_empty) {
+		up(&mc_mac_learn.sc_mac_queue.queue_sem);
+		return MAC_LEARN_FAIL;
+	}
+
+	memcpy(src_mac, mc_mac_learn.sc_mac_queue.mc_src_mac[mc_mac_learn.sc_mac_queue.rd_idx].mac_addr_entry,
+	       sizeof(char) * MV_MAC_ADDR_SIZE);
+	memset(mc_mac_learn.sc_mac_queue.mc_src_mac[mc_mac_learn.sc_mac_queue.rd_idx].mac_addr_entry, 0,
+	       sizeof(char) * MV_MAC_ADDR_SIZE);
+	mc_mac_learn.sc_mac_queue.rd_idx++;
+	if (mc_mac_learn.sc_mac_queue.rd_idx == MAC_LEARN_QUEUE_SIZE)
+		mc_mac_learn.sc_mac_queue.rd_idx = 0;
+	if (mc_mac_learn.sc_mac_queue.wr_idx == mc_mac_learn.sc_mac_queue.rd_idx)
+		mc_mac_learn.sc_mac_queue.queue_empty = true;
+
+	if (mc_mac_learn.sc_mac_queue.queue_full)
+		mc_mac_learn.sc_mac_queue.queue_full = false;
+
+	up(&mc_mac_learn.sc_mac_queue.queue_sem);
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_enable_set()
+*
+* DESCRIPTION:  Set the enable state of mac learning.
+*
+* INPUTS:
+* mac_learn_enable: enable state
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_enable_set(bool mac_learn_enable)
+{
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable;
+
+	/*check original value and new value, if equal, return OK*/
+	if (mac_learn_enable == mc_mac_learn.mac_learn_enable)
+		return MAC_LEARN_OK;
+
+	if (true == mac_learn_enable) {
+		/*check TPM init succeed or not, before enable MAC learning*/
+		if (!tpm_db_init_done_get()) {
+			MVMACLEARN_ERR_PRINT("TPM initialization not success\n");
+			return MAC_LEARN_FAIL;
+		}
+		/*check TPM XML pnc_mac_learn_enable*/
+		tpm_db_pnc_mac_learn_enable_get(&pnc_mac_learn_enable);
+		if (TPM_PNC_MAC_LEARN_DISABLED == pnc_mac_learn_enable) {
+			MVMACLEARN_ERR_PRINT("TPM XML para pnc_mac_learn_enable not enabled\n");
+			return MAC_LEARN_FAIL;
+		}
+		/*Set MAX count to min(range_size, FDB_max_count)*/
+		if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+			MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+			return MAC_LEARN_FAIL;
+		}
+		if (range_conf.api_end - range_conf.api_start + 1 > MAC_LEARN_FDB_MAX_COUNT)
+			mc_mac_learn.mac_learn_max_count = MAC_LEARN_FDB_MAX_COUNT / 2;
+		else
+			mc_mac_learn.mac_learn_max_count = (range_conf.api_end - range_conf.api_start + 1) / 2;
+		MVMACLEARN_DEBUG_PRINT("non-static entry max count: %d\n",mc_mac_learn.mac_learn_max_count);
+		/* Trap packet to CPU */
+		if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_TRAP)) {
+			MVMACLEARN_ERR_PRINT("TPM default rule action set failed\n");
+			return MAC_LEARN_FAIL;
+		}
+		/*Add timer*/
+		add_timer(&mc_mac_learn.mac_learn_timer);
+	} else {
+		/*delete timer*/
+		del_timer(&mc_mac_learn.mac_learn_timer);
+		/*Forward packet to GMAC1*/
+		if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_CONTINUE)) {
+			MVMACLEARN_ERR_PRINT("TPM default rule action set failed\n");
+			return MAC_LEARN_FAIL;
+		}
+		/*Reset FDB and delete PNC rule*/
+		if (mac_learn_db_reset()) {
+			MVMACLEARN_ERR_PRINT("FDB reset failed\n");
+			return MAC_LEARN_FAIL;
+		}
+	}
+
+	mc_mac_learn.mac_learn_enable = mac_learn_enable;
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_enable_get()
+*
+* DESCRIPTION:  Get the enable state of mac learning.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* mac_learn_enable: enable state
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_enable_get(bool *mac_learn_enable)
+{
+	*mac_learn_enable = mc_mac_learn.mac_learn_enable;
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_overwrite_set()
+*
+* DESCRIPTION:  Set the enable state of overwrite if non-static up to max.
+*
+* INPUTS:
+* overwrite_enable: enable state
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_overwrite_set(bool overwrite_enable)
+{
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+
+	if ((true == overwrite_enable) && true == (mc_mac_learn.mac_learn_enable)) {
+		/* Trap packet to CPU when enable overwrite */
+		if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_TRAP)) {
+			MVMACLEARN_ERR_PRINT("MAC learn default rule action set failed\n");
+			return MAC_LEARN_FAIL;
+		}
+	}
+	mc_mac_learn.mac_learn_overwrite_enable = overwrite_enable;
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_overwrite_get()
+*
+* DESCRIPTION:  Get the enable state of overwrite if non-static up to max.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* overwrite_enable: enable state
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_overwrite_get(bool *overwrite_enable)
+{
+	*overwrite_enable = mc_mac_learn.mac_learn_overwrite_enable;
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_max_count_set()
+*
+* DESCRIPTION:  Set the max count of non-static entry.
+*
+* INPUTS:
+* mac_learn_max_count: max count
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_max_count_set(uint32_t mac_learn_max_count)
+{
+	const uint32_t tpm_owner_id = TPM_MOD_OWNER_TPM;
+	uint32_t non_static_count, valid_count, pnc_count;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	if (true == mc_mac_learn.mac_learn_enable) {
+		MVMACLEARN_DEBUG_PRINT("Old max count: %d, New max count: %d\n", mc_mac_learn.mac_learn_enable, mac_learn_max_count);
+		if (mac_learn_max_count < mc_mac_learn.mac_learn_max_count) {
+			if (!mac_learn_db_nonstatic_count_get(&non_static_count)) {
+				MVMACLEARN_DEBUG_PRINT("Current non-static num: %d\n", non_static_count);
+				if (mac_learn_max_count < non_static_count) {
+					/*delete timer*/
+					del_timer(&mc_mac_learn.mac_learn_timer);
+					/*Clear non-static in FDB and delete PNC rule*/
+					mc_mac_learn.mac_learn_enable = false;
+					if (mac_learn_db_nonstatic_clear()) {
+						mc_mac_learn.mac_learn_enable = true;
+						/*add timer*/
+						add_timer(&mc_mac_learn.mac_learn_timer);
+						MVMACLEARN_ERR_PRINT("FDB non-static entry clear failed\n");
+						return MAC_LEARN_FAIL;
+					}
+					mc_mac_learn.mac_learn_max_count = mac_learn_max_count;
+					mc_mac_learn.mac_learn_enable = true;
+					/*add timer*/
+					add_timer(&mc_mac_learn.mac_learn_timer);
+				} else
+					mc_mac_learn.mac_learn_max_count = mac_learn_max_count;
+			} else {
+				return MAC_LEARN_FAIL;
+			}
+		} else {
+			/* Get available PNC number */
+			if (tpm_db_pnc_rng_conf_get(TPM_PNC_MAC_LEARN, &range_conf)){
+				MVMACLEARN_ERR_PRINT("TPM PnC range info get failed\n");
+				return MAC_LEARN_FAIL;
+			}
+			pnc_count = range_conf.api_end - range_conf.api_start + 1;
+			if (mac_learn_db_valid_count_get(&valid_count) || mac_learn_db_nonstatic_count_get(&non_static_count))
+				return MAC_LEARN_FAIL;
+			if (mac_learn_max_count > (pnc_count - (valid_count - non_static_count))) {
+				MVMACLEARN_ERR_PRINT("Non enough free entry left\n");
+				return MAC_LEARN_FAIL;
+			}
+			mc_mac_learn.mac_learn_max_count = mac_learn_max_count;
+		}
+		/*Trap packet to CPU*/
+		if (tpm_mac_learn_default_rule_act_set(tpm_owner_id, TPM_UNK_MAC_TRAP)) {
+			MVMACLEARN_ERR_PRINT("TPM default rule action set failed\n");
+			return MAC_LEARN_FAIL;
+		}
+	} else {
+		mc_mac_learn.mac_learn_max_count = mac_learn_max_count;
+	}
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_max_count_get()
+*
+* DESCRIPTION:  Get the max count of non-static entry.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* mac_learn_max_count: max count
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_max_count_get(uint32_t *mac_learn_max_count)
+{
+	*mac_learn_max_count = mc_mac_learn.mac_learn_max_count;
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_expire_set()
+*
+* DESCRIPTION:  Set the non-static entry expired time.
+*
+* INPUTS:
+* mac_learn_expire_time: expired time (s)
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_expire_set(uint32_t mac_learn_expire_time)
+{
+	/*Set new expired time*/
+	mc_mac_learn.mac_learn_expire_time = mac_learn_expire_time;
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_expire_get()
+*
+* DESCRIPTION:  Get the non-static entry expired time.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* mac_learn_expire_time: expired time (s)
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_expire_get(uint32_t *mac_learn_expire_time)
+{
+	*mac_learn_expire_time = mc_mac_learn.mac_learn_expire_time;
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_op_trace_level_set()
+*
+* DESCRIPTION:  Set the trace level for print info.
+*
+* INPUTS:
+* trace_level: trace level for print info
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* success--MAC_LEARN_OK
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_op_trace_level_set(uint32_t trace_level)
+{
+	/*Set trace level*/
+	mac_learn_glob_trace = trace_level;
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_var_init()
+*
+* DESCRIPTION: Init variable mac_learn_t *mc_mac_learn.
+*
+* INPUTS:
+* mc_mac_learn    Variable to init
+* aging_func      Function pointer for aging of non-static MAC learning entry
+* queue_work_func Function pointer for work queue, used to receive packet to CPU
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* Init success--MAC_LEARN_OK
+* Init failed --MAC_LEARN_FAIL
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_var_init(mac_learn_t *mc_mac_learn, void (*aging_func)(unsigned long mac_learn_aging), void (*queue_work_func)(struct work_struct *work))
+{
+	/* Input Check */
+	if (NULL == mc_mac_learn || NULL == aging_func) {
+		MVMACLEARN_ERR_PRINT("Invalid input, pointer NULL\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	/* Default init to disable mac learning */
+	mc_mac_learn->mac_learn_enable = false;
+	/* Default init to disable overwrite action after full */
+	mc_mac_learn->mac_learn_overwrite_enable = false;
+	/* Max count set to API range size */
+	mc_mac_learn->mac_learn_max_count = MAC_LEARN_NON_STATIC_DEFAULT;
+	/* Default expired time set to 300s*/
+	mc_mac_learn->mac_learn_expire_time = MAC_LEARN_EX_TIME_DEFAULT;
+	/* Init source MAC queue */
+	memset(mc_mac_learn->sc_mac_queue.mc_src_mac, 0, sizeof(src_mac_addr_t)*MAC_LEARN_QUEUE_SIZE);
+	mc_mac_learn->sc_mac_queue.rd_idx = 0;
+	mc_mac_learn->sc_mac_queue.wr_idx = 0;
+	mc_mac_learn->sc_mac_queue.queue_empty = true;
+	mc_mac_learn->sc_mac_queue.queue_full = false;
+	init_MUTEX(&mc_mac_learn->sc_mac_queue.queue_sem);
+	/* Init timer for aging */
+	init_timer(&mc_mac_learn->mac_learn_timer);
+	mc_mac_learn->mac_learn_timer.function = aging_func;
+	mc_mac_learn->mac_learn_timer.data = (unsigned long)mc_mac_learn;
+	mc_mac_learn->mac_learn_timer.expires = jiffies + HZ;
+	/*Init overwrite time*/
+	mc_mac_learn->mac_learn_overwrite_time = jiffies;
+	/* Init work queue for PnC rule adding */
+	mc_mac_learn->mac_learn_queue = create_workqueue("mac_work_queue");
+	INIT_WORK(&mc_mac_learn->mac_learn_work, queue_work_func);
+	mc_mac_learn->queue_init = true;
+
+	/*Init tpm api spin lock*/
+	spin_lock_init(&mc_mac_learn->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_ADD]);
+	spin_lock_init(&mc_mac_learn->tpm_api_lock[MAC_LEARN_TPM_API_LOCK_DEL]);
+
+	/* Debug Info */
+	MVMACLEARN_DEBUG_PRINT("MAC learn default init: enable = %d, mac_learn_max_count = %d, mac_learn_expire_time = %d\n",
+				mc_mac_learn->mac_learn_enable, mc_mac_learn->mac_learn_max_count, mc_mac_learn->mac_learn_expire_time);
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_module_exit()
+*
+* DESCRIPTION: Finish all initialization for module insmod.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* Init success--MAC_LEARN_OK
+* Init failed --MAC_LEARN_FAIL
+* COMMENTS:
+*
+*******************************************************************************/
+static int __init mv_mac_learn_module_init(void)
+{
+	/* Init Global Valriable */
+	if (mv_mac_learn_var_init(&mc_mac_learn, mv_mac_learn_aging, mv_mac_learn_pnc_rule_add)) {
+		MVMACLEARN_ERR_PRINT("MAC learn global variable init failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	/* Init FDB */
+	if (mac_learn_fdb_init()) {
+		MVMACLEARN_ERR_PRINT("MAC learn global variable init failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	/* Init Netdev */
+	if (mv_mac_learn_netdev_init()) {
+		MVMACLEARN_ERR_PRINT("MAC learn netdev init failed\n");
+		return MAC_LEARN_FAIL;
+	}
+	/*Init sysfs*/
+	if(mv_mac_learn_sysfs_init()) {
+		MVMACLEARN_ERR_PRINT("MAC learn sysfs init failed\n");
+		return MAC_LEARN_FAIL;
+	}
+
+	return MAC_LEARN_OK;
+}
+
+/*******************************************************************************
+* mv_mac_learn_module_exit()
+*
+* DESCRIPTION: Release related resources when module del.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* void
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static void __exit mv_mac_learn_module_exit(void)
+{
+	/*release sysfs*/
+	mv_mac_learn_sysfs_exit();
+}
+
+device_initcall_sync(mv_mac_learn_module_init);
+
+module_exit(mv_mac_learn_module_exit);
+
+MODULE_AUTHOR("Evan Wang");
+MODULE_DESCRIPTION("MAC learn module for Media Convert");
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.h
new file mode 100755
index 0000000..5b7bfe2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_mod.h
@@ -0,0 +1,119 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_mod.h
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#ifndef __mv_mac_learn_mod_h__
+#define __mv_mac_learn_mod_h__
+
+/* MACRO
+------------------------------------------------------------------------------*/
+
+#define MAC_LEARN_QUEUE_SIZE 128
+#define MAC_LEARN_EX_TIME_DEFAULT 300
+#define MAC_LEARN_NON_STATIC_DEFAULT 4
+
+/*Debug info*/
+extern uint32_t mac_learn_glob_trace;
+
+#define MAC_LEARN_GLOB_TRACE mac_learn_glob_trace
+#define MAC_LEARN_DEBUG_MASK  0x00000001
+#define MAC_LEARN_WARN_MASK   0x00000002
+#define MAC_LEARN_ERR_MASK    0x00000004
+
+#define MVMACLEARN_DEBUG_PRINT(format , ...) \
+	{ \
+		if (MAC_LEARN_DEBUG_MASK & MAC_LEARN_GLOB_TRACE) \
+			printk("%s(%d):  "format,__FUNCTION__,__LINE__, ##__VA_ARGS__); \
+	}
+
+#define MVMACLEARN_WARN_PRINT(format , ...) \
+	{ \
+		if (MAC_LEARN_WARN_MASK & MAC_LEARN_GLOB_TRACE) \
+			printk("%s(%d) WARN:  "format,__FUNCTION__,__LINE__, ##__VA_ARGS__); \
+	}
+
+#define MVMACLEARN_ERR_PRINT(format, ...)     printk("%s(%d) ERROR:  "format,__FUNCTION__,__LINE__, ##__VA_ARGS__)
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+typedef enum
+{
+	MAC_LEARN_TPM_API_LOCK_ADD,
+	MAC_LEARN_TPM_API_LOCK_DEL,
+	MAC_LEARN_TPM_API_LOCK_MAX
+} mac_learn_tpm_lock_t;
+
+
+typedef struct {
+	char mac_addr_entry[MV_MAC_ADDR_SIZE];
+}src_mac_addr_t;
+
+typedef struct {
+	struct semaphore queue_sem;
+	src_mac_addr_t mc_src_mac[MAC_LEARN_QUEUE_SIZE];
+	uint32_t wr_idx;
+	uint32_t rd_idx;
+	bool queue_empty;
+	bool queue_full;
+}src_mac_queue_t;
+
+typedef struct {
+	volatile bool mac_learn_enable;
+	bool mac_learn_overwrite_enable;/*Used to control the action after full */
+	uint32_t mac_learn_max_count;/*Non-static max count*/
+	uint32_t mac_learn_expire_time;
+	uint32_t mac_learn_overwrite_time;
+	bool queue_init;
+	struct workqueue_struct *mac_learn_queue;
+	struct work_struct mac_learn_work;
+	src_mac_queue_t sc_mac_queue;/*Used to store MAC address from network*/
+	struct timer_list mac_learn_timer;
+	spinlock_t tpm_api_lock[MAC_LEARN_TPM_API_LOCK_MAX];
+} mac_learn_t;
+
+/* Function protype
+------------------------------------------------------------------------------*/
+int mac_learn_queue_work_insert(void);
+void mac_learn_tpm_api_lock_get(mac_learn_tpm_lock_t lock_type);
+void mac_learn_tpm_api_lock_release(mac_learn_tpm_lock_t lock_type);
+int mv_mac_learn_queue_write(char *src_mac);
+int mv_mac_learn_queue_read(char *src_mac);
+int mv_mac_learn_op_enable_set(bool mac_learn_enable);
+int mv_mac_learn_op_enable_get(bool *mac_learn_enable);
+int mv_mac_learn_op_overwrite_set(bool overwrite_enable);
+int mv_mac_learn_op_overwrite_get(bool *overwrite_enable);
+int mv_mac_learn_op_max_count_set(uint32_t mac_learn_max_count);
+int mv_mac_learn_op_max_count_get(uint32_t *mac_learn_max_count);
+int mv_mac_learn_op_expire_set(uint32_t mac_learn_expire_time);
+int mv_mac_learn_op_expire_get(uint32_t *mac_learn_expire_time);
+int mv_mac_learn_op_trace_level_set(uint32_t trace_level);
+
+
+#endif /* __mv_mac_learn_mod_h__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.c
new file mode 100755
index 0000000..ad69a42
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.c
@@ -0,0 +1,107 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_netdev.c
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#include <ctrlEnv/mvCtrlEnvLib.h>
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+#include "mv_mac_learn_header.h"
+
+/*******************************************************************************
+* mv_mac_learn_eth_rx_func()
+*
+* DESCRIPTION:    Special RX function of mv_eth_rx in mv_netdev.c
+*
+* INPUTS:
+*  port: gmac port the packet from
+*  rxq: interrupt for rx
+*  dev: net device
+*  skb: buffer to receive packet
+*  rx_desc: RX descriptor
+*
+* RETURNS:
+* void
+* COMMENTS:
+*
+*******************************************************************************/
+void mv_mac_learn_eth_rx_func(int port, int rxq, struct net_device *dev, struct sk_buff *skb, struct neta_rx_desc *rx_desc)
+{
+	struct ethhdr *eth_hdr1;
+	bool mac_learn_enable = false;
+
+	/*check mac learn enable*/
+	if (mv_mac_learn_op_enable_get(&mac_learn_enable))
+		return;
+	if (false == mac_learn_enable)
+		return;
+
+	/* get source MAC address */
+	eth_hdr1 = eth_hdr(skb);
+	mv_mac_learn_queue_write(eth_hdr1->h_source);
+}
+
+/*******************************************************************************
+* mv_mac_learn_netdev_init()
+*
+* DESCRIPTION:    register special RX function netdev
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* Init success--0
+* COMMENTS:
+*
+*******************************************************************************/
+int mv_mac_learn_netdev_init(void)
+{
+	uint32_t port_i;
+	int mv_eth_ports_num = 0;
+
+	/* Retrieve num_ports, as in mv_eth_init_module*/
+	mv_eth_ports_num = mvCtrlEthMaxPortGet();
+
+	if (mv_eth_ports_num > CONFIG_MV_ETH_PORTS_NUM)
+		mv_eth_ports_num = CONFIG_MV_ETH_PORTS_NUM;
+
+	/* Register mac learn parse function */
+	for (port_i=0;port_i< mv_eth_ports_num;port_i++) {
+		if (port_i == 0)
+			mv_eth_rx_mac_learn_func(port_i, mv_mac_learn_eth_rx_func);
+		else
+			mv_eth_rx_mac_learn_func(port_i, NULL);
+	}
+
+	return 0;
+}
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.h
new file mode 100755
index 0000000..8a153ab
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_netdev.h
@@ -0,0 +1,50 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_netdev.h
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#ifndef __mv_mac_learn_netdev_h__
+#define __mv_mac_learn_netdev_h__
+
+/* Function protype
+------------------------------------------------------------------------------*/
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+
+#include <mvCommon.h>
+#include <mvOs.h>
+#include <mv_neta/net_dev/mv_netdev.h>
+
+/* Function protype
+------------------------------------------------------------------------------*/
+int mv_mac_learn_netdev_init(void);
+
+#endif /* __mv_mac_learn_netdev_h__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.c
new file mode 100755
index 0000000..1e2e584
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.c
@@ -0,0 +1,776 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_sysfsc.c
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+#include "mv_mac_learn_header.h"
+
+/*******************************************************************************
+* sys_mac_learn_parse_addr
+*
+* DESCRIPTION:
+*           This function parses MAC address
+* INPUTS:
+*       buf - buffer with parameter string
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       bool
+*******************************************************************************/
+static bool sys_mac_learn_parse_addr (char *buf, uint32_t *macaddr_parts)
+{
+	if (6 == sscanf(buf, "%x:%x:%x:%x:%x:%x", &macaddr_parts[0], &macaddr_parts[1], &macaddr_parts[2], &macaddr_parts[3],
+	    &macaddr_parts[4], &macaddr_parts[5])) {
+		if (macaddr_parts[0] <= 255 && macaddr_parts[1] <= 255 && macaddr_parts[2] <= 255 && macaddr_parts[3] <= 255 &&
+		    macaddr_parts[4] <= 255 && macaddr_parts[5] <= 255)
+			return true;
+
+	}
+	return false;
+}
+
+/*******************************************************************************
+* sys_mac_learn_count_para
+*
+* DESCRIPTION:
+*           This function get the number of input parameters
+* INPUTS:
+*       buf - buffer with parameter string
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       int, number of input para
+*******************************************************************************/
+static int sys_mac_learn_count_para (const char *buf)
+{
+	char bufcopy[513];
+	char **ap, *argv[20];
+	char *inputstring = bufcopy;
+	int numparms = 0;
+
+	strcpy(bufcopy, buf);
+
+	for (ap = argv; ap < &argv[15] && (*ap = strsep(&inputstring, " \t")) != NULL;) {
+		if (**ap != '\0') {
+			ap++;
+			numparms++;
+		}
+	}
+	return numparms;
+}
+
+/***********************************************************************************
+**
+**  sfs_help_mac_learn_cfg_all - help for mac learn sysfs commands under cfg folder
+**
+************************************************************************************/
+int sfs_help_mac_learn_cfg_all(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "\necho [src_mac] > mac_learn_static_entry_add   - add one static MAC learn entry\n");
+	off += sprintf(buf+off, "\necho [src_mac] > mac_learn_static_entry_del   - del one static MAC learn entry\n");
+	off += sprintf(buf+off, "\tsrc_mac         (str)aa:bb:cc:dd:ee:ff  where each part is hexadecimal in range 0..FF\n");
+
+	off += sprintf(buf+off, "\n");
+
+	off += sprintf(buf+off, "\necho [enable] > mac_learn_enable   - enable/disable MAC learning\n");
+	off += sprintf(buf+off, "\necho [enable] > mac_learn_overwrite_enable   - enable/disable non-static MAC entry overwrite when FDB full\n");
+	off += sprintf(buf+off, "\tenable          (dec)0: disable, 1: enable\n");
+
+	off += sprintf(buf+off, "\n");
+
+	off += sprintf(buf+off, "\necho [max_count] > mac_learn_max_count_set   - Set max count of MAC learning \n");
+	off += sprintf(buf+off, "\tmax_count       (dec)Should not greater than PNC range size\n");
+
+	off += sprintf(buf+off, "\n");
+
+	off += sprintf(buf+off, "\necho [expired_time] > mac_learn_expired_time_set   - Set expired time for non-static MAC learning entry\n");
+	off += sprintf(buf+off, "\texpired_time    (dec)unit: second\n");
+
+	off += sprintf(buf+off, "\n");
+
+	off += sprintf(buf+off, "\necho [trace_level] > mac_learn_trace_level   - Set trace level for print info\n");
+	off += sprintf(buf+off, "\ttrace_level     (dec)0: no trace, 1: debug level, 2: warn level\n");
+
+	off += sprintf(buf+off, "\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+* sfs_mac_learn_static_entry_add
+*
+* DESCRIPTION:
+*           This function adds static MAC address as MAC learn entry
+*
+*
+*******************************************************************************/
+void sfs_mac_learn_static_entry_add(const char *buf, size_t len)
+{
+	typedef enum {
+		mac_learn_static_mac, mac_learn_static_max
+	} l2_mac_rule_parm_indx_t;
+
+	uint32_t sa[6];
+	char temp_sa[30];
+	int numparms;
+	char src_mac[6];
+	int parsedargs;
+
+	numparms = sys_mac_learn_count_para(buf);
+	if (numparms != mac_learn_static_max) {
+		MVMACLEARN_ERR_PRINT("Parameter number not right");
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%s", temp_sa);
+
+		if (sys_mac_learn_parse_addr(temp_sa, sa) == false) {
+			MVMACLEARN_ERR_PRINT("Invalid SA [%s]\n", temp_sa);
+		} else {
+			src_mac[0] = (char)sa[0];
+			src_mac[1] = (char)sa[1];
+			src_mac[2] = (char)sa[2];
+			src_mac[3] = (char)sa[3];
+			src_mac[4] = (char)sa[4];
+			src_mac[5] = (char)sa[5];
+			if (mv_mac_learn_static_entry_add(src_mac))
+				MVMACLEARN_ERR_PRINT("Faild to add static MAC entry");
+			else
+				printk("OK.\n");
+		}
+	}
+}
+
+/*******************************************************************************
+* sfs_mac_learn_static_entry_del
+*
+* DESCRIPTION:
+*           This function deletes static MAC address as MAC learn entry
+*
+*
+*******************************************************************************/
+void sfs_mac_learn_static_entry_del(const char *buf, size_t len)
+{
+	typedef enum {
+		mac_learn_static_mac, mac_learn_static_max
+	} l2_mac_rule_parm_indx_t;
+
+	uint32_t sa[6];
+	char temp_sa[30];
+	int numparms;
+	char src_mac[6];
+	int parsedargs;
+
+	numparms = sys_mac_learn_count_para(buf);
+	if (numparms != mac_learn_static_max) {
+		MVMACLEARN_ERR_PRINT("Parameter number not right");
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%s", temp_sa);
+
+		if (sys_mac_learn_parse_addr(temp_sa, sa) == false) {
+			MVMACLEARN_ERR_PRINT("Invalid SA [%s]\n", temp_sa);
+		} else {
+			src_mac[0] = (char)sa[0];
+			src_mac[1] = (char)sa[1];
+			src_mac[2] = (char)sa[2];
+			src_mac[3] = (char)sa[3];
+			src_mac[4] = (char)sa[4];
+			src_mac[5] = (char)sa[5];
+			if (mv_mac_learn_static_entry_del(src_mac))
+				MVMACLEARN_ERR_PRINT("Faild to del static MAC entry");
+			else
+				printk("OK.\n");
+		}
+	}
+}
+
+/*******************************************************************************
+* sfs_mac_learn_enable_cfg
+*
+* DESCRIPTION:
+*           This function enable or disable MAC learning
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_mac_learn_enable_cfg(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		mac_leanr_enable_bool, mac_leanr_enable_max
+	} mac_learn_enable_t;
+
+	uint32_t mac_learn_enable;
+	int parsedargs;
+	int numparms;
+
+	bool enable_para;
+
+	numparms = sys_mac_learn_count_para(buf);
+	if (numparms != mac_leanr_enable_max) {
+		MVMACLEARN_ERR_PRINT("Parameter number not right");
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d", &mac_learn_enable);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else {
+			if (mac_learn_enable)
+				enable_para = true;
+			else
+				enable_para = false;
+			if (mv_mac_learn_enable_set(enable_para))
+				MVMACLEARN_ERR_PRINT("Faild to enable/diable MAC learning\n");
+		}
+	}
+}
+
+/*******************************************************************************
+* sfs_mac_learn_overwrite_enable_cfg
+*
+* DESCRIPTION:
+*           This function enable or disable MAC learning overwrite when FDB full
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_mac_learn_overwrite_enable_cfg(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		mac_learn_overwrite_bool, mac_learn_overwrite_max
+	} mac_learn_overwrite_t;
+
+	uint32_t mac_learn_overwrite;
+	int parsedargs;
+	int numparms;
+
+	bool enable_para;
+
+	numparms = sys_mac_learn_count_para(buf);
+	if (numparms != mac_learn_overwrite_max) {
+		MVMACLEARN_ERR_PRINT("Parameter number not right");
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d", &mac_learn_overwrite);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else {
+			if (mac_learn_overwrite)
+				enable_para = true;
+			else
+				enable_para = false;
+			if (mv_mac_learn_overwrite_enable_set(enable_para))
+				MVMACLEARN_ERR_PRINT("Faild to enable/diable MAC learning overwrite function\n");
+		}
+	}
+}
+
+/*******************************************************************************
+* sfs_mac_learn_max_count_cfg
+*
+* DESCRIPTION:
+*           This function set the max count of mac leanr entry
+* INPUTS:
+*       buf - Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_mac_learn_max_count_cfg(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		mac_learn_max_count, mac_learn_max_count_max
+	} mac_learn_max_count_t;
+
+	uint32_t max_count;
+	int parsedargs;
+	int numparms;
+
+	numparms = sys_mac_learn_count_para(buf);
+	if (numparms != mac_learn_max_count_max) {
+		MVMACLEARN_ERR_PRINT("Parameter number not right");
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d", &max_count);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else {
+			if (mv_mac_learn_max_count_set(max_count))
+				MVMACLEARN_ERR_PRINT("Faild to cfg MAC learning max count\n");
+		}
+	}
+}
+
+/*******************************************************************************
+* sfs_mac_learn_expire_time_cfg
+*
+* DESCRIPTION:
+*           This function set the expired time of non-static mac leanr entry
+* INPUTS:
+*       buf - Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_mac_learn_expired_time_cfg(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		mac_learn_expire_time, mac_learn_expire_time_max
+	} mac_learn_expire_time_t;
+
+	uint32_t expire_time;
+	int parsedargs;
+	int numparms;
+
+	numparms = sys_mac_learn_count_para(buf);
+	if (numparms != mac_learn_expire_time_max) {
+		MVMACLEARN_ERR_PRINT("Parameter number not right");
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d", &expire_time);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else {
+			if (mv_mac_learn_expire_time_set(expire_time))
+				MVMACLEARN_ERR_PRINT("Faild to cfg MAC learning expired time\n");
+		}
+	}
+}
+
+/*******************************************************************************
+* sfs_mac_learn_trace_level_cfg
+*
+* DESCRIPTION:
+*           This function set the trace level of print info
+* INPUTS:
+*       buf - Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_mac_learn_trace_level_cfg(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		mac_learn_trace_level, mac_learn_trace_level_max
+	} mac_learn_trace_level_t;
+
+	uint32_t trace_level;
+	int parsedargs;
+	int numparms;
+
+	numparms = sys_mac_learn_count_para(buf);
+	if (numparms != mac_learn_trace_level_max) {
+		MVMACLEARN_ERR_PRINT("Parameter number not right");
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d", &trace_level);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else {
+			if (mv_mac_learn_op_trace_level_set(trace_level))
+				MVMACLEARN_ERR_PRINT("Faild to cfg MAC learning expired time\n");
+		}
+	}
+}
+
+/***********************************************************************************
+**
+**  sfs_help_mac_learn_show_all - help for mac learn sysfs commands under show folder
+**
+************************************************************************************/
+int sfs_help_mac_learn_show_all(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "\ncat show_mac_learn_enable             - show mac learn enable state\n");
+	off += sprintf(buf+off, "\ncat show_mac_learn_overwrite_enable   - show mac learn non-static entry overwrite enable state when FDB full\n");
+	off += sprintf(buf+off, "\ncat show_mac_learn_max_count          - show mac learn max entry count\n");
+	off += sprintf(buf+off, "\ncat show_mac_learn_expire_time        - show mac learn non-static entry expired time\n");
+	off += sprintf(buf+off, "\ncat show_mac_learn_fdb_entry          - show mac learn entries in FDB\n");
+
+	off += sprintf(buf+off, "\n");
+
+	return(off);
+}
+
+
+/*******************************************************************************
+* sfs_mac_learn_enable_get
+*
+* DESCRIPTION:
+*           This function show mac learn enable state
+*******************************************************************************/
+int sfs_mac_learn_enable_get(char *buf)
+{
+	int off = 0;
+	char result[8];
+	bool mac_learn_enable;
+
+	if (mv_mac_learn_enable_get(&mac_learn_enable)) {
+		memcpy(result, "failed", 8);
+	} else {
+		if (true == mac_learn_enable)
+			memcpy(result, "enable", 8);
+		else
+			memcpy(result, "disable", 8);
+	}
+	off += sprintf(buf+off, "\nmac learn enable get: %s\n", result);
+
+	return off;
+}
+
+/*******************************************************************************
+* sfs_mac_learn_overwrite_enable_get
+*
+* DESCRIPTION:
+*           This function show mac learn overwrite enable state when FDB full
+*******************************************************************************/
+int sfs_mac_learn_overwrite_enable_get(char *buf)
+{
+	int off = 0;
+	char result[8];
+	bool mac_learn_enable;
+
+	if (mv_mac_learn_overwrite_enable_get(&mac_learn_enable)) {
+		memcpy(result, "failed", 8);
+	} else {
+		if (true == mac_learn_enable)
+			memcpy(result, "enable", 8);
+		else
+			memcpy(result, "disable", 8);
+	}
+	off += sprintf(buf+off, "\nmac learn overwrite enable get: %s\n", result);
+
+	return off;
+}
+
+/*******************************************************************************
+* sfs_mac_learn_max_count_get
+*
+* DESCRIPTION:
+*           This function show mac learn MAX entry count configured
+*******************************************************************************/
+int sfs_mac_learn_max_count_get(char *buf)
+{
+	int off = 0;
+	char result[8];
+	uint32_t max_count;
+
+	if (mv_mac_learn_max_count_get(&max_count)) {
+		memcpy(result, "failed", 8);
+		off += sprintf(buf+off, "\nmac learn max count get: %s\n", result);
+	} else {
+		off += sprintf(buf+off, "\nmac learn max count get: %d\n", max_count);
+	}
+
+	return off;
+}
+
+/**************************************************************************************
+* sfs_mac_learn_expired_time_get
+*
+* DESCRIPTION:
+*           This function show mac learn expired time configured for non-static entry
+***************************************************************************************/
+int sfs_mac_learn_expired_time_get(char *buf)
+{
+	int off = 0;
+	char result[8];
+	uint32_t expire_time;
+
+	if (mv_mac_learn_expire_time_get(&expire_time)) {
+		memcpy(result, "failed", 8);
+		off += sprintf(buf+off, "\nmac learn expire time get: %s\n", result);
+	} else {
+		off += sprintf(buf+off, "\nmac learn expire time get: %d(s)\n", expire_time);
+	}
+
+	return off;
+}
+
+/**************************************************************************************
+* sfs_mac_learn_entry_print
+*
+* DESCRIPTION:
+*           This function print the MAC learning entries learned
+***************************************************************************************/
+int sfs_mac_learn_entry_print(char *buf)
+{
+	int off = 0;
+
+	mac_learn_db_valid_print();
+
+	return off;
+}
+
+
+
+static mac_learn_store_sysfs_func_t mac_learn_sysfs_func_ara[] =
+{
+	{"mac_learn_static_entry_add", sfs_mac_learn_static_entry_add},
+	{"mac_learn_static_entry_del", sfs_mac_learn_static_entry_del},
+	{"mac_learn_enable",           sfs_mac_learn_enable_cfg},
+	{"mac_learn_overwrite_enable", sfs_mac_learn_overwrite_enable_cfg},
+	{"mac_learn_max_count_set",    sfs_mac_learn_max_count_cfg},
+	{"mac_learn_expired_time_set", sfs_mac_learn_expired_time_cfg},
+	{"mac_learn_trace_level",      sfs_mac_learn_trace_level_cfg},
+};
+
+static int mac_learn_num_store = sizeof(mac_learn_sysfs_func_ara)/sizeof(mac_learn_sysfs_func_ara[0]);
+
+static ssize_t mac_learn_cfg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char *name = attr->attr.name;
+	mac_learn_store_sysfs_func_t *pnamefunc;
+	int indx;
+	bool found = false;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	for (indx = 0; indx < mac_learn_num_store; indx++){
+		pnamefunc = &mac_learn_sysfs_func_ara[indx];
+		if (!strcmp(name, pnamefunc->sysfs_name)) {
+			found = true;
+			(pnamefunc->sysfs_func)(buf, len);
+			break;
+		}
+	}
+
+	if (found == false){
+		printk("%s: operation <%s> not found\n", __FUNCTION__, attr->attr.name);
+	}
+
+	return(len);
+}
+
+static mac_learn_show_sysfs_func_t mac_learn_show_sysfs_func_ara[] =
+{
+	{"help_mac_learn_cfg", sfs_help_mac_learn_cfg_all},
+	{"help_mac_learn_show", sfs_help_mac_learn_show_all},
+	{"show_mac_learn_enable", sfs_mac_learn_enable_get},
+	{"show_mac_learn_overwrite_enable", sfs_mac_learn_overwrite_enable_get},
+	{"show_mac_learn_max_count", sfs_mac_learn_max_count_get},
+	{"show_mac_learn_expire_time", sfs_mac_learn_expired_time_get},
+	{"show_mac_learn_fdb_entry", sfs_mac_learn_entry_print},
+
+};
+
+static int mac_learn_num_show = sizeof(mac_learn_show_sysfs_func_ara)/sizeof(mac_learn_show_sysfs_func_ara[0]);
+
+
+static ssize_t mac_learn_cfg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	const char *name = attr->attr.name;
+	mac_learn_show_sysfs_func_t *pnamefunc;
+	int indx;
+	bool found = false;
+	int buflen = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	for (indx = 0; indx < mac_learn_num_show; indx++){
+		pnamefunc = &mac_learn_show_sysfs_func_ara[indx];
+		if (!strcmp(name, pnamefunc->sysfs_name)) {
+			found = true;
+			buflen = (pnamefunc->sysfs_func)(buf);
+			break;
+		}
+	}
+	if (found == false){
+		printk("%s: operation <%s> not found\n", __FUNCTION__, attr->attr.name);
+	}
+
+	return buflen;
+}
+
+/*store attr*/
+static DEVICE_ATTR(mac_learn_static_entry_add, S_IWUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(mac_learn_static_entry_del, S_IWUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(mac_learn_enable, S_IWUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(mac_learn_overwrite_enable, S_IWUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(mac_learn_max_count_set, S_IWUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(mac_learn_expired_time_set, S_IWUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(mac_learn_trace_level, S_IWUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+
+/*show attr*/
+static DEVICE_ATTR(help_mac_learn_cfg, S_IRUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(help_mac_learn_show, S_IRUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(show_mac_learn_enable, S_IRUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(show_mac_learn_overwrite_enable, S_IRUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(show_mac_learn_max_count, S_IRUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(show_mac_learn_expire_time, S_IRUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+static DEVICE_ATTR(show_mac_learn_fdb_entry, S_IRUSR, mac_learn_cfg_show, mac_learn_cfg_store);
+
+
+
+static struct attribute *mac_learn_cfg_attrs[] =
+{
+	&dev_attr_help_mac_learn_cfg.attr,
+	&dev_attr_mac_learn_static_entry_add.attr,
+	&dev_attr_mac_learn_static_entry_del.attr,
+	&dev_attr_mac_learn_enable.attr,
+	&dev_attr_mac_learn_overwrite_enable.attr,
+	&dev_attr_mac_learn_max_count_set.attr,
+	&dev_attr_mac_learn_expired_time_set.attr,
+	&dev_attr_mac_learn_trace_level.attr,
+
+	NULL
+};
+
+static struct attribute *mac_learn_show_attrs[] =
+{
+	&dev_attr_help_mac_learn_show.attr,
+	&dev_attr_show_mac_learn_enable.attr,
+	&dev_attr_show_mac_learn_overwrite_enable.attr,
+	&dev_attr_show_mac_learn_max_count.attr,
+	&dev_attr_show_mac_learn_expire_time.attr,
+	&dev_attr_show_mac_learn_fdb_entry.attr,
+	NULL
+};
+
+
+static struct attribute_group mac_learn_cfg_group =
+{
+	.name = "mac_learn_cfg",
+	.attrs = mac_learn_cfg_attrs
+};
+
+static struct attribute_group mac_learn_show_group =
+{
+	.name = "mac_learn_show",
+	.attrs = mac_learn_show_attrs
+};
+
+static mv_attr_group_pair_t mac_learn_attr_group_pair[] =
+{
+	{"mac_learn_cfg",          &mac_learn_cfg_group},
+	{"mac_learn_show",         &mac_learn_show_group},
+};
+static int num_attr_group_pairs = sizeof(mac_learn_attr_group_pair)/sizeof(mac_learn_attr_group_pair[0]);
+
+/*******************************************************************************
+* mv_mac_learn_sysfs_init()
+*
+* DESCRIPTION:    Finish all initialization for sysfs.
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* int, success--0; failed--non-zero
+*******************************************************************************/
+int mv_mac_learn_sysfs_init(void)
+{
+	int err;
+	struct device *pd;
+	int indx;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "mc_mac_learn");
+	if (!pd) {
+		platform_device_register_simple("mc_mac_learn", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "mc_mac_learn");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR"%s: cannot find mc_mac_learn device\n", __FUNCTION__);
+		pd = &platform_bus;
+	}
+
+	for (indx = 0; indx < num_attr_group_pairs; indx++) {
+		mv_attr_group_pair_t *ppair;
+
+		ppair = &mac_learn_attr_group_pair[indx];
+
+		err = sysfs_create_group(&pd->kobj, ppair->pattrgroup);
+		if (err) {
+			printk(KERN_INFO "sysfs_create_group failed for %s, err = %d\n", ppair->folder_name, err);
+			goto out;
+		}
+	}
+	printk(KERN_INFO "= MC MAC LEARN Module SYS FS Init ended successfully =\n");
+
+out:
+	return err;
+}
+
+/*******************************************************************************
+* mv_mac_learn_sysfs_exit()
+*
+* DESCRIPTION:    unregister sysfs if exit
+*
+* INPUTS:
+* None
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+* None
+*******************************************************************************/
+void mv_mac_learn_sysfs_exit(void)
+{
+	struct device *pd;
+	int indx;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "mc_mac_learn");
+	if (!pd) {
+		printk(KERN_ERR"%s: cannot find mc_mac_learn device\n", __FUNCTION__);
+		return;
+	}
+
+	for (indx = 0; indx < num_attr_group_pairs; indx++) {
+		mv_attr_group_pair_t *ppair;
+		ppair = &mac_learn_attr_group_pair[indx];
+		sysfs_remove_group(&pd->kobj, ppair->pattrgroup);
+	}
+
+	printk(KERN_INFO "= MC MAC LEARN Module SYS FS Remove ended successfully =\n");
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.h
new file mode 100755
index 0000000..3017992
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mac_learn/mv_mac_learn_sysfs.h
@@ -0,0 +1,64 @@
+/************************************************************************
+* Copyright (C) 2010, Marvell Technology Group Ltd.
+* All Rights Reserved.
+*
+* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group;
+* the contents of this file may not be disclosed to third parties, copied
+* or duplicated in any form, in whole or in part, without the prior
+* written permission of Marvell Technology Group.
+*
+*********************************************************************************
+* Marvell GPL License Option
+*
+* If you received this File from Marvell, you may opt to use, redistribute and/or
+* modify this File in accordance with the terms and conditions of the General
+* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+* available along with the File in the license.txt file or by writing to the Free
+* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+*
+* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+* DISCLAIMED.  The GPL License provides additional details about this warranty
+* disclaimer.
+*
+*********************************************************************************
+* mv_mac_learn_sysfs.h
+*
+* DESCRIPTION:
+*
+*
+*******************************************************************************/
+#ifndef __mv_mac_learn_sysfs_h__
+#define __mv_mac_learn_sysfs_h__
+
+/* Include files
+------------------------------------------------------------------------------*/
+#include <linux/capability.h>
+#include <linux/platform_device.h>
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+typedef struct {
+	char                   *folder_name;
+	struct attribute_group *pattrgroup;
+} mv_attr_group_pair_t;
+
+typedef struct
+{
+	char *sysfs_name;
+	void (*sysfs_func)(const char *buf, size_t len);
+} mac_learn_store_sysfs_func_t;
+
+typedef struct
+{
+	char *sysfs_name;
+	int (*sysfs_func)(char *buf);
+} mac_learn_show_sysfs_func_t;
+
+/* Function protype
+------------------------------------------------------------------------------*/
+int mv_mac_learn_sysfs_init(void);
+void mv_mac_learn_sysfs_exit(void);
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/Makefile
new file mode 100755
index 0000000..cd03800
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/Makefile
@@ -0,0 +1,9 @@
+
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+ 
+obj-$(CONFIG_MV_INCLUDE_SFLASH_MTD) += sflash.o
+obj-$(CONFIG_MV_INCLUDE_MFLASH_MTD) += mflash.o
+obj-$(CONFIG_MTD_NAND_LNC)          += nand_lnc.o
+obj-$(CONFIG_MTD_NAND_NFC)          += nand_nfc.o
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/mflash.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/mflash.c
new file mode 100755
index 0000000..bd08825
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/mflash.c
@@ -0,0 +1,361 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <mflash/mvMFlash.h>
+#include "mflash/mvMFlashSpec.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+/*#define MTD_MFLASH_DEBUG*/
+
+#ifdef MTD_MFLASH_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+
+/* Configuration options */
+static struct mtd_info *mflash_probe(struct map_info *map);
+static void mflash_destroy(struct mtd_info *mtd);
+static int mflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+static int mflash_write(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, const u_char *buf);
+static int mflash_erase(struct mtd_info *mtd, struct erase_info *instr);
+static void mflash_sync(struct mtd_info *mtd);
+static int mflash_suspend(struct mtd_info *mtd);
+static void mflash_resume(struct mtd_info *mtd);
+static int mflash_lock (struct mtd_info *mtd, loff_t ofs, size_t len);
+static int mflash_unlock (struct mtd_info *mtd, loff_t ofs, size_t len);
+static int mflash_block_isbad (struct mtd_info *mtd, loff_t ofs);
+static int mflash_block_markbad (struct mtd_info *mtd, loff_t ofs);
+
+static struct mtd_chip_driver mflash_chipdrv = {
+	.probe		= mflash_probe,
+	.destroy	= mflash_destroy,
+	.name		= "mflash",
+	.module		= THIS_MODULE
+};
+
+
+static struct mtd_info *mflash_probe(struct map_info *map)
+{
+	struct mtd_info *mtd = NULL;
+	MV_MFLASH_INFO *mflash = NULL;
+	
+	DB(printk("\nINFO: enterring %s",__FUNCTION__));
+
+	/* allocate the memory for the mtd_info */
+	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	if(!mtd)
+	{
+		printk(KERN_NOTICE "\nERROR: %s - Failed to allocate memory for mtd structure",__FUNCTION__);
+		return NULL;
+	}
+
+	/* allocate memory for the mflash private structure */
+	mflash = kmalloc(sizeof(MV_MFLASH_INFO), GFP_KERNEL);
+	if(!mflash) 
+	{
+		printk(KERN_NOTICE "\nERROR: %s - Failed to allocate memory for mflash structure",__FUNCTION__);
+		kfree(mtd);
+		return NULL;
+	}
+		
+	/* clear both structures before usage */
+	memset(mtd, 0, sizeof(*mtd));
+	memset(mflash, 0, sizeof(*mflash));
+	    
+	DB(printk("\nINFO: %s - Base address %08x",__FUNCTION__, mflash->baseAddr));
+	
+    /* based on the SPI mode try to detect the Mflash device interface type */
+    if (mvCtrlSpiBusModeDetect() == MV_SPI_CONN_TO_MFLASH)
+        mflash->ifMode = MV_MFLASH_SPI; 
+    else               
+        mflash->ifMode = MV_MFLASH_PARALLEL;
+	
+	/* Try to detect the Marvell flash and initialize */	
+	mflash->baseAddr = map->phys;
+	if (mvMFlashInit(mflash) != MV_OK)
+	{
+		printk(KERN_NOTICE "ERROR: %s - Failed to initialize the mflash.", __FUNCTION__);
+		kfree(mtd);
+		kfree(mflash);
+		return NULL;
+	}
+	
+	if (mvMFlashSectorSizeSet(mflash, 0x1000 /*4K*/) != MV_OK)
+	{
+		printk(KERN_NOTICE "ERROR: %s - Failed to sector sector size to small.", __FUNCTION__);
+		kfree(mtd);
+		kfree(mflash);
+		return NULL;
+	}
+	
+	/* After success fill in the MTD structure with the appropriate info */
+	mtd->erasesize = mflash->sectorSize;
+	mtd->size = mflash->sectorSize * mflash->sectorNumber;
+	mtd->priv = map;
+	mtd->type = MTD_NORFLASH;
+	mtd->erase = mflash_erase;
+	mtd->read = mflash_read;
+	mtd->write = mflash_write;
+	mtd->sync = mflash_sync;
+	mtd->suspend = mflash_suspend;
+	mtd->resume = mflash_resume;	
+	mtd->lock = mflash_lock;
+	mtd->unlock = mflash_unlock;
+	mtd->block_isbad = mflash_block_isbad;
+	mtd->block_markbad = mflash_block_markbad;	
+	mtd->flags = (MTD_WRITEABLE | MTD_BIT_WRITEABLE); /* just like MTD_CAP_NORFLASH */
+	mtd->name = map->name;
+	mtd->writesize = 1;
+	
+	map->fldrv = &mflash_chipdrv;
+	map->fldrv_priv = mflash;
+	
+	/* Print some debug messages with the detected mflash info */
+	DB(printk("\nINFO: %s - Detected mflash device (size %d)", __FUNCTION__, mtd->size));
+	DB(printk("\n           Base Address    : 0x%08x", mflash->baseAddr));
+	DB(printk("\n           Interface Mode  : %d", mflash->ifMode));
+	DB(printk("\n           Sector Size     : 0x%x", mflash->sectorSize));
+	DB(printk("\n           Sector Number   : %d", mflash->sectorNumber));
+	DB(printk("\n           Info Region Size: 0x%x", mflash->infoSize));
+	
+	printk("Marvell Flash Detected @ 0x%08x, %dKB Main region (%dsec x %dKB), %dKB Information region\n",
+	         mflash->baseAddr, ((mflash->sectorNumber * mflash->sectorSize)/1024),
+	         mflash->sectorNumber, (mflash->sectorSize/1024), (mflash->infoSize/1024));
+	
+	__module_get(THIS_MODULE);
+	return mtd;
+}
+
+static void mflash_destroy(struct mtd_info *mtd)
+{
+	struct map_info *map = mtd->priv;
+	MV_MFLASH_INFO *mflash = map->fldrv_priv;
+
+	DB(printk("\nINFO: %s called", __FUNCTION__));
+
+	/* free memory allocated at probe for the private mflash structure */
+	if (mflash)
+		kfree(mflash);	
+}
+
+static int mflash_read(struct mtd_info *mtd, loff_t from, size_t len,
+	size_t *retlen, u_char *buf)
+{
+	struct map_info *map = mtd->priv;
+	MV_MFLASH_INFO *mflash = map->fldrv_priv;
+	MV_U32 offset = ((MV_U32)from);
+	
+	*retlen = 0;
+
+	DB(printk("\nINFO: %s  - offset %08x, len %d",__FUNCTION__, offset, (int)len));
+		
+	if (mvMFlashBlockRd(mflash, offset, len, buf) != MV_OK)
+	{
+		printk(KERN_NOTICE "\nERROR: %s - Failed to read block.", __FUNCTION__);
+		return -1;
+	}
+	
+	*retlen = len;
+	
+	DB(printk(" - OK"));
+
+	return 0;	
+}
+
+static int mflash_write(struct mtd_info *mtd, loff_t to, size_t len,
+	size_t *retlen, const u_char *buf)
+{
+	struct map_info *map = mtd->priv;
+	MV_MFLASH_INFO *mflash = map->fldrv_priv;
+	MV_U32 offset = ((MV_U32)to);
+	
+	*retlen = 0;
+	
+	DB(printk("\nINFO: %s - offset %08x, len %d",__FUNCTION__, offset, len));
+		
+	if (mvMFlashBlockWr(mflash, offset, len, (MV_U8*)buf, MV_FALSE) != MV_OK)
+	{
+		printk(KERN_NOTICE "\nERROR: %s - Failed to write block", __FUNCTION__);
+		return -1;
+	}
+	
+	*retlen = len;
+	
+	DB(printk(" - OK"));
+
+	return 0;	
+
+}
+
+
+static int mflash_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct map_info *map = mtd->priv;
+	MV_MFLASH_INFO *mflash = map->fldrv_priv;
+	MV_U32 fsec, lsec;
+	int i;
+
+	DB(printk("\nINFO: %s - Addr %08x, len %d",__FUNCTION__, instr->addr, instr->len));
+	
+	if(instr->addr & (mtd->erasesize - 1))
+	{
+		printk(KERN_NOTICE "\nError: %s - Erase address not sector alligned",__FUNCTION__);
+		return -EINVAL;
+	}
+	if(instr->len & (mtd->erasesize - 1))
+	{
+		printk(KERN_NOTICE "\nError: %s - Erase length is not sector alligned",__FUNCTION__);
+		return -EINVAL;
+	}
+	if(instr->len + instr->addr > mtd->size)
+	{
+		printk(KERN_NOTICE "\nError: %s - Erase exceeded flash size",__FUNCTION__);
+		return -EINVAL;
+	}
+
+	fsec = (instr->addr / mtd->erasesize);
+	lsec = (fsec +(instr->len / mtd->erasesize));
+	
+	DB(printk("\nINFO: %s - from sector %u to %u",__FUNCTION__, fsec, lsec));
+	
+	for (i=fsec; i<lsec; i++)
+	{
+		if (mvMFlashSecErase(mflash, i) != MV_OK)
+		{
+			printk(KERN_NOTICE "\nError: %s - mvMFlashSecErase on sector %d",__FUNCTION__, i);
+			return -1;
+		}
+	}
+	
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int mflash_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+	struct map_info *map = mtd->priv;
+	MV_MFLASH_INFO *mflash = map->fldrv_priv;
+	
+	DB(printk("\nINFO: %s called", __FUNCTION__));
+	
+	if (mvMFlashWriteProtectSet(mflash, MV_TRUE) != MV_OK)
+	{
+		printk(KERN_NOTICE "\nError: %s - mvmflashWpRegionSet failed",__FUNCTION__);
+		return -1;
+	}
+	
+	printk("\nNotice: Marvell flash (%s) lock per sector is not supported!\n        Locking the whole device.", mtd->name);
+		
+	return 0;
+}
+
+static int mflash_unlock (struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+	struct map_info *map = mtd->priv;
+	MV_MFLASH_INFO *mflash = map->fldrv_priv;
+
+	DB(printk("\nINFO: %s called", __FUNCTION__));
+	
+	if (mvMFlashWriteProtectSet(mflash, MV_FALSE) != MV_OK)
+	{
+		printk(KERN_NOTICE "\nError: %s - mvmflashWpRegionSet failed",__FUNCTION__);
+		return -1;
+	}
+		
+	printk("\nNotice: Marvell flash (%s) unlock per sector is not supported!\n        Unlocking the whole device.", mtd->name);
+	return 0;
+}
+
+static void mflash_sync(struct mtd_info *mtd)
+{
+	DB(printk("\nINFO: %s called - DUMMY", __FUNCTION__));
+}
+
+static int mflash_suspend(struct mtd_info *mtd)
+{
+	DB(printk("\nINFO: %s called - DUMMY()", __FUNCTION__));
+	return 0;
+}
+
+static void mflash_resume(struct mtd_info *mtd)
+{
+	DB(printk("\nINFO: %s called - DUMMY", __FUNCTION__));
+}
+
+static int mflash_block_isbad (struct mtd_info *mtd, loff_t ofs)
+{
+	DB(printk("\nINFO: %s called - DUMMY", __FUNCTION__));
+	return 0;
+}
+
+static int mflash_block_markbad (struct mtd_info *mtd, loff_t ofs)
+{
+	DB(printk("\nINFO: %s called - DUMMY", __FUNCTION__));
+	return 0;
+}
+
+static int __init mflash_probe_init(void)
+{
+	DB(printk("\nINFO: %s - MTD mflash chip driver.", __FUNCTION__));
+
+	register_mtd_chip_driver(&mflash_chipdrv);
+
+	return 0;
+}
+
+static void __exit mflash_probe_exit(void)
+{
+	DB(printk(KERN_ALERT "\nINFO: %s - MTD mflash driver exit", __FUNCTION__));
+	unregister_mtd_chip_driver(&mflash_chipdrv);
+}
+
+module_init(mflash_probe_init);
+module_exit(mflash_probe_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("MTD chip driver for the Marvell SUNOL flash device");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_lnc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_lnc.c
new file mode 100755
index 0000000..571e4d5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_lnc.c
@@ -0,0 +1,690 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+#include <asm/io.h>
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "boardEnv/mvBoardEnvLib.h"
+
+#ifdef	CONFIG_MTD_NAND_LNC_RS_ECC
+#include "nand_lnc.h"
+#endif
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt, arg...)	mvOsPrintf(KERN_INFO fmt, ##arg)
+#else
+#define DBG(fmt, arg...)
+#endif
+
+extern MV_U32    boardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devType);
+
+static struct mtd_info *mv_mtd;
+static unsigned long baseaddr;
+
+unsigned int mv_nand_ecc;
+
+#ifdef CONFIG_MTD_PARTITIONS
+extern struct mtd_partition nand_parts_info[];
+extern int nand_parts_num;
+
+static const char *part_probes[] __initdata = { "cmdlinepart", NULL };
+#define MV_NUM_OF_NAND_PARTS nand_parts_num
+#endif
+
+static void board_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *this = (struct nand_chip *)mtd->priv;
+	if (ctrl & NAND_CTRL_CHANGE) {
+		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~3);
+		ctrl &= ~NAND_CTRL_CHANGE;
+		switch (ctrl) {
+		case NAND_CTRL_CLE:
+			this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | 1); /*x8=>1, x16=>2*/
+			break;
+		case NAND_CTRL_ALE:
+			this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | 2); /*x8=>2, x16=>4*/
+			break;
+		}
+	}
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, this->IO_ADDR_W);
+}
+
+static void mv_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	void __iomem *io_base = chip->IO_ADDR_R;
+	uint64_t *buf64;
+	int i = 0;
+
+	while (len && (unsigned long)buf & 7) {
+		*buf++ = readb(io_base);
+		len--;
+	}
+
+	buf64 = (uint64_t *)buf;
+	while (i < len/8) {
+		uint64_t x;
+		__asm__ __volatile__ ("ldrd\t%0, [%1]" : "=r" (x) : "r" (io_base));
+		buf64[i++] = x;
+	}
+
+	i *= 8;
+	while (i < len)
+		buf[i++] = readb(io_base);
+}
+
+
+int __init mv_nand_init(void)
+{
+	struct nand_chip *this;
+	int err = 0;
+	int num_of_parts = 0;
+	const char *part_type = 0;
+	struct mtd_partition *mtd_parts = 0;
+	u32 physaddr;
+	int nand_dev_num;
+	MV_CPU_DEC_WIN addr_win;
+
+	nand_dev_num = boardGetDevCSNum(0, BOARD_DEV_NAND_FLASH);
+	if (-1 == nand_dev_num) {
+		printk(KERN_INFO "NAND init: NAND device not found on board\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (MV_OK != mvCpuIfTargetWinGet((nand_dev_num), &addr_win)) {
+		printk(KERN_INFO "Failed to init NAND MTD (boot-CS window %d err).\n", nand_dev_num);
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (!addr_win.enable) {
+		printk(KERN_INFO "Failed to init NAND MTD (boot-CS window disabled).\n");
+		err = -ENODEV;
+		goto out;
+	}
+	physaddr = addr_win.addrWin.baseLow;
+
+	mv_mtd = kmalloc(sizeof(struct mtd_info)+sizeof(struct nand_chip), GFP_KERNEL);
+	if (!mv_mtd) {
+		printk(KERN_INFO "Failed to allocate NAND MTD structure\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	memset((char *)mv_mtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip));
+
+	baseaddr = (unsigned long)ioremap(physaddr, 1024);
+	if (!baseaddr) {
+		printk(KERN_INFO "Failed to remap NAND MTD\n");
+		err = -EIO;
+		goto out_mtd;
+	}
+
+	this = (struct nand_chip *)((char *)mv_mtd+sizeof(struct mtd_info));
+	mv_mtd->priv = this;
+	this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)baseaddr;
+	this->cmd_ctrl = board_hwcontrol;
+#ifdef	CONFIG_MTD_NAND_LNC_8BYTE_READ
+	this->read_buf = mv_nand_read_buf;
+#endif
+#ifdef	CONFIG_MTD_NAND_LNC_RS_ECC
+	printk(KERN_INFO "Using %s ECC for NAND device\n", (mv_nand_ecc == MV_NAND_ECC_4BIT ?
+		"Reed-Solomon 4-bit" : "Hamming 1-bit"));
+	if (mv_nand_ecc == MV_NAND_ECC_4BIT) {
+		this->ecc.hwctl		= mv_nand_enable_hwecc;
+		this->ecc.calculate	= mv_nand_calculate_ecc_rs;
+		this->ecc.correct	= mv_nand_correct_data_rs;
+		this->ecc.size		= 512;
+		this->ecc.bytes		= 10;
+		this->ecc.layout	= &mv_nand_rs_oobinfo;
+		this->ecc.mode		= NAND_ECC_HW;
+	} else
+#endif
+		this->ecc.mode = NAND_ECC_SOFT;
+
+	this->chip_delay = 30;
+	if (nand_scan(mv_mtd, 1)) {
+		err = -ENXIO;
+		goto out_ior;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	mv_mtd->name = "nand_mtd";
+	num_of_parts = parse_mtd_partitions(mv_mtd, part_probes, &mtd_parts, 0, "");
+	if (num_of_parts > 0)
+		part_type = "command line";
+	else
+		num_of_parts = 0;
+	if (num_of_parts == 0) {
+		mtd_parts = nand_parts_info;
+		num_of_parts = MV_NUM_OF_NAND_PARTS;
+		part_type = "static";
+	}
+
+	printk(KERN_INFO "Using %s partition definition\n", part_type);
+	add_mtd_partitions(mv_mtd, mtd_parts, num_of_parts);
+#endif
+	goto out;
+
+out_ior:
+	iounmap((void *)baseaddr);
+out_mtd:
+	kfree(mv_mtd);
+out:
+	return err;
+}
+
+module_init(mv_nand_init);
+
+#ifdef MODULE
+static void __exit board_cleanup(void)
+{
+	nand_release(mv_mtd);
+	iounmap((void *)baseaddr);
+	kfree(mv_mtd);
+}
+module_exit(board_cleanup);
+#endif
+
+#ifdef CONFIG_MTD_NAND_LNC_RS_ECC
+
+#define mm 10	  /* RS code over GF(2**mm) - the size in bits of a symbol*/
+#define	nn 1023   /* nn=2^mm -1   length of codeword */
+#define tt 4      /* number of errors that can be corrected */
+#define kk 1015   /* kk = number of information symbols  kk = nn-2*tt  */
+
+
+static char rs_initialized = 0;
+
+//typedef unsigned int gf;
+typedef u_short tgf;  /* data type of Galois Functions */
+
+/* Primitive polynomials -  irriducibile polynomial  [ 1+x^3+x^10 ]*/
+short pp[mm+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
+
+
+/* index->polynomial form conversion table */
+tgf alpha_to[nn + 1];
+
+/* Polynomial->index form conversion table */
+tgf index_of[nn + 1];
+
+/* Generator polynomial g(x) = 2*tt with roots @, @^2, .. ,@^(2*tt) */
+tgf Gg[nn - kk + 1];
+
+
+#define	minimum(a,b)	((a) < (b) ? (a) : (b))
+
+#define	BLANK(a,n) {\
+	short ci;\
+	for(ci=0; ci<(n); ci++)\
+		(a)[ci] = 0;\
+	}
+
+#define	COPY(a,b,n) {\
+	short ci;\
+	for(ci=(n)-1;ci >=0;ci--)\
+		(a)[ci] = (b)[ci];\
+	}
+#define	COPYDOWN(a,b,n) {\
+	short ci;\
+	for(ci=(n)-1;ci >=0;ci--)\
+		(a)[ci] = (b)[ci];\
+	}
+
+
+/* generate GF(2^m) from the irreducible polynomial p(X) in p[0]..p[mm]
+   lookup tables:  index->polynomial form   alpha_to[] contains j=alpha^i;
+                   polynomial form -> index form  index_of[j=alpha^i] = i
+   alpha=2 is the primitive element of GF(2^m) 
+*/
+
+void generate_gf(void)
+{
+	register int i, mask;
+
+	mask = 1;
+	alpha_to[mm] = 0;
+	for (i = 0; i < mm; i++) {
+		alpha_to[i] = mask;
+		index_of[alpha_to[i]] = i;
+		if (pp[i] != 0)
+			alpha_to[mm] ^= mask;
+		mask <<= 1;
+	}
+	index_of[alpha_to[mm]] = mm;
+
+	mask >>= 1;
+	for (i = mm + 1; i < nn; i++) {
+		if (alpha_to[i - 1] >= mask)
+			alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i - 1] ^ mask) << 1);
+		else
+			alpha_to[i] = alpha_to[i - 1] << 1;
+		index_of[alpha_to[i]] = i;
+	}
+	index_of[0] = nn;
+	alpha_to[nn] = 0;
+}
+
+
+/*
+ * Obtain the generator polynomial of the tt-error correcting, 
+ * length nn = (2^mm -1) 
+ * Reed Solomon code from the product of (X + @^i), i=1..2*tt
+*/
+void gen_poly(void)
+{
+	register int i, j;
+
+	Gg[0] = alpha_to[1]; /* primitive element*/ 
+	Gg[1] = 1;		     /* g(x) = (X+@^1) initially */
+	for (i = 2; i <= nn - kk; i++) {
+		Gg[i] = 1;
+		/*
+		 * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by
+		 * (@^i + x)
+		 */
+		for (j = i - 1; j > 0; j--)
+			if (Gg[j] != 0)
+				Gg[j] = Gg[j - 1] ^ alpha_to[((index_of[Gg[j]]) + i)%nn];
+			else
+				Gg[j] = Gg[j - 1];
+		Gg[0] = alpha_to[((index_of[Gg[0]]) + i) % nn];
+	}
+	/* convert Gg[] to index form for quicker encoding */
+	for (i = 0; i <= nn - kk; i++)
+		Gg[i] = index_of[Gg[i]];
+}
+
+
+/*
+ * take the string of symbols in data[i], i=0..(k-1) and encode
+ * systematically to produce nn-kk parity symbols in bb[0]..bb[nn-kk-1] data[]
+ * is input and bb[] is output in polynomial form. Encoding is done by using
+ * a feedback shift register with appropriate connections specified by the
+ * elements of Gg[], which was generated above. Codeword is   c(X) =
+ * data(X)*X**(nn-kk)+ b(X)
+ */
+static inline char encode_rs(dtype data[kk], dtype bb[nn-kk])
+{
+	register int i, j;
+	tgf feedback;
+
+	BLANK(bb,nn-kk);
+	for (i = kk - 1; i >= 0; i--) {
+		if(data[i] > nn)
+			return -1;	/* Illegal symbol */
+		feedback = index_of[data[i] ^ bb[nn - kk - 1]];
+		if (feedback != nn) {	/* feedback term is non-zero */
+			for (j = nn - kk - 1; j > 0; j--)
+				if (Gg[j] != nn)					
+					bb[j] = bb[j - 1] ^ alpha_to[(Gg[j] + feedback)%nn];
+				else
+					bb[j] = bb[j - 1];			
+			bb[0] = alpha_to[(Gg[0] + feedback)%nn];
+		} else {	
+			for (j = nn - kk - 1; j > 0; j--)
+				bb[j] = bb[j - 1];
+			bb[0] = 0;
+		}
+	}
+	return 0;
+}
+
+
+
+
+/* assume we have received bits grouped into mm-bit symbols in data[i],
+   i=0..(nn-1), We first compute the 2*tt syndromes, then we use the 
+   Berlekamp iteration to find the error location polynomial  elp[i].   
+   If the degree of the elp is >tt, we cannot correct all the errors
+   and hence just put out the information symbols uncorrected. If the 
+   degree of elp is <=tt, we  get the roots, hence the inverse roots, 
+   the error location numbers. If the number of errors located does not 
+   equal the degree of the elp, we have more than tt errors and cannot 
+   correct them.  Otherwise, we then solve for the error value at the 
+   error location and correct the error.The procedure is that found in
+   Lin and Costello.*/
+
+static inline int decode_rs(dtype data[nn])
+{
+	int deg_lambda, el, deg_omega;
+	int i, j, r;
+	tgf q,tmp,num1,num2,den,discr_r;
+	tgf recd[nn];
+	tgf lambda[nn-kk + 1], s[nn-kk + 1];	/* Err+Eras Locator poly
+						                 * and syndrome poly  */
+	tgf b[nn-kk + 1], t[nn-kk + 1], omega[nn-kk + 1];
+	tgf root[nn-kk], reg[nn-kk + 1], loc[nn-kk];
+	int syn_error, count;
+
+	
+
+	/* data[] is in polynomial form, copy and convert to index form */
+	for (i = nn-1; i >= 0; i--){
+
+	  if(data[i] > nn)
+		return -1;	/* Illegal symbol */
+
+	  recd[i] = index_of[data[i]];
+	}
+
+	/* first form the syndromes; i.e., evaluate recd(x) at roots of g(x)
+	 * namely @**(1+i), i = 0, ... ,(nn-kk-1)
+	 */
+
+	syn_error = 0;
+
+	for (i = 1; i <= nn-kk; i++) {
+		tmp = 0;
+		
+		for (j = 0; j < nn; j++)
+			if (recd[j] != nn)	/* recd[j] in index form */
+								tmp ^= alpha_to[(recd[j] + (1+i-1)*j)%nn];
+		
+			syn_error |= tmp;	/* set flag if non-zero syndrome =>
+					 * error */
+	/* store syndrome in index form  */
+		s[i] = index_of[tmp];
+	}
+
+	if (!syn_error) {
+		/*
+		 * if syndrome is zero, data[] is a codeword and there are no
+		 * errors to correct. So return data[] unmodified
+		 */
+		return 0;
+	}
+
+	BLANK(&lambda[1],nn-kk);
+	
+	lambda[0] = 1;
+	
+	for(i=0;i<nn-kk+1;i++)
+		b[i] = index_of[lambda[i]];
+
+	/*
+	 * Begin Berlekamp-Massey algorithm to determine error
+	 * locator polynomial
+	 */
+	r = 0; 
+	el = 0; 
+	while (++r <= nn-kk) {	/* r is the step number */
+		/* Compute discrepancy at the r-th step in poly-form */
+		discr_r = 0;
+		
+		for (i = 0; i < r; i++){
+			if ((lambda[i] != 0) && (s[r - i] != nn)) {				
+				discr_r ^= alpha_to[(index_of[lambda[i]] + s[r - i])%nn];
+			}
+		}
+		
+
+		discr_r = index_of[discr_r];	/* Index form */
+		if (discr_r == nn) {
+			/* 2 lines below: B(x) <-- x*B(x) */
+			COPYDOWN(&b[1],b,nn-kk);
+			b[0] = nn;
+		} else {
+			/* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
+			t[0] = lambda[0];
+			for (i = 0 ; i < nn-kk; i++) {
+				if(b[i] != nn)
+					//t[i+1] = lambda[i+1] ^ alpha_to[modnn(discr_r + b[i])];
+					t[i+1] = lambda[i+1] ^ alpha_to[(discr_r + b[i])%nn];
+				else
+					t[i+1] = lambda[i+1];
+			}
+			if (2 * el <= r - 1) {
+				el = r - el;
+				/*
+				 * 2 lines below: B(x) <-- inv(discr_r) *
+				 * lambda(x)
+				 */
+				for (i = 0; i <= nn-kk; i++)
+					//b[i] = (lambda[i] == 0) ? nn : modnn(index_of[lambda[i]] - discr_r + nn);
+					b[i] = (lambda[i] == 0) ? nn : ((index_of[lambda[i]] - discr_r + nn)%nn);
+			} else {
+				/* 2 lines below: B(x) <-- x*B(x) */
+				COPYDOWN(&b[1],b,nn-kk);
+				b[0] = nn;
+			}
+			COPY(lambda,t,nn-kk+1);
+		}
+	}
+
+	/* Convert lambda to index form and compute deg(lambda(x)) */
+	deg_lambda = 0;
+	for(i=0;i<nn-kk+1;i++){
+		lambda[i] = index_of[lambda[i]];
+		if(lambda[i] != nn)
+			deg_lambda = i;
+	}
+	/*
+	 * Find roots of the error locator polynomial. By Chien
+	 * Search
+	 */
+	COPY(&reg[1],&lambda[1],nn-kk);
+	count = 0;		/* Number of roots of lambda(x) */
+	for (i = 1; i <= nn; i++) {
+		q = 1;
+		for (j = deg_lambda; j > 0; j--)
+			if (reg[j] != nn) {
+				//reg[j] = modnn(reg[j] + j);
+				reg[j] = (reg[j] + j)%nn;
+				q ^= alpha_to[reg[j]];
+			}
+		if (!q) {
+			/* store root (index-form) and error location number */
+			root[count] = i;
+			loc[count] = nn - i;
+			count++;
+		}
+	}
+
+#ifdef DEBUG
+/*
+	printk("\n Final error positions:\t");
+	for (i = 0; i < count; i++)
+		printk("%d ", loc[i]);
+	printk("\n");
+*/
+#endif
+	
+	
+	
+	if (deg_lambda != count) {
+		/*
+		 * deg(lambda) unequal to number of roots => uncorrectable
+		 * error detected
+		 */
+		return -1;
+	}
+	/*
+	 * Compute err evaluator poly omega(x) = s(x)*lambda(x) (modulo
+	 * x**(nn-kk)). in index form. Also find deg(omega).
+	 */
+	
+	deg_omega = 0;
+	for (i = 0; i < nn-kk;i++){
+		tmp = 0;
+		j = (deg_lambda < i) ? deg_lambda : i;
+		for(;j >= 0; j--){
+			if ((s[i + 1 - j] != nn) && (lambda[j] != nn))
+				//tmp ^= alpha_to[modnn(s[i + 1 - j] + lambda[j])];
+				tmp ^= alpha_to[(s[i + 1 - j] + lambda[j])%nn];
+		}
+		if(tmp != 0)
+			deg_omega = i;
+		omega[i] = index_of[tmp];
+	}
+	omega[nn-kk] = nn;
+
+
+
+
+	/*
+	 * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
+	 * inv(X(l))**(1-1) and den = lambda_pr(inv(X(l))) all in poly-form
+	 */
+	for (j = count-1; j >=0; j--) {
+		num1 = 0;
+		for (i = deg_omega; i >= 0; i--) {
+			if (omega[i] != nn)
+				//num1  ^= alpha_to[modnn(omega[i] + i * root[j])];
+				num1  ^= alpha_to[(omega[i] + i * root[j])%nn];
+		}
+		//num2 = alpha_to[modnn(root[j] * (1 - 1) + nn)];
+		num2 = alpha_to[(root[j] * (1 - 1) + nn)%nn];
+		den = 0;
+
+		/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
+		for (i = minimum(deg_lambda,nn-kk-1) & ~1; i >= 0; i -=2) {
+			if(lambda[i+1] != nn)
+				//den ^= alpha_to[modnn(lambda[i+1] + i * root[j])];
+				den ^= alpha_to[(lambda[i+1] + i * root[j])%nn];
+		}
+		if (den == 0) {
+#ifdef DEBUG
+			printk("\n ERROR: denominator = 0\n");
+#endif
+			return -1;
+		}
+		/* Apply error to data */
+		if (num1 != 0) {
+			//data[loc[j]] ^= alpha_to[modnn(index_of[num1] + index_of[num2] + nn - index_of[den])];
+			data[loc[j]] ^= alpha_to[(index_of[num1] + index_of[num2] + nn - index_of[den])%nn];
+		}
+	}
+	return count;
+}
+
+/**
+ * mv_nand_calculate_ecc_rs - [NAND Interface] Calculate 4 symbol ECC code for 512 byte block
+ * @mtd:	MTD block structure
+ * @dat:	raw data
+ * @ecc_code:	buffer for ECC
+ */
+int mv_nand_calculate_ecc_rs(struct mtd_info *mtd, const u_char *data, u_char *ecc_code)
+{
+    	int i;	
+	u_short rsdata[nn];
+	
+	/* Generate Tables in first run */
+	if (!rs_initialized) {
+		generate_gf();
+		gen_poly();		
+		rs_initialized = 1;
+	}
+
+	for(i=512; i<nn; i++)
+		rsdata[i] = 0;
+
+		for(i=0; i<512; i++)
+			rsdata[i] = (u_short) data[i];	
+		if ((encode_rs(rsdata,&(rsdata[kk]))) != 0) 
+			return -1;
+		*(ecc_code) 	= (unsigned char) rsdata[kk];
+		*(ecc_code+1) 	= ((rsdata[0x3F7])   >> 8) | ((rsdata[0x3F7+1]) << 2);
+		*(ecc_code+2) 	= ((rsdata[0x3F7+1]) >> 6) | ((rsdata[0x3F7+2]) << 4);  
+		*(ecc_code+3) 	= ((rsdata[0x3F7+2]) >> 4) | ((rsdata[0x3F7+3]) << 6);
+		*(ecc_code+4) 	= ((rsdata[0x3F7+3]) >> 2);
+		*(ecc_code+5) 	= (unsigned char) rsdata[kk+4];
+		*(ecc_code+6)	= ((rsdata[0x3F7+4])   >> 8) | ((rsdata[0x3F7+1+4]) << 2);
+		*(ecc_code+7) 	= ((rsdata[0x3F7+1+4]) >> 6) | ((rsdata[0x3F7+2+4]) << 4);
+		*(ecc_code+8) 	= ((rsdata[0x3F7+2+4]) >> 4) | ((rsdata[0x3F7+3+4]) << 6);
+		*(ecc_code+9) 	= ((rsdata[0x3F7+3+4]) >> 2);
+
+	return 0;
+}
+
+/**
+ * mv_nand_correct_data - [NAND Interface] Detect and correct bit error(s)
+ * @mtd:	MTD block structure
+ * @dat:	raw data read from the chip
+ * @store_ecc:	ECC from the chip
+ * @calc_ecc:	the ECC calculated from raw data
+ *
+ * Detect and correct a 1 bit error for 256 byte block
+ */
+int mv_nand_correct_data_rs(struct mtd_info *mtd, u_char *data, u_char *store_ecc, u_char *calc_ecc)
+{
+	int ret,i=0;
+	u_short rsdata[nn];
+	
+	/* Generate Tables in first run */
+	if (!rs_initialized) {
+		generate_gf();
+		gen_poly();		
+		rs_initialized = 1;
+	}
+
+	/* is decode needed ? */
+	if((*(u32*)store_ecc == *(u32*)calc_ecc) &&
+	   (*(u32*)(store_ecc + 4) == *(u32*)(calc_ecc + 4)) &&
+	   (*(u16*)(store_ecc + 8) == *(u16*)(calc_ecc + 8)))
+		return 0;
+
+	/* did we read an erased page ? */
+	for(i = 0; i < 512 ;i += 4) {
+		if(*(u32*)(data+i) != 0xFFFFFFFF) {
+			DBG("%s: trying to correct data\n",__FUNCTION__);
+			goto correct;
+		}
+	}
+	/* page was erased, return gracefully */
+	return 0;
+	
+correct:
+
+	for(i=512; i<nn; i++) 
+	rsdata[i] = 0;
+
+    	/* errors*/
+	//data[20] = 0xDD;
+	//data[30] = 0xDD;
+	//data[40] = 0xDD;
+	//data[50] = 0xDD;
+	//data[60] = 0xDD;
+
+	/* Ecc is calculated on chunks of 512B */
+		for(i=0; i<512; i++)
+			rsdata[i] = (u_short) data[i];
+
+		rsdata[kk]   = ( (*(store_ecc+1) & 0x03) <<8) | (*(store_ecc));
+		rsdata[kk+1] = ( (*(store_ecc+2) & 0x0F) <<6) | (*(store_ecc+1)>>2);
+		rsdata[kk+2] = ( (*(store_ecc+3) & 0x3F) <<4) | (*(store_ecc+2)>>4);
+		rsdata[kk+3] = (*(store_ecc+4) <<2) | (*(store_ecc+3)>>6);
+
+		rsdata[kk+4] = ( (*(store_ecc+1+5) & 0x03) <<8) | (*(store_ecc+5));
+		rsdata[kk+5] = ( (*(store_ecc+2+5) & 0x0F) <<6) | (*(store_ecc+1+5)>>2);
+		rsdata[kk+6] = ( (*(store_ecc+3+5) & 0x3F) <<4) | (*(store_ecc+2+5)>>4);
+		rsdata[kk+7] = (*(store_ecc+4+5) <<2) | (*(store_ecc+3+5)>>6);
+
+		ret = decode_rs(rsdata);
+
+		/* Check for excessive errors */
+		if ((ret > tt) || (ret < 0)) {
+			printk("%s: uncorrectable error !!!\n",__FUNCTION__); 
+			return -1;
+		}
+	
+		/* Copy corrected data */
+		for (i=0; i<512; i++)
+			data[i] = (unsigned char) rsdata[i];
+
+	return 0;
+}
+
+static void mv_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	return;
+}
+
+#endif	/* CONFIG_MTD_NAND_LNC_RS_ECC */
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_lnc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_lnc.h
new file mode 100755
index 0000000..459719e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_lnc.h
@@ -0,0 +1,81 @@
+/*******************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#ifndef _NAND_LNC_H_
+#define _NAND_LNC_H_
+
+/* defines */
+#define	MV_NAND_ECC_4BIT	4
+#define MV_NAND_ECC_1BIT	1
+
+static struct nand_ecclayout mv_nand_rs_oobinfo = {
+	.eccbytes = 40,
+	.eccpos = {
+			24, 25, 26, 27, 28, 29, 30, 31,
+			32, 33, 34, 35, 36, 37, 38, 39,
+			40, 41, 42, 43, 44, 45, 46, 47,
+			48, 49, 50, 51, 52, 53, 54, 55,
+			56, 57, 58, 59, 60, 61, 62, 63
+		  },
+
+	.oobfree = {{6, 18}}
+};
+
+//typedef unsigned int dtype;
+typedef u_short dtype;
+
+void generate_gf(void); /* Generate Galois Field */
+void gen_poly(void);    /* Generate generator polynomial */
+
+/* Reed-Solomon encoding
+ * data[] is the input block, parity symbols are placed in bb[]
+ * bb[] may lie past the end of the data, e.g., for (255,223):
+ *      encode_rs(&data[0],&data[223]);
+ */
+static inline char encode_rs(dtype data[], dtype bb[]);
+
+
+/* Reed-Solomon errors decoding
+ * The received block goes into data[]
+ *
+ * The decoder corrects the symbols in place, if possible and returns
+ * the number of corrected symbols. If the codeword is illegal or
+ * uncorrectible, the data array is unchanged and -1 is returned
+ */
+static inline int decode_rs(dtype data[]);
+
+/**
+ * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block
+ * @mtd:        MTD block structure
+ * @dat:        raw data
+ * @ecc_code:   buffer for ECC
+ */
+int mv_nand_calculate_ecc_rs(struct mtd_info *mtd, const u_char *data, u_char *ecc_code);
+
+/**
+ * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
+ * @mtd:        MTD block structure
+ * @dat:        raw data read from the chip
+ * @store_ecc:  ECC from the chip
+ * @calc_ecc:   the ECC calculated from raw data
+ *
+ * Detect and correct a 1 bit error for 256 byte block
+ */
+int mv_nand_correct_data_rs(struct mtd_info *mtd, u_char *data, u_char *store_ecc, u_char *calc_ecc);
+
+static void mv_nand_enable_hwecc(struct mtd_info *mtd, int mode);
+#endif /* _NAND_LNC_H_ */
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_nfc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_nfc.c
new file mode 100755
index 0000000..de29787
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_nfc.c
@@ -0,0 +1,1760 @@
+/*
+ * nand_nfc.c
+ *
+ * Copyright c 2005 Intel Corporation
+ * Copyright c 2006 Marvell International Ltd.
+ *
+ * This driver is based on the PXA drivers/mtd/nand/pxa3xx_nand.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <asm/dma.h>
+
+#include "mvCommon.h"
+#include "mvOs.h"
+
+#ifdef MV_INCLUDE_PDMA
+#include <asm/hardware/pxa-dma.h>
+#include "pdma/mvPdma.h"
+#include "pdma/mvPdmaRegs.h"
+#endif
+#include "nand_nfc.h"
+
+#define NFC_DPRINT(x) 		//printk x
+#define PRINT_LVL		KERN_DEBUG
+
+#define	CHIP_DELAY_TIMEOUT		(20 * HZ/10)
+#define NFC_MAX_NUM_OF_DESCR	(33) /* worst case in 8K ganaged */
+#define NFC_8BIT1K_ECC_SPARE	(32)
+
+#define NFC_SR_MASK		(0xfff)
+#define NFC_SR_BBD_MASK		(NFC_SR_CS0_BBD_MASK | NFC_SR_CS1_BBD_MASK)
+
+
+char *cmd_text[]= {
+	"MV_NFC_CMD_READ_ID",
+	"MV_NFC_CMD_READ_STATUS",
+	"MV_NFC_CMD_ERASE",
+	"MV_NFC_CMD_MULTIPLANE_ERASE",
+	"MV_NFC_CMD_RESET",
+
+	"MV_NFC_CMD_CACHE_READ_SEQ",
+	"MV_NFC_CMD_CACHE_READ_RAND",
+	"MV_NFC_CMD_EXIT_CACHE_READ",
+	"MV_NFC_CMD_CACHE_READ_START",
+	"MV_NFC_CMD_READ_MONOLITHIC",
+	"MV_NFC_CMD_READ_MULTIPLE",
+	"MV_NFC_CMD_READ_NAKED",
+	"MV_NFC_CMD_READ_LAST_NAKED",
+	"MV_NFC_CMD_READ_DISPATCH",
+
+	"MV_NFC_CMD_WRITE_MONOLITHIC",
+	"MV_NFC_CMD_WRITE_MULTIPLE",
+	"MV_NFC_CMD_WRITE_NAKED",
+	"MV_NFC_CMD_WRITE_LAST_NAKED",
+	"MV_NFC_CMD_WRITE_DISPATCH",
+	"MV_NFC_CMD_WRITE_DISPATCH_START",
+	"MV_NFC_CMD_WRITE_DISPATCH_END",
+
+	"MV_NFC_CMD_COUNT"	/* This should be the last enum */
+
+};
+
+MV_U32 pg_sz[NFC_PAGE_SIZE_MAX_CNT] = {512, 2048, 4096, 8192, 16384};
+
+/* error code and state */
+enum {
+	ERR_NONE	= 0,
+	ERR_DMABUSERR	= -1,
+	ERR_CMD_TO	= -2,
+	ERR_DATA_TO	= -3,
+	ERR_DBERR	= -4,
+	ERR_BBD		= -5,
+};
+
+enum {
+	STATE_READY	= 0,
+	STATE_CMD_HANDLE,
+	STATE_DMA_READING,
+	STATE_DMA_WRITING,
+	STATE_DMA_DONE,
+	STATE_PIO_READING,
+	STATE_PIO_WRITING,
+};
+
+struct orion_nfc_info {
+	struct platform_device	 *pdev;
+
+	struct clk		*clk;
+	void __iomem		*mmio_base;
+	unsigned int		mmio_phys_base;
+
+	unsigned int 		buf_start;
+	unsigned int		buf_count;
+
+	unsigned char		*data_buff;
+	dma_addr_t 		data_buff_phys;
+	size_t			data_buff_size;
+
+	/* saved column/page_addr during CMD_SEQIN */
+	int			seqin_column;
+	int			seqin_page_addr;
+
+	/* relate to the command */
+	unsigned int		state;
+	unsigned int		use_dma;	/* use DMA ? */
+
+	/* flash information */
+	unsigned int		tclk;		/* Clock supplied to NFC */
+	unsigned int		nfc_width;	/* Width of NFC 16/8 bits */
+	unsigned int		num_devs;	/* Number of NAND devices 
+						   (2 for ganged mode).   */
+	unsigned int		num_cs;		/* Number of NAND devices 
+						   chip-selects.	  */
+	MV_NFC_ECC_MODE		ecc_type;
+	enum nfc_page_size	page_size;
+	uint32_t 		page_per_block;	/* Pages per block (PG_PER_BLK) */	
+	uint32_t 		flash_width;	/* Width of Flash memory (DWIDTH_M) */
+	size_t	 		read_id_bytes;
+
+	size_t			data_size;	/* data size in FIFO */
+	size_t			read_size;
+	int 			retcode;
+	uint32_t		dscr;		/* IRQ events - status */
+	struct completion 	cmd_complete;
+
+	int			chained_cmd;
+	uint32_t		column;
+	uint32_t		page_addr;
+	MV_NFC_CMD_TYPE		cmd;
+	MV_NFC_CTRL		nfcCtrl;
+
+	/* RW buffer chunks config */
+	MV_U32			sgBuffAddr[MV_NFC_RW_MAX_BUFF_NUM];
+	MV_U32			sgBuffSize[MV_NFC_RW_MAX_BUFF_NUM];
+	MV_U32			sgNumBuffs;
+
+	/* suspend / resume data */
+	MV_U32			nfcUnitData[128];
+	MV_U32			nfcDataLen;
+	MV_U32			pdmaUnitData[128];
+	MV_U32			pdmaDataLen;
+};
+
+/*
+ * ECC Layout
+ */
+
+static struct nand_ecclayout ecc_latout_512B_hamming = {
+	.eccbytes = 6,
+	.eccpos = {8, 9, 10, 11, 12, 13 },
+	.oobfree = { {2, 6} }
+};
+
+static struct nand_ecclayout ecc_layout_2KB_hamming = {
+	.eccbytes = 24,
+	.eccpos = {
+		40, 41, 42, 43, 44, 45, 46, 47,
+		48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63},
+	.oobfree = { {2, 38} }
+};
+
+static struct nand_ecclayout ecc_layout_2KB_bch4bit = {
+	.eccbytes = 32,
+	.eccpos = {
+		32, 33, 34, 35, 36, 37, 38, 39,
+		40, 41, 42, 43, 44, 45, 46, 47,
+		48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63},
+	.oobfree = { {2, 30} }
+};
+
+static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
+	.eccbytes = 64,
+	.eccpos = {
+		32,  33,  34,  35,  36,  37,  38,  39,
+		40,  41,  42,  43,  44,  45,  46,  47,
+		48,  49,  50,  51,  52,  53,  54,  55,
+		56,  57,  58,  59,  60,  61,  62,  63,
+		96,  97,  98,  99,  100, 101, 102, 103,
+		104, 105, 106, 107, 108, 109, 110, 111,
+		112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127},
+	/* Bootrom looks in bytes 0 & 5 for bad blocks */
+	.oobfree = { {1, 4}, {6, 26}, { 64, 32} }
+};
+
+static struct nand_ecclayout ecc_layout_8KB_bch4bit = {
+	.eccbytes = 128,
+	.eccpos = {
+		32,  33,  34,  35,  36,  37,  38,  39,
+		40,  41,  42,  43,  44,  45,  46,  47,
+		48,  49,  50,  51,  52,  53,  54,  55,
+		56,  57,  58,  59,  60,  61,  62,  63,
+
+		96,  97,  98,  99,  100, 101, 102, 103,
+		104, 105, 106, 107, 108, 109, 110, 111,
+		112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127,
+
+		160, 161, 162, 163, 164, 165, 166, 167,
+		168, 169, 170, 171, 172, 173, 174, 175,
+		176, 177, 178, 179, 180, 181, 182, 183,
+		184, 185, 186, 187, 188, 189, 190, 191,
+
+		224, 225, 226, 227, 228, 229, 230, 231,
+		232, 233, 234, 235, 236, 237, 238, 239,
+		240, 241, 242, 243, 244, 245, 246, 247,
+		248, 249, 250, 251, 252, 253, 254, 255},
+
+	/* Bootrom looks in bytes 0 & 5 for bad blocks */
+	.oobfree = { {1, 4}, {6, 26}, { 64, 32}, {128, 32}, {192, 32} }
+};
+
+static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
+	.eccbytes = 64,
+	.eccpos = {
+		32,  33,  34,  35,  36,  37,  38,  39,
+		40,  41,  42,  43,  44,  45,  46,  47,
+		48,  49,  50,  51,  52,  53,  54,  55,
+		56,  57,  58,  59,  60,  61,  62,  63},
+	/* Bootrom looks in bytes 0 & 5 for bad blocks */
+	.oobfree = { {1, 4}, {6, 26},  }
+};
+
+static struct nand_ecclayout ecc_layout_8KB_bch8bit = {
+	.eccbytes = 160,
+	.eccpos = {
+		128, 129, 130, 131, 132, 133, 134, 135,
+		136, 137, 138, 139, 140, 141, 142, 143,
+		144, 145, 146, 147, 148, 149, 150, 151,
+		152, 153, 154, 155, 156, 157, 158, 159},
+	/* Bootrom looks in bytes 0 & 5 for bad blocks */
+	.oobfree = { {1, 4}, {6, 122},  }
+};
+
+static struct nand_ecclayout ecc_layout_8KB_bch12bit = {
+	.eccbytes = 0,
+	.eccpos = { },
+	/* Bootrom looks in bytes 0 & 5 for bad blocks */
+	.oobfree = { {1, 4}, {6, 58}, }
+};
+
+static struct nand_ecclayout ecc_layout_16KB_bch12bit = {
+	.eccbytes = 0,
+	.eccpos = { },
+	/* Bootrom looks in bytes 0 & 5 for bad blocks */
+	.oobfree = { {1, 4}, {6, 122},  }
+};
+
+/*
+ * Define bad block scan pattern when scanning a device for factory 
+ * marked blocks.
+ */
+static uint8_t mv_scan_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr mv_sp_bb = {
+	.options = NAND_BBT_SCANMVCUSTOM,
+	.offs = 5,
+	.len = 1,
+	.pattern = mv_scan_pattern
+};
+
+static struct nand_bbt_descr mv_lp_bb = {
+	.options = NAND_BBT_SCANMVCUSTOM,
+	.offs = 0,
+	.len = 2,
+	.pattern = mv_scan_pattern
+};
+
+/*
+ * Lookup Tables
+ */
+
+struct orion_nfc_naked_info {
+	
+	struct nand_ecclayout* 	ecc_layout;
+	struct nand_bbt_descr*	bb_info;
+	uint32_t		bb_bytepos;
+	uint32_t		chunk_size;
+	uint32_t		chunk_spare;
+	uint32_t		chunk_cnt;
+	uint32_t		last_chunk_size;
+	uint32_t		last_chunk_spare;
+};
+
+			                     /* PageSize*/          /* ECc Type */
+static struct orion_nfc_naked_info orion_nfc_naked_info_lkup[NFC_PAGE_SIZE_MAX_CNT][MV_NFC_ECC_MAX_CNT] = {
+	/* 512B Pages */
+	{{    	/* Hamming */
+		&ecc_latout_512B_hamming, &mv_sp_bb, 512, 512, 16, 1, 0, 0
+	}, { 	/* BCH 4bit */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}, { 	/* BCH 8bit */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}, { 	/* BCH 12bit */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}, { 	/* BCH 16bit */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}, { 	/* No ECC */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}},
+	/* 2KB Pages */
+	{{	/* Hamming */
+		&ecc_layout_2KB_hamming, &mv_lp_bb, 2048, 2048, 40, 1, 0, 0
+	}, { 	/* BCH 4bit */
+		&ecc_layout_2KB_bch4bit, &mv_lp_bb, 2048, 2048, 32, 1, 0, 0
+	}, { 	/* BCH 8bit */
+		NULL, NULL, 2018, 1024, 0, 1, 1024, 32
+	}, { 	/* BCH 12bit */
+		NULL, NULL, 1988, 704, 0, 2, 640, 0
+	}, { 	/* BCH 16bit */
+		NULL, NULL, 1958, 512, 0, 4, 0, 32
+	}, { 	/* No ECC */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}},
+	/* 4KB Pages */
+	{{	/* Hamming */
+		NULL, 0, 0, 0, 0, 0, 0, 0
+	}, { 	/* BCH 4bit */
+		&ecc_layout_4KB_bch4bit, &mv_lp_bb, 4034, 2048, 32, 2, 0, 0
+	}, { 	/* BCH 8bit */
+		&ecc_layout_4KB_bch8bit, &mv_lp_bb, 4006, 1024, 0, 4, 0, 64
+	}, { 	/* BCH 12bit */
+		NULL, NULL, 3946, 704,  0, 5, 576, 32
+	}, { 	/* BCH 16bit */
+		NULL, NULL, 3886, 512, 0, 8, 0, 32
+	}, { 	/* No ECC */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}},
+	/* 8KB Pages */
+	{{	/* Hamming */
+		NULL, 0, 0, 0, 0, 0, 0, 0
+	}, { 	/* BCH 4bit */
+		&ecc_layout_8KB_bch4bit, &mv_lp_bb, 8102, 2048, 32, 4, 0, 0
+	}, { 	/* BCH 8bit */
+		&ecc_layout_8KB_bch8bit, &mv_lp_bb, 7982, 1024, 0, 8, 0, 160
+	}, { 	/* BCH 12bit */
+		&ecc_layout_8KB_bch12bit, &mv_lp_bb,7862, 704, 0, 11, 448, 64
+	}, { 	/* BCH 16bit */
+		NULL, NULL, 7742, 512, 0, 16, 0, 32
+	}, { 	/* No ECC */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}},
+	/* 16KB Pages */
+	{{	/* Hamming */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}, { 	/* BCH 4bit */
+		NULL, NULL, 15914, 2048, 32, 8, 0, 0
+	}, { 	/* BCH 8bit */
+		NULL, NULL, 15930, 1024, 0, 16, 0, 352
+	}, { 	/* BCH 12bit */
+		&ecc_layout_16KB_bch12bit, &mv_lp_bb, 15724, 704, 0, 23, 192, 128
+	}, { 	/* BCH 16bit */
+		NULL, NULL, 15484, 512, 0, 32, 0, 32
+	}, { 	/* No ECC */
+		NULL, NULL, 0, 0, 0, 0, 0, 0
+	}}};
+		
+
+#define ECC_LAYOUT	(orion_nfc_naked_info_lkup[info->page_size][info->ecc_type].ecc_layout)
+#define BB_INFO		(orion_nfc_naked_info_lkup[info->page_size][info->ecc_type].bb_info)
+#define	BB_BYTE_POS	(orion_nfc_naked_info_lkup[info->page_size][info->ecc_type].bb_bytepos)
+#define CHUNK_CNT	(orion_nfc_naked_info_lkup[info->page_size][info->ecc_type].chunk_cnt)
+#define CHUNK_SZ	(orion_nfc_naked_info_lkup[info->page_size][info->ecc_type].chunk_size)
+#define CHUNK_SPR	(orion_nfc_naked_info_lkup[info->page_size][info->ecc_type].chunk_spare)
+#define LST_CHUNK_SZ	(orion_nfc_naked_info_lkup[info->page_size][info->ecc_type].last_chunk_size)
+#define LST_CHUNK_SPR	(orion_nfc_naked_info_lkup[info->page_size][info->ecc_type].last_chunk_spare)
+
+struct orion_nfc_cmd_info {
+	
+	uint32_t		events_p1;	/* post command events */
+	uint32_t		events_p2;	/* post data events */
+	MV_NFC_PIO_RW_MODE	rw;
+};
+
+static struct orion_nfc_cmd_info orion_nfc_cmd_info_lkup[MV_NFC_CMD_COUNT] = {
+	/* Phase 1 interrupts */			/* Phase 2 interrupts */			/* Read/Write */  /* MV_NFC_CMD_xxxxxx */
+	{(NFC_SR_RDDREQ_MASK), 				(0),						MV_NFC_PIO_READ}, /* READ_ID */
+	{(NFC_SR_RDDREQ_MASK), 				(0),						MV_NFC_PIO_READ}, /* READ_STATUS */
+	{(0), 						(MV_NFC_STATUS_RDY | MV_NFC_STATUS_BBD),	MV_NFC_PIO_NONE}, /* ERASE */
+	{(0), 						(0), 						MV_NFC_PIO_NONE}, /* MULTIPLANE_ERASE */
+	{(0), 						(MV_NFC_STATUS_RDY), 				MV_NFC_PIO_NONE}, /* RESET */
+	{(0), 						(0), 						MV_NFC_PIO_READ}, /* CACHE_READ_SEQ */
+	{(0), 						(0), 						MV_NFC_PIO_READ}, /* CACHE_READ_RAND */
+	{(0), 						(0), 						MV_NFC_PIO_NONE}, /* EXIT_CACHE_READ */
+	{(0), 						(0), 						MV_NFC_PIO_READ}, /* CACHE_READ_START */
+	{(NFC_SR_RDDREQ_MASK | NFC_SR_UNCERR_MASK), 	(0), 						MV_NFC_PIO_READ}, /* READ_MONOLITHIC */
+	{(0), 						(0),						MV_NFC_PIO_READ}, /* READ_MULTIPLE */
+	{(NFC_SR_RDDREQ_MASK | NFC_SR_UNCERR_MASK), 	(0), 						MV_NFC_PIO_READ}, /* READ_NAKED */
+	{(NFC_SR_RDDREQ_MASK | NFC_SR_UNCERR_MASK), 	(0), 						MV_NFC_PIO_READ}, /* READ_LAST_NAKED */
+	{(0), 						(0), 						MV_NFC_PIO_NONE}, /* READ_DISPATCH */
+	{(MV_NFC_STATUS_WRD_REQ), 			(MV_NFC_STATUS_RDY | MV_NFC_STATUS_BBD),	MV_NFC_PIO_WRITE},/* WRITE_MONOLITHIC */
+	{(0), 						(0), 						MV_NFC_PIO_WRITE},/* WRITE_MULTIPLE */
+	{(MV_NFC_STATUS_WRD_REQ),			(MV_NFC_STATUS_PAGED),				MV_NFC_PIO_WRITE},/* WRITE_NAKED */
+	{(0), 						(0), 						MV_NFC_PIO_WRITE},/* WRITE_LAST_NAKED */
+	{(0), 						(0), 						MV_NFC_PIO_NONE}, /* WRITE_DISPATCH */
+	{(MV_NFC_STATUS_CMDD),				(0),						MV_NFC_PIO_NONE}, /* WRITE_DISPATCH_START */
+	{(0),						(MV_NFC_STATUS_RDY | MV_NFC_STATUS_BBD), 	MV_NFC_PIO_NONE}, /* WRITE_DISPATCH_END */
+};
+
+static int prepare_read_prog_cmd(struct orion_nfc_info *info,
+			int column, int page_addr)
+{
+	MV_U32 size;
+
+	if (mvNfcFlashPageSizeGet(&info->nfcCtrl, &size, &info->data_size) 
+	    != MV_OK)
+		return -EINVAL;
+
+	return 0;
+}
+int orion_nfc_wait_for_completion_timeout(struct orion_nfc_info *info, int timeout)
+{
+	return wait_for_completion_timeout(&info->cmd_complete, timeout);
+
+}
+
+#ifdef CONFIG_MV_INCLUDE_PDMA
+static void orion_nfc_data_dma_irq(int irq, void *data)
+{
+	struct orion_nfc_info *info = data;
+	uint32_t dcsr, intr;
+	int channel = info->nfcCtrl.dataChanHndl.chanNumber;
+
+	intr = MV_REG_READ(PDMA_INTR_CAUSE_REG);
+	dcsr = MV_REG_READ(PDMA_CTRL_STATUS_REG(channel));
+	MV_REG_WRITE(PDMA_CTRL_STATUS_REG(channel), dcsr);
+
+	NFC_DPRINT((PRINT_LVL "orion_nfc_data_dma_irq(0x%x, 0x%x) - 1.\n", dcsr, intr));
+
+	if(info->chained_cmd) {
+		if (dcsr & DCSR_BUSERRINTR) {
+			info->retcode = ERR_DMABUSERR;
+			complete(&info->cmd_complete);
+		}
+		if ((info->state == STATE_DMA_READING) && (dcsr & DCSR_ENDINTR)) {
+			info->state = STATE_READY;
+			complete(&info->cmd_complete);
+		}
+		return;
+	}
+
+	if (dcsr & DCSR_BUSERRINTR) {
+		info->retcode = ERR_DMABUSERR;
+		complete(&info->cmd_complete);
+	}
+
+	if (info->state == STATE_DMA_WRITING) {
+		info->state = STATE_DMA_DONE;
+		mvNfcIntrSet(&info->nfcCtrl,  MV_NFC_STATUS_BBD | MV_NFC_STATUS_RDY , MV_TRUE);
+	} else {
+		info->state = STATE_READY;
+		complete(&info->cmd_complete);
+	}
+
+	return;
+}
+#endif
+
+static irqreturn_t orion_nfc_irq_pio(int irq, void *devid)
+{
+	struct orion_nfc_info *info = devid;
+
+	/* Disable all interrupts */
+	mvNfcIntrSet(&info->nfcCtrl, 0xFFF, MV_FALSE);
+
+	/* Clear the interrupt and pass the status UP */
+	info->dscr = MV_REG_READ(NFC_STATUS_REG);
+	NFC_DPRINT((PRINT_LVL ">>> orion_nfc_irq_pio(0x%x)\n", info->dscr));
+	MV_REG_WRITE(NFC_STATUS_REG, info->dscr);
+	complete(&info->cmd_complete);
+
+	return IRQ_HANDLED;
+}
+	
+#ifdef CONFIG_MV_INCLUDE_PDMA
+static irqreturn_t orion_nfc_irq_dma(int irq, void *devid)
+{
+	struct orion_nfc_info *info = devid;
+	unsigned int status;
+
+	status = MV_REG_READ(NFC_STATUS_REG);
+
+	NFC_DPRINT((PRINT_LVL "orion_nfc_irq_dma(0x%x) - 1.\n", status));
+
+	if(!info->chained_cmd) {
+		if (status & (NFC_SR_RDDREQ_MASK | NFC_SR_UNCERR_MASK)) {
+			if (status & NFC_SR_UNCERR_MASK)
+				info->retcode = ERR_DBERR;
+			mvNfcIntrSet(&info->nfcCtrl, NFC_SR_RDDREQ_MASK | NFC_SR_UNCERR_MASK, MV_FALSE);
+			if (info->use_dma) {
+				info->state = STATE_DMA_READING;
+				mvNfcReadWrite(&info->nfcCtrl, info->cmd, (MV_U32*)info->data_buff, info->data_buff_phys);
+			} else {
+				info->state = STATE_PIO_READING;
+				complete(&info->cmd_complete);
+			}
+		} else if (status & NFC_SR_WRDREQ_MASK) {
+			mvNfcIntrSet(&info->nfcCtrl, NFC_SR_WRDREQ_MASK, MV_FALSE);
+			if (info->use_dma) {
+				info->state = STATE_DMA_WRITING;
+				NFC_DPRINT((PRINT_LVL "Calling mvNfcReadWrite().\n"));
+				if (mvNfcReadWrite(&info->nfcCtrl, info->cmd,
+						   (MV_U32 *)info->data_buff,
+						   info->data_buff_phys) 
+				    != MV_OK)
+					printk(KERN_ERR "mvNfcReadWrite() failed.\n");
+			} else {
+				info->state = STATE_PIO_WRITING;
+				complete(&info->cmd_complete);
+			}
+		} else if (status & (NFC_SR_BBD_MASK | MV_NFC_CS0_CMD_DONE_INT |
+				     NFC_SR_RDY0_MASK | MV_NFC_CS1_CMD_DONE_INT |
+				     NFC_SR_RDY1_MASK)) {
+			if (status & NFC_SR_BBD_MASK)
+				info->retcode = ERR_BBD;
+			mvNfcIntrSet(&info->nfcCtrl,  MV_NFC_STATUS_BBD |
+					MV_NFC_STATUS_CMDD | MV_NFC_STATUS_RDY,
+					MV_FALSE);
+			info->state = STATE_READY;
+			complete(&info->cmd_complete);
+		}
+	} else if (status & (NFC_SR_BBD_MASK | NFC_SR_RDY0_MASK |
+				NFC_SR_RDY1_MASK | NFC_SR_UNCERR_MASK)) {
+		if (status & (NFC_SR_BBD_MASK | NFC_SR_UNCERR_MASK))
+			info->retcode = ERR_DBERR;
+		mvNfcIntrSet(&info->nfcCtrl, MV_NFC_STATUS_BBD |
+				MV_NFC_STATUS_RDY | MV_NFC_STATUS_CMDD,
+				MV_FALSE);
+		if ((info->state != STATE_DMA_READING) ||
+		    (info->retcode == ERR_DBERR)) {
+			info->state = STATE_READY;
+			complete(&info->cmd_complete);
+		}
+	}
+	MV_REG_WRITE(NFC_STATUS_REG, status);
+	return IRQ_HANDLED;
+}
+#endif
+
+static int orion_nfc_cmd_prepare(struct orion_nfc_info *info,
+		MV_NFC_MULTI_CMD *descInfo, u32 *numCmds)
+{
+	MV_U32	i;
+	MV_NFC_MULTI_CMD *currDesc;	
+
+	currDesc = descInfo;
+	if (info->cmd == MV_NFC_CMD_READ_MONOLITHIC) {
+		/* Main Chunks */
+		for (i=0; i<CHUNK_CNT; i++)
+		{
+			if (i == 0)
+				currDesc->cmd = MV_NFC_CMD_READ_MONOLITHIC;
+			else if ((i == (CHUNK_CNT-1)) && (LST_CHUNK_SZ == 0) && (LST_CHUNK_SPR == 0))
+				currDesc->cmd = MV_NFC_CMD_READ_LAST_NAKED;
+			else
+				currDesc->cmd = MV_NFC_CMD_READ_NAKED;
+
+			currDesc->pageAddr = info->page_addr;
+			currDesc->pageCount = 1;
+			currDesc->virtAddr = (MV_U32 *)(info->data_buff + (i * CHUNK_SZ));
+			currDesc->physAddr = info->data_buff_phys + (i * CHUNK_SZ);
+			currDesc->length = (CHUNK_SZ + CHUNK_SPR);
+
+			if (CHUNK_SPR == 0)
+				currDesc->numSgBuffs = 1;
+			else
+			{
+				currDesc->numSgBuffs = 2;
+				currDesc->sgBuffAddr[0] = (info->data_buff_phys + (i * CHUNK_SZ));
+				currDesc->sgBuffAddrVirt[0] = (MV_U32 *)(info->data_buff + (i * CHUNK_SZ));
+				currDesc->sgBuffSize[0] = CHUNK_SZ;
+				currDesc->sgBuffAddr[1] = (info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (i * CHUNK_SPR));
+				currDesc->sgBuffAddrVirt[1] = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (i * CHUNK_SPR));
+				currDesc->sgBuffSize[1] = CHUNK_SPR;
+			}
+
+			currDesc++;
+		}
+		
+		/* Last chunk if existing */
+		if ((LST_CHUNK_SZ != 0) || (LST_CHUNK_SPR != 0))
+		{
+			currDesc->cmd = MV_NFC_CMD_READ_LAST_NAKED;
+			currDesc->pageAddr = info->page_addr;
+			currDesc->pageCount = 1;				
+			currDesc->length = (LST_CHUNK_SPR + LST_CHUNK_SZ);
+
+			if ((LST_CHUNK_SZ == 0) && (LST_CHUNK_SPR != 0))	/* Spare only */
+			{
+				currDesc->virtAddr = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (CHUNK_SPR * CHUNK_CNT));
+				currDesc->physAddr = info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (CHUNK_SPR * CHUNK_CNT);
+				currDesc->numSgBuffs = 1;
+				currDesc->length = LST_CHUNK_SPR;
+			}
+			else if ((LST_CHUNK_SZ != 0) && (LST_CHUNK_SPR == 0))	/* Data only */
+			{
+				currDesc->virtAddr = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT));
+				currDesc->physAddr = info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT);
+				currDesc->numSgBuffs = 1;
+				currDesc->length = LST_CHUNK_SZ;
+			}
+			else /* Both spare and data */
+			{
+				currDesc->numSgBuffs = 2;
+				currDesc->sgBuffAddr[0] = (info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT));
+				currDesc->sgBuffAddrVirt[0] = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT));
+				currDesc->sgBuffSize[0] = LST_CHUNK_SZ;
+				currDesc->sgBuffAddr[1] = (info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (CHUNK_SPR * CHUNK_CNT));
+				currDesc->sgBuffAddrVirt[1] =  (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (CHUNK_SPR * CHUNK_CNT));
+				currDesc->sgBuffSize[1] = LST_CHUNK_SPR;
+			}
+			currDesc++;
+		}
+
+		*numCmds = CHUNK_CNT + (((LST_CHUNK_SZ) || (LST_CHUNK_SPR)) ? 1 : 0);
+	} else if (info->cmd == MV_NFC_CMD_WRITE_MONOLITHIC) {
+		/* Write Dispatch */
+		currDesc->cmd = MV_NFC_CMD_WRITE_DISPATCH_START;
+		currDesc->pageAddr = info->page_addr;
+		currDesc->pageCount = 1;
+		currDesc->numSgBuffs = 1;
+		currDesc->length = 0;
+		currDesc++;
+
+		/* Main Chunks */
+		for (i=0; i<CHUNK_CNT; i++)
+		{
+			currDesc->cmd = MV_NFC_CMD_WRITE_NAKED;
+			currDesc->pageAddr = info->page_addr;
+			currDesc->pageCount = 1;
+			currDesc->virtAddr = (MV_U32 *)(info->data_buff + (i * CHUNK_SZ));
+			currDesc->physAddr = info->data_buff_phys + (i * CHUNK_SZ);
+			currDesc->length = (CHUNK_SZ + CHUNK_SPR);
+
+			if (CHUNK_SPR == 0)
+				currDesc->numSgBuffs = 1;
+			else
+			{
+				currDesc->numSgBuffs = 2;
+				currDesc->sgBuffAddr[0] = (info->data_buff_phys + (i * CHUNK_SZ));
+				currDesc->sgBuffAddrVirt[0] = (MV_U32 *)(info->data_buff + (i * CHUNK_SZ));
+				currDesc->sgBuffSize[0] = CHUNK_SZ;
+				currDesc->sgBuffAddr[1] = (info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (i * CHUNK_SPR));
+				currDesc->sgBuffAddrVirt[1] = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (i * CHUNK_SPR));
+				currDesc->sgBuffSize[1] = CHUNK_SPR;
+			}
+
+			currDesc++;
+		}
+		
+		/* Last chunk if existing */
+		if ((LST_CHUNK_SZ != 0) || (LST_CHUNK_SPR != 0))
+		{
+			currDesc->cmd = MV_NFC_CMD_WRITE_NAKED;
+			currDesc->pageAddr = info->page_addr;
+			currDesc->pageCount = 1;
+			currDesc->length = (LST_CHUNK_SZ + LST_CHUNK_SPR);
+
+			if ((LST_CHUNK_SZ == 0) && (LST_CHUNK_SPR != 0))	/* Spare only */
+			{
+				currDesc->virtAddr = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (CHUNK_SPR * CHUNK_CNT));
+				currDesc->physAddr = info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (CHUNK_SPR * CHUNK_CNT);
+				currDesc->numSgBuffs = 1;
+			}
+			else if ((LST_CHUNK_SZ != 0) && (LST_CHUNK_SPR == 0))	/* Data only */
+			{
+				currDesc->virtAddr = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT));
+				currDesc->physAddr = info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT);
+				currDesc->numSgBuffs = 1;
+			}
+			else /* Both spare and data */
+			{
+				currDesc->numSgBuffs = 2;
+				currDesc->sgBuffAddr[0] = (info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT));
+				currDesc->sgBuffAddrVirt[0] = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT));
+				currDesc->sgBuffSize[0] = LST_CHUNK_SZ;
+				currDesc->sgBuffAddr[1] = (info->data_buff_phys + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (CHUNK_SPR * CHUNK_CNT));
+				currDesc->sgBuffAddrVirt[1] = (MV_U32 *)(info->data_buff + (CHUNK_SZ * CHUNK_CNT) + LST_CHUNK_SZ + (CHUNK_SPR * CHUNK_CNT));
+				currDesc->sgBuffSize[1] = LST_CHUNK_SPR;
+			}
+			currDesc++;
+		}
+
+		/* Write Dispatch END */
+		currDesc->cmd = MV_NFC_CMD_WRITE_DISPATCH_END;
+		currDesc->pageAddr = info->page_addr;
+		currDesc->pageCount = 1;
+		currDesc->numSgBuffs = 1;
+		currDesc->length = 0;
+
+		*numCmds = CHUNK_CNT + (((LST_CHUNK_SZ) || (LST_CHUNK_SPR)) ? 1 : 0) + 2;
+	} else {
+		descInfo[0].cmd = info->cmd;
+		descInfo[0].pageAddr = info->page_addr;
+		descInfo[0].pageCount = 1;
+		descInfo[0].virtAddr = (MV_U32 *)info->data_buff;
+		descInfo[0].physAddr = info->data_buff_phys;
+		descInfo[0].numSgBuffs = 1;
+		descInfo[0].length = info->data_size;
+		*numCmds = 1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_MV_INCLUDE_PDM
+static int orion_nfc_do_cmd_dma(struct orion_nfc_info *info,
+		uint32_t event)
+{
+	uint32_t ndcr;
+	int ret, timeout = CHIP_DELAY_TIMEOUT;
+	MV_STATUS status;
+	MV_U32	numCmds;
+
+	/* static allocation to avoid stack overflow*/
+	static MV_NFC_MULTI_CMD descInfo[NFC_MAX_NUM_OF_DESCR];
+
+	/* Clear all status bits. */
+	MV_REG_WRITE(NFC_STATUS_REG, NFC_SR_MASK);
+
+	mvNfcIntrSet(&info->nfcCtrl, event, MV_TRUE);
+
+	NFC_DPRINT((PRINT_LVL "\nAbout to issue dma cmd %d (cs %d) - 0x%x.\n",
+				info->cmd, info->nfcCtrl.currCs,
+				MV_REG_READ(NFC_CONTROL_REG)));
+	if ((info->cmd == MV_NFC_CMD_READ_MONOLITHIC) ||
+	    (info->cmd == MV_NFC_CMD_READ_ID) ||
+	    (info->cmd == MV_NFC_CMD_READ_STATUS))
+		info->state = STATE_DMA_READING;
+	else
+		info->state = STATE_CMD_HANDLE;
+	info->chained_cmd = 1;
+
+	orion_nfc_cmd_prepare(info, descInfo, &numCmds);
+
+	status = mvNfcCommandMultiple(&info->nfcCtrl,descInfo, numCmds);
+	if (status != MV_OK) {
+		printk(KERN_ERR "nfcCmdMultiple() failed for cmd %d (%d).\n",
+				info->cmd, status);
+		goto fail;
+	}
+
+	NFC_DPRINT((PRINT_LVL "After issue command %d - 0x%x.\n",
+				info->cmd, MV_REG_READ(NFC_STATUS_REG)));
+
+	ret = orion_nfc_wait_for_completion_timeout(info, timeout);
+	if (!ret) {
+		printk(KERN_ERR "Cmd %d execution timed out (0x%x) - cs %d.\n",
+				info->cmd, MV_REG_READ(NFC_STATUS_REG),
+				info->nfcCtrl.currCs);
+		info->retcode = ERR_CMD_TO;
+		goto fail_stop;
+	}
+
+	mvNfcIntrSet(&info->nfcCtrl, event | MV_NFC_STATUS_CMDD, MV_FALSE);
+
+	while (MV_PDMA_CHANNEL_STOPPED !=
+			mvPdmaChannelStateGet(&info->nfcCtrl.dataChanHndl)) {
+		if (info->retcode == ERR_NONE)
+			BUG();
+
+	}
+
+	return 0;
+
+fail_stop:
+	ndcr = MV_REG_READ(NFC_CONTROL_REG);
+	MV_REG_WRITE(NFC_CONTROL_REG, ndcr & ~NFC_CTRL_ND_RUN_MASK);
+	udelay(10);
+fail:
+	return -ETIMEDOUT;
+}
+#endif
+
+static int orion_nfc_error_check(struct orion_nfc_info *info)
+{
+	switch (info->cmd) {
+		case MV_NFC_CMD_ERASE:
+		case MV_NFC_CMD_MULTIPLANE_ERASE:
+		case MV_NFC_CMD_WRITE_MONOLITHIC:
+		case MV_NFC_CMD_WRITE_MULTIPLE:
+		case MV_NFC_CMD_WRITE_NAKED:
+		case MV_NFC_CMD_WRITE_LAST_NAKED:
+		case MV_NFC_CMD_WRITE_DISPATCH:
+		case MV_NFC_CMD_WRITE_DISPATCH_START:
+		case MV_NFC_CMD_WRITE_DISPATCH_END:
+			if (info->dscr & (MV_NFC_CS0_BAD_BLK_DETECT_INT | MV_NFC_CS1_BAD_BLK_DETECT_INT)) {
+				info->retcode = ERR_BBD;
+				return 1;
+			}
+			break;
+		
+		case MV_NFC_CMD_CACHE_READ_SEQ:
+		case MV_NFC_CMD_CACHE_READ_RAND:
+		case MV_NFC_CMD_EXIT_CACHE_READ:
+		case MV_NFC_CMD_CACHE_READ_START:
+		case MV_NFC_CMD_READ_MONOLITHIC:
+		case MV_NFC_CMD_READ_MULTIPLE:
+		case MV_NFC_CMD_READ_NAKED:
+		case MV_NFC_CMD_READ_LAST_NAKED:
+		case MV_NFC_CMD_READ_DISPATCH:
+			if (info->dscr & MV_NFC_UNCORR_ERR_INT) {
+				info->dscr = ERR_DBERR;
+				return 1;
+			}
+			break;
+
+		default:
+			break;
+	}
+
+	info->retcode = ERR_NONE;
+	return 0;
+}
+
+/* ==================================================================================================
+ *           STEP  1		|   STEP  2   |   STEP  3   |   STEP  4   |   STEP  5   |   STEP 6
+ *           COMMAND		|   WAIT FOR  |   CHK ERRS  |     PIO     |   WAIT FOR  |   CHK ERRS
+ * =========================|=============|=============|=============|=============|============
+ *   READ MONOLITHIC		|   RDDREQ    |   UNCERR    |    READ     |     NONE    |    NONE
+ *   READ NAKED				|   RDDREQ    |   UNCERR    |    READ     |     NONE    |    NONE
+ *   READ LAST NAKED		|   RDDREQ    |   UNCERR    |    READ     |     NONE    |    NONE
+ *   WRITE MONOLITHIC		|   WRDREQ    |    NONE     |    WRITE    |     RDY     |    BBD
+ *   WRITE DISPATCH START	|   CMDD      |    NONE     |    NONE     |     NONE    |    NONE
+ *   WRITE NAKED			|   WRDREQ    |    NONE     |    WRITE    |     PAGED   |    NONE
+ *   WRITE DISPATCH END		|   NONE      |    NONE     |    NONE     |     RDY     |    BBD
+ *   ERASE					|   NONE      |    NONE     |    NONE     |     RDY     |    BBD
+ *   READ ID				|   RDDREQ    |    NONE     |    READ     |     NONE    |    NONE
+ *   READ STAT				|   RDDREQ    |    NONE     |    READ     |     NONE    |    NONE
+ *   RESET					|   NONE      |    NONE     |    NONE     |     RDY     |    NONE
+ */
+static int orion_nfc_do_cmd_pio(struct orion_nfc_info *info)
+{
+	int timeout = CHIP_DELAY_TIMEOUT;
+	MV_STATUS status;
+	MV_U32	i, j, numCmds;
+	MV_U32 ndcr;
+
+	/* static allocation to avoid stack overflow */
+	static MV_NFC_MULTI_CMD descInfo[NFC_MAX_NUM_OF_DESCR];
+
+	/* Clear all status bits */
+	MV_REG_WRITE(NFC_STATUS_REG, NFC_SR_MASK);	
+	
+	NFC_DPRINT((PRINT_LVL "\nStarting PIO command %d (cs %d) - NDCR=0x%08x\n",
+				info->cmd, info->nfcCtrl.currCs, MV_REG_READ(NFC_CONTROL_REG)));
+
+	/* Build the chain of commands */
+	orion_nfc_cmd_prepare(info, descInfo, &numCmds);
+	NFC_DPRINT((PRINT_LVL "Prepared %d commands in sequence\n", numCmds));
+
+	/* Execute the commands */
+	for (i=0; i < numCmds; i++) {
+		/* Verify that command is supported in PIO mode */
+		if ((orion_nfc_cmd_info_lkup[descInfo[i].cmd].events_p1 == 0) &&
+		    (orion_nfc_cmd_info_lkup[descInfo[i].cmd].events_p2 == 0)) {
+			goto fail_stop;
+		}
+		
+		/* clear the return code */
+		info->dscr = 0;
+
+		/* STEP1: Initiate the command */
+		NFC_DPRINT((PRINT_LVL "About to issue Descriptor #%d (command %d, pageaddr 0x%x, length %d).\n", 
+			    i, descInfo[i].cmd, descInfo[i].pageAddr, descInfo[i].length));
+		if ((status = mvNfcCommandPio(&info->nfcCtrl, &descInfo[i], MV_FALSE)) != MV_OK) {
+			printk(KERN_ERR "mvNfcCommandPio() failed for command %d (%d).\n", descInfo[i].cmd, status);
+			goto fail_stop;
+		}
+		NFC_DPRINT((PRINT_LVL "After issue command %d (NDSR=0x%x)\n", descInfo[i].cmd, MV_REG_READ(NFC_STATUS_REG)));
+	
+		/* Check if command phase interrupts events are needed */
+		if (orion_nfc_cmd_info_lkup[descInfo[i].cmd].events_p1) {
+			/* Enable necessary interrupts for command phase */
+			NFC_DPRINT((PRINT_LVL "Enabling part1 interrupts (IRQs 0x%x)\n", orion_nfc_cmd_info_lkup[descInfo[i].cmd].events_p1));
+			mvNfcIntrSet(&info->nfcCtrl, orion_nfc_cmd_info_lkup[descInfo[i].cmd].events_p1, MV_TRUE);	
+			
+			/* STEP2: wait for interrupt */
+			if (!orion_nfc_wait_for_completion_timeout(info, timeout)) {
+				printk(KERN_ERR "command %d execution timed out (CS %d, NDCR=0x%x, NDSR=0x%x).\n",
+				       descInfo[i].cmd, info->nfcCtrl.currCs, MV_REG_READ(NFC_CONTROL_REG), MV_REG_READ(NFC_STATUS_REG));
+				info->retcode = ERR_CMD_TO;
+				goto fail_stop;
+			}
+		
+			/* STEP3: Check for errors */
+			if (orion_nfc_error_check(info)) {
+				NFC_DPRINT((PRINT_LVL "Command level errors (DSCR=%08x, retcode=%d)\n", info->dscr, info->retcode));
+				goto fail_stop;
+			}
+		}		
+				
+		/* STEP4: PIO Read/Write data if needed */
+		if (descInfo[i].numSgBuffs > 1)
+		{
+			for (j=0; j< descInfo[i].numSgBuffs; j++) {
+				NFC_DPRINT((PRINT_LVL "Starting SG#%d PIO Read/Write (%d bytes, R/W mode %d)\n", j, 
+					    descInfo[i].sgBuffSize[j], orion_nfc_cmd_info_lkup[descInfo[i].cmd].rw));
+				mvNfcReadWritePio(&info->nfcCtrl, descInfo[i].sgBuffAddrVirt[j], 
+						  descInfo[i].sgBuffSize[j], orion_nfc_cmd_info_lkup[descInfo[i].cmd].rw);
+			}
+		}
+		else {
+			NFC_DPRINT((PRINT_LVL "Starting nonSG PIO Read/Write (%d bytes, R/W mode %d)\n", 
+				    descInfo[i].length, orion_nfc_cmd_info_lkup[descInfo[i].cmd].rw));
+			mvNfcReadWritePio(&info->nfcCtrl, descInfo[i].virtAddr, 
+					  descInfo[i].length, orion_nfc_cmd_info_lkup[descInfo[i].cmd].rw);
+		}
+
+		/* check if data phase events are needed */
+		if (orion_nfc_cmd_info_lkup[descInfo[i].cmd].events_p2) {
+			/* Enable the RDY interrupt to close the transaction */
+			NFC_DPRINT((PRINT_LVL "Enabling part2 interrupts (IRQs 0x%x)\n", orion_nfc_cmd_info_lkup[descInfo[i].cmd].events_p2));
+			mvNfcIntrSet(&info->nfcCtrl, orion_nfc_cmd_info_lkup[descInfo[i].cmd].events_p2, MV_TRUE);			
+
+			/* STEP5: Wait for transaction to finish */
+			if (!orion_nfc_wait_for_completion_timeout(info, timeout)) {
+				printk(KERN_ERR "command %d execution timed out (NDCR=0x%08x, NDSR=0x%08x, NDECCCTRL=0x%08x)\n", descInfo[i].cmd, 
+						MV_REG_READ(NFC_CONTROL_REG), MV_REG_READ(NFC_STATUS_REG), MV_REG_READ(NFC_ECC_CONTROL_REG));
+				info->retcode = ERR_DATA_TO;
+				goto fail_stop;
+			}
+		
+			/* STEP6: Check for errors BB errors (in erase) */
+			if (orion_nfc_error_check(info)) {
+				NFC_DPRINT((PRINT_LVL "Data level errors (DSCR=0x%08x, retcode=%d)\n", info->dscr, info->retcode));
+				goto fail_stop;
+			}
+		}
+	
+		/* Fallback - in case the NFC did not reach the idle state */
+		ndcr = MV_REG_READ(NFC_CONTROL_REG);
+		if (ndcr & NFC_CTRL_ND_RUN_MASK) {
+/*			printk(KERN_DEBUG "WRONG NFC STAUS: command %d, NDCR=0x%08x, NDSR=0x%08x, NDECCCTRL=0x%08x)\n", 
+					info->cmd, MV_REG_READ(NFC_CONTROL_REG), MV_REG_READ(NFC_STATUS_REG), MV_REG_READ(NFC_ECC_CONTROL_REG));*/
+			MV_REG_WRITE(NFC_CONTROL_REG, (ndcr & ~NFC_CTRL_ND_RUN_MASK));
+		}
+	}
+
+	NFC_DPRINT((PRINT_LVL "Command done (NDCR=0x%08x, NDSR=0x%08x)\n", MV_REG_READ(NFC_CONTROL_REG), MV_REG_READ(NFC_STATUS_REG)));
+	info->retcode = ERR_NONE;	
+	
+	return 0;
+
+fail_stop:
+	ndcr = MV_REG_READ(NFC_CONTROL_REG);
+	if (ndcr & NFC_CTRL_ND_RUN_MASK) {
+		printk(KERN_ERR "WRONG NFC STAUS: command %d, NDCR=0x%08x, NDSR=0x%08x, NDECCCTRL=0x%08x)\n", 
+		       info->cmd, MV_REG_READ(NFC_CONTROL_REG), MV_REG_READ(NFC_STATUS_REG), MV_REG_READ(NFC_ECC_CONTROL_REG));
+		MV_REG_WRITE(NFC_CONTROL_REG, (ndcr & ~NFC_CTRL_ND_RUN_MASK));
+	}
+	mvNfcIntrSet(&info->nfcCtrl, 0xFFF, MV_FALSE);
+	udelay(10);
+	return -ETIMEDOUT;
+}
+
+static int orion_nfc_dev_ready(struct mtd_info *mtd)
+{
+	return (MV_REG_READ(NFC_STATUS_REG) & (NFC_SR_RDY0_MASK | NFC_SR_RDY1_MASK)) ? 1 : 0;
+}
+
+static inline int is_buf_blank(uint8_t *buf, size_t len)
+{
+	for (; len > 0; len--)
+		if (*buf++ != 0xff)
+			return 0;
+	return 1;
+}
+
+static void orion_nfc_cmdfunc(struct mtd_info *mtd, unsigned command,
+				int column, int page_addr)
+{
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+	int ret = 0;
+
+	info->data_size = 0;
+	info->state = STATE_READY;
+	info->chained_cmd = 0;
+	info->retcode = ERR_NONE;
+
+	init_completion(&info->cmd_complete);
+
+	switch (command) {
+	case NAND_CMD_READOOB:
+		info->buf_count = mtd->writesize + mtd->oobsize;
+		info->buf_start = mtd->writesize + column;
+		info->cmd = MV_NFC_CMD_READ_MONOLITHIC;
+		info->column = column;
+		info->page_addr = page_addr;
+		if (prepare_read_prog_cmd(info, column, page_addr))
+			break;
+
+		if (info->use_dma)
+#ifdef CONFIG_MV_INCLUDE_PDM
+			orion_nfc_do_cmd_dma(info, MV_NFC_STATUS_RDY | NFC_SR_UNCERR_MASK);
+#else
+			printk(KERN_ERR "DMA mode not supported!\n");
+#endif
+		else
+			orion_nfc_do_cmd_pio(info);
+
+		/* We only are OOB, so if the data has error, does not matter */
+		if (info->retcode == ERR_DBERR)
+			info->retcode = ERR_NONE;
+		break;
+
+	case NAND_CMD_READ0:
+		info->buf_start = column;
+		info->buf_count = mtd->writesize + mtd->oobsize;
+		memset(info->data_buff, 0xff, info->buf_count);
+		info->cmd = MV_NFC_CMD_READ_MONOLITHIC;
+		info->column = column;
+		info->page_addr = page_addr;
+
+		if (prepare_read_prog_cmd(info, column, page_addr))
+			break;
+
+		if (info->use_dma)
+#ifdef CONFIG_MV_INCLUDE_PDM
+			orion_nfc_do_cmd_dma(info, MV_NFC_STATUS_RDY | NFC_SR_UNCERR_MASK);
+#else
+			printk(KERN_ERR "DMA mode not supported!\n");
+#endif
+		else
+			orion_nfc_do_cmd_pio(info);
+
+		if (info->retcode == ERR_DBERR) {
+			/* for blank page (all 0xff), HW will calculate its ECC as
+			 * 0, which is different from the ECC information within
+			 * OOB, ignore such double bit errors
+			 */
+			if (is_buf_blank(info->data_buff, mtd->writesize))
+				info->retcode = ERR_NONE;
+			else
+				printk(PRINT_LVL "%s: retCode == ERR_DBERR\n", __FUNCTION__);
+		}
+		break;
+	case NAND_CMD_SEQIN:
+		info->buf_start = column;
+		info->buf_count = mtd->writesize + mtd->oobsize;
+		memset(info->data_buff + mtd->writesize, 0xff, mtd->oobsize);
+
+		/* save column/page_addr for next CMD_PAGEPROG */
+		info->seqin_column = column;
+		info->seqin_page_addr = page_addr;
+		break;
+	case NAND_CMD_PAGEPROG:
+		info->column = info->seqin_column;
+		info->page_addr = info->seqin_page_addr;
+		info->cmd = MV_NFC_CMD_WRITE_MONOLITHIC;
+		if (prepare_read_prog_cmd(info,
+				info->seqin_column, info->seqin_page_addr)) {
+			printk(KERN_ERR "prepare_read_prog_cmd() failed.\n");
+			break;
+		}
+	
+		if (info->use_dma)
+#ifdef CONFIG_MV_INCLUDE_PDM
+			orion_nfc_do_cmd_dma(info, MV_NFC_STATUS_RDY);
+#else
+			printk(KERN_ERR "DMA mode not supported!\n");
+#endif
+		else
+			orion_nfc_do_cmd_pio(info);
+
+		break;
+	case NAND_CMD_ERASE1:
+		info->column = 0;
+		info->page_addr = page_addr;
+		info->cmd = MV_NFC_CMD_ERASE;
+
+		if (info->use_dma)
+#ifdef CONFIG_MV_INCLUDE_PDM
+			orion_nfc_do_cmd_dma(info, MV_NFC_STATUS_BBD | MV_NFC_STATUS_RDY);
+#else
+			printk(KERN_ERR "DMA mode not supported!\n");
+#endif
+		else
+			orion_nfc_do_cmd_pio(info);
+
+		break;
+	case NAND_CMD_ERASE2:
+		break;
+	case NAND_CMD_READID:
+	case NAND_CMD_STATUS:
+		info->buf_start = 0;
+		info->buf_count = (command == NAND_CMD_READID) ?
+				info->read_id_bytes : 1;
+		info->data_size = 8;
+		info->column = 0;
+		info->page_addr = 0;
+		info->cmd = (command == NAND_CMD_READID) ?
+			MV_NFC_CMD_READ_ID : MV_NFC_CMD_READ_STATUS;
+
+		if (info->use_dma)
+#ifdef CONFIG_MV_INCLUDE_PDM
+			orion_nfc_do_cmd_dma(info,MV_NFC_STATUS_RDY);
+#else
+			printk(KERN_ERR "DMA mode not supported!\n");
+#endif
+		else
+			orion_nfc_do_cmd_pio(info);
+
+		break;
+	case NAND_CMD_RESET:
+		info->column = 0;
+		info->page_addr = 0;
+		info->cmd = MV_NFC_CMD_RESET;
+
+		if (info->use_dma)
+#ifdef CONFIG_MV_INCLUDE_PDM
+			ret = orion_nfc_do_cmd_dma(info, MV_NFC_STATUS_CMDD);
+#else
+			printk(KERN_ERR "DMA mode not supported!\n");
+#endif
+		else
+			ret = orion_nfc_do_cmd_pio(info);
+
+		if (ret == 0) {
+			int timeout = 2;
+			uint32_t ndcr;
+
+			while (timeout--) {
+				if (MV_REG_READ(NFC_STATUS_REG) & (NFC_SR_RDY0_MASK | NFC_SR_RDY1_MASK))
+					break;
+				msleep(10);
+			}
+
+			ndcr = MV_REG_READ(NFC_CONTROL_REG);
+			MV_REG_WRITE(NFC_CONTROL_REG, ndcr & ~NFC_CTRL_ND_RUN_MASK);
+		}
+		break;
+	default:
+		printk(KERN_ERR "non-supported command.\n");
+		break;
+	}
+
+	if (info->retcode == ERR_DBERR) {
+		printk(KERN_ERR "double bit error @ page %08x (%d)\n",
+				page_addr, info->cmd);
+		info->retcode = ERR_NONE;
+	}
+}
+
+static uint8_t orion_nfc_read_byte(struct mtd_info *mtd)
+{
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+	char retval = 0xFF;
+
+	if (info->buf_start < info->buf_count)
+		/* Has just send a new command? */
+		retval = info->data_buff[info->buf_start++];
+	return retval;
+}
+
+static u16 orion_nfc_read_word(struct mtd_info *mtd)
+{
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+	u16 retval = 0xFFFF;
+
+	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
+		retval = *((u16 *)(info->data_buff+info->buf_start));
+		info->buf_start += 2;
+	}
+	else
+		printk(KERN_ERR "\n%s: returning 0xFFFF (%d, %d).\n",__FUNCTION__, info->buf_start,info->buf_count);
+
+	return retval;
+}
+
+static void orion_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+
+	memcpy(buf, info->data_buff + info->buf_start, real_len);
+	info->buf_start += real_len;
+}
+
+static void orion_nfc_write_buf(struct mtd_info *mtd,
+		const uint8_t *buf, int len)
+{
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+
+	memcpy(info->data_buff + info->buf_start, buf, real_len);
+	info->buf_start += real_len;
+}
+
+static int orion_nfc_verify_buf(struct mtd_info *mtd,
+		const uint8_t *buf, int len)
+{
+	return 0;
+}
+
+static void orion_nfc_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+	mvNfcSelectChip(&info->nfcCtrl, MV_NFC_CS_0 + chip);
+	return;
+}
+
+static int orion_nfc_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
+{
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+
+	/* orion_nfc_send_command has waited for command complete */
+	if (this->state == FL_WRITING || this->state == FL_ERASING) {
+		if (info->retcode == ERR_NONE)
+			return 0;
+		else {
+			/*
+			 * any error make it return 0x01 which will tell
+			 * the caller the erase and write fail
+			 */
+			return 0x01;
+		}
+	}
+
+	return 0;
+}
+
+static void orion_nfc_ecc_hwctl(struct mtd_info *mtd, int mode)
+{
+	return;
+}
+
+static int orion_nfc_ecc_calculate(struct mtd_info *mtd,
+		const uint8_t *dat, uint8_t *ecc_code)
+{
+	return 0;
+}
+
+static int orion_nfc_ecc_correct(struct mtd_info *mtd,
+		uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+	/*
+	 * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
+	 * consider it as a ecc error which will tell the caller the
+	 * read fail We have distinguish all the errors, but the
+	 * nand_read_ecc only check this function return value
+	 */
+	if (info->retcode != ERR_NONE)
+		return -1;
+
+	return 0;
+}
+
+static int orion_nfc_detect_flash(struct orion_nfc_info *info)
+{
+	MV_U32 my_page_size;
+
+	mvNfcFlashPageSizeGet(&info->nfcCtrl, &my_page_size, NULL);
+
+	/* Translate page size to enum */
+	switch (my_page_size)
+	{
+		case 512:
+			info->page_size = NFC_PAGE_512B;
+			break;
+
+		case 2048:
+			info->page_size = NFC_PAGE_2KB;
+			break;
+
+		case 4096:
+			info->page_size = NFC_PAGE_4KB;
+			break;
+		
+		case 8192:
+			info->page_size = NFC_PAGE_8KB;
+			break;
+
+		case 16384:
+			info->page_size = NFC_PAGE_16KB;
+			break;
+
+		default:
+			return -EINVAL;
+	}
+
+	info->flash_width = info->nfc_width;
+	if (info->flash_width != 16 && info->flash_width != 8)
+		return -EINVAL;
+
+	/* calculate flash information */
+	info->read_id_bytes = (pg_sz[info->page_size] >= 2048) ? 4 : 2;
+
+	return 0;
+}
+
+/* the maximum possible buffer size for ganaged 8K page with OOB data
+ * is: 2 * (8K + Spare) ==> to be alligned allocate 5 MMU (4K) pages
+ */
+#define MAX_BUFF_SIZE	(PAGE_SIZE * 5)
+
+static int orion_nfc_init_buff(struct orion_nfc_info *info)
+{
+	struct platform_device *pdev = info->pdev;
+
+	if (info->use_dma == 0) {
+		info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
+		if (info->data_buff == NULL)
+			return -ENOMEM;
+		return 0;
+	}
+
+	info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
+				&info->data_buff_phys, GFP_KERNEL);
+	if (info->data_buff == NULL) {
+		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
+		return -ENOMEM;
+	}
+	memset(info->data_buff, 0xff, MAX_BUFF_SIZE);
+
+#ifdef CONFIG_MV_INCLUDE_PDM
+	if (pxa_request_dma_intr ("nand-data", info->nfcCtrl.dataChanHndl.chanNumber,
+			orion_nfc_data_dma_irq, info) < 0) {
+		dev_err(&pdev->dev, "failed to request PDMA IRQ\n");
+		return -ENOMEM;
+	}
+#endif
+	return 0;
+}
+
+static uint8_t mv_bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
+static uint8_t mv_mirror_pattern[] = {'1', 't', 'b', 'B', 'V', 'M' };
+
+static struct nand_bbt_descr mvbbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	8,
+	.len = 6,
+	.veroffs = 14,
+	.maxblocks = 8,		/* Last 8 blocks in each chip */
+	.pattern = mv_bbt_pattern
+};
+
+static struct nand_bbt_descr mvbbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	8,
+	.len = 6,
+	.veroffs = 14,
+	.maxblocks = 8,		/* Last 8 blocks in each chip */
+	.pattern = mv_mirror_pattern
+};
+
+
+static int orion_nfc_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	uint8_t buf[6] = {0, 0, 0, 0, 0, 0};
+	int block, ret = 0;
+	loff_t page_addr;
+
+	/* Get block number */
+	block = (int)(ofs >> chip->bbt_erase_shift);
+	if (chip->bbt)
+		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
+	ret = nand_update_bbt(mtd, ofs);
+
+	if (ret == 0) {
+		/* Get address of the next block */
+		ofs += mtd->erasesize;
+		ofs &= ~(mtd->erasesize - 1);
+
+		/* Get start of oob in last page */
+		ofs -= mtd->oobsize;
+
+		page_addr = ofs;
+		do_div(page_addr, mtd->writesize);
+
+		orion_nfc_cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
+				page_addr);
+		orion_nfc_write_buf(mtd, buf, 6);
+		orion_nfc_cmdfunc(mtd, NAND_CMD_PAGEPROG, 0, page_addr);
+	}
+
+	return ret;
+}
+
+
+static void orion_nfc_init_nand(struct nand_chip *nand, struct orion_nfc_info *info)
+{
+	if (info->nfc_width == 16)
+		nand->options 	= (NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16);
+	else
+		nand->options 	= NAND_USE_FLASH_BBT;
+	nand->num_devs		= info->num_devs;
+	nand->oobsize_ovrd	= ((CHUNK_SPR * CHUNK_CNT) + LST_CHUNK_SPR);
+	nand->bb_location	= BB_BYTE_POS;
+	nand->bb_page		= mvNfcBadBlockPageNumber(&info->nfcCtrl);
+	nand->waitfunc		= orion_nfc_waitfunc;
+	nand->select_chip	= orion_nfc_select_chip;
+	nand->dev_ready		= orion_nfc_dev_ready;
+	nand->cmdfunc		= orion_nfc_cmdfunc;
+	nand->read_word		= orion_nfc_read_word;
+	nand->read_byte		= orion_nfc_read_byte;
+	nand->read_buf		= orion_nfc_read_buf;
+	nand->write_buf		= orion_nfc_write_buf;
+	nand->verify_buf	= orion_nfc_verify_buf;
+	nand->block_markbad	= orion_nfc_markbad;
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.hwctl		= orion_nfc_ecc_hwctl;
+	nand->ecc.calculate	= orion_nfc_ecc_calculate;
+	nand->ecc.correct	= orion_nfc_ecc_correct;
+	nand->ecc.size		= pg_sz[info->page_size];
+	nand->ecc.layout	= ECC_LAYOUT;
+	nand->bbt_td 		= &mvbbt_main_descr;
+	nand->bbt_md 		= &mvbbt_mirror_descr;
+	nand->badblock_pattern	= BB_INFO;
+	nand->chip_delay 	= 25;
+}
+
+static int orion_nfc_probe(struct platform_device *pdev)
+{
+	struct nfc_platform_data *pdata;
+	struct orion_nfc_info *info;
+	struct nand_chip *nand;
+	struct mtd_info *mtd;
+	struct resource *r;
+	int ret = 0, irq;
+	char * stat[2] = {"Disabled", "Enabled"};
+	char * ecc_stat[] = {"Hamming", "BCH 4bit", "BCH 8bit", "BCH 12bit", "BCH 16bit", "No"};
+	MV_NFC_INFO nfcInfo;
+
+	pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -ENODEV;
+	}
+
+	dev_info(&pdev->dev, "Initialize HAL based NFC in %dbit mode with DMA %s using %s ECC\n",
+			pdata->nfc_width, stat[pdata->use_dma], ecc_stat[pdata->ecc_type]);
+
+	/* Allocate all data: mtd_info -> nand_chip -> orion_nfc_info */
+	mtd = kzalloc(sizeof(struct mtd_info),	GFP_KERNEL);
+	if (!mtd) {
+		dev_err(&pdev->dev, "failed to allocate memory for mtd_info\n");
+		return -ENOMEM;
+	}
+
+	info = kzalloc(sizeof(struct orion_nfc_info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&pdev->dev, "failed to allocate memory for orion_nfc_info\n");
+		return -ENOMEM;
+	}
+
+	nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
+	if (!nand) {
+		dev_err(&pdev->dev, "failed to allocate memory for nand_chip\n");
+		return -ENOMEM;
+	}	
+
+	/* Hookup pointers */
+	info->pdev = pdev;
+	nand->priv = info;
+	mtd->priv = nand;
+	mtd->owner = THIS_MODULE;
+
+	/* Copy all necessary information from platform data */
+	info->use_dma = pdata->use_dma;
+	info->ecc_type = pdata->ecc_type;
+	info->nfc_width = pdata->nfc_width;
+	info->num_devs = pdata->num_devs;
+	info->num_cs = pdata->num_cs;
+	info->tclk = pdata->tclk;
+
+	/* Get the TCLK */
+        info->clk = clk_get_sys("dove-nand", NULL);
+        if (IS_ERR(info->clk)) {
+		dev_err(&pdev->dev, "failed to get nand clock\n");
+		ret = PTR_ERR(info->clk);
+		goto fail_free_mtd;
+        }
+        clk_enable(info->clk);
+
+#if 0
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ resource defined\n");
+		ret = -ENXIO;
+		goto fail_put_clk;
+	}
+#endif
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no IO memory resource defined\n");
+		ret = -ENODEV;
+		goto fail_put_clk;
+	}
+
+	r = devm_request_mem_region(&pdev->dev, r->start, r->end - r->start + 1,
+				    pdev->name);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "failed to request memory resource\n");
+		ret = -EBUSY;
+		goto fail_put_clk;
+	}
+
+	info->mmio_base = devm_ioremap(&pdev->dev, r->start,
+				       r->end - r->start + 1);
+	if (info->mmio_base == NULL) {
+		dev_err(&pdev->dev, "ioremap() failed\n");
+		ret = -ENODEV;
+		goto fail_put_clk;
+	}
+
+	info->mmio_phys_base = r->start;
+
+#if 0
+	if (mvPdmaHalInit(MV_PDMA_MAX_CHANNELS_NUM) != MV_OK) {
+		dev_err(&pdev->dev, "mvPdmaHalInit() failed.\n");
+		goto fail_put_clk;
+	}
+#endif
+	/* Initialize NFC HAL */
+	nfcInfo.ioMode = (info->use_dma ? MV_NFC_PDMA_ACCESS : MV_NFC_PIO_ACCESS);
+	nfcInfo.eccMode = info->ecc_type;
+		
+	if(info->num_devs == 1)
+		nfcInfo.ifMode = ((info->nfc_width == 8) ? MV_NFC_IF_1X8 : MV_NFC_IF_1X16);
+	else
+		nfcInfo.ifMode = MV_NFC_IF_2X8;
+	nfcInfo.autoStatusRead = MV_FALSE;
+	nfcInfo.tclk = info->tclk;
+	nfcInfo.readyBypass = MV_FALSE;
+	nfcInfo.osHandle = NULL;
+	nfcInfo.regsPhysAddr = INTER_REGS_BASE;
+#ifdef CONFIG_MV_INCLUDE_PDMA
+	nfcInfo.dataPdmaIntMask = MV_PDMA_END_OF_RX_INTR_EN | MV_PDMA_END_INTR_EN;
+	nfcInfo.cmdPdmaIntMask = 0x0;
+#endif
+	if (mvNfcInit(&nfcInfo, &info->nfcCtrl) != MV_OK) {
+		dev_err(&pdev->dev, "mvNfcInit() failed.\n");
+		goto fail_put_clk;
+	}
+
+	mvNfcSelectChip(&info->nfcCtrl, MV_NFC_CS_0);
+	mvNfcIntrSet(&info->nfcCtrl,  0xFFF, MV_FALSE);
+	mvNfcSelectChip(&info->nfcCtrl, MV_NFC_CS_1);
+	mvNfcIntrSet(&info->nfcCtrl,  0xFFF, MV_FALSE);
+	mvNfcSelectChip(&info->nfcCtrl, MV_NFC_CS_NONE);
+
+	ret = orion_nfc_init_buff(info);
+	if (ret)
+		goto fail_put_clk;
+
+	/* Clear all old events on the status register */
+	MV_REG_WRITE(NFC_STATUS_REG, MV_REG_READ(NFC_STATUS_REG));
+	if (info->use_dma)
+#ifdef CONFIG_MV_INCLUDE_PDMA
+		ret = request_irq(IRQ_AURORA_NFC, orion_nfc_irq_dma, IRQF_DISABLED,
+				pdev->name, info);
+#else
+		printk(KERN_ERR "DMA mode not supported!\n");
+#endif
+	else
+		ret = request_irq(NF_IRQ_NUM, orion_nfc_irq_pio, IRQF_DISABLED,
+				pdev->name, info);
+
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to request IRQ\n");
+		goto fail_free_buf;
+	}	
+
+	ret = orion_nfc_detect_flash(info);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to detect flash\n");
+		ret = -ENODEV;
+		goto fail_free_irq;
+	}
+
+	orion_nfc_init_nand(nand, info);
+
+	if (nand->ecc.layout == NULL) {
+		dev_err(&pdev->dev, "Undefined ECC layout for selected nand device\n");
+		ret = -ENXIO;
+		goto fail_free_irq;
+	}
+
+	platform_set_drvdata(pdev, mtd);
+
+	if (nand_scan(mtd, info->num_cs)) {
+		dev_err(&pdev->dev, "failed to scan nand\n");
+		ret = -ENXIO;
+		goto fail_free_irq;
+	}
+
+	if (mtd_has_partitions()) {
+		struct mtd_partition	*parts = NULL;
+		int			i, nr_parts = 0;
+
+		if (mtd_has_cmdlinepart()) {
+			static const char *part_probes[]
+					= { "cmdlinepart", NULL, };
+			mtd->name = "dove-nand";
+			nr_parts = parse_mtd_partitions(mtd,
+					part_probes, &parts, 0);
+		}
+
+		if (nr_parts <= 0 && pdata && pdata->parts) {
+			parts = pdata->parts;
+			nr_parts = pdata->nr_parts;
+		}
+
+		if (nr_parts > 0) {
+			for (i = 0; i < nr_parts; i++) {
+				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
+					"{.name = %s, .offset = 0x%llx, "
+						".size = 0x%llx (%lldKiB) }\n",
+					i, parts[i].name,
+					(long long)parts[i].offset,
+					(long long)parts[i].size,
+					(long long)(parts[i].size >> 10));
+			}
+			return add_mtd_partitions(mtd, parts, nr_parts);
+		}
+	} else if (pdata && pdata->nr_parts)
+		dev_warn(&info->pdev->dev, "ignoring %d default partitions on %s\n",
+				pdata->nr_parts, info->pdev->name);
+
+	return add_mtd_device(mtd) == 1 ? -ENODEV : 0;
+
+fail_free_irq:
+	free_irq(NF_IRQ_NUM, info);
+fail_free_buf:
+	if (pdata->use_dma) {
+		dma_free_coherent(&pdev->dev, info->data_buff_size,
+			info->data_buff, info->data_buff_phys);
+	} else
+		kfree(info->data_buff);
+fail_put_clk:
+	clk_disable(info->clk);
+	clk_put(info->clk);
+fail_free_mtd:
+	kfree(mtd);
+	kfree(nand);
+	kfree(info);
+	return ret;
+}
+
+static int orion_nfc_remove(struct platform_device *pdev)
+{
+	struct mtd_info *mtd = platform_get_drvdata(pdev);
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+
+	platform_set_drvdata(pdev, NULL);
+
+	del_mtd_device(mtd);
+	del_mtd_partitions(mtd);
+	free_irq(NF_IRQ_NUM, info);
+	if (info->use_dma) {
+		dma_free_writecombine(&pdev->dev, info->data_buff_size,
+				info->data_buff, info->data_buff_phys);
+	} else
+		kfree(info->data_buff);
+
+	clk_disable(info->clk);
+	clk_put(info->clk);
+	kfree(mtd);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int orion_nfc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+
+	if (info->state != STATE_READY) {
+		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
+		return -EAGAIN;
+	}
+
+#ifdef MV_INCLUDE_PDMA
+	/* Store PDMA registers.	*/
+	info->pdmaDataLen = 128;
+	mvPdmaUnitStateStore(info->pdmaUnitData, &info->pdmaDataLen);
+#endif
+
+	/* Store NFC registers.	*/
+	info->nfcDataLen = 128;
+	mvNfcUnitStateStore(info->nfcUnitData, &info->nfcDataLen);
+
+	clk_disable(info->clk);
+	return 0;
+}
+
+static int orion_nfc_resume(struct platform_device *pdev)
+{
+	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
+	struct orion_nfc_info *info = (struct orion_nfc_info *)((struct nand_chip *)mtd->priv)->priv;
+	MV_U32	i;
+
+	clk_enable(info->clk);
+
+	/* restore PDMA registers */
+	for(i = 0; i < info->pdmaDataLen; i+=2)
+		MV_REG_WRITE(info->pdmaUnitData[i], info->pdmaUnitData[i+1]);
+
+	/* Clear all NAND interrupts */
+	MV_REG_WRITE(NFC_STATUS_REG, MV_REG_READ(NFC_STATUS_REG));
+
+	/* restore NAND registers */
+	for(i = 0; i < info->nfcDataLen; i+=2)
+		MV_REG_WRITE(info->nfcUnitData[i], info->nfcUnitData[i+1]);
+
+	return 0;
+}
+#else
+#define orion_nfc_suspend	NULL
+#define orion_nfc_resume	NULL
+#endif
+
+static struct platform_driver orion_nfc_driver = {
+	.driver = {
+		.name	= "orion-nfc-hal",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= orion_nfc_probe,
+	.remove		= orion_nfc_remove,
+	.suspend	= orion_nfc_suspend,
+	.resume		= orion_nfc_resume,
+};
+
+static int __init orion_nfc_init(void)
+{
+	return platform_driver_register(&orion_nfc_driver);
+}
+module_init(orion_nfc_init);
+
+static void __exit orion_nfc_exit(void)
+{
+	platform_driver_unregister(&orion_nfc_driver);
+}
+module_exit(orion_nfc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Dove NAND controller driver")
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_nfc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_nfc.h
new file mode 100755
index 0000000..df1cdb1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/nand_nfc.h
@@ -0,0 +1,36 @@
+#ifndef __ASM_ARCH_ORION_NFC_H
+#define __ASM_ARCH_ORION_NFC_H
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include "mvCommon.h"
+#include "mvOs.h"
+#ifdef MV_INCLUDE_PDMA
+#include "pdma/mvPdma.h"
+#endif
+#include "nfc/mvNfc.h"
+#include "nfc/mvNfcRegs.h"
+
+enum nfc_page_size
+{
+	NFC_PAGE_512B = 0,
+	NFC_PAGE_2KB,
+	NFC_PAGE_4KB,
+	NFC_PAGE_8KB,
+	NFC_PAGE_16KB,
+	NFC_PAGE_SIZE_MAX_CNT
+};
+
+struct nfc_platform_data {
+	unsigned int		tclk;		/* Clock supplied to NFC */
+	unsigned int		nfc_width;	/* Width of NFC 16/8 bits */
+	unsigned int		num_devs;	/* Number of NAND devices 
+						   (2 for ganged mode).   */
+	unsigned int		num_cs;		/* Number of NAND devices 
+						   chip-selects.	  */
+	unsigned int		use_dma;	/* Enable/Disable DMA 1/0 */
+	MV_NFC_ECC_MODE		ecc_type;
+	struct mtd_partition *	parts;
+	unsigned int		nr_parts;	
+};
+#endif /* __ASM_ARCH_ORION_NFC_H */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/sflash.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/sflash.c
new file mode 100755
index 0000000..cd7c20a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/sflash.c
@@ -0,0 +1,419 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "sflash/mvSFlash.h"
+#include "sflash/mvSFlashSpec.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+/*#define MTD_SFLASH_DEBUG*/
+
+#ifdef MTD_SFLASH_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/* macros for interrupts enable/disable */
+#define sflash_disable_irqs(flags, sflash_in_irq)	\
+	sflash_in_irq = in_interrupt();			\
+	if(!sflash_in_irq)	 	 		\
+		local_irq_save(flags);	 
+
+#define sflash_enable_irqs(flags, sflash_in_irq)	\
+	if(!sflash_in_irq)				\
+		local_irq_restore(flags);	 
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
+	typedef	uint32_t 	sflash_size_t;
+#else
+	typedef uint64_t	sflash_size_t;
+#endif
+
+/* Configuration options */
+static struct mtd_info *sflash_probe(struct map_info *map);
+static void sflash_destroy(struct mtd_info *mtd);
+static int sflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+static int sflash_write(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, const u_char *buf);
+static int sflash_erase(struct mtd_info *mtd, struct erase_info *instr);
+static void sflash_sync(struct mtd_info *mtd);
+static int sflash_suspend(struct mtd_info *mtd);
+static void sflash_resume(struct mtd_info *mtd);
+static int sflash_lock (struct mtd_info *mtd, loff_t ofs, sflash_size_t len);
+static int sflash_unlock (struct mtd_info *mtd, loff_t ofs, sflash_size_t len);
+static int sflash_block_isbad (struct mtd_info *mtd, loff_t ofs);
+static int sflash_block_markbad (struct mtd_info *mtd, loff_t ofs);
+
+static struct mtd_chip_driver sflash_chipdrv = {
+	.probe		= sflash_probe,
+	.destroy	= sflash_destroy,
+	.name		= "sflash",
+	.module		= THIS_MODULE
+};
+
+
+static struct mtd_info *sflash_probe(struct map_info *map)
+{
+	struct mtd_info *mtd = NULL;
+	MV_SFLASH_INFO *sflash = NULL;
+	MV_ULONG flags = 0, sflash_in_irq = 0;
+
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+	if (MV_FALSE == mvSocUnitIsMappedToThisCpu(SPI_FLASH))
+	{
+		printk(KERN_INFO"SPI flash is not mapped to this CPU\n");
+		return -ENODEV;
+	}		
+#endif
+
+	DB(printk("\nINFO: entering %s",__FUNCTION__));
+
+	/* allocate the memory for the mtd_info */
+	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	if(!mtd)
+	{
+		printk(KERN_NOTICE "\nERROR: %s - Failed to allocate memory for mtd structure",__FUNCTION__);
+		return NULL;
+	}
+
+	/* allocate memory for the sflash private structure */
+	sflash = kmalloc(sizeof(MV_SFLASH_INFO), GFP_KERNEL);
+	if(!sflash) 
+	{
+		printk(KERN_NOTICE "\nERROR: %s - Failed to allocate memory for sflash structure",__FUNCTION__);
+		kfree(mtd);
+		return NULL;
+	}
+		
+	/* clear both structures before usage */
+	memset(mtd, 0, sizeof(*mtd));
+	memset(sflash, 0, sizeof(*sflash));
+	    
+	DB(printk("\nINFO: %s - Base address %08x",__FUNCTION__, sflash->baseAddr));
+#ifdef CONFIG_ARCH_FEROCEON_ORION	
+	/* First check that SPI bus mode is configured to connect to an external SFlash */
+    if (mvCtrlSpiBusModeDetect() != MV_SPI_CONN_TO_EXT_FLASH)
+    {
+        printk(KERN_NOTICE "\nERROR: %s - SPI interface is not routed to external SPI flash!", __FUNCTION__);
+		kfree(mtd);
+		kfree(sflash);
+		return NULL;
+    }
+#endif
+	/* Try to detect the flash and initialize it over SPI */	
+	sflash->baseAddr         = map->phys;
+    sflash->index            = MV_INVALID_DEVICE_NUMBER; /* will be detected in init */	
+	sflash_disable_irqs(flags, sflash_in_irq);	
+	if (mvSFlashInit(sflash) != MV_OK)
+	{
+		sflash_enable_irqs(flags, sflash_in_irq);
+		printk(KERN_NOTICE "ERROR: %s - Failed to initialize the SFlash.", __FUNCTION__);
+		kfree(mtd);
+		kfree(sflash);
+		return NULL;
+	}
+	sflash_enable_irqs(flags, sflash_in_irq);
+	
+	/* After success fill in the MTD structure with the appropriate info */
+	mtd->erasesize = sflash->sectorSize;
+	mtd->size = sflash->sectorSize * sflash->sectorNumber;
+	mtd->priv = map; /*sflash;*/
+	mtd->type = MTD_NORFLASH;
+	mtd->erase = sflash_erase;
+	mtd->read = sflash_read;
+	mtd->write = sflash_write;
+	mtd->sync = sflash_sync;
+	mtd->suspend = sflash_suspend;
+	mtd->resume = sflash_resume;	
+	mtd->lock = sflash_lock;
+	mtd->unlock = sflash_unlock;
+	mtd->block_isbad = sflash_block_isbad;
+	mtd->block_markbad = sflash_block_markbad;	
+	mtd->flags = (MTD_WRITEABLE | MTD_BIT_WRITEABLE); /* just like MTD_CAP_NORFLASH */
+	mtd->name = map->name;
+	mtd->writesize = 1;
+	
+	map->fldrv = &sflash_chipdrv;
+	map->fldrv_priv = sflash;
+	
+	/* Print some debug messages with the detected sflash info */
+	DB(printk("\nINFO: %s - Detected SFlash device (size %d)", __FUNCTION__, mtd->size));
+	DB(printk("\n           Base Address    : 0x%08x", sflash->baseAddr));
+	DB(printk("\n           Manufacturer ID : 0x%02x", sflash->manufacturerId));
+	DB(printk("\n           Device ID       : 0x%04x", sflash->deviceId));
+	DB(printk("\n           Sector Size     : 0x%x", sflash->sectorSize));
+	DB(printk("\n           Sector Number   : %d", sflash->sectorNumber));
+	
+	printk("SPI Serial flash detected @ 0x%08x, %dKB (%dsec x %dKB)\n",
+	         sflash->baseAddr, ((sflash->sectorNumber * sflash->sectorSize)/1024), 
+	         sflash->sectorNumber, (sflash->sectorSize/1024));
+	
+	__module_get(THIS_MODULE);
+	return mtd;
+}
+
+static void sflash_destroy(struct mtd_info *mtd)
+{
+	struct map_info *map = mtd->priv;
+	MV_SFLASH_INFO *sflash = map->fldrv_priv;
+
+	DB(printk("\nINFO: %s called", __FUNCTION__));
+
+	/* free memory allocated at probe for the private sflash structure */
+	if (sflash)
+		kfree(sflash);	
+}
+
+static int sflash_read(struct mtd_info *mtd, loff_t from, size_t len,
+	size_t *retlen, u_char *buf)
+{
+	struct map_info *map = mtd->priv;
+	MV_SFLASH_INFO *sflash = map->fldrv_priv;
+	MV_U32 offset = ((MV_U32)from);
+	MV_ULONG flags = 0, sflash_in_irq = 0;
+
+	
+	*retlen = 0;
+
+	DB(printk("\nINFO: %s  - offset %08x, len %d",__FUNCTION__, offset, (int)len));
+
+	sflash_disable_irqs(flags, sflash_in_irq);
+	if (mvSFlashBlockRd(sflash, offset, buf, len) != MV_OK)
+	{
+		sflash_enable_irqs(flags, sflash_in_irq);
+		printk(KERN_NOTICE "\nERROR: %s - Failed to read block.", __FUNCTION__);
+		return -1;
+	}
+	sflash_enable_irqs(flags, sflash_in_irq);
+	
+	*retlen = len;
+	
+	DB(printk(" - OK"));
+	return 0;	
+}
+
+static int sflash_write(struct mtd_info *mtd, loff_t to, size_t len,
+	size_t *retlen, const u_char *buf)
+{
+	struct map_info *map = mtd->priv;
+	MV_SFLASH_INFO *sflash = map->fldrv_priv;
+/*	MV_SFLASH_INFO *sflash = mtd->priv;*/
+	MV_U32 offset = ((MV_U32)to);
+	MV_ULONG flags = 0, sflash_in_irq = 0;
+	
+	*retlen = 0;
+	
+	DB(printk("\nINFO: %s - offset %08x, len %d",__FUNCTION__, offset, len));
+		
+	sflash_disable_irqs(flags, sflash_in_irq);
+	if (mvSFlashBlockWr(sflash, offset, (MV_U8*)buf, len) != MV_OK)
+	{
+		sflash_enable_irqs(flags, sflash_in_irq);
+		printk(KERN_NOTICE "\nERROR: %s - Failed to write block", __FUNCTION__);
+		return -1;
+	}
+	sflash_enable_irqs(flags, sflash_in_irq);
+	
+	*retlen = len;
+	
+	DB(printk(" - OK"));
+	return 0;	
+
+}
+
+
+static int sflash_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct map_info *map = mtd->priv;
+	MV_SFLASH_INFO *sflash = map->fldrv_priv;
+/*	MV_SFLASH_INFO *sflash = mtd->priv;*/
+	MV_U32 fsec, lsec;
+	int i;
+	MV_ULONG flags = 0, sflash_in_irq = 0;
+
+	DB(printk("\nINFO: %s - Addr %08x, len %d",__FUNCTION__, instr->addr, instr->len));
+	
+	if(instr->addr & (mtd->erasesize - 1))
+	{
+		printk(KERN_NOTICE "\nError: %s - Erase address not sector alligned",__FUNCTION__);
+		return -EINVAL;
+	}
+	if(instr->len & (mtd->erasesize - 1))
+	{
+		printk(KERN_NOTICE "\nError: %s - Erase length is not sector alligned",__FUNCTION__);
+		return -EINVAL;
+	}
+	if(instr->len + instr->addr > mtd->size)
+	{
+		printk(KERN_NOTICE "\nError: %s - Erase exceeded flash size",__FUNCTION__);
+		return -EINVAL;
+	}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
+	fsec = (instr->addr / mtd->erasesize);
+	lsec = (fsec +(instr->len / mtd->erasesize));
+#else
+	fsec = instr->addr;
+	do_div(fsec, mtd->erasesize);
+	lsec = instr->len;
+	do_div(lsec, mtd->erasesize);
+	lsec = (fsec + lsec);
+#endif
+
+	DB(printk("\nINFO: %s - from sector %u to %u",__FUNCTION__, fsec, 
+		  lsec-1));
+	
+	sflash_disable_irqs(flags, sflash_in_irq);
+	for (i=fsec; i<lsec; i++)
+	{
+		if (mvSFlashSectorErase(sflash, i) != MV_OK)
+		{
+			sflash_enable_irqs(flags, sflash_in_irq);
+			printk(KERN_NOTICE "\nError: %s - mvSFlashSectorErase on sector %d",__FUNCTION__, i);
+			return -1;
+		}
+	}
+	sflash_enable_irqs(flags, sflash_in_irq);
+	
+	instr->state = MTD_ERASE_DONE;
+	mtd_erase_callback(instr);
+
+	return 0;
+}
+
+static int sflash_lock (struct mtd_info *mtd, loff_t ofs, sflash_size_t len)
+{
+	struct map_info *map = mtd->priv;
+	MV_SFLASH_INFO *sflash = map->fldrv_priv;
+	MV_ULONG flags = 0, sflash_in_irq = 0;
+/*	MV_SFLASH_INFO *sflash = mtd->priv;*/
+	
+	DB(printk("\nINFO: %s called", __FUNCTION__));
+	
+	sflash_disable_irqs(flags, sflash_in_irq);
+	if (mvSFlashWpRegionSet(sflash, MV_WP_ALL) != MV_OK)
+	{
+		sflash_enable_irqs(flags, sflash_in_irq);
+		printk(KERN_NOTICE "\nError: %s - mvSFlashWpRegionSet failed",__FUNCTION__);
+		return -1;
+	}
+	sflash_enable_irqs(flags, sflash_in_irq);
+	
+	printk("\nNotice: Serial SPI flash (%s) lock per sector is not supported!\n        Locking the whole device.", mtd->name);
+		
+	return 0;
+}
+
+static int sflash_unlock (struct mtd_info *mtd, loff_t ofs, sflash_size_t len)
+{
+	struct map_info *map = mtd->priv;
+	MV_SFLASH_INFO *sflash = map->fldrv_priv;
+	MV_ULONG flags = 0, sflash_in_irq = 0;
+/*	MV_SFLASH_INFO *sflash = mtd->priv;*/
+
+	DB(printk("\nINFO: %s called", __FUNCTION__));
+	
+	sflash_disable_irqs(flags, sflash_in_irq);
+	if (mvSFlashWpRegionSet(sflash, MV_WP_NONE) != MV_OK)
+	{
+		sflash_enable_irqs(flags, sflash_in_irq);
+		printk(KERN_NOTICE "\nError: %s - mvSFlashWpRegionSet failed",__FUNCTION__);
+		return -1;
+	}
+	sflash_enable_irqs(flags, sflash_in_irq);
+		
+	printk("\nNotice: Serial SPI flash (%s) unlock per sector is not supported!\n        Unlocking the whole device.", mtd->name);
+	return 0;
+}
+
+static void sflash_sync(struct mtd_info *mtd)
+{
+	DB(printk("\nINFO: %s called - DUMMY", __FUNCTION__));
+}
+
+static int sflash_suspend(struct mtd_info *mtd)
+{
+	DB(printk("\nINFO: %s called - DUMMY()", __FUNCTION__));
+	return 0;
+}
+
+static void sflash_resume(struct mtd_info *mtd)
+{
+	DB(printk("\nINFO: %s called - DUMMY", __FUNCTION__));
+}
+
+static int sflash_block_isbad (struct mtd_info *mtd, loff_t ofs)
+{
+	DB(printk("\nINFO: %s called - DUMMY", __FUNCTION__));
+	return 0;
+}
+
+static int sflash_block_markbad (struct mtd_info *mtd, loff_t ofs)
+{
+	DB(printk("\nINFO: %s called - DUMMY", __FUNCTION__));
+	return 0;
+}
+
+static int __init sflash_probe_init(void)
+{
+	DB(printk("\nINFO: %s - MTD SFlash chip driver.\n", __FUNCTION__));
+
+	register_mtd_chip_driver(&sflash_chipdrv);
+
+	return 0;
+}
+
+static void __exit sflash_probe_exit(void)
+{
+	DB(printk(KERN_ALERT "\nINFO: %s - MTD SFlash driver exit", __FUNCTION__));
+	unregister_mtd_chip_driver(&sflash_chipdrv);
+}
+
+module_init(sflash_probe_init);
+module_exit(sflash_probe_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("MTD chip driver for the SPI serial flash device");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/Kconfig
new file mode 100755
index 0000000..6046c62
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/Kconfig
@@ -0,0 +1,1027 @@
+config MV_ETH_PORTS_NUM
+	int "Number of Marvell GbE ports"
+	depends on MV_ETH_NETA
+	default 1
+	---help---
+	Number of Marvell GbE ports supported by NETA driver
+
+menu "BM configuration"
+
+config MV_ETH_BM
+	depends on MV_ETH_NETA
+	bool "Buffer Management support (BM)"
+	default y
+        ---help---
+
+config MV_ETH_BM_CPU
+	depends on MV_ETH_BM
+	bool "Use BM for CPU processed traffic"
+	default y
+	---help---
+	BM pools is used for traffic processed by CPU and HWF both
+
+config MV_ETH_BM_0_PKT_SIZE
+	depends on MV_ETH_BM
+	int "Packet size [bytes] can use buffers from pool #0"
+	default 0
+	---help---
+	0 - means that packet size for the pool will be defined accordingly
+        with MTU of the port that use this pool.
+
+config MV_ETH_BM_1_PKT_SIZE
+	depends on MV_ETH_BM
+	int "Packet size [bytes] can use buffers from pool #1"
+	default 0
+        ---help---
+        0 - means that packet size for the pool will be defined accordingly
+        with MTU of the port that use this pool.
+
+config MV_ETH_BM_2_PKT_SIZE
+	depends on MV_ETH_BM
+	int "Packet size [bytes] can use buffers from pool #2"
+	default 0
+	---help---
+        0 - means that packet size for the pool will be defined accordingly
+        with MTU of the port that use this pool.
+
+config MV_ETH_BM_3_PKT_SIZE
+	depends on MV_ETH_BM
+	int "Packet size [bytes] can use buffers from pool #3"
+	default 256
+	---help---
+        0 - means that packet size for the pool will be defined accordingly
+        with MTU of the port that use this pool.
+
+menuconfig  MV_ETH_BM_PORT_0
+        depends on (MV_ETH_BM && (MV_ETH_PORTS_NUM != 0))
+        bool "BM configuration for GbE #0"
+        default y
+        ---help---
+
+config  MV_ETH_BM_PORT_0_LONG_POOL
+	int "Long BM pool for GbE #0"
+	depends on MV_ETH_BM_PORT_0
+	range -1 3 if MV_ETH_BM_CPU
+	range 0 3 if !MV_ETH_BM_CPU
+	default 0
+	---help---
+	BM pool to be used for GbE #0 port to process long packets
+	-1 means that port will choose BM pool closest to required buffers size.
+
+config  MV_ETH_BM_PORT_0_SHORT_POOL
+        int "Short BM pool for GbE #0"
+        depends on MV_ETH_BM_PORT_0
+        range 0 3
+        default 3
+	---help---
+	BM pool to be used for GbE #0 port to process short packets
+
+config  MV_ETH_BM_PORT_0_LONG_BUF_NUM
+        int "Number of buffers for Long pool of GbE #0"
+        depends on MV_ETH_BM_PORT_0
+        range 128 16384
+        default 2048
+        ---help---
+	Number of long buffers allocated for this port.
+
+config  MV_ETH_BM_PORT_0_SHORT_BUF_NUM
+        int "Number of buffers for Short pool of GbE #0"
+        depends on MV_ETH_BM_PORT_0
+        range 1 16384
+        default 3072
+	---help---
+        Number of short buffers allocated for this port.
+
+menuconfig  MV_ETH_BM_PORT_1
+        depends on (MV_ETH_BM && (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1))
+        bool "BM configuration for GbE #1"
+        default y
+        ---help---
+
+config  MV_ETH_BM_PORT_1_LONG_POOL
+        int "Long BM pool for GbE #1"
+        depends on MV_ETH_BM_PORT_1
+	range -1 3 if MV_ETH_BM_CPU
+	range 0 3 if !MV_ETH_BM_CPU
+        default 1
+        ---help---
+        BM pool to be used for GbE #1 port to process long packets.
+	-1 means that port will choose BM pool closest to required buffers size.
+
+config  MV_ETH_BM_PORT_1_SHORT_POOL
+        int "Short BM pool for GbE #1"
+        depends on MV_ETH_BM_PORT_1
+        range 0 3
+        default 3
+        ---help---
+        BM pool to be used for GbE #1 port to process short packets.
+
+config  MV_ETH_BM_PORT_1_LONG_BUF_NUM
+        int "Number of buffers for Long pool of GbE #1"
+        depends on MV_ETH_BM_PORT_1
+        range 128 16384
+        default 2048
+        ---help---
+	Number of long buffers allocated for this port.
+
+config  MV_ETH_BM_PORT_1_SHORT_BUF_NUM
+        int "Number of buffers for Short pool of GbE #1"
+        depends on MV_ETH_BM_PORT_1
+        range 1 16384
+        default 3072
+        ---help---
+	Number of short buffers allocated for this port.
+
+menuconfig  MV_ETH_BM_PORT_2
+        depends on (MV_ETH_BM && (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) &&  (MV_ETH_PORTS_NUM != 2))
+        bool "BM configuration for GbE #2"
+        default y
+        ---help---
+
+config  MV_ETH_BM_PORT_2_LONG_POOL
+        int "Long BM pool for GbE #2"
+        depends on MV_ETH_BM_PORT_2
+        range -1 3 if MV_ETH_BM_CPU
+        range 0 3 if !MV_ETH_BM_CPU
+        default 2
+        ---help---
+        BM pool to be used for GbE #2 port to process long packets.
+	-1 means that port will choose BM pool closest to required buffers size.
+
+config  MV_ETH_BM_PORT_2_SHORT_POOL
+        int "Short BM pool for GbE #2"
+        depends on MV_ETH_BM_PORT_2
+        range 0 3
+        default 3
+        ---help---
+	BM pool to be used for GbE #2 port to process short packets.
+
+config  MV_ETH_BM_PORT_2_LONG_BUF_NUM
+        int "Number of buffers for Long pool of GbE #2"
+        depends on MV_ETH_BM_PORT_2
+        range 1 16384
+        default 2048
+        ---help---
+        Number of long buffers allocated for this port.
+
+config  MV_ETH_BM_PORT_2_SHORT_BUF_NUM
+        int "Number of buffers for Short pool of GbE #2"
+        depends on MV_ETH_BM_PORT_2
+        range 1 16384
+        default 3072
+        ---help---
+        Number of short buffers allocated for this port.
+
+menuconfig  MV_ETH_BM_PORT_3
+        depends on (MV_ETH_BM && (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2) && (MV_ETH_PORTS_NUM != 3))
+        bool "BM configuration for GbE #3"
+        default y
+        ---help---
+
+config  MV_ETH_BM_PORT_3_LONG_POOL
+        int "Long BM pool for GbE #3"
+        depends on MV_ETH_BM_PORT_3
+        range -1 3 if MV_ETH_BM_CPU
+        range 0 3 if !MV_ETH_BM_CPU
+        default 3
+        ---help---
+        BM pool to be used for GbE #3 port to process long packets.
+	-1 means that port will choose BM pool closest to required buffers size.
+
+config  MV_ETH_BM_PORT_3_SHORT_POOL
+        int "Short BM pool for GbE #3"
+        depends on MV_ETH_BM_PORT_3
+        range 0 3
+        default 3
+        ---help---
+	BM pool to be used for GbE #3 port to process short packets.
+
+config  MV_ETH_BM_PORT_3_LONG_BUF_NUM
+        int "Number of buffers for Long pool of GbE #3"
+        depends on MV_ETH_BM_PORT_3
+        range 128 16384
+        default 2048
+        ---help---
+        Number of long buffers allocated for this port.
+
+config  MV_ETH_BM_PORT_3_SHORT_BUF_NUM
+        int "Number of buffers for Short pool of GbE #3"
+        depends on MV_ETH_BM_PORT_3 && (MV_ETH_BM_PORT_3_LONG_POOL != MV_ETH_BM_PORT_3_SHORT_POOL)
+        range 128 16384
+        default 3072
+        ---help---
+        Number of short buffers allocated for this port.
+
+endmenu
+
+config MV_ETH_LEGACY_PARSER
+	depends on !MV_ETH_PNC
+	bool "Use legacy parser for incoming traffic"
+	default y
+	---help---
+
+menuconfig MV_ETH_PNC
+        depends on MV_ETH_NETA
+        bool "PnC support"
+	default y
+        ---help---
+
+config MV_PNC_TCAM_LINES
+        depends on MV_ETH_PNC
+        int "Number of TCAM lines supported by PNC"
+        default 512
+        ---help---
+
+config MV_ETH_PNC_MCAST_NUM
+        depends on MV_ETH_PNC
+        int "Use PnC for Multicast MAC addresses filtering"
+        default 8
+        ---help---
+	Number of Multicast addresses can be matched and accepted
+	for all ports
+
+config MV_ETH_PNC_VLAN_PRIO
+        depends on MV_ETH_PNC
+        int "Use PnC for VLAN priority mapping"
+        range 0 32
+        default 7
+        ---help---
+	Number of VLAN priorities can be mapped to different RXQs for all ports
+
+config MV_ETH_PNC_ETYPE
+        depends on MV_ETH_PNC
+        int "Use PnC for extra ETYPE detection"
+        default 0
+        ---help---
+        Number of extra ETYPEs can be detected in addition to
+	ARP, IPv4, IPv6, PPPoE are detected by default.
+
+config MV_ETH_PNC_DSCP_PRIO
+        depends on MV_ETH_PNC
+        int "Use PnC for DSCP priority mapping"
+        range 0 256
+        default 16
+        ---help---
+        Number of DSCP priorities can be mapped to different RXQs for all ports
+
+config MV_ETH_PNC_L3_FLOW
+	depends on MV_ETH_PNC
+        bool "Use PNC for L3 Flows detection"
+        default n
+        ---help---
+        Use PNC rules for IPv4 and IPv6 Flows processing.
+        When enabled, MV_ETH_PNC_WOL will be disabled.
+
+config MV_ETH_PNC_WOL
+	depends on MV_ETH_PNC
+	bool "Use PNC for Wake On LAN support"
+	default n
+	---help---
+	Use PNC rules for TCAM filtering for Wake on LAN support.
+
+menuconfig MV_ETH_HWF
+	depends on (MV_ETH_PNC && MV_ETH_BM)
+        bool "Hardware Forwarding support (HWF)"
+        default y
+        ---help---
+
+config MV_ETH_HWF_TXQ_DROP
+	depends on MV_ETH_HWF
+	int "HWF Drop Threshold [%]"
+	default 60
+	---help---
+
+config MV_ETH_HWF_TXQ_DROP_RND
+        depends on MV_ETH_HWF
+        int "HWF Drop Random Generator bits"
+        default 0
+        ---help---
+
+config MV_ETH_PMT
+        depends on MV_ETH_NETA
+        bool "Packet Modification Table (PMT)"
+        default n
+        ---help---
+
+config MV_ETH_PMT_FLOWS
+	int "Number of different flows can be set to PMT"
+	depends on MV_ETH_PMT
+	default 256
+	---help---
+	Depend on total number of PMT entries and
+	number of PMT entires reserved for each flow.
+	MV_ETH_PMT_SIZE >= (MV_ETH_PMT_FLOWS * (MV_ETH_PMT_CMD_PER_FLOW + 1))
+
+config MV_ETH_PMT_CMD_PER_FLOW
+        int "Number of PMT entries reserved for each flow"
+        depends on MV_ETH_PMT
+        default 12
+        ---help---
+        Depend on total number of PMT entries and
+        number of flows to be supported.
+	MV_ETH_PMT_SIZE >= (MV_ETH_PMT_FLOWS * (MV_ETH_PMT_CMD_PER_FLOW + 1))
+
+menu "Network Interface configuration"
+
+config  MV_ETH_0_MTU
+	int "Giga port #0 MTU value"
+	depends on (MV_ETH_PORTS_NUM != 0)
+ 	default 1500
+        ---help---
+	Default MTU value for Marvell GbE port #0
+
+config  MV_ETH_0_MACADDR
+        string "Giga port #0 MAC address"
+        depends on (MV_ETH_PORTS_NUM != 0)
+        default "00:00:00:00:00:80"
+        ---help---
+        Default MAC address for Marvell GbE port #0
+
+config  MV_ETH_1_MTU
+        int "Giga port #1 MTU value"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1)
+        default 1500
+        ---help---
+	Default MTU value for Marvell GbE port #1
+
+config  MV_ETH_1_MACADDR
+        string "Giga port #1 MAC address"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1)
+        default "00:00:00:00:00:81"
+        ---help---
+        Default MAC address for Marvell GbE port #1
+
+config  MV_ETH_2_MTU
+        int "Giga port #2 MTU value"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2)
+        default 1500
+        ---help---
+        Default MTU value for Marvell GbE port #2
+
+config  MV_ETH_2_MACADDR
+        string "Giga port #2 MAC address"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2)
+        default "00:00:00:00:00:82"
+        ---help---
+        Default MAC address for Marvell GbE port #2
+
+config  MV_ETH_3_MTU
+        int "Giga port #3 MTU value"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2) && (MV_ETH_PORTS_NUM != 3)
+        default 1500
+        ---help---
+        Default MTU value for Marvell GbE port #3
+
+config  MV_ETH_3_MACADDR
+        string "Giga port #3 MAC address"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2) && (MV_ETH_PORTS_NUM != 3)
+        default "00:00:00:00:00:83"
+        ---help---
+        Default MAC address for Marvell GbE port #3
+
+endmenu
+
+menu "Rx/Tx Queue configuration"
+
+config  MV_ETH_RXQ
+        int "Number of RX queues"
+        default 1
+        ---help---
+          Multiple RX queue support.
+
+config  MV_ETH_TXQ
+        int "Number of TX queues"
+        default 1
+        ---help---
+          Multiple TX queue support.
+
+config MV_ETH_RXQ_DESC
+	int "Number of Rx descriptors"
+	depends on (MV_ETH_PORTS_NUM != 0)
+	default 128
+        ---help---
+	The number of Rx descriptors in each Rx queue.
+
+config MV_ETH_RXQ_DEF
+        int "Default RXQ to recieve packets"
+        default 0
+        ---help---
+
+config MV_ETH_TXQ_DESC
+	int "Number of Tx descriptors"
+	depends on (MV_ETH_PORTS_NUM != 0)
+	default 532
+        ---help---
+	The number of Tx descriptors in each Tx queue.
+
+config MV_ETH_TXQ_DEF
+        int "Default TXQ to send local generated packets"
+        default 0
+        ---help---
+
+endmenu
+
+menu "IP/TCP/UDP Offloading"
+
+config  MV_ETH_TX_CSUM_OFFLOAD
+        bool "L3/L4 TX checksum offload support for Marvell network interface"
+        default y
+        ---help---
+	Marvell network driver compiled with TCP/UDP over IPv4/IPv6 TX checksum offload support.
+
+config MV_ETH_TX_CSUM_OFFLOAD_DEF
+	depends on MV_ETH_TX_CSUM_OFFLOAD
+        bool "Default value for L3/L4 TX checksum offload: enable/disable"
+        default y
+        ---help---
+	Can be changed in run-time using ethtool
+
+config  MV_ETH_RX_CSUM_OFFLOAD
+        bool "L3/L4 RX checksum offload support for Marvell network interface"
+        default y
+        ---help---
+        Marvell network driver compiled with TCP/UDP over IPv4/IPv6 RX checksum offload support.
+
+config MV_ETH_RX_CSUM_OFFLOAD_DEF
+	depends on MV_ETH_RX_CSUM_OFFLOAD
+        bool "Default value for L3/L4 RX checksum offload: enable/disable"
+        default y
+        ---help---
+	Can be changed in run-time using ethtool
+
+config  MV_ETH_GRO
+        bool "GRO Support for Marvell network interface"
+	default y
+        ---help---
+        Marvell network driver compiled with GRO (Generic Receive Offload) support.
+
+config  MV_ETH_GRO_DEF
+	depends on MV_ETH_GRO
+        bool "Default value for GRO feature: enable/disable"
+	default n
+        ---help---
+        Can be changed in run-time using ethtool
+
+config  MV_ETH_TSO
+        bool "TSO Support for Marvell network interface"
+	default y
+        ---help---
+        Marvell network driver compiled with TSO (TCP Segmentation Offload) support.
+
+config  MV_ETH_TSO_DEF
+	depends on MV_ETH_TSO
+        bool "Default value for TSO feature: enable/disable"
+	default n
+        ---help---
+	Can be changed in run-time using ethtool
+
+endmenu
+
+menu "Control and Statistics"
+
+config  MV_ETH_DEBUG_CODE
+	bool "Add run-time debug code"
+	default n
+	---help---
+	Enable run-time enable/disable enter debug code blocks
+
+config  MV_ETH_STAT_ERR
+        bool "Collect error statistics"
+        default y
+	---help---
+	Marvell network interface driver collect minimal number of statistics.
+	Only for error conditions. Can be displayed using mv_eth_tool.
+
+config  MV_ETH_STAT_INF
+        bool "Collect event statistics"
+        default y
+        ---help---
+	Marvell network interface driver collect event statistics.
+	Provide more information about driver functionality and almost doesn't
+	effect performance. Can be displayed using mv_eth_tool.
+
+config  MV_ETH_STAT_DBG
+        bool "Collect debug statistics"
+        default n
+        ---help---
+	Marvell network interface driver collect a lot of statistics.
+	Used for Debug mode. Decrease performance. Can be displayed using mv_eth_tool.
+
+config  MV_ETH_STAT_DIST
+        bool "Collect debug distribution statistics"
+        default n
+        ---help---
+        Marvell network interface driver collect a lot of statistics.
+        Used for Debug mode. Decrease performance. Can be displayed using mv_eth_tool.
+
+config  MV_LINUX_COUNTERS_DISABLE
+	bool "Disable collection of SNMP statistics and Netfilter Contract statistics"
+	default n
+	---help---
+	Disable collection of SNMP statistics and Netfilter Contract statistics to improve performance.
+
+config  MV_ETH_TOOL
+	bool "Support ethtool controls"
+	default y
+	---help---
+	Support kernel's SIOCETHTOOL for ethtool utility
+endmenu
+
+menu "Advanced Features"
+
+config  NET_SKB_HEADROOM
+        int "SKB headroom size"
+        default 64
+        ---help---
+          Customize SKB headroom size. Must be power of 2.
+
+config NET_SKB_RECYCLE
+        bool "Skb recycle"
+        default y
+        ---help---
+          Work-in-progress and experimental.
+
+          This option enables skb's to be returned via a callback at kfree to
+          the allocator to make a fastpath for very skb consuming network
+          applications.
+
+config NET_SKB_RECYCLE_DEF
+        depends on NET_SKB_RECYCLE
+        int "Default value for SKB recycle:  0 - disable, 1 - enable"
+        default 1
+        ---help---
+
+config  MV_ETH_TX_DONE_TIMER_PERIOD
+        int "Periodical Tx Done timer period"
+        default 10
+        ---help---
+          Periodical timer period for Tx Done operation in [msec].
+
+config  MV_ETH_CLEANUP_TIMER_PERIOD
+        int "Periodical Cleanup timer period"
+        default 10
+        ---help---
+          Periodical timer period for cleanup operation in [msec].
+
+config  MV_ETH_TXDONE_ISR
+	bool "Use interrupt to process TX_DONE event"
+	default n
+	---help---
+	When chosen TX_DONE event will be process in interrupt mode
+	When unchosen TX_DONE event will be processed in polling mode
+
+config  MV_ETH_TXDONE_COAL_PKTS
+	int "Threshold for TX_DONE event trigger"
+	default 16
+	---help---
+	Number of packets will be sent before TX_DONE event will be triggered
+	by interrupt or polling.
+
+config  MV_ETH_RX_COAL_PKTS
+        int "Threshold [number of packets] for RX interrupt"
+        default 32
+        ---help---
+        Number of packets will be received before RX interrupt will be generated by HW.
+
+config  MV_ETH_RX_COAL_USEC
+        int "Threshold [usec] for RX interrupt"
+        default 100
+        ---help---
+        Time delay in usec before RX interrupt will be generated by HW if number of
+	received packets larger than 0 but smaller than MV_ETH_RX_COAL_PKTS
+
+config  MV_ETH_RX_DESC_PREFETCH
+	bool "Enable RX descriptor prefetch"
+	default n
+	---help---
+	Use pld instruction to prefetch one RX descriptor ahead
+
+config  MV_ETH_RX_PKT_PREFETCH
+        bool "Enable RX packet prefetch"
+        default n
+        ---help---
+        Use pld instruction to prefetch first two cache lines of received packet data
+
+config MV_ETH_RX_SPECIAL
+	depends on MV_ETH_PNC
+        bool "Enable special RX processing"
+        default n
+        ---help---
+        Enable special RX processing for packets with RI_RX_SEPCIAL PNC result info bit set
+
+config MV_ETH_TX_SPECIAL
+	bool "Enable special TX processing"
+ 	default n
+	---help---
+	Enable special TX processing for packets with signal header (SH)
+
+config MV_ETH_L2FW
+	bool "L2 Forwarding support"
+	default n
+	---help---
+	Enable L2 Forwarding support for received packets.
+	Three modes are supported: Send packet without change, Swap MAC DA<->SA,
+	Copy the whole packet and swap MAC
+
+config MV_ETH_L2SEC
+	bool "L2 Forwarding IPSec support"
+	depends on MV_ETH_L2FW
+	default n
+	---help---
+	Handle encrypted packets with CESA.
+
+config MV_ETH_L2FW_DEBUG
+	depends on MV_ETH_L2FW
+	bool "Add run-time L2FW debug code"
+	default n
+	---help---
+	Enable L2FW run-time enable/disable enter debug code blocks
+
+config MV_ETH_RX_POLL_WEIGHT
+	int "poll weight for the RX poll() function"
+	default 64
+	range 1 255
+	---help---
+	poll weight for the RX poll() function; must be less or equal to 255
+
+config MV_ETH_EXTRA_BUF_SIZE
+	int "Extra buffer size in bytes"
+	default 120
+	range 120 16384
+	---help---
+	Size of buffers allocated for extra pool and used in special cases like TSO,
+	fragmentattion and others
+
+config MV_ETH_EXTRA_BUF_NUM
+        int "Number of extra buffers allocated for each port"
+        default MV_ETH_TXQ_DESC
+	---help---
+	Number of extra buffers allocated for each port
+endmenu
+
+menu "NFP support"
+
+config  MV_ETH_NFP
+        tristate "Use Network Fast Processing (NFP)"
+	default n
+        ---help---
+        Choosing this option will enable Network Fast Processing.
+
+config MV_ETH_NFP_DEF
+        depends on MV_ETH_NFP
+        int "Default value for NFP state:  0 - OFF, 1 - ON"
+        default 0
+	range 0 1
+        ---help---
+
+config MV_ETH_NFP_MODE_DEF
+        depends on MV_ETH_NFP
+        int "Default value for NFP mode:  1 - 2 tuple mode, 2 - 5 tuple mode"
+        default 1
+	range 1 2
+        ---help---
+
+config  MV_ETH_NFP_EXT
+        bool "Support NFP for External (non GBE) network interfaces"
+        depends on MV_ETH_NFP
+        default n
+         ---help---
+        Choosing this option will enable NFP for non-GBE network interfaces.
+
+config  MV_ETH_NFP_EXT_NUM
+        int "Maximum number of External (non-Gbe) interfaces"
+        depends on MV_ETH_NFP_EXT
+        default 1
+	range 1 4
+         ---help---
+
+config MV_ETH_NFP_BRIDGE
+        bool "Support NFP Bridging"
+        default y
+        depends on MV_ETH_NFP
+        ---help---
+        Choosing this option will enable NFP bridging support.
+
+choice
+        prompt "NFP Bridging Mode"
+        depends on MV_ETH_NFP_BRIDGE
+        default MV_ETH_NFP_FDB_MODE
+
+config	MV_ETH_NFP_FDB_MODE
+	bool "NFP FDB"
+	depends on MV_ETH_NFP_BRIDGE
+	---help---
+	  enable NFP FDB mode
+
+config  MV_ETH_NFP_BRIDGE_MODE
+	bool "NFP Bridge"
+	depends on MV_ETH_NFP_BRIDGE
+	---help---
+	  enable NFP Bridge Mode
+
+endchoice
+
+config	MV_ETH_NFP_FDB_LEARN
+	depends on MV_ETH_NFP_BRIDGE && MV_ETH_NFP_FDB_MODE && BRIDGE && MV_ETH_NFP!=m
+	bool "Support NFP FDB Dynamic Learning"
+	default y
+	---help---
+	  enable NFP bridging dynamic learning via NFP hooks
+
+config MV_ETH_NFP_FDB_LEARN_DEF
+        depends on MV_ETH_NFP_FDB_LEARN
+        int "Default value for NFP FDB Dynamic Learning:  0 - disable, 1 - enable"
+        default 1
+	range 0 1
+        ---help---
+
+config MV_ETH_NFP_VLAN
+        bool "Support NFP VLANs processing"
+        default y
+        depends on MV_ETH_NFP
+        ---help---
+        Choosing this option will enable NFP VLANs support.
+
+config MV_ETH_NFP_VLAN_LEARN
+        depends on MV_ETH_NFP_VLAN && VLAN_8021Q && MV_ETH_NFP!=m
+        bool "Support NFP VLAN Dynamic Learning"
+        default y
+        ---help---
+        Choosing this option will enable NFP VLAN dynamic learning via NFP hooks
+	in Linux Network stack.
+
+config MV_ETH_NFP_VLAN_LEARN_DEF
+        depends on MV_ETH_NFP_VLAN_LEARN
+        int "Default value for NFP VLAN Dynamic Learning:  0 - disable, 1 - enable"
+        default 1
+	range 0 1
+        ---help---
+
+config MV_ETH_NFP_FIB
+        bool "Support NFP Routing"
+	default y
+        depends on MV_ETH_NFP
+        ---help---
+        Choosing this option will enable NFP routing support.
+
+config MV_ETH_NFP_FIB_LEARN
+        depends on MV_ETH_NFP_FIB && MV_ETH_NFP!=m
+        bool "Support NFP Routing Dynamic Learning"
+        default y
+        ---help---
+        Choosing this option will enable NFP Routing dynamic learning via NFP hooks
+	in Linux Network stack.
+
+config MV_ETH_NFP_FIB_LEARN_DEF
+        depends on MV_ETH_NFP_FIB_LEARN
+        int "Default value for NFP Routing Dynamic Learning:  0 - disable, 1 - enable"
+        default 1
+	range 0 1
+        ---help---
+
+config MV_ETH_NFP_CT
+        bool "Support NFP 5 Tuple Rules"
+        depends on MV_ETH_NFP_FIB
+	default y
+        ---help---
+        Choosing this option will enable NFP 5 Tuple Rules support.
+
+config MV_ETH_NFP_CT_LEARN
+        depends on MV_ETH_NFP_CT && NF_CONNTRACK && MV_ETH_NFP!=m
+        bool "Support NFP 5 Tuple Dynamic Learning"
+        default y
+        ---help---
+        Choosing this option will enable NFP 5 Tuple dynamic learning via NFP hooks
+	in Linux Network stack.
+
+config MV_ETH_NFP_CT_LEARN_DEF
+        depends on MV_ETH_NFP_CT_LEARN
+        int "Default value for NFP 5 Tuple Dynamic Learning:  0 - disable, 1 - enable"
+        default 1
+	range 0 1
+        ---help---
+
+config MV_ETH_NFP_NAT
+        bool "Support NFP NAT"
+        depends on MV_ETH_NFP_CT
+	default y
+        ---help---
+        Choosing this option will enable NFP NAT support.
+
+config MV_ETH_NFP_LIMIT
+        bool "Support NFP Ingress Rate Limiting"
+        depends on MV_ETH_NFP_CT
+	default n
+        ---help---
+        Choosing this option will enable NFP rate limitation support based on 5 tuple rule.
+
+config  MV_ETH_NFP_CLASSIFY
+	bool "Support NFP Classification rules"
+	depends on MV_ETH_NFP_CT || MV_ETH_NFP_BRIDGE
+	default y
+	---help---
+	Choosing this option will enable NFP classification rules (DSCP and VLAN modification and Tx queue selection)
+
+config  MV_ETH_NFP_PPP
+	bool "Support NFP PPPoE"
+	depends on MV_ETH_NFP_FIB && MV_ETH_PNC
+	default n
+	 ---help---
+	Choosing this option will enable NFP PPPoE protocol.
+
+config MV_ETH_NFP_PPP_LEARN
+        depends on MV_ETH_NFP_PPP && PPPOE && MV_ETH_NFP!=m
+        bool "Support NFP PPPoE Dynamic Learning"
+        default y
+        ---help---
+        Choosing this option will enable NFP PPPoE dynamic learning via NFP hooks
+	in Linux Network stack.
+
+config MV_ETH_NFP_PPP_LEARN_DEF
+        depends on MV_ETH_NFP_PPP_LEARN
+        int "Default value for NFP PPPoE Dynamic Learning:  0 - disable, 1 - enable"
+        default 1
+	range 0 1
+        ---help---
+
+config  MV_ETH_NFP_STATS
+        bool "Collect NFP Statistics"
+	depends on MV_ETH_NFP
+        default n
+        ---help---
+        Collect NFP statistics. Can be displayed using mv_eth_tool.
+
+config  MV_ETH_NFP_DEBUG
+	bool "Add NFP debug code"
+	depends on MV_ETH_NFP
+	default n
+        ---help---
+	Add NFP sanity check code
+
+endmenu
+
+menu "NAPI GROUPS"
+
+config  MV_ETH_NAPI_GROUPS
+        int "Number of NAPI instances which can be used per port"
+		range 1 NR_CPUS if SMP
+		range 1 1 if !SMP
+        default 1
+        ---help---
+	Different RXQs and TXQs can be processed by different CPU using different NAPI instances
+
+menu "Group 0"
+
+config MV_ETH_GROUP0_CPU
+	hex "CPU affinity for group0"
+    range 0x0 0xf if (NR_CPUS=4)
+    range 0x0 0x7 if (NR_CPUS=3)
+    range 0x0 0x3 if (NR_CPUS=2)
+	range 0x0 0x1 if (NR_CPUS=1)
+	default 0xf
+config MV_ETH_GROUP0_RXQ
+	hex "RXQ affinity for group0"
+	range 0x0 0xff
+	default 0xff
+endmenu
+
+menu "Group 1"
+	depends on (MV_ETH_NAPI_GROUPS !=1)
+
+config MV_ETH_GROUP1_CPU
+	hex "CPU affinity for group1"
+    range 0x0 0xf if (NR_CPUS=4)
+    range 0x0 0x7 if (NR_CPUS=3)
+    range 0x0 0x3 if (NR_CPUS=2)
+	range 0x0 0x3 if (NR_CPUS=1)
+	default 0x0
+config MV_ETH_GROUP1_RXQ
+	hex "RXQ affinity for group1"
+	range 0x0 0xff
+	default 0x0
+endmenu
+
+menu "Group 2"
+	depends on (MV_ETH_NAPI_GROUPS !=1) && (MV_ETH_NAPI_GROUPS !=2)
+
+config MV_ETH_GROUP2_CPU
+	hex "CPU affinity for group2"
+    range 0x0 0xf if (NR_CPUS=4)
+    range 0x0 0x7 if (NR_CPUS=3)
+    range 0x0 0x3 if (NR_CPUS=2)
+	range 0x0 0x3 if (NR_CPUS=1)
+	default 0x0
+config MV_ETH_GROUP2_RXQ
+	hex "RXQ affinity for group2"
+	range 0x0 0xff
+	default 0x0
+endmenu
+menu "Group 3"
+	depends on (MV_ETH_NAPI_GROUPS !=1) && (MV_ETH_NAPI_GROUPS !=2) && (MV_ETH_NAPI_GROUPS !=3)
+config MV_ETH_GROUP3_CPU
+	hex "CPU affinity for group3"
+    range 0x0 0xf if (NR_CPUS=4)
+    range 0x0 0x7 if (NR_CPUS=3)
+    range 0x0 0x3 if (NR_CPUS=2)
+	range 0x0 0x3 if (NR_CPUS=1)
+	default 0x0
+config MV_ETH_GROUP3_RXQ
+	hex "RXQ affinity for group3"
+	range 0x0 0xff
+	default 0x0
+endmenu
+endmenu
+
+menu "PON support for Network driver"
+
+config MV_PON
+        bool "PON support"
+        depends on MV_ETH_NETA && MV_INCLUDE_PON
+        ---help---
+        Choose this option to support PON port in Marvell network driver
+
+config MV_PON_TXP_DEF
+        int "Default T-CONT to send local generated packets"
+        depends on MV_PON
+        default 0
+        ---help---
+
+config MV_PON_TXQ_DEF
+        int "Default TXQ to send local generated packets"
+        depends on MV_PON
+        default 0
+        ---help---
+
+endmenu
+
+menu "Switch support"
+
+config MV_ETH_SWITCH
+        bool "Switch support"
+	depends on MV_INCLUDE_SWITCH
+        ---help---
+	Choose this option to support Gigabit Ethernet Controller connected to
+        on-board QuarterDeck switch family
+
+config  MV_ETH_SWITCH_NETDEV_NUM
+	int "Maximum number of subnets on switch ports"
+	depends on MV_ETH_SWITCH
+	default 4
+	---help---
+	Valid range range from 1 to BOARD_ETH_SWITCH_PORT_NUM
+
+config  MV_ETH_SWITCH_NETCONFIG_0
+	string "Switch network configuration for GbE port 0"
+	depends on MV_ETH_SWITCH
+	default "3,(00:11:66:11:66:11,0)(00:22:77:22:77:22,1:2:3:4),mtu=1500"
+	---help---
+	 Set the network configuration when giga port connected to switch.
+         For each interface, define the interface
+	 name, MAC address and participating ports.
+
+config  MV_ETH_SWITCH_NETCONFIG_1
+	string "Switch network configuration for GbE port 1"
+	depends on MV_ETH_SWITCH
+	default "0"
+	---help---
+	 Set the network configuration when giga port connected to switch.
+         For each interface, define the interface
+	 name, MAC address and participating ports.
+
+config  MV_ETH_SWITCH_LINK
+	bool "Link status change indications"
+	depends on MV_ETH_SWITCH
+	default y
+	---help---
+	  Support Phy link status change indications.
+endmenu
+
+menu "ERRATA / WA"
+
+config MV_ETH_ERRATA_SMI_ACCESS
+	bool "use SMI port 1 instead of SMI port 0"
+	depends on ARMADA_XP_REV_Z1
+	default y
+	---help---
+	Using SMI port 1 instead of SMI port 0 prevents the
+	link up/link down on a different port than the port on which
+	an action such as changing speed or starting autonegotiation is done.
+	(NetA BTS #313, DSMP LSP #42, ARMADA XP Z1).
+
+config MV_ETH_REDUCE_BURST_SIZE_WA
+	bool "Limit burst size of RX and TX transactions to 16B in IOCC mode"
+	depends on AURORA_IO_CACHE_COHERENCY
+	default y
+	---help---
+	To avoid CPU make invalidate which might cause hang, force partial
+	read/write by limiting the burst size to 16B since it is less than the
+	size of a cache line.
+
+config MV_ETH_BE_WA
+	bool "WA for RX and TX descriptors swap in HW issue"
+	depends on CPU_ENDIAN_BE32
+	default n
+	---help---
+	If set swap of RX and TX descriptors in BE mode will be done by driver
+
+endmenu
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/bm/bm_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/bm/bm_sysfs.c
new file mode 100755
index 0000000..7698e27
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/bm/bm_sysfs.c
@@ -0,0 +1,154 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "gbe/mvNeta.h"
+#include "net_dev/mv_netdev.h"
+#include "bm/mvBm.h"
+
+static ssize_t bm_help(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "cat                regs         - show BM registers\n");
+	off += sprintf(buf+off, "cat                stat         - show BM status\n");
+	off += sprintf(buf+off, "cat                config       - show compile-time BM configuration\n");
+	off += sprintf(buf+off, "echo p v           > dump       - dump BM pool <p>. v=0-brief, v=1-full\n");
+	off += sprintf(buf+off, "echo p s           > size       - set packet size <s> to BM pool <p>\n");
+
+	return off;
+}
+
+static ssize_t bm_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	int          err = 0;
+	const char   *name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "help"))
+		return bm_help(buf);
+	else if (!strcmp(name, "regs"))
+		mvBmRegs();
+	else if (!strcmp(name, "stat"))
+		mvBmStatus();
+	else if (!strcmp(name, "config"))
+		mv_eth_bm_config_print();
+	else {
+		err = 1;
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	}
+	return err;
+}
+static ssize_t bm_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char    *name = attr->attr.name;
+	unsigned int  err = 0, pool = 0, val = 0;
+	unsigned long flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%d %d", &pool, &val);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "dump")) {
+		mvBmPoolDump(pool, val);
+	} else if (!strcmp(name, "size")) {
+		err = mv_eth_ctrl_pool_size_set(pool, val);
+	} else {
+		err = 1;
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	}
+	local_irq_restore(flags);
+
+	return err ? -EINVAL : len;
+}
+
+static DEVICE_ATTR(size,   S_IWUSR, NULL, bm_store);
+static DEVICE_ATTR(dump,   S_IWUSR, NULL, bm_store);
+static DEVICE_ATTR(config, S_IRUSR, bm_show, NULL);
+static DEVICE_ATTR(stat,   S_IRUSR, bm_show, NULL);
+static DEVICE_ATTR(regs,   S_IRUSR, bm_show, NULL);
+static DEVICE_ATTR(help,   S_IRUSR, bm_show, NULL);
+
+static struct attribute *bm_attrs[] = {
+	&dev_attr_size.attr,
+	&dev_attr_dump.attr,
+	&dev_attr_config.attr,
+	&dev_attr_regs.attr,
+	&dev_attr_stat.attr,
+	&dev_attr_help.attr,
+	NULL
+};
+
+static struct attribute_group bm_group = {
+	.name = "bm",
+	.attrs = bm_attrs,
+};
+
+int __devinit bm_sysfs_init(void)
+{
+		int err;
+		struct device *pd;
+
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+		if (!pd) {
+			platform_device_register_simple("neta", -1, NULL, 0);
+			pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+		}
+
+		if (!pd) {
+			printk(KERN_ERR "%s: cannot find neta device\n", __func__);
+			pd = &platform_bus;
+		}
+
+		err = sysfs_create_group(&pd->kobj, &bm_group);
+		if (err) {
+			printk(KERN_INFO "sysfs group failed %d\n", err);
+			goto out;
+		}
+out:
+		return err;
+}
+
+module_init(bm_sysfs_init);
+
+MODULE_AUTHOR("Dmitri Epshtein");
+MODULE_DESCRIPTION("BM for Marvell NetA");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/bm/mv_eth_bm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/bm/mv_eth_bm.c
new file mode 100755
index 0000000..b49862b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/bm/mv_eth_bm.c
@@ -0,0 +1,196 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "gbe/mvNeta.h"
+#include "bm/mvBm.h"
+
+#include "net_dev/mv_netdev.h"
+
+typedef struct {
+	int             pool_pkt_size[MV_BM_POOLS];
+	MV_BM_CONFIG	port_config[CONFIG_MV_ETH_PORTS_NUM];
+} MV_ETH_BM_CONFIG;
+
+static MV_ETH_BM_CONFIG mv_eth_bm_config;
+
+int mv_eth_bm_config_pkt_size_get(int pool)
+{
+	if (mvNetaMaxCheck(pool, MV_BM_POOLS))
+		return -EINVAL;
+
+	return mv_eth_bm_config.pool_pkt_size[pool];
+}
+
+int mv_eth_bm_config_pkt_size_set(int pool, int pkt_size)
+{
+	if (mvNetaMaxCheck(pool, MV_BM_POOLS))
+		return -EINVAL;
+
+	mv_eth_bm_config.pool_pkt_size[pool] = pkt_size;
+	return 0;
+}
+
+int mv_eth_bm_config_long_pool_get(int port)
+{
+	if (mvNetaPortCheck(port))
+		return -EINVAL;
+
+	return mv_eth_bm_config.port_config[port].longPool;
+}
+
+int mv_eth_bm_config_long_buf_num_get(int port)
+{
+	if (mvNetaPortCheck(port))
+		return -EINVAL;
+
+	return mv_eth_bm_config.port_config[port].longBufNum;
+}
+
+int mv_eth_bm_config_short_pool_get(int port)
+{
+	if (mvNetaPortCheck(port))
+		return -EINVAL;
+
+	return mv_eth_bm_config.port_config[port].shortPool;
+}
+
+int mv_eth_bm_config_short_buf_num_get(int port)
+{
+	if (mvNetaPortCheck(port))
+		return -EINVAL;
+
+	return mv_eth_bm_config.port_config[port].shortBufNum;
+}
+
+int mv_eth_bm_config_buf_num_set(int port, int longBufNum, int shortBufNum)
+{
+	if (mvNetaPortCheck(port))
+		return -EINVAL;
+
+	mv_eth_bm_config.port_config[port].shortBufNum = shortBufNum;
+	mv_eth_bm_config.port_config[port].longBufNum = longBufNum;
+	return 0;
+}
+
+/* Once time call: init configuration structure accordingly with compile time parameters */
+MV_STATUS mv_eth_bm_config_get(void)
+{
+	MV_BM_CONFIG *bmConfig;
+	int           port;
+
+	mv_eth_bm_config.pool_pkt_size[0] = CONFIG_MV_ETH_BM_0_PKT_SIZE;
+	mv_eth_bm_config.pool_pkt_size[1] = CONFIG_MV_ETH_BM_1_PKT_SIZE;
+	mv_eth_bm_config.pool_pkt_size[2] = CONFIG_MV_ETH_BM_2_PKT_SIZE;
+	mv_eth_bm_config.pool_pkt_size[3] = CONFIG_MV_ETH_BM_3_PKT_SIZE;
+
+#ifdef CONFIG_MV_ETH_BM_PORT_0
+	port = 0;
+	bmConfig = &mv_eth_bm_config.port_config[port];
+	memset(bmConfig, 0, sizeof(MV_BM_CONFIG));
+	bmConfig->valid = 1;
+	bmConfig->longPool = CONFIG_MV_ETH_BM_PORT_0_LONG_POOL;
+	bmConfig->shortPool = CONFIG_MV_ETH_BM_PORT_0_SHORT_POOL;
+	bmConfig->longBufNum = CONFIG_MV_ETH_BM_PORT_0_LONG_BUF_NUM;
+
+#if (CONFIG_MV_ETH_BM_PORT_0_SHORT_POOL != CONFIG_MV_ETH_BM_PORT_0_LONG_POOL)
+	bmConfig->shortBufNum = CONFIG_MV_ETH_BM_PORT_0_SHORT_BUF_NUM;
+#endif /* CONFIG_MV_ETH_BM_PORT_0_SHORT_POOL != CONFIG_MV_ETH_BM_PORT_0_LONG_POOL */
+#endif /* CONFIG_MV_ETH_BM_PORT_0 */
+
+#ifdef CONFIG_MV_ETH_BM_PORT_1
+	port = 1;
+	bmConfig = &mv_eth_bm_config.port_config[port];
+	memset(bmConfig, 0, sizeof(MV_BM_CONFIG));
+	bmConfig->valid = 1;
+	bmConfig->longPool = CONFIG_MV_ETH_BM_PORT_1_LONG_POOL;
+	bmConfig->shortPool = CONFIG_MV_ETH_BM_PORT_1_SHORT_POOL;
+	bmConfig->longBufNum = CONFIG_MV_ETH_BM_PORT_1_LONG_BUF_NUM;
+
+#if (CONFIG_MV_ETH_BM_PORT_1_SHORT_POOL != CONFIG_MV_ETH_BM_PORT_1_LONG_POOL)
+	bmConfig->shortBufNum = CONFIG_MV_ETH_BM_PORT_1_SHORT_BUF_NUM;
+#endif /* CONFIG_MV_ETH_BM_PORT_1_SHORT_POOL != CONFIG_MV_ETH_BM_PORT_1_LONG_POOL */
+#endif /* CONFIG_MV_ETH_BM_PORT_1 */
+
+#ifdef CONFIG_MV_ETH_BM_PORT_2
+	port = 2;
+	bmConfig = &mv_eth_bm_config.port_config[port];
+	memset(bmConfig, 0, sizeof(MV_BM_CONFIG));
+	bmConfig->valid = 1;
+	bmConfig->longPool = CONFIG_MV_ETH_BM_PORT_2_LONG_POOL;
+	bmConfig->shortPool = CONFIG_MV_ETH_BM_PORT_2_SHORT_POOL;
+	bmConfig->longBufNum = CONFIG_MV_ETH_BM_PORT_2_LONG_BUF_NUM;
+
+#if (CONFIG_MV_ETH_BM_PORT_2_SHORT_POOL != CONFIG_MV_ETH_BM_PORT_2_LONG_POOL)
+	bmConfig->shortBufNum = CONFIG_MV_ETH_BM_PORT_2_SHORT_BUF_NUM;
+#endif /* CONFIG_MV_ETH_BM_PORT_2_SHORT_POOL != CONFIG_MV_ETH_BM_PORT_2_LONG_POOL */
+#endif /* CONFIG_MV_ETH_BM_PORT_2 */
+
+	#ifdef CONFIG_MV_ETH_BM_PORT_3
+	port = 3;
+	bmConfig = &mv_eth_bm_config.port_config[port];
+	memset(bmConfig, 0, sizeof(MV_BM_CONFIG));
+	bmConfig->valid = 1;
+	bmConfig->longPool = CONFIG_MV_ETH_BM_PORT_3_LONG_POOL;
+	bmConfig->shortPool = CONFIG_MV_ETH_BM_PORT_3_SHORT_POOL;
+	bmConfig->longBufNum = CONFIG_MV_ETH_BM_PORT_3_LONG_BUF_NUM;
+
+#if (CONFIG_MV_ETH_BM_PORT_3_SHORT_POOL != CONFIG_MV_ETH_BM_PORT_3_LONG_POOL)
+	bmConfig->shortBufNum = CONFIG_MV_ETH_BM_PORT_3_SHORT_BUF_NUM;
+#endif /* CONFIG_MV_ETH_BM_PORT_3_SHORT_POOL != CONFIG_MV_ETH_BM_PORT_3_LONG_POOL */
+#endif /* CONFIG_MV_ETH_BM_PORT_3 */
+
+	return MV_OK;
+}
+
+void mv_eth_bm_config_print(void)
+{
+	int           i;
+	MV_BM_CONFIG *bmConfig;
+
+	mvOsPrintf("BM compile time configuration\n");
+	for (i = 0; i < MV_BM_POOLS; i++)
+		mvOsPrintf("pool %d: pkt_size = %d bytes\n", i, mv_eth_bm_config.pool_pkt_size[i]);
+
+	mvOsPrintf("\n");
+	mvOsPrintf("port:  longPool  shortPool  longBufNum  shortBufNum\n");
+	for (i = 0; i < CONFIG_MV_ETH_PORTS_NUM; i++) {
+		bmConfig = &mv_eth_bm_config.port_config[i];
+		if (bmConfig->valid)
+			mvOsPrintf("  %2d:   %4d       %4d        %4d         %4d\n",
+				i, bmConfig->longPool, bmConfig->shortPool,
+				bmConfig->longBufNum, bmConfig->shortBufNum);
+	}
+	mvOsPrintf("\n");
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/hwf/hwf_bm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/hwf/hwf_bm.c
new file mode 100755
index 0000000..5c20873
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/hwf/hwf_bm.c
@@ -0,0 +1,194 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "gbe/mvNeta.h"
+#include "bm/mvBm.h"
+
+#include "net_dev/mv_netdev.h"
+
+static MV_BM_POOL	hwfBmPool[MV_BM_POOLS];
+
+
+static int mv_eth_hwf_pool_add(MV_BM_POOL *pBmPool, int bufNum)
+{
+	int      i;
+	void     *pVirt;
+	MV_ULONG physAddr;
+
+	/* Check total number of buffers doesn't exceed capacity */
+	if ((bufNum < 0) ||
+		((bufNum + pBmPool->bufNum) > (pBmPool->capacity))) {
+
+		mvOsPrintf("%s: to many %d buffers for BM pool #%d: capacity=%d, buf_num=%d\n",
+			   __func__, bufNum, pBmPool->pool, pBmPool->capacity, pBmPool->bufNum);
+		return 0;
+	}
+	/* Allocate buffers for the pool */
+	for (i = 0; i < bufNum; i++) {
+
+		pVirt = mvOsIoCachedMalloc(NULL, pBmPool->bufSize, &physAddr, NULL);
+		if (pVirt == NULL) {
+			mvOsPrintf("%s: Warning! Not all buffers of %d bytes allocated\n",
+						__func__, pBmPool->bufSize);
+			break;
+		}
+		mvBmPoolPut(pBmPool->pool, (MV_ULONG) physAddr);
+	}
+	pBmPool->bufNum += i;
+
+	mvOsPrintf("BM pool #%d for HWF: bufSize=%4d - %4d of %4d buffers added\n",
+	       pBmPool->pool, pBmPool->bufSize, i, bufNum);
+
+	return i;
+}
+
+/*******************************************************************************
+ * mv_eth_hwf_bm_create - create BM pools used by the port for HWF only
+ *
+ * INPUT:
+ *       int        port	- port number
+ *
+ * RETURN:   MV_STATUS
+ *               MV_OK - Success, Others - Failure
+ *
+ *******************************************************************************/
+MV_STATUS mv_eth_hwf_bm_create(int port, int mtuPktSize)
+{
+	static bool		isFirst = true;
+	MV_BM_POOL		*pBmPool;
+	int				long_pool, short_pool;
+	int				long_buf_size, short_buf_size;
+
+	/* Check validity of the parameters */
+	if (mvNetaPortCheck(port))
+		return MV_FAIL;
+
+	/* For the first time - clean hwfBmPool array */
+	if (isFirst == true) {
+		memset(&hwfBmPool, 0, sizeof(hwfBmPool));
+		isFirst = false;
+	}
+
+	long_pool = mv_eth_bm_config_long_pool_get(port);
+	/* Check validity of the parameters */
+	if (mvNetaMaxCheck(long_pool,  MV_BM_POOLS))
+		return MV_FAIL;
+
+	/* For HWF Packet offset in the packet is 8 bytes */
+	long_buf_size = mv_eth_bm_config_pkt_size_get(long_pool);
+	if (long_buf_size == 0)
+		long_buf_size = mtuPktSize + 8;
+
+	/* Check validity of the parameters */
+	if (long_buf_size < (mtuPktSize + 8))
+		return MV_FAIL;
+
+	/* Create long pool */
+	pBmPool = &hwfBmPool[long_pool];
+	if (pBmPool->pVirt == NULL) {
+		/* Allocate new pool */
+		pBmPool->pVirt = mv_eth_bm_pool_create(long_pool, MV_BM_POOL_CAP_MAX, &pBmPool->physAddr);
+		if (pBmPool->pVirt == NULL) {
+			mvOsPrintf("%s: Can't allocate %d bytes for Long pool #%d of port #%d\n",
+					__func__, MV_BM_POOL_CAP_MAX * sizeof(MV_U32), long_pool, port);
+			return MV_OUT_OF_CPU_MEM;
+		}
+		pBmPool->pool = long_pool;
+		pBmPool->capacity = MV_BM_POOL_CAP_MAX;
+		pBmPool->bufSize = long_buf_size;
+	} else {
+		/* Share pool with other port - check buffer size */
+		if (long_buf_size > pBmPool->bufSize) {
+			/* The BM pool doesn't match the mtuPktSize */
+			mvOsPrintf("%s: longBufSize=%d is too match for the pool #%d (%d bytes)\n",
+						__func__, long_buf_size, pBmPool->pool, pBmPool->bufSize);
+			return MV_FAIL;
+		}
+	}
+	/* Set long pool buffer size */
+	mvNetaBmPoolBufSizeSet(port, long_pool, long_buf_size);
+	
+	mv_eth_hwf_pool_add(pBmPool, mv_eth_bm_config_long_buf_num_get(port));
+
+	/* Create short pool */
+	short_pool = mv_eth_bm_config_short_pool_get(port);
+	short_buf_size = mv_eth_bm_config_pkt_size_get(short_pool);
+	if (short_pool != long_pool) {
+		pBmPool = &hwfBmPool[short_pool];
+		if (pBmPool->pVirt == NULL) {
+			/* Allocate new pool */
+			pBmPool->pVirt = mv_eth_bm_pool_create(short_pool, MV_BM_POOL_CAP_MAX, &pBmPool->physAddr);
+			if (pBmPool->pVirt == NULL) {
+				mvOsPrintf("%s: Can't allocate %d bytes for Short pool #%d of port #%d\n",
+						__func__, MV_BM_POOL_CAP_MAX * sizeof(MV_U32), short_pool, port);
+				return MV_OUT_OF_CPU_MEM;
+			}
+			pBmPool->pool = short_pool;
+			pBmPool->capacity = MV_BM_POOL_CAP_MAX;
+			pBmPool->bufSize = short_buf_size;
+		} else {
+			/* Share pool with other port - check buffer size */
+			if (short_buf_size > pBmPool->bufSize) {
+				/* The BM pool doesn't match the mtuPktSize */
+				mvOsPrintf("%s: shortBufSize=%d is too match for the pool #%d (%d bytes)\n",
+							__func__, short_buf_size, pBmPool->pool, pBmPool->bufSize);
+				return MV_FAIL;
+			}
+		}
+		/* Set short pool buffer size */
+		mvNetaBmPoolBufSizeSet(port, short_pool, short_buf_size);		
+
+		/* Add buffers to short pool */
+		mv_eth_hwf_pool_add(pBmPool, mv_eth_bm_config_short_buf_num_get(port));
+	}
+	mvNetaHwfBmPoolsSet(port, short_pool, long_pool);
+	return MV_OK;
+}
+
+void mv_hwf_bm_dump(void)
+{
+	int          i;
+	MV_BM_POOL   *bmPool;
+
+	mvOsPrintf("HWF BM Pools configuration\n");
+	mvOsPrintf("pool:    capacity    bufSize    bufNum      virtPtr       physAddr\n");
+	for (i = 0; i < MV_BM_POOLS; i++) {
+		bmPool = &hwfBmPool[i];
+		if (bmPool->pVirt)
+			mvOsPrintf("  %2d:     %4d       %4d       %4d      %p      0x%08x\n",
+						bmPool->pool, bmPool->capacity, bmPool->bufSize, bmPool->bufNum,
+						bmPool->pVirt, (unsigned)bmPool->physAddr);
+	}
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/hwf/hwf_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/hwf/hwf_sysfs.c
new file mode 100755
index 0000000..a86bbe2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/hwf/hwf_sysfs.c
@@ -0,0 +1,167 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "gbe/mvNeta.h"
+#include "net_dev/mv_netdev.h"
+
+static ssize_t hwf_help(char *buf)
+{
+	int off = 0;
+
+	off += mvOsSPrintf(buf+off, "cat                      help    - print this help\n");
+#ifndef CONFIG_MV_ETH_BM_CPU
+	off += mvOsSPrintf(buf+off, "cat                      bm    - print HWF BM information\n");
+#endif
+	off += mvOsSPrintf(buf+off, "echo rxp p txp         > regs  - print HWF registers of port <p>\n");
+	off += mvOsSPrintf(buf+off, "echo rxp p txp         > cntrs - print HWF counters of port <p>\n");
+	off += mvOsSPrintf(buf+off, "echo rxp p txp txq en  > en    - enable HWF from <rxp> to specific <txq>\n");
+	off += mvOsSPrintf(buf+off, "echo rxp p txp txq a b > drop  - set HWF drop threshold <a> and Random bits <b>\n");
+
+	return off;
+}
+
+static ssize_t hwf_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	const char   *name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "help"))
+		return hwf_help(buf);
+#ifndef CONFIG_MV_ETH_BM_CPU
+	else if (!strcmp(name, "bm"))
+		mv_hwf_bm_dump();
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	return 0;
+}
+static ssize_t hwf_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char    *name = attr->attr.name;
+	unsigned int  err = 0, rxp = 0, p = 0, txp = 0, txq = 0, a = 0, b = 0;
+	unsigned long flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%d %d %d %d %d %d", &rxp, &p, &txp, &txq, &a, &b);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "regs")) {
+		mvNetaHwfRxpRegs(rxp);
+		mvNetaHwfTxpRegs(rxp, p, txp);
+	} else if (!strcmp(name, "cntrs")) {
+		mvNetaHwfTxpCntrs(rxp, p, txp);
+	} else if (!strcmp(name, "en")) {
+		if (a)        {
+			/* Set txp/txq ownership to HWF */
+			if (mv_eth_ctrl_txq_hwf_own(p, txp, txq, rxp)) {
+				printk(KERN_ERR "%s failed: p=%d, txp=%d, txq=%d\n",
+					__func__, p, txp, txq);
+				return -EINVAL;
+			}
+		} else
+			mv_eth_ctrl_txq_hwf_own(p, txp, txq, -1);
+
+		mvNetaHwfTxqEnable(rxp, p, txp, txq, a);
+	} else if (!strcmp(name, "drop")) {
+		mvNetaHwfTxqDropSet(rxp, p, txp, txq, a, b);
+	} else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: <%s>, error %d\n", __func__, attr->attr.name, err);
+
+	return err ? -EINVAL : len;
+}
+
+static DEVICE_ATTR(regs,  S_IWUSR, hwf_show, hwf_store);
+static DEVICE_ATTR(cntrs, S_IWUSR, hwf_show, hwf_store);
+static DEVICE_ATTR(en,    S_IWUSR, hwf_show, hwf_store);
+static DEVICE_ATTR(drop,  S_IWUSR, hwf_show, hwf_store);
+static DEVICE_ATTR(bm,    S_IRUSR, hwf_show, hwf_store);
+static DEVICE_ATTR(help,  S_IRUSR, hwf_show, hwf_store);
+
+static struct attribute *hwf_attrs[] = {
+	&dev_attr_regs.attr,
+	&dev_attr_cntrs.attr,
+	&dev_attr_en.attr,
+	&dev_attr_drop.attr,
+	&dev_attr_bm.attr,
+	&dev_attr_help.attr,
+	NULL
+};
+
+static struct attribute_group hwf_group = {
+	.name = "hwf",
+	.attrs = hwf_attrs,
+};
+
+int __devinit hwf_sysfs_init(void)
+{
+		int err;
+		struct device *pd;
+
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+		if (!pd) {
+			platform_device_register_simple("neta", -1, NULL, 0);
+			pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+		}
+
+		if (!pd) {
+			printk(KERN_ERR "%s: cannot find neta device\n", __func__);
+			pd = &platform_bus;
+		}
+
+		err = sysfs_create_group(&pd->kobj, &hwf_group);
+		if (err) {
+			printk(KERN_INFO "sysfs group failed %d\n", err);
+			goto out;
+		}
+out:
+		return err;
+}
+
+module_init(hwf_sysfs_init);
+
+MODULE_AUTHOR("Dmitri Epshtein");
+MODULE_DESCRIPTION("HWF for Marvell NetA MV65xxx");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/l2fw_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/l2fw_sysfs.c
new file mode 100755
index 0000000..4e8c2b7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/l2fw_sysfs.c
@@ -0,0 +1,216 @@
+/* l2fw_sysfs.c */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "mvTypes.h"
+#include "mv_eth_l2fw.h"
+#include "linux/inet.h"
+
+#ifdef CONFIG_MV_ETH_L2SEC
+extern int l2fw_set_cesa_chan(int port, int cesaChan);
+#endif
+
+static ssize_t l2fw_help(char *buf)
+{
+	int off = 0;
+	off += sprintf(buf+off, "help\n");
+	off += sprintf(buf+off, "echo mode rxp txp > l2fw - set l2f <rxp>->");
+	off += sprintf(buf+off, "<txp><mode> 0-dis,1-as_is,2-swap,3-copy\n");
+	off += sprintf(buf+off, "echo threshold > l2fw_xor: set threshold\n");
+#ifdef CONFIG_MV_ETH_L2SEC
+	off += sprintf(buf+off, "echo 1 > esp   - enable ESP\n");
+#endif
+	off += sprintf(buf+off, "cat dump - display L2fw rules DB\n");
+	off += sprintf(buf+off, "echo 1 > flush - flush L2fw rules DB\n");
+	return off;
+}
+
+static ssize_t l2fw_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+    const char	*name = attr->attr.name;
+    int             off = 0;
+
+    if (!capable(CAP_NET_ADMIN))
+	return -EPERM;
+
+	if (!strcmp(name, "help")) {
+	    off = l2fw_help(buf);
+		return off;
+	}
+	if (!strcmp(name, "dump")) {
+		l2fw_dump();
+		return off;
+	}
+	if (!strcmp(name, "numHashEntries")) {
+		l2fw_show_numHashEntries();
+		return off;
+	}
+#ifdef CONFIG_MV_ETH_L2SEC
+	if (!strcmp(name, "esp")) {
+		l2fw_esp_show();
+		return off;
+	}
+#endif
+	if (!strcmp(name, "help")) {
+	    off = l2fw_help(buf);
+		return off;
+	}
+
+#ifdef CONFIG_MV_ETH_L2SEC
+	if (!strcmp(name, "stats")) {
+	    l2fw_stats();
+		return off;
+	}
+#endif
+
+	return off;
+}
+
+
+
+static ssize_t l2fw_hex_store(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	int             err;
+	unsigned int    addr1, addr2;
+	int port;
+	unsigned long   flags;
+#ifdef CONFIG_MV_ETH_L2SEC
+	int             enableEsp;
+#endif
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+	err = addr1 = addr2 = port = 0;
+
+	local_irq_save(flags);
+	if (!strcmp(name, "l2fw_add")) {
+		sscanf(buf, "%x %x %d", &addr1, &addr2, &port);
+		l2fw_add(addr1, addr2, port);
+	} else if (!strcmp(name, "l2fw_add_ip")) {
+		l2fw_add_ip(buf);
+#ifdef CONFIG_MV_ETH_L2SEC
+	} else if (!strcmp(name, "esp")) {
+		sscanf(buf, "%d", &enableEsp);
+		l2fw_esp_set(enableEsp);
+#endif
+	} else if (!strcmp(name, "flush")) {
+		l2fw_flush();
+	}
+
+	local_irq_restore(flags);
+
+	return err ? -EINVAL : len;
+}
+
+static ssize_t l2fw_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char	*name = attr->attr.name;
+	int             err;
+
+	unsigned int    p, txp, txq, v;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	err = p = txp = txq = v = 0;
+	sscanf(buf, "%d %d %d %d", &p, &txp, &txq, &v);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "l2fw_xor"))
+		l2fw_xor(p);
+
+	else if (!strcmp(name, "l2fw"))
+		l2fw(p, txp, txq);
+#ifdef CONFIG_MV_ETH_L2SEC
+	else if (!strcmp(name, "cesa_chan"))
+		err = l2fw_set_cesa_chan(p, txp);
+#endif
+	local_irq_restore(flags);
+
+	if (err)
+		mvOsPrintf("%s: error %d\n", __func__, err);
+
+	return err ? -EINVAL : len;
+
+}
+
+
+static DEVICE_ATTR(l2fw,			S_IWUSR, l2fw_show, l2fw_store);
+static DEVICE_ATTR(l2fw_xor,		S_IWUSR, l2fw_show, l2fw_store);
+static DEVICE_ATTR(l2fw_add,		S_IWUSR, l2fw_show, l2fw_hex_store);
+static DEVICE_ATTR(l2fw_add_ip,		S_IWUSR, l2fw_show, l2fw_hex_store);
+static DEVICE_ATTR(help,			S_IRUSR, l2fw_show,  NULL);
+static DEVICE_ATTR(dump,			S_IRUSR, l2fw_show,  NULL);
+static DEVICE_ATTR(numHashEntries,	S_IRUSR, l2fw_show,  NULL);
+#ifdef CONFIG_MV_ETH_L2SEC
+static DEVICE_ATTR(stats,			S_IRUSR, l2fw_show, NULL);
+static DEVICE_ATTR(esp,				S_IWUSR, l2fw_show,  l2fw_hex_store);
+static DEVICE_ATTR(cesa_chan,		S_IWUSR, NULL,  l2fw_store);
+#endif
+static DEVICE_ATTR(flush,			S_IWUSR, NULL,  	 l2fw_hex_store);
+
+
+static struct attribute *l2fw_attrs[] = {
+	&dev_attr_l2fw.attr,
+	&dev_attr_l2fw_xor.attr,
+	&dev_attr_l2fw_add.attr,
+	&dev_attr_l2fw_add_ip.attr,
+	&dev_attr_help.attr,
+	&dev_attr_dump.attr,
+	&dev_attr_flush.attr,
+#ifdef CONFIG_MV_ETH_L2SEC
+	&dev_attr_esp.attr,
+	&dev_attr_stats.attr,
+	&dev_attr_cesa_chan.attr,
+#endif
+	&dev_attr_numHashEntries.attr,
+	NULL
+};
+
+static struct attribute_group l2fw_group = {
+	.name = "l2fw",
+	.attrs = l2fw_attrs,
+};
+
+#ifdef CONFIG_MV_ETH_L2FW
+int __devinit mv_l2fw_sysfs_init(void)
+{
+	int err;
+	struct device *pd;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	if (!pd) {
+		platform_device_register_simple("neta", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR "%s: cannot find neta device\n", __func__);
+		pd = &platform_bus;
+	}
+
+	err = sysfs_create_group(&pd->kobj, &l2fw_group);
+	if (err) {
+		printk(KERN_ERR "sysfs group failed %d\n", err);
+		goto out;
+	}
+out:
+	return err;
+}
+#endif
+
+module_init(mv_l2fw_sysfs_init);
+
+MODULE_AUTHOR("Rami Rosen");
+MODULE_DESCRIPTION("sysfs for marvell l2fw");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2fw.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2fw.c
new file mode 100755
index 0000000..588eb94
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2fw.c
@@ -0,0 +1,943 @@
+/* mv_eth_l2fw.c */
+#include <linux/ctype.h>
+
+#include "xor/mvXor.h"
+#include "xor/mvXorRegs.h"
+#include "mv_hal_if/mvSysXorApi.h"
+
+#include "mvOs.h"
+#include "mv_eth_l2fw.h"
+#include "mv_neta/net_dev/mv_netdev.h"
+#include "gbe/mvNeta.h"
+#include "gbe/mvNetaRegs.h"
+
+#include "mv_eth_l2fw.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#ifdef CONFIG_MV_ETH_L2SEC
+extern int cesa_init(void);
+extern MV_STATUS handleEsp(struct eth_pbuf *pkt, struct neta_rx_desc *rx_desc,
+							struct eth_port  *new_pp, int inPort);
+#endif
+
+int espEnabled = 0;
+
+struct eth_pbuf *mv_eth_pool_get(struct bm_pool *pool);
+
+static int mv_eth_ports_l2fw_num;
+
+static L2FW_RULE **l2fw_hash = NULL;
+
+#define	L2FW_HASH_MASK   (L2FW_HASH_SIZE - 1)
+
+static MV_U32 l2fw_jhash_iv;
+
+static int numHashEntries;
+
+struct eth_port_l2fw **mv_eth_ports_l2fw;
+static inline int       mv_eth_l2fw_rx(struct eth_port *pp, int rx_todo, int rxq);
+static inline MV_STATUS mv_eth_l2fw_tx(struct eth_pbuf *pkt, struct eth_port *pp,
+					   int withXor, struct neta_rx_desc *rx_desc);
+
+
+void printBufVirtPtr(MV_BUF_INFO *pBuf)
+{
+	int i;
+	if (pBuf->bufVirtPtr == NULL) {
+		printk(KERN_INFO "pBuf->bufVirtPt==NULL in %s\n", __func__);
+		return;
+	}
+	for (i = 0; i < 40; i++) {
+		printk(KERN_INFO "KERN_INFO [%d]=%x ", i, pBuf->bufVirtPtr[i]);
+		if (!(i%10) && i > 1)
+			printk(KERN_INFO "\n");
+	}
+	printk(KERN_INFO "\n****************** %s\n", __func__);
+
+}
+void printBufInfo(MV_BUF_INFO *pbuf)
+{
+	printk(KERN_INFO "bufSize=%d\n"      , pbuf->bufSize);
+	printk(KERN_INFO "dataSize=%d\n"     , pbuf->dataSize);
+	printk(KERN_INFO "memHandle=%d\n"    , pbuf->memHandle);
+	printk(KERN_INFO "bufAddrShift=%d\n" , pbuf->bufAddrShift);
+	printk(KERN_INFO "*****************************************\n\n");
+
+}
+
+
+static s32 atoi(char *psz_buf)
+{
+	char *pch = psz_buf;
+	s32 base = 0;
+	unsigned long res;
+	int ret_val;
+
+	while (isspace(*pch))
+			pch++;
+
+	if (*pch == '-' || *pch == '+') {
+			base = 10;
+			pch++;
+	} else if (*pch && tolower(pch[strlen(pch) - 1]) == 'h') {
+			base = 16;
+	}
+
+	ret_val = strict_strtoul(pch, base, &res);
+
+	return ret_val ? : res;
+}
+
+
+
+static L2FW_RULE *l2fw_lookup(MV_U32 srcIP, MV_U32 dstIP)
+{
+	MV_U32 hash;
+	L2FW_RULE *rule;
+
+	hash = mv_jhash_3words(srcIP, dstIP, (MV_U32) 0, l2fw_jhash_iv);
+	hash &= L2FW_HASH_MASK;
+	rule = l2fw_hash[hash];
+#ifdef CONFIG_MV_ETH_L2FW_DEBUG
+	if (rule)
+		printk(KERN_INFO "rule is not NULL in %s\n", __func__);
+	else
+		printk(KERN_INFO "rule is NULL in %s\n", __func__);
+#endif
+	while (rule) {
+		if ((rule->srcIP == srcIP) && (rule->dstIP == dstIP))
+			return rule;
+
+		rule = rule->next;
+	}
+	return NULL;
+}
+
+void l2fw_show_numHashEntries(void)
+{
+	mvOsPrintf("number of Hash Entries is %d \n", numHashEntries);
+
+}
+
+
+void l2fw_flush(void)
+{
+	MV_U32 i = 0;
+	mvOsPrintf("\nFlushing L2fw Rule Database: \n");
+	mvOsPrintf("*******************************\n");
+	for (i = 0; i < L2FW_HASH_SIZE; i++)
+		l2fw_hash[i] = NULL;
+	numHashEntries = 0;
+}
+
+
+void l2fw_dump(void)
+{
+	MV_U32 i = 0;
+	L2FW_RULE *currRule;
+	MV_U8	  *srcIP, *dstIP;
+
+	mvOsPrintf("\nPrinting L2fw Rule Database: \n");
+	mvOsPrintf("*******************************\n");
+
+	for (i = 0; i < L2FW_HASH_SIZE; i++) {
+		currRule = l2fw_hash[i];
+		srcIP = (MV_U8 *)&(currRule->srcIP);
+		dstIP = (MV_U8 *)&(currRule->dstIP);
+
+		while (currRule != NULL) {
+			mvOsPrintf("%u.%u.%u.%u->%u.%u.%u.%u    out port=%d (hash=%x)\n",
+				MV_IPQUAD(srcIP), MV_IPQUAD(dstIP),
+				currRule->port, i);
+			currRule = currRule->next;
+		}
+	}
+
+}
+
+
+MV_STATUS l2fw_add(MV_U32 srcIP, MV_U32 dstIP, int port)
+{
+	L2FW_RULE *l2fw_rule;
+	MV_U8	  *srcIPchr, *dstIPchr;
+
+	MV_U32 hash = mv_jhash_3words(srcIP, dstIP, (MV_U32) 0, l2fw_jhash_iv);
+	hash &= L2FW_HASH_MASK;
+	if (numHashEntries == L2FW_HASH_SIZE) {
+		printk(KERN_INFO "cannot add entry, hash table is full, there are %d entires \n", L2FW_HASH_SIZE);
+		return MV_ERROR;
+	}
+
+	srcIPchr = (MV_U8 *)&(srcIP);
+	dstIPchr = (MV_U8 *)&(dstIP);
+
+#ifdef CONFIG_MV_ETH_L2FW_DEBUG
+	mvOsPrintf("srcIP=%x dstIP=%x in %s\n", srcIP, dstIP, __func__);
+	mvOsPrintf("srcIp = %u.%u.%u.%u in %s\n", MV_IPQUAD(srcIPchr), __func__);
+	mvOsPrintf("dstIp = %u.%u.%u.%u in %s\n", MV_IPQUAD(dstIPchr), __func__);
+#endif
+
+	l2fw_rule = l2fw_lookup(srcIP, dstIP);
+	if (l2fw_rule)
+		return MV_OK;
+
+	l2fw_rule = (L2FW_RULE *)mvOsMalloc(sizeof(L2FW_RULE));
+	if (!l2fw_rule) {
+		mvOsPrintf("%s: OOM\n", __func__);
+		return MV_FAIL;
+	}
+#ifdef CONFIG_MV_ETH_L2FW_DEBUG
+	mvOsPrintf("adding a rule to l2fw hash in %s\n", __func__);
+#endif
+	l2fw_rule->srcIP = srcIP;
+	l2fw_rule->dstIP = dstIP;
+	l2fw_rule->port = port;
+
+	l2fw_rule->next = l2fw_hash[hash];
+	l2fw_hash[hash] = l2fw_rule;
+	numHashEntries++;
+    return MV_OK;
+}
+
+MV_STATUS l2fw_add_ip(const char *buf)
+{
+	char *addr1, *addr2;
+	L2FW_RULE *l2fw_rule;
+	MV_U32 srcIP;
+	MV_U32 dstIP;
+	MV_U8	  *srcIPchr, *dstIPchr;
+	char dest1[15];
+	char dest2[15];
+	char *portStr;
+	int offset1, offset2, port;
+	MV_U32 hash    = 0;
+	if (numHashEntries == L2FW_HASH_SIZE) {
+		printk(KERN_INFO "cannot add entry, hash table is full, there are %d entires \n", L2FW_HASH_SIZE);
+		return MV_ERROR;
+	}
+
+	memset(dest1,   0, sizeof(dest1));
+	memset(dest2,   0, sizeof(dest2));
+
+	addr1 = strchr(buf, ',');
+	addr2 =	strchr(addr1+1, ',');
+	offset1 = addr1-buf;
+	offset2 = addr2-addr1;
+	if (!addr1) {
+			printk(KERN_INFO "first separating comma (',') missing in input in %s\n", __func__);
+			return MV_FAIL;
+	}
+	if (!addr2) {
+			printk(KERN_INFO "second separating comma (',') missing in input in %s\n", __func__);
+			return MV_FAIL;
+	}
+
+	strncpy(dest1, buf, addr1-buf);
+	srcIP = in_aton(dest1);
+	strncpy(dest2, buf+offset1+1, addr2-addr1-1);
+	dstIP = in_aton(dest2);
+	srcIPchr = (MV_U8 *)&(srcIP);
+	dstIPchr = (MV_U8 *)&(dstIP);
+	portStr = addr2+1;
+	if (*portStr == 'D') {
+		L2FW_RULE *l2fw_rule_to_del, *prev;
+		hash = mv_jhash_3words(srcIP, dstIP, (MV_U32) 0, l2fw_jhash_iv);
+		hash &= L2FW_HASH_MASK;
+		l2fw_rule_to_del = l2fw_hash[hash];
+		prev = NULL;
+
+		while (l2fw_rule_to_del) {
+		if ((l2fw_rule_to_del->srcIP == srcIP) &&
+			(l2fw_rule_to_del->dstIP == dstIP)) {
+			if (prev)
+				prev->next = l2fw_rule_to_del->next;
+			else
+				l2fw_hash[hash] = l2fw_rule_to_del->next;
+			mvOsPrintf("%u.%u.%u.%u->%u.%u.%u.%u deleted\n", MV_IPQUAD(srcIPchr), MV_IPQUAD(dstIPchr));
+			mvOsFree(l2fw_rule_to_del);
+			numHashEntries--;
+			return MV_OK;
+		}
+
+		prev = l2fw_rule_to_del;
+		l2fw_rule_to_del = l2fw_rule_to_del->next;
+	}
+		mvOsPrintf("%u.%u.%u.%u->%u.%u.%u.%u : entry not found\n", MV_IPQUAD(srcIPchr), MV_IPQUAD(dstIPchr));
+		return MV_NOT_FOUND;
+	}
+
+	port = atoi(portStr);
+	hash = mv_jhash_3words(srcIP, dstIP, (MV_U32) 0, l2fw_jhash_iv);
+	hash &= L2FW_HASH_MASK;
+
+	l2fw_rule = l2fw_lookup(srcIP, dstIP);
+	if (l2fw_rule) {
+		mvOsPrintf("%u.%u.%u.%u->%u.%u.%u.%u : entry already exist\n",
+				MV_IPQUAD(srcIPchr), MV_IPQUAD(dstIPchr));
+		return MV_OK;
+	}
+
+	l2fw_rule = (L2FW_RULE *)mvOsMalloc(sizeof(L2FW_RULE));
+	if (!l2fw_rule) {
+		mvOsPrintf("%s: OOM\n", __func__);
+		return MV_FAIL;
+	}
+#ifdef CONFIG_MV_ETH_L2FW_DEBUG
+	mvOsPrintf("adding a rule to l2fw hash in %s\n", __func__);
+#endif
+	l2fw_rule->srcIP = srcIP;
+	l2fw_rule->dstIP = dstIP;
+	l2fw_rule->port = port;
+
+	l2fw_rule->next = l2fw_hash[hash];
+	l2fw_hash[hash] = l2fw_rule;
+	numHashEntries++;
+    return MV_OK;
+
+}
+
+void l2fw_esp_show(void)
+{
+	if (espEnabled)
+		printk(KERN_INFO "ESP is enabled in %s\n", __func__);
+	else
+		printk(KERN_INFO "ESP is not enabled in %s\n", __func__);
+}
+
+#ifdef CONFIG_MV_INCLUDE_XOR
+static void dump_xor(void)
+{
+	mvOsPrintf(" CHANNEL_ARBITER_REG %08x\n",
+		MV_REG_READ(XOR_CHANNEL_ARBITER_REG(1)));
+	mvOsPrintf(" CONFIG_REG          %08x\n",
+		MV_REG_READ(XOR_CONFIG_REG(1, XOR_CHAN(0))));
+	mvOsPrintf(" ACTIVATION_REG      %08x\n",
+		MV_REG_READ(XOR_ACTIVATION_REG(1, XOR_CHAN(0))));
+	mvOsPrintf(" CAUSE_REG           %08x\n",
+		MV_REG_READ(XOR_CAUSE_REG(1)));
+	mvOsPrintf(" MASK_REG            %08x\n",
+		MV_REG_READ(XOR_MASK_REG(1)));
+	mvOsPrintf(" ERROR_CAUSE_REG     %08x\n",
+		MV_REG_READ(XOR_ERROR_CAUSE_REG(1)));
+	mvOsPrintf(" ERROR_ADDR_REG      %08x\n",
+		MV_REG_READ(XOR_ERROR_ADDR_REG(1)));
+	mvOsPrintf(" NEXT_DESC_PTR_REG   %08x\n",
+		MV_REG_READ(XOR_NEXT_DESC_PTR_REG(1, XOR_CHAN(0))));
+	mvOsPrintf(" CURR_DESC_PTR_REG   %08x\n",
+		MV_REG_READ(XOR_CURR_DESC_PTR_REG(1, XOR_CHAN(0))));
+	mvOsPrintf(" BYTE_COUNT_REG      %08x\n\n",
+		MV_REG_READ(XOR_BYTE_COUNT_REG(1, XOR_CHAN(0))));
+	mvOsPrintf("  %08x\n\n", XOR_WINDOW_CTRL_REG(1, XOR_CHAN(0))) ;
+		mvOsPrintf(" XOR_WINDOW_CTRL_REG      %08x\n\n",
+		MV_REG_READ(XOR_WINDOW_CTRL_REG(1, XOR_CHAN(0)))) ;
+}
+#endif
+
+
+/* L2fw defines */
+#define L2FW_DISABLE				0
+#define TX_AS_IS					1
+#define SWAP_MAC					2
+#define COPY_AND_SWAP		        3
+
+#define XOR_CAUSE_DONE_MASK(chan) ((BIT0|BIT1) << (chan * 16))
+
+static int         l2fw_xor_threshold = 200;
+static MV_XOR_DESC *eth_xor_desc = NULL;
+static MV_LONG      eth_xor_desc_phys_addr;
+
+
+static int mv_eth_poll_l2fw(struct napi_struct *napi, int budget)
+{
+	int rx_done = 0;
+	MV_U32 causeRxTx;
+	struct eth_port *pp = MV_ETH_PRIV(napi->dev);
+	read_lock(&pp->rwlock);
+
+	STAT_INFO(pp->stats.poll[smp_processor_id()]++);
+
+	/* Read cause register */
+	causeRxTx = MV_REG_READ(NETA_INTR_NEW_CAUSE_REG(pp->port)) &
+	    (MV_ETH_MISC_SUM_INTR_MASK | MV_ETH_TXDONE_INTR_MASK |
+		 MV_ETH_RX_INTR_MASK);
+
+	if (causeRxTx & MV_ETH_MISC_SUM_INTR_MASK) {
+		MV_U32 causeMisc;
+
+		/* Process MISC events - Link, etc ??? */
+		causeRxTx &= ~MV_ETH_MISC_SUM_INTR_MASK;
+		causeMisc = MV_REG_READ(NETA_INTR_MISC_CAUSE_REG(pp->port));
+
+		if (causeMisc & NETA_CAUSE_LINK_CHANGE_MASK)
+			mv_eth_link_event(pp, 1);
+		MV_REG_WRITE(NETA_INTR_MISC_CAUSE_REG(pp->port), 0);
+	}
+
+	causeRxTx |= pp->causeRxTx[smp_processor_id()];
+#ifdef CONFIG_MV_ETH_TXDONE_ISR
+	if (causeRxTx & MV_ETH_TXDONE_INTR_MASK) {
+		/* TX_DONE process */
+
+		mv_eth_tx_done_gbe(pp,
+				(causeRxTx & MV_ETH_TXDONE_INTR_MASK));
+
+		causeRxTx &= ~MV_ETH_TXDONE_INTR_MASK;
+	}
+#endif /* CONFIG_MV_ETH_TXDONE_ISR */
+
+#if (CONFIG_MV_ETH_RXQ > 1)
+	while ((causeRxTx != 0) && (budget > 0)) {
+		int count, rx_queue;
+
+		rx_queue = mv_eth_rx_policy(causeRxTx);
+		if (rx_queue == -1)
+			break;
+
+		count = mv_eth_l2fw_rx(pp, budget, rx_queue);
+		rx_done += count;
+		budget -= count;
+		if (budget > 0)
+			causeRxTx &=
+			 ~((1 << rx_queue) << NETA_CAUSE_RXQ_OCCUP_DESC_OFFS);
+	}
+#else
+	rx_done = mv_eth_l2fw_rx(pp, budget, CONFIG_MV_ETH_RXQ_DEF);
+	budget -= rx_done;
+#endif /* (CONFIG_MV_ETH_RXQ > 1) */
+
+
+	if (budget > 0) {
+		unsigned long flags;
+		causeRxTx = 0;
+
+		napi_complete(napi);
+		STAT_INFO(pp->stats.poll_exit[smp_processor_id()]++);
+
+		local_irq_save(flags);
+		MV_REG_WRITE(NETA_INTR_NEW_MASK_REG(pp->port),
+			(MV_ETH_MISC_SUM_INTR_MASK | MV_ETH_TXDONE_INTR_MASK |
+				  MV_ETH_RX_INTR_MASK));
+
+		local_irq_restore(flags);
+	}
+	pp->causeRxTx[smp_processor_id()] = causeRxTx;
+
+	read_unlock(&pp->rwlock);
+
+	return rx_done;
+}
+
+
+void mv_eth_set_l2fw(int cmd, int rx_port, int out_tx_port)
+{
+	struct eth_port *pp;
+	struct net_device *dev;
+	int group;
+
+	pp     = mv_eth_ports[rx_port];
+	if (!pp) {
+		mvOsPrintf("pp is NULL in setting L2FW (%s)\n", __func__);
+		return;
+	}
+
+	dev = pp->dev;
+	if (dev == NULL) {
+		mvOsPrintf("device is NULL in in setting L2FW (%s)\n", __func__);
+		return;
+	}
+	if (!test_bit(MV_ETH_F_STARTED_BIT, &(pp->flags))) {
+		mvOsPrintf("Device is down for port=%d ; MV_ETH_F_STARTED_BIT is not set in %s\n", rx_port, __func__);
+		mvOsPrintf("Cannot set to L2FW mode in %s\n", __func__);
+		return;
+	}
+
+	/* when disabling l2fw, and then ifdown/up, we should
+	   enable MV_ETH_F_CONNECT_LINUX_BIT bit so that the port will be started ok.
+	   TBD: remember last state */
+
+	if (cmd == L2FW_DISABLE)
+		set_bit(MV_ETH_F_CONNECT_LINUX_BIT, &(pp->flags));
+	else
+		clear_bit(MV_ETH_F_CONNECT_LINUX_BIT, &(pp->flags));
+
+	for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++) {
+		if (cmd == L2FW_DISABLE) {
+			if (test_bit(MV_ETH_F_STARTED_BIT, &(pp->flags)))
+				napi_disable(pp->napiGroup[group]);
+			netif_napi_del(pp->napiGroup[group]);
+			netif_napi_add(dev, pp->napiGroup[group], mv_eth_poll,
+				pp->weight);
+			if (test_bit(MV_ETH_F_STARTED_BIT, &(pp->flags)))
+				napi_enable(pp->napiGroup[group]);
+		} else {
+			if (test_bit(MV_ETH_F_STARTED_BIT, &(pp->flags)))
+				napi_disable(pp->napiGroup[group]);
+			netif_napi_del(pp->napiGroup[group]);
+			printk(KERN_INFO "pp->weight=%d in %s\n", pp->weight, __func__);
+			netif_napi_add(dev, pp->napiGroup[group], mv_eth_poll_l2fw,
+				pp->weight);
+			if (test_bit(MV_ETH_F_STARTED_BIT, &(pp->flags)))
+				napi_enable(pp->napiGroup[group]);
+			}
+	}
+}
+
+
+static inline struct eth_pbuf *l2fw_swap_mac(struct eth_pbuf *pRxPktInfo)
+{
+	MV_U16 *pSrc;
+	int i;
+	MV_U16 swap;
+	pSrc = (MV_U16 *)(pRxPktInfo->pBuf + pRxPktInfo->offset + MV_ETH_MH_SIZE);
+
+	for (i = 0; i < 3; i++) {
+		swap = pSrc[i];
+		pSrc[i] = pSrc[i+3];
+		pSrc[i+3] = swap;
+		}
+
+	return  pRxPktInfo;
+}
+
+static inline void l2fw_copy_mac(struct eth_pbuf *pRxPktInfo,
+					 struct eth_pbuf *pTxPktInfo)
+	{
+	/* copy 30 bytes (start after MH header) */
+    /* 12 for SA + DA */
+	/* 18 for the rest */
+	MV_U16 *pSrc;
+	MV_U16 *pDst;
+	int i;
+	pSrc = (MV_U16 *)(pRxPktInfo->pBuf + pRxPktInfo->offset + MV_ETH_MH_SIZE);
+	pDst = (MV_U16 *)(pTxPktInfo->pBuf + pTxPktInfo->offset + MV_ETH_MH_SIZE);
+	/* swap mac SA and DA */
+	for (i = 0; i < 3; i++) {
+		pDst[i]   = pSrc[i+3];
+		pDst[i+3] = pSrc[i];
+		}
+	for (i = 6; i < 15; i++)
+		pDst[i] = pSrc[i];
+	}
+
+static inline void l2fw_copy_and_swap_mac(struct eth_pbuf *pRxPktInfo, struct eth_pbuf *pTxPktInfo)
+{
+	MV_U16 *pSrc;
+	MV_U16 *pDst;
+	int i;
+
+	pSrc = (MV_U16 *)(pRxPktInfo->pBuf +  pRxPktInfo->offset + MV_ETH_MH_SIZE);
+	pDst = (MV_U16 *)(pTxPktInfo->pBuf +  pTxPktInfo->offset + MV_ETH_MH_SIZE);
+	for (i = 0; i < 3; i++) {
+		pDst[i]   = pSrc[i+3];
+		pDst[i+3] = pSrc[i];
+		}
+}
+
+static inline
+struct eth_pbuf *eth_l2fw_copy_packet_withoutXor(struct eth_pbuf *pRxPktInfo)
+{
+	MV_U8 *pSrc;
+	MV_U8 *pDst;
+	struct bm_pool *pool;
+	struct eth_pbuf *pTxPktInfo;
+
+	mvOsCacheInvalidate(NULL, pRxPktInfo->pBuf + pRxPktInfo->offset,
+						pRxPktInfo->bytes);
+
+	pool = &mv_eth_pool[pRxPktInfo->pool];
+	pTxPktInfo = mv_eth_pool_get(pool);
+	if (pTxPktInfo == NULL) {
+		mvOsPrintf("pTxPktInfo == NULL in %s\n", __func__);
+		return NULL;
+		}
+	pSrc = pRxPktInfo->pBuf +  pRxPktInfo->offset + MV_ETH_MH_SIZE;
+	pDst = pTxPktInfo->pBuf +  pTxPktInfo->offset + MV_ETH_MH_SIZE;
+
+	memcpy(pDst+12, pSrc+12, pRxPktInfo->bytes-12);
+	l2fw_copy_and_swap_mac(pRxPktInfo, pTxPktInfo);
+	pTxPktInfo->bytes = pRxPktInfo->bytes;
+	mvOsCacheFlush(NULL, pTxPktInfo->pBuf + pTxPktInfo->offset, pTxPktInfo->bytes);
+
+	return pTxPktInfo;
+}
+
+static inline
+struct eth_pbuf *eth_l2fw_copy_packet_withXor(struct eth_pbuf *pRxPktInfo)
+{
+	struct bm_pool *pool;
+	struct eth_pbuf *pTxPktInfo;
+
+	pool = &mv_eth_pool[pRxPktInfo->pool];
+	pTxPktInfo = mv_eth_pool_get(pool);
+	if (pTxPktInfo == NULL) {
+		mvOsPrintf("pTxPktInfo == NULL in %s\n", __func__);
+		return NULL;
+		}
+
+	/* sync between giga and XOR to avoid errors (like checksum errors in TX)
+	   when working with IOCC */
+
+	mvOsCacheIoSync();
+
+	eth_xor_desc->srcAdd0    = pRxPktInfo->physAddr + pRxPktInfo->offset + MV_ETH_MH_SIZE + 30;
+	eth_xor_desc->phyDestAdd = pTxPktInfo->physAddr + pTxPktInfo->offset + MV_ETH_MH_SIZE + 30;
+
+	eth_xor_desc->byteCnt    = pRxPktInfo->bytes - 30;
+
+	eth_xor_desc->phyNextDescPtr = 0;
+	eth_xor_desc->status         = BIT31;
+	/* we had changed only the first part of eth_xor_desc, so flush only one
+	 line of cache */
+	mvOsCacheLineFlush(NULL, eth_xor_desc);
+	MV_REG_WRITE(XOR_NEXT_DESC_PTR_REG(1, XOR_CHAN(0)), eth_xor_desc_phys_addr);
+
+	MV_REG_WRITE(XOR_ACTIVATION_REG(1, XOR_CHAN(0)), XEXACTR_XESTART_MASK);
+
+	mvOsCacheLineInv(NULL, pRxPktInfo->pBuf + pRxPktInfo->offset);
+	l2fw_copy_mac(pRxPktInfo, pTxPktInfo);
+	mvOsCacheLineFlush(NULL, pTxPktInfo->pBuf + pTxPktInfo->offset);
+
+    /* Update TxPktInfo */
+	pTxPktInfo->bytes = pRxPktInfo->bytes;
+	return pTxPktInfo;
+}
+
+#ifdef CONFIG_MV_INCLUDE_XOR
+void setXorDesc(void)
+{
+	unsigned int mode;
+	eth_xor_desc = mvOsMalloc(sizeof(MV_XOR_DESC) + XEXDPR_DST_PTR_DMA_MASK + 32);
+	eth_xor_desc = (MV_XOR_DESC *)MV_ALIGN_UP((MV_U32)eth_xor_desc, XEXDPR_DST_PTR_DMA_MASK+1);
+	eth_xor_desc_phys_addr = mvOsIoVirtToPhys(NULL, eth_xor_desc);
+	mvSysXorInit();
+
+	mode = MV_REG_READ(XOR_CONFIG_REG(1, XOR_CHAN(0)));
+	mode &= ~XEXCR_OPERATION_MODE_MASK;
+	mode |= XEXCR_OPERATION_MODE_DMA;
+	MV_REG_WRITE(XOR_CONFIG_REG(1, XOR_CHAN(0)), mode);
+
+    MV_REG_WRITE(XOR_NEXT_DESC_PTR_REG(1, XOR_CHAN(0)), eth_xor_desc_phys_addr);
+	dump_xor();
+}
+#endif
+
+static inline int xorReady(void)
+{
+	int timeout = 0;
+
+	while (!(MV_REG_READ(XOR_CAUSE_REG(1)) & XOR_CAUSE_DONE_MASK(XOR_CHAN(0)))) {
+		if (timeout > 0x100000) {
+			mvOsPrintf("XOR timeout\n");
+			return 0;
+			}
+		timeout++;
+	}
+
+	/* Clear int */
+	MV_REG_WRITE(XOR_CAUSE_REG(1), ~(XOR_CAUSE_DONE_MASK(XOR_CHAN(0))));
+
+	return 1;
+}
+
+
+void l2fw(int cmd, int rx_port, int tx_port)
+{
+	struct eth_port_l2fw *ppl2fw;
+
+	mv_eth_ports_l2fw_num = mvCtrlEthMaxPortGet();
+	ppl2fw = mv_eth_ports_l2fw[rx_port];
+	mvOsPrintf("cmd=%d rx_port=%d tx_port=%d in %s \n",
+				cmd, rx_port, tx_port, __func__);
+	ppl2fw->txPort = tx_port;
+	ppl2fw->cmd	= cmd;
+	mv_eth_set_l2fw(cmd, rx_port, tx_port);
+}
+
+void l2fw_xor(int threshold)
+{
+	mvOsPrintf("setting threshold to %d in %s\n", threshold, __func__);
+	l2fw_xor_threshold = threshold;
+}
+
+
+static inline MV_STATUS mv_eth_l2fw_tx(struct eth_pbuf *pkt, struct eth_port *pp, int withXor,
+									   struct neta_rx_desc *rx_desc)
+{
+	struct neta_tx_desc *tx_desc;
+	u32 tx_cmd = 0;
+	struct tx_queue *txq_ctrl;
+	/* assigning different txq for each rx port , to avoid waiting on the
+	same txq lock when traffic on several rx ports are destined to the same
+	outgoing interface */
+	int txq = pp->txq[smp_processor_id()];
+	read_lock(&pp->rwlock);
+	txq_ctrl = &pp->txq_ctrl[pp->txp * CONFIG_MV_ETH_TXQ + txq];
+	spin_lock(&txq_ctrl->queue_lock);
+
+	if (txq_ctrl->txq_count >= mv_ctrl_txdone)
+		mv_eth_txq_done(pp, txq_ctrl);
+	/* Get next descriptor for tx, single buffer, so FIRST & LAST */
+	tx_desc = mv_eth_tx_desc_get(txq_ctrl, 1);
+	if (tx_desc == NULL) {
+		spin_unlock(&txq_ctrl->queue_lock);
+		read_unlock(&pp->rwlock);
+		/* No resources: Drop */
+		pp->dev->stats.tx_dropped++;
+		if (withXor)
+			xorReady();
+		return MV_DROPPED;
+	}
+	txq_ctrl->txq_count++;
+
+	tx_cmd |= NETA_TX_BM_ENABLE_MASK | NETA_TX_BM_POOL_ID_MASK(pkt->pool);
+	txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = (u32) NULL;
+	mv_eth_shadow_inc_put(txq_ctrl);
+
+	tx_desc->command = tx_cmd | NETA_TX_L4_CSUM_NOT |
+		NETA_TX_FLZ_DESC_MASK | NETA_TX_F_DESC_MASK
+		| NETA_TX_L_DESC_MASK |
+		NETA_TX_PKT_OFFSET_MASK(pkt->offset + MV_ETH_MH_SIZE);
+
+	tx_desc->dataSize    = pkt->bytes;
+	tx_desc->bufPhysAddr = pkt->physAddr;
+
+	mv_eth_tx_desc_flush(tx_desc);
+
+	if (withXor) {
+		if (!xorReady()) {
+			mvOsPrintf("MV_DROPPED in %s\n", __func__);
+			spin_unlock(&txq_ctrl->queue_lock);
+			read_unlock(&pp->rwlock);
+			return MV_DROPPED;
+		}
+	}
+	mvNetaTxqPendDescAdd(pp->port, pp->txp, txq, 1);
+
+	spin_unlock(&txq_ctrl->queue_lock);
+	read_unlock(&pp->rwlock);
+
+	return MV_OK;
+}
+
+
+static inline int mv_eth_l2fw_rx(struct eth_port *pp, int rx_todo, int rxq)
+{
+	struct eth_port  *new_pp;
+	L2FW_RULE *l2fw_rule;
+	MV_NETA_RXQ_CTRL *rx_ctrl = pp->rxq_ctrl[rxq].q;
+	int rx_done, rx_filled;
+	struct neta_rx_desc *rx_desc;
+	u32 rx_status = MV_OK;
+	struct eth_pbuf *pkt;
+	struct eth_pbuf *newpkt = NULL;
+	struct bm_pool *pool;
+	MV_STATUS status = MV_OK;
+	struct eth_port_l2fw *ppl2fw = mv_eth_ports_l2fw[pp->port];
+	MV_IP_HEADER *pIph = NULL;
+	MV_U8 *pData;
+	int	ipOffset;
+
+	rx_done = mvNetaRxqBusyDescNumGet(pp->port, rxq);
+	mvOsCacheIoSync();
+	if (rx_todo > rx_done)
+		rx_todo = rx_done;
+	rx_done = 0;
+	rx_filled = 0;
+
+	/* Fairness NAPI loop */
+	while (rx_done < rx_todo) {
+#ifdef CONFIG_MV_ETH_RX_DESC_PREFETCH
+		rx_desc = mv_eth_rx_prefetch(pp, rx_ctrl, rx_done, rx_todo);
+		if (!rx_desc)
+			printk(KERN_INFO "rx_desc is NULL in %s\n", __func__);
+#else
+		rx_desc = mvNetaRxqNextDescGet(rx_ctrl);
+		mvOsCacheLineInv(NULL, rx_desc);
+		prefetch(rx_desc);
+#endif /* CONFIG_MV_ETH_RX_DESC_PREFETCH */
+
+		rx_done++;
+		rx_filled++;
+
+		pkt = (struct eth_pbuf *)rx_desc->bufCookie;
+		if (!pkt) {
+			printk(KERN_INFO "pkt is NULL in ; rx_done=%d %s\n", rx_done, __func__);
+			return rx_done;
+		}
+
+		pool = &mv_eth_pool[pkt->pool];
+		rx_status = rx_desc->status;
+		if (((rx_status & NETA_RX_FL_DESC_MASK) != NETA_RX_FL_DESC_MASK) ||
+			(rx_status & NETA_RX_ES_MASK)) {
+			STAT_ERR(pp->stats.rx_error++);
+
+			if (pp->dev)
+				pp->dev->stats.rx_errors++;
+
+			mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
+			continue;
+		}
+
+		pkt->bytes = rx_desc->dataSize - (MV_ETH_CRC_SIZE + MV_ETH_MH_SIZE);
+
+		pData = pkt->pBuf + pkt->offset;
+
+#ifdef CONFIG_MV_ETH_PNC
+		ipOffset = NETA_RX_GET_IPHDR_OFFSET(rx_desc);
+#else
+		if ((rx_desc->status & ETH_RX_VLAN_TAGGED_FRAME_MASK))
+			ipOffset = MV_ETH_MH_SIZE + sizeof(MV_802_3_HEADER) + MV_VLAN_HLEN;
+		else
+			ipOffset = MV_ETH_MH_SIZE + sizeof(MV_802_3_HEADER);
+#endif
+
+		pIph = (MV_IP_HEADER *)(pData + ipOffset);
+		if (pIph == NULL) {
+			printk(KERN_INFO "pIph==NULL in %s\n", __func__);
+			continue;
+		}
+#ifdef CONFIG_MV_ETH_L2FW_DEBUG
+		if (pIph) {
+			MV_U8 *srcIP, *dstIP;
+			srcIP = (MV_U8 *)&(pIph->srcIP);
+			dstIP = (MV_U8 *)&(pIph->dstIP);
+			printk(KERN_INFO "%u.%u.%u.%u->%u.%u.%u.%u in %s\n", MV_IPQUAD(srcIP), MV_IPQUAD(dstIP), __func__);
+		} else
+			printk(KERN_INFO "pIph is NULL in %s\n", __func__);
+#endif
+		if (espEnabled)
+			new_pp  = mv_eth_ports[ppl2fw->txPort];
+		else {
+			 l2fw_rule = l2fw_lookup(pIph->srcIP, pIph->dstIP);
+
+			 if (!l2fw_rule) {
+#ifdef CONFIG_MV_ETH_L2FW_DEBUG
+				printk(KERN_INFO "l2fw_lookup() failed in %s\n", __func__);
+#endif
+				mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
+				continue;
+			 }
+
+#ifdef CONFIG_MV_ETH_L2FW_DEBUG
+				printk(KERN_INFO "l2fw_lookup() is ok l2fw_rule->port=%d in %s\n", l2fw_rule->port, __func__);
+#endif
+			new_pp  = mv_eth_ports[l2fw_rule->port];
+			}
+
+		switch (ppl2fw->cmd) {
+		case TX_AS_IS:
+#ifdef CONFIG_MV_ETH_L2SEC
+					if (espEnabled) {
+						status = handleEsp(pkt, rx_desc, new_pp, pp->port);
+					}
+				else
+#endif
+					status = mv_eth_l2fw_tx(pkt, new_pp, 0, rx_desc);
+				break;
+
+		case SWAP_MAC:
+				mvOsCacheLineInv(NULL, pkt->pBuf + pkt->offset);
+				l2fw_swap_mac(pkt);
+				mvOsCacheLineFlush(NULL, pkt->pBuf+pkt->offset);
+				status = mv_eth_l2fw_tx(pkt, new_pp, 0, rx_desc);
+				break;
+
+		case COPY_AND_SWAP:
+				if (pkt->bytes >= l2fw_xor_threshold) {
+					newpkt = eth_l2fw_copy_packet_withXor(pkt);
+					if (newpkt)
+						status = mv_eth_l2fw_tx(newpkt, new_pp, 1, rx_desc);
+					else
+						status = MV_ERROR;
+				} else {
+						newpkt = eth_l2fw_copy_packet_withoutXor(pkt);
+						if (newpkt)
+							status = mv_eth_l2fw_tx(newpkt, new_pp, 0, rx_desc);
+						else
+							status = MV_ERROR;
+				}
+		}
+		if (status == MV_OK) {
+			mvOsCacheLineInv(NULL, rx_desc);
+			/* we do not need the pkt , we do not do anything with it*/
+			if  ((ppl2fw->cmd	== COPY_AND_SWAP) && !(espEnabled))
+				mv_eth_pool_put(pool, pkt);
+			continue;
+		} else if (status == MV_DROPPED) {
+			mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
+			if ((ppl2fw->cmd	== COPY_AND_SWAP) && !(espEnabled))
+				mv_eth_pool_put(pool, newpkt);
+
+			continue;
+		} else if (status == MV_ERROR) {
+			printk(KERN_INFO "MV_ERROR in %s\n", __func__);
+			mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
+		}
+
+	} /* of while */
+	/* Update RxQ management counters */
+	mvOsCacheIoSync();
+
+	mvNetaRxqDescNumUpdate(pp->port, rxq, rx_done, rx_filled);
+
+	return rx_done;
+}
+
+#ifdef CONFIG_MV_ETH_L2FW
+int __devinit mv_l2fw_init(void)
+{
+	int size, port;
+	MV_U32 bytes;
+	MV_U32 regVal;
+	mv_eth_ports_l2fw_num = mvCtrlEthMaxPortGet();
+	mvOsPrintf("in %s: mv_eth_ports_l2fw_num=%d\n", __func__, mv_eth_ports_l2fw_num);
+	size = mv_eth_ports_l2fw_num * sizeof(struct eth_port_l2fw *);
+	mv_eth_ports_l2fw = mvOsMalloc(size);
+	if (!mv_eth_ports_l2fw)
+		goto oom;
+	memset(mv_eth_ports_l2fw, 0, size);
+	for (port = 0; port < mv_eth_ports_l2fw_num; port++) {
+		mv_eth_ports_l2fw[port] =
+			mvOsMalloc(sizeof(struct eth_port_l2fw));
+		if (!mv_eth_ports_l2fw[port])
+			goto oom1;
+		mv_eth_ports_l2fw[port]->cmd    = L2FW_DISABLE;
+		mv_eth_ports_l2fw[port]->txPort = -1;
+	}
+
+	bytes = sizeof(L2FW_RULE *) * L2FW_HASH_SIZE;
+	l2fw_jhash_iv = mvOsRand();
+
+	l2fw_hash = (L2FW_RULE **)mvOsMalloc(bytes);
+	if (l2fw_hash == NULL) {
+		mvOsPrintf("l2fw hash: not enough memory\n");
+		return MV_NO_RESOURCE;
+	}
+
+	mvOsMemset(l2fw_hash, 0, bytes);
+
+	mvOsPrintf("L2FW hash init %d entries, %d bytes\n", L2FW_HASH_SIZE, bytes);
+	regVal = 0;
+#ifdef CONFIG_MV_ETH_L2SEC
+	cesa_init();
+#endif
+
+#ifdef CONFIG_MV_INCLUDE_XOR
+	setXorDesc();
+#endif
+	return 0;
+oom:
+	mvOsPrintf("%s: out of memory in L2FW initialization\n", __func__);
+oom1:
+	mvOsFree(mv_eth_ports_l2fw);
+	return -ENOMEM;
+
+}
+#endif
+
+module_init(mv_l2fw_init);
+
+MODULE_AUTHOR("Rami Rosen");
+MODULE_DESCRIPTION("l2fw module");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2fw.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2fw.h
new file mode 100755
index 0000000..c25ef58
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2fw.h
@@ -0,0 +1,40 @@
+/* l2fw/mv_eth_l2fw.h */
+
+#ifndef L2FW_MV_ETH_L2FW_H
+#define L2FW_MV_ETH_L2FW_H
+
+#include "mvOs.h"
+#include "mv_neta/net_dev/mv_netdev.h"
+
+#define	L2FW_HASH_SIZE   (1 << 17)
+extern int espEnabled;
+
+struct eth_port_l2fw {
+	int cmd;
+	int txPort;
+};
+
+typedef struct l2fw_rule {
+	MV_U32 srcIP;
+	MV_U32 dstIP;
+	MV_U8 port;
+	struct l2fw_rule *next;
+} L2FW_RULE;
+
+
+
+void l2fw(int cmd, int rx_port, int tx_port);
+void l2fw_xor(int threshold);
+MV_STATUS l2fw_add(MV_U32 srcIP, MV_U32 dstIP, int port);
+MV_STATUS l2fw_add_ip(const char *buf);
+void l2fw_esp_show(void);
+void l2fw_esp_set(int enableEsp);
+void l2fw_flush(void);
+void l2fw_dump(void);
+void l2fw_show_numHashEntries(void);
+void l2fw_stats(void);
+void l2fw_mode_show(void);
+void l2fw_mode(int mode);
+
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2sec.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2sec.c
new file mode 100755
index 0000000..a6c1dec
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2sec.c
@@ -0,0 +1,497 @@
+/* mv_eth_l2sec.c */
+
+#include "mv_eth_l2sec.h"
+
+static inline MV_STATUS mv_eth_cesa_l2fw_tx(struct eth_pbuf *pkt, struct eth_port *pp)
+{
+	struct neta_tx_desc *tx_desc;
+	u32 tx_cmd = 0;
+	struct tx_queue *txq_ctrl;
+
+	/* assigning different txq for each rx port , to avoid waiting on the
+	same txq lock when traffic on several rx ports are destined to the same
+	outgoing interface */
+	int txq = 0;
+	txq_ctrl = &pp->txq_ctrl[pp->txp * CONFIG_MV_ETH_TXQ + txq];
+	spin_lock(&txq_ctrl->queue_lock);
+
+	if (txq_ctrl->txq_count >= mv_ctrl_txdone)
+		mv_eth_txq_done(pp, txq_ctrl);
+	/* Get next descriptor for tx, single buffer, so FIRST & LAST */
+	tx_desc = mv_eth_tx_desc_get(txq_ctrl, 1);
+	if (tx_desc == NULL) {
+		/* printk("tx_desc == NULL pp->port=%d in %s\n", pp->port, ,__func__); */
+		spin_unlock(&txq_ctrl->queue_lock);
+		/* No resources: Drop */
+		pp->dev->stats.tx_dropped++;
+		return MV_DROPPED;
+	}
+	txq_ctrl->txq_count++;
+
+	tx_cmd |= NETA_TX_BM_ENABLE_MASK | NETA_TX_BM_POOL_ID_MASK(pkt->pool);
+	txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = (u32) NULL;
+	mv_eth_shadow_inc_put(txq_ctrl);
+
+	tx_desc->command = tx_cmd | NETA_TX_L4_CSUM_NOT |
+		NETA_TX_FLZ_DESC_MASK | NETA_TX_F_DESC_MASK
+		| NETA_TX_L_DESC_MASK |
+		NETA_TX_PKT_OFFSET_MASK(pkt->offset + MV_ETH_MH_SIZE);
+
+	tx_desc->dataSize    = pkt->bytes;
+	tx_desc->bufPhysAddr = pkt->physAddr;
+	mv_eth_tx_desc_flush(tx_desc);
+	mvNetaTxqPendDescAdd(pp->port, pp->txp, 0, 1);
+	spin_unlock(&txq_ctrl->queue_lock);
+	return MV_OK;
+}
+
+static inline void nfp_sec_complete_out(unsigned long data)
+
+{
+	MV_NFP_SEC_CESA_PRIV_L2FW *nfp_sec_cesa_priv = (MV_NFP_SEC_CESA_PRIV_L2FW *)data;		MV_U32            ifout;
+	MV_PKT_INFO       *pkt;
+	MV_BUF_INFO       *pBuf;
+	struct eth_port   *pp;
+	struct eth_pbuf   *pPkt;
+	int oldOfsset;
+	MV_STATUS status = MV_FAIL;
+	static int counterOfFailed = 0;
+	if (!nfp_sec_cesa_priv) {
+		printk(KERN_INFO "nfp_sec_cesa_priv is NULL in %s\n", __func__);
+		return;
+	}
+	ifout = nfp_sec_cesa_priv->ifout;
+
+	pkt = nfp_sec_cesa_priv->pPktInfo;
+	if (!pkt) {
+		printk(KERN_INFO "pPktInfo is NULL in %s\n", __func__);
+		return;
+	}
+	pBuf = pkt->pFrags;
+	if (!pBuf) {
+		printk(KERN_INFO "pBuf is NULL in %s\n", __func__);
+		return;
+	}
+	pPkt = nfp_sec_cesa_priv->pPkt;
+	if (!pPkt) {
+		printk(KERN_INFO "!pPkt) in %s\n", __func__);
+		return;
+	}
+	pPkt->bytes    = pBuf->dataSize;
+	pPkt->bytes += MV_NFP_SEC_ESP_OFFSET;
+	oldOfsset      = pPkt->offset;
+	pPkt->offset   = pPkt->offset - (sizeof(MV_ESP_HEADER) + sizeof(MV_IP_HEADER) + MV_CESA_AES_BLOCK_SIZE);
+
+	pp     = mv_eth_ports[ifout];
+
+	status = 	mv_eth_cesa_l2fw_tx(pPkt, pp);
+	if (status == MV_DROPPED)
+		counterOfFailed++;
+	 else
+		pPkt->offset = oldOfsset;
+}
+
+int l2fw_set_cesa_chan(int port, int cesaChan)
+{
+//	struct eth_port *pp;
+	printk(KERN_INFO "setting cesaChan to %d for port=%d \n", cesaChan, port);
+	if ((cesaChan != CESA_0) && (cesaChan != CESA_1))  {
+		printk(KERN_INFO "non permitted value for CESA channel \n");
+		return -EINVAL;
+	}
+//	pp = mv_eth_ports[port];
+//	if (pp)
+//		pp->cesaChan = cesaChan;
+	cesaChanPort[port] = cesaChan;
+	return 0;
+}
+
+MV_STATUS my_mvSysCesaInit(int numOfSession, int queueDepth, void *osHandle)
+{
+	MV_CESA_HAL_DATA halData;
+	MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1];
+	MV_STATUS status;
+	MV_U8 chan;
+
+	status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1);
+
+	if (status == MV_OK) {
+		for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+			status = mvCesaTdmaWinInit(chan, addrWinMap);
+			if (status != MV_OK) {
+				mvOsPrintf("Error, unable to initialize CESA windows for channel(%d)\n", chan);
+				break;
+			}
+			halData.sramPhysBase[chan] = (MV_ULONG)mv_crypto_virt_base_get(chan);
+			halData.sramVirtBase[chan] = (MV_U8 *)mv_crypto_virt_base_get(chan);
+			halData.sramOffset[chan] = 0;
+		}
+
+		if (status == MV_OK) {
+		halData.ctrlModel = mvCtrlModelGet();
+		halData.ctrlRev = mvCtrlRevGet();
+			status = mvCesaHalInit(numOfSession, queueDepth,
+					osHandle, &halData);
+	}
+	}
+
+	return status;
+}
+
+void cesaStart(void)
+{
+	int bufNum, bufSize;
+	int i, j, idx;
+	MV_CESA_MBUF *pMbufSrc_0, *pMbufDst_0;
+	MV_BUF_INFO *pFragsSrc_0, *pFragsDst_0;
+	char *pBuf_0;
+
+	MV_CESA_MBUF *pMbufSrc_1, *pMbufDst_1;
+	MV_BUF_INFO *pFragsSrc_1, *pFragsDst_1;
+	char *pBuf_1;
+
+	printk(KERN_INFO "in %s\n", __func__);
+
+	cesaCmdArray_0 = 	mvOsMalloc(sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE);
+
+	if (cesaCmdArray_0 == NULL) {
+		mvOsPrintf("Can't allocate %d bytes of memory\n",
+			   (int)(sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE));
+		return;
+	}
+	memset(cesaCmdArray_0, 0, sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE);
+	/* CESA_DEF_BUF_NUM */
+	bufNum    =  1;
+	/* CESA_DEF_BUF_SIZE */
+	bufSize   = 1500;
+
+	pMbufSrc_0  = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	pFragsSrc_0 = mvOsMalloc(sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	pMbufDst_0  = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	pFragsDst_0 = mvOsMalloc(sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	if ((pMbufSrc_0 == NULL) || (pFragsSrc_0 == NULL) ||
+		(pMbufDst_0 == NULL) || (pFragsDst_0 == NULL)) {
+		mvOsPrintf(" Can't malloc Src and Dst pMbuf and pFrags structures.\n");
+		return;
+	}
+
+	memset(pMbufSrc_0,  0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	memset(pFragsSrc_0, 0, sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	memset(pMbufDst_0,  0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	memset(pFragsDst_0, 0, sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	idx = 0;
+	for (i = 0; i < CESA_DEF_REQ_SIZE; i++) {
+		pBuf_0 = mvOsIoCachedMalloc(cesaOSHandle, bufSize * bufNum * 2,
+					  &cesaBufs_0[i].bufPhysAddr, &cesaBufs_0[i].memHandle);
+		if (pBuf_0 == NULL) {
+			mvOsPrintf("testStart: Can't malloc %d bytes for pBuf\n", bufSize * bufNum * 2);
+			return;
+		}
+
+		memset(pBuf_0, 0, bufSize * bufNum * 2);
+		mvOsCacheFlush(cesaOSHandle, pBuf_0, bufSize * bufNum * 2);
+		if (pBuf_0 == NULL) {
+			mvOsPrintf("Can't allocate %d bytes for req_%d buffers\n",
+				   bufSize * bufNum * 2, i);
+			return;
+		}
+
+		cesaBufs_0[i].bufVirtPtr = (MV_U8 *) pBuf_0;
+		cesaBufs_0[i].bufSize = bufSize * bufNum * 2;
+
+		cesaCmdArray_0[i].pSrc = &pMbufSrc_0[i];
+		cesaCmdArray_0[i].pSrc->pFrags = &pFragsSrc_0[idx];
+		cesaCmdArray_0[i].pSrc->numFrags = bufNum;
+		cesaCmdArray_0[i].pSrc->mbufSize = 0;
+
+		cesaCmdArray_0[i].pDst = &pMbufDst_0[i];
+		cesaCmdArray_0[i].pDst->pFrags = &pFragsDst_0[idx];
+		cesaCmdArray_0[i].pDst->numFrags = bufNum;
+		cesaCmdArray_0[i].pDst->mbufSize = 0;
+
+		for (j = 0; j < bufNum; j++) {
+			cesaCmdArray_0[i].pSrc->pFrags[j].bufVirtPtr = (MV_U8 *) pBuf_0;
+			cesaCmdArray_0[i].pSrc->pFrags[j].bufSize = bufSize;
+			pBuf_0 += bufSize;
+			cesaCmdArray_0[i].pDst->pFrags[j].bufVirtPtr = (MV_U8 *) pBuf_0;
+
+			cesaCmdArray_0[i].pDst->pFrags[j].bufSize = bufSize;
+			pBuf_0 += bufSize;
+		}
+		idx += bufNum;
+	}
+
+	cesaMbufArray_0 = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	if (cesaMbufArray_0 == NULL) {
+		mvOsPrintf("Can't allocate %d bytes of memory\n",
+			   (int)(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE));
+		return;
+	}
+	memset(cesaMbufArray_0, 0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+
+	cesaPrivArray_0 = mvOsMalloc(sizeof(MV_NFP_SEC_CESA_PRIV_L2FW) * (CESA_DEF_REQ_SIZE + MV_NFP_SEC_REQ_Q_SIZE));
+	memset(cesaPrivArray_0, 0, sizeof(MV_NFP_SEC_CESA_PRIV_L2FW) * (CESA_DEF_REQ_SIZE + MV_NFP_SEC_REQ_Q_SIZE));
+
+	/* second engine */
+	cesaCmdArray_1 = 	mvOsMalloc(sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE);
+
+	if (cesaCmdArray_1 == NULL) {
+		mvOsPrintf("Can't allocate %d bytes of memory\n",
+			   (int)(sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE));
+		return;
+	}
+	memset(cesaCmdArray_1, 0, sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE);
+
+	/* CESA_DEF_BUF_NUM */
+	bufNum    =  1;
+	/* CESA_DEF_BUF_SIZE */
+	bufSize   = 1500;
+
+	pMbufSrc_1  = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	pFragsSrc_1 = mvOsMalloc(sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	pMbufDst_1  = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	pFragsDst_1 = mvOsMalloc(sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	if ((pMbufSrc_1 == NULL) || (pFragsSrc_1 == NULL) || (pMbufDst_1 == NULL)
+		|| (pFragsDst_1 == NULL)) {
+		mvOsPrintf(" Can't malloc Src and Dst pMbuf and pFrags structures.\n");
+		return;
+	}
+
+	memset(pMbufSrc_1,  0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	memset(pFragsSrc_1, 0, sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	memset(pMbufDst_1,  0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	memset(pFragsDst_1, 0, sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	idx = 0;
+	for (i = 0; i < CESA_DEF_REQ_SIZE; i++) {
+		pBuf_1 = mvOsIoCachedMalloc(cesaOSHandle, bufSize * bufNum * 2,
+					  &cesaBufs_1[i].bufPhysAddr, &cesaBufs_1[i].memHandle);
+		if (pBuf_1 == NULL) {
+			mvOsPrintf("testStart: Can't malloc %d bytes for pBuf\n", bufSize * bufNum * 2);
+			return;
+		}
+
+		memset(pBuf_1, 0, bufSize * bufNum * 2);
+		mvOsCacheFlush(cesaOSHandle, pBuf_1, bufSize * bufNum * 2);
+		if (pBuf_1 == NULL) {
+			mvOsPrintf("Can't allocate %d bytes for req_%d buffers\n",
+				   bufSize * bufNum * 2, i);
+			return;
+		}
+
+		cesaBufs_1[i].bufVirtPtr = (MV_U8 *) pBuf_1;
+		cesaBufs_1[i].bufSize = bufSize * bufNum * 2;
+
+		cesaCmdArray_1[i].pSrc = &pMbufSrc_1[i];
+		cesaCmdArray_1[i].pSrc->pFrags = &pFragsSrc_1[idx];
+		cesaCmdArray_1[i].pSrc->numFrags = bufNum;
+		cesaCmdArray_1[i].pSrc->mbufSize = 0;
+
+		cesaCmdArray_1[i].pDst = &pMbufDst_1[i];
+		cesaCmdArray_1[i].pDst->pFrags = &pFragsDst_1[idx];
+		cesaCmdArray_1[i].pDst->numFrags = bufNum;
+		cesaCmdArray_1[i].pDst->mbufSize = 0;
+
+		for (j = 0; j < bufNum; j++) {
+			cesaCmdArray_1[i].pSrc->pFrags[j].bufVirtPtr = (MV_U8 *) pBuf_1;
+			cesaCmdArray_1[i].pSrc->pFrags[j].bufSize = bufSize;
+			pBuf_1 += bufSize;
+			cesaCmdArray_1[i].pDst->pFrags[j].bufVirtPtr = (MV_U8 *) pBuf_1;
+
+			cesaCmdArray_1[i].pDst->pFrags[j].bufSize = bufSize;
+			pBuf_1 += bufSize;
+		}
+		idx += bufNum;
+	}
+
+	cesaMbufArray_1 = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	if (cesaMbufArray_1 == NULL) {
+		mvOsPrintf("Can't allocate %d bytes of memory\n",
+			   (int)(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE));
+		return;
+	}
+	memset(cesaMbufArray_1, 0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+
+	cesaPrivArray_1 = mvOsMalloc(sizeof(MV_NFP_SEC_CESA_PRIV_L2FW) * (CESA_DEF_REQ_SIZE + MV_NFP_SEC_REQ_Q_SIZE));
+	memset(cesaPrivArray_1, 0, sizeof(MV_NFP_SEC_CESA_PRIV_L2FW) * (CESA_DEF_REQ_SIZE + MV_NFP_SEC_REQ_Q_SIZE));
+
+	pPktInfoNewArray_0 = mvOsMalloc(sizeof(MV_PKT_INFO) * MV_NFP_SEC_REQ_Q_SIZE);
+
+	if (!pPktInfoNewArray_0) {
+		printk(KERN_INFO "mvOsMalloc() failed in %s\n", __func__);
+		return;
+	}
+
+	pBufInfoArray_0 = mvOsMalloc(sizeof(MV_BUF_INFO) * MV_NFP_SEC_REQ_Q_SIZE);
+	if (!pBufInfoArray_0) {
+		printk(KERN_INFO "could not allocate MV_BUF_INFO in %s\n", __func__);
+		return;
+	}
+
+	pPktInfoNewArray_1 = mvOsMalloc(sizeof(MV_PKT_INFO) * MV_NFP_SEC_REQ_Q_SIZE);
+
+	if (!pPktInfoNewArray_1) {
+		printk(KERN_INFO "mvOsMalloc() failed in %s\n", __func__);
+		return;
+	}
+	pBufInfoArray_1 = mvOsMalloc(sizeof(MV_BUF_INFO) * MV_NFP_SEC_REQ_Q_SIZE);
+	if (!pBufInfoArray_0) {
+		printk(KERN_INFO "could not allocate MV_BUF_INFO in %s\n", __func__);
+		return;
+	}
+	printk(KERN_INFO "start finished in %s\n", __func__);
+}
+
+static irqreturn_t nfp_sec_interrupt_handler_0(int irq, void *arg)
+{
+	MV_CESA_RESULT  	result;
+	MV_STATUS           status;
+	MV_U8 chan = 0;
+
+    MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+
+	while (1) {
+	/* Get Ready requests */
+
+	status = mvCesaReadyGet(chan, &result);
+	if (status != MV_OK)
+		break;
+
+	nfp_sec_complete_out((unsigned long)((MV_NFP_SEC_CESA_PRIV_L2FW *)result.pReqPrv));
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t nfp_sec_interrupt_handler_1(int irq, void *arg)
+{
+	MV_CESA_RESULT  	result;
+	MV_STATUS           status;
+	MV_U8 chan = 1;
+    MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+	while (1) {
+	/* Get Ready requests */
+	status = mvCesaReadyGet(chan, &result);
+	if (status != MV_OK)
+		break;
+
+	nfp_sec_complete_out((unsigned long)((MV_NFP_SEC_CESA_PRIV_L2FW *)result.pReqPrv));
+	}
+
+	return IRQ_HANDLED;
+}
+
+void openCesaSession(void)
+{
+	unsigned char sha1Key[]  = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+								0x24, 0x68, 0xac, 0xe0, 0x24, 0x68, 0xac, 0xe0,
+								0x13, 0x57, 0x9b, 0xdf};
+	/* sizeof(cryptoKey) should be 128 for AES-128 */
+	unsigned char cryptoKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+									0x02, 0x46, 0x8a, 0xce, 0x13, 0x57, 0x9b, 0xdf};
+
+	int i;
+	MV_NFP_SEC_SA_ENTRY sa;
+	MV_CESA_OPEN_SESSION os;
+	unsigned short digest_size = 0;
+	memset(&sa, 0, sizeof(MV_NFP_SEC_SA_ENTRY));
+	memset(&os, 0, sizeof(MV_CESA_OPEN_SESSION));
+
+	os.operation 		= MV_CESA_MAC_THEN_CRYPTO;
+	os.cryptoAlgorithm  = MV_CESA_CRYPTO_AES;
+	os.macMode  		= MV_CESA_MAC_HMAC_SHA1;
+	digest_size 		= MV_CESA_SHA1_DIGEST_SIZE;
+	os.cryptoMode 		= MV_CESA_CRYPTO_ECB;
+	for (i = 0; i < sizeof(cryptoKey); i++)
+		os.cryptoKey[i] = cryptoKey[i];
+
+	os.cryptoKeyLength = sizeof(cryptoKey);
+
+	for (i = 0; i < sizeof(sha1Key); i++)
+		os.macKey[i] = sha1Key[i];
+	os.macKeyLength = sizeof(sha1Key);
+	os.digestSize = digest_size;
+
+	if (mvCesaSessionOpen(&os, (short *)&(sa.sid)))
+		printk(KERN_INFO "mvCesaSessionOpen failed in %s\n", __func__);
+}
+
+void l2fw_esp_set(int enableEsp)
+{
+	if (enableEsp) {
+		openCesaSession();
+		printk(KERN_INFO "calling cesaStart() in %s\n", __func__);
+		cesaStart();
+	} else
+		printk(KERN_INFO "enableEsp=%d disabling ESP in %s\n", enableEsp, __func__);
+	espEnabled = enableEsp;
+}
+
+int cesa_init(void)
+{
+	u8 chan = 0;
+	int i;
+	const char *irq_str[] = {"cesa0", "cesa1"};
+	printk(KERN_INFO "in %s\n", __func__);
+	for (i = 0; i < 2; i++)
+		spin_lock_init(&cesa_lock[i]);
+	if (mvCtrlPwrClckGet(CESA_UNIT_ID, 0) == MV_FALSE)
+		return 0;
+	if (MV_OK != my_mvSysCesaInit(1, 256, NULL)) {
+		printk(KERN_INFO "%s,%d: mvCesaInit Failed. \n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	/* clear and unmask Int */
+	MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+	MV_REG_WRITE(MV_CESA_ISR_MASK_REG(chan), MV_CESA_CAUSE_ACC_DMA_MASK);
+	if (request_irq(CESA_IRQ(0), nfp_sec_interrupt_handler_0,
+							(IRQF_DISABLED) , irq_str[chan], NULL)) {
+				printk(KERN_INFO "%s,%d: cannot assign irq %x\n", __FILE__, __LINE__, CESA_IRQ(chan));
+		return EINVAL;
+	}
+
+	chan = 1;
+	MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+	MV_REG_WRITE(MV_CESA_ISR_MASK_REG(chan), MV_CESA_CAUSE_ACC_DMA_MASK);
+
+	if (request_irq(CESA_IRQ(1), nfp_sec_interrupt_handler_1,
+							(IRQF_DISABLED) , irq_str[chan], NULL)) {
+				printk(KERN_INFO "%s,%d: cannot assign irq %x\n", __FILE__, __LINE__, CESA_IRQ(chan));
+		return EINVAL;
+		}
+
+	atomic_set(&req_count[0], 0);
+	atomic_set(&req_count[1], 0);
+	mvOsPrintf("MV_CESA_TDMA_CTRL_REG address 0 %08x\n\n", MV_CESA_TDMA_CTRL_REG(0));
+	mvOsPrintf("MV_CESA_TDMA_CTRL_REG address 1 %08x\n\n", MV_CESA_TDMA_CTRL_REG(1));
+	mvOsPrintf("MV_CESA_TDMA_CTRL_REG(0)  %08x\n",
+		MV_REG_READ(MV_CESA_TDMA_CTRL_REG(0)));
+	mvOsPrintf("MV_CESA_TDMA_CTRL_REG(1)  %08x\n",
+		MV_REG_READ(MV_CESA_TDMA_CTRL_REG(1)));
+
+	memset(&sa, 0, sizeof(MV_NFP_SEC_SA_ENTRY));
+	sa.digestSize = MV_CESA_SHA1_DIGEST_SIZE;
+	sa.ivSize = MV_CESA_AES_BLOCK_SIZE;
+	sa.spi = 3;
+
+	sa.tunProt = MV_NFP_SEC_TUNNEL;
+	sa.encap   = MV_NFP_SEC_ESP;
+	sa.seqNum  = 4;
+	sa.tunnelHdr.sIp = 0x6400A8C0;
+	sa.tunnelHdr.dIp = 0x6401A8C0;
+	sa.tunnelHdr.outIfIndex = 0;
+	sa.lifeTime = 0;
+
+	sa.secOp = MV_NFP_SEC_ENCRYPT;
+	strcpy(sa.tunnelHdr.dstMac, "aabbccddeeff");
+	strcpy(sa.tunnelHdr.srcMac, "abacadaeafaa");
+
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2sec.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2sec.h
new file mode 100755
index 0000000..f77e7fe
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/l2fw/mv_eth_l2sec.h
@@ -0,0 +1,493 @@
+/* l2sec/mv_eth_l2sec.h */
+
+#ifndef L2SEC_MV_ETH_L2SEC_H
+#define L2SEC_MV_ETH_L2SEC_H
+
+#include "mvOs.h"
+#include "cesa/mvCesa.h"
+
+#include "mv_neta/l2fw/mv_eth_l2fw.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mv_neta/net_dev/mv_netdev.h"
+
+/* Taken from mvNfpSec.h */
+/* IPSec defines */
+#define MV_NFP_SEC_MAX_PACKET		1540
+#define MV_NFP_SEC_ENC_BLOCK_SIZE	16
+
+#define MV_NFP_SEC_ESP_OFFSET		34
+
+/* IPSec Enumerators */
+typedef enum {
+	MV_NFP_SEC_TUNNEL = 0,
+	MV_NFP_SEC_TRANSPORT,
+} MV_NFP_SEC_PROT;
+
+typedef enum {
+	MV_NFP_SEC_ESP = 0,
+	MV_NFP_SEC_AH,
+} MV_NFP_SEC_ENCAP;
+
+
+typedef enum {
+	MV_NFP_SEC_ENCRYPT = 0,
+	MV_NFP_SEC_DECRYPT,
+} MV_NFP_SEC_OP;
+
+typedef struct _mv_nfp_sa_stats {
+	MV_U32 encrypt;
+	MV_U32 decrypt;
+	MV_U32 rejected;	/* slow path */
+	MV_U32 dropped;		/* packet drop */
+	MV_U32 bytes;
+} MV_NFP_SA_STATS;
+
+/* IPSec Structures */
+typedef struct _mv_nfp_sec_tunnel_hdr {
+	MV_U32 sIp;		/*  BE */
+	MV_U32 dIp;		/* BE */
+	/* dstMac should be 2 byte aligned */
+	MV_U8 dstMac[MV_MAC_ADDR_SIZE];	/* BE */
+	MV_U8 srcMac[MV_MAC_ADDR_SIZE];	/* BE */
+	MV_U8 outIfIndex;
+} MV_NFP_SEC_TUNNEL_HDR;
+
+typedef struct _mv_nfp_sec_sa_entry {
+	MV_U32 spi;		/* BE */
+	MV_NFP_SEC_PROT tunProt;
+	MV_NFP_SEC_ENCAP encap;
+	MV_U16 sid;
+	MV_U32 seqNum;		/* LE  */
+	MV_NFP_SEC_TUNNEL_HDR tunnelHdr;
+	MV_U32 lifeTime;
+	MV_U8 ivSize;
+	MV_U8 cipherBlockSize;
+	MV_U8 digestSize;
+	MV_NFP_SEC_OP secOp;
+	MV_NFP_SA_STATS stats;
+} MV_NFP_SEC_SA_ENTRY;
+
+typedef struct _mv_nfp_sec_cesa_priv {
+	MV_NFP_SEC_SA_ENTRY *pSaEntry;
+	MV_PKT_INFO *pPktInfo;
+	MV_U8 orgDigest[MV_CESA_MAX_DIGEST_SIZE];
+	MV_CESA_COMMAND *pCesaCmd;
+} MV_NFP_SEC_CESA_PRIV;
+
+int cesaChanPort[CONFIG_MV_ETH_PORTS_NUM];
+
+#define CESA_0    0
+#define CESA_1    1
+/* for future - handle by CPU */
+#define CESA_NONE 2
+
+#define MV_NFP_SEC_REQ_Q_SIZE 1000
+#define CESA_DEF_REQ_SIZE       (256*4)
+int counterNoResources[4]  = {0, 0, 0, 0};
+spinlock_t cesa_lock[2];
+
+extern u32 mv_crypto_virt_base_get(u8 chan);
+static MV_PKT_INFO *pPktInfoNewArray_0;
+static MV_PKT_INFO *pPktInfoNewArray_1;
+static MV_BUF_INFO *pBufInfoArray_0;
+static MV_BUF_INFO *pBufInfoArray_1;
+
+MV_BUF_INFO cesaBufs_0[CESA_DEF_REQ_SIZE];
+MV_BUF_INFO cesaBufs_1[CESA_DEF_REQ_SIZE];
+
+static int cesaPrivIndx_0 = 0;
+static int cesaPrivIndx_1 = 0;
+
+static int cesaCmdIndx_0 = 0;
+static int cesaCmdIndx_1 = 0;
+
+typedef struct _mv_nfp_sec_cesa_priv_l2fw {
+	MV_NFP_SEC_SA_ENTRY *pSaEntry;
+	MV_PKT_INFO *pPktInfo;
+	MV_U8 orgDigest[MV_CESA_MAX_DIGEST_SIZE];
+	MV_CESA_COMMAND *pCesaCmd;
+	struct eth_pbuf *pPkt;
+	int ifout;
+	int ownerId;
+	int inPort;
+} MV_NFP_SEC_CESA_PRIV_L2FW;
+
+MV_NFP_SEC_CESA_PRIV_L2FW *cesaPrivArray_0;
+MV_NFP_SEC_CESA_PRIV_L2FW *cesaPrivArray_1;
+
+void *cesaOSHandle = NULL;
+static MV_CESA_MBUF *cesaMbufArray_0;
+static MV_CESA_MBUF *cesaMbufArray_1;
+
+static MV_CESA_COMMAND *cesaCmdArray_0;
+static MV_CESA_COMMAND *cesaCmdArray_1;
+
+
+static MV_NFP_SEC_SA_ENTRY sa;
+atomic_t req_count[2];
+int l2fw_set_cesa_chan(int port, int cesaChan);
+int cesa_init(void);
+
+
+/* from mv_hal/eth/gbe/mvEthRegs.h */
+
+/* Tx descriptor bits */
+#define ETH_TX_ERROR_CODE_OFFSET            1
+#define ETH_TX_ERROR_CODE_MASK              (3<<ETH_TX_ERROR_CODE_OFFSET)
+#define ETH_TX_LATE_COLLISION_ERROR         (0<<ETH_TX_ERROR_CODE_OFFSET)
+#define ETH_TX_UNDERRUN_ERROR               (1<<ETH_TX_ERROR_CODE_OFFSET)
+#define ETH_TX_EXCESSIVE_COLLISION_ERROR    (2<<ETH_TX_ERROR_CODE_OFFSET)
+
+#define ETH_TX_LLC_SNAP_FORMAT_BIT          9
+#define ETH_TX_LLC_SNAP_FORMAT_MASK         (1<<ETH_TX_LLC_SNAP_FORMAT_BIT)
+
+#define ETH_TX_IP_FRAG_BIT                  10
+#define ETH_TX_IP_FRAG_MASK                 (1<<ETH_TX_IP_FRAG_BIT)
+#define ETH_TX_IP_FRAG                      (0<<ETH_TX_IP_FRAG_BIT)
+#define ETH_TX_IP_NO_FRAG                   (1<<ETH_TX_IP_FRAG_BIT)
+
+#define ETH_TX_IP_HEADER_LEN_OFFSET         11
+#define ETH_TX_IP_HEADER_LEN_ALL_MASK       (0xF<<ETH_TX_IP_HEADER_LEN_OFFSET)
+#define ETH_TX_IP_HEADER_LEN_MASK(len)      ((len)<<ETH_TX_IP_HEADER_LEN_OFFSET)
+
+#define ETH_TX_VLAN_TAGGED_FRAME_BIT        15
+#define ETH_TX_VLAN_TAGGED_FRAME_MASK       (1<<ETH_TX_VLAN_TAGGED_FRAME_BIT)
+
+#define ETH_TX_L4_TYPE_BIT                  16
+#define ETH_TX_L4_TCP_TYPE                  (0<<ETH_TX_L4_TYPE_BIT)
+#define ETH_TX_L4_UDP_TYPE                  (1<<ETH_TX_L4_TYPE_BIT)
+
+#define ETH_TX_GENERATE_L4_CHKSUM_BIT       17
+#define ETH_TX_GENERATE_L4_CHKSUM_MASK      (1<<ETH_TX_GENERATE_L4_CHKSUM_BIT)
+
+#define ETH_TX_GENERATE_IP_CHKSUM_BIT       18
+#define ETH_TX_GENERATE_IP_CHKSUM_MASK      (1<<ETH_TX_GENERATE_IP_CHKSUM_BIT)
+
+#define ETH_TX_ZERO_PADDING_BIT             19
+#define ETH_TX_ZERO_PADDING_MASK            (1<<ETH_TX_ZERO_PADDING_BIT)
+
+#define ETH_TX_LAST_DESC_BIT                20
+#define ETH_TX_LAST_DESC_MASK               (1<<ETH_TX_LAST_DESC_BIT)
+
+#define ETH_TX_FIRST_DESC_BIT               21
+#define ETH_TX_FIRST_DESC_MASK              (1<<ETH_TX_FIRST_DESC_BIT)
+
+#define ETH_TX_GENERATE_CRC_BIT             22
+#define ETH_TX_GENERATE_CRC_MASK            (1<<ETH_TX_GENERATE_CRC_BIT)
+
+#define ETH_TX_ENABLE_INTERRUPT_BIT         23
+#define ETH_TX_ENABLE_INTERRUPT_MASK        (1<<ETH_TX_ENABLE_INTERRUPT_BIT)
+
+#define ETH_TX_AUTO_MODE_BIT                30
+#define ETH_TX_AUTO_MODE_MASK               (1<<ETH_TX_AUTO_MODE_BIT)
+
+
+inline MV_VOID mvNfpSecBuildIPTunnel(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	MV_IP_HEADER *pIpHdr, *pIntIpHdr;
+	MV_U16 newIpTotalLength;
+
+	newIpTotalLength = pPktInfo->pFrags[0].dataSize - sizeof(MV_802_3_HEADER);
+
+	pIpHdr = (MV_IP_HEADER *) (pPktInfo->pFrags[0].bufVirtPtr + sizeof(MV_802_3_HEADER));
+	pIntIpHdr = (MV_IP_HEADER *) ((MV_U8 *) (pIpHdr) + sizeof(MV_IP_HEADER) + sizeof(MV_ESP_HEADER) +
+				      pSAEntry->ivSize);
+
+	/* TBD - review below settings in RFC */
+	pIpHdr->version = 0x45;
+	pIpHdr->tos = 0;
+	pIpHdr->checksum = 0;
+	pIpHdr->totalLength = MV_16BIT_BE(newIpTotalLength);
+	pIpHdr->identifier = 0;
+	pIpHdr->fragmentCtrl = 0;
+	pIpHdr->ttl = pIntIpHdr->ttl - 1;
+	pIpHdr->protocol = MV_IP_PROTO_ESP;
+	pIpHdr->srcIP = pSAEntry->tunnelHdr.sIp;
+	pIpHdr->dstIP = pSAEntry->tunnelHdr.dIp;
+
+	pPktInfo->status = ETH_TX_IP_NO_FRAG | ETH_TX_GENERATE_IP_CHKSUM_MASK | (0x5 << ETH_TX_IP_HEADER_LEN_OFFSET);
+
+	return;
+}
+
+
+/* Append sequence number and spi, save some space for IV */
+inline MV_VOID mvNfpSecBuildEspHdr(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	MV_ESP_HEADER *pEspHdr;
+
+	pEspHdr = (MV_ESP_HEADER *) (pPktInfo->pFrags[0].bufVirtPtr + sizeof(MV_802_3_HEADER) + sizeof(MV_IP_HEADER));
+	pEspHdr->spi = pSAEntry->spi;
+	pSAEntry->seqNum = (pSAEntry->seqNum++);
+	pEspHdr->seqNum = MV_32BIT_BE(pSAEntry->seqNum);
+}
+
+inline MV_VOID mvNfpSecBuildMac(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	MV_802_3_HEADER *pMacHdr;
+
+	pMacHdr = (MV_802_3_HEADER *) ((MV_U8 *) (pPktInfo->pFrags[0].bufVirtPtr));
+	memcpy(pMacHdr, &pSAEntry->tunnelHdr.dstMac, 12);
+	pMacHdr->typeOrLen = 0x08;	/* stands for IP protocol code 16bit swapped */
+	return;
+}
+
+
+inline MV_STATUS mvSecEspProcess_0(struct eth_pbuf *pPkt, MV_PKT_INFO *pPktInfo,
+							MV_NFP_SEC_SA_ENTRY *pSAEntry, struct eth_port *newpp,
+							MV_U8 channel, int inPort)
+{
+	MV_CESA_COMMAND	*pCesaCmd;
+	MV_CESA_MBUF *pCesaMbuf;
+	MV_NFP_SEC_CESA_PRIV_L2FW *pCesaPriv;
+	MV_STATUS status;
+	MV_IP_HEADER *pIpHdr;
+	MV_BUF_INFO  *pBuf;
+
+	pCesaCmd  = &cesaCmdArray_0[cesaCmdIndx_0];
+	pCesaMbuf = &cesaMbufArray_0[cesaCmdIndx_0];
+	cesaCmdIndx_0++;
+
+	cesaCmdIndx_0 %= CESA_DEF_REQ_SIZE;
+	pCesaPriv = &cesaPrivArray_0[cesaPrivIndx_0++];
+
+	cesaPrivIndx_0 = cesaPrivIndx_0%(CESA_DEF_REQ_SIZE + MV_NFP_SEC_REQ_Q_SIZE);
+
+	pCesaPriv->pPktInfo = pPktInfo;
+	pCesaPriv->pSaEntry = pSAEntry;
+	pCesaPriv->pCesaCmd = pCesaCmd;
+
+	pCesaPriv->pPkt   = pPkt;
+	pCesaPriv->ifout  = newpp->port;
+	pCesaPriv->inPort = inPort;
+	/*
+	 *  Fix, encrypt/decrypt the IP payload only, --BK 20091027
+	 */
+	pBuf = pPktInfo->pFrags;
+	pIpHdr = (MV_IP_HEADER *)(pBuf->bufVirtPtr + sizeof(MV_802_3_HEADER));
+	pBuf->dataSize = MV_16BIT_BE(pIpHdr->totalLength) + sizeof(MV_802_3_HEADER);
+	/* after next command, pBuf->bufVirtPtr will point to ESP */
+	pBuf->bufVirtPtr += MV_NFP_SEC_ESP_OFFSET;
+	pBuf->bufPhysAddr += MV_NFP_SEC_ESP_OFFSET;
+	pBuf->dataSize -= MV_NFP_SEC_ESP_OFFSET;
+
+	pBuf->bufAddrShift -= MV_NFP_SEC_ESP_OFFSET;
+	pCesaMbuf->pFrags = pPktInfo->pFrags;
+	pCesaMbuf->numFrags = 1;
+	pCesaMbuf->mbufSize = pBuf->dataSize;
+
+	pCesaMbuf->pFrags->bufSize = pBuf->dataSize;
+
+	pCesaCmd->pReqPrv = (MV_VOID *)pCesaPriv;
+	pCesaCmd->sessionId = pSAEntry->sid;
+	pCesaCmd->pSrc = pCesaMbuf;
+	pCesaCmd->pDst = pCesaMbuf;
+	pCesaCmd->skipFlush = MV_TRUE;
+
+	/* Assume ESP */
+	pCesaCmd->cryptoOffset = sizeof(MV_ESP_HEADER) + pSAEntry->ivSize;
+	pCesaCmd->cryptoLength =  pBuf->dataSize - (sizeof(MV_ESP_HEADER)
+				  + pSAEntry->ivSize + pSAEntry->digestSize);
+	pCesaCmd->ivFromUser = 0; /* relevant for encode only */
+	pCesaCmd->ivOffset = sizeof(MV_ESP_HEADER);
+	pCesaCmd->macOffset = 0;
+	pCesaCmd->macLength = pBuf->dataSize - pSAEntry->digestSize;
+	if ((pCesaCmd->digestOffset != 0) && ((pCesaCmd->digestOffset%4)))  {
+		printk(KERN_INFO "pBuf->dataSize=%d pSAEntry->digestSize=%d in %s\n",
+			pBuf->dataSize, pSAEntry->digestSize, __func__);
+		printk(KERN_INFO "pCesaCmd->digestOffset=%d in %s\n",
+			pCesaCmd->digestOffset, __func__);
+	}
+	pCesaCmd->digestOffset = pBuf->dataSize - pSAEntry->digestSize ;
+
+	disable_irq(CESA_IRQ(channel));
+
+	status = mvCesaAction(channel, pCesaCmd);
+	enable_irq(CESA_IRQ(channel));
+	if (status != MV_OK) {
+		pSAEntry->stats.rejected++;
+		mvOsPrintf("%s: mvCesaAction failed %d\n", __func__, status);
+	}
+	return status;
+}
+
+inline MV_STATUS mvSecEspProcess_1(struct eth_pbuf *pPkt, MV_PKT_INFO *pPktInfo,
+						  MV_NFP_SEC_SA_ENTRY *pSAEntry, struct eth_port *newpp,
+						  MV_U8 channel, int inPort)
+
+{
+	MV_CESA_COMMAND	*pCesaCmd;
+	MV_CESA_MBUF *pCesaMbuf;
+	MV_NFP_SEC_CESA_PRIV_L2FW *pCesaPriv;
+	MV_STATUS status;
+	MV_IP_HEADER *pIpHdr;
+	MV_BUF_INFO  *pBuf;
+	pCesaCmd  = &cesaCmdArray_1[cesaCmdIndx_1];
+	pCesaMbuf = &cesaMbufArray_1[cesaCmdIndx_1];
+	cesaCmdIndx_1++;
+	cesaCmdIndx_1 %= CESA_DEF_REQ_SIZE;
+	pCesaPriv = &cesaPrivArray_1[cesaPrivIndx_1++];
+	cesaPrivIndx_1 = cesaPrivIndx_1%(CESA_DEF_REQ_SIZE + MV_NFP_SEC_REQ_Q_SIZE);
+
+	pCesaPriv->pPktInfo = pPktInfo;
+	pCesaPriv->pSaEntry = pSAEntry;
+	pCesaPriv->pCesaCmd = pCesaCmd;
+
+	pCesaPriv->pPkt   = pPkt;
+	pCesaPriv->ifout  = newpp->port;
+	pCesaPriv->inPort = inPort;
+	/*
+	 *  Fix, encrypt/decrypt the IP payload only, --BK 20091027
+	 */
+	pBuf = pPktInfo->pFrags;
+	pIpHdr = (MV_IP_HEADER *)(pBuf->bufVirtPtr + sizeof(MV_802_3_HEADER));
+	pBuf->dataSize = MV_16BIT_BE(pIpHdr->totalLength) + sizeof(MV_802_3_HEADER);
+	/* after next command, pBuf->bufVirtPtr will point to ESP */
+	pBuf->bufVirtPtr += MV_NFP_SEC_ESP_OFFSET;
+	pBuf->bufPhysAddr += MV_NFP_SEC_ESP_OFFSET;
+	pBuf->dataSize -= MV_NFP_SEC_ESP_OFFSET;
+	pBuf->bufAddrShift -= MV_NFP_SEC_ESP_OFFSET;
+	pCesaMbuf->pFrags = pPktInfo->pFrags;
+	pCesaMbuf->numFrags = 1;
+	pCesaMbuf->mbufSize = pBuf->dataSize;
+	pCesaMbuf->pFrags->bufSize = pBuf->dataSize;
+
+	pCesaCmd->pReqPrv = (MV_VOID *)pCesaPriv;
+	pCesaCmd->sessionId = pSAEntry->sid;
+	pCesaCmd->pSrc = pCesaMbuf;
+	pCesaCmd->pDst = pCesaMbuf;
+	pCesaCmd->skipFlush = MV_TRUE;
+
+	/* Assume ESP */
+	pCesaCmd->cryptoOffset = sizeof(MV_ESP_HEADER) + pSAEntry->ivSize;
+	pCesaCmd->cryptoLength =  pBuf->dataSize - (sizeof(MV_ESP_HEADER)
+				  + pSAEntry->ivSize + pSAEntry->digestSize);
+	pCesaCmd->ivFromUser = 0; /* relevant for encode only */
+	pCesaCmd->ivOffset = sizeof(MV_ESP_HEADER);
+	pCesaCmd->macOffset = 0;
+	pCesaCmd->macLength = pBuf->dataSize - pSAEntry->digestSize;
+	if ((pCesaCmd->digestOffset != 0) && ((pCesaCmd->digestOffset%4)))  {
+		printk(KERN_INFO "pBuf->dataSize=%d pSAEntry->digestSize=%d in %s\n",
+			pBuf->dataSize, pSAEntry->digestSize, __func__);
+		printk(KERN_INFO "pCesaCmd->digestOffset=%d in %s\n",
+			pCesaCmd->digestOffset, __func__);
+	}
+	pCesaCmd->digestOffset = pBuf->dataSize - pSAEntry->digestSize ;
+
+	disable_irq(CESA_IRQ(channel));
+
+	status = mvCesaAction(channel, pCesaCmd);
+	enable_irq(CESA_IRQ(channel));
+	if (status != MV_OK) {
+		pSAEntry->stats.rejected++;
+		mvOsPrintf("%s: mvCesaAction failed %d\n", __func__, status);
+	}
+
+	return status;
+}
+
+inline MV_STATUS mvSecOutgoing(struct eth_pbuf *pkt, MV_PKT_INFO *pPktInfo,
+						MV_NFP_SEC_SA_ENTRY *pSAEntry, struct eth_port *new_pp,
+						int inPort, MV_U8 chan)
+{
+	MV_U8 *pTmp;
+	MV_U32 cryptoSize, encBlockMod, dSize;
+	MV_BUF_INFO *pBuf = pPktInfo->pFrags;
+	/* CESA Q is full drop. */
+	if (cesaReqResources[chan] <= 1) {
+		counterNoResources[inPort]++;
+		return MV_DROPPED;
+	}
+	cryptoSize = pBuf->dataSize - sizeof(MV_802_3_HEADER);
+
+	/* Align buffer address to beginning of new packet - TBD handle VLAN tag, LLC */
+	dSize = pSAEntry->ivSize + sizeof(MV_ESP_HEADER) + sizeof(MV_IP_HEADER);
+	pBuf->bufVirtPtr -= dSize;
+	pBuf->bufPhysAddr -= dSize;
+	pBuf->dataSize += dSize;
+	pBuf->bufAddrShift += dSize;
+
+	encBlockMod = (cryptoSize % MV_NFP_SEC_ENC_BLOCK_SIZE);
+	/* leave space for padLen + Protocol */
+	if (encBlockMod > 14) {
+		encBlockMod =  MV_NFP_SEC_ENC_BLOCK_SIZE - encBlockMod;
+		encBlockMod += MV_NFP_SEC_ENC_BLOCK_SIZE;
+	} else
+		encBlockMod =  MV_NFP_SEC_ENC_BLOCK_SIZE - encBlockMod;
+	/* expected frame size */
+	dSize = pBuf->dataSize + encBlockMod + pSAEntry->digestSize;
+
+	pBuf->dataSize += encBlockMod;
+	pTmp = pBuf->bufVirtPtr + pBuf->dataSize;
+	memset(pTmp - encBlockMod, 0, encBlockMod - 2);
+	*((MV_U8 *)(pTmp-2)) = (MV_U8)(encBlockMod-2);
+	*((MV_U8 *)(pTmp-1)) = (MV_U8)4;
+
+	pBuf->dataSize += pSAEntry->digestSize;
+
+	mvNfpSecBuildEspHdr(pPktInfo, pSAEntry);
+	mvNfpSecBuildIPTunnel(pPktInfo, pSAEntry);
+	mvNfpSecBuildMac(pPktInfo, pSAEntry);
+
+	/* flush & invalidate new MAC, IP, & ESP headers + old ip*/
+	dSize = pBuf->bufAddrShift + sizeof(MV_IP_HEADER) + sizeof(MV_802_3_HEADER);
+
+	if (chan == 0)
+	  return mvSecEspProcess_0(pkt, pPktInfo, pSAEntry, new_pp, chan, inPort);
+	else
+	  return mvSecEspProcess_1(pkt, pPktInfo, pSAEntry, new_pp, chan, inPort);
+}
+
+inline MV_STATUS handleEsp(struct eth_pbuf *pkt, struct neta_rx_desc *rx_desc,
+							struct eth_port  *new_pp, int inPort)
+{
+	MV_STATUS res;
+	int chan = 	cesaChanPort[inPort];
+
+	spin_lock(&cesa_lock[chan]);
+
+	if (chan == 0) {
+		pBufInfoArray_0[cesaCmdIndx_0].bufAddrShift = 0;
+		pBufInfoArray_0[cesaCmdIndx_0].dataSize    = pkt->bytes;
+
+		pBufInfoArray_0[cesaCmdIndx_0].bufSize     = pkt->bytes;
+		pBufInfoArray_0[cesaCmdIndx_0].bufVirtPtr  = pkt->pBuf + pkt->offset + MV_ETH_MH_SIZE;
+
+		pBufInfoArray_0[cesaCmdIndx_0].bufPhysAddr = mvOsIoVirtToPhy(NULL, pkt->pBuf + pkt->offset + MV_ETH_MH_SIZE);
+		pBufInfoArray_0[cesaCmdIndx_0].memHandle   = 0;
+
+		pPktInfoNewArray_0[cesaCmdIndx_0].pFrags = &pBufInfoArray_0[cesaCmdIndx_0];
+		pPktInfoNewArray_0[cesaCmdIndx_0].numFrags = 1;
+	} else {
+		pBufInfoArray_1[cesaCmdIndx_1].bufAddrShift = 0;
+		pBufInfoArray_1[cesaCmdIndx_1].dataSize    = pkt->bytes;
+
+		pBufInfoArray_1[cesaCmdIndx_1].bufSize     = pkt->bytes;
+		pBufInfoArray_1[cesaCmdIndx_1].bufVirtPtr  = pkt->pBuf + pkt->offset + MV_ETH_MH_SIZE;
+
+		pBufInfoArray_1[cesaCmdIndx_1].bufPhysAddr = mvOsIoVirtToPhy(NULL, pkt->pBuf + pkt->offset + MV_ETH_MH_SIZE);
+		pBufInfoArray_1[cesaCmdIndx_1].memHandle   = 0;
+
+		pPktInfoNewArray_1[cesaCmdIndx_1].pFrags = &pBufInfoArray_1[cesaCmdIndx_1];
+		pPktInfoNewArray_1[cesaCmdIndx_1].numFrags = 1;
+	}
+
+	if (chan == 0)
+		res = mvSecOutgoing(pkt, &pPktInfoNewArray_0[cesaCmdIndx_0], &sa, new_pp, inPort, chan);
+	else
+		res = mvSecOutgoing(pkt, &pPktInfoNewArray_1[cesaCmdIndx_1], &sa, new_pp, inPort, chan);
+
+	spin_unlock(&cesa_lock[chan]);
+	return res;
+}
+
+void l2fw_stats(void)
+{
+	int i;
+	for (i = 0; i < 4; i++) {
+		mvOsPrintf("number of Cesa No Resources error is port[%d]=%d \n", i, counterNoResources[i]);
+		counterNoResources[i] = 0;
+	}
+}
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/Makefile
new file mode 100755
index 0000000..866029a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/Makefile
@@ -0,0 +1,29 @@
+#
+# Makefile for the Marvell Gigabit Ethernet driver
+#
+
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifeq ($(CONFIG_ARCH_ARMADA370),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifeq ($(CONFIG_ARCH_ARMADA_XP),y)
+	include $(srctree)/arch/arm/mach-armadaxp/config/mvRules.mk
+endif
+
+ifeq ($(CONFIG_MV_ETH_NFP_LIB),y)
+	obj-$(CONFIG_MV_ETHERNET) += mv_netdev.o mv_ethernet.o mv_eth_sysfs.o
+	obj-$(CONFIG_MV_PON)      += mv_pon_sysfs.o
+	obj-$(CONFIG_MV_ETH_SWITCH) +=  mv_eth_switch.o
+	obj-$(CONFIG_MV_ETH_TOOL) += mv_eth_tool.o
+	obj-y += ../nfplib.a
+else
+	obj-$(CONFIG_MV_ETHERNET) += mv_netdev.o mv_ethernet.o mv_eth_sysfs.o
+	obj-$(CONFIG_MV_PON)      += mv_pon_sysfs.o
+	obj-$(CONFIG_MV_ETH_SWITCH) +=  mv_eth_switch.o
+	obj-$(CONFIG_MV_ETH_TOOL) += mv_eth_tool.o
+endif
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_switch.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_switch.c
new file mode 100755
index 0000000..ebc8e72
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_switch.c
@@ -0,0 +1,787 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"  /* Should be included before mvSysHwConfig */
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/version.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+#include "mvOs.h"
+#include "dbg-trace.h"
+#include "mvSysHwConfig.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#ifdef MV_INCLUDE_ETH_COMPLEX
+#include "ctrlEnv/mvCtrlEthCompLib.h"
+#endif /* MV_INCLUDE_ETH_COMPLEX */
+#include "gbe/mvNeta.h"
+
+#include "mv_switch.h"
+#include "mv_netdev.h"
+
+extern int mv_net_devs_num;
+
+/* Example: "mv_net_config=4,(00:99:88:88:99:77,0)(00:55:44:55:66:77,1:2:3:4)(00:11:22:33:44:55,),mtu=1500" */
+static char			*net_config_str[CONFIG_MV_ETH_PORTS_NUM] = {NULL};
+struct mv_eth_switch_config     switch_net_config[CONFIG_MV_ETH_PORTS_NUM];
+
+static int                      mv_eth_switch_started = 0;
+unsigned int                    switch_enabled_ports = 0;
+
+/* Required to get the configuration string from the Kernel Command Line */
+int mv_eth0_cmdline_config(char *s);
+__setup("mv_net_config=", mv_eth0_cmdline_config);
+
+int mv_eth0_cmdline_config(char *s)
+{
+	net_config_str[MV_ETH_PORT_0] = s;
+	return 1;
+}
+
+int mv_eth1_cmdline_config(char *s);
+__setup("mv_net_config1=", mv_eth1_cmdline_config);
+
+int mv_eth1_cmdline_config(char *s)
+{
+	net_config_str[MV_ETH_PORT_1] = s;
+	return 1;
+}
+
+
+/* Local function prototypes */
+static int mv_eth_check_open_bracket(char **p_net_config)
+{
+	if (**p_net_config == '(') {
+		(*p_net_config)++;
+		return 0;
+	}
+	printk(KERN_ERR "Syntax error: could not find opening bracket\n");
+	return -EINVAL;
+}
+
+static int mv_eth_check_closing_bracket(char **p_net_config)
+{
+	if (**p_net_config == ')') {
+		(*p_net_config)++;
+		return 0;
+	}
+	printk(KERN_ERR "Syntax error: could not find closing bracket\n");
+	return -EINVAL;
+}
+
+static int mv_eth_check_comma(char **p_net_config)
+{
+	if (**p_net_config == ',') {
+		(*p_net_config)++;
+		return 0;
+	}
+	printk(KERN_ERR "Syntax error: could not find comma\n");
+	return -EINVAL;
+}
+
+static int mv_eth_netconfig_mac_addr_get(char **p_net_config, int idx, int port)
+{
+	int     num;
+	char *config_str = *p_net_config;
+	MV_U32  mac[MV_MAC_ADDR_SIZE];
+
+	/* the MAC address should look like: 00:99:88:88:99:77 */
+	/* that is, 6 two-digit numbers, separated by :        */
+	num = sscanf(config_str, "%2x:%2x:%2x:%2x:%2x:%2x",
+		&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+	if (num == MV_MAC_ADDR_SIZE) {
+		while (--num >= 0)
+			switch_net_config[port].mac_addr[idx][num] = (mac[num] & 0xFF);
+
+		(*p_net_config) = config_str + 17;
+		return 0;
+	}
+	printk(KERN_ERR "Syntax error while parsing MAC address from command line\n");
+	return -EINVAL;
+}
+
+static int mv_eth_netconfig_ports_get(char **p_net_config, int idx, int port)
+{
+	char ch;
+	char *config_str = *p_net_config;
+	int  sw_port, mask = 0, status = -EINVAL;
+
+	/* the switch port list should look like this: */
+	/* example 0: )         - no ports */
+	/* example 1: 0)        - single port 0 */
+	/* example 2: 1:2:3:4)  - multiple ports */
+
+	while (1) {
+		ch = *config_str++;
+
+		if (ch == ')') {
+			/* Finished */
+			status = 0;
+			break;
+		}
+		sw_port = mvCharToDigit(ch);
+		if (sw_port < 0)
+			break;
+
+		/* TBD - Check sw_port validity */
+		mask |= (1 << sw_port);
+
+		if (*config_str == ':')
+			config_str++;
+	}
+	*p_net_config = config_str;
+
+	if (status == 0) {
+		switch_net_config[port].board_port_map[idx] = mask;
+		return 0;
+	}
+	printk(KERN_ERR "Syntax error while parsing switch port mask from command line\n");
+	return -EINVAL;
+}
+
+/* the mtu value is constructed as follows: */
+/* mtu=value                                */
+static int  mv_eth_netconfig_mtu_get(char **p_net_config, int port)
+{
+	unsigned int mtu;
+
+	if (strncmp(*p_net_config, "mtu=", 4) == 0) {
+		*p_net_config += 4;
+		mtu = strtol(*p_net_config, p_net_config, 10);
+		if (mtu > 0) {
+			switch_net_config[port].mtu = mtu;
+			printk(KERN_ERR "      o MTU set to %d.\n", mtu);
+			return 0;
+		}
+		printk(KERN_ERR "Syntax error while parsing mtu value from command line\n");
+		return -EINVAL;
+	}
+
+	switch_net_config[port].mtu = 1500;
+	printk(KERN_ERR "      o Using default MTU %d\n", switch_net_config[port].mtu);
+	return 0;
+}
+
+static int mv_eth_netconfig_max_get(char **p_net_config, int port)
+{
+	char num = **p_net_config;
+	int netdev_num;
+
+	netdev_num = mvCharToDigit(num);
+	if (netdev_num >= 0) {
+		switch_net_config[port].netdev_max = netdev_num;
+		(*p_net_config) += 1;
+		return 0;
+	}
+	printk(KERN_ERR "Syntax error while parsing number of netdevs from command line\n");
+	return -EINVAL;
+}
+
+int mv_eth_switch_config_get(int use_existing_config, int port)
+{
+	char *p_net_config;
+	int i = 0;
+
+	if ((port != MV_ETH_PORT_0) && (port != MV_ETH_PORT_1))	{
+		printk("%s: invalid port number %d\n", __func__, port);
+		return -EINVAL;
+	}
+
+	if (!use_existing_config) {
+		memset(&(switch_net_config[port]), 0, sizeof((switch_net_config[port])));
+
+		if (net_config_str[port] != NULL) {
+			printk(KERN_ERR "      o Using UBoot netconfig string for port %d\n", port);
+		}
+		else {
+			printk(KERN_ERR "      o Using default netconfig string from Kconfig for port %d\n", port);
+			if (port == MV_ETH_PORT_0)
+				net_config_str[port] = CONFIG_MV_ETH_SWITCH_NETCONFIG_0;
+			else if (port == MV_ETH_PORT_1)
+				net_config_str[port] = CONFIG_MV_ETH_SWITCH_NETCONFIG_1;
+		}
+		printk(KERN_ERR "        net_config_str[%d]: %s\n", port, net_config_str[port]);
+
+		p_net_config = net_config_str[port];
+		if (mv_eth_netconfig_max_get(&p_net_config, port))
+			return -EINVAL;
+
+		/* check restriction: at least one of the configuration strings must be 0 */
+		if ((net_config_str[MV_ETH_PORT_0] != NULL) &&
+		    (net_config_str[MV_ETH_PORT_1] != NULL) &&
+		    (switch_net_config[MV_ETH_PORT_0].netdev_max != 0) &&
+		    (switch_net_config[MV_ETH_PORT_1].netdev_max != 0)) {
+			printk("%s: cannot have both GbE ports using the Gateway driver, change mv_net_config\n", __func__);
+			return -EINVAL;
+		}
+
+		if (switch_net_config[port].netdev_max == 0)
+			return 1;
+
+		if (switch_net_config[port].netdev_max > CONFIG_MV_ETH_SWITCH_NETDEV_NUM) {
+			printk(KERN_ERR "Too large number of netdevs (%d) in command line: cut to %d\n",
+				switch_net_config[port].netdev_max, CONFIG_MV_ETH_SWITCH_NETDEV_NUM);
+			switch_net_config[port].netdev_max = CONFIG_MV_ETH_SWITCH_NETDEV_NUM;
+		}
+
+		if (mv_eth_check_comma(&p_net_config))
+			return -EINVAL;
+
+		for (i = 0; (i < CONFIG_MV_ETH_SWITCH_NETDEV_NUM) && (*p_net_config != '\0'); i++) {
+			if (mv_eth_check_open_bracket(&p_net_config))
+				return -EINVAL;
+
+			if (mv_eth_netconfig_mac_addr_get(&p_net_config, i, port))
+				return -EINVAL;
+
+			if (mv_eth_check_comma(&p_net_config))
+				return -EINVAL;
+
+			if (mv_eth_netconfig_ports_get(&p_net_config, i, port))
+				return -EINVAL;
+
+			switch_net_config[port].netdev_cfg++;
+
+			/* If we have a comma after the closing bracket, then interface */
+			/* definition is done.                                          */
+			if (*p_net_config == ',') {
+				p_net_config++;
+				break;
+			}
+		}
+
+		/* there is a chance the previous loop did not end because a comma was found but because	*/
+		/* the maximum number of interfaces was reached, so check for the comma now.		*/
+		if (i == CONFIG_MV_ETH_SWITCH_NETDEV_NUM)
+			if (mv_eth_check_comma(&p_net_config))
+				return -EINVAL;
+
+		if (*p_net_config != '\0') {
+			if (mv_eth_netconfig_mtu_get(&p_net_config, port))
+				return -EINVAL;
+		} else {
+			switch_net_config[port].mtu = 1500;
+			printk(KERN_ERR "      o Using default MTU %d\n", switch_net_config[port].mtu);
+		}
+
+		/* at this point, we have parsed up to CONFIG_MV_ETH_SWITCH_NETDEV_NUM, and the mtu value */
+		/* if the net_config string is not finished yet, then its format is invalid */
+		if (*p_net_config != '\0') {
+			printk(KERN_ERR "Switch netconfig string is too long: %s\n", p_net_config);
+			return -EINVAL;
+		}
+	} else {
+		/* leave most of the configuration as-is, but update MAC addresses */
+		/* MTU is saved in mv_eth_switch_change_mtu */
+
+		/* Note: at this point, since this is a re-init, mv_eth_switch_netdev_first */
+		/* and mv_eth_switch_netdev_last, as well as mv_net_devs[], are valid.      */
+		for (i = mv_eth_switch_netdev_first; i <= mv_eth_switch_netdev_last; i++) {
+			if (mv_net_devs[i] != NULL)
+				memcpy(switch_net_config[port].mac_addr[i - mv_eth_switch_netdev_first],
+					mv_net_devs[i]->dev_addr, MV_MAC_ADDR_SIZE);
+		}
+
+		if (switch_net_config[port].netdev_max == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+int    mv_eth_switch_set_mac_addr(struct net_device *dev, void *mac)
+{
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+	struct sockaddr *addr = (struct sockaddr *)mac;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	/* remove old mac addr from VLAN DB */
+	mv_switch_mac_addr_set(dev->dev_addr, MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id), (1 << dev_priv->cpu_port), 0);
+
+	memcpy(dev->dev_addr, addr->sa_data, MV_MAC_ADDR_SIZE);
+
+	/* add new mac addr to VLAN DB */
+	mv_switch_mac_addr_set(dev->dev_addr, MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id), (1 << dev_priv->cpu_port), 1);
+
+	printk(KERN_ERR "mv_eth_switch: %s change mac address to %02x:%02x:%02x:%02x:%02x:%02x\n",
+		dev->name, *(dev->dev_addr), *(dev->dev_addr+1), *(dev->dev_addr+2),
+		*(dev->dev_addr+3), *(dev->dev_addr+4), *(dev->dev_addr+5));
+
+	return 0;
+}
+
+void    mv_eth_switch_set_multicast_list(struct net_device *dev)
+{
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+
+	if (dev->flags & IFF_PROMISC) {
+		/* promiscuous mode - connect the CPU port to the VLAN (port based + 802.1q) */
+		/* printk(KERN_ERR "mv_eth_switch: setting promiscuous mode\n"); */
+		if (mv_switch_promisc_set(dev_priv->vlan_grp_id, dev_priv->port_map, dev_priv->cpu_port, 1))
+			printk(KERN_ERR "mv_switch_promisc_set to 1 failed\n");
+	} else {
+		/* not in promiscuous mode - disconnect the CPU port to the VLAN (port based + 802.1q) */
+		if (mv_switch_promisc_set(dev_priv->vlan_grp_id, dev_priv->port_map, dev_priv->cpu_port, 0))
+			printk(KERN_ERR "mv_switch_promisc_set to 0 failed\n");
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* allmulticast - not supported. There is no way to tell the Switch to accept only	*/
+			/* the multicast addresses but not Unicast addresses, so the alternatives are:	*/
+			/* 1) Don't support multicast and do nothing					*/
+			/* 2) Support multicast with same implementation as promiscuous			*/
+			/* 3) Don't rely on Switch for MAC filtering, but use PnC			*/
+			/* Currently option 1 is selected						*/
+			printk(KERN_ERR "mv_eth_switch: setting all-multicast mode is not supported\n");
+		}
+
+		/* Add or delete specific multicast addresses:						*/
+		/* Linux provides a list of the current multicast addresses for the device.		*/
+		/* First, we delete all the multicast addresses in the ATU.				*/
+		/* Then we add the specific multicast addresses Linux provides.				*/
+		if (mv_switch_all_multicasts_del(MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id)))
+			printk(KERN_ERR "mv_eth_switch: mv_switch_all_multicasts_del failed\n");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+		if (!netdev_mc_empty(dev)) {
+			struct netdev_hw_addr *ha;
+
+			netdev_for_each_mc_addr(ha, dev) {
+				mv_switch_mac_addr_set(ha->addr,
+					MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id),
+					(dev_priv->port_map | (1 << dev_priv->cpu_port)), 1);
+			}
+		}
+#else
+		{
+			int i;
+			struct dev_mc_list *curr_addr = dev->mc_list;
+
+			/* accept specific multicasts */
+			for (i = 0; i < dev->mc_count; i++, curr_addr = curr_addr->next) {
+				if (!curr_addr)
+					break;
+
+				/*
+				printk(KERN_ERR "Setting MC = %02X:%02X:%02X:%02X:%02X:%02X\n",
+				curr_addr->dmi_addr[0], curr_addr->dmi_addr[1], curr_addr->dmi_addr[2],
+				curr_addr->dmi_addr[3], curr_addr->dmi_addr[4], curr_addr->dmi_addr[5]);
+				*/
+				mv_switch_mac_addr_set(curr_addr->dmi_addr,
+					MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id),
+					(dev_priv->port_map | (1 << dev_priv->cpu_port)), 1);
+			}
+		}
+#endif /* KERNEL_VERSION >= 2.6.34 */
+	}
+}
+
+int     mv_eth_switch_change_mtu(struct net_device *dev, int mtu)
+{
+	int i;
+	struct eth_port *priv = MV_ETH_PRIV(dev);
+
+	/* All gateway interfaces must be down before changing MTU */
+	for (i = mv_eth_switch_netdev_first; i <= mv_eth_switch_netdev_last; i++) {
+		if ((mv_net_devs[i] != NULL) && (netif_running(mv_net_devs[i]))) {
+			printk(KERN_ERR "All gateway interfaces must be down before changing MTU. %s is not down\n", mv_net_devs[i]->name);
+			return -EPERM;
+		}
+	}
+
+	if (dev->mtu != mtu) {
+		int old_mtu = dev->mtu;
+
+		mtu = mv_eth_check_mtu_valid(dev, mtu);
+		if (mtu < 0)
+			return -EPERM;
+
+		if (mv_eth_change_mtu_internals(dev, mtu))
+			return -EPERM;
+
+		printk(KERN_NOTICE "%s: change mtu %d (pkt-size %d) to %d (pkt-size %d)\n",
+			dev->name, old_mtu, RX_PKT_SIZE(old_mtu),
+			dev->mtu, RX_PKT_SIZE(dev->mtu));
+	}
+
+	if (switch_net_config[priv->port].mtu != mtu) {
+		mv_switch_jumbo_mode_set(RX_PKT_SIZE(mtu));
+		switch_net_config[priv->port].mtu = mtu;
+	}
+
+	return 0;
+}
+
+int    mv_eth_switch_start(struct net_device *dev)
+{
+	struct eth_port	*priv = MV_ETH_PRIV(dev);
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+	unsigned char broadcast[MV_MAC_ADDR_SIZE] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	int i;
+	int group;
+
+	/* Check that MTU value is identical for all gateway interfaces */
+	for (i = mv_eth_switch_netdev_first; i <= mv_eth_switch_netdev_last; i++) {
+		if ((mv_net_devs[i] != NULL) && (mv_net_devs[i]->mtu != dev->mtu)) {
+			printk(KERN_ERR "All gateway devices must have same MTU\n");
+			return -EPERM;
+		}
+	}
+
+	/* in default link is down */
+	netif_carrier_off(dev);
+
+	/* Stop the TX queue - it will be enabled upon PHY status change after link-up interrupt/timer */
+	netif_stop_queue(dev);
+
+	/* start upper layer accordingly with ports_map */
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+	dev_priv->link_map = 0;
+	mv_switch_link_update_event(dev_priv->port_map, 1);
+#else
+	dev_priv->link_map = dev_priv->port_map;
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+	if (mv_eth_switch_started == 0)	{
+		/* fill rx buffers, start rx/tx activity, set coalescing */
+		if (mv_eth_start_internals(priv, dev->mtu) != 0) {
+			printk(KERN_ERR "%s: start internals failed\n", dev->name);
+			goto error;
+		}
+
+		/* enable polling on the port, must be used after netif_poll_disable */
+		for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
+			napi_enable(priv->napiGroup[group]);
+
+		/* connect to port interrupt line */
+		if (request_irq(dev->irq, mv_eth_isr, IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "mv_eth", priv)) {
+			printk(KERN_ERR "cannot request irq %d for %s port %d\n",
+				dev->irq, dev->name, priv->port);
+			for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
+				napi_disable(priv->napiGroup[group]);
+			goto error;
+		}
+
+		/* unmask interrupts */
+		mv_eth_interrupts_unmask(priv);
+	}
+
+	mv_eth_switch_started++;
+
+	/* Add our MAC addr to the VLAN DB at switch level to forward packets with this DA   */
+	/* to CPU port by using the tunneling feature. The device is always in promisc mode. */
+	mv_switch_mac_addr_set(dev->dev_addr, MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id), (1 << dev_priv->cpu_port), 1);
+
+	/* We also need to allow L2 broadcasts comming up for this interface */
+	mv_switch_mac_addr_set(broadcast, MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id),
+			(dev_priv->port_map | (1 << dev_priv->cpu_port)), 1);
+
+	printk(KERN_ERR "%s: started (on switch)\n", dev->name);
+	return 0;
+
+error:
+	printk(KERN_ERR "%s: start failed\n", dev->name);
+	return -1;
+}
+
+int     mv_eth_switch_stop(struct net_device *dev)
+{
+	struct eth_port *priv = MV_ETH_PRIV(dev);
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+	int group;
+
+	/* stop upper layer */
+	netif_carrier_off(dev);
+	netif_stop_queue(dev);
+
+	/* stop switch from forwarding packets from this VLAN toward CPU port */
+	mv_switch_atu_db_flush(MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id));
+
+	/* It is possible that the interface is in promiscuous mode */
+	/* If so, the CPU port is connected with port based VLAN to the other ports, and */
+	/* we must disconnect it now to stop the Switch from forwarding packets to the CPU */
+	/* when the interface is down. */
+	/* mv_eth_switch_set_multicast_list will be called anyway by Linux when we do ifconfig up */
+	/* and will re-set the promiscuous feature if needed */
+	if (dev->flags & IFF_PROMISC) {
+		if (mv_switch_promisc_set(dev_priv->vlan_grp_id, dev_priv->port_map, dev_priv->cpu_port, 0))
+			printk(KERN_ERR "mv_switch_promisc_set to 0 failed\n");
+	}
+	mv_eth_switch_started--;
+	if (mv_eth_switch_started == 0)	{
+		/* first make sure that the port finished its Rx polling - see tg3 */
+		/* otherwise it may cause issue in SMP, one CPU is here and the other is doing the polling */
+		/* and both of it are messing with the descriptors rings!! */
+		for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
+			napi_disable(priv->napiGroup[group]);
+
+		/* stop tx/rx activity, mask all interrupts, relese skb in rings,*/
+		mv_eth_stop_internals(priv);
+
+		del_timer(&priv->tx_done_timer);
+		clear_bit(MV_ETH_F_TX_DONE_TIMER_BIT, &(priv->flags));
+		del_timer(&priv->cleanup_timer);
+		clear_bit(MV_ETH_F_CLEANUP_TIMER_BIT, &(priv->flags));
+
+		if (dev->irq != 0)
+			free_irq(dev->irq, priv);
+	}
+	printk(KERN_NOTICE "%s: stopped\n", dev->name);
+
+	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+
+void mv_eth_switch_interrupt_unmask(int qsgmii_module, int gephy_on_port)
+{
+#ifdef MV_INCLUDE_ETH_COMPLEX
+	MV_U32 reg;
+
+	reg = MV_REG_READ(MV_ETHCOMP_INT_MAIN_MASK_REG);
+
+	if (qsgmii_module) {
+		reg |= (MV_ETHCOMP_PCS0_LINK_INT_MASK |
+			MV_ETHCOMP_PCS1_LINK_INT_MASK |
+			MV_ETHCOMP_PCS2_LINK_INT_MASK |
+			MV_ETHCOMP_PCS3_LINK_INT_MASK);
+	}
+
+	if (gephy_on_port >= 0)
+		reg |= MV_ETHCOMP_GEPHY_INT_MASK;
+
+	reg |= MV_ETHCOMP_SWITCH_INT_MASK;
+
+	MV_REG_WRITE(MV_ETHCOMP_INT_MAIN_MASK_REG, reg);
+#endif /* MV_INCLUDE_ETH_COMPLEX */
+}
+
+void mv_eth_switch_interrupt_clear(int qsgmii_module, int gephy_on_port)
+{
+#ifdef MV_INCLUDE_ETH_COMPLEX
+	MV_U32 reg;
+
+	reg = MV_REG_READ(MV_ETHCOMP_INT_MAIN_CAUSE_REG);
+
+	if (qsgmii_module) {
+		reg &= ~(MV_ETHCOMP_PCS0_LINK_INT_MASK |
+			 MV_ETHCOMP_PCS1_LINK_INT_MASK |
+			 MV_ETHCOMP_PCS2_LINK_INT_MASK |
+			 MV_ETHCOMP_PCS3_LINK_INT_MASK);
+	}
+
+	if (gephy_on_port >= 0)
+		reg &= ~MV_ETHCOMP_GEPHY_INT_MASK;
+
+	reg &= ~MV_ETHCOMP_SWITCH_INT_MASK;
+
+	MV_REG_WRITE(MV_ETHCOMP_INT_MAIN_CAUSE_REG, reg);
+#endif /* MV_INCLUDE_ETH_COMPLEX */
+}
+
+void mv_eth_switch_update_link(unsigned int p, unsigned int link_up)
+{
+	struct eth_netdev *dev_priv = NULL;
+	struct eth_port *priv = NULL;
+	int i = 0;
+	unsigned int prev_ports_link = 0;
+
+	for (i = 0; i < mv_net_devs_num; i++) {
+
+		if (mv_net_devs[i] == NULL)
+			break;
+
+		priv = MV_ETH_PRIV(mv_net_devs[i]);
+		if (priv == NULL)
+			break;
+
+		if (!(priv->flags & (MV_ETH_F_SWITCH | MV_ETH_F_EXT_SWITCH)))
+			continue;
+
+		dev_priv = MV_DEV_PRIV(mv_net_devs[i]);
+		if (dev_priv == NULL)
+			break;
+
+		if ((dev_priv->port_map & (1 << p)) == 0)
+			continue;
+
+		prev_ports_link = dev_priv->link_map;
+
+		if (link_up)
+			dev_priv->link_map |= (1 << p);
+		else
+			dev_priv->link_map &= ~(1 << p);
+
+		if ((prev_ports_link != 0) && (dev_priv->link_map == 0) && netif_running(mv_net_devs[i])) {
+			/* link down */
+			netif_carrier_off(mv_net_devs[i]);
+			netif_stop_queue(mv_net_devs[i]);
+			printk(KERN_ERR "%s: link down\n", mv_net_devs[i]->name);
+		} else if ((prev_ports_link == 0) && (dev_priv->link_map != 0) && netif_running(mv_net_devs[i])) {
+			/* link up */
+			if (mv_eth_ctrl_is_tx_enabled(priv) == 1) {
+				netif_carrier_on(mv_net_devs[i]);
+				netif_wake_queue(mv_net_devs[i]);
+				printk(KERN_ERR "%s: link up\n", mv_net_devs[i]->name);
+			}
+		}
+	}
+}
+
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+int     mv_eth_switch_port_add(struct net_device *dev, int port)
+{
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+	struct eth_port	*priv = MV_ETH_PRIV(dev);
+	int i, switch_port, err = 0;
+
+	if (dev_priv == NULL) {
+		printk(KERN_ERR "%s is not connected to the switch\n", dev->name);
+		return 1;
+	}
+
+	if (netif_running(dev)) {
+		printk(KERN_ERR "%s must be down to change switch ports map\n", dev->name);
+		return 1;
+	}
+
+	switch_port = mvBoardSwitchPortGet(0, port);
+
+	if (switch_port < 0) {
+		printk(KERN_ERR "Switch port %d can't be added\n", port);
+		return 1;
+	}
+
+	if (MV_BIT_CHECK(switch_enabled_ports, switch_port)) {
+		printk(KERN_ERR "Switch port %d is already enabled\n", port);
+		return 0;
+	}
+
+	/* Update data base */
+	dev_priv->port_map |= (1 << switch_port);
+	for (i = mv_eth_switch_netdev_first; i <= mv_eth_switch_netdev_last; i++) {
+		if ((mv_net_devs[i] != NULL) && (mv_net_devs[i] == dev))
+			switch_net_config[priv->port].board_port_map[i - mv_eth_switch_netdev_first] |= (1 << switch_port);
+	}
+	switch_enabled_ports |= (1 << switch_port);
+	dev_priv->tx_vlan_mh = cpu_to_be16((MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id) << 12) | dev_priv->port_map);
+
+	err = mv_switch_port_add(switch_port, dev_priv->vlan_grp_id, dev_priv->port_map);
+	if (!err)
+		printk(KERN_ERR "%s: Switch port #%d mapped\n", dev->name, port);
+
+	return err;
+}
+
+int     mv_eth_switch_port_del(struct net_device *dev, int port)
+{
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+	struct eth_port	*priv = MV_ETH_PRIV(dev);
+	int i, switch_port, err = 0;
+
+	if (dev_priv == NULL) {
+		printk(KERN_ERR "%s is not connected to the switch\n", dev->name);
+		return 1;
+	}
+
+	if (netif_running(dev)) {
+		printk(KERN_ERR "%s must be down to change switch ports map\n", dev->name);
+		return 1;
+	}
+
+	switch_port = mvBoardSwitchPortGet(0, port);
+
+	if (switch_port < 0) {
+		printk(KERN_ERR "Switch port %d can't be added\n", port);
+		return 1;
+	}
+
+	if (!MV_BIT_CHECK(switch_enabled_ports, switch_port)) {
+		printk(KERN_ERR "Switch port %d is already disabled\n", port);
+		return 0;
+	}
+
+	if (!MV_BIT_CHECK(dev_priv->port_map, switch_port)) {
+		printk(KERN_ERR "Switch port %d is not mapped on %s\n", port, dev->name);
+		return 0;
+	}
+
+	/* Update data base */
+	dev_priv->port_map &= ~(1 << switch_port);
+	for (i = mv_eth_switch_netdev_first; i <= mv_eth_switch_netdev_last; i++) {
+		if ((mv_net_devs[i] != NULL) && (mv_net_devs[i] == dev))
+			switch_net_config[priv->port].board_port_map[i - mv_eth_switch_netdev_first] &= ~(1 << switch_port);
+	}
+	dev_priv->link_map &= ~(1 << switch_port);
+	switch_enabled_ports &= ~(1 << switch_port);
+	dev_priv->tx_vlan_mh = cpu_to_be16((MV_SWITCH_VLAN_TO_GROUP(dev_priv->vlan_grp_id) << 12) | dev_priv->port_map);
+
+	err = mv_switch_port_del(switch_port, dev_priv->vlan_grp_id, dev_priv->port_map);
+	if (!err)
+		printk(KERN_ERR "%s: Switch port #%d unmapped\n", dev->name, port);
+
+	return err;
+}
+
+void    mv_eth_switch_status_print(int port)
+{
+	int i;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	struct net_device *dev;
+
+	if (pp->flags & MV_ETH_F_SWITCH) {
+		printk(KERN_ERR "ethPort=%d: mv_eth_switch status - pp=%p, flags=0x%lx\n", port, pp, pp->flags);
+
+		printk(KERN_ERR "mtu=%d, netdev_max=%d, netdev_cfg=%d, first=%d, last=%d\n",
+			switch_net_config[port].mtu, switch_net_config[port].netdev_max, switch_net_config[port].netdev_cfg,
+			mv_eth_switch_netdev_first, mv_eth_switch_netdev_last);
+
+		for (i = 0; i < switch_net_config[port].netdev_cfg; i++) {
+			printk(KERN_ERR "MAC="MV_MACQUAD_FMT", board_port_map=0x%x\n",
+				MV_MACQUAD(switch_net_config[port].mac_addr[i]), switch_net_config[port].board_port_map[i]);
+		}
+		for (i = mv_eth_switch_netdev_first; i <= mv_eth_switch_netdev_last; i++) {
+			dev = mv_eth_netdev_by_id(i);
+			if (dev)
+				mv_eth_netdev_print(dev);
+		}
+	} else
+		printk(KERN_ERR "ethPort=%d: switch is not connected - pp=%p, flags=0x%lx\n", port, pp, pp->flags);
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_sysfs.c
new file mode 100755
index 0000000..d6edeb5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_sysfs.c
@@ -0,0 +1,550 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+
+#include "gbe/mvNeta.h"
+#include "mv_netdev.h"
+
+static ssize_t mv_eth_help(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "cat                ports           - show all ports info\n");
+	off += sprintf(buf+off, "cat                pon_if_name     - show PON interface name\n");
+	off += sprintf(buf+off, "echo p             > port          - show a port info\n");
+	off += sprintf(buf+off, "echo p             > stats         - show a port statistics\n");
+	off += sprintf(buf+off, "echo p mib         > cntrs         - show a port counters\n");
+	off += sprintf(buf+off, "echo p             > tos           - show RX and TX TOS map for port <p>\n");
+	off += sprintf(buf+off, "echo p             > mac           - show MAC info for port <p>\n");
+	off += sprintf(buf+off, "echo p             > vprio         - show VLAN priority map for port <p>\n");
+	off += sprintf(buf+off, "echo p             > napi          - show port NAPI groups: CPUs and RXQs\n");
+	off += sprintf(buf+off, "echo p             > p_regs        - show port registers for <p>\n");
+	off += sprintf(buf+off, "echo p             > dev_name      - show device name for <p> if exists\n");
+#ifdef MV_ETH_GMAC_NEW
+	off += sprintf(buf+off, "echo p             > gmac_regs     - show gmac registers for <p>\n");
+#endif /* MV_ETH_GMAC_NEW */
+	off += sprintf(buf+off, "echo p rxq         > rxq_regs      - show RXQ registers for <p/rxq>\n");
+	off += sprintf(buf+off, "echo p txp         > wrr_regs      - show WRR registers for <p/txp>\n");
+	off += sprintf(buf+off, "echo p txp         > txp_regs      - show TX registers for <p/txp>\n");
+	off += sprintf(buf+off, "echo p txp txq     > txq_regs      - show TXQ registers for <p/txp/txq>\n");
+	off += sprintf(buf+off, "echo p rxq v       > rxq           - show RXQ descriptors ring for <p/rxq>. v=0-brief, v=1-full\n");
+	off += sprintf(buf+off, "echo p txp txq v   > txq           - show TXQ descriptors ring for <p/txp/txq>. v=0-brief, v=1-full\n");
+#ifdef CONFIG_MV_ETH_PNC
+	off += sprintf(buf+off, "echo {0|1}         > pnc           - enable / disable PNC access\n");
+#endif /* CONFIG_MV_ETH_PNC */
+	off += sprintf(buf+off, "echo {0|1}         > skb           - enable / disable SKB recycle\n");
+	off += sprintf(buf+off, "echo p {0|1}       > mh_en         - enable Marvell Header\n");
+	off += sprintf(buf+off, "echo p {0|1}       > tx_nopad      - disable zero padding\n");
+	off += sprintf(buf+off, "echo p hex         > mh_2B         - set 2 bytes of Marvell Header\n");
+	off += sprintf(buf+off, "echo p hex         > tx_cmd        - set 4 bytes of TX descriptor offset 0xc\n");
+	off += sprintf(buf+off, "echo p hex         > debug         - bit0:rx, bit1:tx, bit2:isr, bit3:poll, bit4:dump\n");
+	off += sprintf(buf+off, "echo p l s         > buf_num       - set number of long <l> and short <s> buffers allocated for port <p>\n");
+	off += sprintf(buf+off, "echo p rxq tos     > rxq_tos       - set <rxq> for incoming IP packets with <tos>\n");
+	off += sprintf(buf+off, "echo p group cpus  > cpu_group     - set <cpus mask>  for <port/napi group>.\n");
+	off += sprintf(buf+off, "echo p group rxqs  > rxq_group     - set  <rxqs mask> for <port/napi group>.\n");
+	off += sprintf(buf+off, "echo p rxq prio    > rxq_vlan      - set <rxq> for incoming VLAN packets with <prio>\n");
+	off += sprintf(buf+off, "echo p rxq v       > rxq_size      - set number of descriptors <v> for <port/rxq>.\n");
+	off += sprintf(buf+off, "echo p rxq v       > rxq_pkts_coal - set RXQ interrupt coalesing. <v> - number of received packets\n");
+	off += sprintf(buf+off, "echo p rxq v       > rxq_time_coal - set RXQ interrupt coalesing. <v> - time in microseconds\n");
+	off += sprintf(buf+off, "echo p rxq t       > rxq_type      - set RXQ for different packet types. t=0-bpdu, 1-arp, 2-tcp, 3-udp\n");
+	off += sprintf(buf+off, "echo p             > rx_reset      - reset RX part of the port <p>\n");
+	off += sprintf(buf+off, "echo p txp         > txp_reset     - reset TX part of the port <p/txp>\n");
+	off += sprintf(buf+off, "echo p txq tos     > txq_tos       - set <txq> for outgoing IP packets with <tos>\n");
+	off += sprintf(buf+off, "echo p txp txq cpu > txq_def       - set default <txp/txq> for packets sent to port <p> by <cpu>\n");
+	off += sprintf(buf+off, "echo p txp {0|1}   > ejp           - enable/disable EJP mode for <port/txp>\n");
+	off += sprintf(buf+off, "echo p txp v       > txp_rate      - set outgoing rate <v> in [kbps] for <port/txp>\n");
+	off += sprintf(buf+off, "echo p txp v       > txp_burst     - set maximum burst <v> in [Bytes] for <port/txp>\n");
+	off += sprintf(buf+off, "echo p txp txq v   > txq_rate      - set outgoing rate <v> in [kbps] for <port/txp/txq>\n");
+	off += sprintf(buf+off, "echo p txp txq v   > txq_burst     - set maximum burst <v> in [Bytes] for <port/txp/txq>\n");
+	off += sprintf(buf+off, "echo p txp txq v   > txq_wrr       - set outgoing WRR weight for <port/txp/txq>. <v=0> - fixed\n");
+	off += sprintf(buf+off, "echo p txp txq v   > txq_size      - set number of descriptors <v> for <port/txp/txq>.\n");
+	off += sprintf(buf+off, "echo p txp txq v   > txq_coal      - set TXP/TXQ interrupt coalesing. <v> - number of sent packets\n");
+	off += sprintf(buf+off, "echo v             > tx_done       - set threshold to start tx_done operations\n");
+	off += sprintf(buf+off, "echo p v           > rx_weight     - set weight for the poll function; <v> - new weight, max val: 255\n");
+	return off;
+}
+
+#ifdef CONFIG_MV_ETH_PNC
+int run_rxq_type(int port, int q, int t)
+{
+	void *port_hndl = mvNetaPortHndlGet(port);
+
+	if (port_hndl == NULL)
+		return 1;
+
+	if (!mv_eth_pnc_ctrl_en) {
+		printk(KERN_ERR "%s: PNC control is not supported\n", __func__);
+		return 1;
+	}
+
+	switch (t) {
+	case 1:
+		pnc_etype_arp(q);
+		break;
+	case 2:
+		pnc_ip4_tcp(q);
+		break;
+	case 3:
+		pnc_ip4_udp(q);
+		break;
+	default:
+		printk(KERN_ERR "unsupported packet type: value=%d\n", t);
+		return 1;
+	}
+	return 0;
+}
+#else
+int run_rxq_type(int port, int q, int t)
+{
+	void *port_hndl = mvNetaPortHndlGet(port);
+
+	if (port_hndl == NULL)
+		return 1;
+
+	switch (t) {
+	case 0:
+		mvNetaBpduRxq(port, q);
+		break;
+	case 1:
+		mvNetaArpRxq(port, q);
+		break;
+	case 2:
+		mvNetaTcpRxq(port, q);
+		break;
+	case 3:
+		mvNetaUdpRxq(port, q);
+		break;
+	default:
+		printk(KERN_ERR "unknown packet type: value=%d\n", t);
+		return 1;
+	}
+	return 0;
+}
+#endif /* CONFIG_MV_ETH_PNC */
+
+static ssize_t mv_eth_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	const char      *name = attr->attr.name;
+	unsigned int    p;
+	int             off = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "ports")) {
+		mv_eth_status_print();
+
+		for (p = 0; p <= CONFIG_MV_ETH_PORTS_NUM; p++)
+			mv_eth_port_status_print(p);
+	} else if (!strcmp(name, "pon_if_name")) {
+        off = mv_eth_pon_ifname_dump(buf);
+    } else {
+		off = mv_eth_help(buf);
+	}
+
+	return off;
+}
+
+static ssize_t mv_eth_port_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	int             err;
+	unsigned int    p, v;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read port and value */
+	err = p = v = 0;
+	sscanf(buf, "%d %x", &p, &v);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "debug")) {
+		err = mv_eth_ctrl_flag(p, MV_ETH_F_DBG_RX,   v & 0x1);
+		err = mv_eth_ctrl_flag(p, MV_ETH_F_DBG_TX,   v & 0x2);
+		err = mv_eth_ctrl_flag(p, MV_ETH_F_DBG_ISR,  v & 0x4);
+		err = mv_eth_ctrl_flag(p, MV_ETH_F_DBG_POLL, v & 0x8);
+		err = mv_eth_ctrl_flag(p, MV_ETH_F_DBG_DUMP, v & 0x10);
+	} else if (!strcmp(name, "skb")) {
+		mv_eth_ctrl_recycle(p);
+	} else if (!strcmp(name, "tx_cmd")) {
+		err = mv_eth_ctrl_tx_cmd(p, v);
+	} else if (!strcmp(name, "mh_2B")) {
+		err = mv_eth_ctrl_tx_mh(p, (u16)v);
+	} else if (!strcmp(name, "mh_en")) {
+		err = mv_eth_ctrl_flag(p, MV_ETH_F_MH, v);
+	} else if (!strcmp(name, "tx_nopad")) {
+		err = mv_eth_ctrl_flag(p, MV_ETH_F_NO_PAD, v);
+	} else if (!strcmp(name, "port")) {
+		mv_eth_status_print();
+		mvNetaPortStatus(p);
+		mv_eth_port_status_print(p);
+	} else if (!strcmp(name, "stats")) {
+		mv_eth_port_stats_print(p);
+	} else if (!strcmp(name, "tos")) {
+		mv_eth_tos_map_show(p);
+	} else if (!strcmp(name, "mac")) {
+		mv_eth_mac_show(p);
+	} else if (!strcmp(name, "vprio")) {
+		mv_eth_vlan_prio_show(p);
+	} else if (!strcmp(name, "p_regs")) {
+		printk(KERN_INFO "\n[NetA Port: port=%d]\n", p);
+		mvEthRegs(p);
+		printk(KERN_INFO "\n");
+		mvEthPortRegs(p);
+		mvNetaPortRegs(p);
+#ifdef MV_ETH_GMAC_NEW
+	} else if (!strcmp(name, "gmac_regs")) {
+		mvNetaGmacRegs(p);
+#endif /* MV_ETH_GMAC_NEW */
+#ifdef CONFIG_MV_ETH_PNC
+	} else if (!strcmp(name, "pnc")) {
+		mv_eth_ctrl_pnc(p);
+#endif /* CONFIG_MV_ETH_PNC */
+	} else if (!strcmp(name, "napi")) {
+		mv_eth_napi_group_show(p);
+	} else if (!strcmp(name, "dev_name")) {
+        mv_eth_port_ifname_print(p);
+	} else {
+		err = 1;
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	}
+
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: error %d\n", __func__, err);
+
+	return err ? -EINVAL : len;
+}
+
+static ssize_t mv_eth_3_hex_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	int             err;
+	unsigned int    p, i, v;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	err = p = i = v = 0;
+	sscanf(buf, "%d %d %x", &p, &i, &v);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "txq_tos")) {
+		err = mv_eth_txq_tos_map_set(p, i, v);
+	} else if (!strcmp(name, "rxq_tos")) {
+		err = mv_eth_rxq_tos_map_set(p, i, v);
+	} else if (!strcmp(name, "rxq_vlan")) {
+		err = mv_eth_rxq_vlan_prio_set(p, i, v);
+	} else if (!strcmp(name, "cpu_group")) {
+		err = mv_eth_napi_set_cpu_affinity(p, i, v);
+	} else if (!strcmp(name, "rxq_group")) {
+		err = mv_eth_napi_set_rxq_affinity(p, i, v);
+	} else {
+		err = 1;
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	}
+
+	local_irq_restore(flags);
+
+	return err ? -EINVAL : len;
+}
+
+static ssize_t mv_eth_3_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	int             err;
+	unsigned int    p, i, v;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	err = p = i = v = 0;
+	sscanf(buf, "%d %d %d", &p, &i, &v);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "txp_rate")) {
+        if (v == 0) {
+            printk("Invalid value for rate limit %d \n", v );
+            return 1;
+	    }
+		err = mvNetaTxpRateSet(p, i, v);
+	} else if (!strcmp(name, "txp_burst")) {
+		err = mvNetaTxpBurstSet(p, i, v);
+	} else if (!strcmp(name, "ejp")) {
+		err = mvNetaTxpEjpSet(p, i, v);
+	} else if (!strcmp(name, "rxq_size")) {
+		err = mv_eth_ctrl_rxq_size_set(p, i, v);
+	} else if (!strcmp(name, "rxq_pkts_coal")) {
+		err = mv_eth_rx_ptks_coal_set(p, i, v);
+	} else if (!strcmp(name, "rxq_time_coal")) {
+		err = mv_eth_rx_time_coal_set(p, i, v);
+	} else if (!strcmp(name, "rxq")) {
+		mvNetaRxqShow(p, i, v);
+	} else if (!strcmp(name, "rxq_regs")) {
+		mvNetaRxqRegs(p, i);
+	} else if (!strcmp(name, "buf_num")) {
+		err = mv_eth_ctrl_port_buf_num_set(p, i, v);
+	} else if (!strcmp(name, "rx_reset")) {
+		err = mv_eth_rx_reset(p);
+	} else if (!strcmp(name, "txp_reset")) {
+		err = mv_eth_txp_reset(p, i);
+	} else if (!strcmp(name, "rx_weight")) {
+		err = mv_eth_ctrl_set_poll_rx_weight(p, i);
+	} else if (!strcmp(name, "tx_done")) {
+		mv_eth_ctrl_txdone(p);
+	} else if (!strcmp(name, "rxq_type")) {
+		err = run_rxq_type(p, i, v);
+	} else {
+		err = 1;
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	}
+
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: error %d\n", __func__, err);
+
+	return err ? -EINVAL : len;
+}
+
+static ssize_t mv_eth_4_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	int             err;
+	unsigned int    p, txp, txq, v;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	err = p = txp = txq = v = 0;
+	sscanf(buf, "%d %d %d %d", &p, &txp, &txq, &v);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "txq_def")) {
+		err = mv_eth_ctrl_txq_cpu_def(p, txp, txq, v);
+	} else if (!strcmp(name, "cntrs")) {
+		mvEthPortCounters(p, txp);
+		mvEthPortRmonCounters(p, txp);
+	} else if (!strcmp(name, "wrr_regs")) {
+		mvEthTxpWrrRegs(p, txp);
+	} else if (!strcmp(name, "txp_regs")) {
+		mvNetaTxpRegs(p, txp);
+	} else if (!strcmp(name, "txq_rate")) {
+		err = mvNetaTxqRateSet(p, txp, txq, v);
+	} else if (!strcmp(name, "txq_burst")) {
+		err = mvNetaTxqBurstSet(p, txp, txq, v);
+	} else if (!strcmp(name, "txq_wrr")) {
+		if (v == 0)
+			err = mvNetaTxqFixPrioSet(p, txp, txq);
+		else
+			err = mvNetaTxqWrrPrioSet(p, txp, txq, v);
+	} else if (!strcmp(name, "txq_size")) {
+		err = mv_eth_ctrl_txq_size_set(p, txp, txq, v);
+	} else if (!strcmp(name, "txq_coal")) {
+		mv_eth_tx_done_ptks_coal_set(p, txp, txq, v);
+	} else if (!strcmp(name, "txq")) {
+		mvNetaTxqShow(p, txp, txq, v);
+	} else if (!strcmp(name, "txq_regs")) {
+		mvNetaTxqRegs(p, txp, txq);
+	} else {
+		err = 1;
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	}
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: error %d\n", __func__, err);
+
+	return err ? -EINVAL : len;
+}
+
+static DEVICE_ATTR(rxq,	        S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(txq,         S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(rxq_size,    S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(rxq_pkts_coal, S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(rxq_time_coal, S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(rx_reset,    S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(txq_size,    S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(txq_coal,    S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(txq_def,     S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(txq_wrr,     S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(txq_rate,    S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(txq_burst,   S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(txp_rate,    S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(txp_burst,   S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(txp_reset,   S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(ejp,         S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(buf_num,     S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(rxq_tos,     S_IWUSR, mv_eth_show, mv_eth_3_hex_store);
+static DEVICE_ATTR(rxq_vlan,    S_IWUSR, mv_eth_show, mv_eth_3_hex_store);
+static DEVICE_ATTR(txq_tos,     S_IWUSR, mv_eth_show, mv_eth_3_hex_store);
+static DEVICE_ATTR(mh_en,       S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(mh_2B,       S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(tx_cmd,      S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(tx_nopad,    S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(debug,       S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(wrr_regs,    S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(cntrs,       S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(port,        S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(dev_name,    S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(rxq_regs,    S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(txq_regs,    S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(mac,         S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(vprio,       S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(tos,         S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(stats,       S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(skb,	        S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(pon_if_name,	S_IRUSR, mv_eth_show, NULL);
+static DEVICE_ATTR(ports,       S_IRUSR, mv_eth_show, NULL);
+static DEVICE_ATTR(help,        S_IRUSR, mv_eth_show, NULL);
+static DEVICE_ATTR(rx_weight,   S_IWUSR, NULL, mv_eth_3_store);
+static DEVICE_ATTR(p_regs,      S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(gmac_regs,   S_IWUSR, mv_eth_show, mv_eth_port_store);
+static DEVICE_ATTR(txp_regs,    S_IWUSR, mv_eth_show, mv_eth_4_store);
+static DEVICE_ATTR(rxq_type,    S_IWUSR, mv_eth_show, mv_eth_3_store);
+static DEVICE_ATTR(tx_done,     S_IWUSR, mv_eth_show, mv_eth_3_store);
+#ifdef CONFIG_MV_ETH_PNC
+static DEVICE_ATTR(pnc,         S_IWUSR, NULL, mv_eth_port_store);
+#endif /* CONFIG_MV_ETH_PNC */
+static DEVICE_ATTR(cpu_group,   S_IWUSR, mv_eth_show, mv_eth_3_hex_store);
+static DEVICE_ATTR(rxq_group,   S_IWUSR, mv_eth_show, mv_eth_3_hex_store);
+static DEVICE_ATTR(napi,        S_IWUSR, mv_eth_show, mv_eth_port_store);
+
+static struct attribute *mv_eth_attrs[] = {
+
+	&dev_attr_rxq.attr,
+	&dev_attr_txq.attr,
+	&dev_attr_rxq_time_coal.attr,
+	&dev_attr_rx_reset.attr,
+	&dev_attr_rxq_size.attr,
+	&dev_attr_rxq_pkts_coal.attr,
+	&dev_attr_txq_size.attr,
+	&dev_attr_txq_coal.attr,
+	&dev_attr_txq_def.attr,
+	&dev_attr_txq_wrr.attr,
+	&dev_attr_txq_rate.attr,
+	&dev_attr_txq_burst.attr,
+	&dev_attr_txp_rate.attr,
+	&dev_attr_txp_burst.attr,
+	&dev_attr_txp_reset.attr,
+	&dev_attr_ejp.attr,
+	&dev_attr_buf_num.attr,
+	&dev_attr_rxq_tos.attr,
+	&dev_attr_rxq_vlan.attr,
+	&dev_attr_txq_tos.attr,
+	&dev_attr_mh_en.attr,
+	&dev_attr_mh_2B.attr,
+	&dev_attr_tx_cmd.attr,
+	&dev_attr_tx_nopad.attr,
+	&dev_attr_debug.attr,
+	&dev_attr_wrr_regs.attr,
+    &dev_attr_dev_name.attr,
+	&dev_attr_rxq_regs.attr,
+	&dev_attr_txq_regs.attr,
+	&dev_attr_port.attr,
+	&dev_attr_stats.attr,
+	&dev_attr_cntrs.attr,
+	&dev_attr_ports.attr,
+	&dev_attr_tos.attr,
+	&dev_attr_mac.attr,
+	&dev_attr_vprio.attr,
+	&dev_attr_skb.attr,
+    &dev_attr_pon_if_name.attr,
+	&dev_attr_p_regs.attr,
+	&dev_attr_gmac_regs.attr,
+	&dev_attr_txp_regs.attr,
+	&dev_attr_rxq_type.attr,
+	&dev_attr_tx_done.attr,
+	&dev_attr_help.attr,
+	&dev_attr_rx_weight.attr,
+#ifdef CONFIG_MV_ETH_PNC
+    &dev_attr_pnc.attr,
+#endif /* CONFIG_MV_ETH_PNC */
+	&dev_attr_cpu_group.attr,
+	&dev_attr_rxq_group.attr,
+	&dev_attr_napi.attr,
+	NULL
+};
+
+static struct attribute_group mv_eth_group = {
+	.name = "gbe",
+	.attrs = mv_eth_attrs,
+};
+
+int __devinit mv_eth_sysfs_init(void)
+{
+	int err;
+	struct device *pd;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	if (!pd) {
+		platform_device_register_simple("neta", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR"%s: cannot find neta device\n", __func__);
+		pd = &platform_bus;
+	}
+
+	err = sysfs_create_group(&pd->kobj, &mv_eth_group);
+	if (err) {
+		printk(KERN_INFO "sysfs group failed %d\n", err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+module_init(mv_eth_sysfs_init);
+
+MODULE_AUTHOR("Kostya Belezko");
+MODULE_DESCRIPTION("sysfs for marvell GbE");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_tool.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_tool.c
new file mode 100755
index 0000000..df28415
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_tool.c
@@ -0,0 +1,837 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <linux/mii.h>
+
+#include "mvOs.h"
+#include "mvDebug.h"
+#include "dbg-trace.h"
+#include "mvSysHwConfig.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "eth-phy/mvEthPhy.h"
+#include "mvSysEthPhyApi.h"
+#include "mvSysNetaApi.h"
+
+
+#include "gbe/mvNeta.h"
+#include "bm/mvBm.h"
+#include "pnc/mvPnc.h"
+
+#include "mv_switch.h"
+#include "mv_netdev.h"
+#include "mv_eth_tool.h"
+
+#include "mvOs.h"
+#include "mvSysHwConfig.h"
+
+#define MV_ETH_TOOL_AN_TIMEOUT	5000
+
+
+static int isSwitch(struct eth_port *priv)
+{
+	return (priv->flags & (MV_ETH_F_SWITCH | MV_ETH_F_EXT_SWITCH));
+}
+
+
+/******************************************************************************
+* mv_eth_tool_restore_settings
+* Description:
+*	restore saved speed/dublex/an settings
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	0 for success
+*
+*******************************************************************************/
+int mv_eth_tool_restore_settings(struct net_device *netdev)
+{
+	struct eth_port 	*priv = MV_ETH_PRIV(netdev);
+	int 				mv_phy_speed, mv_phy_duplex;
+	MV_U32			    mv_phy_addr = mvBoardPhyAddrGet(priv->port);
+	MV_ETH_PORT_SPEED	mv_mac_speed;
+	MV_ETH_PORT_DUPLEX	mv_mac_duplex;
+	int			err = -EINVAL;
+
+	 if ((priv == NULL) || (isSwitch(priv)))
+		 return -EOPNOTSUPP;
+
+	switch (priv->speed_cfg) {
+	case SPEED_10:
+		mv_phy_speed  = 0;
+		mv_mac_speed = MV_ETH_SPEED_10;
+		break;
+	case SPEED_100:
+		mv_phy_speed  = 1;
+		mv_mac_speed = MV_ETH_SPEED_100;
+		break;
+	case SPEED_1000:
+		mv_phy_speed  = 2;
+		mv_mac_speed = MV_ETH_SPEED_1000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (priv->duplex_cfg) {
+	case DUPLEX_HALF:
+		mv_phy_duplex = 0;
+		mv_mac_duplex = MV_ETH_DUPLEX_HALF;
+		break;
+	case DUPLEX_FULL:
+		mv_phy_duplex = 1;
+		mv_mac_duplex = MV_ETH_DUPLEX_FULL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (priv->autoneg_cfg == AUTONEG_ENABLE) {
+		err = mvNetaSpeedDuplexSet(priv->port, MV_ETH_SPEED_AN, MV_ETH_DUPLEX_AN);
+		if (!err)
+			err = mvEthPhyAdvertiseSet(mv_phy_addr, priv->advertise_cfg);
+		/* Restart AN on PHY enables it */
+		if (!err) {
+
+			err = mvEthPhyRestartAN(mv_phy_addr, MV_ETH_TOOL_AN_TIMEOUT);
+			if (err == MV_TIMEOUT) {
+				MV_ETH_PORT_STATUS ps;
+
+				mvNetaLinkStatus(priv->port, &ps);
+
+				if (!ps.linkup)
+					err = 0;
+			}
+		}
+	} else if (priv->autoneg_cfg == AUTONEG_DISABLE) {
+		err = mvEthPhyDisableAN(mv_phy_addr, mv_phy_speed, mv_phy_duplex);
+		if (!err)
+			err = mvNetaSpeedDuplexSet(priv->port, mv_mac_speed, mv_mac_duplex);
+	} else {
+		err = -EINVAL;
+	}
+	return err;
+}
+
+
+
+
+/******************************************************************************
+* mv_eth_tool_get_settings
+* Description:
+*	ethtool get standard port settings
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	cmd		command (settings)
+* RETURN:
+*	0 for success
+*
+*******************************************************************************/
+int mv_eth_tool_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct eth_port 	*priv = MV_ETH_PRIV(netdev);
+	u16			lp_ad, stat1000;
+	MV_U32			mv_phy_addr;
+	MV_ETH_PORT_SPEED 	speed;
+	MV_ETH_PORT_DUPLEX 	duplex;
+	MV_ETH_PORT_STATUS      status;
+
+	if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
+		printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
+		return -EOPNOTSUPP;
+	}
+
+	cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half
+			| SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII
+			| SUPPORTED_1000baseT_Full);
+
+	mv_phy_addr = mvBoardPhyAddrGet(priv->port);
+
+	mvNetaLinkStatus(priv->port, &status);
+
+	switch (status.speed) {
+	case MV_ETH_SPEED_1000:
+		cmd->speed = SPEED_1000;
+		break;
+	case MV_ETH_SPEED_100:
+		cmd->speed = SPEED_100;
+		break;
+	case MV_ETH_SPEED_10:
+		cmd->speed = SPEED_10;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (status.duplex == MV_ETH_DUPLEX_FULL)
+		cmd->duplex = 1;
+	else
+		cmd->duplex = 0;
+
+	cmd->port = PORT_MII;
+	cmd->phy_address = mv_phy_addr;
+	cmd->transceiver = XCVR_INTERNAL;
+	/* check if speed and duplex are AN */
+	mvNetaSpeedDuplexGet(priv->port, &speed, &duplex);
+	if (speed == MV_ETH_SPEED_AN && duplex == MV_ETH_DUPLEX_AN) {
+		cmd->lp_advertising = cmd->advertising = 0;
+		cmd->autoneg = AUTONEG_ENABLE;
+		mvEthPhyAdvertiseGet(mv_phy_addr, (MV_U16 *)&(cmd->advertising));
+
+		mvEthPhyRegRead(mv_phy_addr, MII_LPA, &lp_ad);
+		if (lp_ad & LPA_LPACK)
+			cmd->lp_advertising |= ADVERTISED_Autoneg;
+		if (lp_ad & ADVERTISE_10HALF)
+			cmd->lp_advertising |= ADVERTISED_10baseT_Half;
+		if (lp_ad & ADVERTISE_10FULL)
+			cmd->lp_advertising |= ADVERTISED_10baseT_Full;
+		if (lp_ad & ADVERTISE_100HALF)
+			cmd->lp_advertising |= ADVERTISED_100baseT_Half;
+		if (lp_ad & ADVERTISE_100FULL)
+			cmd->lp_advertising |= ADVERTISED_100baseT_Full;
+
+		mvEthPhyRegRead(mv_phy_addr, MII_STAT1000, &stat1000);
+		if (stat1000 & LPA_1000HALF)
+			cmd->lp_advertising |= ADVERTISED_1000baseT_Half;
+		if (stat1000 & LPA_1000FULL)
+			cmd->lp_advertising |= ADVERTISED_1000baseT_Full;
+	} else
+		cmd->autoneg = AUTONEG_DISABLE;
+
+	return 0;
+}
+
+
+/******************************************************************************
+* mv_eth_tool_set_settings
+* Description:
+*	ethtool set standard port settings
+* INPUT:
+*	netdev		Network device structure pointer
+*	cmd		command (settings)
+* OUTPUT
+*	None
+* RETURN:
+*	0 for success
+*
+*******************************************************************************/
+int mv_eth_tool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct eth_port *priv = MV_ETH_PRIV(dev);
+	int _speed, _duplex, _autoneg, _advertise, err;
+
+	if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
+		printk(KERN_ERR "%s is not supported on %s\n", __func__, dev->name);
+		return -EOPNOTSUPP;
+	}
+
+	_duplex  = priv->duplex_cfg;
+	_speed   = priv->speed_cfg;
+	_autoneg = priv->autoneg_cfg;
+	_advertise = priv->advertise_cfg;
+
+	priv->duplex_cfg = cmd->duplex;
+	priv->speed_cfg = cmd->speed;
+	priv->autoneg_cfg = cmd->autoneg;
+	priv->advertise_cfg = cmd->advertising;
+	err = mv_eth_tool_restore_settings(dev);
+
+	if (err) {
+		priv->duplex_cfg = _duplex;
+		priv->speed_cfg = _speed;
+		priv->autoneg_cfg = _autoneg;
+		priv->advertise_cfg = _advertise;
+	}
+	return err;
+}
+
+
+
+
+/******************************************************************************
+* mv_eth_tool_get_regs_len
+* Description:
+*	ethtool get registers array length
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	registers array length
+*
+*******************************************************************************/
+int mv_eth_tool_get_regs_len(struct net_device *netdev)
+{
+#define MV_ETH_TOOL_REGS_LEN 32
+
+	return (MV_ETH_TOOL_REGS_LEN * sizeof(uint32_t));
+}
+
+
+/******************************************************************************
+* mv_eth_tool_get_drvinfo
+* Description:
+*	ethtool get driver information
+* INPUT:
+*	netdev		Network device structure pointer
+*	info		driver information
+* OUTPUT
+*	info		driver information
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_drvinfo(struct net_device *netdev,
+			     struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, "mv_eth");
+	/*strcpy(info->version, LSP_VERSION);*/
+	strcpy(info->fw_version, "N/A");
+	strcpy(info->bus_info, "Mbus");
+/*   TBD
+	info->n_stats = MV_ETH_TOOL_STATS_LEN;
+*/
+	info->testinfo_len = 0;
+	info->regdump_len = mv_eth_tool_get_regs_len(netdev);
+	info->eedump_len = 0;
+}
+
+
+/******************************************************************************
+* mv_eth_tool_get_regs
+* Description:
+*	ethtool get registers array
+* INPUT:
+*	netdev		Network device structure pointer
+*	regs		registers information
+* OUTPUT
+*	p		registers array
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_regs(struct net_device *netdev,
+			  struct ethtool_regs *regs, void *p)
+{
+	struct eth_port	*priv = MV_ETH_PRIV(netdev);
+	uint32_t 	*regs_buff = p;
+
+	if ((priv == NULL) || MV_PON_PORT(priv->port)) {
+		printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
+		return;
+	}
+
+	memset(p, 0, MV_ETH_TOOL_REGS_LEN * sizeof(uint32_t));
+
+	regs->version = mvCtrlModelRevGet();
+
+	/* ETH port registers */
+	regs_buff[0]  = MV_REG_READ(ETH_PORT_STATUS_REG(priv->port));
+	regs_buff[1]  = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(priv->port));
+	regs_buff[2]  = MV_REG_READ(ETH_PORT_CONFIG_REG(priv->port));
+	regs_buff[3]  = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(priv->port));
+	regs_buff[4]  = MV_REG_READ(ETH_SDMA_CONFIG_REG(priv->port));
+/*	regs_buff[5]  = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(priv->port)); */
+	regs_buff[6]  = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(priv->port));
+	/* regs_buff[7]  = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(priv->port)); */
+	regs_buff[8]  = MV_REG_READ(ETH_INTR_CAUSE_REG(priv->port));
+	regs_buff[9]  = MV_REG_READ(ETH_INTR_CAUSE_EXT_REG(priv->port));
+	regs_buff[10] = MV_REG_READ(ETH_INTR_MASK_REG(priv->port));
+	regs_buff[11] = MV_REG_READ(ETH_INTR_MASK_EXT_REG(priv->port));
+	/* ETH Unit registers */
+	regs_buff[16] = MV_REG_READ(ETH_PHY_ADDR_REG(priv->port));
+	regs_buff[17] = MV_REG_READ(ETH_UNIT_INTR_CAUSE_REG(priv->port));
+	regs_buff[18] = MV_REG_READ(ETH_UNIT_INTR_MASK_REG(priv->port));
+	regs_buff[19] = MV_REG_READ(ETH_UNIT_ERROR_ADDR_REG(priv->port));
+	regs_buff[20] = MV_REG_READ(ETH_UNIT_INT_ADDR_ERROR_REG(priv->port));
+
+}
+
+
+
+
+/******************************************************************************
+* mv_eth_tool_nway_reset
+* Description:
+*	ethtool restart auto negotiation
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_nway_reset(struct net_device *netdev)
+{
+	struct eth_port *priv = MV_ETH_PRIV(netdev);
+	MV_U32	        phy_addr;
+
+	if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
+		printk(KERN_ERR "interface %s is not supported\n", netdev->name);
+		return -EOPNOTSUPP;
+	}
+
+	phy_addr = mvBoardPhyAddrGet(priv->port);
+	if (mvEthPhyRestartAN(phy_addr, MV_ETH_TOOL_AN_TIMEOUT) != MV_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_link
+* Description:
+*	ethtool get link status
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	0 if link is down, 1 if link is up
+*
+*******************************************************************************/
+u32 mv_eth_tool_get_link(struct net_device *netdev)
+{
+	struct eth_port     *pp = MV_ETH_PRIV(netdev);
+	struct eth_netdev   *dev_priv = MV_DEV_PRIV(netdev);
+
+	if (pp == NULL) {
+		printk(KERN_ERR "interface %s is not supported\n", netdev->name);
+		return -EOPNOTSUPP;
+	}
+
+	if (isSwitch(pp)) {
+		if (dev_priv == NULL)
+			return -EOPNOTSUPP;
+		return (dev_priv->link_map != 0);
+	}
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(pp->port))
+		return mv_pon_link_status();
+#endif /* CONFIG_MV_PON */
+
+	return mvNetaLinkIsUp(pp->port);
+}
+/******************************************************************************
+* mv_eth_tool_get_coalesce
+* Description:
+*	ethtool get RX/TX coalesce parameters
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	cmd		Coalesce parameters
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_get_coalesce(struct net_device *netdev,
+			     struct ethtool_coalesce *cmd)
+{
+	struct eth_port *pp = MV_ETH_PRIV(netdev);
+	/* get coal parameters only for rxq=0, txp=txq=0 !!!
+	   notice that if you use ethtool to set coal, then all queues have the same value */
+	cmd->rx_coalesce_usecs = mvNetaRxqTimeCoalGet(pp->port, 0);
+	cmd->rx_max_coalesced_frames = mvNetaRxqPktsCoalGet(pp->port, 0);
+	cmd->tx_max_coalesced_frames = mvNetaTxDonePktsCoalGet(pp->port, 0, 0);
+	return 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_set_coalesce
+* Description:
+*	ethtool set RX/TX coalesce parameters
+* INPUT:
+*	netdev		Network device structure pointer
+*	cmd		Coalesce parameters
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_coalesce(struct net_device *netdev,
+			     struct ethtool_coalesce *cmd)
+{
+	struct eth_port *pp = MV_ETH_PRIV(netdev);
+	int rxq, txp, txq;
+
+	/* can't set rx coalesce with both 0 pkts and 0 usecs,  tx coalesce supports only pkts */
+	if ((!cmd->rx_coalesce_usecs && !cmd->rx_max_coalesced_frames) || (!cmd->tx_max_coalesced_frames))
+		return -EPERM;
+
+	for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+		mv_eth_rx_ptks_coal_set(pp->port, rxq, cmd->rx_max_coalesced_frames);
+		mv_eth_rx_time_coal_set(pp->port, rxq, cmd->rx_coalesce_usecs);
+	}
+	for (txp = 0; txp < pp->txp_num; txp++)
+		for (txq = 0; txq < CONFIG_MV_ETH_TXQ; txq++)
+			mv_eth_tx_done_ptks_coal_set(pp->port, txp, txq, cmd->tx_max_coalesced_frames);
+
+	return 0;
+}
+
+
+/******************************************************************************
+* mv_eth_tool_get_ringparam
+* Description:
+*	ethtool get ring parameters
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	ring		Ring paranmeters
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_ringparam(struct net_device *netdev,
+				struct ethtool_ringparam *ring)
+{
+/*	printk("in %s \n",__FUNCTION__); */
+}
+
+/******************************************************************************
+* mv_eth_tool_get_pauseparam
+* Description:
+*	ethtool get pause parameters
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	pause		Pause paranmeters
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_pauseparam(struct net_device *netdev,
+				struct ethtool_pauseparam *pause)
+{
+	struct eth_port      *priv = MV_ETH_PRIV(netdev);
+	int                  port = priv->port;
+	MV_ETH_PORT_STATUS   portStatus;
+	MV_ETH_PORT_FC       flowCtrl;
+
+	if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
+		printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
+		return;
+	}
+
+	mvNetaFlowCtrlGet(port, &flowCtrl);
+	if ((flowCtrl == MV_ETH_FC_AN_NO) || (flowCtrl == MV_ETH_FC_AN_SYM) || (flowCtrl == MV_ETH_FC_AN_ASYM))
+		pause->autoneg = AUTONEG_ENABLE;
+	else
+		pause->autoneg = AUTONEG_DISABLE;
+
+	mvNetaLinkStatus(port, &portStatus);
+	if (portStatus.rxFc == MV_ETH_FC_DISABLE)
+		pause->rx_pause = 0;
+	else
+		pause->rx_pause = 1;
+
+	if (portStatus.txFc == MV_ETH_FC_DISABLE)
+		pause->tx_pause = 0;
+	else
+		pause->tx_pause = 1;
+}
+
+
+
+
+/******************************************************************************
+* mv_eth_tool_set_pauseparam
+* Description:
+*	ethtool configure pause parameters
+* INPUT:
+*	netdev		Network device structure pointer
+*	pause		Pause paranmeters
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_pauseparam(struct net_device *netdev,
+				struct ethtool_pauseparam *pause)
+{
+	struct eth_port *priv = MV_ETH_PRIV(netdev);
+	int				port = priv->port;
+	MV_U32			phy_addr;
+	MV_STATUS		status = MV_FAIL;
+
+	if ((priv == NULL) || (isSwitch(priv)) || (MV_PON_PORT(priv->port))) {
+		printk(KERN_ERR "%s is not supported on %s\n", __func__, netdev->name);
+		return -EOPNOTSUPP;
+	}
+
+	if (pause->rx_pause && pause->tx_pause) { /* Enable FC */
+		if (pause->autoneg) { /* autoneg enable */
+			status = mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_SYM);
+		} else { /* autoneg disable */
+			status = mvNetaFlowCtrlSet(port, MV_ETH_FC_ENABLE);
+		}
+	} else if (!pause->rx_pause && !pause->tx_pause) { /* Disable FC */
+		if (pause->autoneg) { /* autoneg enable */
+			status = mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_NO);
+		} else { /* autoneg disable */
+			status = mvNetaFlowCtrlSet(port, MV_ETH_FC_DISABLE);
+		}
+	}
+	/* Only symmetric change for RX and TX flow control is allowed */
+	if (status == MV_OK) {
+		phy_addr = mvBoardPhyAddrGet(priv->port);
+		status = mvEthPhyRestartAN(phy_addr, MV_ETH_TOOL_AN_TIMEOUT);
+	}
+	if (status != MV_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+/******************************************************************************
+* mv_eth_tool_get_rx_csum
+* Description:
+*	ethtool get RX checksum offloading status
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	RX checksum
+*
+*******************************************************************************/
+u32 mv_eth_tool_get_rx_csum(struct net_device *netdev)
+{
+#ifdef CONFIG_MV_ETH_RX_CSUM_OFFLOAD
+	struct eth_port *priv = MV_ETH_PRIV(netdev);
+
+	return (priv->rx_csum_offload != 0);
+#else
+	return 0;
+#endif
+}
+
+/******************************************************************************
+* mv_eth_tool_set_rx_csum
+* Description:
+*	ethtool enable/disable RX checksum offloading
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Command data
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_rx_csum(struct net_device *netdev, uint32_t data)
+{
+#ifdef CONFIG_MV_ETH_RX_CSUM_OFFLOAD
+	struct eth_port *priv = MV_ETH_PRIV(netdev);
+
+	priv->rx_csum_offload = data;
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
+}
+
+/******************************************************************************
+* mv_eth_tool_set_tx_csum
+* Description:
+*	ethtool enable/disable TX checksum offloading
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Command data
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+#ifdef CONFIG_MV_ETH_TX_CSUM_OFFLOAD
+	if (data) {
+		if (netdev->mtu > MV_ETH_TX_CSUM_MAX_SIZE) {
+			printk(KERN_ERR "Cannot set TX checksum when MTU > %d\n", MV_ETH_TX_CSUM_MAX_SIZE);
+			return -EOPNOTSUPP;
+		}
+		netdev->features |= NETIF_F_IP_CSUM;
+	} else {
+		netdev->features &= ~NETIF_F_IP_CSUM;
+	}
+
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif /* TX_CSUM_OFFLOAD */
+}
+
+
+/******************************************************************************
+* mv_eth_tool_set_tso
+* Description:
+*	ethtool enable/disable TCP segmentation offloading
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Command data
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_tso(struct net_device *netdev, uint32_t data)
+{
+#if defined(CONFIG_MV_ETH_TSO)
+	if (data)
+		netdev->features |= NETIF_F_TSO;
+	else
+		netdev->features &= ~NETIF_F_TSO;
+
+	return 0;
+#else
+	return -EOPNOTSUPP;
+#endif
+}
+/******************************************************************************
+* mv_eth_tool_set_ufo
+* Description:
+*	ethtool enable/disable UDP segmentation offloading
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Command data
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_ufo(struct net_device *netdev, uint32_t data)
+{
+/*	printk("in %s \n",__FUNCTION__);*/
+	return -EOPNOTSUPP;
+}
+/******************************************************************************
+* mv_eth_tool_get_strings
+* Description:
+*	ethtool get strings (used for statistics and self-test descriptions)
+* INPUT:
+*	netdev		Network device structure pointer
+*	stringset	strings parameters
+* OUTPUT
+*	data		output data
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_strings(struct net_device *netdev,
+			     uint32_t stringset, uint8_t *data)
+{
+/*	printk("in %s \n",__FUNCTION__);*/
+
+}
+
+/******************************************************************************
+* mv_eth_tool_get_stats_count
+* Description:
+*	ethtool get statistics count (number of stat. array entries)
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	statistics count
+*
+*******************************************************************************/
+int mv_eth_tool_get_stats_count(struct net_device *netdev)
+{
+/*	printk("in %s \n",__FUNCTION__);*/
+	return 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_ethtool_stats
+* Description:
+*	ethtool get statistics
+* INPUT:
+*	netdev		Network device structure pointer
+*	stats		stats parameters
+* OUTPUT
+*	data		output data
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_ethtool_stats(struct net_device *netdev,
+				   struct ethtool_stats *stats, uint64_t *data)
+{
+
+}
+
+const struct ethtool_ops mv_eth_tool_ops = {
+	.get_settings				= mv_eth_tool_get_settings,
+	.set_settings				= mv_eth_tool_set_settings,
+	.get_drvinfo				= mv_eth_tool_get_drvinfo,
+	.get_regs_len				= mv_eth_tool_get_regs_len,
+	.get_regs					= mv_eth_tool_get_regs,
+	.nway_reset					= mv_eth_tool_nway_reset,
+	.get_link					= mv_eth_tool_get_link,
+	.get_coalesce				= mv_eth_tool_get_coalesce,
+	.set_coalesce				= mv_eth_tool_set_coalesce,
+	.get_ringparam  			= mv_eth_tool_get_ringparam,
+	.get_pauseparam				= mv_eth_tool_get_pauseparam,
+	.set_pauseparam				= mv_eth_tool_set_pauseparam,
+	.get_rx_csum				= mv_eth_tool_get_rx_csum,
+	.set_rx_csum				= mv_eth_tool_set_rx_csum,
+	.get_tx_csum				= ethtool_op_get_tx_csum,
+	.set_tx_csum				= mv_eth_tool_set_tx_csum,
+	.get_sg						= ethtool_op_get_sg,
+	.set_sg						= ethtool_op_set_sg,
+	.get_tso					= ethtool_op_get_tso,
+	.set_tso					= mv_eth_tool_set_tso,
+	.get_ufo					= ethtool_op_get_ufo,
+	.set_ufo					= mv_eth_tool_set_ufo,
+	.get_strings				= mv_eth_tool_get_strings,
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
+	.get_stats_count			= mv_eth_tool_get_stats_count,
+#endif
+	.get_ethtool_stats			= mv_eth_tool_get_ethtool_stats,
+};
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_tool.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_tool.h
new file mode 100755
index 0000000..4e673e7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_eth_tool.h
@@ -0,0 +1,9 @@
+// mv_eth_tool.h
+#ifndef NET_DEV_MV_ETH_TOOL_H
+#define NET_DEV_MV_ETH_TOOL_H
+
+#include <linux/ethtool.h>
+
+extern const struct ethtool_ops mv_eth_tool_ops;
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_ethernet.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_ethernet.c
new file mode 100755
index 0000000..0450ddc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_ethernet.c
@@ -0,0 +1,416 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+
+#include "mvOs.h"
+#include "dbg-trace.h"
+#include "mvSysHwConfig.h"
+#include "boardEnv/mvBoardEnvLib.h"
+
+#include "eth-phy/mvEthPhy.h"
+#include "gbe/mvNeta.h"
+#include "pnc/mvPnc.h"
+
+#include "mv_netdev.h"
+
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+#include "mv_switch.h"
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+static int mv_eth_start(struct net_device *dev);
+static int mv_eth_set_mac_addr_internals(struct net_device *dev, void *addr);
+
+/***********************************************************
+ * mv_eth_start --                                         *
+ *   start a network device. connect and enable interrupts *
+ *   set hw defaults. fill rx buffers. restart phy link    *
+ *   auto neg. set device link flags. report status.       *
+ ***********************************************************/
+static int mv_eth_start(struct net_device *dev)
+{
+	struct eth_port *priv = MV_ETH_PRIV(dev);
+	int group;
+
+	/* in default link is down */
+	netif_carrier_off(dev);
+
+	/* Stop the TX queue - it will be enabled upon PHY status change after link-up interrupt/timer */
+	netif_stop_queue(dev);
+
+	/* fill rx buffers, start rx/tx activity, set coalescing */
+	if (mv_eth_start_internals(priv, dev->mtu) != 0) {
+		printk(KERN_ERR "%s: start internals failed\n", dev->name);
+		goto error;
+	}
+
+	/* enable polling on the port, must be used after netif_poll_disable */
+	if (priv->flags & MV_ETH_F_CONNECT_LINUX)
+		for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
+			napi_enable(priv->napiGroup[group]);
+
+
+	if ((priv->flags & MV_ETH_F_LINK_UP) && !(priv->flags & MV_ETH_F_EXT_SWITCH)) {
+
+		if (mv_eth_ctrl_is_tx_enabled(priv)) {
+			netif_carrier_on(dev);
+			netif_wake_queue(dev);
+		}
+		printk(KERN_NOTICE "%s: link up\n", dev->name);
+	}
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+	if (priv->flags & MV_ETH_F_EXT_SWITCH) {
+		struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+
+		dev_priv->link_map = 0;
+		mv_switch_link_update_event(dev_priv->port_map, 1);
+	}
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+	if (priv->flags & MV_ETH_F_CONNECT_LINUX) {
+		/* connect to port interrupt line */
+		if (request_irq(dev->irq, mv_eth_isr, (IRQF_DISABLED|IRQF_SAMPLE_RANDOM), "mv_eth", priv)) {
+			printk(KERN_ERR "cannot request irq %d for %s port %d\n", dev->irq, dev->name, priv->port);
+			if (priv->flags & MV_ETH_F_CONNECT_LINUX)
+				napi_disable(priv->napiGroup[CPU_GROUP_DEF]);
+			goto error;
+		}
+
+		/* unmask interrupts */
+		mv_eth_interrupts_unmask(priv);
+
+		printk(KERN_NOTICE "%s: started\n", dev->name);
+	}
+	return 0;
+
+error:
+	printk(KERN_ERR "%s: start failed\n", dev->name);
+	return -1;
+}
+
+/***********************************************************
+ * mv_eth_stop --                                          *
+ *   stop interface with linux core. stop port activity.   *
+ *   free skb's from rings.                                *
+ ***********************************************************/
+int mv_eth_stop(struct net_device *dev)
+{
+	struct eth_port *priv = MV_ETH_PRIV(dev);
+	int group;
+
+	/* first make sure that the port finished its Rx polling - see tg3 */
+	for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
+		napi_disable(priv->napiGroup[group]);
+
+	/* stop upper layer */
+	netif_carrier_off(dev);
+	netif_stop_queue(dev);
+
+	/* stop tx/rx activity, mask all interrupts, relese skb in rings,*/
+	mv_eth_stop_internals(priv);
+
+	del_timer(&priv->tx_done_timer);
+	clear_bit(MV_ETH_F_TX_DONE_TIMER_BIT, &(priv->flags));
+	del_timer(&priv->cleanup_timer);
+	clear_bit(MV_ETH_F_CLEANUP_TIMER_BIT, &(priv->flags));
+
+	if (dev->irq != 0)
+		free_irq(dev->irq, priv);
+
+	printk(KERN_NOTICE "%s: stopped\n", dev->name);
+
+	return 0;
+}
+
+
+int mv_eth_change_mtu(struct net_device *dev, int mtu)
+{
+	int old_mtu = dev->mtu;
+
+	mtu = mv_eth_check_mtu_valid(dev, mtu);
+	if (mtu < 0)
+		return -EINVAL;
+
+	if (!netif_running(dev)) {
+		if (mv_eth_change_mtu_internals(dev, mtu) == -1)
+			goto error;
+
+		printk(KERN_NOTICE "%s: change mtu %d (buffer-size %d) to %d (buffer-size %d)\n",
+				dev->name, old_mtu, RX_PKT_SIZE(old_mtu),
+				dev->mtu, RX_PKT_SIZE(dev->mtu));
+		return 0;
+	}
+
+	if (mv_eth_check_mtu_internals(dev, mtu))
+		goto error;
+
+	if (mv_eth_stop(dev)) {
+		printk(KERN_ERR "%s: stop interface failed\n", dev->name);
+		goto error;
+	}
+
+	if (mv_eth_change_mtu_internals(dev, mtu) == -1) {
+		printk(KERN_ERR "%s change mtu internals failed\n", dev->name);
+		goto error;
+	}
+
+	if (mv_eth_start(dev)) {
+		printk(KERN_ERR "%s: start interface failed\n", dev->name);
+		goto error;
+	}
+	printk(KERN_NOTICE "%s: change mtu %d (buffer-size %d) to %d (buffer-size %d)\n",
+				dev->name, old_mtu, RX_PKT_SIZE(old_mtu), dev->mtu,
+				RX_PKT_SIZE(dev->mtu));
+	return 0;
+
+error:
+	printk(KERN_ERR "%s: change mtu failed\n", dev->name);
+	return -1;
+}
+
+/***********************************************************
+ * eth_set_mac_addr --                                   *
+ *   stop port activity. set new addr in device and hw.    *
+ *   restart port activity.                                *
+ ***********************************************************/
+static int mv_eth_set_mac_addr_internals(struct net_device *dev, void *addr)
+{
+	struct eth_port *priv = MV_ETH_PRIV(dev);
+	u8              *mac = &(((u8 *)addr)[2]);  /* skip on first 2B (ether HW addr type) */
+	int             i;
+
+#ifdef CONFIG_MV_ETH_PNC
+	if (mv_eth_pnc_ctrl_en) {
+		if (pnc_mac_me(priv->port, mac, CONFIG_MV_ETH_RXQ_DEF)) {
+			printk(KERN_ERR "%s: ethSetMacAddr failed\n", dev->name);
+			return -1;
+		}
+	} else {
+		printk(KERN_ERR "%s: PNC control is disabled\n", __func__);
+		return -1;
+	}
+#else
+	/* remove previous address table entry */
+	if (mvNetaMacAddrSet(priv->port, dev->dev_addr, -1) != MV_OK) {
+		printk(KERN_ERR "%s: ethSetMacAddr failed\n", dev->name);
+		return -1;
+	}
+
+	/* set new addr in hw */
+	if (mvNetaMacAddrSet(priv->port, mac, CONFIG_MV_ETH_RXQ_DEF) != MV_OK) {
+		printk(KERN_ERR "%s: ethSetMacAddr failed\n", dev->name);
+		return -1;
+	}
+#endif /* CONFIG_MV_ETH_PNC */
+
+	/* set addr in the device */
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = mac[i];
+
+	printk(KERN_NOTICE "%s: mac address changed\n", dev->name);
+
+	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_PNC
+void mv_eth_set_multicast_list(struct net_device *dev)
+{
+	struct eth_port     *priv = MV_ETH_PRIV(dev);
+	int                 rxq = CONFIG_MV_ETH_RXQ_DEF;
+/*
+	printk("%s - mv_eth_set_multicast_list: flags=0x%x, mc_count=%d\n",
+		dev->name, dev->flags, dev->mc_count);
+*/
+	if (!mv_eth_pnc_ctrl_en) {
+		printk(KERN_ERR "%s: PNC control is disabled\n", __func__);
+		return;
+	}
+
+	if (dev->flags & IFF_PROMISC) {
+		/* Accept all */
+		pnc_mac_me(priv->port, NULL, rxq);
+		pnc_mcast_all(priv->port, 1);
+	} else {
+		/* Accept Unicast to me */
+		pnc_mac_me(priv->port, dev->dev_addr, rxq);
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Accept all multicast */
+			pnc_mcast_all(priv->port, 1);
+		} else {
+			/* Accept only initialized Multicast */
+			pnc_mcast_all(priv->port, 0);
+			pnc_mcast_me(priv->port, NULL);
+
+			/* Number of entires for all ports is restricted by CONFIG_MV_ETH_PNC_MCAST_NUM */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+			if (!netdev_mc_empty(dev)) {
+				struct netdev_hw_addr *ha;
+
+				netdev_for_each_mc_addr(ha, dev) {
+					if (pnc_mcast_me(priv->port, ha->addr)) {
+						printk(KERN_ERR "%s: Mcast init failed\n", dev->name);
+						break;
+					}
+				}
+			}
+#else
+			{
+				struct dev_mc_list *curr_addr = dev->mc_list;
+				int                i;
+				for (i = 0; i < dev->mc_count; i++, curr_addr = curr_addr->next) {
+					if (!curr_addr)
+						break;
+					if (pnc_mcast_me(priv->port, curr_addr->dmi_addr)) {
+						printk(KERN_ERR "%s: Mcast init failed - %d of %d\n",
+							dev->name, i, dev->mc_count);
+						break;
+					}
+				}
+			}
+#endif /* KERNEL_VERSION >= 2.6.34 */
+		}
+	}
+}
+#else /* !CONFIG_MV_ETH_PNC - legacy parser */
+void mv_eth_set_multicast_list(struct net_device *dev)
+{
+	struct eth_port    *priv = MV_ETH_PRIV(dev);
+	int                queue = CONFIG_MV_ETH_RXQ_DEF;
+
+	if (dev->flags & IFF_PROMISC) {
+		/* Accept all: Multicast + Unicast */
+		mvNetaRxUnicastPromiscSet(priv->port, MV_TRUE);
+		mvNetaSetUcastTable(priv->port, queue);
+		mvNetaSetSpecialMcastTable(priv->port, queue);
+		mvNetaSetOtherMcastTable(priv->port, queue);
+	} else {
+		/* Accept single Unicast */
+		mvNetaRxUnicastPromiscSet(priv->port, MV_FALSE);
+		mvNetaSetUcastTable(priv->port, -1);
+		if (mvNetaMacAddrSet(priv->port, dev->dev_addr, queue) != MV_OK)
+			printk(KERN_ERR "%s: netaSetMacAddr failed\n", dev->name);
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Accept all Multicast */
+			mvNetaSetSpecialMcastTable(priv->port, queue);
+			mvNetaSetOtherMcastTable(priv->port, queue);
+		} else {
+			/* Accept only initialized Multicast */
+			mvNetaSetSpecialMcastTable(priv->port, -1);
+			mvNetaSetOtherMcastTable(priv->port, -1);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+			if (!netdev_mc_empty(dev)) {
+				struct netdev_hw_addr *ha;
+
+				netdev_for_each_mc_addr(ha, dev) {
+					mvNetaMcastAddrSet(priv->port, ha->addr, queue);
+				}
+			}
+#else
+			{
+				struct dev_mc_list *curr_addr = dev->mc_list;
+				int                i;
+				for (i = 0; i < dev->mc_count; i++, curr_addr = curr_addr->next) {
+					if (!curr_addr)
+						break;
+					mvNetaMcastAddrSet(priv->port, curr_addr->dmi_addr, queue);
+				}
+			}
+#endif /* KERNEL_VERSION >= 2.6.34 */
+		}
+	}
+}
+#endif /* CONFIG_MV_ETH_PNC */
+
+
+int     mv_eth_set_mac_addr(struct net_device *dev, void *addr)
+{
+	if (!netif_running(dev)) {
+		if (mv_eth_set_mac_addr_internals(dev, addr) == -1)
+			goto error;
+		return 0;
+	}
+
+	if (mv_eth_stop(dev)) {
+		printk(KERN_ERR "%s: stop interface failed\n", dev->name);
+		goto error;
+	}
+
+	if (mv_eth_set_mac_addr_internals(dev, addr) == -1)
+		goto error;
+
+	if (mv_eth_start(dev)) {
+		printk(KERN_ERR "%s: start interface failed\n", dev->name);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	printk(KERN_ERR "%s: set mac addr failed\n", dev->name);
+	return -1;
+}
+
+
+/************************************************************
+ * mv_eth_open -- Restore MAC address and call to   *
+ *                mv_eth_start                               *
+ ************************************************************/
+int mv_eth_open(struct net_device *dev)
+{
+	struct eth_port	*priv = MV_ETH_PRIV(dev);
+	int         queue = CONFIG_MV_ETH_RXQ_DEF;
+
+#ifdef CONFIG_MV_ETH_PNC
+	if (mv_eth_pnc_ctrl_en) {
+		if (pnc_mac_me(priv->port, dev->dev_addr, queue)) {
+			printk(KERN_ERR "%s: ethSetMacAddr failed\n", dev->name);
+			return -1;
+		}
+	} else
+		printk(KERN_ERR "%s: PNC control is disabled\n", __func__);
+#else /* Legacy parser */
+	if (mvNetaMacAddrSet(priv->port, dev->dev_addr, queue) != MV_OK) {
+		printk(KERN_ERR "%s: ethSetMacAddr failed\n", dev->name);
+		return -1;
+	}
+#endif /* CONFIG_MV_ETH_PNC */
+
+	if (mv_eth_start(dev)) {
+		printk(KERN_ERR "%s: start interface failed\n", dev->name);
+		return -1;
+	}
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.c
new file mode 100755
index 0000000..6d68843
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.c
@@ -0,0 +1,5415 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/inetdevice.h>
+#include <linux/mv_neta.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+
+#include "mvOs.h"
+#include "mvDebug.h"
+#include "dbg-trace.h"
+#include "mvSysHwConfig.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "eth-phy/mvEthPhy.h"
+#include "mvSysEthPhyApi.h"
+#include "mvSysNetaApi.h"
+
+#include "gbe/mvNeta.h"
+#include "bm/mvBm.h"
+#include "pnc/mvPnc.h"
+#include "pnc/mvTcam.h"
+#include "pmt/mvPmt.h"
+
+#include "mv_switch.h"
+
+#include "mv_netdev.h"
+#include "mv_eth_tool.h"
+
+#include "cpu/mvCpuCntrs.h"
+
+
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+MV_CPU_CNTRS_EVENT	*event0 = NULL;
+MV_CPU_CNTRS_EVENT	*event1 = NULL;
+MV_CPU_CNTRS_EVENT	*event2 = NULL;
+MV_CPU_CNTRS_EVENT	*event3 = NULL;
+MV_CPU_CNTRS_EVENT	*event4 = NULL;
+MV_CPU_CNTRS_EVENT	*event5 = NULL;
+#endif /* CONFIG_MV_CPU_PERF_CNTRS */
+
+unsigned int ext_switch_port_mask = 0;
+
+void handle_group_affinity(int port);
+void set_rxq_affinity(struct eth_port *pp, MV_U32 rxqAffinity, int group);
+static inline int mv_eth_tx_policy(struct eth_port *pp, struct sk_buff *skb);
+
+/* uncomment if you want to debug the SKB recycle feature */
+/* #define ETH_SKB_DEBUG */
+
+#ifdef CONFIG_MV_ETH_PNC
+unsigned int mv_eth_pnc_ctrl_en = 1;
+#else
+unsigned int mv_eth_pnc_ctrl_en = 0;
+#endif /* CONFIG_MV_ETH_PNC */
+
+int mv_eth_ctrl_pnc(int en)
+{
+	mv_eth_pnc_ctrl_en = en;
+	return 0;
+}
+
+int mv_eth_ctrl_pnc_get(void)
+{
+	return mv_eth_pnc_ctrl_en;
+}
+
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+int mv_ctrl_recycle = CONFIG_NET_SKB_RECYCLE_DEF;
+EXPORT_SYMBOL(mv_ctrl_recycle);
+
+int mv_eth_ctrl_recycle(int en)
+{
+	mv_ctrl_recycle = en;
+	return 0;
+}
+#else
+int mv_eth_ctrl_recycle(int en)
+{
+	printk(KERN_ERR "SKB recycle is not supported\n");
+	return 1;
+}
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+extern u8 mvMacAddr[CONFIG_MV_ETH_PORTS_NUM][MV_MAC_ADDR_SIZE];
+extern u16 mvMtu[CONFIG_MV_ETH_PORTS_NUM];
+
+extern unsigned int switch_enabled_ports;
+
+struct bm_pool mv_eth_pool[MV_ETH_BM_POOLS];
+struct eth_port **mv_eth_ports;
+struct net_device **mv_net_devs;
+
+int mv_net_devs_num = 0;
+int mv_ctrl_txdone = CONFIG_MV_ETH_TXDONE_COAL_PKTS;
+EXPORT_SYMBOL(mv_ctrl_txdone);
+
+/*
+ * Static declarations
+ */
+static int mv_eth_ports_num = 0;
+static int mv_net_devs_max = 0;
+
+static int mv_eth_initialized = 0;
+
+/*
+ * Local functions
+ */
+static void mv_eth_txq_delete(struct eth_port *pp, struct tx_queue *txq_ctrl);
+static void mv_eth_tx_timeout(struct net_device *dev);
+static int  mv_eth_tx(struct sk_buff *skb, struct net_device *dev);
+static void mv_eth_tx_frag_process(struct eth_port *pp, struct sk_buff *skb, struct tx_queue *txq_ctrl, u16 flags);
+
+static void mv_eth_config_show(void);
+static int  mv_eth_priv_init(struct eth_port *pp, int port);
+static void mv_eth_priv_cleanup(struct eth_port *pp);
+static int  mv_eth_config_get(struct eth_port *pp, u8 *mac);
+static int  mv_eth_hal_init(struct eth_port *pp);
+struct net_device *mv_eth_netdev_init(struct eth_port *pp, int mtu, u8 *mac);
+static void mv_eth_netdev_set_features(struct net_device *dev);
+static void mv_eth_netdev_update_features(struct net_device *dev);
+
+static MV_STATUS mv_eth_pool_create(int pool, int capacity);
+static int mv_eth_pool_add(int pool, int buf_num);
+static int mv_eth_pool_free(int pool, int num);
+static int mv_eth_pool_destroy(int pool);
+
+#ifdef CONFIG_MV_ETH_TSO
+int mv_eth_tx_tso(struct sk_buff *skb, struct net_device *dev, struct mv_eth_tx_spec *tx_spec,
+		struct tx_queue *txq_ctrl);
+#endif
+
+/* Get the configuration string from the Kernel Command Line */
+static char *port0_config_str = NULL, *port1_config_str = NULL, *port2_config_str = NULL, *port3_config_str = NULL;
+int mv_eth_cmdline_port0_config(char *s);
+__setup("mv_port0_config=", mv_eth_cmdline_port0_config);
+int mv_eth_cmdline_port1_config(char *s);
+__setup("mv_port1_config=", mv_eth_cmdline_port1_config);
+int mv_eth_cmdline_port2_config(char *s);
+__setup("mv_port2_config=", mv_eth_cmdline_port2_config);
+int mv_eth_cmdline_port3_config(char *s);
+__setup("mv_port3_config=", mv_eth_cmdline_port3_config);
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_NFP_MODULE)
+struct nfpHookMgr *nfpHookMgr = NULL;
+int nfp_hook_mgr_register(mv_eth_nfp_func_t *func)
+{
+	nfpHookMgr = kmalloc(sizeof(struct nfpHookMgr *), GFP_ATOMIC);
+	if (nfpHookMgr == NULL) {
+		printk(KERN_ERR "nfp_mgr_init: Error allocating memory for nfp Hook Mgr \n");
+		return -ENOMEM;
+	}
+	nfpHookMgr->mv_eth_nfp = func;
+	return 0;
+}
+EXPORT_SYMBOL(nfp_hook_mgr_register);
+
+void nfp_hook_mgr_unregister(void)
+{
+	kfree(nfpHookMgr);
+	nfpHookMgr = NULL;
+}
+EXPORT_SYMBOL(nfp_hook_mgr_unregister);
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_NFP_MODULE */
+
+int mv_eth_cmdline_port0_config(char *s)
+{
+	port0_config_str = s;
+	return 1;
+}
+
+int mv_eth_cmdline_port1_config(char *s)
+{
+	port1_config_str = s;
+	return 1;
+}
+
+int mv_eth_cmdline_port2_config(char *s)
+{
+	port2_config_str = s;
+	return 1;
+}
+
+int mv_eth_cmdline_port3_config(char *s)
+{
+	port3_config_str = s;
+	return 1;
+}
+
+void set_cpu_affinity(struct eth_port *pp, MV_U32 cpuAffinity, int group)
+{
+	int cpu;
+	MV_U32 rxqAffinity = 0;
+
+	/* nothing to do when cpuAffinity == 0 */
+	if (cpuAffinity == 0)
+		return;
+
+	/* First, read affinity of the target group, in case it contains CPUs */
+	for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
+		if (!(MV_BIT_CHECK(pp->cpuMask, cpu)))
+			continue;
+		if (pp->napiCpuGroup[cpu] == group) {
+			rxqAffinity = MV_REG_READ(NETA_CPU_MAP_REG(pp->port, cpu)) & 0xff;
+			break;
+		}
+	}
+	for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
+		if (cpuAffinity & 1) {
+			pp->napi[cpu] = pp->napiGroup[group];
+			pp->napiCpuGroup[cpu] = group;
+			/* set rxq affinity of the target group */
+			MV_REG_WRITE(NETA_CPU_MAP_REG(pp->port, cpu), rxqAffinity | NETA_CPU_TXQ_ACCESS_ALL_MASK);
+		}
+		cpuAffinity >>= 1;
+	}
+}
+
+int group_has_cpus(struct eth_port *pp, int group)
+{
+	int cpu;
+
+	for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
+		if (!(MV_BIT_CHECK(pp->cpuMask, cpu)))
+			continue;
+		if (pp->napiCpuGroup[cpu] == group)
+			return 1;
+	}
+
+	/* the group contains no CPU */
+	return 0;
+}
+
+void set_rxq_affinity(struct eth_port *pp, MV_U32 rxqAffinity, int group)
+{
+	int rxq, cpu;
+	MV_U32 regVal;
+	MV_U32 tmpRxqAffinity;
+	int groupHasCpus;
+	int cpuInGroup;
+
+	/* nothing to do when rxqAffinity == 0 */
+	if (rxqAffinity == 0)
+		return;
+
+	groupHasCpus = group_has_cpus(pp, group);
+
+	if (!groupHasCpus) {
+		printk(KERN_ERR "%s: operation not performed; group %d has no cpu \n", __func__, group);
+		return;
+	}
+
+   for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
+		if (!(MV_BIT_CHECK(pp->cpuMask, cpu)))
+			continue;
+	   tmpRxqAffinity = rxqAffinity;
+
+	   regVal = MV_REG_READ(NETA_CPU_MAP_REG(pp->port, cpu));
+
+	   if (pp->napiCpuGroup[cpu] == group) {
+		   cpuInGroup = 1;
+		   /* init TXQ Access Enable bits */
+		   regVal = regVal & 0xff00;
+	   } else {
+		   cpuInGroup = 0;
+		}
+
+	   for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+		   /* set rxq affinity for this cpu */
+		   if (tmpRxqAffinity & 1) {
+			   if (cpuInGroup)
+				   regVal |= NETA_CPU_RXQ_ACCESS_MASK(rxq);
+			   else
+				   regVal &= ~NETA_CPU_RXQ_ACCESS_MASK(rxq);
+			}
+			tmpRxqAffinity >>= 1;
+	   }
+	   MV_REG_WRITE(NETA_CPU_MAP_REG(pp->port, cpu), regVal);
+   }
+}
+
+static int mv_eth_port_config_parse(struct eth_port *pp)
+{
+	char *str;
+
+	printk(KERN_ERR "\n");
+	if (pp == NULL) {
+		printk(KERN_ERR "  o mv_eth_port_config_parse: got NULL pp\n");
+		return -1;
+	}
+
+	switch (pp->port) {
+	case 0:
+		str = port0_config_str;
+		break;
+	case 1:
+		str = port1_config_str;
+		break;
+	case 2:
+		str = port2_config_str;
+		break;
+	case 3:
+		str = port3_config_str;
+		break;
+	default:
+		printk(KERN_ERR "  o mv_eth_port_config_parse: got unknown port %d\n", pp->port);
+		return -1;
+	}
+
+	if (str != NULL) {
+		if ((!strcmp(str, "disconnected")) || (!strcmp(str, "Disconnected"))) {
+			printk(KERN_ERR "  o Port %d is disconnected from Linux netdevice\n", pp->port);
+			clear_bit(MV_ETH_F_CONNECT_LINUX_BIT, &(pp->flags));
+			return 0;
+		}
+	}
+
+	printk(KERN_ERR "  o Port %d is connected to Linux netdevice\n", pp->port);
+	set_bit(MV_ETH_F_CONNECT_LINUX_BIT, &(pp->flags));
+	return 0;
+}
+
+#ifdef ETH_SKB_DEBUG
+struct sk_buff *mv_eth_skb_debug[MV_BM_POOL_CAP_MAX * MV_ETH_BM_POOLS];
+static spinlock_t skb_debug_lock;
+
+void mv_eth_skb_check(struct sk_buff *skb)
+{
+	int i;
+	struct sk_buff *temp;
+	unsigned long flags;
+
+	if (skb == NULL)
+		printk(KERN_ERR "mv_eth_skb_check: got NULL SKB\n");
+
+	spin_lock_irqsave(&skb_debug_lock, flags);
+
+	i = *((u32 *)&skb->cb[0]);
+
+	if ((i >= 0) && (i < MV_BM_POOL_CAP_MAX * MV_ETH_BM_POOLS)) {
+		temp = mv_eth_skb_debug[i];
+		if (mv_eth_skb_debug[i] != skb) {
+			printk(KERN_ERR "mv_eth_skb_check: Unexpected skb: %p (%d) != %p (%d)\n",
+			       skb, i, temp, *((u32 *)&temp->cb[0]));
+		}
+		mv_eth_skb_debug[i] = NULL;
+	} else {
+		printk(KERN_ERR "mv_eth_skb_check: skb->cb=%d is out of range\n", i);
+	}
+
+	spin_unlock_irqrestore(&skb_debug_lock, flags);
+}
+
+void mv_eth_skb_save(struct sk_buff *skb, const char *s)
+{
+	int i;
+	int saved = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&skb_debug_lock, flags);
+
+	for (i = 0; i < MV_BM_POOL_CAP_MAX * MV_ETH_BM_POOLS; i++) {
+		if (mv_eth_skb_debug[i] == skb) {
+			printk(KERN_ERR "%s: mv_eth_skb_debug Duplicate: i=%d, skb=%p\n", s, i, skb);
+			mv_eth_skb_print(skb);
+		}
+
+		if ((!saved) && (mv_eth_skb_debug[i] == NULL)) {
+			mv_eth_skb_debug[i] = skb;
+			*((u32 *)&skb->cb[0]) = i;
+			saved = 1;
+		}
+	}
+
+	spin_unlock_irqrestore(&skb_debug_lock, flags);
+
+	if ((i == MV_BM_POOL_CAP_MAX * MV_ETH_BM_POOLS) && (!saved))
+		printk(KERN_ERR "mv_eth_skb_debug is FULL, skb=%p\n", skb);
+}
+#endif /* ETH_SKB_DEBUG */
+
+struct eth_port *mv_eth_port_by_id(unsigned int port)
+{
+	if (port < mv_eth_ports_num)
+		return mv_eth_ports[port];
+
+	return NULL;
+}
+
+struct net_device *mv_eth_netdev_by_id(unsigned int idx)
+{
+	if (idx < mv_net_devs_num)
+		return mv_net_devs[idx];
+
+	return NULL;
+}
+
+static inline int mv_eth_skb_mh_add(struct sk_buff *skb, u16 mh)
+{
+	/* sanity: Check that there is place for MH in the buffer */
+	if (skb_headroom(skb) < MV_ETH_MH_SIZE) {
+		printk(KERN_ERR "%s: skb (%p) doesn't have place for MH, head=%p, data=%p\n",
+		       __func__, skb, skb->head, skb->data);
+		return 1;
+	}
+
+	/* Prepare place for MH header */
+	skb->len += MV_ETH_MH_SIZE;
+	skb->data -= MV_ETH_MH_SIZE;
+	*((u16 *) skb->data) = mh;
+
+	return 0;
+}
+
+void mv_eth_ctrl_txdone(int num)
+{
+	mv_ctrl_txdone = num;
+}
+
+int mv_eth_ctrl_flag(int port, u32 flag, u32 val)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	u32 bit_flag = (fls(flag) - 1);
+
+	if (!pp)
+		return -ENODEV;
+
+	if ((flag == MV_ETH_F_MH) && (pp->flags & MV_ETH_F_SWITCH)) {
+		printk(KERN_ERR "Error: cannot change Marvell Header on a port used by the Gateway driver\n");
+		return -EPERM;
+	}
+
+	if (val)
+		set_bit(bit_flag, &(pp->flags));
+	else
+		clear_bit(bit_flag, &(pp->flags));
+
+	if (flag == MV_ETH_F_MH)
+		mvNetaMhSet(pp->port, val ? MV_NETA_MH : MV_NETA_MH_NONE);
+
+	return 0;
+}
+
+int mv_eth_ctrl_port_buf_num_set(int port, int long_num, int short_num)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL) {
+		printk(KERN_INFO "port doens not exist (%d) in %s\n" , port, __func__);
+		return -EINVAL;
+	}
+
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "Port %d must be stopped before\n", port);
+		return -EINVAL;
+	}
+	if (pp->pool_long != NULL) {
+		/* Update number of buffers in existing pool (allocate or free) */
+		if (pp->pool_long_num > long_num)
+			mv_eth_pool_free(pp->pool_long->pool, pp->pool_long_num - long_num);
+		else if (long_num > pp->pool_long_num)
+			mv_eth_pool_add(pp->pool_long->pool, long_num - pp->pool_long_num);
+	}
+	pp->pool_long_num = long_num;
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+	if (pp->pool_short != NULL) {
+		/* Update number of buffers in existing pool (allocate or free) */
+		if (pp->pool_short_num > short_num)
+			mv_eth_pool_free(pp->pool_short->pool, pp->pool_short_num - short_num);
+		else if (short_num > pp->pool_short_num)
+			mv_eth_pool_add(pp->pool_short->pool, short_num - pp->pool_short_num);
+	}
+	pp->pool_short_num = short_num;
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_BM
+/* Set pkt_size for the pool. Check that pool not in use (all ports are stopped) */
+/* Free all buffers from the pool */
+/* Detach the pool from all ports */
+int mv_eth_ctrl_pool_size_set(int pool, int pkt_size)
+{
+#ifdef CONFIG_MV_ETH_BM_CPU
+	int port;
+	struct bm_pool *ppool;
+	struct eth_port *pp;
+
+	if (mvNetaMaxCheck(pool, MV_ETH_BM_POOLS))
+		return -EINVAL;
+
+	ppool = &mv_eth_pool[pool];
+
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		/* Check that all ports using this pool are stopped */
+		if (ppool->port_map & (1 << port)) {
+			pp = mv_eth_port_by_id(port);
+
+			if (pp->flags & MV_ETH_F_STARTED) {
+				printk(KERN_ERR "Port %d use pool #%d and must be stopped before change pkt_size\n",
+					port, pool);
+				return -EINVAL;
+			}
+		}
+	}
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		/* Free all buffers and detach pool */
+		if (ppool->port_map & (1 << port)) {
+			pp = mv_eth_port_by_id(port);
+
+			if (ppool == pp->pool_long) {
+				mv_eth_pool_free(pool, pp->pool_long_num);
+				ppool->port_map &= ~(1 << pp->port);
+				pp->pool_long = NULL;
+			}
+			if (ppool == pp->pool_short) {
+				mv_eth_pool_free(pool, pp->pool_short_num);
+				ppool->port_map &= ~(1 << pp->port);
+				pp->pool_short = NULL;
+			}
+		}
+	}
+	ppool->pkt_size = pkt_size;
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	mv_eth_bm_config_pkt_size_set(pool, pkt_size);
+	if (pkt_size == 0)
+		mvBmPoolBufSizeSet(pool, 0);
+	else
+		mvBmPoolBufSizeSet(pool, RX_BUF_SIZE(pkt_size));
+
+	return 0;
+}
+#endif /* CONFIG_MV_ETH_BM */
+
+int mv_eth_ctrl_set_poll_rx_weight(int port, u32 weight)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	int cpu;
+
+	if (pp == NULL) {
+		printk(KERN_INFO "port doens not exist (%d) in %s\n" , port, __func__);
+		return -EINVAL;
+	}
+
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "Port %d must be stopped before\n", port);
+		return -EINVAL;
+	}
+
+	if (weight > 255)
+		weight = 255;
+	pp->weight = weight;
+
+	for_each_possible_cpu(cpu) {
+		if (pp->napi[cpu])
+			pp->napi[cpu]->weight = pp->weight;
+	}
+
+	return 0;
+}
+
+int mv_eth_ctrl_rxq_size_set(int port, int rxq, int value)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	struct rx_queue	*rxq_ctrl;
+
+	if (pp == NULL) {
+		printk(KERN_INFO "port doens not exist (%d) in %s\n" , port, __func__);
+		return -EINVAL;
+	}
+
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "Port %d must be stopped before\n", port);
+		return -EINVAL;
+	}
+	rxq_ctrl = &pp->rxq_ctrl[rxq];
+	if ((rxq_ctrl->q) && (rxq_ctrl->rxq_size != value)) {
+		/* Reset is required when RXQ ring size is changed */
+		mv_eth_rx_reset(pp->port);
+
+		mvNetaRxqDelete(pp->port, rxq);
+		rxq_ctrl->q = NULL;
+	}
+	pp->rxq_ctrl[rxq].rxq_size = value;
+
+	/* New RXQ will be created during mv_eth_start_internals */
+	return 0;
+}
+
+int mv_eth_ctrl_txq_size_set(int port, int txp, int txq, int value)
+{
+	struct tx_queue *txq_ctrl;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL) {
+		printk(KERN_INFO "port doens not exist (%d) in %s\n" , port, __func__);
+		return -EINVAL;
+	}
+
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "Port %d must be stopped before\n", port);
+		return -EINVAL;
+	}
+	txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+	if ((txq_ctrl->q) && (txq_ctrl->txq_size != value)) {
+		mv_eth_txq_delete(pp, txq_ctrl);
+		/* Reset of port/txp is required when TXQ ring size is changed */
+		/* Reset done before as part of stop_internals function */
+	}
+	txq_ctrl->txq_size = value;
+
+	/* New TXQ will be created during mv_eth_start_internals */
+	return 0;
+}
+
+int mv_eth_ctrl_txq_mode_get(int port, int txp, int txq, int *value)
+{
+	int mode = MV_ETH_TXQ_FREE, val = 0;
+	struct tx_queue *txq_ctrl;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+	if (txq_ctrl->cpu_owner) {
+		mode = MV_ETH_TXQ_CPU;
+		val = txq_ctrl->cpu_owner;
+	} else if (txq_ctrl->hwf_rxp < (MV_U8) mv_eth_ports_num) {
+		mode = MV_ETH_TXQ_HWF;
+		val = txq_ctrl->hwf_rxp;
+	}
+	if (value)
+		*value = val;
+
+	return mode;
+}
+
+/* Increment/Decrement CPU ownership for this TXQ */
+int mv_eth_ctrl_txq_cpu_own(int port, int txp, int txq, int add)
+{
+	int mode;
+	struct tx_queue *txq_ctrl;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if ((pp == NULL) || (pp->txq_ctrl == NULL))
+		return -ENODEV;
+
+	/* Check that new txp/txq can be allocated for CPU */
+	mode = mv_eth_ctrl_txq_mode_get(port, txp, txq, NULL);
+
+	txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+	if (add) {
+		if ((mode != MV_ETH_TXQ_CPU) && (mode != MV_ETH_TXQ_FREE))
+			return -EINVAL;
+
+		txq_ctrl->cpu_owner++;
+	} else {
+		if (mode != MV_ETH_TXQ_CPU)
+			return -EINVAL;
+
+		txq_ctrl->cpu_owner--;
+	}
+	return 0;
+}
+
+/* Set TXQ ownership to HWF from the RX port.  rxp=-1 - free TXQ ownership */
+int mv_eth_ctrl_txq_hwf_own(int port, int txp, int txq, int rxp)
+{
+	int mode;
+	struct tx_queue *txq_ctrl;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if ((pp == NULL) || (pp->txq_ctrl == NULL))
+		return -ENODEV;
+
+	/* Check that new txp/txq can be allocated for HWF */
+	mode = mv_eth_ctrl_txq_mode_get(port, txp, txq, NULL);
+
+	txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+
+	if (rxp == -1) {
+		if (mode != MV_ETH_TXQ_HWF)
+			return -EINVAL;
+	} else {
+		if ((mode != MV_ETH_TXQ_HWF) && (mode != MV_ETH_TXQ_FREE))
+			return -EINVAL;
+	}
+
+	txq_ctrl->hwf_rxp = (MV_U8) rxp;
+
+	return 0;
+}
+
+/* Set TXQ for CPU originated packets */
+int mv_eth_ctrl_txq_cpu_def(int port, int txp, int txq, int cpu)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (cpu >= CONFIG_NR_CPUS) {
+		printk(KERN_ERR "cpu #%d is out of range: from 0 to %d\n",
+			cpu, CONFIG_NR_CPUS - 1);
+		return -EINVAL;
+	}
+
+	if (mvNetaTxpCheck(port, txp))
+		return -EINVAL;
+
+	if ((pp == NULL) || (pp->txq_ctrl == NULL))
+		return -ENODEV;
+
+	/* Decrement CPU ownership for old txq */
+	mv_eth_ctrl_txq_cpu_own(port, pp->txp, pp->txq[cpu], 0);
+
+	if (txq != -1) {
+		if (mvNetaMaxCheck(txq, CONFIG_MV_ETH_TXQ))
+			return -EINVAL;
+
+		/* Increment CPU ownership for new txq */
+		if (mv_eth_ctrl_txq_cpu_own(port, txp, txq, 1))
+			return -EINVAL;
+	}
+	pp->txp = txp;
+	pp->txq[cpu] = txq;
+
+	return 0;
+}
+
+/* Get deafult TXQ for CPU originated packets */
+int mv_eth_get_txq_cpu_def(int port, int *txp, int *txq, int cpu)
+{
+    struct eth_port *pp = mv_eth_port_by_id(port);
+
+
+    if (!pp) {
+        return -ENODEV;
+    }
+
+    *txp = pp->txp;
+    *txq = pp->txq[cpu];
+
+	return 0;
+}
+
+int mv_eth_ctrl_tx_cmd(int port, u32 tx_cmd)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (!pp)
+		return -ENODEV;
+
+	pp->hw_cmd = tx_cmd;
+
+	return 0;
+}
+
+int mv_eth_ctrl_tx_mh(int port, u16 mh)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (!pp)
+		return -ENODEV;
+
+	pp->tx_mh = mh;
+
+	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+/* Register special transmit check function */
+void mv_eth_tx_special_check_func(int port,
+					int (*func)(int port, struct net_device *dev, struct sk_buff *skb,
+								struct mv_eth_tx_spec *tx_spec_out))
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp)
+		pp->tx_special_check = func;
+}
+#endif /* CONFIG_MV_ETH_TX_SPECIAL */
+
+#ifdef CONFIG_MV_ETH_RX_SPECIAL
+/* Register special transmit check function */
+void mv_eth_rx_special_proc_func(int port, void (*func)(int port, int rxq, struct net_device *dev,
+							struct sk_buff *skb, struct neta_rx_desc *rx_desc))
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	
+	if (pp)
+		pp->rx_special_proc = func;
+}
+#endif /* CONFIG_MV_ETH_RX_SPECIAL */
+#ifdef CONFIG_MV_MAC_LEARN
+/* Register mac learn parse function */
+void mv_eth_rx_mac_learn_func(int port, void (*func)(int port, int rxq, struct net_device *dev,
+							struct sk_buff *skb, struct neta_rx_desc *rx_desc))
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp != NULL)
+		pp->rx_mc_mac_learn = func;
+}
+#endif /* CONFIG_MV_MAC_LEARN */
+
+static inline u16 mv_eth_select_txq(struct net_device *dev,
+									struct sk_buff *skb)
+{
+	struct eth_port *pp = MV_ETH_PRIV(dev);
+	return mv_eth_tx_policy(pp, skb);
+}
+
+
+static const struct net_device_ops mv_eth_netdev_ops = {
+	.ndo_open = mv_eth_open,
+	.ndo_stop = mv_eth_stop,
+	.ndo_start_xmit = mv_eth_tx,
+	.ndo_set_multicast_list = mv_eth_set_multicast_list,
+	.ndo_set_mac_address = mv_eth_set_mac_addr,
+	.ndo_change_mtu = mv_eth_change_mtu,
+	.ndo_tx_timeout = mv_eth_tx_timeout,
+	.ndo_select_queue = mv_eth_select_txq,
+};
+
+#ifdef CONFIG_MV_ETH_SWITCH
+
+static const struct net_device_ops mv_switch_netdev_ops = {
+	.ndo_open = mv_eth_switch_start,
+	.ndo_stop = mv_eth_switch_stop,
+	.ndo_start_xmit = mv_eth_tx,
+	.ndo_set_multicast_list = mv_eth_switch_set_multicast_list,
+	.ndo_set_mac_address = mv_eth_switch_set_mac_addr,
+	.ndo_change_mtu = mv_eth_switch_change_mtu,
+	.ndo_tx_timeout = mv_eth_tx_timeout,
+};
+
+int mv_eth_switch_netdev_first = 0;
+int mv_eth_switch_netdev_last = 0;
+
+static inline struct net_device *mv_eth_switch_netdev_get(struct eth_port *pp, struct eth_pbuf *pkt)
+{
+	MV_U8 *data;
+	int db_num;
+
+	if (pp->flags & MV_ETH_F_SWITCH) {
+		data = pkt->pBuf + pkt->offset;
+
+		/* bits[4-7] of MSB in Marvell header */
+		db_num = ((*data) >> 4);
+
+		return mv_net_devs[mv_eth_switch_netdev_first + db_num];
+	}
+	return pp->dev;
+}
+
+
+void mv_eth_switch_priv_update(struct net_device *netdev, int i)
+{
+	struct eth_netdev *dev_priv;
+	struct eth_port *pp = MV_ETH_PRIV(netdev);
+	int print_flag, port, switch_port;
+
+	/* Update dev_priv structure */
+	dev_priv = MV_DEV_PRIV(netdev);
+	dev_priv->port_map = 0;
+	dev_priv->link_map = 0;
+
+	print_flag = 1;
+	for (port = 0; port < BOARD_ETH_SWITCH_PORT_NUM; port++) {
+		if (switch_net_config[pp->port].board_port_map[i] & (1 << port)) {
+			if (print_flag) {
+				printk(KERN_CONT ". Interface ports: ");
+				print_flag = 0;
+			}
+			printk(KERN_CONT "%d ", port);
+			switch_port = mvBoardSwitchPortGet(MV_SWITCH_ID_0, port);
+			if (switch_port >= 0) {
+				dev_priv->port_map |= (1 << switch_port);
+				switch_enabled_ports |= (1 << switch_port);
+			}
+		}
+	}
+	printk(KERN_CONT "\n");
+	dev_priv->group = i;
+	dev_priv->vlan_grp_id = MV_SWITCH_GROUP_VLAN_ID(i);	/* e.g. 0x100, 0x200... */
+	dev_priv->tx_vlan_mh = cpu_to_be16((i << 12) | dev_priv->port_map);
+	dev_priv->cpu_port = mvBoardSwitchCpuPortGet(MV_SWITCH_ID_0);
+
+	mv_eth_switch_vlan_set(dev_priv->vlan_grp_id, dev_priv->port_map, dev_priv->cpu_port);
+}
+
+
+int mv_eth_switch_netdev_init(struct eth_port *pp, int dev_i)
+{
+	int i;
+	struct net_device *netdev;
+
+	switch_enabled_ports = 0;
+
+	for (i = 0; i < switch_net_config[pp->port].netdev_max; i++) {
+		netdev = mv_eth_netdev_init(pp, switch_net_config[pp->port].mtu, switch_net_config[pp->port].mac_addr[i]);
+		if (netdev == NULL) {
+			printk(KERN_ERR "mv_eth_switch_netdev_init: can't create netdevice\n");
+			break;
+		}
+		mv_net_devs[dev_i++] = netdev;
+
+		mv_eth_switch_priv_update(netdev, i);
+
+	}
+	return dev_i;
+}
+
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+void mv_eth_link_status_print(int port)
+{
+	MV_ETH_PORT_STATUS link;
+
+	mvNetaLinkStatus(port, &link);
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(port))
+		link.linkup = mv_pon_link_status();
+#endif /* CONFIG_MV_PON */
+
+	if (link.linkup) {
+		printk(KERN_CONT "link up");
+		printk(KERN_CONT ", %s duplex", (link.duplex == MV_ETH_DUPLEX_FULL) ? "full" : "half");
+		printk(KERN_CONT ", speed ");
+
+		if (link.speed == MV_ETH_SPEED_1000)
+			printk(KERN_CONT "1 Gbps\n");
+		else if (link.speed == MV_ETH_SPEED_100)
+			printk(KERN_CONT "100 Mbps\n");
+		else
+			printk(KERN_CONT "10 Mbps\n");
+	} else
+		printk(KERN_CONT "link down\n");
+}
+
+static void mv_eth_rx_error(struct eth_port *pp, struct neta_rx_desc *rx_desc)
+{
+	STAT_ERR(pp->stats.rx_error++);
+
+	if (pp->dev)
+		pp->dev->stats.rx_errors++;
+
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+	if ((pp->flags & MV_ETH_F_DBG_RX) == 0)
+		return;
+
+	if (!printk_ratelimit())
+		return;
+
+	if ((rx_desc->status & NETA_RX_FL_DESC_MASK) != NETA_RX_FL_DESC_MASK) {
+		printk(KERN_ERR "giga #%d: bad rx status %08x (buffer oversize), size=%d\n",
+				pp->port, rx_desc->status, rx_desc->dataSize);
+		return;
+	}
+
+	switch (rx_desc->status & NETA_RX_ERR_CODE_MASK) {
+	case NETA_RX_ERR_CRC:
+		printk(KERN_ERR "giga #%d: bad rx status %08x (crc error), size=%d\n",
+				pp->port, rx_desc->status, rx_desc->dataSize);
+		break;
+	case NETA_RX_ERR_OVERRUN:
+		printk(KERN_ERR "giga #%d: bad rx status %08x (overrun error), size=%d\n",
+				pp->port, rx_desc->status, rx_desc->dataSize);
+		break;
+	case NETA_RX_ERR_LEN:
+		printk(KERN_ERR "giga #%d: bad rx status %08x (max frame length error), size=%d\n",
+				pp->port, rx_desc->status, rx_desc->dataSize);
+		break;
+	case NETA_RX_ERR_RESOURCE:
+		printk(KERN_ERR "giga #%d: bad rx status %08x (resource error), size=%d\n",
+				pp->port, rx_desc->status, rx_desc->dataSize);
+		break;
+	}
+	mv_eth_rx_desc_print(rx_desc);
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+}
+
+void mv_eth_skb_print(struct sk_buff *skb)
+{
+	printk(KERN_ERR "skb=%p: head=%p, data=%p, tail=%p, end=%p\n", skb, skb->head, skb->data, skb->tail, skb->end);
+	printk(KERN_ERR "\t mac=%p, network=%p, transport=%p\n",
+			skb->mac_header, skb->network_header, skb->transport_header);
+	printk(KERN_ERR "\t truesize=%d, len=%d, data_len=%d, mac_len=%d\n",
+		skb->truesize, skb->len, skb->data_len, skb->mac_len);
+	printk(KERN_ERR "\t users=%d, dataref=%d, nr_frags=%d, gso_size=%d, gso_segs=%d\n",
+	       atomic_read(&skb->users), atomic_read(&skb_shinfo(skb)->dataref),
+	       skb_shinfo(skb)->nr_frags, skb_shinfo(skb)->gso_size, skb_shinfo(skb)->gso_segs);
+	printk(KERN_ERR "\t proto=%d, ip_summed=%d, priority=%d\n", ntohs(skb->protocol), skb->ip_summed, skb->priority);
+#ifdef CONFIG_NET_SKB_RECYCLE
+	printk(KERN_ERR "\t skb_recycle=%p, hw_cookie=%p\n", skb->skb_recycle, skb->hw_cookie);
+#endif /* CONFIG_NET_SKB_RECYCLE */
+}
+
+void mv_eth_rx_desc_print(struct neta_rx_desc *desc)
+{
+	int i;
+	u32 *words = (u32 *) desc;
+
+	printk(KERN_ERR "RX desc - %p: ", desc);
+	for (i = 0; i < 8; i++)
+		printk(KERN_CONT "%8.8x ", *words++);
+	printk(KERN_CONT "\n");
+
+	if (desc->status & NETA_RX_IP4_FRAG_MASK)
+		printk(KERN_ERR "Frag, ");
+
+	printk(KERN_CONT "size=%d, L3_offs=%d, IP_hlen=%d, L4_csum=%s, L3=",
+	       desc->dataSize,
+	       (desc->status & NETA_RX_L3_OFFSET_MASK) >> NETA_RX_L3_OFFSET_OFFS,
+	       (desc->status & NETA_RX_IP_HLEN_MASK) >> NETA_RX_IP_HLEN_OFFS,
+	       (desc->status & NETA_RX_L4_CSUM_OK_MASK) ? "Ok" : "Bad");
+
+	if (NETA_RX_L3_IS_IP4(desc->status))
+		printk(KERN_CONT "IPv4, ");
+	else if (NETA_RX_L3_IS_IP4_ERR(desc->status))
+		printk(KERN_CONT "IPv4 bad, ");
+	else if (NETA_RX_L3_IS_IP6(desc->status))
+		printk(KERN_CONT "IPv6, ");
+	else
+		printk(KERN_CONT "Unknown, ");
+
+	printk(KERN_CONT "L4=");
+	if (NETA_RX_L4_IS_TCP(desc->status))
+		printk(KERN_CONT "TCP");
+	else if (NETA_RX_L4_IS_UDP(desc->status))
+		printk(KERN_CONT "UDP");
+	else
+		printk(KERN_CONT "Unknown");
+	printk(KERN_CONT "\n");
+
+#ifdef CONFIG_MV_ETH_PNC
+	printk(KERN_ERR "RINFO: ");
+	if (desc->pncInfo & NETA_PNC_DA_MC)
+		printk(KERN_CONT "DA_MC, ");
+	if (desc->pncInfo & NETA_PNC_DA_BC)
+		printk(KERN_CONT "DA_BC, ");
+	if (desc->pncInfo & NETA_PNC_DA_UC)
+		printk(KERN_CONT "DA_UC, ");
+	if (desc->pncInfo & NETA_PNC_VLAN)
+		printk(KERN_CONT "VLAN, ");
+	if (desc->pncInfo & NETA_PNC_PPPOE)
+		printk(KERN_CONT "PPPOE, ");
+	if (desc->pncInfo & NETA_PNC_RX_SPECIAL)
+		printk(KERN_CONT "RX_SPEC, ");
+#endif /* CONFIG_MV_ETH_PNC */
+
+	printk(KERN_CONT "\n");
+}
+EXPORT_SYMBOL(mv_eth_rx_desc_print);
+
+void mv_eth_tx_desc_print(struct neta_tx_desc *desc)
+{
+	int i;
+	u32 *words = (u32 *) desc;
+
+	printk(KERN_ERR "TX desc - %p: ", desc);
+	for (i = 0; i < 8; i++)
+		printk(KERN_CONT "%8.8x ", *words++);
+	printk(KERN_CONT "\n");
+}
+EXPORT_SYMBOL(mv_eth_tx_desc_print);
+
+void mv_eth_pkt_print(struct eth_pbuf *pkt)
+{
+	printk(KERN_ERR "pkt: len=%d off=%d pool=%d "
+	       "skb=%p pa=%lx buf=%p\n",
+	       pkt->bytes, pkt->offset, pkt->pool,
+	       pkt->osInfo, pkt->physAddr, pkt->pBuf);
+
+	mvDebugMemDump(pkt->pBuf + pkt->offset, 64, 1);
+	mvOsCacheInvalidate(NULL, pkt->pBuf + pkt->offset, 64);
+}
+EXPORT_SYMBOL(mv_eth_pkt_print);
+
+static inline void mv_eth_rx_csum(struct eth_port *pp, struct neta_rx_desc *rx_desc, struct sk_buff *skb)
+{
+#if defined(CONFIG_MV_ETH_RX_CSUM_OFFLOAD)
+	if (pp->rx_csum_offload &&
+	    ((NETA_RX_L3_IS_IP4(rx_desc->status) ||
+	      NETA_RX_L3_IS_IP6(rx_desc->status)) && (rx_desc->status & NETA_RX_L4_CSUM_OK_MASK))) {
+		skb->csum = 0;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		STAT_DBG(pp->stats.rx_csum_hw++);
+		return;
+	}
+#endif /* CONFIG_MV_ETH_RX_CSUM_OFFLOAD */
+
+	skb->ip_summed = CHECKSUM_NONE;
+	STAT_DBG(pp->stats.rx_csum_sw++);
+}
+
+static inline int mv_eth_tx_done_policy(u32 cause)
+{
+	return fls(cause >> NETA_CAUSE_TXQ_SENT_DESC_OFFS) - 1;
+}
+
+inline int mv_eth_rx_policy(u32 cause)
+{
+	return fls(cause >> NETA_CAUSE_RXQ_OCCUP_DESC_OFFS) - 1;
+}
+
+static inline int mv_eth_txq_tos_map_get(struct eth_port *pp, MV_U8 tos)
+{
+	MV_U8 q = pp->txq_tos_map[tos];
+
+	if (q == MV_ETH_TXQ_INVALID)
+		return pp->txq[smp_processor_id()];
+
+	return q;
+}
+
+static inline int mv_eth_tx_policy(struct eth_port *pp, struct sk_buff *skb)
+{
+	int txq = pp->txq[smp_processor_id()];
+
+	if (skb->protocol == htons(ETH_P_IP)) {
+		struct iphdr *iph = ip_hdr(skb);
+
+		txq = mv_eth_txq_tos_map_get(pp, iph->tos);
+	}
+	return txq;
+}
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+int mv_eth_skb_recycle(struct sk_buff *skb)
+{
+	struct eth_pbuf *pkt = skb->hw_cookie;
+	struct bm_pool *pool = &mv_eth_pool[pkt->pool];
+	int status = 0;
+
+	if (skb_recycle_check(skb, pool->pkt_size)) {
+
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+		/* Sanity check */
+		if (skb->truesize != ((skb->end - skb->head) + sizeof(struct sk_buff)))
+			mv_eth_skb_print(skb);
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+
+		STAT_DBG(pool->stats.skb_recycled_ok++);
+		mvOsCacheInvalidate(NULL, skb->head, RX_BUF_SIZE(pool->pkt_size));
+
+		status = mv_eth_pool_put(pool, pkt);
+
+#ifdef ETH_SKB_DEBUG
+		if (status == 0)
+			mv_eth_skb_save(skb, "recycle");
+#endif /* ETH_SKB_DEBUG */
+
+		return 0;
+	}
+
+	/* printk(KERN_ERR "mv_eth_skb_recycle failed: pool=%d, pkt=%p, skb=%p\n", pkt->pool, pkt, skb); */
+
+	mvOsFree(pkt);
+	skb->hw_cookie = NULL;
+
+	STAT_DBG(pool->stats.skb_recycled_err++);
+
+	return 1;
+}
+EXPORT_SYMBOL(mv_eth_skb_recycle);
+
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+static struct sk_buff *mv_eth_skb_alloc(struct bm_pool *pool, struct eth_pbuf *pkt)
+{
+	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(pool->pkt_size);
+	if (!skb) {
+		STAT_ERR(pool->stats.skb_alloc_oom++);
+		return NULL;
+	}
+	STAT_DBG(pool->stats.skb_alloc_ok++);
+
+#ifdef ETH_SKB_DEBUG
+	mv_eth_skb_save(skb, "alloc");
+#endif /* ETH_SKB_DEBUG */
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+	/* Save pkt as first 4 bytes in the buffer */
+#if !defined(CONFIG_MV_ETH_BE_WA)
+	*((MV_U32 *) skb->head) = MV_32BIT_LE((MV_U32)pkt);
+#else
+	*((MV_U32 *) skb->head) = (MV_U32)pkt;
+#endif /* !CONFIG_MV_ETH_BE_WA */
+	mvOsCacheLineFlush(NULL, skb->head);
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	pkt->osInfo = (void *)skb;
+	pkt->pBuf = skb->head;
+	pkt->physAddr = mvOsCacheInvalidate(NULL, skb->head, RX_BUF_SIZE(pool->pkt_size));
+	pkt->offset = NET_SKB_PAD;
+	pkt->pool = pool->pool;
+
+	return skb;
+}
+
+static inline void mv_eth_txq_bufs_free(struct eth_port *pp, struct tx_queue *txq_ctrl, int num)
+{
+	u32 shadow;
+	int i;
+
+	/* Free buffers that was not freed automatically by BM */
+	for (i = 0; i < num; i++) {
+		shadow = txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_get_i];
+		mv_eth_shadow_inc_get(txq_ctrl);
+
+		if (!shadow)
+			continue;
+
+		if (shadow & MV_ETH_SHADOW_SKB) {
+			shadow &= ~MV_ETH_SHADOW_SKB;
+			dev_kfree_skb_any((struct sk_buff *)shadow);
+			STAT_DBG(pp->stats.tx_skb_free++);
+		} else {
+			if (shadow & MV_ETH_SHADOW_EXT) {
+				shadow &= ~MV_ETH_SHADOW_EXT;
+				mv_eth_extra_pool_put(pp, (void *)shadow);
+			} else {
+				/* packet from NFP without BM */
+				struct eth_pbuf *pkt = (struct eth_pbuf *)shadow;
+				struct bm_pool *pool = &mv_eth_pool[pkt->pool];
+
+				if (mv_eth_pool_bm(pool)) {
+					/* Refill BM pool */
+					STAT_DBG(pool->stats.bm_put++);
+					mvBmPoolPut(pkt->pool, (MV_ULONG) pkt->physAddr);
+				} else {
+					mv_eth_pool_put(pool, pkt);
+				}
+			}
+		}
+	}
+}
+
+inline u32 mv_eth_txq_done(struct eth_port *pp, struct tx_queue *txq_ctrl)
+{
+	int tx_done;
+
+	tx_done = mvNetaTxqSentDescProc(pp->port, txq_ctrl->txp, txq_ctrl->txq);
+	if (!tx_done)
+		return tx_done;
+/*
+	printk(KERN_ERR "tx_done: txq_count=%d, port=%d, txp=%d, txq=%d, tx_done=%d\n",
+			txq_ctrl->txq_count, pp->port, txq_ctrl->txp, txq_ctrl->txq, tx_done);
+*/
+	if (!mv_eth_txq_bm(txq_ctrl))
+		mv_eth_txq_bufs_free(pp, txq_ctrl, tx_done);
+
+	txq_ctrl->txq_count -= tx_done;
+	STAT_DBG(txq_ctrl->stats.txq_txdone += tx_done);
+
+	return tx_done;
+}
+EXPORT_SYMBOL(mv_eth_txq_done);
+
+inline struct eth_pbuf *mv_eth_pool_get(struct bm_pool *pool)
+{
+	struct eth_pbuf *pkt = NULL;
+	struct sk_buff *skb;
+	unsigned long flags = 0;
+
+	MV_ETH_LOCK(&pool->lock, flags);
+
+	if (mvStackIndex(pool->stack) > 0) {
+		STAT_DBG(pool->stats.stack_get++);
+		pkt = (struct eth_pbuf *)mvStackPop(pool->stack);
+	} else
+		STAT_ERR(pool->stats.stack_empty++);
+
+	MV_ETH_UNLOCK(&pool->lock, flags);
+	if (pkt)
+		return pkt;
+
+	/* Try to allocate new pkt + skb */
+	pkt = mvOsMalloc(sizeof(struct eth_pbuf));
+	if (pkt) {
+		skb = mv_eth_skb_alloc(pool, pkt);
+		if (!skb) {
+			mvOsFree(pkt);
+			pkt = NULL;
+		}
+	}
+	return pkt;
+}
+
+/* Reuse pkt if possible, allocate new skb and move BM pool or RXQ ring */
+inline int mv_eth_refill(struct eth_port *pp, int rxq,
+				struct eth_pbuf *pkt, struct bm_pool *pool, struct neta_rx_desc *rx_desc)
+{
+	if (pkt == NULL) {
+		pkt = mv_eth_pool_get(pool);
+		if (pkt == NULL)
+			return 1;
+	} else {
+		struct sk_buff *skb;
+
+		/* No recycle -  alloc new skb */
+		skb = mv_eth_skb_alloc(pool, pkt);
+		if (!skb) {
+			mvOsFree(pkt);
+			pool->missed++;
+			mv_eth_add_cleanup_timer(pp);
+			return 1;
+		}
+	}
+	mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
+
+	return 0;
+}
+EXPORT_SYMBOL(mv_eth_refill);
+
+static inline MV_U32 mv_eth_skb_tx_csum(struct eth_port *pp, struct sk_buff *skb)
+{
+#ifdef CONFIG_MV_ETH_TX_CSUM_OFFLOAD
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		int   ip_hdr_len = 0;
+		MV_U8 l4_proto;
+
+		if (skb->protocol == htons(ETH_P_IP)) {
+			struct iphdr *ip4h = ip_hdr(skb);
+
+			/* Calculate IPv4 checksum and L4 checksum */
+			ip_hdr_len = ip4h->ihl;
+			l4_proto = ip4h->protocol;
+		} else if (skb->protocol == htons(ETH_P_IPV6)) {
+			/* If not IPv4 - must be ETH_P_IPV6 - Calculate only L4 checksum */
+			struct ipv6hdr *ip6h = ipv6_hdr(skb);
+
+			/* Read l4_protocol from one of IPv6 extra headers ?????? */
+			if (skb_network_header_len(skb) > 0)
+				ip_hdr_len = (skb_network_header_len(skb) >> 2);
+			l4_proto = ip6h->nexthdr;
+		} else {
+			STAT_DBG(pp->stats.tx_csum_sw++);
+			return NETA_TX_L4_CSUM_NOT;
+		}
+		STAT_DBG(pp->stats.tx_csum_hw++);
+
+		return mvNetaTxqDescCsum(skb_network_offset(skb), skb->protocol, ip_hdr_len, l4_proto);
+	}
+#endif /* CONFIG_MV_ETH_TX_CSUM_OFFLOAD */
+
+	STAT_DBG(pp->stats.tx_csum_sw++);
+	return NETA_TX_L4_CSUM_NOT;
+}
+
+#ifdef CONFIG_MV_ETH_RX_DESC_PREFETCH
+inline struct neta_rx_desc *mv_eth_rx_prefetch(struct eth_port *pp, MV_NETA_RXQ_CTRL *rx_ctrl,
+									  int rx_done, int rx_todo)
+{
+	struct neta_rx_desc	*rx_desc, *next_desc;
+
+	rx_desc = mvNetaRxqNextDescGet(rx_ctrl);
+	if (rx_done == 0) {
+		/* First descriptor in the NAPI loop */
+		mvOsCacheLineInv(NULL, rx_desc);
+		prefetch(rx_desc);
+	}
+	if ((rx_done + 1) == rx_todo) {
+		/* Last descriptor in the NAPI loop - prefetch are not needed */
+		return rx_desc;
+	}
+	/* Prefetch next descriptor */
+	next_desc = mvNetaRxqDescGet(rx_ctrl);
+	mvOsCacheLineInv(NULL, next_desc);
+	prefetch(next_desc);
+
+	return rx_desc;
+}
+#endif /* CONFIG_MV_ETH_RX_DESC_PREFETCH */
+
+static inline int mv_eth_rx(struct eth_port *pp, int rx_todo, int rxq)
+{
+	struct net_device *dev;
+	MV_NETA_RXQ_CTRL *rx_ctrl = pp->rxq_ctrl[rxq].q;
+	int rx_done, rx_filled, err;
+	struct neta_rx_desc *rx_desc;
+	u32 rx_status;
+	int rx_bytes;
+	struct eth_pbuf *pkt;
+	struct sk_buff *skb;
+	struct bm_pool *pool;
+
+	/* Get number of received packets */
+	rx_done = mvNetaRxqBusyDescNumGet(pp->port, rxq);
+	mvOsCacheIoSync();
+
+	if (rx_todo > rx_done)
+		rx_todo = rx_done;
+
+	rx_done = 0;
+	rx_filled = 0;
+
+	/* Fairness NAPI loop */
+	while (rx_done < rx_todo) {
+
+#ifdef CONFIG_MV_ETH_RX_DESC_PREFETCH
+		rx_desc = mv_eth_rx_prefetch(pp, rx_ctrl, rx_done, rx_todo);
+#else
+		rx_desc = mvNetaRxqNextDescGet(rx_ctrl);
+		mvOsCacheLineInv(NULL, rx_desc);
+		prefetch(rx_desc);
+#endif /* CONFIG_MV_ETH_RX_DESC_PREFETCH */
+
+		rx_done++;
+		rx_filled++;
+
+#if defined(MV_CPU_BE)
+		mvNetaRxqDescSwap(rx_desc);
+#endif /* MV_CPU_BE */
+
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+		if (pp->flags & MV_ETH_F_DBG_RX) {
+			printk(KERN_ERR "\n%s: port=%d, cpu=%d\n", __func__, pp->port, smp_processor_id());
+			mv_eth_rx_desc_print(rx_desc);
+		}
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+
+		rx_status = rx_desc->status;
+		pkt = (struct eth_pbuf *)rx_desc->bufCookie;
+		pool = &mv_eth_pool[pkt->pool];
+
+		if (((rx_status & NETA_RX_FL_DESC_MASK) != NETA_RX_FL_DESC_MASK) ||
+			(rx_status & NETA_RX_ES_MASK)) {
+
+			mv_eth_rx_error(pp, rx_desc);
+
+			mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
+			continue;
+		}
+
+		/* Speculative ICache prefetch WA: should be replaced with dma_unmap_single (invalidate l2) */
+		mvOsCacheMultiLineInv(NULL, pkt->pBuf + pkt->offset, rx_desc->dataSize);
+
+#ifdef CONFIG_MV_ETH_RX_PKT_PREFETCH
+		prefetch(pkt->pBuf + pkt->offset);
+		prefetch(pkt->pBuf + pkt->offset + CPU_D_CACHE_LINE_SIZE);
+#endif /* CONFIG_MV_ETH_RX_PKT_PREFETCH */
+
+#ifdef CONFIG_MV_ETH_SWITCH
+		dev = mv_eth_switch_netdev_get(pp, pkt);
+#else
+		dev = pp->dev;
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+		STAT_DBG(pp->stats.rxq[rxq]++);
+		dev->stats.rx_packets++;
+
+		rx_bytes = rx_desc->dataSize - (MV_ETH_CRC_SIZE + MV_ETH_MH_SIZE);
+		dev->stats.rx_bytes += rx_bytes;
+
+#ifndef CONFIG_MV_ETH_PNC
+	/* Update IP offset and IP header len in RX descriptor */
+	if (NETA_RX_L3_IS_IP4(rx_desc->status)) {
+		int ip_offset;
+
+		if ((rx_desc->status & ETH_RX_VLAN_TAGGED_FRAME_MASK))
+			ip_offset = MV_ETH_MH_SIZE + sizeof(MV_802_3_HEADER) + MV_VLAN_HLEN;
+		else
+			ip_offset = MV_ETH_MH_SIZE + sizeof(MV_802_3_HEADER);
+
+		NETA_RX_SET_IPHDR_OFFSET(rx_desc, ip_offset);
+		NETA_RX_SET_IPHDR_HDRLEN(rx_desc, 5);
+	}
+#endif /* !CONFIG_MV_ETH_PNC */
+
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+		if (pp->flags & MV_ETH_F_DBG_RX)
+			mvDebugMemDump(pkt->pBuf + pkt->offset, 64, 1);
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+
+#if defined(CONFIG_MV_ETH_PNC) && defined(CONFIG_MV_ETH_RX_SPECIAL)
+		/* Special RX processing */
+#ifdef CONFIG_MV_CUST_FLOW_MAP_HANDLE
+		if ((MV_PON_PORT_ID == pp->port) || (rx_desc->pncInfo & NETA_PNC_RX_SPECIAL)) {
+#else
+		if (rx_desc->pncInfo & NETA_PNC_RX_SPECIAL) {
+#endif
+			if (pp->rx_special_proc) {
+				pp->rx_special_proc(pp->port, rxq, dev, (struct sk_buff *)(pkt->osInfo), rx_desc);
+				STAT_INFO(pp->stats.rx_special++);
+
+                if (rx_desc->pncInfo & NETA_PNC_RX_SPECIAL) {
+				/* Refill processing */
+				err = mv_eth_refill(pp, rxq, pkt, pool, rx_desc);
+				if (err) {
+					printk(KERN_ERR "Linux processing - Can't refill\n");
+					pp->rxq_ctrl[rxq].missed++;
+					rx_filled--;
+				}
+				continue;
+			    }
+			}
+		}
+#endif /* CONFIG_MV_ETH_PNC && CONFIG_MV_ETH_RX_SPECIAL */
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_NFP_MODULE)
+		if (pp->flags & MV_ETH_F_NFP_EN) {
+			MV_STATUS status;
+
+			pkt->bytes = rx_bytes + MV_ETH_MH_SIZE;
+			pkt->offset = NET_SKB_PAD;
+
+			status = nfpHookMgr->mv_eth_nfp(pp, rxq, rx_desc, pkt, pool);
+			if (status == MV_OK)
+				continue;
+			if (status == MV_FAIL) {
+				rx_filled--;
+				continue;
+			}
+			/* MV_TERMINATE - packet returned to slow path */
+		}
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_NFP_MODULE */
+
+		/* Linux processing */
+		skb = (struct sk_buff *)(pkt->osInfo);
+
+		skb->data += MV_ETH_MH_SIZE;
+		skb->tail += (rx_bytes + MV_ETH_MH_SIZE);
+		skb->len = rx_bytes;
+
+#ifdef ETH_SKB_DEBUG
+		mv_eth_skb_check(skb);
+#endif /* ETH_SKB_DEBUG */
+
+		skb->protocol = eth_type_trans(skb, dev);
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+		if (mv_eth_is_recycle()) {
+			skb->skb_recycle = mv_eth_skb_recycle;
+			skb->hw_cookie = pkt;
+			pkt = NULL;
+		}
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+		if (skb)
+			mv_eth_rx_csum(pp, rx_desc, skb);
+
+#ifdef CONFIG_MV_ETH_GRO
+		if (skb && (dev->features & NETIF_F_GRO)) {
+			STAT_DBG(pp->stats.rx_gro++);
+			STAT_DBG(pp->stats.rx_gro_bytes += skb->len);
+
+			rx_status = napi_gro_receive(pp->napi[smp_processor_id()], skb);
+			skb = NULL;
+		}
+#endif /* CONFIG_MV_ETH_GRO */
+
+#if defined(CONFIG_MV_ETH_PNC) && defined(CONFIG_MV_MAC_LEARN)
+				if (skb && (rx_desc->pncInfo & NETA_PNC_MAC_LEARN)) {
+					if (pp->rx_mc_mac_learn) {
+						pp->rx_mc_mac_learn(pp->port, rxq, dev, skb, rx_desc);
+						STAT_INFO(pp->stats.rx_mac_learn++);
+					}
+				}
+#endif /* CONFIG_MV_ETH_PNC && CONFIG_MV_MAC_LEARN */
+
+		if (skb) {
+			STAT_DBG(pp->stats.rx_netif++);
+			rx_status = netif_receive_skb(skb);
+			STAT_DBG((rx_status == 0) ? : pp->stats.rx_drop_sw++);
+		}
+
+		/* Refill processing: */
+		err = mv_eth_refill(pp, rxq, pkt, pool, rx_desc);
+		if (err) {
+			printk(KERN_ERR "Linux processing - Can't refill\n");
+			pp->rxq_ctrl[rxq].missed++;
+			mv_eth_add_cleanup_timer(pp);
+			rx_filled--;
+		}
+	}
+
+	/* Update RxQ management counters */
+	mvOsCacheIoSync();
+	mvNetaRxqDescNumUpdate(pp->port, rxq, rx_done, rx_filled);
+
+	return rx_done;
+}
+
+static int mv_eth_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct eth_port *pp = MV_ETH_PRIV(dev);
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+	int frags = 0;
+	bool tx_spec_ready = false;
+	struct mv_eth_tx_spec tx_spec;
+	u32 tx_cmd;
+	u16 mh;
+	struct tx_queue *txq_ctrl = NULL;
+	struct neta_tx_desc *tx_desc;
+
+	read_lock(&pp->rwlock);
+
+	if (!(netif_running(dev))) {
+		printk(KERN_ERR "!netif_running() in %s\n", __func__);
+		goto out;
+	}
+
+#if defined(CONFIG_MV_ETH_TX_SPECIAL)
+	if (pp->tx_special_check) {
+
+		if (pp->tx_special_check(pp->port, dev, skb, &tx_spec)) {
+			STAT_INFO(pp->stats.tx_special++);
+			if (tx_spec.tx_func) {
+				tx_spec.tx_func(skb->data, skb->len, &tx_spec);
+				goto out;
+			} else {
+				/* Check validity of tx_spec txp/txq must be CPU owned */
+				tx_spec_ready = true;
+			}
+		}
+	}
+#endif /* CONFIG_MV_ETH_TX_SPECIAL */
+
+	/* Get TXQ (without BM) to send packet generated by Linux */
+	if (tx_spec_ready == false) {
+		tx_spec.txp = pp->txp;
+		tx_spec.txq = mv_eth_tx_policy(pp, skb);
+		tx_spec.hw_cmd = pp->hw_cmd;
+		tx_spec.flags = pp->flags;
+	}
+
+	txq_ctrl = &pp->txq_ctrl[tx_spec.txp * CONFIG_MV_ETH_TXQ + tx_spec.txq];
+	if (txq_ctrl == NULL) {
+		printk(KERN_ERR "%s: invalidate txp/txq (%d/%d)\n", __func__, tx_spec.txp, tx_spec.txq);
+		goto out;
+	}
+	spin_lock(&txq_ctrl->queue_lock);
+
+#ifdef CONFIG_MV_ETH_TSO
+	/* GSO/TSO */
+	if (skb_is_gso(skb)) {
+		frags = mv_eth_tx_tso(skb, dev, &tx_spec, txq_ctrl);
+		goto out;
+	}
+#endif /* CONFIG_MV_ETH_TSO */
+
+	frags = skb_shinfo(skb)->nr_frags + 1;
+
+	if (tx_spec.flags & MV_ETH_F_MH) {
+		if (tx_spec.flags & MV_ETH_F_SWITCH)
+			mh = dev_priv->tx_vlan_mh;
+		else
+			mh = pp->tx_mh;
+
+		if (mv_eth_skb_mh_add(skb, mh)) {
+			frags = 0;
+			goto out;
+		}
+	}
+
+	tx_desc = mv_eth_tx_desc_get(txq_ctrl, frags);
+	if (tx_desc == NULL) {
+		frags = 0;
+		goto out;
+	}
+
+	/* Don't use BM for Linux packets: NETA_TX_BM_ENABLE_MASK = 0 */
+	/* NETA_TX_PKT_OFFSET_MASK = 0 - for all descriptors */
+	tx_cmd = mv_eth_skb_tx_csum(pp, skb);
+
+#ifdef CONFIG_MV_PON
+	tx_desc->hw_cmd = tx_spec.hw_cmd;
+#endif
+
+	/* FIXME: beware of nonlinear --BK */
+	tx_desc->dataSize = skb_headlen(skb);
+
+	tx_desc->bufPhysAddr = mvOsCacheFlush(NULL, skb->data, tx_desc->dataSize);
+
+	if (frags == 1) {
+		/*
+		 * First and Last descriptor
+		 */
+		if (tx_spec.flags & MV_ETH_F_NO_PAD)
+			tx_cmd |= NETA_TX_F_DESC_MASK | NETA_TX_L_DESC_MASK;
+		else
+			tx_cmd |= NETA_TX_FLZ_DESC_MASK;
+
+		tx_desc->command = tx_cmd;
+		mv_eth_tx_desc_flush(tx_desc);
+
+		txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = ((MV_ULONG) skb | MV_ETH_SHADOW_SKB);
+		mv_eth_shadow_inc_put(txq_ctrl);
+	} else {
+
+		/* First but not Last */
+		tx_cmd |= NETA_TX_F_DESC_MASK;
+
+		txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = 0;
+		mv_eth_shadow_inc_put(txq_ctrl);
+
+		tx_desc->command = tx_cmd;
+		mv_eth_tx_desc_flush(tx_desc);
+
+		/* Continue with other skb fragments */
+		mv_eth_tx_frag_process(pp, skb, txq_ctrl, tx_spec.flags);
+		STAT_DBG(pp->stats.tx_sg++);
+	}
+/*
+	printk(KERN_ERR "tx: frags=%d, tx_desc[0x0]=%x [0xc]=%x, wr_id=%d, rd_id=%d, skb=%p\n",
+			frags, tx_desc->command,tx_desc->hw_cmd,
+			txq_ctrl->shadow_txq_put_i, txq_ctrl->shadow_txq_get_i, skb);
+*/
+	txq_ctrl->txq_count += frags;
+
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+	if (pp->flags & MV_ETH_F_DBG_TX) {
+		printk(KERN_ERR "\n");
+		printk(KERN_ERR "%s - eth_tx_%lu: port=%d, txp=%d, txq=%d, skb=%p, head=%p, data=%p, size=%d\n",
+		       dev->name, dev->stats.tx_packets, pp->port, tx_spec.txp, tx_spec.txq, skb,
+			   skb->head, skb->data, skb->len);
+		mv_eth_tx_desc_print(tx_desc);
+		/*mv_eth_skb_print(skb);*/
+		mvDebugMemDump(skb->data, 64, 1);
+	}
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(pp->port))
+		mvNetaPonTxqBytesAdd(pp->port, tx_spec.txp, tx_spec.txq, skb->len);
+#endif /* CONFIG_MV_PON */
+
+	/* Enable transmit */
+	mvNetaTxqPendDescAdd(pp->port, tx_spec.txp, tx_spec.txq, frags);
+
+	STAT_DBG(txq_ctrl->stats.txq_tx += frags);
+
+out:
+	if (frags > 0) {
+		dev->stats.tx_packets++;
+		dev->stats.tx_bytes += skb->len;
+	} else {
+		dev->stats.tx_dropped++;
+		dev_kfree_skb_any(skb);
+	}
+
+#ifndef CONFIG_MV_ETH_TXDONE_ISR
+	if (txq_ctrl) {
+		if (txq_ctrl->txq_count >= mv_ctrl_txdone) {
+			STAT_DIST(u32 tx_done = )mv_eth_txq_done(pp, txq_ctrl);
+
+			STAT_DIST((tx_done < pp->dist_stats.tx_done_dist_size) ? pp->dist_stats.tx_done_dist[tx_done]++ : 0);
+
+		}
+		/* If after calling mv_eth_txq_done, txq_ctrl->txq_count equals frags, we need to set the timer */
+		if ((txq_ctrl->txq_count == frags) && (frags > 0))
+			mv_eth_add_tx_done_timer(pp);
+	}
+#endif /* CONFIG_MV_ETH_TXDONE_ISR */
+
+	if (txq_ctrl)
+		spin_unlock(&txq_ctrl->queue_lock);
+
+	read_unlock(&pp->rwlock);
+	return NETDEV_TX_OK;
+}
+
+#ifdef CONFIG_MV_ETH_TSO
+/* Validate TSO */
+static inline int mv_eth_tso_validate(struct sk_buff *skb, struct net_device *dev)
+{
+	if (!(dev->features & NETIF_F_TSO)) {
+		printk(KERN_ERR "error: (skb_is_gso(skb) returns true but features is not NETIF_F_TSO\n");
+		return 1;
+	}
+
+	if (skb_shinfo(skb)->frag_list != NULL) {
+		printk(KERN_ERR "***** ERROR: frag_list is not null\n");
+		return 1;
+	}
+
+	if (skb_shinfo(skb)->gso_segs == 1) {
+		printk(KERN_ERR "***** ERROR: only one TSO segment\n");
+		return 1;
+	}
+
+	if (skb->len <= skb_shinfo(skb)->gso_size) {
+		printk(KERN_ERR "***** ERROR: total_len (%d) less than gso_size (%d)\n", skb->len, skb_shinfo(skb)->gso_size);
+		return 1;
+	}
+	if ((htons(ETH_P_IP) != skb->protocol) || (ip_hdr(skb)->protocol != IPPROTO_TCP) || (tcp_hdr(skb) == NULL)) {
+		printk(KERN_ERR "***** ERROR: Protocol is not TCP over IP\n");
+		return 1;
+	}
+	return 0;
+}
+
+static inline int mv_eth_tso_build_hdr_desc(struct neta_tx_desc *tx_desc, struct eth_port *priv, struct sk_buff *skb,
+					     struct tx_queue *txq_ctrl, u16 *mh, int hdr_len, int size,
+					     MV_U32 tcp_seq, MV_U16 ip_id, int left_len)
+{
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	MV_U8 *data, *mac;
+	int mac_hdr_len = skb_network_offset(skb);
+
+	data = mv_eth_extra_pool_get(priv);
+	if (!data)
+		return 0;
+
+	txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = ((MV_ULONG)data | MV_ETH_SHADOW_EXT);
+
+	/* Reserve 2 bytes for IP header alignment */
+	mac = data + MV_ETH_MH_SIZE;
+	iph = (struct iphdr *)(mac + mac_hdr_len);
+
+	memcpy(mac, skb->data, hdr_len);
+
+	if (iph) {
+		iph->id = htons(ip_id);
+		iph->tot_len = htons(size + hdr_len - mac_hdr_len);
+	}
+
+	tcph = (struct tcphdr *)(mac + skb_transport_offset(skb));
+	tcph->seq = htonl(tcp_seq);
+
+	if (left_len) {
+		/* Clear all special flags for not last packet */
+		tcph->psh = 0;
+		tcph->fin = 0;
+		tcph->rst = 0;
+	}
+
+	if (mh) {
+		/* Start tarnsmit from MH - add 2 bytes to size */
+		*((MV_U16 *)data) = *mh;
+		/* increment ip_offset field in TX descriptor by 2 bytes */
+		mac_hdr_len += MV_ETH_MH_SIZE;
+		hdr_len += MV_ETH_MH_SIZE;
+	} else {
+		/* Start transmit from MAC */
+		data = mac;
+	}
+
+	tx_desc->dataSize = hdr_len;
+	tx_desc->command = mvNetaTxqDescCsum(mac_hdr_len, skb->protocol, ((u8 *)tcph - (u8 *)iph) >> 2, IPPROTO_TCP);
+	tx_desc->command |= NETA_TX_F_DESC_MASK;
+
+	tx_desc->bufPhysAddr = mvOsCacheFlush(NULL, data, tx_desc->dataSize);
+	mv_eth_shadow_inc_put(txq_ctrl);
+
+	mv_eth_tx_desc_flush(tx_desc);
+
+	return hdr_len;
+}
+
+static inline int mv_eth_tso_build_data_desc(struct neta_tx_desc *tx_desc, struct sk_buff *skb,
+					     struct tx_queue *txq_ctrl, char *frag_ptr,
+					     int frag_size, int data_left, int total_left)
+{
+	int size;
+
+	size = MV_MIN(frag_size, data_left);
+
+	tx_desc->dataSize = size;
+	tx_desc->bufPhysAddr = mvOsCacheFlush(NULL, frag_ptr, size);
+	tx_desc->command = 0;
+	txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = 0;
+
+	if (size == data_left) {
+		/* last descriptor in the TCP packet */
+		tx_desc->command = NETA_TX_L_DESC_MASK;
+
+		if (total_left == 0) {
+			/* last descriptor in SKB */
+			txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = ((MV_ULONG) skb | MV_ETH_SHADOW_SKB);
+		}
+	}
+	mv_eth_shadow_inc_put(txq_ctrl);
+	mv_eth_tx_desc_flush(tx_desc);
+
+	return size;
+}
+
+/***********************************************************
+ * mv_eth_tx_tso --                                        *
+ *   send a packet.                                        *
+ ***********************************************************/
+int mv_eth_tx_tso(struct sk_buff *skb, struct net_device *dev,
+		struct mv_eth_tx_spec *tx_spec, struct tx_queue *txq_ctrl)
+{
+	int frag = 0;
+	int total_len, hdr_len, size, frag_size, data_left;
+	char *frag_ptr;
+	int totalDescNum, totalBytes = 0;
+	struct neta_tx_desc *tx_desc;
+	MV_U16 ip_id;
+	MV_U32 tcp_seq = 0;
+	skb_frag_t *skb_frag_ptr;
+	const struct tcphdr *th = tcp_hdr(skb);
+	struct eth_port *priv = MV_ETH_PRIV(dev);
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+	MV_U16 *mh = NULL;
+	int i;
+
+	STAT_DBG(priv->stats.tx_tso++);
+/*
+	printk(KERN_ERR "mv_eth_tx_tso_%d ENTER: skb=%p, total_len=%d\n", priv->stats.tx_tso, skb, skb->len);
+*/
+	if (mv_eth_tso_validate(skb, dev))
+		return 0;
+
+	/* Calculate expected number of TX descriptors */
+	totalDescNum = skb_shinfo(skb)->gso_segs * 2 + skb_shinfo(skb)->nr_frags;
+
+	if ((txq_ctrl->txq_count + totalDescNum) >= txq_ctrl->txq_size) {
+/*
+		printk(KERN_ERR "%s: no TX descriptors - txq_count=%d, len=%d, nr_frags=%d, gso_segs=%d\n",
+					__func__, txq_ctrl->txq_count, skb->len, skb_shinfo(skb)->nr_frags,
+					skb_shinfo(skb)->gso_segs);
+*/
+		STAT_ERR(txq_ctrl->stats.txq_err++);
+		return 0;
+	}
+
+	total_len = skb->len;
+	hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+
+	total_len -= hdr_len;
+	ip_id = ntohs(ip_hdr(skb)->id);
+	tcp_seq = ntohl(th->seq);
+
+	frag_size = skb_headlen(skb);
+	frag_ptr = skb->data;
+
+	if (frag_size < hdr_len) {
+		printk(KERN_ERR "***** ERROR: frag_size=%d, hdr_len=%d\n", frag_size, hdr_len);
+		return 0;
+	}
+
+	frag_size -= hdr_len;
+	frag_ptr += hdr_len;
+	if (frag_size == 0) {
+		skb_frag_ptr = &skb_shinfo(skb)->frags[frag];
+
+		/* Move to next segment */
+		frag_size = skb_frag_ptr->size;
+		frag_ptr = page_address(skb_frag_ptr->page) + skb_frag_ptr->page_offset;
+		frag++;
+	}
+	totalDescNum = 0;
+
+	while (total_len > 0) {
+		data_left = MV_MIN(skb_shinfo(skb)->gso_size, total_len);
+
+		tx_desc = mv_eth_tx_desc_get(txq_ctrl, 1);
+		if (tx_desc == NULL)
+			goto outNoTxDesc;
+
+		totalDescNum++;
+		total_len -= data_left;
+		txq_ctrl->txq_count++;
+
+		if (tx_spec->flags & MV_ETH_F_MH) {
+			if (tx_spec->flags & MV_ETH_F_SWITCH)
+				mh = &dev_priv->tx_vlan_mh;
+			else
+				mh = &priv->tx_mh;
+		}
+
+		/* prepare packet headers: MAC + IP + TCP */
+		size = mv_eth_tso_build_hdr_desc(tx_desc, priv, skb, txq_ctrl, mh,
+					hdr_len, data_left, tcp_seq, ip_id, total_len);
+		if (size == 0)
+			goto outNoTxDesc;
+
+		totalBytes += size;
+/*
+		printk(KERN_ERR "Header desc: tx_desc=%p, skb=%p, hdr_len=%d, data_left=%d\n",
+						tx_desc, skb, hdr_len, data_left);
+*/
+		ip_id++;
+
+		while (data_left > 0) {
+			tx_desc = mv_eth_tx_desc_get(txq_ctrl, 1);
+			if (tx_desc == NULL)
+				goto outNoTxDesc;
+
+			totalDescNum++;
+			txq_ctrl->txq_count++;
+
+			size = mv_eth_tso_build_data_desc(tx_desc, skb, txq_ctrl,
+							  frag_ptr, frag_size, data_left, total_len);
+			totalBytes += size;
+/*
+			printk(KERN_ERR "Data desc: tx_desc=%p, skb=%p, size=%d, frag_size=%d, data_left=%d\n",
+							tx_desc, skb, size, frag_size, data_left);
+ */
+			data_left -= size;
+			tcp_seq += size;
+
+			frag_size -= size;
+			frag_ptr += size;
+
+			if ((frag_size == 0) && (frag < skb_shinfo(skb)->nr_frags)) {
+				skb_frag_ptr = &skb_shinfo(skb)->frags[frag];
+
+				/* Move to next segment */
+				frag_size = skb_frag_ptr->size;
+				frag_ptr = page_address(skb_frag_ptr->page) + skb_frag_ptr->page_offset;
+				frag++;
+			}
+		}		/* of while data_left > 0 */
+	}			/* of while (total_len > 0) */
+
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(priv->port))
+		mvNetaPonTxqBytesAdd(priv->port, txq_ctrl->txp, txq_ctrl->txq, totalBytes);
+#endif /* CONFIG_MV_PON */
+
+	STAT_DBG(priv->stats.tx_tso_bytes += totalBytes);
+	STAT_DBG(txq_ctrl->stats.txq_tx += totalDescNum);
+
+	mvNetaTxqPendDescAdd(priv->port, txq_ctrl->txp, txq_ctrl->txq, totalDescNum);
+/*
+	printk(KERN_ERR "mv_eth_tx_tso EXIT: totalDescNum=%d\n", totalDescNum);
+*/
+	return totalDescNum;
+
+outNoTxDesc:
+	/* No enough TX descriptors for the whole skb - rollback */
+	printk(KERN_ERR "%s: No TX descriptors - rollback %d, txq_count=%d, nr_frags=%d, skb=%p, len=%d, gso_segs=%d\n",
+			__func__, totalDescNum, txq_ctrl->txq_count, skb_shinfo(skb)->nr_frags,
+			skb, skb->len, skb_shinfo(skb)->gso_segs);
+
+	for (i = 0; i < totalDescNum; i++) {
+		txq_ctrl->txq_count--;
+		mv_eth_shadow_dec_put(txq_ctrl);
+		mvNetaTxqPrevDescGet(txq_ctrl->q);
+	}
+	return 0;
+}
+#endif /* CONFIG_MV_ETH_TSO */
+
+/* Drop packets received by the RXQ and free buffers */
+static void mv_eth_rxq_drop_pkts(struct eth_port *pp, int rxq)
+{
+	struct neta_rx_desc *rx_desc;
+	struct eth_pbuf     *pkt;
+	struct bm_pool      *pool;
+	int	                rx_done, i;
+	MV_NETA_RXQ_CTRL    *rx_ctrl = pp->rxq_ctrl[rxq].q;
+
+	if (rx_ctrl == NULL)
+		return;
+
+	rx_done = mvNetaRxqBusyDescNumGet(pp->port, rxq);
+	mvOsCacheIoSync();
+
+	for (i = 0; i < rx_done; i++) {
+		rx_desc = mvNetaRxqNextDescGet(rx_ctrl);
+		mvOsCacheLineInv(NULL, rx_desc);
+
+#if defined(MV_CPU_BE)
+		mvNetaRxqDescSwap(rx_desc);
+#endif /* MV_CPU_BE */
+
+		pkt = (struct eth_pbuf *)rx_desc->bufCookie;
+		pool = &mv_eth_pool[pkt->pool];
+		mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
+	}
+	if (rx_done) {
+		mvOsCacheIoSync();
+		mvNetaRxqDescNumUpdate(pp->port, rxq, rx_done, rx_done);
+	}
+}
+
+static void mv_eth_txq_done_force(struct eth_port *pp, struct tx_queue *txq_ctrl)
+{
+	int tx_done = txq_ctrl->txq_count;
+
+	mv_eth_txq_bufs_free(pp, txq_ctrl, tx_done);
+
+	STAT_DBG(txq_ctrl->stats.txq_txdone += tx_done);
+
+	/* reset txq */
+	txq_ctrl->txq_count = 0;
+	txq_ctrl->shadow_txq_put_i = 0;
+	txq_ctrl->shadow_txq_get_i = 0;
+}
+
+inline u32 mv_eth_tx_done_pon(struct eth_port *pp, int *tx_todo)
+{
+	int txp, txq;
+	struct tx_queue *txq_ctrl;
+	u32 tx_done = 0;
+
+	*tx_todo = 0;
+
+	STAT_INFO(pp->stats.tx_done++);
+
+	/* simply go over all TX ports and TX queues */
+	txp = pp->txp_num;
+	while (txp--) {
+		txq = CONFIG_MV_ETH_TXQ;
+
+		while (txq--) {
+			txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+			spin_lock(&txq_ctrl->queue_lock);
+			if ((txq_ctrl) && (txq_ctrl->txq_count)) {
+				tx_done += mv_eth_txq_done(pp, txq_ctrl);
+				*tx_todo += txq_ctrl->txq_count;
+			}
+			spin_unlock(&txq_ctrl->queue_lock);
+		}
+	}
+
+	STAT_DIST((tx_done < pp->dist_stats.tx_done_dist_size) ? pp->dist_stats.tx_done_dist[tx_done]++ : 0);
+
+	return tx_done;
+}
+
+
+inline u32 mv_eth_tx_done_gbe(struct eth_port *pp, u32 cause_tx_done, int *tx_todo)
+{
+	int txp, txq;
+	struct tx_queue *txq_ctrl;
+	u32 tx_done = 0;
+
+	*tx_todo = 0;
+
+	STAT_INFO(pp->stats.tx_done++);
+
+	while (cause_tx_done != 0) {
+		/* For GbE ports we get TX Buffers Threshold Cross per queue in bits [7:0] */
+		txp = pp->txp_num; /* 1 for GbE ports */
+		while (txp--) {
+			txq = mv_eth_tx_done_policy(cause_tx_done);
+			if (txq == -1)
+				break;
+
+			txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+			spin_lock(&txq_ctrl->queue_lock);
+			if ((txq_ctrl) && (txq_ctrl->txq_count)) {
+				tx_done += mv_eth_txq_done(pp, txq_ctrl);
+				*tx_todo += txq_ctrl->txq_count;
+			}
+			spin_unlock(&txq_ctrl->queue_lock);
+
+			cause_tx_done &= ~((1 << txq) << NETA_CAUSE_TXQ_SENT_DESC_OFFS);
+		}
+	}
+
+	STAT_DIST((tx_done < pp->dist_stats.tx_done_dist_size) ? pp->dist_stats.tx_done_dist[tx_done]++ : 0);
+
+	return tx_done;
+}
+
+
+static void mv_eth_tx_frag_process(struct eth_port *pp, struct sk_buff *skb, struct tx_queue *txq_ctrl,	u16 flags)
+{
+	int i;
+	struct neta_tx_desc *tx_desc;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		tx_desc = mvNetaTxqNextDescGet(txq_ctrl->q);
+
+		/* NETA_TX_BM_ENABLE_MASK = 0 */
+		/* NETA_TX_PKT_OFFSET_MASK = 0 */
+		tx_desc->dataSize = frag->size;
+		tx_desc->bufPhysAddr = mvOsCacheFlush(NULL, page_address(frag->page) + frag->page_offset,
+						      tx_desc->dataSize);
+
+		if (i == (skb_shinfo(skb)->nr_frags - 1)) {
+			/* Last descriptor */
+			if (flags & MV_ETH_F_NO_PAD)
+				tx_desc->command = NETA_TX_L_DESC_MASK;
+			else
+				tx_desc->command = (NETA_TX_L_DESC_MASK | NETA_TX_Z_PAD_MASK);
+
+			txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = ((MV_ULONG) skb | MV_ETH_SHADOW_SKB);
+			mv_eth_shadow_inc_put(txq_ctrl);
+		} else {
+			/* Descriptor in the middle: Not First, Not Last */
+			tx_desc->command = 0;
+
+			txq_ctrl->shadow_txq[txq_ctrl->shadow_txq_put_i] = 0;
+			mv_eth_shadow_inc_put(txq_ctrl);
+		}
+
+		mv_eth_tx_desc_flush(tx_desc);
+	}
+}
+
+
+/* Free "num" buffers from the pool */
+static int mv_eth_pool_free(int pool, int num)
+{
+	struct eth_pbuf *pkt;
+	int i = 0;
+	struct bm_pool *ppool = &mv_eth_pool[pool];
+	unsigned long flags = 0;
+	bool free_all = false;
+
+	MV_ETH_LOCK(&ppool->lock, flags);
+
+	if (num >= ppool->buf_num) {
+		/* Free all buffers from the pool */
+		free_all = true;
+		num = ppool->buf_num;
+	}
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+	if (mv_eth_pool_bm(ppool)) {
+
+		if (free_all)
+			mvBmConfigSet(MV_BM_EMPTY_LIMIT_MASK);
+
+		while (i < num) {
+			MV_U32 *va;
+			MV_U32 pa = mvBmPoolGet(pool);
+
+			if (pa == 0)
+				break;
+
+			va = phys_to_virt(pa);
+			pkt = (struct eth_pbuf *)*va;
+#if !defined(CONFIG_MV_ETH_BE_WA)
+			pkt = (struct eth_pbuf *)MV_32BIT_LE((MV_U32)pkt);
+#endif /* !CONFIG_MV_ETH_BE_WA */
+
+			if (pkt) {
+				mv_eth_pkt_free(pkt);
+#ifdef ETH_SKB_DEBUG
+				mv_eth_skb_check((struct sk_buff *)pkt->osInfo);
+#endif /* ETH_SKB_DEBUG */
+			}
+			i++;
+		}
+		printk(KERN_ERR "bm pool #%d: pkt_size=%d, buf_size=%d - %d of %d buffers free\n",
+			pool, ppool->pkt_size, RX_BUF_SIZE(ppool->pkt_size), i, num);
+
+		if (free_all)
+			mvBmConfigClear(MV_BM_EMPTY_LIMIT_MASK);
+	}
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	ppool->buf_num -= num;
+
+	/* Free buffers from the pool stack too */
+	if (free_all)
+		num = mvStackIndex(ppool->stack);
+	else if (mv_eth_pool_bm(ppool))
+		num = 0;
+
+	i = 0;
+	while (i < num) {
+		/* sanity check */
+		if (mvStackIndex(ppool->stack) == 0) {
+			printk(KERN_ERR "%s: No more buffers in the stack\n", __func__);
+			break;
+		}
+		pkt = (struct eth_pbuf *)mvStackPop(ppool->stack);
+		if (pkt) {
+			mv_eth_pkt_free(pkt);
+#ifdef ETH_SKB_DEBUG
+			mv_eth_skb_check((struct sk_buff *)pkt->osInfo);
+#endif /* ETH_SKB_DEBUG */
+		}
+		i++;
+	}
+	if (i > 0)
+		printk(KERN_ERR "stack pool #%d: pkt_size=%d, buf_size=%d - %d of %d buffers free\n",
+			pool, ppool->pkt_size, RX_BUF_SIZE(ppool->pkt_size), i, num);
+
+	MV_ETH_UNLOCK(&ppool->lock, flags);
+
+	return i;
+}
+
+
+static int mv_eth_pool_destroy(int pool)
+{
+	int num, status = 0;
+	struct bm_pool *ppool = &mv_eth_pool[pool];
+
+	num = mv_eth_pool_free(pool, ppool->buf_num);
+	if (num != ppool->buf_num) {
+		printk(KERN_ERR "Warning: could not free all buffers in pool %d while destroying pool\n", pool);
+		return MV_ERROR;
+	}
+
+	status = mvStackDelete(ppool->stack);
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+	mvBmPoolDisable(pool);
+
+	/* Note: we don't free the bm_pool here ! */
+	if (ppool->bm_pool)
+		mvOsFree(ppool->bm_pool);
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	memset(ppool, 0, sizeof(struct bm_pool));
+
+	return status;
+}
+
+
+static int mv_eth_pool_add(int pool, int buf_num)
+{
+	struct bm_pool *bm_pool;
+	struct sk_buff *skb;
+	struct eth_pbuf *pkt;
+	int i;
+	unsigned long flags = 0;
+
+	if ((pool < 0) || (pool >= MV_ETH_BM_POOLS)) {
+		printk(KERN_ERR "%s: invalid pool number %d\n", __func__, pool);
+		return 0;
+	}
+
+	bm_pool = &mv_eth_pool[pool];
+
+	/* Check buffer size */
+	if (bm_pool->pkt_size == 0) {
+		printk(KERN_ERR "%s: invalid pool #%d state: pkt_size=%d, buf_size=%d, buf_num=%d\n",
+		       __func__, pool, bm_pool->pkt_size, RX_BUF_SIZE(bm_pool->pkt_size), bm_pool->buf_num);
+		return 0;
+	}
+
+	/* Insure buf_num is smaller than capacity */
+	if ((buf_num < 0) || ((buf_num + bm_pool->buf_num) > (bm_pool->capacity))) {
+
+		printk(KERN_ERR "%s: can't add %d buffers into bm_pool=%d: capacity=%d, buf_num=%d\n",
+		       __func__, buf_num, pool, bm_pool->capacity, bm_pool->buf_num);
+		return 0;
+	}
+
+	MV_ETH_LOCK(&bm_pool->lock, flags);
+
+	for (i = 0; i < buf_num; i++) {
+		pkt = mvOsMalloc(sizeof(struct eth_pbuf));
+		if (!pkt) {
+			printk(KERN_ERR "%s: can't allocate %d bytes\n", __func__, sizeof(struct eth_pbuf));
+			break;
+		}
+
+		skb = mv_eth_skb_alloc(bm_pool, pkt);
+		if (!skb) {
+			kfree(pkt);
+			break;
+		}
+/*
+	printk(KERN_ERR "skb_alloc_%d: pool=%d, skb=%p, pkt=%p, head=%p (%lx), skb->truesize=%d\n",
+				i, bm_pool->pool, skb, pkt, pkt->pBuf, pkt->physAddr, skb->truesize);
+*/
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+		mvBmPoolPut(pool, (MV_ULONG) pkt->physAddr);
+		STAT_DBG(bm_pool->stats.bm_put++);
+#else
+		mvStackPush(bm_pool->stack, (MV_U32) pkt);
+		STAT_DBG(bm_pool->stats.stack_put++);
+#endif /* CONFIG_MV_ETH_BM_CPU */
+	}
+	bm_pool->buf_num += i;
+
+	printk(KERN_ERR "pool #%d: pkt_size=%d, buf_size=%d - %d of %d buffers added\n",
+	       pool, bm_pool->pkt_size, RX_BUF_SIZE(bm_pool->pkt_size), i, buf_num);
+
+	MV_ETH_UNLOCK(&bm_pool->lock, flags);
+
+	return i;
+}
+
+#ifdef CONFIG_MV_ETH_BM
+void	*mv_eth_bm_pool_create(int pool, int capacity, MV_ULONG *pPhysAddr)
+{
+		MV_ULONG			physAddr;
+		MV_UNIT_WIN_INFO	winInfo;
+		void				*pVirt;
+		MV_STATUS			status;
+
+		pVirt = mvOsIoUncachedMalloc(NULL, sizeof(MV_U32) * capacity, &physAddr, NULL);
+		if (pVirt == NULL) {
+			mvOsPrintf("%s: Can't allocate %d bytes for Long pool #%d\n",
+					__func__, MV_BM_POOL_CAP_MAX * sizeof(MV_U32), pool);
+			return NULL;
+		}
+
+		/* Pool address must be MV_BM_POOL_PTR_ALIGN bytes aligned */
+		if (MV_IS_NOT_ALIGN((unsigned)pVirt, MV_BM_POOL_PTR_ALIGN)) {
+			mvOsPrintf("memory allocated for BM pool #%d is not %d bytes aligned\n",
+						pool, MV_BM_POOL_PTR_ALIGN);
+			mvOsIoCachedFree(NULL, sizeof(MV_U32) * capacity, physAddr, pVirt, 0);
+			return NULL;
+		}
+		status = mvBmPoolInit(pool, pVirt, physAddr, capacity);
+		if (status != MV_OK) {
+			mvOsPrintf("%s: Can't init #%d BM pool. status=%d\n", __func__, pool, status);
+			mvOsIoCachedFree(NULL, sizeof(MV_U32) * capacity, physAddr, pVirt, 0);
+			return NULL;
+		}
+		status = mvCtrlAddrWinInfoGet(&winInfo, physAddr);
+		if (status != MV_OK) {
+			printk(KERN_ERR "%s: Can't map BM pool #%d. phys_addr=0x%x, status=%d\n",
+			       __func__, pool, (unsigned)physAddr, status);
+			mvOsIoCachedFree(NULL, sizeof(MV_U32) * capacity, physAddr, pVirt, 0);
+			return NULL;
+		}
+		mvBmPoolTargetSet(pool, winInfo.targetId, winInfo.attrib);
+		mvBmPoolEnable(pool);
+
+		if (pPhysAddr != NULL)
+			*pPhysAddr = physAddr;
+
+		return pVirt;
+}
+#endif /* CONFIG_MV_ETH_BM */
+
+static MV_STATUS mv_eth_pool_create(int pool, int capacity)
+{
+	struct bm_pool *bm_pool;
+
+	if ((pool < 0) || (pool >= MV_ETH_BM_POOLS)) {
+		printk(KERN_ERR "%s: pool=%d is out of range\n", __func__, pool);
+		return MV_BAD_VALUE;
+	}
+
+	bm_pool = &mv_eth_pool[pool];
+	memset(bm_pool, 0, sizeof(struct bm_pool));
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+	bm_pool->bm_pool = mv_eth_bm_pool_create(pool, capacity, NULL);
+	if (bm_pool->bm_pool == NULL)
+		return MV_FAIL;
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	/* Create Stack as container of alloacted skbs for SKB_RECYCLE and for RXQs working without BM support */
+	bm_pool->stack = mvStackCreate(capacity);
+
+	if (bm_pool->stack == NULL) {
+		printk(KERN_ERR "Can't create MV_STACK structure for %d elements\n", capacity);
+		return MV_OUT_OF_CPU_MEM;
+	}
+
+	bm_pool->pool = pool;
+	bm_pool->capacity = capacity;
+	bm_pool->pkt_size = 0;
+	bm_pool->buf_num = 0;
+	spin_lock_init(&bm_pool->lock);
+
+	return MV_OK;
+}
+
+/* Interrupt handling */
+irqreturn_t mv_eth_isr(int irq, void *dev_id)
+{
+	struct eth_port *pp = (struct eth_port *)dev_id;
+	struct napi_struct *napi = pp->napi[smp_processor_id()];
+
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+	if (pp->flags & MV_ETH_F_DBG_ISR) {
+		printk(KERN_ERR "%s: port=%d, cpu=%d, mask=0x%x, cause=0x%x\n",
+			__func__, pp->port, smp_processor_id(),
+			MV_REG_READ(NETA_INTR_NEW_MASK_REG(pp->port)), MV_REG_READ(NETA_INTR_NEW_CAUSE_REG(pp->port)));
+	}
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+
+	STAT_INFO(pp->stats.irq++);
+
+	/* Mask all interrupts */
+	MV_REG_WRITE(NETA_INTR_NEW_MASK_REG(pp->port), 0);
+	/* To be sure that itterrupt already masked Dummy read is required */
+	/* MV_REG_READ(NETA_INTR_NEW_MASK_REG(pp->port));*/
+
+	/* Verify that the device not already on the polling list */
+	if (napi_schedule_prep(napi)) {
+		/* schedule the work (rx+txdone+link) out of interrupt contxet */
+		__napi_schedule(napi);
+	} else {
+		STAT_INFO(pp->stats.irq_err++);
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+		printk(KERN_ERR "mv_eth_isr ERROR: port=%d, cpu=%d\n", pp->port, smp_processor_id());
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+	}
+	return IRQ_HANDLED;
+}
+
+void mv_eth_link_event(struct eth_port *pp, int print)
+{
+	struct net_device *dev = pp->dev;
+	bool              link_is_up;
+
+	STAT_INFO(pp->stats.link++);
+
+	/* Check Link status on ethernet port */
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(pp->port))
+		link_is_up = mv_pon_link_status();
+	else
+#endif /* CONFIG_MV_PON */
+		link_is_up = mvNetaLinkIsUp(pp->port);
+
+	if (link_is_up) {
+		mvNetaPortUp(pp->port);
+		set_bit(MV_ETH_F_LINK_UP_BIT, &(pp->flags));
+
+		if (mv_eth_ctrl_is_tx_enabled(pp)) {
+			if (dev) {
+				netif_carrier_on(dev);
+				netif_wake_queue(dev);
+			}
+		}
+	} else {
+		if (dev) {
+			netif_carrier_off(dev);
+			netif_stop_queue(dev);
+		}
+		mvNetaPortDown(pp->port);
+		clear_bit(MV_ETH_F_LINK_UP_BIT, &(pp->flags));
+	}
+
+	if (print) {
+		if (dev)
+			printk(KERN_ERR "%s: ", dev->name);
+		else
+			printk(KERN_ERR "%s: ", "none");
+
+		mv_eth_link_status_print(pp->port);
+	}
+}
+
+/***********************************************************************************************/
+int mv_eth_poll(struct napi_struct *napi, int budget)
+{
+	int rx_done = 0;
+	MV_U32 causeRxTx;
+	struct eth_port *pp = MV_ETH_PRIV(napi->dev);
+
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+	if (pp->flags & MV_ETH_F_DBG_POLL) {
+		printk(KERN_ERR "%s ENTER: port=%d, cpu=%d, mask=0x%x, cause=0x%x\n",
+			__func__, pp->port, smp_processor_id(),
+			MV_REG_READ(NETA_INTR_NEW_MASK_REG(pp->port)), MV_REG_READ(NETA_INTR_NEW_CAUSE_REG(pp->port)));
+	}
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+
+	read_lock(&pp->rwlock);
+
+	STAT_INFO(pp->stats.poll[smp_processor_id()]++);
+
+	/* Read cause register */
+	causeRxTx = MV_REG_READ(NETA_INTR_NEW_CAUSE_REG(pp->port)) &
+	    (MV_ETH_MISC_SUM_INTR_MASK | MV_ETH_TXDONE_INTR_MASK | MV_ETH_RX_INTR_MASK);
+
+	if (causeRxTx & MV_ETH_MISC_SUM_INTR_MASK) {
+		MV_U32 causeMisc;
+
+		/* Process MISC events - Link, etc ??? */
+		causeRxTx &= ~MV_ETH_MISC_SUM_INTR_MASK;
+		causeMisc = MV_REG_READ(NETA_INTR_MISC_CAUSE_REG(pp->port));
+
+		if (causeMisc & NETA_CAUSE_LINK_CHANGE_MASK)
+			mv_eth_link_event(pp, 1);
+
+		MV_REG_WRITE(NETA_INTR_MISC_CAUSE_REG(pp->port), 0);
+	}
+	causeRxTx |= pp->causeRxTx[smp_processor_id()];
+
+#ifdef CONFIG_MV_ETH_TXDONE_ISR
+	if (causeRxTx & MV_ETH_TXDONE_INTR_MASK) {
+		int tx_todo = 0;
+		/* TX_DONE process */
+
+		if (MV_PON_PORT(pp->port))
+			mv_eth_tx_done_pon(pp, &tx_todo);
+		else
+			mv_eth_tx_done_gbe(pp, (causeRxTx & MV_ETH_TXDONE_INTR_MASK), &tx_todo);
+
+		causeRxTx &= ~MV_ETH_TXDONE_INTR_MASK;
+	}
+#endif /* CONFIG_MV_ETH_TXDONE_ISR */
+
+#if (CONFIG_MV_ETH_RXQ > 1)
+	while ((causeRxTx != 0) && (budget > 0)) {
+		int count, rx_queue;
+
+		rx_queue = mv_eth_rx_policy(causeRxTx);
+		if (rx_queue == -1)
+			break;
+
+		count = mv_eth_rx(pp, budget, rx_queue);
+		rx_done += count;
+		budget -= count;
+		if (budget > 0)
+			causeRxTx &= ~((1 << rx_queue) << NETA_CAUSE_RXQ_OCCUP_DESC_OFFS);
+	}
+#else
+	rx_done = mv_eth_rx(pp, budget, CONFIG_MV_ETH_RXQ_DEF);
+	budget -= rx_done;
+#endif /* (CONFIG_MV_ETH_RXQ > 1) */
+
+	STAT_DIST((rx_done < pp->dist_stats.rx_dist_size) ? pp->dist_stats.rx_dist[rx_done]++ : 0);
+
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+	if (pp->flags & MV_ETH_F_DBG_POLL) {
+		printk(KERN_ERR "%s  EXIT: port=%d, cpu=%d, budget=%d, rx_done=%d\n",
+			__func__, pp->port, smp_processor_id(), budget, rx_done);
+	}
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+
+	if (budget > 0) {
+		unsigned long flags;
+
+		causeRxTx = 0;
+
+		napi_complete(napi);
+		STAT_INFO(pp->stats.poll_exit[smp_processor_id()]++);
+
+		local_irq_save(flags);
+		MV_REG_WRITE(NETA_INTR_NEW_MASK_REG(pp->port),
+			     (MV_ETH_MISC_SUM_INTR_MASK | MV_ETH_TXDONE_INTR_MASK | MV_ETH_RX_INTR_MASK));
+
+		local_irq_restore(flags);
+	}
+	pp->causeRxTx[smp_processor_id()] = causeRxTx;
+	read_unlock(&pp->rwlock);
+	return rx_done;
+}
+
+static void mv_eth_cpu_counters_init(void)
+{
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+
+	mvCpuCntrsInitialize();
+
+#ifdef CONFIG_PLAT_ARMADA
+	/*  cycles counter via special CCNT counter */
+	mvCpuCntrsProgram(0, MV_CPU_CNTRS_CYCLES, "Cycles", 13);
+
+	/* instruction counters */
+	mvCpuCntrsProgram(1, MV_CPU_CNTRS_INSTRUCTIONS, "Instr", 13);
+	/* mvCpuCntrsProgram(0, MV_CPU_CNTRS_DCACHE_READ_HIT, "DcRdHit", 0); */
+
+	/* ICache misses counter */
+	mvCpuCntrsProgram(2, MV_CPU_CNTRS_ICACHE_READ_MISS, "IcMiss", 0);
+
+	/* DCache read misses counter */
+	mvCpuCntrsProgram(3, MV_CPU_CNTRS_DCACHE_READ_MISS, "DcRdMiss", 0);
+
+	/* DCache write misses counter */
+	mvCpuCntrsProgram(4, MV_CPU_CNTRS_DCACHE_WRITE_MISS, "DcWrMiss", 0);
+
+	/* DTLB Miss counter */
+	mvCpuCntrsProgram(5, MV_CPU_CNTRS_DTLB_MISS, "dTlbMiss", 0);
+
+	/* mvCpuCntrsProgram(3, MV_CPU_CNTRS_TLB_MISS, "TlbMiss", 0); */
+#else /* CONFIG_FEROCEON */
+	/* 0 - instruction counters */
+	mvCpuCntrsProgram(0, MV_CPU_CNTRS_INSTRUCTIONS, "Instr", 16);
+	/* mvCpuCntrsProgram(0, MV_CPU_CNTRS_DCACHE_READ_HIT, "DcRdHit", 0); */
+
+	/* 1 - ICache misses counter */
+	mvCpuCntrsProgram(1, MV_CPU_CNTRS_ICACHE_READ_MISS, "IcMiss", 0);
+
+	/* 2 - cycles counter */
+	mvCpuCntrsProgram(2, MV_CPU_CNTRS_CYCLES, "Cycles", 18);
+
+	/* 3 - DCache read misses counter */
+	mvCpuCntrsProgram(3, MV_CPU_CNTRS_DCACHE_READ_MISS, "DcRdMiss", 0);
+	/* mvCpuCntrsProgram(3, MV_CPU_CNTRS_TLB_MISS, "TlbMiss", 0); */
+#endif /* CONFIG_PLAT_ARMADA */
+
+	event0 = mvCpuCntrsEventCreate("RX_DESC_PREF", 100000);
+	event1 = mvCpuCntrsEventCreate("RX_DESC_READ", 100000);
+	event2 = mvCpuCntrsEventCreate("RX_BUF_INV", 100000);
+	event3 = mvCpuCntrsEventCreate("RX_DESC_FILL", 100000);
+	event4 = mvCpuCntrsEventCreate("TX_START", 100000);
+	event5 = mvCpuCntrsEventCreate("RX_BUF_INV", 100000);
+	if ((event0 == NULL) || (event1 == NULL) || (event2 == NULL) ||
+		(event3 == NULL) || (event4 == NULL) || (event5 == NULL))
+		printk(KERN_ERR "Can't create cpu counter events\n");
+#endif /* CONFIG_MV_CPU_PERF_CNTRS */
+}
+
+static void mv_eth_port_promisc_set(int port, int queue)
+{
+#ifdef CONFIG_MV_ETH_PNC
+	/* Accept all */
+	if (mv_eth_pnc_ctrl_en) {
+		pnc_mac_me(port, NULL, queue);
+		pnc_mcast_all(port, 1);
+	} else {
+		printk(KERN_ERR "%s: PNC control is disabled\n", __func__);
+	}
+#else /* Legacy parser */
+	mvNetaRxUnicastPromiscSet(port, MV_TRUE);
+	mvNetaSetUcastTable(port, queue);
+	mvNetaSetSpecialMcastTable(port, queue);
+	mvNetaSetOtherMcastTable(port, queue);
+#endif /* CONFIG_MV_ETH_PNC */
+}
+
+void mv_eth_port_filtering_cleanup(int port)
+{
+#ifdef CONFIG_MV_ETH_PNC
+	static bool is_first = true;
+
+	/* clean TCAM only one, no need to do this per port. */
+	if (is_first) {
+		tcam_hw_init();
+		is_first = false;
+	}
+#else
+	mvNetaRxUnicastPromiscSet(port, MV_FALSE);
+	mvNetaSetUcastTable(port, -1);
+	mvNetaSetSpecialMcastTable(port, -1);
+	mvNetaSetOtherMcastTable(port, -1);
+#endif /* CONFIG_MV_ETH_PNC */
+}
+
+
+static MV_STATUS mv_eth_bm_pools_init(void)
+{
+	int i, j;
+	MV_STATUS status;
+
+	/* Get compile time configuration */
+#ifdef CONFIG_MV_ETH_BM
+	mvBmControl(MV_START);
+	mv_eth_bm_config_get();
+#endif /* CONFIG_MV_ETH_BM */
+
+	/* Create all pools with maximum capacity */
+	for (i = 0; i < MV_ETH_BM_POOLS; i++) {
+		status = mv_eth_pool_create(i, MV_BM_POOL_CAP_MAX);
+		if (status != MV_OK) {
+			printk(KERN_ERR "%s: can't create bm_pool=%d - capacity=%d\n", __func__, i, MV_BM_POOL_CAP_MAX);
+			for (j = 0; j < i; j++)
+				mv_eth_pool_destroy(j);
+			return status;
+		}
+#ifdef CONFIG_MV_ETH_BM_CPU
+		mv_eth_pool[i].pkt_size = mv_eth_bm_config_pkt_size_get(i);
+		if (mv_eth_pool[i].pkt_size == 0)
+			mvBmPoolBufSizeSet(i, 0);
+		else
+			mvBmPoolBufSizeSet(i, RX_BUF_SIZE(mv_eth_pool[i].pkt_size));
+#else
+		mv_eth_pool[i].pkt_size = 0;
+#endif /* CONFIG_MV_ETH_BM */
+	}
+	return 0;
+}
+
+/* Note: call this function only after mv_eth_ports_num is initialized */
+static int mv_eth_load_network_interfaces(MV_U32 portMask, MV_U32 cpuMask)
+{
+	u32 port, dev_i = 0;
+	struct eth_port *pp;
+	int mtu, err;
+	u8 mac[MV_MAC_ADDR_SIZE];
+
+	printk(KERN_ERR "  o Loading network interface(s)\n");
+
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		if (!(MV_BIT_CHECK(portMask, port)))
+			continue;
+
+		if (!mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) {
+			printk(KERN_ERR "\n  o Warning: GbE port %d is powered off\n\n", port);
+			continue;
+		}
+		if (!MV_PON_PORT(port) && !mvBoardIsGbEPortConnected(port)) {
+			printk(KERN_ERR "\n  o Warning: GbE port %d is not connected to PHY/RGMII/Switch, skip initialization\n\n",
+					port);
+			continue;
+		}
+
+		pp = mv_eth_ports[port] = mvOsMalloc(sizeof(struct eth_port));
+		if (!pp) {
+			printk(KERN_ERR "Error: failed to allocate memory for port %d\n", port);
+			return -ENOMEM;
+		}
+
+		err = mv_eth_priv_init(pp, port);
+		if (err)
+			return err;
+
+		pp->cpuMask = cpuMask;
+
+#ifdef CONFIG_MV_ETH_PMT
+		if (MV_PON_PORT(port))
+			mvNetaPmtInit(port, (MV_NETA_PMT *)ioremap(PMT_PON_PHYS_BASE, PMT_MEM_SIZE));
+		else
+			mvNetaPmtInit(port, (MV_NETA_PMT *)ioremap(PMT_GIGA_PHYS_BASE + port * 0x40000, PMT_MEM_SIZE));
+#endif /* CONFIG_MV_ETH_PMT */
+
+#ifdef CONFIG_MV_ETH_SWITCH
+		if (pp->flags & (MV_ETH_F_SWITCH | MV_ETH_F_EXT_SWITCH)) {
+			int status = mv_eth_switch_config_get(mv_eth_initialized, port);
+
+			if (status < 0) {
+				printk(KERN_ERR "\nWarning: port %d - Invalid netconfig string\n", port);
+				mv_eth_priv_cleanup(pp);
+				continue;
+			} else if (status == 0) {	/* User selected to work with Gateway driver    */
+				clear_bit(MV_ETH_F_EXT_SWITCH_BIT, &(pp->flags));
+			} else if (status == 1) {
+				/* User selected to work without Gateway driver */
+				clear_bit(MV_ETH_F_SWITCH_BIT, &(pp->flags));
+				printk(KERN_ERR "  o Working in External Switch mode\n");
+				ext_switch_port_mask = mv_switch_link_detection_init();
+			}
+		}
+
+		if (pp->flags & MV_ETH_F_SWITCH) {
+			set_bit(MV_ETH_F_MH_BIT, &(pp->flags));
+			mtu = switch_net_config[port].mtu;
+			if (mv_switch_init(RX_PKT_SIZE(mtu), SWITCH_CONNECTED_PORTS_MASK)) {
+				printk(KERN_ERR "\nWarning: port %d - Switch initialization failed\n", port);
+				mv_eth_priv_cleanup(pp);
+				continue;
+			}
+		} else
+#endif /* CONFIG_MV_ETH_SWITCH */
+			mtu = mv_eth_config_get(pp, mac);
+
+		printk(KERN_ERR "\t%s p=%d: mtu=%d, mac=%p\n", MV_PON_PORT(port) ? "pon" : "giga", port, mtu, mac);
+
+		if (mv_eth_hal_init(pp)) {
+			printk(KERN_ERR "%s: can't init eth hal\n", __func__);
+			mv_eth_priv_cleanup(pp);
+			return -EIO;
+		}
+#ifdef CONFIG_MV_ETH_SWITCH
+		if (pp->flags & MV_ETH_F_SWITCH) {
+			int queue = CONFIG_MV_ETH_RXQ_DEF;
+
+			mv_eth_switch_netdev_first = dev_i;
+			dev_i = mv_eth_switch_netdev_init(pp, dev_i);
+			if (dev_i < (mv_eth_switch_netdev_first + switch_net_config[port].netdev_max)) {
+				printk(KERN_ERR "%s: can't create netdevice for switch\n", __func__);
+				mv_eth_priv_cleanup(pp);
+				return -EIO;
+			}
+			mv_eth_switch_netdev_last = dev_i - 1;
+
+			/* set this port to be in promiscuous mode. MAC filtering is performed by the Switch */
+			mv_eth_port_promisc_set(pp->port, queue);
+			handle_group_affinity(port);
+
+			continue;
+		}
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+		mv_net_devs[dev_i] = mv_eth_netdev_init(pp, mtu, mac);
+		if (!mv_net_devs[dev_i]) {
+			printk(KERN_ERR "%s: can't create netdevice\n", __func__);
+			mv_eth_priv_cleanup(pp);
+			return -EIO;
+		}
+		pp->dev = mv_net_devs[dev_i];
+		dev_i++;
+		handle_group_affinity(port);
+	}
+
+	mv_net_devs_num = dev_i;
+
+	return 0;
+}
+
+
+/***********************************************************
+ * mv_eth_probe --                                         *
+ *   main driver initialization. loading the interfaces.   *
+ ***********************************************************/
+static int mv_eth_probe(struct platform_device *pdev)
+{
+	u32 port;
+	struct eth_port *pp;
+	int size;
+	MV_U32 port_mask, cpu_mask;
+
+	if (pdev->dev.platform_data) {
+		port_mask = ((struct netaSmpGroupStruct *)pdev->dev.platform_data)->portMask;
+		cpu_mask =  ((struct netaSmpGroupStruct *)pdev->dev.platform_data)->cpuMask;
+	} else {
+		port_mask = (1 << CONFIG_MV_ETH_PORTS_NUM) - 1;
+		cpu_mask = (1 << CONFIG_NR_CPUS) - 1;
+	}
+	printk(KERN_INFO "%s: port_mask=0x%x, cpu_mask=0x%x \n", __func__, port_mask, cpu_mask);
+
+#ifdef ETH_SKB_DEBUG
+	memset(mv_eth_skb_debug, 0, sizeof(mv_eth_skb_debug));
+	spin_lock_init(&skb_debug_lock);
+#endif
+
+	if (!mv_eth_initialized) {
+		mvSysNetaInit(port_mask, cpu_mask); /* init MAC Unit */
+
+		mv_eth_ports_num = mvCtrlEthMaxPortGet();
+		if (mv_eth_ports_num > CONFIG_MV_ETH_PORTS_NUM)
+			mv_eth_ports_num = CONFIG_MV_ETH_PORTS_NUM;
+
+		mv_net_devs_max = mv_eth_ports_num;
+
+#ifdef CONFIG_MV_ETH_SWITCH
+		mv_net_devs_max += (CONFIG_MV_ETH_SWITCH_NETDEV_NUM - 1);
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+		mv_eth_config_show();
+
+		size = mv_eth_ports_num * sizeof(struct eth_port *);
+		mv_eth_ports = mvOsMalloc(size);
+		if (!mv_eth_ports)
+			goto oom;
+
+		memset(mv_eth_ports, 0, size);
+
+		/* Allocate array of pointers to struct net_device */
+		size = mv_net_devs_max * sizeof(struct net_device *);
+		mv_net_devs = mvOsMalloc(size);
+		if (!mv_net_devs)
+			goto oom;
+
+		memset(mv_net_devs, 0, size);
+	}
+
+#ifdef CONFIG_MV_ETH_PNC
+	if (mv_eth_pnc_ctrl_en) {
+		if (pnc_default_init())
+			printk(KERN_ERR "%s: Warning PNC init failed\n", __func__);
+	} else
+		printk(KERN_ERR "%s: PNC control is disabled\n", __func__);
+#endif /* CONFIG_MV_ETH_PNC */
+
+	if (mv_eth_bm_pools_init())
+		goto oom;
+
+#ifdef CONFIG_MV_INCLUDE_SWITCH
+	if ((mvBoardSwitchConnectedPortGet(0) != -1) || (mvBoardSwitchConnectedPortGet(1) != -1)) {
+		if (mv_switch_load(SWITCH_CONNECTED_PORTS_MASK))
+			printk(KERN_ERR "\nWarning: Switch load failed\n");
+	}
+#endif /* CONFIG_MV_INCLUDE_SWITCH */
+
+	if (!mv_eth_initialized) {
+		if (mv_eth_load_network_interfaces(port_mask, cpu_mask))
+			goto oom;
+	}
+
+#ifdef CONFIG_MV_ETH_HWF
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		if (mv_eth_ports[port])
+			mvNetaHwfInit(port);
+	}
+#endif /* CONFIG_MV_ETH_HWF */
+
+	/* Call mv_eth_open specifically for ports not connected to Linux netdevice */
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		pp = mv_eth_port_by_id(port);
+		if (pp) {
+			if (!(pp->flags & MV_ETH_F_CONNECT_LINUX)) {
+				if (pp->flags & MV_ETH_F_SWITCH)
+					printk(KERN_ERR "%s: a GbE port using the Gateway driver cannot be disconnected from Linux\n",
+							__func__);
+				else
+					mv_eth_open(pp->dev);
+			}
+		}
+	}
+
+	if (!mv_eth_initialized)
+		mv_eth_cpu_counters_init();
+
+
+	printk(KERN_ERR "\n");
+
+	mv_eth_initialized = 1;
+
+	return 0;
+oom:
+	if (mv_eth_ports)
+		mvOsFree(mv_eth_ports);
+
+	if (mv_net_devs)
+		mvOsFree(mv_net_devs);
+
+	printk(KERN_ERR "%s: out of memory\n", __func__);
+	return -ENOMEM;
+}
+
+
+static int mv_eth_config_get(struct eth_port *pp, MV_U8 *mac_addr)
+{
+	char *mac_str = NULL;
+	u8 zero_mac[MV_MAC_ADDR_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	int mtu;
+
+	switch (pp->port) {
+	case 0:
+		if (mvMtu[0] != 0)
+			mtu = mvMtu[0];
+		else
+			mtu = CONFIG_MV_ETH_0_MTU;
+
+		/* use default MAC address from Kconfig only if the MAC address we got is all 0 */
+		if (memcmp(mvMacAddr[0], zero_mac, MV_MAC_ADDR_SIZE) == 0)
+			mac_str = CONFIG_MV_ETH_0_MACADDR;
+		else
+			memcpy(mac_addr, mvMacAddr[0], MV_MAC_ADDR_SIZE);
+
+		break;
+
+#if (CONFIG_MV_ETH_PORTS_NUM > 1)
+	case 1:
+		if (mvMtu[1] != 0)
+			mtu = mvMtu[1];
+		else
+			mtu = CONFIG_MV_ETH_1_MTU;
+
+		/* use default MAC address from Kconfig only if the MAC address we got is all 0 */
+		if (memcmp(mvMacAddr[1], zero_mac, MV_MAC_ADDR_SIZE) == 0)
+			mac_str = CONFIG_MV_ETH_1_MACADDR;
+		else
+			memcpy(mac_addr, mvMacAddr[1], MV_MAC_ADDR_SIZE);
+
+		break;
+#endif /* CONFIG_MV_ETH_PORTS_NUM > 1 */
+
+#if (CONFIG_MV_ETH_PORTS_NUM > 2)
+	case 2:
+		if (mvMtu[2] != 0)
+			mtu = mvMtu[2];
+		else
+			mtu = CONFIG_MV_ETH_2_MTU;
+
+		/* use default MAC address from Kconfig only if the MAC address we got is all 0 */
+		if (memcmp(mvMacAddr[2], zero_mac, MV_MAC_ADDR_SIZE) == 0)
+			mac_str = CONFIG_MV_ETH_2_MACADDR;
+		else
+			memcpy(mac_addr, mvMacAddr[2], MV_MAC_ADDR_SIZE);
+		break;
+#endif /* CONFIG_MV_ETH_PORTS_NUM > 2 */
+
+#if (CONFIG_MV_ETH_PORTS_NUM > 3)
+	case 3:
+		if (mvMtu[3] != 0)
+			mtu = mvMtu[3];
+		else
+			mtu = CONFIG_MV_ETH_3_MTU;
+
+		/* use default MAC address from Kconfig only if the MAC address we got is all 0 */
+		if (memcmp(mvMacAddr[3], zero_mac, MV_MAC_ADDR_SIZE) == 0)
+			mac_str = CONFIG_MV_ETH_3_MACADDR;
+		else
+			memcpy(mac_addr, mvMacAddr[3], MV_MAC_ADDR_SIZE);
+
+		break;
+#endif /* CONFIG_MV_ETH_PORTS_NUM > 3 */
+
+	default:
+		printk(KERN_ERR "eth_get_config: Unexpected port number %d\n", pp->port);
+		return -1;
+	}
+	if ((mac_str != NULL) && (mac_addr != NULL))
+		mvMacStrToHex(mac_str, mac_addr);
+
+	return mtu;
+}
+
+/***********************************************************
+ * mv_eth_tx_timeout --                                    *
+ *   nothing to be done (?)                                *
+ ***********************************************************/
+static void mv_eth_tx_timeout(struct net_device *dev)
+{
+#ifdef CONFIG_MV_ETH_STAT_ERR
+	struct eth_port *pp = MV_ETH_PRIV(dev);
+
+	pp->stats.tx_timeout++;
+#endif /* #ifdef CONFIG_MV_ETH_STAT_ERR */
+
+	printk(KERN_INFO "%s: tx timeout\n", dev->name);
+}
+
+/***************************************************************
+ * mv_eth_netdev_init -- Allocate and initialize net_device    *
+ *                   structure                                 *
+ ***************************************************************/
+struct net_device *mv_eth_netdev_init(struct eth_port *pp, int mtu, u8 *mac)
+{
+	int cpu, i;
+	struct net_device *dev;
+	struct eth_dev_priv *dev_priv;
+
+	dev = alloc_etherdev_mq(sizeof(struct eth_dev_priv), CONFIG_MV_ETH_TXQ);
+	if (!dev)
+		return NULL;
+
+	dev_priv = (struct eth_dev_priv *)netdev_priv(dev);
+	if (!dev_priv)
+		return NULL;
+
+	memset(dev_priv, 0, sizeof(struct eth_dev_priv));
+	dev_priv->port_p = pp;
+
+	dev->irq = NET_TH_RXTX_IRQ_NUM(pp->port);
+
+	dev->mtu = mtu;
+	memcpy(dev->dev_addr, mac, MV_MAC_ADDR_SIZE);
+	dev->tx_queue_len = CONFIG_MV_ETH_TXQ_DESC;
+	dev->watchdog_timeo = 5 * HZ;
+
+#ifdef CONFIG_MV_ETH_SWITCH
+	if (pp->flags & (MV_ETH_F_SWITCH | MV_ETH_F_EXT_SWITCH)) {
+
+		if (pp->flags & MV_ETH_F_SWITCH)
+			dev->netdev_ops = &mv_switch_netdev_ops;
+		else
+			dev->netdev_ops = &mv_eth_netdev_ops;
+
+		dev_priv->netdev_p = mvOsMalloc(sizeof(struct eth_netdev));
+		if (!dev_priv->netdev_p) {
+			printk(KERN_ERR "failed to allocate eth_netdev\n");
+			free_netdev(dev);
+			return NULL;
+		}
+		memset(dev_priv->netdev_p, 0, sizeof(struct eth_netdev));
+		/* For correct link information of Linux interface: */
+		if (pp->flags & MV_ETH_F_EXT_SWITCH) {
+			dev_priv->netdev_p->port_map = ext_switch_port_mask;
+			dev_priv->netdev_p->link_map = 0;
+		}
+	} else
+#endif /* CONFIG_MV_ETH_SWITCH */
+		dev->netdev_ops = &mv_eth_netdev_ops;
+
+#ifdef CONFIG_MV_ETH_TOOL
+	SET_ETHTOOL_OPS(dev, &mv_eth_tool_ops);
+#endif
+
+	/* Default NAPI initialization */
+	for (i = 0; i < CONFIG_MV_ETH_NAPI_GROUPS; i++) {
+		pp->napiGroup[i] = kmalloc(sizeof(struct napi_struct), GFP_KERNEL);
+		memset(pp->napiGroup[i], 0, sizeof(struct napi_struct));
+	}
+
+	for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
+		pp->napiCpuGroup[cpu] = 0;
+		pp->napi[cpu]         = NULL;
+		}
+
+	/* Add NAPI default group */
+	if (pp->flags & MV_ETH_F_CONNECT_LINUX) {
+		for (i = 0; i < CONFIG_MV_ETH_NAPI_GROUPS; i++)
+			netif_napi_add(dev, pp->napiGroup[i], mv_eth_poll, pp->weight);
+	}
+
+	pp->tx_done_timer.data = (unsigned long)dev;
+	pp->cleanup_timer.data = (unsigned long)dev;
+
+	if (pp->flags & MV_ETH_F_CONNECT_LINUX) {
+		if (register_netdev(dev)) {
+			printk(KERN_ERR "failed to register %s\n", dev->name);
+			free_netdev(dev);
+			return NULL;
+		} else {
+			mv_eth_netdev_set_features(dev);
+
+			printk(KERN_ERR "    o %s, ifindex = %d, GbE port = %d", dev->name, dev->ifindex, pp->port);
+#ifdef CONFIG_MV_ETH_SWITCH
+			if (!(pp->flags & MV_ETH_F_SWITCH))
+				printk(KERN_CONT "\n");
+#else
+			printk(KERN_CONT "\n");
+#endif
+		}
+	}
+	return dev;
+}
+
+bool mv_eth_netdev_find(unsigned int dev_idx)
+{
+	int i;
+
+	for (i = 0; i < mv_net_devs_num; i++) {
+		if (mv_net_devs && mv_net_devs[i] && (mv_net_devs[i]->ifindex == dev_idx))
+			return true;
+	}
+	return false;
+}
+EXPORT_SYMBOL(mv_eth_netdev_find);
+
+void mv_eth_netdev_update(int dev_index, struct eth_port *pp)
+{
+	int i;
+	struct eth_dev_priv *dev_priv;
+#ifdef CONFIG_MV_ETH_SWITCH
+	struct eth_netdev *eth_netdev_priv;
+#endif /* CONFIG_MV_ETH_SWITCH */
+	struct net_device *dev = mv_net_devs[dev_index];
+
+	dev_priv = (struct eth_dev_priv *)netdev_priv(dev); /* assuming dev_priv has to be valid here */
+
+	dev_priv->port_p = pp;
+
+	dev->irq = NET_TH_RXTX_IRQ_NUM(pp->port);
+
+	if (pp->flags & MV_ETH_F_CONNECT_LINUX) {
+		for (i = 0; i < CONFIG_MV_ETH_NAPI_GROUPS; i++)
+			netif_napi_add(dev, pp->napiGroup[i], mv_eth_poll, pp->weight);
+	}
+
+	pp->tx_done_timer.data = (unsigned long)dev;
+	pp->cleanup_timer.data = (unsigned long)dev;
+
+	printk(KERN_ERR "    o %s, ifindex = %d, GbE port = %d", dev->name, dev->ifindex, pp->port);
+
+#ifdef CONFIG_MV_ETH_SWITCH
+	if (pp->flags & MV_ETH_F_SWITCH) {
+		eth_netdev_priv = MV_DEV_PRIV(dev);
+		mv_eth_switch_priv_update(dev, MV_SWITCH_VLAN_TO_GROUP(eth_netdev_priv->vlan_grp_id));
+	} else {
+		printk(KERN_CONT "\n");
+	}
+#else
+	printk(KERN_CONT "\n");
+#endif /* CONFIG_MV_ETH_SWITCH */
+}
+
+
+int mv_eth_hal_init(struct eth_port *pp)
+{
+	int rxq, txp, txq, size;
+	struct tx_queue *txq_ctrl;
+	struct rx_queue *rxq_ctrl;
+
+	if (!MV_PON_PORT(pp->port)) {
+		int phyAddr;
+
+		/* Set the board information regarding PHY address */
+		phyAddr = mvBoardPhyAddrGet(pp->port);
+		mvNetaPhyAddrSet(pp->port, phyAddr);
+	}
+
+	/* Init port */
+	pp->port_ctrl = mvNetaPortInit(pp->port, NULL);
+	if (!pp->port_ctrl) {
+		printk(KERN_ERR "%s: failed to load port=%d\n", __func__, pp->port);
+		return -ENODEV;
+	}
+
+	size = pp->txp_num * CONFIG_MV_ETH_TXQ * sizeof(struct tx_queue);
+	pp->txq_ctrl = mvOsMalloc(size);
+	if (!pp->txq_ctrl)
+		goto oom;
+
+	memset(pp->txq_ctrl, 0, size);
+
+	/* Create TX descriptor rings */
+	for (txp = 0; txp < pp->txp_num; txp++) {
+		for (txq = 0; txq < CONFIG_MV_ETH_TXQ; txq++) {
+			txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+
+			txq_ctrl->q = NULL;
+			txq_ctrl->cpu_owner = 0;
+			txq_ctrl->hwf_rxp = 0xFF;
+			txq_ctrl->txp = txp;
+			txq_ctrl->txq = txq;
+			txq_ctrl->txq_size = CONFIG_MV_ETH_TXQ_DESC;
+			txq_ctrl->txq_count = 0;
+			txq_ctrl->bm_only = MV_FALSE;
+
+			txq_ctrl->shadow_txq_put_i = 0;
+			txq_ctrl->shadow_txq_get_i = 0;
+			txq_ctrl->txq_done_pkts_coal = mv_ctrl_txdone;
+		}
+	}
+
+	pp->rxq_ctrl = mvOsMalloc(CONFIG_MV_ETH_RXQ * sizeof(struct rx_queue));
+	if (!pp->rxq_ctrl)
+		goto oom;
+
+	memset(pp->rxq_ctrl, 0, CONFIG_MV_ETH_RXQ * sizeof(struct rx_queue));
+
+	/* Create Rx descriptor rings */
+	for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+		rxq_ctrl = &pp->rxq_ctrl[rxq];
+		rxq_ctrl->rxq_size = CONFIG_MV_ETH_RXQ_DESC;
+		rxq_ctrl->rxq_pkts_coal = CONFIG_MV_ETH_RX_COAL_PKTS;
+		rxq_ctrl->rxq_time_coal = CONFIG_MV_ETH_RX_COAL_USEC;
+	}
+
+	if (pp->flags & MV_ETH_F_MH)
+		mvNetaMhSet(pp->port, MV_NETA_MH);
+
+#ifdef CONFIG_MV_ETH_TOOL
+	/* Configure defaults */
+	pp->autoneg_cfg  = AUTONEG_ENABLE;
+	pp->speed_cfg    = SPEED_1000;
+	pp->duplex_cfg  = DUPLEX_FULL;
+	pp->advertise_cfg = 0x2f;
+#endif /* CONFIG_MV_ETH_TOOL */
+
+	return 0;
+oom:
+	printk(KERN_ERR "%s: port=%d: out of memory\n", __func__, pp->port);
+	return -ENODEV;
+}
+
+/* Show network driver configuration */
+void mv_eth_config_show(void)
+{
+	/* Check restrictions */
+#if (CONFIG_MV_ETH_PORTS_NUM > MV_ETH_MAX_PORTS)
+#   error "CONFIG_MV_ETH_PORTS_NUM is large than MV_ETH_MAX_PORTS"
+#endif
+
+#if (CONFIG_MV_ETH_RXQ > MV_ETH_MAX_RXQ)
+#   error "CONFIG_MV_ETH_RXQ is large than MV_ETH_MAX_RXQ"
+#endif
+
+#if CONFIG_MV_ETH_TXQ > MV_ETH_MAX_TXQ
+#   error "CONFIG_MV_ETH_TXQ is large than MV_ETH_MAX_TXQ"
+#endif
+
+#if defined(CONFIG_MV_ETH_TSO) && !defined(CONFIG_MV_ETH_TX_CSUM_OFFLOAD)
+#   error "If GSO enabled - TX checksum offload must be enabled too"
+#endif
+
+	printk(KERN_ERR "  o %d Giga ports supported\n", CONFIG_MV_ETH_PORTS_NUM);
+
+#ifdef CONFIG_MV_PON
+	printk(KERN_ERR "  o Giga PON port is #%d: - %d TCONTs supported\n", MV_PON_PORT_ID, MV_ETH_MAX_TCONT());
+#endif
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	printk(KERN_ERR "  o SKB recycle supported (%s)\n", mv_ctrl_recycle ? "Enabled" : "Disabled");
+#endif
+
+#ifdef CONFIG_MV_ETH_NETA
+	printk(KERN_ERR "  o NETA acceleration mode %d\n", mvNetaAccMode());
+#endif
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+	printk(KERN_ERR "  o BM supported for CPU: %d BM pools\n", MV_ETH_BM_POOLS);
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+#ifdef CONFIG_MV_ETH_PNC
+	printk(KERN_ERR "  o PnC supported (%s)\n", mv_eth_pnc_ctrl_en ? "Enabled" : "Disabled");
+#endif
+
+#ifdef CONFIG_MV_ETH_HWF
+	printk(KERN_ERR "  o HWF supported\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_PMT
+	printk(KERN_ERR "  o PMT supported\n");
+#endif
+
+	printk(KERN_ERR "  o RX Queue support: %d Queues * %d Descriptors\n", CONFIG_MV_ETH_RXQ, CONFIG_MV_ETH_RXQ_DESC);
+
+	printk(KERN_ERR "  o TX Queue support: %d Queues * %d Descriptors\n", CONFIG_MV_ETH_TXQ, CONFIG_MV_ETH_TXQ_DESC);
+
+#if defined(CONFIG_MV_ETH_TSO)
+	printk(KERN_ERR "  o GSO supported\n");
+#endif /* CONFIG_MV_ETH_TSO */
+
+#if defined(CONFIG_MV_ETH_GRO)
+	printk(KERN_ERR "  o GRO supported\n");
+#endif /* CONFIG_MV_ETH_GRO */
+
+#if defined(CONFIG_MV_ETH_RX_CSUM_OFFLOAD)
+	printk(KERN_ERR "  o Receive checksum offload supported\n");
+#endif
+#if defined(CONFIG_MV_ETH_TX_CSUM_OFFLOAD)
+	printk(KERN_ERR "  o Transmit checksum offload supported\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP
+	printk(KERN_ERR "  o Network Fast Processing (NFP) supported\n");
+#endif /* CONFIG_MV_ETH_NFP */
+
+#ifdef CONFIG_MV_ETH_STAT_ERR
+	printk(KERN_ERR "  o Driver ERROR statistics enabled\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_STAT_INF
+	printk(KERN_ERR "  o Driver INFO statistics enabled\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_STAT_DBG
+	printk(KERN_ERR "  o Driver DEBUG statistics enabled\n");
+#endif
+
+#ifdef ETH_DEBUG
+	printk(KERN_ERR "  o Driver debug messages enabled\n");
+#endif
+
+#if defined(CONFIG_MV_ETH_SWITCH)
+	printk(KERN_ERR "  o Switch support enabled\n");
+
+#ifdef CONFIG_MV_ETH_LOOP_DETECT
+	printk(KERN_ERR "  o Loop detection support\n");
+#endif /* CONFIG_MV_ETH_LOOP_DETECT */
+
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+	printk(KERN_ERR "\n");
+}
+
+/* Set network device features on initialization. Take into account default compile time configuration. */
+static void mv_eth_netdev_set_features(struct net_device *dev)
+{
+	dev->features = NETIF_F_SG | NETIF_F_LLTX;
+
+#ifdef CONFIG_MV_ETH_TX_CSUM_OFFLOAD_DEF
+	if (dev->mtu <= MV_ETH_TX_CSUM_MAX_SIZE)
+		dev->features |= NETIF_F_IP_CSUM;
+#endif /* CONFIG_MV_ETH_TX_CSUM_OFFLOAD_DEF */
+
+#ifdef CONFIG_MV_ETH_TSO_DEF
+	if (dev->features & NETIF_F_IP_CSUM)
+		dev->features |= NETIF_F_TSO;
+#endif /* CONFIG_MV_ETH_TSO_DEF */
+
+#ifdef CONFIG_MV_ETH_GRO_DEF
+	dev->features |= NETIF_F_GRO;
+#endif /* CONFIG_MV_ETH_GRO_DEF */
+}
+
+/* Update network device features after changing MTU.	*/
+static void mv_eth_netdev_update_features(struct net_device *dev)
+{
+#ifdef CONFIG_MV_ETH_TX_CSUM_OFFLOAD
+	if (dev->mtu > MV_ETH_TX_CSUM_MAX_SIZE) {
+		dev->features &= ~NETIF_F_IP_CSUM;
+		printk(KERN_ERR "Removing NETIF_F_IP_CSUM in device %s features\n", dev->name);
+	}
+#endif /* CONFIG_MV_ETH_TX_CSUM_OFFLOAD */
+
+#ifdef CONFIG_MV_ETH_TSO
+	if (!(dev->features & NETIF_F_IP_CSUM)) {
+		dev->features &= ~NETIF_F_TSO;
+		printk(KERN_ERR "Removing NETIF_F_TSO in device %s features\n", dev->name);
+	}
+#endif /* CONFIG_MV_ETH_TSO */
+}
+
+int mv_eth_napi_set_cpu_affinity(int port, int group, int affinity)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	if (pp == NULL) {
+		printk(KERN_ERR "%s: pp == NULL, port=%d\n", __func__, port);
+		return -1;
+	}
+
+	if (group >= CONFIG_MV_ETH_NAPI_GROUPS) {
+		printk(KERN_ERR "%s: group number is higher than %d\n", __func__, CONFIG_MV_ETH_NAPI_GROUPS-1);
+		return -1;
+		}
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "Port %d must be stopped before\n", port);
+		return -EINVAL;
+	}
+	set_cpu_affinity(pp, affinity, group);
+	return 0;
+
+}
+void handle_group_affinity(int port)
+{
+	int group;
+	struct eth_port *pp;
+	MV_U32 group_cpu_affinity[CONFIG_MV_ETH_NAPI_GROUPS];
+	MV_U32 rxq_affinity[CONFIG_MV_ETH_NAPI_GROUPS];
+
+	group_cpu_affinity[0] = CONFIG_MV_ETH_GROUP0_CPU;
+	rxq_affinity[0] 	  = CONFIG_MV_ETH_GROUP0_RXQ;
+
+#ifdef CONFIG_MV_ETH_GROUP1_CPU
+		group_cpu_affinity[1] = CONFIG_MV_ETH_GROUP1_CPU;
+		rxq_affinity[1] 	  = CONFIG_MV_ETH_GROUP1_RXQ;
+#endif
+
+#ifdef CONFIG_MV_ETH_GROUP2_CPU
+		group_cpu_affinity[2] = CONFIG_MV_ETH_GROUP2_CPU;
+		rxq_affinity[2] 	  = CONFIG_MV_ETH_GROUP2_RXQ;
+#endif
+
+#ifdef CONFIG_MV_ETH_GROUP3_CPU
+		group_cpu_affinity[3] = CONFIG_MV_ETH_GROUP3_CPU;
+		rxq_affinity[3] 	  = CONFIG_MV_ETH_GROUP3_RXQ;
+#endif
+
+	pp = mv_eth_port_by_id(port);
+	if (pp == NULL)
+		return;
+
+	for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
+		set_cpu_affinity(pp, group_cpu_affinity[group], group);
+	for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++)
+		set_rxq_affinity(pp, rxq_affinity[group], group);
+
+}
+
+int	mv_eth_napi_set_rxq_affinity(int port, int group, int rxqAffinity)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL) {
+		printk(KERN_ERR "%s: pp is null \n", __func__);
+		return MV_FAIL;
+	}
+	if (group >= CONFIG_MV_ETH_NAPI_GROUPS) {
+		printk(KERN_ERR "%s: group number is higher than %d\n", __func__, CONFIG_MV_ETH_NAPI_GROUPS-1);
+		return -1;
+		}
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "Port %d must be stopped before\n", port);
+		return -EINVAL;
+	}
+
+	set_rxq_affinity(pp, rxqAffinity, group);
+	return MV_OK;
+}
+
+
+void mv_eth_napi_group_show(int port)
+{
+	int cpu, group;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL) {
+		printk(KERN_ERR "%s: pp == NULL\n", __func__);
+		return;
+	}
+	for (group = 0; group < CONFIG_MV_ETH_NAPI_GROUPS; group++) {
+		printk(KERN_INFO "group=%d:\n", group);
+		for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
+			if (!(MV_BIT_CHECK(pp->cpuMask, cpu)))
+				continue;
+			if (pp->napiCpuGroup[cpu] == group) {
+				printk(KERN_INFO "   CPU%d ", cpu);
+				mvNetaRxqCpuDump(port, cpu);
+				printk(KERN_INFO "\n");
+			}
+		}
+		printk(KERN_INFO "\n");
+	}
+}
+
+void mv_eth_priv_cleanup(struct eth_port *pp)
+{
+	/* TODO */
+}
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+static struct bm_pool *mv_eth_long_pool_get(struct eth_port *pp, int pkt_size)
+{
+	int             pool, i;
+	struct bm_pool	*bm_pool, *temp_pool = NULL;
+	unsigned long   flags = 0;
+
+	pool = mv_eth_bm_config_long_pool_get(pp->port);
+	if (pool != -1) /* constant long pool for the port */
+		return &mv_eth_pool[pool];
+
+	/* look for free pool pkt_size == 0. First check pool == pp->port */
+	/* if no free pool choose larger than required */
+	for (i = 0; i < MV_ETH_BM_POOLS; i++) {
+		pool = (pp->port + i) % MV_ETH_BM_POOLS;
+		bm_pool = &mv_eth_pool[pool];
+
+		MV_ETH_LOCK(&bm_pool->lock, flags);
+
+		if (bm_pool->pkt_size == 0) {
+			/* found free pool */
+
+			MV_ETH_UNLOCK(&bm_pool->lock, flags);
+			return bm_pool;
+		}
+		if (bm_pool->pkt_size >= pkt_size) {
+			if (temp_pool == NULL)
+				temp_pool = bm_pool;
+			else if (bm_pool->pkt_size < temp_pool->pkt_size)
+				temp_pool = bm_pool;
+		}
+		MV_ETH_UNLOCK(&bm_pool->lock, flags);
+	}
+	return temp_pool;
+}
+#else
+static struct bm_pool *mv_eth_long_pool_get(struct eth_port *pp, int pkt_size)
+{
+	return &mv_eth_pool[pp->port];
+}
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+static int mv_eth_rxq_fill(struct eth_port *pp, int rxq, int num)
+{
+	int i;
+
+#ifndef CONFIG_MV_ETH_BM_CPU
+	struct eth_pbuf *pkt;
+	struct bm_pool *bm_pool;
+	MV_NETA_RXQ_CTRL *rx_ctrl;
+	struct neta_rx_desc *rx_desc;
+
+	bm_pool = pp->pool_long;
+
+	rx_ctrl = pp->rxq_ctrl[rxq].q;
+	if (!rx_ctrl) {
+		printk(KERN_ERR "%s: rxq %d is not initialized\n", __func__, rxq);
+		return 0;
+	}
+
+	for (i = 0; i < num; i++) {
+		pkt = mv_eth_pool_get(bm_pool);
+		if (pkt) {
+			rx_desc = (struct neta_rx_desc *)MV_NETA_QUEUE_DESC_PTR(&rx_ctrl->queueCtrl, i);
+			memset(rx_desc, 0, sizeof(struct neta_rx_desc));
+
+			mvNetaRxDescFill(rx_desc, pkt->physAddr, (MV_U32)pkt);
+		} else {
+			printk(KERN_ERR "%s: rxq %d, %d of %d buffers are filled\n", __func__, rxq, i, num);
+			break;
+		}
+	}
+#else
+	i = num;
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	mvNetaRxqNonOccupDescAdd(pp->port, rxq, i);
+
+	return i;
+}
+
+static int mv_eth_txq_create(struct eth_port *pp, struct tx_queue *txq_ctrl)
+{
+	txq_ctrl->q = mvNetaTxqInit(pp->port, txq_ctrl->txp, txq_ctrl->txq, txq_ctrl->txq_size);
+	if (txq_ctrl->q == NULL) {
+		printk(KERN_ERR "%s: can't create TxQ - port=%d, txp=%d, txq=%d, desc=%d\n",
+		       __func__, pp->port, txq_ctrl->txp, txq_ctrl->txp, txq_ctrl->txq_size);
+		return -ENODEV;
+	}
+
+	txq_ctrl->shadow_txq = mvOsMalloc(txq_ctrl->txq_size * sizeof(MV_ULONG));
+	if (txq_ctrl->shadow_txq == NULL)
+		goto no_mem;
+
+	/* reset txq */
+	txq_ctrl->txq_count = 0;
+	txq_ctrl->shadow_txq_put_i = 0;
+	txq_ctrl->shadow_txq_get_i = 0;
+
+#ifdef CONFIG_MV_ETH_HWF
+	mvNetaHwfTxqInit(pp->port, txq_ctrl->txp, txq_ctrl->txq);
+#endif /* CONFIG_MV_ETH_HWF */
+
+	return 0;
+
+no_mem:
+	mv_eth_txq_delete(pp, txq_ctrl);
+	return -ENOMEM;
+}
+
+
+static int mv_force_port_link_speed_fc(int port, MV_ETH_PORT_SPEED port_speed, int en_force)
+{
+	if (en_force) {
+		if (mvNetaForceLinkModeSet(port, 1, 0)) {
+			printk(KERN_ERR "mvNetaForceLinkModeSet failed\n");
+			return -EIO;
+		}
+		if (mvNetaSpeedDuplexSet(port, port_speed, MV_ETH_DUPLEX_FULL)) {
+			printk(KERN_ERR "mvNetaSpeedDuplexSet failed\n");
+			return -EIO;
+		}
+		if (mvNetaFlowCtrlSet(port, MV_ETH_FC_ENABLE)) {
+			printk(KERN_ERR "mvNetaFlowCtrlSet failed\n");
+			return -EIO;
+		}
+	} else {
+		if (mvNetaForceLinkModeSet(port, 0, 0)) {
+			printk(KERN_ERR "mvNetaForceLinkModeSet failed\n");
+			return -EIO;
+		}
+		if (mvNetaSpeedDuplexSet(port, MV_ETH_SPEED_AN, MV_ETH_DUPLEX_AN)) {
+			printk(KERN_ERR "mvNetaSpeedDuplexSet failed\n");
+			return -EIO;
+		}
+		if (mvNetaFlowCtrlSet(port, MV_ETH_FC_AN_SYM)) {
+			printk(KERN_ERR "mvNetaFlowCtrlSet failed\n");
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+static void mv_eth_txq_delete(struct eth_port *pp, struct tx_queue *txq_ctrl)
+{
+	if (txq_ctrl->shadow_txq) {
+		mvOsFree(txq_ctrl->shadow_txq);
+		txq_ctrl->shadow_txq = NULL;
+	}
+
+	if (txq_ctrl->q) {
+		mvNetaTxqDelete(pp->port, txq_ctrl->txp, txq_ctrl->txq);
+		txq_ctrl->q = NULL;
+	}
+}
+
+/* Free all packets pending transmit from all TXQs and reset TX port */
+int mv_eth_txp_reset(int port, int txp)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	int queue;
+
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "Port %d must be stopped before\n", port);
+		return -EINVAL;
+	}
+
+	/* free the skb's in the hal tx ring */
+	for (queue = 0; queue < CONFIG_MV_ETH_TXQ; queue++) {
+		struct tx_queue *txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + queue];
+
+		if (txq_ctrl->q)
+			mv_eth_txq_done_force(pp, txq_ctrl);
+	}
+	mvNetaTxpReset(port, txp);
+	return 0;
+}
+
+/* Free received packets from all RXQs and reset RX of the port */
+int mv_eth_rx_reset(int port)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "Port %d must be stopped before\n", port);
+		return -EINVAL;
+	}
+
+#ifndef CONFIG_MV_ETH_BM_CPU
+	{
+		int rxq = 0;
+
+		for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+			struct eth_pbuf *pkt;
+			struct neta_rx_desc *rx_desc;
+			struct bm_pool *pool;
+			int i, rx_done;
+			MV_NETA_RXQ_CTRL *rx_ctrl = pp->rxq_ctrl[rxq].q;
+
+			if (rx_ctrl == NULL)
+				continue;
+
+			rx_done = mvNetaRxqFreeDescNumGet(pp->port, rxq);
+			mvOsCacheIoSync();
+			for (i = 0; i < rx_done; i++) {
+				rx_desc = mvNetaRxqNextDescGet(rx_ctrl);
+				mvOsCacheLineInv(NULL, rx_desc);
+
+#if defined(MV_CPU_BE)
+				mvNetaRxqDescSwap(rx_desc);
+#endif /* MV_CPU_BE */
+
+				pkt = (struct eth_pbuf *)rx_desc->bufCookie;
+				pool = &mv_eth_pool[pkt->pool];
+				mv_eth_pool_put(pool, pkt);
+			}
+		}
+	}
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	mvNetaRxReset(port);
+	return 0;
+}
+
+/***********************************************************
+ * coal set functions		                           *
+ ***********************************************************/
+MV_STATUS mv_eth_rx_ptks_coal_set(int port, int rxq, MV_U32 value)
+{
+	MV_STATUS status = mvNetaRxqPktsCoalSet(port, rxq, value);
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	if (status == MV_OK)
+		pp->rxq_ctrl[rxq].rxq_pkts_coal = value;
+	return status;
+}
+
+MV_STATUS mv_eth_rx_time_coal_set(int port, int rxq, MV_U32 value)
+{
+	MV_STATUS status = mvNetaRxqTimeCoalSet(port, rxq, value);
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	if (status == MV_OK)
+		pp->rxq_ctrl[rxq].rxq_time_coal = value;
+	return status;
+}
+
+MV_STATUS mv_eth_tx_done_ptks_coal_set(int port, int txp, int txq, MV_U32 value)
+{
+	MV_STATUS status = mvNetaTxDonePktsCoalSet(port, txp, txq, value);
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	if (status == MV_OK)
+		pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq].txq_done_pkts_coal = value;
+	return status;
+}
+
+/***********************************************************
+ * mv_eth_start_internals --                               *
+ *   fill rx buffers. start rx/tx activity. set coalesing. *
+ *   clear and unmask interrupt bits                       *
+ ***********************************************************/
+int mv_eth_start_internals(struct eth_port *pp, int mtu)
+{
+	unsigned long rwflags;
+	unsigned int status;
+	int rxq, txp, txq, num, err = 0;
+	int pkt_size = RX_PKT_SIZE(mtu);
+	MV_BOARD_MAC_SPEED mac_speed;
+
+	write_lock_irqsave(&pp->rwlock, rwflags);
+
+	if (mvNetaMaxRxSizeSet(pp->port, RX_PKT_SIZE(mtu))) {
+		printk(KERN_ERR "%s: can't set maxRxSize=%d for port=%d, mtu=%d\n",
+		       __func__, RX_PKT_SIZE(mtu), pp->port, mtu);
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (mv_eth_ctrl_is_tx_enabled(pp)) {
+		int cpu;
+		for_each_possible_cpu(cpu) {
+			if (!(MV_BIT_CHECK(pp->cpuMask, cpu)))
+				continue;
+			if (mv_eth_ctrl_txq_cpu_own(pp->port, pp->txp, pp->txq[cpu], 1) < 0) {
+				err = -EINVAL;
+				goto out;
+			}
+		}
+	}
+
+	/* Allocate buffers for Long buffers pool */
+	if (pp->pool_long == NULL) {
+		struct bm_pool *new_pool;
+
+		new_pool = mv_eth_long_pool_get(pp, pkt_size);
+		if (new_pool == NULL) {
+			printk(KERN_ERR "%s FAILED: port=%d, Can't find pool for pkt_size=%d\n",
+			       __func__, pp->port, pkt_size);
+			err = -ENOMEM;
+			goto out;
+		}
+		if (new_pool->pkt_size == 0) {
+			new_pool->pkt_size = pkt_size;
+#ifdef CONFIG_MV_ETH_BM_CPU
+			mvBmPoolBufSizeSet(new_pool->pool, RX_BUF_SIZE(pkt_size));
+#endif /* CONFIG_MV_ETH_BM_CPU */
+		}
+		if (new_pool->pkt_size < pkt_size) {
+			printk(KERN_ERR "%s FAILED: port=%d, long pool #%d, pkt_size=%d less than required %d\n",
+					__func__, pp->port, new_pool->pool, new_pool->pkt_size, pkt_size);
+			err = -ENOMEM;
+			goto out;
+		}
+		pp->pool_long = new_pool;
+		pp->pool_long->port_map |= (1 << pp->port);
+
+		num = mv_eth_pool_add(pp->pool_long->pool, pp->pool_long_num);
+		if (num != pp->pool_long_num) {
+			printk(KERN_ERR "%s FAILED: mtu=%d, pool=%d, pkt_size=%d, only %d of %d allocated\n",
+			       __func__, mtu, pp->pool_long->pool, pp->pool_long->pkt_size, num, pp->pool_long_num);
+			err = -ENOMEM;
+			goto out;
+		}
+	}
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+	mvNetaBmPoolBufSizeSet(pp->port, pp->pool_long->pool, RX_BUF_SIZE(pp->pool_long->pkt_size));
+
+	if (pp->pool_short == NULL) {
+		int short_pool = mv_eth_bm_config_short_pool_get(pp->port);
+
+		/* Allocate packets for short pool */
+		if (short_pool < 0) {
+			err = -EINVAL;
+			goto out;
+		}
+		pp->pool_short = &mv_eth_pool[short_pool];
+		pp->pool_short->port_map |= (1 << pp->port);
+		if (pp->pool_short->pool != pp->pool_long->pool) {
+			num = mv_eth_pool_add(pp->pool_short->pool, pp->pool_short_num);
+			if (num != pp->pool_short_num) {
+				printk(KERN_ERR "%s FAILED: pool=%d, pkt_size=%d - %d of %d buffers added\n",
+					   __func__, short_pool, pp->pool_short->pkt_size, num, pp->pool_short_num);
+				err = -ENOMEM;
+				goto out;
+			}
+			mvNetaBmPoolBufSizeSet(pp->port, pp->pool_short->pool, RX_BUF_SIZE(pp->pool_short->pkt_size));
+		} else {
+			int dummy_short_pool = (pp->pool_short->pool + 1) % MV_BM_POOLS;
+
+			/* To disable short pool we choose unused pool and set pkt size to 0 (buffer size = pkt offset) */
+			mvNetaBmPoolBufSizeSet(pp->port, dummy_short_pool, NET_SKB_PAD);
+		}
+	}
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+		if (pp->rxq_ctrl[rxq].q == NULL) {
+			pp->rxq_ctrl[rxq].q = mvNetaRxqInit(pp->port, rxq, pp->rxq_ctrl[rxq].rxq_size);
+			if (!pp->rxq_ctrl[rxq].q) {
+				printk(KERN_ERR "%s: can't create RxQ port=%d, rxq=%d, desc=%d\n",
+				       __func__, pp->port, rxq, pp->rxq_ctrl[rxq].rxq_size);
+				err = -ENODEV;
+				goto out;
+			}
+		}
+
+		/* Set Offset */
+		mvNetaRxqOffsetSet(pp->port, rxq, NET_SKB_PAD);
+
+		/* Set coalescing pkts and time */
+		mv_eth_rx_ptks_coal_set(pp->port, rxq, pp->rxq_ctrl[rxq].rxq_pkts_coal);
+		mv_eth_rx_time_coal_set(pp->port, rxq, pp->rxq_ctrl[rxq].rxq_time_coal);
+
+#if defined(CONFIG_MV_ETH_BM_CPU)
+		/* Enable / Disable - BM support */
+		if (pp->pool_short->pool == pp->pool_long->pool) {
+			int dummy_short_pool = (pp->pool_short->pool + 1) % MV_BM_POOLS;
+
+			/* To disable short pool we choose unused pool and set pkt size to 0 (buffer size = pkt offset) */
+			mvNetaRxqBmEnable(pp->port, rxq, dummy_short_pool, pp->pool_long->pool);
+		} else
+			mvNetaRxqBmEnable(pp->port, rxq, pp->pool_short->pool, pp->pool_long->pool);
+#else
+		/* Fill RXQ with buffers from RX pool */
+		mvNetaRxqBufSizeSet(pp->port, rxq, RX_BUF_SIZE(pkt_size));
+		mvNetaRxqBmDisable(pp->port, rxq);
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+		if (mvNetaRxqFreeDescNumGet(pp->port, rxq) == 0)
+			mv_eth_rxq_fill(pp, rxq, pp->rxq_ctrl[rxq].rxq_size);
+	}
+
+	for (txp = 0; txp < pp->txp_num; txp++) {
+		for (txq = 0; txq < CONFIG_MV_ETH_TXQ; txq++) {
+			struct tx_queue *txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+
+			if ((txq_ctrl->q == NULL) && (txq_ctrl->txq_size > 0)) {
+				err = mv_eth_txq_create(pp, txq_ctrl);
+				if (err)
+					goto out;
+				spin_lock_init(&txq_ctrl->queue_lock);
+			}
+			mv_eth_tx_done_ptks_coal_set(pp->port, txp, txq,
+					pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq].txq_done_pkts_coal);
+		}
+		mvNetaTxpMaxTxSizeSet(pp->port, txp, RX_PKT_SIZE(mtu));
+	}
+
+#ifdef CONFIG_MV_ETH_HWF
+#ifdef CONFIG_MV_ETH_BM_CPU
+	mvNetaHwfBmPoolsSet(pp->port, pp->pool_short->pool, pp->pool_long->pool);
+#else
+	mv_eth_hwf_bm_create(pp->port, RX_PKT_SIZE(mtu));
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	mvNetaHwfEnable(pp->port, 1);
+#endif /* CONFIG_MV_ETH_HWF */
+
+	if (!MV_PON_PORT(pp->port)) {
+		/* force link, speed and duplex if necessary (e.g. Switch is connected) based on board information */
+		mac_speed = mvBoardMacSpeedGet(pp->port);
+		switch (mac_speed) {
+		case BOARD_MAC_SPEED_10M:
+			err = mv_force_port_link_speed_fc(pp->port, MV_ETH_SPEED_10, 1);
+			if (err)
+				goto out;
+			break;
+		case BOARD_MAC_SPEED_100M:
+			err = mv_force_port_link_speed_fc(pp->port, MV_ETH_SPEED_100, 1);
+			if (err)
+				goto out;
+			break;
+		case BOARD_MAC_SPEED_1000M:
+			err = mv_force_port_link_speed_fc(pp->port, MV_ETH_SPEED_1000, 1);
+			if (err)
+				goto out;
+			break;
+		case BOARD_MAC_SPEED_AUTO:
+		default:
+			/* do nothing */
+			break;
+		}
+	}
+
+	/* start the hal - rx/tx activity */
+	status = mvNetaPortEnable(pp->port);
+	if (status == MV_OK)
+		set_bit(MV_ETH_F_LINK_UP_BIT, &(pp->flags));
+#ifdef CONFIG_MV_PON
+	else if (MV_PON_PORT(pp->port) && (mv_pon_link_status() == MV_TRUE)) {
+		mvNetaPortUp(pp->port);
+		set_bit(MV_ETH_F_LINK_UP_BIT, &(pp->flags));
+	}
+#endif /* CONFIG_MV_PON */
+
+	set_bit(MV_ETH_F_STARTED_BIT, &(pp->flags));
+
+ out:
+	write_unlock_irqrestore(&pp->rwlock, rwflags);
+	return err;
+}
+
+/***********************************************************
+ * mv_eth_stop_internals --                                *
+ *   stop port rx/tx activity. free skb's from rx/tx rings.*
+ ***********************************************************/
+int mv_eth_stop_internals(struct eth_port *pp)
+{
+	unsigned long rwflags;
+	int queue;
+
+	write_lock_irqsave(&pp->rwlock, rwflags);
+
+	clear_bit(MV_ETH_F_STARTED_BIT, &(pp->flags));
+
+	/* stop the port activity */
+	if (mvNetaPortDisable(pp->port) != MV_OK) {
+		printk(KERN_ERR "GbE port %d: ethPortDisable failed\n", pp->port);
+		goto error;
+	}
+
+	/* clear all ethernet port interrupts ???? */
+	MV_REG_WRITE(NETA_INTR_MISC_CAUSE_REG(pp->port), 0);
+	MV_REG_WRITE(NETA_INTR_OLD_CAUSE_REG(pp->port), 0);
+
+	/* mask all ethernet port interrupts ???? */
+	MV_REG_WRITE(NETA_INTR_NEW_MASK_REG(pp->port), 0);
+	MV_REG_WRITE(NETA_INTR_OLD_MASK_REG(pp->port), 0);
+	MV_REG_WRITE(NETA_INTR_MISC_MASK_REG(pp->port), 0);
+
+#ifdef CONFIG_MV_ETH_HWF
+	mvNetaHwfEnable(pp->port, 0);
+#else
+	{
+		int txp;
+		/* Reset TX port here. If HWF is supported reset must be called externally */
+		for (txp = 0; txp < pp->txp_num; txp++)
+			mv_eth_txp_reset(pp->port, txp);
+	}
+#endif /* !CONFIG_MV_ETH_HWF */
+
+	if (mv_eth_ctrl_is_tx_enabled(pp)) {
+		int cpu;
+		for_each_possible_cpu(cpu) {
+			if (MV_BIT_CHECK(pp->cpuMask, cpu))
+				mv_eth_ctrl_txq_cpu_own(pp->port, pp->txp, pp->txq[cpu], 0);
+		}
+	}
+
+	/* free the skb's in the hal rx ring */
+	for (queue = 0; queue < CONFIG_MV_ETH_RXQ; queue++)
+		mv_eth_rxq_drop_pkts(pp, queue);
+
+	write_unlock_irqrestore(&pp->rwlock, rwflags);
+
+	return 0;
+
+error:
+	printk(KERN_ERR "GbE port %d: stop internals failed\n", pp->port);
+	write_unlock_irqrestore(&pp->rwlock, rwflags);
+
+	return -1;
+}
+
+/* return positive if MTU is valid */
+int mv_eth_check_mtu_valid(struct net_device *dev, int mtu)
+{
+	if (mtu < 68) {
+		printk(KERN_INFO "MTU must be at least 68, change mtu failed\n");
+		return -EINVAL;
+	}
+	if (mtu > 9676 /* 9700 - 20 and rounding to 8 */) {
+		printk(KERN_ERR "%s: Illegal MTU value %d, ", dev->name, mtu);
+		mtu = 9676;
+		printk(KERN_CONT " rounding MTU to: %d \n", mtu);
+	}
+
+	if (MV_IS_NOT_ALIGN(RX_PKT_SIZE(mtu), 8)) {
+		printk(KERN_ERR "%s: Illegal MTU value %d, ", dev->name, mtu);
+		mtu = MV_ALIGN_UP(RX_PKT_SIZE(mtu), 8);
+		printk(KERN_CONT " rounding MTU to: %d \n", mtu);
+	}
+	return mtu;
+}
+
+/* Check if MTU can be changed */
+int mv_eth_check_mtu_internals(struct net_device *dev, int mtu)
+{
+	struct eth_port *pp = MV_ETH_PRIV(dev);
+	struct bm_pool	*new_pool = NULL;
+
+	new_pool = mv_eth_long_pool_get(pp, RX_PKT_SIZE(mtu));
+
+	/* If no pool for new MTU or shared pool is used - MTU can be changed only when interface is stopped */
+	if (new_pool == NULL) {
+		printk(KERN_ERR "%s: No BM pool available for MTU=%d\n", __func__, mtu);
+		return -EPERM;
+	}
+#ifdef CONFIG_MV_ETH_BM_CPU
+	if (new_pool->pkt_size < RX_PKT_SIZE(mtu)) {
+		if (mv_eth_bm_config_pkt_size_get(new_pool->pool) != 0) {
+			printk(KERN_ERR "%s: BM pool #%d - pkt_size = %d less than required for MTU=%d and can't be changed\n",
+						__func__, new_pool->pool, new_pool->pkt_size, mtu);
+			return -EPERM;
+		}
+		/* Pool packet size can be changed for new MTU, but pool is shared */
+		if ((new_pool == pp->pool_long) && (pp->pool_long->port_map != (1 << pp->port))) {
+			/* Shared pool */
+			printk(KERN_ERR "%s: bmPool=%d is shared port_map=0x%x. Stop all ports uses this pool before change MTU\n",
+						__func__, pp->pool_long->pool, pp->pool_long->port_map);
+			return -EPERM;
+		}
+	}
+#endif /* CONFIG_MV_ETH_BM_CPU */
+	return 0;
+}
+
+/***********************************************************
+ * mv_eth_change_mtu_internals --                          *
+ *   stop port activity. release skb from rings. set new   *
+ *   mtu in device and hw. restart port activity and       *
+ *   and fill rx-buiffers with size according to new mtu.  *
+ ***********************************************************/
+int mv_eth_change_mtu_internals(struct net_device *dev, int mtu)
+{
+	struct bm_pool	*new_pool = NULL;
+	struct eth_port *pp = MV_ETH_PRIV(dev);
+	int             config_pkt_size;
+	unsigned long	rwflags;
+
+	if ((mtu != dev->mtu) && (pp->pool_long)) {
+		/* If long pool assigned and MTU really changed and can't use old pool - free buffers */
+		write_lock_irqsave(&pp->rwlock, rwflags);
+
+		config_pkt_size = 0;
+#ifdef CONFIG_MV_ETH_BM_CPU
+		new_pool = mv_eth_long_pool_get(pp, RX_PKT_SIZE(mtu));
+		if (new_pool != NULL)
+			config_pkt_size = mv_eth_bm_config_pkt_size_get(new_pool->pool);
+#else
+		/* If BM is not used always free buffers */
+		new_pool = NULL;
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+		/* Free all buffers from long pool */
+		if ((new_pool == NULL) || (new_pool->pkt_size < RX_PKT_SIZE(mtu)) || (pp->pool_long != new_pool) ||
+			((new_pool->pkt_size > RX_PKT_SIZE(mtu)) && (config_pkt_size == 0))) {
+			mv_eth_rx_reset(pp->port);
+			mv_eth_pool_free(pp->pool_long->pool, pp->pool_long_num);
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+			/* redefine pool pkt_size */
+			if (pp->pool_long->buf_num == 0) {
+				pp->pool_long->pkt_size = config_pkt_size;
+
+				if (pp->pool_long->pkt_size == 0)
+					mvBmPoolBufSizeSet(pp->pool_long->pool, 0);
+				else
+					mvBmPoolBufSizeSet(pp->pool_long->pool, RX_BUF_SIZE(pp->pool_long->pkt_size));
+			}
+#else
+			pp->pool_long->pkt_size = config_pkt_size;
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+			pp->pool_long->port_map &= ~(1 << pp->port);
+			pp->pool_long = NULL;
+		}
+
+		/* DIMA debug; Free all buffers from short pool */
+/*
+		if(pp->pool_short) {
+			mv_eth_pool_free(pp->pool_short->pool, pp->pool_short_num);
+			pp->pool_short = NULL;
+		}
+*/
+		write_unlock_irqrestore(&pp->rwlock, rwflags);
+	}
+	dev->mtu = mtu;
+
+	mv_eth_netdev_update_features(dev);
+
+	return 0;
+}
+
+/***********************************************************
+ * mv_eth_tx_done_timer_callback --			   *
+ *   N msec periodic callback for tx_done                  *
+ ***********************************************************/
+static void mv_eth_tx_done_timer_callback(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct eth_port *pp = MV_ETH_PRIV(dev);
+	int tx_done = 0, tx_todo = 0;
+
+	read_lock(&pp->rwlock);
+	STAT_INFO(pp->stats.tx_done_timer++);
+
+	clear_bit(MV_ETH_F_TX_DONE_TIMER_BIT, &(pp->flags));
+
+	if (MV_PON_PORT(pp->port))
+		tx_done = mv_eth_tx_done_pon(pp, &tx_todo);
+	else
+		/* check all possible queues, as there is no indication from interrupt */
+		tx_done = mv_eth_tx_done_gbe(pp,
+			(((1 << CONFIG_MV_ETH_TXQ) - 1) & NETA_CAUSE_TXQ_SENT_DESC_ALL_MASK), &tx_todo);
+
+	if (tx_todo > 0)
+		mv_eth_add_tx_done_timer(pp);
+
+	read_unlock(&pp->rwlock);
+}
+
+/***********************************************************
+ * mv_eth_cleanup_timer_callback --			   *
+ *   N msec periodic callback for error cleanup            *
+ ***********************************************************/
+static void mv_eth_cleanup_timer_callback(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct eth_port *pp = MV_ETH_PRIV(dev);
+
+	read_lock(&pp->rwlock);
+	STAT_INFO(pp->stats.cleanup_timer++);
+
+	/* FIXME: check bm_pool->missed and pp->rxq_ctrl[rxq].missed counters and allocate */
+	/* re-add timer if necessary (check bm_pool->missed and pp->rxq_ctrl[rxq].missed   */
+
+	clear_bit(MV_ETH_F_CLEANUP_TIMER_BIT, &(pp->flags));
+	read_unlock(&pp->rwlock);
+}
+
+void mv_eth_mac_show(int port)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL) {
+		printk(KERN_ERR "%s: port %d entry is null \n", __func__, port);
+		return;
+	}
+
+#ifdef CONFIG_MV_ETH_PNC
+	if (mv_eth_pnc_ctrl_en) {
+		mvOsPrintf("PnC MAC Rules - port #%d:\n", port);
+		pnc_mac_show();
+	} else
+		mvOsPrintf("%s: PNC control is disabled\n", __func__);
+#else /* Legacy parser */
+	mvEthPortUcastShow(port);
+	mvEthPortMcastShow(port);
+#endif /* CONFIG_MV_ETH_PNC */
+}
+
+void mv_eth_vlan_prio_show(int port)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL) {
+		printk(KERN_ERR "%s: port %d entry is null \n", __func__, port);
+		return;
+	}
+
+#ifdef CONFIG_MV_ETH_PNC
+	if (mv_eth_pnc_ctrl_en) {
+		mvOsPrintf("PnC VLAN Priority Rules - port #%d:\n", port);
+		pnc_vlan_prio_show(port);
+	} else
+		mvOsPrintf("%s: PNC control is disabled\n", __func__);
+#else /* Legacy parser */
+	{
+		int prio, rxq;
+
+		mvOsPrintf("Legacy VLAN Priority Rules - port #%d:\n", port);
+		for (prio = 0; prio <= 0x7 ; prio++) {
+
+			rxq = mvNetaVprioToRxqGet(port, prio);
+			if (rxq > 0)
+				printk(KERN_INFO "prio=%d: rxq=%d\n", prio, rxq);
+		}
+	}
+#endif /* CONFIG_MV_ETH_PNC */
+}
+
+void mv_eth_tos_map_show(int port)
+{
+	int tos, txq;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL) {
+		printk(KERN_ERR "%s: port %d entry is null \n", __func__, port);
+		return;
+	}
+
+#ifdef CONFIG_MV_ETH_PNC
+	if (mv_eth_pnc_ctrl_en) {
+		mvOsPrintf("PnC TOS to RXQs Mapping Rules - port #%d:\n", port);
+		pnc_ipv4_dscp_show(port);
+	} else
+		mvOsPrintf("%s: PNC control is disabled\n", __func__);
+#else
+	mvOsPrintf("Legacy TOS to RXQs Mapping Rules - port #%d:\n", port);
+	for (tos = 0; tos < 0xFF; tos += 0x4) {
+		int rxq;
+
+		rxq = mvNetaTosToRxqGet(port, tos);
+		if (rxq > 0)
+			printk(KERN_ERR "tos=0x%02x: codepoint=0x%02x, rxq=%d\n",
+					tos, tos >> 2, rxq);
+	}
+#endif /* CONFIG_MV_ETH_PNC */
+
+	printk(KERN_ERR "\n");
+	printk(KERN_ERR " TOS <=> TXQ map for port #%d\n\n", port);
+
+	for (tos = 0; tos < sizeof(pp->txq_tos_map); tos++) {
+		txq = pp->txq_tos_map[tos];
+		if (txq != MV_ETH_TXQ_INVALID)
+			printk(KERN_ERR "0x%02x <=> %d\n", tos, txq);
+	}
+}
+
+int mv_eth_rxq_tos_map_set(int port, int rxq, unsigned char tos)
+{
+	int status = -1;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL) {
+		printk(KERN_ERR "%s: port %d entry is null \n", __func__, port);
+		return 1;
+	}
+
+#ifdef CONFIG_MV_ETH_PNC
+	if (mv_eth_pnc_ctrl_en)
+		status = pnc_ip4_dscp(port, tos, 0xFF, rxq);
+	else
+		mvOsPrintf("%s: PNC control is disabled\n", __func__);
+#else /* Legacy parser */
+	status = mvNetaTosToRxqSet(port, tos, rxq);
+#endif /* CONFIG_MV_ETH_PNC */
+
+	if (status == 0)
+		printk(KERN_ERR "Succeeded\n");
+	else if (status == -1)
+		printk(KERN_ERR "Not supported\n");
+	else
+		printk(KERN_ERR "Failed\n");
+
+	return status;
+}
+
+int mv_eth_rxq_vlan_prio_set(int port, int rxq, unsigned char prio)
+{
+	int status = -1;
+
+#ifdef CONFIG_MV_ETH_PNC
+	if (mv_eth_pnc_ctrl_en)
+		status = pnc_vlan_prio_set(port, prio, rxq);
+	else
+		mvOsPrintf("%s: PNC control is disabled\n", __func__);
+#else /* Legacy parser */
+	status = mvNetaVprioToRxqSet(port, prio, rxq);
+#endif /* CONFIG_MV_ETH_PNC */
+
+	if (status == 0)
+		printk(KERN_ERR "Succeeded\n");
+	else if (status == -1)
+		printk(KERN_ERR "Not supported\n");
+	else
+		printk(KERN_ERR "Failed\n");
+
+	return status;
+}
+
+/* Set TXQ for special TOS value. txq=-1 - use default TXQ for this port */
+int mv_eth_txq_tos_map_set(int port, int txq, unsigned char tos)
+{
+	MV_U8 old_txq;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (mvNetaPortCheck(port))
+		return -EINVAL;
+
+	if ((pp == NULL) || (pp->txq_ctrl == NULL))
+		return -ENODEV;
+
+	old_txq = pp->txq_tos_map[tos];
+
+	if (old_txq != MV_ETH_TXQ_INVALID) {
+		if (old_txq == (MV_U8) txq)
+			return 0;
+
+		if (mv_eth_ctrl_txq_cpu_own(port, pp->txp, old_txq, 0))
+			return -EINVAL;
+	}
+
+	if (txq == -1) {
+		pp->txq_tos_map[tos] = MV_ETH_TXQ_INVALID;
+		return 0;
+	}
+
+	if (mvNetaMaxCheck(txq, CONFIG_MV_ETH_TXQ))
+		return -EINVAL;
+
+	if (mv_eth_ctrl_txq_cpu_own(port, pp->txp, txq, 1))
+		return -EINVAL;
+
+	pp->txq_tos_map[tos] = (MV_U8) txq;
+
+	return 0;
+}
+
+static int mv_eth_priv_init(struct eth_port *pp, int port)
+{
+	int cpu, i;
+	u8	*ext_buf;
+
+	memset(pp, 0, sizeof(struct eth_port));
+
+	pp->port = port;
+	pp->txp_num = 1;
+	pp->txp = 0;
+	for_each_possible_cpu(cpu) {
+		if ((MV_BIT_CHECK(pp->cpuMask, cpu)))
+			pp->txq[cpu] = CONFIG_MV_ETH_TXQ_DEF;
+	}
+
+	pp->flags = 0;
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+	pp->pool_long_num = mv_eth_bm_config_long_buf_num_get(port);
+	if (pp->pool_long_num > MV_BM_POOL_CAP_MAX)
+		pp->pool_long_num = MV_BM_POOL_CAP_MAX;
+
+	pp->pool_short_num = mv_eth_bm_config_short_buf_num_get(port);
+	if (pp->pool_short_num > MV_BM_POOL_CAP_MAX)
+		pp->pool_short_num = MV_BM_POOL_CAP_MAX;
+#else
+	pp->pool_long_num = CONFIG_MV_ETH_RXQ * CONFIG_MV_ETH_RXQ_DESC * 2;
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	for (i = 0; i < 256; i++) {
+		pp->txq_tos_map[i] = MV_ETH_TXQ_INVALID;
+
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+		pp->tx_special_check = NULL;
+#endif /* CONFIG_MV_ETH_TX_SPECIAL */
+	}
+
+	mv_eth_port_config_parse(pp);
+
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(port)) {
+		set_bit(MV_ETH_F_MH_BIT, &(pp->flags));
+		pp->txp_num = MV_ETH_MAX_TCONT();
+		pp->txp = CONFIG_MV_PON_TXP_DEF;
+		for_each_possible_cpu(i)
+			pp->txq[i] = CONFIG_MV_PON_TXQ_DEF;
+	}
+#endif /* CONFIG_MV_PON */
+
+#if defined(CONFIG_MV_ETH_RX_CSUM_OFFLOAD_DEF)
+	pp->rx_csum_offload = 1;
+#endif /* CONFIG_MV_ETH_RX_CSUM_OFFLOAD_DEF */
+
+#ifdef CONFIG_MV_INCLUDE_SWITCH
+	if (mvBoardSwitchConnectedPortGet(port) != -1) {
+		set_bit(MV_ETH_F_SWITCH_BIT, &(pp->flags));
+		set_bit(MV_ETH_F_EXT_SWITCH_BIT, &(pp->flags));
+	}
+#endif /* CONFIG_MV_INCLUDE_SWITCH */
+
+	memset(&pp->tx_done_timer, 0, sizeof(struct timer_list));
+	pp->tx_done_timer.function = mv_eth_tx_done_timer_callback;
+	init_timer(&pp->tx_done_timer);
+	clear_bit(MV_ETH_F_TX_DONE_TIMER_BIT, &(pp->flags));
+	memset(&pp->cleanup_timer, 0, sizeof(struct timer_list));
+	pp->cleanup_timer.function = mv_eth_cleanup_timer_callback;
+	init_timer(&pp->cleanup_timer);
+	clear_bit(MV_ETH_F_CLEANUP_TIMER_BIT, &(pp->flags));
+
+	pp->weight = CONFIG_MV_ETH_RX_POLL_WEIGHT;
+	rwlock_init(&pp->rwlock);
+
+	/* Init pool of external buffers for TSO, fragmentation, etc */
+	spin_lock_init(&pp->extLock);
+	pp->extBufSize = CONFIG_MV_ETH_EXTRA_BUF_SIZE;
+	pp->extArrStack = mvStackCreate(CONFIG_MV_ETH_EXTRA_BUF_NUM);
+	if (pp->extArrStack == NULL) {
+		printk(KERN_ERR "Error: failed create  extArrStack for port #%d\n", port);
+		return -ENOMEM;
+	}
+	for (i = 0; i < CONFIG_MV_ETH_EXTRA_BUF_NUM; i++) {
+		ext_buf = mvOsMalloc(CONFIG_MV_ETH_EXTRA_BUF_SIZE);
+		if (ext_buf == NULL) {
+			printk(KERN_WARNING "%s Warning: %d of %d extra buffers allocated\n",
+				__func__, i, CONFIG_MV_ETH_EXTRA_BUF_NUM);
+			break;
+		}
+		mvStackPush(pp->extArrStack, (MV_U32)ext_buf);
+	}
+
+#ifdef CONFIG_MV_ETH_STAT_DIST
+	pp->dist_stats.rx_dist = mvOsMalloc(sizeof(u32) * (CONFIG_MV_ETH_RXQ * CONFIG_MV_ETH_RXQ_DESC + 1));
+	if (pp->dist_stats.rx_dist != NULL) {
+		pp->dist_stats.rx_dist_size = CONFIG_MV_ETH_RXQ * CONFIG_MV_ETH_RXQ_DESC + 1;
+		memset(pp->dist_stats.rx_dist, 0, sizeof(u32) * pp->dist_stats.rx_dist_size);
+	} else
+		printk(KERN_ERR "ethPort #%d: Can't allocate %d bytes for rx_dist\n",
+		       pp->port, sizeof(u32) * (CONFIG_MV_ETH_RXQ * CONFIG_MV_ETH_RXQ_DESC + 1));
+
+	pp->dist_stats.tx_done_dist =
+	    mvOsMalloc(sizeof(u32) * (pp->txp_num * CONFIG_MV_ETH_TXQ * CONFIG_MV_ETH_TXQ_DESC + 1));
+	if (pp->dist_stats.tx_done_dist != NULL) {
+		pp->dist_stats.tx_done_dist_size = pp->txp_num * CONFIG_MV_ETH_TXQ * CONFIG_MV_ETH_TXQ_DESC + 1;
+		memset(pp->dist_stats.tx_done_dist, 0, sizeof(u32) * pp->dist_stats.tx_done_dist_size);
+	} else
+		printk(KERN_ERR "ethPort #%d: Can't allocate %d bytes for tx_done_dist\n",
+		       pp->port, sizeof(u32) * (pp->txp_num * CONFIG_MV_ETH_TXQ * CONFIG_MV_ETH_TXQ_DESC + 1));
+#endif /* CONFIG_MV_ETH_STAT_DIST */
+
+	return 0;
+}
+
+/***********************************************************************************
+ ***  noqueue net device
+ ***********************************************************************************/
+extern struct Qdisc noop_qdisc;
+void mv_eth_set_noqueue(struct net_device *dev, int enable)
+{
+	struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+
+	if (dev->flags & IFF_UP) {
+		printk(KERN_ERR "%s: device or resource busy, take it down\n", dev->name);
+		return;
+	}
+	dev->tx_queue_len = enable ? 0 : CONFIG_MV_ETH_TXQ_DESC;
+
+	if (txq)
+		txq->qdisc_sleeping = &noop_qdisc;
+	else
+		printk(KERN_ERR "%s: txq #0 is NULL\n", dev->name);
+
+	printk(KERN_ERR "%s: device tx queue len is %d\n", dev->name, (int)dev->tx_queue_len);
+
+}
+
+/***********************************************************************************
+ ***  print RX bm_pool status
+ ***********************************************************************************/
+void mv_eth_pool_status_print(int pool)
+{
+	struct bm_pool *bm_pool = &mv_eth_pool[pool];
+
+	printk(KERN_ERR "\nRX Pool #%d: pkt_size=%d, BM-HW support - %s\n",
+	       pool, bm_pool->pkt_size, mv_eth_pool_bm(bm_pool) ? "Yes" : "No");
+
+	printk(KERN_ERR "bm_pool=%p, stack=%p, capacity=%d, buf_num=%d, port_map=0x%x missed=%d\n",
+	       bm_pool->bm_pool, bm_pool->stack, bm_pool->capacity, bm_pool->buf_num,
+		   bm_pool->port_map, bm_pool->missed);
+
+#ifdef CONFIG_MV_ETH_STAT_ERR
+	printk(KERN_ERR "Errors: skb_alloc_oom=%u, stack_empty=%u, stack_full=%u\n",
+	       bm_pool->stats.skb_alloc_oom, bm_pool->stats.stack_empty, bm_pool->stats.stack_full);
+#endif /* #ifdef CONFIG_MV_ETH_STAT_ERR */
+
+#ifdef CONFIG_MV_ETH_STAT_DBG
+	printk(KERN_ERR "skb_alloc_ok=%u, bm_put=%u, stack_put=%u, stack_get=%u\n",
+	       bm_pool->stats.skb_alloc_ok, bm_pool->stats.bm_put, bm_pool->stats.stack_put, bm_pool->stats.stack_get);
+
+	printk(KERN_ERR "skb_recycled_ok=%u, skb_recycled_err=%u\n",
+	       bm_pool->stats.skb_recycled_ok, bm_pool->stats.skb_recycled_err);
+#endif /* CONFIG_MV_ETH_STAT_DBG */
+
+	if (bm_pool->stack)
+		mvStackStatus(bm_pool->stack, 0);
+
+	memset(&bm_pool->stats, 0, sizeof(bm_pool->stats));
+}
+
+
+/***********************************************************************************
+ ***  print ext pool status
+ ***********************************************************************************/
+void mv_eth_ext_pool_print(struct eth_port *pp)
+{
+	printk(KERN_ERR "\nExt Pool Stack: bufSize = %u bytes\n", pp->extBufSize);
+	mvStackStatus(pp->extArrStack, 0);
+}
+
+/***********************************************************************************
+ ***  print net device status
+ ***********************************************************************************/
+void mv_eth_netdev_print(struct net_device *dev)
+{
+	struct eth_netdev *dev_priv = MV_DEV_PRIV(dev);
+
+	printk(KERN_ERR "%s net_device status: dev=%p, pp=%p\n\n", dev->name, dev, MV_ETH_PRIV(dev));
+	printk(KERN_ERR "ifIdx=%d, features=0x%x, flags=0x%x, mtu=%u, size=%d, MAC=" MV_MACQUAD_FMT "\n",
+	       dev->ifindex, (unsigned int)(dev->features), (unsigned int)(dev->flags),
+	       dev->mtu, RX_PKT_SIZE(dev->mtu), MV_MACQUAD(dev->dev_addr));
+
+	if (dev_priv)
+		printk(KERN_ERR "group=%d, tx_vlan_mh=0x%04x, switch_port_map=0x%x, switch_port_link_map=0x%x\n",
+		       dev_priv->group, dev_priv->tx_vlan_mh, dev_priv->port_map, dev_priv->link_map);
+}
+
+void mv_eth_status_print(void)
+{
+	printk(KERN_ERR "totals: ports=%d, devs=%d\n", mv_eth_ports_num, mv_net_devs_num);
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	printk(KERN_ERR "SKB recycle = %s\n", mv_ctrl_recycle ? "Enabled" : "Disabled");
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+#ifdef CONFIG_MV_ETH_PNC
+	printk(KERN_ERR "PnC control = %s\n", mv_eth_pnc_ctrl_en ? "Enabled" : "Disabled");
+#endif /* CONFIG_MV_ETH_PNC */
+}
+
+/***********************************************************************************
+ ***  print Ethernet port status
+ ***********************************************************************************/
+void mv_eth_port_status_print(unsigned int port)
+{
+	int txp, q;
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (!pp)
+		return;
+
+	printk(KERN_ERR "\n");
+	printk(KERN_ERR "port=%d, flags=0x%lx, rx_weight=%d\n", port, pp->flags, pp->weight);
+	if ((!(pp->flags & MV_ETH_F_SWITCH)) && (pp->flags & MV_ETH_F_CONNECT_LINUX))
+		printk(KERN_ERR "%s: ", pp->dev->name);
+	else
+		printk(KERN_ERR "port %d: ", port);
+
+	mv_eth_link_status_print(port);
+
+#ifdef CONFIG_MV_ETH_NFP
+	printk(KERN_ERR "NFP = ");
+	if (pp->flags & MV_ETH_F_NFP_EN)
+		printk(KERN_CONT "Enabled\n");
+	else
+		printk(KERN_CONT "Disabled\n");
+#endif /* CONFIG_MV_ETH_NFP */
+
+	printk(KERN_ERR "rxq_coal(pkts)[ q]   = ");
+	for (q = 0; q < CONFIG_MV_ETH_RXQ; q++)
+		printk(KERN_CONT "%3d ", mvNetaRxqPktsCoalGet(port, q));
+
+	printk(KERN_CONT "\n");
+	printk(KERN_ERR "rxq_coal(usec)[ q]   = ");
+	for (q = 0; q < CONFIG_MV_ETH_RXQ; q++)
+		printk(KERN_CONT "%3d ", mvNetaRxqTimeCoalGet(port, q));
+
+	printk(KERN_CONT "\n");
+	printk(KERN_ERR "rxq_desc(num)[ q]    = ");
+	for (q = 0; q < CONFIG_MV_ETH_RXQ; q++)
+		printk(KERN_CONT "%3d ", pp->rxq_ctrl[q].rxq_size);
+
+	printk(KERN_CONT "\n");
+	for (txp = 0; txp < pp->txp_num; txp++) {
+		printk(KERN_ERR "txq_coal(pkts)[%2d.q] = ", txp);
+		for (q = 0; q < CONFIG_MV_ETH_TXQ; q++)
+			printk(KERN_CONT "%3d ", mvNetaTxDonePktsCoalGet(port, txp, q));
+		printk(KERN_CONT "\n");
+
+		printk(KERN_ERR "txq_mod(F,C,H)[%2d.q] = ", txp);
+		for (q = 0; q < CONFIG_MV_ETH_TXQ; q++) {
+			int val, mode;
+
+			mode = mv_eth_ctrl_txq_mode_get(port, txp, q, &val);
+			if (mode == MV_ETH_TXQ_CPU)
+				printk(KERN_CONT " C%-d ", val);
+			else if (mode == MV_ETH_TXQ_HWF)
+				printk(KERN_CONT " H%-d ", val);
+			else
+				printk(KERN_CONT "  F ");
+		}
+		printk(KERN_CONT "\n");
+
+		printk(KERN_ERR "txq_desc(num) [%2d.q] = ", txp);
+		for (q = 0; q < CONFIG_MV_ETH_TXQ; q++) {
+			struct tx_queue *txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + q];
+			printk(KERN_CONT "%3d ", txq_ctrl->txq_size);
+		}
+		printk(KERN_CONT "\n");
+	}
+	printk(KERN_ERR "\n");
+
+#ifdef CONFIG_MV_ETH_TXDONE_ISR
+	printk(KERN_ERR "Do tx_done in NAPI context triggered by ISR\n");
+	for (txp = 0; txp < pp->txp_num; txp++) {
+		printk(KERN_ERR "txcoal(pkts)[%2d.q] = ", txp);
+		for (q = 0; q < CONFIG_MV_ETH_TXQ; q++)
+			printk(KERN_CONT "%3d ", mvNetaTxDonePktsCoalGet(port, txp, q));
+		printk(KERN_CONT "\n");
+	}
+	printk(KERN_ERR "\n");
+#else
+	printk(KERN_ERR "Do tx_done in TX or Timer context: tx_done_threshold=%d\n", mv_ctrl_txdone);
+#endif /* CONFIG_MV_ETH_TXDONE_ISR */
+
+	printk(KERN_ERR "txp=%d, zero_pad=%s, mh_en=%s (0x%04x), tx_cmd=0x%08x\n",
+	       pp->txp, (pp->flags & MV_ETH_F_NO_PAD) ? "Disabled" : "Enabled",
+	       (pp->flags & MV_ETH_F_MH) ? "Enabled" : "Disabled", pp->tx_mh, pp->hw_cmd);
+
+	printk(KERN_CONT "\n");
+	printk(KERN_CONT "CPU:   txq_def   causeRxTx    napi\n");
+	{
+		int cpu;
+		for_each_possible_cpu(cpu) {
+			if (MV_BIT_CHECK(pp->cpuMask, cpu))
+				printk(KERN_ERR "  %d:      %d      0x%08x     %d\n",
+					cpu, pp->txq[cpu], pp->causeRxTx[cpu], test_bit(NAPI_STATE_SCHED, &pp->napi[cpu]->state));
+		}
+	}
+	printk(KERN_CONT "\n");
+
+#ifdef CONFIG_MV_ETH_SWITCH
+	if (pp->flags & MV_ETH_F_SWITCH)
+		mv_eth_switch_status_print(port);
+#endif /* CONFIG_MV_ETH_SWITCH */
+}
+
+/***********************************************************************************
+ ***  print port statistics
+ ***********************************************************************************/
+
+void mv_eth_port_stats_print(unsigned int port)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+	struct port_stats *stat = NULL;
+	struct tx_queue *txq_ctrl;
+	int txp, queue;
+	u32 total_rx_ok, total_rx_fill_ok;
+#ifdef CONFIG_MV_ETH_STAT_INF
+	int i;
+#endif
+
+
+	if (pp == NULL) {
+		printk(KERN_ERR "eth_stats_print: wrong port number %d\n", port);
+		return;
+	}
+	stat = &(pp->stats);
+
+#ifdef CONFIG_MV_ETH_STAT_ERR
+	printk(KERN_ERR "\n====================================================\n");
+	printk(KERN_ERR "ethPort_%d: Errors", port);
+	printk(KERN_CONT "\n-------------------------------\n");
+	printk(KERN_ERR "rx_error......................%10u\n", stat->rx_error);
+	printk(KERN_ERR "tx_timeout....................%10u\n", stat->tx_timeout);
+	printk(KERN_ERR "tx_netif_stop.................%10u\n", stat->netif_stop);
+	printk(KERN_ERR "netif_wake....................%10u\n", stat->netif_wake);
+	printk(KERN_ERR "ext_stack_empty...............%10u\n", stat->ext_stack_empty);
+	printk(KERN_ERR "ext_stack_full ...............%10u\n", stat->ext_stack_full);
+#endif /* CONFIG_MV_ETH_STAT_ERR */
+
+#ifdef CONFIG_MV_ETH_STAT_INF
+	printk(KERN_ERR "\n====================================================\n");
+	printk(KERN_ERR "ethPort_%d: interrupt statistics", port);
+	printk(KERN_CONT "\n-------------------------------\n");
+	printk(KERN_ERR "irq...........................%10u\n", stat->irq);
+	printk(KERN_ERR "irq_err.......................%10u\n", stat->irq_err);
+
+	printk(KERN_ERR "\n====================================================\n");
+	printk(KERN_ERR "ethPort_%d: Events", port);
+	printk(KERN_CONT "\n-------------------------------\n");
+	for (i = 0; i < CONFIG_NR_CPUS; i++) {
+		printk(KERN_ERR "poll[%d].....................%10u\n", i, stat->poll[i]);
+		printk(KERN_ERR "poll_exit[%d]................%10u\n", i, stat->poll_exit[i]);
+	}
+	printk(KERN_ERR "tx_fragmentation..............%10u\n", stat->tx_fragment);
+	printk(KERN_ERR "tx_done_event.................%10u\n", stat->tx_done);
+	printk(KERN_ERR "tx_done_timer_event...........%10u\n", stat->tx_done_timer);
+	printk(KERN_ERR "cleanup_timer_event...........%10u\n", stat->cleanup_timer);
+	printk(KERN_ERR "link..........................%10u\n", stat->link);
+#ifdef CONFIG_MV_ETH_RX_SPECIAL
+	printk(KERN_ERR "rx_special....................%10u\n", stat->rx_special);
+#endif /* CONFIG_MV_ETH_RX_SPECIAL */
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+	printk(KERN_ERR "tx_special....................%10u\n", stat->tx_special);
+#endif /* CONFIG_MV_ETH_TX_SPECIAL */
+#endif /* CONFIG_MV_ETH_STAT_INF */
+
+	printk(KERN_ERR "\n");
+	total_rx_ok = total_rx_fill_ok = 0;
+	printk(KERN_ERR "RXQ:       rx_ok      rx_fill_ok     missed\n\n");
+	for (queue = 0; queue < CONFIG_MV_ETH_RXQ; queue++) {
+		u32 rxq_ok = 0, rxq_fill = 0;
+
+#ifdef CONFIG_MV_ETH_STAT_DBG
+		rxq_ok = stat->rxq[queue];
+		rxq_fill = stat->rxq_fill[queue];
+#endif /* CONFIG_MV_ETH_STAT_DBG */
+
+		printk(KERN_ERR "%3d:  %10u    %10u          %d\n",
+			queue, rxq_ok, rxq_fill,
+			pp->rxq_ctrl[queue].missed);
+		total_rx_ok += rxq_ok;
+		total_rx_fill_ok += rxq_fill;
+	}
+	printk(KERN_ERR "SUM:  %10u    %10u\n", total_rx_ok, total_rx_fill_ok);
+
+#ifdef CONFIG_MV_ETH_STAT_DBG
+	{
+		printk(KERN_ERR "\n====================================================\n");
+		printk(KERN_ERR "ethPort_%d: Debug statistics", port);
+		printk(KERN_CONT "\n-------------------------------\n");
+
+		printk(KERN_ERR "\n");
+
+		printk(KERN_ERR "rx_nfp....................%10u\n", stat->rx_nfp);
+		printk(KERN_ERR "rx_nfp_drop...............%10u\n", stat->rx_nfp_drop);
+
+		printk(KERN_ERR "rx_gro....................%10u\n", stat->rx_gro);
+		printk(KERN_ERR "rx_gro_bytes .............%10u\n", stat->rx_gro_bytes);
+
+		printk(KERN_ERR "tx_tso....................%10u\n", stat->tx_tso);
+		printk(KERN_ERR "tx_tso_bytes .............%10u\n", stat->tx_tso_bytes);
+
+		printk(KERN_ERR "rx_netif..................%10u\n", stat->rx_netif);
+		printk(KERN_ERR "rx_drop_sw................%10u\n", stat->rx_drop_sw);
+		printk(KERN_ERR "rx_csum_hw................%10u\n", stat->rx_csum_hw);
+		printk(KERN_ERR "rx_csum_sw................%10u\n", stat->rx_csum_sw);
+
+
+		printk(KERN_ERR "tx_skb_free...............%10u\n", stat->tx_skb_free);
+		printk(KERN_ERR "tx_sg.....................%10u\n", stat->tx_sg);
+		printk(KERN_ERR "tx_csum_hw................%10u\n", stat->tx_csum_hw);
+		printk(KERN_ERR "tx_csum_sw................%10u\n", stat->tx_csum_sw);
+
+		printk(KERN_ERR "ext_stack_get.............%10u\n", stat->ext_stack_get);
+		printk(KERN_ERR "ext_stack_put ............%10u\n", stat->ext_stack_put);
+
+		printk(KERN_ERR "\n");
+	}
+#endif /* CONFIG_MV_ETH_STAT_DBG */
+
+	printk(KERN_ERR "\n");
+	printk(KERN_ERR "TXP-TXQ:  count        send          done      no_resource\n\n");
+
+	for (txp = 0; txp < pp->txp_num; txp++) {
+		for (queue = 0; queue < CONFIG_MV_ETH_TXQ; queue++) {
+			u32 txq_tx = 0, txq_txdone = 0, txq_err = 0;
+
+			txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + queue];
+#ifdef CONFIG_MV_ETH_STAT_DBG
+			txq_tx = txq_ctrl->stats.txq_tx;
+			txq_txdone =  txq_ctrl->stats.txq_txdone;
+#endif /* CONFIG_MV_ETH_STAT_DBG */
+#ifdef CONFIG_MV_ETH_STAT_ERR
+			txq_err = txq_ctrl->stats.txq_err;
+#endif /* CONFIG_MV_ETH_STAT_ERR */
+
+			printk(KERN_ERR "%d-%d:      %3d    %10u    %10u    %10u\n",
+			       txp, queue, txq_ctrl->txq_count, txq_tx,
+			       txq_txdone, txq_err);
+
+			memset(&txq_ctrl->stats, 0, sizeof(txq_ctrl->stats));
+		}
+	}
+	printk(KERN_ERR "\n\n");
+
+	memset(stat, 0, sizeof(struct port_stats));
+
+	/* RX pool statistics */
+#ifdef CONFIG_MV_ETH_BM_CPU
+	if (pp->pool_short)
+		mv_eth_pool_status_print(pp->pool_short->pool);
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	if (pp->pool_long)
+		mv_eth_pool_status_print(pp->pool_long->pool);
+
+		mv_eth_ext_pool_print(pp);
+
+#ifdef CONFIG_MV_ETH_STAT_DIST
+	{
+		int i;
+		struct dist_stats *dist_stats = &(pp->dist_stats);
+
+		if (dist_stats->rx_dist) {
+			printk(KERN_ERR "\n      Linux Path RX distribution\n");
+			for (i = 0; i < dist_stats->rx_dist_size; i++) {
+				if (dist_stats->rx_dist[i] != 0) {
+					printk(KERN_ERR "%3d RxPkts - %u times\n", i, dist_stats->rx_dist[i]);
+					dist_stats->rx_dist[i] = 0;
+				}
+			}
+		}
+
+		if (dist_stats->tx_done_dist) {
+			printk(KERN_ERR "\n      tx-done distribution\n");
+			for (i = 0; i < dist_stats->tx_done_dist_size; i++) {
+				if (dist_stats->tx_done_dist[i] != 0) {
+					printk(KERN_ERR "%3d TxDoneDesc - %u times\n", i, dist_stats->tx_done_dist[i]);
+					dist_stats->tx_done_dist[i] = 0;
+				}
+			}
+		}
+#ifdef CONFIG_MV_ETH_TSO
+		if (dist_stats->tx_tso_dist) {
+			printk(KERN_ERR "\n      TSO stats\n");
+			for (i = 0; i < dist_stats->tx_tso_dist_size; i++) {
+				if (dist_stats->tx_tso_dist[i] != 0) {
+					printk(KERN_ERR "%3d KBytes - %u times\n", i, dist_stats->tx_tso_dist[i]);
+					dist_stats->tx_tso_dist[i] = 0;
+				}
+			}
+		}
+#endif /* CONFIG_MV_ETH_TSO */
+	}
+#endif /* CONFIG_MV_ETH_STAT_DIST */
+}
+
+
+static int mv_eth_port_cleanup(int port)
+{
+	int txp, txq, rxq, i;
+	struct eth_port *pp;
+	struct tx_queue *txq_ctrl;
+	struct rx_queue *rxq_ctrl;
+
+	pp = mv_eth_port_by_id(port);
+
+	if (pp == NULL)
+		return -1;
+
+	if (pp->flags & MV_ETH_F_STARTED) {
+		printk(KERN_ERR "%s: port %d is started, cannot cleanup\n", __func__, port);
+		return -1;
+	}
+
+	/* Reset Tx ports */
+	for (txp = 0; txp < pp->txp_num; txp++) {
+		if (mv_eth_txp_reset(port, txp))
+			printk(KERN_ERR "Warning: Port %d Tx port %d reset failed\n", port, txp);
+	}
+
+	/* Delete Tx queues */
+	for (txp = 0; txp < pp->txp_num; txp++) {
+		for (txq = 0; txq < CONFIG_MV_ETH_TXQ; txq++) {
+			txq_ctrl = &pp->txq_ctrl[txp * CONFIG_MV_ETH_TXQ + txq];
+			mv_eth_txq_delete(pp, txq_ctrl);
+		}
+	}
+
+	mvOsFree(pp->txq_ctrl);
+	pp->txq_ctrl = NULL;
+
+#ifdef CONFIG_MV_ETH_STAT_DIST
+	/* Free Tx Done distribution statistics */
+	mvOsFree(pp->dist_stats.tx_done_dist);
+#endif
+
+	/* Reset RX ports */
+	if (mv_eth_rx_reset(port))
+		printk(KERN_ERR "Warning: Rx port %d reset failed\n", port);
+
+	/* Delete Rx queues */
+	for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+		rxq_ctrl = &pp->rxq_ctrl[rxq];
+		mvNetaRxqDelete(pp->port, rxq);
+		rxq_ctrl->q = NULL;
+	}
+
+	mvOsFree(pp->rxq_ctrl);
+	pp->rxq_ctrl = NULL;
+
+#ifdef CONFIG_MV_ETH_STAT_DIST
+	/* Free Rx distribution statistics */
+	mvOsFree(pp->dist_stats.rx_dist);
+#endif
+
+	/* Free buffer pools */
+	if (pp->pool_long) {
+		mv_eth_pool_free(pp->pool_long->pool, pp->pool_long_num);
+		pp->pool_long->port_map &= ~(1 << pp->port);
+		pp->pool_long = NULL;
+	}
+#ifdef CONFIG_MV_ETH_BM_CPU
+	if (pp->pool_short) {
+		mv_eth_pool_free(pp->pool_short->pool, pp->pool_short_num);
+		pp->pool_short->port_map &= ~(1 << pp->port);
+		pp->pool_short = NULL;
+	}
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+	/* Clear Marvell Header related modes - will be set again if needed on re-init */
+	mvNetaMhSet(port, MV_NETA_MH_NONE);
+
+	/* Clear any forced link, speed and duplex */
+	mv_force_port_link_speed_fc(port, MV_ETH_SPEED_AN, 0);
+
+	mvNetaPortDestroy(port);
+
+	if (pp->flags & MV_ETH_F_CONNECT_LINUX)
+		for (i = 0; i < CONFIG_MV_ETH_NAPI_GROUPS; i++)
+			netif_napi_del(pp->napiGroup[i]);
+
+	return 0;
+}
+
+
+int mv_eth_all_ports_cleanup(void)
+{
+	int port, pool, status = 0;
+
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		status = mv_eth_port_cleanup(port);
+		if (status != 0) {
+			printk(KERN_ERR "Error: mv_eth_port_cleanup failed on port %d, stopping all ports cleanup\n", port);
+			return status;
+		}
+	}
+
+	for (pool = 0; pool < MV_ETH_BM_POOLS; pool++)
+		mv_eth_pool_destroy(pool);
+
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		if (mv_eth_ports[port])
+			mvOsFree(mv_eth_ports[port]);
+	}
+
+	memset(mv_eth_ports, 0, (mv_eth_ports_num * sizeof(struct eth_port *)));
+	/* Note: not freeing mv_eth_ports - we will reuse them */
+
+	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_PNC_WOL
+
+#define DEF_WOL_SIZE	42
+MV_U8	wol_data[DEF_WOL_SIZE] = { 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				   0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x08, 0x00,
+				   0x45, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00,
+				   0x00, 0x11, 0x00, 0x00, 0xc0, 0xa8, 0x01, 0xFA,
+				   0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x89,
+				   0x00, 0x3A };
+
+MV_U8	wol_mask[DEF_WOL_SIZE] = { 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				   0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+				   0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+				   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+				   0xff, 0xff };
+
+int mv_eth_wol_pkts_check(int port)
+{
+	struct eth_port		*pp = mv_eth_port_by_id(port);
+	struct neta_rx_desc *rx_desc;
+	struct eth_pbuf     *pkt;
+	struct bm_pool      *pool;
+	int	                rxq, rx_done, i, wakeup, ruleId;
+	MV_NETA_RXQ_CTRL    *rx_ctrl;
+
+	write_lock(&pp->rwlock);
+	wakeup = 0;
+	for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+		rx_ctrl = pp->rxq_ctrl[rxq].q;
+
+		if (rx_ctrl == NULL)
+			continue;
+
+		rx_done = mvNetaRxqBusyDescNumGet(pp->port, rxq);
+
+		for (i = 0; i < rx_done; i++) {
+			rx_desc = mvNetaRxqNextDescGet(rx_ctrl);
+			mvOsCacheLineInv(NULL, rx_desc);
+
+#if defined(MV_CPU_BE)
+			mvNetaRxqDescSwap(rx_desc);
+#endif /* MV_CPU_BE */
+
+			pkt = (struct eth_pbuf *)rx_desc->bufCookie;
+			mvOsCacheInvalidate(NULL, pkt->pBuf + pkt->offset, rx_desc->dataSize);
+
+			if (mv_pnc_wol_pkt_match(pp->port, pkt->pBuf + pkt->offset, rx_desc->dataSize, &ruleId))
+				wakeup = 1;
+
+			pool = &mv_eth_pool[pkt->pool];
+			mv_eth_rxq_refill(pp, rxq, pkt, pool, rx_desc);
+
+			if (wakeup) {
+				printk(KERN_INFO "packet match WoL rule=%d found on port=%d, rxq=%d\n",
+						ruleId, port, rxq);
+				i++;
+				break;
+			}
+		}
+		if (i) {
+			mvNetaRxqDescNumUpdate(pp->port, rxq, i, i);
+			printk(KERN_INFO "port=%d, rxq=%d: %d of %d packets dropped\n", port, rxq, i, rx_done);
+		}
+		if (wakeup) {
+			/* Failed enter WoL mode */
+			write_unlock(&pp->rwlock);
+			return 1;
+		}
+	}
+	write_unlock(&pp->rwlock);
+	return 0;
+}
+
+void mv_eth_wol_wakeup(int port)
+{
+	int rxq;
+
+	/* Restore RXQ coalescing */
+	for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+		mvNetaRxqPktsCoalSet(port, rxq, CONFIG_MV_ETH_RX_COAL_PKTS);
+		mvNetaRxqTimeCoalSet(port, rxq, CONFIG_MV_ETH_RX_COAL_USEC);
+	}
+
+	/* Set PnC to Active filtering mode */
+	mv_pnc_wol_wakeup(port);
+	printk(KERN_INFO "Exit wakeOnLan mode on port #%d\n", port);
+
+}
+
+int mv_eth_wol_sleep(int port)
+{
+	int rxq;
+
+	/* Set PnC to WoL filtering mode */
+	mv_pnc_wol_sleep(port);
+
+	/* Check received packets in all RXQs */
+	/* If match one of WoL pattern - wakeup, not match - drop */
+	if (mv_eth_wol_pkts_check(port)) {
+		/* Set PNC to Active filtering mode */
+		mv_pnc_wol_wakeup(port);
+		printk(KERN_INFO "Failed to enter wakeOnLan mode on port #%d\n", port);
+		return 1;
+	}
+	printk(KERN_INFO "Enter wakeOnLan mode on port #%d\n", port);
+
+	/* Set RXQ coalescing to minimum */
+	for (rxq = 0; rxq < CONFIG_MV_ETH_RXQ; rxq++) {
+		mvNetaRxqPktsCoalSet(port, rxq, 0);
+		mvNetaRxqTimeCoalSet(port, rxq, 0);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_MV_ETH_PNC_WOL */
+
+
+#ifdef CONFIG_MV_PON
+/* PON link status api */
+PONLINKSTATUSPOLLFUNC pon_link_status_polling_func = NULL;
+
+void pon_link_status_notify_func(MV_BOOL link_state)
+{
+	struct eth_port *pon_port = mv_eth_port_by_id(MV_PON_PORT_ID_GET());
+
+	if ((pon_port->flags & MV_ETH_F_STARTED) == 0) {
+		/* Ignore link event if port is down - link status will be updated on start */
+#ifdef CONFIG_MV_ETH_DEBUG_CODE
+		printk(KERN_ERR "PON port: Link event (%s) when port is down\n",
+			link_state ? "Up" : "Down");
+#endif /* CONFIG_MV_ETH_DEBUG_CODE */
+		return;
+	}
+	mv_eth_link_event(pon_port, 1);
+}
+
+/* called by PON module */
+void mv_pon_link_state_register(PONLINKSTATUSPOLLFUNC poll_func, PONLINKSTATUSNOTIFYFUNC *notify_func)
+{
+	pon_link_status_polling_func = poll_func;
+	*notify_func = pon_link_status_notify_func;
+}
+
+MV_BOOL mv_pon_link_status(void)
+{
+	if (pon_link_status_polling_func != NULL)
+		return pon_link_status_polling_func();
+	printk(KERN_ERR "pon_link_status_polling_func is uninitialized\n");
+	return MV_FALSE;
+}
+#endif /* CONFIG_MV_PON */
+
+/* Support for platform driver */
+
+#ifdef CONFIG_CPU_IDLE
+int mv_eth_suspend(struct platform_device *pdev, pm_message_t state)
+{
+#ifdef CONFIG_MV_ETH_PNC_WOL
+	int port;
+
+	printk(KERN_INFO "Entering WoL mode on All Neta interfaces\n");
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		/* Configure ETH port to be in WoL mode */
+		if (mv_eth_wol_sleep(port))
+			return 1;
+	}
+#endif /* CONFIG_MV_ETH_PNC_WOL */
+
+	return 0;
+}
+
+int mv_eth_resume(struct platform_device *pdev)
+{
+#ifdef CONFIG_MV_ETH_PNC_WOL
+	int port;
+
+	printk(KERN_INFO "Exiting WoL mode on All Neta interfaces\n");
+	for (port = 0; port < mv_eth_ports_num; port++) {
+		/* Configure ETH port to work in normal mode */
+		mv_eth_wol_wakeup(port);
+	}
+#endif /* CONFIG_MV_ETH_PNC_WOL */
+	return 0;
+}
+#endif /* CONFIG_CPU_IDLE */
+
+static int mv_eth_remove(struct platform_device *pdev)
+{
+    printk(KERN_INFO "Removing Marvell Ethernet Driver\n");
+    return 0;
+}
+
+static void mv_eth_shutdown(struct platform_device *pdev)
+{
+    printk(KERN_INFO "Shutting Down Marvell Ethernet Driver\n");
+}
+
+int mv_eth_ctrl_port_started_get(int port)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+	if (!pp) {
+		return MV_FALSE;
+	}
+
+	if (pp->flags & MV_ETH_F_STARTED)
+        return MV_TRUE;
+    else
+        return MV_FALSE;
+}
+
+int mv_eth_dev_name_by_portid (unsigned int port, char * dev_name)
+{
+	struct eth_port *pp = mv_eth_port_by_id(port);
+
+    if (pp) {
+        if (pp->dev) {
+            if (pp->dev->name) {
+                strcpy(dev_name, pp->dev->name);
+                return 1;
+            }
+        }
+    }
+    else {
+        printk("\n%s: Wrong port number port=%d\n", __func__, port);
+    }
+
+
+    *dev_name = '\0';
+    return 0;
+}
+
+
+void mv_eth_port_ifname_print(unsigned int port)
+{
+    char if_name[IFNAMSIZ] = {0};
+
+    mv_eth_dev_name_by_portid(port, if_name);
+	printk("%s\n", if_name);
+
+    return;
+}
+
+
+int mv_eth_pon_ifname_dump(char *buf)
+{
+	unsigned int off = 0;
+
+    mv_eth_dev_name_by_portid(MV_PON_PORT_ID, buf);
+
+	off += mvOsSPrintf(buf + off, "%s\n", buf);
+
+	return off;
+}
+
+
+
+/*******************************************************************************
+* mv_eth_set_mtu -victor added for TPM API.
+*
+* DESCRIPTION:
+*       Change MTU of the port. This configuration will take place
+*       imidiately.
+*
+* INPUT:
+*
+* RETURN:
+*******************************************************************************/
+int mv_eth_set_mtu(int portNo, int mtu)
+{
+#ifdef CONFIG_MV_ETH_SWITCH
+    if(mv_eth_ports[portNo]->flags  & MV_ETH_F_SWITCH)
+    {
+        return mv_eth_switch_change_mtu(mv_net_devs[portNo], mtu);
+	}
+	else
+#endif		
+	{
+        return mv_eth_change_mtu(mv_net_devs[portNo], mtu);
+	}
+
+	return MV_OK;
+}
+/*******************************************************************************
+* mv_eth_get_mtu -victor added for TPM API.
+*
+* DESCRIPTION:
+*       Change MTU of the port. This configuration will take place
+*       imidiately.
+*
+* INPUT:
+*
+* RETURN:
+*******************************************************************************/
+int mv_eth_get_mtu(int portNo, int* mtu)
+{
+
+    *mtu = mv_net_devs[portNo]->mtu;
+
+	return MV_OK;
+}
+
+
+static struct platform_driver mv_eth_driver = {
+	.probe = mv_eth_probe,
+	.remove = mv_eth_remove,
+	.shutdown = mv_eth_shutdown,
+#ifdef CONFIG_CPU_IDLE
+	.suspend = mv_eth_suspend,
+	.resume = mv_eth_resume,
+#endif /* CONFIG_CPU_IDLE */
+	.driver = {
+		.name = "mv88fx_neta",
+	},
+};
+
+static int __init mv_eth_init_module(void)
+{
+	return platform_driver_register(&mv_eth_driver);
+}
+module_init(mv_eth_init_module);
+
+static void __exit mv_eth_cleanup_module(void)
+{
+	platform_driver_unregister(&mv_eth_driver);
+}
+module_exit(mv_eth_cleanup_module);
+
+
+MODULE_DESCRIPTION("Marvell Ethernet Driver - www.marvell.com");
+MODULE_AUTHOR("Dmitri Epshtein <dima@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.h
new file mode 100755
index 0000000..57c0b00
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_netdev.h
@@ -0,0 +1,764 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#ifndef __mv_netdev_h__
+#define __mv_netdev_h__
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mv802_3.h"
+#include "mvStack.h"
+
+#include "gbe/mvNeta.h"
+#include "bm/mvBmRegs.h"
+#include "bm/mvBm.h"
+
+
+/******************************************************
+ * driver statistics control --                       *
+ ******************************************************/
+#ifdef CONFIG_MV_ETH_STAT_ERR
+#define STAT_ERR(c) c
+#else
+#define STAT_ERR(c)
+#endif
+
+#ifdef CONFIG_MV_ETH_STAT_INF
+#define STAT_INFO(c) c
+#else
+#define STAT_INFO(c)
+#endif
+
+#ifdef CONFIG_MV_ETH_STAT_DBG
+#define STAT_DBG(c) c
+#else
+#define STAT_DBG(c)
+#endif
+
+#ifdef CONFIG_MV_ETH_STAT_DIST
+#define STAT_DIST(c) c
+#else
+#define STAT_DIST(c)
+#endif
+
+#ifdef CONFIG_MV_ETH_PNC
+extern unsigned int mv_eth_pnc_ctrl_en;
+int mv_eth_ctrl_pnc(int en);
+int mv_eth_ctrl_pnc_get(void);
+#endif /* CONFIG_MV_ETH_PNC */
+
+extern int mv_ctrl_txdone;
+
+/****************************************************************************
+ * Rx buffer size: MTU + 2(Marvell Header) + 4(VLAN) + 14(MAC hdr) + 4(CRC) *
+ ****************************************************************************/
+#define RX_PKT_SIZE(mtu) \
+		MV_ALIGN_UP((mtu) + 2 + 4 + ETH_HLEN + 4, CPU_D_CACHE_LINE_SIZE)
+
+#define RX_BUF_SIZE(pkt_size)   ((pkt_size) + NET_SKB_PAD)
+
+/******************************************************
+ * interrupt control --                               *
+ ******************************************************/
+#ifdef CONFIG_MV_ETH_TXDONE_ISR
+#define MV_ETH_TXDONE_INTR_MASK       (((1 << CONFIG_MV_ETH_TXQ) - 1) << NETA_CAUSE_TXQ_SENT_DESC_OFFS)
+#else
+#define MV_ETH_TXDONE_INTR_MASK       0
+#endif
+
+#define MV_ETH_MISC_SUM_INTR_MASK     (NETA_CAUSE_TX_ERR_SUM_MASK | NETA_CAUSE_MISC_SUM_MASK)
+#define MV_ETH_RX_INTR_MASK           (((1 << CONFIG_MV_ETH_RXQ) - 1) << NETA_CAUSE_RXQ_OCCUP_DESC_OFFS)
+#define NETA_RX_FL_DESC_MASK          (NETA_RX_F_DESC_MASK|NETA_RX_L_DESC_MASK)
+
+/* NAPI CPU defualt group */
+#define CPU_GROUP_DEF 0
+
+#define MV_ETH_TRYLOCK(lock, flags)                           \
+	(in_interrupt() ? spin_trylock((lock)) :              \
+		spin_trylock_irqsave((lock), (flags)))
+
+#define MV_ETH_LOCK(lock, flags)                              \
+	if (in_interrupt())                                   \
+		spin_lock((lock));                            \
+	else                                                  \
+		spin_lock_irqsave((lock), (flags));
+
+#define MV_ETH_UNLOCK(lock, flags)                            \
+	if (in_interrupt())                                   \
+		spin_unlock((lock));                          \
+	else                                                  \
+		spin_unlock_irqrestore((lock), (flags));
+
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+extern int mv_ctrl_recycle;
+#define mv_eth_is_recycle()     (mv_ctrl_recycle)
+int mv_eth_skb_recycle(struct sk_buff *skb);
+#else
+#define mv_eth_is_recycle()     0
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+/******************************************************
+ * rx / tx queues --                                  *
+ ******************************************************/
+/*
+ * Debug statistics
+ */
+struct txq_stats {
+#ifdef CONFIG_MV_ETH_STAT_ERR
+	u32 txq_err;
+#endif /* CONFIG_MV_ETH_STAT_ERR */
+#ifdef CONFIG_MV_ETH_STAT_DBG
+	u32 txq_tx;
+	u32 txq_txdone;
+#endif /* CONFIG_MV_ETH_STAT_DBG */
+};
+
+struct port_stats {
+
+#ifdef CONFIG_MV_ETH_STAT_ERR
+	u32 rx_error;
+	u32 tx_timeout;
+	u32 netif_stop;
+	u32 ext_stack_empty;
+	u32 ext_stack_full;
+	u32 netif_wake;
+#endif /* CONFIG_MV_ETH_STAT_ERR */
+
+#ifdef CONFIG_MV_ETH_STAT_INF
+	u32 irq;
+	u32 irq_err;
+	u32 poll[CONFIG_NR_CPUS];
+	u32 poll_exit[CONFIG_NR_CPUS];
+	u32 tx_fragment;
+	u32 tx_done;
+	u32 tx_done_timer;
+	u32 cleanup_timer;
+	u32 link;
+
+#ifdef CONFIG_MV_ETH_RX_SPECIAL
+	u32 rx_special;
+#endif /* CONFIG_MV_ETH_RX_SPECIAL */
+
+
+#ifdef CONFIG_MV_MAC_LEARN
+	u32 rx_mac_learn;
+#endif /* CONFIG_MV_MAC_LEARN */
+
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+	u32	tx_special;
+#endif /* CONFIG_MV_ETH_TX_SPECIAL */
+
+#endif /* CONFIG_MV_ETH_STAT_INF */
+
+#ifdef CONFIG_MV_ETH_STAT_DBG
+	u32 rxq[CONFIG_MV_ETH_RXQ];
+	u32 rxq_fill[CONFIG_MV_ETH_RXQ];
+	u32 rx_netif;
+	u32 rx_nfp;
+	u32 rx_nfp_drop;
+	u32 rx_gro;
+	u32 rx_gro_bytes;
+	u32 rx_drop_sw;
+	u32 rx_csum_hw;
+	u32 rx_csum_sw;
+	u32 tx_csum_hw;
+	u32 tx_csum_sw;
+	u32 tx_skb_free;
+	u32 tx_sg;
+	u32 tx_tso;
+	u32 tx_tso_bytes;
+	u32 ext_stack_put;
+	u32 ext_stack_get;
+#endif /* CONFIG_MV_ETH_STAT_DBG */
+};
+
+/* Used for define type of data saved in shadow: SKB or eth_pbuf or nothing */
+#define MV_ETH_SHADOW_SKB		0x1
+#define MV_ETH_SHADOW_EXT		0x2
+
+/* Masks used for pp->flags */
+#define MV_ETH_F_STARTED_BIT        0
+#define MV_ETH_F_TX_DONE_TIMER_BIT  1
+#define MV_ETH_F_SWITCH_BIT         2	/* port is connected to the Switch using the Gateway driver */
+#define MV_ETH_F_MH_BIT             3
+#define MV_ETH_F_NO_PAD_BIT         4
+#define MV_ETH_F_DBG_RX_BIT         5
+#define MV_ETH_F_DBG_TX_BIT         6
+#define MV_ETH_F_EXT_SWITCH_BIT	    7	/* port is connected to the Switch without the Gateway driver */
+#define MV_ETH_F_CONNECT_LINUX_BIT  8	/* port is connected to Linux netdevice */
+#define MV_ETH_F_LINK_UP_BIT        9
+#define MV_ETH_F_DBG_DUMP_BIT       10
+#define MV_ETH_F_DBG_ISR_BIT        11
+#define MV_ETH_F_DBG_POLL_BIT       12
+#define MV_ETH_F_CLEANUP_TIMER_BIT  13
+#define MV_ETH_F_NFP_EN_BIT         14
+
+#define MV_ETH_F_STARTED           (1 << MV_ETH_F_STARTED_BIT)		/* 0x01 */
+#define MV_ETH_F_TX_DONE_TIMER     (1 << MV_ETH_F_TX_DONE_TIMER_BIT)	/* 0x02 */
+#define MV_ETH_F_SWITCH            (1 << MV_ETH_F_SWITCH_BIT)		/* 0x04 */
+#define MV_ETH_F_MH                (1 << MV_ETH_F_MH_BIT)			/* 0x08 */
+#define MV_ETH_F_NO_PAD            (1 << MV_ETH_F_NO_PAD_BIT)		/* 0x10 */
+#define MV_ETH_F_DBG_RX            (1 << MV_ETH_F_DBG_RX_BIT)		/* 0x20 */
+#define MV_ETH_F_DBG_TX            (1 << MV_ETH_F_DBG_TX_BIT)		/* 0x40 */
+#define MV_ETH_F_EXT_SWITCH        (1 << MV_ETH_F_EXT_SWITCH_BIT)		/* 0x80 */
+#define MV_ETH_F_CONNECT_LINUX     (1 << MV_ETH_F_CONNECT_LINUX_BIT)	/* 0x100 */
+#define MV_ETH_F_LINK_UP           (1 << MV_ETH_F_LINK_UP_BIT)		/* 0x200 */
+#define MV_ETH_F_DBG_DUMP          (1 << MV_ETH_F_DBG_DUMP_BIT)		/* 0x400 */
+#define MV_ETH_F_DBG_ISR           (1 << MV_ETH_F_DBG_ISR_BIT)		/* 0x800 */
+#define MV_ETH_F_DBG_POLL          (1 << MV_ETH_F_DBG_POLL_BIT)		/* 0x1000 */
+#define MV_ETH_F_CLEANUP_TIMER     (1 << MV_ETH_F_CLEANUP_TIMER_BIT)	/* 0x2000 */
+#define MV_ETH_F_NFP_EN            (1 << MV_ETH_F_NFP_EN_BIT)		/* 0x4000 */
+
+
+/* One of three TXQ states */
+#define MV_ETH_TXQ_FREE         0
+#define MV_ETH_TXQ_CPU          1
+#define MV_ETH_TXQ_HWF          2
+
+#define MV_ETH_TXQ_INVALID		0xFF
+
+struct mv_eth_tx_spec {
+	u32		hw_cmd;	/* tx_desc offset = 0xC */
+	u16		flags;
+	u8		txp;
+	u8		txq;
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+	void		(*tx_func) (u8 *data, int size, struct mv_eth_tx_spec *tx_spec);
+#endif
+};
+
+struct tx_queue {
+	MV_NETA_TXQ_CTRL   *q;
+	u8                  cpu_owner; /* counter */
+	u8                  hwf_rxp;
+	u8                  txp;
+	u8                  txq;
+	int                 txq_size;
+	int                 txq_count;
+	int                 bm_only;
+	u32                 *shadow_txq; /* can be MV_ETH_PKT* or struct skbuf* */
+	int                 shadow_txq_put_i;
+	int                 shadow_txq_get_i;
+	struct txq_stats    stats;
+	spinlock_t          queue_lock;
+	MV_U32              txq_done_pkts_coal;
+};
+
+struct rx_queue {
+	MV_NETA_RXQ_CTRL    *q;
+	int                 rxq_size;
+	int                 missed;
+	MV_U32	            rxq_pkts_coal;
+	MV_U32	            rxq_time_coal;
+};
+
+struct dist_stats {
+	u32     *rx_dist;
+	int     rx_dist_size;
+	u32     *tx_done_dist;
+	int     tx_done_dist_size;
+	u32     *tx_tso_dist;
+	int     tx_tso_dist_size;
+};
+
+struct eth_port {
+	int                 port;
+	MV_NETA_PORT_CTRL   *port_ctrl;
+	struct rx_queue     *rxq_ctrl;
+	struct tx_queue     *txq_ctrl;
+	int                 txp_num;
+	struct timer_list   tx_done_timer;
+	struct timer_list   cleanup_timer;
+	struct net_device   *dev;
+	rwlock_t            rwlock;
+	struct bm_pool      *pool_long;
+	int                 pool_long_num;
+#ifdef CONFIG_MV_ETH_BM_CPU
+	struct bm_pool      *pool_short;
+	int                 pool_short_num;
+#endif /* CONFIG_MV_ETH_BM_CPU */
+	MV_U32              causeRxTx[CONFIG_NR_CPUS];
+	struct napi_struct  *napi[CONFIG_NR_CPUS];
+	struct napi_struct  *napiGroup[CONFIG_MV_ETH_NAPI_GROUPS];
+	unsigned long       flags;	/* MH, TIMER, etc. */
+	u32                 hw_cmd;	/* offset 0xc in TX descriptor */
+	int                 txp;
+	int                 txq[CONFIG_NR_CPUS];
+	u16                 tx_mh;	/* 2B MH */
+	struct port_stats   stats;
+	struct dist_stats   dist_stats;
+	MV_U8               txq_tos_map[256];
+	int                 weight;
+	MV_STACK            *extArrStack;
+	int                 extBufSize;
+	spinlock_t          extLock;
+#ifdef CONFIG_MV_ETH_TOOL
+	__u16               speed_cfg;
+	__u8                duplex_cfg;
+	__u8                autoneg_cfg;
+	__u16		        advertise_cfg;
+#endif/* CONFIG_MV_ETH_TOOL */
+#ifdef CONFIG_MV_ETH_RX_CSUM_OFFLOAD
+	MV_U32              rx_csum_offload;
+#endif /* CONFIG_MV_ETH_RX_CSUM_OFFLOAD */
+#ifdef CONFIG_MV_ETH_RX_SPECIAL
+	void    (*rx_special_proc)(int port, int rxq, struct net_device *dev,
+					struct sk_buff *skb, struct neta_rx_desc *rx_desc);
+#endif /* CONFIG_MV_ETH_RX_SPECIAL */
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+	int     (*tx_special_check)(int port, struct net_device *dev, struct sk_buff *skb,
+					struct mv_eth_tx_spec *tx_spec_out);
+#endif /* CONFIG_MV_ETH_TX_SPECIAL */
+	int napiCpuGroup[CONFIG_NR_CPUS];
+	MV_U32 cpuMask;
+#ifdef CONFIG_MV_MAC_LEARN
+	void    (*rx_mc_mac_learn)(int port, int rxq, struct net_device *dev,
+					struct sk_buff *skb, struct neta_rx_desc *rx_desc);
+#endif /* CONFIG_MV_ETH_RX_SPECIAL */
+};
+
+struct eth_netdev {
+	u16     tx_vlan_mh;		/* 2B MH */
+	u16     vlan_grp_id;		/* vlan group ID */
+	u16     port_map;		/* switch port map */
+	u16     link_map;		/* switch port link map */
+	u16     cpu_port;		/* switch CPU port */
+	u16     group;
+};
+
+struct eth_dev_priv {
+	struct eth_port     *port_p;
+	struct eth_netdev   *netdev_p;
+};
+
+#define MV_ETH_PRIV(dev)        (((struct eth_dev_priv *)(netdev_priv(dev)))->port_p)
+#define MV_DEV_PRIV(dev)        (((struct eth_dev_priv *)(netdev_priv(dev)))->netdev_p)
+#define MV_DEV_STAT(dev)        (&((dev)->stats))
+
+/* define which Switch ports are relevant */
+#define SWITCH_CONNECTED_PORTS_MASK	0x7F
+
+#define MV_SWITCH_ID_0			0
+#define MV_ETH_PORT_0			0
+#define MV_ETH_PORT_1			1
+
+struct pool_stats {
+#ifdef CONFIG_MV_ETH_STAT_ERR
+	u32 skb_alloc_oom;
+	u32 stack_empty;
+	u32 stack_full;
+#endif /* CONFIG_MV_ETH_STAT_ERR */
+
+#ifdef CONFIG_MV_ETH_STAT_DBG
+	u32 bm_put;
+	u32 stack_put;
+	u32 stack_get;
+	u32 skb_alloc_ok;
+	u32 skb_recycled_ok;
+	u32 skb_recycled_err;
+#endif /* CONFIG_MV_ETH_STAT_DBG */
+};
+
+struct bm_pool {
+	int         pool;
+	int         capacity;
+	int         buf_num;
+	int         pkt_size;
+	u32         *bm_pool;
+	MV_STACK    *stack;
+	spinlock_t  lock;
+	u32         port_map;
+	int         missed;		/* FIXME: move to stats */
+	struct pool_stats  stats;
+};
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+#define MV_ETH_BM_POOLS	        MV_BM_POOLS
+#define mv_eth_pool_bm(p)       (p->bm_pool)
+#define mv_eth_txq_bm(q)        (q->bm_only)
+#else
+#define MV_ETH_BM_POOLS		CONFIG_MV_ETH_PORTS_NUM
+#define mv_eth_pool_bm(p)       0
+#define mv_eth_txq_bm(q)        0
+#endif /* CONFIG_MV_ETH_BM_CPU */
+
+#ifdef CONFIG_MV_ETH_BM
+MV_STATUS mv_eth_bm_config_get(void);
+int mv_eth_bm_config_pkt_size_get(int pool);
+int mv_eth_bm_config_pkt_size_set(int pool, int pkt_size);
+int mv_eth_bm_config_short_pool_get(int port);
+int mv_eth_bm_config_short_buf_num_get(int port);
+int mv_eth_bm_config_buf_num_set(int port, int longBufNum, int shortBufNum);
+int mv_eth_bm_config_long_pool_get(int port);
+int mv_eth_bm_config_long_buf_num_get(int port);
+void mv_eth_bm_config_print(void);
+#endif /* CONFIG_MV_ETH_BM */
+
+extern struct bm_pool mv_eth_pool[MV_ETH_BM_POOLS];
+extern struct eth_port **mv_eth_ports;
+
+static inline void mv_eth_interrupts_unmask(struct eth_port *pp)
+{
+	/* unmask interrupts */
+	if (!(pp->flags & (MV_ETH_F_SWITCH | MV_ETH_F_EXT_SWITCH)))
+		MV_REG_WRITE(NETA_INTR_MISC_MASK_REG(pp->port), NETA_CAUSE_LINK_CHANGE_MASK);
+
+	MV_REG_WRITE(NETA_INTR_NEW_MASK_REG(pp->port),
+		(MV_ETH_MISC_SUM_INTR_MASK |
+		MV_ETH_TXDONE_INTR_MASK |
+		MV_ETH_RX_INTR_MASK));
+}
+
+static inline int mv_eth_ctrl_is_tx_enabled(struct eth_port *pp)
+{
+	if (!pp)
+		return -ENODEV;
+
+	if (pp->flags & MV_ETH_F_CONNECT_LINUX)
+		return 1;
+
+	return 0;
+}
+
+static inline struct neta_tx_desc *mv_eth_tx_desc_get(struct tx_queue *txq_ctrl, int num)
+{
+	/* Is enough TX descriptors to send packet */
+	if ((txq_ctrl->txq_count + num) >= txq_ctrl->txq_size) {
+		/*
+		printk(KERN_ERR "eth_tx: txq_ctrl->txq=%d - no_resource: txq_count=%d, txq_size=%d, num=%d\n",
+			txq_ctrl->txq, txq_ctrl->txq_count, txq_ctrl->txq_size, num);
+		*/
+		STAT_ERR(txq_ctrl->stats.txq_err++);
+		return NULL;
+	}
+	return mvNetaTxqNextDescGet(txq_ctrl->q);
+}
+
+static inline void mv_eth_tx_desc_flush(struct neta_tx_desc *tx_desc)
+{
+#if defined(MV_CPU_BE)
+	mvNetaTxqDescSwap(tx_desc);
+#endif /* MV_CPU_BE */
+
+	mvOsCacheLineFlush(NULL, tx_desc);
+}
+
+static inline void *mv_eth_extra_pool_get(struct eth_port *pp)
+{
+	void *ext_buf;
+
+	spin_lock(&pp->extLock);
+	if (mvStackIndex(pp->extArrStack) == 0) {
+		STAT_ERR(pp->stats.ext_stack_empty++);
+		ext_buf = mvOsMalloc(CONFIG_MV_ETH_EXTRA_BUF_SIZE);
+	} else {
+		STAT_DBG(pp->stats.ext_stack_get++);
+		ext_buf = (void *)mvStackPop(pp->extArrStack);
+	}
+	spin_unlock(&pp->extLock);
+
+	return ext_buf;
+}
+
+static inline int mv_eth_extra_pool_put(struct eth_port *pp, void *ext_buf)
+{
+	spin_lock(&pp->extLock);
+	if (mvStackIsFull(pp->extArrStack)) {
+		STAT_ERR(pp->stats.ext_stack_full++);
+		spin_unlock(&pp->extLock);
+		mvOsFree(ext_buf);
+		return 1;
+	}
+	mvStackPush(pp->extArrStack, (MV_U32)ext_buf);
+	STAT_DBG(pp->stats.ext_stack_put++);
+	spin_unlock(&pp->extLock);
+	return 0;
+}
+
+static inline void mv_eth_add_cleanup_timer(struct eth_port *pp)
+{
+	if (test_and_set_bit(MV_ETH_F_CLEANUP_TIMER_BIT, &(pp->flags)) == 0) {
+		pp->cleanup_timer.expires = jiffies + ((HZ * CONFIG_MV_ETH_CLEANUP_TIMER_PERIOD) / 1000); /* ms */
+		add_timer(&pp->cleanup_timer);
+	}
+}
+
+static inline void mv_eth_add_tx_done_timer(struct eth_port *pp)
+{
+	if (test_and_set_bit(MV_ETH_F_TX_DONE_TIMER_BIT, &(pp->flags)) == 0) {
+
+		pp->tx_done_timer.expires = jiffies + ((HZ * CONFIG_MV_ETH_TX_DONE_TIMER_PERIOD) / 1000); /* ms */
+		add_timer(&pp->tx_done_timer);
+	}
+}
+
+static inline void mv_eth_shadow_inc_get(struct tx_queue *txq)
+{
+	txq->shadow_txq_get_i++;
+	if (txq->shadow_txq_get_i == txq->txq_size)
+		txq->shadow_txq_get_i = 0;
+}
+
+static inline void mv_eth_shadow_inc_put(struct tx_queue *txq)
+{
+	txq->shadow_txq_put_i++;
+	if (txq->shadow_txq_put_i == txq->txq_size)
+		txq->shadow_txq_put_i = 0;
+}
+
+static inline void mv_eth_shadow_dec_put(struct tx_queue *txq)
+{
+	if (txq->shadow_txq_put_i == 0)
+		txq->shadow_txq_put_i = txq->txq_size - 1;
+	else
+		txq->shadow_txq_put_i--;
+}
+
+/* Free pkt + skb pair */
+static inline void mv_eth_pkt_free(struct eth_pbuf *pkt)
+{
+	struct sk_buff *skb = (struct sk_buff *)pkt->osInfo;
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	skb->skb_recycle = NULL;
+	skb->hw_cookie = NULL;
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+	dev_kfree_skb_any(skb);
+	mvOsFree(pkt);
+}
+
+static inline int mv_eth_pool_put(struct bm_pool *pool, struct eth_pbuf *pkt)
+{
+	unsigned long flags = 0;
+
+	MV_ETH_LOCK(&pool->lock, flags);
+	if (mvStackIsFull(pool->stack)) {
+		STAT_ERR(pool->stats.stack_full++);
+		MV_ETH_UNLOCK(&pool->lock, flags);
+
+		/* free pkt+skb */
+		mv_eth_pkt_free(pkt);
+		return 1;
+	}
+	mvStackPush(pool->stack, (MV_U32) pkt);
+	STAT_DBG(pool->stats.stack_put++);
+	MV_ETH_UNLOCK(&pool->lock, flags);
+	return 0;
+}
+
+
+/* Pass pkt to BM Pool or RXQ ring */
+static inline void mv_eth_rxq_refill(struct eth_port *pp, int rxq,
+				     struct eth_pbuf *pkt, struct bm_pool *pool, struct neta_rx_desc *rx_desc)
+{
+	if (mv_eth_pool_bm(pool)) {
+		/* Refill BM pool */
+		STAT_DBG(pool->stats.bm_put++);
+		mvBmPoolPut(pkt->pool, (MV_ULONG) pkt->physAddr);
+		mvOsCacheLineInv(NULL, rx_desc);
+	} else {
+		/* Refill Rx descriptor */
+		STAT_DBG(pp->stats.rxq_fill[rxq]++);
+		mvNetaRxDescFill(rx_desc, pkt->physAddr, (MV_U32)pkt);
+	}
+}
+
+
+#ifdef CONFIG_MV_ETH_SWITCH
+struct mv_eth_switch_config {
+	int             mtu;
+	int             netdev_max;
+	int             netdev_cfg;
+	unsigned char   mac_addr[CONFIG_MV_ETH_SWITCH_NETDEV_NUM][MV_MAC_ADDR_SIZE];
+	u16             board_port_map[CONFIG_MV_ETH_SWITCH_NETDEV_NUM];
+};
+
+extern int  mv_eth_switch_netdev_first, mv_eth_switch_netdev_last;
+extern struct mv_eth_switch_config      switch_net_config[CONFIG_MV_ETH_PORTS_NUM];
+extern struct net_device **mv_net_devs;
+
+int     mv_eth_switch_config_get(int use_existing_config, int port);
+int     mv_eth_switch_set_mac_addr(struct net_device *dev, void *mac);
+void    mv_eth_switch_set_multicast_list(struct net_device *dev);
+int     mv_eth_switch_change_mtu(struct net_device *dev, int mtu);
+int     mv_eth_switch_start(struct net_device *dev);
+int     mv_eth_switch_stop(struct net_device *dev);
+void    mv_eth_switch_status_print(int port);
+int     mv_eth_switch_port_add(struct net_device *dev, int port);
+int     mv_eth_switch_port_del(struct net_device *dev, int port);
+
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+/******************************************************
+ * Function prototypes --                             *
+ ******************************************************/
+int         mv_eth_stop(struct net_device *dev);
+int         mv_eth_change_mtu(struct net_device *dev, int mtu);
+int         mv_eth_check_mtu_internals(struct net_device *dev, int mtu);
+int         mv_eth_check_mtu_valid(struct net_device *dev, int mtu);
+
+int         mv_eth_set_mac_addr(struct net_device *dev, void *mac);
+void        mv_eth_set_multicast_list(struct net_device *dev);
+int         mv_eth_open(struct net_device *dev);
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_NFP_MODULE)
+struct nfpHookMgr {
+	MV_STATUS (*mv_eth_nfp)(struct eth_port *pp, int rxq, struct neta_rx_desc *rx_desc,
+					struct eth_pbuf *pkt, struct bm_pool *pool);
+};
+typedef MV_STATUS mv_eth_nfp_func_t(struct eth_port *pp, int rxq, struct neta_rx_desc *rx_desc,
+					struct eth_pbuf *pkt, struct bm_pool *pool);
+int         nfp_hook_mgr_register(mv_eth_nfp_func_t *func);
+void        nfp_hook_mgr_unregister(void);
+int         mv_eth_ctrl_nfp(struct net_device *dev, int en);
+MV_STATUS   mv_eth_nfp(struct eth_port *pp, int rxq, struct neta_rx_desc *rx_desc,
+			struct eth_pbuf *pkt, struct bm_pool *pool);
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_NFP_MODULE */
+
+irqreturn_t mv_eth_isr(int irq, void *dev_id);
+int         mv_eth_start_internals(struct eth_port *pp, int mtu);
+int         mv_eth_stop_internals(struct eth_port *pp);
+int         mv_eth_change_mtu_internals(struct net_device *netdev, int mtu);
+
+int         mv_eth_rx_reset(int port);
+int         mv_eth_txp_reset(int port, int txp);
+
+MV_STATUS   mv_eth_rx_ptks_coal_set(int port, int rxq, MV_U32 value);
+MV_STATUS   mv_eth_rx_time_coal_set(int port, int rxq, MV_U32 value);
+MV_STATUS   mv_eth_tx_done_ptks_coal_set(int port, int txp, int txq, MV_U32 value);
+
+struct eth_port     *mv_eth_port_by_id(unsigned int port);
+struct net_device   *mv_eth_netdev_by_id(unsigned int idx);
+bool                 mv_eth_netdev_find(unsigned int if_index);
+
+void        mv_eth_mac_show(int port);
+void        mv_eth_tos_map_show(int port);
+int         mv_eth_rxq_tos_map_set(int port, int rxq, unsigned char tos);
+int         mv_eth_txq_tos_map_set(int port, int txq, unsigned char tos);
+int         mv_eth_napi_set_cpu_affinity(int port, int group, int affinity);
+int         mv_eth_napi_set_rxq_affinity(int port, int group, int rxq);
+void        mv_eth_napi_group_show(int port);
+
+int         mv_eth_rxq_vlan_prio_set(int port, int rxq, unsigned char prio);
+void        mv_eth_vlan_prio_show(int port);
+
+void        mv_eth_netdev_print(struct net_device *netdev);
+void        mv_eth_status_print(void);
+void        mv_eth_port_status_print(unsigned int port);
+void        mv_eth_port_stats_print(unsigned int port);
+
+void        mv_eth_set_noqueue(struct net_device *dev, int enable);
+
+void        mv_eth_ctrl_hwf(int en);
+int         mv_eth_ctrl_recycle(int en);
+void        mv_eth_ctrl_txdone(int num);
+int         mv_eth_ctrl_tx_mh(int port, u16 mh);
+int         mv_eth_ctrl_tx_cmd(int port, u32 cmd);
+int         mv_eth_ctrl_txq_cpu_def(int port, int txp, int txq, int cpu);
+int         mv_eth_ctrl_txq_mode_get(int port, int txp, int txq, int *rx_port);
+int         mv_eth_ctrl_txq_cpu_own(int port, int txp, int txq, int add);
+int         mv_eth_ctrl_txq_hwf_own(int port, int txp, int txq, int rxp);
+int         mv_eth_ctrl_flag(int port, u32 flag, u32 val);
+int         mv_eth_ctrl_txq_size_set(int port, int txp, int txq, int value);
+int         mv_eth_ctrl_rxq_size_set(int port, int rxq, int value);
+int         mv_eth_ctrl_port_buf_num_set(int port, int long_num, int short_num);
+int         mv_eth_ctrl_pool_size_set(int pool, int pkt_size);
+int         mv_eth_ctrl_set_poll_rx_weight(int port, u32 weight);
+
+void        mv_eth_tx_desc_print(struct neta_tx_desc *desc);
+void        mv_eth_pkt_print(struct eth_pbuf *pkt);
+void        mv_eth_rx_desc_print(struct neta_rx_desc *desc);
+void        mv_eth_skb_print(struct sk_buff *skb);
+void        mv_eth_link_status_print(int port);
+
+#ifdef CONFIG_MV_PON
+typedef MV_BOOL(*PONLINKSTATUSPOLLFUNC)(void);		  /* prototype for PON link status polling function */
+typedef void   (*PONLINKSTATUSNOTIFYFUNC)(MV_BOOL state); /* prototype for PON link status notification function */
+
+MV_BOOL mv_pon_link_status(void);
+void mv_pon_link_state_register(PONLINKSTATUSPOLLFUNC poll_func, PONLINKSTATUSNOTIFYFUNC *notify_func);
+void mv_pon_ctrl_omci_type(MV_U16 type);
+void mv_pon_ctrl_omci_rx_gh(int en);
+void mv_pon_omci_print(void);
+
+#endif /* CONFIG_MV_PON */
+
+#ifdef CONFIG_MV_ETH_TX_SPECIAL
+void        mv_eth_tx_special_check_func(int port, int (*func)(int port, struct net_device *dev,
+				  struct sk_buff *skb, struct mv_eth_tx_spec *tx_spec_out));
+#endif /* CONFIG_MV_ETH_TX_SPECIAL */
+
+#ifdef CONFIG_MV_ETH_RX_SPECIAL
+void        mv_eth_rx_special_proc_func(int port, void (*func)(int port, int rxq, struct net_device *dev,
+							struct sk_buff *skb, struct neta_rx_desc *rx_desc));
+#endif /* CONFIG_MV_ETH_RX_SPECIAL */
+
+#ifdef CONFIG_MV_MAC_LEARN
+void        mv_eth_rx_mac_learn_func(int port, void (*func)(int port, int rxq, struct net_device *dev,
+							struct sk_buff *skb, struct neta_rx_desc *rx_desc));
+#endif /* CONFIG_MV_MAC_LEARN */
+
+int  mv_eth_poll(struct napi_struct *napi, int budget);
+void mv_eth_link_event(struct eth_port *pp, int print);
+
+int mv_eth_rx_policy(u32 cause);
+int mv_eth_refill(struct eth_port *pp, int rxq,
+				struct eth_pbuf *pkt, struct bm_pool *pool, struct neta_rx_desc *rx_desc);
+u32 mv_eth_txq_done(struct eth_port *pp, struct tx_queue *txq_ctrl);
+u32 mv_eth_tx_done_gbe(struct eth_port *pp, u32 cause_tx_done, int *tx_todo);
+u32 mv_eth_tx_done_pon(struct eth_port *pp, int *tx_todo);
+
+#ifdef CONFIG_MV_ETH_RX_DESC_PREFETCH
+struct neta_rx_desc *mv_eth_rx_prefetch(struct eth_port *pp,
+						MV_NETA_RXQ_CTRL *rx_ctrl, int rx_done, int rx_todo);
+#endif /* CONFIG_MV_ETH_RX_DESC_PREFETCH */
+
+#ifdef CONFIG_MV_ETH_BM
+void	*mv_eth_bm_pool_create(int pool, int capacity, MV_ULONG *physAddr);
+#endif /* CONFIG_MV_ETH_BM */
+
+#if defined(CONFIG_MV_ETH_HWF) && !defined(CONFIG_MV_ETH_BM_CPU)
+MV_STATUS mv_eth_hwf_bm_create(int port, int mtuPktSize);
+void      mv_hwf_bm_dump(void);
+#endif /* CONFIG_MV_ETH_HWF && !CONFIG_MV_ETH_BM_CPU */
+
+int mv_eth_ctrl_port_started_get(int port);
+int mv_eth_dev_name_by_portid (unsigned int port, char * dev_name);
+void mv_eth_port_ifname_print(unsigned int port);
+int mv_eth_pon_ifname_dump(char *buf);
+int mv_eth_set_mtu(int portNo, int mtu);
+int mv_eth_get_mtu(int portNo, int* mtu);
+int mv_eth_get_txq_cpu_def(int port, int *txp, int *txq, int cpu);
+
+#endif /* __mv_netdev_h__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_pon_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_pon_sysfs.c
new file mode 100755
index 0000000..647d620
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/mv_pon_sysfs.c
@@ -0,0 +1,181 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+
+#include "gbe/mvNeta.h"
+#include "pnc/mvPnc.h"
+
+#include "mv_netdev.h"
+
+static ssize_t mv_pon_help(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "cat help                   - show this help\n");
+	off += sprintf(buf+off, "echo p txp   > txp_regs    - show TX registers for <p/txp>\n");
+
+#ifdef MV_PON_MIB_SUPPORT
+	off += sprintf(buf+off, "echo mib gp  > mib_gpid    - MIB set <mib> for incoming packets with GemPID <gp>\n");
+	off += sprintf(buf+off, "echo mib     > mib_def     - MIB set <mib> for incoming packets not matched any GemPID\n");
+#endif /* MV_PON_MIB_SUPPORT */
+
+	return off;
+}
+
+
+static ssize_t mv_pon_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	int        off = 0;
+	const char *name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "help"))
+		off = mv_pon_help(buf);
+	else
+		off = mv_pon_help(buf);
+
+	return off;
+}
+
+static ssize_t mv_pon_1_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	unsigned int    v;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read input */
+	v = 0;
+
+	sscanf(buf, "%x", &v);
+
+	local_irq_save(flags);
+
+#ifdef MV_PON_MIB_SUPPORT
+	if (!strcmp(name, "mib_def")) {
+		mvNetaPonRxMibDefault(v);
+	} else
+#endif /* MV_PON_MIB_SUPPORT */
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	local_irq_restore(flags);
+
+	return len;
+}
+
+static ssize_t mv_pon_2_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char	*name = attr->attr.name;
+	unsigned int    p, v;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read input */
+	v = 0;
+	sscanf(buf, "%d %x", &p, &v);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "txp_regs"))
+		mvNetaPonTxpRegs(p, v);
+#ifdef MV_PON_MIB_SUPPORT
+	else if (!strcmp(name, "mib_gpid"))
+		mvNetaPonRxMibGemPid(p, v);
+#endif /* MV_PON_MIB_SUPPORT */
+	else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	local_irq_restore(flags);
+
+	return len;
+}
+
+static DEVICE_ATTR(txp_regs,   S_IWUSR, mv_pon_show, mv_pon_2_store);
+static DEVICE_ATTR(mib_gpid,   S_IWUSR, mv_pon_show, mv_pon_2_store);
+static DEVICE_ATTR(mib_def,    S_IWUSR, mv_pon_show, mv_pon_1_store);
+static DEVICE_ATTR(help,       S_IRUSR, mv_pon_show, NULL);
+
+static struct attribute *mv_pon_attrs[] = {
+	&dev_attr_txp_regs.attr,
+	&dev_attr_mib_def.attr,
+	&dev_attr_mib_gpid.attr,
+	&dev_attr_help.attr,
+	NULL
+};
+
+static struct attribute_group mv_pon_group = {
+	.name = "pon",
+	.attrs = mv_pon_attrs,
+};
+
+int __devinit mv_pon_sysfs_init(void)
+{
+		int err;
+		struct device *pd;
+
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+		if (!pd) {
+			platform_device_register_simple("neta", -1, NULL, 0);
+			pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+		}
+
+		if (!pd) {
+			printk(KERN_ERR"%s: cannot find neta device\n", __func__);
+			pd = &platform_bus;
+		}
+
+		err = sysfs_create_group(&pd->kobj, &mv_pon_group);
+		if (err) {
+			printk(KERN_INFO "sysfs group failed %d\n", err);
+			goto out;
+		}
+out:
+		return err;
+}
+
+module_init(mv_pon_sysfs_init);
+
+MODULE_AUTHOR("Dmitri Epshtein");
+MODULE_DESCRIPTION("sysfs for Marvell PON");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/nfp_mgr/mv_nfp_mgr_if.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/nfp_mgr/mv_nfp_mgr_if.h
new file mode 100755
index 0000000..372a825
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/nfp_mgr/mv_nfp_mgr_if.h
@@ -0,0 +1,28 @@
+/* mv_nfp_mgr_if.h */
+
+#ifndef MV_NFP_MGR_IF_H
+#define MV_NFP_MGR_IF_H
+
+#ifdef CONFIG_MV_ETH_NFP_FIB_LEARN
+void nfp_fib_learn_enable(int en);
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_CT_LEARN
+void nfp_ct_learn_enable(int en);
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_FDB_LEARN
+void nfp_bridge_learn_enable(int en);
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_VLAN_LEARN
+void nfp_vlan_learn_enable(int en);
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_PPP_LEARN
+void nfp_ppp_learn_enable(int en);
+#endif
+
+extern rwlock_t nfp_lock;
+#endif
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pmt/pmt_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pmt/pmt_sysfs.c
new file mode 100755
index 0000000..7684237
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pmt/pmt_sysfs.c
@@ -0,0 +1,302 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "pmt/mvPmt.h"
+
+static MV_NETA_PMT  mv_neta_pmt_e;
+
+static ssize_t pmt_help(char *buf)
+{
+	int off = 0;
+
+	off += mvOsSPrintf(buf+off, "p, i, a, b, c - are dec numbers\n");
+	off += mvOsSPrintf(buf+off, "v, m          - are hex numbers\n");
+	off += mvOsSPrintf(buf+off, "\n");
+
+	off += mvOsSPrintf(buf+off, "cat          help          - Show this help\n");
+	off += mvOsSPrintf(buf+off, "cat          sw_dump       - Show sw PMT etry\n");
+	off += mvOsSPrintf(buf+off, "cat          sw_clear      - Clear sw PMT etry\n");
+	off += mvOsSPrintf(buf+off, "echo v     > sw_word       - Set 4 bytes value <v> to sw entry\n");
+	off += mvOsSPrintf(buf+off, "echo p     > hw_regs       - Show PMT registers\n");
+	off += mvOsSPrintf(buf+off, "echo p     > hw_dump       - Dump valid PMT entries of the port <p>\n");
+	off += mvOsSPrintf(buf+off, "echo p     > hw_dump_all   - Dump all PMT entries of the port <p>\n");
+	off += mvOsSPrintf(buf+off, "echo p i   > hw_read       - Read PMT entry <i> on port <p> into sw entry\n");
+	off += mvOsSPrintf(buf+off, "echo p i   > hw_write      - Write sw entry into PMT entry <i> on port <p>\n");
+	off += mvOsSPrintf(buf+off, "echo p i   > hw_inv        - Disable PMT entry <i> on port <p>\n");
+	off += mvOsSPrintf(buf+off, "echo p     > hw_inv_all    - Disable all PMT entries on port <p>\n");
+	off += mvOsSPrintf(buf+off, "echo 0|1   > s_last        - Set/Clear last bit\n");
+	off += mvOsSPrintf(buf+off, "echo a b c > s_flags       - Set/Clear flags: <a>-last, <b>-ipv4csum, <c>-l4csum\n");
+	off += mvOsSPrintf(buf+off, "echo v     > s_rep_2b      - Replace 2 bytes with value <v>\n");
+	off += mvOsSPrintf(buf+off, "echo v     > s_add_2b      - Add 2 bytes with value <v> to sw entry\n");
+	off += mvOsSPrintf(buf+off, "echo a b c > s_del_2b      - Delete <a> bytes, Skip <b> bytes before, Skip <c> bytes after\n");
+	off += mvOsSPrintf(buf+off, "echo v m   > s_rep_lsb     - Replace LSB with value <v> and mask <m>\n");
+	off += mvOsSPrintf(buf+off, "echo v m   > s_rep_msb     - Replace MSB with value <v> and mask <m>\n");
+	off += mvOsSPrintf(buf+off, "echo v     > s_ip_csum     - Replace IP checksum. <v> used as additional info\n");
+	off += mvOsSPrintf(buf+off, "echo v     > s_l4_csum     - Replace TCP/UDP checksum. <v> used as additional info\n");
+	off += mvOsSPrintf(buf+off, "echo a b   > s_dec_lsb     - Decrement LSB, Skip <a> bytes before, Skip <b> bytes after\n");
+	off += mvOsSPrintf(buf+off, "echo a b   > s_dec_msb     - Decrement MSB, Skip <a> bytes before, Skip <b> bytes after\n");
+	off += mvOsSPrintf(buf+off, "echo a     > s_skip        - Skip <a> bytes. Must be even\n");
+	off += mvOsSPrintf(buf+off, "echo a b c > s_jump        - Jump to entry <a>. <b>=1-skip,2-subroutine. <c>=1-green,2-yellow\n");
+
+	return off;
+}
+
+static ssize_t pmt_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	const char  *name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "help"))
+		return pmt_help(buf);
+
+	if (!strcmp(name, "sw_dump")) {
+		mvNetaPmtEntryPrint(&mv_neta_pmt_e);
+	} else if (!strcmp(name, "sw_clear")) {
+		MV_NETA_PMT_CLEAR(&mv_neta_pmt_e);
+	}
+
+	return 0;
+}
+
+static ssize_t pmt_hw_store(struct device *dev,
+			struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char    *name = attr->attr.name;
+	unsigned int  err = 0, p = 0, i = 0;
+	unsigned long flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%d %d", &p, &i);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "hw_dump")) {
+		mvNetaPmtDump(p, 1);
+	} else if (!strcmp(name, "hw_dump_all")) {
+		mvNetaPmtDump(p, 0);
+	} else if (!strcmp(name, "hw_regs")) {
+		mvNetaPmtRegs(p, i);
+	} else if (!strcmp(name, "hw_write")) {
+		err = mvNetaPmtWrite(p, i, &mv_neta_pmt_e);
+	} else if (!strcmp(name, "hw_read")) {
+		err = mvNetaPmtRead(p, i, &mv_neta_pmt_e);
+	} else if (!strcmp(name, "hw_inv")) {
+		MV_NETA_PMT_INVALID_SET(&mv_neta_pmt_e);
+		err = mvNetaPmtWrite(p, i, &mv_neta_pmt_e);
+	} else if (!strcmp(name, "hw_inv_all")) {
+		err = mvNetaPmtClear(p);
+	} else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: <%s>, error %d\n", __func__, attr->attr.name, err);
+
+	return err ? -EINVAL : len;
+}
+
+static ssize_t pmt_sw_dec_store(struct device *dev,
+			struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char	*name = attr->attr.name;
+	unsigned int    err = 0, a = 0, b = 0, c = 0;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%d %d %d", &a, &b, &c);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "s_last")) {
+		mvNetaPmtLastFlag(&mv_neta_pmt_e, a);
+	} else if (!strcmp(name, "s_flags")) {
+		mvNetaPmtFlags(&mv_neta_pmt_e, a, b, c);
+	} else if (!strcmp(name, "s_del")) {
+		mvNetaPmtDelShorts(&mv_neta_pmt_e, a/2, b/2, c/2);
+	} else if (!strcmp(name, "s_skip")) {
+		mvNetaPmtSkip(&mv_neta_pmt_e, a/2);
+	} else if (!strcmp(name, "s_dec_lsb")) {
+		mvNetaPmtDecLSB(&mv_neta_pmt_e, a/2, b/2);
+	} else if (!strcmp(name, "s_dec_msb")) {
+		mvNetaPmtDecMSB(&mv_neta_pmt_e, a/2, b/2);
+	} else if (!strcmp(name, "s_jump")) {
+		mvNetaPmtJump(&mv_neta_pmt_e, a, b, c);
+	} else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: <%s>, error %d\n", __func__, attr->attr.name, err);
+
+	return err ? -EINVAL : len;
+}
+
+static ssize_t pmt_sw_hex_store(struct device *dev,
+				struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char	*name = attr->attr.name;
+	unsigned int    err = 0, v = 0, a = 0;
+	unsigned long   flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%x %d", &v, &a);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "sw_word")) {
+		mv_neta_pmt_e.word = v;
+	} else if (!strcmp(name, "s_rep_2b")) {
+		mvNetaPmtReplace2Bytes(&mv_neta_pmt_e, v);
+	} else if (!strcmp(name, "s_add_2b")) {
+		mvNetaPmtAdd2Bytes(&mv_neta_pmt_e, v);
+	} else if (!strcmp(name, "s_rep_lsb")) {
+		mvNetaPmtReplaceLSB(&mv_neta_pmt_e, v, a);
+	} else if (!strcmp(name, "s_rep_msb")) {
+		mvNetaPmtReplaceMSB(&mv_neta_pmt_e, v, a);
+	} else if (!strcmp(name, "s_ip_csum")) {
+		mvNetaPmtReplaceIPv4csum(&mv_neta_pmt_e, v);
+	} else if (!strcmp(name, "s_l4_csum")) {
+		mvNetaPmtReplaceL4csum(&mv_neta_pmt_e, v);
+	} else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: <%s>, error %d\n", __func__, attr->attr.name, err);
+
+	return err ? -EINVAL : len;
+}
+
+static DEVICE_ATTR(help,        S_IRUSR, pmt_show, NULL);
+static DEVICE_ATTR(sw_dump,     S_IRUSR, pmt_show, NULL);
+static DEVICE_ATTR(sw_clear,    S_IRUSR, pmt_show, NULL);
+static DEVICE_ATTR(hw_regs,     S_IWUSR, pmt_show, pmt_hw_store);
+static DEVICE_ATTR(hw_write,    S_IWUSR, pmt_show, pmt_hw_store);
+static DEVICE_ATTR(hw_read,     S_IWUSR, pmt_show, pmt_hw_store);
+static DEVICE_ATTR(hw_dump,     S_IWUSR, pmt_show, pmt_hw_store);
+static DEVICE_ATTR(hw_dump_all, S_IWUSR, pmt_show, pmt_hw_store);
+static DEVICE_ATTR(hw_inv,      S_IWUSR, pmt_show, pmt_hw_store);
+static DEVICE_ATTR(hw_inv_all,  S_IWUSR, pmt_show, pmt_hw_store);
+static DEVICE_ATTR(sw_word,     S_IWUSR, pmt_show, pmt_sw_hex_store);
+static DEVICE_ATTR(s_rep_2b,    S_IWUSR, pmt_show, pmt_sw_hex_store);
+static DEVICE_ATTR(s_rep_lsb,   S_IWUSR, pmt_show, pmt_sw_hex_store);
+static DEVICE_ATTR(s_rep_msb,   S_IWUSR, pmt_show, pmt_sw_hex_store);
+static DEVICE_ATTR(s_ip_csum,   S_IWUSR, pmt_show, pmt_sw_hex_store);
+static DEVICE_ATTR(s_l4_csum,   S_IWUSR, pmt_show, pmt_sw_hex_store);
+static DEVICE_ATTR(s_dec_lsb,   S_IWUSR, pmt_show, pmt_sw_dec_store);
+static DEVICE_ATTR(s_dec_msb,   S_IWUSR, pmt_show, pmt_sw_dec_store);
+static DEVICE_ATTR(s_add_2b,    S_IWUSR, pmt_show, pmt_sw_hex_store);
+static DEVICE_ATTR(s_del,       S_IWUSR, pmt_show, pmt_sw_dec_store);
+static DEVICE_ATTR(s_last,      S_IWUSR, pmt_show, pmt_sw_dec_store);
+static DEVICE_ATTR(s_flags,     S_IWUSR, pmt_show, pmt_sw_dec_store);
+static DEVICE_ATTR(s_skip,      S_IWUSR, pmt_show, pmt_sw_dec_store);
+static DEVICE_ATTR(s_jump,      S_IWUSR, pmt_show, pmt_sw_dec_store);
+
+
+static struct attribute *pmt_attrs[] = {
+	&dev_attr_help.attr,
+	&dev_attr_sw_dump.attr,
+	&dev_attr_sw_clear.attr,
+	&dev_attr_hw_regs.attr,
+	&dev_attr_hw_write.attr,
+	&dev_attr_hw_read.attr,
+	&dev_attr_hw_dump.attr,
+	&dev_attr_hw_dump_all.attr,
+	&dev_attr_hw_inv.attr,
+	&dev_attr_hw_inv_all.attr,
+	&dev_attr_sw_word.attr,
+	&dev_attr_s_rep_2b.attr,
+	&dev_attr_s_add_2b.attr,
+	&dev_attr_s_del.attr,
+	&dev_attr_s_rep_lsb.attr,
+	&dev_attr_s_rep_msb.attr,
+	&dev_attr_s_ip_csum.attr,
+	&dev_attr_s_l4_csum.attr,
+	&dev_attr_s_dec_lsb.attr,
+	&dev_attr_s_dec_msb.attr,
+	&dev_attr_s_last.attr,
+	&dev_attr_s_flags.attr,
+	&dev_attr_s_skip.attr,
+	&dev_attr_s_jump.attr,
+	NULL
+};
+
+static struct attribute_group pmt_group = {
+	.name = "pmt",
+	.attrs = pmt_attrs,
+};
+
+int __devinit pmt_sysfs_init(void)
+{
+		int err;
+		struct device *pd;
+
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+		if (!pd) {
+			platform_device_register_simple("neta", -1, NULL, 0);
+			pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+		}
+
+		if (!pd) {
+			printk(KERN_ERR"%s: cannot find neta device\n", __func__);
+			pd = &platform_bus;
+		}
+
+		err = sysfs_create_group(&pd->kobj, &pmt_group);
+		if (err) {
+			printk(KERN_INFO "sysfs group failed %d\n", err);
+			goto out;
+		}
+out:
+		return err;
+}
+
+module_init(pmt_sysfs_init);
+
+MODULE_AUTHOR("Dima Epshtein");
+MODULE_DESCRIPTION("PMT for Marvell NetA MV65xxx");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pnc/pnc_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pnc/pnc_sysfs.c
new file mode 100755
index 0000000..dd3fe7e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pnc/pnc_sysfs.c
@@ -0,0 +1,407 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "mvOs.h"
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#include "gbe/mvNeta.h"
+
+#include "pnc/mvPnc.h"
+#include "pnc/mvTcam.h"
+
+static struct tcam_entry te;
+
+static ssize_t tcam_help(char *buf)
+{
+	int off = 0;
+
+	off += mvOsSPrintf(buf+off, "cat <file>\n");
+	off += mvOsSPrintf(buf+off, " sw_dump         - dump sw entry\n");
+	off += mvOsSPrintf(buf+off, " hw_dump         - dump valid entries\n");
+	off += mvOsSPrintf(buf+off, " hw_regs         - dump registers\n");
+	off += mvOsSPrintf(buf+off, " hw_hits         - decode hit sequences\n");
+
+#ifdef MV_ETH_PNC_LB
+	off += mvOsSPrintf(buf+off, " lb_dump         - dump load balancing hash entries\n");
+#endif /* MV_ETH_PNC_LB */
+#ifdef MV_ETH_PNC_AGING
+	off += mvOsSPrintf(buf+off, " age_dump        - dump non-zero aging counters\n");
+	off += mvOsSPrintf(buf+off, " age_dump_all    - dump all aging counters\n");
+	off += mvOsSPrintf(buf+off, " age_scan        - dump aging Scanner log\n");
+	off += mvOsSPrintf(buf+off, " age_reset       - reset all aging counters\n");
+#endif /* MV_ETH_PNC_AGING */
+
+	off += mvOsSPrintf(buf+off, "echo a > <file>\n");
+	off += mvOsSPrintf(buf+off, " hw_write        - write sw entry into tcam entry <a>\n");
+	off += mvOsSPrintf(buf+off, " hw_read         - read tcam entry <a> into sw entry\n");
+	off += mvOsSPrintf(buf+off, " hw_inv          - disable tcam entry <a>\n");
+	off += mvOsSPrintf(buf+off, " hw_inv_all      - disable all tcam entries\n");
+	off += mvOsSPrintf(buf+off, " hw_hits         - start recording for port <a>\n");
+
+#ifdef MV_ETH_PNC_LB
+	off += mvOsSPrintf(buf+off, " lb_ip4          - set LB mode <a> for ipv4 traffic: 0-disable, 1-2tuple\n");
+	off += mvOsSPrintf(buf+off, " lb_ip6          - set LB mode <a> for ipv6 traffic: 0-disable, 1-2tuple\n");
+	off += mvOsSPrintf(buf+off, " lb_l4           - set LB mode <a> for TCP/UDP traffic: : 0-disable, 1-2tuple, 2-4tuple\n");
+#endif /* MV_ETH_PNC_LB */
+
+#ifdef MV_ETH_PNC_AGING
+	off += mvOsSPrintf(buf+off, " age_clear       - clear aging counter for tcam entry <a>\n");
+	off += mvOsSPrintf(buf+off, " age_cntr        - show aging counter for tcam entry <a>\n");
+#endif /* MV_ETH_PNC_AGING */
+
+	off += mvOsSPrintf(buf+off, "echo a b > <file>\n");
+	off += mvOsSPrintf(buf+off, " t_offset_byte   - on offset <a> match value <b>\n");
+	off += mvOsSPrintf(buf+off, " t_offset_mask   - on offset <a> use mask <b>\n");
+	off += mvOsSPrintf(buf+off, " t_port          - match port value <a> with mask <b>\n");
+	off += mvOsSPrintf(buf+off, " t_ainfo         - match ainfo value <a> with mask <b>\n");
+	off += mvOsSPrintf(buf+off, " s_shift_update  - fill sram shift index <a> with value <b>\n");
+	off += mvOsSPrintf(buf+off, " s_rinfo         - set rinfo value <a> with mask <b>\n");
+	off += mvOsSPrintf(buf+off, " s_ainfo         - set ainfo value <a> with mask <b>\n");
+	off += mvOsSPrintf(buf+off, " s_flowid        - fill sram flowid nibbles <b> from value <a>\n");
+	off += mvOsSPrintf(buf+off, " s_flowid_part   - fill sram flowid part <b> with value <a>\n");
+
+#ifdef MV_ETH_PNC_NEW
+	off += mvOsSPrintf(buf+off, " s_rinfo_extra   - set 2 bits value <a> to extra result info offset <b>\n");
+#endif /* MV_ETH_PNC_NEW */
+
+#ifdef MV_ETH_PNC_LB
+	off += mvOsSPrintf(buf+off, " lb_rxq          - set rxq <b> for hash value <a>\n");
+#endif /* MV_ETH_PNC_LB */
+
+#ifdef MV_ETH_PNC_AGING
+	off += mvOsSPrintf(buf+off, " age_gr_set      - set group <b> of aging counter for tcam entry <a>\n");
+#endif /* MV_ETH_PNC_AGING */
+
+	return off;
+}
+
+static ssize_t tcam_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	const char   *name = attr->attr.name;
+	unsigned int v, m;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "t_port")) {
+		tcam_sw_get_port(&te, &v, &m);
+		return mvOsSPrintf(buf, "value:0x%x mask:0x%x\n", v, m);
+	} else if (!strcmp(name, "t_lookup")) {
+		tcam_sw_get_lookup(&te, &v, &m);
+		return mvOsSPrintf(buf, "value:0x%x mask:0x%x\n", v, m);
+	} else if (!strcmp(name, "sw_dump"))
+		return tcam_sw_dump(&te, buf);
+	else if (!strcmp(name, "hw_dump"))
+		return tcam_hw_dump(0);
+	else if (!strcmp(name, "hw_dump_all"))
+		return tcam_hw_dump(1);
+	else if (!strcmp(name, "hw_regs"))
+		mvNetaPncRegs();
+	else if (!strcmp(name, "hw_hits"))
+		return tcam_hw_hits(buf);
+#ifdef MV_ETH_PNC_AGING
+	else if (!strcmp(name, "age_dump"))
+		mvPncAgingDump(0);
+	else if (!strcmp(name, "age_dump_all"))
+		mvPncAgingDump(1);
+	else if (!strcmp(name, "age_scan"))
+		mvPncAgingScannerDump();
+	else if (!strcmp(name, "age_reset"))
+		mvPncAgingReset();
+#endif /* MV_ETH_PNC_AGING */
+#ifdef MV_ETH_PNC_LB
+	else if (!strcmp(name, "lb_dump"))
+		mvPncLbDump();
+#endif /* MV_ETH_PNC_LB */
+	else if (!strcmp(name, "help"))
+		return tcam_help(buf);
+
+	return 0;
+}
+static ssize_t tcam_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char    *name = attr->attr.name;
+	unsigned int  err = 0, a = 0, b = 0;
+	unsigned long flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%x %x", &a, &b);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "hw_write"))
+		tcam_hw_write(&te, a);
+	else if (!strcmp(name, "hw_read"))
+		tcam_hw_read(&te, a);
+	else if (!strcmp(name, "hw_debug"))
+		tcam_hw_debug(a);
+	else if (!strcmp(name, "hw_inv"))
+		tcam_hw_inv(a);
+	else if (!strcmp(name, "hw_inv_all"))
+		tcam_hw_inv_all();
+	else if (!strcmp(name, "hw_hits"))
+		tcam_hw_record(a);
+#ifdef MV_ETH_PNC_LB
+	else if (!strcmp(name, "lb_ip4"))
+		mvPncLbModeIp4(a);
+	else if (!strcmp(name, "lb_ip6"))
+		mvPncLbModeIp6(a);
+	else if (!strcmp(name, "lb_l4"))
+		mvPncLbModeL4(a);
+#endif /* MV_ETH_PNC_LB */
+#ifdef MV_ETH_PNC_AGING
+	else if (!strcmp(name, "age_clear"))
+		mvPncAgingCntrClear(a);
+	else if (!strcmp(name, "age_cntr")) {
+		b = mvPncAgingCntrRead(a);
+		printk(KERN_INFO "tid=%d: age_cntr = 0x%08x\n", a, b);
+	}
+#endif /* MV_ETH_PNC_AGING */
+	else if (!strcmp(name, "sw_clear"))
+		tcam_sw_clear(&te);
+	else if (!strcmp(name, "sw_text")) {
+		/* Remove last byte (new line) from the buffer */
+		int  len = strlen(buf);
+		char *temp = mvOsMalloc(len + 1);
+
+		strncpy(temp, buf, len-1);
+		temp[len-1] = 0;
+		tcam_sw_text(&te, temp);
+		mvOsFree(temp);
+	} else if (!strcmp(name, "t_port"))
+		tcam_sw_set_port(&te, a, b);
+	else if (!strcmp(name, "t_lookup"))
+		tcam_sw_set_lookup(&te, a);
+	else if (!strcmp(name, "t_ainfo_0"))
+		tcam_sw_set_ainfo(&te, 0<<a, 1<<a);
+	else if (!strcmp(name, "t_ainfo_1"))
+		tcam_sw_set_ainfo(&te, 1<<a, 1<<a);
+	else if (!strcmp(name, "t_ainfo"))
+		tcam_sw_set_ainfo(&te, a, b);
+	else if (!strcmp(name, "t_offset_byte"))
+		tcam_sw_set_byte(&te, a, b);
+	else if (!strcmp(name, "t_offset_mask"))
+		tcam_sw_set_mask(&te, a, b);
+	else if (!strcmp(name, "s_lookup"))
+		sram_sw_set_next_lookup(&te, a);
+	else if (!strcmp(name, "s_ainfo"))
+		sram_sw_set_ainfo(&te, a, b);
+	else if (!strcmp(name, "s_rinfo"))
+		sram_sw_set_rinfo(&te, a, b);
+	else if (!strcmp(name, "s_lookup_done"))
+		sram_sw_set_lookup_done(&te, a);
+	else if (!strcmp(name, "s_next_lookup_shift"))
+		sram_sw_set_next_lookup_shift(&te, a);
+	else if (!strcmp(name, "s_rxq"))
+		sram_sw_set_rxq(&te, a, b);
+	else if (!strcmp(name, "s_shift_update"))
+		sram_sw_set_shift_update(&te, a, b);
+#ifdef MV_ETH_PNC_NEW
+	else if (!strcmp(name, "s_rinfo_extra"))
+		sram_sw_set_rinfo_extra(&te, a << (b & ~1));
+#endif /* MV_ETH_PNC_NEW */
+	else if (!strcmp(name, "s_flowid"))
+		sram_sw_set_flowid(&te, a, b);
+	else if (!strcmp(name, "s_flowid_part"))
+		sram_sw_set_flowid_partial(&te, a, b);
+#ifdef MV_ETH_PNC_AGING
+	else if (!strcmp(name, "age_gr_set"))
+		mvPncAgingCntrGroupSet(a, b);
+#endif /* MV_ETH_PNC_AGING */
+#ifdef MV_ETH_PNC_LB
+	else if (!strcmp(name, "lb_rxq"))
+		err = mvPncLbRxqSet(a, b);
+#endif /* MV_ETH_PNC_LB */
+	else {
+		err = 1;
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	}
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: <%s>, error %d\n", __func__, attr->attr.name, err);
+
+	return err ? -EINVAL : len;
+}
+
+#ifdef MV_ETH_PNC_AGING
+static DEVICE_ATTR(age_dump,     S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(age_dump_all, S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(age_scan,     S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(age_reset,    S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(age_clear,    S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(age_cntr,     S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(age_gr_set,   S_IWUSR, tcam_show, tcam_store);
+#endif /* MV_ETH_PNC_AGING */
+
+#ifdef MV_ETH_PNC_NEW
+static DEVICE_ATTR(s_rinfo_extra, S_IWUSR, tcam_show, tcam_store);
+#endif
+
+static DEVICE_ATTR(hw_write,    S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(hw_read,     S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(hw_debug,    S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(hw_inv,      S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(hw_inv_all,  S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(hw_dump,     S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(hw_dump_all, S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(hw_regs,     S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(hw_hits,     S_IRUSR | S_IWUSR, tcam_show, tcam_store);
+
+#ifdef MV_ETH_PNC_LB
+static DEVICE_ATTR(lb_dump,     S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(lb_rxq,      S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(lb_ip4,      S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(lb_ip6,      S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(lb_l4,       S_IWUSR, tcam_show, tcam_store);
+#endif /* MV_ETH_PNC_LB */
+
+static DEVICE_ATTR(sw_dump,     S_IRUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(sw_clear,    S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(sw_text,     S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(t_port,      S_IRUSR | S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(t_lookup,    S_IRUSR | S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(t_ainfo_0,   S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(t_ainfo_1,   S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(t_ainfo,     S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(t_offset_byte, S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(t_offset_mask, S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_lookup,    S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_ainfo,     S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_lookup_done, S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_next_lookup_shift, S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_rxq,       S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_shift_update, S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_rinfo,     S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_flowid, 	S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(s_flowid_part, S_IWUSR, tcam_show, tcam_store);
+static DEVICE_ATTR(help,        S_IRUSR, tcam_show, tcam_store);
+
+static struct attribute *pnc_attrs[] = {
+#ifdef MV_ETH_PNC_AGING
+    &dev_attr_age_dump.attr,
+    &dev_attr_age_dump_all.attr,
+    &dev_attr_age_scan.attr,
+    &dev_attr_age_reset.attr,
+    &dev_attr_age_clear.attr,
+    &dev_attr_age_cntr.attr,
+    &dev_attr_age_gr_set.attr,
+#endif /* MV_ETH_PNC_AGING */
+
+#ifdef MV_ETH_PNC_NEW
+    &dev_attr_s_rinfo_extra.attr,
+#endif /* MV_ETH_PNC_NEW */
+
+    &dev_attr_hw_write.attr,
+    &dev_attr_hw_read.attr,
+    &dev_attr_hw_debug.attr,
+    &dev_attr_hw_inv.attr,
+    &dev_attr_hw_inv_all.attr,
+    &dev_attr_hw_dump.attr,
+    &dev_attr_hw_dump_all.attr,
+    &dev_attr_hw_regs.attr,
+    &dev_attr_hw_hits.attr,
+
+#ifdef MV_ETH_PNC_LB
+    &dev_attr_lb_dump.attr,
+	&dev_attr_lb_rxq.attr,
+	&dev_attr_lb_ip4.attr,
+	&dev_attr_lb_ip6.attr,
+	&dev_attr_lb_l4.attr,
+#endif /* MV_ETH_PNC_LB */
+
+    &dev_attr_sw_dump.attr,
+    &dev_attr_sw_clear.attr,
+    &dev_attr_sw_text.attr,
+    &dev_attr_t_port.attr,
+    &dev_attr_t_lookup.attr,
+    &dev_attr_t_ainfo_0.attr,
+    &dev_attr_t_ainfo.attr,
+    &dev_attr_t_ainfo_1.attr,
+    &dev_attr_t_offset_byte.attr,
+    &dev_attr_t_offset_mask.attr,
+    &dev_attr_s_lookup.attr,
+    &dev_attr_s_ainfo.attr,
+    &dev_attr_s_lookup_done.attr,
+    &dev_attr_s_next_lookup_shift.attr,
+    &dev_attr_s_rxq.attr,
+    &dev_attr_s_shift_update.attr,
+    &dev_attr_s_rinfo.attr,
+    &dev_attr_s_flowid.attr,
+    &dev_attr_s_flowid_part.attr,
+    &dev_attr_help.attr,
+    NULL
+};
+
+static struct attribute_group pnc_group = {
+	.name = "pnc",
+	.attrs = pnc_attrs,
+};
+
+int __devinit pnc_sysfs_init(void)
+{
+	int err;
+	struct device *pd;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	if (!pd) {
+		platform_device_register_simple("neta", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR "%s: cannot find neta device\n", __func__);
+		pd = &platform_bus;
+	}
+
+	err = sysfs_create_group(&pd->kobj, &pnc_group);
+	if (err) {
+		printk(KERN_INFO "sysfs group failed %d\n", err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+module_init(pnc_sysfs_init);
+
+MODULE_AUTHOR("Kostya Belezko");
+MODULE_DESCRIPTION("PNC for Marvell NetA MV65xxx");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pnc/wol_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pnc/wol_sysfs.c
new file mode 100755
index 0000000..cb153df
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/pnc/wol_sysfs.c
@@ -0,0 +1,201 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "mvOs.h"
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#include "gbe/mvNeta.h"
+#include "pnc/mvPnc.h"
+
+#include "net_dev/mv_netdev.h"
+
+static char	wol_data[MV_PNC_TOTAL_DATA_SIZE];
+static int  wol_data_size = 0;
+static char	wol_mask[MV_PNC_TOTAL_DATA_SIZE];
+static int  wol_mask_size = 0;
+
+extern void mv_eth_wol_wakeup(int port);
+extern int mv_eth_wol_sleep(int port);
+
+static ssize_t wol_help(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "cat                  dump_all      - dump all wol rules\n");
+	off += sprintf(buf+off, "echo idx           > dump          - dump rule <idx>\n");
+	off += sprintf(buf+off, "echo port          > sleep         - enter WoL mode on <port>\n");
+	off += sprintf(buf+off, "echo port          > wakeup        - exit WoL mode on <port>\n");
+	off += sprintf(buf+off, "echo str           > data          - set data string\n");
+	off += sprintf(buf+off, "echo str           > mask          - set mask string\n");
+	off += sprintf(buf+off, "echo port          > add           - add new rule with <data> and <mask> on <port>\n");
+	off += sprintf(buf+off, "echo idx           > del           - delete existing WoL rule <idx>\n");
+	off += sprintf(buf+off, "echo port          > del_all       - delete all WoL rules added to <port>\n");
+
+	return off;
+}
+
+static ssize_t wol_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	const char   *name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "dump_all"))
+		mv_pnc_wol_dump();
+	else if (!strcmp(name, "help"))
+		return wol_help(buf);
+
+	return 0;
+}
+
+static ssize_t wol_store(struct device *dev,
+				   struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char    *name = attr->attr.name;
+	unsigned int  p, size, err = 0;
+	unsigned long flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%d", &p);
+
+	local_irq_save(flags);
+
+	if (!strcmp(name, "sleep"))
+		mv_eth_wol_sleep(p);
+	else if (!strcmp(name, "wakeup"))
+		mv_eth_wol_wakeup(p);
+	else if (!strcmp(name, "dump")) {
+		if (mv_pnc_wol_rule_dump(p))
+			printk(KERN_INFO "WoL rule #%d doesn't exist\n", p);
+	} else if (!strcmp(name, "data")) {
+		memset(wol_data, 0, sizeof(wol_data));
+		size = strlen(buf) / 2;
+		if (size > sizeof(wol_data))
+			size = sizeof(wol_data);
+		mvHexToBin(buf, wol_data, size);
+		wol_data_size = size;
+	} else if (!strcmp(name, "mask")) {
+		memset(wol_mask, 0, sizeof(wol_mask));
+		size = strlen(buf) / 2;
+		if (size > sizeof(wol_mask))
+			size = sizeof(wol_mask);
+		mvHexToBin(buf, wol_mask, size);
+		wol_mask_size = size;
+	} else if (!strcmp(name, "add")) {
+		int idx;
+		idx = mv_pnc_wol_rule_set(p, wol_data, wol_mask, MV_MIN(wol_data_size, wol_mask_size));
+		if (idx < 0)
+			err = 1;
+	} else if (!strcmp(name, "del")) {
+		err = mv_pnc_wol_rule_del(p);
+	} else if (!strcmp(name, "del_all")) {
+		err = mv_pnc_wol_rule_del_all(p);
+	} else {
+		err = 1;
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	}
+	local_irq_restore(flags);
+
+	if (err)
+		printk(KERN_ERR "%s: <%s>, error %d\n", __func__, attr->attr.name, err);
+
+	return err ? -EINVAL : len;
+}
+
+static DEVICE_ATTR(help,        S_IRUSR, wol_show, wol_store);
+static DEVICE_ATTR(dump_all,    S_IRUSR, wol_show, wol_store);
+static DEVICE_ATTR(dump,        S_IWUSR, wol_show, wol_store);
+static DEVICE_ATTR(data,        S_IWUSR, wol_show, wol_store);
+static DEVICE_ATTR(mask,        S_IWUSR, wol_show, wol_store);
+static DEVICE_ATTR(add,         S_IWUSR, wol_show, wol_store);
+static DEVICE_ATTR(del,         S_IWUSR, wol_show, wol_store);
+static DEVICE_ATTR(del_all,     S_IWUSR, wol_show, wol_store);
+static DEVICE_ATTR(sleep,       S_IWUSR, wol_show, wol_store);
+static DEVICE_ATTR(wakeup,      S_IWUSR, wol_show, wol_store);
+
+static struct attribute *wol_attrs[] = {
+    &dev_attr_help.attr,
+    &dev_attr_dump_all.attr,
+    &dev_attr_dump.attr,
+    &dev_attr_data.attr,
+    &dev_attr_mask.attr,
+    &dev_attr_add.attr,
+    &dev_attr_del.attr,
+    &dev_attr_del_all.attr,
+    &dev_attr_sleep.attr,
+    &dev_attr_wakeup.attr,
+    NULL
+};
+
+static struct attribute_group wol_group = {
+	.name = "wol",
+	.attrs = wol_attrs,
+};
+
+int __devinit wol_sysfs_init(void)
+{
+	int err;
+	struct device *pd;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	if (!pd) {
+		platform_device_register_simple("neta", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR "%s: cannot find neta device\n", __func__);
+		pd = &platform_bus;
+	}
+
+	err = sysfs_create_group(&pd->kobj, &wol_group);
+	if (err) {
+		printk(KERN_INFO "sysfs group failed %d\n", err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+module_init(wol_sysfs_init);
+
+MODULE_AUTHOR("Dmitri Epshtein");
+MODULE_DESCRIPTION("WoL for Marvell NetA");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/Kconfig
new file mode 100755
index 0000000..a67f8c2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/Kconfig
@@ -0,0 +1,320 @@
+config MV_ETH_PORTS_NUM
+	int "Number of Marvell Giga Ethernet controllers"
+	depends on MV_ETH_LEGACY
+	default 1 
+
+menu "Network Interface Configuration"
+
+config  OVERRIDE_ETH_CMDLINE
+	bool "Override command line definitions for SoC Networking"
+	default n
+	---help---
+	Choosing this option will override MAC address and MTU definition of kernel command line.
+	The GbE driver will use the setting from kernel config
+
+config  MV_ETH_0_MTU
+	int "Giga port #0 MTU value"
+	depends on (MV_ETH_PORTS_NUM != 0)
+ 	default 1500
+        ---help---
+	Default MTU value for Marvell Giga port #0
+
+config  MV_ETH_0_MACADDR
+        string "Giga port #0 MAC Address"
+        depends on (MV_ETH_PORTS_NUM != 0)
+        default "00:00:00:00:00:80"
+        ---help---
+        Default MAC address for Marvell Giga port #0 
+
+config  MV_ETH_1_MTU
+        int "Giga port #1 MTU value"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1)
+        default 1500
+        ---help---
+	Default MTU value for Marvell Giga port #1
+
+config  MV_ETH_1_MACADDR
+        string "Giga port #1 MAC Address"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1)
+        default "00:00:00:00:00:81"
+        ---help---
+        Default MAC address for Marvell Giga port #1
+
+config  MV_ETH_2_MTU
+        int "Giga port #2 MTU value"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2)
+        default 1500
+        ---help---
+        Default MTU value for Marvell Giga port #2
+
+config  MV_ETH_2_MACADDR
+        string "Giga port #2 MAC Address"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2)
+        default "00:00:00:00:00:82"
+        ---help---
+        Default MAC address for Marvell Giga port #2
+
+config  MV_ETH_3_MTU
+        int "Giga port #3 MTU value"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2) && (MV_ETH_PORTS_NUM != 3)
+        default 1500
+        ---help---
+        Default MTU value for Marvell Giga port #3
+
+config  MV_ETH_3_MACADDR
+        string "Giga port #3 MAC Address"
+        depends on (MV_ETH_PORTS_NUM != 0) && (MV_ETH_PORTS_NUM != 1) && (MV_ETH_PORTS_NUM != 2) && (MV_ETH_PORTS_NUM != 3)
+        default "00:00:00:00:00:83"
+        ---help---
+        Default MAC address for Marvell Giga port #3
+
+endmenu
+
+menu "Rx/Tx Queue Configuration"
+
+config  MV_ETH_RXQ
+        int "Number of RX queues"
+        default 1
+        ---help---
+          Multiple RX queue support.
+
+config  MV_ETH_TXQ
+        int "Number of TX queues"
+        default 1
+        ---help---
+          Multiple TX queue support.
+
+config MV_ETH_NUM_OF_RX_DESCR
+	int "Number of Rx descriptors"
+	depends on (MV_ETH_PORTS_NUM != 0)
+	default 128
+        ---help---
+	The number of Rx descriptors in each Rx queue.
+
+config MV_ETH_NUM_OF_TX_DESCR
+	int "Number of Tx descriptors"
+	depends on (MV_ETH_PORTS_NUM != 0)
+	default 532
+        ---help---
+	The number of Tx descriptors in each Tx queue.
+
+endmenu
+
+menu "TCP/UDP Offloading"
+
+config  MV_ETH_TSO
+        bool "TSO Support for Marvell network interface"
+	default y
+        ---help---
+        Adds TSO support for TCP segmentation offload on Marvell network interface.
+
+config  MV_ETH_UFO
+        bool "UFO Support for Marvell network interface"
+        ---help---
+        Adds UFO support for transmit UDP buffers larger than MTU size on 
+        Marvell network interface.
+        UFO stands for UDP Fragmentation Offload
+endmenu
+
+menu "Control and Statistics"
+
+config  MV_ETH_TOOL
+	bool "Support ethtool controls"
+	default y
+	---help---
+	Support kernel's SIOCETHTOOL for ethtool utility
+
+config  MV_ETH_PROC
+	bool "Support eth proc FS "
+	default y
+	---help---
+	  Use mv_eth_tool to control Marvell network interface driver.
+
+config  MV_ETH_STATS_ERROR
+        bool "Collect error statistics"
+	---help---
+	Marvell network interface driver collect minimal number of statistics. 
+	Only for error conditions. Can be displayed using mv_eth_tool.
+
+config  MV_ETH_STATS_INFO
+        bool "Collect event statistics"
+        ---help---
+	Marvell network interface driver collect event statistics. 
+	Provide more information about driver functionality and almost doesn't 
+	effect performance. Can be displayed using mv_eth_tool.
+
+config  MV_ETH_STATS_DEBUG
+        bool "Collect debug statistics"
+        ---help---
+	Marvell network interface driver collect a lot of statistics. 
+	Used for Debug mode. Decrease performance. Can be displayed using mv_eth_tool.
+
+config  MV_LINUX_COUNTERS_DISABLE
+	bool "Disable collection of SNMP statistics and Netfilter Contract statistics"
+	default n
+	---help---
+	Disable collection of SNMP statistics and Netfilter Contract statistics to improve performance.
+
+endmenu
+
+menu "Advanced Features"
+
+config  MV_ETH_TIMER_PERIOD
+        int "Periodical timer period"
+        default 10
+        ---help---
+          Periodical timer period for clenup in [msec].
+
+config	MV_ETH_SKB_REUSE
+	bool "Try to reuse SKB"
+	default y
+	---help---
+	  Reuse SKB from TX to RX
+
+config MV_ETH_SKB_REUSE_DEF
+        depends on MV_ETH_SKB_REUSE
+        int "Default value for SKB reuse:  0 - disable, 1 - enable"
+        default 0
+        ---help---
+
+config  NET_SKB_HEADROOM
+        int "SKB headroom size"
+        default 64
+        ---help---
+          Customize SKB headroom size. Must be power of 2.
+
+config  NET_SKB_RECYCLE
+        bool "Try to recycle SKB"
+        default y
+        ---help---
+          Recycle SKB via callback in 'struct sk_buff'
+
+config NET_SKB_RECYCLE_DEF
+        depends on NET_SKB_RECYCLE
+        int "Default value for SKB recycle:  0 - disable, 1 - enable"
+        default 0
+        ---help---
+
+config  MV_ETH_NFP
+        tristate "Use Network Fast Processing (NFP)"
+	default y
+        ---help---
+        Choosing this option will include NFP support in the image.
+
+config MV_ETH_NFP_DEF
+        depends on MV_ETH_NFP
+        int "Default value for NFP:  0 - disable, 1 - enable"
+        default 0
+        ---help---
+
+config MV_ETH_NFP_AGING_TIMER
+        int "NFP aging timer interval"
+        depends on MV_ETH_NFP
+        default 15
+        ---help---
+        The NFP aging mechanism timer interval. If unsure, leave default value.
+
+config  MV_ETH_NFP_TOS
+        bool "Support ToS on NFP routing path"
+	depends on MV_ETH_NFP && IP_NF_TARGET_TOS
+        ---help---
+        Choosing this option will include NFP ToS support in the image.
+
+config MV_ETH_NFP_FIB
+        bool "Support NFP routing"
+        default y
+        depends on MV_ETH_NFP
+        ---help---
+        Choosing this option will enable NFP routing support.
+
+config MV_ETH_NFP_NAT
+        bool "Support NFP NAT"
+        depends on MV_ETH_NFP_FIB && (NF_CONNTRACK_ENABLED || NF_CONNTRACK_IPV4)
+        ---help---
+        Choosing this option will enable NFP NAT support.
+
+config MV_ETH_NFP_FDB
+	bool "Support NFP Bridging"
+	depends on MV_ETH_NFP && BRIDGE
+	default n
+	 ---help---
+	Choosing this option will enable NFP Bridging.
+
+config MV_ETH_NFP_PPP
+        bool "Support NFP PPPoE"
+        depends on MV_ETH_NFP && PPPOE
+        default n
+         ---help---
+        Choosing this option will enable NFP PPPoE protocol.
+
+config MV_ETH_NFP_SEC
+	bool "Support NFP Ipsec"
+        depends on MV_ETH_NFP && !MV_CESA_OCF && !MV_CESA_TEST
+        default n
+         ---help---
+        Choosing this option will enable NFP IPsec protocol.
+
+config	MV_NFP_SEC_5TUPLE_KEY_SUPPORT 
+	bool "Support 5 tuple key search match"
+        depends on MV_ETH_NFP_SEC
+        default y
+         ---help---
+        Choosing this option will enable 5 tuple key search match support.
+
+config MV_ETH_NFP_SEC_HUB
+	bool "Support hub and spoke vpn"
+	depends on MV_ETH_NFP_SEC
+	default n
+	---help---
+	Choosing this option will enable hub-and-spoke vpn with NFP.
+
+config  MV_NFP_STATS
+        bool "Collect NFP statistics"
+	depends on MV_ETH_NFP
+        default n
+        ---help---
+        Collect NFP statistics. Can be displayed using mv_eth_tool.
+
+endmenu
+
+config MV_GATEWAY
+        bool "Gateway support"
+	depends on MV_ETH_LEGACY
+        ---help---
+	Choose this option to support Gigabit Ethernet Controller connected to 
+        on-board QuarterDeck switch family
+
+if MV_GATEWAY
+
+menu "Gateway Interface Configuration"
+
+config  MV_GTW_CONFIG
+	string "Network interface configuration"
+	default "(00:11:66:11:66:11,0)(00:22:77:22:77:22,1:2:3:4),mtu=1500"
+	---help---
+	 Set the network interface configuration. For each interface, define the interface 
+	 name, MAC address and participating ports, at the end (optionally) set the 
+         interfaces MTU. For example, the default configuration defines two interfaces, 
+         eth0 and eth1, and sets the MTU to 1500.
+
+endmenu
+
+menu "Gateway Features"
+
+config  MV_GTW_IGMP
+        bool "L2 IGMP Snooping support"
+        default y
+        ---help---
+          Support L2 IGMP snooping at the switch level, i.e. directing L3 routed multicast
+          stream to the specific L2 port which originally received an IGMP Join message,
+          instead of fluding all VLAN ports.
+
+config  MV_GTW_LINK_STATUS
+	bool "Link status change indications"
+	default y
+	---help---
+	  Support Phy link status change indications.
+
+endmenu
+
+endif # MV_GATEWAY
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/Makefile
new file mode 100755
index 0000000..6d1028b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the Marvell Gigabit Ethernet driver
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+obj-$(CONFIG_MV_ETHERNET) += mv_netdev.o mv_ethernet.o
+obj-$(CONFIG_MV_ETH_PROC) += mv_eth_proc.o
+obj-$(CONFIG_MV_GATEWAY) +=  mv_gateway.o
+obj-$(CONFIG_MV_GTW_IGMP) += mv_gtw_igmp.o
+obj-$(CONFIG_MV_ETH_TOOL) += mv_eth_tool.o
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_proc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_proc.c
new file mode 100755
index 0000000..5838b50
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_proc.c
@@ -0,0 +1,571 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "eth/gbe/mvEthGbe.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mv_eth_proc.h"
+
+#ifdef CONFIG_MV_ETH_NFP
+#include "../nfp_mgr/mv_nfp_mgr.h"
+#endif
+
+#include "mv_netdev.h"
+
+//#define MV_DEBUG
+#ifdef MV_DEBUG
+#define DP printk
+#else
+#define DP(fmt,args...)
+#endif
+
+
+/* global variables from 'regdump' */
+static struct proc_dir_entry *mv_eth_tool;
+
+static unsigned int port = 0, q = 0, weight = 0, status = 0, mac[6] = {0,};
+static unsigned int policy =0, command = 0, packet = 0;
+static unsigned int value = 0;
+
+#ifdef CONFIG_MV_ETH_NFP
+static unsigned int  dip, sip, inport, outport;
+static unsigned int  da[6] = {0,}, sa[6] = {0,};
+static unsigned int  db_type;
+#endif /* CONFIG_MV_ETH_NFP */
+
+void run_com_srq(void) 
+{
+    void* port_hndl = mvEthPortHndlGet(port);
+
+    if(port_hndl == NULL)
+        return;
+
+    if(q >= MV_ETH_RX_Q_NUM)
+	    q = -1;
+
+    switch(packet) {
+	case PT_BPDU:
+		mvEthBpduRxQueue(port_hndl, q);
+		break;
+	case PT_ARP:
+		mvEthArpRxQueue(port_hndl, q);
+		break;
+	case PT_TCP:
+		mvEthTcpRxQueue(port_hndl, q);
+		break;
+	case PT_UDP:
+		mvEthUdpRxQueue(port_hndl, q);
+		break;
+	default:
+		printk("eth proc unknown packet type.\n");	
+    }
+	
+}
+
+extern void    		ethMcastAdd(int port, char* macStr, int queue);
+void run_com_sq(void) {
+
+    char mac_addr[20];
+
+    if(q >= MV_ETH_RX_Q_NUM)
+	    q = -1;
+    
+    sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
+    ethMcastAdd(port, mac_addr, q);
+}
+
+extern void    	ethPortStatus (int port);
+extern void    	ethPortQueues( int port, int rxQueue, int txQueue, int mode);
+extern void    	ethPortMcast(int port);
+extern void    	ethPortUcastShow(int port);
+extern void    	ethPortRegs(int port);
+extern void     ethTxPolicyRegs(int port);
+extern void    	ethPortCounters(int port);
+extern void 	ethPortRmonCounters(int port);
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+extern void    eth_remote_port_status_print(int port, int mode);
+#endif
+
+void run_com_stats(void) {
+	printk("\n\n#########################################################################################\n\n");
+	switch(status) {
+		case STS_PORT:
+			printk("  PORT %d: GET ETH STATUS\n\n",port);
+            mv_eth_status_print(port);
+			ethPortStatus(port);
+			break;
+
+        case STS_PORT_MAC:
+            ethPortUcastShow(port);
+			ethPortMcast(port);
+            break;
+
+		case STS_PORT_Q:
+			printk("  PORT %d: GET ETH STATUS ON Q %d\n\n",port,q);
+			ethPortQueues(port, q, q, 1);
+			break;
+
+#if (MV_ETH_RX_Q_NUM > 1)
+		case STS_PORT_RXP:
+			printk("  PORT %d: GET ETH RX POLICY STATUS\n\n",port);
+			printk("Not supported\n");
+			break;
+#endif /* MV_ETH_RX_Q_NUM > 1 */
+
+		case STS_PORT_TOS_MAP:
+			mv_eth_tos_map_show(port);
+			break;
+
+		case STS_PORT_TXP:
+			printk("  PORT %d: GET ETH TX POLICY STATUS\n\n",port);
+			ethTxPolicyRegs(port);
+			break;
+
+		case STS_PORT_REGS:
+			printk("  PORT %d: GET ETH PORT REGS STATUS\n\n",port);
+			ethPortRegs(port);
+			break;
+
+		case STS_PORT_MIB:
+			ethPortCounters(port);
+			ethPortRmonCounters(port);	
+			break;
+
+		case STS_PORT_STATS:
+			printk("  PORT %d: GET ETH STATISTIC STATUS\n\n",port);
+			mv_eth_stats_print(port);
+			break;
+
+        case STS_NETDEV:
+			mv_eth_netdev_print(port);
+            break;
+
+#ifdef CONFIG_MV_ETH_NFP
+		case STS_PORT_NFP_STATS:
+			printk("  PORT %d: NFP statistics\n\n",port);
+			mv_eth_nfp_stats_print(port);
+			break;
+#endif /* CONFIG_MV_ETH_NFP */
+
+#ifdef CONFIG_MV_GATEWAY
+        case STS_SWITCH_STATS:
+            mv_gtw_switch_stats(port);
+            break;
+#endif /* CONFIG_MV_GATEWAY */
+
+		default:
+			printk(" Unknown status command \n");
+	}
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+    eth_remote_port_status_print(port, status);
+#endif
+}
+
+int run_eth_com(const char *buffer) {
+
+    int scan_count;
+    scan_count = sscanf(buffer, ETH_CMD_STRING, ETH_SCANF_LIST);
+    if( scan_count != ETH_LIST_LEN) {
+	printk("eth command bad format %x != %x\n", scan_count, ETH_LIST_LEN );
+	return 1;
+    }
+    switch(command) {
+
+        case COM_TXDONE_Q:
+            mv_eth_tx_done_quota = value;
+            break;
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+        case COM_SKB_REUSE:
+            eth_skb_reuse_enable = value;
+            break;
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+        case COM_SKB_RECYCLE:
+            eth_skb_recycle_enable = value;
+	    break;
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+#ifdef CONFIG_MV_ETH_NFP
+        case COM_NFP:
+	    if (value) 
+	    {
+		printk("Enabling NFP\n");
+		fp_mgr_enable();
+	    }
+	    else
+	    {
+		printk("Disabling NFP\n");
+		fp_mgr_disable();
+	    }
+            break;
+#endif /* CONFIG_MV_ETH_NFP */
+
+	default:
+            printk(" Unknown ETH command \n");
+    }
+    return 0;
+}
+
+/* Giga Queue commands */
+int run_port_queue_cmd(const char *buffer) {
+
+        int scan_count;
+
+        scan_count = sscanf(buffer, QUEUE_CMD_STRING, QUEUE_SCANF_LIST);
+
+        if( scan_count != QUEUE_LIST_LEN) {
+                printk("eth port/queue command bad format %x != %x\n", scan_count, QUEUE_LIST_LEN );
+                return 1;
+        }
+
+        switch(command) {
+		case COM_TOS_MAP:
+			mv_eth_tos_map_set(port, value, q);
+			break;
+	
+		default:
+			printk(" Unknown port/queue command \n");
+	}
+	return 0;
+}
+
+/* Giga Port commands */
+int run_port_com(const char *buffer) {
+
+	int scan_count;
+    void*   port_hndl;
+
+	scan_count = sscanf(buffer, PORT_CMD_STRING, PORT_SCANF_LIST);
+    
+	if( scan_count != PORT_LIST_LEN) {
+		printk("eth port command bad format %x != %x\n", scan_count, PORT_LIST_LEN );
+		return 1;
+	}
+    if( (port < 0) || (port > mvCtrlEthMaxPortGet()) )
+        return 1;
+
+    port_hndl = mvEthPortHndlGet(port);
+    if(port_hndl == NULL)
+        return 1;
+
+    	switch(command) {
+        	case COM_RX_COAL:
+            	mvEthRxCoalSet(mvEthPortHndlGet(port), value);
+            	break;
+
+        	case COM_TX_COAL:
+            	mvEthTxCoalSet(mvEthPortHndlGet(port), value);
+        	break;
+
+#ifdef ETH_MV_TX_EN
+            case COM_TX_EN:
+                if(value > CONFIG_MV_ETH_NUM_OF_RX_DESCR)
+            {
+                    printk("Eth TX_EN command bad param: value=%d\n", value);
+                return 1;
+            }
+
+                eth_tx_en_config(port, value);
+            break;
+#endif /* ETH_MV_TX_EN */
+
+#if (MV_ETH_VERSION >= 4)
+        	case COM_EJP_MODE:
+            		mvEthEjpModeSet(mvEthPortHndlGet(port), value);
+            	break;
+#endif /* (MV_ETH_VERSION >= 4) */
+			case COM_LRO:
+				mv_eth_set_lro(port, value);
+				break;
+			case COM_LRO_DESC:
+				mv_eth_set_lro_desc(port, value);
+				break;
+
+			case COM_TX_NOQUEUE:
+				mv_eth_set_noqueue(port, value);
+			break;
+
+  		default:
+			printk(" Unknown port command \n");
+    	}
+   	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_NFP
+int run_ip_rule_set_com(const char *buffer)
+{
+    int scan_count, i;
+    MV_FP_RULE  ip_rule;
+    MV_STATUS   status = MV_OK;
+
+    scan_count = sscanf(buffer, IP_RULE_STRING, IP_RULE_SCANF_LIST);
+
+    if( scan_count != IP_RULE_LIST_LEN) {
+	printk("eth proc bad format %x != %x\n", scan_count, IP_RULE_LIST_LEN);
+	return 1;
+    }
+    memset(&ip_rule, 0, sizeof(ip_rule));
+    
+    printk("run_ip_rule_set_com: dip=%08x, sip=%08x, inport=%d, outport=%d\n", 
+            dip, sip, inport, outport);
+
+    ip_rule.routingInfo.dstIp = MV_32BIT_BE(dip);
+    ip_rule.routingInfo.srcIp = MV_32BIT_BE(sip);
+    ip_rule.routingInfo.defGtwIp = MV_32BIT_BE(dip);
+    ip_rule.routingInfo.inIfIndex = inport;
+    ip_rule.routingInfo.outIfIndex = outport;
+    ip_rule.routingInfo.aware_flags = 0;
+
+    for(i=0; i<MV_MAC_ADDR_SIZE; i++)
+    {
+        ip_rule.routingInfo.dstMac[i] = (MV_U8)(da[i] & 0xFF);
+        ip_rule.routingInfo.srcMac[i] = (MV_U8)(sa[i] & 0xFF);;
+    }
+    ip_rule.mgmtInfo.actionType = MV_FP_ROUTE_CMD;
+    ip_rule.mgmtInfo.ruleType = MV_FP_STATIC_RULE;
+
+    status = fp_rule_set(&ip_rule);
+    if(status != MV_OK)
+    {
+        printk("fp_rule_set FAILED: status=%d\n", status);
+    }
+    return status;
+}
+
+int run_ip_rule_del_com(const char *buffer)
+{
+    int scan_count;
+    MV_STATUS status = MV_OK;
+
+    scan_count = sscanf(buffer, IP_RULE_DEL_STRING, IP_RULE_DEL_SCANF_LIST);
+
+    if( scan_count != IP_RULE_DEL_LIST_LEN) {
+	printk("eth proc bad format %x != %x\n", scan_count, IP_RULE_DEL_LIST_LEN);
+	return 1;
+    }
+
+    status = fp_rule_delete(MV_32BIT_BE(sip), MV_32BIT_BE(dip), MV_FP_STATIC_RULE);
+    if(status != MV_OK)
+    {
+        printk("fp_rule_delete FAILED: status=%d\n", status);
+    }
+    return status;
+}
+
+int run_fp_db_print_com(const char *buffer)
+{
+    int scan_count;
+    MV_STATUS status = MV_OK;
+
+    scan_count = sscanf(buffer, NFP_DB_PRINT_STRING, NFP_DB_PRINT_SCANF_LIST);
+
+    if( scan_count != NFP_DB_PRINT_LIST_LEN) {
+	    printk("eth proc bad format %x != %x\n", scan_count, NFP_DB_PRINT_LIST_LEN);
+	    return 1;
+    }
+
+    if (db_type == DB_ROUTING)
+	    status = fp_rule_db_print(MV_FP_DATABASE); 
+#ifdef CONFIG_MV_ETH_NFP_NAT 
+    else if (db_type == DB_NAT)
+	    status = fp_nat_db_print(MV_FP_DATABASE);
+#endif /* CONFIG_MV_ETH_NFP_NA */
+#ifdef CONFIG_MV_ETH_NFP_FDB
+    else if (db_type == DB_FDB)
+            status = fp_fdb_db_print(MV_FP_DATABASE);
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+#ifdef CONFIG_MV_ETH_NFP_PPP
+    else if (db_type == DB_PPP)
+            status = fp_ppp_db_print(MV_FP_DATABASE);
+#endif /* CONFIG_MV_ETH_NFP_PPP */
+#ifdef CONFIG_MV_ETH_NFP_SEC
+    else if (db_type == DB_SEC)
+            status = fp_sec_db_print(MV_FP_DATABASE);
+#endif /* CONFIG_MV_ETH_NFP_SEC */
+    else {
+	    printk("Failed to print rule database: unknown DB type\n");
+	    return 1;
+    }
+    return status;
+}
+#endif /* CONFIG_MV_ETH_NFP */
+
+int run_com_general(const char *buffer) {
+
+	int scan_count;
+
+	scan_count = sscanf(buffer, PROC_STRING, PROC_SCANF_LIST);
+
+	if( scan_count != LIST_LEN) {
+		printk("eth proc bad format %x != %x\n", scan_count, LIST_LEN );
+		return 1;
+	}
+
+	switch(command){
+		case COM_SRQ:
+			DP(" Port %x: Got SRQ command Q %x and packet type is %x <bpdu/arp/tcp/udp> \n",port,q,packet);
+			run_com_srq();
+			break;
+		case COM_SQ:
+			DP(" Port %x: Got SQ command Q %x mac %2x:%2x:%2x:%2x:%2x:%2x\n",port, q, 
+				mac[0],  mac[1],  mac[2],  mac[3],  mac[4],  mac[5]);
+			run_com_sq();
+			break;
+
+#if (MV_ETH_RX_Q_NUM > 1)
+		case COM_SRP:
+			DP(" Port %x: Got SRP command Q %x policy %x <Fixed/WRR> \n",port,q,policy); 
+            printk("Not supported\n");
+			break;
+		case COM_SRQW:
+			DP(" Port %x: Got SQRW command Q %x weight %x \n",port,q,weight);
+			printk("Not supported\n");
+			break;
+		case COM_STP:
+			DP("STP cmd - Unsupported: Port %x Q %x policy %x <WRR/FIXED> weight %x\n",port,q,policy,weight); 
+			break;
+#endif /* MV_ETH_RX_Q_NUM > 1 */
+
+		case COM_STS:
+			DP("  Port %x: Got STS command status %x\n",port,status);
+			run_com_stats();
+			break;
+		default:
+			printk("eth proc unknown command.\n");
+	}
+  	return 0;
+}
+
+int mv_eth_tool_write (struct file *file, const char *buffer,
+                      unsigned long count, void *data) {
+
+	sscanf(buffer,"%x",&command);
+
+	switch (command) {
+		case COM_RX_COAL:
+		case COM_TX_COAL:
+        	case COM_TX_EN:
+        	case COM_EJP_MODE:
+		case COM_TX_NOQUEUE:
+		case COM_LRO:
+		case COM_LRO_DESC:
+			run_port_com(buffer);
+			break;
+		case COM_TXDONE_Q:
+        	case COM_SKB_REUSE:
+                case COM_SKB_RECYCLE:
+		case COM_NFP:
+			run_eth_com(buffer);
+			break;
+
+		case COM_TOS_MAP:
+            run_port_queue_cmd(buffer);
+			break;
+
+#ifdef CONFIG_MV_ETH_NFP
+		case COM_IP_RULE_SET:
+			run_ip_rule_set_com(buffer);
+			break;
+		case COM_IP_RULE_DEL:
+			run_ip_rule_del_com(buffer);
+			break;
+		case COM_NFP_STATUS:
+			fp_mgr_status();
+			break;
+		case COM_NFP_PRINT:
+			run_fp_db_print_com(buffer);
+			break;
+#endif /* CONFIG_MV_ETH_NFP */
+
+		default:
+			run_com_general(buffer);
+			break;
+	}
+	return count;
+}
+
+static int proc_calc_metrics(char *page, char **start, off_t off,
+                                 int count, int *eof, int len)
+{
+        if (len <= off+count) *eof = 1;
+        *start = page + off;
+        len -= off;
+        if (len>count) len = count;
+        if (len<0) len = 0;
+        return len;
+}
+
+
+
+int mv_eth_tool_read (char *page, char **start, off_t off,
+                            int count, int *eof, void *data) {
+	unsigned int len = 0;
+
+	//len  = sprintf(page, "\n");
+	//len += sprintf(page+len, "\n");
+	
+   	return proc_calc_metrics(page, start, off, count, eof, len);
+}
+
+
+
+int __init start_mv_eth_tool(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+  mv_eth_tool = proc_net_create(FILE_NAME , 0666 , NULL);
+#else
+  mv_eth_tool = create_proc_entry(FILE_NAME , 0666 , init_net.proc_net);
+#endif
+  mv_eth_tool->read_proc = mv_eth_tool_read;
+  mv_eth_tool->write_proc = mv_eth_tool_write;
+  mv_eth_tool->nlink = 1;
+  return 0;
+}
+
+module_init(start_mv_eth_tool);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_proc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_proc.h
new file mode 100755
index 0000000..cdeaf07
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_proc.h
@@ -0,0 +1,138 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+#ifndef __mv_eth_proc
+#define __mv_eth_proc
+
+#define FILE_NAME	"mv_eth_tool"
+#define FILE_PATH	"/proc/net/"
+#define STS_FILE	"mvethtool.sts"
+
+#define IP_RULE_STRING	    "%2x %2x %2x %4x %4x %2x:%2x:%2x:%2x:%2x:%2x %2x:%2x:%2x:%2x:%2x:%2x"
+#define IP_RULE_PRINT_LIST	 command, inport, outport, dip, sip, da[0], da[1], da[2], da[3], da[4], da[5], sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]
+#define IP_RULE_SCANF_LIST	&command, &inport, &outport, &dip, &sip, &da[0], &da[1], &da[2], &da[3], &da[4], &da[5], &sa[0], &sa[1], &sa[2], &sa[3], &sa[4], &sa[5]
+#define IP_RULE_LIST_LEN	17
+
+#define IP_RULE_DEL_STRING	"%2x %4x %4x"
+#define IP_RULE_DEL_PRINT_LIST	command, dip, sip
+#define IP_RULE_DEL_SCANF_LIST	&command, &dip, &sip
+#define IP_RULE_DEL_LIST_LEN	3
+
+#define NFP_DB_PRINT_STRING	"%2x %2x"
+#define NFP_DB_PRINT_PRINT_LIST	command, db_type
+#define NFP_DB_PRINT_SCANF_LIST	&command, &db_type
+#define NFP_DB_PRINT_LIST_LEN	2
+
+#define PROC_STRING	"%2x %2x %2x %2x %2x %2x %2x:%2x:%2x:%2x:%2x:%2x %x"
+#define PROC_PRINT_LIST	 command,  port,  q,  policy,  packet,  status,  mac[0],  mac[1],  mac[2],  mac[3],  mac[4],  mac[5],  weight
+#define PROC_SCANF_LIST	&command, &port, &q, &policy, &packet, &status, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5], &weight
+#define LIST_LEN	13
+
+#define PORT_CMD_STRING     "%2x %2x %x"
+#define PORT_PRINTF_LIST    command, port, value
+#define PORT_SCANF_LIST     &command, &port, &value
+#define PORT_LIST_LEN       3
+
+#define QUEUE_CMD_STRING     "%2x %2x %2x %x"
+#define QUEUE_PRINTF_LIST    command, port, q, value
+#define QUEUE_SCANF_LIST     &command, &port, &q, &value
+#define QUEUE_LIST_LEN       4
+
+
+#define ETH_CMD_STRING     "%2x %x"
+#define ETH_PRINTF_LIST    command, value
+#define ETH_SCANF_LIST     &command, &value
+#define ETH_LIST_LEN       2
+
+#define CMD_STRING         "%2x"
+#define CMD_SCANF_LIST     &command
+#define CMD_PRINT_LIST     command
+#define CMD_LIST_LEN       1
+
+typedef enum {
+	COM_SRQ = 0,
+	COM_SQ,
+	COM_SRP,
+	COM_SRQW,
+	COM_STP,
+	COM_STS,
+	COM_HEAD,
+	COM_RX_COAL,
+	COM_TX_COAL,
+	COM_TXDONE_Q,
+ 	COM_IP_RULE_SET,
+	COM_IP_RULE_DEL, 
+	COM_NFP, 
+	COM_NFP_STATUS,
+	COM_NFP_PRINT,
+    	COM_TX_EN,
+    	COM_SKB_REUSE,
+    	COM_SKB_RECYCLE,
+    	COM_EJP_MODE,
+    	COM_TOS_MAP,
+	COM_TX_NOQUEUE,
+	COM_LRO,
+	COM_LRO_DESC,
+} command_t;
+
+typedef enum { 	/**/
+	WRR = 0,
+	FIXED
+} policy_t;
+
+typedef enum {
+	PT_BPDU = 0,
+	PT_ARP,
+	PT_TCP,
+	PT_UDP
+} packet_t;
+
+typedef enum {
+	STS_PORT = 0,
+	STS_PORT_Q,
+	STS_PORT_RXP,
+	STS_PORT_TXP,
+	STS_PORT_REGS,
+	STS_PORT_MIB,
+	STS_PORT_STATS,
+    	STS_PORT_MAC,
+   	STS_PORT_NFP_STATS,
+    	STS_PORT_TOS_MAP,
+    	STS_NETDEV,
+    	STS_SWITCH_STATS,
+} status_t;
+
+typedef enum {
+	DB_ROUTING = 0, 
+	DB_NAT,
+	DB_FDB,
+	DB_PPP,
+	DB_SEC,
+} db_type_t;
+
+#endif
+	
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_tool.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_tool.c
new file mode 100755
index 0000000..7732958
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_tool.c
@@ -0,0 +1,1065 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"  /* Should be included before mvSysHwConfig */
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/string.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#include <asm/arch/system.h>
+#else
+#include <mach/system.h>
+#endif
+
+#include "mvOs.h"
+#include "dbg-trace.h"
+#include "mvSysHwConfig.h"
+#include "eth/mvEth.h"
+#include "eth-phy/mvEthPhy.h"
+#include "mvSysEthApi.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#include "mv_netdev.h"
+#include "mv_eth_tool.h"
+
+extern spinlock_t          mii_lock;
+
+const struct ethtool_ops mv_eth_tool_ops = {
+	.get_settings		= mv_eth_tool_get_settings,
+	.set_settings		= mv_eth_tool_set_settings,
+	.get_drvinfo		= mv_eth_tool_get_drvinfo,
+	.get_regs_len		= mv_eth_tool_get_regs_len,
+	.get_regs		= mv_eth_tool_get_regs,
+	.nway_reset		= mv_eth_tool_nway_reset,
+	.get_link		= mv_eth_tool_get_link,
+	.get_coalesce		= mv_eth_tool_get_coalesce,
+	.set_coalesce		= mv_eth_tool_set_coalesce,
+	.get_ringparam          = mv_eth_tool_get_ringparam,
+	.get_pauseparam		= mv_eth_tool_get_pauseparam,
+	.set_pauseparam		= mv_eth_tool_set_pauseparam,
+	.get_rx_csum		= mv_eth_tool_get_rx_csum,
+	.set_rx_csum		= mv_eth_tool_set_rx_csum,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.set_tx_csum		= mv_eth_tool_set_tx_csum,
+	.get_sg			= ethtool_op_get_sg,
+	.set_sg			= ethtool_op_set_sg,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= mv_eth_tool_set_tso,
+	.get_ufo		= ethtool_op_get_ufo,
+	.set_ufo		= mv_eth_tool_set_ufo,
+	.get_strings		= mv_eth_tool_get_strings,
+	.phys_id		= mv_eth_tool_phys_id,
+	.get_stats_count	= mv_eth_tool_get_stats_count,
+	.get_ethtool_stats	= mv_eth_tool_get_ethtool_stats,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	.get_perm_addr		= ethtool_op_get_perm_addr,
+#endif
+};
+
+struct mv_eth_tool_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int stat_offset;
+};
+
+#define MV_ETH_TOOL_STAT(m)	offsetof(mv_eth_priv, m)
+
+static const struct mv_eth_tool_stats mv_eth_tool_global_strings_stats[] = {
+	{"skb_alloc_fail", MV_ETH_TOOL_STAT(eth_stat.skb_alloc_fail)},
+	{"tx_timeout", MV_ETH_TOOL_STAT(eth_stat.tx_timeout)},
+	{"tx_netif_stop", MV_ETH_TOOL_STAT(eth_stat.tx_netif_stop)},
+	{"tx_done_netif_wake", MV_ETH_TOOL_STAT(eth_stat.tx_done_netif_wake)},
+	{"tx_skb_no_headroom", MV_ETH_TOOL_STAT(eth_stat.tx_skb_no_headroom)},
+#ifdef CONFIG_MV_ETH_STATS_INFO
+	{"irq_total", MV_ETH_TOOL_STAT(eth_stat.irq_total)},
+	{"irq_none_events", MV_ETH_TOOL_STAT(eth_stat.irq_none)},
+	{"irq_while_polling", MV_ETH_TOOL_STAT(eth_stat.irq_while_polling)},
+	{"picr is", MV_ETH_TOOL_STAT(picr)},
+	{"picer is", MV_ETH_TOOL_STAT(picer)},
+	{"poll_events", MV_ETH_TOOL_STAT(eth_stat.poll_events)},
+	{"poll_complete", MV_ETH_TOOL_STAT(eth_stat.poll_complete)},
+	{"tx_events", MV_ETH_TOOL_STAT(eth_stat.tx_events)},
+	{"tx_done_events", MV_ETH_TOOL_STAT(eth_stat.tx_done_events)},
+	{"timer_events", MV_ETH_TOOL_STAT(eth_stat.timer_events)},
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_SKB_REUSE)
+	{"rx_pool_empty", MV_ETH_TOOL_STAT(eth_stat.rx_pool_empty)},
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_SKB_REUSE */
+#endif /* CONFIG_MV_ETH_STATS_INFO */
+
+#ifdef CONFIG_MV_ETH_STATS_DEBUG
+	{"skb_alloc_ok", MV_ETH_TOOL_STAT(eth_stat.skb_alloc_ok)},
+	{"skb_free_ok", MV_ETH_TOOL_STAT(eth_stat.skb_free_ok)},
+#ifdef CONFIG_MV_SKB_REUSE
+	{"skb_reuse_rx", MV_ETH_TOOL_STAT(eth_stat.skb_reuse_rx)},
+	{"skb_reuse_tx", MV_ETH_TOOL_STAT(eth_stat.skb_reuse_tx)},
+	{"skb_reuse_alloc", MV_ETH_TOOL_STAT(eth_stat.skb_reuse_alloc)},
+#endif /* CONFIG_MV_SKB_REUSE */
+	{"tx_csum_hw", MV_ETH_TOOL_STAT(eth_stat.tx_csum_hw)},
+	{"tx_csum_sw", MV_ETH_TOOL_STAT(eth_stat.tx_csum_sw)},
+	{"rx_netif_drop", MV_ETH_TOOL_STAT(eth_stat.rx_netif_drop)},
+	{"rx_csum_hw", MV_ETH_TOOL_STAT(eth_stat.rx_csum_hw)},
+	{"rx_csum_hw_frags", MV_ETH_TOOL_STAT(eth_stat.rx_csum_hw_frags)},
+	{"rx_csum_sw", MV_ETH_TOOL_STAT(eth_stat.rx_csum_sw)},
+#ifdef ETH_INCLUDE_LRO
+	{"rx_lro_aggregated", MV_ETH_TOOL_STAT(lro_mgr.stats.aggregated)},
+	{"rx_lro_flushed", MV_ETH_TOOL_STAT(lro_mgr.stats.flushed)},
+	{"rx_lro_defragmented", MV_ETH_TOOL_STAT(lro_mgr.stats.defragmented)},
+	{"rx_lro_no_resources", MV_ETH_TOOL_STAT(lro_mgr.stats.no_desc)},
+#endif /* ETH_INCLUDE_LRO */
+#ifdef ETH_MV_TX_EN
+	{"tx_en_done", MV_ETH_TOOL_STAT(eth_stat.tx_en_done)},
+	{"tx_en_busy", MV_ETH_TOOL_STAT(eth_stat.tx_en_busy)},
+	{"tx_en_wait", MV_ETH_TOOL_STAT(eth_stat.tx_en_wait)},
+	{"tx_en_wait_count", MV_ETH_TOOL_STAT(eth_stat.tx_en_wait_count)},
+#endif /* ETH_MV_TX_EN */
+#endif /* CONFIG_MV_ETH_STATS_DEBUG */
+};
+
+static const struct mv_eth_tool_stats mv_eth_tool_rx_queue_strings_stats[] = {
+#ifdef CONFIG_MV_ETH_STATS_DEBUG
+	{"rx_hal_ok", MV_ETH_TOOL_STAT(eth_stat.rx_hal_ok)},
+	{"rx_fill_ok", MV_ETH_TOOL_STAT(eth_stat.rx_fill_ok)},
+#endif /* CONFIG_MV_ETH_STATS_DEBUG */
+};
+
+static const struct mv_eth_tool_stats mv_eth_tool_tx_queue_strings_stats[] = {
+#ifdef CONFIG_MV_ETH_STATS_DEBUG
+	{"tx_count", MV_ETH_TOOL_STAT(tx_count)},
+	{"tx_hal_ok", MV_ETH_TOOL_STAT(eth_stat.tx_hal_ok)},
+	{"tx_hal_no_resource", MV_ETH_TOOL_STAT(eth_stat.tx_hal_no_resource)},
+	{"tx_done_hal_ok", MV_ETH_TOOL_STAT(eth_stat.tx_done_hal_ok)},
+#endif /* CONFIG_MV_ETH_STATS_DEBUG */
+};
+
+#define MV_ETH_TOOL_RX_QUEUE_STATS_LEN  \
+	sizeof(mv_eth_tool_rx_queue_strings_stats) / sizeof(struct mv_eth_tool_stats)
+	
+#define MV_ETH_TOOL_TX_QUEUE_STATS_LEN  \
+	sizeof(mv_eth_tool_tx_queue_strings_stats) / sizeof(struct mv_eth_tool_stats)
+	
+#define MV_ETH_TOOL_QUEUE_STATS_LEN 	\
+	((MV_ETH_TOOL_RX_QUEUE_STATS_LEN * MV_ETH_RX_Q_NUM) + \
+	(MV_ETH_TOOL_TX_QUEUE_STATS_LEN * MV_ETH_TX_Q_NUM))
+
+#define MV_ETH_TOOL_GLOBAL_STATS_LEN	\
+	sizeof(mv_eth_tool_global_strings_stats) / sizeof(struct mv_eth_tool_stats)
+	
+#define MV_ETH_TOOL_STATS_LEN 		\
+	(MV_ETH_TOOL_GLOBAL_STATS_LEN + MV_ETH_TOOL_QUEUE_STATS_LEN)
+
+/******************************************************************************
+* mv_eth_tool_read_mdio
+* Description:
+*	MDIO read implementation for kernel core MII calls
+* INPUT:
+*	netdev		Network device structure pointer
+*	addr		PHY address
+*	reg		PHY register number (offset)
+* OUTPUT
+*	Register value or -1 on error
+*
+*******************************************************************************/
+int mv_eth_tool_read_mdio(struct net_device *netdev, int addr, int reg)
+{
+	unsigned long 	flags;
+	unsigned short 	value;
+	MV_STATUS 	status;
+	
+	spin_lock_irqsave(&mii_lock, flags);
+	status = mvEthPhyRegRead(addr, reg, &value);
+	spin_unlock_irqrestore(&mii_lock, flags);
+
+	if (status == MV_OK)
+		return value;
+
+	return -1;
+}
+
+/******************************************************************************
+* mv_eth_tool_write_mdio
+* Description:
+*	MDIO write implementation for kernel core MII calls
+* INPUT:
+*	netdev		Network device structure pointer
+*	addr		PHY address
+*	reg		PHY register number (offset)
+*	data		Data to be written into PHY register
+* OUTPUT
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_write_mdio(struct net_device *netdev, int addr, int reg, int data)
+{
+	unsigned long   flags;
+	unsigned short  tmp   = (unsigned short)data;
+
+	spin_lock_irqsave(&mii_lock, flags);
+	mvEthPhyRegWrite(addr, reg, tmp);
+	spin_unlock_irqrestore(&mii_lock, flags);
+}
+
+
+/******************************************************************************
+* mv_eth_tool_read_phy_reg
+* Description:
+*	Marvell PHY register read (includes page number)
+* INPUT:
+*	phy_addr	PHY address
+*	page		PHY register page (region)
+*	reg		PHY register number (offset)
+* OUTPUT
+*	val		PHY register value
+* RETURN:
+*	0 for success
+*
+*******************************************************************************/
+#define MV_ETH_TOOL_PHY_PAGE_ADDR_REG	22
+int mv_eth_tool_read_phy_reg(int phy_addr, u16 page, u16 reg, u16 *val)
+{
+	unsigned long 	flags;
+	MV_STATUS 	status = 0;
+	
+	spin_lock_irqsave(&mii_lock, flags);
+	/* setup register address page first */
+	if (!mvEthPhyRegWrite(phy_addr, MV_ETH_TOOL_PHY_PAGE_ADDR_REG, page)) {
+		status = mvEthPhyRegRead(phy_addr, reg, val);
+	}
+	spin_unlock_irqrestore(&mii_lock, flags);
+
+	return status;
+}
+
+/******************************************************************************
+* mv_eth_tool_write_phy_reg
+* Description:
+*	Marvell PHY register write (includes page number)
+* INPUT:
+*	phy_addr	PHY address
+*	page		PHY register page (region)
+*	reg		PHY register number (offset)
+*	data		Data to be written into PHY register
+* OUTPUT
+*	None
+* RETURN:
+*	0 for success
+*
+*******************************************************************************/
+int mv_eth_tool_write_phy_reg(int phy_addr, u16 page, u16 reg, u16 data)
+{
+	unsigned long   flags;
+	MV_STATUS 	status = 0;
+	
+	spin_lock_irqsave(&mii_lock, flags);
+	/* setup register address page first */
+	if (!mvEthPhyRegWrite(phy_addr, MV_ETH_TOOL_PHY_PAGE_ADDR_REG,
+						(unsigned int)page)) {
+		status = mvEthPhyRegWrite(phy_addr, reg, data);
+	}
+	spin_unlock_irqrestore(&mii_lock, flags);
+
+	return status;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_settings
+* Description:
+*	ethtool get standard port settings
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	cmd		command (settings)
+* RETURN:
+*	0 for success
+*
+*******************************************************************************/
+int mv_eth_tool_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	mv_eth_priv 		*priv = MV_ETH_PRIV(netdev);
+	struct mii_if_info 	mii;
+	int			retval;
+	MV_ETH_PORT_STATUS 	status;
+	
+#ifdef CONFIG_MII	
+	mii.dev			= netdev;
+	mii.phy_id_mask 	= 0x1F;
+	mii.reg_num_mask 	= 0x1F;
+	mii.mdio_read 		= mv_eth_tool_read_mdio;
+	mii.mdio_write 		= mv_eth_tool_write_mdio;
+	mii.phy_id 		= priv->phy_id;
+	mii.supports_gmii 	= 1;
+
+	/* Get values from PHY */
+	retval = mii_ethtool_gset(&mii, cmd);
+	if (retval)
+		return retval;
+#endif
+
+	/* Get some values from MAC */
+	mvEthStatusGet(priv->hal_priv, &status);
+	
+	switch (status.speed) {
+	case MV_ETH_SPEED_1000:
+		cmd->speed = SPEED_1000;
+		break;	
+	case MV_ETH_SPEED_100:
+		cmd->speed = SPEED_100;
+		break;
+	case MV_ETH_SPEED_10:
+		cmd->speed = SPEED_10;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (status.duplex == MV_ETH_DUPLEX_FULL) 
+		cmd->duplex = 1;
+	else
+		cmd->duplex = 0;
+
+	cmd->port = PORT_MII;
+	cmd->phy_address = priv->phy_id;
+
+	return 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_restore_settings
+* Description:
+*	restore saved speed/dublex/an settings
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	0 for success
+*
+*******************************************************************************/
+int mv_eth_tool_restore_settings(struct net_device *netdev)
+{
+	mv_eth_priv 		*priv = MV_ETH_PRIV(netdev);
+	int 			mv_phy_speed, mv_phy_duplex;
+	MV_U32			mv_phy_addr = priv->phy_id;
+	MV_ETH_PORT_SPEED	mv_mac_speed;
+	MV_ETH_PORT_DUPLEX	mv_mac_duplex;
+	int			err = -EINVAL;
+
+	switch (priv->speed_cfg) {
+		case SPEED_10:
+			mv_phy_speed  = 0;
+			mv_mac_speed = MV_ETH_SPEED_10;
+			break;
+		case SPEED_100:
+			mv_phy_speed  = 1;
+			mv_mac_speed = MV_ETH_SPEED_100;
+			break;
+		case SPEED_1000:
+			mv_phy_speed  = 2;
+			mv_mac_speed = MV_ETH_SPEED_1000;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	switch (priv->duplex_cfg) {
+		case DUPLEX_HALF:
+			mv_phy_duplex = 0;
+			mv_mac_duplex = MV_ETH_DUPLEX_HALF;
+			break;
+		case DUPLEX_FULL:
+			mv_phy_duplex = 1;
+			mv_mac_duplex = MV_ETH_DUPLEX_FULL;
+			break;
+		default:
+			return -EINVAL;
+	}
+	
+	if (priv->autoneg_cfg == AUTONEG_ENABLE) {
+		err = mvEthSpeedDuplexSet(priv->hal_priv,
+					  MV_ETH_SPEED_AN, MV_ETH_DUPLEX_AN);
+
+		/* Restart AN on PHY enables it */
+		if (!err) {
+
+			err = mvEthPhyRestartAN(mv_phy_addr, MV_ETH_TOOL_AN_TIMEOUT);
+			if (err == MV_TIMEOUT) {
+				MV_ETH_PORT_STATUS ps;
+				mvEthStatusGet(priv->hal_priv, &ps);
+				if (!ps.isLinkUp)
+					err = 0;
+			}
+		}
+	} else if (priv->autoneg_cfg == AUTONEG_DISABLE) {
+		err = mvEthPhyDisableAN(mv_phy_addr, mv_phy_speed, mv_phy_duplex);
+		if (!err) {
+			err = mvEthSpeedDuplexSet(priv->hal_priv,
+					mv_mac_speed, mv_mac_duplex);
+		}
+	} else {
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+/******************************************************************************
+* mv_eth_tool_set_settings
+* Description:
+*	ethtool set standard port settings
+* INPUT:
+*	netdev		Network device structure pointer
+*	cmd		command (settings)
+* OUTPUT
+*	None
+* RETURN:
+*	0 for success
+*
+*******************************************************************************/
+int mv_eth_tool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	mv_eth_priv *priv = MV_ETH_PRIV(dev);
+	int _speed, _duplex, _autoneg, err;
+
+#ifdef CONFIG_MV_GATEWAY
+	if (priv->isGtw)
+		return -EPERM;
+#endif /* CONFIG_MV_GATEWAY */
+
+	_duplex = priv->duplex_cfg;
+	_speed = priv->speed_cfg;
+	_autoneg = priv->autoneg_cfg;
+
+	priv->duplex_cfg = cmd->duplex;
+	priv->speed_cfg = cmd->speed;
+	priv->autoneg_cfg = cmd->autoneg;
+
+	err = mv_eth_tool_restore_settings(dev);
+
+	if (err) {
+		priv->duplex_cfg = _duplex;
+		priv->speed_cfg = _speed;
+		priv->autoneg_cfg = _autoneg;
+	}
+	return err;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_drvinfo
+* Description:
+*	ethtool get driver information
+* INPUT:
+*	netdev		Network device structure pointer
+*	info		driver information
+* OUTPUT
+*	info		driver information
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_drvinfo(struct net_device *netdev,
+			     struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, "mv_eth");
+	strcpy(info->version, LSP_VERSION);
+	strcpy(info->fw_version, "N/A");
+	strcpy(info->bus_info, "Mbus");
+	info->n_stats = MV_ETH_TOOL_STATS_LEN;
+	info->testinfo_len = 0;
+	info->regdump_len = mv_eth_tool_get_regs_len(netdev);
+	info->eedump_len = 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_regs_len
+* Description:
+*	ethtool get registers array length
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	registers array length
+*
+*******************************************************************************/
+int mv_eth_tool_get_regs_len(struct net_device *netdev)
+{
+#define MV_ETH_TOOL_REGS_LEN 32
+	return MV_ETH_TOOL_REGS_LEN * sizeof(uint32_t);
+}
+
+/******************************************************************************
+* mv_eth_tool_get_regs
+* Description:
+*	ethtool get registers array
+* INPUT:
+*	netdev		Network device structure pointer
+*	regs		registers information
+* OUTPUT
+*	p		registers array
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_regs(struct net_device *netdev,
+			  struct ethtool_regs *regs, void *p)
+{
+	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
+	uint32_t 	*regs_buff = p;
+
+	memset(p, 0, MV_ETH_TOOL_REGS_LEN * sizeof(uint32_t));
+
+	regs->version = mvCtrlModelRevGet(); 
+
+	/* ETH port registers */
+	regs_buff[0]  = MV_REG_READ(ETH_PORT_STATUS_REG(priv->port));
+	regs_buff[1]  = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(priv->port));
+	regs_buff[2]  = MV_REG_READ(ETH_PORT_CONFIG_REG(priv->port));
+	regs_buff[3]  = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(priv->port));
+	regs_buff[4]  = MV_REG_READ(ETH_SDMA_CONFIG_REG(priv->port));
+	regs_buff[5]  = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(priv->port));
+	regs_buff[6]  = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(priv->port));
+	regs_buff[7]  = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(priv->port));
+	regs_buff[8]  = MV_REG_READ(ETH_INTR_CAUSE_REG(priv->port));
+	regs_buff[9]  = MV_REG_READ(ETH_INTR_CAUSE_EXT_REG(priv->port));
+	regs_buff[10] = MV_REG_READ(ETH_INTR_MASK_REG(priv->port));
+	regs_buff[11] = MV_REG_READ(ETH_INTR_MASK_EXT_REG(priv->port));
+	regs_buff[12] = MV_REG_READ(ETH_RX_DESCR_STAT_CMD_REG(priv->port, 0));
+	regs_buff[13] = MV_REG_READ(ETH_RX_BYTE_COUNT_REG(priv->port, 0));
+	regs_buff[14] = MV_REG_READ(ETH_RX_BUF_PTR_REG(priv->port, 0));
+	regs_buff[15] = MV_REG_READ(ETH_RX_CUR_DESC_PTR_REG(priv->port, 0));
+	/* ETH Unit registers */
+	regs_buff[16] = MV_REG_READ(ETH_PHY_ADDR_REG(priv->port));
+	regs_buff[17] = MV_REG_READ(ETH_UNIT_INTR_CAUSE_REG(priv->port));
+	regs_buff[18] = MV_REG_READ(ETH_UNIT_INTR_MASK_REG(priv->port));
+	regs_buff[19] = MV_REG_READ(ETH_UNIT_ERROR_ADDR_REG(priv->port));
+	regs_buff[20] = MV_REG_READ(ETH_UNIT_INT_ADDR_ERROR_REG(priv->port));
+	
+}
+
+/******************************************************************************
+* mv_eth_tool_nway_reset
+* Description:
+*	ethtool restart auto negotiation
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_nway_reset(struct net_device *netdev)
+{
+	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
+	MV_U32		mv_phy_addr = (MV_U32)(priv->phy_id);
+
+	if (mvEthPhyRestartAN(mv_phy_addr, MV_ETH_TOOL_AN_TIMEOUT) != MV_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_link
+* Description:
+*	ethtool get link status
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	0 if link is down, 1 if link is up
+*
+*******************************************************************************/
+u32 mv_eth_tool_get_link(struct net_device *netdev)
+{
+	mv_eth_priv 		*priv = MV_ETH_PRIV(netdev);
+	MV_ETH_PORT_STATUS	status;
+
+	mvEthStatusGet(priv->hal_priv, &status);
+	if (status.isLinkUp == MV_TRUE)
+		return 1;
+	
+	return 0;
+}
+
+
+/******************************************************************************
+* mv_eth_tool_get_coalesce
+* Description:
+*	ethtool get RX/TX coalesce parameters
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	cmd		Coalesce parameters
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_get_coalesce(struct net_device *netdev,
+			     struct ethtool_coalesce *cmd)
+{
+	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
+
+	if (mvEthCoalGet(priv->hal_priv, &cmd->rx_coalesce_usecs,
+	    &cmd->tx_coalesce_usecs) != MV_OK)
+		return -EINVAL;
+	
+	return 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_set_coalesce
+* Description:
+*	ethtool set RX/TX coalesce parameters
+* INPUT:
+*	netdev		Network device structure pointer
+*	cmd		Coalesce parameters
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_coalesce(struct net_device *netdev,
+			     struct ethtool_coalesce *cmd)
+{
+	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
+
+	if ((cmd->rx_coalesce_usecs == 0) ||
+		(cmd->tx_coalesce_usecs == 0)) {
+		/* coalesce usec=0 means that coalesce frames should be used,
+		 * which is not permitted (unsupported) */
+		return -EPERM;
+	}
+
+	if ((cmd->rx_coalesce_usecs * 166 / 64 > 0x3FFF) ||
+		(cmd->tx_coalesce_usecs * 166 / 64 > 0x3FFF))
+		return -EINVAL;
+	
+	/* Save values for mv_eth_start_internals() */
+	priv->rx_coal_usec = cmd->rx_coalesce_usecs;
+	priv->tx_coal_usec = cmd->tx_coalesce_usecs;
+	
+	mvEthRxCoalSet (priv->hal_priv, cmd->rx_coalesce_usecs);
+	mvEthTxCoalSet (priv->hal_priv, cmd->tx_coalesce_usecs);
+
+	return 0;
+}
+
+
+/******************************************************************************
+* mv_eth_tool_get_ringparam
+* Description:
+*	ethtool get ring parameters
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	ring		Ring paranmeters
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_ringparam( struct net_device *netdev,
+				struct ethtool_ringparam *ring)
+{
+	ring->rx_max_pending = 4096;
+	ring->tx_max_pending = 4096;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = CONFIG_MV_ETH_NUM_OF_RX_DESCR;
+	ring->tx_pending = CONFIG_MV_ETH_NUM_OF_TX_DESCR;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_pauseparam
+* Description:
+*	ethtool get pause parameters
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	pause		Pause paranmeters
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_pauseparam(struct net_device *netdev,
+				struct ethtool_pauseparam *pause)
+{
+	mv_eth_priv 		*priv = MV_ETH_PRIV(netdev);
+	ETH_PORT_CTRL		*pPortCtrl = (ETH_PORT_CTRL*)(priv->hal_priv);
+	MV_U32			reg;
+
+/*	FIXME */	
+	printk("%s not supported for new GMAC\n", __FUNCTION__);
+
+#if 0
+	reg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo));
+	pause->rx_pause = 0;
+	pause->tx_pause = 0;
+
+	if (reg & ETH_DISABLE_FC_AUTO_NEG_MASK) { /* autoneg disabled */
+		pause->autoneg = AUTONEG_DISABLE;
+		if (reg & ETH_SET_FLOW_CTRL_MASK)
+		{
+			pause->rx_pause = 1;
+			pause->tx_pause = 1;
+		}
+	} else { /* autoneg enabled */
+		pause->autoneg = AUTONEG_ENABLE;
+		if (reg & ETH_ADVERTISE_SYM_FC_MASK)
+		{
+			pause->rx_pause = 1;
+			pause->tx_pause = 1;
+		}
+	}
+#endif
+}
+
+/******************************************************************************
+* mv_eth_tool_set_pauseparam
+* Description:
+*	ethtool configure pause parameters
+* INPUT:
+*	netdev		Network device structure pointer
+*	pause		Pause paranmeters
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_pauseparam( struct net_device *netdev,
+				struct ethtool_pauseparam *pause)
+{
+	mv_eth_priv 		*priv = MV_ETH_PRIV(netdev);
+	ETH_PORT_CTRL		*pPortCtrl = (ETH_PORT_CTRL*)(priv->hal_priv);
+	
+	if (pause->rx_pause && pause->tx_pause) { /* Enable FC */
+		if (pause->autoneg) { /* autoneg enable */
+			return mvEthFlowCtrlSet(priv->hal_priv, MV_ETH_FC_AN_ADV_SYM);
+		} else { /* autoneg disable */
+			return mvEthFlowCtrlSet(priv->hal_priv, MV_ETH_FC_ENABLE);
+		}
+	} else if (!pause->rx_pause && !pause->tx_pause) { /* Disable FC */
+		if (pause->autoneg) { /* autoneg enable */
+			return mvEthFlowCtrlSet(priv->hal_priv, MV_ETH_FC_AN_ADV_DIS);
+		} else { /* autoneg disable */
+			return mvEthFlowCtrlSet(priv->hal_priv, MV_ETH_FC_DISABLE);
+		}
+	}
+
+	/* Only symmetric change for RX and TX flow control is allowed */
+	return -EINVAL;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_rx_csum
+* Description:
+*	ethtool get RX checksum offloading status
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	RX checksum
+*
+*******************************************************************************/
+u32 mv_eth_tool_get_rx_csum(struct net_device *netdev)
+{
+	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
+#ifdef RX_CSUM_OFFLOAD
+	return (priv->rx_csum_offload != 0);
+#else
+	return 0;
+#endif
+}
+
+/******************************************************************************
+* mv_eth_tool_set_rx_csum
+* Description:
+*	ethtool enable/disable RX checksum offloading
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Command data
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_rx_csum(struct net_device *netdev, uint32_t data)
+{
+	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
+#ifdef RX_CSUM_OFFLOAD
+	priv->rx_csum_offload = data;
+	return 0;
+#else
+	return data ? -EINVAL : 0;
+#endif
+}
+
+/******************************************************************************
+* mv_eth_tool_set_tx_csum
+* Description:
+*	ethtool enable/disable TX checksum offloading
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Command data
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+#ifdef TX_CSUM_OFFLOAD
+	if (data) {
+		netdev->features |= NETIF_F_IP_CSUM;
+	} else {
+		netdev->features &= ~NETIF_F_IP_CSUM;
+	}
+	return 0;
+#else
+	return data ? -EINVAL : 0;
+#endif /* TX_CSUM_OFFLOAD */
+}
+
+/******************************************************************************
+* mv_eth_tool_set_tso
+* Description:
+*	ethtool enable/disable TCP segmentation offloading
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Command data
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_tso(struct net_device *netdev, uint32_t data)
+{
+#ifdef ETH_INCLUDE_TSO
+	if (data) {
+		netdev->features |= NETIF_F_TSO;
+	} else {
+		netdev->features &= ~NETIF_F_TSO;
+	}
+	return 0;
+#else
+	return data ? -EINVAL : 0;
+#endif /* ETH_INCLUDE_TSO */
+}
+
+/******************************************************************************
+* mv_eth_tool_set_ufo
+* Description:
+*	ethtool enable/disable UDP segmentation offloading
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Command data
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_set_ufo(struct net_device *netdev, uint32_t data)
+{
+#ifdef ETH_INCLUDE_UFO
+	if (data) {
+		netdev->features |= NETIF_F_UFO;
+	} else {
+		netdev->features &= ~NETIF_F_UFO;
+	}
+	return 0;
+#else
+	return data ? -EINVAL : 0;
+#endif /* ETH_INCLUDE_UFO */
+}
+
+/******************************************************************************
+* mv_eth_tool_get_strings
+* Description:
+*	ethtool get strings (used for statistics and self-test descriptions)
+* INPUT:
+*	netdev		Network device structure pointer
+*	stringset	strings parameters
+* OUTPUT
+*	data		output data
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_strings(struct net_device *netdev,
+			     uint32_t stringset, uint8_t *data)
+{
+	uint8_t *p = data;
+	int i, q;
+	char qnum[8][4] = {" Q0"," Q1"," Q2"," Q3"," Q4"," Q5"," Q6"," Q7"};
+
+	switch (stringset) {
+		case ETH_SS_TEST:
+			/*
+			memcpy(data, *mv_eth_tool_gstrings_test,
+			       MV_ETH_TOOL_TEST_LEN*ETH_GSTRING_LEN); */
+			break;
+		case ETH_SS_STATS:
+			for (i = 0; i < MV_ETH_TOOL_GLOBAL_STATS_LEN; i++) {
+				memcpy(p, mv_eth_tool_global_strings_stats[i].stat_string,
+				       ETH_GSTRING_LEN);
+				p += ETH_GSTRING_LEN;
+			}
+			for (q = 0; q < MV_ETH_RX_Q_NUM; q++) {
+				for (i = 0; i < MV_ETH_TOOL_RX_QUEUE_STATS_LEN; i++) {
+					const char *str = mv_eth_tool_rx_queue_strings_stats[i].stat_string;
+					memcpy(p, str, ETH_GSTRING_LEN);
+					strcat(p, qnum[q]);
+					p += ETH_GSTRING_LEN;
+				}
+			}
+			for (q = 0; q < MV_ETH_TX_Q_NUM; q++) {
+				for (i = 0; i < MV_ETH_TOOL_TX_QUEUE_STATS_LEN; i++) {
+					const char *str = mv_eth_tool_tx_queue_strings_stats[i].stat_string;
+					memcpy(p, str, ETH_GSTRING_LEN);
+					strcat(p, qnum[q]);
+					p += ETH_GSTRING_LEN;
+				}
+			}
+			break;
+	}
+}
+
+#define ETH_TOOL_PHY_LED_CTRL_PAGE	3
+#define ETH_TOOL_PHY_LED_CTRL_REG	16
+
+/******************************************************************************
+* mv_eth_tool_get_link
+* Description:
+*	ethtool physically identify port by LED blinking
+* INPUT:
+*	netdev		Network device structure pointer
+*	data		Number of secunds to blink the LED
+* OUTPUT
+*	None
+* RETURN:
+*	0 on success
+*
+*******************************************************************************/
+int mv_eth_tool_phys_id(struct net_device *netdev, u32 data)
+{
+	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
+	u16		old_led_state;
+
+	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+	
+	mv_eth_tool_read_phy_reg(priv->phy_id, ETH_TOOL_PHY_LED_CTRL_PAGE,
+				ETH_TOOL_PHY_LED_CTRL_REG, &old_led_state);
+	/* Forse LED blinking (all LED pins) */
+	mv_eth_tool_write_phy_reg(priv->phy_id, ETH_TOOL_PHY_LED_CTRL_PAGE,
+				ETH_TOOL_PHY_LED_CTRL_REG, 0x0BBB);
+	msleep_interruptible(data * 1000);
+	mv_eth_tool_write_phy_reg(priv->phy_id, ETH_TOOL_PHY_LED_CTRL_PAGE,
+				  ETH_TOOL_PHY_LED_CTRL_REG, old_led_state);
+	return 0;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_stats_count
+* Description:
+*	ethtool get statistics count (number of stat. array entries)
+* INPUT:
+*	netdev		Network device structure pointer
+* OUTPUT
+*	None
+* RETURN:
+*	statistics count
+*
+*******************************************************************************/
+int mv_eth_tool_get_stats_count(struct net_device *netdev)
+{
+	return MV_ETH_TOOL_STATS_LEN;
+}
+
+/******************************************************************************
+* mv_eth_tool_get_ethtool_stats
+* Description:
+*	ethtool get statistics
+* INPUT:
+*	netdev		Network device structure pointer
+*	stats		stats parameters
+* OUTPUT
+*	data		output data
+* RETURN:
+*	None
+*
+*******************************************************************************/
+void mv_eth_tool_get_ethtool_stats(struct net_device *netdev,
+				   struct ethtool_stats *stats, uint64_t *data)
+{
+	mv_eth_priv 	*priv = MV_ETH_PRIV(netdev);
+	uint64_t	*pdest = data;
+	int 		i, q;
+
+	for (i = 0; i < MV_ETH_TOOL_GLOBAL_STATS_LEN; i++) {
+		char *p = (char *)priv +
+			mv_eth_tool_global_strings_stats[i].stat_offset;
+		pdest[i] =  *(uint32_t *)p;
+	}
+	pdest += MV_ETH_TOOL_GLOBAL_STATS_LEN;
+	
+	for (q = 0; q < MV_ETH_RX_Q_NUM; q++) {
+		for (i = 0; i < MV_ETH_TOOL_RX_QUEUE_STATS_LEN; i++) {
+			char *p = (char *)priv +
+				mv_eth_tool_rx_queue_strings_stats[i].stat_offset;
+			pdest[i] =  *((uint32_t *)p + q);
+		}
+		pdest += MV_ETH_TOOL_RX_QUEUE_STATS_LEN;
+	}
+
+	for (q = 0; q < MV_ETH_TX_Q_NUM; q++) {
+		for (i = 0; i < MV_ETH_TOOL_TX_QUEUE_STATS_LEN; i++) {
+			char *p = (char *)priv +
+				mv_eth_tool_tx_queue_strings_stats[i].stat_offset;
+			pdest[i] =  *((uint32_t *)p + q);
+		}
+		pdest += MV_ETH_TOOL_TX_QUEUE_STATS_LEN;
+	}
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_tool.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_tool.h
new file mode 100755
index 0000000..0274459
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_eth_tool.h
@@ -0,0 +1,85 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+#ifndef __mv_eth_tool
+#define __mv_eth_tool
+
+#include <linux/ethtool.h>
+
+#define MV_ETH_TOOL_AN_TIMEOUT	2000
+
+extern const struct ethtool_ops mv_eth_tool_ops;
+
+int mv_eth_tool_read_mdio
+		(struct net_device *netdev, int addr, int reg);
+void mv_eth_tool_write_mdio
+		(struct net_device *netdev, int addr, int reg, int data);
+int mv_eth_tool_restore_settings(struct net_device *netdev);
+int mv_eth_tool_get_settings
+		(struct net_device *netdev, struct ethtool_cmd *cmd);
+int mv_eth_tool_set_settings
+		(struct net_device *netdev, struct ethtool_cmd *cmd);
+int mv_eth_tool_nway_reset
+		(struct net_device *netdev);
+int mv_eth_tool_get_regs_len
+		(struct net_device *netdev);
+void mv_eth_tool_get_regs
+		(struct net_device *netdev, struct ethtool_regs *regs, void *p);
+u32 mv_eth_tool_get_link
+		(struct net_device *netdev);
+int mv_eth_tool_get_coalesce
+		(struct net_device *netdev, struct ethtool_coalesce *cmd);
+int mv_eth_tool_set_coalesce
+		(struct net_device *netdev, struct ethtool_coalesce *cmd);
+void mv_eth_tool_get_ringparam
+		(struct net_device *netdev, struct ethtool_ringparam *ring);
+void mv_eth_tool_get_pauseparam
+		(struct net_device *netdev, struct ethtool_pauseparam *pause);
+int mv_eth_tool_set_pauseparam
+		(struct net_device *netdev, struct ethtool_pauseparam *pause);
+void mv_eth_tool_get_drvinfo
+		(struct net_device *netdev, struct ethtool_drvinfo *info);
+u32 mv_eth_tool_get_rx_csum
+		(struct net_device *netdev);
+int mv_eth_tool_set_rx_csum
+		(struct net_device *netdev, uint32_t data);
+int mv_eth_tool_set_tx_csum
+		(struct net_device *netdev, uint32_t data);
+int mv_eth_tool_set_tso
+		(struct net_device *netdev, uint32_t data);
+int mv_eth_tool_set_ufo
+		(struct net_device *netdev, uint32_t data);
+void mv_eth_tool_get_strings
+		(struct net_device *netdev, uint32_t stringset, uint8_t *data);
+int mv_eth_tool_phys_id
+		(struct net_device *netdev, u32 data);
+int mv_eth_tool_get_stats_count
+		(struct net_device *netdev);
+void mv_eth_tool_get_ethtool_stats
+		(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data);
+
+#endif /* __mv_eth_tool */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_ethernet.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_ethernet.c
new file mode 100755
index 0000000..7b55bf0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_ethernet.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"  /* Should be included before mvSysHwConfig */
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+#include "mvOs.h"
+#include "dbg-trace.h"
+#include "mvSysHwConfig.h"
+#include "eth/mvEth.h"
+#include "eth/gbe/mvEthGbe.h"
+#include "eth-phy/mvEthPhy.h"
+#include "eth-phy/mvEthPhyRegs.h"
+#include "mvSysEthApi.h"
+#include "boardEnv/mvBoardEnvLib.h"
+
+#include "mv_netdev.h"
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+#include "mv78200/mvSemaphore.h"
+#endif
+
+int mv_eth_read_mii(unsigned int portNumber, unsigned int MIIReg, unsigned int* value)
+{
+    unsigned long flags;
+    unsigned short tmp;
+    MV_STATUS status;
+
+    spin_lock_irqsave(&mii_lock, flags);
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+    mvSemaLock(MV_SEMA_SMI);
+#endif
+    status = mvEthPhyRegRead(mvBoardPhyAddrGet(portNumber), MIIReg, &tmp);
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+    mvSemaUnlock(MV_SEMA_SMI);
+#endif
+    spin_unlock_irqrestore(&mii_lock, flags);	
+    *value = tmp;
+    if (status == MV_OK)
+        return 0;
+
+    return -1;
+}
+
+
+int mv_eth_write_mii(unsigned int portNumber, unsigned int MIIReg, unsigned int data)
+{
+    unsigned long   flags;
+    unsigned short  tmp;
+    MV_STATUS       status;
+
+    spin_lock_irqsave(&mii_lock, flags);
+    tmp = (unsigned short)data;
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+    mvSemaLock(MV_SEMA_SMI);
+#endif
+    status = mvEthPhyRegWrite(mvBoardPhyAddrGet(portNumber), MIIReg, tmp);
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+    mvSemaUnlock(MV_SEMA_SMI);
+#endif
+    spin_unlock_irqrestore(&mii_lock, flags);
+
+    if (status == MV_OK)
+        return 0;
+
+    return -1;
+}
+
+#ifndef CONFIG_MV_ETH_TOOL
+static int mv_eth_restart_autoneg( int port )
+{
+    u32 phy_reg_val = 0;
+
+    /* enable auto-negotiation */
+    mv_eth_read_mii(port, ETH_PHY_CTRL_REG, &phy_reg_val);
+    phy_reg_val |= BIT12;
+    mv_eth_write_mii(port, ETH_PHY_CTRL_REG, phy_reg_val);
+
+    mdelay(10);
+
+    /* restart auto-negotiation */
+    phy_reg_val |= BIT9;
+    mv_eth_write_mii(port, ETH_PHY_CTRL_REG, phy_reg_val);
+
+    mdelay(10);
+
+    return 0;
+}
+#endif
+
+/*********************************************************** 
+ * mv_eth_start --                                          *
+ *   start a network device. connect and enable interrupts *
+ *   set hw defaults. fill rx buffers. restart phy link    *
+ *   auto neg. set device link flags. report status.       *
+ ***********************************************************/
+int mv_eth_start( struct net_device *dev ) 
+{
+    mv_eth_priv *priv = MV_ETH_PRIV(dev);
+    int             err;
+
+    ETH_DBG( ETH_DBG_LOAD, ("%s: starting... ", dev->name ) );
+
+    /* in default link is down */
+    netif_carrier_off( dev );
+
+    /* Stop the TX queue - it will be enabled upon PHY status change after link-up interrupt/timer */
+    netif_stop_queue( dev );
+
+    /* enable polling on the port, must be used after netif_poll_disable */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    netif_poll_enable(dev);
+#else
+    napi_enable(&priv->napi);
+#endif
+
+    /* fill rx buffers, start rx/tx activity, set coalescing */
+    if( mv_eth_start_internals( priv, dev->mtu) != 0 ) {
+        printk( KERN_ERR "%s: start internals failed\n", dev->name );
+        goto error;
+    }
+
+#ifdef CONFIG_MV_ETH_TOOL
+    if ((err = mv_eth_tool_restore_settings( dev )) != 0) 
+    {
+        printk( KERN_ERR "%s: mv_eth_tool_restore_settings failed %d\n",
+                          dev->name, err );
+        goto error;
+    }
+    if (priv->autoneg_cfg == AUTONEG_DISABLE) 
+    {
+        if ( MV_REG_READ(NETA_GMAC_STATUS_REG( priv->port )) & NETA_GMAC_LINK_UP_MASK ) 
+	{
+	    netif_carrier_on( dev );
+	    netif_wake_queue( dev );
+        }
+    }
+#else
+    mv_eth_restart_autoneg( priv->port );
+#endif /* #ifdef CONFIG_MV_ETH_TOOL */
+
+    if (priv->timer_flag == 0)
+    {
+        priv->timer.expires = jiffies + ((HZ*CONFIG_MV_ETH_TIMER_PERIOD)/1000); /*ms*/
+        add_timer(&priv->timer);
+        priv->timer_flag = 1;
+    }
+
+    /* connect to port interrupt line */
+    if (request_irq(dev->irq, mv_eth_interrupt_handler,
+        	(IRQF_DISABLED | IRQF_SAMPLE_RANDOM), "mv_ethernet", priv) ) {
+        printk( KERN_ERR "cannot assign irq%d to %s port%d\n", dev->irq, dev->name, priv->port );
+        dev->irq = 0;
+    	goto error;
+    }
+
+    mv_eth_unmask_interrupts(priv);
+
+    ETH_DBG( ETH_DBG_LOAD, ("%s: start ok\n", dev->name) );
+
+    printk( KERN_NOTICE "%s: started\n", dev->name );
+
+    return 0;
+
+ error:
+
+    if( dev->irq != 0 )
+    {
+        free_irq( dev->irq, priv );
+    }
+
+    printk( KERN_ERR "%s: start failed\n", dev->name );
+    return -1;
+}
+
+/*********************************************************** 
+ * mv_eth_stop --                                       *
+ *   stop interface with linux core. stop port activity.   *
+ *   free skb's from rings.                                *
+ ***********************************************************/
+int mv_eth_stop( struct net_device *dev )
+{
+    unsigned long   flags;
+    mv_eth_priv     *priv = MV_ETH_PRIV(dev);
+
+    /* first make sure that the port finished its Rx polling - see tg3 */
+    /* otherwise it may cause issue in SMP, one CPU is here and the other is doing the polling
+    and both of it are messing with the descriptors rings!! */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    netif_poll_disable(dev);
+#else
+    napi_disable(&priv->napi);
+#endif
+    spin_lock_irqsave( priv->lock, flags);
+
+    /* stop upper layer */
+    netif_carrier_off( dev );
+    netif_stop_queue( dev );
+
+    /* stop tx/rx activity, mask all interrupts, relese skb in rings,*/
+    mv_eth_stop_internals( priv );
+    
+    spin_unlock_irqrestore( priv->lock, flags);
+
+    if( dev->irq != 0 )
+    {
+        free_irq( dev->irq, priv );
+    }
+    printk( KERN_NOTICE "%s: stopped\n", dev->name );
+
+    return 0;
+}
+
+
+int mv_eth_change_mtu( struct net_device *dev, int mtu )
+{
+    int old_mtu = dev->mtu;
+
+    if(!netif_running(dev)) {
+    	if(mv_eth_change_mtu_internals(dev, mtu) == -1) {
+            goto error;
+    }
+        printk( KERN_NOTICE "%s: change mtu %d (buffer-size %d) to %d (buffer-size %d)\n",
+                dev->name, old_mtu, MV_RX_BUF_SIZE( old_mtu), 
+                dev->mtu, MV_RX_BUF_SIZE( dev->mtu) );
+        return 0;
+    }
+
+    if( mv_eth_stop( dev )) {
+        printk( KERN_ERR "%s: stop interface failed\n", dev->name );
+        goto error;
+    }
+
+    if(mv_eth_change_mtu_internals(dev, mtu) == -1) {
+        goto error;
+    }
+
+    if(mv_eth_start( dev )) {
+        printk( KERN_ERR "%s: start interface failed\n", dev->name );
+        goto error;
+    } 
+    printk( KERN_NOTICE "%s: change mtu %d (buffer-size %d) to %d (buffer-size %d)\n",
+                dev->name, old_mtu, MV_RX_BUF_SIZE(old_mtu), dev->mtu, 
+                MV_RX_BUF_SIZE(dev->mtu));
+ 
+    return 0;
+
+ error:
+    printk( "%s: change mtu failed\n", dev->name );
+    return -1;
+}
+
+/*********************************************************** 
+ * eth_set_mac_addr --                                   *
+ *   stop port activity. set new addr in device and hw.    *
+ *   restart port activity.                                *
+ ***********************************************************/
+static int mv_eth_set_mac_addr_internals(struct net_device *dev, void *addr )
+{
+    mv_eth_priv *priv = MV_ETH_PRIV(dev);
+    u8          *mac = &(((u8*)addr)[2]);  /* skip on first 2B (ether HW addr type) */
+    int i;
+
+    /* remove previous address table entry */
+    if( mvEthMacAddrSet( priv->hal_priv, dev->dev_addr, -1) != MV_OK ) {
+        printk( KERN_ERR "%s: ethSetMacAddr failed\n", dev->name );
+        return -1;
+    }
+
+    /* set new addr in hw */
+    if( mvEthMacAddrSet( priv->hal_priv, mac, ETH_DEF_RXQ) != MV_OK ) {
+        printk( KERN_ERR "%s: ethSetMacAddr failed\n", dev->name );
+    return -1;
+    }
+
+    /* set addr in the device */ 
+    for( i = 0; i < 6; i++ )
+        dev->dev_addr[i] = mac[i];
+
+    printk( KERN_NOTICE "%s: mac address changed\n", dev->name );
+
+    return 0;
+}
+
+/***********************************************************
+ * eth_set_multicast_list --                             *
+ *   Add multicast addresses or set promiscuous mode.      *
+ *   This function should have been but was not included   *
+ *   by Marvell. -bbozarth                                 *
+ ***********************************************************/
+void mv_eth_set_multicast_list(struct net_device *dev) {
+
+     mv_eth_priv        *priv = MV_ETH_PRIV(dev);
+     int                queue = ETH_DEF_RXQ;
+     struct dev_mc_list *curr_addr = dev->mc_list;
+     int                i;
+
+     if (dev->flags & IFF_PROMISC)
+     {
+        mvEthRxFilterModeSet(priv->hal_priv, 1);
+     }
+     else if (dev->flags & IFF_ALLMULTI)
+     {
+        mvEthRxFilterModeSet(priv->hal_priv, 0);
+        mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue);
+        mvEthSetSpecialMcastTable(priv->port, queue);
+        mvEthSetOtherMcastTable(priv->port, queue);
+     }
+     else if (dev->mc_count)
+     {
+        mvEthRxFilterModeSet(priv->hal_priv, 0);
+        mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue);
+        for (i=0; i<dev->mc_count; i++, curr_addr = curr_addr->next)
+        {
+            if (!curr_addr)
+                break;
+            mvEthMcastAddrSet(priv->hal_priv, curr_addr->dmi_addr, queue);
+        }
+     }
+     else /* No Mcast addrs, not promisc or all multi - clear tables */
+     {
+        mvEthRxFilterModeSet(priv->hal_priv, 0);
+        mvEthMacAddrSet(priv->hal_priv, dev->dev_addr, queue);
+     }
+}
+
+
+int     mv_eth_set_mac_addr( struct net_device *dev, void *addr )
+{
+    if(!netif_running(dev)) {
+        if(mv_eth_set_mac_addr_internals(dev, addr) == -1)
+            goto error;
+        return 0;
+    }
+
+    if( mv_eth_stop( dev )) {
+        printk( KERN_ERR "%s: stop interface failed\n", dev->name );
+        goto error;
+    }
+
+    if(mv_eth_set_mac_addr_internals(dev, addr) == -1)
+        goto error;
+
+    if(mv_eth_start( dev )) {
+        printk( KERN_ERR "%s: start interface failed\n", dev->name );
+    goto error;
+    } 
+
+    return 0;
+
+ error:
+    printk( "%s: set mac addr failed\n", dev->name );
+    return -1;
+}
+
+
+/************************************************************ 
+ * mv_eth_open -- Restore MAC address and call to   *
+ *                mv_eth_start                               *
+ ************************************************************/
+int mv_eth_open( struct net_device *dev )
+{
+    mv_eth_priv	*priv = MV_ETH_PRIV(dev);
+    int         queue = ETH_DEF_RXQ;
+
+    if( mvEthMacAddrSet( priv->hal_priv, dev->dev_addr, queue) != MV_OK ) {
+        printk( KERN_ERR "%s: ethSetMacAddr failed\n", dev->name );
+        return -1;
+    }
+
+    if(mv_eth_start( dev )){
+        printk( KERN_ERR "%s: start interface failed\n", dev->name );
+        return -1;
+    } 
+    return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_gateway.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_gateway.c
new file mode 100755
index 0000000..910991e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_gateway.c
@@ -0,0 +1,1443 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"  /* Should be included before mvSysHwConfig */
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/version.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "dbg-trace.h"
+#include "mvSysHwConfig.h"
+#include "eth/mvEth.h"
+#include "eth/gbe/mvEthGbe.h"
+#include "eth-phy/mvEthPhy.h"
+#include "mvSysEthApi.h"
+#include "msApi.h"
+#include "boardEnv/mvBoardEnvLib.h"
+
+#include "mv_netdev.h"
+
+int SWITCH_PORT_CPU;
+int SWITCH_PORT_0;
+int SWITCH_PORT_1;
+int SWITCH_PORT_2;
+int SWITCH_PORT_3;
+int SWITCH_PORT_4;
+
+
+/* use this MACRO to find if a certain port (0-7) is actually connected */
+#define SWITCH_IS_PORT_CONNECTED(p)	                            \
+            ( ((p) == SWITCH_PORT_CPU) || ((p) == SWITCH_PORT_0) || \
+			  ((p) == SWITCH_PORT_1)   || ((p) == SWITCH_PORT_2) || \
+			  ((p) == SWITCH_PORT_3)   || ((p) == SWITCH_PORT_4) ) 
+
+/* helpers for VLAN tag handling */
+#define MV_GTW_PORT_VLAN_ID(grp,port)  ((grp)+(port)+1)
+#define MV_GTW_GROUP_VLAN_ID(grp)      (((grp)+1)<<8)
+#define MV_GTW_VLANID_TO_PORT(vlanid)  (((vlanid) & 0xf)-1)
+
+unsigned int        switch_enabled_ports;
+
+#ifdef CONFIG_MV_GTW_LINK_STATUS
+static int          switch_irq = -1;
+struct timer_list   switch_link_timer;
+#endif
+
+#ifdef CONFIG_MV_GTW_IGMP
+extern int mv_gtw_igmp_snoop_init(void);
+extern int mv_gtw_igmp_snoop_exit(void);
+extern int mv_gtw_igmp_snoop_process(struct sk_buff* skb, unsigned char port, unsigned char vlan_dbnum);
+#endif 
+
+/* Example: "mv_net_config=(eth0,00:99:88:88:99:77,0)(eth1,00:55:44:55:66:77,1:2:3:4),mtu=1500" */
+static char *cmdline = NULL;
+
+struct mv_gtw_config    gtw_config;
+
+GT_QD_DEV qddev,        *qd_dev = NULL;
+static GT_SYS_CONFIG    qd_cfg;
+
+static int mv_gtw_port2lport(int port)
+{
+    if(port==SWITCH_PORT_0) return 0;
+    if(port==SWITCH_PORT_1) return 1;
+    if(port==SWITCH_PORT_2) return 2;
+    if(port==SWITCH_PORT_3) return 3;
+    if(port==SWITCH_PORT_4) return 4;
+    return -1;
+} 
+
+/* Local function prototypes */
+
+/* Required to get the configuration string from the Kernel Command Line */
+int mv_gtw_cmdline_config(char *s);
+__setup("mv_net_config=", mv_gtw_cmdline_config);
+
+int mv_gtw_cmdline_config(char *s)
+{
+    cmdline = s;
+    return 1;
+}
+
+static int mv_gtw_check_open_bracket(char **p_net_config)
+{
+    if (**p_net_config == '(') {
+        (*p_net_config)++;
+	return 0;
+    }
+    printk("Syntax error: could not find opening bracket\n");
+    return -EINVAL;
+}
+
+static int mv_gtw_check_closing_bracket(char **p_net_config)
+{
+    if (**p_net_config == ')') {
+        (*p_net_config)++;
+	return 0;
+    }
+    printk("Syntax error: could not find closing bracket\n");
+    return -EINVAL;
+}
+
+static int mv_gtw_check_comma(char **p_net_config)
+{
+    if (**p_net_config == ',') {
+        (*p_net_config)++;
+	    return 0;
+    }
+    printk("Syntax error: could not find comma\n");
+    return -EINVAL;
+}
+
+
+static int mv_gtw_is_digit(char ch)
+{
+    if( ((ch >= '0') && (ch <= '9')) ||
+	((ch >= 'a') && (ch <= 'f')) ||
+	((ch >= 'A') && (ch <= 'F')) )
+	    return 0;
+
+    return -1;
+}
+
+static int mv_gtw_get_cmdline_mac_addr(char **p_net_config, int idx)
+{
+    /* the MAC address should look like: 00:99:88:88:99:77 */
+    /* that is, 6 two-digit numbers, separated by :        */
+    /* 6 times two-digits, plus 5 colons, total: 17 characters */
+    const int   exact_len = 17; 
+    int         i = 0;
+    int         syntax_err = 0;
+    char	    *p_mac_addr = *p_net_config;
+
+    /* check first 15 characters in groups of 3 characters at a time */
+    for (i = 0; i < exact_len-2; i+=3) 
+    {
+	    if ( (mv_gtw_is_digit(**p_net_config) == 0) &&
+	         (mv_gtw_is_digit(*(*p_net_config+1)) == 0) &&
+	         ((*(*p_net_config+2)) == ':') )
+	    {
+	        (*p_net_config) += 3;
+	    }
+	    else {
+	        syntax_err = 1;
+	        break;
+	    }
+    }
+
+    /* two characters remaining, must be two digits */
+    if ( (mv_gtw_is_digit(**p_net_config) == 0) &&
+         (mv_gtw_is_digit(*(*p_net_config+1)) == 0) )
+    {
+	    (*p_net_config) += 2;
+    }
+    else
+	    syntax_err = 1;
+
+    if (syntax_err == 0) {
+        mvMacStrToHex(p_mac_addr, gtw_config.vlan_cfg[idx].macaddr);
+        return 0;
+    }
+    printk("Syntax error while parsing MAC address from command line\n");
+    return -EINVAL;
+}
+
+static void mv_gtw_update_curr_port_mask(char digit, unsigned int *curr_port_mask)
+{
+    if (digit == '0')
+	    *curr_port_mask |= (1<<SWITCH_PORT_0);
+    if (digit == '1')
+	    *curr_port_mask |= (1<<SWITCH_PORT_1);
+    if (digit == '2')
+	    *curr_port_mask |= (1<<SWITCH_PORT_2);
+    if (digit == '3')
+	    *curr_port_mask |= (1<<SWITCH_PORT_3);
+    if (digit == '4')
+	    *curr_port_mask |= (1<<SWITCH_PORT_4);
+}
+
+static int mv_gtw_get_port_mask(char **p_net_config, int idx)
+{
+    /* the port mask should look like this: */
+    /* example 1: 0 */
+    /* example 2: 1:2:3:4 */
+    /* that is, one or more one-digit numbers, separated with : */
+    /* we have up to GTW_MAX_NUM_OF_IFS interfaces */
+
+    unsigned int curr_port_mask = 0, i = 0;
+    int syntax_err = 0;
+
+    for (i = 0; i < GTW_MAX_NUM_OF_IFS; i++) 
+    {
+	    if (mv_gtw_is_digit(**p_net_config) == 0) 
+        {
+	        if (*(*p_net_config+1) == ':') 
+            {
+		        mv_gtw_update_curr_port_mask(**p_net_config, &curr_port_mask);
+		        (*p_net_config) += 2;
+	        }
+	        else if (*(*p_net_config+1) == ')') 
+            {
+		        mv_gtw_update_curr_port_mask(**p_net_config, &curr_port_mask);
+		        (*p_net_config)++;
+		        break;
+	        }
+	        else {
+		        syntax_err = 1;
+		        break;
+	        }
+	    }
+	    else {
+	        syntax_err = 1;
+	        break;
+	    }
+    }
+
+    if (syntax_err == 0) {
+	    gtw_config.vlan_cfg[idx].ports_mask = curr_port_mask;
+	    return 0;
+    }
+    printk("Syntax error while parsing port mask from command line\n");
+    return -EINVAL;
+}
+
+static int mv_gtw_get_mtu(char **p_net_config)
+{
+    /* the mtu value is constructed as follows: */
+    /* mtu=value                                */
+    unsigned int mtu;
+    int syntax_err = 0;
+
+    if(strncmp(*p_net_config,"mtu=",4) == 0)
+    {
+        *p_net_config += 4;
+        mtu = 0;
+        while((**p_net_config >= '0') && (**p_net_config <= '9'))
+        {       
+            mtu = (mtu * 10) + (**p_net_config - '0');
+            *p_net_config += 1;
+        }
+        if(**p_net_config != '\0')
+            syntax_err = 1;
+    }
+    else
+    {
+        syntax_err = 1;
+    }
+
+    if(syntax_err == 0)
+    {
+        gtw_config.mtu = mtu;
+        printk("      o MTU set to %d.\n", mtu);
+        return 0;
+    }
+
+    printk("Syntax error while parsing mtu value from command line\n");
+    return -EINVAL;
+}
+
+static int mv_gtw_parse_net_config(char* cmdline)
+{
+    char    *p_net_config = cmdline;
+    int     i = 0;
+    int     status = 0;
+
+    if (p_net_config == NULL)
+	    return -EINVAL;
+
+    for (i=0; (i<GTW_MAX_NUM_OF_IFS) && (*p_net_config != '\0'); i++) 
+    {
+        status = mv_gtw_check_open_bracket(&p_net_config);
+	    if (status != 0)
+	        break;
+	    status = mv_gtw_get_cmdline_mac_addr(&p_net_config, i);
+	    if (status != 0)
+	        break;
+	    status = mv_gtw_check_comma(&p_net_config);
+	    if (status != 0)
+	        break;
+	    status = mv_gtw_get_port_mask(&p_net_config, i);
+	    if (status != 0)
+	        break;
+	    status = mv_gtw_check_closing_bracket(&p_net_config);
+	    if (status != 0)
+	        break;
+
+	    gtw_config.vlans_num++;
+
+        /* If we have a comma after the closing bracket, then interface */
+        /* definition is done.                                          */
+        if(*p_net_config == ',')
+            break;
+    }
+
+    if(*p_net_config != '\0')
+    {
+        status = mv_gtw_check_comma(&p_net_config);
+        if (status == 0)
+        {
+            status = mv_gtw_get_mtu(&p_net_config);
+        }
+    }
+    else
+    {
+        gtw_config.mtu = 1500;
+        printk("      o Using default MTU %d\n", gtw_config.mtu);
+    }
+    
+    /* at this point, we have parsed up to GTW_MAX_NUM_OF_IFS, and the mtu value */
+    /* if the net_config string is not finished yet, then its format is invalid */
+    if (*p_net_config != '\0')
+    {
+        printk("Gateway config string is too long: %s\n", p_net_config);
+        status = -EINVAL;
+    }
+    return status;
+}
+
+GT_BOOL gtwReadMiiWrap(GT_QD_DEV* dev, unsigned int portNumber, unsigned int MIIReg, unsigned int* value)
+{
+    unsigned long   flags;
+    unsigned short  tmp;
+    MV_STATUS       status;
+
+    spin_lock_irqsave(&mii_lock, flags);
+
+    status = mvEthPhyRegRead(portNumber, MIIReg , &tmp);
+    spin_unlock_irqrestore(&mii_lock, flags);
+    *value = tmp;
+
+    if (status == MV_OK)
+        return GT_TRUE;
+
+    return GT_FALSE;
+}
+
+
+GT_BOOL gtwWriteMiiWrap(GT_QD_DEV* dev, unsigned int portNumber, unsigned int MIIReg, unsigned int data)
+{
+    unsigned long   flags;
+    unsigned short  tmp;
+    MV_STATUS       status;
+
+    spin_lock_irqsave(&mii_lock, flags);
+    tmp = (unsigned short)data;
+    status = mvEthPhyRegWrite(portNumber, MIIReg, tmp);
+
+    spin_unlock_irqrestore(&mii_lock, flags);
+
+    if (status == MV_OK)
+        return GT_TRUE;
+
+    return GT_FALSE;
+} 
+
+static int mv_gtw_set_port_based_vlan(unsigned int ports_mask)
+{
+    unsigned int p, pl;
+    unsigned char cnt;
+    GT_LPORT port_list[MAX_SWITCH_PORTS];
+
+    for(p=0; p<qd_dev->numOfPorts; p++) {
+	if( MV_BIT_CHECK(ports_mask, p) && (p != SWITCH_PORT_CPU) ) {
+	    ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("port based vlan, port %d: ",p));
+	    for(pl=0,cnt=0; pl<qd_dev->numOfPorts; pl++) {
+		if( MV_BIT_CHECK(ports_mask, pl) && (pl != p) ) {
+		    ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("%d ",pl));
+		    port_list[cnt] = pl;
+                    cnt++;
+                }
+	    }
+            if( gvlnSetPortVlanPorts(qd_dev, p, port_list, cnt) != GT_OK) {
+	        printk("gvlnSetPortVlanPorts failed\n");
+                return -1;
+            }
+	    ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("\n"));
+        }
+    }
+    return 0;
+}
+
+
+static int mv_gtw_set_vlan_in_vtu(unsigned short vlan_id,unsigned int ports_mask)
+{
+    GT_VTU_ENTRY vtu_entry;
+    unsigned int p;
+
+    vtu_entry.vid = vlan_id;
+    vtu_entry.DBNum = MV_GTW_VLAN_TO_GROUP(vlan_id);
+    vtu_entry.vidPriOverride = GT_FALSE;
+    vtu_entry.vidPriority = 0;
+    vtu_entry.vidExInfo.useVIDFPri = GT_FALSE;
+    vtu_entry.vidExInfo.vidFPri = 0;
+    vtu_entry.vidExInfo.useVIDQPri = GT_FALSE;
+    vtu_entry.vidExInfo.vidQPri = 0;
+    vtu_entry.vidExInfo.vidNRateLimit = GT_FALSE;
+    ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("vtu entry: vid=0x%x, port ", vtu_entry.vid));
+    for(p=0; p<qd_dev->numOfPorts; p++) {
+        if(MV_BIT_CHECK(ports_mask, p)) {
+	    ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("%d ", p));
+	    if(qd_dev->deviceId == GT_88E6061) {
+                /* for 6061 device, no double/provider tag controlling on ingress. */
+                /* therefore, we need to strip the tag on egress on all ports except cpu port */
+                /* anyway, if we're using header mode no vlan-tag need to be added here */
+		vtu_entry.vtuData.memberTagP[p] = MEMBER_EGRESS_UNMODIFIED;
+	    }
+	    else {
+		vtu_entry.vtuData.memberTagP[p] = MEMBER_EGRESS_UNMODIFIED;
+	    }
+	}
+	else {
+	    vtu_entry.vtuData.memberTagP[p] = NOT_A_MEMBER;
+	}
+	vtu_entry.vtuData.portStateP[p] = 0;
+    }
+    if(gvtuAddEntry(qd_dev, &vtu_entry) != GT_OK) {
+        printk("gvtuAddEntry failed\n");
+        return -1;
+    }
+
+    ETH_DBG( ETH_DBG_LOAD|ETH_DBG_MCAST|ETH_DBG_VLAN, ("\n"));
+    return 0;
+}
+
+int mv_gtw_set_mac_addr_to_switch(unsigned char *mac_addr, unsigned char db, unsigned int ports_mask, unsigned char op)
+{
+    GT_ATU_ENTRY mac_entry;
+    struct mv_vlan_cfg *nc;
+
+    /* validate db with VLAN id */
+    nc = &gtw_config.vlan_cfg[db];
+    if(MV_GTW_VLAN_TO_GROUP(nc->vlan_grp_id) != db) {
+        printk("mv_gtw_set_mac_addr_to_switch (invalid db)\n");
+	return -1;
+    }
+
+    memset(&mac_entry,0,sizeof(GT_ATU_ENTRY));
+
+    mac_entry.trunkMember = GT_FALSE;
+    mac_entry.prio = 0;
+    mac_entry.exPrio.useMacFPri = GT_FALSE;
+    mac_entry.exPrio.macFPri = 0;
+    mac_entry.exPrio.macQPri = 0;
+    mac_entry.DBNum = db;
+    mac_entry.portVec = ports_mask;
+    memcpy(mac_entry.macAddr.arEther,mac_addr,6);
+
+    if(is_multicast_ether_addr(mac_addr))
+	mac_entry.entryState.mcEntryState = GT_MC_STATIC;
+    else
+	mac_entry.entryState.ucEntryState = GT_UC_NO_PRI_STATIC;
+
+    ETH_DBG(ETH_DBG_ALL, ("mv_gateway: db%d port-mask=0x%x, %02x:%02x:%02x:%02x:%02x:%02x ",
+	    db, (unsigned int)mac_entry.portVec,
+	    mac_entry.macAddr.arEther[0],mac_entry.macAddr.arEther[1],mac_entry.macAddr.arEther[2],
+	    mac_entry.macAddr.arEther[3],mac_entry.macAddr.arEther[4],mac_entry.macAddr.arEther[5]));
+
+    if((op == 0) || (mac_entry.portVec == 0)) {
+        if(gfdbDelAtuEntry(qd_dev, &mac_entry) != GT_OK) {
+	    printk("gfdbDelAtuEntry failed\n");
+	    return -1;
+        }
+	ETH_DBG(ETH_DBG_ALL, ("deleted\n"));
+    }
+    else {
+        if(gfdbAddMacEntry(qd_dev, &mac_entry) != GT_OK) {
+	    printk("gfdbAddMacEntry failed\n");
+	    return -1;
+        }
+	ETH_DBG(ETH_DBG_ALL, ("added\n"));
+    }
+
+    return 0;
+}
+
+#ifdef CONFIG_MV_GTW_IGMP
+int mv_gtw_enable_igmp(void)
+{
+    unsigned char p;
+
+    ETH_DBG( ETH_DBG_IGMP, ("enabling L2 IGMP snooping\n"));
+
+    /* enable IGMP snoop on all ports (except cpu port) */
+    for(p=0; p<qd_dev->numOfPorts; p++) {
+	if(p != SWITCH_PORT_CPU) {
+	    if(gprtSetIGMPSnoop(qd_dev, p, GT_TRUE) != GT_OK) {
+		printk("gprtSetIGMPSnoop failed\n");
+		return -1;
+	    }
+	}
+    }
+    return -1;
+}
+#endif /* CONFIG_MV_GTW_IGMP */
+
+
+int __init mv_gtw_net_setup(int port)
+{
+    struct mv_vlan_cfg  *nc;
+    int                 i = 0;
+
+    SWITCH_PORT_CPU = mvBoardSwitchCpuPortGet(port);
+    SWITCH_PORT_0   = mvBoardSwitchPortGet(port, 0);
+    SWITCH_PORT_1   = mvBoardSwitchPortGet(port, 1);
+    SWITCH_PORT_2   = mvBoardSwitchPortGet(port, 2);
+    SWITCH_PORT_3   = mvBoardSwitchPortGet(port, 3);
+    SWITCH_PORT_4   = mvBoardSwitchPortGet(port, 4);
+
+#ifdef CONFIG_MV_GTW_LINK_STATUS
+    switch_irq = mvBoardLinkStatusIrqGet(port);
+    if(switch_irq != -1)
+        switch_irq += IRQ_GPP_START;
+#endif
+
+    /* build the net config table */
+    memset(&gtw_config, 0, sizeof(struct mv_gtw_config));
+
+    if(cmdline != NULL) 
+    {
+	    printk("      o Using command line network interface configuration\n");
+    }
+    else
+    {
+	    printk("      o Using default network configuration, overriding boot MAC address\n");
+	    cmdline = CONFIG_MV_GTW_CONFIG;
+    }
+
+	if (mv_gtw_parse_net_config(cmdline) < 0) 
+    {
+	    printk("Error parsing mv_net_config\n");
+	    return -EINVAL;
+    }           
+
+    /* CPU port should always be enabled */
+    switch_enabled_ports = (1 << SWITCH_PORT_CPU); 
+
+    for(i=0, nc=&gtw_config.vlan_cfg[i]; i<gtw_config.vlans_num; i++, nc++) 
+    {
+	    /* VLAN ID */
+	    nc->vlan_grp_id = MV_GTW_GROUP_VLAN_ID(i);
+	    nc->ports_link = 0;
+	    nc->header = cpu_to_be16(	(MV_GTW_VLAN_TO_GROUP(nc->vlan_grp_id) << 12) 
+                    			| nc->ports_mask);
+	    /* print info */
+	    printk("      o mac_addr %02x:%02x:%02x:%02x:%02x:%02x, VID 0x%03x, port list: ", 
+                nc->macaddr[0], nc->macaddr[1], nc->macaddr[2], 
+		        nc->macaddr[3], nc->macaddr[4], nc->macaddr[5], nc->vlan_grp_id);
+
+	    if(nc->ports_mask & (1<<SWITCH_PORT_CPU)) 
+            printk("port-CPU ");
+	    if(nc->ports_mask & (1<<SWITCH_PORT_0)) 
+            printk("port-0 ");
+	    if(nc->ports_mask & (1<<SWITCH_PORT_1)) 
+            printk("port-1 ");
+	    if(nc->ports_mask & (1<<SWITCH_PORT_2)) 
+            printk("port-2 ");
+	    if(nc->ports_mask & (1<<SWITCH_PORT_3)) 
+            printk("port-3 ");
+	    if(nc->ports_mask & (1<<SWITCH_PORT_4)) 
+            printk("port-4 ");
+	    printk("\n");
+
+	    /* collect per-interface port_mask into a global port_mask, used for enabling the Switch ports */
+	    switch_enabled_ports |= nc->ports_mask;
+    }
+
+    return 0;
+}
+
+static int mv_switch_init(int port)
+{
+    unsigned int        i, p;
+    unsigned char       cnt;
+    GT_LPORT            port_list[MAX_SWITCH_PORTS];
+    struct mv_vlan_cfg  *nc;
+    GT_JUMBO_MODE       jumbo_mode;
+
+    /* printk("init switch layer... "); */
+
+    memset((char*)&qd_cfg,0,sizeof(GT_SYS_CONFIG));
+
+    /* init config structure for qd package */
+    qd_cfg.BSPFunctions.readMii   = gtwReadMiiWrap;
+    qd_cfg.BSPFunctions.writeMii  = gtwWriteMiiWrap;
+    qd_cfg.BSPFunctions.semCreate = NULL;
+    qd_cfg.BSPFunctions.semDelete = NULL;
+    qd_cfg.BSPFunctions.semTake   = NULL;
+    qd_cfg.BSPFunctions.semGive   = NULL;
+    qd_cfg.initPorts = GT_TRUE;
+    qd_cfg.cpuPortNum = SWITCH_PORT_CPU;
+    if (mvBoardSmiScanModeGet(port) == 1) {
+	qd_cfg.mode.baseAddr = 0;
+        qd_cfg.mode.scanMode = SMI_MANUAL_MODE;
+    }
+    else if (mvBoardSmiScanModeGet(port) == 2) {
+	qd_cfg.mode.baseAddr = 0xA;
+        qd_cfg.mode.scanMode = SMI_MULTI_ADDR_MODE;
+    }
+    /* load switch sw package */
+    if( qdLoadDriver(&qd_cfg, &qddev) != GT_OK) {
+	printk("qdLoadDriver failed\n");
+        return -1;
+    }
+    qd_dev = &qddev;
+
+    ETH_DBG( ETH_DBG_LOAD, ("Device ID     : 0x%x\n",qd_dev->deviceId));
+    ETH_DBG( ETH_DBG_LOAD, ("Base Reg Addr : 0x%x\n",qd_dev->baseRegAddr));
+    ETH_DBG( ETH_DBG_LOAD, ("No. of Ports  : %d\n",qd_dev->numOfPorts));
+    ETH_DBG( ETH_DBG_LOAD, ("CPU Ports     : %ld\n",qd_dev->cpuPortNum));
+
+    /* disable all ports */
+    for(p=0; p<qd_dev->numOfPorts; p++) {
+	    gstpSetPortState(qd_dev, p, GT_PORT_DISABLE);
+    }
+
+    /* initialize Switch according to Switch ID */
+    switch (qd_dev->deviceId) 
+    {
+	    case GT_88E6131:
+	    case GT_88E6108:
+	        /* enable external ports */
+	        ETH_DBG( ETH_DBG_LOAD, ("enable phy polling for external ports\n"));
+	        if(gsysSetPPUEn(qd_dev, GT_TRUE) != GT_OK) {
+		        printk("gsysSetPPUEn failed\n");
+		        return -1;
+	        }
+	        /* Note: The GbE unit in SoCs connected to these switches does not support Marvell Header Mode */
+	        /* so we always use VLAN tags here */
+	        /* set cpu-port with ingress double-tag mode */
+	        ETH_DBG( ETH_DBG_LOAD, ("cpu port ingress double-tag mode\n"));
+	        if(gprtSetDoubleTag(qd_dev, SWITCH_PORT_CPU, GT_TRUE) != GT_OK) {
+	            printk("gprtSetDoubleTag failed\n");
+	            return -1;
+	        }
+	        /* set cpu-port with egrees add-tag mode */
+	        ETH_DBG( ETH_DBG_LOAD, ("cpu port egrees add-tag mode\n"));
+	        if(gprtSetEgressMode(qd_dev, SWITCH_PORT_CPU, GT_ADD_TAG) != GT_OK) {
+		        printk("gprtSetEgressMode failed\n");
+		    return -1;
+	        }
+	        /* config the switch to use the double tag data (relevant to cpu-port only) */
+	        ETH_DBG( ETH_DBG_LOAD, ("use double-tag and remove\n"));
+	        if(gsysSetUseDoubleTagData(qd_dev,GT_TRUE) != GT_OK) {
+	            printk("gsysSetUseDoubleTagData failed\n");
+	            return -1;
+	        }
+	        /* set cpu-port with 802.1q secured mode */
+	        ETH_DBG( ETH_DBG_LOAD, ("cpu port-based 802.1q secure mode\n"));
+	        if(gvlnSetPortVlanDot1qMode(qd_dev,SWITCH_PORT_CPU,GT_SECURE) != GT_OK) {
+		        printk("gvlnSetPortVlanDot1qMode failed\n");
+	            return -1;
+	        }
+	        break;
+	
+	    case GT_88E6065:
+	        /* set CPU port number */
+            if(gsysSetCPUPort(qd_dev, SWITCH_PORT_CPU) != GT_OK) {
+	            printk("gsysSetCPUPort failed\n");
+	            return -1;
+	        }
+
+	        if(gstatsFlushAll(qd_dev) != GT_OK)
+    	        printk("gstatsFlushAll failed\n");
+
+	        /* set all ports not to unmodify the vlan tag on egress */
+	        for(i=0; i<qd_dev->numOfPorts; i++) 
+            {
+		        if(gprtSetEgressMode(qd_dev, i, GT_UNMODIFY_EGRESS) != GT_OK) {
+		            printk("gprtSetEgressMode GT_UNMODIFY_EGRESS failed\n");
+		            return -1;
+		        }
+	        }
+	        if(gprtSetHeaderMode(qd_dev, SWITCH_PORT_CPU, GT_TRUE) != GT_OK) {
+		        printk("gprtSetHeaderMode GT_TRUE failed\n");
+		        return -1;
+	        }
+
+	        /* init counters */
+	        if(gprtClearAllCtr(qd_dev) != GT_OK)
+	            printk("gprtClearAllCtr failed\n");
+	        if(gprtSetCtrMode(qd_dev, GT_CTR_ALL) != GT_OK)
+	            printk("gprtSetCtrMode failed\n");
+
+	        break;
+
+	    case GT_88E6061: 
+	        /* set CPU port number */
+            if(gsysSetCPUPort(qd_dev, SWITCH_PORT_CPU) != GT_OK) {
+	            printk("gsysSetCPUPort failed\n");
+	            return -1;
+	        }
+
+	        /* set all ports not to unmodify the vlan tag on egress */
+	        for(i=0; i<qd_dev->numOfPorts; i++) {
+		        if(gprtSetEgressMode(qd_dev, i, GT_UNMODIFY_EGRESS) != GT_OK) {
+		            printk("gprtSetEgressMode GT_UNMODIFY_EGRESS failed\n");
+		            return -1;
+		        }
+	        }
+	    
+            if(gprtSetHeaderMode(qd_dev,SWITCH_PORT_CPU,GT_TRUE) != GT_OK) {
+		        printk("gprtSetHeaderMode GT_TRUE failed\n");
+		        return -1;
+	        }   
+
+	        /* init counters */
+	        if(gprtClearAllCtr(qd_dev) != GT_OK)
+	            printk("gprtClearAllCtr failed\n");
+	        if(gprtSetCtrMode(qd_dev, GT_CTR_ALL) != GT_OK)
+	            printk("gprtSetCtrMode failed\n");
+
+	        break;
+
+	    case GT_88E6161:
+	    case GT_88E6165:
+            if(gstatsFlushAll(qd_dev) != GT_OK) {
+                printk("gstatsFlushAll failed\n");
+            }
+
+	        /* set all ports not to unmodify the vlan tag on egress */
+	        for(i=0; i<qd_dev->numOfPorts; i++) {
+		        if(gprtSetEgressMode(qd_dev, i, GT_UNMODIFY_EGRESS) != GT_OK) {
+		            printk("gprtSetEgressMode GT_UNMODIFY_EGRESS failed\n");
+		            return -1;
+		        }
+	        }
+	        if(gprtSetHeaderMode(qd_dev,SWITCH_PORT_CPU,GT_TRUE) != GT_OK) {
+		        printk("gprtSetHeaderMode GT_TRUE failed\n");
+		        return -1;
+	        }
+
+            	/* Setup jumbo frames mode.                         */
+	        if( MV_RX_BUF_SIZE(gtw_config.mtu) <= 1522)
+                	jumbo_mode = GT_JUMBO_MODE_1522;
+            	else if( MV_RX_BUF_SIZE(gtw_config.mtu) <= 2048)
+                	jumbo_mode = GT_JUMBO_MODE_2048;
+            	else
+                	jumbo_mode = GT_JUMBO_MODE_10240;
+
+            	for(i=0; i<qd_dev->numOfPorts; i++) {
+                	if(gsysSetJumboMode(qd_dev, i, jumbo_mode) != GT_OK) {
+                    		printk("gsysSetJumboMode %d failed\n",jumbo_mode);
+                    		return -1;
+                	}
+            	}
+	        break;	
+
+	    default:
+	        printk("Unsupported Switch. Switch ID is 0x%X.\n",qd_dev->deviceId);
+	        return -1;
+    }
+
+    /* set priorities rules */
+    for(i=0; i<qd_dev->numOfPorts; i++) {
+        /* default port priority to queue zero */
+	    if(gcosSetPortDefaultTc(qd_dev, i, 0) != GT_OK)
+	        printk("gcosSetPortDefaultTc failed (port %d)\n", i);
+        
+        /* enable IP TOS Prio */
+	    if(gqosIpPrioMapEn(qd_dev, i, GT_TRUE) != GT_OK)
+	        printk("gqosIpPrioMapEn failed (port %d)\n",i);
+	
+        /* set IP QoS */
+	    if(gqosSetPrioMapRule(qd_dev, i, GT_FALSE) != GT_OK)
+	        printk("gqosSetPrioMapRule failed (port %d)\n",i);
+        
+        /* disable Vlan QoS Prio */
+	    if(gqosUserPrioMapEn(qd_dev, i, GT_FALSE) != GT_OK)
+	        printk("gqosUserPrioMapEn failed (port %d)\n",i);
+        
+        /* Set force flow control to FALSE for all ports */
+	    if(gprtSetForceFc(qd_dev, i, GT_FALSE) != GT_OK)
+	        printk("gprtSetForceFc failed (port %d)\n",i);
+    }
+
+    /* The switch CPU port is not part of the VLAN, but rather connected by tunneling to each */
+    /* of the VLAN's ports. Our MAC addr will be added during start operation to the VLAN DB  */
+    /* at switch level to forward packets with this DA to CPU port.                           */
+    ETH_DBG( ETH_DBG_LOAD, ("Enabling Tunneling on ports: "));
+    for(i=0; i<qd_dev->numOfPorts; i++) {
+	    if(i != SWITCH_PORT_CPU) {
+	        if(gprtSetVlanTunnel(qd_dev, i, GT_TRUE) != GT_OK) {
+		        printk("gprtSetVlanTunnel failed (port %d)\n",i);
+		        return -1;
+	        }
+	        else {
+		        ETH_DBG( ETH_DBG_LOAD, ("%d ",i));
+	        }
+	    }
+    }
+    ETH_DBG( ETH_DBG_LOAD, ("\n"));
+
+    /* configure ports (excluding CPU port) for each network interface (VLAN): */
+    for(i=0, nc=&gtw_config.vlan_cfg[i]; i<gtw_config.vlans_num; i++,nc++) {
+        ETH_DBG( ETH_DBG_LOAD, ("vlan%d configuration (nc->ports_mask = 0x%08x) \n",
+                                i, nc->ports_mask));
+	    /* set port's defaul private vlan id and database number (DB per group): */
+	    for(p=0; p<qd_dev->numOfPorts; p++) {
+	        if( MV_BIT_CHECK(nc->ports_mask, p) && (p != SWITCH_PORT_CPU) ) {
+		        ETH_DBG(ETH_DBG_LOAD,("port %d default private vlan id: 0x%x\n", p, MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p)));
+		        if( gvlnSetPortVid(qd_dev, p, MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p)) != GT_OK ) {
+			        printk("gvlnSetPortVid failed");
+			        return -1;
+		        }
+		        if( gvlnSetPortVlanDBNum(qd_dev, p, MV_GTW_VLAN_TO_GROUP(nc->vlan_grp_id)) != GT_OK) {
+		            printk("gvlnSetPortVlanDBNum failed\n");
+		            return -1;
+		        }
+	        }
+	    }
+
+	    /* set port's port-based vlan (CPU port is not part of VLAN) */
+        if(mv_gtw_set_port_based_vlan(nc->ports_mask & ~(1<<SWITCH_PORT_CPU)) != 0) {
+	        printk("mv_gtw_set_port_based_vlan failed\n");
+	    }
+
+        /* set vtu with group vlan id (used in tx) */
+        if(mv_gtw_set_vlan_in_vtu(nc->vlan_grp_id, nc->ports_mask | (1<<SWITCH_PORT_CPU)) != 0) {
+	        printk("mv_gtw_set_vlan_in_vtu failed\n");
+	    }
+
+        /* set vtu with each port private vlan id (used in rx) */
+ 	    for(p=0; p<qd_dev->numOfPorts; p++) {
+	        if(MV_BIT_CHECK(nc->ports_mask, p) && (p!=SWITCH_PORT_CPU)) {
+                if(mv_gtw_set_vlan_in_vtu(MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p),
+                                          nc->ports_mask & ~(1<<SWITCH_PORT_CPU)) != 0) {
+		            printk("mv_gtw_set_vlan_in_vtu failed\n");
+		        }
+	        }
+	    }
+    }
+
+    /* set cpu-port with port-based vlan to all other ports */
+    ETH_DBG( ETH_DBG_LOAD, ("cpu port-based vlan:"));
+    for(p=0,cnt=0; p<qd_dev->numOfPorts; p++) {
+        if(p != SWITCH_PORT_CPU) {
+	        ETH_DBG( ETH_DBG_LOAD, ("%d ",p));
+            port_list[cnt] = p;
+            cnt++;
+        }
+    }
+    ETH_DBG( ETH_DBG_LOAD, ("\n"));
+    if( gvlnSetPortVlanPorts(qd_dev, SWITCH_PORT_CPU, port_list, cnt) != GT_OK) {
+        printk("gvlnSetPortVlanPorts failed\n");
+        return -1;
+    }
+
+    if(gfdbFlush(qd_dev,GT_FLUSH_ALL) != GT_OK) {
+	    printk("gfdbFlush failed\n");
+    }
+
+    /* done! enable all Switch ports according to the net config table */
+    ETH_DBG( ETH_DBG_LOAD, ("enabling: ports "));
+    for(p=0; p<qd_dev->numOfPorts; p++) {
+	    if (MV_BIT_CHECK(switch_enabled_ports, p)) {
+	        ETH_DBG( ETH_DBG_LOAD, ("%d ",p));
+	        if(gstpSetPortState(qd_dev, p, GT_PORT_FORWARDING) != GT_OK) {
+	            printk("gstpSetPortState failed\n");
+	        }
+	    }
+    }
+    ETH_DBG( ETH_DBG_LOAD, ("\n"));
+
+#ifdef CONFIG_MV_GTW_LINK_STATUS
+    /* Enable Phy Link Status Changed interrupt at Phy level for the all enabled ports */
+    for(p=0; p<qd_dev->numOfPorts; p++) {
+	    if(MV_BIT_CHECK(switch_enabled_ports, p) && (p != SWITCH_PORT_CPU)) {
+	        if(gprtPhyIntEnable(qd_dev, p, (GT_LINK_STATUS_CHANGED)) != GT_OK) {
+		        printk("gprtPhyIntEnable failed port %d\n", p);
+	        }
+	    }
+    }
+
+    if ((qd_dev->deviceId != GT_88E6161) && (qd_dev->deviceId != GT_88E6165)) {
+    	if (switch_irq != -1) {
+            if(eventSetActive(qd_dev, GT_PHY_INTERRUPT) != GT_OK) {
+	    	    printk("eventSetActive failed\n");
+            }
+    	}
+    }
+    else {
+	    GT_DEV_EVENT gt_event = {GT_DEV_INT_PHY, 0, 0x1F}; /* 0x1F is a bit mask for ports 0-4 */
+	    if (switch_irq != -1) {
+	        if(eventSetDevInt(qd_dev, &gt_event) != GT_OK) {
+		        printk("eventSetDevInt failed\n");
+	        }
+	        if(eventSetActive(qd_dev, GT_DEVICE_INT) != GT_OK) {
+    	    	printk("eventSetActive failed\n");
+            }
+	    }
+    }
+#endif /* CONFIG_MV_GTW_LINK_STATUS */
+
+    /* Configure Ethernet related LEDs, currently according to Switch ID */
+    switch (qd_dev->deviceId) {
+	    case GT_88E6131:
+	    case GT_88E6108:
+            /* config LEDs: Bi-Color Mode-4:  */
+            /* 1000 Mbps Link - Solid Green; 1000 Mbps Activity - Blinking Green */
+            /* 100 Mbps Link - Solid Red; 100 Mbps Activity - Blinking Red */
+            for(p=0; p<qd_dev->numOfPorts; p++) {	        
+                if( (p != SWITCH_PORT_CPU) && (SWITCH_IS_PORT_CONNECTED(p)) ) {
+			/* Configure Register 16 page 3 to 0x888F for mode 4 */
+	                if(gprtSetPagedPhyReg(qd_dev,p,16,3,0x888F)) { 
+		                printk("gprtSetPagedPhyReg failed (port=%d)\n", p);
+	                }
+			    /* Configure Register 17 page 3 to 0x4400 50% mixed LEDs */
+		            if(gprtSetPagedPhyReg(qd_dev,p,17,3,0x4400)) {
+		                printk("gprtSetPagedPhyReg failed (port=%d)\n", p);
+	                }
+	            }
+            }
+	        break;
+
+	    case GT_88E6161:
+	    case GT_88E6165:
+		    break; /* do nothing */
+
+	    default:
+	        for(p=0; p<qd_dev->numOfPorts; p++) {
+	            if( (p != SWITCH_PORT_CPU) && (SWITCH_IS_PORT_CONNECTED(p)) ) {
+	                if(gprtSetPhyReg(qd_dev,p,22,0x1FFA)) { 
+                        /* Configure Register 22 LED0 to 0xA for Link/Act */
+	    	            printk("gprtSetPhyReg failed (port=%d)\n", p);
+		            }
+	            }
+	        }
+	        break;
+    }
+
+    /* printk("done\n"); */
+
+    return 0;
+}
+
+int mv_gtw_switch_tos_get(int port, unsigned char tos)
+{
+    unsigned char   queue;
+    int             rc;
+
+    rc = gcosGetDscp2Tc(qd_dev, tos>>2, &queue);
+    if(rc)
+        return -1;
+
+    return (int)queue;
+}
+
+int mv_gtw_switch_tos_set(int port, unsigned char tos, int queue)
+{
+    return gcosSetDscp2Tc(qd_dev, tos>>2, (unsigned char)queue);
+}
+
+static struct net_device* mv_gtw_main_net_dev_get(void)
+{
+    int                 i;
+    mv_eth_priv         *priv;
+    struct net_device   *dev;
+
+    for (i=0; i<mv_net_devs_num; i++) {
+        dev = mv_net_devs[i];
+        priv = MV_ETH_PRIV(dev);
+
+        if (netif_running(dev) && priv->isGtw)
+            return dev;
+    }
+    return NULL;
+}
+
+int mv_gtw_set_mac_addr( struct net_device *dev, void *p )
+{
+    struct mv_vlan_cfg *vlan_cfg = MV_NETDEV_VLAN(dev);
+    struct sockaddr *addr = p;
+
+    if(!is_valid_ether_addr(addr->sa_data))
+	    return -EADDRNOTAVAIL;
+
+    /* remove old mac addr from VLAN DB */
+    mv_gtw_set_mac_addr_to_switch(dev->dev_addr,MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id),(1<<SWITCH_PORT_CPU),0);
+
+    memcpy(dev->dev_addr, addr->sa_data, 6);
+
+    /* add new mac addr to VLAN DB */
+    mv_gtw_set_mac_addr_to_switch(dev->dev_addr,MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id),(1<<SWITCH_PORT_CPU),1);
+
+    printk("mv_gateway: %s change mac address to %02x:%02x:%02x:%02x:%02x:%02x\n", 
+        dev->name, *(dev->dev_addr), *(dev->dev_addr+1), *(dev->dev_addr+2), 
+       *(dev->dev_addr+3), *(dev->dev_addr+4), *(dev->dev_addr+5));
+
+    return 0;
+}
+
+void    mv_gtw_set_multicast_list(struct net_device *dev)
+{
+    struct dev_mc_list *curr_addr = dev->mc_list;
+    struct mv_vlan_cfg *vlan_cfg = MV_NETDEV_VLAN(dev);
+    int i;
+    GT_ATU_ENTRY mac_entry;
+    GT_BOOL found = GT_FALSE;
+    GT_STATUS status;
+
+    if((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) {
+	/* promiscuous mode - connect the CPU port to the VLAN (port based + 802.1q) */
+	/*
+	if(dev->flags & IFF_PROMISC)
+	    printk("mv_gateway: setting promiscuous mode\n");
+	if(dev->flags & IFF_ALLMULTI)
+	    printk("mv_gateway: setting multicast promiscuous mode\n");
+	*/
+	mv_gtw_set_port_based_vlan(vlan_cfg->ports_mask|(1<<SWITCH_PORT_CPU));
+	    for(i=0; i<qd_dev->numOfPorts; i++) 
+        {
+	        if(MV_BIT_CHECK(vlan_cfg->ports_mask, i) && (i!=SWITCH_PORT_CPU)) 
+            {
+		        if(mv_gtw_set_vlan_in_vtu(MV_GTW_PORT_VLAN_ID(vlan_cfg->vlan_grp_id,i),
+                                          vlan_cfg->ports_mask | (1<<SWITCH_PORT_CPU)) != 0) 
+                {
+		            printk("mv_gtw_set_vlan_in_vtu failed\n");
+		        }
+	        }
+	    }
+    }
+    else 
+    {
+	/* not in promiscuous or allmulti mode - disconnect the CPU port to the VLAN (port based + 802.1q) */
+	mv_gtw_set_port_based_vlan(vlan_cfg->ports_mask&(~(1<<SWITCH_PORT_CPU)));
+	for(i=0; i<qd_dev->numOfPorts; i++) {
+	    if(MV_BIT_CHECK(vlan_cfg->ports_mask, i) && (i!=SWITCH_PORT_CPU)) {
+		if(mv_gtw_set_vlan_in_vtu(MV_GTW_PORT_VLAN_ID(vlan_cfg->vlan_grp_id,i),vlan_cfg->ports_mask&(~(1<<SWITCH_PORT_CPU))) != 0) {
+		    printk("mv_gtw_set_vlan_in_vtu failed\n");
+		}
+	   }
+	}
+	if(dev->mc_count) {
+	    /* accept specific multicasts */
+	    for(i=0; i<dev->mc_count; i++, curr_addr = curr_addr->next) {
+	        if (!curr_addr)
+		    break;
+		/* The Switch may already have information about this multicast address in      */
+		/* its ATU. If this address is already in the ATU, use the existing port vector */
+		/* ORed with the CPU port. Otherwise, just use the CPU port.                    */
+		memset(&mac_entry,0,sizeof(GT_ATU_ENTRY));
+		        mac_entry.DBNum = MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id);
+		memcpy(mac_entry.macAddr.arEther, curr_addr->dmi_addr, 6);
+		status = gfdbFindAtuMacEntry(qd_dev, &mac_entry, &found);
+		        if ( (status != GT_OK) || (found != GT_TRUE) ) 
+                {
+		            mv_gtw_set_mac_addr_to_switch(curr_addr->dmi_addr,
+		    				  MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id),
+						  (1<<SWITCH_PORT_CPU)|(vlan_cfg->ports_mask), 1);
+		}
+		        else 
+                {
+		            mv_gtw_set_mac_addr_to_switch(curr_addr->dmi_addr,
+						  MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id),
+						  (mac_entry.portVec | (1<<SWITCH_PORT_CPU)), 1);
+		        }
+	        }
+	    }
+    }
+}
+ 
+
+int mv_gtw_change_mtu(struct net_device *dev, int mtu)
+{
+	printk("mv_gateway does not support changing MTU at runtime.\n"); 
+	return -EPERM;
+} 
+
+
+int mv_gtw_start( struct net_device *dev )
+{
+    mv_eth_priv		*priv = MV_ETH_PRIV(dev);
+    struct 		mv_vlan_cfg *vlan_cfg = MV_NETDEV_VLAN(dev);
+    unsigned char	broadcast[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+    printk("mv_gateway: starting %s\n",dev->name);
+
+    /* start upper layer */
+    netif_carrier_on(dev);
+    netif_wake_queue(dev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    netif_poll_enable(dev);
+#else
+    if ( (priv->net_dev == dev) || !netif_running(priv->net_dev) )
+    {
+	napi_enable(&priv->napi);
+    }
+#endif
+
+    /* Add our MAC addr to the VLAN DB at switch level to forward packets with this DA */
+    /* to CPU port by using the tunneling feature. The device is always in promisc mode.      */
+    mv_gtw_set_mac_addr_to_switch(dev->dev_addr, MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id), (1<<SWITCH_PORT_CPU), 1);
+
+    /* We also need to allow L2 broadcasts comming up for this interface */
+    mv_gtw_set_mac_addr_to_switch(broadcast, MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id), 
+					vlan_cfg->ports_mask|(1<<SWITCH_PORT_CPU), 1);
+
+    if (priv->timer_flag == 0)
+    {
+        priv->timer.expires = jiffies + ((HZ*CONFIG_MV_ETH_TIMER_PERIOD)/1000); /*ms*/
+        add_timer( &(priv->timer) );
+        priv->timer_flag = 1;
+    }
+
+    if ( (priv->net_dev == dev) || !netif_running(priv->net_dev) )
+    {
+        priv->net_dev = dev;
+
+	/* connect to MAC port interrupt line */
+    	if ( request_irq( ETH_PORT_IRQ_NUM(priv->port), mv_eth_interrupt_handler, 
+             (IRQF_DISABLED | IRQF_SAMPLE_RANDOM), "mv_gateway", priv) ) 
+	{
+        	printk(KERN_ERR "failed to assign irq%d\n", ETH_PORT_IRQ_NUM(priv->port));
+    	}
+
+        /* unmask interrupts */
+        mv_eth_unmask_interrupts(priv);
+    }
+    
+    return 0;
+}
+
+
+int mv_gtw_stop( struct net_device *dev )
+{
+    mv_eth_priv		    *priv = MV_ETH_PRIV(dev);
+    struct mv_vlan_cfg	*vlan_cfg = MV_NETDEV_VLAN(dev);
+
+    printk("mv_gateway: stopping %s\n",dev->name);
+
+    /* stop upper layer */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    netif_poll_disable(dev);
+#endif
+    netif_carrier_off(dev);
+    netif_stop_queue(dev);
+
+    /* stop switch from forwarding packets from this VLAN toward CPU port */
+    if( gfdbFlushInDB(qd_dev, GT_FLUSH_ALL, MV_GTW_VLAN_TO_GROUP(vlan_cfg->vlan_grp_id)) != GT_OK) {
+        printk("gfdbFlushInDB failed\n");
+    }
+
+    if(priv->net_dev == dev)
+    {
+        struct net_device *main_dev = mv_gtw_main_net_dev_get();
+
+        if(main_dev == NULL)
+        {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+	    napi_disable(&priv->napi);
+#endif
+            mv_eth_mask_interrupts(priv);
+    	    priv->timer_flag = 0;
+            del_timer(&priv->timer);
+
+            free_irq( dev->irq, priv );
+        }
+        else
+        {
+            priv->net_dev = main_dev;
+        }
+    }
+    return 0;
+}
+
+#ifdef CONFIG_MV_GTW_LINK_STATUS
+static void mv_gtw_update_link_status(unsigned int p, unsigned int link_up)
+{
+    struct mv_vlan_cfg  *vlan_cfg;
+    int                 i = 0;
+    unsigned int        prev_ports_link = 0;
+
+    for(i=0; i<mv_net_devs_num; i++) {
+	if (mv_net_devs[i] == NULL)
+		break;
+        vlan_cfg = MV_NETDEV_VLAN(mv_net_devs[i]);
+	    if ( vlan_cfg != NULL) {
+
+	        if ((vlan_cfg->ports_mask & (1 << p)) == 0)
+		        continue;
+
+	        prev_ports_link = vlan_cfg->ports_link;
+ 
+	        if (link_up)
+	            vlan_cfg->ports_link |= (1 << p);
+	        else
+		        vlan_cfg->ports_link &= ~(1 << p);
+
+	        if ((vlan_cfg->ports_link & vlan_cfg->ports_mask) == 0) {
+                    netif_carrier_off(mv_net_devs[i]);
+                    netif_stop_queue(mv_net_devs[i]);
+	        }
+	        else if (prev_ports_link == 0) {
+		        netif_carrier_on(mv_net_devs[i]);
+                netif_wake_queue(mv_net_devs[i]);          
+	        }
+	    }
+    }
+}
+
+static irqreturn_t mv_gtw_link_interrupt_handler(int irq , void *dev_id)
+{
+    unsigned short switch_cause, phy_cause, phys_port, p;
+
+    if (switch_irq != -1 ) {
+	    if ( (qd_dev->deviceId == GT_88E6161) || (qd_dev->deviceId == GT_88E6165) ) {
+	        OUT GT_DEV_INT_STATUS devIntStatus;
+            /* required to clear the interrupt, and updates phys_port */
+	        geventGetDevIntStatus(qd_dev, &devIntStatus); 
+	        phys_port = devIntStatus.phyInt & 0xFF;
+	        if (phys_port)
+		        switch_cause = GT_PHY_INTERRUPT;
+	    }
+	    else {
+	        if(eventGetIntStatus(qd_dev, &switch_cause) != GT_OK)
+	            switch_cause = 0;
+	    }
+    }
+    else {
+	    switch_cause = GT_PHY_INTERRUPT;
+    }
+
+    if(switch_cause & GT_PHY_INTERRUPT) {
+	    /* If we're using a 6161/6165 Switch and using the Switch interrupt, we already have phys_port updated above */
+	    /* If we're using any other Switch, or if we're using polling, we need to update phys_port now */
+	    if ( (qd_dev->deviceId == GT_88E6161) || (qd_dev->deviceId == GT_88E6165)) {
+		    if (switch_irq == -1) {
+			    gprtGetPhyIntPortSummary(qd_dev,&phys_port);
+			    phys_port |= 0x18; /* we cannot get indication for these ports in this method, so check them */
+		    }
+	    }
+	    else {
+		    /* not 6161 or 6165 */
+        	gprtGetPhyIntPortSummary(qd_dev,&phys_port);
+	    }
+
+        for(p=0; p<qd_dev->numOfPorts; p++) {
+            if (MV_BIT_CHECK(phys_port, p)) {
+		        if(gprtGetPhyIntStatus(qd_dev,p,&phy_cause) == GT_OK) {
+		            if(phy_cause & GT_LINK_STATUS_CHANGED) 
+                    {
+			            char *link=NULL, *duplex=NULL, *speed=NULL;
+			            GT_BOOL flag;
+			            GT_PORT_SPEED_MODE speed_mode;
+
+			            if(gprtGetLinkState(qd_dev,p,&flag) != GT_OK) {
+			                printk("gprtGetLinkState failed (port %d)\n",p);
+			                link = "ERR";
+			            }
+                        else 
+                            link = (flag)?"up":"down";
+
+			            if(flag) {
+			                if(gprtGetDuplex(qd_dev,p,&flag) != GT_OK) {
+			                    printk("gprtGetDuplex failed (port %d)\n",p);
+			                    duplex = "ERR";
+			                }
+                            else 
+                                duplex = (flag)?"Full":"Half";
+
+			                if(gprtGetSpeedMode(qd_dev,p,&speed_mode) != GT_OK) {
+			                    printk("gprtGetSpeedMode failed (port %d)\n",p);
+			                    speed = "ERR";
+			                }
+			                else {
+			                    if (speed_mode == PORT_SPEED_1000_MBPS)
+			                        speed = "1000Mbps";
+			                    else if (speed_mode == PORT_SPEED_100_MBPS)
+			                        speed = "100Mbps";
+			                    else
+			                        speed = "10Mbps";
+			                }
+
+			                mv_gtw_update_link_status(p, 1);
+
+                            printk("Port %d: Link-%s, %s-duplex, Speed-%s.\n",
+                                   mv_gtw_port2lport(p),link,duplex,speed);
+                        }
+			            else {
+			                mv_gtw_update_link_status(p, 0);
+
+			                printk("Port %d: Link-down\n",mv_gtw_port2lport(p));
+			            }
+		            }
+		        }
+	        }
+	    }
+    }
+
+    if (switch_irq == -1 ) {
+    	switch_link_timer.expires = jiffies + (HZ); /* 1 second */
+    	add_timer(&switch_link_timer);
+    }
+
+    return IRQ_HANDLED;
+}
+
+static void mv_gtw_link_timer_function(unsigned long data)
+{
+    mv_gtw_link_interrupt_handler(switch_irq, NULL);
+}
+#endif /* CONFIG_MV_GTW_LINK_STATUS */
+
+
+/*********************************************************** 
+ * gtw_init_complete --                                    *
+ *   complete all initializations relevant for Gateway.    *
+ ***********************************************************/
+int  __init mv_gtw_init_complete(mv_eth_priv* priv)
+{
+    int status = 0;
+
+    status = mv_switch_init(priv->port);
+    if (status != 0)
+	return status;
+
+    status = mv_eth_start_internals(priv, gtw_config.mtu);
+    if (status != 0)
+	return status;
+
+    status = mvEthHeaderModeSet(priv->hal_priv, MV_ETH_ENABLE_HEADER_MODE_PRI_2_1);
+    if (status != 0)
+	return status;
+    
+    /* Mask interrupts */
+    mv_eth_mask_interrupts(priv);
+
+#ifdef CONFIG_MV_GTW_IGMP
+    /* Initialize the IGMP snooping handler */
+    if(mv_gtw_igmp_snoop_init()) {
+        printk("failed to init IGMP snooping handler\n");
+    }
+#endif
+
+#ifdef CONFIG_MV_GTW_LINK_STATUS
+    if (switch_irq != -1) {
+        if(request_irq(switch_irq, mv_gtw_link_interrupt_handler, 
+            (IRQF_DISABLED | IRQF_SAMPLE_RANDOM), "link status", NULL))
+	    {
+                printk(KERN_ERR "failed to assign irq%d\n", switch_irq);
+	    }
+    }
+    else {
+        memset( &switch_link_timer, 0, sizeof(struct timer_list) );
+	init_timer(&switch_link_timer);
+        switch_link_timer.function = mv_gtw_link_timer_function;
+        switch_link_timer.data = -1;
+   	switch_link_timer.expires = jiffies + (HZ); /* 1 second */
+    	add_timer(&switch_link_timer);
+    }
+#endif /* CONFIG_MV_GTW_LINK_STATUS */
+
+    return 0;
+}
+
+#define QD_FMT "%10lu %10lu %10lu %10lu %10lu %10lu\n"
+#define QD_CNT(c,f) c[0].f, c[1].f,c[2].f,c[3].f,c[4].f,c[5].f
+#define QD_MAX 6
+void    mv_gtw_switch_stats(int port)
+{
+    GT_STATS_COUNTER_SET3 counters[QD_MAX];
+    int p;
+
+    if(qd_dev == NULL) {
+        printk("Switch is not initialized\n");
+        return;
+    }
+    memset(counters, 0, sizeof(GT_STATS_COUNTER_SET3) * QD_MAX);
+
+    for (p=0; p<QD_MAX; p++)
+        gstatsGetPortAllCounters3(qd_dev, p, &counters[p]);
+
+    printk("PortNum         " QD_FMT,  (GT_U32)0, (GT_U32)1, (GT_U32)2, (GT_U32)3, (GT_U32)4, (GT_U32)5);
+    printk("-------------------------------------------------------------------------------------\n");
+    printk("InGoodOctetsLo  " QD_FMT,  QD_CNT(counters,InGoodOctetsLo));
+    printk("InGoodOctetsHi  " QD_FMT,  QD_CNT(counters,InGoodOctetsHi));
+    printk("InBadOctets     " QD_FMT,  QD_CNT(counters,InBadOctets));
+    printk("OutFCSErr       " QD_FMT,  QD_CNT(counters,OutFCSErr));
+    printk("Deferred        " QD_FMT,  QD_CNT(counters,Deferred));
+    printk("InBroadcasts    " QD_FMT,  QD_CNT(counters,InBroadcasts));
+    printk("InMulticasts    " QD_FMT,  QD_CNT(counters,InMulticasts));
+    printk("Octets64        " QD_FMT,  QD_CNT(counters,Octets64));
+    printk("Octets127       " QD_FMT,  QD_CNT(counters,Octets127));
+    printk("Octets255       " QD_FMT,  QD_CNT(counters,Octets255));
+    printk("Octets511       " QD_FMT,  QD_CNT(counters,Octets511));
+    printk("Octets1023      " QD_FMT,  QD_CNT(counters,Octets1023));
+    printk("OctetsMax       " QD_FMT,  QD_CNT(counters,OctetsMax));
+    printk("OutOctetsLo     " QD_FMT,  QD_CNT(counters,OutOctetsLo));
+    printk("OutOctetsHi     " QD_FMT,  QD_CNT(counters,OutOctetsHi));
+    printk("OutUnicasts     " QD_FMT,  QD_CNT(counters,OutOctetsHi));
+    printk("Excessive       " QD_FMT,  QD_CNT(counters,Excessive));
+    printk("OutMulticasts   " QD_FMT,  QD_CNT(counters,OutMulticasts));
+    printk("OutBroadcasts   " QD_FMT,  QD_CNT(counters,OutBroadcasts));
+    printk("Single          " QD_FMT,  QD_CNT(counters,OutBroadcasts));
+    printk("OutPause        " QD_FMT,  QD_CNT(counters,OutPause));
+    printk("InPause         " QD_FMT,  QD_CNT(counters,InPause));
+    printk("Multiple        " QD_FMT,  QD_CNT(counters,InPause));
+    printk("Undersize       " QD_FMT,  QD_CNT(counters,Undersize));
+    printk("Fragments       " QD_FMT,  QD_CNT(counters,Fragments));
+    printk("Oversize        " QD_FMT,  QD_CNT(counters,Oversize));
+    printk("Jabber          " QD_FMT,  QD_CNT(counters,Jabber));
+    printk("InMACRcvErr     " QD_FMT,  QD_CNT(counters,InMACRcvErr));
+    printk("InFCSErr        " QD_FMT,  QD_CNT(counters,InFCSErr));
+    printk("Collisions      " QD_FMT,  QD_CNT(counters,Collisions));
+    printk("Late            " QD_FMT,  QD_CNT(counters,Late));
+
+    gstatsFlushAll(qd_dev);
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_gtw_igmp.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_gtw_igmp.c
new file mode 100755
index 0000000..5749d79
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_gtw_igmp.c
@@ -0,0 +1,541 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/igmp.h>
+#include <linux/if_ether.h>
+#include <linux/list.h>
+#include <linux/inetdevice.h>
+#include <linux/version.h>
+#include <net/checksum.h>
+
+/* To enable debugging uncomment CONFIG_IGMPS_DEBUG */
+#define CONFIG_IGMPS_DEBUG
+
+#ifdef CONFIG_IGMPS_DEBUG
+#define IGMPSDEBUG(format, args...)  printk(format , ## args)
+#else
+#define IGMPSDEBUG(format, args...)
+#endif
+
+/* APIs exported by the "mv_gwy_main.c" */
+extern int mv_gtw_enable_igmp(void); 
+extern int mv_gtw_set_mac_addr_to_switch(unsigned char *mac_addr, unsigned char db, unsigned int ports_mask, unsigned char op);
+
+/* MAC node data structure (a member of "ipm_llist") */
+typedef struct mac_node 
+{
+    struct list_head ip_list;
+    unsigned char eth_addr[ETH_ALEN];
+    unsigned int port_bitmap;
+    struct list_head list_node;
+}_mac_node;
+
+/* IP node data structure */
+typedef struct ip_node 
+{
+    unsigned int ip_port_bitmap;
+    unsigned int ip_addr;
+    struct list_head ip_list_node;
+}_ip_node;
+
+static int _igmp_add_mac_node( unsigned char temp_addr[ETH_ALEN], unsigned char vlan_dbnum,
+				__u32		igmp_addr,
+				__u32		port_bitmap);
+			
+/* Linked list of the MAC addresses */
+static LIST_HEAD(ipm_llist);
+
+/* Main process routine */
+int mv_gtw_igmp_snoop_process(struct sk_buff* skb, unsigned char port, unsigned char vlan_dbnum)     
+{
+    struct iphdr      *ipheader;
+    struct igmphdr    *igmpheader;
+    __u32             igmp_addr, igmp_addr_host;
+    unsigned char     mac_found, ip_found, ip_port_found;
+    unsigned char     temp_mac_addr[ETH_ALEN];
+    struct list_head  *l, *ip_l;
+    __u32             temp_port_bitmap = 0;
+    _mac_node         *mac_node_entry;
+    _ip_node          *ip_node_entry;
+    __u16 	      old_igmp_csum, new_igmp_csum;
+
+    ipheader = (struct iphdr*)(skb->data);
+
+    /* First of all, let's filter out non-IGMP traffic */
+    if (ipheader->protocol != IPPROTO_IGMP)
+        goto out;
+		
+    /* Get the pointer to the IGMP header and its data */
+    igmpheader = (struct igmphdr*)((__u32)ipheader + (__u32)(ipheader->ihl * 4));
+
+    /* Filter out unsupported IGMP messages */
+    if ((igmpheader->type != IGMP_HOST_MEMBERSHIP_REPORT) &&
+	(igmpheader->type != IGMPV2_HOST_MEMBERSHIP_REPORT) &&
+	(igmpheader->type != IGMP_HOST_LEAVE_MESSAGE))    	
+	goto out;
+    
+    /* Filter out non-multicast messages */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+    if (!MULTICAST(igmpheader->group))
+#else
+    if (!ipv4_is_multicast(igmpheader->group))
+#endif
+    {
+    	printk(KERN_ERR "\nIGMP snoop: Non-multicast group address in IGMP header\n");
+	goto out;
+    }
+    
+    /* According to "draft-ietf-magma-snoop-12.txt" local multicast messages (224.0.0.x) must be flooded to all ports */
+    /* So, don't do anything with such messages */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+    if (LOCAL_MCAST(igmpheader->group))
+#else
+    if (ipv4_is_local_multicast(igmpheader->group))
+#endif
+    {
+    	IGMPSDEBUG(KERN_INFO "\nIGMP snoop: Local IGMP messages (224.0.0.x) must be flooded \n");
+	goto out;
+    }
+    
+    /* According to RFC 2236 IGMP LEAVE messages should be sent to ALL-ROUTERS address (224.0.0.2) */
+    if (igmpheader->type == IGMP_HOST_LEAVE_MESSAGE)
+    {
+    	if (ntohl(ipheader->daddr) != 0xE0000002)
+	{
+		IGMPSDEBUG(KERN_INFO "\nIGMP snoop: Ignore IGMP LEAVE message sent to non-ALL-ROUTERS address (224.0.0.2) \n");
+		goto out;
+	}	
+    }
+    else
+    {
+    	/* According to RFC 2236 Membership Report (JOIN) IGMP messages should be sent to the IGMP group address */
+	if (ipheader->daddr != igmpheader->group)
+    	{
+    		IGMPSDEBUG(KERN_INFO "\nIGMP snoop: Ignore IGMP JOIN message with different destination IP(%u.%u.%u.%u) and IGMP group address(%u.%u.%u.%u) \n",
+			NIPQUAD(ipheader->daddr), NIPQUAD(igmpheader->group));
+		goto out;
+   	 }
+    }
+    
+    /* According to RFC 2236 the IGMP checksum must be checked before processing */
+    /* Before re-calculation of the IGMP checksum one needs to zero the checksum field */
+    old_igmp_csum = igmpheader->csum;
+    igmpheader->csum = 0;
+	 
+    /* Calculate a new checksum */
+    new_igmp_csum = ip_compute_csum((void *)igmpheader, sizeof(struct igmphdr));
+	
+    /* Restore the old checksum */
+    igmpheader->csum = old_igmp_csum;
+	
+    if (old_igmp_csum != new_igmp_csum)
+    {
+	printk(KERN_ERR "\nIGMP snoop: Wrong IGMP message checksum\n");
+	goto out;
+    }	
+        
+    igmp_addr = igmpheader->group;
+    igmp_addr_host = ntohl(igmpheader->group);
+
+    /* Build the multicast MAC address */
+    temp_mac_addr[0] = 0x01;
+    temp_mac_addr[1] = 0x00;
+    temp_mac_addr[2] = 0x5E;
+    temp_mac_addr[3] = (igmp_addr_host>>16) & 0x000000FF;
+    temp_mac_addr[4] = (igmp_addr_host>>8) & 0x000000FF;
+    temp_mac_addr[5] = igmp_addr_host & 0x000000FF;
+
+    /* Set the bit corresponding to the source port */
+    temp_port_bitmap = 1 << port;
+        
+    switch(igmpheader->type)
+    { 
+	case IGMP_HOST_MEMBERSHIP_REPORT:
+	case IGMPV2_HOST_MEMBERSHIP_REPORT:	
+	    IGMPSDEBUG(KERN_INFO "\n\nIGMP snoop: %s JOIN (if=\"%s\", group=%u.%u.%u.%u, port=%d, vlanDB=%d)\n",
+		(igmpheader->type == IGMP_HOST_MEMBERSHIP_REPORT) ? "IGMPv1" : "IGMPv2",
+		 skb->dev->name, NIPQUAD(igmp_addr), port, vlan_dbnum);
+			
+	    /* If the DB (linked list) is empty, create it and add the MAC node  */
+	    if (list_empty(&ipm_llist)) {
+		IGMPSDEBUG(KERN_INFO "IGMP snoop: Empty MAC node list \n");
+		if (_igmp_add_mac_node(temp_mac_addr, vlan_dbnum, igmp_addr, port) != 0) {
+		    printk(KERN_ERR "IGMP snoop: Failed to add MAC node \n");
+		    goto out;
+		}
+	    }
+	    else {
+		/* Non-empty MAC node list */
+		l = ipm_llist.next;
+		mac_found = 0;
+
+		IGMPSDEBUG(KERN_INFO "IGMP snoop: Searching for MAC(01:00:5e:%x:%x:%x) ...\n", 
+		   temp_mac_addr[3], temp_mac_addr[4], temp_mac_addr[5]); 
+
+		/* Check all entries of the MAC node list */
+		do {
+		    mac_node_entry = list_entry(l, struct mac_node, list_node);	
+	
+		    /* Check whether the node's MAC address is equal to the current one */
+		    if (memcmp(temp_mac_addr,mac_node_entry->eth_addr,ETH_ALEN) == 0) {
+
+			IGMPSDEBUG(KERN_INFO "IGMP snoop: MAC address was found in the list\n");
+			mac_found = 1; /* MAC node was found */
+	
+			/* Now look for ip entry */
+			ip_l = mac_node_entry->ip_list.next;
+			ip_found = 0;
+	
+			/* Check all entries of the IP address list */
+			IGMPSDEBUG(KERN_INFO "IGMP snoop: Searching for IP(%u.%u.%u.%u) ...\n", NIPQUAD(igmp_addr));
+
+			do {
+			    ip_node_entry = list_entry(ip_l, struct ip_node, ip_list_node);	
+	
+			    if (ip_node_entry->ip_addr != igmp_addr) {
+				/* Another IP address was found, continue */	
+				ip_l = ip_l->next;
+			    }
+			    else {
+				/* Current IP address is already in the list */
+				IGMPSDEBUG(KERN_INFO "IGMP snoop: IP address was found in the list\n");
+				ip_found = 1;
+	
+				/* Check whether the port bit is already set in the IP node bitmap */
+				if ((ip_node_entry->ip_port_bitmap & temp_port_bitmap) == 0) {
+				    IGMPSDEBUG(KERN_INFO "IGMP snoop: Port %d is not yet set in IP entry port bitmap\n", port);
+
+				    /* Bit is not set, add a new port to ip entry*/
+				    ip_node_entry->ip_port_bitmap |= temp_port_bitmap;
+	
+				    /* Check whether there is a need to update the MAC entry ? */
+				    if ((mac_node_entry->port_bitmap & temp_port_bitmap) == 0) {
+					/* Bit is not set yet and therefore the switch was not instructed */	
+					mac_node_entry->port_bitmap |= temp_port_bitmap;
+	
+					/* Instruct the switch to add the MAC address + port */
+					IGMPSDEBUG(KERN_INFO "IGMP snoop: Add port (%d) and MAC address (01:00:5e:%d:%d:%d) to switch DB (dbnum=%d)\n", 
+					   port, mac_node_entry->eth_addr[3], mac_node_entry->eth_addr[4], mac_node_entry->eth_addr[5],vlan_dbnum);
+
+					if (mv_gtw_set_mac_addr_to_switch(temp_mac_addr, vlan_dbnum, mac_node_entry->port_bitmap, 1) != 0)
+					    printk(KERN_ERR "IGMP snoop: mv_gtw_set_mac_addr_to_switch() failed \n");
+				    }
+				}
+			    }
+			} while((ip_l != &mac_node_entry->ip_list) && (ip_found==0));
+		
+			/* Check whether the IP node was found */
+			if (ip_found == 0) {
+			    /* Add a new ip node */
+			    _ip_node *new_ip_node;
+						
+			    IGMPSDEBUG(KERN_INFO "IGMP snoop: Add a new IP node to the list (ip=%u.%u.%u.%u port=%d)\n",NIPQUAD(igmp_addr),port);
+
+			    new_ip_node = kmalloc(sizeof(_ip_node), GFP_KERNEL);
+			    if (new_ip_node == NULL) {
+			    	printk(KERN_ERR "IGMP snoop: out-of-memory\n");
+				goto out;
+			    }
+	
+			    /* Fill the IP node with data */
+			    INIT_LIST_HEAD(&new_ip_node->ip_list_node);
+			    new_ip_node->ip_addr = igmp_addr;
+			    new_ip_node->ip_port_bitmap = temp_port_bitmap;
+	
+			    list_add_tail(&new_ip_node->ip_list_node, &mac_node_entry->ip_list);
+	
+			    /* if need to update the mac entry ? */
+			    if ((mac_node_entry->port_bitmap & temp_port_bitmap) == 0) {
+				mac_node_entry->port_bitmap |= temp_port_bitmap;
+				/* Instruct the switch to add the MAC address + port */
+				IGMPSDEBUG(KERN_INFO "IGMP snoop: Add port (%d) and MAC address (01:00:5e:%d:%d:%d) to switch DB (dbnum=%d)\n", 
+				   port,mac_node_entry->eth_addr[3], mac_node_entry->eth_addr[4], mac_node_entry->eth_addr[5],vlan_dbnum);
+
+				if (mv_gtw_set_mac_addr_to_switch(temp_mac_addr,vlan_dbnum,mac_node_entry->port_bitmap, 1) != 0)
+					printk(KERN_ERR "IGMP snoop: mv_gtw_set_mac_addr_to_switch() failed \n");
+			    }
+			}    /* if (ip_found == 0)  */
+		    }  /* if (memcmp(temp_mac_addr,mac_node_entry->eth_addr,ETH_ALEN) == 0)  */
+
+		    else {
+			/* Another MAC address is found in the MAC node linked list */
+			l = l->next;
+		    }
+		} while ((l != &ipm_llist) && (mac_found == 0));
+	
+		/* If the MAC entry was not found, than add a mac entry to the DB */
+		if (mac_found == 0) {
+		    if (_igmp_add_mac_node(temp_mac_addr, vlan_dbnum, igmp_addr, port) != 0) {
+			printk(KERN_ERR "Failed to add MAC node \n");
+			goto out;
+		    }
+		}
+	    }
+	    break;
+
+	case IGMP_HOST_LEAVE_MESSAGE:
+	    IGMPSDEBUG(KERN_INFO "\n\nIGMP snoop: IGMPv2 LEAVE (if=\"%s\", group=%u.%u.%u.%u, port=%d, vlanDB=%d)\n",
+	    skb->dev->name, NIPQUAD(igmp_addr), port, vlan_dbnum);
+
+	    /* Nothing to be done if the MAC node list is empty*/
+	    if (list_empty(&ipm_llist))
+		break;
+	
+	    /* Search for the MAC address in the list */
+	    IGMPSDEBUG(KERN_INFO "IGMP snoop: Searching for MAC(01:00:5e:%x:%x:%x) ...\n", 
+	    temp_mac_addr[3], temp_mac_addr[4], temp_mac_addr[5]); 
+	    l = ipm_llist.next;
+	    mac_found = 0;
+
+	    do {
+		mac_node_entry = list_entry(l, struct mac_node, list_node);
+
+		if (memcmp(temp_mac_addr, mac_node_entry->eth_addr, ETH_ALEN) == 0) {
+
+		    /* MAC address match */
+		    IGMPSDEBUG(KERN_INFO "IGMP snoop: MAC address was found in the list\n");
+		    mac_found = 1;
+		
+		    /* Now look for the IP entry */
+		    ip_l = mac_node_entry->ip_list.next;
+		    ip_found = 0;
+		    ip_port_found = 0;
+
+		    /* First of all, check whether the common bitamp has this bit set */
+		    if ((mac_node_entry->port_bitmap & temp_port_bitmap) != 0) {
+
+			IGMPSDEBUG(KERN_INFO "IGMP snoop: Searching for IP(%u.%u.%u.%u) ...\n", NIPQUAD(igmp_addr));
+								
+			do {
+			    ip_node_entry = list_entry(ip_l, struct ip_node, ip_list_node);
+						
+			    if (ip_node_entry->ip_addr != igmp_addr) {
+				/* Another IP multicast address but need to check if the port to be  */
+				/* removed is set. */ 
+				IGMPSDEBUG(KERN_INFO "IGMP snoop: Port %d is used by IP(%u.%u.%u.%u) ...\n", 
+				    port, NIPQUAD(ip_node_entry->ip_addr)); 
+
+				/* check if the port to be removed is present in the IP entry bitmap */	
+				if((ip_node_entry->ip_port_bitmap & temp_port_bitmap) != 0) {
+				    ip_port_found = 1;
+				}
+			    }
+
+			    else {
+				/* The multicast IP address to remove was found */
+				IGMPSDEBUG(KERN_INFO "IGMP snoop: IP address was found in the list\n");
+				ip_found = 1;
+		
+				/* Check whether the port is set in the IP entry bitmap */
+				if ((ip_node_entry->ip_port_bitmap & temp_port_bitmap) != 0) {
+				    /* Remove the port from the IP entry's bitmap */
+				    ip_node_entry->ip_port_bitmap &= ~temp_port_bitmap;
+			
+				    /* If there are no more bits set to 1, delete the IP entry node */
+				    if (ip_node_entry->ip_port_bitmap == 0) {
+					IGMPSDEBUG(KERN_INFO "IGMP snoop: Last port on IP node, delete the IP entry\n");
+					ip_l = ip_l->next;
+			
+					list_del(&ip_node_entry->ip_list_node);
+			
+					/* MUST FREE MEMORY */
+					kfree(ip_node_entry);
+					continue;
+				    }
+				}
+			    }
+		
+			    ip_l = ip_l->next;
+		
+			} while (ip_l != &mac_node_entry->ip_list); /* walkthrough of IP list */
+		
+		    }
+
+		    /* Check whether we need to update the MAC entry */
+		    if ((ip_found == 1) && (ip_port_found == 0)) {
+			/* If the port to remove is not associated with any IP address, */
+			/* instruct the switch component to remove it */
+			if ((mac_node_entry->port_bitmap & temp_port_bitmap) != 0) {
+			    mac_node_entry->port_bitmap ^= temp_port_bitmap;
+		
+			    /* Send the command to the switch */
+			    IGMPSDEBUG(KERN_INFO "IGMP snoop: Send port bitmap (0x%x) and MAC address (01:00:5e:%d:%d:%d) to switch DB (dbnum=%d)\n", 
+			    mac_node_entry->port_bitmap,mac_node_entry->eth_addr[3], mac_node_entry->eth_addr[4], mac_node_entry->eth_addr[5],vlan_dbnum);
+
+			    /* Is it the last port of the MAC entry ? */ 
+			    if (mac_node_entry->port_bitmap == 0) {
+				IGMPSDEBUG(KERN_INFO "IGMP snoop: Last port on MAC node, delete the MAC entry\n");
+
+				if (mv_gtw_set_mac_addr_to_switch(temp_mac_addr, vlan_dbnum, mac_node_entry->port_bitmap, 0) != 0)
+				    printk(KERN_ERR "IGMP snoop: mv_gtw_set_mac_addr_to_switch() failed \n");
+
+				list_del(&mac_node_entry->list_node);
+				/* MUST FREE MEMORY */
+				kfree(mac_node_entry);
+			    }
+			    else {
+				if (mv_gtw_set_mac_addr_to_switch(temp_mac_addr, vlan_dbnum, mac_node_entry->port_bitmap, 1) != 0)
+				    printk(KERN_ERR "IGMP snoop: mv_gtw_set_mac_addr_to_switch() failed \n");
+			    }
+		    	}
+		    }
+		} /* handling of the found MAC address match */
+		
+		else {
+		    l = l->next;
+		}
+	    } while ((l != &ipm_llist) && (mac_found==0));
+	
+	    break;
+	
+	default:
+	    break;	
+    }
+	
+out:
+    return 0; 
+}
+
+
+
+/* Initialization function */
+int __init mv_gtw_igmp_snoop_init(void)
+{
+    /* Enable the HW-based IGMP snooping */
+    mv_gtw_enable_igmp();
+    return 0;
+}
+
+/* Exit function */
+int __exit mv_gtw_igmp_snoop_exit(void)
+{
+    struct list_head *l, *ip_l;
+    _mac_node *node_entry;
+    _ip_node   *ip_node_entry;
+
+    /* should free all kmalloc allocated memory from llists */
+    if (list_empty(&ipm_llist))
+        goto out;
+
+    l = ipm_llist.next;
+    do
+    {
+        node_entry = list_entry(l, struct mac_node, list_node);
+        IGMPSDEBUG(KERN_INFO "IGMP snoop: Free MAC node (mac=01:00:5e:%x:%x:%x)\n", 
+               node_entry->eth_addr[3], node_entry->eth_addr[4], node_entry->eth_addr[5]); 
+
+	/* now look for ip entry */
+        ip_l = node_entry->ip_list.next;
+        
+	do
+        {
+            ip_node_entry = list_entry(ip_l, struct ip_node, ip_list_node);
+            IGMPSDEBUG(KERN_INFO "IGMP snoop: 	Free IP node (ip=%d.%d.%d.%d)\n", 
+					   NIPQUAD(ip_node_entry->ip_addr));
+                         
+            ip_l = ip_l->next;
+            list_del(&ip_node_entry->ip_list_node);
+
+             /* MUST FREE MEMORY */
+            kfree(ip_node_entry);
+	    
+        }while(ip_l != &node_entry->ip_list); /* walkthrough of IP list */
+
+	l = l->next;
+        
+	list_del(&node_entry->list_node);
+        kfree(node_entry);
+
+    }while(l != &ipm_llist);
+
+out:
+    IGMPSDEBUG(KERN_INFO "IGMP snoop: Exit completed\n");
+    
+    return 0;
+}
+
+/* Add a new MAC node to the list of multicast MAC address structures */
+static int _igmp_add_mac_node(	unsigned char	temp_mac_addr[ETH_ALEN],
+				unsigned char	vlan_dbnum,
+				__u32		igmp_addr,
+				__u32		port)
+{
+	/* should use label , or shorten the code in any other way, I know!!! */
+	_mac_node *new_mac_node;	
+	_ip_node  *new_ip_node;
+
+	IGMPSDEBUG(KERN_INFO "IGMP snoop: Add a new MAC node (mac=01:00:5e:%x:%x:%x, ip=%d.%d.%d.%d, port=%d)\n", 
+				temp_mac_addr[3], temp_mac_addr[4], temp_mac_addr[5], NIPQUAD(igmp_addr), port);
+
+	/* Allocate the memory chunk for the MAC node */
+	new_mac_node = kmalloc(sizeof(_mac_node), GFP_KERNEL);
+	if (new_mac_node == NULL) 
+	{
+		printk(KERN_ERR "out-of-memory\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize the list node */
+	INIT_LIST_HEAD(&new_mac_node->list_node);
+
+	/* Copy the MAC address and port bitmap */
+	memcpy(new_mac_node->eth_addr, temp_mac_addr, ETH_ALEN);
+	new_mac_node->port_bitmap = (1 << port);
+
+	/* Init the head of the IP address list */
+	INIT_LIST_HEAD(&new_mac_node->ip_list);
+
+	/* Create the first element of the IP address list */
+	new_ip_node = kmalloc(sizeof(_ip_node), GFP_KERNEL);
+	if (new_ip_node == NULL) 
+	{
+		printk(KERN_ERR "out-of-memory\n");
+		kfree(new_mac_node);
+		return -ENOMEM;
+	}
+
+	/* Fill the IP address element with data */
+	INIT_LIST_HEAD(&new_ip_node->ip_list_node);	
+	new_ip_node->ip_addr = igmp_addr;
+	new_ip_node->ip_port_bitmap = (1 << port);
+
+	/* Add the IP address element to the list */
+	list_add_tail(&new_ip_node->ip_list_node, &new_mac_node->ip_list);
+
+	/* Add the MAC node element to the list */
+	list_add_tail(&new_mac_node->list_node, &ipm_llist);
+
+	/* Instruct the network driver to add the corresponding entry to the switch table */
+	mv_gtw_set_mac_addr_to_switch(temp_mac_addr, vlan_dbnum, new_mac_node->port_bitmap, 1);
+
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_netdev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_netdev.c
new file mode 100755
index 0000000..6223e5b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_netdev.c
@@ -0,0 +1,3639 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"  /* Should be included before mvSysHwConfig */
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+#include "mvOs.h"
+#include "dbg-trace.h"
+#include "mvSysHwConfig.h"
+#include "eth/mvEth.h"
+#include "eth/gbe/mvEthGbe.h"
+#include "eth-phy/mvEthPhy.h"
+#include "mvSysEthApi.h"
+
+#include "boardEnv/mvBoardEnvLib.h"
+
+#ifdef CONFIG_MV_CPU_PERF_CNTRS__ETH
+#include "cpu/mvCpuCntrs.h"
+MV_CPU_CNTRS_EVENT* hal_rx_event = NULL;
+MV_CPU_CNTRS_EVENT* empty_event = NULL;
+MV_CPU_CNTRS_EVENT* routing_event = NULL; 
+#endif /* CONFIG_MV_CPU_PERF_CNTRS__ETH */
+
+#include "mv_netdev.h"
+#ifdef ETH_LRO
+#include <linux/inetdevice.h>
+#endif
+
+static int __init mv_eth_init_module( void );
+static void __exit mv_eth_exit_module( void );
+module_init( mv_eth_init_module );
+module_exit( mv_eth_exit_module);
+MODULE_DESCRIPTION("Marvell Ethernet Driver - www.marvell.com");
+MODULE_AUTHOR("Dmitri Epshtein <dima@marvell.com>");
+MODULE_LICENSE("GPL");
+
+extern u8 mvMacAddr[CONFIG_MV_ETH_PORTS_NUM][6];
+extern u16 mvMtu[CONFIG_MV_ETH_PORTS_NUM];
+
+int     mv_eth_rxq_desc[MV_ETH_RX_Q_NUM];
+int     mv_eth_txq_desc[MV_ETH_TX_Q_NUM];
+
+int     mv_eth_rx_desc_total = 0;
+int     mv_eth_tx_desc_total = 0;
+
+int     mv_eth_tx_done_quota = 16;
+
+mv_eth_priv**       mv_eth_ports;
+int                 mv_eth_ports_num = 0;
+
+struct net_device** mv_net_devs;
+int                 mv_net_devs_num = 0;
+
+int	mv_gtw_dev_offset = 0;
+
+spinlock_t          mii_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t          nfp_lock = SPIN_LOCK_UNLOCKED;
+
+void eth_print_irq_status(mv_eth_priv *priv);
+
+u32 eth_dbg = ETH_DBG_OFF;
+
+static struct platform_device *mv_plat_dev;
+
+static int mv_eth_probe(struct platform_device *pdev)
+{
+	mv_plat_dev = pdev;
+	return 0;
+}
+
+static struct platform_driver mv_eth_driver = {
+	.probe	=	mv_eth_probe,
+	.driver	=	{.name = "mv88fx_eth",},
+};
+
+
+/***********************************************************************************
+ ***  get device by index
+ ***********************************************************************************/
+static struct net_device* eth_net_device_by_idx(unsigned int idx) 
+{
+    if(idx >= mv_net_devs_num)    
+    {
+        printk("No net_device for index %d\n", idx);
+        return NULL;
+    }
+    return mv_net_devs[idx];
+}
+
+/***********************************************************************************
+ ***  get device first ip address
+ ***********************************************************************************/
+#ifdef ETH_LRO
+static INLINE unsigned int mv_eth_dev_ip(struct net_device *dev)
+{
+	struct in_device *ip = dev->ip_ptr;
+	if (ip && ip->ifa_list)
+		return ip->ifa_list->ifa_address;
+
+	return 0;
+
+}
+#endif
+/***********************************************************************************
+ ***  get eth_priv structure by port number
+ ***********************************************************************************/
+static INLINE mv_eth_priv*     eth_priv_by_port(unsigned int port)
+{
+    if(port >= mv_eth_ports_num)    
+    {
+        printk("No eth device for port %d\n", port);
+        return NULL;
+    }
+    return mv_eth_ports[port];
+}
+
+
+static void eth_print_link_status( struct net_device *dev ) 
+{
+    mv_eth_priv *priv = MV_ETH_PRIV(dev);
+    int         port = priv->port;
+    u32         port_status;
+
+    port_status = MV_REG_READ( NETA_GMAC_STATUS_REG( port ) );
+    if(port_status & NETA_GMAC_LINK_UP_MASK)
+    {
+	    printk( KERN_NOTICE "%s: link up", dev->name );
+
+        /* check port status register */
+        printk(", %s",(port_status & NETA_GMAC_FULL_DUPLEX_MASK) ? "full duplex" : "half duplex" );
+
+        if( port_status & NETA_GMAC_SPEED_1000_MASK ) 
+	        printk(", speed 1 Gbps" );
+        else 
+            printk(", %s", (port_status & NETA_GMAC_SPEED_100_MASK) ? "speed 100 Mbps" : "speed 10 Mbps" );
+	    printk("\n" );
+    }
+    else {
+	    printk( KERN_NOTICE "%s: link down\n", dev->name );
+    }
+}
+
+static int eth_get_config(u32 netdev, MV_U8* mac_addr)
+{
+    char*   mac_str = NULL;
+    u8      zero_mac[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    int     mtu;
+
+    switch(netdev)
+    {
+        case 0:
+	    if (mvMtu[0] != 0)
+		mtu = mvMtu[0];
+            else
+		mtu = CONFIG_MV_ETH_0_MTU;
+	    /* use default MAC address from Kconfig only if the MAC address we got is all 0 */
+	    if (memcmp(mvMacAddr[0], zero_mac, ETH_ALEN) == 0)
+            	mac_str = CONFIG_MV_ETH_0_MACADDR; 
+	    else
+		memcpy(mac_addr, mvMacAddr[0], ETH_ALEN);
+            break;
+
+#if (CONFIG_MV_ETH_PORTS_NUM > 1)
+        case 1:
+	    if (mvMtu[1] != 0)
+		mtu = mvMtu[1];
+            else
+		mtu = CONFIG_MV_ETH_1_MTU;
+	    /* use default MAC address from Kconfig only if the MAC address we got is all 0 */
+	    if (memcmp(mvMacAddr[1], zero_mac, ETH_ALEN) == 0)
+            	mac_str = CONFIG_MV_ETH_1_MACADDR;
+	    else
+		memcpy(mac_addr, mvMacAddr[1], ETH_ALEN);
+            break;
+#endif /* CONFIG_MV_ETH_PORTS_NUM > 1 */
+
+#if (CONFIG_MV_ETH_PORTS_NUM > 2)
+        case 2:
+	    if (mvMtu[2] != 0)
+		mtu = mvMtu[2];
+            else
+		mtu = CONFIG_MV_ETH_2_MTU;
+	    /* use default MAC address from Kconfig only if the MAC address we got is all 0 */
+	    if (memcmp(mvMacAddr[2], zero_mac, ETH_ALEN) == 0)
+            	mac_str = CONFIG_MV_ETH_2_MACADDR;
+	    else
+		memcpy(mac_addr, mvMacAddr[2], ETH_ALEN);
+            break;
+#endif /* CONFIG_MV_ETH_PORTS_NUM > 2 */
+
+#if (CONFIG_MV_ETH_PORTS_NUM > 3)
+        case 3:
+	    if (mvMtu[3] != 0)
+		mtu = mvMtu[3];
+            else
+		mtu = CONFIG_MV_ETH_3_MTU;
+	    /* use default MAC address from Kconfig only if the MAC address we got is all 0 */
+	    if (memcmp(mvMacAddr[3], zero_mac, ETH_ALEN) == 0)
+            	mac_str = CONFIG_MV_ETH_3_MACADDR;
+	    else
+		memcpy(mac_addr, mvMacAddr[3], ETH_ALEN);
+            break;
+#endif /* CONFIG_MV_ETH_PORTS_NUM > 3 */
+
+        default:
+            printk("eth_get_config: Unexpected port number %d\n", netdev);
+            return -1;
+    }
+    if ((mac_str != NULL) && (mac_addr != NULL))
+            mvMacStrToHex(mac_str, mac_addr);
+
+    return mtu;
+}
+
+static void eth_print_rx_errors(MV_U32 pkt_status)
+{
+    switch(pkt_status & ETH_RX_ERROR_CODE_MASK)
+    {
+        case ETH_RX_CRC_ERROR:
+            printk("bad rx status %08x, (crc error)", (unsigned int)pkt_status);
+            break;
+
+        case ETH_RX_OVERRUN_ERROR:
+            printk("bad rx status %08x, (overrun error)", (unsigned int)pkt_status);
+            break;
+
+        case ETH_RX_MAX_FRAME_LEN_ERROR:
+            printk("bad rx status %08x, (max frame length error)", (unsigned int)pkt_status);
+            break;
+
+        case ETH_RX_RESOURCE_ERROR:
+            printk("bad rx status %08x, (resource error)", (unsigned int)pkt_status);
+            break;
+    }
+    printk("\n");
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+static inline int mv_eth_skb_check(struct sk_buff *skb, int skb_size)
+{
+    if (atomic_read(&skb->users) != 1)
+		return 0;
+
+	if (skb_cloned(skb))
+		return 0;
+
+	if ((skb_shinfo(skb))->nr_frags)
+		return 0;
+
+	if (skb->data_len) 
+		return 0;
+
+    skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
+    if( (skb->end - skb->head) < skb_size)
+		return 0;
+
+    return 1;
+}
+#endif /* LINUX_VERSION_CODE < 2.6.24 */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+int eth_skb_recycle_enable = CONFIG_NET_SKB_RECYCLE_DEF;
+static void eth_skb_recycle_clear(mv_eth_priv* priv)
+{
+	struct sk_buff *skb;
+
+	priv->skbRecycleMTU = 0;
+
+    while (!mvStackIsEmpty(priv->skbRecyclePool)) {
+		skb = (struct sk_buff*)mvStackPop(priv->skbRecyclePool);
+		skb->skb_recycle = NULL;
+        dev_kfree_skb_any(skb);
+		ETH_STAT_DBG(priv->eth_stat.skb_recycle_del++);
+    }
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+static inline void mv_eth_skb_recycle_reset(struct sk_buff *skb)
+{
+    /* Reset skb before reuse */
+    skb_shinfo(skb)->gso_size = 0;
+ 
+    skb->dst = NULL;
+    skb->destructor = NULL;
+
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+    skb->nfct = 0;
+    skb->nfct_reasm = 0;
+#endif /* CONFIG_NF_CONNTRACK || CONFIG_NF_CONNTRACK_MODULE */
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+    skb->nf_bridge = 0;
+#endif /* CONFIG_BRIDGE_NETFILTER */
+
+    skb->truesize = (skb->end - skb->head) + sizeof(struct sk_buff);
+    skb->next = NULL;
+    skb->pkt_type = 0; 
+    skb->iif = 0;
+    skb->sk = 0; 
+    skb->len = 0;
+    skb->data = skb->tail = skb->head + NET_SKB_PAD; 
+
+    return;
+}
+#endif /* LINUX_VERSION_CODE < 2.6.24 */
+
+static int eth_skb_recycle(struct sk_buff *skb)
+{
+    mv_eth_priv *priv = (mv_eth_priv*)skb->hw_cookie;
+    unsigned long flags = 0;
+
+    if (!eth_skb_recycle_enable)
+        goto out;
+
+	if (!priv->skbRecycleMTU)
+		priv->skbRecycleMTU = MV_RX_BUF_SIZE(priv->net_dev->mtu) + CPU_D_CACHE_LINE_SIZE + 8;
+
+	if (unlikely(mvStackIsFull(priv->skbRecyclePool))) {
+		ETH_STAT_DBG(priv->eth_stat.skb_recycle_full++);
+		goto out;
+	}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    if (mv_eth_skb_check(skb, priv->skbRecycleMTU)) {
+        mv_eth_skb_recycle_reset(skb);
+#else
+    if (skb_recycle_check(skb, priv->skbRecycleMTU)) {
+#endif /* LINUX_VERSION_CODE < 2.6.24 */
+
+	spin_lock_irqsave(priv->lock, flags);
+
+      	ETH_STAT_DBG(priv->eth_stat.skb_recycle_put++);
+        skb->skb_recycle = eth_skb_recycle;
+        skb->hw_cookie = priv;
+
+	mvStackPush(priv->skbRecyclePool, (MV_U32)skb);
+        spin_unlock_irqrestore(priv->lock, flags);    
+        return 0;
+    }
+
+out:
+	ETH_STAT_DBG(priv->eth_stat.skb_recycle_rej++);
+	return 1;
+}
+#endif
+
+static INLINE struct sk_buff* eth_skb_alloc(mv_eth_priv *priv, MV_PKT_INFO* pPktInfo,
+                                            int mtu)
+{
+    int             buf_size;
+    struct sk_buff  *skb;
+
+    /* allocate new skb */
+    /* 32(extra for cache prefetch) + 8 to align on 8B */
+    buf_size = MV_RX_BUF_SIZE(mtu) + CPU_D_CACHE_LINE_SIZE  + 8;
+#ifdef CONFIG_NET_SKB_RECYCLE
+	if (!mvStackIsEmpty(priv->skbRecyclePool)) {
+		skb = (struct sk_buff*)mvStackPop(priv->skbRecyclePool);
+		ETH_STAT_DBG(priv->eth_stat.skb_recycle_get++);
+		/* FIXME: check size */
+	}
+	else
+#endif /* CONFIG_NET_SKB_RECYCLE */
+		skb = dev_alloc_skb( buf_size ); 
+
+    if (!skb) {
+        ETH_DBG( ETH_DBG_RX_FILL, ("%s: rx_fill cannot allocate skb\n", dev->name) );
+        ETH_STAT_ERR(priv->eth_stat.skb_alloc_fail++);
+        return NULL;
+    }
+#ifdef CONFIG_NET_SKB_RECYCLE
+    skb->skb_recycle = eth_skb_recycle;
+    skb->hw_cookie = priv;
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+    ETH_STAT_DBG(priv->eth_stat.skb_alloc_ok++);
+
+    /* align the buffer on 8B */
+    if( (unsigned long)(skb->data) & 0x7 ) {
+        skb_reserve( skb, 8 - ((unsigned long)(skb->data) & 0x7) );
+    }
+        
+    /* Most of PktInfo and BufInfo parameters left unchanged */
+    pPktInfo->osInfo = (MV_ULONG)skb;
+    pPktInfo->pFrags->bufSize = MV_RX_BUF_SIZE( mtu);
+    pPktInfo->pktSize = pPktInfo->pFrags->bufSize;
+    pPktInfo->pFrags->bufPhysAddr = mvOsIoVirtToPhy(NULL, skb->data);
+    pPktInfo->pFrags->bufVirtPtr = skb->data;
+	
+	return skb;
+} 
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+int eth_skb_reuse_enable = CONFIG_MV_ETH_SKB_REUSE_DEF;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+static INLINE void  eth_skb_reuse_reset(struct sk_buff *skb)
+{
+    /* Taken from __kfree_skb() */
+    dst_release(skb->dst);
+    skb->dst = NULL;
+
+#ifdef CONFIG_XFRM
+    secpath_put(skb->sp);
+#endif /* CONFIG_XFRM */ 
+
+    if (skb->destructor) {
+            WARN_ON(in_irq());
+            skb->destructor(skb);
+            skb->destructor = NULL;
+    }
+
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+    if(skb->nfct)
+    {
+        nf_conntrack_put(skb->nfct);
+        skb->nfct = 0;
+    }
+    if(skb->nfct_reasm)
+    {
+        nf_conntrack_put_reasm(skb->nfct_reasm);
+        skb->nfct_reasm = 0;
+    }
+#endif /* CONFIG_NF_CONNTRACK || CONFIG_NF_CONNTRACK_MODULE */
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+        nf_bridge_put(skb->nf_bridge);
+        skb->nf_bridge = 0;
+#endif /* CONFIG_BRIDGE_NETFILTER */
+/* XXX: IS this still necessary? - JHS */
+#ifdef CONFIG_NET_SCHED
+        skb->tc_index = 0;
+#ifdef CONFIG_NET_CLS_ACT
+        skb->tc_verd = 0;
+#endif /* CONFIG_NET_CLS_ACT */
+#endif /* CONFIG_NET_SCHED */
+
+  	skb->truesize = (skb->end - skb->head) + sizeof(struct sk_buff);
+
+	skb->next = NULL;
+    skb->pkt_type = 0; 
+    skb->iif = 0;
+    skb->sk = 0; 
+    skb->len = 0;
+
+    skb->data = skb->tail = skb->head + NET_SKB_PAD;
+
+    /* align the buffer on 8B */
+    if( (unsigned long)(skb->data) & 0x7 ) {
+        skb_reserve( skb, 8 - ((unsigned long)(skb->data) & 0x7) );
+    }
+}
+#endif /* LINUX_VERSION_CODE < 2.6.24 */
+
+
+
+static INLINE mv_eth_priv* eth_skb_reusable(struct sk_buff *skb)
+{
+    int         i, skb_size;
+    mv_eth_priv *priv = NULL;
+
+    if( (!eth_skb_reuse_enable) )
+        return NULL;
+
+    for(i=0; i<mv_eth_ports_num; i++)
+    {
+        priv = mv_eth_ports[i];
+
+	    if (priv == NULL) 
+            continue;
+
+        if(mvStackIndex(priv->skbReusePool) == 0)
+            continue;
+
+    skb_size = MV_RX_BUF_SIZE( priv->net_dev->mtu) + CPU_D_CACHE_LINE_SIZE + 8;
+    
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+        if( mv_eth_skb_check(skb, skb_size) ) {
+            eth_skb_reuse_reset(skb);
+#else
+        if(skb_recycle_check(skb, skb_size) ) {
+#endif /* LINUX_VERSION_CODE <  2.6.24 */
+            return priv;
+        }
+    }
+    return NULL;
+}
+
+
+static INLINE void eth_skb_alloc_for_reuse(mv_eth_priv *priv, int mtu)
+{
+    int             idx;
+    MV_PKT_INFO     *pPktInfo = NULL;
+    struct sk_buff  *skb;
+
+    idx = mvStackIndex(priv->skbReusePool);
+    while(idx > 0)
+    {
+        ETH_STAT_DBG(priv->eth_stat.skb_reuse_alloc++);
+        pPktInfo = (MV_PKT_INFO*)mvStackPop(priv->skbReusePool);
+        idx--;
+
+        skb = eth_skb_alloc(priv, pPktInfo, mtu);
+        if(skb == NULL)
+        {
+            /* return PktInfo to Pool */
+            mvStackPush(priv->skbReusePool, (MV_U32)pPktInfo);
+            break;
+        }
+        mvStackPush(priv->fpRxPool, (MV_U32)pPktInfo);
+    }
+}
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+static INLINE MV_PKT_INFO* eth_pkt_info_get(mv_eth_priv  *priv)
+{
+    if(mvStackIndex(priv->fpRxPool) > 0)
+        return (MV_PKT_INFO*)mvStackPop(priv->fpRxPool);
+
+    return NULL;
+}
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_SKB_REUSE */
+
+INLINE void  eth_pkt_info_free(mv_eth_priv *priv, MV_PKT_INFO* pPktInfo)
+{
+#if defined(CONFIG_MV_ETH_NFP_PPP) || defined(CONFIG_MV_ETH_NFP_SEC)
+		MV_BUF_INFO *pBuf = pPktInfo->pFrags;
+		if (pBuf->bufAddrShift) {
+			pBuf->bufPhysAddr += pBuf->bufAddrShift;
+			pBuf->bufVirtPtr += pBuf->bufAddrShift;
+			pBuf->bufAddrShift = 0;
+		}
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP
+    if(pPktInfo->ownerId != ~0)
+    {
+        mv_eth_priv  *src_priv = mv_eth_ports[(int)pPktInfo->ownerId];
+
+        /* Return to the NFP pool */
+#ifdef CONFIG_MV_GATEWAY
+        if(!priv->isGtw)
+		    pPktInfo->pFrags->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+#else
+        pPktInfo->pFrags->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+#endif /* CONFIG_MV_GATEWAY */
+/*
+	// for debug:
+	mvEthRxDoneTest(pPktInfo->pFrags, CONFIG_NET_SKB_HEADROOM);
+*/
+        mvStackPush(src_priv->fpRxPool, (MV_U32)pPktInfo);
+	return;
+    }
+#endif /* CONFIG_MV_ETH_NFP */
+
+    if(pPktInfo->osInfo)
+    {
+        struct sk_buff *skb = (struct sk_buff *)pPktInfo->osInfo;
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+        mv_eth_priv  *rx_priv = eth_skb_reusable(skb);
+
+        if( rx_priv != NULL)
+        {
+            MV_PKT_INFO*    pkt_info = NULL;
+
+            ETH_STAT_DBG(rx_priv->eth_stat.skb_reuse_tx++);
+            pkt_info = (MV_PKT_INFO*)mvStackPop(rx_priv->skbReusePool);
+
+            pkt_info->osInfo = (MV_ULONG)skb;
+            pkt_info->pktSize = pkt_info->pFrags->bufSize;
+            pkt_info->pFrags->bufPhysAddr = mvOsIoVirtToPhy(NULL, skb->data);
+            pkt_info->pFrags->bufVirtPtr = skb->data;
+
+            mvStackPush(rx_priv->fpRxPool, (MV_U32)pkt_info);
+            pPktInfo->osInfo = 0;
+            mvStackPush(priv->txPktInfoPool, (MV_U32)pPktInfo);
+            return;
+        }
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+        dev_kfree_skb_any(skb);
+        ETH_STAT_DBG(priv->eth_stat.skb_free_ok++);
+        pPktInfo->osInfo = 0;
+    }
+    mvStackPush(priv->txPktInfoPool, (MV_U32)pPktInfo);
+}
+/**************************************************************************************************************/
+
+
+#ifdef ETH_MV_TX_EN
+void    eth_tx_en_config(int port, int value)
+{
+    MV_U32          port_status = 0;
+    mv_eth_priv     *priv = eth_priv_by_port(port);
+
+    if (priv == NULL)
+    {
+        printk("eth_tx_en_config: wrong port number %d\n", port);
+	    return;
+    }
+
+    if(value == 0)
+    {
+        /* Disable TX_EN support */
+        priv->tx_en_bk = priv->tx_en = MV_FALSE;
+    }
+    else
+    {
+        /* Enable TX_EN support if possible: Link is Down or Duplex != Half or Speed != 10 Mbps */
+        priv->tx_en_deep = value;
+        priv->tx_en_bk = MV_TRUE;
+
+        /* Check ethernet port status */
+        port_status = MV_REG_READ( NETA_GMAC_STATUS_REG( port ) );
+        if( !(port_status & NETA_GMAC_LINK_UP_MASK) || 
+             (port_status & NETA_GMAC_FULL_DUPLEX_MASK) ||
+             (port_status & NETA_GMAC_SPEED_1000_MASK) ||
+             (port_status & NETA_GMAC_SPEED_100_MASK) )
+            priv->tx_en = MV_TRUE;
+    }
+    printk("GbE port %d: TxEnable WA - %s, deep=%d, tx_en_bk=%d\n\n", 
+            priv->port, priv->tx_en ? "Enabled" : "Disabled", 
+            priv->tx_en_deep, priv->tx_en_bk);    
+}
+
+static INLINE void  eth_tx_enable(mv_eth_priv *priv, int queue)
+{
+    int             ret;
+
+    ret = mvEthPortTxEnable(priv->hal_priv, queue, priv->tx_en_deep);
+    if(ret < 0)
+    {
+        ETH_STAT_DBG(priv->eth_stat.tx_en_busy++);
+    }
+    else 
+    {
+        if(ret > 0)
+        {
+            ETH_STAT_DBG(priv->eth_stat.tx_en_wait++);
+            ETH_STAT_DBG(priv->eth_stat.tx_en_wait_count += ret);
+        }        
+        else
+        {
+            ETH_STAT_DBG(priv->eth_stat.tx_en_done++);
+        }
+    }
+}
+#endif /* ETH_MV_TX_EN */
+/**************************************************************************************************************/
+
+
+
+/***********************************************************
+ * mv_eth_down_internals --                                 *
+ *   down port rx/tx activity. free skb's from rx/tx rings.*
+ ***********************************************************/
+int     mv_eth_down_internals( struct net_device *dev )
+{
+    mv_eth_priv     *priv = MV_ETH_PRIV(dev);
+    MV_PKT_INFO     *pPktInfo;
+    unsigned int    queue;
+
+    /* stop the port activity, mask all interrupts */
+    if( mvEthPortDown( priv->hal_priv ) != MV_OK ) {
+        printk( KERN_ERR "%s: ethPortDown failed\n", dev->name );
+        goto error;
+    }
+
+    /* free the skb's in the hal tx ring */
+    for(queue=0; queue<MV_ETH_TX_Q_NUM; queue++) 
+    {
+        while( (pPktInfo = mvEthPortForceTxDone(priv->hal_priv, queue)) ) 
+        {
+            eth_pkt_info_free(priv, pPktInfo);
+        }
+        priv->tx_count[queue] = 0;
+    }
+    
+    return 0;
+
+error:
+    printk( KERN_ERR "%s: stop internals failed\n", dev->name );
+    return -1;
+}
+/**************************************************************************************************************/
+
+static void eth_check_link_status(struct net_device *dev)
+{
+    mv_eth_priv     *priv = MV_ETH_PRIV(dev);
+    MV_U32          port_status = 0;
+
+        ETH_STAT_INFO(priv->eth_stat.link_events++);
+
+    	/* Check Link status on ethernet port */
+        port_status = MV_REG_READ( NETA_GMAC_STATUS_REG( priv->port ) );
+
+        spin_lock(priv->lock);
+
+        if(port_status & NETA_GMAC_LINK_UP_MASK) { 
+
+#ifdef ETH_MV_TX_EN
+        /* Disable TX Enable WA if one of Giga ports is Half Duplex or 10 Mbps */
+        if( ((port_status & NETA_GMAC_FULL_DUPLEX_MASK) ||
+             (port_status & NETA_GMAC_SPEED_1000_MASK) ||
+             (port_status & NETA_GMAC_SPEED_100_MASK)) )
+        {
+            priv->tx_en = priv->tx_en_bk;
+        }
+        else
+        {
+            priv->tx_en_bk = priv->tx_en;
+            priv->tx_en = MV_FALSE;
+        }
+#endif /* ETH_MV_TX_EN */
+
+            mvEthPortUp( priv->hal_priv );
+            netif_carrier_on( dev );
+            netif_wake_queue( dev );            
+        }
+    	else
+        {
+            netif_carrier_off( dev );
+            netif_stop_queue( dev );
+            mv_eth_down_internals( dev );
+        }
+
+        spin_unlock(priv->lock);
+
+   	eth_print_link_status( dev );
+}
+/**************************************************************************************************************/
+
+static INLINE int   eth_rx_policy(mv_eth_priv *priv)
+{
+    u32     rxq_map;
+
+    rxq_map = ( ( (priv->picr & ETH_RXQ_MASK) >> ETH_CAUSE_RX_READY_OFFSET) | 
+		        ( (priv->picr & ETH_RXQ_RES_MASK) >> ETH_CAUSE_RX_ERROR_OFFSET) );
+    
+    return (fls(rxq_map) - 1);
+}
+
+
+static INLINE int   eth_tx_policy(mv_eth_priv *priv, struct sk_buff *skb)
+{
+    int     queue;
+
+#if (MV_ETH_TX_Q_NUM > 1) 
+    if( ip_hdr(skb) )
+    {
+        queue = mv_eth_tos_to_q_map(ip_hdr(skb)->tos, MV_ETH_TX_Q_NUM);
+    }
+    else
+#endif /* (MV_ETH_TX_Q_NUM > 1) */
+    {
+        /* no multiqueue. all packets go to one default queue. */
+        queue = ETH_DEF_TXQ;
+    }
+
+    return queue;
+}
+/**************************************************************************************************************/
+
+
+
+/*********************************************************** 
+ * eth_tx_done --                                             *
+ *   release transmitted packets. interrupt context.       *
+ ***********************************************************/
+u32 eth_tx_done(mv_eth_priv *priv, int queue)
+{
+    MV_PKT_INFO*            pPktInfo;
+    u32                     count = 0;
+
+    ETH_DBG( ETH_DBG_TX_DONE, ("eth%d: tx-done ", priv->port) );
+    ETH_STAT_INFO(priv->eth_stat.tx_done_events++);
+
+    /* release the transmitted packets */
+    while( 1 ) 
+    {
+        /* get a packet */ 
+        pPktInfo = mvEthPortTxDone(priv->hal_priv, queue);
+        if(pPktInfo) 
+        {
+             /* handle tx error */
+            if( pPktInfo->status & (ETH_ERROR_SUMMARY_MASK) ) {
+                ETH_DBG( ETH_DBG_TX_DONE, ("GbE port %d: bad tx-done status\n", priv->port) );
+                priv->net_dev->stats.tx_errors++;
+            }
+
+            count++;
+            ETH_STAT_DBG( priv->eth_stat.tx_done_hal_ok[queue]++);
+
+            eth_pkt_info_free(priv, pPktInfo);
+            continue;
+        }
+        else 
+        {
+            /* no more work */
+            break;
+        }
+    }
+#if (MV_ETH_TX_Q_NUM == 1)
+    /* if transmission was previously stopped, now it can be restarted. */
+    if( netif_queue_stopped( priv->net_dev ) && (priv->net_dev->flags & IFF_UP) && (count > 0) ) {
+        ETH_DBG( ETH_DBG_TX_DONE, ("%s: restart transmit\n", priv->net_dev->name) );
+        ETH_STAT_ERR( priv->eth_stat.tx_done_netif_wake++);
+        netif_wake_queue( priv->net_dev );    
+    }
+#endif /* MV_ETH_TX_Q_NUM == 1 */
+
+    ETH_STAT_DBG( priv->eth_stat.tx_done_dist[count]++);
+    ETH_DBG( ETH_DBG_TX_DONE, ("GbE port %d: tx-done %d\n", priv->port, count) );
+    return count;
+}
+/**************************************************************************************************************/
+
+static INLINE int eth_rx(struct net_device *dev, unsigned int work_to_do, int queue)
+{
+    mv_eth_priv             *priv = MV_ETH_PRIV(dev);
+    struct net_device_stats	*stats = MV_NETDEV_STATS(dev);
+    struct sk_buff          *skb;
+    MV_U8                   *data;
+    MV_PKT_INFO             *pPktInfo;
+    int                     work_done = 0;
+    MV_STATUS               status;
+    struct net_device       *out_dev = NULL;
+    MV_U32		            rx_status; 
+#ifdef CONFIG_MV_ETH_NFP
+    int			            out_if_index;
+    MV_IP_HEADER            *pIpHdr;
+    int                     nfp = fp_is_enabled(); 
+#endif /* CONFIG_MV_ETH_NFP */
+
+    ETH_DBG( ETH_DBG_RX, ("%s: rx_poll work_to_do %d\n", dev->name, work_to_do) );
+
+    /* fairness NAPI loop */
+    while( work_done < work_to_do ) {
+
+        /* get rx packet */ 
+        /* MV_CPU_CNTRS_START(hal_rx_event); */
+        pPktInfo = mvEthPortRx( priv->hal_priv, queue);
+        /* check status */
+        if( pPktInfo == NULL) 
+        {
+            /* no more rx packets ready */
+            break;
+        }
+        /* MV_CPU_CNTRS_STOP(hal_rx_event); */
+        /* MV_CPU_CNTRS_SHOW(hal_rx_event); */
+
+	rx_status = pPktInfo->status;
+	if (rx_status  & (ETH_ERROR_SUMMARY_MASK)) 
+	{
+        	eth_print_rx_errors(rx_status);
+	        mvEthPortRxDone(priv->hal_priv, queue, pPktInfo);
+            	stats->rx_errors++;
+            	continue;
+	}
+	dma_unmap_single(NULL, pPktInfo->pFrags->bufPhysAddr, pPktInfo->pFrags->dataSize, 
+									DMA_FROM_DEVICE);
+	prefetch(pPktInfo->pFrags->bufVirtPtr);
+
+        work_done++;
+        ETH_STAT_DBG( priv->eth_stat.rx_hal_ok[queue]++);
+
+        /* good rx */
+        skb = (struct sk_buff *)( pPktInfo->osInfo );
+        data = (MV_U8*)skb->data;
+        ETH_DBG( ETH_DBG_RX, ("good rx: skb=%p, skb->data=%p\n", skb, skb->data) );
+
+#ifdef CONFIG_MV_GATEWAY
+        if(priv->isGtw)
+        {
+	        dev = mv_gtw_ingress_dev(data);
+	        stats = MV_NETDEV_STATS(dev);
+        }
+#endif /* CONFIG_MV_GATEWAY */
+	
+        stats->rx_packets++;
+        stats->rx_bytes += pPktInfo->pFrags->dataSize - ETH_MV_HEADER_SIZE;
+
+#ifdef CONFIG_MV_ETH_NFP
+	    if (nfp)
+	    {
+            int txq = ETH_DEF_TXQ;
+
+            out_dev = NULL;
+            pIpHdr = mvFpParsing(pPktInfo, &priv->fpStats);
+#ifndef CONFIG_MV_ETH_NFP_PPP
+            if(pIpHdr != NULL)
+#endif
+            {
+                out_if_index = mvFpProcess(dev->ifindex, pPktInfo, pIpHdr, &priv->fpStats);
+                if(out_if_index >= 0)
+                {
+                    out_dev = fp_mgr_get_net_dev(out_if_index);
+                    if(fp_mgr_get_if_type(out_if_index) == MV_FP_IF_INT)
+                    {
+                	    mv_eth_priv    *out_priv = MV_ETH_PRIV(out_dev);
+#if defined(CONFIG_MV_GATEWAY)
+                        if(out_priv->isGtw)
+                        {
+				            struct mv_vlan_cfg* vlan_cfg = MV_NETDEV_VLAN(out_dev);
+				            *(unsigned short *)(pPktInfo->pFrags->bufVirtPtr) = vlan_cfg->header;
+                        }
+                        else
+#endif /* CONFIG_MV_GATEWAY */
+                        {
+				            pPktInfo->pFrags->bufPhysAddr += ETH_MV_HEADER_SIZE;
+				            pPktInfo->pFrags->dataSize -= ETH_MV_HEADER_SIZE;
+                        }
+                        mvOsCacheLineFlushInv(NULL, pPktInfo->pFrags->bufVirtPtr);	
+                        mvOsCacheLineFlushInv(NULL, pPktInfo->pFrags->bufVirtPtr 
+                                                        + CPU_D_CACHE_LINE_SIZE);
+
+            	        spin_lock(out_priv->lock);
+#ifdef CONFIG_MV_ETH_NFP_TOS
+                        txq = pPktInfo->txq;
+#endif
+            	        status = mvEthPortTx(out_priv->hal_priv, txq, pPktInfo);
+            	        if( status != MV_OK ) 
+            	        {
+#ifdef CONFIG_MV_ETH_NFP_PPP
+							//printk("Tx drop: %x %d\n", status);
+							if (pPktInfo->pFrags->bufAddrShift) {
+								pPktInfo->pFrags->bufPhysAddr += pPktInfo->pFrags->bufAddrShift;
+								pPktInfo->pFrags->bufVirtPtr += pPktInfo->pFrags->bufAddrShift;
+								pPktInfo->pFrags->bufAddrShift = 0;
+							}
+#endif
+				            out_dev->stats.tx_dropped++;
+				            spin_unlock(out_priv->lock);
+#if defined(CONFIG_MV_GATEWAY)
+				            if(!out_priv->isGtw)
+#endif /* CONFIG_MV_GATEWAY */
+					            pPktInfo->pFrags->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+
+				            mvEthPortRxDone( priv->hal_priv, queue, pPktInfo );
+				            continue;
+			            }
+                	    out_priv->tx_count[txq]++;
+                	    out_dev->stats.tx_packets++;
+                	    out_dev->stats.tx_bytes += pPktInfo->pFrags->dataSize;
+                	    ETH_STAT_DBG( out_priv->eth_stat.tx_hal_ok[txq]++);
+
+                	    spin_unlock(out_priv->lock);
+
+                	    /* refill RX queue */
+                	    pPktInfo = eth_pkt_info_get(priv);
+			            if (pPktInfo != NULL)
+                	        mvEthPortRxDone( priv->hal_priv, queue, pPktInfo );
+			            else
+			            {
+                            ETH_STAT_ERR(priv->eth_stat.rx_pool_empty++);
+			                priv->refill_needed_flag = 1;
+			            }
+                	    continue;
+                    }
+                }
+#ifdef CONFIG_MV_ETH_NFP_SEC
+		/* NFP will make sure to complete the packet processing */
+		if( out_if_index == MV_NFP_STOLEN)
+		{
+                	    /* refill RX queue */
+                	    pPktInfo = eth_pkt_info_get(priv);
+			            if (pPktInfo != NULL)
+                	        mvEthPortRxDone( priv->hal_priv, queue, pPktInfo );
+			            else
+			            {
+                            ETH_STAT_ERR(priv->eth_stat.rx_pool_empty++);
+			                priv->refill_needed_flag = 1;
+			            }
+                	    continue;		
+		}
+		if( out_if_index == MV_NFP_DROP)
+		{
+			if (pPktInfo->pFrags->bufAddrShift) {
+					pPktInfo->pFrags->bufPhysAddr += pPktInfo->pFrags->bufAddrShift;
+					pPktInfo->pFrags->bufVirtPtr += pPktInfo->pFrags->bufAddrShift;
+					pPktInfo->pFrags->bufAddrShift = 0;
+			}
+			mvOsCacheLineInv(NULL, pPktInfo->pFrags->bufVirtPtr);	
+                        mvOsCacheLineInv(NULL, pPktInfo->pFrags->bufVirtPtr 
+                                                        + CPU_D_CACHE_LINE_SIZE);
+			/* TBD - rx drop counters */
+			mvEthPortRxDone( priv->hal_priv, queue, pPktInfo );
+			continue;
+		}
+#endif /* CONFIG_MV_ETH_NFP_SEC */
+            }
+	    }
+#endif /* CONFIG_MV_ETH_NFP */
+
+	    /* skip on 2B Marvell-header */
+	    skb_reserve(skb, ETH_MV_HEADER_SIZE);
+	    skb_put(skb, pPktInfo->pFrags->dataSize - ETH_MV_HEADER_SIZE);
+
+        if(out_dev != NULL)
+        {
+            /* Send to external net_device */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+            out_dev->hard_start_xmit(skb, out_dev);
+#else
+            out_dev->netdev_ops->ndo_start_xmit(skb, out_dev);
+#endif
+        }
+        else
+        {
+            skb->dev = dev;
+
+            skb->ip_summed = CHECKSUM_NONE;
+            skb->protocol = eth_type_trans(skb, dev);
+
+#ifdef RX_CSUM_OFFLOAD
+	    if ((pPktInfo->pFrags->dataSize > (ETH_CSUM_MIN_BYTE_COUNT-4))  && 
+	        (rx_status & ETH_RX_IP_FRAME_TYPE_MASK) && 
+	        (rx_status & ETH_RX_IP_HEADER_OK_MASK)
+#ifdef CONFIG_MV_ETH_TOOL
+		&& (priv->rx_csum_offload != 0)
+#endif
+		) 
+            {  
+		if (!(pPktInfo->fragIP)		&&
+		   (!(rx_status & ETH_RX_L4_OTHER_TYPE)) &&
+		   (rx_status & ETH_RX_L4_CHECKSUM_OK_MASK)) 
+                { 
+		    skb->csum = 0;
+		    skb->ip_summed = CHECKSUM_UNNECESSARY;	
+		    ETH_STAT_DBG(priv->eth_stat.rx_csum_hw++);
+		}
+           	else if (pPktInfo->fragIP &&
+           	    (rx_status & ETH_RX_L4_UDP_TYPE) &&
+                    !(rx_status & ETH_RX_VLAN_TAGGED_FRAME_MASK)) 
+		{
+		    skb->csum = ntohl(0xFFFF ^ ((rx_status & ETH_RX_L4_CHECKSUM_MASK) >> ETH_RX_L4_CHECKSUM_OFFSET));
+		    skb->ip_summed = CHECKSUM_COMPLETE;
+		    ETH_STAT_DBG( priv->eth_stat.rx_csum_hw_frags++);
+		}
+                else
+                {
+                    ETH_STAT_DBG(priv->eth_stat.rx_csum_sw++);
+                }
+	    }
+            else 
+	    {
+                    ETH_DBG( ETH_DBG_RX, ("%s: no RX csum offload\n", dev->name) );
+		    ETH_STAT_DBG(priv->eth_stat.rx_csum_sw++);
+            }
+#endif /* RX_CSUM_OFFLOAD*/
+
+#ifdef CONFIG_MV_GTW_IGMP
+            if (priv->isGtw && (rx_status & ETH_RX_L4_OTHER_TYPE)) {
+		struct iphdr* iph = (struct iphdr*)skb->data;
+		if ((skb->protocol == htons(ETH_P_IP)) && 
+		    (iph->protocol == IPPROTO_IGMP)) {
+			mv_gtw_igmp_snoop_process(skb, mv_gtw_ingress_port(data),
+					       mv_gtw_ingress_vlan(data) );
+		}
+	    }
+#endif /* CONFIG_MV_GTW_IGMP */
+
+#ifdef ETH_LRO
+	        if (priv->lro_en && !pPktInfo->fragIP && 
+				((rx_status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_TCP_TYPE))
+			{
+				struct iphdr* iph = (struct iphdr*)skb->data;
+
+				if (iph->daddr == mv_eth_dev_ip(dev)) {
+					status = 0;				
+					lro_receive_skb(&priv->lro_mgr, skb, priv);
+				}
+				else
+					status = netif_receive_skb(skb);				
+            }
+	        else
+#endif /* ETH_LRO */
+            {
+                /* MV_CPU_CNTRS_START(routing_event); */
+                status = netif_receive_skb(skb);
+                /* MV_CPU_CNTRS_STOP(routing_event); */
+                /* MV_CPU_CNTRS_SHOW(routing_event); */
+            }
+            ETH_STAT_DBG( if(status) (priv->eth_stat.rx_netif_drop++) );
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+            if( eth_skb_reuse_enable && 
+        	    ( !mvStackIsFull(priv->skbReusePool)) )
+            {
+        	    ETH_STAT_DBG(priv->eth_stat.skb_reuse_rx++);
+        	    mvStackPush(priv->skbReusePool, (MV_U32)pPktInfo);
+        	    /* refill RX queue */
+        	    pPktInfo = eth_pkt_info_get(priv);
+        	    if(pPktInfo != NULL)
+                    mvEthPortRxDone( priv->hal_priv, queue, pPktInfo );
+                else
+                {
+                    ETH_STAT_ERR(priv->eth_stat.rx_pool_empty++);
+		            priv->refill_needed_flag = 1;
+                }
+        	    continue;
+            }
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+	    }
+
+        /* Refill this buffer */
+        skb = eth_skb_alloc(priv, pPktInfo, dev->mtu);
+        if(skb == NULL)
+        {
+            mvOsFree(pPktInfo);
+            priv->skb_alloc_fail_cnt++;
+            continue;
+        }
+
+        /* give the buffer to hal */
+        status = mvEthPortRxDone(priv->hal_priv, queue, pPktInfo);
+        if( (status != MV_OK) && (status != MV_FULL) )
+        {
+            printk( KERN_ERR "%s: error in rx-fill, status=%d\n", dev->name, status );
+        }
+        ETH_STAT_DBG( priv->eth_stat.rx_fill_ok[queue]++);
+    }
+
+    ETH_STAT_DBG( priv->eth_stat.rx_dist[work_done]++); 
+    ETH_DBG( ETH_DBG_RX, ("\nwork_done %d", work_done));
+
+    /* notify upper layer about more work to do */
+    return work_done;
+}
+/**************************************************************************************************************/
+
+
+/*********************************************************** 
+ * eth_rx_fill --                                        *
+ *   fill new rx buffers to ring.                          *
+ ***********************************************************/
+int     eth_rx_fill(mv_eth_priv *priv, int pool_size, int mtu)
+{
+    MV_PKT_INFO     *pPktInfo;
+    MV_BUF_INFO     *pBufInfo;
+    struct sk_buff  *skb;
+    u32             count;
+    MV_STATUS       status;
+    int             rxq = 0;
+
+	count = 0;
+    while(pool_size > count) {
+
+        pPktInfo = mvOsMalloc(sizeof(MV_PKT_INFO));
+        if(pPktInfo == NULL)
+        {
+            printk("GbE port %d: Can't allocate %d bytes for MV_PKT_INFO\n",
+                        priv->port, sizeof(MV_PKT_INFO));
+            return count;
+        }
+
+        pBufInfo = mvOsMalloc(sizeof(MV_BUF_INFO));
+        if(pBufInfo == NULL)
+        {
+            printk("GbE port %d: Can't allocate %d bytes for MV_BUF_INFO\n",
+                        priv->port, sizeof(MV_BUF_INFO));
+            mvOsFree(pPktInfo);
+            return count;
+        }
+
+        pBufInfo->bufAddrShift = 0;
+		pBufInfo->dataSize = 0;
+        pPktInfo->pFrags = pBufInfo;
+        pPktInfo->numFrags = 1;
+        pPktInfo->status = 0;
+        pPktInfo->ownerId = priv->port;
+        pPktInfo->txq = 0;
+
+        skb = eth_skb_alloc(priv, pPktInfo, mtu);
+        if(skb == NULL)
+        {
+            mvOsFree(pPktInfo);
+            mvOsFree(pBufInfo);
+            return count;
+        }
+
+        /* First of all refill RXQs */
+        for(rxq=0; rxq<MV_ETH_RX_Q_NUM; rxq++)
+        {
+            if( !mvEthRxQueueIsFull(priv->hal_priv, rxq) )
+            {
+                status = mvEthPortRxDone(priv->hal_priv, rxq, pPktInfo);
+                if( (status != MV_OK) && (status != MV_FULL) )
+                {
+                    printk("rx_fill: q=%d, resource=%d, status=%d\n", 
+                               rxq, mvEthRxResourceGet(priv->hal_priv, rxq), status);
+                }
+		        ETH_STAT_DBG( priv->eth_stat.rx_fill_ok[rxq]++);
+                pPktInfo = NULL;
+                count++;
+                break;
+            }
+        }
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+        /* Push extra RX buffers to fpRxPool */
+        if( (pPktInfo != NULL) && !mvStackIsFull(priv->fpRxPool) )
+        {
+            mvStackPush(priv->fpRxPool, (MV_U32)pPktInfo);
+            pPktInfo = NULL;
+            count++;
+        }
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_SKB_REUSE*/
+        if(pPktInfo != NULL)
+        {
+            printk("rx_fill: No more place to store pkt_info+skb pairs - pool_size=%d, count=%d\n", 
+                               pool_size, count);
+            mvOsFree(pPktInfo);
+            mvOsFree(pBufInfo);
+            dev_kfree_skb_any(skb);           
+            break;
+        }
+    }
+    return count;
+}
+
+
+/*********************************************************** 
+ * mv_eth_interrupt_handler --                              *
+ *   serve rx-q0, tx-done-q0, phy/link state change.       *
+ *   phy is served in interrupt context.           *
+ *   tx and rx are scheduled out of interrupt context (NAPI poll)  *
+ ***********************************************************/
+irqreturn_t     mv_eth_interrupt_handler(int irq , void *dev_id)
+{
+    mv_eth_priv         *priv = (mv_eth_priv*)dev_id;
+    struct net_device   *dev  = priv->net_dev;
+
+    ETH_DBG( ETH_DBG_INT, ("\n%s: isr ", dev->name) );
+    ETH_STAT_INFO(priv->eth_stat.irq_total++);
+
+    /* read port interrupt cause register */
+    mv_eth_save_interrupts(priv);
+
+    ETH_DBG(ETH_DBG_INT, ("%s: mv_eth_interrupt_handler: picr=%x, picer=%x\n", 
+                            dev->name, priv->picr, priv->picer));
+
+#ifdef ETH_DEBUG
+    if( !priv->picr && !priv->picer) {
+        ETH_STAT_INFO(priv->eth_stat.irq_none++);
+        return IRQ_HANDLED;
+    }
+#endif /* ETH_DEBUG */
+
+    /* Verify that the device not already on the polling list */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    if (netif_rx_schedule_prep(dev)) {
+	/* schedule the work (rx+txdone+link) out of interrupt contxet */
+	mv_eth_mask_interrupts(priv);
+	__netif_rx_schedule(dev);
+#else
+	 if (napi_schedule_prep(&priv->napi)) {
+	    /* schedule the work (rx+txdone+link) out of interrupt contxet */
+        mv_eth_mask_interrupts(priv);
+	__napi_schedule(&priv->napi);
+#endif
+    }
+    else {
+	    if(netif_running(dev)) {
+            ETH_STAT_INFO(priv->eth_stat.irq_while_polling++);
+#ifdef ETH_DEBUG
+            printk("%s: Interrupt while in polling list\n", dev->name);
+	        eth_print_irq_status(priv);
+#endif /* ETH_DEBUG */
+	    }
+    }
+    mv_eth_clear_saved_interrupts(priv);
+
+    return IRQ_HANDLED;
+}
+
+void
+eth_check_for_tx_done(void)
+{
+    int i;
+	int queue;
+
+    for(i=0; i<mv_eth_ports_num; i++)
+    {
+        mv_eth_priv  *tx_priv = mv_eth_ports[i];
+        if (tx_priv != NULL)
+        {
+            spin_lock(tx_priv->lock);
+
+            queue = MV_ETH_TX_Q_NUM;
+            while(queue--)
+            {
+                if(tx_priv->tx_count[queue] > mv_eth_tx_done_quota)
+                    tx_priv->tx_count[queue] -= eth_tx_done(tx_priv, queue);
+
+#ifdef ETH_MV_TX_EN
+                if(tx_priv->tx_en && (tx_priv->tx_count[queue] > 0) )
+                    eth_tx_enable(tx_priv, queue);
+#endif /* ETH_MV_TX_EN */
+	        }
+                spin_unlock(tx_priv->lock);
+        }
+    }
+	return;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+static int eth_poll( struct net_device *dev, int *budget )
+#else
+static int eth_poll( struct napi_struct *napi, int budget )
+#endif
+{
+    int             queue, rx_done=0, rx_todo;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    mv_eth_priv     *priv = MV_ETH_PRIV(dev);
+#else
+    mv_eth_priv     *priv = container_of(napi, mv_eth_priv, napi);
+    struct net_device *dev = priv->net_dev;
+#endif
+
+    ETH_STAT_INFO(priv->eth_stat.poll_events++);
+    ETH_DBG(ETH_DBG_POLL, ("%s: Start eth_poll\n", dev->name));
+
+    if( priv->picer & (1 << ETH_CAUSE_LINK_STATE_CHANGE_BIT) ) 
+    {
+        eth_check_link_status(dev);
+        priv->picer &= ~ETH_LINK_MASK;
+    }
+/*
+    MV_CPU_CNTRS_START(empty_event);
+    MV_CPU_CNTRS_STOP(empty_event);
+    MV_CPU_CNTRS_SHOW(empty_event);
+*/
+#ifdef ETH_TX_DONE_ISR
+        spin_lock(priv->lock);
+
+	queue = MV_ETH_TX_Q_NUM;
+	while(queue--)
+        {
+            if(priv->tx_count[queue] > 0)
+            {
+#ifdef ETH_MV_TX_EN
+                if(priv->tx_en)
+		        eth_tx_enable(priv, queue);
+#endif /* ETH_MV_TX_EN */
+		        priv->tx_count[queue] -= eth_tx_done(priv, queue);
+            }
+        }
+	spin_unlock(priv->lock);
+#endif /* ETH_TX_DONE_ISR */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    rx_todo = min(*budget, dev->quota);
+#else
+    rx_todo = budget;
+#endif
+
+#if (MV_ETH_RX_Q_NUM > 1)
+    while(MV_TRUE)
+    {
+        queue = eth_rx_policy(priv);
+        if(queue == -1)
+            break;
+
+        rx_done += eth_rx(dev, rx_todo - rx_done, queue);
+        if(rx_done < rx_todo)
+            priv->picr &= ~(ETH_CAUSE_RX_READY_MASK(queue) | 
+                            ETH_CAUSE_RX_ERROR_MASK(queue));
+        else
+            break;
+    }
+#else
+    rx_done = eth_rx( dev, rx_todo, ETH_DEF_RXQ);
+#endif /* (MV_ETH_RX_Q_NUM > 1) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    *budget -= rx_done;
+    dev->quota -= rx_done;
+#else
+    budget -= rx_done;
+#endif
+
+#if defined(CONFIG_MV_ETH_NFP) && !defined(ETH_TX_DONE_ISR)
+    if( fp_is_enabled() )
+    {
+	eth_check_for_tx_done();
+    }
+#endif /* CONFIG_MV_ETH_NFP && !ETH_TX_DONE_ISR */
+
+#ifdef ETH_LRO
+    if (rx_done && priv->lro_en)
+        lro_flush_all(&priv->lro_mgr);
+#endif	
+
+    ETH_DBG( ETH_DBG_POLL, ("poll work done: rx-%d\n", rx_done) );
+
+    if ( (!netif_running(dev)) || (rx_done < rx_todo) )
+    { 
+        unsigned long flags;
+        local_irq_save(flags);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+        netif_rx_complete(dev);
+#else
+	napi_complete(&priv->napi);
+#endif
+        ETH_STAT_INFO(priv->eth_stat.poll_complete++);
+        mv_eth_unmask_interrupts(priv);
+	ETH_DBG( ETH_DBG_RX, ("unmask\n") );
+        local_irq_restore(flags);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+        return 0;
+#else
+	return rx_done;
+#endif
+    }
+    else
+    {
+#if (MV_ETH_RX_Q_NUM > 1)
+        /* Leave in NAPI context, so update picr and picer */
+        mv_eth_save_interrupts(priv);
+	    mv_eth_clear_saved_interrupts(priv);
+#endif /* (MV_ETH_RX_Q_NUM > 1) */
+    }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    return 1;
+#else
+	return rx_done;
+#endif
+}
+
+
+/* Show network driver configuration */
+void	mv_eth_config_show(void)
+{
+    int     i;
+
+    printk( "  o %s\n", ETH_DESCR_CONFIG_STR );
+
+#if defined(ETH_DESCR_IN_SRAM)
+    printk( "  o %s\n", INTEG_SRAM_CONFIG_STR );
+#endif
+
+    printk( "  o %s\n", ETH_SDRAM_CONFIG_STR );
+
+#if (CONFIG_MV_ETH_RXQ > MV_ETH_MAX_RXQ)
+#   error "CONFIG_MV_ETH_RXQ is large than MV_ETH_MAX_RXQ"
+#endif  
+
+#if CONFIG_MV_ETH_TXQ > MV_ETH_MAX_TXQ
+#   error "CONFIG_MV_ETH_TXQ is large than MV_ETH_MAX_TXQ"
+#endif 
+ 
+#if defined(ETH_INCLUDE_TSO) && !defined(TX_CSUM_OFFLOAD)
+#error "If TSO supported - TX checksum offload must be supported too"
+#endif
+
+    printk("  o %d Giga ports supported\n", CONFIG_MV_ETH_PORTS_NUM); 
+
+#if (CONFIG_MV_ETH_RXQ > 1)
+    printk( "  o Multi RX Queue support - %d RX queues\n", CONFIG_MV_ETH_RXQ);
+#else
+    printk( "  o Single RX Queue support - ETH_DEF_RXQ=%d\n", ETH_DEF_RXQ);
+#endif /* CONFIG_MV_ETH_RXQ > 1 */
+
+#if (CONFIG_MV_ETH_TXQ > 1)
+    printk( "  o Multi TX Queue support - %d TX Queues\n", CONFIG_MV_ETH_TXQ);
+#else
+    printk( "  o Single TX Queue support - ETH_DEF_TXQ=%d\n", ETH_DEF_TXQ);
+#endif /* CONFIG_MV_ETH_TXQ > 1 */
+
+#if defined(ETH_INCLUDE_TSO)
+    printk("  o TCP segmentation offload (TSO) supported\n");
+#endif /* ETH_INCLUDE_TSO */
+
+#if defined(ETH_INCLUDE_UFO)
+    printk("  o UDP fragmentation offload (UFO) supported\n");
+#endif /* ETH_INCLUDE_UFO */
+
+#ifdef ETH_LRO
+    printk("  o Large Receive offload (LRO) supported\n");
+#endif
+
+#if defined(RX_CSUM_OFFLOAD)
+    printk("  o Receive checksum offload supported\n");
+#endif
+#if defined(TX_CSUM_OFFLOAD)
+    printk("  o Transmit checksum offload supported\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP
+    printk("  o Network Fast Processing (Routing) supported - (%s)\n", 
+                    fp_is_enabled() ? "Enabled" : "Disabled");
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+    printk("  o Network Fast Processing (NAT) supported\n");
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+#endif /* CONFIG_MV_ETH_NFP */
+
+#ifdef CONFIG_MV_ETH_STATS_ERROR
+    printk("  o Driver ERROR statistics enabled\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_STATS_INFO
+    printk("  o Driver INFO statistics enabled\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_STATS_DEBUG
+    printk("  o Driver DEBUG statistics enabled\n");
+#endif
+
+#ifdef ETH_DEBUG
+    printk("  o Driver debug messages enabled\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_PROC
+    printk("  o Proc tool API enabled\n");
+#endif
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+	printk("  o SKB Reuse supported - (%s)\n", 
+                    eth_skb_reuse_enable ? "Enabled" : "Disabled");
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	printk("  o SKB Recycle supported - (%s)\n", 
+                    eth_skb_recycle_enable ? "Enabled" : "Disabled");
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+#if defined(CONFIG_MV_GATEWAY)
+    printk("  o Gateway support enabled\n");
+
+    printk("     o Using Marvell Header Mode\n");
+
+#ifdef CONFIG_MV_GTW_IGMP
+    printk("     o L2 IGMP support\n");
+#endif /* CONFIG_MV_GTW_IGMP */
+
+#endif /* CONFIG_MV_GATEWAY */
+
+    printk("  o Rx descripors:");
+    for(i=0; i<CONFIG_MV_ETH_RXQ; i++) {
+        printk(" q%d=%-3d", i, mv_eth_rxq_desc[i]);
+    }
+    printk("\n");
+
+#if CONFIG_MV_ETH_TXQ > MV_ETH_MAX_TXQ
+#error "CONFIG_MV_ETH_TXQ is large than MV_ETH_MAX_TXQ"
+#endif 
+
+    printk("  o Tx descripors:");
+    for(i=0; i<CONFIG_MV_ETH_TXQ; i++) {
+        printk(" q%d=%-3d", i, mv_eth_txq_desc[i]);
+    }
+    printk("\n");
+}
+
+void    mv_netdev_set_features(struct net_device *dev)
+{
+    dev->features = NETIF_F_SG | NETIF_F_LLTX;
+
+#ifdef TX_CSUM_OFFLOAD
+        if(dev->mtu <= ETH_CSUM_MAX_BYTE_COUNT) 
+        {
+            dev->features |= NETIF_F_IP_CSUM;
+        }
+#endif /* TX_CSUM_OFFLOAD */
+
+#ifdef ETH_INCLUDE_TSO
+    if(dev->features & NETIF_F_IP_CSUM)
+	    dev->features |= NETIF_F_TSO;
+#endif /* ETH_INCLUDE_TSO */
+
+#ifdef ETH_INCLUDE_UFO
+    /* FIXME: HW_CSUM is required by dev.c */
+    if(dev->features & NETIF_F_IP_CSUM)
+        dev->features |= NETIF_F_UFO | NETIF_F_HW_CSUM; 
+#endif /* ETH_INCLUDE_UFO */
+}
+
+/*********************************************************** 
+ * mv_eth_start_internals --                                *
+ *   fill rx buffers. start rx/tx activity. set coalesing. *
+ *   clear and unmask interrupt bits                       *
+ ***********************************************************/
+int     mv_eth_start_internals(mv_eth_priv *priv, int mtu)
+{
+    unsigned long flags;
+    unsigned int status;
+    int num;
+
+    spin_lock_irqsave( priv->lock, flags); 
+
+    /* fill rx ring with buffers */
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+    num = mvStackFreeElements(priv->fpRxPool);
+#else
+    num = mv_eth_rx_desc_total;
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_SKB_REUSE */ 
+
+    eth_rx_fill(priv, num, mtu);
+    priv->skb_alloc_fail_cnt = 0;
+
+    mv_eth_clear_interrupts(priv);
+
+    /* start the hal - rx/tx activity */
+    status = mvEthPortEnable( priv->hal_priv );
+    if( (status != MV_OK) && (status != MV_NOT_READY)) {
+        printk( KERN_ERR "GbE port %d: ethPortEnable failed\n", priv->port);
+        spin_unlock_irqrestore( priv->lock, flags);
+      return -1;
+    }
+
+    /* set tx/rx coalescing mechanism */
+#ifdef CONFIG_MV_ETH_TOOL
+    mvEthTxCoalSet( priv->hal_priv, priv->tx_coal_usec );
+    mvEthRxCoalSet( priv->hal_priv, priv->rx_coal_usec );
+#else
+    mvEthTxCoalSet( priv->hal_priv, ETH_TX_COAL );
+    mvEthRxCoalSet( priv->hal_priv, ETH_RX_COAL );
+#endif
+
+    spin_unlock_irqrestore( priv->lock, flags);
+
+    return 0;
+}
+
+/*********************************************************** 
+ * mv_eth_stop_internals --                                 *
+ *   stop port rx/tx activity. free skb's from rx/tx rings.*
+ ***********************************************************/
+int     mv_eth_stop_internals(mv_eth_priv *priv)
+{
+    MV_PKT_INFO     *pPktInfo;
+    unsigned int    queue;
+
+    /* stop the port activity, mask all interrupts */
+    if( mvEthPortDisable( priv->hal_priv ) != MV_OK ) {
+        printk( KERN_ERR "GbE port %d: ethPortDisable failed\n", priv->port );
+        goto error;
+    }
+
+    /* clear all ethernet port interrupts */
+    mv_eth_clear_interrupts(priv);
+
+    mv_eth_mask_interrupts(priv);
+
+    /* free the skb's in the hal tx ring and release memory */
+    for(queue=0; queue<MV_ETH_TX_Q_NUM; queue++)
+    {
+        while( (pPktInfo = mvEthPortForceTxDone(priv->hal_priv, queue)) ) 
+        {
+            eth_pkt_info_free(priv, pPktInfo);
+        }
+        priv->tx_count[queue] = 0;
+    }
+
+    /* free the skb's in the hal rx ring */
+    for(queue=0; queue<MV_ETH_RX_Q_NUM; queue++)
+    {    
+        while( (pPktInfo = mvEthPortForceRx( priv->hal_priv, queue)) ) {
+            dev_kfree_skb_any( (struct sk_buff *)pPktInfo->osInfo );
+            ETH_STAT_DBG(priv->eth_stat.skb_free_ok++);
+            mvOsFree(pPktInfo->pFrags);
+            mvOsFree(pPktInfo);
+        }
+    }
+
+#if defined(CONFIG_MV_ETH_NFP) || defined (CONFIG_MV_ETH_SKB_REUSE)
+    while( (pPktInfo = eth_pkt_info_get(priv)) )
+    {
+        dev_kfree_skb_any( (struct sk_buff *)pPktInfo->osInfo );
+        ETH_STAT_DBG(priv->eth_stat.skb_free_ok++);
+        mvOsFree(pPktInfo->pFrags);
+        mvOsFree(pPktInfo);
+    }
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	eth_skb_recycle_clear(priv);
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+    /* Reset Rx descriptors ring */
+    for(queue=0; queue<MV_ETH_RX_Q_NUM; queue++)
+    {
+        ethResetRxDescRing(priv->hal_priv, queue);
+    }
+    /* Reset Tx descriptors ring */
+    for(queue=0; queue<MV_ETH_TX_Q_NUM; queue++)
+    {
+        ethResetTxDescRing(priv->hal_priv, queue);
+    }
+
+    return 0;
+
+ error:
+    printk( KERN_ERR "GbE port %d: stop internals failed\n", priv->port );
+    return -1;
+}
+
+
+/*********************************************************** 
+ * mv_eth_change_mtu_internals --                                     *
+ *   stop port activity. release skb from rings. set new   *
+ *   mtu in device and hw. restart port activity and       *
+ *   and fill rx-buiffers with size according to new mtu.  *
+ ***********************************************************/
+int     mv_eth_change_mtu_internals( struct net_device *dev, int mtu )
+{
+    mv_eth_priv *priv = MV_ETH_PRIV(dev);
+
+    if(mtu > 9676 /* 9700 - 20 and rounding to 8 */) {
+        printk( "%s: Illegal MTU value %d, ", dev->name, mtu);
+        mtu = 9676;
+        printk(" rounding MTU to: %d \n",mtu);  
+    }
+
+    if(MV_RX_BUF_SIZE( mtu) & ~ETH_RX_BUFFER_MASK) {
+        printk( "%s: Illegal MTU value %d, ", dev->name, mtu);
+        mtu = 8 - (MV_RX_BUF_SIZE( mtu) & ~ETH_RX_BUFFER_MASK) + mtu;
+        printk(" rounding MTU to: %d \n",mtu);
+    }
+
+    /* set mtu in device and in hal sw structures */
+    if( mvEthMaxRxSizeSet( priv->hal_priv, MV_RX_BUF_SIZE( mtu)) ) {
+        printk( KERN_ERR "%s: ethPortSetMaxBufSize failed\n", dev->name );
+        return -1;
+    }
+
+    dev->mtu = mtu;
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	eth_skb_recycle_clear(priv);
+#endif
+
+    mv_netdev_set_features(dev);
+
+    return 0;
+}
+
+
+/*********************************************************** 
+ * mv_netdev_timer_callback --                                *
+ *   N msec periodic callback for cleanup.                 *
+ ***********************************************************/
+static void mv_netdev_timer_callback( unsigned long data )
+{
+    struct net_device   *dev = (struct net_device *)data;
+    mv_eth_priv         *priv = MV_ETH_PRIV(dev);
+    int                 queue;
+
+    ETH_DBG( ETH_DBG_TX, ("%s: timer_callback\n", dev->name) );
+    ETH_STAT_INFO(priv->eth_stat.timer_events++);
+
+    spin_lock(priv->lock);
+
+    mvEthPortTxRestart(priv->hal_priv);
+
+#ifdef ETH_TX_DONE_ISR
+#else
+    /* Call TX done */
+	queue = MV_ETH_TX_Q_NUM;
+	while(queue--) {
+        if (priv->tx_count[queue] > 0) 
+			priv->tx_count[queue] -= eth_tx_done(priv, queue);
+    }
+#endif /* ETH_TX_DONE_ISR */ 
+
+    if(priv->skb_alloc_fail_cnt > 0)
+    {
+        priv->skb_alloc_fail_cnt -= eth_rx_fill(priv, priv->skb_alloc_fail_cnt, dev->mtu);
+    }
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+    eth_skb_alloc_for_reuse(priv, dev->mtu);
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+    /* Refill pktInfo */
+	if (priv->refill_needed_flag) {
+        int             fill;
+        MV_PKT_INFO*    pPktInfo;
+
+  	    priv->refill_needed_flag = 0;
+        queue = MV_ETH_RX_Q_NUM;
+
+		while (queue--) {
+
+			fill = mv_eth_rxq_desc[queue] - mvEthRxResourceGet(priv->hal_priv, queue);
+
+            while (fill--) {
+		        pPktInfo = eth_pkt_info_get(priv);
+		        if (pPktInfo != NULL) {
+                	mvEthPortRxDone(priv->hal_priv, queue, pPktInfo);
+			        ETH_STAT_DBG(priv->eth_stat.rx_fill_ok[queue]++);
+		        }
+		        else {
+                    ETH_STAT_ERR(priv->eth_stat.rx_pool_empty++);
+                    priv->refill_needed_flag = 1;
+			        break;
+		        }
+            }
+        }
+    }
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_SKB_REUSE */
+
+
+    spin_unlock(priv->lock);
+
+    if (priv->timer_flag)
+    {
+        priv->timer.expires = jiffies + ((HZ*CONFIG_MV_ETH_TIMER_PERIOD)/1000); /*ms*/
+        add_timer(&priv->timer);
+    }
+}
+
+/* Initialize Ethernet port on chip */
+int  __init mv_eth_hal_init(mv_eth_priv *priv, int mtu, u8* mac)
+{
+    MV_ETH_PORT_INIT    hal_init_struct;
+
+        /* init the hal */
+    hal_init_struct.rxDefQ = ETH_DEF_RXQ;
+    memcpy(hal_init_struct.rxDescrNum,  mv_eth_rxq_desc, sizeof(int)*MV_ETH_RX_Q_NUM);
+    memcpy(hal_init_struct.txDescrNum,  mv_eth_txq_desc, sizeof(int)*MV_ETH_TX_Q_NUM);
+    hal_init_struct.osHandle = NULL;
+
+    priv->hal_priv = mvEthPortInit( priv->port, &hal_init_struct );
+    if( !priv->hal_priv ) {
+        printk( KERN_ERR "eth port=%d: load failed\n", priv->port);
+        return -ENODEV;
+    }
+
+#ifdef CONFIG_ETH_FLOW_CONTROL
+    /* enable flow Control in MAC level */
+    mvEthFlowCtrlSet(priv->hal_priv, MV_ETH_FC_ENABLE);
+#endif
+
+    if(mac)
+    {
+        /* set new addr in hw */
+        if( mvEthMacAddrSet( priv->hal_priv, mac, ETH_DEF_RXQ) != MV_OK ) 
+        {
+            printk("mv_eth_hal_init: ethSetMacAddr failed for port=%d\n", priv->port);
+            return -ENODEV;
+        }
+    }
+    else
+    {
+        mvEthRxFilterModeSet(priv->hal_priv, MV_TRUE);
+    }
+
+    if( mvEthMaxRxSizeSet( priv->hal_priv, MV_RX_BUF_SIZE(mtu)) ) {
+        printk( "mv_eth_hal_init: ethPortSetMaxBufSize failed for port=%d\n", priv->port);
+        return -ENODEV;
+    }
+    return 0;
+}
+
+/* Initialize HAL level of Ethernet driver */
+int __init mv_eth_priv_init(mv_eth_priv *priv, int port)
+{
+    int         txq, i;
+    MV_PKT_INFO *pkt_info;
+
+    memset(priv, 0, sizeof(mv_eth_priv) );
+
+#if defined(ETH_INCLUDE_TSO) || defined(ETH_INCLUDE_UFO) || defined(CONFIG_MV_GATEWAY)
+    for(txq=0; txq<MV_ETH_TX_Q_NUM; txq++)
+    {
+        priv->tx_extra_bufs[txq] = mvOsMalloc(mv_eth_txq_desc[txq]*sizeof(char*));
+        if(priv->tx_extra_bufs[txq] == NULL)
+        {
+            printk("GbE port %d TSO/UFO: txq=%d - Can't alloc %d bytes for tx_extra_bufs array\n", 
+                        port, txq, mv_eth_txq_desc[txq]*sizeof(char*));
+            return -ENOMEM;
+        }
+        for(i=0; i<mv_eth_txq_desc[txq]; i++)
+        {
+            priv->tx_extra_bufs[txq][i] = mvOsMalloc(TX_EXTRA_BUF_SIZE);
+            if(priv->tx_extra_bufs[txq][i] == NULL)
+            {
+                printk("GbE port %d TSO/UFO: txq=%d - Can't alloc %d extra TX buffer (%d bytes)\n", 
+                        port, txq, i, TX_EXTRA_BUF_SIZE);
+                return -ENOMEM;
+            }
+        }
+        priv->tx_extra_buf_idx[txq] = 0;
+    }
+#endif /* ETH_INCLUDE_TSO || ETH_INCLUDE_UFO || CONFIG_MV_GATEWAY */
+
+    priv->txPktInfoPool = mvStackCreate(mv_eth_tx_desc_total);
+    if(priv->txPktInfoPool == NULL)
+    {
+        printk("GbE port %d: Can't create txPktInfoPool for %d elements\n", 
+                    port, mv_eth_tx_desc_total);
+        return -ENOMEM;
+    }
+
+    for(i=0; i<mv_eth_tx_desc_total; i++)
+    {
+        pkt_info = mvOsMalloc(sizeof(MV_PKT_INFO));
+        if(pkt_info == NULL)
+        {
+            printk("GbE port %d: Can't alloc %d bytes for %d MV_PKT_INFO structure\n", 
+                    port, sizeof(MV_PKT_INFO), i);
+            return -ENOMEM;
+        }
+        memset(pkt_info, 0, sizeof(MV_PKT_INFO));
+        pkt_info->ownerId = ~0; 
+
+        pkt_info->pFrags = mvOsMalloc(sizeof(MV_BUF_INFO)*(MAX_SKB_FRAGS+3));
+        if(pkt_info->pFrags == NULL)
+        {
+            printk("GbE port %d: Can't alloc %d bytes for %d MV_BUF_INFO array\n", 
+                    port, (int)(sizeof(MV_BUF_INFO)*(MAX_SKB_FRAGS+3)), i);
+            return -ENOMEM;
+        }
+        memset(pkt_info->pFrags, 0, sizeof(MV_BUF_INFO)*(MAX_SKB_FRAGS+3));
+        mvStackPush(priv->txPktInfoPool, (MV_U32)pkt_info);
+    }
+
+    memset(priv->tx_count, 0, sizeof(priv->tx_count));
+
+    /* init mv_eth_priv */
+    priv->port = port;
+
+    memset( &priv->timer, 0, sizeof(struct timer_list) );
+    priv->timer.function = mv_netdev_timer_callback;
+    init_timer(&priv->timer);
+    priv->timer_flag = 0;
+    priv->skb_alloc_fail_cnt = 0;
+
+#ifdef ETH_LRO
+    priv->lro_en = 0;
+    priv->lro_mgr.max_aggr = 10;
+    priv->lro_mgr.max_desc = 4;
+    priv->lro_mgr.lro_arr = priv->lro_desc;
+    priv->lro_mgr.get_skb_header = NULL;
+    priv->lro_mgr.features = LRO_F_NAPI;
+    priv->lro_mgr.dev = NULL;
+    priv->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
+    priv->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+#endif /* ETH_LRO */
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+    priv->refill_needed_flag = 0;
+    priv->fpRxPool = mvStackCreate(mv_eth_rx_desc_total*2 + mv_eth_tx_desc_total);
+    if(priv->fpRxPool == NULL)
+    {
+        mvOsPrintf("eth_priv_init_%d: Can't create fpRxPool for %d elements\n", 
+                port, (mv_eth_rx_desc_total*2 + mv_eth_tx_desc_total));
+        return -ENOMEM;
+    }
+#endif /* (CONFIG_MV_ETH_NFP) || (CONFIG_MV_ETH_SKB_REUSE) */
+
+#ifdef CONFIG_MV_ETH_NFP
+    memset(&priv->fpStats, 0, sizeof(priv->fpStats) );
+    priv->lock = &nfp_lock;
+#else
+    priv->lock = kmalloc(sizeof(spinlock_t), GFP_ATOMIC);
+    spin_lock_init( priv->lock );
+#endif /* CONFIG_MV_ETH_NFP */
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+    priv->skbReusePool = mvStackCreate(mv_eth_rx_desc_total*2);
+    if(priv->skbReusePool == NULL)
+    {
+        printk("eth_priv_init_%d: Can't create skbReusePool for %d elements\n", 
+                port, mv_eth_rx_desc_total*2);
+        return -ENOMEM;
+    }
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+    priv->skbRecycleMTU = 0;
+    priv->skbRecyclePool = mvStackCreate(1024);
+    if (!priv->skbRecyclePool) {
+        printk("%s: port %d, failed to allocate pool\n", __FUNCTION__, port);
+        return -ENOMEM;
+    }	
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+#ifdef ETH_MV_TX_EN
+    priv->tx_en = priv->tx_en_bk = MV_ETH_TX_EN_DEFAULT;
+    priv->tx_en_deep = 1;
+#endif /* ETH_MV_TX_EN */
+
+#ifdef CONFIG_MV_ETH_TOOL
+    /* MII address setup */
+    priv->phy_id = mvBoardPhyAddrGet(port);
+    /* Configure defaults */
+    priv->autoneg_cfg  = AUTONEG_ENABLE;
+    priv->speed_cfg    = SPEED_1000;
+    priv->duplex_cfg  = DUPLEX_FULL;
+    priv->tx_coal_usec = ETH_TX_COAL;
+    priv->rx_coal_usec = ETH_RX_COAL;
+#ifdef RX_CSUM_OFFLOAD
+    priv->rx_csum_offload = 1;
+#endif
+
+#endif /* CONFIG_MV_ETH_TOOL */
+
+    return 0;
+}
+
+/* Release all allocated memory */
+void    mv_eth_priv_cleanup(mv_eth_priv *priv)
+{
+    MV_PKT_INFO *pkt_info;
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+    if(priv->skbReusePool != NULL)
+    {
+        mvStackDelete(priv->skbReusePool);
+        priv->skbReusePool = NULL;
+    }
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+    if (priv->skbRecyclePool) 
+	{
+		mvStackDelete(priv->skbRecyclePool);
+		priv->skbRecyclePool = NULL;
+    }
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+#ifdef CONFIG_MV_ETH_NFP
+#else
+    if(priv->lock != NULL)
+    {
+        kfree(priv->lock);
+        priv->lock = NULL;
+    }
+#endif /* CONFIG_MV_ETH_NFP */
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+    if(priv->fpRxPool != NULL)
+    {
+        mvStackDelete(priv->fpRxPool);
+        priv->fpRxPool = NULL;
+    }
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_SKB_REUSE */
+
+#if defined(ETH_INCLUDE_TSO) || defined(ETH_INCLUDE_UFO) || defined(CONFIG_MV_GATEWAY)
+    {
+        int     i, txq;
+
+        for(txq=0; txq<MV_ETH_TX_Q_NUM; txq++)
+        {
+            if(priv->tx_extra_bufs[txq] != NULL)
+            {
+                for(i=0; i<mv_eth_txq_desc[txq]; i++)
+                {
+                    if(priv->tx_extra_bufs[txq][i] != NULL)
+                    {
+                        mvOsFree(priv->tx_extra_bufs[txq][i]);
+                        priv->tx_extra_bufs[txq][i] = NULL;
+                    }
+                }
+                mvOsFree(priv->tx_extra_bufs[txq]);
+                priv->tx_extra_bufs[txq] = NULL;
+            }
+        }
+    }
+#endif /* ETH_INCLUDE_TSO || ETH_INCLUDE_UFO || CONFIG_MV_GATEWAY */
+
+    if(priv->txPktInfoPool)
+    {
+        while(mvStackIsEmpty(priv->txPktInfoPool) == MV_FALSE)
+        {
+            pkt_info = (MV_PKT_INFO*)mvStackPop(priv->txPktInfoPool);
+            if(pkt_info != NULL)
+            {
+                if(pkt_info->pFrags != NULL)
+                {
+                    mvOsFree(pkt_info->pFrags);
+                }
+                mvOsFree(pkt_info);
+            }
+        }
+        mvStackDelete(priv->txPktInfoPool);
+    }
+}
+
+
+#ifdef ETH_INCLUDE_TSO
+/*********************************************************** 
+ * eth_tso_tx --                                             *
+ *   send a packet.                                        *
+ ***********************************************************/
+static int eth_tso_tx(struct sk_buff *skb, struct net_device *dev, int txq)
+{
+    MV_STATUS       status;
+    MV_PKT_INFO     *pPktInfo;
+    int             pkt, frag, buf;
+    int             total_len, hdr_len, mac_hdr_len, size, frag_size, data_left;
+    char            *frag_ptr, *extra_ptr;
+    MV_U16          ip_id;
+    MV_U32          tcp_seq;
+    struct iphdr    *iph;
+    struct tcphdr   *tcph;
+    skb_frag_t      *skb_frag_ptr;
+    mv_eth_priv     *priv = MV_ETH_PRIV(dev);
+    const struct tcphdr *th = tcp_hdr(skb);
+
+    pkt = 0;        
+    frag = 0;
+    total_len = skb->len;
+    hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+    mac_hdr_len = skb_network_offset(skb);
+
+    total_len -= hdr_len;
+
+    if(skb_shinfo(skb)->frag_list != NULL)
+    {
+        printk("***** ERROR: frag_list is not null\n");
+        print_skb(skb);
+    }
+
+    if(skb_shinfo(skb)->gso_segs == 1)
+    {
+        printk("***** ERROR: only one TSO segment\n");
+        print_skb(skb);
+    }
+
+    if(total_len <= skb_shinfo(skb)->gso_size)
+    {
+        printk("***** ERROR: total_len less than gso_size\n");
+        print_skb(skb);
+    }
+
+    if( (htons(ETH_P_IP) != skb->protocol) || 
+        (ip_hdr(skb)->protocol != IPPROTO_TCP) )
+    {
+        printk("***** ERROR: Unexpected protocol\n");
+        print_skb(skb);
+    }
+
+    ip_id = ntohs(ip_hdr(skb)->id);
+    tcp_seq = ntohl(th->seq);
+
+    frag_size = skb_headlen(skb);
+    frag_ptr = skb->data;
+
+    if(frag_size < hdr_len){
+        printk("***** ERROR: frag_size=%d, hdr_len=%d\n", frag_size, hdr_len);
+        print_skb(skb);
+    }
+
+    frag_size -= hdr_len;
+    frag_ptr += hdr_len;
+    if(frag_size == 0)
+    {
+        skb_frag_ptr = &skb_shinfo(skb)->frags[frag];
+
+        /* Move to next segment */
+        frag_size = skb_frag_ptr->size;
+        frag_ptr = page_address(skb_frag_ptr->page) + skb_frag_ptr->page_offset;
+        frag++;
+    }
+
+    while(total_len > 0)
+    {            
+        pPktInfo = (MV_PKT_INFO*)mvStackPop(priv->txPktInfoPool);
+
+        extra_ptr = priv->tx_extra_bufs[txq][priv->tx_extra_buf_idx[txq]++];
+        if(priv->tx_extra_buf_idx[txq] == mv_eth_txq_desc[txq])
+            priv->tx_extra_buf_idx[txq] = 0;
+
+#ifdef CONFIG_MV_GATEWAY
+	/* Note: supports Marvell Header mode, not VLAN mode */
+        if(priv->isGtw)
+        {
+            struct mv_vlan_cfg* vlan_cfg = MV_NETDEV_VLAN(dev);
+
+	    *(unsigned short *)(extra_ptr) = vlan_cfg->header;
+
+            pPktInfo->pFrags[0].bufVirtPtr = extra_ptr;
+            pPktInfo->pFrags[0].dataSize = ETH_MV_HEADER_SIZE;
+            pPktInfo->pktSize = ETH_MV_HEADER_SIZE;
+        }
+        else
+#endif /* CONFIG_MV_GATEWAY */
+        {
+            pPktInfo->pFrags[0].dataSize = 0;
+            pPktInfo->pktSize = 0;
+            pPktInfo->pFrags[0].bufVirtPtr = extra_ptr + ETH_MV_HEADER_SIZE;
+        }
+
+        extra_ptr += ETH_MV_HEADER_SIZE;
+        memcpy(extra_ptr, skb->data, hdr_len);
+
+        pPktInfo->pFrags[0].dataSize += hdr_len;
+        pPktInfo->pFrags[0].bufSize = TX_EXTRA_BUF_SIZE;
+
+        data_left = MV_MIN(skb_shinfo(skb)->gso_size, total_len);
+        pPktInfo->pktSize += (data_left + hdr_len);
+        total_len -= data_left;
+
+        /* Update fields */
+        iph = (struct iphdr*)(extra_ptr + mac_hdr_len);
+        iph->tot_len = htons(data_left + hdr_len - mac_hdr_len);
+        iph->id = htons(ip_id);
+
+        tcph = (struct tcphdr*)(extra_ptr + skb_transport_offset(skb));
+        tcph->seq = htonl(tcp_seq);
+/*
+        printk("pkt=%d, extra=%p, left=%d, total=%d, iph=%p, tcph=%p, id=%d, seq=0x%x\n",
+                pkt, extra_ptr, data_left, total_len, iph, tcph, ip_id, tcp_seq);
+*/
+        tcp_seq += data_left;
+        ip_id++;
+        if(total_len == 0)
+        {
+            /* Only for last packet */
+            pPktInfo->osInfo = (MV_ULONG)skb;
+        }
+        else
+        {
+            /* Clear all special flags for not last packet */
+            tcph->psh = 0;
+            tcph->fin = 0;
+            tcph->rst = 0;
+            pPktInfo->osInfo = (MV_ULONG)0;
+        }
+
+        buf = 1;
+        while(data_left > 0)
+        {
+            size = MV_MIN(frag_size, data_left);
+            if(size == 0)
+            {
+                printk("***** ERROR: data_left=%d, frag_size=%d\n", data_left, frag_size);
+                print_skb(skb);
+            }
+            data_left -= size;
+            frag_size -= size;
+            pPktInfo->pFrags[buf].bufVirtPtr = frag_ptr;
+            pPktInfo->pFrags[buf].dataSize = size;
+            frag_ptr += size;
+            buf++;
+            if( (frag < skb_shinfo(skb)->nr_frags) && (frag_size == 0) )
+            {                 
+                skb_frag_ptr = &skb_shinfo(skb)->frags[frag];
+
+                /* Move to next segment */
+                frag_size = skb_frag_ptr->size;
+                frag_ptr = page_address(skb_frag_ptr->page) + skb_frag_ptr->page_offset;
+                frag++;
+            }
+        }
+        /* packet is full */
+        pPktInfo->numFrags = buf;
+        pPktInfo->status =  
+                (ETH_TX_IP_NO_FRAG | ETH_TX_L4_TCP_TYPE |
+                 ETH_TX_GENERATE_L4_CHKSUM_MASK | ETH_TX_GENERATE_IP_CHKSUM_MASK |
+                 ((ip_hdr(skb)->ihl) << ETH_TX_IP_HEADER_LEN_OFFSET) );
+
+        status = mvEthPortSgTx( priv->hal_priv, txq, pPktInfo);
+        if( status == MV_OK ) {
+            priv->tx_count[txq]++;
+            dev->stats.tx_packets++;
+            dev->stats.tx_bytes +=  pPktInfo->pktSize;
+            dev->trans_start = jiffies;
+            ETH_STAT_DBG( priv->eth_stat.tx_hal_ok[txq]++);
+        }
+        else
+        {
+            /* tx failed. */
+
+            /* For single TX queue it must not happen because 
+            *   we stop call to netif_stop_queue in advance 
+            * For Multu TX queue config, free skb and continue without stopping. 
+            */
+            dev->stats.tx_dropped++;
+
+            ETH_DBG( ETH_DBG_TX, ("%s: queue=%d is full, stop transmit\n", dev->name, txq) );
+
+            /* we need to reuse this pPktInfo because TX failed */
+            dev_kfree_skb_any(skb);
+            pPktInfo->osInfo = 0;
+            mvStackPush(priv->txPktInfoPool, (MV_U32)pPktInfo);
+
+            /* Release extra buffer too */            
+  			if(priv->tx_extra_buf_idx[txq] == 0)
+            {
+                priv->tx_extra_buf_idx[txq] = mv_eth_txq_desc[txq]-1;
+            }
+            else
+	    	{
+                priv->tx_extra_buf_idx[txq]--;
+            }
+
+            ETH_STAT_DBG( priv->eth_stat.tx_hal_no_resource[txq]++);
+            return 0;
+        }   
+        pkt++;
+    }    
+    return 0;
+}
+#endif /* ETH_INCLUDE_TSO */
+
+#ifdef ETH_INCLUDE_UFO
+/*********************************************************** 
+ * eth_ufo_tx --                                           *
+ *   send a large UDP packet.                              *
+ ***********************************************************/
+static int eth_ufo_tx(struct sk_buff *skb, struct net_device *dev, int txq)
+{
+   	MV_STATUS       status;
+	unsigned int    nr, fn;
+	skb_frag_t      *fp;
+	mv_eth_priv     *priv = MV_ETH_PRIV(dev);
+	struct iphdr    *iph;
+	MV_PKT_INFO     *pPktInfo;
+	int             buf;
+	char            *data;
+	unsigned int    pkt_sz, pkt_nm, size;
+	unsigned int    left, mtu, hlen, hhlen, dlen, offset;
+	int             extra_buf_used = 0;
+
+	ETH_DBG(ETH_DBG_GSO, ("UFO: sbk=%p len=%d gso_type=%d gso_segs=%d, gso_size=%d nr_frags=%d\n",              
+						  skb, skb->len, 
+						  skb_shinfo(skb)->gso_type, 
+						  skb_shinfo(skb)->gso_segs, 
+						  skb_shinfo(skb)->gso_size,
+						  skb_shinfo(skb)->nr_frags));
+
+	ETH_DBG(ETH_DBG_GSO, ("UFO: page[h] %d bytes\n", skb_headlen(skb)));
+
+#ifdef ETH_DEBUG
+	for (fn=0; fn<skb_shinfo(skb)->nr_frags; fn++)
+		ETH_DBG(ETH_DBG_GSO, ("UFO: page[%d] %d bytes\n", fn, skb_shinfo(skb)->frags[fn].size));
+#endif
+
+	iph = ip_hdr(skb);
+	hlen = iph->ihl * 4;
+	hhlen = skb_network_offset(skb);
+	mtu = dev->mtu + hhlen;
+
+	if (skb->ip_summed != CHECKSUM_NONE) {
+		struct udphdr *udph = udp_hdr(skb);
+		udph->check = 0;
+		offset = hhlen + hlen;
+		skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
+		udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len - hhlen - hlen, IPPROTO_UDP, skb->csum);
+	}
+
+	fn = 0;
+	nr = skb_shinfo(skb)->nr_frags;
+
+	/* skb_headlen */
+	size = skb_headlen(skb);
+	data = skb->data;
+	left = skb->len - hhlen - hlen; /* actual data to send */
+	offset = 0;
+
+	while (left) {
+       	pPktInfo = (MV_PKT_INFO*)mvStackPop(priv->txPktInfoPool);
+
+		extra_buf_used = 0;
+		/* ip header */
+		if (offset) { 	
+			data = priv->tx_extra_bufs[txq][priv->tx_extra_buf_idx[txq]++];
+            if(priv->tx_extra_buf_idx[txq] == mv_eth_txq_desc[txq])
+                priv->tx_extra_buf_idx[txq] = 0;
+
+#ifdef CONFIG_MV_GATEWAY
+	    /* Note: supports Marvell Header mode, not VLAN mode */
+            if(priv->isGtw)
+            {
+                struct mv_vlan_cfg *vlan_cfg = MV_NETDEV_VLAN(dev);
+
+	        *(unsigned short *)(data) = vlan_cfg->header;
+
+                pPktInfo->pFrags[0].bufVirtPtr = data;
+                pPktInfo->pFrags[0].dataSize = ETH_MV_HEADER_SIZE;
+          	pPktInfo->pktSize = ETH_MV_HEADER_SIZE;
+            }
+            else
+#endif /* CONFIG_MV_GATEWAY */
+            {
+                pPktInfo->pFrags[0].dataSize = 0;
+                pPktInfo->pktSize = 0;
+                pPktInfo->pFrags[0].bufVirtPtr = data + ETH_MV_HEADER_SIZE;
+            }
+
+			extra_buf_used = 1;
+			data += 2; 
+			size = hhlen + hlen;
+			memcpy(data, skb->data, size);
+		}
+
+		iph = (struct iphdr*)(((u32)data)+hhlen);	
+		pPktInfo->pFrags[0].dataSize += size;
+		buf = 1;
+		pkt_nm = 1;
+		pkt_sz = size;
+		ETH_DBG(ETH_DBG_GSO, ("UFO: add pkt[%d] %d bytes total=%d\n", pkt_nm-1, size, pkt_sz));	
+
+		/* payload */
+		while (fn < nr) {
+			fp = &skb_shinfo(skb)->frags[fn];
+
+			BUG_ON(mtu < pkt_sz);
+
+			size = min_t(int, fp->size, mtu - pkt_sz);
+			data = page_address(fp->page) + fp->page_offset;
+
+			fp->page_offset += size;
+			fp->size -= size;
+
+			if (fp->size == 0)
+				fn++;
+
+			if (size) {
+				pPktInfo->pFrags[buf].dataSize = size;
+				pPktInfo->pFrags[buf].bufVirtPtr = data;
+				buf++;
+				pkt_sz += size; 
+				pkt_nm++;
+				BUG_ON(pkt_nm == MAX_SKB_FRAGS);
+				ETH_DBG(ETH_DBG_GSO, ("UFO: add pkt[%d] %d bytes total=%d frag=%d\n", 
+							pkt_nm-1, size, pkt_sz, fn));	
+			}
+
+			if (mtu == pkt_sz)
+				break;
+		}
+
+		/* fill ip header */
+		dlen = pkt_sz - hhlen - hlen;
+
+		ETH_DBG(ETH_DBG_GSO, ("UFO: ip_payload=%d (bad=%d), offset=%d\n", 
+							   dlen, dlen & 7, offset));
+
+		iph->tot_len = htons(pkt_sz - hhlen);		
+		iph->frag_off = htons(offset>>3);
+		offset += dlen;
+		left -= dlen;
+		if (left)
+			iph->frag_off |= htons(IP_MF);
+
+		pPktInfo->osInfo = left ? 0 : (MV_ULONG)skb;
+		pPktInfo->pktSize += pkt_sz;
+		pPktInfo->numFrags = pkt_nm;
+		pPktInfo->status = ETH_TX_GENERATE_IP_CHKSUM_MASK | ((iph->ihl) << ETH_TX_IP_HEADER_LEN_OFFSET);
+
+		status = mvEthPortSgTx(priv->hal_priv, txq, pPktInfo);
+		ETH_DBG(ETH_DBG_GSO, ("UFO: Tx (ok=%d) %d bytes in %d bufs left=%d\n", 
+			   status, pPktInfo->pktSize, pPktInfo->numFrags, left));
+
+		if (status == MV_OK) {
+			dev->stats.tx_packets++;
+			dev->stats.tx_bytes += pPktInfo->pktSize;
+			dev->trans_start = jiffies;
+			priv->tx_count[txq]++;
+			ETH_STAT_DBG(priv->eth_stat.tx_hal_ok[txq]++);
+		}
+		else {
+            /* tx failed. */
+
+            /* For single TX queue it must not happen because 
+            *   we stop call to netif_stop_queue in advance 
+            * For Multu TX queue config, free skb and continue without stopping. 
+            */
+			dev->stats.tx_dropped++;
+
+			ETH_DBG( ETH_DBG_TX, ("%s: q=%d is full, stop transmit\n", dev->name, txq) );
+
+            /* we need to reuse this pPktInfo because TX failed */
+            dev_kfree_skb_any(skb);
+            pPktInfo->osInfo = 0;
+            mvStackPush(priv->txPktInfoPool, (MV_U32)pPktInfo);
+
+            /* Release extra buffer too */            
+  			if(priv->tx_extra_buf_idx[txq] == 0)
+            {
+                priv->tx_extra_buf_idx[txq] = mv_eth_txq_desc[txq]-1;
+            }
+            else
+	    	{
+                priv->tx_extra_buf_idx[txq]--;
+            }
+
+			ETH_STAT_DBG(priv->eth_stat.tx_hal_no_resource[txq]++);
+			return 0;
+		}   		
+	}
+
+    return 0;
+}
+#endif /* ETH_INCLUDE_UFO */
+
+/*********************************************************** 
+ * mv_eth_tx --                                         *
+ *   send a packet.                                        *
+ ***********************************************************/
+static int eth_tx( struct sk_buff *skb , struct net_device *dev )
+{
+    mv_eth_priv             *priv = MV_ETH_PRIV(dev);
+    struct net_device_stats *stats = MV_NETDEV_STATS(dev);
+    unsigned long           flags = 0;
+    MV_STATUS               status;
+    MV_PKT_INFO             *pPktInfo;
+    int                     ret = 0, i, queue, tx_done_count;
+    int tx_in_interrupt	    = in_interrupt();
+
+    if( netif_queue_stopped( dev ) ) {
+        printk( KERN_ERR "%s: transmitting while stopped\n", dev->name );
+        return 1;
+    }
+
+    if (!tx_in_interrupt)
+    	local_irq_save(flags);
+
+    if (!spin_trylock(priv->lock)) {
+        /* Collision - tell upper layer to requeue */
+	    if (!tx_in_interrupt)
+            local_irq_restore(flags);
+        return NETDEV_TX_LOCKED;
+    }
+
+    ETH_DBG( ETH_DBG_TX, ("%s: tx len=%d headlen=%d frags=%d, ip_summed=%d gso_type=%d\n",
+             dev->name, skb->len, skb_headlen(skb), skb_shinfo(skb)->nr_frags, skb->ip_summed,skb_shinfo(skb)->gso_type));
+    ETH_STAT_INFO(priv->eth_stat.tx_events++);
+
+    /* At this point we need to decide to which tx queue this packet goes, */
+    /* and whether we need to prepend a proprietary header.                */
+    queue = eth_tx_policy(priv, skb);
+
+#ifdef ETH_INCLUDE_TSO
+    if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) {
+        ret = eth_tso_tx(skb, dev, queue);
+	ETH_STAT_DBG( priv->eth_stat.tso_stats[skb->len >> 10]++);
+        goto tx_end;
+    }
+#endif /* ETH_INCLUDE_TSO */
+
+#ifdef ETH_INCLUDE_UFO
+    if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) {
+	    if (skb->len > dev->mtu) {
+	        ETH_STAT_DBG(priv->eth_stat.ufo_stats[skb->len >> 10]++);
+	        ret = eth_ufo_tx(skb, dev, queue);
+	        goto tx_end;
+	    }
+    }
+#endif /* ETH_INCLUDE_UFO */
+
+    pPktInfo = (MV_PKT_INFO*)mvStackPop(priv->txPktInfoPool);
+    pPktInfo->osInfo = (MV_ULONG)skb;
+    pPktInfo->pktSize = skb->len;
+    pPktInfo->status = 0;
+
+    /* see if this is a single/multiple buffered skb */
+    if( skb_shinfo(skb)->nr_frags == 0 ) {
+        pPktInfo->pFrags->bufVirtPtr = skb->data;
+        pPktInfo->pFrags->dataSize = skb->len;
+        pPktInfo->numFrags = 1;
+    }
+    else {
+
+        MV_BUF_INFO *p_buf_info = pPktInfo->pFrags;
+
+        /* first skb fragment */
+        p_buf_info->dataSize = skb_headlen(skb);
+        p_buf_info->bufVirtPtr = skb->data;
+        p_buf_info++;
+
+        /* now handle all other skb fragments */
+        for ( i = 0; i < skb_shinfo(skb)->nr_frags; i++ ) {
+
+            skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+            p_buf_info->dataSize = frag->size;
+            p_buf_info->bufVirtPtr = page_address(frag->page) + frag->page_offset;
+            p_buf_info++;
+        }
+        pPktInfo->numFrags = skb_shinfo(skb)->nr_frags + 1;
+    }
+
+#ifdef TX_CSUM_OFFLOAD
+    /* if HW is suppose to offload layer3 and layer4 checksum, 
+     *   set some bits in the first pkt_info command.
+    */
+    if(skb->ip_summed == CHECKSUM_PARTIAL) {
+        struct iphdr *iph = ip_hdr(skb); 
+
+        ETH_DBG( ETH_DBG_TX, ("%s: tx csum offload\n", dev->name) );
+        ETH_STAT_DBG( priv->eth_stat.tx_csum_hw++);
+
+        /* we do not handle fragmented IP packets. add check inside iph!! */
+        pPktInfo->status = ETH_TX_IP_NO_FRAG | ETH_TX_GENERATE_IP_CHKSUM_MASK |          
+                           (iph->ihl << ETH_TX_IP_HEADER_LEN_OFFSET);   
+
+        if(iph->protocol == IPPROTO_TCP) 
+            pPktInfo->status |= (ETH_TX_L4_TCP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK);
+        else if(iph->protocol == IPPROTO_UDP)
+            pPktInfo->status |= (ETH_TX_L4_UDP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK);
+    }
+    else {
+        ETH_DBG( ETH_DBG_TX, ("%s: no tx csum offload\n", dev->name) );
+        ETH_STAT_DBG( priv->eth_stat.tx_csum_sw++);
+        pPktInfo->status = 0x5 << ETH_TX_IP_HEADER_LEN_OFFSET; /* Errata BTS #50 */
+    }
+#endif
+
+#ifdef CONFIG_MV_GATEWAY
+    if(priv->isGtw)
+        mv_gtw_update_tx_skb(dev, pPktInfo);
+#endif /* CONFIG_MV_GATEWAY */
+
+    /* now send the packet */
+    status = mvEthPortSgTx( priv->hal_priv, queue, pPktInfo);
+
+    /* check status */
+    if( status == MV_OK ) {
+        priv->tx_count[queue]++;
+        stats->tx_bytes += skb->len;
+        stats->tx_packets ++;
+        dev->trans_start = jiffies;
+        ETH_STAT_DBG( priv->eth_stat.tx_hal_ok[queue]++);
+    }
+    else {
+        /* tx failed. */
+
+        /* For single TX queue it must not happen because 
+         *   we stop call to netif_stop_queue in advance 
+         * For Multu TX queue config, free skb and continue without stopping. 
+         */
+        stats->tx_dropped++;
+
+        /* it must not happen because we call to netif_stop_queue in advance. */
+        ETH_DBG( ETH_DBG_TX, ("%s: TX queue=%d is full\n", dev->name, queue) );
+
+        /* we need to reuse this pPktInfo because TX failed */
+        dev_kfree_skb_any(skb);
+        pPktInfo->osInfo = 0;
+        mvStackPush(priv->txPktInfoPool, (MV_U32)pPktInfo);
+
+        ETH_STAT_DBG( priv->eth_stat.tx_hal_no_resource[queue]++);
+    }
+
+#if defined(ETH_INCLUDE_TSO) || defined(ETH_INCLUDE_UFO)
+tx_end:
+#endif
+
+#ifdef ETH_TX_DONE_ISR
+#else
+
+
+#ifdef ETH_MV_TX_EN
+        if(priv->tx_en)
+            eth_tx_enable(priv, queue);
+#endif /* ETH_MV_TX_EN */
+
+    if( priv->tx_count[queue] >= mv_eth_tx_done_quota)
+    {
+        tx_done_count = eth_tx_done(priv, queue);
+        priv->tx_count[queue] -= tx_done_count;
+    }
+#endif /* ETH_TX_DONE_ISR */ 
+
+#if (MV_ETH_TX_Q_NUM == 1)
+    /* if number of available descriptors left is less than  */
+    /* MAX_SKB_FRAGS stop the stack. if multi queue is used, */
+    /* don't stop the stack just because one queue is full.  */
+    if( mvEthTxResourceGet(priv->hal_priv, ETH_DEF_TXQ) <= MAX_SKB_FRAGS ) {
+        ETH_DBG( ETH_DBG_TX, ("%s: stopping network tx interface\n", dev->name) );
+        netif_stop_queue( dev );
+        ETH_STAT_ERR(priv->eth_stat.tx_netif_stop++);
+    }
+#endif /* (MV_ETH_TX_Q_NUM > 1) */
+
+    if (!tx_in_interrupt)
+	    spin_unlock_irqrestore(priv->lock, flags);	    
+    else
+        spin_unlock(priv->lock);
+
+    return ret;
+}
+
+/*********************************************************** 
+ * eth_tx_timeout --                                       *
+ *   nothing to be done (?)                                *
+ ***********************************************************/
+static void eth_tx_timeout( struct net_device *dev ) 
+{
+#ifdef CONFIG_MV_ETH_STATS_ERR
+    mv_eth_priv  *priv = MV_ETH_PRIV(dev);
+    
+    priv->eth_stat.tx_timeout++;
+#endif /* #ifdef CONFIG_MV_ETH_STATS_INFO */    
+
+    printk( KERN_INFO "%s: tx timeout\n", dev->name );
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+static const struct net_device_ops mv_eth_netdev_ops = {
+	.ndo_open		= mv_eth_open,
+	.ndo_stop		= mv_eth_stop,
+	.ndo_start_xmit		= eth_tx,
+	.ndo_set_multicast_list	= mv_eth_set_multicast_list,
+	.ndo_set_mac_address	= mv_eth_set_mac_addr,
+	.ndo_change_mtu		= mv_eth_change_mtu,
+	.ndo_tx_timeout		= eth_tx_timeout,
+};
+
+#ifdef CONFIG_MV_GATEWAY
+static const struct net_device_ops mv_eth_gtw_netdev_ops = {
+	.ndo_open		= mv_gtw_start,
+	.ndo_stop		= mv_gtw_stop,
+	.ndo_start_xmit		= eth_tx,
+	.ndo_set_multicast_list	= mv_gtw_set_multicast_list,
+	.ndo_set_mac_address	= mv_gtw_set_mac_addr,
+	.ndo_change_mtu		= mv_gtw_change_mtu,
+	.ndo_tx_timeout		= eth_tx_timeout,
+};
+#endif
+#endif
+
+/*********************************************************** 
+ * mv_netdev_init -- Allocate and initialize net_device    *
+ *                   structure                             *
+ ***********************************************************/
+struct net_device* __init mv_netdev_init(mv_eth_priv *priv, int mtu, u8* mac)
+{
+    struct net_device   *dev;
+    mv_net_priv         *net_priv;
+#if defined(CONFIG_MV_GATEWAY) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    static int 		once_flag = 0;
+#endif
+
+    dev = alloc_etherdev(sizeof(mv_net_priv));
+    if( !dev ) {
+        return NULL;
+    }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    net_priv = (mv_net_priv *)dev->priv;
+#else
+    net_priv = (mv_net_priv *)netdev_priv(dev);
+#endif
+    if( !net_priv ) { 
+        return NULL;
+    }
+    memset( net_priv , 0, sizeof(mv_net_priv) );
+    net_priv->giga_priv = priv;
+
+    dev->irq = ETH_PORT_IRQ_NUM(priv->port);
+    dev->mtu = mtu;
+    memcpy(dev->dev_addr, mac, 6);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    dev->weight = (CONFIG_MV_ETH_NUM_OF_RX_DESCR / 2);
+#endif
+    dev->tx_queue_len = CONFIG_MV_ETH_NUM_OF_TX_DESCR;
+    dev->watchdog_timeo = 5*HZ;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    dev->hard_start_xmit = eth_tx;
+    dev->tx_timeout = eth_tx_timeout;
+    dev->poll = eth_poll;
+
+    dev->open = mv_eth_open;
+    dev->stop = mv_eth_stop;
+    dev->set_mac_address = mv_eth_set_mac_addr;
+    dev->set_multicast_list = mv_eth_set_multicast_list;
+    dev->change_mtu = &mv_eth_change_mtu; 
+#else
+    dev->netdev_ops = &mv_eth_netdev_ops;
+#ifdef CONFIG_MV_GATEWAY
+    if (priv->isGtw)
+    {
+	if (once_flag == 0)
+	{
+		once_flag = 1;
+		netif_napi_add(dev, &priv->napi, eth_poll, CONFIG_MV_ETH_NUM_OF_RX_DESCR / 2);
+	}
+    }
+    else
+#endif /* CONFIG_MV_GATEWAY */
+    {
+	netif_napi_add(dev, &priv->napi, eth_poll, CONFIG_MV_ETH_NUM_OF_RX_DESCR / 2);
+    }
+#endif
+
+#ifdef CONFIG_MV_ETH_TOOL
+    SET_ETHTOOL_OPS(dev, &mv_eth_tool_ops);
+#endif
+
+#ifdef CONFIG_MV_GATEWAY
+    if(priv->isGtw)
+    {
+        /* For Gateway driver replace some of callback functions */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	dev->open = mv_gtw_start;
+	dev->stop = mv_gtw_stop;
+	dev->set_mac_address = mv_gtw_set_mac_addr;
+	dev->set_multicast_list = mv_gtw_set_multicast_list;
+	dev->change_mtu = &mv_gtw_change_mtu;
+#else
+	dev->netdev_ops = &mv_eth_gtw_netdev_ops;
+#endif
+        dev->hard_header_len += ETH_MV_HEADER_SIZE;
+    }
+#endif /* CONFIG_MV_GATEWAY */
+
+#ifdef ETH_LRO
+    if (!priv->lro_mgr.dev)
+	priv->lro_mgr.dev = dev;
+#endif
+
+    priv->timer.data = (unsigned long)dev;
+
+    mv_netdev_set_features(dev);
+
+    if (mv_plat_dev && (priv->port == 0)) {
+	printk("    o  register under %s platform\n", mv_plat_dev->name);
+	platform_set_drvdata(mv_plat_dev, dev);
+	SET_NETDEV_DEV(dev, &mv_plat_dev->dev);
+    }
+
+    if(register_netdev(dev)) {
+	printk(KERN_ERR "failed to register %s\n",dev->name);
+        free_netdev(dev);
+        return NULL;
+    }
+    else {
+	printk("    o %s, ifindex = %d, GbE port = %d\n",dev->name, dev->ifindex, priv->port);
+    }
+    return dev;
+}
+
+int     mv_eth_tos_map_set(int port, unsigned char tos, int queue)
+{
+    int             rc = 0;
+    mv_eth_priv     *priv = eth_priv_by_port(port);
+
+    if (priv == NULL)
+    {
+        printk("eth_status_print: wrong port number %d\n", port);
+	    return 1;
+    }
+#if defined(CONFIG_MV_GATEWAY)
+    if(priv->isGtw)
+    {
+        rc = mv_gtw_switch_tos_set(port, tos, queue);
+    }
+    else
+#endif /* CONFIG_MV_GATEWAY */
+    {
+        rc = mvEthTosToRxqSet(priv->hal_priv, tos, queue);
+    }
+    return rc;
+}
+
+void    mv_eth_tos_map_show(int port)
+{
+    unsigned int    tos;
+    int             queue;
+    mv_eth_priv     *priv = eth_priv_by_port(port);
+
+    if (priv == NULL)
+    {
+        printk("eth_status_print: wrong port number %d\n", port);
+	    return;
+    }
+    printk("ethPort_%d TOS Map: \n\n", port);
+
+    for(tos=0; tos<=0xFC; tos+=0x4) 
+    {
+#if defined(CONFIG_MV_GATEWAY)
+        if(priv->isGtw)
+        {
+            queue = mv_gtw_switch_tos_get(port, tos);
+        }
+        else
+#endif /* CONFIG_MV_GATEWAY */
+        {
+            queue = mvEthTosToRxqGet(priv->hal_priv, tos);
+        }
+	    if (queue != -1)
+        {
+		   printk("tos=0x%x: codepoint=0x%x, queue=%d\n", 
+                   tos, tos>>2, queue);
+        }
+	}
+}
+
+static void __init mv_eth_tos_map_init(int port)
+{
+    unsigned int    tos;
+
+    /* Set all codepoints to ETH_DEF_RXQ */
+    for(tos=0; tos<=0xFC; tos+=0x4) 
+    {
+        mv_eth_tos_map_set(port, tos, ETH_DEF_RXQ);
+    }
+
+#if (MV_ETH_RX_Q_NUM > 1)
+    for(tos=0; tos<=0xFC; tos+=0x4) 
+    {
+        int queue;
+
+        queue = mv_eth_tos_to_q_map(tos, MV_ETH_RX_Q_NUM);
+        mv_eth_tos_map_set(port, tos, queue);
+	}
+#endif /* MV_ETH_RX_Q_NUM > 1 */
+}
+
+/***********************************************************************************
+ ***  print net device status
+ ***********************************************************************************/
+void    mv_eth_netdev_print(unsigned int idx)
+{
+    struct net_device   *dev = eth_net_device_by_idx(idx);
+
+    printk("%s net_device status: dev=%p, priv=%p\n\n", 
+                dev->name, dev, MV_ETH_PRIV(dev));
+    printk("ifIdx=%d, features=0x%x, flags=0x%x, mtu=%u, size=%d\n", 
+            dev->ifindex, (unsigned int)(dev->features), (unsigned int)(dev->flags), 
+            dev->mtu, MV_RX_BUF_SIZE(dev->mtu));
+}
+
+
+/***********************************************************************************
+ ***  noqueue net device
+ ***********************************************************************************/
+extern struct Qdisc noop_qdisc;
+void mv_eth_set_noqueue(int idx, int enable)
+{
+    struct net_device *dev = eth_net_device_by_idx(idx);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+    if (dev->flags & IFF_UP) {
+            printk(KERN_ERR "%s: device or resource busy, take it down\n", dev->name);
+            return;
+    }
+    dev->tx_queue_len = enable ? 0 : CONFIG_MV_ETH_NUM_OF_TX_DESCR;
+
+    dev->qdisc_sleeping = &noop_qdisc;
+#else
+    struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+
+    if (dev->flags & IFF_UP) {
+            printk(KERN_ERR "%s: device or resource busy, take it down\n", dev->name);
+            return;
+    }
+    dev->tx_queue_len = enable ? 0 : CONFIG_MV_ETH_NUM_OF_TX_DESCR;
+
+    if (txq)
+    	txq->qdisc_sleeping = &noop_qdisc;
+    else
+	printk(KERN_ERR "%s: txq #0 is NULL\n", dev->name);
+#endif
+    printk(KERN_ERR "%s: device tx queue len is %d\n", dev->name, (int)dev->tx_queue_len);
+}
+
+/***********************************************************************************
+ ***  LRO configuration
+ ***********************************************************************************/
+void mv_eth_set_lro(int port, int enable)
+{
+#ifdef ETH_LRO
+	mv_eth_priv* priv = eth_priv_by_port(port);
+	if (priv)
+		priv->lro_en = enable;
+#endif		 
+}
+void mv_eth_set_lro_desc(int port, unsigned int value)
+{
+#ifdef ETH_LRO
+	mv_eth_priv* priv = eth_priv_by_port(port);
+
+	if (value > ETH_LRO_DESC) 
+		value = ETH_LRO_DESC;
+
+	if (priv) 
+        priv->lro_mgr.max_desc = value;
+#endif
+}
+/***********************************************************************************
+ ***  print Ethernet port status
+ ***********************************************************************************/
+void    mv_eth_status_print( unsigned int port )
+{
+    mv_eth_priv         *priv = eth_priv_by_port(port);
+
+    if (priv == NULL)
+    {
+        printk("eth_status_print: wrong port number %d\n", port);
+	    return;
+    }
+    printk("ethPort_%d Status: priv=%p\n\n", port, priv);
+
+    printk("tx_total=%d, rx_total=%d, tx_done_quota=%d\n\n", 
+            mv_eth_tx_desc_total, mv_eth_rx_desc_total, mv_eth_tx_done_quota);
+
+    printk("txPktInfoPool status:\n");
+    mvStackStatus(priv->txPktInfoPool, 0);
+    printk("\n");
+
+#ifdef ETH_MV_TX_EN
+    printk("TxEnable WA - %s. deep=%d, tx_en_bk=%d\n\n", 
+            priv->tx_en ? "Enabled" : "Disabled", 
+            priv->tx_en_deep, priv->tx_en_bk);    
+#endif /* ETH_MV_TX_EN */
+
+#ifdef CONFIG_MV_ETH_NFP
+    printk("NFP - %s.\n\n", fp_is_enabled() ? "Enabled" : "Disabled");
+#endif /* CONFIG_MV_ETH_NFP */
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+    printk("fpRxPool status:\n");
+    mvStackStatus(priv->fpRxPool, 0);
+    printk("\n");
+#endif /* CONFIG_MV_ETH_NFP | CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+    printk("SKB Reuse - %s. min skb size=%d, skbReusePool status:\n", 
+            eth_skb_reuse_enable ? "Enabled" : "Disabled",
+            SKB_DATA_ALIGN(MV_RX_BUF_SIZE(priv->net_dev->mtu) + 
+						   CPU_D_CACHE_LINE_SIZE + 8 + NET_SKB_PAD));
+    mvStackStatus(priv->skbReusePool, 0);
+    printk("\n");
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+    printk("SKB Recycle - %s, min skb size=%d, skbRecyclePool status:\n", 
+            eth_skb_recycle_enable ? "Enabled" : "Disabled",
+            priv->skbRecycleMTU);
+    mvStackStatus(priv->skbRecyclePool, 0);
+    printk("\n");
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+#ifdef ETH_LRO
+	{
+		int i = mv_net_devs_num;
+		struct net_device* dev;
+		u32 ipaddr;
+
+        	printk("LRO - %s, sessions=%d/%d\n", 
+		   priv->lro_en ? "Enabled" : "Disabled", 
+           	priv->lro_mgr.max_desc, ETH_LRO_DESC);
+
+		while (i--) {
+			dev = mv_net_devs[i];
+			if (dev && (priv == MV_ETH_PRIV(dev))) {
+				ipaddr = mv_eth_dev_ip(dev);
+				printk("LRO ip=%d.%d.%d.%d (%s)\n", 
+					   ipaddr & 0xff, (ipaddr >> 8) & 0xff,
+					   (ipaddr >> 16) & 0xff, ipaddr >> 24, dev->name);
+			}
+		}
+	}
+#endif /* ETH_LRO */
+}
+
+/***********************************************************************************
+ ***  print port statistics
+ ***********************************************************************************/
+#define   STAT_PER_Q(qnum,x) for(queue = 0; queue < qnum; queue++) \
+                printk("%10u ",x[queue]); \
+                    printk("\n");
+
+void mv_eth_stats_print( unsigned int port )
+{
+    mv_eth_priv         *priv = eth_priv_by_port(port);
+    eth_statistics      *stat = NULL;
+
+    TRC_OUTPUT();
+
+    if (priv == NULL)
+    {
+	printk("eth_stats_print: wrong port number %d\n", port);
+	return;
+    }
+    stat = &(priv->eth_stat);
+
+    printk( "\n====================================================\n" );
+    printk( "ethPort_%d: Errors", port);
+    printk( "\n-------------------------------\n" );
+    printk( "skb_alloc_fail................%10u\n", stat->skb_alloc_fail );
+    printk( "tx_timeout....................%10u\n", stat->tx_timeout );
+    printk( "tx_netif_stop.................%10u\n", stat->tx_netif_stop );
+    printk( "tx_done_netif_wake............%10u\n", stat->tx_done_netif_wake );
+    printk( "tx_skb_no_headroom............%10u\n", stat->tx_skb_no_headroom );
+
+#ifdef CONFIG_MV_ETH_STATS_INFO
+    printk( "\n====================================================\n" );
+    printk( "ethPort_%d: interrupt statistics", port );
+    printk( "\n-------------------------------\n" );
+    printk( "irq_total.....................%10u\n", stat->irq_total );
+    printk( "irq_none_events...............%10u\n", stat->irq_none );
+    printk( "irq_while_polling.............%10u\n", stat->irq_while_polling );
+    printk( "picr is.......................%10x\n", priv->picr);
+    printk( "picer is......................%10x\n", priv->picer);
+
+    printk( "\n====================================================\n" );
+    printk( "ethPort_%d: Events", port );
+    printk( "\n-------------------------------\n" );
+    printk( "poll_events...................%10u\n", stat->poll_events );
+    printk( "poll_complete.................%10u\n", stat->poll_complete );
+    printk( "tx_events.....................%10u\n", stat->tx_events );
+    printk( "tx_done_events................%10u\n", stat->tx_done_events );
+    printk( "timer_events..................%10u\n", stat->timer_events);
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+    printk( "rx_pool_empty.................%10u\n", stat->rx_pool_empty );
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_SKB_REUSE */
+
+#endif /* CONFIG_MV_ETH_STATS_INFO */
+
+#ifdef CONFIG_MV_ETH_STATS_DEBUG
+    {
+        unsigned int queue=0, i=0;
+
+        printk("\n");
+        printk("RXQs:.........................");
+        for(queue=0; queue<MV_ETH_RX_Q_NUM; queue++) 
+            printk( "%10d ", queue);
+        printk("\n");
+
+        printk( "rx_hal_ok....................."); STAT_PER_Q(MV_ETH_RX_Q_NUM, stat->rx_hal_ok);
+        printk( "rx_fill_ok...................."); STAT_PER_Q(MV_ETH_RX_Q_NUM, stat->rx_fill_ok);
+        printk("\n");
+
+        printk("TXQs:.........................");
+        for(queue=0; queue<MV_ETH_TX_Q_NUM; queue++) 
+            printk( "%10d ", queue);
+        printk("\n");
+        printk( "tx_count......................"); STAT_PER_Q(MV_ETH_TX_Q_NUM, priv->tx_count);
+        printk( "tx_hal_ok....................."); STAT_PER_Q(MV_ETH_TX_Q_NUM, stat->tx_hal_ok);
+        printk( "tx_hal_no_resource............"); STAT_PER_Q(MV_ETH_TX_Q_NUM, stat->tx_hal_no_resource );
+        printk( "tx_done_hal_ok................"); STAT_PER_Q(MV_ETH_TX_Q_NUM, stat->tx_done_hal_ok);
+        printk("\n");
+
+        printk( "skb_alloc_ok..................%10u\n", stat->skb_alloc_ok );
+        printk( "skb_free_ok...................%10u\n", stat->skb_free_ok );
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+        printk( "skb_reuse_rx..................%10u\n", stat->skb_reuse_rx);
+        printk( "skb_reuse_tx..................%10u\n", stat->skb_reuse_tx);
+        printk( "skb_reuse_alloc...............%10u\n", stat->skb_reuse_alloc);
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	printk("\n");
+        printk( "skb_recycle_put...............%10u\n", stat->skb_recycle_put);
+        printk( "skb_recycle_get...............%10u\n", stat->skb_recycle_get);
+	printk( "skb_recycle_full..............%10u\n", stat->skb_recycle_full);
+	printk( "skb_recycle_del...............%10u\n", stat->skb_recycle_del);
+	printk( "skb_recycle_rej...............%10u\n", stat->skb_recycle_rej);
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+        printk("\n");
+
+	printk( "tx_csum_hw....................%10u\n", stat->tx_csum_hw);
+	printk( "tx_csum_sw....................%10u\n", stat->tx_csum_sw);
+        printk("\n");
+
+        printk( "rx_netif_drop.................%10u\n", stat->rx_netif_drop );
+	printk( "rx_csum_hw....................%10u\n", stat->rx_csum_hw);
+	printk( "rx_csum_hw_frags..............%10u\n", stat->rx_csum_hw_frags);
+	printk( "rx_csum_sw....................%10u\n", stat->rx_csum_sw);
+
+#ifdef ETH_MV_TX_EN
+        printk( "\n");
+        printk( "tx_en_done....................%10u\n", stat->tx_en_done);
+        printk( "tx_en_busy....................%10u\n", stat->tx_en_busy);
+        printk( "tx_en_wait....................%10u\n", stat->tx_en_wait);
+        printk( "tx_en_wait_count..............%10u\n", stat->tx_en_wait_count);
+#endif /* ETH_MV_TX_EN */
+
+        printk("\n      Linux Path RX distribution\n");
+        for(i=0; i<sizeof(stat->rx_dist)/sizeof(u32); i++)
+        {
+            if(stat->rx_dist[i] != 0)
+                printk("%d RxPkts - %d times\n", i, stat->rx_dist[i]);
+        } 
+
+#ifdef ETH_INCLUDE_TSO
+        printk("\n      TSO stats\n");
+        for(i=0; i<64; i++)
+        {
+            if(stat->tso_stats[i] != 0)
+            {
+                printk("\t %d KBytes - %d times\n", i, stat->tso_stats[i]);
+                stat->tso_stats[i] = 0;
+            }
+        }
+#endif /* ETH_INCLUDE_TSO */
+
+#ifdef ETH_INCLUDE_UFO
+        printk("\n      UFO stats\n");
+        for(i=0; i<64; i++)
+        {
+	        if(stat->ufo_stats[i] != 0)
+	        {
+		        printk("\t %d KBytes - %d times\n", i, stat->ufo_stats[i]);
+		        stat->ufo_stats[i] = 0;
+	        }
+	    }
+#endif /* ETH_INCLUDE_UFO */
+
+        printk("\n      tx-done stats\n");
+        for(i=0; i<sizeof(stat->tx_done_dist)/sizeof(u32); i++)
+        {
+          if(stat->tx_done_dist[i] != 0)
+              printk("%d TxDonePkts - %d times\n", i, stat->tx_done_dist[i]);
+        } 
+    }
+#endif /* CONFIG_MV_ETH_STATS_DEBUG */
+
+#ifdef ETH_LRO
+        printk( "\n");
+	    printk( "rx_lro_aggregated.............%10u\n", (u32)priv->lro_mgr.stats.aggregated);
+	    printk( "rx_lro_flushed................%10u\n", (u32)priv->lro_mgr.stats.flushed);
+	    printk( "rx_lro_no_resources...........%10u\n", (u32)priv->lro_mgr.stats.no_desc);
+		memset(&priv->lro_mgr.stats, 0, sizeof(struct net_lro_stats));
+#endif /* ETH_LRO */
+
+		memset( stat, 0, sizeof(eth_statistics) );
+}
+
+#ifdef CONFIG_MV_ETH_NFP
+void     mv_eth_nfp_stats_print(unsigned int port)
+{
+    mv_eth_priv         *priv = eth_priv_by_port(port);
+
+    if (priv == NULL)
+    {
+        printk("eth_nfp_stats_print: wrong port number %d\n", port);
+	    return;
+    }
+
+    mvFpStatsPrint(&priv->fpStats);
+    printk("\n");
+    printk("NFP RX pool status:\n");
+    mvStackStatus(priv->fpRxPool, 0);
+}
+#endif /* CONFIG_MV_ETH_NFP */ 
+
+void eth_print_irq_status(mv_eth_priv *priv)
+{
+    printk("Interrupt Cause Register = 0x%08x (0x%08x)\n", 
+            priv->picr, MV_REG_READ(ETH_INTR_CAUSE_REG(priv->port)));
+
+    printk("Interrupt Mask Register = 0x%08x\n", 
+            MV_REG_READ(ETH_INTR_MASK_REG(priv->port)));
+
+    printk("Interrupt Cause Extend Register = 0x%08x (0x%08x)\n", 
+            priv->picer, MV_REG_READ(ETH_INTR_CAUSE_EXT_REG(priv->port)));
+
+    printk("Interrupt Mask Extend Register = 0x%08x\n", 
+            MV_REG_READ(ETH_INTR_MASK_EXT_REG(priv->port)));
+}
+
+void print_iph(struct iphdr* iph)
+{
+    printk("**************** IP Header: ver=%d, ihl=%d ******************\n", 
+            iph->version, iph->ihl);
+    printk("tot_len=%d, id=0x%x, proto=%d, csum=0x%x, sip=0x%x, dip=0x%x\n",
+            ntohs(iph->tot_len & 0xFFFF), ntohs(iph->id & 0xFFFF), iph->protocol & 0xFF, 
+            ntohs(iph->check & 0xFFFF), ntohl(iph->saddr), ntohl(iph->daddr));
+}
+
+void print_tcph(struct tcphdr* hdr)
+{
+    printk("################## TCP Header: doff=%d ####################\n", hdr->doff); 
+    printk("sPort=%d, dPort=%d, seqId=0x%x, ackId=0x%x, win=0x%x, csum=0x%x\n", 
+            ntohs(hdr->source), ntohs(hdr->dest), ntohl(hdr->seq), ntohl(hdr->ack_seq),
+            ntohs(hdr->window), ntohs(hdr->check) );
+    printk("Flags: fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d, ece=%d, cwr=%d\n", 
+            hdr->fin, hdr->syn, hdr->rst, hdr->psh, hdr->ack, hdr->urg, hdr->ece, hdr->cwr);
+}
+
+
+void print_skb(struct sk_buff* skb)
+{
+    int i;
+
+    printk("\nskb=%p: head=%p, data=%p, tail=%p, end=%p\n", 
+                skb, skb->head, skb->data, skb->tail, skb->end);
+    printk("\t users=%d, truesize=%d, len=%d, data_len=%d, mac_len=%d\n", 
+            atomic_read(&skb->users), skb->truesize, skb->len, skb->data_len, skb->mac_len);
+    printk("\t next=%p, prev=%p, csum=0x%x, ip_summed=%d, pkt_type=%d, proto=0x%x, cloned=%d\n",
+            skb->next, skb->prev, skb->csum, skb->ip_summed, skb->pkt_type, 
+            ntohs(skb->protocol & 0xFFFF), skb->cloned);
+    printk("\t mac=%p, nh=%p, h=%p\n", skb_mac_header(skb),  ip_hdr(skb), tcp_hdr(skb));
+    printk("\t dataref=0x%x, nr_frags=%d, gso_size=%d, tso_segs=%d, frag_list=%p\n",
+            atomic_read(&skb_shinfo(skb)->dataref), skb_shinfo(skb)->nr_frags, skb_shinfo(skb)->gso_size,
+            skb_shinfo(skb)->gso_segs, skb_shinfo(skb)->frag_list);
+    for(i=0; i<skb_shinfo(skb)->nr_frags; i++)
+    {
+        printk("\t frag_%d. page=%p, page_offset=0x%x, size=%d\n",
+            i, page_address(skb_shinfo(skb)->frags[i].page), 
+            skb_shinfo(skb)->frags[i].page_offset & 0xFFFF, 
+            skb_shinfo(skb)->frags[i].size & 0xFFFF);
+    }
+    if( (skb->protocol == ntohs(ETH_P_IP)) && (ip_hdr(skb) != NULL) )
+    {
+        print_iph(ip_hdr(skb));
+        if(ip_hdr(skb)->protocol == IPPROTO_TCP)
+            print_tcph(tcp_hdr(skb));
+    }
+    printk("\n");
+}
+
+/*********************************************************** 
+ * eth_init_module --                                    *
+ *   main driver initialization. loading the interfaces.   *
+ ***********************************************************/
+static int __init mv_eth_init_module( void ) 
+{
+    u32             i, port, netdev=0;
+    mv_eth_priv     *priv;
+    u8              mac_addr[6];
+    int             mtu;
+    int             rc;
+
+    rc = platform_driver_register(&mv_eth_driver);
+    if (rc) {
+	printk("can't register Marvell GbE platform driver, %d\n", rc);
+	return rc;
+    }
+
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+    /*if no ports assigned to this CPU, return*/
+    mv_eth_ports_num = mvCtrlEthMaxPortGet();
+#ifdef CONFIG_MV_ETH_PORTS_NUM
+    mv_eth_ports_num = min(mv_eth_ports_num, CONFIG_MV_ETH_PORTS_NUM); 
+#endif
+    for(port=0; port < mv_eth_ports_num; port++)
+    {
+	if (MV_TRUE == mvSocUnitIsMappedToThisCpu(GIGA0+port))
+	{
+		break;
+	}			
+    }
+    if (port == mv_eth_ports_num)
+    {    
+	printk("No Giga ports mapped to this CPU\n");
+	return 1;
+    }
+#endif
+    
+    printk( "Loading Marvell Ethernet Driver:\n");
+
+    /* Initialize mv_eth_rxq_desc array */
+    for(i=0; i<MV_ETH_RX_Q_NUM; i++) 
+    {
+        mv_eth_rxq_desc[i] = CONFIG_MV_ETH_NUM_OF_RX_DESCR;
+	    mv_eth_rx_desc_total += mv_eth_rxq_desc[i];
+    }
+    /* Initialize mv_eth_txq_desc array */
+    for(i=0; i<MV_ETH_TX_Q_NUM; i++) {
+        mv_eth_txq_desc[i] = CONFIG_MV_ETH_NUM_OF_TX_DESCR;
+
+        mv_eth_tx_desc_total += mv_eth_txq_desc[i];
+    }
+
+    spin_lock_init( &mii_lock );
+
+    /* init MAC Unit */
+    mvSysEthInit();
+
+    mv_eth_config_show();
+
+    mv_eth_ports_num = mvCtrlEthMaxPortGet();
+#ifdef CONFIG_MV_ETH_PORTS_NUM
+    if (CONFIG_MV_ETH_PORTS_NUM < mv_eth_ports_num)
+    {
+	    mv_eth_ports_num = CONFIG_MV_ETH_PORTS_NUM;
+    }
+#endif
+    mv_eth_ports = mvOsMalloc(mv_eth_ports_num*sizeof(mv_eth_priv*));
+    if(mv_eth_ports == NULL)
+    {
+        printk("eth_init_module: can't allocate mv_net_devs for %d devices\n", 
+                mv_eth_ports_num);
+        return 1; 
+    }
+    memset(mv_eth_ports, 0, (mv_eth_ports_num*sizeof(struct net_device*)));
+
+    mv_net_devs = mvOsMalloc((mv_eth_ports_num + GTW_MAX_NUM_OF_IFS)*sizeof(struct net_device*));
+    if(mv_net_devs == NULL)
+    {
+        printk("eth_init_module: can't allocate mv_net_devs for %d devices\n", 
+                mv_net_devs_num);
+        return 1; 
+    }
+    memset(mv_net_devs, 0, ((mv_eth_ports_num + GTW_MAX_NUM_OF_IFS) * sizeof(struct net_device*)));
+
+    printk("  o Loading network interface(s):\n");
+
+    for (port = 0; port < mv_eth_ports_num; port++)
+    {
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+	if (MV_FALSE == mvSocUnitIsMappedToThisCpu(GIGA0+port))
+	{
+		printk(KERN_INFO"GbE %d is not mapped to this CPU\n", port);
+		continue;
+	}		
+#endif
+	if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) 
+	{
+	    printk("\nWarning: Giga %d is Powered Off\n", port);
+	    continue;
+        }
+
+	/* we deal with gateway ports later */
+#if defined(CONFIG_MV_GATEWAY)
+	if (mvBoardIsSwitchConnected(port))
+		continue;
+#endif /* CONFIG_MV_GATEWAY */
+
+        /* Allocate mv_eth_priv structure */
+        priv = mvOsMalloc(sizeof(mv_eth_priv));
+        if(priv == NULL)
+        {
+            printk("GbE port %d: can't allocate mv_eth_priv structure\n", port);
+            return 1;
+        }
+        mv_eth_ports[port] = priv;
+
+        if( mv_eth_priv_init(priv, port) )
+        {
+            printk("GbE port %d: can't create mv_eth_priv structure\n", port);
+            mv_eth_priv_cleanup(priv);
+            return 1;
+        }
+#if defined(CONFIG_MV_GATEWAY)
+	priv->isGtw = mvBoardIsSwitchConnected(port);
+#endif /* CONFIG_MV_GATEWAY */
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+		mtu = eth_get_config(port, mac_addr);
+#else
+        mtu = eth_get_config(netdev, mac_addr);
+#endif
+        if( mv_eth_hal_init(priv, mtu, mac_addr) )
+        {
+            printk("eth_init_module: can't init eth_hal driver\n");
+            mv_eth_priv_cleanup(priv);
+            return 1;
+        }
+
+        mv_net_devs[netdev] = mv_netdev_init(priv, mtu, mac_addr);
+        if(mv_net_devs[netdev] == NULL)
+        {
+            printk("eth_init_module: can't create netdevice\n");
+            mv_eth_priv_cleanup(priv);
+            return 1;
+        }
+        priv->net_dev = mv_net_devs[netdev];
+        netdev++;
+
+	mv_eth_tos_map_init(port);        
+    }
+
+    /* now deal with gateway ports */
+    /* We initialize the Gateway interface last to maintain interface name ordering, */
+    /* e.g: the non-gateway interface will be named eth0 and the gateway interface will be eth1 */
+    /* Naming is done according to the order of initialization. */
+#if defined(CONFIG_MV_GATEWAY)
+    mv_gtw_dev_offset = netdev;
+    for (port = 0; port < mv_eth_ports_num; port++)
+    {
+	if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) 
+	{
+	    printk("\nWarning: Giga %d is Powered Off\n", port);
+	    continue;
+        }
+
+	/* disregard non-gateway ports */
+	if (!(mvBoardIsSwitchConnected(port)))
+		continue;
+
+        /* Allocate mv_eth_priv structure */
+        priv = mvOsMalloc(sizeof(mv_eth_priv));
+        if(priv == NULL)
+        {
+            printk("GbE port %d: can't allocate mv_eth_priv structure\n", port);
+            return 1;
+        }
+        mv_eth_ports[port] = priv;
+
+        if( mv_eth_priv_init(priv, port) )
+        {
+            printk("GbE port %d: can't create mv_eth_priv structure\n", port);
+            mv_eth_priv_cleanup(priv);
+            return 1;
+        }
+
+        priv->isGtw = mvBoardIsSwitchConnected(port);
+	printk("  o Loading Gateway interface(s):\n");
+        if( mv_gtw_net_setup(port) < 0)
+        {
+            printk("GbE port %d: mv_gtw_net_setup FAILED\n", port);
+            mv_eth_priv_cleanup(priv);
+            return 1;
+        }
+        if( mv_eth_hal_init(priv, gtw_config.mtu, NULL) )
+        {
+            printk("eth_init_module: can't init eth_hal driver\n");
+            mv_eth_priv_cleanup(priv);
+            return 1;
+        }
+        for(i=0; i<gtw_config.vlans_num; i++)
+        {
+            mv_net_devs[netdev] = mv_netdev_init(priv, gtw_config.mtu, gtw_config.vlan_cfg[i].macaddr);
+            if(mv_net_devs[netdev] == NULL)
+            {
+                printk("eth_init_module: can't create netdevice\n");
+                mv_eth_priv_cleanup(priv);
+                return 1;
+            }
+            priv->net_dev = mv_net_devs[netdev];
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+            ((mv_net_priv*)(mv_net_devs[netdev]->priv))->vlan_cfg = &gtw_config.vlan_cfg[i];
+#else
+            ((mv_net_priv*)(netdev_priv(mv_net_devs[netdev])))->vlan_cfg = &gtw_config.vlan_cfg[i];
+#endif
+            netdev++;
+        }
+
+	/* Note: must update mv_net_devs_num here before calling mv_gtw_init_complete */
+	/* because we might get a link interrupt from the switch and go over all net devices */
+	/* based on mv_net_devs_num */
+	mv_net_devs_num = netdev;
+
+        if (mv_gtw_init_complete(priv) != 0)
+	    return 1;
+
+	mv_eth_tos_map_init(port);
+    }
+#endif /* CONFIG_MV_GATEWAY */
+
+    /* Note: if we have gateway support we already updated mv_net_devs_num, but that's OK */
+    /* If we don't have gateway support, we need to update it here anyway. */
+    mv_net_devs_num = netdev;
+
+    printk("\n");
+
+#ifdef CONFIG_MV_ETH_NFP
+    {
+        MV_STATUS       status;
+
+        status = fp_mgr_init();
+        if (status != MV_OK) {
+            printk("fp_mgr_init failed\n");
+	        return 1;
+        }
+        spin_lock_init( &nfp_lock );
+	    for(i=0; i<mv_net_devs_num; i++) 
+        {
+		    if (mv_net_devs[i] != NULL) 
+            {
+			    status = fp_mgr_if_register(mv_net_devs[i]->ifindex, MV_FP_IF_INT, 
+                                            mv_net_devs[i]);
+			    if (status != MV_OK) {
+				    printk("fp_mgr_if_register failed\n");
+				    return 1;
+			    }
+		    }
+        }
+    }
+#endif /* CONFIG_MV_ETH_NFP */
+
+    TRC_INIT(0, 0, 0, 0);
+    TRC_START();
+
+#ifdef CONFIG_MV_CPU_PERF_CNTRS__ETH
+    /* 0 - instruction counters */
+    mvCpuCntrsProgram(0, MV_CPU_CNTRS_INSTRUCTIONS, "Instr", 25);
+
+    /* 1 - ICache misses counter */
+    mvCpuCntrsProgram(1, MV_CPU_CNTRS_ICACHE_READ_MISS, "IcMiss", 0);
+
+    /* 2 - cycles counter */
+    mvCpuCntrsProgram(2, MV_CPU_CNTRS_CYCLES, "Cycles", 21);
+
+    /* 3 - DCache read misses counter */
+    mvCpuCntrsProgram(3, MV_CPU_CNTRS_DCACHE_READ_MISS, "DcRdMiss", 0);
+    /*mvCpuCntrsProgram(3, MV_CPU_CNTRS_TLB_MISS, "TlbMiss", 0);*/
+
+    hal_rx_event = mvCpuCntrsEventCreate("HAL_RX", 10000);
+    empty_event = mvCpuCntrsEventCreate("EMPTY", 10000);
+    routing_event = mvCpuCntrsEventCreate("LINUX_ROUTING", 10000);
+    if( (empty_event == NULL) || (hal_rx_event == NULL) || (routing_event == NULL) )
+        printk("Can't create cpu counter events\n");
+#endif /* CONFIG_MV_CPU_PERF_CNTRS__ETH */
+    return 0;
+}
+
+static void __exit mv_eth_exit_module(void)
+{
+    printk( "EXIT Marvell Ethernet Driver\n");
+}
+
+
+ 
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_netdev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_netdev.h
new file mode 100755
index 0000000..185ba0b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/mv_netdev.h
@@ -0,0 +1,531 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+#include "mvOs.h"
+#include "mvDebug.h"
+#include "mvStack.h"
+#include "mvSysHwConfig.h"
+#include "eth/mvEth.h"
+#include "eth/gbe/mvEthGbe.h"
+#include "eth-phy/mvEthPhy.h"
+#include "mvSysEthApi.h"
+#include "dbg-trace.h"
+
+#if defined(CONFIG_MV_ETH_TSO)
+#   define ETH_INCLUDE_TSO
+#endif /* CONFIG_MV_ETH_TSO */
+
+#if defined(CONFIG_INET_LRO)
+  /* LRO support */
+#   include <linux/inet_lro.h>
+#   define ETH_LRO
+#   define ETH_LRO_DESC		64
+#endif /* CONFIG_INET_LRO */
+
+#if defined(CONFIG_MV_ETH_UFO)
+  /* UFO support */
+#   include <linux/udp.h>
+#   define ETH_INCLUDE_UFO
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP
+#   include "eth/nfp/mvNfp.h"
+#   include "../nfp_mgr/mv_nfp_mgr.h"
+#endif /* CONFIG_MV_ETH_NFP */
+
+#ifdef CONFIG_MV_ETH_TOOL
+#include "mv_eth_tool.h"
+#endif
+
+/****************************************************** 
+ * driver debug control --                            *
+ ******************************************************/
+/* debug main on/off switch (more in debug control below ) */
+#define ETH_DEBUG
+#undef ETH_DEBUG
+
+#define ETH_DBG_OFF     0x0000
+#define ETH_DBG_RX      0x0001
+#define ETH_DBG_TX      0x0002
+#define ETH_DBG_RX_FILL 0x0004
+#define ETH_DBG_TX_DONE 0x0008
+#define ETH_DBG_LOAD    0x0010
+#define ETH_DBG_IOCTL   0x0020
+#define ETH_DBG_INT     0x0040
+#define ETH_DBG_STATS   0x0080
+#define ETH_DBG_POLL    0x0100
+#define ETH_DBG_GSO		0x0200
+#define ETH_DBG_MCAST   0x0400
+#define ETH_DBG_VLAN    0x0800
+#define ETH_DBG_IGMP    0x1000
+#define ETH_DBG_ALL     0xffff
+
+#ifdef ETH_DEBUG
+extern u32 eth_dbg;
+# define ETH_DBG(FLG, X) if( (eth_dbg & (FLG)) == (FLG) ) printk X
+#else
+# define ETH_DBG(FLG, X)
+#endif
+
+
+/****************************************************** 
+ * driver statistics control --                       *
+ ******************************************************/
+/* statistics main on/off switch (more in statistics control below ) */
+
+#ifdef CONFIG_MV_ETH_STATS_ERROR
+# define ETH_STAT_ERR(CODE) CODE;
+#else
+# define ETH_STAT_ERR(CODE) 
+#endif /* CONFIG_MV_ETH_STATS_ERROR */ 
+
+#ifdef CONFIG_MV_ETH_STATS_INFO
+# define ETH_STAT_INFO(CODE) CODE;
+#else
+# define ETH_STAT_INFO(CODE)
+#endif /* CONFIG_MV_ETH_STATS_INFO */
+
+#ifdef CONFIG_MV_ETH_STATS_DEBUG
+# define ETH_STAT_DBG(CODE) CODE;
+#else
+# define ETH_STAT_DBG(CODE)
+#endif /* CONFIG_MV_ETH_STATS_DEBUG */
+
+/* rx buffer size */ 
+/* 2(HW hdr) + 4(VLAN) + 14(MAC hdr) + 4(CRC) */
+#define MV_WRAP             (2 + 4 + ETH_HLEN + 4)  
+
+#define MV_RX_BUF_SIZE(mtu) MV_ALIGN_UP(((mtu) + MV_WRAP), CPU_D_CACHE_LINE_SIZE)
+
+/* Interrupt Cause Masks */
+#define ETH_TXQ_MASK		(((1 << MV_ETH_TX_Q_NUM) - 1) << ETH_CAUSE_TX_BUF_OFFSET) 
+#define ETH_LINK_MASK		((1 << ETH_CAUSE_PHY_STATUS_CHANGE_BIT) | (1 << ETH_CAUSE_LINK_STATE_CHANGE_BIT))
+#define ETH_RXQ_MASK		(((1 << MV_ETH_RX_Q_NUM) - 1) << ETH_CAUSE_RX_READY_OFFSET)
+#define ETH_RXQ_RES_MASK	(((1 << MV_ETH_RX_Q_NUM) - 1) << ETH_CAUSE_RX_ERROR_OFFSET)
+
+/* Gigabit Ethernet Port Interrupt Mask and Port Interrupt Mask Extend Registers (PIMR and PIMER) */
+#define ETH_PICR_MASK		(BIT1  | ETH_RXQ_MASK | ETH_RXQ_RES_MASK)
+/* phy/link-status-change, tx-done-q0 - q7 */
+#define ETH_PICER_MASK		(ETH_LINK_MASK | ETH_TXQ_MASK) 
+
+
+#if defined(CONFIG_MV_GATEWAY)
+#define GTW_MAX_NUM_OF_IFS  5
+
+struct mv_vlan_cfg {
+    char            name[IFNAMSIZ];
+    unsigned int    ports_mask;
+    unsigned int    ports_link;
+    unsigned short  vlan_grp_id;
+    unsigned short  header;
+    unsigned char   macaddr[ETH_ALEN]; 
+};
+
+struct mv_gtw_config
+{
+    int                 vlans_num;
+    int                 mtu;
+    struct mv_vlan_cfg  vlan_cfg[GTW_MAX_NUM_OF_IFS];
+};
+
+extern struct mv_gtw_config    gtw_config;
+
+#else
+#define GTW_MAX_NUM_OF_IFS  0
+#endif /* CONFIG_MV_GATEWAY */
+
+typedef struct _eth_statistics
+{
+    /* erorrs */
+    u32 skb_alloc_fail;
+    u32 tx_timeout, tx_netif_stop;
+    u32 tx_done_netif_wake;
+    u32 tx_skb_no_headroom;
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+    u32 rx_pool_empty;
+#endif /* CONFIG_MV_ETH_NFP || CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_MV_ETH_STATS_INFO
+    /* Events */
+    u32 irq_total, irq_none, irq_while_polling;
+    u32 poll_events, poll_complete;
+    u32 tx_events;
+    u32 tx_done_events;
+    u32 timer_events;
+    u32 link_events;
+#endif /* CONFIG_MV_ETH_STATS_INFO */
+
+#ifdef CONFIG_MV_ETH_STATS_DEBUG
+    /* rx stats */
+    u32 rx_hal_ok[MV_ETH_RX_Q_NUM];
+    u32 rx_netif_drop;
+    u32 rx_dist[CONFIG_MV_ETH_NUM_OF_RX_DESCR+1];
+    u32 rx_csum_hw, rx_csum_hw_frags, rx_csum_sw;
+
+    /* skb stats */
+    u32 skb_alloc_ok, skb_free_ok;
+
+    /* rx-fill stats */
+    u32 rx_fill_ok[MV_ETH_RX_Q_NUM];
+
+    /* tx stats */
+    u32 tx_hal_ok[MV_ETH_TX_Q_NUM];
+    u32 tx_hal_no_resource[MV_ETH_TX_Q_NUM];
+    u32 tx_csum_hw, tx_csum_sw;
+    u32 tso_stats[64], ufo_stats[64];
+
+    /* tx-done stats */
+    u32 tx_done_hal_ok[MV_ETH_TX_Q_NUM];
+    u32 tx_done_dist[CONFIG_MV_ETH_NUM_OF_TX_DESCR*MV_ETH_TX_Q_NUM + 1];
+
+#ifdef ETH_MV_TX_EN
+    u32 tx_en_done, tx_en_wait, tx_en_wait_count, tx_en_busy;
+#endif /* ETH_MV_TX_EN */
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+    u32 skb_reuse_rx, skb_reuse_tx, skb_reuse_alloc;
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	u32 skb_recycle_put, skb_recycle_get, skb_recycle_full, skb_recycle_del, skb_recycle_rej;
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+#endif /* CONFIG_MV_ETH_STATS_DEBUG */
+
+} eth_statistics;
+
+typedef struct _mv_eth_priv
+{
+    int                 port;
+    void*               hal_priv;
+    spinlock_t*         lock;
+    eth_statistics      eth_stat;
+    u32                 picr;
+    u32                 picer;
+    MV_STACK*           txPktInfoPool;
+    int                 tx_count[MV_ETH_TX_Q_NUM];
+    struct timer_list   timer;
+    unsigned int        timer_flag;
+    unsigned int        skb_alloc_fail_cnt;
+    struct net_device   *net_dev;		/* back reference to the net_device */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    struct napi_struct  napi;
+#endif
+
+#if defined(ETH_INCLUDE_TSO) || defined(ETH_INCLUDE_UFO) || defined(CONFIG_MV_GATEWAY)
+#  define TX_EXTRA_BUF_SIZE     128
+
+    char**  tx_extra_bufs[MV_ETH_TX_Q_NUM]; 
+    int     tx_extra_buf_idx[MV_ETH_TX_Q_NUM];
+#endif /* ETH_INCLUDE_TSO || ETH_INCLUDE_UFO */
+
+#ifdef ETH_LRO
+    struct net_lro_mgr  lro_mgr;
+    struct net_lro_desc lro_desc[ETH_LRO_DESC];
+    unsigned int 	lro_en;	/* enable */
+#endif /* ETH_LRO */
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+    MV_STACK*       skbReusePool;
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	 MV_STACK*		skbRecyclePool;
+	 unsigned int	skbRecycleMTU;
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+#ifdef CONFIG_MV_ETH_NFP
+    MV_FP_STATS     fpStats;
+#endif /* CONFIG_MV_ETH_NFP */
+
+#if defined(CONFIG_MV_ETH_NFP) || defined(CONFIG_MV_ETH_SKB_REUSE)
+    unsigned int    refill_needed_flag;
+    MV_STACK*       fpRxPool;
+#endif /* (CONFIG_MV_ETH_NFP) || (CONFIG_MV_ETH_SKB_REUSE) */
+
+#if defined(CONFIG_MV_GATEWAY)
+    int             isGtw;
+#endif /* CONFIG_MV_GATEWAY */
+
+#ifdef ETH_MV_TX_EN
+    MV_BOOL         tx_en;
+    int             tx_en_deep;
+    MV_BOOL         tx_en_bk;
+#endif /* ETH_MV_TX_EN */
+#ifdef CONFIG_MV_ETH_TOOL
+    int		phy_id;
+    __u16	speed_cfg;
+    __u8	duplex_cfg;
+    __u8 	autoneg_cfg;
+    MV_U32	rx_coal_usec;
+    MV_U32	tx_coal_usec;
+#ifdef RX_CSUM_OFFLOAD
+    MV_U32	rx_csum_offload;
+#endif
+#endif /* CONFIG_MV_ETH_TOOL */
+} mv_eth_priv; 
+
+typedef struct _mv_priv 
+{
+    mv_eth_priv			*giga_priv;
+#ifdef CONFIG_MV_GATEWAY
+    struct mv_vlan_cfg		*vlan_cfg;	/* reference to entry in net config table */
+#endif
+
+} mv_net_priv;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#define MV_ETH_PRIV(dev)        (((mv_net_priv*)((dev)->priv))->giga_priv)
+#define MV_NETDEV_VLAN(dev)     (((mv_net_priv*)((dev)->priv))->vlan_cfg)
+#else
+#define MV_ETH_PRIV(dev)        (((mv_net_priv*)(netdev_priv(dev)))->giga_priv)
+#define MV_NETDEV_VLAN(dev)     (((mv_net_priv*)(netdev_priv(dev)))->vlan_cfg)
+#endif
+#define MV_NETDEV_STATS(dev)    (&((dev)->stats))
+#define MV_GTW_VLAN_TO_GROUP(vid)	((((vid) & 0xf00) >> 8)-1)
+
+extern int     mv_eth_rxq_desc[MV_ETH_RX_Q_NUM];
+extern int     mv_eth_txq_desc[MV_ETH_TX_Q_NUM];
+extern int     mv_eth_rx_desc_total;
+extern int     mv_eth_tx_desc_total;
+
+extern int      mv_eth_tx_done_quota;
+
+extern spinlock_t           mii_lock;
+extern spinlock_t           nfp_lock;
+
+extern struct net_device**  mv_net_devs;
+extern int                  mv_net_devs_num;
+
+extern mv_eth_priv**        mv_eth_ports;
+extern int                  mv_eth_ports_num;
+
+#ifdef CONFIG_MV_ETH_SKB_REUSE
+extern int eth_skb_reuse_enable;
+#endif /* CONFIG_MV_ETH_SKB_REUSE */
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+extern int eth_skb_recycle_enable;
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
+static INLINE int  mv_eth_tos_to_q_map(unsigned char tos, unsigned char num_of_queues)
+{
+    int  prio;
+
+    if(tos == 0)
+        return 0;
+
+    prio = (tos >> 5);
+    if(prio == 0)
+        return 1;
+
+    if(prio >= num_of_queues)
+        return (num_of_queues - 1);
+    
+    return prio;
+}
+
+static INLINE void mv_eth_save_interrupts(mv_eth_priv *priv)
+{
+    priv->picr |= MV_REG_READ(ETH_INTR_CAUSE_REG(priv->port)) & ETH_PICR_MASK;
+    if(priv->picr & BIT1) 
+    {
+	    priv->picer |= MV_REG_READ(ETH_INTR_CAUSE_EXT_REG(priv->port)) & ETH_PICER_MASK;
+    }
+}
+/**************************************************************************************************************/
+
+static INLINE void mv_eth_mask_interrupts(mv_eth_priv *priv)
+{
+    MV_REG_WRITE( ETH_INTR_MASK_REG(priv->port), 0 );
+    MV_REG_WRITE( ETH_INTR_MASK_EXT_REG(priv->port), 0 );
+}
+
+/**************************************************************************************************************/
+
+static INLINE void mv_eth_unmask_interrupts(mv_eth_priv *priv)
+{
+    /* unmask GbE Rx and Tx interrupts */
+    MV_REG_WRITE( ETH_INTR_MASK_REG(priv->port), ETH_PICR_MASK);
+#ifdef ETH_TX_DONE_ISR
+    MV_REG_WRITE( ETH_INTR_MASK_EXT_REG(priv->port), ETH_PICER_MASK); 
+#else
+    MV_REG_WRITE( ETH_INTR_MASK_EXT_REG(priv->port), ETH_LINK_MASK); 
+#endif /* ETH_TX_DONE_ISR */
+}
+/**************************************************************************************************************/
+
+static INLINE void mv_eth_clear_saved_interrupts(mv_eth_priv *priv)
+{
+    /* clear interrupts */
+    MV_REG_WRITE( ETH_INTR_CAUSE_REG(priv->port), ~(priv->picr));
+    /* clear Tx interrupts */
+    MV_REG_WRITE( ETH_INTR_CAUSE_EXT_REG(priv->port), ~(priv->picer));
+}
+/**************************************************************************************************************/
+
+static INLINE void mv_eth_clear_interrupts(mv_eth_priv *priv)
+{
+    /* clear interrupts */
+    MV_REG_WRITE( ETH_INTR_CAUSE_REG(priv->port), 0 );
+    /* clear Tx interrupts */
+    MV_REG_WRITE( ETH_INTR_CAUSE_EXT_REG(priv->port), 0 );
+}
+/**************************************************************************************************************/
+
+/* Function prototypes */
+
+#ifdef CONFIG_MV_GATEWAY
+extern int  mv_gtw_start(struct net_device *dev);
+extern int  mv_gtw_stop(struct net_device *dev);
+extern int  mv_gtw_change_mtu(struct net_device *dev, int mtu);
+extern int  mv_gtw_set_mac_addr( struct net_device *dev, void *mac );
+extern void mv_gtw_set_multicast_list(struct net_device *dev);
+
+extern int  __init mv_gtw_net_setup(int port);
+extern int __init mv_gtw_init_complete(mv_eth_priv* priv);
+
+extern int  mv_gtw_switch_tos_get(int port, unsigned char codepoint);
+extern int  mv_gtw_switch_tos_set(int port, unsigned char codepoint, int queue);
+
+extern void mv_gtw_switch_stats(int port);
+
+#ifdef CONFIG_MV_GTW_IGMP
+int mv_gtw_igmp_snoop_process(struct sk_buff* skb, unsigned char port, unsigned char vlan);
+#endif /* CONFIG_MV_GTW_IGMP */
+
+/* Note: this function currently supports only working with Marvell Header mode */
+extern int mv_gtw_dev_offset;
+static INLINE struct net_device *mv_gtw_ingress_dev(char* data)
+{
+	return mv_net_devs[(((data[0] & 0xF0) >> 4) + mv_gtw_dev_offset)];
+}
+
+static INLINE char mv_gtw_ingress_port(char* data)
+{
+    return data[1] & 0x0F;	
+}
+
+static INLINE char mv_gtw_ingress_vlan(char* data)
+{
+    return (data[0] & 0xF0) >> 4;
+}
+
+static INLINE void mv_gtw_update_tx_skb(struct net_device *dev, MV_PKT_INFO *pPktInfo)
+{
+	/* Note: this function currently supports only working with Marvell Header mode */
+	struct mv_vlan_cfg  *vlan_cfg = MV_NETDEV_VLAN(dev); 
+	struct sk_buff      *skb = (struct sk_buff *)pPktInfo->osInfo;
+	MV_BUF_INFO         *p_buf_info_first = pPktInfo->pFrags;
+	MV_BUF_INFO         *p_buf_info_last = (pPktInfo->pFrags + pPktInfo->numFrags - 1);
+
+	/* check if we have place inside skb for the header */
+	if(skb_headroom(skb) >= ETH_MV_HEADER_SIZE) {
+		*(unsigned short *)((skb->data)-ETH_MV_HEADER_SIZE) = vlan_cfg->header;
+		pPktInfo->pFrags[0].bufVirtPtr -= ETH_MV_HEADER_SIZE;
+		pPktInfo->pFrags[0].dataSize += ETH_MV_HEADER_SIZE;
+		pPktInfo->pktSize += ETH_MV_HEADER_SIZE;
+	}
+	else {
+#ifdef CONFIG_MV_ETH_STATS_ERR
+            mv_eth_priv *priv = MV_ETH_PRIV(dev);
+            priv->eth_stat.tx_skb_no_headroom++;
+#endif /* CONFIG_MV_ETH_STATS_ERR */
+
+		/* make room for one cell (safe because the array is big enough) */
+		do {
+	        	*(p_buf_info_last+1) = *p_buf_info_last;
+        		p_buf_info_last--;
+		} while(p_buf_info_last >= p_buf_info_first);
+
+		/* the header (safe on stack) */		
+		p_buf_info_first->bufVirtPtr = (void*)&vlan_cfg->header;
+		p_buf_info_first->dataSize = ETH_MV_HEADER_SIZE;
+
+		/* count the new frags */
+		pPktInfo->numFrags += 1;
+		pPktInfo->pktSize += ETH_MV_HEADER_SIZE;
+	}
+}
+#endif /* CONFIG_MV_GATEWAY */
+
+extern int  mv_eth_open(struct net_device *dev);
+extern int  mv_eth_start(struct net_device *dev);
+extern int  mv_eth_stop(struct net_device *dev);
+extern int  mv_eth_change_mtu(struct net_device *dev, int mtu);
+extern int  mv_eth_set_mac_addr( struct net_device *dev, void *mac );
+extern void mv_eth_set_multicast_list(struct net_device *dev);
+
+int __init                  mv_eth_hal_init(mv_eth_priv *priv, int mtu, u8* mac);
+int __init                  mv_eth_priv_init(mv_eth_priv *priv, int port);
+struct net_device* __init   mv_eth_netdev_init(mv_eth_priv *priv, int mtu, u8* mac);
+void __init                 mv_eth_priv_cleanup(mv_eth_priv *priv);
+
+void	            mv_eth_config_show(void);
+void                mv_eth_netdev_print(unsigned int idx);
+void                mv_eth_status_print( unsigned int port );
+void                mv_eth_stats_print( unsigned int port );
+void                mv_eth_set_noqueue(int port, int enable);
+void                mv_eth_set_lro(int port, int enable);
+void                mv_eth_set_lro_desc(int port, unsigned int value);
+
+MV_STATUS           mv_eth_rx_fill(mv_eth_priv *priv, int pool_size, int mtu);
+irqreturn_t         mv_eth_interrupt_handler(int irq , void *dev_id);
+int                 mv_eth_start_internals( mv_eth_priv *priv, int mtu );
+int                 mv_eth_stop_internals(mv_eth_priv *priv);
+int                 mv_eth_down_internals( struct net_device *dev );
+int                 mv_eth_change_mtu_internals( struct net_device *dev, int mtu );
+
+void                mv_eth_tos_map_show(int port);
+int                 mv_eth_tos_map_set(int port, unsigned char tos, int queue);
+
+void                print_skb(struct sk_buff* skb);
+
+#ifdef CONFIG_MV_ETH_NFP
+void                mv_eth_nfp_stats_print(unsigned int port);
+#endif /* CONFIG_MV_ETH_NFP */
+
+#ifdef ETH_MV_TX_EN
+void                eth_tx_en_config(int port, int value);
+#endif /* ETH_MV_TX_EN */
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_mgr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_mgr.c
new file mode 100755
index 0000000..316c9da
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_mgr.c
@@ -0,0 +1,2087 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+
+/*******************************************************************************
+* mv_nfp_mgr.c - Marvell Network Fast Processing Manager
+*
+* DESCRIPTION:
+*       
+*       Supported Features:
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvCommon.h"  /* Should be included before mvSysHwConfig */
+#include "mvTypes.h"
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <net/route.h>
+#include <linux/if_arp.h>
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+#include <net/netfilter/nf_nat.h>
+#endif
+
+#include "mvDebug.h"
+#include "mvOs.h"
+#include "mvSysHwConfig.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "eth/nfp/mvNfp.h"
+#include "mv_nfp_mgr.h"
+
+/* defines */
+#define FP_MAX_STR_SIZE		256
+#define AGING_TIMER_PERIOD	((CONFIG_MV_ETH_NFP_AGING_TIMER)*HZ) 
+
+#define MV_FTP_CTRL_PORT 21
+
+/* debug control */
+#define FP_MGR_DEBUG
+#undef FP_MGR_DEBUG
+
+#define FP_MGR_DBG_OFF		0x0000
+#define FP_MGR_DBG_INIT		0x0001
+#define FP_MGR_DBG_CLR		0x0002
+#define FP_MGR_DBG_ARP		0x0004
+#define FP_MGR_DBG_ROUTE	0x0008
+#define FP_MGR_DBG_NAT		0x0010
+#define FP_MGR_DBG_FDB		0x0020
+#define FP_MGR_DBG_PPP		0x0040
+#define FP_MGR_DBG_ALL		0xffff
+
+#ifdef FP_MGR_DEBUG 
+static unsigned int mv_fp_mgr_dbg = FP_MGR_DBG_ALL; 
+#define FP_MGR_DBG(FLG, X) if( (mv_fp_mgr_dbg & (FLG)) == (FLG) ) printk X
+#else
+#define FP_MGR_DBG(FLG, X)
+#endif
+
+#define MAX_MSG_SIZE		128 - 4	
+/* structure definitions */
+#ifdef CONFIG_MV_ETH_NFP_NAT
+#define MASQ_TARGET_NAME	"MASQUERADE"
+#define SNAT_TARGET_NAME	"SNAT"
+#define DNAT_TARGET_NAME	"DNAT"
+#define REDIRECT_TARGET_NAME	"REDIRECT"
+
+typedef struct _fp_iptables_nat_rule
+{
+	struct _fp_iptables_nat_rule *next;
+
+	/* Relevant target names are: */
+	/* SNAT, DNAT, MASQUERADE, REDIRECT */
+	char target_name[XT_FUNCTION_MAXNAMELEN-1];
+
+	/* Relevant for SNAT/DNAT: */
+	__be32 sip, dip, smsk, dmsk;
+
+	char iniface[IFNAMSIZ], outiface[IFNAMSIZ];	
+
+	/* Protocol, 0 = ANY */
+	u_int16_t proto;
+
+} FP_IPTABLES_NAT_RULE;
+
+typedef struct _fp_user_nat_table 
+{
+	FP_IPTABLES_NAT_RULE *rule_chain;
+} FP_USER_NAT_TABLE;
+struct nat_rule_db {
+	MV_FP_NAT_RULE *rule_chain;
+	u32 max_size;
+};
+
+static struct nat_rule_db   mgr_nat_rule_db;
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+typedef struct _mv_fp_arp_rule {
+	struct _mv_fp_arp_rule *next;
+
+	int     if_index;
+	u32     ip;
+	u8      mac[MV_MAC_ADDR_SIZE];
+	int     confirmed;
+
+} MV_FP_ARP_RULE; 
+
+struct rule_db {
+	MV_FP_RULE  *rule_chain;
+	u32         max_size;
+};
+
+struct arp_rule_db {
+	MV_FP_ARP_RULE *rule_chain;
+	u32 max_size;
+};
+
+/* global variables */
+static struct rule_db       mgr_rule_db;
+static struct arp_rule_db   mgr_arp_rule_db;
+static struct timer_list    aging_timer;
+static spinlock_t	        nfp_mgr_lock;
+
+int                         fp_disable_flag = 1;
+struct map_eth_devs         *fp_eth_devs = NULL;
+#ifdef CONFIG_MV_ETH_NFP_FDB
+
+struct fdb_rule_db {
+	MV_FP_FDB_RULE *rule_chain;
+	u32 max_size;	
+};
+static struct fdb_rule_db   mgr_fdb_rule_db;
+
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+/* we have two tables: previous and current */
+static FP_USER_NAT_TABLE    fp_user_nat_table[2];	
+/* user NAT table: 0 or 1 */
+int                         curr_table, old_table;			
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+int mgr_to_fp_chan, fp_to_mgr_chan;
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+static void fp_arp_rule_print(const MV_FP_ARP_RULE *rule);
+#ifdef CONFIG_MV_ETH_NFP_NAT
+static int fp_nat_db_clear_and_update(void);
+#endif
+
+
+static void __exit fp_exit_module(void)
+{
+	fp_rule_db_clear();
+	fp_arp_db_clear();
+
+	if (fp_eth_devs != NULL)
+		kfree(fp_eth_devs);
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_RULE_DB_DESTROY_OPCODE, NULL, 0);
+#else
+	mvFpRuleDbDestroy();
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+    fp_nat_db_clear();
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_NAT_DB_DESTROY_OPCODE, NULL, 0);
+#else
+	mvFpNatDbDestroy();	
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+	fp_fdb_db_clear();
+	mvFpFdbDestroy();
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+}
+
+static int is_valid_index(int if_index)
+{
+	if( (if_index < 0) || (if_index >= ETH_FP_IFINDEX_MAX) )
+	{
+		/*printk("if_index %d is OUT of RANGE\n", if_index);*/
+		return 0;
+	}
+    	if( (fp_eth_devs == NULL) || 
+	    (fp_eth_devs[if_index].if_type == MV_FP_IF_INV) )
+		return 0;
+
+	return 1;
+}
+
+/* helper functions */
+struct net_device *mv_dev_get_by_name(const char *name)
+{
+	/* TODO: may need to take a semaphore here, see documentation of __dev_get_by_name */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	return __dev_get_by_name(name); 
+#else
+	return __dev_get_by_name(&init_net, name);
+#endif
+}
+
+struct net_device *mv_dev_get_by_index(int ifindex)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	return __dev_get_by_index(ifindex);
+#else
+	return __dev_get_by_index(&init_net, ifindex);
+#endif
+}
+
+/* Find and return the first matching rule in the ARP Database */
+static MV_FP_ARP_RULE* fp_arp_rule_find(u32 ip)
+{
+	MV_FP_ARP_RULE  *curr_rule;
+
+	for (curr_rule = mgr_arp_rule_db.rule_chain; curr_rule != NULL; curr_rule = curr_rule->next) {
+		if (curr_rule->ip == ip) {
+			return curr_rule;
+		}
+	}
+	return NULL;
+}
+
+static MV_FP_RULE* fp_rule_find(u32 sip, u32 dip)
+{
+	MV_FP_RULE      *curr_rule;
+
+	for (curr_rule = mgr_rule_db.rule_chain; curr_rule != NULL; curr_rule = curr_rule->next) {
+		if(	(curr_rule->routingInfo.srcIp == sip) && 
+			(curr_rule->routingInfo.dstIp == dip) ) {
+				return curr_rule;
+		}
+	}
+	return NULL;
+}
+
+static int ip_in_same_network(u32 ip1, u32 ip2, u32 mask)
+{
+	if ((mask != 0) && ((ip1 & mask) == (ip2 & mask)))
+		return 1;
+	return 0;
+}
+
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+
+static MV_FP_NAT_RULE* fp_nat_rule_find(u32 sip, u32 dip, u16 sport, u16 dport, u8 proto) 
+{
+	MV_FP_NAT_RULE  *curr_rule;
+
+	for (curr_rule = mgr_nat_rule_db.rule_chain; curr_rule != NULL; curr_rule = curr_rule->next) {
+		if (	curr_rule->srcIp == sip && 
+			curr_rule->dstIp == dip && 
+			curr_rule->srcPort == sport && 
+			curr_rule->dstPort == dport && 
+			curr_rule->proto == proto) {
+				return curr_rule;
+		}
+	}
+	return NULL;
+}
+
+/* Update NFP Rule "NAT awareness" according to the given iptables rule */
+static void update_awareness(FP_IPTABLES_NAT_RULE *nat_rule, MV_FP_RULE *fp_rule, int add_del_flag)
+{
+	int                 in_dev_ifindex = -1, out_dev_ifindex = -1;
+	struct net_device   *dev;
+	int                 inport_avail = 0, outport_avail = 0;	
+
+	if (!strcmp(nat_rule->target_name, MASQ_TARGET_NAME) || !strcmp(nat_rule->target_name, SNAT_TARGET_NAME)) {
+		if ((nat_rule->outiface != NULL) && strcmp(nat_rule->outiface, "")) {
+			dev = mv_dev_get_by_name(nat_rule->outiface);
+			if (dev)
+				out_dev_ifindex = dev->ifindex;
+		
+			if (is_valid_index(out_dev_ifindex)) {
+				outport_avail = 1;
+			}
+		}
+	}
+	else if (!strcmp(nat_rule->target_name, REDIRECT_TARGET_NAME) || !strcmp(nat_rule->target_name, DNAT_TARGET_NAME)) {
+		if ((nat_rule->iniface != NULL) && strcmp(nat_rule->iniface, "")) {
+			dev = mv_dev_get_by_name(nat_rule->iniface);
+			if (dev)
+				in_dev_ifindex = dev->ifindex;
+		
+			if (is_valid_index(in_dev_ifindex)) {
+				inport_avail = 1;
+			}
+		}
+	}
+
+	if (!strcmp(nat_rule->target_name, MASQ_TARGET_NAME) || !strcmp(nat_rule->target_name, SNAT_TARGET_NAME)) {
+		if (	(ip_in_same_network(fp_rule->routingInfo.srcIp, nat_rule->sip, nat_rule->smsk)) || 
+			(outport_avail && fp_rule->routingInfo.outIfIndex == out_dev_ifindex) ) {
+			/* update SNAT awareness */
+			if (add_del_flag) {
+				FP_MGR_DBG(FP_MGR_DBG_NAT, ("adding snat awareness\n"));
+				fp_rule->mgmtInfo.snat_aware_refcnt++;
+				fp_rule->routingInfo.aware_flags |= MV_FP_SNAT_CMD_MAP;
+			}
+			else {
+				fp_rule->mgmtInfo.snat_aware_refcnt--;
+				if (fp_rule->mgmtInfo.snat_aware_refcnt == 0) {
+					FP_MGR_DBG(FP_MGR_DBG_NAT, ("deleting snat awareness\n"));
+					fp_rule->routingInfo.aware_flags &= ~MV_FP_SNAT_CMD_MAP;	
+				}
+			}
+		}
+		if (outport_avail && fp_rule->routingInfo.inIfIndex == out_dev_ifindex) {
+			/* update DNAT awareness, because this is the reverse direction of the SNAT */
+			if (add_del_flag) {
+				FP_MGR_DBG(FP_MGR_DBG_NAT, ("adding dnat awareness\n"));
+				fp_rule->mgmtInfo.dnat_aware_refcnt++;
+				fp_rule->routingInfo.aware_flags |= MV_FP_DNAT_CMD_MAP;
+			}
+			else {
+				fp_rule->mgmtInfo.dnat_aware_refcnt--;
+				if (fp_rule->mgmtInfo.dnat_aware_refcnt == 0) {
+					FP_MGR_DBG(FP_MGR_DBG_NAT, ("deleting dnat awareness\n"));
+					fp_rule->routingInfo.aware_flags &= ~MV_FP_DNAT_CMD_MAP;
+				}	
+			}
+		}
+	}
+	else if (!strcmp(nat_rule->target_name, REDIRECT_TARGET_NAME) || !strcmp(nat_rule->target_name, DNAT_TARGET_NAME)) {
+		if (	(ip_in_same_network(fp_rule->routingInfo.dstIp, nat_rule->dip, nat_rule->dmsk)) || 
+			(inport_avail && fp_rule->routingInfo.inIfIndex == in_dev_ifindex) ) {
+			/* update DNAT awareness */
+			if (add_del_flag) {
+				FP_MGR_DBG(FP_MGR_DBG_NAT, ("adding dnat awareness\n"));
+				fp_rule->mgmtInfo.dnat_aware_refcnt++;
+				fp_rule->routingInfo.aware_flags |= MV_FP_DNAT_CMD_MAP;
+			}
+			else {
+				fp_rule->mgmtInfo.dnat_aware_refcnt--;
+				if (fp_rule->mgmtInfo.dnat_aware_refcnt == 0) {
+					FP_MGR_DBG(FP_MGR_DBG_NAT, ("deleting dnat awareness\n"));
+					fp_rule->routingInfo.aware_flags &= ~MV_FP_DNAT_CMD_MAP;
+				}
+			}
+		}
+		if (inport_avail && fp_rule->routingInfo.outIfIndex == in_dev_ifindex) {
+			/* update SNAT awareness, because this is the reverse direction of the DNAT */
+			if (add_del_flag) {
+				FP_MGR_DBG(FP_MGR_DBG_NAT, ("adding snat awareness\n"));
+				fp_rule->mgmtInfo.snat_aware_refcnt++;
+				fp_rule->routingInfo.aware_flags |= MV_FP_SNAT_CMD_MAP;
+			}
+			else {
+				fp_rule->mgmtInfo.snat_aware_refcnt--;
+				if (fp_rule->mgmtInfo.snat_aware_refcnt == 0) {
+					FP_MGR_DBG(FP_MGR_DBG_NAT, ("deleting snat awareness\n"));
+					fp_rule->routingInfo.aware_flags &= ~MV_FP_SNAT_CMD_MAP;
+				}
+			}
+		}
+	}
+}
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+/* When setting a rule, check if it needs to be aware of any currently existing user NAT rules */
+static void fp_new_rule_awareness(MV_FP_RULE *rule)
+{
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	FP_IPTABLES_NAT_RULE *nat_rule;
+#endif
+	rule->mgmtInfo.snat_aware_refcnt = 0;
+	rule->mgmtInfo.dnat_aware_refcnt = 0;
+	rule->routingInfo.aware_flags = 0;
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	nat_rule = fp_user_nat_table[1-curr_table].rule_chain;
+	while (nat_rule != NULL) {
+		update_awareness(nat_rule, rule, 1);
+		nat_rule = nat_rule->next;
+	}
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+}
+
+/* Clear all NFP databases and update them with the contents of */
+/* the NFP Manager databases. */
+static int fp_db_clear_and_update(void)
+{
+	int status = 0;
+	unsigned long flags;
+	MV_FP_RULE *curr_rule;
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_RULE_DB_CLEAR_OPCODE, NULL, 0);
+#else
+	status = mvFpRuleDbClear();
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	curr_rule = mgr_rule_db.rule_chain;
+	while (curr_rule != NULL) { 
+		if (!is_zero_ether_addr(curr_rule->routingInfo.dstMac)) {
+			fp_new_rule_awareness(curr_rule);
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+			status |= mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+							MV_FP_RULE_SET_OPCODE, curr_rule, sizeof(MV_FP_RULE));
+#else
+			status |= mvFpRuleSet(curr_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+		}
+		curr_rule = curr_rule->next;
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return status;
+}
+
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+static void aging_timer_function(unsigned long data)
+{
+	unsigned long       flags;
+	MV_FP_ARP_RULE      *curr_arp_rule;
+	MV_FP_RULE          *curr_rule;
+	int                 rule_index = 0;
+	ARP_RULE_AGING_MSG  arp_rule_aging_msg;
+	RULE_AGING_MSG      rule_aging_msg;
+	NAT_RULE_AGING_MSG nat_rule_aging_msg;
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	MV_FP_NAT_RULE  *curr_nat_rule;
+#endif
+	static int          current_arp_rule_position = 0;
+	static int          current_rule_position = 0;
+	static int          current_nat_rule_position = 0;
+
+
+	/* Collect ARP information from DB */
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+
+	/* move pointer to rule to the next group of rules we want to handle */
+	for (	curr_arp_rule = mgr_arp_rule_db.rule_chain, rule_index = 0; 
+		(curr_arp_rule != NULL) && (rule_index < (current_arp_rule_position*AGING_QUANTUM)); 
+		curr_arp_rule = curr_arp_rule->next, rule_index++);
+
+	rule_index = 0;
+	memset(&arp_rule_aging_msg, 0, sizeof(ARP_RULE_AGING_MSG));
+	while ((curr_arp_rule != NULL) && (rule_index < AGING_QUANTUM)) {
+		arp_rule_aging_msg.num_tuples++;
+		arp_rule_aging_msg.info[rule_index].ip = curr_arp_rule->ip;
+		curr_arp_rule = curr_arp_rule->next;
+		rule_index++;
+	}
+	current_arp_rule_position++;
+	if( (curr_arp_rule == NULL) || 
+        ((current_arp_rule_position*AGING_QUANTUM) >= mgr_arp_rule_db.max_size))
+		current_arp_rule_position = 0; 
+
+	mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+				MV_FP_MAX_ARP_COUNT_GET_OPCODE, &arp_rule_aging_msg, sizeof(arp_rule_aging_msg));
+
+	/* Collect routing information from DB */	
+
+	/* move pointer to rule to the next group of rules we want to handle */
+	for (	curr_rule = mgr_rule_db.rule_chain, rule_index = 0; 
+		(curr_rule != NULL) && (rule_index < (current_rule_position*AGING_QUANTUM)); 
+		curr_rule = curr_rule->next, rule_index++);
+
+	rule_index = 0;
+	memset(&rule_aging_msg, 0, sizeof(RULE_AGING_MSG));
+
+	while ((curr_rule != NULL) && (rule_index < AGING_QUANTUM)) {
+		rule_aging_msg.num_tuples++;
+		rule_aging_msg.info[rule_index].sip = curr_rule->routingInfo.srcIp;
+		rule_aging_msg.info[rule_index].dip = curr_rule->routingInfo.dstIp;
+		curr_rule = curr_rule->next;
+		rule_index++;
+	}
+	current_rule_position++;
+	if ((curr_rule == NULL) || ((current_rule_position*AGING_QUANTUM) >= mgr_rule_db.max_size))
+		current_rule_position = 0; 
+	mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+				MV_FP_ROUTE_COUNT_GET_OPCODE, &rule_aging_msg, sizeof(rule_aging_msg));
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	/* Collect NAT information from DB */
+
+	/* move pointer to rule to the next group of rules we want to handle */
+	for (	curr_nat_rule = mgr_nat_rule_db.rule_chain, rule_index = 0; 
+		(curr_nat_rule != NULL) && (rule_index < (current_nat_rule_position*AGING_QUANTUM)); 
+		curr_nat_rule = curr_nat_rule->next, rule_index++);
+
+	rule_index = 0;
+	memset(&nat_rule_aging_msg, 0, sizeof(NAT_RULE_AGING_MSG));
+
+	while ((curr_nat_rule != NULL) && (rule_index < AGING_QUANTUM)) {
+		nat_rule_aging_msg.num_tuples++;
+		nat_rule_aging_msg.info[rule_index].sip = curr_nat_rule->srcIp;
+		nat_rule_aging_msg.info[rule_index].dip = curr_nat_rule->dstIp;
+		nat_rule_aging_msg.info[rule_index].sport = curr_nat_rule->srcPort;
+		nat_rule_aging_msg.info[rule_index].dport = curr_nat_rule->dstPort;
+		nat_rule_aging_msg.info[rule_index].proto = curr_nat_rule->proto;
+		curr_nat_rule = curr_nat_rule->next;
+		rule_index++;
+	}
+
+	current_nat_rule_position++;
+	if( (curr_nat_rule == NULL) || 
+        	( (current_nat_rule_position*AGING_QUANTUM) >= mgr_nat_rule_db.max_size) )
+			current_nat_rule_position = 0; 
+
+	mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+				MV_FP_NAT_COUNT_GET_OPCODE, &nat_rule_aging_msg, sizeof(nat_rule_aging_msg));
+
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+  	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	aging_timer.expires = jiffies + AGING_TIMER_PERIOD;
+    	add_timer(&aging_timer);
+}
+
+#else /* not CONFIG_MV_ETH_NFP_DUAL */
+
+static void aging_timer_function(unsigned long data)
+{
+	unsigned long   flags;
+	MV_FP_ARP_RULE  *curr_arp_rule;
+	MV_FP_RULE      *curr_rule;
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	MV_FP_NAT_RULE  *curr_nat_rule;
+#endif
+
+    	spin_lock_irqsave(&nfp_mgr_lock, flags);
+
+	/* Collect routing information from DB */	
+	curr_rule = mgr_rule_db.rule_chain;
+	while (curr_rule != NULL) 
+    	{
+		curr_rule->mgmtInfo.new_count = mvFpRouteCountGet(curr_rule->routingInfo.srcIp, 
+						                                  curr_rule->routingInfo.dstIp);
+        	if(curr_rule->mgmtInfo.new_count != curr_rule->mgmtInfo.old_count)
+        	{
+            		/* Lookup ARP entry to confirm */
+            		curr_arp_rule = fp_arp_rule_find(curr_rule->routingInfo.srcIp);
+            		if(curr_arp_rule != NULL)
+            		{
+                		/* ARP Entry Found - confirmed */
+                		curr_arp_rule->confirmed = 1;
+            		}
+            		else
+            		{
+                		/* ARP Entry Not Found - Confirm default gateway for incoming interface */
+                		curr_arp_rule = fp_arp_rule_find(fp_eth_devs[curr_rule->routingInfo.inIfIndex].def_gtw_ip);
+                		if(curr_arp_rule != NULL)
+                		{
+                    			curr_arp_rule->confirmed = 1;
+                		}       		
+            		}
+        	}
+		curr_rule = curr_rule->next;
+	}
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	/* Collect NAT information from DB */
+	curr_nat_rule = mgr_nat_rule_db.rule_chain;
+	while (curr_nat_rule != NULL) 
+    	{
+		curr_nat_rule->new_count = mvFpNatCountGet(curr_nat_rule->srcIp, 
+						                           curr_nat_rule->dstIp, 
+						                           curr_nat_rule->srcPort, 
+						                           curr_nat_rule->dstPort, 
+						                           curr_nat_rule->proto);
+		curr_nat_rule = curr_nat_rule->next;
+	}
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	aging_timer.expires = jiffies + AGING_TIMER_PERIOD;
+   	add_timer(&aging_timer);
+}
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+/* Return ARP rule confirmation status */
+int fp_is_arp_confirmed(u32 ip, const u8 *mac)
+{
+	unsigned long   flags;
+	MV_FP_ARP_RULE  *curr_rule;
+    	int             confirmed;
+
+	if (fp_disable_flag == 1)
+		return 0;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	curr_rule = mgr_arp_rule_db.rule_chain;
+	while (curr_rule != NULL) {
+		if( (curr_rule->ip == ip) && (memcmp(curr_rule->mac, mac, MV_MAC_ADDR_SIZE) == 0) ) 
+        	{
+            		confirmed = curr_rule->confirmed;
+            		curr_rule->confirmed = 0;
+			spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+			return confirmed;
+		}
+		curr_rule = curr_rule->next;
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return 0;
+}
+
+/* Return routing rule confirmation status */
+int fp_is_route_confirmed(u32 src_ip, u32 dst_ip, int iif, int oif)
+{
+	unsigned long   flags;
+	MV_FP_RULE      *curr_rule;
+    	int             confirmed = 0;
+
+	if (fp_disable_flag == 1)
+		return 0;
+
+        if( !is_valid_index(iif) || !is_valid_index(oif) )
+                return 0;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	curr_rule = mgr_rule_db.rule_chain;
+	while (curr_rule != NULL) {
+		if( (curr_rule->routingInfo.srcIp == src_ip) && 
+			(curr_rule->routingInfo.dstIp == dst_ip) ) 
+        	{
+            		if(curr_rule->mgmtInfo.new_count != curr_rule->mgmtInfo.old_count)
+            		{
+                		confirmed = 1;
+                		curr_rule->mgmtInfo.old_count = curr_rule->mgmtInfo.new_count;
+            		}
+			spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+			return confirmed;
+		}
+		curr_rule = curr_rule->next;
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+void fp_rcv_info_msg(int from_cpu, u16 opcode, void* p_msg, u8 size)
+{
+	int                 i = 0;
+	ARP_RULE_AGING_MSG  *arp_rule_aging_msg;
+	RULE_AGING_MSG      *rule_aging_msg;
+	NAT_RULE_AGING_MSG  *nat_rule_aging_msg;
+	MV_FP_ARP_RULE      *curr_arp_rule;
+	MV_FP_RULE          *curr_rule;
+	MV_FP_NAT_RULE      *curr_nat_rule;
+
+	switch(opcode)
+	{
+		case MV_FP_MAX_ARP_COUNT_REPLY_OPCODE:
+			arp_rule_aging_msg = (ARP_RULE_AGING_MSG *)p_msg;
+			for (i = 0; i < arp_rule_aging_msg->num_tuples; i++) {
+				curr_arp_rule = fp_arp_rule_find(arp_rule_aging_msg->info[i].ip);
+				if (curr_arp_rule != NULL)
+					fp_update_arp_rule_aging(curr_arp_rule, arp_rule_aging_msg->info[i].count);
+			}
+			break;
+		case MV_FP_ROUTE_COUNT_REPLY_OPCODE:
+			rule_aging_msg = (RULE_AGING_MSG *)p_msg;
+			for (i = 0; i < rule_aging_msg->num_tuples; i++) {
+				curr_rule = fp_rule_find(rule_aging_msg->info[i].sip, 
+							rule_aging_msg->info[i].dip);
+				if (curr_rule != NULL) 
+					fp_update_rule_aging(curr_rule, rule_aging_msg->info[i].count);
+			}
+			break;
+		case MV_FP_NAT_COUNT_REPLY_OPCODE:
+			nat_rule_aging_msg = (NAT_RULE_AGING_MSG *)p_msg;
+			for (i = 0; i < nat_rule_aging_msg->num_tuples; i++) {
+				curr_nat_rule = fp_nat_rule_find(nat_rule_aging_msg->info[i].sip, 
+								nat_rule_aging_msg->info[i].dip, 
+								nat_rule_aging_msg->info[i].sport, 
+								nat_rule_aging_msg->info[i].dport, 
+								nat_rule_aging_msg->info[i].proto);
+				if (curr_nat_rule != NULL) 
+					fp_update_nat_rule_aging(curr_nat_rule, nat_rule_aging_msg->info[i].count);
+			}
+			break;
+		default:
+			printk("fp_rcv_info_msg: unknown message type\n"); 
+			break;
+	}
+}
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+/* Initialize NFP Manager */
+int fp_mgr_init(void)
+{
+	int i = 0;
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	int                 status = 0;
+	MV_FP_INIT_STRUCT   fpdb_init_struct;
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+    fp_disable_flag = 1;
+
+	fp_eth_devs = kmalloc((ETH_FP_IFINDEX_MAX * sizeof(struct map_eth_devs)), GFP_ATOMIC);
+	if (fp_eth_devs == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < ETH_FP_IFINDEX_MAX; i++) {
+		fp_eth_devs[i].if_type = MV_FP_IF_INV;
+        	fp_eth_devs[i].dev = NULL;
+        	fp_eth_devs[i].def_gtw_ip = 0;
+	}
+  	spin_lock_init(&nfp_mgr_lock);
+
+	memset(&aging_timer, 0, sizeof(struct timer_list));
+	init_timer(&aging_timer);
+    	aging_timer.function = aging_timer_function;
+    	aging_timer.data = -1;
+	aging_timer.expires = jiffies + AGING_TIMER_PERIOD;
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	mgr_to_fp_chan = mvIpcChanCreate(MV_IPC_HOST_ID, MV_IPC_COPROCESSOR_ID,
+                                        MV_IPC_RX_CB_MODE, MAX_MSG_SIZE, 64 /*mgr_rule_db.max_size*/);
+ 
+	fp_to_mgr_chan = mvIpcChanCreate(MV_IPC_COPROCESSOR_ID, MV_IPC_HOST_ID, 
+                                        MV_IPC_RX_CB_MODE, MAX_MSG_SIZE, 64 /*mgr_rule_db.max_size*/);
+
+	status = mvIpcChanRcvCbSet(fp_to_mgr_chan, fp_rcv_info_msg);
+	if ((status != 0) || (mgr_to_fp_chan < 0) || (fp_to_mgr_chan < 0))
+        {
+		printk("fp_mgr_init: Error setting up IPC channels\n");
+		return status;
+        }
+
+	/* Connect Channel Dispatch function */
+	mvIpcDbConnect(mvIpcChanDoorbellGet(fp_to_mgr_chan), mvIpcChanDispatchIsr, (void*)fp_to_mgr_chan);
+	/* Enable Doorbell interrupt */
+	MV_IPC_DOORBELL_ENABLE(MV_IPC_HOST_ID, mvIpcChanDoorbellGet(fp_to_mgr_chan));
+
+	memset(&fpdb_init_struct, 0, sizeof(MV_FP_INIT_STRUCT));
+	fpdb_init_struct.mgr_to_fp_chan = mgr_to_fp_chan;
+	fpdb_init_struct.fp_to_mgr_chan = fp_to_mgr_chan;
+	fpdb_init_struct.rule_db_size = mgr_rule_db.max_size;
+	status = mvIpcChanMsgSend(	mvIpcTxSharedChanGet(MV_IPC_COPROCESSOR_ID), 
+					MV_SERVICE_NFP_ID, MV_FP_RULE_DB_INIT_OPCODE,
+					&fpdb_init_struct, sizeof(MV_FP_INIT_STRUCT));
+	if (status != 0) 
+	{
+		printk("fp_mgr_init: Error sending NFP initialization message\n");
+		return status;
+	}
+	return 0;
+#else
+	/* Note at this stage the Manager DB is already initialized so mgr_rule_db.max_size is set */
+	mvFpRuleDbInit(mgr_rule_db.max_size);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+    return 0;
+}
+
+static int fp_mgr_get_iftype(int if_index)
+{
+	if (!fp_eth_devs ||
+		(if_index < 0) || 
+		(if_index >= ETH_FP_IFINDEX_MAX))
+		return MV_FP_IF_INV;
+
+	return fp_eth_devs[if_index].if_type;
+}
+
+/* Register a network interface that works with NFP */
+int fp_mgr_if_register(	int if_index, MV_FP_IF_TYPE if_type, 
+			            struct net_device* dev)
+{
+	/* sanity checks */
+	if( (fp_eth_devs == NULL) || 
+	    (if_index < 0) || (if_index >= ETH_FP_IFINDEX_MAX) )
+		return -1;
+
+	fp_eth_devs[if_index].dev = dev;
+	fp_eth_devs[if_index].if_type = if_type;
+
+	return 0;
+}
+
+int fp_mgr_if_unregister(int if_index)
+{
+	if (fp_eth_devs || 
+		(if_index < 0) || 
+		(if_index >= ETH_FP_IFINDEX_MAX))
+		return -1;
+
+	memset(&fp_eth_devs[if_index], 0, sizeof(struct map_eth_devs));
+	return 0;
+}
+
+/* This function is called when user-space tool disables NFP */
+/* All databases are cleared, and learning of new rules is disabled	*/
+/* for all types of rules: static, dynamic, arp, routing etc.		*/
+void fp_mgr_disable(void)
+{
+	if (fp_disable_flag == 0) {
+		fp_disable_flag = 1;
+		del_timer(&aging_timer);
+	}
+	printk("Network Fast Processing Disabled\n");
+}
+
+/* This function is called when user-space tool enables NFP */
+int fp_mgr_enable(void)
+{
+	int status;
+
+	if (fp_disable_flag == 1) {
+		fp_disable_flag = 0;
+		status = fp_db_clear_and_update();
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+        status |= fp_nat_db_clear_and_update();
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+		aging_timer.expires = jiffies + AGING_TIMER_PERIOD;
+		add_timer(&aging_timer);
+		printk("Network Fast Processing Enabled\n");
+		return status;
+	}
+	printk("Network Fast Processing Enabled\n");
+	return 0;
+}
+
+/* This function is called when user-space tool asks about NFP status (enabled/disabled) */
+int fp_mgr_status(void)
+{
+	if (fp_disable_flag == 0)
+		printk("Network Fast Processing is currently Enabled\n");
+	else
+		printk("Network Fast Processing is currently Disabled\n");
+
+	return 0;
+}
+
+/* Initialize NFP Rule Database (Routing + ARP information table) */
+int fp_rule_db_init(u32 db_size)
+{
+	FP_MGR_DBG(FP_MGR_DBG_INIT, ("FP_MGR: Initializing Rule Database\n"));
+	mgr_rule_db.rule_chain = NULL;
+	mgr_rule_db.max_size = db_size;
+	/* Initialization of the NFP HAL Database is called from fp_mgr_init */
+	return 0;
+}
+ 
+/* Initialize NFP Manager ARP Database */
+int fp_arp_db_init(u32 db_size)
+{
+	FP_MGR_DBG(FP_MGR_DBG_INIT, ("FP_MGR: Initializing ARP Rule Database\n"));
+	mgr_arp_rule_db.rule_chain = NULL;
+	mgr_arp_rule_db.max_size = db_size;
+	return 0;
+}
+
+/* Clear NFP Rule Database (Routing + ARP information table) */
+int fp_rule_db_clear(void)
+{
+	int status = 0;
+	unsigned long flags;
+	MV_FP_RULE *curr_rule;
+	MV_FP_RULE *tmp_rule;
+
+	FP_MGR_DBG(FP_MGR_DBG_CLR, ("FP_MGR: Clearing Rule Database\n"));
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	curr_rule = mgr_rule_db.rule_chain;
+	while (curr_rule != NULL) {
+		tmp_rule = curr_rule;
+		curr_rule = curr_rule->next;
+		kfree(tmp_rule);
+	}
+	mgr_rule_db.rule_chain = NULL;
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_RULE_DB_CLEAR_OPCODE, NULL, 0);
+#else
+	status = mvFpRuleDbClear();
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return status;
+}
+
+/* Clear NFP Manager ARP Database */
+int fp_arp_db_clear(void)
+{
+	unsigned long   flags;
+	MV_FP_ARP_RULE  *curr_rule;
+	MV_FP_ARP_RULE  *tmp_rule;
+
+	FP_MGR_DBG(FP_MGR_DBG_CLR, ("FP_MGR: Clearing ARP Rule Database\n"));
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	curr_rule = mgr_arp_rule_db.rule_chain;
+	while (curr_rule != NULL) {
+		tmp_rule = curr_rule;
+		curr_rule = curr_rule->next;
+		kfree(tmp_rule);
+	}
+	mgr_arp_rule_db.rule_chain = NULL;
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return 0;
+}
+
+/* Print NFP Rule Database (Routing + ARP information table) */
+int fp_rule_db_print(MV_FP_OP_TYPE op)
+{
+	int             status = 0;
+	unsigned long   flags;
+	MV_FP_RULE      *curr_rule;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	if (op == MV_FP_MANAGER) {
+		printk("Printing NFP Manager Rule Database: \n");
+		curr_rule = mgr_rule_db.rule_chain;
+		while (curr_rule != NULL) { 
+			mvFpRulePrint(curr_rule);
+			curr_rule = curr_rule->next;
+		}
+	}
+	else {
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+		status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_RULE_DB_PRINT_OPCODE, NULL, 0);
+#else
+		status = mvFpRuleDbPrint();
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return status;
+}
+
+/* Print ARP Rule */
+static void fp_arp_rule_print(const MV_FP_ARP_RULE *rule)
+{
+	printk("ARP Rule: ");
+	printk("IP = %u.%u.%u.%u, ", NIPQUAD(rule->ip));
+	printk("MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", rule->mac[0], rule->mac[1], rule->mac[2], 
+							rule->mac[3], rule->mac[4], rule->mac[5]);
+}
+
+/* Print NFP Manager ARP Database */
+int fp_arp_db_print(void)
+{
+	unsigned long   flags;
+	MV_FP_ARP_RULE  *curr_rule;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	printk("Printing NFP Manager ARP Rule Database: \n");
+	curr_rule = mgr_arp_rule_db.rule_chain;
+	while (curr_rule != NULL) {
+		fp_arp_rule_print(curr_rule);
+		curr_rule = curr_rule->next;
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return 0;
+}
+
+/* Copy 6 bytes. Warning - doesn't perform any checks on memory, just copies */
+static inline void mac_addr_copy(u8 *dst, const u8 *src)
+{
+	dst[0] = src[0];
+	dst[1] = src[1];
+	dst[2] = src[2];
+	dst[3] = src[3];
+	dst[4] = src[4];
+	dst[5] = src[5];
+}
+
+/* Update the Routing + ARP database with new ARP information: */
+/* Go over the database and update the destination MAC address */
+/* for each entry with a matching default gateway IP address.  */
+static int fp_rule_db_arp_update(u32 ip, const u8 *mac)
+{
+	int             status = 0;
+	unsigned long   flags;
+	MV_FP_RULE      *curr_rule;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	for (curr_rule = mgr_rule_db.rule_chain; curr_rule != NULL; curr_rule = curr_rule->next) 
+    	{
+		if(	(curr_rule->routingInfo.defGtwIp == ip) && 
+			(curr_rule->mgmtInfo.ruleType != MV_FP_STATIC_RULE)) 
+        	{
+			mac_addr_copy(curr_rule->routingInfo.dstMac, mac);
+			if (!is_zero_ether_addr(mac)) 
+            		{
+				/* Now we have a full rule - we can update the NFP database */
+				fp_new_rule_awareness(curr_rule);
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+				status |= mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+						MV_FP_RULE_SET_OPCODE, curr_rule, sizeof(MV_FP_RULE));
+#else
+				status |= mvFpRuleSet(curr_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+			}
+			else
+            		{
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+				status |= mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+						MV_FP_RULE_DELETE_OPCODE, curr_rule, sizeof(MV_FP_RULE));
+#else
+				status |= mvFpRuleDelete(curr_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+            		}
+		}
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return status;
+}
+
+/* Set ARP information in the ARP database, and update the Routing + ARP database if necessary */
+/* If we have a complete rule, update the NFP database */
+int fp_arp_info_set(int if_index, u32 ip, const u8 *mac)
+{
+	unsigned long   flags;
+	MV_FP_ARP_RULE  *curr_rule;
+	MV_FP_ARP_RULE  *new_rule;
+
+    	if(!is_valid_index(if_index))
+       		return 0;
+
+	FP_MGR_DBG(FP_MGR_DBG_ARP, ("nfp_mgr Set ARP: if=%d, IP=%u.%u.%u.%u, MAC=%02X:%02X:%02X:%02X:%02X:%02X\n",
+                                if_index, NIPQUAD(ip), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	for (curr_rule = mgr_arp_rule_db.rule_chain; curr_rule != NULL; curr_rule = curr_rule->next) {
+		if (curr_rule->ip == ip) {
+			/* We've found a match with an existing entry. Let's update it */
+			mac_addr_copy(curr_rule->mac, mac);
+			curr_rule->confirmed = 1;
+			spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+			return fp_rule_db_arp_update(ip, mac);
+		}
+	}
+	/* We haven't found a matching existing entry. Let's add a new one */
+	new_rule = kmalloc(sizeof(MV_FP_ARP_RULE), GFP_ATOMIC);
+	if (new_rule == NULL) {
+		spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+		return -ENOMEM;
+	}
+	new_rule->ip = ip;
+	mac_addr_copy(new_rule->mac, mac);
+	new_rule->confirmed = 1;
+    	new_rule->if_index = if_index;
+	new_rule->next = NULL;
+	
+	if (mgr_arp_rule_db.rule_chain == NULL) {
+		/* There is no rule in this table yet */
+		mgr_arp_rule_db.rule_chain = new_rule;
+	}
+	else {
+		/* Let's add this rule at the tail of the list */
+		curr_rule = mgr_arp_rule_db.rule_chain;
+		while (curr_rule->next != NULL)
+			curr_rule = curr_rule->next;
+		
+		curr_rule->next = new_rule;		
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return fp_rule_db_arp_update(ip, mac);
+}
+
+/* Delete ARP information from the ARP database, and update the Routing + ARP database if necessary */
+/* If a rule became incomplete, update the NFP database */
+int fp_arp_info_delete(u32 ip)
+{
+	unsigned long   flags;
+	MV_FP_ARP_RULE  *curr_rule;
+	MV_FP_ARP_RULE  *prev_rule;
+	u8              mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+
+	prev_rule = NULL;	
+	for (	curr_rule = mgr_arp_rule_db.rule_chain; 
+		curr_rule != NULL; 
+		prev_rule = curr_rule, curr_rule = curr_rule->next) {
+		if (curr_rule->ip == ip) {
+			/* Note there should only be one matching entry for this IP address */
+			if (prev_rule == NULL)
+				mgr_arp_rule_db.rule_chain = curr_rule->next;	
+			else
+				prev_rule->next = curr_rule->next;
+			kfree(curr_rule);
+			spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+            		FP_MGR_DBG(FP_MGR_DBG_ARP, 
+                		("nfp_mgr: ARP delete: IP=%u.%u.%u.%u, MAC=%02X:%02X:%02X:%02X:%02X:%02X\n",
+                        	NIPQUAD(ip), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
+
+			return fp_rule_db_arp_update(ip, mac);
+		}
+	}
+	/* We haven't found a matching entry, so nothing to do */
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return 0;
+}
+
+/* Set a new rule or update an existing one  */
+/* When looking for an existing rule, search */
+/* a match for SIP, DIP, and default gateway IP */
+/* Rule type is also taken into account: */
+/* a new static rule can overrode an existing rule of any type, */
+/* while a new dynamic rule can only override an existing dynamic rule */
+int fp_rule_set(MV_FP_RULE *rule)
+{
+	unsigned long   flags;
+	MV_FP_RULE      *curr_rule;
+	MV_FP_RULE      *new_rule;
+	int             status = 0;
+
+	/* Static rules are supplied with GbE port numbers, while */
+	/* dynamic rules are supplied with Linux interface indices. */
+	if (rule->mgmtInfo.ruleType == MV_FP_DYNAMIC_RULE) {
+		struct net_device   *in_dev, *out_dev;
+
+		/* We are not interested in this rule if the input interface or */
+		/* the output interface is not one of our GbE interfaces.	*/
+		if (	!is_valid_index(rule->routingInfo.inIfIndex) || 
+            		!is_valid_index(rule->routingInfo.outIfIndex)) 
+		{
+			return 0;
+		}
+
+		in_dev = mv_dev_get_by_index(rule->routingInfo.inIfIndex);
+		out_dev = mv_dev_get_by_index(rule->routingInfo.outIfIndex);
+
+		/* check MTU compatability */
+		if (in_dev && out_dev) {
+#ifdef CONFIG_MV_ETH_NFP_PPP
+			if ((in_dev->type == ARPHRD_PPP) || (out_dev->type == ARPHRD_PPP))
+				;
+			else
+#endif
+			if ((in_dev->mtu != out_dev->mtu) || 
+				(out_dev->mtu > ETH_CSUM_MAX_BYTE_COUNT))
+			{
+				/* printk("%s: invalid mtu %d, %d\n", __FUNCTION__, 
+					   in_dev->mtu, out_dev->mtu); */
+				return 0;
+			}
+		}
+	}
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+    	curr_rule = fp_rule_find(rule->routingInfo.srcIp, rule->routingInfo.dstIp);
+    	if(curr_rule != NULL)
+    	{
+        	if( (curr_rule->mgmtInfo.ruleType == MV_FP_DYNAMIC_RULE) || 
+	        	(rule->mgmtInfo.ruleType == MV_FP_STATIC_RULE) ) 
+        	{
+	        	/* Update existing rule, but only if the current rule is a dynamic rule, */
+	        	/* or the new rule is a static rule which overrides the current rule. */		
+	        	mvFpRuleCopy(curr_rule, rule);
+
+	        	if (!is_zero_ether_addr(curr_rule->routingInfo.dstMac)) {
+		        	/* Now we have a full rule - we can update the NFP database */
+		        	fp_new_rule_awareness(curr_rule);
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+			    	status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+			                        MV_FP_RULE_SET_OPCODE, curr_rule, sizeof(MV_FP_RULE));
+#else
+			    	status = mvFpRuleSet(curr_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+		    	}
+	    	}
+        	/* else, we have found a matching entry, but the current rule is static and */
+	    	/* the new rule is dynamic, so static rule remains unchanged, and we can exit here. */
+	    	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	    	return status;
+    	}
+	/* We haven't found a matching existing entry. Let's add a new one */
+	new_rule = kmalloc(sizeof(MV_FP_RULE), GFP_ATOMIC);
+	if (new_rule == NULL) {
+		spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+		return -ENOMEM;
+	}
+	mvFpRuleCopy(new_rule, rule);	
+	new_rule->next = NULL;
+
+	if (mgr_rule_db.rule_chain == NULL) {
+		/* There is no rule in this table yet */
+		mgr_rule_db.rule_chain = new_rule;
+	}
+	else {
+		/* Let's add this rule at the tail of the list */
+		curr_rule = mgr_rule_db.rule_chain;		
+		while (curr_rule->next != NULL)
+			curr_rule = curr_rule->next;
+		curr_rule->next = new_rule;		
+	}
+	if (!is_zero_ether_addr(new_rule->routingInfo.dstMac)) {
+		/* Now we have a full rule - we can update the the NFP database */
+		fp_new_rule_awareness(new_rule);
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+		status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+				MV_FP_RULE_SET_OPCODE, new_rule, sizeof(MV_FP_RULE));
+#else
+		status = mvFpRuleSet(new_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return status;
+}
+
+/* Delete an existing rule */
+/* When looking for an existing rule, search */
+/* a match for SIP, DIP */
+int fp_rule_delete(u32 src_ip, u32 dst_ip, MV_FP_RULE_TYPE rule_type)
+{
+	unsigned long   flags;
+	MV_FP_RULE      *curr_rule;
+	MV_FP_RULE      *prev_rule;
+	int             status = 0;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	prev_rule = NULL;	
+
+	for(curr_rule = mgr_rule_db.rule_chain; 
+		curr_rule != NULL; 
+		prev_rule = curr_rule, curr_rule = curr_rule->next) {
+		if( (curr_rule->routingInfo.srcIp == src_ip) && 
+			(curr_rule->routingInfo.dstIp == dst_ip) && 
+			(curr_rule->mgmtInfo.ruleType == rule_type) ) {
+			/* Note there should only be one matching entry, if any */
+			if (prev_rule == NULL) {
+				mgr_rule_db.rule_chain = curr_rule->next;
+			}
+			else {
+				prev_rule->next = curr_rule->next;
+			}
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+			status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+						MV_FP_RULE_DELETE_OPCODE, curr_rule, sizeof(MV_FP_RULE));
+#else
+			status = mvFpRuleDelete(curr_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+			kfree(curr_rule);
+			spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+			return status;
+		}
+	}
+	/* We haven't found a matching entry, so nothing to do */
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return 0;
+}
+
+/* 
+ * Set Routing ToS for 2-tuple connection
+ */
+#ifdef CONFIG_MV_ETH_NFP_TOS
+int fp_routing_tos_set(u32 src_ip, u32 dst_ip, u32 dscp, u32 txq)
+{
+	MV_FP_RULE* rule;
+	unsigned long flags;
+
+	FP_MGR_DBG(FP_MGR_DBG_ROUTE, 
+			("FP_MGR: Setting ToS Information: SIP = "NIPQUAD_FMT ", DIP = "NIPQUAD_FMT", TOS=0x%x TxQ=%d\n", 
+			NIPQUAD(src_ip), NIPQUAD(dst_ip), dscp, txq));
+
+	if (txq >= CONFIG_MV_ETH_TX_Q_NUM)
+		return -EINVAL;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	rule = fp_rule_find(src_ip,dst_ip);
+	if (rule) {
+		rule->routingInfo.dscp = (u8)dscp;
+		rule->routingInfo.txq = (u8)txq;
+	
+		/* The rule is already applied, update engine db */
+		if (!is_zero_ether_addr(rule->routingInfo.dstMac))
+			mvFpToSSet(rule);
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+#endif
+/* Set Routing information received from the IP stack when a new Routing cache entry is created */
+/* Look for matching ARP information to complete the rule */
+/* If we have a complete rule, update the NFP database */
+int fp_routing_info_set(u32 src_ip, u32 dst_ip, u32 def_gtw_ip, int ingress_if, int egress_if)
+{
+	MV_FP_RULE          new_rule;
+	MV_FP_ARP_RULE      *arp_rule;
+	struct net_device   *dev;
+
+        if (fp_disable_flag == 1)
+                return 0;
+
+	FP_MGR_DBG(FP_MGR_DBG_ROUTE, ("FP_MGR: Setting Routing Information\n"));
+	FP_MGR_DBG(FP_MGR_DBG_ROUTE, 
+			("SIP = "NIPQUAD_FMT ", DIP = "NIPQUAD_FMT", GTW = "NIPQUAD_FMT", In IF = %d, Out IF = %d\n", 
+			NIPQUAD(src_ip), NIPQUAD(dst_ip), 
+			NIPQUAD(def_gtw_ip), ingress_if, egress_if));
+
+    	if( !is_valid_index(ingress_if) || !is_valid_index(egress_if) )
+       		return 0;
+
+	memset(&new_rule, 0, sizeof(MV_FP_RULE));
+	new_rule.mgmtInfo.actionType = MV_FP_ROUTE_CMD;
+	new_rule.mgmtInfo.ruleType = MV_FP_DYNAMIC_RULE; 
+
+	new_rule.routingInfo.srcIp = src_ip;
+	new_rule.routingInfo.dstIp = dst_ip;
+	new_rule.routingInfo.defGtwIp = def_gtw_ip;
+	
+	dev = mv_dev_get_by_index(egress_if);
+	if (dev)  
+		mac_addr_copy(new_rule.routingInfo.srcMac, dev->dev_addr);
+
+   	fp_eth_devs[egress_if].def_gtw_ip = def_gtw_ip;
+
+	/* Note: searching destination MAC according to default gateway IP */
+	if ((arp_rule = fp_arp_rule_find(def_gtw_ip)) != NULL) 
+		mac_addr_copy(new_rule.routingInfo.dstMac, arp_rule->mac);
+
+	new_rule.routingInfo.inIfIndex = ingress_if;
+	new_rule.routingInfo.outIfIndex = egress_if;
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	/* DA is defined by pppoe session */
+	if (dev->type == ARPHRD_PPP)
+		new_rule.routingInfo.dstMac[5] = 0xAA;
+#endif
+
+	return fp_rule_set(&new_rule);
+}
+
+/* Delete Routing information from the Routing + ARP database, and update the NFP database */
+int fp_routing_info_delete(u32 src_ip, u32 dst_ip, int iif, int oif)
+{
+        if (fp_disable_flag == 1)
+                return 0;
+
+	FP_MGR_DBG(FP_MGR_DBG_ROUTE, ("FP_MGR: Deleting Routing Information\n"));
+	FP_MGR_DBG(FP_MGR_DBG_ROUTE, (	"SIP = %u.%u.%u.%u, DIP = %u.%u.%u.%u\n", 
+					NIPQUAD(src_ip), NIPQUAD(dst_ip)));
+
+        if( !is_valid_index(iif) || !is_valid_index(oif) )
+                return 0;
+
+	return fp_rule_delete(src_ip, dst_ip, MV_FP_DYNAMIC_RULE);
+}
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+
+/* Initialize NFP NAT Rule Database (SNAT + DNAT table) */
+int fp_nat_db_init(u32 db_size)
+{
+	FP_MGR_DBG(FP_MGR_DBG_INIT, ("FP_MGR: Initializing NAT Rule Database\n"));
+	mgr_nat_rule_db.rule_chain = NULL;
+	mgr_nat_rule_db.max_size = db_size;
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	return mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_NAT_DB_INIT_OPCODE, 
+				&(mgr_nat_rule_db.max_size), sizeof(mgr_nat_rule_db.max_size));
+#else
+	return mvFpNatDbInit(mgr_nat_rule_db.max_size);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+}
+
+/* Clear NFP NAT Rule Database (SNAT + DNAT table) */
+int fp_nat_db_clear(void)
+{
+	int             status = 0;
+	unsigned long   flags;
+	MV_FP_NAT_RULE  *curr_rule;
+	MV_FP_NAT_RULE  *tmp_rule;
+
+	FP_MGR_DBG(FP_MGR_DBG_CLR, ("FP_MGR: Clearing NAT Rule Database\n"));
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	curr_rule = mgr_nat_rule_db.rule_chain;
+	while (curr_rule != NULL) {
+		tmp_rule = curr_rule;
+		curr_rule = curr_rule->next;
+		kfree(tmp_rule);
+	}
+	mgr_nat_rule_db.rule_chain = NULL;
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_NAT_DB_CLEAR_OPCODE, NULL, 0);
+#else
+	status = mvFpNatDbClear();
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return status;
+}
+
+static int fp_nat_db_clear_and_update(void)
+{
+    int             status = 0;
+	unsigned long   flags;
+    MV_FP_NAT_RULE  *curr_nat_rule = mgr_nat_rule_db.rule_chain;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_NAT_DB_CLEAR_OPCODE, NULL, 0);
+#else
+	status = mvFpNatDbClear();
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+
+	while (curr_nat_rule != NULL) { 
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+		status |= mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+					MV_FP_NAT_RULE_SET_OPCODE, curr_nat_rule, sizeof(MV_FP_NAT_RULE));
+#else
+		status |= mvFpNatRuleSet(curr_nat_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+		curr_nat_rule = curr_nat_rule->next;
+    }
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+    return status;
+}
+
+/* Print NFP NAT Rule Database (SNAT + DNAT table) */
+int fp_nat_db_print(MV_FP_OP_TYPE op)
+{
+	int             status = 0;
+	unsigned long   flags;
+	MV_FP_NAT_RULE  *curr_rule;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	if (op == MV_FP_MANAGER) {
+		printk("Printing NFP Manager NAT Rule Database: \n");
+		curr_rule = mgr_nat_rule_db.rule_chain;
+		while (curr_rule != NULL) {
+			mvFpNatRulePrint(curr_rule);
+			curr_rule = curr_rule->next;
+		}
+	}
+	else {
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+		status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, MV_FP_NAT_DB_PRINT_OPCODE, NULL, 0);
+#else
+		status = mvFpNatDbPrint();
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return status;
+}
+
+static int is_relevant_nat_protocol(u8 proto)
+{
+	/* For now we only knw how to handle NAT rules for TCP/UDP/ICMP/Zero_Hop protocols */
+	/* so we disregard everything else */
+	if (	(proto == MV_IP_PROTO_TCP) || 
+		(proto == MV_IP_PROTO_UDP) || 
+		(proto == MV_IP_PROTO_ICMP) || 
+		(proto == MV_IP_PROTO_ZERO_HOP))
+		return 1;
+
+	return 0;
+}
+
+static int is_relevant_port(u16 src_port, u16 dst_port)
+{
+	/* We want to pass FTP control stream packets to Linux */
+	if (	(MV_16BIT_BE(src_port) != MV_FTP_CTRL_PORT) 
+		&& (MV_16BIT_BE(dst_port) != MV_FTP_CTRL_PORT))
+		return 1;
+	return 0;
+}
+
+/* Set a new NAT rule, or update an existing one */
+int fp_nat_info_set(u32 src_ip, u32 dst_ip, u16 src_port, u16 dst_port, u8 proto, 
+			        u32 new_src_ip, u32 new_dst_ip, u16 new_src_port, u16 new_dst_port, 
+			        int if_index, enum nf_nat_manip_type maniptype)
+{
+	unsigned long   flags;
+	MV_FP_NAT_RULE  *curr_rule;
+	MV_FP_NAT_RULE  *new_rule;
+	int             status = 0;
+
+	/* we are not interested in NAT rules that do not involve our interfaces */
+	if (!is_valid_index(if_index)) {
+		FP_MGR_DBG(FP_MGR_DBG_NAT, ("FP_MGR: invalid_index %d\n", if_index));
+		return 0;
+	}
+
+	if (!is_relevant_nat_protocol(proto)) {
+		FP_MGR_DBG(FP_MGR_DBG_NAT, ("FP_MGR: irrelevant nat protocol %d\n", proto));
+		return 0;
+	}
+
+	if (!is_relevant_port(src_port, dst_port)) {
+		FP_MGR_DBG(FP_MGR_DBG_NAT, ("FP_MGR: irrelevant port %d %d\n", src_port, dst_port));
+		return 0;
+	}
+
+	if ((src_ip == new_src_ip) && (dst_ip == new_dst_ip) && 
+		(src_port == new_src_port) && (dst_port == new_dst_port) ) 
+    	{
+   		return 0;
+	}
+
+   	FP_MGR_DBG(FP_MGR_DBG_NAT, ("FP_MGR: Setting NAT Information\n"));
+	FP_MGR_DBG(FP_MGR_DBG_NAT,
+	        ("SIP=%u.%u.%u.%u, DIP=%u.%u.%u.%u, Proto=%u, SPort=%u, DPort=%u, if_index=%d\n",
+			        NIPQUAD(src_ip), NIPQUAD(dst_ip), proto, MV_16BIT_BE(src_port), 
+			        MV_16BIT_BE(dst_port), if_index));
+
+    	FP_MGR_DBG(FP_MGR_DBG_NAT,
+        	("\tNewSIP=%u.%u.%u.%u, NewDIP=%u.%u.%u.%u, NewSPort=%u, NewDPort=%u\n\n", 
+            	NIPQUAD(new_src_ip), NIPQUAD(new_dst_ip), 
+		MV_16BIT_BE(new_src_port), MV_16BIT_BE(new_dst_port)));
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	for (curr_rule = mgr_nat_rule_db.rule_chain; curr_rule != NULL; curr_rule = curr_rule->next) {
+		if( curr_rule->srcIp == src_ip && 
+			curr_rule->dstIp == dst_ip && 
+			curr_rule->srcPort == src_port && 
+			curr_rule->dstPort == dst_port && 
+			curr_rule->proto == proto) 
+        {
+
+			/* Updating existing rule */
+			curr_rule->new_count = 0;
+            		curr_rule->old_count = 0;
+
+			if (maniptype == IP_NAT_MANIP_DST) {
+				curr_rule->newIp = new_dst_ip;
+				curr_rule->newPort = new_dst_port;
+			}
+			else {
+				curr_rule->newIp = new_src_ip;
+				curr_rule->newPort = new_src_port;
+			}
+			if (maniptype == IP_NAT_MANIP_DST) {
+				if ((dst_port != 0) && (dst_port != new_dst_port))
+					curr_rule->flags |= MV_FP_DNAT_CMD_MAP;
+				else
+					curr_rule->flags |= MV_FP_DIP_CMD_MAP; 
+			}
+			else {
+				if ((src_port != 0) && (src_port != new_src_port))
+					curr_rule->flags |= MV_FP_SNAT_CMD_MAP;
+				else
+					curr_rule->flags |= MV_FP_SIP_CMD_MAP;
+			}	
+			/* Now we have a full rule - we can update the NFP database       */
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+			status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+				            MV_FP_NAT_RULE_SET_OPCODE, curr_rule, sizeof(MV_FP_NAT_RULE));
+#else
+			status = mvFpNatRuleSet(curr_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+			spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+			return status;
+		}
+	}
+	/* We haven't found a matching existing entry. Let's add a new one */
+	new_rule = kmalloc(sizeof(MV_FP_NAT_RULE), GFP_ATOMIC);
+	if (new_rule == NULL) {
+		spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+		return -ENOMEM;
+	}
+	new_rule->srcIp = src_ip;
+	new_rule->dstIp = dst_ip;
+	new_rule->srcPort = src_port;
+	new_rule->dstPort = dst_port;
+	new_rule->proto = proto;
+	new_rule->old_count = 0;
+    	new_rule->new_count = 0;
+	if (maniptype == IP_NAT_MANIP_DST) {
+		new_rule->newIp = new_dst_ip;
+		new_rule->newPort = new_dst_port;
+	}
+	else {
+		new_rule->newIp = new_src_ip;
+		new_rule->newPort = new_src_port;
+	}
+	if (maniptype == IP_NAT_MANIP_DST) {
+		if ((dst_port != 0) && (dst_port != new_dst_port))
+			new_rule->flags = MV_FP_DNAT_CMD_MAP;
+		else
+			new_rule->flags = MV_FP_DIP_CMD_MAP;
+	}
+	else {
+		if ((src_port != 0) && (src_port != new_src_port))
+			new_rule->flags = MV_FP_SNAT_CMD_MAP;
+		else
+			new_rule->flags = MV_FP_SIP_CMD_MAP;
+	}
+	new_rule->next = NULL;
+
+	if (mgr_nat_rule_db.rule_chain == NULL) {
+		/* There is no rule in this table yet */
+		mgr_nat_rule_db.rule_chain = new_rule;
+	}
+	else {
+		/* Let's add this rule at the tail of the list */
+		curr_rule = mgr_nat_rule_db.rule_chain;		
+		while (curr_rule->next != NULL)
+			curr_rule = curr_rule->next;
+		curr_rule->next = new_rule;		
+	}
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+	status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+				MV_FP_NAT_RULE_SET_OPCODE, new_rule, sizeof(MV_FP_NAT_RULE));
+#else
+	status = mvFpNatRuleSet(new_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return status;
+}
+
+/* Delete a NAT rule */
+int fp_nat_info_delete(u32 src_ip, u32 dst_ip, u16 src_port, u16 dst_port, u8 proto)
+{
+	unsigned long   flags;
+	MV_FP_NAT_RULE  *curr_rule;
+	MV_FP_NAT_RULE  *prev_rule;
+	int             status = 0;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	prev_rule = NULL;
+	for (	curr_rule = mgr_nat_rule_db.rule_chain; 
+		curr_rule != NULL; 
+		prev_rule = curr_rule, curr_rule = curr_rule->next) {
+		if (	curr_rule->srcIp == src_ip && 
+			curr_rule->dstIp == dst_ip && 
+			curr_rule->srcPort == src_port && 
+			curr_rule->dstPort == dst_port && 
+			curr_rule->proto == proto) {
+
+			if (prev_rule == NULL)
+				mgr_nat_rule_db.rule_chain = curr_rule->next;	
+			else
+				prev_rule->next = curr_rule->next;
+#ifdef CONFIG_MV_ETH_NFP_DUAL
+			status = mvIpcChanMsgSend(mgr_to_fp_chan, MV_SERVICE_NFP_ID, 
+					MV_FP_NAT_RULE_DELETE_OPCODE, curr_rule, sizeof(MV_FP_NAT_RULE));
+#else
+			status = mvFpNatRuleDelete(curr_rule);
+#endif /* CONFIG_MV_ETH_NFP_DUAL */
+			kfree(curr_rule);
+			spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+			return status;
+		}
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return 0;
+}
+
+/* Return NAT rule confirmation status */
+int fp_is_nat_confirmed(u32 src_ip, u32 dst_ip, u16 src_port, u16 dst_port, u8 proto)
+{
+	unsigned long   flags;
+	MV_FP_NAT_RULE  *curr_rule;
+    	int             confirmed = 0;
+
+	if (fp_disable_flag == 1)
+		return 0;
+    	
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	curr_rule = mgr_nat_rule_db.rule_chain;
+	while (curr_rule != NULL) {
+		if( (curr_rule->srcIp == src_ip) && 
+			(curr_rule->dstIp == dst_ip) && 
+			(curr_rule->srcPort == src_port) && 
+			(curr_rule->dstPort == dst_port) && 
+			(curr_rule->proto == proto)) 
+        	{
+            		if(curr_rule->new_count != curr_rule->old_count)
+            		{
+                		curr_rule->old_count = curr_rule->new_count;
+                		confirmed = 1;
+            		}
+		    	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+			return confirmed;
+		}
+		curr_rule = curr_rule->next;
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+	return 0;
+}
+
+/* Set or clear the "NAT Aware" flags according to user's newly added or deleted iptables rule */
+static void fp_handle_user_nat_rule(FP_IPTABLES_NAT_RULE *nat_rule, int add_del_flag)
+{
+	/* This NAT rule that the user added can affect routing entries based on */
+	/* input interface, output interface, SIP, DIP */
+	/* For now, protocol and source/dest port are not taken into consideration */
+
+	MV_FP_RULE      *curr_rule;
+	unsigned long   flags;
+	
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	curr_rule = mgr_rule_db.rule_chain; 
+	while (curr_rule != NULL) {
+		update_awareness(nat_rule, curr_rule, add_del_flag);		
+		mvFpRuleAwareSet(curr_rule);	
+		curr_rule = curr_rule->next;
+	}
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+}
+
+/* Initialize our user NAT tables, mirroring iptables NAT rules table */
+void init_fp_user_nat_tables(void)
+{
+	fp_user_nat_table[0].rule_chain = NULL;
+	fp_user_nat_table[1].rule_chain = NULL;
+	curr_table = 0;
+	old_table = 1 - curr_table;
+}
+
+/* Add a user NAT rule to our mirror table */
+int add_fp_user_nat_rule(struct ipt_entry *e, int table)
+{
+	struct ipt_entry_target *t = NULL;
+	FP_IPTABLES_NAT_RULE *curr_rule = NULL, *new_rule = NULL;
+
+	t = ipt_get_target(e);
+	/* Disregard targets that do not interest us */
+	if (	strcmp(t->u.kernel.target->name, MASQ_TARGET_NAME) && 
+		strcmp(t->u.kernel.target->name, REDIRECT_TARGET_NAME) && 
+		strcmp(t->u.kernel.target->name, SNAT_TARGET_NAME) && 
+		strcmp(t->u.kernel.target->name, DNAT_TARGET_NAME))
+		return 0;
+
+	new_rule = kmalloc(sizeof(FP_IPTABLES_NAT_RULE), GFP_ATOMIC);
+	if (new_rule == NULL)
+		return -ENOMEM;
+	memset(new_rule, 0, sizeof(FP_IPTABLES_NAT_RULE));
+
+	strcpy(new_rule->target_name, t->u.kernel.target->name);
+	strcpy(new_rule->iniface, e->ip.iniface);
+	strcpy(new_rule->outiface, e->ip.outiface);
+	new_rule->sip = e->ip.src.s_addr; 
+	new_rule->dip = e->ip.dst.s_addr;
+	new_rule->smsk = e->ip.smsk.s_addr;
+	new_rule->dmsk = e->ip.dmsk.s_addr;
+	new_rule->proto = e->ip.proto;
+	new_rule->next = NULL;
+
+	if (fp_user_nat_table[table].rule_chain == NULL) {
+		/* There is no rule in this table yet */
+		fp_user_nat_table[table].rule_chain = new_rule;
+	}
+	else {
+		/* Let's add this rule at the tail of the list */
+		curr_rule = fp_user_nat_table[table].rule_chain;		
+		while (curr_rule->next != NULL)
+			curr_rule = curr_rule->next;
+		curr_rule->next = new_rule;		
+	}
+	return 0;
+}
+
+/* Clear our user NAT rule table */
+void clear_fp_user_nat_table(int table)
+{
+	FP_IPTABLES_NAT_RULE *curr_rule;
+	FP_IPTABLES_NAT_RULE *tmp_rule;
+
+	curr_rule = fp_user_nat_table[table].rule_chain;
+	while (curr_rule != NULL) {
+		tmp_rule = curr_rule;
+		curr_rule = curr_rule->next;
+		kfree(tmp_rule);
+	}
+	fp_user_nat_table[table].rule_chain = NULL;
+}
+
+/* Check if two user NAT rules are equal */
+static int rules_are_equal(FP_IPTABLES_NAT_RULE *r1, FP_IPTABLES_NAT_RULE *r2)
+{
+	if (strcmp(r1->target_name, r2->target_name))
+		return 0;
+
+	if (	(r1->sip != r2->sip) || (r1->dip != r2->dip) || 
+		(r1->smsk != r2->smsk) || (r2->dmsk != r2->dmsk) || 
+		(r1->proto != r2->proto))
+		return 0;
+
+	if (strcmp(r1->iniface, r2->iniface) || strcmp(r1->outiface, r2->outiface))
+		return 0;
+
+	return 1;
+}
+
+/* Check if a rule exists in our user NAT table */
+static int rule_exists_in_table(FP_IPTABLES_NAT_RULE *rule, int table)
+{
+	FP_IPTABLES_NAT_RULE *curr_rule;
+
+	curr_rule = fp_user_nat_table[table].rule_chain;
+	while (curr_rule != NULL) {
+		if (rules_are_equal(rule, curr_rule))
+			return 1;
+		curr_rule = curr_rule->next;
+	}
+	return 0;
+}
+
+/* Compare the two mirror tables to discover which new rules were added, and which rules were deleted */
+void compare_fp_user_nat_tables(void)
+{
+	FP_IPTABLES_NAT_RULE *curr_rule;
+	/* Stage 1: */
+	/* Compare current table to previous one to detect newly added rules */
+	/* For each rule in curr_table: */
+	/* If it exists also in old_table, we don't care */
+	/* If not, it is new */
+	curr_rule = fp_user_nat_table[curr_table].rule_chain;
+	while (curr_rule != NULL) {
+		if (!rule_exists_in_table(curr_rule, old_table)) {
+			fp_handle_user_nat_rule(curr_rule, 1); /* pass 1 for adding a new rule */
+		}
+		curr_rule = curr_rule->next;
+	}
+	
+	/* Stage 2: */
+	/* Compare previous table to current one to detect newly deleted rules */
+	/* For each rule in old_table: */
+	/* If it exists also in curr_table, we don't care */
+	/* If not, it was deleted */
+	curr_rule = fp_user_nat_table[old_table].rule_chain;
+	while (curr_rule != NULL) {
+		if (!rule_exists_in_table(curr_rule, curr_table)) {
+			fp_handle_user_nat_rule(curr_rule, 0); /* pass 0 for deleting a rule */
+		}
+		curr_rule = curr_rule->next;
+	}
+}
+
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+module_exit(fp_exit_module);
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+
+/* Initialize Fast Bridge Rule Database */
+int fp_fdb_db_init(u32 db_size)
+{
+        FP_MGR_DBG(FP_MGR_DBG_INIT, ("FP_MGR: Initializing Bridge Rule Database\n"));
+
+		mgr_fdb_rule_db.rule_chain = NULL;
+		mgr_fdb_rule_db.max_size = db_size;
+
+		return mvFpFdbInit(db_size);
+}
+
+/* Set Bridging information in the FDB database */
+int fp_fdb_info_set(u32 if_bridge, u32 if_index, const u8 *mac, int is_local)
+{
+	unsigned long flags;
+	MV_FP_FDB_RULE rule;
+
+	if (is_local && fp_mgr_if_register(if_bridge, MV_FP_IF_BRG, mv_dev_get_by_index(if_bridge))) {
+		FP_MGR_DBG(FP_MGR_DBG_FDB, ("FDB_MNG: failed to register bridge=%d\n", if_bridge));
+	}
+
+	memset(&rule, 0, sizeof(MV_FP_FDB_RULE));
+	rule.mgmtInfo.actionType = MV_FP_BRIDGE_CMD;
+	rule.mgmtInfo.ruleType = MV_FP_DYNAMIC_RULE; 
+
+	mac_addr_copy(rule.fdbInfo.mac, mac);
+	rule.fdbInfo.ifIndex = if_index;
+	rule.fdbInfo.bridge = if_bridge;
+	rule.fdbInfo.flags = (unsigned short)is_local;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	mvFpFdbRuleSet(&rule);
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+
+/* Delete bridging information in the FDB database */
+int fp_fdb_info_del(u32 if_bridge, u32 if_index, const u8 *mac, int is_local)
+{
+	unsigned long flags;
+	MV_FP_FDB_RULE rule;
+
+	if (is_local && !fp_mgr_if_unregister(if_bridge)) 
+		FP_MGR_DBG(FP_MGR_DBG_FDB, ("FDB_MNG: unregister bridge=%d\n", if_bridge));
+    
+	memset(&rule, 0, sizeof(MV_FP_FDB_RULE));
+
+	mac_addr_copy(rule.fdbInfo.mac, mac);
+	rule.fdbInfo.ifIndex = if_index;
+	rule.fdbInfo.bridge = if_bridge;
+	rule.fdbInfo.flags = (unsigned short)is_local;
+
+	/* has expired */
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	if (!is_local && (mvFpFdbRuleAge(&rule) > 0)) {
+		spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+		return 1; 
+	}
+
+	mvFpFdbRuleDel(&rule);
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+
+/* Clear Fast Path FDB Rule Database */
+int fp_fdb_db_clear(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	mvFpFdbClear();
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+
+/* Print Fast Path FDB Rule Database */
+int fp_fdb_db_print(MV_FP_OP_TYPE op)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	mvFpFdbPrint();
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+
+/* Initialize Rule Database */
+int fp_ppp_db_init(void)
+{
+	FP_MGR_DBG(FP_MGR_DBG_INIT, ("FP_MGR: Initializing PPPoE Rule Database\n"));
+	return mvFpPppInit();
+}
+EXPORT_SYMBOL(fp_ppp_db_init);
+
+/* Set information in the PPP database:
+ * @ifindex - virtual interface, e.g. ppp0
+ * @egress - physical interface, e.g. eth0
+ * @sid - session id
+ * @mac - destination mac
+ */
+int fp_ppp_info_set(u32 if_ppp, u32 if_eth, u16 sid, u8 *mac, u32 channel)
+{
+	unsigned long flags;
+	MV_FP_PPP_RULE rule;
+
+	/* the physical interface is not NFP capable */
+	if (if_eth && fp_mgr_get_iftype(if_eth) != MV_FP_IF_INT)
+		goto out;
+
+	if (if_ppp && fp_mgr_if_register(if_ppp, MV_FP_IF_PPP, mv_dev_get_by_index(if_ppp)))
+        goto out;
+
+	memset(&rule, 0, sizeof(MV_FP_PPP_RULE));
+	rule.mgmtInfo.actionType = MV_FP_PPP_CMD;
+	rule.mgmtInfo.ruleType = MV_FP_DYNAMIC_RULE; 
+
+	if (mac) 
+		mac_addr_copy(rule.pppInfo.u.ppp.da, mac);
+
+	if (if_eth) {
+        	struct net_device* dev = mv_dev_get_by_index(if_eth);
+			mac_addr_copy(rule.pppInfo.u.ppp.sa, dev->dev_addr);
+			rule.pppInfo.u.ppp.tag = 0; /* mvHeader */;
+	}
+
+	rule.pppInfo.u.ppp.ethertype = 0x6488;
+	rule.pppInfo.u.ppp.version  = 0x0011;
+	rule.pppInfo.u.ppp.session = sid;
+	rule.pppInfo.u.ppp.proto = 0x2100;
+
+
+	rule.pppInfo.if_ppp = if_ppp;
+	rule.pppInfo.if_eth = if_eth;
+	rule.pppInfo.channel = channel;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	mvFpPppRuleSet(&rule);
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+out:
+	if (if_ppp >= ETH_FP_IFINDEX_MAX) 
+		printk("ppp device ifindex (%d) is out of range, please reboot your system\n", if_ppp);
+
+	FP_MGR_DBG(FP_MGR_DBG_PPP, ("PPP_MNG: failed to register ppp=%d over eth=%d\n", if_ppp, if_eth));
+	return 1;
+}
+EXPORT_SYMBOL(fp_ppp_info_set);
+
+/* Delete bridging information in the PPP database */
+int fp_ppp_info_del(u32 channel)
+{
+	unsigned long flags;
+	MV_FP_PPP_RULE rule;
+
+	memset(&rule, 0, sizeof(MV_FP_PPP_RULE));
+	rule.pppInfo.channel = channel;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	mvFpPppRuleDel(&rule);
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(fp_ppp_info_del);
+
+/* Clear Fast Path PPP Rule Database */
+int fp_ppp_db_clear(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	mvFpPppClear();
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(fp_ppp_db_clear);
+
+/* Print Fast Path PPP Rule Database */
+int fp_ppp_db_print(MV_FP_OP_TYPE op)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	mvFpPppPrint();
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+
+#endif /* CONFIG_MV_ETH_NFP_PPP */
+
+#ifdef CONFIG_MV_ETH_NFP_SEC
+/* Print Fast Path SEC Rule Database */
+int fp_sec_db_print(MV_FP_OP_TYPE op)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&nfp_mgr_lock, flags);
+	mvNfpSecDbPrint();
+	spin_unlock_irqrestore(&nfp_mgr_lock, flags);
+
+	return 0;
+}
+
+#endif /* CONFIG_MV_ETH_NFP_SEC */
+
+
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_mgr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_mgr.h
new file mode 100755
index 0000000..9f8b113
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_mgr.h
@@ -0,0 +1,224 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+
+/*******************************************************************************
+* mv_nfp_mgr.h - Header File for Marvell NFP Manager
+*
+* DESCRIPTION:
+*       This header file contains macros, typedefs and function declarations 
+* 	specific to the Marvell Network Fast Processing Manager.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __mv_nfp_mgr_h__
+#define __mv_nfp_mgr_h__
+
+/* includes */
+#ifdef CONFIG_MV_ETH_NFP_NAT
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <net/netfilter/nf_nat.h>
+#endif
+#include "eth/nfp/mvNfp.h"
+
+/* defines */
+
+/* enumerations */
+
+typedef enum {
+	MV_FP_MANAGER = 0, 
+	MV_FP_DATABASE = 1
+
+} MV_FP_OP_TYPE;
+
+/* NFP interface type, used for registration */
+typedef enum {
+	MV_FP_IF_INV,   /* Invalid interface */
+	MV_FP_IF_INT,   /* use to register a Marvell GbE interface */
+	MV_FP_IF_BRG,   /* use to register a virtual interface such as bridge */
+	MV_FP_IF_PPP,   /* use to register a virtual interface such as pppoe */
+	MV_FP_IF_EXT    /* use to register an external interface such as WLAN */
+
+} MV_FP_IF_TYPE;
+
+/* data types */
+struct map_eth_devs {
+	MV_FP_IF_TYPE       if_type;
+	struct net_device*  dev;
+    u32                 def_gtw_ip;
+};
+
+extern struct map_eth_devs *fp_eth_devs;
+extern int  fp_disable_flag;
+
+static INLINE int fp_is_enabled(void)
+{
+	return (!fp_disable_flag);
+}
+
+static INLINE MV_FP_IF_TYPE fp_mgr_get_if_type(int if_index)
+{
+    if( (if_index < 0) || (if_index >= ETH_FP_IFINDEX_MAX) )
+    {
+        mvOsPrintf("if_index %d is OUT of RANGE\n", if_index);
+        return MV_FP_IF_INV;
+    }
+    return fp_eth_devs[if_index].if_type;
+}
+
+static INLINE struct net_device* fp_mgr_get_net_dev(int if_index)
+{
+    if( (if_index < 0) || (if_index >= ETH_FP_IFINDEX_MAX) )
+    {
+        mvOsPrintf("if_index %d is OUT of RANGE\n", if_index);
+        return NULL;
+    }
+    return fp_eth_devs[if_index].dev;
+}
+
+/* function headers: */
+
+/* Initialize NFP Manager */
+int fp_mgr_init(void);
+
+/* Register a network interface that works with NFP	  */
+/* Parameters: 						  */
+/* if_index: Linux network interface index 		  */
+/* if_type: interface type (gateway, external)		  */
+/* dev: pointer to the Linux net_device			  */
+/* Returns port number 					  */
+int fp_mgr_if_register(	int if_index, MV_FP_IF_TYPE if_type, 
+			            struct net_device* dev);
+int fp_mgr_if_unregister(int if_index);
+
+/* This function is called when user-space tool disables the NFP.	*/
+/* All databases are cleared, and learning of new rules is disabled	*/
+/* for all types of rules: static, dynamic, arp, routing etc.		*/
+void fp_mgr_disable(void);
+
+/* This function is called when user-space tool enables the NFP.	*/
+int fp_mgr_enable(void);
+
+/* This function is called when user-space tool asks about NFP status (enabled/disabled) */
+int fp_mgr_status(void);
+
+/* Initialize NFP Rule Database (Routing + ARP information table) 	*/
+int fp_rule_db_init(u32 db_size);
+
+/* Initialize NFP NAT Rule Database (SNAT + DNAT table) 		*/
+int fp_nat_db_init(u32 db_size);
+
+/* Initialize NFP Manager ARP Database 					*/
+int fp_arp_db_init(u32 db_size);
+
+/* Clear NFP Rule Database (Routing + ARP information table) 		*/
+int fp_rule_db_clear(void);
+
+/* Clear NFP NAT Rule Database (SNAT + DNAT table) 			*/
+int fp_nat_db_clear(void);
+
+/* Clear NFP Manager ARP Database */
+int fp_arp_db_clear(void);
+
+/* Print NFPRule Database (Routing + ARP information table) */
+int fp_rule_db_print(MV_FP_OP_TYPE);
+
+/* Print NFP NAT Rule Database (SNAT + DNAT table) */
+int fp_nat_db_print(MV_FP_OP_TYPE);
+
+/* Print NFP Manager ARP Database */
+int fp_arp_db_print(void);
+
+/* Set a new rule or update an existing one  */
+/* When looking for an existing rule, search */
+/* a match for SIP, DIP, and default gateway IP */
+/* Rule type is also taken into account: */
+/* a new static rule can overrode an existing rule of any type, */
+/* while a new dynamic rule can only override an existing dynamic rule */
+int fp_rule_set(MV_FP_RULE *rule);
+
+/* Delete an existing rule */
+/* When looking for an existing rule, search */
+/* a match for SIP, DIP */
+int fp_rule_delete(u32 src_ip, u32 dst_ip, MV_FP_RULE_TYPE rule_type);
+
+/* Set Routing information received from the IP stack when a new Routing cache entry is created */
+/* Look for matching ARP information to complete the rule */
+/* If we have a complete rule, update the NFP database */
+int fp_routing_info_set(u32 src_ip, u32 dst_ip, u32 def_gtw_ip, int ingress_if, int egress_if);
+
+/* Delete Routing information from the Routing + ARP database, and update the NFP database */
+int fp_routing_info_delete(u32 src_ip, u32 dst_ip, int iif, int oif);
+
+/* Set ARP information in the ARP database, and update the Routing + ARP database if necessary */
+/* If we have a complete rule, update the NFP database */
+int fp_arp_info_set(int if_index, u32 ip, const u8 *mac);
+
+/* Delete ARP information from the ARP database, and update the Routing + ARP database if necessary */
+/* If a rule became incomplete, update the NFP database */
+int fp_arp_info_delete(u32 ip);
+
+/* Return ARP rule confirmation status */
+int fp_is_arp_confirmed(u32 ip, const u8 *mac);
+
+/* Return routing rule confirmation status */
+int fp_is_route_confirmed(u32 src_ip, u32 dst_ip, int iif, int oif);
+int fp_is_enabled(void);
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+/* Set a new NAT rule, or update an existing one */
+int fp_nat_info_set(	u32 src_ip, u32 dst_ip, u16 src_port, u16 dst_port, u8 proto,  
+			u32 new_src_ip, u32 new_dst_ip, u16 new_src_port, u16 new_dst_port, 
+			int if_index, enum nf_nat_manip_type maniptype);
+
+int fp_nat_info_delete(u32 src_ip, u32 dst_ip, u16 src_port, u16 dst_port, u8 proto);
+
+/* Return NAT rule confirmation status */
+int fp_is_nat_confirmed(u32 src_ip, u32 dst_ip, u16 src_port, u16 dst_port, u8 proto);
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+int fp_fdb_db_init(u32 db_size);
+int fp_fdb_info_set(u32 ifvlan, u32 ifport, const u8 *mac, int is_local);
+int fp_fdb_info_del(u32 ifvlan, u32 ifport, const u8 *mac, int is_local);
+int fp_fdb_db_print(MV_FP_OP_TYPE op);
+int fp_fdb_db_clear(void);
+#endif	/* CONFIG_MV_ETH_NFP_FDB */
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+int fp_ppp_db_print(MV_FP_OP_TYPE op);
+#endif	/* CONFIG_MV_ETH_NFP_PPP */
+#ifdef CONFIG_MV_ETH_NFP_SEC
+int fp_sec_db_print(MV_FP_OP_TYPE op);
+#endif	/* CONFIG_MV_ETH_NFP_SEC */
+
+#endif /* __mv_nfp_mgr_h__ */
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_sec.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_sec.c
new file mode 100755
index 0000000..3da9dcb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/nfp_mgr/mv_nfp_sec.c
@@ -0,0 +1,710 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <asm/scatterlist.h>
+#include <linux/spinlock.h>
+#include "ctrlEnv/sys/mvSysCesa.h"
+#include "cesa/mvCesa.h"
+#include "../../../common/mv802_3.h"
+#include "eth/nfp/mvNfpSec.h"
+#include "mvDebug.h"
+#include "eth/mvEth.h"
+#include "eth-phy/mvEthPhy.h"
+#include "ctrlEnv/sys/mvSysGbe.h"
+#include "../mv_ethernet/mv_netdev.h"
+
+#include "cesa/mvMD5.h"
+#include "cesa/mvSHA1.h"
+
+#include "cesa/mvCesaRegs.h"
+#include "cesa/AES/mvAes.h"
+#include "cesa/mvLru.h"
+
+#undef RT_DEBUG
+#undef dprintk
+#ifdef RT_DEBUG
+#define dprintk(a...)    printk(a)
+#else
+#define dprintk(a...)
+#endif
+
+#define MV_NFP_SEC_MAX_SES	100
+
+extern u32 mv_crypto_base_get(void);
+extern void eth_check_for_tx_done(void);
+extern MV_U8 mvFpPortsGet(MV_IP_HEADER* pIpHdr, MV_U16* pDstPort, MV_U16* pSrcPort);
+
+static struct tasklet_struct nfp_sec_tasklet;
+static spinlock_t 	nfp_sec_lock;
+
+int nfp_sec_sent = 0;
+
+static wait_queue_head_t   nfp_sec_waitq;
+atomic_t req_count;
+static MV_NFP_SEC_CESA_PRIV * req_array[MV_NFP_SEC_REQ_Q_SIZE];
+unsigned int req_empty = 0;
+unsigned int req_ready = 0;
+
+
+/* TBD -  should be used from netdev.c */
+INLINE void  nfp_sec_pkt_info_free(MV_PKT_INFO* pPktInfo)
+{
+	MV_BUF_INFO *pBuf = pPktInfo->pFrags;
+	mv_eth_priv *src_priv = mv_eth_ports[(int)pPktInfo->ownerId];
+	
+	if (pBuf->bufAddrShift) {
+		pBuf->bufPhysAddr += pBuf->bufAddrShift;
+		pBuf->bufVirtPtr += pBuf->bufAddrShift;
+		pBuf->bufAddrShift = 0;
+	}
+/*
+	// for debug:	
+	mvEthRxDoneTest(pBuf, CONFIG_NET_SKB_HEADROOM);
+*/	
+	/* Return to the NFP pool */
+	mvStackPush(src_priv->fpRxPool, (MV_U32)pPktInfo);
+}
+
+/* TDB - move to h file */
+static INLINE MV_VOID mvNfpSecClearRange(MV_U8* addr, MV_U32 size)
+{
+	MV_U32 i;
+	MV_U8  *align;
+
+	align = (MV_U8*)((MV_U32)addr & ~0x1f);
+	
+	for(i = 0; align <= (addr+size); align += CPU_D_CACHE_LINE_SIZE)
+		mvOsCacheLineFlushInv(NULL, align);
+}
+
+static INLINE MV_VOID mvNfpSecInvRange(MV_U8* addr, MV_U32 size)
+{
+	MV_U32 i;
+	MV_U8  *align;
+
+	align = (MV_U8*)((MV_U32)addr & ~0x1f);
+	
+	for(i = 0; align <= (addr+size); align += CPU_D_CACHE_LINE_SIZE)
+		mvOsCacheLineInv(NULL, align);
+}
+
+
+
+static inline void mvNfpSecBuildMac(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY* pSAEntry)
+{
+        MV_802_3_HEADER *pMacHdr;
+
+        pMacHdr = (MV_802_3_HEADER*)((MV_U8 *)(pPktInfo->pFrags[0].bufVirtPtr));
+        memcpy(pMacHdr, &pSAEntry->tunnelHdr.dstMac, 12);
+        pMacHdr->typeOrLen = 0x08;  /* stands for IP protocol code 16bit swapped */          
+	return;	
+}
+
+static void inline 
+nfp_sec_complete_out(unsigned long data) 
+{
+	MV_NFP_SEC_CESA_PRIV *nfp_sec_cesa_priv = (MV_NFP_SEC_CESA_PRIV *)data;
+	MV_U32            if_out,if_type,if_ppp;
+	MV_PKT_INFO       *pPktInfo;
+	MV_BUF_INFO       *pBuf;
+	mv_eth_priv       *out_priv;
+	struct net_device *out_dev;
+	int txq = ETH_DEF_TXQ;
+	MV_STATUS status;
+
+	if_ppp = 0;
+	if_out = nfp_sec_cesa_priv->pSaEntry->tunnelHdr.outIfIndex;
+	if_type = fp_mgr_get_if_type(if_out);
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	if (if_type == MV_FP_IF_PPP)
+	{
+		if_ppp = if_out;
+		if_out = mvFpPppPhyIf(if_ppp);
+		if_type = fp_mgr_get_if_type(if_out);
+	}
+#endif
+	if (if_type != MV_FP_IF_INT)
+	{
+		printk("%s: NFP Tx on ifindex=%d is not supported\n", __FUNCTION__, if_out);
+		nfp_sec_cesa_priv->pSaEntry->stats.dropped++;
+		nfp_sec_pkt_info_free(nfp_sec_cesa_priv->pPktInfo);
+		return;
+	}
+
+	out_dev = fp_mgr_get_net_dev(if_out);
+	out_priv = MV_ETH_PRIV(out_dev);
+
+	pPktInfo = nfp_sec_cesa_priv->pPktInfo;
+	pBuf = pPktInfo->pFrags;
+	pBuf->bufVirtPtr -= MV_NFP_SEC_ESP_OFFSET + ETH_MV_HEADER_SIZE;
+	pBuf->bufPhysAddr -= MV_NFP_SEC_ESP_OFFSET + ETH_MV_HEADER_SIZE;
+	pBuf->dataSize += MV_NFP_SEC_ESP_OFFSET + ETH_MV_HEADER_SIZE;
+	pBuf->bufAddrShift += MV_NFP_SEC_ESP_OFFSET + ETH_MV_HEADER_SIZE;
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	/* PPPoE */
+	if (if_ppp)
+		mvFpPPPoE(if_ppp, pPktInfo, &out_priv->fpStats);
+#endif
+
+#if defined(CONFIG_MV_GATEWAY)
+	if(out_priv->isGtw)
+	{
+		struct mv_vlan_cfg* vlan_cfg = MV_NETDEV_VLAN(out_dev);
+		*(unsigned short *)(pBuf->bufVirtPtr) = vlan_cfg->header;
+		mvOsCacheLineFlushInv(NULL, pBuf->bufVirtPtr);
+	}
+    else
+#endif
+	{
+		pBuf->bufPhysAddr += ETH_MV_HEADER_SIZE;
+		pBuf->dataSize -= ETH_MV_HEADER_SIZE;
+	}
+
+    spin_lock(out_priv->lock);
+	status = mvEthPortTx(out_priv->hal_priv, txq, pPktInfo);
+	spin_unlock(out_priv->lock);
+
+    if (status != MV_OK)
+    {
+		printk("%s: mvEthPortTx failed 0x%x\n", __FUNCTION__, status);
+#ifdef CONFIG_MV_GATEWAY
+		if(!out_priv->isGtw)
+			pBuf->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+#else
+		pBuf->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+#endif /* CONFIG_MV_GATEWAY */
+	
+		nfp_sec_pkt_info_free(pPktInfo);
+		out_dev->stats.tx_dropped++;
+		return;
+	}
+
+	nfp_sec_sent++;
+	out_priv->tx_count[txq]++;
+	out_dev->stats.tx_packets++;
+	out_dev->stats.tx_bytes += pBuf->dataSize;
+	ETH_STAT_DBG( out_priv->eth_stat.tx_hal_ok[txq]++);
+
+#if !defined(ETH_TX_DONE_ISR)
+  	if (nfp_sec_sent > 32)
+    {
+		nfp_sec_sent = 0;
+		eth_check_for_tx_done();
+    }
+#endif /* !ETH_TX_DONE_ISR */
+}
+
+static void inline 
+nfp_sec_complete_in(unsigned long data) 
+{
+	MV_NFP_SEC_CESA_PRIV * nfp_sec_cesa_priv = (MV_NFP_SEC_CESA_PRIV *)data;
+	MV_U8 if_out, proto = 0, *pNewDigest;
+	MV_PKT_INFO *pPktInfo = nfp_sec_cesa_priv->pPktInfo;
+	MV_BUF_INFO *pBuf = pPktInfo->pFrags;
+	MV_NFP_SEC_SA_ENTRY* pSAEntry =  nfp_sec_cesa_priv->pSaEntry;
+	mv_eth_priv  *out_priv;
+	struct net_device *out_dev = NULL;
+	int txq = ETH_DEF_TXQ;
+	MV_STATUS status;
+	MV_U32 dip, sip, calc_digest_off, size;
+	MV_U16 sport = 0, dport = 0;
+	MV_IP_HEADER* pIpHdr;
+	MV_NFP_SEC_SPD_RULE *pSpd;
+
+	/* align pointers to MAC header */
+	size = sizeof(MV_ESP_HEADER) + pSAEntry->ivSize - sizeof(MV_802_3_HEADER);
+	pBuf->bufAddrShift -= size;
+	pBuf->bufVirtPtr += size;
+	pBuf->bufPhysAddr += size;
+	pBuf->dataSize -= (size + pSAEntry->digestSize);
+	calc_digest_off = pBuf->dataSize;
+
+	/* extract parameters for SPD match search */
+	pIpHdr = (MV_IP_HEADER*)(pBuf->bufVirtPtr + sizeof(MV_802_3_HEADER));
+#ifdef	MV_NFP_SEC_5TUPLE_KEY_SUPPORT 
+	proto = mvFpPortsGet(pIpHdr, &dport, &sport);
+#endif
+	dip = pIpHdr->dstIP;
+    sip = pIpHdr->srcIP;
+	
+	/* remove crypto padding */
+	pBuf->dataSize = sizeof(MV_802_3_HEADER) + MV_16BIT_BE(pIpHdr->totalLength);
+
+	/* check what to do with the packet according to SPD */
+	pSpd = mvNfpSecSPDRuleFind(dip, sip, proto, dport, sport, MV_NFP_SEC_RULE_DB_IN);
+	if(pSpd == NULL) {
+		printk("%s(%d): SPD rule not found\n", __FUNCTION__, __LINE__);
+		printk("dip(0x%x) sip(0x%x) proto(0x%x) dport(0x%x) sport(0x%x), dataSize(0x%x)\n",
+			dip, sip, proto, dport, sport, pBuf->dataSize);
+		pBuf->bufVirtPtr -= ETH_MV_HEADER_SIZE;
+		pBuf->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+		pBuf->bufAddrShift += ETH_MV_HEADER_SIZE;
+		nfp_sec_pkt_info_free(pPktInfo);
+		return;
+	}
+
+	/* compare digest */
+	pNewDigest = pBuf->bufVirtPtr + calc_digest_off;
+	if(memcmp(nfp_sec_cesa_priv->orgDigest, pNewDigest, pSAEntry->digestSize)) {
+		printk("%s(%d): ERR. original digest is different from calculated digest(size=%d)\n", __FUNCTION__, __LINE__,calc_digest_off);
+		pBuf->bufVirtPtr -= ETH_MV_HEADER_SIZE;
+		pBuf->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+		pBuf->bufAddrShift += ETH_MV_HEADER_SIZE;
+		nfp_sec_pkt_info_free(pPktInfo);
+		return;
+	}
+
+	/*
+	 * Hub and spoke vpn. Check 2nd tunnel
+	 */
+#ifdef CONFIG_MV_ETH_NFP_SEC_HUB
+	/* ipheader of the original packet */
+	pIpHdr = (MV_IP_HEADER*)(pBuf->bufVirtPtr + sizeof(MV_802_3_HEADER));
+	proto = mvFpPortsGet(pIpHdr, &dport, &sport);
+	sip = pIpHdr->srcIP;
+	dip = pIpHdr->dstIP;
+
+	/* check legitimacy for entring the 2nd tunnel */
+	pSpd = mvNfpSecSPDRuleFind(dip, sip, proto, dport, sport, MV_NFP_SEC_RULE_DB_OUT);
+	if (pSpd && pSpd->actionType == MV_NFP_SEC_SECURE)
+	{
+		pBuf->bufVirtPtr -= ETH_MV_HEADER_SIZE;
+		pBuf->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+		pBuf->dataSize += ETH_MV_HEADER_SIZE;
+		pBuf->bufAddrShift += ETH_MV_HEADER_SIZE;
+
+		status = mvNfpSecOutgoing(pPktInfo, pSpd->pSAEntry);
+		if (status != MV_OK)
+		{
+			if (pSpd->pSAEntry)
+				pSpd->pSAEntry->stats.dropped++;
+			nfp_sec_pkt_info_free(pPktInfo);
+			mvOsPrintf("nfp_sec_complete_in: hub-in-spoke status=%x\n", status);
+		}
+
+		return;
+	}		
+#endif
+
+	/* build MAC header */	
+	mvNfpSecBuildMac(pPktInfo, pSAEntry);
+
+	/* flush & invalidate MAC,IP & TCP headers */ 
+	size = sizeof(MV_802_3_HEADER)+ sizeof(MV_IP_HEADER);
+#ifdef MV_NFP_SEC_5TUPLE_KEY_SUPPORT
+	size += sizeof(MV_TCP_HEADER);
+#endif
+
+	mvNfpSecClearRange(pBuf->bufVirtPtr, size);
+	mvNfpSecInvRange(pNewDigest, pSAEntry->digestSize);
+
+	if_out = pSAEntry->tunnelHdr.outIfIndex;
+	out_dev = fp_mgr_get_net_dev(if_out);
+
+	if(fp_mgr_get_if_type(if_out) != MV_FP_IF_INT)
+	{
+		printk("%s: NFP Tx on ifindex=%d is not supported\n", __FUNCTION__, if_out);
+		pSAEntry->stats.dropped++;
+		nfp_sec_pkt_info_free(pPktInfo);
+		return;
+	}
+
+	pBuf->bufVirtPtr -= ETH_MV_HEADER_SIZE;
+	pBuf->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+	pBuf->dataSize += ETH_MV_HEADER_SIZE;
+	pBuf->bufAddrShift += ETH_MV_HEADER_SIZE;
+
+	out_priv = MV_ETH_PRIV(out_dev);
+
+#if defined(CONFIG_MV_GATEWAY)
+	if(out_priv->isGtw)
+	{
+		struct mv_vlan_cfg* vlan_cfg = MV_NETDEV_VLAN(out_dev);
+		*(unsigned short *)(pBuf->bufVirtPtr) = vlan_cfg->header;
+		mvOsCacheLineFlushInv(NULL, pBuf->bufVirtPtr);
+	}
+    else
+#endif
+	{
+		pBuf->bufPhysAddr += ETH_MV_HEADER_SIZE;
+		pBuf->dataSize -= ETH_MV_HEADER_SIZE;
+	}
+
+	spin_lock(out_priv->lock);
+	status = mvEthPortTx(out_priv->hal_priv, txq, pPktInfo);
+	spin_unlock(out_priv->lock);
+
+    if (status != MV_OK)
+    {
+
+		printk("%s: mvEthPortTx failed 0x%x\n", __FUNCTION__, status);
+#ifdef CONFIG_MV_GATEWAY
+        if(!out_priv->isGtw)
+			pBuf->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+#else
+        	pBuf->bufPhysAddr -= ETH_MV_HEADER_SIZE;
+#endif /* CONFIG_MV_GATEWAY */
+
+		nfp_sec_pkt_info_free(pPktInfo);
+		out_dev->stats.tx_dropped++;
+		return;
+	}
+
+	nfp_sec_sent++;
+	out_priv->tx_count[txq]++;
+	out_dev->stats.tx_packets++;
+	out_dev->stats.tx_bytes += pBuf->dataSize;
+	ETH_STAT_DBG( out_priv->eth_stat.tx_hal_ok[txq]++);
+    
+#if !defined(ETH_TX_DONE_ISR)
+  	if (nfp_sec_sent > 32)
+	{
+		nfp_sec_sent = 0;
+		eth_check_for_tx_done();
+    }
+#endif /* !ETH_TX_DONE_ISR */
+}
+
+
+/*
+ * nfp sec callback. 
+ */
+void
+req_handler(unsigned long dummy)
+{
+	while(atomic_read(&req_count) != 0) {
+		if(req_array[req_ready]->pSaEntry->secOp == MV_NFP_SEC_ENCRYPT)
+			nfp_sec_complete_out((unsigned long)req_array[req_ready]);
+		else
+			nfp_sec_complete_in((unsigned long)req_array[req_ready]);
+		req_ready++;
+		if(req_ready == MV_NFP_SEC_REQ_Q_SIZE)
+			req_ready = 0;
+		
+		atomic_dec(&req_count);
+	}
+
+}
+
+/*
+ * nfp sec Interrupt handler routine.
+ */
+static irqreturn_t
+nfp_sec_interrupt_handler(int irq, void *arg)
+{
+	MV_CESA_RESULT  	result;
+	MV_STATUS               status;
+
+	/* clear interrupts */
+    	MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
+#if defined(MV_CESA_CHAIN_MODE_SUPPORT)
+	while(1) {
+#endif
+	/* Get Ready requests */
+	status = mvCesaReadyGet(&result);
+	if(status != MV_OK)
+	{
+#if !defined(MV_CESA_CHAIN_MODE_SUPPORT)
+		printk("ERROR: Ready get return %d\n",status);
+		return IRQ_HANDLED;
+#else
+			break;
+#endif
+	}	
+
+	/* handle result */
+	// TBD - need to verify return code !!!
+	if(atomic_read(&req_count) > (MV_NFP_SEC_REQ_Q_SIZE - 4)){
+		// must take sure that no tx_done will happen on the same time.. 
+		// maybe should be moved to tasklet to handle.. 
+		MV_NFP_SEC_CESA_PRIV *req_priv = (MV_NFP_SEC_CESA_PRIV *)result.pReqPrv;
+		MV_PKT_INFO *pkt_info = req_priv->pPktInfo;
+		printk("Error: Q request is full - TBD test...\n");
+		pkt_info->pFrags->bufVirtPtr -= (MV_NFP_SEC_ESP_OFFSET + ETH_MV_HEADER_SIZE);
+		pkt_info->pFrags->bufPhysAddr -= (MV_NFP_SEC_ESP_OFFSET + ETH_MV_HEADER_SIZE);
+		nfp_sec_pkt_info_free(pkt_info);
+		return IRQ_HANDLED;
+	}
+	req_array[req_empty] = (MV_NFP_SEC_CESA_PRIV *)result.pReqPrv;
+	req_empty++;
+	if(req_empty == MV_NFP_SEC_REQ_Q_SIZE)
+		req_empty = 0;
+	atomic_inc(&req_count);
+#if defined(MV_CESA_CHAIN_MODE_SUPPORT)
+	}
+#endif
+	tasklet_schedule(&nfp_sec_tasklet);
+
+	return IRQ_HANDLED;
+}
+
+
+static int nfp_sec_add_rule(int dir, u32 spi, char* sa_mac, char* da_mac, 
+	u32 left_peer, u32 right_peer, int if_out, u32 left_sub, u32 right_sub)
+{
+	MV_NFP_SEC_SPD_RULE spd;
+	MV_NFP_SEC_SA_ENTRY sa;
+	MV_CESA_OPEN_SESSION os;
+	unsigned short 	digest_size = 0;
+	int i;
+	unsigned int iv_size;
+	unsigned char sha1Key[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+                               0x24, 0x68, 0xac, 0xe0, 0x24, 0x68, 0xac, 0xe0,
+                               0x13, 0x57, 0x9b, 0xdf};
+	unsigned char cryptoKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+                                 0x02, 0x46, 0x8a, 0xce, 0x13, 0x57, 0x9b, 0xdf};
+
+	memset(&spd, 0, sizeof(MV_NFP_SEC_SPD_RULE));
+	memset(&sa, 0, sizeof(MV_NFP_SEC_SA_ENTRY));
+	memset(&os, 0, sizeof(MV_CESA_OPEN_SESSION));
+
+   	os.cryptoAlgorithm = MV_CESA_CRYPTO_AES;
+	switch(os.cryptoAlgorithm)
+	{
+		case MV_CESA_CRYPTO_DES:
+			iv_size = MV_CESA_DES_BLOCK_SIZE;
+			break;
+		case MV_CESA_CRYPTO_3DES:
+			iv_size = MV_CESA_3DES_BLOCK_SIZE;
+			break;
+		
+		case MV_CESA_CRYPTO_AES:
+			iv_size = MV_CESA_AES_BLOCK_SIZE;
+			break;
+		default:
+			printk("Unknown crypto \n");
+
+	}
+   	os.macMode = MV_CESA_MAC_HMAC_SHA1;
+   	switch(os.macMode)
+   	{
+		case MV_CESA_MAC_MD5:
+		case MV_CESA_MAC_HMAC_MD5:
+			digest_size = MV_CESA_MD5_DIGEST_SIZE;
+			break;
+	
+		case MV_CESA_MAC_SHA1:
+		case MV_CESA_MAC_HMAC_SHA1:
+			digest_size = 12;//MV_CESA_SHA1_DIGEST_SIZE;
+			break;
+	
+		case MV_CESA_MAC_NULL:
+			digest_size = 0;
+			break;
+		}
+
+	os.cryptoMode = MV_CESA_CRYPTO_CBC;
+	if (dir == MV_NFP_SEC_RULE_DB_IN) {
+		os.direction = MV_CESA_DIR_DECODE;
+		os.operation = MV_CESA_MAC_THEN_CRYPTO;
+	}
+	else {
+		os.direction = MV_CESA_DIR_ENCODE;
+		os.operation = MV_CESA_CRYPTO_THEN_MAC;
+	}
+
+   	for(i=0; i<sizeof(cryptoKey); i++)
+       	os.cryptoKey[i] = cryptoKey[i];
+
+	os.cryptoKeyLength = sizeof(cryptoKey);
+
+	for(i=0; i<sizeof(sha1Key); i++)
+       		os.macKey[i] = sha1Key[i];
+
+	os.macKeyLength = sizeof(sha1Key);
+	os.digestSize = digest_size;
+
+	if (MV_OK != mvCesaSessionOpen(&os, (short*)&(sa.sid)))
+	{
+		printk("%s: open session failed\n", __FUNCTION__);
+	}
+
+	sa.digestSize = digest_size;
+	sa.ivSize = iv_size;
+	sa.spi = MV_32BIT_BE(spi);
+	sa.tunProt = MV_NFP_SEC_TUNNEL;
+	sa.encap = MV_NFP_SEC_ESP;
+	sa.seqNum = 0;
+	sa.tunnelHdr.sIp = left_peer;
+	sa.tunnelHdr.dIp = right_peer;
+	sa.tunnelHdr.outIfIndex = if_out;
+	sa.lifeTime = 0; 
+
+	if (dir == MV_NFP_SEC_RULE_DB_IN) 
+		sa.secOp = MV_NFP_SEC_DECRYPT;
+	else
+		sa.secOp = MV_NFP_SEC_ENCRYPT;
+
+	for(i=0; i<6; i++)
+	{
+		sa.tunnelHdr.dstMac[i] = da_mac[i];
+		sa.tunnelHdr.srcMac[i] = sa_mac[i];
+	}
+
+	spd.pSAEntry = mvNfpSecSAEntrySet(&sa, dir);	
+	printk("pSAEntry=%p\n",spd.pSAEntry);
+	if (!spd.pSAEntry)
+		printk("%s: SA creation failed \n", __FUNCTION__);
+
+	spd.sIp = left_sub;
+	spd.dIp = right_sub;
+
+#ifdef	MV_NFP_SEC_5TUPLE_KEY_SUPPORT 
+	spd.dstPort = 0x2;       	// dport: 512
+	spd.srcPort = 0x3;      	// sport: 768
+	spd.proto = MV_IP_PROTO_TCP;
+#endif
+	spd.actionType = MV_NFP_SEC_SECURE;
+
+	if (!mvNfpSecSPDRuleSet(&spd, dir))
+		printk("%s: SPD creation failed \n", __FUNCTION__);
+        
+	return 0;
+}
+
+static void nfp_sec_init_rule(void)
+{
+	unsigned char 	sa_wan[] = {0, 0, 0, 0, 0x61, 0x92};
+	unsigned char 	sa_lan[] = {0, 0, 0, 0, 0x61, 0x93};
+	unsigned char 	da_peer_wan[] = {0x0,0x13,0x20,0x8b,0xbc,0x49};
+	unsigned char 	da_host_lan[] = {0x0,0x15,0x58,0x2F,0xF0,0x39};
+	unsigned char 	da_peer_lan[] = {0x0,0x62,0x81,0x00,0x39,0x01};
+	unsigned char 	null_mac[] = {0, 0, 0, 0, 0, 0};
+
+#if 1
+	/* eth0 */
+	nfp_sec_add_rule(MV_NFP_SEC_RULE_DB_OUT, 0x65060000, sa_wan, da_peer_wan,
+					0x0101a8c0, /* left/sip 192.168.1.1 */
+					0x25d2050A, /* right/dip 10.5.210.37 */
+					1,          /* egress ifindex 1=eth0, 4=ppp0 */
+					0x0a010101,	/* left sub */
+					0x0a020202);/* right sub */
+#else
+	/* ppp0 */
+	nfp_sec_add_rule(MV_NFP_SEC_RULE_DB_OUT, 0x65060000, sa_wan, da_peer_wan,
+					0x05000028, /* left/sip 40.0.0.5  use ppp0 */
+					0x25d2050A, /* right/dip 10.5.210.37 */
+					4,          /* egress ifindex 1=eth0, 4=ppp0 */
+					0x0a010101,	/* left sub */
+					0x0a020202);/* right sub */
+#endif
+
+#if 1
+	/* eth0 */
+	nfp_sec_add_rule(MV_NFP_SEC_RULE_DB_IN, 0x65060000, sa_lan, da_host_lan,  
+					0x25d2050A, /* left/sip 10.5.210.37 */
+					0x0101a8c0, /* right/dip 192.168.1.1 */
+					2,          /* egress ifindex 2=eth1 */
+					0x0a020202,	/* left sub */
+					0x0a010101);/* right sub */
+#else
+	/* ppp0 */
+	nfp_sec_add_rule(MV_NFP_SEC_RULE_DB_IN, 0x65060000, sa_lan, da_host_lan,  
+					0x25d2050A, /* left/sip 10.5.210.37 */
+					0x05000028, /* right/dip 40.0.0.5 */
+					2,          /* egress ifindex 2=eth1 */
+					0x0a020202,	/* left sub */
+					0x0a010101);/* right sub */
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_SEC_HUB
+	/* dummy, will be rerouted to 2nd tunnel on LAN */
+	nfp_sec_add_rule(MV_NFP_SEC_RULE_DB_IN, 0x77070000, null_mac, null_mac,
+					0x6402a8c0, /* sip/remote/peer */
+					0x0102a8c0, /* dip/local/me */
+					4,          /* egress ifindex */
+					0x0a010101,	/* left sub */
+					0x0a020202);/* right sub */
+
+	/* 2nd tunnel on LAN */
+	nfp_sec_add_rule(MV_NFP_SEC_RULE_DB_OUT, 0x77070000, sa_lan, da_peer_lan,  
+					0x0102a8c0, /* left/sip/me 192.168.2.1 */
+					0x6402a8c0, /* right/dip/peer 192.168.2.100 */
+					2,          /* egress ifindex */
+					0x0a020202,	/* left sub */
+					0x0a010101);/* right sub */
+#endif
+}
+
+static int nfp_sec_init(void)
+{
+	spin_lock_init( &nfp_sec_lock );
+	if( MV_OK != mvCesaInit(MV_NFP_SEC_MAX_SES, MV_NFP_SEC_Q_SIZE, (char *)mv_crypto_base_get(),
+				NULL) ) {
+            	printk("%s,%d: mvCesaInit Failed. \n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+	/* clear and unmask Int */
+	MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
+	MV_REG_WRITE( MV_CESA_ISR_MASK_REG, MV_CESA_CAUSE_ACC_DMA_MASK);
+
+	tasklet_init(&nfp_sec_tasklet, req_handler, (unsigned long) 0);
+	/* register interrupt */
+	if( request_irq( CESA_IRQ, nfp_sec_interrupt_handler,
+                             (IRQF_DISABLED) , "cesa", NULL) < 0) {
+            	printk("%s,%d: cannot assign irq %x\n", __FILE__, __LINE__, CESA_IRQ);
+		return EINVAL;
+        }
+
+	mvNfpSecInit(10);
+
+	/* add rules manually */
+	nfp_sec_init_rule();
+    
+	/* use for debug */
+	/* mvNfpSecDbPrint(); */ 
+
+	/* init waitqueue */
+	init_waitqueue_head(&nfp_sec_waitq);
+	
+	atomic_set(&req_count, 0);
+
+	return 0;
+}
+
+
+module_init(nfp_sec_init);
+
+MODULE_LICENSE("Marvell/GPL");
+MODULE_AUTHOR("Ronen Shitrit\Eran Ben Avi");
+MODULE_DESCRIPTION("NFP SEC for CESA crypto");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Kconfig
new file mode 100755
index 0000000..ff696e2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Kconfig
@@ -0,0 +1,127 @@
+menu "Telephony options"
+	depends on MV_INCLUDE_TDM
+
+config  MV_PHONE
+	bool "Support for Marvell telephony(VoIP)"
+	depends on MV_INCLUDE_TDM && PHONE
+	default y
+	---help---
+	  Choosing this option enables the Marvell telephony underlying 
+	  support for various VoIP applications. 
+	  Note, kernel Telephony subsystem must be chosen too.
+
+choice 
+	prompt "TDM Unit"
+	depends on MV_PHONE
+	default MV_TDM_SUPPORT
+
+config MV_TDM_SUPPORT
+	bool "Support legacy TDM(2 channels)"
+
+config MV_COMM_UNIT_SUPPORT
+	depends on ARCH_FEROCEON_KW2
+	bool "Support CommUnit(up to 32 channels)"
+
+endchoice
+
+choice 
+	prompt "SLIC Vendor"
+	depends on MV_PHONE
+	default ZARLINK_SLIC_SUPPORT
+
+config SILABS_SLIC_SUPPORT
+	bool "Support Silicon Labs devices"
+
+config ZARLINK_SLIC_SUPPORT
+	bool "Support Zarlink/Legirity devices"
+
+endchoice
+
+choice 
+	prompt "SLIC Device"
+	depends on MV_PHONE && SILABS_SLIC_SUPPORT
+
+config SILAB_SLIC_SI3226x
+	bool "Support Silicon Labs 3226x device"
+	
+config SILAB_SLIC_SI3217x
+	bool "Support Silicon Labs 3217x device"
+
+endchoice
+
+choice 
+	prompt "SLIC Device"
+	depends on MV_PHONE && ZARLINK_SLIC_SUPPORT
+	default ZARLINK_SLIC_VE880
+
+config ZARLINK_SLIC_VE880
+	bool "Support Zarlink VE880 SLIC family"
+
+config ZARLINK_SLIC_VE890
+	bool "Support Zarlink VE890 SLIC family"
+
+config ZARLINK_SLIC_VE792
+	bool "Support Zarlink VE792 SLIC family"
+
+endchoice
+
+choice 
+	prompt "PCM Clock Frequency"
+	depends on MV_PHONE
+	default MV_TDM_PCM_CLK_8MHZ
+	---help---
+	This menu selects the PCM clock frequency generated by the TDM master.
+	SLIC should be configured accordingly in order to maintain bus coherency.
+ 
+config MV_TDM_PCM_CLK_8MHZ
+	bool "Support 8MHz PCM clock"
+
+config MV_TDM_PCM_CLK_4MHZ
+	bool "Support 4MHz PCM clock"
+
+config MV_TDM_PCM_CLK_2MHZ
+	bool "Support 2MHz PCM clock"
+
+endchoice
+
+choice 
+	prompt "TDM Clock Source"
+	depends on MV_PHONE
+	default MV_TDM_USE_INTERNAL_PCLK_SOURCE
+
+config MV_TDM_USE_INTERNAL_PCLK_SOURCE
+	bool "Support PCLK internally generated"
+
+config MV_TDM_USE_EXTERNAL_PCLK_SOURCE
+	bool "Support PCLK from external source"
+
+config MV_TDM_USE_DCO
+	bool "Support PCLK from DCO enabled PLL"
+
+endchoice
+
+choice 
+	prompt "TDM voice processing"
+	depends on MV_PHONE
+	default MV_TDM_DUMMY
+
+config MV_TDM_DUMMY
+	bool "Support TDM voice processing in softIRQ"
+
+config MV_PHONE_USE_IRQ_PROCESSING
+	bool "Support TDM voice processing in IRQ"
+
+config MV_PHONE_USE_FIQ_PROCESSING
+	bool "Support TDM voice processing in FIQ"
+
+endchoice
+
+config MV_PHONE_USE_SLIC_LIBS
+	bool "Use binary SLIC drivers"
+	depends on MV_PHONE
+	default y
+	---help---
+	Unselect this option only if you have source code of SLIC drivers.
+	If unsure, say "y"
+
+endmenu
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Makefile
new file mode 100755
index 0000000..8374120
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/Makefile
@@ -0,0 +1,163 @@
+
+
+#
+# Makefile for the Marvell Phone Device Driver
+#
+#
+
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+VB_SRC_PATH = ../../mv_hal/voiceband
+LSP_TDM_PATH = tdm
+LSP_SPI_PATH = spi
+LSP_SLIC_PATH = slic
+LSP_TDM_TEST_PATH = tdm/test
+
+obj-$(CONFIG_MV_INCLUDE_TDM) += mv_phone.o
+
+ifeq ($(CONFIG_MV_TDM_SUPPORT),y)
+	PHONE_OBJS = $(VB_SRC_PATH)/tdm/mvTdm.o $(VB_SRC_PATH)/tdm/mvTdmAddrDec.o
+else # CONFIG_MV_COMM_UNIT_SUPPORT
+	PHONE_OBJS = $(VB_SRC_PATH)/commUnit/mvCommUnit.o $(VB_SRC_PATH)/commUnit/mvCommUnitAddrDec.o
+endif
+
+PHONE_OBJS += $(LSP_TDM_PATH)/tdm_if.o $(LSP_TDM_PATH)/tal.o ../../../../../$(MACHINE)/mv_hal_if/mvSysTdm.o
+
+PHONE_OBJS += $(LSP_SPI_PATH)/spi_dev.o
+
+EXTRA_CFLAGS += -DMV_KERNEL_SLIC_SUPPORT
+
+# Silabs support
+ifeq ($(CONFIG_SILABS_SLIC_SUPPORT),y)
+
+	SILABS_BASE_PATH = $(VB_SRC_PATH)/slic/silabs
+	SILABS_SRC_PATH = $(SILABS_BASE_PATH)/src
+	SILABS_CUSTOM_PATH = $(SILABS_BASE_PATH)/custom
+	SILABS_ARCH_MARVELL_PATH = $(VB_SRC_PATH)/slic/silabs/arch_marvell
+	EXTRA_CFLAGS += -I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/silabs/inc \
+			-I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/silabs/custom \
+			-I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell
+
+
+	SILABS_OBJS = $(SILABS_SRC_PATH)/proslic.o \
+				$(SILABS_SRC_PATH)/si_voice.o $(SILABS_SRC_PATH)/si_voice_version.o
+
+	SILABS_CUSTOM_OBJS = $(SILABS_ARCH_MARVELL_PATH)/spi.o $(SILABS_ARCH_MARVELL_PATH)/timer.o
+
+ifeq ($(CONFIG_SILAB_SLIC_SI3226x),y)
+
+	SILABS_OBJS += $(SILABS_SRC_PATH)/si3226x_intf.o
+
+	SILABS_CUSTOM_OBJS += $(SILABS_CUSTOM_PATH)/si3226x_FLBK_constants.o  \
+		$(SILABS_CUSTOM_PATH)/si3226x_patch_B_FB_2010SEP22.o $(SILABS_CUSTOM_PATH)/si3226x_patch_C_FB_2011MAY19.o
+	
+	SLIC_LIB_NAME=silabs_3226x.lib
+endif
+
+ifeq ($(CONFIG_SILAB_SLIC_SI3217x),y)
+
+	SILABS_OBJS += $(SILABS_SRC_PATH)/si3217x_intf.o
+
+	SILABS_CUSTOM_OBJS += $(SILABS_CUSTOM_PATH)/si3217x_FLBK_constants.o  \
+		$(SILABS_CUSTOM_PATH)/si3217x_patch_B_FB_2010DEC16.o
+	
+	SLIC_LIB_NAME=silabs_3217x.lib
+endif
+
+PHONE_OBJS += $(LSP_SLIC_PATH)/silabs_dev.o
+
+endif
+
+# Zarlink support
+ifeq ($(CONFIG_ZARLINK_SLIC_SUPPORT),y)
+
+ifeq ($(CONFIG_ZARLINK_SLIC_VE880),y)
+	ZARLINK_BASE_PATH = $(VB_SRC_PATH)/slic/zarlink/api_lib
+	ZARLINK_COMMON_SRC_PATH = $(ZARLINK_BASE_PATH)/common
+	ZARLINK_ARCH_MARVELL_PATH = $(VB_SRC_PATH)/slic/zarlink/arch_marvell
+	ZARLINK_VP880API_SRC_PATH = $(ZARLINK_BASE_PATH)/vp880_api
+
+	EXTRA_CFLAGS += -I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes \
+			-I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell \
+			-I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/vp880_api
+
+	ZARLINK_OBJS =  $(ZARLINK_COMMON_SRC_PATH)/vp_api_common.o $(ZARLINK_COMMON_SRC_PATH)/vp_api_config.o \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_control.o $(ZARLINK_COMMON_SRC_PATH)/vp_api_cslac_seq.o \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_init.o $(ZARLINK_COMMON_SRC_PATH)/vp_api_query.o \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_test.o $(ZARLINK_COMMON_SRC_PATH)/vp_debug.o \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_abs_calibration.o $(ZARLINK_VP880API_SRC_PATH)/vp880_calibration_common.o \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_control_common.o $(ZARLINK_VP880API_SRC_PATH)/vp880_fxo_control.o \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_fxs_control.o $(ZARLINK_VP880API_SRC_PATH)/vp880_init.o \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_linestate_control.o $(ZARLINK_VP880API_SRC_PATH)/vp880_lp_control.o \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_query.o $(ZARLINK_VP880API_SRC_PATH)/vp880_seq.o \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_tracker_calibration.o \
+			$(ZARLINK_ARCH_MARVELL_PATH)/sys_service.o $(ZARLINK_ARCH_MARVELL_PATH)/vp_hal.o
+
+	SLIC_LIB_NAME=zarlink_880.lib
+endif
+
+ifeq ($(CONFIG_ZARLINK_SLIC_VE890),y)
+	ZARLINK_BASE_PATH = $(VB_SRC_PATH)/slic/zarlink/api_lib
+	ZARLINK_COMMON_SRC_PATH = $(ZARLINK_BASE_PATH)/common
+	ZARLINK_ARCH_MARVELL_PATH = $(VB_SRC_PATH)/slic/zarlink/arch_marvell
+	ZARLINK_VP890API_SRC_PATH = $(ZARLINK_BASE_PATH)/vp890_api
+
+	EXTRA_CFLAGS += -I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes \
+			-I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell \
+			-I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/vp890_api
+
+	ZARLINK_OBJS =  $(ZARLINK_COMMON_SRC_PATH)/vp_api_common.o $(ZARLINK_COMMON_SRC_PATH)/vp_api_config.o \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_control.o $(ZARLINK_COMMON_SRC_PATH)/vp_api_cslac_seq.o \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_init.o $(ZARLINK_COMMON_SRC_PATH)/vp_api_query.o \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_test.o $(ZARLINK_COMMON_SRC_PATH)/vp_debug.o \
+			$(ZARLINK_VP890API_SRC_PATH)/vp890_apiCal.o $(ZARLINK_VP890API_SRC_PATH)/vp890_common.o \
+			$(ZARLINK_VP890API_SRC_PATH)/vp890_config.o $(ZARLINK_VP890API_SRC_PATH)/vp890_control.o \
+			$(ZARLINK_VP890API_SRC_PATH)/vp890_fxo_control.o $(ZARLINK_VP890API_SRC_PATH)/vp890_fxs_control.o \
+			$(ZARLINK_VP890API_SRC_PATH)/vp890_init.o $(ZARLINK_VP890API_SRC_PATH)/vp890_lp_control.o \
+			$(ZARLINK_VP890API_SRC_PATH)/vp890_query.o $(ZARLINK_VP890API_SRC_PATH)/vp890_seq.o \
+			$(ZARLINK_ARCH_MARVELL_PATH)/sys_service.o $(ZARLINK_ARCH_MARVELL_PATH)/vp_hal.o
+
+	SLIC_LIB_NAME=zarlink_890.lib
+endif
+
+ifeq ($(CONFIG_ZARLINK_SLIC_VE792),y)
+
+	ZARLINK_BASE_PATH = $(VB_SRC_PATH)/slic/zarlink/vp792_api_lib
+	ZARLINK_COMMON_SRC_PATH = $(ZARLINK_BASE_PATH)/common
+	ZARLINK_ARCH_MARVELL_PATH = $(VB_SRC_PATH)/slic/zarlink/arch_marvell
+	ZARLINK_VP792API_SRC_PATH = $(ZARLINK_BASE_PATH)/vp792_api
+
+	EXTRA_CFLAGS += -I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes \
+			-I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell \
+			-I$(srctree)/$(MACHINE)/../plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/vp792_api
+
+	ZARLINK_OBJS =  $(ZARLINK_COMMON_SRC_PATH)/vp_api_config.o  $(ZARLINK_COMMON_SRC_PATH)/vp_api_common.o \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_init.o  $(ZARLINK_COMMON_SRC_PATH)/vp_api_query.o \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_control.o $(ZARLINK_COMMON_SRC_PATH)/vp_debug.o \
+			$(ZARLINK_VP792API_SRC_PATH)/vp792_common.o $(ZARLINK_VP792API_SRC_PATH)/vp792_config.o \
+			$(ZARLINK_VP792API_SRC_PATH)/vp792_control.o $(ZARLINK_VP792API_SRC_PATH)/vp792_init.o \
+			$(ZARLINK_VP792API_SRC_PATH)/vp792_query.o $(ZARLINK_VP792API_SRC_PATH)/vp792_firmware.o \
+			$(ZARLINK_ARCH_MARVELL_PATH)/sys_service.o $(ZARLINK_ARCH_MARVELL_PATH)/vp_hal.o \
+			$(ZARLINK_ARCH_MARVELL_PATH)/Le71HP0410G_init.o
+
+	SLIC_LIB_NAME=zarlink_792.lib
+
+endif
+
+PHONE_OBJS += $(LSP_SLIC_PATH)/vpapi_dev.o
+
+endif
+
+ifeq ($(CONFIG_MV_PHONE_USE_SLIC_LIBS),y)
+$(obj)/lib.a:
+	cp $(obj)/$(LSP_SLIC_PATH)/libs/$(SLIC_LIB_NAME) $(obj)/lib.a
+else
+	lib-y := $(ZARLINK_OBJS) $(SILABS_OBJS)
+endif
+
+obj-y := mv_phone.o $(LSP_TDM_TEST_PATH)/
+
+mv_phone-objs := $(PHONE_OBJS) $(SILABS_CUSTOM_OBJS) lib.a
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/silabs_3217x.lib b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/silabs_3217x.lib
new file mode 100755
index 0000000..2b77dac
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/silabs_3217x.lib
Binary files differ
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/silabs_3226x.lib b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/silabs_3226x.lib
new file mode 100755
index 0000000..ede8a9b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/silabs_3226x.lib
Binary files differ
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_792.lib b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_792.lib
new file mode 100755
index 0000000..9fd4522
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_792.lib
Binary files differ
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_880.lib b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_880.lib
new file mode 100755
index 0000000..efc3a84
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_880.lib
Binary files differ
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_890.lib b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_890.lib
new file mode 100755
index 0000000..7c1b195
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/libs/zarlink_890.lib
Binary files differ
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/silabs_dev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/silabs_dev.c
new file mode 100755
index 0000000..d410cb1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/silabs_dev.c
@@ -0,0 +1,940 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include "silabs_dev.h"
+#include "spi.h"
+#include "timer.h"
+#include "boardEnv/mvBoardEnvLib.h"
+
+/* SI3226 */
+#if defined(CONFIG_SILAB_SLIC_SI3226x)
+#define NUMBER_OF_DEVICES 1 
+#define NUMBER_OF_PROSLIC NUMBER_OF_DEVICES
+#define CHAN_PER_DEVICE 2
+#define NUMBER_OF_CHAN (NUMBER_OF_DEVICES*CHAN_PER_DEVICE) 
+#define PROSLIC_DEVICE_TYPE SI3226X_TYPE
+#endif
+
+/* SI3217 */
+#if defined(CONFIG_SILAB_SLIC_SI3217x)
+#define NUMBER_OF_DEVICES 1 
+#define NUMBER_OF_PROSLIC NUMBER_OF_DEVICES
+#define CHAN_PER_DEVICE 1
+#define NUMBER_OF_CHAN (NUMBER_OF_DEVICES*CHAN_PER_DEVICE) 
+#define PROSLIC_DEVICE_TYPE SI3217X_TYPE
+#endif
+
+/* Defines */
+#define GET_DEV_STATUS(deviceNum)	silabs_dev_status[deviceNum]
+#define GET_LINE_STATUS(chanNum)	silabs_line_status[chanNum]
+#define REGISTER_DEVICE(deviceNum)	silabs_dev_status[deviceNum] = 1;
+#define REGISTER_LINE(chanNum)		silabs_line_status[chanNum] = 1;
+#define MAX_PROFILE_SIZE			128
+#define GET_DEVICE(chanNum)			(chanNum / CHAN_PER_DEVICE)
+#define GET_LINE(chanNum)			(chanNum % CHAN_PER_DEVICE)
+#define MAX_EVENT_QUEUE_SIZE		256
+#define SILABS_TICK_TIMER_PERIOD	1
+#define SILABS_MOD_NAME				"silabs"
+#define SLIC_TIMER_EVENT_SUPPORT
+
+static void silabs_tick_handler(unsigned long data);
+static ssize_t silabs_read(struct file *file, char __user *buf, size_t size, loff_t * ppos);
+static ssize_t silabs_write(struct file *file, const char __user *buf, size_t size, loff_t * ppos);
+static unsigned int silabs_poll(struct file *pFile, poll_table *pPollTable);
+static int silabs_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg);
+static int silabs_open(struct inode *pInode, struct file *pFile);
+static int silabs_release(struct inode *pInode, struct file *pFile);
+//static int __init silabs_module_init(void);
+//static void __exit silabs_module_exit(void);
+
+/* SI-API-II Dispatchers */
+static int silabs_control_interface(unsigned long arg);
+static int silabs_register_access(unsigned long arg);
+static int silabs_device_init(unsigned long arg);
+static int silabs_channel_all(unsigned long arg);
+static int silabs_channel_init(unsigned long arg);
+static int silabs_channel_setup(unsigned long arg);
+static int silabs_channel_operation(unsigned long arg);
+static int silabs_PCM_TS_setup(unsigned long arg);
+static int silabs_get_event(unsigned long arg);
+static int silabs_channel_set_line_feed(unsigned long arg);
+static int silabs_channel_read_hook_status(unsigned long arg);
+static int silabs_channel_set_loopback(unsigned long arg);
+
+#if defined(CONFIG_SILAB_SLIC_SI3226x)
+extern Si3226x_General_Cfg Si3226x_General_Configuration;
+#endif
+#if defined(CONFIG_SILAB_SLIC_SI3217x)
+extern Si3217x_General_Cfg Si3217x_General_Configuration;
+#endif
+
+/* Enumurators */
+typedef struct {
+	unsigned char valid;		/* valid event */
+	
+	SiEventType si_event;
+} silabs_event;
+
+typedef struct _chanState {
+	proslicChanType_ptr		ProObj;
+} chanState;
+
+/* Structs */
+static struct file_operations silabs_fops = {
+    owner:      THIS_MODULE,
+    llseek:     NULL,
+    read:       silabs_read,
+    write:      silabs_write,
+    poll:       silabs_poll,
+    ioctl:      silabs_ioctl,
+    open:       silabs_open,
+    release:    silabs_release,
+    fasync:     NULL
+};
+
+/* Globals */
+static chanState ports[NUMBER_OF_CHAN];			/* User’s channel object, which has a member defined as proslicChanType_ptr ProObj */
+static controlInterfaceType *ProHWIntf; 		/* Define ProSLIC control interface object */
+static ProslicDeviceType *ProSLICDevices[NUMBER_OF_PROSLIC];	/* Define array of ProSLIC device objects */
+static proslicChanType_ptr arrayOfProslicChans[NUMBER_OF_CHAN];
+ctrl_S spiGciObj;
+
+static DEFINE_SPINLOCK(silabs_lock);
+static DECLARE_WAIT_QUEUE_HEAD(silabs_wait);
+static atomic_t event_count;
+static atomic_t silabs_init;
+static atomic_t silabs_in_ioctl;
+static silabs_event event_queue[MAX_EVENT_QUEUE_SIZE];
+static u8 silabs_dev_status[NUMBER_OF_DEVICES];
+static u8 silabs_line_status[NUMBER_OF_CHAN];
+static volatile u32 next_event = 0, curr_event = 0;
+static struct timer_list silabs_timer;
+static u16 total_devs = 0, total_lines = 0;
+
+static struct miscdevice silabs_misc_dev = {
+	.minor = SLICDEV_MINOR,
+ 	.name = SILABS_MOD_NAME,
+ 	.fops = &silabs_fops,
+};
+
+static ssize_t silabs_read(struct file *file, char __user *buf, size_t size, loff_t * ppos)
+{
+	return 0;
+}
+
+static ssize_t silabs_write(struct file *file, const char __user *buf, size_t size, loff_t * ppos)
+{
+	return 0;
+}
+
+static unsigned int silabs_poll(struct file *pFile, poll_table *pPollTable)
+{
+	int mask = 0;
+
+	poll_wait(pFile, &silabs_wait, pPollTable);
+	
+	if(atomic_read(&event_count) > 0) {
+		mask |= POLLPRI;
+	}
+
+	return mask;
+}
+
+static int silabs_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg)
+{
+	int ret = 0;
+
+	/* Argument checking */
+	if (_IOC_TYPE(cmd) != SILABS_MOD_IOCTL_MAGIC) {
+		printk("%s: invalid SILABS MOD Magic Num %i %i\n", __func__, _IOC_TYPE(cmd), SILABS_MOD_IOCTL_MAGIC);
+		return -ENOTTY;
+	}
+
+	if ((_IOC_NR(cmd) > SILABS_MOD_IOCTL_MAX) || (_IOC_NR(cmd) < SILABS_MOD_IOCTL_MIN)) {
+		printk("%s: invalid SILABS MOD IOCTL request\n", __func__);
+		return -ENOTTY;
+	}
+
+	if (_IOC_DIR(cmd) & _IOC_READ) {
+		ret = !access_ok(VERIFY_WRITE, (void __user*)arg, _IOC_SIZE(cmd));
+	} 
+	else if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		ret = !access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd));
+	}
+
+	if (ret) {
+		printk("%s: invalid SILABS MOD access type %i from cmd %i\n", __func__, _IOC_DIR(cmd), cmd);
+		return -EFAULT;
+	}
+
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+	/* Disable timer routine processing */
+	atomic_set(&silabs_in_ioctl, 1);
+#endif
+
+	switch (cmd) {
+		
+		case SILABS_MOD_IOX_CTRL_IF:
+			printk("ioctl: SILABS_MOD_IOX_CTRL_IF\n");
+			ret = silabs_control_interface(arg);	
+			break;
+		
+		case SILABS_MOD_IOX_DEVICE_INIT:
+			printk("ioctl: SILABS_MOD_IOX_DEVICE_INIT\n");
+			ret = silabs_device_init(arg);
+			break;
+
+		case SILABS_MOD_IOX_CHAN_ALL:
+			printk("ioctl: SILABS_MOD_IOX_CHAN_ALL\n");
+			ret = silabs_channel_all(arg);
+			break;
+
+		case SILABS_MOD_IOX_CHAN_INIT:
+			printk("ioctl: SILABS_MOD_IOX_CHAN_INIT\n");
+			ret  = silabs_channel_init(arg);
+			break;
+
+		case SILABS_MOD_IOX_CHAN_SETUP:
+			printk("ioctl: SILABS_MOD_IOX_CHAN_SETUP\n");
+			ret = silabs_channel_setup(arg);
+			break;
+
+		case SILABS_MOD_IOX_CHAN_OP:
+			printk("ioctl: SILABS_MOD_IOX_CHAN_OP\n");
+			ret = silabs_channel_operation(arg);
+			break;
+
+		case SILABS_MOD_IOX_PCM_TS_SETUP:
+			printk("ioctl: SILABS_MOD_IOX_PCM_TS_SETUP\n");
+			ret = silabs_PCM_TS_setup(arg);
+			break;
+
+		case SILABS_MOD_IOX_GET_EVENT:
+//			printk("ioctl: SILABS_MOD_IOX_GET_EVENT\n");
+			ret = silabs_get_event(arg);
+			break;
+		
+		case SILABS_MOD_IOX_REG_CTRL:
+			printk("ioctl: SILABS_MOD_IOX_REG_CTRL\n");
+			ret = silabs_register_access(arg);
+			break;
+			
+		case SILABS_MOD_IOX_CHAN_LINE_FEED:
+			printk("ioctl: SILABS_MOD_IOX_CHAN_LINE_FEED\n");
+			ret = silabs_channel_set_line_feed(arg);
+			break;
+	
+		case SILABS_MOD_IOX_CHAN_HOOK_STATUS:
+			printk("ioctl: SILABS_MOD_IOX_CHAN_HOOK_STATUS\n");
+			ret = silabs_channel_read_hook_status(arg);
+			break;
+
+		case SILABS_MOD_IOX_CHAN_LOOPBACK:
+			printk("ioctl: SILABS_MOD_IOX_CHAN_LOOPBACK\n");
+			ret = silabs_channel_set_loopback(arg);
+			break;
+
+		default:
+			printk("%s: error, ioctl command(0x%x) not supported !!!\n", __func__, cmd);
+			ret = -EFAULT;
+			break;
+	}
+
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+	/* Enable timer routine processing */
+	atomic_set(&silabs_in_ioctl, 0);
+#endif
+
+	return ret;
+}
+
+static int silabs_register_access(unsigned long arg)
+{
+	SilabsRegObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsRegObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (data.func) {
+		case SI_REG_READ:
+			data.value = ctrl_ReadRegisterWrapper (&spiGciObj, data.chanNum, data.regAddr);
+			break;
+		case SI_REG_WRITE:
+			ctrl_WriteRegisterWrapper(&spiGciObj, data.chanNum, data.regAddr, data.value);
+			break;
+		case SI_RAM_READ:
+			data.ramValue = ctrl_ReadRAMWrapper (&spiGciObj, data.chanNum, data.ramAddr);
+			break;
+		case SI_RAM_WRITE:
+			ctrl_WriteRAMWrapper(&spiGciObj, data.chanNum, data.ramAddr, data.ramValue);
+			break;
+		default:
+			printk("%s: error, function (0x%x) not supported !!!\n", __func__, data.func);
+			return  -EFAULT;
+	}
+	
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsRegObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_control_interface(unsigned long arg)
+{
+	SilabsModCtrlObjType data;
+
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModCtrlObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (data.func) {
+		case SI_IF_CREATE:
+#if defined(CONFIG_SILAB_SLIC_SI3226x)
+			Si3226x_General_Configuration.irqen2 = 0x3;
+#endif
+#if defined(CONFIG_SILAB_SLIC_SI3217x)
+			Si3217x_General_Configuration.irqen2 = 0x3;
+#endif			
+			data.status = ProSLIC_createControlInterface (&ProHWIntf);
+			break;
+		case SI_IF_DESTROY:
+			data.status = ProSLIC_destroyControlInterface (&ProHWIntf);
+			break;
+		case SI_IF_SET_FUNCS:
+			ProSLIC_setControlInterfaceCtrlObj (ProHWIntf, &spiGciObj);
+			ProSLIC_setControlInterfaceReset (ProHWIntf, ctrl_ResetWrapper);
+			ProSLIC_setControlInterfaceWriteRegister (ProHWIntf, ctrl_WriteRegisterWrapper);
+			ProSLIC_setControlInterfaceReadRegister (ProHWIntf, ctrl_ReadRegisterWrapper);
+			ProSLIC_setControlInterfaceWriteRAM (ProHWIntf, ctrl_WriteRAMWrapper);
+			ProSLIC_setControlInterfaceReadRAM (ProHWIntf, ctrl_ReadRAMWrapper);
+			ProSLIC_setControlInterfaceTimerObj (ProHWIntf, NULL);
+			ProSLIC_setControlInterfaceDelay (ProHWIntf, time_DelayWrapper);
+			ProSLIC_setControlInterfaceTimeElapsed (ProHWIntf, NULL);
+			ProSLIC_setControlInterfaceGetTime (ProHWIntf, NULL);
+			ProSLIC_setControlInterfaceSemaphore (ProHWIntf, NULL);
+
+			break;
+		default:
+			printk("%s: error, function (0x%x) not supported !!!\n", __func__, data.func);
+			return  -EFAULT;
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModCtrlObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_device_init(unsigned long arg)
+{
+	SilabsModDevObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModDevObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (data.func) {
+		case SI_DEVICE_CREATE:
+			data.status = ProSLIC_createDevice (&(ProSLICDevices[data.devNum]));
+			total_devs++;
+			REGISTER_DEVICE(data.devNum);
+	
+			break;
+		case SI_DEVICE_DESTROY:
+			data.status = ProSLIC_destroyDevice (&(ProSLICDevices[data.devNum]));
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+			if(total_lines == 0) {
+				atomic_set(&silabs_init, 0);
+				del_timer(&silabs_timer);
+			}
+#endif
+			break;
+		default:
+			printk("%s: error, function (0x%x) not supported !!!\n", __func__, data.func);
+			return  -EFAULT;
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModDevObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_channel_all(unsigned long arg)
+{
+	SilabsModChannelAllObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModChannelAllObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (data.func) {
+		case SI_CHANNEL_ALL_INIT:
+			data.status = ProSLIC_Init(arrayOfProslicChans, NUMBER_OF_CHAN);
+			break;
+		case SI_CHANNEL_ALL_CAL:
+			data.status = ProSLIC_Cal(arrayOfProslicChans, NUMBER_OF_CHAN);
+			break;
+		case SI_CHANNEL_ALL_LBCAL:
+			data.status = ProSLIC_LBCal(arrayOfProslicChans, NUMBER_OF_CHAN);
+			break;
+		default:
+			printk("%s: error, function (0x%x) not supported !!!\n", __func__, data.func);
+			return  -EFAULT;
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModChannelAllObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+
+}
+
+static int silabs_channel_init(unsigned long arg)
+{
+	SilabsModChannelObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModChannelObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (data.func) {
+		case SI_CHANNEL_CREATE:
+			data.status = ProSLIC_createChannel (&(ports[data.chanNum].ProObj));
+			REGISTER_LINE(data.chanNum);
+			break;
+		case SI_CHANNEL_DESTROY:
+			data.status = ProSLIC_destroyChannel (&(ports[data.chanNum].ProObj));
+			break;
+		case SI_CHANNEL_BC_INIT:
+			data.status = ProSLIC_InitBroadcast (&(ports[data.chanNum].ProObj));
+			break;
+		case SI_CHANNEL_SW_INIT:
+			data.status = ProSLIC_SWInitChan (ports[data.chanNum].ProObj, data.chanNum,
+						PROSLIC_DEVICE_TYPE, ProSLICDevices[GET_DEVICE(data.chanNum)], ProHWIntf);
+
+			arrayOfProslicChans[data.chanNum] = ports[data.chanNum].ProObj;
+			ProSLIC_setSWDebugMode(ports[data.chanNum].ProObj,TRUE);  /* optional */ 
+			break;
+		default:
+			printk("%s: error, function (0x%x) not supported !!!\n", __func__, data.func);
+			return  -EFAULT;
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModChannelObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_channel_setup(unsigned long arg)
+{
+	SilabsModChannelSetupObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModChannelSetupObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (data.func) {
+		case SI_CHANNEL_SETUP_RING:
+			data.status = ProSLIC_RingSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_TONEGEN:
+			data.status = ProSLIC_ToneGenSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_FSK:
+			data.status = ProSLIC_FSKSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_DTMF_DECODE:
+			data.status = ProSLIC_DTMFDecodeSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_ZSYNTH:
+			data.status = ProSLIC_ZsynthSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_GCICI:
+			data.status = ProSLIC_GciCISetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_MODEM_DET:
+			data.status = ProSLIC_ModemDetSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_TX_AUDIO_GAIN:
+			data.status = ProSLIC_TXAudioGainSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_RX_AUDIO_GAIN:
+			data.status = ProSLIC_RXAudioGainSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_DC_FEED:
+			data.status = ProSLIC_DCFeedSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_PULSE_METER:
+			data.status = ProSLIC_PulseMeterSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		case SI_CHANNEL_SETUP_PCM:
+			data.status = ProSLIC_PCMSetup (ports[data.chanNum].ProObj, data.preset);
+			break;
+		default:
+			printk("%s: error, function (0x%x) not supported !!!\n", __func__, data.func);
+			return  -EFAULT;
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModChannelSetupObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_channel_operation(unsigned long arg)
+{
+	SilabsModChannelOpObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModChannelOpObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	switch (data.func) {
+		case SI_CHANNEL_OP_RESET:
+			data.status = ProSLIC_Reset (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_CLEAR_ERR:
+			data.status = ProSLIC_clearErrorFlag (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_GPIO_SETUP:
+			data.status = ProSLIC_GPIOSetup (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_VERIFY_CTRL_IF:
+			data.status = ProSLIC_VerifyControlInterface (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_SHUT_DOWN_CHAN:
+			data.status = ProSLIC_ShutdownChannel (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_RING_START:
+			data.status = ProSLIC_RingStart (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_RING_STOP:
+			data.status = ProSLIC_RingStop (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_ENA_CID:
+			data.status = ProSLIC_EnableCID (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_DIS_CID:
+			data.status = ProSLIC_DisableCID (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_PLL_FREE_RUN_START:
+			data.status = ProSLIC_PLLFreeRunStart (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_PLL_FREE_RUN_STOP:
+			data.status = ProSLIC_PLLFreeRunStop (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_PULSE_METER_START:
+			data.status = ProSLIC_PulseMeterStart (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_PULSE_METER_STOP:
+			data.status = ProSLIC_PulseMeterStop (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_PWR_UP_CONV:
+			data.status = ProSLIC_PowerUpConverter (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_PWR_DOWN_CONV:
+			data.status = ProSLIC_PowerDownConverter (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_ENA_INT:
+			data.status = ProSLIC_EnableInterrupts (ports[data.chanNum].ProObj);
+					
+			if(!atomic_read(&silabs_init)) {
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+				memset(&silabs_timer, 0, sizeof(struct timer_list));
+				init_timer(&silabs_timer);
+				silabs_timer.function = silabs_tick_handler;
+				silabs_timer.data = -1;
+				silabs_timer.expires = jiffies + SILABS_TICK_TIMER_PERIOD;
+				add_timer(&silabs_timer);
+#endif
+				atomic_set(&silabs_init, 1);
+			}
+			break;
+		case SI_CHANNEL_OP_PCM_START:
+			data.status = ProSLIC_PCMStart (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_PCM_STOP:
+			data.status = ProSLIC_PCMStop (ports[data.chanNum].ProObj);
+			break;
+		case SI_CHANNEL_OP_TONE_GEN_START:
+			data.status = ProSLIC_ToneGenStart (ports[data.chanNum].ProObj, 0);
+			break;
+		case SI_CHANNEL_OP_TONE_GEN_STOP:
+			data.status = ProSLIC_ToneGenStop (ports[data.chanNum].ProObj);
+			break;
+		default:
+			printk("%s: error, function (0x%x) not supported !!!\n", __func__, data.func);
+			return  -EFAULT;
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModChannelOpObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_PCM_TS_setup(unsigned long arg)
+{
+	SilabsModPCMTSSetupObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModPCMTSSetupObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	data.status = ProSLIC_PCMTimeSlotSetup(ports[data.chanNum].ProObj, data.rxcount, data.txcount);
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModPCMTSSetupObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_channel_set_line_feed(unsigned long arg)
+{
+	SilabsModChannelLineFeedObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModChannelLineFeedObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	data.status = ProSLIC_SetLinefeedStatus(ports[data.chanNum].ProObj, data.newLineFeed);
+	
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModChannelLineFeedObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+
+int silabs_get_event(unsigned long arg)
+{
+	SilabsModGetEventType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModGetEventType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	if(atomic_read(&event_count) == 0) {
+		data.newEvent = FALSE;
+	}
+	else {
+		/* Copy event info back to user */
+		if(copy_to_user(data.pEvent, &event_queue[curr_event].si_event, sizeof(SiEventType))) {
+			printk("%s: copy_to_user failed\n", __func__);
+			return  -EFAULT;
+		}
+
+		event_queue[curr_event].valid = 0;
+		data.newEvent = TRUE;
+		atomic_dec(&event_count);
+		curr_event++;
+		if(curr_event == MAX_EVENT_QUEUE_SIZE)
+			curr_event = 0;
+	}
+
+	/* Copy status and event info back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModGetEventType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_channel_read_hook_status(unsigned long arg)
+{
+	SilabsModChannelReadHookStatObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModChannelReadHookStatObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	data.status = ProSLIC_ReadHookStatus (ports[data.chanNum].ProObj, &data.hookStatus);
+	
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModChannelReadHookStatObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_channel_set_loopback(unsigned long arg)
+{
+	SilabsModChannelSetLoopbackObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SilabsModChannelSetLoopbackObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	data.status = ProSLIC_SetLoopbackMode (ports[data.chanNum].ProObj, data.newMode);
+	
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SilabsModChannelSetLoopbackObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int silabs_open(struct inode *pInode, struct file *pFile)
+{
+	try_module_get(THIS_MODULE);
+	return 0;
+}
+
+static int silabs_release(struct inode *pInode, struct file *pFile)
+{
+	module_put(THIS_MODULE);
+	return 0;
+}
+
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+static void silabs_tick_handler(unsigned long data)
+{
+	u8 chanNum;
+	unsigned long flags;
+	
+	silabs_event *pEvent;
+	
+	proslicIntType siEvent;
+	ProslicInt irqs[MAX_PROSLIC_IRQS];
+	
+	/* Check if events are already active and not processing IOCTL */
+	if ((atomic_read(&silabs_init) == 0) || (atomic_read(&silabs_in_ioctl) == 1))
+		goto timer_exit;
+
+	spin_lock_irqsave(&silabs_lock, flags);
+
+	siEvent.irqs = irqs;
+
+	for (chanNum = 0; chanNum < NUMBER_OF_CHAN; chanNum++) {
+		
+		if (GET_LINE_STATUS(chanNum) == 0)
+			continue;
+
+		siEvent.number = 0;
+
+		/* Check for free resources */
+		if (atomic_read(&event_count) >= MAX_EVENT_QUEUE_SIZE)
+			goto timer_exit;
+
+		if (ProSLIC_GetInterrupts(ports[chanNum].ProObj, &siEvent)) {
+
+			printk("We got new %d events! \n", siEvent.number);
+	
+			pEvent = &event_queue[next_event];
+			pEvent->si_event.chanNum = chanNum;
+			pEvent->si_event.devNum = GET_DEVICE(chanNum);
+			pEvent->si_event.eventsNum = siEvent.number;
+			memcpy(pEvent->si_event.irqs, siEvent.irqs, sizeof(ProslicInt)*MAX_PROSLIC_IRQS);
+				
+			next_event++;
+			
+			if (next_event == MAX_EVENT_QUEUE_SIZE)
+				next_event = 0;
+
+			atomic_inc(&event_count);
+		
+			if (pEvent->valid == 0) {
+				pEvent->valid = 1;
+			} else {
+				printk("%s: error, event(%u) was overrided\n", __func__, next_event);
+				break;
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&silabs_lock, flags);
+
+timer_exit:
+
+	/* Checks if user application should be signaled */
+	if (atomic_read(&event_count) > 0) {
+		wake_up_interruptible(&silabs_wait);
+	}
+
+	/* Schedule next timer tick */
+	silabs_timer.expires = jiffies + SILABS_TICK_TIMER_PERIOD;
+    	add_timer(&silabs_timer);
+}
+#endif
+
+int __init silabs_module_init(void)
+{
+	int status = 0;
+
+	printk("Loading Marvell %s device\n", SILABS_MOD_NAME);
+	
+	status = misc_register(&silabs_misc_dev);
+
+	/* Register SILABS device module */
+	if (status < 0) {
+		printk("Error, failed to load %s module(%d)\n", SILABS_MOD_NAME, status);
+		return status;
+	}
+
+	atomic_set(&silabs_init, 0);
+	atomic_set(&silabs_in_ioctl, 0);
+	total_devs = 0;
+	total_lines = 0;
+	next_event = 0;
+	curr_event = 0;
+	memset(silabs_dev_status, 0, NUMBER_OF_DEVICES);
+	memset(silabs_line_status, 0, NUMBER_OF_CHAN);
+	
+	/* Reset event counter */
+	atomic_set(&event_count, 0);
+
+	/* Clear event queue */
+	memset(event_queue, 0, (MAX_EVENT_QUEUE_SIZE * sizeof(silabs_event)));
+	
+	spiGciObj.portID = mvBoardTdmSpiIdGet();
+	SPI_Init (&spiGciObj);
+
+	return 0;
+}
+
+void __exit silabs_module_exit(void)
+{
+	printk("Unloading %s device module\n", SILABS_MOD_NAME);
+
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+	if(total_lines == 0)
+		del_timer(&silabs_timer);
+#endif
+
+	/* Unregister SILABS misc device */
+	misc_deregister(&silabs_misc_dev);
+
+	return;
+}
+
+/* Module stuff */
+module_init(silabs_module_init);
+module_exit(silabs_module_exit);
+MODULE_DESCRIPTION("Silicon Labs Proslic Device");
+MODULE_AUTHOR("Nadav Haklai <nadavh@marvell.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/silabs_dev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/silabs_dev.h
new file mode 100755
index 0000000..f928fb0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/silabs_dev.h
@@ -0,0 +1,326 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _SILABS_DEV_H_
+#define _SILABS_DEV_H_
+
+#include "proslic.h"
+#include "si3226x.h"
+#include "si3217x.h"
+
+#define SILABS_MOD_IOCTL_MAGIC           'z'
+
+#define SILABS_MOD_IOCTL_MIN 			1
+
+/* SI-API System Configuration Functions */
+#define SILABS_MOD_IOX_CTRL_IF			_IOWR(SILABS_MOD_IOCTL_MAGIC, 1, SilabsModCtrlObjType)
+#define SILABS_MOD_IOX_DEVICE_INIT		_IOWR(SILABS_MOD_IOCTL_MAGIC, 2, SilabsModDevObjType)
+#define SILABS_MOD_IOX_CHAN_ALL			_IOWR(SILABS_MOD_IOCTL_MAGIC, 3, SilabsModChannelAllObjType)
+#define SILABS_MOD_IOX_CHAN_INIT		_IOWR(SILABS_MOD_IOCTL_MAGIC, 4, SilabsModChannelObjType)
+#define SILABS_MOD_IOX_CHAN_SETUP		_IOWR(SILABS_MOD_IOCTL_MAGIC, 5, SilabsModChannelSetupObjType)
+#define SILABS_MOD_IOX_CHAN_OP			_IOWR(SILABS_MOD_IOCTL_MAGIC, 6, SilabsModChannelOpObjType)
+#define SILABS_MOD_IOX_PCM_TS_SETUP		_IOWR(SILABS_MOD_IOCTL_MAGIC, 7, SilabsModPCMTSSetupObjType)
+#define SILABS_MOD_IOX_GET_EVENT		_IOWR(SILABS_MOD_IOCTL_MAGIC, 8, SilabsModGetEventType)
+#define SILABS_MOD_IOX_REG_CTRL			_IOWR(SILABS_MOD_IOCTL_MAGIC, 9, SilabsRegObjType)
+#define SILABS_MOD_IOX_CHAN_LINE_FEED	_IOWR(SILABS_MOD_IOCTL_MAGIC, 10, SilabsModChannelLineFeedObjType)
+#define SILABS_MOD_IOX_CHAN_HOOK_STATUS	_IOWR(SILABS_MOD_IOCTL_MAGIC, 11, SilabsModChannelReadHookStatObjType)
+#define SILABS_MOD_IOX_CHAN_LOOPBACK	_IOWR(SILABS_MOD_IOCTL_MAGIC, 12, SilabsModChannelSetLoopbackObjType)
+//#define SILABS_MOD_IOX_SET_PROFILE		_IOWR(SILABS_MOD_IOCTL_MAGIC, 13, SilabsModCSetProfileObjType)
+
+/* SI-API Initialization Functions */
+/* SI-API Control Functions */
+/* SI-API Status and Query Functions */
+/* SLIC register read/write */
+
+#define SILABS_MOD_IOCTL_MAX 		14
+#define MAX_SLIC_RDWR_BUFF_SIZE		128
+
+/******************** SI-API Enums *********************/
+
+typedef enum {
+	SI_IF_CREATE,
+	SI_IF_DESTROY,
+	SI_IF_SET_FUNCS
+} ControlFuncType;
+
+typedef enum {
+	SI_DEVICE_CREATE,
+ 	SI_DEVICE_DESTROY
+} DeviceFuncType;
+
+typedef enum {
+	SI_CHANNEL_CREATE,
+	SI_CHANNEL_DESTROY,
+	SI_CHANNEL_BC_INIT,
+	SI_CHANNEL_SW_INIT,
+} ChannelFuncType;
+
+typedef enum {
+	SI_CHANNEL_ALL_INIT,
+	SI_CHANNEL_ALL_CAL,
+	SI_CHANNEL_ALL_LBCAL
+} ChannelAllFuncType;
+
+typedef enum {
+	SI_CHANNEL_SETUP_RING,
+	SI_CHANNEL_SETUP_TONEGEN,
+	SI_CHANNEL_SETUP_FSK,
+	SI_CHANNEL_SETUP_DTMF_DECODE,
+	SI_CHANNEL_SETUP_ZSYNTH,
+	SI_CHANNEL_SETUP_GCICI,
+	SI_CHANNEL_SETUP_MODEM_DET,
+	SI_CHANNEL_SETUP_TX_AUDIO_GAIN,
+	SI_CHANNEL_SETUP_RX_AUDIO_GAIN,
+	SI_CHANNEL_SETUP_DC_FEED,
+	SI_CHANNEL_SETUP_PULSE_METER,
+	SI_CHANNEL_SETUP_PCM,
+} ChannelSetupFuncType;
+
+typedef enum {
+	SI_CHANNEL_OP_RESET,
+	SI_CHANNEL_OP_CLEAR_ERR,
+	SI_CHANNEL_OP_GPIO_SETUP,
+	SI_CHANNEL_OP_VERIFY_CTRL_IF,
+	SI_CHANNEL_OP_SHUT_DOWN_CHAN,
+	SI_CHANNEL_OP_RING_START,
+	SI_CHANNEL_OP_RING_STOP,
+	SI_CHANNEL_OP_ENA_CID,
+	SI_CHANNEL_OP_DIS_CID,
+	SI_CHANNEL_OP_PLL_FREE_RUN_START,
+	SI_CHANNEL_OP_PLL_FREE_RUN_STOP,
+	SI_CHANNEL_OP_PULSE_METER_START,
+	SI_CHANNEL_OP_PULSE_METER_STOP,
+	SI_CHANNEL_OP_PWR_UP_CONV,
+	SI_CHANNEL_OP_PWR_DOWN_CONV,
+	SI_CHANNEL_OP_ENA_INT,
+	SI_CHANNEL_OP_PCM_START,
+	SI_CHANNEL_OP_PCM_STOP,
+	SI_CHANNEL_OP_TONE_GEN_START,
+	SI_CHANNEL_OP_TONE_GEN_STOP,
+} ChannelOPFuncType;
+
+typedef enum {
+	SI_REG_READ,
+	SI_REG_WRITE,
+	SI_RAM_READ,
+	SI_RAM_WRITE
+} RegFuncType;
+
+/************************ SI-API Initialization Structs ************************/
+
+typedef struct SilabsModCtrlObj {
+	/* Input arg(s) */
+	ControlFuncType			func;
+	/* Output arg(s) */
+	int						status;
+} SilabsModCtrlObjType;
+
+typedef struct SilabsModDevObj {
+	/* Input arg(s) */
+	int						devNum;
+	DeviceFuncType			func;
+	/* Output arg(s) */
+	int						status;
+} SilabsModDevObjType;
+
+typedef struct SilabsModChannelObj {
+	/* Input arg(s) */
+	int						chanNum;
+	ChannelFuncType			func;
+	/* Output arg(s) */
+	int						status;
+} SilabsModChannelObjType;
+
+/******************** SI-API System Configuration Structs *********************/
+
+typedef struct SilabsModChannelSetupObj {
+	/* Input arg(s) */
+	int						chanNum;
+	int						preset;
+	ChannelSetupFuncType	func;
+		/* Output arg(s) */
+	int						status;
+} SilabsModChannelSetupObjType;
+
+typedef struct SilabsModChannelAllObj {
+	/* Input arg(s) */
+	ChannelAllFuncType		func;
+	/* Output arg(s) */
+	int						status;
+} SilabsModChannelAllObjType;
+
+/****************************VP-API Control Structs ***************************/
+
+typedef struct SilabsModPCMTSSetupObj {
+	/* Input arg(s) */
+	int						chanNum;
+	uInt16 					rxcount;
+	uInt16 					txcount;
+	/* Output arg(s) */
+	int						status;
+} SilabsModPCMTSSetupObjType;
+
+typedef struct SilabsModChannelOpObj {
+	/* Input arg(s) */
+	int						chanNum;
+	ChannelOPFuncType		func;
+	/* Output arg(s) */
+	int						status;
+} SilabsModChannelOpObjType;
+
+typedef struct SilabsModChannelLoopbackModeObj {
+	/* Input arg(s) */
+	int						chanNum;
+	ProslicLoopbackModes 	newMode;
+	/* Output arg(s) */
+	int						status;
+} SilabsModChannelLoopbackModeObjType;
+
+typedef struct SilabsModChannelLineFeedObj {
+	/* Input arg(s) */
+	int						chanNum;
+	uInt8				 	newLineFeed;
+	/* Output arg(s) */
+	int						status;
+} SilabsModChannelLineFeedObjType;
+
+
+typedef struct SilabsModChannelSetLoopbackObj {
+	/* Input arg(s) */
+	int						chanNum;
+	ProslicLoopbackModes 	newMode;
+	/* Output arg(s) */
+	int						status;
+} SilabsModChannelSetLoopbackObjType;
+
+#if 0
+typedef struct SilabsModCSetProfileObj {
+	/* Input arg(s) */
+	Si3226x_General_Cfg User_Si3226x_General_Configuration;
+	Si3226x_GPIO_Cfg User_Si3226x_GPIO_Configuration;
+	Si3226x_CI_Cfg User_Si3226x_CI_Presets;
+	Si3226x_audioGain_Cfg User_Si3226x_audioGain_Presets;
+	Si3226x_Ring_Cfg User_Si3226x_Ring_Presets;
+	Si3226x_DCfeed_Cfg User_Si3226x_DCfeed_Presets;
+	Si3226x_Impedance_Cfg User_Si3226x_Impedance_Presets;
+	Si3226x_FSK_Cfg User_Si3226x_FSK_Presets;
+	Si3226x_PulseMeter_Cfg User_Si3226x_PulseMeter_Presets;
+	Si3226x_Tone_Cfg User_Si3226x_Tone_Presets[5];
+	Si3226x_PCM_Cfg User_Si3226x_PCM_Presets[4];
+
+	/* Output arg(s) */
+	int						status;
+} SilabsModCSetProfileObjType
+#endif
+/********************** VP-API Status and Query Structs ***********************/
+
+typedef struct SiEventTypeObj {
+	int 					chanNum;	/* Channel that caused the event */
+	int 					devNum;		/* device chip select ID corresponding to the
+											device that caused the event */
+	uInt8					eventsNum;
+	ProslicInt				irqs[MAX_PROSLIC_IRQS];	/* The events that occurred.  Requires that the event
+														catagory be known to interpret */
+} SiEventType;
+
+typedef struct SilabsModGetEventObj {
+	/* Input arg(s) */
+	int						devNum;
+	/* Output arg(s) */
+	bool					newEvent;
+	SiEventType				*pEvent;
+	int						status;
+} SilabsModGetEventType;
+
+typedef struct SilabsModChannelReadHookStatObj {
+	/* Input arg(s) */
+	int 					chanNum;	/* Channel that caused the event */
+	/* Output arg(s) */
+	uInt8					hookStatus;
+	int						status;
+}
+SilabsModChannelReadHookStatObjType;
+
+/********************** SLIC register read/write ********************/
+typedef struct SilabsRegObj {
+	/* Input arg(s) */
+	int						chanNum;
+	RegFuncType				func;
+	unsigned char 			regAddr;
+	uInt16 					ramAddr;
+	unsigned char 			value;
+	unsigned int 			ramValue;
+	
+	/* Output arg(s) */
+	int						status;
+} SilabsRegObjType;
+
+
+/* APIs */
+int silabs_module_init(void);
+void silabs_module_exit(void);
+
+
+#endif /*_SILABS_DEV_H_*/
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/vpapi_dev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/vpapi_dev.c
new file mode 100755
index 0000000..a2154e9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/vpapi_dev.c
@@ -0,0 +1,1017 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include "vpapi_dev.h"
+
+/* Defines */
+#define GET_DEV_STATUS(deviceId)	vpapi_dev_status[deviceId]
+#define GET_LINE_STATUS(lineId)		vpapi_line_status[lineId]
+#define REGISTER_DEVICE(deviceId)	\
+	vpapi_dev_status[deviceId] = 1;
+#define REGISTER_LINE(lineId)		\
+	vpapi_line_status[lineId] = 1;
+
+#define MAX_PROFILE_SIZE		128
+#define GET_DEVICE(lineId)		(lineId/MAX_LINES_PER_DEVICE)
+#define GET_LINE(lineId)		(lineId % MAX_LINES_PER_DEVICE)
+#define MAX_EVENT_QUEUE_SIZE		256
+#define VPAPI_TICK_TIMER_PERIOD		1
+#define VPAPI_MOD_NAME                  "vpapi"
+
+/* VE880 */
+#if defined(CONFIG_ZARLINK_SLIC_VE880)
+
+#define MAX_DEVICES			2
+#define MAX_LINES			4
+#define MAX_LINES_PER_DEVICE		2
+	
+static VpDevCtxType pDevCtx[MAX_DEVICES];
+static VpLineCtxType pLineCtx[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+static Vp880DeviceObjectType pDevObj[MAX_DEVICES];
+static Vp880LineObjectType pLineObj[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+
+/* VE890 */
+#elif defined(CONFIG_ZARLINK_SLIC_VE890)
+
+#define MAX_DEVICES			1
+#define MAX_LINES			1
+#define MAX_LINES_PER_DEVICE		1
+	
+static VpDevCtxType pDevCtx[MAX_DEVICES];
+static VpLineCtxType pLineCtx[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+static Vp890DeviceObjectType pDevObj[MAX_DEVICES];
+static Vp890LineObjectType pLineObj[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+
+/* VE792 */
+#elif defined(CONFIG_ZARLINK_SLIC_VE792)
+
+#define MAX_DEVICES			4
+#define MAX_LINES			32
+#define MAX_LINES_PER_DEVICE		8
+
+static VpDevCtxType pDevCtx[MAX_DEVICES];
+static VpLineCtxType pLineCtx[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+static Vp792DeviceObjectType pDevObj[MAX_DEVICES];
+static Vp792LineObjectType pLineObj[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+
+extern int BattOn(int vbhSetting, int vblSetting, int vbpSetting);
+extern int BattOff(void);
+
+#endif
+
+static void vpapi_tick_handler(unsigned long data);
+static ssize_t vpapi_read(struct file *file, char __user *buf, size_t size, loff_t * ppos);
+static ssize_t vpapi_write(struct file *file, const char __user *buf, size_t size, loff_t * ppos);
+static unsigned int vpapi_poll(struct file *pFile, poll_table *pPollTable);
+static int vpapi_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg);
+static int vpapi_open(struct inode *pInode, struct file *pFile);
+static int vpapi_release(struct inode *pInode, struct file *pFile);
+//static int __init vpapi_module_init(void);
+//static void __exit vpapi_module_exit(void);
+
+/* VP-API-II Dispatchers */
+static int vpapi_make_dev_object(unsigned long arg);
+static int vpapi_make_line_object(unsigned long arg);
+static int vpapi_map_line_id(unsigned long arg);
+static int vpapi_map_slac_id(unsigned long arg);
+static int vpapi_free_line_context(unsigned long arg);
+static int vpapi_init_device(unsigned long arg);
+static int vpapi_cal_line(unsigned long arg);
+static int vpapi_set_line_state(unsigned long arg);
+static int vpapi_set_option(unsigned long arg);
+int vpapi_get_event(unsigned long arg);
+#if defined(CONFIG_ZARLINK_SLIC_VE792)
+static int vpapi_batt_on(unsigned long arg);
+static int vpapi_batt_off(unsigned long arg);
+#endif
+#if defined(CONFIG_ZARLINK_SLIC_VE880)
+static int vpapi_reg_read(unsigned long arg);
+static int vpapi_reg_write(unsigned long arg);
+#endif
+
+/* Enumurators */
+typedef struct {
+	unsigned char valid;		/* valid event */
+	VpEventType vp_event;
+} vpapi_event;
+
+
+/* Structs */
+static struct file_operations vpapi_fops = {
+    owner:      THIS_MODULE,
+    llseek:     NULL,
+    read:       vpapi_read,
+    write:      vpapi_write,
+    poll:       vpapi_poll,
+    ioctl:      vpapi_ioctl,
+    open:       vpapi_open,
+    release:    vpapi_release,
+    fasync:     NULL
+};
+
+/* Globals */
+static DEFINE_SPINLOCK(vpapi_lock);
+static DECLARE_WAIT_QUEUE_HEAD(vpapi_wait);
+static atomic_t event_count;
+static atomic_t vpapi_init;
+static atomic_t vpapi_in_ioctl;
+static vpapi_event event_queue[MAX_EVENT_QUEUE_SIZE];
+static u8 vpapi_dev_status[MAX_DEVICES];
+static u8 vpapi_line_status[MAX_LINES];
+static volatile u32 next_event = 0, curr_event = 0;
+static struct timer_list vpapi_timer;
+static u16 total_devs = 0, total_lines = 0;
+
+
+static struct miscdevice vpapi_misc_dev = {
+	.minor = SLICDEV_MINOR,
+	.name = VPAPI_MOD_NAME,
+	.fops = &vpapi_fops,
+};
+
+static ssize_t vpapi_read(struct file *file, char __user *buf, size_t size, loff_t * ppos)
+{
+	return 0;
+}
+
+static ssize_t vpapi_write(struct file *file, const char __user *buf, size_t size, loff_t * ppos)
+{
+	return 0;
+}
+
+static unsigned int vpapi_poll(struct file *pFile, poll_table *pPollTable)
+{
+	int mask = 0;
+
+	poll_wait(pFile, &vpapi_wait, pPollTable);
+	
+	if(atomic_read(&event_count) > 0) {
+		mask |= POLLPRI;
+	}
+
+	return mask;
+}
+
+static int vpapi_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg)
+{
+	int ret = 0;
+
+	/* Argument checking */
+	if (_IOC_TYPE(cmd) != VPAPI_MOD_IOCTL_MAGIC) {
+		printk("%s: invalid VPAPI MOD Magic Num %i %i\n", __func__, _IOC_TYPE(cmd), VPAPI_MOD_IOCTL_MAGIC);
+		return -ENOTTY;
+	}
+
+	if ((_IOC_NR(cmd) > VPAPI_MOD_IOCTL_MAX) || (_IOC_NR(cmd) < VPAPI_MOD_IOCTL_MIN)) {
+		printk("%s: invalid VPAPI MOD IOCTL request\n", __func__);
+		return -ENOTTY;
+	}
+
+	if (_IOC_DIR(cmd) & _IOC_READ) {
+		ret = !access_ok(VERIFY_WRITE, (void __user*)arg, _IOC_SIZE(cmd));
+	} 
+	else if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		ret = !access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd));
+	}
+
+	if (ret) {
+		printk("%s: invalid VPAPI MOD access type %i from cmd %i\n", __func__, _IOC_DIR(cmd), cmd);
+		return -EFAULT;
+	}
+
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+	/* Disable timer routine processing */
+	atomic_set(&vpapi_in_ioctl, 1);
+#endif
+
+	switch (cmd) {
+		case VPAPI_MOD_IOX_MK_DEV_OBJ:
+			//printk("ioctl: VPAPI_MOD_IOX_MK_DEV_OBJ\n");
+			ret = vpapi_make_dev_object(arg);	
+			break;
+		
+		case VPAPI_MOD_IOX_MK_LN_OBJ:
+			//printk("ioctl: VPAPI_MOD_IOX_MK_LN_OBJ\n");
+			ret = vpapi_make_line_object(arg);
+			break;
+
+		case VPAPI_MOD_IOX_MAP_LN_ID:
+			//printk("ioctl: VPAPI_MOD_IOX_MAP_LN_ID\n");
+			ret = vpapi_map_line_id(arg);
+			break;
+
+		case VPAPI_MOD_IOX_MAP_SLAC_ID:
+			//printk("ioctl: VPAPI_MOD_IOX_MAP_SLAC_ID\n");
+			ret  = vpapi_map_slac_id(arg);
+			break;
+
+		case VPAPI_MOD_IOX_FREE_LN_CTX:
+			//printk("ioctl: VPAPI_MOD_IOX_FREE_LN_CTX\n");
+			ret = vpapi_free_line_context(arg);
+			break;
+
+		case VPAPI_MOD_IOX_INIT_DEV:
+			//printk("ioctl: VPAPI_MOD_IOX_INIT_DEV\n");
+			ret = vpapi_init_device(arg);
+			break;
+
+		case VPAPI_MOD_IOX_CAL_LN:
+			//printk("ioctl: VPAPI_MOD_IOX_CAL_LN\n");
+			ret = vpapi_cal_line(arg);
+			break;
+
+		case VPAPI_MOD_IOX_SET_LN_ST:
+			//printk("ioctl: VPAPI_MOD_IOX_SET_LN_ST\n");
+			ret = vpapi_set_line_state(arg);
+			break;
+
+		case VPAPI_MOD_IOX_SET_OPTION:
+			//printk("ioctl: VPAPI_MOD_IOX_SET_OPTION\n");
+			ret = vpapi_set_option(arg);
+			break;
+
+		case VPAPI_MOD_IOX_GET_EVENT:
+			//printk("ioctl: VPAPI_MOD_IOX_GET_EVENT\n");
+			ret = vpapi_get_event(arg);
+			break;
+
+#if defined(CONFIG_ZARLINK_SLIC_VE792)		
+		case VPAPI_MOD_IOX_BATT_ON:
+			//printk("ioctl: VPAPI_MOD_IOX_BATT_ON\n");
+			ret = vpapi_batt_on(arg);
+			break;
+
+		case VPAPI_MOD_IOX_BATT_OFF:
+			//printk("ioctl: VPAPI_MOD_IOX_BATT_OFF\n");
+			ret = vpapi_batt_off(arg);
+			break;
+#endif
+#if defined(CONFIG_ZARLINK_SLIC_VE880)
+		case VPAPI_MOD_IOX_REG_READ:
+			ret = vpapi_reg_read(arg);
+			break;
+
+		case VPAPI_MOD_IOX_REG_WRITE:
+			ret = vpapi_reg_write(arg);
+			break;
+#endif
+		default:
+			printk("%s: error, ioctl command(0x%x) not supported !!!\n", __func__, cmd);
+			ret = -EFAULT;
+			break;
+	}
+
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+	/* Enable timer routine processing */
+	atomic_set(&vpapi_in_ioctl, 0);
+#endif
+
+	return ret;
+}
+
+static int vpapi_make_dev_object(unsigned long arg)
+{
+	VpApiModMkDevObjType data;
+	VpDeviceType deviceType;
+	VpDeviceIdType deviceId;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModMkDevObjType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	deviceType = data.deviceType;
+	deviceId = data.deviceId;
+	
+	data.status = VpMakeDeviceObject(deviceType, deviceId, &pDevCtx[deviceId], &pDevObj[deviceId]);
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModMkDevObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int vpapi_make_line_object(unsigned long arg)
+{
+	VpApiModMkLnObjType data;
+	VpTermType termType;
+	VpLineIdType lineId;
+	VpDeviceIdType deviceId;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModMkLnObjType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	termType = data.termType;
+	lineId = GET_LINE(data.lineId);
+	deviceId = GET_DEVICE(data.lineId);
+
+	data.status = VpMakeLineObject(termType, lineId, &pLineCtx[deviceId][lineId],
+                        	&pLineObj[deviceId][lineId], &pDevCtx[deviceId]);
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModMkLnObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	
+	return 0;
+}
+
+static int vpapi_map_line_id(unsigned long arg)
+{
+	VpApiModMapLnIdType data;
+	VpLineIdType lineId;
+	VpDeviceIdType deviceId;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModMapLnIdType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	lineId = GET_LINE(data.lineId);
+	deviceId = GET_DEVICE(data.lineId);
+
+	data.status = VpMapLineId(&pLineCtx[deviceId][lineId], data.lineId);
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModMapLnIdType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int vpapi_map_slac_id(unsigned long arg)
+{
+	VpApiModMapSlacIdType data;
+	VpDeviceIdType deviceId;
+	u8 slacId;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModMapSlacIdType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+	
+	deviceId = data.deviceId;
+	slacId = data.slacId;
+#if defined(CONFIG_ZARLINK_SLIC_VE792)
+	data.status = VpMapSlacId(&pDevCtx[deviceId], slacId);
+#endif
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModMapSlacIdType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+	
+}
+
+static int vpapi_free_line_context(unsigned long arg)
+{
+	VpApiModFreeLnCtxType data;
+	VpLineIdType lineId;
+	VpDeviceIdType deviceId;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModFreeLnCtxType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	lineId = GET_LINE(data.lineId);
+	deviceId = GET_DEVICE(data.lineId);
+
+	data.status = VpFreeLineCtx(&pLineCtx[deviceId][lineId]);
+
+	if(data.status == VP_STATUS_SUCCESS) {
+		vpapi_line_status[data.lineId] = 0;
+		total_lines--;
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+		if(total_lines == 0) {
+			atomic_set(&vpapi_init, 0);
+			del_timer(&vpapi_timer);
+		}
+#endif
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModFreeLnCtxType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int vpapi_init_device(unsigned long arg)
+{
+	VpApiModInitDeviceType data;
+	VpDeviceIdType deviceId;
+	VpProfileDataType devProfile[MAX_PROFILE_SIZE];
+	VpProfileDataType acProfile[MAX_PROFILE_SIZE];
+	VpProfileDataType dcProfile[MAX_PROFILE_SIZE];
+	VpProfileDataType ringProfile[MAX_PROFILE_SIZE];
+	VpProfileDataType fxoAcProfile[MAX_PROFILE_SIZE];
+	VpProfileDataType fxoCfgProfile[MAX_PROFILE_SIZE];
+	VpProfilePtrType pDevProfile = NULL, pAcProfile = NULL;
+	VpProfilePtrType pDcProfile = NULL, pRingProfile = NULL;
+	VpProfilePtrType pFxoAcProfile = NULL, pFxoCfgProfile = NULL;
+	u16 devProfileSize, acProfileSize, dcProfileSize;
+	u16 ringProfileSize, fxoAcProfileSize, fxoCfgProfileSize;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModInitDeviceType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	deviceId = data.deviceId;
+	devProfileSize = data.devProfileSize;
+	acProfileSize = data.acProfileSize;
+	dcProfileSize = data.dcProfileSize;
+	ringProfileSize = data.ringProfileSize;
+	fxoAcProfileSize = data.fxoAcProfileSize;
+	fxoCfgProfileSize = data.fxoCfgProfileSize;
+
+	if(devProfileSize) {
+		/* Get device profile */
+		if(copy_from_user(devProfile, (void*)data.pDevProfile, (sizeof(VpProfileDataType)*devProfileSize))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+		}
+		pDevProfile = devProfile;
+	}
+
+	if(acProfileSize) {
+		/* Get AC profile */
+		if(copy_from_user(acProfile, (void*)data.pAcProfile, (sizeof(VpProfileDataType)*acProfileSize))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+		}
+		pAcProfile = acProfile;
+	}
+
+	if(dcProfileSize) {
+		/* Get DC profile */
+		if(copy_from_user(dcProfile, (void*)data.pDcProfile, (sizeof(VpProfileDataType)*dcProfileSize))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+		}
+		pDcProfile = dcProfile;
+	}
+
+	if(ringProfileSize) {
+		/* Get ring profile */
+		if(copy_from_user(ringProfile, (void*)data.pRingProfile, (sizeof(VpProfileDataType)*ringProfileSize))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+		}
+		pRingProfile = ringProfile;
+	}
+
+	if(fxoAcProfileSize) {
+		/* Get FXO AC profile */
+		if(copy_from_user(fxoAcProfile, (void*)data.pFxoAcProfile, (sizeof(VpProfileDataType)*fxoAcProfileSize))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+		}
+		pFxoAcProfile = fxoAcProfile;
+	}
+
+	if(fxoCfgProfileSize) {
+		/* Get FXO configuration profile */
+		if(copy_from_user(fxoCfgProfile, (void*)data.pFxoCfgProfile,
+					 (sizeof(VpProfileDataType)*fxoCfgProfileSize))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+		}
+		pFxoCfgProfile = fxoCfgProfile;
+	}
+
+	data.status = VpInitDevice(&pDevCtx[deviceId], pDevProfile, pAcProfile, pDcProfile, pRingProfile,
+					 pFxoAcProfile, pFxoCfgProfile);
+
+	if(data.status == VP_STATUS_SUCCESS) {
+		total_devs++;
+		REGISTER_DEVICE(deviceId);
+
+		if(!atomic_read(&vpapi_init)) {
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+			memset(&vpapi_timer, 0, sizeof(struct timer_list));
+			init_timer(&vpapi_timer);
+    			vpapi_timer.function = vpapi_tick_handler;
+    			vpapi_timer.data = -1;
+			vpapi_timer.expires = jiffies + VPAPI_TICK_TIMER_PERIOD;
+			add_timer(&vpapi_timer);
+#endif
+			atomic_set(&vpapi_init, 1);
+		}
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModInitDeviceType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int vpapi_cal_line(unsigned long arg)
+{
+	VpApiModCalLnType data;
+	VpLineIdType lineId;
+	VpDeviceIdType deviceId;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModCalLnType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	lineId = GET_LINE(data.lineId);
+	deviceId = GET_DEVICE(data.lineId);
+
+	data.status = VpCalLine(&pLineCtx[deviceId][lineId]);
+
+	if(data.status == VP_STATUS_SUCCESS) {
+		total_lines++;
+		REGISTER_LINE(data.lineId);
+	}
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModCalLnType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int vpapi_set_line_state(unsigned long arg)
+{
+	VpApiModSetLnStType data;
+	VpLineIdType lineId;
+	VpDeviceIdType deviceId;
+	VpLineStateType state;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModSetLnStType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	lineId = GET_LINE(data.lineId);
+	deviceId = GET_DEVICE(data.lineId);
+	state = data.state;
+
+	data.status = VpSetLineState(&pLineCtx[deviceId][lineId], state);
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModSetLnStType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int vpapi_set_option(unsigned long arg)
+{
+	VpApiModSetOptionType data;
+	u8 lineRequest;
+	VpLineIdType lineId;
+	VpDeviceIdType deviceId;
+	VpOptionIdType option;
+	void *pOptInfo;
+	long size;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModSetOptionType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	option = data.option;
+	lineRequest = data.lineRequest;
+	deviceId = data.deviceId;
+	lineId = GET_LINE(data.lineId);
+
+	switch(option) {
+		case VP_OPTION_ID_TIMESLOT:
+			size = sizeof(VpOptionTimeslotType);
+			pOptInfo = (VpOptionTimeslotType*)kmalloc(size, GFP_KERNEL);
+			break;
+		case VP_OPTION_ID_CODEC:
+			size = sizeof(VpOptionCodecType);
+			pOptInfo = (VpOptionCodecType*)kmalloc(size, GFP_KERNEL);
+			break;
+		case VP_OPTION_ID_LOOPBACK:
+			size = sizeof(VpOptionLoopbackType);
+			pOptInfo = (VpOptionLoopbackType*)kmalloc(size, GFP_KERNEL);
+			break;
+		case VP_OPTION_ID_EVENT_MASK:
+			size = sizeof(VpOptionEventMaskType);
+			pOptInfo = (VpOptionEventMaskType*)kmalloc(size, GFP_KERNEL);
+			break;
+		case VP_OPTION_ID_LINE_STATE:
+			size = sizeof(VpOptionLineStateType);
+			pOptInfo = (VpOptionLineStateType*)kmalloc(size, GFP_KERNEL);
+			break;
+		default:
+			printk("%s: option(%d) not supported\n",__func__, option);
+			return -EFAULT;
+	}
+
+	/* Get option info */
+	if(copy_from_user(pOptInfo, (void*)data.pValue, size)) {
+			printk("%s: copy_from_user failed\n", __func__);
+			kfree(pOptInfo);
+			return -EFAULT;
+	}
+
+	/* Set option to line/device */
+	if(lineRequest)
+		data.status = VpSetOption(&pLineCtx[deviceId][lineId], VP_NULL, option, pOptInfo);
+	else
+		data.status = VpSetOption(VP_NULL, &pDevCtx[deviceId], option, pOptInfo);
+
+
+	kfree(pOptInfo);
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModSetOptionType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+int vpapi_get_event(unsigned long arg)
+{
+	VpApiModGetEventType data;
+	VpDeviceIdType deviceId;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpApiModGetEventType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	deviceId = data.deviceId;
+
+	if(atomic_read(&event_count) == 0) {
+		data.newEvent = FALSE;
+	}
+	else {
+		/* Copy event info back to user */
+		if(copy_to_user(data.pEvent, &event_queue[curr_event].vp_event, sizeof(VpEventType))) {
+			printk("%s: copy_to_user failed\n", __func__);
+			return  -EFAULT;
+		}
+
+		event_queue[curr_event].valid = 0;
+		data.newEvent = TRUE;
+		atomic_dec(&event_count);
+		curr_event++;
+		if(curr_event == MAX_EVENT_QUEUE_SIZE)
+			curr_event = 0;
+	}
+
+	/* Copy status and event info back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpApiModGetEventType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+#if defined(CONFIG_ZARLINK_SLIC_VE792)
+static int vpapi_batt_on(unsigned long arg)
+{
+	VpModBatteryOnType data;
+	int vbh, vbl, vbp;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpModBatteryOnType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+	
+	vbh = data.vbh;
+	vbl = data.vbl;
+	vbp = data.vbp;
+
+	data.status = BattOn(vbh, vbl, vbp);
+
+	/* Copy status and event info back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpModBatteryOnType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int vpapi_batt_off(unsigned long arg)
+{
+	VpModBatteryOffType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpModBatteryOffType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+	
+	data.status = BattOff();
+
+	/* Copy status and event info back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpModBatteryOffType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_ZARLINK_SLIC_VE880)
+static int vpapi_reg_read(unsigned long arg)
+{
+	VpModRegOpType data;
+	VpLineIdType	line_id;
+	unsigned char	cmd;
+	unsigned short  cmd_len;
+	unsigned char *buff_p = NULL;
+	unsigned char ec_val[] = {0x1, 0x2};
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpModRegOpType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	line_id = data.lineId;
+	cmd = data.cmd;
+	cmd_len = data.cmdLen;
+	buff_p = data.buff;
+
+	VpMpiCmd(GET_DEVICE(line_id), ec_val[GET_LINE(line_id)], (cmd | 1), cmd_len, buff_p);
+
+	/* Copy status and event info back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(VpModRegOpType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int vpapi_reg_write(unsigned long arg)
+{
+	VpModRegOpType data;
+	VpLineIdType	line_id;
+	unsigned char	cmd;
+	unsigned short  cmd_len;
+	unsigned char *buff_p = NULL;
+	unsigned char ec_val[] = {0x1, 0x2};
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(VpModRegOpType))) {
+			printk("%s: copy_from_user failed\n", __func__);
+			return -EFAULT;
+	}
+
+	line_id = data.lineId;
+	cmd = data.cmd;
+	cmd_len = data.cmdLen;
+	buff_p = data.buff;
+
+	VpMpiCmd(GET_DEVICE(line_id), ec_val[GET_LINE(line_id)], cmd, cmd_len, buff_p);
+
+	return 0;
+}
+#endif
+
+static int vpapi_open(struct inode *pInode, struct file *pFile)
+{
+	try_module_get(THIS_MODULE);
+	return 0;
+}
+
+static int vpapi_release(struct inode *pInode, struct file *pFile)
+{
+	module_put(THIS_MODULE);
+	return 0;
+}
+
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+static void vpapi_tick_handler(unsigned long data)
+{
+	u8 deviceId;
+	unsigned long flags;
+	vpapi_event *pEvent;
+#if !defined(CONFIG_ZARLINK_SLIC_VE792)
+	bool eventStatus;
+#endif
+
+	/* Check if events are already active and not processing IOCTL */
+	if((atomic_read(&vpapi_init) == 0) || (atomic_read(&vpapi_in_ioctl) == 1))
+		goto timer_exit;
+
+	spin_lock_irqsave(&vpapi_lock, flags);
+
+	for(deviceId = 0; deviceId < MAX_DEVICES; deviceId++) {
+
+		if(GET_DEV_STATUS(deviceId) == 0)
+			continue;
+
+		/* Check for free resources */
+		if(atomic_read(&event_count) >= MAX_EVENT_QUEUE_SIZE)
+			goto timer_exit;
+
+#if !defined(CONFIG_ZARLINK_SLIC_VE792)
+		if(VP_STATUS_SUCCESS == VpApiTick(&pDevCtx[deviceId], &eventStatus)) {
+			if(eventStatus == TRUE) {
+#endif
+				pEvent = &event_queue[next_event];
+				while(VpGetEvent(&pDevCtx[deviceId], &pEvent->vp_event) == TRUE) {
+					if(pEvent->vp_event.status != VP_STATUS_SUCCESS) {
+						printk("%s: bad status(%d)\n", __func__, pEvent->vp_event.status);
+						break;
+					}
+					
+					if(pEvent->vp_event.eventId == 0)  {
+						printk("%s: warning, empty event\n", __func__);
+						break;
+					}
+					
+					next_event++;
+					if(next_event == MAX_EVENT_QUEUE_SIZE) {
+						next_event = 0;
+					}
+
+					atomic_inc(&event_count);
+					
+					if(pEvent->valid == 0) {
+						pEvent->valid = 1;			
+					}
+					else {
+						printk("%s: error, event(%u) was overrided\n", __func__, next_event);
+						break;
+					}
+
+					pEvent = &event_queue[next_event];
+				}
+#if !defined(CONFIG_ZARLINK_SLIC_VE792)
+			}
+		}
+#endif
+	}
+
+	
+	spin_unlock_irqrestore(&vpapi_lock, flags);
+
+timer_exit:
+
+	/* Checks if user application should be signaled */
+	if(atomic_read(&event_count) > 0) {
+		wake_up_interruptible(&vpapi_wait);
+	}
+
+	/* Schedule next timer tick */
+	vpapi_timer.expires = jiffies + VPAPI_TICK_TIMER_PERIOD;
+    	add_timer(&vpapi_timer);
+}
+#endif
+
+int __init vpapi_module_init(void)
+{
+	int status;
+
+	printk("Loading Marvell %s device\n", VPAPI_MOD_NAME);
+	status = misc_register(&vpapi_misc_dev);
+
+	/* Register VPAPI device module */
+	if (status < 0) {
+		printk("Error, failed to load %s module(%d)\n", VPAPI_MOD_NAME, status);
+		return status;
+	}
+
+	atomic_set(&vpapi_init, 0);
+	atomic_set(&vpapi_in_ioctl, 0);
+	total_devs = 0;
+	total_lines = 0;
+	next_event = 0;
+	curr_event = 0;
+	memset(vpapi_dev_status, 0, MAX_DEVICES);
+	memset(vpapi_line_status, 0, MAX_LINES);
+
+	/* Reset event counter */
+	atomic_set(&event_count, 0);
+
+	/* Clear event queue */
+	memset(event_queue, 0, (MAX_EVENT_QUEUE_SIZE * sizeof(vpapi_event)));
+
+	return 0;
+}
+
+void __exit vpapi_module_exit(void)
+{
+	printk("Unloading %s device module\n", VPAPI_MOD_NAME);
+
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+	if(total_lines == 0)
+		del_timer(&vpapi_timer);
+#endif
+
+	/* Unregister VPAPI misc device */
+	misc_deregister(&vpapi_misc_dev);
+
+	return;
+}
+
+/* Module stuff */
+module_init(vpapi_module_init);
+module_exit(vpapi_module_exit);
+MODULE_DESCRIPTION("Zarlink VPAPI-II Device");
+MODULE_AUTHOR("Eran Ben-Avi <benavi@marvell.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/vpapi_dev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/vpapi_dev.h
new file mode 100755
index 0000000..c7cb3b6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/slic/vpapi_dev.h
@@ -0,0 +1,268 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _VPAPI_DEV_H_
+#define _VPAPI_DEV_H_
+
+#include "vp_api_common.h"
+#if defined(CONFIG_ZARLINK_SLIC_VE880)
+#include "vp880_api.h"
+#elif defined(CONFIG_ZARLINK_SLIC_VE890)
+#include "vp890_api.h"
+#elif defined(CONFIG_ZARLINK_SLIC_VE792)
+#include "vp792_api.h"
+#endif
+
+#define VPAPI_MOD_IOCTL_MAGIC           'z'
+
+#define VPAPI_MOD_IOCTL_MIN 		1
+
+/* VP-API System Configuration Functions */
+#define VPAPI_MOD_IOX_MK_DEV_OBJ	_IOWR(VPAPI_MOD_IOCTL_MAGIC, 1, VpApiModMkDevObjType)
+#define VPAPI_MOD_IOX_MK_LN_OBJ		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 2, VpApiModMkLnObjType)
+#define VPAPI_MOD_IOX_MAP_LN_ID		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 3, VpApiModMapLnIdType)
+#define VPAPI_MOD_IOX_MAP_SLAC_ID	_IOWR(VPAPI_MOD_IOCTL_MAGIC, 4, VpApiModMapSlacIdType)
+#define VPAPI_MOD_IOX_FREE_LN_CTX	_IOWR(VPAPI_MOD_IOCTL_MAGIC, 5, VpApiModFreeLnCtxType)
+
+/* VP-API Initialization Functions */
+#define VPAPI_MOD_IOX_INIT_DEV		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 6, VpApiModInitDeviceType)
+#define VPAPI_MOD_IOX_CAL_LN		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 7, VpApiModCalLnType)
+
+/* VP-API Control Functions */
+#define VPAPI_MOD_IOX_SET_LN_ST		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 8, VpApiModSetLnStType)
+#define VPAPI_MOD_IOX_SET_OPTION	_IOWR(VPAPI_MOD_IOCTL_MAGIC, 9, VpApiModSetOptionType)
+
+/* VP-API Status and Query Functions */
+#define VPAPI_MOD_IOX_GET_EVENT		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 10, VpApiModGetEventType)
+
+/* VE792 Battery Control */
+#define VPAPI_MOD_IOX_BATT_ON		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 11, VpModBatteryOnType)
+#define VPAPI_MOD_IOX_BATT_OFF		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 12, VpModBatteryOffType)
+
+/* SLIC register read/write */
+#define VPAPI_MOD_IOX_REG_READ		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 13, VpModRegOpType)
+#define VPAPI_MOD_IOX_REG_WRITE		_IOWR(VPAPI_MOD_IOCTL_MAGIC, 14, VpModRegOpType)
+
+#define VPAPI_MOD_IOCTL_MAX 		14
+#define MAX_SLIC_RDWR_BUFF_SIZE		128
+
+
+/******************** VP-API System Configuration Structs *********************/
+typedef struct VpApiModMkDevObj {
+	/* Input arg(s) */
+	VpDeviceType	deviceType;
+	VpDeviceIdType	deviceId;
+    
+	/* Output arg(s) */
+	VpStatusType		status;
+} VpApiModMkDevObjType;
+
+
+typedef struct VpApiModMkLnObj {
+	/* Input arg(s) */
+	VpTermType	termType;
+	VpLineIdType	lineId;
+
+	/* Output arg(s) */
+	VpStatusType	status;
+} VpApiModMkLnObjType;
+
+typedef struct VpApiModMapLnId {
+	/* Input arg(s) */
+	VpLineIdType	lineId;
+
+	/* Output arg(s) */
+	VpStatusType	status;
+} VpApiModMapLnIdType;
+
+typedef struct VpApiModMapSlacId {
+ 	/* Input arg(s) */
+	VpDeviceIdType	deviceId;
+	unsigned char	slacId;
+
+	/* Output arg(s) */
+	VpStatusType	status;
+} VpApiModMapSlacIdType;
+
+typedef struct VpApiModFreeLnCtx {
+ 	/* Input arg(s) */
+	VpLineIdType	lineId;
+
+	/* Output arg(s) */
+	VpStatusType	status;
+} VpApiModFreeLnCtxType;
+
+
+/************************ VP-API Initialization Structs ************************/
+typedef struct VpApiModInitDevice {
+    	/* Input arg(s) */
+	VpDeviceIdType		deviceId;
+	VpProfilePtrType	pDevProfile;
+	VpProfilePtrType	pAcProfile;
+	VpProfilePtrType	pDcProfile;
+	VpProfilePtrType	pRingProfile;
+	VpProfilePtrType	pFxoAcProfile;
+	VpProfilePtrType	pFxoCfgProfile;
+	unsigned short		devProfileSize;
+	unsigned short		acProfileSize;
+	unsigned short		dcProfileSize;
+	unsigned short		ringProfileSize;
+	unsigned short		fxoAcProfileSize;
+	unsigned short		fxoCfgProfileSize;
+
+	/* Output arg(s) */
+	VpStatusType		status;
+} VpApiModInitDeviceType;
+
+typedef struct VpApiModCalLn {
+	/* Input arg(s) */
+	VpLineIdType	lineId;
+
+	/* Output arg(s) */
+	VpStatusType	status;
+} VpApiModCalLnType;
+
+
+/****************************VP-API Control Structs ***************************/
+typedef struct VpApiModSetLnSt {
+	/* Input arg(s) */
+	VpLineIdType	lineId;
+	VpLineStateType	state;
+
+	/* Output arg(s) */
+	VpStatusType	status;
+} VpApiModSetLnStType;
+
+
+typedef struct VpApiModSetOption {
+	/* Input arg(s) */
+	unsigned char	lineRequest;
+	VpLineIdType	lineId;
+	VpDeviceIdType	deviceId;
+	VpOptionIdType	option;
+	void		*pValue;
+
+	/* Output arg(s) */
+	VpStatusType	status;
+} VpApiModSetOptionType;
+
+#if 0
+typedef struct VpApiModLowLvlCmd {
+	/* Input arg(s) */
+	const VpModLineRegNumType	lineRegNum;
+	uint8				*pCmdData;
+	const uint8			len;
+	const uint16			handle;
+
+	/* Output arg(s) */
+	VpStatusType			status;
+} VpApiModLowLvlCmdType;
+#endif
+
+/********************** VP-API Status and Query Structs ***********************/
+typedef struct VpApiModGetEvent {
+	/* Input arg(s) */
+	VpDeviceIdType	deviceId;
+
+	/* Output arg(s) */
+	bool		newEvent;
+	VpEventType	*pEvent;
+} VpApiModGetEventType;
+
+/********************** VE792 Battery Control ***********************/
+typedef struct VpModBatteryOn {
+	/* Input arg(s) */
+	int	vbh;
+	int	vbl;
+	int	vbp;
+
+	/* Output arg(s) */
+	int	status;
+} VpModBatteryOnType;
+
+typedef struct VpModBatteryOff {
+
+	/* Output arg(s) */
+	int	status;
+} VpModBatteryOffType;
+
+/********************** SLIC register read/write ********************/
+typedef struct VpModRegOp {
+	/* Input arg(s) */
+	VpLineIdType	lineId;
+	unsigned char	cmd;
+	unsigned short  cmdLen;
+	unsigned char buff[MAX_SLIC_RDWR_BUFF_SIZE];
+
+	/* Output arg(s) */
+	VpStatusType	status;
+} VpModRegOpType;
+
+/* APIs */
+int vpapi_module_init(void);
+void vpapi_module_exit(void);
+
+
+#endif /*_VPAPI_DEV_H_*/
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/spi/spi_dev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/spi/spi_dev.c
new file mode 100644
index 0000000..af994af
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/spi/spi_dev.c
@@ -0,0 +1,263 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include "spi_dev.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "voiceband/mvSysTdmSpi.h"
+
+/* Defines */
+#define SPI_MOD_NAME				"spi"
+
+static ssize_t spi_read(struct file *file, char __user *buf, size_t size, loff_t * ppos);
+static ssize_t spi_write(struct file *file, const char __user *buf, size_t size, loff_t * ppos);
+static unsigned int spi_poll(struct file *pFile, poll_table *pPollTable);
+static int spi_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg);
+static int spi_open(struct inode *pInode, struct file *pFile);
+static int spi_release(struct inode *pInode, struct file *pFile);
+
+/* SPI-API Dispatchers */
+static int spi_read_reg(unsigned long arg);
+static int spi_write_reg(unsigned long arg);
+
+/* Structs */
+static struct file_operations spi_fops = {
+    owner:      THIS_MODULE,
+    llseek:     NULL,
+    read:       spi_read,
+    write:      spi_write,
+    poll:       spi_poll,
+    ioctl:      spi_ioctl,
+    open:       spi_open,
+    release:    spi_release,
+    fasync:     NULL
+};
+
+/* Globals */
+static struct miscdevice spi_misc_dev = {
+//	.minor = SLICDEV_MINOR,
+	.minor = MISC_DYNAMIC_MINOR,
+ 	.name = SPI_MOD_NAME,
+ 	.fops = &spi_fops,
+};
+
+static ssize_t spi_read(struct file *file, char __user *buf, size_t size, loff_t * ppos)
+{
+	return 0;
+}
+
+static ssize_t spi_write(struct file *file, const char __user *buf, size_t size, loff_t * ppos)
+{
+	return 0;
+}
+
+static unsigned int spi_poll(struct file *pFile, poll_table *pPollTable)
+{
+	return 0;
+}
+
+static int spi_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg)
+{
+	int ret = 0;
+
+	/* Argument checking */
+	if (_IOC_TYPE(cmd) != SPI_MOD_IOCTL_MAGIC) {
+		printk("%s: invalid SPI MOD Magic Num %i %i\n", __func__, _IOC_TYPE(cmd), SPI_MOD_IOCTL_MAGIC);
+		return -ENOTTY;
+	}
+
+	if ((_IOC_NR(cmd) > SPI_MOD_IOCTL_MAX) || (_IOC_NR(cmd) < SPI_MOD_IOCTL_MIN)) {
+		printk("%s: invalid SPI MOD IOCTL request\n", __func__);
+		return -ENOTTY;
+	}
+
+	if (_IOC_DIR(cmd) & _IOC_READ) {
+		ret = !access_ok(VERIFY_WRITE, (void __user*)arg, _IOC_SIZE(cmd));
+	} 
+	else if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		ret = !access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd));
+	}
+
+	if (ret) {
+		printk("%s: invalid SPI MOD access type %i from cmd %i\n", __func__, _IOC_DIR(cmd), cmd);
+		return -EFAULT;
+	}
+
+	switch (cmd) {
+		
+		case SPI_MOD_IOX_REG_READ:
+			//printk("ioctl: SPI_MOD_IOX_REG_READ\n");
+			ret = spi_read_reg(arg);
+			break;
+		
+		case SPI_MOD_IOX_REG_WRITE:
+			//printk("ioctl: SPI_MOD_IOX_REG_WRITE\n");
+			ret = spi_write_reg(arg);
+			break;
+
+		default:
+			printk("%s: error, ioctl command(0x%x) not supported !!!\n", __func__, cmd);
+			ret = -EFAULT;
+			break;
+	}
+
+	return ret;
+}
+
+static int spi_read_reg(unsigned long arg)
+{
+	SpiModRWObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SpiModRWObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	mvSysTdmIntDisable(data.lineId);
+
+	mvSysTdmSpiRead(data.lineId, data.pCmdBuff, data.cmdSize, data.pDataBuff, data.dataSize);
+
+	mvSysTdmIntEnable(data.lineId);
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SpiModRWObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int spi_write_reg(unsigned long arg)
+{
+	SpiModRWObjType data;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(SpiModRWObjType))) {
+		printk("%s: copy_from_user failed\n", __func__);
+		return -EFAULT;
+	}
+	
+	mvSysTdmIntDisable(data.lineId);
+
+	mvSysTdmSpiWrite(data.lineId, data.pCmdBuff, data.cmdSize, data.pDataBuff, data.dataSize);
+
+	mvSysTdmIntEnable(data.lineId);
+
+	/* Copy status back to user */
+	if(copy_to_user((void*)arg, &data, sizeof(SpiModRWObjType))) {
+		printk("%s: copy_to_user failed\n", __func__);
+		return  -EFAULT;
+	}
+
+	return 0;
+}
+
+static int spi_open(struct inode *pInode, struct file *pFile)
+{
+	try_module_get(THIS_MODULE);
+	return 0;
+}
+
+static int spi_release(struct inode *pInode, struct file *pFile)
+{
+	module_put(THIS_MODULE);
+	return 0;
+}
+
+int __init spi_module_init(void)
+{
+	int status = 0;
+
+	printk("Loading Marvell %s device\n", SPI_MOD_NAME);
+	
+	status = misc_register(&spi_misc_dev);
+
+	/* Register SPI device module */
+	if (status < 0) {
+		printk("Error, failed to load %s module(%d)\n", SPI_MOD_NAME, status);
+		return status;
+	}
+	return 0;
+}
+
+void __exit spi_module_exit(void)
+{
+	printk("Unloading %s device module\n", SPI_MOD_NAME);
+
+	/* Unregister SPI misc device */
+	misc_deregister(&spi_misc_dev);
+
+	return;
+}
+
+/* Module stuff */
+module_init(spi_module_init);
+module_exit(spi_module_exit);
+MODULE_DESCRIPTION("SPI Access Device");
+MODULE_AUTHOR("Nadav Haklai <nadavh@marvell.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/spi/spi_dev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/spi/spi_dev.h
new file mode 100644
index 0000000..d52b248
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/spi/spi_dev.h
@@ -0,0 +1,95 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _SPI_DEV_H_
+#define _SPI_DEV_H_
+
+
+#define SPI_MOD_IOCTL_MAGIC           'z'
+
+#define SPI_MOD_IOCTL_MIN 			1
+
+/* SI-API System Configuration Functions */
+#define SPI_MOD_IOX_REG_READ			_IOWR(SPI_MOD_IOCTL_MAGIC, 1, SpiModRWObjType)
+#define SPI_MOD_IOX_REG_WRITE			_IOWR(SPI_MOD_IOCTL_MAGIC, 2, SpiModRWObjType)
+
+#define SPI_MOD_IOCTL_MAX 			2
+
+/********************** SPI register read/write ********************/
+typedef struct SpiModRWObj {
+	/* Input arg(s) */
+	unsigned short	lineId;
+	unsigned char	*pCmdBuff;
+	unsigned char	cmdSize;
+	unsigned char	*pDataBuff;
+	unsigned char	dataSize;
+} SpiModRWObjType;
+
+/* APIs */
+int spi_module_init(void);
+void spi_module_exit(void);
+
+
+#endif /*_SPI_DEV_H_*/
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.c
new file mode 100755
index 0000000..427b8fb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.c
@@ -0,0 +1,190 @@
+
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************/
+
+/* Marvell Telephony Adaptation Layer */
+
+#include "tal.h"
+#include "tdm_if.h"
+
+/* GLobals */
+static tdm_if_register_ops_t tal_tdm_if_register_ops;
+static tal_mmp_ops_t* tal_mmp_ops;
+static tdm_if_params_t tal_tdm_if_params;
+ 
+/* Static APIs */
+static void tal_pcm_tx_callback(uint8_t* tx_buff, int size);
+static void tal_pcm_rx_callback(uint8_t* rx_buff, int size);
+
+/*---------------------------------------------------------------------------*
+ * tal_init
+ * Issue telephony subsytem initialization and callbacks registration
+ *---------------------------------------------------------------------------*/
+tal_stat_t tal_init(tal_params_t* tal_params, tal_mmp_ops_t* mmp_ops)
+{
+	if((tal_params == NULL) || (mmp_ops == NULL))
+	{
+		mvOsPrintf("%s: Error, bad parameters\n",__FUNCTION__);
+		return TAL_STAT_BAD_PARAM;
+	}
+
+	if(mmp_ops->tal_mmp_rx_callback == NULL ||
+	   mmp_ops->tal_mmp_tx_callback == NULL) 
+	{
+		mvOsPrintf("%s:Error, missing callbacks(MMP)\n",__FUNCTION__);
+		return TAL_STAT_BAD_PARAM;
+	}
+
+	/* Convert tal_params to tdm_if_params */
+	memcpy(&tal_tdm_if_params, tal_params, sizeof(tal_params_t));
+
+	/* Assign MMP operations */
+	tal_mmp_ops = mmp_ops;
+
+	/* Clear tdm_if operations structure */
+	memset(&tal_tdm_if_register_ops, 0, sizeof(tdm_if_register_ops_t));
+	
+	/* Assign tdm_if operations */
+	tal_tdm_if_register_ops.tdm_if_pcm_ops.pcm_tx_callback = tal_pcm_tx_callback;
+	tal_tdm_if_register_ops.tdm_if_pcm_ops.pcm_rx_callback = tal_pcm_rx_callback;
+
+	/* Dispatch tdm_if driver */
+	if(tdm_if_init(&tal_tdm_if_register_ops, &tal_tdm_if_params) != MV_OK)
+	{
+		mvOsPrintf("%s: Error, could not initialize tdm_if driver !!!\n",__FUNCTION__);
+		return TAL_STAT_INIT_ERROR;
+	}
+
+	/* Verify control callbacks were assigned properly */
+	if(tal_tdm_if_register_ops.tdm_if_ctl_ops.ctl_pcm_start == NULL ||
+	   tal_tdm_if_register_ops.tdm_if_ctl_ops.ctl_pcm_stop == NULL)
+	{
+		mvOsPrintf("%s:Error, missing callbacks(tdm_if)\n",__FUNCTION__);
+		return TAL_STAT_BAD_PARAM;
+	}
+
+	return TAL_STAT_OK;
+}
+
+
+/*---------------------------------------------------------------------------*
+ * tal_pcm_tx_completion
+ * Tx callback
+ *---------------------------------------------------------------------------*/
+
+static void tal_pcm_tx_callback(uint8_t* tx_buff, int size)
+{
+	tal_mmp_ops->tal_mmp_tx_callback(tx_buff, size);
+}
+
+/*---------------------------------------------------------------------------*
+ * tal_pcm_rx_completion
+ * Rx callback
+ *---------------------------------------------------------------------------*/
+
+static void tal_pcm_rx_callback(uint8_t* rx_buff, int size)
+{
+	tal_mmp_ops->tal_mmp_rx_callback(rx_buff, size);
+}
+
+/*---------------------------------------------------------------------------*
+ * tal_pcm_start
+ * Start PCM bus
+ *---------------------------------------------------------------------------*/
+tal_stat_t tal_pcm_start(void)
+{
+	tal_tdm_if_register_ops.tdm_if_ctl_ops.ctl_pcm_start();
+	return TAL_STAT_OK;
+}
+
+/*---------------------------------------------------------------------------*
+ * tal_pcm_stop
+ * Stop PCM bus
+ *---------------------------------------------------------------------------*/
+tal_stat_t tal_pcm_stop(void)
+{
+	tal_tdm_if_register_ops.tdm_if_ctl_ops.ctl_pcm_stop();
+	return TAL_STAT_OK;
+}
+
+/*---------------------------------------------------------------------------*
+ * tal_exit
+ * Stop TDM channels and release all resources
+ *---------------------------------------------------------------------------*/
+tal_stat_t tal_exit(void)
+{
+	tdm_if_exit();
+	return TAL_STAT_OK;
+}
+
+/*---------------------------------------------------------------------------*
+ * tal_stats_get
+ * Get TDM statistics
+ *---------------------------------------------------------------------------*/
+tal_stat_t tal_stats_get(tal_stats_t* tal_stats)
+{
+	tdm_if_stats_t stats;
+
+	tdm_if_stats_get(&stats);
+	memcpy(tal_stats, &stats, sizeof(tal_stats_t));
+
+	return TAL_STAT_OK;
+}
+
+/*---------------------------------------------------------------------------*
+ * tal_tdm_clk_config
+ * Config TDM clock
+ *---------------------------------------------------------------------------*/
+void tal_tdm_clk_config(void)
+{
+	mvCtrlTdmClkCtrlConfig();
+}
+
+#if defined(MV_TDM_USE_DCO)
+/*---------------------------------------------------------------------------*
+ * tal_tdm_clk_get
+ * Get current TDM clock correction
+ *---------------------------------------------------------------------------*/
+int tal_tdm_clk_get(void)
+{
+	return mvCtrlTdmClkCtrlGet();
+}
+
+/*---------------------------------------------------------------------------*
+ * tal_tdm_clk_set
+ * Set TDM clock correction
+ *---------------------------------------------------------------------------*/
+void tal_tdm_clk_set(int correction)
+{
+	return mvCtrlTdmClkCtrlSet(correction);
+}
+#endif
+
+/* EXPORTS */
+EXPORT_SYMBOL(tal_init);
+EXPORT_SYMBOL(tal_pcm_start);
+EXPORT_SYMBOL(tal_pcm_stop);
+EXPORT_SYMBOL(tal_exit);
+EXPORT_SYMBOL(tal_stats_get);
+EXPORT_SYMBOL(tal_tdm_clk_config);
+#if defined(MV_TDM_USE_DCO)
+EXPORT_SYMBOL(tal_tdm_clk_get);
+EXPORT_SYMBOL(tal_tdm_clk_set);
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.h
new file mode 100755
index 0000000..d005b4f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tal.h
@@ -0,0 +1,78 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************/
+
+/* Marvell Telephony Adaptation Layer */
+
+#ifndef _TAL_H_
+#define _TAL_H_
+
+#include "mvOs.h" /* for kernel abstraction wrappers */
+
+/* Defines */
+#define TAL_MAX_PHONE_LINES	32
+
+/* Enumerators */
+typedef enum {
+	TAL_PCM_FORMAT_1BYTE = 1,
+	TAL_PCM_FORMAT_2BYTES = 2,
+	TAL_PCM_FORMAT_4BYTES = 4
+} tal_pcm_format_t;
+
+typedef enum {
+	TAL_STAT_OK = 0,
+	TAL_STAT_BAD_PARAM,
+	TAL_STAT_INIT_ERROR
+} tal_stat_t;
+
+/* Structures */
+typedef struct {
+	tal_pcm_format_t pcm_format;
+	unsigned short pcm_slot[TAL_MAX_PHONE_LINES];
+	unsigned char sampling_period;
+	unsigned short total_lines;
+	unsigned short test_enable;
+} tal_params_t;
+
+typedef struct {
+	int tdm_init;
+	unsigned int rx_miss;
+	unsigned int tx_miss;
+	unsigned int rx_over;
+	unsigned int tx_under;
+} tal_stats_t;
+
+typedef struct {
+	void (*tal_mmp_rx_callback)(unsigned char* rx_buff, int size);
+	void (*tal_mmp_tx_callback)(unsigned char* tx_buff, int size);
+} tal_mmp_ops_t;
+
+/* APIs */
+tal_stat_t tal_init(tal_params_t* tal_params, tal_mmp_ops_t* mmp_ops);
+tal_stat_t tal_stats_get(tal_stats_t* tal_stats);
+tal_stat_t tal_pcm_start(void);
+tal_stat_t tal_pcm_stop(void);
+tal_stat_t tal_exit(void);
+void tal_tdm_clk_config(void);
+#if defined(MV_TDM_USE_DCO)
+int tal_tdm_clk_get(void);
+void tal_tdm_clk_set(int correction);
+#endif
+
+#endif /* _TAL_H */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.c
new file mode 100755
index 0000000..4ae4bbc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.c
@@ -0,0 +1,550 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include "tdm_if.h"
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#ifndef CONFIG_MV_TDM_SUPPORT
+#include "gpp/mvGppRegs.h"
+#endif
+
+
+/* TDM Interrupt Service Routine */
+static irqreturn_t tdm_if_isr(int irq, void* dev_id);
+
+/* PCM start/stop */
+static void tdm_if_pcm_start(void);
+static void tdm_if_pcm_stop(void);
+
+/* Rx/Tx Tasklets  */
+#if !(defined CONFIG_MV_PHONE_USE_IRQ_PROCESSING) && !(defined CONFIG_MV_PHONE_USE_FIQ_PROCESSING)
+static void tdm_if_pcm_rx_process(unsigned long arg);
+static void tdm_if_pcm_tx_process(unsigned long arg);
+#else
+static inline void tdm_if_pcm_rx_process(void);
+static inline void tdm_if_pcm_tx_process(void);
+#endif
+/* TDM proc-fs statistics */
+static int proc_tdm_init_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr);
+static int proc_rx_miss_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr);
+static int proc_tx_miss_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr);
+static int proc_rx_over_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr);
+static int proc_tx_under_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr);
+
+
+/* Module */
+static int __init tdm_if_module_init(void);
+static void __exit tdm_if_module_exit(void);
+
+/* Globals */
+static tdm_if_register_ops_t* tdm_if_register_ops;
+#if !(defined CONFIG_MV_PHONE_USE_IRQ_PROCESSING) && !(defined CONFIG_MV_PHONE_USE_FIQ_PROCESSING)
+static DECLARE_TASKLET(tdm_if_rx_tasklet, tdm_if_pcm_rx_process, 0);
+static DECLARE_TASKLET(tdm_if_tx_tasklet, tdm_if_pcm_tx_process, 0);
+#endif
+static DEFINE_SPINLOCK(tdm_if_lock);
+static unsigned char *rxBuff = NULL, *txBuff = NULL;
+static char irqnr;
+static unsigned int rx_miss = 0, tx_miss = 0;
+static unsigned int rx_over = 0, tx_under = 0;
+static struct proc_dir_entry *tdm_stats;
+static int pcm_enable = 0;
+static int irq_init = 0;
+static int tdm_init = 0;
+static int buff_size = 0;
+static unsigned short test_enable = 0;
+
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+extern int __must_check
+request_fiq(unsigned int irq, irq_handler_t handler, unsigned long flags,
+           const char *name, void *dev);
+extern void free_fiq(unsigned int irq, void *dev_id);
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
+static int proc_tdm_init_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr)
+{
+	return sprintf(buffer, "%u\n", tdm_init);
+}
+
+static int proc_rx_miss_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr)
+{
+	return sprintf(buffer, "%u\n", rx_miss);
+}
+
+static int proc_tx_miss_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr)
+{
+	return sprintf(buffer, "%u\n", tx_miss);
+}
+
+static int proc_rx_over_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr)
+{
+	return sprintf(buffer, "%u\n", rx_over);
+}
+
+static int proc_tx_under_read(char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr)
+{
+	return sprintf(buffer, "%u\n", tx_under);
+}
+
+MV_STATUS tdm_if_init(tdm_if_register_ops_t* register_ops, tdm_if_params_t* tdm_if_params)
+{
+	MV_TDM_PARAMS tdm_params;
+	
+	printk("Loading Marvell Telephony Driver\n");
+
+	/* Check if any SLIC module exists */
+	if(mvBoardTdmDevicesCountGet() == 0) {
+		mvCtrlPwrClckSet(TDM_32CH_UNIT_ID, 0, MV_FALSE);
+		mvCtrlPwrClckSet(TDM_2CH_UNIT_ID, 0, MV_FALSE);
+		printk("%s: Warning, no SLIC module is connected\n",__FUNCTION__);
+		return MV_OK;
+	}
+
+	/* Check that selected TDM unit is active */
+	if (MV_FALSE == mvCtrlPwrClckGet(mvCtrlTdmUnitTypeGet(), 0)) {
+		printk("%s: Warning, TDM is powered off\n",__FUNCTION__);
+		return MV_OK;
+	}
+
+	/* Shut down unused unit */
+	if(mvCtrlTdmUnitTypeGet() == TDM_2CH_UNIT_ID) {
+		mvCtrlPwrClckSet(TDM_32CH_UNIT_ID, 0, MV_FALSE);
+	}
+	else { /* TDM_32CH_UNIT_ID */
+		mvCtrlPwrClckSet(TDM_2CH_UNIT_ID, 0, MV_FALSE);
+	}
+
+	if((register_ops == NULL) || (tdm_if_params == NULL)) {
+		printk("%s: bad parameters\n",__FUNCTION__);
+		return MV_ERROR;
+
+	}
+
+	/* Check callbacks */
+	if(register_ops->tdm_if_pcm_ops.pcm_tx_callback == NULL ||
+	   register_ops->tdm_if_pcm_ops.pcm_rx_callback == NULL ) {
+		printk("%s: missing parameters\n",__FUNCTION__);
+		return MV_ERROR;
+	}
+
+	/* Reset globals */
+	rxBuff = txBuff = NULL;
+#ifdef CONFIG_MV_TDM_SUPPORT
+	pcm_enable = 0;
+#else
+	pcm_enable = 1;
+#endif
+	irq_init = 0;
+	tdm_init = 0;
+
+	/* Extract test enable */
+	test_enable = tdm_if_params->test_enable;
+
+	/* Calculate Rx/Tx buffer size(use in callbacks) */
+	buff_size = (tdm_if_params->pcm_format * tdm_if_params->total_lines * 80 * 
+				(tdm_if_params->sampling_period/MV_TDM_BASE_SAMPLING_PERIOD));
+
+	/* Extract TDM irq number */
+	irqnr = mvCtrlTdmUnitIrqGet();
+
+	/* Enable Marvell tracing */
+	TRC_START();
+	TRC_INIT();
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	/* Assign TDM parameters */
+	memcpy(&tdm_params, tdm_if_params, sizeof(MV_TDM_PARAMS));
+
+	/* Assign control callbacks */
+	tdm_if_register_ops = register_ops;
+	tdm_if_register_ops->tdm_if_ctl_ops.ctl_pcm_start = tdm_if_pcm_start;
+	tdm_if_register_ops->tdm_if_ctl_ops.ctl_pcm_stop = tdm_if_pcm_stop;
+
+	/* TDM init */
+	if(mvSysTdmInit(&tdm_params) != MV_OK) {
+			printk("%s: Error, TDM initialization failed !!!\n",__FUNCTION__);
+			return MV_ERROR;
+	}
+	tdm_init = 1;
+
+	/* Register TDM interrupt */
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+       if (request_fiq(irqnr, tdm_if_isr, IRQF_DISABLED, "tdm", NULL)) {
+               printk("%s: Failed to connect fiq(%d)\n", __FUNCTION__, irqnr);
+               return MV_ERROR;
+       }
+#else /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+	if (request_irq(irqnr, tdm_if_isr, IRQF_DISABLED, "tdm", NULL)) {
+		printk("%s: Failed to connect irq(%d)\n", __FUNCTION__, irqnr);
+		return MV_ERROR;
+	}
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
+	irq_init = 1;
+
+	/* Create TDM procFS statistics */
+	tdm_stats = proc_mkdir("tdm", NULL);
+	create_proc_read_entry("tdm_init", 0, tdm_stats, proc_tdm_init_read, NULL);
+	create_proc_read_entry("rx_miss", 0, tdm_stats, proc_rx_miss_read, NULL);
+	create_proc_read_entry("tx_miss", 0, tdm_stats, proc_tx_miss_read, NULL);
+	create_proc_read_entry("rx_over", 0, tdm_stats, proc_rx_over_read, NULL);
+	create_proc_read_entry("tx_under", 0, tdm_stats, proc_tx_under_read, NULL);
+
+	TRC_REC("Marvell Telephony Driver Loaded Successfully\n");
+
+#ifdef CONFIG_MV_COMM_UNIT_SUPPORT
+	/* WA to stop the MCDMA gracefully after commUnit initialization */
+	tdm_if_pcm_stop();
+#endif
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return MV_OK;
+}
+
+
+void tdm_if_exit(void)
+{
+	/* Check if already stopped */
+	if(!irq_init && !pcm_enable && !tdm_init)
+		return;
+
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	if(irq_init) {
+		/* Release interrupt */
+#ifndef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+                free_irq(irqnr, NULL);
+#else /* !CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+               free_fiq(irqnr, NULL);
+#endif /* !CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+		irq_init = 0;
+	}
+
+	/* Stop PCM data sampling */
+	if(pcm_enable)
+		tdm_if_pcm_stop();
+
+	if(tdm_init) {
+#ifdef CONFIG_MV_TDM_SUPPORT
+		mvTdmRelease();
+#else
+		mvCommUnitRelease();
+#endif
+		tdm_init = 0;
+	}
+
+	/* Remove proc directory & entries */
+	remove_proc_entry("tdm_init", tdm_stats);
+	remove_proc_entry("rx_miss", tdm_stats);
+	remove_proc_entry("tx_miss", tdm_stats);
+	remove_proc_entry("rx_over", tdm_stats);
+	remove_proc_entry("tx_under", tdm_stats);
+	remove_proc_entry("tdm", NULL);
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+
+	/* Dump output and release Marvell trace resources */
+	TRC_OUTPUT(0, 1);
+	TRC_RELEASE();
+}
+
+static void tdm_if_pcm_start(void)
+{
+	unsigned long flags;
+
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	spin_lock_irqsave(&tdm_if_lock, flags);
+	if(!pcm_enable) {
+		rxBuff = txBuff = NULL;
+		pcm_enable = 1;
+#ifdef CONFIG_MV_TDM_SUPPORT
+		mvTdmPcmStart();
+#else
+		mvCommUnitPcmStart();
+#endif
+	}
+	spin_unlock_irqrestore(&tdm_if_lock, flags);
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return;
+}
+
+static void tdm_if_pcm_stop(void)
+{
+	unsigned long flags;
+
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	spin_lock_irqsave(&tdm_if_lock, flags);
+	if(pcm_enable) {
+		pcm_enable = 0;
+		rxBuff = txBuff = NULL;
+#ifdef CONFIG_MV_TDM_SUPPORT
+		mvTdmPcmStop();
+#else
+		mvCommUnitPcmStop();
+#endif
+	}
+	spin_unlock_irqrestore(&tdm_if_lock, flags);
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return;
+}
+
+static irqreturn_t tdm_if_isr(int irq, void* dev_id)
+{
+	MV_TDM_INT_INFO tdm_int_info;
+	unsigned int int_type;
+
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	/* Extract interrupt information from low level ISR */
+#ifdef CONFIG_MV_TDM_SUPPORT
+	mvTdmIntLow(&tdm_int_info);
+#else
+	mvCommUnitIntLow(&tdm_int_info);
+#endif
+
+	int_type = tdm_int_info.intType;
+	/*device_id = tdm_int_info.cs;*/
+	
+	/* Nothing to do - return */
+	if(int_type == MV_EMPTY_INT)
+		goto out;
+
+	/* Support multiple interrupt handling */
+	/* RX interrupt */
+	if(int_type & MV_RX_INT) {
+		if(rxBuff != NULL) {
+			rx_miss++;
+			TRC_REC("%s: Warning, missed Rx buffer processing !!!\n",__FUNCTION__);
+		}
+		else {
+			rxBuff = tdm_int_info.tdmRxBuff;
+#if (defined CONFIG_MV_PHONE_USE_IRQ_PROCESSING) || (defined CONFIG_MV_PHONE_USE_FIQ_PROCESSING)
+			TRC_REC("%s: running Rx in ISR\n", __FUNCTION__);
+			tdm_if_pcm_rx_process();
+#else
+			/* Schedule Rx processing within SOFT_IRQ context */
+			TRC_REC("%s: schedule Rx tasklet\n", __FUNCTION__);
+			tasklet_hi_schedule(&tdm_if_rx_tasklet);
+#endif
+		}
+	}
+
+	/* TX interrupt */
+	if(int_type & MV_TX_INT) {
+		if(txBuff != NULL) {
+			tx_miss++;
+			TRC_REC("%s: Warning, missed Tx buffer processing !!!\n",__FUNCTION__);
+		}
+		else {
+			txBuff = tdm_int_info.tdmTxBuff;
+#if (defined CONFIG_MV_PHONE_USE_IRQ_PROCESSING) || (defined CONFIG_MV_PHONE_USE_FIQ_PROCESSING)		
+			TRC_REC("%s: running Tx in ISR\n", __FUNCTION__);
+			tdm_if_pcm_tx_process();
+#else
+			/* Schedule Tx processing within SOFT_IRQ context */
+			TRC_REC("%s: schedule Tx tasklet\n", __FUNCTION__);
+			tasklet_hi_schedule(&tdm_if_tx_tasklet);
+#endif
+		}
+	}
+
+	/* PHONE interrupt */
+	if(int_type & MV_PHONE_INT) {
+		/* TBD */
+	}
+
+	/* ERROR interrupt */
+	if(int_type & MV_ERROR_INT) {
+		if(int_type & MV_RX_ERROR_INT)
+			rx_over++;
+
+		if(int_type & MV_TX_ERROR_INT)
+			tx_under++;
+	}
+
+
+out:
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return IRQ_HANDLED;
+}
+#if (defined CONFIG_MV_PHONE_USE_IRQ_PROCESSING) || (defined CONFIG_MV_PHONE_USE_FIQ_PROCESSING)
+static inline void tdm_if_pcm_rx_process(void)
+#else
+/* Rx tasklet */
+static void tdm_if_pcm_rx_process(unsigned long arg)
+#endif
+{
+	TRC_REC("->%s\n",__FUNCTION__);
+	if(pcm_enable) {
+		if(rxBuff == NULL) {
+			TRC_REC("%s: Error, empty Rx processing\n",__FUNCTION__);
+			return;
+		}
+
+		/* Fill TDM Rx aggregated buffer */
+#ifdef CONFIG_MV_TDM_SUPPORT
+		if(mvTdmRx(rxBuff) == MV_OK)
+			tdm_if_register_ops->tdm_if_pcm_ops.pcm_rx_callback(rxBuff, buff_size); /* Dispatch Rx handler */
+#else
+		if(mvCommUnitRx(rxBuff) == MV_OK) {
+			tdm_if_register_ops->tdm_if_pcm_ops.pcm_rx_callback(rxBuff, buff_size); /* Dispatch Rx handler */
+			/* Since data buffer is shared among MCDMA and CPU, need to invalidate 	
+				before it accessed by MCDMA	*/
+			mvOsCacheInvalidate(NULL, rxBuff, buff_size);
+		}
+#endif
+		else
+			printk("%s: could not fill Rx buffer\n",__FUNCTION__);
+
+	}
+	
+	/* Clear rxBuff for next iteration */
+	rxBuff = NULL;
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return;
+}
+
+#if (defined CONFIG_MV_PHONE_USE_IRQ_PROCESSING) || (defined CONFIG_MV_PHONE_USE_FIQ_PROCESSING)
+static inline void tdm_if_pcm_tx_process(void)
+#else
+/* Tx tasklet */
+static void tdm_if_pcm_tx_process(unsigned long arg)
+#endif
+{
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	if(pcm_enable) {
+		if(txBuff == NULL) {
+			TRC_REC("%s: Error, empty Tx processing\n",__FUNCTION__);
+			return;
+		}
+
+		/* Dispatch Tx handler */
+		tdm_if_register_ops->tdm_if_pcm_ops.pcm_tx_callback(txBuff, buff_size);
+
+		if(test_enable == 0) {
+			/* Fill Tx aggregated buffer */
+#ifdef CONFIG_MV_TDM_SUPPORT
+			if(mvTdmTx(txBuff) != MV_OK)
+#else
+			if(mvCommUnitTx(txBuff) != MV_OK)
+#endif /* CONFIG_MV_TDM_SUPPORT */
+				printk("%s: could not fill Tx buffer\n",__FUNCTION__);
+		}
+	}
+
+	/* Clear txBuff for next iteration */
+	txBuff = NULL;
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return;
+}
+
+void tdm_if_stats_get(tdm_if_stats_t* tdm_if_stats)
+{
+	tdm_if_stats->tdm_init = tdm_init;
+	tdm_if_stats->rx_miss = rx_miss;
+	tdm_if_stats->tx_miss = tx_miss;
+	tdm_if_stats->rx_over = rx_over;
+	tdm_if_stats->tx_under = tx_under;
+	
+	return;
+}
+
+static int __init tdm_if_module_init(void)
+{
+	/* The real init is done later */
+	return 0;
+}
+
+static void __exit tdm_if_module_exit(void)
+{
+	tdm_if_exit();
+	return;
+}
+
+/* Module stuff */
+module_init(tdm_if_module_init);
+module_exit(tdm_if_module_exit);
+MODULE_DESCRIPTION("Marvell TDM I/F Device Driver - www.marvell.com");
+MODULE_AUTHOR("Eran Ben-Avi <benavi@marvell.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.h
new file mode 100755
index 0000000..964cef0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/tdm_if.h
@@ -0,0 +1,125 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _TDM_IF_H_
+#define _TDM_IF_H_
+
+#include "mvSysTdmApi.h"
+#ifdef CONFIG_MV_TDM_SUPPORT
+ #include "voiceband/tdm/mvTdm.h"
+#else
+ #include "voiceband/commUnit/mvCommUnit.h"
+#endif
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ctrlEnv/mvCtrlEnvRegs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+
+
+/* Structures */
+typedef struct {
+	int tdm_init;
+	unsigned int rx_miss;
+	unsigned int tx_miss;
+	unsigned int rx_over;
+	unsigned int tx_under;
+} tdm_if_stats_t;
+
+typedef struct {
+	MV_PCM_FORMAT pcm_format;
+	unsigned short pcm_slot[32];
+	unsigned char sampling_period;
+	unsigned short total_lines;
+	unsigned short test_enable;
+} tdm_if_params_t;
+
+/* control callbacks */
+typedef struct {
+	void (*ctl_pcm_start)(void);
+	void (*ctl_pcm_stop)(void);
+} tdm_if_ctl_ops_t;
+
+/* pcm callbacks */
+typedef struct {
+	void (*pcm_tx_callback)(unsigned char* tx_buff, int size);
+	void (*pcm_rx_callback)(unsigned char* rx_buff, int size);
+} tdm_if_pcm_ops_t;
+
+typedef struct {
+	tdm_if_ctl_ops_t tdm_if_ctl_ops;
+	tdm_if_pcm_ops_t tdm_if_pcm_ops;
+} tdm_if_register_ops_t;
+
+/* APIs */
+void tdm_if_stats_get(tdm_if_stats_t* tdm_if_stats);
+MV_STATUS tdm_if_init(tdm_if_register_ops_t* register_ops, tdm_if_params_t* tdm_if_params);
+void tdm_if_exit(void);
+#if defined(MV_TDM_USE_DCO)
+MV_VOID mvCtrlTdmDcoReset(MV_VOID);
+MV_32 mvCtrlTdmDcoGet(MV_VOID);
+MV_VOID mvCtrlTdmDcoSet(MV_32 DcoCorrection);
+#endif
+
+#endif /*_TDM_IF_H_*/
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/Makefile
new file mode 100755
index 0000000..ce89118
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/Makefile
@@ -0,0 +1,12 @@
+
+
+#
+# Makefile for the Marvell Phone Device Driver Test Module
+#
+#
+
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+obj-$(CONFIG_MV_INCLUDE_TDM) += tdm_dev.o
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/tdm_dev.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/tdm_dev.c
new file mode 100755
index 0000000..c164b89
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/tdm_dev.c
@@ -0,0 +1,456 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include "mvSysHwConfig.h"
+#include "mvSysTdmConfig.h"
+#include "tdm_dev.h"
+#include "mv_phone/tdm/tdm_if.h"
+#include "mv_phone/tdm/tal.h"
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#ifdef CONFIG_MV_TDM_SUPPORT
+ #include "voiceband/tdm/mvTdm.h"
+#else
+ #include "voiceband/commUnit/mvCommUnit.h"
+#endif
+
+#define TDM_DEV_NAME 	"tdm"
+#define DISABLE		0
+#define ENABLE		1
+#define MAX_POLL	12 /* millisecond */
+
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+extern unsigned int mvCtrlTdmUnitIrqGet(void);
+extern void mv_mask_fiq(unsigned int irq);
+extern void mv_unmask_fiq(unsigned int irq);
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
+/* Globals */
+static DECLARE_WAIT_QUEUE_HEAD(tdm_dev_wait);
+static DEFINE_SPINLOCK(tdm_dev_lock);
+static tal_params_t tdm_dev_params;
+static tal_mmp_ops_t tdm_dev_ops;
+static atomic_t tdm_init, rx_ready, tx_ready;
+static unsigned char *rx_buff_p = NULL, *tx_buff_p = NULL;
+static unsigned char rx_temp_buff[MV_TDM_TOTAL_CHANNELS * MV_TDM_TOTAL_CH_SAMPLES * 4];
+#if defined(MV_TDM_USE_DCO)
+static tdm_dev_clk_t tdm_dev_clk;
+#endif
+
+/* Forward declarations */
+static int tdm_dev_tdm_start(unsigned long arg);
+static ssize_t tdm_dev_read(struct file *file_p, char __user *buf, size_t size, loff_t * ppos);
+static ssize_t tdm_dev_write(struct file *file_p, const char __user *buf, size_t size, loff_t * ppos);
+static unsigned int tdm_dev_poll(struct file *file_p, poll_table *poll_table_p);
+static int tdm_dev_ioctl(struct inode *inode_p, struct file *file_p, unsigned int cmd, unsigned long arg);
+static int tdm_dev_open(struct inode *inode_p, struct file *file_p);
+static int tdm_dev_release(struct inode *inode_p, struct file *file_p);
+void tdm_dev_tx_callback(unsigned char* tx_buff, int size);
+void tdm_dev_rx_callback(unsigned char* rx_buff, int size);
+static int __init tdm_dev_init(void);
+static void __exit tdm_dev_exit(void);
+
+static struct file_operations tdm_dev_fops = {
+    owner:      THIS_MODULE,
+    llseek:     NULL,
+    read:       tdm_dev_read,
+    write:      tdm_dev_write,
+    poll:       tdm_dev_poll,
+    ioctl:      tdm_dev_ioctl,
+    open:       tdm_dev_open,
+    release:    tdm_dev_release,
+    fasync:     NULL
+};
+
+static struct miscdevice tdm_dev_misc_dev = {
+	.minor = TDMDEV_MINOR,
+	.name = TDM_DEV_NAME,
+	.fops = &tdm_dev_fops,
+};
+
+
+static int __init tdm_dev_init(void)
+{
+	int status;
+
+	printk("Loading Marvell tdm device\n");
+	status = misc_register(&tdm_dev_misc_dev);
+
+	/* Register tdm device */
+	if (status < 0) {
+		printk("Error, failed to load %s device(status %d)\n", TDM_DEV_NAME, status);
+		return status;
+	}
+
+	atomic_set(&tdm_init, DISABLE);
+
+	return 0;
+}
+
+static int tdm_dev_tdm_start(unsigned long arg)
+{
+	tdm_dev_params_t data;
+	int i;
+
+	/* Get user data */
+	if(copy_from_user(&data, (void*)arg, sizeof(tdm_dev_params_t))) {
+		printk("%s: copy_from_user failed\n", __FUNCTION__);
+		return -EFAULT;
+	}
+
+	/* Check parameters */
+	if((data.pcm_format != 1) && (data.pcm_format != 2) && (data.pcm_format != 4)) {
+		printk("%s: bad parameter(pcm_format=%u)\n", __FUNCTION__, data.pcm_format);
+		return -EFAULT;
+	}
+
+	if(data.total_lines > MV_TDM_TOTAL_CHANNELS) {
+		printk("%s: bad parameter(data.total_lines=%u)\n", __FUNCTION__, data.total_lines);
+		return -EFAULT;
+	}
+
+	tdm_dev_params.pcm_format = (tal_pcm_format_t)data.pcm_format;
+	/* Fill time slot table */
+	for(i = 0; i < data.total_lines; i++)
+		tdm_dev_params.pcm_slot[i] = ((i+1) * data.pcm_format); /* skip time slot #0 */
+
+	tdm_dev_params.sampling_period = MV_TDM_BASE_SAMPLING_PERIOD;
+	tdm_dev_params.total_lines = data.total_lines;
+	tdm_dev_params.test_enable = 1;
+
+	/* Assign Rx/Tx callbacks */
+	tdm_dev_ops.tal_mmp_rx_callback = tdm_dev_rx_callback;
+	tdm_dev_ops.tal_mmp_tx_callback = tdm_dev_tx_callback;
+
+	if(tal_init(&tdm_dev_params, &tdm_dev_ops) != MV_OK) {
+		printk("%s: Error, could not init tdm driver\n",__FUNCTION__);
+		return -EFAULT;
+	}
+
+	/* Prepare globals */
+	atomic_set(&tdm_init, ENABLE);
+	atomic_set(&rx_ready, DISABLE);
+	atomic_set(&tx_ready, DISABLE);
+	rx_buff_p = NULL;
+	tx_buff_p = NULL;
+
+	return 0;
+}
+
+static ssize_t tdm_dev_read(struct file *file_p, char __user *buf, size_t size, loff_t * ppos)
+{
+	size_t ret = size;
+
+	TRC_REC("->%s\n",__FUNCTION__);
+
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	mv_mask_fiq(mvCtrlTdmUnitIrqGet());
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+	if(rx_buff_p != NULL) {
+		if (copy_to_user(buf, rx_buff_p, size))
+			ret = -EFAULT;
+		rx_buff_p = NULL;
+		atomic_set(&rx_ready, DISABLE);
+	} else {
+		ret = 0;
+		TRC_REC("%s: missed Rx buffer\n",__FUNCTION__);
+	}
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	mv_unmask_fiq(mvCtrlTdmUnitIrqGet());
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+	return ret;
+}
+
+static ssize_t tdm_dev_write(struct file *file_p, const char __user *buf, size_t size, loff_t * ppos)
+{
+	unsigned long flags = 0;
+	MV_STATUS status;
+	size_t ret = size;
+
+	TRC_REC("->%s\n",__FUNCTION__);
+
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	mv_mask_fiq(mvCtrlTdmUnitIrqGet());
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+	if(tx_buff_p != NULL) {
+		if (copy_from_user(tx_buff_p, buf, size))
+			ret = -EFAULT;
+		atomic_set(&tx_ready, DISABLE);
+		spin_lock_irqsave(&tdm_dev_lock, flags);
+#ifdef CONFIG_MV_TDM_SUPPORT
+		status = mvTdmTx(tx_buff_p);
+#else
+		status = mvCommUnitTx(tx_buff_p);
+#endif
+		spin_unlock_irqrestore(&tdm_dev_lock, flags);
+		tx_buff_p = NULL;
+		if(status != MV_OK)
+			printk("%s: could not fill Tx buffer\n",__FUNCTION__);
+	} else {
+		ret = 0;
+		TRC_REC("%s: missed Tx buffer\n",__FUNCTION__);
+	}
+	TRC_REC("<-%s\n",__FUNCTION__);
+
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	mv_unmask_fiq(mvCtrlTdmUnitIrqGet());
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+	return ret;
+}
+
+static unsigned int tdm_dev_poll(struct file *file_p, poll_table *poll_table_p)
+{
+	int mask = 0, max_poll = 0;
+
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	while (!atomic_read(&rx_ready) && !atomic_read(&tx_ready) && (max_poll < MAX_POLL)) {
+		mdelay(1);
+		max_poll++;
+	}
+
+	if (max_poll >= MAX_POLL)
+		printk("%s: Warning, no Rx/Tx callback for at least 10ms\n",__FUNCTION__);
+
+	if (atomic_read(&rx_ready)) {
+		atomic_set(&rx_ready, DISABLE);
+		mask |= POLLIN | POLLRDNORM;	/* readable */
+		TRC_REC("poll can read\n");
+	}
+
+	if (atomic_read(&tx_ready)) {
+		atomic_set(&tx_ready, DISABLE);
+		mask |= POLLOUT | POLLWRNORM;	/* writable */
+		TRC_REC("poll can write\n");
+	}
+#else /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	poll_wait(file_p, &tdm_dev_wait, poll_table_p);
+
+	if(atomic_read(&rx_ready)) {
+		mask |= POLLIN | POLLRDNORM;	/* readable */
+		TRC_REC("poll can read\n");
+	}
+
+	if(atomic_read(&tx_ready)) {
+		mask |= POLLOUT | POLLWRNORM;	/* writable */
+		TRC_REC("poll can write\n");
+	}
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
+	return mask;
+}
+
+static int tdm_dev_ioctl(struct inode *inode_p, struct file *file_p, unsigned int cmd, unsigned long arg)
+{
+	int ret = 0;
+
+	/* Argument checking */
+	if (_IOC_TYPE(cmd) != TDM_DEV_IOCTL_MAGIC) {
+		printk("%s: invalid TDM DEV Magic Num %i %i\n", __FUNCTION__, _IOC_TYPE(cmd), TDM_DEV_IOCTL_MAGIC);
+		return -ENOTTY;
+	}
+
+	if ((_IOC_NR(cmd) > TDM_DEV_IOCTL_MAX) || (_IOC_NR(cmd) < TDM_DEV_IOCTL_MIN)) {
+		printk("%s: invalid TDM DEV IOCTL request\n", __FUNCTION__);
+		return -ENOTTY;
+	}
+
+	if (_IOC_DIR(cmd) & _IOC_READ) {
+		ret = !access_ok(VERIFY_WRITE, (void __user*)arg, _IOC_SIZE(cmd));
+	} 
+	else if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		ret = !access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd));
+	}
+
+	if (ret) {
+		printk("%s: invalid TDM DEV access type %i from cmd %i\n", __FUNCTION__, _IOC_DIR(cmd), cmd);
+		return -EFAULT;
+	}
+
+	switch (cmd) {
+		case TDM_DEV_TDM_START:
+			printk("ioctl: TDM_DEV_TDM_START\n");
+			ret = tdm_dev_tdm_start(arg);
+			break;
+
+		case TDM_DEV_TDM_STOP:
+			atomic_set(&tdm_init, DISABLE);
+			tal_exit();
+			printk("ioctl: TDM_DEV_TDM_STOP\n");
+			break;
+
+		case TDM_DEV_PCM_START:
+			printk("ioctl: TDM_DEV_PCM_START\n");
+			atomic_set(&rx_ready, DISABLE);
+			atomic_set(&tx_ready, DISABLE);
+			rx_buff_p = NULL;
+			tx_buff_p = NULL;
+			tal_pcm_start();
+			break;
+
+		case TDM_DEV_PCM_STOP:
+			tal_pcm_stop();
+			printk("ioctl: TDM_DEV_PCM_STOP\n");
+			break;
+
+#if defined(MV_TDM_USE_DCO)
+		case TDM_DEV_TDM_CLK_CONFIG:
+			mvCtrlTdmClkCtrlConfig();
+			printk("ioctl: TDM_DEV_TDM_CLK_CONFIG\n");
+			break;
+
+		case TDM_DEV_TDM_CLK_GET:
+			tdm_dev_clk.correction=mvCtrlTdmClkCtrlGet();
+			printk("ioctl: TDM_DEV_TDM_CLK_GET: %x\n", tdm_dev_clk.correction);
+			/* Put user data */
+			if(copy_to_user((void*)arg, &tdm_dev_clk, sizeof(tdm_dev_clk_t))) {
+				printk("%s: copy_to_user failed\n", __FUNCTION__);
+			return -EFAULT;
+			}
+			printk("ioctl: TDM_DEV_TDM_CLK_GET\n");
+			break;
+
+		case TDM_DEV_TDM_CLK_SET:
+			/* Get user data */
+			if(copy_from_user(&tdm_dev_clk, (void*)arg, sizeof(tdm_dev_clk_t))) {
+				printk("%s: copy_from_user failed\n", __FUNCTION__);
+			return -EFAULT;
+			}
+			printk("ioctl: TDM_DEV_TDM_CLK_SET: %x\n", tdm_dev_clk.correction);
+			mvCtrlTdmClkCtrlSet(tdm_dev_clk.correction);
+			printk("ioctl: TDM_DEV_TDM_CLK_SET\n");
+			break;
+#endif
+	}
+
+	return ret;
+}
+static int tdm_dev_open(struct inode *inode_p, struct file *file_p)
+{
+	try_module_get(THIS_MODULE);
+	return 0;
+}
+
+static int tdm_dev_release(struct inode *inode_p, struct file *file_p)
+{
+	module_put(THIS_MODULE);
+	return 0;
+}
+
+void tdm_dev_tx_callback(unsigned char* tx_buff, int size)
+{
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	tx_buff_p = tx_buff;
+	atomic_set(&tx_ready, ENABLE);
+#ifndef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	wake_up_interruptible(&tdm_dev_wait);
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return;
+}
+
+void tdm_dev_rx_callback(unsigned char* rx_buff, int size)
+{
+	TRC_REC("->%s\n",__FUNCTION__);
+
+	rx_buff_p = rx_temp_buff;
+	memcpy(rx_buff_p, rx_buff, size);
+	atomic_set(&rx_ready, ENABLE);
+#ifndef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	wake_up_interruptible(&tdm_dev_wait);
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
+	TRC_REC("<-%s\n",__FUNCTION__);
+	return;
+}
+
+static void __exit tdm_dev_exit(void)
+{
+	printk("Marvell telephony test device exits\n");
+
+	/* Stop TDM channels and release all resources */
+	tal_exit();
+
+	/* Unregister tdm misc device */
+	misc_deregister(&tdm_dev_misc_dev);
+}
+
+/* Module stuff */
+module_init(tdm_dev_init);
+module_exit(tdm_dev_exit);
+MODULE_DESCRIPTION("Marvell Telephony Test Device - www.marvell.com");
+MODULE_AUTHOR("Eran Ben-Avi <benavi@marvell.com>");
+MODULE_LICENSE("GPL");
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/tdm_dev.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/tdm_dev.h
new file mode 100755
index 0000000..d792125
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/tdm/test/tdm_dev.h
@@ -0,0 +1,97 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _TDM_DEV_H_
+#define _TDM_DEV_H_
+
+#define TDM_DEV_IOCTL_MAGIC		't'
+
+#define TDM_DEV_IOCTL_MIN 		1
+
+#define TDM_DEV_TDM_START		_IOWR(TDM_DEV_IOCTL_MAGIC, 1, tdm_dev_params_t)
+#define TDM_DEV_TDM_STOP		_IO(TDM_DEV_IOCTL_MAGIC, 2)
+#define TDM_DEV_PCM_START		_IO(TDM_DEV_IOCTL_MAGIC, 3)
+#define TDM_DEV_PCM_STOP		_IO(TDM_DEV_IOCTL_MAGIC, 4)
+
+#define TDM_DEV_IOCTL_MAX 		7
+
+#define TDM_DEV_TDM_CLK_CONFIG		_IOWR(TDM_DEV_IOCTL_MAGIC, 5, tdm_dev_clk_t)
+#if defined(MV_TDM_USE_DCO)
+#define TDM_DEV_TDM_CLK_GET		_IOWR(TDM_DEV_IOCTL_MAGIC, 6, tdm_dev_clk_t)
+#define TDM_DEV_TDM_CLK_SET		_IOWR(TDM_DEV_IOCTL_MAGIC, 7, tdm_dev_clk_t)
+
+typedef struct tdm_dev_clk {
+	int correction;
+} tdm_dev_clk_t;
+#endif /*_MV_TDM_USE_DCO_*/
+
+typedef struct tdm_dev_params {
+	unsigned char pcm_format;
+	unsigned short total_lines;
+} tdm_dev_params_t;
+
+/* APIs */
+
+#endif /*_TDM_DEV_H_*/
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/Kconfig
new file mode 100755
index 0000000..3ff1cd1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/Kconfig
@@ -0,0 +1,109 @@
+menu "SoC PON support"
+depends on MV_INCLUDE_PON
+
+config MV_PON_TCONTS
+        int "GPON maximum T-CONT's number"
+        default 8 
+        ---help---
+
+config MV_EPON_LLID
+        int "EPON maximum LLID number"
+        default 1
+        ---help---
+
+config PON_Z1
+	bool "Support for PON Z1 Driver"
+      	default y
+	---help---
+
+config PON_Z2
+	bool "Support for PON Z2 Driver"
+      	default n
+	---help---
+
+config PON_FPGA
+	bool "Support for PON Driver for FPGA"
+      	default n
+	---help---
+
+config  MV_GPON
+	bool "Support for Marvell GPON Driver"
+	depends on MV_INCLUDE_PON
+	default y
+	---help---
+
+config  MV_EPON
+	bool "Support for Marvell EPON Driver"
+	depends on MV_INCLUDE_PON
+	default y
+	---help---
+
+
+comment "GPON Driver Options"
+depends on MV_GPON
+
+config  MV_GPON_HW_INTERRUPT
+	bool "Support for GPON HW Interrupt"
+	depends on MV_GPON
+      	default y
+	---help---
+
+config  MV_GPON_DEBUG_PRINT
+	bool "Support for GPON Debug printing"
+	depends on MV_GPON
+      	default y
+	---help---
+
+config  MV_GPON_STATIC_GEM_PORT
+	bool "Support for GPON Static Gem Port"
+	depends on MV_GPON
+      	default y
+	---help---
+
+config  MV_GPON_PERFORMANCE_CHECK
+	bool "Support for GPON Performance Validation"
+	depends on MV_GPON
+      	default n
+	---help---
+
+comment "EPON Driver Options"
+depends on MV_EPON
+
+config  MV_EPON_HW_INTERRUPT
+	bool "Support for EPON HW Interrupt"
+	depends on MV_EPON
+      	default y
+	---help---
+
+config  MV_EPON_DBA_LOW_RATE_VALUE
+        int "DBA report low rate value (Bytes)"
+	depends on MV_EPON
+        default 2000 
+        ---help---
+        
+config  MV_EPON_DBA_LOW_RATE_THRESHOLD
+        int "DBA report low rate threshold (msec)"
+	depends on MV_EPON
+        default 20 
+        ---help---
+
+config  MV_EPON_DBA_LOW_RATE_CONST_VALUE
+        int "DBA report low rate const value (Bytes)"
+	depends on MV_EPON
+        default 256 
+        ---help---
+
+config  MV_EPON_DBA_HIGH_RATE_THRESHOLD
+        int "DBA report high rate threshold (Bytes)"
+	depends on MV_EPON
+        default 8192 
+        ---help---
+
+config  MV_EPON_DBA_HIGH_RATE_VALUE
+        int "DBA report high rate value (Bytes)"
+	depends on MV_EPON
+        default 2000 
+        ---help---
+
+endmenu
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/Makefile
new file mode 100755
index 0000000..78c0d54
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/Makefile
@@ -0,0 +1,52 @@
+#
+# Makefile for the Marvell Gpon driver
+#
+
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifdef CONFIG_MV_HAL_RULES_PATH
+include $(srctree)/include/config/auto.conf
+include $(srctree)/$(subst ",,$(CONFIG_MV_HAL_RULES_PATH))
+endif
+
+PON_OBJ += ../../mv_hal/pon/mvPonOnuRegs.o \
+	../../mv_hal/pon/mvPonOnuMac.o \
+	plat/ponOnuBoard.o \
+	plat/ponOnuLnxKsOs.o \
+	perf/ponOnuLnxKsMI.o
+
+GPON_OBJS += core/gpon/gponOnuAlloc.o \
+	core/gpon/gponOnuAlrm.o \
+	core/gpon/gponOnuApi.o \
+	core/gpon/gponOnuBer.o \
+        core/gpon/gponOnuDb.o \
+	core/gpon/gponOnuInit.o \
+	core/gpon/gponOnuIsr.o \
+	core/gpon/gponOnuMngr.o \
+	core/gpon/gponOnuMngrStateMachine.o \
+        core/gpon/gponOnuPm.o \
+	core/gpon/gponOnuSrvc.o \
+	perf/gpon/gponOnuLnxKsUI.o \
+	perf/gpon/gponOnuLnxKsMI.o \
+	plat/gpon/gponOnuBoard.o \
+	plat/gpon/gponOnuLnxKsOs.o
+
+EPON_OBJS += core/epon/eponOnuAlrm.o \
+	core/epon/eponOnuApi.o \
+        core/epon/eponOnuDb.o \
+	core/epon/eponOnuInit.o \
+	core/epon/eponOnuIsr.o \
+	core/epon/eponOnuMngr.o \
+        core/epon/eponOnuPm.o \
+	perf/epon/eponOnuLnxKsUI.o \
+	perf/epon/eponOnuLnxKsMI.o \
+	plat/epon/eponOnuBoard.o \
+	plat/epon/eponOnuLnxKsOs.o
+
+obj-$(CONFIG_MV_INCLUDE_PON) += mv_pon.o
+mv_pon-y := $(PON_OBJ)
+mv_pon-$(CONFIG_MV_GPON) += $(GPON_OBJS)
+mv_pon-$(CONFIG_MV_EPON) += $(EPON_OBJS)
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuAlrm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuAlrm.c
new file mode 100755
index 0000000..ff48289
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuAlrm.c
@@ -0,0 +1,264 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuAlrm.c                                             **/

+/**                                                                          **/

+/**  DESCRIPTION : This file implements ONU EPON Alarm and Statistics        **/

+/**                functionality                                             **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *      

+ *                                                                     

+ ******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "eponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/                                               

+#define __FILE_DESC__ "mv_pon/core/epon/eponOnuAlrm.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+MV_U32 onuEponPreviousAlarm = 0;

+MV_U32 onuEponCurrentAlarm  = 0;  

+MV_U32 onuEponLosAlarm      = 0;  

+

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+void onuEponAlarmProcess(void);

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Alarm Section                                      */

+/* ========================================================================== */

+/******************************************************************************/

+

+/*******************************************************************************

+**

+**  onuEponAlarmSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu epon alarm 

+**               

+**  PARAMETERS:  MV_U32  alarm

+**               MV_BOOL status

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK 

+**                   

+*******************************************************************************/

+MV_STATUS onuEponAlarmSet(MV_U32 alarm, MV_BOOL state)

+{

+  if ((alarm & ONU_EPON_ALARM_MASK) == 0)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_ALARM_MODULE, 

+               "ERROR: (%s:%d) invalid alarm(%d) type\n\r", __FILE_DESC__, __LINE__, alarm);

+    return(MV_ERROR);

+  }

+

+  if (state == MV_FALSE)

+  {

+    onuEponCurrentAlarm &= ~(alarm);

+  }

+  else

+  {

+    onuEponCurrentAlarm |=  (alarm);

+  }

+

+  onuEponAlarmProcess();

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponAlarmProcess

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function process the current alarm state and notify screen

+**               

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**                   

+*******************************************************************************/

+void onuEponAlarmProcess(void)

+{

+  MV_U32 onuEponPreviousAlarmState;

+  MV_U32 onuEponCurrentAlarmState;

+  MV_U32 onuEponChangeAlarm;

+

+  /* get the ASIC prvious alarm status */

+  onuEponPreviousAlarmState = onuEponPreviousAlarm;

+

+  /* get the ASIC current alarm status */

+  onuEponCurrentAlarmState = onuEponCurrentAlarm;

+

+  /* Init PON los alarm */

+  onuEponLosAlarm = 0;  

+  

+  /* alarm changed */

+  if ((onuEponCurrentAlarmState ^ onuEponPreviousAlarmState) != 0)

+  {

+    onuEponChangeAlarm = (onuEponCurrentAlarmState ^ onuEponPreviousAlarmState);

+

+    if ((onuEponChangeAlarm & onuEponCurrentAlarmState) != 0)

+    {

+      if (onuEponChangeAlarm & ONU_EPON_XVR_SD_MASK)

+      {

+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, 

+                   "INFO: (%s:%d) === XVR SD Off ===\n\r", __FILE_DESC__, __LINE__);

+        onuEponLosAlarm |= 0x01;

+      }

+

+      if (onuEponChangeAlarm & ONU_EPON_SERDES_SD_MASK)

+      {

+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, 

+                   "INFO: (%s:%d) === SERDES SD Off ===\n\r", __FILE_DESC__, __LINE__);

+        onuEponLosAlarm |= 0x02;           

+      }

+    }

+    else /* ((onuEponChangeAlarm & onuEponCurrentAlarmState) == 0) */

+    {

+      if (onuEponChangeAlarm & ONU_EPON_XVR_SD_MASK)

+      {

+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, 

+                   "INFO: (%s:%d) === XVR SD On ===\n\r", __FILE_DESC__, __LINE__);

+        onuEponLosAlarm |= 0x01<<8;           

+      }

+

+      if (onuEponChangeAlarm & ONU_EPON_SERDES_SD_MASK)

+      {

+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, 

+                   "INFO: (%s:%d) === SERDES SD On ===\n\r", __FILE_DESC__, __LINE__);

+

+        onuEponLosAlarm |= 0x02<<8;

+      }

+    }

+

+    onuEponPreviousAlarm = onuEponCurrentAlarmState;  

+  }

+}

+

+/*******************************************************************************

+**

+**  onuEponAlarmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return current alarm status

+**               

+**  PARAMETERS:  MV_U32 *alarm

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**                   

+*******************************************************************************/

+void onuEponAlarmGet(MV_U32 *alarm)

+{

+  alarm[0] = ((onuEponCurrentAlarm & ONU_EPON_XVR_SD_MASK)    != 0) ? (1) : (0); 

+  alarm[1] = ((onuEponCurrentAlarm & ONU_EPON_SERDES_SD_MASK) != 0) ? (1) : (0);

+}

+

+/*******************************************************************************

+**

+**  onuEponLosAlarmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return current PON los alarm status

+**               

+**  PARAMETERS:  MV_U32 *alarm

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**                   

+*******************************************************************************/

+void onuEponLosAlarmGet(MV_U32 *alarm)

+{

+  *alarm = onuEponLosAlarm;

+

+  /* Set PON los alarm to default value */

+  //onuEponLosAlarm = 0;

+}

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.c
new file mode 100755
index 0000000..6bcf46b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.c
@@ -0,0 +1,791 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuApi.c                                              **/

+/**                                                                          **/

+/**  DESCRIPTION : This file implements ONU EPON API functionality           **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *      

+ *                                                                          

+ ******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "eponOnuHeader.h"

+#include "mv_netdev.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/                                               

+#define __FILE_DESC__ "mv_pon/core/epon/eponOnuApi.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+S_EponPm g_OnuEponOutPm[EPON_MAX_MAC_NUM];

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions 

+------------------------------------------------------------------------------*/

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/*******************************************************************************

+**

+**  onuEponApiStatusNotifyRegister

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function register status callback function

+**               

+**  PARAMETERS:  STATUSNOTIFYFUNC notifyCallBack 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiStatusNotifyRegister(STATUSNOTIFYFUNC notifyCallBack)

+{

+  MV_STATUS status;

+

+  status = onuEponDbStatusNotifySet(notifyCallBack);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) ponOnuApiStatusNotifyRegister", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponStatusNotify

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function notify EPON status to user space

+**               

+**  PARAMETERS:  MV_U32 status 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponStatusNotify(MV_U32 status)

+{

+  STATUSNOTIFYFUNC statusFunc = NULL; 

+

+  /* Send signal to management layer */

+  statusFunc = onuEponDbStatusNotifyGet();

+  if (statusFunc != NULL)

+  {

+    statusFunc(status);

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiInformationGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu info

+**               

+**  PARAMETERS:  S_IoctlInfo *onuInfo 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiInformationGet(S_EponIoctlInfo *onuInfo, MV_U32 macId)

+{

+  MV_U32 addressLow;

+  MV_U32 addressHigh;

+

+  onuInfo->onuEponState        = onuEponDbOnuStateGet(macId);      

+  onuInfo->onuEponCtrlType     = onuEponDbOnuCtrlTypeGet(); 

+  onuInfo->onuEponSignalDetect = onuEponDbOnuSignalDetectGet();

+  onuInfo->onuEponDsSyncOkPcs  = onuEponDbOnuDsSyncOkPcsGet();

+  onuInfo->onuEponMode         = onuEponDbModeGet();

+

+  onuEponDbOnuMacAddrGet(&addressLow, &addressHigh, macId);

+  onuInfo->onuEponMacAddr[5] = ((addressLow  >>  0) & 0xFF);

+  onuInfo->onuEponMacAddr[4] = ((addressLow  >>  8) & 0xFF); 

+  onuInfo->onuEponMacAddr[3] = ((addressLow  >> 16) & 0xFF);

+  onuInfo->onuEponMacAddr[2] = ((addressLow  >> 24) & 0xFF);

+  onuInfo->onuEponMacAddr[1] = ((addressHigh >>  0) & 0xFF);

+  onuInfo->onuEponMacAddr[0] = ((addressHigh >>  8) & 0xFF);

+

+  onuEponDbOnuBcastAddrGet(&addressLow, &addressHigh);

+  onuInfo->onuEponBcastAddr[5] = ((addressLow  >>  0) & 0xFF);

+  onuInfo->onuEponBcastAddr[4] = ((addressLow  >>  8) & 0xFF); 

+  onuInfo->onuEponBcastAddr[3] = ((addressLow  >> 16) & 0xFF);

+  onuInfo->onuEponBcastAddr[2] = ((addressLow  >> 24) & 0xFF);

+  onuInfo->onuEponBcastAddr[1] = ((addressHigh >>  0) & 0xFF);

+  onuInfo->onuEponBcastAddr[0] = ((addressHigh >>  8) & 0xFF);

+

+  onuEponDbPktRxLlidGet(&(onuInfo->onuEponRxLLID), macId);

+  onuEponDbPktTxLlidGet(&(onuInfo->onuEponTxLLID), macId);

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiLinkStateGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu link state

+**               

+**  PARAMETERS:  MV_U32 *linkState 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiLinkStateGet(MV_U32 *linkState, MV_U32 macId)

+{

+  if (onuEponDbOnuStateGet(macId) == ONU_EPON_03_OPERATION) *linkState = 1;

+  else                                                      *linkState = 0;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiFecConfig

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function configure onu FEC

+**               

+**  PARAMETERS:  MV_U32 rxGenFecEn

+**               MV_U32 txGenFecEn

+**               MV_U32 txMacFecEn[8]

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiFecConfig(MV_U32 rxGenFecEn, MV_U32 txGenFecEn, MV_U32 *txMacFecEn, MV_U32 source)

+{

+  MV_STATUS status;

+  MV_U32    regReqAutoRes;

+  MV_U32    regAckAutoRes;

+  MV_U32    reportAutoRes;

+  MV_U32    rxGenFecEnTemp;

+  MV_U32    txGenFecEnTemp;   

+  MV_U32    txMacFecEnTemp;   

+

+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE, 

+			 "DEBUG: (%s:%d) onuEponApiFecConfig, input rxGenFecEn(%d), txGenFecEn(%d), txMacFecEn(%d,%d,%d,%d,%d,%d,%d,%d)", 

+			 __FILE_DESC__, __LINE__, rxGenFecEn, txGenFecEn, txMacFecEn[0], txMacFecEn[1], txMacFecEn[2], txMacFecEn[3],

+             txMacFecEn[4], txMacFecEn[5], txMacFecEn[6], txMacFecEn[7]);

+

+  onuEponDbOnuCfgGet(&regReqAutoRes, &regAckAutoRes, &reportAutoRes, &rxGenFecEnTemp, &txGenFecEnTemp, &txMacFecEnTemp);

+  rxGenFecEnTemp = rxGenFecEn;

+  txGenFecEnTemp = txGenFecEn;

+  txMacFecEnTemp = ((txMacFecEn[0] & 0x1) << 0) |

+                   ((txMacFecEn[1] & 0x1) << 1) |

+                   ((txMacFecEn[2] & 0x1) << 2) |

+                   ((txMacFecEn[3] & 0x1) << 3) |

+                   ((txMacFecEn[4] & 0x1) << 4) |

+                   ((txMacFecEn[5] & 0x1) << 5) |

+                   ((txMacFecEn[6] & 0x1) << 6) |

+                   ((txMacFecEn[7] & 0x1) << 7);

+

+  if (source == ONU_FEC_CFG_INIT) 

+  {

+	onuEponDbOnuCfgSet(regReqAutoRes, regAckAutoRes, reportAutoRes, rxGenFecEnTemp, txGenFecEnTemp, txMacFecEnTemp);

+	onuEponDbOnuRxFecCfgSet(rxGenFecEn);

+  }

+

+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE, 

+			 "DEBUG: (%s:%d) onuEponApiFecConfig, config regReqAutoRes(%d), regAckAutoRes(%d), reportAutoRes(%d), rxGenFecEnTemp(%d), txGenFecEnTemp(%d), txMacFecEnTemp(%d)\n", 

+			 __FILE_DESC__, __LINE__, regReqAutoRes, regAckAutoRes, reportAutoRes, rxGenFecEnTemp, txGenFecEnTemp,txMacFecEnTemp);

+

+  status = mvOnuEponMacGenOnuConfigSet(rxGenFecEnTemp, txGenFecEnTemp, reportAutoRes, regAckAutoRes, regReqAutoRes, txMacFecEnTemp);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponApiFecConfig", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  if (rxGenFecEn)

+  {

+	status = mvOnuEponMacPcsDelaySet(0x1058);

+	if (status != MV_OK)

+	{

+	  mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+	  		   "ERROR: (%s:%d) onuEponApiFecConfig", __FILE_DESC__, __LINE__); 

+	  return(status);

+	}

+  }

+  else

+  {

+	status = mvOnuEponMacPcsDelaySet(0x1C58);

+	if (status != MV_OK)

+	{

+	  mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+	  		 "ERROR: (%s:%d) onuEponApiFecConfig", __FILE_DESC__, __LINE__); 

+	  return(status);

+	}

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiFecReConfig

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function re-configure onu FEC

+**               

+**  PARAMETERS:  MV_U32 rxGenFecEn

+**               MV_U32 txGenFecEn

+**               MV_U32 txMacFecEn[8]

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiFecReConfig(void)

+{

+  MV_STATUS status;

+  MV_U32    regReqAutoRes;

+  MV_U32    regAckAutoRes;

+  MV_U32    reportAutoRes;

+  MV_U32    rxGenFecEn;

+  MV_U32    txGenFecEn;   

+  MV_U32    txMacFecEn;   

+

+  onuEponDbOnuCfgGet(&regReqAutoRes, &regAckAutoRes, &reportAutoRes, &rxGenFecEn, &txGenFecEn, &txMacFecEn);

+

+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE, 

+			 "DEBUG: (%s:%d) onuEponApiFecReConfig, regReqAutoRes(%d), regAckAutoRes(%d), reportAutoRes(%d), rxGenFecEn(%d), txGenFecEn(%d), txMacFecEn(0x%x)\n", 

+			 __FILE_DESC__, __LINE__, regReqAutoRes, regAckAutoRes, reportAutoRes, rxGenFecEn, txGenFecEn, txMacFecEn);

+

+  status = mvOnuEponMacGenOnuConfigSet(rxGenFecEn, txGenFecEn, reportAutoRes, regAckAutoRes, regReqAutoRes, txMacFecEn);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponApiFecReConfig", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  if (rxGenFecEn)

+  {

+	status = mvOnuEponMacPcsDelaySet(0x1058);

+	if (status != MV_OK)

+	{

+	  mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+	  		   "ERROR: (%s:%d) onuEponApiFecReConfig", __FILE_DESC__, __LINE__); 

+	  return(status);

+	}

+  }

+  else

+  {

+	status = mvOnuEponMacPcsDelaySet(0x1C58);

+	if (status != MV_OK)

+	{

+	  mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+	  		 "ERROR: (%s:%d) onuEponApiFecReConfig", __FILE_DESC__, __LINE__); 

+	  return(status);

+	}

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiEncryptionConfig

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function configure onu Encryption

+**               

+**  PARAMETERS:  MV_U32 onuEncryptCfg

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiEncryptionConfig(MV_U32 onuEncryptCfg)

+{

+  MV_STATUS status;

+

+  status = mvOnuEponMacRxpEncConfigSet(onuEncryptCfg);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponApiEncryptionConfig", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiEncryptionKeyConfig

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function configure onu Encryption Key

+**               

+**  PARAMETERS:  MV_U32 encryptKey

+**               MV_U32 encryptKeyIndex

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiEncryptionKeyConfig(MV_U32 encryptKey, MV_U32 encryptKeyIndex, MV_U32 macId)

+{

+  MV_STATUS status;

+

+  status = mvOnuEponMacRxpEncKeySet(encryptKey, encryptKeyIndex, macId); 

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponApiEncryptionKeyConfig", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiRxPmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU

+**               Rx counters                           

+**                

+**  PARAMETERS:  S_EponIoctlRxPm *rxPm

+**               MV_BOOL         clear

+**               MV_U32          macId

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponApiRxPmGet(S_EponIoctlRxPm *rxPm,  MV_BOOL clear, MV_U32 macId)

+{

+  MV_STATUS status;

+  S_RxPm    inCounters;

+

+  status = onuEponPmRxPmGet(&inCounters, macId);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponApiRxPmGet", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  rxPm->fcsErrorFramesCnt = inCounters.fcsErrorFramesCnt - g_OnuEponOutPm[macId].rx.fcsErrorFramesCnt;

+  rxPm->shortFramesCnt    = inCounters.shortFramesCnt    - g_OnuEponOutPm[macId].rx.shortFramesCnt;

+  rxPm->longFramesCnt     = inCounters.longFramesCnt     - g_OnuEponOutPm[macId].rx.longFramesCnt; 

+  rxPm->dataFramesCnt     = inCounters.dataFramesCnt     - g_OnuEponOutPm[macId].rx.dataFramesCnt; 

+  rxPm->ctrlFramesCnt     = inCounters.ctrlFramesCnt     - g_OnuEponOutPm[macId].rx.ctrlFramesCnt; 

+  rxPm->reportFramesCnt   = inCounters.reportFramesCnt   - g_OnuEponOutPm[macId].rx.reportFramesCnt;  

+  rxPm->gateFramesCnt     = inCounters.gateFramesCnt     - g_OnuEponOutPm[macId].rx.gateFramesCnt;    

+

+  if (clear == MV_TRUE)

+  {

+    g_OnuEponOutPm[macId].rx.fcsErrorFramesCnt = inCounters.fcsErrorFramesCnt;

+    g_OnuEponOutPm[macId].rx.shortFramesCnt    = inCounters.shortFramesCnt;   

+    g_OnuEponOutPm[macId].rx.longFramesCnt     = inCounters.longFramesCnt;    

+    g_OnuEponOutPm[macId].rx.dataFramesCnt     = inCounters.dataFramesCnt;    

+    g_OnuEponOutPm[macId].rx.ctrlFramesCnt     = inCounters.ctrlFramesCnt;    

+    g_OnuEponOutPm[macId].rx.reportFramesCnt   = inCounters.reportFramesCnt;   

+    g_OnuEponOutPm[macId].rx.gateFramesCnt     = inCounters.gateFramesCnt;     

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiTxPmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU

+**               Tx counters                           

+**                

+**  PARAMETERS:  S_EponIoctlTxPm *rxPm

+**               MV_BOOL         clear

+**               MV_U32          macId

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponApiTxPmGet(S_EponIoctlTxPm *txPm, MV_BOOL clear, MV_U32 macId)

+{

+  MV_STATUS  status;

+  S_EponTxPm inCounters;

+

+  status = onuEponPmTxPmGet(&inCounters, macId);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponApiTxPmGet", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  txPm->ctrlRegReqFramesCnt = inCounters.ctrlRegReqFramesCnt - g_OnuEponOutPm[macId].tx.ctrlRegReqFramesCnt;

+  txPm->ctrlRegAckFramesCnt = inCounters.ctrlRegAckFramesCnt - g_OnuEponOutPm[macId].tx.ctrlRegAckFramesCnt;

+  txPm->reportFramesCnt     = inCounters.reportFramesCnt     - g_OnuEponOutPm[macId].tx.reportFramesCnt;    

+  txPm->dataFramesCnt       = inCounters.dataFramesCnt       - g_OnuEponOutPm[macId].tx.dataFramesCnt;      

+  txPm->txAllowedBytesCnt   = inCounters.txAllowedBytesCnt   - g_OnuEponOutPm[macId].tx.txAllowedBytesCnt;  

+

+  if (clear == MV_TRUE)

+  {

+    g_OnuEponOutPm[macId].tx.ctrlRegReqFramesCnt = inCounters.ctrlRegReqFramesCnt;

+    g_OnuEponOutPm[macId].tx.ctrlRegAckFramesCnt = inCounters.ctrlRegAckFramesCnt;

+    g_OnuEponOutPm[macId].tx.reportFramesCnt     = inCounters.reportFramesCnt;   

+    g_OnuEponOutPm[macId].tx.dataFramesCnt       = inCounters.dataFramesCnt;      

+    g_OnuEponOutPm[macId].tx.txAllowedBytesCnt   = inCounters.txAllowedBytesCnt;

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiSwPmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU

+**               SW counters                           

+**                

+**  PARAMETERS:  S_EponIoctlSwPm *swPm

+**               MV_BOOL         clear

+**               MV_U32          macId

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponApiSwPmGet(S_EponIoctlSwPm *swPm, MV_BOOL clear, MV_U32 macId)

+{

+  MV_STATUS status;

+  S_SwPm    inCounters;

+  MV_U32    index;

+

+  status = onuEponPmSwPmGet(&inCounters, macId);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponApiSwPmGet", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  for (index = 0; index < MAX_EPON_RX_SW_CNT; index++)

+  {

+    swPm->swRxCnt[index] = inCounters.swRxCnt[index] - g_OnuEponOutPm[macId].sw.swRxCnt[index];

+  }

+

+  for (index = 0; index < MAX_EPON_TX_SW_CNT; index++)

+  {

+    swPm->swTxCnt[index] = inCounters.swTxCnt[index] - g_OnuEponOutPm[macId].sw.swTxCnt[index];

+  }

+

+  if (clear == MV_TRUE)

+  {

+    for (index = 0; index < MAX_EPON_RX_SW_CNT; index++)

+    {

+      g_OnuEponOutPm[macId].sw.swRxCnt[index] = inCounters.swRxCnt[index];

+    }

+

+    for (index = 0; index < MAX_EPON_TX_SW_CNT; index++)

+    {

+      g_OnuEponOutPm[macId].sw.swTxCnt[index] = inCounters.swTxCnt[index];

+    }

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiGpmPmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU

+**               Gpm counters                           

+**                

+**  PARAMETERS:  S_EponIoctlGpmPm *rxPm

+**               MV_BOOL          clear

+**               MV_U32           macId

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponApiGpmPmGet(S_EponIoctlGpmPm *gpmPm, MV_BOOL clear, MV_U32 macId)

+{

+  MV_STATUS status;

+  S_GpmPm   inCounters;

+

+  status = onuEponPmGpmPmGet(&inCounters, macId);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponApiTxPmGet", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+

+  gpmPm->grantValidCnt                 = inCounters.grantValidCnt                 - g_OnuEponOutPm[macId].gpm.grantValidCnt;                

+  gpmPm->grantMaxFutureTimeErrorCnt    = inCounters.grantMaxFutureTimeErrorCnt    - g_OnuEponOutPm[macId].gpm.grantMaxFutureTimeErrorCnt;   

+  gpmPm->minProcTimeErrorCnt           = inCounters.minProcTimeErrorCnt           - g_OnuEponOutPm[macId].gpm.minProcTimeErrorCnt;          

+  gpmPm->lengthErrorCnt                = inCounters.lengthErrorCnt                - g_OnuEponOutPm[macId].gpm.lengthErrorCnt;               

+  gpmPm->discoveryAndRegCnt            = inCounters.discoveryAndRegCnt            - g_OnuEponOutPm[macId].gpm.discoveryAndRegCnt;           

+  gpmPm->fifoFullErrorCnt              = inCounters.fifoFullErrorCnt              - g_OnuEponOutPm[macId].gpm.fifoFullErrorCnt;             

+  gpmPm->opcDiscoveryNotRegBcastCnt    = inCounters.opcDiscoveryNotRegBcastCnt    - g_OnuEponOutPm[macId].gpm.opcDiscoveryNotRegBcastCnt;   

+  gpmPm->opcRegisterNotDiscoveryCnt    = inCounters.opcRegisterNotDiscoveryCnt    - g_OnuEponOutPm[macId].gpm.opcRegisterNotDiscoveryCnt;   

+  gpmPm->opcDiscoveryNotRegNotBcastCnt = inCounters.opcDiscoveryNotRegNotBcastCnt - g_OnuEponOutPm[macId].gpm.opcDiscoveryNotRegNotBcastCnt;

+  gpmPm->opcDropGrantCnt               = inCounters.opcDropGrantCnt               - g_OnuEponOutPm[macId].gpm.opcDropGrantCnt;              

+  gpmPm->opcHiddenGrantCnt             = inCounters.opcHiddenGrantCnt             - g_OnuEponOutPm[macId].gpm.opcHiddenGrantCnt;            

+  gpmPm->opcBackToBackCnt              = inCounters.opcBackToBackCnt              - g_OnuEponOutPm[macId].gpm.opcBackToBackCnt;             

+

+  if (clear == MV_TRUE)

+  {

+    g_OnuEponOutPm[macId].gpm.grantValidCnt                 = inCounters.grantValidCnt;                

+    g_OnuEponOutPm[macId].gpm.grantMaxFutureTimeErrorCnt    = inCounters.grantMaxFutureTimeErrorCnt;   

+    g_OnuEponOutPm[macId].gpm.minProcTimeErrorCnt           = inCounters.minProcTimeErrorCnt;          

+    g_OnuEponOutPm[macId].gpm.lengthErrorCnt                = inCounters.lengthErrorCnt;               

+    g_OnuEponOutPm[macId].gpm.discoveryAndRegCnt            = inCounters.discoveryAndRegCnt;           

+    g_OnuEponOutPm[macId].gpm.fifoFullErrorCnt              = inCounters.fifoFullErrorCnt;             

+    g_OnuEponOutPm[macId].gpm.opcDiscoveryNotRegBcastCnt    = inCounters.opcDiscoveryNotRegBcastCnt;   

+    g_OnuEponOutPm[macId].gpm.opcRegisterNotDiscoveryCnt    = inCounters.opcRegisterNotDiscoveryCnt;   

+    g_OnuEponOutPm[macId].gpm.opcDiscoveryNotRegNotBcastCnt = inCounters.opcDiscoveryNotRegNotBcastCnt;

+    g_OnuEponOutPm[macId].gpm.opcDropGrantCnt               = inCounters.opcDropGrantCnt;              

+    g_OnuEponOutPm[macId].gpm.opcHiddenGrantCnt             = inCounters.opcHiddenGrantCnt;            

+    g_OnuEponOutPm[macId].gpm.opcBackToBackCnt              = inCounters.opcBackToBackCnt;             

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiTransmitOamFrame

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function transmit OAM frame via FIFO

+**               

+**  PARAMETERS:  S_OnuEponCtrlBuffer *frame

+**               MV_U32              macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiTransmitOamFrame(S_OnuEponCtrlBuffer *frame, MV_U32 macId)

+{

+  MV_STATUS status;

+

+  if (onuEponDbOnuStateGet(0) != ONU_EPON_03_OPERATION) 

+  {

+	mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE, 

+	  		 "ERROR: (%s:%d) onuEponApiTransmitOamFrame, ONU not registered", __FILE_DESC__, __LINE__); 

+	return(MV_OK);

+  }

+

+  status = onuEponOamAllocMsg(frame, macId);

+  if (status != MV_OK)

+  {

+	mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE, 

+			   "ERROR: (%s:%d) onuEponApiTransmitOamFrame", __FILE_DESC__, __LINE__); 

+	return(status);

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiDgCallbackRegister

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function register Dying Gasp callback function

+**               

+**  PARAMETERS:  DYINGGASPFUNC dgCallBack 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiDgCallbackRegister(DYINGGASPFUNC dgCallBack)

+{

+  MV_STATUS status;

+

+  status = onuEponDbDgCallbackSet(dgCallBack);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE, 

+               "ERROR: (%s:%d) onuEponDbDgCallbackSet", __FILE_DESC__, __LINE__); 

+    return(status);

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponApiLinkStatusCallbackRegister

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function register Link Status callback function

+**               

+**  PARAMETERS:  LINKSTATUSFUNC linkStatusCallBack

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponApiLinkStatusCallbackRegister(void)

+{

+  mv_pon_link_state_register(onuEponLinkIsUp,

+	 					     &onuEponDb_s.onuEponGenTbl_s.onuLinkStatusCallback);

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponLinkIsUp

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function register Link Status callback function

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_TRUE or MV_FLASE

+**                   

+*******************************************************************************/

+MV_BOOL onuEponLinkIsUp(void)

+{

+  MV_U32 mode;

+

+  mode = onuEponDbModeGet();

+

+  if (onuEponForceTxDownStateGet(0) == MV_TRUE)

+    return(MV_TRUE);

+

+  if (mode == E_EPON_IOCTL_STD_MODE) 

+  {

+    if (onuEponDbOnuStateGet(0) == ONU_EPON_03_OPERATION) return(MV_TRUE);

+    else                                                  return(MV_FALSE);

+  }

+  else /* P2P */

+  {

+    if (onuEponDbOnuSignalDetectGet() == 1) return(MV_TRUE);

+    else                                    return(MV_FALSE);

+  }

+}

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.h
new file mode 100755
index 0000000..cd4eebd
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuApi.h
@@ -0,0 +1,149 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuApi.h                                              **/

+/**                                                                          **/

+/**  DESCRIPTION : This file contains ONU EPON API definitions               **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *      

+ *                                                                          

+ ******************************************************************************/

+#ifndef _ONU_EPON_API_H

+#define _ONU_EPON_API_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Structs                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Notify API

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponApiStatusNotifyRegister(STATUSNOTIFYFUNC notifyCallBack);

+MV_STATUS onuEponStatusNotify(MV_U32 status);

+

+/* Information API

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponApiInformationGet(S_EponIoctlInfo *onuInfo, MV_U32 macId);

+MV_STATUS onuEponApiLinkStateGet(MV_U32 *linkState, MV_U32 macId);

+

+/* FEC API

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponApiFecConfig(MV_U32 rxGenFecEn, MV_U32 txGenFecEn, MV_U32 *txMacFecEn, MV_U32 source);

+MV_STATUS onuEponApiFecReConfig(void);

+

+/* Encryption API

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponApiEncryptionConfig(MV_U32 onuEncryptCfg);

+MV_STATUS onuEponApiEncryptionKeyConfig(MV_U32 encryptKey, MV_U32 encryptKeyIndex, MV_U32 macId);

+

+/* PM API

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponApiRxPmGet(S_EponIoctlRxPm *rxPm, MV_BOOL clear, MV_U32 macId);

+MV_STATUS onuEponApiTxPmGet(S_EponIoctlTxPm *txPm, MV_BOOL clear, MV_U32 macId);

+MV_STATUS onuEponApiSwPmGet(S_EponIoctlSwPm *swPm, MV_BOOL clear, MV_U32 macId);

+MV_STATUS onuEponApiGpmPmGet(S_EponIoctlGpmPm *gpmPm, MV_BOOL clear, MV_U32 macId);

+

+/* OAM Frame API

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponApiTransmitOamFrame(S_OnuEponCtrlBuffer *frame, MV_U32 macId);

+

+/* Dying Gasp API

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponApiDgCallbackRegister(DYINGGASPFUNC dgCallBack);

+

+/* Link status API

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponApiLinkStatusCallbackRegister(void);

+MV_BOOL onuEponLinkIsUp(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_EPON_API_H */

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.c
new file mode 100755
index 0000000..040d80b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.c
@@ -0,0 +1,2209 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuDb.c                                               **/

+/**                                                                          **/

+/**  DESCRIPTION : This file implements ONU EPON database functionality      **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *      

+ *                                                                          

+ ******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "eponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/                                               

+#define __FILE_DESC__ "mv_pon/core/epon/eponOnuDb.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+/* ONU GPON Database */

+S_OnuEponDb onuEponDb_s;

+

+#ifdef PON_FPGA

+#define MV_MAC_ADDR_SIZE (6)

+#endif /* PON_FPGA */

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+/* ONU EPON database init function */

+MV_STATUS onuEponOnuMacTblInit(void);

+MV_STATUS onuEponOnuGenTblInit(void);

+MV_STATUS onuEponDbOnuDatapathTblInit(void);

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+MV_U32 swRprtMacTimerInterval; /* in 16 nano sec units */

+MV_U32 swRprtTimerType;

+

+MV_U8 fixMacAddrs[8][6] = {{0x00,0x00,0x00,0x00,0x00,0x82},

+                           {0x00,0x00,0x00,0x00,0x00,0x83},

+                           {0x00,0x00,0x00,0x00,0x00,0x84},

+                           {0x00,0x00,0x00,0x00,0x00,0x85},

+                           {0x00,0x00,0x00,0x00,0x00,0x86},

+                           {0x00,0x00,0x00,0x00,0x00,0x87},

+                           {0x00,0x00,0x00,0x00,0x00,0x88},

+                           {0x00,0x00,0x00,0x00,0x00,0x89}};

+

+extern u8 mvMacAddr[CONFIG_MV_ETH_PORTS_NUM][MV_MAC_ADDR_SIZE];

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Initialization Section                             */

+/* ========================================================================== */

+/******************************************************************************/

+

+/*******************************************************************************

+**

+**  onuEponDbInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function init onu database to default values

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbInit(void)

+{

+#ifndef PON_FPGA

+  onuEponOnuMacTblInit();             

+#endif /* PON_FPGA */

+  onuEponOnuGenTblInit();             

+  onuEponDbOnuDatapathTblInit();      

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbReInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function re-init onu database to default values

+**               

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbReInit(MV_U32 macId)

+{

+  /* set onu to state 01 */

+  onuEponDbOnuStateSet(ONU_EPON_02_REGISTER_PENDING, macId);

+

+  /* set onu sync time to 0 */

+  onuEponDbOnuSyncTimeSet(0, macId);

+

+  onuEponDbPktTxLlidSet(ONU_DEF_TX_LLID, macId);

+  onuEponDbPktRxLlidSet(ONU_DEF_RX_LLID, macId);

+

+  if (macId == 0)

+    onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_BLINK_SLOW);

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponOnuGenTblInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function init onu database MAC table

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponOnuMacTblInit(void)

+{

+  MV_U32 macId;

+  MV_U8  macAddrSkeleton[MV_MAC_ADDR_SIZE];

+

+  memcpy(macAddrSkeleton, mvMacAddr[2], MV_MAC_ADDR_SIZE);

+  printk("macAddrSkeleton = %x:%x:%x:%x:%x:%x\n\r", 

+         macAddrSkeleton[0], macAddrSkeleton[1], macAddrSkeleton[2],

+         macAddrSkeleton[3], macAddrSkeleton[4], macAddrSkeleton[5]);

+

+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) 

+  {

+    memcpy(fixMacAddrs[macId], macAddrSkeleton, MV_MAC_ADDR_SIZE);

+

+    macAddrSkeleton[5]++;

+    if (macAddrSkeleton[5] == 0x10) 

+        macAddrSkeleton[5] = 0;

+

+    printk("mac -%d- macAddr = %x:%x:%x:%x:%x:%x\n\r", macId,

+           fixMacAddrs[macId][0], fixMacAddrs[macId][1], fixMacAddrs[macId][2],

+           fixMacAddrs[macId][3], fixMacAddrs[macId][4], fixMacAddrs[macId][5]);

+  }

+

+

+  return(MV_OK); 

+}

+

+/*******************************************************************************

+**

+**  onuEponOnuGenTblInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function init onu database general table

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**                   

+*******************************************************************************/

+MV_STATUS onuEponOnuGenTblInit(void)

+{

+	MV_U32 macAddrLow;

+	MV_U32 macAddrHigh;

+	MV_U32 macId;

+	MV_U32 queueSet;

+	MV_U32 queueId;

+

+	/* clear onu database general table */

+	memset ((&(onuEponDb_s.onuEponGenTbl_s)), 0, sizeof (S_OnuEponGenTbl));

+

+	/* set onu control type to MPCP - 8808 */

+	onuEponDbOnuCtrlTypeSet(ONU_MPCP_CTRL_TYPE);

+

+	/* set onu broadcast address */

+	onuEponDbOnuBcastAddrSet(ONU_BROADCAST_ADDR_LOW, ONU_BROADCAST_ADDR_HIGH);

+

+	for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {

+		/* set onu to valid */

+		onuEponDbOnuValidSet(MV_TRUE, macId);

+

+		/* set onu to state 01 */

+		onuEponDbOnuStateSet(ONU_EPON_02_REGISTER_PENDING, macId);

+

+		/* set onu sync time to 0 */

+		onuEponDbOnuSyncTimeSet(0, macId);

+

+		/* set onu mac address */

+		macAddrLow  = ((fixMacAddrs[macId][5] & 0xFF)      ) |

+			      ((fixMacAddrs[macId][4] & 0xFF) <<  8) |

+			      ((fixMacAddrs[macId][3] & 0xFF) << 16) |

+			      ((fixMacAddrs[macId][2] & 0xFF) << 24);

+		macAddrHigh = ((fixMacAddrs[macId][1] & 0xFF)      ) |

+			      ((fixMacAddrs[macId][0] & 0xFF) << 8 );

+

+		onuEponDbOnuMacAddrSet(macAddrLow, macAddrHigh, macId);

+	}

+

+	/* set led */

+	onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_BLINK_SLOW);

+

+	/* set holdover */

+	onuEponDbOnuHoldoverStateSet(ONU_HOLDOVER_NOT_ACTIVE);

+

+	/* set silence */

+	onuEponDbOnuSilenceStateSet(ONU_SILENCE_NOT_ACTIVE);

+

+

+	/* SW DBA params */

+	onuEponDbOnuSwRprtTimerTypeSet(ONU_EPON_SW_DBA_RPRT_TIMER);

+	onuEponDbOnuSwRprtMacTimerIntervalSet(62500); /* 1 msec in 16nano units */

+

+	onuEponDbOnuDbaModeSet(ONU_DBA_SW_RPRT_MODE);

+	onuEponDbOnuDbaSwModeQueuesetDirSet(ONU_DBA_SW_RPRT_NORMAL_DIR);

+	onuEponDbOnuDbaSwModeQueueDirSet(ONU_DBA_SW_RPRT_NORMAL_DIR);

+

+	for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {

+		if (macId == 0)

+			onuEponDbOnuDbaLlidActiveStatusSet(ONU_DBA_ACTIVE_LLID, macId);

+		else

+			onuEponDbOnuDbaLlidActiveStatusSet(ONU_DBA_NON_ACTIVE_LLID, macId);

+

+		onuEponDbOnuDbaHighestReportQueueSet(ONU_DBA_DEF_HIGHEST_QUEUE, macId);

+		onuEponDbOnuDbaNumOfQueuesSet(ONU_DBA_DEF_NUM_OF_QUEUE, macId);

+		onuEponDbOnuDbaNumOfQueuesetSet(ONU_DBA_DEF_NUM_OF_QUEUESET, macId);

+		onuEponDbOnuDbaQueuesBitMapSet(ONU_DBA_DEF_QUEUES_BIT_MAP, macId);

+

+		for (queueSet = 0; queueSet < ONU_DBA_DEF_NUM_OF_QUEUESET; queueSet++) {

+			for (queueId = 0; queueId < ONU_DBA_DEF_NUM_OF_QUEUE; queueId++) {

+				if (queueSet == 0)

+					onuEponDbOnuDbaQueueThresholdSet(ONU_DBA_DEF_QUEUESET_DEF_THRESHOLD,

+									 1, queueId, queueSet, macId);

+				else if (queueSet == 1)

+					onuEponDbOnuDbaQueueThresholdSet(ONU_DBA_DEF_QUEUESET_DEF_THRESHOLD,

+									 1, queueId, queueSet, macId);

+				else if (queueSet == 2)

+					onuEponDbOnuDbaQueueThresholdSet(ONU_DBA_DEF_QUEUESET_DEF_THRESHOLD,

+									 1, queueId, queueSet, macId);

+				else

+					onuEponDbOnuDbaQueueThresholdSet(ONU_DBA_DEF_QUEUESET_DEF_THRESHOLD,

+									 1, queueId, queueSet, macId);

+			}

+		}

+	}

+

+	/* set onu configuration */

+	onuEponDbOnuCfgSet(ONU_REG_REQ_AUTO_RES,

+			   ONU_REG_ACK_AUTO_RES,

+			   ONU_REPORT_AUTO_RES,

+			   ONU_RX_PCS_FEC_DIS,

+			   ONU_TX_PCS_FEC_DIS,

+			   ONU_TX_FEC_DIS);

+

+	onuEponDbOnuRxFecCfgSet(ONU_RX_PCS_FEC_DIS);

+

+	onuEponDbStatusNotifySet(NULL);

+	onuEponDbDgCallbackSet(NULL);

+	onuEponDbModeSet(E_EPON_IOCTL_STD_MODE);

+

+	return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDatapathTblInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function init onu database data path table

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDatapathTblInit(void)

+{

+  MV_U32 macId;

+

+  /* clear onu database data path table */

+  memset ((&(onuEponDb_s.onuEponDataPathTbl_s)), 0, sizeof (S_OnuEponDatapathTbl));

+

+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) 

+  {

+    onuEponDb_s.onuEponDataPathTbl_s.onuEponRxLLID[macId] = ONU_UNUSED_LLID;

+    onuEponDb_s.onuEponDataPathTbl_s.onuEponTxLLID[macId] = ONU_UNUSED_LLID;

+

+    onuEponDbPktTxLlidSet(ONU_DEF_TX_LLID, macId);

+    onuEponDbPktRxLlidSet(ONU_DEF_RX_LLID, macId);

+  }

+

+  onuEponDbPktForwardSet(ONU_SLOW_FRAME_TO_CTRL_QUEUE,  

+                         ONU_SLOW_FRAME_TO_RPRT_QUEUE,  

+                         ONU_RPRT_FRAME_TO_RPRT_QUEUE,  

+                         ONU_RPRT_FRAME_TO_DATA_QUEUE,  

+                         ONU_CTRL_FRAME_TO_CTRL_QUEUE,  

+                         ONU_CTRL_FRAME_TO_DATA_QUEUE); 

+

+  onuEponDbPktFilterPacketSet(ONU_FORWARD_LLID_ALL_PKT, 

+                              ONU_FORWARD_LLID_XXXX_MODE_1_PKT, 

+                              ONU_FORWARD_LLID_7FFF_MODE_1_PKT, 

+                              ONU_FORWARD_LLID_7FFF_MODE_0_PKT, 

+                              ONU_DROP_LLID_NNNN_MODE_1_PKT);

+

+  onuEponDbPktFilterErrorSet(ONU_FORWARD_LLID_LEN_ERR_PKT, 

+                             ONU_FORWARD_LLID_GMII_ERR_PKT, 

+                             ONU_FORWARD_LLID_FCS_ERR_PKT, 

+                             ONU_FORWARD_LLID_CRC_ERR_PKT);

+

+  onuEponDbPktSizeSet(ONU_DEF_MIN_PKT_SIZE, ONU_DEF_MAX_PKT_SIZE);

+

+  return(MV_OK);

+}

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Interface Section                                  */

+/* ========================================================================== */

+/******************************************************************************/

+

+/********************************************/

+/* ======================================== */

+/*   ONU EPON General Table API Functions   */

+/* ======================================== */

+/********************************************/

+MV_STATUS matchDestAddressToMacId(MV_U8 *destAddr, MV_U32 *macId)

+{

+  MV_U32 addrIndex;

+

+  for (addrIndex = 0; addrIndex < EPON_MAX_MAC_NUM; addrIndex++) 

+  {

+    if (memcmp(fixMacAddrs[addrIndex], destAddr, 6) == 0)

+    {

+      *macId = addrIndex;

+      return(MV_OK);

+    }

+  }

+

+  return(MV_ERROR);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuValidSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu valid in the database

+**               

+**  PARAMETERS:  MV_BOOL onuValid  

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuValidSet(MV_BOOL onuValid, MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponValid[macId] = onuValid;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuValidGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu valid 

+**               

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     onu state

+**                   

+*******************************************************************************/

+MV_BOOL onuEponDbOnuValidGet(MV_U32 macId)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponValid[macId]);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuStateSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu state in the database

+**               

+**  PARAMETERS:  MV_U32 onuState - ONU_EPON_02_REGISTER_PENDING

+**                                 ONU_EPON_03_OPERATION         

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuStateSet(MV_U32 onuState, MV_U32 macId)

+{

+  if ((onuState < ONU_EPON_02_REGISTER_PENDING) ||

+      (onuState > ONU_EPON_03_OPERATION))

+  {

+    return(MV_ERROR);

+  }

+

+  onuEponDb_s.onuEponGenTbl_s.onuEponState[macId] = onuState;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuStateGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu state 

+**               

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     onu state

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuStateGet(MV_U32 macId)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponState[macId]);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSignalDetectSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu signal detect in the database

+**               

+**  PARAMETERS:  MV_U32 state       

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuSignalDetectSet(MV_U32 state)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponSignalDetect = state;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSignalDetectGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu state signal detect

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     onu state

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuSignalDetectGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponSignalDetect);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDsSyncOkPcsSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu ds sync OK PCS in the database

+**               

+**  PARAMETERS:  MV_U32 state       

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDsSyncOkPcsSet(MV_U32 state)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDsSyncOkPcs = state;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDsSyncOkPcsGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu ds sync OK PCS

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     onu state

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDsSyncOkPcsGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDsSyncOkPcs);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuCtrlTypeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu ether type in the database

+**               

+**  PARAMETERS:  MV_U32 ctrlType 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuCtrlTypeSet(MV_U32 ctrlType)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponCtrlType = ctrlType;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuCtrlTypeGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu ether type 

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuCtrlTypeGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponCtrlType);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSyncTimeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu sync time in the database

+**               

+**  PARAMETERS:  MV_U32 syncTime

+**               MV_U32 macId 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuSyncTimeSet(MV_U32 syncTime, MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponSyncTime[macId] = syncTime;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSyncTimeGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu sync time

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     onu sync time

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuSyncTimeGet(MV_U32 macId)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponSyncTime[macId]);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuMacAddrSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu mac address in the database

+**               

+**  PARAMETERS:  MV_U32 lowAddr

+**               MV_U32 highAddr

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuMacAddrSet(MV_U32 lowAddr, MV_U32 highAddr, MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponMacAddr[macId].addressLow  = lowAddr;

+  onuEponDb_s.onuEponGenTbl_s.onuEponMacAddr[macId].addressHigh = highAddr;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuMacAddrGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu mac address in the database

+**               

+**  PARAMETERS:  MV_U32 *lowAddr

+**               MV_U32 *highAddr

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuMacAddrGet(MV_U32 *lowAddr, MV_U32 *highAddr, MV_U32 macId)

+{

+  *lowAddr  = onuEponDb_s.onuEponGenTbl_s.onuEponMacAddr[macId].addressLow; 

+  *highAddr = onuEponDb_s.onuEponGenTbl_s.onuEponMacAddr[macId].addressHigh; 

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuBcastAddrSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu mac broadcast address in the database

+**               

+**  PARAMETERS:  MV_U32 lowAddr

+**               MV_U32 highAddr

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuBcastAddrSet(MV_U32 lowAddr, MV_U32 highAddr)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponBcastAddr.addressLow  = lowAddr;

+  onuEponDb_s.onuEponGenTbl_s.onuEponBcastAddr.addressHigh = highAddr;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuMacAddrGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu mac broadcast address in the database

+**               

+**  PARAMETERS:  MV_U32 *lowAddr

+**               MV_U32 *highAddr

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuBcastAddrGet(MV_U32 *lowAddr, MV_U32 *highAddr)

+{

+  *lowAddr  = onuEponDb_s.onuEponGenTbl_s.onuEponBcastAddr.addressLow; 

+  *highAddr = onuEponDb_s.onuEponGenTbl_s.onuEponBcastAddr.addressHigh; 

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuCfgAutoSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu mac auto configuration in the database

+**               

+**  PARAMETERS:  MV_U32 regReqAutoRes

+**               MV_U32 regAckAutoRes

+**               MV_U32 reportAutoRes

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuCfgAutoSet(MV_U32 regReqAutoRes, 

+                                 MV_U32 regAckAutoRes, 

+                                 MV_U32 reportAutoRes)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRegReqAutoRes = regReqAutoRes;

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRegAckAutoRes = regAckAutoRes;

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponReportAutoRes = reportAutoRes;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuCfgSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu mac configuration in the database

+**               

+**  PARAMETERS:  MV_U32 regReqAutoRes

+**               MV_U32 regAckAutoRes

+**               MV_U32 reportAutoRes

+**               MV_U32 rxPcsFecEn        

+**               MV_U32 txPcsFecEn   

+**               MV_U32 txFecEn     

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuCfgSet(MV_U32 regReqAutoRes, 

+                             MV_U32 regAckAutoRes, 

+                             MV_U32 reportAutoRes, 

+                             MV_U32 rxPcsFecEn, 

+                             MV_U32 txPcsFecEn, 

+                             MV_U32 txFecEn)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRegReqAutoRes = regReqAutoRes;

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRegAckAutoRes = regAckAutoRes;

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponReportAutoRes = reportAutoRes;

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRxPcsFecEn    = rxPcsFecEn;      

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponTxPcsFecEn    = txPcsFecEn;      

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponTxFecEn       = txFecEn;      

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuCfgGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu mac configuration in the database

+**               

+**  PARAMETERS:  MV_U32 regReqAutoRes

+**               MV_U32 regAckAutoRes

+**               MV_U32 reportAutoRes

+**               MV_U32 rxFec        

+**               MV_U32 txFec        

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuCfgGet(MV_U32 *regReqAutoRes, 

+                             MV_U32 *regAckAutoRes, 

+                             MV_U32 *reportAutoRes, 

+                             MV_U32 *rxPcsFecEn, 

+                             MV_U32 *txPcsFecEn,

+                             MV_U32 *txFecEn)

+{

+  *regReqAutoRes = onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRegReqAutoRes;

+  *regAckAutoRes = onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRegAckAutoRes;

+  *reportAutoRes = onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponReportAutoRes;

+  *rxPcsFecEn    = onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRxPcsFecEn;      

+  *txPcsFecEn    = onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponTxPcsFecEn;      

+  *txFecEn       = onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponTxFecEn;

+                  

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuRxFecCfgSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu mac Rx FEC configuration in the database

+**               

+**  PARAMETERS:  MV_U32 rxPcsFecEn        

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuRxFecCfgSet(MV_U32 rxPcsFecEn)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRxPcsFecEn = rxPcsFecEn;      

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuRxFecCfgGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu mac Rx FEC configuration in the database

+**               

+**  PARAMETERS:  MV_U32 rxFec        

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuRxFecCfgGet(MV_U32 *rxPcsFecEn)

+{

+  *rxPcsFecEn = onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponRxPcsFecEn;      

+                  

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuTxFecCfgGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu mac Tx FEC configuration in the database

+**               

+**  PARAMETERS:  MV_U32 txFec   

+**               MV_U32 macId     

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuTxFecCfgGet(MV_U32 *txFecEn, MV_U32 macId)

+{

+  *txFecEn = ((onuEponDb_s.onuEponGenTbl_s.onuEponCfg.onuEponTxFecEn >> macId) & 0x1);      

+                  

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaModeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu DBA mode 

+**               

+**  PARAMETERS:  MV_U32 mode - HW(0) SW(1)

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaModeSet(MV_U32 mode)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDbaMode = mode;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaModeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu DBA mode 

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 mode - HW(0) SW(1)

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDbaModeGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDbaMode);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaSwModeQueuesetDirSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu SW mode queueset direction  

+**               

+**  PARAMETERS:  MV_U32 dir - Normal(0) Reverse(1)

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaSwModeQueuesetDirSet(MV_U32 dir)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDbaSwQueuesetDir = dir;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaSwModeQueuesetDirGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu SW mode queueset direction

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 dir - Normal(0) Reverse(1)

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDbaSwModeQueuesetDirGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDbaSwQueuesetDir);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaSwModeQueueDirSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu SW mode queues direction  

+**               

+**  PARAMETERS:  MV_U32 dir - Normal(0) Reverse(1)

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaSwModeQueueDirSet(MV_U32 dir)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDbaSwQueueDir = dir;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaSwModeQueueDirGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu SW mode queues direction

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 dir - Normal(0) Reverse(1)

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDbaSwModeQueueDirGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDbaSwQueueDir);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaLlidActiveStatusSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu DBA LLID active status 

+**               

+**  PARAMETERS:  MV_U32 status - Off(0) On(1)

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaLlidActiveStatusSet(MV_U32 status, MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].active = status;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaLlidActiveStatusGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu DBA mode 

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 status - Off(0) On(1)

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDbaLlidActiveStatusGet(MV_U32 macId)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].active);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaHighestReportQueueSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu highest DBA report queue

+**               

+**  PARAMETERS:  MV_U32 queueNum 

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaHighestReportQueueSet(MV_U32 queueNum, MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].highestReportQueue = queueNum;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaHighestReportQueueGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu highest DBA report queue

+**               

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDbaHighestReportQueueGet(MV_U32 macId)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].highestReportQueue);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaQueuesBitMapSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu queues bit map per LLID

+**               

+**  PARAMETERS:  MV_U32 queuesBitMap 

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaQueuesBitMapSet(MV_U32 queuesBitMap, MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].queuesBitMap = queuesBitMap;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaQueuesBitMapGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu queues bit map per LLID

+**               

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     onu queues bit map

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDbaQueuesBitMapGet(MV_U32 macId)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].queuesBitMap);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaNumOfQueuesSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu number of queues per LLID

+**               

+**  PARAMETERS:  MV_U32 numOfQueues 

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaNumOfQueuesSet(MV_U32 numOfQueues, MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].numOfQueues = numOfQueues;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaNumOfQueuesGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu number of queues per LLID

+**               

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDbaNumOfQueuesGet(MV_U32 macId)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].numOfQueues);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaNumOfQueuesetSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu number of queueset per LLID

+**               

+**  PARAMETERS:  MV_U32 numOfQueueset 

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaNumOfQueuesetSet(MV_U32 numOfQueueset, MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].numOfQueueSets = numOfQueueset;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaNumOfQueuesetGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu number of queueset per LLID

+**               

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuDbaNumOfQueuesetGet(MV_U32 macId)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].numOfQueueSets);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaQueueThresholdSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu queue threshold per LLID

+**               

+**  PARAMETERS:  MV_U32 threshold  

+**               MV_U32 state

+**               MV_U32 queueId 

+**               MV_U32 queueSet

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaQueueThresholdSet(MV_U32 threshold, 

+										   MV_U32 state, 

+										   MV_U32 queueId, 

+										   MV_U32 queueSet, 

+										   MV_U32 macId)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].queueThreshold[queueSet][queueId].threshold = threshold;

+  onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].queueThreshold[queueSet][queueId].state     = state;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaQueueThresholdGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu queue threshold per LLID

+**               

+**  PARAMETERS:  MV_U32 *threshold  

+**               MV_U32 *state

+**               MV_U32 queueId 

+**               MV_U32 queueSet

+**               MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaQueueThresholdGet(MV_U32 *threshold, 

+										   MV_U32 *state, 

+										   MV_U32 queueId, 

+										   MV_U32 queueSet,

+										   MV_U32 macId)

+{

+  *threshold = onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].queueThreshold[queueSet][queueId].threshold; 

+  *state     = onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId].queueThreshold[queueSet][queueId].state; 

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuDbaLlidThresholdGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu llid threshold per LLID

+**               

+**  PARAMETERS:  S_OnuEponDba *llidDba 

+**               MV_U32        macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuDbaLlidThresholdGet(S_OnuEponDba *llidDba, MV_U32 macId)

+{

+  memcpy(llidDba, &(onuEponDb_s.onuEponGenTbl_s.onuEponDba[macId]), sizeof(S_OnuEponDba));

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuHoldoverStateSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu holdover state in the database

+**               

+**  PARAMETERS:  MV_U32 state 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuHoldoverStateSet(MV_U32 state)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponHoldoverState = state;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuHoldoverStateGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu holdover state

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuHoldoverStateGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponHoldoverState);

+}

+/*******************************************************************************

+**

+**  onuEponDbOnuHoldoverTimeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu holdover time in the database

+**               

+**  PARAMETERS:  MV_U32 time 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuHoldoverTimeSet(MV_U32 time)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponHoldoverTime = time;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuHoldoverTimeGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu holdover time

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuHoldoverTimeGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponHoldoverTime);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuHoldoverExecSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu holdover execute in the database

+**               

+**  PARAMETERS:  MV_U32 state 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuHoldoverExecSet(MV_U32 state)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponHoldoverExecute = state;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuHoldoverExecGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu holdover execute

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuHoldoverExecGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponHoldoverExecute);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSilenceStateSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu silence state in the database

+**               

+**  PARAMETERS:  MV_U32 state 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuSilenceStateSet(MV_U32 state)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuEponSilenceState = state;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSilenceStateGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu silence state

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     ctrl frame ether type

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuSilenceStateGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuEponSilenceState);

+}

+

+/********************************************/

+/* ======================================== */

+/*   ONU EPON DataPath Table API Functions  */

+/* ======================================== */

+/********************************************/

+

+/*******************************************************************************

+**

+**  onuEponDbPktSizeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu mac RX packet size

+**               

+**  PARAMETERS:  MV_U32 minSize 

+**               MV_U32 maxSize

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktSizeSet(MV_U32 minSize, MV_U32 maxSize)

+{

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponRxPktMinSize = minSize;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponRxPktMaxSize = maxSize;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktSizeGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu mac RX packet size

+**               

+**  PARAMETERS:  MV_U32 *minSize 

+**               MV_U32 *maxSize

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktSizeGet(MV_U32 *minSize, MV_U32 *maxSize)

+{

+ *minSize = onuEponDb_s.onuEponDataPathTbl_s.onuEponRxPktMinSize;  

+ *maxSize = onuEponDb_s.onuEponDataPathTbl_s.onuEponRxPktMaxSize;  

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktFilterPacketSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu filter packet configuration

+**               

+**  PARAMETERS:  MV_U32 forwardLlidAll 

+**               MV_U32 forwardLlid1XXX

+**               MV_U32 forwardLlid1FFF

+**               MV_U32 forwardLlid0FFF

+**               MV_U32 dropLlid1NNN

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktFilterPacketSet(MV_U32 forwardLlidAll, 

+                                      MV_U32 forwardLlid1XXX, 

+                                      MV_U32 forwardLlid1FFF, 

+                                      MV_U32 forwardLlid0FFF,

+                                      MV_U32 dropLlid1NNN)

+{

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.forwardLlidAll  = forwardLlidAll;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.forwardLlid1XXX = forwardLlid1XXX;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.forwardLlid1FFF = forwardLlid1FFF;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.forwardLlid0FFF = forwardLlid0FFF;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.dropLlid1NNN    = dropLlid1NNN;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktFilterPacketGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu filter packet configuration

+**               

+**  PARAMETERS:  MV_U32 *forwardLlidAll 

+**               MV_U32 *forwardLlid1XXX

+**               MV_U32 *forwardLlid1FFF

+**               MV_U32 *forwardLlid0FFF

+**               MV_U32 *dropLlid1NNN

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktFilterPacketGet(MV_U32 *forwardLlidAll, 

+                                      MV_U32 *forwardLlid1XXX, 

+                                      MV_U32 *forwardLlid1FFF, 

+                                      MV_U32 *forwardLlid0FFF,

+                                      MV_U32 *dropLlid1NNN)

+{

+  *forwardLlidAll  = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.forwardLlidAll; 

+  *forwardLlid1XXX = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.forwardLlid1XXX;

+  *forwardLlid1FFF = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.forwardLlid1FFF;

+  *forwardLlid0FFF = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.forwardLlid0FFF;

+  *dropLlid1NNN    = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.dropLlid1NNN;

+

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktFilterErrorSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu filter error configuration

+**               

+**  PARAMETERS:  MV_U32 ignoreLenErr   

+**               MV_U32 ignoreGmiiErr  

+**               MV_U32 ignoreFcsErr   

+**               MV_U32 ignoreLlidCrcErr

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktFilterErrorSet(MV_U32 ignoreLenErr, 

+                                     MV_U32 ignoreGmiiErr, 

+                                     MV_U32 ignoreFcsErr, 

+                                     MV_U32 ignoreLlidCrcErr)

+{

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.ignoreLenErr     = ignoreLenErr;   

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.ignoreGmiiErr    = ignoreGmiiErr;  

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.ignoreFcsErr     = ignoreFcsErr;   

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.ignoreLlidCrcErr = ignoreLlidCrcErr;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktFilterErrorGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu filter error configuration

+**               

+**  PARAMETERS:  MV_U32 *ignoreLenErr   

+**               MV_U32 *ignoreGmiiErr  

+**               MV_U32 *ignoreFcsErr   

+**               MV_U32 *ignoreLlidCrcErr

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktFilterErrorGet(MV_U32 *ignoreLenErr, 

+                                     MV_U32 *ignoreGmiiErr, 

+                                     MV_U32 *ignoreFcsErr, 

+                                     MV_U32 *ignoreLlidCrcErr)

+{

+  *ignoreLenErr     = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.ignoreLenErr;  

+  *ignoreGmiiErr    = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.ignoreGmiiErr; 

+  *ignoreFcsErr     = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.ignoreFcsErr;  

+  *ignoreLlidCrcErr = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktFilter.ignoreLlidCrcErr; 

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktForwardSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu forwarding configuration

+**               

+**  PARAMETERS:  MV_U32 slowFrameToCtrlQueue

+**               MV_U32 slowFrameToRprtQueue

+**               MV_U32 rprtFrameToRprtQueue

+**               MV_U32 rprtFrameToDataQueue

+**               MV_U32 ctrlFrameToCtrlQueue

+**               MV_U32 ctrlFrameToDataQueue

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktForwardSet(MV_U32 slowFrameToCtrlQueue, 

+                                 MV_U32 slowFrameToRprtQueue,

+                                 MV_U32 rprtFrameToRprtQueue, 

+                                 MV_U32 rprtFrameToDataQueue,

+                                 MV_U32 ctrlFrameToCtrlQueue, 

+                                 MV_U32 ctrlFrameToDataQueue)

+{

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.slowFrameToCtrlQueue = slowFrameToCtrlQueue;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.slowFrameToRprtQueue = slowFrameToRprtQueue;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.rprtFrameToRprtQueue = rprtFrameToRprtQueue;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.rprtFrameToDataQueue = rprtFrameToDataQueue;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.ctrlFrameToCtrlQueue = ctrlFrameToCtrlQueue;

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.ctrlFrameToDataQueue = ctrlFrameToDataQueue;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktForwardGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu forwarding configuration

+**               

+**  PARAMETERS:  MV_U32 *slowFrameToCtrlQueue

+**               MV_U32 *slowFrameToRprtQueue

+**               MV_U32 *rprtFrameToRprtQueue

+**               MV_U32 *rprtFrameToDataQueue

+**               MV_U32 *ctrlFrameToCtrlQueue

+**               MV_U32 *ctrlFrameToDataQueue

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktForwardGet(MV_U32 *slowFrameToCtrlQueue, 

+                                 MV_U32 *slowFrameToRprtQueue,

+                                 MV_U32 *rprtFrameToRprtQueue, 

+                                 MV_U32 *rprtFrameToDataQueue,

+                                 MV_U32 *ctrlFrameToCtrlQueue, 

+                                 MV_U32 *ctrlFrameToDataQueue)

+{

+  *slowFrameToCtrlQueue = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.slowFrameToCtrlQueue;

+  *slowFrameToRprtQueue = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.slowFrameToRprtQueue;

+  *rprtFrameToRprtQueue = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.rprtFrameToRprtQueue;

+  *rprtFrameToDataQueue = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.rprtFrameToDataQueue;

+  *ctrlFrameToCtrlQueue = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.ctrlFrameToCtrlQueue;

+  *ctrlFrameToDataQueue = onuEponDb_s.onuEponDataPathTbl_s.onuEponPktForward.ctrlFrameToDataQueue;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktRxLlidSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu Rx LLID

+**               

+**  PARAMETERS:  MV_U32 llid 

+**               MV_U32 index

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktRxLlidSet(MV_U32 llid, MV_U32 index)

+{

+  if (index >= EPON_MAX_MAC_NUM) 

+    return(MV_ERROR);

+

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponRxLLID[index] = llid;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktRxLlidGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu Rx LLID

+**               

+**  PARAMETERS:  MV_U32 *llid 

+**               MV_U32 index

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktRxLlidGet(MV_U32 *llid, MV_U32 index)

+{

+  if (index >= EPON_MAX_MAC_NUM) 

+    return(MV_ERROR);

+

+  *llid = onuEponDb_s.onuEponDataPathTbl_s.onuEponRxLLID[index];

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktTxLlidSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set onu Tx LLID

+**               

+**  PARAMETERS:  MV_U32 llid 

+**               MV_U32 index

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktTxLlidSet(MV_U32 llid, MV_U32 index)

+{

+  if (index >= EPON_MAX_MAC_NUM) 

+    return(MV_ERROR);

+

+  onuEponDb_s.onuEponDataPathTbl_s.onuEponTxLLID[index] = llid;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPktTxLlidGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu Tx LLID

+**               

+**  PARAMETERS:  MV_U32 *llid 

+**               MV_U32 index

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPktTxLlidGet(MV_U32 *llid, MV_U32 index)

+{

+  if (index >= EPON_MAX_MAC_NUM) 

+    return(MV_ERROR);

+

+  *llid = onuEponDb_s.onuEponDataPathTbl_s.onuEponTxLLID[index];

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbStatusNotifySet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set Status Notify Callback in the database

+**               

+**  PARAMETERS:  STATUSNOTIFYFUNC statusCallback      

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbStatusNotifySet(STATUSNOTIFYFUNC statusCallback)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuStatusCallback = statusCallback;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbStatusNotifyGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu Status Notify Callback

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     Status Notify Callback

+**                   

+*******************************************************************************/

+STATUSNOTIFYFUNC onuEponDbStatusNotifyGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuStatusCallback);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSwRprtTimerTypeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set SW report timer type MAC or OS

+**               

+**  PARAMETERS:  MV_U32 timer type      

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuSwRprtTimerTypeSet(MV_U32 timerType)

+{

+  swRprtTimerType = timerType;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSwRprtTimerTypeGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return SW report timer type MAC or OS

+**               

+**  PARAMETERS:  None     

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 timer type 

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuSwRprtTimerTypeGet(void)

+{

+  return(swRprtTimerType);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSwRprtTimerTypeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set SW report MAC timer interval

+**               

+**  PARAMETERS:  MV_U32 timer interval      

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOnuSwRprtMacTimerIntervalSet(MV_U32 timerInterval)

+{

+  swRprtMacTimerInterval = timerInterval;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOnuSwRprtMacTimerIntervalGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return SW report MAC timer interval

+**               

+**  PARAMETERS:  None     

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 timer interval 

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOnuSwRprtMacTimerIntervalGet(void)

+{

+  return(swRprtMacTimerInterval);

+}

+

+

+/*******************************************************************************

+**

+**  onuEponDbModeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function sets EPON mode in the database

+**               

+**  PARAMETERS:  MV_U32 mode

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbModeSet(MV_U32   mode)

+{

+    if (mode >= E_EPON_IOCTL_MAX_MODE_NUM) 

+      return(MV_ERROR);

+

+    onuEponDb_s.onuEponGenTbl_s.onuEponMode = mode;

+

+    return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbModeGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function returns current EPON mode

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 mode

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbModeGet(void)

+{

+    return(onuEponDb_s.onuEponGenTbl_s.onuEponMode);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPcsCfgSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function sets EPON PCS configuration register value in the database

+**               

+**  PARAMETERS:  MV_U32 val

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbPcsCfgSet(MV_U32   val)

+{

+    onuEponDb_s.onuEponGenTbl_s.onuEponPcsCfg = val;

+

+    return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbPcsCfgGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function returns EPON PCS configuration register value

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 mode

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbPcsCfgGet(void)

+{

+    return(onuEponDb_s.onuEponGenTbl_s.onuEponPcsCfg);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOverheadSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function sets EPON Overhead register value in the database

+**               

+**  PARAMETERS:  MV_U32 val

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbOverheadSet(MV_U32   val)

+{

+    onuEponDb_s.onuEponGenTbl_s.onuEponOverHead = val;

+

+    return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbOverheadGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function returns EPON Overhead register value

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 mode

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbOverheadGet(void)

+{

+    return(onuEponDb_s.onuEponGenTbl_s.onuEponOverHead);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbXvrPolaritySet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function sets EPON XVR polarity register value in the database

+**               

+**  PARAMETERS:  MV_U32 val

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbXvrPolaritySet(MV_U32   val)

+{

+    onuEponDb_s.onuEponGenTbl_s.onuEponXvrPolarity = val;

+

+    return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbXvrPolarityGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function returns EPON XVR polarity register value

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_U32 mode

+**                   

+*******************************************************************************/

+MV_U32 onuEponDbXvrPolarityGet(void)

+{

+    return(onuEponDb_s.onuEponGenTbl_s.onuEponXvrPolarity);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbDgCallbackSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set Dying Gasp Callback in the database

+**               

+**  PARAMETERS:  DYINGGASPFUNC dgCallback      

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbDgCallbackSet(DYINGGASPFUNC dgCallback)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuDgCallback = dgCallback;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbDgCallbackGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu Dying Gasp Callback

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     Dying Gasp Callback

+**                   

+*******************************************************************************/

+DYINGGASPFUNC onuEponDbDgCallbackGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuDgCallback);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbLinkStatusCallbackSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set Link Status Callback in the database

+**               

+**  PARAMETERS:  LINKSTATUSFUNC linkStatusCallback    

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuEponDbLinkStatusCallbackSet(LINKSTATUSFUNC linkStatusCallback)

+{

+  onuEponDb_s.onuEponGenTbl_s.onuLinkStatusCallback = linkStatusCallback;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponDbLinkStatusCallbackGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu Link Status Callback

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     Link Status Callback

+**                   

+*******************************************************************************/

+LINKSTATUSFUNC onuEponDbLinkStatusCallbackGet(void)

+{

+  return(onuEponDb_s.onuEponGenTbl_s.onuLinkStatusCallback);

+}

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.h
new file mode 100755
index 0000000..120be03
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuDb.h
@@ -0,0 +1,524 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuDb.h                                               **/

+/**                                                                          **/

+/**  DESCRIPTION : This file contains ONU EPON database definitions          **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *      

+ *                                                                     

+ ******************************************************************************/

+#ifndef _ONU_EPON_DB_H

+#define _ONU_EPON_DB_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+/******************************************************************************/

+/* ========================================================================== */

+/*                               Database Definitions                         */

+/* ========================================================================== */

+/******************************************************************************/

+

+/* EPON MAC State Definitions */

+#define ONU_EPON_REGISTERED               (0x01) 

+#define ONU_EPON_NOT_REGISTERD            (0x00)

+ 

+/* EPON State Definitions */

+#define ONU_EPON_02_REGISTER_PENDING      (0x01) 

+#define ONU_EPON_03_OPERATION             (0x02) 

+#define ONU_EPON_MAX_NUM_OF_STATE         (4) 

+

+/* EPON Event Definitions */

+#define ONU_EPON_REGISTER_MSG_FLAG_ACK    (0x01) 

+#define ONU_EPON_REGISTER_MSG_FLAG_DEREG  (0x02) 

+#define ONU_EPON_REGISTER_MSG_FLAG_REREG  (0x03) 

+#define ONU_EPON_MAX_NUM_OF_EVENT         (8) 

+

+/* EPON Configuration Definitions */

+#define ONU_REG_REQ_AUTO_RES              (0x01) 

+#define ONU_REG_REQ_SW_RES                (0x00) 

+#define ONU_REG_ACK_AUTO_RES              (0x01) 

+#define ONU_REG_ACK_SW_RES                (0x00) 

+#define ONU_REPORT_AUTO_RES               (0x01) 

+#define ONU_REPORT_SW_RES                 (0x00) 

+#define ONU_RX_PCS_FEC_EN                 (0x01) 

+#define ONU_RX_PCS_FEC_DIS                (0x00) 

+#define ONU_TX_PCS_FEC_EN                 (0x01) 

+#define ONU_TX_PCS_FEC_DIS                (0x00) 

+#define ONU_TX_FEC_DIS                    (0x00) 

+#define ONU_RX_DIS                        (0x00) 

+#define ONU_RX_EN                         (0x01) 

+#define ONU_TX_DIS                        (0x00) 

+#define ONU_TX_EN                         (0x01) 

+

+/* EPON Registration Definitions */

+#define ONU_REGISTER                      (0x01) 

+#define ONU_REGISTER_ACK                  (0x02) 

+#define ONU_REGISTER_REQ                  (0x03) 

+

+/* EPON ONU Sync Time Definitions */

+#define ONU_DEF_SYNC_TIME_ADD             (0x00)

+#define ONU_DEF_SYNC_TIME_DIS_DISCOVER_AUTO (0x01)

+#define ONU_DEF_SYNC_TIME_DIS_GATE_AUTO   (0x00)

+#define ONU_DEF_SYNC_TIME_FORCE_SW        (0x00)

+#define ONU_DEF_SYNC_TIME                 (0x34)

+

+/* EPON ONU DDM Definitions */

+#define ONU_DEF_DDM_DELAY                 (0x08)

+

+/* EPON Packet Filtering Definitions */

+#define ONU_FORWARD_LLID_ALL_PKT          (0x00) 

+#define ONU_FORWARD_LLID_ALL_PKT_FILTER   (0x01) 

+#define ONU_FORWARD_LLID_7FFF_MODE_0_PKT  (0x01) 

+#define ONU_FORWARD_LLID_7FFF_MODE_1_PKT  (0x01) 

+#define ONU_FORWARD_LLID_XXXX_MODE_1_PKT  (0x00) 

+#define ONU_DROP_LLID_NNNN_MODE_1_PKT     (0x00) 

+

+/* EPON Error Filtering Definitions */

+#define ONU_FORWARD_LLID_CRC_ERR_PKT      (0x00) 

+#define ONU_FORWARD_LLID_CRC_ERR_PKT_IGNORE (0x01) 

+#define ONU_FORWARD_LLID_FCS_ERR_PKT      (0x00) 

+#define ONU_FORWARD_LLID_GMII_ERR_PKT     (0x00) 

+#define ONU_FORWARD_LLID_LEN_ERR_PKT      (0x00) 

+

+/* EPON Packet Forwarding Definitions */

+#define ONU_SLOW_FRAME_TO_CTRL_QUEUE      (0x00) 

+#define ONU_SLOW_FRAME_TO_RPRT_QUEUE      (0x00) 

+#define ONU_RPRT_FRAME_TO_RPRT_QUEUE      (0x00) 

+#define ONU_RPRT_FRAME_TO_DATA_QUEUE      (0x00) 

+#define ONU_CTRL_FRAME_TO_CTRL_QUEUE      (0x01) 

+#define ONU_CTRL_FRAME_TO_DATA_QUEUE      (0x00) 

+

+/* EPON Ether Type Definitions */

+#define ONU_MPCP_CTRL_TYPE                (0x8808) 

+#define ONU_OAM_CTRL_TYPE                 (0x8809) 

+

+/* EPON MAC Address Definitions */

+#define ONU_BROADCAST_ADDR_LOW            (0xC2000001) 

+#define ONU_BROADCAST_ADDR_HIGH           (0x00000180) 

+#define ONU_MAC_ADDR_LOW                  (0x09b0302c) 

+#define ONU_MAC_ADDR_HIGH                 (0x00000013) 

+

+/* EPON LLID Definitions */

+#define ONU_UNUSED_LLID                   (0xFFFF)

+#define ONU_DEF_TX_LLID                   (0x07FF)

+#define ONU_DEF_RX_LLID                   (0x0000)

+#define ONU_LLID_VALUE_MASK               (0x7FFF)

+#define ONU_LLID_INDEX_MASK               (0x000F)

+#define ONU_LLID_VALID_MASK               (0x0001)

+#define ONU_LLID_VALUE_SHIFT              (0)

+#define ONU_LLID_INDEX_SHIFT              (15)

+#define ONU_LLID_VALID_SHIFT              (19)

+

+/* EPON Laser Definitions */

+#define ONU_DEF_LASER_ON_TIME             (0x10)

+#define ONU_DEF_LASER_OFF_TIME            (0x00)

+#define ONU_DEF_LASER_ON_OFF_TIME         (0x30)

+

+/* EPON TXM Definitions */

+#ifdef PON_Z1

+#define ONU_DEF_TXM_CFG_MODE              (0x0)

+#define ONU_DEF_TXM_CFG_ALIGNMENT         (0x1)

+#define ONU_DEF_TXM_CFG_PRIORITY          (0x0)

+#else /* PON_Z2 */

+#define ONU_DEF_TXM_CFG_TFEC_1              (0x2)

+#define ONU_DEF_TXM_CFG_TFEC_2              (0x2)

+#define ONU_DEF_TXM_CFG_CTRL_FIFO_DIS_FCS_ON  (0x1)

+#define ONU_DEF_TXM_CFG_CTRL_FIFO_DIS_FCS_OFF (0x0)

+#define ONU_DEF_TXM_CFG_MASK_GMII_ON        (0x1)

+#define ONU_DEF_TXM_CFG_MASK_GMII_OFF       (0x0)

+#define ONU_DEF_TXM_CFG_BLOCK_DATA_ON       (0x1) 

+#define ONU_DEF_TXM_CFG_BLOCK_DATA_OFF      (0x0) 

+#define ONU_DEF_TXM_CFG_IPG_ADD             (0x1)

+#define ONU_DEF_TXM_CFG_IPG_DONT_ADD        (0x0)

+#define ONU_DEF_TXM_CFG_MODE_EPON           (0x00)

+#define ONU_DEF_TXM_CFG_MODE_GE             (0x01)

+#define ONU_DEF_TXM_CFG_MODE_TX_DIS         (0x10)

+#define ONU_DEF_TXM_CFG_ALIGNMENT_ODD       (0x10)

+#define ONU_DEF_TXM_CFG_ALIGNMENT_EVEN      (0x01)

+#define ONU_DEF_TXM_CFG_ALIGNMENT_DONT_CARE (0x00)

+#define ONU_DEF_TXM_CFG_PRIORITY_CTRL_FIRST (0x1)

+#define ONU_DEF_TXM_CFG_PRIORITY_RPRT_FIRST (0x0)

+#define ONU_DEF_TXM_CFG_EPON_OVERHEAD       (0x0E01)

+#define ONU_DEF_TXM_CFG_P2P_OVERHEAD        (0x0E06)

+#endif /* PON_Z2 */

+

+/* EPON PCS Definitions */

+#define ONU_DEF_PCS_CFG_RX_EN               (0x01)

+#define ONU_DEF_PCS_CFG_TX_EN               (0x10)

+

+/* P2P PCS Definitions */

+#define ONU_P2P_PCS_TX_RX_NEW               (0x610)

+#define ONU_P2P_PCS_TX_NEW                  (0x611)

+#define ONU_P2P_PCS_TX_RX_OLD               (0x613)

+

+/* EPON DDM Definitions */

+#define ONU_DEF_DDM_CFG_TX_EN_OR            (0x2)

+#define ONU_DEF_DDM_CFG_POLARITY_HIGH       (0x0)

+#define ONU_DEF_DDM_CFG_POLARITY_LOW        (0x1)

+

+/* EPON Packet Size */

+#define ONU_DEF_MIN_PKT_SIZE                (64)

+#define ONU_DEF_MAX_PKT_SIZE                (2040)

+

+/* EPON Holdover State */

+#define ONU_HOLDOVER_NOT_ACTIVE             (0)

+#define ONU_HOLDOVER_ACTIVE                 (1)

+

+/* EPON Silence State */

+#define ONU_SILENCE_NOT_ACTIVE              (0)

+#define ONU_SILENCE_ACTIVE                  (1)

+#define ONU_SILENCE_DISABLED                (0)

+#define ONU_SILENCE_ENABLED                 (1)

+

+/* EPON DBA */

+#define ONU_DBA_HW_RPRT_MODE                (0)

+#define ONU_DBA_SW_RPRT_MODE                (1)

+#define ONU_DBA_DEF_QUEUES_BIT_MAP          (0xFF)

+#define ONU_DBA_DEF_NUM_OF_QUEUE            (8)

+#define ONU_DBA_DEF_NUM_OF_QUEUESET         (1)

+#define ONU_DBA_MAX_NUM_OF_QUEUE            (8)

+#define ONU_DBA_MAX_NUM_OF_QUEUESET         (4)

+#define ONU_DBA_DEF_QUEUESET_0_THRESHOLD    (0x2000)

+#define ONU_DBA_DEF_QUEUESET_1_THRESHOLD    (0x4000)

+#define ONU_DBA_DEF_QUEUESET_2_THRESHOLD    (0x6000)

+#define ONU_DBA_DEF_QUEUESET_3_THRESHOLD    (0xFFFF)

+#define ONU_DBA_DEF_QUEUESET_DEF_THRESHOLD  (0xFFFF)

+#define ONU_DBA_UPDATE_LLID                 (2)

+#define ONU_DBA_ACTIVE_LLID                 (1)

+#define ONU_DBA_NON_ACTIVE_LLID             (0)

+#define ONU_DBA_SW_RPRT_NORMAL_DIR          (0)

+#define ONU_DBA_SW_RPRT_REVERSE_DIR         (1)

+

+#define ONU_OAM_CTRL_MSG                    (0)

+#define ONU_OAM_RPRT_MSG                    (1)

+#define ONU_OAM_DG_MSG                      (2)

+

+/* EPON FEC */

+#define ONU_FEC_CFG_INIT                    (0)

+#define ONU_FEC_CFG_RE_INIT                 (1)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef void (*EPONFUNCPTR) (MV_U8, MV_U8, MV_U8*);

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                               Database Definitions                         */

+/* ========================================================================== */

+/******************************************************************************/

+

+/* ONU EPON General Tables */

+typedef struct

+{

+  MV_U32 onuEponRegReqAutoRes;                          /* Register Request Auto Response */  

+  MV_U32 onuEponRegAckAutoRes;                          /* Register Ack Auto Response  */

+  MV_U32 onuEponReportAutoRes;                          /* Report Auto Response  */

+  MV_U32 onuEponRxPcsFecEn;                             /* Rx PCS FEC Enable */

+  MV_U32 onuEponTxPcsFecEn;                             /* Tx PCS FEC Enable */

+  MV_U32 onuEponTxFecEn;                                /* Tx FEC Enable */

+}S_OnuEponConfig;                                      

+                                                       

+typedef struct                                         

+{                                                      

+  MV_U32 addressLow;                                    /* MAC Address Low */  

+  MV_U32 addressHigh;                                   /* MAC Address High */

+}S_OnuEponMacAddr;

+

+typedef struct  

+{

+    MV_U8  state;	    /* Is threshold configuration active for the queue */ 

+    MV_U16 threshold;   /* Queue threshold: range 0 - 65535                */ 

+}S_OnuEponDbaQueue; 

+

+typedef struct                                         

+{

+  MV_U32            active;                          

+  MV_U32            highestReportQueue;                          

+  MV_U32            queuesBitMap;                                 

+  MV_U32            numOfQueues;                                 

+  MV_U32            numOfQueueSets;                              

+  S_OnuEponDbaQueue queueThreshold[EPON_MAX_QUEUE_SET_NUMBER][EPON_MAX_THRESHOLD_SET_RER_QUEUE];   

+}S_OnuEponDba;

+

+typedef struct                                         

+{

+  MV_U32 reg;                          

+  MV_U32 shift;                          

+  MV_U32 shadowIdx;                              

+}S_OnuEponDbaSwRprtRegMap;

+

+typedef struct                                         

+{

+  MV_U32 reg;                          

+  MV_U32 shadow;                              

+}S_OnuEponDbaShadowRegMap;

+

+typedef struct                                         

+{                                                      

+  MV_U32           onuEponValid[EPON_MAX_MAC_NUM];      /* ONU Valid for sync */  

+  MV_U32           onuEponState[EPON_MAX_MAC_NUM];      /* ONU State */  

+  MV_U32           onuEponSignalDetect;             

+  MV_U32           onuEponDsSyncOkPcs;             

+  MV_U32           onuEponCtrlType;                     /* ONU Control Type */

+  MV_U32           onuEponSyncTime[EPON_MAX_MAC_NUM];   /* ONU Sync Time */

+  MV_U32           onuEponHoldoverState;             

+  MV_U32           onuEponHoldoverTime;             

+  MV_U32           onuEponHoldoverExecute;             

+  MV_U32           onuEponSilenceState;             

+  MV_U32           onuEponDbaMode;                      /* HW / SW Modes */

+  MV_U32           onuEponDbaSwQueuesetDir;             /* SW Report Queueset Direction */

+  MV_U32           onuEponDbaSwQueueDir;                /* SW Report Queue Direction */

+  S_OnuEponDba     onuEponDba[EPON_MAX_MAC_NUM];

+  S_OnuEponConfig  onuEponCfg;                          /* ONU Configuration */

+  S_OnuEponMacAddr onuEponMacAddr[EPON_MAX_MAC_NUM];    /* ONU MAC Address */

+  S_OnuEponMacAddr onuEponBcastAddr;                    /* ONU MAC Broadcast Address */

+  STATUSNOTIFYFUNC onuStatusCallback;

+  DYINGGASPFUNC    onuDgCallback;

+  LINKSTATUSFUNC   onuLinkStatusCallback;

+  MV_U32           onuEponMode;

+  MV_U32           onuEponPcsCfg;             

+  MV_U32           onuEponOverHead;             

+  MV_U32           onuEponPhyOutput;             

+  MV_U32           onuEponXvrPolarity;             

+}S_OnuEponGenTbl;                                     

+

+/* ONU EPON Data Path tables */

+typedef struct

+{

+  MV_U32 slowFrameToCtrlQueue;                     

+  MV_U32 slowFrameToRprtQueue;                     

+  MV_U32 rprtFrameToRprtQueue;                     

+  MV_U32 rprtFrameToDataQueue;                     

+  MV_U32 ctrlFrameToCtrlQueue;                     

+  MV_U32 ctrlFrameToDataQueue;                     

+}S_OnuEponRxPktForward;

+

+typedef struct

+{

+  MV_U32 dropLlid1NNN;

+  MV_U32 forwardLlidAll;                     

+  MV_U32 forwardLlid1XXX;                     

+  MV_U32 forwardLlid1FFF;                     

+  MV_U32 forwardLlid0FFF;                     

+  MV_U32 ignoreLenErr;                   

+  MV_U32 ignoreGmiiErr;                    

+  MV_U32 ignoreFcsErr;                    

+  MV_U32 ignoreLlidCrcErr;                    

+}S_OnuEponRxPktFilter;

+

+typedef struct

+{

+  MV_U32                onuEponRxPktMinSize;             /* ONU Rx Packet Min Size */

+  MV_U32                onuEponRxPktMaxSize;             /* ONU Rx Packet Max Size */

+  S_OnuEponRxPktForward onuEponPktForward;               /* ONU Rx Packet Forward */

+  S_OnuEponRxPktFilter  onuEponPktFilter;                /* ONU Rx Packet Filter */ 

+  MV_U32                onuEponRxLLID[EPON_MAX_MAC_NUM]; /* ONU Rx Packet Rx LLID Array */

+  MV_U32                onuEponTxLLID[EPON_MAX_MAC_NUM]; /* ONU Rx Packet Tx LLID Array */

+}S_OnuEponDatapathTbl;                                     

+

+/* ONU EPON DataBase */

+typedef struct

+{

+  S_OnuEponGenTbl      onuEponGenTbl_s;

+  S_OnuEponDatapathTbl onuEponDataPathTbl_s;

+}S_OnuEponDb;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+/* ONU EPON Database */

+extern S_OnuEponDb onuEponDb_s;

+

+/* Global functions

+------------------------------------------------------------------------------*/

+/* ONU EPON database init function */

+MV_STATUS onuEponDbInit(void);

+MV_STATUS onuEponDbReInit(MV_U32 macId);

+

+/* ONU EPON general table API functions */

+MV_STATUS onuEponDbOnuValidSet(MV_BOOL onuValid, MV_U32 macId);

+MV_BOOL   onuEponDbOnuValidGet(MV_U32 macId);

+MV_STATUS onuEponDbOnuStateSet(MV_U32 onuState, MV_U32 macId);

+MV_U32    onuEponDbOnuStateGet(MV_U32 macId);

+MV_STATUS onuEponDbOnuSignalDetectSet(MV_U32 onuState);

+MV_U32    onuEponDbOnuSignalDetectGet(void);

+MV_STATUS onuEponDbOnuDsSyncOkPcsSet(MV_U32 onuState);

+MV_U32    onuEponDbOnuDsSyncOkPcsGet(void);

+MV_STATUS onuEponDbOnuCtrlTypeSet(MV_U32 ctrlType);

+MV_U32    onuEponDbOnuCtrlTypeGet(void);

+MV_STATUS onuEponDbOnuSyncTimeSet(MV_U32 syncTime, MV_U32 macId);

+MV_U32    onuEponDbOnuSyncTimeGet(MV_U32 macId);

+MV_STATUS onuEponDbOnuMacAddrSet(MV_U32 lowAddr, MV_U32 highAddr, MV_U32 macId);

+MV_STATUS onuEponDbOnuMacAddrGet(MV_U32 *lowAddr, MV_U32 *highAddr, MV_U32 macId);

+MV_STATUS onuEponDbOnuBcastAddrSet(MV_U32 lowAddr, MV_U32 highAddr);

+MV_STATUS onuEponDbOnuBcastAddrGet(MV_U32 *lowAddr, MV_U32 *highAddr);

+MV_STATUS onuEponDbOnuCfgSet(MV_U32 regReqAutoRes, MV_U32 regAckAutoRes, MV_U32 reportAutoRes, 

+                             MV_U32 rxPcsFecEn, MV_U32 txPcsFecEn, MV_U32 txFecEn);

+MV_STATUS onuEponDbOnuCfgGet(MV_U32 *regReqAutoRes, MV_U32 *regAckAutoRes, MV_U32 *reportAutoRes, 

+                             MV_U32 *rxPcsFecEn, MV_U32 *txPcsFecEn, MV_U32 *txFecEn);

+MV_STATUS onuEponDbOnuCfgAutoSet(MV_U32 regReqAutoRes, MV_U32 regAckAutoRes, MV_U32 reportAutoRes);

+MV_STATUS onuEponDbOnuRxFecCfgSet(MV_U32 rxPcsFecEn);

+MV_STATUS onuEponDbOnuRxFecCfgGet(MV_U32 *rxPcsFecEn);

+MV_STATUS onuEponDbOnuTxFecCfgGet(MV_U32 *txFecEn, MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaHighestReportQueueSet(MV_U32 queueNum, MV_U32 macId);

+MV_U32    onuEponDbOnuDbaHighestReportQueueGet(MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaQueuesBitMapSet(MV_U32 queuesBitMap, MV_U32 macId);

+MV_U32    onuEponDbOnuDbaQueuesBitMapGet(MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaNumOfQueuesSet(MV_U32 numOfQueues, MV_U32 macId);

+MV_U32    onuEponDbOnuDbaNumOfQueuesGet(MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaNumOfQueuesetSet(MV_U32 numOfQueueset, MV_U32 macId);

+MV_U32    onuEponDbOnuDbaNumOfQueuesetGet(MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaQueueThresholdSet(MV_U32 threshold, MV_U32 state, MV_U32 queueId, 

+										   MV_U32 queueSet, MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaQueueThresholdGet(MV_U32 *threshold, MV_U32 *state, MV_U32 queueId, 

+										   MV_U32 queueSet, MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaLlidThresholdGet(S_OnuEponDba *llidDba, MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaLlidActiveStatusSet(MV_U32 status, MV_U32 macId);

+MV_U32    onuEponDbOnuDbaLlidActiveStatusGet(MV_U32 macId);

+MV_STATUS onuEponDbOnuDbaModeSet(MV_U32 mode);

+MV_U32    onuEponDbOnuDbaModeGet(void);

+MV_STATUS onuEponDbOnuDbaSwModeQueuesetDirSet(MV_U32 dir);

+MV_U32    onuEponDbOnuDbaSwModeQueuesetDirGet(void);

+MV_STATUS onuEponDbOnuDbaSwModeQueueDirSet(MV_U32 dir);

+MV_U32    onuEponDbOnuDbaSwModeQueueDirGet(void);

+MV_STATUS onuEponDbOnuHoldoverStateSet(MV_U32 state);

+MV_U32    onuEponDbOnuHoldoverStateGet(void);

+MV_STATUS onuEponDbOnuHoldoverTimeSet(MV_U32 time);

+MV_U32    onuEponDbOnuHoldoverTimeGet(void);

+MV_STATUS onuEponDbOnuHoldoverExecSet(MV_U32 state);

+MV_U32    onuEponDbOnuHoldoverExecGet(void);

+MV_STATUS onuEponDbOnuSilenceStateSet(MV_U32 state);

+MV_U32    onuEponDbOnuSilenceStateGet(void);

+MV_STATUS onuEponDbOnuSwRprtTimerTypeSet(MV_U32 timerType);

+MV_U32    onuEponDbOnuSwRprtTimerTypeGet(void);

+MV_STATUS onuEponDbOnuSwRprtMacTimerIntervalSet(MV_U32 timerInterval);

+MV_U32    onuEponDbOnuSwRprtMacTimerIntervalGet(void);

+

+

+/* ONU EPON Data Path table API functions */

+MV_STATUS onuEponDbPktSizeSet(MV_U32 minSize, MV_U32 maxSize);

+MV_STATUS onuEponDbPktSizeGet(MV_U32 *minSize, MV_U32 *maxSize);

+MV_STATUS onuEponDbPktFilterPacketSet(MV_U32 forwardLlidAll, MV_U32 forwardLlid1XXX, 

+                                      MV_U32 forwardLlid1FFF, MV_U32 forwardLlid0FFF, MV_U32 dropLlid1NNN);

+MV_STATUS onuEponDbPktFilterPacketGet(MV_U32 *forwardLlidAll, MV_U32 *forwardLlid1XXX, 

+                                      MV_U32 *forwardLlid1FFF, MV_U32 *forwardLlid0FFF, MV_U32 *dropLlid1NNN);

+MV_STATUS onuEponDbPktFilterErrorSet(MV_U32 ignoreLenErr, MV_U32 ignoreGmiiErr, 

+                                     MV_U32 ignoreFcsErr, MV_U32 ignoreLlidCrcErr);

+MV_STATUS onuEponDbPktFilterErrorGet(MV_U32 *ignoreLenErr, MV_U32 *ignoreGmiiErr, 

+                                     MV_U32 *ignoreFcsErr, MV_U32 *ignoreLlidCrcErr);

+MV_STATUS onuEponDbPktForwardSet(MV_U32 slowFrameToCtrlQueue, MV_U32 slowFrameToRprtQueue,

+                                 MV_U32 rprtFrameToRprtQueue, MV_U32 rprtFrameToDataQueue,

+                                 MV_U32 ctrlFrameToCtrlQueue, MV_U32 ctrlFrameToDataQueue);

+MV_STATUS onuEponDbPktForwardGet(MV_U32 *slowFrameToCtrlQueue, MV_U32 *slowFrameToRprtQueue,

+                                 MV_U32 *rprtFrameToRprtQueue, MV_U32 *rprtFrameToDataQueue,

+                                 MV_U32 *ctrlFrameToCtrlQueue, MV_U32 *ctrlFrameToDataQueue);

+MV_STATUS onuEponDbPktRxLlidSet(MV_U32 llid, MV_U32 index);

+MV_STATUS onuEponDbPktRxLlidGet(MV_U32 *llid, MV_U32 index);

+MV_STATUS onuEponDbPktTxLlidSet(MV_U32 llid, MV_U32 index);

+MV_STATUS onuEponDbPktTxLlidGet(MV_U32 *llid, MV_U32 index);

+

+MV_STATUS        onuEponDbStatusNotifySet(STATUSNOTIFYFUNC statusCallback);

+STATUSNOTIFYFUNC onuEponDbStatusNotifyGet(void);

+

+MV_STATUS        onuEponDbDgCallbackSet(DYINGGASPFUNC dgCallback);

+DYINGGASPFUNC    onuEponDbDgCallbackGet(void);

+

+MV_STATUS        onuEponDbLinkStatusCallbackSet(LINKSTATUSFUNC linkStatusCallback);

+LINKSTATUSFUNC   onuEponDbLinkStatusCallbackGet(void);

+

+MV_STATUS matchDestAddressToMacId(MV_U8 *destAddr, MV_U32 *macId);

+

+MV_STATUS   onuEponDbModeSet(MV_U32 mode);

+MV_U32      onuEponDbModeGet(void);

+MV_STATUS   onuEponDbPcsCfgSet(MV_U32 val);

+MV_U32      onuEponDbPcsCfgGet(void);

+MV_STATUS   onuEponDbOverheadSet(MV_U32 val);

+MV_U32      onuEponDbOverheadGet(void);

+MV_STATUS   onuEponDbXvrPolaritySet(MV_U32 val);

+MV_U32      onuEponDbXvrPolarityGet(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_EPON_DB_H */

+

+ 

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuHeader.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuHeader.h
new file mode 100755
index 0000000..29addcc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuHeader.h
@@ -0,0 +1,124 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuHeader.h                                           **/

+/**                                                                          **/

+/**  DESCRIPTION : This file pon module header files                         **/

+/**                                                                          **/ 

+/******************************************************************************

+ *                                                                            *

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== * 

+ *                                                                            *

+ ******************************************************************************/

+

+#ifndef _ONU_EPON_HEADER_H 

+#define _ONU_EPON_HEADER_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuRtos.h"

+#include "mvPonOnuDefines.h"

+#include "mvPonOnuRegs.h"

+#include "mvPonOnuMac.h"

+#include "eponOnuBoard.h"

+#include "eponOnuLnxKsOs.h"

+#include "eponOnuLnxKsMI.h"

+#include "eponOnuLnxKsUI.h"

+#include "eponOnuStd.h"

+#include "eponOnuInit.h"

+#include "eponOnuIsr.h"

+#include "eponOnuApi.h"

+#include "eponOnuDb.h"

+#include "eponOnuPm.h"

+#include "eponOnuMngr.h"

+#include "eponOnuStd.h"

+#include "ponOnuBoard.h"

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums 

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Macros

+------------------------------------------------------------------------------*/

+

+#endif /* _ONU_EPON_HEADER_H */

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.c
new file mode 100755
index 0000000..9c31f1f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.c
@@ -0,0 +1,967 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or

+modify this File in accordance with the terms and conditions of the General

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is

+available along with the File in the license.txt file or by writing to the Free

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY

+DISCLAIMED.  The GPL License provides additional details about this warranty

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or

+modify this File under the following licensing terms.

+Redistribution and use in source and binary forms, with or without modification,

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer.

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution.

+

+    *   Neither the name of Marvell nor the names of its contributors may be

+        used to endorse or promote products derived from this software without

+        specific prior written permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuInit.c                                             **/

+/**                                                                          **/

+/**  DESCRIPTION : This file contains ONU EPON init sequence definitions     **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *

+ * ========================================================================== *

+ *

+ ******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuHeader.h"

+#include "eponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/

+#define __FILE_DESC__ "mv_pon/core/epon/eponOnuInit.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+extern MV_U32 dbaRprtT0StateVal;

+extern MV_U32 dbaRprtT0StateInterval;

+extern MV_U32 dbaRprtT1StateVal;

+extern MV_U32 dbaRprtT1StateInterval;

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponAsicInit(void);

+#if 0 /* NOT USED */

+MV_STATUS onuEponAsicFiFoReInit(void);

+#endif /* NOT USED */

+MV_STATUS onuGponAppInit(void);

+void      onuGponStateAndEventTblInit(void);

+void      onuGponInPmInit(void);

+

+/*******************************************************************************

+**

+**  onuEponSetup

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function execute onu setup init sequence

+**

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**               MV_ERROR

+**

+*******************************************************************************/

+MV_STATUS onuEponSetup(void)

+{

+  MV_STATUS rcode;

+

+  /* init onu base address */

+  rcode = onuEponGlbAddrInit();

+  if (rcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) Failed to init onu base address\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* init onu database */

+  rcode = onuEponDbInit();

+  if (rcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) Failed to init onu database\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* init onu Asic */

+  rcode = onuEponAsicInit();

+  if (rcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) Failed to init asic\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  return(MV_OK);

+}

+

+#ifndef PON_FPGA

+/*******************************************************************************

+**

+**  onuEponAsicLedsInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function init onu leds

+**

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**

+*******************************************************************************/

+MV_STATUS onuEponAsicLedsInit(void)

+{

+  onuPonLedInit();

+

+  onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_OFF);

+  onuPonLedHandler(ONU_PON_SYS_LED, ACTIVE_LED_ON);

+

+  return(MV_OK);

+}

+#endif /* PON_FPGA */

+

+/*******************************************************************************

+**

+**  onuEponAsicInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function init default onu EPON MAC configuration

+**

+**  PARAMETERS:  MV_BOOL initTime - init indication flag, true = init sequence

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponAsicInit(void)

+{

+	MV_STATUS status;

+	MV_U32    macAddrHigh;

+	MV_U32    macAddrLow;

+#ifdef PON_Z2

+	MV_U32    pcsConfig;

+#endif /* PON_Z2 */

+	MV_U32    macId;

+	MV_U32    devId = mvCtrlModelGet();

+

+#ifndef PON_FPGA

+	status = onuEponSerdesInit();

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) onuEponSerdesInit\n", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+#endif /* PON_FPGA */

+

+#ifndef PON_FPGA

+	onuEponAsicLedsInit();

+#endif /*PON_FPGA */

+

+	/* Setup TX power ON/OFF GPP and turn TX power OFF */

+	status = onuPonTxPowerControlInit();

+	if (status == MV_OK)

+		status = onuPonTxPowerOn(MV_FALSE);

+

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) Unable to configure TX POWER GPP\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	/* Disable MAC */

+	status = mvOnuEponMacOnuEnableSet(ONU_RX_DIS, ONU_TX_DIS);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacOnuStateSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	/* MAC State */

+	for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {

+		status = mvOnuEponMacOnuStateSet(ONU_EPON_NOT_REGISTERD, macId);

+		if (status != MV_OK) {

+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+				   "ERROR: (%s:%d) mvOnuEponMacOnuStateSet\n\r", __FILE_DESC__, __LINE__);

+			return(MV_ERROR);

+		}

+	}

+

+	/* Broadcast Address */

+	status = mvOnuEponMacGenBcastAddrSet(ONU_BROADCAST_ADDR_HIGH, ONU_BROADCAST_ADDR_LOW);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacGenBcastAddrSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	/* Unicast Address */

+	for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {

+		onuEponDbOnuMacAddrGet(&macAddrLow, &macAddrHigh, macId);

+

+		status = mvOnuEponMacGenUcastAddrSet(macAddrHigh, macAddrLow, macId);

+		if (status != MV_OK) {

+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+				   "ERROR: (%s:%d) mvOnuEponMacGenUcastAddrSet\n\r", __FILE_DESC__, __LINE__);

+			return(MV_ERROR);

+		}

+	}

+

+	status = mvOnuEponMacGenSyncTimeSet(ONU_DEF_SYNC_TIME,

+					    ONU_DEF_SYNC_TIME_ADD,

+					    ONU_DEF_SYNC_TIME_FORCE_SW,

+					    ONU_DEF_SYNC_TIME_DIS_GATE_AUTO,

+					    ONU_DEF_SYNC_TIME_DIS_DISCOVER_AUTO);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacGenSyncTimeSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacDdmDelaySet(ONU_DEF_DDM_DELAY);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvAsicReg_EPON_DDM_1814_CONFIG\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacRxpPacketForwardSet(ONU_CTRL_FRAME_TO_DATA_QUEUE,

+						 ONU_CTRL_FRAME_TO_CTRL_QUEUE,

+						 ONU_RPRT_FRAME_TO_DATA_QUEUE,

+						 ONU_RPRT_FRAME_TO_RPRT_QUEUE,

+						 ONU_SLOW_FRAME_TO_RPRT_QUEUE,

+						 ONU_SLOW_FRAME_TO_CTRL_QUEUE);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacRxpPacketForwardSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacOnuRegAutoUpdateStateSet(1);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacOnuAutoUpdateStateSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	/* ONU_REPORT_AUTO_RES is always ON */

+	/* In case of SW Report via Control FIFO, the HW will send empty report - keep alive */

+	status = mvOnuEponMacGenOnuConfigSet(ONU_RX_PCS_FEC_DIS,

+					     ONU_TX_PCS_FEC_DIS,

+					     ONU_REPORT_AUTO_RES,

+					     ONU_REG_ACK_AUTO_RES,

+					     ONU_REG_REQ_AUTO_RES,

+					     ONU_TX_FEC_DIS);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacGenOnuConfigSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacRxpPacketFilterSet(ONU_FORWARD_LLID_CRC_ERR_PKT,

+						ONU_FORWARD_LLID_FCS_ERR_PKT,

+						ONU_FORWARD_LLID_GMII_ERR_PKT,

+						ONU_FORWARD_LLID_LEN_ERR_PKT,

+						ONU_FORWARD_LLID_ALL_PKT,

+						ONU_FORWARD_LLID_7FFF_MODE_0_PKT,

+						ONU_FORWARD_LLID_7FFF_MODE_1_PKT,

+						ONU_FORWARD_LLID_XXXX_MODE_1_PKT,

+						ONU_DROP_LLID_NNNN_MODE_1_PKT);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacRxpPacketFilterSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacGenLaserParamSet(ONU_DEF_LASER_ON_OFF_TIME,

+					      ONU_DEF_LASER_ON_TIME,

+					      ONU_DEF_LASER_OFF_TIME);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacGenLaserParamSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {

+		status = mvOnuEponMacTxmLlidSet(ONU_DEF_TX_LLID, macId);

+		if (status != MV_OK) {

+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+				   "ERROR: (%s:%d) mvOnuEponMacTxmLlidSet\n\r", __FILE_DESC__, __LINE__);

+			return(MV_ERROR);

+		}

+

+		status = mvOnuEponMacRxpLlidDataSet(ONU_DEF_RX_LLID, macId);

+		if (status != MV_OK) {

+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+				   "ERROR: (%s:%d) mvOnuEponMacRxpLlidDataSet\n\r", __FILE_DESC__, __LINE__);

+			return(MV_ERROR);

+		}

+	}

+

+#ifdef PON_Z1

+

+	status = mvOnuEponMacTxmConfigSet(ONU_DEF_TXM_CFG_MODE,

+					  ONU_DEF_TXM_CFG_ALIGNMENT,

+					  ONU_DEF_TXM_CFG_PRIORITY);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacTxmConfigSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+#else /* PON_Z2 and later */

+

+	status = mvOnuEponMacTxmOverheadSet(0x0E01);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacTxmOverheadSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacTxmConfigSet(ONU_DEF_TXM_CFG_TFEC_1,

+					  ONU_DEF_TXM_CFG_TFEC_2,

+					  ONU_DEF_TXM_CFG_CTRL_FIFO_DIS_FCS_OFF,

+					  ONU_DEF_TXM_CFG_MASK_GMII_OFF,

+					  ONU_DEF_TXM_CFG_BLOCK_DATA_OFF,

+					  ONU_DEF_TXM_CFG_IPG_ADD,

+					  ONU_DEF_TXM_CFG_MODE_EPON,

+					  ONU_DEF_TXM_CFG_ALIGNMENT_EVEN,

+					  ONU_DEF_TXM_CFG_PRIORITY_CTRL_FIRST);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacTxmConfigSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	pcsConfig = (ONU_DEF_PCS_CFG_RX_EN | ONU_DEF_PCS_CFG_TX_EN);

+	status = mvOnuEponMacPcsConfigSet(pcsConfig);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacPcsConfigSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacDdmTxPolaritySet(ONU_DEF_DDM_CFG_TX_EN_OR,

+					      ONU_DEF_DDM_CFG_POLARITY_HIGH);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacDdmTxPolaritySet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	onuEponDbXvrPolaritySet(ONU_DEF_DDM_CFG_POLARITY_HIGH);

+	mvOnuPonMacBurstEnablePolarityInit(ONU_DEF_DDM_CFG_POLARITY_HIGH);

+

+	status = mvOnuEponMacGpmDiscoveryGrantLengthSet(0x26,  /* grantLength */

+							0x06,  /* addOffsetForCalc */

+							0x32); /* grantLengthMultiTq */

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacGpmDiscoveryGrantLengthSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacGenTimestampConfig(0x0,   /* gpmAddSyncTimeToTimestamp */

+						0x760, /* gpmAimestampOffset */

+						0x1,   /* txmAddSyncTimeToTimestamp */

+						0x0,   /* txmUseTimestampImage */

+						0x77B);/* txmTimestampOffset) */

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacGenTimestampConfig\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	/* ==================================== */

+	/* ==         SW REPORT MODE         == */

+	/* ==================================== */

+	for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {

+		status  = mvOnuEponMacTxmCppReportConfig(0xFF,	/* Queueset2 not supported -

+								 * set to 0xFF (queueReportQ2) */

+							 0x1,	/* Queueset2 not supported - set to 0x1,

+								 * Software (reportBitmapQ2) */

+							 0xFF,	/* Queueset1 supported - set to 0, means all

+								 * 8 queues are active (queueReport) */

+							 1,	/* Number of queueSet -

+								 * support for 1 queueset */

+							 0x1,	/* Queueset1 supported - set to 0x1,

+								 * Software (reportBitmap) */

+							 macId);

+		if (status != MV_OK) {

+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+				   "ERROR: (%s:%d) mvOnuEponMacTxmCppReportConfig, macId=%d\n\r",

+				   __FILE_DESC__, __LINE__, macId);

+			return(MV_ERROR);

+		}

+	}

+

+	if (devId == MV_6601_DEV_ID) {

+

+#if (!defined PON_Z1) && (!defined PON_Z2)

+		/* DDM TX Polarity */

+		status = mvOnuEponMacDdmTxPolaritySet(EPON_DDM_TX_EN_MASK_DEFAULT,

+						      EPON_DDM_TX_TX_POL_DEFAULT,

+						      EPON_DDM_TX_SERDES_POL_DEFAULT,

+						      EPON_DDM_TX_XVR_POL_DEFAULT,

+						      EPON_DDM_TX_BURST_ENA_DEFAULT);

+		if (status != MV_OK) {

+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+				   "ERROR: (%s:%d) mvOnuEponMacDdmTxPolaritySet\n\r", __FILE_DESC__, __LINE__);

+			return(MV_ERROR);

+		}

+#endif

+	} /* devId == MV_6601_DEV_ID*/

+

+	status = mvOnuEponMacGenUtmTcPeriodSet(0x100);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacGenUtmTcPeriodSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuEponMacGenUtmTcPeriodEnSet(0x1);

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuEponMacGenUtmTcPeriodEnSet\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+	status = mvOnuPonMacBurstEnableInit();

+	if (status != MV_OK) {

+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+			   "ERROR: (%s:%d) mvOnuPonMacBurstEnableInit\n\r", __FILE_DESC__, __LINE__);

+		return(MV_ERROR);

+	}

+

+#endif /* !defined PON_Z1 */

+

+	return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponAsicReInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function re-init default onu EPON MAC configuration

+**

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponAsicReInit(MV_U32 macId, MV_U32 silenceMode)

+{

+  MV_STATUS status;

+  MV_U32    rxGenFecEn = 0;

+  MV_U32    txGenFecEn = 0;

+  MV_U32    txMacFecEn[8] = {0,0,0,0,0,0,0,0};

+

+  status = mvOnuEponMacOnuStateSet(ONU_EPON_NOT_REGISTERD, macId);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacOnuStateSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  status = mvOnuEponMacTxmLlidSet(ONU_DEF_TX_LLID, macId);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacTxmLlidSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  status = mvOnuEponMacRxpLlidDataSet(ONU_DEF_RX_LLID, macId);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacRxpLlidDataSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* handle silence mode */

+  if ((onuEponDbOnuSilenceStateGet() != ONU_SILENCE_NOT_ACTIVE) &&

+	  (silenceMode == ONU_SILENCE_ENABLED))

+  {

+	/* Clear onu Silence Timers */

+	onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonSilenceTimerId[macId]));

+

+	status  = mvOnuEponMacGenOnuConfigAutoAckSet(ONU_REG_ACK_AUTO_RES);

+	status |= mvOnuEponMacGenOnuConfigAutoRequestSet(ONU_REG_REQ_AUTO_RES);

+	if (status != MV_OK)

+	{

+	  mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,

+				 "ERROR: (%s:%d) Failed to enable auto request / ack\n\r", __FILE_DESC__, __LINE__);

+	  return(status);

+	}

+

+	onuEponDbOnuCfgAutoSet(ONU_REG_REQ_AUTO_RES, ONU_REG_ACK_AUTO_RES, ONU_REPORT_AUTO_RES);

+  }

+

+  mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MODULE,

+			 "DEBUG: (%s:%d) onuEponAsicReInit, rxGenFecEn(%d), txGenFecEn(%d), txMacFecEn(%d,%d,%d,%d,%d,%d,%d,%d)\n",

+			 __FILE_DESC__, __LINE__, rxGenFecEn, txGenFecEn, txMacFecEn[0], txMacFecEn[1], txMacFecEn[2], txMacFecEn[3],

+             txMacFecEn[4], txMacFecEn[5], txMacFecEn[6], txMacFecEn[7]);

+

+  status = onuEponApiFecConfig(rxGenFecEn, txGenFecEn, txMacFecEn, ONU_FEC_CFG_RE_INIT);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+    		   "ERROR: (%s:%d) onuEponApiFecConfig\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* clear OAM SW FIFO - Tx */

+  onuEponOamFlushAllMsg();

+

+  mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MODULE,

+			 "DEBUG: (%s:%d) onuEponAsicReInit, onuEponOamFlushAllMsg\n\r", __FILE_DESC__, __LINE__);

+

+#if 0 /* NOT USED */

+  status = onuEponAsicQueueDisable(macId);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) onuEponAsicQueueDisable\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  if (macId == 0)

+  {

+    status = onuEponAsicFiFoReInit();

+    if (status != MV_OK)

+    {

+      mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+                 "ERROR: (%s:%d) onuEponMacFiFoReInit\n\r", __FILE_DESC__, __LINE__);

+      return(MV_ERROR);

+    }

+  }

+#endif  /* NOT USED */

+

+  return(MV_OK);

+}

+

+#if 0 /* NOT USED */

+/*******************************************************************************

+**

+**  onuEponAsicFiFoReInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function re-init onu EPON MAC Fifo

+**

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponAsicFiFoReInit(void)

+{

+  MV_STATUS status;

+  MV_U32    rxEnable;

+  MV_U32    txEnable;

+

+  /* Disable all TX  */

+  rxEnable = 1;

+  txEnable = 0;

+  status = mvOnuEponMacOnuEnableSet(rxEnable, txEnable);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacOnuEnableSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* disable onu pon interrupt mask */

+  mvOnuEponMacPonInterruptMaskSet(0);

+

+  /* Turn on GMII MASK */

+  /* Switch TX port to Standard GE mode */

+  status = mvOnuEponMacTxmConfigSet(ONU_DEF_TXM_CFG_TFEC_1,

+                                    ONU_DEF_TXM_CFG_TFEC_2,

+                                    ONU_DEF_TXM_CFG_CTRL_FIFO_DIS_FCS_OFF,

+                                    ONU_DEF_TXM_CFG_MASK_GMII_ON,

+                                    ONU_DEF_TXM_CFG_BLOCK_DATA_OFF,

+                                    ONU_DEF_TXM_CFG_IPG_DONT_ADD,

+                                    ONU_DEF_TXM_CFG_MODE_GE,

+                                    ONU_DEF_TXM_CFG_ALIGNMENT_EVEN,

+                                    ONU_DEF_TXM_CFG_PRIORITY_RPRT_FIRST);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacTxmConfigSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* Enable all TX  */

+  rxEnable = 1;

+  txEnable = 0xFF;

+  status = mvOnuEponMacOnuEnableSet(rxEnable, txEnable);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacOnuEnableSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* Wait 10ms */

+  mvOsDelay(10);

+

+  /* Disable all TX  */

+  rxEnable = 1;

+  txEnable = 0;

+  status = mvOnuEponMacOnuEnableSet(rxEnable, txEnable);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacOnuEnableSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* Switch TX port to Standard EPON mode */

+  /* Turn off GMII MASK */

+  status = mvOnuEponMacTxmConfigSet(ONU_DEF_TXM_CFG_TFEC_1,

+                                    ONU_DEF_TXM_CFG_TFEC_2,

+                                    ONU_DEF_TXM_CFG_CTRL_FIFO_DIS_FCS_OFF,

+                                    ONU_DEF_TXM_CFG_MASK_GMII_OFF,

+                                    ONU_DEF_TXM_CFG_BLOCK_DATA_OFF,

+                                    ONU_DEF_TXM_CFG_IPG_DONT_ADD,

+                                    ONU_DEF_TXM_CFG_MODE_EPON,

+                                    ONU_DEF_TXM_CFG_ALIGNMENT_EVEN,

+                                    ONU_DEF_TXM_CFG_PRIORITY_RPRT_FIRST);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacTxmConfigSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* enable onu pon interrupt mask */

+  mvOnuEponMacPonInterruptMaskSet(0x120);

+

+  /* Enable all TX  */

+ rxEnable = 1;

+ txEnable = 0xFF;

+ status = mvOnuEponMacOnuEnableSet(rxEnable, txEnable);

+ if (status != MV_OK)

+ {

+   mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+              "ERROR: (%s:%d) mvOnuEponMacOnuEnableSet\n\r", __FILE_DESC__, __LINE__);

+   return(MV_ERROR);

+ }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponAsicQueueEnable

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function enables all queues for the specific mac Id

+**

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponAsicQueueEnable(MV_U32 macId)

+{

+  switch (macId)

+  {

+    case 0: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID0_QUEUES, 0x00FF, 0); break;

+    case 1: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID1_QUEUES, 0x00FF, 0); break;

+    case 2: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID2_QUEUES, 0x00FF, 0); break;

+    case 3: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID3_QUEUES, 0x00FF, 0); break;

+    case 4: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID4_QUEUES, 0x00FF, 0); break;

+    case 5: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID5_QUEUES, 0x00FF, 0); break;

+    case 6: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID6_QUEUES, 0x00FF, 0); break;

+    case 7: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID7_QUEUES, 0x00FF, 0); break;

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponAsicQueueDisable

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function disables all queues for the specific mac Id

+**               except queue 0

+**

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponAsicQueueDisable(MV_U32 macId)

+{

+  switch (macId)

+  {

+    case 0: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID0_QUEUES, 0xFE00, 0); break;

+    case 1: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID1_QUEUES, 0xFE00, 0); break;

+    case 2: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID2_QUEUES, 0xFE00, 0); break;

+    case 3: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID3_QUEUES, 0xFE00, 0); break;

+    case 4: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID4_QUEUES, 0xFE00, 0); break;

+    case 5: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID5_QUEUES, 0xFE00, 0); break;

+    case 6: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID6_QUEUES, 0xFE00, 0); break;

+    case 7: asicOntMiscRegWrite(mvAsicReg_GUNIT_LLID7_QUEUES, 0xFE00, 0); break;

+  }

+

+  return(MV_OK);

+}

+#endif  /* NOT USED */

+

+/*******************************************************************************

+**

+**  onuEponSwitchOn

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function execute onu switchOn init sequence

+**

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or MV_ERROR

+**

+*******************************************************************************/

+MV_STATUS onuEponSwitchOn(void)

+{

+  MV_STATUS rcode;

+

+  /* init onu RTOS resources */

+  rcode = onuEponRtosResourceInit();

+  if (rcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) onuPonRtosResourceInit\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  onuEponAppInit();

+

+  /* onu epon counters table */

+  onuEponPmInit();

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponOperate

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function execute onu operate init sequence

+**

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponOperate(void)

+{

+  MV_STATUS status;

+  MV_U32    interruptMask;

+

+  /* enable onu pon interrupt mask */

+  interruptMask = (ONU_EPON_INTERRUPTS);

+  interruptMask &= ~(ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK);

+  status = mvOnuEponMacPonInterruptMaskSet(interruptMask);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) Enable PON interrupt mask\n\r", __FILE_DESC__, __LINE__);

+    return(status);

+  }

+

+

+  /* Enable MAC */

+  status = mvOnuEponMacOnuRxEnableSet(ONU_RX_EN);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacOnuRxEnableSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* Turn ON TX Power */

+  status = onuPonTxPowerOn(MV_TRUE);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) onuPonTxPowerOn\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  status = mvOnuEponMacOnuTxEnableSet(ONU_TX_EN, 0);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacOnuTxEnableSet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);

+  if (status != MV_OK)

+  {

+	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+	  		 "ERROR: (%s:%d) mvOnuEponMacOnuIOEnable\n\r", __FILE_DESC__, __LINE__);

+	return(MV_ERROR);

+  }

+

+  /* start onu pon pon pm timer */

+  onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonPmTimerId));

+

+  /* start onu pon pon mpc timer */

+  onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonMpcpTimerId));

+

+  if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_HW_DBA_RPRT_TIMER)

+  {

+    /* start onu pon pon tx module timer */

+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHwRprtTxModTimerId));

+

+    /* Enable DBA Report message handling */

+	onuEponIsrTimerHwReportStateSet(MV_TRUE, /* Enable */

+									dbaRprtT0StateVal,

+									dbaRprtT0StateInterval,

+									dbaRprtT1StateVal,

+									dbaRprtT1StateInterval);

+

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function init ONU

+**

+**  PARAMETERS:  IOCTL Init data

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponInit(S_EponIoctlInit *ioctlInit)

+{

+  MV_STATUS status;

+

+  /*re-set DBA mode */

+  status = onuEponDbaModeInit(ONU_DBA_SW_RPRT_MODE);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) onuEponDbaModeInit\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* re-set DDM polarity */

+  status = mvOnuEponMacDdmTxPolaritySet(ONU_DEF_DDM_CFG_TX_EN_OR, ioctlInit->xvrPolarity);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuEponMacDdmTxPolaritySet\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  onuEponDbXvrPolaritySet(ioctlInit->xvrPolarity);

+  mvOnuPonMacBurstEnablePolarityInit(ioctlInit->xvrPolarity);

+

+#ifndef PON_FPGA

+  /* enable onu dying gasp interrupt mask */

+  status = mvOnuPonMacDgInterruptEn(ioctlInit->dgPolarity);

+  if (status != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) mvOnuPonMacDgInterruptEn\n", __FILE_DESC__, __LINE__);

+    return(status);

+  }

+#endif /* PON_FPGA */

+

+  return(MV_OK);

+}

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.h
new file mode 100755
index 0000000..56b8369
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuInit.h
@@ -0,0 +1,120 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuInit.h                                             **/

+/**                                                                          **/

+/**  DESCRIPTION : This file contains ONU EPON init sequence definitions     **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *      

+ *                                                                          

+ ******************************************************************************/

+#ifndef _ONU_EPON_INIT_H

+#define _ONU_EPON_INIT_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponSetup(void);

+MV_STATUS onuEponSwitchOn(void);

+MV_STATUS onuEponOperate(void);

+

+MV_STATUS onuEponAsicReInit(MV_U32 macId, MV_U32 silenceMode);

+MV_STATUS onuEponRtosResourceRelease(void);

+MV_STATUS onuEponInit(S_EponIoctlInit *ioctlInit);

+

+#if 0 /* NOT USED */

+MV_STATUS onuEponAsicQueueEnable(MV_U32 macId); 

+MV_STATUS onuEponAsicQueueDisable(MV_U32 macId); 

+#endif /* NOT USED */

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_EPON_INIT_H */

+

+  

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.c
new file mode 100755
index 0000000..733e8e8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.c
@@ -0,0 +1,1395 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************/
+/**                                                                          **/
+/**  MODULE      : ONU EPON                                                  **/
+/**                                                                          **/
+/**  FILE        : eponOnuIsr.c                                              **/
+/**                                                                          **/
+/**  DESCRIPTION : This file implements ONU EPON Interrupt handling          **/
+/**                                                                          **/
+/******************************************************************************
+ *                                                                            *
+ *  MODIFICATION HISTORY:                                                     *
+ *                                                                            *
+ *   26Jan10  oren_ben_hayun    created                                       *
+ * ========================================================================== *
+ *
+ ******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "eponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/epon/eponOnuIsr.c"
+
+#define MV_NO_XVR_RST (0xFF)
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+extern spinlock_t onuPonIrqLock;
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+MV_U32 onuEponCurrentInterrupt = 0;
+MV_U32 onuEponRxMacCtrlPackets = 0;
+MV_U32 onuEponTxMacByteAllowed = 0;
+MV_U32 recvGateFrameBase       = 0;
+MV_U32 recvDiscNotRegFrameBase = 0;
+MV_U32 sendCtrlRegReqFrameBase = 0;
+MV_U32 regRandomInitInd        = 0;
+MV_U32 regRandomCheckThreshold = 3/*10*/;
+MV_U32 regRandomMaskThreshold  = 0x1FF; /* 0-512 msec */
+MV_U32 regRandomResetState     = 0;     /* Off */
+
+MV_U32 isrTimestampEventCnt    = 0;
+MV_U32 isrTimestampEventMiss   = 0;
+MV_U32 isrInvalidRegState      = 0;
+
+MV_U32 isrP2pPreviousFecState  = 0;
+
+MV_BOOL eponMgmtForceTxDisable = MV_FALSE;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+MV_STATUS onuEponIsrXvrReset(void);
+void      onuEponIsrResetRandomStateMachine(void);
+
+/*******************************************************************************
+**
+**  onuEponIsrLowRoutine
+**
+*******************************************************************************/
+void onuEponIsrLowRoutine(MV_U32 *interruptEvent, MV_U32 *interruptStatus)
+{
+	MV_U32 interrupt;
+
+	mvOnuEponMacPonInterruptGet(&interrupt);
+	onuEponCurrentInterrupt &= 0xFFFF0000;
+	onuEponCurrentInterrupt |= interrupt;
+
+	*interruptEvent  = (onuEponCurrentInterrupt >> ONU_EPON_EVENT_SHIFT) & ONU_EPON_INTERRUPTS;
+	*interruptStatus =  onuEponCurrentInterrupt                          & ONU_EPON_INTERRUPTS;
+
+	mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE,
+		   "DEBUG: (%s:%d) Event(0x%08X) Status(0x%08X)\n",
+		   __FILE_DESC__, __LINE__, *interruptEvent, *interruptStatus);
+
+	onuEponCurrentInterrupt = 0;
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrRoutine
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements interrupt handler
+**
+**  PARAMETERS:  None, void* param
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None, void*
+**
+*******************************************************************************/
+void onuEponIsrRoutine(MV_U32 event, MV_U32 status)
+{
+	MV_BOOL state;
+	MV_U32  rxGenFecEn      = 0;
+	MV_U32  interruptEvent  = 0;
+	MV_U32  interruptStatus = 0;
+
+
+#ifdef MV_EPON_HW_INTERRUPT
+	onuEponIsrLowRoutine(&interruptEvent, &interruptStatus);
+#else
+	interruptEvent  = event;
+	interruptStatus = status;
+#endif /* MV_GPON_HW_INTERRUPT */
+
+	/* Interrupt Protect */
+	/* ================= */
+
+	if (interruptEvent & ONU_EPON_XVR_SD_MASK) {
+
+		state = (interruptStatus & ONU_EPON_XVR_SD_MASK) ? MV_FALSE : MV_TRUE;
+		if (state == MV_FALSE)
+			onuEponDbOnuSignalDetectSet(1); /* alarm is OFF */
+		else if (state == MV_TRUE)
+			onuEponDbOnuSignalDetectSet(0);/* alarm is ON */
+
+		onuEponPonMngIntrAlarmHandler(ONU_EPON_XVR_SD_MASK, state);
+
+		mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE,
+			   "DEBUG: (%s:%d) Link %s\n", __FILE_DESC__, __LINE__, (state == MV_FALSE) ? "On" : "Off");
+
+		if (state == MV_FALSE) { /* alarm is OFF */
+
+			onuEponDbOnuRxFecCfgGet(&rxGenFecEn);
+
+			if (rxGenFecEn != ONU_RX_PCS_FEC_DIS)		/* config PCS synchronization */
+				mvOnuEponMacPcsDelaySet(0x1058);	/*configuration - FEC enabled */
+#ifndef PON_FPGA
+			onuEponIsrXvrReset();
+#endif /* PON_FPGA */
+			mvPonPrint(PON_PRINT_DEBUG, PON_ISR_RAND_MODULE,
+				   "DEBUG: (%s:%d) ResetRandomStateMachine %s\n", __FILE_DESC__, __LINE__);
+			onuEponIsrResetRandomStateMachine();
+
+		} else if (state == MV_TRUE) { /* alarm is ON */
+
+			/* set EPON mode */
+			onuEponDbModeSet(E_EPON_IOCTL_STD_MODE);
+			/* config PCS synchronization configuration  - FEC disabled */
+			mvOnuEponMacPcsDelaySet(0x1C58);
+			/* clear Rx Ctrl message FIFO */
+			onuEponPonMngIntrRxCtrlFifoCleanup();
+			/* clear OAM SW FIFO - Tx */
+			onuEponOamFlushAllMsg();
+			/* start xvr reset timer */
+			onuEponIsrXvrResetStateSet(MV_TRUE);
+		}
+	}
+
+	if (interruptEvent & ONU_EPON_SERDES_SD_MASK) {
+		state = (interruptStatus & ONU_EPON_SERDES_SD_MASK) ? MV_FALSE : MV_TRUE;
+		onuEponPonMngIntrAlarmHandler(ONU_EPON_SERDES_SD_MASK, state);
+	}
+
+	if (interruptEvent & ONU_EPON_TIMESTAMP_DRIFT_MASK) {
+		state = (interruptStatus & ONU_EPON_TIMESTAMP_DRIFT_MASK) ? MV_TRUE : MV_FALSE;
+		onuEponPonMngIntrAlarmHandler(ONU_EPON_TIMESTAMP_DRIFT_MASK, state);
+	}
+
+	if (interruptEvent & ONU_EPON_DS_SYNC_OK_PCS_MASK) {
+		state = (interruptStatus & ONU_EPON_DS_SYNC_OK_PCS_MASK) ? MV_TRUE : MV_FALSE;
+
+		mvPonPrint(PON_PRINT_DEBUG, PON_ISR_INT_MODULE,
+			   "DEBUG: (%s:%d) PCS Sync %s\n", __FILE_DESC__, __LINE__, (state == MV_FALSE) ? "Off" : "On");
+
+		if (state == MV_TRUE)
+			onuEponDbOnuDsSyncOkPcsSet(1); /* set DS Sync OK PCS to ON */
+		else if (state == MV_FALSE)
+			onuEponDbOnuDsSyncOkPcsSet(0); /* set DS Sync OK PCS to OFF */
+	}
+
+	if (interruptEvent & ONU_EPON_REGISTERED_LLID_0_MASK) {
+		/* state = (interruptStatus & ONU_EPON_REGISTERED_LLID_0_MASK) ? MV_TRUE : MV_FALSE;
+		 onuEponPonMngIntrRegHandler(ONU_EPON_REGISTERED_LLID_0_MASK, state); */
+	}
+
+	/* Event is triggered for each change in the Status  */
+	/* Status == 0, means there is something in the FIFO */
+	/* Status == 1, means there is nothing in the FIFO   */
+	/* ================================================= */
+	if ((interruptEvent   & ONU_EPON_RX_CTRL_QUEUE_MASK) &&
+	    ((interruptStatus & ONU_EPON_RX_CTRL_QUEUE_MASK) == 0))
+		onuEponPonMngIntrMessageHandler(ONU_EPON_RX_CTRL_MSG);
+
+	if ((interruptEvent   & ONU_EPON_RX_RPRT_QUEUE_MASK) &&
+	    ((interruptStatus & ONU_EPON_RX_RPRT_QUEUE_MASK) == 0))
+		onuEponPonMngIntrMessageHandler(ONU_EPON_RX_RPRT_MSG);
+
+	if (interruptEvent & ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK) {
+		/* Set onu DBA Report interrupt */
+		onuEponPonMngTxCtrlMessageHandler();
+		onuEponDbaSwRprtMacTimerCfg(onuEponDbOnuSwRprtMacTimerIntervalGet());
+		isrTimestampEventCnt++;
+	}
+}
+
+#ifndef PON_FPGA
+/*******************************************************************************
+**
+**  onuGponDgIsrRoutine
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements Dying Gasp
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponDgIsrRoutine(void)
+{
+  onuEponPonMngIntrDgHandler();
+}
+#endif /* PON_FPGA */
+
+/*******************************************************************************
+**
+**  onuEponIsrResetRandomStateMachine
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clear Random state machine
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponIsrResetRandomStateMachine(void)
+{
+  /* enable tx */
+  if (onuEponForceTxDownStateGet(0) != MV_TRUE)
+    mvOnuEponMacOnuTxEnableSet(ONU_TX_EN, 0);
+
+  /* restore MPCP timer interval */
+  onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonMpcpTimerId), 0, ONU_PON_TIMER_MPCP_INTERVAL, 1);
+
+  /* clear all required counters for handling random delay for ONU transmission */
+  recvGateFrameBase       = 0;
+  recvDiscNotRegFrameBase = 0;
+  sendCtrlRegReqFrameBase = 0;
+  regRandomInitInd        = 0;
+  regRandomResetState     = 0;
+  onuEponPmRandomReset();
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerMpcpHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function validate mpcp frames arrival rate
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponIsrTimerMpcpHndl(unsigned long data)
+{
+  MV_U32 currentCtrlPackets      = 0;
+  MV_U32 currentTxByteAllowed    = 0;
+  MV_U32 recvGateFrame           = 0;
+  MV_U32 recvDiscoverNotRegFrame = 0;
+  MV_U32 sendCtrlRegReqFrame     = 0;
+  MV_U32 randomTime              = 0;
+  MV_U32 randomShift             = 0;
+  MV_U32 randomRange             = 0;
+  MV_U32 state                   = 0;
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonMpcpTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  if (regRandomResetState != 0)
+  {
+	  mvPonPrint(PON_PRINT_DEBUG, PON_ISR_RAND_MODULE,
+				 "DEBUG: (%s:%d) Reset Random State Machine\n", __FILE_DESC__, __LINE__);
+	  onuEponIsrResetRandomStateMachine();
+  }
+  else
+  {
+	if (onuEponDbOnuStateGet(0) == ONU_EPON_03_OPERATION)
+	{
+	  /* = Rx Ctrl Packet Check = */
+	  /* ======================== */
+	  currentCtrlPackets   = onuEponPmCtrlCntGet(0);
+	  currentTxByteAllowed = onuEponPmTxByteCntGet(0);
+
+	  if ((currentTxByteAllowed == onuEponTxMacByteAllowed) ||
+	  	  (currentCtrlPackets   == onuEponRxMacCtrlPackets))
+	  {
+	    /* Holdover Active */
+	    if (onuEponDbOnuHoldoverStateGet() != ONU_HOLDOVER_NOT_ACTIVE)
+	    {
+	  	  if (onuEponDbOnuHoldoverExecGet() != ONU_HOLDOVER_ACTIVE)
+	  	  {
+	  	    /* start onu epon pon holdover timer */
+	  	    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHoldoverTimerId));
+	  	    onuEponDbOnuHoldoverExecSet(ONU_HOLDOVER_ACTIVE);
+
+	  	    mvPonPrint(PON_PRINT_DEBUG, PON_ISR_STATE_MODULE,
+	  	  			   "DEBUG: (%s:%d) Holdover Timer Start(Tmr)\n", __FILE_DESC__, __LINE__);
+	  	  }
+	    }
+	    /* Holdover Not Active */
+	    else
+	    {
+	  	  onuEponPonMngAlarmHandlerExecute(ALL_MAC_INDICATION);
+	    }
+	  }
+
+	  onuEponRxMacCtrlPackets = currentCtrlPackets;
+	  onuEponTxMacByteAllowed = currentTxByteAllowed;
+
+	  /* clear all required counters for handling random delay for ONU transmission */
+	  onuEponIsrResetRandomStateMachine();
+
+	  isrInvalidRegState = 0;
+	}
+	else /* (onuEponDbOnuStateGet(0) != ONU_EPON_03_OPERATION) */
+	{
+	  mvPonPrint(PON_PRINT_DEBUG, PON_ISR_STATE_MODULE,
+	  		     "DEBUG: (%s:%d) MPCP state not registered\n", __FILE_DESC__, __LINE__);
+
+	  /* handling of invalid ONU register state */
+	  /* ====================================== */
+	  mvOnuEponMacOnuStateGet(&state, 0);
+	  if (state != 0)
+	  {
+	    isrInvalidRegState++;
+	    if (isrInvalidRegState >= 2)
+	    {
+	      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_STATE_MODULE,
+	      		     "DEBUG: (%s:%d) Force ONU Re-registration\n", __FILE_DESC__, __LINE__);
+
+	      mvOnuEponMacOnuStateSet(ONU_EPON_NOT_REGISTERD, 0);
+	      isrInvalidRegState = 0;
+	    }
+	  }
+
+	  /* handling of random delay for ONU transmission to disable transmission collisions */
+	  /* ================================================================================ */
+	  /* get counters for random transmission check */
+	  onuEponPmRandomThresholdCheck(&recvGateFrame,
+								    &recvDiscoverNotRegFrame,
+								    &sendCtrlRegReqFrame);
+
+	  mvPonPrint(PON_PRINT_DEBUG, PON_ISR_RAND_MODULE,
+				 "regRandomInitInd (%d)\n", regRandomInitInd);
+
+	  if (regRandomInitInd == 0)
+	  {
+	    /* save current counter state for future comparison */
+	    recvGateFrameBase       = recvGateFrame;
+	    recvDiscNotRegFrameBase = recvDiscoverNotRegFrame;
+	    sendCtrlRegReqFrameBase = sendCtrlRegReqFrame;
+
+	    regRandomInitInd = 1;
+
+	    mvPonPrint(PON_PRINT_DEBUG, PON_ISR_RAND_MODULE,
+	  		       "DEBUG[0]: B-gate(%d)disc(%d)regReq(%d), regRandomInitInd(%d)\n",
+	  		       recvGateFrameBase, recvDiscNotRegFrameBase, sendCtrlRegReqFrameBase, regRandomInitInd);
+	  }
+
+	  mvPonPrint(PON_PRINT_DEBUG, PON_ISR_RAND_MODULE,
+				 "DEBUG[1]: C-gate(%d)disc(%d)regReq(%d)\n"
+				 "DEBUG[1]: B-gate(%d)disc(%d)regReq(%d), regRandomInitInd(%d), regRandomResetState(%d)\n",
+				 recvGateFrame, recvDiscoverNotRegFrame, sendCtrlRegReqFrame,
+				 recvGateFrameBase, recvDiscNotRegFrameBase, sendCtrlRegReqFrameBase, regRandomInitInd, regRandomResetState);
+
+
+	  /* start random timer section */
+	  if (((recvGateFrame           - recvGateFrameBase)       > regRandomCheckThreshold) &&
+	   	  ((recvDiscoverNotRegFrame - recvDiscNotRegFrameBase) > regRandomCheckThreshold) &&
+	  	  ((sendCtrlRegReqFrame     - sendCtrlRegReqFrameBase) > regRandomCheckThreshold))
+	  {
+	    /* calc random value */
+	    onuEponPmRandomGet(&randomTime);
+	    randomShift = ((randomTime >> 16) & 0xF);
+	    randomRange = ((randomTime >> randomShift) & regRandomMaskThreshold);
+
+	    mvPonPrint(PON_PRINT_DEBUG, PON_ISR_RAND_MODULE,
+	  			   "DEBUG[2]: C-gate(%d)disc(%d)regReq(%d)\n"
+	  			   "DEBUG[2]: B-gate(%d)disc(%d)regReq(%d), thres(%d)randtime(%d)\n",
+	  			   recvGateFrame, recvDiscoverNotRegFrame, sendCtrlRegReqFrame,
+	  			   recvGateFrameBase, recvDiscNotRegFrameBase, sendCtrlRegReqFrameBase, regRandomCheckThreshold, randomRange);
+
+	    /* wait random time */
+	    onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonMpcpTimerId), 0, randomRange, 0);
+
+	    regRandomResetState = 1;
+
+	    /* disable tx */
+	    mvOnuEponMacOnuTxEnableSet(ONU_TX_DIS, 0);
+	  }
+	}
+  }
+
+  if ((onuPonResourceTbl_s.onuPonMpcpTimerId.onuPonTimerPeriodic) != 0)
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonMpcpTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerMpcpStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable epon mpcp timer
+**
+**  PARAMETERS:  MV_BOOL mode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void onuEponIsrTimerMpcpStateSet(MV_BOOL mode)
+{
+  if (mode == MV_TRUE)
+  {
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonMpcpTimerId));
+  }
+  else
+  {
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonMpcpTimerId));
+  }
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerMpcpIntervalSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure epon mpcp timer interval
+**
+**  PARAMETERS:  MV_BOOL interval
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void onuEponIsrTimerMpcpIntervalSet(MV_U32 interval)
+{
+  onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonMpcpTimerId), 0, interval, 1);
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerMpcpRandomResetSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure epon mpcp timer random reset params
+**
+**  PARAMETERS:  MV_U32 checkThreshold
+**               MV_U32 maskThreshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void onuEponIsrTimerMpcpRandomResetSet(MV_U32 checkThreshold, MV_U32 maskThreshold)
+{
+  regRandomCheckThreshold = checkThreshold;
+  regRandomMaskThreshold  = maskThreshold;
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerHwReportHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function transmit report frame
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponIsrTimerHwReportHndl(unsigned long data)
+{
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonHwRprtTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  onuEponPonMngHwRprtMessageHandler();
+
+  if ((onuPonResourceTbl_s.onuPonHwRprtTimerId.onuPonTimerPeriodic) != 0)
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerHwReportStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable epon HW report message timer
+**
+**  PARAMETERS:  MV_BOOL mode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void onuEponIsrTimerHwReportStateSet(MV_U32 enable, MV_U32 t0_val, MV_U32 t0_time,
+								     MV_U32 t1_val, MV_U32 t1_time)
+{
+  if (enable == MV_TRUE)
+  {
+	onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+	onuEponPonMngTimerHwRprtCfg(t0_val, t0_time, t1_val, t1_time);
+	onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+  }
+  else
+  {
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+	onuEponPonMngTimerHwRprtCfg(t0_val, t0_time, t1_val, t1_time);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerHoldoverHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle holdover for epon
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponIsrTimerHoldoverHndl(unsigned long data)
+{
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonHoldoverTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  mvPonPrint(PON_PRINT_DEBUG, PON_ISR_STATE_MODULE,
+			 "DEBUG: (%s:%d) Holdover Timer Expire\n", __FILE_DESC__, __LINE__);
+  onuEponPonMngAlarmHandlerExecute(ALL_MAC_INDICATION);
+
+  if ((onuPonResourceTbl_s.onuPonHoldoverTimerId.onuPonTimerPeriodic) != 0)
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHoldoverTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerHoldoverIntervalSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure epon mpcp timer interval
+**
+**  PARAMETERS:  MV_BOOL interval
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void onuEponIsrTimerHoldoverIntervalSet(MV_U32 interval, MV_U32 state)
+{
+  onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonHoldoverTimerId), 0, interval, state);
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerEventMissHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function validate interrupt event miss
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponIsrTimerEventMissHndl(unsigned long data)
+{
+  MV_U32 currHwTime;
+  MV_U32 currHwThreshold;
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonIsrMissTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  if (isrTimestampEventCnt != 0)
+  {
+	isrTimestampEventCnt = 0;
+  }
+  else
+  {
+	mvOnuEponMacGenLocalTimeStampGet(&currHwTime);
+    mvOnuEponMacGenTimeStampForIntrGet(&currHwThreshold);
+
+	if (isrTimestampEventMiss > 0)
+	{
+		mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MISS_MODULE,
+				   "DEBUG: (%s:%d) Event miss(%d) Currtime(%x) CurrThreshold(%x)\n",
+				   __FILE_DESC__, __LINE__, isrTimestampEventMiss, currHwTime, currHwThreshold);
+
+		onuEponOamHandleMsg();
+		onuEponDbaSwRprtMacTimerCfg(62500);
+		isrTimestampEventMiss = 0;
+	}
+
+	isrTimestampEventMiss++;
+  }
+
+  if ((onuPonResourceTbl_s.onuPonIsrMissTimerId.onuPonTimerPeriodic) != 0)
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonIsrMissTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrTimerEventMissStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable epon event miss timer
+**
+**  PARAMETERS:  MV_BOOL mode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void onuEponIsrTimerEventMissStateSet(MV_BOOL mode)
+{
+  if (mode == MV_TRUE)
+  {
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonIsrMissTimerId));
+  }
+  else
+  {
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonIsrMissTimerId));
+  }
+}
+
+/*******************************************************************************
+**
+**  onuEponDbaSwRprtMacTimerCfg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure abd trigger timestamp interupt
+**
+**  PARAMETERS:  MV_U32 interval - 16 nanaosec units
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void onuEponDbaSwRprtMacTimerCfg(MV_U32 interval)
+{
+  MV_U32 currentTimestamp;
+  MV_U32 maxHwTimer = 0xFFFFFFFF;
+
+  mvOnuEponMacGenLocalTimeStampGet(&currentTimestamp);
+
+  if ((maxHwTimer - currentTimestamp) < interval)
+  {
+	mvOnuEponMacGenTimeStampForIntrSet(interval);
+  }
+  else
+  {
+	mvOnuEponMacGenTimeStampForIntrSet(currentTimestamp + interval);
+  }
+}
+
+#ifndef PON_FPGA
+/*******************************************************************************
+**
+**  onuEponIsrXvrResetTimerHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called by the EPON Interrupt handler to execute
+**               XVR reset sequence in case of a problem with XVR signal detect
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponIsrXvrResetTimerHndl(unsigned long data)
+{
+  MV_STATUS status;
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonIsrXvrRstTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  status = onuEponIsrXvrReset();
+  if (status != MV_NO_XVR_RST)
+  {
+	if ((onuPonResourceTbl_s.onuPonIsrXvrRstTimerId.onuPonTimerPeriodic) != 0)
+	  onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId));
+  }
+  else
+  {
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId));
+  }
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrXvrReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reset xvr
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuEponIsrXvrReset(void)
+{
+  MV_STATUS status;
+  MV_U32    onuState;
+  MV_U32    initDone;
+
+  onuState = onuEponDbOnuStateGet(0);
+  if (onuState == ONU_EPON_02_REGISTER_PENDING)
+  {
+    status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x1, 0);
+    if (status != MV_OK)
+      return(status);
+
+    do
+    {
+      status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE, &initDone, 0);
+      if (status != MV_OK)
+        return(status);
+
+    } while (initDone == 0);
+
+    status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x0, 0);
+    if (status != MV_OK)
+      return(status);
+  }
+  else
+  {
+	return(MV_NO_XVR_RST);
+  }
+
+  return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponIsrXvrResetStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable onu xvr reset timer
+**
+**  PARAMETERS:  MV_BOOL mode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void onuEponIsrXvrResetStateSet(MV_BOOL mode)
+{
+  if (mode == MV_TRUE)
+  {
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId));
+  }
+  else
+  {
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId));
+  }
+}
+#endif /* PON_FPGA */
+
+/*******************************************************************************
+**
+**  mvP2PStart
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function starts ONU P2P configuration
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvP2PStart(void)
+{
+#ifdef PON_Z2
+    MV_STATUS status = MV_OK;
+    MV_U32    pcsConfig;
+    MV_U32    overHead;
+    MV_U32    ignoreLlidCrcError;
+    MV_U32    ignoreFcsError;
+    MV_U32    ignoreGmiiError;
+    MV_U32    ignoreLengthError;
+    MV_U32    forwardAllLlid;
+    MV_U32    forwardBc0FFF;
+    MV_U32    forwardBc1FFF;
+    MV_U32    forwardBc1xxx;
+    MV_U32    dropBc1nnn;
+    MV_U32    gpioGroup, gpioMask;
+	MV_U32    interruptMask;
+	MV_U32    polarity;
+
+    LINKSTATUSFUNC linkStatusCallback;
+
+	if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_SW_DBA_RPRT_TIMER)
+	{
+	  /* Stop SW DBA event miss timer */
+	  onuEponIsrTimerEventMissStateSet(MV_FALSE);
+
+	  /* Clear onu DBA Report interrupt */
+	  status |= mvOnuEponMacPonInterruptMaskGet(&interruptMask);
+	  interruptMask &= ~(ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK);
+	  status |= mvOnuEponMacPonInterruptMaskSet(interruptMask);
+	  if (status != MV_OK)
+		return(status);
+	}
+	else
+	{
+	  /* Clear onu DBA Report Timer */
+	  onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+	}
+
+	/* stop xvr reset timer */
+	onuEponIsrXvrResetStateSet(MV_FALSE);
+
+    /* Save EPON PCS configuration */
+    status = mvOnuEponMacPcsConfigGet(&pcsConfig);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacPcsConfigGet\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    onuEponDbPcsCfgSet(pcsConfig);
+
+    /* Set P2P PCS */
+    status = asicOntGlbRegWrite(mvAsicReg_P2P_PCS_CONFIGURATION, ONU_P2P_PCS_TX_RX_NEW, 0);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) asicOntGlbRegWrite\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    /* Set TXM configuration mode */
+    status = asicOntGlbRegWrite(mvAsicReg_P2P_TXM_CFG_MODE, ONU_DEF_TXM_CFG_MODE_GE, 0);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) asicOntGlbRegWrite\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    /* Set configuration mode in the GEN ONT register */
+    status = asicOntGlbRegWrite(mvAsicReg_P2P_GEN_ONT_MODE, ONU_DEF_TXM_CFG_MODE_GE, 0);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) asicOntGlbRegWrite\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    /* Save TXM overhead value */
+    status = mvOnuEponMacTxmOverheadGet(&overHead);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacTxmOverheadGet\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    onuEponDbOverheadSet(overHead);
+
+    mvOnuEponMacTxmOverheadSet(ONU_DEF_TXM_CFG_P2P_OVERHEAD);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacTxmOverheadSet\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    /* Save current RXP packet filter */
+    mvOnuEponMacRxpPacketFilterGet(&ignoreLlidCrcError,
+                                   &ignoreFcsError,
+                                   &ignoreGmiiError,
+                                   &ignoreLengthError,
+                                   &forwardAllLlid,
+                                   &forwardBc0FFF,
+                                   &forwardBc1FFF,
+                                   &forwardBc1xxx,
+                                   &dropBc1nnn);
+
+    onuEponDbPktFilterPacketSet(forwardAllLlid, forwardBc1xxx, forwardBc1FFF, forwardBc0FFF, dropBc1nnn);
+    onuEponDbPktFilterErrorSet(ignoreLengthError, ignoreGmiiError, ignoreFcsError, ignoreLlidCrcError);
+
+    /* Set P2P RXP packet filter */
+    status = mvOnuEponMacRxpPacketFilterSet(ONU_FORWARD_LLID_CRC_ERR_PKT_IGNORE,
+                                            ONU_FORWARD_LLID_FCS_ERR_PKT,
+                                            ONU_FORWARD_LLID_GMII_ERR_PKT,
+                                            ONU_FORWARD_LLID_LEN_ERR_PKT,
+                                            ONU_FORWARD_LLID_ALL_PKT_FILTER,
+                                            ONU_FORWARD_LLID_7FFF_MODE_0_PKT,
+                                            ONU_FORWARD_LLID_7FFF_MODE_1_PKT,
+                                            ONU_FORWARD_LLID_XXXX_MODE_1_PKT,
+                                            ONU_DROP_LLID_NNNN_MODE_1_PKT);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacRxpPacketFilterSet\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+   /* MC ASIC     */
+   /* =========== */
+   if (MV_6601_DEV_ID == mvCtrlModelGet())
+	{
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+	  if (status != MV_OK)
+	  {
+	    mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			 "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+	    return(MV_ERROR);
+	  }
+
+	  /* PHY control register - force enable */
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_FORCE, 1, 0);
+	  if (status != MV_OK)
+	  {
+		mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			"ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	  }
+
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_VALUE, 1, 0);
+	  if (status != MV_OK)
+	  {
+		mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			"ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	  }
+	}
+	/* KW2 ASIC Rev Z2 */
+	/* =============== */
+	else if (mvCtrlRevGet() == ONU_ASIC_REV_Z2)
+	{
+	  /* PHY control register - output status*/
+	  PON_GPIO_GET(BOARD_GPP_PON_XVR_TX, gpioGroup, gpioMask);
+	  if (gpioMask != PON_GPIO_NOT_USED)
+	  {
+	  	status = mvGppTypeSet(gpioGroup, gpioMask, ~gpioMask/*output*/);
+	  	if (status != MV_OK)
+	  	{
+	  	  mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  			   "ERROR: (%s:%d) mvGppTypeSet\n\r", __FILE_DESC__, __LINE__);
+	  	  return(MV_ERROR);
+	  	}
+
+	  	status = mvGppValueSet(gpioGroup, gpioMask, gpioMask /*enable*/);
+	  	if (status != MV_OK)
+	  	{
+	  	  mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  			   "ERROR: (%s:%d) mvGppTypeSet\n\r", __FILE_DESC__, __LINE__);
+	  	  return(MV_ERROR);
+	  	}
+	  }
+
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_INPUT, 0);
+	  if (status != MV_OK)
+	  {
+	    mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  		   "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+	    return(MV_ERROR);
+	  }
+	}
+
+	/* KW2 ASIC Rev A0 */
+	/* =============== */
+	else if (mvCtrlRevGet() == ONU_ASIC_REV_A0)
+	{
+      status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+	  if (status != MV_OK)
+	  {
+	    mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  		 "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+	    return(MV_ERROR);
+	  }
+
+	  /* PHY control register - force enable */
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_EN, 1, 0);
+	  if (status != MV_OK)
+	  {
+		mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			       "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	  }
+
+	  polarity = onuEponDbXvrPolarityGet();
+
+	  /* XVR polarity */
+	  /* XVR polarity == 0, Active High, transmit 1 to the line  */
+	  /* XVR polarity == 1, Active Low, transmit 0 to the line  */
+
+	  /* P2P mode */
+	  /* Force Value == 0, transmit 0 to the line  */
+	  /* Force Value == 1, transmit 1 to the line  */
+
+	  /* Setting P2P should be reversed from XVR polarity */
+	  /* XVR polarity == 0, Active High, write 1 for Force Value */
+	  /* XVR polarity == 1, Active Low, write 0 for Force Value */
+
+	  /* PHY control register - force enable value - according to polarity */
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL, ~polarity, 0);
+	  if (status != MV_OK)
+	  {
+		mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			       "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	  }
+	}
+
+	/* Read current FEC configuration */
+    status = mvOnuEponMacRxpEncConfigGet(&isrP2pPreviousFecState);
+	if (status != MV_OK)
+	{
+	  mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				 "ERROR: (%s:%d) mvOnuEponMacRxpEncConfigGet\n\r", __FILE_DESC__, __LINE__);
+	  return(MV_ERROR);
+	}
+
+	/* Reset FEC configuration */
+    status = mvOnuEponMacRxpEncConfigSet(0);
+	if (status != MV_OK)
+	{
+	  mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				 "ERROR: (%s:%d) mvOnuEponMacRxpEncConfigSet\n\r", __FILE_DESC__, __LINE__);
+	  return(MV_ERROR);
+	}
+
+    onuEponDbModeSet(E_EPON_IOCTL_P2P_MODE);
+
+    /* Call link status callback function */
+    linkStatusCallback = onuEponDbLinkStatusCallbackGet();
+    if (linkStatusCallback != NULL)
+    {
+      linkStatusCallback(MV_TRUE);
+    }
+#endif
+
+    return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvP2PStop
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function stops ONU P2P configuration
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvP2PStop(void)
+{
+#ifdef PON_Z2
+    MV_STATUS status;
+    MV_U32    pcsConfig;
+    MV_U32    overHead;
+    MV_U32    ignoreLlidCrcError;
+    MV_U32    ignoreFcsError;
+    MV_U32    ignoreGmiiError;
+    MV_U32    ignoreLengthError;
+    MV_U32    forwardAllLlid;
+    MV_U32    forwardBc0FFF;
+    MV_U32    forwardBc1FFF;
+    MV_U32    forwardBc1xxx;
+    MV_U32    dropBc1nnn;
+    MV_U32    gpioGroup, gpioMask;
+	MV_U32    interruptMask;
+
+    /* Set EPON PCS */
+    pcsConfig = onuEponDbPcsCfgGet();
+    status = mvOnuEponMacPcsConfigSet(pcsConfig);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacPcsConfigSet\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    /* Set TXM configuration mode */
+    status = asicOntGlbRegWrite(mvAsicReg_P2P_TXM_CFG_MODE, ONU_DEF_TXM_CFG_MODE_EPON, 0);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) asicOntGlbRegWrite\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    /* Set configuration mode in the GEN ONT register */
+    status = asicOntGlbRegWrite(mvAsicReg_P2P_GEN_ONT_MODE, ONU_DEF_TXM_CFG_MODE_EPON, 0);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) asicOntGlbRegWrite\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    overHead = onuEponDbOverheadGet();
+    status = mvOnuEponMacTxmOverheadSet(overHead);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacTxmOverheadSet\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+    /* Set EPON RXP packet filter */
+    onuEponDbPktFilterPacketGet(&forwardAllLlid, &forwardBc1xxx, &forwardBc1FFF, &forwardBc0FFF, &dropBc1nnn);
+    onuEponDbPktFilterErrorGet(&ignoreLengthError, &ignoreGmiiError, &ignoreFcsError, &ignoreLlidCrcError);
+
+    status = mvOnuEponMacRxpPacketFilterSet(ignoreLlidCrcError,
+                                            ignoreFcsError,
+                                            ignoreGmiiError,
+                                            ignoreLengthError,
+                                            forwardAllLlid,
+                                            forwardBc0FFF,
+                                            forwardBc1FFF,
+                                            forwardBc1xxx,
+                                            dropBc1nnn);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacRxpPacketFilterSet\n\r", __FILE_DESC__, __LINE__);
+      return(MV_ERROR);
+    }
+
+   /* MC ASIC     */
+   /* =========== */
+   if (MV_6601_DEV_ID == mvCtrlModelGet())
+   {
+	  /* PHY control register - output status set */
+	   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+	   if (status != MV_OK)
+	   {
+	     mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				 "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+	     return(MV_ERROR);
+	   }
+
+	   /* PHY control register - force disable */
+	   status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_FORCE, 0, 0);
+	   if (status != MV_OK)
+	   {
+		 mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			 "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+		 return(MV_ERROR);
+	   }
+   }
+	/* KW2 ASIC Rev Z2 */
+	/* =============== */
+	else if (mvCtrlRevGet() == ONU_ASIC_REV_Z2)
+	{
+	  PON_GPIO_GET(BOARD_GPP_PON_XVR_TX, gpioGroup, gpioMask);
+	  if (gpioMask != PON_GPIO_NOT_USED)
+	  {
+	  	status = mvGppTypeSet(gpioGroup, gpioMask, ~gpioMask/*output*/);
+	  	if (status != MV_OK)
+	  	{
+	  	  mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  			     "ERROR: (%s:%d) mvGppTypeSet\n\r", __FILE_DESC__, __LINE__);
+	  	  return(MV_ERROR);
+	  	}
+
+	  	status = mvGppValueSet(gpioGroup, gpioMask, ~gpioMask/*disable*/);
+	  	if (status != MV_OK)
+	  	{
+	  	  mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  			     "ERROR: (%s:%d) mvGppValueSet\n\r", __FILE_DESC__, __LINE__);
+	  	  return(MV_ERROR);
+	  	}
+
+	  	status = mvGppTypeSet(gpioGroup, gpioMask, gpioMask/*input*/);
+	  	if (status != MV_OK)
+	  	{
+	  	  mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  			     "ERROR: (%s:%d) mvGppTypeSet\n\r", __FILE_DESC__, __LINE__);
+	  	  return(MV_ERROR);
+	  	}
+	  }
+
+	  /* PHY control register - output status set */
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+	  if (status != MV_OK)
+      {
+	    mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  		       "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+	    return(MV_ERROR);
+	  }
+	}
+	/* KW2 ASIC Rev A0 */
+	/* =============== */
+	else if (mvCtrlRevGet() == ONU_ASIC_REV_A0)
+	{
+	  /* PHY control register - output status set */
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+	  if (status != MV_OK)
+	  {
+	    mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  		        "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+	    return(MV_ERROR);
+	  }
+
+	  /* PHY control register - force disable */
+	  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_EN, 0, 0);
+	  if (status != MV_OK)
+	  {
+		mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			       "ERROR: (%s:%d) asicOntMiscRegWrite\n\r", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	  }
+	}
+
+    onuEponDbModeSet(E_EPON_IOCTL_STD_MODE);
+
+
+	if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_SW_DBA_RPRT_TIMER)
+	{
+	  /* Set onu DBA Report interrupt */
+	  status |= mvOnuEponMacPonInterruptMaskGet(&interruptMask);
+	  interruptMask |= (ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK);
+	  status |= mvOnuEponMacPonInterruptMaskSet(interruptMask);
+	  if (status != MV_OK)
+		return(status);
+
+	  onuEponDbaSwRprtMacTimerCfg(onuEponDbOnuSwRprtMacTimerIntervalGet());
+
+      /* Start SW DBA event miss timer */
+	  onuEponIsrTimerEventMissStateSet(MV_TRUE);
+    }
+	else
+	{
+	  onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+	}
+
+	if (isrP2pPreviousFecState & 0x1)
+	{
+	  /* Set FEC configuration */
+	  status = mvOnuEponMacRxpEncConfigSet(isrP2pPreviousFecState);
+	  if (status != MV_OK)
+	  {
+	    mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+	  			 "ERROR: (%s:%d) mvOnuEponMacRxpEncConfigSet\n\r", __FILE_DESC__, __LINE__);
+	    return(MV_ERROR);
+	  }
+	}
+
+	/* start xvr reset timer */
+	onuEponIsrXvrResetStateSet(MV_TRUE);
+#endif
+
+    return(MV_OK);
+}
+
+void onuEponForceTxDownStateSet(MV_U32 txEnable, MV_U32 macId)
+{
+	if (txEnable == 0)
+		eponMgmtForceTxDisable = MV_TRUE;
+	else
+		eponMgmtForceTxDisable = MV_FALSE;
+}
+
+MV_BOOL onuEponForceTxDownStateGet(MV_U32 macId)
+{
+	return(eponMgmtForceTxDisable);
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.h
new file mode 100755
index 0000000..c711a4f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuIsr.h
@@ -0,0 +1,166 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************/
+/**                                                                          **/
+/**  MODULE      : ONU GPON                                                  **/
+/**                                                                          **/
+/**  FILE        : eponOnuIsr.h                                              **/
+/**                                                                          **/
+/**  DESCRIPTION : This file contains ONU EPON Interrupt implementation      **/
+/**                                                                          **/
+/******************************************************************************
+ *                                                                            *
+ *  MODIFICATION HISTORY:                                                     *
+ *                                                                            *
+ *   26Jan10  oren_ben_hayun    created                                       *
+ * ========================================================================== *
+ *
+ ******************************************************************************/
+#ifndef _ONU_EPON_ISR_H
+#define _ONU_EPON_ISR_H
+
+/* Include Files
+------------------------------------------------------------------------------*/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define ONU_EPON_REGISTERED_LLID_0_MASK     (0x0001)
+#define ONU_EPON_REGISTERED_LLID_0_7_MASK   (0x0002)
+#define ONU_EPON_TIMESTAMP_DRIFT_MASK       (0x0004)
+#define ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK (0x0008)
+#define ONU_EPON_RX_CTRL_QUEUE_MASK         (0x0010)
+#define ONU_EPON_RX_RPRT_QUEUE_MASK         (0x0020)
+#define ONU_EPON_DS_SYNC_OK_PCS_MASK        (0x0080)
+#define ONU_EPON_XVR_SD_MASK                (0x0100)
+#define ONU_EPON_SERDES_SD_MASK             (0x0200)
+
+#define ONU_EPON_EVENT_SHIFT                (16)
+
+#ifdef PON_Z1
+
+#define ONU_EPON_INTERRUPTS                 (ONU_EPON_RX_CTRL_QUEUE_MASK | \
+                                             ONU_EPON_XVR_SD_MASK)
+
+#else /* PON_Z2 */
+
+#define ONU_EPON_INTERRUPTS                 (ONU_EPON_RX_CTRL_QUEUE_MASK  | \
+                                             ONU_EPON_XVR_SD_MASK         | \
+                                             ONU_EPON_DS_SYNC_OK_PCS_MASK | \
+                                             ONU_EPON_REGISTERED_LLID_0_MASK | \
+                                             ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK)
+#endif /* PON_Z2 */
+
+/* Alarms Mask */
+#define ONU_EPON_ALARM_MASK                 (ONU_EPON_SERDES_SD_MASK | \
+                                             ONU_EPON_XVR_SD_MASK    | \
+                                             ONU_EPON_TIMESTAMP_DRIFT_MASK)
+/* Message Types */
+#define ONU_EPON_RX_CTRL_MSG                (1)
+#define ONU_EPON_RX_RPRT_MSG                (2)
+
+/* DBA Report Timer Types */
+#define ONU_EPON_SW_DBA_RPRT_TIMER          (0)
+#define ONU_EPON_HW_DBA_RPRT_TIMER          (1)
+
+
+/* Enums
+------------------------------------------------------------------------------*/
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+void onuEponIsrLowRoutine(MV_U32 *interruptEvent, MV_U32 *interruptStatus);
+void onuEponIsrRoutine(MV_U32 interruptEvent, MV_U32 interruptStatus);
+#ifndef PON_FPGA
+void onuEponDgIsrRoutine(void);
+#endif /* PON_FPGA */
+void onuEponIsrTimerMpcpHndl(unsigned long data);
+void onuEponIsrTimerMpcpStateSet(MV_BOOL mode);
+void onuEponIsrTimerMpcpIntervalSet(MV_U32 interval);
+void onuEponIsrTimerMpcpRandomResetSet(MV_U32 checkThreshold, MV_U32 maskThreshold);
+void onuEponIsrTimerHwReportHndl(unsigned long data);
+void onuEponIsrTimerHwReportStateSet(MV_U32 enable, MV_U32 t0_val, MV_U32 t0_time, MV_U32 t1_val, MV_U32 t1_time);
+void onuEponIsrTimerHoldoverHndl(unsigned long data);
+void onuEponIsrTimerHoldoverIntervalSet(MV_U32 interval, MV_U32 state);
+void onuEponDbaSwRprtMacTimerCfg(MV_U32 interval);
+void onuEponIsrTimerEventMissHndl(unsigned long data);
+void onuEponIsrTimerEventMissStateSet(MV_BOOL mode);
+void onuEponIsrXvrResetTimerHndl(unsigned long data);
+void onuEponIsrXvrResetStateSet(MV_BOOL mode);
+void onuEponForceTxDownStateSet(MV_U32 txEnable, MV_U32 macId);
+MV_BOOL onuEponForceTxDownStateGet(MV_U32 macId);
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _ONU_EPON_ISR_H */
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.c
new file mode 100755
index 0000000..c889c69
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.c
@@ -0,0 +1,3107 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************/
+/**                                                                          **/
+/**  MODULE      : ONU EPON                                                  **/
+/**                                                                          **/
+/**  FILE        : eponOnuMngr.c                                             **/
+/**                                                                          **/
+/**  DESCRIPTION : This file implements ONU EPON Manager functionality       **/
+/**                                                                          **/
+/******************************************************************************
+ *                                                                            *
+ *  MODIFICATION HISTORY:                                                     *
+ *                                                                            *
+ *   26Jan10  oren_ben_hayun    created                                       *
+ * ========================================================================== *
+ *
+ ******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "eponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/epon/eponOnuMngr.c"
+
+#define OAM_MSG_NOT_TRANS   (0xFFFF)
+#define OAM_MSG_FIFO_LENGTH (16)
+#define OAM_MSG_REGS        (10)
+#define OAM_MSG_DG_IND      (1)
+
+#define DBA_RPRT_MAX_SIZE   (35) /* Report via EPON REGS */
+
+#define DBA_RPRT_PERIODIC_CYCLE (6)
+#define DBA_RPRT_TX_FIFO_SIZE (4*1024)
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+extern spinlock_t onuPonIrqLock;
+
+extern MV_U8 fixMacAddrs[8][6];
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+
+/* HW DBA params */
+MV_U32 dbaRprtState           = 0; /* TO */
+MV_U32 dbaRprtT0StateVal      = 0x43FF;
+MV_U32 dbaRprtT0StateInterval = ONU_PON_TIMER_HW_RPRT_T0_INTERVAL;
+MV_U32 dbaRprtT1StateVal      = 0x07FF;
+MV_U32 dbaRprtT1StateInterval = ONU_PON_TIMER_HW_RPRT_T1_INTERVAL;
+
+/* SW DBA params */
+
+MV_U32 llidDbaRprtCount = 0;
+MV_U32 llidDbaRprtValue = 0;
+
+MV_U32 llidDbaRprtForOamMsgInd = 0;
+
+MV_U32 llidCounter[8]           = {0,0,0,0,0,0,0,0};
+
+MV_U32 llidQueueState[8][4][8]  = {
+	                               {{0,0,0,0,0,0,0,0},
+                                    {0,0,0,0,0,0,0,0},
+                                    {0,0,0,0,0,0,0,0},
+                                    {0,0,0,0,0,0,0,0}},
+								   {{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0}},
+								   {{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0}},
+								   {{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0}},
+								   {{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0}},
+								   {{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0}},
+								   {{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0}},
+								   {{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0},
+									{0,0,0,0,0,0,0,0}}
+                                  };
+
+MV_U32 llidQueueThreshold[8][4][8] = {
+	                                  {{0,0,0,0,0,0,0,0},
+                                       {0,0,0,0,0,0,0,0},
+                                       {0,0,0,0,0,0,0,0},
+                                       {0,0,0,0,0,0,0,0}},
+									  {{0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0}},
+									  {{0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0}},
+									  {{0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0}},
+									  {{0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0}},
+									  {{0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0}},
+									  {{0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0}},
+									  {{0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0},
+									   {0,0,0,0,0,0,0,0}}
+                                     };
+
+MV_U32 llidNumOfQueuesets[8] = {0,0,0,0,0,0,0,0};
+
+MV_U32 llidNumOfQueues[8] = {0,0,0,0,0,0,0,0};
+
+MV_U32 llidQueuesBitMap[8] = {0,0,0,0,0,0,0,0};
+
+MV_U32 llidNumOfReportBytes[8] = {0,0,0,0,0,0,0,0};
+
+/* SW DBA array for Mix mode SW/HW */
+S_OnuEponDbaShadowRegMap dbaSwRprtRegShadow[] =
+{
+  /* Index 0 - queueset*/{mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET, 0},
+  /* Index 1 - bitmap*/  {mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP,   0},
+  /* Index 2 - queue0*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0,   0},
+  /* Index 3 - queue1*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1,   0},
+  /* Index 4 - queue2*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2,   0},
+  /* Index 5 - queue3*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3,   0},
+  /* Index 6 - queue4*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4,   0},
+  /* Index 7 - queue5*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5,   0},
+  /* Index 8 - queue6*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6,   0},
+  /* Index 9 - queue7*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7,   0}
+};
+
+S_OnuEponDbaSwRprtRegMap dbaSwRprtRegMap[] =
+{
+  /*  0 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET,  0,  0},
+  /*  1 */ {mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP,    0,  1},
+  /*  2 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0,    8,  2},
+  /*  3 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0,    0,  2},
+  /*  4 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1,    8,  3},
+  /*  5 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1,    0,  3},
+  /*  6 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2,    8,  4},
+  /*  7 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2,    0,  4},
+  /*  8 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3,    8,  5},
+  /*  9 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3,    0,  5},
+  /* 10 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4,    8,  6},
+  /* 11 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4,    0,  6},
+  /* 12 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5,    8,  7},
+  /* 13 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5,    0,  7},
+  /* 14 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6,    8,  8},
+  /* 15 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6,    0,  8},
+  /* 16 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7,    8,  9},
+  /* 17 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7,    0,  9},
+  /* 18 */ {mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP,    8,  1},
+  /* 19 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0,   24,  2},
+  /* 20 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0,   16,  2},
+  /* 21 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1,   24,  3},
+  /* 22 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1,   16,  3},
+  /* 23 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2,   24,  4},
+  /* 24 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2,   16,  4},
+  /* 25 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3,   24,  5},
+  /* 26 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3,   16,  5},
+  /* 27 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4,   24,  6},
+  /* 28 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4,   16,  6},
+  /* 29 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5,   24,  7},
+  /* 30 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5,   16,  7},
+  /* 31 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6,   24,  8},
+  /* 32 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6,   16,  8},
+  /* 33 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7,   24,  9},
+  /* 34 */ {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7,   16,  9}
+};
+
+/* SW DBA array for Mix mode SW/HW */
+S_OnuEponDbaShadowRegMap dbaDgSwRprtRegShadow[] =
+{
+  /* Index 0 - queueset*/{mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET, 0x00000001},
+  /* Index 1 - bitmap*/  {mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP,   0x000000FF},
+  /* Index 2 - queue7*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0,   0x00000000},
+  /* Index 3 - queue6*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1,   0x00000000},
+  /* Index 4 - queue5*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2,   0x00000000},
+  /* Index 5 - queue4*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3,   0x00000000},
+  /* Index 6 - queue3*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4,   0x00000000},
+  /* Index 7 - queue2*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5,   0x00000000},
+  /* Index 8 - queue1*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6,   0x00000000},
+  /* Index 9 - queue0*/  {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7,   0x0000FFFF}
+};
+
+MV_U32 llidPacketFcsCompensation[] =
+{
+  /*  0    0 add    0 */  0,
+  /*  1   64 add  1/2 */  2,
+  /*  2  128 add  1/4 */  4,
+  /*  3  192 add  1/6 */  6,
+  /*  4  256 add  1/5 */  5,
+  /*  5  320 add  1/6 */  6,
+  /*  6  384 add  1/8 */  8,
+  /*  7  448 add  1/8 */  8,
+  /*  8  512 add  1/8 */  8,
+  /*  9  576 add  1/9 */  9,
+  /* 10  640 add 1/10 */ 10,
+  /* 11  704 add 1/10 */ 10,
+  /* 12  768 add 1/10 */ 10,
+  /* 13  832 add 1/11 */ 11,
+  /* 14  896 add 1/11 */ 11,
+  /* 15  960 add 1/11 */ 11,
+  /* 16 1024 add 1/11 */ 11,
+  /* 17 1088 add 1/12 */ 12,
+  /* 18 1152 add 1/12 */ 12,
+  /* 19 1216 add 1/12 */ 12,
+  /* 20 1280 add 1/12 */ 12,
+  /* 21 1344 add 1/12 */ 12,
+  /* 22 1408 add 1/12 */ 12,
+  /* 23 1472 add 1/12 */ 12,
+  /* 24 1536 add 1/12 */ 12,
+  /* 25 1600 add 1/12 */ 12,
+  /* 26 1664 add 1/12 */ 12,
+  /* 27 1728 add 1/12 */ 12,
+  /* 28 1792 add 1/12 */ 12,
+  /* 29 1856 add 1/12 */ 12,
+  /* 30 1920 add 1/12 */ 12,
+  /* 31 1984 add 1/12 */ 12,
+  /* 32 2048 add 1/12 */ 12
+};
+
+/* SW DBA report additional bandwidth params */
+MV_U32 rprtLowRateThreshold;
+MV_U32 rprtLowRateValue;
+MV_U32 rprtLowRateConstValue;
+MV_U32 rprtHighRateThreshold;
+MV_U32 rprtHighRateValue;
+
+/* SW DBA report message */
+MV_U8  reportMsg[40];
+MV_U8  reportMsgIdx;
+
+/* OAM message transmission handling */
+//S_OnuEponOamMsg oamDgMsgQueue;
+S_OnuEponOamMsg oamMsgData[OAM_MSG_FIFO_LENGTH];
+
+/* Data array pointers definition */
+MV_U8 oamMsgWriteIndex = 0;
+MV_U8 oamMsgReadIndex  = 0;
+
+/* Dying Gasp message parameters */
+MV_U16 dgMsgEtype    = 0x8809; /* Slow Protocol */
+MV_U16 dgMsgSubType  = 0x03;   /* OAM */
+MV_U16 dgMsgFlags    = 0x52;   /* Dying Gasp */
+MV_U8  dgMsgCode     = 0x0;    /* Information OAMPDU */
+S_OnuEponCtrlBuffer dgOamMsg;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+/* Interrupt handler Functions */
+void      onuEponPonMngIntrAlarmHandler(MV_U32 alarm, MV_BOOL alarmStatus);
+void      onuEponPonMngIntrMessageHandler(MV_U32 msg);
+void      onuEponPonMngIntrRxCtrlFifoCleanup(void);
+MV_STATUS onuEponPonMngIntrCtrlMessageHandler(S_OnuEponCtrlBuffer *ctrlBuf);
+MV_STATUS onuEponPonMngIntrRprtMessageHandler(S_OnuEponCtrlBuffer *ctrlBuf);
+MV_STATUS onuEponPonMngTimerRprtMessageHandler(MV_U32 macId);
+
+/* State Machine Functions */
+MV_STATUS onuEponPonMngRegMsgFlagAck(S_OnuEponRegMpcFrame *mpcFrame);
+MV_STATUS onuEponPonMngRegMsgFlagNack(S_OnuEponRegMpcFrame *mpcFrame);
+MV_STATUS onuEponPonMngRegMsgFlagReReg(S_OnuEponRegMpcFrame *mpcFrame);
+MV_STATUS onuEponPonMngRegMsgFlagDeReg(S_OnuEponRegMpcFrame *mpcFrame);
+
+/* MPC Message Handling Functions */
+MV_STATUS onuEponReadCtrlFrameData(S_OnuEponCtrlBuffer *ctrlBuf);
+MV_STATUS onuEponRetrieveCtrlFrameData(S_OnuEponCtrlBuffer *ctrlBuf);
+MV_STATUS onuEponReadReportFrameData(S_OnuEponCtrlBuffer *ctrlBuf);
+MV_STATUS onuEponRetrieveReportFrameData(S_OnuEponCtrlBuffer *ctrlBuf);
+
+void      onuEponConvertN2HShort(void *srcValPtr, void *destValPtr);
+void      onuEponConvertN2HLong(void *srcValPtr, void *destValPtr);
+void      onuEponConvertH2NShort(void *srcValPtr, void *destValPtr);
+void      onuEponConvertH2NLong(void *srcValPtr, void *destValPtr);
+
+MV_STATUS onuEponOamMsgFifoInit(void);
+MV_STATUS onuEponPonMngDbaParamsInit(void);
+MV_STATUS onuEponPonMngDbaHwRprtHandler(void);
+MV_STATUS onuEponPonMngDbaSwRprtHandler(void);
+MV_STATUS onuEponPonMngDbaDgSwRprtHandler(void);
+
+MV_STATUS onuEponSendCtrlFrameData(S_OnuEponCtrlBuffer *ctrlBuf, MV_U32 macId);
+MV_BOOL   onuEponSendCtrlFrameDataFreeStatus(MV_U32 macId);
+
+void      onuEponDgMsgDefaultMessageInit(void);
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Init Section                                       */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponPonMngAlarmHandlerExecute
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init EPON App
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponAppInit(void)
+{
+  MV_U32 macId;
+
+  onuEponOamMsgFifoInit();
+  onuEponDgMsgDefaultMessageInit();
+  onuEponPonMngDbaParamsInit();
+  for (macId = 0; macId < 8; macId++)
+    onuEponDbaInfoUpdate(macId);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponOamMsgFifoInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init OAM messages FIFO
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponOamMsgFifoInit(void)
+{
+  memset(oamMsgData, 0, sizeof(S_OnuEponOamMsg) * 8);
+//  memset(&oamDgMsgQueue, 0, sizeof(S_OnuEponOamMsg));
+
+  return(MV_OK);
+}
+
+
+/*******************************************************************************
+**
+**  onuEponPonMngDbaParamsInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init DBA Report parameters
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngDbaParamsInit(void)
+{
+  rprtLowRateThreshold  = ONU_EPON_DBA_LOW_RATE_THRESHOLD;
+  rprtLowRateValue      = ONU_EPON_DBA_LOW_RATE_VALUE;
+  rprtLowRateConstValue = ONU_EPON_DBA_LOW_RATE_CONST_VALUE;
+  rprtHighRateThreshold = ONU_EPON_DBA_HIGH_RATE_THRESHOLD;
+  rprtHighRateValue     = ONU_EPON_DBA_HIGH_RATE_VALUE;
+
+  /* LLID0 configuration */
+  onuEponPmGunitLlid0PktModMaxHeaderSizeSet(0);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponDbaInfoUpdate
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init DBA Report parameters
+**
+**  PARAMETERS:  MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponDbaInfoUpdate(MV_U32 macId)
+{
+  MV_U32 queueId;
+  MV_U32 queueSetId;
+
+  llidNumOfQueues[macId]    = onuEponDbOnuDbaNumOfQueuesGet(macId);
+  llidQueuesBitMap[macId]   = onuEponDbOnuDbaQueuesBitMapGet(macId);
+  llidNumOfQueuesets[macId] = onuEponDbOnuDbaNumOfQueuesetGet(macId);
+
+  llidNumOfReportBytes[macId] =  (((llidNumOfQueuesets[macId] * llidNumOfQueues[macId]) * 2) + /* number of bytes for queues */
+  				                  llidNumOfQueuesets[macId]                                + /* number of bytes for bit map */
+  				                  1);                                                        /* number of bytes for #queuesets */
+  if (llidNumOfReportBytes[macId] > DBA_RPRT_MAX_SIZE) /* hardware limit */
+    llidNumOfReportBytes[macId] = DBA_RPRT_MAX_SIZE;
+
+
+  mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MODULE,
+  		   "MAC[%d] QSet(%d) Q(%d) Rbytes(%d)\n",
+  		   macId, llidNumOfQueuesets[macId], llidNumOfQueues[macId], llidNumOfReportBytes[macId]);
+
+  for (queueSetId = 0; queueSetId < llidNumOfQueuesets[macId]; queueSetId++)
+  {
+    mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MODULE,
+  		     "QSet(%d) Q[thres:state]", queueSetId);
+
+    for (queueId = 0; queueId <  EPON_MAX_QUEUE; queueId++)
+    {
+  	  onuEponDbOnuDbaQueueThresholdGet(&(llidQueueThreshold[macId][queueSetId][queueId]),
+  	  							     &(llidQueueState[macId][queueSetId][queueId]),
+  	    							     queueId, queueSetId, macId);
+  	  mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MODULE,
+  	  		     "[%d:%d]",
+  	  		     llidQueueThreshold[macId][queueSetId][queueId],
+  	  		     llidQueueState[macId][queueSetId][queueId]);
+    }
+
+    mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "\n");
+  }
+
+  return(MV_OK);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Alarm Section                                      */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponPonMngAlarmHandlerExecute
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager interrupt alarm
+**               functionality
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngAlarmHandlerExecute(MV_U32 macId)
+{
+  MV_STATUS status;
+  MV_U32    startMacId;
+  MV_U32    endMacId;
+  MV_U32    interruptMask;
+  LINKSTATUSFUNC linkStatusCallback;
+
+  if (macId == ALL_MAC_INDICATION)
+  {
+	startMacId = 0;
+	endMacId   = EPON_MAX_MAC_NUM;
+  }
+  else
+  {
+	startMacId = macId;
+	endMacId   = macId + 1;
+  }
+
+  if ((macId == 0) || (macId == ALL_MAC_INDICATION))
+  {
+	if (onuEponDbModeGet() == E_EPON_IOCTL_STD_MODE)
+	{
+	  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "===================\n");
+	  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "== MPCP Sync Off ==\n");
+	  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "===================\n");
+	}
+  }
+
+  if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_SW_DBA_RPRT_TIMER)
+  {
+	/* Stop SW DBA event miss timer */
+	onuEponIsrTimerEventMissStateSet(MV_FALSE);
+
+	/* Clear onu DBA Report interrupt */
+	mvOnuEponMacPonInterruptMaskGet(&interruptMask);
+	interruptMask &= ~(ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK);
+	mvOnuEponMacPonInterruptMaskSet(interruptMask);
+  }
+  else
+  {
+	/* Clear onu DBA Report Timer */
+	onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+  }
+
+  /* handle silence mode */
+  if (onuEponDbOnuSilenceStateGet() != ONU_SILENCE_NOT_ACTIVE)
+  {
+
+	/* Clear onu Silence Timers */
+	for (macId = startMacId; macId < endMacId; macId++)
+	{
+		onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonSilenceTimerId[macId]));
+	}
+
+	status  = mvOnuEponMacGenOnuConfigAutoAckSet(ONU_REG_ACK_AUTO_RES);
+	status |= mvOnuEponMacGenOnuConfigAutoRequestSet(ONU_REG_REQ_AUTO_RES);
+	if (status != MV_OK)
+	{
+	  mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+				 "ERROR: (%s:%d) Failed to enable auto request / ack\n\r", __FILE_DESC__, __LINE__);
+	  return;
+	}
+
+	onuEponDbOnuCfgAutoSet(ONU_REG_REQ_AUTO_RES, ONU_REG_ACK_AUTO_RES, ONU_REPORT_AUTO_RES);
+  }
+
+  for (macId = startMacId; macId < endMacId; macId++)
+  {
+      /* re-init onu database */
+      status = onuEponDbReInit(macId);
+      if (status != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+                   "ERROR: (%s:%d) Failed to re-init onu database\n\r", __FILE_DESC__, __LINE__);
+        return;
+      }
+
+      /* init onu Asic */
+      status = onuEponAsicReInit(macId, ONU_SILENCE_DISABLED);
+      if (status != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+                   "ERROR: (%s:%d) Failed to re-init onu EPON MAC\n\r", __FILE_DESC__, __LINE__);
+        return;
+      }
+  }
+
+  /* Call link status callback function */
+  linkStatusCallback = onuEponDbLinkStatusCallbackGet();
+  if (linkStatusCallback != NULL)
+  {
+    if (onuEponForceTxDownStateGet(0) != MV_TRUE)
+      linkStatusCallback(MV_FALSE);
+  }
+
+  if (onuEponDbOnuHoldoverStateGet() != ONU_HOLDOVER_NOT_ACTIVE)
+  {
+	if (onuEponDbOnuHoldoverExecGet() != ONU_HOLDOVER_NOT_ACTIVE)
+	{
+	  onuEponDbOnuHoldoverExecSet(ONU_HOLDOVER_NOT_ACTIVE);
+	}
+  }
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngIntrAlarmHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager interrupt alarm
+**               functionality
+**
+**  PARAMETERS:  MV_U32 alarm
+**               MV_U32 alarmStatus
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngIntrAlarmHandler(MV_U32 alarm, MV_BOOL alarmStatus)
+{
+	if (alarmStatus != MV_FALSE) {
+
+		/* alarm is ON */
+		if (onuEponDbOnuHoldoverStateGet() != ONU_HOLDOVER_NOT_ACTIVE) {
+			if (onuEponDbOnuHoldoverExecGet() != ONU_HOLDOVER_ACTIVE) {
+				/* start onu epon pon holdover timer */
+				onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHoldoverTimerId));
+				onuEponDbOnuHoldoverExecSet(ONU_HOLDOVER_ACTIVE);
+				mvPonPrint(PON_PRINT_DEBUG, PON_ISR_STATE_MODULE,
+						   "DEBUG: (%s:%d) Holdover Timer Start(Intr)\n", __FILE_DESC__, __LINE__);
+			}
+		} else
+			onuEponPonMngAlarmHandlerExecute(ALL_MAC_INDICATION);
+
+		/* update alarm */
+		onuEponAlarmSet(alarm, alarmStatus);
+
+	} else {
+
+		/* alarm is OFF */
+		if (onuEponDbOnuHoldoverStateGet() != ONU_HOLDOVER_NOT_ACTIVE) {
+			if (onuEponDbOnuHoldoverExecGet() != ONU_HOLDOVER_NOT_ACTIVE) {
+				/* stop onu epon pon holdover timer */
+				onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonHoldoverTimerId));
+				onuEponDbOnuHoldoverExecSet(ONU_HOLDOVER_NOT_ACTIVE);
+				mvPonPrint(PON_PRINT_DEBUG, PON_ISR_STATE_MODULE,
+						   "DEBUG: (%s:%d) Holdover Timer Stop\n", __FILE_DESC__, __LINE__);
+			}
+		}
+
+		/* update alarm */
+		onuEponAlarmSet(alarm, alarmStatus);
+	}
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Register Section                                   */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponPonMngIntrRegHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager interrupt register
+**               functionality
+**
+**  PARAMETERS:  MV_U32 reg
+**               MV_U32 regStatus
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngIntrRegHandler(MV_U32 reg, MV_BOOL regStatus)
+{
+  MV_STATUS status;
+  MV_U32    delay;
+  MV_U32    laser;
+
+  /* Register State Active */
+  if (regStatus != MV_FALSE)
+  {
+    delay  = ((0x0 << 8) | (0x0 + ONU_DEF_DDM_DELAY));
+    status = mvOnuEponMacDdmDelaySet(delay);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                 "ERROR: (%s:%d) mvAsicReg_EPON_DDM_1814_CONFIG\n\r", __FILE_DESC__, __LINE__);
+    }
+
+    laser  = (ONU_DEF_LASER_ON_OFF_TIME << 24) |
+             (ONU_DEF_LASER_OFF_TIME << 8) |
+             (ONU_DEF_LASER_ON_TIME);
+    status = mvOnuEponMacGenLaserParamSet(ONU_DEF_LASER_ON_OFF_TIME,
+                                          ONU_DEF_LASER_ON_TIME,
+                                          ONU_DEF_LASER_OFF_TIME);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacGenLaserParamSet\n\r", __FILE_DESC__, __LINE__);
+    }
+
+    mvPonPrint(PON_PRINT_INFO, PON_API_MODULE,
+               "Register State[ON]: DDM_Config(0x%x) LASER_PARAM(0x%x)\n\r", delay, laser);
+  }
+  /* Register State Not - Active */
+  else
+  {
+    delay  = ONU_DEF_DDM_DELAY;
+    status = mvOnuEponMacDdmDelaySet(delay);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                 "ERROR: (%s:%d) mvAsicReg_EPON_DDM_1814_CONFIG\n\r", __FILE_DESC__, __LINE__);
+    }
+
+    laser  = (ONU_DEF_LASER_ON_OFF_TIME << 24) |
+             (ONU_DEF_LASER_OFF_TIME << 8) |
+             (ONU_DEF_LASER_ON_TIME);
+    status = mvOnuEponMacGenLaserParamSet(ONU_DEF_LASER_ON_OFF_TIME,
+                                          ONU_DEF_LASER_ON_TIME,
+                                          ONU_DEF_LASER_OFF_TIME);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                 "ERROR: (%s:%d) mvOnuEponMacGenLaserParamSet\n\r", __FILE_DESC__, __LINE__);
+    }
+
+    mvPonPrint(PON_PRINT_INFO, PON_API_MODULE,
+               "Register State[OFF]: DDM_Config(0x%x) LASER_PARAM(0x%x)\n\r", delay, laser);
+  }
+
+
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Message Section                                    */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponPonMngTimerHwRprtTxModHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function transmit OAM frame handling
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngTimerHwRprtTxModHndl(unsigned long data)
+{
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonHwRprtTxModTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  onuEponPonMngTxCtrlMessageHandler();
+
+  if ((onuPonResourceTbl_s.onuPonHwRprtTxModTimerId.onuPonTimerPeriodic) != 0)
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHwRprtTxModTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngTxCtrlMessageHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager interrupt MPC message
+**               functionality
+**
+**  PARAMETERS:  MV_U32 msg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngTxCtrlMessageHandler(void)
+{
+	MV_STATUS status;
+
+	status = onuEponOamHandleMsg();
+	if (status != OAM_MSG_NOT_TRANS)
+		llidDbaRprtForOamMsgInd = 1;
+
+	if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_SW_DBA_RPRT_TIMER)
+		onuEponPonMngSwRprtMessageHandler();
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngHwRprtMessageHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager DBA HW report functionality
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngHwRprtMessageHandler(void)
+{
+  MV_STATUS status;
+
+  status = onuEponPonMngDbaHwRprtHandler();
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_MODULE,
+  			   "ERROR: (%s:%d) Handle HW DBA Report\n\r", __FILE_DESC__, __LINE__);
+    return;
+  }
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngSwRprtMessageHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager DBA SW report functionality
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngSwRprtMessageHandler(void)
+{
+	MV_STATUS status;
+
+	status = onuEponPonMngDbaSwRprtHandler();
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_MODULE,
+			   "ERROR: (%s:%d) Handle SW DBA Report\n\r", __FILE_DESC__, __LINE__);
+		return;
+	}
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngIntrMessageHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager message handling functionality
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngIntrMessageHandler(MV_U32 msg)
+{
+	MV_STATUS           status;
+	S_OnuEponCtrlBuffer ctrlBuf;
+
+	memset((void*)&ctrlBuf, 0, sizeof (S_OnuEponCtrlBuffer));
+
+	if (msg == ONU_EPON_RX_CTRL_MSG) {
+		do {
+			status = onuEponRetrieveCtrlFrameData(&ctrlBuf);
+			if (status != MV_OK)
+				return;
+
+			status = onuEponPonMngIntrCtrlMessageHandler(&ctrlBuf);
+			if (status != MV_OK) {
+				mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+						   "ERROR: (%s:%d) Handle Rx Ctrl Frame\n\r", __FILE_DESC__, __LINE__);
+				onuEponPmSwRxCountersAdd(TOTAL_MPCP_RX_ERROR_FRAME_CNT, 0);
+			}
+		} while (status == MV_OK);
+
+	} else if (msg == ONU_EPON_RX_RPRT_MSG) {
+
+		status = onuEponRetrieveReportFrameData(&ctrlBuf);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+					   "ERROR: (%s:%d) Read Rx Report Frame\n\r", __FILE_DESC__, __LINE__);
+			return;
+		}
+
+		status = onuEponPonMngIntrRprtMessageHandler(&ctrlBuf);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+					   "ERROR: (%s:%d) Handle Rx Report Frame\n\r", __FILE_DESC__, __LINE__);
+			return;
+		}
+
+	} else {
+
+		mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+				   "ERROR: (%s:%d) Unsupported Frame\n\r", __FILE_DESC__, __LINE__);
+	}
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngIntrRxCtrlFifoCleanup
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clear the pon manager RX ctrl message FIFO
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngIntrRxCtrlFifoCleanup(void)
+{
+	MV_STATUS           status;
+	S_OnuEponCtrlBuffer ctrlBuf;
+
+	memset((void*)&ctrlBuf, 0, sizeof (S_OnuEponCtrlBuffer));
+
+	do {
+		status = onuEponRetrieveCtrlFrameData(&ctrlBuf);
+
+	} while (status == MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngIntrCtrlMessageHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager interrupt MPC Ctrl
+**               message functionality
+**
+**  PARAMETERS:  S_OnuEponCtrlBuffer *ctrlBuf
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngIntrCtrlMessageHandler(S_OnuEponCtrlBuffer *ctrlBuf)
+{
+  MV_STATUS            status;
+  S_OnuEponGenMpcFrame *genMpcMsg;
+  S_OnuEponRegMpcFrame *regMpcMsg;
+  MV_U16               regOpcode;
+  MV_U16               regFlags;
+
+  genMpcMsg = (S_OnuEponGenMpcFrame *)ctrlBuf->data;
+  onuEponConvertN2HShort(&genMpcMsg->genMpcPdu.opCode, &regOpcode);
+
+	if (regOpcode == MPC_OPCODE_REGISTER) {
+
+		regMpcMsg = (S_OnuEponRegMpcFrame *)ctrlBuf->data;
+		regFlags  = regMpcMsg->regMpcPdu.flags;
+
+		if (regFlags == REGISTER_FLAGS_ACK) {
+			onuEponPmSwRxCountersAdd(TOTAL_MPCP_REGISTER_ACK_CNT, 0);
+
+			status = onuEponPonMngRegMsgFlagAck(regMpcMsg);
+			if (status != MV_OK) {
+				mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+						   "ERROR: (%s:%d) Register with flag Ack\n\r", __FILE_DESC__, __LINE__);
+				return(MV_ERROR);
+			}
+
+		} else if (regFlags == REGISTER_FLAGS_NACK) {
+
+			onuEponPmSwRxCountersAdd(TOTAL_MPCP_REGISTER_NACK_CNT, 0);
+
+			status = onuEponPonMngRegMsgFlagNack(regMpcMsg);
+			if (status != MV_OK) {
+				mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+						   "ERROR: (%s:%d) Register with flag Nack\n\r", __FILE_DESC__, __LINE__);
+				return(MV_ERROR);
+			}
+
+		} else if (regFlags == REGISTER_FLAGS_REREG) {
+
+			onuEponPmSwRxCountersAdd(TOTAL_MPCP_REGISTER_REREG_FRAME_CNT, 0);
+
+			status = onuEponPonMngRegMsgFlagReReg(regMpcMsg);
+			if (status != MV_OK) {
+				mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+						   "ERROR: (%s:%d) Register with flag Re-Register\n\r", __FILE_DESC__, __LINE__);
+				return(MV_ERROR);
+			}
+
+		} else if (regFlags == REGISTER_FLAGS_DEREG) {
+
+			onuEponPmSwRxCountersAdd(TOTAL_MPCP_REGISTER_DEREG_FRAME_CNT, 0);
+
+			status = onuEponPonMngRegMsgFlagDeReg(regMpcMsg);
+			if (status != MV_OK) {
+				mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+						   "ERROR: (%s:%d) Register with flag De-Register\n\r", __FILE_DESC__, __LINE__);
+				return(MV_ERROR);
+			}
+
+		} else {
+
+			mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+					   "ERROR: (%s:%d) Invalid Control message flag(%d)\n\r", __FILE_DESC__, __LINE__, regFlags);
+			return(MV_ERROR);
+		}
+
+	}
+
+	return(MV_OK);
+
+} /* end of onuEponPonMngIntrCtrlMessageHandler */
+
+
+/*******************************************************************************
+**
+**  onuEponPonMngIntrRprtMessageHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager interrupt MPC Report
+**               message functionality
+**
+**  PARAMETERS:  S_OnuEponCtrlBuffer *ctrlBuf
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngIntrRprtMessageHandler(S_OnuEponCtrlBuffer *ctrlBuf)
+{
+  mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MODULE,
+             "ERROR: (%s:%d) Report Messages are handled by the EPON MAC\n\r", __FILE_DESC__, __LINE__);
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngTimerRprtMessageHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager interrupt MPC Report
+**               message transmit function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngTimerRprtMessageHandler(MV_U32 macId)
+{
+  MV_STATUS             status;
+  S_OnuEponCtrlBuffer   ctrlBuf;
+  S_OnuEponGenMpcFrame *genMpcMsg;
+  MV_U16                msgEtype  = 0x8808;
+  MV_U16                msgOpcode = 0x0003;
+  MV_U16                reportIdx;
+  MV_U16                frameIdx;
+
+  /* clear message */
+  memset(&ctrlBuf, 0, MIN_RPRT_FRAME_LEN);
+
+  /* set message length */
+  ctrlBuf.length = MIN_RPRT_FRAME_LEN;
+
+  genMpcMsg = (S_OnuEponGenMpcFrame *)&(ctrlBuf.data);
+
+  /* update message content */
+  genMpcMsg->stdEthFrame.destAddr[0] = 0x01;
+  genMpcMsg->stdEthFrame.destAddr[1] = 0x80;
+  genMpcMsg->stdEthFrame.destAddr[2] = 0xC2;
+  genMpcMsg->stdEthFrame.destAddr[3] = 0x00;
+  genMpcMsg->stdEthFrame.destAddr[4] = 0x00;
+  genMpcMsg->stdEthFrame.destAddr[5] = 0x01;
+
+  onuEponConvertH2NShort(&msgEtype,  &genMpcMsg->stdEthFrame.etherType);
+
+  onuEponConvertH2NShort(&msgOpcode, &genMpcMsg->genMpcPdu.opCode);
+
+  genMpcMsg->genMpcPdu.timeStamp  = 0;
+
+  genMpcMsg->stdEthFrame.srcAddr[0] = fixMacAddrs[macId][0];
+  genMpcMsg->stdEthFrame.srcAddr[1] = fixMacAddrs[macId][1];
+  genMpcMsg->stdEthFrame.srcAddr[2] = fixMacAddrs[macId][2];
+  genMpcMsg->stdEthFrame.srcAddr[3] = fixMacAddrs[macId][3];
+  genMpcMsg->stdEthFrame.srcAddr[4] = fixMacAddrs[macId][4];
+  genMpcMsg->stdEthFrame.srcAddr[5] = fixMacAddrs[macId][5];
+
+  for (reportIdx = 0, frameIdx = 20; reportIdx < 40; reportIdx++, frameIdx++)
+  {
+    ctrlBuf.data[frameIdx] = reportMsg[reportIdx];
+  }
+
+  status = onuEponSendCtrlFrameData(&ctrlBuf, macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Handle OAM Message\n\r", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**  ========================================================================  **
+**                            SW Report Section                               **
+**  ========================================================================  **
+*******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponPonMngDbaSwRprtAddQueueSetThreshold
+**
+*******************************************************************************/
+//void onuEponPonMngDbaSwRprtAddQueueSetThreshold(MV_32 queueSetIdx, MV_32 queueIdx)
+//{
+//  if (llidQueueState[queueSetIdx][queueIdx] != 0)
+//  {
+//    if (llidCounter[queueIdx] > llidQueueThreshold[queueSetIdx][queueIdx])
+//	{
+//	  reportMsg[reportMsgIdx++] = ((llidQueueThreshold[queueSetIdx][queueIdx] >> 8) & 0xFF);
+//	  reportMsg[reportMsgIdx++] =  (llidQueueThreshold[queueSetIdx][queueIdx]       & 0xFF);
+//	}
+//    else
+//	{
+//	  reportMsg[reportMsgIdx++] = ((llidCounter[queueIdx] >> 8) & 0xFF);
+//	  reportMsg[reportMsgIdx++] =  (llidCounter[queueIdx]       & 0xFF);
+//	}
+//  }
+//}
+
+/*******************************************************************************
+**
+**  onuEponPonMngDbaSwRprtHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager DBA SW report handler
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngDbaSwRprtHandler(void)
+{
+	MV_STATUS status = MV_OK;
+	MV_U32    idx;
+	MV_U32    llidIdx;
+	MV_32     queueSetIdx;
+	MV_32     queueIdx;
+	MV_U32    msgIdx;
+	MV_U32    msgTmpData;
+	MV_U32    llidQueuesByteCount;
+	MV_U32    llidTotalByteCount;
+	MV_U32    llidAvePacketLength;
+	MV_U32    llidPacketCountCompensationIdx;
+	MV_U32    llidPacketCountCompensation;
+	MV_U32    llidPacketCount = 0;
+	MV_U32    llidTransmittedPacketCount = 0;
+	MV_U32    tmpLlidHighQueue;   /* highest queue according to mng configuration */
+	MV_U32    llidTxFecState = 0;
+	MV_U32    ts[10] = {0};
+	MV_U32    *pTs = ts;
+	MV_U32    interval[6] = {0};
+#define COLLECT_DBA_TS		mvOnuEponMacGenLocalTimeStampGet(pTs++)
+
+	for (llidIdx = 0; llidIdx < EPON_MAX_MAC_NUM; llidIdx++) {
+
+		llidQueuesByteCount         = 0;
+		llidTotalByteCount          = 0;
+		llidPacketCount             = 0;
+		llidPacketCountCompensation = 0;
+
+		/* Non-active LLID */
+		if (onuEponDbOnuDbaLlidActiveStatusGet(llidIdx) != ONU_DBA_ACTIVE_LLID)
+			continue;
+
+		COLLECT_DBA_TS;
+
+		/* ======================= */
+		/* Retrieve Queue Counters */
+		/* ======================= */
+
+		/* update counters in case FEC is enabled */
+		onuEponDbOnuTxFecCfgGet(&llidTxFecState, llidIdx);
+
+		queueSetIdx = 0;
+
+		for (queueIdx = 0; queueIdx < EPON_MAX_QUEUE; queueIdx++) {
+			/* for each queue */
+			if (llidQueuesBitMap[llidIdx] & (1 << queueIdx)) {
+
+				status = onuEponPmGunitLlidQueueCntGet(llidIdx, queueIdx, &(llidCounter[queueIdx]));
+				if (status != MV_OK) {
+					mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+							"ERROR: (%s:%d) Llid[%d] Queue[%d] Cnt Get Failed\n\r",
+							__FILE_DESC__, __LINE__, llidIdx, queueIdx);
+					return(MV_ERROR);
+				}
+
+			} else
+				llidCounter[queueIdx] = 0;
+
+			mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_MODULE,
+					"SW DBA, queue[%d] count[%d]\n", queueIdx, llidCounter[queueIdx]);
+
+			/* convert to TQ units */
+			llidCounter[queueIdx] /= 2;
+
+			/* sum queues TQ to verify data was received */
+			llidQueuesByteCount += llidCounter[queueIdx];
+		} /* for each queue */
+
+		/* Count the number of transmitted words in the GPUnit without - checksum and header modified bytes */
+		/* Counter is clear-on-read */
+		onuEponPmGunitLlid0PktModPktCountGet(&llidPacketCount);
+
+		tmpLlidHighQueue = onuEponDbOnuDbaHighestReportQueueGet(llidIdx);
+
+		llidTotalByteCount = (llidQueuesByteCount * 2) + (llidPacketCount * 2);
+
+		COLLECT_DBA_TS;
+
+		/* =========================== */
+		/* Low-Rate and Birsty Traffic */
+		/* =========================== */
+		/* Incase there is no data was found in the LLID queues, and */
+		/* The LLID packet count != 0, meaning packets were transmitted towards the GPON MAC */
+		/* Add the number of transmitted packets in words + threshold LLID to the highest queue report */
+		/* The number of transmitted packets does include packets checksum and header modified bytes */
+		/* The threshold is used to compensate checksum and header modified bytes */
+		/* The report is sent maximum of DBA_RPRT_PERIODIC_CYCLE (6) intervals, it will be periodicly transmitted */
+		/* until is identifes data in the LLID Queues or LLID FIFO. */
+		/* In case of very low rate traffic, it send the report DBA_RPRT_PERIODIC_CYCLE (6) intervals. */
+		/* This WA is to compensate the "breathing" scheme of OLT DBA GATE allocation */
+		if (llidQueuesByteCount == 0) {
+
+			if (llidPacketCount != 0) {
+
+				llidDbaRprtCount = DBA_RPRT_PERIODIC_CYCLE;
+				/* If the previous GATE allowed large traffic burst, so all packets from queues got TXed and
+				*  packet counter indicates more packets than theoretically can be waiting in TX FIFO,
+				*  limit the counter value to the FIFO size in order to avoid bandwidth oversubscribtion needed
+				*  for FIFO release
+				*/
+				if (llidPacketCount > DBA_RPRT_TX_FIFO_SIZE)
+					llidDbaRprtValue = DBA_RPRT_TX_FIFO_SIZE;
+				else
+					llidDbaRprtValue = llidPacketCount;
+			}
+
+			if ((llidDbaRprtCount > 0) && (llidDbaRprtCount <= DBA_RPRT_PERIODIC_CYCLE)) {
+
+				llidCounter[tmpLlidHighQueue] += (llidDbaRprtValue + (rprtLowRateConstValue / 2));
+
+				mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_WA_MODULE,
+							"DBA WA[%d], PktCnt(%d), RprtCnt(%d)\n",
+							llidDbaRprtCount, llidDbaRprtValue, llidCounter[tmpLlidHighQueue]);
+
+				llidDbaRprtCount--;
+			}
+
+		} else {
+
+			llidDbaRprtCount = 0;
+			llidDbaRprtValue = 0;
+		}
+
+		COLLECT_DBA_TS;
+
+		/* ================= */
+		/* High-Rate Traffic */
+		/* ================= */
+		/* Incase data was found in the LLID queues, the 4K FIFO is full */
+		/* If total number of bytes in the LLID queues is less the 8192 bytes */
+		/* Add configurable number of TQ (default to 1000) to highest queue report */
+		if ((llidQueuesByteCount > 0) && (llidQueuesByteCount < (rprtHighRateThreshold / 2)))
+			llidCounter[tmpLlidHighQueue] += (rprtHighRateValue / 2);
+
+		/* =========== */
+		/* OAM Traffic */
+		/* =========== */
+		if (llidDbaRprtForOamMsgInd == 1) {
+			mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_MODULE,
+					"SW DBA, OAM Message addition to highQ[%d], \n", tmpLlidHighQueue);
+
+			llidCounter[tmpLlidHighQueue] += (rprtLowRateValue / 2);
+
+			llidDbaRprtForOamMsgInd = 0;
+		}
+
+		COLLECT_DBA_TS;
+
+		/* =========== */
+		/* FEC Section */
+		/* =========== */
+		if (llidTxFecState != 0) {
+
+			status = onuEponPmTxDataPmLastIntervalGet(&llidTransmittedPacketCount, llidIdx);
+			if (status != MV_OK) {
+				for (queueIdx = 0; queueIdx < EPON_MAX_QUEUE; queueIdx++) {
+					if (llidCounter[queueIdx] != 0)
+						llidCounter[queueIdx] = (llidCounter[queueIdx] + (llidCounter[queueIdx] / 12));/* default */
+				}
+
+				mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_FEC_MODULE, "SW DBA FEC, default setting\n");
+
+			} else {
+
+				if (llidTransmittedPacketCount != 0) {
+
+					llidAvePacketLength            = (llidTotalByteCount / llidTransmittedPacketCount);
+					llidPacketCountCompensationIdx = ((llidAvePacketLength / 64) + 1);
+
+					if (llidPacketCountCompensationIdx > 32/*limit*/)
+						llidPacketCountCompensationIdx = 32;
+
+					llidPacketCountCompensation = llidPacketFcsCompensation[llidPacketCountCompensationIdx];
+
+					mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_FEC_MODULE,
+							"SW DBA FEC, Total Bytes(%d), Total Pkt, Ave Pkt(%d), CompIdx(%d), CompVal(%d)\n",
+							llidTotalByteCount, llidTransmittedPacketCount,
+							llidAvePacketLength, llidPacketCountCompensationIdx, llidPacketCountCompensation);
+
+					for (queueIdx = 0; queueIdx < EPON_MAX_QUEUE; queueIdx++) {
+						if (llidCounter[queueIdx] != 0)
+							llidCounter[queueIdx] =
+									(llidCounter[queueIdx] + (llidCounter[queueIdx] / llidPacketCountCompensation));
+					}
+
+				} /* llidTransmittedPacketCount != 0 */
+			} /* onuEponPmTxDataPmLastIntervalGet() == MV_OK */
+		} /* llidTxFecState != 0 */
+
+		COLLECT_DBA_TS;
+
+		/* ==================== */
+		/* Build Report Message */
+		/* ==================== */
+		/* Support for normal report
+		** Queue Set: [Qset1, Qset2, .., QsetN, BC]
+		** Queue: [Queue0, .., QueueN]
+		** Report is sent via EPON REGISTERS
+		** =================== */
+		memset(reportMsg, 0, 40);
+
+		reportMsgIdx = 0;
+		reportMsg[reportMsgIdx++] = llidNumOfQueuesets[llidIdx];
+
+		/* update queueset reports */
+		for (queueSetIdx = 0; queueSetIdx < llidNumOfQueuesets[llidIdx]; queueSetIdx++) {
+
+			reportMsg[reportMsgIdx++] = llidQueuesBitMap[llidIdx];
+
+			for (queueIdx = (EPON_MAX_QUEUE - 1); queueIdx >= 0; queueIdx--) {
+				if (llidQueueState[llidIdx][queueSetIdx][queueIdx] != 0) {
+					if (llidCounter[queueIdx] > llidQueueThreshold[llidIdx][queueSetIdx][queueIdx]) {
+						reportMsg[reportMsgIdx++] = ((llidQueueThreshold[llidIdx][queueSetIdx][queueIdx] >> 8) & 0xFF);
+						reportMsg[reportMsgIdx++] = (llidQueueThreshold[llidIdx][queueSetIdx][queueIdx] & 0xFF);
+					} else {
+						reportMsg[reportMsgIdx++] = ((llidCounter[queueIdx] >> 8) & 0xFF);
+						reportMsg[reportMsgIdx++] =  (llidCounter[queueIdx]       & 0xFF);
+					}
+				}
+			} /* for each queue */
+		} /* for each queueset */
+
+		/* Build report in message format */
+		for (idx = 0; idx < OAM_MSG_REGS; idx++)
+			dbaSwRprtRegShadow[idx].shadow = 0;
+
+		for (msgIdx = 0; msgIdx < llidNumOfReportBytes[llidIdx]; msgIdx++) {
+
+			msgTmpData = ((((MV_U32)(reportMsg[msgIdx])) << dbaSwRprtRegMap[msgIdx].shift) |
+										(dbaSwRprtRegShadow[dbaSwRprtRegMap[msgIdx].shadowIdx].shadow));
+			dbaSwRprtRegShadow[dbaSwRprtRegMap[msgIdx].shadowIdx].shadow = msgTmpData;
+		}
+
+		/* =================== */
+		/* Send Report Message */
+		/* =================== */
+		for (msgIdx = 0; msgIdx < OAM_MSG_REGS; msgIdx++) {
+
+			status = asicOntGlbRegWrite(dbaSwRprtRegShadow[msgIdx].reg,
+										dbaSwRprtRegShadow[msgIdx].shadow,
+										llidIdx);
+			if (status != MV_OK) {
+				mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+						"ERROR: (%s:%d) Llid[%d] msgIdx[%d] Regiter write failed\n\r",
+						__FILE_DESC__, __LINE__, llidIdx, msgIdx);
+				return(MV_ERROR);
+			}
+		}
+
+		COLLECT_DBA_TS;
+
+		for (idx = 0; idx < 4; idx++) {
+			if (ts[idx + 1] > ts[idx])
+				interval[idx] = (MV_U32)(-1) - ts[idx] + ts[idx + 1];
+			else
+				interval[idx] = ts[idx + 1] - ts[idx];
+			interval[5] += interval[idx];
+		}
+		mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_TS_MODULE,
+				"llid[%d] ticks - QC[%d], LR[%d], HR[%d], FEC[%d], TX[%d], TOTAL[%d - %dnS]\n\r",
+				llidIdx, interval[0], interval[1], interval[2], interval[3], interval[4], interval[5],
+				interval[5] * 16);
+
+	} /* For each LLID */
+
+	return(status);
+} /* enf of onuEponPonMngDbaSwRprtHandler */
+
+/*******************************************************************************
+**
+**  onuEponPonMngDbaSwRprtHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager DBA SW report handler
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngDbaDgSwRprtHandler(void)
+{
+	MV_STATUS status = MV_OK;
+	MV_U32    llidIdx;
+	MV_U32    msgIdx;
+
+	for (llidIdx = 0; llidIdx < EPON_MAX_MAC_NUM; llidIdx++) {
+		/* Active LLID */
+		/* =========== */
+		if (onuEponDbOnuDbaLlidActiveStatusGet(llidIdx) == ONU_DBA_ACTIVE_LLID) {
+			/* Send Report Message */
+			/* =================== */
+			for (msgIdx = 0; msgIdx < OAM_MSG_REGS; msgIdx++) {
+				status = asicOntGlbRegWrite(dbaDgSwRprtRegShadow[msgIdx].reg,
+							    dbaDgSwRprtRegShadow[msgIdx].shadow,
+							    llidIdx);
+				if (status != MV_OK)
+					return(MV_ERROR);
+			}
+		}
+	}
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngDbaDgSwRprtCfg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function build DG DBA SW report
+**
+**  PARAMETERS:  MV_U32 numOfQueue
+**               MV_U32 queueReport
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponPonMngDbaDgSwRprtCfg(MV_U32 numOfQueue, MV_U32 queueReport)
+{
+  MV_U32 msgIdx;
+  MV_U32 msgIdx_2;
+  MV_U8  bitMapArray[] = { /* 0  */ 0x00,
+	                       /* 1  */ 0x80,
+	                       /* 2  */ 0xC0,
+	                       /* 3  */ 0xE0,
+	                       /* 4  */ 0xF0,
+	                       /* 5  */ 0xF8,
+	                       /* 6  */ 0xFC,
+	                       /* 7  */ 0xFE,
+	                       /* 8  */ 0xFF};
+
+  if (numOfQueue > 8)       numOfQueue  = 8;
+  if (queueReport > 0xFFFF) queueReport = 0xFFFF;
+
+  /* bit map */
+  dbaDgSwRprtRegShadow[1].shadow = bitMapArray[numOfQueue];
+
+  /* queues */
+  for (msgIdx = 2; msgIdx < (2 + numOfQueue); msgIdx++)
+    dbaDgSwRprtRegShadow[msgIdx].shadow = queueReport;
+
+  for (msgIdx_2 = msgIdx; msgIdx_2 < 10; msgIdx_2++)
+    dbaDgSwRprtRegShadow[msgIdx_2].shadow = 0;
+
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "DG DBA Report\n");
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queueset - 0x%08X\n", dbaDgSwRprtRegShadow[0].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Bitmap   - 0x%08X\n", dbaDgSwRprtRegShadow[1].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queue-0  - 0x%08X\n", dbaDgSwRprtRegShadow[2].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queue-1  - 0x%08X\n", dbaDgSwRprtRegShadow[3].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queue-2  - 0x%08X\n", dbaDgSwRprtRegShadow[4].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queue-3  - 0x%08X\n", dbaDgSwRprtRegShadow[5].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queue-4  - 0x%08X\n", dbaDgSwRprtRegShadow[6].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queue-5  - 0x%08X\n", dbaDgSwRprtRegShadow[7].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queue-6  - 0x%08X\n", dbaDgSwRprtRegShadow[8].shadow);
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "Queue-7  - 0x%08X\n", dbaDgSwRprtRegShadow[9].shadow);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngDbaHwRprtHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager DBA HW report handler
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngDbaHwRprtHandler(void)
+{
+  MV_STATUS status;
+  MV_U32    highRprtQueue;
+  MV_U32    macId;
+
+  if (dbaRprtState == 0)
+  {
+    for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+    {
+      highRprtQueue = onuEponDbOnuDbaHighestReportQueueGet(macId);
+
+      mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_MODULE,
+     		     "HW DBA report[T0], mac(%d), highest(%d)\n", macId, highRprtQueue);
+
+      status = mvOnuEponMacTxmCppReportQueueX(highRprtQueue, dbaRprtT0StateVal, macId);
+      if (status != MV_OK)
+      {
+    	mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+    		   "ERROR: (%s:%d) onuEponSendCtrlFrameData\n\r", __FILE_DESC__, __LINE__);
+    	return(MV_ERROR);
+      }
+    }
+
+	onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonHwRprtTimerId), 0, dbaRprtT0StateInterval, 1);
+    dbaRprtState = 1;
+  }
+  else if (dbaRprtState == 1)
+  {
+    for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+    {
+      highRprtQueue = onuEponDbOnuDbaHighestReportQueueGet(macId);
+
+      mvPonPrint(PON_PRINT_DEBUG, PON_MNG_DBA_MODULE,
+     		     "HW DBA report[T1], mac(%d), highest(%d)\n", macId, highRprtQueue);
+
+      status = mvOnuEponMacTxmCppReportQueueX(highRprtQueue, dbaRprtT1StateVal, macId);
+      if (status != MV_OK)
+      {
+    	mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+    		   "ERROR: (%s:%d) onuEponSendCtrlFrameData\n\r", __FILE_DESC__, __LINE__);
+    	return(MV_ERROR);
+      }
+    }
+
+	onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonHwRprtTimerId), 0, dbaRprtT1StateInterval, 1);
+    dbaRprtState = 0;
+  }
+
+  return (0);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngTimerHwRprtCfg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager DBA timer report config
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngTimerHwRprtCfg(MV_U32 t0_val, MV_U32 t0_time, MV_U32 t1_val, MV_U32 t1_time)
+{
+  dbaRprtT0StateVal      = t0_val;
+  dbaRprtT0StateInterval = t0_time;
+  dbaRprtT1StateVal      = t1_val;
+  dbaRprtT1StateInterval = t1_time;
+
+  return (0);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngTimerSilenceHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager silence timer handler
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+void onuEponPonMngTimerSilenceHndl(unsigned long macId)
+{
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuPonSilenceTimerId[macId].onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+  mvPonPrint(PON_PRINT_DEBUG, PON_MNG_SILENCE_MODULE,
+			 "DEBUG: (%s:%d) Silence Timer[%d] Expire\n", __FILE_DESC__, __LINE__, macId);
+  onuEponPonMngAlarmHandlerExecute(macId);
+
+  if ((onuPonResourceTbl_s.onuPonSilenceTimerId[macId].onuPonTimerPeriodic) != 0)
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonSilenceTimerId[macId]));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+#ifndef PON_FPGA
+/******************************************************************************/
+/* ========================================================================== */
+/*                         OAM - Dying Gasp Message Handling Section          */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponPonMngDgMsgPrint
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print DG message
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+void onuEponPonMngDgMsgPrint(void)
+{
+  S_OnuEponOamFrame *oamMsg;
+
+  oamMsg = ((S_OnuEponOamFrame*)(&(dgOamMsg.data[0])));
+
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE,
+  		 "\n"
+  		 "DG Message\n"
+  		 "==========\n"
+  		 "DestMac[%x:%x:%x:%x:%x:%x] SrcMac[%x:%x:%x:%x:%x:%x]\n"
+  		 "Etype[0x%x] flags[%x] code[0x%x]\n",
+  		 oamMsg->stdEthFrame.destAddr[0], oamMsg->stdEthFrame.destAddr[1],
+  		 oamMsg->stdEthFrame.destAddr[2], oamMsg->stdEthFrame.destAddr[3],
+  		 oamMsg->stdEthFrame.destAddr[4], oamMsg->stdEthFrame.destAddr[5],
+  		 oamMsg->stdEthFrame.srcAddr[0],  oamMsg->stdEthFrame.srcAddr[1],
+  		 oamMsg->stdEthFrame.srcAddr[2],  oamMsg->stdEthFrame.srcAddr[3],
+  		 oamMsg->stdEthFrame.srcAddr[4],  oamMsg->stdEthFrame.srcAddr[5],
+  		 dgMsgEtype, oamMsg->stdOamHeader.subType,
+  		 dgMsgFlags, oamMsg->stdOamHeader.code);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngDgMessageHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager dying gasp interrupt
+**               message transmit function
+**
+**  PARAMETERS:  MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngDgMessageHandler(MV_U32 macId)
+{
+  MV_STATUS status = MV_ERROR;
+  MV_U32    transNum = 0;
+  MV_U32    maxTransNum = 100;
+
+  onuEponPonMngDbaDgSwRprtHandler();
+  do
+  {
+	if (onuEponSendCtrlFrameDataFreeStatus(macId) != MV_TRUE)
+	  continue;
+
+	status = onuEponSendCtrlFrameData(&dgOamMsg, macId);
+    transNum++;
+
+  } while ((status != MV_OK) && (transNum <= maxTransNum));
+
+//  status = onuEponDgAllocMsg(&dgOamMsg, macId);
+//  if (status != MV_OK)
+//  {
+//	mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+//			   "ERROR: (%s:%d) onuEponPonMngDgMessageHandler", __FILE_DESC__, __LINE__);
+//	return(status);
+//  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponDgMsgDefaultMessageInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Create default dying gasp interrupt message
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponDgMsgDefaultMessageInit(void)
+{
+  MV_U32 macId = 0;
+  S_OnuEponOamFrame *oamMsg;
+
+  /* clear message */
+  memset(&dgOamMsg, 0, sizeof(S_OnuEponCtrlBuffer));
+
+  /* set message length */
+  dgOamMsg.length = MIN_DG_FRAME_LEN;
+
+  /* update message content */
+  oamMsg = ((S_OnuEponOamFrame*)(&(dgOamMsg.data[0])));
+
+  oamMsg->stdEthFrame.destAddr[0] = 0x01;
+  oamMsg->stdEthFrame.destAddr[1] = 0x80;
+  oamMsg->stdEthFrame.destAddr[2] = 0xC2;
+  oamMsg->stdEthFrame.destAddr[3] = 0x00;
+  oamMsg->stdEthFrame.destAddr[4] = 0x00;
+  oamMsg->stdEthFrame.destAddr[5] = 0x02;
+
+  oamMsg->stdEthFrame.srcAddr[0] = fixMacAddrs[macId][0];
+  oamMsg->stdEthFrame.srcAddr[1] = fixMacAddrs[macId][1];
+  oamMsg->stdEthFrame.srcAddr[2] = fixMacAddrs[macId][2];
+  oamMsg->stdEthFrame.srcAddr[3] = fixMacAddrs[macId][3];
+  oamMsg->stdEthFrame.srcAddr[4] = fixMacAddrs[macId][4];
+  oamMsg->stdEthFrame.srcAddr[5] = fixMacAddrs[macId][5];
+
+  onuEponConvertH2NShort(&dgMsgEtype,  &oamMsg->stdEthFrame.etherType);
+
+  oamMsg->stdOamHeader.subType = dgMsgSubType;
+
+  onuEponConvertH2NShort(&dgMsgFlags,  &oamMsg->stdOamHeader.flags);
+
+  oamMsg->stdOamHeader.code = dgMsgCode;
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngIntrDgHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function implements the pon manager dying gasp interrupt
+**               handler function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_STATUS
+**
+*******************************************************************************/
+void onuEponPonMngIntrDgHandler(void)
+{
+  static MV_U32 first_time = 1;
+  DYINGGASPFUNC dgCallback;
+  MV_U32        macId = 0;
+
+  onuEponPonMngDgMessageHandler(macId);
+
+  if (first_time)
+  {
+    dgCallback = onuEponDbDgCallbackGet();
+
+    if (dgCallback != NULL)
+    {
+        dgCallback();
+        first_time = 0;
+    }
+  }
+
+  onuPonDyingGaspExit();
+
+  onuEponPonMngDgMsgPrint();
+}
+
+#endif /* PON_FPGA */
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         MPC State Machine Handling Section                 */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponPonMngRegMsgFlagAck
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when REGISTER message with flag Ack is
+**               received
+**
+**  PARAMETERS:  S_OnuEponRegMpcFrame *mpcFrame
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngRegMsgFlagAck(S_OnuEponRegMpcFrame *mpcFrame)
+{
+  MV_STATUS status;
+  MV_U32    macId;
+  MV_U32    macState;
+  MV_U16    msgEtype;
+  MV_U16    msgSyncTime;
+  MV_U16    msgLlid;
+  MV_U16    msgOpcode;
+  MV_U8     msgFlags;
+  MV_U8     msgEchoedPendingGrants;
+  MV_U32    interruptMask;
+  LINKSTATUSFUNC linkStatusCallback;
+
+  status = matchDestAddressToMacId(mpcFrame->stdEthFrame.destAddr, &macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MAC_ADDR_MODULE,
+               "ERROR: (%s:%d) matchDestAddressToMacId, invalid dest addr [%02X:%02X:%02X:%02X:%02X:%02X]\n",
+               __FILE_DESC__, __LINE__,
+               mpcFrame->stdEthFrame.destAddr[0], mpcFrame->stdEthFrame.destAddr[1],
+               mpcFrame->stdEthFrame.destAddr[2], mpcFrame->stdEthFrame.destAddr[3],
+               mpcFrame->stdEthFrame.destAddr[4], mpcFrame->stdEthFrame.destAddr[5]);
+    return(MV_OK);
+  }
+
+  onuEponConvertN2HShort(&mpcFrame->stdEthFrame.etherType, &msgEtype);
+  onuEponConvertN2HShort(&mpcFrame->genMpcPdu.opCode, &msgOpcode);
+  onuEponConvertN2HShort(&mpcFrame->regMpcPdu.assignedLlidPort, &msgLlid);
+  onuEponConvertN2HShort(&mpcFrame->regMpcPdu.syncTime, &msgSyncTime);
+  msgFlags               = mpcFrame->regMpcPdu.flags;
+  msgEchoedPendingGrants = mpcFrame->regMpcPdu.echoedPendingGrants;
+
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE,
+             "\n"
+             "REGISTER [Flag=Ack] Message\n"
+             "===========================\n"
+             "DestMac[%x:%x:%x:%x:%x:%x] SrcMac[%x:%x:%x:%x:%x:%x]\n"
+             "Etype[0x%x] Opcode[%x] Sync[0x%x], LLID[%x] Grant[%x] Flag[%x]\n",
+             mpcFrame->stdEthFrame.destAddr[0], mpcFrame->stdEthFrame.destAddr[1],
+             mpcFrame->stdEthFrame.destAddr[2], mpcFrame->stdEthFrame.destAddr[3],
+             mpcFrame->stdEthFrame.destAddr[4], mpcFrame->stdEthFrame.destAddr[5],
+             mpcFrame->stdEthFrame.srcAddr[0], mpcFrame->stdEthFrame.srcAddr[1],
+             mpcFrame->stdEthFrame.srcAddr[2], mpcFrame->stdEthFrame.srcAddr[3],
+             mpcFrame->stdEthFrame.srcAddr[4], mpcFrame->stdEthFrame.srcAddr[5],
+             msgEtype,
+             msgOpcode,
+             msgSyncTime,
+             msgLlid,
+             msgEchoedPendingGrants,
+             msgFlags);
+
+  /* Validate mac state was updated by HW */
+  status = mvOnuEponMacOnuStateGet(&macState, macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) mvOnuEponMacOnuStateGet\n\r", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  if (macState != ONU_EPON_REGISTERED)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Mac[%d] state is not Registered!!!!\n\r", __FILE_DESC__, __LINE__, macId);
+    return(MV_ERROR);
+  }
+
+  onuEponApiFecReConfig();
+
+  if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_SW_DBA_RPRT_TIMER)
+  {
+	/* Set onu DBA Report interrupt */
+	mvOnuEponMacPonInterruptMaskGet(&interruptMask);
+	interruptMask |= (ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK);
+	mvOnuEponMacPonInterruptMaskSet(interruptMask);
+	onuEponDbaSwRprtMacTimerCfg(onuEponDbOnuSwRprtMacTimerIntervalGet());
+
+	/* Start SW DBA event miss timer */
+	onuEponIsrTimerEventMissStateSet(MV_TRUE);
+
+  }
+  else
+  {
+	onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+  }
+
+  onuEponDbPktTxLlidSet(msgLlid, macId);
+  onuEponDbPktRxLlidSet(msgLlid, macId);
+  onuEponDbOnuStateSet(ONU_EPON_03_OPERATION, macId);
+  onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_ON);
+
+#if 0 /* NOT USED */
+  status = onuEponAsicQueueEnable(macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuEponAsicQueueEnable\n\r", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+#endif /* NOT USED */
+
+  mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+             "= ONU Mac[%d] Registered =\n\r", macId);
+  if (macId == 0)
+  {
+     mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "==================\n");
+     mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "== MPCP Sync On ==\n");
+     mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE, "==================\n");
+  }
+
+  /* Call link status callback function */
+  linkStatusCallback = onuEponDbLinkStatusCallbackGet();
+  if (linkStatusCallback != NULL)
+  {
+    linkStatusCallback(MV_TRUE);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngRegMsgFlagNack
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when REGISTER message with flag Nack
+**               is received
+**
+**  PARAMETERS:  S_OnuEponRegMpcFrame *mpcFrame
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngRegMsgFlagNack(S_OnuEponRegMpcFrame *mpcFrame)
+{
+  MV_STATUS status;
+  MV_U32    macId;
+  MV_U16    msgEtype;
+  MV_U16    msgSyncTime;
+  MV_U16    msgLlid;
+  MV_U16    msgOpcode;
+  MV_U8     msgFlags;
+  MV_U8     msgEchoedPendingGrants;
+
+  status = matchDestAddressToMacId(mpcFrame->stdEthFrame.destAddr, &macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MAC_ADDR_MODULE,
+               "ERROR: (%s:%d) matchDestAddressToMacId, invalid dest addr [%02X:%02X:%02X:%02X:%02X:%02X]\n",
+               __FILE_DESC__, __LINE__,
+               mpcFrame->stdEthFrame.destAddr[0], mpcFrame->stdEthFrame.destAddr[1],
+               mpcFrame->stdEthFrame.destAddr[2], mpcFrame->stdEthFrame.destAddr[3],
+               mpcFrame->stdEthFrame.destAddr[4], mpcFrame->stdEthFrame.destAddr[5]);
+    return(MV_OK);
+  }
+
+  onuEponConvertN2HShort(&mpcFrame->stdEthFrame.etherType, &msgEtype);
+  onuEponConvertN2HShort(&mpcFrame->genMpcPdu.opCode, &msgOpcode);
+  onuEponConvertN2HShort(&mpcFrame->regMpcPdu.assignedLlidPort, &msgLlid);
+  onuEponConvertN2HShort(&mpcFrame->regMpcPdu.syncTime, &msgSyncTime);
+  msgFlags               = mpcFrame->regMpcPdu.flags;
+  msgEchoedPendingGrants = mpcFrame->regMpcPdu.echoedPendingGrants;
+
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE,
+             "\n"
+             "REGISTER [Flag=Nack] Message\n"
+             "============================\n"
+             "DestMac[%x:%x:%x:%x:%x:%x] SrcMac[%x:%x:%x:%x:%x:%x]\n"
+             "Etype[0x%x] Opcode[%x] Sync[0x%x], LLID[%x] Grant[%x] Flag[%x]\n",
+             mpcFrame->stdEthFrame.destAddr[0], mpcFrame->stdEthFrame.destAddr[1],
+             mpcFrame->stdEthFrame.destAddr[2], mpcFrame->stdEthFrame.destAddr[3],
+             mpcFrame->stdEthFrame.destAddr[4], mpcFrame->stdEthFrame.destAddr[5],
+             mpcFrame->stdEthFrame.srcAddr[0], mpcFrame->stdEthFrame.srcAddr[1],
+             mpcFrame->stdEthFrame.srcAddr[2], mpcFrame->stdEthFrame.srcAddr[3],
+             mpcFrame->stdEthFrame.srcAddr[4], mpcFrame->stdEthFrame.srcAddr[5],
+             msgEtype,
+             msgOpcode,
+             msgSyncTime,
+             msgLlid,
+             msgEchoedPendingGrants,
+             msgFlags);
+
+
+  if (onuEponDbOnuSilenceStateGet() != ONU_SILENCE_NOT_ACTIVE)
+  {
+    status  = mvOnuEponMacGenOnuConfigAutoAckSet(0);
+    status |= mvOnuEponMacGenOnuConfigAutoRequestSet(0);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+                 "ERROR: (%s:%d) Failed to disable auto request / ack\n\r", __FILE_DESC__, __LINE__);
+	  return(MV_ERROR);
+    }
+
+	onuEponDbOnuCfgAutoSet(ONU_REG_REQ_SW_RES, ONU_REG_ACK_SW_RES, ONU_REPORT_AUTO_RES);
+
+	onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonSilenceTimerId[macId]), macId, ONU_PON_TIMER_SILENCE_INTERVAL, 1);
+
+	mvPonPrint(PON_PRINT_DEBUG, PON_MNG_SILENCE_MODULE,
+			   "DEBUG: (%s:%d) Silence Timer Start\n", __FILE_DESC__, __LINE__);
+  }
+  else
+  {
+    onuEponPonMngAlarmHandlerExecute(macId);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngRegMsgFlagReReg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when REGISTER message with flag re-register
+**               is received
+**
+**  PARAMETERS:  S_OnuEponRegMpcFrame *mpcFrame
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngRegMsgFlagReReg(S_OnuEponRegMpcFrame *mpcFrame)
+{
+  MV_STATUS status;
+  MV_U32    macId;
+  MV_U32    macState;
+  MV_U16    msgEtype;
+  MV_U16    msgSyncTime;
+  MV_U16    msgLlid;
+  MV_U16    msgOpcode;
+  MV_U8     msgFlags;
+  MV_U8     msgEchoedPendingGrants;
+
+  status = matchDestAddressToMacId(mpcFrame->stdEthFrame.destAddr, &macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MAC_ADDR_MODULE,
+               "ERROR: (%s:%d) matchDestAddressToMacId, invalid dest addr [%02X:%02X:%02X:%02X:%02X:%02X]\n",
+               __FILE_DESC__, __LINE__,
+               mpcFrame->stdEthFrame.destAddr[0], mpcFrame->stdEthFrame.destAddr[1],
+               mpcFrame->stdEthFrame.destAddr[2], mpcFrame->stdEthFrame.destAddr[3],
+               mpcFrame->stdEthFrame.destAddr[4], mpcFrame->stdEthFrame.destAddr[5]);
+    return(MV_OK);
+  }
+
+  onuEponConvertN2HShort(&mpcFrame->stdEthFrame.etherType, &msgEtype);
+  onuEponConvertN2HShort(&mpcFrame->genMpcPdu.opCode, &msgOpcode);
+  onuEponConvertN2HShort(&mpcFrame->regMpcPdu.assignedLlidPort, &msgLlid);
+  onuEponConvertN2HShort(&mpcFrame->regMpcPdu.syncTime, &msgSyncTime);
+  msgFlags               = mpcFrame->regMpcPdu.flags;
+  msgEchoedPendingGrants = mpcFrame->regMpcPdu.echoedPendingGrants;
+
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE,
+             "\n"
+             "REGISTER [Flag=ReReg] Message\n"
+             "=============================\n"
+             "DestMac[%x:%x:%x:%x:%x:%x] SrcMac[%x:%x:%x:%x:%x:%x]\n"
+             "Etype[0x%x] Opcode[%x] Sync[0x%x], LLID[%x] Grant[%x] Flag[%x]\n",
+             mpcFrame->stdEthFrame.destAddr[0], mpcFrame->stdEthFrame.destAddr[1],
+             mpcFrame->stdEthFrame.destAddr[2], mpcFrame->stdEthFrame.destAddr[3],
+             mpcFrame->stdEthFrame.destAddr[4], mpcFrame->stdEthFrame.destAddr[5],
+             mpcFrame->stdEthFrame.srcAddr[0], mpcFrame->stdEthFrame.srcAddr[1],
+             mpcFrame->stdEthFrame.srcAddr[2], mpcFrame->stdEthFrame.srcAddr[3],
+             mpcFrame->stdEthFrame.srcAddr[4], mpcFrame->stdEthFrame.srcAddr[5],
+             msgEtype,
+             msgOpcode,
+             msgSyncTime,
+             msgLlid,
+             msgEchoedPendingGrants,
+             msgFlags);
+
+  /* Validate mac state was updated by HW */
+  status = mvOnuEponMacOnuStateGet(&macState, macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) mvOnuEponMacOnuStateGet\n\r", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  if (macState != ONU_EPON_REGISTERED)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Mac[%d] state is not Registered!!!!\n\r", __FILE_DESC__, __LINE__, macId);
+    return(MV_ERROR);
+  }
+
+  onuEponDbPktTxLlidSet(msgLlid, macId);
+  onuEponDbPktRxLlidSet(msgLlid, macId);
+  onuEponDbOnuStateSet(ONU_EPON_03_OPERATION, macId);
+  onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_ON);
+
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE,
+             "= ONU Mac[%d] Registered =\n\r", macId);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponPonMngRegMsgFlagDeReg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when REGISTER message with flag de-register
+**               is received
+**
+**  PARAMETERS:  S_OnuEponRegMpcFrame *mpcFrame
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponPonMngRegMsgFlagDeReg(S_OnuEponRegMpcFrame *mpcFrame)
+{
+  MV_STATUS status;
+  MV_U32    macId;
+  MV_U32    interruptMask;
+  MV_U16    msgEtype;
+  MV_U16    msgSyncTime;
+  MV_U16    msgLlid;
+  MV_U16    msgOpcode;
+  MV_U8     msgFlags;
+  MV_U8     msgEchoedPendingGrants;
+  LINKSTATUSFUNC linkStatusCallback;
+
+  status = matchDestAddressToMacId(mpcFrame->stdEthFrame.destAddr, &macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MAC_ADDR_MODULE,
+               "ERROR: (%s:%d) matchDestAddressToMacId, invalid dest addr [%02X:%02X:%02X:%02X:%02X:%02X]\n",
+               __FILE_DESC__, __LINE__,
+               mpcFrame->stdEthFrame.destAddr[0], mpcFrame->stdEthFrame.destAddr[1],
+               mpcFrame->stdEthFrame.destAddr[2], mpcFrame->stdEthFrame.destAddr[3],
+               mpcFrame->stdEthFrame.destAddr[4], mpcFrame->stdEthFrame.destAddr[5]);
+    return(MV_OK);
+  }
+
+  onuEponConvertN2HShort(&mpcFrame->stdEthFrame.etherType, &msgEtype);
+  onuEponConvertN2HShort(&mpcFrame->genMpcPdu.opCode, &msgOpcode);
+  onuEponConvertN2HShort(&mpcFrame->regMpcPdu.assignedLlidPort, &msgLlid);
+  onuEponConvertN2HShort(&mpcFrame->regMpcPdu.syncTime, &msgSyncTime);
+  msgFlags               = mpcFrame->regMpcPdu.flags;
+  msgEchoedPendingGrants = mpcFrame->regMpcPdu.echoedPendingGrants;
+
+  mvPonPrint(PON_PRINT_INFO, PON_MNG_MODULE,
+             "\n"
+             "REGISTER [Flag=DeReg] Message\n"
+             "=============================\n"
+             "DestMac[%x:%x:%x:%x:%x:%x] SrcMac[%x:%x:%x:%x:%x:%x]\n"
+             "Etype[0x%x] Opcode[%x] Sync[0x%x], LLID[%x] Grant[%x] Flag[%x]\n",
+             mpcFrame->stdEthFrame.destAddr[0], mpcFrame->stdEthFrame.destAddr[1],
+             mpcFrame->stdEthFrame.destAddr[2], mpcFrame->stdEthFrame.destAddr[3],
+             mpcFrame->stdEthFrame.destAddr[4], mpcFrame->stdEthFrame.destAddr[5],
+             mpcFrame->stdEthFrame.srcAddr[0], mpcFrame->stdEthFrame.srcAddr[1],
+             mpcFrame->stdEthFrame.srcAddr[2], mpcFrame->stdEthFrame.srcAddr[3],
+             mpcFrame->stdEthFrame.srcAddr[4], mpcFrame->stdEthFrame.srcAddr[5],
+             msgEtype,
+             msgOpcode,
+             msgSyncTime,
+             msgLlid,
+             msgEchoedPendingGrants,
+             msgFlags);
+
+  if (onuEponDbOnuSwRprtTimerTypeGet() == ONU_EPON_SW_DBA_RPRT_TIMER)
+  {
+	/* Stop SW DBA event miss timer */
+	onuEponIsrTimerEventMissStateSet(MV_FALSE);
+
+	/* Clear onu DBA Report interrupt */
+	mvOnuEponMacPonInterruptMaskGet(&interruptMask);
+	interruptMask &= ~(ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK);
+	mvOnuEponMacPonInterruptMaskSet(interruptMask);
+  }
+  else
+  {
+	/* Clear onu DBA Report Timer */
+	onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonHwRprtTimerId));
+  }
+
+  /* re-init onu database */
+  status = onuEponDbReInit(macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Failed to re-init onu database\n\r", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  /* init onu Asic */
+  status = onuEponAsicReInit(macId, ONU_SILENCE_ENABLED);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Failed to re-init onu EPON MAC\n\r", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  /* Call link status callback function */
+  linkStatusCallback = onuEponDbLinkStatusCallbackGet();
+  if (linkStatusCallback != NULL)
+  {
+    if (onuEponForceTxDownStateGet(0) != MV_TRUE)
+      linkStatusCallback(MV_FALSE);
+  }
+
+  /* send signal to management layer */
+  onuEponStatusNotify(0/*don't care*/);
+
+  return(MV_OK);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         MPC Message Handling Section                       */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponReadCtrlFrameData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function read control frame from the Rx Control queue
+**
+**  PARAMETERS:  S_OnuEponCtrlBuffer *ctrlBuf
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponReadCtrlFrameData(S_OnuEponCtrlBuffer *ctrlBuf)
+{
+  MV_STATUS status;
+  MV_U32    usedCount;
+  MV_U32    data;
+  MV_U32    index;
+
+  status = mvOnuEponMacCpqRxCtrlQueueUsedCountGet(&usedCount);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Read Rx Ctrl Queue Used Count\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  if (usedCount < ctrlBuf->length)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Not enough data,  Frame Length = %d, usedCount = %d\n\r",
+               __FILE_DESC__, __LINE__, ctrlBuf->length, usedCount);
+    return(MV_ERROR);
+  }
+
+  for(index = 0; index < ctrlBuf->length; index++)
+  {
+    status = mvOnuEponMacCpqRxCtrlQueueReadData(&data);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+                 "ERROR: (%s:%d) Read Rx Ctrl Queue Data\n\r", __FILE_DESC__, __LINE__);
+      return(status);
+    }
+    else
+    {
+      ctrlBuf->data[index] = (MV_U8)data;
+    }
+  }
+
+  onuEponPmSwRxCountersAdd(TOTAL_MPCP_RX_FRAME_CNT, 0);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponRetrieveCtrlFrameData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function retrieve control frame from the Rx Control queue
+**
+**  PARAMETERS:  S_OnuEponCtrlBuffer *ctrlBuf
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponRetrieveCtrlFrameData(S_OnuEponCtrlBuffer *ctrlBuf)
+{
+  MV_STATUS status;
+  MV_U32    usedHeaderCount;
+  MV_U32    flagLow;
+  MV_U32    flagHigh;
+  MV_U32    frameLength;
+
+  ctrlBuf->length = 0;
+
+  status = mvOnuEponMacCpqRxCtrlHeaderQueueUsedCountGet(&usedHeaderCount);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Read Rx Ctrl Header Queue Used Count\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  if (usedHeaderCount <= 0)
+  {
+    return(MV_ERROR);
+  }
+
+  status = mvOnuEponMacCpqRxCtrlHeaderQueueReadData(&flagLow, &flagHigh);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Read Rx Ctrl Header Queue Data\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  frameLength = ((flagLow & MPC_FRAME_LENGTH_MASK) >> MPC_FRAME_LENGTH_SHIFT);
+  if ((frameLength > 0) && (frameLength <= sizeof(ctrlBuf->data)))
+  {
+    ctrlBuf->length = frameLength;
+    status = onuEponReadCtrlFrameData(ctrlBuf);
+    if (status != MV_OK)
+    {
+      return(status);
+    }
+  }
+  else
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Unexpected frame length %d\n\r", __FILE_DESC__, __LINE__, frameLength);
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponSendCtrlFrameData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function check for free space for transmission of control frame
+**
+**  PARAMETERS:  MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_TRUE or MV_FALSE
+**
+*******************************************************************************/
+MV_BOOL onuEponSendCtrlFrameDataFreeStatus(MV_U32 macId)
+{
+  MV_STATUS status;
+  MV_U32    numFreeFrames;
+  MV_U32    numFreeData;
+
+  status = mvOnuEponMacCpqTxCtrlHeaderQueueFree(&numFreeFrames, macId);
+  if (status != MV_OK)
+    return(MV_FALSE);
+
+  status = mvOnuEponMacCpqTxCtrlQueueFree(&numFreeData, macId);
+  if (status != MV_OK)
+    return(MV_FALSE);
+
+  if ((numFreeFrames <= 0) || (numFreeData < 256))
+    return(MV_FALSE);
+
+  return(MV_TRUE);
+}
+
+/*******************************************************************************
+**
+**  onuEponSendCtrlFrameData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function send control frame to the Tx Control queue
+**
+**  PARAMETERS:  S_OnuEponCtrlBuffer *ctrlBuf
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponSendCtrlFrameData(S_OnuEponCtrlBuffer *ctrlBuf, MV_U32 macId)
+{
+  MV_STATUS status;
+  MV_U32    numFreeFrames;
+  MV_U32    numFreeData;
+  MV_U32    index;
+
+  status = mvOnuEponMacCpqTxCtrlHeaderQueueFree(&numFreeFrames, macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Read Tx Ctrl Header Queue\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  status = mvOnuEponMacCpqTxCtrlQueueFree(&numFreeData, macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Read Tx Ctrl Queue\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  if (numFreeFrames <= 0)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+    		   "ERROR: (%s:%d) No free place in Tx Ctrl Header Queue (%d), data(%d)\n\r",
+    		   __FILE_DESC__, __LINE__, numFreeFrames, numFreeData);
+    return(MV_ERROR);
+  }
+
+  if (numFreeData < ctrlBuf->length)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) No free place in Tx Ctrl Data Queue\n\r", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  for(index = 0; index < ctrlBuf->length; index++)
+  {
+    status = mvOnuEponMacCpqTxCtrlQueueWrite(ctrlBuf->data[index], macId);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+                 "ERROR: (%s:%d) Write Tx Ctrl Queue Data\n\r", __FILE_DESC__, __LINE__);
+      return(status);
+    }
+  }
+
+  status = mvOnuEponMacCpqTxCtrlHeaderQueueWrite(ctrlBuf->length, macId);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Write Tx Ctrl Header Queue\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  onuEponPmSwTxCountersAdd(TOTAL_MPCP_TX_FRAME_CNT, macId);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponReadReportFrameData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function read report frame from the Rx report queue
+**
+**  PARAMETERS:  S_OnuEponCtrlBuffer *ctrlBuf
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponReadReportFrameData(S_OnuEponCtrlBuffer *ctrlBuf)
+{
+  MV_STATUS status;
+  MV_U32    usedCount;
+  MV_U32    data;
+  MV_U32    index;
+
+  status = mvOnuEponMacCpqRxRprtQueueUsedCountGet(&usedCount);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Read Rx Report Queue Used Count\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  if (usedCount < ctrlBuf->length)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Not enough data,  Frame Length = %i, usedCount = %i\n\r",
+               __FILE_DESC__, __LINE__, ctrlBuf->length, usedCount);
+    return(MV_ERROR);
+  }
+
+  for(index = 0; index < usedCount; index++)
+  {
+    status = mvOnuEponMacCpqRxRprtQueueReadData(&data);
+    if (status != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+                 "ERROR: (%s:%d) Read Rx Report Queue Data\n\r", __FILE_DESC__, __LINE__);
+      return(status);
+    }
+    else
+    {
+      ctrlBuf->data[index] = (MV_U8)data;
+    }
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponRetrieveReportFrameData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function retrieve report frame from the Rx report queue
+**
+**  PARAMETERS:  S_OnuEponCtrlBuffer *ctrlBuf
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponRetrieveReportFrameData(S_OnuEponCtrlBuffer *ctrlBuf)
+{
+  MV_STATUS status;
+  MV_U32    usedHeaderCount;
+  MV_U32    flagLow;
+  MV_U32    flagHigh;
+  MV_U32    frameLength;
+
+  ctrlBuf->length = 0;
+
+  status = mvOnuEponMacCpqRxRprtHeaderQueueUsedCountGet(&usedHeaderCount);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Read Rx Report Header Queue Used Count\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  if (usedHeaderCount <= 0)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) No frames received,  Used Header Count = %i\n\r",
+               __FILE_DESC__, __LINE__, usedHeaderCount);
+    return(MV_ERROR);
+  }
+
+  status = mvOnuEponMacCpqRxRprtHeaderQueueReadData(&flagLow, &flagHigh);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Read Rx Report Header Queue Data\n\r", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  frameLength = flagLow & MPC_FRAME_LENGTH_MASK;
+  if (frameLength > 0 && frameLength <= sizeof(ctrlBuf->data))
+  {
+    ctrlBuf->length = frameLength;
+    status = onuEponReadReportFrameData(ctrlBuf);
+    if (status != MV_OK)
+    {
+      return(status);
+    }
+  }
+  else
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+               "ERROR: (%s:%d) Unexpected frame length %d\n\r", __FILE_DESC__, __LINE__, frameLength);
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponConvertN2HShort
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function convert MV_U16 from Netwotk order to Host
+**
+**  PARAMETERS:  void *srcValPtr
+**               void *destValPtr
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponConvertN2HShort(void *srcValPtr, void *destValPtr)
+{
+  MV_U16 src;
+  MV_U16 dest;
+
+  memcpy(&src, srcValPtr, sizeof(src));
+
+  dest = ((src       & 0xFF) << 8) |
+         ((src >> 8) & 0xFF);
+
+  memcpy(destValPtr, &dest, sizeof(dest));
+}
+
+/*******************************************************************************
+**
+**  onuEponConvertH2NShort
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function convert MV_U16 from Host order to Network
+**
+**  PARAMETERS:  void *srcValPtr
+**               void *destValPtr
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponConvertH2NShort(void *srcValPtr, void *destValPtr)
+{
+  MV_U16 src;
+  MV_U16 dest;
+
+  memcpy(&src, srcValPtr, sizeof(src));
+
+  dest = ((src       & 0xFF) << 8) |
+         ((src >> 8) & 0xFF);
+
+  memcpy(destValPtr, &dest, sizeof(dest));
+}
+
+/*******************************************************************************
+**
+**  onuEponConvertN2HLong
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function convert MV_U32 from Netwotk order to Host
+**
+**  PARAMETERS:  void *srcValPtr
+**               void *destValPtr
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponConvertN2HLong(void *srcValPtr, void *destValPtr)
+{
+  MV_U32 src;
+  MV_U32 dest;
+
+  memcpy(&src, srcValPtr, sizeof(src));
+
+  dest =  ((src        & 0xFF) << 24) |
+         (((src >>  8) & 0xFF) << 16) |
+         (((src >> 16) & 0xFF) <<  8) |
+          ((src >> 24) & 0xFF);
+
+  memcpy(destValPtr, &dest, sizeof(dest));
+}
+
+/*******************************************************************************
+**
+**  onuEponConvertH2NLong
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function convert MV_U32 from Host order to Network
+**
+**  PARAMETERS:  void *srcValPtr
+**               void *destValPtr
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponConvertH2NLong(void *srcValPtr, void *destValPtr)
+{
+  MV_U32 src;
+  MV_U32 dest;
+
+  memcpy(&src, srcValPtr, sizeof(src));
+
+  dest =  ((src        & 0xFF) << 24) |
+         (((src >>  8) & 0xFF) << 16) |
+         (((src >> 16) & 0xFF) <<  8) |
+          ((src >> 24) & 0xFF);
+
+  memcpy(destValPtr, &dest, sizeof(dest));
+}
+
+/*******************************************************************************
+**
+**  onuEponOamHandleMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function transmit OAM frames from SW FIFO
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponOamHandleMsg(void)
+{
+  MV_STATUS        status;
+  MV_U8  		   nextOamMsgReadIndex;
+  S_OnuEponOamMsg *oamMsg;
+
+  if (oamMsgReadIndex != oamMsgWriteIndex)
+  {
+    nextOamMsgReadIndex = oamMsgReadIndex + 1;
+    /* roll over */
+    if (nextOamMsgReadIndex == OAM_MSG_FIFO_LENGTH)
+    {
+      nextOamMsgReadIndex = 0;
+    }
+    oamMsg = (S_OnuEponOamMsg*)(&(oamMsgData[nextOamMsgReadIndex]));
+
+	if(onuEponSendCtrlFrameDataFreeStatus(oamMsg->macId) != MV_TRUE)
+	  return(MV_OK);
+
+	/* Send OAM message to queue */
+	status = onuEponSendCtrlFrameData(&(oamMsg->msg), oamMsg->macId);
+	if (status != MV_OK)
+	{
+	  mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+				 "ERROR: (%s:%d) onuEponSendCtrlFrameData OAM", __FILE_DESC__, __LINE__);
+	  return(status);
+	}
+
+	oamMsgReadIndex = nextOamMsgReadIndex;
+	mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+               "Handle read(%d) write(%d)\n", oamMsgReadIndex, oamMsgWriteIndex);
+
+	return(MV_OK);
+  }
+
+  return(OAM_MSG_NOT_TRANS);
+}
+
+/*******************************************************************************
+**
+**  onuEponOamFlushAllMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function flush OAM frames from SW FIFO
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponOamFlushAllMsg(void)
+{
+  oamMsgReadIndex = oamMsgWriteIndex;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponOamAllocMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function allocate OAM frame for transmission
+**
+**  PARAMETERS:  S_OnuEponOamMsg *msg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponOamAllocMsg(S_OnuEponCtrlBuffer *msg, MV_U32 macId)
+{
+  MV_U8 nextOamMsgWriteIndex;
+
+  if ((oamMsgWriteIndex + 1) != oamMsgReadIndex)
+  {
+    nextOamMsgWriteIndex = oamMsgWriteIndex + 1;
+    /* roll over */
+    if(nextOamMsgWriteIndex == OAM_MSG_FIFO_LENGTH) nextOamMsgWriteIndex = 0;
+
+	/* update OAM message to the FIFO */
+	oamMsgData[nextOamMsgWriteIndex].macId = macId;
+    memcpy (&(oamMsgData[nextOamMsgWriteIndex].msg), msg, sizeof (S_OnuEponCtrlBuffer));
+
+	/* update index */
+    oamMsgWriteIndex = nextOamMsgWriteIndex;
+
+	mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+	           "Alloc read(%d) write(%d\n", oamMsgReadIndex, oamMsgWriteIndex);
+
+	if (((oamMsgWriteIndex > oamMsgReadIndex)              &&
+		((oamMsgWriteIndex - oamMsgReadIndex) > 2))        ||
+		((oamMsgWriteIndex < oamMsgReadIndex)              &&
+		((OAM_MSG_FIFO_LENGTH - (oamMsgReadIndex - oamMsgWriteIndex)) > 2)))
+	{
+	  onuEponOamHandleMsg();
+	  onuEponDbaSwRprtMacTimerCfg(62500);
+	}
+  }
+  else
+  {
+	return (MV_ERROR);
+  }
+
+  return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponDgHandleMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function transmit DG OAM frame from SW FIFO
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+//MV_STATUS onuEponDgHandleMsg(void)
+//{
+//  MV_STATUS status;
+//
+//  if (oamDgMsgQueue.valid == OAM_MSG_DG_IND)
+//  {
+//	do
+//	{
+//	  status = onuEponSendCtrlFrameData(&oamDgMsgQueue.msg, oamDgMsgQueue.macId);
+//	}while (status != MV_OK);
+//
+//	return(status);
+//  }
+//
+//  return(OAM_MSG_NOT_TRANS);
+//}
+
+/*******************************************************************************
+**
+**  onuEponDgAllocMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function allocate DG OAM frame for transmission
+**
+**  PARAMETERS:  S_OnuEponCtrlBuffer *ctrlBuf
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+//MV_STATUS onuEponDgAllocMsg(S_OnuEponCtrlBuffer *ctrlBuf, MV_U32 macId)
+//{
+//  memcpy(&(oamDgMsgQueue.msg), ctrlBuf, sizeof(S_OnuEponCtrlBuffer));
+//  oamDgMsgQueue.macId = macId;
+//  oamDgMsgQueue.valid = OAM_MSG_DG_IND;
+//
+//  return(MV_OK);
+//}
+
+/*******************************************************************************
+**
+**  onuEponDbaModeInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns EPON PHY output register value
+**
+**  PARAMETERS:  dbaMode either ONU_DBA_HW_RPRT_MODE or ONU_DBA_SW_RPRT_MODE
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_U32 status
+**
+*******************************************************************************/
+MV_STATUS onuEponDbaModeInit(MV_32 dbaMode)
+{
+	MV_U32    macId;
+	MV_U32    queueId;
+	MV_U32    currentDbaMode;
+	MV_U32    interruptMask;
+	MV_STATUS status = MV_OK;
+
+	currentDbaMode = onuEponDbOnuDbaModeGet();
+	if (currentDbaMode == dbaMode)
+		return(MV_OK);
+
+	switch (dbaMode) {
+
+	case ONU_DBA_HW_RPRT_MODE:
+
+		/* Stop SW DBA event miss timer */
+		onuEponIsrTimerEventMissStateSet(MV_FALSE);
+
+		/* Clear DBA Report interrupt */
+		mvOnuEponMacPonInterruptMaskGet(&interruptMask);
+		interruptMask &= ~(ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK);
+		mvOnuEponMacPonInterruptMaskSet(interruptMask);
+
+		/* Configure MAC DBA Report Registers */
+		for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {
+
+			status  = mvOnuEponMacTxmCppReportConfig(0xFF,	 /* Queueset2 not supported -
+										set to 0xFF (queueReportQ2) */
+								 0x1,	 /* Queueset2 not supported -
+										set to 0x1, Software (reportBitmapQ2) */
+								 0x0,	 /* Queueset1 supported -
+										set to 0, means all 8 queues
+										are active (queueReport) */
+								 0x1,	 /* Number of queueSet -
+										support for 1 queueset */
+								 0x1,	 /* Queueset1 supported -
+										set to 0x1, Software (reportBitmap) */
+								 macId);
+
+			status |= mvOnuEponMacTxmCppReportBitMap(0x00FF, macId); /* Queueset1 - 8 queues enabled(0xFF),
+											8 queues disabled(0x00) */
+			status |= mvOnuEponMacTxmCppReportQueueSet(0x1, macId);	 /* Number of queuesets -
+											support for 1 queueset */
+
+			for (queueId = 0; queueId < 7; queueId++)
+				status |= mvOnuEponMacTxmCppReportQueueX(queueId, 0x03FF, macId);
+
+			status |= mvOnuEponMacTxmCppReportQueueX(queueId, 0x53FF, macId);
+			if (status != MV_OK) {
+				mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+					   "ERROR: (%s:%d) mvOnuEponMacTxmCppReport...\n\r", __FILE_DESC__, __LINE__);
+				break;
+			}
+		}
+
+		/* Set HW DBA mode */
+		onuEponDbOnuSwRprtTimerTypeSet(ONU_EPON_HW_DBA_RPRT_TIMER);
+
+		/* Start HW DBA Tx module timer */
+		onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonHwRprtTxModTimerId));
+
+		/* Enable HW DBA Report message handling */
+		onuEponIsrTimerHwReportStateSet(MV_TRUE, /* Enable */
+						dbaRprtT0StateVal,
+						dbaRprtT0StateInterval,
+						dbaRprtT1StateVal,
+						dbaRprtT1StateInterval);
+		break;
+
+	case ONU_DBA_SW_RPRT_MODE:
+
+		/* Disable HW DBA Report message handling */
+		onuEponIsrTimerHwReportStateSet(MV_FALSE,
+						dbaRprtT0StateVal,
+						dbaRprtT0StateInterval,
+						dbaRprtT1StateVal,
+						dbaRprtT1StateInterval);
+
+		/* Disable HW DBA Tx module timer */
+		onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonHwRprtTxModTimerId));
+
+		/* Set SW DBA mode */
+		onuEponDbOnuSwRprtTimerTypeSet(ONU_EPON_SW_DBA_RPRT_TIMER);
+
+		/* Set SW DBA report update interval - 1 msec */
+		onuEponDbOnuSwRprtMacTimerIntervalSet(62500);
+		onuEponDbaSwRprtMacTimerCfg(onuEponDbOnuSwRprtMacTimerIntervalGet());
+
+		/* Set SW DBA Report interrupt */
+		mvOnuEponMacPonInterruptMaskGet(&interruptMask);
+		interruptMask |= (ONU_EPON_TIMESTAMP_VALUE_MATCH_MASK);
+		mvOnuEponMacPonInterruptMaskSet(interruptMask);
+
+		/* Start SW DBA event miss timer */
+		onuEponIsrTimerEventMissStateSet(MV_TRUE);
+
+		for (status = MV_OK, macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {
+			status |= mvOnuEponMacTxmCppReportConfig(0xFF,	/* Queueset2 not supported -
+									 * set to 0xFF (queueReportQ2) */
+								 0x1,	/* Queueset2 not supported -
+									 * set to 0x1, Software (reportBitmapQ2)
+									 */
+								 0xFF,	/* Queueset1 supported -
+									 * set to 0, means all 8 queues
+									 * are active (queueReport) */
+								 0x1,	/* Number of queueSet -
+									 * support for 1 queueset */
+								 0x1,	/* Queueset1 supported -
+									 * set to 0x1, Software (reportBitmap)
+									 */
+								 macId);
+		}
+
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+				   "ERROR: (%s:%d) onuEponDbaModeInit...\n\r", __FILE_DESC__, __LINE__);
+			return(MV_ERROR);
+		}
+		break;
+
+	default:
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuEponDbaModeInit: Wrong DBA mode!\n\r", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	onuEponDbOnuDbaModeSet(dbaMode);
+
+	return(status);
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.h
new file mode 100755
index 0000000..7db46f0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuMngr.h
@@ -0,0 +1,137 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************/
+/**                                                                          **/
+/**  MODULE      : ONU GPON                                                  **/
+/**                                                                          **/
+/**  FILE        : eponOnuMngr.h                                             **/
+/**                                                                          **/
+/**  DESCRIPTION : This file contains ONU EPON Manager definitions           **/
+/**                                                                          **/
+/******************************************************************************
+ *                                                                            *
+ *  MODIFICATION HISTORY:                                                     *
+ *                                                                            *
+ *   26Jan10  oren_ben_hayun    created                                       *
+ * ========================================================================== *
+ *
+ ******************************************************************************/
+#ifndef _ONU_EPON_MNGR_H
+#define _ONU_EPON_MNGR_H
+
+/* Include Files
+------------------------------------------------------------------------------*/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define MPC_FRAME_LENGTH_MASK  (0x000000FF)
+#define MPC_FRAME_LENGTH_SHIFT (0)
+
+#define ALL_MAC_INDICATION     (0xFF)
+
+/* Enums
+------------------------------------------------------------------------------*/
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+/* Interrupt handler Functions */
+void onuEponPonMngIntrAlarmHandler(MV_U32 alarm, MV_BOOL alarmStatus);
+void onuEponPonMngIntrRegHandler(MV_U32 reg, MV_BOOL regStatus);
+void onuEponPonMngIntrMessageHandler(MV_U32 msg);
+void onuEponPonMngIntrRxCtrlFifoCleanup(void);
+void onuEponPonMngTxCtrlMessageHandler(void);
+void onuEponPonMngHwRprtMessageHandler(void);
+void onuEponPonMngSwRprtMessageHandler(void);
+
+void onuEponPonMngDbaDgSwRprtCfg(MV_U32 numOfQueue, MV_U32 queueReport);
+
+#ifndef PON_FPGA
+void onuEponPonMngIntrDgHandler(void);
+#endif /* PON_FPGA */
+void onuEponPonMngAlarmHandlerExecute(MV_U32 macId);
+
+MV_STATUS onuEponAppInit(void);
+MV_STATUS onuEponOamHandleMsg(void);
+MV_STATUS onuEponOamFlushAllMsg(void);
+MV_STATUS onuEponOamAllocMsg(S_OnuEponCtrlBuffer *msg, MV_U32 macId);
+//MV_STATUS onuEponDgHandleMsg(void);
+//MV_STATUS onuEponDgAllocMsg(S_OnuEponCtrlBuffer *ctrlBuf, MV_U32 macId);
+MV_STATUS onuEponDbaModeInit(MV_32 dba_mode);
+MV_STATUS onuEponDbaInfoUpdate(MV_U32 macId);
+
+void      onuEponPonMngTimerSilenceHndl(unsigned long data);
+void      onuEponPonMngTimerHwRprtTxModHndl(unsigned long data);
+MV_STATUS onuEponPonMngTimerHwRprtCfg(MV_U32 t0_val, MV_U32 t0_time, MV_U32 t1_val, MV_U32 t1_time);
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _ONU_EPON_MNGR_H */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuPm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuPm.c
new file mode 100755
index 0000000..97c3937
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuPm.c
@@ -0,0 +1,1026 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU GPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuPm.c                                               **/

+/**                                                                          **/

+/**  DESCRIPTION : This file implements ONU EPON Alarm and Statistics        **/

+/**                functionality                                             **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *  

+ *                                                                            

+ ******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "eponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/                                               

+#define __FILE_DESC__ "mv_pon/core/epon/eponOnuPm.c"

+

+#define POLYNOMIAL (0x04c11db7)

+

+/* Macro based on "TXQn Number Of Bytes" register group offset formula (registers TXQ0Bytes, TXQ1Bytes,...TXQ7Bytes) */

+#define MV_PON_GUNIT_TX_N_QUEUES(llid, queue)	(0xA5900 + (llid%2) * 0x400 + (llid/2) * 0x2000 + queue * 4)

+

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+S_EponPm g_OnuEponPm[EPON_MAX_MAC_NUM];

+S_SwPm   g_OnuEponSwPm[EPON_MAX_MAC_NUM];

+MV_U32   g_OnuEponSwPmAddCntPerLlidAndQueue[EPON_MAX_MAC_NUM][EPON_MAX_QUEUE];

+MV_U32   g_OnuEponSwPmAddCntPerLlidFifo[EPON_MAX_MAC_NUM];

+

+#define GPON_RANDOM_ARR_SZ	8

+#define GPON_RANDOM_VAL_ARR_SZ	256

+MV_U32   g_OnuEponRandomNum[GPON_RANDOM_ARR_SZ] = {0, 0, 0, 0, 0, 0, 0, 0};

+MV_U32   g_OnuEponRandomCount = 0;

+MV_U32   g_OnuEponRandomValues[GPON_RANDOM_VAL_ARR_SZ] = {0};

+

+static MV_U32 crc_table[256];

+

+extern spinlock_t onuPonIrqLock;

+

+/* Global functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponPmSwCountersUpdate(S_SwPm *swPm, MV_U32 macId);

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Statistics Section                                 */

+/* ========================================================================== */

+/******************************************************************************/

+

+/*******************************************************************************

+**

+**  onuEponPmInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function init the onu epon pm table

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**                   

+*******************************************************************************/

+void onuEponPmInit(void)

+{

+  MV_U32 index;

+  

+  /* reset all counters */

+  memset(&g_OnuEponPm,   0, sizeof(S_EponPm) * EPON_MAX_MAC_NUM);

+  memset(&g_OnuEponSwPm, 0, sizeof(S_SwPm)   * EPON_MAX_MAC_NUM);

+  memset(g_OnuEponSwPmAddCntPerLlidAndQueue, 0, (sizeof(MV_U32) * EPON_MAX_MAC_NUM * EPON_MAX_QUEUE));

+

+  for (index = 0; index < EPON_MAX_MAC_NUM; index++) 

+    g_OnuEponSwPmAddCntPerLlidFifo[index] = 4000;  

+

+  /* generate crc table */

+  onuEponPmGenCrcTable();

+

+  mvOnuEponMacGenLocalTimeStampGet(&g_OnuEponRandomNum[0]);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmTimerPmHndl

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function is called by the EPON PM timer

+**               

+**  PARAMETERS:  unsigned long data

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuEponPmTimerPmHndl(unsigned long data)

+{

+  unsigned long flags;

+

+  spin_lock_irqsave(&onuPonIrqLock, flags);

+  onuPonResourceTbl_s.onuPonPmTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;

+  spin_unlock_irqrestore(&onuPonIrqLock, flags);

+

+  /* Call PM handler */

+  onuEponPmTimerExpireHndl();

+

+  spin_lock_irqsave(&onuPonIrqLock, flags);

+  if ((onuPonResourceTbl_s.onuPonPmTimerId.onuPonTimerPeriodic) != 0) 

+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonPmTimerId));

+  spin_unlock_irqrestore(&onuPonIrqLock, flags);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmTimerExpireHndl

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: This routine execute PM handler functionality                          

+**                

+**  PARAMETERS:  None  

+**                   

+**  OUTPUTS:     None 

+**                   

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuEponPmTimerExpireHndl(void)

+{

+  onuEponPmCountersAdd();

+}

+

+/*******************************************************************************

+**

+**  onuEponPmCountersAdd

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: This routine read statistics values from ASIC to the database                             

+**                 

+**  PARAMETERS:  None  

+**                   

+**  OUTPUTS:     None 

+**                   

+**  RETURNS:     MV_OK 

+**

+*******************************************************************************/

+MV_STATUS onuEponPmCountersAdd(void)

+{

+  MV_U32 counter;

+  MV_U32 llidTxFecState;

+  MV_U32 macId;

+  S_PcsPm statCounters;

+

+

+  /* Rx Counters - One set of counters for all MACs */

+  /* ============================================== */

+  mvOnuEponMacRxStatsFcsErrorGet(&counter, 0);          /* Count number of received frames with FCS errors */

+  g_OnuEponPm[0].rx.fcsErrorFramesCnt += counter;                                                             

+  mvOnuEponMacRxStatsShortErrorGet(&counter, 0);        /* Count number of short frames received */

+  g_OnuEponPm[0].rx.shortFramesCnt += counter;                                                     

+  mvOnuEponMacRxStatsLongErrorGet(&counter, 0);         /* Count number of long frames received */

+  g_OnuEponPm[0].rx.longFramesCnt += counter;                                                     

+  mvOnuEponMacRxStatsDataFrameGet(&counter, 0);         /* Count number of data frames received */

+  g_OnuEponPm[0].rx.dataFramesCnt += counter;                                                                

+  mvOnuEponMacRxStatsCtrlFrameGet(&counter, 0);         /* Count number of control frames received */

+  g_OnuEponPm[0].rx.ctrlFramesCnt += counter;                       

+  mvOnuEponMacRxStatsReportFrameGet(&counter, 0);       /* Count number of report frames received */

+  g_OnuEponPm[0].rx.reportFramesCnt += counter;                                                     

+  mvOnuEponMacRxStatsGateFrameGet(&counter, 0);         /* Count number of gate frames received */

+  g_OnuEponPm[0].rx.gateFramesCnt += counter;    

+

+	/* PCS Stats counters - one for all MACs */

+	mvOnuEponMacPcsStatsGet(&statCounters.legalFrameCnt,

+				&statCounters.maxFrameSizeErrCnt,

+				&statCounters.parityLenErrCnt,

+				&statCounters.longGateErrCnt,

+				&statCounters.protocolErrCnt,

+				&statCounters.minFrameSizeErrCnt,

+				&statCounters.legalFecFrameCnt,

+				&statCounters.legalNonFecFrameCnt);

+

+	g_OnuEponPm[0].pcs.legalFrameCnt += statCounters.legalFrameCnt;

+	g_OnuEponPm[0].pcs.maxFrameSizeErrCnt += statCounters.maxFrameSizeErrCnt;

+	g_OnuEponPm[0].pcs.parityLenErrCnt += statCounters.parityLenErrCnt;

+	g_OnuEponPm[0].pcs.longGateErrCnt += statCounters.longGateErrCnt;

+	g_OnuEponPm[0].pcs.protocolErrCnt += statCounters.protocolErrCnt;

+	g_OnuEponPm[0].pcs.minFrameSizeErrCnt += statCounters.minFrameSizeErrCnt;

+	g_OnuEponPm[0].pcs.legalFecFrameCnt += statCounters.legalFecFrameCnt;

+	g_OnuEponPm[0].pcs.legalNonFecFrameCnt += statCounters.legalNonFecFrameCnt;

+

+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) 

+  {   

+    /* Tx Counters */

+    /* =========== */

+    mvOnuEponMacTxStatsCtrlRegReqFrameGet(&counter, macId);   /* Count number of register request frames transmitted */    

+    g_OnuEponPm[macId].tx.ctrlRegReqFramesCnt += counter;                                                                  

+    mvOnuEponMacTxStatsCtrlRegAckFrameGet(&counter, macId);   /* Count number of register acknowledge frames transmitted */

+    g_OnuEponPm[macId].tx.ctrlRegAckFramesCnt += counter;                                                                  

+    mvOnuEponMacTxStatsCtrlReportFrameGet(&counter, macId);   /* Count number of report frames transmitted */              

+    g_OnuEponPm[macId].tx.reportFramesCnt += counter;                                                                      

+    mvOnuEponMacTxStatsTxAllowedByteCountGet(&counter, macId) /* Count number of Tx Byte Allow counter */                  ;

+    g_OnuEponPm[macId].tx.txAllowedBytesCnt += counter;   

+

+	/* update counters in case FEC is disabled */

+	onuEponDbOnuTxFecCfgGet(&llidTxFecState, macId);

+	if (llidTxFecState == 0) 

+	{

+	  mvOnuEponMacTxStatsDataFrameGet(&counter, macId);         /* Count number of data frames transmitted */                

+	  g_OnuEponPm[macId].tx.dataFramesCnt += counter;                                                                        

+	}

+

+    /* Sw Counters */

+    /* =========== */

+    onuEponPmSwCountersUpdate(&g_OnuEponPm[macId].sw, macId); 

+

+    /* Gpm Counters */

+    /* ============ */

+    mvOnuEponMacGpmGrantValidCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.grantValidCnt += counter;                 

+    mvOnuEponMacGpmGrantMaxFutureTimeErrorCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.grantMaxFutureTimeErrorCnt += counter;    

+    mvOnuEponMacGpmMinProcTimeErrorCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.minProcTimeErrorCnt += counter;          

+    mvOnuEponMacGpmLengthErrorCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.lengthErrorCnt += counter;                

+    mvOnuEponMacGpmDiscoveryAndRegisterCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.discoveryAndRegCnt += counter;            

+    mvOnuEponMacGpmFifoFullErrorCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.fifoFullErrorCnt += counter;              

+    mvOnuEponMacGpmOpcDiscoveryNotRegisterBcastCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.opcDiscoveryNotRegBcastCnt += counter;    

+    mvOnuEponMacGpmOpcRegisterNotDiscoveryCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.opcRegisterNotDiscoveryCnt += counter;    

+    mvOnuEponMacGpmOpcDiscoveryNotRegisterNotBcastCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.opcDiscoveryNotRegNotBcastCnt += counter; 

+    mvOnuEponMacGpmOpcDropGrantCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.opcDropGrantCnt += counter;               

+    mvOnuEponMacGpmOpcHiddenGrantCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.opcHiddenGrantCnt += counter;             

+    mvOnuEponMacGpmOpcBackToBackCounterGet(&counter, macId);

+    g_OnuEponPm[macId].gpm.opcBackToBackCnt += counter; 

+  }

+

+  return(MV_OK);

+}

+

+ /*******************************************************************************

+**

+**  onuEponPmSwCountersUpdate

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function updates software counters

+**                

+**  PARAMETERS:  S_SwPm *swPm

+**               MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuEponPmSwCountersUpdate(S_SwPm *swPm, MV_U32 macId)

+{

+  MV_U32 index;

+

+  /* MAC 0 counts RX statitics for all modules */

+  for (index = 0; index < MAX_EPON_RX_SW_CNT; index++)

+  {

+    swPm->swRxCnt[index] = g_OnuEponSwPm[macId].swRxCnt[index];

+  }

+

+  for (index = 0; index < MAX_EPON_TX_SW_CNT; index++)

+  {

+    swPm->swTxCnt[index] = g_OnuEponSwPm[macId].swTxCnt[index];

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmSwRxCountersAdd

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function updates SW Rx counters

+**                

+**  PARAMETERS:  MV_U32 cnt 

+**               MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuEponPmSwRxCountersAdd(MV_U32 cnt, MV_U32 macId)

+{

+  if (cnt >= MAX_EPON_RX_SW_CNT) 

+    return(MV_ERROR);

+

+  if (macId >= EPON_MAX_MAC_NUM)

+    return(MV_ERROR);

+

+  g_OnuEponSwPm[macId].swRxCnt[cnt]++;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmSwTxCountersAdd

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function updates SW counters

+**                

+**  PARAMETERS:  MV_U32 cnt 

+**               MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuEponPmSwTxCountersAdd(MV_U32 cnt, MV_U32 macId)

+{

+  if (cnt >= MAX_EPON_TX_SW_CNT) 

+    return(MV_ERROR);

+

+  if (macId >= EPON_MAX_MAC_NUM)

+    return(MV_ERROR);

+

+  g_OnuEponSwPm[macId].swTxCnt[cnt]++;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmRxPmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu Rx counters

+**                 

+**  PARAMETERS:  S_RxPm *rxPm

+**               MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuEponPmRxPmGet(S_RxPm *rxPm, MV_U32 macId)

+{

+  if (macId >= EPON_MAX_MAC_NUM)

+    return(MV_ERROR);

+

+  rxPm->fcsErrorFramesCnt = g_OnuEponPm[macId].rx.fcsErrorFramesCnt;

+  rxPm->shortFramesCnt    = g_OnuEponPm[macId].rx.shortFramesCnt;   

+  rxPm->longFramesCnt     = g_OnuEponPm[macId].rx.longFramesCnt;    

+  rxPm->dataFramesCnt     = g_OnuEponPm[macId].rx.dataFramesCnt;    

+  rxPm->ctrlFramesCnt     = g_OnuEponPm[macId].rx.ctrlFramesCnt;    

+  rxPm->reportFramesCnt   = g_OnuEponPm[macId].rx.reportFramesCnt;  

+  rxPm->gateFramesCnt     = g_OnuEponPm[macId].rx.gateFramesCnt;    

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmCtrlCntGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu control packet counters

+**                 

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_U32 onuEponPmCtrlCntGet(MV_U32 macId)

+{

+  return(g_OnuEponPm[macId].rx.ctrlFramesCnt);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmTxPmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu Tx counters

+**                 

+**  PARAMETERS:  S_TxPm *txPm

+**               MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuEponPmTxPmGet(S_EponTxPm *txPm, MV_U32 macId)

+{

+  if (macId >= EPON_MAX_MAC_NUM)

+    return(MV_ERROR);

+

+  txPm->ctrlRegReqFramesCnt = g_OnuEponPm[macId].tx.ctrlRegReqFramesCnt;

+  txPm->ctrlRegAckFramesCnt = g_OnuEponPm[macId].tx.ctrlRegAckFramesCnt;

+  txPm->reportFramesCnt     = g_OnuEponPm[macId].tx.reportFramesCnt;    

+  txPm->dataFramesCnt       = g_OnuEponPm[macId].tx.dataFramesCnt;      

+  txPm->txAllowedBytesCnt   = g_OnuEponPm[macId].tx.txAllowedBytesCnt;  

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmTxDataPmLastIntervalGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu Tx datacounters

+**                 

+**  PARAMETERS:  MV_U32 *txDataPm

+**               MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuEponPmTxDataPmLastIntervalGet(MV_U32 *txDataPm, MV_U32 macId)

+{

+	MV_U32 counter;

+	MV_STATUS status = MV_OK;

+

+	if (macId >= EPON_MAX_MAC_NUM)

+		return(MV_ERROR);

+

+	status = mvOnuEponMacTxStatsDataFrameGet(&counter, macId); /* Count number of data frames transmitted */

+	if (status == MV_OK) {

+		g_OnuEponPm[macId].tx.dataFramesCnt += counter;

+		*txDataPm = counter;                                                                        

+	}

+

+	return(status);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmTxByteCntGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu control tx byte allowed counter

+**                 

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_U32 onuEponPmTxByteCntGet(MV_U32 macId)

+{

+  return(g_OnuEponPm[macId].tx.txAllowedBytesCnt);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmSwPmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu SW counters

+**                 

+**  PARAMETERS:  S_SwPm *swPm

+**               MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuEponPmSwPmGet(S_SwPm *swPm, MV_U32 macId)

+{

+  MV_U32 index;

+

+  if (macId >= EPON_MAX_MAC_NUM)

+    return(MV_ERROR);

+

+  for (index = 0; index < MAX_EPON_RX_SW_CNT; index++)

+  {

+    swPm->swRxCnt[index] = g_OnuEponPm[macId].sw.swRxCnt[index];

+  }

+

+  for (index = 0; index < MAX_EPON_TX_SW_CNT; index++)

+  {

+    swPm->swTxCnt[index] = g_OnuEponPm[macId].sw.swTxCnt[index];

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmGpmPmGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu Gpm counters

+**                 

+**  PARAMETERS:  S_GpmPm *gpmPm

+**               MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuEponPmGpmPmGet(S_GpmPm *gpmPm, MV_U32 macId)

+{

+  if (macId >= EPON_MAX_MAC_NUM)

+    return(MV_ERROR);

+

+  gpmPm->grantValidCnt                 = g_OnuEponPm[macId].gpm.grantValidCnt;                

+  gpmPm->grantMaxFutureTimeErrorCnt    = g_OnuEponPm[macId].gpm.grantMaxFutureTimeErrorCnt;   

+  gpmPm->minProcTimeErrorCnt           = g_OnuEponPm[macId].gpm.minProcTimeErrorCnt;          

+  gpmPm->lengthErrorCnt                = g_OnuEponPm[macId].gpm.lengthErrorCnt;               

+  gpmPm->discoveryAndRegCnt            = g_OnuEponPm[macId].gpm.discoveryAndRegCnt;           

+  gpmPm->fifoFullErrorCnt              = g_OnuEponPm[macId].gpm.fifoFullErrorCnt;             

+  gpmPm->opcDiscoveryNotRegBcastCnt    = g_OnuEponPm[macId].gpm.opcDiscoveryNotRegBcastCnt;   

+  gpmPm->opcRegisterNotDiscoveryCnt    = g_OnuEponPm[macId].gpm.opcRegisterNotDiscoveryCnt;   

+  gpmPm->opcDiscoveryNotRegNotBcastCnt = g_OnuEponPm[macId].gpm.opcDiscoveryNotRegNotBcastCnt;

+  gpmPm->opcDropGrantCnt               = g_OnuEponPm[macId].gpm.opcDropGrantCnt;              

+  gpmPm->opcHiddenGrantCnt             = g_OnuEponPm[macId].gpm.opcHiddenGrantCnt;            

+  gpmPm->opcBackToBackCnt              = g_OnuEponPm[macId].gpm.opcBackToBackCnt;             

+                                         

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmGpmValidGrantGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu Gpm valid grant counter

+**                 

+**  PARAMETERS:  MV_U32 macId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     onu Gpm valid grant counter  

+**

+*******************************************************************************/

+MV_U32 onuEponPmGpmValidGrantGet(MV_U32 macId)

+{

+  if (macId >= EPON_MAX_MAC_NUM)

+    return(MV_ERROR);

+

+  return(g_OnuEponPm[macId].gpm.grantValidCnt);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmPcsPmGet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The funtion return onu Pcs counters

+**

+**  PARAMETERS:  S_PcsPm *pcsPm

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK

+**

+*******************************************************************************/

+MV_STATUS onuEponPmPcsPmGet(S_PcsPm *pcsPm)

+{

+	if (pcsPm == 0)

+		return(MV_BAD_PARAM);

+

+	pcsPm->legalFrameCnt       = g_OnuEponPm[0].pcs.legalFrameCnt;

+	pcsPm->maxFrameSizeErrCnt  = g_OnuEponPm[0].pcs.maxFrameSizeErrCnt;

+	pcsPm->parityLenErrCnt     = g_OnuEponPm[0].pcs.parityLenErrCnt;

+	pcsPm->longGateErrCnt      = g_OnuEponPm[0].pcs.longGateErrCnt;

+	pcsPm->protocolErrCnt      = g_OnuEponPm[0].pcs.protocolErrCnt;

+	pcsPm->minFrameSizeErrCnt  = g_OnuEponPm[0].pcs.minFrameSizeErrCnt;

+	pcsPm->legalFecFrameCnt    = g_OnuEponPm[0].pcs.legalFecFrameCnt;

+	pcsPm->legalNonFecFrameCnt = g_OnuEponPm[0].pcs.legalNonFecFrameCnt;

+

+	return(MV_OK);

+}

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         GUNIT LLID TX Queues Section                       */

+/* ========================================================================== */

+/******************************************************************************/

+

+/*******************************************************************************

+**

+**  onuEponPmDbaAddBytePerLlidFifo

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion add additional bytes per LLID FIFO

+**                 

+**  PARAMETERS:  MV_U32 llId

+**               MV_U32 counter

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     OK or ERROR

+**

+*******************************************************************************/

+MV_STATUS onuEponPmDbaAddBytePerLlidFifo(MV_U32 llId, MV_U32 counter)

+{

+	if (llId >= EPON_MAX_MAC_NUM)

+    return(MV_ERROR);

+

+  g_OnuEponSwPmAddCntPerLlidFifo[llId] = counter;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmDbaAddBytePerLlidFifoGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return additional bytes per LLID FIFO

+**                 

+**  PARAMETERS:  MV_U32 llId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     Additional bytes per LLID FIFO

+**

+*******************************************************************************/

+MV_U32 onuEponPmDbaAddBytePerLlidFifoGet(MV_U32 llId)

+{

+	if (llId >= EPON_MAX_MAC_NUM)

+		return(0);

+

+	return(g_OnuEponSwPmAddCntPerLlidFifo[llId]);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmDbaAddBytePerLlidAndQueue

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion add additional bytes per queue

+**                 

+**  PARAMETERS:  MV_U32 llId

+**				 MV_U32 queueId

+**               MV_U32 counter

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     OK or ERROR

+**

+*******************************************************************************/

+MV_STATUS onuEponPmDbaAddBytePerLlidAndQueue(MV_U32 llId, MV_U32 queueId, MV_U32 counter)

+{

+	if ((queueId >= EPON_MAX_QUEUE) || (llId >= EPON_MAX_MAC_NUM))

+		return(MV_ERROR);

+

+	g_OnuEponSwPmAddCntPerLlidAndQueue[llId][queueId] = counter;

+

+	return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmDbaAddBytePerLlidAndQueueGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return additional bytes per queue

+**                 

+**  PARAMETERS:  MV_U32 llId

+**				 MV_U32 queueId

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     Additional bytes per queue

+**

+*******************************************************************************/

+MV_U32 onuEponPmDbaAddBytePerLlidAndQueueGet(MV_U32 llId, MV_U32 queueId)

+{

+	if ((queueId >= EPON_MAX_QUEUE) || (llId >= EPON_MAX_MAC_NUM))

+		return(0);

+

+	return(g_OnuEponSwPmAddCntPerLlidAndQueue[llId][queueId]);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmGunitLlidQueueCntGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu Gunit LLID TX queue counter

+**                 

+**  PARAMETERS:  MV_U32 llId

+**               MV_U32 queueId

+**               MV_U32 *counter

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     nu Gunit LLID TX queue counter

+**

+*******************************************************************************/

+MV_STATUS onuEponPmGunitLlidQueueCntGet(MV_U32 llid, MV_U32 queueId, MV_U32 *counter)

+{

+	/* This function is called from IRQ context, therefore the registers access should be as fast as possible

+	For this purpose the standard call to asicOntMiscRegRead() API is not used and registers are indexed

+	and accesses using macros only

+	*/

+	if ((llid >= EPON_MAX_MAC_NUM) || (queueId > onuEponDbOnuDbaHighestReportQueueGet(llid)) || (counter == 0))

+		return(MV_ERROR);

+

+	*counter = MV_REG_READ(MV_PON_GUNIT_TX_N_QUEUES(llid, queueId));

+	*counter += onuEponPmDbaAddBytePerLlidAndQueueGet(llid, queueId);

+

+	return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmGunitLlid0PktModMaxHeaderSizeSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion configure LLID0 Packet Modification max header size to 2 bytes

+**                 

+**  PARAMETERS:  MV_U32 headerSize

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK or Error

+**

+*******************************************************************************/

+MV_STATUS onuEponPmGunitLlid0PktModMaxHeaderSizeSet(MV_U32 headerSize)

+{

+	MV_STATUS status;

+

+	status  = asicOntMiscRegWrite(mvAsicReg_GUNIT_TX_0_PKT_MOD_MAX_HEAD_SIZE_CFG, headerSize, 0); 

+

+	return(status);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmGunitLlid0PktModPktCountGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return LLID0 Packet Modification long header packet 

+**               counter

+**                 

+**  PARAMETERS:  MV_U32 *packetCount

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     Onu Gunit LLID0 Packet Modification long header packet count

+**

+*******************************************************************************/

+MV_STATUS onuEponPmGunitLlid0PktModPktCountGet(MV_U32 *packetCount)

+{

+	MV_STATUS status;

+

+	status  = asicOntMiscRegRead(mvAsicReg_GUNIT_TX_0_PKT_MOD_STATS_PKT_COUNT, packetCount, 0); 

+

+	return(status);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmRandomGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu random number

+**                 

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     0nu random number

+**

+*******************************************************************************/

+MV_STATUS onuEponPmRandomGet(MV_U32 *random)

+{

+	MV_U32 addressLow;

+	MV_U32 addressHigh;

+	MV_U32 thermalRegValue;

+	MV_U32 thermalRegAddr = 0x000184D8;

+	MV_STATUS status;

+	S_PcsPm pcsPm;

+

+	if (random == 0)

+		return(MV_BAD_PARAM);

+

+	status = onuEponDbOnuMacAddrGet(&addressLow, &addressHigh, 0);

+	if (status == MV_OK)

+		status = onuEponPmPcsPmGet(&pcsPm); /* take stat counters from DB */

+

+	if (status != MV_OK)

+		return status;

+

+	thermalRegValue = ((MV_REG_READ(thermalRegAddr) >> 10)  & 0x1FF);

+	g_OnuEponRandomNum[7] = thermalRegValue;

+	mvOsDelay(addressLow & 0xFF);

+

+	g_OnuEponRandomNum[1] = pcsPm.legalFrameCnt;

+	g_OnuEponRandomNum[2] = pcsPm.parityLenErrCnt | (pcsPm.maxFrameSizeErrCnt << 16);

+

+	thermalRegValue = ((MV_REG_READ(thermalRegAddr) >> 10)  & 0x1FF);

+	g_OnuEponRandomNum[7] |= thermalRegValue << 9;    

+	mvOsDelay(addressLow & 0xFF);

+

+	g_OnuEponRandomNum[3] = pcsPm.protocolErrCnt | (pcsPm.longGateErrCnt << 16);

+

+	thermalRegValue = ((MV_REG_READ(thermalRegAddr) >> 10)  & 0x1FF);

+	g_OnuEponRandomNum[7] |= thermalRegValue << 18;   

+	mvOsDelay(addressLow & 0xFF);

+

+	g_OnuEponRandomNum[4] = pcsPm.minFrameSizeErrCnt;

+	g_OnuEponRandomNum[5] = pcsPm.legalNonFecFrameCnt | (pcsPm.legalFecFrameCnt << 16);

+

+	g_OnuEponRandomNum[6] = addressLow;

+

+	thermalRegValue = ((MV_REG_READ(thermalRegAddr) >> 10)  & 0x1F);

+	g_OnuEponRandomNum[7] |= thermalRegValue << 27;

+

+	*random = onuEponPmGenCrcKey(g_OnuEponRandomNum, GPON_RANDOM_ARR_SZ);

+	/* Count number of random value requests and put value into DB */

+	g_OnuEponRandomValues[g_OnuEponRandomCount % GPON_RANDOM_VAL_ARR_SZ] = *random;

+	g_OnuEponRandomCount++;

+

+	return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmRandomReset

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion reset onu random number

+**                 

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     0nu random number

+**

+*******************************************************************************/

+MV_STATUS onuEponPmRandomReset(void)

+{

+	MV_U32	i;

+

+	for (i = 0; i < GPON_RANDOM_ARR_SZ; i++)

+		g_OnuEponRandomNum[i] = 0;

+

+	return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmRandomThresholdCheck

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The funtion return onu random threshold check parameters

+**                 

+**  PARAMETERS:  MV_U32 *gateFrames

+**               MV_U32 *discNotRegFrames

+**               MV_U32 *regReqframes

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     0nu random number

+**

+*******************************************************************************/

+MV_STATUS onuEponPmRandomThresholdCheck(MV_U32 *gateFrames, MV_U32 *discNotRegFrames, 

+										MV_U32 *regReqframes)

+{

+  *gateFrames       = g_OnuEponPm[0].rx.gateFramesCnt; 

+  *discNotRegFrames = g_OnuEponPm[0].gpm.opcDiscoveryNotRegBcastCnt;

+  *regReqframes     = g_OnuEponPm[0].tx.ctrlRegReqFramesCnt;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponPmGenCrcTable

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function generate table of CRC remainders 

+**               

+**  PARAMETERS:  None  

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+MV_STATUS onuEponPmGenCrcTable(void)

+{ 

+  register int    i, j;  

+  register MV_U32 crc_accum;

+

+  for ( i = 0;  i < 256;  i++ )

+  { 

+    crc_accum = ( (MV_U32) i << 24 );

+    for ( j = 0;  j < 8;  j++ )

+    { 

+      if ( crc_accum & 0x80000000 )

+      {

+        crc_accum = ( crc_accum << 1 ) ^ POLYNOMIAL;

+      }

+      else

+      {

+        crc_accum = ( crc_accum << 1 ); 

+      }

+    }

+    crc_table[i] = crc_accum; 

+  } 

+

+  return(MV_OK); 

+}

+

+/*******************************************************************************

+**

+**  onuEponPmGenCrcKey

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function calculate CRC key 

+**               

+** 	PARAMETERS:  unsigned long msg[]

+**				 int           size  

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+MV_U32 onuEponPmGenCrcKey(MV_U32 msg[], MV_U32 size)

+{ 

+   MV_U8  data;

+   MV_U32 idx;

+   MV_U32 calcCrc = 0;

+   

+   for (idx = 0;  idx < size;  idx++)

+   { 

+     data    = (MV_U8)((msg[idx]) ^ (calcCrc >> 24));

+     calcCrc = ((crc_table[data]) ^ (calcCrc << 8)); 

+   }

+

+   return (calcCrc); 

+}

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuPm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuPm.h
new file mode 100755
index 0000000..1697dc8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuPm.h
@@ -0,0 +1,224 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU GPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnuPm.h                                               **/

+/**                                                                          **/

+/**  DESCRIPTION : This file contains ONU EPON Alarm and Statistics          **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *  

+ *                                                                            

+ ******************************************************************************/

+#ifndef _ONU_EPON_PM_H

+#define _ONU_EPON_PM_H

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+typedef enum

+{

+  TOTAL_MPCP_TX_FRAME_CNT             = 0,

+  TOTAL_MPCP_TX_ERROR_FRAME_CNT       = 1,

+  MAX_EPON_TX_SW_CNT

+}E_EponTxSwCnt;

+

+typedef enum

+{

+  TOTAL_MPCP_RX_FRAME_CNT             = 0,

+  TOTAL_MPCP_RX_ERROR_FRAME_CNT       = 1,

+  TOTAL_MPCP_REGISTER_ACK_CNT         = 2,

+  TOTAL_MPCP_REGISTER_NACK_CNT        = 3,

+  TOTAL_MPCP_REGISTER_DEREG_FRAME_CNT = 4,

+  TOTAL_MPCP_REGISTER_REREG_FRAME_CNT = 5,

+  MAX_EPON_RX_SW_CNT

+}E_EponRxSwCnt;

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef struct

+{

+  MV_U32 ctrlRegReqFramesCnt; /* Count number of register request frames transmitted     */  

+  MV_U32 ctrlRegAckFramesCnt; /* Count number of register acknowledge frames transmitted */  

+  MV_U32 reportFramesCnt;     /* Count number of report frames transmitted               */

+  MV_U32 dataFramesCnt;       /* Count number of data frames transmitted                 */

+  MV_U32 txAllowedBytesCnt;   /* Count number of Tx Byte Allow counter                   */

+}S_EponTxPm;

+

+typedef struct

+{

+  MV_U32 fcsErrorFramesCnt;   /* Count number of received frames with FCS errors */

+  MV_U32 shortFramesCnt;      /* Count number of short frames received           */

+  MV_U32 longFramesCnt;       /* Count number of long frames received            */

+  MV_U32 dataFramesCnt;       /* Count number of data frames received            */

+  MV_U32 ctrlFramesCnt;       /* Count number of control frames received         */

+  MV_U32 reportFramesCnt;     /* Count number of report frames received          */

+  MV_U32 gateFramesCnt;       /* Count number of gate frames received            */

+}S_RxPm;

+

+typedef struct

+{

+  MV_U32 grantValidCnt;                 /* Count number of valid grant                          */

+  MV_U32 grantMaxFutureTimeErrorCnt;    /* Count number of grant max future time error          */

+  MV_U32 minProcTimeErrorCnt;           /* Count number of min proc time error                  */

+  MV_U32 lengthErrorCnt;                /* Count number of length error                         */

+  MV_U32 discoveryAndRegCnt;            /* Count number of discovery & register                 */

+  MV_U32 fifoFullErrorCnt;              /* Count number of fifo full error                      */

+  MV_U32 opcDiscoveryNotRegBcastCnt;    /* Count number of opc discoveryNotRegBcastCnt          */

+  MV_U32 opcRegisterNotDiscoveryCnt;    /* Count number of opc register not discovery           */ 

+  MV_U32 opcDiscoveryNotRegNotBcastCnt; /* Count number of opc discovery not register not bcast */ 

+  MV_U32 opcDropGrantCnt;               /* Count number of opc drop grant                       */ 

+  MV_U32 opcHiddenGrantCnt;             /* Count number of opc hidden grant                     */ 

+  MV_U32 opcBackToBackCnt;              /* Count number of opc back to back                     */ 

+}S_GpmPm;                               

+

+typedef struct {

+	MV_U32 legalFrameCnt;		/* stat0[31:0]	*/

+	MV_U32 maxFrameSizeErrCnt;	/* stat1[31:16]	*/

+	MV_U32 parityLenErrCnt;		/* stat1[15:0]	*/

+	MV_U32 longGateErrCnt;		/* stat2[31:16]	*/

+	MV_U32 protocolErrCnt;		/* stat2[15:0]	*/

+	MV_U32 minFrameSizeErrCnt;	/* stat3[15:0]	*/

+	MV_U32 legalFecFrameCnt;	/* stat4[31:16]	*/

+	MV_U32 legalNonFecFrameCnt;	/* stat4[15:0]	*/

+} S_PcsPm;

+

+typedef struct

+{

+  MV_U32 swTxCnt[MAX_EPON_TX_SW_CNT];

+  MV_U32 swRxCnt[MAX_EPON_RX_SW_CNT];

+}S_SwPm;

+

+typedef struct {

+	S_RxPm     rx;

+	S_EponTxPm tx;

+	S_SwPm     sw;

+	S_GpmPm    gpm;

+	S_PcsPm    pcs;

+} S_EponPm;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+void      onuEponPmInit(void);

+void      onuEponPmTimerPmHndl(unsigned long data);

+void      onuEponPmTimerExpireHndl(void);

+MV_STATUS onuEponPmCountersAdd(void);

+MV_STATUS onuEponPmSwRxCountersAdd(MV_U32 cnt, MV_U32 macId);

+MV_STATUS onuEponPmSwTxCountersAdd(MV_U32 cnt, MV_U32 macId);

+MV_STATUS onuEponPmSwPmGet(S_SwPm *swPm, MV_U32 macId);

+MV_STATUS onuEponPmRxPmGet(S_RxPm *rxPm, MV_U32 macId);

+MV_STATUS onuEponPmTxPmGet(S_EponTxPm *txPm, MV_U32 macId);

+MV_STATUS onuEponPmTxDataPmLastIntervalGet(MV_U32 *txDataPm, MV_U32 macId);

+MV_STATUS onuEponPmGpmPmGet(S_GpmPm *gpmPm, MV_U32 macId);

+MV_U32    onuEponPmGpmValidGrantGet(MV_U32 macId);

+MV_STATUS onuEponPmPcsPmGet(S_PcsPm *pcsPm);

+MV_U32    onuEponPmCtrlCntGet(MV_U32 macId);

+MV_U32    onuEponPmTxByteCntGet(MV_U32 macId);

+

+MV_STATUS onuEponPmDbaAddBytePerLlidAndQueue(MV_U32 llId, MV_U32 queueId, MV_U32 counter);

+MV_U32    onuEponPmDbaAddBytePerLlidAndQueueGet(MV_U32 llId, MV_U32 queueId);

+MV_STATUS onuEponPmDbaAddBytePerLlidFifo(MV_U32 llId, MV_U32 counter);

+MV_U32    onuEponPmDbaAddBytePerLlidFifoGet(MV_U32 llId);

+

+MV_STATUS onuEponPmGunitLlidQueueCntGet(MV_U32 llid, MV_U32 queueId, MV_U32 *counter);

+MV_STATUS onuEponPmGunitLlid0PktModMaxHeaderSizeSet(MV_U32 headerSize);

+MV_STATUS onuEponPmGunitLlid0PktModPktCountGet(MV_U32 *packetCount);

+

+MV_STATUS onuEponAlarmSet(MV_U32 alarm, MV_BOOL state);

+void      onuEponAlarmGet(MV_U32 *alarm);

+void      onuEponLosAlarmGet(MV_U32 *alarm);

+

+

+MV_STATUS onuEponPmGenCrcTable(void);

+MV_U32    onuEponPmGenCrcKey(MV_U32 msg[], MV_U32 size);

+MV_STATUS onuEponPmRandomGet(MV_U32 *random);

+MV_STATUS onuEponPmRandomReset(void);

+MV_STATUS onuEponPmRandomThresholdCheck(MV_U32 *gateFrames, MV_U32 *discNotRegFrames, 

+										MV_U32 *regReqframes);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_EPON_PM_H */

+     

+

+

+              

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuStd.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuStd.h
new file mode 100755
index 0000000..ab4d42c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/epon/eponOnuStd.h
@@ -0,0 +1,312 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : eponOnustd.h                                              **/

+/**                                                                          **/

+/**  DESCRIPTION : This file contains ONU EPON standard definitions          **/

+/**                                                                          **/

+/******************************************************************************

+ *                                                                            *                              

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== *      

+ *                                                                          

+ ******************************************************************************/

+#ifndef _ONU_EPON_STD_H

+#define _ONU_EPON_STD_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+#define MIN_ETH_FRAME_LEN  (256)

+#define MIN_RPRT_FRAME_LEN (64)

+#define MIN_DG_FRAME_LEN   (64)

+#define MAC_ADDR_LEN       (6)

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+typedef enum

+{

+  MPC_OPCODE_GATE          = 2,     

+  MPC_OPCODE_REPORT        = 3,       

+  MPC_OPCODE_REGISTER_REQ  = 4,

+  MPC_OPCODE_REGISTER      = 5, 

+  MPC_OPCODE_REGISTER_ACK  = 6

+}E_EponMpcOpcode;

+

+typedef enum

+{

+  REGISTER_FLAGS_REREG     = 1,     

+  REGISTER_FLAGS_DEREG     = 2,

+  REGISTER_FLAGS_ACK       = 3,            

+  REGISTER_FLAGS_NACK      = 4

+}E_EponMpcRegFlag;

+

+typedef enum

+{

+  REGISTER_ACK_FLAGS_NACK  = 0,     

+  REGISTER_ACK_FLAGS_ACK   = 1

+}E_EponMpcRegAckFlag;

+

+typedef enum

+{

+  REGISTER_REQ_FLAGS_REG   = 1,     

+  REGISTER_REQ_FLAGS_DEREG = 3

+}E_EponMpcRegReqFlag;

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+#pragma pack(1)

+typedef struct

+{

+  MV_U32 length;

+  MV_U8  data[MIN_ETH_FRAME_LEN];

+}S_OnuEponCtrlBuffer;

+#pragma pack(0)

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         General MPC Frame Definitions                      */

+/* ========================================================================== */

+/******************************************************************************/

+#pragma pack(1)

+typedef struct

+{

+  MV_U8  destAddr[MAC_ADDR_LEN];                      

+  MV_U8  srcAddr[MAC_ADDR_LEN];                       

+  MV_U16 etherType;                        

+}S_OnuEponStdEthFrame;                                      

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  MV_U16 opCode;

+  MV_U32 timeStamp;

+}S_OnuEponGenMpcPdu;                                      

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  S_OnuEponStdEthFrame stdEthFrame;

+  S_OnuEponGenMpcPdu   genMpcPdu;  

+}S_OnuEponGenMpcFrame;                                      

+#pragma pack(0)

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Register MPC Frame Definitions                     */

+/* ========================================================================== */

+/******************************************************************************/

+#pragma pack(1)

+typedef struct 

+{

+  MV_U16 assignedLlidPort;

+  MV_U8  flags;              

+  MV_U16 syncTime;           

+  MV_U8  echoedPendingGrants;

+}S_OnuEponRegMpcPdu;                                      

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  S_OnuEponStdEthFrame stdEthFrame;

+  S_OnuEponGenMpcPdu   genMpcPdu;

+  S_OnuEponRegMpcPdu   regMpcPdu;

+}S_OnuEponRegMpcFrame;                                      

+#pragma pack(0)

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Register Ack MPC Frame Definitions                 */

+/* ========================================================================== */

+/******************************************************************************/

+#pragma pack(1)

+typedef struct 

+{

+  MV_U8  flags;              

+  MV_U16 echoedAssignedport;  

+  MV_U16 echoedSyncTime;      

+}S_OnuEponRegAckMpcPdu;                                      

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  S_OnuEponStdEthFrame  stdEthFrame;

+  S_OnuEponGenMpcPdu    genMpcPdu;

+  S_OnuEponRegAckMpcPdu regAckMpcPdu;

+}S_OnuEponRegAckMpcFrame;                                      

+#pragma pack(0)

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Register Request MPC Frame Definitions             */

+/* ========================================================================== */

+/******************************************************************************/

+#pragma pack(1)

+typedef struct 

+{

+  MV_U8  flags;              

+  MV_U8  pendingGrants;  

+}S_OnuEponRegReqMpcPdu;                                      

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  S_OnuEponStdEthFrame  stdEthFrame;

+  S_OnuEponGenMpcPdu    genMpcPdu;

+  S_OnuEponRegReqMpcPdu regReqMpcPdu;

+}S_OnuEponRegReqMpcFrame;     

+#pragma pack(0)

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Report MPC Frame Definitions                       */

+/* ========================================================================== */

+/******************************************************************************/

+#pragma pack(1)

+typedef struct 

+{

+  MV_U8  numQueueSets;

+}S_OnuEponReportMpcPduStart;

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  MV_U16 queueLength;

+}S_OnuEponReportQueueReport;

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  MV_U8                      bitMap;

+  S_OnuEponReportQueueReport queueReport;

+}S_OnuEponReportQueueSetStart;

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  S_OnuEponStdEthFrame        stdEthFrame;

+  S_OnuEponGenMpcPdu          genMpcPdu;

+  S_OnuEponReportMpcPduStart  reportMpcPduStart;

+  MV_U8                       next;

+}S_OnuEponReportMpcFrame;

+#pragma pack(0)

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                                OAM Frame Definitions                       */

+/* ========================================================================== */

+/******************************************************************************/

+

+#pragma pack(1)

+typedef struct 

+{

+  MV_U8  subType;

+  MV_U16 flags;

+  MV_U8  code;

+}S_OnuEponOamHeader;

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct 

+{

+  S_OnuEponStdEthFrame        stdEthFrame;

+  S_OnuEponOamHeader          stdOamHeader;

+}S_OnuEponOamFrame;

+#pragma pack(0)

+

+#pragma pack(1)

+typedef struct                                         

+{                                                      

+  S_OnuEponCtrlBuffer msg;

+  MV_U32              macId;

+  MV_U32              valid;

+}S_OnuEponOamMsg;

+#pragma pack(0)

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_EPON_STD_H */

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.c
new file mode 100755
index 0000000..d23c1ac
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.c
@@ -0,0 +1,871 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuAlloc.c                                             **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON BW Allocation Table          **
+**                                                                           **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+ ******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "gponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuAlloc.c"
+/* Global Variables
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+MV_U32 onuIdleAllocTcont = PON_ONU_IDLE_ALLOC_TCONT;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+MV_STATUS onuGponAllocIdTcontClearAll(void);
+MV_STATUS onuGponAllocIdTcontSet(MV_U32 allocId, MV_U32 tcontNum);
+
+/*
+** ALLOC ID & T-CONT Handling
+** ==========================
+** Three tables to used to handle Alloc-Id and T-Cont management
+**
+** Software tables:
+** ==> Alloc Id table           - contains all Alloc Id configured by the OLT
+** ==> Idle Alloc Id table      - contains all configured Alloc not connected to HW
+** ==> T-Cont table             - contains the XC between configured Alloc Id and T-Cont
+**
+** Hanrdware table
+** ==> BW Map table             - contains the hardware configuration of the GMAC
+**
+** Rules
+** =====
+** 1. Default Alloc Id == ONU ID, is set to default T-Cont and can not be changed
+** 2. Configure T-cont is only valid for a pre-defined Alloc Id which is not used
+*/
+
+MV_BOOL sendNotifyToMng = MV_FALSE;
+
+ /******************************************************************************/
+/* ========================================================================== */
+/*                     SoC BW MAP Table Access Operations                     */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponAllocIdMacInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init Rx Bw Map
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdMacInit(void)
+{
+	MV_U32 iEntry;
+	MV_STATUS status = MV_OK;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++)
+		status |= mvOnuGponMacRxBwMapSet(iEntry, 0, GPON_BW_MAP_IDLE_TCONT, MV_FALSE);
+
+	return (status);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdMacAllocExistCheck
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function checks if allocId is configured to T-Cont and
+**               returns T-Cont entry index in the BW MAP table
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 *entry
+**
+**  OUTPUTS:     MV_U32 *entry
+**
+**  RETURNS:     MV_TRUE or MV_FALSE
+**
+*******************************************************************************/
+MV_BOOL onuGponAllocIdMacAllocExistCheck(MV_U32 allocId, MV_U32 *entry)
+{
+	MV_U32  iEntry;
+	MV_U32  macAllocId;
+	MV_U32  tcontNum;
+	MV_BOOL valid;
+	MV_STATUS status;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		status = mvOnuGponMacRxBwMapGet(iEntry,&macAllocId,&valid,&tcontNum);
+		if ((status == MV_OK) && (macAllocId == allocId) && (valid == MV_TRUE)) {
+			*entry = iEntry;
+			return (MV_TRUE);
+		}
+	}
+
+	return (MV_FALSE);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdMacAllocFreeEntryGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns free T-Cont entry in the BW MAP table
+**
+**  PARAMETERS:  MV_U32 *entry
+**
+**  OUTPUTS:     MV_U32 *entry
+**
+**  RETURNS:     MV_TRUE or MV_FALSE
+**
+*******************************************************************************/
+MV_BOOL onuGponAllocIdMacAllocFreeEntryGet(MV_U32 *entry)
+{
+	MV_U32  iEntry;
+	MV_U32  macAllocId;
+	MV_U32  tcontNum;
+	MV_BOOL valid;
+	MV_STATUS status;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		status = mvOnuGponMacRxBwMapGet(iEntry, &macAllocId, &valid, &tcontNum);
+		if ((status == MV_OK) && (valid == MV_FALSE)) {
+			*entry = iEntry;
+			return (MV_TRUE);
+		}
+	}
+
+	return (MV_FALSE);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdMacAdd
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function adds an entry to the BW MAP table
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 tcontId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdMacAdd(MV_U32 allocId, MV_U32 tcontId)
+{
+	MV_U32  entry;
+	MV_BOOL exist;
+
+	exist = onuGponAllocIdMacAllocFreeEntryGet(&entry);
+	if (exist == MV_FALSE)
+		return (MV_ERROR);
+
+	return (mvOnuGponMacRxBwMapSet(entry, allocId, tcontId, MV_TRUE));
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdMacConnect
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function connect Alloc-Id to  T-Cont
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 tcontnum
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdMacConnect(MV_U32 allocId, MV_U32 tcontNum)
+{
+	MV_STATUS status;
+	MV_BOOL   exist;
+	MV_U32    entry;
+	MV_U32    newIdleTcontEntry;
+	MV_U32    freeTcontEntry;
+	MV_U32    entryAllocId;
+	MV_U32    bwMapEntry;
+
+	/* validate that requested alloc-Id is configured in HW and is valid */
+	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry);
+	if (exist != MV_TRUE) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+					"ERROR: (%s:%d) onuGponAllocIdMacConnect, alloc Id(%d) entry(%d)\n",
+					__FILE_DESC__, __LINE__, allocId, entry);
+		return (MV_ERROR);
+	}
+
+	if (tcontNum == onuIdleAllocTcont) {
+		/* If the input T-Cont is the T-Cont used as an Idle T-Cont, all alloc-Id connected to the T-Cont
+		** should be changed to another Idle T-Cont */
+
+		/* Check for a free (idle) entry in the Tcont DB table */
+		exist = onuGponDbBwTcontFreeGet(allocId, &freeTcontEntry);
+		if (exist != MV_TRUE) {
+#ifdef MV_GPON_DEBUG_PRINT
+			mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+						"DEBUG: (%s:%d) onuGponAllocIdMacConnect, alloc Id(%d) freeTcontEntry(%d)\n",
+						__FILE_DESC__, __LINE__, allocId, freeTcontEntry);
+#endif /* MV_GPON_DEBUG_PRINT */
+		} else {
+			/* new idle Tcont entry allocated, update it globally */
+			onuIdleAllocTcont = freeTcontEntry;
+
+			/* scan all T-Cont / Alloc-Id in DB and update each HW Idle Alloc-Id to the new Idle T-Cont */
+			for (newIdleTcontEntry = 0 ; newIdleTcontEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; newIdleTcontEntry++) {
+				/* find the idle Alloc ID for this Tcont entry in DB */
+				onuGponDbBwIdleAllocGet(newIdleTcontEntry, &entryAllocId);
+				if (entryAllocId != PON_ONU_ALLOC_NOT_EXIST) {
+					/* Check if this idle Alloc ID exists in the HW table */
+					exist = onuGponAllocIdMacAllocExistCheck(entryAllocId, &bwMapEntry);
+					if (exist == MV_TRUE) {
+						/* re-assign this Alloc ID to the new idle Tcont in HW */
+						status = mvOnuGponMacRxBwMapSet(bwMapEntry, entryAllocId, onuIdleAllocTcont, MV_TRUE);
+						if (status != MV_OK) {
+							mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+										"ERROR: (%s:%d) onuGponAllocIdMacConnect, Faild to re-ssign alloc Id(%d) "
+										"to idle Tcont(%d)%d\n",
+										__FILE_DESC__, __LINE__, entryAllocId, onuIdleAllocTcont);
+						}
+					} else {
+						/* Gewalt! DB and HW are not in sync! */
+						mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+									"ERROR: (%s:%d) onuGponAllocIdMacConnect, alloc Id(%d) is not in sync!\n",
+									__FILE_DESC__, __LINE__, allocId);
+					}
+				} /* entryAllocId != PON_ONU_ALLOC_NOT_EXIST */
+			}
+		}
+		 /* There is a free entry in Tcont table */
+	} /* tcontNum == onuIdleAllocTcont */
+
+	/* update input Alloc-Id and T-Cont in the HW */
+	return (mvOnuGponMacRxBwMapSet(entry, allocId, tcontNum, MV_TRUE));
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdMacReconnect
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reconnect alloc-Id to idle tcont
+**
+**  PARAMETERS:  MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdMacReconnect(MV_U32 allocId)
+{
+	MV_BOOL   exist;
+	MV_STATUS status = MV_OK;
+	MV_U32    entry;
+	MV_U32    onuId;
+	MV_U32    tcontNum;
+
+	/* Get free entry */
+	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry);
+	if (exist != MV_TRUE)
+		return (MV_ERROR);
+
+	exist = onuGponDbBwTcontFreeGet(allocId, &tcontNum);
+	if (exist != MV_TRUE)
+		onuIdleAllocTcont = tcontNum;
+
+	/* Check if default Alloc Id */
+	onuId = onuGponDbOnuIdGet();
+	if (allocId != onuId) {
+		/* Set Alloc Id to T-Cont in the GMAC hardware */
+		status = mvOnuGponMacRxBwMapSet(entry, allocId, onuIdleAllocTcont, MV_TRUE);
+	}
+
+	return (status);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdMacDisconnect
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function disconnect alloc-Id from tcont
+**
+**  PARAMETERS:  MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdMacDisconnect(MV_U32 allocId)
+{
+	MV_U32  onuId;
+	MV_U32  entry;
+	MV_BOOL exist;
+	MV_STATUS status = MV_OK;
+
+	/* Check if already exist */
+	exist = onuGponAllocIdMacAllocExistCheck(allocId, &entry);
+	if (exist == MV_FALSE)
+		return (MV_ERROR);
+
+	/* Check if default Alloc Id */
+	onuId = onuGponDbOnuIdGet();
+	if (allocId != onuId)
+		status = mvOnuGponMacRxBwMapSet(entry, 0, 0, MV_FALSE);
+
+	return (status);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                                    APIs                                    */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponAllocIdInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init Tconts Bitmap
+**
+**  PARAMETERS:  MV_U32 existTcontsBitmap
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdInit(MV_U32 existTcontsBitmap)
+{
+	MV_U32  iEntry;
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+				"DEBUG: (%s:%d) Tconts Bitmap(0x%x)\n", __FILE_DESC__, __LINE__, existTcontsBitmap);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		/* Check if T-CONT Exist */
+		if ((existTcontsBitmap >> iEntry) & 0x01)
+			onuGponDbBwTcontSet(iEntry, MV_TRUE, PON_ONU_ALLOC_NOT_EXIST, MV_FALSE);
+	}
+
+	return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdAssign
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function Assign Alloc ID
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 notifyFlag
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdAssign(MV_U32 allocId, MV_U32 notifyFlag)
+{
+	MV_STATUS status;
+	MV_U32    entry;
+	MV_U32    idleEntry;
+	MV_U32    onuId;
+	MV_BOOL   allocIdExist;
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+				"DEBUG: (%s:%d) Alloc ID Assign, alloc Id(%d)\n", __FILE_DESC__, __LINE__, allocId);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	/* check if Alloc-Id exist in the alloc Id DB table */
+	allocIdExist = onuGponDbBwAllocExist(allocId);
+	if (allocIdExist == MV_TRUE)
+		return (MV_OK);
+
+	/* set the Alloc-Id exist to the database */
+	status = onuGponDbBwAllocInsert(allocId, &entry);
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) onuGponDbBwAllocInsert, alloc Id(%d)\n",
+					__FILE_DESC__, __LINE__, allocId);
+		return (status);
+	}
+
+	onuId = onuGponDbOnuIdGet();
+
+	/* Default AllocId */
+	/* =============== */
+	/* configured in the T-Cont table and BW MAP */
+	if (allocId == onuId) {
+		/* Set default Alloc Id to T-Cont table */
+		status = onuGponDbBwTcontAlloc(PON_ONU_DEFAULT_ALLOC_TCONT, allocId);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) tcont to alloc set failed, tcont (%d) alloc Id(%d)\n",
+						__FILE_DESC__, __LINE__, PON_ONU_DEFAULT_ALLOC_TCONT, allocId);
+			return (MV_ERROR);
+		}
+
+		sendNotifyToMng = MV_TRUE;
+
+	} else {
+
+		/* Data AllocId  */
+		/* ============= */
+		/* Configured in the Idle Alloc table and BW MAP */
+		/* set the Alloc-Id exist to the database */
+		status = onuGponDbBwIdleAllocInsert(allocId, &idleEntry);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) onuGponDbBwIdleAllocInsert, alloc Id(%d))\n",
+						__FILE_DESC__, __LINE__, allocId);
+			return (status);
+		}
+
+		/* set the Alloc-Id exist to the BW table in the MAC (hardware) */
+		status = onuGponAllocIdMacAdd(allocId, onuIdleAllocTcont);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) onuGponAllocIdMacAdd, alloc Id(%d)\n",
+						__FILE_DESC__, __LINE__, allocId);
+			return (status);
+		}
+
+		sendNotifyToMng = MV_TRUE;
+	}
+
+	if ((sendNotifyToMng == MV_TRUE) && (notifyFlag != 0)) {
+		/* Send Status Notification to upper layer */
+		onuGponSrvcStatusNotify(GPON_ONU_STATUS_RANGED);
+	}
+
+	return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdDeAssign
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function De-Assign Alloc ID
+**
+**  PARAMETERS:  MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdDeAssign(MV_U32 allocId)
+{
+	MV_STATUS status;
+	MV_U32    entry;
+	MV_U32    tcontNum;
+	MV_BOOL   allocIdExist;
+	MV_BOOL   valid;
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+				"DEBUG: (%s:%d) De-Assign Alloc ID, alloc Id(%d)\n", __FILE_DESC__, __LINE__, allocId);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	/* Check if Alloc-Id exist in the database alloc Id, if not exist */
+	allocIdExist = onuGponDbBwAllocExist(allocId);
+	if (allocIdExist == MV_FALSE)
+		return (MV_OK);
+
+	/* Delete the Alloc Id from the BW MAP table (if it is not the default T-Cont) */
+	status = onuGponAllocIdMacDisconnect(allocId);
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) onuGponAllocIdMacDisconnect, alloc Id(%d)\n",
+					__FILE_DESC__, __LINE__, allocId);
+		return (status);
+	}
+
+	/* check if Alloc-Id is connected Data T-Cont */
+	status = onuGponDbBwTcontConnectCheck(allocId, &tcontNum, &valid);
+	if ((status == MV_OK) && (valid == MV_TRUE)) {
+		/* Delete Alloc ID from the Alloc Id / T-Cont table in the database */
+		onuGponDbBwTcontClear(tcontNum);
+	}
+
+	/* check if Alloc-Id is Idle Alloc-Id */
+	if (onuGponDbBwIdleAllocExist(allocId, &entry) == MV_TRUE) {
+		/* Delete Alloc ID from the Idle Alloc Id table */
+		status = onuGponDbBwIdleAllocRemove(allocId, &entry);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) onuGponDbBwIdleAllocRemove, alloc Id(%d) entry(%d)\n",
+						__FILE_DESC__, __LINE__, allocId, entry);
+			return (status);
+		}
+	}
+
+	/* Delete Alloc Id from the Alloc Id table in the database */
+	status = onuGponDbBwAllocRemove(allocId, &entry);
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) onuGponDbBwAllocRemove, alloc Id(%d) entry(%d)\n",
+					__FILE_DESC__, __LINE__, allocId, entry);
+		return (status);
+	}
+
+	return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdDeAssignAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function De-Assign All Alloc IDs
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdDeAssignAll(void)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+             "DEBUG: (%s:%d) De-Assign All Alloc IDs and T-Conts\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  onuGponDbBwAllocInit();
+  onuGponAllocIdMacInit();
+  onuGponAllocIdInit(0x00FF);
+
+  sendNotifyToMng = MV_FALSE;
+
+  return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdTcontSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function Set Alloc ID to T-CONT
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 tcontnum
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdTcontSet(MV_U32 allocId, MV_U32 tcontNum)
+{
+	MV_STATUS status;
+	MV_U32    otherTcontNum;
+	MV_U32    dbAllocId;
+	MV_U32    entry;
+	MV_BOOL   valid;
+	MV_BOOL   exist;
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+				"DEBUG: (%s:%d) Set Alloc ID to T-CONT, alloc Id(%d) tcont(%d)\n",
+				__FILE_DESC__, __LINE__, allocId, tcontNum);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	/* Check if Alloc Id was assigned by the OLT */
+	exist = onuGponDbBwAllocExist(allocId);
+	if (exist == MV_FALSE) {
+		mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) Alloc ID Not Exist, alloc Id(%d)\n",
+				__FILE_DESC__, __LINE__, allocId, tcontNum);
+		return (MV_OK);
+	}
+
+	/* Check if T-CONT Exist - all 8 tconts are set to exist during onuGponAllocIdInit function */
+	status = onuGponDbBwTcontExist(tcontNum,&exist);
+	if ((status != MV_OK) || (exist == MV_FALSE)) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) Tcont Not Exist, alloc Id(%d) tcont(%d)\n",
+				__FILE_DESC__, __LINE__, allocId, tcontNum);
+		return (MV_ERROR);
+	}
+
+	/* Check that Alloc Id is not exist on other T-CONT */
+	status = onuGponDbBwTcontConnectCheck(allocId, &otherTcontNum, &valid);
+	if ((status == MV_OK) && (valid == MV_TRUE)) {
+		if (otherTcontNum == tcontNum) {
+
+			mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) Alloc Id/T-CONT Already Configured, alloc Id(%d) tcont(%d) otherTcontNum(%d)\n",
+						__FILE_DESC__, __LINE__, allocId, tcontNum, otherTcontNum);
+			return (MV_OK);
+
+		} else {
+
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) Alloc Id Already Exist on T-CONT, alloc Id(%d) tcont(%d) otherTcontNum(%d)\n",
+						__FILE_DESC__, __LINE__, allocId, tcontNum, otherTcontNum);
+			return (MV_ERROR);
+		}
+	}
+
+	/* Check that the T-CONT is valid */
+	onuGponDbBwTcontGet(tcontNum, &exist, &dbAllocId, &valid);
+	if (valid == MV_TRUE) {
+		if (dbAllocId != PON_ONU_ALLOC_NOT_EXIST) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) Alloc Id/T-CONT Already Configured, alloc Id(%d) tcont(%d)\n",
+						__FILE_DESC__, __LINE__, allocId, tcontNum);
+			return (MV_OK);
+		}
+	}
+
+	/* configure Alloc Id / T-Cont table */
+	status = onuGponDbBwTcontAlloc(tcontNum, allocId);
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) onuGponDbBwTcontAlloc, alloc Id(%d) tcont(%d)\n",
+				__FILE_DESC__, __LINE__, allocId, tcontNum);
+		return (MV_ERROR);
+	}
+
+	/* remove Alloc Id from Idle Alloc table */
+	status = onuGponDbBwIdleAllocRemove(allocId, &entry);
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) onuGponDbBwIdleAllocRemove, alloc Id(%d) entry(%d) removed from Idle table\n",
+				__FILE_DESC__, __LINE__, allocId, entry);
+		return (MV_ERROR);
+	}
+
+	/* set Alloc Id to T-Cont in the GMAC hardware */
+	status = onuGponAllocIdMacConnect(allocId, tcontNum);
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) onuGponAllocIdMacConnect, alloc Id(%d) tcont(%d)\n",
+				__FILE_DESC__, __LINE__, allocId, tcontNum);
+		return (MV_ERROR);
+	}
+
+	return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdTcontClear
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function Clear Alloc ID from T-CONT
+**
+**  PARAMETERS:  MV_U32 tcontnum
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdTcontClear(MV_U32 tcontNum)
+{
+	MV_STATUS status;
+	MV_U32    allocId;
+	MV_U32    onuId;
+	MV_U32    idleEntry;
+	MV_BOOL   valid;
+	MV_BOOL   exist;
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+				"DEBUG: (%s:%d) Clear Alloc ID from T-CONT: T-CONT(%d)\n",
+				__FILE_DESC__, __LINE__, tcontNum);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	/* Check if T-CONT Exist */
+	status = onuGponDbBwTcontExist(tcontNum,&exist);
+	if ((status != MV_OK) || (exist == MV_FALSE)) {
+		mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+				"ERROR: (%s:%d) T-CONT Not Exist, tcont(%d)\n",
+				__FILE_DESC__, __LINE__, tcontNum);
+		return (MV_ERROR);
+	}
+
+	/* Get tcont params from the database */
+	onuGponDbBwTcontGet(tcontNum, &exist, &allocId, &valid);
+	if (valid == MV_FALSE)
+		return (MV_OK);
+
+	/* Check if Alloc Id Exist */
+	exist = onuGponDbBwAllocExist(allocId);
+	if (exist == MV_TRUE) {
+		/* Clear T-Cont in hardware in case T-Cont is not connected to default Alloc-Id (== ONU ID) */
+		status = onuGponAllocIdMacReconnect(allocId);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) onuGponAllocIdMacReconnect, alloc Id(%d)\n",
+						__FILE_DESC__, __LINE__, allocId);
+			return (MV_ERROR);
+		}
+	}
+
+	/* Clear T-Cont in the database */
+	onuId = onuGponDbOnuIdGet();
+	if (allocId != onuId) {
+		onuGponDbBwTcontClear(tcontNum);
+
+		/* set the Alloc-Id exist to the idle alloc-Id */
+		status = onuGponDbBwIdleAllocInsert(allocId, &idleEntry);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ALLOC_MODULE,
+						"ERROR: (%s:%d) onuGponAllocIdTcontClear, idle alloc Id(%d) entry(%d)\n",
+						__FILE_DESC__, __LINE__, allocId, idleEntry);
+			return (status);
+		}
+	}
+
+	return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAllocIdTcontClearAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function Clear All Alloc-Ids from T-TCONTs
+**
+**  PARAMETERS:  MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponAllocIdTcontClearAll(void)
+{
+	MV_U32  iEntry;
+	MV_BOOL exist;
+	MV_STATUS status;
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_ALLOC_MODULE,
+				"DEBUG: (%s:%d) Clear All Alloc-Ids from T-TCONTs\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		/* Check if T-CONT Exist */
+		status = onuGponDbBwTcontExist(iEntry,&exist);
+		if ((status == MV_OK) && (exist == MV_TRUE))
+			onuGponAllocIdTcontClear(iEntry);
+	}
+
+	return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponIdleAllocIdTcontGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Idle Alloc-Id
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_U32 allocId
+**
+*******************************************************************************/
+MV_U32 onuGponIdleAllocIdTcontGet(void)
+{
+  return (onuIdleAllocTcont);
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.h
new file mode 100755
index 0000000..0e5e6e1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlloc.h
@@ -0,0 +1,116 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuAlloc.h                                             **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON BW Allocation Table            **

+**                prototypes                                                 **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef ONU_GPON_ALLOC_H

+#define ONU_GPON_ALLOC_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+#define PON_ONU_ALLOC_NOT_EXIST     (0x1000)

+#define PON_ONU_DEFAULT_ALLOC_TCONT (0)

+#define PON_ONU_IDLE_ALLOC_TCONT    (1)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+  

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponAllocIdInit(MV_U32 existTcontsBitmap);

+MV_STATUS onuGponAllocIdAssign(MV_U32 allocId, MV_U32 notifyFlag);

+MV_STATUS onuGponAllocIdDeAssign(MV_U32 allocId);

+MV_STATUS onuGponAllocIdTcontSet(MV_U32 allocId, MV_U32 tcontNum);

+MV_STATUS onuGponAllocIdTcontClear(MV_U32 tcontNum);

+MV_STATUS onuGponAllocIdDeAssignAll(void);

+MV_STATUS onuGponAllocIdTcontClearAll(void);

+MV_U32    onuGponIdleAllocIdTcontGet(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* ONU_GPON_ALLOC_H */

+

+  

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.c
new file mode 100755
index 0000000..c328cfb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.c
@@ -0,0 +1,528 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuAlrm.c                                              **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON Alarm and Statistics         **
+**                functionality                                              **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "gponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuAlrm.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+S_OnuGponApmTbl onuGponApmTbl_s;
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+MV_U16 l_onuGponPreviousAlarmState = ONU_GPON_ALARM_DEF_STATE;
+MV_U16 l_onuGponCurrentAlarmState  = ONU_GPON_ALARM_DEF_STATE;
+MV_U32 l_onuGponDsSyncFlag         = 1;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+void onuGponAlarmProcess(void);
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Alarm Section                                      */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponAlarmTblInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init the onu gpon alarm table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponAlarmTblInit (void)
+{
+  /* set alarm Off as default for all alarms */
+  memset(&(onuGponApmTbl_s.onuGponAlarmTbl_s.onuGponAlarmTbl[0]),
+         ONU_GPON_ALARM_OFF,
+         sizeof (S_OnuGponAlarmTbl));
+
+  /* set alarms on as default only for LOS, LOF, and LCDG */
+  onuGponApmTbl_s.onuGponAlarmTbl_s.onuGponAlarmTbl[ONU_GPON_ALARM_LOS]  = ONU_GPON_ALARM_ON;
+  onuGponApmTbl_s.onuGponAlarmTbl_s.onuGponAlarmTbl[ONU_GPON_ALARM_LOF]  = ONU_GPON_ALARM_ON;
+}
+
+/*******************************************************************************
+**
+**  onuGponAlarmSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu gpon alarm
+**
+**  PARAMETERS:  E_OnuGponAlarmType  alarm
+**               E_OnuGponAlarmState status
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponAlarmSet(E_OnuGponAlarmType  alarm,
+                          E_OnuGponAlarmState state)
+{
+  if (alarm > ONU_GPON_ALARM_RDI)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_ALARM_MODULE,
+               "ERROR: (%s:%d) invalid alarm(%d) type\n", __FILE_DESC__, __LINE__, alarm);
+    return(MV_ERROR);
+  }
+
+  if (state > ONU_GPON_ALARM_ON)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_ALARM_MODULE,
+               "ERROR: (%s:%d)  invalid alarm(%d) state(%d)\n", __FILE_DESC__, __LINE__, alarm, state);
+    return(MV_ERROR);
+  }
+
+  onuGponApmTbl_s.onuGponAlarmTbl_s.onuGponAlarmTbl[alarm] = state;
+
+  if (state == ONU_GPON_ALARM_OFF)
+  {
+    l_onuGponCurrentAlarmState &= ~(1 << alarm);
+  }
+  else
+  {
+    l_onuGponCurrentAlarmState |= (1 << alarm);
+  }
+
+  onuGponAlarmProcess();
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAlarmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu gpon alarm state
+**
+**  PARAMETERS:  E_OnuGponAlarmType alarm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu gpon alarm state
+**
+*******************************************************************************/
+E_OnuGponAlarmState onuGponAlarmGet(E_OnuGponAlarmType alarm)
+{
+  if (alarm > ONU_GPON_ALARM_RDI)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_ALARM_MODULE,
+               "ERROR: (%s:%d) invalid alarm(%d) type\n", __FILE_DESC__, __LINE__, alarm);
+    return(MV_ERROR);
+  }
+
+  return(onuGponApmTbl_s.onuGponAlarmTbl_s.onuGponAlarmTbl[alarm]);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicAlarmStatusGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu gpon alarm state, alarm is off if all
+**               asic alarms (LOS, LOF, and LCDG) are off, else alarm is on
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu gpon alarm state
+**
+*******************************************************************************/
+E_OnuGponAlarmState onuGponAsicAlarmStatusGet(void)
+{
+#if 0
+  if ((onuGponAlarmGet(ONU_GPON_ALARM_LOS)  == ONU_GPON_ALARM_OFF) &&
+      (onuGponAlarmGet(ONU_GPON_ALARM_LOF)  == ONU_GPON_ALARM_OFF) &&
+      (onuGponAlarmGet(ONU_GPON_ALARM_LCDG) == ONU_GPON_ALARM_OFF))
+#else
+  if ((onuGponAlarmGet(ONU_GPON_ALARM_LOS) == ONU_GPON_ALARM_OFF) &&
+      (onuGponAlarmGet(ONU_GPON_ALARM_LOF) == ONU_GPON_ALARM_OFF))
+#endif
+  {
+    return(ONU_GPON_ALARM_OFF);
+  }
+  else
+  {
+    return(ONU_GPON_ALARM_ON);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponAlarmProcess
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function process the current alarm state and notify screen
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponAlarmProcess(void)
+{
+  MV_U32 onuGponPreviousAlarmState;
+  MV_U32 onuGponCurrentAlarmState;
+  MV_U32 onuGponChangeAlarm;
+  LINKSTATUSFUNC linkStatusCallback;
+
+
+  /* get the ASIC prvious alarm status */
+  onuGponPreviousAlarmState = l_onuGponPreviousAlarmState;
+
+  /* get the ASIC current alarm status */
+  onuGponCurrentAlarmState = l_onuGponCurrentAlarmState;
+
+  /* alarm changed */
+  if ((onuGponCurrentAlarmState ^ onuGponPreviousAlarmState) != 0)
+  {
+    onuGponChangeAlarm = (onuGponCurrentAlarmState ^ onuGponPreviousAlarmState);
+
+    if ((onuGponChangeAlarm & onuGponCurrentAlarmState) != 0)
+    {
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_LOS_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm LOS On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_LOS, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_LOF_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm LOF On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_LOF, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_LCDG_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm LCDG On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_LCDG, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_TF_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm TF On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_TF, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_SUF_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm SUF On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_SUF, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_MEM_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm MEM On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_MEM, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_DACT_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm DACT On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_DACT, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_DIS_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm DIS On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_DIS, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_MIS_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm MIS On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_MIS, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_PEE_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm PEE On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_PEE, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_RDI_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm RDI On ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_RDI, GPON_ONU_ALARM_STATUS_ON );
+      }
+
+      if ((onuGponAsicAlarmStatusGet() == ONU_GPON_ALARM_ON) &&
+          l_onuGponDsSyncFlag == 0)
+      {
+#ifndef PON_FPGA
+        /* Turn OFF LED */
+        onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_OFF);
+#endif /* PON_FPGA */
+
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "=======================\n");
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "== Upstream sync Off ==\n");
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "=======================\n");
+
+		/* Call link status callback function */
+		linkStatusCallback = onuGponDbLinkStatusCallbackGet();
+		if (linkStatusCallback != NULL)
+		{
+		  linkStatusCallback(MV_FALSE);
+		}
+
+        onuPonTxPowerOn(MV_FALSE);
+        onuGponSrvcStatusNotify(GPON_ONU_STATUS_DISCONNECTED);
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "=========================\n");
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "== Downstream sync Off ==\n");
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "=========================\n");
+        l_onuGponDsSyncFlag = 1;
+      }
+    }
+    else /* ((onuGponChangeAlarm & onuGponCurrentAlarmState) == 0) */
+    {
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_LOS_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm LOS Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_LOS, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_LOF_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm LOF Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_LOF, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_LCDG_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm LCDG Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_LCDG, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_TF_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm TF Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_TF, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_SUF_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm SUF Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_SUF, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_MEM_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm MEM Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_MEM, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_DACT_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm DACT Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_DACT, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_DIS_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm DIS Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_DIS, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_MIS_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm MIS Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_MIS, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_PEE_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm PEE Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_PEE, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if (onuGponChangeAlarm & ONU_GPON_ALARM_RDI_LOC)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+                   "INFO: (%s:%d) === Alarm RDI Off ===\n", __FILE_DESC__, __LINE__);
+        onuGponSrvcAlarmNotify( GPON_ONU_ALARM_RDI, GPON_ONU_ALARM_STATUS_OFF );
+      }
+
+      if ((onuGponAsicAlarmStatusGet() == ONU_GPON_ALARM_OFF) &&
+          l_onuGponDsSyncFlag == 1)
+      {
+#ifndef PON_FPGA
+        /* Turn LED ON */
+        onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_BLINK_SLOW);
+#endif /* PON_FPGA */
+        onuGponSrvcStatusNotify(GPON_ONU_STATUS_NOT_RANGED);
+
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "========================\n");
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "== Downstream sync On ==\n");
+        mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "========================\n");
+        l_onuGponDsSyncFlag = 0;
+
+        onuPonTxPowerOn(MV_TRUE);
+        mvOnuGponMacXvrActivate();
+        onuGponDbOnuDsSyncOnSet(1);
+      }
+    }
+
+    l_onuGponPreviousAlarmState = l_onuGponCurrentAlarmState;
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponOnuAlarmShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print current alarm statsus
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponOnuAlarmShow(void)
+{
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE,
+          "ONU Gpon alarms state\n"
+          "=====================\n");
+
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm LOS  - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_LOS_LOC)  ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm LOF  - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_LOF_LOC)  ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm LCDG - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_LCDG_LOC) ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm TF   - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_TF_LOC)   ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm SUF  - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_SUF_LOC)  ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm MEM  - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_MEM_LOC)  ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm DACT - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_DACT_LOC) ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm DIS  - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_DIS_LOC)  ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm MIS  - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_MIS_LOC)  ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm PEE  - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_PEE_LOC)  ? ("On") : ("Off"));
+  mvPonPrint(PON_PRINT_INFO, PON_ALARM_MODULE, "Alarm RDI  - %s\n",
+          (l_onuGponCurrentAlarmState & ONU_GPON_ALARM_RDI_LOC)  ? ("On") : ("Off"));
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.h
new file mode 100755
index 0000000..fdb8f5d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuAlrm.h
@@ -0,0 +1,198 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuAlrm.h                                              **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Alarm and Statistics           **

+**                                                                           **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_ALRM_H

+#define _ONU_GPON_ALRM_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+#define ONU_GPON_ALARM_LOS_LOC   (0x0001) 

+#define ONU_GPON_ALARM_LOF_LOC   (0x0002) 

+#define ONU_GPON_ALARM_LCDA_LOC  (0x0004)

+#define ONU_GPON_ALARM_LCDG_LOC  (0x0008)

+#define ONU_GPON_ALARM_SF_LOC    (0x0010)

+#define ONU_GPON_ALARM_SD_LOC    (0x0020)

+#define ONU_GPON_ALARM_TF_LOC    (0x0040)

+#define ONU_GPON_ALARM_SUF_LOC   (0x0080)

+#define ONU_GPON_ALARM_MEM_LOC   (0x0100)

+#define ONU_GPON_ALARM_DACT_LOC  (0x0200)

+#define ONU_GPON_ALARM_DIS_LOC   (0x0400)

+#define ONU_GPON_ALARM_MIS_LOC   (0x0800)

+#define ONU_GPON_ALARM_PEE_LOC   (0x1000)

+#define ONU_GPON_ALARM_RDI_LOC   (0x2000)

+

+#define ONU_GPON_ALARM_DEF_STATE (ONU_GPON_ALARM_LOS_LOC | \

+                                  ONU_GPON_ALARM_LOF_LOC | \

+                                  ONU_GPON_ALARM_LCDG_LOC)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+typedef enum 

+{

+  /* ASIC Alarms */

+  ONU_GPON_ALARM_LOS = 0,

+  ONU_GPON_ALARM_LOF,

+  ONU_GPON_ALARM_LCDA,

+  ONU_GPON_ALARM_LCDG,

+  /* SW Alarms */

+  ONU_GPON_ALARM_SF,

+  ONU_GPON_ALARM_SD,

+  ONU_GPON_ALARM_TF,

+  ONU_GPON_ALARM_SUF,

+  ONU_GPON_ALARM_MEM,

+  ONU_GPON_ALARM_DACT,

+  ONU_GPON_ALARM_DIS,

+  ONU_GPON_ALARM_MIS,

+  ONU_GPON_ALARM_PEE,

+  ONU_GPON_ALARM_RDI,

+  ONU_GPON_MAX_ALARMS

+}E_OnuGponAlarmType;

+  

+typedef enum

+{

+  ONU_GPON_ALARM_OFF,

+  ONU_GPON_ALARM_ON

+}E_OnuGponAlarmState;

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* ONU GPON Alarm table */

+typedef struct

+{

+  E_OnuGponAlarmState onuGponAlarmTbl[ONU_GPON_NUM_OF_ALARMS];

+}S_OnuGponAlarmTbl;

+

+/* ONU GPON Stats table */

+typedef struct

+{

+  MV_U32 onuGponInComingPloamCrcErrCnt;

+  MV_U32 onuGponInComingPloamOverflowCnt;

+  MV_U32 onuGponOutGoingBwCrcErrCnt;

+  MV_U32 onuGponOutGoingBwCrcCorrectErrCnt;

+}S_OnuGponStatsTbl;

+

+/* ONU GPON APM table */

+typedef struct

+{

+  S_OnuGponAlarmTbl onuGponAlarmTbl_s;

+  S_OnuGponStatsTbl onuGponStatsTbl_s;

+}S_OnuGponApmTbl;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+/* ONU GPON APM table */

+extern S_OnuGponApmTbl onuGponApmTbl_s;

+

+/* Global functions

+------------------------------------------------------------------------------*/

+ 

+/* ONU GPON Alarm table init function */

+void                onuGponAlarmTblInit(void);

+

+/* ONU GPON Alarm table API functions */

+MV_STATUS           onuGponAlarmSet(E_OnuGponAlarmType alarm, E_OnuGponAlarmState state);

+E_OnuGponAlarmState onuGponAlarmGet(E_OnuGponAlarmType alarm);

+E_OnuGponAlarmState onuGponAsicAlarmStatusGet(void);

+

+void                onuGponOnuAlarmShow(void);

+

+/* ONU GPON Stats API functions */

+void                onuGponOnuStatsAccmulate(void);

+void                onuGponOnuStatsReset(void);

+void                onuGponOnuStatsShow(void);

+                   

+MV_STATUS           onuGponInComingPloamCrcErrSet(MV_U32 count);

+MV_U32              onuGponInComingPloamCrcErrGet(void);

+MV_STATUS           onuGponInComingPloamOverflowCntSet(MV_U32 count);

+MV_U32              onuGponInComingPloamOverflowCntGet(void);

+MV_STATUS           onuGponOutGoingBwCrcErrCntSet(MV_U32 count);

+MV_U32              onuGponOutGoingBwCrcErrCntGet(void);

+MV_STATUS           onuGponOutGoingBwCrcCorrErrCntSet(MV_U32 count);

+MV_U32              onuGponOutGoingBwCrcCorrErrCntGet(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_ALRM_H */

+

+  

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.c
new file mode 100755
index 0000000..b25a37d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.c
@@ -0,0 +1,2115 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuApi.c                                               **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON API functionality            **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "gponOnuHeader.h"
+#include "mv_netdev.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/gpon/gonuGponApi.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+S_GponPm g_OnuGponOutPm;
+
+MV_U32  g_UponDebugMode = 0;
+extern u8 mvMacAddr[CONFIG_MV_ETH_PORTS_NUM][MV_MAC_ADDR_SIZE];
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+#ifdef MV_GPON_STATIC_GEM_PORT
+MV_U32 staticGemPortConfig[4096];
+MV_U32 staticGemPortConfigFlag  = 0;
+#endif /* MV_GPON_STATIC_GEM_PORT */
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+MV_STATUS onuGponApiGemPortIdConfig(MV_U32 gemPortid);
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Initialization Section                             */
+/* ========================================================================== */
+/******************************************************************************/
+/*******************************************************************************
+**
+**  onuGponApiInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu gpon API
+**
+**  PARAMETERS:  MV_U8 *serialNumber
+**               MV_U8 *password
+**               MV_BOOL  disabled
+**               MV_U32   sn_src
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiInit(MV_U8 *serialNumber, MV_U8 *password, MV_BOOL disabled, MV_U32 sn_src)
+{
+  MV_STATUS rcode;
+  MV_U32    i;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiInit Serial number (%s) Password (%s)\n",
+             __FILE_DESC__, __LINE__, serialNumber, password);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  onuGponDbPasswordSet(password);
+  if (sn_src == 1)
+  {
+    /*the digit part of the serial number is taken from the 4lower pairs of the MAC address*/
+    for (i = 0; i < 4; i++)
+	{
+      serialNumber[i+4] = mvMacAddr[2][i+2];
+    }
+  }
+
+  rcode = onuGponSrvcSerialNumberSet(serialNumber);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponSrvcSerialNumberSet", __FILE_DESC__, __LINE__);
+    return rcode;
+  }
+
+  rcode = onuGponSrvcRangingRandomInit();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponRangingRandomInit", __FILE_DESC__, __LINE__);
+    return rcode;
+  }
+
+  if (disabled == MV_TRUE)
+  {
+    /* update asic */
+    rcode = mvOnuGponMacOnuStateSet(ONU_GPON_07_EMERGANCY_STOP);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                 "ERROR: (%s:%d) mvOnuGponMacOnuStateSet", __FILE_DESC__, __LINE__);
+      return(rcode);
+    }
+
+    /* update database */
+    onuGponDbOnuStateSet(ONU_GPON_07_EMERGANCY_STOP);
+  }
+
+  memset(&g_OnuGponOutPm, 0, sizeof (S_GponPm));
+
+  onuGponDbInitSet(MV_TRUE);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiAlarmNotifyRegister
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function register alarm callback function
+**
+**  PARAMETERS:  ALARMNOTIFYFUNC notifyCallBack
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiAlarmNotifyRegister(ALARMNOTIFYFUNC notifyCallBack)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiAlarmNotifyRegister\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponDbAlarmNotifySet(notifyCallBack);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiAlarmNotifyRegister", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiStatusNotifyRegister
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function register status callback function
+**
+**  PARAMETERS:  STATUSNOTIFYFUNC notifyCallBack
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiStatusNotifyRegister(STATUSNOTIFYFUNC notifyCallBack)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiStatusNotifyRegister\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponDbStatusNotifySet(notifyCallBack);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiStatusNotifyRegister", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiOmccNotifyRegister
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function register omcc callback function
+**
+**  PARAMETERS:  OMCCNOTIFYFUNC notifyCallBack
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiOmccNotifyRegister(OMCCNOTIFYFUNC notifyCallBack)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiOmccNotifyRegister\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponDbOmccNotifySet(notifyCallBack);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiOmccNotifyRegister", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiDisableNotifyRegister
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function register disable onu callback function
+**
+**  PARAMETERS:  DISABLENOTIFYFUNC notifyCallBack
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiDisableNotifyRegister(DISABLENOTIFYFUNC notifyCallBack)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiDisableNotifyRegister\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponDbDisableNotifySet(notifyCallBack);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiDisableNotifyRegister", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiTcontConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function validates and configures Alloc-Id to T-cont
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 tcontId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiTcontConfig(MV_U32 allocId, MV_U32 tcontId)
+{
+  MV_STATUS  rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiTcontConfig alloc Id (%d) tcont (%d)\n",
+             __FILE_DESC__, __LINE__, allocId, tcontId);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponAllocIdTcontSet(allocId,tcontId);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiTcontConfig", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiBerThresholdConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures the SD / SF thresholds for GPON ONU
+**
+**  PARAMETERS:  MV_U32 sd
+**               MV_U32 sf
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiBerThresholdConfig(MV_U32 sd, MV_U32 sf)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiBerThresholdConfig sd (%d) sf (%d)\n",
+             __FILE_DESC__, __LINE__, sd, sf);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  if ((sf >= sd) ||
+      (sf > ONU_GPON_MAX_SF_THRESHOLD) || (sf < ONU_GPON_MIN_SF_THRESHOLD) ||
+      (sd > ONU_GPON_MAX_SD_THRESHOLD) || (sd < ONU_GPON_MIN_SD_THRESHOLD))
+  {
+    /* SD threshold must be higher than SF */
+    return(MV_ERROR);
+  }
+
+  rcode = onuGponDbSdThresholdSet(sd);
+  rcode |= onuGponDbSfThresholdSet(sf);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiBerThresholdConfig", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiBerIntervalConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures the ONU BER interval,
+**               which defines the time the ONU send BER information
+**
+**  PARAMETERS:  MV_U32 interval
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK.
+**
+*******************************************************************************/
+MV_STATUS onuGponApiBerIntervalConfig(MV_U32 interval)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiBerIntervalConfig interval (%d)\n",
+             __FILE_DESC__, __LINE__, interval);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  onuGponBerIntervalSet(interval);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiBerCoefficientConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures the BER coefficient, which are used
+**               in the BER Calculation formula
+**
+**  PARAMETERS:  MV_U32 denominator
+**               MV_U32 numerator
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponApiBerCoefficientConfig(MV_U32 denominator, MV_U32 numerator)
+{
+  S_BerCoefficient coef;
+
+  coef.denominator = denominator;
+  coef.numerator   = numerator;
+  onuGponBerCoefficientSet(&coef);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiTcontClear
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears all Alloc-Ids from T-cont
+**
+**  PARAMETERS:  MV_U32 tcontId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiTcontClear(MV_U32 tcontId)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiTcontClear tcontId (%d)\n",
+             __FILE_DESC__, __LINE__, tcontId);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponAllocIdTcontClear(tcontId);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiTcontClear", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiTcontsReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears all Alloc-Ids from all T-conts
+**
+**  PARAMETERS:  void
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiTcontsReset(void)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiTcontsReset\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponAllocIdTcontClearAll();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiTcontsReset", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function Adds or removes a gem port by the action
+**
+**  PARAMETERS:  gemmap bit map, corresponding action per this group
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemConfig(MV_U32* gemmap, E_GponIoctlGemAction action){
+
+    MV_U32 index, bit, mask;
+    MV_U32 portId;
+    MV_STATUS rcode = MV_OK;
+
+    for (index = 0; index < GPON_ONU_MAX_GEM_PORTS/32; index ++) {
+
+                if (gemmap[index] != 0 ) {
+
+            mask = 1;
+            for (bit = 0 ; bit < 32 ; bit ++) {
+
+                if (gemmap[index] & mask)
+                {
+                    portId = index*32+bit;
+                    if (action != E_GEPON_IOCTL_GEM_REMOVE) {
+
+                        rcode  = onuGponApiGemPortIdConfig(portId);
+                        if (rcode != MV_OK)
+                        {
+                              mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                                         "ERROR: (%s:%d) onuGponApiGemConfig", __FILE_DESC__, __LINE__);
+                              break;
+                        }
+                        if (onuGponDbGemPortAesGet(portId) == MV_TRUE) {
+                            /*update HW as well*/
+                            mvOnuGponMacAesPortIdSet(portId,MV_TRUE);
+                        }
+                    }
+                    else{
+                        rcode  = onuGponApiGemPortIdClear(portId);
+                        if (rcode != MV_OK)
+                        {
+                              mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                                         "ERROR: (%s:%d) onuGponApiGemConfig", __FILE_DESC__, __LINE__);
+                              break;
+                        }
+                        if (onuGponDbGemPortAesGet(portId) == MV_TRUE) {
+                            /*remove HW configuration but keep SW encryption indication*/
+                            mvOnuGponMacAesPortIdSet(portId,MV_FALSE);
+                        }
+                    }
+
+                }
+                mask = mask << 1;
+            }
+        }
+    }
+
+    return rcode;
+
+
+
+}
+/*******************************************************************************
+**
+**  onuGponApiGemClearAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function removes all gem port
+**
+**  PARAMETERS:  savePorts
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemClearAll(MV_BOOL savePorts)
+{
+	if (savePorts == MV_TRUE)
+		onuGponDbGemPortSaveAll();
+
+	onuGponDbGemPortClearAll();
+	mvOnuGponMacGemInit();
+	/*reconfigure omcc port*/
+	onuGponApiGemPortIdConfig(onuGponDbOmccPortGet());
+
+	return MV_OK;
+}
+/*******************************************************************************
+**
+**  onuGponApiGemRestoreAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function restores all previously saved gem ports
+**
+**  PARAMETERS:  void
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemRestoreAll(void)
+{
+	MV_U32    gemPortId;
+	MV_STATUS rcode = MV_OK;
+
+	for (gemPortId = 0; gemPortId < GPON_ONU_MAX_GEM_PORTS; gemPortId++) {
+
+		if (onuGponDbGemPortSavedValidGet(gemPortId) == MV_TRUE)
+			rcode = onuGponApiGemPortIdConfig(gemPortId);
+
+		if (rcode != MV_OK)
+			break;
+	}
+
+	return (rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemOmccIdConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure omcc port Id
+**
+**  PARAMETERS:  MV_U32 gemPortid
+**               MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemOmccIdConfig(MV_U32 gemPortid, MV_BOOL valid)
+{
+  MV_STATUS rcode;
+#ifdef MV_GPON_STATIC_GEM_PORT
+  MV_U32 index;
+#endif /* MV_GPON_STATIC_GEM_PORT */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiGemOmcctIdConfig gemPortid (%d) valid (%d)\n",
+             __FILE_DESC__, __LINE__, gemPortid, valid);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = mvOnuGponMacGemOmciPortIdSet(gemPortid, (valid == MV_TRUE) ? (1) : (0)); /* Rx */
+  rcode |= mvOnuGponMacUtmOmciPortIdSet(gemPortid, (valid == MV_TRUE) ? (1) : (0)); /* Tx */
+  rcode |= mvOnuGponMacPortIdValidSet(gemPortid, valid);                         /* Gem Port-Id Valid Table */
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiGemOmcctIdConfig", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+#ifdef MV_GPON_STATIC_GEM_PORT
+  if (staticGemPortConfigFlag != 0)
+  {
+    for (index = 0; index < 4096; index++)
+    {
+      if (staticGemPortConfig[index] != 0)
+      {
+        onuGponApiGemPortIdConfig(index);
+      }
+    }
+  }
+#endif /* MV_GPON_STATIC_GEM_PORT */
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemPortIdConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure gem port Id from MAC
+**
+**  PARAMETERS:  MV_U32 gemPortid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemPortIdConfig(MV_U32 gemPortid)
+{
+  MV_STATUS  rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiGemPortIdConfig gemPortid (%d)\n",
+             __FILE_DESC__, __LINE__, gemPortid);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = mvOnuGponMacPortIdValidSet(gemPortid, MV_TRUE);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiGemPortIdConfig", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+  onuGponDbGemPortValidSet(gemPortid, MV_TRUE);
+
+#ifdef MV_GPON_STATIC_GEM_PORT
+  if (staticGemPortConfigFlag == 0)
+  {
+    if (gemPortid < 4096)
+      staticGemPortConfig[gemPortid] = 1;
+  }
+#endif /* MV_GPON_STATIC_GEM_PORT */
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemPortIdClear
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears gem port Id from MAC
+**
+**  PARAMETERS:  MV_U32 gemPortid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemPortIdClear(MV_U32 gemPortid)
+{
+  MV_STATUS  rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiGemPortIdClear gemPortid (%d)\n",
+             __FILE_DESC__, __LINE__, gemPortid);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = mvOnuGponMacPortIdValidSet(gemPortid, MV_FALSE);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiGemPortIdClear", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+  onuGponDbGemPortValidSet(gemPortid, MV_FALSE);
+
+  return(rcode);
+}
+
+#ifdef MV_GPON_STATIC_GEM_PORT
+
+/*******************************************************************************
+**
+**  onuGponApiGemPortIdStaticConfigReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears dummy gem port Id table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemPortIdStaticConfigFlag(MV_U32 flag)
+{
+   staticGemPortConfigFlag = flag;
+   return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemPortIdStaticConfigReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears dummy gem port Id table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemPortIdStaticConfigReset(void)
+{
+  MV_U32 index;
+
+  for(index = 0; index < 4096; index++)
+  {
+    staticGemPortConfig[index] = 0;
+  }
+
+  return(MV_OK);
+}
+#endif /* MV_GPON_STATIC_GEM_PORT */
+
+/*******************************************************************************
+**
+**  onuGponApiInformationGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu info
+**
+**  PARAMETERS:  S_OnuInfo *onuInfo
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponApiInformationGet(S_OnuInfo *onuInfo)
+{
+  onuGponDbPasswordGet(onuInfo->password);
+  onuGponDbSerialNumGet(onuInfo->serialNumber);
+  onuInfo->onuId             = onuGponDbOnuIdGet();
+  onuInfo->state             = onuGponDbOnuStateGet();
+  onuInfo->sdThreshold       = onuGponDbSdThresholdGet();
+  onuInfo->sfThreshold       = onuGponDbSfThresholdGet();
+  onuInfo->localBerInterval  = onuGponDbBerCalcIntervalGet();
+  onuInfo->remoteBerInterval = onuGponDbBerIntervalGet();
+  onuInfo->omccPortId        = onuGponDbOmccPortGet();
+  onuInfo->constDelay        = onuGponDbConstDelayGet();
+  onuInfo->eqDelay           = onuGponDbEqualizationDelayGet();
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiAlarmsGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu alarms bit map
+**
+**  PARAMETERS:  MV_U32 *alarms
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiAlarmsGet(MV_U32 *alarms)
+{
+  MV_U32  i;
+  MV_U32  status;
+
+  *alarms = 0;
+  for (i = ONU_GPON_ALARM_LOS ; i < ONU_GPON_MAX_ALARMS ; i++)
+  {
+    status = onuGponAlarmGet(i);
+    if (status == ONU_GPON_ALARM_ON)
+    {
+      *alarms |= 1 << i;
+    }
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmFecPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU
+**               FEC PM counters
+**
+**  PARAMETERS:  S_IoctlFecPm *fecPm
+**               MV_BOOL      a_clear
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiPmFecPmGet(S_GponIoctlFecPm *fecPm, MV_BOOL a_clear)
+{
+  MV_STATUS rcode;
+  S_RxFecPm inCounters;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiPmFecPmGet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponPmFecPmGet(&inCounters);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiPmFecPmGet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  fecPm->receivedBytes        = inCounters.receivedBytes        - g_OnuGponOutPm.rxFec.receivedBytes;
+  fecPm->correctedBytes       = inCounters.correctedBytes       - g_OnuGponOutPm.rxFec.correctedBytes;
+  fecPm->correctedBits        = inCounters.correctedBits        - g_OnuGponOutPm.rxFec.correctedBits;
+  fecPm->receivedCodeWords    = inCounters.receivedCodeWords    - g_OnuGponOutPm.rxFec.receivedCodeWords;
+  fecPm->uncorrectedCodeWords = inCounters.uncorrectedCodeWords - g_OnuGponOutPm.rxFec.uncorrectedCodeWords;
+
+  if (a_clear == MV_TRUE)
+  {
+    g_OnuGponOutPm.rxFec.receivedBytes        = inCounters.receivedBytes;
+    g_OnuGponOutPm.rxFec.correctedBytes       = inCounters.correctedBytes;
+    g_OnuGponOutPm.rxFec.correctedBits        = inCounters.correctedBits;
+    g_OnuGponOutPm.rxFec.receivedCodeWords    = inCounters.receivedCodeWords;
+    g_OnuGponOutPm.rxFec.uncorrectedCodeWords = inCounters.uncorrectedCodeWords;
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiPmRxPloamPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU
+**               Rx Ploam counters
+**
+**  PARAMETERS:  S_IoctlPloamRxPm *rxPloamPm
+**               MV_BOOL           a_clear
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiPmRxPloamPmGet(S_GponIoctlPloamRxPm *rxPloamPm, MV_BOOL a_clear)
+{
+  MV_STATUS   rcode;
+  S_RxPloamPm inCounters;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiPmRxPloamPmGet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponPmRxPloamPmGet(&inCounters);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiPmRxPloamPmGet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  rxPloamPm->rxCrcErrorPloam      = inCounters.crcErrorPloamCounter          - g_OnuGponOutPm.rxPloam.crcErrorPloamCounter;
+  rxPloamPm->rxBroadcastPloam     = inCounters.receivedBroadcastPloamCounter - g_OnuGponOutPm.rxPloam.receivedBroadcastPloamCounter;
+  rxPloamPm->rxOnuIdPloam         = inCounters.receivedOnuIdPloamCounter     - g_OnuGponOutPm.rxPloam.receivedOnuIdPloamCounter;
+  rxPloamPm->rxFifoOverErrorPloam = inCounters.fifoOverErrorPloamCounter     - g_OnuGponOutPm.rxPloam.fifoOverErrorPloamCounter;
+  rxPloamPm->rxIdlePloam          = inCounters.idlePloamCounter              - g_OnuGponOutPm.rxPloam.idlePloamCounter;
+  if (a_clear == MV_TRUE)
+  {
+    g_OnuGponOutPm.rxPloam.crcErrorPloamCounter          = inCounters.crcErrorPloamCounter;
+    g_OnuGponOutPm.rxPloam.receivedBroadcastPloamCounter = inCounters.receivedBroadcastPloamCounter;
+    g_OnuGponOutPm.rxPloam.receivedOnuIdPloamCounter     = inCounters.receivedOnuIdPloamCounter;
+    g_OnuGponOutPm.rxPloam.fifoOverErrorPloamCounter     = inCounters.fifoOverErrorPloamCounter;
+    g_OnuGponOutPm.rxPloam.idlePloamCounter              = inCounters.idlePloamCounter;
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiPmTxPloamPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU
+**               Tx Ploam counters
+**
+**  PARAMETERS:  S_TxPloamAdvApiPm *txPloamPm
+**               S_RxPloamAdvApiPm *rxPloamPm
+**               MV_BOOL              a_clear
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiAdvancedPloamsCounterGet(S_GponIoctlPloamTxPm *txPloamPm,
+                                             S_GponIoctlPloamRxPm *rxPloamPm,
+                                             MV_BOOL a_clear)
+{
+  MV_STATUS   status;
+  S_TxPloamPm inCounters1;
+  S_RxPloamPm inCounters2;
+  MV_U32       numOfDsMsgIdIndex;
+  MV_U32       numOfUsMsgIdIndex;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiAdvancedPloamsCounterGet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  status  = onuGponPmTxPloamPmGet(&inCounters1);
+  status |= onuGponPmRxPloamPmGet(&inCounters2);
+
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiAdvancedPloamsCounterGet", __FILE_DESC__, __LINE__);
+    return status;
+  }
+
+  txPloamPm->txMsgTotalPloam = inCounters1.txMsgTotalPloamCounter - g_OnuGponOutPm.txPloam.txMsgTotalPloamCounter;
+
+  for (numOfUsMsgIdIndex = 1 ;numOfUsMsgIdIndex <= ONU_GPON_US_MSG_LAST ;numOfUsMsgIdIndex++)
+  {
+    txPloamPm->txMsgIdPloam[numOfUsMsgIdIndex]    = inCounters1.txMsgIdPloamCounter[numOfUsMsgIdIndex]    -
+                                                    g_OnuGponOutPm.txPloam.txMsgIdPloamCounter[numOfUsMsgIdIndex];
+    txPloamPm->txErrMsgIdPloam[numOfUsMsgIdIndex] = inCounters1.txErrMsgIdPloamCounter[numOfUsMsgIdIndex] -
+                                                    g_OnuGponOutPm.txPloam.txErrMsgIdPloamCounter[numOfUsMsgIdIndex];
+  }
+
+  rxPloamPm->rxMsgTotalPloam = inCounters2.rxMsgTotalPloamCounter - g_OnuGponOutPm.rxPloam.rxMsgTotalPloamCounter;
+
+  for (numOfDsMsgIdIndex = 0 ;numOfDsMsgIdIndex <= ONU_GPON_DS_MSG_LAST ;numOfDsMsgIdIndex++)
+  {
+    rxPloamPm->rxMsgIdPloam[numOfDsMsgIdIndex] = inCounters2.rxMsgIdPloamCounter[numOfDsMsgIdIndex]-
+                                                 g_OnuGponOutPm.rxPloam.rxMsgIdPloamCounter[numOfDsMsgIdIndex];
+  }
+
+  if (a_clear == MV_TRUE)
+  {
+    g_OnuGponOutPm.txPloam.txMsgTotalPloamCounter = inCounters1.txMsgTotalPloamCounter;
+
+    for (numOfUsMsgIdIndex = 0 ;numOfUsMsgIdIndex <= ONU_GPON_US_MSG_LAST ;numOfUsMsgIdIndex++)
+    {
+      g_OnuGponOutPm.txPloam.txErrMsgIdPloamCounter[numOfUsMsgIdIndex] = inCounters1.txErrMsgIdPloamCounter[numOfUsMsgIdIndex];
+      g_OnuGponOutPm.txPloam.txMsgIdPloamCounter[numOfUsMsgIdIndex]    = inCounters1.txMsgIdPloamCounter[numOfUsMsgIdIndex];
+    }
+
+    g_OnuGponOutPm.rxPloam.rxMsgTotalPloamCounter = inCounters2.rxMsgTotalPloamCounter;
+
+    for (numOfDsMsgIdIndex = 0 ;numOfDsMsgIdIndex <= ONU_GPON_DS_MSG_LAST ;numOfDsMsgIdIndex++)
+    {
+      g_OnuGponOutPm.rxPloam.rxMsgIdPloamCounter[numOfDsMsgIdIndex] = inCounters2.rxMsgIdPloamCounter[numOfDsMsgIdIndex];
+
+    }
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiPmRxBwMapPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU
+**               Rx Bw Map counters
+**
+**  PARAMETERS:  S_RxBwMapApiPm *rxBwMapPm
+**               MV_BOOL           a_clear
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiPmRxBwMapPmGet(S_GponIoctlBwMapPm *rxBwMapPm, MV_BOOL a_clear)
+{
+  MV_STATUS   rcode;
+  S_RxBwMapPm inCounters;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiPmRxBwMapPmGet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponPmRxBwMapPmGet(&inCounters);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiPmRxBwMapPmGet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  rxBwMapPm->allocCorrec              = inCounters.allocCorrec              - g_OnuGponOutPm.rxBwMap.allocCorrec;
+  rxBwMapPm->allocCorrectableCrcErr   = inCounters.allocCorrectableCrcErr   - g_OnuGponOutPm.rxBwMap.allocCorrectableCrcErr;
+  rxBwMapPm->allocCrcErr              = inCounters.allocCrcErr              - g_OnuGponOutPm.rxBwMap.allocCrcErr;
+  rxBwMapPm->allocUnCorrectableCrcErr = inCounters.allocUnCorrectableCrcErr - g_OnuGponOutPm.rxBwMap.allocUnCorrectableCrcErr;
+  rxBwMapPm->totalReceivedAllocBytes  = inCounters.totalReceivedAllocBytes  - g_OnuGponOutPm.rxBwMap.totalReceivedAllocBytes;
+
+  if (a_clear == MV_TRUE)
+  {
+    g_OnuGponOutPm.rxBwMap.allocCorrec              = inCounters.allocCorrec;
+    g_OnuGponOutPm.rxBwMap.allocCorrectableCrcErr   = inCounters.allocCorrectableCrcErr;
+    g_OnuGponOutPm.rxBwMap.allocCrcErr              = inCounters.allocCrcErr;
+    g_OnuGponOutPm.rxBwMap.allocUnCorrectableCrcErr = inCounters.allocUnCorrectableCrcErr;
+    g_OnuGponOutPm.rxBwMap.totalReceivedAllocBytes  = inCounters.totalReceivedAllocBytes;
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiPmRxBwMapPmDumpSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable dump BW MAP counters before
+**               ONU state changing
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiPmRxBwMapPmDumpSet(MV_BOOL enable)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiPmRxBwMapPmDumpSet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  if (enable == MV_TRUE)
+  {
+      onuPonTimerDisable(&onuPonResourceTbl_s.onuPonPmTimerId);
+  }
+  else
+  {
+      onuPonTimerEnable(&onuPonResourceTbl_s.onuPonPmTimerId);
+  }
+
+  rcode  = onuGponDbBwMapCntDumpSet(enable);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiExtendedBurstDelaySet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiPmRxBwMapPmDump
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu bw map counters
+**
+**  PARAMETERS:  MV_U32 currstate
+**               MV_U32 newstate
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponApiPmRxBwMapPmDump(MV_U32 currstate, MV_U32 newstate)
+{
+  MV_STATUS          rcode;
+  S_GponIoctlBwMapPm counters;
+
+ // MV_U8 *counterText[] = {"Alloc Crc Error               ",
+ //                         "Alloc Correctable Crc Error   ",
+ //                         "Alloc UnCorrectable Crc Error ",
+ //                         "Alloc Correct                 ",
+ //                         "Total Received Alloc Bytes    "};
+
+  rcode = onuGponApiPmRxBwMapPmGet(&counters, MV_TRUE);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_API_MODULE,
+               "%s:%d, failed to get counters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  //printk("\n");
+  //printk("------------------------------------------------------------\n");
+  printk("ONT STATE CHANGING: FROM [%d] TO [%d] - allocCor[%10u]\n",
+          currstate, newstate, counters.allocCorrec);
+  //printk("-------------------------------------------------------------\n");
+  //printk("| BWMAP COUNTERS                  |   VALUE    |\n");
+  //printk("------------------------------------------------\n");
+  //printk(" %s   | %10u |\n", counterText[0],counters.allocCrcErr);
+  //printk(" %s   | %10u |\n", counterText[1],counters.allocCorrectableCrcErr);
+  //printk(" %s   | %10u |\n", counterText[2],counters.allocUnCorrectableCrcErr);
+  //printk(" %s   | %10u |\n", counterText[3],counters.allocCorrec);
+  //printk(" %s   | %10u |\n", counterText[4],counters.totalReceivedAllocBytes);
+  //printk("------------------------------------------------\n");
+}
+
+/*******************************************************************************
+**
+**  onuGponApiPmRxStandardPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU
+**               Rx Standard counters
+**
+**  PARAMETERS:  S_RxStandardApiPm *rxStandardPm
+**               MV_BOOL              a_clear
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiPmRxStandardPmGet(S_RxStandardApiPm *rxStandardPm, MV_BOOL a_clear)
+{
+  MV_STATUS   rcode;
+  S_RxBip8Pm  inCounter1;
+  S_RxPlendPm inCounter2;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiPmRxStandardPmGet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = onuGponPmRxBip8PmGet(&inCounter1);
+  rcode |= onuGponPmRxPlendPmGet(&inCounter2);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiPmRxStandardPmGet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  rxStandardPm->bip8  = inCounter1.bip8  - g_OnuGponOutPm.rxBip8.bip8;
+  rxStandardPm->plend = inCounter2.plend - g_OnuGponOutPm.rxPlend.plend;
+
+  if (a_clear == MV_TRUE)
+  {
+    g_OnuGponOutPm.rxBip8.bip8   = inCounter1.bip8;
+    g_OnuGponOutPm.rxPlend.plend = inCounter2.plend;
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemRxCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU
+**               GEM counters
+**
+**  PARAMETERS:  S_IoctlGemRxPm *gemPm
+**               MV_BOOL         a_clear
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemRxCounterGet(S_GponIoctlGemRxPm *gemPm, MV_BOOL a_clear)
+{
+  MV_STATUS rcode;
+  S_GemPm   inCounters;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiGemCounterGet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = onuGponPmGemPmGet(&inCounters);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiGemCounterGet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  gemPm->gemRxIdleGemFrames                              = inCounters.receivedIdleGemFrames               -
+                                                           g_OnuGponOutPm.gem.receivedIdleGemFrames;
+  gemPm->gemRxValidGemFrames                             = inCounters.receivedValidGemFrames              -
+                                                           g_OnuGponOutPm.gem.receivedValidGemFrames;
+  gemPm->gemRxUndefinedGemFrames                         = inCounters.receivedUndefinedGemFrames          -
+                                                           g_OnuGponOutPm.gem.receivedUndefinedGemFrames;
+  gemPm->gemRxOmciFrames                                 = inCounters.receivedOmciFrames                  -
+                                                           g_OnuGponOutPm.gem.receivedOmciFrames;
+  gemPm->gemRxDroppedGemFrames                           = inCounters.droppedGemFrames                    -
+                                                           g_OnuGponOutPm.gem.droppedGemFrames;
+  gemPm->gemRxDroppedOmciFrames                          = inCounters.droppedOmciFrames                   -
+                                                           g_OnuGponOutPm.gem.droppedOmciFrames;
+  gemPm->gemRxGemFramesWithUncorrHecErr                  = inCounters.receivedGemFramesWithUncorrHecErr   -
+                                                           g_OnuGponOutPm.gem.receivedGemFramesWithUncorrHecErr;
+  gemPm->gemRxGemFramesWithOneFixedHecErr                = inCounters.receivedGemFramesWithOneFixedHecErr -
+                                                           g_OnuGponOutPm.gem.receivedGemFramesWithOneFixedHecErr;
+  gemPm->gemRxGemFramesWithTwoFixedHecErr                = inCounters.receivedGemFramesWithTwoFixedHecErr -
+                                                           g_OnuGponOutPm.gem.receivedGemFramesWithTwoFixedHecErr;
+  gemPm->gemRxTotalByteCountOfReceivedValidGemFrames     = inCounters.totalByteCountOfReceivedValidGemFrames     -
+                                                           g_OnuGponOutPm.gem.totalByteCountOfReceivedValidGemFrames;
+  gemPm->gemRxTotalByteCountOfReceivedUndefinedGemFrames = inCounters.totalByteCountOfReceivedUndefinedGemFrames -
+                                                           g_OnuGponOutPm.gem.totalByteCountOfReceivedUndefinedGemFrames;
+  gemPm->gemRxGemReassembleMemoryFlush                   = inCounters.gemReassembleMemoryFlush            -
+                                                           g_OnuGponOutPm.gem.gemReassembleMemoryFlush;
+  gemPm->gemRxGemSynchLost                               = inCounters.gemSynchLost                        -
+                                                           g_OnuGponOutPm.gem.gemSynchLost;
+  gemPm->gemRxEthFramesWithCorrFcs                       = inCounters.receivedEthFramesWithCorrFcs        -
+                                                           g_OnuGponOutPm.gem.receivedEthFramesWithCorrFcs;
+  gemPm->gemRxEthFramesWithFcsError                      = inCounters.receivedEthFramesWithFcsError       -
+                                                           g_OnuGponOutPm.gem.receivedEthFramesWithFcsError;
+  gemPm->gemRxOmciFramesWithCorrCrc                      = inCounters.receivedOmciFramesWithCorrCrc       -
+                                                           g_OnuGponOutPm.gem.receivedOmciFramesWithCorrCrc;
+  gemPm->gemRxOmciFramesWithCrcError                     = inCounters.receivedOmciFramesWithCrcError      -
+                                                           g_OnuGponOutPm.gem.receivedOmciFramesWithCrcError;
+  if (a_clear == MV_TRUE)
+  {
+    g_OnuGponOutPm.gem.receivedIdleGemFrames                      = inCounters.receivedIdleGemFrames;
+    g_OnuGponOutPm.gem.receivedValidGemFrames                     = inCounters.receivedValidGemFrames;
+    g_OnuGponOutPm.gem.receivedUndefinedGemFrames                 = inCounters.receivedUndefinedGemFrames;
+    g_OnuGponOutPm.gem.receivedOmciFrames                         = inCounters.receivedOmciFrames;
+    g_OnuGponOutPm.gem.droppedGemFrames                           = inCounters.droppedGemFrames;
+    g_OnuGponOutPm.gem.droppedOmciFrames                          = inCounters.droppedOmciFrames;
+    g_OnuGponOutPm.gem.receivedGemFramesWithUncorrHecErr          = inCounters.receivedGemFramesWithUncorrHecErr;
+    g_OnuGponOutPm.gem.receivedGemFramesWithOneFixedHecErr        = inCounters.receivedGemFramesWithOneFixedHecErr;
+    g_OnuGponOutPm.gem.receivedGemFramesWithTwoFixedHecErr        = inCounters.receivedGemFramesWithTwoFixedHecErr;
+    g_OnuGponOutPm.gem.totalByteCountOfReceivedValidGemFrames     = inCounters.totalByteCountOfReceivedValidGemFrames;
+    g_OnuGponOutPm.gem.totalByteCountOfReceivedUndefinedGemFrames = inCounters.totalByteCountOfReceivedUndefinedGemFrames;
+    g_OnuGponOutPm.gem.gemReassembleMemoryFlush                   = inCounters.gemReassembleMemoryFlush;
+    g_OnuGponOutPm.gem.gemSynchLost                               = inCounters.gemSynchLost;
+    g_OnuGponOutPm.gem.receivedEthFramesWithCorrFcs               = inCounters.receivedEthFramesWithCorrFcs;
+    g_OnuGponOutPm.gem.receivedEthFramesWithFcsError              = inCounters.receivedEthFramesWithFcsError;
+    g_OnuGponOutPm.gem.receivedOmciFramesWithCorrCrc              = inCounters.receivedOmciFramesWithCorrCrc;
+    g_OnuGponOutPm.gem.receivedOmciFramesWithCrcError             = inCounters.receivedOmciFramesWithCrcError;
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemTxCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is used to retrieve and clear (if requested) ONU
+**               Tx counters
+**
+**  PARAMETERS:  S_TxApiPm *txPm
+**               MV_BOOL       a_clear
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemTxCounterGet(S_GponIoctlGemTxPm *txPm, MV_BOOL a_clear)
+{
+	MV_STATUS  rcode;
+	S_GponTxPm inCounters;
+	MV_U32     tcont;
+	MV_BOOL    exist;
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+			   "DEBUG: (%s:%d) onuGponApiTxCounterGet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	rcode = onuGponPmTxPmGet(&inCounters);
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+				   "ERROR: (%s:%d) onuGponApiTxCounterGet", __FILE_DESC__, __LINE__);
+		return(rcode);
+	}
+
+	txPm->gemTxGemPtiTypeOneFrames  = inCounters.transmittedGemPtiTypeOneFrames  - g_OnuGponOutPm.tx.transmittedGemPtiTypeOneFrames;
+	txPm->gemTxGemPtiTypeZeroFrames = inCounters.transmittedGemPtiTypeZeroFrames - g_OnuGponOutPm.tx.transmittedGemPtiTypeZeroFrames;
+	txPm->gemTxIdleGemFrames        = inCounters.transmittedIdleGemFrames        - g_OnuGponOutPm.tx.transmittedIdleGemFrames;
+
+	for (tcont = 0; tcont < ONU_GPON_MAX_NUM_OF_T_CONTS; tcont++) {
+		rcode = onuGponDbBwTcontExist(tcont, &exist);
+		if ((rcode == MV_OK) && (exist != MV_FALSE)) {
+			txPm->gemTxEthFramesViaTconti[tcont]     = inCounters.transmittedEthFramesViaTconti[tcont]     - g_OnuGponOutPm.tx.transmittedEthFramesViaTconti[tcont];
+			txPm->gemTxEthBytesViaTconti[tcont]      = inCounters.transmittedEthBytesViaTconti[tcont]      - g_OnuGponOutPm.tx.transmittedEthBytesViaTconti[tcont];
+			txPm->gemTxGemFramesViaTconti[tcont]     = inCounters.transmittedGemFramesViaTconti[tcont]     - g_OnuGponOutPm.tx.transmittedGemFramesViaTconti[tcont];
+			txPm->gemTxIdleGemFramesViaTconti[tcont] = inCounters.transmittedIdleGemFramesViaTconti[tcont] - g_OnuGponOutPm.tx.transmittedIdleGemFramesViaTconti[tcont];
+		}
+	}
+
+	if (a_clear == MV_TRUE) {
+		g_OnuGponOutPm.tx.transmittedGemPtiTypeOneFrames    = inCounters.transmittedGemPtiTypeOneFrames;
+		g_OnuGponOutPm.tx.transmittedGemPtiTypeZeroFrames   = inCounters.transmittedGemPtiTypeZeroFrames;
+		g_OnuGponOutPm.tx.transmittedIdleGemFrames          = inCounters.transmittedIdleGemFrames;
+
+		for (tcont = 0; tcont < ONU_GPON_MAX_NUM_OF_T_CONTS; tcont++) {
+			rcode = onuGponDbBwTcontExist(tcont, &exist);
+			if ((rcode == MV_OK) && (exist != MV_FALSE)) {
+				g_OnuGponOutPm.tx.transmittedEthFramesViaTconti[tcont]     = inCounters.transmittedEthFramesViaTconti[tcont];
+				g_OnuGponOutPm.tx.transmittedEthBytesViaTconti[tcont]      = inCounters.transmittedEthBytesViaTconti[tcont];
+				g_OnuGponOutPm.tx.transmittedGemFramesViaTconti[tcont]     = inCounters.transmittedGemFramesViaTconti[tcont];
+				g_OnuGponOutPm.tx.transmittedIdleGemFramesViaTconti[tcont] = inCounters.transmittedIdleGemFramesViaTconti[tcont];
+			}
+		}
+	}
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiResetAllCtr
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reset all ONU PM information
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponApiResetAllCtr(void)
+{
+  onuGponPmInPmInit();                                   /* reset pm counters */
+  onuGponBerClear();                                     /* reset ber counters */
+  memset(&(g_OnuGponOutPm), 0, sizeof (g_OnuGponOutPm)); /* reset api counters */
+}
+
+/*******************************************************************************
+**
+**  onuGponApiBurstConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures ONU TX Burst enable parameters
+**
+**  PARAMETERS:  S_apiBurstConfig *burstConfigSet
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiBurstConfigSet(S_apiBurstConfig *burstConfigSet)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiBurstConfigSet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = mvOnuGponMacTxBurstEnParamSet(burstConfigSet->mask,
+                                        burstConfigSet->polarity,
+                                        burstConfigSet->order,
+                                        burstConfigSet->stop,
+                                        burstConfigSet->start);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiPmRxStandardPmGet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  onuGponDbXvrPolaritySet(burstConfigSet->polarity);
+  mvOnuPonMacBurstEnablePolarityInit(burstConfigSet->polarity);
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiBurstConfigGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function retrieves ONU TX Burst enable parameters
+**
+**  PARAMETERS:  S_apiBurstConfig *burstConfigSet
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiBurstConfigGet(S_apiBurstConfig *burstConfigGet)
+{
+  MV_STATUS rcode;
+  MV_U32    mask;
+  MV_U32    polarity;
+  MV_U32    order;
+  MV_U32    stop;
+  MV_U32    start;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiBurstConfigGet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode = mvOnuGponMacTxBurstEnParamGet(&mask, &polarity,&order, &stop, &start);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiBurstConfigGet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  burstConfigGet->start    = start;
+  burstConfigGet->stop     = stop;
+  burstConfigGet->order    = order;
+  burstConfigGet->polarity = polarity;
+  burstConfigGet->mask     = mask;
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiExtendedBurstSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable to override ONU Type 3 preamble
+**               bytes assigned from the OLT with input values
+**
+**  PARAMETERS:  MV_BOOL   enable
+**               MV_U32 range
+**               MV_U32 oper
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiExtendedBurstSet(MV_BOOL enable, MV_U32 range, MV_U32 oper)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiExtendedBurstSet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = onuGponDbExtendedBurstOverrideSet(enable);
+  rcode |= onuGponDbExtendedBurstOverrideValueSet(range , oper);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiExtendedBurstSet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiExtendedBurstDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable to add configured delay to ONU Type 3 preamble
+**               bytes assigned from the OLT with input values
+**
+**  PARAMETERS:  MV_BOOL enable
+**               MV_U32  syncDel
+**               MV_U32  operDel
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiExtendedBurstDelaySet(MV_BOOL enable, MV_U32 syncDel, MV_U32 operDel)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiExtendedBurstDelaySet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = onuGponDbExtendedBurstDelayAddSet(enable);
+  rcode |= onuGponDbExtendedBurstDelayValueSet(syncDel, operDel);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiExtendedBurstDelaySet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiDelimiterSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable to override ONU delimiter
+**               assigned from the OLT with input value
+**
+**  PARAMETERS:  MV_BOOL   enable
+**               MV_U32 delimiter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiDelimiterSet(MV_BOOL enable, MV_U32 delimiter)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiDelimiterSet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = onuGponDbDelimiterOverrideSet(enable);
+  rcode |= onuGponDbDelimiterOverrideValueSet(delimiter);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiDelimiterSet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiOnuIdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable to override ONU ID assigned
+**               from the OLT with input value
+**
+**  PARAMETERS:  MV_BOOL   enable
+**               MV_U32 onuId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiOnuIdSet(MV_BOOL enable, MV_U32 onuId)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiOnuIdSet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = onuGponDbOnuIdOverrideSet(enable);
+  rcode |= onuGponDbOnuIdOverrideValueSet(onuId);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiOnuIdSet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiOmccPortIdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable to override ONU OMCC assigned
+**               from the OLT with input value
+**
+**  PARAMETERS:  MV_BOOL   enable
+**               MV_U32 portId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiOmccPortIdSet (MV_BOOL enable, MV_U32 portId)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiOmccPortIdSet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = onuGponDbOmccPortOverrideSet(enable);
+  rcode |= onuGponDbOmccPortOverrideValueSet(portId);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiOmccPortIdSet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiEqualizationDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable / disable to override ONU Equalization
+**               Delay measured and assigned from the OLT with input value
+**
+**  PARAMETERS:  MV_BOOL   enable
+**               MV_U32 eqD
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiEqualizationDelaySet(MV_BOOL enable, MV_U32 eqD)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiEqualizationDelaySet\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = onuGponDbEqualizationDelayOverrideSet(enable);
+  rcode |= onuGponDbEqualizationDelayOverrideValueSet(eqD);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiEqualizationDelaySet", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiEqualizationDelayChange
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enables changes in the ONU Equalization Delay
+**
+**  PARAMETERS:  MV_U32 direction
+**               MV_U32 size
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiEqualizationDelayChange(MV_U32 direction, MV_U32 size)
+{
+  MV_U32 eqD;
+  MV_U32 newEqD;
+  MV_U32 newFinalEqD;
+  MV_U32 onuState = onuGponDbOnuStateGet();
+  MV_U8  onuId;
+  MV_U8  newEqDelay[5];
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiEqualizationDelayChange\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  if (onuState != ONU_GPON_05_OPERATION)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) EqD change failed. EqD can only be changed in state 05\n", __FILE_DESC__, __LINE__);
+    return(MV_OK);
+  }
+  eqD    = onuGponDbEqualizationDelayGet();
+  newEqD = (direction == 1) ? eqD + size : eqD - size;
+  newFinalEqD = M_ONU_GPON_RANG_MSG_FINAL_DELAY(newEqD);
+
+  if (newFinalEqD < GPON_TX_FINAL_DELAY_MIN || newFinalEqD > GPON_TX_FINAL_DELAY_MAX )
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) EqD change failed. New Final eqD value is out of range\n", __FILE_DESC__, __LINE__);
+    return(MV_OK);
+  }
+
+  newEqDelay[4] = newEqD & 0xFF;        /* LSB */
+  newEqDelay[3] = (newEqD >> 8 )& 0xFF;
+  newEqDelay[2] = (newEqD >> 16)& 0xFF;
+  newEqDelay[1] = (newEqD >> 24)& 0xFF; /* MSB */
+
+  onuId = onuGponDbOnuIdGet();
+  onuGponPonMngPloamProcess(onuId, ONU_GPON_DS_MSG_RANGING_TIME, newEqDelay);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiSnMaskConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure sn mask
+**
+**  PARAMETERS:  MV_BOOL enable
+**               MV_BOOL match
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiSnMaskConfig(MV_BOOL enable, MV_BOOL match)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_API_MODULE,
+             "DEBUG: (%s:%d) onuGponApiSnMaskConfig\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  rcode  = onuGponDbSnMaskSet(enable);
+  rcode |= onuGponDbSerialNumberMaskEnableSet(enable);
+  rcode |= onuGponDbSerialNumberMaskMatchSet (match);
+
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponApiSnMaskConfig\n", __FILE_DESC__, __LINE__);
+  }
+
+  return(rcode);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         GEM Port PM Section                                */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponApiGemPortPmConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures HW so that MIB Counter PM is activated
+**               for a GEM port
+**
+**  PARAMETERS:  S_GponIoctlGemPortPmConfig *
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemPortPmConfig(S_GponIoctlGemPortPmConfig *gponIoctlGemPortPmConfig)
+{
+  MV_STATUS rcode = MV_ERROR;
+
+  if (gponIoctlGemPortPmConfig->gem_port > GPON_MAX_GEMPORTID)
+  {
+      return MV_ERROR;
+  }
+
+  if (gponIoctlGemPortPmConfig->command == GEMPORTPMCMD_START)
+  {
+    rcode = onuGponPmGemPortPmStart(gponIoctlGemPortPmConfig->gem_port);
+  }
+  else if (gponIoctlGemPortPmConfig->command == GEMPORTPMCMD_STOP)
+  {
+    rcode = onuGponPmGemPortPmStop(gponIoctlGemPortPmConfig->gem_port);
+  }
+  return rcode;
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemPortPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function retrieves MIB Counter PM for GEM Port
+**
+**  PARAMETERS:  S_GponIoctlGemPortMibCounters *
+**
+**  OUTPUTS:     MIB counters copied
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemPortPmGet(S_GponIoctlGemPortMibCounters *gemPortMibCounters)
+{
+  MV_STATUS            rcode = MV_OK;
+
+  if (gemPortMibCounters->gem_port > GPON_MAX_GEMPORTID)
+  {
+      return MV_ERROR;
+  }
+
+  rcode = onuGponPmGemPortPmGet(gemPortMibCounters->gem_port, gemPortMibCounters);
+
+  return rcode;
+}
+
+/*******************************************************************************
+**
+**  onuGponApiGemPortPmReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function Reset MIB Counter PM for GEM Port
+**
+**  PARAMETERS:  S_GponIoctlGemPortMibCounters *
+**
+**  OUTPUTS:     MIB counters copied
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiGemPortPmReset(void)
+{
+  MV_STATUS            rcode = MV_OK;
+
+
+  rcode = onuGponPmGemPortPmReset();
+
+  return rcode;
+}
+
+/*******************************************************************************
+**
+**  onuGponApiUponDebugSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Set UPON debug flag
+**
+**  PARAMETERS:  MV_U32 mode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void      onuGponApiUponDebugSet(MV_U32 mode)
+{
+    g_UponDebugMode = mode;
+}
+
+/*******************************************************************************
+**
+**  onuGponApiUponDebugGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Get UPON debug flag
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_U32 mode
+**
+*******************************************************************************/
+MV_U32 onuGponApiUponDebugGet(void)
+{
+    return g_UponDebugMode;
+}
+
+/*******************************************************************************
+**
+**  onuGponApiDgCallbackRegister
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function register Dying Gasp callback function
+**
+**  PARAMETERS:  DYINGGASPFUNC dgCallBack
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiDgCallbackRegister(DYINGGASPFUNC dgCallBack)
+{
+  MV_STATUS status;
+
+  status = onuGponDbDgCallbackSet(dgCallBack);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+               "ERROR: (%s:%d) onuGponDbDgCallbackSet", __FILE_DESC__, __LINE__);
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiLinkStatusCallbackRegister
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function register Link Status callback function
+**
+**  PARAMETERS:  LINKSTATUSFUNC linkStatusCallBack
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponApiLinkStatusCallbackRegister(void)
+{
+  mv_pon_link_state_register(onuGponLinkIsUp,
+  						     &onuGponDb_s.onuGponGenTbl_s.onuLinkStatusCallback);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponLinkIsUp
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function register Link Status callback function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_TRUE or MV_FLASE
+**
+*******************************************************************************/
+MV_BOOL onuGponLinkIsUp(void)
+{
+  if (onuGponDbOnuStateGet() == ONU_GPON_05_OPERATION) return(MV_TRUE);
+  else                                                 return(MV_FALSE);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiAdminStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure PON Admin state
+**
+**  PARAMETERS:  MV_U32 mode 0-Enable, 1 Disable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponApiAdminStateSet(MV_U32 mode)
+{
+  return onuGponAdminStateSet(mode);
+}
+
+/*******************************************************************************
+**
+**  onuGponApiFecStatusGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return FEC Status
+**
+**  PARAMETERS:  MV_U32 fecStatus 0-Off, 1-On
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponApiFecStatusGet(MV_U32 *fecMode)
+{
+  return mvOnuGponMacRxFecStatusGet(fecMode);
+}
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.h
new file mode 100755
index 0000000..962e2d7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuApi.h
@@ -0,0 +1,269 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuApi.h                                                **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON API definitions                **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_API_H

+#define _ONU_GPON_API_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "gponOnuHeader.h"

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+#define GPON_ONU_ITEM_NOT_CONIGURED	  (0xFFFFFFFF)

+

+#define GPON_MAX_GEMPORTID            (4095)

+

+/* Notify Types */

+#define GPON_NOTIFY_OPERATION		  (0)

+#define GPON_NOTIFY_ALARM			  (1)

+#define GPON_NOTIFY_OMCC			  (2

+

+/* Counter Sizes */

+#define GPON_ONU_RX_PLOAM_CNT_SIZE    (21)

+#define GPON_ONU_TX_PLOAM_CNT_SIZE    (10)

+

+/* Operational Statuses */

+#define GPON_ONU_STATUS_DISCONNECTED  (0)                       /* No Downstream sync */

+#define GPON_ONU_STATUS_NOT_RANGED	  (1)                       /* Downstream sync, not ranged */

+#define GPON_ONU_STATUS_RANGED		  (2)                       /* Ranged */

+#define GPON_ONU_STATUS_MAX			  (GPON_ONU_STATUS_RANGED)

+

+/* Alarms */

+#define GPON_ONU_ALARM_LOS			  (0)

+#define GPON_ONU_ALARM_LOF			  (1)

+#define GPON_ONU_ALARM_LCDA			  (2)

+#define GPON_ONU_ALARM_LCDG			  (3)

+#define GPON_ONU_ALARM_SF			  (4)

+#define GPON_ONU_ALARM_SD			  (5)

+#define GPON_ONU_ALARM_TF			  (6)

+#define GPON_ONU_ALARM_SUF			  (7)

+#define GPON_ONU_ALARM_MEM			  (8)

+#define GPON_ONU_ALARM_DACT			  (9)

+#define GPON_ONU_ALARM_DIS			  (10)

+#define GPON_ONU_ALARM_MIS			  (11)

+#define GPON_ONU_ALARM_PEE			  (12)

+#define GPON_ONU_ALARM_RDI			  (13)

+

+#define GPON_ONU_ALARM_STATUS_OFF	  (0)

+#define GPON_ONU_ALARM_STATUS_ON	  (1)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Structs                              

+------------------------------------------------------------------------------*/ 

+typedef struct

+{

+  MV_U8   password[10];

+  MV_U8   serialNumber[8];

+  MV_U32  onuId;

+  MV_U32  state;

+  MV_U32  sdThreshold;

+  MV_U32  sfThreshold;

+  MV_U32  localBerInterval;

+  MV_U32  remoteBerInterval;

+  MV_U32  omccPortId;

+  MV_U32  constDelay;

+  MV_U32  eqDelay;

+}S_OnuInfo;

+

+typedef struct

+{

+  MV_U32  bip8;

+  MV_U32  plend;

+}S_RxStandardApiPm;

+

+typedef struct

+{

+  MV_U32  start;

+  MV_U32  stop;

+  MV_U32  order;

+  MV_U32  polarity;

+  MV_U32  mask;

+}S_apiBurstConfig;

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef void (*ALARMNOTIFYFUNC)(MV_U32 alarm, MV_U32 status);     

+typedef void (*OMCCNOTIFYFUNC)(MV_U32 omccPortId);     

+typedef void (*DISABLENOTIFYFUNC)(MV_BOOL disable);     

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Init API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiInit(MV_U8 *serialNumber, MV_U8 *password, MV_BOOL disabled, MV_U32 sn_src);

+

+/* Notify API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiStatusNotifyRegister(STATUSNOTIFYFUNC notifyCallBack);

+MV_STATUS onuGponApiAlarmNotifyRegister(ALARMNOTIFYFUNC notifyCallBack);

+MV_STATUS onuGponApiOmccNotifyRegister(OMCCNOTIFYFUNC notifyCallBack);

+MV_STATUS onuGponApiDisableNotifyRegister(DISABLENOTIFYFUNC notifyCallBack);

+

+/* Ber API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiBerThresholdConfig(MV_U32 sd, MV_U32 sf);

+MV_STATUS onuGponApiBerIntervalConfig(MV_U32 interval);

+MV_STATUS onuGponApiBerCoefficientConfig(MV_U32 denominator, MV_U32 numerator);

+

+/* Tcont API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiTcontConfig(MV_U32 allocId, MV_U32 tcontId);

+MV_STATUS onuGponApiTcontClear(MV_U32 tcontId);

+MV_STATUS onuGponApiTcontsReset(void);

+

+/* GEM API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiGemOmccIdConfig(MV_U32 gemPortid, MV_BOOL valid);

+MV_STATUS onuGponApiGemPortIdConfig(MV_U32 gemPortid);

+MV_STATUS onuGponApiGemPortIdClear(MV_U32 gemPortid);

+#ifdef MV_GPON_STATIC_GEM_PORT

+MV_STATUS onuGponApiGemPortIdStaticConfigReset(void);

+MV_STATUS onuGponApiGemPortIdStaticConfigFlag(MV_U32 flag);

+MV_STATUS onuGponApiGemConfig(MV_U32* gemmap, E_GponIoctlGemAction action);

+MV_STATUS onuGponApiGemClearAll(MV_BOOL savePorts);

+MV_STATUS onuGponApiGemRestoreAll(void);

+#endif /* MV_GPON_STATIC_GEM_PORT */

+

+/* Information API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiInformationGet(S_OnuInfo *onuInfo);

+

+/* Alarm API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiAlarmsGet(MV_U32 *alarms);

+

+/* PM API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiPmFecPmGet(S_GponIoctlFecPm *fecPm, MV_BOOL a_clear);

+MV_STATUS onuGponApiPmRxPloamPmGet(S_GponIoctlPloamRxPm *rxPloamPm, MV_BOOL a_clear);

+MV_STATUS onuGponApiPmRxBwMapPmGet(S_GponIoctlBwMapPm *rxBwMapPm, MV_BOOL a_clear);

+MV_STATUS onuGponApiPmRxBwMapPmDumpSet(MV_BOOL enable);

+void      onuGponApiPmRxBwMapPmDump(MV_U32 currstate, MV_U32 newstate);

+MV_STATUS onuGponApiAdvancedPloamsCounterGet(S_GponIoctlPloamTxPm *txPloamPm, S_GponIoctlPloamRxPm *rxPloamPm, MV_BOOL a_clear);

+MV_STATUS onuGponApiGemRxCounterGet(S_GponIoctlGemRxPm *gemPm, MV_BOOL a_clear);

+MV_STATUS onuGponApiGemTxCounterGet(S_GponIoctlGemTxPm *txPm, MV_BOOL a_clear);

+MV_STATUS onuGponApiPmRxStandardPmGet(S_RxStandardApiPm *rxStandardPm, MV_BOOL a_clear);

+

+/* Genral API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiBurstConfigSet(S_apiBurstConfig *burstConfigSet);

+MV_STATUS onuGponApiBurstConfigGet(S_apiBurstConfig *burstConfigGet);

+void      onuGponApiResetAllCtr(void);

+void      onuGponApiUponDebugSet(MV_U32 mode);

+MV_U32    onuGponApiUponDebugGet(void);

+MV_STATUS onuGponApiAdminStateSet(MV_U32 mode);

+MV_STATUS onuGponApiFecStatusGet(MV_U32 *fecMode);

+

+/* Sn Mask  API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiSnMaskConfig(MV_BOOL enable, MV_BOOL match);

+

+/* Interoperability API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiExtendedBurstSet(MV_BOOL enable, MV_U32 range, MV_U32 oper);

+MV_STATUS onuGponApiExtendedBurstDelaySet(MV_BOOL enable, MV_U32 syncDel, MV_U32 operDel);

+MV_STATUS onuGponApiDelimiterSet(MV_BOOL enable, MV_U32 delimiter);

+MV_STATUS onuGponApiOnuIdSet(MV_BOOL enable, MV_U32 onuId);

+MV_STATUS onuGponApiOmccPortIdSet(MV_BOOL enable, MV_U32 portId);

+MV_STATUS onuGponApiEqualizationDelaySet(MV_BOOL enable, MV_U32  eqD); 

+MV_STATUS onuGponApiEqualizationDelayChange(MV_U32 direction, MV_U32 size);

+

+/* GEM Port MIB Counters PM  API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiGemPortPmConfig(S_GponIoctlGemPortPmConfig *ioctlGemPortPmConfig);

+MV_STATUS onuGponApiGemPortPmGet(S_GponIoctlGemPortMibCounters *ioctlGemPortMibCounters);

+MV_STATUS onuGponApiGemPortPmReset(void);

+

+/* Dying Gasp API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiDgCallbackRegister(DYINGGASPFUNC dgCallBack);

+

+/* Link status API

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponApiLinkStatusCallbackRegister(void);

+MV_BOOL onuGponLinkIsUp(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_API_H */

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuBer.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuBer.c
new file mode 100755
index 0000000..123e8f7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuBer.c
@@ -0,0 +1,547 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuBer.c                                               **

+**                                                                           **

+**  DESCRIPTION : This file implements the OLT GPON Bit Error Rate Mechanism **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "gponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/  

+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuBer.c"

+

+#define PON_BER_PERIOD_LENGTH  (ONU_PON_TIMER_PM_INTERVAL)

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+MV_U32           g_numsOfPeriodInInterval;

+MV_U32           g_intervalSeconds;

+S_BerCoefficient g_berCoefficient;

+S_PonBer         onuBer;

+

+/* Local Prototypes

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+

+/*******************************************************************************

+**

+**  onuGponBerInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function init onu BER parameters

+**                 

+**  PARAMETERS:  S_BerCoefficient coefficient - the perdentage of the current BER in overall BER

+**			     MV_U32			  interval    - the interval of BER measures (seconds)    

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuGponBerInit(S_BerCoefficient *coefficient, MV_U32 interval)

+{

+  /* Keep how many periods pass before BER is checked */

+  g_numsOfPeriodInInterval     = (interval * 1000) / PON_BER_PERIOD_LENGTH;

+  g_intervalSeconds            = interval;

+  g_berCoefficient.numerator   = coefficient->numerator;

+  g_berCoefficient.denominator = coefficient->denominator;

+

+  onuGponBerClear();

+

+  return(MV_OK);

+}     

+

+/*******************************************************************************

+**

+**  onuGponBerPeriodPass

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function calculate BER if interval expired

+**                 

+**  PARAMETERS:  S_BerCoefficient coefficient - the perdentage of the current BER in overall BER

+**			     MV_U32			  interval    - the interval of BER measures (seconds)    

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuGponBerPeriodPass(MV_U32 inbip8Counter)

+{

+  onuBer.periodsCounter++;

+  onuBer.intervalBandwidth += ONU_GPON_DS_DEF_RATE;

+

+  /* Check if is BER caculating Time */

+  if (onuBer.periodsCounter < g_numsOfPeriodInInterval)

+  {

+    /* Do nothing */

+    return(MV_OK);

+  }

+  else

+  {

+    /* Need to calculate BER */

+    onuGponBerBerCaculate(inbip8Counter);

+    onuBer.periodsCounter = 0;

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponBerBerCaculate

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: This routine Calculate the BER

+**				 NIOS doen't support floating-point, so we need to pass that limit:

+**				 We use this method OvarallBER(n) = Coefficient * IntervalBer(n) + 

+**				 								  (1 - Coefficient) * OvarallBER(n-1)

+**				 Coefficient is structure of ( numerator / denominator )

+**				 IntervalBer is Bip8Counter(Interval)/OverallBits(Interval)

+**				 Since the lowest BER we'd like to measure is 10^(-10) (standard lowest 

+**				 value to Cacel SD condition), we shell multiple all values by 10^(10).

+**				 The thresholds also will be multiple by 10^(10).

+**				 The Ber calculation will be as the following (for 1.244 upstream rate):

+**

+**                  Bip8Counter(Interval) x 10^11     Bip8Counter(Interval) x 10^11

+**				 IntervalBer(n) = ---------------------------- = ---------------------------------

+**				                      OverallBits(Interval)        actual bits passed(Interval)

+**

+**				                    Bip8Counter(Interval) x 10^5

+**				                = --------------------------------

+**                              Mbits 

+**

+**				                 (IntervalBer(n) x Coef.numerator) + (OverAllBer(n-1) x (Coef.denominator - Coef.numerator))

+**				 OverAllBer(n) = -------------------------------------------------------------------------------------------

+**				                                                    Coef.denominator          

+**

+**  PARAMETERS:	 MV_U32 inbip8Counter

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuGponBerBerCaculate(MV_U32 inbip8Counter)

+{

+  onuBer.intervalBip8ErrorsCounter = inbip8Counter - onuBer.outBip8Counter;

+  onuBer.newBer = (onuBer.intervalBip8ErrorsCounter * 100000) / onuBer.intervalBandwidth;

+

+  onuBer.ber = ((g_berCoefficient.numerator * onuBer.newBer) +

+                (( g_berCoefficient.denominator - g_berCoefficient.numerator ) * onuBer.ber))

+               / g_berCoefficient.denominator;

+

+  onuGponBerAlarmsCheck(onuBer.ber);

+  onuBer.outBip8Counter = inbip8Counter;

+  onuBer.intervalBandwidth = 0;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponBerAlarmsCheck

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: This routine check the Ber Value and decide whether there is a

+**				 change in the alarms SD and SF condistion. 

+**               

+**  PARAMETERS:	 MV_U32 ber

+**

+**  OUTPUTS:     None  

+**

+**  RETURNS:     MV_OK  

+**

+*******************************************************************************/

+MV_STATUS onuGponBerAlarmsCheck(MV_U32 ber)

+{

+  MV_U32  sdThreshold;

+  MV_U32  sfThreshold;

+  MV_U32  sdDetectValue;

+  MV_U32  sdCancelValue;

+  MV_U32  sfDetectValue;

+  MV_U32  sfCancelValue;

+  MV_BOOL onuSd;

+  MV_BOOL onuSf;

+  MV_BOOL sd = MV_FALSE;

+  MV_BOOL sf = MV_FALSE;

+

+  /* Get curent alarm condition */

+  onuSf         = onuGponAlarmGet(ONU_GPON_ALARM_SF);

+  onuSd         = onuGponAlarmGet(ONU_GPON_ALARM_SD);

+               

+  sfThreshold   = onuGponDbSfThresholdGet();

+  sdThreshold   = onuGponDbSdThresholdGet();

+

+  sdDetectValue = onuGponBerPower(10 ,(11 - sdThreshold));

+  sdCancelValue = onuGponBerPower(10 ,(11 - sdThreshold - 1));

+  sfDetectValue = onuGponBerPower(10 ,(11 - sfThreshold));

+  sfCancelValue = onuGponBerPower(10 ,(11 - sfThreshold - 1));

+

+  /* check Detect Alarm */

+  if ( ber >= sfDetectValue)

+  {

+    sf = MV_TRUE;

+  }

+  else if (ber >= sdDetectValue)

+  {

+    sd = MV_TRUE;

+  }

+

+  /* check Cancel Alarm */

+  if ( ber < sdCancelValue)

+  {

+    sd = MV_FALSE;

+  }

+  else if (ber < sfCancelValue)

+  {

+    sf = MV_FALSE;

+  }

+

+  if ((onuSf == MV_FALSE) && (onuSd == MV_FALSE))

+  {

+    if ((sd == MV_FALSE) && (sf == MV_TRUE))

+    {

+      onuGponAlarmSet(ONU_GPON_ALARM_SF,MV_TRUE);

+      onuGponSrvcAlarmNotify(ONU_GPON_ALARM_SF,MV_TRUE);

+    }

+    else if ((sd == MV_TRUE) && (sf == MV_FALSE))

+    {

+      onuGponAlarmSet(ONU_GPON_ALARM_SD,MV_TRUE);

+      onuGponSrvcAlarmNotify(ONU_GPON_ALARM_SD,MV_TRUE);

+    }

+  }

+  else if ((onuSf == MV_TRUE) && (onuSd == MV_FALSE))

+  {

+    if ((sd == MV_FALSE) && (sf == MV_FALSE))

+    {

+      onuGponAlarmSet(ONU_GPON_ALARM_SF,MV_FALSE);

+      onuGponSrvcAlarmNotify(ONU_GPON_ALARM_SF,MV_FALSE);

+    }

+    else if ((sd == MV_TRUE) && (sf == MV_FALSE))

+    {

+      onuGponAlarmSet(ONU_GPON_ALARM_SD,MV_TRUE);

+      onuGponSrvcAlarmNotify(ONU_GPON_ALARM_SD,MV_TRUE);

+

+      onuGponAlarmSet(ONU_GPON_ALARM_SF,MV_FALSE);

+      onuGponSrvcAlarmNotify(ONU_GPON_ALARM_SF,MV_FALSE);

+    }

+  }

+  else if ((onuSf == MV_FALSE) && (onuSd == MV_TRUE))

+  {

+    if ((sd == MV_FALSE) && (sf == MV_FALSE))

+    {

+      onuGponAlarmSet(ONU_GPON_ALARM_SD,MV_FALSE);

+      onuGponSrvcAlarmNotify(ONU_GPON_ALARM_SD,MV_FALSE);

+    }

+    else if ((sd == MV_FALSE) && (sf == MV_TRUE))

+    {

+      onuGponAlarmSet(ONU_GPON_ALARM_SD,MV_FALSE);

+      onuGponSrvcAlarmNotify(ONU_GPON_ALARM_SD,MV_FALSE);

+

+      onuGponAlarmSet(ONU_GPON_ALARM_SF,MV_TRUE);

+      onuGponSrvcAlarmNotify(ONU_GPON_ALARM_SF,MV_TRUE);

+    }

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponBerClear

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function clear all BER counters and thresholds  

+**               

+**  PARAMETERS:	 None

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     None

+**

+*******************************************************************************/

+void onuGponBerClear(void)

+{

+  onuBer.periodsCounter            = 0;

+  onuBer.intervalBip8ErrorsCounter = 0;

+  onuBer.ber                       = 0;

+  onuBer.newBer                    = 0;

+  onuBer.outBip8Counter            = 0;

+  onuBer.intervalBandwidth         = 0;

+

+  onuGponAlarmSet(ONU_GPON_ALARM_SD, MV_FALSE);

+  onuGponAlarmSet(ONU_GPON_ALARM_SF, MV_FALSE);

+}

+

+/*******************************************************************************

+**

+**  onuGponBerBip8CounterGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return bip8 counter 

+**               

+**  PARAMETERS:	 None

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     bip8 counter

+**

+*******************************************************************************/

+MV_U32 onuGponBerBip8CounterGet(void)

+{

+  MV_U32     counter;

+  S_RxBip8Pm inBip8Pm;

+

+  onuGponPmRxBip8PmGet(&inBip8Pm);

+  counter = inBip8Pm.bip8 - onuBer.outBip8Counter;

+

+  return(counter); 

+}

+

+/*******************************************************************************

+**

+**  onuGponBerLastIntervalBip8CounterGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return bip8 counter of the last interval

+**               

+**  PARAMETERS:	 None

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     bip8 counter

+**

+*******************************************************************************/

+MV_U32 onuGponBerLastIntervalBip8CounterGet(void)

+{

+  MV_U32 counter;

+

+  counter = onuBer.intervalBip8ErrorsCounter;

+

+  return(counter); 

+}

+

+/*******************************************************************************

+**

+**  onuGponBerBerValueGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu ber

+**               

+**  PARAMETERS:	 None

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     onu ber

+**

+*******************************************************************************/

+MV_U32 onuGponBerBerValueGet(void)

+{

+  return(onuBer.ber); 

+}

+

+/*******************************************************************************

+**

+**  onuGponBerIntervalBerValueGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return ber interval value

+**               

+**  PARAMETERS:	 None

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     ber interval

+**

+*******************************************************************************/

+MV_U32 onuGponBerIntervalBerValueGet(void)

+{

+  return(onuBer.newBer); 

+}

+

+/*******************************************************************************

+**

+**  onuGponBerCoefficientGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return ber coefficient

+**               

+**  PARAMETERS:	 None

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     ber coefficient

+**

+*******************************************************************************/

+S_BerCoefficient onuGponBerCoefficientGet(void)

+{

+  return(g_berCoefficient); 

+}

+

+/*******************************************************************************

+**

+**  onuGponBerIntervalSecondsGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return ber interval in seconds

+**               

+**  PARAMETERS:	 None

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     ber interval in seconds

+**

+*******************************************************************************/

+MV_U32 onuGponBerIntervalSecondsGet(void)

+{

+  return(g_intervalSeconds); 

+}

+

+/*******************************************************************************

+**

+**  onuGponBerCoefficientSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set ber coefficient

+**               

+**  PARAMETERS:	 S_BerCoefficient *coefficient

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     None

+**

+*******************************************************************************/

+void onuGponBerCoefficientSet(S_BerCoefficient *coefficient)

+{

+  g_berCoefficient.numerator   = coefficient->numerator;

+  g_berCoefficient.denominator = coefficient->denominator;

+}

+

+/*******************************************************************************

+**

+**  onuGponBerIntervalSet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set ber interval

+**               

+**  PARAMETERS:	 MV_U32 interval

+**

+**  OUTPUTS:     None 

+**

+**  RETURNS:     None

+**

+*******************************************************************************/

+void onuGponBerIntervalSet(MV_U32 interval)

+{

+  g_intervalSeconds        = interval;

+  g_numsOfPeriodInInterval = (interval * 1000) / PON_BER_PERIOD_LENGTH;

+  onuGponDbBerCalcIntervalSet(interval);

+}

+

+/*******************************************************************************

+**

+**  onuGponBerPower

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function is a BER utility function

+**               

+**  PARAMETERS:	 MV_U32 x

+**               MV_U32 y

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     calculated value  

+**

+*******************************************************************************/

+MV_U32 onuGponBerPower(MV_U32 x, MV_U32 y)

+{

+  MV_U32  i;

+  MV_U32  sum = 1;

+

+  for (i = 0 ; i < y ; i++)

+  {

+    sum = sum*x;

+  }

+

+  return(sum); 

+}

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuBer.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuBer.h
new file mode 100755
index 0000000..d7e563d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuBer.h
@@ -0,0 +1,143 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuBer.h                                               **

+**                                                                           **

+**  DESCRIPTION : This is header file of external interface of OLT           **

+**		    	  GPON BER mechnism                                          **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef PON_ONU_BER_H

+#define PON_ONU_BER_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+

+/* Definitions

+------------------------------------------------------------------------------*/

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Structs

+------------------------------------------------------------------------------*/

+typedef struct

+{

+  MV_U32 periodsCounter;

+  MV_U32 intervalBip8ErrorsCounter;

+  MV_U32 ber;

+  MV_U32 newBer;

+  MV_U32 outBip8Counter;

+  MV_U32 intervalBandwidth;

+}S_PonBer;

+

+typedef struct

+{

+  MV_U32 numerator;

+  MV_U32 denominator;

+}S_BerCoefficient;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Prototypes

+------------------------------------------------------------------------------*/  

+MV_STATUS        onuGponBerInit(S_BerCoefficient *coefficient, MV_U32 interval);

+MV_STATUS        onuGponBerPeriodPass(MV_U32 inbip8Counter);

+MV_STATUS        onuGponBerBerCaculate(MV_U32 inbip8Counter);

+MV_STATUS        onuGponBerAlarmsCheck(MV_U32 ber);

+void             onuGponBerClear(void); 

+MV_U32           onuGponBerBip8CounterGet(void);

+MV_U32           onuGponBerLastIntervalBip8CounterGet(void);

+MV_U32           onuGponBerBerValueGet(void);

+MV_U32           onuGponBerIntervalBerValueGet(void);

+S_BerCoefficient onuGponBerCoefficientGet(void);

+MV_U32           onuGponBerIntervalSecondsGet(void);

+void             onuGponBerCoefficientSet(S_BerCoefficient *coefficient);

+void             onuGponBerIntervalSet(MV_U32 interval);

+MV_U32           onuGponBerPower(MV_U32 x, MV_U32 y);

+

+#endif /* PON_ONU_BER_H */

+

+

+

+

+

+

+ 

+ 

+ 

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.c
new file mode 100755
index 0000000..8e48a4b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.c
@@ -0,0 +1,3446 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuDb.c                                                **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON database functionality       **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "gponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuDb.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+/* ONU GPON Database */
+S_OnuGponDb onuGponDb_s;
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+MV_U8 onuGponPassword[ONU_GPON_PASS_LEN] = {0x01, 0x02, 0x03, 0x04, 0x05,
+                                             0x0A, 0x0B, 0x0C, 0x0D, 0x0E};
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+void      onuGponDbOnuGenTblInit(void);
+void      onuGponDbOnuSyncParamTblInit(void);
+void      onuGponDbOnuOperParamTblInit(void);
+MV_STATUS onuGponDbGemPortAesClearAll(void);
+MV_STATUS onuGponDbSerialNumberMaskEnableSet(MV_BOOL a_SerialNumberMaskEnable);
+MV_BOOL   onuGponDbSerialNumberMaskEnableGet(void);
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Initialization Section                             */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponDbDbInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu database to default values
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbInit (void)
+{
+  MV_STATUS rcode = MV_OK;
+
+  onuGponDbOnuGenTblInit();
+  onuGponDbOnuSyncParamTblInit();
+  onuGponDbOnuOperParamTblInit();
+  onuGponDbBwAllocInit();
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuGenTblInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu database general table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbOnuGenTblInit(void)
+{
+  /* clear onu database general table */
+  memset((&(onuGponDb_s.onuGponGenTbl_s)), 0, sizeof (S_OnuGponGenTbl));
+
+  /* set onu to state 01 */
+  onuGponDbOnuStateSet(GPON_ONU_ID_STATE_01);
+
+  /* set onu Id to undefined onu */
+  onuGponDbOnuIdSet(GPON_ONU_ID_ONU_ID_DEF);
+
+  /* set gpon rate to default value */
+  onuGponDbRateSet(GPON_FRAME_DELINEATION_FR);
+
+  /* set gpon xvr polarity to default value */
+  onuGponDbXvrPolaritySet(ONU_PON_XVR_POLARITY_ACT_HIGH);
+
+  /* set onu init status to be MV_FALSE */
+  onuGponDbInitSet(MV_FALSE);
+
+  /* set OMCC Valid to be MV_FALSE */
+  onuGponDbOmccValidSet(MV_FALSE);
+
+  /* set OnuId Override to be MV_FALSE */
+  onuGponDbOnuIdOverrideSet(MV_FALSE);
+
+  /* Set NULL in Notify functions */
+  onuGponDbAlarmNotifySet(NULL);
+  onuGponDbStatusNotifySet(NULL);
+  onuGponDbOmccNotifySet(NULL);
+  onuGponDbDisableNotifySet(NULL);
+
+  onuGponDbOmccPortSet(0xFFFF);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuSyncParamTblInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu database sync params table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbOnuSyncParamTblInit(void)
+{
+  MV_U32 IdleMsgData[ONU_GPON_MSG_LEN];
+  MV_U32 snMsgData[ONU_GPON_MSG_LEN];
+  MV_U8  serialNumber[ONU_GPON_SN_LEN];
+
+  /* clear onu database sync params table */
+  memset ((&(onuGponDb_s.onuGponSyncParamsTbl_s)), 0, sizeof (S_OnuGponSyncParamsTbl));
+
+  /* set onu guard bits */
+  onuGponDbGuardBitsSet(0);
+
+  /* set onu delays */
+  onuGponDbConstDelaySet(GPON_TX_DELAY_TD_1244);
+  onuGponDbEqualizationDelaySet(GPON_TX_EQUAL_DELAY_TD);
+
+  /* set onu preamble */
+  onuGponDbPreambleSet(ONU_GPON_PREM_TYPE_01, ONU_TX_PREAMBLE_TYPE_01_P, ONU_TX_PREAMBLE_TYPE_01_PC);
+  onuGponDbPreambleSet(ONU_GPON_PREM_TYPE_02, ONU_TX_PREAMBLE_TYPE_02_P, ONU_TX_PREAMBLE_TYPE_02_PC);
+  onuGponDbPreambleSet(ONU_GPON_PREM_TYPE_03, ONU_TX_PREAMBLE_TYPE_03_P, ONU_TX_PREAMBLE_TYPE_03_DEF_PC);
+
+  /* set onu delimiter */
+  onuGponDbDelimiterSet(ONU_GPON_DELM_BYTE_01, GPON_TX_DELIMITER_D0);
+  onuGponDbDelimiterSet(ONU_GPON_DELM_BYTE_02, GPON_TX_DELIMITER_D1);
+  onuGponDbDelimiterSet(ONU_GPON_DELM_BYTE_03, GPON_TX_DELIMITER_D2);
+  onuGponDbDelimiterSizeSet(GPON_TX_DELIMITER_DS);
+  onuGponDbDelimiterOverrideSet (MV_FALSE);
+
+  /* set onu serial number */
+  serialNumber[0] = ONU_GPON_SN_DEF_BYTE_1;
+  serialNumber[1] = ONU_GPON_SN_DEF_BYTE_2;
+  serialNumber[2] = ONU_GPON_SN_DEF_BYTE_3;
+  serialNumber[3] = ONU_GPON_SN_DEF_BYTE_4;
+  serialNumber[4] = ONU_GPON_SN_DEF_BYTE_5;
+  serialNumber[5] = ONU_GPON_SN_DEF_BYTE_6;
+  serialNumber[6] = ONU_GPON_SN_DEF_BYTE_7;
+  serialNumber[7] = ONU_GPON_SN_DEF_BYTE_8;
+
+  /* set onu serial number mask parametrs */
+  onuGponDbSerialNumberMaskEnableSet(ONU_GPON_SN_MSK_GEN_ENA);
+  onuGponDbSerialNumberMaskMatchSet(ONU_GPON_SN_MSK_DEF_MATCH);
+  onuGponDbSnMaskSet(MV_FALSE);
+
+  onuGponDbSerialNumSet (&(serialNumber[0]));
+
+  IdleMsgData[0] = ((MV_U32)0) |
+                   (((MV_U32)0) << 8) |
+                   (((MV_U32)ONU_GPON_IDLE_MSG_DEF_BYTE_02) << 16) |
+                   (((MV_U32)ONU_GPON_IDLE_MSG_DEF_BYTE_01) << 24);
+  IdleMsgData[1] = ((MV_U32)0) |
+                   (((MV_U32)0) << 8) |
+                   (((MV_U32)0) << 16) |
+                   (((MV_U32)0) << 24);
+  IdleMsgData[2] = ((MV_U32)0) |
+                   (((MV_U32)0) << 8) |
+                   (((MV_U32)0) << 16) |
+                   (((MV_U32)0) << 24);
+
+  onuGponDbIdleMsgSet(IdleMsgData);
+
+  snMsgData[0] = ((MV_U32)serialNumber[1]) |
+                 (((MV_U32)serialNumber[0]) << 8) |
+                 (((MV_U32)ONU_GPON_SN_MSG_DEF_BYTE_02) << 16) |
+                 (((MV_U32)ONU_GPON_SN_MSG_DEF_BYTE_01) << 24);
+  snMsgData[1] = ((MV_U32)serialNumber[5]) |
+                 (((MV_U32)serialNumber[4]) << 8) |
+                 (((MV_U32)serialNumber[3]) << 16) |
+                 (((MV_U32)serialNumber[2]) << 24);
+  snMsgData[2] = ((MV_U32)ONU_GPON_SN_MSG_DEF_BYTE_12) |
+                 (((MV_U32)ONU_GPON_SN_MSG_DEF_BYTE_11) << 8) |
+                 (((MV_U32)serialNumber[7]) << 16) |
+                 (((MV_U32)serialNumber[6]) << 24);
+
+  onuGponDbSnMsgSet(snMsgData);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuOperParamTblInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu database oper params table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbOnuOperParamTblInit(void)
+{
+  /* clear onu database oper params table */
+  memset((&(onuGponDb_s.onuGponOperParamsTbl_s)), 0, sizeof (S_OnuGponOperParamsTbl));
+
+  /* set ber, signal fail threshold and signal degraded threshold */
+  onuGponDbBerIntervalSet(GPON_BIP_PERIOD_CNTR);
+  onuGponDbBerCalcIntervalSet(ONU_GPON_DEF_INTERNAL_BER_INTERVAL);
+  onuGponDbSfThresholdSet(ONU_GPON_DEF_SF_THRESHOLD);
+  onuGponDbSdThresholdSet(ONU_GPON_DEF_SD_THRESHOLD);
+
+  /* Init GEM Port AES table */
+  onuGponDbGemPortAesClearAll();
+
+  /* Init GEM Port table */
+  onuGponDbGemPortClearAll();
+  onuGponDbGemPortSavedClearAll();
+
+  /* set onu REI sequence number */
+  onuGponDbReiSeqNumSet(ONU_GPON_DEF_REI_SEQ_NUM);
+
+  /* set onu password */
+  onuGponDbPasswordSet(&(onuGponPassword[0]));
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwAllocInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu database bandwidth allocation table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwAllocInit(void)
+{
+	MV_U32 iEntry;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		onuGponDbBwTcontSet(iEntry, MV_FALSE, PON_ONU_ALLOC_NOT_EXIST, MV_FALSE);
+		onuGponDbBwAllocSet(iEntry, PON_ONU_ALLOC_NOT_EXIST, MV_FALSE);
+		onuGponDbBwIdleAllocSet(iEntry, PON_ONU_ALLOC_NOT_EXIST);
+	}
+
+	return(MV_OK);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Interface Section                                  */
+/* ========================================================================== */
+/******************************************************************************/
+
+/********************************************/
+/* ======================================== */
+/*   ONU GPON General Table API Functions   */
+/* ======================================== */
+/********************************************/
+
+/*******************************************************************************
+**
+**  onuGponDbOnuStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu state in the database
+**
+**  PARAMETERS:  E_OnuState onuState_e - ONU_GPON_01_INIT
+**                                       ONU_GPON_02_STANDBY
+**                                       ONU_GPON_03_SERIAL_NUM
+**                                       ONU_GPON_04_RANGING
+**                                       ONU_GPON_05_OPERATION
+**  									 ONU_GPON_06_POPUP
+**  									 ONU_GPON_07_EMERGANCY_STOP
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOnuStateSet(MV_U32 onuState)
+{
+  if ((onuState < ONU_GPON_01_INIT) ||
+      (onuState > ONU_GPON_07_EMERGANCY_STOP))
+  {
+    return(MV_ERROR);
+  }
+
+  onuGponDb_s.onuGponGenTbl_s.onuGponOnuState = onuState;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuStateGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu state
+**
+*******************************************************************************/
+MV_U32 onuGponDbOnuStateGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponOnuState);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuIdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu Id in the database
+**
+**  PARAMETERS:  MV_U32 onuId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOnuIdSet(MV_U32 onuId)
+{
+  MV_U32 idleMsg[3];
+  MV_U32 snNumMsg[3];
+
+  onuGponDb_s.onuGponGenTbl_s.onuGponOnuId = onuId;
+
+  onuGponDbIdleMsgGet(idleMsg);
+
+  idleMsg[0] &= (0x00FFFFFF);
+  idleMsg[0] |=  (onuId << 24);
+
+  onuGponDbIdleMsgSet(idleMsg);
+
+  onuGponDbSnMsgGet(snNumMsg);
+
+  snNumMsg[0] &= (0x00FFFFFF);
+  snNumMsg[0] |=  (onuId << 24);
+
+  onuGponDbSnMsgSet(snNumMsg);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuIdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Id
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu Id
+**
+*******************************************************************************/
+MV_U32 onuGponDbOnuIdGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponOnuId);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuSignalDetectSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu signal detect state in the database
+**
+**  PARAMETERS:  MV_U32 state
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOnuSignalDetectSet(MV_U32 state)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponSignalDetect = state;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuSignalDetectGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu signal detect state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu state
+**
+*******************************************************************************/
+MV_U32 onuGponDbOnuSignalDetectGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponSignalDetect);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuDsSyncOnSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu DS Sync state in the database
+**
+**  PARAMETERS:  MV_U32 state
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOnuDsSyncOnSet(MV_U32 state)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponDsSyncOn = state;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuDsSyncOnGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return DS Sync state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu state
+**
+*******************************************************************************/
+MV_U32 onuGponDbOnuDsSyncOnGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponDsSyncOn);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuIdOverrideValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Id override value
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu Id
+**
+*******************************************************************************/
+MV_U32 onuGponDbOnuIdOverrideValueGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponOnuIdOverrideVal);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuIdOverrideValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu Id override value
+**
+**  PARAMETERS:  MV_U32 onuId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOnuIdOverrideValueSet(MV_U32 onuId)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponOnuIdOverrideVal = onuId;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuIdOverrideSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu Id override state
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOnuIdOverrideSet(MV_BOOL enable)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponOnuIdOverrideEn = enable;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuIdOverrideGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Id override state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu Id
+**
+*******************************************************************************/
+MV_BOOL onuGponDbOnuIdOverrideGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponOnuIdOverrideEn);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbdGaspEnSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set dying gasp in the database
+**
+**  PARAMETERS:  MV_BOOL dGaspEn
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbdGaspEnSet(MV_BOOL dGaspEn)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponDyingGaspEn = dGaspEn;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbdGaspEnGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu dying gasp state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu Id
+**
+*******************************************************************************/
+MV_BOOL onuGponDbdGaspEnGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponDyingGaspEn);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbInitSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set ONU Init status in the database
+**
+**  PARAMETERS:  MV_BOOL init
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbInitSet(MV_BOOL init)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponInit = init;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbInitGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu init state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu init state - MV_TRUE/MV_FALSE
+**
+*******************************************************************************/
+MV_BOOL onuGponDbInitGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponInit);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOmccValidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu OMCC state in the database
+**
+**  PARAMETERS:  MV_BOOL omccValid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOmccValidSet(MV_BOOL omccValid)
+{
+  onuGponDb_s.onuGponGenTbl_s.omccValid = omccValid;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOmccValidGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu OMCC state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     OMCC - MV_TRUE/MV_FALSE
+**
+*******************************************************************************/
+MV_BOOL onuGponDbOmccValidGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.omccValid);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOmccPortdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu OMCC value in the database
+**
+**  PARAMETERS:  MV_U32 omccPort
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOmccPortSet(MV_U32 omccPort)
+{
+  onuGponDb_s.onuGponGenTbl_s.omccPort = omccPort;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOmccPortGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu OMCC port
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     OMCC port
+**
+*******************************************************************************/
+MV_U32 onuGponDbOmccPortGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.omccPort);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuIdOverrideValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu OMCC override value
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     OMCC override value
+**
+*******************************************************************************/
+MV_U32 onuGponDbOmccPortOverrideValueGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponOmccPortOverrideVal);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOnuIdOverrideValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu OMCC override value in the database
+**
+**  PARAMETERS:  MV_U32 OmccPort
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOmccPortOverrideValueSet(MV_U32 OmccPort)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponOmccPortOverrideVal = OmccPort;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOmccPortOverrideSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu OMCC override state in the database
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOmccPortOverrideSet(MV_BOOL enable)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponOmccPortOverrideEn = enable;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOmccPortOverrideGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu OMCC override state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     OMCC override state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbOmccPortOverrideGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponOmccPortOverrideEn);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbRateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set ONU Rate in the database
+**
+**  PARAMETERS:  MV_U32 rate
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbRateSet(MV_U32 rate)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponRate = rate;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbRateGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Rate
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu Rate
+**
+*******************************************************************************/
+MV_U32 onuGponDbRateGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponRate);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbXvrPolaritySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set ONU XVR polarity in the database
+**
+**  PARAMETERS:  MV_U32 rate
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbXvrPolaritySet(MV_U32 polarity)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuGponXvrPolarity = polarity;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbXvrPolarityGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu polarity
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu Rate
+**
+*******************************************************************************/
+MV_U32 onuGponDbXvrPolarityGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuGponXvrPolarity);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbAlarmNotifySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Alarm Notify Callback in the database
+**
+**  PARAMETERS:  ALARMNOTIFYFUNC alarmCallback - alarm callback
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbAlarmNotifySet(ALARMNOTIFYFUNC alarmCallback)
+{
+  onuGponDb_s.onuGponGenTbl_s.alarmCallback = alarmCallback;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbAlarmNotifyGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Alarm Notify Callback
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Alarm Notify Callback
+**
+*******************************************************************************/
+ALARMNOTIFYFUNC onuGponDbAlarmNotifyGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.alarmCallback);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbStatusNotifySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Status Notify Callback in the database
+**
+**  PARAMETERS:  STATUSNOTIFYFUNC statusCallback
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbStatusNotifySet(STATUSNOTIFYFUNC statusCallback)
+{
+  onuGponDb_s.onuGponGenTbl_s.statusCallback = statusCallback;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbStatusNotifyGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Status Notify Callback
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Status Notify Callback
+**
+*******************************************************************************/
+STATUSNOTIFYFUNC onuGponDbStatusNotifyGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.statusCallback);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOmccNotifySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu Omcc Notify Callback in the database
+**
+**  PARAMETERS:  OMCCNOTIFYFUNC omccCallback
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbOmccNotifySet(OMCCNOTIFYFUNC omccCallback)
+{
+  onuGponDb_s.onuGponGenTbl_s.omccCallback = omccCallback;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbOmccNotifyGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Omcc Notify Callback
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Omcc Notify Callback
+**
+*******************************************************************************/
+OMCCNOTIFYFUNC onuGponDbOmccNotifyGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.omccCallback);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDisableNotifySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu disable Notify Callback in the database
+**
+**  PARAMETERS:  DISABLENOTIFYFUNC disableCallback
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbDisableNotifySet(DISABLENOTIFYFUNC disableCallback)
+{
+  onuGponDb_s.onuGponGenTbl_s.disableCallback = disableCallback;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDisableNotifyGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu disable Notify Callback
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Disable Notify Callback
+**
+*******************************************************************************/
+DISABLENOTIFYFUNC onuGponDbDisableNotifyGet (void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.disableCallback);
+}
+
+/***********************************************/
+/* =========================================== */
+/*   ONU GPON Sync Params Table API Functions  */
+/* =========================================== */
+/***********************************************/
+
+/*******************************************************************************
+**
+**  onuGponDbSnMaskSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SN mask in the database
+**
+**  PARAMETERS:  MV_U32 snMaskEn
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbSnMaskSet(MV_U32 snMaskEn)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSerialNumberMaskDefEnable = snMaskEn;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGuardBitsSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead guard bit
+**
+**  PARAMETERS:  MV_U32 guardBit
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbGuardBitsSet(MV_U32 guardBit)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponGuardBits = guardBit;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGuardBitsGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead guard bit
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Overhead guard bit
+**
+*******************************************************************************/
+MV_U32 onuGponDbGuardBitsGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponGuardBits);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbPreambleSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead preamble type and count
+**
+**  PARAMETERS:  E_OnuOverheadPreambleType premType_e
+**               MV_U32                    premVal
+**               MV_U32                    premCnt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbPreambleSet(E_OnuOverheadPreambleType premType_e,
+                               MV_U32 premVal,
+                               MV_U32 premCnt)
+{
+  if (premType_e > ONU_GPON_PREM_TYPE_03)
+  {
+    return(MV_ERROR);
+  }
+
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponPreambleVal[premType_e] = premVal;
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponPreambleCnt[premType_e] = premCnt;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbPreambleGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead preamble type and count
+**
+**  PARAMETERS:  E_OnuOverheadPreambleType premType_e
+**               MV_U32                    *premVal
+**               MV_U32                    *premCnt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbPreambleGet(E_OnuOverheadPreambleType premType_e,
+                          MV_U32 *premVal,
+                          MV_U32 *premCnt)
+{
+  *premVal = onuGponDb_s.onuGponSyncParamsTbl_s.onuGponPreambleVal[premType_e];
+  *premCnt = onuGponDb_s.onuGponSyncParamsTbl_s.onuGponPreambleCnt[premType_e];
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtPreambleStatusSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead extended preamble type3 status
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbExtPreambleStatusSet(MV_U32 extendPremStatus)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleStatus = extendPremStatus;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtPreambleStatusGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead extended preamble type3 status
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     extended preamble type3 status
+**
+*******************************************************************************/
+MV_U32 onuGponDbExtPreambleStatusGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleStatus);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtPreambleSyncSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead extended preamble type3 - state 3/4
+**
+**  PARAMETERS:  MV_U32 extendPremCnt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbExtPreambleSyncSet(MV_U32 extendPremCnt)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleSync = extendPremCnt;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtPreambleSyncGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead extended preamble type3
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     overhead extended preamble type3 count - state 3/4
+**
+*******************************************************************************/
+MV_U32 onuGponDbExtPreambleSyncGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleSync);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtPreambleOperSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead extended preamble type3 - state 5
+**
+**  PARAMETERS:  MV_U32 extendPremCnt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbExtPreambleOperSet(MV_U32 extendPremCnt)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleOper = extendPremCnt;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtPreambleOperGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead extended preamble type3
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     overhead extended preamble type3 count - state 5
+**
+*******************************************************************************/
+MV_U32 onuGponDbExtPreambleOperGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleOper);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDelimiterSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead delimiter byte
+**
+**  PARAMETERS:  E_OnuOverheadDelimiterByte delimByte_e
+**               MV_U32                     delimVal
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbDelimiterSet(E_OnuOverheadDelimiterByte delimByte_e,
+                                MV_U32 delimVal)
+{
+  if (delimByte_e > ONU_GPON_DELM_BYTE_03)
+  {
+    return(MV_ERROR);
+  }
+
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponDelimiter[delimByte_e] = delimVal;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDelimiterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead delimiter byte
+**
+**  PARAMETERS:  E_OnuOverheadDelimiterByte delimByte_e
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     overhead delimiter byte
+**
+*******************************************************************************/
+MV_U32 onuGponDbDelimiterGet(E_OnuOverheadDelimiterByte delimByte_e)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponDelimiter[delimByte_e]);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDelimiterSizeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead delimiter size
+**
+**  PARAMETERS:  MV_U32 delimSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbDelimiterSizeSet(MV_U32 delimSize)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponDelimiterSize = delimSize;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDelimiterSizeGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead delimiter size
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     overhead delimiter size
+**
+*******************************************************************************/
+MV_U32 onuGponDbDelimiterSizeGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponDelimiterSize);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDelimiterOverrideValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead delimiter override value
+**
+**  PARAMETERS:  MV_U32 delimVal
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbDelimiterOverrideValueSet(MV_U32 delimVal)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponDelimiterOverrideValue = delimVal;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDelimiterOverrideValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead delimiter override value
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu overhead delimiter override value
+**
+*******************************************************************************/
+MV_U32 onuGponDbDelimiterOverrideValueGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponDelimiterOverrideValue);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDelimiterOverrideSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead delimiter override state
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu overhead delimiter state
+**
+*******************************************************************************/
+MV_STATUS onuGponDbDelimiterOverrideSet(MV_BOOL enable)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponDelimiterOverride = enable;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDelimiterOverridGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead delimiter override state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     overhead delimiter override state
+**
+*******************************************************************************/
+MV_U32 onuGponDbDelimiterOverrideGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponDelimiterOverride);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstDelayAddSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu extended burst delay add state
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbExtendedBurstDelayAddSet(MV_BOOL enable)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleDelayAdd = enable;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstDelayAddGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu extended burst delay add state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu extended burst delay add state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbExtendedBurstDelayAddGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleDelayAdd);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstDelayValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu extended burst delay values
+**
+**  PARAMETERS:  MV_U32 exBurstSync
+**               MV_U32 exBurstOper
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbExtendedBurstDelayValueSet(MV_U32 exBurstSync, MV_U32 exBurstOper)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleSyncDelay = exBurstSync;
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleOperDelay = exBurstOper;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstSyncDelayValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu extended burst delay value (O3/O4)
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu extended burst delay value (O3/O4)
+**
+*******************************************************************************/
+MV_U32 onuGponDbExtendedBurstSyncDelayValueGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleSyncDelay);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstOperDelayValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu extended burst delay value (O5)
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu extended burst delay value (O5)
+**
+*******************************************************************************/
+MV_U32 onuGponDbExtendedBurstOperDelayValueGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleOperDelay);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstOverrideSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu extended burst override state
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbExtendedBurstOverrideSet(MV_BOOL enable)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleOverride = enable;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstOverrideGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu extended burst override state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu extended burst override state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbExtendedBurstOverrideGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleOverride);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstOverrideValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu extended burst override values
+**
+**  PARAMETERS:  MV_U32 exBurstRange
+**               MV_U32 exBurstOper
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbExtendedBurstOverrideValueSet(MV_U32 exBurstRange, MV_U32 exBurstOper)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleSyncOverride = exBurstRange;
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleOperOverride = exBurstOper;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstSyncOverrideValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu extended burst override value (O3/O4)
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu extended burst override value (O3/O4)
+**
+*******************************************************************************/
+MV_U32 onuGponDbExtendedBurstSyncOverrideValueGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleSyncOverride);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbExtendedBurstOperOverrideValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu extended burst override value (O5)
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu extended burst override value (O5)
+**
+*******************************************************************************/
+MV_U32 onuGponDbExtendedBurstOperOverrideValueGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponExtPreambleOperOverride);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbMaxExtraSnTransSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set overhead max extra sn transmissions
+**
+**  PARAMETERS:  MV_U32 maxExtraSnTrans
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbMaxExtraSnTransSet(MV_U32 maxExtraSnTrans)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponMaxExtraSnTrans = maxExtraSnTrans;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbMaxExtraSnTransGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return overhead max extra sn transmissions
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     overhead max extra sn transmissions
+**
+*******************************************************************************/
+MV_U32 onuGponDbMaxExtraSnTransGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponMaxExtraSnTrans);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSerialNumSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu serial number
+**
+**  PARAMETERS:  MV_U8 *serialNum
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbSerialNumSet(MV_U8 *serialNum)
+{
+  MV_U32 index;
+
+  for (index = 0; index < ONU_GPON_SN_LEN; index++)
+  {
+    onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSerialNum[index] = *(serialNum + index);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSerialNumGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu serial number
+**
+**  PARAMETERS:  MV_U8 *serialNum
+**
+**  OUTPUTS:     MV_U8 *serialNum
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbSerialNumGet(MV_U8 *serialNum)
+{
+  MV_U32 index;
+
+  for (index = 0; index < ONU_GPON_SN_LEN; index++)
+  {
+    *(serialNum + index) = onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSerialNum[index];
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSerialNumberMaskEnableGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu SN mask enable state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     SN mask enable state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbSerialNumberMaskEnableGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSerialNumberMaskEnable);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSerialNumberMaskEnableSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SN mask enable state
+**
+**  PARAMETERS:  MV_BOOL a_SerialNumberMaskEnable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbSerialNumberMaskEnableSet(MV_BOOL a_SerialNumberMaskEnable)
+{
+  MV_BOOL profileSnMaskValue;
+
+  profileSnMaskValue = onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSerialNumberMaskDefEnable;
+
+  if (profileSnMaskValue == MV_TRUE)
+  {
+    onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSerialNumberMaskEnable = a_SerialNumberMaskEnable;
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSerialNumberMaskMatchGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu SN mask match state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     SN mask match state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbSerialNumberMaskMatchGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSerialNumberMaskMatch);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSerialNumberMaskMatchSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SN mask enable state
+**
+**  PARAMETERS:  MV_BOOL a_SerialNumberMaskMatch
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbSerialNumberMaskMatchSet(MV_BOOL a_SerialNumberMaskMatch)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSerialNumberMaskMatch = a_SerialNumberMaskMatch;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbConstDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu const delay
+**
+**  PARAMETERS:  MV_U32 constDelay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbConstDelaySet(MV_U32 constDelay)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponConstDelay = constDelay;
+}
+
+/*******************************************************************************
+**
+**  onuGponDbConstDelayGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu const delay
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu const delay
+**
+*******************************************************************************/
+MV_U32 onuGponDbConstDelayGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponConstDelay);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbEqualizationDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu equalization delay
+**
+**  PARAMETERS:  MV_U32 equalizationDelay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbEqualizationDelaySet(MV_U32 equalizationDelay)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponEqualizationDelay = equalizationDelay;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbEqualizationDelayGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu equalization delay
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu equalization delay
+**
+*******************************************************************************/
+MV_U32 onuGponDbEqualizationDelayGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponEqualizationDelay);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbEqualizationDelayOverrideValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu equalization delay override value
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu equalization delay override value
+**
+*******************************************************************************/
+MV_U32 onuGponDbEqualizationDelayOverrideValueGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponEqualizationDelayOverrideValue);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbEqualizationDelayOverrideValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu equalization delay override value
+**
+**  PARAMETERS:  MV_U32 equalizationDelayOverrideVal
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbEqualizationDelayOverrideValueSet(MV_U32 equalizationDelayOverrideVal)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponEqualizationDelayOverrideValue = equalizationDelayOverrideVal;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbEqualizationDelayOverrideValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu equalization delay override state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu equalization delay override state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbEqualizationDelayOverrideGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponEqualizationDelayOverride);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbEqualizationDelayOverrideSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu equalization delay override state
+**
+**  PARAMETERS:  MV_BOOL OverrideEqualizationDelay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbEqualizationDelayOverrideSet(MV_BOOL OverrideEqualizationDelay)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponEqualizationDelayOverride = OverrideEqualizationDelay;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbPowerLevelSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu power level
+**
+**  PARAMETERS:  MV_U32 powerLevel
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbPowerLevelSet(MV_U32 powerLevel)
+{
+  onuGponDb_s.onuGponSyncParamsTbl_s.onuGponPowerLevel = powerLevel;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbPowerLevelGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu power level
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu power level
+**
+*******************************************************************************/
+MV_U32 onuGponDbPowerLevelGet(void)
+{
+  return(onuGponDb_s.onuGponSyncParamsTbl_s.onuGponPowerLevel);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbIdleMsgSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu idle message
+**
+**  PARAMETERS:  MV_U32 *idleMsg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbIdleMsgSet(MV_U32 *idleMsg)
+{
+  MV_U32 index;
+
+  for (index = 0; index < ONU_GPON_MSG_LEN; index++)
+  {
+    onuGponDb_s.onuGponSyncParamsTbl_s.onuGponIdleMsg[index] = *(idleMsg + index);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponDbIdleMsgGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu idle message
+**
+**  PARAMETERS:  MV_U32 *idleMsg
+**
+**  OUTPUTS:     MV_U32 *idleMsg
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbIdleMsgGet(MV_U32 *idleMsg)
+{
+  MV_U32 index;
+
+  for (index = 0; index < ONU_GPON_MSG_LEN; index++)
+  {
+    *(idleMsg + index) = onuGponDb_s.onuGponSyncParamsTbl_s.onuGponIdleMsg[index];
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSnMsgSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu serial number message
+**
+**  PARAMETERS:  MV_U32 *snMsg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbSnMsgSet(MV_U32 *snMsg)
+{
+  MV_U32 index;
+
+  for (index = 0; index < ONU_GPON_MSG_LEN; index++)
+  {
+    onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSnMsg[index] = *(snMsg + index);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSnMsgGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu serial number message
+**
+**  PARAMETERS:  MV_U32 *snMsg
+**
+**  OUTPUTS:     MV_U32 *snMsg
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbSnMsgGet(MV_U32 *snMsg)
+{
+  MV_U32 index;
+
+  for (index = 0; index < ONU_GPON_MSG_LEN; index++)
+  {
+    *(snMsg + index) = onuGponDb_s.onuGponSyncParamsTbl_s.onuGponSnMsg[index];
+  }
+}
+
+/***********************************************/
+/* =========================================== */
+/*   ONU GPON Oper Params Table API Functions  */
+/* =========================================== */
+/***********************************************/
+
+/*******************************************************************************
+**
+**  onuGponDbBerIntervalSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu ber interval
+**
+**  PARAMETERS:  MV_U32 berInterval
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBerIntervalSet(MV_U32 berInterval)
+{
+  onuGponDb_s.onuGponOperParamsTbl_s.onuGponBerInterval = berInterval;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBerIntervalGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu ber interval
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu ber interval
+**
+*******************************************************************************/
+MV_U32 onuGponDbBerIntervalGet(void)
+{
+  return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponBerInterval);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBipInterruptStatusValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function update onu ber interval value
+**
+**  PARAMETERS:  MV_U32 Bip8
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBipInterruptStatusValueSet(MV_U32 Bip8)
+{
+  onuGponDb_s.onuGponOperParamsTbl_s.onuGponBerIntervalValue = Bip8;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBerIntervalGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu ber interval value
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu ber interval value
+**
+*******************************************************************************/
+MV_U32 onuGponDbBipInterruptStatusValueGet(void)
+{
+  return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponBerIntervalValue);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemResetSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets onu gem reset on fiber disconnection
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbGemResetSet(MV_U32 gem_reset){
+
+    onuGponDb_s.onuGponSyncParamsTbl_s.onuGponResetGemPorts = gem_reset;
+    return(MV_OK);
+}
+/*******************************************************************************
+**
+**  onuGponDbGemResetGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu gem reset on fiber disconnection
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     return onu gem reset on fiber disconnection
+**
+*******************************************************************************/
+MV_U32 onuGponDbGemResetGet(void){
+
+    return (onuGponDb_s.onuGponSyncParamsTbl_s.onuGponResetGemPorts);
+}
+/*******************************************************************************
+**
+**  onuGponDbTcontResetSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets onu TCONT reset on fiber disconnection
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbTcontResetSet(MV_U32 tcont_reset){
+
+    onuGponDb_s.onuGponSyncParamsTbl_s.onuGponResetTconts = tcont_reset;
+    return(MV_OK);
+}
+/*******************************************************************************
+**
+**  onuGponDbTcontResetGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu tcont reset on fiber disconnection
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     return onu gem reset on fiber disconnection
+**
+*******************************************************************************/
+MV_U32 onuGponDbTcontResetGet(void){
+
+    return (onuGponDb_s.onuGponSyncParamsTbl_s.onuGponResetTconts);
+}
+/*******************************************************************************
+**
+**  onuGponDbGemRestoreSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets flag "restore GEM ports on exiting from state 7"
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_VOID onuGponDbGemRestoreSet(MV_BOOL gem_restore)
+{
+    onuGponDb_s.onuGponSyncParamsTbl_s.onuGponRestoreGemPorts = gem_restore;
+}
+/*******************************************************************************
+**
+**  onuGponDbGemRestoreGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return flag "GEM ports restore on exiting from state 7"
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     return onu gem restore on exiting from state 7
+**
+*******************************************************************************/
+MV_BOOL onuGponDbGemRestoreGet(MV_VOID)
+{
+    return (onuGponDb_s.onuGponSyncParamsTbl_s.onuGponRestoreGemPorts);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBerCalcIntervalSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu internal ber interval
+**
+**  PARAMETERS:  MV_U32 internalBerInterval
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBerCalcIntervalSet(MV_U32 internalBerInterval)
+{
+  onuGponDb_s.onuGponOperParamsTbl_s.onuGponBerCalcInterval = internalBerInterval;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBerCalcIntervalGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu internal ber interval
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu internal ber interval
+**
+*******************************************************************************/
+MV_U32 onuGponDbBerCalcIntervalGet(void)
+{
+  return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponBerCalcInterval);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSfThresholdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SF threshold
+**
+**  PARAMETERS:  MV_U32 SF_Threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbSfThresholdSet(MV_U32 SF_Threshold)
+{
+  onuGponDb_s.onuGponOperParamsTbl_s.onuGponSfThreshold = SF_Threshold;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSfThresholdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu SF threshold
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu SF threshold
+**
+*******************************************************************************/
+MV_U32 onuGponDbSfThresholdGet(void)
+{
+  return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponSfThreshold);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSdThresholdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SD threshold
+**
+**  PARAMETERS:  MV_U32 SD_Threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbSdThresholdSet(MV_U32 SD_Threshold)
+{
+  onuGponDb_s.onuGponOperParamsTbl_s.onuGponSdThreshold = SD_Threshold;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbSdThresholdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu SD threshold
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu SD threshold
+**
+*******************************************************************************/
+MV_U32 onuGponDbSdThresholdGet(void)
+{
+  return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponSdThreshold);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortValidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set gem port valid state
+**
+**  PARAMETERS:  MV_U32 gemPortId
+**               MV_BOOL   valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbGemPortValidSet(MV_U32 gemPortId, MV_BOOL valid)
+{
+	if (gemPortId >= GPON_ONU_MAX_GEM_PORTS)
+		return(MV_ERROR);
+
+	onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortValid[gemPortId] = valid;
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortValidGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return gem port valid state
+**
+**  PARAMETERS:  MV_U32 gemPortId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     gem port valid state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbGemPortValidGet(MV_U32 gemPortId)
+{
+	if (gemPortId >= GPON_ONU_MAX_GEM_PORTS)
+		return(MV_FALSE);
+
+	return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortValid[gemPortId]);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortClearAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clear all gem ports
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbGemPortClearAll(void)
+{
+	MV_U32  iPort;
+
+	for (iPort = 0 ; iPort < GPON_ONU_MAX_GEM_PORTS ; iPort++)
+		onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortValid[iPort] = MV_FALSE;
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortSavedClearAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clear all saved gem ports
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_VOID onuGponDbGemPortSavedClearAll(void)
+{
+	MV_U32  iPort;
+
+	for (iPort = 0 ; iPort < GPON_ONU_MAX_GEM_PORTS ; iPort++)
+		onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortSave[iPort] = MV_FALSE;
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortSaveAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function saves validity state of all gem ports
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_VOID onuGponDbGemPortSaveAll(void)
+{
+	MV_U32  iPort;
+
+	for (iPort = 0 ; iPort < GPON_ONU_MAX_GEM_PORTS ; iPort++) {
+		onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortSave[iPort] =
+				onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortValid[iPort];
+	}
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortSavedValidGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return gem port valid state from "saved ports" array
+**
+**  PARAMETERS:  MV_U32 gemPortId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     gem port valid state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbGemPortSavedValidGet(MV_U32 gemPortId)
+{
+	if (gemPortId >= GPON_ONU_MAX_GEM_PORTS)
+		return(MV_FALSE);
+
+	return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortSave[gemPortId]);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortAesSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set gem port encryption state
+**
+**  PARAMETERS:  MV_U32 gemPortId
+**               MV_BOOL mode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbGemPortAesSet(MV_U32 gemPortId, MV_BOOL mode)
+{
+  if (gemPortId >= GPON_ONU_MAX_GEM_PORTS)
+  {
+    return(MV_ERROR);
+  }
+  onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortAes[gemPortId] = mode;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortAesGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return gem port encryption state
+**
+**  PARAMETERS:  MV_U32 gemPortId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     gem port encryption state
+**
+*******************************************************************************/
+MV_BOOL onuGponDbGemPortAesGet(MV_U32 gemPortId)
+{
+  if (gemPortId >= GPON_ONU_MAX_GEM_PORTS)
+  {
+    return(MV_FALSE);
+  }
+
+  return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortAes[gemPortId]);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbGemPortAesClearAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clear all AES gem ports
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbGemPortAesClearAll(void)
+{
+  MV_U32  iPort;
+
+  for (iPort = 0 ; iPort < GPON_ONU_MAX_GEM_PORTS ; iPort++)
+  {
+    onuGponDb_s.onuGponOperParamsTbl_s.onuGponGemPortAes[iPort] = MV_FALSE;
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbReiSeqNumSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu REI sequence number
+**
+**  PARAMETERS:  MV_U32 reiSeqNum
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbReiSeqNumSet(MV_U32 reiSeqNum)
+{
+  onuGponDb_s.onuGponOperParamsTbl_s.onuGponReiSeqNum = reiSeqNum;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbReiSeqNumGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu REI sequence number
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu REI sequence number
+**
+*******************************************************************************/
+MV_U32 onuGponDbReiSeqNumGet(void)
+{
+  return(onuGponDb_s.onuGponOperParamsTbl_s.onuGponReiSeqNum);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbPasswordSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu password
+**
+**  PARAMETERS:  MV_U8 *password
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbPasswordSet(MV_U8 *password)
+{
+  MV_U32 index;
+
+  for (index = 0; index < ONU_GPON_PASS_LEN; index++)
+  {
+    onuGponDb_s.onuGponOperParamsTbl_s.onuGponPassword[index] = *(password + index);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbPasswordGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu password
+**
+**  PARAMETERS:  MV_U8 *password
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponDbPasswordGet(MV_U8 *password)
+{
+  MV_U32 index;
+
+  for (index = 0; index < ONU_GPON_PASS_LEN; index++)
+  {
+    *(password + index) = onuGponDb_s.onuGponOperParamsTbl_s.onuGponPassword[index];
+  }
+}
+
+/********************************************/
+/* ======================================== */
+/*   ONU GPON BW Alloc Table API Functions  */
+/* ======================================== */
+/********************************************/
+
+/* ======================================== */
+/*   ONU BW ALLOC SECTION                   */
+/* ======================================== */
+
+/*******************************************************************************
+**
+**  onuGponDbBwAllocSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets Alloc-Id value & state to T-Cont
+**
+**  PARAMETERS:  MV_U32 entry
+**               MV_U32 allocId
+**               MV_BOOL valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwAllocSet(MV_U32 entry, MV_U32 allocId, MV_BOOL valid)
+{
+	if (entry >= ONU_GPON_MAX_NUM_OF_T_CONTS)
+		return(MV_ERROR);
+
+	onuGponDb_s.onuGponBwTbl_s.onuAllocIds[entry].allocId = allocId;
+	onuGponDb_s.onuGponBwTbl_s.onuAllocIds[entry].valid   = valid;
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwAllocGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Alloc-Id value & state to T-Cont
+**
+**  PARAMETERS:  MV_U32 entry
+**               MV_U32 allocId
+**               MV_BOOL valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Alloc-Id value & state
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwAllocGet(MV_U32 entry, MV_U32 *allocId, MV_BOOL *valid)
+{
+	if (entry >= ONU_GPON_MAX_NUM_OF_T_CONTS) {
+		*allocId = 0;
+		*valid   = MV_FALSE;
+		return(MV_ERROR);
+	}
+
+	*allocId = onuGponDb_s.onuGponBwTbl_s.onuAllocIds[entry].allocId;
+	*valid   = onuGponDb_s.onuGponBwTbl_s.onuAllocIds[entry].valid;
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwAllocExist
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function true if Alloc-Id exist in the onu
+**
+**  PARAMETERS:  MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Alloc-Id existance
+**
+*******************************************************************************/
+MV_BOOL onuGponDbBwAllocExist(MV_U32 allocId)
+{
+	MV_U32  iEntry;
+	MV_U32  entryAllocId;
+	MV_BOOL valid;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		onuGponDbBwAllocGet(iEntry, &entryAllocId, &valid);
+		if ((entryAllocId == allocId) && (valid == MV_TRUE))
+			return(MV_TRUE);
+	}
+
+	return(MV_FALSE);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwAllocInsert
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function assign Alloc-Id to T-Cont
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 *entry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwAllocInsert(MV_U32 allocId, MV_U32 *entry)
+{
+	MV_U32  iEntry;
+	MV_U32  entryAllocId;
+	MV_BOOL valid;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		onuGponDbBwAllocGet(iEntry, &entryAllocId, &valid);
+		if (valid == MV_FALSE) {
+			onuGponDbBwAllocSet(iEntry, allocId, MV_TRUE);
+			*entry = iEntry;
+			return(MV_OK);
+		}
+	}
+
+	return(MV_ERROR);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwAllocRemove
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function remove Alloc-Id from T-Cont
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 *entry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwAllocRemove(MV_U32 allocId, MV_U32 *entry)
+{
+	MV_U32  iEntry;
+	MV_U32  entryAllocId;
+	MV_BOOL valid;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		onuGponDbBwAllocGet(iEntry, &entryAllocId, &valid);
+		if ((entryAllocId == allocId) && (valid == MV_TRUE)) {
+			onuGponDbBwAllocSet(iEntry, PON_ONU_ALLOC_NOT_EXIST, MV_FALSE);
+			*entry = iEntry;
+			return(MV_OK);
+		}
+	}
+
+	return(MV_ERROR);
+}
+
+/* ======================================== */
+/*   ONU BW IDLE ALLOC SECTION              */
+/* ======================================== */
+
+/*******************************************************************************
+**
+**  onuGponDbBwIdleAllocSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets Idle Alloc-Id value
+**
+**  PARAMETERS:  MV_U32 entry
+**               MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     NONE
+**
+*******************************************************************************/
+MV_VOID onuGponDbBwIdleAllocSet(MV_U32 entry, MV_U32 allocId)
+{
+	if (entry < ONU_GPON_MAX_NUM_OF_T_CONTS)
+		onuGponDb_s.onuGponBwTbl_s.onuIdleAllocIds[entry] = allocId;
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwIdleAllocGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Idle Alloc-Id value
+**
+**  PARAMETERS:  MV_U32 entry
+**               MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     NONE
+**
+*******************************************************************************/
+MV_VOID onuGponDbBwIdleAllocGet(MV_U32 entry, MV_U32 *allocId)
+{
+	if (entry < ONU_GPON_MAX_NUM_OF_T_CONTS)
+		*allocId = onuGponDb_s.onuGponBwTbl_s.onuIdleAllocIds[entry];
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwIdleAllocExist
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function true if Idle Alloc-Id exist in the onu
+**
+**  PARAMETERS:  MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Alloc-Id existance
+**
+*******************************************************************************/
+MV_BOOL onuGponDbBwIdleAllocExist(MV_U32 allocId, MV_U32 *entry)
+{
+	MV_U32 iEntry;
+	MV_U32 entryAllocId;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		onuGponDbBwIdleAllocGet(iEntry, &entryAllocId);
+		if (entryAllocId == allocId) {
+			*entry = entryAllocId;
+			return(MV_TRUE);
+		}
+	}
+
+	*entry = 0;
+	return(MV_FALSE);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwIdleAllocInsert
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function add Idle Alloc-Id
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 *entry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwIdleAllocInsert(MV_U32 allocId, MV_U32 *entry)
+{
+	MV_U32  iEntry;
+	MV_U32  entryAllocId;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		onuGponDbBwIdleAllocGet(iEntry, &entryAllocId);
+		if (entryAllocId == PON_ONU_ALLOC_NOT_EXIST) {
+			onuGponDbBwIdleAllocSet(iEntry, allocId);
+			*entry = iEntry;
+			return(MV_OK);
+		}
+	}
+
+	return(MV_ERROR);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwIdleAllocRemove
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function remove Idle Alloc-Id
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 *entry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwIdleAllocRemove(MV_U32 allocId, MV_U32 *entry)
+{
+	MV_U32 iEntry;
+	MV_U32 entryAllocId;
+
+	for (iEntry = 0 ; iEntry < ONU_GPON_MAX_NUM_OF_T_CONTS ; iEntry++) {
+		onuGponDbBwIdleAllocGet(iEntry, &entryAllocId);
+		if (entryAllocId == allocId) {
+			onuGponDbBwIdleAllocSet(iEntry, PON_ONU_ALLOC_NOT_EXIST);
+			*entry = iEntry;
+			return(MV_OK);
+		}
+	}
+
+	return(MV_ERROR);
+}
+
+/* ======================================== */
+/*   ONU BW TCONT SECTION                   */
+/* ======================================== */
+
+/*******************************************************************************
+**
+**  onuGponDbBwTcontSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set an entry in the T-Cont table
+**
+**  PARAMETERS:  MV_U32  tcontNum
+**               MV_BOOL exist
+**               MV_U32  allocId
+**               MV_BOOL valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     NONE
+**
+*******************************************************************************/
+MV_VOID onuGponDbBwTcontSet(MV_U32  tcontNum,
+                              MV_BOOL exist,
+                              MV_U32  allocId,
+                              MV_BOOL valid)
+{
+	if (tcontNum < ONU_GPON_MAX_NUM_OF_T_CONTS) {
+		onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].exist   = exist;
+		onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].allocId = allocId;
+		onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].valid   = valid;
+	}
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwTcontGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return an entry from the T-Cont table
+**
+**  PARAMETERS:  MV_U32  tcontNum
+**               MV_BOOL *exist
+**               MV_U32  *allocId
+**               MV_BOOL *valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     NONE
+**
+*******************************************************************************/
+MV_VOID onuGponDbBwTcontGet(MV_U32  tcontNum,
+                              MV_BOOL *exist,
+                              MV_U32  *allocId,
+                              MV_BOOL *valid)
+{
+	if (tcontNum < ONU_GPON_MAX_NUM_OF_T_CONTS) {
+		*exist   = onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].exist;
+		*allocId = onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].allocId;
+		*valid   = onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].valid;
+	}
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwTcontExist
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return true if T-Cont entry is valid
+**
+**  PARAMETERS:  MV_U32 tcontNum
+**               MV_BOOL   *exist
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwTcontExist(MV_U32 tcontNum, MV_BOOL *exist)
+{
+	if (tcontNum >= ONU_GPON_MAX_NUM_OF_T_CONTS)
+		return(MV_ERROR);
+
+	*exist = onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].exist;
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwTcontClear
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reset T-Cont table entry
+**
+**  PARAMETERS:  MV_U32 tcontNum
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwTcontClear(MV_U32 tcontNum)
+{
+	if ((tcontNum >= ONU_GPON_MAX_NUM_OF_T_CONTS) ||
+		(onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].exist != MV_TRUE))
+		return(MV_ERROR);
+
+	onuGponDbBwTcontSet(tcontNum, MV_TRUE, PON_ONU_ALLOC_NOT_EXIST, MV_FALSE);
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwTcontAlloc
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set T-Cont table entry
+**
+**  PARAMETERS:  MV_U32 tcontNum
+**               MV_U32 allocId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwTcontAlloc(MV_U32 tcontNum, MV_U32 allocId)
+{
+	if ((tcontNum >= ONU_GPON_MAX_NUM_OF_T_CONTS) ||
+		(onuGponDb_s.onuGponBwTbl_s.onuTcontIds[tcontNum].exist != MV_TRUE))
+		return(MV_ERROR);
+
+	onuGponDbBwTcontSet(tcontNum, MV_TRUE, allocId, MV_TRUE);
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwTcontConnectCheck
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return T-Cont table entry according to Alloc-Id
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 *tcontNum
+**               MV_BOOL   *valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwTcontConnectCheck(MV_U32 allocId, MV_U32 *tcontNum, MV_BOOL *valid)
+{
+	MV_BOOL exist;
+	MV_U32  dbAllocId;
+	MV_BOOL dbValid;
+	MV_U32  iTcont;
+
+	for (iTcont = 0 ; iTcont < ONU_GPON_MAX_NUM_OF_T_CONTS ; iTcont++) {
+		onuGponDbBwTcontGet(iTcont, &exist, &dbAllocId, &dbValid);
+		if ((exist == MV_TRUE) && (dbValid == MV_TRUE) && (allocId == dbAllocId)) {
+			*valid    = dbValid;
+			*tcontNum = iTcont;
+			return(MV_OK);
+		}
+	}
+
+	*valid    = MV_FALSE;
+	*tcontNum = 0;
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwTcontFreeGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return free T-Cont table entry according to Alloc-Id
+**
+**  PARAMETERS:  MV_U32 allocId
+**               MV_U32 *tcontNum
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_TRUE if there is a free entry, MV_FALSE otherwise
+**
+*******************************************************************************/
+MV_BOOL onuGponDbBwTcontFreeGet(MV_U32 allocId, MV_U32 *tcontNum)
+{
+	MV_BOOL exist;
+	MV_U32  dbAllocId;
+	MV_BOOL dbValid;
+	MV_U32  iTcont;
+	MV_U32  tempTcont = 0;
+
+	for (iTcont = 0 ; iTcont < ONU_GPON_MAX_NUM_OF_T_CONTS ; iTcont++) {
+
+		onuGponDbBwTcontGet(iTcont, &exist, &dbAllocId, &dbValid);
+		if ((exist == MV_TRUE) && (dbValid == MV_FALSE)) {
+			*tcontNum = iTcont;
+			return(MV_TRUE);
+		}
+
+		if (dbAllocId == allocId)
+			tempTcont = iTcont;
+	}
+
+	*tcontNum = tempTcont;
+
+	return(MV_FALSE);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwMapCntDumpSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enables/disables BW MAP counters dump before
+**               ONU state changing
+**
+**  PARAMETERS:  MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbBwMapCntDumpSet(MV_U32 enable)
+{
+    onuGponDb_s.onuGponGenTbl_s.onuGponBwMapDumpEn = enable;
+
+    return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbBwMapCntDumpGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns the BW MAP counters dump state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     enabled/disabled
+**
+*******************************************************************************/
+MV_BOOL onuGponDbBwMapCntDumpGet(void)
+{
+    return (onuGponDb_s.onuGponGenTbl_s.onuGponBwMapDumpEn);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDgCallbackSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Dying Gasp Callback in the database
+**
+**  PARAMETERS:  DYINGGASPFUNC dgCallback
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbDgCallbackSet(DYINGGASPFUNC dgCallback)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuDgCallback = dgCallback;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbDgCallbackGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Dying Gasp Callback
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Dying Gasp Callback
+**
+*******************************************************************************/
+DYINGGASPFUNC onuGponDbDgCallbackGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuDgCallback);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbLinkStatusCallbackSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Link Status Callback in the database
+**
+**  PARAMETERS:  LINKSTATUSFUNC linkStatusCallback
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponDbLinkStatusCallbackSet(LINKSTATUSFUNC linkStatusCallback)
+{
+  onuGponDb_s.onuGponGenTbl_s.onuLinkStatusCallback = linkStatusCallback;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDbLinkStatusCallbackGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Link Status Callback
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     Link Status Callback
+**
+*******************************************************************************/
+LINKSTATUSFUNC onuGponDbLinkStatusCallbackGet(void)
+{
+  return(onuGponDb_s.onuGponGenTbl_s.onuLinkStatusCallback);
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.h
new file mode 100755
index 0000000..33aafa7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuDb.h
@@ -0,0 +1,414 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuDb.h                                                **
+**                                                                           **
+**  DESCRIPTION : This file contains ONU GPON database definitions           **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+#ifndef _ONU_GPON_DB_H
+#define _ONU_GPON_DB_H
+
+/* Include Files
+------------------------------------------------------------------------------*/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+/******************************************************************************/
+/* ========================================================================== */
+/*                               Database Definitions                         */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* GPON Definitions */
+#define ONU_GPON_SN_LEN          (8)
+#define ONU_GPON_PASS_LEN        (10)
+#define ONU_GPON_PREAMBLE_LEN    (3)
+#define ONU_GPON_DELIMITER_LEN   (3)
+#define ONU_GPON_MSG_LEN         (3)
+
+/* Enums
+------------------------------------------------------------------------------*/
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+/******************************************************************************/
+/* ========================================================================== */
+/*                               Database Definitions                         */
+/* ========================================================================== */
+/******************************************************************************/
+
+/**************************************/
+/* ONU GPON functions prototype       */
+/**************************************/
+typedef void (*GPONFUNCPTR) (MV_U8, MV_U8, MV_U8*);
+
+/**************************************/
+/* ONU GPON general table             */
+/**************************************/
+typedef struct
+{
+  MV_U32      onuGponOnuState;                     /* ONU State */
+  MV_U32      onuGponOnuId;                        /* ONU ID */
+  MV_U32      onuGponSignalDetect;                 /* ONU Signal Detect */
+  MV_U32      onuGponDsSyncOn;                     /* ONU DS Sync On */
+  MV_U32      onuGponOnuIdOverrideEn;              /* ONU ID Overeide Enable*/
+  MV_U32      onuGponOnuIdOverrideVal;             /* ONU ID Overeide value*/
+  MV_U32	  onuGponRate;
+  MV_U32	  onuGponXvrPolarity;
+  GPONFUNCPTR onuGponStateAndEventTbl[ONU_GPON_NUM_OF_EVENTS][ONU_GPON_NUM_OF_STATES];
+  MV_BOOL	  onuGponInit;						   /* Is ONU initialized? */
+  MV_BOOL     omccValid;
+  MV_U32      omccPort;
+  MV_U32      onuGponOmccPortOverrideVal;
+  MV_U32      onuGponOmccPortOverrideEn;
+  MV_BOOL     onuGponDyingGaspEn;
+  MV_BOOL     onuGponBwMapDumpEn;
+
+  ALARMNOTIFYFUNC   alarmCallback;
+  STATUSNOTIFYFUNC  statusCallback;
+  OMCCNOTIFYFUNC    omccCallback;
+  DISABLENOTIFYFUNC disableCallback;
+  DYINGGASPFUNC     onuDgCallback;
+  LINKSTATUSFUNC    onuLinkStatusCallback;
+
+}S_OnuGponGenTbl;
+
+/**************************************/
+/* ONU GPON Sync param table          */
+/**************************************/
+typedef struct
+{
+  MV_U32  onuGponGuardBits;                         /* ONU number of guard bits */
+  MV_U32  onuGponPreambleVal[ONU_GPON_PREAMBLE_LEN];/* ONU preamble value */
+  MV_U32  onuGponPreambleCnt[ONU_GPON_PREAMBLE_LEN];/* ONU preamble count */
+  MV_U32  onuGponDelimiter[ONU_GPON_DELIMITER_LEN]; /* ONU delimiter value */
+  MV_U32  onuGponDelimiterSize;                     /* ONU delimiter size */
+  MV_U32  onuGponDelimiterOverrideValue;            /* ONU delimiter value override */
+  MV_BOOL onuGponDelimiterOverride;                 /* ONU delimiter override */
+
+  MV_U32  onuGponExtPreambleStatus;                 /* ONU extended preamble status (on/off) */
+  MV_U32  onuGponExtPreambleSync;                   /* ONU extended preamble type 3 - state 3/4 */
+  MV_U32  onuGponExtPreambleOper;                   /* ONU extended preamble type 3 - state 5 */
+  MV_U32  onuGponExtPreambleSyncOverride;           /* ONU extended preamble override type 3 - state 3/4 */
+  MV_U32  onuGponExtPreambleOperOverride;           /* ONU extended preamble override type 3 - state 5 */
+  MV_BOOL onuGponExtPreambleOverride;               /* ONU extended Preamble override */
+  MV_BOOL onuGponExtPreambleDelayAdd;               /* ONU extended Preamble delay add */
+  MV_U32  onuGponExtPreambleSyncDelay;              /* ONU extended preamble override type 3 - state 3/4 */
+  MV_U32  onuGponExtPreambleOperDelay;              /* ONU extended preamble override type 3 - state 5 */
+
+  MV_U32  onuGponMaxExtraSnTrans;                   /* ONU max extra SN transmissions */
+
+  MV_U8   onuGponSerialNum[ONU_GPON_SN_LEN];        /* ONU Serial number */
+  MV_U32  onuGponConstDelay;                        /* ONU Const Delay - cannot be changed */
+  MV_U32  onuGponEqualizationDelay;                 /* ONU Equalization Delay */
+  MV_U32  onuGponEqualizationDelayOverrideValue;    /* ONU delimiter override */
+  MV_BOOL onuGponEqualizationDelayOverride;         /* ONU delimiter override */
+
+  MV_U32  onuGponPowerLevel;                        /* ONU power level */
+
+  MV_BOOL onuGponSerialNumberMaskEnable;            /* ONU Serial Number Mask */
+  MV_BOOL onuGponSerialNumberMaskMatch;             /* ONU Serial Number Mask  Match Mode */
+  MV_BOOL onuGponSerialNumberMaskDefEnable;         /* ONU Serial Number Mask profile override status */
+
+  MV_U32  onuGponIdleMsg[ONU_GPON_MSG_LEN];         /* ONU idle message */
+  MV_U32  onuGponSnMsg[ONU_GPON_MSG_LEN];           /* ONU serial number message */
+  MV_U32  onuGponResetGemPorts;                     /* ONU reset Gem on disconnection */
+  MV_U32  onuGponResetTconts;                       /* ONU reset Tcont on disconnection */
+  MV_BOOL onuGponRestoreGemPorts;                   /* ONU restore Gem on exiting from state 7 */

+}S_OnuGponSyncParamsTbl;
+
+/**************************************/
+/* ONU GPON Oper param table          */
+/**************************************/
+typedef struct
+{
+  MV_U32  onuGponBerInterval;                       /* ONU Ber Interval - set by the OLT */
+  MV_U32  onuGponBerCalcInterval;                   /* ONU Calc Ber Interval - internal for ONU */
+  MV_U32  onuGponSfThreshold;                       /* ONU Signal Fail Threshold */
+  MV_U32  onuGponSdThreshold;                       /* ONU Signal degraded Threshold */
+  MV_U32  onuGponBerIntervalValue;                  /* ONU Ber Interval Value of Bip8 Errors */
+  MV_BOOL onuGponGemPortAes[GPON_ONU_MAX_GEM_PORTS];
+  MV_BOOL onuGponGemPortValid[GPON_ONU_MAX_GEM_PORTS];
+  MV_BOOL onuGponGemPortSave[GPON_ONU_MAX_GEM_PORTS];

+  MV_U8   onuGponPassword[ONU_GPON_PASS_LEN];       /* ONU password */
+  MV_U16  onuGponReiSeqNum;                         /* ONU REI sequence number */
+}S_OnuGponOperParamsTbl;
+
+/**************************************/
+/* ONU GPON BW Allocation param table */
+/**************************************/
+typedef struct
+{
+  MV_U32  allocId;
+  MV_BOOL valid;
+}S_OnuAllocIds;
+
+typedef struct
+{
+  MV_BOOL exist;
+  MV_U32  allocId;
+  MV_BOOL valid;
+}S_OnuTcontIds;
+
+typedef struct
+{
+  S_OnuTcontIds onuTcontIds[ONU_GPON_MAX_NUM_OF_T_CONTS];
+  S_OnuAllocIds onuAllocIds[ONU_GPON_MAX_NUM_OF_T_CONTS];
+  MV_U32        onuIdleAllocIds[ONU_GPON_MAX_NUM_OF_T_CONTS];
+}S_OnuGponBwAllocTbl;
+
+/* ONU GPON Database */
+typedef struct
+{
+  S_OnuGponGenTbl        onuGponGenTbl_s;
+  S_OnuGponSyncParamsTbl onuGponSyncParamsTbl_s;
+  S_OnuGponOperParamsTbl onuGponOperParamsTbl_s;
+  S_OnuGponBwAllocTbl    onuGponBwTbl_s;
+}S_OnuGponDb;
+
+/* Global variables
+------------------------------------------------------------------------------*/
+/* ONU GPON Database */
+extern S_OnuGponDb onuGponDb_s;
+
+/* Global functions
+------------------------------------------------------------------------------*/
+/* ONU GPON database init function */
+MV_STATUS onuGponDbInit(void);
+
+void       onuGponOnuGenTblInit(void);
+void       onuGponDbOnuSyncParamTblInit(void);
+void       onuGponDbOnuOperParamTblInit(void);
+void       onuGponDbOnuTcontTblInit(void);
+void       onuGponDbOnuPortTblInit(void);
+MV_STATUS onuGponDbBwAllocInit(void);
+
+/* ONU GPON general table API functions */
+MV_STATUS onuGponDbOnuStateSet(MV_U32 onuState);
+MV_U32    onuGponDbOnuStateGet(void);
+MV_STATUS onuGponDbOnuIdSet(MV_U32 onuId);
+MV_U32    onuGponDbOnuIdGet(void);
+MV_STATUS onuGponDbOnuSignalDetectSet(MV_U32 state);
+MV_U32    onuGponDbOnuSignalDetectGet(void);
+MV_STATUS onuGponDbOnuDsSyncOnSet(MV_U32 state);
+MV_U32    onuGponDbOnuDsSyncOnGet(void);
+MV_STATUS onuGponDbOnuIdOverrideSet(MV_BOOL enable);
+MV_BOOL   onuGponDbOnuIdOverrideGet(void);
+MV_STATUS onuGponDbOnuIdOverrideValueSet(MV_U32 onuId);
+MV_U32    onuGponDbOnuIdOverrideValueGet(void);
+MV_STATUS onuGponDbInitSet(MV_BOOL init);
+MV_BOOL   onuGponDbInitGet(void);
+MV_STATUS onuGponDbOmccValidSet(MV_BOOL omccValid);
+MV_BOOL   onuGponDbOmccValidGet(void);
+MV_STATUS onuGponDbOmccPortSet(MV_U32 omccPort);
+MV_U32    onuGponDbOmccPortGet (void);
+MV_BOOL   onuGponDbOmccPortOverrideGet(void);
+MV_STATUS onuGponDbOmccPortOverrideSet(MV_BOOL enable);
+MV_U32    onuGponDbOmccPortOverrideValueGet(void);
+MV_STATUS onuGponDbOmccPortOverrideValueSet(MV_U32 omccPort);
+MV_STATUS onuGponDbRateSet(MV_U32 rate);
+MV_U32	  onuGponDbRateGet (void);
+MV_STATUS onuGponDbXvrPolaritySet(MV_U32 rate);
+MV_U32	  onuGponDbXvrPolarityGet (void);
+MV_BOOL   onuGponDbdGaspEnGet(void);
+MV_STATUS onuGponDbdGaspEnSet(MV_BOOL dGaspEn);
+MV_STATUS onuGponDbAlarmNotifySet(ALARMNOTIFYFUNC alarmCallback);
+ALARMNOTIFYFUNC   onuGponDbAlarmNotifyGet (void);
+MV_STATUS         onuGponDbStatusNotifySet(STATUSNOTIFYFUNC	statusCallback);
+STATUSNOTIFYFUNC  onuGponDbStatusNotifyGet (void);
+MV_STATUS         onuGponDbOmccNotifySet(OMCCNOTIFYFUNC omccCallback);
+OMCCNOTIFYFUNC    onuGponDbOmccNotifyGet (void);
+MV_STATUS         onuGponDbDisableNotifySet(DISABLENOTIFYFUNC disableCallback);
+DISABLENOTIFYFUNC onuGponDbDisableNotifyGet (void);
+MV_STATUS         onuGponDbDgCallbackSet(DYINGGASPFUNC dgCallback);
+DYINGGASPFUNC     onuGponDbDgCallbackGet(void);
+MV_STATUS         onuGponDbLinkStatusCallbackSet(LINKSTATUSFUNC linkStatusCallback);
+LINKSTATUSFUNC    onuGponDbLinkStatusCallbackGet(void);
+
+/* ONU GPON Sync param table API functions */
+MV_STATUS onuGponDbGuardBitsSet(MV_U32 guardBit);
+MV_U32    onuGponDbGuardBitsGet(void);
+MV_STATUS onuGponDbPreambleSet(E_OnuOverheadPreambleType premType_e, MV_U32 premVal, MV_U32 premCnt);
+void      onuGponDbPreambleGet(E_OnuOverheadPreambleType premType_e, MV_U32 *premVal, MV_U32 *premCnt);
+MV_BOOL   onuGponDbExtendedBurstOverrideGet(void);
+MV_STATUS onuGponDbExtendedBurstOverrideSet(MV_BOOL enable);
+MV_BOOL   onuGponDbExtendedBurstDelayAddGet(void);
+MV_STATUS onuGponDbExtendedBurstDelayAddSet(MV_BOOL enable);
+MV_STATUS onuGponDbExtendedBurstOverrideValueSet (MV_U32 exBurstRange , MV_U32 exBurstOper);
+MV_STATUS onuGponDbExtendedBurstDelayValueSet (MV_U32 exBurstSync , MV_U32 exBurstOper);
+MV_U32    onuGponDbExtendedBurstSyncDelayValueGet(void);
+MV_U32    onuGponDbExtendedBurstOperDelayValueGet(void);
+MV_U32    onuGponDbExtendedBurstSyncOverrideValueGet(void);
+MV_U32    onuGponDbExtendedBurstOperOverrideValueGet(void);
+MV_STATUS onuGponDbDelimiterSet(E_OnuOverheadDelimiterByte delimType_e, MV_U32 delimVal);
+MV_U32    onuGponDbDelimiterGet(E_OnuOverheadDelimiterByte delimType_e);
+MV_STATUS onuGponDbDelimiterSizeSet(MV_U32 delimSize);
+MV_U32    onuGponDbDelimiterSizeGet(void);
+MV_STATUS onuGponDbDelimiterOverrideSet(MV_BOOL enable);
+MV_U32    onuGponDbDelimiterOverrideGet(void);
+MV_STATUS onuGponDbDelimiterOverrideValueSet(MV_U32 delimVal);
+MV_U32    onuGponDbDelimiterOverrideValueGet(void);
+MV_STATUS onuGponDbExtPreambleSyncSet(MV_U32 extendPremCnt);
+MV_U32    onuGponDbExtPreambleSyncGet(void);
+MV_STATUS onuGponDbExtPreambleOperSet(MV_U32 extendPremCnt);
+MV_U32    onuGponDbExtPreambleOperGet(void);
+MV_STATUS onuGponDbMaxExtraSnTransSet(MV_U32 maxExtraSnTrans);
+MV_U32    onuGponDbMaxExtraSnTransGet(void);
+MV_STATUS onuGponDbSerialNumSet(MV_U8 *serialNum);
+void      onuGponDbSerialNumGet(MV_U8 *serialNum);
+void      onuGponDbConstDelaySet(MV_U32 constDelay);
+MV_U32    onuGponDbConstDelayGet(void);
+MV_BOOL   onuGponDbSerialNumberMaskEnableGet(void);
+MV_STATUS onuGponDbSerialNumberMaskEnableSet(MV_BOOL a_SerialNumberMaskEnable);
+MV_BOOL   onuGponDbSerialNumberMaskMatchGet(void);
+MV_STATUS onuGponDbSerialNumberMaskMatchSet(MV_BOOL a_SerialNumberMaskMatch);
+MV_STATUS onuGponDbSnMaskSet(MV_U32 snMaskEn);
+MV_STATUS onuGponDbEqualizationDelaySet(MV_U32 equalizationDelay);
+MV_U32    onuGponDbEqualizationDelayGet(void);
+MV_STATUS onuGponDbEqualizationDelayOverrideSet (MV_BOOL OverrideEqualizationDelay);
+MV_BOOL   onuGponDbEqualizationDelayOverrideGet (void);
+MV_U32    onuGponDbEqualizationDelayOverrideValueGet (void);
+MV_STATUS onuGponDbEqualizationDelayOverrideValueSet (MV_U32 equalizationDelayOverrideVal);
+MV_STATUS onuGponDbPowerLevelSet(MV_U32 powerLevel);
+MV_U32    onuGponDbPowerLevelGet(void);
+void      onuGponDbIdleMsgSet(MV_U32 *idleMsg);
+void      onuGponDbIdleMsgGet(MV_U32 *idleMsg);
+void      onuGponDbSnMsgSet(MV_U32 *snMsg);
+void      onuGponDbSnMsgGet(MV_U32 *snMsg);
+
+/* ONU GPON Oper param table API functions */
+MV_STATUS onuGponDbBerIntervalSet(MV_U32 berInterval);
+MV_U32    onuGponDbBerIntervalGet(void);
+MV_STATUS onuGponDbBerCalcIntervalSet(MV_U32 internalBerInterval);
+MV_U32    onuGponDbBerCalcIntervalGet(void);
+MV_STATUS onuGponDbSfThresholdSet(MV_U32 SF_Threshold);
+MV_U32    onuGponDbSfThresholdGet(void);
+MV_STATUS onuGponDbSdThresholdSet(MV_U32 SD_Threshold);
+MV_U32    onuGponDbSdThresholdGet(void);
+MV_STATUS onuGponDbGemPortValidSet(MV_U32 gemPortId, MV_BOOL mode);
+MV_BOOL   onuGponDbGemPortValidGet(MV_U32 gemPortId);
+MV_STATUS onuGponDbGemPortClearAll(void);
+MV_VOID   onuGponDbGemPortSavedClearAll(void);

+MV_VOID   onuGponDbGemPortSaveAll(void);

+MV_BOOL   onuGponDbGemPortSavedValidGet(MV_U32 gemPortId);

+MV_STATUS onuGponDbGemPortAesSet(MV_U32 gemPortId, MV_BOOL mode);
+MV_BOOL   onuGponDbGemPortAesGet(MV_U32 gemPortId);
+MV_STATUS onuGponDbGemPortAesClearAll(void);
+MV_STATUS onuGponDbReiSeqNumSet(MV_U32 reiSeqNum);
+MV_U32    onuGponDbReiSeqNumGet(void);
+MV_STATUS onuGponDbPasswordSet(MV_U8 *password);
+void      onuGponDbPasswordGet(MV_U8 *password);
+MV_STATUS onuGponDbBipInterruptStatusValueSet(MV_U32 Bip8);
+MV_U32    onuGponDbBipInterruptStatusValueGet(void);
+MV_STATUS onuGponDbGemResetSet(MV_U32 gem_reset);
+MV_U32    onuGponDbGemResetGet(void);
+MV_STATUS onuGponDbTcontResetSet(MV_U32 tcont_reset);
+MV_U32    onuGponDbTcontResetGet(void);
+MV_VOID   onuGponDbGemRestoreSet(MV_BOOL gem_restore);

+MV_BOOL   onuGponDbGemRestoreGet(MV_VOID);

+
+/* ONU GPON BW Alloc param table API functions */
+MV_STATUS onuGponDbBwAllocSet(MV_U32 entry, MV_U32 allocId, MV_BOOL valid);
+MV_STATUS onuGponDbBwAllocGet(MV_U32 entry, MV_U32 *allocId, MV_BOOL *valid);
+MV_BOOL   onuGponDbBwAllocExist(MV_U32 allocId);
+MV_STATUS onuGponDbBwAllocInsert(MV_U32 allocId, MV_U32 *entry);
+MV_STATUS onuGponDbBwAllocRemove(MV_U32 allocId, MV_U32 *entry);
+
+MV_VOID onuGponDbBwIdleAllocSet(MV_U32 entry, MV_U32 allocId);
+MV_VOID onuGponDbBwIdleAllocGet(MV_U32 entry, MV_U32 *allocId);
+MV_BOOL   onuGponDbBwIdleAllocExist(MV_U32 allocId, MV_U32 *entry);
+MV_STATUS onuGponDbBwIdleAllocInsert(MV_U32 allocId, MV_U32 *entry);
+MV_STATUS onuGponDbBwIdleAllocRemove(MV_U32 allocId, MV_U32 *entry);
+
+MV_VOID onuGponDbBwTcontSet(MV_U32 tcontNum, MV_BOOL exist, MV_U32 allocId, MV_BOOL valid);
+MV_VOID onuGponDbBwTcontGet(MV_U32 tcontNum, MV_BOOL *exist, MV_U32 *allocId, MV_BOOL *valid);
+MV_STATUS onuGponDbBwTcontExist(MV_U32 tcontNum, MV_BOOL *exist);
+MV_STATUS onuGponDbBwTcontClear(MV_U32 tcontNum);
+MV_STATUS onuGponDbBwTcontAlloc(MV_U32 tcontNum, MV_U32 allocId);
+MV_STATUS onuGponDbBwTcontConnectCheck(MV_U32 allocId, MV_U32 *tcontNum, MV_BOOL *valid);
+MV_BOOL   onuGponDbBwTcontFreeGet(MV_U32 allocId, MV_U32 *tcontNum);
+
+MV_STATUS onuGponDbBwMapCntDumpSet(MV_U32 enable);
+MV_BOOL   onuGponDbBwMapCntDumpGet(void);
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _ONU_GPON_DB_H */
+
+
+
+
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuHeader.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuHeader.h
new file mode 100755
index 0000000..05c90de
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuHeader.h
@@ -0,0 +1,120 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuHeader.h                                            **

+**                                                                           **

+**  DESCRIPTION : This file pon module header files                          **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_HEADER_H 

+#define _ONU_GPON_HEADER_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuRtos.h"

+#include "mvPonOnuDefines.h"

+#include "mvPonOnuRegs.h"

+#include "mvPonOnuMac.h"

+#include "gponOnuBoard.h"

+#include "gponOnuLnxKsOs.h"

+#include "gponOnuLnxKsMI.h"

+#include "gponOnuLnxKsUI.h"

+#include "gponOnuInit.h"

+#include "gponOnuIsr.h"

+#include "gponOnuApi.h"

+#include "gponOnuDb.h"

+#include "gponOnuPm.h"

+#include "gponOnuAlrm.h"

+#include "gponOnuMngr.h"

+#include "gponOnuSrvc.h"

+#include "gponOnuAlloc.h"

+#include "gponOnuBer.h"

+#include "ponOnuBoard.h"

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums 

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Macros

+------------------------------------------------------------------------------*/

+

+#endif /* _ONU_GPON_HEADER_H */

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.c
new file mode 100755
index 0000000..a360076
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.c
@@ -0,0 +1,1217 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuInit.c                                              **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON init sequence                **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "gponOnuHeader.h"
+#include "ponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuInit.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+MV_STATUS onuGponAsicDelayInit(void);
+MV_STATUS onuGponAsicOverheadInit(void);
+MV_STATUS onuGponAsicPortIdsInit(void);
+MV_STATUS onuGponAsicBerCounterInit(void);
+MV_STATUS onuGponAsicPloamParamInit(void);
+MV_STATUS onuGponAsicFrameDelineationInit(void);
+MV_STATUS onuGponAsicTxInit(void);
+MV_STATUS onuGponAsicBurstEnableInit(void);
+MV_STATUS onuGponAsicFrameLengthInit(void);
+MV_STATUS onuGponAsicPortInit(void);
+#ifndef PON_FPGA
+MV_STATUS onuGponAsicBoardInit(void);
+#endif /* PON_FPGA */
+MV_STATUS onuGponAsicInit(MV_BOOL initTime);
+MV_STATUS onuGponAppInit(void);
+void      onuGponStateAndEventTblInit(void);
+void      onuGponInPmInit(void);
+MV_STATUS mvOnuPonMacAcCouplingInit(void);
+
+
+/*******************************************************************************
+**
+**  onuGponSetup
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function execute onu setup init sequence
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**               MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponSetup(void)
+{
+  MV_STATUS rcode;
+
+  /* init onu base address */
+  rcode = onuGponGlbAddrInit();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) Failed to init onu base address\n", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  /* init onu database */
+  rcode = onuGponDbInit();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) Failed to init onu database\n", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  /* init onu Asic */
+  rcode = onuGponAsicInit(MV_TRUE);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) Failed to init asic\n", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  rcode = onuGponPmInit();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) Failed to init pm\n", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+  onuGponIsrInit();
+  onuGponSrvcInit();
+  onuGponAllocIdInit(0x00FF);
+  onuGponPmGemPortPmInit();
+
+  return(MV_OK);
+}
+
+#ifndef PON_FPGA
+/*******************************************************************************
+**
+**  onuGponAsicLedsInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu leds
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicLedsInit(void)
+{
+  onuPonLedInit();
+
+  onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_OFF);
+  onuPonLedHandler(ONU_PON_SYS_LED, ACTIVE_LED_ON);
+
+  return(MV_OK);
+}
+#endif /* PON_FPGA */
+
+/*******************************************************************************
+**
+**  onuGponOnuStateAndIdInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu Id and state
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicOnuStateAndIdInit(void)
+{
+  MV_STATUS rcode;
+  MV_U32    onuState;
+  MV_U32    onuId;
+  MV_BOOL   onuIdEnable;
+
+  /* ONU State Register */
+  /* get onu state */
+  onuState = onuGponDbOnuStateGet();
+  rcode    = mvOnuGponMacOnuStateSet(onuState);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacOnuStateSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  /* ONU-ID Register */
+  onuId       = onuGponDbOnuIdGet();
+  onuIdEnable = (onuId == ONU_GPON_UNDEFINED_ONU_ID) ? MV_FALSE : MV_TRUE;
+  rcode = mvOnuGponMacOnuIdSet(onuId, onuIdEnable);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacOnuIdSet onu Id(%d), enable(%d)\n",
+               __FILE_DESC__, __LINE__, onuId, onuIdEnable);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicDelayInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu delay: const, equilization, and
+**               Final
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicDelayInit(void)
+{
+  MV_STATUS rcode;
+  MV_U32    eqDelay;
+  MV_U32    finalDelay;
+  MV_U32    equalizationDelay;
+  MV_U32    constDelay;
+  MV_U32    snForRandomSeed;
+  MV_U8     sn[8];
+
+
+  /* TX Delay Register - const */
+  constDelay = onuGponDbConstDelayGet();
+  rcode      = mvOnuGponMacRxInternalDelaySet(constDelay);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacRxInternalDelaySet, constDelay(0x%x)\n",
+               __FILE_DESC__, __LINE__, constDelay);
+    return(rcode);
+  }
+
+  /* calc delay */
+  eqDelay           = onuGponDbEqualizationDelayGet();
+  finalDelay        = M_ONU_GPON_RANG_MSG_FINAL_DELAY(eqDelay);
+  equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(eqDelay);
+
+  /* TX Delay Register - equilization */
+  rcode = mvOnuGponMacRxEqualizationDelaySet(equalizationDelay);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacRxInternalDelaySet, constDelay(0x%x)\n",
+               __FILE_DESC__, __LINE__, constDelay);
+    return(rcode);
+  }
+
+  /* TX Final Delay Register */
+  rcode = mvOnuGponMacTxFinalDelaySet(GPON_TX_FINAL_DELAY_FD);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacTxFinalDelaySet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  /* Update two last bytes of Serial Number -Help Asic generate Random numbers
+     for S/N Request answer delay */
+  onuGponDbSerialNumGet(sn);
+  snForRandomSeed = sn[7] + (MV_U32)(sn[6] << 8);
+  rcode = mvOnuGponMacSerialNumberSet(snForRandomSeed);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacTxFinalDelaySet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicOverheadInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu overhead parameters: Preamble, and
+**               Delimiter
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicOverheadInit(void)
+{
+  MV_STATUS rcode;
+  MV_U32    preambleType1Ctr;
+  MV_U32    preambleType1Pattern;
+  MV_U32    preambleType2Ctr;
+  MV_U32    preambleType2Pattern;
+  MV_U32    preambleType3Ctr;
+  MV_U32    preambleType3Pattern;
+  MV_U32    delimiterByte1;
+  MV_U32    delimiterByte2;
+  MV_U32    delimiterByte3;
+  MV_U32    delimiter;
+
+  onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_01, &preambleType1Pattern, &preambleType1Ctr);
+  onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_02, &preambleType2Pattern, &preambleType2Ctr);
+  onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_03, &preambleType3Pattern, &preambleType3Ctr);
+
+  /* TX Preamble Register */
+  rcode = mvOnuGponMacPreambleSet(ONU_TX_PREAMBLE_TYPE_01_P, preambleType1Ctr,
+                                ONU_TX_PREAMBLE_TYPE_02_P, preambleType2Ctr,
+                                preambleType3Pattern, preambleType3Ctr);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacPreambleSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  /* TX Delimiter Register */
+  delimiterByte1 = onuGponDbDelimiterGet(ONU_GPON_DELM_BYTE_01);
+  delimiterByte2 = onuGponDbDelimiterGet(ONU_GPON_DELM_BYTE_02);
+  delimiterByte3 = onuGponDbDelimiterGet(ONU_GPON_DELM_BYTE_03);
+
+  delimiter = (delimiterByte3 << 16) | (delimiterByte2 << 8) | delimiterByte1;
+  rcode = mvOnuGponMacTxDelimiterSet(delimiter, GPON_TX_DELIMITER_DS);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacTxDelimiterSet, delimiter(0x%x)\n", __FILE_DESC__, __LINE__, delimiter);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicBerCounterInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu ber interval
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicBerCounterInit(void)
+{
+#if 0
+  MV_U32    berInterval;
+  MV_STATUS rcode;
+
+  berInterval = onuGponDbBerIntervalGet();
+  /* ONU BIP period Counter Register */
+  rcode = mvOnuGponMacBerIntervalSet(berInterval);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) onuGponDbBerIntervalGet, berInterval(%d)\n", __FILE_DESC__, __LINE__, berInterval);
+    return(rcode);
+  }
+#endif
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicPloamParamInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu Rx PLOAM configuration
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicPloamParamInit(void)
+{
+  MV_STATUS rcode;
+
+  rcode = mvOnuGponMacRxPloamConfigSet(MV_FALSE,MV_FALSE,MV_FALSE);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacRxPloamConfigSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicFrameDelineationInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu frame delineation
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicFrameDelineationInit(void)
+{
+  MV_STATUS rcode;
+
+  /* Frame Delineation Register */
+  rcode = mvOnuGponMacRxPsaConfigSet(GPON_FRAME_DELINEATION_M1,
+                                   GPON_FRAME_DELINEATION_M2,
+                                   GPON_FRAME_DELINEATION_M2,
+                                   4);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacRxPsaConfigSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicBurstEnableInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu burst enable
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicBurstEnableInit(void)
+{
+  MV_STATUS rcode;
+
+  /* BURST enable parameter */
+  rcode = mvOnuGponMacTxBurstEnParamSet(GPON_BURST_EN_MASK,
+                                        GPON_BURST_EN_P,
+                                        GPON_BURST_EN_ORDER,
+                                        GPON_BURST_EN_STOP,
+                                        GPON_BURST_EN_START);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacTxBurstEnParamSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  onuGponDbXvrPolaritySet(GPON_BURST_EN_P);
+  mvOnuPonMacBurstEnablePolarityInit(GPON_BURST_EN_P);
+
+  rcode = mvOnuGponMacTxTxEnableCounterThresholdSet(GPON_BURST_THRESHOLD);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacTxTxEnableCounterThresholdSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicFrameLengthInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu frame lengths
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicFrameLengthInit(void)
+{
+  MV_STATUS  rcode;
+
+  rcode = mvOnuGponMacGemPayloadLenSet(GPON_MAX_GEM_PAYLOAD_LEN);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacGemPayloadLenSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  rcode = mvOnuGponMacGemEthFrameLenSet(GPON_MAX_ETH_FRAME_LEN, GPON_MIN_ETH_FRAME_LEN);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacGemEthFrameLenSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  rcode = mvOnuGponMacGemOmciFrameLenSet(GPON_MAX_OMCI_FRAME_LEN, GPON_MIN_OMCI_FRAME_LEN);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacGemOmciFrameLenSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAsicPortInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu gem and aes tables
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicPortInit(void)
+{
+  MV_STATUS rcode;
+
+  rcode = mvOnuGponMacAesInit();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacAesInit\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  rcode = mvOnuGponMacGemInit();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacGemInit\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+#ifndef PON_FPGA
+/*******************************************************************************
+**
+**  onuGponAsicBoardInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu Serdes and Dying Gasp
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicBoardInit(void)
+{
+	MV_STATUS status;
+
+	status = onuGponSerdesInit();
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuPonSerdesInit\n", __FILE_DESC__, __LINE__);
+		return(status);
+	}
+
+	status = mvOnuPonMacBurstEnableInit();
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) mvOnuPonMacBurstEnableInit\n\r", __FILE_DESC__, __LINE__);
+		return(status);
+	}
+
+	/* Setup TX power ON/OFF GPP and turn TX power OFF */
+	status = onuPonTxPowerControlInit();
+	if (status == MV_OK)
+		status = onuPonTxPowerOn(MV_FALSE);
+
+	if (status != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) Unable to configure TX POWER GPP\n\r", __FILE_DESC__, __LINE__);
+		return(status);
+	}
+
+	return(status);
+}
+
+#endif /* PON_FPGA */
+
+/*******************************************************************************
+**
+**  onuGponAsicInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init default onu GPON MAC configuration
+**
+**  PARAMETERS:  MV_BOOL initTime - init indication flag, true = init sequence
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponAsicInit(MV_BOOL initTime)
+{
+	MV_STATUS  rcode;
+	MV_U32 devId = mvCtrlModelGet();
+
+#ifndef PON_FPGA
+	rcode =  onuGponAsicBoardInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicBoardInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+#endif /* PON_FPGA */
+
+#ifndef PON_FPGA
+	onuGponAsicLedsInit();
+#endif /*PON_FPGA */
+
+	rcode = onuGponAsicOnuStateAndIdInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicOnuStateAndIdInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode = onuGponAsicDelayInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicDelayInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode = onuGponAsicOverheadInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicOverheadInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode = onuGponAsicBerCounterInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicBerCounterInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode = onuGponAsicFrameDelineationInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicFrameDelineationInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode = onuGponAsicPloamParamInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicPloamParamInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	/* Const RAM - serial number message + Idle message */
+	rcode = onuGponSrvcConstPloamFromDbInit(initTime);
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponSrvcConstPloamFromDbInit, initTime (%d)\n", __FILE_DESC__, __LINE__, initTime);
+		return(rcode);
+	}
+
+	rcode =  onuGponAsicBurstEnableInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicBurstEnableInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode =  onuGponAsicFrameLengthInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicFrameLengthInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode =  onuGponAsicPortInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) onuGponAsicPortInit\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode =  mvOnuGponMacUtmTcValidSet(1);
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) mvOnuGponMacUtmTcValidSet\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	rcode = mvOnuPonMacAcCouplingInit();
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "ERROR: (%s:%d) mvOnuPonMacAcCouplingInit\n\r", __FILE_DESC__, __LINE__);
+		return(rcode);
+	}
+
+	if (devId == MV_6601_DEV_ID) {
+		/* GPON is always works in legacy mode */
+		MV_REG_WRITE(NETA_LEGACY_DBA_REG(MV_PON_PORT_ID), 0);
+	}
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponSwitchOn
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function execute onu switchOn init sequence
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponSwitchOn(void)
+{
+  MV_STATUS        rcode;
+  S_BerCoefficient berCoeff;
+
+  /* init onu RTOS resources */
+  rcode = onuGponRtosResourceInit();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) onuGponRtosResourceInit\n", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  /* init onu application strcutures */
+  rcode = onuGponAppInit();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) onuGponAppInit\n", __FILE_DESC__, __LINE__);
+    return(MV_ERROR);
+  }
+
+  berCoeff.numerator   = ONU_GPON_BER_DEF_COEFF_NUMERATOR;
+  berCoeff.denominator = ONU_GPON_BER_DEF_COEFF_DENOMINATOR;
+  onuGponBerInit(&berCoeff, ONU_GPON_DEF_INTERNAL_BER_INTERVAL);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAppInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu gpon application: state & event table,
+**               and alarm table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponAppInit(void)
+{
+  /* onu gpon state & event table */
+  onuGponStateAndEventTblInit();
+
+  /* onu gpon alarm table */
+  onuGponAlarmTblInit();
+
+  /* onu gpon counters table */
+  onuGponPmInPmInit();
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponStateAndEventTblInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function initialize the State and Event Table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponStateAndEventTblInit(void)
+{
+  MV_U32 event;
+  MV_U32 state;
+  S_OnuGponGenTbl *onuGponGenTbl_p = &(onuGponDb_s.onuGponGenTbl_s);
+
+  /* ========================================== */
+  /* Initial setup for the Status & Event table */
+  /* ========================================== */
+
+  /* set onuGponIsrNotExpected function as default */
+  for (event = 0; event < ONU_GPON_NUM_OF_EVENTS; event++)
+  {
+      for (state = 0; state < ONU_GPON_NUM_OF_STATES; state++)
+      {
+          onuGponGenTbl_p->onuGponStateAndEventTbl[event][state] = (GPONFUNCPTR)onuGponPonMngIsrNotExpected;
+      }
+  }
+
+  /* ================================== */
+  /* Message state transittions section */
+  /* ================================== */
+
+  /* ONU GPON STANDBY STATE 02 */
+  /* ------------------------- */
+  state = ONU_GPON_02_STANDBY;
+
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_OVERHEAD][state]      = (GPONFUNCPTR)onuGponPonMngOverheadMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DIS_SN][state]        = (GPONFUNCPTR)onuGponPonMngDisSnMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_PHYSICAL_EQUIP_ERR][state] = (GPONFUNCPTR)onuGponPonMngPhyEquErrMsg;
+
+  /* ONU GPON SERIAL NUM STATE 03 */
+  /* ---------------------------- */
+  state = ONU_GPON_03_SERIAL_NUM;
+
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_SN_MASK][state] = (GPONFUNCPTR)onuGponPonMngSerialNumberMaskMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_EXT_BURST_LEN][state] = (GPONFUNCPTR)onuGponPonMngExtBurstMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_ASSIGN_ONU_ID][state] = (GPONFUNCPTR)onuGponPonMngOnuIdMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DIS_SN][state]        = (GPONFUNCPTR)onuGponPonMngDisSnMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_PHYSICAL_EQUIP_ERR][state] = (GPONFUNCPTR)onuGponPonMngPhyEquErrMsg;
+
+  /* ONU GPON RANGING STATE 04 */
+  /* ------------------------- */
+  state = ONU_GPON_04_RANGING;
+
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_EXT_BURST_LEN][state] = (GPONFUNCPTR)onuGponPonMngExtBurstMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_RANGING_TIME][state]  = (GPONFUNCPTR)onuGponPonMngRangeTimeMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DACT_ONU_ID][state]   = (GPONFUNCPTR)onuGponPonMngDactOnuIdMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DIS_SN][state]        = (GPONFUNCPTR)onuGponPonMngDisSnMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_PHYSICAL_EQUIP_ERR][state] = (GPONFUNCPTR)onuGponPonMngPhyEquErrMsg;
+
+  /* ONU GPON OPERATION STATE 05 */
+  /* --------------------------- */
+  state = ONU_GPON_05_OPERATION;
+
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_EXT_BURST_LEN][state] = (GPONFUNCPTR)onuGponPonMngExtBurstMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_RANGING_TIME][state]  = (GPONFUNCPTR)onuGponPonMngRangeTimeMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DACT_ONU_ID][state]   = (GPONFUNCPTR)onuGponPonMngDactOnuIdMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DIS_SN][state]        = (GPONFUNCPTR)onuGponPonMngDisSnMsg;
+
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_CONFIG_PORT_ID][state] = (GPONFUNCPTR)onuGponPonMngCfgPortIdMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_PHYSICAL_EQUIP_ERR][state] = (GPONFUNCPTR)onuGponPonMngPhyEquErrMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_ENCRYPT_VPI_PORT_ID][state] = (GPONFUNCPTR)onuGponPonMngEncrptPortIdMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_ASSIGN_ALLOC_ID][state] = (GPONFUNCPTR)onuGponPonMngAssignAllocIdMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_REQ_PASSWORD][state]  = (GPONFUNCPTR)onuGponPonMngReqPassMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_REQ_KEY][state]       = (GPONFUNCPTR)onuGponPonMngReqKeyMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_BER_INTERVAL][state]  = (GPONFUNCPTR)onuGponPonMngBerIntervalMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_KEY_SWITCH_TIME][state] = (GPONFUNCPTR)onuGponPonMngKeySwitchTimeMsg;
+
+  /* ONU GPON POPUP STATE 06 */
+  /* ----------------------- */
+  state = ONU_GPON_06_POPUP;
+
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_POPUP][state]         = (GPONFUNCPTR)onuGponPonMngPopupMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DACT_ONU_ID][state]   = (GPONFUNCPTR)onuGponPonMngDactOnuIdMsg;
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DIS_SN][state]        = (GPONFUNCPTR)onuGponPonMngDisSnMsg;
+
+  /* ONU GPON EMERGANCY STOP STATE 07 */
+  /* -------------------------------- */
+  state = ONU_GPON_07_EMERGANCY_STOP;
+
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_MSG_DIS_SN][state]        = (GPONFUNCPTR)onuGponPonMngDisSnMsg;
+
+
+  /* =================== */
+  /* Alarm event section */
+  /* =================== */
+  for (state  = ONU_GPON_01_INIT; state <= ONU_GPON_07_EMERGANCY_STOP; state++)
+  {
+    /* generate */
+    onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_ALM_GEN_LOS][state]     = (GPONFUNCPTR)onuGponPonMngGenCritAlarm;
+    onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_ALM_GEN_LOF][state]     = (GPONFUNCPTR)onuGponPonMngGenCritAlarm;
+    onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_ALM_GEN_LCDG][state]    = (GPONFUNCPTR)onuGponPonMngGenCritAlarm;
+
+    /* cancel */
+    onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_ALM_CAN_LOS][state]     = (GPONFUNCPTR)onuGponPonMngCanCritAlarm;
+    onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_ALM_CAN_LOF][state]     = (GPONFUNCPTR)onuGponPonMngCanCritAlarm;
+    onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_ALM_CAN_LCDG][state]    = (GPONFUNCPTR)onuGponPonMngCanCritAlarm;
+  }
+
+  /* MEM alarm */
+  /* --------- */
+  state = ONU_GPON_05_OPERATION;
+
+  onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_ALM_GEN_MEM][state]       = (GPONFUNCPTR)onuGponPonMngGenMemAlarm;
+}
+
+/*******************************************************************************
+**
+**  onuGponOperate
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function execute onu operate init sequence
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponOperate(void)
+{
+#if 0 /* standalone bring up */
+  MV_STATUS rcode;
+  MV_U32    interruptMask;
+  MV_BOOL   disabledSnState;
+  MV_U8     serialNumber[8];
+  MV_U8     password[10];
+
+  /* ======================================================= */
+  /* ================ Disable SN Section =================== */
+  /* ======================================================= */
+
+  /* register disable SN handler */
+  onuGponPonMngDisableSetRegister(onuGponDisableSnSetHandler);
+
+  /* get disable State */
+  onuGponDisableSnGetHandler(&disabledSnState);
+  if (disabledSnState == MV_FALSE)
+    /* Send Disable Notification to upper layer */
+    onuGponSrvcDisableMsgNotify(MV_FALSE);
+  else
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "==================\n");
+    mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "== ONT DISABLED ==\n");
+    mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "==================\n");
+    /* Send Disable Notification to upper layer */
+    onuGponSrvcDisableMsgNotify(MV_TRUE);
+  }
+
+  /* ======================================================= */
+  /* ================ Serial NUmber Section ================ */
+  /* ======================================================= */
+  onuGponSerialNumberHandler(serialNumber);
+
+  /* ======================================================= */
+  /* ================ Password Section ===================== */
+  /* ======================================================= */
+  onuGponPasswordHandler(password);
+
+  /* ======================================================= */
+  /* ================ Init App Section ===================== */
+  /* ======================================================= */
+  onuGponApiSnMaskConfig(MV_FALSE, MV_FALSE);
+  onuGponApiInit(serialNumber, password, disabledSnState,0);
+
+  /* XVR reset sequence */
+  mvOnuGponMacXvrReset(0);
+
+  /* Enable AES in SoC */
+  mvOnuGponMacAesEnableSet(MV_TRUE);
+
+  /* enable onu gpon interrupt mask */
+  interruptMask = 0;
+  interruptMask |= ONU_GPON_INTERRUPTS << 16;
+  rcode = mvOnuGponMacPonInterruptMaskSet(interruptMask);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) Enable PON interrupt mask\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+#ifndef PON_FPGA
+  /* enable onu dying gasp interrupt mask */
+  rcode = mvOnuPonMacDgInterruptEn(0x1); /* Active High */
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) Enable Dying Gasp interrupt mask\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+#endif /* PON_FPGA */
+
+  /* ======================================================= */
+  /* ================ Enable MAC RX ======================== */
+  /* ======================================================= */
+  mvOnuGponMacRxConfigSet(MV_TRUE);
+
+#else /* dynamic bring up */
+
+  onuGponApiSnMaskConfig(MV_FALSE, MV_FALSE);
+
+  /* XVR reset sequence */
+  mvOnuGponMacXvrReset(0);
+
+  /* Enable AES in SoC */
+  mvOnuGponMacAesEnableSet(MV_TRUE);
+
+#endif
+
+  printk(KERN_INFO "= PON Module Operate ended successfully =\n");
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponStart
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function start onu app
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponStart(S_GponIoctlInfo *onuInit)
+{
+  MV_STATUS rcode;
+  MV_U32    interruptMask;
+  MV_BOOL   disabledSnState;
+
+  /* ======================================================= */
+  /* ================ Disable SN Section =================== */
+  /* ======================================================= */
+  disabledSnState = (onuInit->disableSn != 0) ? (MV_TRUE) : (MV_FALSE);
+  if (disabledSnState == MV_FALSE)
+    /* Send Disable Notification to upper layer */
+    onuGponSrvcDisableMsgNotify(MV_FALSE);
+  else
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "==================\n");
+    mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "== ONT DISABLED ==\n");
+    mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "==================\n");
+    /* Send Disable Notification to upper layer */
+    onuGponSrvcDisableMsgNotify(MV_TRUE);
+  }
+
+  /* ======================================================= */
+  /* ================ Init App Section ===================== */
+  /* ======================================================= */
+  onuGponApiInit(onuInit->serialNum, onuInit->password, disabledSnState, onuInit->serialNumSource);
+  onuGponDbGemResetSet(onuInit->clearGem == 0 ? MV_FALSE : MV_TRUE);
+  onuGponDbTcontResetSet(onuInit->clearTcont  == 0 ? MV_FALSE : MV_TRUE);
+  onuGponDbGemRestoreSet(onuInit->restoreGem  == 0 ? MV_FALSE : MV_TRUE);
+
+  /* ======================================================= */
+  /* ================ Enable PON Interrupt Section ========= */
+  /* ======================================================= */
+  interruptMask = 0;
+  interruptMask |= ONU_GPON_INTERRUPTS << 16;
+  rcode = mvOnuGponMacPonInterruptMaskSet(interruptMask);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) Enable PON interrupt mask\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  /* ======================================================= */
+  /* ================ PON XVR polarity Section ============= */
+  /* ======================================================= */
+  rcode = mvOnuGponMacTxBurstEnPolaritySet(onuInit->xvrPolarity);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+    		   "ERROR: (%s:%d) Set XVR polarity\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  onuGponDbXvrPolaritySet(onuInit->xvrPolarity);
+  mvOnuPonMacBurstEnablePolarityInit(onuInit->xvrPolarity);
+
+#ifndef PON_FPGA
+  /* ========================================================== */
+  /* ================ Dying Gasp Interrupt / Polarity Section = */
+  /* ========================================================== */
+  rcode = mvOnuPonMacDgInterruptEn(onuInit->dgPolarity);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+               "ERROR: (%s:%d) Enable Dying Gasp interrupt mask\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+#endif /* PON_FPGA */
+
+  /* ======================================================= */
+  /* ================ Enable MAC RX ======================== */
+  /* ======================================================= */
+  mvOnuGponMacRxConfigSet(MV_TRUE);
+
+  rcode = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+  if (rcode != MV_OK)
+  {
+	mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+	  		 "ERROR: (%s:%d) mvOnuEponMacOnuIOEnable\n\r", __FILE_DESC__, __LINE__);
+	return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuPonMacAcCouplingInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function inits AC coupling configuration
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuPonMacAcCouplingInit(void)
+{
+	MV_U32 devId = mvCtrlModelGet();
+
+	if (devId != MV_6601_DEV_ID)
+		return(MV_OK);
+
+	return(mvOnuGponMacTxConfigAcCouplingSet(GPON_TX_AC_COUPL_BUST_MODE_0,
+						 GPON_TX_AC_COUPL_PREACT_BURST_TIME,
+						 GPON_TX_AC_COUPL_DATA_PATTERN_1,
+						 GPON_TX_AC_COUPL_DATA_PATTERN_2));
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.h
new file mode 100755
index 0000000..16bc754
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuInit.h
@@ -0,0 +1,107 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuInit.h                                              **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON init sequence definitions      **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_INIT_H

+#define _ONU_GPON_INIT_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponSetup(void);

+MV_STATUS onuGponSwitchOn(void);

+MV_STATUS onuGponOperate(void);

+MV_STATUS onuGponStart(S_GponIoctlInfo *onuInit);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_INIT_H */

+

+  

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.c
new file mode 100755
index 0000000..37d9de2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.c
@@ -0,0 +1,541 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuIsr.c                                               **

+**                                                                           **

+**  DESCRIPTION : This file implements ONU GPON Interrupt handling           **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "gponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/                                               

+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuIsr.c"

+

+#define MV_NO_XVR_RST (0xFF)

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+extern spinlock_t onuPonIrqLock;

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+MV_U32               g_onuGponPreviousInterrupt = ONU_GPON_INT_ALARMS;

+MV_U32               g_onuGponCurrentInterrupt = 0;

+S_OnuGponIsrCounters g_onuGponIsrCounters;

+MV_BOOL              g_ponDebugMode = MV_FALSE;

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponIsrXvrReset(void);

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Operational Section                                */

+/* ========================================================================== */

+/******************************************************************************/

+

+/*******************************************************************************

+**

+**  onuGponIsrInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function reset onu interrupt counters 

+**               

+**  PARAMETERS:  None 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK 

+**                   

+*******************************************************************************/

+MV_STATUS onuGponIsrInit(void)

+{

+  MV_U32 i;

+

+  g_onuGponIsrCounters.interruptReadError = 0;

+  g_onuGponIsrCounters.ploamStatusNoInterrupt = 0;

+  for (i = 0; i < ONU_GPON_ISR_TYPE_MAX ; i++)

+  {

+    g_onuGponIsrCounters.sendMessageError[i] = 0;

+    g_onuGponIsrCounters.setEventError[i] = 0;

+  }

+  for (i = 0; i < ON_GPON_MAX_ALARMS ; i++)

+  {

+    g_onuGponIsrCounters.interruptSameStatus[i] = 0;

+  }

+

+  return(MV_OK);

+}

+

+#ifndef PON_FPGA

+/*******************************************************************************

+**

+**  onuGponIsrXvrResetTimerHndl

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function is called by the GPON Iterrupt handler to execute 

+**               XVR reset sequence in case of a problem with XVR signal detect

+**               

+**  PARAMETERS:  unsigned long data

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**                   

+*******************************************************************************/

+void onuGponIsrXvrResetTimerHndl(unsigned long data)

+{

+  MV_STATUS status;

+  unsigned long flags;

+

+  spin_lock_irqsave(&onuPonIrqLock, flags);

+

+  onuPonResourceTbl_s.onuPonIsrXvrRstTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;

+

+  status = onuGponIsrXvrReset();

+  if (status != MV_NO_XVR_RST) 

+  {

+	if ((onuPonResourceTbl_s.onuPonIsrXvrRstTimerId.onuPonTimerPeriodic) != 0) 

+	  onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId));

+  }

+  else

+  {

+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId));

+  }

+  

+  spin_unlock_irqrestore(&onuPonIrqLock, flags);

+}

+

+/*******************************************************************************

+**

+**  onuGponDgIsrRoutine

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function implements Dying Gasp 

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None

+**                   

+*******************************************************************************/

+void onuGponDgIsrRoutine(void)

+{

+  onuGponPonMngIntrDgHandler();

+}

+#endif /* PON_FPGA */

+

+/*******************************************************************************

+**

+**  onuGponIsrLowRoutine

+**  onuGponIsrRoutine

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function implements interrupt polling mode, it polls the 

+**               current status of an interrupt compare it to the previous 

+**               status, and if an interrupt is active trigger the operation 

+**               of the pon manager task.

+**               

+**  PARAMETERS:  None, void* param 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None, void* 

+**                   

+*******************************************************************************/

+

+/*******************************************************************************

+**

+**  onuGponIsrLowRoutine

+**                   

+*******************************************************************************/

+void onuGponIsrLowRoutine(MV_U32 *interruptEvent, MV_U32 *interruptStatus)

+{

+  MV_U32 interrupt;

+  MV_U32 interruptRawEvent;

+  MV_U32 bip8InterruptValue;

+#ifdef MV_GPON_PERFORMANCE_CHECK

+  S_GponPerformanceCheckNode *tmpPmCheckNode;

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+

+#ifdef MV_GPON_PERFORMANCE_CHECK

+  tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_ISR_PERFORMANCE]);

+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, 

+                             &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+  mvOnuGponMacPonInterruptGet(&interrupt);

+  g_onuGponCurrentInterrupt &= 0xFFFF0000;

+  g_onuGponCurrentInterrupt |= interrupt;

+

+  interruptRawEvent = (g_onuGponCurrentInterrupt >> ONU_GPON_EVENT_SHIFT) & 

+                                                 ONU_GPON_INTERRUPTS;

+  

+  if (interruptRawEvent & ONU_GPON_BIP_INERVAL_MASK)

+  {  

+    mvOnuGponMacBipInterruptStatusValueGet(&bip8InterruptValue);

+    onuGponDbBipInterruptStatusValueSet(bip8InterruptValue);

+  }

+

+  *interruptEvent  = (g_onuGponCurrentInterrupt >> ONU_GPON_EVENT_SHIFT) & ONU_GPON_INTERRUPTS;

+  *interruptStatus = (g_onuGponCurrentInterrupt                        ) & ONU_GPON_INTERRUPTS;

+

+  g_onuGponCurrentInterrupt = 0;

+

+#ifdef MV_GPON_PERFORMANCE_CHECK

+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, 

+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);

+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+}

+

+/*******************************************************************************

+**

+**  onuGponIsrRoutine

+**                   

+*******************************************************************************/

+void onuGponIsrRoutine(MV_U32 event, MV_U32 status)

+{

+  MV_BOOL state;

+  MV_U32 interruptEvent;

+  MV_U32 interruptStatus;

+#ifdef MV_GPON_DEBUG_PRINT

+  MV_U32 timer = 0;

+#endif

+

+#ifdef MV_GPON_HW_INTERRUPT

+  onuGponIsrLowRoutine(&interruptEvent, &interruptStatus);

+#else

+  interruptEvent  = event; 

+  interruptStatus = status;

+#endif /* MV_GPON_HW_INTERRUPT */

+

+  if (g_ponDebugMode != MV_TRUE)

+  {

+#ifdef MV_GPON_DEBUG_PRINT

+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, &timer, 0);

+    mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+               "DEBUG: (%s:%d) Event(0x%08x) Status(0x%08x) timestamp(%d)\n", 

+               __FILE_DESC__, __LINE__, interruptEvent, interruptStatus, timer); 

+#endif

+

+    if (interruptEvent & ONU_GPON_LOS_ALARM_MASK)

+    {

+     // state = (interruptStatus & ONU_GPON_LOS_ALARM_MASK) ? MV_TRUE : MV_FALSE;

+     // onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOS_ALARM, state);

+    }

+

+    if (interruptEvent & ONU_GPON_LOF_ALARM_MASK)

+    {

+      state = (interruptStatus & ONU_GPON_LOF_ALARM_MASK) ? MV_TRUE : MV_FALSE;

+      onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOF_ALARM, state);

+

+	 // if (state == MV_TRUE) 

+	 // {

+  	 //   /* Set DS Sync Ind to OFF */

+	 //   //onuGponDbOnuDsSyncOnSet(0);

+	 // }

+	 // else if (state == MV_FALSE)

+	 // {

+	 //   /* Set DS Sync Ind  to ON */

+	 //   //onuGponDbOnuDsSyncOnSet(1);

+	 // }

+     if (state != MV_TRUE) 

+        onuGponPonMngIntrMessageHandler();

+    }

+

+    if (interruptEvent & ONU_GPON_LCDG_ALARM_MASK)

+    {

+     // state = (interruptStatus & ONU_GPON_LCDG_ALARM_MASK) ? MV_TRUE : MV_FALSE;

+     // onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LCDG_ALARM, state);

+    }

+

+    if (interruptEvent & ONU_GPON_DS_PLOAM_MASK)

+    {

+      onuGponPonMngIntrMessageHandler();

+    }

+

+    if (interruptEvent & ONU_GPON_BIP_INERVAL_MASK)

+    {

+      onuGponPonMngIntrBeCounterHandler();

+    }

+

+    if (interruptEvent & ONU_GPON_RAM_TEST_GRX_PARITY_ERR_MASK)

+    {

+#ifdef MV_GPON_DEBUG_PRINT

+      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+                 "DEBUG: (%s:%d) Event 0x%x - Not supported\n", __FILE_DESC__, __LINE__, interruptEvent);

+#endif /* MV_GPON_DEBUG_PRINT */

+    }

+

+    if (interruptEvent & ONU_GPON_RAM_TEST_GEM_PARITY_ERR_MASK)

+    {

+#ifdef MV_GPON_DEBUG_PRINT

+      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+                 "DEBUG: (%s:%d) Event 0x%x - Not supported\n", __FILE_DESC__, __LINE__, interruptEvent);

+#endif /* MV_GPON_DEBUG_PRINT */

+    }

+

+    if (interruptEvent & ONU_GPON_RAM_TEST_GTX_PARITY_ERR_MASK)

+    {

+#ifdef MV_GPON_DEBUG_PRINT

+      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+                 "DEBUG: (%s:%d) Event 0x%x - Not supported\n", __FILE_DESC__, __LINE__, interruptEvent);

+#endif /* MV_GPON_DEBUG_PRINT */

+    }

+

+    if (interruptEvent & ONU_GPON_RAM_TEST_UTM_PARITY_ERR_MASK)

+    {

+#ifdef MV_GPON_DEBUG_PRINT

+      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+                 "DEBUG: (%s:%d) Event 0x%x - Not supported\n", __FILE_DESC__, __LINE__, interruptEvent);

+#endif /* MV_GPON_DEBUG_PRINT */

+    }

+

+    if (interruptEvent & ONU_GPON_PHY_READY_STATUS_MASK)

+    {

+#ifdef MV_GPON_DEBUG_PRINT

+      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+                 "DEBUG: (%s:%d) Event 0x%x - Not supported\n", __FILE_DESC__, __LINE__, interruptEvent);

+#endif /* MV_GPON_DEBUG_PRINT */

+    }

+

+    if (interruptEvent & ONU_GPON_PHY_SIGNAL_DETECT_STATUS_MASK)

+    {

+#ifdef MV_GPON_DEBUG_PRINT

+      mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+                 "DEBUG: (%s:%d) Event 0x%x - Not supported\n", __FILE_DESC__, __LINE__, interruptEvent);

+#endif /* MV_GPON_DEBUG_PRINT */

+    }

+

+    if (interruptEvent & ONU_GPON_XVR_SIGNAL_DETECT_STATUS_MASK)

+    {

+  	  state = (interruptStatus & ONU_GPON_XVR_SIGNAL_DETECT_STATUS_MASK) ? MV_TRUE : MV_FALSE;

+

+	  if (state == MV_TRUE) 

+	  {

+		onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOS_ALARM, MV_FALSE);

+  	    /* Set signal detect to ON */

+		onuGponDbOnuSignalDetectSet(1);

+

+#ifdef MV_GPON_DEBUG_PRINT

+        mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+                   "DEBUG: (%s:%d) Set signal detect to ON = 1 \n", __FILE_DESC__, __LINE__);

+#endif /* MV_GPON_DEBUG_PRINT */

+#ifndef PON_FPGA

+        onuGponIsrXvrReset();

+        onuGponPonMngIntrMessageHandler();

+#endif /* PON_FPGA */

+	  }

+	  else if (state == MV_FALSE)

+	  {

+		onuGponPonMngIntrAlarmHandler(ONU_PON_MNGR_LOS_ALARM, MV_TRUE);

+	    /* Set signal detect to OFF */

+        onuGponDbOnuSignalDetectSet(0);

+

+#ifdef MV_GPON_DEBUG_PRINT

+        mvPonPrint(PON_PRINT_DEBUG, PON_ISR_MODULE, 

+                   "DEBUG: (%s:%d) Set signal detect to OFF = 0\n", __FILE_DESC__, __LINE__);

+#endif /* MV_GPON_DEBUG_PRINT */

+	  }

+    }

+  }

+}

+

+/*******************************************************************************

+**

+**  onuGponPonMngDebugModeSet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function configure onu debug mode

+**               

+**  PARAMETERS:  MV_BOOL mode 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None  

+**

+*******************************************************************************/

+void onuGponPonMngDebugModeSet(MV_BOOL mode)

+{

+  g_ponDebugMode = mode;

+}

+

+/*******************************************************************************

+**

+**  onuGponPonMngDebugModeGet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function returns onu debug mode

+**               

+**  PARAMETERS:  None  

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     Debug mode   

+**

+*******************************************************************************/

+MV_BOOL onuGponPonMngDebugModeGet(void)

+{

+  return(g_ponDebugMode);

+}

+

+#ifndef PON_FPGA

+/*******************************************************************************

+**

+**  onuGponIsrXvrReset

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function reset xvr

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error    

+**

+*******************************************************************************/

+MV_STATUS onuGponIsrXvrReset(void)

+{

+  MV_STATUS status;

+  MV_U32    onuState;

+  MV_U32    initDone;

+

+  onuState = onuGponDbOnuStateGet();

+  if ((onuState == ONU_GPON_01_INIT) ||

+     ((onuState == ONU_GPON_07_EMERGANCY_STOP) && (onuGponAsicAlarmStatusGet() == ONU_GPON_ALARM_ON)) || 

+	 ((onuState == ONU_GPON_06_POPUP)))

+  {

+    status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x1, 0);  

+    if (status != MV_OK) 

+      return(status);

+

+    do 

+    {

+      status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE, &initDone, 0);  

+      if (status != MV_OK) 

+        return(status);

+

+    } while (initDone == 0);

+

+    status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x0, 0);  

+    if (status != MV_OK) 

+      return(status);

+  }

+  else

+  {

+	return(MV_NO_XVR_RST);

+  }

+

+  return (MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponIsrXvrResetStateSet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function enable / disable onu xvr reset timer

+**               

+**  PARAMETERS:  MV_BOOL mode 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error    

+**

+*******************************************************************************/

+MV_STATUS onuGponIsrXvrResetStateSet(MV_BOOL mode)

+{

+  MV_STATUS rcode = MV_OK;

+

+  if (mode == MV_TRUE)

+  {

+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId));  

+  }

+  else

+  {

+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId));

+  }

+

+  return (rcode);

+}

+#endif /* PON_FPGA */

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.h
new file mode 100755
index 0000000..11ee96b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuIsr.h
@@ -0,0 +1,185 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuIsr.h                                               **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Interrupt implementation       **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_ISR_H

+#define _ONU_GPON_ISR_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+#define ONU_GPON_LOS_ALARM_MASK                 (0x0001)

+#define ONU_GPON_LOF_ALARM_MASK                 (0x0002)

+#define ONU_GPON_LCDG_ALARM_MASK                (0x0004)

+#define ONU_GPON_DS_PLOAM_MASK                  (0x0008)

+#define ONU_GPON_CDR_LOL_MASK                   (0x0010)

+#define ONU_GPON_BIP_INERVAL_MASK               (0x0020)

+#define ONU_GPON_RAM_TEST_GRX_PARITY_ERR_MASK   (0x0040)

+#define ONU_GPON_RAM_TEST_GEM_PARITY_ERR_MASK   (0x0080)

+#define ONU_GPON_RAM_TEST_GTX_PARITY_ERR_MASK   (0x0100)

+#define ONU_GPON_RAM_TEST_UTM_PARITY_ERR_MASK   (0x0200)

+#define ONU_GPON_PHY_READY_STATUS_MASK          (0x0400)

+#define ONU_GPON_PHY_SIGNAL_DETECT_STATUS_MASK  (0x0800)

+#define ONU_GPON_XVR_SIGNAL_DETECT_STATUS_MASK  (0x1000)

+                                               

+#define ONU_GPON_LOS_ALARM_SHIFT                (0)

+#define ONU_GPON_LOF_ALARM_SHIFT                (1)

+#define ONU_GPON_LCDG_ALARM_SHIFT               (2)

+#define ONU_GPON_DS_PLOAM_SHIFT                 (3)

+#define ONU_GPON_CDR_LOL_SHIFT                  (4)

+#define ONU_GPON_BIP_INERVAL_SHIFT              (5)

+#define ONU_GPON_RAM_TEST_GRX_PARITY_ERR_SHIFT  (6)

+#define ONU_GPON_RAM_TEST_GEM_PARITY_ERR_SHIFT  (7)

+#define ONU_GPON_RAM_TEST_GTX_PARITY_ERR_SHIFT  (8)

+#define ONU_GPON_RAM_TEST_UTM_PARITY_ERR_SHIFT  (9)

+#define ONU_GPON_PHY_READY_STATUS_SHIFT         (10)

+#define ONU_GPON_PHY_SIGNAL_DETECT_STATUS_SHIFT (11)

+#define ONU_GPON_XVR_SIGNAL_DETECT_STATUS_SHIFT (12)

+

+#define ONU_GPON_EVENT_SHIFT                    (16)

+                                               

+#define ON_GPON_MAX_ALARMS                      (3)

+

+#define ONU_GPON_INT_ALARMS                     (ONU_GPON_LOF_ALARM_MASK |\

+                                                 ONU_GPON_LCDG_ALARM_MASK)

+

+#define ONU_GPON_PARITY_ERROR                   (ONU_GPON_RAM_TEST_GRX_PARITY_ERR_MASK  |\

+                                                 ONU_GPON_RAM_TEST_GEM_PARITY_ERR_MASK  |\

+                                                 ONU_GPON_RAM_TEST_GTX_PARITY_ERR_MASKK |\

+                                                 ONU_GPON_RAM_TEST_UTM_PARITY_ERR_MASK)

+                                               

+#define ONU_GPON_READY_STATUS                   (ONU_GPON_PHY_READY_STATUS_SHIFT         |\

+                                                 ONU_GPON_PHY_SIGNAL_DETECT_STATUS_SHIFT |\

+                                                 ONU_GPON_XVR_SIGNAL_DETECT_STATUS_SHIFT)

+

+#if 1

+#define ONU_GPON_INTERRUPTS                     (ONU_GPON_INT_ALARMS |\

+                                                 ONU_GPON_DS_PLOAM_MASK |\

+                                                 ONU_GPON_BIP_INERVAL_MASK |\

+                                                 ONU_GPON_XVR_SIGNAL_DETECT_STATUS_MASK)

+#else

+#define ONU_GPON_INTERRUPTS                     (ONU_GPON_INT_ALARMS       |\

+                                                 ONU_GPON_PARITY_ERROR     |\

+                                                 ONU_GPON_READY_STATUS     |\

+                                                 ONU_GPON_DS_PLOAM_MASK    |\

+                                                 ONU_GPON_BIP_INERVAL_MASK)*/                                               

+#endif

+

+#define ONU_GPON_INTERRUPT_INTERVAL             (10)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+typedef enum

+{

+  ONU_GPON_ISR_ALARM,

+  ONU_GPON_ISR_PLOAM,

+  ONU_GPON_ISR_BIP,

+  ONU_GPON_ISR_TYPE_MAX

+}E_OnuGponIsrTypes;

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef struct

+{

+  MV_U32 interruptReadError;

+  MV_U32 sendMessageError[ONU_GPON_ISR_TYPE_MAX];   

+  MV_U32 setEventError[ONU_GPON_ISR_TYPE_MAX]; 

+  MV_U32 interruptSameStatus[ON_GPON_MAX_ALARMS];

+  MV_U32 ploamStatusNoInterrupt;

+}S_OnuGponIsrCounters;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponIsrInit(void);

+void      onuGponIsrLowRoutine(MV_U32 *interruptEvent, MV_U32 *interruptStatus);

+void      onuGponIsrRoutine(MV_U32 interruptEvent, MV_U32 interruptStatus);

+#ifndef PON_FPGA

+void      onuGponDgIsrRoutine(void);

+void      onuGponIsrXvrResetTimerHndl(unsigned long data);

+MV_STATUS onuGponIsrXvrResetStateSet(MV_BOOL mode);

+#endif /* PON_FPGA */

+void      onuGponPonMngDebugModeSet(MV_BOOL mode);

+MV_BOOL   onuGponPonMngDebugModeGet(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_ISR_H */

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.c
new file mode 100755
index 0000000..71f0803
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.c
@@ -0,0 +1,556 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuMngr.c                                              **

+**                                                                           **

+**  DESCRIPTION : This file implements ONU GPON Manager functionality        **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "gponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/      

+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuMngr.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+MV_U32  g_mngrSuspiciousFifoErrCounter = 0;

+MV_U32  g_mngrDecidedFifoErrCounter    = 0;

+

+MV_U8 *dsPloamText[MAC_LAST_DOWNSTREAM_PLOAM + 1] = 

+{ "UNKNOWN",

+  "UPSTREAM OVERHEAD",  

+  "SERIAL_NUMBER MASK",

+  "ASSIGN ONU ID",      

+  "RANGING TIME",

+  "DEACTIVATE ONU ID",  

+  "DISABLE SERIAL NUMBER",

+  "CONFIGURE VP/VC",    

+  "ENCRYPTED PORT-ID/VPI",

+  "REQUEST PASSWORD",   

+  "ASSIGN ALLOC ID",

+  "NO MESSAGE",         

+  "POPUP",

+  "REQUEST KEY",        

+  "CONFIGURE PORT-ID",

+  "PEE",                

+  "CHANGE POWER LEVEL",

+  "PST MESSAGE",        

+  "BER INTERVAL",

+  "KEY SWITCHING TIME", 

+  "EXTENDED BURST LENGTH"

+};

+

+extern spinlock_t onuPonIrqLock;

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+

+/******************************************************************************/

+/* ========================================================================== */

+/*                         Operational Section                                */

+/* ========================================================================== */

+/******************************************************************************/

+

+/*******************************************************************************

+**

+**  onuGponPonMngIntrAlarmHandler

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function implements the pon manager interrupt alarm 

+**               functionality 

+**               - handle alarms (LOS, LOF, and LCDG)

+**               

+**  PARAMETERS:  MV_U32 alarm    

+**               MV_U32 alarmStatus

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponPonMngIntrAlarmHandler(MV_U32 alarm, MV_BOOL alarmStatus)

+{

+  MV_U32          onuState;

+  MV_U32          alarmIndex;

+  MV_U32          alarmEvent;

+  GPONFUNCPTR     ptrFunc;

+  S_OnuGponGenTbl *onuGponGenTbl_p;

+  MV_U32          eventBase;

+

+  /* Events State Machine Table */

+  onuGponGenTbl_p = &(onuGponDb_s.onuGponGenTbl_s);

+

+  /* get onu state */

+  onuState = onuGponDbOnuStateGet();

+

+  /* Get the Alarm Index in the Event Table */

+  switch (alarm)

+  {

+  case ONU_PON_MNGR_LOS_ALARM:

+    alarmIndex = ONU_GPON_ALARM_LOS;

+    alarmEvent = ONU_GPON_EVENT_ALARM_LOS;

+    break;

+  case ONU_PON_MNGR_LOF_ALARM: 

+    alarmIndex = ONU_GPON_ALARM_LOF;

+    alarmEvent = ONU_GPON_EVENT_ALARM_LOF;

+    break;

+  case ONU_PON_MNGR_LCDG_ALARM:

+    alarmIndex = ONU_GPON_ALARM_LCDG;

+    alarmEvent = ONU_GPON_EVENT_ALARM_LCDG;

+    break;

+  default:

+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,

+               "ERROR: (%s:%d) Unkown Alarm Type, alarm(%d), status(%d)\n", 

+               __FILE_DESC__, __LINE__, alarm, alarmStatus);

+    return;

+  }

+

+  /* Get the Base Enum in the Event Table */

+  eventBase = (alarmStatus == MV_TRUE) ? ONU_GPON_ALARM_GEN_BASE : ONU_GPON_ALARM_CAN_BASE;

+

+  /* handle alarm deactivation */

+  ptrFunc = onuGponGenTbl_p->onuGponStateAndEventTbl[eventBase + alarmEvent][onuState];

+  if (ptrFunc == NULL)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,

+               "ERROR: (%s:%d) Cancel alarm - function is NULL, alarm(%d), status(%d)\n", 

+               __FILE_DESC__, __LINE__, alarm, alarmStatus);

+  }

+  else

+  {

+    (*ptrFunc)(alarmIndex, 0, NULL);

+  }

+}

+

+/*******************************************************************************

+**

+**  onuGponPonMngIntrMessageHandler

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function implements the pon manager interrupt message 

+**               functionality 

+**               

+**  PARAMETERS:  None    

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponPonMngIntrMessageHandler(void)

+{

+  MV_STATUS     rcode;

+  MV_U32        ploamFifoSize;

+  static MV_U32 ploamErrorCounter = 0;

+  MV_U32        i;

+  MV_U32        dummyBuffer;

+  MV_U8         msgData[12];

+  MV_U8         msgOnuId;

+  MV_U8         msgId;

+  MV_BOOL       onuValid;

+

+#ifdef MV_GPON_PERFORMANCE_CHECK

+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_MNG1_PERFORMANCE]);

+

+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, 

+                             &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+  /* Get the Init value of the ONU (if it MV_FALSE - not Valid yet) */

+  onuValid = onuGponDbInitGet();

+

+  /* read fifo size */

+  rcode = mvOnuGponMacRxPloamDataUsedGet(&ploamFifoSize);

+  if (rcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,

+               "ERROR: (%s:%d) Read ploam message fifo size\n", __FILE_DESC__, __LINE__);

+    return;

+  }

+

+#ifdef MV_GPON_DEBUG_PRINT

+  mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MODULE,

+             "DEBUG: (%s:%d) PLOAM FIFO Used (%d) words\n", __FILE_DESC__, __LINE__, ploamFifoSize);

+#endif /* MV_GPON_DEBUG_PRINT */

+

+#ifdef MV_GPON_PERFORMANCE_CHECK

+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, 

+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);

+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+  /* there is at least one full ploam message in the fifo */

+  while (ploamFifoSize >= 3)

+  {

+#ifdef MV_GPON_PERFORMANCE_CHECK

+    tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_MNG2_PERFORMANCE]);

+   

+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, 

+                             &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+    /* clear received message content */

+    memset((void*)msgData, 0, sizeof (msgData));

+

+    /* read message from fifo */

+    rcode = mvOnuGponMacMessageReceive(&msgOnuId, &msgId, msgData);

+    if (rcode != MV_OK)

+    {

+      mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,

+                 "ERROR: (%s:%d) Read ploam message\n", __FILE_DESC__, __LINE__);

+      return;     

+    }

+

+#ifdef MV_GPON_DEBUG_PRINT

+    mvPonPrint(PON_PRINT_DEBUG, PON_MNG_MODULE,

+               "[DS PLOAM] %s, onuId(%d), msgId(%d), msg[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",

+               dsPloamText[(msgId > 20) ? 0 : msgId], msgOnuId, msgId, 

+               msgData[0], msgData[1], msgData[2], msgData[3], msgData[4], 

+               msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);

+#endif /* MV_GPON_DEBUG_PRINT */

+

+    onuGponPmRxSwCountersAdd(msgId);

+

+#ifdef MV_GPON_PERFORMANCE_CHECK

+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, 

+                             &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);

+    if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+    /* If ONU wasn't init ONU will receive Downstream PLOAMs but won't handle it */

+    if (onuValid != MV_FALSE)

+    {

+      onuGponPonMngPloamProcess(msgOnuId, msgId, msgData);  

+    }

+

+#ifdef MV_GPON_PERFORMANCE_CHECK

+    tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_MNG3_PERFORMANCE]);

+   

+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, 

+                             &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+    /* Check first if there are any complete message in FIFO */

+    rcode = mvOnuGponMacRxPloamDataUsedGet(&ploamFifoSize);

+    if (rcode != MV_OK)

+    {

+      mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,

+                 "ERROR: (%s:%d) Read ploam message\n", __FILE_DESC__, __LINE__);

+      return;

+    }

+

+#ifdef MV_GPON_PERFORMANCE_CHECK

+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT, 

+                             &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);

+    if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+  } /* while */

+

+  /* Clean FIFO if it lost alignment */

+  if ((ploamFifoSize > 0) && (ploamFifoSize < 3))

+  {

+    ploamErrorCounter++;

+    g_mngrSuspiciousFifoErrCounter++;

+    if (ploamErrorCounter == 3)

+    {

+      g_mngrDecidedFifoErrCounter++;

+      for (i = 0; i < ploamFifoSize; i++)

+      {

+        mvOnuGponMacRxPloamDataGet(&dummyBuffer);

+      }

+    }

+  }

+  else

+    ploamErrorCounter = 0;

+}

+

+/*******************************************************************************

+**

+**  onuGponPonMngPloamProcess

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function Hadnle single received PLAOM message

+**               

+**  PARAMETERS:  MV_U8 onuId

+**               MV_U8 msgId

+**               MV_U8 *msgData    

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponPonMngPloamProcess(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)

+{

+  MV_U32          appOnuId;

+  MV_U32          onuState;

+  GPONFUNCPTR     ptrFunc;

+  S_OnuGponGenTbl *onuGponGenTbl_p = &(onuGponDb_s.onuGponGenTbl_s);

+

+  /* get onu Id */

+  appOnuId = onuGponDbOnuIdGet();

+

+  /* get onu state */

+  onuState = onuGponDbOnuStateGet();

+

+  /* Filter for messages with invalid ONU Id */

+  if ((onuId == ONU_GPON_BROADCAST_ONU_ID) || (onuId == appOnuId))

+  {

+    /* Handle valid messages */

+    if ((msgId >= ONU_GPON_DS_MSG_OVERHEAD) && (msgId <= ONU_GPON_DS_MSG_EXT_BURST_LEN))

+    {

+      /* Call the relevant event function */

+      ptrFunc = (onuGponGenTbl_p->onuGponStateAndEventTbl[(msgId)][onuState]);

+      if (ptrFunc == NULL)

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,

+                   "ERROR: (%s:%d) Msg function is NULL, onuId(%d), msgId(%d)\n", 

+                   __FILE_DESC__, __LINE__, onuId, msgId);

+      }

+      else

+      {

+        (*ptrFunc)(onuId, msgId, msgData);

+      }           

+    }

+    /* handle invalid messages */

+    else

+    {

+      /* Call the relevant function */

+      ptrFunc = (onuGponGenTbl_p->onuGponStateAndEventTbl[ONU_GPON_EVENT_ALM_GEN_MEM][onuState]);

+      if (ptrFunc == NULL)

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,

+                   "ERROR: (%s:%d) Msg function is NULL, onuId(%d), msgId(%d)\n", 

+                   __FILE_DESC__, __LINE__, onuId, msgId);

+      }

+      else

+      {

+        (*ptrFunc)(ONU_GPON_ALARM_MEM, 0, NULL);

+      }           

+    } 

+  } 

+}

+

+/*******************************************************************************

+**

+**  onuGponPonMngIntrBeCounterHandler

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function implements the pon manager interrupt BER counter 

+**               expired functionality 

+**               

+**  PARAMETERS:  None    

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponPonMngIntrBeCounterHandler(void)

+{

+  MV_U32 onuState;

+  MV_U32 bipErrorsCounter = 0;

+  MV_U8  onuId;

+

+  onuState = onuGponDbOnuStateGet();

+  onuId    = onuGponDbOnuIdGet();

+

+  if (onuState != ONU_GPON_05_OPERATION)

+  {

+    return;

+  }

+

+  /* Read BIP8 errors counter in MAC */

+  bipErrorsCounter = onuGponDbBipInterruptStatusValueGet();

+ 

+  /* Send an upstream REI message */

+  mvOnuGponMacReiMessageSend(onuId, bipErrorsCounter);

+}

+

+#ifndef PON_FPGA

+/*******************************************************************************

+**

+**  onuGponPonMngIntrDgHandler

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function implements the pon manager interrupt dying gasp  

+**               functionality 

+**               

+**  PARAMETERS:  None    

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponPonMngIntrDgHandler(void)

+{

+  MV_U8         onuId = onuGponDbOnuIdGet();

+  static MV_U32 first_time = 1;

+  DYINGGASPFUNC dgCallback;

+

+  mvOnuGponMacDgMessageSend(onuId);

+

+  if (first_time) 

+  {

+    dgCallback = onuGponDbDgCallbackGet();

+

+    if (dgCallback != NULL) 

+    {

+        dgCallback();

+        first_time = 0;

+    }

+  }

+

+  onuPonDyingGaspExit();

+}

+#endif /* PON_FPGA */

+

+/*******************************************************************************

+**

+**  onuGponPonMngrFifoErrCountersGet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION:   The function 

+**                 

+**  PARAMETERS:    None    

+**

+**  OUTPUTS:       None

+**

+**  RETURNS:       None 

+**

+*******************************************************************************/

+MV_U32 onuGponPonMngrFifoErrCountersGet(MV_U32 *suspiciousCounter)

+{

+  MV_U32 suspected;

+  MV_U32 decided;

+

+  suspected = g_mngrSuspiciousFifoErrCounter;

+  decided = g_mngrDecidedFifoErrCounter;

+

+  g_mngrSuspiciousFifoErrCounter = 0;

+  g_mngrDecidedFifoErrCounter = 0;

+

+  *suspiciousCounter = suspected;

+  return(decided);

+}

+

+/*******************************************************************************

+**

+**  onuGponTimerFifoAuditHndl

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function is called by the GPON PM timer and trigger the

+**               GPON handler to execute SW FIFO Audit

+**               

+**  PARAMETERS:  unsigned long data

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponTimerFifoAuditHndl(unsigned long data)

+{

+  unsigned long flags;

+  /* Lock GPON interrupt */

+  spin_lock_irqsave(&onuPonIrqLock, flags);

+

+  onuPonResourceTbl_s.onuPonSwFIFOTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;

+

+  if (onuGponDbOnuStateGet() == ONU_GPON_05_OPERATION)

+  {

+    spin_unlock_irqrestore(&onuPonIrqLock, flags);

+    return;

+  }

+

+  /* Call PM handler */

+  mvOnuGponFifoAuditTimerExpireHndl();

+

+  if ((onuPonResourceTbl_s.onuPonSwFIFOTimerId.onuPonTimerPeriodic) != 0) 

+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId));

+

+  /* Unlock GPON interrupt */

+  spin_unlock_irqrestore(&onuPonIrqLock, flags);

+}

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.h
new file mode 100755
index 0000000..8e54d99
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngr.h
@@ -0,0 +1,200 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuMngr.h                                              **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Manager definitions            **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_MNGR_H

+#define _ONU_GPON_MNGR_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+/* Disable Message disable/Enable Options */

+#define GPON_ONU_DISABLE		    (0xFF)

+#define GPON_ONU_ENABLE_ALL	        (0x0F)

+#define GPON_ONU_ENABLE_ONU	        (0x00)

+

+/* timer sub types */

+#define TIMER_T01_EXPIRE            (1)

+#define TIMER_T02_EXPIRE            (2)

+#define TIMER_PEE_EXPIRE            (3)

+                                   

+/* stats sub types */              

+#define STATS_ACCMULATE             (1)

+#define STATS_RESET                 (2)

+#define STATS_SHOW                  (3)

+

+/* Alarms Types */

+#define ONU_PON_MNGR_LOS_ALARM      (0)

+#define ONU_PON_MNGR_LOF_ALARM      (1)

+#define ONU_PON_MNGR_LCDG_ALARM     (2)

+

+/* Assign Alloc Id Types */

+#define ONU_GPON_ATM_PAYLOAD        (0)

+#define ONU_GPON_GEM_PAYLOAD        (1)

+#define ONU_GPON_DBA_PAYLOAD        (2)

+#define ONU_GPON_DEALLOCATE         (255)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef MV_STATUS (*DISABLESTATSETFUNC)(MV_BOOL disable);

+

+typedef struct

+{

+  MV_U32 msgType;

+  MV_U32 subType;

+  MV_U32 status;

+  MV_U32 param;

+}S_MngrMsg;

+

+typedef struct

+{

+  MV_U32 msgType;

+  MV_U32 subType;

+  MV_U8  onuId;

+  MV_U8  msgId;

+  MV_U8  data[10];

+}S_MngrDebugMsg;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+/* Interrupt handler Functions */

+void      onuGponPonMngIntrAlarmHandler(MV_U32 alarm, MV_BOOL alarmStatus); 

+void      onuGponPonMngIntrMessageHandler(void);

+void      onuGponPonMngIntrBeCounterHandler(void);

+#ifndef PON_FPGA

+void      onuGponPonMngIntrDgHandler(void);

+#endif /* PON_FPGA */

+

+/* Timer handler Functions */

+void      onuGponTimerFifoAuditHndl(unsigned long data);

+

+/* State Machine Functions */

+void      onuGponPonMngPloamProcess(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+

+void      onuGponPonMngIsrNotExpected(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngOverheadMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngSerialNumberMaskMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngOnuIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngRangeTimeMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngDactOnuIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngDisSnMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngCfgVpVcMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngEncrptPortIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngAssignAllocIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngNoMsgMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngPopupMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngCfgPortIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngPhyEquErrMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngChgPwrLvlMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngPstMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngKeySwitchTimeMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngExtBurstMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+

+void      onuGponPonMngTimerT01Hndl(unsigned long data);

+void      onuGponPonMngTimerT02Hndl(unsigned long data);

+void      onuGponPonMngTimerPeeHndl(unsigned long data);

+void      onuGponPonMngTimerT01ExpireHndl(void);

+void      onuGponPonMngTimerT02ExpireHndl(void);

+void      onuGponPonMngTimerPeeExpireHndl(void);

+

+/* Alarm Functions */

+void      onuGponPonMngGenCritAlarm(E_OnuGponAlarmType alarmType_e, MV_U8 dummyVal, MV_U8 *dummyPtr);

+void      onuGponPonMngCanCritAlarm(E_OnuGponAlarmType alarmType_e, MV_U8 dummyVal, MV_U8 *dummyPtr);

+void      onuGponPonMngGenMemAlarm(E_OnuGponAlarmType alarmType_e, MV_U8 dummyVal, MV_U8 *dummyPtr);

+/* Operation State Functions */                 

+void      onuGponPonMngConfigPortIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);    

+void      onuGponPonMngReqPassMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);    

+void      onuGponPonMngBerIntervalMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData); 

+void      onuGponPonMngPhyEquipErrMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);   

+void      onuGponPonMngReqKeyMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+void      onuGponPonMngEncryptPortIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);       

+void      onuGponPonMngKeySwitchTimwMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData);

+

+void      onuGponPonMngOverheadManualModeSet(MV_BOOL mode);

+MV_BOOL   onuGponPonMngOverheadManualModeGet(void);

+MV_U32    onuGponPonMngrFifoErrCountersGet(MV_U32 *suspiciousCounter);

+MV_STATUS onuGponPonMngDisableSetRegister(DISABLESTATSETFUNC disableFunc);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_MNGR_H */

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngrStateMachine.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngrStateMachine.c
new file mode 100755
index 0000000..5248f2b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuMngrStateMachine.c
@@ -0,0 +1,3048 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuMngrStateMachine.c                                  **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON Manager state machine        **
+**                functionality                                              **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "gponOnuHeader.h"
+#include "gbe/mvNeta.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuStateMachine.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+extern spinlock_t onuPonIrqLock;
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+MV_BOOL            g_overheadManualMode = MV_FALSE;
+DISABLESTATSETFUNC g_onuGponDisableFunc = NULL;
+MV_BOOL            g_periodicTimerState = MV_FALSE;
+MV_U32             g_overheadPreAssignDelayForPopup = 0;
+/* Export Functions
+------------------------------------------------------------------------------*/
+extern MV_STATUS onuGponAllocIdMacAdd(MV_U32 allocId, MV_U32 tcontId);
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+MV_STATUS onuGponPonMngrUpdateState(MV_U32 newState);
+MV_STATUS onuGponPonMngClearOnuInfo(void);
+MV_STATUS onuGponPonMngClearOnuTconts(void);
+MV_STATUS onuGponPonMngClearOnuPorts(void);
+MV_STATUS onuGponPonMngClearOnuId(void);
+MV_STATUS onuGponPonMngClearOnuDelay(void);
+MV_STATUS onuGponPonMngClearOnuOverhead(void);
+MV_STATUS onuGponPonMngClearBerInterval(void);
+MV_STATUS onuGponPonMngPreambleSet(MV_U32 onuState);
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Messages Section                                   */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponPonMngUpdateState
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when a change of state in the ONU
+**               state machine is needed.
+**
+**  PARAMETERS:  MV_U32 newState
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngrUpdateState(MV_U32 newState)
+{
+  MV_STATUS rcode;
+  MV_U32    currentState;
+  MV_U32    asicNewState = newState;
+  MV_BOOL   dumpEnabled;
+
+  /* get onu state */
+  currentState = onuGponDbOnuStateGet();
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) ONT STATE CHANGING: FROM STATE[%d] TO STATE [%d]\n",
+             __FILE_DESC__, __LINE__, currentState, newState);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  dumpEnabled = onuGponDbBwMapCntDumpGet();
+
+  if (dumpEnabled == MV_TRUE)
+  {
+      onuGponPmRxBwMapCountersAdd();
+  }
+
+  if (newState == ONU_GPON_01_INIT)
+  {
+    /*Reset All Counters*/
+    onuGponApiResetAllCtr();
+
+#ifndef PON_FPGA
+    /* No Downstream - Turn LED OFF */
+    onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_OFF);
+#endif /* PON_FPGA */
+
+    /* stop onu periodic timers */
+    if (g_periodicTimerState != MV_FALSE)
+    {
+      onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonPmTimerId));
+      onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId));
+      mvOnuGponMacMessageCleanSwFifo();
+      g_periodicTimerState = MV_FALSE;
+    }
+  }
+
+  if (newState == ONU_GPON_02_STANDBY)
+  {
+#ifndef PON_FPGA
+    /* Downstream ON - Blink the LED */
+    onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_BLINK_SLOW);
+#endif /* PON_FPGA */
+
+    /* start onu periodic timers */
+    if (g_periodicTimerState != MV_TRUE)
+    {
+      onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonPmTimerId));
+      onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId));
+      mvOnuGponMacMessageCleanSwFifo();
+      g_periodicTimerState = MV_TRUE;
+    }
+  }
+
+  rcode = onuGponPonMngPreambleSet(newState);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) Preamble Set\n", __FILE_DESC__, __LINE__);
+  }
+
+  if (newState == ONU_GPON_03_SERIAL_NUM)
+  {
+#ifndef PON_FPGA
+    /* Sync sequence - Blink the LED fast */
+    onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_BLINK_FAST);
+#endif /* PON_FPGA */
+
+    if ((onuGponDbSerialNumberMaskMatchGet()  == MV_FALSE) &&
+        (onuGponDbSerialNumberMaskEnableGet() == MV_TRUE))
+    {
+      asicNewState = ONU_GPON_02_STANDBY;
+    }
+  }
+
+  /* update state */
+  /* ============ */
+
+  /* update asic */
+  rcode = mvOnuGponMacOnuStateSet(asicNewState);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacOnuStateSet\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  /* update database */
+  onuGponDbOnuStateSet(newState);
+
+  if (dumpEnabled == MV_TRUE)
+  {
+      onuGponApiPmRxBwMapPmDump(currentState, newState);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngClearOnuInfo
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reset onu information to its default state:
+**               asic & application
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngClearOnuInfo(void)
+{
+  MV_STATUS rcode;
+
+  rcode = onuGponPonMngClearOnuPorts();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuPorts\n", __FILE_DESC__, __LINE__);    return(rcode);
+  }
+
+  rcode = onuGponPonMngClearOnuTconts();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuTconts\n", __FILE_DESC__, __LINE__);    return(rcode);
+  }
+
+  rcode = onuGponPonMngClearOnuId();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuId\n", __FILE_DESC__, __LINE__);    return(rcode);
+  }
+
+  rcode = onuGponPonMngClearOnuDelay();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuDelay\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  rcode = onuGponPonMngClearOnuOverhead();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuOverhead\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  rcode = onuGponPonMngClearBerInterval();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearBerInterval\n", __FILE_DESC__, __LINE__);
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngClearOnuPorts
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clear onu ports information from the
+**               asic & application
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngClearOnuPorts(void)
+{
+  /* Remove Encryption from all ports */
+  onuGponDbGemPortAesClearAll();
+  mvOnuGponMacAesInit();
+
+  /* Remove all gem ports */
+  if (onuGponDbGemResetGet()== MV_TRUE) {
+      onuGponDbGemPortClearAll();
+      mvOnuGponMacGemInit();
+     /* Remove OMCC port */
+      onuGponApiGemOmccIdConfig(0, MV_FALSE);
+      onuGponDbOmccPortSet(0);
+  }
+
+  /* Set OMCC To be not Valid */
+  onuGponDbOmccValidSet(MV_FALSE);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngClearOnuTconts
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clear onu tcont information from the
+**               asic & application
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngClearOnuTconts(void)
+{
+  MV_STATUS rcode = MV_OK;
+
+  if (onuGponDbTcontResetGet()==MV_TRUE) {
+      rcode = onuGponAllocIdDeAssignAll();
+      if (rcode != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) onuGponAllocIdDeAssignAll\n", __FILE_DESC__, __LINE__);
+        return(rcode);
+      }
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngClearOnuId
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION:   The function clear onu Id information from the
+**                 asic & application
+**
+**  PARAMETERS:    None
+**
+**  OUTPUTS:       None
+**
+**  RETURNS:       MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngClearOnuId(void)
+{
+  MV_STATUS rcode;
+
+  /* update asic */
+  rcode = onuGponSrvcOnuIdUpdate(ONU_GPON_UNDEFINED_ONU_ID, MV_FALSE);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  /* update database */
+  onuGponDbOnuIdSet(ONU_GPON_UNDEFINED_ONU_ID);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngClearOnuDelay
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION:   The function clear onu delay information from the
+**                 asic & application
+**
+**  PARAMETERS:    None
+**
+**  OUTPUTS:       None
+**
+**  RETURNS:       MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngClearOnuDelay(void)
+{
+  MV_STATUS rcode;
+
+  /* update asic */
+  rcode = mvOnuGponMacRxEqualizationDelaySet(GPON_TX_EQUAL_DELAY_TD);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  rcode = mvOnuGponMacTxFinalDelaySet(GPON_TX_FINAL_DELAY_FD);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  /* update database */
+  onuGponDbEqualizationDelaySet(GPON_TX_EQUAL_DELAY_TD);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngClearOnuOverhead
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION:   The function clear onu overhead information from the
+**                 asic & application
+**
+**  PARAMETERS:    None
+**
+**  OUTPUTS:       None
+**
+**  RETURNS:       MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngClearOnuOverhead(void)
+{
+  MV_STATUS rcode;
+
+  if (g_overheadManualMode == MV_TRUE)
+  {
+    return(MV_OK);
+  }
+
+  /* update asic */
+  rcode = mvOnuGponMacPreambleSet(ONU_TX_PREAMBLE_TYPE_01_P, ONU_TX_PREAMBLE_TYPE_01_PC,
+                                ONU_TX_PREAMBLE_TYPE_02_P, ONU_TX_PREAMBLE_TYPE_02_PC,
+                                ONU_TX_PREAMBLE_TYPE_03_P, ONU_TX_PREAMBLE_TYPE_03_DEF_PC);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  rcode = mvOnuGponMacTxDelimiterSet(GPON_TX_DELIMITER, GPON_TX_DELIMITER_DS);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  /* update database */
+  onuGponDbPreambleSet (ONU_GPON_PREM_TYPE_01, ONU_TX_PREAMBLE_TYPE_01_P, ONU_TX_PREAMBLE_TYPE_01_PC);
+  onuGponDbPreambleSet (ONU_GPON_PREM_TYPE_02, ONU_TX_PREAMBLE_TYPE_02_P, ONU_TX_PREAMBLE_TYPE_02_PC);
+  onuGponDbPreambleSet (ONU_GPON_PREM_TYPE_03, ONU_TX_PREAMBLE_TYPE_03_P, ONU_TX_PREAMBLE_TYPE_03_DEF_PC);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngClearBerInterval
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION:   The function clear ber interval information from the
+**                 asic & application
+**
+**  PARAMETERS:    None
+**
+**  OUTPUTS:       None
+**
+**  RETURNS:       MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngClearBerInterval(void)
+{
+  MV_STATUS rcode;
+
+  rcode = mvOnuGponMacBipInterruptIntervalSet(GPON_BIP_PERIOD_CNTR);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  /* Update S/W Database */
+  onuGponDbBerIntervalSet(GPON_BIP_PERIOD_CNTR);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngIsrNotExpected
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when a combination of state and event
+**               is not expected
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngIsrNotExpected(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_DEBUG_MODULE,
+             "DEBUG: (%s:%d) not expected, onuId(%d), msgId(%d), state(%d)\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet());
+#endif /* MV_GPON_DEBUG_PRINT */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngOverheadMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when upstream overhead message is
+**               received (message 01)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngOverheadMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U8     totalPlouBytes;
+  MV_U8     numOfGaurdBits;
+  MV_U8     preambleType1Cnt;
+  MV_U8     preambleType2Cnt;
+  MV_U8     preambleType3Cnt;
+  MV_U8     preambleType3Pattern;
+  MV_U8     delimiterByte_01;
+  MV_U8     delimiterByte_02;
+  MV_U8     delimiterByte_03;
+  MV_U32    delimiter;
+  MV_U8     overheadStatus;
+  MV_U32    preAssignDelay;
+  MV_U32    preAssignDelayTemp;
+  MV_U32    finalDelay;
+  MV_U32    equalizationDelay;
+  MV_U32    extendedPreambleSyncSize;
+  MV_U32    extendedPreambleOperSize;
+  MV_BOOL   extendedBurstOverride;
+  MV_BOOL   delimiterOverride;
+  MV_U32    randomRange[2];
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_OVERHEAD_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) OVERHEAD, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  if (g_overheadManualMode == MV_FALSE)
+  {
+    /* Support 1.244 G Rate */
+    totalPlouBytes = GPON_US_1244_PLOU_TOTAL_BYTES_SIZE;
+
+    /* guard handling */
+    /* ============== */
+    numOfGaurdBits = msgData[0];
+
+    /* preamble handling */
+    /* ================= */
+    preambleType1Cnt = msgData[1];         /* ploam message byte 4 */
+    preambleType2Cnt = msgData[2];         /* ploam message byte 5 */
+    preambleType3Pattern = msgData[3];     /* ploam message byte 6 */
+
+    preambleType1Cnt /= UINT8_NUM_OF_BITS; /* preamble type 1 count in bytes */
+    preambleType2Cnt /= UINT8_NUM_OF_BITS; /* preamble type 2 count in bytes */
+
+    extendedBurstOverride = onuGponDbExtendedBurstOverrideGet();
+
+    if (extendedBurstOverride == MV_TRUE)
+    {
+      extendedPreambleSyncSize = onuGponDbExtendedBurstSyncOverrideValueGet();
+      extendedPreambleOperSize = onuGponDbExtendedBurstOperOverrideValueGet();
+
+      onuGponDbExtPreambleSyncSet(extendedPreambleSyncSize);
+      onuGponDbExtPreambleOperSet(extendedPreambleOperSize);
+
+      preambleType3Cnt = ONU_TX_PREAMBLE_TYPE_03_DEF_PC;
+    }
+    else
+    {
+      /* preamble type 3 count in bytes */
+      /* Total Time = Guard Time + Preamble Time(Types 1, 2, 3) + Delimiter Time */
+      preambleType3Cnt = totalPlouBytes - GPON_TX_DELIMITER_DS - preambleType1Cnt -
+                         preambleType2Cnt - (numOfGaurdBits / UINT8_NUM_OF_BITS);
+
+      onuGponDbExtPreambleOperSet(preambleType3Cnt);
+      onuGponDbExtPreambleSyncSet(preambleType3Cnt);
+    }
+
+    /* update database */
+    onuGponDbPreambleSet(ONU_GPON_PREM_TYPE_01, (MV_U32)ONU_TX_PREAMBLE_TYPE_01_P, (MV_U32)preambleType1Cnt);
+    onuGponDbPreambleSet(ONU_GPON_PREM_TYPE_02, (MV_U32)ONU_TX_PREAMBLE_TYPE_02_P, (MV_U32)preambleType2Cnt);
+    onuGponDbPreambleSet(ONU_GPON_PREM_TYPE_03, (MV_U32)preambleType3Pattern, (MV_U32)preambleType3Cnt);
+
+    /* delimiter handling */
+    /* ================== */
+     delimiterOverride = onuGponDbDelimiterOverrideGet();
+
+    if (delimiterOverride == MV_FALSE)
+    {
+      delimiterByte_01 = msgData[4]; /* ploam message byte 7 */
+      delimiterByte_02 = msgData[5]; /* ploam message byte 8 */
+      delimiterByte_03 = msgData[6]; /* ploam message byte 9 */
+      delimiter = (((MV_U32)delimiterByte_01) << 16) | (((MV_U32)delimiterByte_02) << 8) |
+                  ((MV_U32)delimiterByte_03);
+
+      /* update database */
+      onuGponDbDelimiterSet (ONU_GPON_DELM_BYTE_01, (MV_U32)delimiterByte_01);
+      onuGponDbDelimiterSet (ONU_GPON_DELM_BYTE_02, (MV_U32)delimiterByte_02);
+      onuGponDbDelimiterSet (ONU_GPON_DELM_BYTE_03, (MV_U32)delimiterByte_03);
+      onuGponDbDelimiterSizeSet (GPON_TX_DELIMITER_DS);
+
+    }
+    else
+    {
+      delimiter = onuGponDbDelimiterOverrideValueGet();
+
+      /* update database with override value */
+      onuGponDbDelimiterSet (ONU_GPON_DELM_BYTE_01, (delimiter & 0xFF));
+      onuGponDbDelimiterSet (ONU_GPON_DELM_BYTE_02, (delimiter >> 8)& 0xFF);
+      onuGponDbDelimiterSet (ONU_GPON_DELM_BYTE_03, (delimiter >> 16)& 0xFF);
+
+    }
+
+    mvOnuGponMacTxDelimiterSet(delimiter, GPON_TX_DELIMITER_DS);
+
+    /* status handling */
+    /* =============== */
+    overheadStatus = msgData[7]; /* ploam message byte 10 */
+
+    if (overheadStatus & ONU_GPON_OVER_MSG_STATUS_XX)
+    {/* future use */
+    }
+    if (overheadStatus & ONU_GPON_OVER_MSG_STATUS_M)  /* Serial Number Mask Enabled*/
+    {
+      onuGponDbSerialNumberMaskEnableSet(MV_TRUE);
+    }
+    if (overheadStatus & ONU_GPON_OVER_MSG_STATUS_SS)
+    {/* future use */
+    }
+    if (overheadStatus & ONU_GPON_OVER_MSG_STATUS_PP)
+    {/* future use */
+    }
+
+    /* pre-assign equalization delay handling */
+    /* ====================================== */
+    if (overheadStatus & ONU_GPON_OVER_MSG_STATUS_E)
+    {
+      preAssignDelayTemp  = msgData[8] << UINT8_OFFSET; /* ploam message byte 11 */
+      preAssignDelayTemp |= msgData[9];                 /* ploam message byte 12 */
+
+      preAssignDelayTemp <<= UINT8_OFFSET;              /* align to bytes from words */
+
+      /* save pre-assign delay */
+      preAssignDelay = preAssignDelayTemp;
+
+      /* calc delay */
+      finalDelay        = M_ONU_GPON_RANG_MSG_FINAL_DELAY(preAssignDelayTemp);
+      equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(preAssignDelayTemp);
+
+      /* update asic */
+      get_random_bytes((void*)randomRange, sizeof(randomRange));
+
+      equalizationDelay += ((randomRange[0] & 0x7F) + (randomRange[1] & 0x3F) + 24) * 32;
+
+      rcode = mvOnuGponMacRxEqualizationDelaySet(equalizationDelay);
+      if (rcode != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) mvOnuGponMacRxEqualizationDelaySet equalizationDelay(%d)\n",
+                    __FILE_DESC__, __LINE__, equalizationDelay);
+        return;
+      }
+
+      /* update asic */
+      finalDelay |= (MV_U32)GPON_TX_FINAL_DELAY_FD;
+
+      rcode = mvOnuGponMacTxFinalDelaySet(finalDelay);
+      if (rcode != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) mvOnuGponMacTxFinalDelaySet finalDelay(%d)\n",
+                   __FILE_DESC__, __LINE__, finalDelay);
+        return;
+      }
+
+      /* update database */
+      onuGponDbEqualizationDelaySet(preAssignDelay);
+
+      g_overheadPreAssignDelayForPopup = preAssignDelay;
+    }
+  } /* g_overheadManualMode */
+
+  /* alarm handling */
+  /* ============== */
+
+  /* cancel deactivate onu alarm (if enabled) */
+  onuGponAlarmSet(ONU_GPON_ALARM_DACT, ONU_GPON_ALARM_OFF);
+
+  /* T01 timer handling */
+  /* ================== */
+
+  /* start onu gpon pon mng T01 timer */
+  onuPonTimerEnable(&(onuPonResourceTbl_s.onuGponT01_TimerId));
+
+  /* state handling */
+  /* ============== */
+
+  /* Before changing state check SN_Mask VALUE and serialNumberMaskDefaultStateFlag mode.
+  ** Add Support for HW and SW state machine */
+  rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_03_SERIAL_NUM);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngrUpdateState(3)\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngSerialNumberMaskMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when serial number mask message is
+**               received (message 02)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngSerialNumberMaskMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U8     numOfValidMaskBits;
+  MV_U8     numOfValidMaskBytes;
+  MV_U8     serialNumber[8];
+  MV_U8     maskIndex;
+  MV_U8     maskShift;
+  MV_U8     lastByteMask;
+  MV_U8     serialNumIndex = 7;
+  MV_U8     maskMsgOffset  = 8;
+
+  if (onuGponDbSerialNumberMaskEnableGet() == MV_TRUE)
+  {
+    /* Get Serial Number */
+    onuGponDbSerialNumGet(&(serialNumber[0]));
+
+#ifdef MV_GPON_DEBUG_PRINT
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+               "DEBUG: (%s:%d) SN_MASK, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x  ]\n",
+               __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+               msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+               msgData[5], msgData[6], msgData[7], msgData[8]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+    /* numOfValidMaskBits handling */
+    numOfValidMaskBits  = msgData[0];
+    numOfValidMaskBytes = (numOfValidMaskBits / UINT8_NUM_OF_BITS)+1;
+
+    /* Creating the last byte mask -if needed*/
+    maskIndex = ((maskMsgOffset-numOfValidMaskBytes)+1);
+    if (numOfValidMaskBits <= UINT8_NUM_OF_BITS)
+    {
+      maskShift = numOfValidMaskBits;
+    }
+    else
+    {
+      maskShift = (numOfValidMaskBits % UINT8_NUM_OF_BITS);
+    }
+    if (maskShift != 0)
+    {
+      lastByteMask= ((1 << (maskShift))-1);
+      msgData[maskIndex] &= lastByteMask;
+      serialNumber[maskIndex-1] &= lastByteMask;
+    }
+
+    /* Compering the active bytes in the Serial number mask to ONU's serial number*/
+    for (maskIndex=0;maskIndex < numOfValidMaskBytes;maskIndex++)
+    {
+      if (serialNumber[serialNumIndex-maskIndex] != msgData[maskMsgOffset-maskIndex])
+      {
+        /* updating serial number flag to - no match */
+        onuGponDbSerialNumberMaskMatchSet(MV_FALSE);
+
+        /* state handling */
+        rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_03_SERIAL_NUM);
+        if (rcode != MV_OK)
+        {
+          mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                     "ERROR: (%s:%d) onuGponPonMngrUpdateState(3)\n", __FILE_DESC__, __LINE__);
+          return;
+        }
+        return;
+      }
+    }
+
+    /* updating serial number flag to - match */
+    onuGponDbSerialNumberMaskMatchSet(MV_TRUE);
+
+    /* state handling */
+    rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_03_SERIAL_NUM);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) onuGponPonMngrUpdateState(3)\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngOnuIdMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when onu Id message is received
+**               (message 03)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngOnuIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U8     serialNum[8];
+  MV_U32    msgOnuId;
+  MV_U32    equalizationDelay;
+  MV_U32    equalizationDelayTemp;
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_ONU_ID_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) ASSIGN ONU ID, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* serial number handling */
+  /* ====================== */
+
+  /* get onu serial number */
+  onuGponDbSerialNumGet(&(serialNum[0]));
+
+  /* match onu serial number with message serial number */
+  if ((msgData[1] == serialNum[0]) &&
+      (msgData[2] == serialNum[1]) &&
+      (msgData[3] == serialNum[2]) &&
+      (msgData[4] == serialNum[3]) &&
+      (msgData[5] == serialNum[4]) &&
+      (msgData[6] == serialNum[5]) &&
+      (msgData[7] == serialNum[6]) &&
+      (msgData[8] == serialNum[7]))
+  {
+    /* extract onuId from the message */
+    if (onuGponDbOnuIdOverrideGet() == MV_FALSE)
+    {
+      msgOnuId = msgData[0];
+    }
+    else
+    {
+      msgOnuId = onuGponDbOnuIdOverrideValueGet();
+    }
+
+    /* update asic */
+    rcode = onuGponSrvcOnuIdUpdate(msgOnuId, MV_TRUE);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) onuGponSrvcOnuIdUpdate\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+
+    /* update database */
+    onuGponDbOnuIdSet(msgOnuId);
+
+    /* set Default allocId according to the onuId */
+    rcode = onuGponAllocIdAssign(msgOnuId, 0);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) onuGponAllocIdAssign\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+
+    onuGponAllocIdMacAdd(msgOnuId, PON_ONU_DEFAULT_ALLOC_TCONT);
+
+    /* Set delay received from OLT */
+    equalizationDelayTemp = onuGponDbEqualizationDelayGet();
+    equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(equalizationDelayTemp);
+    rcode = mvOnuGponMacRxEqualizationDelaySet(equalizationDelay);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) mvOnuGponMacRxEqualizationDelaySet equalizationDelay(%d)\n",
+                  __FILE_DESC__, __LINE__, equalizationDelay);
+      return;
+    }
+
+    /* state handling */
+    /* ============== */
+    rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_04_RANGING);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) onuGponPonMngrUpdateState(4)\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+  }
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngRangeTimeMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when ranging time message is received
+**               (message 04)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngRangeTimeMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U8     delay[4];
+  MV_U32    msgDelay;
+  MV_U32    msgDelayTemp;
+  MV_U32    equalizationDelay;
+  MV_U32    finalDelay;
+  MV_U32    currentDelay;
+  MV_U32    changeDelay;
+  MV_U32    currFinalDelay;
+  MV_BOOL   equalizationDelayOverride;
+  LINKSTATUSFUNC linkStatusCallback;
+  MV_U32    onuState = onuGponDbOnuStateGet();
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_RNG_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) RANGE TIME, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuState,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  equalizationDelayOverride = onuGponDbEqualizationDelayOverrideGet();
+
+  if ((equalizationDelayOverride == MV_FALSE) || (onuState == ONU_GPON_05_OPERATION))
+  {
+    /* equalization delay handling */
+    /* =========================== */
+    delay[0] = msgData[1]; /* MSB */
+    delay[1] = msgData[2];
+    delay[2] = msgData[3];
+    delay[3] = msgData[4]; /* LSB */
+
+    msgDelayTemp  = delay[3];
+    msgDelayTemp |= delay[2] << 8;
+    msgDelayTemp |= delay[1] << 16;
+    msgDelayTemp |= delay[0] << 24;
+
+    msgDelay = msgDelayTemp;
+  }
+  else
+  {
+    msgDelay = onuGponDbEqualizationDelayOverrideValueGet();
+  }
+
+  /* calc delay */
+  finalDelay        = M_ONU_GPON_RANG_MSG_FINAL_DELAY(msgDelay);
+  equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(msgDelay);
+
+
+  /* sync state */
+  /* ========== */
+  if (onuState != ONU_GPON_05_OPERATION)
+  {
+    /* stop onu gpon pon mng T01 timer */
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponT01_TimerId));
+
+    /* update asic */
+    rcode = mvOnuGponMacRxEqualizationDelaySet(equalizationDelay);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) mvOnuGponMacRxEqualizationDelaySet equalizationDelay(%d)\n",
+                 __FILE_DESC__, __LINE__, equalizationDelay);
+      return;
+    }
+
+    /* update asic */
+    finalDelay += (MV_U32)GPON_TX_FINAL_DELAY_FD;
+
+    rcode = mvOnuGponMacTxFinalDelaySet(finalDelay);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) mvOnuGponMacTxFinalDelaySet finalDelay(%d)\n",
+                 __FILE_DESC__, __LINE__, finalDelay);
+      return;
+    }
+
+    /* update database */
+    onuGponDbEqualizationDelaySet(msgDelay);
+
+    /* alarm handling */
+    /* ============== */
+    onuGponAlarmSet(ONU_GPON_ALARM_SUF, ONU_GPON_ALARM_OFF);
+
+    /* state handling */
+    /* ============== */
+    rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_05_OPERATION);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) onuGponPonMngrUpdateState(5)\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+
+	onuPonTimerEnable(&onuPonResourceTbl_s.onuPonSwFIFOTimerId);
+
+#ifndef PON_FPGA
+    onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_ON);
+#endif /* PON_FPGA */
+
+    mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "======================\n");
+    mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "== Upstream sync On ==\n");
+    mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "======================\n");
+
+	/* Call link status callback function */
+    linkStatusCallback = onuGponDbLinkStatusCallbackGet();
+    if (linkStatusCallback != NULL)
+    {
+      linkStatusCallback(MV_TRUE);
+    }
+  }
+  /* operational state */
+  /* ================= */
+  else
+  {
+    /* get current delay */
+    currentDelay = onuGponDbEqualizationDelayGet();
+
+    /* Reduce Equlization delay */
+    if (currentDelay > msgDelay)
+    {
+      changeDelay = currentDelay - msgDelay;
+      mvOnuGponMacTxFinalDelayGet(&currFinalDelay);
+
+      /* Check if can change the TX Final Delay only */
+      if (changeDelay <= currFinalDelay)
+      {
+        finalDelay = currFinalDelay - changeDelay;
+      }
+      else
+      {
+#ifdef MV_GPON_DEBUG_PRINT
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) Change Range delay while O5 - Update EqD\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+        /* calc delay */
+        finalDelay        = M_ONU_GPON_RANG_MSG_FINAL_DELAY(msgDelay) + (MV_U32)GPON_TX_FINAL_DELAY_FD;
+        equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(msgDelay);
+        /* update asic */
+        rcode = mvOnuGponMacRxEqualizationDelaySet(equalizationDelay);
+        if (rcode != MV_OK)
+        {
+          mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                     "ERROR: (%s:%d) mvOnuGponMacRxEqualizationDelaySet equalizationDelay(%d)\n",
+                     __FILE_DESC__, __LINE__, equalizationDelay);
+          return;
+        }
+      }
+
+      rcode = mvOnuGponMacTxFinalDelaySet(finalDelay);
+      if (rcode != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) mvOnuGponMacTxFinalDelaySet finalDelay(%d)\n",
+                   __FILE_DESC__, __LINE__, finalDelay);
+        return;
+      }
+      /* update database */
+      onuGponDbEqualizationDelaySet(msgDelay);
+    }
+    else if (currentDelay < msgDelay)
+    {
+      changeDelay = msgDelay - currentDelay;
+      mvOnuGponMacTxFinalDelayGet(&currFinalDelay);
+
+      /* Check if can change the TX Final Delay only */
+      if (changeDelay + currFinalDelay > GPON_TX_FINAL_DELAY_MAX)
+      {
+        finalDelay = currFinalDelay + changeDelay;
+      }
+      else
+      {
+#ifdef MV_GPON_DEBUG_PRINT
+        mvPonPrint(PON_PRINT_DEBUG, PON_SM_DEBUG_MODULE,
+                   "DEBUG: (%s:%d) Change Range delay while O5 - Update EqD\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+        /* calc delay */
+        finalDelay        = M_ONU_GPON_RANG_MSG_FINAL_DELAY(msgDelay) + (MV_U32)GPON_TX_FINAL_DELAY_FD;
+        equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(msgDelay);
+
+        /* update asic */
+        rcode = mvOnuGponMacRxEqualizationDelaySet(equalizationDelay);
+        if (rcode != MV_OK)
+        {
+          mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                     "ERROR: (%s:%d) mvOnuGponMacRxEqualizationDelaySet equalizationDelay(%d)\n",
+                     __FILE_DESC__, __LINE__, equalizationDelay);
+          return;
+        }
+      }
+
+      rcode = mvOnuGponMacTxFinalDelaySet(finalDelay);
+      if (rcode != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) mvOnuGponMacTxFinalDelaySet finalDelay(%d)\n",
+                   __FILE_DESC__, __LINE__, finalDelay);
+        return;
+      }
+      /* update database */
+      onuGponDbEqualizationDelaySet(msgDelay);
+    }
+  }
+
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngDactOnuIdMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when deactivate onu message is received
+**               (message 05)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngDactOnuIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  LINKSTATUSFUNC linkStatusCallback;
+
+  MV_U32    onuState = onuGponDbOnuStateGet();
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_DACT_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) DEACTIVATE, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuState,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* timer T01 is running */
+  if ((onuState >= ONU_GPON_02_STANDBY) &&
+      (onuState <= ONU_GPON_04_RANGING))
+  {
+    /* stop onu gpon pon mng T01 timer */
+    onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponT01_TimerId));
+  }
+
+  /* clear onu information */
+  /* ===================== */
+  rcode = onuGponPonMngClearOnuInfo();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuInfo\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
+  /* alarm handling */
+  /* ============== */
+  onuGponAlarmSet(ONU_GPON_ALARM_DACT, ONU_GPON_ALARM_ON);
+
+  /* state handling */
+  /* ============== */
+  rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_02_STANDBY);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngrUpdateState(2)\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
+  if (onuState == ONU_GPON_05_OPERATION)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "=======================\n");
+    mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "== Upstream sync Off ==\n");
+    mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "=======================\n");
+
+    /* Send Status Notification to upper layer */
+    onuGponSrvcStatusNotify(GPON_ONU_STATUS_NOT_RANGED);
+
+	/* Call link status callback function */
+    linkStatusCallback = onuGponDbLinkStatusCallbackGet();
+    if (linkStatusCallback != NULL)
+    {
+      linkStatusCallback(MV_FALSE);
+    }
+  }
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngDisSnMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when disable onu message is received
+**               (message 06)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngDisSnMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+	MV_STATUS rcode;
+	MV_U32    onuState = onuGponDbOnuStateGet();
+	MV_U32    disableStatus;
+	MV_U8     msgSerialNumber[8];
+	MV_U8     onuSerialNumber[8];
+	MV_BOOL   isSnMatch;
+
+#ifdef MV_GPON_DEBUG_PRINT
+	mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+			   "DEBUG: (%s:%d) DISABLE, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+			   __FILE_DESC__, __LINE__, onuId, msgId, onuState,
+			   msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+			   msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+	disableStatus = msgData[0];
+	memcpy(msgSerialNumber, &(msgData[1]), 8);
+	onuGponDbSerialNumGet(onuSerialNumber);
+	if (memcmp(msgSerialNumber,onuSerialNumber,8) == 0)
+		isSnMatch = MV_TRUE;
+	else
+		isSnMatch = MV_FALSE;
+
+	/* Disable */
+	if ((disableStatus == GPON_ONU_DISABLE) && (isSnMatch == MV_TRUE) &&
+		(onuState != ONU_GPON_07_EMERGANCY_STOP)) {
+
+		/* clear onu information */
+		/* ===================== */
+		rcode = onuGponPonMngClearOnuInfo();
+		if (rcode != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+					   "ERROR: (%s:%d) DISABLE: onuGponPonMngClearOnuInfo\n", __FILE_DESC__, __LINE__);
+			return;
+		}
+
+		/* clear GEM ports */
+		/* =============== */
+		rcode = onuGponApiGemClearAll(onuGponDbGemRestoreGet());
+		if (rcode != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+					   "ERROR: (%s:%d) DISABLE: onuGponApiGemClearAll\n", __FILE_DESC__, __LINE__);
+			return;
+		}
+
+		/* alarm handling */
+		/* ============== */
+		onuGponAlarmSet(ONU_GPON_ALARM_DIS, ONU_GPON_ALARM_ON);
+
+		/* state handling */
+		/* ============== */
+		rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_07_EMERGANCY_STOP);
+		if (rcode != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+					   "ERROR: (%s:%d) DISABLE: onuGponPonMngrUpdateState(7)\n", __FILE_DESC__, __LINE__);
+			return;
+		}
+
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "==================\n");
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "== ONT DISABLED ==\n");
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "==================\n");
+
+		if (g_onuGponDisableFunc != NULL)
+			g_onuGponDisableFunc(MV_TRUE);
+
+		/* Send Disable Notification to upper layer */
+		onuGponSrvcDisableMsgNotify( MV_TRUE );
+
+		/* If was ranged then now ont is not ranged - send status notification */
+		if (onuState == ONU_GPON_05_OPERATION)
+			onuGponSrvcStatusNotify(GPON_ONU_STATUS_NOT_RANGED);
+
+	/* Enable */
+	} else if (((disableStatus == GPON_ONU_ENABLE_ALL) ||
+			  ((disableStatus == GPON_ONU_ENABLE_ONU) && (isSnMatch == MV_TRUE))) &&
+			 (onuState == ONU_GPON_07_EMERGANCY_STOP)) {
+
+		/* alarm handling */
+		/* ============== */
+		onuGponAlarmSet(ONU_GPON_ALARM_DIS, ONU_GPON_ALARM_OFF);
+
+		/* state handling */
+		/* ============== */
+		rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_02_STANDBY);
+		if (rcode != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+					   "ERROR: (%s:%d) DISABLE: onuGponPonMngrUpdateState(2)\n", __FILE_DESC__, __LINE__);
+			return;
+		}
+
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "=================\n");
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "== ONT ENABLED ==\n");
+		mvPonPrint(PON_PRINT_INFO, PON_SM_MODULE, "=================\n");
+
+		if (g_onuGponDisableFunc != NULL)
+			g_onuGponDisableFunc(MV_FALSE);
+
+		/* Send Disable Notification to upper layer */
+		onuGponSrvcDisableMsgNotify( MV_FALSE );
+
+		/* Restore saved GEM ports */
+		if (onuGponDbGemRestoreGet() == MV_TRUE) {
+			rcode = onuGponApiGemRestoreAll();
+			if (rcode != MV_OK) {
+				mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+						   "ERROR: (%s:%d) DISABLE: onuGponApiGemRestoreAll\n", __FILE_DESC__, __LINE__);
+				return;
+			}
+		}
+
+	}
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngCfgVpVcMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when config Vp/Vc message is received
+**               (message 07)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngCfgVpVcMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_DEBUG_MODULE,
+             "DEBUG: (%s:%d) config Vp/Vc, onuId(%d), msgId(%d), state(%d)\n",
+             __FILE_DESC__, __LINE__, onuId, msgId,  onuGponDbOnuStateGet());
+
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_DEBUG_MODULE,
+             "DEBUG: (%s:%d) config Vp/Vc, function not supported\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngEncrptPortIdMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when encrpt port Id message is received
+**               (message 08)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngEncrptPortIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS status;
+  MV_BOOL   encrypted;
+  MV_BOOL   gem;
+  MV_U32    portId;
+#ifdef MV_GPON_DEBUG_PRINT
+  MV_U8     *text[] = {"NOT Encrypted","Encrypted"};
+#endif
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_ENC_PORT_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) ENCRYPTED PORT, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* Send Acknowledge PLOAM */
+  status = mvOnuGponMacAcknowledgeMessageSend(onuId, msgId, msgData);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacAcknowledgeMessageSend msgId(%d)\n",
+               __FILE_DESC__, __LINE__, msgId);
+    return;
+  }
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "[US PLOAM] ACKNOWLEDGE, onuId(%d), msgId(%d), msg[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",
+             onuId, msgId,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  portId    = ((MV_U32)(msgData[1]) << 4) +
+              ((MV_U32)(msgData[2]) >> 4);
+  encrypted = (msgData[0] & 0x01) ? MV_TRUE : MV_FALSE;
+  gem       = (msgData[0] & 0x02) ? MV_TRUE : MV_FALSE;
+  if (gem != MV_TRUE)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) ONT Does not support ATM\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
+  /* to start AES on a port Id, it should be valid */
+  if (encrypted == MV_TRUE)
+  {
+    if (onuGponDbGemPortValidGet(portId) != MV_TRUE)
+    {
+      /*Gem port was not yet configured, so avoid updating the HW and "just" mark the SW*/
+      onuGponDbGemPortAesSet(portId,encrypted);
+      return;
+    }
+  }
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_AES_MODULE,
+             "DEBUG: (%s:%d) SM AES: PORT ID [%d] - %s Encrypted\n",
+             __FILE_DESC__, __LINE__, portId, text[encrypted]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  mvOnuGponMacAesPortIdSet(portId,encrypted);
+  onuGponDbGemPortAesSet(portId,encrypted);
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngReqPassMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when request password message is received
+**               (message 09)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngReqPassMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_U8 password[10];
+  MV_U8 srcOnuId;
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_PASS_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) PASSWORD REQUEST, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  onuGponDbPasswordGet(password);
+  srcOnuId = onuGponDbOnuIdGet();
+  /* Send Upstream Password message */
+  mvOnuGponMacPasswordMessageSend(srcOnuId, password, 3);
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "[US PLOAM] PASSWORD, onuId(%d), msgId(%d), msg[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",
+             srcOnuId, msgId,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngAssignAllocIdMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when assign allocId password message
+**               is received (message 10)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngAssignAllocIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS status;
+  MV_U32    allocId;
+  MV_U32    assignType;
+  MV_BOOL   curAllocStatus;
+  MV_BOOL   newAllocStatus;
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_ALLOC_ID_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) ASSIGN ALLOC ID, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+
+  allocId = (((MV_U32)(msgData[0])) << 4) + (((MV_U32)(msgData[1])) >> 4);
+  assignType = msgData[2];
+
+  switch (assignType)
+  {
+    case ONU_GPON_ATM_PAYLOAD:
+#ifdef MV_GPON_DEBUG_PRINT
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_ALLOC_MODULE,
+                 "DEBUG: (%s:%d) Alloc Id Type ATM - Not supported, allocId (%d)\n", __FILE_DESC__, __LINE__, allocId);
+#endif /* MV_GPON_DEBUG_PRINT */
+      return;
+      break;
+    case ONU_GPON_GEM_PAYLOAD:
+#ifdef MV_GPON_DEBUG_PRINT
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_ALLOC_MODULE,
+                 "DEBUG: (%s:%d) Alloc Id Type GEM, allocId (%d)\n", __FILE_DESC__, __LINE__, allocId);
+#endif /* MV_GPON_DEBUG_PRINT */
+      newAllocStatus = MV_TRUE;
+      break;
+    case ONU_GPON_DBA_PAYLOAD:
+#ifdef MV_GPON_DEBUG_PRINT
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_ALLOC_MODULE,
+                 "DEBUG: (%s:%d) Alloc Id Type DBA - Not supported, allocId (%d)\n", __FILE_DESC__, __LINE__, allocId);
+#endif /* MV_GPON_DEBUG_PRINT */
+      return;
+      break;
+    case ONU_GPON_DEALLOCATE:
+#ifdef MV_GPON_DEBUG_PRINT
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_ALLOC_MODULE,
+                 "DEBUG: (%s:%d) Alloc Id Type DEALLOCATE, allocId (%d)\n", __FILE_DESC__, __LINE__, allocId);
+#endif /* MV_GPON_DEBUG_PRINT */
+      newAllocStatus = MV_FALSE;
+      break;
+    default:
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_ALLOC_MODULE,
+                 "DEBUG: (%s:%d) Alloc Id Type - Not supported, allocId (%d) type(%d)\n", __FILE_DESC__, __LINE__, allocId, assignType);
+      return;
+  }
+  /* Scan the alloc-Id table and check if the Alloc-Id has been defined and is valid */
+  curAllocStatus = onuGponDbBwAllocExist(allocId);
+  if (curAllocStatus == newAllocStatus)
+  {
+#ifdef MV_GPON_DEBUG_PRINT
+    if (assignType == ONU_GPON_GEM_PAYLOAD)
+    {
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_ALLOC_MODULE,
+                 "DEBUG: (%s:%d) Alloc Id Type - exist, allocId (%d)\n", __FILE_DESC__, __LINE__, allocId);
+    }
+    else if (assignType == ONU_GPON_DEALLOCATE)
+    {
+      mvPonPrint(PON_PRINT_DEBUG, PON_SM_ALLOC_MODULE,
+                 "DEBUG: (%s:%d) Alloc Id Type - removed, allocId (%d)\n", __FILE_DESC__, __LINE__, allocId);
+    }
+#endif /* MV_GPON_DEBUG_PRINT */
+  }
+  else
+  {
+    /* Assign new Alloc Id */
+    if (newAllocStatus == MV_TRUE)
+    {
+      status = onuGponAllocIdAssign(allocId, 1);
+      if (status != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) onuGponAllocIdAssign onuId(%d), allocId(%d)\n", __FILE_DESC__, __LINE__, onuId, allocId);
+      }
+    }
+    /* De-Assign exist Alloc Id */
+    else
+    {
+      status = onuGponAllocIdDeAssign(allocId);
+      if (status != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) onuGponAllocIdDeAssign onuId(%d), allocId(%d)\n", __FILE_DESC__, __LINE__, onuId, allocId);
+      }
+    }
+  }
+
+  /* Send Acknowledge PLOAM */
+  status = mvOnuGponMacAcknowledgeMessageSend(onuId, msgId, msgData);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacAcknowledgeMessageSend onuId(%d), allocId(%d)\n", __FILE_DESC__, __LINE__, onuId, allocId);
+    return;
+  }
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "[US PLOAM] ACKNOWLEDGE, onuId(%d), msgId(%d), msg[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",
+             onuId, msgId,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngNoMsgMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when downstream no message is received
+**               (message 11)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngNoMsgMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) no message, onuId(%d), msgId(%d), state(%d)\n",
+             __FILE_DESC__, __LINE__, onuId, msgId,  onuGponDbOnuStateGet());
+#endif /* MV_GPON_DEBUG_PRINT */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngPopupMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when popup message is received
+**               (message 12)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngPopupMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U32    equalizationDelay;
+  MV_U32    equalizationDelayTemp;
+
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) POPUP, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* stop onu gpon pon mng T02 timer */
+  onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponT02_TimerId));
+
+  if (onuId == ONU_GPON_BROADCAST_ONU_ID) /* Broadcast ONU-ID */
+  {
+    /* T01 timer handling */
+    /* ================== */
+    /* start onu gpon pon mng T01 timer */
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuGponT01_TimerId));
+
+    /* state handling */
+    mvOnuGponMacMessageCleanSwFifo();
+
+    /* update pre-assign delay before re-range */
+    equalizationDelayTemp = g_overheadPreAssignDelayForPopup;
+    equalizationDelay = M_ONU_GPON_RANG_MSG_EQUAL_DELAY(equalizationDelayTemp);
+    rcode = mvOnuGponMacRxEqualizationDelaySet(equalizationDelay);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) mvOnuGponMacRxEqualizationDelaySet equalizationDelay(%d)\n",
+                  __FILE_DESC__, __LINE__, equalizationDelay);
+      return;
+    }
+
+    /* state handling */
+    /* ============== */
+    rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_04_RANGING);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) POPUP: onuGponPonMngrUpdateState(4)\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+  }
+  else  /* ONU ID is directed */
+  {
+    /* state handling */
+    /* ============== */
+    rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_05_OPERATION);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) POPUP: onuGponPonMngrUpdateState(5)\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+
+#ifdef MV_GPON_DEBUG_PRINT
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "========================\n");
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "== Recover from POPUP ==\n");
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "========================\n");
+#endif /* MV_GPON_DEBUG_PRINT */
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngReqKeyMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when request key message is received
+**               (message 13)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngReqKeyMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS     rcode;
+  MV_U8         key[16];
+  MV_U32        i;
+  static MV_U8  keyIndex;
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_REQ_KEY_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) REQUEST KEY, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  keyIndex++;
+
+  /* Generate new AES Key */
+  onuGponSrvcAesKeyGenerate(key);
+
+  /* Write it to asic */
+  rcode = mvOnuGponMacAesKeyShadowWrite(key);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacAesKeyShadowWrite\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
+  /* Send the Key 3 times */
+  for (i = 0 ; i < 3 ; i++)
+  {
+    rcode  = mvOnuGponMacEncryptionKeyMessageSend(onuId, keyIndex,0, key);
+    rcode |= mvOnuGponMacEncryptionKeyMessageSend(onuId, keyIndex,1, &(key[8]));
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) mvOnuGponMacEncryptionKeyMessageSend\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+  }
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_AES_MODULE,
+             "DEBUG: (%s:%d) SM AES: INDEX [%u] KEY [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",
+             __FILE_DESC__, __LINE__, keyIndex,
+             key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7],
+             key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                             &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+    if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngCfgPortIdMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when config portId message is received
+**               (message 14)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngCfgPortIdMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS  status;
+  MV_BOOL    active;
+  MV_U32     portId;
+  MV_U32     currentOmcc;
+  MV_BOOL    omccValid;
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_CFG_PORT_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) CONFIG PORT ID, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* Get Enable */
+  active = (msgData[0] == 1)?MV_TRUE:MV_FALSE;  /* 0x00 - Activate, 0x01 - Deactivate */
+
+  if (onuGponDbOmccPortOverrideGet() == MV_FALSE)
+  {
+    /* Get Port ID */
+    /* PLOAM Octet 4 (msgData[1]) - Port-ID[11:4] */
+    /* 4 MSB bits of PLOAM Octet 5 (msgData[2]) - Port-ID[3:0] */
+    portId = (msgData[1] << 4) + (msgData[2] >> 4);
+  }
+  else
+  {
+    portId = onuGponDbOmccPortOverrideValueGet();
+  }
+
+
+  /* Send Acknowledge PLOAM */
+  status = mvOnuGponMacAcknowledgeMessageSend(onuId, msgId, msgData);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacAcknowledgeMessageSend, msgId(%d) , active(%d)\n",
+               __FILE_DESC__, __LINE__, msgId, active);
+  }
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "[US PLOAM] ACKNOWLEDGE, onuId(%d), msgId(%d), msg[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",
+             onuId, msgId,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+
+
+  /* Get OMCC State */
+  omccValid = onuGponDbOmccValidGet();
+  if (omccValid == active)
+  {
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_OMCC_MODULE,
+               "DEBUG: (%s:%d) Configure Port Id - Activness not changed, portId(%d), active(%d), omccValid(%d)\n",
+               __FILE_DESC__, __LINE__, portId, active, omccValid);
+    return;
+  }
+
+  /* Update the new OMCC State */
+  onuGponDbOmccValidSet(active);
+
+  /*get current */
+  currentOmcc = onuGponDbOmccPortGet();
+  /*when system is configured to keep gem port configuration
+   BUT onu id changed, remove ALL gem port configuration */
+  if ((currentOmcc != portId)&&
+      (currentOmcc != GPON_ONU_ID_ONU_ID_DEF) &&
+      (onuGponDbGemResetGet() == MV_FALSE)){
+       onuGponDbGemPortClearAll();
+       mvOnuGponMacGemInit();
+  }
+  /*configure the omcc port when value changed */
+  if (currentOmcc != portId) {
+      /* Set OMCC Port Id */
+      status = onuGponApiGemOmccIdConfig(portId, active);
+      if (status != MV_OK)
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                   "ERROR: (%s:%d) onuGponApiGemOmccIdConfig portId(%d) active(%d)\n",
+                   __FILE_DESC__, __LINE__, portId, active);
+      }
+     onuGponDbOmccPortSet(portId);
+  }
+
+  /* Send Status Notification to upper layer */
+  onuGponSrvcStatusNotify(GPON_ONU_STATUS_RANGED);
+
+  if (active == MV_TRUE)
+  {
+#ifdef MV_GPON_DEBUG_PRINT
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_OMCC_MODULE,
+               "DEBUG: (%s:%d) GPON SM: OMCC ACTIVE: GEM Port[%d]\n", __FILE_DESC__, __LINE__, portId);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+#ifndef PON_FPGA
+    /* Upstream ON - Turn LED On */
+    onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_ON);
+#endif /* PON_FPGA */
+  }
+  else
+  {
+#ifdef MV_GPON_DEBUG_PRINT
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_OMCC_MODULE,
+               "DEBUG: (%s:%d) GPON SM: OMCC DEACTIVE\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+#ifndef PON_FPGA
+    /* Upstream OFF - Blink the LED (Downstream only) */
+    onuPonLedHandler(ONU_PON_SYNC_LED, ACTIVE_LED_BLINK_SLOW);
+#endif /* PON_FPGA */
+  }
+#ifdef MV_GPON_PERFORMANCE_CHECK
+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                             &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+    if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngPhyEquErrMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when physical equipt error message is
+**               received (message 15)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngPhyEquErrMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) PEE, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* Stop PEE Timer */
+  onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponPeeTimerId));
+
+  /* Start PEE Timer */
+  onuPonTimerEnable(&(onuPonResourceTbl_s.onuGponPeeTimerId));
+
+  /* Generate PEE Alarm */
+  onuGponAlarmSet(ONU_GPON_ALARM_PEE, ONU_GPON_ALARM_ON);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngChgPwrLvlMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when change power level message is
+**               received (message 16)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngChgPwrLvlMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_DEBUG_MODULE,
+             "DEBUG: (%s:%d) change power level, onuId(%d), msgId(%d), state(%d)\n",
+             __FILE_DESC__, __LINE__, onuId, msgId,  onuGponDbOnuStateGet());
+
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_DEBUG_MODULE,
+             "DEBUG: (%s:%d) change power level, function not supported\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngPstMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when PST message is received
+**               (message 17)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngPstMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_DEBUG_MODULE,
+             "DEBUG: (%s:%d) pst, onuId(%d), msgId(%d), state(%d)\n",
+             __FILE_DESC__, __LINE__, onuId, msgId,  onuGponDbOnuStateGet());
+
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_DEBUG_MODULE,
+             "DEBUG: (%s:%d) pst, function not supported\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngBerIntervalMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when ber interval message is received
+**               (message 18)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngBerIntervalMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS status;
+  MV_U32    berInterval;
+  MV_U32    currentBerInterval;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) BER INTERVAL, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* BER Interval in Downstream Superframes */
+  berInterval = (MV_U32)(msgData[0] << 24) + (MV_U32)(msgData[1] << 16) +
+                (MV_U32)(msgData[2] << 8) + (MV_U32)msgData[3];
+
+  /* Send Acknowledge PLOAM */
+  status = mvOnuGponMacAcknowledgeMessageSend(onuId, msgId, msgData);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) BER: mvOnuGponMacAcknowledgeMessageSend onuId(%d), msgId(%d)\n",
+               __FILE_DESC__, __LINE__, onuId, msgId);
+    return;
+  }
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "[US PLOAM] ACKNOWLEDGE, onuId(%d), msgId(%d), msg[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",
+             onuId, msgId,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+
+  currentBerInterval = onuGponDbBerIntervalGet();
+  if (currentBerInterval == berInterval)
+  {
+    return;
+  }
+
+  status = mvOnuGponMacBipInterruptIntervalSet(berInterval);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) BER: mvOnuGponMacBipInterruptIntervalSet onuId(%d), msgId(%d), interval(%d)\n",
+               __FILE_DESC__, __LINE__, onuId, msgId, berInterval);
+    return;
+  }
+
+  /* Update S/W Database */
+  onuGponDbBerIntervalSet(berInterval);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngKeySwitchTimeMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when key switch time message is received
+**               (message 19)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngKeySwitchTimeMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS status;
+  MV_U32    time;
+  MV_U8     realOnuId;
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_KEY_SWITCH_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "DEBUG: (%s:%d) KEY SWITCHING TIME, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuGponDbOnuStateGet(),
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  time = (MV_U32)(msgData[3]) + (((MV_U32)(msgData[2])) << 8) + (((MV_U32)(msgData[1])) << 16) +
+         (((MV_U32)((msgData[0]) & 0x3F)) << 24);
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_AES_MODULE,
+             "DEBUG: (%s:%d) SM AES: SWITCHING TIME [0x%x (%u)]\n",
+             __FILE_DESC__, __LINE__, time, time);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  realOnuId = (MV_U8)onuGponDbOnuIdGet();
+
+  /* Send Acknowledge PLOAM */
+  status = mvOnuGponMacAcknowledgeMessageSend(realOnuId, msgId, msgData);
+  if (status != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacAcknowledgeMessageSend\n", __FILE_DESC__, __LINE__);
+  }
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "[US PLOAM] ACKNOWLEDGE, onuId(%d), msgId(%d), msg[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]\n",
+             realOnuId, msgId,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+    asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                             &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+    if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngExtBurstMsg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when ext burst message is received
+**               (message 20)
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngExtBurstMsg(MV_U8 onuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS  rcode;
+  MV_U32     onuState = onuGponDbOnuStateGet();
+  MV_U8      preambleCnt_03Oper;
+  MV_U8      preambleCnt_03Sync;
+  MV_U8      preambleDelay_03Oper = 0;
+  MV_U8      preambleDelay_03Sync = 0;
+  MV_U32     currentExtPreambleSync;
+  MV_U32     currentExtPreambleOper;
+  MV_BOOL    burstOverride;
+  MV_BOOL    burstDelayAdd;
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  S_GponPerformanceCheckNode *tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[PON_EXT_BURST_PLOAM_PERFORMANCE]);
+
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStart[tmpPmCheckNode->uSecCntIdx]), 0);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_STATE_MODULE,
+             "INFO: (%s:%d) EXT BURST, onuId(%d), msgId(%d), state(%d) msg[0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+             __FILE_DESC__, __LINE__, onuId, msgId, onuState,
+             msgData[0], msgData[1], msgData[2], msgData[3], msgData[4],
+             msgData[5], msgData[6], msgData[7], msgData[8], msgData[9]);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  burstDelayAdd = onuGponDbExtendedBurstDelayAddGet();
+
+  if (burstDelayAdd == MV_TRUE)
+  {
+      preambleDelay_03Oper = onuGponDbExtendedBurstOperDelayValueGet();
+      preambleDelay_03Sync = onuGponDbExtendedBurstSyncDelayValueGet();
+  }
+
+  currentExtPreambleSync = onuGponDbExtPreambleSyncGet();
+  currentExtPreambleOper = onuGponDbExtPreambleOperGet();
+  if (g_overheadManualMode == MV_TRUE)
+  {
+    return;
+  }
+  burstOverride = onuGponDbExtendedBurstOverrideGet();
+
+  if (burstOverride == MV_TRUE)
+  {
+    preambleCnt_03Sync = onuGponDbExtendedBurstSyncOverrideValueGet();
+    preambleCnt_03Oper = onuGponDbExtendedBurstOperOverrideValueGet();
+
+    onuGponDbExtPreambleSyncSet(preambleCnt_03Sync);
+    onuGponDbExtPreambleOperSet(preambleCnt_03Oper);
+  }
+  else
+  {
+    /* preamble handling */
+    /* ================= */
+    preambleCnt_03Sync = msgData[0] + preambleDelay_03Sync;
+    preambleCnt_03Oper = msgData[1] + preambleDelay_03Oper;
+
+    if ((currentExtPreambleSync == preambleCnt_03Sync) &&
+        (currentExtPreambleOper == preambleCnt_03Oper))
+    {
+      return;
+    }
+
+    onuGponDbExtPreambleSyncSet(preambleCnt_03Sync);
+    onuGponDbExtPreambleOperSet(preambleCnt_03Oper);
+  }
+  rcode = onuGponPonMngPreambleSet(onuState);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) Preamble Set\n", __FILE_DESC__, __LINE__);
+  }
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+  asicOntGlbRegReadNoCheck(mvAsicReg_GPON_GEN_MICRO_SEC_CNT,
+                           &(tmpPmCheckNode->uSecCntStop[tmpPmCheckNode->uSecCntIdx]), 0);
+  if(tmpPmCheckNode->uSecCntIdx < 255) tmpPmCheckNode->uSecCntIdx++;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngTimerT01Hndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when timer T01 expires
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngTimerT01Hndl(unsigned long data)
+{
+  unsigned long flags;
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_TIMER_MODULE,
+             "DEBUG: (%s:%d) onuGponPonMngTimerT01Hndl\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuGponT01_TimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+  onuGponPonMngTimerT01ExpireHndl();
+  /* stop onu gpon pon mng T01 timer */
+  onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponT01_TimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngTimerT01ExpireHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function executes timer T01 functionality
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngTimerT01ExpireHndl(void)
+{
+  MV_STATUS rcode;
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_TIMER_MODULE,
+             "DEBUG: (%s:%d) TIMER TO1 Expired, state(%d)\n", __FILE_DESC__, __LINE__, onuGponDbOnuStateGet());
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* state handling */
+  /* ============== */
+  rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_02_STANDBY);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngrUpdateState(2)\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
+  /* clear onu information */
+  /* ===================== */
+  rcode = onuGponPonMngClearOnuInfo();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuInfo\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
+  /* alarm handling */
+  /* ============== */
+  onuGponAlarmSet(ONU_GPON_ALARM_SUF, ONU_GPON_ALARM_ON);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngTimerT02Hndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when timer T02 expires
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngTimerT02Hndl(unsigned long data)
+{
+  unsigned long flags;
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_TIMER_MODULE,
+             "DEBUG: (%s:%d) onuGponPonMngTimerT02Hndl\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuGponT02_TimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+  onuGponPonMngTimerT02ExpireHndl();
+  /* stop onu gpon pon mng T02 timer */
+  onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponT02_TimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngTimerT02ExpireHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function executes timer T02 functionality
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 msgId
+**               MV_U8 *msgData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngTimerT02ExpireHndl(void)
+{
+  MV_STATUS rcode;
+
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_TIMER_MODULE,
+             "DEBUG: (%s:%d) TIMER TO2 Expired, state(%d)\n", __FILE_DESC__, __LINE__, onuGponDbOnuStateGet());
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* clear onu information */
+  /* ===================== */
+  rcode = onuGponPonMngClearOnuInfo();
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngClearOnuInfo\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+
+  /* state handling */
+  /* ============== */
+  rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_01_INIT);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) onuGponPonMngrUpdateState(1)\n", __FILE_DESC__, __LINE__);
+    return;
+  }
+#ifndef PON_FPGA
+    /* start xvr reset timer */
+    onuGponIsrXvrResetStateSet(MV_TRUE);
+#endif /* PON_FPGA */
+
+    onuGponDbOnuDsSyncOnSet(0);
+
+  onuGponAlarmSet(ONU_GPON_ALARM_LOF, ONU_GPON_ALARM_ON);
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "==================\n");
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "== POPUP Expire ==\n");
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "==================\n");
+#endif /* MV_GPON_DEBUG_PRINT */
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngTimerPeeHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called when timer Pee expires
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngTimerPeeHndl(unsigned long data)
+{
+  unsigned long flags;
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_TIMER_MODULE,
+             "DEBUG: (%s:%d) onuGponPonMngTimerPeeHndl\n", __FILE_DESC__, __LINE__);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+
+  onuPonResourceTbl_s.onuGponPeeTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+  onuGponPonMngTimerPeeExpireHndl();
+  /* stop onu gpon pon mng Pee timer */
+  onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponPeeTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngTimerPeeExpireHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function executes timer PEE functionality
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngTimerPeeExpireHndl(void)
+{
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_TIMER_MODULE,
+            "DEBUG: (%s:%d) TIMER PEE Expired, state(%d)\n",
+             __FILE_DESC__, __LINE__, onuGponDbOnuStateGet());
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* Cancel PEE Alarm */
+  onuGponAlarmSet(ONU_GPON_ALARM_PEE, ONU_GPON_ALARM_OFF);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Alarm Section                                      */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponPonMngGenCritAlarm
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function generate critical alarm
+**
+**  PARAMETERS:  E_OnuGponAlarmType alarmType_e
+**               MV_U8              dummyVal
+**               MV_U8              *dummyPtr
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngGenCritAlarm(E_OnuGponAlarmType alarmType_e,
+                               MV_U8 dummyVal,
+                               MV_U8 *dummyPtr)
+{
+  MV_STATUS rcode;
+  MV_U32    currentState;
+  MV_U32    onuId;
+
+  onuId        = onuGponDbOnuIdGet();
+  currentState = onuGponDbOnuStateGet();
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE,
+             "DEBUG: (%s:%d) ALARM ON - (%d), onuId(%d), state(%d)\n",
+             __FILE_DESC__, __LINE__, alarmType_e, onuId, currentState);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* Operation State */
+  /* =============== */
+  if (currentState == ONU_GPON_05_OPERATION)
+  {
+    /* special care for operation state */
+    /* move to popup state - start T02 timer */
+
+	/* state handling */
+	/* ============== */
+	rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_06_POPUP);
+	if (rcode != MV_OK)
+	{
+	  mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+	  		   "ERROR: (%s:%d) Set onu state to state 06\n", __FILE_DESC__, __LINE__);
+	  return;
+	}
+
+    /* T02 timer handling */
+    /* ================== */
+
+    /* start onu gpon pon mng T02 timer */
+	if ((alarmType_e == ONU_PON_MNGR_LOS_ALARM) ||
+		(alarmType_e == ONU_PON_MNGR_LOF_ALARM))
+      onuPonTimerEnable(&(onuPonResourceTbl_s.onuGponT02_TimerId));
+	else
+	  mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+	  		     "ERROR: (%s:%d) wrong start to T02\n", __FILE_DESC__, __LINE__);
+
+#ifdef MV_GPON_DEBUG_PRINT
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "===========\n");
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "== POPUP ==\n");
+    mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE, "===========\n");
+#endif /* MV_GPON_DEBUG_PRINT */
+  }
+
+  /* Ranging States */
+  /* ============== */
+  else if ((currentState >= ONU_GPON_01_INIT) &&
+           (currentState <= ONU_GPON_04_RANGING))
+  {
+    /* timer T01 is running */
+    if ((currentState >= ONU_GPON_02_STANDBY) &&
+        (currentState <= ONU_GPON_04_RANGING))
+    {
+      /* stop onu gpon pon mng T01 timer */
+      onuPonTimerDisable(&(onuPonResourceTbl_s.onuGponT01_TimerId));
+    }
+
+    /* clear onu information */
+    /* ===================== */
+    rcode = onuGponPonMngClearOnuInfo();
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) Clear onu information\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+
+    /* state handling */
+    /* ============== */
+    rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_01_INIT);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) Set onu state to state 01\n",__FILE_DESC__, __LINE__);
+      return;
+    }
+
+#ifndef PON_FPGA
+    /* start xvr reset timer */
+    onuGponIsrXvrResetStateSet(MV_TRUE);
+#endif /* PON_FPGA */
+
+    onuGponDbOnuDsSyncOnSet(0);
+  }
+
+  /* Emergancy Stop State */
+  /* ==================== */
+  else if (currentState == ONU_GPON_07_EMERGANCY_STOP)
+  {
+#ifndef PON_FPGA
+    /* start xvr reset timer */
+    onuGponIsrXvrResetStateSet(MV_TRUE);
+#endif /* PON_FPGA */
+  }
+
+  /* alarm handling */
+  /* ============== */
+  if (onuGponDbOnuStateGet() != ONU_GPON_06_POPUP)
+  onuGponAlarmSet(alarmType_e, ONU_GPON_ALARM_ON);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngCanCritAlarm
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function cancel critical alarm
+**
+**  PARAMETERS:  E_OnuGponAlarmType alarmType_e
+**               MV_U8              dummyVal
+**               MV_U8              *dummyPtr
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngCanCritAlarm(E_OnuGponAlarmType alarmType_e,
+                               MV_U8 dummyVal,
+                               MV_U8 *dummyPtr)
+{
+  MV_STATUS rcode;
+  MV_U32    currentState;
+  MV_U32    onuId;
+
+  onuId        = onuGponDbOnuIdGet();
+  currentState = onuGponDbOnuStateGet();
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE,
+             "DEBUG: (%s:%d) ALARM OFF - (%d), onuId(%d), state(%d)\n",
+             __FILE_DESC__, __LINE__, alarmType_e, onuId, currentState);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* alarm handling */
+  /* ============== */
+  onuGponAlarmSet(alarmType_e, ONU_GPON_ALARM_OFF);
+
+  if ((onuGponAsicAlarmStatusGet() == ONU_GPON_ALARM_OFF) &&
+      currentState == ONU_GPON_01_INIT)
+  {
+    /* state handling */
+    /* ============== */
+    rcode = onuGponPonMngrUpdateState((MV_U32)ONU_GPON_02_STANDBY);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+                 "ERROR: (%s:%d) Set onu state to state 02\n", __FILE_DESC__, __LINE__);
+      return;
+    }
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngGenMemAlarm
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle mem alarm (received unsupported message)
+**
+**  PARAMETERS:  E_OnuGponAlarmType alarmType_e
+**               MV_U8              dummyVal
+**               MV_U8              *dummyPtr
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngGenMemAlarm(E_OnuGponAlarmType alarmType_e,
+                              MV_U8 dummyVal,
+                              MV_U8 *dummyPtr)
+{
+  MV_U32 currentState;
+  MV_U32 onuId;
+
+  onuId        = onuGponDbOnuIdGet();
+  currentState = onuGponDbOnuStateGet();
+
+#ifdef MV_GPON_DEBUG_PRINT
+  mvPonPrint(PON_PRINT_DEBUG, PON_SM_MODULE,
+             "DEBUG: (%s:%d) generate mem, onuId(%d), state(%d)\n",
+             __FILE_DESC__, __LINE__, onuId, currentState);
+#endif /* MV_GPON_DEBUG_PRINT */
+
+  /* alarm handling */
+  /* ============== */
+  onuGponAlarmSet(alarmType_e, ONU_GPON_ALARM_ON);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         UTILS Routines                                     */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponPonMngPreambleSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function update onu preamble according to onu state
+**
+**  PARAMETERS:  MV_U32 onuState
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngPreambleSet(MV_U32 onuState)
+{
+  MV_STATUS rcode;
+  MV_U32    type1Size;
+  MV_U32    type2Size;
+  MV_U32    type3Size = 0;
+  MV_U32    type3Pattern;
+  MV_U32    dummy;
+
+  /* Get Preambles Parameters */
+  onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_01, &dummy, &type1Size);
+  onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_02, &dummy, &type2Size);
+  onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_03, &type3Pattern, &dummy);
+  switch (onuState)
+  {
+  case ONU_GPON_01_INIT:
+  case ONU_GPON_02_STANDBY:
+    break;
+  case ONU_GPON_03_SERIAL_NUM:
+  case ONU_GPON_04_RANGING:
+    type3Size = onuGponDbExtPreambleSyncGet();
+    break;
+  case ONU_GPON_05_OPERATION:
+    type3Size = onuGponDbExtPreambleOperGet();
+    break;
+  case ONU_GPON_06_POPUP:
+  case ONU_GPON_07_EMERGANCY_STOP:
+  default:
+    break;
+  }
+
+  /* update asic */
+  rcode = mvOnuGponMacPreambleSet(ONU_TX_PREAMBLE_TYPE_01_P, type1Size,
+                                  ONU_TX_PREAMBLE_TYPE_02_P, type2Size,
+                                  type3Pattern, type3Size);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_SM_MODULE,
+               "ERROR: (%s:%d) mvOnuGponMacPreambleSet type3 size(%d) type3 pattern(%d)\n",
+               __FILE_DESC__, __LINE__, type3Size, type3Pattern);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngOverheadManualModeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu overhead manual mode
+**
+**  PARAMETERS:  MV_BOOL mode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPonMngOverheadManualModeSet(MV_BOOL mode)
+{
+  g_overheadManualMode = mode;
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngOverheadManualModeGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu overhead manual mode
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     onu overhead manual mode
+**
+*******************************************************************************/
+MV_BOOL onuGponPonMngOverheadManualModeGet(void)
+{
+  return(g_overheadManualMode);
+}
+
+/*******************************************************************************
+**
+**  onuGponPonMngDisableSetRegister
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu disable function
+**
+**  PARAMETERS:  DISABLESTATSETFUNC disableFunc
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPonMngDisableSetRegister(DISABLESTATSETFUNC disableFunc)
+{
+  g_onuGponDisableFunc = disableFunc;
+
+  return(MV_OK);
+}
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuPm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuPm.c
new file mode 100755
index 0000000..a0eae0b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuPm.c
@@ -0,0 +1,1111 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuPm.c                                                **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON Alarm and Statistics         **
+**                functionality                                              **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "gponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuPm.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+/* ONU GPON PM table */
+S_GponPm    g_OnuGponPm;
+S_PloamSwPm g_OnuGponSwPm;
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+S_GponPerformanceCheck g_GponPmCheck;
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+extern spinlock_t onuPonIrqLock;
+
+static S_apiGemPortPmConfigDb apiGemPortPmConfigDb;
+
+/* Global functions
+------------------------------------------------------------------------------*/
+void       onuGponPmInPmInit(void);
+MV_STATUS onuGponPmCountersAdd(void);
+MV_STATUS onuGponRougeOnuCheck(void);
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Init Section                                       */
+/* ========================================================================== */
+/******************************************************************************/
+#ifdef MV_GPON_PERFORMANCE_CHECK
+MV_STATUS onuGponPmInit(void)
+{
+  MV_U32 index;
+
+  for (index = 0; index < PON_MAX_PERFORMANCE; index++)
+  {
+    g_GponPmCheck.pmCheckNode[index].uSecCntStart = (MV_U32*)onuPonMemAlloc(256 * sizeof(MV_U32));
+    if (g_GponPmCheck.pmCheckNode[index].uSecCntStart == NULL)
+      return(MV_ERROR);
+
+    g_GponPmCheck.pmCheckNode[index].uSecCntStop = (MV_U32*)onuPonMemAlloc(256 * sizeof(MV_U32));
+    if (g_GponPmCheck.pmCheckNode[index].uSecCntStop == NULL)
+      return(MV_ERROR);
+
+    g_GponPmCheck.pmCheckNode[index].uSecCntIdx = 0;
+  }
+
+  return(MV_OK);
+}
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Statistics Section                                 */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponPmInPmInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init the onu gpon alarm table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPmInPmInit(void)
+{
+  /* reset all counters */
+  memset(&g_OnuGponPm,   0, sizeof(S_GponPm));
+  memset(&g_OnuGponSwPm, 0, sizeof(S_PloamSwPm));
+}
+
+/*******************************************************************************
+**
+**  onuGponPmTimerPmHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is called by the GPON PM timer and trigger the
+**               GPON handler to execute PM functionality
+**
+**  PARAMETERS:  unsigned long data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPmTimerPmHndl(unsigned long data)
+{
+  unsigned long flags;
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+  onuPonResourceTbl_s.onuPonPmTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+
+  /* Call PM handler */
+  onuGponPmTimerExpireHndl();
+
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+  if ((onuPonResourceTbl_s.onuPonPmTimerId.onuPonTimerPeriodic) != 0)
+    onuPonTimerEnable(&(onuPonResourceTbl_s.onuPonPmTimerId));
+
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmTimerExpireHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: This routine execute PM handler functionality
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponPmTimerExpireHndl(void)
+{
+  S_RxBip8Pm inBip8Pm;
+  unsigned long flags;
+
+  onuGponPmCountersAdd();
+  onuGponPmRxBip8PmGet(&inBip8Pm);
+  spin_lock_irqsave(&onuPonIrqLock, flags);
+  onuGponBerPeriodPass(inBip8Pm.bip8);
+  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+  onuGponRougeOnuCheck();
+}
+
+/*******************************************************************************
+**
+**  onuGponRougeOnuCheck
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: This routine validate rouge ONU statistics values
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponRougeOnuCheck(void)
+{
+#ifndef PON_FPGA
+  MV_STATUS status;
+#endif /* PON_FPGA */
+  MV_U32    txBurstEnCnt;
+
+  onuGponPmTxBurstEnCntGet(&txBurstEnCnt);
+
+  if (txBurstEnCnt >= GPON_BURST_THRESHOLD)
+  {
+    mvPonPrint(PON_PRINT_ERROR, PON_PM_MODULE, "===========================\n");
+    mvPonPrint(PON_PRINT_ERROR, PON_PM_MODULE, "== ROUGE ONU             ==\n");
+    mvPonPrint(PON_PRINT_ERROR, PON_PM_MODULE, "== Shutting Down the XVR ==\n");
+    mvPonPrint(PON_PRINT_ERROR, PON_PM_MODULE, "===========================\n");
+
+#ifndef PON_FPGA
+    /* Set the output enable of the GP_BEN IO to Input */
+    status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_INPUT, 0);
+    if (status != MV_OK)
+      return(status);
+#endif /* PON_FPGA */
+  }
+
+  return(MV_OK);
+}
+
+
+/*******************************************************************************
+**
+**  ponOltPmOnuCountersAdd
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: This routine read statistics values from ASIC to the database
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmCountersAdd(void)
+{
+	MV_U32  tempCounter1;
+	MV_U32  tempCounter2;
+	MV_U32  tempCounter3;
+	MV_U32  tempCounter4;
+	MV_U32  tcont;
+	MV_BOOL exist;
+	MV_STATUS status;
+
+	/* BIP8 Counter */
+	/* ============ */
+	mvOnuGponMacBipStatusValueGet(&tempCounter1);
+	g_OnuGponPm.rxBip8.bip8 += tempCounter1;
+
+	/* Ploam Counters */
+	/* ============== */
+	mvOnuGponMacRxPloamLostCrcCounterGet(&tempCounter1);				 /* Error CRC */
+	g_OnuGponPm.rxPloam.crcErrorPloamCounter += tempCounter1;
+	mvOnuGponMacRxPloamLostFullCounterGet(&tempCounter1);				 /* Downstream lost due to full FIFO */
+	g_OnuGponPm.rxPloam.fifoOverErrorPloamCounter += tempCounter1;
+	mvOnuGponMacRxPloamRcvdIdleCounterGet(&tempCounter1);				 /* Downstream received idle */
+	g_OnuGponPm.rxPloam.idlePloamCounter += tempCounter1;
+	mvOnuGponMacRxPloamRcvdBroadCounterGet(&tempCounter1);				 /* Downstream received broadcast */
+	g_OnuGponPm.rxPloam.receivedBroadcastPloamCounter += tempCounter1;
+	mvOnuGponMacRxPloamRcvdOnuIdCounterGet(&tempCounter1);				 /* Downstream received ONU ID */
+	g_OnuGponPm.rxPloam.receivedOnuIdPloamCounter += tempCounter1;
+
+	/* BW MAP counters  */
+	/* =============== */
+	mvOnuGponMacRxBwMapAllocatrionsCounterGet(&tempCounter1, &tempCounter2, &tempCounter3, &tempCounter4);
+	g_OnuGponPm.rxBwMap.allocCorrec += tempCounter1;				   /* Received allocations errors free */
+	g_OnuGponPm.rxBwMap.allocUnCorrectableCrcErr += tempCounter2;	   /* Received allocations with uncorrectable CRC errors */
+	g_OnuGponPm.rxBwMap.allocCorrectableCrcErr += tempCounter3;		   /* Received allocations with correctable CRC errors or errors free */
+	g_OnuGponPm.rxBwMap.allocCrcErr += tempCounter4;				   /* Received allocations with CRC error */
+	mvOnuGponMacRxBwMapTotalBwGet(&tempCounter1);						 /* Total received byte allocations */
+	g_OnuGponPm.rxBwMap.totalReceivedAllocBytes += tempCounter1;
+
+	/* PLEND unusable counter */
+	/* ====================== */
+	mvOnuGponMacInComingPlendCntGet(&tempCounter1);
+	g_OnuGponPm.rxPlend.plend += tempCounter1;
+
+	/* FEC Counters */
+	/* ============ */
+	mvOnuGponMacRxFecBytesCounterGet(&tempCounter1);					 /* Received bytes */
+	g_OnuGponPm.rxFec.receivedBytes += tempCounter1;
+	mvOnuGponMacRxFecCorrectCounterGet(&tempCounter1, &tempCounter2);
+	g_OnuGponPm.rxFec.correctedBits += tempCounter2;				   /* Received corrected bits */
+	g_OnuGponPm.rxFec.correctedBytes += tempCounter1;				   /* Received corrected bytes */
+	mvOnuGponMacRxFecInorrectCounterGet(&tempCounter1, &tempCounter2);
+	g_OnuGponPm.rxFec.receivedCodeWords += tempCounter2;			   /* Received code words */
+	g_OnuGponPm.rxFec.uncorrectedCodeWords += tempCounter1;			   /* Received corrected code words */
+
+	/* GEM Counters */
+	/* ============ */
+	mvOnuGponMacGemRcvdIdleGemFramesCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedIdleGemFrames += tempCounter1;
+	mvOnuGponMacGemRcvdValidGemFramesCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedValidGemFrames += tempCounter1;
+	mvOnuGponMacGemRcvdUndefGemFramesCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedUndefinedGemFrames += tempCounter1;
+	mvOnuGponMacGemRcvdOmciFramesCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedOmciFrames += tempCounter1;
+	mvOnuGponMacGemDropGemFramesCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.droppedGemFrames += tempCounter1;
+	mvOnuGponMacGemDropOmciFramesCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.droppedOmciFrames += tempCounter1;
+	mvOnuGponMacGemRcvdGemFramesWithUncorrHecErrCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedGemFramesWithUncorrHecErr += tempCounter1;
+	mvOnuGponMacGemRcvdGemFramesWithOneFixedHecErrCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedGemFramesWithOneFixedHecErr += tempCounter1;
+	mvOnuGponMacGemRcvdGemFramesWithTwoFixedHecErrCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedGemFramesWithTwoFixedHecErr += tempCounter1;
+	mvOnuGponMacGemRcvdValidGemFramesTotalByteCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.totalByteCountOfReceivedValidGemFrames += tempCounter1;
+	mvOnuGponMacGemRcvdUndefGemFramesTotalByteCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.totalByteCountOfReceivedUndefinedGemFrames += tempCounter1;
+	mvOnuGponMacGemReassembleMemoryFlushCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.gemReassembleMemoryFlush += tempCounter1;
+	mvOnuGponMacGemSynchLostCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.gemSynchLost += tempCounter1;
+	mvOnuGponMacGemRcvdEthFramesWithCorrFcsCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedEthFramesWithCorrFcs += tempCounter1;
+	mvOnuGponMacGemRcvdEthFramesWithFcsErrCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedEthFramesWithFcsError += tempCounter1;
+	mvOnuGponMacGemRcvdOmciFramesWithCorrCrcCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedOmciFramesWithCorrCrc += tempCounter1;
+	mvOnuGponMacGemRcvdOmciFramesWithCrcErrCounterGet(&tempCounter1);
+	g_OnuGponPm.gem.receivedOmciFramesWithCrcError += tempCounter1;
+
+	/* Tx Counters */
+	/* =========== */
+	mvOnuGponMacTxGemPtiTypeOneFrameCounterGet(&tempCounter1);
+	g_OnuGponPm.tx.transmittedGemPtiTypeOneFrames += tempCounter1;
+	mvOnuGponMacTxGemPtiTypeZeroFrameCounterGet(&tempCounter1);
+	g_OnuGponPm.tx.transmittedGemPtiTypeZeroFrames += tempCounter1;
+	mvOnuGponMacTxIdleGemFramesCounterGet(&tempCounter1);
+	g_OnuGponPm.tx.transmittedIdleGemFrames += tempCounter1;
+	mvOnuGponMacTxTxEnableCounterGet(&tempCounter1);
+	g_OnuGponPm.tx.transmittedTxEnableCount += tempCounter1;
+
+	for (tcont = 0; tcont < ONU_GPON_MAX_NUM_OF_T_CONTS; tcont++) {
+		status = onuGponDbBwTcontExist(tcont, &exist);
+		if ((status == MV_OK) && (exist != MV_FALSE)) {
+			mvOnuGponMacTxEthFramesTcontiCounterGet(tcont, &tempCounter1);
+			g_OnuGponPm.tx.transmittedEthFramesViaTconti[tcont] += tempCounter1;
+			mvOnuGponMacTxEthBytesTcontiCounterGet(tcont, &tempCounter1);
+			g_OnuGponPm.tx.transmittedEthBytesViaTconti[tcont] += tempCounter1;
+			mvOnuGponMacTxGemFramesTcontiCounterGet(tcont, &tempCounter1);
+			g_OnuGponPm.tx.transmittedGemFramesViaTconti[tcont] += tempCounter1;
+			mvOnuGponMacTxIdleGemFramesTcontiCounterGet(tcont, &tempCounter1);
+			g_OnuGponPm.tx.transmittedIdleGemFramesViaTconti[tcont] += tempCounter1;
+		}
+	}
+
+	/* Sw Counters */
+	/* =========== */
+	onuGponPmSwCountersUpdate(&g_OnuGponPm.rxPloam, &g_OnuGponPm.txPloam);
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmRxSwCountersAdd
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function updates Rx Ploam message counters
+**
+**  PARAMETERS:  MV_U8 a_msgId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmRxSwCountersAdd(MV_U8 a_msgId)
+{
+  g_OnuGponSwPm.rxMsgTotalPloamCounter++;
+  g_OnuGponSwPm.rxMsgIdPloamCounter[a_msgId]++;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmSwCountersUpdate
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function updates Rx Ploam message counters
+**
+**  PARAMETERS:  MV_U8 a_msgId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmSwCountersUpdate(S_RxPloamPm *rxPloamPm, S_TxPloamPm *txPloamPm)
+{
+  MV_U32 numOfMsgIdIndex;
+
+  /* Rx PLOAM */
+  rxPloamPm->rxMsgTotalPloamCounter = g_OnuGponSwPm.rxMsgTotalPloamCounter;
+
+  for (numOfMsgIdIndex = ONU_GPON_DS_MSG_OVERHEAD;
+       numOfMsgIdIndex <= ONU_GPON_DS_MSG_EXT_BURST_LEN;
+       numOfMsgIdIndex++)
+  {
+    rxPloamPm->rxMsgIdPloamCounter[numOfMsgIdIndex] = g_OnuGponSwPm.rxMsgIdPloamCounter[numOfMsgIdIndex];
+  }
+
+  mvOnuGponMacTxSwCountersGet((void*)txPloamPm);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmFecPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Rx FEC counters
+**
+**  PARAMETERS:  S_RxFecPm *fecPm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmFecPmGet(S_RxFecPm *fecPm)
+{
+  fecPm->receivedBytes        = g_OnuGponPm.rxFec.receivedBytes;
+  fecPm->correctedBytes       = g_OnuGponPm.rxFec.correctedBytes;
+  fecPm->correctedBits        = g_OnuGponPm.rxFec.correctedBits ;
+  fecPm->receivedCodeWords    = g_OnuGponPm.rxFec.receivedCodeWords;
+  fecPm->uncorrectedCodeWords = g_OnuGponPm.rxFec.uncorrectedCodeWords;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmRxPloamPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Rx PLOAM counters
+**
+**  PARAMETERS:  S_RxPloamPm *rxPloamPm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmRxPloamPmGet(S_RxPloamPm *rxPloamPm)
+{
+  MV_U32 numOfMsgIdIndex;
+
+  rxPloamPm->crcErrorPloamCounter          = g_OnuGponPm.rxPloam.crcErrorPloamCounter;
+  rxPloamPm->receivedBroadcastPloamCounter = g_OnuGponPm.rxPloam.receivedBroadcastPloamCounter;
+  rxPloamPm->receivedOnuIdPloamCounter     = g_OnuGponPm.rxPloam.receivedOnuIdPloamCounter;
+  rxPloamPm->fifoOverErrorPloamCounter     = g_OnuGponPm.rxPloam.fifoOverErrorPloamCounter;
+  rxPloamPm->idlePloamCounter              = g_OnuGponPm.rxPloam.idlePloamCounter;
+  rxPloamPm->rxMsgTotalPloamCounter        = g_OnuGponPm.rxPloam.rxMsgTotalPloamCounter;
+
+  for (numOfMsgIdIndex = 0 ;numOfMsgIdIndex <= ONU_GPON_DS_MSG_LAST;numOfMsgIdIndex++)
+  {
+    rxPloamPm->rxMsgIdPloamCounter[numOfMsgIdIndex] = g_OnuGponPm.rxPloam.rxMsgIdPloamCounter[numOfMsgIdIndex];
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmTxPloamPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Tx PLOAM counters
+**
+**  PARAMETERS:  S_TxPloamPm *txPloamPm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmTxPloamPmGet(S_TxPloamPm *txPloamPm)
+{
+  MV_U32 numOfMsgIdIndex;
+
+  txPloamPm->txMsgTotalPloamCounter = g_OnuGponPm.txPloam.txMsgTotalPloamCounter;
+
+  for (numOfMsgIdIndex = 1; numOfMsgIdIndex <= ONU_GPON_US_MSG_LAST; numOfMsgIdIndex++ )
+  {
+    txPloamPm->txMsgIdPloamCounter[numOfMsgIdIndex] = g_OnuGponPm.txPloam.txMsgIdPloamCounter[numOfMsgIdIndex];
+
+    txPloamPm->txErrMsgIdPloamCounter[numOfMsgIdIndex] = g_OnuGponPm.txPloam.txErrMsgIdPloamCounter[numOfMsgIdIndex];
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmRxBwMapCountersAdd
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: This routine read BW MAP counters from ASIC to the database
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmRxBwMapCountersAdd(void)
+{
+  MV_U32  tempCounter1;
+  MV_U32  tempCounter2;
+  MV_U32  tempCounter3;
+  MV_U32  tempCounter4;
+
+  mvOnuGponMacRxBwMapAllocatrionsCounterGet(&tempCounter1, &tempCounter2, &tempCounter3, &tempCounter4);
+  g_OnuGponPm.rxBwMap.allocCorrec              += tempCounter1;      /* Received allocations errors free */
+  g_OnuGponPm.rxBwMap.allocUnCorrectableCrcErr += tempCounter2;      /* Received allocations with uncorrectable CRC errors */
+  g_OnuGponPm.rxBwMap.allocCorrectableCrcErr   += tempCounter3;      /* Received allocations with correctable CRC errors or errors free */
+  g_OnuGponPm.rxBwMap.allocCrcErr              += tempCounter4;      /* Received allocations with CRC error */
+  mvOnuGponMacRxBwMapTotalBwGet(&tempCounter1);                     /* Total received byte allocations */
+  g_OnuGponPm.rxBwMap.totalReceivedAllocBytes  += tempCounter1;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmRxBwMapPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Rx BW MAP counters
+**
+**  PARAMETERS:  S_RxPloamPm *rxPloamPm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmRxBwMapPmGet(S_RxBwMapPm *rxBwMapPm)
+{
+  rxBwMapPm->allocCorrec              = g_OnuGponPm.rxBwMap.allocCorrec;
+  rxBwMapPm->allocCorrectableCrcErr   = g_OnuGponPm.rxBwMap.allocCorrectableCrcErr;
+  rxBwMapPm->allocCrcErr              = g_OnuGponPm.rxBwMap.allocCrcErr;
+  rxBwMapPm->allocUnCorrectableCrcErr = g_OnuGponPm.rxBwMap.allocUnCorrectableCrcErr;
+  rxBwMapPm->totalReceivedAllocBytes  = g_OnuGponPm.rxBwMap.totalReceivedAllocBytes;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmRxPlendPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Rx Plend counter
+**
+**  PARAMETERS:  S_RxPlendPm *rxPlendPm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmRxPlendPmGet(S_RxPlendPm *rxPlendPm)
+{
+  rxPlendPm->plend = g_OnuGponPm.rxPlend.plend;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmRxBip8PmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Rx Bip8 counter
+**
+**  PARAMETERS:  S_RxBip8Pm *rxBip8Pm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmRxBip8PmGet(S_RxBip8Pm *rxBip8Pm)
+{
+  rxBip8Pm->bip8 = g_OnuGponPm.rxBip8.bip8;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmGemPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Gem pm counters
+**
+**  PARAMETERS:  S_GemPm *gemPm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmGemPmGet(S_GemPm *gemPm)
+{
+  gemPm->receivedIdleGemFrames                       = g_OnuGponPm.gem.receivedIdleGemFrames;
+  gemPm->receivedValidGemFrames                      = g_OnuGponPm.gem.receivedValidGemFrames;
+  gemPm->receivedUndefinedGemFrames                  = g_OnuGponPm.gem.receivedUndefinedGemFrames;
+  gemPm->receivedOmciFrames                          = g_OnuGponPm.gem.receivedOmciFrames;
+  gemPm->droppedGemFrames                            = g_OnuGponPm.gem.droppedGemFrames;
+  gemPm->droppedOmciFrames                           = g_OnuGponPm.gem.droppedOmciFrames;
+  gemPm->receivedGemFramesWithUncorrHecErr           = g_OnuGponPm.gem.receivedGemFramesWithUncorrHecErr;
+  gemPm->receivedGemFramesWithOneFixedHecErr         = g_OnuGponPm.gem.receivedGemFramesWithOneFixedHecErr;
+  gemPm->receivedGemFramesWithTwoFixedHecErr         = g_OnuGponPm.gem.receivedGemFramesWithTwoFixedHecErr;
+  gemPm->totalByteCountOfReceivedValidGemFrames      = g_OnuGponPm.gem.totalByteCountOfReceivedValidGemFrames;
+  gemPm->totalByteCountOfReceivedUndefinedGemFrames  = g_OnuGponPm.gem.totalByteCountOfReceivedUndefinedGemFrames;
+  gemPm->gemReassembleMemoryFlush                    = g_OnuGponPm.gem.gemReassembleMemoryFlush;
+  gemPm->gemSynchLost                                = g_OnuGponPm.gem.gemSynchLost;
+  gemPm->receivedEthFramesWithCorrFcs                = g_OnuGponPm.gem.receivedEthFramesWithCorrFcs;
+  gemPm->receivedEthFramesWithFcsError               = g_OnuGponPm.gem.receivedEthFramesWithFcsError;
+  gemPm->receivedOmciFramesWithCorrCrc               = g_OnuGponPm.gem.receivedOmciFramesWithCorrCrc;
+  gemPm->receivedOmciFramesWithCrcError              = g_OnuGponPm.gem.receivedOmciFramesWithCrcError;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmTxPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Tx pm counters
+**
+**  PARAMETERS:  S_TxPm *txPm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmTxPmGet(S_GponTxPm *txPm)
+{
+	MV_U32 tcont;
+	MV_BOOL   exist;
+	MV_STATUS status;
+
+	txPm->transmittedGemPtiTypeOneFrames    = g_OnuGponPm.tx.transmittedGemPtiTypeOneFrames;
+	txPm->transmittedGemPtiTypeZeroFrames   = g_OnuGponPm.tx.transmittedGemPtiTypeZeroFrames;
+	txPm->transmittedIdleGemFrames          = g_OnuGponPm.tx.transmittedIdleGemFrames;
+	txPm->transmittedTxEnableCount          = g_OnuGponPm.tx.transmittedTxEnableCount;
+
+	for (tcont = 0; tcont < ONU_GPON_MAX_NUM_OF_T_CONTS; tcont++) {
+		status = onuGponDbBwTcontExist(tcont, &exist);
+		if ((status == MV_OK) && (exist != MV_FALSE)) {
+			txPm->transmittedEthFramesViaTconti[tcont]     = g_OnuGponPm.tx.transmittedEthFramesViaTconti[tcont];
+			txPm->transmittedEthBytesViaTconti[tcont]      = g_OnuGponPm.tx.transmittedEthBytesViaTconti[tcont];
+			txPm->transmittedGemFramesViaTconti[tcont]     = g_OnuGponPm.tx.transmittedGemFramesViaTconti[tcont];
+			txPm->transmittedIdleGemFramesViaTconti[tcont] = g_OnuGponPm.tx.transmittedIdleGemFramesViaTconti[tcont];
+		}
+	}
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPmTxBurstEnCntGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The funtion return onu Tx burst enable counter
+**
+**  PARAMETERS:  unsigned int *txBurstEnCnt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS onuGponPmTxBurstEnCntGet(unsigned int *txBurstEnCnt)
+{
+  *txBurstEnCnt = g_OnuGponPm.tx.transmittedTxEnableCount;
+
+  g_OnuGponPm.tx.transmittedTxEnableCount = 0;
+
+  return(MV_OK);
+}
+
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         GEM Port PM Section                                */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponPmGemPortPmInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears GEM Port PM database
+**
+**  PARAMETERS:  void
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuGponPmGemPortPmInit(void)
+{
+  int       indx;
+
+  for (indx = 0; indx < MAX_ENTRIES_GEMPORTPM_CONFIG_DB; indx++)
+  {
+    apiGemPortPmConfigDb.apiGemPortPmConfigAra[indx].in_use = MV_FALSE;
+  }
+
+  if (asicOntMiscRegRead(mvAsicReg_RX_MIB_DEFAULT, &apiGemPortPmConfigDb.origRxMibDefaultReg, 0) != MV_OK)
+  {
+    printk("%s: asicOntMiscRegRead failed for mvAsicReg_RX_MIB_DEFAULT(%d)\n", __FUNCTION__, mvAsicReg_RX_MIB_DEFAULT);
+  }
+}
+
+
+/*******************************************************************************
+**
+**  onuGponPmGemPortPmGetNumUsedEntries
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function counts the number of used GEM port entries in the DB
+**
+**  PARAMETERS:  void
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     int
+**
+*******************************************************************************/
+int onuGponPmGemPortPmGetNumUsedEntries(void)
+{
+  int       indx;
+  int       usedEntries = 0;
+
+  for (indx = 0; indx < MAX_ENTRIES_GEMPORTPM_CONFIG_DB; indx++)
+  {
+    if (apiGemPortPmConfigDb.apiGemPortPmConfigAra[indx].in_use == MV_TRUE)
+      usedEntries++;
+  }
+  return usedEntries;
+}
+
+
+/*******************************************************************************
+**
+**  onuGponPmGemPortPmStart
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function activates MIB Counter PM for a GEM port
+**
+**  PARAMETERS:  S_GponIoctlGemPortPmConfig *
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPmGemPortPmStart(MV_U16 gemPort)
+{
+  MV_STATUS            rcode = MV_OK;
+  int                  indx;
+  S_apiGemPortPmConfig *apiGemPortPmConfig;
+  S_apiGemPortPmConfig *tgtApiGemPortPmConfig = 0;
+  int                  freeIndx;
+  MV_U32               mibCtrlValue;
+
+  // Does the GEM Port already appear in table
+  for (indx = 0; indx < MAX_SUPPORTED_GEMPORTS_FOR_PM; indx++)
+  {
+    apiGemPortPmConfig = &apiGemPortPmConfigDb.apiGemPortPmConfigAra[indx];
+    if (apiGemPortPmConfig->in_use == MV_TRUE && apiGemPortPmConfig->gem_port == gemPort)
+    {
+        printk("%s: gemPort %d already in table (start)\n", __FUNCTION__, gemPort);
+        return MV_ALREADY_EXIST;
+    }
+  }
+
+  for (indx = 0; indx < MAX_SUPPORTED_GEMPORTS_FOR_PM; indx++)
+  {
+    apiGemPortPmConfig = &apiGemPortPmConfigDb.apiGemPortPmConfigAra[indx];
+    if (apiGemPortPmConfig->in_use == MV_FALSE)
+    {
+      tgtApiGemPortPmConfig = apiGemPortPmConfig;
+      freeIndx              = indx;
+      break;
+    }
+  }
+
+  // Did we find a free entry
+  if (tgtApiGemPortPmConfig == 0)
+  {
+      printk("%s: Table full. gemPort = %d (start)\n", __FUNCTION__, gemPort);
+      return MV_NO_MORE;
+  }
+
+  if (onuGponPmGemPortPmGetNumUsedEntries() == 0)
+  {
+    if ((rcode = asicOntMiscRegRead(mvAsicReg_RX_MIB_DEFAULT, &apiGemPortPmConfigDb.origRxMibDefaultReg, 0)) != MV_OK)
+    {
+      printk("%s: asicOntMiscRegRead failed for mvAsicReg_RX_MIB_DEFAULT(%d)\n", __FUNCTION__, mvAsicReg_RX_MIB_DEFAULT);
+      return rcode;
+    }
+    mibCtrlValue = MAKE_MIB_COUNTER_CONTROL(MIB_COUNTER_CONTROL_INVALID_BIT,0,0);
+    if ((rcode = asicOntMiscRegWrite(mvAsicReg_RX_MIB_DEFAULT, mibCtrlValue, 0)) != MV_OK)
+    {
+      printk("%s: asicOntMiscRegWrite failed for mvAsicReg_RX_MIB_DEFAULT(%d)\n", __FUNCTION__, mvAsicReg_RX_MIB_DEFAULT);
+      return rcode;
+    }
+  }
+
+  mibCtrlValue = MAKE_MIB_COUNTER_CONTROL(MIB_COUNTER_CONTROL_VALID_BIT,freeIndx,gemPort);
+  if ((rcode = asicOntMiscRegWrite(mvAsicReg_RX_MIB_CTRL, mibCtrlValue, indx)) != MV_OK)
+  {
+      printk("%s: asicOntMiscRegWrite failed for indx = %d (start)\n", __FUNCTION__, indx);
+  }
+  else
+  {
+    tgtApiGemPortPmConfig->gem_port    = gemPort;
+    tgtApiGemPortPmConfig->counter_set = freeIndx;
+    tgtApiGemPortPmConfig->in_use      = MV_TRUE;
+  }
+  return rcode;
+}
+
+
+/*******************************************************************************
+**
+**  onuGponPmGemPortPmStop
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function activates MIB Counter PM for a GEM port
+**
+**  PARAMETERS:  S_GponIoctlGemPortPmConfig *
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS  onuGponPmGemPortPmStop(MV_U16 gemPort)
+{
+  MV_STATUS            rcode = MV_OK;
+  int                  indx;
+  S_apiGemPortPmConfig *apiGemPortPmConfig;
+  S_apiGemPortPmConfig *tgtApiGemPortPmConfig = 0;
+  MV_U32               mibCtrlValue;
+
+  // Does the GEM Port already appear in table
+  for (indx = 0; indx < MAX_SUPPORTED_GEMPORTS_FOR_PM; indx++)
+  {
+    apiGemPortPmConfig = &apiGemPortPmConfigDb.apiGemPortPmConfigAra[indx];
+    if (apiGemPortPmConfig->in_use == MV_TRUE && apiGemPortPmConfig->gem_port == gemPort)
+    {
+      tgtApiGemPortPmConfig = apiGemPortPmConfig;
+      break;
+    }
+  }
+
+  // Did we find a free entry
+  if (tgtApiGemPortPmConfig == 0)
+  {
+      printk("%s: gemPort %d not in table (stop)\n", __FUNCTION__, gemPort);
+      return MV_NOT_FOUND;
+  }
+
+  mibCtrlValue = MAKE_MIB_COUNTER_CONTROL(MIB_COUNTER_CONTROL_INVALID_BIT,0,0);
+  if ((rcode = asicOntMiscRegWrite(mvAsicReg_RX_MIB_CTRL, mibCtrlValue, indx)) != MV_OK)
+  {
+    printk("%s: asicOntMiscRegWrite failed for indx = %d (stop)\n", __FUNCTION__, indx);
+    return rcode;
+  }
+  else
+  {
+    tgtApiGemPortPmConfig->in_use = MV_FALSE;
+  }
+
+  // If no more GEM ports are being monitored, restore the original RX_MIB_DEFAULT register value
+  if (onuGponPmGemPortPmGetNumUsedEntries() == 0)
+  {
+    if ((rcode = asicOntMiscRegWrite(mvAsicReg_RX_MIB_DEFAULT, apiGemPortPmConfigDb.origRxMibDefaultReg, 0)) != MV_OK)
+    {
+      printk("%s: asicOntMiscRegWrite failed for mvAsicReg_RX_MIB_DEFAULT(%d)\n", __FUNCTION__, mvAsicReg_RX_MIB_DEFAULT);
+      return rcode;
+    }
+  }
+
+  return rcode;
+}
+
+/*******************************************************************************
+**
+**  onuGponPmGemPortPmReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears HW register for PM collection for GEM Port
+**
+**  PARAMETERS:  void
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPmGemPortPmReset(void)
+{
+  MV_STATUS            rcode;
+  int                  indx;
+  uint32_t             mibCtrlValue = MAKE_MIB_COUNTER_CONTROL(MIB_COUNTER_CONTROL_INVALID_BIT,0,0);
+
+  for (indx = 0; indx < MAX_ENTRIES_GEMPORTPM_CONFIG_DB; indx++)
+  {
+    // Clear register (indx)
+    apiGemPortPmConfigDb.apiGemPortPmConfigAra[indx].in_use = MV_FALSE;
+    if ((rcode = asicOntMiscRegWrite(mvAsicReg_RX_MIB_CTRL, mibCtrlValue, indx)) != MV_OK)
+    {
+      printk("%s: asicOntMiscRegWrite failure, rcode = %d, indx = %d\n", __FUNCTION__, rcode, indx);
+      return rcode;
+    }
+  }
+
+  if ((rcode = asicOntMiscRegWrite(mvAsicReg_RX_MIB_DEFAULT, apiGemPortPmConfigDb.origRxMibDefaultReg, 0)) != MV_OK)
+  {
+    printk("%s: asicOntMiscRegWrite failed for mvAsicReg_RX_MIB_DEFAULT(%d)\n", __FUNCTION__, mvAsicReg_RX_MIB_DEFAULT);
+    return rcode;
+  }
+
+  return MV_OK;
+}
+
+
+/*******************************************************************************
+**
+**  onuGponPmGemPortPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function retrieves MIB Counter PM for GEM Port
+**
+**  PARAMETERS:  S_GponIoctlGemPortMibCounters *
+**
+**  OUTPUTS:     Reads MIB counters from HW
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPmGemPortPmGet(MV_U16 gemPort, S_GponIoctlGemPortMibCounters *gemPortMibCounters)
+{
+  MV_STATUS            rcode = MV_OK;
+  int                  indx;
+  S_apiGemPortPmConfig *apiGemPortPmConfig;
+  S_apiGemPortPmConfig *tgtApiGemPortPmConfig = 0;
+  MV_U32               baseCounterReg;
+  MV_U32               lowvalue;
+  MV_U32               hivalue;
+  MV_U32               registersAra[] =
+  {
+    mvAsicReg_PON_MAC_MIB_COUNTERS_0, mvAsicReg_PON_MAC_MIB_COUNTERS_1, mvAsicReg_PON_MAC_MIB_COUNTERS_2, mvAsicReg_PON_MAC_MIB_COUNTERS_3,
+    mvAsicReg_PON_MAC_MIB_COUNTERS_4, mvAsicReg_PON_MAC_MIB_COUNTERS_5, mvAsicReg_PON_MAC_MIB_COUNTERS_6, mvAsicReg_PON_MAC_MIB_COUNTERS_7
+  };
+
+  for (indx = 0; indx < MAX_SUPPORTED_GEMPORTS_FOR_PM; indx++)
+  {
+    apiGemPortPmConfig = &apiGemPortPmConfigDb.apiGemPortPmConfigAra[indx];
+    if (apiGemPortPmConfig->in_use == MV_TRUE && apiGemPortPmConfig->gem_port == gemPort)
+    {
+      baseCounterReg = registersAra[apiGemPortPmConfig->counter_set];
+      tgtApiGemPortPmConfig = apiGemPortPmConfig;
+      break;
+    }
+  }
+
+  if (tgtApiGemPortPmConfig != 0)
+  {
+//    printk("%s: gemPort %d, counterSet %d, baseCounterReg %d\n",
+//           __FUNCTION__, tgtApiGemPortPmConfig->gem_port, tgtApiGemPortPmConfig->counter_set, baseCounterReg);
+
+    // Read PM MIB Counters from counter_set (indx)
+
+    // 64 bit counter treatment: read the low part first, to lock the high part
+    rcode |= asicOntMiscRegRead(baseCounterReg, &lowvalue, ONU_GPON_MIB_PM_GoodOctetsReceived_low );
+    rcode |= asicOntMiscRegRead(baseCounterReg, &hivalue,  ONU_GPON_MIB_PM_GoodOctetsReceived_high);
+    gemPortMibCounters->good_octets_received = (uint64_t) hivalue << 32 | lowvalue;
+
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->bad_octets_received,       ONU_GPON_MIB_PM_BadOctetsReceived);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->mac_trans_error,           ONU_GPON_MIB_PM_MACTransError);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->good_frames_received,      ONU_GPON_MIB_PM_GoodFramesReceived);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->bad_frames_received,       ONU_GPON_MIB_PM_BadFramesReceived);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->broadcast_frames_received, ONU_GPON_MIB_PM_BroadcastFramesReceived);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->multicast_frames_received, ONU_GPON_MIB_PM_MulticastFramesReceived);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->frames_64_octets,          ONU_GPON_MIB_PM_Frames64Octets);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->frames_65_to_127_octets,   ONU_GPON_MIB_PM_Frames65to127Octets);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->frames_128_to_255octets,   ONU_GPON_MIB_PM_Frames128to255Octets);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->frames_256_to_511_octets,  ONU_GPON_MIB_PM_Frames256to511Octets);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->frames_512_to_1023_octets, ONU_GPON_MIB_PM_Frames512to1023Octets);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->frames_1024_to_max_octets, ONU_GPON_MIB_PM_Frames1024toMaxOctets);
+
+    // 64 bit counter treatment: read the low part first, to lock the high part
+    rcode |= asicOntMiscRegRead(baseCounterReg, &lowvalue, ONU_GPON_MIB_PM_GoodOctetsSent_low);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &hivalue,  ONU_GPON_MIB_PM_GoodOctetsSent_high);
+    gemPortMibCounters->good_octets_sent = (uint64_t) hivalue << 32 | lowvalue;
+
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->good_frames_sent, ONU_GPON_MIB_PM_GoodFramesSent);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->multicast_frames_sent, ONU_GPON_MIB_PM_MulticastFramesSent);
+    rcode |= asicOntMiscRegRead(baseCounterReg, &gemPortMibCounters->broadcast_frames_sent, ONU_GPON_MIB_PM_BroadcastFramesSent);
+
+    if (rcode != MV_OK)
+    {
+      printk("%s: asicOntMiscRegRead failure, rcode = %d, baseCounterReg = %d\n", __FUNCTION__, rcode, baseCounterReg);
+    }
+  }
+  else
+  {
+    printk("%s: gemPort %d not in table\n", __FUNCTION__, gemPort);
+    return MV_NOT_FOUND;
+  }
+
+  return rcode;
+}
+
+/*******************************************************************************
+**
+**  onuGponPmGemPortPmConfigGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns configured GEM port data
+**
+**  PARAMETERS:  Index in the GEM port DB
+**
+**  OUTPUTS:     S_apiGemPortPmConfig
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponPmGemPortPmConfigGet(MV_U16 dbIdx, S_apiGemPortPmConfig *gemPortPmConfig)
+{
+  memset (gemPortPmConfig, 0, sizeof(S_apiGemPortPmConfig));
+
+  if ( dbIdx >= MAX_SUPPORTED_GEMPORTS_FOR_PM )
+  {
+      printk("%s: Invalid index = %d\n", __FUNCTION__, dbIdx);
+      return MV_OUT_OF_RANGE;
+  }
+
+  if ( apiGemPortPmConfigDb.apiGemPortPmConfigAra[dbIdx].in_use == MV_FALSE )
+      return MV_GET_ERROR;
+
+  memcpy (gemPortPmConfig, &apiGemPortPmConfigDb.apiGemPortPmConfigAra[dbIdx], sizeof(S_apiGemPortPmConfig));
+
+  return MV_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuPm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuPm.h
new file mode 100755
index 0000000..80f50fa
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuPm.h
@@ -0,0 +1,282 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuPm.h                                                **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Alarm and Statistics           **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_PM_H

+#define _ONU_GPON_PM_H

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+#ifdef MV_GPON_PERFORMANCE_CHECK

+typedef enum

+{

+  PON_ISR_PERFORMANCE              = 0, 

+  PON_MNG1_PERFORMANCE             = 1,  

+  PON_MNG2_PERFORMANCE             = 2,

+  PON_MNG3_PERFORMANCE             = 3,

+  PON_EXT_BURST_PLOAM_PERFORMANCE  = 4,

+  PON_KEY_SWITCH_PLOAM_PERFORMANCE = 5,

+  PON_CFG_PORT_PLOAM_PERFORMANCE   = 6,

+  PON_REQ_KEY_PLOAM_PERFORMANCE    = 7,

+  PON_ALLOC_ID_PLOAM_PERFORMANCE   = 8,

+  PON_PASS_PLOAM_PERFORMANCE       = 9,

+  PON_ENC_PORT_PLOAM_PERFORMANCE   = 10,

+  PON_DIS_PLOAM_PERFORMANCE        = 11,

+  PON_DACT_PLOAM_PERFORMANCE       = 12,

+  PON_RNG_PLOAM_PERFORMANCE        = 13,

+  PON_ONU_ID_PLOAM_PERFORMANCE     = 14,

+  PON_OVERHEAD_PLOAM_PERFORMANCE   = 15,

+  PON_MAX_PERFORMANCE              = 16

+}E_GponPerformanceCheck;

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef struct

+{

+  MV_U32 rxMsgIdPloamCounter [ONU_GPON_DS_MSG_LAST+1];

+  MV_U32 rxMsgTotalPloamCounter;

+  MV_U32 txErrMsgIdPloamCounter [ONU_GPON_US_MSG_LAST+1];

+  MV_U32 txMsgIdPloamCounter[ONU_GPON_US_MSG_LAST+1];

+  MV_U32 txMsgTotalPloamCounter;

+}S_PloamSwPm;

+

+typedef struct

+{

+  MV_U32 idlePloamCounter;

+  MV_U32 crcErrorPloamCounter;

+  MV_U32 fifoOverErrorPloamCounter;

+  MV_U32 receivedBroadcastPloamCounter;

+  MV_U32 receivedOnuIdPloamCounter;

+  MV_U32 rxMsgIdPloamCounter [ONU_GPON_DS_MSG_LAST+1];

+  MV_U32 rxMsgTotalPloamCounter;

+}S_RxPloamPm;

+

+typedef struct

+{

+  MV_U32 txErrMsgIdPloamCounter [ONU_GPON_US_MSG_LAST+1];

+  MV_U32 txMsgIdPloamCounter    [ONU_GPON_US_MSG_LAST+1];

+  MV_U32 txMsgTotalPloamCounter;

+}S_TxPloamPm;

+

+typedef struct                                       

+{

+  MV_U32 allocCrcErr;

+  MV_U32 allocCorrectableCrcErr;

+  MV_U32 allocUnCorrectableCrcErr;

+  MV_U32 allocCorrec;

+  MV_U32 totalReceivedAllocBytes;

+}S_RxBwMapPm;

+

+typedef struct

+{

+  MV_U32 receivedBytes;

+  MV_U32 correctedBytes;

+  MV_U32 correctedBits;

+  MV_U32 receivedCodeWords;

+  MV_U32 uncorrectedCodeWords;

+}S_RxFecPm;

+

+typedef struct

+{

+  MV_U32 plend;

+}S_RxPlendPm;

+

+typedef struct

+{

+  MV_U32 bip8;

+}S_RxBip8Pm;

+

+typedef struct

+{

+  MV_U32 receivedIdleGemFrames;

+  MV_U32 receivedValidGemFrames;

+  MV_U32 receivedUndefinedGemFrames;

+  MV_U32 receivedOmciFrames;

+  MV_U32 droppedGemFrames;

+  MV_U32 droppedOmciFrames;

+  MV_U32 receivedGemFramesWithUncorrHecErr;

+  MV_U32 receivedGemFramesWithOneFixedHecErr;

+  MV_U32 receivedGemFramesWithTwoFixedHecErr;

+  MV_U32 totalByteCountOfReceivedValidGemFrames;

+  MV_U32 totalByteCountOfReceivedUndefinedGemFrames;

+  MV_U32 gemReassembleMemoryFlush;

+  MV_U32 gemSynchLost;

+  MV_U32 receivedEthFramesWithCorrFcs;

+  MV_U32 receivedEthFramesWithFcsError;

+  MV_U32 receivedOmciFramesWithCorrCrc;

+  MV_U32 receivedOmciFramesWithCrcError;

+}S_GemPm;

+

+typedef struct

+{

+  MV_U32 transmittedGemPtiTypeOneFrames;   

+  MV_U32 transmittedGemPtiTypeZeroFrames;  

+  MV_U32 transmittedIdleGemFrames;         

+  MV_U32 transmittedTxEnableCount;         

+  MV_U32 transmittedEthFramesViaTconti[ONU_GPON_MAX_NUM_OF_T_CONTS];    

+  MV_U32 transmittedEthBytesViaTconti[ONU_GPON_MAX_NUM_OF_T_CONTS];     

+  MV_U32 transmittedGemFramesViaTconti[ONU_GPON_MAX_NUM_OF_T_CONTS];     

+  MV_U32 transmittedIdleGemFramesViaTconti[ONU_GPON_MAX_NUM_OF_T_CONTS];

+}S_GponTxPm;

+

+typedef struct

+{

+  S_RxBwMapPm rxBwMap;

+  S_RxPloamPm rxPloam;

+  S_TxPloamPm txPloam;

+  S_RxPlendPm rxPlend;

+  S_RxFecPm   rxFec;

+  S_RxBip8Pm  rxBip8;

+  S_GemPm     gem;

+  S_GponTxPm  tx;

+}S_GponPm;

+

+#ifdef MV_GPON_PERFORMANCE_CHECK

+typedef struct

+{

+  MV_U32 *uSecCntStart;

+  MV_U32 *uSecCntStop;

+  MV_U32  uSecCntIdx;

+}S_GponPerformanceCheckNode;

+

+typedef struct

+{

+  S_GponPerformanceCheckNode pmCheckNode[PON_MAX_PERFORMANCE];

+}S_GponPerformanceCheck;

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+

+typedef struct

+{

+  MV_BOOL in_use;

+  MV_U16  gem_port;

+  MV_U32  counter_set;

+}S_apiGemPortPmConfig;

+

+#define MAX_SUPPORTED_GEMPORTS_FOR_PM           8

+#define MAX_ENTRIES_GEMPORTPM_CONFIG_DB         32

+typedef struct

+{

+  S_apiGemPortPmConfig apiGemPortPmConfigAra[MAX_ENTRIES_GEMPORTPM_CONFIG_DB];

+  MV_U32               origRxMibDefaultReg;

+}S_apiGemPortPmConfigDb;

+

+

+

+/* Global variables

+------------------------------------------------------------------------------*/

+#ifdef MV_GPON_PERFORMANCE_CHECK

+extern S_GponPerformanceCheck g_GponPmCheck;

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+

+/* Global functions

+------------------------------------------------------------------------------*/

+#ifdef MV_GPON_PERFORMANCE_CHECK

+MV_STATUS onuGponPmInit(void);

+#endif /* MV_GPON_PERFORMANCE_CHECK */

+void      onuGponPmInPmInit(void);

+void      onuGponPmTimerPmHndl(unsigned long data);

+void      onuGponPmTimerExpireHndl(void);

+MV_STATUS onuGponPmCountersAdd(void);

+MV_STATUS onuGponPmRxSwCountersAdd(MV_U8 a_msgId);

+MV_STATUS onuGponPmSwCountersUpdate(S_RxPloamPm *rxPloamPm, S_TxPloamPm *txPloamPm);

+MV_STATUS onuGponPmFecPmGet(S_RxFecPm *fecPm);

+MV_STATUS onuGponPmRxPloamPmGet(S_RxPloamPm *rxPloamPm);

+MV_STATUS onuGponPmTxPloamPmGet(S_TxPloamPm *txPloamPm);

+MV_STATUS onuGponPmRxBwMapPmGet(S_RxBwMapPm *rxBwMapPm);

+MV_STATUS onuGponPmRxBwMapCountersAdd(void);

+MV_STATUS onuGponPmRxPlendPmGet(S_RxPlendPm *rxPlendPm);

+MV_STATUS onuGponPmRxBip8PmGet(S_RxBip8Pm *rxBip8Pm);

+MV_STATUS onuGponPmGemPmGet(S_GemPm *gemPm);

+MV_STATUS onuGponPmTxPmGet(S_GponTxPm *txPm);

+MV_STATUS onuGponPmTxBurstEnCntGet(unsigned int *txBurstEnCnt);

+

+MV_STATUS onuGponPmGemPortPmStart(MV_U16 gemPort);

+MV_STATUS onuGponPmGemPortPmStop (MV_U16 gemPort);

+MV_STATUS onuGponPmGemPortPmGet  (MV_U16 gemPort, S_GponIoctlGemPortMibCounters *gemPortMibCounters);

+MV_STATUS onuGponPmGemPortPmReset(void);

+void      onuGponPmGemPortPmInit (void);

+MV_STATUS onuGponPmGemPortPmConfigGet(MV_U16 dbIdx, S_apiGemPortPmConfig *gemPortPmConfig);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_PM_H */

+  

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.c
new file mode 100755
index 0000000..654bd6d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.c
@@ -0,0 +1,1078 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuSrvc.c                                              **

+**                                                                           **

+**  DESCRIPTION : This file implements ONU GPON Service Routines             **

+**                functionality                                              **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "gponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/  

+#define __FILE_DESC__ "mv_pon/core/gpon/gponOnuSrvc.c"

+

+#define POLYNOMIAL (0x04c11db7)

+

+static unsigned long crc_table[256];

+MV_U32 randomInternalDelayKey[5] = {0,0,0,0,0};

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+S_DbrBlockSize gponDbrArray[2048];

+MV_U32         gponDbrBlock2048AndMore;

+

+extern u8      mvMacAddr[CONFIG_MV_ETH_PORTS_NUM][MV_MAC_ADDR_SIZE];

+

+MV_U32  randomCode = 0;

+MV_U32  randomType = 0;

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+  

+/* Export Functions

+------------------------------------------------------------------------------*/

+MV_STATUS     onuGponSrvcGenCrcTable(void);

+unsigned long onuGponSrvcUpdateCrc(unsigned long crc_accum, char *data_blk_ptr, int data_blk_size);

+MV_STATUS     onuGponSrvcGenDbrTable(void);

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+

+/*******************************************************************************

+**

+**  onuGponSrvcInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function init onu CRC generator

+**               

+**  PARAMETERS:  None 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK 

+**

+*******************************************************************************/

+MV_STATUS onuGponSrvcInit(void)

+{

+  MV_STATUS rcode;

+

+  rcode = onuGponSrvcGenDbrTable();

+  if (rcode != MV_OK) 

+    return(MV_ERROR);

+

+  rcode = onuGponSrvcGenCrcTable();

+  if (rcode != MV_OK) 

+    return(MV_ERROR);

+

+  return (MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcGenCrcTable

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function generate the table of CRC remainders 

+**               for all possible bytes 

+**               

+**  PARAMETERS:  None  

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+MV_STATUS onuGponSrvcGenCrcTable(void)

+{ 

+  register int           i, j;  

+  register unsigned long crc_accum;

+

+  for ( i = 0;  i < 256;  i++ )

+  { 

+    crc_accum = ( (unsigned long) i << 24 );

+    for ( j = 0;  j < 8;  j++ )

+    { 

+      if ( crc_accum & 0x80000000 )

+      {

+        crc_accum = ( crc_accum << 1 ) ^ POLYNOMIAL;

+      }

+      else

+      {

+        crc_accum = ( crc_accum << 1 ); 

+      }

+    }

+    crc_table[i] = crc_accum; 

+  } 

+

+  return(MV_OK); 

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcUpdateCrc

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function CRC table 

+**               

+** 	PARAMETERS:  unsigned long crc_accum

+** 				 char          *data_blk_ptr

+**				 int           data_blk_size  

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+unsigned long onuGponSrvcUpdateCrc(unsigned long crc_accum, char *data_blk_ptr, int data_blk_size)

+{ 

+   register int i, j;

+   

+   for ( j = 0;  j < data_blk_size;  j++ )

+   { 

+     i = ( (int) ( crc_accum >> 24) ^ *data_blk_ptr++ ) & 0xff;

+     crc_accum = ( crc_accum << 8 ) ^ crc_table[i]; 

+   }

+

+   return (crc_accum ^ 0xFFFFFFFF); 

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcCalcCrc

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function calc CRC

+**               

+** 	PARAMETERS:  unsigned long crc_accum

+** 				 char          *data_blk_ptr

+**				 int           data_blk_size  

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+unsigned int onuGponSrvcCalcCrc(unsigned char msg[], int size)

+{ 

+   unsigned char data;

+   unsigned int idx;

+   unsigned int calcCrc = 0;

+   

+   for (idx = 0;  idx < size;  idx++)

+   { 

+     data    = (unsigned char)((msg[idx]) ^ (calcCrc >> 24));

+     calcCrc = ((crc_table[data]) ^ (calcCrc << 8)); 

+   }

+

+   return (calcCrc); 

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcSerialNumberSet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function set SN in database and GPON MAC 

+**               

+**  PARAMETERS:  MV_U8 *serialNumber 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error 

+**

+*******************************************************************************/

+MV_STATUS onuGponSrvcSerialNumberSet(MV_U8 *serialNumber)

+{

+  MV_STATUS rcode;

+  MV_U32	 snMsg[ONU_GPON_MSG_LEN];

+  MV_U32    onuId;

+

+  /* Update Serial Number In Data Base */

+  /* --------------------------------- */

+  rcode = onuGponDbSerialNumSet((MV_U8*)serialNumber);

+  if (rcode != MV_OK) 

+	return (rcode);

+

+  /* Get Serial Number Message from Database */

+  onuGponDbSnMsgGet(snMsg);

+

+  /* Update the Serial Number in S/N Message */

+  snMsg[0] = (snMsg[0] & 0xFFFF0000) |

+             (((MV_U32)(serialNumber[1])) | 

+              (((MV_U32)(serialNumber[0])) << 8));

+  snMsg[1] = (((MV_U32)(serialNumber[5])) | 

+              (((MV_U32)(serialNumber[4])) << 8) |

+              (((MV_U32)(serialNumber[3])) << 16)|

+							(((MV_U32)(serialNumber[2])) << 24));

+  snMsg[2] = ((((MV_U32)(serialNumber[7])) << 16) | 

+              (((MV_U32)(serialNumber[6])) << 24) |

+                         0x00000505);

+

+  /* Put back the updated Serial Number Message to Database */

+  onuGponDbSnMsgSet(snMsg);

+

+  /* Update Serial Number in ASIC */

+  /* ---------------------------- */

+  onuId = onuGponDbOnuIdGet();

+	

+  rcode = mvOnuGponMacTxConstSerialNumberMsgSet(onuId,serialNumber,0);

+

+  if (rcode != MV_OK) 

+    return (rcode);

+

+  return (MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcConstPloamFromDbInit

+**  ____________________________________________________________________________

+**

+** 	DESCRIPTION: The function initialize the Constant Ploams in ASIC

+**	  			 by values are in Database 

+**               

+**  PARAMETERS:  MV_BOOL initTime 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error  

+**

+*******************************************************************************/

+MV_STATUS onuGponSrvcConstPloamFromDbInit(MV_BOOL initTime)

+{

+  MV_U32    onuId;

+  MV_U8     serialNumber[8];

+  MV_STATUS rcode;

+

+  if (initTime != MV_FALSE)	/* In init time we wouldn't want to use semaphore */

+  {

+	  onuId = onuGponDbOnuIdGet();

+      onuGponDbSerialNumGet(serialNumber);

+     

+      rcode  = mvOnuGponMacTxConstIdleMsgSet(onuId);

+      rcode |= mvOnuGponMacTxConstSerialNumberMsgSet(onuId, serialNumber,0);

+

+      return (rcode);

+  }

+

+  onuId = onuGponDbOnuIdGet();

+  onuGponDbSerialNumGet(serialNumber);

+

+  rcode  = mvOnuGponMacTxConstIdleMsgSet(onuId);

+  rcode |= mvOnuGponMacTxConstSerialNumberMsgSet(onuId, serialNumber,0);

+

+  return (rcode);

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcOnuIdUpdate

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function update the ONU ID in the ASIC register and 

+**               const ram

+**               

+**  PARAMETERS:  MV_U32 onuId

+**

+**  OUTPUTS:     None    

+**

+**  RETURNS:     MV_OK or error  

+**

+*******************************************************************************/

+MV_STATUS onuGponSrvcOnuIdUpdate(MV_U32 onuId, MV_BOOL valid)

+{

+  MV_STATUS rcode;

+  MV_U32	snMsg[ONU_GPON_MSG_LEN];

+  MV_U32	idleMsg[ONU_GPON_MSG_LEN];

+  MV_U8     serialNumber[8];

+

+  /* update onu Id register */

+  rcode = mvOnuGponMacOnuIdSet (onuId, valid); 

+  if (rcode != MV_OK) return (rcode);

+

+  /* Get Serial Number Message from Database */

+  onuGponDbSnMsgGet(snMsg);

+

+  /* Update the Serial Number in S/N Message */

+  snMsg[0] = (ONU_GPON_US_MSG_SN_ONU << 16) | (onuId << 24) |

+             (snMsg[0] & 0x0000FFFF);

+

+  /* Put back the updated Serial Number Message to Database */

+  onuGponDbSnMsgSet(snMsg);

+	

+  /* Get Idle Message from Database */

+  onuGponDbIdleMsgGet(idleMsg);

+

+  /* Update the Serial Number in S/N Message */

+  idleMsg[0] = (ONU_GPON_US_MSG_NO_MESSAGE << 16) | (onuId << 24) |

+               (idleMsg[0] & 0x0000FFFF);

+  /* Put back the updated Serial Number Message to Database */

+  onuGponDbIdleMsgSet(idleMsg);

+

+  onuGponDbSerialNumGet(serialNumber);

+

+  /* Write to ASIC the new Constant Messages */

+  rcode  = mvOnuGponMacTxConstIdleMsgSet(onuId);

+  rcode |= mvOnuGponMacTxConstSerialNumberMsgSet(onuId, serialNumber,0);

+

+  return(rcode);

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcAlarmNotify

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function call Alarm Notification routine (if exist)

+**               

+** 	PARAMETERS:  MV_U32 alarm

+**	             MV_U32 status 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponSrvcAlarmNotify(MV_U32 alarm, MV_U32 status)

+{

+  ALARMNOTIFYFUNC alarmFunc;     

+

+  alarmFunc = onuGponDbAlarmNotifyGet();

+  if (alarmFunc != NULL)

+  {

+	  alarmFunc(alarm, status);

+  }

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcStatusNotify

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function call Status Notification routine (if exist)

+**               

+**  PARAMETERS:  MV_U32 status 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponSrvcStatusNotify(MV_U32 status)

+{

+  STATUSNOTIFYFUNC statusFunc = NULL; 

+

+  /* Send signal to management layer ONLY for US sync */

+  if (status != GPON_ONU_STATUS_RANGED)

+    return;

+

+  statusFunc = onuGponDbStatusNotifyGet();

+  if (statusFunc != NULL)

+  {

+	  statusFunc(status);

+  }

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcOmccNotify

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function call OMCC Port Notification routine (if exist)

+**               

+**  PARAMETERS:  MV_U32 omccPortId 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponSrvcOmccNotify(MV_U32 omccPortId)

+{

+  OMCCNOTIFYFUNC omccFunc;   

+

+  omccFunc = onuGponDbOmccNotifyGet();

+  if (omccFunc != NULL)

+  {

+	  omccFunc(omccPortId);

+  }

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcDisableMsgNotify

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function call onu dusable Notification routine (if exist)

+**               

+**  PARAMETERS:  MV_BOOL disable 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponSrvcDisableMsgNotify(MV_BOOL disable)

+{

+  DISABLENOTIFYFUNC	disableFunc;   

+

+  disableFunc = onuGponDbDisableNotifyGet();

+  if (disableFunc != NULL)

+  {

+	  disableFunc(disable);

+  }

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcAesKeyGenerate

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function generates AES key

+**               

+**  PARAMETERS:  MV_U8 *key 

+**

+**  OUTPUTS:     8 bytes buffer

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+void onuGponSrvcAesKeyGenerate(MV_U8 *key)

+{

+  MV_U32        aesKey[4] = {0x00000000,0x00000000,0x00000000,0x00000000};

+  MV_U32        i;

+  MV_U32        j;

+  static MV_U32 counter = 0;

+  MV_U32        microSec;

+  MV_U32        microSec_1;

+  MV_U32        advancer;

+  MV_U32        bw;

+  MV_U32        sfc;

+

+  mvOnuGponMacMicroSecCounterGet(&microSec);

+  mvOnuGponMacTxPloamDataFreeGet(&advancer);

+  mvOnuGponMacMicroSecCounterGet(&microSec_1);

+  microSec_1 += 0x11111111;

+  bw = 0xA5A5A5A5;

+  mvOnuGponMacRxSuperFrameCounterGet(&sfc);

+  bw ^= sfc;

+

+  for (i = 0 ; i < 8 ; i++)

+  {

+    aesKey[0] |= (MV_U32)((microSec >> i)   & 0x1) << (4*i);

+    aesKey[0] |= (MV_U32)((bw >> i)         & 0x1) << (4*i + 1);

+    aesKey[0] |= (MV_U32)((counter >> i)    & 0x1) << (4*i + 2);

+    aesKey[0] |= (MV_U32)((microSec_1 >> i) & 0x1) << (4*i + 3);

+  }              

+  for (i = 8 ; i < 16 ; i++)

+  {

+    aesKey[1] |= (MV_U32)((microSec >> i)   & 0x1) << (4*(i-8));

+    aesKey[1] |= (MV_U32)((bw >> i)         & 0x1) << (4*(i-8) + 1);

+    aesKey[1] |= (MV_U32)((counter >> i)    & 0x1) << (4*(i-8) + 2);

+    aesKey[1] |= (MV_U32)((microSec_1 >> i) & 0x1) << (4*(i-8) + 3);

+  }

+  for (i = 16 ; i < 24 ; i++)

+  {

+    aesKey[2] |= (MV_U32)((microSec >> i)   & 0x1) << (4*(i-16));

+    aesKey[2] |= (MV_U32)((bw >> i)         & 0x1) << (4*(i-16) + 1);

+    aesKey[2] |= (MV_U32)((counter >> i)    & 0x1) << (4*(i-16) + 2);

+    aesKey[2] |= (MV_U32)((microSec_1 >> i) & 0x1) << (4*(i-16) + 3);

+  }

+  for (i = 24 ; i < 32 ; i++)

+  {

+    aesKey[3] |= (MV_U32)((microSec >> i)   & 0x1) << (4*(i-24));

+    aesKey[3] |= (MV_U32)((bw >> i)         & 0x1) << (4*(i-24) + 1);

+    aesKey[3] |= (MV_U32)((counter >> i)    & 0x1) << (4*(i-24) + 2);

+    aesKey[3] |= (MV_U32)((microSec_1 >> i) & 0x1) << (4*(i-24) + 3);

+  }

+

+  counter += advancer;

+

+  for (i = 0 ; i < 4 ; i++)

+  {

+    for (j = 0 ; j < 4 ; j++)

+    {

+      key[(j * 4) + i] = (MV_U8)((aesKey[j] >> (8 * (3 - i))) & 0xFF);

+    }

+  }

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcGenDbrTable

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function init onu DBR table

+**               

+**  PARAMETERS:  None 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK 

+**

+*******************************************************************************/

+MV_STATUS onuGponSrvcGenDbrTable(void)

+{

+  MV_U32 index;

+

+/*  DBR table for all block size supported - NOT sorted 

+    ===================================================

+    

+    Config 	1/512	1/256	1/128	1/64	1/32	1/16	SUM	    1/SUM	    (1/SUM) * 4	 Block Size

+    0	    0.0000	0.0000	0.0000	0.0000	0.0000	0.0000	0.0000	0.0000      0.0000       0

+    000001	0.0000	0.0000	0.0000	0.0000	0.0000	0.0625	0.0625	16.0000  	64.0000      64

+    000010	0.0000	0.0000	0.0000	0.0000	0.0313	0.0000	0.0313	32.0000  	128.0000     128

+    000011	0.0000	0.0000	0.0000	0.0000	0.0313	0.0625	0.0938	10.6667  	42.6667	     43

+    000100	0.0000	0.0000	0.0000	0.0156	0.0000	0.0000	0.0156	64.0000  	256.0000     256

+    000101	0.0000	0.0000	0.0000	0.0156	0.0000	0.0625	0.0781	12.8000  	51.2000      51

+    000110	0.0000	0.0000	0.0000	0.0156	0.0313	0.0000	0.0469	21.3333  	85.3333      85

+    000111	0.0000	0.0000	0.0000	0.0156	0.0313	0.0625	0.1094	9.1429      36.5714      37

+    001000	0.0000	0.0000	0.0078	0.0000	0.0000	0.0000	0.0078	128.0000	512.0000     512

+    001001	0.0000	0.0000	0.0078	0.0000	0.0000	0.0625	0.0703	14.2222  	56.8889	     57

+    001010	0.0000	0.0000	0.0078	0.0000	0.0313	0.0000	0.0391	25.6000  	102.4000     102

+    001011	0.0000	0.0000	0.0078	0.0000	0.0313	0.0625	0.1016	9.8462      39.3846	     39

+    001100	0.0000	0.0000	0.0078	0.0156	0.0000	0.0000	0.0234	42.6667  	170.6667     171

+    001101	0.0000	0.0000	0.0078	0.0156	0.0000	0.0625	0.0859	11.6364  	46.5455      47

+    001110	0.0000	0.0000	0.0078	0.0156	0.0313	0.0000	0.0547	18.2857  	73.1429      73

+    001111	0.0000	0.0000	0.0078	0.0156	0.0313	0.0625	0.1172	8.5333      34.1333      34

+    010000	0.0000	0.0039	0.0000	0.0000	0.0000	0.0000	0.0039	256.0000	1024.0000    1024

+    010001	0.0000	0.0039	0.0000	0.0000	0.0000	0.0625	0.0664	15.0588  	60.2353	     60

+    010010	0.0000	0.0039	0.0000	0.0000	0.0313	0.0000	0.0352	28.4444  	113.7778     114

+    010011	0.0000	0.0039	0.0000	0.0000	0.0313	0.0625	0.0977	10.2400  	40.9600	     41

+    010100	0.0000	0.0039	0.0000	0.0156	0.0000	0.0000	0.0195	51.2000  	204.8000     205

+    010101	0.0000	0.0039	0.0000	0.0156	0.0000	0.0625	0.0820	12.1905  	48.7619      49

+    010110	0.0000	0.0039	0.0000	0.0156	0.0313	0.0000	0.0508	19.6923  	78.7692      79

+    010111	0.0000	0.0039	0.0000	0.0156	0.0313	0.0625	0.1133	8.8276      35.3103      35

+    011000	0.0000	0.0039	0.0078	0.0000	0.0000	0.0000	0.0117	85.3333  	341.3333     341

+    011001	0.0000	0.0039	0.0078	0.0000	0.0000	0.0625	0.0742	13.4737  	53.8947      54

+    011010	0.0000	0.0039	0.0078	0.0000	0.0313	0.0000	0.0430	23.2727  	93.0909      93

+    011011	0.0000	0.0039	0.0078	0.0000	0.0313	0.0625	0.1055	9.4815      37.9259      38

+    011100	0.0000	0.0039	0.0078	0.0156	0.0000	0.0000	0.0273	36.5714  	146.2857     146

+    011101	0.0000	0.0039	0.0078	0.0156	0.0000	0.0625	0.0898	11.1304  	44.5217      45

+    011110	0.0000	0.0039	0.0078	0.0156	0.0313	0.0000	0.0586	17.0667  	68.2667      68

+    011111	0.0000	0.0039	0.0078	0.0156	0.0313	0.0625	0.1211	8.2581      33.0323      33

+    100000	0.0020	0.0000	0.0000	0.0000	0.0000	0.0000	0.0020	512.0000	2048.0000    2048

+    100001	0.0020	0.0000	0.0000	0.0000	0.0000	0.0625	0.0645	15.5152  	62.0606	     62

+    100010	0.0020	0.0000	0.0000	0.0000	0.0313	0.0000	0.0332	30.1176  	120.4706     120

+    100011	0.0020	0.0000	0.0000	0.0000	0.0313	0.0625	0.0957	10.4490  	41.7959      42

+    100100	0.0020	0.0000	0.0000	0.0156	0.0000	0.0000	0.0176	56.8889  	227.5556     228

+    100101	0.0020	0.0000	0.0000	0.0156	0.0000	0.0625	0.0801	12.4878  	49.9512      50

+    100110	0.0020	0.0000	0.0000	0.0156	0.0313	0.0000	0.0488	20.4800  	81.9200      82

+    100111	0.0020	0.0000	0.0000	0.0156	0.0313	0.0625	0.1113	8.9825      35.9298      36

+    101000	0.0020	0.0000	0.0078	0.0000	0.0000	0.0000	0.0098	102.4000	409.6000     410

+    101001	0.0020	0.0000	0.0078	0.0000	0.0000	0.0625	0.0723	13.8378  	55.3514      55

+    101010	0.0020	0.0000	0.0078	0.0000	0.0313	0.0000	0.0410	24.3810  	97.5238      98

+    101011	0.0020	0.0000	0.0078	0.0000	0.0313	0.0625	0.1035	9.6604      38.6415      39

+    101100	0.0020	0.0000	0.0078	0.0156	0.0000	0.0000	0.0254	39.3846  	157.5385     158

+    101101	0.0020	0.0000	0.0078	0.0156	0.0000	0.0625	0.0879	11.3778  	45.5111      46

+    101110	0.0020	0.0000	0.0078	0.0156	0.0313	0.0000	0.0566	17.6552  	70.6207      71

+    101111	0.0020	0.0000	0.0078	0.0156	0.0313	0.0625	0.1191	8.3934      33.5738      34

+    110000	0.0020	0.0039	0.0000	0.0000	0.0000	0.0000	0.0059	170.6667	682.6667     683

+    110001	0.0020	0.0039	0.0000	0.0000	0.0000	0.0625	0.0684	14.6286  	58.5143      59

+    110010	0.0020	0.0039	0.0000	0.0000	0.0313	0.0000	0.0371	26.9474  	107.7895     108

+    110011	0.0020	0.0039	0.0000	0.0000	0.0313	0.0625	0.0996	10.0392  	40.1569      40

+    110100	0.0020	0.0039	0.0000	0.0156	0.0000	0.0000	0.0215	46.5455  	186.1818     186

+    110101	0.0020	0.0039	0.0000	0.0156	0.0000	0.0625	0.0840	11.9070  	47.6279      48

+    110110	0.0020	0.0039	0.0000	0.0156	0.0313	0.0000	0.0527	18.9630  	75.8519      76

+    110111	0.0020	0.0039	0.0000	0.0156	0.0313	0.0625	0.1152	8.6780      34.7119      35

+    111000	0.0020	0.0039	0.0078	0.0000	0.0000	0.0000	0.0137	73.1429  	292.5714     293

+    111001	0.0020	0.0039	0.0078	0.0000	0.0000	0.0625	0.0762	13.1282  	52.5128      53

+    111010	0.0020	0.0039	0.0078	0.0000	0.0313	0.0000	0.0449	22.2609  	89.0435      89

+    111011	0.0020	0.0039	0.0078	0.0000	0.0313	0.0625	0.1074	9.3091      37.2364      37

+    111100	0.0020	0.0039	0.0078	0.0156	0.0000	0.0000	0.0293	34.1333  	136.5333     137

+    111101	0.0020	0.0039	0.0078	0.0156	0.0000	0.0625	0.0918	10.8936  	43.5745      44

+    111110	0.0020	0.0039	0.0078	0.0156	0.0313	0.0000	0.0605	16.5161  	66.0645      66

+    111111	0.0020	0.0039	0.0078	0.0156	0.0313	0.0625	0.1230	8.1270      32.5079      33

+    

+    DBR table for all block size supported - Sorted by Block Size

+    =============================================================

+    

+    Config	1/512	1/256	1/128	1/64	1/32	1/16	SUM	    1/SUM	  (1/SUM) * 4	Block Size

+    0	    0.0000	0.0000	0.0000	0.0000	0.0000	0.0000	0.0000	0.0000    0.0000        0

+    111111	0.0020	0.0039	0.0078	0.0156	0.0313	0.0625	0.1230	8.1270    32.5079    	33

+    011111	0.0000	0.0039	0.0078	0.0156	0.0313	0.0625	0.1211	8.2581    33.0323    	33

+    101111	0.0020	0.0000	0.0078	0.0156	0.0313	0.0625	0.1191	8.3934    33.5738    	34

+    001111	0.0000	0.0000	0.0078	0.0156	0.0313	0.0625	0.1172	8.5333    34.1333    	34

+    110111	0.0020	0.0039	0.0000	0.0156	0.0313	0.0625	0.1152	8.6780    34.7119    	35

+    010111	0.0000	0.0039	0.0000	0.0156	0.0313	0.0625	0.1133	8.8276    35.3103    	35

+    100111	0.0020	0.0000	0.0000	0.0156	0.0313	0.0625	0.1113	8.9825    35.9298    	36

+    000111	0.0000	0.0000	0.0000	0.0156	0.0313	0.0625	0.1094	9.1429    36.5714    	37

+    111011	0.0020	0.0039	0.0078	0.0000	0.0313	0.0625	0.1074	9.3091    37.2364    	37

+    011011	0.0000	0.0039	0.0078	0.0000	0.0313	0.0625	0.1055	9.4815    37.9259    	38

+    101011	0.0020	0.0000	0.0078	0.0000	0.0313	0.0625	0.1035	9.6604    38.6415    	39

+    001011	0.0000	0.0000	0.0078	0.0000	0.0313	0.0625	0.1016	9.8462    39.3846    	39

+    110011	0.0020	0.0039	0.0000	0.0000	0.0313	0.0625	0.0996	10.0392 	40.1569    	40

+    010011	0.0000	0.0039	0.0000	0.0000	0.0313	0.0625	0.0977	10.2400 	40.9600    	41

+    100011	0.0020	0.0000	0.0000	0.0000	0.0313	0.0625	0.0957	10.4490 	41.7959    	42

+    000011	0.0000	0.0000	0.0000	0.0000	0.0313	0.0625	0.0938	10.6667 	42.6667    	43

+    111101	0.0020	0.0039	0.0078	0.0156	0.0000	0.0625	0.0918	10.8936 	43.5745    	44

+    011101	0.0000	0.0039	0.0078	0.0156	0.0000	0.0625	0.0898	11.1304 	44.5217    	45

+    101101	0.0020	0.0000	0.0078	0.0156	0.0000	0.0625	0.0879	11.3778 	45.5111    	46

+    001101	0.0000	0.0000	0.0078	0.0156	0.0000	0.0625	0.0859	11.6364 	46.5455    	47

+    110101	0.0020	0.0039	0.0000	0.0156	0.0000	0.0625	0.0840	11.9070 	47.6279    	48

+    010101	0.0000	0.0039	0.0000	0.0156	0.0000	0.0625	0.0820	12.1905 	48.7619    	49

+    100101	0.0020	0.0000	0.0000	0.0156	0.0000	0.0625	0.0801	12.4878 	49.9512    	50

+    000101	0.0000	0.0000	0.0000	0.0156	0.0000	0.0625	0.0781	12.8000 	51.2000    	51

+    111001	0.0020	0.0039	0.0078	0.0000	0.0000	0.0625	0.0762	13.1282 	52.5128    	53

+    011001	0.0000	0.0039	0.0078	0.0000	0.0000	0.0625	0.0742	13.4737 	53.8947    	54

+    101001	0.0020	0.0000	0.0078	0.0000	0.0000	0.0625	0.0723	13.8378 	55.3514    	55

+    001001	0.0000	0.0000	0.0078	0.0000	0.0000	0.0625	0.0703	14.2222 	56.8889    	57

+    110001	0.0020	0.0039	0.0000	0.0000	0.0000	0.0625	0.0684	14.6286 	58.5143    	59

+    010001	0.0000	0.0039	0.0000	0.0000	0.0000	0.0625	0.0664	15.0588 	60.2353    	60

+    100001	0.0020	0.0000	0.0000	0.0000	0.0000	0.0625	0.0645	15.5152 	62.0606    	62

+    000001	0.0000	0.0000	0.0000	0.0000	0.0000	0.0625	0.0625	16.0000 	64.0000    	64

+    111110	0.0020	0.0039	0.0078	0.0156	0.0313	0.0000	0.0605	16.5161 	66.0645    	66

+    011110	0.0000	0.0039	0.0078	0.0156	0.0313	0.0000	0.0586	17.0667 	68.2667    	68

+    101110	0.0020	0.0000	0.0078	0.0156	0.0313	0.0000	0.0566	17.6552 	70.6207    	71

+    001110	0.0000	0.0000	0.0078	0.0156	0.0313	0.0000	0.0547	18.2857 	73.1429    	73

+    110110	0.0020	0.0039	0.0000	0.0156	0.0313	0.0000	0.0527	18.9630 	75.8519    	76

+    010110	0.0000	0.0039	0.0000	0.0156	0.0313	0.0000	0.0508	19.6923 	78.7692    	79

+    100110	0.0020	0.0000	0.0000	0.0156	0.0313	0.0000	0.0488	20.4800 	81.9200    	82

+    000110	0.0000	0.0000	0.0000	0.0156	0.0313	0.0000	0.0469	21.3333 	85.3333    	85

+    111010	0.0020	0.0039	0.0078	0.0000	0.0313	0.0000	0.0449	22.2609 	89.0435    	89

+    011010	0.0000	0.0039	0.0078	0.0000	0.0313	0.0000	0.0430	23.2727 	93.0909    	93

+    101010	0.0020	0.0000	0.0078	0.0000	0.0313	0.0000	0.0410	24.3810 	97.5238    	98

+    001010	0.0000	0.0000	0.0078	0.0000	0.0313	0.0000	0.0391	25.6000 	102.4000    102

+    110010	0.0020	0.0039	0.0000	0.0000	0.0313	0.0000	0.0371	26.9474 	107.7895    108

+    010010	0.0000	0.0039	0.0000	0.0000	0.0313	0.0000	0.0352	28.4444 	113.7778    114

+    100010	0.0020	0.0000	0.0000	0.0000	0.0313	0.0000	0.0332	30.1176 	120.4706    120

+    000010	0.0000	0.0000	0.0000	0.0000	0.0313	0.0000	0.0313	32.0000 	128.0000    128

+    111100	0.0020	0.0039	0.0078	0.0156	0.0000	0.0000	0.0293	34.1333 	136.5333    137

+    011100	0.0000	0.0039	0.0078	0.0156	0.0000	0.0000	0.0273	36.5714 	146.2857    146

+    101100	0.0020	0.0000	0.0078	0.0156	0.0000	0.0000	0.0254	39.3846 	157.5385    158

+    001100	0.0000	0.0000	0.0078	0.0156	0.0000	0.0000	0.0234	42.6667 	170.6667    171

+    110100	0.0020	0.0039	0.0000	0.0156	0.0000	0.0000	0.0215	46.5455 	186.1818    186

+    010100	0.0000	0.0039	0.0000	0.0156	0.0000	0.0000	0.0195	51.2000 	204.8000    205

+    100100	0.0020	0.0000	0.0000	0.0156	0.0000	0.0000	0.0176	56.8889 	227.5556    228

+    000100	0.0000	0.0000	0.0000	0.0156	0.0000	0.0000	0.0156	64.0000 	256.0000    256

+    111000	0.0020	0.0039	0.0078	0.0000	0.0000	0.0000	0.0137	73.1429 	292.5714    293

+    011000	0.0000	0.0039	0.0078	0.0000	0.0000	0.0000	0.0117	85.3333 	341.3333    341

+    101000	0.0020	0.0000	0.0078	0.0000	0.0000	0.0000	0.0098	102.4000	409.6000    410

+    001000	0.0000	0.0000	0.0078	0.0000	0.0000	0.0000	0.0078	128.0000	512.0000    512

+    110000	0.0020	0.0039	0.0000	0.0000	0.0000	0.0000	0.0059	170.6667	682.6667    683

+    010000	0.0000	0.0039	0.0000	0.0000	0.0000	0.0000	0.0039	256.0000	1024.0000 	1024

+    100000	0.0020	0.0000	0.0000	0.0000	0.0000	0.0000	0.0020	512.0000	2048.0000 	2048

+*/

+

+  for (index = 0; index < 34; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x3F; /*0b111111;*/

+      gponDbrArray[index].blockSize = 33;

+  }

+  gponDbrArray[ 34].bitMask   = 0x2F; /*0b101111;*/

+  gponDbrArray[ 34].blockSize = 34;

+  gponDbrArray[ 35].bitMask   = 0x37; /*0b110111;*/

+  gponDbrArray[ 35].blockSize = 35; 

+  gponDbrArray[ 36].bitMask   = 0x27; /*0b100111;*/

+  gponDbrArray[ 36].blockSize = 36; 

+  gponDbrArray[ 37].bitMask   = 0x07; /*0b000111;*/

+  gponDbrArray[ 37].blockSize = 37; 

+  gponDbrArray[ 38].bitMask   = 0x1B; /*0b011011;*/

+  gponDbrArray[ 38].blockSize = 38; 

+  gponDbrArray[ 39].bitMask   = 0x2B; /*0b101011;*/

+  gponDbrArray[ 39].blockSize = 39; 

+  gponDbrArray[ 40].bitMask   = 0x33; /*0b110011;*/

+  gponDbrArray[ 40].blockSize = 40; 

+  gponDbrArray[ 41].bitMask   = 0x13; /*0b010011;*/

+  gponDbrArray[ 41].blockSize = 41; 

+  gponDbrArray[ 42].bitMask   = 0x23; /*0b100011;*/

+  gponDbrArray[ 42].blockSize = 42; 

+  gponDbrArray[ 43].bitMask   = 0x03; /*0b000011;*/

+  gponDbrArray[ 43].blockSize = 43; 

+  gponDbrArray[ 44].bitMask   = 0x3D; /*0b111101;*/

+  gponDbrArray[ 44].blockSize = 44; 

+  gponDbrArray[ 45].bitMask   = 0x1D; /*0b011101;*/

+  gponDbrArray[ 45].blockSize = 45; 

+  gponDbrArray[ 46].bitMask   = 0x2D; //0b101101; 

+  gponDbrArray[ 46].blockSize = 46; 

+  gponDbrArray[ 47].bitMask   = 0x0D; //0b001101; 

+  gponDbrArray[ 47].blockSize = 47; 

+  gponDbrArray[ 48].bitMask   = 0x35; //0b110101; 

+  gponDbrArray[ 48].blockSize = 48; 

+  gponDbrArray[ 49].bitMask   = 0x15; //0b010101; 

+  gponDbrArray[ 49].blockSize = 49; 

+  gponDbrArray[ 50].bitMask   = 0x25; //0b100101; 

+  gponDbrArray[ 50].blockSize = 50; 

+  gponDbrArray[ 51].bitMask   = 0x05; //0b000101; 

+  gponDbrArray[ 51].blockSize = 51; 

+  gponDbrArray[ 52].bitMask   = 0x05; //0b000101; 

+  gponDbrArray[ 52].blockSize = 51; 

+  gponDbrArray[ 53].bitMask   = 0x39; //0b111001;

+  gponDbrArray[ 53].blockSize = 53; 

+  gponDbrArray[ 54].bitMask   = 0x19; //0b011001;

+  gponDbrArray[ 54].blockSize = 54; 

+  gponDbrArray[ 55].bitMask   = 0x29; //0b101001; 

+  gponDbrArray[ 55].blockSize = 55; 

+  gponDbrArray[ 56].bitMask   = 0x29; //0b101001; 

+  gponDbrArray[ 56].blockSize = 55; 

+  gponDbrArray[ 57].bitMask   = 0x09; //0b001001;

+  gponDbrArray[ 57].blockSize = 57; 

+  gponDbrArray[ 58].bitMask   = 0x09; //0b001001;

+  gponDbrArray[ 58].blockSize = 57; 

+  gponDbrArray[ 59].bitMask   = 0x31; //0b110001; 

+  gponDbrArray[ 59].blockSize = 59; 

+  gponDbrArray[ 60].bitMask   = 0x11; //0b010001; 

+  gponDbrArray[ 60].blockSize = 60; 

+  gponDbrArray[ 61].bitMask   = 0x11; //0b010001; 

+  gponDbrArray[ 61].blockSize = 60; 

+  gponDbrArray[ 62].bitMask   = 0x21; //0b100001; 

+  gponDbrArray[ 62].blockSize = 62; 

+  gponDbrArray[ 63].bitMask   = 0x21; //0b100001; 

+  gponDbrArray[ 63].blockSize = 62; 

+  gponDbrArray[ 64].bitMask   = 0x01; //0b000001; 

+  gponDbrArray[ 64].blockSize = 64; 

+  gponDbrArray[ 65].bitMask   = 0x01; //0b000001;  

+  gponDbrArray[ 65].blockSize = 64;  

+  gponDbrArray[ 66].bitMask   = 0x3E; //0b111110;  

+  gponDbrArray[ 66].blockSize = 66;  

+  gponDbrArray[ 67].bitMask   = 0x3E; //0b111110;  

+  gponDbrArray[ 67].blockSize = 66;  

+  gponDbrArray[ 68].bitMask   = 0x1E; //0b011110;  

+  gponDbrArray[ 68].blockSize = 68;  

+  gponDbrArray[ 69].bitMask   = 0x1E; //0b011110;

+  gponDbrArray[ 69].blockSize = 68;

+  gponDbrArray[ 70].bitMask   = 0x1E; //0b011110;

+  gponDbrArray[ 70].blockSize = 68;

+  gponDbrArray[ 71].bitMask   = 0x2E; //0b101110;

+  gponDbrArray[ 71].blockSize = 71;

+  gponDbrArray[ 72].bitMask   = 0x2E; //0b101110;

+  gponDbrArray[ 72].blockSize = 71;

+

+  for (index = 73; index < 76; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x0E; //0b001110;

+      gponDbrArray[index].blockSize = 73;

+  }

+  for (index = 76; index < 79; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x36; //0b110110;

+      gponDbrArray[index].blockSize = 76;

+  }

+  for (index = 79; index < 82; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x16; //0b010110;

+      gponDbrArray[index].blockSize = 79;

+  }

+  for (index = 82; index < 85; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x26; //0b100110;

+      gponDbrArray[index].blockSize = 82;

+  }

+  for (index = 85; index < 89; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x06; //0b000110;

+      gponDbrArray[index].blockSize = 85;

+  }

+  for (index = 89; index < 93; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x3A; //0b111010;

+      gponDbrArray[index].blockSize = 89;

+  }

+  for (index = 93; index < 98; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x1A; //0b011010;

+      gponDbrArray[index].blockSize = 93;

+  }

+  for (index = 98; index < 102; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x2A; //0b101010;

+      gponDbrArray[index].blockSize = 98;

+  }

+  for (index = 102; index < 108; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x0A; //0b001010;

+      gponDbrArray[index].blockSize = 102;

+  }

+  for (index = 108; index < 114; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x32; //0b110010;

+      gponDbrArray[index].blockSize = 108;

+  }

+  for (index = 114; index < 120; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x12; //0b010010;

+      gponDbrArray[index].blockSize = 114;

+  }

+  for (index = 120; index < 128; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x22; //0b100010;

+      gponDbrArray[index].blockSize = 120;

+  }

+  for (index = 128; index < 137; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x02; //0b000010;

+      gponDbrArray[index].blockSize = 128;

+  }

+  for (index = 137; index < 146; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x3C; //0b111100;

+      gponDbrArray[index].blockSize = 137;

+  }

+  for (index = 137; index < 146; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x3C; //0b111100;

+      gponDbrArray[index].blockSize = 137;

+  }

+  for (index = 146; index < 158; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x1C; //0b011100;

+      gponDbrArray[index].blockSize = 146;

+  }

+  for (index = 158; index < 171; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x2C; //0b101100;

+      gponDbrArray[index].blockSize = 158;

+  }

+  for (index = 171; index < 186; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x0C; //0b001100;

+      gponDbrArray[index].blockSize = 171;

+  }

+  for (index = 186; index < 205; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x34; //0b110100;

+      gponDbrArray[index].blockSize = 186;

+  }

+  for (index = 205; index < 228; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x14; //0b010100;

+      gponDbrArray[index].blockSize = 205;

+  }

+  for (index = 228; index < 256; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x24; //0b100100;

+      gponDbrArray[index].blockSize = 228;

+  }

+  for (index = 256; index < 293; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x04; //0b000100;

+      gponDbrArray[index].blockSize = 256;

+  }

+  for (index = 293; index < 341; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x38; //0b111000;

+      gponDbrArray[index].blockSize = 293;

+  }

+  for (index = 341; index < 410; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x18; //0b011000;

+      gponDbrArray[index].blockSize = 341;

+  }

+  for (index = 410; index < 512; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x28; //0b101000;

+      gponDbrArray[index].blockSize = 410;

+  }

+  for (index = 512; index < 683; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x08; //0b001000;

+      gponDbrArray[index].blockSize = 512;

+  }

+  for (index = 683; index < 1024; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x30; //0b110000;

+      gponDbrArray[index].blockSize = 683;

+  }

+  for (index = 1024; index < 2048; index++)

+  {

+      gponDbrArray[index].bitMask   = 0x10; //0b010000;

+      gponDbrArray[index].blockSize = 1024;

+  }

+

+  gponDbrBlock2048AndMore = 0x20; //0b100000;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponSrvcDbrBlockSizeSet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: The function configure DBR block size

+**               

+**  PARAMETERS:  MV_U32 blockSize 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None 

+**

+*******************************************************************************/

+MV_STATUS onuGponSrvcDbrBlockSizeSet(MV_U32 blockSize, MV_U32 *actualBlockSize)

+{

+  MV_STATUS rcode;

+  MV_U32    macBlockSizeBitMask;

+  MV_U32    macBlockSizeValue;

+

+  if (blockSize >= 2048)

+  {

+    macBlockSizeBitMask = gponDbrBlock2048AndMore;

+    macBlockSizeValue   = 2048;

+  }

+  else

+  {

+    macBlockSizeBitMask = gponDbrArray[blockSize].bitMask;

+    macBlockSizeValue   = gponDbrArray[blockSize].blockSize;

+  }

+

+  rcode = mvOnuGponMacTxDbrBlockSizeSet(macBlockSizeBitMask);

+  if (rcode != MV_OK)

+    return (rcode);

+

+  *actualBlockSize = macBlockSizeValue;

+

+  return (rcode);

+}

+

+

+/*******************************************************************************

+**

+**  onuGponSrvcRangingRandomInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function init onu gpon ranging random number

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error

+**                   

+*******************************************************************************/

+MV_STATUS onuGponSrvcRangingRandomInit(void)

+{

+  MV_U32    thermalRegAddr  = 0x000184D8;

+  MV_U32    thermalRegValue = 0;

+

+  MV_U32    temp            = 0;

+  int       tmp_size;

+

+  /* 0 MAC          */

+  /* 1 Thermal      */

+  /* 2 Micro Timer  */

+  /* 3 Randon Num 1 */

+  /* 4 Randon Num 2 */

+

+  /* Generate internal delay random part */

+  randomInternalDelayKey[0]  =  (mvMacAddr[2][2]);

+  randomInternalDelayKey[0] |= ((mvMacAddr[2][3]) << 8);

+  randomInternalDelayKey[0] |= ((mvMacAddr[2][4]) << 16);

+  randomInternalDelayKey[0] |= ((mvMacAddr[2][5]) << 24);

+

+  mvOsDelay((mvMacAddr[2][2]) + (mvMacAddr[2][3]) + (mvMacAddr[2][4]) + (mvMacAddr[2][5]));

+  thermalRegValue = ((MV_REG_READ(thermalRegAddr) >> 10)  & 0x1FF); 

+  randomInternalDelayKey[1] = thermalRegValue;     

+

+  mvOsDelay((thermalRegValue & 0xFF) + (mvMacAddr[2][4]) + (mvMacAddr[2][5]));

+  mvOnuGponMacMicroSecCounterGet(&temp);

+  randomInternalDelayKey[2] = (temp & 0xFFFF);

+

+  thermalRegValue = ((MV_REG_READ(thermalRegAddr) >> 10)  & 0x1FF);

+  randomInternalDelayKey[1] |= thermalRegValue << 9;    

+

+  mvOsDelay((thermalRegValue & 0xFF) + (mvMacAddr[2][3]));

+  thermalRegValue = ((MV_REG_READ(thermalRegAddr) >> 10)  & 0x1FF);

+  randomInternalDelayKey[1] |= thermalRegValue << 18;   

+

+  mvOsDelay((thermalRegValue & 0xFF) + (mvMacAddr[2][2]));

+  mvOnuGponMacMicroSecCounterGet(&temp);

+  randomInternalDelayKey[3] = (temp & 0xFFFF);

+

+  thermalRegValue = ((MV_REG_READ(thermalRegAddr) >> 10)  & 0x1F);

+  randomInternalDelayKey[1] |= thermalRegValue << 27;

+

+  mvOnuGponMacMicroSecCounterGet(&temp);

+  randomInternalDelayKey[2] |= ((temp & 0xFFFF) << 16);

+

+  mvOsDelay(randomInternalDelayKey[2] & 0xFF);

+  mvOnuGponMacMicroSecCounterGet(&temp);

+  randomInternalDelayKey[4] = (temp & 0xFFFF);

+

+  mvOsDelay((randomInternalDelayKey[1] & 0xFF000) >> 12);

+  mvOnuGponMacMicroSecCounterGet(&temp);

+  randomInternalDelayKey[4] |= (((temp & 0xFFFF00) >> 8) << 16);

+

+  mvOsDelay((randomInternalDelayKey[1] & 0xFF00000) >> 20);

+  mvOnuGponMacMicroSecCounterGet(&temp);

+  randomInternalDelayKey[3] |= (((temp & 0xFFFF000) >> 12) << 16);

+

+  for (tmp_size=0; tmp_size<5; tmp_size++) 

+  {

+    add_input_randomness(randomType, randomCode, randomInternalDelayKey[tmp_size]);

+  }

+

+  return(MV_OK);

+}

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.h
new file mode 100755
index 0000000..839e60c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/core/gpon/gponOnuSrvc.h
@@ -0,0 +1,122 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuSrvc.h                                              **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Services routines              **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_SRVC_H

+#define _ONU_GPON_SRVC_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+  

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef struct

+{

+  MV_U32 bitMask;

+  MV_U32 blockSize;

+}S_DbrBlockSize;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+MV_STATUS     onuGponSrvcInit(void);

+MV_STATUS     onuGponSrvcSerialNumberSet(MV_U8 *serialNumber);

+MV_STATUS     onuGponSrvcConstPloamFromDbInit(MV_BOOL initTime);

+MV_STATUS     onuGponSrvcOnuIdUpdate(MV_U32 onuId, MV_BOOL valid);

+void          onuGponSrvcAlarmNotify(MV_U32 alarm, MV_U32 status);

+void          onuGponSrvcStatusNotify(MV_U32 status);

+void          onuGponSrvcOmccNotify(MV_U32 omccPortId);

+void          onuGponSrvcDisableMsgNotify(MV_BOOL disable);

+unsigned long onuGponSrvcUpdateCrc(unsigned long crc_accum, char *data_blk_ptr, int data_blk_size);

+unsigned int  onuGponSrvcCalcCrc(unsigned char msg[], int size);

+void          onuGponSrvcAesKeyGenerate(MV_U8 *key);

+MV_STATUS     onuGponSrvcDbrBlockSizeSet(MV_U32 blockSize, MV_U32 *actualBlockSize);

+MV_STATUS     onuGponSrvcRangingRandomInit(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_APM_H */

+

+  

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.c
new file mode 100755
index 0000000..d847357
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.c
@@ -0,0 +1,967 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : eponOnuLnxKsMI.c                                           **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON Management Interface         **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include <linux/version.h>
+#include "eponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/perf/epon/eponOnuLnxKsMI.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+extern spinlock_t onuPonIrqLock;
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+
+/*******************************************************************************
+**
+**  onuEponMiInfoGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu info
+**
+**  PARAMETERS:  S_IoctlInfo *info
+**               MV_U32      macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuEponMiInfoGet(S_EponIoctlInfo *info, MV_U32 macId)
+{
+  return(onuEponApiInformationGet(info, macId));
+}
+
+/*******************************************************************************
+**
+**  onuEponMiPm
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu pm info
+**
+**  PARAMETERS:  S_IoctlPm *ioctlPm
+**               MV_U32    macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuEponMiPm(S_EponIoctlPm *ioctlPm, MV_U32 macId)
+{
+  switch (ioctlPm->section)
+  {
+    case E_EPON_IOCTL_PM_RX:
+      return(onuEponApiRxPmGet((&(ioctlPm->rxCnt)), MV_TRUE, 0));
+      break;
+    case E_EPON_IOCTL_PM_TX:
+      return(onuEponApiTxPmGet((&(ioctlPm->txCnt)), MV_TRUE, macId));
+      break;
+    case E_EPON_IOCTL_PM_SW:
+      return(onuEponApiSwPmGet((&(ioctlPm->swCnt)), MV_TRUE, macId));
+      break;
+    case E_EPON_IOCTL_PM_GPM:
+      return(onuEponApiGpmPmGet((&(ioctlPm->gpmCnt)), MV_TRUE, macId));
+      break;
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiFecConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu FEC
+**
+**  PARAMETERS:  MV_U32 rxGenFecEn
+**               MV_U32 txGenFecEn
+**               MV_U32 txMacFecEn[8]
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiFecConfig(MV_U32 rxGenFecEn, MV_U32 txGenFecEn, MV_U32 *txMacFecEn)
+{
+  return(onuEponApiFecConfig(rxGenFecEn, txGenFecEn, txMacFecEn, ONU_FEC_CFG_INIT));
+}
+
+/*******************************************************************************
+**
+**  onuEponMiEncConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu ENC
+**
+**  PARAMETERS:  MV_U32 onuEncryptCfg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiEncConfig(MV_U32 onuEncryptCfg)
+{
+  MV_STATUS status;
+
+  status  = onuEponApiEncryptionConfig(onuEncryptCfg);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiEncConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu ENC
+**
+**  PARAMETERS:  MV_U32 encryptKey
+**               MV_U32 encryptKeyIndex
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiEncKey(MV_U32 encryptKey, MV_U32 encryptKeyIndex, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  status = onuEponApiEncryptionKeyConfig(encryptKey, encryptKeyIndex, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiDbaConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu DBA report
+**
+**  PARAMETERS:  S_EponIoctlDba *ioctlDba
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiDbaConfig(S_EponIoctlDba *ioctlDba)
+{
+	MV_STATUS status = MV_OK;
+	MV_U32    validReportQueueBitMap;
+	MV_U32    highestReportQueue;
+	MV_U32    llidIdx;
+	MV_U32    queueSetIdx;
+	MV_U32    queueIdx;
+	MV_U32    numOfQueues;
+	MV_U32    numOfQueueSets;
+
+	MV_U32    reportLimit[4] = {/* Queueset, Queues */
+					/* 1 */      8,
+					/* 2 */      8,
+					/* 3 */      5,
+					/* 4 */      3};
+
+	for (llidIdx = 0; llidIdx < EPON_MAX_MAC_NUM; llidIdx++) {
+		validReportQueueBitMap = 0;
+		highestReportQueue     = 0;
+
+		/* LLID */
+		/* ==== */
+		if (!ioctlDba->validLlid[llidIdx]) {
+			onuEponDbOnuDbaLlidActiveStatusSet(ONU_DBA_NON_ACTIVE_LLID, llidIdx);
+			continue;
+		}
+
+		onuEponDbOnuDbaLlidActiveStatusSet(ONU_DBA_UPDATE_LLID, llidIdx);
+
+		numOfQueues    = ioctlDba->dbaLlid[llidIdx].numOfQueues;
+		numOfQueueSets = ioctlDba->dbaLlid[llidIdx].numOfQueueSets;
+
+		/* Queue Set */
+		/* ========= */
+		if (ioctlDba->dbaLlid[llidIdx].numOfQueueSets == 0)
+			continue;
+
+		/* support up to 4 queuesets */
+		if (numOfQueueSets > EPON_MAX_QUEUE_SET_NUMBER)
+			numOfQueueSets = EPON_MAX_QUEUE_SET_NUMBER;
+
+		for (queueSetIdx = 0; queueSetIdx < numOfQueueSets; queueSetIdx++) {
+			/* Queue Id */
+			/* ======== */
+			for (queueIdx = 0; queueIdx < EPON_MAX_QUEUE; queueIdx++) {
+
+				if (ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].state != 0) {
+
+					validReportQueueBitMap |= 1 << queueIdx;
+					highestReportQueue = queueIdx;
+
+					onuEponDbOnuDbaQueueThresholdSet(
+						ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].threshold,
+						ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].state,
+						 queueIdx,
+						 queueSetIdx,
+						 llidIdx);
+					printk("onuEponMiDbaConfig Qset(%d) queue(%d) state(%d) thres(%d)\n",
+					       queueSetIdx,
+					       queueIdx,
+					       ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].state,
+					       ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].threshold);
+
+				} else {
+
+					onuEponDbOnuDbaQueueThresholdSet(0,	    /* threshold */
+									 0,	    /* state     */
+									 queueIdx,
+									 queueSetIdx,
+									 llidIdx);
+					printk("onuEponMiDbaConfig Qset(%d) queue(%d) state(%d) thres(%d)\n",
+					       queueSetIdx,
+					       queueIdx,
+					       ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].state,
+					       ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].threshold);
+
+				}
+			} /* for each queueIdx */
+		} /* for each queueIdx */
+
+		/* Report Validation Check                                                  */
+		/* =======================                                                  */
+		/* Number of bytes for queue report = 39 bytes (64 - mac, type, fcs, etc')  */
+		/* Formula - Number of Queueset X                                           */
+		/*           Number of Queues   X                                           */
+		/*           Queue bytes [2]    +                                           */
+		/*           Number of reports ( == Number of Queueset)                     */
+		/*                                                                          */
+		/* SW REPORT via EPON REGS is limited to 34 bytes                           */
+		/*                                       ========                           */
+		/*                                                                          */
+		/*  QueueSet    1         2        3        4                               */
+		/*  Report      1b        1b       -        -                               */
+		/*  Queue0      2b        2b                                                */
+		/*  Queue1      2b        2b                                                */
+		/*  Queue2      2b        2b                                                */
+		/*  Queue3      2b        2b                                                */
+		/*  Queue4      2b        2b                                                */
+		/*  Queue5      2b        2b                                                */
+		/*  Queue6      2b        2b                                                */
+		/*  Queue7      2b        2b                      = 2 X 8 X 2 + 2 = 34bytes */
+		/*                                                                          */
+		/*  QueueSet    1         2        3        4                               */
+		/*  Report      1b        1b       1b       -                               */
+		/*  Queue0      2b        2b       2b                                       */
+		/*  Queue1      2b        2b       2b                                       */
+		/*  Queue2      2b        2b       2b                                       */
+		/*  Queue3      2b        2b       2b                                       */
+		/*  Queue4      2b        2b       2b                                       */
+		/*  Queue5                                                                  */
+		/*  Queue6                                                                  */
+		/*  Queue7                                        = 3 X 5 X 2 + 3 = 33bytes */
+		/*                                                                          */
+		/*  QueueSet    1         2        3        4                               */
+		/*  Report      1b        1b       1b       1b                              */
+		/*  Queue0      2b        2b       2b       2b                              */
+		/*  Queue1      2b        2b       2b       2b                              */
+		/*  Queue2                                                                  */
+		/*  Queue3                                                                  */
+		/*  Queue4                                                                  */
+		/*  Queue5                                                                  */
+		/*  Queue6                                                                  */
+		/*  Queue7                                        = 4 X 3 X 2 + 4 = 28bytes */
+		/*                                                                          */
+		/*  MV_U32 reportLimit[4] = {Queueset, Queues                               */
+		/*                              1         8,                                */
+		/*                              2         8,                                */
+		/*                              3         5,                                */
+		/*                              4         3};                               */
+
+		printk("numOfQueues(%d), numOfQueueSets(%d), reportLimit[numOfQueueSets](%d)\n",
+		       numOfQueues, numOfQueueSets, reportLimit[numOfQueueSets - 1]);
+
+		while (numOfQueues > reportLimit[numOfQueueSets - 1])
+			numOfQueueSets--;
+
+		onuEponDbOnuDbaHighestReportQueueSet(highestReportQueue, llidIdx);
+		onuEponDbOnuDbaNumOfQueuesSet(numOfQueues, llidIdx);
+		onuEponDbOnuDbaNumOfQueuesetSet(numOfQueueSets, llidIdx);
+		onuEponDbOnuDbaQueuesBitMapSet(validReportQueueBitMap, llidIdx);
+
+		printk("highestReportQueue(%d), numOfQueues(%d, bit map 0x%08x), numOfQueueSets(%d)\n",
+		       highestReportQueue, numOfQueues, validReportQueueBitMap, numOfQueueSets);
+
+		onuEponDbaInfoUpdate(llidIdx);
+
+		onuEponDbOnuDbaLlidActiveStatusSet(ONU_DBA_ACTIVE_LLID, llidIdx);
+
+		/* ==================================== */
+		/* ==         HW REPORT MODE         == */
+		/* ==================================== */
+		if (onuEponDbOnuDbaModeGet() == ONU_DBA_HW_RPRT_MODE) {
+			status = mvOnuEponMacTxmCppReportUpdate(validReportQueueBitMap, highestReportQueue, llidIdx);
+			if (status != MV_OK)
+				return(status);
+		}
+
+	} /* for each llidIdx */
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiDbaRprt
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu DBA report
+**
+**  PARAMETERS:  S_EponIoctlDba *ioctlDba
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiDbaRprt(S_EponIoctlDba *ioctlDba)
+{
+  MV_STATUS status = MV_OK;
+  MV_U32    llidIdx;
+  MV_U32    queueSetIdx;
+  MV_U32    queueIdx;
+  MV_U32    queueState;
+  MV_U32    queueThreshold;
+
+  for (llidIdx = 0; llidIdx < EPON_MAX_MAC_NUM; llidIdx++)
+  {
+	/* LLID */
+	/* ==== */
+	if (ioctlDba->validLlid[llidIdx])
+	{
+	  ioctlDba->dbaLlid[llidIdx].numOfQueues    = onuEponDbOnuDbaNumOfQueuesGet(llidIdx);
+	  ioctlDba->dbaLlid[llidIdx].numOfQueueSets = onuEponDbOnuDbaNumOfQueuesetGet(llidIdx);
+
+      /* Queue Set */
+      /* ========= */
+	  for (queueSetIdx = 0; queueSetIdx < ioctlDba->dbaLlid[llidIdx].numOfQueueSets; queueSetIdx++)
+	  {
+	    /* Queue Id */
+	    /* ======== */
+	    for (queueIdx = 0; queueIdx < ioctlDba->dbaLlid[llidIdx].numOfQueues; queueIdx++)
+	    {
+		  onuEponDbOnuDbaQueueThresholdGet(&(queueThreshold),
+										   &(queueState),
+										   queueIdx,
+										   queueSetIdx,
+										   llidIdx);
+
+		  ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].threshold = (MV_U16)queueThreshold;
+		  ioctlDba->dbaLlid[llidIdx].threshold[queueSetIdx][queueIdx].state     = (MV_U8)queueState;
+	    }
+	  }
+	}
+  }
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiHoldoverConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu Holdover time
+**
+**  PARAMETERS:  S_EponIoctlHoldOver *ioctlHoldover
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiHoldoverConfig(S_EponIoctlHoldOver *ioctlHoldover)
+{
+  MV_STATUS status = MV_OK;
+
+  onuEponDbOnuHoldoverStateSet(ioctlHoldover->holdoverState);
+  onuEponDbOnuHoldoverTimeSet(ioctlHoldover->holdoverTime);
+
+  onuEponIsrTimerHoldoverIntervalSet(ioctlHoldover->holdoverTime, 0);
+
+  mvPonPrint(PON_PRINT_INFO, PON_API_MODULE,
+			 "DEBUG: Holdover config, state(%d), time(%d))\n",
+			 ioctlHoldover->holdoverState, ioctlHoldover->holdoverTime);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiHoldoverReport
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu Holdover parameters
+**
+**  PARAMETERS:  S_EponIoctlHoldOver *ioctlHoldover
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiHoldoverReport(S_EponIoctlHoldOver *ioctlHoldover)
+{
+  MV_STATUS status = MV_OK;
+
+  ioctlHoldover->holdoverState = onuEponDbOnuHoldoverStateGet();
+  ioctlHoldover->holdoverTime  = onuEponDbOnuHoldoverTimeGet();
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiSilenceConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu silence state
+**
+**  PARAMETERS:  S_EponIoctlSilence *ioctlSilence
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiSilenceConfig(S_EponIoctlSilence *ioctlSilence)
+{
+  MV_STATUS status = MV_OK;
+
+  onuEponDbOnuSilenceStateSet(ioctlSilence->silenceState);
+
+  mvPonPrint(PON_PRINT_INFO, PON_API_MODULE,
+			 "DEBUG: Silence config, state(%d)\n", ioctlSilence->silenceState);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiAlarmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get EPON alarm(PON LOS)
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     alarm bit0:XVR LoS, alarm bit1:SERDES Los.
+**               bit8: XVR ON, bit9: SERDES ON
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiAlarmGet(MV_U32 *alarm)
+{
+  MV_STATUS status = MV_OK;
+
+  onuEponLosAlarmGet(alarm);
+
+/*
+  mvPonPrint(PON_PRINT_INFO, PON_API_MODULE,
+             "DEBUG: EPON Alarm[%x], bit0: XVR LoS, bit1:SERDES LoS, bit8: XVR ON, bit9:SERDES ON\n", *alarm);
+*/
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiTdmQueueConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu tdm queue params
+**
+**  PARAMETERS:  S_EponIoctlTdmQueue *ioctlTdm
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+MV_STATUS onuEponMiTdmQueueConfig(S_EponIoctlTdmQueue *ioctlTdm)
+{
+  MV_STATUS status = MV_OK;
+  MV_U32    llidIdx;
+  MV_U32    queueIdx;
+  MV_U32    numOfQueues;
+
+  for (llidIdx = 0; llidIdx < EPON_MAX_MAC_NUM; llidIdx++)
+  {
+	if (onuEponDbOnuDbaLlidActiveStatusGet(llidIdx) == ONU_DBA_ACTIVE_LLID)
+	{
+	  numOfQueues = onuEponDbOnuDbaNumOfQueuesGet(llidIdx);
+
+	  for (queueIdx = 0; queueIdx < numOfQueues; queueIdx++)
+	  {
+		onuEponPmDbaAddBytePerLlidAndQueue(llidIdx, queueIdx, ioctlTdm->tdmQueCnt[llidIdx][queueIdx]);
+	  }
+	}
+  }
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  onuEponMiCfgMacTxEn
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config onu mac TX enable
+**
+**  PARAMETERS:  enable - enable [1] or disable [0] TX
+**
+**  OUTPUTS:
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponMiCfgMacTxEn(MV_U32 enable, MV_U32 macId)
+{
+	onuPonTxPowerOn(enable == 1 ? MV_TRUE : MV_FALSE);
+	onuEponForceTxDownStateSet(enable, macId);
+	mvOnuEponMacOnuTxEnableSet(enable, macId);
+}
+
+
+/*******************************************************************************
+**
+**  mvEponCdevIoctl
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function execute IO commands
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**               unsigned int cmd
+**               unsigned long arg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+int mvEponCdevIoctl(struct inode *inode, struct file *filp, unsigned int cmd,
+                    unsigned long arg)
+{
+  MV_STATUS           status;
+  S_EponIoctlInit     ioctlInit;
+  S_EponIoctlInfo     ioctlInfo;
+  S_EponIoctlPm       ioctlPm;
+  S_EponIoctlFec      ioctlFec;
+  S_EponIoctlEnc      ioctlEnc;
+  S_EponIoctlOamTx    ioctlTxOam;
+  S_EponIoctlDba      ioctlDba;
+  S_EponIoctlHoldOver ioctlHoldover;
+  S_EponIoctlSilence  ioctlSilence;
+  S_EponIoctlTdmQueue ioctlTdmQueue;
+  MV_U32              ioctlState;
+  MV_U32              ioctlAlarm;
+  S_EponIoctlRogueOnu ioctlRogueOnu;
+  unsigned long       flags;
+  int                 ret = -EINVAL;
+
+
+
+  switch(cmd)
+  {
+    /* ====== MVEPON_IOCTL_INIT ======= */
+    case MVEPON_IOCTL_INIT:
+      if(copy_from_user(&ioctlInit, (S_EponIoctlInit*)arg, sizeof(S_EponIoctlInit)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      onuEponInit(&ioctlInit);
+
+      ret = 0;
+      break;
+
+
+    /* ====== MVEPON_IOCTL_FEC_CONFIG ======= */
+    case MVEPON_IOCTL_FEC_CONFIG:
+      if(copy_from_user(&ioctlFec, (S_EponIoctlFec*)arg, sizeof(S_EponIoctlFec)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+	  spin_lock_irqsave(&onuPonIrqLock, flags);
+      status = onuEponMiFecConfig(ioctlFec.rxGenFecEn,
+                                  ioctlFec.txGenFecEn,
+                                  ioctlFec.txMacFecEn);
+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+      if(status != MV_OK)
+        goto ioctlErr;
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_ENC_CONFIG ======== */
+    case MVEPON_IOCTL_ENC_CONFIG:
+      if(copy_from_user(&ioctlEnc, (S_EponIoctlEnc*)arg, sizeof(S_EponIoctlEnc)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+	  spin_lock_irqsave(&onuPonIrqLock, flags);
+      status = onuEponMiEncConfig(ioctlEnc.encEnable);
+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+      if(status != MV_OK)
+        goto ioctlErr;
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_ENC_KEY ======== */
+    case MVEPON_IOCTL_ENC_KEY:
+      if(copy_from_user(&ioctlEnc, (S_EponIoctlEnc*)arg, sizeof(S_EponIoctlEnc)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+	  spin_lock_irqsave(&onuPonIrqLock, flags);
+      status = onuEponMiEncKey(ioctlEnc.encKey,
+                               ioctlEnc.encKeyIndex & 0x1,
+                               ioctlEnc.macId);
+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+      if(status != MV_OK)
+        goto ioctlErr;
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_INFO ==================== */
+    case MVEPON_IOCTL_INFO:
+      if(copy_from_user(&ioctlInfo, (S_EponIoctlInfo*)arg, sizeof(S_EponIoctlInfo)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      status = onuEponMiInfoGet(&ioctlInfo, ioctlInfo.macId);
+      if(status != MV_OK)
+        goto ioctlErr;
+
+      if(copy_to_user((S_EponIoctlInfo*)arg, &ioctlInfo, sizeof(S_EponIoctlInfo)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_PM ==================== */
+    case MVEPON_IOCTL_PM:
+      if(copy_from_user(&ioctlPm, (S_EponIoctlPm*)arg, sizeof(S_EponIoctlPm)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      status = onuEponMiPm(&ioctlPm, ioctlPm.macId);
+      if(status != MV_OK)
+        goto ioctlErr;
+
+      if(copy_to_user((S_EponIoctlPm*)arg, &ioctlPm, sizeof(S_EponIoctlPm)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_OAM_TX ==================== */
+    case MVEPON_IOCTL_OAM_TX:
+      if(copy_from_user(&ioctlTxOam, (S_EponIoctlOamTx*)arg, sizeof(S_EponIoctlOamTx)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+      			 "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+	  spin_lock_irqsave(&onuPonIrqLock, flags);
+	  status = onuEponApiTransmitOamFrame((S_OnuEponCtrlBuffer*)&(ioctlTxOam.oamFrame), ioctlTxOam.macId);
+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+	  if (status != MV_OK)
+	  {
+		mvPonPrint(PON_PRINT_DEBUG, PON_MNG_OAM_TX_MODULE,
+				   "ERROR: (%s:%d) onuEponSendCtrlFrameData\n\r", __FILE_DESC__, __LINE__);
+		goto ioctlErr;
+      }
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_DBA_CFG ==================== */
+    case MVEPON_IOCTL_DBA_CFG:
+      if(copy_from_user(&ioctlDba, (S_EponIoctlDba*)arg, sizeof(S_EponIoctlDba)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+      		   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      spin_lock_irqsave(&onuPonIrqLock, flags);
+      status = onuEponMiDbaConfig((S_EponIoctlDba*)&(ioctlDba));
+      spin_unlock_irqrestore(&onuPonIrqLock, flags);
+      if (status != MV_OK)
+        goto ioctlErr;
+
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_DBA_RPRT =================== */
+    case MVEPON_IOCTL_DBA_RPRT:
+      if(copy_from_user(&ioctlDba, (S_EponIoctlDba*)arg, sizeof(S_EponIoctlDba)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+      		 "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      status = onuEponMiDbaRprt((S_EponIoctlDba*)&(ioctlDba));
+      if (status != MV_OK)
+        goto ioctlErr;
+
+      if(copy_to_user((S_EponIoctlDba*)arg, &ioctlDba, sizeof(S_EponIoctlDba)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_HOLDOVER_CFG ==================== */
+    case MVEPON_IOCTL_HOLDOVER_CFG:
+      if(copy_from_user(&ioctlHoldover, (S_EponIoctlHoldOver*)arg, sizeof(S_EponIoctlHoldOver)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+      		 "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      spin_lock_irqsave(&onuPonIrqLock, flags);
+      status = onuEponMiHoldoverConfig((S_EponIoctlHoldOver*)&(ioctlHoldover));
+      spin_unlock_irqrestore(&onuPonIrqLock, flags);
+      if (status != MV_OK)
+        goto ioctlErr;
+
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_HOLDOVER_RPRT ==================== */
+    case MVEPON_IOCTL_HOLDOVER_RPRT:
+      status = onuEponMiHoldoverReport((S_EponIoctlHoldOver*)&(ioctlHoldover));
+      if (status != MV_OK)
+        goto ioctlErr;
+
+      if(copy_to_user((S_EponIoctlHoldOver*)arg, &ioctlHoldover, sizeof(S_EponIoctlHoldOver)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_SILENCE ==================== */
+    case MVEPON_IOCTL_SILENCE:
+      if(copy_from_user(&ioctlSilence, (S_EponIoctlSilence*)arg, sizeof(S_EponIoctlSilence)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+      	   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      spin_lock_irqsave(&onuPonIrqLock, flags);
+      status = onuEponMiSilenceConfig((S_EponIoctlSilence*)&(ioctlSilence));
+      spin_unlock_irqrestore(&onuPonIrqLock, flags);
+      if (status != MV_OK)
+        goto ioctlErr;
+
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_P2P_SET ==================== */
+    case MVEPON_IOCTL_P2P_SET:
+      if(copy_from_user(&ioctlState, (MV_U32*)arg, sizeof(MV_U32)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+           "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+	  spin_lock_irqsave(&onuPonIrqLock, flags);
+      if (ioctlState) status = mvP2PStart();
+      else            status = mvP2PStop();
+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);
+
+      if (status != MV_OK)
+        goto ioctlErr;
+
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_TDM_QUE_CFG ==================== */
+    case MVEPON_IOCTL_TDM_QUE_CFG:
+      if(copy_from_user(&ioctlTdmQueue,  (S_EponIoctlTdmQueue*)arg, sizeof(S_EponIoctlTdmQueue)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+      	 "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      spin_lock_irqsave(&onuPonIrqLock, flags);
+      status = onuEponMiTdmQueueConfig((S_EponIoctlTdmQueue*)&(ioctlTdmQueue));
+      spin_unlock_irqrestore(&onuPonIrqLock, flags);
+
+      if (status != MV_OK)
+        goto ioctlErr;
+
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_ALARM_GET ==================== */
+    case MVEPON_IOCTL_ALARM_GET:
+      status = onuEponMiAlarmGet(&ioctlAlarm);
+      if (status != MV_OK)
+        goto ioctlErr;
+
+      if(copy_to_user((MV_U32 *)arg, &ioctlAlarm, sizeof(MV_U32)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+      ret = 0;
+      break;
+
+    /* ====== MVEPON_IOCTL_ROGUE_ONU_SET ==================== */
+    case MVEPON_IOCTL_ROGUE_ONU_SET:
+      if(copy_from_user(&ioctlRogueOnu, (S_EponIoctlRogueOnu*)arg, sizeof(S_EponIoctlRogueOnu)))
+      {
+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+           "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);
+        goto ioctlErr;
+      }
+
+      onuEponMiCfgMacTxEn(ioctlRogueOnu.enable, ioctlRogueOnu.macId);
+
+      ret = 0;
+      break;
+
+     default:
+      ret = -EINVAL;
+  }
+
+ioctlErr:
+
+
+  return(ret);
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.h
new file mode 100755
index 0000000..0cdb12f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsMI.h
@@ -0,0 +1,341 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : eponOnuLnxKsMI.h                                           **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Management Interface           **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_EPON_LINUX_KS_MNG_INTERFACE_H

+#define _ONU_EPON_LINUX_KS_MNG_INTERFACE_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+#define MVEPON_IOCTL_INIT          _IOW(MVPON_IOCTL_MAGIC, 1, unsigned int)

+#define MVEPON_IOCTL_FEC_CONFIG    _IOW(MVPON_IOCTL_MAGIC, 2, unsigned int)

+#define MVEPON_IOCTL_ENC_CONFIG    _IOW(MVPON_IOCTL_MAGIC, 3, unsigned int)

+#define MVEPON_IOCTL_ENC_KEY       _IOW(MVPON_IOCTL_MAGIC, 4, unsigned int)

+#define MVEPON_IOCTL_INFO          _IOR(MVPON_IOCTL_MAGIC, 5, unsigned int)

+#define MVEPON_IOCTL_PM            _IOR(MVPON_IOCTL_MAGIC, 6, unsigned int)

+#define MVEPON_IOCTL_OAM_TX        _IOW(MVPON_IOCTL_MAGIC, 7, unsigned int)

+#define MVEPON_IOCTL_DBA_CFG       _IOW(MVPON_IOCTL_MAGIC, 8, unsigned int)

+#define MVEPON_IOCTL_DBA_RPRT      _IOR(MVPON_IOCTL_MAGIC, 8, unsigned int)

+#define MVEPON_IOCTL_HOLDOVER_CFG  _IOW(MVPON_IOCTL_MAGIC, 9, unsigned int)

+#define MVEPON_IOCTL_HOLDOVER_RPRT _IOW(MVPON_IOCTL_MAGIC, 10, unsigned int)

+#define MVEPON_IOCTL_SILENCE       _IOW(MVPON_IOCTL_MAGIC, 11, unsigned int)

+#define MVEPON_IOCTL_P2P_SET       _IOW(MVPON_IOCTL_MAGIC, 12, unsigned int)

+#define MVEPON_IOCTL_TDM_QUE_CFG   _IOW(MVPON_IOCTL_MAGIC, 13, unsigned int)

+#define MVEPON_IOCTL_ALARM_GET     _IOR(MVPON_IOCTL_MAGIC, 14, unsigned int)

+#define MVEPON_IOCTL_ROGUE_ONU_SET _IOW(MVPON_IOCTL_MAGIC, 15, unsigned int)
+

+#define EPON_MAX_NUM_OF_MAC          (8)

+#define EPON_MAX_NUM_OF_QUEUE        (8)

+#define EPON_MAC_LEN                 (6)

+

+#define EPON_API_MAX_OAM_FRAME_SIZE      (512)

+/*db threshold set*/

+#define EPON_MIN_QUEUE_SET_NUMBER        (2)

+#define EPON_MAX_QUEUE_SET_NUMBER        (4)

+#define EPON_MAX_THRESHOLD_SET_RER_QUEUE (8)

+#define EPON_MAX_QUEUE                   (8)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+typedef enum

+{

+  E_EPON_IOCTL_PM_RX  = 1,

+  E_EPON_IOCTL_PM_TX  = 2,

+  E_EPON_IOCTL_PM_SW  = 3,

+  E_EPON_IOCTL_PM_GPM = 4

+}E_EponIoctlPmSection;

+

+typedef enum

+{

+  E_EPON_IOCTL_MPCP_TX_FRAME_CNT             = 0,

+  E_EPON_IOCTL_MPCP_TX_ERROR_FRAME_CNT       = 1,

+  E_EPON_IOCTL_MAX_TX_SW_CNT

+}E_EponIoctlTxSwCnt;

+

+typedef enum

+{

+  E_EPON_IOCTL_MPCP_RX_FRAME_CNT             = 0,

+  E_EPON_IOCTL_MPCP_RX_ERROR_FRAME_CNT       = 1,

+  E_EPON_IOCTL_MPCP_REGISTER_ACK_CNT         = 2,

+  E_EPON_IOCTL_MPCP_REGISTER_NACK_CNT        = 3,

+  E_EPON_IOCTL_MPCP_REGISTER_DEREG_FRAME_CNT = 4,

+  E_EPON_IOCTL_MPCP_REGISTER_REREG_FRAME_CNT = 5,

+  E_EPON_IOCTL_MAX_RX_SW_CNT

+}E_EponIoctlRxSwCnt;

+

+typedef enum

+{

+  E_EPON_IOCTL_STD_MODE,

+  E_EPON_IOCTL_P2P_MODE,

+  E_EPON_IOCTL_MAX_MODE_NUM

+}E_EponIoctlMode;

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+/* TX Counters */

+typedef struct

+{

+  MV_U32 ctrlRegReqFramesCnt; /* Count number of register request frames transmitted     */  

+  MV_U32 ctrlRegAckFramesCnt; /* Count number of register acknowledge frames transmitted */  

+  MV_U32 reportFramesCnt;     /* Count number of report frames transmitted               */

+  MV_U32 dataFramesCnt;       /* Count number of data frames transmitted                 */

+  MV_U32 txAllowedBytesCnt;   /* Count number of Tx Byte Allow counter                   */

+}S_EponIoctlTxPm;

+

+/* RX Counters */

+typedef struct

+{

+  MV_U32 fcsErrorFramesCnt;   /* Count number of received frames with FCS errors */

+  MV_U32 shortFramesCnt;      /* Count number of short frames received           */

+  MV_U32 longFramesCnt;       /* Count number of long frames received            */

+  MV_U32 dataFramesCnt;       /* Count number of data frames received            */

+  MV_U32 ctrlFramesCnt;       /* Count number of control frames received         */

+  MV_U32 reportFramesCnt;     /* Count number of report frames received          */

+  MV_U32 gateFramesCnt;       /* Count number of gate frames received            */

+}S_EponIoctlRxPm;

+

+/* SW Counters */

+typedef struct

+{

+  MV_U32 swTxCnt[E_EPON_IOCTL_MAX_TX_SW_CNT];

+  MV_U32 swRxCnt[E_EPON_IOCTL_MAX_RX_SW_CNT]; 

+}S_EponIoctlSwPm;

+

+/* GEM Counters */

+typedef struct

+{

+  MV_U32 grantValidCnt;                 /* Count number of valid grant                          */

+  MV_U32 grantMaxFutureTimeErrorCnt;    /* Count number of grant max future time error          */

+  MV_U32 minProcTimeErrorCnt;           /* Count number of min proc time error                  */

+  MV_U32 lengthErrorCnt;                /* Count number of length error                         */

+  MV_U32 discoveryAndRegCnt;            /* Count number of discovery & register                 */

+  MV_U32 fifoFullErrorCnt;              /* Count number of fifo full error                      */

+  MV_U32 opcDiscoveryNotRegBcastCnt;    /* Count number of opc discoveryNotRegBcastCnt          */

+  MV_U32 opcRegisterNotDiscoveryCnt;    /* Count number of opc register not discovery           */ 

+  MV_U32 opcDiscoveryNotRegNotBcastCnt; /* Count number of opc discovery not register not bcast */ 

+  MV_U32 opcDropGrantCnt;               /* Count number of opc drop grant                       */ 

+  MV_U32 opcHiddenGrantCnt;             /* Count number of opc hidden grant                     */ 

+  MV_U32 opcBackToBackCnt;              /* Count number of opc back to back                     */ 

+}S_EponIoctlGpmPm;                               

+

+/* PM Counters */

+typedef struct

+{

+  MV_U32 macId;

+  MV_U32 section;

+  union

+  {

+    S_EponIoctlRxPm  rxCnt;

+    S_EponIoctlTxPm  txCnt;

+    S_EponIoctlSwPm  swCnt;

+    S_EponIoctlGpmPm gpmCnt;

+  };

+}S_EponIoctlPm;

+

+/* INFO */

+typedef struct

+{

+  MV_U32 macId;

+  MV_U32 onuEponState;                   /* ONU State                   */  

+  MV_U32 onuEponSignalDetect;            /* ONU Signal Detect           */  

+  MV_U32 onuEponDsSyncOkPcs;             /* ONU DS Sync OK - PCS        */  

+  MV_U32 onuEponCtrlType;                /* ONU Control Type            */

+  MV_U8  onuEponMacAddr[EPON_MAC_LEN];   /* ONU MAC Address             */

+  MV_U8  onuEponBcastAddr[EPON_MAC_LEN]; /* ONU MAC Broadcast Address   */

+  MV_U32 onuEponRxLLID;                  /* ONU Rx Packet Rx LLID Array */

+  MV_U32 onuEponTxLLID;                  /* ONU Rx Packet Tx LLID Array */

+  MV_U32 onuEponMode;                    /* ONU mode (EPON, P2P)        */  

+}S_EponIoctlInfo;

+

+/* Init */

+typedef struct

+{

+  MV_U32 xvrPolarity;

+  MV_U32 dgPolarity;

+  MV_U8  macAddr[EPON_MAX_NUM_OF_MAC][EPON_MAC_LEN];

+}S_EponIoctlInit;

+

+/* FEC */

+typedef struct

+{

+  MV_U32 rxGenFecEn;

+  MV_U32 txGenFecEn;

+  MV_U32 txMacFecEn[EPON_MAX_NUM_OF_MAC];

+}S_EponIoctlFec;

+

+/* Encryption */

+typedef struct

+{

+  MV_U32 macId;

+  MV_U32 encEnable;

+  MV_U32 encKey;

+  MV_U32 encKeyIndex;

+}S_EponIoctlEnc;

+

+/* OAM Transmission */

+typedef struct

+{

+  MV_U32 length;

+  MV_U8  data[EPON_API_MAX_OAM_FRAME_SIZE];

+}S_EponOamFrame;

+

+typedef struct

+{

+  MV_U32         macId;

+  S_EponOamFrame oamFrame;

+}S_EponIoctlOamTx;

+

+/* DBA */

+typedef struct  

+{

+    MV_U8  state;	    /* Is threshold configuration active for the queue */ 

+    MV_U16 threshold;   /* Queue threshold: range 0 - 65535                */ 

+}S_EponDbaThreshold; 

+

+typedef struct

+{

+  MV_U32             numOfQueueSets;

+  MV_U32             numOfQueues;

+  MV_U32             aggrThreshold;

+  S_EponDbaThreshold threshold[EPON_MAX_QUEUE_SET_NUMBER][EPON_MAX_THRESHOLD_SET_RER_QUEUE];

+}S_EponIoctlDbaLlid;

+

+typedef struct 

+{

+  MV_U8              validLlid[EPON_MAX_NUM_OF_MAC];

+  S_EponIoctlDbaLlid dbaLlid[EPON_MAX_NUM_OF_MAC];

+}S_EponIoctlDba; 

+

+/* Holdover */

+typedef struct

+{

+  MV_U32 holdoverState; /* 0 - Deactivate, 1 - Activate */ 

+  MV_U32 holdoverTime;

+}S_EponIoctlHoldOver;

+

+/* Silence */

+typedef struct

+{

+  MV_U32 silenceState; /* 0 - Deactivate, 1 - Activate */ 

+}S_EponIoctlSilence;

+

+typedef struct

+{

+  uint32_t tdmQueCnt[EPON_MAX_NUM_OF_MAC][EPON_MAX_NUM_OF_QUEUE];

+}S_EponIoctlTdmQueue;

+
+/* Rogue ONU */
+typedef struct
+{
+  uint32_t macId;
+  uint32_t enable;
+}S_EponIoctlRogueOnu;
+

+typedef struct 

+{

+  S_EponIoctlInit     init;

+  S_EponIoctlInfo     e_info;

+  S_EponIoctlPm       e_pm;

+  S_EponIoctlFec      fec;

+  S_EponIoctlEnc      enc;

+  S_EponIoctlDba      dba;

+  S_EponIoctlHoldOver holdover;

+  S_EponIoctlSilence  silence;

+  S_EponIoctlTdmQueue tdmQueue;

+  S_EponIoctlRogueOnu rogueOnu;
+  struct cdev         cdev;

+}S_EponModuleCdev;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+MV_STATUS onuEponMngInterfaceCreate(void);

+MV_STATUS onuEponMngInterfaceRelease(void);

+void      onuEponMiNotifyCallback(MV_U32 onuState);

+

+MV_STATUS mvP2PStart(void);

+MV_STATUS mvP2PStop(void);

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_EPON_LINUX_KS_MNG_INTERFACE_H */

+

+  

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.c
new file mode 100755
index 0000000..e425751
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.c
@@ -0,0 +1,2042 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : eponOnuLnxKsUI.c                                           **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON CLI functionality            **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "eponOnuHeader.h"
+#ifndef PON_FPGA
+#include "mvSysPonConfig.h"
+#endif /* PON_FPGA */
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/perf/epon/eponOnuLnxKsUI.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+extern MV_U32 llidQueueState[8][4][8];
+extern MV_U32 llidQueueThreshold[8][4][8];
+extern MV_U32 llidNumOfQueuesets[8];
+extern MV_U32 llidNumOfQueues[8];
+extern MV_U32 llidNumOfReportBytes[8];
+
+extern MV_U32 g_OnuEponRandomCount;
+extern MV_U32 g_OnuEponRandomValues[];
+
+extern MV_U32 regRandomMaskThreshold;
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+MV_BOOL infoEponCntReadClearInd = MV_TRUE;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+extern MV_STATUS onuEponMiDbaConfig(S_EponIoctlDba *ioctlDba);
+extern MV_STATUS onuEponMiHoldoverConfig(S_EponIoctlHoldOver *ioctlHoldover);
+extern MV_STATUS onuEponMiSilenceConfig(S_EponIoctlSilence *ioctlSilence);
+extern MV_STATUS onuEponMiAlarmGet(MV_U32 *alarm);
+extern void      onuEponMiCfgMacTxEn(MV_U32 enable, MV_U32 macId);
+
+extern void rprtThresholdSet(MV_U32 lowThCnt, MV_U32 lowThVal, MV_U32 hiThCnt, MV_U32 hiThVal);
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+/* ========================================================================== */
+/*                            Info Commands                                   */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponUiInfoShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu information
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiInfoShow(char* buf)
+{
+  MV_STATUS status;
+  S_EponIoctlInfo info[EPON_MAX_MAC_NUM];
+  MV_U8           *stateDesc[] = {"", "Pending", "Active"};
+  int             off = 0;
+  int             macId;
+
+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+  {
+    status = onuEponApiInformationGet(&info[macId], macId);
+    if (status != MV_OK)
+    {
+      off += mvOsSPrintf(buf+off, "Failed read mac information!!!\n");
+      return(off);
+    }
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "ONT Information:\n");
+  off += mvOsSPrintf(buf+off, "---------------------------------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "     State    Ether    Unicast             Bcast               Tx LLId  Tx LLId  \n");
+  off += mvOsSPrintf(buf+off, "              Type     Mac Addr            Mac Addr                              \n");
+  off += mvOsSPrintf(buf+off, " MAC                                                                             \n");
+  off += mvOsSPrintf(buf+off, "---------------------------------------------------------------------------------\n");
+
+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+  {
+      off += mvOsSPrintf(buf+off, "[%02d] %-8s %8x %02x:%02x:%02x:%02x:%02x:%02x %02x:%02x:%02x:%02x:%02x:%02x %8u %8u\n",
+                        macId,
+                        stateDesc[info[macId].onuEponState],
+                        info[macId].onuEponCtrlType,
+                        info[macId].onuEponMacAddr[0], info[macId].onuEponMacAddr[1], info[macId].onuEponMacAddr[2],
+                        info[macId].onuEponMacAddr[3], info[macId].onuEponMacAddr[4], info[macId].onuEponMacAddr[5],
+                        info[macId].onuEponBcastAddr[0], info[macId].onuEponBcastAddr[1], info[macId].onuEponBcastAddr[2],
+                        info[macId].onuEponBcastAddr[3], info[macId].onuEponBcastAddr[4], info[macId].onuEponBcastAddr[5],
+                        info[macId].onuEponTxLLID,
+                        info[macId].onuEponRxLLID);
+  }
+  off += mvOsSPrintf(buf+off, "--------------------------------------------------\n\r");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiAlarmShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu alarms
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiAlarmShow(char* buf)
+{
+  MV_U32 alarm[2];
+  MV_U8  *statusText[] = {"OFF", "ON "};
+  int    off = 0;
+
+  onuEponAlarmGet(alarm);
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "-------------\n");
+  off += mvOsSPrintf(buf+off, "|ONU ALARMS |\n");
+  off += mvOsSPrintf(buf+off, "-------------------------\n");
+  off += mvOsSPrintf(buf+off, "| XVR SD    | SERDES SD |\n");
+  off += mvOsSPrintf(buf+off, "-------------------------\n");
+  off += mvOsSPrintf(buf+off, "| %9s | %9s |\n", statusText[alarm[0]], statusText[alarm[1]]);
+  off += mvOsSPrintf(buf+off, "-------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiDebugReadReg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function test requested address space
+**
+**  PARAMETERS:  MV_U32 readOffset
+**               MV_U32 readEntry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponUiDebugReadReg(MV_U32 readOffset, MV_U32 readEntry)
+{
+  MV_U32 regValue;
+
+#ifndef PON_FPGA
+  regValue = MV_REG_READ((MV_EPON_MAC_REGS_BASE) + readOffset + (readEntry * sizeof (MV_U32)));
+#else /* PON_FPGA */
+  regValue = MV_REG_READ((MV_GPON_REG_BASE) + readOffset + (readEntry * sizeof (MV_U32)));
+#endif /* PON_FPGA */
+
+  mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+             "Read register offset 0x%x, entry %d = [0x%08X]\n\r", readOffset, readEntry, regValue);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiDebugWriteReg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function test requested address space
+**
+**  PARAMETERS:  MV_U32 writeOffset
+**               MV_U32 writeEntry
+**               MV_U32 regValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuEponUiDebugWriteReg(MV_U32 writeOffset, MV_U32 writeEntry, MV_U32 regValue)
+{
+#ifndef PON_FPGA
+  MV_REG_WRITE((MV_EPON_MAC_REGS_BASE) + writeOffset + (writeEntry * sizeof (MV_U32)), regValue);
+#else /* PON_FPGA */
+  MV_REG_WRITE((MV_GPON_REG_BASE) + writeOffset + (writeEntry * sizeof (MV_U32)), regValue);
+#endif /* PON_FPGA */
+
+  mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+             "Write  register offset 0x%x, entry %d = [0x%08X]\n\r", writeOffset, writeEntry, regValue);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiInfoHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print info help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiInfoHelpShow(char* buf)
+{
+  int off = 0;
+
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Configuration Commands[HEX]\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " echo [Offset] [Entry]           > readReg   - read onu reg\n");
+  off += mvOsSPrintf(buf+off, " echo [Offset] [Entry] [Value]   > writeReg  - write onu reg\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " cat info  - dump onu information\n");
+  off += mvOsSPrintf(buf+off, " cat alarm - dump onu alarms\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+
+  return(off);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Pm Commands                                     */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuEponUiRxCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu rx counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiRxCountersShow(char* buf)
+{
+  MV_STATUS       status;
+  S_EponIoctlRxPm rxCounters;
+  int             off = 0;
+
+  status = onuEponApiRxPmGet(&rxCounters, infoEponCntReadClearInd, 0);
+  if (status != MV_OK)
+  {
+    off += mvOsSPrintf(buf+off, "Failed read Rx pm information!!!\n");
+    return(off);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "Rx Counters\n");
+  off += mvOsSPrintf(buf+off, "-------------------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "     FCS      Short    Long     Data     Ctrl     Rprt     Gate    \n");
+  off += mvOsSPrintf(buf+off, "     Frames   Frames   Frames   Frames   Frames   Frames   Frames  \n");
+  off += mvOsSPrintf(buf+off, " MAC Rece     Rece     Rece     Rece     Rece     Rece     Rece    \n");
+  off += mvOsSPrintf(buf+off, "-------------------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "[00] %8u %8u %8u %8u %8u %8u %8u\n",
+                     rxCounters.fcsErrorFramesCnt,
+                     rxCounters.shortFramesCnt,
+                     rxCounters.longFramesCnt,
+                     rxCounters.dataFramesCnt,
+                     rxCounters.ctrlFramesCnt,
+                     rxCounters.reportFramesCnt,
+                     rxCounters.gateFramesCnt);
+  off += mvOsSPrintf(buf+off, "-------------------------------------------------------------------\n\r");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiTxCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu tx counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiTxCountersShow(char* buf)
+{
+  MV_STATUS       status;
+  S_EponIoctlTxPm txCounters[EPON_MAX_MAC_NUM];
+  int             macId;
+  int             off = 0;
+
+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+  {
+    status = onuEponApiTxPmGet(&txCounters[macId], infoEponCntReadClearInd, macId);
+    if (status != MV_OK)
+    {
+      off += mvOsSPrintf(buf+off, "Failed read Tx pm information!!!\n");
+      return(off);
+    }
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "Tx Counters\n");
+  off += mvOsSPrintf(buf+off, "--------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "     Register Register Report   Data     Tx Byte  \n");
+  off += mvOsSPrintf(buf+off, "     Request  Ack      Frames   Frames   Allow    \n");
+  off += mvOsSPrintf(buf+off, " MAC Frames   Frames                              \n");
+  off += mvOsSPrintf(buf+off, "--------------------------------------------------\n");
+
+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+  {
+      off += mvOsSPrintf(buf+off, "[%02d] %8u %8u %8u %8u %8u\n",
+                        macId,
+                        txCounters[macId].ctrlRegReqFramesCnt,
+                        txCounters[macId].ctrlRegAckFramesCnt,
+                        txCounters[macId].reportFramesCnt,
+                        txCounters[macId].dataFramesCnt,
+                        txCounters[macId].txAllowedBytesCnt);
+  }
+  off += mvOsSPrintf(buf+off, "--------------------------------------------------\n\r");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiSwCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu sw counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiSwCountersShow(char* buf)
+{
+	MV_STATUS       status;
+	S_EponIoctlSwPm swCounters[EPON_MAX_MAC_NUM];
+	int             macId;
+	int             off = 0;
+
+	for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {
+		status = onuEponApiSwPmGet(&swCounters[macId], infoEponCntReadClearInd, macId);
+		if (status != MV_OK) {
+			off += mvOsSPrintf(buf+off, "Failed read Sw pm information!!!\n");
+			return(off);
+		}
+	}
+
+	off += mvOsSPrintf(buf+off, "\n");
+	off += mvOsSPrintf(buf+off, "Sw Counters\n");
+	off += mvOsSPrintf(buf+off, "----------------------------------------------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "     Total    Total    Total    Total    Total    Total    Total    Total   \n");
+	off += mvOsSPrintf(buf+off, "     MPC Tx   MPC Tx   MPC Rx   MPC Rx   MPC Reg  MPC Reg  MPC Reg  MPC Reg \n");
+	off += mvOsSPrintf(buf+off, "     Frames   Error    Frames   Error    Ack      Nack     De-Reg   Re-Reg  \n");
+	off += mvOsSPrintf(buf+off, " MAC          Frames            Frames   Frames   Frames   Frames   Frames  \n");
+	off += mvOsSPrintf(buf+off, "----------------------------------------------------------------------------\n");
+
+	for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++) {
+		off += mvOsSPrintf(buf+off, "[%02d] %8u %8u %8u %8u %8u %8u %8u %8u\n",
+						   macId,
+						   swCounters[macId].swTxCnt[TOTAL_MPCP_TX_FRAME_CNT],
+						   swCounters[macId].swTxCnt[TOTAL_MPCP_TX_ERROR_FRAME_CNT],
+						   swCounters[macId].swRxCnt[TOTAL_MPCP_RX_FRAME_CNT],
+						   swCounters[macId].swRxCnt[TOTAL_MPCP_RX_ERROR_FRAME_CNT],
+						   swCounters[macId].swRxCnt[TOTAL_MPCP_REGISTER_ACK_CNT],
+						   swCounters[macId].swRxCnt[TOTAL_MPCP_REGISTER_NACK_CNT],
+						   swCounters[macId].swRxCnt[TOTAL_MPCP_REGISTER_DEREG_FRAME_CNT],
+						   swCounters[macId].swRxCnt[TOTAL_MPCP_REGISTER_REREG_FRAME_CNT]);
+	}
+	off += mvOsSPrintf(buf+off, "----------------------------------------------------------------------------\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiGpmCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu gpm counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiGpmCountersShow(char* buf)
+{
+  MV_STATUS        status;
+  S_EponIoctlGpmPm gpmCounters[EPON_MAX_MAC_NUM];
+  int              macId;
+  int              off = 0;
+
+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+  {
+    status = onuEponApiGpmPmGet(&gpmCounters[macId], infoEponCntReadClearInd, macId);
+    if (status != MV_OK)
+    {
+      off += mvOsSPrintf(buf+off, "Failed read Gpm pm information!!!\n");
+      return(off);
+    }
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "GPM Counters\n");
+  off += mvOsSPrintf(buf+off, "----------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "     Valid    Grant    Min Proc Length   Discover Fifo    \n");
+  off += mvOsSPrintf(buf+off, "     Grant    Max Time Time     Error    And      Full    \n");
+  off += mvOsSPrintf(buf+off, " MAC          Error    Error             Register Error   \n");
+  off += mvOsSPrintf(buf+off, "----------------------------------------------------------\n");
+
+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+  {
+     off += mvOsSPrintf(buf+off, "[%02d] %8u %8u %8u %8u %8u %8u\n",
+                        macId,
+                        gpmCounters[macId].grantValidCnt,
+                        gpmCounters[macId].grantMaxFutureTimeErrorCnt,
+                        gpmCounters[macId].minProcTimeErrorCnt,
+                        gpmCounters[macId].lengthErrorCnt,
+                        gpmCounters[macId].discoveryAndRegCnt,
+                        gpmCounters[macId].fifoFullErrorCnt);
+  }
+  off += mvOsSPrintf(buf+off, "----------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "     OPC      OPC      OPC      OPC      OPC      OPC     \n");
+  off += mvOsSPrintf(buf+off, "     Discover Register Discover Drop     Hidden   Back to \n");
+  off += mvOsSPrintf(buf+off, "     Not      Not      Not      Grant    Grant    Back    \n");
+  off += mvOsSPrintf(buf+off, "     Register Discover Register                           \n");
+  off += mvOsSPrintf(buf+off, "     Bcast             Or Bcast                           \n");
+  off += mvOsSPrintf(buf+off, " MAC                                                      \n");
+  off += mvOsSPrintf(buf+off, "----------------------------------------------------------\n");
+
+
+  for (macId = 0; macId < EPON_MAX_MAC_NUM; macId++)
+  {
+     off += mvOsSPrintf(buf+off, "[%02d] %8u %8u %8u %8u %8u %8u\n",
+                        macId,
+                        gpmCounters[macId].opcDiscoveryNotRegBcastCnt,
+                        gpmCounters[macId].opcRegisterNotDiscoveryCnt,
+                        gpmCounters[macId].opcDiscoveryNotRegNotBcastCnt,
+                        gpmCounters[macId].opcDropGrantCnt,
+                        gpmCounters[macId].opcHiddenGrantCnt,
+                        gpmCounters[macId].opcBackToBackCnt);
+  }
+  off += mvOsSPrintf(buf+off, "----------------------------------------------------------\n\r");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiAllCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print all onu counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiAllCountersShow(char* buf)
+{
+	int              off = 0;
+
+	off += onuEponUiRxCountersShow(buf);
+	off += onuEponUiTxCountersShow(buf+off);
+	off += onuEponUiSwCountersShow(buf+off);
+	off += onuEponUiGpmCountersShow(buf+off);
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiPmHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print pm help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiPmHelpShow(char* buf)
+{
+	int off = 0;
+
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, "Configuration Commands[DEC]\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, " echo [state]               > cntRdClrState - onu counters flag, Read[0], "
+												"Read Clear[1]\n");
+	off += mvOsSPrintf(buf+off, " echo [llid][Queue][#Bytes] > addDbaBytesPerLlidQueue - add bytes per LLID "
+												"/ Queue\n");
+	off += mvOsSPrintf(buf+off, " echo [llid][#Bytes]        > addDbaBytesPerLlidFifo - add bytes per LLID FIFO\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, " cat rxCnt                    - dump Rx counters\n");
+	off += mvOsSPrintf(buf+off, " cat txCnt                    - dump Tx counters\n");
+	off += mvOsSPrintf(buf+off, " cat swCnt                    - dump Sw counters\n");
+	off += mvOsSPrintf(buf+off, " cat gpmCnt                   - dump GPM counters\n");
+	off += mvOsSPrintf(buf+off, " cat allCnt                   - dump All counters\n");
+	off += mvOsSPrintf(buf+off, " cat showDbaBytesPerLlidQueue - dump byres addition per LLID / Queue\n");
+	off += mvOsSPrintf(buf+off, " cat showDbaBytesPerLlidFifo  - dump byres addition per LLID FIFO\n");
+	off += mvOsSPrintf(buf+off, " cat showRandom               - dump random generator counters\n");
+	off += mvOsSPrintf(buf+off, " cat showPcsStat              - dump accumulates PCS statistics counters\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCountersReadClearFlag
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config onu clear counters flag
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCountersReadClearFlag(MV_BOOL clear)
+{
+	infoEponCntReadClearInd = clear;
+}
+
+/*******************************************************************************
+**
+**  onuEponUiAddLlidQueueBytes
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function add bytes for LLID queue for DBA report
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiAddLlidQueueBytes(MV_U32 llId, MV_U32 queueId, MV_U32 counter)
+{
+  onuEponPmDbaAddBytePerLlidAndQueue(llId, queueId, counter);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiAddLlidQueueBytes
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function show bytes added for LLID queue for DBA report
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+int onuEponUiShowLlidQueueBytes(char* buf)
+{
+  MV_U32 llldIndex;
+  MV_U32 queueIndex;
+  MV_U32 counter;
+  int off = 0;
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "Additional Bytes per Queue\n");
+  off += mvOsSPrintf(buf+off, "---------------------------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "LLID Queue0   Queue1   Queue2   Queue3   Queue4   Queue5   Queue6   Queue7  \n");
+
+  for (llldIndex = 0; llldIndex < EPON_MAX_MAC_NUM; llldIndex++)
+  {
+    off += mvOsSPrintf(buf+off, "[%02d]", llldIndex);
+
+	for (queueIndex = 0; queueIndex < EPON_MAX_QUEUE; queueIndex++)
+	{
+	  counter = onuEponPmDbaAddBytePerLlidAndQueueGet(llldIndex, queueIndex);
+	  off += mvOsSPrintf(buf+off, " %8u", counter);
+	}
+	off += mvOsSPrintf(buf+off, "\n");
+  }
+
+  off += mvOsSPrintf(buf+off, "---------------------------------------------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiAddLlidFifoBytes
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function add bytes for LLID FIFO for DBA report
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiAddLlidFifoBytes(MV_U32 llId, MV_U32 counter)
+{
+  onuEponPmDbaAddBytePerLlidFifo(llId, counter);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiShowLlidFifoBytes
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function show bytes added for queueset FIFO for DBA report
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+int onuEponUiShowLlidFifoBytes(char* buf)
+{
+  MV_U32 llldIndex;
+  MV_U32 counter;
+  int off = 0;
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "Additional Bytes per LLID FIFO\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "LLID0     LLID1     LLID2     LLID3     LLID4     LLID5     LLID6     LLID7   \n");
+
+  for (llldIndex = 0; llldIndex < EPON_MAX_MAC_NUM; llldIndex++)
+  {
+	counter = onuEponPmDbaAddBytePerLlidFifoGet(llldIndex);
+	off += mvOsSPrintf(buf+off, "%8u  ", counter);
+  }
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiShowRandom
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function show random generation counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+int onuEponUiShowRandom(char *buf)
+{
+	int off = 0;
+	int i;
+	MV_U32 randomShift = 0;
+	MV_U32 randomRange = 0;
+
+	off += mvOsSPrintf(buf+off, "\n");
+
+	off += mvOsSPrintf(buf+off, "------------------------------------------------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "onuEponPmRandomGet was called %d times ", g_OnuEponRandomCount);
+
+	if (g_OnuEponRandomCount != 0) {
+		off += mvOsSPrintf(buf+off, "and the following random values were generated:");
+		for (i = 0; i < g_OnuEponRandomCount; i++) {
+			if ((i % 4) == 0) /* 4 values in one row */
+				off += mvOsSPrintf(buf+off, "\n");
+			off += mvOsSPrintf(buf+off, "0x%08x\t", g_OnuEponRandomValues[i]);
+		}
+		off += mvOsSPrintf(buf+off, "\n");
+		off += mvOsSPrintf(buf+off, "------------------------------------------------------------------------------\n");
+		off += mvOsSPrintf(buf+off, "The same random values after processing:");
+		for (i = 0; i < g_OnuEponRandomCount; i++) {
+			if ((i % 4) == 0) /* 4 values in one row */
+				off += mvOsSPrintf(buf+off, "\n");
+
+			randomShift = ((g_OnuEponRandomValues[i] >> 16) & 0xF);
+			randomRange = ((g_OnuEponRandomValues[i] >> randomShift) & regRandomMaskThreshold);
+			off += mvOsSPrintf(buf+off, "%04d\t", randomRange);
+		}
+		off += mvOsSPrintf(buf+off, "\n");
+	} else
+		off += mvOsSPrintf(buf+off, ", no random values were generated\n");
+
+	off += mvOsSPrintf(buf+off, "------------------------------------------------------------------------------\n");
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiShowPcsStat
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function show PCS statistics
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+int onuEponUiShowPcsStat(char *buf)
+{
+	S_PcsPm statCounters;
+	int off = 0;
+
+	off += mvOsSPrintf(buf+off, "------------------------------------------------------------------------------\n");
+
+	onuEponPmPcsPmGet(&statCounters);
+
+	off += mvOsSPrintf(buf+off, "Accumulated counter values in DB:\n");
+	off += mvOsSPrintf(buf+off, "\n");
+	off += mvOsSPrintf(buf+off, "legalFrameCnt                     0x%08x\n", statCounters.legalFrameCnt);
+	off += mvOsSPrintf(buf+off, "maxFrameSizeErrCnt                0x%08x\n", statCounters.maxFrameSizeErrCnt);
+	off += mvOsSPrintf(buf+off, "parityLenErrCnt                   0x%08x\n", statCounters.parityLenErrCnt);
+	off += mvOsSPrintf(buf+off, "longGateErrCnt                    0x%08x\n", statCounters.longGateErrCnt);
+	off += mvOsSPrintf(buf+off, "protocolErrCnt                    0x%08x\n", statCounters.protocolErrCnt);
+	off += mvOsSPrintf(buf+off, "minFrameSizeErrCnt                0x%08x\n", statCounters.minFrameSizeErrCnt);
+	off += mvOsSPrintf(buf+off, "legalFecFrameCnt                  0x%08x\n", statCounters.legalFecFrameCnt);
+	off += mvOsSPrintf(buf+off, "legalNonFecFrameCnt               0x%08x\n", statCounters.legalNonFecFrameCnt);
+	off += mvOsSPrintf(buf+off, "------------------------------------------------------------------------------\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuEponUiCfgHelpShow(char* buf)
+{
+	int off = 0;
+	MV_U32 devId = mvCtrlModelGet();
+
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, "Configuration Commands[HEX]\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, " echo [enable]        > rxEn            - onu RX enbale, Disable[0], Enable[1]\n");
+	off += mvOsSPrintf(buf+off, " echo [enable][macId] > txEn            - onu mac TX enbale, Disable[0], Enable[1]\n");
+	off += mvOsSPrintf(buf+off, " echo [enable]        > ctrlTimerEn     - control timer for  reception of MPCP "
+										"/ GATES, Disable[0], Enable[1]\n");
+	off += mvOsSPrintf(buf+off, " echo [interval]      > ctrlTimerVal    - control timer interval\n");
+	off += mvOsSPrintf(buf+off, " echo [limit][mask]   > ctrlTimerRandom - control timer random reset, expire limit"
+										" and expire duration\n");
+	off += mvOsSPrintf(buf+off, " echo [enable][T0 val][T0 time][T1 val][T1 time]\n");
+	off += mvOsSPrintf(buf+off, "                      > rprtTimerCfg - report dba timer config\n");
+	off += mvOsSPrintf(buf+off, " echo [queue][Threshold][llid]\n");
+	off += mvOsSPrintf(buf+off, "                      > dbaHwParamsCfg   - configuration of HW DBA queues "
+										"(Max Threshold 0xFFFF)\n");
+	off += mvOsSPrintf(buf+off, " echo [interval]      > dbaSwIntervalCfg - configure SW report interval\n");
+	off += mvOsSPrintf(buf+off, " echo [#qset][qBitMap][T0][T1][T2]\n");
+	off += mvOsSPrintf(buf+off, "                      > dbaSwParamsCfg   - simulate configuration of SW DBA "
+										"queues for LLID 0\n");
+	off += mvOsSPrintf(buf+off, " echo [qset][queue]   > dbaSwOptionCfg   - configure SW report direction [0]normal"
+										" [1]reverse\n");
+	off += mvOsSPrintf(buf+off, " echo [time][state]   > holdoverDebug    - simulate configuration of Holdover\n");
+	off += mvOsSPrintf(buf+off, " echo [state]         > silenceMode      - Set Silence Mode\n");
+	off += mvOsSPrintf(buf+off, " echo [state]         > silenceSim       - simulate Silence Mode\n");
+	off += mvOsSPrintf(buf+off, " echo [dummy]         > dgDebug          - simulate reception of Dying Gasp "
+										"Interrupt\n");
+	off += mvOsSPrintf(buf+off, " echo [#Queue][Thresh]> dgCfg            - configure Dying Gasp DBA report\n");
+	off += mvOsSPrintf(buf+off, " echo [module][Level][Options] > printMask - change printing options\n");
+	off += mvOsSPrintf(buf+off, " echo [enable][pattern][burst][duration]\n");
+	off += mvOsSPrintf(buf+off, "      [period]        > pattern          - start enable[1] or stop[0] transmission"
+										" of pattern: 0x1-1T, 0x2-2T, 0x80-RPBS"
+										"-9, 0x82-RPBS-15, 0x83-RPBS-23 in "
+										"burst: 0-static, 1- periodic for "
+										"duration: peac time interval"
+										"[micro seconds] in period - full cicle"
+										" time interval[micro seconds]\n");
+	if (devId == MV_6601_DEV_ID) {
+		off += mvOsSPrintf(buf+off, " echo [latency][size] > pcsFrameLimits   - Configure PCS Frame Size "
+											"limits\n");
+		off += mvOsSPrintf(buf+off, " echo [threshold]     > rxDataFifoThresh - Configure RX Parser Data FIFO "
+											"threshold\n");
+		off += mvOsSPrintf(buf+off, " echo [txMask][txP][serdesP][xvrP][burstEn] > ddmTxPolarity - Configure "
+											" DDM Polarity settings\n");
+	}
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, " cat printMask                           - dump printing options\n");
+	off += mvOsSPrintf(buf+off, " cat dbaSwCfgPrint                       - dump DBA cfg\n");
+	if (devId == MV_6601_DEV_ID) {
+		off += mvOsSPrintf(buf+off, " cat pcsFrameLimits                     - dump PCS Frame Size Limits\n");
+		off += mvOsSPrintf(buf+off, " cat rxDataFifoThresh                   - dump RX Parser Data FIFO "
+											"threshold\n");
+	}
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCountersReadClearFlag
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config onu RX enable
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgMacRxEn(MV_U32 enable)
+{
+  mvOnuEponMacOnuRxEnableSet(enable);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgMacTxEn
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config onu mac TX enable
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgMacTxEn(MV_U32 enable, MV_U32 macId)
+{
+	onuEponMiCfgMacTxEn(enable, macId);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgMpcpTimerEn
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config onu mac MPCP timer enable
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgMpcpTimerEn(MV_U32 enable)
+{
+  onuEponIsrTimerMpcpStateSet((enable == 1) ? (MV_TRUE) : (MV_FALSE));
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgMpcpTimerVal
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config onu mac MPCP timer enable
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgMpcpTimerVal(MV_U32 value)
+{
+  onuEponIsrTimerMpcpIntervalSet(value);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgMpcpTimerRandom
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config onu mac MPCP timer random reset
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgMpcpTimerRandom(MV_U32 limit, MV_U32 mask)
+{
+  onuEponIsrTimerMpcpRandomResetSet(limit, mask);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgRprtTimerEn
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config onu periodic report message transmit
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgRprtTimerEn(MV_U32 enable, MV_U32 t0_val, MV_U32 t0_time, MV_U32 t1_val, MV_U32 t1_time)
+{
+  onuEponIsrTimerHwReportStateSet(((enable == 1) ? (MV_TRUE) : (MV_FALSE)),
+							   	  t0_val, t0_time, t1_val, t1_time);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgDbaHwDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure HW DBA queues thresholds for LLID 0
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgDbaHwDebug(MV_U32 queueId, MV_U32 threshold, MV_U32 llid)
+{
+  mvOnuEponMacTxmCppReportQueueX(queueId, (threshold / 64), llid);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgDbaSwRprtDir
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure DBA SW report direction [0]Normal [1]Reverse
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgDbaSwRprtDir(MV_U32 queueSetDir, MV_U32 queueDir)
+{
+  onuEponDbOnuDbaSwModeQueuesetDirSet(queueSetDir);
+  onuEponDbOnuDbaSwModeQueueDirSet(queueDir);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgDbaSwDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function simulate configuration of DBA queues for LLID 0
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgDbaSwDebug(MV_U32 queueSet, MV_U32 queueBitMap,
+						    MV_U32 queueSet0, MV_U32 queueSet1, MV_U32 queueSet2, MV_U32 queueSet3)
+{
+  MV_U32         idx;
+  MV_U32         qsetidx;
+  MV_U32         numOfQueues = 0;
+  S_EponIoctlDba ioctlDba;
+
+  memset (&ioctlDba, 0, sizeof(S_EponIoctlDba));
+
+  for (qsetidx = 0; qsetidx < queueSet; qsetidx++)
+  {
+	for (idx = 0; idx < EPON_MAX_QUEUE; idx++)
+	{
+	  if (queueBitMap & (1 << idx))
+	  {
+		if (qsetidx == 0)
+		{
+			ioctlDba.dbaLlid[0].threshold[qsetidx][idx].state     = 1;
+			ioctlDba.dbaLlid[0].threshold[qsetidx][idx].threshold = queueSet0;
+		}
+		else if (qsetidx == 1)
+		{
+			ioctlDba.dbaLlid[0].threshold[qsetidx][idx].state     = 1;
+			ioctlDba.dbaLlid[0].threshold[qsetidx][idx].threshold = queueSet1;
+		}
+		else if (qsetidx == 2)
+		{
+			ioctlDba.dbaLlid[0].threshold[qsetidx][idx].state     = 1;
+			ioctlDba.dbaLlid[0].threshold[qsetidx][idx].threshold = queueSet2;
+		}
+		else if (qsetidx == 3)
+		{
+			ioctlDba.dbaLlid[0].threshold[qsetidx][idx].state     = 1;
+			ioctlDba.dbaLlid[0].threshold[qsetidx][idx].threshold = queueSet3;
+		}
+
+		if (qsetidx == 0) numOfQueues++;
+	  }
+	}
+  }
+
+  ioctlDba.validLlid[0]              = 1;
+  ioctlDba.dbaLlid[0].numOfQueueSets = queueSet;
+  ioctlDba.dbaLlid[0].numOfQueues    = numOfQueues;
+
+  onuEponMiDbaConfig(&ioctlDba);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgDgCfg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure DG DBA report
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgDgCfg(MV_U32 numOfQueue, MV_U32 queueReport)
+{
+  onuEponPonMngDbaDgSwRprtCfg(numOfQueue, queueReport);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgDbaSwInterval
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure Sw DBA interval
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgDbaSwInterval(MV_U32 interval)
+{
+  onuEponDbOnuSwRprtMacTimerIntervalSet(interval);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgDbaCfgPrint
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print configuration of DBA queues for LLID 0
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+int onuEponUiCfgDbaCfgPrint(char* buf)
+{
+  MV_U32 llidIdx;
+  MV_U32 queueSetIdx;
+  MV_U32 queueIdx;
+  MV_U32 threshold;
+  MV_U32 state;
+  MV_U32 numOfQueueSets;
+  MV_U32 numOfQueues;
+  int off = 0;
+
+  for (llidIdx = 0; llidIdx < EPON_MAX_MAC_NUM; llidIdx++)
+  {
+    if (onuEponDbOnuDbaLlidActiveStatusGet(llidIdx) == ONU_DBA_ACTIVE_LLID)
+    {
+      numOfQueueSets = onuEponDbOnuDbaNumOfQueuesetGet(llidIdx);
+      numOfQueues    = onuEponDbOnuDbaNumOfQueuesGet(llidIdx);
+
+  	  off += mvOsSPrintf(buf+off, "LLID[%d]: #Queuesets = (%d), #Queues = (%d)\n",
+  			             llidIdx, numOfQueueSets, numOfQueues);
+
+      for (queueSetIdx = 0; queueSetIdx < numOfQueueSets; queueSetIdx++)
+      {
+        off += mvOsSPrintf(buf+off, "Queueset[%d]: Queues:", queueSetIdx);
+
+        /* Queue Id */
+        /* ======== */
+        for (queueIdx = 0; queueIdx < EPON_MAX_QUEUE; queueIdx++)
+        {
+      	  onuEponDbOnuDbaQueueThresholdGet(&threshold, &state, queueIdx, queueSetIdx, llidIdx);
+
+      	  off += mvOsSPrintf(buf+off, " [%d-%3s-0x%04x]",
+                             queueIdx, ((state == 0) ? "off" : "on"), ((state == 0) ? 0 : threshold));
+        }
+
+        off += mvOsSPrintf(buf+off, "\n");
+      }
+    }
+  }
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgDbaStaticCfgPrint
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print static configuration of DBA info
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+int onuEponUiCfgDbaStaticCfgPrint(char* buf)
+{
+  MV_U32 llidIdx;
+  MV_U32 queueSetIdx;
+  MV_U32 queueIdx;
+  MV_U32 threshold;
+  MV_U32 state;
+  MV_U32 numOfQueueSets;
+  MV_U32 numOfQueues;
+  int off = 0;
+
+  for (llidIdx = 0; llidIdx < EPON_MAX_MAC_NUM; llidIdx++)
+  {
+    if (onuEponDbOnuDbaLlidActiveStatusGet(llidIdx) == ONU_DBA_ACTIVE_LLID)
+    {
+      numOfQueueSets = onuEponDbOnuDbaNumOfQueuesetGet(llidIdx);
+      numOfQueues    = onuEponDbOnuDbaNumOfQueuesGet(llidIdx);
+
+  	  off += mvOsSPrintf(buf+off, "LLID[%d]: #Queuesets = (%d), #Queues = (%d)\n",
+  			             llidIdx, numOfQueueSets, numOfQueues);
+
+      for (queueSetIdx = 0; queueSetIdx < numOfQueueSets; queueSetIdx++)
+      {
+        off += mvOsSPrintf(buf+off, "Queueset[%d]: Queues:", queueSetIdx);
+
+        /* Queue Id */
+        /* ======== */
+        for (queueIdx = 0; queueIdx < EPON_MAX_QUEUE; queueIdx++)
+        {
+      	  onuEponDbOnuDbaQueueThresholdGet(&threshold, &state, queueIdx, queueSetIdx, llidIdx);
+
+      	  off += mvOsSPrintf(buf+off, " [%d-%3s-0x%04x]",
+                             queueIdx, ((state == 0) ? "off" : "on"), ((state == 0) ? 0 : threshold));
+        }
+
+        off += mvOsSPrintf(buf+off, "\n");
+      }
+    }
+  }
+
+  return(off);
+}
+
+
+
+/*******************************************************************************
+**
+**  onuEponUiCfgHoldoverDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function simulate configuration of Holdover
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgHoldoverDebug(MV_U32 time, MV_U32 state)
+{
+  S_EponIoctlHoldOver ioctlHoldover;
+
+  ioctlHoldover.holdoverState = state;
+  ioctlHoldover.holdoverTime  = time;
+
+  onuEponMiHoldoverConfig(&ioctlHoldover);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgSilenceModeDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function simulate configuration of Silence
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgSilenceModeDebug(MV_U32 state)
+{
+  S_EponIoctlSilence ioctlSilence;
+
+  ioctlSilence.silenceState = state;
+
+  onuEponMiSilenceConfig(&ioctlSilence);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgSilenceSimDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function simulate configuration of Silence
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgSilenceSimDebug(void)
+{
+  MV_STATUS status;
+  S_EponIoctlSilence ioctlSilence;
+
+  ioctlSilence.silenceState = 1;
+
+  onuEponMiSilenceConfig(&ioctlSilence);
+
+  status  = mvOnuEponMacGenOnuConfigAutoAckSet(0);
+  status |= mvOnuEponMacGenOnuConfigAutoRequestSet(0);
+  if (status != MV_OK)
+  {
+	mvPonPrint(PON_PRINT_ERROR, PON_MNG_MODULE,
+			   "ERROR: (%s:%d) Failed to disable auto request / ack\n\r", __FILE_DESC__, __LINE__);
+	return;
+  }
+
+  onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonSilenceTimerId[0]), 0, ONU_PON_TIMER_SILENCE_INTERVAL, 1);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgSilenceDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function simulate reception of DG interrupt
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgDgDebug(MV_U32 dummy)
+{
+  mvOnuPonMacDgInterruptDis();
+  onuPonDyingGaspProcess();
+  onuEponDgIsrRoutine();
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgSetPatternBurst
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config start/stop onu transmission of pattern burst
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgSetPatternBurst(MV_U32 enable, MV_U32 pattern, MV_U32 burst, MV_U32 duration, MV_U32 period)
+{
+  if (enable == 0)
+  {
+    onuPonPatternBurstOff();
+  }
+  else
+  {
+    onuPonPatternBurstOn(pattern, (MV_BOOL)burst, period, duration);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgSetPcsFrameLimits
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures PCS Frame Limits
+**
+**  PARAMETERS:  MV_U32 latency - FED decoder latency in unit of clock cycles
+**               MV_U32 size    - Maximum frame size
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgSetPcsFrameLimits(MV_U32 latency, MV_U32 size)
+{
+	mvOnuEponMacPcsFrameSizeLimitsSet(size, latency);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgShowPcsFrameLimits
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function shows PCS Frame Limits
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+int onuEponUiCfgShowPcsFrameLimits(char* buf)
+{
+	int off = 0;
+	MV_STATUS status;
+	MV_U32 size,latency;
+
+	status = mvOnuEponMacPcsFrameSizeLimitsGet(&size, &latency);
+
+	if (status != MV_OK)
+		off += mvOsSPrintf(buf+off, "Failed to obtain PCS Frame Limits!\n");
+	else {
+		off += mvOsSPrintf(buf+off, "\n");
+		off += mvOsSPrintf(buf+off, "FEC Decoder Latency = %#x\n", latency);
+		off += mvOsSPrintf(buf+off, "Maximum Frame Size  = %#x\n", size);
+	}
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgSetRxDataFifoThresh
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures RX Parser Data FIFO Threshold
+**
+**  PARAMETERS:  MV_U32 threshold - RX Data FIFO MAX allowed capacity
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgSetRxDataFifoThresh(MV_U32 threshold)
+{
+	mvOnuEponMacRxpDataFifoThresholdSet(threshold);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgShowRxDataFifoThresh
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function shows RX Parser Data FIFO Threshold
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+int onuEponUiCfgShowRxDataFifoThresh(char* buf)
+{
+	int off = 0;
+	MV_STATUS status;
+	MV_U32 threshold;
+
+	status = mvOnuEponMacRxpDataFifoThresholdGet(&threshold);
+
+	if (status != MV_OK)
+		off += mvOsSPrintf(buf+off, "Failed to obtain RX Parser Data FIFO Threshold!\n");
+	else {
+		off += mvOsSPrintf(buf+off, "\n");
+		off += mvOsSPrintf(buf+off, "RX Parser Data FIFO Threshold = %#x\n", threshold);
+	}
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuEponUiCfgSetDdmTxPolarity
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures DDM TX polarity
+**
+**  PARAMETERS:  MV_U32 txEnable
+**               MV_U32 txPol
+**               MV_U32 serdesPol
+**               MV_U32 xvrPol
+**               MV_U32 burstEn
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuEponUiCfgSetDdmTxPolarity(MV_U32 txEnable, MV_U32 txPol, MV_U32 serdesPol, MV_U32 xvrPol, MV_U32 burstEn)
+{
+#if (!defined PON_Z1) && (!defined PON_Z2)
+	mvOnuEponMacDdmTxPolaritySet(txEnable, txPol, serdesPol, xvrPol, burstEn);
+#endif
+}
+
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ========================================================================== */
+/* ========================================================================== */
+/*                            ONU SYS FS Definition                           */
+/* ========================================================================== */
+/* ========================================================================== */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Info Group                                      */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Info Commands                                   */
+/* ========================================================================== */
+static ssize_t epon_info_show(struct device *dev,
+                              struct device_attribute *attr,
+                              char *buf)
+{
+  const char* name = attr->attr.name;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  if      (!strcmp(name, "infoEpon"))
+  	return(onuEponUiInfoShow(buf));
+  else if (!strcmp(name, "alarmEpon"))
+    return(onuEponUiAlarmShow(buf));
+  else if (!strcmp(name, "helpEInfo"))
+    return(onuEponUiInfoHelpShow(buf));
+
+  return 0;
+}
+
+static ssize_t epon_info_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t len)
+{
+  const char* name = attr->attr.name;
+  unsigned long flags;
+  unsigned int  param1 = 0;
+  unsigned int  param2 = 0;
+  unsigned int  param3 = 0;
+
+  if (!capable(CAP_NET_ADMIN))
+    return -EPERM;
+
+  sscanf(buf, "%x %x %x", &param1, &param2, &param3);
+
+  raw_local_irq_save(flags);
+
+  if      (!strcmp(name, "readRegEpon"))
+    onuEponUiDebugReadReg((MV_U32)param1, (MV_U32)param2);                     /* readOffset, readEntry */
+  else if (!strcmp(name, "writeRegEpon"))
+    onuEponUiDebugWriteReg((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);    /*  writeOffset, writeEntry, regValue */
+  else
+    printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+  raw_local_irq_restore(flags);
+
+  return(len);
+}
+
+/* ========================================================================== */
+/*                            Info Attributes                                 */
+/* ========================================================================== */
+static DEVICE_ATTR(infoEpon,     S_IRUSR, epon_info_show, epon_info_store);
+static DEVICE_ATTR(alarmEpon,    S_IRUSR, epon_info_show, epon_info_store);
+static DEVICE_ATTR(helpEInfo,    S_IRUSR, epon_info_show, epon_info_store);
+static DEVICE_ATTR(readRegEpon,  S_IWUSR, epon_info_show, epon_info_store);
+static DEVICE_ATTR(writeRegEpon, S_IWUSR, epon_info_show, epon_info_store);
+
+static struct attribute *epon_info_attrs[] = {
+	&dev_attr_infoEpon.attr,
+	&dev_attr_alarmEpon.attr,
+    &dev_attr_readRegEpon.attr,
+    &dev_attr_writeRegEpon.attr,
+    &dev_attr_helpEInfo.attr,
+	NULL
+};
+
+static struct attribute_group epon_info_group =
+{
+  .name = "info",
+  .attrs = epon_info_attrs,
+};
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Pm Group                                        */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Pm Commands                                     */
+/* ========================================================================== */
+static ssize_t epon_pm_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+	const char* name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "rxCnt"))
+		return(onuEponUiRxCountersShow(buf));
+	else if (!strcmp(name, "txCnt"))
+		return(onuEponUiTxCountersShow(buf));
+	else if (!strcmp(name, "swCnt"))
+		return(onuEponUiSwCountersShow(buf));
+	else if (!strcmp(name, "gpmCnt"))
+		return(onuEponUiGpmCountersShow(buf));
+	else if (!strcmp(name, "allCnt"))
+		return(onuEponUiAllCountersShow(buf));
+	else if (!strcmp(name, "showDbaBytesPerLlidQueue"))
+		return(onuEponUiShowLlidQueueBytes(buf));
+	else if (!strcmp(name, "showDbaBytesPerLlidFifo"))
+		return(onuEponUiShowLlidFifoBytes(buf));
+	else if (!strcmp(name, "showRandom"))
+		return(onuEponUiShowRandom(buf));
+	else if (!strcmp(name, "showPcsStat"))
+		return(onuEponUiShowPcsStat(buf));
+	else if (!strcmp(name, "helpPm"))
+		return(onuEponUiPmHelpShow(buf));
+
+	return 0;
+}
+
+static ssize_t epon_pm_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t len)
+{
+	const char* name = attr->attr.name;
+	unsigned long flags;
+	unsigned int  param1 = 0;
+	unsigned int  param2 = 0;
+	unsigned int  param3 = 0;
+
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%d %d %d", &param1, &param2, &param3);
+
+	raw_local_irq_save(flags);
+
+	if (!strcmp(name, "cntRdClrState"))
+		onuEponUiCountersReadClearFlag((MV_BOOL)param1);
+	else if (!strcmp(name, "addDbaBytesPerLlidQueue"))
+		onuEponUiAddLlidQueueBytes(param1, param2, param3);
+	else if (!strcmp(name, "addDbaBytesPerLlidFifo"))
+		onuEponUiAddLlidFifoBytes(param1, param2);
+	else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	raw_local_irq_restore(flags);
+
+  return(len);
+}
+
+/* ========================================================================== */
+/*                            PM Attributes                                   */
+/* ========================================================================== */
+static DEVICE_ATTR(rxCnt,                    S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(txCnt,                    S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(swCnt,                    S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(gpmCnt,                   S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(allCnt,                   S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(showDbaBytesPerLlidQueue, S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(addDbaBytesPerLlidQueue,  S_IWUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(showDbaBytesPerLlidFifo,  S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(addDbaBytesPerLlidFifo,   S_IWUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(cntRdClrState,            S_IWUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(showRandom,               S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(showPcsStat,              S_IRUSR, epon_pm_show, epon_pm_store);
+static DEVICE_ATTR(helpPm,                   S_IRUSR, epon_pm_show, epon_pm_store);
+
+
+static struct attribute *epon_pm_attrs[] = {
+	&dev_attr_rxCnt.attr,
+	&dev_attr_txCnt.attr,
+	&dev_attr_swCnt.attr,
+	&dev_attr_gpmCnt.attr,
+	&dev_attr_allCnt.attr,
+	&dev_attr_showDbaBytesPerLlidQueue.attr,
+	&dev_attr_addDbaBytesPerLlidQueue.attr,
+	&dev_attr_showDbaBytesPerLlidFifo.attr,
+	&dev_attr_addDbaBytesPerLlidFifo.attr,
+	&dev_attr_cntRdClrState.attr,
+	&dev_attr_showRandom.attr,
+	&dev_attr_showPcsStat.attr,
+	&dev_attr_helpPm.attr,
+	NULL
+};
+
+static struct attribute_group epon_pm_group =
+{
+  .name = "pm",
+  .attrs = epon_pm_attrs,
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Cfg Group                                       */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Cfg Commands                                    */
+/* ========================================================================== */
+static ssize_t cfg_show(struct device *dev,
+                        struct device_attribute *attr,
+                        char *buf)
+{
+	const char* name = attr->attr.name;
+	MV_U32 devId = mvCtrlModelGet();
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "printMask"))
+		return ponOnuPrintStatus(buf);
+	else if (!strcmp(name, "dbaSwCfgPrint"))
+		return(onuEponUiCfgDbaCfgPrint(buf));
+	else if (!strcmp(name, "dbaStaticCfgPrint"))
+		return(onuEponUiCfgDbaStaticCfgPrint(buf));
+	else if (!strcmp(name, "helpCfg"))
+		return(onuEponUiCfgHelpShow(buf));
+	else if (devId == MV_6601_DEV_ID) {
+		if (!strcmp(name, "pcsFrameLimits"))
+			return(onuEponUiCfgShowPcsFrameLimits(buf));
+		else if (!strcmp(name, "rxDataFifoThresh"))
+			return(onuEponUiCfgShowRxDataFifoThresh(buf));
+	}
+
+	return 0;
+}
+
+
+static ssize_t cfg_store(struct device *dev,
+                         struct device_attribute *attr,
+                         const char *buf, size_t len)
+{
+	const char* name = attr->attr.name;
+	unsigned long flags;
+	unsigned int  param1 = 0;
+	unsigned int  param2 = 0;
+	unsigned int  param3 = 0;
+	unsigned int  param4 = 0;
+	unsigned int  param5 = 0;
+	unsigned int  param6 = 0;
+	MV_U32 devId = mvCtrlModelGet();
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%x %x %x %x %x %x", &param1, &param2, &param3, &param4, &param5, &param6);
+
+	raw_local_irq_save(flags);
+
+	if (!strcmp(name, "rxEn"))
+		onuEponUiCfgMacRxEn((MV_U32)param1);
+	else if (!strcmp(name, "txEn"))
+		onuEponUiCfgMacTxEn((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "ctrlTimerEn"))
+		onuEponUiCfgMpcpTimerEn((MV_U32)param1);
+	else if (!strcmp(name, "ctrlTimerVal"))
+		onuEponUiCfgMpcpTimerVal((MV_U32)param1);
+	else if (!strcmp(name, "ctrlTimerRandom"))
+		onuEponUiCfgMpcpTimerRandom((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "rprtTimerCfg"))
+		onuEponUiCfgRprtTimerEn((MV_U32)param1, (MV_U32)param2, (MV_U32)param3, (MV_U32)param4, (MV_U32)param5);
+	else if (!strcmp(name, "dbaHwParamsCfg"))
+		onuEponUiCfgDbaHwDebug((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);
+	else if (!strcmp(name, "dbaSwIntervalCfg"))
+		onuEponUiCfgDbaSwInterval((MV_U32)param1);
+	else if (!strcmp(name, "dbaSwParamsCfg"))
+		onuEponUiCfgDbaSwDebug((MV_U32)param1, (MV_U32)param2, (MV_U32)param3, (MV_U32)param4,
+				       (MV_U32)param5, (MV_U32)param6);
+	else if (!strcmp(name, "dbaSwOptionCfg"))
+		onuEponUiCfgDbaSwRprtDir((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "holdoverDebug"))
+		onuEponUiCfgHoldoverDebug((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "silenceMode"))
+		onuEponUiCfgSilenceModeDebug((MV_U32)param1);
+	else if (!strcmp(name, "silenceSim"))
+		onuEponUiCfgSilenceSimDebug();
+	else if (!strcmp(name, "dgDebug"))
+		onuEponUiCfgDgDebug((MV_U32)param1);
+	else if (!strcmp(name, "dgCfg"))
+		onuEponUiCfgDgCfg((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "printMask"))					/* module, print level, options */
+		ponOnuChangePrintStatus((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);
+	else if (!strcmp(name, "pattern"))
+		onuEponUiCfgSetPatternBurst((MV_U32)param1,(MV_U32)param2,(MV_U32)param3,(MV_U32)param4,(MV_U32)param5);
+	else if (devId == MV_6601_DEV_ID) {
+		if (!strcmp(name, "pcsFrameLimits"))
+			onuEponUiCfgSetPcsFrameLimits((MV_U32)param1, (MV_U32)param2);
+		else if (!strcmp(name, "rxDataFifoThresh"))
+			onuEponUiCfgSetRxDataFifoThresh((MV_U32)param1);
+		else if (!strcmp(name, "ddmTxPolarity")) /* txEnable, txPol, serdesPol, xvrPol, burstEn */
+			onuEponUiCfgSetDdmTxPolarity((MV_U32)param1,(MV_U32)param2,(MV_U32)param3,
+						     (MV_U32)param4,(MV_U32)param5);
+		else
+			printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	} else
+		printk("%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	raw_local_irq_restore(flags);
+
+	return(len);
+}
+
+/* ========================================================================== */
+/*                            Cfg Attributes                                  */
+/* ========================================================================== */
+static DEVICE_ATTR(rxEn,                    S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(txEn,                    S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(ctrlTimerEn,             S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(ctrlTimerVal,            S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(ctrlTimerRandom,         S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(rprtTimerCfg,            S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(dbaHwParamsCfg,          S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(dbaSwIntervalCfg,        S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(dbaSwParamsCfg,          S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(dbaSwOptionCfg,          S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(dbaSwCfgPrint,           S_IRUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(dbaStaticCfgPrint,       S_IRUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(holdoverDebug,           S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(silenceMode,             S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(silenceSim,              S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(dgDebug,                 S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(dgCfg,                   S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(pattern,                 S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(printMask,               S_IRUSR | S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(pcsFrameLimits,          S_IWUSR | S_IRUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(rxDataFifoThresh,        S_IWUSR | S_IRUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(ddmTxPolarity,           S_IWUSR, cfg_show, cfg_store);
+static DEVICE_ATTR(helpCfg,                 S_IRUSR, cfg_show, cfg_store);
+
+static struct attribute *cfg_attrs[] = {
+	&dev_attr_rxEn.attr,
+	&dev_attr_txEn.attr,
+	&dev_attr_ctrlTimerEn.attr,
+	&dev_attr_ctrlTimerVal.attr,
+	&dev_attr_ctrlTimerRandom.attr,
+	&dev_attr_rprtTimerCfg.attr,
+	&dev_attr_dbaHwParamsCfg.attr,
+	&dev_attr_dbaSwIntervalCfg.attr,
+	&dev_attr_dbaSwParamsCfg.attr,
+	&dev_attr_dbaSwOptionCfg.attr,
+	&dev_attr_dbaSwCfgPrint.attr,
+	&dev_attr_dbaStaticCfgPrint.attr,
+	&dev_attr_holdoverDebug.attr,
+	&dev_attr_silenceMode.attr,
+	&dev_attr_silenceSim.attr,
+	&dev_attr_dgDebug.attr,
+	&dev_attr_dgCfg.attr,
+	&dev_attr_pattern.attr,
+	&dev_attr_printMask.attr,
+	&dev_attr_pcsFrameLimits.attr,
+	&dev_attr_rxDataFifoThresh.attr,
+	&dev_attr_ddmTxPolarity.attr,
+	&dev_attr_helpCfg.attr,
+	NULL
+};
+
+static struct attribute_group cfg_group =
+{
+  .name = "cfg",
+  .attrs = cfg_attrs,
+};
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            ONU SYS FS                                      */
+/* ========================================================================== */
+/******************************************************************************/
+int epon_sysfs_init(void)
+{
+  int err;
+  struct device *pd;
+
+  pd = bus_find_device_by_name(&platform_bus_type, NULL, "epon");
+  if (!pd) {
+  	platform_device_register_simple("epon", -1, NULL, 0);
+  	pd = bus_find_device_by_name(&platform_bus_type, NULL, "epon");
+  }
+
+  if (!pd) {
+  	printk(KERN_ERR"%s: cannot find epon device\n", __FUNCTION__);
+  	pd = &platform_bus;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &epon_info_group);
+  if (err) {
+  	printk(KERN_INFO "sysfs group failed %d\n", err);
+  	goto out;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &epon_pm_group);
+  if (err) {
+  	printk(KERN_INFO "sysfs group failed %d\n", err);
+  	goto out;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &cfg_group);
+  if (err) {
+  	printk(KERN_INFO "sysfs group failed %d\n", err);
+  	goto out;
+  }
+
+  printk(KERN_INFO "= EPON Module SYS FS Init ended successfully =\n");
+out:
+  return err;
+}
+
+void epon_sysfs_delete(void)
+{
+  struct device *pd;
+
+  pd = bus_find_device_by_name(&platform_bus_type, NULL, "epon");
+  if (!pd)
+  {
+  	printk(KERN_ERR"%s: cannot find epon device\n", __FUNCTION__);
+	return;
+  }
+
+  sysfs_remove_group(&pd->kobj, &epon_info_group);
+  sysfs_remove_group(&pd->kobj, &epon_pm_group);
+  sysfs_remove_group(&pd->kobj, &cfg_group);
+
+  printk(KERN_INFO "= EPON Module SYS FS Remove ended successfully =\n");
+}
+
+
+/*******************************************************************************
+**
+**  onuEponUsrInterfaceCreate
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function create user interface - sys fs
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuEponUsrInterfaceCreate(void)
+{
+  if (epon_sysfs_init() != 0)
+    return(MV_ERROR);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuEponUsrInterfaceRelease
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function release user interface - sys fs
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuEponUsrInterfaceRelease(void)
+{
+  epon_sysfs_delete();
+
+  return(MV_OK);
+}
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.h
new file mode 100755
index 0000000..f8c9cde
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/epon/eponOnuLnxKsUI.h
@@ -0,0 +1,105 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : eponOnuLnxKsUI.h                                           **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU EPON User Interface - SysFs         **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_EPON_LINUX_KS_USR_INTERFACE_H

+#define _ONU_EPON_LINUX_KS_USR_INTERFACE_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuEponUsrInterfaceCreate(void);

+MV_STATUS onuEponUsrInterfaceRelease(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_EPON_LINUX_KS_USR_INTERFACE_H */

+

+  

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.c
new file mode 100755
index 0000000..457c5e7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.c
@@ -0,0 +1,584 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuLnxKsMI.c                                           **

+**                                                                           **

+**  DESCRIPTION : This file implements ONU GPON Management Interface         **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include <linux/version.h>

+#include "gponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/                                               

+#define __FILE_DESC__ "mv_pon/perf/gpon/gponOnuLnxKsMI.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+extern spinlock_t onuPonIrqLock;

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+

+/*******************************************************************************

+**

+**  onuGponMiInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function init onu 

+**               

+**  PARAMETERS:  MV_U32 alloc

+**               MV_U32 tcont 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None

+**                   

+*******************************************************************************/

+MV_STATUS onuGponMiInit(S_GponIoctlInfo *ioctlInfo)

+{

+  return(onuGponStart(ioctlInfo));

+}

+

+/*******************************************************************************

+**

+**  onuGponMiInfoGet

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu info

+**               

+**  PARAMETERS:  S_IoctlInfo *onuInfo 

+**                        

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or MV_ERROR 

+**                   

+*******************************************************************************/

+MV_STATUS onuGponMiInfoGet(S_GponIoctlInfo *onuInfo)

+{

+  MV_U32  uponDebugState;

+

+  uponDebugState = onuGponApiUponDebugGet();

+

+  if (uponDebugState) onuInfo->onuState = ONU_GPON_DEBUG_STATE;

+  else                onuInfo->onuState = onuGponDbOnuStateGet();

+

+  onuInfo->onuId           = onuGponDbOnuIdGet();

+  onuInfo->omccPort        = onuGponDbOmccPortGet();

+  onuInfo->omccValid       = onuGponDbOmccValidGet();

+  onuInfo->onuSignalDetect = onuGponDbOnuSignalDetectGet();

+  onuInfo->onuDsSyncOn     = onuGponDbOnuDsSyncOnGet();

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponMiAlarm

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu alarms

+**               

+**  PARAMETERS:  S_IoctlAlarm *ioctlAlarm

+**                        

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or MV_ERROR 

+**                   

+*******************************************************************************/

+MV_STATUS onuGponMiAlarm(S_GponIoctlAlarm *ioctlAlarm)

+{

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_LOS]  = onuGponAlarmGet(ONU_GPON_ALARM_LOS);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_LOF]  = onuGponAlarmGet(ONU_GPON_ALARM_LOF);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_LCDA] = onuGponAlarmGet(ONU_GPON_ALARM_LCDA);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_LCDG] = onuGponAlarmGet(ONU_GPON_ALARM_LCDG);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_SF]   = onuGponAlarmGet(ONU_GPON_ALARM_SF);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_SD]   = onuGponAlarmGet(ONU_GPON_ALARM_SD);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_TF]   = onuGponAlarmGet(ONU_GPON_ALARM_TF);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_SUF]  = onuGponAlarmGet(ONU_GPON_ALARM_SUF);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_MEM]  = onuGponAlarmGet(ONU_GPON_ALARM_MEM);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_DACT] = onuGponAlarmGet(ONU_GPON_ALARM_DACT);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_DIS]  = onuGponAlarmGet(ONU_GPON_ALARM_DIS);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_MIS]  = onuGponAlarmGet(ONU_GPON_ALARM_MIS);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_PEE]  = onuGponAlarmGet(ONU_GPON_ALARM_PEE);

+  ioctlAlarm->alarmTbl[ONU_GPON_ALARM_RDI]  = onuGponAlarmGet(ONU_GPON_ALARM_RDI);

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponMiPm

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu pm info

+**               

+**  PARAMETERS:  S_IoctlPm *ioctlPm

+**                        

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or MV_ERROR 

+**                   

+*******************************************************************************/

+MV_STATUS onuGponMiPm(S_GponIoctlPm *ioctlPm)

+{

+  MV_STATUS            status;

+  S_GponIoctlPloamTxPm ploamTxPm;

+  S_GponIoctlPloamRxPm ploamRxPm;

+

+  switch (ioctlPm->section) 

+  {

+    case E_GPON_IOCTL_PM_PLOAM_RX:

+      status  = onuGponApiPmRxPloamPmGet(&(ioctlPm->ploamRx), MV_TRUE);

+      status |= onuGponApiAdvancedPloamsCounterGet(&ploamTxPm, &(ioctlPm->ploamRx), MV_TRUE);

+      return(status);

+      break;

+    case E_GPON_IOCTL_PM_PLOAM_TX:

+      status = onuGponApiAdvancedPloamsCounterGet(&(ioctlPm->ploamTx), &ploamRxPm, MV_TRUE);

+      break;

+    case E_GPON_IOCTL_PM_BW_MAP:  

+      return(onuGponApiPmRxBwMapPmGet(&(ioctlPm->bwMap), MV_TRUE));

+      break;

+    case E_GPON_IOCTL_PM_FEC:     

+      return(onuGponApiPmFecPmGet(&(ioctlPm->fec), MV_TRUE));

+      break;

+    case E_GPON_IOCTL_PM_GEM_RX:

+      return(onuGponApiGemRxCounterGet(&(ioctlPm->gemRx), MV_TRUE));

+      break;

+    case E_GPON_IOCTL_PM_GEM_TX:

+      return(onuGponApiGemTxCounterGet(&(ioctlPm->gemTx), MV_TRUE));

+      break;

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponMiTcontConfig

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function configure onu tcont <--> alloc

+**               

+**  PARAMETERS:  MV_U32 alloc

+**               MV_U32 tcont 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None

+**                   

+*******************************************************************************/

+MV_STATUS onuGponMiTcontConfig(MV_U32 alloc, MV_U32 tcont)

+{

+  return(onuGponApiTcontConfig(alloc, tcont));

+}

+

+/*******************************************************************************

+**

+**  onuGponMiResetTcontsConfig

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function reset onu bw map table

+**               

+**  PARAMETERS:  None 

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     None

+**                   

+*******************************************************************************/

+MV_STATUS onuGponMiResetTcontsConfig(void)

+{

+  return(onuGponApiTcontsReset());

+}

+

+/*******************************************************************************

+**

+**  onuGponMiGem

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function return onu pm info

+**               

+**  PARAMETERS:  S_GponIoctlGem *ioctlGem

+**                        

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or MV_ERROR 

+**                   

+*******************************************************************************/

+MV_STATUS onuGponMiGem(S_GponIoctlGem *ioctlGem)

+{

+  MV_STATUS            status = MV_OK;

+ 

+

+  switch (ioctlGem->action) 

+  {

+    case E_GEPON_IOCTL_GEM_ADD:

+      status = onuGponApiGemConfig(ioctlGem->gemmap, ioctlGem->action);

+      break;

+    case E_GEPON_IOCTL_GEM_REMOVE:

+      status = onuGponApiGemConfig(ioctlGem->gemmap, ioctlGem->action);

+      break;

+    case E_GEPON_IOCTL_GEM_CLEARALL:

+        status = onuGponApiGemClearAll(MV_FALSE);

+        break;

+      break;

+  }

+

+  return(status);

+}

+

+

+/*******************************************************************************

+**

+**  mvPonCdevIoctl

+**  ___________________________________________________________________________

+** 

+**  DESCRIPTION: The function execute IO commands

+**               

+**  PARAMETERS:  struct inode *inode

+**               struct file *filp   

+**               unsigned int cmd

+**               unsigned long arg   

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     (0)

+**                   

+*******************************************************************************/

+int mvGponCdevIoctl(struct inode *inode, 

+                    struct file  *filp, 

+                    unsigned int  cmd,

+                    unsigned long arg)

+{

+  MV_STATUS                     status;

+  S_GponIoctlData               ioctlData;

+  S_GponIoctlInfo               ioctlInfo;

+  S_GponIoctlAlarm              ioctlAlarm;

+  S_GponIoctlPm                 ioctlPm;

+  S_GponIoctlXvr                ioctlXvr;

+  S_GponIoctlGem                ioctlGem;  

+  S_GponIoctlGemPortPmConfig    ioctlGemPortPmConfig;

+  S_GponIoctlGemPortMibCounters ioctlGemPortMibCounters;

+  unsigned long                 flags;

+  int                           ret = -EINVAL;

+

+  switch(cmd)

+  {

+    /* =========================== */

+    /* ====== Init Section ======= */

+    /* =========================== */

+

+    /* ====== MVGPON_IOCTL_INIT ==================== */

+    case MVGPON_IOCTL_INIT:

+      if(copy_from_user(&ioctlInfo, (S_GponIoctlInfo*)arg, sizeof(S_GponIoctlInfo)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+	  spin_lock_irqsave(&onuPonIrqLock, flags);

+      status = onuGponMiInit(&ioctlInfo);

+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);

+      if(status != MV_OK)

+        goto ioctlErr;

+      ret = 0;

+      break;

+

+    /* ====== MVGPON_IOCTL_BEN_INIT ================ */

+    case MVGPON_IOCTL_BEN_INIT:

+      if(copy_from_user(&ioctlXvr, (S_GponIoctlXvr*)arg, sizeof(S_GponIoctlXvr)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+	  spin_lock_irqsave(&onuPonIrqLock, flags);

+      status = mvOnuGponMacTxBurstEnParamSet(ioctlXvr.mask, 

+                                             ioctlXvr.polarity, 

+                                             ioctlXvr.delay, 

+                                             ioctlXvr.enStop, 

+                                             ioctlXvr.enStart);

+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);

+      if(status != MV_OK)

+        goto ioctlErr;

+	  onuGponDbXvrPolaritySet(ioctlXvr.polarity);

+	  mvOnuPonMacBurstEnablePolarityInit(ioctlXvr.polarity);

+      ret = 0;

+      break;

+

+    /* =========================== */

+    /* ====== Data Section ======= */

+    /* =========================== */

+

+    /* ====== MVGPON_IOCTL_DATA_TCONT_CONFIG ======= */

+    case MVGPON_IOCTL_DATA_TCONT_CONFIG:

+      if(copy_from_user(&ioctlData, (S_GponIoctlData*)arg, sizeof(S_GponIoctlData)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+	  spin_lock_irqsave(&onuPonIrqLock, flags);

+      status = onuGponMiTcontConfig(ioctlData.alloc, 

+                                    ioctlData.tcont);

+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);

+      if(status != MV_OK)

+        goto ioctlErr;

+      ret = 0;

+      break;

+

+    /* ====== MVGPON_IOCTL_DATA_TCONT_RESET ======== */

+    case MVGPON_IOCTL_DATA_TCONT_RESET:

+	  spin_lock_irqsave(&onuPonIrqLock, flags);

+      status = onuGponMiResetTcontsConfig();

+	  spin_unlock_irqrestore(&onuPonIrqLock, flags);

+      if(status == MV_OK)

+        ret = 0;

+      break;

+

+    /* ====== MVGPON_IOCTL_GEMPORT_STATE_SET ======= */

+    case MVGPON_IOCTL_GEMPORT_STATE_SET:

+      if(copy_from_user(&ioctlData, (S_GponIoctlData*)arg, sizeof(S_GponIoctlData)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);                   

+        goto ioctlErr;

+      }

+      spin_lock_irqsave(&onuPonIrqLock, flags);

+      if(ioctlData.gemState != 0)

+         status = onuGponApiGemPortIdConfig(ioctlData.gemPort);

+      else

+         status = onuGponApiGemPortIdClear(ioctlData.gemPort);

+      spin_unlock_irqrestore(&onuPonIrqLock, flags);

+

+      if(status != MV_OK)

+        goto ioctlErr;

+      ret = 0;

+      break;

+

+    /* ====== MVGPON_IOCTL_GEMPORT_STATE_GET ======= */

+    case MVGPON_IOCTL_GEMPORT_STATE_GET:

+        

+      if(copy_from_user(&ioctlData, (S_GponIoctlData*)arg, sizeof(S_GponIoctlData)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);

+                   

+        goto ioctlErr;

+      }

+      spin_lock_irqsave(&onuPonIrqLock, flags);

+      ioctlData.gemState = mvOnuGponMacPortIdValidGet(ioctlData.gemPort);

+      spin_unlock_irqrestore(&onuPonIrqLock, flags);

+      if(copy_to_user((S_GponIoctlData *)arg, &ioctlData, sizeof(S_GponIoctlData)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);                  

+        goto ioctlErr;

+      }        

+      ret = 0;

+      break;      

+      

+   

+    /* =========================== */

+    /* ====== Info Section ======= */

+    /* =========================== */

+

+    /* ====== MVGPON_IOCTL_INFO ==================== */

+    case MVGPON_IOCTL_INFO:

+      status = onuGponMiInfoGet(&ioctlInfo);

+      if(status != MV_OK)

+        goto ioctlErr;

+      if(copy_to_user((S_GponIoctlInfo*)arg, &ioctlInfo, sizeof(S_GponIoctlInfo)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+      ret = 0;

+      break;

+

+    /* ====== MVGPON_IOCTL_ALARM =================== */

+    case MVGPON_IOCTL_ALARM:

+      status = onuGponMiAlarm(&ioctlAlarm);

+      if(status != MV_OK)

+        goto ioctlErr;

+      if(copy_to_user((S_GponIoctlAlarm*)arg, &ioctlAlarm, sizeof(S_GponIoctlAlarm)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+      ret = 0;

+      break;

+   

+    /* =========================== */

+    /* ====== PM Section ======= */

+    /* =========================== */

+

+    /* ====== MVGPON_IOCTL_PM ==================== */

+    case MVGPON_IOCTL_PM:

+		if(copy_from_user(&ioctlPm, (S_GponIoctlPm*)arg, sizeof(S_GponIoctlPm)))

+		{

+			mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+					   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);

+			goto ioctlErr;

+		}

+      status = onuGponMiPm(&ioctlPm);

+      if(status != MV_OK)

+        goto ioctlErr;

+      if(copy_to_user((S_GponIoctlPm*)arg, &ioctlPm, sizeof(S_GponIoctlPm)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+      ret = 0;

+      break;

+

+    /* ================================== */

+    /* ====== GEM Port PM Section ======= */

+    /* ================================== */

+

+    /* ====== MVGPON_IOCTL_GEMPORT_PM_CONFIG =========== */

+    case MVGPON_IOCTL_GEMPORT_PM_CONFIG:

+      if(copy_from_user(&ioctlGemPortPmConfig, (S_GponIoctlGemPortPmConfig *)arg, sizeof(S_GponIoctlGemPortPmConfig)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+    status = onuGponApiGemPortPmConfig(&ioctlGemPortPmConfig);

+    if(status != MV_OK)

+      goto ioctlErr;

+    ret = 0;

+    break;

+

+    /* ====== MVGPON_IOCTL_GEMPORT_PM_GET =========== */

+    case MVGPON_IOCTL_GEMPORT_PM_GET:

+      if(copy_from_user(&ioctlGemPortMibCounters, (S_GponIoctlGemPortMibCounters *)arg, sizeof(S_GponIoctlGemPortMibCounters)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_from_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+      status = onuGponApiGemPortPmGet(&ioctlGemPortMibCounters);

+      if(status != MV_OK)

+        goto ioctlErr;

+      if(copy_to_user((S_GponIoctlGemPortMibCounters *)arg, &ioctlGemPortMibCounters, sizeof(S_GponIoctlGemPortMibCounters)))

+      {

+        mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                   "ERROR: (%s:%d) copy_to_user failed\n", __FILE_DESC__, __LINE__);

+        goto ioctlErr;

+      }

+      ret = 0;

+      break;

+

+    /* ====== MVGPON_IOCTL_GEMPORT_PM_RESET =========== */

+    case MVGPON_IOCTL_GEMPORT_PM_RESET:

+      status = onuGponPmGemPortPmReset();

+      if(status != MV_OK)

+        goto ioctlErr;

+      ret = 0;

+      break;

+

+	/* ====== MVGPON_IOCTL_GEM ==================== */

+    case MVGPON_IOCTL_GEM:

+        if(copy_from_user(&ioctlGem, (S_GponIoctlGem*)arg, sizeof(S_GponIoctlGem)))

+            {

+              printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);

+              goto ioctlErr;

+            }

+	spin_lock_irqsave(&onuPonIrqLock, flags);

+        status =  onuGponMiGem(&ioctlGem);

+	spin_unlock_irqrestore(&onuPonIrqLock, flags);

+        ret = 0;

+        break;

+

+    default:

+      ret = -EINVAL;

+  }

+

+ioctlErr:

+

+

+

+

+  return(ret);

+}

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.h
new file mode 100755
index 0000000..d091673
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsMI.h
@@ -0,0 +1,318 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuLnxKsMI.h                                           **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Management Interface           **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_LINUX_KS_MNG_INTERFACE_H

+#define _ONU_GPON_LINUX_KS_MNG_INTERFACE_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+#define MVGPON_IOCTL_INIT               _IOW(MVPON_IOCTL_MAGIC, 1,  unsigned int)

+#define MVGPON_IOCTL_BEN_INIT           _IOW(MVPON_IOCTL_MAGIC, 2,  unsigned int)

+#define MVGPON_IOCTL_DATA_TCONT_CONFIG	_IOW(MVPON_IOCTL_MAGIC, 3,  unsigned int)

+#define MVGPON_IOCTL_DATA_TCONT_RESET	 _IO(MVPON_IOCTL_MAGIC, 4)

+#define MVGPON_IOCTL_INFO               _IOR(MVPON_IOCTL_MAGIC, 5,  unsigned int)

+#define MVGPON_IOCTL_ALARM              _IOR(MVPON_IOCTL_MAGIC, 6,  unsigned int)

+#define MVGPON_IOCTL_PM                 _IOR(MVPON_IOCTL_MAGIC, 7,  unsigned int)

+#define MVGPON_IOCTL_GEM                _IOW(MVPON_IOCTL_MAGIC, 8,  unsigned int)

+#define MVGPON_IOCTL_GEMPORT_PM_CONFIG  _IOW(MVPON_IOCTL_MAGIC, 9,  unsigned int)

+#define MVGPON_IOCTL_GEMPORT_PM_GET     _IOR(MVPON_IOCTL_MAGIC, 10, unsigned int)

+#define MVGPON_IOCTL_GEMPORT_PM_RESET   _IOW(MVPON_IOCTL_MAGIC, 11, unsigned int)

+#define MVGPON_IOCTL_GEMPORT_STATE_GET  _IOW(MVPON_IOCTL_MAGIC, 12, unsigned int)

+#define MVGPON_IOCTL_GEMPORT_STATE_SET  _IOW(MVPON_IOCTL_MAGIC, 13, unsigned int)

+

+#define ONU_GPON_DEBUG_STATE        (0xFF)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+typedef enum

+{

+  E_GPON_IOCTL_PM_PLOAM_RX = 1,

+  E_GPON_IOCTL_PM_PLOAM_TX = 2,

+  E_GPON_IOCTL_PM_BW_MAP   = 3,

+  E_GPON_IOCTL_PM_FEC      = 4,

+  E_GPON_IOCTL_PM_GEM_RX   = 5,

+  E_GPON_IOCTL_PM_GEM_TX   = 6

+}E_GponIoctlPmSection;

+

+typedef enum

+{

+  E_GEPON_IOCTL_GEM_ADD         = 1,

+  E_GEPON_IOCTL_GEM_REMOVE      = 2,

+  E_GEPON_IOCTL_GEM_CLEARALL    = 3

+}E_GponIoctlGemAction;

+

+typedef enum

+{

+  GEMPORTPMCMD_STOP  = 0, 

+  GEMPORTPMCMD_START = 1

+}E_GponIoctlGemPortCmd;

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef struct                                                                                                                                

+{                                                                                                                                             

+  MV_U32 rxIdlePloam;                                                                                                                       

+  MV_U32 rxCrcErrorPloam;                                                                                                                   

+  MV_U32 rxFifoOverErrorPloam;                                                                                                              

+  MV_U32 rxBroadcastPloam;                                                                                                                  

+  MV_U32 rxOnuIdPloam;                                                                                                                      

+  MV_U32 rxMsgIdPloam[ONU_GPON_DS_MSG_LAST+1];                                                                                              

+  MV_U32 rxMsgTotalPloam;                                                                                                                   

+}S_GponIoctlPloamRxPm;                                                                                                                            

+

+typedef struct                                                                                                                                

+{                                                                                                                                             

+  MV_U32 txErrMsgIdPloam[ONU_GPON_US_MSG_LAST+1];                                                                                           

+  MV_U32 txMsgIdPloam[ONU_GPON_US_MSG_LAST+1];                                                                                                                                  

+  MV_U32 txMsgTotalPloam;                                                                    

+}S_GponIoctlPloamTxPm;                                                                             

+                                                                                               

+typedef struct                                                                                 

+{                                                                                              

+  MV_U32 allocCrcErr;                                                                        

+  MV_U32 allocCorrectableCrcErr;                                                                                                                                                  

+  MV_U32 allocUnCorrectableCrcErr;                                                                                                             

+  MV_U32 allocCorrec;                                                                                                                          

+  MV_U32 totalReceivedAllocBytes;                                                                                                              

+}S_GponIoctlBwMapPm;                                                                                                                                 

+                                                                                                                                                 

+typedef struct                                                                                                                                   

+{                                                                                                          

+  MV_U32 receivedBytes;                                                                                  

+  MV_U32 correctedBytes;                                                                                                                    

+  MV_U32 correctedBits;                                                                                                                     

+  MV_U32 receivedCodeWords;                                                                                                                 

+  MV_U32 uncorrectedCodeWords;                                                                                                              

+}S_GponIoctlFecPm;                                                                                                                                

+                                                                                                                                              

+typedef struct                                                                                                                                

+{                                                                                                                                             

+  MV_U32 gemRxIdleGemFrames;                                                                                

+  MV_U32 gemRxValidGemFrames;                                                                               

+  MV_U32 gemRxUndefinedGemFrames;                                                                                                                 

+  MV_U32 gemRxOmciFrames;                                                                                                                         

+  MV_U32 gemRxDroppedGemFrames;                                                                                                                   

+  MV_U32 gemRxDroppedOmciFrames;                                                                                                                  

+  MV_U32 gemRxGemFramesWithUncorrHecErr;                                                                                                          

+  MV_U32 gemRxGemFramesWithOneFixedHecErr;                                                                                             

+  MV_U32 gemRxGemFramesWithTwoFixedHecErr;                                                                                             

+  MV_U32 gemRxTotalByteCountOfReceivedValidGemFrames;                                                                                  

+  MV_U32 gemRxTotalByteCountOfReceivedUndefinedGemFrames;                                                                              

+  MV_U32 gemRxGemReassembleMemoryFlush;                                                                                                

+  MV_U32 gemRxGemSynchLost;                                                                                                            

+  MV_U32 gemRxEthFramesWithCorrFcs;                                                                                                    

+  MV_U32 gemRxEthFramesWithFcsError;                                                                                                   

+  MV_U32 gemRxOmciFramesWithCorrCrc;                                                                                                   

+  MV_U32 gemRxOmciFramesWithCrcError;                                                                                                  

+}S_GponIoctlGemRxPm;              

+

+typedef struct                                                                                                            

+{                                                                                                                         

+  MV_U32 gemTxGemPtiTypeOneFrames;                                                                                      

+  MV_U32 gemTxGemPtiTypeZeroFrames;                                                                                     

+  MV_U32 gemTxIdleGemFrames;                                                                                            

+  MV_U32 gemTxEthFramesViaTconti[ONU_GPON_MAX_NUM_OF_T_CONTS];                                                          

+  MV_U32 gemTxEthBytesViaTconti[ONU_GPON_MAX_NUM_OF_T_CONTS];                                                           

+  MV_U32 gemTxGemFramesViaTconti[ONU_GPON_MAX_NUM_OF_T_CONTS];                                                           

+  MV_U32 gemTxIdleGemFramesViaTconti[ONU_GPON_MAX_NUM_OF_T_CONTS];                                                      

+}S_GponIoctlGemTxPm;                                                                                                          

+                                                                                                                          

+typedef struct                                                                                                            

+{                                                                                                                         

+  unsigned int  section;                                                                                                  

+  union                                                                                                                   

+  {                                                                                                                       

+    S_GponIoctlPloamRxPm ploamRx;                                                                                             

+    S_GponIoctlPloamTxPm ploamTx;                                                                                             

+    S_GponIoctlBwMapPm   bwMap;                                                             

+    S_GponIoctlFecPm     fec;                                                                             

+    S_GponIoctlGemRxPm   gemRx;                                                                           

+    S_GponIoctlGemTxPm   gemTx;                                                                           

+  };                                                                                                  

+}S_GponIoctlPm;                                                                                           

+                                                                                                      

+typedef struct                                                                                        

+{                                                                                                     

+  MV_U32 alarmTbl[ONU_GPON_NUM_OF_ALARMS];                                                      

+}S_GponIoctlAlarm;                                                                                        

+                                                                                                      

+typedef struct                                                                                         

+{                                                                                        

+  MV_U32 onuId;      

+  MV_U32 onuState;      

+  MV_U32 onuSignalDetect;      

+  MV_U32 onuDsSyncOn;

+  MV_U32 omccPort;                                                                 

+  MV_U32 omccValid;  

+  MV_U32 serialNumSource;

+  MV_U8  serialNum[8];                                                            

+  MV_U8  password[10];     

+  MV_U32 disableSn;

+  MV_U32 clearGem;  

+  MV_U32 clearTcont;

+  MV_U32 restoreGem;

+  MV_U32 dgPolarity;

+  MV_U32 xvrPolarity;

+}S_GponIoctlInfo;  

+                                                                                         

+typedef struct                                                                           

+{                                                                                        

+  MV_U32 alloc;                                                                    

+  MV_U32 tcont;    

+  MV_U32 gemPort;                                                                    

+  MV_U32 gemState;    

+}S_GponIoctlData;                                                                            

+                                                                                         

+typedef struct                                                                           

+{

+  MV_U32 mask;   

+  MV_U32 polarity;

+  MV_U32 delay;  

+  MV_U32 enStop; 

+  MV_U32 enStart;

+}S_GponIoctlXvr;

+

+/* Gem */

+typedef struct                                                                           

+{   

+  uint32_t             gemmap[GPON_ONU_MAX_GEM_PORTS/32];   

+  E_GponIoctlGemAction action;

+}S_GponIoctlGem;

+

+typedef struct

+{

+  E_GponIoctlGemPortCmd command;

+  MV_U16                gem_port;

+}S_GponIoctlGemPortPmConfig;

+

+typedef struct

+{

+  MV_U16  gem_port;

+

+  MV_U64  good_octets_received;

+  MV_U32  bad_octets_received;

+  MV_U32  mac_trans_error;

+  MV_U32  good_frames_received;

+  MV_U32  bad_frames_received;

+  MV_U32  broadcast_frames_received;

+  MV_U32  multicast_frames_received;

+  MV_U32  frames_64_octets;

+  MV_U32  frames_65_to_127_octets;

+  MV_U32  frames_128_to_255octets;

+  MV_U32  frames_256_to_511_octets;

+  MV_U32  frames_512_to_1023_octets; 

+  MV_U32  frames_1024_to_max_octets; 

+  MV_U64  good_octets_sent;

+  MV_U32  good_frames_sent;

+  MV_U32  multicast_frames_sent;

+  MV_U32  broadcast_frames_sent;

+  MV_U32  bad_crc_received;

+} S_GponIoctlGemPortMibCounters;

+

+typedef struct 

+{

+  S_GponIoctlInfo  g_info;

+  S_GponIoctlAlarm alarm;

+  S_GponIoctlPm    g_pm;

+  S_GponIoctlData  data;

+  struct cdev      cdev;

+}S_GponModuleCdev;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+MV_STATUS onuGponMngInterfaceCreate(void);

+MV_STATUS onuGponMngInterfaceRelease(void);

+void      onuGponMiNotifyCallback(MV_U32 onuState);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_LINUX_KS_MNG_INTERFACE_H */

+

+  

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.c
new file mode 100755
index 0000000..7467f76
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.c
@@ -0,0 +1,4067 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuLnxKsUI.c                                           **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU GPON CLI functionality            **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "gponOnuHeader.h"
+
+#ifndef PON_FPGA
+#include "mvSysPonConfig.h"
+#endif /* PON_FPGA */
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/perf/gpon/gponOnuLnxKsUI.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+MV_BOOL infoGponCntReadClearInd = MV_TRUE;
+MV_U32  maxPloamsSend = 270;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Info Commands                                   */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponUiInfoShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu information
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiInfoShow(char* buf)
+{
+  MV_U8   *stateText[] = {"",
+                           "INITIAL",
+                           "STANDBY",
+                           "SERIAL NUMBER",
+                           "RANGING",
+                           "OPERATION",
+                           "POPUP",
+                           "EMERGENCY STOP"};
+  MV_U8   *boolText[] = {"FALSE","TRUE"};
+  MV_U8   serialNumber[8];
+  MV_U8   password[10];
+  MV_U32  onuId,onuState;
+  MV_BOOL init,omcc,snMaskEnable,snMaskMatchMode;
+  MV_U32  berInt, dummy,omccPort;
+  MV_U32  guard,pre1Size;
+  MV_U32  pre2Size,pre3RaSize,pre3OpSize,pre3Pat;
+  MV_U32  dbDelimiter,asicDelimiter,sd,sf;
+  MV_U32  intDelay,eqdDb,eqdAsic,fDelay;
+  MV_U32  snMsg[3], idleMsg[3];
+  MV_U8   *mchText[] = {"NO MATCH","MATCH "};
+  int     off = 0;
+
+                    onuGponDbSerialNumGet(serialNumber);
+  onuState        = onuGponDbOnuStateGet();
+  onuId           = onuGponDbOnuIdGet();
+  init            = onuGponDbInitGet();
+  omcc            = onuGponDbOmccValidGet();
+  omccPort        = onuGponDbOmccPortGet();
+  snMaskEnable    = onuGponDbSerialNumberMaskEnableGet();
+  snMaskMatchMode = onuGponDbSerialNumberMaskMatchGet();
+                    onuGponDbPasswordGet(password);
+  guard           = onuGponDbGuardBitsGet();
+  berInt          = onuGponDbBerIntervalGet();
+                    onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_01,&dummy,&pre1Size);
+                    onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_02,&dummy,&pre2Size);
+                    onuGponDbPreambleGet(ONU_GPON_PREM_TYPE_03,&pre3Pat,&dummy);
+  pre3OpSize      = onuGponDbExtPreambleOperGet();
+  pre3RaSize      = onuGponDbExtPreambleSyncGet();
+  sd              = onuGponDbSdThresholdGet();
+  sf              = onuGponDbSfThresholdGet();
+  intDelay        = onuGponDbConstDelayGet();
+  eqdDb           = onuGponDbEqualizationDelayGet();
+                    mvOnuGponMacRxEqualizationDelayGet(&eqdAsic);
+                    mvOnuGponMacTxFinalDelayGet(&fDelay);
+  dbDelimiter     = onuGponDbDelimiterGet(ONU_GPON_DELM_BYTE_01) |
+                   (onuGponDbDelimiterGet(ONU_GPON_DELM_BYTE_02) << 8) |
+                   (onuGponDbDelimiterGet(ONU_GPON_DELM_BYTE_03) << 16);
+                    mvOnuGponMacTxDelimiterGet(&asicDelimiter,&dummy);
+                    onuGponDbSnMsgGet(snMsg);
+                    onuGponDbIdleMsgGet(idleMsg);
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "ONT Full Information:\n");
+  off += mvOsSPrintf(buf+off, "---------------------\n");
+  off += mvOsSPrintf(buf+off, "SN[VENDOR ID]:                 %02X:%02X:%02X:%02X [%c%c%c%c]\n",
+                     serialNumber[0],serialNumber[1],serialNumber[2],serialNumber[3],
+                     serialNumber[0],serialNumber[1],serialNumber[2],serialNumber[3]);
+  off += mvOsSPrintf(buf+off, "SN[Serial Number]:             %02X:%02X:%02X:%02X\n",
+                     serialNumber[4],serialNumber[5],serialNumber[6],serialNumber[7]);
+  off += mvOsSPrintf(buf+off, "ONU ID:                        %d\n", onuId);
+  off += mvOsSPrintf(buf+off, "ONU STATE:                     %d [%s]\n", onuState, stateText[onuState]);
+  off += mvOsSPrintf(buf+off, "INIT STATE:                    %s\n", boolText[init]);
+  off += mvOsSPrintf(buf+off, "OMCC Valid:                    %s\n", boolText[omcc]);
+  off += mvOsSPrintf(buf+off, "OMCC Port:                     %d\n", omccPort);
+  off += mvOsSPrintf(buf+off, "Password:                      %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X\n",
+                     password[0],password[1],password[2],password[3],password[4],
+                     password[5],password[6],password[7],password[8],password[9]);
+  off += mvOsSPrintf(buf+off, "BER Interval:                  %d\n", berInt);
+  off += mvOsSPrintf(buf+off, "SD Threshold:                  %d\n", sd);
+  off += mvOsSPrintf(buf+off, "SF Threshold:                  %d\n", sf);
+  off += mvOsSPrintf(buf+off, "Guard Bits:                    %d\n", guard);
+  off += mvOsSPrintf(buf+off, "Preamble Type1 Size:           %d\n", pre1Size);
+  off += mvOsSPrintf(buf+off, "Preamble Type2 Size:           %d\n", pre2Size);
+  off += mvOsSPrintf(buf+off, "Preamble Type3 Pattern:        0x%02X\n", pre3Pat);
+  off += mvOsSPrintf(buf+off, "Preamble Type3 Range Size:     %d\n", pre3RaSize);
+  off += mvOsSPrintf(buf+off, "Preamble Type3 Oper Size:      %d\n", pre3OpSize);
+  off += mvOsSPrintf(buf+off, "Delimiter:                     0x%08X [0x%08X]\n", dbDelimiter, asicDelimiter);
+  off += mvOsSPrintf(buf+off, "Internal Delay:                %d [0x%x]\n", intDelay, intDelay);
+  off += mvOsSPrintf(buf+off, "Equalization Delay:            %d [0x%x] (HW:0x%x)\n", eqdDb, eqdDb, eqdAsic);
+  off += mvOsSPrintf(buf+off, "Final Delay:                   %d\n", fDelay);
+  off += mvOsSPrintf(buf+off, "Const Idle Ploam:              [0x%08X][0x%08X][0x%08X]\n", idleMsg[0],idleMsg[1],idleMsg[2]);
+  off += mvOsSPrintf(buf+off, "Const Serial Number Ploam:     [0x%08X][0x%08X][0x%08X]\n", snMsg[0],snMsg[1],snMsg[2]);
+  off += mvOsSPrintf(buf+off, "Serial Number Mask Enable:     %s\n", boolText[snMaskEnable]);
+  off += mvOsSPrintf(buf+off, "Serial Number Mask Match Mode: %s\n", mchText [snMaskMatchMode]);
+  off += mvOsSPrintf(buf+off, "Debug Mode:                    %s\n", boolText[onuGponPonMngDebugModeGet()]);
+  off += mvOsSPrintf(buf+off, "Overhead Manual Mode:          %s\n", boolText[onuGponPonMngOverheadManualModeGet()]);
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiAlarmShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu alarms
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiAlarmShow(char* buf)
+{
+  MV_STATUS rcode;
+  MV_U32    alarms;
+  MV_U32    iAlarm;
+  MV_U8     *alarmText[] = {"LOS ","LOF ","LCDA","LCDG"," SF "," SD "," TF ",
+                            "SUF ","MEM ","DACT","DIS ","MIS ","PEE ","RDI "};
+  MV_U8     *statusText[] = {"OFF","ON "};
+  MV_U32    status;
+  int       off = 0;
+
+  rcode = onuGponApiAlarmsGet(&alarms);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get alarms status, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "------------------\n");
+  off += mvOsSPrintf(buf+off, "|ONU ALARMS:     |\n");
+  off += mvOsSPrintf(buf+off, "------------------\n");
+  off += mvOsSPrintf(buf+off, "| ALARM | STATUS |\n");
+  off += mvOsSPrintf(buf+off, "------------------\n");
+
+  for (iAlarm = 0 ; iAlarm < ONU_GPON_MAX_ALARMS ; iAlarm++)
+  {
+    status = (alarms >> iAlarm) & 0x01;
+    off += mvOsSPrintf(buf+off, " %s   | %s    |\n", alarmText[iAlarm], statusText[status]);
+  }
+
+  off += mvOsSPrintf(buf+off, "------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiFifoShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function prints US PLOAM statistics
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiFifoShow(char* buf)
+{
+  S_MacFifoCtrl*  fifo;
+  int             auditEn, auditAc, fifoSup;
+  int             msgSend, allocFifo, freeFifo, ploamSend;
+  int             off = 0;
+
+  mvOnuGponMacFifoGetInfo(&fifo, &fifoSup);
+  mvOnuGponMacFifoGetStat(&msgSend, &allocFifo, &freeFifo, &ploamSend);
+  mvOnuGponMacFifoAuditGetStat(&auditEn, &auditAc);
+
+  if (fifoSup)
+  {
+    off += mvOsSPrintf(buf+off, "===========================\n");
+    off += mvOsSPrintf(buf+off, "GPON SW FIFO\n");
+    off += mvOsSPrintf(buf+off, "===========================\n");
+    off += mvOsSPrintf(buf+off, "FIFO size               %d\n", GPON_SW_FIFO_SIZE);
+    off += mvOsSPrintf(buf+off, "Write index             %d\n", fifo->fifoWriteIndex);
+    off += mvOsSPrintf(buf+off, "Read index              %d\n", fifo->fifoReadIndex);
+    off += mvOsSPrintf(buf+off, "Repeating cycle number  %d\n", fifo->fifoReparoundNum);
+    off += mvOsSPrintf(buf+off, "===========================\n");
+    off += mvOsSPrintf(buf+off, "FIFO Audit Enter cnt.   %d\n", auditEn);
+    off += mvOsSPrintf(buf+off, "FIFO Audit Action cnt.  %d\n", auditAc);
+  }
+
+  off += mvOsSPrintf(buf+off, "===========================\n");
+  off += mvOsSPrintf(buf+off, "US msg. send cnt.       %d\n", msgSend);
+
+  if (fifoSup)
+  {
+    off += mvOsSPrintf(buf+off, "Add to SW FIFO cnt.     %d\n", allocFifo);
+    off += mvOsSPrintf(buf+off, "Free SW FIFO cnt.       %d\n", freeFifo);
+  }
+
+  off += mvOsSPrintf(buf+off, "Add to HW FIFO cnt.     %d\n", ploamSend);
+  off += mvOsSPrintf(buf+off, "===========================\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiFecStatus
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function prints DS FEC Statsus
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiFecStatus(char* buf)
+{
+  MV_U32 fecMode;
+  int off = 0;
+
+  onuGponApiFecStatusGet(&fecMode);
+
+  off += mvOsSPrintf(buf+off, "GPON FEC Status - %s\n", (fecMode == 0) ? ("Off") : ("On"));
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiInfoHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print info help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiInfoHelpShow(char* buf)
+{
+  int off = 0;
+
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " cat info      - dump onu information\n");
+  off += mvOsSPrintf(buf+off, " cat alarm     - dump onu alarms\n");
+  off += mvOsSPrintf(buf+off, " cat fecStatus - dump onu fec status\n");
+  off += mvOsSPrintf(buf+off, " cat swfifo    - dump onu SW FIFO info\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+
+  return(off);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            PM Commands                                     */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponUiCountersReadClearFlag
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu FEC counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuGponUiCountersReadClearFlag(MV_BOOL clear)
+{
+	infoGponCntReadClearInd = clear;
+}
+
+/*******************************************************************************
+**
+**  onuGponBwMapCountersEnDisFlag
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu FEC counters
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponBwMapCountersEnDisFlag(MV_BOOL enable)
+{
+    return (onuGponApiPmRxBwMapPmDumpSet(enable));
+}
+
+/*******************************************************************************
+**
+**  onuGponUiFecCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu FEC counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiFecCountersShow(char* buf)
+{
+  MV_STATUS        rcode;
+  S_GponIoctlFecPm counters;
+  int              off = 0;
+
+  MV_U8  *counterText[] = {"FEC received Bytes       ",
+                           "FEC corrected Bytes      ",
+                           "FEC corrected Bits       ",
+                           "FEC received CodeWords   ",
+                           "FEC uncorrected CodeWords"};
+
+  rcode = onuGponApiPmFecPmGet(&counters,infoGponCntReadClearInd);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get counters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "------------------\n");
+  off += mvOsSPrintf(buf+off, "| FEC COUNTERS:   |\n");
+  off += mvOsSPrintf(buf+off, "--------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| COUNTER                   |   VALUE      |\n");
+  off += mvOsSPrintf(buf+off, "--------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[0],counters.receivedBytes);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[1],counters.correctedBytes);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[2],counters.correctedBits);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[3],counters.receivedCodeWords);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[4],counters.uncorrectedCodeWords);
+  off += mvOsSPrintf(buf+off, "--------------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiRxPloamCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu Rx Ploam counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiRxPloamCountersShow(char* buf)
+{
+  MV_STATUS            rcode;
+  S_GponIoctlPloamRxPm counters;
+  S_GponIoctlPloamTxPm countDummy;
+  MV_U32               MsgId;
+  int                  off = 0;
+
+  MV_U8 *counterText[] = {"Idle Ploam Counter                 ",
+                          "CRC Error Ploam Counter            ",
+                          "FIFO Overflaw Error Ploam Counter  ",
+                          "received Broadcast Ploam Counter   ",
+                          "Received Onu Id Ploam Counter      "};
+
+  MV_U8 *msgIdCntText  =  {"Total PLOAM        "};
+  MV_U8 *msgIdText[]   =  {"ERROR PLOAM        ",
+                           "OVERHEAD           ",
+                           "SN_MASK            ",
+                           "ASSIGN_ONU_ID      ",
+                           "RANGING_TIME       ",
+                           "DACT_ONU_ID        ",
+                           "DIS_SN             ",
+                           "CONFIG_VP_VC       ",
+                           "ENCRYPT_VPI_PORT_ID",
+                           "REQ_PASSWORD       ",
+                           "ASSIGN_ALLOC_ID    ",
+                           "NO_MESSAGE         ",
+                           "POPUP              ",
+                           "REQ_KEY            ",
+                           "CONFIG_PORT_ID     ",
+                           "PHYSICAL_EQUIP_ERR ",
+                           "CHANGE_POWER_LEVEL ",
+                           "PST                ",
+                           "BER_INTERVAL       ",
+                           "KEY_SWITCH_TIME    ",
+                           "EXT_BURST_LEN      "};
+
+  rcode  = onuGponApiPmRxPloamPmGet(&counters, infoGponCntReadClearInd);
+  rcode |= onuGponApiAdvancedPloamsCounterGet(&countDummy, &counters, infoGponCntReadClearInd);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get counters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "-------------------------\n");
+  off += mvOsSPrintf(buf+off, "|RX PLOAM COUNTERS:     |\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| HW COUNTERS                          |    VALUE    |\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[0],counters.rxIdlePloam);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[1],counters.rxCrcErrorPloam);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[2],counters.rxFifoOverErrorPloam);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[3],counters.rxBroadcastPloam);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[4],counters.rxOnuIdPloam);
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| SW COUNTERS          |    VALUE    |\n");
+  off += mvOsSPrintf(buf+off, "--------------------------------------\n");
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", msgIdCntText, counters.rxMsgTotalPloam);
+
+  for (MsgId = 0; MsgId <= ONU_GPON_DS_MSG_LAST; MsgId++)
+    off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", msgIdText[MsgId], counters.rxMsgIdPloam[MsgId]);
+
+  off += mvOsSPrintf(buf+off, "--------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiTxPloamCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu Tx Ploam counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiTxPloamCountersShow(char* buf)
+{
+  MV_STATUS            rcode;
+  S_GponIoctlPloamRxPm countDummy;
+  S_GponIoctlPloamTxPm counters;
+  MV_U32               MsgId;
+  int                  off = 0;
+
+  MV_U8 *msgIdText[] = {"Total Ploams Recived",
+                        "SN_ONU              ",
+                        "PASSWORD            ",
+                        "DYING_GASP          ",
+                        "NO_MESSAGE          ",
+                        "ENCRYPT_KEY         ",
+                        "PHYSICAL_EQUIP_ERR  ",
+                        "PST                 ",
+                        "REI                 ",
+                        "ACK                 "};
+
+  rcode = onuGponApiAdvancedPloamsCounterGet(&counters, &countDummy, infoGponCntReadClearInd);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get counters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "-------------------------\n");
+  off += mvOsSPrintf(buf+off, "|TX PLOAM COUNTERS:     |\n");
+  off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| COUNTER             |    VALUE    |\n");
+  off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+  off += mvOsSPrintf(buf+off, " %s | %10d  |\n", msgIdText[0], counters.txMsgTotalPloam);
+  off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| TX Error            |    VALUE    |\n");
+  off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+
+  for (MsgId=1;MsgId <= ONU_GPON_US_MSG_LAST; MsgId++)
+  {
+    off += mvOsSPrintf(buf+off, " %s | %10d  |\n", msgIdText[MsgId], counters.txErrMsgIdPloam[MsgId]);
+
+  }
+
+  off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| TX Correct          |    VALUE    |\n");
+  off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+
+  for (MsgId=1;MsgId <= ONU_GPON_US_MSG_LAST; MsgId++)
+  {
+    off += mvOsSPrintf(buf+off, " %s | %10d  |\n", msgIdText[MsgId], counters.txMsgIdPloam[MsgId]);
+  }
+
+  off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiBwMapCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu bw map counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiBwMapCountersShow(char* buf)
+{
+  MV_STATUS          rcode;
+  S_GponIoctlBwMapPm counters;
+  int                off = 0;
+
+  MV_U8 *counterText[] = {"Alloc Crc Error               ",
+                          "Alloc Correctable Crc Error   ",
+                          "Alloc UnCorrectable Crc Error ",
+                          "Alloc Correct                 ",
+                          "Total Received Alloc Bytes    "};
+
+  rcode = onuGponApiPmRxBwMapPmGet(&counters, infoGponCntReadClearInd);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get counters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "----------------------\n");
+  off += mvOsSPrintf(buf+off, "| BWMAP COUNTERS:    |\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| COUNTER                         |   VALUE    |\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, " %s   | %10u |\n", counterText[0],counters.allocCrcErr);
+  off += mvOsSPrintf(buf+off, " %s   | %10u |\n", counterText[1],counters.allocCorrectableCrcErr);
+  off += mvOsSPrintf(buf+off, " %s   | %10u |\n", counterText[2],counters.allocUnCorrectableCrcErr);
+  off += mvOsSPrintf(buf+off, " %s   | %10u |\n", counterText[3],counters.allocCorrec);
+  off += mvOsSPrintf(buf+off, " %s   | %10u |\n", counterText[4],counters.totalReceivedAllocBytes);
+  off += mvOsSPrintf(buf+off, "------------------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiStandardCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu standard counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiStandardCountersShow(char* buf)
+{
+  MV_STATUS         rcode;
+  S_RxStandardApiPm counters;
+  int               off = 0;
+
+  MV_U8 *counterText[] = {"bip8 Error Counter     ",
+                          "plend Counter          "};
+
+  rcode = onuGponApiPmRxStandardPmGet(&counters, infoGponCntReadClearInd);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get counters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "-------------------------\n");
+  off += mvOsSPrintf(buf+off, "|STANDARD COUNTERS:     |\n");
+  off += mvOsSPrintf(buf+off, "-----------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| COUNTER                  |    VALUE   |\n");
+  off += mvOsSPrintf(buf+off, "-----------------------------------------\n");
+  off += mvOsSPrintf(buf+off, " %s   | %8u   |\n", counterText[0],counters.bip8);
+  off += mvOsSPrintf(buf+off, " %s   | %8u   |\n",counterText[1],counters.plend);
+  off += mvOsSPrintf(buf+off, "-----------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiGemCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu gem counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiGemCountersShow(char* buf)
+{
+  MV_STATUS          rcode;
+  S_GponIoctlGemRxPm counters;
+  int                off = 0;
+
+  MV_U8 *counterText[] = {"Received Idle Gem Frames                       ",
+                          "Received Valid Gem Frames                      ",
+                          "Received Undefined Gem Frames                  ",
+                          "Received Omci Frames                           ",
+                          "Dropped Gem Frames                             ",
+                          "Dropped Omci Frames                            ",
+                          "Received Gem Frames With Uncorr Hec Error      ",
+                          "Received Gem Frames With One Fixed Hec Error   ",
+                          "Received Gem Frames With Two Fixed Hec Error   ",
+                          "Received Valid Gem Frames Total Byte Count     ",
+                          "Received Undefined Gem Frames Total Byte Count ",
+                          "Gem Reassemble Memory Flush                    ",
+                          "Gem Synch Lost                                 ",
+                          "Received Eth Frames With Correct FCS           ",
+                          "Received Eth Frames With FCS Error             ",
+                          "Received Omci Frames With Correct CRC          ",
+                          "Received Omci Frames With CRC Error            "};
+
+  rcode = onuGponApiGemRxCounterGet(&counters, infoGponCntReadClearInd);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get counters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "----------------------\n");
+  off += mvOsSPrintf(buf+off, "|GEM COUNTERS:       |\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| COUNTER                                          |  VALUE      |\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------------------\n");
+
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[0], counters.gemRxIdleGemFrames);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[1], counters.gemRxValidGemFrames);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[2], counters.gemRxUndefinedGemFrames);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[3], counters.gemRxOmciFrames);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[4], counters.gemRxDroppedGemFrames);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[5], counters.gemRxDroppedOmciFrames);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[6], counters.gemRxGemFramesWithUncorrHecErr);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[7], counters.gemRxGemFramesWithOneFixedHecErr);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[8], counters.gemRxGemFramesWithTwoFixedHecErr);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[9], counters.gemRxTotalByteCountOfReceivedValidGemFrames);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[10],counters.gemRxTotalByteCountOfReceivedUndefinedGemFrames);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[11],counters.gemRxGemReassembleMemoryFlush);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[12],counters.gemRxGemSynchLost);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[13],counters.gemRxEthFramesWithCorrFcs);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[14],counters.gemRxEthFramesWithFcsError);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[15],counters.gemRxOmciFramesWithCorrCrc);
+  off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[16],counters.gemRxOmciFramesWithCrcError);
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiTxCountersShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu tx counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiTxCountersShow(char* buf)
+{
+	MV_STATUS          rcode;
+	S_GponIoctlGemTxPm counters;
+	MV_BOOL            exist;
+	MV_U32             tcont;
+	int                off = 0;
+
+	MV_U8 *counterText[] = {"Transmitted Gem Pti Type-1 Frames              ",
+							"Transmitted Gem Pti Type-0 Frames              ",
+							"Transmitted Idle Gem Frames                    ",
+							"Transmitted Eth Frames Via Tcont               ",
+							"Transmitted Eth Bytes Via Tcont                ",
+							"Transmitted Gem Frames Via Tcont               ",
+							"Transmitted Idle Gem Frames Via Tcont          "};
+
+	rcode = onuGponApiGemTxCounterGet(&counters, infoGponCntReadClearInd);
+	if (rcode != MV_OK) {
+		mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+				   "%s:%d, failed to get counters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+	}
+
+	off += mvOsSPrintf(buf+off, "\n");
+	off += mvOsSPrintf(buf+off, "----------------------\n");
+	off += mvOsSPrintf(buf+off, "|TX COUNTERS:        |\n");
+	off += mvOsSPrintf(buf+off, "------------------------------------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "| COUNTER                                          |  VALUE      |\n");
+	off += mvOsSPrintf(buf+off, "------------------------------------------------------------------\n");
+	off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[0],counters.gemTxGemPtiTypeOneFrames);
+	off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[1],counters.gemTxGemPtiTypeZeroFrames);
+	off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[2],counters.gemTxIdleGemFrames);
+
+	for (tcont = 0; tcont < ONU_GPON_MAX_NUM_OF_T_CONTS; tcont++) {
+		rcode = onuGponDbBwTcontExist(tcont, &exist);
+		if ((rcode == MV_OK) && (exist != MV_FALSE)) {
+			off += mvOsSPrintf(buf+off, "T-Cont [%d] Counters                                              |\n", tcont);
+			off += mvOsSPrintf(buf+off, "------------------------------------------------------------------\n");
+			off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[3],counters.gemTxEthFramesViaTconti[tcont]);
+			off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[4],counters.gemTxEthBytesViaTconti[tcont]);
+			off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[5],counters.gemTxGemFramesViaTconti[tcont]);
+			off += mvOsSPrintf(buf+off, " %s   | %10u  |\n", counterText[6],counters.gemTxIdleGemFramesViaTconti[tcont]);
+		}
+	}
+
+	off += mvOsSPrintf(buf+off, "------------------------------------------------------------------\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiRawCounters
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu counters
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiRaw_1Counters(char* buf)
+{
+  MV_U32      suspected;
+  MV_U32      decided;
+  S_RxPloamPm inRxPloamCounters;
+  S_RxBwMapPm inRxBwMapCounters;
+  S_RxBip8Pm  inBip8Counter;
+  S_RxPlendPm inPlendCounter;
+  S_RxFecPm   inRxFecCounters;
+  S_GemPm     gemCounters;
+  int         off = 0;
+
+  decided = onuGponPonMngrFifoErrCountersGet(&suspected);
+  onuGponPmFecPmGet(&inRxFecCounters);
+  onuGponPmRxBwMapPmGet(&inRxBwMapCounters);
+  onuGponPmRxBip8PmGet(&inBip8Counter);
+  onuGponPmRxPlendPmGet(&inPlendCounter);
+  onuGponPmRxPloamPmGet(&inRxPloamCounters);
+  onuGponPmGemPmGet(&gemCounters);
+
+  off += mvOsSPrintf(buf+off, "ONT GPON Counters\n");
+  off += mvOsSPrintf(buf+off, "----------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "PLOAM FIFO SYNC ERROR SUSPECTED:                   %u\n", suspected);
+  off += mvOsSPrintf(buf+off, "PLOAM FIFO SYNC ERROR DECIDED:                     %u\n", decided);
+  off += mvOsSPrintf(buf+off, "This ONU ID PLOAMs:                                %u\n", inRxPloamCounters.receivedOnuIdPloamCounter);
+  off += mvOsSPrintf(buf+off, "Broadcast PLOAMs:                                  %u\n", inRxPloamCounters.receivedBroadcastPloamCounter);
+  off += mvOsSPrintf(buf+off, "Idles PLOAMs:                                      %u\n", inRxPloamCounters.idlePloamCounter);
+  off += mvOsSPrintf(buf+off, "CRC Error PLOAMs:                                  %u\n", inRxPloamCounters.crcErrorPloamCounter);
+  off += mvOsSPrintf(buf+off, "FIFO Full Dropped PLOAMs:                          %u\n", inRxPloamCounters.fifoOverErrorPloamCounter);
+  off += mvOsSPrintf(buf+off, "BW Error Free Allocs:                              %u\n", inRxBwMapCounters.allocCorrec);
+  off += mvOsSPrintf(buf+off, "BW Uncorrectable Allocs:                           %u\n", inRxBwMapCounters.allocUnCorrectableCrcErr);
+  off += mvOsSPrintf(buf+off, "BW Bad CRC Allocs:                                 %u\n", inRxBwMapCounters.allocCrcErr);
+  off += mvOsSPrintf(buf+off, "BW Error Free and Correctable Allocs:              %u\n", inRxBwMapCounters.allocCorrectableCrcErr);
+  off += mvOsSPrintf(buf+off, "BW Total Allocation:                               %u\n", inRxBwMapCounters.totalReceivedAllocBytes);
+  off += mvOsSPrintf(buf+off, "Bip8:                                              %u\n", inBip8Counter.bip8);
+  off += mvOsSPrintf(buf+off, "Plend:                                             %u\n", inPlendCounter.plend);
+  off += mvOsSPrintf(buf+off, "FEC correctedBits:                                 %u\n", inRxFecCounters.correctedBits);
+  off += mvOsSPrintf(buf+off, "FEC correctedBytes:                                %u\n", inRxFecCounters.correctedBytes);
+  off += mvOsSPrintf(buf+off, "FEC receivedBytes:                                 %u\n", inRxFecCounters.receivedBytes);
+  off += mvOsSPrintf(buf+off, "FEC receivedCodeWords:                             %u\n", inRxFecCounters.receivedCodeWords);
+  off += mvOsSPrintf(buf+off, "FEC uncorrectedCodeWords:                          %u\n", inRxFecCounters.uncorrectedCodeWords);
+  off += mvOsSPrintf(buf+off, "GEM Received Idle Gem Frames                       %u\n", gemCounters.receivedIdleGemFrames);
+  off += mvOsSPrintf(buf+off, "GEM Received Valid Gem Frames                      %u\n", gemCounters.receivedValidGemFrames);
+  off += mvOsSPrintf(buf+off, "GEM Received Undefined Gem Frames                  %u\n", gemCounters.receivedUndefinedGemFrames);
+  off += mvOsSPrintf(buf+off, "GEM Received Omci Frames                           %u\n", gemCounters.receivedOmciFrames);
+  off += mvOsSPrintf(buf+off, "GEM Dropped Gem Frames                             %u\n", gemCounters.droppedGemFrames);
+  off += mvOsSPrintf(buf+off, "GEM Dropped Omci Frames                            %u\n", gemCounters.droppedOmciFrames);
+  off += mvOsSPrintf(buf+off, "GEM Received Gem Frames With Uncorr Hec Error      %u\n", gemCounters.receivedGemFramesWithUncorrHecErr);
+  off += mvOsSPrintf(buf+off, "GEM Received Gem Frames With One Fixed Hec Error   %u\n", gemCounters.receivedGemFramesWithOneFixedHecErr);
+  off += mvOsSPrintf(buf+off, "GEM Received Gem Frames With Two Fixed Hec Error   %u\n", gemCounters.receivedGemFramesWithTwoFixedHecErr);
+  off += mvOsSPrintf(buf+off, "GEM Received Valid Gem Frames Total Byte Count     %u\n", gemCounters.totalByteCountOfReceivedValidGemFrames);
+  off += mvOsSPrintf(buf+off, "GEM Received Undefined Gem Frames Total Byte Count %u\n", gemCounters.totalByteCountOfReceivedUndefinedGemFrames);
+  off += mvOsSPrintf(buf+off, "GEM Gem Reassemble Memory Flush                    %u\n", gemCounters.gemReassembleMemoryFlush);
+  off += mvOsSPrintf(buf+off, "GEM Gem Synch Lost                                 %u\n", gemCounters.gemSynchLost);
+  off += mvOsSPrintf(buf+off, "GEM Received Eth Frames With Correct FCS           %u\n", gemCounters.receivedEthFramesWithCorrFcs);
+  off += mvOsSPrintf(buf+off, "GEM Received Eth Frames With FCS Error             %u\n", gemCounters.receivedEthFramesWithFcsError);
+  off += mvOsSPrintf(buf+off, "GEM Received Omci Frames With Correct CRC          %u\n", gemCounters.receivedOmciFramesWithCorrCrc);
+  off += mvOsSPrintf(buf+off, "GEM Received Omci Frames With CRC Error            %u\n", gemCounters.receivedOmciFramesWithCrcError);
+
+  return(off);
+}
+
+int onuGponUiRaw_2Counters(char* buf)
+{
+  S_GponTxPm txCounters;
+  MV_U32     tcont;
+  int        off = 0;
+
+  onuGponPmTxPmGet(&txCounters);
+
+  off += mvOsSPrintf(buf+off, "ONT GPON Raw Counters\n");
+  off += mvOsSPrintf(buf+off, "----------------------------------------------------------\n");
+
+  off += mvOsSPrintf(buf+off, "Transmitted Gem Pti Type-1 Frames                  %u\n", txCounters.transmittedGemPtiTypeOneFrames);
+  off += mvOsSPrintf(buf+off, "Transmitted Gem Pti Type-0 Frames                  %u\n", txCounters.transmittedGemPtiTypeZeroFrames);
+  off += mvOsSPrintf(buf+off, "Transmitted Idle Gem Frames                        %u\n", txCounters.transmittedIdleGemFrames);
+  off += mvOsSPrintf(buf+off, "Transmitted Tx Enable Count                        %u\n", txCounters.transmittedTxEnableCount);
+
+  for (tcont = 0; tcont < ONU_GPON_MAX_NUM_OF_T_CONTS; tcont++)
+  {
+    off += mvOsSPrintf(buf+off, "T-Cont [%d] Counters                                      \n", tcont);
+    off += mvOsSPrintf(buf+off, "----------------------------------------------------------\n");
+    off += mvOsSPrintf(buf+off, "Transmitted Eth Frames Via Tcont                   %u\n", txCounters.transmittedEthFramesViaTconti[tcont]);
+    off += mvOsSPrintf(buf+off, "Transmitted Eth Bytes Via Tcont                    %u\n", txCounters.transmittedEthBytesViaTconti[tcont]);
+    off += mvOsSPrintf(buf+off, "Transmitted Gem Frames Via Tcont                   %u\n", txCounters.transmittedGemFramesViaTconti[tcont]);
+    off += mvOsSPrintf(buf+off, "Transmitted Idle Gem Frames Via Tcont              %u\n", txCounters.transmittedIdleGemFramesViaTconti[tcont]);
+  }
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiPmHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print pm help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiPmHelpShow(char* buf)
+{
+  int off = 0;
+
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Configuration Commands[DEC]\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " echo [state] > cntRdClrFlState  - onu counters flag, Read[0], Read Clear[1]\n");
+  off += mvOsSPrintf(buf+off, " echo [state] > bwMapCntByState  - dump bw map counters before changing ONU state\n");
+  off += mvOsSPrintf(buf+off, "                                   Disable[0], Enable[1]                    \n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " cat rxPloamCnt               - dump Rx PLOAM counters\n");
+  off += mvOsSPrintf(buf+off, " cat txPloamCnt               - dump Tx PLOAM counters\n");
+  off += mvOsSPrintf(buf+off, " cat bwMapCnt                 - dump bw map counters\n");
+  off += mvOsSPrintf(buf+off, " cat stdCnt                   - dump standard counters\n");
+  off += mvOsSPrintf(buf+off, " cat fecCnt                   - dump fec counters\n");
+  off += mvOsSPrintf(buf+off, " cat gemCnt                   - dump gem counters\n");
+  off += mvOsSPrintf(buf+off, " cat txCnt                    - dump Tx counters\n");
+  off += mvOsSPrintf(buf+off, " cat rawCnt_1                 - dump raw counters\n");
+  off += mvOsSPrintf(buf+off, " cat rawCnt_2                 - dump raw counters\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+
+  return(off);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Data Commands                                   */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponUiTcontConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu tcont <--> alloc
+**
+**  PARAMETERS:  MV_U32 alloc
+**               MV_U32 tcont
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiTcontConfig(MV_U32 alloc, MV_U32 tcont)
+{
+  MV_STATUS rcode;
+
+  rcode = onuGponApiTcontConfig(alloc, tcont);
+  if (rcode != MV_OK)
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "ONU Allocation Id(%d) to T-CONT(%d) Config - FAIL\n", alloc, tcont);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiClearTcontConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clear onu tcont
+**
+**  PARAMETERS:  MV_U32 tcont
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiClearTcontConfig(MV_U32 tcont)
+{
+  MV_STATUS rcode;
+
+  rcode = onuGponApiTcontClear(tcont);
+  if (rcode != MV_OK)
+   mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "ONU T-CONT(%d) Clear - FAIL\n", tcont);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiResetTcontsConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reset onu bw map table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiResetTcontsConfig(void)
+{
+  onuGponApiTcontsReset();
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugTcont
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle onu tcont
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiDebugTcont(char* buf)
+{
+	MV_U32  allocId;
+	MV_U32  idleAllocId;
+	MV_U32  validCount = 0;
+	MV_BOOL valid;
+	MV_BOOL exist;
+	MV_U32  i;
+	MV_U8   *boolText[2] = {"NO ","YES"};
+	MV_U32  fAllocId;
+	MV_BOOL fEna;
+	MV_U32  fTcont;
+	MV_U32  knowTcont;
+	MV_U8   *knowTcontText[] = {"T-CONT 0  ","T-CONT 1  ","T-CONT 2  ",
+		"T-CONT 3  ","T-CONT 4  ","T-CONT 5  ",
+		"T-CONT 6  ","T-CONT 7  ","T-CONT 8  ",
+		"T-Def     ","T-Idle    "};
+	int      off = 0;
+	MV_STATUS status;
+
+	off += mvOsSPrintf(buf+off, "\n");
+	off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "| Alloc Id Table                    |\n");
+	off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "| Assigned             ||   Idle    |\n");
+	off += mvOsSPrintf(buf+off, "|-----------------------------------|\n");
+	off += mvOsSPrintf(buf+off, "| ALLOC-ID | Valid     ||           |\n");
+	off += mvOsSPrintf(buf+off, "|-----------------------------------|\n");
+
+	for (i = 0 ; i < ONU_GPON_MAX_NUM_OF_T_CONTS; i++) {
+		onuGponDbBwAllocGet(i, &allocId, &valid);
+		onuGponDbBwIdleAllocGet(i, &idleAllocId);
+		if (idleAllocId != PON_ONU_ALLOC_NOT_EXIST) {
+			off += mvOsSPrintf(buf+off, "|   %04d   |  %3s      ||   %04d    |\n",
+							   allocId, boolText[valid], idleAllocId);
+		} else {
+			off += mvOsSPrintf(buf+off, "|   %04d   |  %3s      ||   ====    |\n",
+							   allocId, boolText[valid]);
+		}
+	}
+
+	off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "| Alloc Id to T-CONT Connect  Table |\n");
+	off += mvOsSPrintf(buf+off, "|-----------------------------------|\n");
+	off += mvOsSPrintf(buf+off, "| T-CONT | Exist | ALLOC-ID | Valid |\n");
+	off += mvOsSPrintf(buf+off, "|-----------------------------------|\n");
+
+	for (i = 0 ; i < ONU_GPON_MAX_NUM_OF_T_CONTS; i++) {
+		onuGponDbBwTcontGet(i, &exist, &allocId, &valid);
+		off += mvOsSPrintf(buf+off, "|   %02d   |  %s  |   %04d   |  %s  |\n", i, boolText[exist], allocId, boolText[valid]);
+		if (valid != MV_FALSE) validCount++;
+	}
+
+	off += mvOsSPrintf(buf+off, "-------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "----------------------------------------------------\n");
+	off += mvOsSPrintf(buf+off, "| BW MAC - SoC Table                |              |\n");
+	off += mvOsSPrintf(buf+off, "|-----------------------------------|              |\n");
+	off += mvOsSPrintf(buf+off, "| Index | ALLOC-ID | T-CONT | Valid | KNOWN T-CONT |\n");
+	off += mvOsSPrintf(buf+off, "|--------------------------------------------------|\n");
+
+	for (i = 0 ; i < ONU_GPON_MAX_NUM_OF_T_CONTS ; i++) {
+		status = mvOnuGponMacRxBwMapGet(i, &fAllocId, &fEna, &fTcont);
+		if (status != MV_OK)
+			off += mvOsSPrintf(buf+off, "Error calling mvOnuGponMacRxBwMapGet, Tcont(%d)\n", i);
+
+		if (fTcont == PON_ONU_DEFAULT_ALLOC_TCONT)
+			knowTcont = 9;
+		else {
+			if ((fTcont == onuGponIdleAllocIdTcontGet()) && (validCount < 8))
+				knowTcont = 10;
+			else
+				knowTcont = fTcont;
+		}
+
+		off += mvOsSPrintf(buf+off, "|  %02d   |   %04d   |   %02d   |  %s  |  %s  |\n",
+						   i,fAllocId, fTcont, boolText[fEna],knowTcontText[knowTcont]);
+	}
+
+	off += mvOsSPrintf(buf+off, "----------------------------------------------------\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugGemPortidValidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable gem port Id valid configuration
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugGemPortidValidSet(MV_U32 portId, MV_U32 enable)
+{
+  if (enable != 0) onuGponApiGemPortIdConfig(portId);
+  else             onuGponApiGemPortIdClear(portId);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugGemPortidValidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable gem port Id valid configuration
+**
+**  PARAMETERS:  MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugAllGemPortidValidSet(MV_U32 enable)
+{
+  MV_U32  portId;
+
+  if (enable != 0) {
+        for (portId = 0; portId < 4096; portId++)
+             onuGponApiGemPortIdConfig(portId);
+  } else {
+        for (portId = 0; portId < 4096; portId++)
+             onuGponApiGemPortIdClear(portId);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugGemPmSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function start or stop Gem PM.
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugGemPmSet(MV_U32 portId, MV_U32 enable)
+{
+  S_GponIoctlGemPortPmConfig gemPm;
+
+  gemPm.gem_port = portId;
+
+  if(enable !=0)
+    gemPm.command = GEMPORTPMCMD_START;
+  else
+    gemPm.command = GEMPORTPMCMD_STOP;
+
+  onuGponApiGemPortPmConfig(&gemPm);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugGemPmReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function resets GEM PM MIB counters
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugGemPmReset(void)
+{
+    onuGponApiGemPortPmReset();
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugGemPmListShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function prints Gem PM ports enabled to collect MIB counters
+**
+**  PARAMETERS:  MV_U32 portId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+int onuGponUiDebugGemPmListShow(char* buf)
+{
+    S_apiGemPortPmConfig    gemPortCfg;
+    int                     off = 0;
+    MV_U16                  dbIdx;
+    MV_STATUS               rc;
+
+    off += mvOsSPrintf(buf+off, "GEM port ids list\n");
+    off += mvOsSPrintf(buf+off, "=================\n");
+    off += mvOsSPrintf(buf+off, " Counter    GEM  \n");
+    off += mvOsSPrintf(buf+off, "   set      port \n");
+    off += mvOsSPrintf(buf+off, "=================\n");
+
+    for (dbIdx = 0; dbIdx < MAX_SUPPORTED_GEMPORTS_FOR_PM; dbIdx++)
+    {
+        rc = onuGponPmGemPortPmConfigGet(dbIdx, &gemPortCfg);
+        if (rc == MV_OK)
+        {
+            off += mvOsSPrintf(buf+off, "    %d       %d\n", dbIdx, gemPortCfg.gem_port);
+        }
+    }
+
+    off += mvOsSPrintf(buf+off, "=================\n");
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugGemPmGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function prints Gem PM counters
+**
+**  PARAMETERS:  MV_U32 portId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugGemPmGet(MV_U32 portId)
+{
+  S_GponIoctlGemPortMibCounters mibCounters;
+  MV_STATUS                     rcode;
+
+  MV_U8 *counterText[] = {"Received Eth broadcast Frames                  ",
+                          "Received Eth multicast Frames                  ",
+                          "Received Eth good Frames                       ",
+                          "Received Eth good Frames length 65-127         "};
+
+  memset(&mibCounters, 0, sizeof(S_GponIoctlGemPortMibCounters));
+
+  mibCounters.gem_port = portId;
+  rcode = onuGponApiGemPortPmGet(&mibCounters);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get mibCounters value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  mvOsPrintf("\n");
+  mvOsPrintf("------------------------------------------------------------------\n");
+  mvOsPrintf("|MIB COUNTERS for GEM port:  %d\n", portId);
+  mvOsPrintf("------------------------------------------------------------------\n");
+  mvOsPrintf("|COUNTER                                           |  VALUE      |\n");
+  mvOsPrintf("------------------------------------------------------------------\n");
+  mvOsPrintf(" %s   | %10u  |\n", counterText[0], mibCounters.broadcast_frames_received);
+  mvOsPrintf(" %s   | %10u  |\n", counterText[1], mibCounters.multicast_frames_received);
+  mvOsPrintf(" %s   | %10u  |\n", counterText[2], mibCounters.good_frames_received);
+  mvOsPrintf(" %s   | %10u  |\n", counterText[3], mibCounters.frames_65_to_127_octets);
+  mvOsPrintf("------------------------------------------------------------------\n");
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugGemPortid
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return gem port Id valid configuration
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiDebugGemPortid(char* buf, int range)
+{
+  MV_BOOL enable;
+  MV_U32  portId;
+  MV_U32  startRange;
+  MV_U32  endRange;
+  int     off = 0;
+
+  off += mvOsSPrintf(buf+off, "GEM port ids list\n");
+  off += mvOsSPrintf(buf+off, "=================\n");
+
+  switch (range)
+  {
+    case 1:  startRange = 1000; endRange = 1999; break;
+    case 2:  startRange = 2000; endRange = 2999; break;
+    case 3:  startRange = 3000; endRange = 4096; break;
+    default: startRange = 0;    endRange = 999;  break;
+  }
+
+  for (portId = startRange ; portId < endRange ; portId++)
+  {
+    enable = mvOnuGponMacPortIdValidGet(portId);
+    if (enable == MV_TRUE) off += mvOsSPrintf(buf+off, "[%04d]", portId);
+    if ((portId / 14) == 0) off += mvOsSPrintf(buf+off, "\n");
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  return(off);
+}
+
+#ifdef MV_GPON_STATIC_GEM_PORT
+/*******************************************************************************
+**
+**  onuGponUiDebugDummyGemPortFlagSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set dummy gem port flag
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugDummyGemPortFlagSet(MV_U32 flag)
+{
+  onuGponApiGemPortIdStaticConfigFlag(flag);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugDummyGemPortReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reset dummy gem port table
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     OK or ERROR
+**
+*******************************************************************************/
+void onuGponUiDebugDummyGemPortReset(void)
+{
+  onuGponApiGemPortIdStaticConfigReset();
+}
+#endif /* MV_GPON_STATIC_GEM_PORT */
+
+/*******************************************************************************
+**
+**  onuGponUiDataHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print data help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiDataHelpShow(char* buf)
+{
+  int off = 0;
+
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Configuration Commands[DEC]\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " echo [AllocId] [T-Cont] > cfgTcont        - config alloc to tcont\n");
+  off += mvOsSPrintf(buf+off, " echo [T-Cont]           > clrTcont        - clear alloc Ids from T-Cont\n");
+  off += mvOsSPrintf(buf+off, " echo [0]                > rstTcont        - clear T-Cont configuration\n");
+  off += mvOsSPrintf(buf+off, " echo [GemPort] [Valid]  > cfgGem          - config gem port valid state, Disable[0], Enable[1]\n");
+  off += mvOsSPrintf(buf+off, " echo [Valid]            > cfgAllGem       - config all gem ports valid state, Disable[0], Enable[1]\n");
+  off += mvOsSPrintf(buf+off, " echo [gemport] [state]  > cfgMibPm        - Config onu gem port for MIB PM: start count[1], stop count[0]\n");
+  off += mvOsSPrintf(buf+off, " echo [dummy]            > resetMibPm      - Reset MIB PM\n");
+  off += mvOsSPrintf(buf+off, " echo [gemport]          > getMibPm        - Get MIB PM for a Gem port\n");
+#ifdef MV_GPON_STATIC_GEM_PORT
+  off += mvOsSPrintf(buf+off, " echo [state]            > dummyGemState   - static gem port flag, Disable[0], Enable[1]\n");
+  off += mvOsSPrintf(buf+off, " echo [0]                > dummyGemRst     - clear static gem port table\n");
+#endif /* MV_GPON_STATIC_GEM_PORT */
+  off += mvOsSPrintf(buf+off, " echo [PortId] [State]   > cfgAesPort      - config gem port encryption state\n");
+  off += mvOsSPrintf(buf+off, " echo [State]            > cfgAllAes       - config all gem ports encryption state\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " cat showTcont                             - dump T-Cont configuration\n");
+  off += mvOsSPrintf(buf+off, " cat showMibGemPorts                       - dump a list of gem ports enabled for MIB PM\n");
+  off += mvOsSPrintf(buf+off, " cat showGem0xxx showGem1xxx showGem2xxx showGem3xxx - dump valid gem port list\n");
+  off += mvOsSPrintf(buf+off, " cat showAes0xxx showAes1xxx showAes2xxx showAes3xxx - dump encrypted gem port list\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  return(off);
+}
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Introp Commands                                 */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponUiOverrideShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu override parameters info
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiOverrideShow(char* buf)
+{
+  MV_U8 *parametersText[] = {"ExtendedBurst",
+                             "Delimiter        ",
+                             "OnuId            ",
+                             "OmccPortId       ",
+                             "EqualizationDelay"};
+  MV_U8  *enableText[]    = {"disabled","enabled"};
+  MV_U32 tempValue1;
+  MV_U32 tempValue2;
+  MV_U32 status;
+  int     off = 0;
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "--------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "|  ONU OVERRIDE:                           |\n");
+  off += mvOsSPrintf(buf+off, "--------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "|    PARAMETER       |  VALUE   |  STATUS  |\n");
+  off += mvOsSPrintf(buf+off, "--------------------------------------------\n");
+
+  tempValue1 = onuGponDbExtendedBurstOperOverrideValueGet();
+  tempValue2 = onuGponDbExtendedBurstSyncOverrideValueGet();
+  status     = (MV_U32)onuGponDbExtendedBurstOverrideGet();
+  off += mvOsSPrintf(buf+off, "| %s SYNC | %8u | %s |\n", parametersText[0], tempValue1, enableText[status]);
+  off += mvOsSPrintf(buf+off, "| %s OPER | %8u | %s |\n", parametersText[0], tempValue2, enableText[status]);
+
+  tempValue1 = onuGponDbDelimiterOverrideValueGet();
+  status     = (MV_U32)onuGponDbDelimiterOverrideGet();
+  off += mvOsSPrintf(buf+off, "| %s  | %8u | %s |\n", parametersText[1], tempValue1, enableText[status]);
+
+  tempValue1 = onuGponDbOnuIdOverrideValueGet();
+  status     = (MV_U32)onuGponDbOnuIdOverrideGet();
+  off += mvOsSPrintf(buf+off, "| %s  | %8u | %s |\n", parametersText[2], tempValue1, enableText[status]);
+
+  tempValue1 = onuGponDbOmccPortOverrideValueGet();
+  status     = (MV_U32)onuGponDbOmccPortOverrideGet();
+  off += mvOsSPrintf(buf+off, "| %s  | %8u | %s |\n", parametersText[3], tempValue1, enableText[status]);
+
+  tempValue1 = onuGponDbEqualizationDelayOverrideValueGet();
+  status     = (MV_U32)onuGponDbEqualizationDelayOverrideGet();
+  off += mvOsSPrintf(buf+off, "| %s  | %8u | %s |\n", parametersText[4], tempValue1, enableText[status]);
+  off += mvOsSPrintf(buf+off, "--------------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDelimiterConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu delimiter
+**
+**  PARAMETERS:  MV_U32 enable
+**               MV_U32 DelValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDelimiterConfig(MV_U32 enable, MV_U32 DelValue)
+{
+  onuGponApiDelimiterSet((MV_BOOL)enable, DelValue);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiOnuIdConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu Id
+**
+**  PARAMETERS:  MV_U32 onuId
+**               MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiOnuIdConfig(MV_U32 onuId, MV_U32 enable)
+{
+  onuGponApiOnuIdSet((MV_BOOL)enable, onuId);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiPortIdConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu omcc port Id
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiPortIdConfig(MV_U32 portId, MV_U32 enable)
+{
+  onuGponApiOmccPortIdSet((MV_BOOL)enable, portId);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiEquDelaySetConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu equalization delay
+**
+**  PARAMETERS:  MV_U32 equDelayVal
+**               MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiEquDelaySetConfig(MV_U32 equDelayVal, MV_U32 enable)
+{
+  onuGponApiEqualizationDelaySet((MV_BOOL)enable, equDelayVal);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiEquDelayChangeConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu equalization delay
+**
+**  PARAMETERS:  MV_U32 direction
+**               MV_U32 size
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiEquDelayChangeConfig(MV_U32 direction, MV_U32 size)
+{
+  onuGponApiEqualizationDelayChange(direction, size);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiExtendedBurstConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu extended burst
+**
+**  PARAMETERS:  MV_U32 enable
+**               MV_U32 rangeValue
+**               MV_U32 operValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiExtendedBurstConfig(MV_U32 enable, MV_U32 rangeValue, MV_U32 operValue)
+{
+  onuGponApiExtendedBurstSet ((MV_BOOL)enable, rangeValue, operValue);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiExtendedBurstDelayConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure delay for the received onu extended burst
+**
+**  PARAMETERS:  MV_U32 enable
+**               MV_U32 rangeValue
+**               MV_U32 operValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiExtendedBurstDelayConfig(MV_U32 enable, MV_U32 rangeValue, MV_U32 operValue)
+{
+  onuGponApiExtendedBurstDelaySet ((MV_BOOL)enable, rangeValue, operValue);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugOverheadMode
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle onu overhead mode
+**
+**  PARAMETERS:  MV_U32 overMode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugOverheadMode(MV_U32 overMode)
+{
+  MV_BOOL mode = (overMode == 0)? MV_FALSE : MV_TRUE;
+  onuGponPonMngOverheadManualModeSet(mode);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugOverheadGuard
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle onu overhead guard bits
+**
+**  PARAMETERS:  MV_U32 guard
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugOverheadGuard(MV_U32 guard)
+{
+  onuGponDbGuardBitsSet(guard);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugOverheadPreamble
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle onu overhead preamble
+**
+**  PARAMETERS:  MV_U32 pream3RangeCnt
+**               MV_U32 pream3OperCnt
+**               MV_U32 pream3PattCnt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugOverheadPreamble(MV_U32 pream3RangeCnt,
+                                    MV_U32 pream3OperCnt,
+                                    MV_U32 pream3PattCnt)
+{
+  MV_U32 onuState;
+
+  onuGponDbPreambleSet(ONU_GPON_PREM_TYPE_03, pream3PattCnt, 0);
+  onuGponDbExtPreambleSyncSet(pream3RangeCnt);
+  onuGponDbExtPreambleOperSet(pream3OperCnt);
+  onuState = onuGponDbOnuStateGet();
+  if (onuState == ONU_GPON_05_OPERATION) mvOnuGponMacPreambleType3Set(pream3PattCnt,pream3OperCnt);
+  else                                   mvOnuGponMacPreambleType3Set(pream3PattCnt,pream3RangeCnt);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiIntropHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print introp help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiIntropHelpShow(char* buf)
+{
+  int off = 0;
+
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Configuration Commands[DEC]\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " echo [OnuId] [Enable]                   > onuIdCfg     - override configured OnuId\n");
+  off += mvOsSPrintf(buf+off, " echo [PortId] [Enable]                  > portIdCfg    - override configured omcc portId\n");
+  off += mvOsSPrintf(buf+off, " echo [EquDelay] [Enable]                > eqdCfg       - override configured Equ Delay\n");
+  off += mvOsSPrintf(buf+off, " echo [Direction] [Size]                 > eqdChange    - change Equ Delay\n");
+  off += mvOsSPrintf(buf+off, " echo [Enable] [RangeValue] [OperValue]  > extBurstCfg  - override configured external burst\n");
+  off += mvOsSPrintf(buf+off, " echo [Enable] [RangeValue] [OperValue]  > extBurstDelayCfg  - add configured delay to received external burst\n");
+  off += mvOsSPrintf(buf+off, " echo [Enable] [Value]                   > delimiterCfg - override configured delimiter\n");
+  off += mvOsSPrintf(buf+off, " echo [RangeValue] [OperValue] [Pattern] > preambleCfg  - override configured preamble type3\n");
+  off += mvOsSPrintf(buf+off, " echo [Guard Bits]                       > guardCfg     - configure guard bits\n");
+  off += mvOsSPrintf(buf+off, " echo [Mode]                             > manModeCfg   - configure override parameters mode\n");
+  off += mvOsSPrintf(buf+off, " echo [Mode]                             > adminCfg     - configure onu Tx mode:(0)Enable, (1)Disable\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+  off += mvOsSPrintf(buf+off, " cat manMode                              - override parameters mode\n");
+  off += mvOsSPrintf(buf+off, "============================================================================\n");
+
+  return(off);
+}
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Protocol Commands                               */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponUiDebugBurstConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu tx burst
+**
+**  PARAMETERS:  MV_U32 start
+**               MV_U32 stop
+**               MV_U32 order
+**               MV_U32 polarity
+**               MV_U32 mask
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugBurstConfig(MV_U32 start,
+                               MV_U32 stop,
+                               MV_U32 order,
+                               MV_U32 polarity,
+                               MV_U32 mask)
+{
+  S_apiBurstConfig burstConfig;
+
+  burstConfig.start    = start;
+  burstConfig.stop     = stop;
+  burstConfig.order    = order;
+  burstConfig.polarity = polarity;
+  burstConfig.mask     = mask;
+
+  onuGponApiBurstConfigSet(&burstConfig);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugBurstInfo
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu tx burst info
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiDebugBurstInfo(char* buf)
+{
+  S_apiBurstConfig burstConfig;
+  int              off = 0;
+
+  onuGponApiBurstConfigGet(&burstConfig);
+
+  off += mvOsSPrintf(buf+off, "----------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| Burst Parameters                           |\n");
+  off += mvOsSPrintf(buf+off, "|--------------------------------------------|\n");
+  off += mvOsSPrintf(buf+off, "|  Start |  Stop  | Order  |Polarity| Mask   |\n");
+  off += mvOsSPrintf(buf+off, "|--------------------------------------------|\n");
+  off += mvOsSPrintf(buf+off, "|   %02d   |   %02d   |   %02d   |   %02d   |   %02d   |\n",
+                     burstConfig.start, burstConfig.stop, burstConfig.order,
+                     burstConfig.polarity, burstConfig.mask);
+  off += mvOsSPrintf(buf+off, "|--------------------------------------------|\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiInfoBerDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get Global OLT BER Information
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiInfoBerDebug(char* buf)
+{
+  S_BerCoefficient coeff;
+  MV_U32           seconds;
+  MV_U32           ber;
+  MV_U32           intervalBer;
+  MV_U32           bip,lastBip;
+  MV_U32           sdThreshold;
+  MV_U32           sfThreshold;
+  MV_U32           sdDetectValue;
+  MV_U32           sdCancelValue;
+  MV_U32           sfDetectValue;
+  MV_U32           sfCancelValue;
+  int              off = 0;
+
+  coeff         = onuGponBerCoefficientGet();
+  seconds       = onuGponBerIntervalSecondsGet();
+  sdThreshold   = onuGponDbSdThresholdGet();
+  sfThreshold   = onuGponDbSfThresholdGet();
+
+  sdDetectValue = onuGponBerPower(10 ,(11 - sdThreshold));
+  sdCancelValue = onuGponBerPower(10 ,(11 - sdThreshold - 1));
+  sfDetectValue = onuGponBerPower(10 ,(11 - sfThreshold));
+  sfCancelValue = onuGponBerPower(10 ,(11 - sfThreshold - 1));
+
+  ber           = onuGponBerBerValueGet();
+  intervalBer   = onuGponBerIntervalBerValueGet();
+  bip           = onuGponBerBip8CounterGet();
+  lastBip       = onuGponBerLastIntervalBip8CounterGet();
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "----------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| BER Information                      |\n");
+  off += mvOsSPrintf(buf+off, "|--------------------------------------|\n");
+  off += mvOsSPrintf(buf+off, "|Interval of %2d Seconds                |\n", seconds);
+  off += mvOsSPrintf(buf+off, "|Coefficient is %2d/%2d                  |\n", coeff.numerator, coeff.denominator);
+  off += mvOsSPrintf(buf+off, "-----------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "|Interval BER|   BER      | BIP8       | Inter.BIP8 |\n");
+  off += mvOsSPrintf(buf+off, "-----------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "   %010u | %010u | %010u | %010u |\n", intervalBer, ber ,bip, lastBip);
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, " | DET SD TH  | CNC SD TH  | DET SF TH  | CNC SF TH  |\n");
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------\n");
+  off += mvOsSPrintf(buf+off, "   %010u | %010u | %010u | %010u |\n", sdDetectValue, sdCancelValue, sfDetectValue, sfCancelValue);
+  off += mvOsSPrintf(buf+off, "------------------------------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugBerIntervalDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu ber interval
+**
+**  PARAMETERS:  MV_U32 interval
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugBerIntervalDebug(MV_U32 interval)
+{
+  onuGponApiBerIntervalConfig(interval);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugBerCoefficientDebug
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu ber coefficient
+**
+**  PARAMETERS:  MV_U32 numerator
+**               MV_U32 denominator
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugBerCoefficientDebug(MV_U32 numerator, MV_U32 denominator)
+{
+  onuGponApiBerCoefficientConfig(denominator,numerator);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiBerThresholdsConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu ber thresholds
+**
+**  PARAMETERS:  MV_U32 sd
+**               MV_U32 sf
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiBerThresholdsConfig(MV_U32 sd, MV_U32 sf)
+{
+  onuGponApiBerThresholdConfig(sd, sf);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugAesSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle onu AES port configuration
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugAesSet(MV_U32 portId, MV_U32 enable)
+{
+  MV_STATUS rcode = MV_OK;
+  MV_BOOL   enaBool;
+  MV_BOOL   valid;
+
+  /* to start AES on a port Id, it should be valid */
+  if (enable == 1)
+  {
+    valid = onuGponDbGemPortValidGet(portId);
+    if (valid != MV_TRUE)
+    {
+      mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+                 "Set GEM Port AES: Port(%d) is not Valid\n", portId);
+      return;
+    }
+  }
+
+  enaBool = (enable == 0) ? MV_FALSE : MV_TRUE;
+
+  rcode = mvOnuGponMacAesPortIdSet(portId, enaBool);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "Set GEM Port AES: Port(%d) enable(%d) failed\n", portId, enable);
+  }
+
+  onuGponDbGemPortAesSet(portId, enaBool);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugAesSetAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle onu AES port configuration
+**
+**  PARAMETERS:  MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugAesSetAll(MV_U32 enable)
+{
+  MV_STATUS  rcode = MV_OK;
+  MV_BOOL    enaBool;
+  MV_BOOL    valid;
+  MV_U32     portId;
+
+  for (portId = 0; portId < 4096; portId++)
+  {
+    /* to start AES on a port Id, it should be valid */
+    if (enable == 1)
+    {
+      valid = onuGponDbGemPortValidGet(portId);
+      if (valid != MV_TRUE)
+      {
+        mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+                   "Set GEM Port AES: Port(%d) is not Valid\n", portId);
+        return;
+      }
+    }
+
+    enaBool = (enable == 0) ? MV_FALSE : MV_TRUE;
+
+    rcode = mvOnuGponMacAesPortIdSet(portId, enaBool);
+    if (rcode != MV_OK)
+    {
+      mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+                 "Set GEM Port AES: Port(%d) enable(%d) failed\n", portId, enable);
+    }
+
+    onuGponDbGemPortAesSet(portId,enaBool);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugAesGemAll
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return a list of all gem port AES and status
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiDebugAesGemAll(char* buf, int range)
+{
+  MV_U32  portId;
+  MV_BOOL enable;
+  MV_U32  startRange;
+  MV_U32  endRange;
+  int     off = 0;
+
+  off += mvOsSPrintf(buf+off, "Encrypted GEM port ids list\n");
+  off += mvOsSPrintf(buf+off, "===========================\n");
+
+  switch (range)
+  {
+    case 1:  startRange = 1000; endRange = 1999; break;
+    case 2:  startRange = 2000; endRange = 2999; break;
+    case 3:  startRange = 3000; endRange = 4096; break;
+    default: startRange = 0;    endRange = 999;  break;
+  }
+
+  for (portId = startRange ; portId < endRange ; portId++)
+  {
+    if (onuGponDbGemPortValidGet(portId)== MV_TRUE) {
+        enable = onuGponDbGemPortAesGet(portId);
+        if (enable == MV_TRUE) off += mvOsSPrintf(buf+off, "[%04d]", portId);
+    }
+    if ((portId / 14) == 0) off += mvOsSPrintf(buf+off, "\n");
+  }
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerSendPloam
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function transmit US ploam message
+**
+**  PARAMETERS:  MV_U32 msgId
+**               MV_U32 onuId
+**               MV_U32 data1
+**               MV_U32 data2
+**               MV_U32 data3
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugManagerSendPloam(MV_U32 msgId,
+                                    MV_U32 onuId,
+                                    MV_U32 data1,
+                                    MV_U32 data2,
+                                    MV_U32 data3)
+{
+  MV_U8     msgData[12];
+  MV_STATUS rcode;
+
+  msgData[0]  = (MV_U8)((data1 >> 24) & 0xFF);
+  msgData[1]  = (MV_U8)((data1 >> 16) & 0xFF);
+  msgData[2]  = (MV_U8)((data1 >> 8) & 0xFF);
+  msgData[3]  = (MV_U8)((data1) & 0xFF);
+  msgData[4]  = (MV_U8)((data2 >> 24) & 0xFF);
+  msgData[5]  = (MV_U8)((data2 >> 16) & 0xFF);
+  msgData[6]  = (MV_U8)((data2 >> 8) & 0xFF);
+  msgData[7]  = (MV_U8)((data2) & 0xFF);
+  msgData[8]  = (MV_U8)((data3 >> 24) & 0xFF);
+  msgData[9]  = (MV_U8)((data3 >> 16) & 0xFF);
+  msgData[10] = (MV_U8)((data3 >> 8) & 0xFF);
+  msgData[11] = (MV_U8)((data3) & 0xFF);
+
+  rcode = mvOnuGponMacMessageSend(onuId, msgId, msgData);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "mvOnuGponMacMessageSend failed\n");
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerReceivePloam
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function receive DS ploam message
+**
+**  PARAMETERS:  MV_U32 msgId
+**               MV_U32 onuId
+**               MV_U32 data1
+**               MV_U32 data2
+**               MV_U32 data3
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugManagerReceivePloam(MV_U32 msgId,
+                                       MV_U32 onuId,
+                                       MV_U32 data1,
+                                       MV_U32 data2,
+                                       MV_U32 data3)
+{
+  MV_U8 msgData[12];
+
+  msgData[0]  = (MV_U8)((data1 >> 24) & 0xFF);
+  msgData[1]  = (MV_U8)((data1 >> 16) & 0xFF);
+  msgData[2]  = (MV_U8)((data1 >> 8) & 0xFF);
+  msgData[3]  = (MV_U8)((data1) & 0xFF);
+  msgData[4]  = (MV_U8)((data2 >> 24) & 0xFF);
+  msgData[5]  = (MV_U8)((data2 >> 16) & 0xFF);
+  msgData[6]  = (MV_U8)((data2 >> 8) & 0xFF);
+  msgData[7]  = (MV_U8)((data2) & 0xFF);
+  msgData[8]  = (MV_U8)((data3 >> 24) & 0xFF);
+  msgData[9]  = (MV_U8)((data3 >> 16) & 0xFF);
+  msgData[10] = (MV_U8)((data3 >> 8) & 0xFF);
+  msgData[11] = (MV_U8)((data3) & 0xFF);
+
+  onuGponPonMngPloamProcess((MV_U8)onuId, (MV_U8)msgId, msgData);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerRcvBurstPloams
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function receives DS ploam messages
+**
+**  PARAMETERS:  MV_U32 msgId
+**               MV_U32 onuId
+**               MV_U32 data1
+**               MV_U32 data2
+**               MV_U32 data3
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugManagerRcvBurstPloams(MV_U32 msgId,
+                                         MV_U32 onuId,
+                                         MV_U32 data1,
+                                         MV_U32 data2,
+                                         MV_U32 data3)
+{
+    int i;
+
+    for (i=0; i<maxPloamsSend; i++) {
+        onuGponUiDebugManagerReceivePloam(msgId, onuId, data1, data2, data3);
+    }
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerRcvBurstCfg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures DS PLOAM burst size
+**
+**  PARAMETERS:  MV_U32 size
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugManagerRcvBurstCfg(MV_U32    size)
+{
+    maxPloamsSend = size;
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerFifoCntsClear
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears SW FIFO counters
+**
+**  PARAMETERS:  MV_U32 size
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugManagerFifoCntsClear(MV_U32    value)
+{
+    mvOnuGponMacFifoCountersSet(value);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerFifoSupportSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enables or disables SW FIFO support
+**
+**  PARAMETERS:  MV_U32 size
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugManagerFifoSupportSet (MV_U32    enDis)
+{
+    mvOnuGponMacFifoSupportSet(enDis);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerAcCouplingSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configures TX AC coupling parameters
+**
+**  PARAMETERS:  MV_U32 mode
+**               MV_U32 time
+**               MV_U32 pattern1
+**               MV_U32 pattern2
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugManagerAcCouplingSet(MV_U32 mode, MV_U32 time, MV_U32 pattern1, MV_U32 pattern2)
+{
+	mvOnuGponMacTxConfigAcCouplingSet(mode, time, pattern1, pattern2);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugManagerAcCouplingGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function prints TX AC coupling parameters
+**
+**  PARAMETERS:  char *buf
+**
+**  OUTPUTS:     char *buf
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+int onuGponUiDebugManagerAcCouplingGet(char *buf)
+{
+	int        off = 0;
+	MV_U32     mode, time;
+	MV_U8      pattern1, pattern2;
+	MV_STATUS  status;
+
+	status = mvOnuGponMacTxConfigAcCouplingGet(&mode, &time, &pattern1, &pattern2);
+
+	if (status != MV_OK)
+		off += mvOsSPrintf(buf+off, "Failed to obtain AC coupling configuration!\n");
+	else {
+		off += mvOsSPrintf(buf+off, "------------------------------------\n");
+		off += mvOsSPrintf(buf+off, "| AC Coupling Parameters (HEX val)  |\n");
+		off += mvOsSPrintf(buf+off, "|-----------------------------------|\n");
+		off += mvOsSPrintf(buf+off, "| Mode | Time | Pattern1 | Pattern2 |\n");
+		off += mvOsSPrintf(buf+off, "|-----------------------------------|\n");
+		off += mvOsSPrintf(buf+off, "|  %02x  | %04x |    %02x    |    %02x    |\n",
+				   mode, time, pattern1, pattern2);
+		off += mvOsSPrintf(buf+off, "|-----------------------------------|\n");
+	}
+
+	return(off);
+}
+
+
+/*******************************************************************************
+**
+**  onuGponUiGemOmciPortIdConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu omci port Id
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiGemOmciPortIdConfig(MV_U32 portId, MV_U32 valid)
+{
+  mvOnuGponMacGemOmciPortIdSet(portId, valid); /* Rx */
+  mvOnuGponMacUtmOmciPortIdSet(portId, valid); /* Tx */
+
+  onuGponDbOmccPortSet(portId);
+  onuGponDbOmccValidSet(valid);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiGemOmciPortIdShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu omcc port Id
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiGemOmciPortIdShow(char* buf)
+{
+  MV_STATUS rcode;
+  MV_U32    gemPortId;
+  MV_U32    gemPortValid;
+  MV_U32    utmPortId;
+  MV_U32    utmPortValid;
+  int       off = 0;
+
+  rcode = mvOnuGponMacGemOmciPortIdGet(&gemPortId, &gemPortValid);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get Rx(gem) omci portId, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  rcode = mvOnuGponMacUtmOmciPortIdGet(&utmPortId, &utmPortValid);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get Tx(Utm) omci portId, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "OMCI Rx(Gem) PortId %8d valid %s\n", gemPortId, (gemPortValid == 0) ? ("FALSE") : ("TRUE"));
+  off += mvOsSPrintf(buf+off, "OMCI Tx(Utm) PortId %8d valid %s\n", utmPortId, (utmPortValid == 0) ? ("FALSE") : ("TRUE"));
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiGemFrameLengthShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print onu frame lengths
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiGemFrameLengthShow(char* buf)
+{
+  MV_STATUS rcode;
+  MV_U32    payloadlen;
+  MV_U32    maxEthFrameLen;
+  MV_U32    minEthFrameLen;
+  MV_U32    maxOmciFrameLen;
+  MV_U32    minOmciFrameLen;
+  int       off = 0;
+
+  rcode = mvOnuGponMacGemPayloadLenGet(&payloadlen);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get gem payload length value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  rcode = mvOnuGponMacGemEthFrameLenGet(&maxEthFrameLen, &minEthFrameLen);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get ethernet frame length value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  rcode = mvOnuGponMacGemOmciFrameLenGet(&maxOmciFrameLen, &minOmciFrameLen);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to get omci frame value, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+
+  off += mvOsSPrintf(buf+off, "\n");
+  off += mvOsSPrintf(buf+off, "----------------------\n");
+  off += mvOsSPrintf(buf+off, "|Frame Length        |\n");
+  off += mvOsSPrintf(buf+off, "-----------------------------------\n");
+  off += mvOsSPrintf(buf+off, "| Frame              |   VALUE    |\n");
+  off += mvOsSPrintf(buf+off, "-----------------------------------\n");
+  off += mvOsSPrintf(buf+off, "Gem payload          | %10d |\n", payloadlen);
+  off += mvOsSPrintf(buf+off, "Gem min eth frame    | %10d |\n", minEthFrameLen);
+  off += mvOsSPrintf(buf+off, "Gem max eth frame    | %10d |\n", maxEthFrameLen);
+  off += mvOsSPrintf(buf+off, "Gem min omci frame   | %10d |\n", minOmciFrameLen);
+  off += mvOsSPrintf(buf+off, "Gem max omci frame   | %10d |\n", maxOmciFrameLen);
+  off += mvOsSPrintf(buf+off, "-----------------------------------\n");
+
+  return(off);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiGemPayloadLenConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu gem payload length
+**
+**  PARAMETERS:  MV_U32 payloadLen
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiGemPayloadLenConfig(MV_U32 payloadLen)
+{
+  mvOnuGponMacGemPayloadLenSet(payloadLen);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiGemEthFrameLenConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu ethernet min/max frame length
+**
+**  PARAMETERS:  MV_U32 minFrameLenArg
+**               MV_U32 maxFrameLenArg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiGemEthFrameLenConfig(MV_U32 minFrameLenArg, MV_U32 maxFrameLenArg)
+{
+  mvOnuGponMacGemEthFrameLenSet(maxFrameLenArg, minFrameLenArg);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiGemOmciFrameLenConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu omci min/max frame length
+**
+**  PARAMETERS:  MV_U32 minFrameLenArg
+**               MV_U32 maxFrameLenArg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiGemOmciFrameLenConfig(MV_U32 minFrameLenArg, MV_U32 maxFrameLenArg)
+{
+  mvOnuGponMacGemOmciFrameLenSet(maxFrameLenArg, minFrameLenArg);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiProtoHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print protocol help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiProtoHelpShow(char* buf)
+{
+	int off = 0;
+	MV_U32 devId = mvCtrlModelGet();
+
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, "Configuration Commands[DEC]\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, " echo [BER Interval]            > berIntervalCfg  - config ber interval\n");
+	off += mvOsSPrintf(buf+off, " echo [Numerator] [Denominator] > berCoeffCfg     - "
+									"config ber coeff numerator, denominator\n");
+	off += mvOsSPrintf(buf+off, " echo [SD] [SF]                 > berThesholdCfg  - "
+										"config ber SD, SF thresholds\n");
+	off += mvOsSPrintf(buf+off, " echo [OmccPortId] [State]      > omciPortCfg     - config omcc gem port state\n");
+	off += mvOsSPrintf(buf+off, " echo [Len]                     > gemFrameLenCfg  - "
+										"config gem frame payload len\n");
+	off += mvOsSPrintf(buf+off, " echo [MinLen] [MaxLen]         > ethFrameLenCfg  - "
+										"config eth frame min & max lengths\n");
+	off += mvOsSPrintf(buf+off, " echo [MinLen] [MaxLen]         > omciFrameLenCfg - "
+									"config omci frame min & max lengths\n");
+	off += mvOsSPrintf(buf+off, " echo [Start] [Stop] [Order] [Pola] [Mask] > txBurstCfg   - config tx burst\n");
+	off += mvOsSPrintf(buf+off, " echo [MsgId] [OnuId] [Data] [Data] [Data] > ploamMsgSend - "
+										"simulate transmit of US PLOAM msg\n");
+	off += mvOsSPrintf(buf+off, " echo [MsgId] [OnuId] [Data] [Data] [Data] > ploamMsgRece - "
+								"simulate reception and process of DS PLOAM msg\n");
+	off += mvOsSPrintf(buf+off, " echo [MsgId] [OnuId] [Data] [Data] [Data] > ploamBurstRcv - "
+							"simulate reception and process of DS burst PLOAM msgs\n");
+	off += mvOsSPrintf(buf+off, " echo [DS burst size]           > ploamBurstCfg - config DS PLOAM burst size\n");
+	off += mvOsSPrintf(buf+off, " echo 0                         > clearFifoCnts - clear all SW FIFO counters\n");
+	off += mvOsSPrintf(buf+off, " echo [enable(1) or disable(0)] > fifoSupport - config US SW FIFO support\n");
+	if (devId == MV_6601_DEV_ID){
+		off += mvOsSPrintf(buf+off, " echo [Mode] [Time] [Pattern1] [Pattern2] > acCoupling - "
+									"configure TX AC Coupling parameters\n");
+	}
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, " cat txBurst                              - dump tx burst info\n");
+	off += mvOsSPrintf(buf+off, " cat gemFrameLen                          - dump frame lengths\n");
+	if (devId == MV_6601_DEV_ID){
+		off += mvOsSPrintf(buf+off, " cat acCoupling                           - "
+									"dump TX AC Coupling parameters\n");
+	}
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+
+	return(off);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Misc Commands                                   */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  onuGponUiDebugSerialNumberSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set ONU serial Number
+**
+**  PARAMETERS:  ON_U32 serialNumber1
+**               MV_U32 serialNumber2
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugSerialNumberSet(MV_U32 serialNumber1, MV_U32 serialNumber2)
+{
+  MV_STATUS rcode;
+  MV_U8     serialNumber[8];
+
+  serialNumber[0] = (MV_U8)((serialNumber1 >> 24) & 0xFF);
+  serialNumber[1] = (MV_U8)((serialNumber1 >> 16) & 0xFF);
+  serialNumber[2] = (MV_U8)((serialNumber1 >> 8) & 0xFF);
+  serialNumber[3] = (MV_U8)((serialNumber1) & 0xFF);
+  serialNumber[4] = (MV_U8)((serialNumber2 >> 24) & 0xFF);
+  serialNumber[5] = (MV_U8)((serialNumber2 >> 16) & 0xFF);
+  serialNumber[6] = (MV_U8)((serialNumber2 >> 8) & 0xFF);
+  serialNumber[7] = (MV_U8)((serialNumber2) & 0xFF);
+
+  rcode = onuGponSrvcSerialNumberSet(serialNumber);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to set Serial Number, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugSerialNumberSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set ONU serial Number
+**
+**  PARAMETERS:  ON_U32 serialNumber1
+**               MV_U32 serialNumber2
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugPasswordSet(MV_U32 passwordNumber1,
+                               MV_U32 passwordNumber2,
+                               MV_U32 passwordNumber3)
+{
+  MV_STATUS rcode;
+  MV_U8     password[10];
+
+  password[0] = (MV_U8)((passwordNumber1 >> 24) & 0xFF);
+  password[1] = (MV_U8)((passwordNumber1 >> 16) & 0xFF);
+  password[2] = (MV_U8)((passwordNumber1 >> 8) & 0xFF);
+  password[3] = (MV_U8)((passwordNumber1) & 0xFF);
+  password[4] = (MV_U8)((passwordNumber2 >> 24) & 0xFF);
+  password[5] = (MV_U8)((passwordNumber2 >> 16) & 0xFF);
+  password[6] = (MV_U8)((passwordNumber2 >> 8) & 0xFF);
+  password[7] = (MV_U8)((passwordNumber2) & 0xFF);
+  password[8] = (MV_U8)((passwordNumber3 >> 24) & 0xFF);
+  password[9] = (MV_U8)((passwordNumber3 >> 16) & 0xFF);
+
+  rcode = onuGponDbPasswordSet(password);
+  if (rcode != MV_OK)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "%s:%d, failed to set password, rcode(%d)\n", __FILE_DESC__, __LINE__, rcode);
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponUiTxEnThresholdConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu tx enable threshold
+**
+**  PARAMETERS:  MV_U32 threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiTxEnThresholdConfig(MV_U32 threshold)
+{
+  mvOnuGponMacTxTxEnableCounterThresholdSet(threshold);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiUtmTcPeriodConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu utm tc period
+**
+**  PARAMETERS:  MV_U32 period
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiUtmTcPeriodConfig(MV_U32 period)
+{
+  mvOnuGponMacUtmTcPeriodSet(period);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiUtmTcValidConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu utm tc valid
+**
+**  PARAMETERS:  MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiUtmTcValidConfig(MV_U32 valid)
+{
+  mvOnuGponMacUtmTcValidSet(valid);
+}
+
+/*******************************************************************************
+**
+**  onuGponUitxDbrBlockSizeConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function change onu dbr block size
+**
+**  PARAMETERS:  MV_U32 blockSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUitxDbrBlockSizeConfig(MV_U32 blockSize)
+{
+  MV_U32 configuredBlockSize;
+
+  onuGponSrvcDbrBlockSizeSet(blockSize, &configuredBlockSize);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugMemReadReg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function test requested address space
+**
+**  PARAMETERS:  MV_U32 readOffset
+**               MV_U32 readEntry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugReadReg(MV_U32 readOffset, MV_U32 readEntry)
+{
+  MV_U32 regValue;
+
+#ifndef PON_FPGA
+  regValue = MV_REG_READ((MV_GPON_MAC_REGS_BASE) + readOffset + (readEntry * sizeof (MV_U32)));
+#else /* PON_FPGA */
+  regValue = MV_REG_READ((MV_GPON_REG_BASE) + readOffset + (readEntry * sizeof (MV_U32)));
+#endif /* PON_FPGA */
+
+  mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+             "Read register offset 0x%x, entry %d = [0x%08X]\n\r", readOffset, readEntry, regValue);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugWriteReg
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function test requested address space
+**
+**  PARAMETERS:  MV_U32 writeOffset
+**               MV_U32 writeEntry
+**               MV_U32 regValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugWriteReg(MV_U32 writeOffset, MV_U32 writeEntry, MV_U32 regValue)
+{
+#ifndef PON_FPGA
+  MV_REG_WRITE((MV_GPON_MAC_REGS_BASE) + writeOffset + (writeEntry * sizeof (MV_U32)), regValue);
+#else /* PON_FPGA */
+  MV_REG_WRITE((MV_GPON_REG_BASE) + writeOffset + (writeEntry * sizeof (MV_U32)), regValue);
+#endif /* PON_FPGA */
+
+  mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+             "Write  register offset 0x%x, entry %d = [0x%08X]\n\r", writeOffset, writeEntry, regValue);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugDebugModeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu denug mode
+**
+**  PARAMETERS:  MV_U32 debugMode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugDebugModeSet(MV_U32 debugMode)
+{
+  MV_BOOL mode;
+
+  mode = (debugMode == 0)? MV_FALSE : MV_TRUE;
+  onuGponPonMngDebugModeSet(mode);
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugUponModeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure onu UPON mode
+**
+**  PARAMETERS:  MV_U32 debugMode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugUponModeSet(MV_U32 uponMode)
+{
+  MV_BOOL mode;
+
+  mode = (uponMode == 0)? MV_FALSE : MV_TRUE;
+  onuGponApiUponDebugSet(mode);
+}
+
+/*******************************************************************************
+****  onuGponUiCfgSetPatternBurst
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function config start onu transmission of pattern burst
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void onuGponUiCfgSetPatternBurst(MV_U32 enable,MV_U32 pattern, MV_U32 burst, MV_U32 duration, MV_U32 period)
+{
+
+    if (enable == 0) {
+        onuPonPatternBurstOff();
+    }
+    else{
+        onuPonPatternBurstOn(pattern, (MV_BOOL)burst, period, duration);
+    }
+
+}
+
+/*******************************************************************************
+**
+**  onuGponUiDebugAdminMode
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handle onu admin mode
+**
+**  PARAMETERS:  MV_U32 admin
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiDebugAdminMode(MV_U32 mode)
+{
+  onuGponApiAdminStateSet(mode);
+}
+
+#ifdef MV_GPON_PERFORMANCE_CHECK
+
+/*******************************************************************************
+**
+**  onuGponCliDebugPerformanceCheck
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function
+**
+**  PARAMETERS:  MV_U32 step
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponCliDebugPerformanceCheck(MV_U32 step)
+{
+  MV_U32 minCheck   = 0;
+  MV_U32 maxCheck   = 0;
+  MV_U32 aveCheck   = 0;
+  MV_U32 aveCount   = 0;
+  MV_U32 tempCheck  = 0;
+  MV_U32 minMaxTemp = 0;
+  MV_U32 index;
+
+  S_GponPerformanceCheckNode *tmpPmCheckNode;
+
+  char* pmStepDesc[] =
+  {
+    "ISR        ",
+    "MNG1       ",
+    "MNG2       ",
+    "MNG3       ",
+    "ExtB       ",
+    "Key Switch ",
+    "Cfg Port   ",
+    "Req Key    ",
+    "AllocId    ",
+    "Password   ",
+    "Enc Port   ",
+    "Dis        ",
+    "Dact       ",
+    "Rng        ",
+    "OnuId      ",
+    "Over       "
+  };
+
+  if (step >= PON_MAX_PERFORMANCE)
+  {
+    mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+               "Invalid performance step(%d)\n", step);
+    return;
+  }
+
+  tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[step]);
+
+  mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+             "             Interval    Minimum     Maximum     Average\n");
+
+  aveCount = 0;
+  for (index = 0; index < tmpPmCheckNode->uSecCntIdx; index++)
+  {
+    tempCheck = tmpPmCheckNode->uSecCntStop[index] -
+                tmpPmCheckNode->uSecCntStart[index];
+
+    if (tempCheck < 1000)
+    {
+      aveCheck += tempCheck;
+      aveCount++;
+
+      if (minMaxTemp == 0)
+      {
+        minCheck = maxCheck = tempCheck;
+        minMaxTemp = 1;
+      }
+      else
+      {
+        if      (tempCheck > maxCheck) maxCheck = tempCheck;
+        else if (tempCheck < minCheck) minCheck = tempCheck;
+      }
+    }
+  }
+
+  if (aveCount > 0) aveCheck = aveCheck / aveCount;
+
+  mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+             "%11s  %8u    %7lu     %7lu     %7lu\n",
+             pmStepDesc[step], tmpPmCheckNode->uSecCntIdx, minCheck, maxCheck, aveCheck);
+
+  if (tmpPmCheckNode->uSecCntIdx > 0)
+  {
+    for (index = 0; index < tmpPmCheckNode->uSecCntIdx - 1; index++)
+    {
+      mvPonPrint(PON_PRINT_INFO, PON_CLI_MODULE,
+                 "%11s   Start %u Stop %u diff %u\n",
+                 pmStepDesc[step],
+                 tmpPmCheckNode->uSecCntStart[index],
+                 tmpPmCheckNode->uSecCntStop[index],
+                 (tmpPmCheckNode->uSecCntStop[index] - tmpPmCheckNode->uSecCntStart[index]));
+    }
+  }
+}
+
+/*******************************************************************************
+**
+**  onuGponCliDebugPerformanceClear
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponCliDebugPerformanceClear(void)
+{
+  MV_U32 step;
+  MV_U32 index;
+  S_GponPerformanceCheckNode *tmpPmCheckNode;
+
+  for (step = 0; step < PON_MAX_PERFORMANCE; step++)
+  {
+    tmpPmCheckNode = &(g_GponPmCheck.pmCheckNode[step]);
+
+    for (index = 0; index < tmpPmCheckNode->uSecCntIdx; index++)
+    {
+      tmpPmCheckNode->uSecCntStop[index]  = 0;
+      tmpPmCheckNode->uSecCntStart[index] = 0;
+    }
+
+    tmpPmCheckNode->uSecCntIdx = 0;
+  }
+}
+
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+
+/*******************************************************************************
+**
+**  onuGponUiT01IntervalConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiT01IntervalConfig(MV_U32 interval)
+{
+	S_OnuPonTimer  *timerId = &(onuPonResourceTbl_s.onuGponT01_TimerId);
+
+	if (timerId->onuPonTimerActive != ONU_PON_TIMER_ACTIVE) {
+		onuPonTimerUpdate(timerId,
+						  timerId->onuPonTimerId.data,
+						  interval,
+						  0);
+	} else
+		printk(KERN_ERR "GPON T01 timer is running, the value is not accepted\n");
+
+}
+
+/*******************************************************************************
+**
+**  onuGponUiT02IntervalConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void onuGponUiT02IntervalConfig(MV_U32 interval)
+{
+	S_OnuPonTimer  *timerId = &(onuPonResourceTbl_s.onuGponT02_TimerId);
+
+	if (timerId->onuPonTimerActive != ONU_PON_TIMER_ACTIVE) {
+		onuPonTimerUpdate(timerId,
+						  timerId->onuPonTimerId.data,
+						  interval,
+						  0);
+	} else
+		printk(KERN_ERR "GPON T02 timer is running, the value is not accepted\n");
+
+}
+
+
+/*******************************************************************************
+**
+**  onuGponUiMiscHelpShow
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print misc help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int onuGponUiMiscHelpShow(char* buf)
+{
+	int off = 0;
+	MV_U32 devId = mvCtrlModelGet();
+
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, "Configuration Commands[HEX]\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, " echo [SN1] [SN2]                > serialNumCfg    - config serial number\n");
+    off += mvOsSPrintf(buf+off, " echo [PWD1] [PWD2] [PWD3]       > passwordCfg     - config password\n");
+    off += mvOsSPrintf(buf+off, "                                                     10 bytes: PWD1, PWD2, 2 MSB of PWD3\n");
+	off += mvOsSPrintf(buf+off, " echo [TxEnThreshold]            > txEnThresCfg    - config tx enable threshold\n");
+	off += mvOsSPrintf(buf+off, " echo [TC Period]                > utmTxPeriodCfg  - config utm tc period\n");
+	off += mvOsSPrintf(buf+off, " echo [TC Valid]                 > utmTcValidCfg   - config utm tc valid\n");
+	off += mvOsSPrintf(buf+off, " echo [DBR Block Size]           > txDbrBlkSizeCfg - config dbr block size\n");
+	off += mvOsSPrintf(buf+off, " echo [Offset] [Entry]           > readReg         - "
+						"read onu reg [Id from mvPonOnuRegs.h]\n");
+	off += mvOsSPrintf(buf+off, " echo [Offset] [Entry] [Value]   > writeReg        - "
+						"write onu reg [Id from mvPonOnuRegs.h]\n");
+	off += mvOsSPrintf(buf+off, " echo [Mode]                     > debugModeCfg    - config debug mode\n");
+	off += mvOsSPrintf(buf+off, " echo [Mode]                     > stopPonSw       - "
+						"stop PON switching (enabled/disabled)\n");
+	off += mvOsSPrintf(buf+off, " echo [Section]                  > pmCheck         - performance check section\n");
+	off += mvOsSPrintf(buf+off, " echo [0]                        > pmClear         - performance check reset\n");
+	off += mvOsSPrintf(buf+off, " echo [module] [Level] [Options] > printMask       - change printing options\n");
+	off += mvOsSPrintf(buf+off, " echo [state]                    > adminCfg        - "
+						"change PON BE (TX EN) state 0=Enable, 1=Disable\n");
+	off += mvOsSPrintf(buf+off, " echo [enable][pattern][burst][duration][period] > pattern\n");
+	off += mvOsSPrintf(buf+off, "                                                   - "
+						"start enable[1] or stop [0] transmission of\n");
+	off += mvOsSPrintf(buf+off, "                                                     "
+						"pattern: 0x1-1T, 0x2-2T, 0x80-RPBS-9, 0x82-RPBS-15, 0x83-RPBS-23\n");
+	off += mvOsSPrintf(buf+off, "                                                     "
+						"burst: 0-static, 1-periodic\n");
+	off += mvOsSPrintf(buf+off, "                                                     "
+						"duration: peak time interval[micro seconds]\n");
+	off += mvOsSPrintf(buf+off, "                                                     "
+						"period - full cicle time interval[micro seconds]\n");
+	off += mvOsSPrintf(buf+off, " echo [T01 Interval]             > t01IntervalCfg  - "
+						"config T01 timer interval in mS\n");
+	off += mvOsSPrintf(buf+off, " echo [T02 Interval]             > t02IntervalCfg  - "
+						"config T02 timer interval in mS\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, "Display Commands: cat <file>\n");
+	off += mvOsSPrintf(buf+off, "============================================================================\n");
+	off += mvOsSPrintf(buf+off, " cat printMask                                     - dump printing options\n");
+
+	return(off);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ========================================================================== */
+/* ========================================================================== */
+/*                            ONU SYS FS Definition                           */
+/* ========================================================================== */
+/* ========================================================================== */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Misc Commands                                   */
+/* ========================================================================== */
+static ssize_t misc_show(struct device *dev,
+                         struct device_attribute *attr,
+                         char *buf)
+{
+	const char* name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "printMask"))
+		return ponOnuPrintStatus(buf);
+	else if (!strcmp(name, "helpMisc"))
+		return onuGponUiMiscHelpShow(buf);
+
+	return 0;
+}
+
+static ssize_t misc_store(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t len)
+{
+	const char* name = attr->attr.name;
+	unsigned long flags;
+	unsigned int  param1 = 0;
+	unsigned int  param2 = 0;
+	unsigned int  param3 = 0;
+	unsigned int  param4 = 0;
+	unsigned int  param5 = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%x %x %x %x %x", &param1, &param2, &param3, &param4, &param5);
+
+	raw_local_irq_save(flags);
+
+	if (!strcmp(name, "serialNumCfg"))		/* serialNumber1, serialNumber2 */
+		onuGponUiDebugSerialNumberSet((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "passwordCfg"))		/* serialNumber1, serialNumber2 */
+		onuGponUiDebugPasswordSet((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);
+	else if (!strcmp(name, "txEnThresCfg"))		/* threshold */
+		onuGponUiTxEnThresholdConfig((MV_U32)param1);
+	else if (!strcmp(name, "utmTxPeriodCfg"))	/* period */
+		onuGponUiUtmTcPeriodConfig((MV_U32)param1);
+	else if (!strcmp(name, "utmTcValidCfg"))	/* valid */
+		onuGponUiUtmTcValidConfig((MV_U32)param1);
+	else if (!strcmp(name, "txDbrBlkSizeCfg"))	/* blockSize */
+		onuGponUitxDbrBlockSizeConfig((MV_U32)param1);
+	else if (!strcmp(name, "readReg"))		/* readOffset, readEntry */
+		onuGponUiDebugReadReg((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "writeReg"))		/*  writeOffset, writeEntry, regValue */
+		onuGponUiDebugWriteReg((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);
+	else if (!strcmp(name, "debugModeCfg"))		/* debugMode */
+		onuGponUiDebugDebugModeSet((MV_U32)param1);
+	else if (!strcmp(name, "stopPonSw"))		/* uponMode */
+		onuGponUiDebugUponModeSet((MV_U32)param1);
+#ifdef MV_GPON_PERFORMANCE_CHECK
+	else if (!strcmp(name, "pmCheck"))		/* step */
+		onuGponCliDebugPerformanceCheck((MV_U32)param1);
+	else if (!strcmp(name, "pmClear"))
+		onuGponCliDebugPerformanceClear();
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+	else if (!strcmp(name, "printMask"))		/* module, print level, options */
+		ponOnuChangePrintStatus((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);
+	else if (!strcmp(name, "pattern"))		/* pattern type, burst type, duration, period */
+		onuGponUiCfgSetPatternBurst((MV_U32)param1, (MV_U32)param2, (MV_U32)param3 ,
+					    (MV_U32)param4 , (MV_U32)param5);
+	else if (!strcmp(name, "adminCfg"))		/* admin 0=enable 1 = disable */
+		onuGponUiDebugAdminMode((MV_U32)param1);
+	else if (!strcmp(name, "t01IntervalCfg"))	/* T01 interval in mS */
+		onuGponUiT01IntervalConfig((MV_U32)param1);
+	else if (!strcmp(name, "t02IntervalCfg"))	/* T02 interval in mS */
+		onuGponUiT02IntervalConfig((MV_U32)param1);
+	else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	raw_local_irq_restore(flags);
+
+	return(len);
+}
+
+/* ========================================================================== */
+/*                            Misc Attributes                                 */
+/* ========================================================================== */
+static DEVICE_ATTR(serialNumCfg,          S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(passwordCfg,           S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(txEnThresCfg,          S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(utmTxPeriodCfg,        S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(utmTcValidCfg,         S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(txDbrBlkSizeCfg,       S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(readReg,               S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(writeReg,              S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(debugModeCfg,          S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(stopPonSw,             S_IWUSR, misc_show, misc_store);
+#ifdef MV_GPON_PERFORMANCE_CHECK
+static DEVICE_ATTR(pmCheck,               S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(pmClear,               S_IWUSR, misc_show, misc_store);
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+static DEVICE_ATTR(printMask,             S_IRUSR | S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(pattern,               S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(adminCfg,              S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(helpMisc,              S_IRUSR, misc_show, misc_store);
+static DEVICE_ATTR(t01IntervalCfg,        S_IWUSR, misc_show, misc_store);
+static DEVICE_ATTR(t02IntervalCfg,        S_IWUSR, misc_show, misc_store);
+
+static struct attribute *misc_attrs[] = {
+	&dev_attr_serialNumCfg.attr,
+	&dev_attr_passwordCfg.attr,
+	&dev_attr_txEnThresCfg.attr,
+	&dev_attr_utmTxPeriodCfg.attr,
+	&dev_attr_utmTcValidCfg.attr,
+	&dev_attr_txDbrBlkSizeCfg.attr,
+	&dev_attr_readReg.attr,
+	&dev_attr_writeReg.attr,
+	&dev_attr_debugModeCfg.attr,
+	&dev_attr_stopPonSw.attr,
+#ifdef MV_GPON_PERFORMANCE_CHECK
+	&dev_attr_pmCheck.attr,
+	&dev_attr_pmClear.attr,
+#endif /* MV_GPON_PERFORMANCE_CHECK */
+	&dev_attr_printMask.attr,
+	&dev_attr_helpMisc.attr,
+	&dev_attr_pattern.attr,
+	&dev_attr_adminCfg.attr,
+	&dev_attr_t01IntervalCfg.attr,
+	&dev_attr_t02IntervalCfg.attr,
+	NULL
+};
+
+static struct attribute_group misc_group =
+{
+  .name = "misc",
+  .attrs = misc_attrs,
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Protocol Group                                 */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Protocol Commands                               */
+/* ========================================================================== */
+static ssize_t protocol_show(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+	const char* name = attr->attr.name;
+	MV_U32 devId = mvCtrlModelGet();
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "txBurst"))
+		return(onuGponUiDebugBurstInfo(buf));
+	else if (!strcmp(name, "gemFrameLen"))
+		return(onuGponUiGemFrameLengthShow(buf));
+	else if (!strcmp(name, "helpProto"))
+		return(onuGponUiProtoHelpShow(buf));
+	else if (devId == MV_6601_DEV_ID) {
+		if (!strcmp(name, "acCoupling"))
+			return onuGponUiDebugManagerAcCouplingGet(buf);
+	}
+	return 0;
+}
+
+static ssize_t protocol_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t len)
+{
+	const char* name = attr->attr.name;
+	unsigned long flags;
+	unsigned int  param1 = 0;
+	unsigned int  param2 = 0;
+	unsigned int  param3 = 0;
+	unsigned int  param4 = 0;
+	unsigned int  param5 = 0;
+	MV_U32 devId = mvCtrlModelGet();
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sscanf(buf, "%d %d %d %d %d", &param1, &param2, &param3, &param4, &param5);
+
+	raw_local_irq_save(flags);
+
+	if (!strcmp(name, "txBurstCfg"))		/* start, stop, order, polarity, mask */
+		onuGponUiDebugBurstConfig((MV_U32)param1, (MV_U32)param2, (MV_U32)param3,
+					  (MV_U32)param4, (MV_U32)param5);
+	else if (!strcmp(name, "berIntervalCfg"))	/* interval */
+		onuGponUiDebugBerIntervalDebug((MV_U32)param1);
+	else if (!strcmp(name, "berCoeffCfg"))		/* numerator, denominator*/
+		onuGponUiDebugBerCoefficientDebug((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "berThesholdCfg"))	/* sd, sf */
+		onuGponUiBerThresholdsConfig((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "omciPortCfg"))		/* portId, valid */
+		onuGponUiGemOmciPortIdConfig((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "gemFrameLenCfg"))	/* payloadLen */
+		onuGponUiGemPayloadLenConfig((MV_U32)param1);
+	else if (!strcmp(name, "ethFrameLenCfg"))	/* minFrameLenArg, maxFrameLenArg */
+		onuGponUiGemEthFrameLenConfig((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "omciFrameLenCfg"))	/* minFrameLenArg, maxFrameLenArg */
+		onuGponUiGemOmciFrameLenConfig((MV_U32)param1, (MV_U32)param2);
+	else if (!strcmp(name, "ploamMsgSend"))		/* msgId, onuId, data1, data2, data3 */
+		onuGponUiDebugManagerSendPloam((MV_U32)param1, (MV_U32)param2, (MV_U32)param3,
+					       (MV_U32)param4, (MV_U32)param5);
+	else if (!strcmp(name, "ploamMsgRece"))		/* msgId, onuId, data1, data2, data3 */
+		onuGponUiDebugManagerReceivePloam((MV_U32)param1, (MV_U32)param2, (MV_U32)param3,
+						  (MV_U32)param4, (MV_U32)param5);
+	else if (!strcmp(name, "ploamBurstRcv"))	/* msgId, onuId, data1, data2, data3 */
+		onuGponUiDebugManagerRcvBurstPloams((MV_U32)param1, (MV_U32)param2, (MV_U32)param3,
+						    (MV_U32)param4, (MV_U32)param5);
+	else if (!strcmp(name, "ploamBurstCfg"))	/* burst size */
+		onuGponUiDebugManagerRcvBurstCfg((MV_U32)param1);
+	else if (!strcmp(name, "clearFifoCnts"))	/* value */
+		onuGponUiDebugManagerFifoCntsClear((MV_U32)param1);
+	else if (!strcmp(name, "fifoSupport"))		/* enable/disable */
+		onuGponUiDebugManagerFifoSupportSet((MV_U32)param1);
+	else if (devId == MV_6601_DEV_ID) {
+		if (!strcmp(name, "acCoupling"))				/* mode, time, pattern1, pattern2 */
+			onuGponUiDebugManagerAcCouplingSet((MV_U32)param1, (MV_U32)param2, (MV_U32)param3,
+							   (MV_U32)param4);
+		else
+			printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+	} else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	raw_local_irq_restore(flags);
+
+	return(len);
+}
+
+/* ========================================================================== */
+/*                            Protocol Attributes                             */
+/* ========================================================================== */
+static DEVICE_ATTR(txBurstCfg,       S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(txBurst,          S_IRUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(berIntervalCfg,   S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(berCoeffCfg,      S_IRUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(berThesholdCfg,   S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(omciPortCfg,      S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(gemFrameLen,      S_IRUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(gemFrameLenCfg,   S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(ethFrameLenCfg,   S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(omciFrameLenCfg,  S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(ploamMsgSend,     S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(ploamMsgRece,     S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(ploamBurstRcv,    S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(ploamBurstCfg,    S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(clearFifoCnts,    S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(fifoSupport,      S_IWUSR, protocol_show, protocol_store);
+static DEVICE_ATTR(helpProto,        S_IRUSR, protocol_show, protocol_store);
+
+static struct attribute *protocol_attrs[] = {
+	&dev_attr_txBurstCfg.attr,
+	&dev_attr_txBurst.attr,
+	&dev_attr_berIntervalCfg.attr,
+	&dev_attr_berCoeffCfg.attr,
+	&dev_attr_berThesholdCfg.attr,
+	&dev_attr_omciPortCfg.attr,
+	&dev_attr_gemFrameLen.attr,
+	&dev_attr_gemFrameLenCfg.attr,
+	&dev_attr_ethFrameLenCfg.attr,
+	&dev_attr_omciFrameLenCfg.attr,
+	&dev_attr_ploamMsgSend.attr,
+	&dev_attr_ploamMsgRece.attr,
+	&dev_attr_ploamBurstRcv.attr,
+	&dev_attr_ploamBurstCfg.attr,
+	&dev_attr_clearFifoCnts.attr,
+	&dev_attr_fifoSupport.attr,
+	&dev_attr_helpProto.attr,
+	NULL
+};
+
+static struct attribute_group protocol_group =
+{
+  .name = "protocol",
+  .attrs = protocol_attrs,
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Introp Group                                    */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Introp Commands                                 */
+/* ========================================================================== */
+static ssize_t introp_show(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+  const char* name = attr->attr.name;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  if      (!strcmp(name, "manMode"))
+  	return (onuGponUiOverrideShow(buf));
+  else if (!strcmp(name, "helpIot"))
+    return (onuGponUiIntropHelpShow(buf));
+
+
+  return 0;
+}
+
+static ssize_t introp_store(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t len)
+{
+  const char* name = attr->attr.name;
+  unsigned long flags;
+  unsigned int  param1 = 0;
+  unsigned int  param2 = 0;
+  unsigned int  param3 = 0;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  sscanf(buf, "%d %d %d", &param1, &param2, &param3);
+
+  raw_local_irq_save(flags);
+
+  if      (!strcmp(name, "onuIdCfg"))
+  	onuGponUiOnuIdConfig((MV_U32)param1, (MV_U32)param2);                           /* onuId, enable */
+  else if (!strcmp(name, "portIdCfg"))
+    onuGponUiPortIdConfig((MV_U32)param1, (MV_U32)param2);                          /* portId, enable */
+  else if (!strcmp(name, "eqdCfg"))
+    onuGponUiEquDelaySetConfig((MV_U32)param1, (MV_U32)param2);                     /* equDelayVal, enable*/
+  else if (!strcmp(name, "eqdChange"))
+    onuGponUiEquDelayChangeConfig((MV_U32)param1, (MV_U32)param2);                  /* direction, size */
+  else if (!strcmp(name, "extBurstCfg"))
+    onuGponUiExtendedBurstConfig((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);   /* enable, rangeValue, operValue */
+  else if (!strcmp(name, "extBurstDelayCfg"))
+    onuGponUiExtendedBurstDelayConfig((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);   /* enable, rangeValue, operValue */
+  else if (!strcmp(name, "delimiterCfg"))
+    onuGponUiDelimiterConfig((MV_U32)param1, (MV_U32)param2);                       /* enable , value*/
+  else if (!strcmp(name, "preambleCfg"))
+    onuGponUiDebugOverheadPreamble((MV_U32)param1, (MV_U32)param2, (MV_U32)param3); /* pream3RangeCnt, pream3OperCnt, pream3PattCnt */
+  else if (!strcmp(name, "guardCfg"))
+    onuGponUiDebugOverheadGuard((MV_U32)param1);                                    /* guard */
+  else if (!strcmp(name, "manModeCfg"))
+    onuGponUiDebugOverheadMode((MV_U32)param1);                                     /* overMode */
+  else
+ 	printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+  raw_local_irq_restore(flags);
+
+  return(len);
+}
+
+/* ========================================================================== */
+/*                            Introp Attributes                                 */
+/* ========================================================================== */
+static DEVICE_ATTR(onuIdCfg,        S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(portIdCfg,       S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(eqdCfg,          S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(eqdChange,       S_IRUSR, introp_show, introp_store);
+static DEVICE_ATTR(extBurstCfg,     S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(extBurstDelayCfg,S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(delimiterCfg,    S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(preambleCfg,     S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(guardCfg,        S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(manModeCfg,      S_IWUSR, introp_show, introp_store);
+static DEVICE_ATTR(manMode,         S_IRUSR, introp_show, introp_store);
+static DEVICE_ATTR(helpIot,         S_IRUSR, introp_show, introp_store);
+
+static struct attribute *introp_attrs[] = {
+    &dev_attr_onuIdCfg.attr,
+	&dev_attr_portIdCfg.attr,
+	&dev_attr_eqdCfg.attr,
+    &dev_attr_eqdChange.attr,
+	&dev_attr_extBurstCfg.attr,
+    &dev_attr_extBurstDelayCfg.attr,
+    &dev_attr_delimiterCfg.attr,
+    &dev_attr_preambleCfg.attr,
+    &dev_attr_guardCfg.attr,
+    &dev_attr_manModeCfg.attr,
+	&dev_attr_manMode.attr,
+    &dev_attr_helpIot.attr,
+	NULL
+};
+
+static struct attribute_group introp_group =
+{
+  .name = "introp",
+  .attrs = introp_attrs,
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Data Group                                      */
+/* ========================================================================== */
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Data Commands                                   */
+/* ========================================================================== */
+static ssize_t data_show(struct device *dev,
+                         struct device_attribute *attr,
+                         char *buf)
+{
+  const char* name = attr->attr.name;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  if      (!strcmp(name, "showTcont"))
+  	return (onuGponUiDebugTcont(buf));
+  else if (!strcmp(name, "showGem0xxx"))
+    return (onuGponUiDebugGemPortid(buf, 0));
+  else if (!strcmp(name, "showGem1xxx"))
+    return (onuGponUiDebugGemPortid(buf, 1));
+  else if (!strcmp(name, "showGem2xxx"))
+    return (onuGponUiDebugGemPortid(buf, 2));
+  else if (!strcmp(name, "showGem3xxx"))
+    return (onuGponUiDebugGemPortid(buf, 3));
+  else if (!strcmp(name, "showAes0xxx"))
+  	return (onuGponUiDebugAesGemAll(buf, 0));
+  else if (!strcmp(name, "showAes1xxx"))
+  	return (onuGponUiDebugAesGemAll(buf, 1));
+  else if (!strcmp(name, "showAes2xxx"))
+  	return (onuGponUiDebugAesGemAll(buf, 2));
+  else if (!strcmp(name, "showAes3xxx"))
+  	return (onuGponUiDebugAesGemAll(buf, 3));
+  else if (!strcmp(name, "showMibGemPorts"))
+    return (onuGponUiDebugGemPmListShow(buf));
+  else if (!strcmp(name, "helpData"))
+    return (onuGponUiDataHelpShow(buf));
+
+  return 0;
+}
+
+static ssize_t data_store(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t len)
+{
+  const char* name = attr->attr.name;
+  unsigned long flags;
+  unsigned int  param1 = 0;
+  unsigned int  param2 = 0;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  sscanf(buf, "%d %d", &param1, &param2);
+
+  raw_local_irq_save(flags);
+
+  if      (!strcmp(name, "cfgTcont"))
+  	onuGponUiTcontConfig((MV_U32)param1, (MV_U32)param2);             /* alloc, tcont */
+  else if (!strcmp(name, "clrTcont"))
+    onuGponUiClearTcontConfig((MV_U32)param1);                        /* tcont */
+  else if (!strcmp(name, "rstTcont"))
+    onuGponUiResetTcontsConfig();
+  else if (!strcmp(name, "cfgGem"))
+    onuGponUiDebugGemPortidValidSet((MV_U32)param1, (MV_U32)param2);  /* portId, enable */
+  else if (!strcmp(name, "cfgAllGem"))
+    onuGponUiDebugAllGemPortidValidSet((MV_U32)param1);               /* enable */
+  else if (!strcmp(name, "cfgMibPm"))
+    onuGponUiDebugGemPmSet((MV_U32)param1, (MV_U32)param2);           /* Start or stop Gem port PM */
+  else if (!strcmp(name, "resetMibPm"))
+    onuGponUiDebugGemPmReset();                                       /* Reset PM*/
+  else if (!strcmp(name, "getMibPm"))
+    onuGponUiDebugGemPmGet((MV_U32)param1);                           /* Get GEM PM counters */
+#ifdef MV_GPON_STATIC_GEM_PORT
+  else if (!strcmp(name, "dummyGemState"))
+    onuGponUiDebugDummyGemPortFlagSet((MV_U32)param1);                /* flag */
+  else if (!strcmp(name, "dummyGemRst"))
+    onuGponUiDebugDummyGemPortReset();
+#endif /* MV_GPON_STATIC_GEM_PORT */
+  else if (!strcmp(name, "cfgAesPort"))
+    onuGponUiDebugAesSet((MV_U32)param1, (MV_U32)param2);                 /* portId, enable */
+  else if (!strcmp(name, "cfgAllAes"))
+    onuGponUiDebugAesSetAll((MV_U32)param1);                              /* enable */
+  else
+ 	printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+  raw_local_irq_restore(flags);
+
+  return(len);
+}
+
+/* ========================================================================== */
+/*                            Data Attributes                                 */
+/* ========================================================================== */
+static DEVICE_ATTR(cfgTcont,          S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(clrTcont,          S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(rstTcont,          S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(showTcont,         S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(cfgGem,            S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(cfgAllGem,         S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(showGem0xxx,       S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(showGem1xxx,       S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(showGem2xxx,       S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(showGem3xxx,       S_IRUSR, data_show, data_store);
+#ifdef MV_GPON_STATIC_GEM_PORT
+static DEVICE_ATTR(dummyGemState,     S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(dummyGemRst,       S_IWUSR, data_show, data_store);
+#endif /* MV_GPON_STATIC_GEM_PORT */
+static DEVICE_ATTR(cfgAesPort,        S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(cfgMibPm,          S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(resetMibPm,        S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(getMibPm,          S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(showMibGemPorts,   S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(cfgAllAes,         S_IWUSR, data_show, data_store);
+static DEVICE_ATTR(showAes0xxx,       S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(showAes1xxx,       S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(showAes2xxx,       S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(showAes3xxx,       S_IRUSR, data_show, data_store);
+static DEVICE_ATTR(helpData,          S_IRUSR, data_show, data_store);
+
+static struct attribute *data_attrs[] = {
+	&dev_attr_cfgTcont.attr,
+	&dev_attr_clrTcont.attr,
+	&dev_attr_rstTcont.attr,
+	&dev_attr_showTcont.attr,
+	&dev_attr_cfgGem.attr,
+	&dev_attr_cfgAllGem.attr,
+	&dev_attr_cfgMibPm.attr,
+	&dev_attr_resetMibPm.attr,
+    &dev_attr_getMibPm.attr,
+    &dev_attr_showMibGemPorts.attr,
+	&dev_attr_showGem0xxx.attr,
+    &dev_attr_showGem1xxx.attr,
+    &dev_attr_showGem2xxx.attr,
+    &dev_attr_showGem3xxx.attr,
+#ifdef MV_GPON_STATIC_GEM_PORT
+	&dev_attr_dummyGemState.attr,
+	&dev_attr_dummyGemRst.attr,
+#endif /* MV_GPON_STATIC_GEM_PORT */
+	&dev_attr_cfgAesPort.attr,
+    &dev_attr_cfgAllAes.attr,
+    &dev_attr_showAes0xxx.attr,
+    &dev_attr_showAes1xxx.attr,
+    &dev_attr_showAes2xxx.attr,
+    &dev_attr_showAes3xxx.attr,
+	&dev_attr_helpData.attr,
+	NULL
+};
+
+static struct attribute_group data_group =
+{
+  .name = "data",
+  .attrs = data_attrs,
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Pm Group                                        */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Pm Commands                                     */
+/* ========================================================================== */
+static ssize_t gpon_pm_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+  const char* name = attr->attr.name;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  if      (!strcmp(name, "fecCnt"))
+  	return (onuGponUiFecCountersShow(buf));
+  else if (!strcmp(name, "rxPloamCnt"))
+    return (onuGponUiRxPloamCountersShow(buf));
+  else if (!strcmp(name, "txPloamCnt"))
+    return (onuGponUiTxPloamCountersShow(buf));
+  else if (!strcmp(name, "bwMapCnt"))
+    return (onuGponUiBwMapCountersShow(buf));
+  else if (!strcmp(name, "stdCnt"))
+    return (onuGponUiStandardCountersShow(buf));
+  else if (!strcmp(name, "gemCnt"))
+    return (onuGponUiGemCountersShow(buf));
+  else if (!strcmp(name, "txPktCnt"))
+    return (onuGponUiTxCountersShow(buf));
+  else if (!strcmp(name, "rawCnt_1"))
+    return (onuGponUiRaw_1Counters(buf));
+  else if (!strcmp(name, "rawCnt_2"))
+    return (onuGponUiRaw_2Counters(buf));
+  else if (!strcmp(name, "helpGPm"))
+    return (onuGponUiPmHelpShow(buf));
+
+  return 0;
+}
+
+static ssize_t gpon_pm_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t len)
+{
+  const char* name = attr->attr.name;
+  unsigned long flags;
+  unsigned int  param = 0;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  sscanf(buf, "%d", &param);
+
+  raw_local_irq_save(flags);
+
+  if (!strcmp(name, "cntRdClrFlState"))
+  	onuGponUiCountersReadClearFlag((MV_BOOL)param);
+  if (!strcmp(name, "bwMapCntByState"))
+    onuGponBwMapCountersEnDisFlag((MV_BOOL)param);
+  else
+  	printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+  raw_local_irq_restore(flags);
+
+  return(len);
+}
+
+/* ========================================================================== */
+/*                            PM Attributes                                   */
+/* ========================================================================== */
+static DEVICE_ATTR(fecCnt,        S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(rxPloamCnt,    S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(txPloamCnt,    S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(bwMapCnt,      S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(stdCnt,        S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(gemCnt,        S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(txPktCnt,      S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(rawCnt_1,      S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(rawCnt_2,      S_IRUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(cntRdClrFlState,S_IWUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(bwMapCntByState,S_IWUSR, gpon_pm_show, gpon_pm_store);
+static DEVICE_ATTR(helpGPm,       S_IRUSR, gpon_pm_show, gpon_pm_store);
+
+static struct attribute *gpon_pm_attrs[] = {
+    &dev_attr_fecCnt.attr,
+	&dev_attr_rxPloamCnt.attr,
+	&dev_attr_txPloamCnt.attr,
+	&dev_attr_bwMapCnt.attr,
+	&dev_attr_stdCnt.attr,
+	&dev_attr_gemCnt.attr,
+	&dev_attr_txPktCnt.attr,
+	&dev_attr_rawCnt_1.attr,
+    &dev_attr_rawCnt_2.attr,
+	&dev_attr_cntRdClrFlState.attr,
+    &dev_attr_bwMapCntByState.attr,
+    &dev_attr_helpGPm.attr,
+	NULL
+};
+
+static struct attribute_group gpon_pm_group =
+{
+  .name = "pm",
+  .attrs = gpon_pm_attrs,
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Info Group                                      */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Info Commands                                   */
+/* ========================================================================== */
+static ssize_t gpon_info_show(struct device *dev,
+                              struct device_attribute *attr,
+                              char *buf)
+{
+  const char* name = attr->attr.name;
+
+  if (!capable(CAP_NET_ADMIN))
+  	return -EPERM;
+
+  if      (!strcmp(name, "infoGpon"))
+  	return(onuGponUiInfoShow(buf));
+  else if (!strcmp(name, "alarmGpon"))
+    return(onuGponUiAlarmShow(buf));
+  else if (!strcmp(name, "swfifoGpon"))
+    return(onuGponUiFifoShow(buf));
+  else if (!strcmp(name, "fecStatus"))
+    return(onuGponUiFecStatus(buf));
+  else if (!strcmp(name, "helpGInfo"))
+    return(onuGponUiInfoHelpShow(buf));
+
+  return 0;
+}
+
+static ssize_t gpon_info_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t len)
+{
+  return(0);
+}
+
+/* ========================================================================== */
+/*                            Info Attributes                                 */
+/* ========================================================================== */
+static DEVICE_ATTR(infoGpon,   S_IRUSR, gpon_info_show, gpon_info_store);
+static DEVICE_ATTR(alarmGpon,  S_IRUSR, gpon_info_show, gpon_info_store);
+static DEVICE_ATTR(swfifoGpon, S_IRUSR, gpon_info_show, gpon_info_store);
+static DEVICE_ATTR(fecStatus,  S_IRUSR, gpon_info_show, gpon_info_store);
+static DEVICE_ATTR(helpGInfo,  S_IRUSR, gpon_info_show, gpon_info_store);
+
+static struct attribute *gpon_info_attrs[] = {
+	&dev_attr_infoGpon.attr,
+	&dev_attr_alarmGpon.attr,
+    &dev_attr_swfifoGpon.attr,
+	&dev_attr_fecStatus.attr,
+    &dev_attr_helpGInfo.attr,
+	NULL
+};
+
+static struct attribute_group gpon_info_group =
+{
+  .name = "info",
+  .attrs = gpon_info_attrs,
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            ONU SYS FS                                      */
+/* ========================================================================== */
+/******************************************************************************/
+int __devinit gpon_sysfs_init(void)
+{
+  int err;
+  struct device *pd;
+
+  pd = bus_find_device_by_name(&platform_bus_type, NULL, "gpon");
+  if (!pd) {
+  	platform_device_register_simple("gpon", -1, NULL, 0);
+  	pd = bus_find_device_by_name(&platform_bus_type, NULL, "gpon");
+  }
+
+  if (!pd) {
+  	printk(KERN_ERR"%s: cannot find gpon device\n", __FUNCTION__);
+  	pd = &platform_bus;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &gpon_info_group);
+  if (err) {
+  	printk(KERN_INFO "sysfs group failed %d\n", err);
+  	goto out;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &gpon_pm_group);
+  if (err) {
+  	printk(KERN_INFO "sysfs group failed %d\n", err);
+  	goto out;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &data_group);
+  if (err) {
+  	printk(KERN_INFO "sysfs group failed %d\n", err);
+  	goto out;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &introp_group);
+  if (err) {
+  	printk(KERN_INFO "sysfs group failed %d\n", err);
+  	goto out;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &protocol_group);
+  if (err) {
+  	printk(KERN_INFO "sysfs group failed %d\n", err);
+  	goto out;
+  }
+
+  err = sysfs_create_group(&pd->kobj, &misc_group);
+  if (err) {
+      printk(KERN_INFO "sysfs group failed %d\n", err);
+      goto out;
+  }
+
+  printk(KERN_INFO "= PON Module SYS FS Init ended successfully =\n");
+out:
+  return err;
+}
+
+void gpon_sysfs_delete(void)
+{
+  struct device *pd;
+
+  pd = bus_find_device_by_name(&platform_bus_type, NULL, "gpon");
+  if (!pd)
+  {
+  	printk("%s: cannot find gpon device\n", __FUNCTION__);
+	return;
+  }
+
+  sysfs_remove_group(&pd->kobj, &gpon_info_group);
+  sysfs_remove_group(&pd->kobj, &gpon_pm_group);
+  sysfs_remove_group(&pd->kobj, &data_group);
+  sysfs_remove_group(&pd->kobj, &introp_group);
+  sysfs_remove_group(&pd->kobj, &protocol_group);
+  sysfs_remove_group(&pd->kobj, &misc_group);
+
+  printk(KERN_INFO "= PON Module SYS FS Remove ended successfully =\n");
+}
+
+/*******************************************************************************
+**
+**  onuGponUsrInterfaceCreate
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function create user interface - sys fs
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponUsrInterfaceCreate(void)
+{
+  if (gpon_sysfs_init() != 0)
+	return(MV_ERROR);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponUsrInterfaceRelease
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function release user interface - sys fs
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponUsrInterfaceRelease(void)
+{
+  gpon_sysfs_delete();
+
+  return(MV_OK);
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.h
new file mode 100755
index 0000000..a2c5327
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/gpon/gponOnuLnxKsUI.h
@@ -0,0 +1,105 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuLnxKsUI.h                                           **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON User Interface - SysFs         **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_LINUX_KS_USR_INTERFACE_H

+#define _ONU_GPON_LINUX_KS_USR_INTERFACE_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+ 

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+MV_STATUS onuGponUsrInterfaceCreate(void);

+MV_STATUS onuGponUsrInterfaceRelease(void);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_LINUX_KS_USR_INTERFACE_H */

+

+  

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.c
new file mode 100755
index 0000000..34e3840
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.c
@@ -0,0 +1,529 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : ponOnuLnxKsMI.c                                            **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU PON Management Interface MUX      **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   27 Nov 2011  Konstantin Porotchkin   created                              *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include <linux/version.h>
+#include "ponOnuHeader.h"
+#include "ponOnuLnxKsMI.h"
+#include "eponOnuHeader.h"
+#include "gponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_pon/perf/ponOnuLnxKsMI.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+S_PonModuleCdev  ponDev;
+/*
+static char *drvMode = "epon";
+module_param(drvMode, charp, 0);
+MODULE_PARM_DESC(drvMode, "PON driver mode (epon/gpon)");
+*/
+/* udev class's */
+struct class  *pon_udev_class;
+struct device *pon_udev_dev;
+
+struct fasync_struct *mvPonAsqueue;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+extern int mvGponCdevIoctl(struct inode *inode, struct file  *filp, unsigned int  cmd, unsigned long arg);
+extern int mvEponCdevIoctl(struct inode *inode, struct file  *filp, unsigned int  cmd, unsigned long arg);
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+void onuPonMiNotifyCallback(MV_U32 onuState);
+
+/*******************************************************************************
+**
+**  mvPonMiInit
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: Initialize driver
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0) on success or error
+**
+*******************************************************************************/
+int mvPonMiInit (void)
+{
+	MV_STATUS status = 0;
+
+	status = ponDev.func.ponOnuSetup();
+	if (status != MV_OK) {
+		printk(KERN_INFO "= PON Module setup failed =\n");
+		goto ponInitError;
+	}
+
+	status = ponDev.func.ponOnuSwitchOn();
+	if (status != MV_OK) {
+		printk(KERN_INFO "= PON Module switch ON failed =\n");
+		goto ponInitError;
+	}
+
+	status = ponDev.func.ponOnuOperate();
+	if (status != MV_OK) {
+		printk(KERN_INFO "= PON Module operate failed =\n");
+		goto ponInitError;
+	}
+
+	/* create user interface */
+	status = ponDev.func.userInterfaceCreate();
+	if (status != MV_OK) {
+		printk(KERN_INFO "= PON Module UI creation failed =\n");
+		goto ponInitError;
+	}
+
+	/* register mng notification callback */
+	status = ponDev.func.apiStatusNotifyRegister(onuPonMiNotifyCallback);
+	if (status != MV_OK) {
+		printk(KERN_INFO "= PON Module API status notification callback registration failed =\n");
+		goto ponInitError;
+	}
+
+	/* register link status callback */
+	status = ponDev.func.apiLinkStatusCallbackRegister();
+	if (status != MV_OK) {
+		printk(KERN_INFO "= PON Module link status notification callback registration failed =\n");
+		goto ponInitError;
+	}
+
+	printk(KERN_INFO "= PON Module Init ended successfully =\n");
+
+ponInitError:
+		return(-status);
+}
+
+/*******************************************************************************
+**
+**  mvPonCdevIoctl
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function execute IO commands
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**               unsigned int cmd
+**               unsigned long arg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+int mvPonCdevIoctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	int				ret = -EINVAL;
+	E_PonDriverMode drvMode;
+
+
+	switch (cmd) {
+	/* ====== MVPON_IOCTL_START ======= */
+	case MVPON_IOCTL_START:
+		if (ponDev.drvMode == E_PON_DRIVER_UNDEF_MODE) {
+			/* The driver only alows transition from Undefined to EPON or GPON mode */
+			ret = get_user(drvMode, (E_PonDriverMode __user *)arg);
+			if (ret != 0) {
+				mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+					"ERROR: (%s:%d) copy from user failed\n", __FILE_DESC__, __LINE__);
+				goto ioctlErr;
+			}
+			if (drvMode == E_PON_DRIVER_EPON_MODE) {
+
+				ponDev.func.ponOnuSetup = onuEponSetup;
+				ponDev.func.ponOnuSwitchOn = onuEponSwitchOn;
+				ponDev.func.ponOnuOperate = onuEponOperate;
+				ponDev.func.userInterfaceCreate = onuEponUsrInterfaceCreate;
+				ponDev.func.usrInterfaceRelease = onuEponUsrInterfaceRelease;
+				ponDev.func.rtosResourceRelease = onuEponRtosResourceRelease;
+				ponDev.func.memRelease = 0;
+				ponDev.func.apiStatusNotifyRegister = onuEponApiStatusNotifyRegister;
+				ponDev.func.apiLinkStatusCallbackRegister = onuEponApiLinkStatusCallbackRegister;
+				ponDev.func.cdevIoctl = mvEponCdevIoctl;
+
+			} else if (drvMode == E_PON_DRIVER_GPON_MODE) {
+
+				ponDev.func.ponOnuSetup = onuGponSetup;
+				ponDev.func.ponOnuSwitchOn = onuGponSwitchOn;
+				ponDev.func.ponOnuOperate = onuGponOperate;
+				ponDev.func.userInterfaceCreate = onuGponUsrInterfaceCreate;
+				ponDev.func.usrInterfaceRelease = onuGponUsrInterfaceRelease;
+				ponDev.func.rtosResourceRelease = onuGponRtosResourceRelease;
+				ponDev.func.memRelease = onuPonMemRelease;
+				ponDev.func.apiStatusNotifyRegister = onuGponApiStatusNotifyRegister;
+				ponDev.func.apiLinkStatusCallbackRegister = onuGponApiLinkStatusCallbackRegister;
+				ponDev.func.cdevIoctl = mvGponCdevIoctl;
+
+			} else {
+				mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+					"ERROR: (%s:%d) requested unsupported PON mode 0x%x\n", __FILE_DESC__, __LINE__, arg);
+				goto ioctlErr;
+			}
+
+			ret = mvPonMiInit();
+			if (ret != 0) {
+				mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+					"ERROR: (%s:%d) error switching to %s mode\n",
+					__FILE_DESC__, __LINE__, (drvMode == E_PON_DRIVER_EPON_MODE) ? "EPON" : "GPON");
+				goto ioctlErr;
+			}
+			ponDev.drvMode = drvMode;
+
+		} else {
+			/* Switching between EPON-GPON modes requires reboot initiated by US application */
+			mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+					"ERROR: (%s:%d) command MVPON_IOCTL_INIT is not supported in this mode\n",
+					__FILE_DESC__, __LINE__);
+			goto ioctlErr;
+		}
+		break;
+
+	/* ====== MVPON_IOCTL_MODE_GET ======= */
+	case MVPON_IOCTL_MODE_GET:
+		ret = put_user(ponDev.drvMode, (int __user *)arg);
+		if (ret != 0) {
+			mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,
+				"ERROR: (%s:%d) copy to user failed\n", __FILE_DESC__, __LINE__);
+			goto ioctlErr;
+		}
+		break;
+
+	/* ====== All GPON/EPON-specific IOCTLs ======= */
+	default:
+		if (ponDev.drvMode != E_PON_DRIVER_UNDEF_MODE)
+			ret = ponDev.func.cdevIoctl(inode, filp, cmd, arg);
+		else
+			ret = -EINVAL;
+	}
+
+
+ioctlErr:
+
+	return(ret);
+}
+
+/*******************************************************************************
+**
+**  mvPonCdevFasync
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function execute notification to User space
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**               unsigned int cmd
+**               unsigned long arg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+
+void onuPonMiNotifyCallback(MV_U32 onuState)
+{
+	if (mvPonAsqueue)
+		kill_fasync(&mvPonAsqueue, SIGIO, POLL_IN);
+}
+
+int mvPonCdevFasync(int fd, struct file *filp, int mode)
+{
+	return(fasync_helper(fd, filp, mode, &mvPonAsqueue));
+}
+
+
+/*******************************************************************************
+**
+**  mvEponCdevOpen
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function opens the EPON Char device
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+int mvPonCdevOpen(struct inode *inode, struct file *filp)
+{
+	S_PonModuleCdev *dev;
+
+	/* find the device structure */
+	dev = container_of(inode->i_cdev, S_PonModuleCdev, cdev);
+	dev->devOpen++;
+	filp->private_data = dev;
+
+	return(0);
+}
+
+/*******************************************************************************
+**
+**  mvPonCdevRelease
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function releases the EPON Char device
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+int mvPonCdevRelease(struct inode *inode, struct file *filp)
+{
+	S_PonModuleCdev *dev = filp->private_data;
+
+	dev->devOpen--;
+
+	return(0);
+}
+
+/*******************************************************************************
+**  PON device operations
+*******************************************************************************/
+const struct file_operations ponCdevFops = {
+	.owner   = THIS_MODULE,
+	.open    = mvPonCdevOpen,
+	.release = mvPonCdevRelease,
+	.ioctl   = mvPonCdevIoctl,
+	.fasync  = mvPonCdevFasync
+};
+
+/*******************************************************************************
+**
+**  onuPonMngInterfaceCreate
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function create management interface - char device
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuPonMngInterfaceCreate(void)
+{
+	int   rcode;
+	dev_t dev;
+
+	dev   = MKDEV(MV_PON_MAJOR, 0);
+	rcode = register_chrdev_region(dev, PON_NUM_DEVICES, PON_DEV_NAME);
+	if (rcode < 0) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+				   "ERROR: (%s:%d) Pon Char Device\n", __FILE_DESC__, __LINE__);
+		return(MV_ERROR);
+	}
+
+	cdev_init(&ponDev.cdev, &ponCdevFops);
+	ponDev.cdev.owner = THIS_MODULE;
+	ponDev.drvMode = E_PON_DRIVER_UNDEF_MODE;
+
+	rcode = cdev_add(&ponDev.cdev, dev, 1);
+	if (rcode < 0) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+				   "ERROR: (%s:%d) Pon Char Device Add\n", __FILE_DESC__, __LINE__);
+
+		cdev_del(&ponDev.cdev);
+		unregister_chrdev_region(dev, PON_NUM_DEVICES);
+
+		return(MV_ERROR);
+	}
+
+	/* create device for udev */
+	pon_udev_class = class_create(THIS_MODULE, PON_DEV_NAME);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+	pon_udev_dev   = device_create(pon_udev_class, NULL, dev, PON_DEV_NAME);
+#else
+	pon_udev_dev   = device_create(pon_udev_class, NULL, dev, NULL, PON_DEV_NAME);
+#endif
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuPonMngInterfaceRelease
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function release management interface - char device
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuPonMngInterfaceRelease(void)
+{
+	dev_t dev = MKDEV(MV_PON_MAJOR, 0);
+
+	device_destroy(pon_udev_class, dev);
+	class_unregister(pon_udev_class);
+	class_destroy(pon_udev_class);
+
+	unregister_chrdev_region(dev, PON_NUM_DEVICES);
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuPonModule_init
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Driver INIT function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     0
+**
+*******************************************************************************/
+int __init mvOnuPonModule_init(void)
+{
+	MV_STATUS	status;
+
+	printk(KERN_INFO "= PON Module Init =\n");
+
+	memset(&ponDev, 0, sizeof(ponDev));
+	status = onuPonMngInterfaceCreate();
+	if (status != MV_OK) {
+		printk(KERN_ERR "= PON Module Init FAILED =\n");
+		return(status);
+	}
+
+	printk(KERN_INFO "= PON Module Init ended successfully =\n");
+	return(0);
+}
+
+/*******************************************************************************
+**
+**  mvOnuPonModule_exit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Driver EXIT function
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void __exit mvOnuPonModule_exit(void)
+{
+	printk(KERN_INFO "= PON Module Exit =\n");
+
+	/* release allocated memory */
+	if (ponDev.func.memRelease != 0)
+		ponDev.func.memRelease();
+
+	/* release rtos resources */
+	if (ponDev.func.rtosResourceRelease != 0)
+		ponDev.func.rtosResourceRelease();
+
+	/* release user interface */
+	if (ponDev.func.usrInterfaceRelease != 0)
+		ponDev.func.usrInterfaceRelease();
+
+	/* release mng interface */
+	onuPonMngInterfaceRelease();
+
+	return;
+}
+
+module_init(mvOnuPonModule_init);
+module_exit(mvOnuPonModule_exit);
+
+MODULE_AUTHOR("Konstantin Porotchkin");
+MODULE_DESCRIPTION("United PON Driver for Marvell MV65xxx");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.h
new file mode 100755
index 0000000..620bcb0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/perf/ponOnuLnxKsMI.h
@@ -0,0 +1,132 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : ponOnuLnxKsMI.h                                            **
+**                                                                           **
+**  DESCRIPTION : This file contains ONU PON Management Interface            **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   27 Nov 2011  Konstantin Porotchkin   created                              *
+* =========================================================================== *
+******************************************************************************/
+#ifndef _ONU_PON_LINUX_KS_MNG_INTERFACE_H
+#define _ONU_PON_LINUX_KS_MNG_INTERFACE_H
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "ponOnuHeader.h"
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define MVPON_IOCTL_START         _IOW(MVPON_IOCTL_MAGIC, 30, unsigned int)
+#define MVPON_IOCTL_MODE_GET      _IOR(MVPON_IOCTL_MAGIC, 31, unsigned int)
+
+typedef enum {
+	E_PON_DRIVER_UNDEF_MODE	= 0,
+	E_PON_DRIVER_EPON_MODE	= 1,
+	E_PON_DRIVER_GPON_MODE	= 2,
+	E_PON_DRIVER_MAX_MODE
+} E_PonDriverMode;
+
+typedef struct {
+	MV_STATUS (*ponOnuSetup)(void);
+	MV_STATUS (*ponOnuSwitchOn)(void);
+	MV_STATUS (*ponOnuOperate)(void);
+	MV_STATUS (*userInterfaceCreate)(void);
+	MV_STATUS (*usrInterfaceRelease)(void);
+	MV_STATUS (*rtosResourceRelease)(void);
+	void (*memRelease)(void);
+	MV_STATUS (*apiStatusNotifyRegister)(STATUSNOTIFYFUNC notifyCallBack);
+	MV_STATUS (*apiLinkStatusCallbackRegister)(void);
+	int (*cdevIoctl)(struct inode *, struct file *, unsigned int, unsigned long);
+} S_PonFunctions;
+
+
+typedef struct {
+	E_PonDriverMode		drvMode;
+	int					devOpen;
+	S_PonFunctions		func;
+	struct cdev			cdev;
+} S_PonModuleCdev;
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+MV_STATUS onuPonMngInterfaceCreate(void);
+MV_STATUS onuPonMngInterfaceRelease(void);
+void onuPonMiNotifyCallback(MV_U32 onuState);
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _ONU_PON_LINUX_KS_MNG_INTERFACE_H */
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.c
new file mode 100755
index 0000000..d1d245f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.c
@@ -0,0 +1,479 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : eponOnuBoard.c                                             **

+**                                                                           **

+**  DESCRIPTION : This file implements ONU Board specific                    **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuHeader.h"

+

+/* Local Constant

+------------------------------------------------------------------------------*/                                               

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+

+#ifndef PON_FPGA

+/*******************************************************************************

+**

+**  onuEponSerdesPowerUpSeq

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set serdes

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None    

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponSerdesPowerUpSeq(void)

+{

+  MV_STATUS status;

+  MV_U32    rxReady = 0;

+  MV_U32    txReady = 0;

+  MV_U32    initDone;

+  MV_U32    temp;

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x0, 0);

+  if (status != MV_OK)                                                         

+    return(status);     

+

+  mvOsDelay(10);

+                                                                               

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x0, 0);

+  if (status != MV_OK)                                                         

+    return(status);                                                            

+                                                                              

+  mvOsDelay(10);

+  

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x0, 0);

+  if (status != MV_OK)                                                         

+    return(status);                                                            

+

+  // asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0, &temp, 0);

+  // temp &= ~(0x7);

+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0, temp, 0); 

+  // if (status != MV_OK) 

+  //   return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_GEPON, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_REF_CLK_25M, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x0, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(40);

+

+  asicOntMiscRegRead(mvAsicReg_PON_SERDES_INTERNAL_PASSWORD, &temp, 0);

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PASSWORD, temp | 0x76, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PON_SELECT, 0x3, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x1, 0);

+  // if (status != MV_OK) 

+  //   return(status);

+  // 

+  // mvOsDelay(40);

+  // 

+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x1, 0); 

+  // if (status != MV_OK) 

+  //   return(status);

+  // 

+  // mvOsDelay(10);

+  // 

+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x1, 0);  

+  // if (status != MV_OK) 

+  //   return(status);

+

+  asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0, &temp, 0);

+  temp |= (0x7);

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0, temp, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(20);

+

+  temp = 0;

+  do 

+  {

+	temp++;

+

+	status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_TX, &txReady, 0);  

+    if (status != MV_OK) 

+      return(status);

+

+	mvOsDelay(10);

+

+    status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_RX, &rxReady, 0);  

+    if (status != MV_OK) 

+      return(status);

+

+	if ((temp % 10) == 0) 

+	{

+	  return (MV_FAIL);

+	}

+

+  } while ((txReady == 0) || (rxReady == 0));

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x1, 0);  

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  temp = 0;

+  do 

+  {

+	temp++;

+

+	status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE, &initDone, 0);  

+    if (status != MV_OK) 

+      return(status);

+

+	if ((temp % 10) == 0) 

+	{

+	  return (MV_FAIL);

+	}

+

+	mvOsDelay(10);

+ 

+  } while (initDone == 0);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x0, 0);  

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponSerdesInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function set serdes

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None    

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponSerdesInit(void)

+{

+  MV_STATUS status;

+  MV_U32    loop = 0;

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 

+  if (status != MV_OK) 

+   return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x0, 0); 

+  if (status != MV_OK) 

+   return(status);

+

+  /* Put PON MAC to Reset */

+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  /* Switch to new PON MAC */

+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x1, 0); 

+  if (status != MV_OK) 

+   return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  /* Take PON MAC out of Reset */

+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+

+  /*    EPON configuration of XVR SD is done by LSP code (mvBoardEnvSpec.h, mvCtrlEnvLib.c) */

+

+  /*    EPON configuration/SerDes power up and init sequence   */

+  /* ========================================================= */

+

+  do 

+  {

+	loop++;

+

+	status = onuEponSerdesPowerUpSeq();

+	if      (status == MV_ERROR) return(status);

+	else if (status == MV_OK)    break;

+

+  } while (loop < 10);

+

+  if (loop >= 10) 

+  {

+	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "======================================\n");

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "========= Serdes Not Sync !!! ========\n");

+	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "======================================\n");

+  }

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST_TX_DOUT, 0x0, 0);  

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR, 0x0, 0);  

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 

+  if (status != MV_OK) 

+      return(status);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  mvOsDelay(10);

+

+ // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0); 

+ // if (status != MV_OK) 

+ //   return(status);

+ //

+ // mvOsDelay(10);

+

+  return(MV_OK);

+}

+

+#if 0 /* only for pon mode switch without Reset */

+/*******************************************************************************

+**

+**  onuEponSwitchOver

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function switch between EPON and GPON

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None    

+**

+**  RETURNS:     MV_OK or error

+**

+*******************************************************************************/

+MV_STATUS onuEponSwitchOver(void)

+{

+  MV_STATUS status;

+

+  /* STOP Traffic */

+

+

+  /* Close TX EN */

+  printk("onuPonSwitchOver - Close TX EN\n\r");

+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  /* Put PON MAC to Reset */

+  printk("onuPonSwitchOver - Put PON MAC to Reset\n\r");

+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 

+  if (status != MV_OK) 

+   return(status);

+  

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0); 

+  if (status != MV_OK) 

+    return(status);

+  

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  /* Switch to new PON MAC */

+  printk("onuPonSwitchOver - Switch to new PON MAC - EPON\n\r");

+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  /* Take PON MAC out of Reset */

+  printk("onuPonSwitchOver - Take PON MAC out of Reset\n\r");

+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  /* Re-init Serdes */

+  printk("onuPonSwitchOver - Re-init Serdes\n\r");

+

+  printk("onuPonSwitchOver - Put PON MAC to Reset\n\r");

+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+

+  printk("onuPonSerdeSwitchOverInit - Serdes CLK EN\n\r");

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0); 

+  if (status != MV_OK) 

+      return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  /* Take PON MAC out of Reset */

+  printk("onuPonSwitchOver - Take PON MAC out of Reset\n\r");

+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0); 

+  if (status != MV_OK) 

+	return(status);

+

+  /* Open TX EN */

+  printk("onuPonSwitchOver - Open TX EN\n\r");

+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0); 

+  if (status != MV_OK) 

+    return(status);

+

+  return(MV_OK);

+}

+#endif

+#endif /* PON_FPGA */

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.h
new file mode 100755
index 0000000..46d169c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuBoard.h
@@ -0,0 +1,111 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : eponOnuBoard.h                                             **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON board specific definitions     **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_EPON_BOARD_H

+#define _ONU_EPON_BOARD_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+#ifndef PON_FPGA

+MV_STATUS onuEponSerdesInit(void);

+MV_STATUS onuEponSerdesPowerUpSeq(void);

+#if 0 /* only for pon mode switch without Reset */

+MV_STATUS onuEponSwitchOver(void);

+#endif

+#endif /* PON_FPGA */

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_BOARD_H */

+

+  

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.c
new file mode 100755
index 0000000..f7bbfcf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.c
@@ -0,0 +1,506 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : eponOnuLnxKsOs.c                                           **

+**                                                                           **

+**  DESCRIPTION : This file implements ONU GPON Linux OS handling            **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuHeader.h"

+#include "eponOnuHeader.h"

+#ifndef PON_FPGA

+#include "mvSysPonConfig.h"

+#endif /* PON_FPGA */

+

+/* Local Constant

+------------------------------------------------------------------------------*/     

+#define __FILE_DESC__ "mv_pon/plat/epon/eponOnuLnxKsOs.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+

+/* ========================================================================== */

+/* ===========================  ISR SECTION  ================================ */

+/* ========================================================================== */

+MV_U32 eponCurrentInterruptEvent  = 0;

+MV_U32 eponCurrentInterruptStatus = 0;

+

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+void        onuEponTaskletFunc(unsigned long dummy);

+irqreturn_t onuEponIrqRoutine(int irq, void *arg);

+#ifndef PON_FPGA

+irqreturn_t onuEponDgIrqRoutine(int irq, void *arg);

+#endif /* PON_FPGA */

+

+

+/*******************************************************************************

+**

+**  onuEponRtosResourceInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function allocates onu RTOS resources

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error          

+**                   

+*******************************************************************************/

+MV_STATUS onuEponRtosResourceInit(void)

+{

+  MV_STATUS retcode;

+  MV_U32    idx;

+

+  /* Timer */

+  /* ===== */

+

+  /* onu epon pm timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonPmTimerId),           /* timer Id */

+                              "epon_Pm",                                        /* timer description */

+                              (PTIMER_FUNCPTR)onuEponPmTimerPmHndl,             /* timer function */

+                              0,                                                /* timer function param */

+                              ONU_PON_TIMER_PM_INTERVAL,                        /* init value */ 

+                              1);                                               /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+               "ERROR: (%s:%d) pon PM timer create\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* onu epon Pattern Burst timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonPatternBurstTimerId), /* timer Id */

+                              "epon_PatternBurst",                              /* timer description */

+                              (PTIMER_FUNCPTR)onuPonPatternBurstTimerHndl,      /* timer function */

+                              0,                                                /* timer function param */

+                              ONU_PON_TIMER_NOT_ACTIVE ,                        /* init value */ 

+                              0);                                               /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+               "ERROR: (%s:%d) pon Pattern Burst timer create\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* onu epon mpcp timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonMpcpTimerId),         /* timer Id */

+                              "epon_mpc",                                       /* timer description */

+                              (PTIMER_FUNCPTR)onuEponIsrTimerMpcpHndl,          /* timer function */

+                              ONU_PON_TIMER_NOT_ACTIVE,                         /* timer function param */

+                              ONU_PON_TIMER_MPCP_INTERVAL,                      /* init value */ 

+                              1);                                               /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+               "ERROR: (%s:%d) pon mpcp timer create\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* onu epon Isr miss timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonIsrMissTimerId),      /* timer Id */

+							  "epon_tx",                                        /* timer description */

+							  (PTIMER_FUNCPTR)onuEponIsrTimerEventMissHndl,     /* timer function */

+							  ONU_PON_TIMER_NOT_ACTIVE,                         /* timer function param */

+							  ONU_PON_TIMER_EVENT_MISS_INTERVAL,                /* init value */ 

+							  1);                                               /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+	mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+			   "ERROR: (%s:%d) pon event miss timer create\n\r", __FILE_DESC__, __LINE__);

+	return(MV_ERROR);

+  }

+

+#ifndef PON_FPGA

+  /* onu epon xvr reset timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId),    /* timer Id */

+                               "gpon_xvr",                                      /* timer description */

+                               (PTIMER_FUNCPTR)onuEponIsrXvrResetTimerHndl,     /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                        /* timer active (run) state */

+                               ONU_PON_TIMER_XVR_RST_INTERVAL,                  /* init value */ 

+                               1);                                              /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon Cvr Reset timer create\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+#endif /* PON_FPGA */

+

+  

+   /* onu epon report timer */

+   retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonHwRprtTimerId),     /* timer Id */

+                               "epon_rprt",                                    /* timer description */

+                               (PTIMER_FUNCPTR)onuEponIsrTimerHwReportHndl,    /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                       /* timer function param */

+                               ONU_PON_TIMER_RPRT_INTERVAL,                    /* init value */ 

+                               0);                                             /* periodic value */ 

+   if (retcode != MV_OK)

+   {

+     mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                "ERROR: (%s:%d) pon report timer create\n\r", __FILE_DESC__, __LINE__);

+     return(MV_ERROR);

+   }

+ 

+   /* onu epon tx module timer */

+   retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonHwRprtTxModTimerId),  /* timer Id */

+                               "epon_tx",                                        /* timer description */

+                               (PTIMER_FUNCPTR)onuEponPonMngTimerHwRprtTxModHndl,/* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                         /* timer function param */

+                               ONU_PON_TIMER_TX_MOD_INTERVAL,                    /* init value */ 

+                               1);                                               /* periodic value */ 

+   if (retcode != MV_OK)

+   {

+     mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+                "ERROR: (%s:%d) pon report timer create\n\r", __FILE_DESC__, __LINE__);

+     return(MV_ERROR);

+   }

+  

+

+  /* onu epon holdover timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonHoldoverTimerId),     /* timer Id */

+                              "epon_hold",                                      /* timer description */

+                              (PTIMER_FUNCPTR)onuEponIsrTimerHoldoverHndl,      /* timer function */

+                              ONU_PON_TIMER_NOT_ACTIVE,                         /* timer function param */

+                              ONU_PON_TIMER_HOLDOVER_INTERVAL,                  /* init value */ 

+                              0);                                               /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+               "ERROR: (%s:%d) pon holdover timer create\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* onu epon silence timer */

+  for (idx = 0; idx < EPON_MAX_MAC_NUM; idx++) 

+  {

+	retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonSilenceTimerId[idx]),/* timer Id */

+	  						    "epon_Sile",                                       /* timer description */

+	  						    (PTIMER_FUNCPTR)onuEponPonMngTimerSilenceHndl,     /* timer function */

+	  						    ONU_PON_TIMER_NOT_ACTIVE,                          /* timer function param */

+	  						    ONU_PON_TIMER_SILENCE_INTERVAL,                    /* init value */ 

+	  						    0);                                                /* periodic value */ 

+	if (retcode != MV_OK)

+	{

+	  mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+	  		   "ERROR: (%s:%d) pon holdover timer create\n\r", __FILE_DESC__, __LINE__);

+	  return(MV_ERROR);

+	}

+  }

+

+

+  /* Interrupt */

+  /* ========= */

+  retcode = onuPonIrqInit();

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) epon interrupt init\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  retcode = onuEponIrqTaskletInit(&(onuPonResourceTbl_s.onuPonIrqId));

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) epon interrupt tasklet\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  retcode = onuEponIrqRegister(&(onuPonResourceTbl_s.onuPonIrqId));      

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) epon interrupt register\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponRtosResourceRelease

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function release onu RTOS resources

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error          

+**                   

+*******************************************************************************/

+MV_STATUS onuEponRtosResourceRelease(void)

+{

+  del_timer(&(onuPonResourceTbl_s.onuPonMpcpTimerId.onuPonTimerId));

+  del_timer(&(onuPonResourceTbl_s.onuPonPmTimerId.onuPonTimerId));

+

+  free_irq(onuPonResourceTbl_s.onuPonIrqId.onuPonIrqNum, &(onuPonResourceTbl_s.onuPonIrqId));

+#ifndef PON_FPGA

+  printk("onuPonResourceTbl_s.onuPonIrqId.onuDgIrqNum, &(onuPonResourceTbl_s.onuPonIrqId\n\r");

+  free_irq(onuPonResourceTbl_s.onuPonIrqId.onuDgIrqNum, &(onuPonResourceTbl_s.onuPonIrqId));

+#endif /* PON_FPGA */

+

+  tasklet_kill(&(onuPonResourceTbl_s.onuPonIrqId.onuPonTasklet));

+

+  return(MV_OK);

+}

+

+

+/*******************************************************************************

+**

+**  onuEponIrqTaskletInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: EPON Interrupt tasklet init

+**               

+**  PARAMETERS:  S_onuPonIrq irqId

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     MV_OK

+**

+*******************************************************************************/

+MV_STATUS onuEponIrqTaskletInit(S_onuPonIrq *irqId)

+{

+  tasklet_init(&(irqId->onuPonTasklet), onuEponTaskletFunc, (unsigned int)0);

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponIrqRegister

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: EPON Interrupt register

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     EPON Interrupt number

+**

+*******************************************************************************/

+MV_STATUS onuEponIrqRegister(S_onuPonIrq *irqId)

+{

+  int rcode;

+

+  rcode = request_irq(irqId->onuPonIrqNum, onuEponIrqRoutine, IRQF_DISABLED, "mvEpon", (void*)irqId);

+  if (rcode) 

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) epon interrupt register\n", __FILE_DESC__, __LINE__);

+    free_irq(irqId->onuPonIrqNum, NULL);

+    return(MV_ERROR);

+  }

+

+#ifndef PON_FPGA

+  rcode = request_irq(irqId->onuDgIrqNum, onuEponDgIrqRoutine, IRQF_DISABLED, "mvDyGasp", (void*)irqId);

+  if (rcode) 

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) EPON Dying Gasp interrupt register\n", __FILE_DESC__, __LINE__);

+    free_irq(irqId->onuDgIrqNum, NULL);

+    return(MV_ERROR);

+  }

+#endif /* PON_FPGA */

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuEponIrqRoutine

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: EPON Interrupt routinr

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     IRQ_HANDLED

+**

+*******************************************************************************/

+irqreturn_t onuEponIrqRoutine(int irq, void *arg)

+{

+#ifdef MV_EPON_HW_INTERRUPT

+  onuEponIsrRoutine(0, 0);

+#else /* SW_INTERRUPT - TASKLET */

+  MV_U32 interruptEvent;

+  MV_U32 interruptStatus;

+

+  S_onuPonIrq *irqId = (S_onuPonIrq*)arg;

+  onuEponIsrLowRoutine(&interruptEvent, &interruptStatus);

+  eponCurrentInterruptEvent  = interruptEvent;

+  eponCurrentInterruptStatus = interruptStatus;

+  tasklet_hi_schedule(&(irqId->onuPonTasklet));

+#endif 

+

+  return(IRQ_HANDLED);

+}

+

+#ifndef PON_FPGA

+/*******************************************************************************

+**

+**  onuEponDgIrqRoutine

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: Dying Gasp Interrupt routinr

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     IRQ_HANDLED

+**

+*******************************************************************************/

+irqreturn_t onuEponDgIrqRoutine(int irq, void *arg)

+{

+  mvOnuPonMacDgInterruptDis();

+  onuPonDyingGaspProcess();

+  onuEponDgIsrRoutine();

+

+  return(IRQ_HANDLED);

+}

+#endif /* PON_FPGA */

+

+/*******************************************************************************

+**

+**  onuEponTaskletFunc

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: EPON Interrupt tasklet function

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     GPON Interrupt number

+**

+*******************************************************************************/

+void onuEponTaskletFunc(unsigned long dummy)

+{

+  MV_U32 interruptEvent  = eponCurrentInterruptEvent;  

+  MV_U32 interruptStatus = eponCurrentInterruptStatus; 

+

+  onuPonIrqDisable(&(onuPonResourceTbl_s.onuPonIrqId)); /* disable EPON interrupt */

+

+  onuEponIsrRoutine(interruptEvent, interruptStatus);

+

+  onuPonIrqEnable(&(onuPonResourceTbl_s.onuPonIrqId)); /* enable EPON interrupt */

+}

+

+/*******************************************************************************

+**

+**  onuEponGlbAddrInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: Allocate a memory space for EPON MAC register space

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     IAMBA_OK

+**

+*******************************************************************************/

+MV_STATUS onuEponGlbAddrInit(void)

+{

+#ifndef PON_FPGA

+  /* set base address in the pon onu register table */

+  ponOnuGlbAddrSet((MV_U32)(MV_EPON_MAC_REGS_BASE));

+#else /* PON_FPGA */

+  /* set base address in the pon onu register table */

+  ponOnuGlbAddrSet((MV_U32)(MV_GPON_REG_BASE + 0xC000));

+#endif /* PON_FPGA */

+

+  return (MV_OK);

+}             

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.h
new file mode 100755
index 0000000..a89ba0e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/epon/eponOnuLnxKsOs.h
@@ -0,0 +1,107 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : eponOnuLnxKsOs.c                                           **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Linux OS resources             **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_EPON_LINUX_KS_OS_H

+#define _ONU_EPON_LINUX_KS_OS_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuHeader.h"

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+/* Init API */

+extern MV_STATUS onuEponGlbAddrInit(void);

+extern MV_STATUS onuEponRtosResourceInit(void);

+extern MV_STATUS onuEponRtosResourceRelease(void);

+

+/* Interrupt API */

+extern MV_STATUS onuEponIrqRegister(S_onuPonIrq *irqId); 

+extern MV_STATUS onuEponIrqTaskletInit(S_onuPonIrq *irqId);

+

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_EPON_LINUX_KS_OS_H */

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.c
new file mode 100755
index 0000000..b7be4fc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.c
@@ -0,0 +1,593 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuBoard.c                                             **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU Board specific                    **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "ponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+
+/*******************************************************************************
+**
+**  onuGponDisableSnSetHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function saves disable SN state to non-volatile memory
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponDisableSnSetHandler(MV_BOOL state)
+{
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponDisableSnGetHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function extract disable SN state from non-volatile memory
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponDisableSnGetHandler(MV_BOOL *state)
+{
+  *state = MV_FALSE;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponPasswordHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function extract password from external source
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponPasswordHandler(MV_U8 *password)
+{
+  MV_U8 defaultPassword[10] = ONU_GPON_PASSWORD_DEFAULT;
+
+  memcpy(password, defaultPassword, 10);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponSerialNumberHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function extract serial number from external source
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponSerialNumberHandler(MV_U8 *serialNumber)
+{
+  MV_U8 defaultSerialNumber[8] = ONU_GPON_SN_DEFAULT;
+
+  memcpy(serialNumber, defaultSerialNumber, 8);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponAdminStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure PON Admin state
+**
+**  PARAMETERS:  mode 0-Enable, 1 Disable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuGponAdminStateSet(MV_U32 mode)
+{
+  MV_STATUS status;
+
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, mode, 0);
+  if (status != MV_OK)
+	return(status);
+
+  return(MV_OK);
+}
+
+
+#ifndef PON_FPGA
+/*******************************************************************************
+**
+**  onuGponSerdesPowerUpSeq
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set serdes
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponSerdesPowerUpSeq(void)
+{
+  MV_STATUS status;
+  MV_U32    rxReady = 0;
+  MV_U32    txReady = 0;
+  MV_U32    initDone;
+  MV_U32    temp;
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  // asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0, &temp, 0);
+  // temp &= ~(0x7);
+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0, temp, 0);
+  // if (status != MV_OK)
+  //   return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_GEPON, 0x0, 0);
+ if (status != MV_OK)
+   return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_REF_CLK_25M, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(40);
+
+  asicOntMiscRegRead(mvAsicReg_PON_SERDES_INTERNAL_PASSWORD, &temp, 0);
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PASSWORD, temp | 0x76, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_PON_SELECT, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll, 0x1, 0);
+  // if (status != MV_OK)
+  //   return(status);
+  //
+  // mvOsDelay(40);
+  //
+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX, 0x1, 0);
+  // if (status != MV_OK)
+  //   return(status);
+  //
+  // mvOsDelay(10);
+  //
+  // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX, 0x1, 0);
+  // if (status != MV_OK)
+  //   return(status);
+
+  asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0, &temp, 0);
+  temp |= (0x7);
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0, temp, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(20);
+
+  temp = 0;
+  do
+  {
+	temp++;
+
+	status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_TX, &txReady, 0);
+    if (status != MV_OK)
+      return(status);
+
+	mvOsDelay(10);
+
+    status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_RX, &rxReady, 0);
+    if (status != MV_OK)
+      return(status);
+
+	if ((temp % 10) == 0)
+	{
+	  return (MV_FAIL);
+	}
+
+  } while ((txReady == 0) || (rxReady == 0));
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  temp = 0;
+  do
+  {
+	temp++;
+
+	status  = asicOntMiscRegRead(mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE, &initDone, 0);
+    if (status != MV_OK)
+      return(status);
+
+	if ((temp % 10) == 0)
+	{
+	  return (MV_FAIL);
+	}
+
+	mvOsDelay(10);
+
+  } while (initDone == 0);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuGponSerdesInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set serdes
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponSerdesInit(void)
+{
+  MV_STATUS status;
+  MV_U32    loop = 0;
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0);
+  if (status != MV_OK)
+   return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x0, 0);
+  if (status != MV_OK)
+   return(status);
+
+  /* Put PON MAC to Reset */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  /* Switch to new PON MAC */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_MAC_GPON_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+   return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  /* Take PON MAC out of Reset */
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+
+  /*    GPON  configuration of XVR SD is done by LSP code (mvBoardEnvSpec.h, mvCtrlEnvLib.c) */
+  /* ================================= */
+
+  /*    GPON configuration/SerDes power up and init sequence   */
+  /* ========================================================= */
+
+  do
+  {
+	loop++;
+
+	status = onuGponSerdesPowerUpSeq();
+	if      (status == MV_ERROR) return(status);
+	else if (status == MV_OK)    break;
+
+  } while (loop < 10);
+
+  if (loop >= 10)
+  {
+	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "======================================\n");
+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "========= Serdes Not Sync !!! ========\n");
+	mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "======================================\n");
+  }
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_0_RST_TX_DOUT, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0);
+  if (status != MV_OK)
+      return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  mvOsDelay(10);
+
+ // status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0);
+ // if (status != MV_OK)
+ //   return(status);
+ //
+ // mvOsDelay(10);
+
+  return(MV_OK);
+}
+
+#if 0 /* only for pon mode switch without Reset */
+/*******************************************************************************
+**
+**  onuGponSwitchOver
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function switch between EPON and GPON
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuGponSwitchOver(void)
+{
+  MV_STATUS status;
+
+  /* STOP Traffic */
+
+
+  /* Close TX EN */
+  printk("onuPonSwitchOver - Close TX EN\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  /* Put PON MAC to Reset */
+  printk("onuPonSwitchOver - Put PON MAC to Reset\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0);
+  if (status != MV_OK)
+   return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  /* Switch to new PON MAC */
+  printk("onuPonSwitchOver - Switch to new PON MAC - GPON\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_XPON_CTRL, 0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  /* Take PON MAC out of Reset */
+  printk("onuPonSwitchOver - Take PON MAC out of Reset\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  /* Re-init Serdes */
+  printk("onuPonSwitchOver - Re-init Serdes\n\r");
+
+  printk("onuPonSwitchOver - Put PON MAC to Reset\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+
+  printk("onuPonSerdeSwitchOverInit - Serdes CLK EN\n\r");
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x0, 0);
+  if (status != MV_OK)
+      return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_SEL, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_CLK_EN, 0x1, 0);
+  if (status != MV_OK)
+    return(status);
+
+  /* Take PON MAC out of Reset */
+  printk("onuPonSwitchOver - Take PON MAC out of Reset\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_MAC_SW_RESET_CTRL, 0x1, 0);
+  if (status != MV_OK)
+	return(status);
+
+  /* Open TX EN */
+  printk("onuPonSwitchOver - Open TX EN\n\r");
+  status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, 0x0, 0);
+  if (status != MV_OK)
+    return(status);
+
+  return(MV_OK);
+}
+#endif /* 0 */
+
+#endif /* PON_FPGA */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.h
new file mode 100755
index 0000000..f2bd3c9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuBoard.h
@@ -0,0 +1,117 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : gponOnuBoard.h                                             **
+**                                                                           **
+**  DESCRIPTION : This file contains ONU GPON board specific definitions     **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+#ifndef _ONU_GPON_BOARD_H
+#define _ONU_GPON_BOARD_H
+
+/* Include Files
+------------------------------------------------------------------------------*/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+
+/* Enums
+------------------------------------------------------------------------------*/
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+MV_STATUS onuGponDisableSnSetHandler(MV_BOOL state);
+MV_STATUS onuGponDisableSnGetHandler(MV_BOOL *state);
+MV_STATUS onuGponPasswordHandler(MV_U8 *password);
+MV_STATUS onuGponSerialNumberHandler(MV_U8 *serialNumber);
+MV_STATUS onuGponAdminStateSet(MV_U32 mode);
+
+#ifndef PON_FPGA
+MV_STATUS onuGponSerdesInit(void);
+MV_STATUS onuGponSerdesPowerUpSeq(void);
+#if 0 /* only for pon mode switch without Reset */
+MV_STATUS onuGponSwitchOver(void);
+#endif
+#endif /* PON_FPGA */
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _ONU_GPON_BOARD_H */
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.c
new file mode 100755
index 0000000..25f8155
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.c
@@ -0,0 +1,474 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuLnxKsOs.c                                           **

+**                                                                           **

+**  DESCRIPTION : This file implements ONU GPON Linux OS handling            **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuHeader.h"

+#include "gponOnuHeader.h"

+#ifndef PON_FPGA

+#include "mvSysPonConfig.h"

+#endif /* PON_FPGA */

+

+/* Local Constant

+------------------------------------------------------------------------------*/     

+#define __FILE_DESC__ "mv_pon/plat/gpon/gponOnuLnxKsOs.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+

+/* ========================================================================== */

+/* ===========================  ISR SECTION  ================================ */

+/* ========================================================================== */

+MV_U32 gponCurrentInterruptEvent  = 0;

+MV_U32 gponCurrentInterruptStatus = 0;

+

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+void        onuGponTaskletFunc(unsigned long dummy);

+irqreturn_t onuGponIrqRoutine(int irq, void *arg);

+#ifndef PON_FPGA

+irqreturn_t onuGponDgIrqRoutine(int irq, void *arg);

+#endif /* PON_FPGA */

+

+

+/*******************************************************************************

+**

+**  onuGponRtosResourceInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function allocates onu RTOS resources

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error          

+**                   

+*******************************************************************************/

+MV_STATUS onuGponRtosResourceInit(void)

+{

+  MV_STATUS retcode;

+

+  /* Timer */

+  /* ===== */

+

+  /* onu gpon T01 timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuGponT01_TimerId),   /* timer Id */

+                               "gpon_T01",                                 /* timer description */

+                               (PTIMER_FUNCPTR)onuGponPonMngTimerT01Hndl,  /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                   /* timer active (run) state */

+                               ONU_PON_TIMER_T01_INTERVAL,                 /* init value */ 

+                               0);                                         /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon T01 timer create\n", __FILE_DESC__, __LINE__);

+    return(retcode);

+  }

+

+  /* onu gpon T02 timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuGponT02_TimerId),   /* timer Id */

+                               "gpon_T02",                                 /* timer description */

+                               (PTIMER_FUNCPTR)onuGponPonMngTimerT02Hndl,  /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                   /* timer active (run) state */

+                               ONU_PON_TIMER_T02_INTERVAL,                 /* init value */ 

+                               0);                                         /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon T02 timer create\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* onu gpon PEE timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuGponPeeTimerId),    /* timer Id */

+                               "gpon_Pee",                                 /* timer description */

+                               (PTIMER_FUNCPTR)onuGponPonMngTimerPeeHndl,  /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                   /* timer active (run) state */

+                               ONU_PON_TIMER_PEE_INTERVAL,                 /* init value */ 

+                               0);                                         /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon Pee timer create\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+#ifndef PON_FPGA

+  /* onu gpon xvr reset timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonIsrXvrRstTimerId),    /* timer Id */

+                               "gpon_xvr",                                      /* timer description */

+                               (PTIMER_FUNCPTR)onuGponIsrXvrResetTimerHndl,     /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                        /* timer active (run) state */

+                               ONU_PON_TIMER_XVR_RST_INTERVAL,                  /* init value */ 

+                               1);                                              /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon Cvr Reset timer create\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+#endif /* PON_FPGA */

+

+  /* onu gpon pm timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonPmTimerId),      /* timer Id */

+                               "gpon_Pm",                                  /* timer description */

+                               (PTIMER_FUNCPTR)onuGponPmTimerPmHndl,       /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                   /* timer active (run) state */

+                               ONU_PON_TIMER_PM_INTERVAL,                  /* init value */ 

+                               1);                                         /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon PM timer create\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* onu gpon Pattern Burst timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonPatternBurstTimerId), /* timer Id */

+                              "gpon_PatternBurst",                              /* timer description */

+                              (PTIMER_FUNCPTR)onuPonPatternBurstTimerHndl,      /* timer function */

+                              0,                                                /* timer function param */

+                              ONU_PON_TIMER_NOT_ACTIVE ,                        /* init value */ 

+                              0);                                               /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_API_MODULE,

+               "ERROR: (%s:%d) pon Pattern Burst timer create\n\r", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  /* onu gpon sw fifo timer */

+  retcode = onuPonTimerCreate(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId),  /* timer Id */

+                               "gpon_Fifo",                                /* timer description */

+                               (PTIMER_FUNCPTR)onuGponTimerFifoAuditHndl,  /* timer function */

+                               ONU_PON_TIMER_NOT_ACTIVE,                   /* timer active (run) state */

+                               ONU_PON_TIMER_FIFO_AUDIT_INTERVAL,          /* init value */ 

+                               1);                                         /* periodic value */ 

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) pon FIFO Audit timer create\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+

+  /* Interrupt */

+  /* ========= */

+  retcode = onuPonIrqInit();

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) gpon interrupt init\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  retcode = onuGponIrqTaskletInit(&(onuPonResourceTbl_s.onuPonIrqId));

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) gpon interrupt tasklet\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  retcode = onuGponIrqRegister(&(onuPonResourceTbl_s.onuPonIrqId));      

+  if (retcode != MV_OK)

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) gpon interrupt register\n", __FILE_DESC__, __LINE__);

+    return(MV_ERROR);

+  }

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponRtosResourceRelease

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function release onu RTOS resources

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error          

+**                   

+*******************************************************************************/

+MV_STATUS onuGponRtosResourceRelease(void)

+{

+  del_timer(&(onuPonResourceTbl_s.onuGponT01_TimerId.onuPonTimerId));

+  del_timer(&(onuPonResourceTbl_s.onuGponT02_TimerId.onuPonTimerId));

+  del_timer(&(onuPonResourceTbl_s.onuGponPeeTimerId.onuPonTimerId));

+  del_timer(&(onuPonResourceTbl_s.onuPonSwFIFOTimerId.onuPonTimerId));

+  del_timer(&(onuPonResourceTbl_s.onuPonPmTimerId.onuPonTimerId));

+

+  free_irq(onuPonResourceTbl_s.onuPonIrqId.onuPonIrqNum, &(onuPonResourceTbl_s.onuPonIrqId));

+#ifndef PON_FPGA

+  printk("onuPonResourceTbl_s.onuPonIrqId.onuDgIrqNum, &(onuPonResourceTbl_s.onuPonIrqId\n\r");

+  free_irq(onuPonResourceTbl_s.onuPonIrqId.onuDgIrqNum, &(onuPonResourceTbl_s.onuPonIrqId));

+#endif /* PON_FPGA */

+

+  tasklet_kill(&(onuPonResourceTbl_s.onuPonIrqId.onuPonTasklet));

+

+  return(MV_OK);

+}

+

+

+/*******************************************************************************

+**

+**  onuGponIrqTaskletInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: GPON Interrupt tasklet init

+**               

+**  PARAMETERS:  S_onuPonIrq irqId

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     MV_OK

+**

+*******************************************************************************/

+MV_STATUS onuGponIrqTaskletInit(S_onuPonIrq *irqId)

+{

+  tasklet_init(&(irqId->onuPonTasklet), onuGponTaskletFunc, (unsigned int)0);

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponIrqRegister

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: GPON Interrupt register

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     GPON Interrupt number

+**

+*******************************************************************************/

+MV_STATUS onuGponIrqRegister(S_onuPonIrq *irqId)

+{

+  int rcode;

+

+  rcode = request_irq(irqId->onuPonIrqNum, onuGponIrqRoutine, IRQF_DISABLED, "mvGpon", (void*)irqId);

+  if (rcode) 

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) gpon interrupt register\n", __FILE_DESC__, __LINE__);

+    free_irq(irqId->onuPonIrqNum, NULL);

+    return(MV_ERROR);

+  }

+

+#ifndef PON_FPGA

+  rcode = request_irq(irqId->onuDgIrqNum, onuGponDgIrqRoutine, IRQF_DISABLED, "mvDyGasp", (void*)irqId);

+  if (rcode) 

+  {

+    mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,

+               "ERROR: (%s:%d) GPON Dying Gasp interrupt register\n", __FILE_DESC__, __LINE__);

+    free_irq(irqId->onuDgIrqNum, NULL);

+    return(MV_ERROR);

+  }

+#endif /* PON_FPGA */

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuGponIrqRoutine

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: GPON Interrupt routinr

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     IRQ_HANDLED

+**

+*******************************************************************************/

+irqreturn_t onuGponIrqRoutine(int irq, void *arg)

+{

+#ifdef MV_GPON_HW_INTERRUPT

+  onuGponIsrRoutine(0, 0);

+#else /* SW_INTERRUPT - TASKLET */

+  MV_U32 interruptEvent;

+  MV_U32 interruptStatus;

+

+  S_onuPonIrq *irqId = (S_onuPonIrq*)arg;

+  onuGponIsrLowRoutine(&interruptEvent, &interruptStatus);

+  gponCurrentInterruptEvent  = interruptEvent;

+  gponCurrentInterruptStatus = interruptStatus;

+  tasklet_hi_schedule(&(irqId->onuPonTasklet));

+#endif /* MV_GPON_HW_INTERRUPT */

+

+  return(IRQ_HANDLED);

+}

+

+#ifndef PON_FPGA

+/*******************************************************************************

+**

+**  onuGponDgIrqRoutine

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: Dying Gasp Interrupt routinr

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     IRQ_HANDLED

+**

+*******************************************************************************/

+irqreturn_t onuGponDgIrqRoutine(int irq, void *arg)

+{

+  mvOnuPonMacDgInterruptDis();

+  onuPonDyingGaspProcess();

+  onuGponDgIsrRoutine();

+  

+  return(IRQ_HANDLED);

+}

+#endif /* PON_FPGA */

+

+/*******************************************************************************

+**

+**  onuGponTaskletFunc

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: GPON Interrupt tasklet function

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     GPON Interrupt number

+**

+*******************************************************************************/

+void onuGponTaskletFunc(unsigned long dummy)

+{

+  MV_U32 interruptEvent  = gponCurrentInterruptEvent;  

+  MV_U32 interruptStatus = gponCurrentInterruptStatus; 

+

+  onuPonIrqDisable(&(onuPonResourceTbl_s.onuPonIrqId)); /* disable GPON interrupt */

+

+  onuGponIsrRoutine(interruptEvent, interruptStatus);

+

+  onuPonIrqEnable(&(onuPonResourceTbl_s.onuPonIrqId)); /* enable GPON interrupt */

+}

+

+

+/*******************************************************************************

+**

+**  gponOnuGlbAddrInit

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: Allocate a memory space for GPON MAC register space

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     IAMBA_OK

+**

+*******************************************************************************/

+MV_STATUS onuGponGlbAddrInit(void)

+{

+#ifndef PON_FPGA

+  /* set base address in the pon onu register table */

+  ponOnuGlbAddrSet((MV_U32)(MV_GPON_MAC_REGS_BASE));

+#else /* PON_FPGA */

+  /* set base address in the pon onu register table */

+  ponOnuGlbAddrSet((MV_U32)(MV_GPON_REG_BASE + 0xC000));

+#endif /* PON_FPGA */

+

+  return (MV_OK);

+}             

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.h
new file mode 100755
index 0000000..ca4b7e3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/gpon/gponOnuLnxKsOs.h
@@ -0,0 +1,107 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : gponOnuLnxKsOs.c                                           **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Linux OS resources             **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_LINUX_KS_OS_H

+#define _ONU_GPON_LINUX_KS_OS_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuHeader.h"

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+/* Init API */

+extern MV_STATUS onuGponGlbAddrInit(void);

+extern MV_STATUS onuGponRtosResourceInit(void);

+extern MV_STATUS onuGponRtosResourceRelease(void);

+

+/* Interrupt API */

+extern MV_STATUS onuGponIrqRegister(S_onuPonIrq *irqId); 

+extern MV_STATUS onuGponIrqTaskletInit(S_onuPonIrq *irqId);

+

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_LINUX_KS_OS_H */

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.c
new file mode 100755
index 0000000..153bf20
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.c
@@ -0,0 +1,851 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : ponOnuBoard.c                                              **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU Board specific                    **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "ponOnuHeader.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+MV_U32 ponXvrPolarity;
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+extern spinlock_t onuPonIrqLock;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+MV_STATUS onuPonPatternBurstEnable(bool on);
+
+#ifndef PON_FPGA
+
+MV_U32  time_interval_up   = 0;
+MV_U32  time_interval_down = 0;
+MV_BOOL transmit_up;
+
+/*******************************************************************************
+**
+**  onuPonLedInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init led operation
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuPonLedInit(void)
+{
+	MV_STATUS status;
+	MV_U32    gpioGroup, gpioMask;
+
+	PON_GPIO_GET(BOARD_GPP_SYS_LED, gpioGroup, gpioMask);
+	if (gpioMask != PON_GPIO_NOT_USED) {
+		status = mvGppTypeSet(gpioGroup, gpioMask, 0/*output*/);
+		if (status != MV_OK)
+			return(status);
+	}
+
+	PON_GPIO_GET(BOARD_GPP_PON_LED, gpioGroup, gpioMask);
+	if (gpioMask != PON_GPIO_NOT_USED) {
+		status = mvGppTypeSet(gpioGroup, gpioMask, 0/*output*/);
+		if (status != MV_OK)
+			return(status);
+	}
+
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_LED_BLINK_FREQ_A_ON, 0x30000000, 0);
+	if (status != MV_OK)
+		return(status);
+
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_LED_BLINK_FREQ_A_OFF, 0x30000000, 0);
+	if (status != MV_OK)
+		return(status);
+
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_LED_BLINK_FREQ_B_ON, 0x15000000, 0);
+	if (status != MV_OK)
+		return(status);
+
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_LED_BLINK_FREQ_B_OFF, 0x15000000, 0);
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  onuPonLedHandler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function handles led operation
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS onuPonLedHandler(MV_U32 led, MV_U32 action)
+{
+	MV_STATUS status;
+	MV_U32    gpioGroup = 0;
+	MV_U32    gpioMask = 0;
+
+	if (led == ONU_PON_SYS_LED) {
+
+		PON_GPIO_GET(BOARD_GPP_SYS_LED, gpioGroup, gpioMask);
+		if (gpioMask != PON_GPIO_NOT_USED) {
+			status = mvGppValueSet(gpioGroup, gpioMask, gpioMask);
+			if (status != MV_OK)
+				return(status);
+		}
+
+	} else if (led == ONU_PON_SYNC_LED) {
+
+		PON_GPIO_GET(BOARD_GPP_PON_LED, gpioGroup, gpioMask);
+		if (gpioMask != PON_GPIO_NOT_USED) {
+			switch (action) {
+			case ACTIVE_LED_OFF:
+				status  = mvGppValueSet(gpioGroup, gpioMask, ~gpioMask);
+				if (status != MV_OK)
+					return(status);
+				break;
+
+			case ACTIVE_LED_BLINK_SLOW:
+				status  = mvGppValueSet(gpioGroup, gpioMask, gpioMask);
+				if (status != MV_OK)
+					return(status);
+				status  = mvGppBlinkEn(gpioGroup, gpioMask, gpioMask);
+				if (status != MV_OK)
+					return(status);
+				status  = asicOntMiscRegWrite(mvAsicReg_PON_SYNC_LED_BLINK_FREQ, 0, 0);
+				if (status != MV_OK)
+					return(status);
+				break;
+
+			case ACTIVE_LED_BLINK_FAST:
+				status  = mvGppValueSet(gpioGroup, gpioMask, gpioMask);
+				if (status != MV_OK)
+					return(status);
+				status  = mvGppBlinkEn(gpioGroup, gpioMask, gpioMask);
+				if (status != MV_OK)
+					return(status);
+				status  = asicOntMiscRegWrite(mvAsicReg_PON_SYNC_LED_BLINK_FREQ, 1, 0);
+				if (status != MV_OK)
+					return(status);
+				break;
+
+			case ACTIVE_LED_ON:
+				status  = mvGppValueSet(gpioGroup, gpioMask, gpioMask);
+				if (status != MV_OK)
+					return(status);
+				status  = mvGppBlinkEn(gpioGroup, gpioMask, ~gpioMask);
+				if (status != MV_OK)
+					return(status);
+				break;
+			}
+		}
+	}
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuPonDyingGaspProcess
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function process dying gasp function, kill VoIP
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonDyingGaspProcess(void)
+{
+	MV_STATUS status;
+	MV_U32 boardType;
+
+	/* GPON/EPON configuration of Dying Gasp */
+	/* ===================================== */
+	boardType = mvBoardIdGet();
+
+	switch (boardType) {
+	case RD_88F6510_SFU_ID:
+	case RD_88F6560_GW_ID:
+	case RD_88F6530_MDU_ID:
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_MPP_24, 0, 0); /* power down voip */
+		break;
+	default:
+		status = MV_ERROR;
+	}
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  onuPonDyingGaspExit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function forces system reset after dying gasp
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonDyingGaspExit(void)
+{
+	if (mvBoardIdGet() == DB_88F6535_BP_ID) {
+		mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "\n\n\n");
+		mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "=========================================\n");
+		mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "======= Dying Gasp Detected =============\n");
+		mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "======= System Need To Reboot !!!!! =====\n");
+		mvPonPrint(PON_PRINT_INFO, PON_INIT_MODULE, "=========================================\n");
+	}
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuPonMacBurstEnableInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init Burst Enable MPP
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuPonMacBurstEnableInit(void)
+{
+	MV_U32    gpioGroup, gpioMask;
+	MV_STATUS status = MV_OK;
+
+	if (MV_6601_DEV_ID == mvCtrlModelGet())
+	{
+	       /* PHY control register - output status set */
+	       status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+	       if (status != MV_OK) {
+		       mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				  "ERROR: asicOntMiscRegWrite failed for PON phy ctrl enable - output\n\r");
+		       return(MV_ERROR);
+	       }
+
+	       /* Set SW BEN control for MC tranciever */
+	       status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_HW_SELECT, 1, 0);
+	       if (status != MV_OK) {
+		       mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			"ERROR: asicOntMiscRegWrite failed for PON phy SW ctrl select\n\r");
+		       return(MV_ERROR);
+	       }
+
+	       /* PHY control register - force disable */
+	       status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_FORCE, 0, 0);
+	       if (status != MV_OK) {
+		       mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			     "ERROR: asicOntMiscRegWrite failed for PON phy SW ctrl not force\n\r");
+		       return(MV_ERROR);
+	       }
+	} else if (mvCtrlRevGet() == ONU_ASIC_REV_Z2) {
+
+		/* KW2 ASIC Rev Z2 */
+		/* =============== */
+		PON_GPIO_GET(BOARD_GPP_PON_XVR_TX, gpioGroup, gpioMask);
+		if (gpioMask == PON_GPIO_NOT_USED)
+			return MV_ERROR;
+
+		status = mvGppTypeSet(gpioGroup, gpioMask, ~gpioMask/* 0-output allow transsmit*/);
+
+		if (status == MV_OK)
+			status = mvGppValueSet(gpioGroup, gpioMask, ~gpioMask/*0-disable signal*/);
+		else
+			return(status);
+
+		if (status == MV_OK)
+			status = mvGppTypeSet(gpioGroup, gpioMask, gpioMask /* 0-input NOT allow transsmit*/);
+
+	} else if (mvCtrlRevGet() == ONU_ASIC_REV_A0) {
+
+		/* KW2 ASIC Rev A0 */
+		/* =============== */
+		/* PHY control register - output status set */
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				   "ERROR: asicOntMiscRegWrite failed for PON phy ctrl enable - output\n\r");
+			return(MV_ERROR);
+		}
+
+		/* PHY control register - force disable */
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_EN, 0, 0);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				   "ERROR: asicOntMiscRegWrite failed for PON phy ctrl not force\n\r");
+			return(MV_ERROR);
+		}
+	}
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuPonMacBurstEnablePolarityInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init Burst Enable XVR polarity
+**
+**  PARAMETERS:  MV_U32 polarity
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuPonMacBurstEnablePolarityInit(MV_U32 polarity)
+{
+	ponXvrPolarity = polarity;
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuPonPatternBurstTransmit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function turn on or off actuacl burst transmission
+**
+**  PARAMETERS:  when on  == true  transmission is on
+**               when off == false transmission is off
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonPatternBurstTransmit(MV_BOOL on)
+{
+	MV_STATUS status;
+	MV_U32    gpioGroup, gpioMask;
+	MV_U32    trans_value = 0;
+
+	if (mvCtrlRevGet() == ONU_ASIC_REV_Z2) {
+
+		/* ASIC Rev Z2 */
+		/* =========== */
+		PON_GPIO_GET(BOARD_GPP_PON_XVR_TX, gpioGroup, gpioMask);
+		if (gpioMask == PON_GPIO_NOT_USED)
+			return(MV_ERROR);
+
+		trans_value = (on == MV_TRUE ? ~gpioMask /*0*/: gpioMask /*1*/);
+
+		status = mvGppTypeSet(gpioGroup, gpioMask, trans_value);
+		if (status != MV_OK)
+			return(MV_ERROR);
+
+	} else if (mvCtrlRevGet() == ONU_ASIC_REV_A0) {
+
+		/* ASIC Rev A0 */
+		/* =========== */
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				   "ERROR: asicOntMiscRegWrite failed for PON phy ctrl enable - output\n\r");
+			return(MV_ERROR);
+		}
+	}
+
+	transmit_up = on;
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuPonPatternBurstEnable
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION:
+**
+**  PARAMETERS:  bool on
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonPatternBurstEnable(bool on)
+{
+	MV_STATUS status;
+	MV_U32    gpioGroup, gpioMask;
+	MV_U32    trans_value = 0;
+	MV_U32    polarity;
+
+	if (MV_6601_DEV_ID == mvCtrlModelGet())
+	{
+	       /* PHY control register - force enable */
+	       status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_FORCE, 1, 0);
+	       if (status != MV_OK) {
+		       mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+			     "ERROR: asicOntMiscRegWrite failed for PON phy SW ctrl force\n\r");
+		       return(MV_ERROR);
+	       }
+
+	       /* PHY control register - force enable value - according to polarity */
+	       status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_VALUE, 1, 0);
+	       if (status != MV_OK) {
+		       mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				  "ERROR: asicOntMiscRegWrite failed for PON phy ctrl SW force value %d\n\r",
+				  trans_value);
+		       return(MV_ERROR);
+	       }
+
+	} else if (mvCtrlRevGet() == ONU_ASIC_REV_Z2) {
+
+	    	/* ASIC Rev Z2 */
+	    	/* =========== */
+		PON_GPIO_GET(BOARD_GPP_PON_XVR_TX, gpioGroup, gpioMask);
+		if (gpioMask == PON_GPIO_NOT_USED)
+			return MV_ERROR;
+
+		trans_value = ((on == MV_TRUE) ? (gpioMask/*1*/) : (~gpioMask/*0*/));
+
+		status = mvGppValueSet(gpioGroup, gpioMask, trans_value);
+		if (status != MV_OK)
+			return(MV_ERROR);
+
+	} else if (mvCtrlRevGet() == ONU_ASIC_REV_A0) {
+
+		/* ASIC Rev A0 */
+		/* =========== */
+		/* PHY control register - force enable */
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_EN, 1, 0);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				   "ERROR: asicOntMiscRegWrite failed for PON phy ctrl force\n\r");
+			return(MV_ERROR);
+		}
+
+		polarity = ponXvrPolarity;
+
+		/* XVR polarity */
+		/* XVR polarity == 0, Active High, transmit 1 to the line  */
+		/* XVR polarity == 1, Active Low, transmit 0 to the line  */
+
+		/* P2P mode */
+		/* Force Value == 0, transmit 0 to the line  */
+		/* Force Value == 1, transmit 1 to the line  */
+
+		/* Setting P2P should be reversed from XVR polarity */
+		/* XVR polarity == 0, Active High, write 1 for Force Value */
+		/* XVR polarity == 1, Active Low, write 0 for Force Value */
+
+		trans_value = ((on == MV_TRUE) ? (~polarity) : (polarity));
+
+		/* PHY control register - force enable value - according to polarity */
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL, trans_value, 0);
+		if (status != MV_OK) {
+			mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+				   "ERROR: asicOntMiscRegWrite failed for PON phy ctrl force value %d\n\r",
+				   trans_value);
+			return(MV_ERROR);
+		}
+	}
+
+	transmit_up = on;
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuPonPatternBurstOn
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function start TX transmissions of a selected pattern as periodic or static burst
+**
+**  PARAMETERS:
+**      MV_U32 pattern      0x1     1T
+**                          0x2     2T
+**                          0x80    PRBS - 9
+**                          0x82    PRBS - 15
+**                          0x83    PRBS - 23
+**     MV_BOOL isPeriodic   TX burst can be either static (in this case the following parameters has no effect)
+**                          and this parameter is FALSE OR periodic in this case this parameters is TRUE
+**     MV_U32 period        cycle time - the time in micro seconds between the start of on peak and the other
+**                          (must be greater then the duration interval)
+**     MV_U32 duration      peak time interval in micro seconds  (must be smaller then the duration interval)
+
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonPatternBurstOn(MV_U32 pattern, MV_BOOL isPeriodic, MV_U32 period, MV_U32 duration)
+{
+	MV_STATUS  status;
+
+	/*pattern validation*/
+	if (!((pattern == ONU_PON_TX_PATTERN_TYPE_T1) ||
+	      (pattern == ONU_PON_TX_PATTERN_TYPE_T2) ||
+	      (pattern == ONU_PON_TX_PATTERN_TYPE_PRBS_9) ||
+	      (pattern == ONU_PON_TX_PATTERN_TYPE_PRBS_15) ||
+	      (pattern == ONU_PON_TX_PATTERN_TYPE_PRBS_23))) {
+
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE, "Wrong pattern type value %d \n", pattern);
+		return MV_BAD_VALUE;
+	}
+
+	if ((isPeriodic == MV_TRUE) && (duration >= period)) {
+		mvPonPrint(PON_PRINT_ERROR, PON_INIT_MODULE,
+			   "Period value %d MUST be greater then duration value %d \n", period, duration);
+		return MV_BAD_VALUE;
+	}
+
+	/*in case of sequential call to onuPonPatternBurstOn*/
+	/*stop timer operation and transmissions*/
+	onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonPatternBurstTimerId));
+	onuPonPatternBurstTransmit(MV_TRUE);
+	onuPonPatternBurstEnable(MV_FALSE);
+	time_interval_up     = 0;
+	time_interval_down   = 0;
+
+	if (mvCtrlRevGet() == ONU_ASIC_REV_Z2) {
+
+		/* ASIC Rev Z2 */
+		/* =========== */
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_INPUT, 0);
+		if (status != MV_OK)
+			return(status);
+
+	} else if (mvCtrlRevGet() == ONU_ASIC_REV_A0) {
+
+		/* ASIC Rev A0 */
+		/* =========== */
+		status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+		if (status != MV_OK)
+			return(status);
+	}
+
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING, 0x0, 0);
+	if (status != MV_OK)
+		return(status);
+
+	/*Set system in PHY mode, meaning disconnect the PON MAC*/
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR_15, 0x1, 0);
+	if (status != MV_OK)
+		return(status);
+
+	/*Set sedes power up in phy mode*/
+	status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_POWER_PHY_MODE, 0xfd04,0);
+	if (status != MV_OK)
+		return(status);
+
+	/*set select on pattern*/
+	status  = asicOntMiscRegWrite(mvAsicReg_PT_PATTERN_SELECT, 0x7, 0);
+	if (status != MV_OK)
+		return(status);
+
+	/*set pattern type*/
+	status  = asicOntMiscRegWrite(mvAsicReg_PT_PATTERN_DATA, pattern, 0);
+	if (status != MV_OK)
+		return(status);
+
+	/*turn on selected pattern*/
+	status  = asicOntMiscRegWrite(mvAsicReg_PT_PATTERN_ENABLED, 0x1, 0);
+	if (status != MV_OK)
+		return(status);
+
+
+	onuPonPatternBurstEnable(MV_TRUE);
+	if (isPeriodic == MV_TRUE) {
+		/*periosic burst*/
+		time_interval_up     = duration;
+		time_interval_down   = (period - duration);
+		transmit_up          = MV_TRUE;
+		onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonPatternBurstTimerId),0,time_interval_up,1);
+
+	}
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuPonPatternBurstOff
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function Turn off  pattern burst and reconnect PON MAC
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonPatternBurstOff(void)
+{
+	MV_STATUS  status;
+
+	onuPonPatternBurstTransmit(MV_TRUE);
+	onuPonPatternBurstEnable(MV_FALSE);
+
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING, 0x1, 0);
+	if (status != MV_OK)
+		return(status);
+
+	/*Set system in MAC mode, meaning connect the PON MAC*/
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR_15, 0x0, 0);
+	if (status != MV_OK)
+		return(status);
+
+	/*Set serdes power down in phy mode*/
+	status = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_POWER_PHY_MODE, 0x8d00,0);
+	if (status != MV_OK)
+		return(status);
+
+
+	/* Set the output enable of the GP_BEN IO to Output */
+	status  = asicOntMiscRegWrite(mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN, ONU_PHY_OUTPUT, 0);
+	if (status != MV_OK)
+		return(status);
+
+	/*turn off selected pattern*/
+	status  = asicOntMiscRegWrite(mvAsicReg_PT_PATTERN_ENABLED, 0x0, 0);
+	if (status != MV_OK)
+		return(status);
+
+	/*stop tranmission */
+	status = onuPonPatternBurstTransmit(MV_FALSE);
+	if (status != MV_OK)
+		return(status);
+	/*stop timer operation*/
+	onuPonTimerDisable(&(onuPonResourceTbl_s.onuPonPatternBurstTimerId));
+
+	time_interval_up     = 0;
+	time_interval_down   = 0;
+
+	return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  onuPonPatternBurstTimerHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function is the timer callback when periodic burst is enabled
+**
+**  PARAMETERS:  when on  == true  transmission is on
+**               when off == false transmission is off
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+void      onuPonPatternBurstTimerHndl(void)
+{
+	MV_U32  time_interval;
+	MV_BOOL is_transmit_up;
+	unsigned long flags;
+	MV_STATUS status;
+
+	spin_lock_irqsave(&onuPonIrqLock, flags);
+
+	onuPonResourceTbl_s.onuPonPatternBurstTimerId.onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;
+
+	time_interval  = (transmit_up == MV_TRUE ? time_interval_down : time_interval_up);
+	is_transmit_up = (transmit_up == MV_TRUE ? MV_FALSE : MV_TRUE);
+
+	if (onuPonResourceTbl_s.onuPonPatternBurstTimerId.onuPonTimerPeriodic == 0)
+		onuPonResourceTbl_s.onuPonPatternBurstTimerId.onuPonTimerPeriodic = 1;
+
+	onuPonPatternBurstTransmit(is_transmit_up);
+
+	/*switch on/off selected pattern*/
+	status = asicOntMiscRegWrite(mvAsicReg_PT_PATTERN_ENABLED, is_transmit_up, 0);
+	if (status != MV_OK) {
+		 mvPonPrint(PON_PRINT_ERROR, PON_ISR_MODULE,
+					"ERROR: asicOntMiscRegWrite failed in PON pattern burst timer handler\n\r");
+	 }
+
+	onuPonTimerUpdate(&(onuPonResourceTbl_s.onuPonPatternBurstTimerId),0,time_interval,1);
+
+	spin_unlock_irqrestore(&onuPonIrqLock, flags);
+}
+
+/*******************************************************************************
+**
+**  onuPonTxPowerOn
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function turns ON/OFF TX tranciever power using MPP
+**
+**  PARAMETERS:  MV_BOOL txOn - MV_TRUE - turn TX XVR ON, othervise OFF
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonTxPowerOn(MV_BOOL txOn)
+{
+	MV_U32		gpioGroup, gpioMask;
+	MV_U32		devId = mvCtrlModelGet();
+	MV_STATUS	status = MV_OK;
+
+	PON_GPIO_GET(BOARD_GPP_PON_XVR_TX_POWER, gpioGroup, gpioMask);
+	if (gpioMask != PON_GPIO_NOT_USED) {
+		if (txOn == MV_TRUE)
+			status = mvGppValueSet(gpioGroup, gpioMask, gpioMask);
+		else
+			status = mvGppValueSet(gpioGroup, gpioMask, 0);
+	} else if (devId == MV_6601_DEV_ID)
+		status = MV_ERROR;
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  onuPonTxPowerControlInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function initialyzes TX power control pins
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS onuPonTxPowerControlInit(void)
+{
+	MV_U32		gpioPinNum, gpioGroup, gpioMask;
+	MV_U32		regVal, mppGroup;
+	MV_GPP_HAL_DATA	halData;
+	MV_U32		devId = mvCtrlModelGet();
+	MV_STATUS	status = MV_OK;
+
+	gpioPinNum = mvBoarGpioPinNumGet(BOARD_GPP_PON_XVR_TX_POWER, 0);
+	if (gpioPinNum != MV_ERROR) {
+		mppGroup = mvCtrlMppRegGet(gpioPinNum / 8);
+		/* Set TX power MPP to GPP mode */
+		regVal = MV_REG_READ(mppGroup);
+		regVal &= ~(0xf << ((gpioPinNum % 8) * 4));
+		MV_REG_WRITE(mppGroup, regVal);
+
+		halData.ctrlRev = mvCtrlRevGet();
+
+		status = mvGppInit(&halData);
+		if (status == MV_OK) {
+			/* Set TX power GPP pin direction to OUT */
+			gpioGroup = gpioPinNum / 32;
+			gpioMask = 1 << gpioPinNum;
+			status = mvGppTypeSet(gpioGroup, gpioMask, (MV_GPP_OUT & gpioMask));
+		}
+
+	} else if (devId == MV_6601_DEV_ID)
+		status = MV_ERROR;
+
+	return(status);
+}
+
+#endif /* PON_FPGA */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.h
new file mode 100755
index 0000000..1231b55
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuBoard.h
@@ -0,0 +1,158 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : ponOnuBoard.h                                              **
+**                                                                           **
+**  DESCRIPTION : This file contains ONU GPON board specific definitions     **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   29Oct06  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+#ifndef _ONU_PON_BOARD_H
+#define _ONU_PON_BOARD_H
+
+/* Include Files
+------------------------------------------------------------------------------*/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define PON_NUM_DEVICES     (1)
+#define PON_DEV_NAME        ("pon")
+#define MVPON_IOCTL_MAGIC   ('P')
+
+#define DB_88F65xx_XVR_SD (0x6)
+#define RD_88F65xx_XVR_SD (0x5)
+
+#define DB_88F65xx_DG     (0x3)
+#define RD_88F65xx_DG     (0x4)
+
+#define ONU_PON_TX_PATTERN_TYPE_T1        (0x1)
+#define ONU_PON_TX_PATTERN_TYPE_T2        (0x2)
+#define ONU_PON_TX_PATTERN_TYPE_PRBS_9    (0x80)
+#define ONU_PON_TX_PATTERN_TYPE_PRBS_15   (0x82)
+#define ONU_PON_TX_PATTERN_TYPE_PRBS_23   (0x83)
+
+#define ONU_PON_XVR_POLARITY_ACT_HIGH     (0x1)
+#define ONU_PON_XVR_POLARITY_ACT_LOW      (0x0)
+
+#define ONU_XVR_GPIO_OUTPUT               (0x0)
+#define ONU_XVR_GPIO_INPUT                (0x1)
+
+#define ONU_PHY_OUTPUT                    (0x0)
+#define ONU_PHY_INPUT                     (0x1)
+
+#define ONU_ASIC_REV_Z2                   (0x1)
+#define ONU_ASIC_REV_A0                   (0x2)
+
+/* Enums
+------------------------------------------------------------------------------*/
+typedef enum
+{
+  ONU_PON_SYS_LED       = 0,
+  ONU_PON_SYNC_LED      = 1
+}E_OnuPonLedTypes;
+
+typedef enum
+{
+  ACTIVE_LED_OFF        = 0,
+  ACTIVE_LED_BLINK_SLOW = 1,
+  ACTIVE_LED_BLINK_FAST = 2,
+  ACTIVE_LED_ON         = 3
+}E_OnuPonLedActivation;
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+#ifndef PON_FPGA
+MV_STATUS onuPonLedInit(void);
+MV_STATUS onuPonLedHandler(MV_U32 led, MV_U32 action);
+MV_STATUS onuPonDyingGaspProcess(void);
+MV_STATUS onuPonDyingGaspExit(void);
+MV_STATUS mvOnuPonMacBurstEnableInit(void);
+MV_STATUS mvOnuPonMacBurstEnablePolarityInit(MV_U32 polarity);
+MV_STATUS onuPonPatternBurstOn(MV_U32 pattern, MV_BOOL isPeriodic, MV_U32 period, MV_U32 duration);
+MV_STATUS onuPonPatternBurstOff(void);
+void      onuPonPatternBurstTimerHndl(void);
+MV_STATUS onuPonTxPowerOn(MV_BOOL txOn);
+MV_STATUS onuPonTxPowerControlInit(void);
+
+#endif /* PON_FPGA */
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _ONU_PON_BOARD_H */
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuHeader.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuHeader.h
new file mode 100755
index 0000000..6dc928d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuHeader.h
@@ -0,0 +1,118 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************/

+/**                                                                          **/

+/**  MODULE      : ONU EPON                                                  **/

+/**                                                                          **/

+/**  FILE        : ponOnuHeader.h                                            **/

+/**                                                                          **/

+/**  DESCRIPTION : This file pon module header files                         **/

+/**                                                                          **/ 

+/******************************************************************************

+ *                                                                            *

+ *  MODIFICATION HISTORY:                                                     *

+ *                                                                            *

+ *   26Jan10  oren_ben_hayun    created                                       *  

+ * ========================================================================== * 

+ *                                                                            *

+ ******************************************************************************/

+

+#ifndef _ONU_PON_HEADER_H 

+#define _ONU_PON_HEADER_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "mvCommon.h"

+#include "boardEnv/mvBoardEnvLib.h"

+#include "boardEnv/mvBoardEnvSpec.h"

+#include "pon/mvPonOnuRegs.h"

+#include "mvPonOnuDefines.h"

+#include "mvPonOnuRegs.h"

+#include "mvPonOnuMac.h"

+#include "ponOnuBoard.h"

+#include "ponOnuLnxKsOs.h"

+#include "gpp/mvGpp.h"

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums 

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+extern MV_STATUS ponOnuGlbAddrSet(MV_U32 address);

+

+/* Macros

+------------------------------------------------------------------------------*/

+

+#endif /* _ONU_PON_HEADER_H */

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.c
new file mode 100755
index 0000000..0361301
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.c
@@ -0,0 +1,624 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : ponOnuLnxKsOs.c                                            **

+**                                                                           **

+**  DESCRIPTION : This file implements ONU GPON Linux OS handling            **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuLnxKsOs.h"

+#ifndef PON_FPGA

+#include "mvSysPonConfig.h"

+#endif /* PON_FPGA */

+

+/* Local Constant

+------------------------------------------------------------------------------*/     

+#define __FILE_DESC__ "mv_pon/plat/ponOnuLnxKsOs.c"

+

+/* Global Variables

+------------------------------------------------------------------------------*/

+S_OnuPonResourceTbl onuPonResourceTbl_s;

+

+S_PonModulePrint gponModulePrint_s[PON_LAST_MODULE + 1] =      

+{                                                      

+                           {0,0},                                 

+  /* PON_MAC_MODULE   */  {PON_PRINT_INFO, 0}, /* No Options */                                

+  /* PON_INIT_MODULE  */  {PON_PRINT_INFO, 0}, /* No Options */                                

+  /* PON_ISR_MODULE   */  {PON_PRINT_INFO, 0}, /* No Options */                           

+  /* PON_CLI_MODULE   */  {PON_PRINT_INFO, 0}, /* No Options */                           

+  /* PON_MNG_MODULE   */  {PON_PRINT_INFO, 0}, /* No Options */                           

+  /* PON_SM_MODULE    */  {PON_PRINT_INFO, 0}, /* No Options */                           

+  /* PON_PM_MODULE    */  {PON_PRINT_INFO, 0}, /* No Options */                           

+  /* PON_ALARM_MODULE */  {PON_PRINT_INFO, 0}, /* No Options */                           

+  /* PON_BER_MODULE   */  {PON_PRINT_INFO, 0}, /* No Options */                           

+  /* PON_API_MODULE   */  {PON_PRINT_INFO, 0}, /* No Options */                               

+  /* PON_ALLOC_MODULE */  {PON_PRINT_INFO, 0}  /* No Options */                                

+};

+

+/* Global functions

+------------------------------------------------------------------------------*/

+spinlock_t onuPonIrqLock;

+

+/* Local Variables

+------------------------------------------------------------------------------*/

+

+/* ========================================================================== */

+/* ===========================  MEMORY SECTION  ============================= */

+/* ========================================================================== */

+void*  onuPonMemoryAllocArray[128];

+MV_U32 onuPonMemoryAllocIndex = 0;

+

+/* Export Functions

+------------------------------------------------------------------------------*/

+

+/* Local Functions

+------------------------------------------------------------------------------*/

+

+/*******************************************************************************

+**

+**  onuPonIrqInit

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION: The function inits PON interrupts

+**               

+**  PARAMETERS:  None

+**

+**  OUTPUTS:     None

+**

+**  RETURNS:     MV_OK or error          

+**                   

+*******************************************************************************/

+MV_STATUS onuPonIrqInit(void)

+{

+

+  /* Interrupt */

+  /* ========= */

+  onuPonIrqNumInit();

+

+  spin_lock_init(&onuPonIrqLock);

+

+  return(MV_OK);

+}

+

+/* ========================================================================== */

+/* ===========================  TIMER SECTION  ============================== */

+/* ========================================================================== */

+

+/*******************************************************************************

+**

+**  onuPonTimerCreate

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION:   The function  

+**                 

+**  PARAMETERS:       

+**

+**  OUTPUTS:       None    

+**

+**  RETURNS:       

+**

+*******************************************************************************/

+MV_STATUS onuPonTimerCreate(S_OnuPonTimer  *timerId, 

+                            MV_U8          *timerDesc, 

+                            PTIMER_FUNCPTR  timerFunc, 

+                            MV_U32          timerParam, 

+                            MV_U32          timerInterval, 

+                            MV_U32          timerPeriodic)

+{

+  memset(&(timerId->onuPonTimerId), 0, sizeof(struct timer_list));

+  timerId->onuPonTimerId.function = timerFunc;

+  timerId->onuPonTimerId.data     = (-1);

+

+  timerId->onuPonTimerInterval    = timerInterval; 

+  timerId->onuPonTimerPeriodic    = timerPeriodic;

+  init_timer(&(timerId->onuPonTimerId));

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  onuPonTimerUpdate

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION:   The function  

+**                 

+**  PARAMETERS:       

+**

+**  OUTPUTS:       None    

+**

+**  RETURNS:       

+**

+*******************************************************************************/

+int onuPonTimerUpdate(S_OnuPonTimer *timerId, MV_U32 data, MV_U32 interval, MV_U32 state)

+{

+  onuPonTimerDisable(timerId);

+  timerId->onuPonTimerId.data  = data;

+  timerId->onuPonTimerInterval = interval;

+  if (state != 0)

+	onuPonTimerEnable(timerId);

+

+  return (0);

+}

+

+/*******************************************************************************

+**

+**  onuPonTimerEnable

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION:   The function  

+**                 

+**  PARAMETERS:       

+**

+**  OUTPUTS:       None    

+**

+**  RETURNS:       

+**

+*******************************************************************************/

+int onuPonTimerEnable(S_OnuPonTimer *timerId)

+{

+  if (timerId->onuPonTimerActive != ONU_PON_TIMER_ACTIVE) 

+  {

+    del_timer(&(timerId->onuPonTimerId));

+    timerId->onuPonTimerId.expires = jiffies + (((timerId->onuPonTimerInterval) * HZ) / 1000); /* ms */

+    add_timer(&(timerId->onuPonTimerId));

+    timerId->onuPonTimerActive = ONU_PON_TIMER_ACTIVE;

+  }

+

+  return (0);

+}

+

+/*******************************************************************************

+**

+**  onuPonTimerDisable

+**  ____________________________________________________________________________

+** 

+**  DESCRIPTION:   The function  

+**                 

+**  PARAMETERS:       

+**

+**  OUTPUTS:       None    

+**

+**  RETURNS:       

+**

+*******************************************************************************/

+int onuPonTimerDisable(S_OnuPonTimer *timerId)

+{

+  if (timerId->onuPonTimerActive != ONU_PON_TIMER_NOT_ACTIVE) 

+  {

+    del_timer(&(timerId->onuPonTimerId));

+    timerId->onuPonTimerActive = ONU_PON_TIMER_NOT_ACTIVE;

+  }

+

+  return (0);

+}

+

+

+/* ========================================================================== */

+/* ===========================  ISR SECTION  ================================ */

+/* ========================================================================== */

+

+/*******************************************************************************

+**

+**  onuPonIrqNumGet

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: GPON Interrupt number get

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     GPON Interrupt number

+**

+*******************************************************************************/

+MV_STATUS onuPonIrqNumInit(void)

+{

+#ifdef PON_FPGA

+   onuPonResourceTbl_s.onuPonIrqId.onuPonIrqNum = 76/*GPON_MAC_IRQ_NUM*/; 

+#else

+   onuPonResourceTbl_s.onuPonIrqId.onuPonIrqNum = GPON_MAC_IRQ_NUM; 

+#endif /* PON_FPGA */

+#ifndef PON_FPGA

+   onuPonResourceTbl_s.onuPonIrqId.onuDgIrqNum  = DYNGASP_IRQ_NUM; 

+#endif /* PON_FPGA */

+

+   return(MV_OK);

+}

+

+/*******************************************************************************

+**  onuPonIrqEnable

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: GPON Interrupt enable

+**               

+**  PARAMETERS:  S_onuPonIrq irqId

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     MV_OK

+**

+*******************************************************************************/

+int onuPonIrqEnable(S_onuPonIrq *irqId)

+{

+  enable_irq(irqId->onuPonIrqNum);

+

+  return(0);

+}

+

+/*******************************************************************************

+**

+**  onuPonIrqDisable

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: GPON Interrupt disable

+**               

+**  PARAMETERS:  S_onuPonIrq irqId

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     MV_OK

+**

+*******************************************************************************/

+int onuPonIrqDisable(S_onuPonIrq *irqId)

+{

+  disable_irq(irqId->onuPonIrqNum);

+

+  return(0);

+}

+

+/* ========================================================================== */

+/* ===========================  MEMORY SECTION  ============================= */

+/* ========================================================================== */

+

+

+/*******************************************************************************

+**

+**  onuPonMemAlloc

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: Allocate a memory space for GPON MAC

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     IAMBA_OK

+**

+*******************************************************************************/

+void* onuPonMemAlloc(unsigned int size) 

+{

+  void* memoryAlloc = kmalloc(size, GFP_KERNEL);

+

+  onuPonMemoryAllocArray[onuPonMemoryAllocIndex] = memoryAlloc;

+  onuPonMemoryAllocIndex++;

+

+  return(memoryAlloc);

+}

+

+/*******************************************************************************

+**

+**  onuPonMemRelease

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: release all allocated memory for GPON module

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     IAMBA_OK

+**

+*******************************************************************************/

+void onuPonMemRelease(void) 

+{

+  MV_U32 index;

+

+  for (index = 0; index < onuPonMemoryAllocIndex; index++) 

+    kfree(onuPonMemoryAllocArray[index]);

+}

+

+/* ========================================================================== */

+/* ===========================  PRINT SECTION  ============================== */

+/* ========================================================================== */

+

+/*******************************************************************************

+**

+**  mvPonPrint

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: GPON print function

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     MV_OK

+**

+*******************************************************************************/

+MV_STATUS mvPonPrint(MV_U32 level, MV_U32 bitMask, const char *format, ...)

+{

+  MV_STATUS rcode;

+  char      buf[256];

+  va_list   argptr;

+

+  /* check module printing status */

+  rcode = ponOnuCheckPrintStatus(level, bitMask);

+  if (rcode != MV_OK) 

+    return(MV_OK); 

+

+  /* build message */

+  va_start(argptr, format);

+  vsnprintf(buf, sizeof(buf), format, argptr);

+  va_end(argptr);     

+

+  /* print message */

+  switch (level) 

+  {

+    case PON_PRINT_ERROR:

+      printk(KERN_ERR "%s", buf);

+      break;

+    case PON_PRINT_INFO:

+      printk(KERN_INFO "%s", buf);

+      break;

+    case PON_PRINT_DEBUG:

+    default:

+      printk(KERN_DEBUG "%s", buf);

+      break;

+  }

+

+  return(MV_OK); 

+}

+

+/*******************************************************************************

+**

+**  ponOnuCheckPrintStatus

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: Check module printing status

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     MV_OK / MV_ERROR

+**

+*******************************************************************************/

+MV_STATUS ponOnuCheckPrintStatus(MV_U32 printLevel, 

+                                  MV_U32 moduleOptions)

+{

+  MV_U32  module;

+  MV_U32  options;

+  MV_U32  modulePrintLevel;

+  MV_U32  modulePrintOptions;

+  MV_BOOL printLevelInd;

+  MV_BOOL printOptionsInd;

+

+  /* input params */

+  module             =  moduleOptions        & MODULE_MASK;

+  options            = (moduleOptions >> 16) & OPTIONS_MASK;

+

+  /* current module params */

+  modulePrintLevel   = gponModulePrint_s[module].modulePrintLevel;

+  modulePrintOptions = gponModulePrint_s[module].moduleOptions;

+

+  /* check print level */

+  if (printLevel <= modulePrintLevel) printLevelInd = MV_TRUE;

+  else                                printLevelInd = MV_FALSE;

+

+  /* check module options */

+  if (options == 0) printOptionsInd = MV_TRUE; /* no options */

+  else

+  {

+    if (options & modulePrintOptions) printOptionsInd = MV_TRUE;

+    else                              printOptionsInd = MV_FALSE; 

+  }

+

+  if((printLevelInd == MV_TRUE) && (printOptionsInd == MV_TRUE)) return(MV_OK);

+  else                                                             return(MV_ERROR);

+}

+

+/*******************************************************************************

+**

+**  ponOnuChangePrintStatus

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: Change module printing status

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     MV_OK / MV_ERROR

+**

+*******************************************************************************/

+MV_STATUS ponOnuChangePrintStatus(MV_U32 module, 

+                                   MV_U32 printLevel, 

+                                   MV_U32 moduleOptions)

+{

+  gponModulePrint_s[module].modulePrintLevel = printLevel;

+  gponModulePrint_s[module].moduleOptions    = moduleOptions;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  ponOnuGetPrintStatus

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: Change module printing status

+**               

+**  PARAMETERS:  none

+** 

+**  OUTPUTS:     none

+**                               

+**  RETURNS:     MV_OK / MV_ERROR

+**

+*******************************************************************************/

+MV_STATUS ponOnuGetPrintStatus(MV_U32 module, 

+                                MV_U32 *printLevel, 

+                                MV_U32 *moduleOptions)

+{

+  *printLevel    = gponModulePrint_s[module].modulePrintLevel;

+  *moduleOptions = gponModulePrint_s[module].moduleOptions;

+

+  return(MV_OK);

+}

+

+/*******************************************************************************

+**

+**  ponOnuPrintStatus

+**  ____________________________________________________________________________

+**

+**  DESCRIPTION: print modules printing status

+**               

+**  PARAMETERS:  char* buf

+** 

+**  OUTPUTS:     char* buf

+**                               

+**  RETURNS:     message length

+**

+*******************************************************************************/

+int ponOnuPrintStatus(char* buf)

+{

+  MV_U32 index;

+  MV_U32 printLevel;   

+  MV_U32 moduleOptions;

+

+  char* moduleDesc[PON_LAST_MODULE + 1] = 

+  {

+    "", 

+    "MAC   -  1            ", 

+    "INIT  -  2            ", 

+    "ISR   -  3            ", 

+    "CLI   -  4            ", 

+    "MNG   -  5            ", 

+    "SM    -  6 (GPON Only)", 

+    "PM    -  7 (GPON Only)", 

+    "ALARM -  8            ", 

+    "BER   -  9 (GPON Only)", 

+    "API   - 10            ", 

+    "ALLOC - 11 (GPON Only)"

+  };

+

+  char* printLevelDesc[4] = 

+  {

+    "", 

+    "ERROR", 

+    "INFO", 

+    "DEBUG" 

+  };

+

+  int off = 0;

+

+  off += mvOsSPrintf(buf+off, "Module                  Print Level  Options\n");

+  for (index = 0; index < PON_LAST_MODULE; index++) 

+  {

+    ponOnuGetPrintStatus(index, &printLevel, &moduleOptions);

+    off += mvOsSPrintf(buf+off, "%22s  %11s   0x%08x\n", moduleDesc[index], printLevelDesc[printLevel], moduleOptions);

+  }

+

+  off += mvOsSPrintf(buf+off, "\n");

+  off += mvOsSPrintf(buf+off, "GPON              | EPON\n");

+  off += mvOsSPrintf(buf+off, "==================+====================\n");

+  off += mvOsSPrintf(buf+off, "SM Module Options | ISR Module Options\n"); 

+  off += mvOsSPrintf(buf+off, "DEBUG    - 0x0001 | INT      - 0x0001\n");  

+  off += mvOsSPrintf(buf+off, "STATE    - 0x0002 | MISS     - 0x0002\n");  

+  off += mvOsSPrintf(buf+off, "AES      - 0x0004 | STATE    - 0x0004\n");  

+  off += mvOsSPrintf(buf+off, "ALLOC    - 0x0008 | RAND     - 0x0008\n");  

+  off += mvOsSPrintf(buf+off, "OMCC     - 0x0010 | \n");                   

+  off += mvOsSPrintf(buf+off, "TIMER    - 0x0020 | MNG Module Options\n"); 

+  off += mvOsSPrintf(buf+off, "ALARM    - 0x0040 | DBA      - 0x0001\n");  

+  off += mvOsSPrintf(buf+off, "                  | SILENCE  - 0x0002\n");  

+  off += mvOsSPrintf(buf+off, "                  | MAC ADDR - 0x0004\n");  

+  off += mvOsSPrintf(buf+off, "                  | OAM TX   - 0x0008\n");  

+  off += mvOsSPrintf(buf+off, "                  | DBA WA   - 0x0010\n");  

+  off += mvOsSPrintf(buf+off, "                  | DBA FEC  - 0x0020\n");  

+  off += mvOsSPrintf(buf+off, "                  | DBA TS   - 0x0040\n");  

+  off += mvOsSPrintf(buf+off, "==================+====================\n");

+  off += mvOsSPrintf(buf+off, "GPON Print Levels\n");

+  off += mvOsSPrintf(buf+off, "ERROR    - 1\n");

+  off += mvOsSPrintf(buf+off, "INFO     - 2\n");

+  off += mvOsSPrintf(buf+off, "DEBUG    - 3\n");

+  off += mvOsSPrintf(buf+off, "\n");

+  off += mvOsSPrintf(buf+off, "Kernel Print Levels\n");

+  off += mvOsSPrintf(buf+off, "KERN_ERR   - 4\n");

+  off += mvOsSPrintf(buf+off, "KERN_INFO  - 7\n");

+  off += mvOsSPrintf(buf+off, "KERN_DEBUG - 8\n");

+  off += mvOsSPrintf(buf+off, "Change Kernel Print Level >> dmesg -n[level]\n");

+  off += mvOsSPrintf(buf+off, "\n");

+

+  return(off);

+}

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.h
new file mode 100755
index 0000000..a1e3869
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuLnxKsOs.h
@@ -0,0 +1,304 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : ponOnuLnxKsOs.c                                            **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Linux OS resources             **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_PON_LINUX_KS_OS_H

+#define _ONU_PON_LINUX_KS_OS_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include <linux/kernel.h>

+#include <linux/module.h>

+#include <linux/init.h>

+#include <linux/string.h>

+#include <linux/spinlock.h>

+#include <linux/interrupt.h>

+#include <linux/sched.h>

+#include <linux/wait.h>

+#include <linux/time.h>

+#include <linux/timer.h> 

+#include <linux/slab.h>

+#include <linux/byteorder/generic.h>

+#include <linux/random.h>

+#include <linux/delay.h>

+#include <linux/types.h>

+#include <linux/capability.h>

+#include <linux/platform_device.h>

+#include <linux/cdev.h>

+#include <linux/fs.h>

+#include <linux/ioctl.h>

+

+#include "mvTypes.h"

+#include "mvCommon.h"

+#include "mvOs.h"

+#include "ctrlEnv/mvCtrlEnvSpec.h"

+#include "boardEnv/mvBoardEnvLib.h"

+#include "mv_netdev.h"

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Printing Definitions */

+#define PON_PRINT_ERROR           (1)                                                                                   

+#define PON_PRINT_INFO            (2)

+#define PON_PRINT_DEBUG           (3)

+                                  

+#define MODULE_SHIFT              (16)

+#define MODULE_MASK               (0x001F)

+#define OPTIONS_MASK              (0xFFFF)

+                                  

+#define ONU_PON_SM_DEBUG_ATTR     (0x0001)                              

+#define ONU_PON_SM_STATE_ATTR     (0x0002)

+#define ONU_PON_SM_AES_ATTR       (0x0004)

+#define ONU_PON_SM_ALLOC_ATTR     (0x0008)

+#define ONU_PON_SM_OMCC_ATTR      (0x0010)

+#define ONU_PON_SM_TIMER_ATTR     (0x0020)

+#define ONU_PON_SM_ALARM_ATTR     (0x0040)

+

+#define ONU_PON_MNG_DBA_ATTR      (0x0001)   

+#define ONU_PON_MNG_SILENCE_ATTR  (0x0002)   

+#define ONU_PON_MNG_MAC_ADDR_ATTR (0x0004)   

+#define ONU_PON_MNG_OAM_TX_ATTR   (0x0008)   

+#define ONU_PON_MNG_DBA_WA_ATTR   (0x0010)   

+#define ONU_PON_MNG_DBA_FEC_ATTR  (0x0020)   

+#define ONU_PON_MNG_DBA_TS_ATTR   (0x0040)   

+

+#define ONU_PON_ISR_INT_ATTR      (0x0001)

+#define ONU_PON_ISR_MISS_ATTR     (0x0002)

+#define ONU_PON_ISR_STATE_ATTR    (0x0004)

+#define ONU_PON_ISR_RAND_ATTR     (0x0008)

+

+#define PON_MAC_MODULE            (1)      

+#define PON_INIT_MODULE           (2)     

+#define PON_ISR_MODULE            (3)      

+#define PON_ISR_INT_MODULE        (3 | (ONU_PON_ISR_INT_ATTR   << MODULE_SHIFT))      

+#define PON_ISR_MISS_MODULE       (3 | (ONU_PON_ISR_MISS_ATTR  << MODULE_SHIFT))      

+#define PON_ISR_STATE_MODULE      (3 | (ONU_PON_ISR_STATE_ATTR << MODULE_SHIFT))      

+#define PON_ISR_RAND_MODULE       (3 | (ONU_PON_ISR_RAND_ATTR  << MODULE_SHIFT))      

+#define PON_CLI_MODULE            (4)      

+#define PON_MNG_MODULE            (5) 

+#define PON_MNG_DBA_MODULE        (5 | (ONU_PON_MNG_DBA_ATTR      << MODULE_SHIFT)) 

+#define PON_MNG_SILENCE_MODULE    (5 | (ONU_PON_MNG_SILENCE_ATTR  << MODULE_SHIFT)) 

+#define PON_MNG_MAC_ADDR_MODULE   (5 | (ONU_PON_MNG_MAC_ADDR_ATTR << MODULE_SHIFT)) 

+#define PON_MNG_OAM_TX_MODULE     (5 | (ONU_PON_MNG_OAM_TX_ATTR   << MODULE_SHIFT)) 

+#define PON_MNG_DBA_WA_MODULE     (5 | (ONU_PON_MNG_DBA_WA_ATTR   << MODULE_SHIFT)) 

+#define PON_MNG_DBA_FEC_MODULE    (5 | (ONU_PON_MNG_DBA_FEC_ATTR  << MODULE_SHIFT)) 

+#define PON_MNG_DBA_TS_MODULE     (5 | (ONU_PON_MNG_DBA_TS_ATTR   << MODULE_SHIFT)) 

+#define PON_SM_MODULE             (6)

+#define PON_SM_DEBUG_MODULE       (6 | (ONU_PON_SM_DEBUG_ATTR << MODULE_SHIFT))  

+#define PON_SM_STATE_MODULE       (6 | (ONU_PON_SM_STATE_ATTR << MODULE_SHIFT))  

+#define PON_SM_AES_MODULE         (6 | (ONU_PON_SM_AES_ATTR   << MODULE_SHIFT))  

+#define PON_SM_ALLOC_MODULE       (6 | (ONU_PON_SM_ALLOC_ATTR << MODULE_SHIFT))  

+#define PON_SM_OMCC_MODULE        (6 | (ONU_PON_SM_OMCC_ATTR  << MODULE_SHIFT))  

+#define PON_SM_TIMER_MODULE       (6 | (ONU_PON_SM_TIMER_ATTR << MODULE_SHIFT))  

+#define PON_SM_ALARM_MODULE       (6 | (ONU_PON_SM_ALARM_ATTR << MODULE_SHIFT))  

+#define PON_PM_MODULE	          (7)

+#define PON_ALARM_MODULE          (8)    

+#define PON_BER_MODULE	          (9)

+#define PON_API_MODULE            (10)      

+#define PON_ALLOC_MODULE          (11)    

+#define PON_LAST_MODULE           (12)    

+

+/* Timers Definitions */

+#define ONU_PON_TIMER_T01_INTERVAL           (10000) /* 10 sec */

+#define ONU_PON_TIMER_T02_INTERVAL           (100)   /* 100 msec */
+#define ONU_PON_TIMER_FIFO_AUDIT_INTERVAL    (20)    /* 20 msec */

+#define ONU_PON_TIMER_PM_INTERVAL            (1000)  /* 1 sec */

+#define ONU_PON_TIMER_PEE_INTERVAL           (3000)  /* 3 sec */

+#define ONU_PON_TIMER_PON_EVT_CLEAN_INTERVAL (5000)  /* 5 sec */

+#define ONU_PON_TIMER_XVR_RST_INTERVAL       (450)   /* 450 msec */

+#define ONU_PON_TIMER_MPCP_INTERVAL          (1000)  /* 1 sec */

+#define ONU_PON_TIMER_RPRT_INTERVAL          (1)     /* 1 msec */

+#define ONU_PON_TIMER_HW_RPRT_T0_INTERVAL    (2)     /* 2 msec */

+#define ONU_PON_TIMER_HW_RPRT_T1_INTERVAL    (150)   /* 150 msec */

+#define ONU_PON_TIMER_HOLDOVER_INTERVAL      (200)   /* 200 msec */

+#define ONU_PON_TIMER_SILENCE_INTERVAL       (60000) /* 60 sec */

+#define ONU_PON_TIMER_TX_MOD_INTERVAL        (1)   /* 1 msec */

+#define ONU_PON_TIMER_EVENT_MISS_INTERVAL    (10)   /* 10 msec */

+

+#define ONU_PON_TIMER_ACTIVE                 (1)

+#define ONU_PON_TIMER_NOT_ACTIVE             (0)

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+typedef void (*PTIMER_FUNCPTR)(unsigned long data);

+typedef void (*STATUSNOTIFYFUNC)(MV_U32 status);

+typedef void (*DYINGGASPFUNC)(void);

+typedef void (*LINKSTATUSFUNC)(MV_BOOL);

+

+/* Timer Id */

+typedef struct

+{

+  struct timer_list onuPonTimerId;

+  PTIMER_FUNCPTR    onuPonTimerFunc;

+  MV_U32            onuPonTimerActive;

+  MV_U32            onuPonTimerInterval; 

+  MV_U32            onuPonTimerPeriodic;

+}S_OnuPonTimer;

+

+/* Interrupt */

+typedef struct

+{

+  int                   onuPonIrqNum;

+#ifndef PON_FPGA

+  int                   onuDgIrqNum;

+#endif /* PON_FPGA */

+  spinlock_t            onuPonIrqLock;

+  struct tasklet_struct onuPonTasklet;

+}S_onuPonIrq;

+

+/* ONU GPON resource table */

+typedef struct

+{

+  /* Timer */

+  S_OnuPonTimer onuGponT01_TimerId;         /* ONU GPON T01 timer */

+  S_OnuPonTimer onuGponT02_TimerId;         /* ONU GPON T02 timer */

+  S_OnuPonTimer onuGponPeeTimerId;          /* ONU GPON PEE timer */

+  S_OnuPonTimer onuPonSwFIFOTimerId;        /* ONU GPON SW FIFO timer */

+                                            

+  S_OnuPonTimer onuPonMpcpTimerId;          /* ONU EPON MPCP timer */

+  S_OnuPonTimer onuPonHwRprtTimerId;        /* ONU EPON Hw Periodic Report timer */

+  S_OnuPonTimer onuPonHwRprtTxModTimerId;   /* ONU EPON Tx Module timer */

+  S_OnuPonTimer onuPonIsrMissTimerId;       /* ONU EPON ISR Miss timer */

+  S_OnuPonTimer onuPonHoldoverTimerId;      /* ONU EPON Holdover timer */

+  S_OnuPonTimer onuPonSilenceTimerId[8];    /* ONU EPON Silence timer */

+                                            

+  S_OnuPonTimer onuPonPmTimerId;            /* ONU PON PM timer */

+  S_OnuPonTimer onuPonPatternBurstTimerId;  /* ONU PON Pattern Burst timer */

+#ifndef PON_FPGA                            

+  S_OnuPonTimer onuPonIsrXvrRstTimerId;     /* ONU PON XVR Reset timer */

+#endif /* PON_FPGA */                       

+

+

+  /* Interrupt */

+  S_onuPonIrq   onuPonIrqId;           

+}S_OnuPonResourceTbl;

+

+/* Printing Options */

+typedef struct

+{

+  MV_U32 modulePrintLevel; /* Severity printing level per module */

+  MV_U32 moduleOptions;    /* Optional module printing options */

+}S_PonModulePrint;

+

+/* Global variables

+------------------------------------------------------------------------------*/

+extern S_OnuPonResourceTbl onuPonResourceTbl_s;

+

+/* Global functions

+------------------------------------------------------------------------------*/

+/* Init API */

+extern MV_STATUS onuPonRtosResourceInit(void);

+

+/* Timer API */

+extern MV_STATUS onuPonTimerCreate(S_OnuPonTimer *timerId, 

+                                   MV_U8         *timerDesc, 

+                                   PTIMER_FUNCPTR timerFunc, 

+                                   MV_U32         timerParam, 

+                                   MV_U32         timerInterval, 

+                                   MV_U32         timerPeriodic);

+extern int       onuPonTimerUpdate(S_OnuPonTimer *timerId, 

+								   MV_U32         data, 

+								   MV_U32         interval, 

+								   MV_U32         state);

+extern int       onuPonTimerEnable(S_OnuPonTimer *timerId);

+extern int       onuPonTimerDisable(S_OnuPonTimer *timerId);

+

+

+/* Memory API */

+extern MV_STATUS ponOnuGlbAddrInit(void);

+extern void*     onuPonMemAlloc(unsigned int size); 

+extern void      onuPonMemRelease(void); 

+

+/* Interrupt API */

+MV_STATUS onuPonIrqInit(void);

+

+extern MV_STATUS onuPonIrqNumInit(void);

+extern int       onuPonIrqEnable(S_onuPonIrq *irqId);

+extern int       onuPonIrqDisable(S_onuPonIrq *irqId);

+

+/* Printing API */

+extern MV_STATUS mvPonPrint(MV_U32 level, MV_U32 bitMask, const char *format, ...);

+extern MV_STATUS ponOnuCheckPrintStatus(MV_U32 printLevel, MV_U32 moduleOptions);

+extern MV_STATUS ponOnuChangePrintStatus(MV_U32 module, MV_U32 printLevel, MV_U32 moduleOptions);

+extern MV_STATUS ponOnuGetPrintStatus(MV_U32 module, MV_U32 *printLevel, MV_U32 *moduleOptions);

+extern int       ponOnuPrintStatus(char* buf);

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_PON_LINUX_KS_OS_H */

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuRtos.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuRtos.h
new file mode 100755
index 0000000..d2203fb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_pon/plat/ponOnuRtos.h
@@ -0,0 +1,104 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell 

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File in accordance with the terms and conditions of the General 

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 

+available along with the File in the license.txt file or by writing to the Free 

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or 

+modify this File under the following licensing terms. 

+Redistribution and use in source and binary forms, with or without modification, 

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer. 

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution. 

+

+    *   Neither the name of Marvell nor the names of its contributors may be 

+        used to endorse or promote products derived from this software without 

+        specific prior written permission. 

+    

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+******************************************************************************/

+

+/******************************************************************************

+**  FILE        : ponOnuRtos.h                                               **

+**                                                                           **

+**  DESCRIPTION : This file contains ONU GPON Linux OS resources             **

+*******************************************************************************

+*                                                                             *                              

+*  MODIFICATION HISTORY:                                                      *

+*                                                                             *

+*   29Oct06  Oren Ben Hayun   created                                         *  

+* =========================================================================== *      

+******************************************************************************/

+#ifndef _ONU_GPON_RTOS_H

+#define _ONU_GPON_RTOS_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+#include "ponOnuLnxKsOs.h"

+

+/* Definitions

+------------------------------------------------------------------------------*/ 

+

+/* Enums                              

+------------------------------------------------------------------------------*/ 

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Macros

+------------------------------------------------------------------------------*/    

+

+#endif /* _ONU_GPON_RTOS_H */

+

+

+             

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_proc/proc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_proc/proc.c
new file mode 100755
index 0000000..4c5b842
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_proc/proc.c
@@ -0,0 +1,541 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+#include <linux/proc_fs.h>
+#include <linux/version.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "gpp/mvGpp.h"
+#include "mvOs.h"
+#include "cpu/mvCpuCntrs.h"
+#include "cpu/mvCpuL2Cntrs.h"
+#include "eth-phy/mvEthPhy.h"
+
+#include "ddr2/mvDramCounters.h"
+
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+MV_CPU_CNTRS_EVENT *proc_event = NULL;
+#endif	/*  */
+
+#ifdef CONFIG_MV_CPU_L2_PERF_CNTRS
+MV_CPU_L2_CNTRS_EVENT *proc_l2_event = NULL;
+#endif	/*  */
+
+extern u32 mvCpuIfPrintSystemConfig(u8 *buffer, u32 index);
+
+/* global variables from 'regdump' */
+static struct proc_dir_entry *evb_resource_dump;
+static u32 evb_resource_dump_request, evb_resource_dump_result;
+
+/* Some service routines */
+static int ishex(char ch)
+{
+	if (((ch >= '0') && (ch <= '9')) || ((ch >= 'a') && (ch <= 'f')) || ((ch >= 'A') && (ch <= 'F')))
+		return 1;
+	return 0;
+}
+
+static int hex_value(char ch)
+{
+	if ((ch >= '0') && (ch <= '9'))
+		return ch - '0';
+	if ((ch >= 'a') && (ch <= 'f'))
+		return ch - 'a' + 10;
+	if ((ch >= 'A') && (ch <= 'F'))
+		return ch - 'A' + 10;
+	return 0;
+}
+
+static int atoh(char *s, int len)
+{
+	int i = 0;
+	while (ishex(*s) && len--) {
+		i = i * 0x10 + hex_value(*s);
+		s++;
+	}
+	return i;
+}
+
+
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+void mv_proc_start_cntrs(int cc0, int cc1, int cc2, int cc3)
+{
+	printk(KERN_INFO "configure CPU counters %d %d %d %d \n", cc0, cc1, cc2, cc3);
+	if (mvCpuCntrsProgram(0, cc0, "cc0", 0) != MV_OK)
+		goto error;
+	if (mvCpuCntrsProgram(1, cc1, "cc1", 0) != MV_OK)
+		goto error;
+	if (mvCpuCntrsProgram(2, cc2, "cc2", 0) != MV_OK)
+		goto error;
+	if (mvCpuCntrsProgram(3, cc3, "cc3", 0) != MV_OK)
+		goto error;
+	if (proc_event == NULL) {
+		proc_event = mvCpuCntrsEventCreate("PROC_CPU_CNTRS", 1);
+		if (proc_event == NULL)
+			goto error;
+	}
+	mvCpuCntrsEventClear(proc_event);
+	mvCpuCntrsReset();
+	MV_CPU_CNTRS_START(proc_event);
+	return;
+error:
+	printk(KERN_INFO "ERROR configuring counter\n");
+	return;
+}
+
+void mv_proc_show_cntrs(void)
+{
+	if (proc_event != NULL) {
+		MV_CPU_CNTRS_STOP(proc_event);
+		MV_CPU_CNTRS_SHOW(proc_event);
+	}
+}
+
+
+#endif	/*  */
+
+#ifdef CONFIG_MV_CPU_L2_PERF_CNTRS
+void mv_proc_start_l2_cntrs(int l20, int l21)
+{
+	printk(KERN_INFO "configure CPU L2 counters %d %d \n", l20, l21);
+	if (mvCpuL2CntrsProgram(0, l20, "l20", 0) != MV_OK)
+		goto error;
+	if (mvCpuL2CntrsProgram(1, l21, "l21", 0) != MV_OK)
+		goto error;
+	if (proc_l2_event == NULL) {
+		proc_l2_event = mvCpuL2CntrsEventCreate("PROC_CPU_L2_CNTRS", 1);
+		if (proc_l2_event == NULL)
+			goto error;
+	}
+	mvCpuL2CntrsEventClear(proc_l2_event);
+	mvCpuL2CntrsReset();
+	MV_CPU_L2_CNTRS_START(proc_l2_event);
+	return;
+error:
+	printk(KERN_INFO "ERROR configuring L2 counter\n");
+	return;
+}
+
+void mv_proc_show_l2_cntrs(void)
+{
+	if (proc_l2_event != NULL) {
+		MV_CPU_L2_CNTRS_STOP(proc_l2_event);
+		MV_CPU_L2_CNTRS_SHOW(proc_l2_event);
+	}
+}
+
+
+#endif	/*  */
+
+#ifdef CONFIG_MV_DRAM_STATS_CNTRS
+void mv_proc_start_dram_stats_cntrs(int mode0, int mode1)
+{
+	printk(KERN_INFO "configure DRAM statistics counters %d %d \n", mode0, mode1);
+	mvDramStatStop();
+	mvDramStatClear();
+	mvDramStatConfig(0, mode0);
+	mvDramStatConfig(1, mode1);
+	mvDramStatStart();
+	return;
+}
+
+void mv_proc_show_dram_stats_cntrs(void)
+{
+	MV_U64 cnt0, cnt1, hclk;
+	mvDramStatRead(&cnt0, &cnt1, &hclk);
+	printk(KERN_INFO "Counter #0 - 0x%llx.\n", cnt0);
+	printk(KERN_INFO "Counter #1 - 0x%llx.\n", cnt1);
+	printk(KERN_INFO "HCLK       - 0x%llx.\n", hclk);
+	return;
+}
+
+
+#endif	/*  */
+
+/* The format of writing to this module is as follows -
+   char 0 - r/w (Reading from register or Writing to register/memory)
+   char 1 - space
+   char 2 - register/mem_addr offset 7
+   char 3 - register/mem_addr offset 6
+   char 4 - register/mem_addr offset 5
+   char 5 - register/mem_addr offset 4
+   char 6 - register/mem_addr offset 3
+   char 7 - register/mem_addr offset 2
+   char 8 - register/mem_addr offset 1
+   char 9 - register/mem_addr offset 0
+   // The following is valid only if write request
+   char 10 - space
+   char 11 - register/mem_addr value 7
+   char 12 - register/mem_addr value 6
+   char 13 - register/mem_addr value 5
+   char 14 - register/mem_addr value 4
+   char 15 - register/mem_addr value 3
+   char 16 - register/mem_addr value 2
+   char 17 - register/mem_addr value 1
+   char 18 - register/mem_addr value 0
+
+*/
+
+/********************************************************************
+* evb_resource_dump_write -
+*
+* When written to the /proc/resource_dump file this function is called
+*
+* Inputs: file / data are not used. Buffer and count are the pointer
+*         and length of the input string
+* Returns: Read from GT register
+* Outputs: count
+*********************************************************************/
+unsigned int kernel_align = 0;
+extern unsigned int support_wait_for_interrupt;
+int evb_resource_dump_write(struct file *file, const char *buffer, unsigned long count, void *data)
+{
+	/* Reading / Writing from system controller internal registers */
+	if (!strncmp(buffer, "register", 8)) {
+		if (buffer[10] == 'r') {
+			evb_resource_dump_request = atoh((char *)((unsigned int)buffer + 12), 8);
+			evb_resource_dump_result = MV_REG_READ(evb_resource_dump_request);
+		}
+		if (buffer[10] == 'w') {
+			evb_resource_dump_request = atoh((char *)((unsigned int)buffer + 12), 8);
+			evb_resource_dump_result = atoh((char *)((unsigned int)buffer + 12 + 8 + 1), 8);
+			MV_REG_WRITE(evb_resource_dump_request, evb_resource_dump_result);
+		}
+	}
+
+	/* Reading / Writing from 32bit address - mostly usable for memory */
+	if (!strncmp(buffer, "memory  ", 8)) {
+		if (buffer[10] == 'r') {
+			evb_resource_dump_request = atoh((char *)((unsigned int)buffer + 12), 8);
+			evb_resource_dump_result = *(unsigned int *)evb_resource_dump_request;
+		}
+		if (buffer[10] == 'w') {
+			evb_resource_dump_request = atoh((char *)((unsigned int)buffer + 12), 8);
+			evb_resource_dump_result = atoh((char *)((unsigned int)buffer + 12 + 8 + 1), 8);
+			*(unsigned int *)evb_resource_dump_request = evb_resource_dump_result;
+		}
+	}
+
+	/* Reading / Writing from a rgister via SMI */
+	if (!strncmp(buffer, "smi", 3)) {
+		unsigned short regVal;
+		unsigned int dev_addr = atoh((char *)((unsigned int)buffer + 7), 8);
+		if (buffer[5] == 'r') {
+			evb_resource_dump_request = atoh((char *)((unsigned int)buffer + 7 + 8 + 1), 8);
+			regVal = 0;
+			mvEthPhyRegRead(dev_addr, evb_resource_dump_request, &regVal);
+			evb_resource_dump_result = (u32) regVal;
+		}
+		if (buffer[5] == 'w') {
+			evb_resource_dump_request = atoh((char *)((unsigned int)buffer + 7 + 8 + 1), 8);
+			evb_resource_dump_result = atoh((char *)((unsigned int)buffer + 7 + 8 + 8 + 2), 8);
+			mvEthPhyRegWrite(dev_addr, evb_resource_dump_request, (u16) evb_resource_dump_result);
+		}
+	}
+
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+	if (!strncmp(buffer, "start_cc", 8)) {
+		int cc0, cc1, cc2, cc3;
+		sscanf((char *)((unsigned int)buffer + 8), "%d %d %d %d", &cc0, &cc1, &cc2, &cc3);
+		mv_proc_start_cntrs(cc0, cc1, cc2, cc3);
+	}
+	if (!strncmp(buffer, "show__cc", 8))
+		mv_proc_show_cntrs();
+
+
+#endif	/*  */
+#ifdef CONFIG_MV_CPU_L2_PERF_CNTRS
+	if (!strncmp(buffer, "start_l2", 8)) {
+		int l20, l21;
+		sscanf((char *)((unsigned int)buffer + 8), "%d %d", &l20, &l21);
+		mv_proc_start_l2_cntrs(l20, l21);
+	}
+	if (!strncmp(buffer, "show__l2", 8))
+		mv_proc_show_l2_cntrs();
+
+#endif	/*  */
+
+#ifdef CONFIG_MV_DRAM_STATS_CNTRS
+	if (!strncmp(buffer, "start_dram_stats", strlen("start_dram_stats"))) {
+		int mode0, mode1;
+		sscanf((char *)((unsigned int)buffer + strlen("start_dram_stats")), "%d %d", &mode0, &mode1);
+		mv_proc_start_dram_stats_cntrs(mode0, mode1);
+	}
+	if (!strncmp(buffer, "stop_dram_stats", strlen("stop_dram_stats")))
+		mvDramStatStop();
+
+	if (!strncmp(buffer, "show_dram_stats", strlen("show_dram_stats")))
+		mv_proc_show_dram_stats_cntrs();
+
+#endif	/*  */
+
+	if (!strncmp(buffer, "idle_wfi", strlen("idle_wfi"))) {
+		int en;
+		sscanf((char *)((unsigned int)buffer + strlen("idle_wfi")), "%d", &en);
+		support_wait_for_interrupt = en;
+	}
+
+	if (!strncmp(buffer, "show__ua", 8)) {
+		if (kernel_align == 1)
+			kernel_align = 0;
+		else
+			kernel_align = 1;
+		printk(KERN_INFO "debug kernel align %d\n", kernel_align);
+	}
+
+
+	if (!strncmp(buffer, "cpu_freq", strlen("cpu_freq"))) {
+		buffer += strlen("cpu_freq") + 1;
+		if (!strncmp(buffer, "normal", strlen("normal"))) {
+			printk(KERN_INFO "Entering fast mode.\n");
+			mvCtrlPwrSaveOff();
+		} else if (!strncmp(buffer, "ddr", strlen("ddr"))) {
+			printk(KERN_INFO "Entering slow mode.\n");
+			mvCtrlPwrSaveOn();
+		}
+	}
+
+#if 0
+	    if (!strncmp(buffer, "ddd", 3)) {
+		unsigned int ii[10];
+		int ip, sum = 0;
+		volatile unsigned int *tt = (unsigned int *)((unsigned int)ii + 2);
+		MV_CPU_CNTRS_EVENT *hal_rx_event = NULL;
+
+		    /* 0 - instruction counters */
+		    mvCpuCntrsProgram(0, MV_CPU_CNTRS_INSTRUCTIONS, "Instr", 25);
+
+		    /* 1 - ICache misses counter */
+		    mvCpuCntrsProgram(1, MV_CPU_CNTRS_ICACHE_READ_MISS, "IcMiss", 0);
+
+		    /* 2 - cycles counter */
+		    mvCpuCntrsProgram(2, MV_CPU_CNTRS_CYCLES, "Cycles", 21);
+
+		    /* 3 - DCache read misses counter */
+		    mvCpuCntrsProgram(3, MV_CPU_CNTRS_DCACHE_READ_MISS, "DcRdMiss", 0);
+		hal_rx_event = mvCpuCntrsEventCreate("HAL_RX", 1);
+		MV_CPU_CNTRS_START(hal_rx_event);
+		for (ip = 0; ip < 1000; ip++)
+			sum += *tt;
+		MV_CPU_CNTRS_STOP(hal_rx_event);
+		MV_CPU_CNTRS_SHOW(hal_rx_event);
+	}
+
+#endif	/*  */
+	    return count;
+}
+
+
+/********************************************************************
+* evb_resource_dump_read -
+*
+* When read from the /proc/resource_dump file this function is called
+*
+* Inputs: buffer_location and buffer_length and zero are not used.
+*         buffer is the pointer where to post the result
+* Returns: N/A
+* Outputs: length of string posted
+*********************************************************************/
+int evb_resource_dump_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *zero,
+			   void *ptr)
+{
+	if (offset > 0)
+		return 0;
+	return sprintf(buffer, "%08x\n", evb_resource_dump_result);
+}
+
+
+/********************************************************************
+* start_regdump_memdump -
+*
+* Register the /proc/regdump file at the /proc filesystem
+* Register the /proc/memdump file at the /proc filesystem
+*
+* Inputs: N/A
+* Returns: N/A
+* Outputs: N/A
+*********************************************************************/
+int __init start_resource_dump(void)
+{
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+	evb_resource_dump = create_proc_entry("resource_dump", 0666, &proc_root);
+#else	/* */
+	evb_resource_dump = create_proc_entry("resource_dump", 0666, NULL);
+
+#endif	/* */
+	evb_resource_dump->read_proc = evb_resource_dump_read;
+	evb_resource_dump->write_proc = evb_resource_dump_write;
+	evb_resource_dump->nlink = 1;
+	return 0;
+}
+
+module_init(start_resource_dump);
+
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+/*
+ * FIQ proc entry
+ */
+static struct proc_dir_entry *fiq_proc;
+extern int fiq_cnt;
+
+int fiq_proc_read(char *buffer, char **buffer_location, off_t offset,
+		  int buffer_length, int *zero, void *ptr)
+{
+	if (offset > 0)
+		return 0;
+	return sprintf(buffer, "%d\n", fiq_cnt);
+}
+
+int __init fiq_proc_init(void)
+{
+	fiq_proc = create_proc_entry("fiq_dump", 0666, NULL);
+	fiq_proc->read_proc = fiq_proc_read;
+	fiq_proc->write_proc = NULL ; /* fiq_proc_write; */
+	fiq_proc->nlink = 1;
+	return 0;
+}
+module_init(fiq_proc_init);
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
+/* global variables from 'regdump' */
+static struct proc_dir_entry *soc_type;
+static struct proc_dir_entry *board_type;
+static struct proc_dir_entry *pon_type;
+
+/********************************************************************
+* soc_type_read -
+*********************************************************************/
+int soc_type_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *zero, void *ptr)
+{
+	int count = 0;
+	char tmp_buffer[1000] = { 0 };
+
+#ifdef CONFIG_ARCH_FEROCEON_MV78XX0
+	char name[100] = { 0 };
+
+#endif	/*  */
+	if (offset > 0)
+		return 0;
+
+#ifdef CONFIG_ARCH_FEROCEON_MV78XX0
+	mvCtrlModelRevNameGet(name);
+	count += sprintf(tmp_buffer, "%s\n", name);
+
+#endif	/*  */
+#ifdef CONFIG_MV88F6281
+	count += sprintf(tmp_buffer, "%s%x Rev %d\n", SOC_NAME_PREFIX, mvCtrlModelGet(), mvCtrlRevGet());
+
+#endif	/* */
+	count += mvCpuIfPrintSystemConfig(tmp_buffer, count);
+	*(tmp_buffer + count) = '\0';
+	sprintf(buffer, "%s", tmp_buffer);
+	return count;
+}
+
+
+/********************************************************************
+* board_type_read -
+*********************************************************************/
+int board_type_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *zero, void *ptr)
+{
+	char name_buff[50];
+	if (offset > 0)
+		return 0;
+	mvBoardNameGet(name_buff);
+	return sprintf(buffer, "%s\n", name_buff);
+}
+
+
+/********************************************************************
+* pon_type_read -
+*********************************************************************/
+int pon_type_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *zero, void *ptr)
+{
+	MV_U32 ponType;
+	if (offset > 0)
+		return 0;
+	ponType = mvBoardPonConfigGet();
+	if (ponType == BOARD_EPON_CONFIG)
+		return sprintf(buffer, "epon\n");
+
+	else if (ponType == BOARD_GPON_CONFIG)
+		return sprintf(buffer, "gpon\n");
+	else
+		return sprintf(buffer, "none\n");
+}
+
+
+/********************************************************************
+* start_soc_type -
+*********************************************************************/
+int __init start_soc_type(void)
+{
+	struct proc_dir_entry *parent;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+	parent = &proc_root;
+#else	/*  */
+	parent = NULL;
+#endif	/*  */
+
+	soc_type = create_proc_entry("soc_type", 0666, parent);
+	soc_type->read_proc = soc_type_read;
+	soc_type->write_proc = NULL;
+	soc_type->nlink = 1;
+	board_type = create_proc_entry("board_type", 0666, parent);
+	board_type->read_proc = board_type_read;
+	board_type->write_proc = NULL;
+	board_type->nlink = 1;
+	pon_type = create_proc_entry("pon_type", 0666, parent);
+	pon_type->read_proc = pon_type_read;
+	pon_type->write_proc = NULL;
+	pon_type->nlink = 1;
+	return 0;
+}
+
+void __exit stop_soc_type(void)
+{
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+	    remove_proc_entry("soc_type", &proc_root);
+#else	/* */
+	    remove_proc_entry("soc_type", NULL);
+#endif	/* */
+	    return;
+}
+
+module_init(start_soc_type);
+module_exit(stop_soc_type);
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/Kconfig
new file mode 100755
index 0000000..fc8a105
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/Kconfig
@@ -0,0 +1,34 @@
+menu "Sata options"
+	depends on SCSI_MVSATA
+	depends on BLOCK
+	
+config  MV_SATA_SUPPORT_ATAPI
+        bool "Support ATAPI (CR-ROM/DVD-ROM) devices"
+        default n
+
+config  MV_SATA_ENABLE_1MB_IOS
+        bool "Enable 1 MByte requests"
+        default n
+        help
+          Set the maximum io request size to 1 MByte for HDD's the support LBA48 feature,
+          say No if you want to keep the maximum limit on 128KBytes.
+choice
+	prompt "Debug level"
+	default SATA_NO_DEBUG
+
+config SATA_NO_DEBUG
+	bool "No Debug"
+
+config SATA_DEBUG_ON_ERROR
+	bool "Debug on errors"
+	help
+	  print debug messages when EDMA/System/HDD errors occur.
+
+config SATA_FULL_DEBUG
+	bool "Full debug"
+
+endchoice
+
+endmenu
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/Makefile
new file mode 100755
index 0000000..50865be
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Marvell egiga ethernet driver
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+IAL_OBJS        := mvLinuxIalLib.o mvLinuxIalHt.o mvLinuxIalOs.o mvIALCommon.o mvIALCommonUtils.o mvLinuxIalSmart.o
+SAL_OBJS        := mvScsiAtaLayer.o
+
+obj-$(CONFIG_SCSI_MVSATA) := mvsata.o
+mvsata-y        := $(IAL_OBJS) $(SAL_OBJS) ../../$(HAL_SATA_DIR)/mvSata.o ../../$(HAL_SATA_DIR)/mvStorageDev.o		\
+                  ../../$(HAL_SATA_DIR)/mvLog.o
+
+
+
+INCLUDE_DIRS    := -Idrivers/scsi
+EXTRA_CFLAGS += -DLINUX -D__LINUX__ $(INCLUDE_DIRS)
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommon.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommon.c
new file mode 100755
index 0000000..b701211
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommon.c
@@ -0,0 +1,2613 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvIALCommon.c
+*
+* DESCRIPTION:
+*       C implementation for IAL's common functions.
+*
+* DEPENDENCIES:
+*   mvIALCommon.h
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvOs.h"
+#include "mvScsiAtaLayer.h"
+#include "mvIALCommon.h"
+#include "mvIALCommonUtils.h"
+#include "mvStorageDev.h"
+
+
+/* defines */
+#undef DISABLE_PM_SCC
+/* typedefs */
+
+/*Static functions*/
+static MV_BOOLEAN mvGetDisksModes(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                  MV_SAL_ADAPTER_EXTENSION *pScsiAdapterExt,
+                                  MV_U8 channelIndex,
+                                  MV_BOOLEAN *TCQ,
+                                  MV_BOOLEAN *NCQ,
+                                  MV_U8   *numOfDrives);
+
+static void mvFlushSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                    MV_U8 channelIndex);
+
+static void mvAddToSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                    MV_U8 channelIndex,
+                                    MV_SATA_SCSI_CMD_BLOCK *Scb);
+
+static MV_BOOLEAN mvAdapterStateMachine(
+                                       MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                       MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+static MV_BOOLEAN mvChannelStateMachine(
+                                       MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                       MV_U8 channelIndex,
+                                       MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+static void mvSetChannelState(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                              MV_U8 channelIndex,
+                              MV_CHANNEL_STATE state);
+
+static MV_BOOLEAN clearSErrorPorts(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex, 
+				   MV_U8     PMnumberOfPorts);
+/*PM related*/
+static MV_BOOLEAN mvPMCommandCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
+                                          MV_U8 channelIndex,
+                                          MV_COMPLETION_TYPE comp_type,
+                                          MV_VOID_PTR commandId,
+                                          MV_U16 responseFlags,
+                                          MV_U32 timeStamp,
+                                          MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+
+static MV_BOOLEAN mvQueuePMAccessRegisterCommand(
+                                                MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
+                                                MV_U8 channelIndex,
+                                                MV_U8 PMPort,
+                                                MV_U8 PMReg,
+                                                MV_U32 Value,
+                                                MV_BOOLEAN isRead);
+
+static MV_BOOLEAN mvPMEnableCommStatusChangeBits(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                                 MV_U8 channelIndex,
+                                                 MV_BOOLEAN enable);
+
+static MV_BOOLEAN mvPMEnableAsyncNotify(
+                                       MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                       MV_U8 channelIndex);
+
+#if 0
+static void mvCheckPMForError(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                              MV_U8 channelIndex);
+#endif
+
+/*End PM related*/
+
+static MV_BOOLEAN mvStartChannelInit(MV_SATA_ADAPTER *pSataAdapter,
+                                     MV_U8 channelIndex,
+                                     MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+                                     MV_BOOLEAN *isChannelReady);
+
+static MV_BOOLEAN mvChannelSRSTFinished(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_SATA_CHANNEL *pSataChannel,
+                                        MV_U8 channelIndex,
+                                        MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+                                        MV_BOOLEAN* bIsChannelReady,
+                                        MV_BOOLEAN* bFatalError);
+
+static MV_BOOLEAN mvConfigChannelQueuingMode(
+                                            MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
+                                            MV_U8 channelIndex,
+                                            MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+static MV_BOOLEAN mvConfigChannelDMA(
+                                    MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
+                                    MV_U8 channelIndex,
+                                    MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+static void mvSetChannelTimer(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                              MV_U8 channelIndex,
+                              MV_U32 timeout);
+static void mvDecrementChannelTimer(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                    MV_U8 channelIndex);
+static MV_BOOLEAN mvIsChannelTimerExpired(
+                                         MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                         MV_U8 channelIndex);
+
+
+/*Channel state machine*/
+
+
+static MV_BOOLEAN mvChannelNotConnectedStateHandler(
+                                                   MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                                   MV_U8 channelIndex,
+                                                   MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+
+static MV_BOOLEAN mvChannelConnectedStateHandler(
+                                                MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                                MV_U8 channelIndex,
+                                                MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+MV_BOOLEAN mvChannelInSrstStateHandler(
+                                      MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                      MV_U8 channelIndex,
+                                      MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+static MV_BOOLEAN mvPMInitDevicesStateHandler(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+					      MV_U8 channelIndex,
+					      MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+static MV_BOOLEAN mvChannelReadyStateHandler(
+                                            MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                            MV_U8 channelIndex);
+
+static MV_BOOLEAN mvChannelPMHotPlugStateHandler(
+                                                MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                                MV_U8 channelIndex,
+                                                MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+
+
+static void mvDrivesInfoSaveAll(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                MV_U8 channelIndex);
+
+static void mvDrivesInfoFlushAll(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                 MV_U8 channelIndex);
+
+static void mvDrivesInfoFlushSingleDrive(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                         MV_U8 channelIndex, MV_U8 PMPort);
+
+static void mvDrivesInfoSaveSingleDrive(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_U8 channelIndex,
+                                        MV_U8 PMPort,
+                                        MV_BOOLEAN  isDriveAdded,
+                                        MV_U16_PTR identifyBuffer);
+
+static void mvSetDriveReady(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                            MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+                            MV_U8 channelIndex,
+                            MV_U8 PMPort,
+                            MV_BOOLEAN  isReady,
+                            MV_U16_PTR identifyBuffer);
+
+static void mvDrivesInfoGetChannelRescanParams(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                               MV_U8 channelIndex,
+                                               MV_U16 *drivesToRemove,
+                                               MV_U16 *drivesToAdd);
+
+
+
+#ifdef DISABLE_PM_SCC
+MV_BOOLEAN mvPMDisableSSC(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex);
+#endif
+
+MV_BOOLEAN mvPMEnableLocking(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex);
+
+
+
+/*Public functions*/
+
+/*******************************************************************************
+* mvAdapterStartInitialization - start adapter initialization
+*
+* DESCRIPTION:
+*  Starts adapter initialization after driver load.
+*  State - machine related data structure is initialized for adapter
+*  and its channels. Begin staggered spin-up.
+*  Adapter state is changed to ADAPTER_READY.
+* INPUT:
+*    pAdapter    - pointer to the adapter data structure.
+*    scsiAdapterExt  - SCSI to ATA layer adapter extension data structure
+* OUTPUT:
+*    None.
+*
+* RETURN:
+*    MV_TRUE on success
+*    MV_FALSE on error
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvAdapterStartInitialization(MV_SATA_ADAPTER *pSataAdapter,
+                                        MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_U8 channelIndex;
+    ialExt->pSataAdapter = pSataAdapter;
+    ialExt->adapterState = ADAPTER_INITIALIZING;
+    for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++)
+    {
+        ialExt->channelState[channelIndex] = CHANNEL_NOT_CONNECTED;
+        ialExt->IALChannelExt[channelIndex].SRSTTimerThreshold = 0;
+        ialExt->IALChannelExt[channelIndex].SRSTTimerValue = 0;
+        ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue = NULL;
+        ialExt->IALChannelExt[channelIndex].completionError = MV_FALSE;
+        ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress = MV_FALSE;
+        ialExt->IALChannelExt[channelIndex].pmRegPollCounter = 0;
+        ialExt->IALChannelExt[channelIndex].devInSRST =
+        MV_SATA_PM_CONTROL_PORT + 1;
+        ialExt->IALChannelExt[channelIndex].PMdevsToInit = 0;
+        ialExt->IALChannelExt[channelIndex].PMnumberOfPorts = 0;
+        ialExt->IALChannelExt[channelIndex].pmAccessType = 0;
+        ialExt->IALChannelExt[channelIndex].pmReg = 0;
+        ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled = MV_FALSE;
+        ialExt->IALChannelExt[channelIndex].bHotPlug = MV_FALSE;
+        memset(&ialExt->IALChannelExt[channelIndex].drivesInfo, 0, sizeof(MV_DRIVES_INFO));
+    }
+    return mvAdapterStateMachine(ialExt, scsiAdapterExt);
+}
+
+
+/*******************************************************************************
+* mvRestartChannel - restart specific channel
+*
+* DESCRIPTION:
+*  The function is used in channel hot-plug to restart the channel
+*  initialization sequence. The channel stated is changed to
+*  CHANNEL_CONNECTED and any pending command in software queue are flushed
+* INPUT:
+*    pAdapter    - pointer to the adapter data structure.
+*    channelIndex  - channel number
+*    scsiAdapterExt  - SCSI to ATA layer adapter extension data structure
+*    bBusReset       - MV_TRUE if the faunction is called because of bus reset,
+*                       MV_FALSE otherwise
+* OUTPUT:
+*    None.
+*
+* RETURN:
+*    MV_TRUE on success
+*    MV_FALSE on error
+*
+*******************************************************************************/
+
+void mvRestartChannel(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                      MV_U8 channelIndex,
+                      MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+                      MV_BOOLEAN bBusReset)
+{
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    MV_BOOLEAN bBusChangeNotify = MV_FALSE;
+    ialExt->IALChannelExt[channelIndex].bHotPlug = MV_TRUE;
+    mvSetDriveReady(ialExt,
+                    scsiAdapterExt,
+                    channelIndex, 0xFF, MV_FALSE, NULL);
+    if (pSataAdapter->sataChannel[channelIndex] != NULL)
+    {
+        if (mvStorageDevGetDeviceType(pSataAdapter,channelIndex)
+            == MV_SATA_DEVICE_TYPE_PM)
+        {
+            bBusChangeNotify = MV_TRUE;
+        }
+        mvSataDisableChannelDma(pSataAdapter, channelIndex);
+        mvSataFlushDmaQueue (pSataAdapter, channelIndex,
+                             MV_FLUSH_TYPE_CALLBACK);
+    }
+    mvFlushSCSICommandQueue(ialExt, channelIndex);
+    ialExt->IALChannelExt[channelIndex].SRSTTimerThreshold = 0;
+    ialExt->IALChannelExt[channelIndex].SRSTTimerValue = 0;
+    ialExt->channelState[channelIndex] = CHANNEL_CONNECTED;
+    if (bBusReset == MV_TRUE)
+    {
+        if (bBusChangeNotify == MV_TRUE)
+        {
+            /*Notify about bus change*/
+            IALBusChangeNotify(pSataAdapter, channelIndex);
+        }
+    }
+    else
+    {
+        /*Notify about bus change*/
+        IALBusChangeNotify(pSataAdapter, channelIndex);
+    }
+}
+
+
+
+/*******************************************************************************
+* mvPMHotPlugDetected - restart specific channel
+*
+* DESCRIPTION:
+*  The function is used in PM hot-plug to wait for empty EDMA command queue
+*  and then restart the channel initialization sequence.
+*  The channel stated is changed to CHANNEL_PM_HOT_PLUG if there are any
+*  pending command in EDMA queue
+* INPUT:
+*    pAdapter    - pointer to the adapter data structure.
+*    channelIndex  - channel number
+
+* OUTPUT:
+*    None.
+*
+* RETURN:
+*    None
+*
+*******************************************************************************/
+
+void mvPMHotPlugDetected(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                         MV_U8 channelIndex,
+                         MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    if (ialExt->channelState[channelIndex] == CHANNEL_NOT_CONNECTED ||
+        ialExt->channelState[channelIndex] == CHANNEL_CONNECTED ||
+        ialExt->channelState[channelIndex] == CHANNEL_IN_SRST)
+    {
+        return;
+    }
+    mvSataDisableChannelDma(ialExt->pSataAdapter, channelIndex);
+    mvSataFlushDmaQueue (ialExt->pSataAdapter,
+                         channelIndex, MV_FLUSH_TYPE_CALLBACK);
+    mvSataChannelHardReset(ialExt->pSataAdapter, channelIndex);
+    mvRestartChannel(ialExt, channelIndex, scsiAdapterExt, MV_FALSE);
+}
+
+/*******************************************************************************
+* mvStopChannel - stop channel
+*
+* DESCRIPTION:
+*  The function is used when the channel is unplugged.
+*  The channel stated is changed to CHANNEL_NOT_CONNECTED
+*  until further connection.
+* INPUT:
+*    pAdapter    - pointer to the adapter data structure.
+*    channelIndex  - channel number
+* OUTPUT:
+*    None.
+*
+* RETURN:
+*    None
+*******************************************************************************/
+void mvStopChannel(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                   MV_U8 channelIndex,
+                   MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    MV_U16 drivesSnapshot =
+    ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotSaved;
+    mvDrivesInfoFlushAll(ialExt, channelIndex);
+    mvSetDriveReady(ialExt, scsiAdapterExt, channelIndex, 0xFF, MV_FALSE, NULL);
+    mvSetChannelState(ialExt, channelIndex, CHANNEL_NOT_CONNECTED);
+    if (pSataAdapter->sataChannel[channelIndex] != NULL)
+    {
+        mvSataDisableChannelDma(ialExt->pSataAdapter, channelIndex);
+        mvSataFlushDmaQueue (ialExt->pSataAdapter, channelIndex,
+                             MV_FLUSH_TYPE_CALLBACK);
+    }
+    mvFlushSCSICommandQueue(ialExt, channelIndex);
+    if (pSataAdapter->sataChannel[channelIndex] != NULL)
+    {
+        mvSataRemoveChannel(pSataAdapter,channelIndex);
+        IALReleaseChannel(pSataAdapter, channelIndex);
+    }
+    pSataAdapter->sataChannel[channelIndex] = NULL;
+    /*Notify about bus change*/
+    IALBusChangeNotify(pSataAdapter, channelIndex);
+    if (drivesSnapshot != 0)
+    {
+        IALBusChangeNotifyEx(pSataAdapter, channelIndex, drivesSnapshot, 0);
+    }
+}
+
+
+/*******************************************************************************
+* mvExecuteScsiCommand - execute SCSI command
+*
+* DESCRIPTION:
+*  IAL common layer wrapper of mvSataExecuteScsiCommand function.
+*  If either the adapter state is either other than ADAPTER_READY
+*  or the channel is connected but channel state is not CHANNEL_READY,
+*  the current SCSI command is queued in channel's SCSI commands
+*  software queue until channel initialization sequence completed.
+*  If channel is found in CHANNEL ready state the SCSI command is passed to
+*  SCSI ATA translation layer.
+* INPUT:
+*    pScb    - SCSI command block structure.
+*
+* OUTPUT:
+*    None.
+*
+* RETURN:
+*    Return MV_SCSI_COMMAND_STATUS_COMPLETED if the command has been added
+*    to channel software queue. Otherwise return the result of
+*    mvSataExecuteScsiCommand function call
+*******************************************************************************/
+MV_SCSI_COMMAND_STATUS_TYPE mvExecuteScsiCommand(MV_SATA_SCSI_CMD_BLOCK *pScb,
+                                                 MV_BOOLEAN canQueue)
+{
+    MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt = pScb->pIalAdapterExtension;
+    MV_U8 channelIndex = pScb->bus;
+
+#if 0
+    if ((ialExt->adapterState == ADAPTER_READY) &&
+        (ialExt->channelState[channelIndex] == CHANNEL_READY))
+    {
+        mvCheckPMForError(ialExt, channelIndex);
+    }
+#endif
+
+    if ((ialExt->adapterState == ADAPTER_READY) &&
+        ((ialExt->channelState[channelIndex] == CHANNEL_READY) ||
+         (ialExt->channelState[channelIndex] == CHANNEL_NOT_CONNECTED)))
+    {
+        return mvSataExecuteScsiCommand(pScb);
+    }
+    if (canQueue == MV_FALSE)
+    {
+        pScb->ScsiStatus = MV_SCSI_STATUS_BUSY;
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_QUEUE_FULL;
+        if (pScb->completionCallBack)
+        {
+            pScb->completionCallBack(ialExt->pSataAdapter, pScb);
+        }
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    else
+    {
+        mvAddToSCSICommandQueue(ialExt, channelIndex, pScb);
+        return MV_SCSI_COMMAND_STATUS_QUEUED_BY_IAL;
+    }
+}
+
+
+/*******************************************************************************
+* mvIALTimerCallback - IAL timer callback
+*
+* DESCRIPTION:
+*  The adapter/channel state machine is timer-driven.
+*  After being loaded, the IAL must call this callback every 0.5 seconds
+* INPUT:
+*    pSataAdapter    - pointer to the adapter data structure.
+*    scsiAdapterExt  - SCSI to ATA layer adapter extension data structure
+* OUTPUT:
+*    None.
+*
+* RETURN:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvIALTimerCallback(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                              MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+
+    return mvAdapterStateMachine(ialExt,
+                                 scsiAdapterExt);
+}
+
+/*******************************************************************************
+* mvCommandCompletionErrorHandler - IAL common command completion error handler
+*
+* DESCRIPTION:
+*  Called by whether SAL completion of SMART completion function. Check whether
+*  command is failed because of PM hot plug
+*
+* INPUT:
+*    pSataAdapter    - pointer to the adapter data structure.
+*    channelIndex    - channelNumber
+* OUTPUT:
+*    None.
+*
+* RETURN:
+*
+*******************************************************************************/
+
+void mvCommandCompletionErrorHandler(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                     MV_U8 channelIndex)
+{
+    MV_SATA_ADAPTER* pSataAdapter = ialExt->pSataAdapter;
+    if (pSataAdapter->sataChannel[channelIndex] == NULL)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
+                 "Invalid channel data structure pointer.\n",
+                 pSataAdapter->adapterId, channelIndex);
+    }
+
+    if ((ialExt->channelState[channelIndex] != CHANNEL_READY) ||
+        (mvStorageDevGetDeviceType(pSataAdapter,channelIndex) !=
+         MV_SATA_DEVICE_TYPE_PM) ||
+        (ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled == MV_TRUE))
+    {
+        return;
+    }
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
+             "Set completion error to MV_TRUE.\n",
+             pSataAdapter->adapterId, channelIndex);
+    ialExt->IALChannelExt[channelIndex].completionError = MV_TRUE;
+}
+
+/*Static functions*/
+
+
+static void printAtaDeviceRegisters(
+                                   MV_STORAGE_DEVICE_REGISTERS *mvStorageDevRegisters)
+{
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "ATA Drive Registers:\n");
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","Error",
+             mvStorageDevRegisters->errorRegister);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","SectorCount",
+             mvStorageDevRegisters->sectorCountRegister);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA Low",
+             mvStorageDevRegisters->lbaLowRegister);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA Mid",
+             mvStorageDevRegisters->lbaMidRegister);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA High",
+             mvStorageDevRegisters->lbaHighRegister);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","Device",
+             mvStorageDevRegisters->deviceRegister);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","Status",
+             mvStorageDevRegisters->statusRegister);
+}
+
+
+
+static void mvDrivesInfoSaveAll(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                MV_U8 channelIndex)
+{
+    /*Save disk drives information for channel*/
+    ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotSaved =
+    ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotCurrent;
+    memcpy(ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialSaved,
+           ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent,
+           sizeof(ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent));
+    /*Reset current disk drives information*/
+    ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotCurrent = 0;
+    memset(ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent,
+           0,
+           sizeof(ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent));
+
+}
+
+static void mvDrivesInfoFlushAll(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                 MV_U8 channelIndex)
+{
+    /*Flush drives info*/
+    memset(&ialExt->IALChannelExt[channelIndex].drivesInfo, 0,
+           sizeof(ialExt->IALChannelExt[channelIndex].drivesInfo));
+}
+
+static void mvDrivesInfoFlushSingleDrive(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                         MV_U8 channelIndex, MV_U8 PMPort)
+{
+    /*Clear bit in disk drive drive snapshot*/
+    ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotCurrent &=
+    ~(1 << PMPort);
+    ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotSaved &=
+    ~(1 << PMPort);
+    /*Clear disk drive serial number string*/
+    ialExt->
+    IALChannelExt[channelIndex].drivesInfo.driveSerialSaved[PMPort].serial[0] = 0;
+    ialExt->
+    IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent[PMPort].serial[0] = 0;
+}
+
+
+static void mvDrivesInfoSaveSingleDrive(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_U8 channelIndex,
+                                        MV_U8 PMPort,
+                                        MV_BOOLEAN  isDriveAdded,
+                                        MV_U16_PTR identifyBuffer)
+{
+    if (MV_TRUE == isDriveAdded)
+    {
+        /*Set bit in disk drive snapshot for current disk drive*/
+        ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotCurrent |=
+        1 << PMPort;
+        /*Save serial number for current disk drive*/
+        memcpy(ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent[PMPort].serial,
+               &identifyBuffer[IDEN_SERIAL_NUM_OFFSET], IDEN_SERIAL_NUM_SIZE);
+    }
+    else
+    {
+        if (0xFF == PMPort)
+        {
+            ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotCurrent
+            = 0;
+            memset(ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent,
+                   0,
+                   sizeof(ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent));
+        }
+        else
+        {
+            ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotCurrent
+            &= ~(1 << PMPort);
+            ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent[PMPort].serial[0] = 0;
+        }
+    }
+}
+
+static void mvSetDriveReady(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                            MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+                            MV_U8 channelIndex,
+                            MV_U8 PMPort,
+                            MV_BOOLEAN  isReady,
+                            MV_U16_PTR identifyBuffer)
+{
+    mvDrivesInfoSaveSingleDrive(ialExt,
+                                channelIndex,
+                                PMPort,
+                                isReady,
+                                identifyBuffer);
+    mvSataScsiSetDriveReady(scsiAdapterExt,
+                            channelIndex, PMPort, isReady);
+}
+
+
+static void mvDrivesInfoGetChannelRescanParams(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                               MV_U8 channelIndex,
+                                               MV_U16 *drivesToRemove,
+                                               MV_U16 *drivesToAdd)
+{
+    MV_U8 PMPort;
+
+    *drivesToRemove = 0;
+    *drivesToAdd = 0;
+
+    for (PMPort = 0; PMPort < MV_SATA_PM_MAX_PORTS; PMPort++)
+    {
+        if (ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotCurrent
+            & (1 << PMPort))
+        {
+            if (ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotSaved
+                & (1 << PMPort))
+            {
+                if (memcmp(&ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialCurrent[PMPort].serial,
+                           &ialExt->IALChannelExt[channelIndex].drivesInfo.driveSerialSaved[PMPort].serial,
+                           IDEN_SERIAL_NUM_SIZE))
+                {
+                    /*Disk drive connected to port is replaced*/
+                    *drivesToAdd |= (1 << PMPort);
+                    *drivesToRemove |= (1 << PMPort);
+                }
+            }
+            else
+            {
+                /*New drive connected to port*/
+                *drivesToAdd |= (1 << PMPort);
+            }
+        }
+        else
+        {
+            /*Drive removed from Port*/
+            if (ialExt->IALChannelExt[channelIndex].drivesInfo.drivesSnapshotSaved
+                & (1 << PMPort))
+            {
+                *drivesToRemove |= (1 << PMPort);
+            }
+        }
+    }
+}
+
+
+
+/*SCSI command queue functions*/
+static void mvAddToSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                    MV_U8 channelIndex,
+                                    MV_SATA_SCSI_CMD_BLOCK *pScb)
+{
+
+    MV_SATA_SCSI_CMD_BLOCK *cmdBlock = (MV_SATA_SCSI_CMD_BLOCK *)
+                                       ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue;
+    pScb->pNext = NULL;
+    if (cmdBlock)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d] Adding next command to SW queue\n",
+                 ialExt->pSataAdapter->adapterId, channelIndex);
+        while (cmdBlock->pNext)
+        {
+            cmdBlock = cmdBlock->pNext;
+        }
+        cmdBlock->pNext = pScb;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d] Adding first command to SW queue\n",
+                 ialExt->pSataAdapter->adapterId, channelIndex);
+        ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue =
+        (MV_VOID_PTR)pScb;
+    }
+}
+
+MV_BOOLEAN mvRemoveFromSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_U8 channelIndex,
+                                        MV_SATA_SCSI_CMD_BLOCK *pScb)
+{
+
+    MV_SATA_SCSI_CMD_BLOCK *cmdBlock = (MV_SATA_SCSI_CMD_BLOCK *)
+                                       ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue;
+    pScb->pNext = NULL;
+    if (cmdBlock)
+    {
+        if (cmdBlock == pScb)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d] Removing command"
+                     " %p from head of SW queue\n",
+                     ialExt->pSataAdapter->adapterId,channelIndex, pScb);
+            ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue =
+            (MV_VOID_PTR) cmdBlock->pNext;
+            return MV_TRUE;
+        }
+        else
+        {
+            while (cmdBlock->pNext)
+            {
+                if (cmdBlock->pNext == pScb)
+                {
+                    break;
+                }
+                cmdBlock = cmdBlock->pNext;
+            }
+            if (cmdBlock->pNext == NULL)
+            {
+                mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d] Removing"
+                         " command %p from SW queue failed. command not found\n",
+                         ialExt->pSataAdapter->adapterId,channelIndex, pScb);
+                return MV_FALSE;
+            }
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d] Removing command"
+                     " %p from SW queue\n", ialExt->pSataAdapter->adapterId,
+                     channelIndex, pScb);
+            cmdBlock->pNext = cmdBlock->pNext->pNext;
+            return MV_TRUE;
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d] Removing"
+                 " command %p from SW queue failed. queue empty\n",
+                 ialExt->pSataAdapter->adapterId,channelIndex, pScb);
+        return MV_FALSE;
+    }
+    return MV_FALSE;
+}
+
+static void mvFlushSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                    MV_U8 channelIndex)
+{
+    /*Abort all pending commands in SW queue*/
+    MV_SATA_SCSI_CMD_BLOCK *cmdBlock = (MV_SATA_SCSI_CMD_BLOCK *)
+                                       ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue;
+
+    while (cmdBlock)
+    {
+        MV_SATA_SCSI_CMD_BLOCK *nextBlock = cmdBlock->pNext;
+        if (cmdBlock->completionCallBack)
+        {
+            cmdBlock->ScsiStatus = MV_SCSI_STATUS_BUSY;
+            cmdBlock->dataTransfered = 0;
+            cmdBlock->ScsiCommandCompletion = MV_SCSI_COMPLETION_QUEUE_FULL;
+            cmdBlock->completionCallBack(ialExt->pSataAdapter, cmdBlock);
+        }
+        cmdBlock = nextBlock;
+    }
+    ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue = NULL;
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: Flush command queue is done\n",
+             ialExt->pSataAdapter->adapterId, channelIndex);
+}
+
+
+/*Port Multilier related functions*/
+static MV_BOOLEAN mvPMCommandCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
+                                          MV_U8 channelIndex,
+                                          MV_COMPLETION_TYPE comp_type,
+                                          MV_VOID_PTR commandId,
+                                          MV_U16 responseFlags,
+                                          MV_U32 timeStamp,
+                                          MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+    MV_U32 value;
+    MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt =
+    (MV_IAL_COMMON_ADAPTER_EXTENSION *)commandId;
+    ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress = MV_FALSE;
+    switch (comp_type)
+    {
+    case MV_COMPLETION_TYPE_NORMAL:
+        if (ialExt->IALChannelExt[channelIndex].pmAccessType
+            == MV_ATA_COMMAND_PM_READ_REG)
+        {
+            value = registerStruct->sectorCountRegister;
+            value |= (registerStruct->lbaLowRegister << 8);
+            value |= (registerStruct->lbaMidRegister << 16);
+            value |= (registerStruct->lbaMidRegister << 24);
+            if (ialExt->IALChannelExt[channelIndex].pmReg
+                == MV_SATA_GSCR_ERROR_REG_NUM)
+            {
+                if (value != 0)
+                {
+                    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: PM GSCR[32] = 0x%X\n",
+                             pSataAdapter->adapterId, channelIndex, value);
+                    ialExt->IALChannelExt[channelIndex].PMdevsToInit =
+                    (MV_U16)(value & 0x7FFF);
+                    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: "
+                             "PM Hot plug detected "
+                             "Bitmask = 0x%X\n",
+                             pSataAdapter->adapterId, channelIndex,
+                             ialExt->IALChannelExt[channelIndex].PMdevsToInit);
+                    mvSetChannelState(ialExt, channelIndex,
+                                      CHANNEL_PM_HOT_PLUG);
+                }
+            }
+        }
+        break;
+    case MV_COMPLETION_TYPE_ABORT:
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: read PM register aborted!\n",
+                 pSataAdapter->adapterId, channelIndex);
+
+        break;
+    case MV_COMPLETION_TYPE_ERROR:
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: read PM register error!\n",
+                 pSataAdapter->adapterId, channelIndex);
+        break;
+    default:
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Unknown completion type (%d)\n",
+                 pSataAdapter->adapterId, channelIndex, comp_type);
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+
+
+static MV_BOOLEAN mvQueuePMAccessRegisterCommand(
+                                                MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
+                                                MV_U8 channelIndex,
+                                                MV_U8 PMPort,
+                                                MV_U8 PMReg,
+                                                MV_U32 Value,
+                                                MV_BOOLEAN isRead)
+{
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO *pCommandInfo = &ialExt->IALChannelExt[channelIndex].commandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO commandInfo, *pCommandInfo;
+    pCommandInfo = &commandInfo;
+#endif
+    memset(pCommandInfo, 0, sizeof(MV_QUEUE_COMMAND_INFO));
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType =
+    MV_NON_UDMA_PROTOCOL_NON_DATA;
+    pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_TRUE;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = NULL;
+    pCommandInfo->PMPort = MV_SATA_PM_CONTROL_PORT;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.features = PMReg;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = (MV_U8)PMPort;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack =
+    mvPMCommandCompletionCB;
+
+    ialExt->IALChannelExt[channelIndex].pmReg = PMReg;
+
+    if (isRead == MV_TRUE)
+    {
+        ialExt->IALChannelExt[channelIndex].pmAccessType =
+        MV_ATA_COMMAND_PM_READ_REG;
+        pCommandInfo->commandParams.NoneUdmaCommand.command =
+        MV_ATA_COMMAND_PM_READ_REG;
+        pCommandInfo->commandParams.NoneUdmaCommand.commandId =
+        (MV_VOID_PTR)ialExt;
+        pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = 0;
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = 0;
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = 0;
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = 0;
+    }
+    else
+    {
+        ialExt->IALChannelExt[channelIndex].pmAccessType =
+        MV_ATA_COMMAND_PM_WRITE_REG;
+        pCommandInfo->commandParams.NoneUdmaCommand.command =
+        MV_ATA_COMMAND_PM_WRITE_REG;
+        pCommandInfo->commandParams.NoneUdmaCommand.commandId =
+        (MV_VOID_PTR)ialExt;
+        pCommandInfo->commandParams.NoneUdmaCommand.sectorCount =
+        (MV_U16)((Value) & 0xff),
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaLow =
+        (MV_U16)(((Value) & 0xff00) >> 8);
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaMid =
+        (MV_U16)(((Value) & 0xff0000) >> 16);
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh =
+        (MV_U16)(((Value) & 0xff000000) >> 24);
+    }
+    ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress = MV_TRUE;
+    result = mvSataQueueCommand(pSataAdapter,
+                                channelIndex,
+                                pCommandInfo);
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        switch (result)
+        {
+        case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS:
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command failed. Bad LBA "
+                     "\n");
+            break;
+        case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED:
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command failed. EDMA"
+                     " disabled adapter %d channel %d\n",
+                     pSataAdapter->adapterId, channelIndex);
+            break;
+        case MV_QUEUE_COMMAND_RESULT_FULL:
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command failed. Queue is"
+                     " Full adapter %d channel %d\n",
+                     pSataAdapter->adapterId, channelIndex);
+
+            break;
+        case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS:
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command failed. (Bad "
+                     "Params), pMvSataAdapter: %p, pSataChannel: %p.\n",
+                     pSataAdapter, pSataAdapter->sataChannel[channelIndex]);
+            break;
+        default:
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command bad result value (%d) "
+                     "from queue command\n",
+                     result);
+        }
+        ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress = MV_FALSE;
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+
+
+static MV_BOOLEAN mvPMEnableCommStatusChangeBits(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                                 MV_U8 channelIndex,
+                                                 MV_BOOLEAN enable)
+{
+    MV_U32 regVal;
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+
+    if (enable == MV_TRUE)
+    {
+        regVal = MV_BIT16;
+    }
+    else
+    {
+        regVal = 0;
+    }
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: Set PM "
+             "GSCR[33] register to 0x%X\n",
+             pSataAdapter->adapterId, channelIndex, regVal);
+    /*Set N bit reflection in PM GSCR*/
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex,
+                        MV_SATA_PM_CONTROL_PORT,
+                        MV_SATA_GSCR_ERROR_ENABLE_REG_NUM,
+                        regVal, NULL) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Failed to set "
+                 "PortMultiplier Features Enable register\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+
+static MV_BOOLEAN mvPMEnableAsyncNotify(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_U8 channelIndex)
+{
+    MV_U32 regVal1, regVal2;
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    /*Features register*/
+    if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                       MV_SATA_GSCR_FEATURES_REG_NUM,
+                       &regVal1, NULL) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Failed to get Port Multiplier Features"
+                 " supported register\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: Port Multiplier features supported: 0x%X\n",
+             pSataAdapter->adapterId, channelIndex, regVal1);
+
+    /*PM asynchronous notification supported*/
+    if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                       MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM,
+                       &regVal2 ,NULL) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Failed to get Port Multiplier Features"
+                 " register\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+
+    }
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: Port Multiplier features enabled "
+             "register: 0x%X\n",
+             pSataAdapter->adapterId, channelIndex, regVal2);
+    if (regVal1 & MV_BIT3)
+    {
+        regVal2 |= MV_BIT3;
+        if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                            MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM,
+                            regVal2 ,NULL) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Failed to set "
+                     "PortMultiplier Features Enable register\n",
+                     pSataAdapter->adapterId, channelIndex);
+            return MV_FALSE;
+
+        }
+        ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled = MV_TRUE;
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: PM asynchronous notification is "
+                 "enabled.\n", pSataAdapter->adapterId, channelIndex);
+    }
+    else
+    {
+        regVal2 &= ~MV_BIT3;
+        if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                            MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM,
+                            regVal2 ,NULL) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Failed to set "
+                     "PortMultiplier Features Enable register\n",
+                     pSataAdapter->adapterId, channelIndex);
+            return MV_FALSE;
+
+        }
+        ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled = MV_FALSE;
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: PM asynchronous notification is "
+                 "disabled.\n", pSataAdapter->adapterId, channelIndex);
+    }
+
+    return MV_TRUE;
+}
+
+static MV_BOOLEAN mvPMDisableAsyncNotify(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_U8 channelIndex)
+{
+    MV_U32 regVal2;
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+
+
+    /*PM asynchronous notification supported*/
+    if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                       MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM,
+                       &regVal2 ,NULL) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Failed to get Port Multiplier Features"
+                 " register\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+
+    }
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: Port Multiplier features enabled "
+             "register: 0x%X\n",
+             pSataAdapter->adapterId, channelIndex, regVal2);
+
+        regVal2 &= ~MV_BIT3;
+        if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                            MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM,
+                            regVal2 ,NULL) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Failed to set "
+                     "PortMultiplier Features Enable register\n",
+                     pSataAdapter->adapterId, channelIndex);
+            return MV_FALSE;
+
+        }
+        ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled = MV_FALSE;
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: PM asynchronous notification is "
+                 "disabled.\n", pSataAdapter->adapterId, channelIndex);
+
+    return MV_TRUE;
+}
+
+
+
+static MV_BOOLEAN mvConfigurePMDevice(
+                                     MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                     MV_U8 channelIndex)
+{
+    MV_SATA_PM_DEVICE_INFO PMInfo;
+    ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled = MV_FALSE;
+
+    if (mvGetPMDeviceInfo(ialExt->pSataAdapter, channelIndex, &PMInfo)
+        == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Failed to get PortMultiplier Info\n",
+                 ialExt->pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: PM of %d ports found\n",
+             ialExt->pSataAdapter->adapterId, channelIndex,
+             PMInfo.numberOfPorts);
+    ialExt->IALChannelExt[channelIndex].PMnumberOfPorts = PMInfo.numberOfPorts;
+#ifdef DISABLE_PM_SCC
+    if (PMInfo.vendorId == 0x11AB)
+    {
+
+        if (mvPMDisableSSC(ialExt->pSataAdapter, channelIndex) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: cannot disable SSC for PM.\n"
+                     "unknown vendor.\n",
+                     ialExt->pSataAdapter->adapterId, channelIndex);
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: cannot disable SSC for PM - "
+                 "unknown vendor.\n",
+                 ialExt->pSataAdapter->adapterId, channelIndex);
+    }
+#endif
+#if 1
+    if (clearSErrorPorts(ialExt->pSataAdapter, channelIndex,
+			 ialExt->IALChannelExt[channelIndex].PMnumberOfPorts) != 
+	MV_TRUE)
+    {
+	    return MV_FALSE;
+    }
+#endif
+    if (mvPMEnableCommStatusChangeBits(ialExt,
+                                       channelIndex,
+                                       MV_FALSE) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    if (mvPMDisableAsyncNotify(ialExt, channelIndex) == MV_FALSE)
+    {
+        return MV_FALSE;
+    }
+#if 0
+
+    if (mvPMDevEnableStaggeredSpinUpAll(ialExt->pSataAdapter,
+                                        channelIndex,
+                                        ialExt->IALChannelExt[channelIndex].PMnumberOfPorts,
+                                        &ialExt->IALChannelExt[channelIndex].PMdevsToInit) == MV_FALSE)
+    {
+	 mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: PM Enable Staggered Spin-\
+Up Failed\n",
+		  ialExt->pSataAdapter->adapterId, channelIndex);
+	 ialExt->IALChannelExt[channelIndex].PMdevsToInit = 0;
+	 return MV_FALSE;
+    }
+#endif
+    return MV_TRUE;
+}
+
+static MV_BOOLEAN clearSErrorPorts(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex, 
+				   MV_U8     PMnumberOfPorts)
+{
+	MV_U8 PMPort;
+	
+	for (PMPort = 0; PMPort < PMnumberOfPorts; PMPort++)
+	{
+		if (mvPMDevWriteReg(pSataAdapter, channelIndex, PMPort,
+				    MV_SATA_PSCR_SERROR_REG_NUM, 0xFFFFFFFF, NULL) ==
+		    MV_FALSE)
+		{
+			if (mvStorageDevATASoftResetDevice(pSataAdapter, channelIndex,
+							   MV_SATA_PM_CONTROL_PORT, NULL) == MV_FALSE)
+			{
+				mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
+					 "failed to Soft Reset PM control port\n",
+					 pSataAdapter->adapterId, channelIndex);
+				return MV_FALSE;
+			}
+		}
+	}
+	return MV_TRUE;
+}
+
+MV_BOOLEAN mvPMEnableLocking(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex)
+{
+    MV_STORAGE_DEVICE_REGISTERS regs;
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex,
+                        MV_SATA_PM_CONTROL_PORT,
+                        0x89,
+                        0x8000003F,
+                        &regs) == MV_TRUE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: NCQ lock is enabled for PM.\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_TRUE;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: cannot enable NCQ lock for PM.\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+
+#ifdef DISABLE_PM_SCC
+MV_BOOLEAN mvPMDisableSSC(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex)
+{
+    MV_STORAGE_DEVICE_REGISTERS regs;
+    MV_U32 regVal = 0;
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: "
+             "Disable SSC for all PM ports.\n",
+             pSataAdapter->adapterId, channelIndex);
+
+    if (mvPMDevReadReg(pSataAdapter,channelIndex, MV_SATA_PM_CONTROL_PORT,
+                       MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM,
+                       &regVal,
+                       &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+
+    /*Host SSC disable*/
+    regVal &= ~MV_BIT2;
+    if (mvPMDevWriteReg(pSataAdapter,channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM,
+                        regVal,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+
+    /* disable ssc for port 0*/
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x8C,
+                        0,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x92,
+                        0xb02a402a,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    /* disable ssc for port 1*/
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x8C,
+                        1,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x92,
+                        0xb02a402a,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    /* disable ssc for port 2*/
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x8C,
+                        2,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x92,
+                        0xb02a402a,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+
+    /* disable ssc for port 3*/
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x8C,
+                        3,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x92,
+                        0xb02a402a,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+
+    /* disable ssc for port 15*/
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x8C,
+                        MV_SATA_PM_CONTROL_PORT,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                        0x92,
+                        0xb02a402a,
+                        &regs) != MV_TRUE)
+    {
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+#endif
+
+static MV_BOOLEAN mvConfigChannelQueuingMode(MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
+                                             MV_U8 channelIndex,
+                                             MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_SATA_ADAPTER         *pSataAdapter = ialExt->pSataAdapter;
+    MV_EDMA_MODE            EDMAMode = MV_EDMA_MODE_NOT_QUEUED;
+    MV_SATA_SWITCHING_MODE  switchingMode;
+    MV_BOOLEAN              isTCQSupported = MV_FALSE;
+    MV_BOOLEAN              isNCQSupported = MV_FALSE;
+    MV_U8                   numOfDrives = 0;
+    MV_SATA_PM_DEVICE_INFO  PMInfo;
+    MV_SATA_DEVICE_TYPE     connectedDevice;
+    MV_BOOLEAN              use128Entries = MV_FALSE;
+
+
+    if (mvGetDisksModes(ialExt,
+                        scsiAdapterExt,
+                        channelIndex,
+                        &isTCQSupported,
+                        &isNCQSupported,
+                        &numOfDrives) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,
+                 "[%d %d]:mvConfigChannelQueuingMode: failed to get disks modes.\n"
+                 ,pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    else
+    {
+
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: Supported queuing mode: TCQ = %s, "
+                 "NCQ = %s. number of disks %d\n",
+                 pSataAdapter->adapterId, channelIndex,
+                 (isTCQSupported == MV_TRUE) ? "Yes" : "No",
+                 (isNCQSupported == MV_TRUE) ? "Yes" : "No",
+                 numOfDrives);
+    }
+    connectedDevice = mvStorageDevGetDeviceType(pSataAdapter,channelIndex);
+    if (connectedDevice == MV_SATA_DEVICE_TYPE_UNKNOWN)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,
+                 "[%d %d] mvConfigChannelQueuingMode: failed to get device type.\n"
+                 ,pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    if (connectedDevice == MV_SATA_DEVICE_TYPE_PM)
+    {
+        if (mvGetPMDeviceInfo(ialExt->pSataAdapter, channelIndex, &PMInfo)
+            == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,
+                     "[%d %d] mvConfigChannelQueuingMode: Failed to get "
+                     "PortMultiplier Info\n",
+                     ialExt->pSataAdapter->adapterId, channelIndex);
+            return MV_FALSE;
+        }
+    }
+    mvSelectConfiguration(pSataAdapter, channelIndex,
+                          pSataAdapter->sataAdapterGeneration,
+                          connectedDevice,&PMInfo,
+                          isNCQSupported,
+                          isTCQSupported,
+                          numOfDrives,
+                          &EDMAMode,
+                          &switchingMode,
+                          &use128Entries);
+
+#ifndef MV_SATA_SUPPORT_GEN2E_128_QUEUE_LEN
+    use128Entries = MV_FALSE;
+#endif
+    switch (switchingMode)
+    {
+    case MV_SATA_SWITCHING_MODE_FBS:
+        {
+            if (mvSataSetFBSMode(pSataAdapter, channelIndex, MV_TRUE,
+                                 use128Entries) == MV_FALSE)
+            {
+                mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,
+                         "[%d %d] mvConfigChannelQueuingMode: failed to enable FBS.\n"
+                         ,pSataAdapter->adapterId, channelIndex);
+                return MV_FALSE;
+            }
+        }
+        break;
+    case MV_SATA_SWITCHING_MODE_QCBS:
+        if (mvPMEnableLocking(pSataAdapter,channelIndex) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,
+                     "[%d %d] mvConfigChannelQueuingMode: failed to enable QCBS.\n"
+                     ,pSataAdapter->adapterId, channelIndex);
+            return MV_FALSE;
+        }
+        break;
+    default:
+        break;
+    }         
+    IALConfigQueuingMode(pSataAdapter,
+                         channelIndex,
+                         EDMAMode,
+                         switchingMode,
+                         use128Entries);
+    return MV_TRUE;
+}
+
+
+
+/*Channel related functions*/
+
+static void mvSetChannelState(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                              MV_U8 channelIndex,
+                              MV_CHANNEL_STATE state)
+{
+    if (ialExt->channelState[channelIndex] != state)
+    {
+        if ((state == CHANNEL_READY) || (state == CHANNEL_NOT_CONNECTED))
+        {
+            ialExt->IALChannelExt[channelIndex].SRSTTimerThreshold = 0;
+            ialExt->IALChannelExt[channelIndex].SRSTTimerValue = 0;
+        }
+        if (state == CHANNEL_READY)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: CHANNEL_READY\n",
+                     ialExt->pSataAdapter->adapterId,
+                     channelIndex);
+            ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress
+            = MV_FALSE;
+            ialExt->IALChannelExt[channelIndex].completionError = MV_FALSE;
+            ialExt->channelState[channelIndex] = state;
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d] flush pending queue\n",
+                     ialExt->pSataAdapter->adapterId, channelIndex);
+            /*Abort all pending commands in SW queue*/
+            mvFlushSCSICommandQueue(ialExt, channelIndex);
+            if (MV_TRUE == ialExt->IALChannelExt[channelIndex].bHotPlug)
+            {
+                MV_U16 drivesToRemove;
+                MV_U16 drivesToAdd;
+                ialExt->IALChannelExt[channelIndex].bHotPlug = MV_FALSE;
+                mvDrivesInfoGetChannelRescanParams(ialExt,
+                                                   channelIndex,
+                                                   &drivesToRemove,
+                                                   &drivesToAdd);
+                if (drivesToRemove != 0 || drivesToAdd != 0)
+                {
+
+                    IALBusChangeNotifyEx(ialExt->pSataAdapter,
+                                         channelIndex,
+                                         drivesToRemove,
+                                         drivesToAdd);
+                }
+            }
+            mvDrivesInfoSaveAll(ialExt, channelIndex);
+        }
+        else
+        {
+            ialExt->channelState[channelIndex] = state;
+        }
+    }
+}
+
+
+static MV_BOOLEAN mvStartChannelInit(MV_SATA_ADAPTER *pSataAdapter,
+                                     MV_U8 channelIndex,
+                                     MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+                                     MV_BOOLEAN* bIsChannelReady)
+{
+    *bIsChannelReady = MV_FALSE;
+
+    if (mvSataConfigureChannel(pSataAdapter, channelIndex) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: configure channel failed\n",
+                 pSataAdapter->adapterId,
+                 channelIndex);
+        return MV_FALSE;
+    }
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: start channel\n",
+             pSataAdapter->adapterId,
+             channelIndex);
+    /*Just check SStatus in case of SATA I adapter*/
+    if (pSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: starting SATA I channel.\n",
+                 pSataAdapter->adapterId, channelIndex);
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: starting SATA II channel.\n",
+                 pSataAdapter->adapterId, channelIndex);
+    }
+
+    return mvStorageDevATAStartSoftResetDevice(pSataAdapter,
+                                               channelIndex,
+                                               MV_SATA_PM_CONTROL_PORT);
+}
+
+static MV_BOOLEAN mvChannelSRSTFinished(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_SATA_CHANNEL *pSataChannel,
+                                        MV_U8 channelIndex,
+                                        MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+                                        MV_BOOLEAN* bIsChannelReady,
+                                        MV_BOOLEAN* bFatalError)
+{
+    MV_SATA_DEVICE_TYPE deviceType;
+    MV_STORAGE_DEVICE_REGISTERS mvStorageDevRegisters;
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData;
+    *bIsChannelReady = MV_FALSE;
+    *bFatalError = MV_FALSE;
+    if (pSataAdapter->sataAdapterGeneration > MV_SATA_GEN_I)
+    {
+        if (mvStorageIsDeviceBsyBitOff(pSataAdapter,
+                                       channelIndex,
+                                       &mvStorageDevRegisters)
+            == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: soft Reset PM control port "
+                     "in progress\n",
+                     pSataAdapter->adapterId, channelIndex);
+            printAtaDeviceRegisters(&mvStorageDevRegisters);
+            return MV_FALSE;
+        }
+        deviceType = mvGetSataDeviceType(&mvStorageDevRegisters);
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: soft reset SATA II channel - "
+                 "device ready.\n",
+                 pSataAdapter->adapterId, channelIndex);
+    }
+    else
+    {
+        if (mvStorageIsDeviceBsyBitOff(pSataAdapter,
+                                       channelIndex,
+                                       &mvStorageDevRegisters)
+            == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: soft reset of SATA I channel "
+                     "in progress\n",
+                     pSataAdapter->adapterId, channelIndex);
+            printAtaDeviceRegisters(&mvStorageDevRegisters);
+            return MV_FALSE;
+        }
+        deviceType = mvGetSataDeviceType(&mvStorageDevRegisters);
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: soft reset SATA I channel - "
+                 "device ready.\n",
+                 pSataAdapter->adapterId, channelIndex);
+        deviceType = mvGetSataDeviceType(&mvStorageDevRegisters);
+        if (deviceType != MV_SATA_DEVICE_TYPE_ATA_DISK)
+        {
+            deviceType = MV_SATA_DEVICE_TYPE_UNKNOWN;
+        }
+
+    }
+    switch (deviceType)
+    {
+    case MV_SATA_DEVICE_TYPE_ATA_DISK:
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO,"[%d %d]: SATA disk found\n",
+                 pSataAdapter->adapterId, channelIndex);
+        if (mvStorageDevSetDeviceType(pSataAdapter,channelIndex, deviceType) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: Failed to initialize disk\n",
+                     pSataAdapter->adapterId, channelIndex);
+            *bFatalError = MV_TRUE;
+            return MV_FALSE;
+
+        }
+        pDriveData = &scsiAdapterExt->ataDriveData[channelIndex][0];
+        if (mvInitSataDisk(pSataAdapter,
+                           channelIndex,
+                           0,
+                           &pDriveData->identifyInfo,
+                           pDriveData->identifyBuffer) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: Failed to initialize disk\n",
+                     pSataAdapter->adapterId, channelIndex);
+            *bFatalError = MV_TRUE;
+            mvDrivesInfoFlushSingleDrive(ialExt,
+                                         channelIndex,
+                                         0);
+            return MV_FALSE;
+        }
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO,"[%d %d]: Disk ready\n",
+                 pSataAdapter->adapterId, channelIndex);
+        mvSetDriveReady(ialExt,
+                        scsiAdapterExt,
+                        channelIndex,
+                        0,
+                        MV_TRUE,
+                        pDriveData->identifyBuffer);
+        mvSataScsiNotifyUA(scsiAdapterExt, channelIndex, 0);
+        *bIsChannelReady = MV_TRUE;
+        return MV_TRUE;
+        break;
+    case MV_SATA_DEVICE_TYPE_PM:
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO,"[%d %d]: PortMultiplier device found\n",
+                 pSataAdapter->adapterId, channelIndex);
+        if (mvStorageDevSetDeviceType(pSataAdapter,channelIndex, deviceType) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: Failed to initialize PM\n",
+                     pSataAdapter->adapterId, channelIndex);
+            *bFatalError = MV_TRUE;
+            return MV_FALSE;
+
+        }
+        break;
+#ifdef MV_SUPPORT_ATAPI
+    case MV_SATA_DEVICE_TYPE_ATAPI_DEVICE:
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO,"[%d %d]: ATAPI device found\n",
+                 pSataAdapter->adapterId, channelIndex);
+        if (mvStorageDevSetDeviceType(pSataAdapter,channelIndex, deviceType) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: Failed to initialize ATAPI device\n",
+                     pSataAdapter->adapterId, channelIndex);
+            *bFatalError = MV_TRUE;
+            return MV_FALSE;
+
+        }
+        pDriveData = &scsiAdapterExt->ataDriveData[channelIndex][0];
+        if (mvInitSataATAPI(pSataAdapter,
+                           channelIndex,
+                           0,
+                           &pDriveData->identifyInfo,
+                           pDriveData->identifyBuffer) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: Failed to initialize ATAPI device\n",
+                     pSataAdapter->adapterId, channelIndex);
+            *bFatalError = MV_TRUE;
+            mvDrivesInfoFlushSingleDrive(ialExt,
+                                         channelIndex,
+                                         0);
+            return MV_FALSE;
+        }
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO,"[%d %d]: ATAPI Device ready\n",
+                 pSataAdapter->adapterId, channelIndex);
+
+        mvSetDriveReady(ialExt,
+                        scsiAdapterExt,
+                        channelIndex,
+                        0,
+                        MV_TRUE,
+                        pDriveData->identifyBuffer);
+
+
+        mvSataScsiNotifyUA(scsiAdapterExt, channelIndex, 0);
+        *bIsChannelReady = MV_TRUE;
+        return MV_TRUE;
+         break;
+#endif
+    default:
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: ERROR: unknown device type\n",
+                 pSataAdapter->adapterId, channelIndex);
+        *bFatalError    =    MV_TRUE;
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+
+
+
+static MV_BOOLEAN mvConfigChannelDMA(
+                                    MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
+                                    MV_U8 channelIndex,
+                                    MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d] config queueing mode\n",
+             pSataAdapter->adapterId, channelIndex);
+
+
+    if (mvConfigChannelQueuingMode(ialExt,
+                                   channelIndex,
+                                   scsiAdapterExt)
+        == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d] Failed to config DMA queuing\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    /* Enable EDMA */
+    if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d] Failed to enable DMA, channel=%d\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d]: channel started successfully\n",
+             pSataAdapter->adapterId, channelIndex);
+    return MV_TRUE;
+}
+
+
+
+
+
+static void mvSetChannelTimer(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                              MV_U8 channelIndex,
+                              MV_U32 timeout)
+{
+    ialExt->IALChannelExt[channelIndex].SRSTTimerThreshold = timeout;
+    ialExt->IALChannelExt[channelIndex].SRSTTimerValue = 1;
+}
+
+static void mvDecrementChannelTimer(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                    MV_U8 channelIndex)
+{
+    if (ialExt->IALChannelExt[channelIndex].SRSTTimerThreshold > 0)
+    {
+        ialExt->IALChannelExt[channelIndex].SRSTTimerValue +=
+        MV_IAL_ASYNC_TIMER_PERIOD;
+    }
+}
+
+static MV_BOOLEAN mvIsChannelTimerExpired(
+                                         MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                         MV_U8 channelIndex)
+{
+    if (ialExt->IALChannelExt[channelIndex].SRSTTimerValue >
+        ialExt->IALChannelExt[channelIndex].SRSTTimerThreshold)
+    {
+        return MV_TRUE;
+    }
+    else
+    {
+        return MV_FALSE;
+    }
+}
+
+/*******************************************************************************
+*State Machine related functions:
+*  Return MV_TRUE to proceed to the next channel
+*  Return MV_FALSE to proceed to the next state on current channel
+*******************************************************************************/
+
+static MV_BOOLEAN mvChannelNotConnectedStateHandler(
+                                                   MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                                   MV_U8 channelIndex,
+                                                   MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    if (pSataAdapter->sataChannel[channelIndex] != NULL)
+    {
+        mvSataRemoveChannel(pSataAdapter,channelIndex);
+        pSataAdapter->sataChannel[channelIndex] = NULL;
+        mvSetDriveReady(ialExt,
+                        scsiAdapterExt,
+                        channelIndex,
+                        0xFF, MV_FALSE, NULL);
+        mvFlushSCSICommandQueue(ialExt, channelIndex);
+    }
+    return MV_TRUE;
+}
+
+
+static MV_BOOLEAN mvChannelConnectedStateHandler(
+     MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+     MV_U8 channelIndex,
+     MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+     MV_BOOLEAN res = MV_FALSE;
+     MV_BOOLEAN isChannelReady;
+     MV_SATA_CHANNEL *pSataChannel;
+     MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+     
+     mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d] CHANNEL_CONNECTED\n",
+	      ialExt->pSataAdapter->adapterId, channelIndex);
+     if (pSataAdapter->sataChannel[channelIndex] == NULL)
+    {
+	 if (IALInitChannel(pSataAdapter, channelIndex) == MV_FALSE)
+	 {
+	      IALReleaseChannel(pSataAdapter, channelIndex);
+	      mvDrivesInfoFlushAll(ialExt, channelIndex);
+	      mvSetChannelState(ialExt, channelIndex, CHANNEL_NOT_CONNECTED);
+	      return MV_TRUE;
+	 }
+    }
+     pSataChannel = pSataAdapter->sataChannel[channelIndex];
+     res = mvStartChannelInit(pSataAdapter,
+			      channelIndex,
+			      scsiAdapterExt,
+			      &isChannelReady);
+     if (res == MV_TRUE)
+     {
+	  if (isChannelReady == MV_FALSE)
+	  {
+	       /*SRST channel, Set polling timer*/
+            mvSetChannelTimer(ialExt, channelIndex,
+                              MV_IAL_SRST_TIMEOUT);
+            mvSetChannelState(ialExt,
+                              channelIndex,
+                              CHANNEL_IN_SRST);
+	  }
+	  else
+	  {
+            if (mvConfigChannelDMA(ialExt,
+                                   channelIndex,
+                                   scsiAdapterExt) == MV_TRUE)
+            {
+		 mvSetChannelState(ialExt,
+				   channelIndex,
+				   CHANNEL_READY);
+            }
+            else
+            {
+		 mvStopChannel(ialExt,
+			       channelIndex,
+			       scsiAdapterExt);
+            }
+	  }
+    }
+     else
+     {
+	  mvStopChannel(ialExt,
+			channelIndex,
+			scsiAdapterExt);
+     }
+     return MV_TRUE;
+}
+
+
+MV_BOOLEAN mvChannelInSrstStateHandler(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                       MV_U8 channelIndex,
+                                       MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_BOOLEAN bFatalError;
+    MV_BOOLEAN res = MV_FALSE;
+    MV_BOOLEAN isChannelReady;
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    MV_SATA_CHANNEL *pSataChannel = pSataAdapter->sataChannel[channelIndex];
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d] CHANNEL_IN_SRST\n",
+             pSataAdapter->adapterId, channelIndex);
+    mvDecrementChannelTimer(ialExt, channelIndex);
+    res = mvChannelSRSTFinished(ialExt,
+                                pSataChannel,
+                                channelIndex,
+                                scsiAdapterExt,
+                                &isChannelReady,
+                                &bFatalError);
+    if (res == MV_TRUE)
+    {
+        /*Finishing channel initialization*/
+        if (isChannelReady == MV_TRUE)
+        {
+	     mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO,"[%d %d]: Sata device ready\n",
+		      pSataAdapter->adapterId,channelIndex);
+            if (mvConfigChannelDMA(ialExt,
+                                   channelIndex,
+                                   scsiAdapterExt) == MV_TRUE)
+            {
+                mvSetChannelState(ialExt,
+                                  channelIndex,
+                                  CHANNEL_READY);
+            }
+            else
+            {
+                mvStopChannel(ialExt,
+                              channelIndex,
+                              scsiAdapterExt);
+            }
+        }
+        else
+        {/*If channel not ready and function call succeed -> PM is found*/
+            if (mvConfigurePMDevice(ialExt, channelIndex) == MV_FALSE)
+            {
+                mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: Failed to "
+                         "initialize PM\n",
+                         pSataAdapter->adapterId,channelIndex);
+#if 0               
+		mvStopChannel(ialExt,
+                              channelIndex,
+                              scsiAdapterExt);
+#else
+		mvSataChannelHardReset(pSataAdapter, channelIndex);
+		mvRestartChannel(ialExt, channelIndex, scsiAdapterExt, MV_FALSE);
+#endif
+            }
+            else
+            {
+		 MV_IAL_COMMON_CHANNEL_EXTENSION* channelExt = 
+		      &ialExt->IALChannelExt[channelIndex];
+		 
+		 channelExt->port_state = MV_PORT_NOT_INITIALIZED;
+		 channelExt->devInSRST = 0;
+		 
+                mvSetChannelState(ialExt, channelIndex,
+                                  CHANNEL_PM_INIT_DEVICES);
+                return MV_FALSE;
+            }
+        }
+    }
+    else
+    {
+        if (bFatalError == MV_TRUE)
+        {
+            mvStopChannel(ialExt,
+                          channelIndex,
+                          scsiAdapterExt);
+        }
+        else
+        {
+            if (mvIsChannelTimerExpired(ialExt, channelIndex) == MV_TRUE)
+            {
+                mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,
+                         "[%d %d]: SW reset Failed, timer expired\n",
+                         pSataAdapter->adapterId,channelIndex);
+                mvStopChannel(ialExt,
+                              channelIndex,
+                              scsiAdapterExt);
+            }
+        }
+    }
+    return MV_TRUE;
+}
+
+MV_BOOLEAN classifyAndInitDevice(MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+				 MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+				 MV_U8 channelIndex, MV_U8 PMPort)
+{
+     
+     MV_SATA_DEVICE_TYPE deviceType;
+     MV_SATA_ADAPTER *pSataAdapter = scsiAdapterExt->pSataAdapter;
+     MV_IAL_COMMON_CHANNEL_EXTENSION* channelExt = &ialExt->IALChannelExt[channelIndex];
+     MV_SATA_SCSI_DRIVE_DATA *pDriveData = &scsiAdapterExt->ataDriveData[channelIndex][PMPort];
+     MV_STORAGE_DEVICE_REGISTERS *mvStorageDevRegisters = &channelExt->mvStorageDevRegisters;
+
+     deviceType = mvGetSataDeviceType(mvStorageDevRegisters);
+     if (deviceType == MV_SATA_DEVICE_TYPE_ATA_DISK)
+     {
+	  if (mvInitSataDisk(pSataAdapter,
+			     channelIndex ,
+			     PMPort, &pDriveData->identifyInfo,
+			     pDriveData->identifyBuffer) == MV_FALSE)
+	  {
+	       mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: Failed to initialize disk\n",
+			pSataAdapter->adapterId, channelIndex, PMPort);
+	       mvDrivesInfoFlushSingleDrive(ialExt, channelIndex, PMPort);
+	  }
+	  else
+	  {
+	       mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO, "[%d %d %d]: Disk ready\n",
+			pSataAdapter->adapterId, channelIndex, PMPort);
+	       mvSetDriveReady(ialExt,
+			       scsiAdapterExt,
+			       channelIndex, PMPort,
+			       MV_TRUE,
+			       pDriveData->identifyBuffer);
+	       mvSataScsiNotifyUA(scsiAdapterExt, channelIndex, PMPort);
+	  }
+     }
+#ifdef MV_SUPPORT_ATAPI
+     else if (deviceType == MV_SATA_DEVICE_TYPE_ATAPI_DEVICE)
+     {
+	  if (mvInitSataATAPI(pSataAdapter,
+			      channelIndex ,
+			      PMPort, &pDriveData->identifyInfo,
+			      pDriveData->identifyBuffer) == MV_FALSE)
+	  {
+	       mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: Failed to initialize ATAPI device\n",
+			pSataAdapter->adapterId, channelIndex, PMPort);
+                    mvDrivesInfoFlushSingleDrive(ialExt, channelIndex, PMPort);
+	  }
+	  else
+	  {
+	       mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO, "[%d %d %d]: ATAPI device ready\n",
+			pSataAdapter->adapterId, channelIndex, PMPort);
+	       mvSetDriveReady(ialExt,
+                                    scsiAdapterExt,
+			       channelIndex, PMPort,
+			       MV_TRUE,
+			       pDriveData->identifyBuffer);
+	       mvSataScsiNotifyUA(scsiAdapterExt, channelIndex, PMPort);
+	  }
+     }
+#endif
+     else  
+     {
+	  mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: bad type for the connected device, deviceType = %d\n",
+		   pSataAdapter->adapterId, channelIndex, PMPort, deviceType - MV_SATA_DEVICE_TYPE_UNKNOWN);
+	  mvDrivesInfoFlushSingleDrive(ialExt, channelIndex, PMPort);
+     }
+     return MV_TRUE;
+}
+static MV_BOOLEAN mvPMPortProbeLink(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+				    MV_U8 channelIndex,
+				    MV_U8 PMPort,
+				    MV_BOOLEAN force_speed_gen1,
+				    MV_U32 *SStatus,
+				    MV_BOOLEAN *H2DReceived)
+{
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    
+    mvPMDevEnableStaggeredSpinUpPort(pSataAdapter, channelIndex, PMPort, 
+				     force_speed_gen1);
+    /* clear N bit (16) and X bit (26)in serror */
+    /* some driver expect the host to respond with R_RDY immediatly */
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, PMPort,
+			MV_SATA_PSCR_SERROR_REG_NUM, 
+			MV_BIT26 | MV_BIT18 |MV_BIT16, NULL) ==
+	MV_FALSE)
+    {
+	 mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,
+		  "[%d %d %d]: PM Write SERROR Failed\n",
+		  pSataAdapter->adapterId, channelIndex, PMPort);
+    }
+    mvMicroSecondsDelay(pSataAdapter, 50000);
+    *H2DReceived = mvSataIfD2HReceived(pSataAdapter, channelIndex, PMPort);
+    
+    /* clear again*/
+    mvPMDevWriteReg(pSataAdapter, channelIndex, PMPort,
+		    MV_SATA_PSCR_SERROR_REG_NUM,
+		    MV_BIT26| MV_BIT18 |MV_BIT16, NULL);
+    
+    if (mvPMDevReadReg(pSataAdapter, channelIndex, PMPort,
+		       MV_SATA_PSCR_SSTATUS_REG_NUM, SStatus, NULL) ==
+	MV_FALSE)
+    {
+	 mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: mvPMDevReadReg Failed\n",
+		  pSataAdapter->adapterId, channelIndex, PMPort);
+	 return MV_FALSE;
+    }
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO, "[%d %d %d]: S-Status: 0x%x\n",
+	     pSataAdapter->adapterId,
+	     channelIndex, PMPort, *SStatus);
+    
+    /* clear X bit in serror */
+    if (mvPMDevWriteReg(pSataAdapter, channelIndex, PMPort,
+			MV_SATA_PSCR_SERROR_REG_NUM,
+			MV_BIT26 | MV_BIT18 | MV_BIT16, NULL) ==
+	MV_FALSE)
+    {
+	 mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,
+		  "[%d %d %d]: PM Write SERROR Failed\n",
+		  pSataAdapter->adapterId, channelIndex, PMPort);
+    }
+    return MV_TRUE;      
+}
+static MV_BOOLEAN mvPMInitDevicesStateHandler(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+					      MV_U8 channelIndex,
+					      MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_IAL_COMMON_CHANNEL_EXTENSION* channelExt =
+    &ialExt->IALChannelExt[channelIndex];
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    MV_U8 PMPort = channelExt->devInSRST;
+    MV_U32 SStatus;
+    MV_STORAGE_DEVICE_REGISTERS *mvStorageDevRegisters = &channelExt->mvStorageDevRegisters;
+    MV_BOOLEAN H2DReceived = MV_FALSE;
+
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d] CHANNEL_PM_INIT_DEVICES port:%d status:%d\n",
+             ialExt->pSataAdapter->adapterId, channelIndex, PMPort,
+	     channelExt->port_state);
+    
+    if(channelExt->port_state == MV_PORT_NOT_INITIALIZED)
+    {
+	 MV_BOOLEAN found_device = MV_FALSE;
+	 MV_U32 retry_count = 0;
+	 MV_BOOLEAN force_speed_gen1 = MV_FALSE;
+	 do {
+	      if(mvPMPortProbeLink(ialExt, channelIndex, PMPort, force_speed_gen1,
+				   &SStatus, &H2DReceived) == MV_FALSE) {
+		   if (mvStorageDevATASoftResetDevice(pSataAdapter, channelIndex,
+						      MV_SATA_PM_CONTROL_PORT, NULL)
+		       == MV_FALSE)
+		   {
+			mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,
+				 "[%d %d]:failed to Soft Reset PM control port\n",
+				 pSataAdapter->adapterId, channelIndex);
+			return MV_FALSE;
+		   }
+		   PMPort++;
+		   if(PMPort == channelExt->PMnumberOfPorts)
+			break;
+		   else
+			continue;
+	      }
+	      
+	      if ((SStatus & 0xf) == 3) {
+		   if(H2DReceived == MV_TRUE){
+			channelExt->port_state = MV_PORT_ISSUE_SRST;
+		   }else{
+			mvSetChannelTimer(ialExt, channelIndex,
+					  MV_IAL_WAIT_FOR_RDY_TIMEOUT);
+			channelExt->port_state = MV_PORT_WAIT_FOR_RDY;
+		   }
+		   channelExt->devInSRST = PMPort;
+		   found_device = MV_TRUE;
+		   return MV_FALSE;
+	      }
+	      if((SStatus & 0xf) == 1) {
+		   if(retry_count++ < 5) {
+			/* probe link again 
+			 */
+			mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,
+				 "[%d %d %d]: retry link (%d)\n",
+				 pSataAdapter->adapterId, channelIndex, PMPort,
+				 SStatus & 0xf, retry_count);
+			
+			if((SStatus & 0xf0) == 0x10)
+			     force_speed_gen1 = MV_TRUE;
+			continue;
+		   }
+	      } 
+	      /* next PORT*/
+	      PMPort++;
+	      if(PMPort == channelExt->PMnumberOfPorts)
+	      {
+		   channelExt->port_state = MV_PORT_DONE;
+		   break;
+	      }
+	 }while(found_device == MV_FALSE);
+	 
+    }else if(channelExt->port_state == MV_PORT_WAIT_FOR_RDY){
+	 mvDecrementChannelTimer(ialExt, channelIndex);
+	 if(mvSataIfD2HReceived(pSataAdapter, channelIndex, PMPort) == MV_FALSE){
+	      mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,
+		       "[%d %d %d] - disk not ready: wait a little more\n",
+		       pSataAdapter->adapterId, channelIndex, PMPort);
+
+	      printAtaDeviceRegisters(mvStorageDevRegisters);
+	      if(mvIsChannelTimerExpired(ialExt, channelIndex) == MV_TRUE){
+		   mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,
+			    "[%d %d %d]: PM port signature timed out\n",
+			    pSataAdapter->adapterId, channelIndex, PMPort);
+	      }else{
+		   return MV_TRUE;
+	      }
+	 }else{
+	      mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO, "[%d %d %d]: "
+		       "device signature received.\n",
+		       pSataAdapter->adapterId, channelIndex, PMPort);
+	 }
+	 channelExt->port_state = MV_PORT_ISSUE_SRST;
+	 channelExt->devInSRST = PMPort;
+	 return MV_FALSE; /* re-call this function without delay*/
+    }else if(channelExt->port_state == MV_PORT_ISSUE_SRST){
+	 MV_U32 SError;
+	 /* check if disk is connected*/
+	 mvPMDevReadReg(pSataAdapter, channelIndex, PMPort, 
+			MV_SATA_PSCR_SERROR_REG_NUM, &SError, NULL);
+	 mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]:SError "
+		  " 0x%08x\n",
+		  pSataAdapter->adapterId, channelIndex, PMPort, SError);
+
+	 /*check N bit*/
+	 if(SError & MV_BIT16)
+	 {
+	      mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO, "[%d %d %d]: "
+		       "link was changed\n",
+                       pSataAdapter->adapterId, channelIndex, PMPort);
+	      if(++channelExt->devInSRST == channelExt->PMnumberOfPorts)
+	      {
+		   channelExt->port_state = MV_PORT_DONE;
+	      }else{
+		   channelExt->port_state = MV_PORT_NOT_INITIALIZED;
+	      }
+
+	      return MV_TRUE;
+	 }
+
+
+
+	 if (mvStorageDevATAStartSoftResetDevice(pSataAdapter,
+						 channelIndex,
+						 PMPort) == MV_FALSE)
+	 {
+	      mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: "
+		       "failed to Soft Reset PM device port.\n",
+		       pSataAdapter->adapterId, channelIndex, PMPort);
+	      /* this port not functional, next port*/
+	      channelExt->port_state = MV_PORT_NOT_INITIALIZED;
+	      channelExt->devInSRST++;
+	 }
+	 else
+	 {
+	      mvSetChannelTimer(ialExt, channelIndex, MV_IAL_SRST_TIMEOUT);
+	      channelExt->port_state = MV_PORT_IN_SRST;
+	      channelExt->devInSRST = PMPort;
+	      return MV_TRUE;
+	 }	 
+    }else if(channelExt->port_state == MV_PORT_IN_SRST){
+	 mvDecrementChannelTimer(ialExt, channelIndex);
+	 if (mvStorageIsDeviceBsyBitOff(pSataAdapter,
+					channelIndex,
+					mvStorageDevRegisters) == MV_FALSE)
+	 {
+	      if (mvIsChannelTimerExpired(ialExt, channelIndex) !=
+		  MV_TRUE)
+	      {
+		   mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d %d] - disk not ready: wait a "
+			    "little more\n",
+			    pSataAdapter->adapterId,
+			    channelIndex, PMPort);
+		   printAtaDeviceRegisters(mvStorageDevRegisters);
+		   return MV_TRUE;
+	      }
+	      /* SRST timeout*/
+	      mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: Soft Reset PM port time out\n",
+		       pSataAdapter->adapterId, channelIndex, PMPort);
+	      
+	      if (mvStorageDevATASoftResetDevice(pSataAdapter, channelIndex,
+						 MV_SATA_PM_CONTROL_PORT, NULL) == MV_FALSE)
+	      {
+		   mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
+			    "failed to Soft Reset PM control port\n",
+			    pSataAdapter->adapterId, channelIndex);
+		   return MV_FALSE;
+	      }
+	      
+	      if(++channelExt->devInSRST == channelExt->PMnumberOfPorts)
+	      {
+		   channelExt->port_state = MV_PORT_DONE;
+	      }else{
+		   channelExt->port_state = MV_PORT_NOT_INITIALIZED;
+		   return MV_TRUE;
+	      }
+	      
+	 }
+	 /* SRST completed*/
+	 channelExt->port_state = MV_PORT_INIT_DEVICE;
+	 return MV_TRUE;
+    }else if(channelExt->port_state == MV_PORT_INIT_DEVICE){
+	 MV_U32 SError;
+	 /* check if disk is connected*/
+	 mvPMDevReadReg(pSataAdapter, channelIndex, PMPort, 
+			MV_SATA_PSCR_SERROR_REG_NUM, &SError, NULL);
+	 mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]:SError "
+		  " 0x%08x\n",
+		  pSataAdapter->adapterId, channelIndex, PMPort, SError);
+
+	 /*check N bit*/
+	 if(SError & MV_BIT16)
+	 {
+	      mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO, "[%d %d %d]: "
+		       "link was changed\n",
+		       pSataAdapter->adapterId, channelIndex, PMPort);
+	 } else {
+	      classifyAndInitDevice(scsiAdapterExt, ialExt,
+				    channelIndex, PMPort);
+	 }
+	 /* next port*/
+	 if(++channelExt->devInSRST == channelExt->PMnumberOfPorts)
+	 {
+	      channelExt->port_state = MV_PORT_DONE;
+	 }else{
+	      channelExt->port_state = MV_PORT_NOT_INITIALIZED;
+	      return MV_TRUE;
+	 }
+    }
+    
+    if(channelExt->port_state == MV_PORT_DONE) {
+	 mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_INFO,"[%d %d]: PM devices initialized\n",  pSataAdapter->adapterId,
+		  channelIndex, PMPort, channelExt->port_state);
+#if 0
+	 if (clearSErrorPorts(ialExt->pSataAdapter, channelIndex,
+			      ialExt->IALChannelExt[channelIndex].PMnumberOfPorts) != 
+	     MV_TRUE)
+	 {
+	      return MV_FALSE;
+	 }
+#endif
+#if 1
+	 if (mvPMEnableCommStatusChangeBits(ialExt,
+					    channelIndex,
+					    MV_TRUE) != MV_TRUE)
+	 {
+	      return MV_FALSE;
+	 }
+	 if (mvPMEnableAsyncNotify(ialExt, channelIndex) == MV_FALSE)
+	 {
+	      return MV_FALSE;
+	 }
+#endif
+	 if (mvConfigChannelDMA(ialExt,
+				channelIndex,
+				scsiAdapterExt) == MV_TRUE)
+	 {
+	      mvSetChannelState(ialExt, channelIndex, CHANNEL_READY);
+	      
+	 }
+	 else
+	 {
+	      mvStopChannel(ialExt, channelIndex, scsiAdapterExt);
+	 }
+    }else if(channelExt->port_state == MV_PORT_FAILED){
+	 mvStopChannel(ialExt, channelIndex, scsiAdapterExt);
+    }else {
+	 mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,"[%d %d %d] - unknown port"
+		  " status: %d\n",  pSataAdapter->adapterId,
+		  channelIndex, PMPort, channelExt->port_state);
+    }
+    return MV_TRUE;
+}
+
+static MV_BOOLEAN mvChannelReadyStateHandler(
+                                            MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                            MV_U8 channelIndex)
+{
+
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    if ((ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress == MV_FALSE) &&
+        (mvStorageDevGetDeviceType (pSataAdapter, channelIndex) == MV_SATA_DEVICE_TYPE_PM) &&
+        (ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled == MV_FALSE))
+    {
+        /*poll pm GSCR error register one time of 4 steps (2 seconds)*/
+        if (ialExt->IALChannelExt[channelIndex].pmRegPollCounter++ & 0x3) 
+        {
+            return MV_TRUE;
+        }
+        if (mvQueuePMAccessRegisterCommand(ialExt,
+                                           channelIndex,
+                                           MV_SATA_PM_CONTROL_PORT,
+                                           MV_SATA_GSCR_ERROR_REG_NUM,
+                                           0,
+                                           MV_TRUE) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d] error reading "
+                     " PM GSCR_ERROR register.\n",
+                     pSataAdapter->adapterId, channelIndex);
+        }
+    }
+    mvSata60X1B2CheckDevError(pSataAdapter, channelIndex);
+    return MV_TRUE;
+}
+
+
+static MV_BOOLEAN mvChannelPMHotPlugStateHandler(
+                                                MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                                MV_U8 channelIndex,
+                                                MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d] CHANNEL_PM_HOT_PLUG\n",
+             ialExt->pSataAdapter->adapterId, channelIndex);
+    mvSataDisableChannelDma(ialExt->pSataAdapter, channelIndex);
+    mvSataFlushDmaQueue (ialExt->pSataAdapter,
+                         channelIndex, MV_FLUSH_TYPE_CALLBACK);
+    mvSataChannelHardReset(ialExt->pSataAdapter, channelIndex);
+    mvRestartChannel(ialExt, channelIndex, scsiAdapterExt, MV_FALSE);
+    return MV_TRUE;
+}
+
+static MV_BOOLEAN mvChannelStateMachine(
+                                       MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                       MV_U8 channelIndex,
+                                       MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_BOOLEAN res = MV_FALSE;
+    do
+    {
+        switch (ialExt->channelState[channelIndex])
+        {
+        case CHANNEL_NOT_CONNECTED:
+            res = mvChannelNotConnectedStateHandler(ialExt,
+                                                    channelIndex,
+                                                    scsiAdapterExt);
+            break;
+        case CHANNEL_CONNECTED:
+            res = mvChannelConnectedStateHandler(ialExt,
+                                                 channelIndex,
+                                                 scsiAdapterExt);
+            break;
+        case CHANNEL_IN_SRST:
+            res = mvChannelInSrstStateHandler(ialExt,
+                                              channelIndex,
+                                              scsiAdapterExt);
+            break;
+        case CHANNEL_PM_INIT_DEVICES:
+            res = mvPMInitDevicesStateHandler(ialExt,
+					      channelIndex,
+					      scsiAdapterExt);
+            break;
+        case CHANNEL_READY:
+            res = mvChannelReadyStateHandler(ialExt,
+                                             channelIndex);
+            break;
+        case CHANNEL_PM_HOT_PLUG:
+            res = mvChannelPMHotPlugStateHandler(ialExt,
+                                                 channelIndex,
+                                                 scsiAdapterExt);
+            break;
+        default:
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: Unknown channel state.\n",
+                     ialExt->pSataAdapter->adapterId, channelIndex);
+            return MV_FALSE;
+        }
+    } while (res == MV_FALSE);
+
+    return MV_TRUE;
+}
+
+
+static MV_BOOLEAN mvAdapterStateMachine(
+                                       MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                       MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
+{
+    MV_BOOLEAN res = MV_TRUE;
+    MV_U8 channelIndex;
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    switch (ialExt->adapterState)
+    {
+    case ADAPTER_INITIALIZING:     {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d] ADAPTER_INITIALIZING\n",
+                     pSataAdapter->adapterId);
+ 
+            res = mvSataEnableStaggeredSpinUpAll(pSataAdapter);
+            if (res == MV_TRUE)
+            {
+                if (mvSataUnmaskAdapterInterrupt(pSataAdapter) == MV_FALSE)
+                {
+                    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d]: "
+                             "mvSataUnmaskAdapterInterrupt failed\n",
+                             pSataAdapter->adapterId);
+                    ialExt->adapterState = ADAPTER_FATAL_ERROR;
+                    return MV_FALSE;
+                }
+                ialExt->adapterState = ADAPTER_READY;
+            }
+        }
+        break;
+    case ADAPTER_READY:
+        for (channelIndex = 0;
+            channelIndex < pSataAdapter->numberOfChannels; channelIndex++)
+        {
+
+            mvChannelStateMachine(ialExt,
+                                  channelIndex,
+                                  scsiAdapterExt);
+        }
+        return MV_TRUE;
+        break;
+    default:
+        break;
+    }
+
+    if (ialExt->adapterState != ADAPTER_READY)
+    {
+        return res;
+    }
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d] ADAPTER_READY\n",
+             pSataAdapter->adapterId);
+
+    /*Start channel initialization for connected channels*/
+    for (channelIndex = 0;
+        channelIndex < pSataAdapter->numberOfChannels;
+        channelIndex++)
+    {
+        mvFlushSCSICommandQueue(ialExt, channelIndex);
+        if (mvSataIsStorageDeviceConnected(pSataAdapter, channelIndex, NULL) ==
+            MV_FALSE)
+        {
+            mvSetChannelState(ialExt,
+                              channelIndex,
+                              CHANNEL_NOT_CONNECTED);
+            continue;
+        }
+
+        mvSetChannelState(ialExt,
+                          channelIndex,
+                          CHANNEL_CONNECTED);
+	
+        if (mvChannelStateMachine(ialExt,
+                                  channelIndex,
+                                  scsiAdapterExt) == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d]: Failed to "
+                     "start channel.\n", pSataAdapter->adapterId, channelIndex);
+            mvSetChannelState(ialExt,
+                              channelIndex,
+                              CHANNEL_NOT_CONNECTED);
+            mvFlushSCSICommandQueue(ialExt, channelIndex);
+            mvSataRemoveChannel(pSataAdapter,channelIndex);
+            IALReleaseChannel(pSataAdapter, channelIndex);
+            pSataAdapter->sataChannel[channelIndex] = NULL;
+            mvDrivesInfoFlushAll(ialExt, channelIndex);
+            mvSetDriveReady(ialExt,
+                            scsiAdapterExt,
+                            channelIndex,
+                            0xFF, MV_FALSE, NULL);
+            continue;
+        }
+    }
+    return res;
+}
+
+static MV_BOOLEAN mvGetDisksModes(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                  MV_SAL_ADAPTER_EXTENSION *pScsiAdapterExt,
+                                  MV_U8 channelIndex,
+                                  MV_BOOLEAN *TCQ,
+                                  MV_BOOLEAN *NCQ,
+                                  MV_U8   *numOfDrives)
+{
+    MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
+    MV_BOOLEAN allNCQ = MV_TRUE;
+    MV_BOOLEAN allTCQ = MV_TRUE;
+    MV_U8               i;
+
+    if ((pSataAdapter == NULL) || (pScsiAdapterExt == NULL))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,"[%d %d]"
+                 " mvGetDisksModes failed, bad pointer\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    if ((ialExt->adapterState != ADAPTER_READY) ||
+        (ialExt->channelState[channelIndex] == CHANNEL_NOT_CONNECTED))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,"[%d %d] "
+                 "mvGetDisksModes failed,Bad Adapter or Channel State\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    if (pSataAdapter->sataChannel[channelIndex] == NULL)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR,"[%d %d] "
+                 "mvGetDisksModes failed, channel not configured\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return MV_FALSE;
+    }
+    *numOfDrives = 0;
+    for (i = 0; i < MV_SATA_PM_MAX_PORTS; i++)
+    {
+        if ((pScsiAdapterExt->
+            ataDriveData[channelIndex][i].driveReady == MV_TRUE) &&
+           (pScsiAdapterExt->ataDriveData[channelIndex][i].identifyInfo.deviceType == MV_SATA_DEVICE_TYPE_ATA_DISK))
+        {
+            (*numOfDrives)++;
+
+            if (pScsiAdapterExt->ataDriveData[channelIndex][i].
+                identifyInfo.DMAQueuedModeSupported == MV_FALSE)
+            {
+                allTCQ = MV_FALSE;
+            }
+            if (pScsiAdapterExt->
+                ataDriveData[channelIndex][i].identifyInfo.
+                SATACapabilities.NCQSupported == MV_FALSE)
+            {
+                allNCQ = MV_FALSE;
+            }
+        }
+    }
+
+    if (TCQ)
+    {
+        if ((*numOfDrives > 0) && (allTCQ == MV_TRUE))
+        {
+            *TCQ = MV_TRUE;
+        }
+        else
+        {
+            *TCQ = MV_FALSE;
+        }
+    }
+    if (NCQ)
+    {
+        if ((*numOfDrives > 0) && (allNCQ == MV_TRUE))
+        {
+            *NCQ = MV_TRUE;
+        }
+        else
+        {
+            *NCQ = MV_FALSE;
+        }
+    }
+    return MV_TRUE;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommon.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommon.h
new file mode 100755
index 0000000..3a512d7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommon.h
@@ -0,0 +1,192 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvIALCommon.h
+*
+* DESCRIPTION:
+*       H implementation for IAL's common functions.
+*
+* DEPENDENCIES:
+*   mvSata.h
+*   mvStorageDev.h
+*
+*******************************************************************************/
+#ifndef __INCmvIALCommonh
+#define __INCmvIALCommonh
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* includes */
+#include "mvSata.h"
+#include "mvStorageDev.h"
+
+/* defines  */
+
+/*Timer period in milliseconds*/
+#define MV_IAL_ASYNC_TIMER_PERIOD       500
+#define MV_IAL_SRST_TIMEOUT             31000
+#define MV_IAL_WAIT_FOR_RDY_TIMEOUT     10000
+/* typedefs */
+
+
+
+typedef enum mvAdapterState
+{
+    ADAPTER_INITIALIZING,
+    ADAPTER_READY,
+    ADAPTER_FATAL_ERROR
+} MV_ADAPTER_STATE;
+
+typedef enum mvChannelState
+{
+    CHANNEL_NOT_CONNECTED,
+    CHANNEL_CONNECTED,
+    CHANNEL_IN_SRST,
+    CHANNEL_PM_INIT_DEVICES,
+    CHANNEL_READY,
+    CHANNEL_PM_HOT_PLUG,
+} MV_CHANNEL_STATE;
+
+typedef struct mvDriveSerialNumber
+{
+    MV_U8 serial[IDEN_SERIAL_NUM_SIZE];    
+}   MV_DRIVE_SERIAL_NUMBER;
+
+
+typedef struct mvDrivesInfo
+{
+    MV_U16                      drivesSnapshotSaved;
+    MV_DRIVE_SERIAL_NUMBER      driveSerialSaved[MV_SATA_PM_MAX_PORTS];    
+    MV_U16                      drivesSnapshotCurrent;
+    MV_DRIVE_SERIAL_NUMBER      driveSerialCurrent[MV_SATA_PM_MAX_PORTS];    
+}   MV_DRIVES_INFO;
+
+typedef enum mvPortState
+{
+    MV_PORT_NOT_INITIALIZED,
+    MV_PORT_WAIT_FOR_RDY, /* wait for the disk's signature*/
+    MV_PORT_ISSUE_SRST,
+    MV_PORT_IN_SRST,
+    MV_PORT_INIT_DEVICE,
+    MV_PORT_DONE, /* PM ports scan is complete successfully*/
+    MV_PORT_FAILED
+} MV_PORT_STATE;
+
+typedef struct mvIALChannelExtension
+{
+    MV_U8                       PMnumberOfPorts;
+    MV_U16                      PMdevsToInit;
+    MV_U8                       devInSRST;
+    MV_PORT_STATE		port_state;
+    MV_BOOLEAN                  completionError;
+    MV_U8                       pmAccessType;
+    MV_U8                       pmReg;
+    MV_BOOLEAN                  pmRegAccessInProgress;
+    MV_BOOLEAN                  pmAsyncNotifyEnabled;
+    MV_U8                       pmRegPollCounter;
+    MV_U32                      SRSTTimerThreshold;
+    MV_U32                      SRSTTimerValue;
+    MV_VOID_PTR                 IALChannelPendingCmdQueue;
+    MV_BOOLEAN                  bHotPlug;
+    MV_DRIVES_INFO              drivesInfo;
+    MV_STORAGE_DEVICE_REGISTERS mvStorageDevRegisters;
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO       commandInfo;
+#endif
+} MV_IAL_COMMON_CHANNEL_EXTENSION;
+
+
+typedef struct mvIALCommonAdapterExtension
+{
+    MV_SATA_ADAPTER   *pSataAdapter;
+    MV_ADAPTER_STATE  adapterState;
+    MV_CHANNEL_STATE  channelState[MV_SATA_CHANNELS_NUM];
+    MV_IAL_COMMON_CHANNEL_EXTENSION IALChannelExt[MV_SATA_CHANNELS_NUM];
+} MV_IAL_COMMON_ADAPTER_EXTENSION;
+
+
+/*Public functions*/
+MV_BOOLEAN mvAdapterStartInitialization(MV_SATA_ADAPTER* pSataAdapter,
+                                        MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+void mvRestartChannel(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                      MV_U8 channelIndex,
+                      MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
+                      MV_BOOLEAN    bBusReset);
+
+void mvStopChannel(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                   MV_U8 channelIndex,
+                   MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+void mvPMHotPlugDetected(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                         MV_U8 channelIndex,
+                         MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+
+MV_SCSI_COMMAND_STATUS_TYPE mvExecuteScsiCommand(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                                                 MV_BOOLEAN canQueue);
+
+MV_BOOLEAN  mvIALTimerCallback(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                               MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
+
+void mvCommandCompletionErrorHandler(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                     MV_U8 channelIndex);
+
+MV_BOOLEAN mvRemoveFromSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
+                                        MV_U8 channelIndex,
+                                        MV_SATA_SCSI_CMD_BLOCK *pScb);
+
+/*The following functions which must be implemented in IAL*/
+
+MV_BOOLEAN IALConfigQueuingMode(MV_SATA_ADAPTER *pSataAdapter,
+                                MV_U8 channelIndex,
+                                MV_EDMA_MODE mode,
+                                MV_SATA_SWITCHING_MODE switchingMode,
+                                MV_BOOLEAN  use128Entries);
+
+
+MV_BOOLEAN IALInitChannel(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex);
+
+void IALReleaseChannel(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex);
+MV_BOOLEAN IALBusChangeNotify(MV_SATA_ADAPTER *pSataAdapter,
+                              MV_U8 channelIndex);
+MV_BOOLEAN IALBusChangeNotifyEx(MV_SATA_ADAPTER *pSataAdapter, 
+                                MV_U8 channelIndex, 
+                                MV_U16 targetsToRemove,
+                                MV_U16 targetsToAdd);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INCmvIALCommonh */
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommonUtils.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommonUtils.c
new file mode 100755
index 0000000..d88109d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommonUtils.c
@@ -0,0 +1,1274 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvIALCommonUtils.c
+*
+* DESCRIPTION:
+*       C implementation for IAL's extension utility functions.
+*
+* DEPENDENCIES:
+*   mvIALCommonUtils.h
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvOs.h"
+#include "mvIALCommonUtils.h"
+
+#define MV_ANY_PM {0, 0, 0, 0, 0}
+#define MV_MARVELL_PM_A0 {0x11AB, 0x1116, 0, 0, 0}
+#define MV_MARVELL_PM {0x11AB, 0x1116, 0xFF, 0, 0}
+struct _EDMAConfiguration
+{
+    MV_U8                   configNumber;
+    /*inputs*/
+    MV_SATA_GEN             adapterGen;
+    MV_SATA_DEVICE_TYPE     connectedDevice;
+    MV_BOOLEAN              specificPM;
+    MV_SATA_PM_DEVICE_INFO  PMInfo;
+    MV_BOOLEAN              AllNCQ;
+    MV_BOOLEAN              AllTCQ;
+    MV_U8                   maxDisks;
+    /*outputs*/
+    MV_EDMA_MODE            EDMAMode;
+    MV_SATA_SWITCHING_MODE  switchingMode;
+    MV_BOOLEAN              use128Entries;
+} EDMAConfigurations[] =
+{
+    /*Gen1, TCQ disk*/
+    {1, MV_SATA_GEN_I, MV_SATA_DEVICE_TYPE_ATA_DISK, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_TRUE, 1,
+        MV_EDMA_MODE_QUEUED, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+    /*Gen1, Normal disk*/
+    {2, MV_SATA_GEN_I, MV_SATA_DEVICE_TYPE_ATA_DISK, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_FALSE, 1,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+    /*Gen2, NCQ disk*/
+    {3, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_ATA_DISK, MV_FALSE, MV_ANY_PM, MV_TRUE, MV_FALSE, 1,
+        MV_EDMA_MODE_NATIVE_QUEUING, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+    /*Gen2, TCQ disk*/
+    {4, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_ATA_DISK, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_TRUE, 1,
+        MV_EDMA_MODE_QUEUED, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+    /*Gen2, Normal disk*/
+    {5, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_ATA_DISK, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_FALSE, 1,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+    /*Gen2, Marvell PM, NCQ disks*/
+    /*{6, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_PM, MV_TRUE, MV_MARVELL_PM, MV_TRUE, MV_FALSE, MV_SATA_PM_MAX_PORTS,
+        MV_EDMA_MODE_NATIVE_QUEUING, MV_SATA_SWITCHING_MODE_QCBS, MV_FALSE},*/
+    /*Gen2, Marvell PM, single TCQ disk*/
+    /*{7, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_PM, MV_TRUE, MV_MARVELL_PM, MV_FALSE, MV_TRUE, 1,
+        MV_EDMA_MODE_QUEUED, MV_SATA_SWITCHING_MODE_QCBS, MV_FALSE},*/
+    /*Gen2, Marvell PM, Normal disks*/
+    /*{8, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_PM, MV_TRUE, MV_MARVELL_PM, MV_FALSE, MV_FALSE, MV_SATA_PM_MAX_PORTS,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_QCBS, MV_FALSE},*/
+    /*Gen2, PM, single NCQ disk*/
+    {9, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_PM, MV_FALSE, MV_ANY_PM, MV_TRUE, MV_FALSE, 1,
+        MV_EDMA_MODE_NATIVE_QUEUING, MV_SATA_SWITCHING_MODE_CBS, MV_FALSE},
+    /*Gen2, PM, single TCQ disk*/
+    {10, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_PM, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_TRUE, 1,
+        MV_EDMA_MODE_QUEUED, MV_SATA_SWITCHING_MODE_CBS, MV_FALSE},
+    /*Gen2, PM, Normal disks*/
+    {11, MV_SATA_GEN_II, MV_SATA_DEVICE_TYPE_PM, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_FALSE, MV_SATA_PM_MAX_PORTS,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_CBS, MV_FALSE},
+    /*Gen2E, NCQ disk*/
+    {12, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_ATA_DISK, MV_FALSE, MV_ANY_PM, MV_TRUE, MV_FALSE, 1,
+        MV_EDMA_MODE_NATIVE_QUEUING, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+    /*Gen2E, TCQ disk*/
+    {13, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_ATA_DISK, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_TRUE, 1,
+        MV_EDMA_MODE_QUEUED, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+    /*Gen2E, Normal disk*/
+    {14, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_ATA_DISK, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_FALSE, 1,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+    /*Gen2E, Marvell PM <= A0, NCQ disks*/
+    {15, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_PM, MV_TRUE, MV_MARVELL_PM_A0, MV_TRUE, MV_FALSE, MV_SATA_PM_MAX_PORTS,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_CBS, MV_FALSE},
+    /*Gen2E, PM, NCQ disks*/
+    {16, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_PM, MV_FALSE, MV_ANY_PM, MV_TRUE, MV_FALSE, MV_SATA_PM_MAX_PORTS,
+        MV_EDMA_MODE_NATIVE_QUEUING, MV_SATA_SWITCHING_MODE_FBS, MV_TRUE},
+    /*Gen2E, Marvell PM <= A0, single TCQ disk*/
+    {17, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_PM, MV_TRUE, MV_MARVELL_PM_A0, MV_FALSE, MV_TRUE, 1,
+        MV_EDMA_MODE_QUEUED, MV_SATA_SWITCHING_MODE_CBS, MV_FALSE},
+    /*Gen2E, PM, TCQ disks*/
+    {18, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_PM, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_TRUE, MV_SATA_PM_MAX_PORTS,
+        MV_EDMA_MODE_QUEUED, MV_SATA_SWITCHING_MODE_FBS, MV_TRUE},
+    /*Gen2E, Marvell PM <= A0, Normal disks*/
+    {19, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_PM, MV_TRUE, MV_MARVELL_PM_A0, MV_FALSE, MV_FALSE, MV_SATA_PM_MAX_PORTS,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_CBS, MV_FALSE},
+    /*Gen2E, PM, Normal disks*/
+    {20, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_PM, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_FALSE, MV_SATA_PM_MAX_PORTS,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_FBS, MV_FALSE},
+    /*Gen2E , ATAPI device*/
+    {21, MV_SATA_GEN_IIE, MV_SATA_DEVICE_TYPE_ATAPI_DEVICE, MV_FALSE, MV_ANY_PM, MV_FALSE, MV_FALSE, 1,
+        MV_EDMA_MODE_NOT_QUEUED, MV_SATA_SWITCHING_MODE_NONE, MV_FALSE},
+
+};
+
+MV_VOID mvSelectConfiguration(MV_SATA_ADAPTER        *pSataAdapter,
+                              MV_U8                  channelIndex,
+                              MV_SATA_GEN            gen,
+                              MV_SATA_DEVICE_TYPE    connectedDevice,
+                              MV_SATA_PM_DEVICE_INFO *pPMInfo,
+                              MV_BOOLEAN             AllNCQ,
+                              MV_BOOLEAN             AllTCQ,
+                              MV_BOOLEAN             disks,
+                              MV_EDMA_MODE           *pEdmaMode,
+                              MV_SATA_SWITCHING_MODE *pSwitchingMode,
+                              MV_BOOLEAN             *pUse128Entries)
+{
+    MV_U32      i;
+    MV_U32      configurationsNum = sizeof(EDMAConfigurations)/sizeof(struct _EDMAConfiguration);       
+
+    for (i = 0; i < configurationsNum; i++)
+    {
+        if (gen != EDMAConfigurations[i].adapterGen)
+        {
+            continue;
+        }
+        if (connectedDevice != EDMAConfigurations[i].connectedDevice)
+        {
+            continue;
+        }
+        if ((connectedDevice == MV_SATA_DEVICE_TYPE_PM) &&
+            (EDMAConfigurations[i].specificPM == MV_TRUE))
+        {
+            if ((pPMInfo->vendorId != EDMAConfigurations[i].PMInfo.vendorId) ||
+                (pPMInfo->deviceId != EDMAConfigurations[i].PMInfo.deviceId) ||
+                (pPMInfo->productRevision > EDMAConfigurations[i].PMInfo.productRevision))
+            {
+                continue;
+            }
+        }
+        if ((EDMAConfigurations[i].AllNCQ == MV_TRUE) &&
+            (AllNCQ == MV_FALSE))
+        {
+            continue;
+        }
+        if ((EDMAConfigurations[i].AllTCQ == MV_TRUE) &&
+            (AllTCQ == MV_FALSE))
+        {
+            continue;
+        }
+        if (disks > EDMAConfigurations[i].maxDisks)
+        {
+            continue;
+        }
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: mvSelectConfiguration"
+                 ": Matching configuration found #%d\n",
+                 pSataAdapter->adapterId,
+                 channelIndex, 
+                 EDMAConfigurations[i].configNumber);
+
+        *pEdmaMode = EDMAConfigurations[i].EDMAMode;     
+        *pSwitchingMode = EDMAConfigurations[i].switchingMode;
+        *pUse128Entries = EDMAConfigurations[i].use128Entries;
+	/* some of the integrated adapters doesn't support the EDMA 128 entries mode*/
+	if(pSataAdapter->hostInterface == MV_HOST_IF_INTEGRATED)
+	{
+		*pUse128Entries = MV_FALSE;
+	}
+        break;
+    }
+    if ( i >= configurationsNum)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR, "[%d %d]:"
+                 " in mvSelectConfiguration failed to find matching configuration\n",
+                 pSataAdapter->adapterId,
+                 channelIndex);
+        *pEdmaMode = MV_EDMA_MODE_NOT_QUEUED;
+        *pSwitchingMode = MV_SATA_SWITCHING_MODE_NONE;
+        *pUse128Entries = MV_FALSE;
+    }
+#ifdef MV_LOGGER
+    {
+        char *edmaModeStr[] = { "TCQ", "Normal", "NCQ"};
+        char *switchingModeStr[] = {"None", "CBS", "QCBS", "FBS"};
+
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]:"
+                 "mvSelectConfiguration: EDMA %s, switch mode %s, 128 mode %s\n",
+                 pSataAdapter->adapterId,
+                 channelIndex,
+                 edmaModeStr[(*pEdmaMode - MV_EDMA_MODE_QUEUED) % 3],
+                 switchingModeStr[(*pSwitchingMode - MV_SATA_SWITCHING_MODE_NONE) % 4],
+                 (*pUse128Entries == MV_TRUE) ? "yes":"no");
+
+    }
+#endif
+}
+
+static MV_BOOLEAN mvConfigSataDisk(MV_SATA_ADAPTER *pSataAdapter,
+                                   MV_U8 channelIndex,
+                                   MV_U8 PMPort,
+                                   ATA_IDENTIFY_INFO   *pIdentifyInfo,
+                                   MV_U16_PTR identifyBuffer);
+
+
+static MV_VOID mvAta2HostString(MV_U16 *source, MV_U16 *target,
+                                MV_U32 wordsCount)
+{
+    MV_U32 i;
+    for (i=0 ; i < wordsCount; i++)
+    {
+        /* Big to little*/
+        target[i] = (source[i] >> 8) | ((source[i] & 0xff) << 8);
+        /* Little to cpu*/
+        target[i] = MV_LE16_TO_CPU(target[i]);
+    }
+}
+
+/******************************************************************************
+ *  Name: ParseIdentifyResult
+ *
+ *  Description:    this functions parses the identify command results, checks
+ *                  that the connected deives can be accesed by device EDMA,
+ *                  and updates the ATA drive parameters stucture accordingly.
+ *
+ *  Parameters:     pSataChannel - pointer to the channel data structure.
+ *                  pIdentifyInfo- pointer to the ATA parameters structure.
+ *
+ *  Returns:        MV_TRUE if the ATA drive supported by device.
+ *
+ ******************************************************************************/
+MV_BOOLEAN mvParseIdentifyResult(MV_U16_PTR  iden,
+                                 ATA_IDENTIFY_INFO   *pIdentifyInfo)
+{
+    char    temp[80];
+    MV_U8  version;
+    MV_BOOLEAN  udmaModeEnabled = MV_FALSE;
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "Parse IDENTIFY data:\n");
+
+    mvAta2HostString( iden + IDEN_MODEL_OFFSET, (MV_U16_PTR)temp, 24);
+    temp[25] = '\0';
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n","Model", temp);
+    memcpy(&pIdentifyInfo->model[0], iden + IDEN_MODEL_OFFSET, 24);
+    memcpy(&pIdentifyInfo->firmware[0], iden + IDEN_FIRMWARE_OFFSET, 4);
+    /* ATA version supported*/
+    if (iden[IDEN_ATA_VERSION] & MV_BIT7)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %d\n", "ATA version supported", 7);
+        version = 7;
+    }
+    else if (iden[IDEN_ATA_VERSION] & MV_BIT6)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %d\n", "ATA version supported", 6);
+        version = 6;
+    }
+    else if (iden[IDEN_ATA_VERSION] & MV_BIT5)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %d\n", "ATA version supported", 5);
+        version = 5;
+    }
+    else if (iden[IDEN_ATA_VERSION] & MV_BIT4)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %d\n", "ATA version supported", 4);
+        version = 4;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, " IDENTIFY info: ATA "
+                 "version(%d) not supported\n", iden[IDEN_ATA_VERSION]);
+        return MV_FALSE;
+    }
+    pIdentifyInfo->version = version;
+    /*LBA addressing*/
+    if ((version >= 6) && (!(iden[IDEN_CAPACITY_1_OFFSET] & MV_BIT9)))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, " IDENTIFY info: LBA not supported\n");
+        return MV_FALSE;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "Capabilities",
+                 "LBA supported");
+    }
+    /* 48 bit address */
+    if ((version >= 6) && (iden[IDEN_SUPPORTED_COMMANDS2] & MV_BIT10))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "LBA48 addressing", "supported");
+        pIdentifyInfo->LBA48Supported = MV_TRUE;
+
+	pIdentifyInfo->ATADiskSize = 
+		((MV_U64)iden[103] << 48) |
+		((MV_U64)iden[102] << 32) |
+		((MV_U64)iden[101] << 16) |
+		((MV_U64)iden[100]);
+
+                
+
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - 0x%x%04x%04x%04x sectors\n",
+                 "Number of sectors", iden[103] , iden[102], iden[101],
+                 iden[100]);
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "LBA48 addressing", "Not supported");
+        pIdentifyInfo->LBA48Supported = MV_FALSE;
+        pIdentifyInfo->ATADiskSize = (iden[IDEN_NUM_OF_ADDRESSABLE_SECTORS + 1] << 16) |
+                                     (iden[IDEN_NUM_OF_ADDRESSABLE_SECTORS]);
+
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - 0x%x sectors\n",
+                 "Number of sectors",
+                 (iden[IDEN_NUM_OF_ADDRESSABLE_SECTORS + 1] << 16) |
+                 ((MV_U32)iden[IDEN_NUM_OF_ADDRESSABLE_SECTORS]));
+
+
+    }
+    /*DMA support*/
+    if ((version >= 6) && (!(iden[IDEN_CAPACITY_1_OFFSET] & MV_BIT8)))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "IDENTIFY info: DMA not "
+                 "supported\n");
+        return MV_FALSE;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "Capabilities",
+                 "DMA supported");
+    }
+    /* PIO */
+    if ((iden[IDEN_VALID] & MV_BIT1) == 0)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, " IDENTIFY info: not "
+                 "able to find PIO mode\n");
+        return MV_FALSE;
+    }
+    else if (iden[IDEN_PIO_MODE_SPPORTED] & MV_BIT0)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "PIO mode 3",
+                 "supported");
+        pIdentifyInfo->PIOMode = MV_ATA_TRANSFER_PIO_3;
+    }
+    else if (iden[IDEN_PIO_MODE_SPPORTED] & MV_BIT1)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "PIO mode 4",
+                 "supported");
+        pIdentifyInfo->PIOMode = MV_ATA_TRANSFER_PIO_4;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "IDENTIFY info: PIO "
+                 "modes 3 and 4 not supported\n");
+        pIdentifyInfo->PIOMode = MV_ATA_TRANSFER_PIO_SLOW;
+        return MV_FALSE;
+    }
+
+
+    /*UDMA*/
+    if ((iden[IDEN_VALID] & MV_BIT2) == 0)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, " IDENTIFY info: not "
+                 "able to find UDMA mode\n");
+        return MV_FALSE;
+    }
+
+
+    if ((version >= 7) && (iden[IDEN_UDMA_MODE] & MV_BIT6))
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_6;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT14)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else if ((version >= 6) && (iden[IDEN_UDMA_MODE] & MV_BIT5))
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_5;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT13)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else if ((version >= 5) && (iden[IDEN_UDMA_MODE] & MV_BIT4))
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_4;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT12)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else if ((version >= 4) && (iden[IDEN_UDMA_MODE] & MV_BIT3))
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_3;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT11)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else if (iden[IDEN_UDMA_MODE] & MV_BIT2)
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_2;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT10)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "IDENTIFY info: Ultra"
+                 " DMA mode < 2 not supported IDENTIFY[88] 0x%04x\n",
+                 iden[IDEN_UDMA_MODE]);
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_0;
+        return MV_FALSE;
+    }
+    if (udmaModeEnabled == MV_TRUE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s%d%s\n",
+                 "Ultra DMA mode","UDMA mode ",
+                 pIdentifyInfo->UdmaMode - MV_ATA_TRANSFER_UDMA_0,
+                 " supported and enabled");
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s%d%s\n",
+                 "Ultra DMA mode","UDMA mode ",
+                 pIdentifyInfo->UdmaMode - MV_ATA_TRANSFER_UDMA_0,
+                 " supported but disabled");
+    }
+
+
+    if ((iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT13))
+    {
+        if (iden[IDEN_ENABLED_COMMANDS1] & MV_BIT13)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "READ BUFFER", "supported and enabled");
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "READ BUFFER", "supported and disabled");
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "READ BUFFER",
+                 " Not supported");
+    }
+
+    if ((iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT12))
+    {
+        if (iden[IDEN_ENABLED_COMMANDS1] & MV_BIT12)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "WRITE BUFFER", "supported and enabled");
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "WRITE BUFFER", "supported and disabled");
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "WRITE BUFFER",
+                 "Not supported");
+    }
+
+    if ((iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT6))
+    {
+        pIdentifyInfo->readAheadSupported = MV_TRUE;
+        if (iden[IDEN_ENABLED_COMMANDS1] & MV_BIT6)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "READ LOOK-AHEAD", "supported and enabled");
+            pIdentifyInfo->readAheadEnabled = MV_TRUE;
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "READ LOOK-AHEAD", "supported and disabled");
+            pIdentifyInfo->readAheadEnabled = MV_FALSE;
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "READ LOOK-AHEAD","Not supported");
+        pIdentifyInfo->readAheadSupported = MV_FALSE;
+        pIdentifyInfo->readAheadEnabled = MV_FALSE;
+    }
+
+    if ((iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT5))
+    {
+        pIdentifyInfo->writeCacheSupported = MV_TRUE;
+        if (iden[IDEN_ENABLED_COMMANDS1] & MV_BIT5)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "WRITE CACHE", "supported and enabled");
+            pIdentifyInfo->writeCacheEnabled = MV_TRUE;
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "WRITE CACHE", "supported and disabled");
+            pIdentifyInfo->writeCacheEnabled = MV_FALSE;
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "WRITE CACHE",
+                 "Not supported");
+        pIdentifyInfo->writeCacheSupported = MV_FALSE;
+        pIdentifyInfo->writeCacheEnabled = MV_FALSE;
+    }
+
+    if ((iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT3))
+    {
+
+        if (iden[IDEN_ENABLED_COMMANDS1] & MV_BIT3)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "POWER MANAGMENT", "supported and enabled");
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "POWER MANAGMENT", "supported and disabled");
+        }
+
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "POWER MANAGMENT","Not supported");
+    }
+
+    if ((iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT0))
+    {
+
+        if (iden[IDEN_ENABLED_COMMANDS1] & MV_BIT0)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n", "SMART",
+                     "supported and enabled");
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n", "SMART",
+                     "supported and disabled");
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "SMART",
+                 "Not supported");
+    }
+
+
+    /* check if REAd/WRITE DMA QUEUE commands supported */
+    pIdentifyInfo->DMAQueuedModeDepth = (iden[IDEN_QUEUE_DEPTH] & 0x1f) + 1;
+    if ((version >= 5) &&(iden[IDEN_SUPPORTED_COMMANDS2] & MV_BIT1))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %15s Queue Depth %d\n",
+                 "READ/WRITE DMA QUEUE","supported",
+                 (iden[IDEN_QUEUE_DEPTH] & 0x1f) + 1);
+        pIdentifyInfo->DMAQueuedModeSupported = MV_TRUE;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "READ/WRITE DMA QUEUE", "not supported");
+        pIdentifyInfo->DMAQueuedModeSupported = MV_FALSE;
+    }
+
+    /*check that the non-UDMA ATA commands supported*/
+
+    /*FLUSH CHACHE*/
+    if ((version >=6) && ((iden[IDEN_SUPPORTED_COMMANDS2] & MV_BIT12) == 0))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "FLUSH CACHE command", "not supported");
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "FLUSH CACHE command", "supported");
+    }
+
+    pIdentifyInfo->SATACapabilities.SATA_GEN_I_supported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.SATA_GEN_II_supported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.NCQSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.RxHostInitiatedPMSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.TxDeviceInitiatedPMSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.TxDeviceInitiatedPMEnabled = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.DMASetupAutoActiveSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.DMASetupAutoActiveEnables = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.NonZeroBufferOffsetSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.NonZeroBufferOffsetEnabled = MV_FALSE;
+
+    if (version >= 6)
+    {
+        if (iden[IDEN_SATA_CAPABILITIES] & MV_BIT1)
+        {
+            pIdentifyInfo->SATACapabilities.SATA_GEN_I_supported = MV_TRUE;
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "SATA Gen I",
+                     "not supported");
+        }
+        if (iden[IDEN_SATA_CAPABILITIES] & MV_BIT2)
+        {
+            pIdentifyInfo->SATACapabilities.SATA_GEN_II_supported = MV_TRUE;
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "SATA Gen II",
+                     "supported");
+        }
+
+        if (iden[IDEN_SATA_CAPABILITIES] & MV_BIT8)
+        {
+            pIdentifyInfo->SATACapabilities.NCQSupported = MV_TRUE;
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "NCQ",
+                     "supported");
+        }
+
+        if (iden[IDEN_SATA_CAPABILITIES] & MV_BIT9)
+        {
+            pIdentifyInfo->SATACapabilities.RxHostInitiatedPMSupported = MV_TRUE;
+        }
+
+        if (iden[IDEN_SATA_FEATURES_SUPPORTED] & MV_BIT1)
+        {
+            pIdentifyInfo->SATACapabilities.NonZeroBufferOffsetSupported = MV_TRUE;
+            if (iden[IDEN_SATA_FEATURES_ENABLED] & MV_BIT1)
+            {
+                pIdentifyInfo->SATACapabilities.NonZeroBufferOffsetEnabled = MV_TRUE;
+            }
+        }
+        if (iden[IDEN_SATA_FEATURES_SUPPORTED] & MV_BIT2)
+        {
+            pIdentifyInfo->SATACapabilities.DMASetupAutoActiveSupported = MV_TRUE;
+            if (iden[IDEN_SATA_FEATURES_ENABLED] & MV_BIT2)
+            {
+                pIdentifyInfo->SATACapabilities.DMASetupAutoActiveEnables = MV_TRUE;
+            }
+        }
+        if (iden[IDEN_SATA_FEATURES_SUPPORTED] & MV_BIT3)
+        {
+            pIdentifyInfo->SATACapabilities.TxDeviceInitiatedPMSupported = MV_TRUE;
+            if (iden[IDEN_SATA_FEATURES_ENABLED] & MV_BIT3)
+            {
+                pIdentifyInfo->SATACapabilities.TxDeviceInitiatedPMEnabled = MV_TRUE;
+            }
+        }
+    }
+
+    return MV_TRUE;
+}
+MV_BOOLEAN mvParseIdentifyPacketResult(MV_U16_PTR  iden,
+                                 ATA_IDENTIFY_INFO   *pIdentifyInfo)
+{
+    char    temp[80];
+    MV_U8  version = 6;
+    MV_BOOLEAN  udmaModeEnabled = MV_FALSE;
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "Parse IDENTIFY data:\n");
+    if ((iden[0] & 0x3) == 0)
+    {
+        pIdentifyInfo->commandPacketLength = 12;
+    }
+    else if ((iden[0] & 0x3) == 1)
+    {
+        pIdentifyInfo->commandPacketLength = 16;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "IDENTIFY info: bad command packet length\n");
+        
+        return MV_FALSE;
+    }
+
+    mvAta2HostString( iden + IDEN_MODEL_OFFSET, (MV_U16_PTR)temp, 24);
+    temp[25] = '\0';
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n","Model", temp);
+    memcpy(&pIdentifyInfo->model[0], iden + IDEN_MODEL_OFFSET, 24);
+    memcpy(&pIdentifyInfo->firmware[0], iden + IDEN_FIRMWARE_OFFSET, 4);
+    pIdentifyInfo->version = version;
+    /*DMA support*/
+    if ((version >= 6) && (!(iden[IDEN_CAPACITY_1_OFFSET] & MV_BIT8)))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "IDENTIFY info: DMA not "
+                 "supported\n");
+        return MV_FALSE;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "Capabilities",
+                 "DMA supported");
+    }
+
+
+    if ((version >= 7) && (iden[IDEN_UDMA_MODE] & MV_BIT6))
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_6;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT14)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else if ((version >= 6) && (iden[IDEN_UDMA_MODE] & MV_BIT5))
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_5;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT13)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else if ((version >= 5) && (iden[IDEN_UDMA_MODE] & MV_BIT4))
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_4;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT12)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else if ((version >= 4) && (iden[IDEN_UDMA_MODE] & MV_BIT3))
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_3;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT11)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else if (iden[IDEN_UDMA_MODE] & MV_BIT2)
+    {
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_2;
+        if (iden[IDEN_UDMA_MODE] & MV_BIT10)
+        {
+            udmaModeEnabled = MV_TRUE;
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "IDENTIFY info: Ultra"
+                 " DMA mode < 2 not supported IDENTIFY[88] 0x%04x\n",
+                 iden[IDEN_UDMA_MODE]);
+        pIdentifyInfo->UdmaMode = MV_ATA_TRANSFER_UDMA_0;
+        return MV_FALSE;
+    }
+    if (udmaModeEnabled == MV_TRUE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s%d%s\n",
+                 "Ultra DMA mode","UDMA mode ",
+                 pIdentifyInfo->UdmaMode - MV_ATA_TRANSFER_UDMA_0,
+                 " supported and enabled");
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s%d%s\n",
+                 "Ultra DMA mode","UDMA mode ",
+                 pIdentifyInfo->UdmaMode - MV_ATA_TRANSFER_UDMA_0,
+                 " supported but disabled");
+    }
+
+
+    if ((iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT3))
+    {
+
+        if (iden[IDEN_ENABLED_COMMANDS1] & MV_BIT3)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "POWER MANAGMENT", "supported and enabled");
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n",
+                     "POWER MANAGMENT", "supported and disabled");
+        }
+
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "POWER MANAGMENT","Not supported");
+    }
+
+    if ((iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT0))
+    {
+
+        if (iden[IDEN_ENABLED_COMMANDS1] & MV_BIT0)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n", "SMART",
+                     "supported and enabled");
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %20s\n", "SMART",
+                     "supported and disabled");
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "SMART",
+                 "Not supported");
+    }
+
+
+
+    /*check that the non-UDMA ATA commands supported*/
+
+    /*FLUSH CHACHE*/
+    if ((version >=6) && ((iden[IDEN_SUPPORTED_COMMANDS2] & MV_BIT12) == 0))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "FLUSH CACHE command", "not supported");
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n",
+                 "FLUSH CACHE command", "supported");
+    }
+
+    pIdentifyInfo->SATACapabilities.SATA_GEN_I_supported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.SATA_GEN_II_supported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.NCQSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.RxHostInitiatedPMSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.TxDeviceInitiatedPMSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.TxDeviceInitiatedPMEnabled = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.DMASetupAutoActiveSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.DMASetupAutoActiveEnables = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.NonZeroBufferOffsetSupported = MV_FALSE;
+    pIdentifyInfo->SATACapabilities.NonZeroBufferOffsetEnabled = MV_FALSE;
+
+    if (version >= 6)
+    {
+        if (iden[IDEN_SATA_CAPABILITIES] & MV_BIT1)
+        {
+            pIdentifyInfo->SATACapabilities.SATA_GEN_I_supported = MV_TRUE;
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "SATA Gen I",
+                     "not supported");
+        }
+        if (iden[IDEN_SATA_CAPABILITIES] & MV_BIT2)
+        {
+            pIdentifyInfo->SATACapabilities.SATA_GEN_II_supported = MV_TRUE;
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "SATA Gen II",
+                     "supported");
+        }
+
+        if (iden[IDEN_SATA_CAPABILITIES] & MV_BIT8)
+        {
+            pIdentifyInfo->SATACapabilities.NCQSupported = MV_TRUE;
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %s\n", "NCQ",
+                     "supported");
+        }
+
+        if (iden[IDEN_SATA_CAPABILITIES] & MV_BIT9)
+        {
+            pIdentifyInfo->SATACapabilities.RxHostInitiatedPMSupported = MV_TRUE;
+        }
+
+        if (iden[IDEN_SATA_FEATURES_SUPPORTED] & MV_BIT1)
+        {
+            pIdentifyInfo->SATACapabilities.NonZeroBufferOffsetSupported = MV_TRUE;
+            if (iden[IDEN_SATA_FEATURES_ENABLED] & MV_BIT1)
+            {
+                pIdentifyInfo->SATACapabilities.NonZeroBufferOffsetEnabled = MV_TRUE;
+            }
+        }
+        if (iden[IDEN_SATA_FEATURES_SUPPORTED] & MV_BIT2)
+        {
+            pIdentifyInfo->SATACapabilities.DMASetupAutoActiveSupported = MV_TRUE;
+            if (iden[IDEN_SATA_FEATURES_ENABLED] & MV_BIT2)
+            {
+                pIdentifyInfo->SATACapabilities.DMASetupAutoActiveEnables = MV_TRUE;
+            }
+        }
+        if (iden[IDEN_SATA_FEATURES_SUPPORTED] & MV_BIT3)
+        {
+            pIdentifyInfo->SATACapabilities.TxDeviceInitiatedPMSupported = MV_TRUE;
+            if (iden[IDEN_SATA_FEATURES_ENABLED] & MV_BIT3)
+            {
+                pIdentifyInfo->SATACapabilities.TxDeviceInitiatedPMEnabled = MV_TRUE;
+            }
+        }
+    }
+
+    return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvGetSataDeviceType - short description
+*
+* DESCRIPTION:
+*       None.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_SATA_DEVICE_TYPE mvGetSataDeviceType(
+                                       MV_STORAGE_DEVICE_REGISTERS *mvStorageDevRegisters)
+{
+    if (((mvStorageDevRegisters->sectorCountRegister & 0xff) != 1) ||
+        ((mvStorageDevRegisters->lbaLowRegister & 0xff) != 1))
+    {
+        return MV_SATA_DEVICE_TYPE_UNKNOWN;
+    }
+    if (((mvStorageDevRegisters->lbaMidRegister & 0xff) == 0) &&
+         ((mvStorageDevRegisters->lbaHighRegister & 0xff) == 0)) 
+    {
+        return MV_SATA_DEVICE_TYPE_ATA_DISK;
+    }
+    if ((((mvStorageDevRegisters->lbaMidRegister & 0xff) == 0x14) &&
+         ((mvStorageDevRegisters->lbaHighRegister & 0xff) == 0xEB))/* ||
+         (((mvStorageDevRegisters->lbaMidRegister & 0xff) == 0x69) &&
+         ((mvStorageDevRegisters->lbaHighRegister & 0xff) == 0x96))*/)
+    {
+        return MV_SATA_DEVICE_TYPE_ATAPI_DEVICE;
+    }
+    if (((mvStorageDevRegisters->lbaMidRegister & 0xff) == 0x69) &&
+        ((mvStorageDevRegisters->lbaHighRegister & 0xff) == 0x96))
+    {
+        return MV_SATA_DEVICE_TYPE_PM;
+    }
+   return MV_SATA_DEVICE_TYPE_UNKNOWN;
+}
+
+#ifdef MV_LOG_DEBUG
+static void printIdentifyBuffer(MV_U16_PTR identifyBuffer)
+{
+    MV_U8 i,j;
+    /*Print Identify buffer*/
+    for (i = 0; i < 0x20; i++)
+    {
+        mvLogMsg(MV_RAW_MSG_ID,  0, "Words [%03d-%03d]: ", i*8, i*8+7);
+        for (j = 0; j < 0x8; j++)
+        {
+            mvLogMsg(MV_RAW_MSG_ID,  0, "0x%04X ", identifyBuffer[i*8+j]);
+        }
+        mvLogMsg(MV_RAW_MSG_ID,  0, "\n");
+    }
+}
+#endif
+
+/*******************************************************************************
+* mvConfigSataDisk - short description
+*
+* DESCRIPTION:
+*       None.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvConfigSataDisk(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex,
+                            MV_U8 PMPort, ATA_IDENTIFY_INFO   *pIdentifyInfo,
+                            MV_U16_PTR identifyBuffer)
+{
+    MV_STORAGE_DEVICE_REGISTERS inATARegs;
+    MV_STORAGE_DEVICE_REGISTERS outATARegs;
+
+    /* identify device*/
+    memset(&inATARegs, 0, sizeof(inATARegs));
+    inATARegs.commandRegister = MV_ATA_COMMAND_IDENTIFY;
+    if (mvStorageDevATAIdentifyDevice(pSataAdapter, channelIndex, PMPort,
+                                      identifyBuffer)
+        == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: failed "
+                 "to perform ATA Identify command\n", pSataAdapter->adapterId,
+                 channelIndex, PMPort);
+        return MV_FALSE;
+    }
+#ifdef MV_LOG_DEBUG
+    mvLogMsg(MV_RAW_MSG_ID, 0, "Drive [%d,%d,%d] Identify Buffer:\n",
+             pSataAdapter->adapterId, channelIndex, PMPort);
+
+    printIdentifyBuffer(identifyBuffer);
+#endif
+    if (mvParseIdentifyResult(identifyBuffer, pIdentifyInfo) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: in "
+                 "parsing ATA Identify Data\n", pSataAdapter->adapterId,
+                 channelIndex, PMPort);
+        return MV_FALSE;
+    }
+    if ((pIdentifyInfo->writeCacheSupported == MV_TRUE) &&
+        (pIdentifyInfo->writeCacheEnabled == MV_FALSE))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG,"[%d %d %d]: Write Cache "
+                 "supported but disabled\n", pSataAdapter->adapterId,
+                 channelIndex, PMPort);
+        memset(&inATARegs, 0, sizeof(inATARegs));
+        inATARegs.commandRegister = MV_ATA_COMMAND_SET_FEATURES;
+        inATARegs.featuresRegister = MV_ATA_SET_FEATURES_ENABLE_WCACHE;
+
+        if (mvStorageDevExecutePIO(pSataAdapter, channelIndex, PMPort,
+                                   MV_NON_UDMA_PROTOCOL_NON_DATA,
+                                   MV_FALSE, NULL,0, &inATARegs, &outATARegs)
+            == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: "
+                     "Set Features failed(ENABLE WCACHE)\n",
+                     pSataAdapter->adapterId, channelIndex, PMPort);
+            return MV_FALSE;
+        }
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]: Write Cache "
+                 "enabled\n", pSataAdapter->adapterId, channelIndex, PMPort);
+    }
+    if ((pIdentifyInfo->readAheadSupported == MV_TRUE) &&
+        (pIdentifyInfo->readAheadEnabled == MV_FALSE))
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]: Read Look "
+                 "Ahead supported but disabled\n", pSataAdapter->adapterId,
+                 channelIndex, PMPort);
+        memset(&inATARegs, 0, sizeof(inATARegs));
+        inATARegs.commandRegister = MV_ATA_COMMAND_SET_FEATURES;
+        inATARegs.featuresRegister = MV_ATA_SET_FEATURES_ENABLE_RLA;
+        if (mvStorageDevExecutePIO(pSataAdapter, channelIndex, PMPort,
+                                   MV_NON_UDMA_PROTOCOL_NON_DATA,
+                                   MV_FALSE, NULL,0, &inATARegs, &outATARegs)
+            == MV_FALSE)
+        {
+            mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: "
+                     "Set Features failed(ENABLE RLA)\n",
+                     pSataAdapter->adapterId, channelIndex, PMPort);
+            return MV_FALSE;
+        }
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]: Read Look "
+                 "Ahead enabled\n", pSataAdapter->adapterId, channelIndex,
+                 PMPort);
+    }
+    /* mvStorageDevATASetFeatures */
+
+    /* Set transfer mode */
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]: Set transfer mode "
+             "XFER_PIO_SLOW\n", pSataAdapter->adapterId, channelIndex, PMPort);
+    memset(&inATARegs, 0, sizeof(inATARegs));
+    inATARegs.commandRegister = MV_ATA_COMMAND_SET_FEATURES;
+    inATARegs.featuresRegister = MV_ATA_SET_FEATURES_TRANSFER;
+    inATARegs.sectorCountRegister = MV_ATA_TRANSFER_PIO_SLOW;
+    if (mvStorageDevExecutePIO(pSataAdapter, channelIndex, PMPort,
+                               MV_NON_UDMA_PROTOCOL_NON_DATA,
+                               MV_FALSE, NULL,0, &inATARegs, &outATARegs) ==
+        MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: "
+                 "Set Features failed to set XFER PIO SLOW\n",
+                 pSataAdapter->adapterId, channelIndex, PMPort);
+
+        return MV_FALSE;
+    }
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]: Set transfer mode "
+             "XFER_PIO_%d\n", pSataAdapter->adapterId, channelIndex, PMPort,
+             pIdentifyInfo->PIOMode - MV_ATA_TRANSFER_PIO_0);
+
+    memset(&inATARegs, 0, sizeof(inATARegs));
+    inATARegs.commandRegister = MV_ATA_COMMAND_SET_FEATURES;
+    inATARegs.featuresRegister = MV_ATA_SET_FEATURES_TRANSFER;
+    inATARegs.sectorCountRegister = pIdentifyInfo->PIOMode;
+    if (mvStorageDevExecutePIO(pSataAdapter, channelIndex, PMPort,
+                               MV_NON_UDMA_PROTOCOL_NON_DATA,
+                               MV_FALSE, NULL,0, &inATARegs, &outATARegs) ==
+        MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: "
+                 "Set Features failed to set XFER PIO %d\n",
+                 pSataAdapter->adapterId, channelIndex, PMPort,
+                 pIdentifyInfo->PIOMode - MV_ATA_TRANSFER_PIO_0);
+        return MV_FALSE;
+    }
+
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]: Set transfer mode"
+             " XFER_UDMA_%d\n", pSataAdapter->adapterId, channelIndex, PMPort,
+             pIdentifyInfo->UdmaMode & 0xf);
+    memset(&inATARegs, 0, sizeof(inATARegs));
+    inATARegs.commandRegister = MV_ATA_COMMAND_SET_FEATURES;
+    inATARegs.featuresRegister = MV_ATA_SET_FEATURES_TRANSFER;
+    inATARegs.sectorCountRegister = pIdentifyInfo->UdmaMode;
+    if (mvStorageDevExecutePIO(pSataAdapter, channelIndex, PMPort,
+                               MV_NON_UDMA_PROTOCOL_NON_DATA,
+                               MV_FALSE, NULL,0, &inATARegs, &outATARegs) ==
+        MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: "
+                 "Set Features failed to set XFER UDMA %d\n",
+                 pSataAdapter->adapterId, channelIndex, PMPort,
+                 pIdentifyInfo->UdmaMode & 0xf);
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvInitSataDisk - short description
+*
+* DESCRIPTION:
+*       None.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_BOOLEAN mvInitSataDisk(MV_SATA_ADAPTER   *pSataAdapter, MV_U8 channelIndex,
+                          MV_U8 PMPort, ATA_IDENTIFY_INFO   *pIdentifyInfo,
+                          MV_U16_PTR identifyBuffer
+                         )
+{
+    pIdentifyInfo->deviceType = MV_SATA_DEVICE_TYPE_ATA_DISK;
+    if (mvConfigSataDisk(pSataAdapter, channelIndex, PMPort, pIdentifyInfo,
+                         identifyBuffer) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: Failed to"
+                 " Config Device\n", pSataAdapter->adapterId, channelIndex,
+                 PMPort);
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+#ifdef MV_SUPPORT_ATAPI
+MV_BOOLEAN mvInitSataATAPI(MV_SATA_ADAPTER   *pSataAdapter, MV_U8 channelIndex,
+                          MV_U8 PMPort, ATA_IDENTIFY_INFO   *pIdentifyInfo,
+                          MV_U16_PTR identifyBuffer
+                         )
+{
+    MV_STORAGE_DEVICE_REGISTERS inATARegs;
+    MV_STORAGE_DEVICE_REGISTERS outATARegs;
+
+    pIdentifyInfo->deviceType = MV_SATA_DEVICE_TYPE_ATAPI_DEVICE;
+    /* identify device*/
+    memset(&inATARegs, 0, sizeof(inATARegs));
+    inATARegs.commandRegister = MV_ATA_COMMAND_ATAPI_IDENTIFY;
+    inATARegs.featuresRegister = 0x1;
+    if (mvStorageDevExecutePIO(pSataAdapter, channelIndex, PMPort,
+                                   MV_NON_UDMA_PROTOCOL_PIO_DATA_IN,
+                                   MV_FALSE, identifyBuffer, 256, &inATARegs, &outATARegs)
+            == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: "
+                "failed to perform ATAPI Identify command\n",
+                pSataAdapter->adapterId, channelIndex, PMPort);
+        return MV_FALSE;
+    }
+
+#ifdef MV_LOG_DEBUG
+    mvLogMsg(MV_RAW_MSG_ID, 0, "Drive [%d,%d,%d] Identify Buffer:\n",
+             pSataAdapter->adapterId, channelIndex, PMPort);
+
+    printIdentifyBuffer(identifyBuffer);
+#endif
+    if (mvParseIdentifyPacketResult(identifyBuffer, pIdentifyInfo) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR,"[%d %d %d]: in "
+                 "parsing ATA Identify Data\n", pSataAdapter->adapterId,
+                 channelIndex, PMPort);
+        return MV_FALSE;
+    }
+    /* Set transfer mode */
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d %d]: Set transfer mode "
+             "XFER_PIO_SLOW\n", pSataAdapter->adapterId, channelIndex, PMPort);
+    mvMicroSecondsDelay(NULL, 1000);
+    memset(&inATARegs, 0, sizeof(inATARegs));
+    inATARegs.commandRegister = MV_ATA_COMMAND_SET_FEATURES;
+    inATARegs.featuresRegister = MV_ATA_SET_FEATURES_TRANSFER;
+    inATARegs.sectorCountRegister = MV_ATA_TRANSFER_UDMA_2;
+    if (mvStorageDevExecutePIO(pSataAdapter, channelIndex, PMPort,
+                               MV_NON_UDMA_PROTOCOL_NON_DATA,
+                               MV_FALSE, NULL,0, &inATARegs, &outATARegs) ==
+        MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: "
+                 "Set Features failed to set XFER mode\n",
+                 pSataAdapter->adapterId, channelIndex, PMPort);
+
+        return MV_FALSE;
+    }
+    return MV_TRUE;
+}
+#endif
+MV_BOOLEAN  mvGetPMDeviceInfo(MV_SATA_ADAPTER   *pSataAdapter,
+                              MV_U8 channelIndex,
+                              MV_SATA_PM_DEVICE_INFO *pPMDeviceInfo)
+{
+    MV_U32  regVal;
+
+    if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                       MV_SATA_GSCR_ID_REG_NUM, &regVal, NULL) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
+                 "mvGetPMDeviceInfo Failed", pSataAdapter->adapterId,
+                 channelIndex);
+        return MV_FALSE;
+    }
+    pPMDeviceInfo->vendorId = (MV_U16)(regVal & 0xffff);
+    pPMDeviceInfo->deviceId = (MV_U16)((regVal & 0xffff0000) >> 16);
+
+    if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                       MV_SATA_GSCR_REVISION_REG_NUM, &regVal, NULL)== MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
+                 "mvGetPMDeviceInfo Failed", pSataAdapter->adapterId,
+                 channelIndex);
+        return MV_FALSE;
+    }
+
+    pPMDeviceInfo->PMSpecRevision = (MV_U8)(regVal & 0xff);
+    pPMDeviceInfo->productRevision = (MV_U8)((regVal & 0xff00) >> 8);
+
+    if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT,
+                       MV_SATA_GSCR_INFO_REG_NUM, &regVal, NULL)== MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
+                 "mvGetPMDeviceInfo Failed", pSataAdapter->adapterId,
+                 channelIndex);
+        return MV_FALSE;
+    }
+    pPMDeviceInfo->numberOfPorts = (MV_U8)(regVal & 0xf);
+
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: PM Information:\n",
+             pSataAdapter->adapterId,channelIndex);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %04x\n", "Vendor Id", pPMDeviceInfo->vendorId);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %04x\n", "Device Id", pPMDeviceInfo->deviceId);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %02x\n", "Product Revision", pPMDeviceInfo->productRevision);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %02x\n", "Spec Revision", pPMDeviceInfo->PMSpecRevision);
+    mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%25s - %02x\n", "Fan-out ports", pPMDeviceInfo->numberOfPorts);
+    return MV_TRUE;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommonUtils.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommonUtils.h
new file mode 100755
index 0000000..528060d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvIALCommonUtils.h
@@ -0,0 +1,140 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvIALCommonUtils.h
+*
+* DESCRIPTION:
+*       H implementation for IAL's extension utility functions.
+*
+* DEPENDENCIES:
+*   mvSata.h
+*   mvStorageDev.h
+*
+*******************************************************************************/
+#ifndef __INCmvIALCommonUtilsh
+#define __INCmvIALCommonUtilsh
+
+#ifdef __cplusplus
+extern "C"  {
+#endif /* __cplusplus */
+
+/* includes */
+#include "mvSata.h"
+#include "mvStorageDev.h"
+
+/* defines */
+#define MV_IAL_COMMON_LOG_ID            2
+
+/* typedefs */
+typedef struct serialATACapabilites
+{
+    MV_BOOLEAN  SATA_GEN_I_supported:1;
+    MV_BOOLEAN  SATA_GEN_II_supported:1;
+    MV_BOOLEAN  NCQSupported:1;/*native command queuing*/
+    MV_BOOLEAN  RxHostInitiatedPMSupported:1;/* Supports receipt of host-initiated
+                                              interface power management
+                                              requests*/
+    MV_BOOLEAN  TxDeviceInitiatedPMSupported:1;/* device supports initiating
+                                                interface power management*/
+    MV_BOOLEAN  TxDeviceInitiatedPMEnabled:1;
+    MV_BOOLEAN  DMASetupAutoActiveSupported:1;/* supports DMA Setup Auto-Activate
+                                               optimization*/
+    MV_BOOLEAN  DMASetupAutoActiveEnables:1;
+    MV_BOOLEAN  NonZeroBufferOffsetSupported:1;/* supports non-zero buffer offsets
+                                                in DMA Setup FIS*/
+    MV_BOOLEAN  NonZeroBufferOffsetEnabled:1;
+}SERIAL_ATA_CAPABILITIES;
+
+typedef struct ATAIdentifyInfo
+{
+    MV_U8           version;
+    MV_U8           model[24];
+    MV_U8           firmware[4];
+    MV_U8           UdmaMode;
+    MV_U8           PIOMode;
+    MV_BOOLEAN      LBA48Supported:1;/* used for READ/WRITE commands*/
+    MV_BOOLEAN      writeCacheSupported:1;
+    MV_BOOLEAN      writeCacheEnabled:1;
+    MV_BOOLEAN      readAheadSupported:1;
+    MV_BOOLEAN      readAheadEnabled:1;
+    MV_BOOLEAN      DMAQueuedModeSupported:1;
+    MV_U8           DMAQueuedModeDepth;
+    MV_U64          ATADiskSize;
+    SERIAL_ATA_CAPABILITIES SATACapabilities;/*valid only for ATA-7 or higher*/
+    MV_U8           commandPacketLength;
+    MV_SATA_DEVICE_TYPE deviceType;
+} ATA_IDENTIFY_INFO;
+
+
+typedef struct mvSataPMDeviceInfo
+{
+    MV_U16      vendorId;
+    MV_U16      deviceId;
+    MV_U8       productRevision;
+    MV_U8       PMSpecRevision:4;
+    MV_U8       numberOfPorts:4;
+} MV_SATA_PM_DEVICE_INFO;
+
+
+MV_BOOLEAN mvParseIdentifyResult(MV_U16_PTR  iden,ATA_IDENTIFY_INFO *pIdentifyInfo);
+
+MV_SATA_DEVICE_TYPE mvGetSataDeviceType(MV_STORAGE_DEVICE_REGISTERS *mvStorageDevRegisters);
+
+MV_BOOLEAN mvInitSataDisk(MV_SATA_ADAPTER   *pSataAdapter, MV_U8 channelIndex,
+                          MV_U8 PMPort, ATA_IDENTIFY_INFO   *pIdentifyInfo,
+                          MV_U16_PTR identifyBuffer
+                         );
+
+MV_BOOLEAN mvInitSataATAPI(MV_SATA_ADAPTER   *pSataAdapter, MV_U8 channelIndex,
+                          MV_U8 PMPort, ATA_IDENTIFY_INFO   *pIdentifyInfo,
+                          MV_U16_PTR identifyBuffer
+                         );
+
+
+MV_BOOLEAN  mvGetPMDeviceInfo(MV_SATA_ADAPTER   *pSataAdapter,
+                              MV_U8 channelIndex,
+                              MV_SATA_PM_DEVICE_INFO *pPMDeviceInfo);
+
+MV_VOID mvSelectConfiguration(MV_SATA_ADAPTER        *pSataAdapter,
+                              MV_U8                  channelIndex,
+                              MV_SATA_GEN            gen,
+                              MV_SATA_DEVICE_TYPE    connectedDevice,
+                              MV_SATA_PM_DEVICE_INFO *pPMInfo,
+                              MV_BOOLEAN             AllNCQ,
+                              MV_BOOLEAN             AllTCQ,
+                              MV_BOOLEAN             disks,
+                              MV_EDMA_MODE           *pEdmaMode,
+                              MV_SATA_SWITCHING_MODE *pSwitchingMode,
+                              MV_BOOLEAN             *pUse128Entries);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INCmvIALCommonh */
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalHt.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalHt.c
new file mode 100755
index 0000000..770c2bd
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalHt.c
@@ -0,0 +1,2133 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* file_name - mvLinuxIalHt.c
+*
+* DESCRIPTION:  implementation for Linux IAL.
+*
+* DEPENDENCIES:
+*   mvLinuxIalHt.h
+*   mvLinuxIalLib.h
+*   Linux Os header files
+*   Core driver header files
+*
+*
+*******************************************************************************/
+
+/* includes */
+
+#ifndef LINUX_VERSION_CODE
+    #include <linux/version.h>
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+    #error "This driver works only with kernel 2.4.0 or higher!"
+#endif
+
+#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)))
+    #error "This driver does not support kernel 2.5!"
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/kdev_t.h>
+#include <linux/hdreg.h>
+
+#ifdef CONFIG_MV_INCLUDE_INTEG_SATA
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mvSysSataApi.h"
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include <linux/blk.h>
+#include "scsi.h"
+#include "hosts.h"
+#else
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#endif
+
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <asm/dma.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "mvLinuxIalHt.h"
+#include "mvRegs.h"
+#include "mvIALCommon.h"
+#include "mvLinuxIalSmart.h"
+
+extern Scsi_Host_Template driver_template;
+
+static void mv_ial_init_log(void);
+
+static char mv_ial_proc_version[]="Version_1_1";
+extern void release_ata_mem(struct mv_comp_info * pInfo);
+extern MV_BOOLEAN IALCompletion(struct mvSataAdapter *pSataAdapter,
+                                MV_SATA_SCSI_CMD_BLOCK *pCmdBlock);
+
+static struct pci_device_id mvSata_pci_table[] =
+{
+    {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_5080, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+    {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_5081, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+    {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_5040, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+    {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_5041, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+    {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_6081, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+    {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_6041, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+    {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_6042, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+    {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_7042, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+    {0,}
+};
+
+
+int          adapterId = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+
+#ifndef __devexit_p
+#define __devexit_p(x)  x
+#endif
+static void mv_ial_ht_select_queue_depths (struct Scsi_Host* pHost,
+                                           struct scsi_device* pDevs);
+
+
+static inline struct Scsi_Host *scsi_host_alloc(Scsi_Host_Template *t, size_t s)
+{
+    return scsi_register(t, s);
+}
+static inline void scsi_host_put(struct Scsi_Host *h)
+{
+    scsi_unregister(h);
+}
+
+#define scsi_scan_host(x...)
+#define scsi_remove_host(x...)
+
+#else
+
+static int mv_ial_ht_slave_configure (struct scsi_device* pDevs);
+static int __devinit  mv_ial_probe_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
+static void __devexit mv_ial_remove_device(struct pci_dev *pci_dev);
+
+
+MODULE_DEVICE_TABLE(pci, mvSata_pci_table);
+
+static char mv_hot_plug_name[] = "mvSata";
+
+static struct pci_driver mv_ial_pci_driver =
+{
+    .name       = mv_hot_plug_name,
+    .id_table   = mvSata_pci_table,
+    .probe      = mv_ial_probe_device,
+    .remove     = __devexit_p(mv_ial_remove_device),
+};
+
+#ifdef CONFIG_MV_INCLUDE_INTEG_SATA
+static int __devinit mv_ial_init_soc_sata(void);
+#endif
+IAL_ADAPTER_T       *pSocAdapter = NULL;
+
+
+static int __init mv_ial_init(void)
+{
+    mv_ial_init_log();
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "mvSata init.\n");
+    driver_template.module = THIS_MODULE;
+#ifdef CONFIG_MV_INCLUDE_INTEG_SATA
+	if (MV_FALSE == mvCtrlPwrClckGet(SATA_UNIT_ID, 0)) 
+	{
+		printk("\nWarning Sata is Powered Off\n");
+	}
+	else
+	{
+		printk("Integrated Sata device found\n");
+        	mv_ial_init_soc_sata();
+	}
+#endif
+    return (int)pci_register_driver(&mv_ial_pci_driver);
+}
+
+static void __exit mv_ial_exit(void)
+{
+
+#ifdef CONFIG_MV_INCLUDE_INTEG_SATA
+      mv_ial_remove_device(NULL);
+#endif
+    pci_unregister_driver(&mv_ial_pci_driver);
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "mvSata exit.\n");
+}
+
+module_init(mv_ial_init);
+module_exit(mv_ial_exit);
+
+#endif
+
+
+static void mv_ial_init_log(void)
+{
+#ifdef MV_LOGGER
+    char *szModules[] = {"Core Driver",
+        "SAL",
+        "Common IAL",
+        "Linux IAL"
+    };
+#if defined (MV_LOG_DEBUG)
+    mvLogRegisterModule(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ENABLE_ALL,
+                        szModules[MV_CORE_DRIVER_LOG_ID]);
+    mvLogRegisterModule(MV_SAL_LOG_ID, MV_DEBUG_ENABLE_ALL,
+                        szModules[MV_SAL_LOG_ID]);
+    mvLogRegisterModule(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ENABLE_ALL,
+                        szModules[MV_IAL_COMMON_LOG_ID]);
+    mvLogRegisterModule(MV_IAL_LOG_ID, MV_DEBUG_ENABLE_ALL,
+                        szModules[MV_IAL_LOG_ID]);
+#elif defined (MV_LOG_ERROR)
+    mvLogRegisterModule(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_ERROR |
+			MV_DEBUG_INFO,
+                        szModules[MV_CORE_DRIVER_LOG_ID]);
+    mvLogRegisterModule(MV_SAL_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_ERROR |
+			MV_DEBUG_INFO,
+                        szModules[MV_SAL_LOG_ID]);
+    mvLogRegisterModule(MV_IAL_COMMON_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_ERROR |
+			MV_DEBUG_INFO,
+                        szModules[MV_IAL_COMMON_LOG_ID]);
+    mvLogRegisterModule(MV_IAL_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_ERROR | 
+			MV_DEBUG_INFO,
+                        szModules[MV_IAL_LOG_ID]);
+#endif
+#endif
+}
+
+/****************************************************************
+ *  Name: set_device_regs
+ *
+ *  Description:    initialize the device registers.
+ *
+ *  Parameters:     pMvSataAdapter, pointer to the Device data structure.
+ *          pcidev, pointer to the pci device data structure.
+ *
+ *  Returns:        =0 ->success, < 0 ->failure.
+ *
+ ****************************************************************/
+static int set_device_regs(MV_SATA_ADAPTER *pMvSataAdapter,
+                           struct pci_dev   *pcidev)
+{
+    pMvSataAdapter->intCoalThre[0]= MV_IAL_HT_SACOALT_DEFAULT;
+    pMvSataAdapter->intCoalThre[1]= MV_IAL_HT_SACOALT_DEFAULT;
+    pMvSataAdapter->intTimeThre[0] = MV_IAL_HT_SAITMTH_DEFAULT;
+    pMvSataAdapter->intTimeThre[1] = MV_IAL_HT_SAITMTH_DEFAULT;
+    pMvSataAdapter->pciCommand = MV_PCI_COMMAND_REG_DEFAULT;
+    pMvSataAdapter->pciSerrMask = MV_PCI_SERR_MASK_REG_ENABLE_ALL;
+    pMvSataAdapter->pciInterruptMask = MV_PCI_INTERRUPT_MASK_REG_ENABLE_ALL;
+    pMvSataAdapter->mvSataEventNotify = mv_ial_lib_event_notify;
+
+    return 0;
+}
+
+
+static int mv_ial_get_num_of_ports(const struct pci_device_id *id)
+{
+    switch(id->device)
+    {
+        case MV_SATA_DEVICE_ID_5080:
+        case MV_SATA_DEVICE_ID_5081:
+        case MV_SATA_DEVICE_ID_6081:
+            return 8;
+        case MV_SATA_DEVICE_ID_5040:
+        case MV_SATA_DEVICE_ID_5041:
+        case MV_SATA_DEVICE_ID_6041:
+        case MV_SATA_DEVICE_ID_6042:
+        case MV_SATA_DEVICE_ID_7042:
+            return 4;
+        default:
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_FATAL_ERROR,
+                     "getMaxNumberOfPorts() Unknown device ID.\n");
+            return 0;
+    }
+}
+
+static void mv_ial_free_scsi_hosts(IAL_ADAPTER_T *pAdapter, MV_BOOLEAN freeAdapter)
+{
+    int i;
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if (pAdapter->host[i] != NULL)
+        {
+            mv_ial_lib_prd_destroy(pAdapter->host[i]);
+            scsi_host_put(pAdapter->host[i]->scsihost);
+            pAdapter->host[i] = NULL;
+        }
+    }
+    pAdapter->activeHosts = 0;
+    if (MV_TRUE == freeAdapter)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG,
+                     "[%d] freeing Adapter data structure.\n", pAdapter->mvSataAdapter.adapterId);
+        kfree(pAdapter);
+    }
+}
+
+
+
+
+static int __devinit  mv_ial_probe_device(struct pci_dev *pcidev,
+                                          const struct pci_device_id *id)
+{
+
+    MV_SATA_ADAPTER     *pMvSataAdapter;
+    IAL_ADAPTER_T       *pAdapter;
+    MV_U8                 i;
+
+    pci_set_drvdata(pcidev, NULL);
+
+    if (pci_enable_device(pcidev))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,
+                 "pci_enable_device() failed\n");
+        return -ENODEV;
+    }
+
+    pci_set_master(pcidev);
+    if (0 == pci_set_dma_mask(pcidev, 0xffffffffffffffffULL))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG,"using 64-bit DMA.\n");
+    }
+    else if (0 == pci_set_dma_mask(pcidev, 0xffffffffUL))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "using 32-bit DMA.\n");
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "DMA 32-bit not supported"
+                 " in the system\n");
+        pci_disable_device(pcidev);
+        return -ENODEV;
+    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    if (pci_request_regions(pcidev, mv_hot_plug_name) != 0)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "pci_request_regions() failed\n");
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+#endif
+
+
+    pAdapter = (IAL_ADAPTER_T*)kmalloc(sizeof(IAL_ADAPTER_T), GFP_ATOMIC);
+    if (pAdapter == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "IAL Adapter allocation failed\n");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    memset(pAdapter, 0, sizeof(IAL_ADAPTER_T));
+    pAdapter->activeHosts = 0;
+    pAdapter->maxHosts = mv_ial_get_num_of_ports(id);
+    if (pAdapter->maxHosts == 0)
+    {
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "mv_ial_get_num_of_ports() failed\n");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        struct Scsi_Host    *pshost = scsi_host_alloc(&driver_template, sizeof(IAL_HOST_T));
+        if (pshost == NULL)
+        {
+            mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "Scsi_Host allocation failed\n");
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            pci_release_regions(pcidev);
+ #endif
+            pci_disable_device(pcidev);
+            return -ENOMEM;
+        }
+        pAdapter->host[i] = HOSTDATA(pshost);
+        memset(pAdapter->host[i], 0, sizeof(IAL_HOST_T));
+        pAdapter->host[i]->scsihost = pshost;
+        pAdapter->host[i]->pAdapter = pAdapter;
+        pAdapter->host[i]->channelIndex = (MV_U8)i;
+        pAdapter->activeHosts |= (1 << i);
+    }
+    pAdapter->pcidev = pcidev;
+    pMvSataAdapter = &(pAdapter->mvSataAdapter);
+    pMvSataAdapter->IALData = pAdapter;
+    spin_lock_init (&pAdapter->adapter_lock);
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        pAdapter->host[i]->scsi_cmnd_done_head = NULL;
+        pAdapter->host[i]->scsi_cmnd_done_tail = NULL;
+    }
+    
+    pAdapter->host[0]->scsihost->base = pci_resource_start(pcidev, 0);
+    for (i = 1; i < pAdapter->maxHosts; i++)
+    {
+        if (pAdapter->host[i] != NULL)
+            pAdapter->host[i]->scsihost->base = pAdapter->host[0]->scsihost->base;
+    }
+    pMvSataAdapter->adapterIoBaseAddress =
+        (MV_BUS_ADDR_T)ioremap(pAdapter->host[0]->scsihost->base,
+                               pci_resource_len(pcidev, 0));
+    if (!pMvSataAdapter->adapterIoBaseAddress)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "Failed to remap memory io spcae\n");
+        
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "io base address 0x%08lx\n",
+                 (ulong)pMvSataAdapter->adapterIoBaseAddress);
+    }
+    
+    pMvSataAdapter->adapterId = adapterId++;
+    /* get the revision ID */
+    if (pci_read_config_byte(pcidev, PCI_REVISION_ID, &pAdapter->rev_id))
+    {
+        printk(KERN_WARNING "mvSata: Failed to get revision id.\n");
+        iounmap(pMvSataAdapter->adapterIoBaseAddress);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    pMvSataAdapter->pciConfigRevisionId = pAdapter->rev_id;
+    pMvSataAdapter->pciConfigDeviceId = id->device;
+    if (set_device_regs(pMvSataAdapter, pcidev))
+    {
+        iounmap(pMvSataAdapter->adapterIoBaseAddress);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    /*Do not allow hotplug handler to work*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    init_MUTEX(&pAdapter->rescan_mutex);
+    atomic_set(&pAdapter->stopped, 1);
+#endif
+
+    if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: core failed to initialize the adapter\n",
+                 pMvSataAdapter->adapterId);
+        iounmap(pMvSataAdapter->adapterIoBaseAddress);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    if (mv_ial_lib_allocate_edma_queues(pAdapter))
+    {
+        mvLogMsg(MV_IAL_LOG_ID,MV_DEBUG_ERROR,
+                 "Failed to allocate memory for EDMA queues\n");
+        iounmap(pMvSataAdapter->adapterIoBaseAddress);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if ((pAdapter->activeHosts & (1 << i)) == 0)
+        {
+            continue;
+        }
+        if (mv_ial_lib_prd_init(pAdapter->host[i]))
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,
+                     "Failed to init PRD memory manager - host %d\n", i);
+            iounmap(pMvSataAdapter->adapterIoBaseAddress);
+            mv_ial_lib_free_edma_queues(pAdapter);
+            mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            pci_release_regions(pcidev);
+#endif
+            pci_disable_device(pcidev);
+            return -ENOMEM;
+        }
+    }
+    pAdapter->ataScsiAdapterExt = (MV_SAL_ADAPTER_EXTENSION*)kmalloc(sizeof(MV_SAL_ADAPTER_EXTENSION),
+                                                                     GFP_ATOMIC);
+    if (pAdapter->ataScsiAdapterExt == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR,"[%d]: out of memory, failed to allocate MV_SAL_ADAPTER_EXTENSION\n",
+                 pAdapter->mvSataAdapter.adapterId);
+        iounmap(pMvSataAdapter->adapterIoBaseAddress);
+        mv_ial_lib_free_edma_queues(pAdapter);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    mvSataScsiInitAdapterExt(pAdapter->ataScsiAdapterExt,
+                             pMvSataAdapter);
+    /* let SAL report only the BUS RESET UA event*/
+    pAdapter->ataScsiAdapterExt->UAMask = MV_BIT0;
+    /* enable device interrupts even if no storage devices connected now*/
+#ifdef MV_SUPPORT_MSI
+    {
+    	int err;
+	if ((err = pci_enable_msi(pcidev)))
+	{
+	    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: Unable to allocate MSI interrupt Error: %d\n",
+		    pMvSataAdapter->adapterId, err);
+	}
+    }
+#endif
+
+    if (request_irq(pcidev->irq, mv_ial_lib_int_handler,
+                    (IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED), "mvSata",
+                    pAdapter) < 0)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: unable to allocate IRQ for controler\n",
+                 pMvSataAdapter->adapterId);
+#ifdef MV_SUPPORT_MSI
+	pci_disable_msi(pAdapter->pcidev);
+#endif
+        kfree(pAdapter->ataScsiAdapterExt);
+        iounmap(pMvSataAdapter->adapterIoBaseAddress);
+        mv_ial_lib_free_edma_queues(pAdapter);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if ((pAdapter->activeHosts & (1 << i)) == 0)
+        {
+            continue;
+        }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        scsi_set_device(pAdapter->host[i]->scsihost, &pcidev->dev);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        scsi_set_pci_device(pAdapter->host[i]->scsihost, pcidev);
+#endif
+        pAdapter->host[i]->scsihost->irq = pcidev->irq;
+        /* each SATA channel will emulate scsi host !!!*/
+        if (pMvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
+        {
+            pAdapter->host[i]->scsihost->max_id = 1;
+        }
+        else
+        {
+            pAdapter->host[i]->scsihost->max_id = MV_SATA_PM_MAX_PORTS;
+        }
+        pAdapter->host[i]->scsihost->max_lun = 1;
+        pAdapter->host[i]->scsihost->max_channel = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        pAdapter->host[i]->scsihost->select_queue_depths = mv_ial_ht_select_queue_depths;
+#endif
+    }
+    if (MV_FALSE == mvAdapterStartInitialization(pMvSataAdapter,
+                                                 &pAdapter->ialCommonExt,
+                                                 pAdapter->ataScsiAdapterExt))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: mvAdapterStartInitialization"
+                 " Failed\n", pMvSataAdapter->adapterId);
+        free_irq (pcidev->irq, pMvSataAdapter);
+#ifdef MV_SUPPORT_MSI
+	pci_disable_msi(pAdapter->pcidev);
+#endif
+        kfree(pAdapter->ataScsiAdapterExt);
+        iounmap(pMvSataAdapter->adapterIoBaseAddress);
+        mv_ial_lib_free_edma_queues(pAdapter);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        pci_release_regions(pcidev);
+#endif
+        pci_disable_device(pcidev);
+        return -ENOMEM;
+    }
+    pci_set_drvdata(pcidev, pAdapter);
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if ((pAdapter->activeHosts & (1 << i)) == 0)
+        {
+            continue;
+        }
+        mv_ial_block_requests(pAdapter, i);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        if (scsi_add_host(pAdapter->host[i]->scsihost, &pcidev->dev) != 0)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: scsi_add_host() failed.\n"
+                     , pMvSataAdapter->adapterId);
+            free_irq (pcidev->irq, pMvSataAdapter);
+#ifdef MV_SUPPORT_MSI
+	    pci_disable_msi(pAdapter->pcidev);
+#endif
+	    kfree(pAdapter->ataScsiAdapterExt);
+            iounmap(pMvSataAdapter->adapterIoBaseAddress);
+            mv_ial_lib_free_edma_queues(pAdapter);
+            mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+            pci_release_regions(pcidev);
+            pci_disable_device(pcidev);
+            return -ENODEV;
+        }
+#endif
+    }
+
+    pAdapter->stopAsyncTimer = MV_FALSE;
+    init_timer(&pAdapter->asyncStartTimer);
+    pAdapter->asyncStartTimer.data = (unsigned long)pAdapter;
+    pAdapter->asyncStartTimer.function = asyncStartTimerFunction;
+    pAdapter->asyncStartTimer.expires = jiffies + MV_LINUX_ASYNC_TIMER_PERIOD;
+    add_timer (&pAdapter->asyncStartTimer);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if ((pAdapter->activeHosts & (1 << i)) != 0)
+        {
+            scsi_scan_host(pAdapter->host[i]->scsihost);
+        }
+    }
+    /*Enable hotplug handler*/
+    atomic_set(&pAdapter->stopped, 0);
+#endif
+    return 0;
+}
+
+#ifdef CONFIG_MV_INCLUDE_INTEG_SATA
+static int __devinit mv_ial_init_soc_sata(void)
+{
+    MV_SATA_ADAPTER     *pMvSataAdapter;
+    IAL_ADAPTER_T       *pAdapter;
+    MV_U8                 i;
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+    if (MV_FALSE == mvSocUnitIsMappedToThisCpu(SATA))
+    {
+	printk(KERN_INFO"Integrated SATA is not mapped to this CPU\n");
+	return -ENODEV;
+    }	
+#endif        	
+
+//    mvSataWinInit();
+    
+    pAdapter = (IAL_ADAPTER_T*)kmalloc(sizeof(IAL_ADAPTER_T), GFP_ATOMIC);
+    if (pAdapter == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "IAL Adapter allocation failed\n");
+        return -ENOMEM;
+    }
+    pSocAdapter = pAdapter;
+    memset(pAdapter, 0, sizeof(IAL_ADAPTER_T));
+    pAdapter->activeHosts = 0;
+
+    if(MV_5182_DEV_ID == mvCtrlModelGet())
+	pAdapter->maxHosts = MV_SATA_5182_PORT_NUM;
+    else if(MV_5082_DEV_ID == mvCtrlModelGet())
+	pAdapter->maxHosts = MV_SATA_5082_PORT_NUM;
+    else if(MV_6082_DEV_ID == mvCtrlModelGet())
+	pAdapter->maxHosts = MV_SATA_6082_PORT_NUM;
+#ifdef MV88F6281
+    else if(MV_6281_DEV_ID == mvCtrlModelGet())
+	pAdapter->maxHosts = MV_SATA_6281_PORT_NUM;
+    else if(MV_6192_DEV_ID == mvCtrlModelGet())
+	pAdapter->maxHosts = MV_SATA_6192_PORT_NUM;
+    else if(MV_6190_DEV_ID == mvCtrlModelGet())
+        pAdapter->maxHosts = MV_SATA_6190_PORT_NUM;
+    else if(MV_6282_DEV_ID == mvCtrlModelGet())
+        pAdapter->maxHosts = MV_SATA_6282_PORT_NUM;
+#endif
+    else if ((mvCtrlModelGet() == MV_78100_DEV_ID) || 
+		(mvCtrlModelGet() == MV_78200_DEV_ID) || 
+		(mvCtrlModelGet() == MV_78XX0_DEV_ID))
+	    pAdapter->maxHosts = MV_SATA_78XX0_PORT_NUM;
+    else if (mvCtrlModelGet() == MV_76100_DEV_ID)
+		pAdapter->maxHosts = MV_SATA_76100_PORT_NUM;
+    else if (mvCtrlModelGet() == MV_6323_DEV_ID)
+		pAdapter->maxHosts = MV_SATA_6323_PORT_NUM;
+    else if ((mvCtrlModelGet() == MV_6510_DEV_ID) ||
+	     (mvCtrlModelGet() == MV_6530_DEV_ID) ||
+	     (mvCtrlModelGet() == MV_6550_DEV_ID) ||
+	     (mvCtrlModelGet() == MV_6560_DEV_ID))
+		pAdapter->maxHosts = MV_SATA_65XX_PORT_NUM;
+
+	for (i = 0; i < pAdapter->maxHosts; i++)
+	{	
+		if (MV_FALSE == mvCtrlPwrClckGet(SATA_UNIT_ID, (MV_U32)i))
+		{
+			printk("Warning: SATA %d is powered off\n", i);
+			mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+			return -ENOMEM;
+		}
+	}
+    
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        struct Scsi_Host    *pshost = scsi_host_alloc(&driver_template, sizeof(IAL_HOST_T));
+        if (pshost == NULL)
+        {
+            mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "Scsi_Host allocation failed\n");
+            return -ENOMEM;
+        }
+        pAdapter->host[i] = HOSTDATA(pshost);
+        memset(pAdapter->host[i], 0, sizeof(IAL_HOST_T));
+        pAdapter->host[i]->scsihost = pshost;
+        pAdapter->host[i]->pAdapter = pAdapter;
+        pAdapter->host[i]->channelIndex = (MV_U8)i;
+        pAdapter->activeHosts |= (1 << i);
+    }
+    pAdapter->pcidev = NULL;
+    pMvSataAdapter = &(pAdapter->mvSataAdapter);
+    pMvSataAdapter->IALData = pAdapter;
+    spin_lock_init (&pAdapter->adapter_lock);
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        pAdapter->host[i]->scsi_cmnd_done_head = NULL;
+        pAdapter->host[i]->scsi_cmnd_done_tail = NULL;
+    }
+    
+    pAdapter->host[0]->scsihost->base = 0/*pci_resource_start(pcidev, 0)*/;
+    for (i = 1; i < pAdapter->maxHosts; i++)
+    {
+        if (pAdapter->host[i] != NULL)
+            pAdapter->host[i]->scsihost->base = pAdapter->host[0]->scsihost->base;
+    }
+    pMvSataAdapter->adapterIoBaseAddress = (MV_BUS_ADDR_T)(INTER_REGS_BASE + MV_SATA_REGS_OFFSET - 
+                                            0x20000);
+    
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "io base address 0x%08lx\n",
+             (ulong)pMvSataAdapter->adapterIoBaseAddress);
+    
+    pMvSataAdapter->adapterId = adapterId++;
+    /* get the revision ID */
+    
+    pMvSataAdapter->pciConfigRevisionId = 0;
+    pMvSataAdapter->pciConfigDeviceId = mvCtrlModelGet();
+    if (set_device_regs(pMvSataAdapter, NULL))
+    {
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+        return -ENOMEM;
+    }
+    /*Do not allow hotplug handler to work*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    init_MUTEX(&pAdapter->rescan_mutex);
+    atomic_set(&pAdapter->stopped, 1);
+#endif
+
+    if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,
+                 "[%d]: core failed to initialize the adapter\n",
+                 pMvSataAdapter->adapterId);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+        return -ENOMEM;
+    }
+    if (mv_ial_lib_allocate_edma_queues(pAdapter))
+    {
+        mvLogMsg(MV_IAL_LOG_ID,MV_DEBUG_ERROR,
+                 "Failed to allocate memory for EDMA queues\n");
+
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+        return -ENOMEM;
+    }
+
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if ((pAdapter->activeHosts & (1 << i)) == 0)
+        {
+            continue;
+        }
+        if (mv_ial_lib_prd_init(pAdapter->host[i]))
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,
+                     "Failed to init PRD memory manager - host %d\n", i);
+            mv_ial_lib_free_edma_queues(pAdapter);
+            mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+            return -ENOMEM;
+        }
+    }
+    pAdapter->ataScsiAdapterExt = (MV_SAL_ADAPTER_EXTENSION*)kmalloc(sizeof(MV_SAL_ADAPTER_EXTENSION),
+                                                                     GFP_ATOMIC);
+    if (pAdapter->ataScsiAdapterExt == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR,"[%d]: out of memory, failed to allocate MV_SAL_ADAPTER_EXTENSION\n",
+                 pAdapter->mvSataAdapter.adapterId);
+        mv_ial_lib_free_edma_queues(pAdapter);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+        return -ENOMEM;
+    }
+    mvSataScsiInitAdapterExt(pAdapter->ataScsiAdapterExt,
+                             pMvSataAdapter);
+    /* let SAL report only the BUS RESET UA event*/
+    pAdapter->ataScsiAdapterExt->UAMask = MV_BIT0;
+    /* enable device interrupts even if no storage devices connected now*/
+    if (request_irq(SATA_IRQ_NUM, mv_ial_lib_int_handler,
+                    (IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED), "mvSata",
+                    pAdapter) < 0)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: unable to allocate IRQ for controler\n",
+                 pMvSataAdapter->adapterId);
+        kfree(pAdapter->ataScsiAdapterExt);
+        mv_ial_lib_free_edma_queues(pAdapter);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+        return -ENOMEM;
+    }
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if ((pAdapter->activeHosts & (1 << i)) == 0)
+        {
+            continue;
+        }
+        pAdapter->host[i]->scsihost->irq = SATA_IRQ_NUM;
+        pAdapter->host[i]->scsihost->max_id = MV_SATA_PM_MAX_PORTS;
+        
+        pAdapter->host[i]->scsihost->max_lun = 1;
+        pAdapter->host[i]->scsihost->max_channel = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        pAdapter->host[i]->scsihost->select_queue_depths = mv_ial_ht_select_queue_depths;
+#endif
+    }
+    if (MV_FALSE == mvAdapterStartInitialization(pMvSataAdapter,
+                                                 &pAdapter->ialCommonExt,
+                                                 pAdapter->ataScsiAdapterExt))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: mvAdapterStartInitialization"
+                 " Failed\n", pMvSataAdapter->adapterId);
+        free_irq (SATA_IRQ_NUM, pMvSataAdapter);
+        kfree(pAdapter->ataScsiAdapterExt);
+        mv_ial_lib_free_edma_queues(pAdapter);
+        mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+        return -ENOMEM;
+    }
+
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if ((pAdapter->activeHosts & (1 << i)) == 0)
+        {
+            continue;
+        }
+        mv_ial_block_requests(pAdapter, i);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        if (scsi_add_host(pAdapter->host[i]->scsihost, NULL) != 0)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: scsi_add_host() failed.\n"
+                     , pMvSataAdapter->adapterId);
+            free_irq (SATA_IRQ_NUM , pMvSataAdapter);
+            kfree(pAdapter->ataScsiAdapterExt);
+            mv_ial_lib_free_edma_queues(pAdapter);
+            mv_ial_free_scsi_hosts(pAdapter, MV_TRUE);
+            return -ENODEV;
+        }
+#endif
+    }
+
+    pAdapter->stopAsyncTimer = MV_FALSE;
+    init_timer(&pAdapter->asyncStartTimer);
+    pAdapter->asyncStartTimer.data = (unsigned long)pAdapter;
+    pAdapter->asyncStartTimer.function = asyncStartTimerFunction;
+    pAdapter->asyncStartTimer.expires = jiffies + MV_LINUX_ASYNC_TIMER_PERIOD;
+    add_timer (&pAdapter->asyncStartTimer);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        if ((pAdapter->activeHosts & (1 << i)) != 0)
+        {
+            scsi_scan_host(pAdapter->host[i]->scsihost);
+        }
+    }
+    /*Enable hotplug handler*/
+    atomic_set(&pAdapter->stopped, 0);
+#endif
+    return 0;
+
+}
+#endif 
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+/****************************************************************
+ *  Name: mv_ial_ht_detect
+ *
+ *  Description:    Detect and initialize our boards.
+ *
+ *  Parameters:     tpnt - Pointer to SCSI host template structure.
+ *
+ *  Returns:        Number of adapters installed.
+ *
+ ****************************************************************/
+int mv_ial_ht_detect (Scsi_Host_Template *tpnt)
+{
+    int                 num_hosts=0;
+    struct pci_dev      *pcidev = NULL;
+    int                 index;
+    struct pci_device_id *id = &mvSata_pci_table[0];
+
+    mv_ial_init_log();
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    if (!pci_present())
+    {
+        printk ("mvSata: PCI BIOS not present\n");
+        return 0;
+    }
+#endif
+
+    if (sizeof(struct mv_comp_info) > sizeof(Scsi_Pointer))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "WARNING mv_comp_info must be "
+                 "re-defined - its too big");
+        return -1;
+    }
+    index = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    spin_unlock_irq (&io_request_lock);
+#endif
+
+    while (1)
+    {
+        if (id[index].device == 0)
+        {
+            break;
+        }
+        pcidev = NULL;
+
+        while ((pcidev = pci_find_device (MV_SATA_VENDOR_ID,
+                                          id[index].device, pcidev)) != NULL)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "PCI device found, DeviceId 0x%x "
+                     "BAR0=%lx\n",
+                      id[index].device, pci_resource_start(pcidev,0));
+            if (mv_ial_probe_device(pcidev, &id[index]) == 0)
+            {
+                IAL_ADAPTER_T *pAdapter = pci_get_drvdata(pcidev);
+                num_hosts += pAdapter->maxHosts;
+            }
+        }
+        index ++;
+    }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    spin_lock_irq (&io_request_lock);
+#endif
+    return num_hosts;
+}
+#endif
+
+/****************************************************************
+ *  Name:   mv_ial_ht_release
+ *
+ *  Description:   release scsi host
+ *
+ *  Parameters:     SCpnt - Pointer to SCSI host structure.
+ *
+ *  Returns:          0 on success, otherwise of failure.
+ *
+ ****************************************************************/
+int mv_ial_ht_release (struct Scsi_Host *pHost)
+{
+    IAL_ADAPTER_T *pAdapter = MV_IAL_ADAPTER (pHost);
+    MV_U8 channel;
+    MV_SATA_ADAPTER * pMvSataAdapter = &pAdapter->mvSataAdapter;
+    unsigned long lock_flags;
+    struct scsi_cmnd *cmnds_done_list = NULL;
+    IAL_HOST_T          *ial_host = HOSTDATA(pHost);
+
+    channel = ial_host->channelIndex;
+    pAdapter->activeHosts &= ~ (1 << channel);
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, ": release host %d\n", pHost->host_no);
+    spin_lock_irqsave (&pAdapter->adapter_lock, lock_flags);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    if (pAdapter->stopAsyncTimer != MV_TRUE)
+    {
+        /* Delete any pending timers */
+        pAdapter->stopAsyncTimer = MV_TRUE;
+        del_timer_sync(&pAdapter->asyncStartTimer);
+    }
+#endif
+
+    if (pMvSataAdapter->sataChannel[channel])
+    {
+        mvSataDisableChannelDma(pMvSataAdapter, channel);
+
+        mvSataFlushDmaQueue(pMvSataAdapter, channel,
+                            MV_FLUSH_TYPE_CALLBACK);
+        mv_ial_lib_free_channel(pAdapter, channel);
+   }
+     /* Check if there are commands in the done queue to be completed */
+
+    cmnds_done_list = mv_ial_lib_get_first_cmnd (pAdapter, channel);
+    if (cmnds_done_list)
+    {
+        unsigned long flags_io_request_lock;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        spin_lock_irqsave(&io_request_lock, flags_io_request_lock);
+#else
+        spin_lock_irqsave(ial_host->scsihost->host_lock, flags_io_request_lock);
+#endif
+        mv_ial_lib_do_done(cmnds_done_list);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        spin_unlock_irqrestore(&io_request_lock, flags_io_request_lock);
+#else
+        spin_unlock_irqrestore(ial_host->scsihost->host_lock, flags_io_request_lock);
+#endif
+    }
+    if (0 == pAdapter->activeHosts)
+    {
+      mvSataShutdownAdapter(pMvSataAdapter);
+    }
+    pAdapter->host[channel] = NULL;
+    mv_ial_lib_prd_destroy(ial_host);
+    spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+    scsi_remove_host(pHost);
+    scsi_host_put(pHost);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    if (0 == pAdapter->activeHosts)
+    {
+        struct pci_dev *dev = pAdapter->pcidev;
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG,
+                     "[%d] freeing Adapter resources.\n", pAdapter->mvSataAdapter.adapterId);
+        free_irq (pAdapter->pcidev->irq, pMvSataAdapter);
+#ifdef MV_SUPPORT_MSI
+	pci_disable_msi(pAdapter->pcidev);
+#endif
+        kfree(pAdapter->ataScsiAdapterExt);
+        iounmap(pMvSataAdapter->adapterIoBaseAddress);
+        mv_ial_lib_free_edma_queues(pAdapter);
+        kfree(pAdapter);
+	pci_disable_device(dev);
+    }
+#endif
+    return 0;
+}
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static void __devexit mv_ial_remove_device(struct pci_dev *pdev)
+{
+    IAL_ADAPTER_T       *pAdapter = (pdev != NULL) ? pci_get_drvdata(pdev) : pSocAdapter;
+    int numhosts;
+    int i;
+    unsigned long lock_flags;
+
+    if (pAdapter == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_FATAL_ERROR,
+                     "mv_ial_remove_device() No valid Adapter IAL structure found.\n");
+        return;
+    }
+
+    numhosts           = pAdapter->maxHosts;
+    /*flush hotplug rescan worker*/
+    atomic_inc(&pAdapter->stopped);
+    flush_scheduled_work();
+    /* Delete any pending timers */
+    spin_lock_irqsave (&pAdapter->adapter_lock, lock_flags);
+    pAdapter->stopAsyncTimer = MV_TRUE;
+    del_timer_sync(&pAdapter->asyncStartTimer);
+    spin_unlock_irqrestore(&pAdapter->adapter_lock, lock_flags);
+
+    for (i = 0; i < numhosts; i++)
+    {
+        if (pAdapter->host[i] != NULL)
+        {
+            mv_ial_ht_release (pAdapter->host[i]->scsihost);
+        }
+    }
+    if (pdev != NULL) /* pci device */
+    {
+        free_irq (pAdapter->pcidev->irq, &pAdapter->mvSataAdapter);
+#ifdef MV_SUPPORT_MSI
+	pci_disable_msi(pAdapter->pcidev);
+#endif
+	kfree(pAdapter->ataScsiAdapterExt);
+	iounmap(pAdapter->mvSataAdapter.adapterIoBaseAddress);
+	mv_ial_lib_free_edma_queues(pAdapter);
+	kfree(pAdapter);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+    }
+#ifdef CONFIG_MV_INCLUDE_INTEG_SATA
+    else /* Soc sata*/
+    {
+        free_irq (SATA_IRQ_NUM, &pAdapter->mvSataAdapter);
+	kfree(pAdapter->ataScsiAdapterExt);
+	mv_ial_lib_free_edma_queues(pAdapter);
+	kfree(pAdapter);
+    }
+#endif
+}
+#endif
+
+ /****************************************************************
+ *  Name:   mv_ial_ht_ata_cmd
+ *
+ *  Description:    handles mv_sata ata IOCTL special drive command (HDIO_DRIVE_CMD)
+ *
+ *  Parameters:     scsidev - Device to which we are issuing command
+ *                  arg     - User provided data for issuing command
+ *
+ *  Returns:        0 on success, otherwise of failure.
+ *
+ ****************************************************************/
+static int mv_ial_ht_ata_cmd(struct scsi_device *scsidev, void __user *arg)
+{
+    int rc = 0;
+    u8 scsi_cmd[MAX_COMMAND_SIZE];
+    u8 args[4], *argbuf = NULL, *sensebuf = NULL;
+    int argsize = 0;
+    enum dma_data_direction data_dir;
+    int cmd_result;
+
+    if (arg == NULL)
+        return -EINVAL;
+
+    if (copy_from_user(args, arg, sizeof(args)))
+        return -EFAULT;
+
+    sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
+    if (!sensebuf)
+        return -ENOMEM;
+
+    memset(scsi_cmd, 0, sizeof(scsi_cmd));
+
+    if (args[3]) {
+        argsize = SECTOR_SIZE * args[3];
+        argbuf = kmalloc(argsize, GFP_KERNEL);
+        if (argbuf == NULL) {
+            rc = -ENOMEM;
+            goto error;
+        }
+
+        scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
+        scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
+		                            block count in sector count field */
+        data_dir = DMA_FROM_DEVICE;
+    } else {
+        scsi_cmd[1]  = (3 << 1); /* Non-data */
+        scsi_cmd[2]  = 0x20;     /* cc but no off.line or data xfer */
+        data_dir = DMA_NONE;
+    }
+
+    scsi_cmd[0] = ATA_16;
+
+    scsi_cmd[4] = args[2];
+    if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */
+        scsi_cmd[6]  = args[3];
+        scsi_cmd[8]  = args[1];
+        scsi_cmd[10] = 0x4f;
+        scsi_cmd[12] = 0xc2;
+    } else {
+        scsi_cmd[6]  = args[1];
+    }
+    scsi_cmd[14] = args[0];
+
+    /* Good values for timeout and retries?  Values below
+       from scsi_ioctl_send_command() for default case... */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+    cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,
+                              sensebuf, (10*HZ), 5, 0);
+#else
+    cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,
+                              sensebuf, (10*HZ), 5, 0, NULL);
+#endif
+    if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
+        u8 *desc = sensebuf + 8;
+        cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
+
+        /* If we set cc then ATA pass-through will cause a
+        * check condition even if no error. Filter that. */
+        if (cmd_result & SAM_STAT_CHECK_CONDITION) {
+            struct scsi_sense_hdr sshdr;
+            scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
+                                 &sshdr);
+            if (sshdr.sense_key==0 &&
+                sshdr.asc==0 && sshdr.ascq==0)
+                cmd_result &= ~SAM_STAT_CHECK_CONDITION;
+        }
+
+        /* Send userspace a few ATA registers (same as drivers/ide) */
+        if (sensebuf[0] == 0x72 &&     /* format is "descriptor" */
+            desc[0] == 0x09 ) {        /* code is "ATA Descriptor" */
+            args[0] = desc[13];    /* status */
+            args[1] = desc[3];     /* error */
+            args[2] = desc[5];     /* sector count (0:7) */
+            if (copy_to_user(arg, args, sizeof(args)))
+                rc = -EFAULT;
+        }
+    }
+
+    if (cmd_result) {
+        rc = -EIO;
+        goto error;
+    }
+
+    if ((argbuf) && copy_to_user(arg + sizeof(args), argbuf, argsize))
+        rc = -EFAULT;
+
+error:
+    if (sensebuf) kfree(sensebuf);
+    if (argbuf) kfree(argbuf);
+    return rc;
+}
+
+/****************************************************************
+ *  Name:   mv_ial_ht_ioctl
+ *
+ *  Description:    mv_sata scsi ioctl
+ *
+ *  Parameters:     scsidev - Device to which we are issuing command
+ *                  cmd     - ioctl command
+ *                  arg     - User provided data for issuing command
+ *
+ *  Returns:        0 on success, otherwise of failure.
+ *
+ ****************************************************************/
+int mv_ial_ht_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+{
+    int rc = -ENOTTY;
+
+    /* No idea how this happens.... */
+    if (!scsidev)
+        return -ENXIO;
+
+    if (arg == NULL)
+        return -EINVAL;
+
+    switch (cmd) {
+        case HDIO_DRIVE_CMD:
+            if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+                return -EACCES;
+
+            rc =  mv_ial_ht_ata_cmd(scsidev, arg);
+            break;
+
+        default:
+            rc = -ENOTTY;
+    }
+
+    return rc;
+}
+
+/****************************************************************
+ *  Name:   mv_ial_ht_queuecommand
+ *
+ *  Description:    Process a queued command from the SCSI manager.
+ *
+ *  Parameters:     SCpnt - Pointer to SCSI command structure.
+ *                  done  - Pointer to done function to call.
+ *
+ *  Returns:        Status code.
+ *
+ ****************************************************************/
+int mv_ial_ht_queuecommand (struct scsi_cmnd * SCpnt, void (*done) (struct scsi_cmnd *))
+{
+    IAL_ADAPTER_T   *pAdapter = MV_IAL_ADAPTER(SCpnt->device->host);
+    MV_SATA_ADAPTER *pMvSataAdapter;
+    IAL_HOST_T      *pHost = HOSTDATA(SCpnt->device->host);
+    MV_U8            channel = pHost->channelIndex;
+    int             build_prd_table = 0;
+    unchar *cmd = (unchar *) SCpnt->cmnd;
+    struct mv_comp_info *completion_info;
+    unsigned long lock_flags;
+
+    struct scsi_cmnd   *cmnds_done_list = NULL;
+
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, " :queuecommand host=%d, bus=%d, channel=%d\n",
+             SCpnt->device->host->host_no,
+             SCpnt->device->channel,
+             channel);
+    if (done == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, ": in queuecommand, done function can't be NULL\n");
+        return 0;
+    }
+
+    if ((pAdapter == NULL) || (channel >= MV_SATA_CHANNELS_NUM)||
+        (pAdapter->host[channel] == NULL))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_FATAL_ERROR,": in queuecommand, "
+                 "command queued for released host!!\n");
+        SCpnt->result = DID_NO_CONNECT << 16;
+        done(SCpnt);
+        return 0;
+    }
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    spin_unlock_irq (&io_request_lock);
+#else
+    spin_unlock_irq(pHost->scsihost->host_lock);
+#endif
+
+    spin_lock_irqsave (&pAdapter->adapter_lock, lock_flags);
+
+    if (SCpnt->retries > 0)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,": retry command host=%d, bus=%d"
+                 " SCpnt = %p\n", SCpnt->device->host->host_no, channel, SCpnt);
+    }
+
+    if (MV_TRUE == pAdapter->host[channel]->hostBlocked)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,": command received for "
+                 "blocked host=%d, bus=%d, channel=%d, SCpnt = %p\n",
+                 SCpnt->device->host->host_no,
+                 SCpnt->device->channel,
+                 channel, SCpnt);
+#if 0
+        spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        spin_lock_irq (&io_request_lock);
+#else
+        spin_lock_irq(pHost->scsihost->host_lock);
+#endif
+        return SCSI_MLQUEUE_HOST_BUSY;
+#endif
+    }
+
+    pMvSataAdapter = &pAdapter->mvSataAdapter;
+
+    SCpnt->result = DID_ERROR << 16;
+    SCpnt->scsi_done = done;
+
+    completion_info = ( struct mv_comp_info *) &(SCpnt->SCp);
+    completion_info->pSALBlock =
+    (MV_SATA_SCSI_CMD_BLOCK *) kmalloc(sizeof(MV_SATA_SCSI_CMD_BLOCK),
+                                       GFP_ATOMIC);
+    if (completion_info->pSALBlock == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,  "in queuecommand: Failed to allocate SAL Block\n");
+        spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+		done(SCpnt);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        spin_lock_irq (&io_request_lock);
+#else
+        spin_lock_irq(pHost->scsihost->host_lock);
+#endif
+        return -1;
+    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    completion_info->kmap_buffer = 0;
+#endif
+    /* prepare the SAL Block paramters*/
+    if ((*cmd == READ_6) || (*cmd == READ_10) || (*cmd == READ_16) ||
+	(*cmd == WRITE_6) || (*cmd == WRITE_10) || (*cmd == WRITE_16))
+    {
+        build_prd_table = 1;
+    }
+    else if((pAdapter->ataScsiAdapterExt->ataDriveData[channel][SCpnt->device->id].identifyInfo.deviceType == MV_SATA_DEVICE_TYPE_ATAPI_DEVICE) && use_sg(SCpnt))
+    {
+	 /*
+	   for the 60x1 devices don't use DMA for control commands as the BMDMA will
+	   not write date to DRAM in case on underrun.
+	 */
+	 if(!(pAdapter->mvSataAdapter.sataAdapterGeneration == MV_SATA_GEN_II)){
+	      mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG,
+		       "in queuecommand: PRD for non data command for ATAPI device\n");
+	      build_prd_table = 1;
+	 }
+    }
+     if((pAdapter->ataScsiAdapterExt->ataDriveData[channel][SCpnt->device->id].identifyInfo.deviceType == MV_SATA_DEVICE_TYPE_ATAPI_DEVICE))
+    {
+        BUG_ON(((unsigned int)SCpnt->cmnd) & 0x1);
+    }
+    completion_info->pSALBlock->singleDataRegion = MV_FALSE;
+
+    /* prepare the SAL Block paramters*/
+    if(build_prd_table)
+    {
+        if(pAdapter->ataScsiAdapterExt->ataDriveData[channel][SCpnt->device->id].identifyInfo.deviceType == MV_SATA_DEVICE_TYPE_ATAPI_DEVICE)
+        {
+           mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "in queuecommand: Data command for ATAPI device\n");
+        }
+        else
+        {
+              mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "in queuecommand: Data command for ATA device\n");
+ 
+        }
+        if (mv_ial_lib_generate_prd(pMvSataAdapter, SCpnt, completion_info))
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "in queuecommand: illegal requested buffer\n");
+            spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+	   		done(SCpnt);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+            spin_lock_irq (&io_request_lock);
+#else
+            spin_lock_irq(pHost->scsihost->host_lock);
+#endif
+            return -1;
+        }
+        completion_info->pSALBlock->pDataBuffer = NULL;
+    }
+    else
+    {
+        completion_info->cpu_PRDpnt = NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+	if (use_sg(SCpnt))
+	{
+       	    completion_info->kmap_buffer  = 1;
+	}
+#else
+        completion_info->pSALBlock->pDataBuffer = SCpnt->request_buffer;
+#endif
+    }
+    completion_info->SCpnt = SCpnt;
+
+    completion_info->pSALBlock->bus = channel;
+
+    completion_info->pSALBlock->target = SCpnt->device->id;
+    completion_info->pSALBlock->lun = SCpnt->device->lun;
+    completion_info->pSALBlock->pSalAdapterExtension = pAdapter->ataScsiAdapterExt;
+    completion_info->pSALBlock->pIalAdapterExtension = &pAdapter->ialCommonExt;
+    completion_info->pSALBlock->completionCallBack = IALCompletion;
+    completion_info->pSALBlock->IALData = SCpnt;
+    completion_info->pSALBlock->dataBufferLength = scsi_bufflen(SCpnt);
+    completion_info->pSALBlock->pSenseBuffer = SCpnt->sense_buffer;
+    completion_info->pSALBlock->ScsiCdb = SCpnt->cmnd;
+    completion_info->pSALBlock->ScsiCdbLength = SCpnt->cmd_len;
+    completion_info->pSALBlock->senseBufferLength = SCSI_SENSE_BUFFERSIZE;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    if (completion_info->kmap_buffer)
+    {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	struct scatterlist *sg;
+	sg = (struct scatterlist *) SCpnt->request_buffer;
+#endif
+	mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SCpnt %p, cmd %x need to use"
+		" temp data buffer.lengh %d \n", SCpnt, *cmd , scsi_bufflen(SCpnt));
+	completion_info->pSALBlock->pDataBuffer = kmalloc(scsi_bufflen(SCpnt), GFP_ATOMIC);
+	if (completion_info->pSALBlock->pDataBuffer == NULL)
+    	{
+        	mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,  "in queuecommand: Failed to allocate temp buffer for kmap\n");
+	        spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+		done(SCpnt);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+	        spin_lock_irq (&io_request_lock);
+#else
+        	spin_lock_irq(pHost->scsihost->host_lock);
+#endif
+	        return -1;
+    	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+        completion_info->pSALBlock->dataBufferLength = sg->length;
+#else
+        completion_info->pSALBlock->dataBufferLength = scsi_bufflen(SCpnt);
+#endif
+	if( SCpnt->sc_data_direction == DMA_TO_DEVICE) 
+	{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+		struct scatterlist *sg;
+	        MV_U8*          pBuffer;
+        	sg = (struct scatterlist *) SCpnt->request_buffer;
+
+		mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SCpnt %p, cmd %x kmap temp data buffer and copy data.lengh %d \n", SCpnt, *cmd ,sg->length);
+	        pBuffer = kmap_atomic(sg->page, KM_USER0) + sg->offset;
+	        memcpy(completion_info->pSALBlock->pDataBuffer, pBuffer , sg->length);
+	        kunmap_atomic(pBuffer - sg->offset, KM_USER0);
+#else
+		scsi_sg_copy_to_buffer(SCpnt, completion_info->pSALBlock->pDataBuffer,
+				       scsi_bufflen(SCpnt));
+#endif
+	}
+
+    }
+#endif
+    switch(SCpnt->sc_data_direction)
+    {
+        case DMA_FROM_DEVICE:
+            completion_info->pSALBlock->dataDirection = MV_SCSI_COMMAND_DATA_DIRECTION_IN;
+            break;
+        case DMA_TO_DEVICE:
+            completion_info->pSALBlock->dataDirection = MV_SCSI_COMMAND_DATA_DIRECTION_OUT;
+            break;
+        default:
+           completion_info->pSALBlock->dataDirection = MV_SCSI_COMMAND_DATA_DIRECTION_NON;
+    }
+
+    if (*cmd != SCSI_OPCODE_MVSATA_SMART)
+    {
+        mvExecuteScsiCommand(completion_info->pSALBlock, MV_TRUE);
+    }
+    else
+    {
+        mvScsiAtaSendSmartCommand(pMvSataAdapter, completion_info->pSALBlock);
+    }
+
+    /*
+     * Check if there is valid commands to be completed. This is usually
+     * an immediate completed commands such as INQUIRY etc...
+     */
+    cmnds_done_list = mv_ial_lib_get_first_cmnd(pAdapter, channel);
+    spin_unlock_irqrestore(&pAdapter->adapter_lock, lock_flags);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    spin_lock_irq (&io_request_lock);
+#else
+    spin_lock_irq(pHost->scsihost->host_lock);
+#endif
+    if (cmnds_done_list)
+    {
+        mv_ial_lib_do_done(cmnds_done_list);
+    }
+    return 0;
+}
+/****************************************************************
+ *  Name:   mv_ial_ht_bus_reset
+ *
+ *  Description:    reset given devise, all pending commands will be aborted
+ *                  with status DID_RESET.
+ *
+ *  Parameters:     SCpnt - Pointer to SCSI command structure.
+ *
+ *  Returns:        Status code.
+ *
+ ****************************************************************/
+int mv_ial_ht_bus_reset (struct scsi_cmnd *SCpnt)
+{
+    IAL_ADAPTER_T   *pAdapter = MV_IAL_ADAPTER(SCpnt->device->host);
+    MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
+    IAL_HOST_T      *pHost = HOSTDATA(SCpnt->device->host);
+    MV_U8 channel = pHost->channelIndex;
+
+    unsigned long lock_flags;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    spin_unlock_irq (&io_request_lock);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
+    spin_unlock_irq(pHost->scsihost->host_lock);
+#endif
+    spin_lock_irqsave (&pAdapter->adapter_lock, lock_flags);
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "Bus Reset: host=%d, channel=%d, target=%d\n",
+             SCpnt->device->host->host_no, SCpnt->device->channel, SCpnt->device->id);
+    if (pMvSataAdapter->sataChannel[channel] == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "trying to reset disabled channel, host=%d, channel=%d\n",
+                 SCpnt->device->host->host_no, channel);
+        spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        spin_lock_irq(&io_request_lock);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
+        spin_lock_irq(pHost->scsihost->host_lock);
+#endif
+        return FAILED;
+    }
+
+    mvSataDisableChannelDma(pMvSataAdapter, channel);
+
+    /* Flush pending commands */
+    mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
+
+    /* Hardware reset channel */
+    mvSataChannelHardReset(pMvSataAdapter, channel);
+
+    if (pMvSataAdapter->sataChannel[channel])
+    {
+        mvRestartChannel(&pAdapter->ialCommonExt, channel,
+                         pAdapter->ataScsiAdapterExt, MV_TRUE);
+        mv_ial_block_requests(pAdapter, channel);
+    }
+    /* don't call scsi done for the commands on this channel*/
+    mv_ial_lib_get_first_cmnd(pAdapter, channel);
+    spin_unlock_irqrestore(&pAdapter->adapter_lock, lock_flags);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    spin_lock_irq(&io_request_lock);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
+    spin_lock_irq(pHost->scsihost->host_lock);
+#endif
+    return SUCCESS;
+}
+
+static MV_VOID mvAta2HostString(IN MV_U16 *source,
+                                OUT MV_U16 *target,
+                                IN MV_U32 wordsCount
+                               )
+{
+    MV_U32 i;
+    for (i=0 ; i < wordsCount; i++)
+    {
+        target[i] = MV_LE16_TO_CPU(target[i]);
+    }
+}
+
+/****************************************************************
+ *  Name:   mv_ial_ht_proc_info
+ *
+ *  Description:   /proc file
+ *
+ *  Parameters:
+ *
+ *  Returns:
+ *
+ ****************************************************************/
+int mv_ial_ht_proc_info(struct Scsi_Host *pshost,
+                        char *buffer, char **start, off_t offset,
+                        int length, int inout)
+{
+    int len = 0, temp, pmPort;
+    IAL_ADAPTER_T       *pAdapter;
+    MV_SATA_ADAPTER *pMvSataAdapter;
+    IAL_HOST_T       *pHost = HOSTDATA(pshost);
+
+    unsigned long lock_flags;
+
+    pAdapter = MV_IAL_ADAPTER(pshost);
+    pMvSataAdapter = &pAdapter->mvSataAdapter;
+    temp = pHost->channelIndex;
+    spin_lock_irqsave (&pAdapter->adapter_lock, lock_flags);
+    if (inout == 1)
+    {                     /* Writing to file */
+        /* The format is 'int_coal <sata unit> <coal_threshold> <timeout>' */
+        int i;
+        /* Check signature 'int_coal' at start of buffer */
+        if (!strncmp (buffer, "int_coal", strlen ("int_coal")))
+        {
+            int sata_unit;
+            u32 time_thre, coal_thre;
+            i = sscanf (buffer + strlen ("int_coal"), "%d %d %d\n",
+                        &sata_unit, &coal_thre, &time_thre);
+            if (i == 3)
+            {        /* Three matched inputs */
+                mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d]: Modifying interrupt coalescing of unit %d to %d threshold and %d timer\n",pMvSataAdapter->adapterId, sata_unit, coal_thre, time_thre);
+                mvSataSetIntCoalParams (pMvSataAdapter, sata_unit, coal_thre, time_thre);
+            }
+            else
+            {
+                mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "[%d]: Error in interrupt coalescing parameters\n",
+                         pMvSataAdapter->adapterId);
+            }
+        }
+        /* Check signature 'sata_phy_shutdown' at start of buffer */
+        else if (!strncmp (buffer, "sata_phy_shutdown", strlen ("sata_phy_shutdown")))
+        {
+            int sata_phy;
+            i = sscanf (buffer + strlen ("sata_phy_shutdown"), "%d\n", &sata_phy);
+            if (i == 1)
+            {        /* Three matched inputs */
+
+                if (mvSataIsStorageDeviceConnected (pMvSataAdapter, sata_phy, NULL) == MV_TRUE)
+                {
+                    mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "[%d,%d]: Warning - shutting down a phy that is connected to a storage device\n", pMvSataAdapter->adapterId, sata_phy);
+                }
+                if (mvSataChannelPhyShutdown (pMvSataAdapter, sata_phy) == MV_TRUE)
+                {
+                    mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "[%d,%d]: Shutting down SATA phy\n", pMvSataAdapter->adapterId, sata_phy);
+                }
+            }
+            else
+            {
+                mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d]: Error in shutting down SATA phy parameters\n",
+                         pMvSataAdapter->adapterId);
+            }
+        }
+        else if (!strncmp (buffer, "sata_phy_powerup", strlen ("sata_phy_powerup")))
+        {
+            int sata_phy;
+            i = sscanf (buffer + strlen ("sata_phy_powerup"), "%d\n", &sata_phy);
+            if (i == 1)
+            {        /* Three matched inputs */
+                if (mvSataChannelPhyPowerOn (pMvSataAdapter, sata_phy) == MV_TRUE)
+                {
+                    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d,%d]: Turning on SATA phy\n", pMvSataAdapter->adapterId, sata_phy);
+                }
+            }
+            else
+            {
+                mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG,"[%d]: Error in powering up SATA phy parameters\n",
+                         pMvSataAdapter->adapterId);
+            }
+        }
+        spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+        return length;
+    }
+    else
+    {      /* Reading from file */
+        int i;
+        /*
+         * Write to the file the time stamp which is difference between last
+         * jiffies and current one. Next to it write the HZ parameter which
+         * indicates how many time jiffies parameter is incremented in a
+         * second.
+         */
+        len += snprintf (buffer + len,length - len, "%s\n", mv_ial_proc_version);
+        if (len >= length)
+        {
+            goto out;
+        }
+        len += snprintf (buffer + len,length - len, "\nTimeStamp :\n%ld\t%d\n",
+                         jiffies, HZ);
+        if (len >= length)
+        {
+            goto out;
+        }
+        /* Write the number of interrupts this adapter generated within the
+         * sampling time.
+         */
+        len += snprintf (buffer + len,length - len, "\nNumber of interrupts generated by the adapter is : \n%d\n",
+                         pAdapter->procNumOfInterrupts);
+        if (len >= length)
+        {
+            goto out;
+        }
+        if (pAdapter->pcidev)
+        {
+            len += snprintf (buffer + len, length - len, "\nPCI location: Bus %d, Slot %d\n",
+                             pAdapter->pcidev->bus->number,
+                             PCI_SLOT(pAdapter->pcidev->devfn));
+        
+            if (len >= length)
+            {
+                goto out;
+            }
+            len += snprintf (buffer + len, length - len, "DeviceID: %x, Rev %x,"
+                             " adapterId %d, channel %d \n",
+                             pAdapter->mvSataAdapter.pciConfigDeviceId,
+                             pAdapter->mvSataAdapter.pciConfigRevisionId,   
+                             pAdapter->mvSataAdapter.adapterId,
+                             pHost->channelIndex);
+
+            if (len >= length)
+            {
+                goto out;
+            }
+        }
+        else /*integrated sata*/
+        {
+            len += snprintf (buffer + len, length - len, "\nIntegrated Sata adapterId %d,  "
+                             "channel %d\n",pAdapter->mvSataAdapter.adapterId,
+                             pHost->channelIndex);
+            
+            if (len >= length)
+            {
+                goto out;
+            }  
+        }
+        if (pMvSataAdapter->sataChannel[temp])
+        {
+            if (pMvSataAdapter->sataChannel[temp]->deviceType == MV_SATA_DEVICE_TYPE_PM)
+            {
+                len += snprintf (buffer + len, length - len, 
+                                 "Port Multiplier connected, switching mode: %s\n",
+                                 (pMvSataAdapter->sataChannel[temp]->FBSEnabled == MV_TRUE) ?
+                                 "FBS":"CBS");
+
+                if (len >= length)
+                {
+                    goto out;
+                }
+            }
+        }
+        /*
+         * Check if channel connected.
+         * If not connected write -1 on a line
+         * If connected, write a line that has -
+         * 1.. Adapter number
+         * 2.. SCSI channel number (equivalent to SATA channel number).
+         * 3.. ID
+         * 4.. LUN (always 0)
+         * 5.. vendor name
+         * 6.. number of outstanding commands accumulated
+         * 7.. total sampling of outstanding commands
+         * 8.. total sectors transferred
+         * 9.. flag if queued / non-queued (1/0)
+         * 10. flag if LBA 48 or not (1/0)
+         * 11. flag if the storage device can be removed or not
+         *  (1 means can't be removed / 0 can be removed).
+         */
+        len += snprintf (buffer + len,length - len,"\n%s\t%s\t%s\t%s\t%s\t%s\t%s\t\t%s\t%s\n",
+                         "Adapter", "Channel", "Id", "LUN", "TO", "TS", "Vendor",
+                         "Mode", "LBA48");
+        if (len >= length)
+        {
+            goto out;
+        }
+        if ((len + 100) >= length)
+        {
+            goto out;
+        }
+        for (i = 0 ; i < 80 ; i++)
+            buffer [len + i] = '-';
+        len += i;
+        len += snprintf (buffer + len,length - len, "\n");
+        if (len >= length)
+        {
+            goto out;
+        }
+        
+        if (pMvSataAdapter->sataChannel[temp])
+        {
+            for (pmPort = 0; pmPort < MV_SATA_PM_MAX_PORTS; pmPort++)
+            {
+                if (pmPort > 0 &&
+                    (pMvSataAdapter->sataChannel[temp]->deviceType != MV_SATA_DEVICE_TYPE_PM))
+                {
+                    break;
+                }
+                if (pAdapter->ataScsiAdapterExt->ataDriveData[temp][pmPort].driveReady == MV_FALSE)
+                {
+                    continue;
+                }
+
+                len += snprintf (buffer + len,length - len, "%d\t%d\t%d\t%d\t%u\t%u\t",
+                                 pAdapter->mvSataAdapter.adapterId, temp, pmPort, 0,
+                                 pAdapter->ataScsiAdapterExt->ataDriveData[temp][pmPort].stats.totalIOs,
+                                 pAdapter->ataScsiAdapterExt->ataDriveData[temp][pmPort].stats.totalSectorsTransferred);
+                if (len >= length)
+                {
+                    goto out;
+                }
+                /*
+                 * Copy first 10 characters of the vendor name from the IDENTIFY
+                 * DEVICE ATA command result buffer
+                 */
+                if ((len+10) >= length)
+                {
+                    goto out;
+                }
+                memcpy (buffer+len,
+                        pAdapter->ataScsiAdapterExt->ataDriveData[temp][pmPort].identifyInfo.model, 10);
+                mvAta2HostString((MV_U16 *)(buffer+len), (MV_U16 *)(buffer+len), 5);
+                /*
+                 * Clean spaces in vendor name and swap odd and even characters.
+                 * The swap is due to the format of the IDENTIFY DEVICE command
+                 */
+                for (i=0 ; i<10 ; i+=2)
+                {
+                    char ch = buffer[len + i];
+                    buffer[len + i] = buffer[len+1 + i];
+                    buffer[len+1 + i] = ch;
+                    if (buffer[len + i] == ' ')
+                    {
+                        buffer[len + i + 1] = ' ';
+                        break;
+                    }
+                    if (buffer[len+1 + i] == ' ')
+                    {
+                        break;
+                    }
+                }
+                if ((len + 10) >= length)
+                {
+                    goto out;
+                }
+                for (; i < 10; i++)
+                {
+                    buffer[len + i] = ' ';
+                }
+
+                len += 10;
+                len += snprintf (buffer + len,length - len, "\t%s \t%d\n",
+                                 (pMvSataAdapter->sataChannel[temp]->queuedDMA == MV_EDMA_MODE_QUEUED) ?
+                                  "TCQ" : (pMvSataAdapter->sataChannel[temp]->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) ?
+                                  "NCQ":"Normal",
+                                 (pAdapter->ataScsiAdapterExt->ataDriveData[temp][pmPort].identifyInfo.LBA48Supported == MV_TRUE)  ? 1 : 0);
+                if (len >= length)
+                {
+                    goto out;
+                }
+            }
+        }
+        if ((!pMvSataAdapter->sataChannel[temp]) &&
+            (mvSataIsStorageDeviceConnected (pMvSataAdapter, temp, NULL) == MV_TRUE))
+            len += snprintf (buffer + len,length - len, "Storage device connected to channel %d is malfunction\n", temp);
+        if (len >= length)
+        {
+            goto out;
+        }
+        len += snprintf (buffer + len,length - len,"\n\n\nTO           - Total Outstanding commands accumulated\n");
+        if (len >= length)
+        {
+            goto out;
+        }
+        len += snprintf (buffer + len,length - len,"TSA          - Total number of IOs accumulated\n");
+        if (len >= length)
+        {
+            goto out;
+        }
+        len += snprintf (buffer + len,length - len,"TS           - Total number of sectors transferred (both read/write)\n");
+        if (len >= length)
+        {
+            goto out;
+        }
+        len += snprintf (buffer + len,length - len,"Mode         - EDMA mode (TCQ|NCQ|Normal)\n");
+        if (len >= length)
+        {
+            goto out;
+        }
+        len += snprintf (buffer + len,length - len,"LBA48        - Large Block Address 48 feature set enabled\n");
+        if (len >= length)
+        {
+            goto out;
+        }
+    }
+    out:
+    spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+    return(len);
+}
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+/****************************************************************
+ *  Name:   mv_ial_ht_proc_info (kernel version < 2.6)
+ *
+ *  Description:   /proc file
+ *
+ *  Parameters:
+ *
+ *  Returns:
+ *
+ ****************************************************************/
+int mv_ial_ht_proc_info24(char *buffer, char **start, off_t offset,
+                        int length, int inode, int inout)
+{
+    struct Scsi_Host *pshost = 0;
+
+    for (pshost = scsi_hostlist; pshost; pshost = pshost->next)
+    {
+        if (pshost->host_no == inode)
+        {
+            return mv_ial_ht_proc_info(pshost, buffer, start,
+                                       offset,length, inout);
+        }
+    }
+    return -EINVAL;
+}
+#endif
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
+static int mv_ial_ht_slave_configure (struct scsi_device* pDevs)
+{
+    IAL_HOST_T *pHost = HOSTDATA (pDevs->host);
+    struct Scsi_Host* scsiHost = pDevs->host;
+    struct scsi_device*    pDevice = NULL;
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d]: slave configure\n",
+                        pHost->pAdapter->mvSataAdapter.adapterId);
+
+    if (pHost->use128Entries == MV_TRUE)
+    {
+        pHost->scsihost->can_queue = MV_SATA_GEN2E_SW_QUEUE_SIZE;
+    }
+    else
+    {
+        pHost->scsihost->can_queue = MV_SATA_SW_QUEUE_SIZE;
+    }
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d %d]: adjust host[channel] queue depth"
+             " to %d\n", pHost->pAdapter->mvSataAdapter.adapterId, pHost->channelIndex,
+                  pHost->scsihost->can_queue);
+    shost_for_each_device(pDevice, scsiHost)
+    {
+        int deviceQDepth = 2;
+        
+        if(pHost->pAdapter->ataScsiAdapterExt->ataDriveData[pHost->channelIndex][pDevice->id].identifyInfo.deviceType == MV_SATA_DEVICE_TYPE_ATAPI_DEVICE)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d %d %d]: ATAPI device found\n", 
+                  pHost->pAdapter->mvSataAdapter.adapterId, pHost->channelIndex,
+                  pDevice->id);
+            pDevice->use_10_for_rw = 1;
+            pDevice->use_10_for_ms = 1;
+            scsi_adjust_queue_depth(pDevice, 0, 1);
+//                pHost->scsihost->max_cmd_len = 12;
+	    blk_queue_max_sectors(pDevice->request_queue, 256);
+        }
+        else
+        {
+
+            if (pHost->mode != MV_EDMA_MODE_NOT_QUEUED)
+            {
+                deviceQDepth = 31;
+                if (pHost->scsihost->can_queue >= 32)
+                {
+                    deviceQDepth = 32;
+                }
+            }
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d %d %d]: adjust device queue "
+                     "depth to %d\n", pHost->pAdapter->mvSataAdapter.adapterId,
+                     pDevice->channel, pDevice->id, deviceQDepth);
+            scsi_adjust_queue_depth(pDevice, MSG_SIMPLE_TAG, deviceQDepth);
+#ifdef MV_SUPPORT_1MBYTE_IOS
+            if(pHost->pAdapter->ataScsiAdapterExt->ataDriveData[pHost->channelIndex][pDevice->id].identifyInfo.LBA48Supported == MV_TRUE)
+	    {
+	        blk_queue_max_sectors(pDevice->request_queue, 2048);
+ 	        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: set device max sectors to 2048 \n",
+	            pHost->pAdapter->mvSataAdapter.adapterId,
+                    pHost->channelIndex, pDevice->id);
+            }
+#endif
+        }
+    }
+    scsiHost->max_cmd_len = 16;    
+    return 0;
+}
+#else
+static void mv_ial_ht_select_queue_depths (struct Scsi_Host* pHost,
+                                           struct scsi_device* pDevs)
+{
+    IAL_HOST_T *ial_host = HOSTDATA (pHost);
+    struct scsi_device* pDevice;
+    if (ial_host != NULL)
+    {
+        
+        /* linux 2.4 queue depth is not tunable, so we set the device queue */
+        /* to the max value (MV_SATA_SW_QUEUE_SIZE), and limit the number queued */
+        /* commands using the cmd_per_lun */
+
+        /* set can_queue to the max number of queued commands per host (sata */
+        /* channel). This may casue startvation if PortMultiplier is connected*/
+        pHost->cmd_per_lun = 31;
+        if (ial_host->mode != MV_EDMA_MODE_NOT_QUEUED)
+        {   
+            if (ial_host->use128Entries == MV_TRUE)
+            {
+                pHost->can_queue = MV_SATA_GEN2E_SW_QUEUE_SIZE;
+                pHost->cmd_per_lun = 32;
+            }
+            else
+            {
+                pHost->can_queue = MV_SATA_SW_QUEUE_SIZE;
+            }
+        }
+        else
+        {
+            pHost->can_queue = MV_DEFAULT_QUEUE_DEPTH;
+        }
+        
+
+        /*always allocate the max number of commands */
+        for (pDevice = pDevs; pDevice; pDevice = pDevice->next)
+        {
+            if (pDevice->host == pHost)
+            {
+                pDevice->queue_depth = MV_SATA_SW_QUEUE_SIZE;
+            }
+        }
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d %d]: adjust queue depth to %d\n",
+            ial_host->pAdapter->mvSataAdapter.adapterId,
+            ial_host->channelIndex,
+            pHost->can_queue);
+    }
+}
+#endif
+
+int mv_ial_ht_abort(struct scsi_cmnd *SCpnt)
+{
+    IAL_ADAPTER_T   *pAdapter;
+    IAL_HOST_T      *pHost;
+
+    MV_SATA_ADAPTER *pMvSataAdapter;
+    MV_U8           channel;
+    unsigned long lock_flags;
+    struct scsi_cmnd *cmnds_done_list = NULL;
+
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "abort command %p\n", SCpnt);
+    if (SCpnt == NULL)
+    {
+        return FAILED;
+    }
+    pHost = HOSTDATA(SCpnt->device->host);
+    channel = pHost->channelIndex;
+    pAdapter = MV_IAL_ADAPTER(SCpnt->device->host);
+    pMvSataAdapter = &pAdapter->mvSataAdapter;
+    
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    if (SCpnt->serial_number != SCpnt->serial_number_at_timeout)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: abort failed, "
+                 "serial number mismatch\n",SCpnt->device->host->host_no,
+                 channel, SCpnt->device->id);
+        return FAILED;
+    }
+    spin_unlock_irq (&io_request_lock);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
+    spin_unlock_irq (pHost->scsihost->host_lock);
+#endif
+    spin_lock_irqsave (&pAdapter->adapter_lock, lock_flags);
+
+    mvRestartChannel(&pAdapter->ialCommonExt, channel,
+                     pAdapter->ataScsiAdapterExt, MV_TRUE);
+    mv_ial_block_requests(pAdapter, channel);
+
+    cmnds_done_list = mv_ial_lib_get_first_cmnd(pAdapter, channel);
+
+    spin_unlock_irqrestore (&pAdapter->adapter_lock, lock_flags);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    spin_lock_irq(&io_request_lock);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
+    spin_lock_irq (pHost->scsihost->host_lock);
+#endif
+
+    if (cmnds_done_list)
+    {
+        scsi_report_bus_reset(SCpnt->device->host, SCpnt->device->channel);
+        mv_ial_lib_do_done(cmnds_done_list);
+        return SUCCESS;
+    }
+
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d %d %d]: command abort failed\n",
+             SCpnt->device->host->host_no, SCpnt->device->channel, SCpnt->device->id);
+    return FAILED;
+}
+
+
+Scsi_Host_Template driver_template = mvSata;
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Marvell Serial ATA PCI-X Adapter");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include "scsi_module.c"
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalHt.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalHt.h
new file mode 100755
index 0000000..ee6f666
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalHt.h
@@ -0,0 +1,268 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* file_name - mvLinuxIalHt.h
+*
+* DESCRIPTION: header file for the layer that emulates SCSI adapter on the
+*           SATA adapter
+*
+*
+* DEPENDENCIES:
+*   None.
+*
+*
+******************************************************************************/
+#ifndef __INCmvLinuxIalHth
+#define __INCmvLinuxIalHth
+
+#include <linux/version.h>
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/autoconf.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_eh.h>
+#else
+#include <linux/blk.h>
+#include "scsi.h"
+#include "hosts.h"
+#endif
+
+#include "mvOs.h"
+#include "mvSata.h"
+#include "mvStorageDev.h"
+#include "mvScsiAtaLayer.h"
+#include "mvLinuxIalLib.h"
+#include "mvIALCommon.h"
+
+#include <linux/blkdev.h>
+#include <linux/spinlock.h>
+/* Common forward declarations for all Linux-versions: */
+
+/* Interfaces to the midlevel Linux SCSI driver */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+extern int mv_ial_ht_detect (Scsi_Host_Template *);
+#else
+typedef struct scsi_host_template Scsi_Host_Template;
+#endif
+extern int mv_ial_ht_release (struct Scsi_Host *);
+extern int mv_ial_ht_queuecommand (struct scsi_cmnd *, void (*done) (struct scsi_cmnd *));
+extern int mv_ial_ht_bus_reset (struct scsi_cmnd *);
+extern int mv_ial_ht_abort(struct scsi_cmnd *SCpnt);
+extern int mv_ial_ht_ioctl(struct scsi_device *, int, void __user *);
+
+#define HOSTDATA(host) ((IAL_HOST_T *)&host->hostdata)
+#define MV_IAL_ADAPTER(host) (HOSTDATA(host)->pAdapter)
+
+#define TEMP_DATA_BUFFER_LENGTH		    512
+
+/*#define MV_SUPPORT_1MBYTE_IOS*/
+#ifdef CONFIG_PCI_MSI
+/*#define MV_SUPPORT_MSI*/
+#endif
+
+
+/* Set the MRVL_SATA_BUFF_BOUNDARY to SATA minimal window size (according to CS) */
+#ifndef MRVL_SATA_BUFF_BOUNDARY
+#define MRVL_SATA_BUFF_BOUNDARY (1 << 24)
+#endif /* MRVL_SATA_BUFF_BOUNDARY */
+
+#define MRVL_SATA_BOUNDARY_MASK (MRVL_SATA_BUFF_BOUNDARY - 1)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define mvSata                                                          \
+{                                                                           \
+    module:     THIS_MODULE,\
+    proc_name:          "mvSata",                   /* proc_name */     \
+    proc_info:          mv_ial_ht_proc_info,    /*proc info fn */   \
+    slave_configure:    mv_ial_ht_slave_configure,\
+    name:               "Marvell SCSI to SATA adapter", /*name*/            \
+    release:            mv_ial_ht_release,              /*release fn*/      \
+    queuecommand:       mv_ial_ht_queuecommand,         /*queuecommand fn*/ \
+    ioctl:              mv_ial_ht_ioctl,                /*ioctl fn */       \
+    bios_param:         NULL    /*mv_ial_ht_biosparam*/,/*bios fn*/     \
+    eh_device_reset_handler: NULL/*mv_ial_ht_dev_reset*/,                   \
+    eh_bus_reset_handler: mv_ial_ht_bus_reset,                              \
+    eh_abort_handler:   mv_ial_ht_abort,                                    \
+    can_queue:          MV_SATA_SW_QUEUE_SIZE,           /* unlimited */     \
+    this_id:            MV_SATA_PM_MAX_PORTS,                          /*set by detect*/   \
+    sg_tablesize:       64,                             /*sg_tablesize*/    \
+    max_sectors:        256,                                                \
+    cmd_per_lun:        MV_SATA_SW_QUEUE_SIZE,           /*cmd_per_lun*/     \
+    unchecked_isa_dma:  0,                              /*32-Bit Busmaster*/\
+    emulated:           1,                      /* not real scsi adapter */ \
+    support_scattered_spinup:           1,                      /* support_scattered_spinup */ \
+    use_clustering:     ENABLE_CLUSTERING               /*use_clustering*/  \
+}
+#else
+#define mvSata                                                          \
+{                                                                           \
+    proc_name:          "mvSata",                   /* proc_name */     \
+    proc_info:          mv_ial_ht_proc_info24,  /*proc info fn */   \
+    select_queue_depths: NULL,              \
+    name:               "Marvell SCSI to SATA adapter", /*name*/            \
+    detect:             mv_ial_ht_detect,               /*detect fn*/       \
+    release:            mv_ial_ht_release,              /*release fn*/      \
+    command:            NULL,                           /*command fn*/      \
+    queuecommand:       mv_ial_ht_queuecommand,         /*queuecommand fn*/ \
+    ioctl:              mv_ial_ht_ioctl,                /*ioctl fn */       \
+    bios_param:         NULL    /*mv_ial_ht_biosparam*/,/*bios fn*/     \
+    eh_device_reset_handler: NULL/*mv_ial_ht_dev_reset*/,                   \
+    eh_bus_reset_handler: mv_ial_ht_bus_reset,                              \
+    eh_abort_handler:   mv_ial_ht_abort,                                    \
+    can_queue:          MV_SATA_SW_QUEUE_SIZE,                         /* unlimited */     \
+    this_id:            MV_SATA_PM_MAX_PORTS,                              /*set by detect*/   \
+    sg_tablesize:       64,                             /*sg_tablesize*/    \
+    max_sectors:        256,                                                \
+    cmd_per_lun:        MV_SATA_SW_QUEUE_SIZE,           /*cmd_per_lun*/     \
+    unchecked_isa_dma:  0,                              /*32-Bit Busmaster*/\
+    emulated:           1,                      /* not real scsi adapter */ \
+    use_new_eh_code:    1,                                                  \
+    highmem_io:         1,                           /*highmem_io enabled*/\
+    use_clustering:     ENABLE_CLUSTERING               /*use_clustering*/  \
+}
+#endif
+
+
+#define MV_IAL_HT_SACOALT_DEFAULT   4
+#define MV_IAL_HT_SAITMTH_DEFAULT   (150 * 50)
+
+/****************************************/
+/*          GENERAL Definitions         */
+/****************************************/
+
+struct IALHost;
+
+/*struct prdPool;*/
+typedef struct IALAdapter
+{
+    MV_SATA_ADAPTER     mvSataAdapter;
+    MV_U8               activeHosts;
+    int                 maxHosts;
+    struct IALHost      *host[MV_SATA_CHANNELS_NUM];
+    struct pci_dev      *pcidev;
+    u8                  rev_id; /* adapter revision id */
+    u8                  *requestsArrayBaseAddr;
+    u8                  *requestsArrayBaseAlignedAddr;
+    dma_addr_t          requestsArrayBaseDmaAddr;
+    dma_addr_t          requestsArrayBaseDmaAlignedAddr;
+    u8                  *responsesArrayBaseAddr;
+    u8                  *responsesArrayBaseAlignedAddr;
+    dma_addr_t          responsesArrayBaseDmaAddr;
+    dma_addr_t          responsesArrayBaseDmaAlignedAddr;
+    u32                  requestQueueSize;
+    u32                  responseQueueSize;
+    u32                 procNumOfInterrupts;
+    MV_IAL_COMMON_ADAPTER_EXTENSION ialCommonExt;
+    MV_BOOLEAN          stopAsyncTimer;
+    struct timer_list   asyncStartTimer;
+    MV_SAL_ADAPTER_EXTENSION  *ataScsiAdapterExt;
+    spinlock_t          adapter_lock;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    struct semaphore    rescan_mutex;
+    atomic_t            stopped;
+#endif
+    MV_U16		tempDataBuffer[TEMP_DATA_BUFFER_LENGTH/2];
+} IAL_ADAPTER_T;
+
+typedef struct IALHost
+{
+    struct Scsi_Host* scsihost;
+    MV_U8 channelIndex;
+    IAL_ADAPTER_T* pAdapter;
+    MV_EDMA_MODE mode;
+    MV_SATA_SWITCHING_MODE switchingMode;
+    MV_BOOLEAN  use128Entries;
+    void  *prdPool[MV_SATA_GEN2E_SW_QUEUE_SIZE];
+    void  *prdPoolAligned[MV_SATA_GEN2E_SW_QUEUE_SIZE];
+    MV_U32  freePRDsNum;
+    struct scsi_cmnd *scsi_cmnd_done_head, *scsi_cmnd_done_tail;
+    MV_BOOLEAN  hostBlocked;
+} IAL_HOST_T;
+
+/******************************************************************************
+* We use the Scsi_Pointer structure that's included with each command
+* SCSI_Cmnd as a scratchpad for our SRB. This allows us to accept
+* an unlimited number of commands.
+*
+* SCp will always point to mv_comp_info structure
+*******************************************************************************/
+
+/* UDMA command completion info */
+struct mv_comp_info
+{
+    struct scsi_cmnd           *SCpnt;
+    MV_SATA_EDMA_PRD_ENTRY  *cpu_PRDpnt;
+    dma_addr_t      dma_PRDpnt;
+    dma_addr_t      single_buff_busaddr;
+    unsigned int        allocated_entries;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    unsigned int        kmap_buffer;
+#endif
+    unsigned int        seq_number;
+    MV_SATA_SCSI_CMD_BLOCK  *pSALBlock;
+    struct scsi_cmnd           *next_done;
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+#define scsi_bufflen(p)		((p)->request_bufflen)
+#define use_sg(p)		((p)->use_sg)
+#else
+#define use_sg(p)		1
+#endif
+
+
+/* Once pci64_ DMA mapping interface is in, kill this. */
+/*#define pci64_alloc_consistent(d,s,p) pci_alloc_consistent((d),(s),(p))*/
+/*#define pci64_free_consistent(d,s,c,a) pci_free_consistent((d),(s),(c),(a))*/
+
+#define pci64_map_single(d,c,s,dir) pci_map_single((d),(c),(s),(dir))
+#define pci64_map_sg(d,s,n,dir) pci_map_sg((d),(s),(n),(dir))
+#define pci64_unmap_single(d,a,s,dir) pci_unmap_single((d),(a),(s),(dir))
+#define pci64_unmap_sg(d,s,n,dir) pci_unmap_sg((d),(s),(n),(dir))
+
+#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
+#define pci64_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32)))
+#define pci64_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a)))))
+#else
+#define pci64_dma_hi32(a) 0
+#define pci64_dma_lo32(a) (a)
+#endif  /* BITS_PER_LONG */
+#define sg_dma64_address(s) sg_dma_address(s)
+#define sg_dma64_len(s) sg_dma_len(s)
+
+
+#endif /* __INCmvLinuxIalHth */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalLib.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalLib.c
new file mode 100755
index 0000000..ccd77b8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalLib.c
@@ -0,0 +1,1415 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* file_name - mvLinuxIalLib.c
+*
+* DESCRIPTION:
+*   implementation for linux IAL lib functions.
+*
+* DEPENDENCIES:
+*   mvLinuxIalLib.h
+*   mvLinuxIalHt.h
+*
+*
+*******************************************************************************/
+
+/* includes */
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/autoconf.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    #include <linux/workqueue.h>
+#endif
+
+#include "mvLinuxIalLib.h"
+#include "mvIALCommon.h"
+
+#ifndef scsi_to_pci_dma_dir
+    #define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir))
+#endif
+
+
+/* Connect / disconnect timers. */
+/* Note that the disconnect timer should be smaller than the SCSI */
+/* subsystem timer. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+struct rescan_wrapper
+{
+    struct work_struct     work;
+    IAL_ADAPTER_T       *pAdapter;
+    MV_U8                  channelIndex;
+    MV_U16                 targetsToRemove;
+    MV_U16                 targetsToAdd;
+};
+#endif
+
+
+static void *mv_ial_lib_prd_allocate(IAL_HOST_T *pHost);
+
+static int mv_ial_lib_add_buffer_to_prd_table(MV_SATA_ADAPTER   *pMvSataAdapter,
+                                              MV_SATA_EDMA_PRD_ENTRY *pPRD_table,
+                                              int table_size,
+                                              int *count, dma_addr_t buf_addr,
+                                              unsigned int buf_len, int isEOT);
+
+void release_ata_mem(struct mv_comp_info * pInfo);
+
+dma_addr_t inline pci64_map_page(struct pci_dev *hwdev, void* address,
+                                 size_t size, int direction)
+
+{
+    dma_addr_t mm = pci_map_page(hwdev, virt_to_page(address),
+                                 ((unsigned long)address & ~PAGE_MASK),
+                                 size, direction);
+    return mm;
+}
+
+
+void inline pci64_unmap_page(struct pci_dev *hwdev, dma_addr_t address,
+                             size_t size, int direction)
+{
+    pci_unmap_page(hwdev, address, size, direction);
+}
+
+
+int mv_ial_lib_prd_init(IAL_HOST_T *pHost)
+{
+    MV_U8  i;
+    MV_U32  boolSize = MV_SATA_SW_QUEUE_SIZE;
+
+    if ((pHost->pAdapter->mvSataAdapter.sataAdapterGeneration >= MV_SATA_GEN_IIE)&&
+        (pHost->pAdapter->mvSataAdapter.pciConfigDeviceId != MV_SATA_DEVICE_ID_6082))
+    {
+        boolSize = MV_SATA_GEN2E_SW_QUEUE_SIZE;
+    }
+    /*
+     * Allocate PRD Pool  -
+     * Since the driver supports 64 SG table, then each PRD table can go upto
+     * 1KByte (64 entries * 16byte)
+     */
+    for (i = 0 ; i < boolSize; i++)
+    {
+        pHost->prdPool[i] = kmalloc ((MV_EDMA_PRD_ENTRY_SIZE * MV_PRD_TABLE_SIZE * 2)
+				     + 16, 
+                                     GFP_KERNEL);
+        if (pHost->prdPool[i] == NULL)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Could not allocate PRD pool\n",
+                     pHost->pAdapter->mvSataAdapter.adapterId, pHost->channelIndex);
+            return -1;
+        }
+        pHost->prdPoolAligned[i] = (void *)(((ulong)(pHost->prdPool[i]) + 15 ) & ~0xf);
+    }
+
+    pHost->freePRDsNum = boolSize;
+
+    return 0;
+}
+
+static void *mv_ial_lib_prd_allocate(IAL_HOST_T *pHost)
+{
+    return pHost->prdPoolAligned[--pHost->freePRDsNum];
+}
+
+int mv_ial_lib_prd_free(IAL_HOST_T *pHost, int size, dma_addr_t dmaPtr,
+                        void *cpuPtr)
+{
+    pci64_unmap_page(pHost->pAdapter->pcidev,
+                     dmaPtr,
+                     size * MV_EDMA_PRD_ENTRY_SIZE,
+                     PCI_DMA_TODEVICE);
+
+    pHost->prdPoolAligned[pHost->freePRDsNum++] = cpuPtr;
+    return 0;
+}
+
+
+int mv_ial_lib_prd_destroy(IAL_HOST_T *pHost)
+{
+    MV_U8 temp;
+    MV_U32  boolSize = MV_SATA_SW_QUEUE_SIZE;
+
+    if ((pHost->pAdapter->mvSataAdapter.sataAdapterGeneration >= MV_SATA_GEN_IIE)&&
+        (pHost->pAdapter->mvSataAdapter.pciConfigDeviceId != MV_SATA_DEVICE_ID_6082))
+    {
+        boolSize = MV_SATA_GEN2E_SW_QUEUE_SIZE;
+    }
+    
+    for (temp = 0; temp < boolSize; temp++)
+    {
+        if (pHost->prdPool[temp] != NULL)
+        {
+            kfree (pHost->prdPool[temp]);
+        }
+    }
+    return 0;
+}
+
+
+/*******************************************************************************
+ *  Name:   mv_ial_lib_add_done_queue
+ *
+ *  Description:    Add scsi_cmnd to done list. Caller must take care of
+ *                  adapter_lock locking.
+ *
+ *  Parameters:     pAdapter - Adapter data structure
+ *                  scsi_cmnd - SCSI command data sturcture
+ *
+ ******************************************************************************/
+void mv_ial_lib_add_done_queue (struct IALAdapter *pAdapter,
+                                MV_U8 channel,
+                                struct scsi_cmnd   *scsi_cmnd)
+{
+    /* Put new command in the tail of the queue and make it point to NULL */
+    ((struct mv_comp_info *)(&scsi_cmnd->SCp))->next_done = NULL;
+
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Adding command @ %p to done queue, "
+             "channel %d\n",scsi_cmnd, channel);
+    if ((channel >= MV_SATA_CHANNELS_NUM) || (pAdapter->host[channel] == NULL))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_FATAL_ERROR, "Adding command @ %p to "
+                 " invalid channel (%d)\n",scsi_cmnd, channel);
+    }
+    if (pAdapter->host[channel]->scsi_cmnd_done_head == NULL)
+    {
+        /* First command to the queue */
+        pAdapter->host[channel]->scsi_cmnd_done_head = scsi_cmnd;
+        pAdapter->host[channel]->scsi_cmnd_done_tail = scsi_cmnd;
+    }
+    else
+    {
+        /* We already have commands in the queue ; put this command in the tail */
+        ((struct mv_comp_info *)(&pAdapter->host[channel]->scsi_cmnd_done_tail->SCp))->next_done = scsi_cmnd;
+        pAdapter->host[channel]->scsi_cmnd_done_tail = scsi_cmnd;
+    }
+}
+
+/*******************************************************************************
+ *  Name:   mv_ial_lib_get_first_cmnd
+ *
+ *  Description:    Gets first scsi_cmnd from a chain of scsi commands to be
+ *                  completed, then sets NULL to head and tail.
+ *                  Caller must take care of adapter_lock locking.
+ *
+ *  Parameters:     pAdapter - Adapter data structure
+ *
+ *  Return Value:   Pointer to first scsi command in chain
+ ******************************************************************************/
+struct scsi_cmnd * mv_ial_lib_get_first_cmnd (struct IALAdapter *pAdapter, MV_U8 channel)
+{
+    if (pAdapter->host[channel] != NULL)
+    {
+        struct scsi_cmnd *cmnd = pAdapter->host[channel]->scsi_cmnd_done_head;
+        pAdapter->host[channel]->scsi_cmnd_done_head = NULL;
+        pAdapter->host[channel]->scsi_cmnd_done_tail = NULL;
+        return cmnd;
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+ *  Name:   mv_ial_lib_do_done
+ *
+ *  Description:    Calls scsi_done of chain of scsi commands.
+ *                  Note that adapter_lock can be locked or unlocked, but
+ *                  caller must take care that io_request_lock is locked.
+ *
+ *  Parameters:     cmnd - First command in scsi commands chain
+ *
+ ******************************************************************************/
+void mv_ial_lib_do_done (struct scsi_cmnd *cmnd)
+{
+    /* Call done function for all commands in queue */
+    while (cmnd)
+    {
+        struct scsi_cmnd *temp;
+        temp = ((struct mv_comp_info *)(&cmnd->SCp))->next_done;
+
+        if (cmnd->scsi_done == NULL)
+        {
+            return;
+        }
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Calling done to command @ %p "
+                 "scsi_done = %p\n",cmnd, cmnd->scsi_done);
+        cmnd->scsi_done(cmnd);
+        cmnd = temp;
+    }
+}
+
+
+/*******************************************************************************
+ *  Name:   mv_ial_lib_free_channel
+ *
+ *  Description:    free allocated queues for the given channel
+ *
+ *  Parameters:     pMvSataAdapter - pointer to the adapter controler this
+ *                  channel connected to.
+ *          channelNum - channel number.
+ *
+ ******************************************************************************/
+void mv_ial_lib_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
+{
+    MV_SATA_CHANNEL *pMvSataChannel;
+
+    if (channelNum >= pAdapter->mvSataAdapter.numberOfChannels)
+    {
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR, "[%d]: Bad channelNum=%d\n",
+                 pAdapter->mvSataAdapter.adapterId, channelNum);
+        return;
+    }
+
+    pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channelNum];
+    kfree(pMvSataChannel);
+    pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL;
+    return;
+}
+/****************************************************************
+ *  Name:   mv_ial_lib_init_channel
+ *
+ *  Description:    allocate request and response queues for the EDMA of the
+ *                  given channel and sets other fields.
+ *
+ *  Parameters:
+ *      pAdapter - pointer to the emulated adapter data structure
+ *      channelNum - channel number.
+ *  Return: 0 on success, otherwise on failure
+ ****************************************************************/
+int mv_ial_lib_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
+{
+    MV_SATA_CHANNEL *pMvSataChannel;
+    dma_addr_t    req_dma_addr;
+    dma_addr_t    rsp_dma_addr;
+
+    if (channelNum >= pAdapter->mvSataAdapter.numberOfChannels)
+    {
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR, "[%d]: Bad channelNum=%d",
+                 pAdapter->mvSataAdapter.adapterId, channelNum);
+        return -1;
+    }
+
+    pMvSataChannel = (MV_SATA_CHANNEL *)kmalloc(sizeof(MV_SATA_CHANNEL),
+                                                GFP_ATOMIC);
+    if (pMvSataChannel == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: out of memory\n",
+                 pAdapter->mvSataAdapter.adapterId);
+        return -1;
+    }
+    pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel;
+    pMvSataChannel->channelNumber = channelNum;
+
+    pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *)
+                                   (pAdapter->requestsArrayBaseAlignedAddr +
+                                    (channelNum * pAdapter->requestQueueSize));
+    req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr +
+                   (channelNum * pAdapter->requestQueueSize);
+
+/* check the 1K alignment of the request queue*/
+    if (((u64)req_dma_addr) & 0x3ffULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: request queue allocated isn't 1 K aligned,"
+                 " dma_addr=%x.%x channel=%d\n", pAdapter->mvSataAdapter.adapterId,
+                 (unsigned int)pci64_dma_hi32(req_dma_addr),
+                 (unsigned int)pci64_dma_lo32(req_dma_addr),
+                 channelNum);
+        return -1;
+    }
+    pMvSataChannel->requestQueuePciLowAddress = pci64_dma_lo32(req_dma_addr);
+    pMvSataChannel->requestQueuePciHiAddress = pci64_dma_hi32(req_dma_addr);
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d,%d]: request queue allocated: 0x%p\n",
+             pAdapter->mvSataAdapter.adapterId, channelNum,
+             pMvSataChannel->requestQueue);
+    pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *)
+                                    (pAdapter->responsesArrayBaseAlignedAddr +
+                                     (channelNum * pAdapter->responseQueueSize));
+    rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr +
+                   (channelNum * pAdapter->responseQueueSize);
+
+/* check the 256 alignment of the response queue*/
+    if (((u64)rsp_dma_addr) & 0xff)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d,%d]: response queue allocated isn't 256 byte "
+                 "aligned, dma_addr=%x.%x\n",
+                 pAdapter->mvSataAdapter.adapterId, (unsigned int)pci64_dma_hi32(rsp_dma_addr),
+                 (unsigned int)pci64_dma_lo32(rsp_dma_addr), channelNum);
+        return -1;
+    }
+    pMvSataChannel->responseQueuePciLowAddress = pci64_dma_lo32(rsp_dma_addr);
+    pMvSataChannel->responseQueuePciHiAddress = pci64_dma_hi32(rsp_dma_addr);
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d,%d]: response queue allocated: 0x%p\n",
+             pAdapter->mvSataAdapter.adapterId, channelNum,
+             pMvSataChannel->responseQueue);
+    return 0;
+}
+
+/****************************************************************
+ *  Name:   mv_ial_lib_int_handler
+ *
+ *  Description:    Interrupt handler.
+ *
+ *  Parameters:     irq - Hardware IRQ number.assume that different cards will have
+ *                  different IRQ's TBD
+ *                  dev_id  - points to the mvxxxxxxDeviceStruct that generated
+ *                    the interrupt
+ *                  regs    -
+ *
+ *
+ ****************************************************************/
+irqreturn_t mv_ial_lib_int_handler (int irq, void *dev_id )
+{
+    IAL_ADAPTER_T       *pAdapter;
+    unsigned long       flags;
+    int                 handled = 0;
+    struct scsi_cmnd *cmnds_done_list = NULL;
+    pAdapter = (IAL_ADAPTER_T *)dev_id;
+
+/*
+ * Acquire the adapter spinlock. Meantime all completed commands will be added
+ * to done queue.
+ */
+    spin_lock_irqsave(&pAdapter->adapter_lock, flags);
+
+    if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE)
+    {
+        handled = 1;
+        pAdapter->procNumOfInterrupts ++;
+        mvSataScsiPostIntService(pAdapter->ataScsiAdapterExt);
+    }
+    /* Unlock adapter lock */
+    spin_unlock_irqrestore(&pAdapter->adapter_lock, flags);
+    /* Check if there are commands in the done queue to be completed */
+    if (handled == 1)
+    {
+        MV_U8 i;
+
+        for (i = 0; i < pAdapter->maxHosts; i++)
+        {
+            spin_lock_irqsave(&pAdapter->adapter_lock, flags);
+            cmnds_done_list = mv_ial_lib_get_first_cmnd(pAdapter, i);
+            spin_unlock_irqrestore(&pAdapter->adapter_lock, flags);
+            if (cmnds_done_list)
+            {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+                spin_lock_irqsave(&io_request_lock, flags);
+#else
+                spin_lock_irqsave(pAdapter->host[i]->scsihost->host_lock, flags);
+#endif
+                mv_ial_lib_do_done(cmnds_done_list);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+                spin_unlock_irqrestore(&io_request_lock, flags);
+#else
+                spin_unlock_irqrestore(pAdapter->host[i]->scsihost->host_lock, flags);
+#endif
+            }
+        }
+    }
+    return IRQ_RETVAL(handled);
+}
+
+/****************************************************************
+ *  Name: mv_ial_lib_add_buffer_to_prd_table
+ *
+ *  Description:    insert one buffer into number of entries in the PRD table,
+ *                  keeping 64KB boundaries
+ *
+ *  Parameters:     pPRD_table: pointer to the PRD table.
+ *          table_size: number of entries in the PRD table.
+ *          count: index of the next entry to add, should be updated by this
+ *          function
+ *          buf_addr,buf_len: the dma address and the size of the buffer to add.
+ *          isEOT: 1 if this is the last entry
+ *  Returns:        0 on success, otherwise onfailure.
+ *
+ ****************************************************************/
+
+static int mv_ial_lib_add_buffer_to_prd_table(MV_SATA_ADAPTER   *pMvSataAdapter,
+                                              MV_SATA_EDMA_PRD_ENTRY *pPRD_table,
+                                              int table_size, int *count,
+                                              dma_addr_t buf_addr,
+                                              unsigned int buf_len,
+                                              int isEOT)
+{
+    unsigned int    entry = *count;
+    u64             xcount = 0;
+
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG,"insert to PRD table, count=%d, buf_addr=%x, buf_len=%x\n",
+             *count,(unsigned int) buf_addr, buf_len);
+
+
+
+    /*
+    The buffer is splitted in case then either the buffer size exceeds 64 KB
+    or 2 high address bits of all data in the buffer are not identical
+    */
+    while (buf_len)
+    {
+        if (entry >= table_size)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,"PRD table too small (entry %d, table_size %d\n",
+                     entry, table_size);
+            mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR,"[%d] insert to PRD table, count=%d,"
+                     " buf_addr=%x, buf_len=%x\n",
+                     pMvSataAdapter->adapterId,
+                     *count,(unsigned int) buf_addr, buf_len);
+            return -1;
+        }
+        else
+        {
+            u64 bcount = buf_len;
+            /*buffer size exceeds 64K*/
+            if (bcount > 0x10000)
+                bcount = 0x10000;
+            if (buf_addr & 0x1)
+            {
+                mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, " PRD entry low address is not 1 bit aligned\n");
+                return -1;
+            }
+#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
+            /*Split the buffer if 2 high address bits of all
+            data in the buffer are not the same*/
+            if ((buf_addr | 0xFFFFFFFF)  !=
+                ((buf_addr + bcount - 1) | 0xFFFFFFFF))
+            {
+                bcount = 0x100000000ULL - (buf_addr & 0xFFFFFFFF);
+            }
+#endif
+	    if(((buf_addr & MRVL_SATA_BOUNDARY_MASK) + bcount) > 
+	       MRVL_SATA_BUFF_BOUNDARY)
+	    {
+		 bcount = MRVL_SATA_BUFF_BOUNDARY -
+		      (buf_addr & MRVL_SATA_BOUNDARY_MASK);
+	    }
+            /*In case then buffer size is 64K
+            PRD entry byte count is set to zero*/
+            xcount = bcount & 0xffff;
+            pPRD_table[entry].lowBaseAddr =
+            cpu_to_le32(pci64_dma_lo32(buf_addr));
+            pPRD_table[entry].highBaseAddr =
+            cpu_to_le32(pci64_dma_hi32(buf_addr));
+            pPRD_table[entry].byteCount = cpu_to_le16(xcount);
+            pPRD_table[entry].reserved = 0;
+            /* enable snoop on data buffers */
+            pPRD_table[entry].flags = 0;/*cpu_to_le16(MV_EDMA_PRD_NO_SNOOP_FLAG);*/
+            if (xcount & 0x1)
+            {
+                mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR," PRD entry byte count is not 1 bit aligned\n");
+                return -1;
+            }
+            buf_addr += bcount;
+            buf_len -= bcount;
+            entry++;
+        }
+    }
+
+    if (entry)
+    {
+        if (isEOT)/* enable snoop on data buffers */
+            pPRD_table[entry-1].flags = cpu_to_le16(MV_EDMA_PRD_EOT_FLAG /*|
+                                                    MV_EDMA_PRD_NO_SNOOP_FLAG*/);
+
+        *count = entry;
+        return 0;
+    }
+
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "insert zero entries to PRD table \n");
+    return -1;
+}
+
+/* map to pci */
+int mv_ial_lib_generate_prd(MV_SATA_ADAPTER *pMvSataAdapter, struct scsi_cmnd *SCpnt,
+                            struct mv_comp_info *completion_info)
+{
+    IAL_ADAPTER_T   *pAdapter = MV_IAL_ADAPTER(SCpnt->device->host);
+    IAL_HOST_T      *pHost = HOSTDATA(SCpnt->device->host);
+    MV_SATA_EDMA_PRD_ENTRY *pPRD_table = NULL;
+    dma_addr_t PRD_dma_address = 0;
+    dma_addr_t busaddr = 0;
+    unsigned int prd_size = 0;
+    struct scatterlist *sg;
+    unsigned int prd_count;
+    MV_SATA_DEVICE_TYPE deviceType = pAdapter->ataScsiAdapterExt->ataDriveData[pHost->channelIndex][SCpnt->device->id].identifyInfo.deviceType;
+    /*should be removed*/
+#ifndef   MV_SUPPORT_1MBYTE_IOS 
+    if (scsi_bufflen(SCpnt) > (SCpnt->device->host->max_sectors << 9))
+    {
+        printk("ERROR: request length exceeds the maximum alowed value, %x %x\n",
+               pMvSataAdapter->pciConfigDeviceId,
+               pMvSataAdapter->pciConfigRevisionId);
+    }
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+    if (SCpnt->use_sg)
+    {
+        unsigned int sg_count;
+        unsigned int i;
+        sg = (struct scatterlist *) SCpnt->request_buffer;
+
+        sg_count = pci64_map_sg(pAdapter->pcidev, sg,
+                                SCpnt->use_sg,
+                                scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+
+        if (sg_count != SCpnt->use_sg)
+            printk("WARNING sg_count(%d) != SCpnt->use_sg(%d)\n",
+                   (unsigned int)sg_count, SCpnt->use_sg);
+#else
+	{
+        unsigned int sg_count;
+        unsigned int i;
+
+	sg = scsi_sglist(SCpnt);
+	sg_count = scsi_dma_map(SCpnt);
+	if (sg_count < 0) {
+		dev_err(&pAdapter->pcidev->dev, "pci_map_sg failed!\n");
+		return -1;
+	}
+
+#endif
+        if ((sg_count == 1) && (pAdapter->mvSataAdapter.sataAdapterGeneration >=
+                                MV_SATA_GEN_IIE) && (sg_dma_len(sg) <= 0x10000) && 
+            (deviceType != MV_SATA_DEVICE_TYPE_ATAPI_DEVICE))
+        {
+            completion_info->pSALBlock->singleDataRegion = MV_TRUE;
+            completion_info->cpu_PRDpnt = NULL;
+            completion_info->dma_PRDpnt = 0;
+            completion_info->allocated_entries = 0;
+            completion_info->single_buff_busaddr = 0;
+            PRD_dma_address = sg_dma_address(sg);
+            completion_info->pSALBlock->PRDTableLowPhyAddress = pci64_dma_lo32(PRD_dma_address);
+            completion_info->pSALBlock->PRDTableHighPhyAddress = pci64_dma_hi32(PRD_dma_address);
+            completion_info->pSALBlock->byteCount = sg_dma_len(sg);
+            mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "Use single data region"
+                     " buffer, size=%d\n",
+                     completion_info->pSALBlock->byteCount);
+
+            return 0;
+        }
+        prd_size = MV_PRD_TABLE_SIZE;
+        pPRD_table = (MV_SATA_EDMA_PRD_ENTRY*)mv_ial_lib_prd_allocate(pHost);
+        if (pPRD_table == NULL)
+        {
+            mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR, "Failed to allocate PRD table, requested size=%d\n"
+                     , prd_size);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+            pci64_unmap_sg(pAdapter->pcidev, sg, SCpnt->use_sg,
+                           scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+#else
+	    scsi_dma_unmap(SCpnt);
+#endif
+            return -1;
+        }
+        prd_count=0;
+        for (i=0; (i < sg_count) && (sg_dma_len(sg)); i++, sg++)
+        {
+            int isEOT;
+
+            isEOT =((i+1 < sg_count) && (sg_dma_len(&sg[1]))) ? 0 : 1;
+
+            if (mv_ial_lib_add_buffer_to_prd_table(pMvSataAdapter,
+                                                   pPRD_table,
+                                                   prd_size,
+                                                   &prd_count,
+                                                   sg_dma_address(sg),
+                                                   sg_dma_len(sg),
+                                                   isEOT))
+            {
+                mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR," in building PRD table from scatterlist, "
+                         "prd_size=%d, prd_count=%d\n", prd_size,
+                         prd_count);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+                pci64_unmap_sg(pAdapter->pcidev,
+                               (struct scatterlist *)SCpnt->request_buffer,
+                               SCpnt->use_sg,
+                               scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+#else
+		scsi_dma_unmap(SCpnt);
+#endif
+
+                return -1;
+            }
+        }
+        PRD_dma_address = pci64_map_page(pAdapter->pcidev,
+                                         pPRD_table,
+                                         MV_EDMA_PRD_ENTRY_SIZE * (prd_size),
+                                         PCI_DMA_TODEVICE);
+    }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+    else if (scsi_bufflen(SCpnt) && SCpnt->sc_data_direction != PCI_DMA_NONE)
+    {
+        if ((pAdapter->mvSataAdapter.sataAdapterGeneration >= MV_SATA_GEN_IIE)
+            && (scsi_bufflen(SCpnt) <= 0x10000) && 
+            (deviceType != MV_SATA_DEVICE_TYPE_ATAPI_DEVICE))
+        {
+            completion_info->pSALBlock->singleDataRegion = MV_TRUE;
+            completion_info->cpu_PRDpnt = NULL;
+            completion_info->dma_PRDpnt = 0;
+            completion_info->allocated_entries = 0;
+            busaddr = pci64_map_page(pAdapter->pcidev, SCpnt->request_buffer,
+                                     scsi_bufflen(SCpnt),
+                                     scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+            completion_info->single_buff_busaddr = busaddr;
+            completion_info->pSALBlock->PRDTableLowPhyAddress = pci64_dma_lo32(busaddr);
+            completion_info->pSALBlock->PRDTableHighPhyAddress = pci64_dma_hi32(busaddr);
+            completion_info->pSALBlock->byteCount = scsi_bufflen(SCpnt);
+            mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "Use single data region"
+                     " buffer, size=%d\n",
+                     completion_info->pSALBlock->byteCount);
+            return 0;
+        }
+        prd_size = MV_PRD_TABLE_SIZE;
+        pPRD_table = (MV_SATA_EDMA_PRD_ENTRY*)mv_ial_lib_prd_allocate(pHost);
+        if (pPRD_table == NULL)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "Failed to allocate PRD table, requested size=%d\n",
+                     prd_size);
+            return -1;
+        }
+
+        busaddr = pci64_map_page(pAdapter->pcidev, SCpnt->request_buffer,
+                                 scsi_bufflen(SCpnt),
+                                 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+        prd_count = 0;
+        if (mv_ial_lib_add_buffer_to_prd_table(pMvSataAdapter,
+                                               pPRD_table,
+                                               prd_size,
+                                               &prd_count, busaddr,
+                                               scsi_bufflen(SCpnt), 1))
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, " in building PRD table from buffer\n");
+            pci64_unmap_page(pAdapter->pcidev, busaddr, scsi_bufflen(SCpnt),
+                             scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+            return -1;
+        }
+        PRD_dma_address = pci64_map_page(pAdapter->pcidev,
+                                         pPRD_table,
+                                         MV_EDMA_PRD_ENTRY_SIZE* (prd_size),
+                                         PCI_DMA_TODEVICE);
+    }
+#endif
+    completion_info->cpu_PRDpnt = pPRD_table;
+    completion_info->dma_PRDpnt = PRD_dma_address;
+    completion_info->allocated_entries = prd_size;
+    completion_info->single_buff_busaddr = busaddr;
+    completion_info->pSALBlock->PRDTableLowPhyAddress = pci64_dma_lo32(PRD_dma_address);
+    completion_info->pSALBlock->PRDTableHighPhyAddress = pci64_dma_hi32(PRD_dma_address);
+    mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "PRD table allocated %p\n", pPRD_table);
+    mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "PRD table allocated (dma) %x \n", PRD_dma_address);
+    return 0;
+}
+
+
+/****************************************************************
+ *  Name: mv_ial_block_requests
+ *
+ *  Description:    Blocks request from SCSI mid layer while channel
+ *                  initialization is in progress
+ *
+ *  Parameters:     pAdapter, pointer to the IAL adapter data structure.
+ *                  channelIndex, channel number
+ *
+ *  Returns:        None.
+ *
+ ****************************************************************/
+
+void mv_ial_block_requests(struct IALAdapter *pAdapter, MV_U8 channelIndex)
+{
+    if (MV_TRUE == pAdapter->host[channelIndex]->hostBlocked)
+    {
+        return;
+    }
+
+    if ((pAdapter->ialCommonExt.channelState[channelIndex] != CHANNEL_READY) &&
+        (pAdapter->ialCommonExt.channelState[channelIndex] != CHANNEL_NOT_CONNECTED))
+    {
+        pAdapter->host[channelIndex]->hostBlocked = MV_TRUE;
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "[%d,%d]: blocking SCSI host.\n",
+                 pAdapter->mvSataAdapter.adapterId, channelIndex);
+        scsi_block_requests(pAdapter->host[channelIndex]->scsihost);
+    }
+    else
+    {
+        pAdapter->host[channelIndex]->hostBlocked = MV_FALSE;
+    }
+}
+
+/****************************************************************
+ *  Name: mv_ial_unblock_requests
+ *
+ *  Description:    Unblocks request from SCSI mid layer for non connected
+ *                  channels or channels whose initialization is finished
+ *
+ *  Parameters:     pAdapter -  pointer to the IAL adapter data structure.
+ *                  channelIndex -  channel number
+ *
+ *  Returns:        None.
+ *
+ ****************************************************************/
+static void mv_ial_unblock_requests(struct IALAdapter *pAdapter, MV_U8 channelIndex)
+{
+    if ((CHANNEL_NOT_CONNECTED == pAdapter->ialCommonExt.channelState[channelIndex]) ||
+        (CHANNEL_READY == pAdapter->ialCommonExt.channelState[channelIndex]))
+    {
+        pAdapter->host[channelIndex]->hostBlocked = MV_FALSE;
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "[%d,%d]: unblocking SCSI host.\n",
+                 pAdapter->mvSataAdapter.adapterId, channelIndex);
+        scsi_unblock_requests(pAdapter->host[channelIndex]->scsihost);
+    }
+}
+
+
+
+
+/****************************************************************
+ *  Name: mv_ial_lib_event_notify
+ *
+ *  Description:    this function called by the low  level to notify a certain event
+ *
+ *  Parameters:     pMvSataAdapter, pointer to the Device data structure.
+ *
+ *  Returns:        MV_TRUE on success, MV_FALSE on failure.
+ *
+ ****************************************************************/
+MV_BOOLEAN mv_ial_lib_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
+                                   MV_U32 param1, MV_U32 param2)
+{
+    IAL_ADAPTER_T   *pAdapter = pMvSataAdapter->IALData;
+    MV_U8   channel = param2;
+
+    switch (eventType)
+    {
+    case MV_EVENT_TYPE_SATA_CABLE:
+        {
+
+
+            if (param1 == MV_SATA_CABLE_EVENT_CONNECT)
+            {
+
+                mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "[%d,%d]: device connected event received\n",
+                         pMvSataAdapter->adapterId, channel);
+                mvRestartChannel(&pAdapter->ialCommonExt, channel,
+                                 pAdapter->ataScsiAdapterExt, MV_FALSE);
+                mv_ial_block_requests(pAdapter, channel);
+            }
+            else if (param1 == MV_SATA_CABLE_EVENT_DISCONNECT)
+            {
+                mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "[%d,%d]: device disconnected event received \n",
+                         pMvSataAdapter->adapterId, channel);
+                if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel, NULL) ==
+                    MV_FALSE)
+                {
+                    mvStopChannel(&pAdapter->ialCommonExt, channel,
+                                  pAdapter->ataScsiAdapterExt);
+                }
+                else
+                {
+                    mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG, "[%d,%d]: device disconnected event ignored.\n",
+                             pMvSataAdapter->adapterId, channel);
+                }
+
+            }
+            else if (param1 == MV_SATA_CABLE_EVENT_PM_HOT_PLUG)
+            {
+                mvPMHotPlugDetected(&pAdapter->ialCommonExt, channel,
+                                    pAdapter->ataScsiAdapterExt);
+                mv_ial_block_requests(pAdapter, channel);
+            }
+            else
+            {
+
+                mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "illegal value for param1(%d) at "
+                         "connect/disconect event, host=%d\n", param1,
+                         pMvSataAdapter->adapterId );
+            }
+        }
+        break;
+    case MV_EVENT_TYPE_ADAPTER_ERROR:
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR, "DEVICE error event received, pci cause "
+                 "reg=%x, don't know how to handle this\n", param1);
+        return MV_TRUE;
+    case MV_EVENT_TYPE_SATA_ERROR:
+        switch (param1)
+        {
+        case MV_SATA_RECOVERABLE_COMMUNICATION_ERROR:
+            mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR,
+                     " [%d %d] sata recoverable error occured\n",
+                     pMvSataAdapter->adapterId, channel);
+            break;
+        case MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR:
+            mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR,
+                     " [%d %d] sata unrecoverable error occured, restart channel\n",
+                     pMvSataAdapter->adapterId, channel);
+            mvSataChannelHardReset(pMvSataAdapter, channel);
+            mvRestartChannel(&pAdapter->ialCommonExt, channel,
+                             pAdapter->ataScsiAdapterExt, MV_TRUE);
+            mv_ial_block_requests(pAdapter, channel);
+            break;
+        case MV_SATA_DEVICE_ERROR:
+            mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR,
+                     " [%d %d] device error occured\n",
+                     pMvSataAdapter->adapterId, channel);
+            break;
+        }
+        break;
+    default:
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG_ERROR,  " adapter %d unknown event %d"
+                 " param1= %x param2 = %x\n", pMvSataAdapter->adapterId,
+                 eventType - MV_EVENT_TYPE_ADAPTER_ERROR, param1, param2);
+        return MV_FALSE;
+
+    }/*switch*/
+    return MV_TRUE;
+}
+
+MV_BOOLEAN IALConfigQueuingMode(MV_SATA_ADAPTER *pSataAdapter,
+                                MV_U8 channelIndex,
+                                MV_EDMA_MODE mode,
+                                MV_SATA_SWITCHING_MODE switchingMode,
+                                MV_BOOLEAN  use128Entries)
+
+{
+    IAL_ADAPTER_T   *pAdapter = pSataAdapter->IALData;
+    pAdapter->host[channelIndex]->mode = mode;
+    pAdapter->host[channelIndex]->switchingMode = switchingMode;
+    pAdapter->host[channelIndex]->use128Entries = use128Entries;
+
+    if (mvSataConfigEdmaMode(pSataAdapter, channelIndex,
+                             mode, 31) == MV_FALSE)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: mvSataConfigEdmaMode failed\n",
+                 pSataAdapter->adapterId, channelIndex);
+        return -1;
+    }
+    return MV_TRUE;
+}
+
+MV_BOOLEAN IALInitChannel(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex)
+{
+    if (mv_ial_lib_init_channel(pSataAdapter->IALData, channelIndex) == 0)
+    {
+        return MV_TRUE;
+    }
+    return MV_FALSE;
+}
+void IALReleaseChannel(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex)
+{
+    mv_ial_lib_free_channel(pSataAdapter->IALData, channelIndex);
+}
+
+void IALChannelCommandsQueueFlushed(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex)
+{
+
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
+static void channel_rescan(struct work_struct *work)
+{
+    struct rescan_wrapper* rescan = container_of(work, struct rescan_wrapper, work);
+    struct Scsi_Host *host;
+    struct scsi_device *sdev = NULL;
+    MV_U16 target;
+    if (rescan->pAdapter->host[rescan->channelIndex] == NULL)
+    {
+        kfree(rescan);
+        return;
+    }
+    host = rescan->pAdapter->host[rescan->channelIndex]->scsihost;
+    down(&rescan->pAdapter->rescan_mutex);
+    if (atomic_read(&rescan->pAdapter->stopped) > 0)
+    {
+        up(&rescan->pAdapter->rescan_mutex);
+        kfree(rescan);
+        return;
+    }
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "[%d %d] channel_rescan(): "
+             "targets to add 0x%X, targets to remove 0x%X\n",
+             rescan->pAdapter->mvSataAdapter.adapterId,
+             rescan->channelIndex,
+             rescan->targetsToAdd,
+             rescan->targetsToRemove);
+
+    for (target = 0; (rescan->targetsToRemove != 0) && (target < host->max_id); target++)
+    {
+        if (rescan->targetsToRemove & (1 << target))
+        {
+            sdev = scsi_device_lookup(host, 0, target, 0);
+            if (sdev != NULL)
+            {
+		    /*scsi_device_cancel(sdev, 0);*/
+                scsi_remove_device(sdev);
+                scsi_device_put(sdev);
+            }
+	    else
+	    {
+		    mvLogMsg(MV_IAL_LOG_ID,
+                         MV_DEBUG_ERROR,
+                         "[%d %d %d] failed to deattach scsi device\n",
+                         rescan->pAdapter->mvSataAdapter.adapterId,
+                         rescan->channelIndex,
+                         target);
+	    }
+        }
+    }
+    sdev = NULL;
+    for (target = 0; (rescan->targetsToAdd != 0) && (target < host->max_id); target++)
+    {
+        if (rescan->targetsToAdd & (1 << target))
+        {
+            int error = scsi_add_device(host, 0, target, 0);
+            if (error)
+            {
+                mvLogMsg(MV_IAL_LOG_ID,
+                         MV_DEBUG_ERROR,
+                         "[%d %d %d] Error adding scsi device\n",
+                         rescan->pAdapter->mvSataAdapter.adapterId,
+                         rescan->channelIndex,
+                         target);
+            }
+        }
+    }
+    up(&rescan->pAdapter->rescan_mutex);
+    kfree(rescan);
+}
+#endif
+
+MV_BOOLEAN IALBusChangeNotify(MV_SATA_ADAPTER *pSataAdapter,
+                              MV_U8 channelIndex)
+{
+    return MV_TRUE;
+}
+
+MV_BOOLEAN IALBusChangeNotifyEx(MV_SATA_ADAPTER *pSataAdapter,
+                                MV_U8 channelIndex,
+                                MV_U16 targetsToRemove,
+                                MV_U16 targetsToAdd)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    IAL_ADAPTER_T   *pAdapter = pSataAdapter->IALData;
+    if (0 == atomic_read(&pAdapter->stopped))
+    {
+        struct rescan_wrapper* rescan =
+        kmalloc(sizeof(struct rescan_wrapper), GFP_ATOMIC);
+        if (rescan != NULL)
+        {
+            INIT_WORK(&rescan->work, channel_rescan);
+            rescan->pAdapter = pAdapter;
+            rescan->channelIndex = channelIndex;
+            rescan->targetsToRemove = targetsToRemove;
+            rescan->targetsToAdd = targetsToAdd;
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,
+                     "[%d %d] Rescan bus: remove 0x%X, add 0x%X.\n",
+                     pSataAdapter->adapterId,
+                     channelIndex, targetsToRemove, targetsToAdd);
+            if (schedule_work(&rescan->work) == 0)
+            {
+                mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,
+                         "[%d %d] Rescan bus: schedule_work() failed.\n",
+                         pSataAdapter->adapterId,
+                         channelIndex);
+                kfree(rescan);
+            }
+        }
+        else
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,
+                     "[%d %d] Rescan bus: memory allocation error.\n",
+                     pSataAdapter->adapterId,
+                     channelIndex);
+        }
+    }
+#endif
+    return MV_TRUE;
+}
+
+
+void asyncStartTimerFunction(unsigned long data)
+{
+    IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)data;
+    unsigned long       flags;
+    struct scsi_cmnd *cmnds_done_list = NULL;
+    MV_U8 i;
+
+    spin_lock_irqsave(&pAdapter->adapter_lock, flags);
+    if (pAdapter->stopAsyncTimer == MV_FALSE)
+    {
+        mvIALTimerCallback(&pAdapter->ialCommonExt,
+                           pAdapter->ataScsiAdapterExt);
+        for (i = 0; i < pAdapter->maxHosts; i++)
+        {
+            if (MV_TRUE == pAdapter->host[i]->hostBlocked)
+            {
+                spin_unlock_irqrestore(&pAdapter->adapter_lock, flags);
+                mv_ial_unblock_requests(pAdapter, i);
+                spin_lock_irqsave(&pAdapter->adapter_lock, flags);
+            }
+        }
+        pAdapter->asyncStartTimer.expires = jiffies + MV_LINUX_ASYNC_TIMER_PERIOD;
+        add_timer (&pAdapter->asyncStartTimer);
+    }
+    else
+    {
+        mvLogMsg(MV_IAL_LOG_ID,  MV_DEBUG,   "[%d]: Async timer stopped\n",
+                 pAdapter->mvSataAdapter.adapterId);
+    }
+    spin_unlock_irqrestore(&pAdapter->adapter_lock, flags);
+    /* Check if there are commands in the done queue to be completed */
+    for (i = 0; i < pAdapter->maxHosts; i++)
+    {
+        spin_lock_irqsave(&pAdapter->adapter_lock, flags);
+        cmnds_done_list = mv_ial_lib_get_first_cmnd(pAdapter, i);
+        spin_unlock_irqrestore(&pAdapter->adapter_lock, flags);
+        if (cmnds_done_list)
+        {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+            spin_lock_irqsave(&io_request_lock, flags);
+#else
+            spin_lock_irqsave(pAdapter->host[i]->scsihost->host_lock, flags);
+#endif
+            mv_ial_lib_do_done(cmnds_done_list);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+            spin_unlock_irqrestore(&io_request_lock, flags);
+#else
+            spin_unlock_irqrestore(pAdapter->host[i]->scsihost->host_lock, flags);
+#endif
+        }
+    }
+}
+
+/****************************************************************
+ *  Name: release_ata_mem
+ *
+ *  Description:   free memory allocated to the PRD table
+ *          unmap the data buffers of the scsi command
+ *          free completion_info data structure.
+ *  Parameters:     pInfo: pointer to the data structure returned by the
+ *          completion call back function to identify the origial command
+ *
+ ****************************************************************/
+void release_ata_mem(struct mv_comp_info * pInfo)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+    IAL_ADAPTER_T   *pAdapter = MV_IAL_ADAPTER(pInfo->SCpnt->device->host);
+#endif
+    IAL_HOST_T      *pHost = HOSTDATA(pInfo->SCpnt->device->host);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    if(pInfo->kmap_buffer)
+    {
+	if( pInfo->SCpnt->sc_data_direction == DMA_FROM_DEVICE)
+	{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+
+		struct scatterlist *sg;
+		MV_U8*		pBuffer;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+        	sg = (struct scatterlist *) pInfo->SCpnt->request_buffer;
+#else
+		sg = scsi_sglist(pInfo->SCpnt);
+#endif
+		mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SCpnt %p: copy data from temp"
+			 " buffer to command buffer, length %d \n", pInfo->SCpnt, sg->length);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+		pBuffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+#else
+		pBuffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+#endif
+		memcpy(pBuffer, pInfo->pSALBlock->pDataBuffer , sg->length); 	
+	        kunmap_atomic(pBuffer - sg->offset, KM_IRQ0);
+
+#else
+		scsi_sg_copy_from_buffer(pInfo->SCpnt, pInfo->pSALBlock->pDataBuffer,
+					 scsi_bufflen(pInfo->SCpnt));
+
+#endif
+
+	}
+	mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SCpnt %p: free temp data "
+		 "buffer\n", pInfo->SCpnt);
+	kfree(pInfo->pSALBlock->pDataBuffer);
+    }
+#endif
+    if (pInfo->cpu_PRDpnt)
+    {
+        mv_ial_lib_prd_free(pHost,
+                            pInfo->allocated_entries,
+                            pInfo->dma_PRDpnt,
+                            pInfo->cpu_PRDpnt);
+    }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+    if( pInfo->cpu_PRDpnt || (pInfo->pSALBlock->singleDataRegion == MV_TRUE)) 
+    {
+        if (pInfo->SCpnt->use_sg)
+        {
+            pci64_unmap_sg(pAdapter->pcidev,
+                           (struct scatterlist *)pInfo->SCpnt->request_buffer,
+                           pInfo->SCpnt->use_sg,
+                           scsi_to_pci_dma_dir(pInfo->SCpnt->sc_data_direction));
+        }
+        else
+        {
+            pci64_unmap_page(pAdapter->pcidev,
+                             pInfo->single_buff_busaddr,
+                             scsi_bufflen(pInfo->SCpnt),
+                             scsi_to_pci_dma_dir(pInfo->SCpnt->sc_data_direction));
+        }
+    }
+#else
+	scsi_dma_unmap(pInfo->SCpnt);
+#endif
+    
+    pInfo->cpu_PRDpnt = NULL;
+    kfree(pInfo->pSALBlock);
+}
+
+int mv_ial_lib_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
+{
+    ulong *tmp;
+    ulong   requests_array_size;
+    ulong   responses_array_size;
+
+    if ((pAdapter->mvSataAdapter.sataAdapterGeneration >= MV_SATA_GEN_IIE) && 
+		(pAdapter->mvSataAdapter.pciConfigDeviceId != MV_SATA_DEVICE_ID_6082))
+    {
+        pAdapter->requestQueueSize = MV_EDMA_GEN2E_REQUEST_QUEUE_SIZE;
+        pAdapter->responseQueueSize = MV_EDMA_GEN2E_RESPONSE_QUEUE_SIZE;
+    }
+    else
+    {
+        pAdapter->requestQueueSize = MV_EDMA_REQUEST_QUEUE_SIZE;
+        pAdapter->responseQueueSize = MV_EDMA_RESPONSE_QUEUE_SIZE;
+    }
+    
+    requests_array_size = (pAdapter->maxHosts + 1) * (pAdapter->requestQueueSize);
+    responses_array_size =(pAdapter->maxHosts + 1) * (pAdapter->responseQueueSize);
+
+    pAdapter->requestsArrayBaseAddr =
+    pci_alloc_consistent(pAdapter->pcidev,
+                         requests_array_size,
+                         &(pAdapter->requestsArrayBaseDmaAddr));
+    if (pAdapter->requestsArrayBaseAddr == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: Failed to allocate memory for EDMA request"
+                 " queues\n", pAdapter->mvSataAdapter.adapterId);
+        return -1;
+    }
+    pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr +
+                                             pAdapter->requestQueueSize;
+    tmp = (ulong*)&pAdapter->requestsArrayBaseAlignedAddr;
+    *tmp &= ~((ulong)pAdapter->requestQueueSize - 1);
+
+    pAdapter->requestsArrayBaseDmaAlignedAddr =
+    pAdapter->requestsArrayBaseDmaAddr + pAdapter->requestQueueSize;
+    pAdapter->requestsArrayBaseDmaAlignedAddr &=
+    ~(pAdapter->requestQueueSize - 1);
+
+    if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) !=
+        (pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: Error in Request Queues Alignment\n",
+                 pAdapter->mvSataAdapter.adapterId
+                );
+        pci_free_consistent(pAdapter->pcidev, requests_array_size,
+                            pAdapter->requestsArrayBaseAddr,
+                            pAdapter->requestsArrayBaseDmaAddr);
+        return -1;
+    }
+/* response queues */
+    pAdapter->responsesArrayBaseAddr =
+    pci_alloc_consistent(pAdapter->pcidev,
+                         responses_array_size,
+                         &(pAdapter->responsesArrayBaseDmaAddr));
+    if (pAdapter->responsesArrayBaseAddr == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: Failed to allocate memory for EDMA response"
+                 " queues\n", pAdapter->mvSataAdapter.adapterId);
+        pci_free_consistent(pAdapter->pcidev, requests_array_size,
+                            pAdapter->requestsArrayBaseAddr,
+                            pAdapter->requestsArrayBaseDmaAddr);
+        return -1;
+    }
+    pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr
+                                              + pAdapter->responseQueueSize;
+    tmp = (ulong*)&pAdapter->responsesArrayBaseAlignedAddr;
+    *tmp &= ~((ulong)pAdapter->responseQueueSize - 1);
+
+    pAdapter->responsesArrayBaseDmaAlignedAddr =
+    pAdapter->responsesArrayBaseDmaAddr + pAdapter->responseQueueSize;
+    pAdapter->responsesArrayBaseDmaAlignedAddr &=
+    ~(pAdapter->responseQueueSize - 1);
+
+
+    if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) !=
+        (pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "[%d]: Error in Response Quueues Alignment\n",
+                 pAdapter->mvSataAdapter.adapterId);
+        pci_free_consistent(pAdapter->pcidev, responses_array_size,
+                            pAdapter->responsesArrayBaseAddr,
+                            pAdapter->responsesArrayBaseDmaAddr);
+        pci_free_consistent(pAdapter->pcidev, requests_array_size,
+                            pAdapter->requestsArrayBaseAddr,
+                            pAdapter->requestsArrayBaseDmaAddr);
+        return -1;
+    }
+    return 0;
+}
+
+void mv_ial_lib_free_edma_queues(IAL_ADAPTER_T *pAdapter)
+{
+    pci_free_consistent(pAdapter->pcidev,
+                        (pAdapter->maxHosts + 1) * (pAdapter->responseQueueSize),
+                        pAdapter->responsesArrayBaseAddr,
+                        pAdapter->responsesArrayBaseDmaAddr);
+    pci_free_consistent(pAdapter->pcidev,
+                        (pAdapter->maxHosts + 1) * (pAdapter->requestQueueSize),
+                        pAdapter->requestsArrayBaseAddr,
+                        pAdapter->requestsArrayBaseDmaAddr);
+}
+
+MV_BOOLEAN IALCompletion(struct mvSataAdapter *pSataAdapter,
+                         MV_SATA_SCSI_CMD_BLOCK *pCmdBlock)
+{
+    struct scsi_cmnd   *SCpnt = (struct scsi_cmnd *)pCmdBlock->IALData;
+    struct mv_comp_info *pInfo = ( struct mv_comp_info *) &(SCpnt->SCp);
+    MV_U8       host_status;
+
+
+     switch (pCmdBlock->ScsiCommandCompletion)
+    {
+    case MV_SCSI_COMPLETION_SUCCESS:
+        host_status = DID_OK;
+        break;
+    case MV_SCSI_COMPLETION_BAD_SCSI_COMMAND:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with BAD_SCSI_COMMAND\n");
+        host_status = DID_OK;
+        break;
+    case MV_SCSI_COMPLETION_ATA_FAILED:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with ATA FAILED\n");
+        host_status = DID_OK;
+        break;
+    case MV_SCSI_COMPLETION_UA_RESET:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with UA BUS"
+                 " RESET\n");
+        scsi_report_bus_reset(pInfo->SCpnt->device->host, pInfo->SCpnt->device->channel);
+        host_status = DID_OK;
+        break;
+    case MV_SCSI_COMPLETION_UA_PARAMS_CHANGED:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with UA "
+                 "PARAMETERS CHANGED\n");
+        scsi_report_bus_reset(pInfo->SCpnt->device->host, pInfo->SCpnt->device->channel);
+        host_status = DID_OK;
+        break;
+
+    case MV_SCSI_COMPLETION_QUEUE_FULL:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with QUEUE FULL\n");
+        /* flushed from ial common*/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        if (pCmdBlock->ScsiStatus == MV_SCSI_STATUS_BUSY)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Host status: DID_RESET\n");
+            host_status = DID_RESET;
+
+            pInfo->SCpnt->flags |= IS_RESETTING;
+        }
+        else
+#endif
+        {
+            host_status = DID_OK;
+        }
+        break;
+
+    case MV_SCSI_COMPLETION_ABORTED:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with ABORTED\n");
+        host_status = DID_ERROR;
+        break;
+
+    case MV_SCSI_COMPLETION_OVERRUN:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with OVERRUN\n");
+        if (pInfo->SCpnt->underflow > pCmdBlock->dataTransfered)
+        {
+            host_status = DID_ERROR;
+        }
+        else
+        {
+            host_status = DID_OK;
+        }
+        break;
+    case MV_SCSI_COMPLETION_UNDERRUN:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with UNDERRUN\n");
+        host_status = DID_ERROR;
+        break;
+
+    case MV_SCSI_COMPLETION_PARITY_ERROR:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "Scsi command completed with PARITY ERROR\n");
+        host_status = DID_PARITY;
+        break;
+    case MV_SCSI_COMPLETION_INVALID_BUS:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with INVALID BUS\n");
+        host_status = DID_BAD_TARGET;
+        break;
+    case MV_SCSI_COMPLETION_NO_DEVICE:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with NO DEVICE\n");
+        host_status = DID_NO_CONNECT;
+        break;
+    case MV_SCSI_COMPLETION_INVALID_STATUS:
+    case MV_SCSI_COMPLETION_BAD_SCB:
+    case MV_SCSI_COMPLETION_NOT_READY:
+    case MV_SCSI_COMPLETION_DISCONNECT:
+    case MV_SCSI_COMPLETION_BUS_RESET:
+    case MV_SCSI_COMPLETION_BUSY:
+    default:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR,"Bad Scsi completion status %d\n",
+                 pCmdBlock->ScsiCommandCompletion);
+        host_status = DID_ERROR;
+
+    }
+    if ((pCmdBlock->senseDataLength == 0) && (pCmdBlock->senseBufferLength))
+    {
+        pCmdBlock->pSenseBuffer[0] = 0;
+    }
+    pInfo->SCpnt->result = host_status << 16 | (pCmdBlock->ScsiStatus & 0x3f);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+    pInfo->SCpnt->resid = pCmdBlock->dataBufferLength - pCmdBlock->dataTransfered;
+#else
+    scsi_set_resid(pInfo->SCpnt, pCmdBlock->dataBufferLength - pCmdBlock->dataTransfered);
+#endif
+    if(pCmdBlock->dataBufferLength - pCmdBlock->dataTransfered) 
+    {
+	    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "Scsi command completed with resid 0x%x\n",pCmdBlock->dataBufferLength - pCmdBlock->dataTransfered);
+    }
+
+    {
+        MV_U8   channelIndex = pCmdBlock->bus;
+        release_ata_mem(pInfo);
+        mv_ial_lib_add_done_queue (pSataAdapter->IALData, channelIndex, SCpnt);
+    }
+    return MV_TRUE;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalLib.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalLib.h
new file mode 100755
index 0000000..23fb7ae
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalLib.h
@@ -0,0 +1,111 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvLinuxIalLib - Header File for Linux IAL Lib.
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*
+*******************************************************************************/
+#ifndef __INCmvLinuxIalLibh
+#define __INCmvLinuxIalLibh
+
+#include "mvLinuxIalHt.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION (2,4,23)
+#define irqreturn_t         void
+#define IRQ_RETVAL(foo)
+#endif
+#define MV_LINUX_ASYNC_TIMER_PERIOD       ((MV_IAL_ASYNC_TIMER_PERIOD * HZ) / 1000)
+
+struct pci_dev;
+struct IALAdapter;
+struct IALHost;
+struct mv_comp_info;
+
+
+/* Adapter Initialization */
+int mv_ial_lib_allocate_edma_queues(struct IALAdapter *pAdapter);
+
+void mv_ial_lib_free_edma_queues(struct IALAdapter *pAdapter);
+
+int mv_ial_lib_init_channel(struct IALAdapter *pAdapter, MV_U8 channelNum);
+
+void mv_ial_lib_free_channel(struct IALAdapter *pAdapter, MV_U8 channelNum);
+
+/* PRD Table Generation, set to twice the size of SCSI sg_tablesize (64) */
+/* this is done for cases of buffers splitting (>64k) WA, also set the   */
+/* MRVL_SATA_BUFF_BOUNDARY to SATA minimal window size (according to CS) */
+#ifndef MV_PRD_TABLE_SIZE
+ #define MV_PRD_TABLE_SIZE                  128 /* 128 entries max in PRD table */
+#endif
+
+
+int mv_ial_lib_prd_destroy(struct IALHost *pHost);
+int mv_ial_lib_prd_init(struct IALHost *);
+
+
+
+int mv_ial_lib_generate_prd(MV_SATA_ADAPTER *pMvSataAdapter, struct scsi_cmnd *SCpnt,
+                            struct mv_comp_info *);
+
+
+/* Interrupt Service Routine*/
+irqreturn_t mv_ial_lib_int_handler (int irq, void *dev_id);
+
+
+/* Event Notification */
+MV_BOOLEAN mv_ial_lib_udma_command_completion_call_back(MV_SATA_ADAPTER *pMvSataAdapter,
+                                           MV_U8 channelNum,
+                                           MV_COMPLETION_TYPE comp_type,
+                                           void *commandId,
+                                           MV_U16 responseFlags,
+                                           MV_U32 timeStamp,
+                                           MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+MV_BOOLEAN mv_ial_lib_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
+                             MV_U32 param1, MV_U32 param2);
+void asyncStartTimerFunction(unsigned long data);
+
+/* SCSI done queuing and callback */
+void mv_ial_lib_add_done_queue (struct IALAdapter *pAdapter,
+                                MV_U8 channel,
+                                struct scsi_cmnd   *scsi_cmnd);
+
+struct scsi_cmnd * mv_ial_lib_get_first_cmnd (struct IALAdapter *pAdapter,
+                                       MV_U8 channel);
+
+void mv_ial_lib_do_done (struct scsi_cmnd *cmnd);
+
+void mv_ial_block_requests(struct IALAdapter *pAdapter, MV_U8 channelIndex);
+
+#endif /* __INCmvLinuxIalLibh */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalOs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalOs.c
new file mode 100755
index 0000000..84979e8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalOs.c
@@ -0,0 +1,55 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* file_name - mvLinuxOs.c
+*
+* DESCRIPTION:  implementation for Linux Os layer
+*
+*
+* DEPENDENCIES:
+*   mvLinuxOs.h
+*   Linux header files.
+*
+*
+*******************************************************************************/
+/* Includes */
+#include "mvOsS.h"
+
+void mvMicroSecondsDelay(MV_VOID_PTR pSataAdapter, MV_U32 usecs)
+{
+    MV_U32 msecs = usecs / 1000;
+    MV_U32 i;        
+    MV_U32 tmp = usecs % 1000;
+    for (i = 0; i < msecs; i++)
+    {
+        udelay(1000);
+    }    
+    if (tmp > 0)
+        udelay(tmp);
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalSmart.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalSmart.c
new file mode 100755
index 0000000..0bfabb8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalSmart.c
@@ -0,0 +1,428 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* file_name - mvLinuxIALSmart.c
+*
+* DESCRIPTION: C file for S.M.A.R.T. features - smartmontools app
+*
+* DEPENDENCIES:
+*   None.
+*
+*
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/kdev_t.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <asm/dma.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#else
+#include <linux/blk.h>
+#include "scsi.h"
+#include "hosts.h"
+#endif
+#include "mvScsiAtaLayer.h"
+#include "mvLinuxIalHt.h"
+#include "mvRegs.h"
+#include "mvIALCommon.h"
+#include "mvLinuxIalSmart.h"
+
+
+extern MV_VOID handleNoneUdmaError(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                                   MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+extern MV_VOID handleUdmaError(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                               MV_U32 responseFlags,
+                               MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+extern MV_VOID  checkQueueCommandResult(MV_SATA_SCSI_CMD_BLOCK *pScb,
+                                        MV_QUEUE_COMMAND_RESULT result);
+
+extern MV_VOID setSenseData(IN MV_SATA_SCSI_CMD_BLOCK *pScb, IN MV_U8 SenseKey,
+                            IN MV_U8 AdditionalSenseCode);
+
+static MV_BOOLEAN
+SmartCommandCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
+                         MV_U8 channelNum,
+                         MV_COMPLETION_TYPE comp_type,
+                         MV_VOID_PTR commandId,
+                         MV_U16 responseFlags,
+                         MV_U32 timeStamp,
+                         MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+static void swap_buf_le16(u16 *buf, unsigned int buf_words)
+{
+#ifdef __BIG_ENDIAN
+     unsigned int i;
+
+     for (i = 0; i < buf_words; i++)
+	  buf[i] = le16_to_cpu(buf[i]);
+#endif /* __BIG_ENDIAN */
+}
+
+MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSendSmartCommand(IN  MV_SATA_ADAPTER* pSataAdapter,
+                                                       IN  MV_SATA_SCSI_CMD_BLOCK *pScb)
+{
+    MV_U8 *buff = (MV_U8*)pScb->pDataBuffer;
+    MV_NON_UDMA_PROTOCOL protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+    MV_QUEUE_COMMAND_RESULT result = MV_QUEUE_COMMAND_RESULT_OK;
+    MV_QUEUE_COMMAND_INFO   qCommandInfo;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SMART command: command received, bufflen = %d.\n",
+             pScb->dataBufferLength);
+    pScb->dataTransfered = 0;
+    pScb->senseDataLength = 0;
+    if (pScb->bus >= pSataAdapter->numberOfChannels)
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_INVALID_BUS;
+        pScb->dataTransfered = 0;
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    if ((pScb->target >= MV_SATA_PM_MAX_PORTS) ||
+        (pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target].driveReady == MV_FALSE))
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_NO_DEVICE;
+        pScb->dataTransfered = 0;
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    if (pScb->dataBufferLength <= 6 || /*six byte opcode*/
+        (buff[SMART_BUF_COMMAND_OFFSET] != WIN_IDENTIFY &&
+        buff[SMART_BUF_COMMAND_OFFSET] != MV_ATA_COMMAND_IDLE &&
+        buff[SMART_BUF_COMMAND_OFFSET] != MV_ATA_COMMAND_IDLE_IMMEDIATE &&
+        buff[SMART_BUF_COMMAND_OFFSET] != MV_ATA_COMMAND_STANDBY_IMMEDIATE &&
+         buff[SMART_BUF_COMMAND_OFFSET] != WIN_SMART))
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "invalid SMART command received");
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                     SCSI_ADSENSE_NO_SENSE);
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    if (buff[SMART_BUF_COMMAND_OFFSET] == WIN_IDENTIFY)
+    {
+        if (pScb->dataBufferLength < MV_ATA_IDENTIFY_DEV_DATA_LENGTH*2 + 6)
+        {
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "WIN_IDENTIFY: "
+                     "invalid buffer length.%d\n", pScb->dataBufferLength);
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                         SCSI_ADSENSE_NO_SENSE);
+            pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+            pScb->completionCallBack(pSataAdapter, pScb);
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+        protocolType = MV_NON_UDMA_PROTOCOL_PIO_DATA_IN;
+        buff[SMART_BUF_COMMAND_OFFSET] = MV_ATA_COMMAND_IDENTIFY;
+        buff[SMART_BUF_SECTORCOUNT_OFFSET] = 0;
+        buff[SMART_BUF_LBALOW_OFFSET] = 0;
+        buff[SMART_BUF_LBAMID_OFFSET] = 0;
+        buff[SMART_BUF_LBAHIGH_OFFSET] = 0;
+        buff[SMART_BUF_FEATURES_OFFSET] = 0;
+    }
+    else  if (buff[SMART_BUF_COMMAND_OFFSET] == MV_ATA_COMMAND_IDLE)
+    {
+         mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SMART command: IDLE command received, sector count = %d.\n",
+              buff[SMART_BUF_SECTORCOUNT_OFFSET]);
+
+        protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+        buff[SMART_BUF_COMMAND_OFFSET] = MV_ATA_COMMAND_IDLE;
+        buff[SMART_BUF_LBALOW_OFFSET] = 0;
+        buff[SMART_BUF_LBAMID_OFFSET] = 0;
+        buff[SMART_BUF_LBAHIGH_OFFSET] = 0;
+        buff[SMART_BUF_FEATURES_OFFSET] = 0;
+    }
+    else  if (buff[SMART_BUF_COMMAND_OFFSET] == MV_ATA_COMMAND_IDLE_IMMEDIATE)
+    {
+         mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SMART command: IDLE IMMEDIATE command received\n");
+              
+        protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+        buff[SMART_BUF_COMMAND_OFFSET] = MV_ATA_COMMAND_IDLE_IMMEDIATE;
+        buff[SMART_BUF_LBALOW_OFFSET] = 0;
+        buff[SMART_BUF_LBAMID_OFFSET] = 0;
+        buff[SMART_BUF_LBAHIGH_OFFSET] = 0;
+        buff[SMART_BUF_FEATURES_OFFSET] = 0;
+        buff[SMART_BUF_SECTORCOUNT_OFFSET] = 0;
+
+    }
+    else  if (buff[SMART_BUF_COMMAND_OFFSET] == MV_ATA_COMMAND_STANDBY_IMMEDIATE)
+    {
+         mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SMART command: STANDBY IMMEDIATE command received\n");
+              
+        protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+        buff[SMART_BUF_COMMAND_OFFSET] = MV_ATA_COMMAND_STANDBY_IMMEDIATE;
+        buff[SMART_BUF_LBALOW_OFFSET] = 0;
+        buff[SMART_BUF_LBAMID_OFFSET] = 0;
+        buff[SMART_BUF_LBAHIGH_OFFSET] = 0;
+        buff[SMART_BUF_FEATURES_OFFSET] = 0;
+        buff[SMART_BUF_SECTORCOUNT_OFFSET] = 0;
+
+    }
+ 
+    else
+    {
+        buff[SMART_BUF_LBAMID_OFFSET] = 0x4F;
+        buff[SMART_BUF_LBAHIGH_OFFSET] = 0xC2;
+        switch (buff[SMART_BUF_FEATURES_OFFSET])
+        {
+        case SMART_READ_VALUES:
+        case SMART_READ_THRESHOLDS:
+        case SMART_READ_LOG_SECTOR:
+            if (pScb->dataBufferLength < ATA_SECTOR_SIZE + 6)
+            {
+                setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                             SCSI_ADSENSE_NO_SENSE);
+                pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+                pScb->ScsiCommandCompletion =
+                MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+                pScb->completionCallBack(pSataAdapter, pScb);
+                return MV_SCSI_COMMAND_STATUS_COMPLETED;
+            }
+            protocolType = MV_NON_UDMA_PROTOCOL_PIO_DATA_IN;
+            break;
+        case SMART_ENABLE:
+        case SMART_DISABLE:
+        case SMART_AUTO_OFFLINE:
+        case SMART_AUTOSAVE:
+        case SMART_IMMEDIATE_OFFLINE:
+        case SMART_STATUS:
+            protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+            break;
+        default:
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                         SCSI_ADSENSE_NO_SENSE);
+            pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+            pScb->completionCallBack(pSataAdapter, pScb);
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+    }
+    qCommandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    qCommandInfo.commandParams.NoneUdmaCommand.protocolType = protocolType;
+    qCommandInfo.commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    qCommandInfo.PMPort = pScb->target;
+    if (protocolType == MV_NON_UDMA_PROTOCOL_NON_DATA)
+    {
+        qCommandInfo.commandParams.NoneUdmaCommand.bufPtr = NULL;
+        qCommandInfo.commandParams.NoneUdmaCommand.count = 0;
+    }
+    else
+    {
+        qCommandInfo.commandParams.NoneUdmaCommand.bufPtr =
+        (MV_U16_PTR)&buff[6];
+        qCommandInfo.commandParams.NoneUdmaCommand.count =
+        (MV_U32)(ATA_SECTOR_SIZE/2);
+        /*in words*/
+    }
+    qCommandInfo.commandParams.NoneUdmaCommand.features =
+    (MV_U16)buff[SMART_BUF_FEATURES_OFFSET];
+    qCommandInfo.commandParams.NoneUdmaCommand.sectorCount =
+    (MV_U16)buff[SMART_BUF_SECTORCOUNT_OFFSET];
+    qCommandInfo.commandParams.NoneUdmaCommand.lbaLow =
+    (MV_U16)buff[SMART_BUF_LBALOW_OFFSET];
+    qCommandInfo.commandParams.NoneUdmaCommand.lbaMid =
+    (MV_U16)buff[SMART_BUF_LBAMID_OFFSET];
+    qCommandInfo.commandParams.NoneUdmaCommand.lbaHigh =
+    (MV_U16)buff[SMART_BUF_LBAHIGH_OFFSET];
+    qCommandInfo.commandParams.NoneUdmaCommand.device = (MV_U8)(MV_BIT6);
+    qCommandInfo.commandParams.NoneUdmaCommand.command =
+    buff[SMART_BUF_COMMAND_OFFSET];
+    qCommandInfo.commandParams.NoneUdmaCommand.callBack =
+    SmartCommandCompletionCB;
+    qCommandInfo.commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, &qCommandInfo);
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    pDriveData->stats.totalIOs++;
+
+    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SMART command: SMART command %02X, queued\n",
+             buff[SMART_BUF_FEATURES_OFFSET]);
+    return MV_SCSI_COMMAND_STATUS_QUEUED;
+}
+
+static void SmartFillReturnBuffer(IN MV_U8* buff,
+                                  IN MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+
+    /*For PIO non-data return registers' values*/
+    if (buff[SMART_BUF_COMMAND_OFFSET] == WIN_SMART &&
+        buff[SMART_BUF_FEATURES_OFFSET] != SMART_READ_VALUES &&
+        buff[SMART_BUF_FEATURES_OFFSET] != SMART_READ_THRESHOLDS &&
+        buff[SMART_BUF_FEATURES_OFFSET] != SMART_READ_LOG_SECTOR)
+    {
+        buff[6+SMART_BUF_COMMAND_OFFSET] =
+        buff[SMART_BUF_COMMAND_OFFSET];
+        buff[6+SMART_BUF_FEATURES_OFFSET] =
+        buff[SMART_BUF_FEATURES_OFFSET];
+        buff[6+SMART_BUF_LBALOW_OFFSET] =
+        registerStruct->lbaLowRegister & 0xFF;
+        buff[6+SMART_BUF_SECTORCOUNT_OFFSET] =
+        registerStruct->sectorCountRegister & 0xFF;
+        buff[6+SMART_BUF_LBAMID_OFFSET] =
+        registerStruct->lbaMidRegister & 0xFF;
+        buff[6+SMART_BUF_LBAHIGH_OFFSET] =
+        registerStruct->lbaHighRegister & 0xFF;
+        buff[6+SMART_BUF_DEVICE_OFFSET] =
+        registerStruct->deviceRegister & 0xFF;
+        buff[6+SMART_BUF_ERROR_OFFSET] =
+        registerStruct->errorRegister & 0xFF;
+    }
+    else
+    {
+	 swap_buf_le16((u16 *) (buff + 6), ATA_SECTOR_SIZE/2);
+    }
+}
+
+static MV_BOOLEAN
+SmartCommandCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
+                         MV_U8 channelNum,
+                         MV_COMPLETION_TYPE comp_type,
+                         MV_VOID_PTR commandId,
+                         MV_U16 responseFlags,
+                         MV_U32 timeStamp,
+                         MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+    MV_SATA_SCSI_CMD_BLOCK  *pScb;
+    struct scsi_cmnd   *SCpnt;
+    struct mv_comp_info *pInfo;
+
+    if (commandId == NULL)
+    {
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, " commandId is NULL, can't hanlde this !!!,adapterId=%d,"
+                 " channel=%d \n", pSataAdapter->adapterId, channelNum);
+        return MV_FALSE;
+    }
+
+    pScb = commandId;
+    SCpnt = (struct scsi_cmnd *)pScb->IALData;
+    pInfo = ( struct mv_comp_info *) &(SCpnt->SCp);
+
+    switch (comp_type)
+    {
+    case MV_COMPLETION_TYPE_NORMAL:
+        if (pScb->ScsiCdb[0] == SCSI_OPCODE_MVSATA_SMART)
+        {
+            SmartFillReturnBuffer(pScb->pDataBuffer, registerStruct);
+            mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SMART PIO command completed: "
+                     "dev=%04X, Low=%04X, Mid=%04X, High=%04X, "
+                     "SC=%04X, status = %04X,\n",
+                     registerStruct->deviceRegister,
+                     registerStruct->lbaLowRegister,
+                     registerStruct->lbaMidRegister,
+                     registerStruct->lbaHighRegister,
+                     registerStruct->sectorCountRegister,
+                     registerStruct->statusRegister);
+
+	    if(pInfo->kmap_buffer)
+	    {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+		    struct scatterlist *sg;
+		    MV_U8*		pBuffer;
+		    sg = (struct scatterlist *)SCpnt->request_buffer;
+		    
+		    mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "SMART PIO command needs kmap for Data-in buffer\n");
+		    
+		    pBuffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+		    memcpy(pBuffer, pInfo->pSALBlock->pDataBuffer, sg->length); 	
+		    kunmap_atomic(pBuffer - sg->offset, KM_IRQ0);
+#else
+		    scsi_sg_copy_from_buffer(SCpnt, pInfo->pSALBlock->pDataBuffer,
+					     scsi_bufflen(SCpnt));
+#endif
+	    }
+		    
+        }
+        pScb->dataTransfered = MV_ATA_IDENTIFY_DEV_DATA_LENGTH*2;
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG, "command completed. pScb %p\n", pScb);
+        break;
+    case MV_COMPLETION_TYPE_ABORT:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, " command Aborted. Cdb: %02x %02x %02x %02x %02x "
+                 "%02x %02x %02x %02x %02x\n", pScb->ScsiCdb[0],
+                 pScb->ScsiCdb[1], pScb->ScsiCdb[2], pScb->ScsiCdb[3],
+                 pScb->ScsiCdb[4], pScb->ScsiCdb[5], pScb->ScsiCdb[6],
+                 pScb->ScsiCdb[7], pScb->ScsiCdb[8], pScb->ScsiCdb[9]);
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_ABORTED;
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+        break;
+    case MV_COMPLETION_TYPE_ERROR:
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_ATA_FAILED;
+
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, " completion error, adapter =%d, channel=%d, flags=%x\n"
+                 ,pSataAdapter->adapterId, channelNum, responseFlags);
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "Failed command Cdb: %02x %02x %02x %02x %02x "
+                 "%02x %02x %02x %02x %02x\n", pScb->ScsiCdb[0],
+                 pScb->ScsiCdb[1], pScb->ScsiCdb[2], pScb->ScsiCdb[3],
+                 pScb->ScsiCdb[4], pScb->ScsiCdb[5], pScb->ScsiCdb[6],
+                 pScb->ScsiCdb[7], pScb->ScsiCdb[8], pScb->ScsiCdb[9]);
+        /* here the  eDMA will be stopped, so we have to flush  */
+        /* the pending commands                                 */
+        handleNoneUdmaError(pScb, registerStruct);
+        break;
+    default:
+        mvLogMsg(MV_IAL_LOG_ID, MV_DEBUG_ERROR, "Unknown completion type (%d)\n", comp_type);
+        return MV_FALSE;
+    }
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_TRUE;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalSmart.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalSmart.h
new file mode 100755
index 0000000..206ed2b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvLinuxIalSmart.h
@@ -0,0 +1,109 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* file_name - mvLinuxIALSmart.h
+*
+* DESCRIPTION: C header file for S.M.A.R.T. features - smartmontools app
+*
+*
+* DEPENDENCIES:
+*   
+*
+*
+*******************************************************************************/
+#ifndef __INCmvScsiSmart
+#define __INCmvScsiSmart
+
+/*Proprietary opcode to support smartmontools app*/
+#define SCSI_OPCODE_MVSATA_SMART            0x0C
+
+
+/*S.M.A.R.T ATA commands used*/
+#ifndef WIN_IDENTIFY
+#define WIN_IDENTIFY                        0xEC
+#endif
+#ifndef WIN_SMART
+#define WIN_SMART                           0xB0    
+#endif
+#ifndef SMART_READ_VALUES
+#define SMART_READ_VALUES                   0xD0
+#endif
+#ifndef SMART_READ_THRESHOLDS   
+#define SMART_READ_THRESHOLDS               0xD1
+#endif
+#ifndef SMART_AUTOSAVE 
+#define SMART_AUTOSAVE                      0xD2
+#endif
+#ifndef SMART_SAVE
+#define SMART_SAVE                          0xD3
+#endif
+#ifndef SMART_IMMEDIATE_OFFLINE 
+#define SMART_IMMEDIATE_OFFLINE             0xD4
+#endif
+#ifndef SMART_READ_LOG_SECTOR
+#define SMART_READ_LOG_SECTOR               0xD5
+#endif
+#ifndef SMART_WRITE_LOG_SECTOR
+#define SMART_WRITE_LOG_SECTOR              0xD6
+#endif
+/* The following is obsolete -- don't use it!*/
+#ifndef SMART_WRITE_THRESHOLDS
+#define SMART_WRITE_THRESHOLDS              0xD7
+#endif
+#ifndef SMART_ENABLE
+#define SMART_ENABLE                        0xD8
+#endif
+#ifndef SMART_DISABLE
+#define SMART_DISABLE                       0xD9
+#endif
+#ifndef SMART_STATUS
+#define SMART_STATUS                        0xDA
+#endif
+
+/* The following is also marked obsolete in ATA-5*/
+#ifndef SMART_AUTO_OFFLINE
+#define SMART_AUTO_OFFLINE                  0xDB
+#endif
+
+/*Definitions of S.M.A.R.T. command buffer offsets*/
+#define SMART_BUF_COMMAND_OFFSET                0
+#define SMART_BUF_LBALOW_OFFSET                 1
+#define SMART_BUF_FEATURES_OFFSET               2
+#define SMART_BUF_SECTORCOUNT_OFFSET            3
+#define SMART_BUF_LBAMID_OFFSET                 4
+#define SMART_BUF_LBAHIGH_OFFSET                5
+#define SMART_BUF_DEVICE_OFFSET                 6
+#define SMART_BUF_ERROR_OFFSET                  7
+
+
+MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSendSmartCommand
+                (IN  MV_SATA_ADAPTER* pSataAdapter,
+                 IN  MV_SATA_SCSI_CMD_BLOCK *pScb);
+
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvScsiAtaLayer.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvScsiAtaLayer.c
new file mode 100755
index 0000000..a178247
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvScsiAtaLayer.c
@@ -0,0 +1,3563 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvScsiAtaLayer.c
+*
+* DESCRIPTION:
+*       C implementation for SCSI to ATA translation layer.
+*
+* DEPENDENCIES:
+*   mvIALCommon.h
+*   mvScsiAtaLayer.h
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvScsiAtaLayer.h"
+#include "mvIALCommon.h"
+
+#ifdef MV_LOGGER
+    #define SAL_SPRINTF     sprintf
+#endif
+
+/* ATA defines */
+/* Bits for HD_ERROR */
+#define NM_ERR          0x02    /* media present */
+#define ABRT_ERR        0x04    /* Command aborted */
+#define MCR_ERR         0x08    /* media change request */
+#define IDNF_ERR        0x10    /* ID field not found */
+#define MC_ERR          0x20    /* media changed */
+#define UNC_ERR         0x40    /* Uncorrect data */
+#define WP_ERR          0x40    /* write protect */
+#define ICRC_ERR        0x80    /* new meaning:  CRC error during transfer */
+
+#ifdef MV_LOGGER
+static MV_VOID reportScbCompletion(MV_SATA_ADAPTER*    pSataAdapter,
+                                   MV_SATA_SCSI_CMD_BLOCK *pScb);
+#endif
+
+/* Locals */
+static MV_VOID mvAta2HostString(IN   MV_U16 *source,
+                                OUT  MV_U16 *target,
+                                IN   MV_U32 wordsCount);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetInquiryData(IN  MV_SATA_ADAPTER*    pSataAdapter,
+                                                            IN  MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaTestUnitReady(IN  MV_SATA_ADAPTER*    pSataAdapter,
+                                                           IN  MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSendDataCommand(IN  MV_SATA_ADAPTER*    pSataAdapter,
+                                                             IN  MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetReadCapacityData(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                                 IN MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaReportLuns(IN MV_SATA_ADAPTER*    pSataAdapter,
+							IN MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSendVerifyCommand(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                               IN MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaReassignBlocks(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                            IN MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSendSyncCacheCommand(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                                  IN MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetRequestSenseData(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                                 IN MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetModeSenseData(IN    MV_SATA_ADAPTER*    pSataAdapter,
+                                                              IN    MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_BOOLEAN  mvScsiAtaGetModeSenseDataPhase2(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                   IN  MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaModeSelect(IN    MV_SATA_ADAPTER*    pSataAdapter,
+                                                        IN    MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_U8 modeSelect(IN MV_SATA_ADAPTER    *pSataAdapter,
+                        IN  MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                        MV_SCSI_COMMAND_STATUS_TYPE *pCommandStatus);
+
+static MV_U8 mvParseModeCachingPage(MV_SATA_ADAPTER *pSataAdapter,
+                                    IN  MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                                    MV_U8 *buffer,
+                                    MV_SCSI_COMMAND_STATUS_TYPE *pCommandStatus);
+static MV_U32 mvModeSenseCachingPage(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                                     MV_U8 *buffer, MV_U8 pageControl);
+
+static MV_U32 mvModeSenseControlPage(MV_SATA_ADAPTER *pSataAdapter,
+                                     MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                                     MV_U8 *buffer, MV_U8 pageControl);
+
+static MV_BOOLEAN SALCommandCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
+                                         MV_U8 channelNum,
+                                         MV_COMPLETION_TYPE comp_type,
+                                         MV_VOID_PTR commandId,
+                                         MV_U16 responseFlags,
+                                         MV_U32 timeStamp,
+                                         MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+MV_VOID setSenseData(IN MV_SATA_SCSI_CMD_BLOCK *pScb, IN MV_U8 SenseKey,
+                     IN MV_U8 AdditionalSenseCode, IN MV_U8 ASCQ);
+
+MV_VOID _fillSenseInformation(IN MV_SATA_SCSI_CMD_BLOCK *pScb, MV_SCSI_SENSE_DATA *SenseData,
+			      MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+MV_VOID handleNoneUdmaError(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                            MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+static MV_VOID handleUdmaError(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                               MV_U32 responseFlags,
+                               MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+/*static*/ MV_VOID  checkQueueCommandResult(MV_SATA_SCSI_CMD_BLOCK *pScb,
+                                            MV_QUEUE_COMMAND_RESULT result);
+
+static MV_VOID  mvScsiAtaSendSplittedVerifyCommand(IN MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_VOID  mvScsiAtaSendReadLookAhead(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                           IN MV_SATA_SCSI_CMD_BLOCK  *pScb);
+
+static MV_VOID mvAta2HostString(IN MV_U16 *source,
+                                OUT MV_U16 *target,
+                                IN MV_U32 wordsCount
+                               )
+{
+    MV_U32 i;
+    for (i=0 ; i < wordsCount; i++)
+    {
+        target[i] = (source[i] >> 8) | ((source[i] & 0xff) << 8);
+        target[i] = MV_LE16_TO_CPU(target[i]);
+    }
+}
+
+MV_VOID setSenseData(IN MV_SATA_SCSI_CMD_BLOCK *pScb, IN MV_U8 SenseKey,
+                     IN MV_U8 AdditionalSenseCode, IN MV_U8 ASCQ)
+{
+    MV_SCSI_SENSE_DATA SenseData;
+
+    if (pScb->senseBufferLength == 0)
+    {
+        pScb->senseDataLength = 0;
+        return;
+    }
+    memset(&SenseData, 0, sizeof(MV_SCSI_SENSE_DATA));
+//    SenseData.Valid = 0;
+    SenseData.ResponseCode = MV_SCSI_RESPONSE_CODE;
+    SenseData.SenseKey = SenseKey;
+    SenseData.AdditionalSenseCode = AdditionalSenseCode;
+    SenseData.AdditionalSenseCodeQualifier = ASCQ;
+    SenseData.AdditionalSenseLength = sizeof(MV_SCSI_SENSE_DATA) - 8;
+    pScb->senseDataLength = sizeof(MV_SCSI_SENSE_DATA);
+    if (pScb->senseBufferLength < pScb->senseDataLength)
+    {
+        pScb->senseDataLength = pScb->senseBufferLength;
+    }
+    memcpy(pScb->pSenseBuffer, &SenseData, pScb->senseDataLength);
+}
+
+MV_VOID _fillSenseInformation(IN MV_SATA_SCSI_CMD_BLOCK *pScb, MV_SCSI_SENSE_DATA *SenseData,
+			      MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+        if (pScb->isExtended == MV_TRUE)
+        {
+		/* LBA 48 error handling */
+		SenseData->InformationDesc.information[2] = (MV_U8)((registerStruct->lbaHighRegister >> 8) & 0xff);
+		SenseData->InformationDesc.information[3] = (MV_U8)((registerStruct->lbaMidRegister >> 8) & 0xff);
+		SenseData->InformationDesc.information[4] = (MV_U8)((registerStruct->lbaLowRegister >> 8) & 0xff);
+        }
+        else
+        {
+            /* LBA 28 error handling */
+            SenseData->InformationDesc.information[4] =  (MV_U8)((registerStruct->deviceRegister) & 0x0f);
+        }
+        SenseData->InformationDesc.information[5] = (MV_U8)(registerStruct->lbaHighRegister & 0xff);
+        SenseData->InformationDesc.information[6] = (MV_U8)(registerStruct->lbaMidRegister & 0xff);
+        SenseData->InformationDesc.information[7] = (MV_U8)(registerStruct->lbaLowRegister & 0xff);
+}
+
+/*
+ *  setPassThruSense - Set SCSI PassThru sense block.
+ *
+ *  This function is specific to the ATA passthru command.
+ *  Regardless of whether the command issue or not, fill the sense
+ *  buffer with the ATA descriptor return.
+ */
+static MV_VOID setPassThruSense(MV_SATA_SCSI_CMD_BLOCK *pScb,
+                                MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+    MV_SCSI_SENSE_DATA *sb = (MV_SCSI_SENSE_DATA *) pScb->pSenseBuffer;
+    MV_U8 *desc;
+
+    /* Some sanity checks */
+    if (unlikely(!pScb->pSenseBuffer ||
+                 (pScb->senseBufferLength < sizeof(MV_SCSI_SENSE_DATA))))
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR,
+                 "Can't set ATA pass through sense: invalid buffer\n");
+        return;
+    }
+
+    memset(sb, 0, sizeof(MV_SCSI_SENSE_DATA));
+    desc = (MV_U8 *) &sb->InformationDesc;
+
+    sb->ResponseCode = MV_SCSI_RESPONSE_CODE;
+
+    /* CK_COND bit it on, need to return indication to application */
+    if (pScb->ScsiCdb[2] & MV_BIT5)
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+
+    /*
+     * TODO: Check registerStruct->errorRegister and fill the sense
+     * buffer accordingly.
+     */
+
+    pScb->senseDataLength = 22;
+
+    /* Set length of additional sense data */
+    sb->AdditionalSenseLength = 14;
+
+    /*
+     * Copy registers into the additional sense buffer.
+     * This buffer should map the ATA descriptor return.
+     */
+    desc[0]     = 0x09;
+    desc[1]     = 12; /* Additional length */
+    desc[2]     = 0x00;
+    desc[3]     = registerStruct->errorRegister;
+    desc[5]     = (MV_U8)(registerStruct->sectorCountRegister);
+    desc[7]     = (MV_U8)(registerStruct->lbaLowRegister);
+    desc[9]     = (MV_U8)(registerStruct->lbaMidRegister);
+    desc[11]    = (MV_U8)(registerStruct->lbaHighRegister);
+    desc[12]    = registerStruct->deviceRegister;
+    desc[13]    = registerStruct->statusRegister;
+
+    /* LBA 48 error handling */
+    if (pScb->isExtended == MV_TRUE)
+    {
+        desc[2]     |= 0x01; /* Extended ATA descriptor return bit */
+        desc[4]     = (MV_U8)(registerStruct->sectorCountRegister >> 8);
+        desc[6]     = (MV_U8)(registerStruct->lbaLowRegister >> 8);
+        desc[8]     = (MV_U8)(registerStruct->lbaMidRegister >> 8);
+        desc[10]    = (MV_U8)(registerStruct->lbaHighRegister >> 8);
+    }
+}
+
+static MV_BOOLEAN checkLBAOutOfRange(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                     IN MV_SATA_SCSI_CMD_BLOCK *pScb,
+                                     IN MV_U64 ATADiskSize, IN MV_U64 LBA,
+                                     IN MV_U32 sectors)
+{
+    if ((ATADiskSize <= LBA) ||  ((ATADiskSize - LBA) < sectors) || sectors > 0xFFFF)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Error LBA out of range. DiskSize %x sectors %x LBA %x\n"
+                 , ATADiskSize, sectors, LBA);
+
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                     SCSI_ADSENSE_ILLEGAL_BLOCK, 0);
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_TRUE;
+
+    }
+    return MV_FALSE;
+}
+/*******************************************************************************
+* mvScsiAtaGetInquiryData - Get the SCSI-3 standard inquiry(12h) data
+*
+* DESCRIPTION: This function fills the data buffer with Scsi standard inquiry
+*       data according to the ATA Identify data
+*
+* INPUT:
+*   pSataAdapter    - pointer to the SATA adapter data structure.
+*   pScb->bus    - the index of the specific SATA channel.
+*   pScb            - pointer to the Scsi command block.
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE on failure.
+*
+* COMMENTS:
+*   No sanity check is done for the parameters.
+*
+*******************************************************************************/
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetInquiryData(IN  MV_SATA_ADAPTER*    pSataAdapter,
+                                                            IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_U8           buff[42];
+    MV_U32          inquiryLen;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+    memset(buff, 0, 42);
+
+    if ((pScb->ScsiCdb[1] & (MV_BIT0 | MV_BIT1)) ||
+        (pScb->ScsiCdb[2]))
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%d %d: Inquiry completed with error: cmd[1] %x cmd[2] %x\n",
+                 pSataAdapter->adapterId, pScb->bus, pScb->ScsiCdb[1],
+                 pScb->ScsiCdb[2]);
+        if (pDriveData->UAConditionPending == MV_TRUE)
+        {
+
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Unit Attention condition is pending.\n");
+
+            if (pDriveData->UAEvents & MV_BIT0)
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Report Bus Reset.\n");
+
+                pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_UA_RESET;
+                setSenseData(pScb, SCSI_SENSE_UNIT_ATTENTION, SCSI_ADSENSE_BUS_RESET
+                             , 2);
+                pDriveData->UAEvents &= ~MV_BIT0;
+            }
+            else if (pDriveData->UAEvents & MV_BIT1)
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Report Mode Parameters Changed.\n");
+                pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_UA_PARAMS_CHANGED;
+                setSenseData(pScb, SCSI_SENSE_UNIT_ATTENTION,
+                             SCSI_ADSENSE_PARAMETERS_CHANGED, 1);
+                pDriveData->UAEvents &= ~MV_BIT1;
+            }
+
+            pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+            pScb->dataTransfered = 0;
+#ifdef MV_LOGGER
+            reportScbCompletion(pSataAdapter, pScb);
+#endif
+            pScb->completionCallBack(pSataAdapter, pScb);
+            if (pDriveData->UAEvents == 0)
+            {
+                pDriveData->UAConditionPending = MV_FALSE;
+            }
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB,
+                     0);
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    if (pScb->lun)
+    {
+        buff[0] = 0x7f;
+        inquiryLen = 5;
+    }
+    else
+    {
+        MV_U8   Vendor[9],Product[17], temp[24];
+        buff[0] = MV_SCSI_DIRECT_ACCESS_DEVICE;
+        buff[1] = 0;    /* Not Removable disk */
+        buff[2] = 5;    /*claim conformance to SCSI-3*/
+        buff[3] = 2;    /* set RESPONSE DATA FORMAT to 2*/
+        buff[4] = 41 - 4; /* n - 4, n start from 0 */
+#if 0
+        buff[6] = 0x80;     /* basic queuing*/
+        buff[7] = 0;
+#else
+        buff[6] = 0x0;     /* tagged queuing*/
+        buff[7] = 2;
+#endif
+        memcpy(temp, pDriveData->identifyInfo.model, 24);
+        mvAta2HostString((MV_U16 *)temp, (MV_U16 *)(temp), 12);
+        {
+            MV_U32 i;
+            for (i = 0; i < 9; i++)
+            {
+                if (temp[i] == ' ')
+                {
+                    break;
+                }
+            }
+            if (i == 9)
+            {
+                if (((temp[0] == 'I') && (temp[1] == 'C')) ||
+                    ((temp[0] == 'H') && (temp[1] == 'T')) ||
+                    ((temp[0] == 'H') && (temp[1] == 'D')) ||
+                    ((temp[0] == 'D') && (temp[1] == 'K')))
+                { /*Hitachi*/
+                    Vendor[0] = 'H';
+                    Vendor[1] = 'i';
+                    Vendor[2] = 't';
+                    Vendor[3] = 'a';
+                    Vendor[4] = 'c';
+                    Vendor[5] = 'h';
+                    Vendor[6] = 'i';
+                    Vendor[7] = ' ';
+                    Vendor[8] = '\0';
+                }
+                else if ((temp[0] == 'S') && (temp[1] == 'T'))
+                {
+                    /*Seagate*/
+                    Vendor[0] = 'S';
+                    Vendor[1] = 'e';
+                    Vendor[2] = 'a';
+                    Vendor[3] = 'g';
+                    Vendor[4] = 'a';
+                    Vendor[5] = 't';
+                    Vendor[6] = 'e';
+                    Vendor[7] = ' ';
+                    Vendor[8] = '\0';
+                }
+                else
+                {
+                    /*Unkown*/
+                    Vendor[0] = 'A';
+                    Vendor[1] = 'T';
+                    Vendor[2] = 'A';
+                    Vendor[3] = ' ';
+                    Vendor[4] = ' ';
+                    Vendor[5] = ' ';
+                    Vendor[6] = ' ';
+                    Vendor[7] = ' ';
+                    Vendor[8] = '\0';
+                }
+                memcpy(Product, temp, 16);
+                Product[16] = '\0';
+            }
+            else
+            {
+                MV_U32 j = i;
+                memcpy(Vendor, temp, j);
+                for (; j < 9; j++)
+                {
+                    Vendor[j] = ' ';
+                }
+                Vendor[8] = '\0';
+                for (; i < 24; i++)
+                {
+                    if (temp[i] != ' ')
+                    {
+                        break;
+                    }
+                }
+                memcpy(Product, &temp[i], 24 - i);
+                Product[16] = '\0';
+            }
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Vendor %s Product %s\n", Vendor, Product);
+            memcpy(&buff[8], Vendor, 8);
+            memcpy(&buff[16], Product, 16);
+            memcpy(&buff[32], pDriveData->identifyInfo.firmware, 4);
+            mvAta2HostString((MV_U16 *)(&buff[32]), (MV_U16 *)(&buff[32]), 2);
+        }
+        memcpy(&buff[36], "MVSATA", 6);
+
+        /*buff[32] = '3';*/
+
+        inquiryLen = 42;
+    }
+    if (pScb->dataBufferLength > inquiryLen)
+    {
+        memcpy(pScb->pDataBuffer, buff, inquiryLen);
+        pScb->dataTransfered = inquiryLen;
+    }
+    else
+    {
+        memcpy(pScb->pDataBuffer, buff, pScb->dataBufferLength);
+        pScb->dataTransfered = pScb->dataBufferLength;
+    }
+    pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+    pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+    pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+}
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaTestUnitReady(IN  MV_SATA_ADAPTER*    pSataAdapter,
+                                                           IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+    pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+    pScb->senseDataLength = 0;
+    pScb->dataTransfered = 0;
+
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+}
+
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSendDataCommand(IN  MV_SATA_ADAPTER*    pSataAdapter,
+                                                             IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_U8           *cmd = pScb->ScsiCdb;
+    MV_QUEUE_COMMAND_RESULT    result;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+    MV_SAL_ADAPTER_EXTENSION *pAdapterExt = pScb->pSalAdapterExtension;
+    MV_U32                  sectors;
+    MV_U64		    LBA;
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO *pCommandInfo = pScb->pCommandInfo;
+    MV_UDMA_COMMAND_PARAMS  *pUdmaParams = &pCommandInfo->commandParams.udmaCommand;
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE;
+    pUdmaParams->isEXT = MV_FALSE;
+    pUdmaParams->FUA = MV_FALSE;
+    pUdmaParams->highLBAAddress = 0;
+    pUdmaParams->callBack = SALCommandCompletionCB;
+    pUdmaParams->commandId = (MV_VOID_PTR )pScb;
+#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION
+    pUdmaParams->singleDataRegion = pScb->singleDataRegion;
+    pUdmaParams->byteCount = pScb->byteCount;
+#endif
+#else    
+    MV_QUEUE_COMMAND_INFO commandInfo =
+    {
+        MV_QUEUED_COMMAND_TYPE_UDMA,
+        pScb->target,
+        {
+            {
+                MV_UDMA_TYPE_WRITE, MV_FALSE, MV_FALSE, 0, 0, 0, 0, 0,
+#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION
+                pScb->singleDataRegion,
+                pScb->byteCount,
+#endif
+                SALCommandCompletionCB, (MV_VOID_PTR )pScb
+            }
+        }
+    };
+    MV_QUEUE_COMMAND_INFO *pCommandInfo = &commandInfo;
+    MV_UDMA_COMMAND_PARAMS  *pUdmaParams = &pCommandInfo->commandParams.udmaCommand;
+#endif
+
+    if ((cmd[0] == SCSI_OPCODE_READ6) || (cmd[0] == SCSI_OPCODE_WRITE6))
+    {
+        pUdmaParams->lowLBAAddress =
+        ( (MV_U32)  cmd[3]) |
+        (((MV_U32)  cmd[2]) << 8) |
+        ((((MV_U32) cmd[1]) & 0x1f) << 16);
+        sectors = (MV_U16) cmd[4];
+    }
+    else if ((cmd[0] == SCSI_OPCODE_READ10) || (cmd[0] == SCSI_OPCODE_WRITE10))
+    {
+        pUdmaParams->lowLBAAddress =
+        (((MV_U32) cmd[5]) << 0) |
+        (((MV_U32) cmd[4]) << 8) |
+        (((MV_U32) cmd[3]) << 16) |
+        (((MV_U32) cmd[2]) << 24);
+
+        sectors = ((MV_U16) cmd[8]) |
+		(((MV_U16) cmd[7]) << 8);
+        if (cmd[1] & MV_BIT3)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%d %d: READ10/WRITE10 command "
+                     "received with FUA\n",
+                     pSataAdapter->adapterId, pScb->bus);
+            pUdmaParams->FUA = MV_TRUE;
+        }
+    }
+    else
+    {
+        pUdmaParams->lowLBAAddress =
+        (((MV_U32) cmd[9]) << 0) |
+        (((MV_U32) cmd[8]) << 8) |
+        (((MV_U32) cmd[7]) << 16) |
+        (((MV_U32) cmd[6]) << 24);
+
+        pUdmaParams->highLBAAddress =
+        (((MV_U32) cmd[5]) << 0) |
+        (((MV_U32) cmd[4]) << 8) |
+        (((MV_U32) cmd[3]) << 16) |
+        (((MV_U32) cmd[2]) << 24);
+
+        sectors = (cmd[13]) |
+		  (cmd[12] << 8) |
+		  (cmd[11] << 16) |
+		  (cmd[10] << 24);
+
+        if (cmd[1] & MV_BIT3)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%d %d: READ16/WRITE16 command "
+                     "received with FUA\n",
+                     pSataAdapter->adapterId, pScb->bus);
+            pUdmaParams->FUA = MV_TRUE;
+        }
+    }
+    LBA = ((MV_U64)pUdmaParams->highLBAAddress << 32) | (MV_U64)pUdmaParams->lowLBAAddress;
+    pScb->isExtended = pUdmaParams->isEXT = pDriveData->identifyInfo.LBA48Supported;
+
+    /* If READ10 / WRITE10 with 0 sectors (no data transfer), then complete */
+    /* the command with OK.                                                 */
+    /* If READ6 / WRITE6 with 0 sectors, seemse the Windows have problem with */
+    /* this and doesn't allocate and buffers for this ; so complete this    */
+    /* command with ILLEGAL REQUEST sense and INVLAID CDB in addition sense */
+    /* code.                                                                */
+
+    if (sectors == 0)
+    {
+        if ((cmd[0] == SCSI_OPCODE_READ10) || (cmd[0] == SCSI_OPCODE_WRITE10) || 
+	    (cmd[0] == SCSI_OPCODE_READ16) || (cmd[0] == SCSI_OPCODE_WRITE16))
+        {
+
+            if (checkLBAOutOfRange(pSataAdapter, pScb,
+                                   pDriveData->identifyInfo.ATADiskSize,
+                                   LBA, 0) == MV_TRUE)
+            {
+                return MV_SCSI_COMMAND_STATUS_COMPLETED;
+            }
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+            pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+            pScb->dataTransfered = 0;
+            pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+            reportScbCompletion(pSataAdapter, pScb);
+#endif
+            pScb->completionCallBack(pSataAdapter, pScb);
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+        else
+        {
+            /* READ6 / WRITE6 with sector count 0, which means 256 sectors */
+            sectors = 256;
+        }
+    }
+    if (checkLBAOutOfRange(pSataAdapter, pScb,
+                           pDriveData->identifyInfo.ATADiskSize,
+                           LBA, sectors) == MV_TRUE)
+    {
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    /* If trying to send more than 256 sectors or DataTransferLength field is
+     * not equal to number of sectors request in CDB then return invalid
+     * request.
+     */
+
+    if (((sectors > 256) && (pUdmaParams->isEXT == MV_FALSE)) ||
+        ((sectors * ATA_SECTOR_SIZE) != pScb->dataBufferLength))
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    if ((cmd[0] == SCSI_OPCODE_READ6) || (cmd[0] == SCSI_OPCODE_READ10) || 
+	(cmd[0] == SCSI_OPCODE_READ16))
+    {
+        pUdmaParams->readWrite = MV_UDMA_TYPE_READ;
+    }
+    pScb->dataTransfered = sectors * ATA_SECTOR_SIZE;
+    pScb->udmaType = pUdmaParams->readWrite;
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_UDMA;
+    pScb->LowLbaAddress = pUdmaParams->lowLBAAddress;
+    pUdmaParams->numOfSectors = sectors;
+
+    if ((sectors == 256) &&
+        ((pDriveData->identifyInfo.LBA48Supported == MV_FALSE)))
+    {
+        pUdmaParams->numOfSectors = 0;
+    }
+    pUdmaParams->prdLowAddr = pScb->PRDTableLowPhyAddress;
+    pUdmaParams->prdHighAddr = pScb->PRDTableHighPhyAddress;
+
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    /*update statistics*/
+
+    pAdapterExt->totalAccumulatedOutstanding[pScb->bus] +=
+    mvSataNumOfDmaCommands(pSataAdapter,pScb->bus);
+    pDriveData->stats.totalIOs++;
+    pDriveData->stats.totalSectorsTransferred += pUdmaParams->numOfSectors;
+
+    return MV_SCSI_COMMAND_STATUS_QUEUED;
+}
+
+
+/*******************************************************************************
+ *  mvScsiAtaStartStopCommand - Translate SCSI START_STOP UNIT command
+ *
+ *  DESCRIPTION:Enqueue an ATA command to issue STANDBY (to stop) or READ VERIFY
+ *              (to start). Perhaps these commands should be preceded by
+ *              CHECK POWER MODE to see what power mode the device is already in.
+ *              [See SAT revision 5 at www.t10.org]
+ *
+ *  INPUT:
+ *          pSataAdapter - pointer to the SATA adapter data structure.
+ *          pScb         - SCSI command block structure.
+ *
+ *  RETURNS:
+ *          MV_SCSI_COMMAND_STATUS_COMPLETED or MV_SCSI_COMMAND_STATUS_QUEUED.
+ *******************************************************************************/
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaStartStopCommand(IN MV_SATA_ADAPTER        *pSataAdapter,
+                                                              IN MV_SATA_SCSI_CMD_BLOCK *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_U8                   *cdb = pScb->ScsiCdb;
+    MV_U32                  sectors = 0;
+    MV_U8                   command;
+
+    if (pScb->ScsiCdbLength < 5)
+    {
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        goto error;
+    }
+    /* FIXME : Don't know how to handle Immed flag. */
+    if (cdb[1] & 0x1) {
+        ;
+    }
+    if (cdb[4] & 0x2)   /* LOEJ bit set not supported */
+
+    {
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        goto error;
+    }
+    if (((cdb[4] >> 6) & 0xf) != 0)
+    {
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        goto error;
+    }
+
+    if (cdb[4] & 0x1)   /* START UNIT command */
+    {
+        sectors = 1;
+        command = MV_ATA_COMMAND_READ_VERIFY_SECTORS;
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, 
+                 "Sending VERIFY command (emulate SCSI START UNIT): channel %d, Srb %p\n", pScb->bus, pScb);
+    }
+    else                /* STOP UNIT command */
+    {
+        command = MV_ATA_COMMAND_STANDBY_IMMEDIATE;
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, 
+                 "Sending STANDBY_IMMEDIATE command (emulate SCSI STOP UNIT): channel %d, Srb %p\n", pScb->bus, pScb);
+    }
+
+    memset(pCommandInfo, 0, sizeof(MV_QUEUE_COMMAND_INFO));
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+    pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = NULL;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.features = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = sectors;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = (MV_U8)(MV_BIT6);
+    pCommandInfo->commandParams.NoneUdmaCommand.command = command;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+    if (result == MV_QUEUE_COMMAND_RESULT_OK)
+        return MV_SCSI_COMMAND_STATUS_QUEUED;
+    else
+        checkQueueCommandResult(pScb, result);
+
+error:
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+}
+
+
+static inline MV_NON_UDMA_PROTOCOL mvScsiAtaPassThru_MapProto(MV_U8 byte)
+{
+    switch((byte & 0x1e) >> 1)
+    {
+        case 3:  /* Non-data */
+            return MV_NON_UDMA_PROTOCOL_NON_DATA;
+	    case 4:  /* PIO Data-in */
+        case 10: /* UDMA Data-in */
+	        return MV_NON_UDMA_PROTOCOL_PIO_DATA_IN;
+        case 5:  /* PIO Data-out */
+	    case 11: /* UDMA Data-Out */
+            return MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT;
+
+        case 0:  /* Hard Reset */
+        case 1:  /* SRST */
+        case 6:  /* DMA */
+        case 8:  /* Device Diagnostic */
+        case 9:  /* Device Reset */
+        case 7:  /* DMA Queued */
+        case 12: /* FPDMA */
+        case 15: /* Return Response Info */
+        default: /* Reserved */
+            break;
+    }
+    return MV_NON_UDMA_PROTOCOL_UNKNOWN;
+}
+
+/*
+ *      mvScsiAtaPassThru - Enqueue an ATA pass-thru command
+ *
+ *      INPUT:
+ *      pSataAdapter - pointer to the SATA adapter data structure.
+ *      pScb         - SCSI command block structure.
+ *
+ *      RETURNS:
+ *      MV_SCSI_COMMAND_STATUS_COMPLETED or MV_SCSI_COMMAND_STATUS_QUEUED.
+ */
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaPassThru(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                       IN MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_NON_UDMA_PROTOCOL    protocolType;
+    MV_U8                   *cdb = pScb->ScsiCdb;
+
+    memset(pCommandInfo, 0, sizeof(MV_QUEUE_COMMAND_INFO));
+
+    protocolType = mvScsiAtaPassThru_MapProto(cdb[1]);
+    if (protocolType == MV_NON_UDMA_PROTOCOL_UNKNOWN)
+    {
+        pScb->dataTransfered = 0;
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+	             SCSI_ADSENSE_INVALID_CDB, 0);
+        goto error;
+    }
+    /* PIO command can process a "multi_count" number of sectors. */
+    if (cdb[1] & 0xe0)
+    {
+        /*
+         * FIXME : How to check the passed "multi_count" value ?
+         *         Please remove the unused attribute when unneeded.
+         */
+        unsigned int multi_count __attribute__((unused)) = 1 << (cdb[1] >> 5);
+    }
+
+    if (cdb[0] == SCSI_OPCODE_ATA16)
+    {
+        /* 16-byte CDB can contain extend commands. */
+        if (cdb[1] & 0x01)
+        {
+            pCommandInfo->commandParams.NoneUdmaCommand.features =	MV_LE16_TO_CPU(*((MV_U16 *) &cdb[3]));
+            pCommandInfo->commandParams.NoneUdmaCommand.sectorCount =   MV_LE16_TO_CPU(*((MV_U16 *) &cdb[5]));
+            pCommandInfo->commandParams.NoneUdmaCommand.lbaLow =        MV_LE16_TO_CPU(*((MV_U16 *) &cdb[7]));
+            pCommandInfo->commandParams.NoneUdmaCommand.lbaMid =        MV_LE16_TO_CPU(*((MV_U16 *) &cdb[9]));
+            pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh =       MV_LE16_TO_CPU(*((MV_U16 *) &cdb[11]));
+            pCommandInfo->commandParams.NoneUdmaCommand.isEXT =         MV_TRUE;
+        }
+        else
+        {
+            pCommandInfo->commandParams.NoneUdmaCommand.features = cdb[4];
+            pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = cdb[6];
+            pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = cdb[8];
+            pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = cdb[10];
+            pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = cdb[12];
+            pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+        }
+        pCommandInfo->commandParams.NoneUdmaCommand.device = cdb[13];
+        pCommandInfo->commandParams.NoneUdmaCommand.command = cdb[14];
+    }
+    else
+    {
+        pCommandInfo->commandParams.NoneUdmaCommand.features = cdb[3];
+        pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = cdb[4];
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = cdb[5];
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = cdb[6];
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = cdb[7];
+        pCommandInfo->commandParams.NoneUdmaCommand.device = cdb[8];
+        pCommandInfo->commandParams.NoneUdmaCommand.command = cdb[9];
+        pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    }
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType = protocolType;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = (MV_U16_PTR)pScb->pDataBuffer;
+    /* count is in words (double byte), so we devide by 2 */
+    pCommandInfo->commandParams.NoneUdmaCommand.count = pScb->dataBufferLength >> 1;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+    if (result == MV_QUEUE_COMMAND_RESULT_OK)
+        return MV_SCSI_COMMAND_STATUS_QUEUED;
+    else
+        checkQueueCommandResult(pScb, result);
+
+error:
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+}
+
+
+/*******************************************************************************
+* mvScsiAtaGetReadCapacityData - Get the SCSI-3 Read Capacity (10h/16h) data
+*
+* DESCRIPTION: This function fills the data buffer with Scsi Read Capacity 10 or
+*       Read Capacity 16 data according to the disk size as it is reported in
+*       the ATA Identify data.
+*
+* INPUT:
+*   pSataAdapter    - pointer to the SATA adapter data structure.
+*   pScb->bus    - the index of the specific SATA channel.
+*
+* OUTPUT:
+* RETURN:
+*   MV_TRUE on success, MV_FALSE on failure.
+*
+* COMMENTS:
+*   No sanity check is done for the parameters.
+*
+*******************************************************************************/
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetReadCapacityData(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                                 IN    MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_U32  lastAddressableLBA;
+    MV_U8   *buff;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+    if ((pScb->ScsiCdb[8] & MV_BIT1) == 0)
+    {
+        if (pScb->ScsiCdb[2] || pScb->ScsiCdb[3] ||pScb->ScsiCdb[4] ||
+            pScb->ScsiCdb[5])
+        {
+
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Inquiry completed with error: PMI = 0, LBA != 0\n",
+                     pSataAdapter->adapterId, pScb->bus);
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                         SCSI_ADSENSE_INVALID_CDB, 0);
+            pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+            pScb->dataTransfered = 0;
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+            reportScbCompletion(pSataAdapter, pScb);
+#endif
+            pScb->completionCallBack(pSataAdapter, pScb);
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+    }
+    if((pDriveData->identifyInfo.ATADiskSize >> 32) & 0xFFFFFFFF)
+    {
+	    lastAddressableLBA = 0xFFFFFFFF;
+    }
+    else
+    {
+	    lastAddressableLBA = pDriveData->identifyInfo.ATADiskSize - 1;
+    }
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "MVSATA: last Addressable sector = 0x%x "
+             " (sec size=%d bytes)\n", lastAddressableLBA, ATA_SECTOR_SIZE);
+
+    /* The disk size as indicated by the ATA spec is the total addressable
+     * secotrs on the drive ; while the SCSI translation of the command
+     * should be the last addressable sector.
+     */
+    buff = pScb->pDataBuffer;
+    memset(buff, 0, pScb->dataBufferLength);
+    buff[0] = (MV_U8)(lastAddressableLBA >> 24);
+    buff[1] = (MV_U8)((lastAddressableLBA >> 16) & 0xff);
+    buff[2] = (MV_U8)((lastAddressableLBA >> 8) & 0xff);
+    buff[3] = (MV_U8)(lastAddressableLBA & 0xff);
+    buff[4] = 0;
+    buff[5] = 0;
+    buff[6] = (MV_U8)((ATA_SECTOR_SIZE >> 8) & 0xff);           /* 512 byte sectors */
+    buff[7] = (MV_U8)(ATA_SECTOR_SIZE & 0xff);
+    pScb->dataTransfered = 8;
+    pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+    pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+    pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+}
+
+/*******************************************************************************
+* mvScsiAtaGetReadCapacity16Data - Get the SCSI-3 Read Capacity (16h) data
+*
+* DESCRIPTION: This function fills the data buffer with Scsi Read Capacity 16
+* data according to the disk size as it is reported in
+*       the ATA Identify data.
+*
+* INPUT:
+*   pSataAdapter    - pointer to the SATA adapter data structure.
+*   pScb->bus    - the index of the specific SATA channel.
+*
+* OUTPUT:
+* RETURN:
+*   MV_TRUE on success, MV_FALSE on failure.
+*
+* COMMENTS:
+*   No sanity check is done for the parameters.
+*
+*******************************************************************************/
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetReadCapacity16Data(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                                   IN    MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_U64  lastAddressableLBA;
+    MV_U8   *buff;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+    if ((pScb->ScsiCdb[14] & MV_BIT1) == 0)
+    {
+        if (pScb->ScsiCdb[2] || pScb->ScsiCdb[3] ||pScb->ScsiCdb[4] ||
+            pScb->ScsiCdb[5] || pScb->ScsiCdb[6] ||pScb->ScsiCdb[7] ||
+	    pScb->ScsiCdb[8] || pScb->ScsiCdb[9])
+        {
+
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Read Capacity completed with error: PMI = 0, LBA != 0\n",
+                     pSataAdapter->adapterId, pScb->bus);
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                         SCSI_ADSENSE_INVALID_CDB, 0);
+            pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+            pScb->dataTransfered = 0;
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+            reportScbCompletion(pSataAdapter, pScb);
+#endif
+            pScb->completionCallBack(pSataAdapter, pScb);
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+    }
+
+    lastAddressableLBA = pDriveData->identifyInfo.ATADiskSize - 1;
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "MVSATA: last Addressable sector = 0x%x "
+             " (sec size=%d bytes)\n", lastAddressableLBA, ATA_SECTOR_SIZE);
+
+    /* The disk size as indicated by the ATA spec is the total addressable
+     * secotrs on the drive ; while the SCSI translation of the command
+     * should be the last addressable sector.
+     */
+    buff = pScb->pDataBuffer;
+    memset(buff, 0, pScb->dataBufferLength);
+    buff[0] = (MV_U8)((lastAddressableLBA >> 56) & 0xff);
+    buff[1] = (MV_U8)((lastAddressableLBA >> 48) & 0xff);
+    buff[2] = (MV_U8)((lastAddressableLBA >> 40) & 0xff);
+    buff[3] = (MV_U8)((lastAddressableLBA >> 32) & 0xff);
+    buff[4] = (MV_U8)((lastAddressableLBA >> 24) & 0xff);
+    buff[5] = (MV_U8)((lastAddressableLBA >> 16) & 0xff);
+    buff[6] = (MV_U8)((lastAddressableLBA >> 8) & 0xff);
+    buff[7] = (MV_U8)(lastAddressableLBA & 0xff);
+    buff[8] = 0;
+    buff[9] = 0;
+    buff[10] = (MV_U8)((ATA_SECTOR_SIZE >> 8) & 0xff);           /* 512 byte sectors */
+    buff[11] = (MV_U8)(ATA_SECTOR_SIZE & 0xff);
+    pScb->dataTransfered = 8;
+    pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+    pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+    pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+}
+
+
+/*******************************************************************************
+* mvScsiAtaReportLuns - handle the SCSI-3 Report LUNS
+*
+* DESCRIPTION: Report 1 LUN
+*
+* INPUT:
+*   pSataAdapter    - pointer to the SATA adapter data structure.
+*   pScb->bus    - the index of the specific SATA channel.
+*
+* OUTPUT:
+* RETURN:
+*   MV_TRUE on success, MV_FALSE on failure.
+*
+* COMMENTS:
+*   No sanity check is done for the parameters.
+*
+*******************************************************************************/
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaReportLuns(IN MV_SATA_ADAPTER*    pSataAdapter,
+							IN    MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+	MV_U8   *buff;
+
+
+    buff = pScb->pDataBuffer;
+    memset(buff, 0, pScb->dataBufferLength);
+    buff[3] = 8; /* 1 lun*/
+    pScb->dataTransfered = 16;
+    pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+    pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+    pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+}
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSendVerifyCommand(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                               IN MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_U8                   *cmd = pScb->ScsiCdb;
+    MV_U64                   LbaAddress;
+    MV_U32                  sectors;
+    MV_U16                  commands;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+    MV_SAL_ADAPTER_EXTENSION *pAdapterExt = pScb->pSalAdapterExtension;
+
+    if (cmd[0] == SCSI_OPCODE_VERIFY6)
+    {
+	    LbaAddress =
+		    ( (unsigned)  cmd[3]) |
+		    (((unsigned)  cmd[2]) << 8) |
+		    ((((unsigned) cmd[1]) & 0x1f) << 16);
+	    sectors = (unsigned) cmd[4];
+    }
+    else if (cmd[0] == SCSI_OPCODE_VERIFY10)
+    {
+	    LbaAddress =
+		    (((unsigned) cmd[5]) << 0) |
+		    (((unsigned) cmd[4]) << 8) |
+		    (((unsigned) cmd[3]) << 16) |
+		    (((unsigned) cmd[2]) << 24);
+	    
+	    
+	    sectors = ((unsigned) cmd[8]) |
+		    (((unsigned) cmd[7]) << 8);
+    }
+    else
+    {
+	    LbaAddress =
+		    (((MV_U64) cmd[9]) << 0) |
+		    (((MV_U64) cmd[8]) << 8) |
+		    (((MV_U64) cmd[7]) << 16) |
+		    (((MV_U64) cmd[6]) << 24) |
+		    (((MV_U64) cmd[5]) << 32) |
+		    (((MV_U64) cmd[4]) << 40) |
+		    (((MV_U64) cmd[3]) << 48) |
+		    (((MV_U64) cmd[2]) << 56);
+
+
+	    sectors = 
+		    ((unsigned) cmd[13]) |
+		    (((unsigned) cmd[12]) << 8) |
+		    (((unsigned) cmd[11]) << 16) |
+		    (((unsigned) cmd[10]) << 24);
+    }
+
+    if (sectors == 0)
+    {
+        if ((cmd[0] == SCSI_OPCODE_VERIFY10) || (cmd[0] == SCSI_OPCODE_VERIFY16))
+        {
+            if (checkLBAOutOfRange(pSataAdapter, pScb,
+                                   pDriveData->identifyInfo.ATADiskSize,
+                                   LbaAddress, 0) == MV_TRUE)
+            {
+                return MV_SCSI_COMMAND_STATUS_COMPLETED;
+            }
+            pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+            pScb->senseDataLength = 0;
+            pScb->dataTransfered = 0;
+#ifdef MV_LOGGER
+            reportScbCompletion(pSataAdapter, pScb);
+#endif
+            pScb->completionCallBack(pSataAdapter, pScb);
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+        else
+        {
+            /* If VERIFY6 to 48bit device, then 256 sectors is OK ; otherwise
+            the CORE driver must get sector count of 0 in order to understand that
+            256 sectors must be transferred
+            */
+
+            if (pDriveData->identifyInfo.LBA48Supported == MV_TRUE)
+            {
+                sectors = 256;
+            }
+            else
+            {
+                sectors = 0;
+            }
+        }
+        if (checkLBAOutOfRange(pSataAdapter, pScb,
+                               pDriveData->identifyInfo.ATADiskSize,
+                               LbaAddress, 256) == MV_TRUE)
+        {
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+    }
+    else
+    {
+        if (checkLBAOutOfRange(pSataAdapter, pScb,
+                               pDriveData->identifyInfo.ATADiskSize,
+                               LbaAddress, sectors) == MV_TRUE)
+        {
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+    }
+
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pScb->LowLbaAddress = (MV_U32)(LbaAddress & 0xFFFFFFFF);
+//    pScb->highLbaAddress = (MV_U32)(LbaAddress >> 32);
+
+    if (pDriveData->identifyInfo.LBA48Supported == MV_TRUE)
+    {
+        pScb->splitCount = 1;
+        pScb->isExtended = MV_TRUE;
+        pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+        pCommandInfo->PMPort = pScb->target;
+        pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = NULL;
+        pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+        pCommandInfo->commandParams.NoneUdmaCommand.command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT;
+        pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+        pCommandInfo->commandParams.NoneUdmaCommand.count = 0;
+        pCommandInfo->commandParams.NoneUdmaCommand.features = 0;
+        pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_TRUE;
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = 
+	(MV_U16)(((LbaAddress & 0xff0000000000ULL) >> 40) | ((LbaAddress & 0xff0000) >> 16));
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = 
+        (MV_U16)(((LbaAddress & 0xff00000000ULL) >> 32) | ((LbaAddress & 0xff00) >> 8));
+        pCommandInfo->commandParams.NoneUdmaCommand.lbaLow =
+        (MV_U16)(((LbaAddress & 0xff000000) >> 24) | (LbaAddress & 0xff));
+        pCommandInfo->commandParams.NoneUdmaCommand.protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+        pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = sectors;
+        pCommandInfo->commandParams.NoneUdmaCommand.device = (MV_U8)(MV_BIT6);
+
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Sending EXT Verify command: channel %d, code %x lba %x(%x.%x.%x), sectors %d[%d] Srb %p\n",
+                 pScb->bus, cmd[0], LbaAddress,
+                 pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh,
+                 pCommandInfo->commandParams.NoneUdmaCommand.lbaMid,
+                 pCommandInfo->commandParams.NoneUdmaCommand.lbaLow,
+                 pCommandInfo->commandParams.NoneUdmaCommand.sectorCount,
+                 mvSataNumOfDmaCommands(pSataAdapter,pScb->bus), pScb);
+
+        result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+
+        if (result != MV_QUEUE_COMMAND_RESULT_OK)
+        {
+            checkQueueCommandResult(pScb, result);
+#ifdef MV_LOGGER
+            reportScbCompletion(pSataAdapter, pScb);
+#endif
+            pScb->completionCallBack(pSataAdapter, pScb);
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+        /* update stats*/
+        pAdapterExt->totalAccumulatedOutstanding[pScb->bus] +=
+        mvSataNumOfDmaCommands(pSataAdapter,pScb->bus);
+        pDriveData->stats.totalIOs++;
+        pDriveData->stats.totalSectorsTransferred += sectors;
+
+    }
+    else
+    {
+        /* The following only in case command is VERIFY 6 with 0 sector count */
+        if (sectors == 0)
+        {
+            commands = 1;
+        }
+        else
+        {
+            commands = (MV_U16)((((MV_U32)sectors + 0xff) & 0x1ff00) >> 8);
+        }
+
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "split Verify to %d commands: channel %d, lba %x, sectors %d\n",
+                 commands,pScb->bus, LbaAddress, sectors);
+
+        pScb->splitCount = commands;
+        pScb->sequenceNumber = 0;
+        pScb->isExtended = MV_FALSE;
+        mvScsiAtaSendSplittedVerifyCommand(pScb);
+    }
+    return MV_SCSI_COMMAND_STATUS_QUEUED;
+}
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSeek(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                  IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_U32 lbaAddress;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+    lbaAddress = (((MV_U32) pScb->ScsiCdb[5]) << 0) |
+                 (((MV_U32) pScb->ScsiCdb[4]) << 8) |
+                 (((MV_U32) pScb->ScsiCdb[3]) << 16) |
+                 (((MV_U32) pScb->ScsiCdb[2]) << 24);
+    if (checkLBAOutOfRange(pSataAdapter, pScb,
+                           pDriveData->identifyInfo.ATADiskSize,
+                           lbaAddress, 0) == MV_TRUE)
+    {
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+    pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+    pScb->dataTransfered = 0;
+    pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+
+}
+
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaReassignBlocks(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                            IN MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    setSenseData(pScb, SCSI_SENSE_HARDWARE_ERROR, 0x32, 0);
+    pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+    pScb->dataTransfered = 0;
+    pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_ATA_FAILED;
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_TRUE;
+
+}
+
+
+#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG
+static MV_SCSI_COMMAND_STATUS_TYPE mvScsiAtaWriteLong(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                      IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_U32                  LBA;
+    MV_U16                  eccBytes;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+    MV_SAL_ADAPTER_EXTENSION *pAdapterExt = pScb->pSalAdapterExtension;
+
+    memset(pCommandInfo, 0, sizeof(MV_QUEUE_COMMAND_INFO));
+
+
+    LBA = (((MV_U32) pScb->ScsiCdb[5]) << 0) |
+          (((MV_U32) pScb->ScsiCdb[4]) << 8) |
+          (((MV_U32) pScb->ScsiCdb[3]) << 16) |
+          (((MV_U32) pScb->ScsiCdb[2]) << 24);
+
+    eccBytes = (MV_U16)pScb->ScsiCdb[8];
+
+    if ((pScb->ScsiCdb[7] != 2) || ((eccBytes != 4) && (eccBytes != 8)))
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    if (checkLBAOutOfRange(pSataAdapter, pScb,
+                           pDriveData->identifyInfo.ATADiskSize,
+                           LBA, 1) == MV_TRUE)
+    {
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    /*if (checkLBAOutOfRange(pSataAdapter, pScb, MV_BIT28 - 2,
+                        LBA, 1) == MV_TRUE)
+    {
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }*/
+    if (LBA & (MV_BIT31|MV_BIT30|MV_BIT29|MV_BIT28))
+    {
+
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Error LBA (0x%x) out of range.\n", LBA);
+
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                     SCSI_ADSENSE_ILLEGAL_BLOCK, 0);
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_TRUE;
+    }
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = (MV_U16_PTR)pScb->pDataBuffer;
+    pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 256+4;
+    pCommandInfo->commandParams.NoneUdmaCommand.features = eccBytes;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = (MV_U16)((LBA & 0xff0000) >> 16);
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = (MV_U16)((LBA & 0xff00) >> 8) ;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = (MV_U16)LBA & 0xff;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType = MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT;
+    pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = 1;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = MV_BIT6 | (MV_U16)((LBA & 0xf000000) >> 24) ;
+    pScb->isExtended = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.command = 0x32;
+
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Sending WRITE LONG command : channel %d, code %x pScb %p\n",
+             pScb->bus, pScb->ScsiCdb[0], pScb);
+
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+        /* shoudl complete the Scsi request here*/
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    /* update stats*/
+    pAdapterExt->totalAccumulatedOutstanding[pScb->bus] += mvSataNumOfDmaCommands(pSataAdapter,pScb->bus);
+    pDriveData->stats.totalIOs++;
+
+    return MV_SCSI_COMMAND_STATUS_QUEUED;
+}
+static MV_SCSI_COMMAND_STATUS_TYPE mvScsiAtaReadLong(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                     IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_U32                  LBA;
+    MV_U16                  eccBytes;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+    MV_SAL_ADAPTER_EXTENSION *pAdapterExt = pScb->pSalAdapterExtension;
+
+    memset(pCommandInfo, 0, sizeof(MV_QUEUE_COMMAND_INFO));
+
+
+    LBA = (((MV_U32) pScb->ScsiCdb[5]) << 0) |
+          (((MV_U32) pScb->ScsiCdb[4]) << 8) |
+          (((MV_U32) pScb->ScsiCdb[3]) << 16) |
+          (((MV_U32) pScb->ScsiCdb[2]) << 24);
+
+    eccBytes = (MV_U16)pScb->ScsiCdb[8];
+
+    if ((pScb->ScsiCdb[7] != 2) || ((eccBytes != 4) && (eccBytes != 8)))
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    if (checkLBAOutOfRange(pSataAdapter, pScb,
+                           pDriveData->identifyInfo.ATADiskSize,
+                           LBA, 1) == MV_TRUE)
+    {
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    /*if (checkLBAOutOfRange(pSataAdapter, pScb, MV_BIT28 - 2,
+                        LBA, 1) == MV_TRUE)
+    {
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }*/
+    if (LBA & (MV_BIT31|MV_BIT30|MV_BIT29|MV_BIT28))
+    {
+
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Error LBA (0x%x) out of range.\n", LBA);
+
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                     SCSI_ADSENSE_ILLEGAL_BLOCK, 0);
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_TRUE;
+    }
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = (MV_U16_PTR)pScb->pDataBuffer;
+    pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 256+4;
+    pCommandInfo->commandParams.NoneUdmaCommand.features = eccBytes;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = (MV_U16)((LBA & 0xff0000) >> 16);
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = (MV_U16)((LBA & 0xff00) >> 8) ;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = (MV_U16)LBA & 0xff;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType = MV_NON_UDMA_PROTOCOL_PIO_DATA_IN;
+    pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = 1;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = MV_BIT6 | (MV_U16)((LBA & 0xf000000) >> 24) ;
+    pScb->isExtended = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.command = 0x22;
+
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Sending READ LONG command : channel %d, code %x pScb %p\n",
+             pScb->bus, pScb->ScsiCdb[0], pScb);
+
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+        /* shoudl complete the Scsi request here*/
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    /* update stats*/
+    pAdapterExt->totalAccumulatedOutstanding[pScb->bus] += mvSataNumOfDmaCommands(pSataAdapter,pScb->bus);
+    pDriveData->stats.totalIOs++;
+
+    return MV_SCSI_COMMAND_STATUS_QUEUED;
+}
+#endif
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaSendSyncCacheCommand(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                                      IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_U64                  LBA;
+    MV_U32                  sectors;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+    MV_SAL_ADAPTER_EXTENSION *pAdapterExt = pScb->pSalAdapterExtension;
+
+    /* Check if IMMED bit is set, if so then return ILLEGAL REQUEST */
+    if (pScb->ScsiCdb[1] & MV_BIT1)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Synchronise cache completed with error:"
+                 " IMMED is set\n", pSataAdapter->adapterId,
+                 pScb->bus);
+
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB,
+                     0);
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    memset(pCommandInfo, 0, sizeof(MV_QUEUE_COMMAND_INFO));
+
+    if(pScb->ScsiCdb[0] == SCSI_OPCODE_SYNCHRONIZE_CACHE10)
+    {
+	    LBA = (((MV_U64) pScb->ScsiCdb[5]) << 0) |
+		    (((MV_U64) pScb->ScsiCdb[4]) << 8) |
+		    (((MV_U64) pScb->ScsiCdb[3]) << 16) |
+		    (((MV_U64) pScb->ScsiCdb[2]) << 24);
+	    
+	    sectors = ((MV_U32) pScb->ScsiCdb[8]) |
+		    (((MV_U32) pScb->ScsiCdb[7]) << 8);
+    }
+    else
+    {
+	    LBA = (((MV_U64) pScb->ScsiCdb[9]) << 0) |
+		    (((MV_U64) pScb->ScsiCdb[8]) << 8) |
+		    (((MV_U64) pScb->ScsiCdb[7]) << 16) |
+		    (((MV_U64) pScb->ScsiCdb[6]) << 24) |
+		    (((MV_U64) pScb->ScsiCdb[5]) << 32) |
+		    (((MV_U64) pScb->ScsiCdb[4]) << 40) |
+		    (((MV_U64) pScb->ScsiCdb[3]) << 48) |
+		    (((MV_U64) pScb->ScsiCdb[2]) << 56);
+	    
+	    sectors = ((MV_U32) pScb->ScsiCdb[13]) |
+		    (((MV_U32) pScb->ScsiCdb[12]) << 8) |
+		    (((MV_U32) pScb->ScsiCdb[11]) << 16) |
+		    (((MV_U32) pScb->ScsiCdb[10]) << 24);
+    }
+    if (checkLBAOutOfRange(pSataAdapter, pScb,
+                           pDriveData->identifyInfo.ATADiskSize,LBA, sectors)
+        == MV_TRUE)
+    {
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = NULL;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.features = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType =
+    MV_NON_UDMA_PROTOCOL_NON_DATA;
+    pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = (MV_U8)(MV_BIT6);
+
+    if (pDriveData->identifyInfo.LBA48Supported == MV_TRUE)
+    {
+        pScb->isExtended = MV_TRUE;
+        pCommandInfo->commandParams.NoneUdmaCommand.command = MV_ATA_COMMAND_FLUSH_CACHE_EXT;
+        pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_TRUE;
+    }
+    else
+    {
+        pScb->isExtended = MV_FALSE;
+        pCommandInfo->commandParams.NoneUdmaCommand.command = MV_ATA_COMMAND_FLUSH_CACHE;
+        pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+
+    }
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Sending Flush Cache command : channel %d, code %x (extended -->"
+             " %s) pScb %p\n", pScb->bus, pScb->ScsiCdb[0],
+             (pScb->isExtended == MV_TRUE) ? "Yes":"No", pScb);
+
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+        /* shoudl complete the Scsi request here*/
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    /* update stats*/
+    pAdapterExt->totalAccumulatedOutstanding[pScb->bus] += mvSataNumOfDmaCommands(pSataAdapter,pScb->bus);
+    pDriveData->stats.totalIOs++;
+
+    return MV_SCSI_COMMAND_STATUS_QUEUED;
+}
+
+/*******************************************************************************
+* mvScsiAtaGetRequestSenseData - Get the SCSI-3 Request Sense(03h) data
+*
+* DESCRIPTION: This function fills the sense buffer with a sense key of NO SENSE
+*       and an additional sense code of NO ADDITIONAL SENSE INFORMATION.
+*
+* INPUT:
+*   pSataAdapter    - pointer to the SATA adapter data structure.
+*   pScb->bus    - the index of the specific SATA channel.
+*   Cdb             - specifies the SCSI-3 command descriptor block.
+*
+* OUTPUT:
+*   pScsiStatus     - pointer to the Scsi status to be returned.
+*   pSenseBuffer    - pointer to the Scsi sense buffer.
+*   senseBufferLength   - the size in bytes of the sense buffer.
+*   pDataTransfered - the size in bytes of the data transfered into the data
+*                     buffer(alwasy zero for this command).
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE on failure.
+*
+* COMMENTS:
+*   No sanity check is done for the parameters.
+*
+*******************************************************************************/
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetRequestSenseData(IN MV_SATA_ADAPTER*    pSataAdapter,
+                                                                 IN MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_SCSI_SENSE_DATA SenseData;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+    memset(pScb->pDataBuffer, 0, pScb->dataBufferLength);
+
+    memset(&SenseData, 0, sizeof(MV_SCSI_SENSE_DATA));
+//    SenseData.Valid = 0;
+    SenseData.ResponseCode = MV_SCSI_RESPONSE_CODE;
+    SenseData.SenseKey = SCSI_SENSE_NO_SENSE;
+    SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+    SenseData.AdditionalSenseLength = sizeof(MV_SCSI_SENSE_DATA) - 8;
+
+    pScb->senseDataLength = 0;
+    if (pDriveData->UAConditionPending == MV_TRUE)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Unit Attention condition is pending.\n");
+        SenseData.SenseKey = SCSI_SENSE_UNIT_ATTENTION;
+        if (pDriveData->UAEvents & MV_BIT0)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Report Bus Reset.\n");
+
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_BUS_RESET;
+            SenseData.AdditionalSenseCodeQualifier = 2;
+            pDriveData->UAEvents &= ~MV_BIT0;
+        }
+        else if (pDriveData->UAEvents & MV_BIT1)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Report Mode Parameters Changed.\n");
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_PARAMETERS_CHANGED;
+            SenseData.AdditionalSenseCodeQualifier = 1;
+            pDriveData->UAEvents &= ~MV_BIT1;
+        }
+
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+        if (pDriveData->UAEvents == 0)
+        {
+            pDriveData->UAConditionPending = MV_FALSE;
+        }
+    }
+    else
+    {
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+    }
+    if (pScb->dataBufferLength >= sizeof(MV_SCSI_SENSE_DATA))
+    {
+        pScb->dataTransfered = sizeof(MV_SCSI_SENSE_DATA);
+        memcpy(pScb->pDataBuffer, &SenseData, pScb->dataTransfered);
+        /*pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;*/
+        /*pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;*/
+    }
+    else
+    {
+        pScb->dataTransfered = pScb->dataBufferLength;
+        memcpy(pScb->pDataBuffer, &SenseData, pScb->dataTransfered);
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;/*TBD*/
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+    }
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_SCSI_COMMAND_STATUS_COMPLETED;
+}
+
+/*******************************************************************************
+* mvScsiAtaGetModeSenseData - Get the SCSI-3 Mode Sense data
+*
+* DESCRIPTION: This function issues ATA Identify command, in the command
+*       completion, the Mode Sense data will be filled according to the returned
+*       Identify Data.
+*
+* INPUT:
+*   pSataAdapter    - pointer to the SATA adapter data structure.
+*   pScb->bus    - the index of the specific SATA channel.
+*   Cdb             - specifies the SCSI-3 command descriptor block.
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE on failure.
+*
+* COMMENTS:
+*   No sanity check is done for the parameters.
+*
+*******************************************************************************/
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaGetModeSenseData(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                              IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+    memset(pCommandInfo, 0, sizeof(MV_QUEUE_COMMAND_INFO));
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = pDriveData->identifyBuffer;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 256;         /* 512 bytes */
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.command = MV_ATA_COMMAND_IDENTIFY;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+    pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType = MV_NON_UDMA_PROTOCOL_PIO_DATA_IN;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = (MV_U8)(MV_BIT6);
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Sending Identify command: channel %d, Srb %p\n",
+             pScb->bus, pScb);
+
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+        /* shoudl complete the Scsi request here*/
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    return MV_SCSI_COMMAND_STATUS_QUEUED;
+}
+static MV_BOOLEAN  mvScsiAtaGetModeSenseDataPhase2(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                   IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_U8   AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+    MV_U8   *cmd = pScb->ScsiCdb;
+    MV_U8   pageCode= cmd[2] & 0x3f;
+    MV_U8   pageControl = (MV_U8)((cmd[2] & 0xc0) >> 6);
+    MV_U8   modeSenseResult[MV_MAX_MODE_SENSE_RESULT_LENGTH];
+    MV_U32  offset;
+    MV_U32  pageLength;
+    MV_BOOLEAN  commandFailed = MV_FALSE;
+
+    memset(pScb->pDataBuffer, 0, pScb->dataBufferLength);
+    memset(modeSenseResult, 0, MV_MAX_MODE_SENSE_RESULT_LENGTH);
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Sense: cmd[2] 0x%xcode 0x%x control 0x%x "
+             "allocation length %d \n", pSataAdapter->adapterId, pScb->bus,
+             cmd[2], pageCode, pageControl, (MV_U32)cmd[4]);
+
+
+    if (pageControl == 0x3)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Sense: save control not supported\n.",
+                 pSataAdapter->adapterId, pScb->bus);
+        AdditionalSenseCode = 0x39; /*SAVING PARAMETERS NOT SUPPORTED */
+        commandFailed = MV_TRUE;
+    }
+    if (commandFailed != MV_TRUE)
+    {
+        memset(modeSenseResult, 0, MV_MAX_MODE_SENSE_RESULT_LENGTH);
+        /*1. Mode parameter header*/
+        /* Mode data length will be set later */
+        /* Medium Type 0: Default medium type */
+        /* Device-specific parameter 0:  write enabled, target */
+        /*      supports the DPO and FUA bits only in NCQ mode*/
+        if (pSataAdapter->sataChannel[pScb->bus]->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)
+        {
+            modeSenseResult[2] = MV_BIT4;
+        }
+
+        /* Block descriptor length 0: no block descriptors*/
+
+        /*2. Block descriptor(s): Empty list*/
+        /*3. Page(s)*/
+        offset = 4;
+
+        switch (pageCode)
+        {
+        case 0x3f:
+        case 0x8: /*Caching page */
+            pageLength = mvModeSenseCachingPage(pScb,
+                                                modeSenseResult + offset,
+                                                pageControl);
+
+            offset += pageLength;
+
+            if (pageCode == 0x8)
+            {
+                break;
+            }
+        case 0xa:
+            pageLength = mvModeSenseControlPage(pSataAdapter,pScb,
+                                                modeSenseResult + offset,
+                                                pageControl);
+
+            offset += pageLength;
+            break;
+        default:
+            AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB;
+            commandFailed = MV_TRUE;
+        }
+
+        /* set the DATA LENGTH of the Mode parameter list not including the number*/
+        /* of bytes of the DATA LENGTH itself ( 1 byte for Mode Selet(6)) */
+        modeSenseResult[0] = (MV_U8)(offset - 1);
+
+        if (pScb->dataBufferLength < offset)
+        {
+            memcpy(pScb->pDataBuffer, modeSenseResult, pScb->dataBufferLength);
+            pScb->dataTransfered = pScb->dataBufferLength;
+        }
+        else
+        {
+            memcpy(pScb->pDataBuffer, modeSenseResult, offset);
+            pScb->dataTransfered = offset;
+        }
+    }
+
+    if (commandFailed == MV_TRUE)
+    {
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST, AdditionalSenseCode, 0);
+
+        pScb->dataTransfered = 0;
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+    }
+    else
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+    }
+    return MV_TRUE;
+}
+static MV_SCSI_COMMAND_STATUS_TYPE  mvScsiAtaModeSelect(IN MV_SATA_ADAPTER    *pSataAdapter,
+                                                        IN  MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_U8 result;
+    MV_SCSI_COMMAND_STATUS_TYPE     commandStatus= MV_SCSI_COMMAND_STATUS_FAILED;
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " MODE SELECT RECEIVED: cmd:");
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %02x, %02x, %02x, %02x, %02x, %02x\n", pScb->ScsiCdb[0], pScb->ScsiCdb[1],
+                 pScb->ScsiCdb[2], pScb->ScsiCdb[3], pScb->ScsiCdb[4], pScb->ScsiCdb[5]);
+    }
+    result = modeSelect(pSataAdapter, pScb, &commandStatus);
+    if (result != 0x0)
+    {
+        if (result == 0x1)/*PARAMETER LIST LENGTH ERROR*/
+        {
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST, 0x1a, 0);
+
+        }
+        else if (result == 0x2)
+        {
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                         SCSI_ADSENSE_INVALID_CDB, 0);
+
+        }
+        else if (result == 0x3)
+        {
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                         SCSI_ADSENSE_INVALID_FIELD_IN_PARAMETER_LIST, 0);
+
+        }
+        else
+        {
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                         SCSI_ADSENSE_NO_SENSE, 0);
+
+        }
+
+        pScb->dataTransfered = 0;
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    return commandStatus;
+}
+
+static MV_U8
+modeSelect(IN MV_SATA_ADAPTER    *pSataAdapter,
+           IN  MV_SATA_SCSI_CMD_BLOCK  *pScb,
+           MV_SCSI_COMMAND_STATUS_TYPE *pCommandStatus)
+{
+    MV_U8   *cmd = pScb->ScsiCdb;
+    MV_VOID_PTR pBuffer = pScb->pDataBuffer;
+    MV_U32  length = pScb->dataBufferLength;
+    MV_U8   PF = (cmd[1] & MV_BIT4) >> 4;
+    MV_U8   SP = (cmd[1] & MV_BIT0);
+    MV_U8   *list = (MV_U8 *)pBuffer;
+    MV_U32  offset;
+    MV_U32  cachePageOffset = 0;
+
+    {
+        MV_U32 i;
+        for (i =0 ; i < length; i++)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %02x", list[i]);
+        }
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "\n");
+    }
+    if (PF == 0)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%d %d: Mode Select Error: PF not supported\n.",
+                 pSataAdapter->adapterId, pScb->bus);
+        return 0x2; /* Invalid field in CDB */
+    }
+    if (SP == 1)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%d %d: Mode Select Error: SP not supported\n.",
+                 pSataAdapter->adapterId, pScb->bus);
+        return 0x2; /* PARAMETER LIST LENGTH ERROR */
+    }
+    if (length == 0)
+    {
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        *pCommandStatus = MV_SCSI_COMMAND_STATUS_COMPLETED;
+        return 0;
+    }
+    if (length < 4)
+    {
+        return 0x1; /* PARAMETER LIST LENGTH ERROR */
+    }
+    if (list[0] || (list[1] != MV_SCSI_DIRECT_ACCESS_DEVICE) || list[2])
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in parameter "
+                 "list\n", pSataAdapter->adapterId, pScb->bus);
+        return 0x3; /* Invalid field in parameter list */
+    }
+    if (list[3])
+    {
+        if (list[3] != 8)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: wrong size for mode parameter"
+                     " block descriptor, BLOCK DESCRIPTOR LENGTH %d\n.",
+                     pSataAdapter->adapterId, pScb->bus, list[3]);
+            return 0x3; /* Invalid field in parameter list */
+        }
+        if (length < 12)
+        {
+            return 0x1; /* PARAMETER LIST LENGTH ERROR */
+        }
+        if (list[4] || list[5] || list[6] || list[7] || list[8] || list[9] ||
+            (list[10] != 0x2) || list[11])
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in parameter "
+                     "block descriptor list\n", pSataAdapter->adapterId,
+                     pScb->bus);
+            return 0x3; /* Invalid field in parameter list */
+        }
+    }
+    offset = 4 + list[3];/* skip the mode parameter block descriptor */
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select: PF 0x%x SP 0x%x parameter length %x "
+             "length %d(0x%x)\n offset %d", pSataAdapter->adapterId, pScb->bus,
+             PF, SP, (MV_U32)cmd[4], length, length,
+             offset);
+    if (length == offset)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select : no mode pages available\n",
+                 pSataAdapter->adapterId, pScb->bus);
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        *pCommandStatus = MV_SCSI_COMMAND_STATUS_COMPLETED;
+        return 0;
+    }
+
+    while ((offset + 2) < length)
+    {
+        switch (list[offset] & 0x3f)
+        {
+        case 0x8:
+            if (list[offset + 1] != 0x12)
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: bad length in caching mode "
+                         "page %d\n.",
+                         pSataAdapter->adapterId, pScb->bus, list[offset + 1]);
+                return 0x3; /* Invalid field in parameter list */
+            }
+            cachePageOffset = offset;
+            offset += list[offset + 1] + 2;
+            break;
+        case 0xa:
+            if ((list[offset] != 0xa) || (list[offset+1] != 0xa))
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in"
+                         " mode control page, list[%x] %x, list[%x] %x\n",
+                         pSataAdapter->adapterId, pScb->bus, offset,
+                         list[offset], offset + 1, list[offset+1]);
+                return 0x3;
+            }
+
+            if (list[offset + 3] != MV_BIT4)
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in"
+                         " mode control page, list[%x] %x\n",
+                         pSataAdapter->adapterId, pScb->bus, offset + 3,
+                         list[offset + 3]);
+                return 0x3;
+            }
+
+            if (list[offset + 2] || list[offset + 4] || list[offset + 5] ||
+                list[offset + 6] || list[offset + 7]||list[offset + 8] ||
+                list[offset + 9]|| list[offset + 10] || list[offset + 11])
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in"
+                         " mode control page, line %d\n",
+                         pSataAdapter->adapterId, pScb->bus, __LINE__);
+                return 0x3;
+            }
+            offset += list[offset + 1] + 2;
+            break;
+        default:
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in parameter "
+                     "list, mode page %d not supported, offset %d\n",
+                     pSataAdapter->adapterId, pScb->bus, list[offset],
+                     offset);
+            return 0x3; /* Invalid field in parameter list */
+        }
+    }
+
+    if (length != offset)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: bad length %d\n.",
+                 pSataAdapter->adapterId, pScb->bus, length);
+        return 0x1; /* PARAMETER LIST LENGTH ERROR */
+    }
+
+    if (cachePageOffset)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Mode Select: caching Page found, offset %d\n", cachePageOffset);
+        return mvParseModeCachingPage(pSataAdapter, pScb,list + cachePageOffset, pCommandStatus);
+    }
+    else
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Mode Select: No caching Page found\n");
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        *pCommandStatus = MV_SCSI_COMMAND_STATUS_COMPLETED;
+        return 0;
+    }
+}
+
+static MV_U8
+mvParseModeCachingPage(MV_SATA_ADAPTER *pSataAdapter,
+                       IN  MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                       MV_U8 *buffer,
+                       MV_SCSI_COMMAND_STATUS_TYPE *pCommandStatus)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_U8                   index = 0;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+
+    if ((buffer[index++] & 0xc0) || (buffer[index++] != 0x12) ||
+        ((buffer[index++] | MV_BIT2)!= MV_BIT2) || (buffer[index++]) ||
+        (buffer[index++] != 0xff) || (buffer[index++] != 0xff) ||
+        buffer[index++] || buffer[index++] || buffer[index++] ||
+        (buffer[index++] != 0x10) || buffer[index++] ||
+        (buffer[index++] != 0x10) || ((buffer[index++] | MV_BIT5) != MV_BIT5) ||
+        (buffer[index++] != 0x1) || (buffer[index++] != 0xff) ||
+        (buffer[index++] != 0xff) || buffer[index++] || buffer[index++]
+        || buffer[index++] || buffer[index++])
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in caching mode"
+                 " page, index %d\n", pSataAdapter->adapterId, pScb->bus,
+                 index);
+        return 0x3; /* Invalid field in parameter list */
+    }
+
+    pScb->splitCount = 2;
+    pScb->sequenceNumber = 1;
+    if (buffer[12] & MV_BIT5) /* Disable Look Ahead*/
+    {
+        if (pDriveData->identifyInfo.readAheadSupported == MV_FALSE)
+        {
+            pScb->splitCount--;
+        }
+        pScb->LowLbaAddress = 0;
+    }
+    else
+    {
+        if (pDriveData->identifyInfo.readAheadSupported == MV_FALSE)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in caching mode"
+                     " page, enable read ahead (feature not supported)\n",
+                     pSataAdapter->adapterId, pScb->bus);
+            return 0x3; /* Invalid field in parameter list */
+        }
+        pScb->LowLbaAddress = 1;
+    }
+
+    if (buffer[2] & MV_BIT2) /* enable write cache*/
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Parse Caching Page: enable Write Cache\n");
+        if (pDriveData->identifyInfo.writeCacheSupported == MV_FALSE)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d: Mode Select Error: invalid field in caching mode"
+                     " page, enable write cache (feature not supported)\n",
+                     pSataAdapter->adapterId, pScb->bus);
+            return 0x3; /* Invalid field in parameter list */
+        }
+        pCommandInfo->commandParams.NoneUdmaCommand.features = MV_ATA_SET_FEATURES_ENABLE_WCACHE;
+    }
+    else
+    {
+        if (pDriveData->identifyInfo.writeCacheSupported == MV_FALSE)
+        {
+            pScb->splitCount--;
+            if (pScb->splitCount == 1)
+            {
+                mvScsiAtaSendReadLookAhead(pSataAdapter, pScb);
+                *pCommandStatus = MV_SCSI_COMMAND_STATUS_QUEUED;
+                return 0;
+            }
+        }
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Parse Caching Page: disable Write Cache\n");
+        pCommandInfo->commandParams.NoneUdmaCommand.features = MV_ATA_SET_FEATURES_DISABLE_WCACHE;
+    }
+
+    if (pScb->splitCount == 0)
+    {
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+        pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        *pCommandStatus = MV_SCSI_COMMAND_STATUS_COMPLETED;
+        return 0;
+    }
+
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = NULL;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.command = MV_ATA_COMMAND_SET_FEATURES;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 0;
+
+    pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+    pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = (MV_U8)(MV_BIT6);
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Sending SET FEATURES command: features %d\n",
+             pCommandInfo->commandParams.NoneUdmaCommand.features);
+
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        *pCommandStatus = MV_SCSI_COMMAND_STATUS_COMPLETED;
+
+        return 0;
+    }
+    *pCommandStatus = MV_SCSI_COMMAND_STATUS_QUEUED;
+    return 0;
+}
+
+static MV_U32
+mvModeSenseCachingPage(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                       MV_U8 *buffer,MV_U8 pageControl)
+{
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+
+
+    buffer[0] = 0x8; /* caching page*/
+    buffer[1] = 0x12; /* length = 2 + 0x12*/
+    buffer[2] = 0;
+    if (pageControl == 2) /*default values*/
+    {
+        if (pDriveData->identifyInfo.writeCacheSupported == MV_TRUE)
+        {
+            buffer[2] = MV_BIT2;
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Cache Page: writeCacheEnabledByDefault\n");
+        }
+    }
+    else if (pageControl == 0)  /* current values*/
+    {
+        if ((pDriveData->identifyInfo.writeCacheSupported == MV_TRUE) &&
+            (pDriveData->identifyBuffer[85] & MV_BIT5))
+        {
+            buffer[2] = MV_BIT2;
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Cache Page: writeCacheEnabled\n");
+        }
+    }
+    else if (pageControl == 1)  /* changeable values*/
+    {
+        if (pDriveData->identifyInfo.writeCacheSupported == MV_TRUE)
+        {
+            buffer[2] = MV_BIT2;
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Cache Page: writeCacheSupported\n");
+        }
+    }
+
+    buffer[3] = 0;
+    if (pageControl != 1)
+    {
+        buffer[4] = 0xff;
+        buffer[5] = 0xff;
+        buffer[9] = 0x10;
+        buffer[11] = 0x10;
+    }
+    if (pageControl == 2) /*default values*/
+    {
+        if (pDriveData->identifyInfo.readAheadSupported == MV_FALSE)
+        {
+            buffer[12] = MV_BIT5;
+        }
+    }
+    else if (pageControl == 0)  /* current values*/
+    {
+        if ((pDriveData->identifyInfo.readAheadSupported == MV_TRUE) &&
+            (pDriveData->identifyBuffer[85] & MV_BIT6))
+        {
+            buffer[12] = 0;
+        }
+        else
+        {
+            buffer[12] = MV_BIT5;
+        }
+    }
+    else if (pageControl == 1)  /* changeable values*/
+    {
+        if (pDriveData->identifyInfo.readAheadSupported == MV_TRUE)
+        {
+            buffer[12] = MV_BIT5;
+        }
+    }
+    if (pageControl != 1)
+    {
+        buffer[13] = 0x01;
+        buffer[14] = 0xff;
+        buffer[15] = 0xff;
+    }
+
+    {
+        MV_U32 i;
+
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Cache Page: \n");
+        for (i = 0; i < 0x14; i++)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "[%d] %x\n",i, buffer[i]);
+        }
+    }
+    return 0x14;
+}
+
+static MV_U32
+mvModeSenseControlPage(MV_SATA_ADAPTER *pSataAdapter,
+                       MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                       MV_U8 *buffer, MV_U8 pageControl)
+{
+    buffer[0] = 0xA;    /* control page */
+    buffer[1] = 0xA;    /* length 2 + 0xa*/
+    if (pageControl != 1)
+    {
+        buffer[3] = MV_BIT4/*Unrestricted reordering allowed*/;
+    }
+
+    {
+        MV_U32 i;
+
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Control Page: \n");
+        for (i = 0; i < 0xc; i++)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "[%d] %x\n",i , buffer[i]);
+        }
+    }
+    return 0xc;
+}
+
+static MV_BOOLEAN
+SALCommandCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
+                       MV_U8 channelNum,
+                       MV_COMPLETION_TYPE comp_type,
+                       MV_VOID_PTR commandId,
+                       MV_U16 responseFlags,
+                       MV_U32 timeStamp,
+                       MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+    MV_SATA_SCSI_CMD_BLOCK  *pScb;
+    if (commandId == NULL)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_FATAL_ERROR, " commandId is NULL, can't hanlde this !!!,adapterId=%d,"
+                 " channel=%d \n", pSataAdapter->adapterId, channelNum);
+        return MV_FALSE;
+    }
+
+    pScb = commandId;
+    switch (comp_type)
+    {
+    case MV_COMPLETION_TYPE_NORMAL:
+        /* finish */
+#ifdef  MV_SUPPORT_ATAPI
+        if(pScb->commandType == MV_QUEUED_COMMAND_TYPE_PACKET)
+        {
+            if ((registerStruct->statusRegister & MV_ATA_ERROR_STATUS) ||
+               (registerStruct->statusRegister & MV_ATA_DEVICE_FAULT_STATUS))  
+            {
+                pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "packet command completed ",
+                        "with check condition\n", pScb);
+            }
+            else
+            {
+                pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+            }
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+            pScb->dataTransfered = timeStamp;
+            break;
+        }
+#endif
+        /* If splited VERIFY command, then SRB completion will be on the last fragment */
+        if ((((pScb->ScsiCdb[0] == SCSI_OPCODE_VERIFY6) ||
+              (pScb->ScsiCdb[0] == SCSI_OPCODE_VERIFY10) ||
+              (pScb->ScsiCdb[0] == SCSI_OPCODE_VERIFY16) ||
+              (pScb->ScsiCdb[0] == SCSI_OPCODE_MODE_SELECT6)))
+            &&  (pScb->splitCount > pScb->sequenceNumber))
+        {
+            /* add the command to the list for post interrupt service*/
+            pScb->pNext = pScb->pSalAdapterExtension->pHead;
+            pScb->pSalAdapterExtension->pHead = pScb;
+            return MV_TRUE;
+        }
+        if (pScb->ScsiCdb[0] == SCSI_OPCODE_MODE_SENSE6)
+        {
+            mvScsiAtaGetModeSenseDataPhase2(pSataAdapter, pScb);
+        }
+        else
+        {
+            pScb->ScsiStatus = MV_SCSI_STATUS_GOOD;
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_SUCCESS;
+        }
+        /*
+         * ATA passthru command have to return some consistent sense
+         * data when the caller ask for it.
+         */
+        if (((pScb->ScsiCdb[0] == SCSI_OPCODE_ATA12) ||
+             (pScb->ScsiCdb[0] == SCSI_OPCODE_ATA16)) &&
+             (pScb->ScsiCdb[2] & 0x20))
+        {
+            setPassThruSense(pScb, registerStruct);
+        }
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "command completed. pScb %p\n", pScb);
+
+        break;
+    case MV_COMPLETION_TYPE_ABORT:
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "Error: command Aborted. Cdb: %02x %02x %02x %02x %02x "
+                 "%02x %02x %02x %02x %02x\n", pScb->ScsiCdb[0],
+                 pScb->ScsiCdb[1], pScb->ScsiCdb[2], pScb->ScsiCdb[3],
+                 pScb->ScsiCdb[4], pScb->ScsiCdb[5], pScb->ScsiCdb[6],
+                 pScb->ScsiCdb[7], pScb->ScsiCdb[8], pScb->ScsiCdb[9]);
+
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_ABORTED;
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+        mvCommandCompletionErrorHandler(pScb->pIalAdapterExtension, channelNum);
+        break;
+    case MV_COMPLETION_TYPE_ERROR:
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_ATA_FAILED;
+
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "COMPLETION ERROR , adapter =%d, channel=%d, flags=%x\n",
+                 pSataAdapter->adapterId, channelNum, responseFlags);
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " Failed command Cdb: %02x %02x %02x %02x %02x "
+                 "%02x %02x %02x %02x %02x\n", pScb->ScsiCdb[0],
+                 pScb->ScsiCdb[1], pScb->ScsiCdb[2], pScb->ScsiCdb[3],
+                 pScb->ScsiCdb[4], pScb->ScsiCdb[5], pScb->ScsiCdb[6],
+                 pScb->ScsiCdb[7], pScb->ScsiCdb[8], pScb->ScsiCdb[9]);
+        /* here the  eDMA will be stopped, so we have to flush  */
+        /* the pending commands                                 */
+
+        if (pScb->commandType == MV_QUEUED_COMMAND_TYPE_UDMA)
+        {
+            handleUdmaError(pScb, responseFlags, registerStruct);
+#ifdef MV_LOGGER
+            memcpy(&pScb->ATAregStruct, registerStruct,
+                   sizeof(pScb->ATAregStruct));
+#endif
+        }
+        else
+        {
+            handleNoneUdmaError(pScb, registerStruct);
+#ifdef MV_LOGGER
+            memcpy(&pScb->ATAregStruct, registerStruct,
+                   sizeof(pScb->ATAregStruct));
+#endif
+        }
+        mvCommandCompletionErrorHandler(pScb->pIalAdapterExtension, channelNum);
+        break;
+    default:
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_FATAL_ERROR, " Unknown completion type (%d)\n", comp_type);
+        return MV_FALSE;
+    }
+#ifdef MV_LOGGER
+    reportScbCompletion(pSataAdapter, pScb);
+#endif
+    if (!virt_addr_valid(pScb->completionCallBack))
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "IAL ERROR: invalid completionCallBack=0x%X\n",
+                 pScb->completionCallBack);
+        return MV_FALSE;
+    }
+
+    pScb->completionCallBack(pSataAdapter, pScb);
+    return MV_TRUE;
+}
+MV_VOID
+handleNoneUdmaError(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                    MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+    MV_U8 errorReg = registerStruct->errorRegister;
+    MV_SCSI_SENSE_DATA SenseData;
+
+    memset(&SenseData, 0, sizeof(MV_SCSI_SENSE_DATA));
+
+    pScb->dataBufferLength = 0;
+
+    /*if (pSrb->SenseInfoBufferLength < 13)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "IAL ERROR: invalid Sense Info buffer len (%d)\n",
+                 Srb->SenseInfoBufferLength);
+        Srb->SrbStatus = SRB_STATUS_ERROR;
+        return;
+    }*/
+    memset(pScb->pSenseBuffer, 0, pScb->senseBufferLength);
+    /*pScb->ScsiCommandCompletion = ;*/
+    pScb->ScsiStatus =  MV_SCSI_STATUS_CHECK_CONDITION;
+
+    SenseData.ResponseCode = MV_SCSI_RESPONSE_CODE;
+//    SenseData.Valid = 0;
+
+    SenseData.AdditionalSenseLength = 12;
+    SenseData.InformationDesc.type = 0;
+    SenseData.InformationDesc.AdditionalLength = 0xA;
+    SenseData.InformationDesc.valid = 1 << 7;
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " ATA Drive Registers:\n");
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","Error", registerStruct->errorRegister);
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","SectorCount", registerStruct->sectorCountRegister);
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA Low", registerStruct->lbaLowRegister);
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA Mid", registerStruct->lbaMidRegister);
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA High", registerStruct->lbaHighRegister);
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","Device", registerStruct->deviceRegister);
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","Status", registerStruct->statusRegister);
+
+    /* If the command is synchronize cache */
+    if ((pScb->ScsiCdb[0] == SCSI_OPCODE_SYNCHRONIZE_CACHE10) || 
+	(pScb->ScsiCdb[0] == SCSI_OPCODE_SYNCHRONIZE_CACHE16))
+    {
+        if (!(registerStruct->errorRegister & ABRT_ERR))
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " received error completion on flush cache command"
+                     " but ABORT bit in error register is not set\n");
+        }
+        SenseData.SenseKey = SCSI_SENSE_MEDIUM_ERROR;
+	_fillSenseInformation(pScb, &SenseData, registerStruct);
+    }
+    else if ((pScb->ScsiCdb[0] == SCSI_OPCODE_VERIFY10) ||
+	     (pScb->ScsiCdb[0] == SCSI_OPCODE_VERIFY6) ||
+	     (pScb->ScsiCdb[0] == SCSI_OPCODE_VERIFY16))
+    {
+        if (errorReg & (NM_ERR | MC_ERR | MCR_ERR))
+        {
+            SenseData.SenseKey = SCSI_SENSE_UNIT_ATTENTION;
+        }
+        else if (errorReg & UNC_ERR)
+        {
+#if 0
+            MV_U32  LowLbaAddress = pScb->LowLbaAddress;
+#endif
+            SenseData.SenseKey = SCSI_SENSE_MEDIUM_ERROR;
+#if 0
+            /* Since high 8 bit address are taken immediatly from LowLbaAddress and
+            not from the completion info ; the following code is relevant for both
+            48bit and 28bit LBA addressing*/
+            SenseData.Information[0] = (MV_U8)((LowLbaAddress & 0xff000000) >> 24);
+            SenseData.Information[1] = (MV_U8)(registerStruct->lbaHighRegister & 0xff);
+            SenseData.Information[2] = (MV_U8)(registerStruct->lbaMidRegister & 0xff);
+            SenseData.Information[3] = (MV_U8)(registerStruct->lbaLowRegister & 0xff);
+#endif
+	    _fillSenseInformation(pScb, &SenseData, registerStruct);
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " Read Verify failed on UNC at sector %02x %02x %02x %02x %02x %02x\n",
+                     SenseData.InformationDesc.information[2],
+                     SenseData.InformationDesc.information[3],
+                     SenseData.InformationDesc.information[4],
+                     SenseData.InformationDesc.information[5],
+                     SenseData.InformationDesc.information[6],
+                     SenseData.InformationDesc.information[7]
+		     );
+        }
+        /*else if (errorReg & IDNF_ERR)
+        {
+            SenseData.SenseKey = SCSI_SENSE_VOL_OVERFLOW;
+        }*/
+        else if ((errorReg & ABRT_ERR) || (errorReg & IDNF_ERR))
+        {
+            SenseData.SenseKey = SCSI_SENSE_ABORTED_COMMAND;
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+        }
+        else
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " in mapping ATA error to SCSI error\n");
+            SenseData.SenseKey = SCSI_SENSE_NO_SENSE;
+        }
+    }
+    else if (pScb->ScsiCdb[0] == SCSI_OPCODE_MODE_SELECT6)
+    {
+        /* MODE SELECT is only when enabling / disabling write cache */
+        if (errorReg & ABRT_ERR)
+        {
+            SenseData.SenseKey = SCSI_SENSE_ABORTED_COMMAND;
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+        }
+        else
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " in mapping ATA error to SCSI error\n");
+            SenseData.SenseKey = SCSI_SENSE_NO_SENSE;
+        }
+    }
+    pScb->senseDataLength = 20;
+    memcpy(pScb->pSenseBuffer, &SenseData,
+           (pScb->senseBufferLength > pScb->senseDataLength) ?
+           pScb->senseDataLength : pScb->senseBufferLength);
+}
+
+
+
+static MV_VOID
+handleUdmaError(MV_SATA_SCSI_CMD_BLOCK  *pScb,
+                MV_U32 responseFlags,
+                MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "UDMA %s command failed\n", (pScb->udmaType == MV_UDMA_TYPE_READ) ?
+             "READ" : "WRITE");
+    if (responseFlags & (MV_BIT3))
+    {
+        /* prevent the error_handler from re-send any commands */
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_DISCONNECT;
+    }
+    else if (responseFlags & MV_BIT2)           /* ATA error*/
+    {
+        MV_SCSI_SENSE_DATA SenseData;
+
+        memset(&SenseData, 0, sizeof(MV_SCSI_SENSE_DATA));
+        pScb->ScsiStatus =  MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->dataTransfered = 0;
+        pScb->senseDataLength = 13;
+//        SenseData.Valid = 1;
+        SenseData.ResponseCode = MV_SCSI_RESPONSE_CODE;
+        SenseData.AdditionalSenseLength = 12;
+	SenseData.InformationDesc.type = 0;
+	SenseData.InformationDesc.AdditionalLength = 0xA;
+	SenseData.InformationDesc.valid = 1 << 7;
+
+
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " ATA Drive Registers:\n");
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","Error", registerStruct->errorRegister);
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","SectorCount", registerStruct->sectorCountRegister);
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA Low", registerStruct->lbaLowRegister);
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA Mid", registerStruct->lbaMidRegister);
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA High", registerStruct->lbaHighRegister);
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","Device", registerStruct->deviceRegister);
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "%20s : %04x\n","Status", registerStruct->statusRegister);
+
+        if ((registerStruct->errorRegister & ICRC_ERR)||
+            (registerStruct->errorRegister == 0xC))/*error code injected by 88i8030*/
+        {
+            SenseData.SenseKey = SCSI_SENSE_ABORTED_COMMAND;
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+        }
+        else if (registerStruct->errorRegister &
+                 (NM_ERR | MC_ERR | MCR_ERR))
+        {
+            SenseData.SenseKey = SCSI_SENSE_UNIT_ATTENTION;
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
+        }
+        else if ((registerStruct->errorRegister & UNC_ERR) ||
+		 (registerStruct->errorRegister == 1))
+        {
+#if 0
+            MV_U32  LowLbaAddress = pScb->LowLbaAddress;
+
+            SenseData.Valid = 1;
+            SenseData.Information[0] = (MV_U8)((LowLbaAddress & 0xff000000) >> 24);
+            SenseData.Information[1] = (MV_U8)(registerStruct->lbaHighRegister & 0xff);
+            SenseData.Information[2] = (MV_U8)(registerStruct->lbaMidRegister & 0xff);
+            SenseData.Information[3] = (MV_U8)(registerStruct->lbaLowRegister & 0xff);
+#endif
+	    _fillSenseInformation(pScb, &SenseData, registerStruct);
+            if (pScb->udmaType == MV_UDMA_TYPE_READ)
+            {
+                SenseData.SenseKey = SCSI_SENSE_MEDIUM_ERROR;
+                SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+
+		mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " DMA Read failed on UNC at sector %02x %02x %02x %02x %02x %02x\n",
+			 SenseData.InformationDesc.information[2],
+			 SenseData.InformationDesc.information[3],
+			 SenseData.InformationDesc.information[4],
+			 SenseData.InformationDesc.information[5],
+			 SenseData.InformationDesc.information[6],
+			 SenseData.InformationDesc.information[7]
+		     );
+            }
+            else
+            {
+                SenseData.SenseKey = SCSI_SENSE_DATA_PROTECT;
+                SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+            }
+        }
+        else if ((registerStruct->errorRegister & IDNF_ERR) &&
+                 (!(registerStruct->errorRegister & ABRT_ERR)))
+        {
+            /* In case IDNF is set and ABRT reset OR IDNF reset and ABRT is set */
+            SenseData.SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_ILLEGAL_BLOCK;
+        }
+        else if (registerStruct->errorRegister & ABRT_ERR)
+        {
+            SenseData.SenseKey = SCSI_SENSE_ABORTED_COMMAND;
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+        }
+        else
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " in mapping ATA error to SCSI error\n");
+            SenseData.SenseKey = SCSI_SENSE_ABORTED_COMMAND;
+            SenseData.AdditionalSenseCode = SCSI_ADSENSE_NO_SENSE;
+        }
+        pScb->senseDataLength = 20;
+        memcpy(pScb->pSenseBuffer, &SenseData,
+               (pScb->senseBufferLength > pScb->senseDataLength) ?
+               pScb->senseDataLength : pScb->senseBufferLength);
+    }
+    else if (responseFlags & (MV_BIT0 | MV_BIT1))
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_PARITY_ERROR;
+        pScb->ScsiStatus =  MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->senseDataLength = 0;
+        pScb->dataTransfered = 0;
+    }
+    else if (responseFlags & (MV_BIT6|MV_BIT5))
+    {
+        if (responseFlags & MV_BIT6)
+        {
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_UNDERRUN;
+        }
+        else
+        {
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_OVERRUN;
+        }
+        pScb->dataTransfered = 0;
+
+    }
+}
+
+/*******************************************************************************
+* checkQueueCommandResult -
+*
+* DESCRIPTION:  set the scsi request completion status and the Scsi Status
+*       according to the result returned form the mvSataQueueCommand function
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+
+/*static*/ MV_VOID  checkQueueCommandResult(MV_SATA_SCSI_CMD_BLOCK *pScb,
+                                            MV_QUEUE_COMMAND_RESULT  result)
+{
+    switch (result)
+    {
+    case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS:
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " Edma Queue command failed. Bad LBA \n");
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        break;
+    case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED:
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " Edma Queue command failed. EDMA disabled\n");
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_NOT_READY;
+
+        break;
+    case MV_QUEUE_COMMAND_RESULT_FULL:
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " Edma Queue command failed. Queue is Full\n");
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_QUEUE_FULL;
+        pScb->ScsiStatus = MV_SCSI_STATUS_QUEUE_FULL;
+        break;
+    case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS:
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " Edma Queue command failed. (Bad Params)\n");
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCB;
+        break;
+    default:
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " Bad result value (%d) from queue"
+                 " command\n", result);
+    }
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " mvSataQueueUDmaCommand Failed\n");
+    pScb->dataTransfered = 0;
+    pScb->senseDataLength = 0;
+}
+#ifdef MV_LOGGER
+static MV_VOID reportScbCompletion(MV_SATA_ADAPTER*    pSataAdapter,
+                                   MV_SATA_SCSI_CMD_BLOCK *pScb)
+{
+    if (pScb->ScsiCommandCompletion != MV_SCSI_COMPLETION_SUCCESS)
+    {
+        MV_U8   buffer[100];
+        MV_U32  index = 0;
+        MV_BOOLEAN      printInfo = MV_TRUE;
+
+        switch (pScb->ScsiCommandCompletion)
+        {
+        case MV_SCSI_COMPLETION_BAD_SCSI_COMMAND:
+            SAL_SPRINTF(buffer, "%s", "MV_SCSI_COMPLETION_BAD_SCSI_COMMAND");
+            break;
+        case MV_SCSI_COMPLETION_ATA_FAILED:
+            SAL_SPRINTF(buffer, "%s", "MV_SCSI_COMPLETION_ATA_FAILED");
+            break;
+        case MV_SCSI_COMPLETION_PARITY_ERROR:
+            SAL_SPRINTF(buffer, "%s", "MV_SCSI_COMPLETION_PARITY");
+            break;
+        default:
+            printInfo = MV_FALSE;
+        }
+
+        if (printInfo == MV_TRUE)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " %d %d %d :Scsi command completed. pScb %p, ScsiStatus %d "
+                     "completionStatus %s\n", pSataAdapter->adapterId,
+                     pScb->bus, pScb->target, pScb, pScb->ScsiStatus, buffer);
+        }
+        else
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Scsi command completed. pScb %p, ScsiStatus %d "
+                     "completionStatus %d\n", pScb, pScb->ScsiStatus,
+                     pScb->ScsiCommandCompletion);
+        }
+
+        index = SAL_SPRINTF(buffer, "%s", "CDB:");
+        {
+            MV_U32  i;
+            for (i =0 ; i < pScb->ScsiCdbLength; i++)
+            {
+                index += SAL_SPRINTF(&buffer[index], "%x ",
+                                     pScb->ScsiCdb[i]);
+            }
+            buffer[index] = '\n';
+            buffer[index+1] = 0;
+            mvLogMsg(MV_SAL_LOG_ID,(printInfo == MV_TRUE) ?
+                     MV_DEBUG_ERROR : MV_DEBUG, buffer);
+            if (pScb->ScsiStatus == MV_SCSI_STATUS_CHECK_CONDITION)
+            {
+                if ((pScb->pSenseBuffer != NULL) && (pScb->senseBufferLength > 0))
+                {
+                    MV_U32  len = pScb->senseDataLength > pScb->senseBufferLength ?
+                                  pScb->senseBufferLength:pScb->senseDataLength;
+                    index = SAL_SPRINTF(buffer, "%s", "Sense Data:");
+                    for (i = 0; i < len; i++)
+                    {
+                        index += SAL_SPRINTF(buffer + index, "%x ",
+                                             pScb->pSenseBuffer[i]);
+                    }
+                    buffer[index] = '\n';
+                    buffer[index+1] = 0;
+                    mvLogMsg(MV_SAL_LOG_ID, (printInfo == MV_TRUE) ?
+                             MV_DEBUG_ERROR : MV_DEBUG, buffer);
+                }
+            }
+        }
+        if (pScb->ScsiCommandCompletion == MV_SCSI_COMPLETION_ATA_FAILED)
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " ATA Drive Registers:\n");
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n","Error", pScb->ATAregStruct.errorRegister);
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n","SectorCount", pScb->ATAregStruct.sectorCountRegister);
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n","LBA Low", pScb->ATAregStruct.lbaLowRegister);
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n","LBA Mid", pScb->ATAregStruct.lbaMidRegister);
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n","LBA High", pScb->ATAregStruct.lbaHighRegister);
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n","Device", pScb->ATAregStruct.deviceRegister);
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n","Status", pScb->ATAregStruct.statusRegister);
+        }
+    }
+    else
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Scsi command completed. pScb %p, ScsiStatus %d "
+                 "completionStatus %d  dataTransfered %d \n", pScb, pScb->ScsiStatus,
+                 pScb->ScsiCommandCompletion,  pScb->dataTransfered);
+    }
+    
+}
+#endif
+static MV_VOID  mvScsiAtaSendSplittedVerifyCommand(IN MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+    MV_U8                  sectors = 0;/*256 sectors*/
+
+    pScb->sequenceNumber++;
+    if (pScb->sequenceNumber == 1)/*for the first command*/
+    {
+        if (pScb->ScsiCdb[0] == SCSI_OPCODE_VERIFY6)
+        {
+            sectors = pScb->ScsiCdb[4];
+        }
+        else if (pScb->ScsiCdb[0] == SCSI_OPCODE_VERIFY10)
+        {
+            sectors = pScb->ScsiCdb[8];
+        }
+	else 
+        {
+            sectors = pScb->ScsiCdb[13];
+        }
+    }
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = NULL;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.command = MV_ATA_COMMAND_READ_VERIFY_SECTORS;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 0;
+
+    pCommandInfo->commandParams.NoneUdmaCommand.features = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = (MV_U16)((pScb->LowLbaAddress & 0xff0000) >> 16);
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = (MV_U16)((pScb->LowLbaAddress & 0xff00) >> 8);
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = (MV_U16)(pScb->LowLbaAddress & 0xff);
+    pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = sectors;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = (MV_U8)(MV_BIT6 |
+                                                                 ((pScb->LowLbaAddress & 0xf000000) >> 24));
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d %d: Sending Splitted Verify command:seq# %d code %x lba"
+             " %x(%x.%x.%x), sectors %d[%d] Srb %p\n",
+             pScb->pSalAdapterExtension->pSataAdapter->adapterId, pScb->bus,
+             pScb->target,
+             pScb->sequenceNumber,pScb->ScsiCdb[0],
+             pScb->LowLbaAddress,
+             pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh,
+             pCommandInfo->commandParams.NoneUdmaCommand.lbaMid,
+             pCommandInfo->commandParams.NoneUdmaCommand.lbaLow,
+             pCommandInfo->commandParams.NoneUdmaCommand.sectorCount,
+             mvSataNumOfDmaCommands(pScb->pSalAdapterExtension->pSataAdapter,
+                                    pScb->bus), pScb);
+
+    if (sectors)
+    {
+        pScb->LowLbaAddress += sectors;
+    }
+    else
+    {
+        pScb->LowLbaAddress += 0x100;
+    }
+
+    result = mvSataQueueCommand(pScb->pSalAdapterExtension->pSataAdapter,
+                                pScb->bus, pCommandInfo);
+
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+#ifdef MV_LOGGER
+        reportScbCompletion(pScb->pSalAdapterExtension->pSataAdapter, pScb);
+#endif
+
+        return;
+    }
+
+    /* update stats*/
+    pScb->pSalAdapterExtension->totalAccumulatedOutstanding[pScb->bus] +=
+    mvSataNumOfDmaCommands(pScb->pSalAdapterExtension->pSataAdapter,pScb->bus);
+    pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target].stats.totalIOs++;
+    pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target].stats.totalSectorsTransferred += sectors;
+
+}
+static MV_VOID  mvScsiAtaSendReadLookAhead(IN MV_SATA_ADAPTER *pSataAdapter,
+                                           IN MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+
+    if (pScb->LowLbaAddress == 0) /* Disable Look Ahead*/
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Parse Caching Page: Disable Read Look Ahead\n");
+        pCommandInfo->commandParams.NoneUdmaCommand.features = MV_ATA_SET_FEATURES_DISABLE_RLA;
+    }
+    else
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Parse Caching Page: Enable Look Ahead\n");
+        pCommandInfo->commandParams.NoneUdmaCommand.features = MV_ATA_SET_FEATURES_ENABLE_RLA;
+    }
+
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.NoneUdmaCommand.bufPtr = NULL;
+    pCommandInfo->commandParams.NoneUdmaCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.NoneUdmaCommand.command = MV_ATA_COMMAND_SET_FEATURES;
+    pCommandInfo->commandParams.NoneUdmaCommand.commandId = (MV_VOID_PTR) pScb;
+    pCommandInfo->commandParams.NoneUdmaCommand.count = 0;
+
+    pCommandInfo->commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaHigh = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaMid = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.lbaLow = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
+    pCommandInfo->commandParams.NoneUdmaCommand.sectorCount = 0;
+    pCommandInfo->commandParams.NoneUdmaCommand.device = (MV_U8)(MV_BIT6);
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Sending SET FEATURES command: features %d\n",
+             pCommandInfo->commandParams.NoneUdmaCommand.features);
+
+    pScb->sequenceNumber++;
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return;
+    }
+}
+
+MV_VOID     mvSataScsiInitAdapterExt(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
+                                     MV_SATA_ADAPTER* pSataAdapter)
+{
+    MV_U8   channelIndex;
+    MV_U8   PMPort;
+    pAdapterExt->pSataAdapter = pSataAdapter;
+    pAdapterExt->pHead = NULL;
+    pAdapterExt->UAMask = 0xFF;
+    for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++)
+    {
+        for (PMPort = 0; PMPort < MV_SATA_PM_MAX_PORTS; PMPort++)
+        {
+            pAdapterExt->ataDriveData[channelIndex][PMPort].driveReady = MV_FALSE;
+            /* one identify data buffer used for all the drives connected to */
+            /* the same channel*/
+            pAdapterExt->ataDriveData[channelIndex][PMPort].identifyBuffer =
+            pAdapterExt->identifyBuffer[channelIndex];
+        }
+    }
+}
+#ifdef MV_SUPPORT_ATAPI
+MV_SCSI_COMMAND_STATUS_TYPE mvScsiAtaSendATAPICommand(MV_SATA_ADAPTER *pSataAdapter, 
+                                                        MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = pScb->pCommandInfo;
+#else
+    MV_QUEUE_COMMAND_INFO   commandInfo;
+    MV_QUEUE_COMMAND_INFO   *pCommandInfo = &commandInfo;
+#endif
+    MV_QUEUE_COMMAND_RESULT result;
+
+ 
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Send Packet command, adapter %d bus %d target %d lun %"
+             "d pScb %p\n  dir(%d)  Data Buffer %p (%d), cdb %p (%d)\n",
+             pSataAdapter->adapterId, pScb->bus, pScb->target,
+             pScb->lun, pScb, pScb->dataDirection,
+            pScb->pDataBuffer, 
+                pScb->dataBufferLength, pScb->ScsiCdb, pScb->ScsiCdbLength);
+ 
+    pScb->commandType = MV_QUEUED_COMMAND_TYPE_PACKET;
+
+    pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_PACKET;
+    pCommandInfo->PMPort = pScb->target;
+    pCommandInfo->commandParams.packetCommand.bufPtr = (MV_U16_PTR)pScb->pDataBuffer;
+    pCommandInfo->commandParams.packetCommand.buffer_len = pScb->dataBufferLength;
+    pCommandInfo->commandParams.packetCommand.transfered_data = 0;
+    pCommandInfo->commandParams.packetCommand.cdb_len = (pScb->ScsiCdbLength  >> 1);
+    pCommandInfo->commandParams.packetCommand.cdb_buffer = (MV_U16_PTR)pScb->ScsiCdb;
+    pCommandInfo->commandParams.packetCommand.flags = 0;
+    pCommandInfo->commandParams.packetCommand.callBack = SALCommandCompletionCB;
+    pCommandInfo->commandParams.packetCommand.commandId = (MV_VOID_PTR) pScb;
+    pCommandInfo->commandParams.packetCommand.prdLowAddr = pScb->PRDTableLowPhyAddress;
+    pCommandInfo->commandParams.packetCommand.prdHighAddr = pScb->PRDTableHighPhyAddress;
+    
+    if((pScb->dataDirection == MV_SCSI_COMMAND_DATA_DIRECTION_IN) && (pScb->pDataBuffer == NULL))
+    {
+        pCommandInfo->commandParams.packetCommand.protocolType = MV_NON_UDMA_PROTOCOL_PACKET_DMA;
+    }
+    else if((pScb->dataDirection == MV_SCSI_COMMAND_DATA_DIRECTION_OUT) && (pScb->pDataBuffer == NULL))
+    {
+        pCommandInfo->commandParams.packetCommand.protocolType = MV_NON_UDMA_PROTOCOL_PACKET_DMA;
+        pCommandInfo->commandParams.packetCommand.flags = MV_BIT0;
+    }
+    else
+    {
+        switch(pScb->dataDirection)
+        {
+            case MV_SCSI_COMMAND_DATA_DIRECTION_IN:
+                pCommandInfo->commandParams.packetCommand.protocolType = MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN;
+                break;
+            case MV_SCSI_COMMAND_DATA_DIRECTION_OUT:
+                pCommandInfo->commandParams.packetCommand.protocolType = MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT;
+                break;
+        default:
+                pCommandInfo->commandParams.packetCommand.protocolType = MV_NON_UDMA_PROTOCOL_PACKET_PIO_NON_DATA;
+        }
+    }
+    pScb->sequenceNumber = 0;
+    result = mvSataQueueCommand(pSataAdapter, pScb->bus, pCommandInfo);
+
+    if (result != MV_QUEUE_COMMAND_RESULT_OK)
+    {
+        checkQueueCommandResult(pScb, result);
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    return MV_SCSI_COMMAND_STATUS_QUEUED;
+}
+#endif
+MV_SCSI_COMMAND_STATUS_TYPE mvSataExecuteScsiCommand(MV_SATA_SCSI_CMD_BLOCK  *pScb)
+{
+    MV_U8               *cmd = pScb->ScsiCdb;
+    MV_BOOLEAN          invalidCDB = MV_FALSE;
+    MV_SATA_ADAPTER *pSataAdapter = pScb->pSalAdapterExtension->pSataAdapter;
+    MV_SATA_SCSI_DRIVE_DATA *pDriveData;
+
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Scsi Command Received, adapter %d bus %d target %d lun %"
+             "d pScb %p\n    Data Buffer length %d, Sense buffer length %x\n",
+             pSataAdapter->adapterId, pScb->bus, pScb->target,
+             pScb->lun, pScb, pScb->dataBufferLength, pScb->senseBufferLength);
+
+#ifdef MV_LOGGER
+
+    {
+        MV_U8 buffer[50];
+        MV_U32  i, index;
+
+        index = SAL_SPRINTF(buffer, "%s", "CDB:");
+        for (i =0 ; i < pScb->ScsiCdbLength; i++)
+        {
+            index += SAL_SPRINTF(&buffer[index], "%x ",
+                                 pScb->ScsiCdb[i]);
+        }
+        buffer[index] = '\n';
+        buffer[index+1] = 0;
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, buffer);
+    }
+#endif
+    pScb->dataTransfered = 0;
+    pScb->senseDataLength = 0;
+    pScb->ScsiStatus = 0;
+    if (pScb->bus >= pSataAdapter->numberOfChannels)
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_INVALID_BUS;
+        pScb->dataTransfered = 0;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    if ((pScb->target >= MV_SATA_PM_MAX_PORTS) ||
+        (pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target].driveReady == MV_FALSE) ||
+        ((pScb->lun) && (pScb->ScsiCdb[0] != SCSI_OPCODE_INQUIRY)))
+    {
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_NO_DEVICE;
+        pScb->dataTransfered = 0;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+    pDriveData = &pScb->pSalAdapterExtension->ataDriveData[pScb->bus][pScb->target];
+#ifdef MV_SUPPORT_ATAPI
+    if(pDriveData->identifyInfo.deviceType == MV_SATA_DEVICE_TYPE_ATAPI_DEVICE)
+    {
+        return mvScsiAtaSendATAPICommand(pSataAdapter, pScb);
+    }
+#endif
+    switch (cmd[0])
+    {
+    case SCSI_OPCODE_READ10:
+    case SCSI_OPCODE_WRITE10:
+    case SCSI_OPCODE_READ_CAPACITY10:
+    case SCSI_OPCODE_VERIFY10:
+    case SCSI_OPCODE_SYNCHRONIZE_CACHE10:
+
+#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG
+    case SCSI_OPCODE_WRITE_LONG10:
+    case SCSI_OPCODE_READ_LONG10:
+#endif
+        if (cmd[1] & MV_BIT0) /* if related address*/
+        {
+            invalidCDB = MV_TRUE;
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d %d: Scsi command received with "
+                     "RELADR bit enabled - returning ILLEGAL REQUEST\n"
+                     ,pSataAdapter->adapterId, pScb->bus, pScb->target);
+
+        }
+    }
+    if (cmd[pScb->ScsiCdbLength - 1] != 0) /*if CONTROL is set*/
+    {
+        MV_BOOLEAN commandSupported = MV_TRUE;
+
+        switch (cmd[0])
+        {
+        case SCSI_OPCODE_READ6:
+        case SCSI_OPCODE_READ10:
+        case SCSI_OPCODE_READ16:
+        case SCSI_OPCODE_WRITE6:
+        case SCSI_OPCODE_WRITE10:
+        case SCSI_OPCODE_WRITE16:
+        case SCSI_OPCODE_INQUIRY:
+        case SCSI_OPCODE_TEST_UNIT_READY:
+        case SCSI_OPCODE_MODE_SELECT6:
+        case SCSI_OPCODE_MODE_SENSE6:
+        case SCSI_OPCODE_START_STOP:
+        case SCSI_OPCODE_READ_CAPACITY10:     /* read capctiy CDB*/
+        case SCSI_OPCODE_REQUEST_SENSE6:
+        case SCSI_OPCODE_VERIFY6:
+        case SCSI_OPCODE_VERIFY10:
+        case SCSI_OPCODE_VERIFY16:
+        case SCSI_OPCODE_SYNCHRONIZE_CACHE10:
+        case SCSI_OPCODE_SYNCHRONIZE_CACHE16:
+        case SCSI_OPCODE_SEEK10:
+        case SCSI_OPCODE_REASSIGN_BLOCKS:
+        case SCSI_OPCODE_REPORT_LUNS:
+#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG
+        case SCSI_OPCODE_WRITE_LONG10:
+        case SCSI_OPCODE_READ_LONG10:
+#endif
+        case SCSI_OPCODE_ATA12:
+        case SCSI_OPCODE_ATA16:
+
+            break;
+        default:
+            commandSupported = MV_FALSE;
+        }
+        if (commandSupported == MV_TRUE)
+        {
+            invalidCDB = MV_TRUE;
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "[%d,%d] Scsi command received with "
+                     "none zero CONTROL bits - returning ILLEGAL REQUEST\n"
+                     ,pSataAdapter->adapterId, pScb->bus);
+        }
+    }
+
+    if (pDriveData->UAConditionPending == MV_TRUE)
+    {
+        if (((cmd[0] != SCSI_OPCODE_INQUIRY) &&
+	     (cmd[0] != SCSI_OPCODE_REPORT_LUNS) &&
+             (cmd[0] != SCSI_OPCODE_REQUEST_SENSE6)) || (invalidCDB == MV_TRUE))
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " Unit Attention condition is pending.\n");
+
+            if (pDriveData->UAEvents & MV_BIT0)
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Report Bus Reset.\n");
+                pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_UA_RESET;
+                setSenseData(pScb, SCSI_SENSE_UNIT_ATTENTION, SCSI_ADSENSE_BUS_RESET
+                             , 2);
+                pDriveData->UAEvents &= ~MV_BIT0;
+            }
+            else if (pDriveData->UAEvents & MV_BIT1)
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Report Mode Parameters Changed.\n");
+                pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_UA_PARAMS_CHANGED;
+                setSenseData(pScb, SCSI_SENSE_UNIT_ATTENTION,
+                             SCSI_ADSENSE_PARAMETERS_CHANGED, 1);
+                pDriveData->UAEvents &= ~MV_BIT1;
+            }
+
+            pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+            pScb->dataTransfered = 0;
+#ifdef MV_LOGGER
+            reportScbCompletion(pSataAdapter, pScb);
+#endif
+            pScb->completionCallBack(pSataAdapter, pScb);
+            if (pDriveData->UAEvents == 0)
+            {
+                pDriveData->UAConditionPending = MV_FALSE;
+            }
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+        }
+    }
+    if (invalidCDB == MV_TRUE)
+    {
+        setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB,
+                     0);
+        pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+        pScb->dataTransfered = 0;
+        pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+        reportScbCompletion(pSataAdapter, pScb);
+#endif
+        pScb->completionCallBack(pSataAdapter, pScb);
+        return MV_SCSI_COMMAND_STATUS_COMPLETED;
+    }
+
+    switch (cmd[0])
+    {
+    case SCSI_OPCODE_READ6:
+    case SCSI_OPCODE_READ10:
+    case SCSI_OPCODE_READ16:
+    case SCSI_OPCODE_WRITE6:
+    case SCSI_OPCODE_WRITE10:
+    case SCSI_OPCODE_WRITE16:
+        return mvScsiAtaSendDataCommand(pSataAdapter, pScb);
+    case SCSI_OPCODE_START_STOP:
+        return mvScsiAtaStartStopCommand(pSataAdapter, pScb);
+    case SCSI_OPCODE_INQUIRY:
+        return mvScsiAtaGetInquiryData(pSataAdapter, pScb);
+    case SCSI_OPCODE_TEST_UNIT_READY:
+        return mvScsiAtaTestUnitReady(pSataAdapter, pScb);
+    case SCSI_OPCODE_MODE_SELECT6:
+        return mvScsiAtaModeSelect(pSataAdapter, pScb);
+    case SCSI_OPCODE_MODE_SENSE6:
+        return mvScsiAtaGetModeSenseData(pSataAdapter,pScb);
+        /* Used to detect write protected status.*/
+    case SCSI_OPCODE_READ_CAPACITY10:     /* read capctiy CDB*/
+        return mvScsiAtaGetReadCapacityData(pSataAdapter, pScb);
+    case SCSI_OPCODE_READ_CAPACITY16:     /* read capctiy CDB*/
+        return mvScsiAtaGetReadCapacity16Data(pSataAdapter, pScb);
+    case SCSI_OPCODE_REQUEST_SENSE6:
+        return mvScsiAtaGetRequestSenseData(pSataAdapter, pScb);
+    case SCSI_OPCODE_REPORT_LUNS:
+        return mvScsiAtaReportLuns(pSataAdapter, pScb);
+    case SCSI_OPCODE_VERIFY6:
+    case SCSI_OPCODE_VERIFY10:
+    case SCSI_OPCODE_VERIFY16:
+        return mvScsiAtaSendVerifyCommand(pSataAdapter, pScb);
+    case SCSI_OPCODE_SYNCHRONIZE_CACHE10:
+    case SCSI_OPCODE_SYNCHRONIZE_CACHE16:
+        return mvScsiAtaSendSyncCacheCommand(pSataAdapter, pScb);
+    case SCSI_OPCODE_SEEK10:
+        return mvScsiAtaSeek(pSataAdapter, pScb);
+    case SCSI_OPCODE_REASSIGN_BLOCKS:
+        return mvScsiAtaReassignBlocks(pSataAdapter, pScb);
+#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG
+    case SCSI_OPCODE_WRITE_LONG10:
+        return mvScsiAtaWriteLong(pSataAdapter, pScb);
+    case SCSI_OPCODE_READ_LONG10:
+        return mvScsiAtaReadLong(pSataAdapter, pScb);
+#endif
+    case SCSI_OPCODE_ATA12:
+    case SCSI_OPCODE_ATA16:
+        return mvScsiAtaPassThru(pSataAdapter, pScb);
+
+    default:
+        {
+            setSenseData(pScb, SCSI_SENSE_ILLEGAL_REQUEST,
+                         SCSI_ADSENSE_ILLEGAL_COMMAND, 0);
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, "mvExecuteScsiCommand: ERROR: Unsupported command %02X\n", pScb->ScsiCdb[0]);
+            pScb->ScsiStatus = MV_SCSI_STATUS_CHECK_CONDITION;
+            pScb->dataTransfered = 0;
+            pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_BAD_SCSI_COMMAND;
+#ifdef MV_LOGGER
+            reportScbCompletion(pSataAdapter, pScb);
+#endif
+            pScb->completionCallBack(pSataAdapter, pScb);
+            return MV_SCSI_COMMAND_STATUS_COMPLETED;
+
+        }
+    }
+
+    return MV_SCSI_COMMAND_STATUS_FAILED;
+}
+
+MV_VOID mvSataScsiPostIntService(MV_SAL_ADAPTER_EXTENSION *pAdapterExt)
+{
+    MV_SATA_SCSI_CMD_BLOCK  *pScb = pAdapterExt->pHead;
+    while (pScb)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, "Post Interrupt Service: pScb %p command %x\n", pScb,
+                 pScb->ScsiCdb[0]);
+        switch (pScb->ScsiCdb[0])
+        {
+	case    SCSI_OPCODE_VERIFY16:
+        case    SCSI_OPCODE_VERIFY10:
+        case    SCSI_OPCODE_VERIFY6:
+            mvScsiAtaSendSplittedVerifyCommand(pScb);
+            break;
+        case    SCSI_OPCODE_MODE_SELECT6:
+            mvScsiAtaSendReadLookAhead(pAdapterExt->pSataAdapter,
+                                       pScb);
+            break;
+        default:
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG_ERROR, " Post Interrupt Service called for bad scsi"
+                     " command(%x)\n", pScb->ScsiCdb[0]);
+        }
+        pScb = pScb->pNext;
+    }
+    pAdapterExt->pHead = NULL;
+    return;
+}
+
+MV_VOID     mvSataScsiSetDriveReady(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
+                                    MV_U8   channelIndex, MV_U8 PMPort,
+                                    MV_BOOLEAN  isReady)
+{
+    if (isReady == MV_TRUE)
+    {
+        mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d %d: ATA Drive is Ready.\n",
+                 pAdapterExt->pSataAdapter->adapterId, channelIndex, PMPort);
+        pAdapterExt->ataDriveData[channelIndex][PMPort].driveReady = MV_TRUE;
+        pAdapterExt->totalAccumulatedOutstanding[channelIndex] = 0;
+        pAdapterExt->ataDriveData[channelIndex][PMPort].stats.totalIOs = 0;
+        pAdapterExt->ataDriveData[channelIndex][PMPort].stats.totalSectorsTransferred = 0;
+    }
+    else
+    {
+        if (PMPort == 0xFF)
+        {
+            MV_U8   i;
+
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d  : SATA Channel is Removed.\n",
+                     pAdapterExt->pSataAdapter->adapterId, channelIndex);
+            for (i = 0; i < MV_SATA_PM_MAX_PORTS; i++)
+            {
+                mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d %d: SATA Drive is Removed.\n",
+                         pAdapterExt->pSataAdapter->adapterId, channelIndex,
+                         i);
+                pAdapterExt->ataDriveData[channelIndex][i].driveReady = MV_FALSE;
+            }
+
+        }
+        else
+        {
+            mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d %d: SATA Drive is Removed.\n",
+                     pAdapterExt->pSataAdapter->adapterId, channelIndex,
+                     PMPort);
+            pAdapterExt->ataDriveData[channelIndex][PMPort].driveReady = MV_FALSE;
+
+        }
+    }
+}
+
+
+/* notify the translation layer with Reset and Power on reset*/
+MV_VOID mvSataScsiNotifyUA(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
+                           MV_U8    channelIndex, MV_U8 PMPort)
+{
+/*
+ * disable unit attention errors, the commit "[SCSI] fix barrier failure issue" causes to 
+ * some of those commands to be completed with error by the scsi layer.
+ */
+
+#if 0 
+    pAdapterExt->ataDriveData[channelIndex][PMPort].UAConditionPending = MV_TRUE;
+    /* bit 0 - reset*/
+    /* bit 1 - parameters changed*/
+    pAdapterExt->ataDriveData[channelIndex][PMPort].UAEvents = MV_BIT1 | MV_BIT0;
+    pAdapterExt->ataDriveData[channelIndex][PMPort].UAEvents &=
+    pAdapterExt->UAMask;
+    mvLogMsg(MV_SAL_LOG_ID, MV_DEBUG, " %d %d %d: Notify SAL with Unit Attention condition.\n",
+             pAdapterExt->pSataAdapter->adapterId, channelIndex, PMPort);
+#else
+    pAdapterExt->ataDriveData[channelIndex][PMPort].UAConditionPending = MV_FALSE;
+    pAdapterExt->ataDriveData[channelIndex][PMPort].UAEvents = 0;
+#endif
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvScsiAtaLayer.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvScsiAtaLayer.h
new file mode 100755
index 0000000..5abaa9c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/mvScsiAtaLayer.h
@@ -0,0 +1,402 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+/*******************************************************************************
+* mvScsiAtaLayer.c
+*
+* DESCRIPTION:
+*       C implementation for SCSI to ATA translation layer.
+*
+* DEPENDENCIES:
+*   mvIALCommonUtils.h
+*   mvSata.h
+*   mvStorageDev.h
+*   mvOs.h
+*
+*******************************************************************************/
+#ifndef __INCmvScsiAtaLayer
+#define __INCmvScsiAtaLayer
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* includes */
+#include "mvOs.h"
+#include "mvSata.h"
+#include "mvStorageDev.h"
+#include "mvIALCommonUtils.h"
+
+/* Defines */
+#define MV_SAL_LOG_ID       1
+
+
+#ifndef IN
+#define IN
+#endif
+
+#ifndef OUT
+#define OUT
+#endif
+
+#ifndef INOUT
+#define INOUT
+#endif
+
+/* Scsi opcodes*/
+/* 6 - bytes commands*/
+#define SCSI_OPCODE_TEST_UNIT_READY         0x00
+#define SCSI_OPCODE_REPORT_LUNS		    0xA0
+#define SCSI_OPCODE_REQUEST_SENSE6          0x03
+#define SCSI_OPCODE_REASSIGN_BLOCKS         0x07
+#define SCSI_OPCODE_READ6                   0x08
+#define SCSI_OPCODE_WRITE6                  0x0A
+#define SCSI_OPCODE_INQUIRY                 0x12
+#define SCSI_OPCODE_VERIFY6                 0x13
+#define SCSI_OPCODE_MODE_SELECT6            0x15
+#define SCSI_OPCODE_MODE_SENSE6             0x1A
+#define SCSI_OPCODE_START_STOP              0x1B
+
+/* 10 - bytes commands*/
+#define SCSI_OPCODE_READ_CAPACITY10         0x25
+#define SCSI_OPCODE_READ10                  0x28
+#define SCSI_OPCODE_WRITE10                 0x2A
+#define SCSI_OPCODE_VERIFY10                0x2F
+#define SCSI_OPCODE_SYNCHRONIZE_CACHE10     0x35
+#define SCSI_OPCODE_SEEK10                  0x2B
+#define SCSI_OPCODE_WRITE_LONG10            0x3F
+#define SCSI_OPCODE_READ_LONG10				0x3E
+
+/* 12 - bytes commands */
+/* 16 - bytes commands */
+#define SCSI_OPCODE_READ_CAPACITY16         0x9E
+#define SCSI_OPCODE_READ16                  0x88
+#define SCSI_OPCODE_WRITE16                 0x8A
+#define SCSI_OPCODE_VERIFY16                0x8F
+#define SCSI_OPCODE_SYNCHRONIZE_CACHE16     0x91
+#define SCSI_OPCODE_ATA16                   0x85
+#define SCSI_OPCODE_ATA12                   0xA1
+
+
+    /* SCSI bus status codes */
+#define MV_SCSI_STATUS_GOOD                  0x00
+#define MV_SCSI_STATUS_CHECK_CONDITION       0x02
+#define MV_SCSI_STATUS_CONDITION_MET         0x04
+#define MV_SCSI_STATUS_BUSY                  0x08
+#define MV_SCSI_STATUS_INTERMEDIATE          0x10
+#define MV_SCSI_STATUS_INTERMEDIATE_COND_MET 0x14
+#define MV_SCSI_STATUS_RESERVATION_CONFLICT  0x18
+#define MV_SCSI_STATUS_COMMAND_TERMINATED    0x22
+#define MV_SCSI_STATUS_QUEUE_FULL            0x28
+
+
+/* Typedefs */
+
+#if 0
+/* Scsi Sense Data Format */
+/* Max length - 18 bytes, the additional sense length will not exceed 10 bytes*/
+    typedef struct _mvScsiSenseData
+    {
+#ifdef MV_BIG_ENDIAN_BITFIELD
+        MV_U8 Valid:1;
+        MV_U8 ResponseCode:7;
+#else
+        MV_U8 ResponseCode:7;
+        MV_U8 Valid:1;
+#endif
+        MV_U8 Reserved1;
+#ifdef MV_BIG_ENDIAN_BITFIELD
+        MV_U8 FileMark:1;
+        MV_U8 EOM:1; /* End Of Media */
+        MV_U8 ILI:1; /* Incorrect Length Indicator*/
+        MV_U8 Reserved2:1;
+        MV_U8 SenseKey:4;
+#else
+        MV_U8 SenseKey:4;
+        MV_U8 Reserved2:1;
+        MV_U8 ILI:1; /* Incorrect Length Indicator*/
+        MV_U8 EOM:1; /* End Of Media */
+        MV_U8 FileMark:1;
+#endif        
+        MV_U8 Information[4];
+        MV_U8 AdditionalSenseLength;
+        MV_U8 CommandSpecificInformation[4];
+        MV_U8 AdditionalSenseCode;
+        MV_U8 AdditionalSenseCodeQualifier;
+        MV_U8 FieldReplaceableUnitCode;
+        MV_U8 SenseKeySpecific[3];
+    } MV_SCSI_SENSE_DATA;
+#else
+/* Scsi Sense Data Descriptor Format + information descriptor */
+/* Max length - 18 bytes, the additional sense length will not exceed 10 bytes*/
+    typedef struct _mvScsiInfoSenseDesc
+    {
+	    MV_U8 type;
+	    MV_U8 AdditionalLength;
+	    MV_U8 valid;
+	    MV_U8 reserved;
+	    MV_U8 information[11-4+1];
+    }MV_SCSI_INFO_SENSE_DESC;
+    typedef struct _mvScsiSenseData
+    {
+        MV_U8 ResponseCode;
+#ifdef MV_BIG_ENDIAN_BITFIELD
+        MV_U8 Reserved:4;
+        MV_U8 SenseKey:4;
+#else
+        MV_U8 SenseKey:4;
+        MV_U8 Reserved:4;
+#endif        
+        MV_U8 AdditionalSenseCode;
+        MV_U8 AdditionalSenseCodeQualifier;
+        MV_U8 Reserved2[3];
+        MV_U8 AdditionalSenseLength;
+	MV_SCSI_INFO_SENSE_DESC InformationDesc;
+    } MV_SCSI_SENSE_DATA;
+#endif
+/* Sense codes */
+
+#define SCSI_SENSE_NO_SENSE         0x00
+#define SCSI_SENSE_RECOVERED_ERROR  0x01
+#define SCSI_SENSE_NOT_READY        0x02
+#define SCSI_SENSE_MEDIUM_ERROR     0x03
+#define SCSI_SENSE_HARDWARE_ERROR   0x04
+#define SCSI_SENSE_ILLEGAL_REQUEST  0x05
+#define SCSI_SENSE_UNIT_ATTENTION   0x06
+#define SCSI_SENSE_DATA_PROTECT     0x07
+#define SCSI_SENSE_BLANK_CHECK      0x08
+#define SCSI_SENSE_UNIQUE           0x09
+#define SCSI_SENSE_COPY_ABORTED     0x0A
+#define SCSI_SENSE_ABORTED_COMMAND  0x0B
+#define SCSI_SENSE_EQUAL            0x0C
+#define SCSI_SENSE_VOL_OVERFLOW     0x0D
+#define SCSI_SENSE_MISCOMPARE       0x0E
+#define SCSI_SENSE_RESERVED         0x0F
+
+/* Additional Sense codes */
+
+#define SCSI_ADSENSE_NO_SENSE       0x00
+#define SCSI_ADSENSE_ILLEGAL_COMMAND 0x20
+#define SCSI_ADSENSE_ILLEGAL_BLOCK  0x21
+#define SCSI_ADSENSE_INVALID_CDB    0x24
+#define SCSI_ADSENSE_INVALID_LUN    0x25
+#define SCSI_ADSENSE_INVALID_FIELD_IN_PARAMETER_LIST    0x26
+#define SCSI_ADSENSE_BUS_RESET      0x29
+#define SCSI_ADSENSE_PARAMETERS_CHANGED     0x2A
+#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE 0x3a
+
+
+#define MV_SCSI_RESPONSE_CODE   0x72
+#define MV_SCSI_DIRECT_ACCESS_DEVICE    0x00
+#define MV_MAX_MODE_SENSE_RESULT_LENGTH 50
+
+
+/* Typedefs */
+    typedef enum _mvScsiCompletionType
+    {
+        MV_SCSI_COMPLETION_INVALID_STATUS,
+        MV_SCSI_COMPLETION_SUCCESS,
+        MV_SCSI_COMPLETION_BAD_SCB,
+        MV_SCSI_COMPLETION_BAD_SCSI_COMMAND,
+        MV_SCSI_COMPLETION_ATA_FAILED,
+        MV_SCSI_COMPLETION_QUEUE_FULL,
+        MV_SCSI_COMPLETION_NOT_READY,
+        MV_SCSI_COMPLETION_ABORTED,
+        MV_SCSI_COMPLETION_OVERRUN,
+        MV_SCSI_COMPLETION_UNDERRUN,
+        MV_SCSI_COMPLETION_PARITY_ERROR,
+        MV_SCSI_COMPLETION_DISCONNECT,
+        MV_SCSI_COMPLETION_NO_DEVICE,
+        MV_SCSI_COMPLETION_INVALID_BUS,
+        MV_SCSI_COMPLETION_BUS_RESET,
+        MV_SCSI_COMPLETION_BUSY,
+        MV_SCSI_COMPLETION_UA_RESET,
+        MV_SCSI_COMPLETION_UA_PARAMS_CHANGED
+    }MV_SCSI_COMPLETION_TYPE;
+
+    typedef enum _mvScsiCommandStatus
+    {
+        MV_SCSI_COMMAND_STATUS_COMPLETED,
+        MV_SCSI_COMMAND_STATUS_QUEUED,
+        MV_SCSI_COMMAND_STATUS_FAILED,
+        MV_SCSI_COMMAND_STATUS_QUEUED_BY_IAL
+    }MV_SCSI_COMMAND_STATUS_TYPE;
+
+    typedef enum _mvScsiCommandDataDirection
+    {
+        MV_SCSI_COMMAND_DATA_DIRECTION_NON,
+        MV_SCSI_COMMAND_DATA_DIRECTION_IN,
+        MV_SCSI_COMMAND_DATA_DIRECTION_OUT
+    } MV_SCSI_COMMAND_DATA_DIRECTION;
+
+    struct _mvSataScsiCmdBlock;
+
+    typedef MV_BOOLEAN (* mvScsiCommandCompletionCallBack)(struct mvSataAdapter *,
+                                                           struct _mvSataScsiCmdBlock*);
+
+    struct mvSalAdapterExtension;
+    struct mvIalCommonAdapterExtension;
+
+    typedef struct _mvSataScsiCmdBlock
+    {
+        /*  the Scsi command data block buffer*/
+        IN MV_U8*       ScsiCdb;
+
+        /* the length in bytes of the CDB (6,10,12,16)*/
+        IN MV_U32       ScsiCdbLength;
+
+        /* the scsi bus*/
+        IN MV_U8        bus;
+
+        /* the target device id*/
+        IN MV_U8        target;
+
+        /* scsi lun number of the device*/
+        IN MV_U8        lun;
+
+        /* True when the data located in the buffer pointed by pDataBuffer  */
+        /* (virtual address), false when the command is READ/WRITE, in this */
+        /* case the data located in a PRD table*/
+        /*IN MV_BOOLEAN useSingleBuffer;*/
+
+        /* pointer to the command data buffer*/
+        IN MV_U8        *pDataBuffer;
+
+        /* length in bytes of the command data buffer*/
+        IN MV_U32       dataBufferLength;
+
+        /* number of entries in the PRD table*/
+        /*IN MV_U32     PRDTableEntries; */
+
+        /* low 32 bits of the PRD table physical address*/
+        IN MV_U32       PRDTableLowPhyAddress;
+
+        /* high 32 bits of the PRD table physical address*/
+        IN MV_U32       PRDTableHighPhyAddress;
+
+#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION
+        MV_BOOLEAN      singleDataRegion;
+        MV_U16          byteCount;
+#endif
+        /* the Scsi status will be written to this field*/
+        OUT MV_U8       ScsiStatus;
+
+        /* pointer to the Scsi sense buffer*/
+        IN MV_U8*       pSenseBuffer;
+
+        /* length in bytes of the Scsi sense buffer*/
+        IN MV_U32       senseBufferLength;
+
+        /* length in bytes of the generated sense data*/
+        OUT MV_U32      senseDataLength;
+
+        /* length in bytes of the data transferred to the data buffer/s*/
+        OUT MV_U32      dataTransfered;
+
+        /* the translation layer status of the completed Scsi command */
+        OUT MV_SCSI_COMPLETION_TYPE ScsiCommandCompletion;
+        /* call back function called by the translation layer when the Scsi */
+        /* completed    */
+        IN mvScsiCommandCompletionCallBack completionCallBack;
+
+        IN struct mvSalAdapterExtension * pSalAdapterExtension;
+        IN struct mvIALCommonAdapterExtension* pIalAdapterExtension;
+
+        IN MV_SCSI_COMMAND_DATA_DIRECTION dataDirection;
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+        MV_QUEUE_COMMAND_INFO   *pCommandInfo;
+#endif
+        /* field for IAL usage only*/
+        MV_VOID_PTR     IALData;
+        /* fields for internal usage for the translation layer*/
+
+
+        MV_UDMA_TYPE            udmaType;
+        MV_QUEUED_COMMAND_TYPE  commandType;
+        /* used for sense buffer */
+        MV_U32                  LowLbaAddress;
+        /* Used for non-UDMA and for sense buffer */
+        MV_BOOLEAN              isExtended;
+        MV_U16                  splitCount;
+        MV_U16                  sequenceNumber;
+        /* used to create list for comands that need post interrupt service */
+        struct _mvSataScsiCmdBlock  *pNext;
+#ifdef MV_LOGGER
+        MV_STORAGE_DEVICE_REGISTERS ATAregStruct;
+#endif
+    }MV_SATA_SCSI_CMD_BLOCK;
+
+    typedef struct
+    {
+        MV_U32              totalIOs;
+        MV_U32              totalSectorsTransferred;
+    }MV_SATA_SCSI_CHANNEL_STATS;
+
+    typedef struct
+    {
+        MV_BOOLEAN          driveReady;
+        ATA_IDENTIFY_INFO   identifyInfo;
+        MV_U16_PTR          identifyBuffer;
+        MV_SATA_SCSI_CHANNEL_STATS stats;
+        MV_BOOLEAN          UAConditionPending;
+        MV_U8               UAEvents;
+    }MV_SATA_SCSI_DRIVE_DATA;
+
+    typedef struct mvSalAdapterExtension
+    {
+        MV_SATA_ADAPTER *pSataAdapter;
+        MV_SATA_SCSI_CMD_BLOCK  *pHead;
+        MV_U8                   UAMask;/*which UA condictions to report*/
+        MV_U32  totalAccumulatedOutstanding[MV_SATA_CHANNELS_NUM];
+        MV_SATA_SCSI_DRIVE_DATA     ataDriveData[MV_SATA_CHANNELS_NUM][MV_SATA_PM_MAX_PORTS];
+        MV_U16  identifyBuffer[MV_SATA_CHANNELS_NUM][MV_ATA_IDENTIFY_DEV_DATA_LENGTH];
+
+    }MV_SAL_ADAPTER_EXTENSION;
+
+
+    MV_VOID     mvSataScsiInitAdapterExt(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
+                                         MV_SATA_ADAPTER* pSataAdapter);
+
+    MV_VOID     mvSataScsiPostIntService(MV_SAL_ADAPTER_EXTENSION *pAdapterExt);
+
+
+    MV_SCSI_COMMAND_STATUS_TYPE mvSataExecuteScsiCommand(MV_SATA_SCSI_CMD_BLOCK *pMvSataScsiCmdBlock);
+
+    MV_VOID     mvSataScsiSetDriveReady(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
+                                        MV_U8   channelIndex, MV_U8 PMPort,
+                                        MV_BOOLEAN  isReady);
+
+    MV_VOID mvSataScsiNotifyUA(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
+                               MV_U8    channelIndex, MV_U8 PMPort);
+
+/* Locals */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __IsNCmvScsiAtaLayer */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/Kconfig
new file mode 100755
index 0000000..6e4c68f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/Kconfig
@@ -0,0 +1,14 @@
+menu "Marvell SDIO\MMC driver"

+	depends on MV_INCLUDE_SDIO

+

+

+config MMC_MVSDMMC

+	tristate "Marvell SDIO host driver"

+	depends on MMC && MV_INCLUDE_SDIO

+	---help---

+	  This selects the Marvell SDIO host driver

+	  say Y or M here.

+	  If unsure, say N.

+

+endmenu

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/Makefile
new file mode 100755
index 0000000..e14b3ef
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/Makefile
@@ -0,0 +1,8 @@
+#

+# Makefile for the Marvell Audio ALSA Device Driver

+#

+ifeq ($(CONFIG_ARCH_FEROCEON),y)

+	include $(srctree)/$(MACHINE)/config/mvRules.mk

+endif

+

+obj-$(CONFIG_MMC_MVSDMMC)	+= mvsdmmc.o

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/mvsdmmc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/mvsdmmc.c
new file mode 100755
index 0000000..aeeb982
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/mvsdmmc.c
@@ -0,0 +1,1615 @@
+/*
+*
+* Marvell Orion SD\MMC\SDIO driver
+*
+* Author: Maen Suleiman
+* Copyright (C) 2008 Marvell Ltd.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+*/
+/*
+ * mvsdmmc TODO list:
+ *
+ * --> Set timeout value according to timeout_ns and timeout_clks,
+ *  meanwhile a maximum value is set for the host
+ *
+ * --> Report errors in mrq->data->stop->error and in mrq->data->error,
+ *  meanwhile errors are reported in the command itself since always the
+ *  completion of data and AutoCmd12 are done with the originated command.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include <linux/mbus.h>
+#endif
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/mmc/host.h>
+#include <linux/proc_fs.h>
+#include <linux/irq.h>
+
+
+#include <asm/dma.h>
+#include <asm/sizes.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include <asm/plat-orion/mvsdmmc-orion.h>
+#endif
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mvsdmmc.h"
+
+#undef MVSDMMC_DEBUG
+#undef MVSDMMC_DUMP_REGS_ON_CMD
+#define MVSDMMC_DUMP_ALL_REGS_ON_ERROR
+#define MVSDMMC_DBG_ERROR
+
+#undef MVSDMMC_DBG_FUNC_ENTRY
+#ifdef MVSDMMC_DBG_FUNC_ENTRY
+#define mvsdmmc_dbg_enter()	printk(KERN_DEBUG "ENTER <=%s\n",  __func__)
+#define mvsdmmc_dbg_exit()	printk(KERN_DEBUG "EXIT  <=%s\n",  __func__)
+#else
+#define mvsdmmc_dbg_enter()
+#define mvsdmmc_dbg_exit()
+#endif
+
+#undef MVSDMMC_WARN
+#ifdef MVSDMMC_WARN
+#define mvsdmmc_warning(host, fmt, arg...) 	\
+			dev_printk(KERN_INFO, &host->pdev->dev, fmt, ##arg) 
+#else 
+#define mvsdmmc_warning(host, a...) 
+#endif 
+#ifdef MVSDMMC_DEBUG
+#define mvsdmmc_debug(host, fmt, arg...) 	\
+			dev_printk(KERN_DEBUG, &host->pdev->dev, fmt, ##arg) 
+#else 
+#define mvsdmmc_debug(host, a...) 
+#endif
+
+#if defined(MVSDMMC_DBG_ERROR)
+#define mvsdmmc_debug_error(host, fmt, arg...)	\
+			  dev_printk(KERN_ERR, &host->pdev->dev, fmt, ##arg) 
+#else 
+#define mvsdmmc_debug_error(host, a...) 
+#endif
+
+#define DRIVER_NAME	"mvsdmmc"
+
+
+struct mvsdmmc_host_stat {
+
+	int total_requests;
+	int copied_data;
+	int total_data;
+	int unaligned_buf;
+	int cache_unaligned_buf;
+	int ints;
+	int error_ints;
+	int card_ints;
+	int unfinished_dma;
+	int buf_256;
+	int cmd_timeout;
+	int int_timeout;
+	int empty_int;
+	int first_int_status;
+	int first_error_status;
+	int detect_int;
+	int first_err_int;	/* request number of first error interrupt */
+	int first_unfinished_dma;/* request number of first unfinished dma */ 
+};
+
+struct mvsdmmc_host {
+	struct mmc_host		*mmc;		/* associated mmc structure */
+	struct platform_device	*pdev;		/* platform device */
+	spinlock_t		lock;		/* spin lock of the host */
+	struct resource		*res;		/* resource for IRQ and base */
+	void __iomem		*base;		/* base address of the host
+						 *  registers
+						 */
+	int			irq;		/* host IRQ number */
+	int			irq_detect;	/* host IRQ number for
+						 * insertion/detection
+						 */
+	char			*dma_buffer;	/* virtual address for
+						temp buffer*/
+	dma_addr_t		dma_addr;	/* Physical address for
+						remp buffer */
+	unsigned int		dma_len;	/* sg fragments number
+						 * of the request
+						 */
+	int			size;		/* Total size of transfer */
+	unsigned char		power_mode;	/* power status */
+	struct mmc_request	*mrq;		/* current mmc request
+						 *  structure
+						 */
+	struct mmc_command	*cmd;		/* current mmc command
+						 * structure
+						 */
+	struct mmc_data		*data;		/* current mmc data structure */
+	unsigned short		intr_status;	/* interrupt status on IRQ */
+	unsigned short		intr_en;	/* enabled interrupts
+						 * during command- status
+						 */
+	unsigned short		intr_cmd;	/* enabled interrupts
+						 * during command
+						 */
+	unsigned int		cmd_data;	/* if cmd\data are proccesed */
+	#define	MVSDMMC_CMD	0x1
+	#define	MVSDMMC_DATA	0x2
+	#define	MVSDMMC_CMD12	0x4
+	unsigned int		pending_commands;/* commands on process*/
+	int			card_present;	/* if card present*/
+	struct timer_list	timer;		/* Timer for timeouts */
+	unsigned int		copy_buf;	/* copy to host buffer*/
+	unsigned int		bad_size;	/* unaligned size */
+	struct mvsdmmc_host_stat	stat;	/* host statistics */
+};
+
+
+static int maxfreq = MVSDMMC_CLOCKRATE_MAX; 
+static int highspeed = 1;
+static int detect = 1;
+static int dump_on_error;
+
+static void mvsdmmc_request_done(struct mvsdmmc_host *host);
+static void mvsdmmc_power_down(struct mmc_host *mmc);
+static void mvsdmmc_power_up(struct mmc_host *mmc);
+static void mvsdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
+
+static inline void mvsdmmc_sg_to_dma(struct mvsdmmc_host *host,
+				     struct mmc_data *data);
+static inline void mvsdmmc_dma_to_sg(struct mvsdmmc_host *host,
+				     struct mmc_data *data);
+static irqreturn_t mvsdmmc_irq(int irq, void *dev);
+static irqreturn_t mvsdmmc_irq_detect(int irq, void *dev);
+
+#define mvsdmmc_writew(host, offs, val)	\
+		writew((val), (host->base + offs))
+
+
+static inline unsigned short mvsdmmc_readw(struct mvsdmmc_host *host,
+					   unsigned short offs)
+{
+	unsigned short val = readw((host->base + offs));
+	return (val);
+}
+
+#define mvsdmmc_bitset(host, offs, bitmask)	\
+		writew((readw(host->base + offs) | (bitmask)),	\
+			host->base + offs)
+
+#define mvsdmmc_bitreset(host, offs, bitmask)	\
+		writew((readw(host->base + offs) & (~(bitmask))),	\
+			host->base + offs)
+
+int mvsdmmc_read_procmem(char *buf, char **start, off_t offset,
+			 int count, int *eof, void *data) 
+{
+
+	int len = 0;
+	struct mvsdmmc_host *host = (struct mvsdmmc_host *)data;
+
+	len += sprintf(buf+len, "\ntotal requests=%d\n",
+		host->stat.total_requests);
+	len += sprintf(buf+len, "total data=%d\n",
+		host->stat.total_data);
+	len += sprintf(buf+len, "copied data=%d\n", host->stat.copied_data);
+	len += sprintf(buf+len, "buffers small than 256=%d\n",
+		host->stat.buf_256);
+	len += sprintf(buf+len, "buffers not word aligned=%d\n",
+			 host->stat.unaligned_buf);
+	len += sprintf(buf+len, "buffers not cache line aligned=%d\n",
+			host->stat.cache_unaligned_buf);
+	len += sprintf(buf+len, "total interrupts=%d\n", host->stat.ints);
+	len += sprintf(buf+len, "total card ints=%d\n", host->stat.card_ints);
+	len += sprintf(buf+len, "total error ints=%d\n", host->stat.error_ints);
+	len += sprintf(buf+len, "Request num of first error int=%d\n",
+			host->stat.first_err_int);
+	len += sprintf(buf+len, "Status of int on first error int=0x%x\n",
+			(unsigned int)host->stat.first_int_status);
+	len += sprintf(buf+len, "Status of first error int=0x%x\n",
+			(unsigned int)host->stat.first_error_status);
+	len += sprintf(buf+len, "Empty interrupts=%d\n", host->stat.empty_int);
+	len += sprintf(buf+len, "Detect interrupts=%d\n",
+				host->stat.detect_int);
+	len += sprintf(buf+len, "Unifinished dma=%d\n",
+		host->stat.unfinished_dma);
+	len += sprintf(buf+len, "Request num of first unfinished dma=%d\n",
+			host->stat.first_unfinished_dma);
+	len += sprintf(buf+len, "interrupt timeouts=%d\n",
+		host->stat.int_timeout);
+	len += sprintf(buf+len, "command timeouts=%d\n",
+					host->stat.cmd_timeout);
+
+	*eof = 1;
+
+	memset(&host->stat , sizeof(struct mvsdmmc_host_stat), 0);
+
+	return len;
+
+}
+
+static void mvsdmmc_dump_registers(struct mvsdmmc_host *host,
+				   unsigned short cmdreg)
+{
+	unsigned int reg;
+
+	for (reg = SDIO_SYS_ADDR_LOW; reg <= SDIO_AUTO_RSP2; reg += 4) {
+		if (reg == SDIO_CMD) {
+			mvsdmmc_debug(host, "reg 0x%x = 0x%x \n", reg,
+				      (unsigned int)cmdreg);
+			continue;
+		}
+
+		mvsdmmc_debug(host, "reg 0x%x = 0x%x \n", reg,
+			      (unsigned int)mvsdmmc_readw(host, reg));
+	}
+	for (reg = 0x100; reg <= 0x130; reg += 4) {
+		mvsdmmc_debug(host, "reg 0x%x = 0x%x \n", reg,
+			      (unsigned int)mvsdmmc_readw(host, reg));
+	}
+}
+
+
+static inline u32 mvsdmmc_aligned_size(u32 size)
+{
+	return ((size + 3) / 4) * 4;
+}
+
+/*
+ * Tx alignment. This is a workaround for problems with
+ * data sizes which are not 4-bytes aligned.
+ * Currently this function only works for LSB_FIRST=0.
+ */
+static void mvsdmmc_align_tx_data(struct mvsdmmc_host *host,
+					struct mmc_data *data)
+{
+	u32 size = data->blocks * data->blksz;
+	u32 aligned_size = mvsdmmc_aligned_size(size);
+	u8 *ptr = (u8 *)sg_virt_addr(data->sg);
+	u8 *end = ptr + aligned_size-4;
+	u32 remainder = size%4;
+	u8 tmp[4];
+
+	if (!remainder)
+		return;
+
+	data->sg->length = aligned_size;
+	memcpy(tmp, end, 4);
+	memset(end, 0, 4);
+	memcpy(end+4-remainder, tmp, remainder);
+}
+
+
+/*
+ * Rx alignment. This is a workaround for problems with
+ * data sizes which are not 4-bytes aligned.
+ * Currently this function only works for LSB_FIRST=0
+ */
+static void mvsdmmc_align_rx_data(struct mvsdmmc_host *host,
+					struct mmc_data *data)
+{
+	u32 size = data->blocks * data->blksz;
+	u32 aligned_size = mvsdmmc_aligned_size(size);
+	u8 *ptr = (u8 *)sg_virt_addr(data->sg);
+	u8 *end = ptr + aligned_size-4;
+	u32 remainder = size%4;
+	u8 tmp[4];
+
+	if (!remainder)
+		return;
+
+	data->sg->length = aligned_size;
+	memcpy(tmp, end, 4);
+	memset(end, 0, 4);
+	memcpy(end, &tmp[4-remainder], remainder);
+}
+
+
+
+
+
+
+static void mvsdmmc_stop_clock(struct mvsdmmc_host *host)
+{
+
+	mvsdmmc_dbg_enter();
+	mvsdmmc_bitset(host, SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK);
+	mvsdmmc_dbg_exit();
+}
+
+static void __mvsdmmc_enable_irq(struct mvsdmmc_host *host, unsigned int mask)
+{
+	host->intr_en |= mask;
+	mvsdmmc_writew(host, SDIO_NOR_INTR_EN, host->intr_en);
+	host->intr_cmd |= mask; /* intr_cmd is zeroed in mvsdmmc_start_cmd */
+	if (mask == SDIO_NOR_CARD_INT)
+		mvsdmmc_bitset(host, SDIO_XFER_MODE,
+			       SDIO_XFER_MODE_INT_CHK_EN);
+}
+static void mvsdmmc_enable_irq(struct mvsdmmc_host *host, unsigned int mask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	__mvsdmmc_enable_irq(host, mask);
+	spin_unlock_irqrestore(&host->lock, flags); 
+}
+
+static void __mvsdmmc_disable_irq(struct mvsdmmc_host *host, unsigned int mask)
+{
+	host->intr_en &= ~mask;
+	mvsdmmc_writew(host, SDIO_NOR_INTR_EN, host->intr_en);
+	if (mask == SDIO_NOR_CARD_INT)
+		mvsdmmc_bitreset(host, SDIO_XFER_MODE,
+				 SDIO_XFER_MODE_INT_CHK_EN);
+}
+
+static void mvsdmmc_disable_irq(struct mvsdmmc_host *host, unsigned int mask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	__mvsdmmc_disable_irq(host, mask);
+	spin_unlock_irqrestore(&host->lock, flags); 
+}
+
+static void mvsdmmc_setup_data(struct mvsdmmc_host *host, struct mmc_data *data)
+{
+	char	*virt_addr = NULL;
+	dma_addr_t	phys_addr = 0;
+	u32		reg;
+
+	mvsdmmc_dbg_enter();
+
+	host->stat.total_data++;
+
+	/*
+	 * Calculate size.
+	 */
+	host->size = data->blocks * data->blksz;
+
+	host->bad_size = 0;
+
+	host->copy_buf = 0;
+	
+	if (data->flags & MMC_DATA_READ) {
+
+		if (host->size & 0x3)
+			mvsdmmc_align_rx_data(host, data);
+
+		host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+					   data->sg_len,
+					   DMA_FROM_DEVICE);
+
+		BUG_ON(host->dma_len == 0);
+		phys_addr = sg_dma_address(data->sg);
+
+		if (host->dma_len > 1) {
+			host->copy_buf = 1;
+		}
+	}
+
+	if (data->flags & MMC_DATA_WRITE) {
+
+		if (host->size & 0x3)
+			mvsdmmc_align_tx_data(host, data);
+
+		host->dma_len = dma_map_sg(mmc_dev(host->mmc),
+					   data->sg, data->sg_len,
+					   DMA_TO_DEVICE);
+		BUG_ON(host->dma_len == 0);
+		phys_addr = sg_dma_address(data->sg);
+
+		if (host->dma_len > 1)
+			host->copy_buf = 1;
+	}
+
+	if (phys_addr & 0x3)
+		host->copy_buf = 1;
+
+	reg = mvsdmmc_readw(host, SDIO_HOST_CTRL);
+	
+	if (host->bad_size) {
+		reg &= ~SDIO_HOST_CTRL_BIG_ENDIAN;
+		host->copy_buf = 1;
+	} else {
+		reg |= SDIO_HOST_CTRL_BIG_ENDIAN;
+	}
+	mvsdmmc_writew(host, SDIO_HOST_CTRL, reg);
+
+        if (host->copy_buf) {
+
+			virt_addr = host->dma_buffer;
+			phys_addr = host->dma_addr;
+	}
+
+	BUG_ON(host->size > MVSDMMC_DMA_SIZE);
+
+	if ((data->flags & MMC_DATA_WRITE) && (host->copy_buf)) {
+		/*
+		* Transfer data from the SG list to
+		* the DMA buffer.
+		*/
+		BUG_ON(virt_addr == NULL);
+		mvsdmmc_sg_to_dma(host, data);
+		dma_sync_single_for_device(mmc_dev(host->mmc),
+					host->dma_addr,
+					mvsdmmc_aligned_size(host->size),
+					DMA_TO_DEVICE);
+
+	} else if ((data->flags & MMC_DATA_READ) && (host->copy_buf)) {
+
+		dma_sync_single_for_device(mmc_dev(host->mmc),
+					host->dma_addr,
+					mvsdmmc_aligned_size(host->size),
+					DMA_FROM_DEVICE);
+	}
+
+	mvsdmmc_writew(host, SDIO_BLK_COUNT, data->blocks);
+	mvsdmmc_writew(host, SDIO_SYS_ADDR_LOW,
+		       (0xffff & ((unsigned int)phys_addr)));
+	mvsdmmc_writew(host, SDIO_SYS_ADDR_HI,
+		       (0xffff & (((unsigned int)phys_addr) >> 16)));
+
+	mvsdmmc_writew(host, SDIO_BLK_SIZE, data->blksz);
+
+	mvsdmmc_dbg_exit();
+
+}
+
+static void mvsdmmc_start_cmd(struct mvsdmmc_host *host,
+			      struct mmc_command *cmd)
+{
+
+	struct mmc_data		*data = host->mrq->data;
+	struct mmc_request	*mrq = cmd->mrq;
+	unsigned short cmdreg = 0, xfer = 0;
+	unsigned short intr_enable = 0;
+
+	mvsdmmc_dbg_enter();
+	BUG_ON(host->cmd_data);
+	BUG_ON(host->cmd == NULL);
+
+	/* disable interrupts */
+	mvsdmmc_writew(host, SDIO_ERR_INTR_EN, 0);
+	/* clear error status */
+	mvsdmmc_writew(host, SDIO_ERR_INTR_STATUS,
+			mvsdmmc_readw(host, SDIO_ERR_INTR_STATUS));
+
+	BUG_ON(host->intr_en & ~SDIO_NOR_CARD_INT);
+
+	/* reset host->intr_cmd*/
+	host->intr_cmd = 0;
+
+	if (cmd->flags != MMC_RSP_NONE) {
+		intr_enable |= SDIO_NOR_UNEXP_RSP;
+		cmdreg |= SDIO_UNEXPECTED_RESP;
+	}
+	if (cmd->flags & MMC_RSP_OPCODE)
+		cmdreg |= SDIO_CMD_INDX_CHECK;
+
+
+	if (cmd->flags == MMC_RSP_NONE)
+		cmdreg |= SDIO_CMD_RSP_NONE;
+	else if (cmd->flags & MMC_RSP_BUSY)
+		cmdreg |= SDIO_CMD_RSP_48BUSY;
+	else if (cmd->flags & MMC_RSP_136)
+		cmdreg |= SDIO_CMD_RSP_136;
+	else if (cmd->flags & MMC_RSP_PRESENT)
+		cmdreg |= SDIO_CMD_RSP_48;
+
+	if (cmd->flags & MMC_RSP_CRC)
+		cmdreg |= (SDIO_CMD_CHECK_CMDCRC);
+
+	if (data) {
+		host->data = mrq->data;
+		mvsdmmc_setup_data(host, mrq->data);
+
+		/* if multiple blocks and need AutoCMD12*/
+		if (data->stop) {
+			struct mmc_command *stop = data->stop;
+			mvsdmmc_writew(host, SDIO_AUTOCMD12_ARG_LOW,
+				       stop->arg & 0xffff);
+			mvsdmmc_writew(host, SDIO_AUTOCMD12_ARG_HI,
+				       stop->arg >> 16);
+			mvsdmmc_writew(host, SDIO_AUTOCMD12_INDEX,
+				       (stop->opcode << 8) | 3);
+			/* enable autocmd12 interrupt*/
+			intr_enable |= SDIO_NOR_AUTOCMD12_DONE;
+
+			xfer |= SDIO_XFER_MODE_AUTO_CMD12;
+			host->cmd_data = (MVSDMMC_CMD | MVSDMMC_CMD12);
+		} else {
+			/* enable data interrupt*/
+			intr_enable |= SDIO_NOR_DMA_INI;
+			host->cmd_data = (MVSDMMC_CMD|MVSDMMC_DATA);
+		}
+
+		/* default values */
+		cmdreg |= SDIO_CMD_CHECK_DATACRC16;
+		cmdreg |= SDIO_CMD_DATA_PRESENT;
+		xfer |= SDIO_XFER_MODE_HW_WR_DATA_EN;
+
+		if (data->flags & MMC_DATA_READ)
+			xfer |= SDIO_XFER_MODE_TO_HOST;
+		else if (data->flags & MMC_DATA_WRITE)
+			xfer &= ~SDIO_XFER_MODE_TO_HOST;
+	} else {
+		intr_enable |= SDIO_NOR_CMD_DONE;
+		cmdreg &= ~SDIO_CMD_DATA_PRESENT;
+		host->cmd_data = MVSDMMC_CMD;
+	}
+
+	if (host->intr_en & SDIO_NOR_CARD_INT)
+		xfer |= SDIO_XFER_MODE_INT_CHK_EN;
+
+	cmdreg |= ((cmd->opcode & 0xff) << 0x8);
+
+	mvsdmmc_writew(host, SDIO_ARG_LOW, cmd->arg & 0xffff);
+	mvsdmmc_writew(host, SDIO_ARG_HI, cmd->arg >> 16);
+	mvsdmmc_writew(host, SDIO_XFER_MODE, xfer);
+
+	/* start timer */
+	mod_timer(&host->timer, jiffies + 5 * HZ);
+
+	__mvsdmmc_enable_irq(host, intr_enable);
+
+	host->pending_commands++;
+
+	/* enable error interrupts*/
+	mvsdmmc_writew(host, SDIO_ERR_INTR_EN, 0xffff); 
+#if defined(MVSDMMC_DUMP_REGS_ON_CMD)
+	mvsdmmc_debug_error(host, "================================>\n");
+	mvsdmmc_debug_error(host, "CMD%d Start \n", host->cmd->opcode);
+	mvsdmmc_dump_registers(host, cmdreg);
+#endif
+	mvsdmmc_writew(host, SDIO_CMD, cmdreg);
+
+	BUG_ON(host->intr_en == 0);
+	BUG_ON(host->intr_en == SDIO_NOR_UNEXP_RSP);
+
+}
+
+
+static void mvsdmmc_finish_data(struct mvsdmmc_host *host) {
+	char				*virt_addr;
+	struct mmc_data	*data = host->data;
+	u32		blocks_left;
+	unsigned short response[3], resp_indx = 0;
+
+
+	BUG_ON(data == NULL);
+	BUG_ON(!(host->intr_status & SDIO_NOR_AUTOCMD12_DONE) &&
+		!(host->intr_status & SDIO_NOR_DMA_INI));
+
+	if (host->intr_status & SDIO_NOR_AUTOCMD12_DONE) {
+		host->cmd_data &= ~MVSDMMC_CMD12;
+		host->intr_status &= ~(SDIO_NOR_AUTOCMD12_DONE);
+	} else if (host->intr_status & SDIO_NOR_DMA_INI) {
+		host->cmd_data &= ~MVSDMMC_DATA;
+		host->intr_status &= ~(SDIO_NOR_DMA_INI);
+	}
+
+	if (!host->copy_buf)
+		BUG_ON(host->dma_len == 0);
+
+	if ((data->flags & MMC_DATA_READ) && (host->copy_buf)) {
+
+		virt_addr = host->dma_buffer;
+		BUG_ON(virt_addr == NULL);
+		dma_sync_single_for_cpu(mmc_dev(host->mmc),
+					host->dma_addr,
+					host->size,
+					DMA_FROM_DEVICE);
+
+		/*
+		* Transfer data from DMA buffer to
+		* SG list.
+		*/
+		mvsdmmc_dma_to_sg(host, data);
+
+		mvsdmmc_align_rx_data(host, data);
+
+	} else if ((data->flags & MMC_DATA_WRITE) && (host->copy_buf)) {
+
+		dma_sync_single_for_cpu(mmc_dev(host->mmc),
+					host->dma_addr,
+					host->size,
+					DMA_TO_DEVICE);
+
+	}
+
+	if ((!host->copy_buf) && (data->flags & MMC_DATA_READ))
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
+			     DMA_FROM_DEVICE);
+
+	if ((!host->copy_buf) && (data->flags & MMC_DATA_WRITE))
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
+			     DMA_TO_DEVICE);
+
+	/* check how much data was transfered */
+	blocks_left = mvsdmmc_readw(host, SDIO_CURR_BLK_LEFT);
+	if (blocks_left) {
+		u32 bytes_left = mvsdmmc_readw(host, SDIO_CURR_BYTE_LEFT);
+		data->bytes_xfered = host->size -
+			(((blocks_left - 1) * data->blksz) + bytes_left);
+	} else {
+		data->bytes_xfered = host->size;
+	}
+
+	/* Handle Auto cmd 12 response */
+	if (data->stop) {
+
+		for (resp_indx = 0 ; resp_indx < 3; resp_indx++)
+			response[resp_indx] =
+				mvsdmmc_readw(host, SDIO_AUTO_RSP(resp_indx));
+
+		memset(data->stop->resp, 0, 4 * sizeof(data->stop->resp[0]));
+
+		data->stop->resp[0] = ((response[2] & 0x3f) << (8 - 8)) |
+			((response[1] & 0xffff) << (14 - 8)) |
+			((response[0] & 0x3ff) << (30 - 8));
+		data->stop->resp[1] = ((response[0] & 0xfc00) >> 10);
+
+	}
+
+
+	if (data->bytes_xfered != host->size) {
+		host->stat.unfinished_dma++;
+
+		if (host->stat.unfinished_dma == 1)
+			host->stat.first_unfinished_dma =
+				host->stat.total_requests;
+
+		mvsdmmc_warning(host, "data transfere not complete\n");
+		mvsdmmc_warning(host, "data transfered =%d"
+					  "original size= %d\n",
+					data->bytes_xfered, host->size);
+	}
+
+	host->data = NULL;
+}
+
+static void mvsdmmc_finish_cmd(struct mvsdmmc_host *host) {
+	unsigned short response[8], resp_indx = 0;
+	struct mmc_command	*cmd = host->cmd;
+
+	host->intr_status &= ~(SDIO_NOR_CMD_DONE);
+	host->cmd_data &= ~MVSDMMC_CMD;
+
+	for (resp_indx = 0 ; resp_indx < 8; resp_indx++)
+		response[resp_indx] = mvsdmmc_readw(host, SDIO_RSP(resp_indx));
+
+	memset(cmd->resp, 0, 4 * sizeof(cmd->resp[0]));
+
+	if (cmd->flags & MMC_RSP_136) {
+		cmd->resp[3] = ((response[7] & 0x3fff) << 8)	|
+			((response[6] & 0x3ff) << 22);
+		cmd->resp[2] = ((response[6] & 0xfc00) >> 10)	|
+			((response[5] & 0xffff) << 6)	|
+			((response[4] & 0x3ff) << 22);
+		cmd->resp[1] = ((response[4] & 0xfc00) >> 10)	|
+			((response[3] & 0xffff) << 6)	|
+			((response[2] & 0x3ff) << 22);
+		cmd->resp[0] = ((response[2] & 0xfc00) >> 10)	|
+			((response[1] & 0xffff) << 6)	|
+			((response[0] & 0x3ff) << 22);
+	} else  if (cmd->flags & MMC_RSP_PRESENT) {
+		cmd->resp[0] = ((response[2] & 0x3f) << (8 - 8)) |
+			((response[1] & 0xffff) << (14 - 8)) |
+			((response[0] & 0x3ff) << (30 - 8));
+		cmd->resp[1] = ((response[0] & 0xfc00) >> 10);
+	}
+}
+
+static unsigned int mvsdmmc_check_error(struct mvsdmmc_host *host) {
+	unsigned short		error_status;
+	unsigned int		error = 0;
+
+	error_status = mvsdmmc_readw(host, SDIO_NOR_INTR_STATUS);
+	/* make sure if there is an error*/
+	if (error_status & SDIO_NOR_UNEXP_RSP) {
+		error = -EPROTO;
+		mvsdmmc_warning(host, "SDIO_NOR_INTR_STATUS(0x%x)=0x%x"
+				    "\n", SDIO_NOR_INTR_STATUS, error_status);
+	} else if (error_status & SDIO_NOR_ERROR) {
+		/* clear error status*/
+		mvsdmmc_writew(host, SDIO_NOR_INTR_STATUS, SDIO_NOR_ERROR);
+
+		error_status = mvsdmmc_readw(host, SDIO_ERR_INTR_STATUS);
+
+		mvsdmmc_warning(host, "SDIO_ERR_INTR_STATUS(0x%x)=0x%x"
+				    "\n", SDIO_ERR_INTR_STATUS,
+				    error_status);
+
+		if (error_status & (SDIO_ERR_CMD_TIMEOUT |
+				    SDIO_ERR_DATA_TIMEOUT)) {
+			error = -ETIMEDOUT;
+		} else {
+			error = EILSEQ;
+		}
+	}
+
+	if (host->cmd)
+		host->cmd->error = error;
+
+	return error;
+}
+
+static void mvsdmmc_request_done(struct mvsdmmc_host *host) {
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command	*cmd = host->cmd;
+
+	if ((cmd->error) && (host->data)) {
+		char *virt_addr;
+		int i;
+
+		host->intr_status = host->intr_cmd;
+		__mvsdmmc_disable_irq(host, host->intr_cmd);
+		if (!host->copy_buf)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+			virt_addr = (char *)sg_virt(host->data->sg);
+#else
+			virt_addr = (char *)sg_virt_addr(host->data->sg);
+#endif
+		else
+			virt_addr = (char *)host->dma_buffer;
+
+		mvsdmmc_warning(host, "error: data size =%d, block size= %d "
+				    "block numbers=%d\n",
+				    host->size, host->data->blksz,
+				    host->data->blocks);
+
+		if (dump_on_error) {
+			for (i = 0 ; i < host->size ; i++) {
+				if (i % 32 == 0)
+					mvsdmmc_warning(host, "\n 0x%04X:",
+							    (unsigned int)i);
+				mvsdmmc_warning(host, "%02X ", *virt_addr++);
+			}
+		}
+		mvsdmmc_warning(host, "\n");
+		mvsdmmc_finish_data(host);
+	}
+
+	if ((cmd->error)) {
+
+		/* disable pending interrupts*/
+		__mvsdmmc_disable_irq(host, host->intr_cmd);
+		/* clear pending interrupts*/
+		mvsdmmc_writew(host, SDIO_NOR_INTR_STATUS, host->intr_cmd);
+
+		host->cmd_data = 0;
+		host->intr_status = 0;
+	}
+
+	host->mrq = NULL;
+	host->cmd = NULL;
+	host->pending_commands--;
+
+	mmc_request_done(host->mmc, mrq);
+}
+
+static irqreturn_t mvsdmmc_irq_detect(int irq, void *dev) 
+{
+	struct mmc_host *mmc = (struct mmc_host *)dev;
+	struct mvsdmmc_host *host = mmc_priv(mmc);
+
+	host->stat.detect_int++;
+	mmc_detect_change(mmc, msecs_to_jiffies(100));
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mvsdmmc_irq(int irq, void *dev) 
+{
+	struct mmc_host *mmc = (struct mmc_host *)dev;
+	struct mvsdmmc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+	int handled = IRQ_NONE;
+	int cardint = 0;
+	int cmd_data_int = 0;
+	unsigned int	error;
+
+	mvsdmmc_dbg_enter();
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->stat.ints++;
+
+	if (host->pending_commands)
+		del_timer(&host->timer);
+
+	/* first make sure if there is an error*/
+	error = mvsdmmc_check_error(host);
+
+
+#if defined(MVSDMMC_DUMP_REGS_ON_CMD)
+	if (host->cmd)  {
+		mvsdmmc_debug_error(host, "==============================>\n");
+		mvsdmmc_debug_error(host, "CMD%d Response \n",
+					host->cmd->opcode);
+		mvsdmmc_dump_registers(host,
+				       mvsdmmc_readw(host, SDIO_CMD));
+	}
+#endif
+
+	if (error) {
+
+		host->stat.error_ints++;
+
+		if (dump_on_error)
+			mvsdmmc_dump_registers(host, mvsdmmc_readw(host,
+								   SDIO_CMD));
+
+		if (host->stat.error_ints == 1) {
+			host->stat.first_err_int = host->stat.total_requests;
+			host->stat.first_int_status =
+				mvsdmmc_readw(host, SDIO_NOR_INTR_STATUS);
+			host->stat.first_error_status =
+				mvsdmmc_readw(host, SDIO_ERR_INTR_STATUS);
+		}
+
+		/* clear error interrupts*/
+		mvsdmmc_writew(host, SDIO_ERR_INTR_STATUS,
+				mvsdmmc_readw(host, SDIO_ERR_INTR_STATUS));
+
+		mvsdmmc_writew(host, SDIO_ERR_INTR_EN, 0);
+
+		mvsdmmc_warning(host, "command,data error \n");
+		handled = IRQ_HANDLED;
+		goto done;
+	}
+
+	/* read interrupts status */
+	host->intr_status = mvsdmmc_readw(host, SDIO_NOR_INTR_STATUS);
+	/* handle only enabled interrupts*/
+	host->intr_status &= mvsdmmc_readw(host, SDIO_NOR_INTR_EN);
+
+	/* disable pending interrupts*/
+	__mvsdmmc_disable_irq(host, host->intr_status);
+	/* clear pending interrupts*/
+	mvsdmmc_writew(host, SDIO_NOR_INTR_STATUS, host->intr_status);
+
+	if (host->intr_status & SDIO_NOR_CARD_INT) {
+		host->intr_status &= ~SDIO_NOR_CARD_INT;
+		host->stat.card_ints++;
+		cardint = 1;
+		handled = IRQ_HANDLED;
+	}
+
+	if (host->intr_status) {
+		cmd_data_int = 1;
+		if ((host->intr_status & SDIO_NOR_AUTOCMD12_DONE) ||
+			(host->intr_status & SDIO_NOR_DMA_INI)) {
+
+			mvsdmmc_finish_data(host);
+			/* if data only interrupt was enable,
+			 * then handle command now as well
+			 */
+			if (!(host->intr_cmd & SDIO_NOR_CMD_DONE))
+				mvsdmmc_finish_cmd(host);
+		}
+
+		if (host->intr_status & SDIO_NOR_CMD_DONE)
+			mvsdmmc_finish_cmd(host);
+
+		handled = IRQ_HANDLED;
+	}
+
+	if (cardint)
+		mmc_signal_sdio_irq(host->mmc);
+
+	if (handled != IRQ_HANDLED) {
+		/* clear interrupts*/
+		__mvsdmmc_disable_irq(host, 0xffff);
+		dev_printk(KERN_WARNING, &host->pdev->dev , "interrupt not handled!!! int status = 0x%x\n", mvsdmmc_readw(host, SDIO_NOR_INTR_STATUS));
+
+		mvsdmmc_writew(host, SDIO_NOR_INTR_STATUS,
+			       mvsdmmc_readw(host, SDIO_NOR_INTR_STATUS));
+
+		if ((host->cmd_data&MVSDMMC_DATA) && (host->data)) {
+			host->data->error = ETIMEDOUT;
+			host->intr_status = SDIO_NOR_DMA_INI; /* dummy */
+			mvsdmmc_finish_data(host);
+		}
+		if ((host->cmd_data&MVSDMMC_CMD) && (host->cmd)) {
+			host->cmd->error = ETIMEDOUT;
+			mvsdmmc_finish_cmd(host);
+		}
+
+		handled = IRQ_HANDLED;
+		host->stat.empty_int++;
+	}
+done:
+	if ((cmd_data_int) ||
+	    ((host->pending_commands) && (host->cmd->error))) {
+		/* Since we may and may not have SDIO_NOR_UNEXP_RSP interrupt
+		 * make sure SDIO_NOR_UNEXP_RSP cleared and disabled before next
+		 * command
+		 */
+		host->intr_status &= ~SDIO_NOR_UNEXP_RSP;
+		__mvsdmmc_disable_irq(host, SDIO_NOR_UNEXP_RSP);
+		mvsdmmc_bitset(host, SDIO_NOR_INTR_STATUS, SDIO_NOR_UNEXP_RSP);
+		mvsdmmc_request_done(host);
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	mvsdmmc_dbg_exit();
+	return handled;
+
+}
+
+static void mvsdmmc_timeout_timer(unsigned long data)
+{
+	struct mvsdmmc_host *host;
+	irqreturn_t retval;
+
+	host = (struct mvsdmmc_host *)data;
+
+	/* disable interrupts */
+	mvsdmmc_writew(host, SDIO_ERR_INTR_EN, 0);
+
+	host->stat.int_timeout++;
+	mvsdmmc_debug_error(host, "timeout for cmd%d\n",host->cmd->opcode);
+
+	mvsdmmc_bitset(host, SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK); 
+	mvsdmmc_bitset(host, SDIO_HOST_CTRL,
+			 SDIO_HOST_CTRL_HI_SPEED_EN);
+	mvsdmmc_bitreset(host, SDIO_HOST_CTRL,
+			 SDIO_HOST_CTRL_HI_SPEED_EN);
+	/* reset */
+	mvsdmmc_writew(host, SDIO_SW_RESET, 0x100);
+	/* enable the clock*/
+	mvsdmmc_bitreset(host, SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK); 
+
+	if (dump_on_error)
+		mvsdmmc_dump_registers(host, mvsdmmc_readw(host, SDIO_CMD));
+
+	if (host->pending_commands) {
+		mvsdmmc_debug_error(host, "timeout:trying to call interrupt routine\n");
+		/* first try to handle any pending interrupts*/
+		retval =  mvsdmmc_irq(0, (void *)host->mmc);
+	}
+}
+
+/* 32bit byte swap. For example 0x11223344 -> 0x44332211                    */
+#define MV_BYTE_SWAP_32BIT(X) ((((X)&0xff)<<24) |                       \
+                               (((X)&0xff00)<<8) |                      \
+                               (((X)&0xff0000)>>8) |                    \
+                               (((X)&0xff000000)>>24))
+
+static inline void swap_buf(void *buf, int size) {
+
+	int i, aligned_size = (size & 0x3)?((size & ~0x3) + 4):size;
+	u32 temp, *buf32 = (u32*)buf;
+
+	for (i = 0; i < aligned_size; i+=4) {
+		temp = *buf32;
+		*buf32 = MV_BYTE_SWAP_32BIT((temp));
+		buf32++;
+	}
+}
+
+static inline void mvsdmmc_sg_to_dma(struct mvsdmmc_host *host,
+					struct mmc_data *data)
+{
+	unsigned int len, i;
+	struct scatterlist *sg;
+	char *dmabuf = host->dma_buffer;
+	char *sgbuf;
+
+	sg = data->sg;
+	len = data->sg_len;
+
+	for (i = 0; i < len; i++) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+		sgbuf = (char *)sg_virt((&sg[i]));
+#else
+		sgbuf = (char *)sg_virt_addr((&sg[i]));
+#endif
+
+		memcpy(dmabuf, sgbuf, sg[i].length);
+		dmabuf += sg[i].length;
+	}
+	if (host->bad_size)
+		swap_buf(host->dma_buffer, host->size);
+}
+
+static inline void mvsdmmc_dma_to_sg(struct mvsdmmc_host *host,
+					struct mmc_data *data)
+{
+	unsigned int len, i;
+	struct scatterlist *sg;
+	char *dmabuf = host->dma_buffer;
+	char *sgbuf;
+
+	sg = data->sg;
+	len = data->sg_len;
+
+	if (host->bad_size)
+		swap_buf(host->dma_buffer, host->size);
+
+	for (i = 0; i < len; i++) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+		sgbuf = (char *)sg_virt((&sg[i]));
+#else
+		sgbuf = (char *)sg_virt_addr((&sg[i]));
+#endif
+		memcpy(sgbuf, dmabuf, sg[i].length);
+		dmabuf += sg[i].length;
+	}
+}
+
+
+static int mvsdmmc_dma_init(struct mmc_host *mmc)
+{
+	struct mvsdmmc_host *host = mmc_priv(mmc);
+
+	mvsdmmc_dbg_enter();
+
+	host->dma_buffer = NULL;
+	host->dma_addr = (dma_addr_t)NULL;
+
+	/*
+	* We need to allocate a special buffer in
+	* order for SDIO host to be able to DMA to it.
+	*/
+
+	host->dma_buffer = kmalloc(MVSDMMC_DMA_SIZE,
+		GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN);
+
+	if (!host->dma_buffer)
+		goto err;
+
+	/*
+	* Translate the address to a physical address.
+	*/
+
+	host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
+		MVSDMMC_DMA_SIZE, DMA_BIDIRECTIONAL);
+
+	/*
+	* SDIO host DMA must be aligned on a 4 byte basis.
+	*/
+	if ((host->dma_addr & 0x3) != 0) {
+
+		mvsdmmc_warning(host, "mvsdmmc: dma alignment error\n");
+		goto kfree;
+	}
+
+
+
+	mvsdmmc_dbg_exit();
+	return 0;
+kfree:
+	/*
+	 * If we've gotten here then there is some kind of alignment bug
+	 */
+
+	dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
+		MVSDMMC_DMA_SIZE, DMA_BIDIRECTIONAL);
+	host->dma_addr = (dma_addr_t)NULL;
+
+	kfree(host->dma_buffer);
+	host->dma_buffer = NULL;
+
+	return -ENOMEM;
+
+err:
+	printk(KERN_WARNING DRIVER_NAME ": Unable to allocate DMA %d. "
+		"Falling back on FIFO.\n", (unsigned int)host->dma_buffer);
+
+	return -ENOMEM;
+
+}
+
+
+static void mvsdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 
+{
+	struct mvsdmmc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	WARN_ON(host->mrq != NULL);
+
+	host->stat.total_requests++;
+
+	BUG_ON(host->pending_commands == 1);
+
+	host->mrq = mrq;
+	host->cmd = mrq->cmd;
+	host->data = mrq->data;
+
+	mvsdmmc_start_cmd(host, mrq->cmd);
+
+	spin_unlock_irqrestore(&host->lock, flags); 
+
+	mvsdmmc_dbg_exit();
+
+}
+
+static void mvsdmmc_set_clock(struct mmc_host *mmc, unsigned int clock)
+{
+	struct mvsdmmc_host *host = mmc_priv(mmc);
+	unsigned int m;
+	mvsdmmc_dbg_enter();
+
+	BUG_ON(clock == 0);
+
+	if(MV_6183_DEV_ID == mvCtrlModelGet())
+		m = MVSDMMC_BASE_FAST_CLOCK_ORION/(2*clock) - 1;
+	else
+		m = MVSDMMC_BASE_FAST_CLOCK_KW/(2*clock) - 1;
+
+	mvsdmmc_debug(host, "mvsdmmc_set_clock: dividor = 0x%x clock=%d\n",
+		      m, clock);
+
+	mvsdmmc_writew(host, SDIO_CLK_DIV, m & 0x7ff);
+
+	msleep(10);
+
+	mvsdmmc_dbg_exit();
+}
+
+static void mvsdmmc_power_up(struct mmc_host *mmc)
+{
+	unsigned int reg;
+	struct mvsdmmc_host *host = mmc_priv(mmc);
+
+
+	mvsdmmc_dbg_enter();
+
+	reg = mvsdmmc_readw(host, SDIO_HOST_CTRL);
+	/* set sd-mem only*/
+	reg &= ~SDIO_HOST_CTRL_CARD_TYPE_MASK;
+	reg |= SDIO_HOST_CTRL_CARD_TYPE_MASK;
+
+	/* set big endian */
+	reg |= SDIO_HOST_CTRL_BIG_ENDIAN;
+	reg &= ~SDIO_HOST_CTRL_LSB_FIRST;
+
+	/* set maximum timeout */
+	reg &= ~SDIO_HOST_CTRL_TMOUT_MASK;
+	reg |= SDIO_HOST_CTRL_TMOUT_MAX;
+	reg |= SDIO_HOST_CTRL_TMOUT_EN;
+	mvsdmmc_writew(host, SDIO_HOST_CTRL, reg);
+
+	mvsdmmc_writew(host, SDIO_NOR_STATUS_EN, 0xffff);
+	mvsdmmc_writew(host, SDIO_ERR_STATUS_EN, 0xffff);
+	mvsdmmc_writew(host, SDIO_NOR_INTR_EN, 0);
+	mvsdmmc_writew(host, SDIO_NOR_INTR_STATUS, 0xffff);
+
+	mvsdmmc_bitreset(host, SDIO_HOST_CTRL,
+			 SDIO_HOST_CTRL_HI_SPEED_EN);
+
+	/* reset */
+	mvsdmmc_writew(host, SDIO_SW_RESET, 0x100);
+	msleep(50);
+
+
+	/* enable the clock*/
+	mvsdmmc_bitreset(host, SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK);
+	mvsdmmc_dbg_exit();
+}
+static void mvsdmmc_power_down(struct mmc_host *mmc)
+{
+	struct mvsdmmc_host *host = mmc_priv(mmc);
+
+	mvsdmmc_dbg_enter();
+	/* stop the clock*/
+	mvsdmmc_bitset(host, SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK);
+	mvsdmmc_writew(host, SDIO_NOR_STATUS_EN, 0);
+	mvsdmmc_writew(host, SDIO_ERR_STATUS_EN, 0);
+	mvsdmmc_writew(host, SDIO_NOR_INTR_EN, 0);
+	mvsdmmc_writew(host, SDIO_NOR_INTR_STATUS, 0xffff);
+
+	mvsdmmc_dbg_exit();
+}
+
+
+
+static void mvsdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct mvsdmmc_host *host = mmc_priv(mmc);
+	
+	mvsdmmc_dbg_enter();
+	
+	mvsdmmc_debug(host, "setting clock to %d\n", ios->clock);
+	if (ios->clock)
+		mvsdmmc_set_clock(mmc, ios->clock);
+	else
+		mvsdmmc_stop_clock(host);
+
+	if ((ios->power_mode == MMC_POWER_UP) &&
+	    (host->power_mode != MMC_POWER_UP)) {
+
+		mvsdmmc_debug(host, "power up\n");
+		mvsdmmc_power_up(mmc);
+		host->power_mode = MMC_POWER_UP;
+	}
+
+	if ((ios->power_mode == MMC_POWER_OFF) &&
+	    (host->power_mode != MMC_POWER_OFF)) {
+
+		mvsdmmc_debug(host, " power off\n");
+		mvsdmmc_power_down(mmc);
+		host->power_mode = MMC_POWER_OFF;
+	}
+
+	if ((ios->power_mode == MMC_POWER_ON) &&
+	    (host->power_mode != MMC_POWER_ON)) {
+
+		mvsdmmc_debug(host, " power on\n");
+		host->power_mode = MMC_POWER_ON;
+	}
+
+	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
+		mvsdmmc_debug(host, " set bus mode to opendrain\n");
+		mvsdmmc_bitreset(host, SDIO_HOST_CTRL,
+				 SDIO_HOST_CTRL_PUSH_PULL_EN);
+	} else if (ios->bus_mode == MMC_BUSMODE_PUSHPULL) {
+
+		mvsdmmc_debug(host, " set bus mode to pushpull\n");
+		mvsdmmc_bitset(host, SDIO_HOST_CTRL,
+				SDIO_HOST_CTRL_PUSH_PULL_EN);
+	}
+
+	if (ios->bus_width == MMC_BUS_WIDTH_1) {
+		mvsdmmc_debug(host, " set width x1\n");
+		mvsdmmc_bitreset(host, SDIO_HOST_CTRL,
+				 SDIO_HOST_CTRL_DATA_WIDTH_4_BITS);
+	} else if (ios->bus_width == MMC_BUS_WIDTH_4) {
+		mvsdmmc_debug(host, " set width x4\n");
+		mvsdmmc_bitset(host, SDIO_HOST_CTRL,
+			       SDIO_HOST_CTRL_DATA_WIDTH_4_BITS);
+	}
+
+	mvsdmmc_dbg_exit();
+}
+
+static void mvsdmmc_enable_sdio_irq(struct mmc_host *host, int enable)
+{
+	struct mvsdmmc_host *mvsdmmc_host = mmc_priv(host);
+	if (enable)
+		mvsdmmc_enable_irq(mvsdmmc_host, SDIO_NOR_CARD_INT);
+	else
+		mvsdmmc_disable_irq(mvsdmmc_host, SDIO_NOR_CARD_INT);
+}
+
+static const struct mmc_host_ops mvsdmmc_ops = {
+	.request	= mvsdmmc_request,
+	.get_ro		= NULL,
+	.set_ios	= mvsdmmc_set_ios,
+	.enable_sdio_irq	= mvsdmmc_enable_sdio_irq,
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+static void mv_conf_mbus_windows(struct mvsdmmc_host *host,
+				 struct mbus_dram_target_info *dram) {
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		writel(0, host->base + WINDOW_CTRL(i));
+		writel(0, host->base + WINDOW_BASE(i));
+	}
+
+	for (i = 0; i < dram->num_cs; i++) {
+		struct mbus_dram_window *cs = dram->cs + i;
+		writel(((cs->size - 1) & 0xffff0000) |
+		       (cs->mbus_attr << 8) |
+		       (dram->mbus_dram_target_id << 4) | 1,
+		       host->base + WINDOW_CTRL(i));
+		writel(cs->base, host->base + WINDOW_BASE(i));
+	}
+}
+#endif
+
+static int mvsdmmc_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = NULL;
+	struct mvsdmmc_host *host = NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+	const struct orion_mvsdmmc_data *mv_platform_data;
+#endif
+	struct resource *r;
+	int ret = 0, irq = NO_IRQ;
+	int irq_detect = NO_IRQ;
+
+	mvsdmmc_dbg_enter();
+
+	BUG_ON(pdev == NULL);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENXIO;
+
+	r = request_mem_region(r->start, SZ_1K, DRIVER_NAME);
+	if (!r)
+		return -EBUSY;
+
+	irq = platform_get_irq(pdev, 0);
+
+	if (irq == NO_IRQ) {
+		ret = -ENXIO;
+		goto out;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+	mv_platform_data = pdev->dev.platform_data;
+#endif
+
+	printk( DRIVER_NAME ": irq =%d start %x\n", irq, r->start);
+
+	if (detect) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+		irq_detect = mv_platform_data->detect_irq;
+#else
+		irq_detect = platform_get_irq(pdev, 1);
+#endif
+
+		if (irq_detect == NO_IRQ) {
+			detect = 0;
+			printk( DRIVER_NAME ": no IRQ detect\n");
+		}
+		else
+			printk( DRIVER_NAME ": irq_detect=%d\n", irq_detect);
+	}
+
+
+	mmc = mmc_alloc_host(sizeof(struct mvsdmmc_host), &pdev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mmc->ops = &mvsdmmc_ops;
+	mmc->f_min = MVSDMMC_CLOCKRATE_MIN;
+	mmc->f_max = (unsigned int)maxfreq;
+
+	mmc->max_hw_segs = 1;
+	mmc->max_phys_segs = 1;
+
+	mmc->max_req_size = MVSDMMC_DMA_SIZE;
+	mmc->max_seg_size = mmc->max_req_size;
+	mmc->max_blk_count = MVSDMMC_DMA_SIZE;
+	mmc->max_blk_size = 2048;
+
+	host = mmc_priv(mmc);
+	BUG_ON(host == NULL);
+
+	host->pdev = pdev;
+	host->mmc = mmc;
+	host->irq = irq;
+
+	if (detect)
+		host->irq_detect = irq_detect;
+
+	host->res = r;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+	if (highspeed) {
+		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
+		mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
+	}
+
+	mmc->caps |= MMC_CAP_SDIO_IRQ;
+
+	spin_lock_init(&host->lock);
+	host->power_mode = MMC_POWER_OFF;
+
+	host->base = ioremap(r->start, SZ_4K);
+
+	if (!host->base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+	/*
+	 * (Re-)program MBUS remapping windows if we are asked to.
+	 */
+	if (mv_platform_data->dram != NULL)
+		mv_conf_mbus_windows(host, mv_platform_data->dram);
+#endif
+
+	if (request_irq(host->irq, mvsdmmc_irq,
+			0 , DRIVER_NAME, mmc)) {
+		mvsdmmc_debug(host, "cannot assign irq %d\n", host->irq);
+		ret = -EINVAL;
+		host->irq = NO_IRQ;
+		goto out;
+	}
+
+	if (detect) {
+		if (request_irq(host->irq_detect, mvsdmmc_irq_detect,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+				IRQT_RISING | IRQT_FALLING,
+#else
+				0,
+#endif
+				DRIVER_NAME, mmc)) {
+
+			mvsdmmc_debug(host, "cannot assign irq %d\n",
+				      host->irq_detect);
+			ret = -EINVAL;
+			host->irq_detect = NO_IRQ;
+			goto out;
+		}
+	} else {
+		mmc->caps |= MMC_CAP_NEEDS_POLL;
+		host->irq_detect = NO_IRQ;
+	}
+
+	platform_set_drvdata(pdev, mmc);
+	setup_timer(&host->timer, mvsdmmc_timeout_timer, (unsigned long)host);
+
+	if (mvsdmmc_dma_init(mmc) != 0)
+		goto out;
+
+	if (mmc_add_host(mmc) != 0)
+		goto out;
+
+	create_proc_read_entry("mvsdmmc", 0 , NULL ,
+			       mvsdmmc_read_procmem, host);
+
+	mvsdmmc_dbg_exit();
+	return 0;
+out:
+	if (host) {
+		mvsdmmc_disable_irq(host, 0xffff);
+
+		if (host->base) {
+			mvsdmmc_stop_clock(host);
+			iounmap(host->base);
+		}
+
+
+		if (host->irq != NO_IRQ)
+			free_irq(host->irq, host);
+
+		if (detect) {
+			if (host->irq_detect != NO_IRQ)
+				free_irq(host->irq_detect, host);
+		}
+
+		if (host->res)
+			release_resource(host->res);
+	}
+
+	if (mmc)
+		mmc_free_host(mmc);
+
+	return ret;
+}
+
+static int mvsdmmc_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	platform_set_drvdata(pdev, NULL);
+
+	if (mmc) {
+		struct mvsdmmc_host *host = mmc_priv(mmc);
+		mvsdmmc_disable_irq(host, 0xffff);
+
+		cancel_delayed_work(&mmc->detect);
+
+		mmc_remove_host(mmc);
+
+		if (host) {
+			mvsdmmc_stop_clock(host);
+
+
+			if (host->irq != NO_IRQ)
+				free_irq(host->irq, mmc);
+
+			if (detect) {
+				if (host->irq_detect != NO_IRQ)
+					free_irq(host->irq_detect, mmc);
+			}
+
+			if (host->base)
+				iounmap(host->base);
+
+			if (host->res)
+				release_resource(host->res);
+
+			del_timer_sync(&host->timer);
+		}
+		mmc_free_host(mmc);
+	}
+	remove_proc_entry("mvsdmmc", NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mvsdmmc_suspend(struct platform_device *dev, pm_message_t state,
+			   u32 level)
+{
+	struct mmc_host *mmc = platform_get_drvdata(dev);
+	int ret = 0;
+
+	if (mmc && level == SUSPEND_DISABLE)
+		ret = mmc_suspend_host(mmc, state);
+
+	return ret;
+}
+
+static int mvsdmmc_resume(struct platform_device *dev, u32 level)
+{
+	struct mmc_host *mmc = platform_dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (mmc && level == RESUME_ENABLE)
+		ret = mmc_resume_host(mmc);
+
+	return ret;
+}
+#else
+#define mvsdmmc_suspend	NULL
+#define mvsdmmc_resume	NULL
+#endif
+
+
+static struct platform_driver mvsdmmc_driver = {
+	.probe		= mvsdmmc_probe,
+	.remove		= mvsdmmc_remove,
+	.suspend	= mvsdmmc_suspend,
+	.resume		= mvsdmmc_resume,
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init mvsdmmc_init(void)
+{
+	int ret = 0;
+	mvsdmmc_dbg_enter();
+
+	if (MV_FALSE == mvCtrlPwrClckGet(SDIO_UNIT_ID, 0)) {
+		printk("\nWarning SDIO unit is Powered Off\n");
+		return;
+	}
+
+	ret = platform_driver_register(&mvsdmmc_driver);
+
+	mvsdmmc_dbg_exit();
+	return ret;
+}
+
+static void __exit mvsdmmc_exit(void)
+{
+	mvsdmmc_dbg_enter();
+	platform_driver_unregister(&mvsdmmc_driver);
+	mvsdmmc_dbg_exit();
+}
+
+module_init(mvsdmmc_init);
+module_exit(mvsdmmc_exit);
+
+/* maximum frequency used in the driver (default 50MHz) */ 
+module_param(maxfreq, int, 0);
+
+/* do we support high speed, default yes*/ 
+module_param(highspeed, int, 0);
+
+module_param(dump_on_error, int, 0);
+
+/* support detection removal\insersion (default = 1) */ 
+module_param(detect, int, 0);
+
+
+MODULE_AUTHOR("Maen Suleiman <maen@marvell.com>"); 
+MODULE_DESCRIPTION("Marvell SD,SDIO,MMC Host Controller driver"); 
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/mvsdmmc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/mvsdmmc.h
new file mode 100755
index 0000000..11400a5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_sdio/mvsdmmc.h
@@ -0,0 +1,199 @@
+/*
+ *  Copyright (C) 2008 Marvell Semiconductors, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _MVSDMMC_INCLUDE
+#define _MVSDMMC_INCLUDE
+
+
+#define MVSDMMC_DMA_SIZE			65536
+
+#define MVSDMMC_CMD_TIMEOUT			2 /* 100 usec*/
+
+
+/*
+ * The base MMC clock rate
+ */
+
+#define MVSDMMC_CLOCKRATE_MIN			100000
+#define MVSDMMC_CLOCKRATE_MAX			50000000
+
+#define MVSDMMC_BASE_FAST_CLOCK_ORION	400000000 /* 100000000 */
+#define MVSDMMC_BASE_FAST_CLOCK_KW		200000000 /* 100000000 */
+
+
+
+/*
+ * SDIO register
+ */
+
+#define SDIO_SYS_ADDR_LOW			0x000
+#define SDIO_SYS_ADDR_HI			0x004
+#define SDIO_BLK_SIZE				0x008
+#define SDIO_BLK_COUNT				0x00c
+#define SDIO_ARG_LOW				0x010
+#define SDIO_ARG_HI				0x014
+#define SDIO_XFER_MODE				0x018
+#define SDIO_CMD				0x01c
+#define SDIO_RSP(i)				(0x020 + ((i)<<2))
+#define SDIO_RSP0				0x020
+#define SDIO_RSP1				0x024
+#define SDIO_RSP2				0x028
+#define SDIO_RSP3				0x02c
+#define SDIO_RSP4				0x030
+#define SDIO_RSP5				0x034
+#define SDIO_RSP6				0x038
+#define SDIO_RSP7				0x03c
+#define SDIO_BUF_DATA_PORT			0x040
+#define SDIO_RSVED				0x044
+
+#define SDIO_PRESENT_STATE0			0x048
+#define SDIO_PRESENT_STATE1			0x04c
+#define SDIO_HOST_CTRL				0x050
+#define SDIO_BLK_GAP_CTRL			0x054
+#define SDIO_CLK_CTRL				0x058
+#define SDIO_SW_RESET				0x05c
+#define SDIO_NOR_INTR_STATUS			0x060
+#define SDIO_ERR_INTR_STATUS			0x064
+#define SDIO_NOR_STATUS_EN			0x068
+#define SDIO_ERR_STATUS_EN			0x06c
+#define SDIO_NOR_INTR_EN			0x070
+#define SDIO_ERR_INTR_EN			0x074
+#define SDIO_AUTOCMD12_ERR_STATUS		0x078
+#define SDIO_CURR_BYTE_LEFT			0x07c
+#define SDIO_CURR_BLK_LEFT			0x080
+#define SDIO_AUTOCMD12_ARG_LOW			0x084
+#define SDIO_AUTOCMD12_ARG_HI			0x088
+#define SDIO_AUTOCMD12_INDEX			0x08c
+#define SDIO_AUTO_RSP(i)			(0x090 + ((i)<<2))
+#define SDIO_AUTO_RSP0				0x090
+#define SDIO_AUTO_RSP1				0x094
+#define SDIO_AUTO_RSP2				0x098
+#define SDIO_CLK_DIV				0x128
+
+#define WINDOW_CTRL(i)				(0x108 + ((i) << 3))
+#define WINDOW_BASE(i)				(0x10c + ((i) << 3))
+
+
+/*
+ * SDIO_PRESENT_STATE
+ */
+
+#define CARD_BUSY				(1 << 1)
+#define CMD_INHIBIT				(1 << 0)
+#define CMD_TXACTIVE				(1 << 8)
+#define CMD_RXACTIVE				(1 << 9)
+#define CMD_AUTOCMD12ACTIVE			(1 << 14)
+
+#define CMD_BUS_BUSY				(CMD_AUTOCMD12ACTIVE|	\
+						CMD_RXACTIVE|	\
+						CMD_TXACTIVE|	\
+						CMD_INHIBIT|	\
+						CARD_BUSY)
+
+/*
+ * SDIO_CMD
+ */
+
+#define SDIO_CMD_RSP_NONE			(0 << 0)
+#define SDIO_CMD_RSP_136			(1 << 0)
+#define SDIO_CMD_RSP_48				(2 << 0)
+#define SDIO_CMD_RSP_48BUSY			(3 << 0)
+
+#define SDIO_CMD_CHECK_DATACRC16		(1 << 2)
+#define SDIO_CMD_CHECK_CMDCRC			(1 << 3)
+#define SDIO_CMD_INDX_CHECK			(1 << 4)
+#define SDIO_CMD_DATA_PRESENT			(1 << 5)
+#define SDIO_UNEXPECTED_RESP			(1 << 7)
+
+
+/*
+ * SDIO_XFER_MODE
+ */
+
+#define SDIO_XFER_MODE_STOP_CLK			(1 << 5)
+#define SDIO_XFER_MODE_HW_WR_DATA_EN		(1 << 1)
+#define SDIO_XFER_MODE_AUTO_CMD12		(1 << 2)
+#define SDIO_XFER_MODE_INT_CHK_EN		(1 << 3)
+#define SDIO_XFER_MODE_TO_HOST			(1 << 4)
+
+
+/*
+ * SDIO_HOST_CTRL
+ */
+
+#define SDIO_HOST_CTRL_PUSH_PULL_EN 		(1 << 0)
+
+#define SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY 	(0 << 1)
+#define SDIO_HOST_CTRL_CARD_TYPE_IO_ONLY 	(1 << 1)
+#define SDIO_HOST_CTRL_CARD_TYPE_IO_MEM_COMBO 	(2 << 1)
+#define SDIO_HOST_CTRL_CARD_TYPE_IO_MMC 	(3 << 1)
+#define SDIO_HOST_CTRL_CARD_TYPE_MASK	 	(3 << 1)
+
+#define SDIO_HOST_CTRL_BIG_ENDIAN 		(1 << 3)
+#define SDIO_HOST_CTRL_LSB_FIRST 		(1 << 4)
+#define SDIO_HOST_CTRL_ID_MODE_LOW_FREQ 	(1 << 5)
+#define SDIO_HOST_CTRL_HALF_SPEED 		(1 << 6)
+#define SDIO_HOST_CTRL_DATA_WIDTH_4_BITS 	(1 << 9)
+#define SDIO_HOST_CTRL_HI_SPEED_EN 		(1 << 10)
+
+
+#define SDIO_HOST_CTRL_TMOUT_MASK 		(0xf << 11)
+#define SDIO_HOST_CTRL_TMOUT_MAX 		(0xf << 11)
+#define SDIO_HOST_CTRL_TMOUT(x) 		((x) << 11)
+#define SDIO_HOST_CTRL_TMOUT_EN 		(1 << 15)
+
+#define SDIO_HOST_CTRL_DFAULT_OPEN_DRAIN 	\
+		(SDIO_HOST_CTRL_TMOUT(x)(0xf))
+#define SDIO_HOST_CTRL_DFAULT_PUSH_PULL 	\
+		(SDIO_HOST_CTRL_TMOUT(x)(0xf) | SDIO_HOST_CTRL_PUSH_PULL_EN)
+
+
+/*
+ * NOR status bits
+ */
+
+#define SDIO_NOR_ERROR				(1 << 15)
+#define SDIO_NOR_UNEXP_RSP			(1 << 14)
+#define SDIO_NOR_AUTOCMD12_DONE			(1 << 13)
+#define SDIO_NOR_SUSPEND_ON			(1 << 12)
+#define SDIO_NOR_LMB_FF_8W_AVAIL		(1 << 11)
+#define SDIO_NOR_LMB_FF_8W_FILLED		(1 << 10)
+#define SDIO_NOR_READ_WAIT_ON			(1 << 9)
+#define SDIO_NOR_CARD_INT			(1 << 8)
+#define SDIO_NOR_READ_READY			(1 << 5)
+#define SDIO_NOR_WRITE_READY			(1 << 4)
+#define SDIO_NOR_DMA_INI			(1 << 3)
+#define SDIO_NOR_BLK_GAP_EVT			(1 << 2)
+#define SDIO_NOR_XFER_DONE			(1 << 1)
+#define SDIO_NOR_CMD_DONE			(1 << 0)
+
+
+/*
+ * ERR status bits
+ */
+
+#define SDIO_ERR_CRC_STATUS			(1 << 14)
+#define SDIO_ERR_CRC_STARTBIT			(1 << 13)
+#define SDIO_ERR_CRC_ENDBIT			(1 << 12)
+#define SDIO_ERR_RESP_TBIT			(1 << 11)
+#define SDIO_ERR_SIZE				(1 << 10)
+#define SDIO_ERR_CMD_STARTBIT			(1 << 9)
+#define SDIO_ERR_AUTOCMD12			(1 << 8)
+#define SDIO_ERR_DATA_ENDBIT			(1 << 6)
+#define SDIO_ERR_DATA_CRC			(1 << 5)
+#define SDIO_ERR_DATA_TIMEOUT			(1 << 4)
+#define SDIO_ERR_CMD_INDEX			(1 << 3)
+#define SDIO_ERR_CMD_ENDBIT			(1 << 2)
+#define SDIO_ERR_CMD_CRC			(1 << 1)
+#define SDIO_ERR_CMD_TIMEOUT			(1 << 0)
+
+#define SDIO_POLL_MASK 				0xffff /* enable all for polling */
+
+
+#endif /* _MVSDMMC_INCLUDE */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/Makefile
new file mode 100755
index 0000000..80392a6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/Makefile
@@ -0,0 +1,13 @@
+#

+# Makefile for the Marvell Key

+#

+ifeq ($(CONFIG_ARCH_FEROCEON),y)

+	include $(srctree)/$(MACHINE)/config/mvRules.mk

+endif

+

+ifeq ($(CONFIG_ARCH_ARMADA_XP),y)

+	include $(srctree)/arch/arm/mach-armadaxp/config/mvRules.mk

+endif

+

+obj-$(CONFIG_MV_INCLUDE_SWITCH)	+= mv_switch.o mv_switch_sysfs.o mv_switch_wrap.o

+

diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch.c
new file mode 100755
index 0000000..677dede
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch.c
@@ -0,0 +1,1424 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"		/* Should be included before mvSysHwConfig */
+#include <linux/etherdevice.h>
+#include "mvOs.h"
+#include "mvSysHwConfig.h"
+#include "eth-phy/mvEthPhy.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#ifdef MV_INCLUDE_ETH_COMPLEX
+#include "ctrlEnv/mvCtrlEthCompLib.h"
+#endif /* MV_INCLUDE_ETH_COMPLEX */
+
+#include "msApi.h"
+#include "h/platform/gtMiiSmiIf.h"
+#include "mv_switch.h"
+
+
+#include "msApiTypes.h"
+#include "msApiDefs.h"
+#include "mv_switch_wrap.h"
+
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+extern void mv_eth_switch_update_link(unsigned int p, unsigned int link_up);
+extern void mv_eth_switch_interrupt_unmask(int qsgmii_module, int gephy_on_port);
+extern void mv_eth_switch_interrupt_clear(int qsgmii_module, int gephy_on_port);
+#endif
+
+#define MV_SWITCH_DEF_INDEX     0
+#define MV_ETH_PORT_0           0
+#define MV_ETH_PORT_1           1
+
+/* uncomment for debug prints */
+/* #define SWITCH_DEBUG */
+
+#define SWITCH_DBG_OFF      0x0000
+#define SWITCH_DBG_LOAD     0x0001
+#define SWITCH_DBG_MCAST    0x0002
+#define SWITCH_DBG_VLAN     0x0004
+#define SWITCH_DBG_ALL      0xffff
+
+#ifdef SWITCH_DEBUG
+static u32 switch_dbg = 0;
+#define SWITCH_DBG(FLG, X) if ((switch_dbg & (FLG)) == (FLG)) printk X
+#else
+#define SWITCH_DBG(FLG, X)
+#endif /* SWITCH_DEBUG */
+
+/*static GT_QD_DEV        qddev, *qd_dev = NULL; */
+GT_QD_DEV        qddev, *qd_dev = NULL; 
+static GT_SYS_CONFIG qd_cfg;
+
+static int qd_cpu_port = -1;
+static int qsgmii_module = 0;
+static int gephy_on_port = -1;
+static int rgmiia_on_port = -1;
+
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+static int switch_irq = -1;
+int switch_link_poll = 0;
+static struct timer_list switch_link_timer;
+/*eth port los alarm state*/
+static u32 sw_port_los_alarm= 0;
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+static spinlock_t switch_lock;
+
+static GT_BOOL mv_switch_mii_read(GT_QD_DEV *dev, unsigned int phy, unsigned int reg, unsigned int *data)
+{
+	unsigned long flags;
+	unsigned short tmp;
+	MV_STATUS status;
+
+	spin_lock_irqsave(&switch_lock, flags);
+	status = mvEthPhyRegRead(phy, reg, &tmp);
+	spin_unlock_irqrestore(&switch_lock, flags);
+	*data = tmp;
+
+	if (status == MV_OK)
+		return GT_TRUE;
+
+	return GT_FALSE;
+}
+
+static GT_BOOL mv_switch_mii_write(GT_QD_DEV *dev, unsigned int phy, unsigned int reg, unsigned int data)
+{
+	unsigned long flags;
+	unsigned short tmp;
+	MV_STATUS status;
+
+	spin_lock_irqsave(&switch_lock, flags);
+	tmp = (unsigned short)data;
+	status = mvEthPhyRegWrite(phy, reg, tmp);
+	spin_unlock_irqrestore(&switch_lock, flags);
+
+	if (status == MV_OK)
+		return GT_TRUE;
+
+	return GT_FALSE;
+}
+
+int mv_switch_mac_addr_set(unsigned char *mac_addr, unsigned char db, unsigned int ports_mask, unsigned char op)
+{
+	GT_ATU_ENTRY mac_entry;
+
+	memset(&mac_entry, 0, sizeof(GT_ATU_ENTRY));
+
+	mac_entry.trunkMember = GT_FALSE;
+	mac_entry.prio = 0;
+	mac_entry.exPrio.useMacFPri = GT_FALSE;
+	mac_entry.exPrio.macFPri = 0;
+	mac_entry.exPrio.macQPri = 0;
+	mac_entry.DBNum = db;
+	mac_entry.portVec = ports_mask;
+	memcpy(mac_entry.macAddr.arEther, mac_addr, 6);
+
+	if (is_multicast_ether_addr(mac_addr))
+		mac_entry.entryState.mcEntryState = GT_MC_STATIC;
+	else
+		mac_entry.entryState.ucEntryState = GT_UC_NO_PRI_STATIC;
+
+	if ((op == 0) /*|| (mac_entry.portVec == 0)*/) {
+		if (gfdbDelAtuEntry(qd_dev, &mac_entry) != GT_OK) {
+			printk(KERN_ERR "gfdbDelAtuEntry failed\n");
+			return -1;
+		}
+	} else {
+		if (gfdbAddMacEntry(qd_dev, &mac_entry) != GT_OK) {
+			printk(KERN_ERR "gfdbAddMacEntry failed\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int mv_switch_port_based_vlan_set(unsigned int ports_mask, int set_cpu_port)
+{
+	unsigned int p, pl;
+	unsigned char cnt;
+	GT_LPORT port_list[MAX_SWITCH_PORTS];
+
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(ports_mask, p) && (set_cpu_port || (p != qd_cpu_port))) {
+			SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN,
+				   ("port based vlan, port %d: ", p));
+			for (pl = 0, cnt = 0; pl < qd_dev->numOfPorts; pl++) {
+				if (MV_BIT_CHECK(ports_mask, pl) && (pl != p)) {
+					SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("%d ", pl));
+					port_list[cnt] = pl;
+					cnt++;
+				}
+			}
+			if (gvlnSetPortVlanPorts(qd_dev, p, port_list, cnt) != GT_OK) {
+				printk(KERN_ERR "gvlnSetPortVlanPorts failed\n");
+				return -1;
+			}
+			SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("\n"));
+		}
+	}
+	return 0;
+}
+
+int mv_switch_vlan_in_vtu_set(unsigned short vlan_id, unsigned short db_num, unsigned int ports_mask)
+{
+	GT_VTU_ENTRY vtu_entry;
+	unsigned int p;
+
+	vtu_entry.vid = vlan_id;
+	vtu_entry.DBNum = db_num;
+	vtu_entry.vidPriOverride = GT_FALSE;
+	vtu_entry.vidPriority = 0;
+	vtu_entry.vidExInfo.useVIDFPri = GT_FALSE;
+	vtu_entry.vidExInfo.vidFPri = 0;
+	vtu_entry.vidExInfo.useVIDQPri = GT_FALSE;
+	vtu_entry.vidExInfo.vidQPri = 0;
+	vtu_entry.vidExInfo.vidNRateLimit = GT_FALSE;
+	SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("vtu entry: vid=0x%x, port ", vtu_entry.vid));
+
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(ports_mask, p)) {
+			SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("%d ", p));
+			vtu_entry.vtuData.memberTagP[p] = MEMBER_EGRESS_UNMODIFIED;
+		} else {
+			vtu_entry.vtuData.memberTagP[p] = NOT_A_MEMBER;
+		}
+		vtu_entry.vtuData.portStateP[p] = 0;
+	}
+
+	if (gvtuAddEntry(qd_dev, &vtu_entry) != GT_OK) {
+		printk(KERN_ERR "gvtuAddEntry failed\n");
+		return -1;
+	}
+
+	SWITCH_DBG(SWITCH_DBG_LOAD | SWITCH_DBG_MCAST | SWITCH_DBG_VLAN, ("\n"));
+	return 0;
+}
+
+int mv_switch_atu_db_flush(int db_num)
+{
+	if (gfdbFlushInDB(qd_dev, GT_FLUSH_ALL, db_num) != GT_OK) {
+		printk(KERN_ERR "gfdbFlushInDB failed\n");
+		return -1;
+	}
+	return 0;
+}
+
+int mv_switch_promisc_set(u16 vlan_grp_id, u16 port_map, u16 cpu_port, u8 promisc_on)
+{
+	int i;
+
+	if (promisc_on) {
+
+		mv_switch_port_based_vlan_set((port_map | (1 << cpu_port)), 0);
+
+		for (i = 0; i < qd_dev->numOfPorts; i++) {
+			if (MV_BIT_CHECK(port_map, i) && (i != cpu_port)) {
+				if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, i),
+							      MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id),
+							      (port_map | (1 << cpu_port))) != 0) {
+					printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n");
+					return -1;
+				}
+			}
+		}
+
+	} else {
+
+		mv_switch_port_based_vlan_set((port_map & ~(1 << cpu_port)), 0);
+
+		for (i = 0; i < qd_dev->numOfPorts; i++) {
+			if (MV_BIT_CHECK(port_map, i) && (i != cpu_port)) {
+				if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, i),
+							      MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id),
+							      (port_map & ~(1 << cpu_port))) != 0) {
+					printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n");
+					return -1;
+				}
+			}
+		}
+
+	}
+
+	return 0;
+}
+
+int mv_eth_switch_vlan_set(u16 vlan_grp_id, u16 port_map, u16 cpu_port)
+{
+	int p;
+
+	/* set port's default private vlan id and database number (DB per group): */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(port_map, p) && (p != cpu_port)) {
+			if (gvlnSetPortVid(qd_dev, p, MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, p)) != GT_OK) {
+				printk(KERN_ERR "gvlnSetPortVid failed\n");
+				return -1;
+			}
+			if (gvlnSetPortVlanDBNum(qd_dev, p, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id)) != GT_OK) {
+				printk(KERN_ERR "gvlnSetPortVlanDBNum failed\n");
+				return -1;
+			}
+		}
+	}
+
+	/* set port's port-based vlan (CPU port is not part of VLAN) */
+	if (mv_switch_port_based_vlan_set((port_map & ~(1 << cpu_port)), 0) != 0)
+		printk(KERN_ERR "mv_switch_port_based_vlan_set failed\n");
+
+	/* set vtu with group vlan id (used in tx) */
+	if (mv_switch_vlan_in_vtu_set(vlan_grp_id, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id), port_map | (1 << cpu_port)) != 0)
+		printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n");
+
+	/* set vtu with each port private vlan id (used in rx) */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(port_map, p) && (p != cpu_port)) {
+			if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, p),
+						      MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id),
+						      port_map & ~(1 << cpu_port)) != 0) {
+				printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n");
+			}
+		}
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+MV_VOID mv_switch_set_port_los_alarm(MV_U32 port)
+{
+	sw_port_los_alarm |= (1 << port);
+	//printk("switch port[%d] los, sw_port_los_alarm[%d] \r\n",port,sw_port_los_alarm);
+}
+
+MV_VOID mv_switch_clear_port_los_alarm(MV_U32 port)
+{
+	sw_port_los_alarm &= ~(1 << port);
+	//printk("switch port[%d] los, sw_port_los_alarm[%d] \r\n",port,sw_port_los_alarm);
+}
+
+MV_U32  mv_switch_get_port_los_alarm(MV_U32 *eth_alarm)
+{
+	*eth_alarm = sw_port_los_alarm;
+	return 0;
+}
+
+void mv_switch_link_update_event(MV_U32 port_mask, int force_link_check)
+{
+	int p;
+	unsigned short phy_cause = 0;
+
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(port_mask, p)) {
+			if ((!qsgmii_module) || (p == gephy_on_port)) { /* liron, TODO: || (p == rgmiia_on_port)  */
+				/* this is needed to clear the PHY interrupt */
+				gprtGetPhyIntStatus(qd_dev, p, &phy_cause);
+			} else {
+				phy_cause |= GT_LINK_STATUS_CHANGED;
+			}
+
+			if (force_link_check)
+				phy_cause |= GT_LINK_STATUS_CHANGED;
+
+			if (phy_cause & GT_LINK_STATUS_CHANGED) {
+				char *link = NULL, *duplex = NULL, *speed = NULL;
+				GT_BOOL flag;
+				GT_PORT_SPEED_MODE speed_mode;
+
+				if (gprtGetLinkState(qd_dev, p, &flag) != GT_OK) {
+					printk(KERN_ERR "gprtGetLinkState failed (port %d)\n", p);
+					link = "ERR";
+				} else
+					link = (flag) ? "up" : "down";
+
+				if(flag)/*clear eth port los alarm state*/	
+				{
+					mv_switch_clear_port_los_alarm(mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p));
+				}
+				else/*set eth port los alarm state*/
+				{
+					mv_switch_set_port_los_alarm(mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p));
+				}
+				
+				if (flag) {
+					if (gprtGetDuplex(qd_dev, p, &flag) != GT_OK) {
+						printk(KERN_ERR "gprtGetDuplex failed (port %d)\n", p);
+						duplex = "ERR";
+					} else
+						duplex = (flag) ? "Full" : "Half";
+
+					if (gprtGetSpeedMode(qd_dev, p, &speed_mode) != GT_OK) {
+						printk(KERN_ERR "gprtGetSpeedMode failed (port %d)\n", p);
+						speed = "ERR";
+					} else {
+						if (speed_mode == PORT_SPEED_1000_MBPS)
+							speed = "1000Mbps";
+						else if (speed_mode == PORT_SPEED_100_MBPS)
+							speed = "100Mbps";
+						else
+							speed = "10Mbps";
+					}
+					mv_eth_switch_update_link(p, 1);
+					printk(KERN_ERR "Port %d: Link-%s, %s-duplex, Speed-%s.\n",
+					       mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p), link, duplex, speed);
+				} else {
+					mv_eth_switch_update_link(p, 0);
+					printk(KERN_ERR "Port %d: Link-down\n", mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p));
+				}
+			}
+		}
+	}
+}
+
+void mv_switch_link_timer_function(unsigned long data)
+{
+	/* GT_DEV_INT_STATUS devIntStatus; */
+	MV_U32 port_mask = (data & 0xFF);
+
+	mv_switch_link_update_event(port_mask, 0);
+
+	if (switch_link_poll) {
+		switch_link_timer.expires = jiffies + (HZ);	/* 1 second */
+		add_timer(&switch_link_timer);
+	}
+}
+
+static irqreturn_t mv_switch_isr(int irq, void *dev_id)
+{
+	GT_DEV_INT_STATUS devIntStatus;
+	MV_U32 port_mask = 0;
+
+	if (qsgmii_module) {
+#ifdef MV_INCLUDE_ETH_COMPLEX
+		MV_U32 reg = 0;
+
+		reg = MV_REG_READ(MV_ETHCOMP_INT_MAIN_CAUSE_REG);
+
+		if (reg & MV_ETHCOMP_PCS0_LINK_INT_MASK)
+			port_mask |= 0x1;
+		if (reg & MV_ETHCOMP_PCS1_LINK_INT_MASK)
+			port_mask |= 0x2;
+		if (reg & MV_ETHCOMP_PCS2_LINK_INT_MASK)
+			port_mask |= 0x4;
+		if (reg & MV_ETHCOMP_PCS3_LINK_INT_MASK)
+			port_mask |= 0x8;
+#endif /* MV_INCLUDE_ETH_COMPLEX */
+	} else {
+		if (geventGetDevIntStatus(qd_dev, &devIntStatus) != GT_OK)
+			printk(KERN_ERR "geventGetDevIntStatus failed\n");
+
+		if (devIntStatus.devIntCause & GT_DEV_INT_PHY)
+			port_mask = devIntStatus.phyInt & 0xFF;
+	}
+
+	if (gephy_on_port >= 0)
+		port_mask |= (1 << gephy_on_port);
+
+	mv_switch_link_update_event(port_mask, 0);
+
+	mv_eth_switch_interrupt_clear(qsgmii_module, gephy_on_port);
+
+	return IRQ_HANDLED;
+}
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+int mv_switch_jumbo_mode_set(int max_size)
+{
+	int i;
+	GT_JUMBO_MODE jumbo_mode;
+
+	/* Set jumbo frames mode */
+	if (max_size <= 1522)
+		jumbo_mode = GT_JUMBO_MODE_1522;
+	else if (max_size <= 2048)
+		jumbo_mode = GT_JUMBO_MODE_2048;
+	else
+		jumbo_mode = GT_JUMBO_MODE_10240;
+
+	for (i = 0; i < qd_dev->numOfPorts; i++) {
+		if (gsysSetJumboMode(qd_dev, i, jumbo_mode) != GT_OK) {
+			printk(KERN_ERR "gsysSetJumboMode %d failed\n", jumbo_mode);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int mv_switch_load(unsigned int switch_ports_mask)
+{
+	int p;
+
+	printk(KERN_ERR "  o Loading Switch QuarterDeck driver\n");
+
+	if (qd_dev) {
+		printk(KERN_ERR "    o %s: Already initialized\n", __func__);
+		return 0;
+	}
+
+	memset((char *)&qd_cfg, 0, sizeof(GT_SYS_CONFIG));
+	spin_lock_init(&switch_lock);
+
+	/* init config structure for qd package */
+	qd_cfg.BSPFunctions.readMii = mv_switch_mii_read;
+	qd_cfg.BSPFunctions.writeMii = mv_switch_mii_write;
+	qd_cfg.BSPFunctions.semCreate = NULL;
+	qd_cfg.BSPFunctions.semDelete = NULL;
+	qd_cfg.BSPFunctions.semTake = NULL;
+	qd_cfg.BSPFunctions.semGive = NULL;
+	qd_cfg.initPorts = GT_TRUE;
+	qd_cfg.cpuPortNum = mvBoardSwitchCpuPortGet(MV_SWITCH_DEF_INDEX);
+	if (mvBoardSmiScanModeGet(MV_SWITCH_DEF_INDEX) == 1) {
+		qd_cfg.mode.baseAddr = 0;
+		qd_cfg.mode.scanMode = SMI_MANUAL_MODE;
+	} else if (mvBoardSmiScanModeGet(MV_SWITCH_DEF_INDEX) == 2) {
+		qd_cfg.mode.scanMode = SMI_MULTI_ADDR_MODE;
+		if (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_0) != -1) {
+			qd_cfg.mode.baseAddr = mvBoardPhyAddrGet(MV_ETH_PORT_0);
+		} else if (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_1) != -1) {
+			qd_cfg.mode.baseAddr = mvBoardPhyAddrGet(MV_ETH_PORT_1);
+		} else {
+			printk(KERN_ERR "mv_switch_load failed: Wrong SCAN mode\n");
+			return -1;
+		}
+	}
+
+	/* load switch sw package */
+	if (qdLoadDriver(&qd_cfg, &qddev) != GT_OK) {
+		printk(KERN_ERR "qdLoadDriver failed\n");
+		return -1;
+	}
+	qd_dev = &qddev;
+	qd_cpu_port = qd_cfg.cpuPortNum;
+
+	printk(KERN_ERR "    o Device ID     : 0x%x\n", qd_dev->deviceId);
+	printk(KERN_ERR "    o No. of Ports  : %d\n", qd_dev->numOfPorts);
+	printk(KERN_ERR "    o CPU Port      : %ld\n", qd_dev->cpuPortNum);
+
+	qsgmii_module = mvBoardIsQsgmiiModuleConnected();
+	if (qsgmii_module)
+		printk(KERN_ERR "    o QSGMII Module Detected\n");
+
+	gephy_on_port = mvBoardGePhySwitchPortGet();
+	if (gephy_on_port >= 0)
+		printk(KERN_ERR "    o Internal GE PHY Connected to Switch Port %d Detected\n", gephy_on_port);
+
+	rgmiia_on_port = mvBoardRgmiiASwitchPortGet();
+	if (rgmiia_on_port >= 0)
+		printk(KERN_ERR "    o RGMII-A Connected to Switch Port %d Detected\n", rgmiia_on_port);
+
+	/* disable all disconnected ports */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		/* Do nothing for ports that are not part of the given switch_port_mask */
+		if (!MV_BIT_CHECK(switch_ports_mask, p))
+			continue;
+
+		if (mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p) != -1) {
+			/* Switch port mapped to connector on the board */
+
+			if ((gpcsSetFCValue(qd_dev, p, GT_FALSE) != GT_OK) ||
+			    (gpcsSetForcedFC(qd_dev, p, GT_FALSE) != GT_OK)) {
+				printk(KERN_ERR "Force Flow Control - Failed\n");
+				return -1;
+			}
+#if 0
+			/* TODO - decide if we want to enable auto-negotiation of Flow Control for external ports */
+			if (qsgmii_module) {
+				/* TODO - configure ports via QSGMII registers */
+			} else {
+				GT_STATUS status;
+
+				status = gprtSetPause(qd_dev, p, GT_PHY_PAUSE);
+				if (status != GT_OK)
+					printk(KERN_ERR "Failed set pause for switch port #%d: status = %d\n", p, status);
+			}
+#endif
+			continue;
+		}
+
+		if ((mvBoardSwitchConnectedPortGet(MV_ETH_PORT_0) == p) ||
+		    (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_1) == p)) {
+			/* Switch port connected to GMAC - force link UP - 1000 Full with FC */
+			printk(KERN_ERR "    o Setting Switch Port #%d connected to GMAC port for 1000 Full with FC\n", p);
+			if (gpcsSetForceSpeed(qd_dev, p, PORT_FORCE_SPEED_1000_MBPS) != GT_OK) {
+				printk(KERN_ERR "Force speed 1000mbps - Failed\n");
+				return -1;
+			}
+
+			if ((gpcsSetDpxValue(qd_dev, p, GT_TRUE) != GT_OK) ||
+			    (gpcsSetForcedDpx(qd_dev, p, GT_TRUE) != GT_OK)) {
+				printk(KERN_ERR "Force duplex FULL - Failed\n");
+				return -1;
+			}
+
+			if ((gpcsSetFCValue(qd_dev, p, GT_TRUE) != GT_OK) ||
+			    (gpcsSetForcedFC(qd_dev, p, GT_TRUE) != GT_OK)) {
+				printk(KERN_ERR "Force Flow Control - Failed\n");
+				return -1;
+			}
+
+			if ((gpcsSetLinkValue(qd_dev, p, GT_TRUE) != GT_OK) ||
+			    (gpcsSetForcedLink(qd_dev, p, GT_TRUE) != GT_OK)) {
+				printk(KERN_ERR "Force Link UP - Failed\n");
+				return -1;
+			}
+			continue;
+		}
+		printk(KERN_ERR "    o Disable disconnected Switch Port #%d and force link down\n", p);
+
+		if (gstpSetPortState(qd_dev, p, GT_PORT_DISABLE) != GT_OK) {
+			printk(KERN_ERR "gstpSetPortState failed\n");
+			return -1;
+		}
+		if ((gpcsSetLinkValue(qd_dev, p, GT_FALSE) != GT_OK) ||
+		    (gpcsSetForcedLink(qd_dev, p, GT_TRUE) != GT_OK)) {
+			printk(KERN_ERR "Force Link DOWN - Failed\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int mv_switch_unload(unsigned int switch_ports_mask)
+{
+	int i;
+
+	printk(KERN_ERR "  o Unloading Switch QuarterDeck driver\n");
+
+	if (qd_dev == NULL) {
+		printk(KERN_ERR "    o %s: Already un-initialized\n", __func__);
+		return 0;
+	}
+
+	/* Flush all addresses from the MAC address table */
+	/* this also happens in mv_switch_init() but we call it here to clean-up nicely */
+	/* Note: per DB address flush (gfdbFlushInDB) happens when doing ifconfig down on a Switch interface */
+	if (gfdbFlush(qd_dev, GT_FLUSH_ALL) != GT_OK)
+		printk(KERN_ERR "gfdbFlush failed\n");
+
+	/* Reset VLAN tunnel mode */
+	for (i = 0; i < qd_dev->numOfPorts; i++) {
+		if (MV_BIT_CHECK(switch_ports_mask, i) && (i != qd_cpu_port))
+			if (gprtSetVlanTunnel(qd_dev, i, GT_FALSE) != GT_OK)
+				printk(KERN_ERR "gprtSetVlanTunnel failed (port %d)\n", i);
+	}
+
+	/* restore port's default private vlan id and database number to their default values after reset: */
+	for (i = 0; i < qd_dev->numOfPorts; i++) {
+		if (gvlnSetPortVid(qd_dev, i, 0x0001) != GT_OK) { /* that's the default according to the spec */
+			printk(KERN_ERR "gvlnSetPortVid failed\n");
+			return -1;
+		}
+		if (gvlnSetPortVlanDBNum(qd_dev, i, 0) != GT_OK) {
+			printk(KERN_ERR "gvlnSetPortVlanDBNum failed\n");
+			return -1;
+		}
+	}
+
+	/* Port based VLAN */
+	if (mv_switch_port_based_vlan_set(switch_ports_mask, 1))
+		printk(KERN_ERR "mv_switch_port_based_vlan_set failed\n");
+
+	/* Remove all entries from the VTU table */
+	if (gvtuFlush(qd_dev) != GT_OK)
+		printk(KERN_ERR "gvtuFlush failed\n");
+
+	/* unload switch sw package */
+	if (qdUnloadDriver(qd_dev) != GT_OK) {
+		printk(KERN_ERR "qdUnloadDriver failed\n");
+		return -1;
+	}
+	qd_dev = NULL;
+	qd_cpu_port = -1;
+	qsgmii_module = 0;
+	gephy_on_port = -1;
+	rgmiia_on_port = -1;
+
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+	switch_irq = -1;
+	switch_link_poll = 0;
+	del_timer(&switch_link_timer);
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+	return 0;
+}
+
+int mv_switch_init(int mtu, unsigned int switch_ports_mask)
+{
+	unsigned int p;
+	unsigned char cnt;
+	GT_LPORT port_list[MAX_SWITCH_PORTS];
+
+	if (qd_dev == NULL) {
+		printk(KERN_ERR "%s: qd_dev not initialized, call mv_switch_load() first\n", __func__);
+		return -1;
+	}
+
+	/* general Switch initialization - relevant for all Switch devices */
+
+	/* disable all ports */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(switch_ports_mask, p))
+			if (gstpSetPortState(qd_dev, p, GT_PORT_DISABLE) != GT_OK) {
+				printk(KERN_ERR "gstpSetPortState failed\n");
+				return -1;
+			}
+	}
+
+	/* flush All counters for all ports */
+	if (gstatsFlushAll(qd_dev) != GT_OK)
+		printk(KERN_ERR "gstatsFlushAll failed\n");
+
+	/* set all ports not to unmodify the vlan tag on egress */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(switch_ports_mask, p)) {
+			if (gprtSetEgressMode(qd_dev, p, GT_UNMODIFY_EGRESS) != GT_OK) {
+				printk(KERN_ERR "gprtSetEgressMode GT_UNMODIFY_EGRESS failed\n");
+				return -1;
+			}
+		}
+	}
+
+	/* initializes the PVT Table (cross-chip port based VLAN) to all one's (initial state) */
+	if (gpvtInitialize(qd_dev) != GT_OK) {
+		printk(KERN_ERR "gpvtInitialize failed\n");
+		return -1;
+	}
+
+	/* set all ports to work in Normal mode */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(switch_ports_mask, p)) {
+			if (gprtSetFrameMode(qd_dev, p, GT_FRAME_MODE_NORMAL) != GT_OK) {
+				printk(KERN_ERR "gprtSetFrameMode GT_FRAME_MODE_NORMAL failed\n");
+				return -1;
+			}
+		}
+	}
+
+	/* set priorities rules */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(switch_ports_mask, p)) {
+			/* default port priority to queue zero */
+			if (gcosSetPortDefaultTc(qd_dev, p, 0) != GT_OK)
+				printk(KERN_ERR "gcosSetPortDefaultTc failed (port %d)\n", p);
+
+			/* enable IP TOS Prio */
+			if (gqosIpPrioMapEn(qd_dev, p, GT_TRUE) != GT_OK)
+				printk(KERN_ERR "gqosIpPrioMapEn failed (port %d)\n", p);
+
+			/* set IP QoS */
+			if (gqosSetPrioMapRule(qd_dev, p, GT_FALSE) != GT_OK)
+				printk(KERN_ERR "gqosSetPrioMapRule failed (port %d)\n", p);
+
+			/* disable Vlan QoS Prio */
+			if (gqosUserPrioMapEn(qd_dev, p, GT_FALSE) != GT_OK)
+				printk(KERN_ERR "gqosUserPrioMapEn failed (port %d)\n", p);
+		}
+	}
+
+	/* specific Switch initialization according to Switch ID */
+	switch (qd_dev->deviceId) {
+	case GT_88E6161:
+	case GT_88E6165:
+	case GT_88E6171:
+	case GT_88E6351:
+		/* set Header Mode in all ports to False */
+		for (p = 0; p < qd_dev->numOfPorts; p++) {
+			if (MV_BIT_CHECK(switch_ports_mask, p)) {
+				if (gprtSetHeaderMode(qd_dev, p, GT_FALSE) != GT_OK) {
+					printk(KERN_ERR "gprtSetHeaderMode GT_FALSE failed\n");
+					return -1;
+				}
+			}
+		}
+
+		if (gprtSetHeaderMode(qd_dev, qd_cpu_port, GT_TRUE) != GT_OK) {
+			printk(KERN_ERR "gprtSetHeaderMode GT_TRUE failed\n");
+			return -1;
+		}
+
+		mv_switch_jumbo_mode_set(mtu);
+		break;
+
+	default:
+		printk(KERN_ERR "Unsupported Switch. Switch ID is 0x%X.\n", qd_dev->deviceId);
+		return -1;
+	}
+
+	/* The switch CPU port is not part of the VLAN, but rather connected by tunneling to each */
+	/* of the VLAN's ports. Our MAC addr will be added during start operation to the VLAN DB  */
+	/* at switch level to forward packets with this DA to CPU port.                           */
+	SWITCH_DBG(SWITCH_DBG_LOAD, ("Enabling Tunneling on ports: "));
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(switch_ports_mask, p) && (p != qd_cpu_port)) {
+			if (gprtSetVlanTunnel(qd_dev, p, GT_TRUE) != GT_OK) {
+				printk(KERN_ERR "gprtSetVlanTunnel failed (port %d)\n", p);
+				return -1;
+			} else {
+				SWITCH_DBG(SWITCH_DBG_LOAD, ("%d ", p));
+			}
+		}
+	}
+	SWITCH_DBG(SWITCH_DBG_LOAD, ("\n"));
+
+	/* set cpu-port with port-based vlan to all other ports */
+	SWITCH_DBG(SWITCH_DBG_LOAD, ("cpu port-based vlan:"));
+	for (p = 0, cnt = 0; p < qd_dev->numOfPorts; p++) {
+		if (p != qd_cpu_port) {
+			SWITCH_DBG(SWITCH_DBG_LOAD, ("%d ", p));
+			port_list[cnt] = p;
+			cnt++;
+		}
+	}
+	SWITCH_DBG(SWITCH_DBG_LOAD, ("\n"));
+	if (gvlnSetPortVlanPorts(qd_dev, qd_cpu_port, port_list, cnt) != GT_OK) {
+		printk(KERN_ERR "gvlnSetPortVlanPorts failed\n");
+		return -1;
+	}
+
+	if (gfdbFlush(qd_dev, GT_FLUSH_ALL) != GT_OK)
+		printk(KERN_ERR "gfdbFlush failed\n");
+
+	mv_switch_link_detection_init();
+
+	/* Configure Ethernet related LEDs, currently according to Switch ID */
+	switch (qd_dev->deviceId) {
+	case GT_88E6161:
+	case GT_88E6165:
+	case GT_88E6171:
+	case GT_88E6351:
+		break;		/* do nothing */
+
+	default:
+		for (p = 0; p < qd_dev->numOfPorts; p++) {
+			if ((p != qd_cpu_port) && ((p))) {
+				if (gprtSetPhyReg(qd_dev, p, 22, 0x1FFA)) {
+					/* Configure Register 22 LED0 to 0xA for Link/Act */
+					printk(KERN_ERR "gprtSetPhyReg failed (port=%d)\n", p);
+				}
+			}
+		}
+		break;
+	}
+
+	/* enable all relevant ports (ports connected to the MAC or external ports) */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(switch_ports_mask, p)) {
+			if ((mvBoardSwitchPortMap(MV_SWITCH_DEF_INDEX, p) != -1) ||
+			    (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_0) == p) ||
+			    (mvBoardSwitchConnectedPortGet(MV_ETH_PORT_1) == p)) {
+				if (gstpSetPortState(qd_dev, p, GT_PORT_FORWARDING) != GT_OK) {
+					printk(KERN_ERR "gstpSetPortState failed\n");
+					return -1;
+				}
+			}
+		}
+	}
+
+#ifdef SWITCH_DEBUG
+	/* for debug: */
+	mv_switch_status_print();
+#endif
+
+	return 0;
+}
+
+unsigned int mv_switch_link_detection_init(void)
+{
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+
+	unsigned int p;
+	static int link_init_done = 0;
+	unsigned int connected_phys_mask = 0;
+	unsigned int ethCompOpt;
+
+	if (qd_dev == NULL) {
+		printk(KERN_ERR "%s: qd_dev not initialized, call mv_switch_load() first\n", __func__);
+		return 0;
+	}
+
+	switch_irq = mvBoardSwitchIrqGet();
+	ethCompOpt = mvBoardEthComplexConfigGet();
+
+	if (!qsgmii_module) {
+		/* liron, TODO: find a nicer solution or use BoardEnv */
+#ifdef MV_INCLUDE_ETH_COMPLEX
+		if (ethCompOpt & ESC_OPT_SGMII_2_SW_P1)
+			connected_phys_mask = 0x02;	/* KW2: Switch PHY 1 */
+		else
+			connected_phys_mask = 0x0E;	/* KW2: Switch PHYs 1, 2, 3 */
+#else
+		connected_phys_mask = 0x1F;	/* KW40: Switch PHYs 0, 1, 2, 3, 4 */
+#endif
+
+		if (!link_init_done) {
+			/* Enable Phy Link Status Changed interrupt at Phy level for the all enabled ports */
+			for (p = 0; p < qd_dev->numOfPorts; p++) {
+				if (MV_BIT_CHECK(connected_phys_mask, p) && (p != qd_cpu_port)) {
+					if (gprtPhyIntEnable(qd_dev, p, (GT_LINK_STATUS_CHANGED)) != GT_OK)
+						printk(KERN_ERR "gprtPhyIntEnable failed port %d\n", p);
+				}
+			}
+
+			if (switch_irq != -1) {
+				/* Interrupt supported */
+
+				if ((qd_dev->deviceId == GT_88E6161) || (qd_dev->deviceId == GT_88E6165) ||
+				    (qd_dev->deviceId == GT_88E6351) || (qd_dev->deviceId == GT_88E6171)) {
+					GT_DEV_EVENT gt_event = { GT_DEV_INT_PHY, 0, connected_phys_mask };
+
+					if (eventSetDevInt(qd_dev, &gt_event) != GT_OK)
+						printk(KERN_ERR "eventSetDevInt failed\n");
+
+					if (eventSetActive(qd_dev, GT_DEVICE_INT) != GT_OK)
+						printk(KERN_ERR "eventSetActive failed\n");
+				} else {
+					if (eventSetActive(qd_dev, GT_PHY_INTERRUPT) != GT_OK)
+						printk(KERN_ERR "eventSetActive failed\n");
+				}
+			}
+		}
+	}
+
+	if (!link_init_done) {
+		if (gephy_on_port >= 0) {
+			if (gprtPhyIntEnable(qd_dev, gephy_on_port, (GT_LINK_STATUS_CHANGED)) != GT_OK)
+				printk(KERN_ERR "gprtPhyIntEnable failed port %d\n", gephy_on_port);
+		}
+	}
+
+	if (qsgmii_module)
+		connected_phys_mask = 0x0F;	/* Switch ports 0, 1, 2, 3 connected to QSGMII */
+
+	if (gephy_on_port >= 0)
+		connected_phys_mask |= (1 << gephy_on_port);
+
+	if (rgmiia_on_port >= 0)
+		connected_phys_mask |= (1 << rgmiia_on_port);
+
+	if (!link_init_done) {
+		/* we want to use a timer for polling link status if no interrupt is available for all or some of the PHYs */
+		if ((switch_irq == -1)) { /* liron, TODO: || (rgmiia_on_port >= 0) */
+			/* Use timer for polling */
+			switch_link_poll = 1;
+			init_timer(&switch_link_timer);
+			switch_link_timer.function = mv_switch_link_timer_function;
+
+			if (switch_irq == -1)
+				switch_link_timer.data = connected_phys_mask;
+			else		/* timer only for RGMII-A connected port */
+				switch_link_timer.data = (1 << rgmiia_on_port);
+
+			switch_link_timer.expires = jiffies + (HZ);	/* 1 second */
+			add_timer(&switch_link_timer);
+		}
+	}
+
+	if (!link_init_done) {
+		if (switch_irq != -1) {
+			/* Interrupt supported */
+			mv_eth_switch_interrupt_unmask(qsgmii_module, gephy_on_port);
+
+			if (request_irq(switch_irq, mv_switch_isr, (IRQF_DISABLED | IRQF_SAMPLE_RANDOM), "switch", NULL))
+				printk(KERN_ERR "failed to assign irq%d\n", switch_irq);
+		}
+	}
+
+	link_init_done = 1;
+
+	return connected_phys_mask;
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+}
+
+int mv_switch_tos_get(unsigned char tos)
+{
+	unsigned char queue;
+	int rc;
+
+	rc = gcosGetDscp2Tc(qd_dev, tos >> 2, &queue);
+	if (rc)
+		return -1;
+
+	return (int)queue;
+}
+
+int mv_switch_tos_set(unsigned char tos, int rxq)
+{
+	return gcosSetDscp2Tc(qd_dev, tos >> 2, (unsigned char)rxq);
+}
+
+int mv_switch_get_free_buffers_num(void)
+{
+	MV_U16 regVal;
+
+	if (gsysGetFreeQSize(qd_dev, &regVal) != GT_OK) {
+		printk(KERN_ERR "gsysGetFreeQSize - FAILED\n");
+		return -1;
+	}
+
+	return regVal;
+}
+
+#define QD_FMT "%10lu %10lu %10lu %10lu %10lu %10lu %10lu\n"
+#define QD_CNT(c, f) (GT_U32)c[0].f, (GT_U32)c[1].f, (GT_U32)c[2].f, (GT_U32)c[3].f, (GT_U32)c[4].f, (GT_U32)c[5].f, (GT_U32)c[6].f
+#define QD_MAX 7
+void mv_switch_stats_print(void)
+{
+	GT_STATS_COUNTER_SET3 counters[QD_MAX];
+	GT_PORT_STAT2 port_stats[QD_MAX];
+	int p;
+
+	if (qd_dev == NULL) {
+		printk(KERN_ERR "Switch is not initialized\n");
+		return;
+	}
+	memset(counters, 0, sizeof(GT_STATS_COUNTER_SET3) * QD_MAX);
+
+	printk(KERN_ERR "Total free buffers:      %u\n\n", mv_switch_get_free_buffers_num());
+
+	for (p = 0; p < QD_MAX; p++) {
+		if (gstatsGetPortAllCounters3(qd_dev, p, &counters[p]) != GT_OK)
+			printk(KERN_ERR "gstatsGetPortAllCounters3 for port #%d - FAILED\n", p);
+
+		if (gprtGetPortCtr2(qd_dev, p, &port_stats[p]) != GT_OK)
+			printk(KERN_ERR "gprtGetPortCtr2 for port #%d - FAILED\n", p);
+	}
+
+	printk(KERN_ERR "PortNum         " QD_FMT, (GT_U32) 0, (GT_U32) 1, (GT_U32) 2, (GT_U32) 3, (GT_U32) 4, (GT_U32) 5,
+	       (GT_U32) 6);
+	printk(KERN_ERR "-----------------------------------------------------------------------------------------------\n");
+	printk(KERN_ERR "InGoodOctetsLo  " QD_FMT, QD_CNT(counters, InGoodOctetsLo));
+	printk(KERN_ERR "InGoodOctetsHi  " QD_FMT, QD_CNT(counters, InGoodOctetsHi));
+	printk(KERN_ERR "InBadOctets     " QD_FMT, QD_CNT(counters, InBadOctets));
+	printk(KERN_ERR "InUnicasts      " QD_FMT, QD_CNT(counters, InUnicasts));
+	printk(KERN_ERR "InBroadcasts    " QD_FMT, QD_CNT(counters, InBroadcasts));
+	printk(KERN_ERR "InMulticasts    " QD_FMT, QD_CNT(counters, InMulticasts));
+	printk(KERN_ERR "inDiscardLo     " QD_FMT, QD_CNT(port_stats, inDiscardLo));
+	printk(KERN_ERR "inDiscardHi     " QD_FMT, QD_CNT(port_stats, inDiscardHi));
+	printk(KERN_ERR "InFiltered      " QD_FMT, QD_CNT(port_stats, inFiltered));
+
+	printk(KERN_ERR "OutOctetsLo     " QD_FMT, QD_CNT(counters, OutOctetsLo));
+	printk(KERN_ERR "OutOctetsHi     " QD_FMT, QD_CNT(counters, OutOctetsHi));
+	printk(KERN_ERR "OutUnicasts     " QD_FMT, QD_CNT(counters, OutUnicasts));
+	printk(KERN_ERR "OutMulticasts   " QD_FMT, QD_CNT(counters, OutMulticasts));
+	printk(KERN_ERR "OutBroadcasts   " QD_FMT, QD_CNT(counters, OutBroadcasts));
+	printk(KERN_ERR "OutFiltered     " QD_FMT, QD_CNT(port_stats, outFiltered));
+
+	printk(KERN_ERR "OutPause        " QD_FMT, QD_CNT(counters, OutPause));
+	printk(KERN_ERR "InPause         " QD_FMT, QD_CNT(counters, InPause));
+
+	printk(KERN_ERR "Octets64        " QD_FMT, QD_CNT(counters, Octets64));
+	printk(KERN_ERR "Octets127       " QD_FMT, QD_CNT(counters, Octets127));
+	printk(KERN_ERR "Octets255       " QD_FMT, QD_CNT(counters, Octets255));
+	printk(KERN_ERR "Octets511       " QD_FMT, QD_CNT(counters, Octets511));
+	printk(KERN_ERR "Octets1023      " QD_FMT, QD_CNT(counters, Octets1023));
+	printk(KERN_ERR "OctetsMax       " QD_FMT, QD_CNT(counters, OctetsMax));
+
+	printk(KERN_ERR "Excessive       " QD_FMT, QD_CNT(counters, Excessive));
+	printk(KERN_ERR "Single          " QD_FMT, QD_CNT(counters, Single));
+	printk(KERN_ERR "Multiple        " QD_FMT, QD_CNT(counters, InPause));
+	printk(KERN_ERR "Undersize       " QD_FMT, QD_CNT(counters, Undersize));
+	printk(KERN_ERR "Fragments       " QD_FMT, QD_CNT(counters, Fragments));
+	printk(KERN_ERR "Oversize        " QD_FMT, QD_CNT(counters, Oversize));
+	printk(KERN_ERR "Jabber          " QD_FMT, QD_CNT(counters, Jabber));
+	printk(KERN_ERR "InMACRcvErr     " QD_FMT, QD_CNT(counters, InMACRcvErr));
+	printk(KERN_ERR "InFCSErr        " QD_FMT, QD_CNT(counters, InFCSErr));
+	printk(KERN_ERR "Collisions      " QD_FMT, QD_CNT(counters, Collisions));
+	printk(KERN_ERR "Late            " QD_FMT, QD_CNT(counters, Late));
+	printk(KERN_ERR "OutFCSErr       " QD_FMT, QD_CNT(counters, OutFCSErr));
+	printk(KERN_ERR "Deferred        " QD_FMT, QD_CNT(counters, Deferred));
+
+	gstatsFlushAll(qd_dev);
+}
+
+static char *mv_str_port_state(GT_PORT_STP_STATE state)
+{
+	switch (state) {
+	case GT_PORT_DISABLE:
+		return "Disable";
+	case GT_PORT_BLOCKING:
+		return "Blocking";
+	case GT_PORT_LEARNING:
+		return "Learning";
+	case GT_PORT_FORWARDING:
+		return "Forwarding";
+	default:
+		return "Invalid";
+	}
+}
+
+static char *mv_str_speed_state(int port)
+{
+	GT_PORT_SPEED_MODE speed;
+	char *speed_str;
+
+	if (gprtGetSpeedMode(qd_dev, port, &speed) != GT_OK) {
+		printk(KERN_ERR "gprtGetSpeedMode failed (port %d)\n", port);
+		speed_str = "ERR";
+	} else {
+		if (speed == PORT_SPEED_1000_MBPS)
+			speed_str = "1 Gbps";
+		else if (speed == PORT_SPEED_100_MBPS)
+			speed_str = "100 Mbps";
+		else
+			speed_str = "10 Mbps";
+	}
+	return speed_str;
+}
+
+static char *mv_str_duplex_state(int port)
+{
+	GT_BOOL duplex;
+
+	if (gprtGetDuplex(qd_dev, port, &duplex) != GT_OK) {
+		printk(KERN_ERR "gprtGetDuplex failed (port %d)\n", port);
+		return "ERR";
+	} else
+		return (duplex) ? "Full" : "Half";
+}
+
+static char *mv_str_link_state(int port)
+{
+	GT_BOOL link;
+
+	if (gprtGetLinkState(qd_dev, port, &link) != GT_OK) {
+		printk(KERN_ERR "gprtGetLinkState failed (port %d)\n", port);
+		return "ERR";
+	} else
+		return (link) ? "Up" : "Down";
+}
+
+static char *mv_str_pause_state(int port)
+{
+	GT_BOOL force, pause;
+
+	if (gpcsGetForcedFC(qd_dev, port, &force) != GT_OK) {
+		printk(KERN_ERR "gpcsGetForcedFC failed (port %d)\n", port);
+		return "ERR";
+	}
+	if (force) {
+		if (gpcsGetFCValue(qd_dev, port, &pause) != GT_OK) {
+			printk(KERN_ERR "gpcsGetFCValue failed (port %d)\n", port);
+			return "ERR";
+		}
+	} else {
+		if (gprtGetPauseEn(qd_dev, port, &pause) != GT_OK) {
+			printk(KERN_ERR "gprtGetPauseEn failed (port %d)\n", port);
+			return "ERR";
+		}
+	}
+	return (pause) ? "Enable" : "Disable";
+}
+
+static char *mv_str_egress_mode(GT_EGRESS_MODE mode)
+{
+	switch (mode) {
+	case GT_UNMODIFY_EGRESS:
+		return "Unmodify";
+	case GT_UNTAGGED_EGRESS:
+		return "Untagged";
+	case GT_TAGGED_EGRESS:
+		return "Tagged";
+	case GT_ADD_TAG:
+		return "Add Tag";
+	default:
+		return "Invalid";
+	}
+}
+
+static char *mv_str_frame_mode(GT_FRAME_MODE mode)
+{
+	switch (mode) {
+	case GT_FRAME_MODE_NORMAL:
+		return "Normal";
+	case GT_FRAME_MODE_DSA:
+		return "DSA";
+	case GT_FRAME_MODE_PROVIDER:
+		return "Provider";
+	case GT_FRAME_MODE_ETHER_TYPE_DSA:
+		return "EtherType DSA";
+	default:
+		return "Invalid";
+	}
+}
+
+static char *mv_str_header_mode(GT_BOOL mode)
+{
+	switch (mode) {
+	case GT_FALSE:
+		return "False";
+	case GT_TRUE:
+		return "True";
+	default:
+		return "Invalid";
+	}
+}
+
+void mv_switch_status_print(void)
+{
+	int p;
+	GT_PORT_STP_STATE port_state = -1;
+	GT_EGRESS_MODE egress_mode = -1;
+	GT_FRAME_MODE frame_mode = -1;
+	GT_BOOL header_mode = -1;
+
+	if (qd_dev == NULL) {
+		printk(KERN_ERR "Switch is not initialized\n");
+		return;
+	}
+	printk(KERN_ERR "Printing Switch Status:\n");
+
+	printk(KERN_ERR "Port   State     Link   Duplex   Speed    Pause     Egress     Frame    Header\n");
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+
+		if (gstpGetPortState(qd_dev, p, &port_state) != GT_OK)
+			printk(KERN_ERR "gstpGetPortState failed\n");
+
+		if (gprtGetEgressMode(qd_dev, p, &egress_mode) != GT_OK)
+			printk(KERN_ERR "gprtGetEgressMode failed\n");
+
+		if (gprtGetFrameMode(qd_dev, p, &frame_mode) != GT_OK)
+			printk(KERN_ERR "gprtGetFrameMode failed\n");
+
+		if (gprtGetHeaderMode(qd_dev, p, &header_mode) != GT_OK)
+			printk(KERN_ERR "gprtGetHeaderMode failed\n");
+
+		printk(KERN_ERR "%2d, %10s,  %4s,  %4s,  %8s,  %7s,  %s,  %s,  %s\n",
+		       p, mv_str_port_state(port_state), mv_str_link_state(p),
+		       mv_str_duplex_state(p), mv_str_speed_state(p), mv_str_pause_state(p),
+		       mv_str_egress_mode(egress_mode), mv_str_frame_mode(frame_mode), mv_str_header_mode(header_mode));
+	}
+}
+
+int mv_switch_reg_read(int port, int reg, int type, MV_U16 *value)
+{
+	GT_STATUS status;
+
+	if (qd_dev == NULL) {
+		printk(KERN_ERR "Switch is not initialized\n");
+		return 1;
+	}
+
+	switch (type) {
+	case MV_SWITCH_PHY_ACCESS:
+		if (qsgmii_module)
+			printk(KERN_ERR "warning: cannot read Switch PHY register when QSGMII module is connected\n");
+		status = gprtGetPhyReg(qd_dev, port, reg, value);
+		break;
+
+	case MV_SWITCH_PORT_ACCESS:
+		status = gprtGetSwitchReg(qd_dev, port, reg, value);
+		break;
+
+	case MV_SWITCH_GLOBAL_ACCESS:
+		status = gprtGetGlobalReg(qd_dev, reg, value);
+		break;
+
+	case MV_SWITCH_GLOBAL2_ACCESS:
+		status = gprtGetGlobal2Reg(qd_dev, reg, value);
+		break;
+
+	case MV_SWITCH_SMI_ACCESS:
+		/* port means phyAddr */
+		status = miiSmiIfReadRegister(qd_dev, port, reg, value);
+		break;
+
+	default:
+		printk(KERN_ERR "%s Failed: Unexpected access type %d\n", __func__, type);
+		return 1;
+	}
+	if (status != GT_OK) {
+		printk(KERN_ERR "%s Failed: status = %d\n", __func__, status);
+		return 2;
+	}
+	return 0;
+}
+
+int mv_switch_reg_write(int port, int reg, int type, MV_U16 value)
+{
+	GT_STATUS status;
+
+	if (qd_dev == NULL) {
+		printk(KERN_ERR "Switch is not initialized\n");
+		return 1;
+	}
+
+	switch (type) {
+	case MV_SWITCH_PHY_ACCESS:
+		if (qsgmii_module)
+			printk(KERN_ERR "warning: cannot write Switch PHY register when QSGMII module is connected\n");
+		status = gprtSetPhyReg(qd_dev, port, reg, value);
+		break;
+
+	case MV_SWITCH_PORT_ACCESS:
+		status = gprtSetSwitchReg(qd_dev, port, reg, value);
+		break;
+
+	case MV_SWITCH_GLOBAL_ACCESS:
+		status = gprtSetGlobalReg(qd_dev, reg, value);
+		break;
+
+	case MV_SWITCH_GLOBAL2_ACCESS:
+		status = gprtSetGlobal2Reg(qd_dev, reg, value);
+		break;
+
+	case MV_SWITCH_SMI_ACCESS:
+		/* port means phyAddr */
+		status = miiSmiIfWriteRegister(qd_dev, port, reg, value);
+		break;
+
+	default:
+		printk(KERN_ERR "%s Failed: Unexpected access type %d\n", __func__, type);
+		return 1;
+	}
+	if (status != GT_OK) {
+		printk(KERN_ERR "%s Failed: status = %d\n", __func__, status);
+		return 2;
+	}
+	return 0;
+}
+
+int mv_switch_all_multicasts_del(int db_num)
+{
+	GT_STATUS status = GT_OK;
+	GT_ATU_ENTRY atu_entry;
+	GT_U8 mc_mac[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	GT_U8 bc_mac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+	memcpy(atu_entry.macAddr.arEther, &mc_mac, 6);
+	atu_entry.DBNum = db_num;
+
+	while ((status = gfdbGetAtuEntryNext(qd_dev, &atu_entry)) == GT_OK) {
+
+		/* we don't want to delete the broadcast entry which is the last one */
+		if (memcmp(atu_entry.macAddr.arEther, &bc_mac, 6) == 0)
+			break;
+
+		SWITCH_DBG(SWITCH_DBG_MCAST, ("Deleting ATU Entry: db = %d, MAC = %02X:%02X:%02X:%02X:%02X:%02X\n",
+					      atu_entry.DBNum, atu_entry.macAddr.arEther[0],
+					      atu_entry.macAddr.arEther[1], atu_entry.macAddr.arEther[2],
+					      atu_entry.macAddr.arEther[3], atu_entry.macAddr.arEther[4],
+					      atu_entry.macAddr.arEther[5]));
+
+		if (gfdbDelAtuEntry(qd_dev, &atu_entry) != GT_OK) {
+			printk(KERN_ERR "gfdbDelAtuEntry failed\n");
+			return -1;
+		}
+		memcpy(atu_entry.macAddr.arEther, &mc_mac, 6);
+		atu_entry.DBNum = db_num;
+	}
+
+	return 0;
+}
+
+int mv_switch_port_add(int switch_port, u16 vlan_grp_id, u16 port_map)
+{
+	int p;
+
+	/* Set default VLAN_ID for port */
+	if (gvlnSetPortVid(qd_dev, switch_port, MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, switch_port)) != GT_OK) {
+		printk(KERN_ERR "gvlnSetPortVid failed\n");
+		return -1;
+	}
+	/* Map port to VLAN DB */
+	if (gvlnSetPortVlanDBNum(qd_dev, switch_port, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id)) != GT_OK) {
+		printk(KERN_ERR "gvlnSetPortVlanDBNum failed\n");
+		return -1;
+	}
+
+	/* Add port to the VLAN (CPU port is not part of VLAN) */
+	if (mv_switch_port_based_vlan_set((port_map & ~(1 << qd_cpu_port)), 0) != 0)
+		printk(KERN_ERR "mv_switch_port_based_vlan_set failed\n");
+
+	/* Add port to vtu (used in tx) */
+	if (mv_switch_vlan_in_vtu_set(vlan_grp_id, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id),
+				      (port_map | (1 << qd_cpu_port)))) {
+		printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n");
+	}
+
+	/* set vtu with each port private vlan id (used in rx) */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(port_map, p) && (p != qd_cpu_port)) {
+			if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, p),
+						      MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id),
+						      port_map & ~(1 << qd_cpu_port)) != 0) {
+				printk(KERN_ERR "mv_switch_vlan_in_vtu_set failed\n");
+			}
+		}
+	}
+
+	/* Enable port */
+	if (gstpSetPortState(qd_dev, switch_port, GT_PORT_FORWARDING) != GT_OK)
+		printk(KERN_ERR "gstpSetPortState failed\n");
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+	if (!qsgmii_module) {
+		/* Enable Phy Link Status Changed interrupt at Phy level for the port */
+		if (gprtPhyIntEnable(qd_dev, switch_port, (GT_LINK_STATUS_CHANGED)) != GT_OK)
+			printk(KERN_ERR "gprtPhyIntEnable failed port %d\n", switch_port);
+	}
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+	return 0;
+}
+
+int mv_switch_port_del(int switch_port, u16 vlan_grp_id, u16 port_map)
+{
+	int p;
+
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+	if (!qsgmii_module) {
+		/* Disable link change interrupts on unmapped port */
+		if (gprtPhyIntEnable(qd_dev, switch_port, 0) != GT_OK)
+			printk(KERN_ERR "gprtPhyIntEnable failed on port #%d\n", switch_port);
+	}
+#endif /* CONFIG_MV_ETH_SWITCH_LINK */
+
+	/* Disable unmapped port */
+	if (gstpSetPortState(qd_dev, switch_port, GT_PORT_DISABLE) != GT_OK)
+		printk(KERN_ERR "gstpSetPortState failed on port #%d\n", switch_port);
+
+	/* Remove port from the VLAN (CPU port is not part of VLAN) */
+	if (mv_switch_port_based_vlan_set((port_map & ~(1 << qd_cpu_port)), 0) != 0)
+		printk(KERN_ERR "mv_gtw_set_port_based_vlan failed\n");
+
+	/* Remove port from vtu (used in tx) */
+	if (mv_switch_vlan_in_vtu_set(vlan_grp_id, MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id),
+				      (port_map | (1 << qd_cpu_port))) != 0) {
+		printk(KERN_ERR "mv_gtw_set_vlan_in_vtu failed\n");
+	}
+
+	/* Remove port from vtu of each port private vlan id (used in rx) */
+	for (p = 0; p < qd_dev->numOfPorts; p++) {
+		if (MV_BIT_CHECK(port_map, p) && (p != qd_cpu_port)) {
+			if (mv_switch_vlan_in_vtu_set(MV_SWITCH_PORT_VLAN_ID(vlan_grp_id, p),
+						      MV_SWITCH_VLAN_TO_GROUP(vlan_grp_id),
+						      (port_map & ~(1 << qd_cpu_port))) != 0)
+				printk(KERN_ERR "mv_gtw_set_vlan_in_vtu failed\n");
+		}
+	}
+
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch.h
new file mode 100755
index 0000000..8476349
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch.h
@@ -0,0 +1,72 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#ifndef __mv_switch_h__
+#define __mv_switch_h__
+
+#define MV_SWITCH_PHY_ACCESS			1
+#define MV_SWITCH_PORT_ACCESS			2
+#define MV_SWITCH_GLOBAL_ACCESS			3
+#define MV_SWITCH_GLOBAL2_ACCESS		4
+#define MV_SWITCH_SMI_ACCESS                	5
+
+#define MV_SWITCH_PORT_VLAN_ID(grp, port)  ((grp) + (port) + 1)
+#define MV_SWITCH_GROUP_VLAN_ID(grp)       (((grp) + 1) << 8)
+#define MV_SWITCH_VLAN_TO_GROUP(vid)       ((((vid) & 0xf00) >> 8) - 1)
+
+int     mv_switch_load(unsigned int switch_ports_mask);
+int     mv_switch_unload(unsigned int switch_ports_mask);
+int     mv_switch_init(int mtu, unsigned int switch_ports_mask);
+void    mv_switch_link_update_event(MV_U32 port_mask, int force_link_check);
+int     mv_switch_jumbo_mode_set(int max_size);
+int     mv_switch_tos_get(unsigned char tos);
+int     mv_switch_tos_set(unsigned char tos, int queue);
+int     mv_switch_port_based_vlan_set(unsigned int ports_mask, int set_cpu_port);
+int     mv_switch_vlan_in_vtu_set(unsigned short vlan_id, unsigned short db_num, unsigned int ports_mask);
+int     mv_switch_mac_addr_set(unsigned char *mac_addr, unsigned char db,
+			       unsigned int ports_mask, unsigned char op);
+int     mv_switch_atu_db_flush(int db_num);
+int     mv_eth_switch_vlan_set(u16 vlan_grp_id, u16 port_map, u16 cpu_port);
+int     mv_switch_promisc_set(u16 vlan_grp_id, u16 port_map, u16 cpu_port, u8 promisc_on);
+unsigned int    mv_switch_link_detection_init(void);
+
+int     mv_switch_reg_read(int port, int reg, int type, MV_U16 *value);
+int     mv_switch_reg_write(int port, int reg, int type, MV_U16 value);
+
+void    mv_switch_stats_print(void);
+void    mv_switch_status_print(void);
+
+int     mv_switch_all_multicasts_del(int db_num);
+
+int     mv_switch_port_add(int switch_port, u16 vlan_grp_id, u16 port_map);
+int     mv_switch_port_del(int switch_port, u16 vlan_grp_id, u16 port_map);
+
+#ifdef CONFIG_MV_ETH_SWITCH_LINK
+MV_U32  mv_switch_get_port_los_alarm(MV_U32 *eth_alarm);
+#endif
+
+#endif /* __mv_switch_h__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_sysfs.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_sysfs.c
new file mode 100755
index 0000000..f6b19e8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_sysfs.c
@@ -0,0 +1,205 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+
+#include "mvTypes.h"
+#include "mv_switch.h"
+#include "../mv_neta/net_dev/mv_netdev.h"
+
+static ssize_t mv_switch_help(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "cat help                            - show this help\n");
+	off += sprintf(buf+off, "cat stats                           - show statistics for switch all ports info\n");
+	off += sprintf(buf+off, "cat status                          - show switch status\n");
+#ifdef CONFIG_MV_ETH_SWITCH
+	off += sprintf(buf+off, "echo <eth_name>   > netdev_sts      - print network device status\n");
+	off += sprintf(buf+off, "echo <eth_name> p > port_add        - map switch port to a network device\n");
+	off += sprintf(buf+off, "echo <eth_name> p > port_del        - unmap switch port from a network device\n");
+#endif /* CONFIG_MV_ETH_SWITCH */
+	off += sprintf(buf+off, "echo p r t   > reg_r                - read switch register.  t: 1-phy, 2-port, 3-global, 4-global2, 5-smi\n");
+	off += sprintf(buf+off, "echo p r t v > reg_w                - write switch register. t: 1-phy, 2-port, 3-global, 4-global2, 5-smi\n");
+	return off;
+}
+
+static ssize_t mv_switch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	const char *name = attr->attr.name;
+	int off = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "stats"))
+		mv_switch_stats_print();
+	else if (!strcmp(name, "status"))
+		mv_switch_status_print();
+	else
+		off = mv_switch_help(buf);
+
+	return off;
+}
+
+static ssize_t mv_switch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	unsigned long   flags;
+	int             err, port, reg, type;
+	unsigned int    v;
+	MV_U16          val;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read arguments */
+	err = port = reg = type = val = 0;
+	sscanf(buf, "%d %d %d %x", &port, &reg, &type, &v);
+
+	local_irq_save(flags);
+	if (!strcmp(name, "reg_r")) {
+		err = mv_switch_reg_read(port, reg, type, &val);
+	} else if (!strcmp(name, "reg_w")) {
+		val = (MV_U16)v;
+		err = mv_switch_reg_write(port, reg, type, v);
+	}
+	printk(KERN_ERR "switch register access: type=%d, port=%d, reg=%d", type, port, reg);
+
+	if (err)
+		printk(KERN_ERR " - FAILED, err=%d\n", err);
+	else
+		printk(KERN_ERR " - SUCCESS, val=0x%04x\n", val);
+
+	local_irq_restore(flags);
+
+	return err ? -EINVAL : len;
+}
+
+#ifdef CONFIG_MV_ETH_SWITCH
+static ssize_t mv_switch_netdev_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	int             err = 0, port = 0;
+	char            dev_name[30];
+	struct net_device *netdev;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read arguments */
+	sscanf(buf, "%s %d", dev_name, &port);
+	netdev = dev_get_by_name(&init_net, dev_name);
+	if (netdev == NULL) {
+		err = 1;
+	} else {
+		if (!strcmp(name, "netdev_sts"))
+			mv_eth_netdev_print(netdev);
+		else if (!strcmp(name, "port_add"))
+			err = mv_eth_switch_port_add(netdev, port);
+		else if (!strcmp(name, "port_del"))
+			err = mv_eth_switch_port_del(netdev, port);
+
+		dev_put(netdev);
+	}
+
+	if (err)
+		printk(KERN_ERR " - FAILED, err=%d\n", err);
+	else
+		printk(KERN_ERR " - SUCCESS\n");
+
+	return err ? -EINVAL : len;
+}
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+static DEVICE_ATTR(reg_r,       S_IWUSR, mv_switch_show, mv_switch_store);
+static DEVICE_ATTR(reg_w,       S_IWUSR, mv_switch_show, mv_switch_store);
+static DEVICE_ATTR(status,      S_IRUSR, mv_switch_show, mv_switch_store);
+static DEVICE_ATTR(stats,       S_IRUSR, mv_switch_show, mv_switch_store);
+static DEVICE_ATTR(help,        S_IRUSR, mv_switch_show, mv_switch_store);
+#ifdef CONFIG_MV_ETH_SWITCH
+static DEVICE_ATTR(netdev_sts,  S_IWUSR, mv_switch_show, mv_switch_netdev_store);
+static DEVICE_ATTR(port_add,    S_IWUSR, mv_switch_show, mv_switch_netdev_store);
+static DEVICE_ATTR(port_del,    S_IWUSR, mv_switch_show, mv_switch_netdev_store);
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+static struct attribute *mv_switch_attrs[] = {
+	&dev_attr_reg_r.attr,
+	&dev_attr_reg_w.attr,
+	&dev_attr_status.attr,
+	&dev_attr_stats.attr,
+	&dev_attr_help.attr,
+#ifdef CONFIG_MV_ETH_SWITCH
+	&dev_attr_netdev_sts.attr,
+	&dev_attr_port_add.attr,
+	&dev_attr_port_del.attr,
+#endif /* CONFIG_MV_ETH_SWITCH */
+	NULL
+};
+
+static struct attribute_group mv_switch_group = {
+	.name = "switch",
+	.attrs = mv_switch_attrs,
+};
+
+int __devinit mv_switch_sysfs_init(void)
+{
+	int err;
+	struct device *pd;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	if (!pd) {
+		platform_device_register_simple("neta", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR "%s: cannot find neta device\n", __func__);
+		pd = &platform_bus;
+	}
+
+	err = sysfs_create_group(&pd->kobj, &mv_switch_group);
+	if (err) {
+		printk(KERN_INFO "sysfs group failed %d\n", err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+module_init(mv_switch_sysfs_init);
+
+MODULE_AUTHOR("Dima Epshtein");
+MODULE_DESCRIPTION("sysfs for Marvell switch");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.c
new file mode 100755
index 0000000..5c27c0d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.c
@@ -0,0 +1,5103 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include <linux/etherdevice.h>
+#include <gtHwCntl.h>
+#include "mvOs.h"
+#include "mvSysHwConfig.h"
+#include "eth-phy/mvEthPhy.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ctrlEnv/mvCtrlEthCompLib.h"
+
+#include "msApi.h"
+#include "msApiPrototype.h"
+#include "mv_switch.h"
+#include "mv_switch_wrap.h"
+
+static sw_port_type_info   sw_ports_tbl[SW_MAX_PORTS_NUM];
+static sw_vlan_tbl_type    sw_vlan_tbl[SW_MAX_VLAN_NUM];
+
+static uint8_t   weight_arr[4] = {0};
+extern GT_QD_DEV *qd_dev;
+
+
+/*******************************************************************************
+* mv_switch_prv_port_add_vid
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per lport.
+*
+* INPUTS:
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       see the example sample802_1qSetup().
+*
+*******************************************************************************/
+int32_t mv_switch_prv_port_add_vid
+(
+    uint16_t vid
+)
+{
+    GT_STATUS    rc = GT_OK;
+    GT_VTU_ENTRY tmpVtuEntry;
+    uint32_t     found = GT_FALSE;
+    uint32_t     port;
+
+    memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+    tmpVtuEntry.vid   = vid;
+
+    rc = gvtuFindVidEntry(qd_dev, &tmpVtuEntry, &found);
+    if ( (rc != GT_OK) && (rc != GT_NO_SUCH) )
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gvtuFindVidEntry failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        return GT_FAIL;
+    }
+
+    printk(KERN_DEBUG "%s: found[%d]\n\r", __FUNCTION__,found);
+
+    if (found == GT_FALSE)/* VTU entry does not exist */
+    {
+        /* Add new VTU entry with VLAN ID vid with lport as members of the Vlan vid. */
+        tmpVtuEntry.DBNum                           = 0;
+        tmpVtuEntry.vid                             = vid;
+        tmpVtuEntry.vidPriOverride                  = GT_FALSE;
+        tmpVtuEntry.vidPriority                     = 0;
+        tmpVtuEntry.vidExInfo.useVIDFPri            = GT_FALSE;
+        tmpVtuEntry.vidExInfo.vidFPri               = 0;
+        tmpVtuEntry.vidExInfo.useVIDQPri            = GT_FALSE;
+        tmpVtuEntry.vidExInfo.vidQPri               = 0;
+        tmpVtuEntry.vidExInfo.vidNRateLimit         = GT_FALSE;
+
+    }
+
+    /* In case the VTU entry exist:
+     *
+     *      Update the VTU entry with update vtuEntry.vtuData.memberTagP[port].
+     *      The previous VTU data stored in tmpVtuEntry
+     */
+
+    for (port=0; port < qd_dev->numOfPorts; port++)
+    {
+        if (sw_vlan_tbl[vid].members & (1 << port)){
+            tmpVtuEntry.vtuData.memberTagP[port] = sw_vlan_tbl[vid].egr_mode[port];
+        }
+        else{
+            tmpVtuEntry.vtuData.memberTagP[port] = NOT_A_MEMBER;
+
+        }
+    }
+
+    rc = gvtuAddEntry(qd_dev,&tmpVtuEntry);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gvtuAddEntry failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        return GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_prv_del_vid_per_port
+*
+* DESCRIPTION:
+*       The API delete and existing VID from the list of VIDs allowed per lport.
+*
+* INPUTS:
+*       port     - port for deleting the VID.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_prv_del_vid_per_port
+(
+    uint32_t port,
+    uint16_t vid
+)
+{
+    GT_STATUS    rc = GT_OK;
+    GT_VTU_ENTRY tmpVtuEntry;
+    uint32_t     found = GT_TRUE;
+    GT_U8        port_idx;
+    uint32_t     isVlanMember = 0;
+
+    memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+    tmpVtuEntry.vid = vid;
+
+    rc = gvtuFindVidEntry(qd_dev, &tmpVtuEntry, &found);
+    if ( (rc != GT_OK) && (rc != GT_NO_SUCH) )
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gvtuFindVidEntry failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+        goto out_func;
+    }
+
+    if (found == GT_TRUE) /* VTU entry exist */
+    {
+        /* 1. Mark the lport as NOT_A_MEMBER. */
+        tmpVtuEntry.vtuData.memberTagP[port] = NOT_A_MEMBER;
+
+        /* 2. Search whether a secure port is a member of the VLAN */
+        for(port_idx=0; port_idx < qd_dev->numOfPorts; port_idx++)
+        {
+            if ((tmpVtuEntry.vtuData.memberTagP[port_idx] != NOT_A_MEMBER) &&
+                 ((sw_ports_tbl[port_idx].port_mode == GT_SECURE)||
+                  (sw_ports_tbl[port_idx].vlan_blong[vid]==SW_PORT_BELONG)) )
+            {
+                isVlanMember = 1;
+                break;
+            }
+        }
+
+        if (isVlanMember == 1) /* Only update the VTU */
+        {
+            rc = gvtuAddEntry(qd_dev,&tmpVtuEntry);
+            if (rc != GT_OK)
+            {
+                printk(KERN_ERR "%s:%d:==ERROR==gvtuAddEntry failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                rc = GT_FAIL;
+                goto out_func;
+            }
+
+            sw_vlan_tbl[vid].members &= ~(((uint32_t)0x1) << (port));/* Delete port from VID DB */
+        }
+        else/* Delete VTU */
+        {
+            rc = gvtuDelEntry(qd_dev, &tmpVtuEntry);
+            if (rc != GT_OK)
+            {
+                printk(KERN_ERR "%s:%d:==ERROR==gvtuDelEntry failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                rc = GT_FAIL;
+                goto out_func;
+            }
+
+            sw_vlan_tbl[vid].members = 0;
+        }
+    }
+    else /* VTU entry does not exist in search */
+    {
+        printk(KERN_ERR "%s:%d:==ERROR== No Such VID\r\n",__FUNCTION__,__LINE__);
+
+        rc = GT_FAIL;
+        goto out_func;
+
+    }
+
+out_func:
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_add_static_mac
+*
+* DESCRIPTION:
+*       This function creates a static MAC entry in the MAC address table for a
+*       specific lport in the integrated switch
+*
+* INPUTS:
+*       lport		- Packet origination.
+*       static_mac	- 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_add_static_mac
+(
+	IN uint32_t lport,
+    IN uint8_t  static_mac[6]
+)
+{
+    GT_STATUS    rc = GT_OK;
+    GT_ATU_ENTRY mac_entry;
+
+    memset(&mac_entry, 0, sizeof(GT_ATU_ENTRY));
+
+    mac_entry.trunkMember = GT_FALSE;
+    mac_entry.prio = 0;
+    mac_entry.exPrio.useMacFPri = 0;
+    mac_entry.exPrio.macFPri = 0;
+    mac_entry.exPrio.macQPri = 0;
+    mac_entry.DBNum = 0;
+    mac_entry.entryState.mcEntryState = GT_UC_STATIC;
+    mac_entry.portVec = 1 << lport;
+    memcpy(mac_entry.macAddr.arEther, static_mac, 6);
+
+    rc = gfdbAddMacEntry(qd_dev, &mac_entry);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbAddMacEntry failed rc[0x%x]\n\r",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_del_static_mac
+*
+* DESCRIPTION:
+*       This function removes an existing static MAC entry from the MAC address
+*       table  in the integrated switch.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       static_mac	- 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_del_static_mac
+(
+    IN uint8_t static_mac[6]
+)
+{
+    GT_STATUS    rc = GT_OK;
+    GT_ETHERADDR macAddress;
+
+    memcpy(&macAddress.arEther, static_mac, GT_ETHERNET_HEADER_SIZE);
+
+    rc = gfdbDelMacEntry(qd_dev, &macAddress);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbDelMacEntry failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_max_macs
+*
+* DESCRIPTION:
+*       This function limits the number of MAC addresses per lport.
+*
+* INPUTS:
+*       lport		 - Packet origination.
+*       mac_per_port - maximum number of MAC addresses per port (1-255).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       The following care is needed when enabling this feature:
+*			1) disable learning on the ports
+*			2) flush all non-static addresses in the ATU
+*			3) define the desired limit for the ports
+*			4) re-enable learing on the ports
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_max_macs
+(
+    IN uint32_t lport,
+    IN uint8_t 	mac_per_port
+)
+{
+    GT_STATUS rc = GT_OK;
+
+#if 0
+    /* Efi Dror - Not neccary to perform - disable learning on the ports*/
+
+    /* dsable learning on the ports */
+    rc = gprtSetLearnDisable(qd_dev, lport,GT_TRUE);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetLearnDisable failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+        goto out_func;
+    }
+
+    /* Efi Dror - Not neccary to perform - Flash all adresses in ATU*/
+
+    /* Flash all adresses in ATU */
+    rc = gfdbFlush(qd_dev, GT_FLUSH_ALL);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbFlush failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+        goto out_func;
+    }
+#endif
+
+    /* define the desired limit for the ports */
+    rc = gfdbSetPortAtuLearnLimit(qd_dev, lport, mac_per_port);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbSetPortAtuLearnLimit failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+        goto out_func;
+    }
+
+#if 0
+    /* Efi Dror - Not neccary to perform - re-enable learing on the ports */
+
+    /* re-enable learing on the ports */
+    rc = gprtSetLearnDisable(qd_dev, lport,GT_FALSE);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetLearnDisable failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+        goto out_func;
+    }
+#endif
+
+out_func:
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_max_macs
+*
+* DESCRIPTION:
+*      Port's auto learning limit. When the limit is non-zero value, the number
+*		of MAC addresses that can be learned on this lport are limited to the value
+*		specified in this API. When the learn limit has been reached any frame
+*		that ingresses this lport with a source MAC address not already in the
+*		address database that is associated with this lport will be discarded.
+*		Normal auto-learning will resume on the lport as soon as the number of
+*		active unicast MAC addresses associated to this lport is less than the
+*		learn limit.
+*		CPU directed ATU Load, Purge, or Move will not have any effect on the
+*		learn limit.
+*		This feature is disabled when the limit is zero.
+*		The following care is needed when enabling this feature:
+*			1) dsable learning on the ports
+*			2) flush all non-static addresses in the ATU
+*			3) define the desired limit for the ports
+*			4) re-enable learing on the ports
+*
+* INPUTS:
+*       owner_id	 - APP owner id - should be used for all API calls.
+*       lport		 - Packet origination.
+*
+*
+* OUTPUTS:
+*       limit - maximum number of MAC addresses per lport (1-255).
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_max_macs
+(
+    IN uint32_t  lport,
+    OUT uint32_t *limit
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gfdbGetPortAtuLearnLimit(qd_dev, lport, (GT_U32*)limit);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbGetPortAtuLearnLimit failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_clear_dynamic_mac
+*
+* DESCRIPTION:
+*       Clear all dynamic MAC.
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_clear_dynamic_mac(void)
+{
+     GT_STATUS rc = GT_OK;
+
+    rc = gfdbClearAtuDynamicEntry(qd_dev);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbClearAtuDynamicEntry failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_mirror
+*
+* DESCRIPTION:
+*       Set port mirror.
+*
+* INPUTS:
+*       sport		 - Source port.
+*       dport		 - Destination port.
+*       mode		 - mirror mode.
+*       enable		 - enable/disable mirror.
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_set_mirror(IN uint32_t  sport, IN uint32_t  dport, IN GT_MIRROR_MODE mode, IN GT_BOOL enable)
+{
+    GT_STATUS rc = GT_OK;
+
+    switch(mode)
+    {
+        case SW_MIRROR_INGRESS:
+	     /*enable mirror*/
+	     if(enable == GT_TRUE)
+	     {
+    	         /*enable ingress monitor source register*/
+    	         rc = gprtSetIngressMonitorSource(qd_dev, sport, GT_TRUE);
+                if (rc != GT_OK)
+                {
+                    printk(KERN_ERR "%s:%d:==ERROR==gprtSetIngressMonitorSource failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                    rc = GT_FAIL;
+                }
+
+    	         /*set ingress monitor destination register*/
+    	         rc = gsysSetIngressMonitorDest(qd_dev, dport);
+                if (rc != GT_OK)
+                {
+                    printk(KERN_ERR "%s:%d:==ERROR==gprtSetIngressMonitorSource failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                    rc = GT_FAIL;
+                }
+	     }
+	     else
+	     {
+	          /*disable ingress monitor source register*/
+    	         rc = gprtSetIngressMonitorSource(qd_dev, sport, GT_FALSE);
+                if (rc != GT_OK)
+                {
+                    printk(KERN_ERR "%s:%d:==ERROR==gprtSetIngressMonitorSource failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                    rc = GT_FAIL;
+                }
+	     }
+
+	     break;
+
+        case SW_MIRROR_EGRESS:
+
+	     /*enable mirror*/
+	     if(enable == GT_TRUE)
+	     {
+    	         /*enable egress monitor source register*/
+    	         rc = gprtSetEgressMonitorSource(qd_dev, sport, GT_TRUE);
+                if (rc != GT_OK)
+                {
+                    printk(KERN_ERR "%s:%d:==ERROR==gprtSetEgressMonitorSource failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                    rc = GT_FAIL;
+                }
+
+    	         /*set egress monitor destination register*/
+    	         rc = gsysSetEgressMonitorDest(qd_dev, dport);
+                if (rc != GT_OK)
+                {
+                    printk(KERN_ERR "%s:%d:==ERROR==gsysSetEgressMonitorDest failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                    rc = GT_FAIL;
+                }
+	     }
+	     else
+	     {
+	          /*disable egress monitor source register*/
+    	         rc = gprtSetEgressMonitorSource(qd_dev, sport, GT_FALSE);
+                if (rc != GT_OK)
+                {
+                    printk(KERN_ERR "%s:%d:==ERROR==gprtSetEgressMonitorSource failed rc[0x%x]\r\n",
+                       __FUNCTION__, __LINE__, rc);
+
+                    rc = GT_FAIL;
+                }
+	     }
+
+	     break;
+
+	 default:
+	     break;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_mirror
+*
+* DESCRIPTION:
+*       Get port mirror status.
+*
+* INPUTS:
+*       sport		 - Source port.
+*       dport		 - Destination port.
+*       mode		 - mirror mode.
+*
+* OUTPUTS:
+*       enable		 - enable/disable mirror.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_get_mirror(IN uint32_t  sport, IN uint32_t  dport, IN GT_MIRROR_MODE mode, OUT GT_BOOL* enable)
+{
+    GT_STATUS rc = GT_OK;
+
+    switch(mode)
+    {
+        case SW_MIRROR_INGRESS:
+
+            /*Get ingress monitor source register status*/
+            rc = gprtGetIngressMonitorSource(qd_dev, sport, enable);
+            if (rc != GT_OK)
+            {
+                printk(KERN_ERR "%s:%d:==ERROR==gprtGetIngressMonitorSource failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+                rc = GT_FAIL;
+            }
+
+	     break;
+
+        case SW_MIRROR_EGRESS:
+
+            /*Get egress monitor source register status*/
+            rc = gprtGetEgressMonitorSource(qd_dev, sport, enable);
+            if (rc != GT_OK)
+            {
+                printk(KERN_ERR "%s:%d:==ERROR==gprtGetEgressMonitorSource failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+                rc = GT_FAIL;
+            }
+
+	     break;
+
+	 default:
+	     break;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_mtu
+*
+* DESCRIPTION:
+*       Set switch MTU size.
+*
+* INPUTS:
+*       mtu		 - MTU size.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_set_mtu(IN uint32_t mtu)
+{
+    uint32_t  i;
+    GT_STATUS rc = GT_OK;
+    GT_JUMBO_MODE   jumbo_mode;
+
+    /* Set jumbo frames mode */
+    if(mtu <= 1522)
+        jumbo_mode = GT_JUMBO_MODE_1522;
+    else if(mtu <= 2048)
+        jumbo_mode = GT_JUMBO_MODE_2048;
+    else
+       	jumbo_mode = GT_JUMBO_MODE_10240;
+
+    for(i=0; i<qd_dev->numOfPorts; i++)
+    {
+    	 /*Set switch MTU*/
+	      rc = gsysSetJumboMode(qd_dev, i, jumbo_mode);
+	      if (rc != GT_OK)
+          {
+              printk(KERN_ERR "%s:%d:==ERROR==gsysSetJumboMode failed rc[0x%x]\r\n",
+                 __FUNCTION__, __LINE__, rc);
+
+              rc = GT_FAIL;
+				return rc;
+          }
+    }
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_mtu
+*
+* DESCRIPTION:
+*       Get switch MTU size.
+*
+* INPUTS:
+*
+*
+* OUTPUTS:
+*       mtu		 - MTU size.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_get_mtu(OUT uint32_t* mtu)
+{
+    GT_STATUS rc = GT_OK;
+    GT_JUMBO_MODE   jumbo_mode;
+
+	/*Get switch MTU*/
+	rc = gsysGetJumboMode(qd_dev, 4/*uplink port for DEV_88E6351_FAMILY switch*/, &jumbo_mode);
+	if (rc != GT_OK)
+	{
+		printk(KERN_ERR "%s:%d:==ERROR==gsysSetJumboMode failed rc[0x%x]\r\n",
+		   __FUNCTION__, __LINE__, rc);
+
+		rc = GT_FAIL;
+	}
+
+    /* Convert jumbo frames mode to MTU size */
+    if(jumbo_mode == GT_JUMBO_MODE_1522)
+		*mtu = 1522;
+    else if(jumbo_mode == GT_JUMBO_MODE_2048)
+		*mtu = 2048;
+    else
+		*mtu = 10240;
+
+    return rc;
+}
+
+
+
+#if 0 /* The masked one is old code, just remains as a reference*/
+/*******************************************************************************
+* mv_switch_set_port_flooding
+*
+* DESCRIPTION:
+*       This function control the flooding behavior (unknown Dest MAC address) per lport.
+*
+* INPUTS:
+*       owner_id	 - APP owner id - should be used for all API calls.
+*       egress_port	 - Egress lport for applying the flood settings.
+*       allow_flood  - permit flooding of unknown DA: set to 1,
+*                      do not permit flooding of uknown DA: set to 0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_flooding
+(
+    IN uint32_t lport,
+    IN GT_BOOL 	mode
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtSetForwardUnknown(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetForwardUnknown failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_flooding
+*
+* DESCRIPTION:
+*       This routine gets Forward Unknown mode of a switch port.
+*		When this mode is set to GT_TRUE, normal switch operation occurs.
+*		When this mode is set to GT_FALSE, unicast frame with unknown DA addresses
+*		will not egress out this port.
+*
+* INPUTS:
+*       owner_id	 - APP owner id - should be used for all API calls.
+*       egress_port	 - Egress port for applying the flood settings.
+*
+*
+* OUTPUTS:
+*       mode  -  GT_TRUE: header mode enabled
+*				 GT_FALSE otherwise.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_flooding
+(
+    IN  uint32_t lport,
+    OUT uint32_t *mode
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtGetForwardUnknown(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetForwardUnknown failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+#endif
+
+/*******************************************************************************
+* mv_switch_set_port_tagged
+*
+* DESCRIPTION:
+*       The API allows or drops tagged packets on a per lport basis.
+*
+* INPUTS:
+*       lport		 -  lport for applying the filtering of tagged packets.
+*       mode         - set to 1 = discard tagged packets per lport
+*                      set to 0 = allow tagged packets per lport.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_tagged
+(
+    IN uint32_t lport,
+    IN GT_BOOL  mode
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtSetDiscardTagged(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetDiscardTagged failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_tagged
+*
+* DESCRIPTION:
+*       This routine gets DiscardTagged bit for the given lport.
+*
+* INPUTS:
+*       lport		 - lport for applying the filtering of tagged packets.
+
+*
+* OUTPUTS:
+*      mode  - GT_TRUE if DiscardTagged bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_tagged
+(
+    IN  uint32_t lport,
+    OUT uint32_t *mode
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtGetDiscardTagged(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetDiscardTagged failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_OK;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_untagged
+*
+* DESCRIPTION:
+*       The API allows or drops untagged packets on a per lport basis.
+*
+* INPUTS:
+*       lport		   -  lport for applying the filtering of tagged packets.
+*       mode           - set to 1 = discard untagged packets per lport
+*                        set to 0 = alow untagged packets per lport.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_untagged
+(
+    IN uint32_t lport,
+    IN GT_BOOL 	mode
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtSetDiscardUntagged(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetDiscardUntagged failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_OK;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_untagged
+*
+* DESCRIPTION:
+*       This routine gets DiscardUntagged bit for the given lport.
+*
+* INPUTS:
+*       lport		   -  lport for applying the filtering of tagged packets.
+
+*
+* OUTPUTS:
+*       mode  - GT_TRUE if DiscardUntagged bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_untagged
+(
+    IN  uint32_t lport,
+    OUT uint32_t *mode
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtGetDiscardUntagged(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetDiscardUntagged failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_def_vlan
+*
+* DESCRIPTION:
+*       The API sets port default vlan id.
+*
+* INPUTS:
+*       lport	   - lport for applying the filtering of tagged packets.
+*       vid        - the port vlan id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_def_vlan
+(
+    IN uint32_t lport,
+    IN GT_U16 	vid
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gvlnSetPortVid(qd_dev, lport, vid);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gvlnSetPortVid failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_OK;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_def_vlan
+*
+* DESCRIPTION:
+*       This routine gets DiscardUntagged bit for the given lport.
+*
+* INPUTS:
+*       lport	   - lport for applying the filtering of tagged packets.
+*
+* OUTPUTS:
+*       vid        - the port vlan id
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_def_vlan
+(
+    IN  uint32_t lport,
+    OUT GT_U16 	*vid
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gvlnGetPortVid(qd_dev, lport, vid);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gvlnGetPortVid failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+
+/*******************************************************************************
+* mv_switch_set_port_def_pri
+*
+* DESCRIPTION:
+*       The API sets port default priority.
+*
+* INPUTS:
+*       lport	   - lport for applying the filtering of tagged packets.
+*       pri        - the port priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_def_pri
+(
+    IN uint32_t lport,
+    IN GT_U8 	pri
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gcosSetPortDefaultTc(qd_dev, lport, pri);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gcosSetPortDefaultTc failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_OK;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_def_pri
+*
+* DESCRIPTION:
+*       The API gets port default priority.
+*
+* INPUTS:
+*       lport	   - lport for applying the filtering of tagged packets.
+*
+* OUTPUTS:
+*       pri        - the port priority.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_def_pri
+(
+    IN  uint32_t lport,
+    OUT GT_U8 	*pri
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gcosGetPortDefaultTc(qd_dev, lport, pri);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gcosGetPortDefaultTc failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_port_add_vid
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       lport     -  lport for adding the vid.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       see the example sample802_1qSetup().
+*
+*******************************************************************************/
+int32_t mv_switch_port_add_vid
+(
+    IN uint32_t lport,
+    IN uint16_t vid,
+    IN uint16_t gmac0Idx
+)
+{
+    GT_STATUS rc = GT_OK;
+    uint32_t  port;
+    uint32_t  port_bm;
+
+    /* Verify whether the port is already a member of this VID */
+    port_bm = (uint32_t)(1 << lport);
+    if ( !(sw_vlan_tbl[vid].members & port_bm) )
+    {
+        /* All fallback ports are also added to this VLAN in order
+           to support traffic on this VLAN with all fallback ports */
+        for(port = 0; port < qd_dev->numOfPorts; port++)
+        {
+            if (port == lport)
+            {
+                sw_vlan_tbl[vid].members |= port_bm;
+                sw_vlan_tbl[vid].egr_mode[port] = MEMBER_EGRESS_UNMODIFIED;
+            }
+            else
+            {
+                #if 0
+                if (sw_ports_tbl[port].port_mode == GT_FALLBACK && \
+                    !(sw_vlan_tbl[vid].members & (1 << port)))
+                {
+                    sw_vlan_tbl[vid].members |= (uint32_t)(1 << port);
+                    sw_vlan_tbl[vid].egr_mode[port] = MEMBER_EGRESS_UNMODIFIED;
+                }
+                #endif
+            }
+        }
+
+        /*if (sw_ports_tbl[gmac0Idx].port_mode == GT_FALLBACK &&
+            !(sw_vlan_tbl[vid].members & (1 << gmac0Idx)))*/
+        /* Always add GMAC_0 to VLAN */
+        if (!(sw_vlan_tbl[vid].members & (1 << gmac0Idx)))
+        {
+            sw_vlan_tbl[vid].members |= (uint32_t)(1 << gmac0Idx);
+            sw_vlan_tbl[vid].egr_mode[gmac0Idx] = MEMBER_EGRESS_UNMODIFIED;
+        }
+
+        rc = mv_switch_prv_port_add_vid(vid);
+        if (rc != GT_OK)
+        {
+            printk(KERN_ERR "%s:%d:==ERROR== failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+            rc = GT_FAIL;
+        }
+    }
+
+    /* Add the specified port to the SW Port table */
+    if (sw_ports_tbl[lport].vlan_blong[vid] == SW_PORT_NOT_BELONG)
+    {
+        sw_ports_tbl[lport].cnt++;
+        sw_ports_tbl[lport].vlan_blong[vid] = SW_PORT_BELONG;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_del_vid_per_port
+*
+* DESCRIPTION:
+*       The API delete and existing VID from the list of VIDs allowed per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       lport     -  lport for deleting the VID.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_del_vid_per_port
+(
+    IN uint32_t lport,
+    IN uint16_t vid
+)
+{
+    GT_STATUS rc = GT_OK;
+    uint32_t  port_bm;
+
+    /* Verify whether the port is a member of this VID */
+    port_bm = (uint32_t)(1 << lport);
+    if ( sw_vlan_tbl[vid].members & port_bm )
+    {
+        rc = mv_switch_prv_del_vid_per_port(lport, vid);
+        if (rc != GT_OK)
+        {
+            printk(KERN_ERR "%s:%d:==ERROR==tpm_sw_prv_del_vid_per_port failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+            rc = GT_FAIL;
+        }
+        else
+        {
+            if (sw_ports_tbl[lport].vlan_blong[vid] == SW_PORT_BELONG )
+            {
+                if (sw_ports_tbl[lport].cnt)
+                    sw_ports_tbl[lport].cnt--;
+                sw_ports_tbl[lport].vlan_blong[vid] = SW_PORT_NOT_BELONG;
+                sw_vlan_tbl[vid].egr_mode[lport]    = NOT_A_MEMBER;
+            }
+        }
+            }
+
+
+    return rc;
+        }
+
+/*******************************************************************************
+* mv_switch_set_port_vid_egress_mode
+*
+* DESCRIPTION:
+*       The API sets the egress mode for a member port of a vlan.
+*
+* INPUTS:
+*       lport     - logic port id to set
+*       vid       - vlan id
+*       vid       - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_vid_egress_mode
+(
+    IN uint32_t lport,
+    IN uint16_t vid,
+    IN uint8_t  eMode
+)
+{
+    GT_STATUS    rc = GT_OK;
+    GT_VTU_ENTRY vtuEntry;
+    GT_BOOL      found = GT_FALSE;
+
+    /* If the port is the member of vlan, set */
+    if (sw_vlan_tbl[vid].members & (1 << lport))
+    {
+        sw_vlan_tbl[vid].egr_mode[lport] = eMode;
+
+        memset(&vtuEntry, 0, sizeof(GT_VTU_ENTRY));
+        vtuEntry.vid = vid;
+
+        rc = gvtuFindVidEntry(qd_dev, &vtuEntry, &found);
+        if (rc != GT_OK && rc != GT_NO_SUCH)
+        {
+            printk(KERN_ERR"%s:%d:==ERROR==gvtuFindVidEntry failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+            return GT_FAIL;
+    }
+
+        printk(KERN_DEBUG "%s: found[%d]\n\r", __FUNCTION__, found);
+
+        vtuEntry.vtuData.memberTagP[lport] = eMode;
+
+        rc = gvtuAddEntry(qd_dev, &vtuEntry);
+        if (rc != GT_OK)
+        {
+            printk(KERN_ERR"%s:%d:==ERROR==gvtuAddEntry failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+            return GT_FAIL;
+        }
+    }
+    else
+    {
+        printk(KERN_ERR"%s:%d:==ERROR==port[%d] is not the member of vlan[%d]\r\n",
+               __FUNCTION__, __LINE__, lport, vid);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_port_print_vid
+*
+* DESCRIPTION:
+*       The API return VID to the list of the allowed VIDs per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       vid     -  searching VID.
+*
+* OUTPUTS:
+*        found    - GT_TRUE, if the appropriate entry exists.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_port_print_vid
+(
+    IN  uint32_t vid,
+    OUT uint32_t *found
+)
+{
+    GT_STATUS    rc = GT_OK;
+    GT_VTU_ENTRY tmpVtuEntry;
+    uint32_t     portIndex;
+    uint32_t     port;
+
+    memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+	tmpVtuEntry.vid = vid;
+
+    rc = gvtuFindVidEntry(qd_dev, &tmpVtuEntry, found);
+    if ( (rc != GT_OK) && (rc != GT_NO_SUCH) )
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gvtuFindVidEntry failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+    else if (rc == GT_NO_SUCH)
+    {
+        printk(KERN_ERR "%s: VTU not vid[%d]\n\r", __FUNCTION__, tmpVtuEntry.vid);
+    }
+    else
+    {
+        if (found)
+        {
+            printk("DBNum:%i, VID:%i \n",tmpVtuEntry.DBNum,tmpVtuEntry.vid);
+            printk("Tag: ");
+
+            for(portIndex=0; portIndex < qd_dev->numOfPorts; portIndex++)
+            {
+                port = portIndex;
+                printk("%d %d;",port,tmpVtuEntry.vtuData.memberTagP[port]);
+            }
+
+            printk("\n");
+
+            printk("vidPriOverride[%d],vidPriority[%d],useVIDFPri[%d],vidFPri[%d],useVIDQPri[%d],vidQPri[%d],vidNRateLimit[%d]\n",
+                   tmpVtuEntry.vidPriOverride,
+                   tmpVtuEntry.vidPriority,
+                   tmpVtuEntry.vidExInfo.useVIDFPri,
+                   tmpVtuEntry.vidExInfo.vidFPri,
+                   tmpVtuEntry.vidExInfo.useVIDQPri,
+                   tmpVtuEntry.vidExInfo.vidQPri,
+                   tmpVtuEntry.vidExInfo.vidNRateLimit);
+        }
+    }
+
+    return rc;
+}
+
+
+
+/*******************************************************************************
+* mv_switch_prv_set_secure_mode
+*
+* DESCRIPTION:
+*       Change a port mode in the SW data base and remove it from all VLANs
+*
+* INPUTS:
+*       port       -  secure port number
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_prv_set_secure_mode
+(
+    uint32_t port
+)
+{
+    GT_STATUS rc = GT_OK;
+    uint32_t  port_bm;
+    uint16_t  vlan_idx;
+
+    sw_ports_tbl[port].port_mode = GT_SECURE;
+
+    port_bm = 1 << port;
+
+    for (vlan_idx=0; vlan_idx < SW_MAX_VLAN_NUM; vlan_idx++)
+    {
+        if ((sw_vlan_tbl[vlan_idx].members & port_bm) &&
+            (sw_ports_tbl[port].vlan_blong[vlan_idx] == SW_PORT_NOT_BELONG))
+        {
+            rc |= mv_switch_prv_del_vid_per_port(port, vlan_idx);
+
+            if (rc != GT_OK)
+            {
+                printk(KERN_ERR
+                       "%s:%d:==ERROR== failed to remove port [%d] from VLAN [%d]\r\n",
+                       __FUNCTION__,__LINE__,port, vlan_idx);
+            }
+
+            sw_vlan_tbl[vlan_idx].egr_mode[port] = NOT_A_MEMBER;
+        }
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_prv_set_fallback_mode
+*
+* DESCRIPTION:
+*       Change a port mode in the SW data base and add it to all VLANs
+*
+* INPUTS:
+*       port       -  secure port number
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_prv_set_fallback_mode
+(
+    uint32_t port
+)
+{
+    GT_STATUS rc = GT_OK;
+    uint32_t  port_bm;
+    uint16_t  vlan_idx;
+
+    sw_ports_tbl[port].port_mode = GT_FALLBACK;
+
+    port_bm = 1 << port;
+
+    for (vlan_idx=0; vlan_idx < SW_MAX_VLAN_NUM; vlan_idx++)
+    {
+        /* If a VLAN has been defined (there is a member in the VLAN) and
+           the specified port is not a member */
+        if ( sw_vlan_tbl[vlan_idx].members &&
+             !(sw_vlan_tbl[vlan_idx].members & port_bm))
+        {
+            sw_vlan_tbl[vlan_idx].members |= port_bm;
+            sw_vlan_tbl[vlan_idx].egr_mode[port] = MEMBER_EGRESS_UNMODIFIED;
+
+            /* Update VTU table */
+            rc |= mv_switch_prv_port_add_vid(vlan_idx);
+
+            if (rc != GT_OK)
+            {
+                printk(KERN_ERR
+                       "%s:%d:==ERROR== failed to add port [%d] to VLAN [%d]\r\n",
+                       __FUNCTION__,__LINE__,port, vlan_idx);
+            }
+        }
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_vid_filter_per_port
+*
+* DESCRIPTION:
+*       The API sets the filtering mode of a certain lport.
+*       If the lport is in filtering mode, only the VIDs added by the
+*       tpm_sw_port_add_vid API will be allowed to ingress and egress the lport.
+*
+* INPUTS:
+*       lport       -  lport for setting the filtering mode.
+*       vid_filter  - set to 1 means the lport will DROP all packets which are NOT in
+*                    the allowed VID list (built using API tpm_sw_port_add_vid).
+*                    set to 0 - means that the list of VIDs allowed
+*                    per lport has no significance (the list is not deleted).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_vid_filter_per_port
+(
+    IN uint32_t lport,
+    IN uint8_t  vid_filter
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_DOT1Q_MODE mode;
+
+    if (vid_filter == 1)
+    {
+        /* Port should be moved to the secure mode and removed from all VLANs */
+
+        if (sw_ports_tbl[lport].port_mode == GT_SECURE)
+        {
+            /* The port is already in the secure mode - do noting */
+            return rc;
+        }
+
+        rc   = mv_switch_prv_set_secure_mode(lport);
+        mode = GT_SECURE;
+    }
+    else
+    {
+        /* Port should be moved to the fallback mode and added to all VLANs */
+        if (sw_ports_tbl[lport].port_mode == GT_FALLBACK)
+        {
+            /* The port is already in the fallback mode - do noting */
+            return rc;
+        }
+
+        rc   = mv_switch_prv_set_fallback_mode(lport);
+        mode = GT_FALLBACK;
+    }
+
+    if (rc != GT_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== failed to set new port mode - retval[%d]\r\n",
+               __FUNCTION__,__LINE__,rc);
+        return GT_FAIL;
+    }
+
+    rc = gvlnSetPortVlanDot1qMode(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR==gvlnSetPortVlanDot1qMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__,rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_vid_filter_per_port
+*
+* DESCRIPTION:
+*       The API gets the filtering mode of a certain lport.
+*       If the lport is in filtering mode, only the VIDs added by the
+*       tpm_sw_port_add_vid API will be allowed to ingress and egress the lport.
+*
+* INPUTS:
+*       lport       -  lport for setting the filtering mode.
+*
+* OUTPUTS:
+*       vid_filter  - set to - means the lport will DROP all packets which are NOT in
+*                    the allowed VID list (built using API tpm_sw_port_add_vid).
+*                    set to  - means that the list of VIDs allowed
+*                    per lport has no significance (the list is not deleted).
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case  see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_vid_filter_per_port
+(
+    IN  uint32_t lport,
+    OUT uint8_t  *vid_filter
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_DOT1Q_MODE mode;
+
+    rc = gvlnGetPortVlanDot1qMode(qd_dev, lport, &mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR==gvlnGetPortVlanDot1qMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__,rc);
+
+        rc = GT_FAIL;
+    }
+
+    if (GT_SECURE == mode)
+        *vid_filter = 1;
+    else
+        *vid_filter = 0;
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_sched_mode()
+*
+* DESCRIPTION:      Configures the scheduling mode per Ethernet port.
+*
+* INPUTS:
+*       uni_port          - UNI port for setting the scheduling mode
+*       sched_mode        - scheduler mode per port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*DDD
+*******************************************************************************/
+int32_t mv_switch_set_port_sched_mode
+(
+    IN uint32_t      uni_port,
+    IN GT_PORT_SCHED_MODE  mode
+)
+{
+    GT_STATUS           rc = GT_OK;
+
+    rc = gprtSetPortSched(qd_dev, uni_port, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetPortSched failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_uni_q_weight
+*
+* DESCRIPTION:
+*       The API configures the weight of a queues for all
+*       Ethernet UNI ports in the integrated switch.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       weight   - weight value per queue (1-8).queue (value 1-3).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.  DDD
+*
+*******************************************************************************/
+int32_t mv_switch_set_uni_q_weight
+(
+    IN uint8_t queue_id,
+    IN uint8_t weight
+)
+{
+    GT_STATUS     rc = GT_OK;
+    uint32_t      len;
+    uint32_t      i,j;
+    GT_QoS_WEIGHT Weight;
+
+    len = 0;
+    /* Update global weight_array */
+    weight_arr[queue_id-1] = weight;
+
+    for (i = 0; i < SW_QOS_NUM_OF_QUEUES; i++)
+    {
+        for(j = 0; j < weight_arr[i];j++)
+        {
+            Weight.queue[j] = i;
+            len++;
+        }
+    }
+
+    Weight.len = len;
+
+    rc = gsysSetQoSWeight(qd_dev, &Weight);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gsysSetQoSWeight failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures an ingress policing function for an Ethernet UNI lport.
+*
+* INPUTS:
+*       owner_id - APP owner id, should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*       count_mode - count mode:
+*	                           GT_PIRL2_COUNT_FRAME
+*	                           GT_PIRL2_COUNT_ALL_LAYER1
+*	                           GT_PIRL2_COUNT_ALL_LAYER2
+*	                           GT_PIRL2_COUNT_ALL_LAYER3
+*       cir      - comited info rate.
+*		      cbs	        - Committed Burst Size limit (expected to be 2kBytes)
+*		      ebs        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_uni_ingr_police_rate
+(
+    IN uint32_t	uni_port,
+    IN GT_PIRL2_COUNT_MODE	count_mode,
+	IN uint32_t cir,
+    IN uint32_t cbs,
+    IN uint32_t ebs
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_U32		  irlRes;
+    GT_PIRL2_DATA pirl_2_Data;
+    GT_BOOL pause_state;
+
+    memset(&pirl_2_Data,0,sizeof(GT_PIRL_DATA));
+
+    irlRes = 0;
+
+    /* Gets the PIRL2 default params for uni_port
+    rc = gpirl2ReadResource(qd_dev, uni_port, irlRes, &pirl_2_Data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d:==ERROR==pirl2ReadResource failed rc[0x%x]\r\n",
+               __FUNCTION__,
+               __LINE__, rc);
+
+        rc = GT_FAIL;
+        goto out_func;
+    }*/
+
+    /* configure tc,cbs,cir on the uni_port */
+    pirl_2_Data.ingressRate             = cir;
+    pirl_2_Data.customSetup.isValid     = GT_FALSE;
+    pirl_2_Data.accountQConf 		    = GT_FALSE;
+    pirl_2_Data.accountFiltered	        = GT_TRUE;
+    pirl_2_Data.mgmtNrlEn               = GT_TRUE;
+    pirl_2_Data.saNrlEn                 = GT_FALSE;
+    pirl_2_Data.daNrlEn                 = GT_FALSE;
+    pirl_2_Data.samplingMode            = GT_FALSE;
+    pirl_2_Data.actionMode              = PIRL_ACTION_USE_LIMIT_ACTION;
+
+    /*Decide which mode to adopt when deal with overload traffic.
+	*  If pause state is ON, select FC mode, otherwize select drop mode.
+	*/
+    mv_switch_get_port_pause_state(uni_port, &pause_state);
+    if(pause_state == GT_TRUE)
+    {
+        pirl_2_Data.ebsLimitAction          = ESB_LIMIT_ACTION_FC;
+    }
+	else
+	{
+    pirl_2_Data.ebsLimitAction          = ESB_LIMIT_ACTION_DROP;
+	}
+
+    /*pirl_2_Data.ebsLimitAction          = ESB_LIMIT_ACTION_DROP;	*/
+
+    pirl_2_Data.fcDeassertMode          = GT_PIRL_FC_DEASSERT_EMPTY;
+    pirl_2_Data.bktRateType		        = BUCKET_TYPE_TRAFFIC_BASED;
+    pirl_2_Data.priORpt                 = GT_TRUE;
+    pirl_2_Data.priMask                 = 0;
+    pirl_2_Data.bktTypeMask             = 0x7fff;
+	/*Input code mode*/
+    pirl_2_Data.byteTobeCounted	        = count_mode;
+    /*pirl_2_Data.byteTobeCounted	        = GT_PIRL2_COUNT_ALL_LAYER2;*/
+
+    /*Set custom param: cbs, ebs*/
+    pirl_2_Data.customSetup.cbsLimit   = cbs;
+    pirl_2_Data.customSetup.ebsLimit     = ebs;
+
+    rc = gpirl2WriteResource(qd_dev, uni_port, irlRes, &pirl_2_Data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gpirl2WriteResource failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API gets an ingress policing function for an Ethernet UNI lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+
+*
+* OUTPUTS:
+*       count_mode - count mode:
+*	                           GT_PIRL2_COUNT_FRAME
+*	                           GT_PIRL2_COUNT_ALL_LAYER1
+*	                           GT_PIRL2_COUNT_ALL_LAYER2
+*	                           GT_PIRL2_COUNT_ALL_LAYER3
+*       cir      - comited info rate.
+*		      cbs	        - Committed Burst Size limit (expected to be 2kBytes)
+*		      ebs        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_uni_ingr_police_rate
+(
+    IN  uint32_t uni_port,
+    OUT GT_PIRL2_COUNT_MODE	*count_mode,
+	OUT uint32_t *cir,
+    OUT uint32_t *cbs,
+    OUT uint32_t *ebs
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_PIRL2_DATA pirl_2_Data;
+    GT_U32		  irlUnit;
+
+    irlUnit =  0; /* IRL Unit 0 - bucket to be used (0 ~ 4) */
+	memset(&pirl_2_Data, 0, sizeof(GT_PIRL2_DATA));
+
+    rc = gpirl2ReadResource(qd_dev, uni_port, irlUnit, &pirl_2_Data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==pirl2ReadResource failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    *count_mode = pirl_2_Data.byteTobeCounted;
+    *cir = pirl_2_Data.ingressRate;
+    *cbs = pirl_2_Data.customSetup.cbsLimit;
+    *ebs = pirl_2_Data.customSetup.ebsLimit;
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures a policer function for a traffic class for an Ethernet UNI lport.
+*       There are 4 globally defined traffic classes in the integrated switch.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*       tc       - traffic class ( a combination of p-bits and DSCP values).
+*       cir      - comited info rate.
+*       cbs      - comited burst rate.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_set_uni_tc_ingr_police_rate
+(
+    IN uint32_t	uni_port,
+    IN uint32_t	tc,
+	IN uint32_t cir,
+	IN uint32_t	cbs
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_U32		  irlRes;
+    GT_PIRL2_DATA pirl_2_Data;
+    GT_U32		  priMask = 1;
+
+    irlRes = tc;
+    memset(&pirl_2_Data,0,sizeof(GT_PIRL_DATA));
+
+    /* Gets the PIRL2 default params for uni_port
+    rc = gpirl2ReadResource(qd_dev, uni_port, irlRes, &pirl_2_Data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d:==ERROR==pirl2ReadResource failed rc[0x%x]\r\n",
+               __FUNCTION__,
+               __LINE__, rc);
+
+        rc = GT_FAIL;
+        goto out_func;
+    }*/
+
+    /* configure tc,cbs,cir on the uni_port */
+    pirl_2_Data.ingressRate             = cir;
+    pirl_2_Data.customSetup.isValid     = GT_FALSE;
+    pirl_2_Data.accountQConf 		    = GT_FALSE;
+    pirl_2_Data.accountFiltered	        = GT_TRUE;
+    pirl_2_Data.mgmtNrlEn               = GT_TRUE;
+    pirl_2_Data.saNrlEn                 = GT_FALSE;
+    pirl_2_Data.daNrlEn                 = GT_FALSE;
+    pirl_2_Data.samplingMode            = GT_FALSE;
+    pirl_2_Data.actionMode              = PIRL_ACTION_USE_LIMIT_ACTION;
+    pirl_2_Data.ebsLimitAction          = ESB_LIMIT_ACTION_DROP;
+    pirl_2_Data.fcDeassertMode          = GT_PIRL_FC_DEASSERT_EMPTY;
+    pirl_2_Data.bktRateType		        = BUCKET_TYPE_TRAFFIC_BASED;
+    pirl_2_Data.priORpt                 = GT_FALSE;
+    pirl_2_Data.priMask                 = priMask << tc;
+    pirl_2_Data.bktTypeMask             = 0x7fff;
+    pirl_2_Data.byteTobeCounted	        = GT_PIRL2_COUNT_ALL_LAYER2;
+
+    pirl_2_Data.customSetup.cbsLimit    = cbs;
+
+    rc = gpirl2WriteResource(qd_dev, uni_port, irlRes, &pirl_2_Data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gpirl2WriteResource failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       This routine gets the lport's ingress data limit for priority 0 or 1 or 2 or 3 frames.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*
+* OUTPUTS:
+*
+*       tc       - traffic class ( a combination of p-bits and DSCP values).
+*       cir      - comited info rate.
+*       cbs      - comited burst rate
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_uni_tc_ingr_police_rate
+(
+	IN  uint32_t uni_port,
+	OUT uint32_t *tc,
+	OUT uint32_t *cir,
+	OUT uint32_t *cbs
+)
+{
+	GT_STATUS     rc = GT_OK;
+	GT_U32		  irlRes;
+	GT_PIRL2_DATA pirl_2_Data[5];
+	uint8_t       i;
+
+	irlRes = 0;/* bucket to be used (0 ~ 4) */
+
+	for (irlRes = 0; irlRes <= 4; irlRes ++) {
+		/* Gets the CBS params */
+		rc = gpirl2ReadResource(qd_dev, uni_port, irlRes, &pirl_2_Data[irlRes]);
+		if (rc != GT_OK) {
+			printk(KERN_ERR "%s:%d:==ERROR==gpirl2ReadResource failed rc[0x%x]\r\n",
+				__FUNCTION__, __LINE__, rc);
+
+			rc = GT_FAIL;
+		}
+		tc[irlRes]  = 0;
+		cbs[irlRes] = pirl_2_Data[irlRes].customSetup.cbsLimit;
+		cir[irlRes] = pirl_2_Data[irlRes].ingressRate;
+
+		for (i=0; i < SW_QOS_NUM_OF_QUEUES; i++) {
+			if (pirl_2_Data[irlRes].priMask & (1 << i))
+				tc[irlRes] = i;
+		}
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API Configures the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*       trg_lport            - uni lport for configuring the egress rate limit.
+*		  mode					  - frame/rate limit mode
+*       frame_rate_limit_val  - egress rate limit value.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       GT_ERATE_TYPE used kbRate - frame rate valid values are:
+*							        7600,..., 9600,
+*							        10000, 20000, 30000, 40000, ..., 100000,
+*							        110000, 120000, 130000, ..., 1000000.
+*
+*
+*******************************************************************************/
+int32_t mv_switch_set_uni_egr_rate_limit
+(
+    IN uint32_t	trg_lport,
+    IN GT_PIRL_ELIMIT_MODE mode,
+	IN uint32_t frame_rate_limit_val
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_ERATE_TYPE fRate;
+
+    fRate.fRate = frame_rate_limit_val;
+	 fRate.kbRate = frame_rate_limit_val;
+
+    rc = grcSetELimitMode(qd_dev, trg_lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==grcSetELimitMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    rc = grcSetEgressRate(qd_dev, trg_lport, &fRate);
+    if (rc != GT_OK)
+    {
+        printk(KERN_INFO "%s:%d:==ERROR==grcSetEgressRate failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API return the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id        - APP owner id - should be used for all API calls.
+*       trg_lport        - uni lport for configuring the egress rate limit.
+
+*
+* OUTPUTS:
+*		   mode					  - frame/rate limit mode
+*        rate_limit_val  - egress rate limit value..
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       GT_ERATE_TYPE used kbRate - frame rate valid values are:
+*							        7600,..., 9600,
+*							        10000, 20000, 30000, 40000, ..., 100000,
+*							        110000, 120000, 130000, ..., 1000000.
+
+*
+*******************************************************************************/
+int32_t mv_switch_get_uni_egr_rate_limit
+(
+    IN  uint32_t trg_lport,
+    OUT GT_PIRL_ELIMIT_MODE *mode,
+	OUT uint32_t *frame_rate_limit_val
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_ERATE_TYPE fRate;
+
+    rc = grcGetELimitMode(qd_dev, trg_lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==grcGetELimitMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    rc = grcGetEgressRate(qd_dev, trg_lport, &fRate);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==grcGetEgressRate failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+     /*frame based limit*/
+	 if(mode == GT_PIRL_ELIMIT_FRAME)
+	 {
+    *frame_rate_limit_val = fRate.fRate;
+	 }
+    else/*rate based limit*/
+	 {
+        *frame_rate_limit_val = fRate.kbRate;
+	 }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_age_time
+*
+* DESCRIPTION:
+*       This function Sets the Mac address table size.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       time_out    - Aging Time value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_set_age_time
+(
+	IN uint32_t time_out
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gfdbSetAgingTimeout(qd_dev, time_out);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbSetAgingTimeout failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_mac_learn
+*
+* DESCRIPTION:
+*       Enable/disable automatic learning of new source MAC addresses on port
+*       ingress.
+*
+* INPUTS:
+*       lport       - logical port number to set.
+*       enable - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+int32_t mv_switch_set_mac_learn
+(
+	IN uint32_t lport,
+    IN GT_BOOL  enable
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtSetLearnEnable(qd_dev, lport, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetLearnEnable failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_mac_learn
+*
+* DESCRIPTION:
+*       Get automatic learning status of new source MAC addresses on port ingress.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       lport       - logical port number to set.
+*       enable - GT_TRUE if enabled  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+int32_t mv_switch_get_mac_learn
+(
+	IN uint32_t lport,
+    OUT GT_BOOL  *enable
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtGetLearnEnable(qd_dev, lport, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetLearnEnable failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_vlan_ports
+*
+* DESCRIPTION:
+*       This routine sets the port VLAN group port membership list.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - logical port number to set.
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_vlan_ports
+(
+	IN uint32_t lport,
+    IN uint32_t memPorts[],
+    IN uint8_t  memPortsLen
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gvlnSetPortVlanPorts(qd_dev, lport, (GT_LPORT*)memPorts, memPortsLen);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gvlnSetPortVlanPorts failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_vlan_ports
+*
+* DESCRIPTION:
+*       This routine gets the port VLAN group port membership list.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - logical port number to set.
+*
+*
+* OUTPUTS:
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_vlan_ports
+(
+	IN  uint32_t lport,
+    OUT uint32_t memPorts[],
+    OUT uint8_t  *memPortsLen
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gvlnGetPortVlanPorts(qd_dev, lport, (GT_LPORT*)memPorts, memPortsLen);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gvlnGetPortVlanPorts failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_age_time
+*
+* DESCRIPTION:
+*       This function Sets the Mac address table size.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*
+* OUTPUTS:
+*       time_out    - time out value.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_get_age_time
+(
+	OUT uint32_t *time_out
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gfdbGetAgingTimeout(qd_dev, (GT_U32*)time_out);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbGetAgingTimeout failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_ingress_limit_mode
+*
+* DESCRIPTION:
+*       This routine sets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       lport       - logical port number to set.
+*       mode 	    - rate control ingress limit mode.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*    GT_LIMT_ALL = 0,        limit and count all frames
+*    GT_LIMIT_FLOOD,         limit and count Broadcast, Multicast and flooded unicast frames
+*    GT_LIMIT_BRDCST_MLTCST, limit and count Broadcast and Multicast frames
+*    GT_LIMIT_BRDCST         limit and count Broadcast frames
+*
+*******************************************************************************/
+int32_t mv_switch_set_ingress_limit_mode
+(
+	IN uint32_t           lport,
+    IN GT_RATE_LIMIT_MODE mode
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = grcSetLimitMode(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==grcSetLimitMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_ingress_limit_mode
+*
+* DESCRIPTION:
+*       This routine gets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       lport       - logical port number to set.
+*
+*
+* OUTPUTS:
+*        mode 	    - rate control ingress limit mode.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*    GT_LIMT_ALL = 0,        limit and count all frames
+*    GT_LIMIT_FLOOD,         limit and count Broadcast, Multicast and flooded unicast frames
+*    GT_LIMIT_BRDCST_MLTCST, limit and count Broadcast and Multicast frames
+*    GT_LIMIT_BRDCST         limit and count Broadcast frames
+*
+*******************************************************************************/
+int32_t mv_switch_get_ingress_limit_mode
+(
+	IN  uint32_t           lport,
+    OUT GT_RATE_LIMIT_MODE *mode
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = grcGetLimitMode(qd_dev, lport, mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==grcGetLimitMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This routine sets initial QPri and FPri selection.
+*
+* INPUTS:
+*       lport       - Port number to set init pri.
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+int32_t mv_switch_set_priority_selection
+(
+    IN  uint8_t  lport,
+    IN  uint8_t  init_pri,
+    IN  GT_BOOL  tag_if_both
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    if (PRI_SEL_TAG_PRI_ONLY == init_pri || \
+        PRI_SEL_TAG_AND_IP_PRI == init_pri)
+    {
+        rc = gqosUserPrioMapEn(qd_dev, lport, GT_TRUE);
+    }
+    else
+    {
+        rc = gqosUserPrioMapEn(qd_dev, lport, GT_FALSE);
+    }
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gqosUserPrioMapEn failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        return GT_FAIL;
+    }
+
+    if (PRI_SEL_IP_PRI_ONLY == init_pri || \
+        PRI_SEL_TAG_AND_IP_PRI == init_pri)
+    {
+        rc = gqosIpPrioMapEn(qd_dev, lport, GT_TRUE);
+    }
+    else
+    {
+        rc = gqosIpPrioMapEn(qd_dev, lport, GT_FALSE);
+    }
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gqosIpPrioMapEn failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        return GT_FAIL;
+    }
+
+    if (PRI_SEL_TAG_AND_IP_PRI == init_pri)
+    {
+        rc = gqosSetPrioMapRule(qd_dev, lport, tag_if_both);
+        if (rc != GT_OK)
+        {
+            printk(KERN_ERR "%s:%d:==ERROR==gqosSetPrioMapRule failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+            return GT_FAIL;
+        }
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_priority_selection
+*
+* DESCRIPTION:
+*       This routine gets initial QPri and FPri selection.
+*
+* INPUTS:
+*       lport       - Port number to set init pri.
+*
+* OUTPUTS:
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+int32_t mv_switch_get_priority_selection
+(
+    IN  uint8_t  lport,
+    OUT uint8_t *init_pri,
+    OUT GT_BOOL *tag_if_both
+)
+{
+    GT_STATUS rc = GT_OK;
+    GT_BOOL ip_en, tag_en;
+
+    rc = gqosGetUserPrioMapEn(qd_dev, lport, &tag_en);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gqosGetUserPrioMapEn failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    rc = gqosGetIpPrioMapEn(qd_dev, lport, &ip_en);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gqosGetIpPrioMapEn failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    *init_pri = (ip_en << 1) | tag_en;
+
+    rc = gqosGetPrioMapRule(qd_dev, lport, tag_if_both);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gqosGetPrioMapRule failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This routine maps a tag priority to a queue priority.
+*
+* INPUTS:
+*       tag_pri     - Source tag priority number.
+*       q_pri       - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+int32_t mv_switch_set_tag_pri_mapping
+(
+    IN  uint8_t  tag_pri,
+    IN  uint8_t  q_pri
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gcosSetUserPrio2Tc(qd_dev, tag_pri, q_pri);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gcosSetUserPrio2Tc failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        return GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This routine gets the queue priority for a tag priority mapping to.
+*
+* INPUTS:
+*       tag_pri     - Source tag priority number.
+*
+* OUTPUTS:
+*       q_pri       - Target queue priority number.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+int32_t mv_switch_get_tag_pri_mapping
+(
+    IN  uint8_t  tag_pri,
+    OUT uint8_t *q_pri
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gcosGetUserPrio2Tc(qd_dev, tag_pri, q_pri);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gcosGetUserPrio2Tc failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        return GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This routine maps a dscp value to a queue priority.
+*
+* INPUTS:
+*       dscp        - Source dscp value.
+*       q_pri       - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+int32_t mv_switch_set_ip_pri_mapping
+(
+    IN  uint8_t  dscp,
+    IN  uint8_t  q_pri
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gcosSetDscp2Tc(qd_dev, dscp, q_pri);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gcosSetDscp2Tc failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        return GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This routine gets the queue priority for a dscp value mapping to.
+*
+* INPUTS:
+*       dscp        - Source dscp value.
+*
+* OUTPUTS:
+*       q_pri       - Target queue priority number.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+int32_t mv_switch_get_ip_pri_mapping
+(
+    IN  uint8_t  dscp,
+    OUT uint8_t *q_pri
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gcosGetDscp2Tc(qd_dev, dscp, q_pri);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gcosGetDscp2Tc failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        return GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_unknown_unicast_flood
+*
+* DESCRIPTION:
+*       This routine enable/disable unknown unicast frame egress on a specific port.
+*
+* INPUTS:
+*       lport   - Port number to egress unknown unicast frames.
+*       enable  - Enable unknown unicast flooding.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_unknown_unicast_flood
+(
+    IN  uint8_t  lport,
+    OUT GT_BOOL  enable
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtSetForwardUnknown(qd_dev, lport, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetForwardUnknown failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_unknown_unicast_flood
+*
+* DESCRIPTION:
+*       This routine gets unknown unicast frame egress mode of a specific port.
+*
+* INPUTS:
+*       lport   - Port number to egress unknown unicast frames.
+*
+* OUTPUTS:
+*       enable  - Enable unknown unicast flooding.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_unknown_unicast_flood
+(
+    IN  uint8_t  lport,
+    OUT GT_BOOL *enable
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtGetForwardUnknown(qd_dev, lport, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetForwardUnknown failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_unknown_multicast_flood
+*
+* DESCRIPTION:
+*       This routine enable/disable unknown multicast frame egress on a specific port.
+*
+* INPUTS:
+*       lport   - Port number to egress unknown multicast frames.
+*       enable  - Enable unknown multicast flooding.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_unknown_multicast_flood
+(
+    IN  uint8_t  lport,
+    OUT GT_BOOL  enable
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtSetDefaultForward(qd_dev, lport, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetDefaultForward failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_unknown_multicast_flood
+*
+* DESCRIPTION:
+*       This routine gets unknown multicast frame egress mode of a specific port.
+*
+* INPUTS:
+*       lport   - Port number to egress unknown multicast frames.
+*
+* OUTPUTS:
+*       enable  - Enable unknown multicast flooding.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_unknown_multicast_flood
+(
+    IN  uint8_t  lport,
+    OUT GT_BOOL *enable
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtGetDefaultForward(qd_dev, lport, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetDefaultForward failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_broadcast_flood
+*
+* DESCRIPTION:
+*       This routine decides whether the switch always floods the broadcast
+*       frames to all portsr or uses the multicast egress mode (per port).
+*
+* INPUTS:
+*       always_on - always floods the broadcast regardless the multicast egress mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_broadcast_flood
+(
+    IN  GT_BOOL  always_on
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gsysSetFloodBC(qd_dev, always_on);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gsysSetFloodBC failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_broadcast_flood
+*
+* DESCRIPTION:
+*       This routine gets the global mode of broadcast flood.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       always_on - always floods the broadcast regardless the multicast egress mode.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_broadcast_flood
+(
+    IN  GT_BOOL *always_on
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gsysGetFloodBC(qd_dev, always_on);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gsysGetFloodBC failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_marvell_header_mode
+*
+* DESCRIPTION:
+*       This routine sets ingress and egress header mode of a switch port.
+*
+* INPUTS:
+*       lport  - logical port number to set.
+*       enable - enable marvell header.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_marvell_header_mode
+(
+    IN  uint8_t  lport,
+    IN  GT_BOOL  enable
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtSetHeaderMode(qd_dev, lport, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetHeaderMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_marvell_header_mode
+*
+* DESCRIPTION:
+*       This routine gets ingress and egress header mode of a switch port.
+*
+* INPUTS:
+*       lport  - logical port number to set.
+*
+* OUTPUTS:
+*       enable - enable marvell header.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_marvell_header_mode
+(
+    IN  uint8_t  lport,
+    IN  GT_BOOL *enable
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gprtGetHeaderMode(qd_dev, lport, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetHeaderMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_preamble
+*
+* DESCRIPTION:
+*       This routine sets preamble of a switch port.
+*
+* INPUTS:
+*       lport  - logical port number to set.
+*       preamble - preamble length.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_preamble
+(
+    IN  uint8_t  lport,
+    IN  uint16_t preamble
+)
+{
+    GT_STATUS rc = GT_OK;
+	uint16_t data;
+
+	rc = mv_switch_set_port_reg(3, 26, preamble);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==mv_switch_set_port_reg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+	mvOsDelay(10);
+
+	data = 0xb002 | (lport << 8);
+	rc = mv_switch_set_port_reg(2, 26, data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==mv_switch_set_port_reg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_preamble
+*
+* DESCRIPTION:
+*       This routine gets preamble of a switch port.
+*
+* INPUTS:
+*       lport  - logical port number to set.
+*
+* OUTPUTS:
+*       preamble - preamble length.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_preamble
+(
+    IN  uint8_t   lport,
+    OUT uint16_t *preamble
+)
+{
+    GT_STATUS rc = GT_OK;
+	uint16_t data;
+
+	data = 0xc002 | (lport << 8);
+	rc = mv_switch_set_port_reg(2, 26, data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==mv_switch_set_port_reg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+	mvOsDelay(10);
+
+	rc = mv_switch_get_port_reg(3, 26, &data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==mv_switch_get_port_reg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+    }
+
+	*preamble = data;
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_autoneg_mode
+*
+* DESCRIPTION:
+*       The API Configures the auto negotiation state of an Ethernet  lport.
+* INPUTS:
+*       lport        		- logical port  number for setting the auto negotiation state.
+*       autoneg_state  - autonegotiation state, enabled or disabled.
+*       autoneg_mode   - enum:
+*                        SPEED_AUTO_DUPLEX_AUTO: Auto for both speed and duplex
+*                        SPEED_1000_DUPLEX_AUTO: 1000Mbps and auto duplex
+*                        SPEED_100_DUPLEX_AUTO:  100Mbps and auto duplex
+*                        SPEED_10_DUPLEX_AUTO:   10Mbps and auto duplex
+*                        SPEED_AUTO_DUPLEX_FULL: Auto for speed only and Full duplex
+*                        SPEED_AUTO_DUPLEX_HALF: Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                        SPEED_1000_DUPLEX_FULL: 1000Mbps Full duplex.
+*                        SPEED_1000_DUPLEX_HALF: 1000Mbps half duplex.
+*                        SPEED_100_DUPLEX_FULL:  100Mbps Full duplex.
+*                        SPEED_100_DUPLEX_HALF:  100Mbps half duplex.
+*                        SPEED_10_DUPLEX_FULL:   10Mbps Full duplex.
+*                        SPEED_10_DUPLEX_HALF:   10Mbps half duplex.
+
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case,see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_autoneg_mode
+(
+    IN uint32_t  lport,
+    IN GT_BOOL           autoneg_state,
+    IN GT_PHY_AUTO_MODE  autoneg_mode
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    if(GT_FALSE == autoneg_state)
+    {
+        rc = gprtPortAutoNegEnable(qd_dev, lport, GT_FALSE);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtPortAutoNegEnable failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+        return rc;
+    }
+    else
+    {
+        rc = gprtPortAutoNegEnable(qd_dev, lport, GT_TRUE);
+        if (rc != GT_OK)
+        {
+            printk(KERN_ERR "%s:%d:==ERROR==gprtPortAutoNegEnable failed rc[0x%x]\r\n",
+                   __FUNCTION__, __LINE__, rc);
+
+            rc = GT_FAIL;
+            return rc;
+        }
+    }
+
+    rc = gprtSetPortAutoMode(qd_dev, lport, autoneg_mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetPortAutoMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_autoneg_mode
+*
+* DESCRIPTION:
+*       The API return the the auto negotiation state of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the auto negotiation state.
+*
+*
+* OUTPUTS:
+*       autoneg_state  - autonegotiation state, enabled or disabled.
+*       autoneg_mode   - enum:
+*                        SPEED_AUTO_DUPLEX_AUTO: Auto for both speed and duplex
+*                        SPEED_1000_DUPLEX_AUTO: 1000Mbps and auto duplex
+*                        SPEED_100_DUPLEX_AUTO:  100Mbps and auto duplex
+*                        SPEED_10_DUPLEX_AUTO:   10Mbps and auto duplex
+*                        SPEED_AUTO_DUPLEX_FULL: Auto for speed only and Full duplex
+*                        SPEED_AUTO_DUPLEX_HALF: Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                        SPEED_1000_DUPLEX_FULL: 1000Mbps Full duplex.
+*                        SPEED_1000_DUPLEX_HALF: 1000Mbps half duplex.
+*                        SPEED_100_DUPLEX_FULL:  100Mbps Full duplex.
+*                        SPEED_100_DUPLEX_HALF:  100Mbps half duplex.
+*                        SPEED_10_DUPLEX_FULL:   10Mbps Full duplex.
+*                        SPEED_10_DUPLEX_HALF:   10Mbps half duplex.
+
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_autoneg_mode
+(
+    IN  uint32_t lport,
+    OUT GT_BOOL           *autoneg_state,
+    OUT GT_PHY_AUTO_MODE  *autoneg_mode
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtGetPortAutoNegState(qd_dev, lport, autoneg_state);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPortAutoNegState failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+        return rc;
+    }
+
+    rc = gprtGetPortAutoMode(qd_dev, lport, autoneg_mode);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPortAutoMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_restart_port_autoneg
+*
+* DESCRIPTION:
+*       The API restart the auto negotiation of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for restarting the auto negotiation state.
+*
+*
+* OUTPUTS:
+*        NONE.
+*								.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_restart_port_autoneg
+(
+    IN  uint32_t lport
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtPortRestartAutoNeg(qd_dev, lport);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtPortRestartAutoNeg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_set_phy_port_state
+*
+* DESCRIPTION:
+*       The API Configures the PHY port  state of an Ethernet  lport.
+* INPUTS:
+*       lport            - logical port to set.
+*       phy_port_state  - PHY port  state to set.
+*				     0:normal state
+*				     1:power down
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_set_phy_port_state
+(
+    IN uint32_t  lport,
+    IN GT_BOOL  phy_port_state
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_BOOL state;
+
+    if(phy_port_state == GT_TRUE)
+    {
+	state = GT_FALSE;
+    }
+    else
+    {
+    	state = GT_TRUE;
+    }
+    rc = gprtPortPowerDown(qd_dev, (GT_LPORT)lport, state);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtPortPowerDown failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_phy_port_state
+*
+* DESCRIPTION:
+*       The API return the PHY port  state of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the PHY port state.
+*
+*
+* OUTPUTS:
+*        phy_port_state  -  0:normal state
+*				       1:power down									.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_phy_port_state
+(
+    IN  uint32_t lport,
+    OUT GT_BOOL * phy_port_state
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_BOOL state;
+
+
+    rc = gprtGetPortPowerDown(qd_dev, (GT_LPORT)lport, &state);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPortPowerDown failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    if(state == GT_TRUE)
+    {
+	*phy_port_state = GT_FALSE;
+    }
+    else
+    {
+    	*phy_port_state = GT_TRUE;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_get_port_link_status
+*
+* DESCRIPTION:
+*       The API return realtime port link status of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the port link status.
+*
+*
+* OUTPUTS:
+*        port_link_status  -  0:port link is ON
+*				        1:port link is DOWN									.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_link_status
+(
+    IN  uint32_t lport,
+    OUT GT_BOOL * port_link_status
+)
+{
+    GT_STATUS     rc = GT_OK;
+    GT_BOOL state;
+
+
+    rc = gprtGetPhyLinkStatus(qd_dev, lport, &state);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPhyLinkStatus failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    *port_link_status = state;
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_duplex_status
+*
+* DESCRIPTION:
+*       The API return realtime port duplex status of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the port link status.
+*
+*
+* OUTPUTS:
+*        port_duplex_status  -  0:half deplex mode
+*				               1:full deplex mode					.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_duplex_status
+(
+    IN  uint32_t lport,
+    OUT GT_BOOL * port_duplex_status
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtGetDuplex(qd_dev, lport, port_duplex_status);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetDuplex failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_speed_mode
+*
+* DESCRIPTION:
+*       The API return realtime port speed mode of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the port link status.
+*
+*
+* OUTPUTS:
+*        port_duplex_status  -  0:10M
+*				               1:100M
+*						 2:1000M
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_speed_mode
+(
+    IN  uint32_t lport,
+    OUT GT_PORT_SPEED_MODE   *speed
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtGetSpeedMode(qd_dev, lport, speed);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetSpeedMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_pause
+*
+* DESCRIPTION:
+*       This routine will set the pause bit in Autonegotiation Advertisement
+*		Register. And restart the autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*		state - GT_PHY_PAUSE_MODE enum value.
+*				GT_PHY_NO_PAUSE		- disable pause
+* 				GT_PHY_PAUSE		- support pause
+*				GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*				GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+int32_t mv_switch_set_port_pause
+(
+IN GT_LPORT  port,
+IN GT_PHY_PAUSE_MODE state
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtSetPause(qd_dev, port, state);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetPause failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_pause
+*
+* DESCRIPTION:
+*       This routine will get the pause bit in Autonegotiation Advertisement
+*		Register.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+*
+* OUTPUTS:
+*		state - GT_PHY_PAUSE_MODE enum value.
+*				GT_PHY_NO_PAUSE		- disable pause
+* 				GT_PHY_PAUSE		- support pause
+*				GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*				GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+int32_t mv_switch_get_port_pause
+(
+IN GT_LPORT  port,
+OUT  GT_PHY_PAUSE_MODE *state
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtGetPause(qd_dev, port, state);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPause failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_get_port_pause_state
+*
+* DESCRIPTION:
+*     This routine will get the current pause state.
+*		Register.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+*
+* OUTPUTS:
+*		state -
+*				GT_FALSE: MAC Pause not implemented in the link partner or in MyPause
+*				GT_TRUE:MAC Pause is implemented in the link partner and in MyPause
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+* COMMENTS:
+*       None.
+*******************************************************************************/
+
+int32_t mv_switch_get_port_pause_state
+(
+IN GT_LPORT  port,
+OUT  GT_BOOL *state
+)
+{
+    GT_BOOL force, pause;
+
+    if(gpcsGetForcedFC(qd_dev, port, &force) != GT_OK)
+    {
+	    printk("gpcsGetForcedFC failed (port %d)\n", (GT_UINT)port);
+	    return GT_FAIL;
+    }
+    if(force)
+    {
+        if(gpcsGetFCValue(qd_dev, port, &pause) != GT_OK) {
+	        printk("gpcsGetFCValue failed (port %d)\n", (GT_UINT)port);
+	        return GT_FAIL;
+        }
+    }
+    else
+    {
+	    if(gprtGetPauseEn(qd_dev, port, &pause) != GT_OK) {
+	        printk("gprtGetPauseEn failed (port %d)\n", (GT_UINT)port);
+	        return GT_FAIL;
+        }
+    }
+
+	*state = pause;
+
+    return GT_OK;
+}
+/*******************************************************************************
+* mv_switch_set_port_loopback
+*
+* DESCRIPTION:
+* Enable/Disable Internal Port Loopback.
+* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and
+*   forces speed to be 10Mbps.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
+*   it is recommended to call gprtSetPortAutoMode for PHY configuration after
+*   Loopback test.
+* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled and Link is active, the current speed is used.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   All other cases, default MAC Interface speed is used. Please refer to the data
+*   sheet for the information of the default MAC Interface speed.
+*
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+* enable - If GT_TRUE, enable loopback mode
+*				 If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+
+int32_t mv_switch_set_port_loopback
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtSetPortLoopback(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetPortLoopback failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_get_port_loopback
+*
+* DESCRIPTION:
+* Get Internal Port Loopback state.
+* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and
+*   forces speed to be 10Mbps.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
+*   it is recommended to call gprtSetPortAutoMode for PHY configuration after
+*   Loopback test.
+* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled and Link is active, the current speed is used.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   All other cases, default MAC Interface speed is used. Please refer to the data
+*   sheet for the information of the default MAC Interface speed.
+*
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* enable - If GT_TRUE,  loopback mode is enabled
+* If GT_FALSE,  loopback mode is disabled
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_loopback
+(
+IN GT_LPORT  port,
+OUT GT_BOOL   *enable
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtGetPortLoopback(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPortLoopback failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_line_loopback
+*
+* DESCRIPTION:
+* Enable/Disable Port Line Loopback.
+*
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register FE:28.4, GE:21_2.14  - Loop_back
+*
+*******************************************************************************/
+
+int32_t mv_switch_set_port_line_loopback
+(
+	IN GT_LPORT  port,
+	IN GT_BOOL   enable
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtSetPortLineLoopback(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetPortLineLoopback failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_get_port_line_loopback
+*
+* DESCRIPTION:
+* Get Port Line Loopback status.
+*
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register FE:28.4, GE:21_2.14  - Loop_back
+*
+*******************************************************************************/
+
+int32_t mv_switch_get_port_line_loopback
+(
+	IN GT_LPORT  port,
+	OUT GT_BOOL*   enable
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtGetPortLineLoopback(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPortLineLoopback failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+
+/*******************************************************************************
+* mv_switch_set_port_duplex_mode
+*
+* DESCRIPTION:
+* 		Sets duplex mode for a specific logical port. This function will keep
+*		the speed and loopback mode to the previous value, but disable others,
+*		such as Autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+* 		enable	- Enable/Disable dulpex mode
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_duplex_mode
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtSetPortDuplexMode(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetPortDuplexMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_get_port_duplex_mode
+*
+* DESCRIPTION:
+* 		Gets duplex mode for a specific logical port.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+*		enable	- Dulpex mode :Enabled or Disabled
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_duplex_mode
+(
+IN GT_LPORT  port,
+OUT GT_BOOL*   enable
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtGetPortDuplexMode(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPortDuplexMode failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_set_port_speed
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		speed -    PHY_SPEED_10_MBPS -10 Mbps
+*				PHY_SPEED_100_MBPS -100 Mbps
+* 				PHY_SPEED_1000_MBPS -100 Mbps.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t mv_switch_set_port_speed
+(
+IN GT_LPORT  port,
+IN GT_PHY_SPEED speed
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtSetPortSpeed(qd_dev, port, speed);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtSetPortSpeed failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_speed
+*
+* DESCRIPTION:
+*       This routine will get current PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*
+* OUTPUTS:
+*		speed -    PHY_SPEED_10_MBPS -10 Mbps
+*				PHY_SPEED_100_MBPS -100 Mbps
+* 				PHY_SPEED_1000_MBPS -100 Mbps.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t mv_switch_get_port_speed
+(
+IN GT_LPORT  port,
+OUT GT_PHY_SPEED *speed
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gprtGetPortSpeed(qd_dev, port, speed);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==mv_switch_get_port_speed failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+
+/*******************************************************************************
+* mv_switch_set_port_forced_link
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable-
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t mv_switch_set_port_forced_link
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gpcsSetForcedLink(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gpcsSetForcedLink failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+
+/*******************************************************************************
+* mv_switch_get_port_forced_link
+*
+* DESCRIPTION:
+* 		Gets duplex mode for a specific logical port.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+*		enable	- Forced Link mode :Enabled or Disabled
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_forced_link
+(
+IN GT_LPORT  port,
+OUT GT_BOOL*   enable
+)
+{
+    GT_STATUS     rc = GT_OK;
+
+    rc = gpcsGetForcedLink(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gpcsGetForcedLink failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+
+
+/*******************************************************************************
+* mv_switch_set_port_link_value
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable - Forced Link Value : Enabled or Disabled
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_link_value
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gpcsSetLinkValue(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gpcsSetLinkValue failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_link_value
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable - Forced Link Value : Enabled or Disabled
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t mv_switch_get_port_link_value
+(
+IN GT_LPORT  port,
+OUT GT_BOOL*   enable
+)
+{
+
+    GT_STATUS     rc = GT_OK;
+
+    rc = gpcsGetLinkValue(qd_dev, port, enable);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gpcsGetLinkValue failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+
+/*******************************************************************************
+* mv_switch_clean_port_counters
+*
+* DESCRIPTION:
+*       This function clean all counters of the given port
+*
+* INPUTS:
+*       owner_id	- APP owner id, should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_clean_port_counters
+(
+   IN  uint32_t lport
+)
+
+{
+   GT_STATUS rc = GT_OK;
+   rc = gstatsFlushPort(qd_dev,lport);
+   if (rc != GT_OK)
+   {
+        printk(KERN_ERR "%s:%d:==ERROR==gstatsFlushAll failed rc[0x%x]\r\n",
+              __FUNCTION__, __LINE__, rc);
+        rc = GT_FAIL;
+
+   }
+    return rc;
+}
+
+/*------------------------------------------------------------------------------
+                            Debug functions
+------------------------------------------------------------------------------*/
+
+
+/*******************************************************************************
+* mv_switch_clear_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_clear_port_counters
+(
+    void
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = gstatsFlushAll(qd_dev);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gstatsFlushAll failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_global_reg
+*
+* DESCRIPTION:
+*       This function sets value to the global register.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_set_global_reg
+(
+	IN uint8_t  regAddr,
+    IN uint16_t data
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = hwWriteGlobalReg(qd_dev, regAddr, data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==hwWriteGlobalReg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_global_reg
+*
+* DESCRIPTION:
+*       This function gets value from the global register.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_get_global_reg
+(
+    IN  uint8_t  regAddr,
+    OUT uint16_t *data
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = hwReadGlobalReg(qd_dev, regAddr, data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==hwReadGlobalReg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_set_port_reg
+*
+* DESCRIPTION:
+*       This function sets value to the port register.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_reg
+(
+    IN  uint8_t  lport,
+    IN  uint8_t  regAddr,
+    IN  uint16_t data
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = hwWritePortReg(qd_dev, lport, regAddr, data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==hwWritePortReg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_reg
+*
+* DESCRIPTION:
+*       This function gets value from the port register.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+*       data        - The data to be written.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_reg
+(
+    IN  uint8_t  lport,
+    IN  uint8_t  regAddr,
+    OUT uint16_t *data
+)
+{
+    GT_STATUS rc = GT_OK;
+
+    rc = hwReadPortReg(qd_dev, lport, regAddr, data);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==hwWritePortReg failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_print_port_counters
+*
+* DESCRIPTION:
+*       This function prints all counters of the given port
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        Clear on read.
+*
+*******************************************************************************/
+int32_t mv_switch_print_port_counters
+(
+    IN  uint32_t lport
+)
+{
+    GT_STATUS             rc = GT_OK;
+    GT_STATS_COUNTER_SET3 statsCounterSet;
+
+    rc = gstatsGetPortAllCounters3(qd_dev, lport, &statsCounterSet);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gstatsGetPortAllCounters3 failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        return GT_FAIL;
+    }
+
+    printk("=======Counters for lport[%d]=======",lport);
+    printk("InGoodOctetsLo  %08ld    ", statsCounterSet.InGoodOctetsLo);
+    printk("InGoodOctetsHi  %08ld   \n", statsCounterSet.InGoodOctetsHi);
+    printk("InBadOctets     %08ld    ", statsCounterSet.InBadOctets);
+    printk("OutFCSErr       %08ld   \n", statsCounterSet.OutFCSErr);
+    printk("InUnicasts      %08ld    ", statsCounterSet.InUnicasts);
+    printk("Deferred        %08ld   \n", statsCounterSet.Deferred);
+    printk("InBroadcasts    %08ld    ", statsCounterSet.InBroadcasts);
+    printk("InMulticasts    %08ld   \n", statsCounterSet.InMulticasts);
+    printk("64Octets        %08ld    ", statsCounterSet.Octets64);
+    printk("127Octets       %08ld   \n", statsCounterSet.Octets127);
+    printk("255Octets       %08ld    ", statsCounterSet.Octets255);
+    printk("511Octets       %08ld   \n", statsCounterSet.Octets511);
+    printk("1023Octets      %08ld    ", statsCounterSet.Octets1023);
+    printk("MaxOctets       %08ld   \n", statsCounterSet.OctetsMax);
+    printk("OutOctetsLo     %08ld    ", statsCounterSet.OutOctetsLo);
+    printk("OutOctetsHi     %08ld   \n", statsCounterSet.OutOctetsHi);
+    printk("OutUnicasts     %08ld    ", statsCounterSet.OutUnicasts);
+    printk("Excessive       %08ld   \n", statsCounterSet.Excessive);
+    printk("OutMulticasts   %08ld    ", statsCounterSet.OutMulticasts);
+    printk("OutBroadcasts   %08ld   \n", statsCounterSet.OutBroadcasts);
+    printk("Single          %08ld    ", statsCounterSet.Single);
+    printk("OutPause        %08ld   \n", statsCounterSet.OutPause);
+    printk("InPause         %08ld    ", statsCounterSet.InPause);
+    printk("Multiple        %08ld   \n", statsCounterSet.Multiple);
+    printk("Undersize       %08ld    ", statsCounterSet.Undersize);
+    printk("Fragments       %08ld   \n", statsCounterSet.Fragments);
+    printk("Oversize        %08ld    ", statsCounterSet.Oversize);
+    printk("Jabber          %08ld   \n", statsCounterSet.Jabber);
+    printk("InMACRcvErr     %08ld    ", statsCounterSet.InMACRcvErr);
+    printk("InFCSErr        %08ld   \n", statsCounterSet.InFCSErr);
+    printk("Collisions      %08ld    ", statsCounterSet.Collisions);
+    printk("Late            %08ld   \n", statsCounterSet.Late);
+
+
+    rc = gstatsFlushAll(qd_dev);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gstatsFlushAll failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        rc = GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        Clear on read.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_counters
+(
+    IN  uint32_t          lport,
+    GT_STATS_COUNTER_SET3 *statsCounterSet
+)
+{
+    GT_STATUS             rc = GT_OK;
+
+    rc = gstatsGetPortAllCounters3(qd_dev, lport, statsCounterSet);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gstatsGetPortAllCounters3 failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        return GT_FAIL;
+    }
+
+    return rc;
+}
+
+/*******************************************************************************
+* mv_switch_get_port_drop_counters
+*
+* DESCRIPTION:
+*       This function gets the port InDiscards, InFiltered, and OutFiltered counters.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       ctr         - the counters value.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        Clear on read.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_drop_counters
+(
+    IN  uint32_t          lport,
+    GT_PORT_STAT2         *ctr
+)
+{
+    GT_STATUS             rc = GT_OK;
+
+    rc = gprtGetPortCtr2(qd_dev, lport, ctr);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gprtGetPortCtr2 failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+        return GT_FAIL;
+    }
+
+    return rc;
+}
+
+
+/*******************************************************************************
+* mv_switch_print_fdb
+*
+* DESCRIPTION:
+*       This function gets all FDB table.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       db_num      - ATU MAC Address Database number. If multiple address
+*					 databases are not being used, DBNum should be zero.
+*					 If multiple address databases are being used, this value
+*					 should be set to the desired address database number.
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_print_fdb
+(
+    IN  uint16_t db_num
+)
+{
+    GT_STATUS    rc = GT_OK;
+    GT_ATU_ENTRY atu_entry;
+    GT_U8        mc_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* initial MAC address */
+
+
+    memcpy(atu_entry.macAddr.arEther, &mc_mac, 6);
+    atu_entry.DBNum = db_num;
+
+    while ((rc = gfdbGetAtuEntryNext(qd_dev, &atu_entry)) == GT_OK)
+    {
+        printk("Printing ATU Entry: db = [%d], MAC = [0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x], Port Vector = [0x%x]\n",
+               atu_entry.DBNum,
+               atu_entry.macAddr.arEther[0],
+               atu_entry.macAddr.arEther[1],
+               atu_entry.macAddr.arEther[2],
+               atu_entry.macAddr.arEther[3],
+               atu_entry.macAddr.arEther[4],
+               atu_entry.macAddr.arEther[5],
+			   (uint32_t)atu_entry.portVec);
+    }
+
+    return rc;
+}
+/*******************************************************************************
+* mv_switch_flush_vtu
+*
+* DESCRIPTION:
+*       Flush VTU on the Switch
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_flush_vtu(void)
+{
+	GT_STATUS    rc = GT_OK;
+	uint32_t   port;
+
+	if ((rc = gvtuFlush(qd_dev)) != GT_OK) {
+		printk("Flush VTU on the Switch failed with RC = [%d]\n", rc);
+		return rc;
+	}
+	memset(sw_vlan_tbl,  0,  sizeof(sw_vlan_tbl));
+	for(port = 0; port < qd_dev->numOfPorts; port++)
+	{
+		memset(&(sw_ports_tbl[port].vlan_blong), 0, sizeof(sw_ports_tbl[port].vlan_blong));
+	}
+	return rc;
+}
+/*******************************************************************************
+* mv_switch_flush_atu
+*
+* DESCRIPTION:
+*       Flush ATU on the Switch
+*
+* INPUTS:
+*       flush_cmd     FLUSH all or FLUSH all dynamic
+*       db_num        ATU DB Num, only 0 should be used, since there is only one ATU DB right now.
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_flush_atu
+(
+    IN  GT_FLUSH_CMD flush_cmd,
+    IN  uint16_t db_num
+)
+{
+	GT_STATUS    rc = GT_OK;
+
+	if((rc = gfdbFlushInDB(qd_dev, flush_cmd, db_num)) != GT_OK) {
+		printk("Flush ATU on the Switch failed with RC = [%d]\n", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* mv_switch_drv_init
+*
+* DESCRIPTION:
+*       This function init all parameters
+*
+* INPUTS:
+*       NONE.
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       NONE
+*
+* COMMENTS:
+*        There is a temprorary function.
+*
+*******************************************************************************/
+void mv_switch_drv_init
+(
+    void
+)
+{
+    uint16_t   vid;
+    uint32_t   port;
+    uint32_t   i;
+    GT_STATUS  rc = GT_OK;
+    GT_BOOL    mode;
+
+    memset(sw_ports_tbl, 0, sizeof(sw_ports_tbl));
+    memset(sw_vlan_tbl,  0,  sizeof(sw_vlan_tbl));
+
+    for(vid = 0; vid < SW_MAX_VLAN_NUM; vid++)
+    {
+        for(port = 0; port < qd_dev->numOfPorts; port++)
+        {
+           sw_vlan_tbl[vid].egr_mode[port] = NOT_A_MEMBER;
+        }
+    }
+
+    for(port = 0; port < qd_dev->numOfPorts; port++)
+    {
+       sw_ports_tbl[port].port_mode = GT_DISABLE;
+    }
+
+    /* Initialize Packet Ingress Rate Limit */
+    rc = gpirl2Initialize(qd_dev);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d:==ERROR==gpirl2Initialize failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+    }
+
+    gfdbGetLearn2All(qd_dev,&mode);
+
+    printk(KERN_DEBUG "gfdbGetLearn2All mode1[%d]\n\r",mode);
+
+    /* Enable Learn2All mode.*/
+    rc = gfdbSetLearn2All(qd_dev,GT_TRUE);
+    if (rc != GT_OK)
+    {
+        printk(KERN_ERR "%s:%d:==ERROR==gfdbSetLearn2All failed rc[0x%x]\r\n",
+               __FUNCTION__, __LINE__, rc);
+
+    }
+
+    /* Initialize weight array with default values */
+    for (i = 0; i < SW_QOS_NUM_OF_QUEUES; i++)
+    {
+        weight_arr[i] = MV_TPM_DEFAULT_WEIGHT;
+    }
+
+    gfdbGetLearn2All(qd_dev,&mode);
+
+    printk(KERN_DEBUG "gfdbGetLearn2All mode2[%d]\n\r", mode);
+
+    return;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.h
new file mode 100755
index 0000000..18c3fb9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_switch/mv_switch_wrap.h
@@ -0,0 +1,2867 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#define SW_SRC_PORT_MIN        (1)
+#define SW_SRC_PORT_MAX        (4)
+
+#define SW_QOS_NUM_OF_QUEUES   (4)
+
+#define SW_MAX_VLAN_NUM        (4096)
+#define SW_MAX_PORTS_NUM       (7)
+
+#define SW_PORT_NOT_BELONG     (0)
+#define SW_PORT_BELONG         (1)
+
+#define MV_TPM_DEFAULT_WEIGHT  (2)
+
+
+/* Initial Q_PRI and F_PRI selection */
+
+#define PRI_SEL_USE_PORTS_DEF    (0)
+#define PRI_SEL_TAG_PRI_ONLY     (1)
+#define PRI_SEL_IP_PRI_ONLY      (2)
+#define PRI_SEL_TAG_AND_IP_PRI   (3)
+#define PRI_SEL_TYPE_MAX         (4)
+
+#define SW_QOS_NUM_OF_TAG_PRI    (7)
+#define SW_QOS_DSCP_MAX          (64)
+
+
+/* LPort data base*/
+typedef struct _sw_port_info_type_t
+{
+    GT_DOT1Q_MODE   port_mode;
+    uint32_t        cnt;
+    uint32_t        vlan_blong[4095];
+} sw_port_type_info;
+
+typedef struct _sw_vlan_tbl_type
+{
+    uint32_t members;        /* bitmap of the ports max number of ports 32 */
+    uint8_t  egr_mode[SW_MAX_PORTS_NUM]; /* egress mode of each port */
+}sw_vlan_tbl_type;
+
+/* auto negotiation type */
+typedef enum _sw_autoneg_type_t
+{
+    SW_AUTONEG_1000_FDX = 1<<0,
+    SW_AUTONEG_1000_HDX = 1<<1,
+    SW_AUTONEG_100_FDX  = 1<<2,
+    SW_AUTONEG_100_HDX  = 1<<3,
+    SW_AUTONEG_10_FDX   = 1<<4,
+    SW_AUTONEG_10_HDX   = 1<<5
+}sw_autoneg_type_t;
+
+/*******************************************************************************
+* mv_switch_prv_port_add_vid
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per lport.
+*
+* INPUTS:
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       see the example sample802_1qSetup().
+*
+*******************************************************************************/
+int32_t mv_switch_prv_port_add_vid
+(
+    uint16_t vid
+);
+
+/*******************************************************************************
+* mv_switch_prv_del_vid_per_port
+*
+* DESCRIPTION:
+*       The API delete and existing VID from the list of VIDs allowed per lport.
+*
+* INPUTS:
+*       port     - port for deleting the VID.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_prv_del_vid_per_port
+(
+    uint32_t port,
+    uint16_t vid
+);
+
+/*******************************************************************************
+* mv_switch_add_static_mac
+*
+* DESCRIPTION:
+*       This function creates a static MAC entry in the MAC address table for a
+*       specific lport in the integrated switch
+*
+* INPUTS:
+*       lport		- Packet origination.
+*       static_mac	- 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_add_static_mac
+(
+	uint32_t lport,
+    uint8_t  static_mac[6]
+);
+
+/*******************************************************************************
+* mv_switch_del_static_mac
+*
+* DESCRIPTION:
+*       This function removes an existing static MAC entry from the MAC address
+*       table  in the integrated switch.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       static_mac	- 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_del_static_mac
+(
+    uint8_t static_mac[6]
+);
+
+/*******************************************************************************
+* mv_switch_set_port_max_macs
+*
+* DESCRIPTION:
+*       This function limits the number of MAC addresses per lport.
+*
+* INPUTS:
+*       lport		 - Packet origination.
+*       mac_per_port - maximum number of MAC addresses per port (1-255).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       The following care is needed when enabling this feature:
+*			1) disable learning on the ports
+*			2) flush all non-static addresses in the ATU
+*			3) define the desired limit for the ports
+*			4) re-enable learing on the ports
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_max_macs
+(
+      uint32_t lport,
+      uint8_t 	mac_per_port
+);
+
+/*******************************************************************************
+* mv_switch_get_port_max_macs
+*
+* DESCRIPTION:
+*      Port's auto learning limit. When the limit is non-zero value, the number
+*		of MAC addresses that can be learned on this lport are limited to the value
+*		specified in this API. When the learn limit has been reached any frame
+*		that ingresses this lport with a source MAC address not already in the
+*		address database that is associated with this lport will be discarded.
+*		Normal auto-learning will resume on the lport as soon as the number of
+*		active unicast MAC addresses associated to this lport is less than the
+*		learn limit.
+*		CPU directed ATU Load, Purge, or Move will not have any effect on the
+*		learn limit.
+*		This feature is disabled when the limit is zero.
+*		The following care is needed when enabling this feature:
+*			1) dsable learning on the ports
+*			2) flush all non-static addresses in the ATU
+*			3) define the desired limit for the ports
+*			4) re-enable learing on the ports
+*
+* INPUTS:
+*       owner_id	 - APP owner id - should be used for all API calls.
+*       lport		 - Packet origination.
+*
+*
+* OUTPUTS:
+*       limit - maximum number of MAC addresses per lport (1-255).
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_max_macs
+(
+      uint32_t  lport,
+      uint32_t *limit
+);
+/*******************************************************************************
+* mv_switch_clear_dynamic_mac
+*
+* DESCRIPTION:
+*       Clear all dynamic MAC.
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_clear_dynamic_mac
+(
+void
+);
+/*******************************************************************************
+* mv_switch_set_mirror
+*
+* DESCRIPTION:
+*       Set port mirror.
+*
+* INPUTS:
+*       sport		 - Source port.
+*       dport		 - Destination port.
+*       mode		 - mirror mode.
+*       enable		 - enable/disable mirror.
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_set_mirror
+(
+IN uint32_t  sport,
+IN uint32_t  dport,
+IN GT_MIRROR_MODE mode,
+IN GT_BOOL enable
+);
+
+/*******************************************************************************
+* mv_switch_get_mirror
+*
+* DESCRIPTION:
+*       Get port mirror status.
+*
+* INPUTS:
+*       sport		 - Source port.
+*       dport		 - Destination port.
+*       mode		 - mirror mode.
+*
+* OUTPUTS:
+*       enable		 - enable/disable mirror.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_get_mirror
+(
+IN uint32_t  sport,
+IN uint32_t  dport,
+IN GT_MIRROR_MODE mode,
+OUT GT_BOOL* enable
+);
+
+/*******************************************************************************
+* mv_switch_set_mtu
+*
+* DESCRIPTION:
+*       Set switch MTU size.
+*
+* INPUTS:
+*       mtu		 - MTU size.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_set_mtu
+(
+IN uint32_t mtu
+);
+
+/*******************************************************************************
+* mv_switch_get_mtu
+*
+* DESCRIPTION:
+*       Get switch MTU size.
+*
+* INPUTS:
+*
+*
+* OUTPUTS:
+*       mtu		 - MTU size.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int32_t mv_switch_get_mtu
+(
+OUT uint32_t* mtu
+);
+#if 0
+/*******************************************************************************
+* mv_switch_set_port_flooding
+*
+* DESCRIPTION:
+*       This function control the flooding behavior (unknown Dest MAC address) per lport.
+*
+* INPUTS:
+*       owner_id	 - APP owner id - should be used for all API calls.
+*       egress_port	 - Egress lport for applying the flood settings.
+*       allow_flood  - permit flooding of unknown DA: set to 1,
+*                      do not permit flooding of uknown DA: set to 0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_flooding
+(
+      uint32_t lport,
+      GT_BOOL 	mode
+);
+
+/*******************************************************************************
+* mv_switch_get_port_flooding
+*
+* DESCRIPTION:
+*       This routine gets Forward Unknown mode of a switch port.
+*		When this mode is set to GT_TRUE, normal switch operation occurs.
+*		When this mode is set to GT_FALSE, unicast frame with unknown DA addresses
+*		will not egress out this port.
+*
+* INPUTS:
+*       owner_id	 - APP owner id - should be used for all API calls.
+*       egress_port	 - Egress port for applying the flood settings.
+*
+*
+* OUTPUTS:
+*       mode  -  GT_TRUE: header mode enabled
+*				 GT_FALSE otherwise.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_flooding
+(
+      uint32_t lport,
+      uint32_t *mode
+);
+#endif
+/*******************************************************************************
+* mv_switch_set_port_tagged
+*
+* DESCRIPTION:
+*       The API allows or drops tagged packets on a per lport basis.
+*
+* INPUTS:
+*       lport		 -  lport for applying the filtering of tagged packets.
+*       mode         - set to 1 = discard tagged packets per lport
+*                      set to 0 = allow tagged packets per lport.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_tagged
+(
+      uint32_t lport,
+      GT_BOOL  mode
+);
+
+/*******************************************************************************
+* mv_switch_get_port_tagged
+*
+* DESCRIPTION:
+*       This routine gets DiscardTagged bit for the given lport.
+*
+* INPUTS:
+*       lport		 - lport for applying the filtering of tagged packets.
+
+*
+* OUTPUTS:
+*      mode  - GT_TRUE if DiscardTagged bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_tagged
+(
+      uint32_t lport,
+      uint32_t *mode
+);
+
+/*******************************************************************************
+* mv_switch_set_port_untagged
+*
+* DESCRIPTION:
+*       The API allows or drops untagged packets on a per lport basis.
+*
+* INPUTS:
+*       lport		   -  lport for applying the filtering of tagged packets.
+*       mode           - set to 1 = discard untagged packets per lport
+*                        set to 0 = alow untagged packets per lport.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_untagged
+(
+      uint32_t lport,
+      GT_BOOL 	mode
+);
+
+/*******************************************************************************
+* tpm_sw_get_port_untagged
+*
+* DESCRIPTION:
+*       This routine gets DiscardUntagged bit for the given lport.
+*
+* INPUTS:
+*       lport		   -  lport for applying the filtering of tagged packets.
+
+*
+* OUTPUTS:
+*       mode  - GT_TRUE if DiscardUntagged bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_untagged
+(
+      uint32_t lport,
+      uint32_t *mode
+);
+
+/*******************************************************************************
+* mv_switch_set_port_def_vlan
+*
+* DESCRIPTION:
+*       The API sets port default vlan id.
+*
+* INPUTS:
+*       lport	   - lport for applying the filtering of tagged packets.
+*       vid        - the port vlan id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_def_vlan
+(
+    IN uint32_t lport,
+    IN GT_U16 	vid
+);
+
+/*******************************************************************************
+* mv_switch_get_port_def_vlan
+*
+* DESCRIPTION:
+*       This routine gets DiscardUntagged bit for the given lport.
+*
+* INPUTS:
+*       lport	   - lport for applying the filtering of tagged packets.
+*
+* OUTPUTS:
+*       vid        - the port vlan id
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_def_vlan
+(
+    IN  uint32_t lport,
+    OUT GT_U16 	*vid
+);
+
+/*******************************************************************************
+* mv_switch_set_port_def_pri
+*
+* DESCRIPTION:
+*       The API sets port default priority.
+*
+* INPUTS:
+*       lport	   - lport for applying the filtering of tagged packets.
+*       pri        - the port priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_def_pri
+(
+    IN uint32_t lport,
+    IN GT_U8 	pri
+);
+
+/*******************************************************************************
+* mv_switch_get_port_def_pri
+*
+* DESCRIPTION:
+*       The API gets port default priority.
+*
+* INPUTS:
+*       lport	   - lport for applying the filtering of tagged packets.
+*
+* OUTPUTS:
+*       pri        - the port priority.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_def_pri
+(
+    IN  uint32_t lport,
+    OUT GT_U8 	*pri
+);
+
+/*******************************************************************************
+* mv_switch_port_add_vid
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       lport     -  lport for adding the vid.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       see the example sample802_1qSetup().
+*
+*******************************************************************************/
+int32_t mv_switch_port_add_vid
+(
+      uint32_t lport,
+      uint16_t vid,
+      uint16_t gmac0Idx
+);
+
+/*******************************************************************************
+* mv_switch_del_vid_per_port
+*
+* DESCRIPTION:
+*       The API delete and existing VID from the list of VIDs allowed per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       lport     -  lport for deleting the VID.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_del_vid_per_port
+(
+      uint32_t lport,
+      uint16_t vid
+);
+
+/*******************************************************************************
+* mv_switch_set_port_vid_egress_mode
+*
+* DESCRIPTION:
+*       The API sets the egress mode for a member port of a vlan.
+*
+* INPUTS:
+*       lport     - logic port id to set
+*       vid       - vlan id
+*       vid       - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_vid_egress_mode
+(
+    IN uint32_t lport,
+    IN uint16_t vid,
+    IN uint8_t  eMode
+);
+
+/*******************************************************************************
+* mv_switch_port_print_vid
+*
+* DESCRIPTION:
+*       The API return VID to the list of the allowed VIDs per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       vid     -  searching VID.
+*
+* OUTPUTS:
+*        found    - GT_TRUE, if the appropriate entry exists.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_port_print_vid
+(
+      uint32_t vid,
+      uint32_t *found
+);
+
+/*******************************************************************************
+* mv_switch_prv_set_secure_mode
+*
+* DESCRIPTION:
+*       Change a port mode in the SW data base and remove it from all VLANs
+*
+* INPUTS:
+*       port       -  secure port number
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_prv_set_secure_mode
+(
+    uint32_t port
+);
+
+/*******************************************************************************
+* mv_switch_prv_set_fallback_mode
+*
+* DESCRIPTION:
+*       Change a port mode in the SW data base and add it to all VLANs
+*
+* INPUTS:
+*       port       -  secure port number
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_prv_set_fallback_mode
+(
+    uint32_t port
+);
+
+/*******************************************************************************
+* mv_switch_set_vid_filter_per_port
+*
+* DESCRIPTION:
+*       The API sets the filtering mode of a certain lport.
+*       If the lport is in filtering mode, only the VIDs added by the
+*       tpm_sw_port_add_vid API will be allowed to ingress and egress the lport.
+*
+* INPUTS:
+*       lport       -  lport for setting the filtering mode.
+*       vid_filter  - set to 1 - means the lport will DROP all packets which are NOT in
+*                    the allowed VID list (built using API tpm_sw_port_add_vid).
+*                    set to '0' - means that the list of VIDs allowed
+*                    per lport has no significance (the list is not deleted).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_set_vid_filter_per_port
+(
+      uint32_t lport,
+      uint8_t  vid_filter
+);
+
+/*******************************************************************************
+* mv_switch_get_vid_filter_per_port
+*
+* DESCRIPTION:
+*       The API gets the filtering mode of a certain lport.
+*       If the lport is in filtering mode, only the VIDs added by the
+*       tpm_sw_port_add_vid API will be allowed to ingress and egress the lport.
+*
+* INPUTS:
+*       lport       -  lport for setting the filtering mode.
+*
+* OUTPUTS:
+*       vid_filter  - set to - means the lport will DROP all packets which are NOT in
+*                    the allowed VID list (built using API tpm_sw_port_add_vid).
+*                    set to  - means that the list of VIDs allowed
+*                    per lport has no significance (the list is not deleted).
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case  see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_vid_filter_per_port
+(
+    IN  uint32_t lport,
+    OUT uint8_t  *vid_filter
+);
+
+/*******************************************************************************
+* mv_switch_set_port_sched_mode()
+*
+* DESCRIPTION:      Configures the scheduling mode per Ethernet port.
+*
+* INPUTS:
+*       uni_port          - UNI port for setting the scheduling mode
+*       sched_mode        - scheduler mode per port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*DDD
+*******************************************************************************/
+int32_t mv_switch_set_port_sched_mode
+(
+      uint32_t            uni_port,
+      GT_PORT_SCHED_MODE  mode
+);
+
+/*******************************************************************************
+* mv_switch_set_uni_q_weight
+*
+* DESCRIPTION:
+*       The API configures the weight of a queues for all
+*       Ethernet UNI ports in the integrated switch.
+*
+* INPUTS:
+*       weight   - weight value per queue (1-8).queue (value 1-3).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.  DDD
+*
+*******************************************************************************/
+int32_t mv_switch_set_uni_q_weight
+(
+      uint8_t queue_id,
+      uint8_t weight
+);
+
+/*******************************************************************************
+* mv_switch_set_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures an ingress policing function for an Ethernet UNI lport.
+*
+* INPUTS:
+*       owner_id - APP owner id, should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*       count_mode - count mode:
+*	                           GT_PIRL2_COUNT_FRAME
+*	                           GT_PIRL2_COUNT_ALL_LAYER1
+*	                           GT_PIRL2_COUNT_ALL_LAYER2
+*	                           GT_PIRL2_COUNT_ALL_LAYER3
+*       cir      - comited info rate.
+*		      cbs	        - Committed Burst Size limit (expected to be 2kBytes)
+*		      ebs        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_uni_ingr_police_rate
+(
+    IN uint32_t	uni_port,
+    IN GT_PIRL2_COUNT_MODE	count_mode,
+    IN uint32_t cir,
+    IN uint32_t cbs,
+    IN uint32_t ebs
+);
+
+/*******************************************************************************
+* mv_switch_get_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API gets an ingress policing function for an Ethernet UNI lport.
+*
+* INPUTS:
+*       owner_id - APP owner id, should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*
+*
+* OUTPUTS:
+*       count_mode - count mode:
+*	                           GT_PIRL2_COUNT_FRAME
+*	                           GT_PIRL2_COUNT_ALL_LAYER1
+*	                           GT_PIRL2_COUNT_ALL_LAYER2
+*	                           GT_PIRL2_COUNT_ALL_LAYER3
+*       cir      - comited info rate.
+*		      cbs	        - Committed Burst Size limit (expected to be 2kBytes)
+*		      ebs        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int32_t mv_switch_get_uni_ingr_police_rate
+(
+    IN  uint32_t uni_port,
+    OUT GT_PIRL2_COUNT_MODE	*count_mode,
+    OUT uint32_t *cir,
+    OUT uint32_t *cbs,
+    OUT uint32_t *ebs
+);
+
+/*******************************************************************************
+* mv_switch_set_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures a policer function for a traffic class for an Ethernet UNI lport.
+*       There are 4 globally defined traffic classes in the integrated switch.
+*
+* INPUTS:
+*       uni_port - uni lport for configuring the ingress policer function.
+*       tc       - traffic class ( a combination of p-bits and DSCP values).
+*       cir      - comited info rate.
+*       cbs      - comited burst rate.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_set_uni_tc_ingr_police_rate
+(
+      uint32_t	uni_port,
+      uint32_t	tc,
+	  uint32_t cir,
+	  uint32_t	cbs
+);
+
+/*******************************************************************************
+* mv_switch_get_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       This routine gets the lport's ingress data limit for priority 0 or 1 or 2 or 3 frames.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*
+* OUTPUTS:
+*
+*       tc       - traffic class ( a combination of p-bits and DSCP values).
+*       cir      - comited info rate.
+*       cbs      - comited burst rate
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_uni_tc_ingr_police_rate
+(
+      uint32_t uni_port,
+      uint32_t *tc,
+	  uint32_t *cir,
+      uint32_t *cbs
+);
+
+/*******************************************************************************
+* mv_switch_set_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API Configures the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*       trg_lport            - uni lport for configuring the egress rate limit.
+*		  mode					  - frame/rate limit mode
+*       frame_rate_limit_val  - egress rate limit value.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       GT_ERATE_TYPE used kbRate - frame rate valid values are:
+*							        7600,..., 9600,
+*							        10000, 20000, 30000, 40000, ..., 100000,
+*							        110000, 120000, 130000, ..., 1000000.
+*
+*
+*******************************************************************************/
+int32_t mv_switch_set_uni_egr_rate_limit
+(
+IN uint32_t	trg_lport,
+IN GT_PIRL_ELIMIT_MODE mode,
+IN uint32_t frame_rate_limit_val
+);
+
+/*******************************************************************************
+* mv_switch_get_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API return the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id        - APP owner id - should be used for all API calls.
+*       trg_lport        - uni lport for configuring the egress rate limit.
+
+*
+* OUTPUTS:
+*		   mode					  - frame/rate limit mode
+*        rate_limit_val  - egress rate limit value..
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       GT_ERATE_TYPE used kbRate - frame rate valid values are:
+*							        7600,..., 9600,
+*							        10000, 20000, 30000, 40000, ..., 100000,
+*							        110000, 120000, 130000, ..., 1000000.
+
+*
+*******************************************************************************/
+int32_t mv_switch_get_uni_egr_rate_limit
+(
+     IN uint32_t trg_lport,
+     OUT GT_PIRL_ELIMIT_MODE *mode,
+	 OUT uint32_t *frame_rate_limit_val
+);
+
+/*******************************************************************************
+* mv_switch_set_age_time
+*
+* DESCRIPTION:
+*       This function Sets the Mac address table size.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       time_out    - Aging Time value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_set_age_time
+(
+	  uint32_t time_out
+);
+
+/*******************************************************************************
+* mv_switch_set_mac_learn
+*
+* DESCRIPTION:
+*       Enable/disable automatic learning of new source MAC addresses on port
+*       ingress.
+*
+* INPUTS:
+*       lport       - logical port number to set.
+*       enable - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+int32_t mv_switch_set_mac_learn
+(
+	IN uint32_t lport,
+	IN GT_BOOL  enable
+);
+/*******************************************************************************
+* mv_switch_get_mac_learn
+*
+* DESCRIPTION:
+*       Get automatic learning status of new source MAC addresses on port ingress.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       lport       - logical port number to set.
+*       enable - GT_TRUE if enabled  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+int32_t mv_switch_get_mac_learn
+(
+	IN uint32_t lport,
+    OUT GT_BOOL  *enable
+);
+/*******************************************************************************
+* mv_switch_set_port_vlan_ports
+*
+* DESCRIPTION:
+*       This routine sets the port VLAN group port membership list.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - logical port number to set.
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_vlan_ports
+(
+	  uint32_t lport,
+      uint32_t memPorts[],
+      uint8_t  memPortsLen
+);
+
+/*******************************************************************************
+* mv_switch_get_port_vlan_ports
+*
+* DESCRIPTION:
+*       This routine gets the port VLAN group port membership list.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - logical port number to set.
+*
+*
+* OUTPUTS:
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_vlan_ports
+(
+	  uint32_t lport,
+      uint32_t memPorts[],
+      uint8_t  *memPortsLen
+);
+
+/*******************************************************************************
+* mv_switch_get_age_time
+*
+* DESCRIPTION:
+*       This function Sets the Mac address table size.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*
+* OUTPUTS:
+*       time_out    - time out value.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_get_age_time
+(
+	  uint32_t *time_out
+);
+
+/*******************************************************************************
+* mv_switch_set_ingress_limit_mode
+*
+* DESCRIPTION:
+*       This routine sets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - logical port number to set.
+*       mode 	    - rate control ingress limit mode.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*    GT_LIMT_ALL = 0,        limit and count all frames
+*    GT_LIMIT_FLOOD,         limit and count Broadcast, Multicast and flooded unicast frames
+*    GT_LIMIT_BRDCST_MLTCST, limit and count Broadcast and Multicast frames
+*    GT_LIMIT_BRDCST         limit and count Broadcast frames
+*
+*******************************************************************************/
+int32_t mv_switch_set_ingress_limit_mode
+(
+	  uint32_t           lport,
+      GT_RATE_LIMIT_MODE mode
+);
+
+/*******************************************************************************
+* mv_switch_get_ingress_limit_mode
+*
+* DESCRIPTION:
+*       This routine gets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - logical port number to set.
+*
+*
+* OUTPUTS:
+*        mode 	    - rate control ingress limit mode.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*    GT_LIMT_ALL = 0,        limit and count all frames
+*    GT_LIMIT_FLOOD,         limit and count Broadcast, Multicast and flooded unicast frames
+*    GT_LIMIT_BRDCST_MLTCST, limit and count Broadcast and Multicast frames
+*    GT_LIMIT_BRDCST         limit and count Broadcast frames
+*
+*******************************************************************************/
+int32_t mv_switch_get_ingress_limit_mode
+(
+	  uint32_t           lport,
+      GT_RATE_LIMIT_MODE *mode
+);
+
+/*******************************************************************************
+* mv_switch_set_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This routine sets initial QPri and FPri selection.
+*
+* INPUTS:
+*       lport       - Port number to set init pri.
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+int32_t mv_switch_set_priority_selection
+(
+    IN  uint8_t  lport,
+    IN  uint8_t  init_pri,
+    IN  GT_BOOL  tag_if_both
+);
+
+/*******************************************************************************
+* mv_switch_get_priority_selection
+*
+* DESCRIPTION:
+*       This routine gets initial QPri and FPri selection.
+*
+* INPUTS:
+*       lport       - Port number to set init pri.
+*
+* OUTPUTS:
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+int32_t mv_switch_get_priority_selection
+(
+    IN  uint8_t  lport,
+    OUT uint8_t *init_pri,
+    OUT GT_BOOL *tag_if_both
+);
+
+/*******************************************************************************
+* mv_switch_set_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This routine maps a tag priority to a queue priority.
+*
+* INPUTS:
+*       tag_pri     - Source tag priority number.
+*       q_pri       - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+int32_t mv_switch_set_tag_pri_mapping
+(
+    IN  uint8_t  tag_pri,
+    IN  uint8_t  q_pri
+);
+
+/*******************************************************************************
+* mv_switch_get_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This routine gets the queue priority for a tag priority mapping to.
+*
+* INPUTS:
+*       tag_pri     - Source tag priority number.
+*
+* OUTPUTS:
+*       q_pri       - Target queue priority number.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+int32_t mv_switch_get_tag_pri_mapping
+(
+    IN  uint8_t  tag_pri,
+    OUT uint8_t *q_pri
+);
+
+/*******************************************************************************
+* mv_switch_set_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This routine maps a dscp value to a queue priority.
+*
+* INPUTS:
+*       dscp        - Source dscp value.
+*       q_pri       - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+int32_t mv_switch_set_ip_pri_mapping
+(
+    IN  uint8_t  dscp,
+    IN  uint8_t  q_pri
+);
+
+/*******************************************************************************
+* mv_switch_get_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This routine gets the queue priority for a dscp value mapping to.
+*
+* INPUTS:
+*       dscp        - Source dscp value.
+*
+* OUTPUTS:
+*       q_pri       - Target queue priority number.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+int32_t mv_switch_get_ip_pri_mapping
+(
+    IN  uint8_t  dscp,
+    OUT uint8_t *q_pri
+);
+
+/*******************************************************************************
+* mv_switch_set_unknown_unicast_flood
+*
+* DESCRIPTION:
+*       This routine enable/disable unknown unicast frame egress on a specific port.
+*
+* INPUTS:
+*       lport   - Port number to egress unknown unicast frames.
+*       enable  - Enable unknown unicast flooding.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_unknown_unicast_flood
+(
+    IN  uint8_t  lport,
+    OUT GT_BOOL  enable
+);
+
+/*******************************************************************************
+* mv_switch_get_unknown_unicast_flood
+*
+* DESCRIPTION:
+*       This routine gets unknown unicast frame egress mode of a specific port.
+*
+* INPUTS:
+*       lport   - Port number to egress unknown unicast frames.
+*
+* OUTPUTS:
+*       enable  - Enable unknown unicast flooding.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_unknown_unicast_flood
+(
+    IN  uint8_t  lport,
+    OUT GT_BOOL *enable
+);
+
+/*******************************************************************************
+* mv_switch_set_unknown_multicast_flood
+*
+* DESCRIPTION:
+*       This routine enable/disable unknown multicast frame egress on a specific port.
+*
+* INPUTS:
+*       lport   - Port number to egress unknown multicast frames.
+*       enable  - Enable unknown multicast flooding.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_unknown_multicast_flood
+(
+    IN  uint8_t  lport,
+    OUT GT_BOOL  enable
+);
+
+/*******************************************************************************
+* mv_switch_get_unknown_multicast_flood
+*
+* DESCRIPTION:
+*       This routine gets unknown multicast frame egress mode of a specific port.
+*
+* INPUTS:
+*       lport   - Port number to egress unknown multicast frames.
+*
+* OUTPUTS:
+*       enable  - Enable unknown multicast flooding.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_unknown_multicast_flood
+(
+    IN  uint8_t  lport,
+    OUT GT_BOOL *enable
+);
+
+/*******************************************************************************
+* mv_switch_set_broadcast_flood
+*
+* DESCRIPTION:
+*       This routine decides whether the switch always floods the broadcast
+*       frames to all portsr or uses the multicast egress mode (per port).
+*
+* INPUTS:
+*       always_on - always floods the broadcast regardless the multicast egress mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_broadcast_flood
+(
+    IN  GT_BOOL  always_on
+);
+
+/*******************************************************************************
+* mv_switch_get_broadcast_flood
+*
+* DESCRIPTION:
+*       This routine gets the global mode of broadcast flood.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       always_on - always floods the broadcast regardless the multicast egress mode.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_broadcast_flood
+(
+    IN  GT_BOOL *always_on
+);
+
+/*******************************************************************************
+* mv_switch_set_marvell_header_mode
+*
+* DESCRIPTION:
+*       This routine sets ingress and egress header mode of a switch port.
+*
+* INPUTS:
+*       lport  - logical port number to set.
+*       enable - enable marvell header.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_marvell_header_mode
+(
+    IN  uint8_t  lport,
+    IN  GT_BOOL  enable
+);
+
+/*******************************************************************************
+* mv_switch_get_marvell_header_mode
+*
+* DESCRIPTION:
+*       This routine gets ingress and egress header mode of a switch port.
+*
+* INPUTS:
+*       lport  - logical port number to set.
+*
+* OUTPUTS:
+*       enable - enable marvell header.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_marvell_header_mode
+(
+    IN  uint8_t  lport,
+    IN  GT_BOOL *enable
+);
+
+/*******************************************************************************
+* mv_switch_set_port_preamble
+*
+* DESCRIPTION:
+*       This routine sets preamble of a switch port.
+*
+* INPUTS:
+*       lport  - logical port number to set.
+*       preamble - preamble length.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_preamble
+(
+    IN  uint8_t  lport,
+    IN  uint16_t preamble
+);
+
+/*******************************************************************************
+* mv_switch_get_port_preamble
+*
+* DESCRIPTION:
+*       This routine gets preamble of a switch port.
+*
+* INPUTS:
+*       lport  - logical port number to set.
+*
+* OUTPUTS:
+*       preamble - preamble length.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_preamble
+(
+    IN  uint8_t   lport,
+    OUT uint16_t *preamble
+);
+
+/*******************************************************************************
+* mv_switch_set_port_autoneg_mode
+*
+* DESCRIPTION:
+*       The API Configures the auto negotiation state of an Ethernet  lport.
+* INPUTS:
+*       lport        		- logical port  number for setting the auto negotiation state.
+*       autoneg_state  - autonegotiation state, enabled or disabled.
+*       autoneg_mode   - enum:
+*                        SPEED_AUTO_DUPLEX_AUTO: Auto for both speed and duplex
+*                        SPEED_1000_DUPLEX_AUTO: 1000Mbps and auto duplex
+*                        SPEED_100_DUPLEX_AUTO:  100Mbps and auto duplex
+*                        SPEED_10_DUPLEX_AUTO:   10Mbps and auto duplex
+*                        SPEED_AUTO_DUPLEX_FULL: Auto for speed only and Full duplex
+*                        SPEED_AUTO_DUPLEX_HALF: Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                        SPEED_1000_DUPLEX_FULL: 1000Mbps Full duplex.
+*                        SPEED_1000_DUPLEX_HALF: 1000Mbps half duplex.
+*                        SPEED_100_DUPLEX_FULL:  100Mbps Full duplex.
+*                        SPEED_100_DUPLEX_HALF:  100Mbps half duplex.
+*                        SPEED_10_DUPLEX_FULL:   10Mbps Full duplex.
+*                        SPEED_10_DUPLEX_HALF:   10Mbps half duplex.
+
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case,see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_autoneg_mode
+(
+    IN uint32_t  lport,
+    IN GT_BOOL           autoneg_state,
+    IN GT_PHY_AUTO_MODE  autoneg_mode
+);
+
+
+/*******************************************************************************
+* mv_switch_get_port_autoneg_mode
+*
+* DESCRIPTION:
+*       The API return the the auto negotiation state of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the auto negotiation state.
+*
+*
+* OUTPUTS:
+*       autoneg_state  - autonegotiation state, enabled or disabled.
+*       autoneg_mode   - enum:
+*                        SPEED_AUTO_DUPLEX_AUTO: Auto for both speed and duplex
+*                        SPEED_1000_DUPLEX_AUTO: 1000Mbps and auto duplex
+*                        SPEED_100_DUPLEX_AUTO:  100Mbps and auto duplex
+*                        SPEED_10_DUPLEX_AUTO:   10Mbps and auto duplex
+*                        SPEED_AUTO_DUPLEX_FULL: Auto for speed only and Full duplex
+*                        SPEED_AUTO_DUPLEX_HALF: Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                        SPEED_1000_DUPLEX_FULL: 1000Mbps Full duplex.
+*                        SPEED_1000_DUPLEX_HALF: 1000Mbps half duplex.
+*                        SPEED_100_DUPLEX_FULL:  100Mbps Full duplex.
+*                        SPEED_100_DUPLEX_HALF:  100Mbps half duplex.
+*                        SPEED_10_DUPLEX_FULL:   10Mbps Full duplex.
+*                        SPEED_10_DUPLEX_HALF:   10Mbps half duplex.
+
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_autoneg_mode
+(
+    IN  uint32_t lport,
+    OUT GT_BOOL           *autoneg_state,
+    OUT GT_PHY_AUTO_MODE  *autoneg_mode
+);
+
+/*******************************************************************************
+* mv_switch_restart_port_autoneg
+*
+* DESCRIPTION:
+*       The API restart the auto negotiation of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for restarting the auto negotiation state.
+*
+*
+* OUTPUTS:
+*        NONE.
+*								.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_restart_port_autoneg
+(
+    IN  uint32_t lport
+);
+/*******************************************************************************
+* mv_switch_set_phy_port_state
+*
+* DESCRIPTION:
+*       The API Configures the PHY port  state of an Ethernet  lport.
+* INPUTS:
+*       lport            - logical port to set.
+*       phy_port_state  - PHY port  state to set.
+*				     0:normal state
+*				     1:power down
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_set_phy_port_state
+(
+    IN uint32_t  lport,
+    IN GT_BOOL  phy_port_state
+);
+/*******************************************************************************
+* mv_switch_get_phy_port_state
+*
+* DESCRIPTION:
+*       The API return the PHY port  state of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the PHY port state.
+*
+*
+* OUTPUTS:
+*        phy_port_state  -  0:normal state
+*				       1:power down									.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_phy_port_state
+(
+    IN  uint32_t lport,
+    OUT GT_BOOL * phy_port_state
+);
+/*******************************************************************************
+* mv_switch_get_phy_port_state
+*
+* DESCRIPTION:
+*       The API return the PHY port  state of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the PHY port state.
+*
+*
+* OUTPUTS:
+*        phy_port_state  -  0:normal state
+*				       1:power down									.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_link_status
+(
+    IN  uint32_t lport,
+    OUT GT_BOOL * phy_port_state
+);
+/*******************************************************************************
+* mv_switch_get_port_duplex_status
+*
+* DESCRIPTION:
+*       The API return realtime port duplex status of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the port link status.
+*
+*
+* OUTPUTS:
+*        port_duplex_status  -  0:half deplex mode
+*				               1:full deplex mode					.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_duplex_status
+(
+    IN  uint32_t lport,
+    OUT GT_BOOL * port_duplex_status
+);
+
+/*******************************************************************************
+* mv_switch_get_port_speed_mode
+*
+* DESCRIPTION:
+*       The API return realtime port speed mode of an Ethernet  lport.
+* INPUTS:
+*       lport        - logical port  number for getting the port link status.
+*
+*
+* OUTPUTS:
+*        port_duplex_status  -  0:10M
+*				               1:100M
+*						 2:1000M
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_speed_mode
+(
+    IN  uint32_t lport,
+    OUT GT_PORT_SPEED_MODE   *speed
+);
+/*******************************************************************************
+* mv_switch_set_port_pause
+*
+* DESCRIPTION:
+*       This routine will set the pause bit in Autonegotiation Advertisement
+*		Register. And restart the autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*		state - GT_PHY_PAUSE_MODE enum value.
+*				GT_PHY_NO_PAUSE		- disable pause
+* 				GT_PHY_PAUSE		- support pause
+*				GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*				GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+int32_t mv_switch_set_port_pause
+(
+IN GT_LPORT  port,
+IN GT_PHY_PAUSE_MODE state
+);
+/*******************************************************************************
+* mv_switch_get_port_pause
+*
+* DESCRIPTION:
+*       This routine will get the pause bit in Autonegotiation Advertisement
+*		Register.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+*
+* OUTPUTS:
+*		state - GT_PHY_PAUSE_MODE enum value.
+*				GT_PHY_NO_PAUSE		- disable pause
+* 				GT_PHY_PAUSE		- support pause
+*				GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*				GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+int32_t mv_switch_get_port_pause
+(
+IN GT_LPORT  port,
+OUT  GT_PHY_PAUSE_MODE *state
+);
+/*******************************************************************************
+* mv_switch_get_port_pause_state
+*
+* DESCRIPTION:
+*     This routine will get the current pause state.
+*		Register.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+*
+* OUTPUTS:
+*		state -
+*				GT_FALSE: MAC Pause not implemented in the link partner or in MyPause
+*				GT_TRUE:MAC Pause is implemented in the link partner and in MyPause
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+* COMMENTS:
+*       None.
+*******************************************************************************/
+
+int32_t mv_switch_get_port_pause_state
+(
+IN GT_LPORT  port,
+OUT  GT_BOOL *state
+);
+/*******************************************************************************
+* mv_switch_set_port_loopback
+*
+* DESCRIPTION:
+* Enable/Disable Internal Port Loopback.
+* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and
+*   forces speed to be 10Mbps.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
+*   it is recommended to call gprtSetPortAutoMode for PHY configuration after
+*   Loopback test.
+* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled and Link is active, the current speed is used.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   All other cases, default MAC Interface speed is used. Please refer to the data
+*   sheet for the information of the default MAC Interface speed.
+*
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+* enable - If GT_TRUE, enable loopback mode
+*				 If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+
+int32_t mv_switch_set_port_loopback
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+);
+/*******************************************************************************
+* mv_switch_get_port_loopback
+*
+* DESCRIPTION:
+* Get Internal Port Loopback state.
+* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and
+*   forces speed to be 10Mbps.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
+*   it is recommended to call gprtSetPortAutoMode for PHY configuration after
+*   Loopback test.
+* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled and Link is active, the current speed is used.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   All other cases, default MAC Interface speed is used. Please refer to the data
+*   sheet for the information of the default MAC Interface speed.
+*
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* enable - If GT_TRUE,  loopback mode is enabled
+* If GT_FALSE,  loopback mode is disabled
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_loopback
+(
+IN GT_LPORT  port,
+OUT GT_BOOL   *enable
+);
+/*******************************************************************************
+* mv_switch_set_port_line_loopback
+*
+* DESCRIPTION:
+* Enable/Disable Port Line Loopback.
+*
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register FE:28.4, GE:21_2.14  - Loop_back
+*
+*******************************************************************************/
+
+int32_t mv_switch_set_port_line_loopback
+(
+	IN GT_LPORT  port,
+	IN GT_BOOL   enable
+);
+
+/*******************************************************************************
+* mv_switch_get_port_line_loopback
+*
+* DESCRIPTION:
+* Get Port Line Loopback status.
+*
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register FE:28.4, GE:21_2.14  - Loop_back
+*
+*******************************************************************************/
+
+int32_t mv_switch_get_port_line_loopback
+(
+	IN GT_LPORT  port,
+	OUT GT_BOOL*   enable
+);
+
+/*******************************************************************************
+* mv_switch_set_port_duplex_mode
+*
+* DESCRIPTION:
+* 		Sets duplex mode for a specific logical port. This function will keep
+*		the speed and loopback mode to the previous value, but disable others,
+*		such as Autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+* 		enable	- Enable/Disable dulpex mode
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_duplex_mode
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+);
+/*******************************************************************************
+* mv_switch_get_port_duplex_mode
+*
+* DESCRIPTION:
+* 		Gets duplex mode for a specific logical port.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+*		enable	- Dulpex mode :Enabled or Disabled
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_duplex_mode
+(
+IN GT_LPORT  port,
+OUT GT_BOOL*   enable
+);
+/*******************************************************************************
+* mv_switch_set_port_speed
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		speed -    PHY_SPEED_10_MBPS -10 Mbps
+*				PHY_SPEED_100_MBPS -100 Mbps
+* 				PHY_SPEED_1000_MBPS -100 Mbps.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t mv_switch_set_port_speed
+(
+IN GT_LPORT  port,
+IN GT_PHY_SPEED speed
+);
+/*******************************************************************************
+* mv_switch_get_port_speed
+*
+* DESCRIPTION:
+*       This routine will get current PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*
+* OUTPUTS:
+*		speed -    PHY_SPEED_10_MBPS -10 Mbps
+*				PHY_SPEED_100_MBPS -100 Mbps
+* 				PHY_SPEED_1000_MBPS -100 Mbps.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t mv_switch_get_port_speed
+(
+IN GT_LPORT  port,
+OUT GT_PHY_SPEED *speed
+);
+
+/*******************************************************************************
+* mv_switch_set_port_forced_link
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable-
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t mv_switch_set_port_forced_link
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+);
+
+/*******************************************************************************
+* mv_switch_get_port_forced_link
+*
+* DESCRIPTION:
+* 		Gets duplex mode for a specific logical port.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+*		enable	- Forced Link mode :Enabled or Disabled
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_forced_link
+(
+IN GT_LPORT  port,
+OUT GT_BOOL*   enable
+);
+
+
+/*******************************************************************************
+* mv_switch_set_port_link_value
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable - Forced Link Value : Enabled or Disabled
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_link_value
+(
+IN GT_LPORT  port,
+IN GT_BOOL   enable
+);
+
+/*******************************************************************************
+* mv_switch_get_port_link_value
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*
+*		enable - Forced Link Value : Enabled or Disabled
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t mv_switch_get_port_link_value
+(
+IN GT_LPORT  port,
+OUT GT_BOOL*   enable
+);
+
+
+
+
+
+/*------------------------------------------------------------------------------
+                            Debug functions
+------------------------------------------------------------------------------*/
+
+
+/*******************************************************************************
+* mv_switch_clear_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_clear_port_counters
+(
+    void
+);
+
+/*******************************************************************************
+* mv_switch_set_global_reg
+*
+* DESCRIPTION:
+*       This function sets value to the global register.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_set_global_reg
+(
+	  uint8_t  regAddr,
+      uint16_t data
+);
+
+/*******************************************************************************
+* mv_switch_get_global_reg
+*
+* DESCRIPTION:
+*       This function gets value from the global register.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_get_global_reg
+(
+      uint8_t  regAddr,
+      uint16_t *data
+);
+
+/*******************************************************************************
+* mv_switch_set_port_reg
+*
+* DESCRIPTION:
+*       This function sets value to the port register.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_set_port_reg
+(
+      uint8_t  lport,
+      uint8_t  regAddr,
+      uint16_t data
+);
+
+/*******************************************************************************
+* mv_switch_get_port_reg
+*
+* DESCRIPTION:
+*       This function gets value from the port register.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+*       data        - The data to be written.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_reg
+(
+      uint8_t  lport,
+      uint8_t  regAddr,
+      uint16_t *data
+);
+
+/*******************************************************************************
+* mv_switch_print_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        Clear on read.
+*
+*******************************************************************************/
+int32_t mv_switch_print_port_counters
+(
+      uint32_t lport
+);
+
+/*******************************************************************************
+* mv_switch_clean_port_counters
+*
+* DESCRIPTION:
+*       This function clean all counters of the given port
+*
+* INPUTS:
+*       owner_id	- APP owner id, should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_clean_port_counters
+(
+   IN  uint32_t lport
+);
+
+/*******************************************************************************
+* mv_switch_get_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        Clear on read.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_counters
+(
+      uint32_t              lport,
+      GT_STATS_COUNTER_SET3 *statsCounterSet
+);
+
+/*******************************************************************************
+* mv_switch_get_port_drop_counters
+*
+* DESCRIPTION:
+*       This function gets the port InDiscards, InFiltered, and OutFiltered counters.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       ctr         - the counters value.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        Clear on read.
+*
+*******************************************************************************/
+int32_t mv_switch_get_port_drop_counters
+(
+      uint32_t              lport,
+      GT_PORT_STAT2         *ctr
+);
+
+/*******************************************************************************
+* mv_switch_print_fdb
+*
+* DESCRIPTION:
+*       This function gets all FDB table.
+*
+* INPUTS:
+*       owner_id	- APP owner id - should be used for all API calls.
+*       db_num      - ATU MAC Address Database number. If multiple address
+*					 databases are not being used, DBNum should be zero.
+*					 If multiple address databases are being used, this value
+*					 should be set to the desired address database number.
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_print_fdb
+(
+      uint16_t db_num
+);
+/*******************************************************************************
+* mv_switch_flush_vtu
+*
+* DESCRIPTION:
+*       Flush VTU on the Switch
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_flush_vtu(void);
+
+/*******************************************************************************
+* mv_switch_flush_atu
+*
+* DESCRIPTION:
+*       Flush ATU on the Switch
+*
+* INPUTS:
+*       flush_cmd     FLUSH all or FLUSH all dynamic
+*       db_num        ATU DB Num, only 0 should be used, since there is only one ATU DB right now .
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+int32_t mv_switch_flush_atu
+(
+    IN  GT_FLUSH_CMD flush_cmd,
+    IN  uint16_t db_num
+);
+
+/*******************************************************************************
+* mv_switch_drv_init
+*
+* DESCRIPTION:
+*       This function init all parameters
+*
+* INPUTS:
+*       NONE.
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       NONE
+*
+* COMMENTS:
+*        There is a temprorary function.
+*
+*******************************************************************************/
+void mv_switch_drv_init
+(
+    void
+);
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/Kconfig
new file mode 100755
index 0000000..87eb427
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/Kconfig
@@ -0,0 +1,54 @@
+menu "SoC TPM support"
+depends on MV_INCLUDE_TPM
+
+config  MV_TPM
+	tristate "Support for Marvell TPM Driver"
+      	default y
+	---help---
+
+comment "TPM Driver Options"
+depends on MV_TPM
+
+config  MV_TPM_Z1_VER
+	bool "Support for TPM Z1 Version"
+	depends on MV_TPM
+      	default n
+	---help---
+
+config  MV_TPM_Z2_VER
+	bool "Support for TPM Z2 Version"
+	depends on MV_TPM
+      	default y
+	---help---
+
+config  MV_TPM_FPGA_VER
+	bool "Support for TPM FPGA Version"
+	depends on MV_TPM
+      	default n
+	---help---
+
+config  MV_TPM_INT_LOCK
+	bool "Support for TPM Protection - Int Lock"
+	depends on MV_TPM
+      	default n
+	---help---
+
+config  MV_TPM_DEBUG_PRINT
+	bool "Support for tpm Debug printing"
+	depends on MV_TPM
+      	default N
+	---help---
+
+config  MV_TPM_SFS_2_IOCTL
+	bool "Support for debugging ioctl API via sysfs interface"
+	depends on MV_TPM
+	default N
+	---help---
+	
+config  MV_TPM_SYSFS_HELP
+	bool "Support for tpm sysfs help"
+	depends on MV_TPM
+      	default Y
+	---help---
+
+endmenu
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/Makefile
new file mode 100755
index 0000000..da84deb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/Makefile
@@ -0,0 +1,47 @@
+#
+# Makefile for the Marvell TPM driver
+#
+
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifdef CONFIG_MV_HAL_RULES_PATH
+include $(srctree)/include/config/auto.conf
+include $(srctree)/$(subst ",,$(CONFIG_MV_HAL_RULES_PATH))
+endif
+
+TPM_OBJS += 	core/tpm_api.o \
+		core/tpm_db.o \
+		core/tpm_counter.o \
+		core/tpm_mempool.o \
+		core/tpm_init.o \
+		core/tpm_pkt_proc_logic.o \
+		core/tpm_tm.o \
+		core/tpm_pnc_logic.o \
+		core/tpm_print.o \
+		core/tpm_trace.o \
+		core/tpm_sysfs_trace.o \
+		core/tpm_sysfs_print.o \
+		core/tpm_setup.o \
+		core/tpm_xml_params.o \
+		core/tpm_mtu.o\
+		core/tpm_ctc_cm.o\
+		core/tpm_cpu_port_fc.o\
+		plat/tpm_modz2_mgr.o \
+		plat/tpm_pnc_mgr.o \
+		plat/tpm_switch_mgr.o \
+		plat/tpm_alarm.o \
+		perf/tpm_bring_up.o \
+		perf/tpm_mng_if.o \
+		perf/tpm_usr_if.o \
+		perf/tpm_sysfs_setup.o \
+		perf/tpm_sysfs_rule_db.o \
+		perf/tpm_sysfs_hwcall.o \
+		perf/tpm_sysfs_help.o \
+		perf/tpm_sysfs_utils.o\
+		perf/tpm_self_check.o
+
+mv_tpm-objs := $(TPM_OBJS)
+obj-$(CONFIG_MV_TPM) := mv_tpm.o
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.c
new file mode 100755
index 0000000..970597b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.c
@@ -0,0 +1,3172 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_api.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1.1.1
+*
+*
+*******************************************************************************/
+#include <linux/version.h>
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+#define RET_BUSY_ERROR(ret_code, busy_ret_code)\
+		if (ret_code != TPM_OK)\
+			return(ret_code);\
+		else\
+			return (busy_ret_code);
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/********************************** Packet Processor APIs *********************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/********************************** Administrative APIs ***********************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_create_ownerid()
+*
+* DESCRIPTION:      Creates an ownerId per an application group.
+*
+* INPUTS:
+*
+* OUTPUTS:
+* owner_id           - ID of an application group.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* This function is used for error prevention and not as a security mechanism.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_create_ownerid(uint32_t *owner_id)
+{
+	printk(KERN_WARNING "\n  <<tpm_create_ownerid>> NOT implemented. \n");
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_create_ownerid);
+
+/*******************************************************************************
+* tpm_request_api_ownership()
+*
+* DESCRIPTION:      Establishes an ownership between owner_id and a group of APIs.
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* api_type           - the API group whom ownership is requested.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_api_ownership_error_t tpm_request_api_ownership(uint32_t owner_id,
+						    tpm_api_type_t api_type)
+{
+	printk(KERN_WARNING "\n  <<tpm_request_api_ownership>> NOT implemented. \n");
+	return API_OWNERSHIP_SUCCESS;
+}
+EXPORT_SYMBOL(tpm_request_api_ownership);
+
+/*******************************************************************************
+* tpm_mib_reset()
+*
+* DESCRIPTION:      Performs MIB reset
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* reset_level        - The reset level determines the which elements will not be reset in the API call
+*                      ( by comparing to the element's reset level)
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mib_reset(uint32_t owner_id,
+			       tpm_reset_level_enum_t reset_level)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_mib_reset(owner_id, reset_level);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_mib_reset);
+
+/*******************************************************************************
+* tpm_erase_section()
+*
+* DESCRIPTION:      Erases a section per an application group.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* api_type          - the API group area to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_erase_section(uint32_t owner_id,
+				   tpm_api_type_t api_type)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_erase_section(owner_id, api_type);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_erase_section);
+
+/*******************************************************************************
+* tpm_get_section_free_size()
+*
+* DESCRIPTION:      Returns the free size of an application group.
+*
+* INPUTS:
+* api_type         - the API group for retrieving the section size.
+*
+* OUTPUTS:
+* cur_size          - number of free entries per API group.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_section_free_size(tpm_api_type_t	api_type,
+					   int32_t	       *cur_size)
+{
+	uint32_t api_rng_size, num_valid_entries, last_valid, tbl_start;
+	tpm_pnc_ranges_t prim_pnc_range;
+	tpm_api_sections_t api_section = TPM_INVALID_SECTION;
+	int32_t int_ret_code;
+
+	if (!cur_size)
+		return ERR_NULL_POINTER;
+
+	if (ILLEGAL_API(api_type)) {
+		printk(KERN_ERR "Error, API Type does not exist (%d))\n", api_type);
+		return ERR_API_TYPE_INVALID;
+	}
+
+	int_ret_code = tpm_db_api_section_get_from_api_type(api_type, &api_section);
+	if (int_ret_code != TPM_OK) {
+		printk(KERN_ERR "Error, API Type does not exist (%d))\n", api_type);
+		return (int_ret_code);
+	}
+
+	int_ret_code = tpm_db_api_section_get(api_section, &api_rng_size, &num_valid_entries,
+					      &prim_pnc_range, &last_valid, &tbl_start);
+	if (int_ret_code != TPM_OK) {
+		printk(KERN_ERR "Error, API Section does not exist\n");
+		return (int_ret_code);
+	}
+
+	*cur_size = api_rng_size - num_valid_entries;
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_get_section_free_size);
+
+/******************************************************************************/
+/********************************** Data Forwarding APIs **********************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_add_l2_rule()
+*
+* DESCRIPTION:      Creates a new primary L2 processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for L2 API:
+*                        TPM_L2_PARSE_MAC_DA|TPM_L2_PARSE_MAC_SA|TPM_L2_PARSE_ONE_VLAN_TAG
+*                        |TPM_L2_PARSE_TWO_VLAN_TAG|TPM_L2_PARSE_ETYPE|TPM_L2_PARSE_PPPOE_SES
+*                        |TPM_L2_PARSE_PPP_PROT|TPM_L2_PARSE_GEMPORT)
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for L2 API:
+*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_TAG2_MASK|
+*                        TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+* l2_key             - Information to create a parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frw            - Information for packet forwarding decision.
+* pkt_mod            - Packet modification information.
+* pkt_mod_bm         - Bitmap containind the set of fields in the packet to be changed.
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      possible "next_phase" for L2 API   -> STAGE_L3_TYPE , STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number which is used when deleting the rule.
+*                     (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_l2_rule(uint32_t owner_id,
+				 tpm_src_port_type_t src_port,
+				 uint32_t rule_num,
+				 uint32_t *rule_idx,
+				 tpm_parse_fields_t parse_rule_bm,
+				 tpm_parse_flags_t parse_flags_bm,
+				 tpm_l2_acl_key_t *l2_key,
+				 tpm_pkt_frwd_t *pkt_frwd,
+				 tpm_pkt_mod_t *pkt_mod,
+				 tpm_pkt_mod_bm_t pkt_mod_bm,
+				 tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_section Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_L2_PRIM, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_l2_prim_acl_rule(owner_id, src_port, rule_num, rule_idx, parse_rule_bm, parse_flags_bm,
+						 l2_key, pkt_frwd, pkt_mod, pkt_mod_bm, rule_action);
+	if (ret_code != TPM_OK)
+	{
+		/* to remove MC_AI_BITS if add l2 acl rule failed */
+		tpm_proc_mc_vid_remove_ai_bits(rule_action, src_port, l2_key, ret_code);
+	}
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_L2_PRIM, rule_num);
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_l2_rule);
+
+/*******************************************************************************
+* tpm_add_l3_type_rule()
+*
+* DESCRIPTION:      Creates a new L3 type (ether type of pppoe proto) processing ACL.
+*                   It is used for operations that are not possible to be performed
+*                   in a single ACL or to ease the primary ACL processing
+*                   (as a helper of the primary L2 ACL).
+*                   The L3 type ACL is optional.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for L3 API:
+*                        TPM_L2_PARSE_ETYPE|TPM_L2_PARSE_PPPOE_SES|TPM_L2_PARSE_PPP_PROT
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for L3 API:
+*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_TAG2_MASK|
+*                        TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+* l3_key             - Structure for PPPoE proto or ether type. In order to define a rule for
+*                      any ether type, the ether type value should be set to 0xFFFF
+* action_drop        - If this stage is dropping the packet.
+* pkt_frw            - Information for packet forwarding decision.
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      possible "next_phase" for L3 API   ->  STAGE_IPv4, STAGE_IPv6_GEN, STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number, which is used when deleting the rule.
+*                     (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_l3_type_rule(uint32_t owner_id,
+				      tpm_src_port_type_t src_port,
+				      uint32_t rule_num,
+				      uint32_t *rule_idx,
+				      tpm_parse_fields_t parse_rule_bm,
+				      tpm_parse_flags_t parse_flags_bm,
+				      tpm_l3_type_key_t *l3_key,
+				      tpm_pkt_frwd_t *pkt_frwd,
+				      tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_L3_TYPE, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_l3_type_acl_rule(owner_id, src_port, rule_num,
+						 rule_idx, parse_rule_bm, parse_flags_bm,
+						 l3_key, pkt_frwd, rule_action);
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_L3_TYPE, rule_num);
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_l3_type_rule);
+
+/*******************************************************************************
+* tpm_del_l2_rule()
+*
+* DESCRIPTION:      Deletes an existing L2 ACL primary rule.
+*                   Any of the existing access-list entries may be deleted. The src_port parameter
+*                   determines if the rule to be deleted belongs to the upstream access-list
+*                   or the downstream access-list. All parameters are compulsory. If the rule number
+*                   does not match the internally stored src_port and parsing key
+*                   (parse_rule_bm and l2_key), the API will return an error.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_l2_rule(uint32_t owner_id,
+				 uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_del_l2_prim_acl_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_l2_rule);
+
+/*******************************************************************************
+* tpm_del_l3_type_rule()
+*
+* DESCRIPTION:      Deletes an existing ethernet type or PPPoE proto access-list entry .
+*                   Any of the existing access-list entries may be deleted. The src_port parameter
+*                   determines if the rule to be deleted belongs to the upstream access-list
+*                   or the downstream access-list. All parameters are compulsory. If the rule number
+*                   does not match the internally stored src_port and parsing key
+*                   (parse_rule_bm and l3_key), the API will return an error.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_l3_type_rule(uint32_t owner_id,
+				      uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_del_l3_type_acl_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_l3_type_rule);
+
+/*******************************************************************************
+* tpm_add_ipv4_rule()
+*
+* DESCRIPTION:      Creates a new IPv4 processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for IPv4 API:
+*                        TPM_IPv4_PARSE_SIP|TPM_IPv4_PARSE_DIP|TPM_IPv4_PARSE_DSCP
+*                         |TPM_IPv4_PARSE_PROTO|TPM_PARSE_L4_SRC|TPM_PARSE_L4_DST
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for IPv4 API:
+*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+* ipv4_key           - Information to create an IPv4 parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* pkt_mod            - VLAN packet modification information.
+* pkt_mod_bm         - Bitmap containing the significant fields to modify (used for GWY only - in SFU is NULL)
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase.
+*                      possible "next_phase" for IPv4 API   ->  STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number, which is used when deleting the rule.
+*                     (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv4_rule(uint32_t owner_id,
+				   tpm_src_port_type_t src_port,
+				   uint32_t rule_num,
+				   uint32_t *rule_idx,
+				   tpm_parse_fields_t parse_rule_bm,
+				   tpm_parse_flags_t parse_flags_bm,
+				   tpm_ipv4_acl_key_t *ipv4_key,
+				   tpm_pkt_frwd_t *pkt_frwd,
+				   tpm_pkt_mod_t *pkt_mod,
+				   tpm_pkt_mod_bm_t pkt_mod_bm,
+				   tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV4, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+
+	ret_code = tpm_proc_add_ipv4_acl_rule(owner_id, src_port, rule_num, rule_idx, parse_rule_bm,
+					      parse_flags_bm, ipv4_key, pkt_frwd, pkt_mod, pkt_mod_bm, rule_action);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV4, rule_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv4_rule);
+
+/*******************************************************************************
+* tpm_del_ipv4_rule()
+*
+* DESCRIPTION:      Deletes an existing IPv4 ACL rule.
+*                   Both rule number and key are compulsory.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv4_rule(uint32_t owner_id,
+				   uint32_t rule_idx)
+{
+
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_del_ipv4_acl_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_del_ipv4_rule);
+
+/*******************************************************************************
+* tpm_add_ipv6_nh_rule()
+*
+* DESCRIPTION:      Creates a new IPv6 NH processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* rule_num           - Entry index to be added in the current ACL
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for IPv6 NH API:
+*                         TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+* nh                 - Information to create a NH parsing key for the rule.
+* pkt_frwd           - Information for packet forwarding decision.
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase (for GWY only).
+*                      possible "next_phase" for IPv6 NH API   ->  STAGE_IPV6_L4,STAGE_DONE
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number, which is used when deleting the rule.
+*                     (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_nh_rule(uint32_t owner_id,
+				      uint32_t rule_num,
+				      uint32_t *rule_idx,
+				      tpm_parse_flags_t parse_flags_bm,
+				      tpm_nh_iter_t nh_iter,
+				      uint32_t nh,
+				      tpm_pkt_frwd_t *pkt_frwd,
+				      tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_NH, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv6_nh_acl_rule(owner_id, rule_num, rule_idx, parse_flags_bm,
+						 nh_iter, nh, pkt_frwd, rule_action);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_NH, rule_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv6_nh_rule);
+
+/*******************************************************************************
+* tpm_del_ipv6_nh_rule()
+*
+* DESCRIPTION:      Deletes an existng IPv6 NH processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_nh_rule(uint32_t owner_id,
+				      uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_del_ipv6_nh_acl_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv6_nh_rule);
+
+/*******************************************************************************
+* tpm_add_ipv6_gen_rule()
+*
+* DESCRIPTION:      Creates a new IPv6 gen processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for IPv6 GEN API: 0
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for IPv6 GEN API:
+*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+* ipv6_gen_key     - Information to create an IPv6 gen parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase (for GWY only).
+*                      possible "next_phase" for IPv6 GEN API   ->  STAGE_IPv6_DIP, ,STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx          - Unique rule identification number, which is used when deleting the rule.
+*                      (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_gen_rule(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint32_t rule_num,
+					 uint32_t *rule_idx,
+					 tpm_parse_fields_t parse_rule_bm,
+					 tpm_parse_flags_t parse_flags_bm,
+					 tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					 tpm_pkt_frwd_t *pkt_frwd,
+					 tpm_pkt_mod_t *pkt_mod,
+					 tpm_pkt_mod_bm_t pkt_mod_bm,
+					 tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_GEN, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv6_gen_acl_rule(owner_id, src_port, rule_num, rule_idx, parse_rule_bm,
+						    parse_flags_bm, ipv6_gen_key, pkt_frwd, pkt_mod, pkt_mod_bm,
+						    rule_action);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_GEN, rule_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv6_gen_rule);
+
+/*******************************************************************************
+* tpm_del_ipv6_gen_rule()
+*
+* DESCRIPTION:      Deletes an existng IPv6 gen processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_gen_rule(uint32_t owner_id,
+					 uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+
+	if (ipv6_5t_enable != TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	ret_code = tpm_proc_del_ipv6_gen_acl_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv6_gen_rule);
+
+/*******************************************************************************
+* tpm_add_ipv6_dip_rule()
+*
+* DESCRIPTION:      Creates a new IPv6 DIP processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for IPv6 DIP API: TPM_IPv6_PARSE_DIP
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for IPv6 DIP API:
+*                        TPM_PARSE_FLAG_TAG1_MASK|TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+* ipv6_dip_key       - Information to create an IPv6 DIP parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* pkt_mod            - Packet modification information.
+* pkt_mod_bm         - Bitmap containing the significant fields to modify (used for GWY only - in SFU is NULL)
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase (for GWY only).
+*                      possible "next_phase" for IPv6 GEN API   ->  STAGE_IPv6_NHSTAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx          - Unique rule identification number, which is used when deleting the rule.
+*                      (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_dip_rule(uint32_t owner_id,
+				       tpm_src_port_type_t src_port,
+				       uint32_t rule_num,
+				       uint32_t *rule_idx,
+				       tpm_parse_fields_t parse_rule_bm,
+				       tpm_parse_flags_t parse_flags_bm,
+				       tpm_ipv6_addr_key_t *ipv6_dip_key,
+				       tpm_pkt_frwd_t *pkt_frwd,
+				       tpm_pkt_mod_t *pkt_mod,
+				       tpm_pkt_mod_bm_t pkt_mod_bm,
+				       tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_DIP, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv6_dip_acl_rule(owner_id, src_port, rule_num, rule_idx, parse_rule_bm,
+						parse_flags_bm, ipv6_dip_key, pkt_frwd, pkt_mod, pkt_mod_bm,
+						rule_action);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_DIP, rule_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv6_dip_rule);
+
+/*******************************************************************************
+* tpm_del_ipv6_dip_rule()
+*
+* DESCRIPTION:      Deletes an existng IPv6 DIP processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_dip_rule(uint32_t owner_id,
+				       uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+
+	if (ipv6_5t_enable != TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	ret_code = tpm_proc_del_ipv6_dip_acl_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv6_dip_rule);
+
+/*******************************************************************************
+* tpm_add_ipv6_l4_ports_rule()
+*
+* DESCRIPTION:      Creates a new IPv6 L4 processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for L4 API: TPM_PARSE_L4_SRC|TPM_PARSE_L4_DST
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for L4 API:
+*                         TPM_PARSE_FLAG_MTM_MASK|TPM_PARSE_FLAG_TO_CPU_MASK
+* l4_key             - Information to create an L4 parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* pkt_mod            - Packet modification information.
+* pkt_mod_bm         - Bitmap containing the significant fields to modify (used for GWY only - in SFU is NULL)
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase (for GWY only).
+*                      possible "next_phase" for L4 API   ->  STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx          - Unique rule identification number, which is used when deleting the rule.
+*                      (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_l4_ports_rule(uint32_t owner_id,
+					    tpm_src_port_type_t src_port,
+					    uint32_t rule_num,
+					    uint32_t *rule_idx,
+					    tpm_parse_fields_t parse_rule_bm,
+					    tpm_parse_flags_t parse_flags_bm,
+					    tpm_l4_ports_key_t *l4_key,
+					    tpm_pkt_frwd_t *pkt_frwd,
+					    tpm_pkt_mod_t *pkt_mod,
+					    tpm_pkt_mod_bm_t pkt_mod_bm,
+					    tpm_rule_action_t *rule_action)
+{
+
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_L4, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv6_l4_ports_acl_rule(owner_id, src_port, rule_num, rule_idx, parse_rule_bm,
+							parse_flags_bm, l4_key, pkt_frwd, pkt_mod, pkt_mod_bm,
+							rule_action);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_L4, rule_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv6_l4_ports_rule);
+
+/*******************************************************************************
+* tpm_del_ipv6_l4_ports_rule()
+*
+* DESCRIPTION:      Deletes an existng L4 processing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_l4_ports_rule(uint32_t owner_id,
+					    uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+
+	if (ipv6_5t_enable != TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	ret_code = tpm_proc_del_ipv6_l4_ports_acl_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv6_l4_ports_rule);
+
+
+tpm_error_code_t tpm_add_ipv6_gen_5t_rule(uint32_t owner_id,
+					  tpm_dir_t src_dir,
+					  uint32_t rule_num,
+					  uint32_t *rule_idx,
+					  tpm_parse_fields_t parse_rule_bm,
+					  tpm_parse_flags_t parse_flags_bm,
+					  tpm_l4_ports_key_t *l4_key,
+					  tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					  tpm_pkt_frwd_t *pkt_frwd,
+					  tpm_pkt_mod_t *pkt_mod,
+					  tpm_pkt_mod_bm_t pkt_mod_bm,
+					  tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_GEN, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+
+	ret_code = tpm_proc_add_ipv6_gen_5t_rule(owner_id, src_dir, rule_num, rule_idx, parse_rule_bm, parse_flags_bm,
+						l4_key, ipv6_gen_key, pkt_frwd, pkt_mod, pkt_mod_bm, rule_action);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_GEN, rule_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv6_gen_5t_rule);
+
+tpm_error_code_t tpm_del_ipv6_gen_5t_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	ret_code = tpm_proc_del_ipv6_gen_5t_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv6_gen_5t_rule);
+
+tpm_error_code_t tpm_add_ipv6_dip_5t_rule(uint32_t owner_id,
+					  tpm_dir_t src_dir,
+					  uint32_t rule_num,
+					  uint32_t *rule_idx,
+					  tpm_parse_fields_t parse_rule_bm,
+					  tpm_parse_flags_t parse_flags_bm,
+					  tpm_l4_ports_key_t *l4_key,
+					  tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					  tpm_ipv6_addr_key_t *ipv6_dip_key,
+					  tpm_pkt_frwd_t *pkt_frwd,
+					  tpm_pkt_mod_t *pkt_mod,
+					  tpm_pkt_mod_bm_t pkt_mod_bm,
+					  tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_DIP, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv6_dip_5t_rule(owner_id, src_dir, rule_num, rule_idx, parse_rule_bm, parse_flags_bm,
+										l4_key, ipv6_gen_key, ipv6_dip_key, pkt_frwd, pkt_mod, pkt_mod_bm, rule_action);
+
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_DIP, rule_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv6_dip_5t_rule);
+
+tpm_error_code_t tpm_del_ipv6_dip_5t_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	ret_code = tpm_proc_del_ipv6_dip_5t_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv6_dip_5t_rule);
+
+tpm_error_code_t tpm_add_ipv6_l4_ports_5t_rule(uint32_t owner_id,
+					       tpm_dir_t src_dir,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l4_ports_key_t *l4_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_pkt_mod_t *pkt_mod,
+					       tpm_pkt_mod_bm_t pkt_mod_bm,
+					       tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_L4, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv6_l4_ports_5t_rule(owner_id, src_dir, rule_num, rule_idx, parse_rule_bm, parse_flags_bm,
+						      l4_key, pkt_frwd, pkt_mod, pkt_mod_bm, rule_action);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_L4, rule_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv6_l4_ports_5t_rule);
+
+tpm_error_code_t tpm_del_ipv6_l4_ports_5t_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	ret_code = tpm_proc_del_ipv6_l4_ports_5t_rule(owner_id, rule_idx, TPM_EXT_CALL);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv6_l4_ports_5t_rule);
+
+
+/******************************************************************************/
+/********************************** MC handling APIs **************************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_add_ipv4_mc_stream()
+*
+* DESCRIPTION:      Creates a new IPv4 MC stream.
+*                   It is APIs caller responsibility to maintain the correct number of
+*                   each stream number.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* vid                - VLAN ID (0-4095). If set to 4096 - stream is untagged.
+*                      If set to 0xFFFF - do not care.
+* ipv4_src_add       - IPv4 source IP address in network order.
+* ipv4_src_add       - IPv4 destination IP address in network order.
+* ignore_ipv4_src    - when set to 1 - the IP source is not part of the key.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv4_mc_stream(uint32_t owner_id,
+					uint32_t stream_num,
+					tpm_mc_igmp_mode_t igmp_mode,
+					uint8_t mc_stream_pppoe,
+					uint16_t vid,
+					uint8_t ipv4_src_add[4],
+					uint8_t ipv4_dst_add[4],
+					uint8_t ignore_ipv4_src,
+					tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV4_MC, stream_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv4_mc_stream(owner_id, stream_num, igmp_mode, mc_stream_pppoe,
+						vid, ipv4_src_add, ipv4_dst_add, ignore_ipv4_src, dest_port_bm);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV4_MC, stream_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ipv4_mc_stream);
+
+/*******************************************************************************
+* tpm_updt_ipv4_mc_stream()
+*
+* DESCRIPTION:      Updates an existing IPv4 MC stream.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_updt_ipv4_mc_stream(uint32_t owner_id,
+					 uint32_t stream_num,
+					 tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV4_MC, stream_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_updt_ipv4_mc_stream(owner_id, stream_num, dest_port_bm);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV4_MC, stream_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_updt_ipv4_mc_stream);
+
+/*******************************************************************************
+* tpm_del_ipv4_mc_stream()
+*
+* DESCRIPTION:      Deletes an existing IPv4 MC stream.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv4_mc_stream(uint32_t owner_id,
+					uint32_t stream_num)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_del_ipv4_mc_stream(owner_id, stream_num);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv4_mc_stream);
+
+/*******************************************************************************
+* tpm_add_ipv6_mc_stream()
+*
+* DESCRIPTION:      Creates a new ipv6 MC stream.
+*                   It is APIs caller responsibility to maintain the correct number of
+*                   each stream number.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* vid                - VLAN ID (0-4095). If set to 4096 - stream is untagged.
+*                      If set to 0xFFFF - do not care.
+* ipv6_src_add       - ipv6 source IP address in network order.
+* ipv6_dst_add       - ipv6 destination IP address in network order.
+* ignore_ipv6_src    - when set to 1 - the IP source is not part of the key.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_mc_stream(uint32_t owner_id,
+					uint32_t stream_num,
+					tpm_mc_igmp_mode_t igmp_mode,
+					uint8_t mc_stream_pppoe,
+					uint16_t vid,
+					uint8_t ipv6_src_add[16],
+					uint8_t ipv6_dst_add[16],
+					uint8_t ignore_ipv6_src,
+					tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_MC, stream_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_ipv6_mc_stream(owner_id, stream_num, igmp_mode, mc_stream_pppoe,
+						vid, ipv6_src_add, ipv6_dst_add, ignore_ipv6_src, dest_port_bm);
+
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_MC, stream_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+
+}
+EXPORT_SYMBOL(tpm_add_ipv6_mc_stream);
+
+/*******************************************************************************
+* tpm_updt_ipv6_mc_stream()
+*
+* DESCRIPTION:      Updates an existing ipv6 MC stream.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_updt_ipv6_mc_stream(uint32_t owner_id,
+					 uint32_t stream_num,
+					 tpm_trg_port_type_t dest_port_bm)
+{	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_type Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_IPV6_MC, stream_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_updt_ipv6_mc_stream(owner_id, stream_num, dest_port_bm);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_IPV6_MC, stream_num);
+
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_updt_ipv6_mc_stream);
+
+/*******************************************************************************
+* tpm_del_ipv6_mc_stream()
+*
+* DESCRIPTION:      Deletes an existing ipv6 MC stream.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_mc_stream(uint32_t owner_id,
+					uint32_t stream_num)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_del_ipv6_mc_stream(owner_id, stream_num);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ipv6_mc_stream);
+
+/******************************************************************************/
+/********************************** Management protocol APIs ******************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_omci_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the OMCI management protocol.
+*                   The API sets the gemportid, the Rx input queue in the CPU, and the
+*                   Tx T-CONT and queue parameters, which are configured in the driver.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* gem_port           - for OMCI Rx frames - the gem port wherefrom the OMCI frames are received.
+* cpu_rx_queue       - for OMCI Rx frames - the CPU rx queue number.
+* tcont_num          - for OMCI Tx frames - the TCONT number where to send the OMCI frames.
+* cpu_tx_queue       - for OMCI Tx frames - the CPU tx queue number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_omci_add_channel(uint32_t owner_id,
+				      tpm_gem_port_key_t gem_port,
+				      uint32_t cpu_rx_queue,
+				      tpm_trg_port_type_t tcont_num,
+				      uint32_t cpu_tx_queue)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_omci_add_channel(owner_id, gem_port, cpu_rx_queue, tcont_num, cpu_tx_queue);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_omci_add_channel);
+
+/*******************************************************************************
+* tpm_omci_del_channel()
+*
+* DESCRIPTION:      Deletes an existing communication channel for the OMCI management protocol.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_omci_del_channel(uint32_t owner_id)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_omci_del_channel(owner_id);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_omci_del_channel);
+
+/*******************************************************************************
+* tpm_oam_epon_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the OAM EPON management protocol.
+*                   The API sets the Rx input queue in the CPU, and the
+*                   Tx T-CONT and queue parameters, which are configured in the driver.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* cpu_rx_queue       - for OAM (EPON) Rx frames - the CPU rx queue number.
+* llid_num           - for OAM (EPON)Tx frames - the LLID number where to send the OMCI frames.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_epon_add_channel(uint32_t owner_id,
+					  uint32_t cpu_rx_queue,
+					  tpm_trg_port_type_t llid_num)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_oam_epon_add_channel(owner_id, cpu_rx_queue, llid_num);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_oam_epon_add_channel);
+
+/*******************************************************************************
+* tpm_loop_detect_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for loop detection management protocol.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_loop_detect_add_channel(uint32_t owner_id)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_loop_detect_add_channel(owner_id);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_loop_detect_add_channel);
+
+/*******************************************************************************
+* tpm_oam_loopback_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the OAM remote loopback.
+*
+*
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_loopback_add_channel(uint32_t owner_id)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_oam_loopback_add_channel(owner_id);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_oam_loopback_add_channel);
+
+/*******************************************************************************
+* tpm_oam_loopback_del_channel()
+*
+* DESCRIPTION:      Del a communication channel for the OAM remote loopback .
+*
+*
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_loopback_del_channel(uint32_t owner_id)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_oam_loopback_del_channel(owner_id);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_oam_loopback_del_channel);
+
+/*******************************************************************************
+* tpm_oam_epon_del_channel()
+*
+* DESCRIPTION:      Deletes an existing communication channel for the OAM EPON management protocol.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_epon_del_channel(uint32_t owner_id)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_oam_epon_del_channel(owner_id);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_oam_epon_del_channel);
+
+/*******************************************************************************
+* tpm_get_next_valid_rule()
+*
+* DESCRIPTION:      General purpose API to retrieve the internal configuration of an existing ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* direction          - direction - UpStream or DownStream - TPM_DOWNSTREAM = 0 and TPM_UPSTREAM = 1.
+* current_index      - the entry index in the section (rule_num/stream_num).
+*                      In case it is (-1) - the get next function will point to the first ruleof the section.
+* rule_type          - type of the rule to retrieve - indicates the api group where to point.
+*
+* OUTPUTS:
+* next_index         - returns the first following index (rule_num/stream_num) after the index in
+*                      the current_index parameter. It is invalid, if there is no next_index.
+* rule_idx           - Unique rule identification number. Equals to stream_num for functions that take a stream_num.
+* tpm_rule           - points to a structure holding the information of a single rule,
+*                      of the type specified in the rule_type param.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_next_valid_rule(uint32_t owner_id,
+					 int32_t current_index,
+					 tpm_api_type_t rule_type,
+					 int32_t *next_index,
+					 uint32_t *rule_idx,
+					 tpm_rule_entry_t *tpm_rule)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_get_next_valid_rule(owner_id, current_index, rule_type, next_index, rule_idx, tpm_rule);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_get_next_valid_rule);
+
+/******************************************************************************/
+/********************************** Configuration retrieval APIs **************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_omci_get_channel()
+*
+* DESCRIPTION:      Retrieves the OMCI management protocol channel information.
+*
+* INPUTS:
+*  None.
+*
+* OUTPUTS:
+* is_valid           - indicates that the OMCI channel is valid or not.
+* gem_port           - for OMCI Rx frames - the gem port wherefrom the OMCI frames are received.
+* cpu_rx_queue       - for OMCI Rx frames - the CPU rx queue number.
+* tcont_num          - for OMCI Tx frames - the TCONT number where to send the OMCI frames.
+* cpu_tx_queue       - for OMCI Tx frames - the CPU tx queue number.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_omci_get_channel(uint32_t *is_valid,
+				      tpm_gem_port_key_t *gem_port,
+				      uint32_t *cpu_rx_queue,
+				      tpm_trg_port_type_t *tcont_num,
+				      uint32_t *cpu_tx_queue)
+{
+	if (!is_valid || !gem_port || !cpu_rx_queue || !tcont_num || !cpu_tx_queue)
+		return ERR_NULL_POINTER;
+
+	tpm_db_omci_channel_get(is_valid, gem_port, cpu_rx_queue, cpu_tx_queue, tcont_num);
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_omci_get_channel);
+
+/*******************************************************************************
+* tpm_set_port_igmp_frwd_mode()
+*
+* DESCRIPTION:      Set the IGMP status of a UNI port or WAN port.
+*
+* INPUTS:
+* src_port          - source port to set
+* state             - how to process IGMP packets
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_port_igmp_frwd_mode(tpm_src_port_type_t src_port,
+					     tpm_igmp_frwd_mode_t mode)
+{
+	tpm_error_code_t ret_code = TPM_RC_OK;
+	tpm_igmp_frwd_mode_t _mode;
+
+	tpm_db_igmp_get_port_frwd_mode(src_port, &_mode);
+
+	if (_mode != mode) {
+		if (TPM_SRC_PORT_WAN == src_port)
+			ret_code = tpm_proc_add_wan_port_igmp_rule(mode);
+		else
+			ret_code = tpm_proc_add_uni_port_igmp_rule(src_port, mode);
+
+		tpm_db_igmp_set_port_frwd_mode(src_port, mode);
+	}
+
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_set_port_igmp_frwd_mode);
+
+/*******************************************************************************
+* tpm_get_port_igmp_frwd_mode()
+*
+* DESCRIPTION:      Get the IGMP status of a UNI port or WAN port.
+*
+* INPUTS:
+* src_port          - source port to get
+*
+* OUTPUTS:
+* state             - how to process IGMP packets
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_port_igmp_frwd_mode(tpm_src_port_type_t src_port,
+					     tpm_igmp_frwd_mode_t *mode)
+{
+	if (!mode)
+		return ERR_NULL_POINTER;
+
+	tpm_db_igmp_get_port_frwd_mode(src_port, mode);
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_get_port_igmp_frwd_mode);
+
+/*******************************************************************************
+* tpm_set_igmp_cpu_rx_queue()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to.
+*
+* INPUTS:
+* queue             - queue number
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_igmp_cpu_rx_queue(uint32_t queue)
+{
+	tpm_error_code_t ret_code = TPM_RC_OK;
+	uint32_t _queue;
+	tpm_igmp_frwd_mode_t _mode;
+	tpm_src_port_type_t src_port;
+
+	tpm_db_igmp_get_cpu_queue(&_queue);
+
+	if (_queue != queue) {
+		tpm_db_igmp_set_cpu_queue(queue);
+
+		for (src_port = TPM_SRC_PORT_UNI_0; src_port <= TPM_SRC_PORT_WAN; src_port++) {
+
+			/* virt uni do not need to add PNC entry for IGMP */
+			if (  (src_port == TPM_SRC_PORT_UNI_VIRT)
+				|| (tpm_db_eth_port_switch_port_get(src_port) == TPM_DB_ERR_PORT_NUM)){
+				TPM_OS_INFO(TPM_TPM_LOG_MOD, " src_port %d\n", src_port);
+				continue;
+			}
+			tpm_db_igmp_get_port_frwd_mode(src_port, &_mode);
+
+			if (TPM_IGMP_FRWD_MODE_SNOOPING == _mode) {
+
+				if (TPM_SRC_PORT_WAN == src_port)
+					ret_code |= tpm_proc_add_wan_port_igmp_rule(_mode);
+				else
+					ret_code |= tpm_proc_add_uni_port_igmp_rule(src_port, _mode);
+			}
+		}
+	}
+
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_set_igmp_cpu_rx_queue);
+
+/*******************************************************************************
+* tpm_get_igmp_cpu_rx_queue()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to.
+*
+* INPUTS:
+* queue             - queue number
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_igmp_cpu_rx_queue(uint32_t *queue)
+{
+	if (!queue)
+		return ERR_NULL_POINTER;
+
+	tpm_db_igmp_get_cpu_queue(queue);
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_get_igmp_cpu_rx_queue);
+
+/*******************************************************************************
+* tpm_set_igmp_proxy_sa_mac()
+*
+* DESCRIPTION:      Set source mac address replaced for igmp proxy.
+*
+* INPUTS:
+* sa_mac          - source mac
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_igmp_proxy_sa_mac(uint8_t *sa_mac)
+{
+	tpm_db_set_mc_igmp_proxy_sa_mac(sa_mac);
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_set_igmp_proxy_sa_mac);
+
+/*******************************************************************************
+* tpm_get_igmp_proxy_sa_mac()
+*
+* DESCRIPTION:      Get source mac address replaced for igmp proxy.
+*
+* INPUTS:
+* sa_mac          - source mac
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_igmp_proxy_sa_mac(uint8_t *sa_mac)
+{
+	uint8_t mac[6], mac_valid;
+
+	tpm_db_get_mc_igmp_proxy_sa_mac(mac, &mac_valid);
+	if (mac_valid)
+		memcpy(sa_mac, mac, 6 * sizeof(uint8_t));
+	else
+		return ERR_GENERAL;
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_get_igmp_proxy_sa_mac);
+
+/*******************************************************************************
+* tpm_oam_epon_get_channel()
+*
+* DESCRIPTION:      Retrieves OAM EPON management protocol channel information.
+*
+* INPUTS:
+*  None.
+*
+* OUTPUTS:
+* is_valid           -  indicates that the OMCI channel is valid or not.
+* cpu_rx_queue       - for OAM (EPON) Rx frames - the CPU rx queue number.
+* llid_num           - for OAM (EPON)Tx frames - the LLID number where to send the OMCI frames.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_epon_get_channel(uint32_t *is_valid,
+					  uint32_t *cpu_rx_queue,
+					  tpm_trg_port_type_t *llid_num)
+{
+	uint32_t dummy_cpu_tx_queue;
+
+	if (!is_valid || !cpu_rx_queue || !llid_num)
+		return ERR_NULL_POINTER;
+
+	tpm_db_oam_channel_get(is_valid, cpu_rx_queue, &dummy_cpu_tx_queue, llid_num);
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_oam_epon_get_channel);
+
+/*******************************************************************************
+* tpm_get_api_ownership()
+*
+* DESCRIPTION:      Retrieves OAM EPON management protocol channel information.
+*
+* INPUTS:
+* api_type          - Specifies the API group whom owner_id is requested.
+*
+* OUTPUTS:
+* owner_id           - specifies the ownerId of the application group
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS.
+* On error:     API_TYPE_UNKNOWN  when illegal API group
+*               API_OWNERSHIP_ERROR  other errors.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_api_ownership_error_t tpm_get_api_ownership(uint32_t *owner_id,
+						tpm_api_type_t api_type)
+{
+	printk(KERN_WARNING "\n  <<tpm_oam_epon_get_channel>> NOT implemented. \n");
+	owner_id = 0;
+	return API_OWNERSHIP_SUCCESS;
+}
+EXPORT_SYMBOL(tpm_get_api_ownership);
+
+/******************************************************************************/
+/************************** Packet modification APIs **************************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_mod_entry_set()
+*
+* DESCRIPTION: The API sets a complete Modification table entry
+*
+* INPUTS:   trg_port    - target port
+*           mod_bm      - set of flags described which fields in the packet
+*                         to be changed
+*           int_mod_bm  - set of internal flags
+*           mod_data    - modification entry data
+*
+* OUTPUTS:
+*           mod_entry   - start entry number which has been set for this
+*                         modification
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mod_entry_set(tpm_trg_port_type_t trg_port,
+				   tpm_pkt_mod_bm_t mod_bm,
+				   tpm_pkt_mod_int_bm_t int_mod_bm,
+				   tpm_pkt_mod_t *mod_data,
+				   uint32_t *mod_entry)
+{
+	tpm_error_code_t rc = TPM_RC_OK;
+	tpm_gmacs_enum_t gmac_port;
+
+	/*printk("tpm_mod_entry_set: trg_port = %d\n", trg_port); */
+
+	tpm_proc_trg_port_gmac_map(trg_port, &gmac_port);
+	if (gmac_port == TPM_INVALID_GMAC) {
+		printk(KERN_ERR "ERROR: PKT modification not possible on this target port(%d) \n", trg_port);
+		rc = ERR_ACTION_INVALID;
+	} else
+		rc = tpm_mod2_entry_set(TPM_MOD_OWNER_CPU, gmac_port, mod_bm, int_mod_bm, mod_data, mod_entry);
+
+	return rc;
+}
+EXPORT_SYMBOL(tpm_mod_entry_set);
+
+/*******************************************************************************
+* tpm_mod_entry_get()
+*
+* DESCRIPTION: The API gets Modification table entries
+*
+* INPUTS:   trg_port    - target port
+*           mod_entry   - start entry number (in the "jump" area)
+*
+* OUTPUTS:
+*           valid_cmds  - number of valid commands in the chunk
+*                             0 - there is no requested data
+*           pnc_ref     - Number of references from Pnc entries to this modification rule
+*           rule        - modification rule (set of modification entries)
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mod_entry_get(tpm_trg_port_type_t trg_port,
+				   uint32_t mod_entry,
+				   uint16_t *valid_cmds,
+				   uint16_t *pnc_ref,
+				   tpm_mod_rule_t *rule)
+{
+	tpm_gmacs_enum_t gmac_port;
+	tpm_error_code_t rc = TPM_RC_OK;
+
+	/*printk("tpm_mod_entry_get: trg_port = %d mod_entry = %d\n", trg_port, mod_entry); */
+
+	tpm_proc_trg_port_gmac_map(trg_port, &gmac_port);
+	if (gmac_port == TPM_INVALID_GMAC) {
+		printk(KERN_ERR "ERROR: PKT modification not possible on this target port(%d) \n", trg_port);
+		rc = ERR_ACTION_INVALID;
+	} else {
+		*pnc_ref = 0;
+
+		if (tpm_mod2_entry_get(gmac_port, mod_entry, valid_cmds, rule) != TPM_OK)
+			rc = ERR_GENERAL;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(tpm_mod_entry_get);
+
+/*******************************************************************************
+* tpm_mod_entry_del()
+*
+* DESCRIPTION: The API invalidates a modification entry chunk
+*
+* INPUTS:   trg_port    - target port
+*           mod_entry   - start entry number (in the "jump" area)
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mod_entry_del(tpm_trg_port_type_t trg_port,
+				   uint32_t mod_entry)
+{
+	tpm_error_code_t rc = TPM_RC_OK;
+	tpm_gmacs_enum_t gmac_port;
+
+	/*printk("tpm_mod_entry_del: trg_port = %d mod_entry = %d\n", trg_port, mod_entry); */
+
+	tpm_proc_trg_port_gmac_map(trg_port, &gmac_port);
+	if (gmac_port == TPM_INVALID_GMAC) {
+		printk(KERN_ERR "ERROR: PKT modification not possible on this target port(%d) \n", trg_port);
+		rc = ERR_ACTION_INVALID;
+	} else
+		rc = tpm_mod2_entry_del(TPM_MOD_OWNER_CPU, gmac_port, mod_entry);
+
+	return rc;
+}
+EXPORT_SYMBOL(tpm_mod_entry_del);
+
+/*******************************************************************************
+* tpm_mod_mac_inv()
+*
+* DESCRIPTION: The API resets Modification table for a specified port
+*
+* INPUTS:   trg_port    - target port
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mod_mac_inv(tpm_trg_port_type_t trg_port)
+{
+	tpm_error_code_t rc = TPM_RC_OK;
+	tpm_gmacs_enum_t gmac_port;
+
+	/*printk("tpm_mod_mac_inv: trg_port = %d\n", trg_port); */
+
+	tpm_proc_trg_port_gmac_map(trg_port, &gmac_port);
+	if (gmac_port == TPM_INVALID_GMAC) {
+		printk(KERN_ERR "ERROR: PKT modification not possible on this target port(%d) \n", trg_port);
+		rc = ERR_ACTION_INVALID;
+	} else {
+		if (tpm_db_mod2_inv_mac_entries(gmac_port) != TPM_OK) {
+			TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to reset database (%d) \n", gmac_port);
+			rc = TPM_FAIL;
+		}
+
+		if (tpm_mod2_mac_inv(gmac_port) != TPM_OK) {
+			TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to reset hardware (%d) \n", gmac_port);
+			rc = TPM_FAIL;
+		}
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(tpm_mod_mac_inv);
+
+/*******************************************************************************
+* tpm_rx_igmp_frame()
+*
+* DESCRIPTION: The API rx IGMP frames from either LAN or WAN side,
+*              it will be blocked until a packet arrived.
+*
+* INPUTS:   owner_id    - owner id
+*           buf         - Message buffer allocated by user
+*           len         - Max len of this buffer
+*
+* OUTPUTS:
+*           llid        - source LLID index in case this frame comes from WAN side
+*           src_port    - source UNI port in case this frame comes from LAN side
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_rx_igmp_frame(uint32_t owner_id,
+				   uint16_t *llid,
+				   tpm_src_port_type_t *src_port,
+				   uint8_t *buf,
+				   uint32_t *len)
+{
+	static struct socket *sock = NULL;
+	struct msghdr msg;
+	struct iovec iov;
+	int32_t length, error;
+	mm_segment_t oldfs;
+	static uint8_t temp_buf[MAX_FRAME_SIZE];
+
+	if (NULL == sock) {
+		/* First create a socket */
+		error = sock_create(AF_PACKET, SOCK_RAW, htons(0xa000), &sock);
+		if (error < 0) {
+			printk(KERN_ERR "%s: sock_create(AF_PACKET, SOCK_RAW, htons(0xbaba)) failed. errno = %d\n",
+			       __func__, error);
+			return ERR_GENERAL;
+		}
+	}
+
+	/* Set the msghdr structure */
+	msg.msg_name = 0;
+	msg.msg_namelen = 0;
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags = 0;
+
+	/* Set the iovec structure */
+	iov.iov_base = (void *)&temp_buf[0];
+	iov.iov_len = (size_t) MAX_FRAME_SIZE;
+
+	/* Recieve the message */
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	length = sock_recvmsg(sock, &msg, MAX_FRAME_SIZE, msg.msg_flags);
+	set_fs(oldfs);
+
+	if (length <= 2)
+		return ERR_GENERAL;
+	else {
+		*len = length - 2;
+
+		/* Set by MV_CUST_EXT IGMP RX */
+		if (2 == temp_buf[0]) {
+			*llid = (temp_buf[1] & 0x0F) - 1;
+			*src_port = TPM_SRC_PORT_WAN;
+		} else
+			*src_port = tpm_db_phy_convert_port_index(temp_buf[1]);
+			/* How to support GMAC1? */
+
+		memcpy(buf, &(temp_buf[2]), length - 2);
+	}
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_rx_igmp_frame);
+
+/*******************************************************************************
+* tpm_tx_igmp_frame()
+*
+* DESCRIPTION: The API tx IGMP frames to either LAN or WAN side
+*
+* INPUTS:   owner_id    - owner id
+*           tgt_port    - target port, LLID0-7/TCONT0-7/UNI0-3
+*           tgt_queue   - target queue, 0-7
+*           gem_port    - target gem port ID
+*           buf         - Message buffer allocated by user
+*           len         - Len of this buffer
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tx_igmp_frame(uint32_t owner_id,
+				   tpm_trg_port_type_t tgt_port,
+				   uint8_t tgt_queue,
+				   uint16_t gem_port,
+				   uint8_t *buf,
+				   uint32_t len)
+{
+	static struct socket *sock = NULL;
+	struct msghdr msg;
+	struct iovec iov;
+	int32_t length, error;
+	mm_segment_t oldfs;
+	static uint8_t temp_buf[MAX_FRAME_SIZE];
+
+	if (NULL == sock) {
+		/* First create a socket */
+		error = sock_create(AF_PACKET, SOCK_RAW, htons(0xa000), &sock);
+		if (error < 0) {
+			printk(KERN_ERR "%s: sock_create(AF_PACKET, SOCK_RAW, htons(0xbaba)) failed. errno = %d\n",
+			       __func__, error);
+			return ERR_GENERAL;
+		}
+	}
+
+	/* Set the msghdr structure */
+	msg.msg_name = 0;
+	msg.msg_namelen = 0;
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = NULL;
+	msg.msg_controllen = 0;
+	msg.msg_flags = 0;
+
+	/* Set the iovec structure */
+	iov.iov_base = (void *)&temp_buf[0];
+	iov.iov_len = (size_t) (len + 4);
+
+	memcpy(&temp_buf[4], buf, len);
+	/* BYTE 0 to 3 will be used by MV_CUST_EXT */
+	temp_buf[0] = tgt_port;
+	temp_buf[1] = tgt_queue;
+	temp_buf[2] = (gem_port & 0xff00) >> 8;
+	temp_buf[3] = gem_port & 0xff;
+
+	if ((tgt_port & TPM_TRG_TCONT_0) || (tgt_port & TPM_TRG_TCONT_1) ||
+	    (tgt_port & TPM_TRG_TCONT_2) || (tgt_port & TPM_TRG_TCONT_3) ||
+	    (tgt_port & TPM_TRG_TCONT_4) || (tgt_port & TPM_TRG_TCONT_5) ||
+	    (tgt_port & TPM_TRG_TCONT_6) || (tgt_port & TPM_TRG_TCONT_7)) {
+		struct net_device *dev = NULL;
+		struct sockaddr sockAddr;
+		struct sockaddr_ll *sockAddr_ll = (struct sockaddr_ll *)&sockAddr;
+
+		/*strcpy(ifReq.ifr_name, "pon0"); */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+		dev = dev_get_by_name("pon0");
+#else
+		dev = dev_get_by_name(sock_net(sock->sk), "pon0");
+#endif
+		if (dev == NULL) {
+			printk(KERN_ERR "%s: pon0 interface not found \n", __func__);
+			return ERR_GENERAL;
+		}
+		sockAddr_ll->sll_ifindex = dev->ifindex;
+		sockAddr_ll->sll_family = AF_PACKET;
+		sockAddr_ll->sll_protocol = htons(0xa000);
+
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		if (sock->ops->bind(sock, &sockAddr, sizeof(struct sockaddr_ll)) < 0) {
+			set_fs(oldfs);
+			printk(KERN_ERR "%s: sock->ops->ioctl(sock,SIOCGIFINDEX,&ifReq) failed.\n", __func__);
+			return ERR_GENERAL;
+		}
+		set_fs(oldfs);
+
+		if (tgt_port & TPM_TRG_TCONT_0) {
+			temp_buf[0] = 0;
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+			length = sock_sendmsg(sock, &msg, len + 4);
+			set_fs(oldfs);
+		}
+		if (tgt_port & TPM_TRG_TCONT_1) {
+			temp_buf[0] = 1;
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+			length = sock_sendmsg(sock, &msg, len + 4);
+			set_fs(oldfs);
+		}
+		if (tgt_port & TPM_TRG_TCONT_2) {
+			temp_buf[0] = 2;
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+			length = sock_sendmsg(sock, &msg, len + 4);
+			set_fs(oldfs);
+		}
+		if (tgt_port & TPM_TRG_TCONT_3) {
+			temp_buf[0] = 3;
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+			length = sock_sendmsg(sock, &msg, len + 4);
+			set_fs(oldfs);
+		}
+		if (tgt_port & TPM_TRG_TCONT_4) {
+			temp_buf[0] = 4;
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+			length = sock_sendmsg(sock, &msg, len + 4);
+			set_fs(oldfs);
+		}
+		if (tgt_port & TPM_TRG_TCONT_5) {
+			temp_buf[0] = 5;
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+			length = sock_sendmsg(sock, &msg, len + 4);
+			set_fs(oldfs);
+		}
+		if (tgt_port & TPM_TRG_TCONT_6) {
+			temp_buf[0] = 6;
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+			length = sock_sendmsg(sock, &msg, len + 4);
+			set_fs(oldfs);
+		}
+		if (tgt_port & TPM_TRG_TCONT_7) {
+			temp_buf[0] = 7;
+			oldfs = get_fs();
+			set_fs(KERNEL_DS);
+			length = sock_sendmsg(sock, &msg, len + 4);
+			set_fs(oldfs);
+		}
+	} else {
+		struct net_device *dev = NULL;
+		struct sockaddr sockAddr;
+		struct sockaddr_ll *sockAddr_ll = (struct sockaddr_ll *)&sockAddr;
+
+		/*strcpy(ifReq.ifr_name, "pon0"); */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+		dev = dev_get_by_name("eth0");
+#else
+		dev = dev_get_by_name(sock_net(sock->sk), "eth0");
+#endif
+		if (dev == NULL) {
+			printk(KERN_ERR "%s: eth0 interface not found \n", __func__);
+			return ERR_GENERAL;
+		}
+		sockAddr_ll->sll_ifindex = dev->ifindex;
+		sockAddr_ll->sll_family = AF_PACKET;
+		sockAddr_ll->sll_protocol = htons(0xa000);
+
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		if (sock->ops->bind(sock, &sockAddr, sizeof(struct sockaddr_ll)) < 0) {
+			set_fs(oldfs);
+			printk(KERN_ERR "%s: sock->ops->ioctl(sock,SIOCGIFINDEX,&ifReq) failed.\n", __func__);
+			return ERR_GENERAL;
+		}
+		set_fs(oldfs);
+
+		/* Always go to queue 7 */
+		temp_buf[1] = 7;
+		if (TPM_TRG_PORT_UNI_ANY & tgt_port)
+			temp_buf[3] = 0;
+		else
+			temp_buf[3] = tpm_db_trg_port_switch_port_get(tgt_port);
+
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		length = sock_sendmsg(sock, &msg, len + 4);
+		set_fs(oldfs);
+
+		/* How to support GMAC1? */
+	}
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_tx_igmp_frame);
+
+/*******************************************************************************
+* tpm_add_cpu_wan_loopback()
+*
+* DESCRIPTION: The API add CPU egress loopback modification and PnC rules for
+*              specific Tcont/queue/gem_port
+*
+* INPUTS:   owner_id    - APP owner id  should be used for all API calls.
+*           pkt_frwd    - packet forwarding info: target tcont/LLID number, 0-7
+*                         target queue, 0-7, target gem port ID
+*
+*
+* OUTPUTS:
+*           mod_idx     - Returned by HW modification, to fill Tx description
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_cpu_wan_loopback(uint32_t owner_id,
+					  tpm_pkt_frwd_t *pkt_frwd,
+					  uint32_t *mod_idx)
+{
+	tpm_error_code_t ret_code;
+	ret_code = tpm_proc_add_cpu_wan_loopback(owner_id, pkt_frwd, mod_idx);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_add_cpu_wan_loopback);
+
+/*******************************************************************************
+* tpm_del_cpu_wan_loopback()
+*
+* DESCRIPTION: The API delete CPU egress loopback modification and PnC rules for
+*              specific Tcont/queue/gem_port
+*
+* INPUTS:   owner_id    - APP owner id  should be used for all API calls.
+*           pkt_frwd    - packet forwarding info: target tcont/LLID number, 0-7
+*                         target queue, 0-7, target gem port ID
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_cpu_wan_loopback(uint32_t owner_id,
+					  tpm_pkt_frwd_t *pkt_frwd)
+{
+	tpm_error_code_t ret_code;
+	ret_code = tpm_proc_del_cpu_wan_loopback(owner_id, pkt_frwd);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_del_cpu_wan_loopback);
+
+/*******************************************************************************
+* tpm_get_pnc_lu_entry()
+*
+* DESCRIPTION: The API get least used PnC rule by in specific PnC range
+*
+* INPUTS:   owner_id        - APP owner id  should be used for all API calls
+*           api_type       - TPM API group type
+*           lu_num          - The required number of least used PnC entries
+*           lu_reset        - Whether need to reset counter after read LU
+*
+*
+* OUTPUTS:
+*           valid_num       - The valid number of least used PnC entries
+*           count_array     - The least used PnC entry index  and hit counter array
+*           unrelated_num   - The unlelated number of least used PnC entries
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_pnc_lu_entry(uint32_t owner_id,
+				      tpm_api_type_t api_type,
+				      uint16_t lu_num,
+				      uint8_t lu_reset,
+				      uint16_t *valid_num,
+				      tpm_api_entry_count_t *count_array,
+				      uint16_t *unrelated_num)
+{
+	tpm_error_code_t ret_code;
+	ret_code = tpm_count_get_pnc_lu_entry(owner_id, api_type, lu_num, lu_reset, valid_num, count_array,
+					      unrelated_num);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_get_pnc_lu_entry);
+/*******************************************************************************
+* tpm_get_pnc_all_hit_counters
+*
+* DESCRIPTION: The API returns all PnC hit counters per API type lower than a given threshold
+*
+* INPUTS:   owner_id            - APP owner id  should be used for all API calls
+*           api_type            - TPM API group type
+*           high_thresh_pkts    - High threashold watermark, counters lower than will be returned
+*           counters_reset      - Reset API group type counters after read (0-false, 1-true)
+*           valid_counters      - The count_array size (entry number, not byte count)
+*
+* OUTPUTS:  valid_counters      - The valid number of entries copied to count_array
+*           count_array         - The PnC entries for the API type lower than high_thresh_pkts
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_pnc_all_hit_counters(uint32_t owner_id,
+					      tpm_api_type_t api_type,
+					      uint32_t high_thresh_pkts,
+					      uint8_t counters_reset,
+					      uint16_t *valid_counters,
+					      tpm_api_entry_count_t *count_array)
+{
+	tpm_error_code_t ret_code;
+	ret_code = tpm_count_get_pnc_all_hit_counters(owner_id, api_type, high_thresh_pkts,
+						      counters_reset, valid_counters, count_array);
+	return(ret_code);
+}
+/*******************************************************************************
+* tpm_set_pnc_counter_mask()
+*
+* DESCRIPTION: The API set the least used scanner ability, to mask or enable it
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type    - TPM API group type
+*           rule_idx     - The PnC rule index returned when created PnC rules
+*           lu_rule_mask - The least used scanner mask, 1: maskscanner ,
+*                          0:enable scanner
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_pnc_counter_mask(uint32_t owner_id,
+					  tpm_api_type_t api_type,
+					  uint32_t rule_idx,
+					  uint32_t lu_rule_mask)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_count_set_pnc_counter_mask(owner_id, api_type, rule_idx, lu_rule_mask);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_set_pnc_counter_mask);
+
+/*******************************************************************************
+* tpm_get_pnc_hit_count()
+*
+* DESCRIPTION: The API get the hit counter according to rule_idx
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type    - TPM API group type
+*           rule_idx     - The PnC rule index returned when created PnC rules
+*           hit_reset    - Should the API reset the hit counters after after reading
+*
+* OUTPUTS:
+*           rule_idx     - The hitted times of specific PnC rule
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_pnc_hit_count(uint32_t owner_id,
+				       tpm_api_type_t api_type,
+				       uint32_t rule_idx,
+				       uint8_t  hit_reset,
+				       uint32_t *hit_count)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_count_get_pnc_hit_count(owner_id, api_type, rule_idx, hit_reset, hit_count);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_get_pnc_hit_count);
+
+/*******************************************************************************
+* tpm_set_pnc_lu_threshold()
+*
+* DESCRIPTION: The API set the theshold packets number for least used scanner
+*
+* INPUTS:   owner_id       - APP owner id  should be used for all API calls
+*           api_type      - TPM API group type
+*           lu_thresh_pkts - The theshold number(hitted packets number) to be used
+*                            for least used scanner
+*
+* OUTPUTS:
+*            None
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_pnc_lu_threshold(uint32_t owner_id,
+					  tpm_api_type_t api_type,
+					  uint32_t lu_thresh_pkts)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_count_set_pnc_lu_threshold(owner_id, api_type, lu_thresh_pkts);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_set_pnc_lu_threshold);
+
+/*******************************************************************************
+* tpm_reset_pnc_age_group()
+*
+* DESCRIPTION: The API reset the hitted counter of all the PnC entries of specific
+*              group
+*
+* INPUTS:   owner_id      - APP owner id  should be used for all API calls
+*           api_type     - TPM API group type
+*
+* OUTPUTS:
+*            None
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_reset_pnc_age_group(uint32_t owner_id,
+					 tpm_api_type_t api_type)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_count_reset_pnc_age_group(owner_id, api_type);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_reset_pnc_age_group);
+
+/*******************************************************************************
+* tpm_set_mc_vid_port_vids()
+*
+* DESCRIPTION: The API sets the multicast vid configuration for each UNI port
+*
+* INPUTS:   owner_id - APP owner id  should be used for all API calls
+*               mc_vid - multicast VID
+*               mc_vid_uniports_config - VID configurations for different uni ports
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_mc_vid_port_vids(uint32_t owner_id,
+					  uint32_t mc_vid,
+					  tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config)
+{
+	tpm_error_code_t ret;
+
+	ret = tpm_proc_set_mc_vid_port_vids(owner_id, mc_vid, mc_vid_uniports_config);
+	if (TPM_RC_OK != ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "set VID error\n");
+		return ERR_GENERAL;
+	}
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_set_mc_vid_port_vids);
+/*******************************************************************************
+* tpm_set_mtu_enable()
+*
+* DESCRIPTION:      enable or disable MTU checking.
+*
+* INPUTS:
+*           enable   - set MTU checking to enable or disable.
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_mtu_enable(tpm_init_mtu_setting_enable_t  enable)
+{
+	tpm_db_set_mtu_enable(enable);
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_set_mtu()
+*
+* DESCRIPTION:      set the MTU value for PNC to check.
+*
+* INPUTS:
+*           mtu           - MTU value
+*           ethertype     - IPv4 or IPv6
+*           direction     - US or DS
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_mtu(uint32_t mtu,
+			     tpm_mtu_ethertype_t ethertype,
+			     uint32_t direction)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_set_mtu(ethertype, direction, mtu);
+	return(ret_code);
+}
+
+/*******************************************************************************
+* tpm_set_pppoe_mtu()
+*
+* DESCRIPTION:      set the PPPoE packets MTU value for PNC to check.
+*
+* INPUTS:
+*           pppoe_mtu     - MTU value
+*           ethertype     - IPv4 or IPv6
+*           direction     - US or DS
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_pppoe_mtu(uint32_t		pppoe_mtu,
+				   tpm_mtu_ethertype_t	ethertype,
+				   uint32_t		direction)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_set_pppoe_mtu(ethertype, direction, pppoe_mtu);
+	return(ret_code);
+}
+
+/*******************************************************************************
+* tpm_add_ctc_cm_acl_rule()
+*
+* DESCRIPTION:      Creates a new CTC CnM ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port, could be any UNI port:
+* precedence         - precedence of this CnM rule, from 0 to 7
+* l2_parse_rule_bm
+* ipv4_parse_rule_bm
+*                    - Bitmap containing the significant flags for parsing fields of the packet.
+* l2_key
+* ipv4_key
+*                    - Information to create a parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frw            - Information for packet forwarding decision.
+* pkt_act            - Action associated to the rule
+*
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct precedence of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ctc_cm_acl_rule(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint32_t precedence,
+					 tpm_parse_fields_t l2_parse_rule_bm,
+					 tpm_parse_fields_t ipv4_parse_rule_bm,
+					 tpm_l2_acl_key_t *l2_key,
+					 tpm_ipv4_acl_key_t  *ipv4_key,
+					 tpm_pkt_frwd_t *pkt_frwd,
+					 tpm_pkt_action_t pkt_act,
+					 uint32_t pbits)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+	uint32_t rule_num;
+	tpm_parse_fields_t ipv6_parse_rule_bm = 0;
+	tpm_ipv6_acl_key_t ipv6_key;
+
+	tpm_proc_calc_cnm_rule_num(src_port, precedence, &rule_num);
+
+	/* Check API_section Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_CNM, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_ctc_cm_acl_rule_add(owner_id, src_port, precedence, l2_parse_rule_bm, ipv4_parse_rule_bm,
+					   ipv6_parse_rule_bm, l2_key, ipv4_key, &ipv6_key, pkt_frwd, pkt_act, pbits);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_CNM, rule_num);
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ctc_cm_acl_rule);
+
+/*******************************************************************************
+* tpm_del_ctc_cm_acl_rule()
+*
+* DESCRIPTION:      Deletes an existing CTC CnM rule.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port, could be any UNI port:
+* precedence         - precedence of this CnM rule, from 0 to 7
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ctc_cm_acl_rule(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint32_t precedence)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_ctc_cm_acl_rule_del(owner_id, src_port, precedence);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_del_ctc_cm_acl_rule);
+/*******************************************************************************
+* tpm_flush_vtu()
+*
+* DESCRIPTION:      Flush VTU on the Switch.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_flush_vtu(uint32_t owner_id)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_sw_flush_vtu(owner_id);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_flush_vtu);
+/*******************************************************************************
+* tpm_flush_atu()
+*
+* DESCRIPTION:      Flush ATU on the Switch.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* flush_type         - FLUSH all or FLUSH all dynamic
+* db_num             - ATU DB Num, only 0 should be used, since there is only one ATU DB right now.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* 
+*
+*******************************************************************************/
+tpm_error_code_t tpm_flush_atu(uint32_t owner_id, tpm_flush_atu_type_t flush_type, uint16_t db_num)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_sw_flush_atu(owner_id, flush_type, db_num);
+	return ret_code;
+}
+EXPORT_SYMBOL(tpm_flush_atu);
+
+/*******************************************************************************
+* tpm_rule_self_check()
+*
+* DESCRIPTION:      Performs TPM self check
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* check_level        - The check level determines to correct bad tpm rule or not in the API call
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_rule_self_check(uint32_t owner_id,
+				     tpm_self_check_level_enum_t check_level)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_self_check(owner_id, check_level);
+
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_rule_self_check);
+
+/*******************************************************************************
+* tpm_add_ctc_cm_ipv6_acl_rule()
+*
+* DESCRIPTION:      Creates a new CTC IPv6 CnM ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port, could be any UNI port:
+* precedence         - precedence of this CnM rule, from 0 to 7
+* ipv6_parse_rule_bm
+*                    - Bitmap containing the significant flags for parsing fields of the packet.
+* ipv6_key
+*                    - Information to create a parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frw            - Information for packet forwarding decision.
+* pkt_act            - Action associated to the rule
+*
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct precedence of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ctc_cm_ipv6_acl_rule(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      uint32_t precedence,
+					      tpm_parse_fields_t ipv6_parse_rule_bm,
+					      tpm_ipv6_acl_key_t  *ipv6_key,
+					      tpm_pkt_frwd_t *pkt_frwd,
+					      tpm_pkt_action_t pkt_act,
+					      uint32_t pbits)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+	uint32_t rule_num;
+
+	tpm_proc_calc_cnm_rule_num(src_port, precedence, &rule_num);
+
+	/* Check API_section Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_CNM, rule_num);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_ctc_cm_ipv6_acl_rule_add(owner_id, src_port, precedence, ipv6_parse_rule_bm,
+					        ipv6_key, pkt_frwd, pkt_act, pbits);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_CNM, rule_num);
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_ctc_cm_ipv6_acl_rule);
+
+/*******************************************************************************
+* tpm_ctc_cm_set_ipv6_parse_window()
+*
+* DESCRIPTION:      Set IPv6 CnM rule parse window
+*     Two sets of IPv6 parse window:
+*       - first 24 bytes from IPv6 Header, include fields like: NH, TC, SIP
+*       - second 24 bytes from IPv6 Header, include fields like: L4 ports and DIP
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* check_level        - The check level determines to correct bad tpm rule or not in the API call
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_set_ipv6_parse_window(uint32_t owner_id,
+				     		  tpm_ctc_cm_ipv6_parse_win_t ipv6_parse_window)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_ctc_cm_set_ipv6_parse_win(owner_id, ipv6_parse_window);
+
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_ctc_cm_set_ipv6_parse_window);
+/*******************************************************************************
+* tpm_add_mac_learn_rule()
+*
+* DESCRIPTION:      Add a PNC L2 rule for source MAC learn
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* src_mac_addr       - MAC addr to learn
+* OUTPUTS:
+* rule_idx           - Unique rule identification number, which is used when deleting the rule.
+*                      (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_mac_learn_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr)
+{
+	tpm_error_code_t ret_code, busy_ret_code;
+
+	/* Check API_section Busy */
+	ret_code = tpm_proc_check_api_busy(TPM_API_MAC_LEARN, 0);
+	if (ret_code != TPM_OK)
+		return(ret_code);
+
+	ret_code = tpm_proc_add_static_mac_rule(owner_id, src_mac_addr);
+
+	busy_ret_code = tpm_proc_api_busy_done(TPM_API_MAC_LEARN, 0);
+	RET_BUSY_ERROR(ret_code, busy_ret_code);
+}
+EXPORT_SYMBOL(tpm_add_mac_learn_rule);
+
+/*******************************************************************************
+* tpm_del_mac_learn_rule()
+*
+* DESCRIPTION:      Del a PNC L2 rule for source MAC learn
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* src_mac_addr       - L2_key define the src mac addr for mac learn.
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_mac_learn_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_del_static_mac_rule(owner_id, src_mac_addr);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_del_mac_learn_rule);
+
+/*******************************************************************************
+* tpm_mac_learn_default_rule_act_set()
+*
+* DESCRIPTION:      Set the action for mac learn default rule
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* action             - rule action for mac learn default.
+* OUTPUTS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mac_learn_default_rule_act_set(uint32_t owner_id, tpm_unknown_mac_conf_t mac_conf)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_mac_learn_default_rule_act_set(owner_id, mac_conf);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_mac_learn_default_rule_act_set);
+
+/*******************************************************************************
+* tpm_mac_learn_entry_num_get()
+*
+* DESCRIPTION:      Get the mac learn entry number currently in system
+*
+* INPUTS:
+* None
+* OUTPUTS:
+* entry_num          - current MAC learn entry count in MAC_LEARN range, not including default one
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mac_learn_entry_num_get(uint32_t *entry_num)
+{
+	tpm_error_code_t ret_code;
+
+	ret_code = tpm_proc_mac_learn_entry_num_get(entry_num);
+	return (ret_code);
+}
+EXPORT_SYMBOL(tpm_mac_learn_entry_num_get);
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.h
new file mode 100755
index 0000000..ffa8aa3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_api.h
@@ -0,0 +1,3828 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_api.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1.1.1
+*
+*
+*******************************************************************************/
+
+#ifndef _TPM_API_H_
+#define _TPM_API_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "tpm_types.h"
+
+
+/******************************************************************************/
+/********************************** Administrative APIs ***********************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_create_ownerid()
+*
+* DESCRIPTION:      Creates an ownerId per an application group.
+*
+* INPUTS:
+*
+* OUTPUTS:
+* owner_id           - ID of an application group.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* This function is used for error prevention and not as a security mechanism.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_create_ownerid(uint32_t *owner_id);
+
+/*******************************************************************************
+* tpm_request_api_ownership()
+*
+* DESCRIPTION:      Establishes an ownership between owner_id and a group of APIs.
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* api_type          - the API type for which ownership is requested.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS.
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_api_ownership_error_t tpm_request_api_ownership(uint32_t 		owner_id,
+						    tpm_api_type_t 	api_type);
+
+/*******************************************************************************
+* tpm_erase_section()
+*
+* DESCRIPTION:      Erases a section per an application group.
+*
+* INPUTS:
+* owner_id          - API owner id  should be used for all API calls.
+* api_type          - the API PnC section to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_erase_section(uint32_t 		owner_id,
+				   tpm_api_type_t 	api_type);
+
+/*******************************************************************************
+* tpm_get_section_free_size()
+*
+* DESCRIPTION:      Returns the free size of an application group.
+*
+* INPUTS:
+* api_type          - the API type to retrieve section size for.
+*
+* OUTPUTS:
+* cur_size          - number of free entries for the API type.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_section_free_size(tpm_api_type_t 	 api_type,
+					   int32_t 		*cur_size);
+
+/******************************************************************************/
+/********************************** Data Forwarding APIs **********************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_add_l2_rule()
+*
+* DESCRIPTION:      Creates a new L2 processing ACL. Supports Table mode and ACL mode.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter determines if the packet is arriving
+*                      from the WAN port, a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for L2 API:
+*                        TPM_L2_PARSE_GEMPORT|
+*                        TPM_L2_PARSE_MAC_DA|TPM_L2_PARSE_MAC_SA|
+*                        TPM_L2_PARSE_ONE_VLAN_TAG|TPM_L2_PARSE_TWO_VLAN_TAG|
+*                        TPM_L2_PARSE_ETYPE| (Note: ETYPE recommended in tpm_add_l3_type_acl_rule)
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for L2 API:
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_TAG2_TRUE|TPM_PARSE_FLAG_TAG2_FALSE
+* l2_key             - Information to create a parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* pkt_mod            - Packet modification information.
+* pkt_mod_bm         - Bitmap contains the set of packet fields to modify.
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      possible "next_phase" for L2 API   -> STAGE_L3_TYPE , STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx         - If this API is in Table mode, this will equal to the rule_num,
+*                     otherwise it will be a unique number acrosss all API's.
+*
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_l2_rule(uint32_t 		owner_id,
+				 tpm_src_port_type_t 	src_port,
+				 uint32_t 		rule_num,
+				 uint32_t 	        *rule_idx,
+				 tpm_parse_fields_t 	parse_rule_bm,
+				 tpm_parse_flags_t 	parse_flags_bm,
+				 tpm_l2_acl_key_t      *l2_key,
+				 tpm_pkt_frwd_t        *pkt_frwd,
+				 tpm_pkt_mod_t         *pkt_mod,
+				 tpm_pkt_mod_bm_t 	pkt_mod_bm,
+				 tpm_rule_action_t     *rule_action);
+
+/*******************************************************************************
+* tpm_del_l2_rule()
+*
+* DESCRIPTION:      Deletes an existing L2 ACL primary rule.
+*                   Any of the existing entries may be deleted.
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* rule_idx           - Rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_l2_rule(uint32_t owner_id,
+				 uint32_t rule_idx);
+
+/*******************************************************************************
+* tpm_add_l3_type_rule()
+*
+* DESCRIPTION:      Creates a new L3 (ether_type or pppoe proto) processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter determines if the packet is arriving
+*                      from the WAN port, a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for L3 API:
+*                        TPM_L2_PARSE_ETYPE|TPM_L2_PARSE_PPPOE_SES|TPM_L2_PARSE_PPP_PROT
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for L3 API:
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_TAG2_TRUE|TPM_PARSE_FLAG_TAG2_FALSE|
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE
+* l3_key             - Structure for PPPoE proto or ether type.
+* pkt_frwd           - Information for packet forwarding decision.
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      possible "next_phase" for L3 API   ->  STAGE_IPv4, STAGE_IPv6_GEN, STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number, acrosss all API's.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_l3_type_rule(uint32_t 			owner_id,
+				      tpm_src_port_type_t 	src_port,
+				      uint32_t 			rule_num,
+				      uint32_t 		       *rule_idx,
+				      tpm_parse_fields_t 	parse_rule_bm,
+				      tpm_parse_flags_t 	parse_flags_bm,
+				      tpm_l3_type_key_t        *l3_key,
+				      tpm_pkt_frwd_t           *pkt_frwd,
+				      tpm_rule_action_t        *rule_action);
+
+/*******************************************************************************
+* tpm_del_l3_type_rule()
+*
+* DESCRIPTION:      Deletes an existing ethernet type or PPPoE proto access-list entry .
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* rule_idx           - rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_l3_type_rule(uint32_t owner_id,
+				      uint32_t rule_idx);
+
+/*******************************************************************************
+* tpm_add_ipv4_rule()
+*
+* DESCRIPTION:      Creates a new IPv4 processing ACL. Supports Table mode and ACL mode.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter determines if the packet is arriving
+*                      from the WAN port, a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for IPv4 API:
+*                        TPM_IPv4_PARSE_SIP|TPM_IPv4_PARSE_DIP|
+*                        TPM_IPv4_PARSE_DSCP|TPM_IPv4_PARSE_PROTO|
+*                        TPM_PARSE_L4_SRC|TPM_PARSE_L4_DST
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for IPv4 API:
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_PPPOE_TRUE|TPM_PARSE_FLAG_PPPOE_FALSE
+* ipv4_key           - Information to create an IPv4 parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* pkt_mod            - VLAN packet modification information.
+* pkt_mod_bm         - Bitmap containing the significant fields to modify (used for GWY only - in SFU is NULL)
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase.
+*                      possible "next_phase" for IPv4 API   ->  STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx         - If this API is in Table mode, this will equal to the rule_num,
+*                     otherwise it will be a unique number acrosss all API's.
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv4_rule(uint32_t 		owner_id,
+				   tpm_src_port_type_t 	src_port,
+				   uint32_t 		rule_num,
+				   uint32_t 	       *rule_idx,
+				   tpm_parse_fields_t 	parse_rule_bm,
+				   tpm_parse_flags_t 	parse_flags_bm,
+				   tpm_ipv4_acl_key_t  *ipv4_key,
+				   tpm_pkt_frwd_t      *pkt_frwd,
+				   tpm_pkt_mod_t       *pkt_mod,
+				   tpm_pkt_mod_bm_t 	pkt_mod_bm,
+				   tpm_rule_action_t   *rule_action);
+
+/*******************************************************************************
+* tpm_del_ipv4_rule()
+*
+* DESCRIPTION:      Deletes an existing IPv4 ACL rule.
+*                   Both rule number and key are compulsory.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* rule_idx           - rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv4_rule(uint32_t owner_id,
+				   uint32_t rule_idx);
+
+/*******************************************************************************
+* tpm_add_ipv6_nh_rule()
+*
+* DESCRIPTION:      Creates a new IPv6 NH processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* rule_num           - Entry index to be added in the current ACL
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for IPv6 NH API:
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_PPPOE_TRUE|TPM_PARSE_FLAG_PPPOE_FALSE
+* nh                 - Information to create a NH parsing key for the rule.
+* pkt_frwd           - Information for packet forwarding decision.
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase (for GWY only).
+*                      possible "next_phase" for IPv6 NH API   ->  STAGE_IPV6_L4,STAGE_DONE
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number, acrosss all API's.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+* This version does not support HWF for IPV6. Therefore (pkt_frwd) params are N/A in this version.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_nh_rule(uint32_t 			owner_id,
+				      uint32_t 			rule_num,
+				      uint32_t 	       	       *rule_idx,
+				      tpm_parse_flags_t 	parse_flags_bm,
+				      tpm_nh_iter_t 		nh_iter,
+				      uint32_t 			nh,
+				      tpm_pkt_frwd_t   	       *pkt_frwd,
+				      tpm_rule_action_t        *rule_action);
+
+/*******************************************************************************
+* tpm_del_ipv6_nh_rule()
+*
+* DESCRIPTION:      Deletes an existng IPv6 NH processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* rule_idx           - rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_nh_rule(uint32_t owner_id,
+				      uint32_t rule_idx);
+
+/*******************************************************************************
+* tpm_add_ipv6_gen_rule()
+*
+* DESCRIPTION:      Creates a new IPv6 gen processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter determines if the packet is arriving
+*                      from the WAN port, a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for IPv6 GEN API:
+*                        TPM_IPv6_PARSE_SIP|TPM_IPv6_PARSE_DSCP|TPM_IPv6_PARSE_HOPL
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for IPv6 GEN API:
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_PPPOE_TRUE|TPM_PARSE_FLAG_PPPOE_FALSE
+* ipv6_gen_key     - Information to create an IPv6 gen parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* pkt_mod            - Packet modification information.
+* pkt_mod_bm         - Bitmap containing the significant fields to modify
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase (for GWY only).
+*                      possible "next_phase" for IPv6 GEN API   ->  STAGE_IPv6_DIP, ,STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number, acrosss all API's.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+* This version does not support HWF for IPV6. Therefore (pkt_mod_bm, pkt_mod, pkt_frwd) params are N/A in this version.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_gen_rule(uint32_t 			owner_id,
+					 tpm_src_port_type_t 		src_port,
+					 uint32_t 			rule_num,
+					 uint32_t 		       *rule_idx,
+					 tpm_parse_fields_t 		parse_rule_bm,
+					 tpm_parse_flags_t 		parse_flags_bm,
+					 tpm_ipv6_gen_acl_key_t      *ipv6_gen_key,
+					 tpm_pkt_frwd_t 	       *pkt_frwd,
+					 tpm_pkt_mod_t 		       *pkt_mod,
+					 tpm_pkt_mod_bm_t 		pkt_mod_bm,
+					 tpm_rule_action_t             *rule_action);
+
+/*******************************************************************************
+* tpm_del_ipv6_gen_rule()
+*
+* DESCRIPTION:      Deletes an existng IPv6 gen processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* rule_idx           - rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_gen_rule(uint32_t owner_id,
+					 uint32_t rule_idx);
+
+/*******************************************************************************
+* tpm_add_ipv6_dip_rule()
+*
+* DESCRIPTION:      Creates a new IPv6 DIP processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter determines if the packet is arriving
+*                      from the WAN port, a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for IPv6 DIP API:
+*                        TPM_IPv6_PARSE_DIP
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for IPv6 DIP API:
+*                        TPM_PARSE_FLAG_TAG1_TRUE|TPM_PARSE_FLAG_TAG1_FLASE|
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_PPPOE_TRUE|TPM_PARSE_FLAG_PPPOE_FALSE
+* ipv6_dip_key       - Information to create an IPv6 DIP parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* pkt_mod            - Packet modification information.
+* pkt_mod_bm         - Bitmap containing the significant fields to modify
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase (for GWY only).
+*                      possible "next_phase" for IPv6 GEN API   ->  STAGE_IPv6_NHSTAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx          - Unique rule identification number, acrosss all API's.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+* This version does not support HWF for IPV6. Therefore (pkt_mod_bm, pkt_mod, pkt_frwd) params are N/A in this version.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_dip_rule(uint32_t 		owner_id,
+				       tpm_src_port_type_t 	src_port,
+				       uint32_t 		rule_num,
+				       uint32_t 	       *rule_idx,
+				       tpm_parse_fields_t 	parse_rule_bm,
+				       tpm_parse_flags_t 	parse_flags_bm,
+				       tpm_ipv6_addr_key_t     *ipv6_dip_key,
+				       tpm_pkt_frwd_t          *pkt_frwd,
+				       tpm_pkt_mod_t           *pkt_mod,
+				       tpm_pkt_mod_bm_t 	pkt_mod_bm,
+				       tpm_rule_action_t       *rule_action);
+
+/*******************************************************************************
+* tpm_del_ipv6_dip_rule()
+*
+* DESCRIPTION:      Deletes an existng IPv6 DIP processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* rule_idx           - rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_dip_rule(uint32_t owner_id,
+				       uint32_t rule_idx);
+
+/*******************************************************************************
+* tpm_add_ipv6_l4_ports_rule()
+*
+* DESCRIPTION:      Creates a new IPv6 L4 processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter determines if the packet is arriving
+*                      from the WAN port, a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+*                      possible values for L4 API:
+*                        TPM_PARSE_L4_SRC|TPM_PARSE_L4_DST
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+*                      possible values for L4 API:
+*                        TPM_PARSE_FLAG_MTM_TRUE|TPM_PARSE_FLAG_MTM_FALSE|
+*                        TPM_PARSE_FLAG_TO_CPU_TRUE|TPM_PARSE_FLAG_TO_CPU_FALSE|
+*                        TPM_PARSE_FLAG_L4_TCP|TPM_PARSE_FLAG_L4_UDP
+* l4_key             - Information to create an L4 parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frwd           - Information for packet forwarding decision.
+* pkt_mod            - Packet modification information.
+* pkt_mod_bm         - Bitmap containing the significant fields to modify (used for GWY only - in SFU is NULL)
+* rule_action        - Action associated to the rule = drop/set target/set packet modification/to CPU
+*                      and the next phase (for GWY only).
+*                      possible "next_phase" for L4 API   ->  STAGE_DONE
+*
+* OUTPUTS:
+*  rule_idx          - Unique rule identification number, acrosss all API's.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+* This version does not support HWF for IPV6. Therefore (pkt_mod_bm, pkt_mod, pkt_frwd) params are N/A in this version.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_l4_ports_rule(uint32_t 			owner_id,
+					    tpm_src_port_type_t 	src_port,
+					    uint32_t 			rule_num,
+					    uint32_t 		       *rule_idx,
+					    tpm_parse_fields_t 		parse_rule_bm,
+					    tpm_parse_flags_t 		parse_flags_bm,
+					    tpm_l4_ports_key_t 	       *l4_key,
+					    tpm_pkt_frwd_t 	       *pkt_frwd,
+					    tpm_pkt_mod_t 	       *pkt_mod,
+					    tpm_pkt_mod_bm_t 		pkt_mod_bm,
+					    tpm_rule_action_t 	       *rule_action);
+
+/*******************************************************************************
+* tpm_del_ipv6_l4_ports_rule()
+*
+* DESCRIPTION:      Deletes an existng L4 processing ACL.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* rule_idx           - rule idenitifcation number specifying the rule to be deleted.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_l4_ports_rule(uint32_t owner_id,
+					    uint32_t rule_idx);
+
+
+tpm_error_code_t tpm_add_ipv6_gen_5t_rule(uint32_t owner_id,
+										tpm_dir_t src_dir,
+										uint32_t rule_num,
+										uint32_t *rule_idx,
+										tpm_parse_fields_t parse_rule_bm,
+										tpm_parse_flags_t parse_flags_bm,
+										tpm_l4_ports_key_t *l4_key,
+										tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+										tpm_pkt_frwd_t *pkt_frwd,
+										tpm_pkt_mod_t *pkt_mod,
+										tpm_pkt_mod_bm_t pkt_mod_bm,
+										tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_del_ipv6_gen_5t_rule(uint32_t owner_id, uint32_t rule_idx);
+
+tpm_error_code_t tpm_add_ipv6_dip_5t_rule(uint32_t owner_id,
+										tpm_dir_t src_dir,
+										uint32_t rule_num,
+										uint32_t *rule_idx,
+										tpm_parse_fields_t parse_rule_bm,
+										tpm_parse_flags_t parse_flags_bm,
+										tpm_l4_ports_key_t *l4_key,
+										tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+										tpm_ipv6_addr_key_t *ipv6_dip_key,
+										tpm_pkt_frwd_t *pkt_frwd,
+										tpm_pkt_mod_t *pkt_mod,
+										tpm_pkt_mod_bm_t pkt_mod_bm,
+										tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_del_ipv6_dip_5t_rule(uint32_t owner_id, uint32_t rule_idx);
+
+tpm_error_code_t tpm_add_ipv6_l4_ports_5t_rule(uint32_t owner_id,
+											tpm_dir_t src_dir,
+											uint32_t rule_num,
+											uint32_t *rule_idx,
+											tpm_parse_fields_t parse_rule_bm,
+											tpm_parse_flags_t parse_flags_bm,
+											tpm_l4_ports_key_t *l4_key,
+											tpm_pkt_frwd_t *pkt_frwd,
+											tpm_pkt_mod_t *pkt_mod,
+											tpm_pkt_mod_bm_t pkt_mod_bm,
+											tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_del_ipv6_l4_ports_5t_rule(uint32_t owner_id, uint32_t rule_idx);
+
+
+/******************************************************************************/
+/********************************** MC handling APIs **************************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_add_ipv4_mc_stream()
+*
+* DESCRIPTION:      Creates a new IPv4 MC stream.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* igmp_mode          - Defines if stream is in snooping or in proxy mode. Not relevant when sending stream to CPU.
+*                        snooping_mode: Vlan_translation only
+*                        proxy_mode   : snooping_mode + Replace SA_MAC, and reduce TTL.
+*                                       For pppoe stream, replace unicast DA to MC DA, and delete pppoe header.
+* mc_stream_pppoe    - The stream's underlying L2 protocol.  0(IPv4oE), 1(IPv4oPPPoE)
+* vid                - VLAN ID (0-4095).
+*                      If set to 0xFFFF - do not care about vid.
+* ipv4_src_add       - IPv4 source IP address in network order.
+* ipv4_src_add       - IPv4 destination IP address in network order.
+* ignore_ipv4_src    - when set to 1 - the IP source is not part of the key.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*                   It is APIs caller responsibility to maintain the correct number of
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv4_mc_stream(uint32_t		 owner_id,
+					uint32_t 		stream_num,
+					tpm_mc_igmp_mode_t 	igmp_mode,
+					uint8_t 		mc_stream_pppoe,
+					uint16_t 		vid,
+					uint8_t 		ipv4_src_add[4],
+					uint8_t 		ipv4_dst_add[4],
+					uint8_t 		ignore_ipv4_src,
+					tpm_trg_port_type_t 	dest_port_bm);
+
+/*******************************************************************************
+* tpm_updt_ipv4_mc_stream()
+*
+* DESCRIPTION:      Updates an existing IPv4 MC stream.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_updt_ipv4_mc_stream(uint32_t 		owner_id,
+					 uint32_t 		stream_num,
+					 tpm_trg_port_type_t 	dest_port_bm);
+
+/*******************************************************************************
+* tpm_del_ipv4_mc_stream()
+*
+* DESCRIPTION:      Deletes an existing IPv4 MC stream.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv4_mc_stream(uint32_t owner_id,
+					uint32_t stream_num);
+
+/*******************************************************************************
+* tpm_add_ipv6_mc_stream()
+*
+* DESCRIPTION:      Creates a new ipv6 MC stream.
+*                   It is APIs caller responsibility to maintain the correct number of
+*                   each stream number.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* vid                - VLAN ID (0-4095). If set to 4096 - stream is untagged.
+*                      If set to 0xFFFF - do not care.
+* ipv6_src_add       - ipv6 source IP address in network order.
+* ipv6_dst_add       - ipv6 destination IP address in network order.
+* ignore_ipv6_src    - when set to 1 - the IP source is not part of the key.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ipv6_mc_stream(uint32_t owner_id,
+					uint32_t stream_num,
+					tpm_mc_igmp_mode_t igmp_mode,
+					uint8_t mc_stream_pppoe,
+					uint16_t vid,
+					uint8_t ipv6_src_add[16],
+					uint8_t ipv6_dst_add[16],
+					uint8_t ignore_ipv6_src,
+					tpm_trg_port_type_t dest_port_bm);
+
+/*******************************************************************************
+* tpm_updt_ipv6_mc_stream()
+*
+* DESCRIPTION:      Updates an existing ipv6 MC stream.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+* dest_port_bm       - bitmap which includes all destination UNI ports.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_updt_ipv6_mc_stream(uint32_t 		owner_id,
+					 uint32_t 		stream_num,
+					 tpm_trg_port_type_t 	dest_port_bm);
+
+/*******************************************************************************
+* tpm_del_ipv6_mc_stream()
+*
+* DESCRIPTION:      Deletes an existing ipv6 MC stream.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ipv6_mc_stream(uint32_t owner_id,
+					uint32_t stream_num);
+
+/*******************************************************************************
+* tpm_set_mc_vid_port_vids()
+*
+* DESCRIPTION:         Sets the port_participation for a Multicast VID.
+*                      Each uni_port can be excluded, or member in (transparent, vlan_strip, vlan_translate) mode.
+* INPUTS:
+* owner_id                      - API owner id  should be used for all API calls.
+* mc_vid                        - The Multicast VID.
+* mc_vid_uniports_config        - Array of per_uni_port configurations.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_mc_vid_port_vids(uint32_t 			owner_id,
+					  uint32_t 			mc_vid,
+					  tpm_mc_vid_port_vid_set_t    *mc_vid_uniports_config);
+
+/*******************************************************************************
+* tpm_set_port_igmp_frwd_mode()
+*
+* DESCRIPTION:      Set the IGMP status of a UNI port or WAN port.
+*
+* INPUTS:
+* src_port         - source port to set IGMP behavior for, valid values (WAN, UNI_0/1/2/3/4)
+* mode             - how to process IGMP packets (drop, forward, snoop_to_cpu)
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_port_igmp_frwd_mode(tpm_src_port_type_t  src_port,
+					     tpm_igmp_frwd_mode_t mode);
+
+/*******************************************************************************
+* tpm_set_igmp_cpu_rx_queue()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to.
+*
+* INPUTS:
+* queue             - cpu queue number to send IGMP packets to.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_igmp_cpu_rx_queue(uint32_t queue);
+
+/*******************************************************************************
+* tpm_mib_reset()
+*
+* DESCRIPTION:      Performs MIB reset
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* reset_level        - The reset level determines the which elements will not be reset in the API call
+*                      (by comparing to the element's reset level)
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mib_reset(uint32_t 		owner_id,
+			       tpm_reset_level_enum_t	reset_level);
+
+/******************************************************************************/
+/********************************** Management protocol APIs ******************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_omci_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the OMCI management protocol.
+*                   The API sets the gemportid, the Rx input queue in the CPU, and the
+*                   Tx T-CONT and queue parameters, which are configured in the driver.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* gem_port           - for OMCI Rx frames - the gem port wherefrom the OMCI frames are received.
+* cpu_rx_queue       - for OMCI Rx frames - the CPU rx queue number.
+* tcont_num          - for OMCI Tx frames - the TCONT number where to send the OMCI frames.
+* cpu_tx_queue       - for OMCI Tx frames - the CPU tx queue number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_omci_add_channel(uint32_t 			owner_id,
+				      tpm_gem_port_key_t 	gem_port,
+				      uint32_t 			cpu_rx_queue,
+				      tpm_trg_port_type_t 	tcont_num,
+				      uint32_t 			cpu_tx_queue);
+
+/*******************************************************************************
+* tpm_omci_del_channel()
+*
+* DESCRIPTION:      Deletes an existing communication channel for the OMCI management protocol.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_omci_del_channel(uint32_t owner_id);
+
+/*******************************************************************************
+* tpm_oam_epon_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the OAM EPON management protocol.
+*                   The API sets the Rx input queue in the CPU, and the
+*                   Tx T-CONT and queue parameters, which are configured in the driver.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+* cpu_rx_queue       - for OAM (EPON) Rx frames - the CPU rx queue number.
+* llid_num           - for OAM (EPON)Tx frames - the LLID number where to send the OMCI frames.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_epon_add_channel(uint32_t		owner_id,
+					  uint32_t		cpu_rx_queue,
+					  tpm_trg_port_type_t	llid_num);
+
+/*******************************************************************************
+* tpm_oam_epon_del_channel()
+*
+* DESCRIPTION:      Deletes an existing communication channel for the OAM EPON management protocol.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_epon_del_channel(uint32_t owner_id);
+
+/*******************************************************************************
+* tpm_oam_loopback_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the EPON OAM remote loopback.
+*
+*
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_loopback_add_channel(uint32_t owner_id);
+
+/*******************************************************************************
+* tpm_oam_loopback_del_channel()
+*
+* DESCRIPTION:      Delete the communication channel for the OAM remote loopback .
+*
+*
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_loopback_del_channel(uint32_t owner_id);
+
+/*******************************************************************************
+* tpm_loop_detect_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for loop detection application.
+*
+* INPUTS:
+* owner_id           - API owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_loop_detect_add_channel(uint32_t owner_id);
+
+/******************************************************************************/
+/********************************** Configuration retrieval APIs **************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_get_next_valid_rule()
+*
+* DESCRIPTION:      General purpose API to retrieve the internal configuration of an existing ACL.
+*
+* INPUTS:
+* owner_id            - API owner id  should be used for all API calls.
+* current_index       - the entry index in the section (rule_num/stream_num). In case it is (-1) - the get next function
+*                      will point to the first ruleof the section.
+* api_type            - TPM API type
+*
+* OUTPUTS:
+* next_index         - returns the first following index (rule_num/stream_num) after the index in the current_index
+*                      parameter. It is invalid, if there is no next_index.
+* rule_idx           - Unique rule identification number. Equals to stream_num for API's that are operating
+*                      in table mode.
+* tpm_rule           - points to a structure holding the information of a single rule,
+*                      of the type specified in the rule_type param.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_next_valid_rule(uint32_t		owner_id,
+					 int32_t 		current_index,
+					 tpm_api_type_t 	api_type,
+					 int32_t       	       *next_index,
+					 uint32_t	       *rule_idx,
+					 tpm_rule_entry_t      *tpm_rule);
+
+/*******************************************************************************
+* tpm_omci_get_channel()
+*
+* DESCRIPTION:      Retrieves the OMCI management protocol channel information.
+*
+* INPUTS:
+*  None.
+*
+* OUTPUTS:
+* is_valid           - indicates that the OMCI channel is valid or not.
+* gem_port           - for OMCI Rx frames - the gem port wherefrom the OMCI frames are received.
+* cpu_rx_queue       - for OMCI Rx frames - the CPU rx queue number.
+* tcont_num          - for OMCI Tx frames - the TCONT number where to send the OMCI frames.
+* cpu_tx_queue       - for OMCI Tx frames - the CPU tx queue number.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_omci_get_channel(uint32_t 			*is_valid,
+				      tpm_gem_port_key_t 	*gem_port,
+				      uint32_t 			*cpu_rx_queue,
+				      tpm_trg_port_type_t 	*tcont_num,
+				      uint32_t 			*cpu_tx_queue);
+
+/*******************************************************************************
+* tpm_get_port_igmp_frwd_mode()
+*
+* DESCRIPTION:      Get the IGMP status of a UNI port or WAN port.
+*
+* INPUTS:
+* src_port          - source port to get
+*
+* OUTPUTS:
+* state             - how to process IGMP packets
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_port_igmp_frwd_mode(tpm_src_port_type_t   src_port,
+					     tpm_igmp_frwd_mode_t *mode);
+
+/*******************************************************************************
+* tpm_get_igmp_cpu_rx_queue()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to.
+*
+* INPUTS:
+* queue             - queue number
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_igmp_cpu_rx_queue(uint32_t *queue);
+
+/*******************************************************************************
+* tpm_set_igmp_proxy_sa_mac()
+*
+* DESCRIPTION:      Set source mac address replaced for igmp proxy.
+*
+* INPUTS:
+* sa_mac          - source mac
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_igmp_proxy_sa_mac(uint8_t *sa_mac);
+
+/*******************************************************************************
+* tpm_get_igmp_proxy_sa_mac()
+*
+* DESCRIPTION:      Get source mac address replaced for igmp proxy.
+*
+* INPUTS:
+* sa_mac          - source mac
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_igmp_proxy_sa_mac(uint8_t *sa_mac);
+
+/*******************************************************************************
+* tpm_oam_epon_get_channel()
+*
+* DESCRIPTION:      Retrieves OAM EPON management protocol channel information.
+*
+* INPUTS:
+*  None.
+*
+* OUTPUTS:
+* is_valid           -  indicates that the OMCI channel is valid or not.
+* cpu_rx_queue       - for OAM (EPON) Rx frames - the CPU rx queue number.
+* llid_num           - for OAM (EPON)Tx frames - the LLID number where to send the OMCI frames.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_oam_epon_get_channel(uint32_t		*is_valid,
+					  uint32_t 		*cpu_rx_queue,
+					  tpm_trg_port_type_t 	*llid_num);
+
+/*******************************************************************************
+* tpm_get_api_ownership()
+*
+* DESCRIPTION:      Retrieves OAM EPON management protocol channel information.
+*
+* INPUTS:
+* api_group          - Specifies the API group whom owner_id is requested.
+*
+* OUTPUTS:
+* owner_id           - specifies the ownerId of the application group
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS.
+* On error:     API_TYPE_UNKNOWN  when illegal API group
+*               API_OWNERSHIP_ERROR  other errors.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_api_ownership_error_t tpm_get_api_ownership(uint32_t      *owner_id,
+						tpm_api_type_t api_type);
+
+/******************************************************************************/
+/************************** Packet modification APIs **************************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_mod_entry_set()
+*
+* DESCRIPTION: The API sets a complete Modification table entry
+*
+* INPUTS:   trg_port    - target port
+*           mod_bm      - set of flags described which fields in the packet
+*                         to be changed
+*           int_mod_bm  - set of internal flags
+*           mod_data    - modification entry data
+*
+* OUTPUTS:
+*           mod_entry   - start entry number which has been set for this
+*                         modification
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mod_entry_set(tpm_trg_port_type_t 		trg_port,
+				   tpm_pkt_mod_bm_t 		mod_bm,
+				   tpm_pkt_mod_int_bm_t 	int_mod_bm,
+				   tpm_pkt_mod_t 	       *mod_data,
+				   uint32_t 		       *mod_entry);
+
+/*******************************************************************************
+* tpm_mod_entry_get()
+*
+* DESCRIPTION: The API gets Modification table entries
+*
+* INPUTS:   trg_port    - target port
+*           mod_entry   - start entry number (in the "jump" area)
+*
+* OUTPUTS:
+*           valid_cmds  - number of valid commands in the chunk
+*                             0 - there is no requested data
+*           pnc_ref     - Number of references from Pnc entries to this modification rule
+*           rule        - modification rule (set of modification entries)
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mod_entry_get(tpm_trg_port_type_t	trg_port,
+				   uint32_t 		mod_entry,
+				   uint16_t 	       *valid_cmds,
+				   uint16_t	       *pnc_ref,
+				   tpm_mod_rule_t      *rule);
+
+/*******************************************************************************
+* tpm_mod_entry_del()
+*
+* DESCRIPTION: The API invalidates a modification entry chunk
+*
+* INPUTS:   trg_port    - target port
+*           mod_entry   - start entry number (in the "jump" area)
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mod_entry_del(tpm_trg_port_type_t 	trg_port,
+				   uint32_t 		mod_entry);
+
+/*******************************************************************************
+* tpm_mod_mac_inv()
+*
+* DESCRIPTION: The API resets Modification table for a specified port
+*
+* INPUTS:   trg_port    - target port
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mod_mac_inv(tpm_trg_port_type_t trg_port);
+
+/******************************************************************************/
+/*************************** Least Used & Hit Counters APIs *******************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_get_pnc_lu_entry()
+*
+* DESCRIPTION: The API get least used PnC rule by in specific PnC range
+*
+* INPUTS:   owner_id        - API owner id  should be used for all API calls
+*           api_type        - TPM API type
+*           lu_num          - The required number of least used PnC entries
+*           lu_reset        - Should the API reset the counters after after reading the LU Counters
+*
+*
+* OUTPUTS:
+*           valid_num       - Number of valid least used PnC entries
+*           count_array     - Array of the returned least used PnC entry rule_idx  and hit_counter.
+*           unrelated_num   - Number of unrelated  least used PnC entries
+*                             (PnC entries which were not part of this API_type)
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_pnc_lu_entry(uint32_t			owner_id,
+				      tpm_api_type_t 		api_type,
+				      uint16_t 			lu_num,
+				      uint8_t 			lu_reset,
+				      uint16_t 		       *valid_num,
+				      tpm_api_entry_count_t    *count_array,
+				      uint16_t 		       *unrelated_num);
+/*******************************************************************************
+* tpm_get_pnc_all_hit_counters
+*
+* DESCRIPTION: The API returns all PnC hit counters per API type lower than a given threshold
+*
+* INPUTS:   owner_id            - APP owner id  should be used for all API calls
+*           api_type            - TPM API group type
+*           high_thresh_pkts    - High threashold watermark, counters lower than will be returned
+*           counters_reset      - Reset API group type counters after read (0-false, 1-true)
+*           valid_counters      - The count_array size (entry number, not byte count)
+*
+* OUTPUTS:
+*           valid_counters      - The valid number of entries copied to count_array
+*           count_array         - The PnC entries for the API type lower than high_thresh_pkts
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_pnc_all_hit_counters(uint32_t                owner_id,
+					      tpm_api_type_t          api_type,
+					      uint32_t                high_thresh_pkts,
+					      uint8_t                 counters_reset,
+					      uint16_t               *valid_counters,
+					      tpm_api_entry_count_t  *count_array);
+
+/*******************************************************************************
+* tpm_set_pnc_counter_mask()
+*
+* DESCRIPTION: The API set the ability to mask or unmask a specific API entry from being LU scanned.
+*
+* INPUTS:   owner_id     - API owner id  should be used for all API calls
+*           api_type     - TPM API type
+*           rule_idx     - The rule index of the requested entry.
+*           lu_rule_mask - The least used scanner mask
+*                            0:enable_scanner, 1: mask_from_scanner
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_pnc_counter_mask(uint32_t		owner_id,
+					  tpm_api_type_t 	api_type,
+					  uint32_t 		rule_idx,
+					  uint32_t 		lu_rule_mask);
+
+/*******************************************************************************
+* tpm_get_pnc_hit_count()
+*
+* DESCRIPTION: The API get the hit counter according to rule_idx
+*
+* INPUTS:   owner_id     - API owner id  should be used for all API calls
+*           api_type     - TPM API type
+*           rule_idx     - The rule index of the requested entry.
+*           hit_reset    - Should the API reset the hit counters after after reading
+*
+* OUTPUTS:
+*           hit_count    - The number of hits of the rule.
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_pnc_hit_count(uint32_t 	owner_id,
+				       tpm_api_type_t 	api_type,
+				       uint32_t 	rule_idx,
+				       uint8_t		hit_reset,
+				       uint32_t        *hit_count);
+
+/*******************************************************************************
+* tpm_set_pnc_lu_threshold()
+*
+* DESCRIPTION: The API set the theshold packets number for least used scanner
+*
+* INPUTS:   owner_id       - API owner id  should be used for all API calls
+*           api_type       - TPM API type
+*           lu_thresh_pkts - The least_used theshold to be used for the lu_scanner, in number of packets.
+*                            Hit_counts above this threshold are not returned by the scanner,
+*                            even if they are the lowest amoung their peers.
+* OUTPUTS:
+*            None
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_pnc_lu_threshold(uint32_t 		owner_id,
+					  tpm_api_type_t 	api_type,
+					  uint32_t 		lu_thresh_pkts);
+
+/*******************************************************************************
+* tpm_reset_pnc_age_group()
+*
+* DESCRIPTION: This API resets the hit counters of all the PnC entries of a specific
+*              API. It may reset other PnC entries as well, if they share the same hit_group.
+*
+* INPUTS:   owner_id       - API owner id  should be used for all API calls
+*           api_type       - TPM API type
+*
+* OUTPUTS:
+*            None
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_reset_pnc_age_group(uint32_t 	owner_id,
+					 tpm_api_type_t api_type);
+
+/*******************************************************************************
+* tpm_add_cpu_wan_loopback()
+*
+* DESCRIPTION: The API allows the CPU to set the target for packets that will be
+*              loopbacked to the WAN port to a HWF queue, by means of packet_modification.
+*              It returns to the CPU the mod_idx to put in the Tx_Descriptor, so that the
+*              packet will be forwarded to the correct target. The cpu_loopback mechanism is
+*              done by use of GMAC1, it is assumed that GMAC0&GMAC1 are both connected to the Internal Switch.
+*
+* INPUTS:   owner_id    - owner id
+*           pkt_frwd    - packet forwarding info: target tcont/LLID number, 0-7
+*                         target queue, 0-7, target gem port ID
+*
+* OUTPUTS:
+*           mod_idx     - Returned by HW modification, to fill Tx description
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_cpu_wan_loopback(uint32_t 		owner_id,
+					  tpm_pkt_frwd_t       *pkt_frwd,
+					  uint32_t 	       *mod_idx);
+
+/*******************************************************************************
+* tpm_del_cpu_wan_loopback()
+*
+* DESCRIPTION: The API delete CPU egress loopback modification and PnC rules for
+*              specific Tcont/queue/gem_port
+*
+* INPUTS:   owner_id    - owner id
+*           pkt_frwd    - packet forwarding info: target tcont/LLID number, 0-7
+*                         target queue, 0-7, target gem port ID
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_cpu_wan_loopback(uint32_t 	  owner_id,
+					  tpm_pkt_frwd_t *pkt_frwd);
+
+/*******************************************************************************
+* tpm_rx_igmp_frame()
+*
+* DESCRIPTION: The API receives IGMP frames from either LAN or WAN side,
+*              it will be blocked until a packet arrived.
+*
+* INPUTS:   owner_id    - owner id
+*           buf         - Message buffer allocated by user
+*           len         - Max len of this buffer
+*
+* OUTPUTS:
+*           llid        - source LLID index in case this frame comes from WAN side
+*           src_port    - source UNI port in case this frame comes from LAN side
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_rx_igmp_frame(uint32_t 		owner_id,
+				   uint16_t 	       *llid,
+				   tpm_src_port_type_t *src_port,
+				   uint8_t 	       *buf,
+				   uint32_t 	       *len);
+/*******************************************************************************
+* tpm_tx_igmp_frame()
+*
+* DESCRIPTION: The API sends IGMP frames to either LAN or WAN side
+*
+* INPUTS:   owner_id    - owner id
+*           tgt_port    - target port, LLID0-7/TCONT0-7/UNI0-3
+*           tgt_queue   - target queue, 0-7
+*           gem_port    - target gem port ID
+*           buf         - Message buffer allocated by user
+*           len         - Len of this buffer
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tx_igmp_frame(uint32_t owner_id,
+				   tpm_trg_port_type_t tgt_port,
+				   uint8_t tgt_queue,
+				   uint16_t gem_port,
+				   uint8_t *buf,
+				   uint32_t len);
+
+/*******************************************************************************
+* tpm_set_mtu_enable()
+*
+* DESCRIPTION:      enable or disable MTU checking.
+*
+* INPUTS:
+*           enable   - set MTU checking to enable or disable.
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_mtu_enable(tpm_init_mtu_setting_enable_t enable);
+
+/*******************************************************************************
+* tpm_set_mtu()
+*
+* DESCRIPTION:      set the MTU value for PNC to check.
+*
+* INPUTS:
+*           mtu           - MTU value
+*           ethertype     - IPv4 or IPv6
+*           direction     - US or DS
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_mtu(uint32_t mtu,
+			     tpm_mtu_ethertype_t ethertype,
+			     uint32_t direction);
+
+/*******************************************************************************
+* tpm_set_pppoe_mtu()
+*
+* DESCRIPTION:      set the PPPoE packets MTU value for PNC to check.
+*
+* INPUTS:
+*           pppoe_mtu     - MTU value
+*           ethertype     - IPv4 or IPv6
+*           direction     - US or DS
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_pppoe_mtu(uint32_t pppoe_mtu,
+				   tpm_mtu_ethertype_t ethertype,
+				   uint32_t direction);
+
+tpm_error_code_t tpm_rule_self_check(uint32_t owner_id,
+				     tpm_self_check_level_enum_t check_level);
+
+/******************************************************************************/
+/********************************** Switch APIs *******************************/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_sw_add_static_mac
+*
+* DESCRIPTION:
+*       This function creates a static MAC entry in the MAC address table for a
+*       specific lport in the integrated switch
+*
+* INPUTS:
+*       owner_id    - APP owner id, should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       static_mac  - 6 byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_add_static_mac(uint32_t owner_id,
+				       tpm_src_port_type_t src_port,
+				       uint8_t static_mac[6]);
+
+/*******************************************************************************
+* tpm_sw_del_static_mac
+*
+* DESCRIPTION:
+*       This function removes an existing static MAC entry from the MAC address
+*       table  in the integrated switch.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       static_mac  - 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_del_static_mac(uint32_t owner_id,
+				       uint8_t static_mac[6]);
+
+/*******************************************************************************
+* tpm_sw_set_port_max_macs
+*
+* DESCRIPTION:
+*       This function limits the number of MAC addresses per lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id  should be used for all API calls.
+*       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mac_per_port - maximum number of MAC addresses per port (1-255).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       The following care is needed when enabling this feature:
+*            1) disable learning on the ports
+*            2) flush all non-static addresses in the ATU
+*            3) define the desired limit for the ports
+*            4) re-enable learing on the ports
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_max_macs(uint32_t owner_id,
+					  tpm_src_port_type_t src_port,
+					  uint8_t mac_per_port);
+
+/*******************************************************************************
+* tpm_sw_clear_dynamic_mac
+*
+* DESCRIPTION:
+*       Clear all dynamic MAC.
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_clear_dynamic_mac(uint32_t owner_id);
+
+/*******************************************************************************
+* tpm_sw_set_port_mirror
+*
+* DESCRIPTION:
+*       Set port mirror.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*       sport      - Source port.
+*       dport      - Destination port.
+*       mode       - mirror mode.
+*       enable     - enable/disable mirror.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_mirror(uint32_t owner_id,
+					uint32_t sport,
+					uint32_t dport,
+					tpm_sw_mirror_type_t mode,
+					bool enable);
+
+/*******************************************************************************
+* tpm_sw_get_port_mirror
+*
+* DESCRIPTION:
+*       Get port mirror status.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*       sport      - Source port.
+*       dport      - Destination port.
+*       mode       - mirror mode.
+*
+* OUTPUTS:
+*       enable     - enable/disable mirror.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_mirror(uint32_t owner_id,
+					uint32_t sport,
+					uint32_t dport,
+					tpm_sw_mirror_type_t mode,
+					bool *enable);
+
+/*******************************************************************************
+* tpm_sw_set_isolate_eth_port_vector()
+*
+* DESCRIPTION:      Isolate port vector.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       port_vector - port vector.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_isolate_eth_port_vector(uint32_t owner_id,
+						    tpm_src_port_type_t src_port,
+						    uint32_t port_vector);
+
+/*******************************************************************************
+* tpm_sw_get_isolate_eth_port_vector()
+*
+* DESCRIPTION:      Isolate port vector.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       port_vector - port vector.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_isolate_eth_port_vector(uint32_t owner_id,
+						    tpm_src_port_type_t src_port,
+						    uint32_t *port_vector);
+
+/*******************************************************************************
+* tpm_set_mtu_size
+*
+* DESCRIPTION:
+*       Set switch MTU size.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*       type       - MRU type:GMAC0, GMAC1, PONMAC, switch
+*       mtu        - MTU size.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_mtu_size(uint32_t owner_id,
+				  tpm_mru_type_t type,
+				  uint32_t mtu);
+
+/*******************************************************************************
+* tpm_get_mtu_size
+*
+* DESCRIPTION:
+*       Get switch MTU size.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*       type       - MRU type:GMAC0, GMAC1, PONMAC, switch
+*
+* OUTPUTS:
+*       mtu        - MTU size.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_mtu_size(uint32_t owner_id,
+				  tpm_mru_type_t type,
+				  uint32_t *mtu);
+
+/*******************************************************************************
+* tpm_sw_set_port_tagged
+*
+* DESCRIPTION:
+*       The API allows or drops tagged packets on a per lport basis.
+*
+* INPUTS:
+*       owner_id     - APP owner id should be used for all API calls.
+*       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       allow_tagged - set to 1 = discard tagged packets per lport
+*                      set to 0 = allow tagged packets per lport.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_tagged(uint32_t owner_id,
+					tpm_src_port_type_t src_port,
+					uint8_t allow_tagged);
+
+/*******************************************************************************
+* tpm_sw_get_port_tagged
+*
+* DESCRIPTION:
+*       This routine gets DiscardTagged bit for the given lport.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       mode       - MV_TRUE if DiscardTagged bit is set, MV_FALSE otherwise
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_tagged(uint32_t owner_id,
+					tpm_src_port_type_t src_port,
+					uint32_t *mode);
+
+/*******************************************************************************
+* tpm_sw_set_port_untagged
+*
+* DESCRIPTION:
+*       The API allows or drops untagged packets on a per UNI port basis.
+*
+* INPUTS:
+*       owner_id       - APP owner id should be used for all API calls.
+*       src_port       - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       allow_untagged - set to 1 = discard untagged packets per lport
+*                        set to 0 = alow untagged packets per lport.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_untagged(uint32_t owner_id,
+					  tpm_src_port_type_t src_port,
+					  uint8_t allow_untagged);
+
+/*******************************************************************************
+* tpm_sw_get_port_untagged
+*
+* DESCRIPTION:
+*       This routine gets DiscardUntagged bit for the given lport.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       mode        - MV_TRUE if DiscardUntagged bit is set, MV_FALSE otherwise
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_untagged(uint32_t owner_id,
+					  tpm_src_port_type_t src_port,
+					  uint32_t *mode);
+
+/*******************************************************************************
+* tpm_sw_set_port_def_vlan
+*
+* DESCRIPTION:
+*       The API sets port default vlan id.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - the port vlan id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_def_vlan(uint32_t owner_id,
+					  tpm_src_port_type_t src_port,
+					  uint16_t vid);
+
+/*******************************************************************************
+* tpm_sw_get_port_def_vlan
+*
+* DESCRIPTION:
+*       The API gets port default vlan id.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       vid        - the port vlan id
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_def_vlan(uint32_t owner_id,
+					  tpm_src_port_type_t src_port,
+					  uint16_t *vid);
+
+/*******************************************************************************
+* tpm_sw_set_port_def_pri
+*
+* DESCRIPTION:
+*       The API sets port default priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       pri        - the port priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_def_pri(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint8_t pri);
+
+/*******************************************************************************
+* tpm_sw_get_port_def_pri
+*
+* DESCRIPTION:
+*       The API gets port default priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       pri        - the port priority.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_def_pri(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint8_t *pri);
+
+/*******************************************************************************
+* tpm_sw_port_add_vid
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per lport.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       see the example sample802_1qSetup().
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_add_vid(uint32_t owner_id,
+				     tpm_src_port_type_t src_port,
+				     uint16_t vid);
+
+/*******************************************************************************
+* tpm_sw_port_add_vid_group()
+*
+* DESCRIPTION:  Add a group of VID to the list of the allowed VIDs per port,
+*               and set the egress mode correspondingly.
+*
+* INPUTS:
+*       owner_id - APP owner id should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode     - VLAN egress mode.
+*       min_vid  - min VLAN ID.
+*       max_vid  - max VLAN ID.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_add_vid_group(uint32_t owner_id,
+					   tpm_src_port_type_t src_port,
+					   uint8_t mode,
+					   uint16_t min_vid,
+					   uint16_t max_vid);
+
+/*******************************************************************************
+* tpm_sw_port_del_vid_group()
+*
+* DESCRIPTION:      Delete a group of VID to the list of the allowed VIDs per port,
+*                    and set the egress mode correspondingly.
+*
+* INPUTS:
+*       owner_id - APP owner id should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       min_vid  - min VLAN ID.
+*       max_vid  - max VLAN ID.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_del_vid_group(uint32_t owner_id,
+					   tpm_src_port_type_t src_port,
+					   uint16_t min_vid,
+					   uint16_t max_vid);
+
+/*******************************************************************************
+* tpm_sw_port_del_vid
+*
+* DESCRIPTION:
+*       The API delete and existing VID from the list of VIDs allowed per lport.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_del_vid(uint32_t owner_id,
+				     tpm_src_port_type_t src_port,
+				     uint16_t vid);
+
+/*******************************************************************************
+* tpm_sw_clear_vid_per_port
+*
+* DESCRIPTION:
+*       The API delete all VID from the list of VIDs allowed per lport.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_clear_vid_per_port(uint32_t owner_id,
+					   tpm_src_port_type_t src_port);
+
+/*******************************************************************************
+* tpm_sw_add_all_vid_per_port
+*
+* DESCRIPTION:
+*       The API adds all allowed VIDs from 1 to 4095 per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_add_all_vid_per_port(uint32_t owner_id,
+					     tpm_src_port_type_t src_port);
+
+/*******************************************************************************
+* tpm_sw_set_port_vid_egress_mode
+*
+* DESCRIPTION:
+*       The API sets the egress mode for a member port of a vlan.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - vlan id
+*       eMode      - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_vid_egress_mode(uint32_t owner_id,
+						 tpm_src_port_type_t src_port,
+						 uint16_t vid,
+						 uint8_t eMode);
+
+/*******************************************************************************
+* tpm_sw_port_set_vid_filter
+*
+* DESCRIPTION:
+*       The API sets the filtering mode of a certain lport.
+*       If the lport is in filtering mode, only the VIDs added by the
+*       tpm_sw_port_add_vid API will be allowed to ingress and egress the lport.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid_filter  - set to 1 - means the lport will DROP all packets which are NOT in
+*                    the allowed VID list (built using API tpm_sw_port_add_vid).
+*                    set to  0 - means that the list of VIDs allowed
+*                    per lport has no significance (the list is not deleted).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_set_vid_filter(uint32_t owner_id,
+					    tpm_src_port_type_t src_port,
+					    uint8_t vid_filter);
+
+/*******************************************************************************
+* tpm_sw_set_mac_age_time
+*
+* DESCRIPTION:
+*       This function Sets the MAC address aging time.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       time_out   - MAC address aging time
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_mac_age_time(uint32_t owner_id,
+					 uint32_t time_out);
+
+/*******************************************************************************
+* tpm_sw_get_mac_age_time
+*
+* DESCRIPTION:
+*       This function Sets the MAC address aging time.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*
+* OUTPUTS:
+*       time_out   - time out value.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_mac_age_time(uint32_t owner_id,
+					 uint32_t *time_out);
+
+/*******************************************************************************
+*  tpm_sw_set_mac_learn
+*
+* DESCRIPTION:
+*       Enable/disable automatic learning of new source MAC addresses on port
+*       ingress.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       enable     - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_mac_learn(uint32_t owner_id,
+				      tpm_src_port_type_t src_port,
+				      bool enable);
+
+/*******************************************************************************
+*  tpm_sw_get_mac_learn
+*
+* DESCRIPTION:
+*       Enable/disable automatic learning of new source MAC addresses on port
+*       ingress.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       enable     - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_mac_learn(uint32_t owner_id,
+				      tpm_src_port_type_t src_port,
+				      bool *enable);
+
+/*******************************************************************************
+* tpm_sw_set_port_flooding()
+*
+* DESCRIPTION:      permit or not the flooding per port
+*
+* INPUTS:
+*   owner_id    - APP owner id should be used for all API calls.
+*   src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*   flood_mode  - flooding mode.
+*   allow_flood - set to 1 = permit flooding of unknown DA.
+*
+* OUTPUTS:
+*   None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_flooding(uint32_t owner_id,
+					  tpm_src_port_type_t src_port,
+					  tpm_flood_type_t flood_mode,
+					  uint8_t allow_flood);
+
+/*******************************************************************************
+* tpm_sw_get_port_flooding()
+*
+* DESCRIPTION:      permit or not the flooding per port
+*
+* INPUTS:
+*   owner_id    - APP owner id should be used for all API calls.
+*   src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*   flood_mode  - flooding mode
+*
+* OUTPUTS:
+*   allow_flood - set to 1 = permit flooding .
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_flooding(uint32_t owner_id,
+					  tpm_src_port_type_t src_port,
+					  tpm_flood_type_t flood_mode,
+					  uint8_t *allow_flood);
+
+/******************************************************************************/
+/*                            MAC security APIs                               */
+/******************************************************************************/
+
+/******************************************************************************/
+/********************************** Traffic management switch APIs ************/
+/******************************************************************************/
+/*******************************************************************************
+* tpm_sw_set_uni_sched()
+*
+* DESCRIPTION:      Configures the scheduling mode per Ethernet port.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* uni_port          - UNI port for setting the scheduling mode
+* sched_mode        - scheduler mode per port
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_sched(uint32_t owner_id,
+				      tpm_src_port_type_t uni_port,
+				      tpm_sw_sched_type_t sched_mode);
+
+/*******************************************************************************
+* tpm_sw_set_uni_q_weight()
+*
+* DESCRIPTION:      Configures the weight of a queue for all Ethernet UNI ports
+*                   in the integrated switch.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* queue_id          - queueId for setting the weight.
+* weight            - weight value per queue.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_q_weight(uint32_t owner_id,
+					 uint8_t queue_id,
+					 uint8_t weight);
+
+/*******************************************************************************
+* tpm_sw_set_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures an ingress policing function for an Ethernet UNI lport.
+*
+* INPUTS:
+*       owner_id   - APP owner id, should be used for all API calls.
+*       uni_port   - uni lport for configuring the ingress policer function.
+*       count_mode - count mode:
+*                               TPM_SW_LIMIT_FRAME
+*                               TPM_SW_LIMIT_LAYER1
+*                               TPM_SW_LIMIT_LAYER2
+*                               TPM_SW_LIMIT_LAYER3
+*       cir        - comited info rate.
+*       cbs        - Committed Burst Size limit (expected to be 2kBytes)
+*       ebs        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_ingr_police_rate(uint32_t owner_id,
+						 tpm_src_port_type_t uni_port,
+						 tpm_limit_mode_t count_mode,
+						 uint32_t cir,
+						 uint32_t cbs,
+						 uint32_t ebs);
+
+/*******************************************************************************
+* tpm_sw_get_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API gets an ingress policing function for an Ethernet UNI lport.
+*
+* INPUTS:
+*       owner_id   - APP owner id, should be used for all API calls.
+*       uni_port   - uni lport for configuring the ingress policer function.
+*
+*
+* OUTPUTS:
+*       count_mode - count mode:
+*                               TPM_SW_LIMIT_FRAME
+*                               TPM_SW_LIMIT_LAYER1
+*                               TPM_SW_LIMIT_LAYER2
+*                               TPM_SW_LIMIT_LAYER3
+*       cir        - comited info rate.
+*       cbs        - Committed Burst Size limit (expected to be 2kBytes)
+*       ebs        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_uni_ingr_police_rate(uint32_t owner_id,
+						 tpm_src_port_type_t uni_port,
+						 tpm_limit_mode_t *count_mode,
+						 uint32_t *cir,
+						 uint32_t *cbs,
+						 uint32_t *ebs);
+
+/*******************************************************************************
+* tpm_sw_set_uni_tc_ingr_police_rate()
+*
+* DESCRIPTION:      Configures an policer function for a traffic class.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* uni_port          - UNI port.
+* tc                - traffic class
+* cir
+* cbs
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_tc_ingr_police_rate(uint32_t owner_id,
+						    tpm_src_port_type_t uni_port,
+						    uint32_t tc,
+						    uint32_t cir,
+						    uint32_t cbs);
+
+/*******************************************************************************
+* tpm_sw_set_uni_egr_rate_limit()
+*
+* DESCRIPTION:      Configures the egress rate limit of an Ethernet UNI port.
+*
+* INPUTS:
+*       owner_id        - APP owner id  should be used for all API calls.
+*       trg_port        - UNI port for fonfig the egress rate limit
+*       limit_mode      - limit mode:  TPM_SW_LIMIT_FRAME,  TPM_SW_LIMIT_LAYER1,
+*                                      TPM_SW_LIMIT_LAYER2, TPM_SW_LIMIT_LAYER3
+*       rate_limit_val  - egress rate limit value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_egr_rate_limit(uint32_t wner_id,
+					       tpm_src_port_type_t trg_port,
+					       tpm_limit_mode_t limit_mode,
+					       uint32_t rate_limit_val);
+
+/*******************************************************************************
+* tpm_sw_get_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API return the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id        - APP owner id , should be used for all API calls.
+*       trg_lport        - uni lport for configuring the egress rate limit.
+
+*
+* OUTPUTS:
+*      limit_mode      - limit mode:    TPM_SW_LIMIT_FRAME, TPM_SW_LIMIT_LAYER1,
+*                                            TPM_SW_LIMIT_LAYER2, TPM_SW_LIMIT_LAYER3
+*      rate_limit_val    - egress rate limit value
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       Valid rate_limit_val values are:
+*                                    7600,..., 9600,
+*                                    10000, 20000, 30000, 40000, ..., 100000,
+*                                    110000, 120000, 130000, ..., 1000000.
+
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_uni_egr_rate_limit(uint32_t owner_id,
+					       tpm_src_port_type_t trg_port,
+					       tpm_limit_mode_t *limit_mode,
+					       uint32_t *rate_limit_val);
+
+/******************************************************************************/
+/********************************** Switch PHY port management  APIs **********/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_phy_convert_port_index()
+*
+* DESCRIPTION: convert switch port index to external port index.
+*
+* INPUTS:
+* owner_id       - APP owner id  should be used for all API calls.
+* switch_port    - switch port index
+*
+* OUTPUTS:
+* extern_port    - external port index
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_convert_port_index(uint32_t owner_id,
+					    uint32_t switch_port,
+					    tpm_src_port_type_t *extern_port);
+
+/*******************************************************************************
+* tpm_phy_set_port_autoneg_mode
+*
+* DESCRIPTION:
+*       The API Configures the auto negotiation state of an Ethernet  lport.
+* INPUTS:
+*       owner_id       - APP owner id should be used for all API calls.
+*       src_port       - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       autoneg_state  - autonegotiation state, enabled or disabled.
+*       autoneg_mode   - enum:
+*                        TPM_SPEED_AUTO_DUPLEX_AUTO: Auto for both speed and duplex
+*                        TPM_SPEED_1000_DUPLEX_AUTO: 1000Mbps and auto duplex
+*                        TPM_SPEED_100_DUPLEX_AUTO:  100Mbps and auto duplex
+*                        TPM_SPEED_10_DUPLEX_AUTO:   10Mbps and auto duplex
+*                        TPM_SPEED_AUTO_DUPLEX_FULL: Auto for speed only and Full duplex
+*                        TPM_SPEED_AUTO_DUPLEX_HALF: Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                        TPM_SPEED_1000_DUPLEX_FULL: 1000Mbps Full duplex.
+*                        TPM_SPEED_1000_DUPLEX_HALF: 1000Mbps half duplex.
+*                        TPM_SPEED_100_DUPLEX_FULL:  100Mbps Full duplex.
+*                        TPM_SPEED_100_DUPLEX_HALF:  100Mbps half duplex.
+*                        TPM_SPEED_10_DUPLEX_FULL:   10Mbps Full duplex.
+*                        TPM_SPEED_10_DUPLEX_HALF:   10Mbps half duplex.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_autoneg_mode(uint32_t owner_id,
+					       tpm_src_port_type_t src_port,
+					       bool autoneg_state,
+					       tpm_autoneg_mode_t autoneg_mode);
+
+/*******************************************************************************
+* tpm_phy_get_port_autoneg_mode
+*
+* DESCRIPTION:
+*       The API return the the auto negotiation state of an Ethernet  lport.
+* INPUTS:
+*       owner_id       - APP owner id should be used for all API calls.
+*       src_port       - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       autoneg_state  - autonegotiation state, enabled or disabled.
+*       autoneg_mode   - enum:
+*                        TPM_SPEED_AUTO_DUPLEX_AUTO: Auto for both speed and duplex
+*                        TPM_SPEED_1000_DUPLEX_AUTO: 1000Mbps and auto duplex
+*                        TPM_SPEED_100_DUPLEX_AUTO:  100Mbps and auto duplex
+*                        TPM_SPEED_10_DUPLEX_AUTO:   10Mbps and auto duplex
+*                        TPM_SPEED_AUTO_DUPLEX_FULL: Auto for speed only and Full duplex
+*                        TPM_SPEED_AUTO_DUPLEX_HALF: Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                        TPM_SPEED_1000_DUPLEX_FULL: 1000Mbps Full duplex.
+*                        TPM_SPEED_1000_DUPLEX_HALF: 1000Mbps half duplex.
+*                        TPM_SPEED_100_DUPLEX_FULL:  100Mbps Full duplex.
+*                        TPM_SPEED_100_DUPLEX_HALF:  100Mbps half duplex.
+*                        TPM_SPEED_10_DUPLEX_FULL:   10Mbps Full duplex.
+*                        TPM_SPEED_10_DUPLEX_HALF:   10Mbps half duplex.
+
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_autoneg_mode(uint32_t owner_id,
+					       tpm_src_port_type_t src_port,
+					       bool *autoneg_state,
+					       tpm_autoneg_mode_t *autoneg_mode);
+
+/*******************************************************************************
+* tpm_phy_restart_port_autoneg
+*
+* DESCRIPTION:
+*       The API restart the auto negotiation of an Ethernet  lport.
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*        NONE.
+*                                .
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_restart_port_autoneg(uint32_t owner_id,
+					      tpm_src_port_type_t src_port);
+
+/*******************************************************************************
+* tpm_phy_set_port_admin_state
+*
+* DESCRIPTION:
+*       The API Configures the PHY port  state of an Ethernet  lport.
+* INPUTS:
+*       owner_id        - APP owner id should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       phy_port_state  - PHY port  state to set.
+*                         0:normal state
+*                         1:power down
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_admin_state(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      bool phy_port_state);
+
+/*******************************************************************************
+* tpm_phy_get_port_admin_state
+*
+* DESCRIPTION:
+*       The API return the PHY port  state of an Ethernet  lport.
+* INPUTS:
+*       owner_id        - APP owner id should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       phy_port_state  -  0:normal state
+*                          1:power down                                    .
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_admin_state(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      bool *phy_port_state);
+
+/*******************************************************************************
+* tpm_phy_get_port_link_status
+*
+* DESCRIPTION:
+*       The API return realtime port link status of an Ethernet  lport.
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       port_link_status  -  0:port link is ON
+*                            1:port link is DOWN                                    .
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_link_status(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      bool *port_link_status);
+
+/*******************************************************************************
+* tpm_phy_get_port_duplex_status
+*
+* DESCRIPTION:
+*       The API return realtime port duplex status of an Ethernet  lport.
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       port_duplex_status  -  0:half deplex mode
+*                              1:full deplex mode                    .
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_duplex_status(uint32_t owner_id,
+						tpm_src_port_type_t src_port,
+						bool *port_duplex_status);
+
+/*******************************************************************************
+* tpm_phy_get_port_speed_mode
+*
+* DESCRIPTION:
+*       The API return realtime port speed mode of an Ethernet  lport.
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       port_duplex_status  -  0:10M
+*                              1:100M
+*                              2:1000M
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_speed_mode(uint32_t owner_id,
+					     tpm_src_port_type_t src_port,
+					     uint32_t *speed);
+
+/*******************************************************************************
+* tpm_phy_set_port_flow_control_support
+*
+* DESCRIPTION:
+*       This routine will set the pause bit in Autonegotiation Advertisement
+*        Register. And restart the autonegotiation.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       state       - false:port pause is off.
+*                     true:port pause is on.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+tpm_error_code_t tpm_phy_set_port_flow_control_support(uint32_t owner_id,
+						       tpm_src_port_type_t src_port,
+						       bool state);
+
+/*******************************************************************************
+* tpm_phy_get_port_flow_control_support
+* DESCRIPTION:
+*       This routine will get the pause bit in Autonegotiation Advertisement
+*        Register.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       state      -  false:port pause is off.
+*                     true:port pause is on.
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+tpm_error_code_t tpm_phy_get_port_flow_control_support(uint32_t owner_id,
+						       tpm_src_port_type_t src_port,
+						       bool *state);
+
+/*******************************************************************************
+* tpm_phy_get_port_flow_control_state
+*
+* DESCRIPTION:
+*     This routine will get the current pause state.
+*        Register.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       state       -
+*                   false: MAC Pause not implemented in the link partner or in MyPause
+*                   rue:  MAC Pause is implemented in the link partner and in MyPause
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*       None.
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_flow_control_state(uint32_t owner_id,
+						     tpm_src_port_type_t src_port,
+						     bool *state);
+
+/*******************************************************************************
+* tpm_phy_set_port_loopback
+*
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode        - Internal or external loopback
+*       enable      - If true, enable loopback mode
+*                     If false, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_loopback(uint32_t owner_id,
+					   tpm_src_port_type_t src_port,
+					   tpm_phy_loopback_mode_t mode,
+					   bool enable);
+
+/*******************************************************************************
+* tpm_phy_get_port_loopback
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode        - Internal or external loopback
+*
+* OUTPUTS:
+*       enable      - If GT_TRUE,  loopback mode is enabled
+*                     If GT_FALSE,  loopback mode is disabled
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_loopback(uint32_t owner_id,
+					   tpm_src_port_type_t src_port,
+					   tpm_phy_loopback_mode_t mode,
+					   bool *enable);
+
+/*******************************************************************************
+* tpm_phy_set_port_duplex_mode
+*
+* DESCRIPTION:
+*        Sets duplex mode for a specific logical port. This function will keep
+*        the speed and loopback mode to the previous value, but disable others,
+*        such as Autonegotiation.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       enable      - Enable/Disable dulpex mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*         data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_duplex_mode(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      bool enable);
+
+/*******************************************************************************
+* tpm_phy_get_port_duplex_mode
+*
+* DESCRIPTION:
+*         Gets duplex mode for a specific logical port.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+
+*
+* OUTPUTS:
+*       enable      - Enable/Disable dulpex mode
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*         data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_duplex_mode(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      bool *enable);
+
+/*******************************************************************************
+* tpm_phy_set_port_speed
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       speed       -    PHY_SPEED_10_MBPS   - 10Mbps
+*                        PHY_SPEED_100_MBPS  - 100Mbps
+*                        PHY_SPEED_1000_MBPS - 1000Mbps.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case, see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_speed(uint32_t owner_id,
+					tpm_src_port_type_t src_port,
+					tpm_phy_speed_t speed);
+
+/*******************************************************************************
+* tpm_phy_get_port_speed
+*
+* DESCRIPTION:
+*       This routine will get current PHY port speed .
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+
+*
+*
+* OUTPUTS:
+*        speed      -    PHY_SPEED_10_MBPS   -10Mbps
+*                        PHY_SPEED_100_MBPS  -100Mbps
+*                        PHY_SPEED_1000_MBPS -1000Mbps.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_speed(uint32_t owner_id,
+					tpm_src_port_type_t src_port,
+					tpm_phy_speed_t *speed);
+
+/******************************************************************************/
+/**                       Traffic management packet processor APIs           **/
+/******************************************************************************/
+
+/*******************************************************************************
+* tpm_tm_set_wan_egr_queue_sched()
+*
+* DESCRIPTION:      Configures the scheduling mode per WAN queue.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* sched_ent         - entity for setting the scheduling mode: ex:TPM_TRG_PORT_WAN
+* sched_mode        - scheduler mode per port: strict(0) / wrr(1)
+* queue_id          - queue number
+* wrr_weight        - weight value when WRR scheduling (1-256)
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_egr_queue_sched(uint32_t owner_id,
+						tpm_trg_port_type_t sched_ent,
+						tpm_pp_sched_type_t sched_mode,
+						uint8_t queue_id,
+						uint16_t wrr_weight);
+
+/*******************************************************************************
+* tpm_tm_set_wan_ingr_queue_sched()
+*
+* DESCRIPTION:      Configures the scheduling mode per all downstream traffic from the WAN.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* sched_mode        - scheduler mode per port: strict(0) / wrr(1)
+* queue_id          - queue number
+* wrr_weight        - weight value when WRR scheduling (1-256)
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_ingr_queue_sched(uint32_t owner_id,
+						 tpm_pp_sched_type_t sched_mode,
+						 uint8_t queue_id,
+						 uint16_t wrr_weight);
+
+/*******************************************************************************
+* tpm_tm_set_wan_sched_egr_rate_lim()
+*
+* DESCRIPTION:      Configures the egress rate limit of upstream traffic.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* sched_ent         - entity for setting the rate limit: ex:TPM_TRG_PORT_WAN
+* rate_limit_val    - egress rate limit value
+* bucket_size       - bucket size value
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_sched_egr_rate_lim(uint32_t owner_id,
+						   tpm_trg_port_type_t sched_ent,
+						   uint32_t rate_limit_val,
+						   uint32_t bucket_size);
+
+/*******************************************************************************
+* tpm_tm_set_wan_queue_egr_rate_lim()
+*
+* DESCRIPTION:      Configures the upstream traffic egress rate limit for a specific
+*                   queue of an upstream scheduling entity.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* sched_ent         - entity for setting the rate limit: ex:TPM_TRG_PORT_WAN
+* queue_id          - queue number
+* rate_limit_val    - egress rate limit value
+* bucket_size       - bucket size value
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_queue_egr_rate_lim(uint32_t owner_id,
+						   tpm_trg_port_type_t sched_ent,
+						   uint32_t queue_id,
+						   uint32_t rate_limit_val,
+						   uint32_t bucket_size);
+
+/*******************************************************************************
+* tpm_tm_set_wan_ingr_rate_lim()
+*
+* DESCRIPTION:      Configures the rate limit of all downstream traffic from the WAN.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* rate_limit_val    - ingress rate limit value
+* bucket_size       - bucket size value
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_ingr_rate_lim(uint32_t owner_id,
+					      uint32_t rate_limit_val,
+					      uint32_t bucket_size);
+
+/*******************************************************************************
+* tpm_tm_set_wan_q_ingr_rate_lim()
+*
+* DESCRIPTION:      Configures the egress rate limit of a specific queue for
+*                   downstream traffic.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* queue_id          - queue number
+* rate_limit_val    - ingress rate limit value
+* bucket_size       - bucket size value
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_q_ingr_rate_lim(uint32_t owner_id,
+						uint32_t queue_id,
+						uint32_t rate_limit_val,
+						uint32_t bucket_size);
+
+/*******************************************************************************
+* tpm_alarm_get_eth_port
+*
+* DESCRIPTION:
+*       This function gets eth port alarm.
+*
+* INPUTS:
+*       owner_id     - APP owner id , should be used for all API calls.
+*
+* OUTPUTS:
+*       alarm_type  - eth alarm type
+*         port_bitmap    - port bitmap
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_alarm_get_eth_port(uint32_t owner_id,
+					uint32_t *alarm_type,
+					uint8_t *port_bitmap);
+
+/*******************************************************************************
+* tpm_sw_pm_1_read
+*
+*
+* INPUTS:
+*      owner_id          - APP owner id  should be used for all API calls.
+*       port              - The logical port number
+*      tpm_swport_pm_3   - Holds PM data
+*
+* OUTPUTS:
+* PM data is supplied structure.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_1_read(uint32_t owner_id,
+				  tpm_src_port_type_t port,
+				  tpm_swport_pm_1_t *tpm_swport_pm_1);
+
+/*******************************************************************************
+* tpm_sw_pm_3_read
+*
+*
+* INPUTS:
+*      owner_id          - APP owner id  should be used for all API calls.
+*       port              - The logical port number
+*      tpm_swport_pm_3   - Holds PM data
+*
+* OUTPUTS:
+* PM data is supplied structure.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_3_read(uint32_t owner_id,
+				  tpm_src_port_type_t port,
+				  tpm_swport_pm_3_t *tpm_swport_pm_3);
+
+/*******************************************************************************
+* tpm_sw_clear_port_counter
+*
+* DESCRIPTION:
+*       The API clear port pm counter.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*
+*
+* OUTPUTS:
+*       none.
+*
+* RETURNS:
+* On success - TPM_RC_OK
+* On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_clear_port_counter(uint32_t owner_id,
+					   tpm_src_port_type_t port);
+/*******************************************************************************
+* tpm_add_ctc_cm_acl_rule()
+*
+* DESCRIPTION:      Creates a new CTC CnM ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port, could be any UNI port:
+* precedence         - precedence of this CnM rule, from 0 to 7
+* l2_parse_rule_bm   
+* ipv4_parse_rule_bm
+*                    - Bitmap containing the significant flags for parsing fields of the packet.
+* l2_key
+* ipv4_key
+*                    - Information to create a parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frw            - Information for packet forwarding decision.
+* pkt_act            - Action associated to the rule
+*
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct precedence of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t	tpm_add_ctc_cm_acl_rule(uint32_t	owner_id,
+        tpm_src_port_type_t   src_port,
+        uint32_t              precedence,
+        tpm_parse_fields_t    l2_parse_rule_bm,
+        tpm_parse_fields_t    ipv4_parse_rule_bm,
+        tpm_l2_acl_key_t      *l2_key,
+        tpm_ipv4_acl_key_t    *ipv4_key,
+        tpm_pkt_frwd_t        *pkt_frwd,
+        tpm_pkt_action_t      pkt_act,
+        uint32_t              pbits);
+
+/*******************************************************************************
+* tpm_del_ctc_cm_acl_rule()
+*
+* DESCRIPTION:      Deletes an existing CTC CnM rule.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port, could be any UNI port:
+* precedence         - precedence of this CnM rule, from 0 to 7
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct precedence of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_ctc_cm_acl_rule(uint32_t owner_id,
+	tpm_src_port_type_t   src_port,
+	uint32_t			  precedence);
+
+/*******************************************************************************
+* tpm_add_ctc_cm_ipv6_acl_rule()
+*
+* DESCRIPTION:      Creates a new CTC IPv6 CnM ACL.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port, could be any UNI port:
+* precedence         - precedence of this CnM rule, from 0 to 7
+* ipv6_parse_rule_bm
+*                    - Bitmap containing the significant flags for parsing fields of the packet.
+* ipv6_key
+*                    - Information to create a parsing key for the rule.
+*                      Some pointers may be NULL depending on the parse_rule_bm.
+* pkt_frw            - Information for packet forwarding decision.
+* pkt_act            - Action associated to the rule
+*
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct precedence of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_ctc_cm_ipv6_acl_rule(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      uint32_t precedence,
+					      tpm_parse_fields_t ipv6_parse_rule_bm,
+					      tpm_ipv6_acl_key_t  *ipv6_key,
+					      tpm_pkt_frwd_t *pkt_frwd,
+					      tpm_pkt_action_t pkt_act,
+					      uint32_t pbits);
+/*******************************************************************************
+* tpm_ctc_cm_set_ipv6_parse_window()
+*
+* DESCRIPTION:      Set IPv6 CnM rule parse window
+*     Two sets of IPv6 parse window:
+*       - first 24 bytes from IPv6 Header, include fields like: NH, TC, SIP
+*       - second 24 bytes from IPv6 Header, include fields like: L4 ports and DIP
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* check_level        - The check level determines to correct bad tpm rule or not in the API call
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_set_ipv6_parse_window(uint32_t owner_id,
+				     		  tpm_ctc_cm_ipv6_parse_win_t ipv6_parse_window);
+/*******************************************************************************
+* tpm_flush_vtu()
+*
+* DESCRIPTION:      Flush VTU on the Switch.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_flush_vtu(uint32_t owner_id);
+/*******************************************************************************
+* tpm_flush_atu()
+*
+* DESCRIPTION:      Flush ATU on the Switch.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* flush_type         - FLUSH all or FLUSH all dynamic
+* db_num             - ATU DB Num, only 0 should be used, since there is only one ATU DB right now.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_flush_atu(uint32_t owner_id, tpm_flush_atu_type_t flush_type, uint16_t db_num);
+
+/*******************************************************************************
+* tpm_add_mac_learn_rule()
+*
+* DESCRIPTION:      Add a PNC L2 rule for source MAC learn
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* rule_num           - Entry index to be added in the current ACL
+* queue              - GMAC1 queue send packet to
+* src_mac_addr       - MAC addr to learn
+* OUTPUTS:
+* rule_idx           - Unique rule identification number, which is used when deleting the rule.
+*                      (this is not the rule_num)
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_add_mac_learn_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr);
+
+/*******************************************************************************
+* tpm_del_mac_learn_rule()
+*
+* DESCRIPTION:      Del a PNC L2 rule for source MAC learn
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* rule_idx           - Unique rule identification number, which is used when deleting the rule.
+*                      (this is not the rule_num)
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_del_mac_learn_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr);
+
+/*******************************************************************************
+* tpm_mac_learn_default_rule_act_set()
+*
+* DESCRIPTION:      Set the action for mac learn default rule
+*
+* INPUTS:
+* owner_id           - ID of an application which requests ownership on a group of APIs.
+* mac_conf           - MAC conf determine rule action for mac learn default.
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mac_learn_default_rule_act_set(uint32_t owner_id, tpm_unknown_mac_conf_t mac_conf);
+
+/*******************************************************************************
+* tpm_mac_learn_entry_num_get()
+*
+* DESCRIPTION:      Get the mac learn entry number currently in system
+*
+* INPUTS:
+* None
+* OUTPUTS:
+* entry_num          - current MAC learn entry count in MAC_LEARN range, not including default one
+* RETURNS:
+* On success, the function returns API_OWNERSHIP_SUCCESS. On error, see tpm_api_ownership_error_t.
+*
+* COMMENTS: none
+*
+*******************************************************************************/
+tpm_error_code_t tpm_mac_learn_entry_num_get(uint32_t *entry_num);
+
+/* OLD API functions */
+#define tpm_add_l2_prim_acl_rule                            tpm_add_l2_rule
+#define tpm_add_l3_type_acl_rule                            tpm_add_l3_type_rule
+#define tpm_add_ipv4_acl_rule                               tpm_add_ipv4_rule
+#define tpm_add_ipv6_step1_acl_rule                         tpm_add_ipv6_gen_rule
+#define tpm_add_ipv6_dip_acl_rule                           tpm_add_ipv6_dip_rule
+#define tpm_add_ipv6_nh_acl_rule                            tpm_add_ipv6_nh_rule
+#define tpm_add_ipv6_l4_ports_acl_rule                      tpm_add_ipv6_l4_ports_rule
+
+#define tpm_del_l2_prim_acl_rule(owner, src, idx)           tpm_del_l2_rule(owner, idx)
+#define tpm_del_l3_type_acl_rule(owner, src, idx)           tpm_del_l3_type_rule(owner, idx)
+#define tpm_del_ipv4_acl_rule(owner, src, idx)              tpm_del_ipv4_rule(owner, idx)
+#define tpm_del_ipv6_step1_acl_rule(owner, src, idx)        tpm_del_ipv6_gen_rule(owner, idx)
+#define tpm_del_ipv6_dip_acl_rule(owner, src, idx)          tpm_del_ipv6_dip_rule(owner, idx)
+#define tpm_del_ipv6_nh_acl_rule                            tpm_del_ipv6_nh_rule
+#define tpm_del_ipv6_l4_ports_acl_rule(owner, src, idx)     tpm_del_ipv6_l4_ports_rule(owner, idx)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_common.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_common.h
new file mode 100755
index 0000000..0e938bb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_common.h
@@ -0,0 +1,91 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_common.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1.1.1
+*
+*
+*******************************************************************************/
+
+#ifndef __TPM_COMMON_TYPES_H__
+#define __TPM_COMMON_TYPES_H__
+
+#include "tpm_rtos.h"
+#include "tpm_types.h"
+#include "tpm_api.h"
+#include "tpm_internal_types.h"
+
+#endif /* __TPM_COMMON_TYPES_H__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.c
new file mode 100755
index 0000000..8aed74f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.c
@@ -0,0 +1,1015 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_api.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   Victor
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1
+*
+*
+*******************************************************************************/
+#include <linux/version.h>
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "mvOs.h"
+
+/*#define TPM_COUNTER_DEBUG_TIME*/
+
+#define IF_ERROR(ret)	\
+		if (ret != TPM_OK) {\
+			TPM_OS_ERROR(TPM_PNCL_MOD, " recvd ret_code(%d)\n", ret);\
+			return(ret);\
+		}
+
+spinlock_t tpmTcamAgingLock;
+
+static uint32_t gs_tcam_array[TPM_MAX_LU_ENTRY_NUM];
+static uint32_t gs_valid_tcam_array[TPM_MAX_LU_ENTRY_NUM];
+
+/*******************************************************************************
+* tpm_tcam_get_lu_entry()
+*
+* DESCRIPTION: The API get least used PnC rule by in specific aging couter group
+*
+* INPUTS:   group  - TCAM hit counter group number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           LU entry
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline MV_U32 tpm_tcam_get_lu_entry(int32_t group)
+{
+	unsigned long flags;
+	MV_U32 lu_entry;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* Read LU entry */
+	lu_entry = mvPncAgingLogEntryRead(group, 0);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return lu_entry;
+}
+
+/*******************************************************************************
+* tpm_tcam_set_triger()
+*
+* DESCRIPTION: The API set the triger to re-start LU scan
+*
+* INPUTS:   None
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline void tpm_tcam_set_triger(void)
+{
+	unsigned long flags;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* Set triger */
+	mvPncAgingTrigerSet();
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_tcam_get_aging_cntr()
+*
+* DESCRIPTION: The API get hit counter of specific TCAM entry
+*
+* INPUTS:   tid   - - TCAM entry number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           Hit counter
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline MV_U32 tpm_tcam_get_aging_cntr(int32_t tid)
+{
+	unsigned long flags;
+	MV_U32 hit_count;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* read aging hit counter by TID */
+	hit_count = mvPncAgingCntrRead(tid);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return hit_count;
+}
+
+/*******************************************************************************
+* tpm_tcam_clear_aging_cntr()
+*
+* DESCRIPTION: The API clear hit counter of specific TCAM entry
+*
+* INPUTS:   tid   - - TCAM entry number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           Hit counter
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline void tpm_tcam_clear_aging_cntr(int32_t tid)
+{
+	unsigned long flags;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* clear aging hit counter by TID */
+	mvPncAgingCntrClear(tid);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_tcam_clear_lu_read_flag()
+*
+* DESCRIPTION: The API clear the LU read flag to let the TCAM entries to be
+*              scaned again
+*
+* INPUTS:   tid   - TCAM entry number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline void tpm_tcam_clear_lu_read_flag(int32_t tid)
+{
+	unsigned long flags;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* Clear LU read flag */
+	mvPncAgingLuReadClear(tid);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_tcam_clear_lu_read_cntr()
+*
+* DESCRIPTION: The API clear the hit counter of LU read TCAM entry
+*
+* INPUTS:   tid   - TCAM entry number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline void tpm_tcam_clear_lu_read_cntr(int32_t tid)
+{
+	unsigned long flags;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* Clear hit counter of LU entry */
+	mvPncAgingCouterClear(tid);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_tcam_set_lu_threshold()
+*
+* DESCRIPTION: The API set the LU threshold
+*
+* INPUTS:   group - TCAM aging counter group number
+*           thesh - threshold value in packet number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline void tpm_tcam_set_lu_threshold(int32_t group, int32_t thesh)
+{
+	unsigned long flags;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* Set aging LU threshold */
+	mvPncAgingLuThreshSet(group, thesh);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_tcam_clear_lu_group()
+*
+* DESCRIPTION: The API clear the hit counter of all the TCAM entries in one group
+*
+* INPUTS:   group - TCAM aging counter group number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline void tpm_tcam_clear_lu_group(int32_t group)
+{
+	unsigned long flags;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* Clear aging counter group */
+	mvPncAgingGroupCntrClear(group);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_tcam_set_cntr_group()
+*
+* DESCRIPTION: The API set the counter group of aging counter
+*
+* INPUTS:   tid   - TCAM aging entry
+*           group - TCAM aging counter group number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+void tpm_tcam_set_cntr_group(int32_t tid, int32_t group)
+{
+	unsigned long flags;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* Set aging LU counter group */
+	mvPncAgingCntrGroupSet(tid, group);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_tcam_get_cntr_group()
+*
+* DESCRIPTION: The API get the counter group of aging counter
+*
+* INPUTS:   tid   - TCAM aging entry
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           group - TCAM aging counter group number the PNC belong to
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+MV_U32 tpm_tcam_get_cntr_group(int32_t tid)
+{
+	uint32_t w32;
+
+	/* Reading counter reg */
+	w32 = mvPncAgingCntrRead(tid);
+	w32 = (w32 & PNC_AGING_GROUP_ALL_MASK) >> PNC_AGING_GROUP_OFFS;
+
+	return w32;
+}
+
+/*******************************************************************************
+* tpm_tcam_set_lu_mask()
+*
+* DESCRIPTION: The API set the LU mask
+*
+* INPUTS:   tid   - TCAM entry number
+*           mask  - mask flag, 0: do not mask, 1:mask LU scan
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+void tpm_tcam_set_lu_mask(int32_t tid, int32_t mask)
+{
+	unsigned long flags;
+
+	/* Lock the TCAM hit counter */
+	spin_lock_irqsave(&tpmTcamAgingLock, flags);
+
+	/* Set LU scan mask */
+	mvPncAgingCntrLuMaskSet(tid, mask);
+
+	/* Unlock TCAM hit counter */
+	spin_unlock_irqrestore(&tpmTcamAgingLock, flags);
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_tcam_get_lu_mask()
+*
+* DESCRIPTION: The API get the LU mask flag
+*
+* INPUTS:   tid   - TCAM entry number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           mask flag, 0: do not mask, non-zero: mask LU scan
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+MV_U32 tpm_tcam_get_lu_mask(int32_t tid)
+{
+	uint32_t w32;
+
+	/* Reading counter reg */
+	w32 = mvPncAgingCntrRead(tid);
+	w32 &= PNC_AGING_SKIP_LU_SCAN_MASK;
+
+	return w32;
+}
+
+/*******************************************************************************
+* tpm_count_get_api_section_range_id()
+*
+* DESCRIPTION: The API get API section and PnC range ID according to API group
+*              type
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type     - TPM API group type
+*
+* OUTPUTS:
+*           api_section  - API section ID
+*           range_id     - PnC range ID
+
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_get_api_section_range_id(uint32_t owner_id,
+						    tpm_api_type_t api_type,
+						    tpm_api_sections_t *api_section,
+						    tpm_pnc_ranges_t *range_id)
+{
+	tpm_api_sections_t l_api_section;
+	tpm_pnc_ranges_t l_range_id;
+	int32_t ret_code = TPM_RC_OK;
+
+	/* Check whether the API group is supported, currently only support three types */
+	if ((api_type != TPM_API_L2_PRIM) && (api_type != TPM_API_L3_TYPE)
+	    && (api_type != TPM_API_IPV4)) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "api_type[%d] is not supported \n", api_type);
+		return ERR_GENERAL;
+	}
+
+	/* Convert to API section ID */
+	switch (api_type) {
+	case TPM_API_L2_PRIM:
+		l_api_section = TPM_L2_PRIM_ACL;
+		break;
+	case TPM_API_L3_TYPE:
+		l_api_section = TPM_L3_TYPE_ACL;
+		break;
+	case TPM_API_IPV4:
+		l_api_section = TPM_IPV4_ACL;
+		break;
+	default:
+		l_api_section = TPM_IPV4_ACL;
+		break;
+	}
+
+	/* Get PnC range ID */
+	ret_code = tpm_db_api_section_main_pnc_get(l_api_section, &l_range_id);
+	IF_ERROR(ret_code);
+
+	/* Save API section ID and PnC range ID */
+	if (api_section != NULL)
+		*api_section = l_api_section;
+	if (range_id != NULL)
+		*range_id = l_range_id;
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_count_get_pnc_lu_entry()
+*
+* DESCRIPTION: The API get least used PnC rule by in specific PnC range
+*
+* INPUTS:   owner_id        - APP owner id  should be used for all API calls
+*           api_type       - TPM API group type
+*           lu_num          - The required number of least used PnC entries
+*           lu_reset        - Whether need to reset counter after read LU
+*
+*
+* OUTPUTS:
+*           valid_num       - The valid number of least used PnC entries
+*           count_array     - The least used PnC entry index  and hit counter array
+*           unrelated_num   - The unlelated number of least used PnC entries
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_get_pnc_lu_entry(uint32_t owner_id,
+					    tpm_api_type_t api_type,
+					    uint16_t lu_num,
+					    uint8_t lu_reset,
+					    uint16_t *valid_num,
+					    tpm_api_entry_count_t *count_array,
+					    uint16_t *unrelated_num)
+{
+	tpm_api_lu_conf_t lu_conf;
+	tpm_api_sections_t api_section;
+	tpm_pnc_ranges_t range_id;
+	int16_t l_lu_num = 0;
+	uint16_t l_valid_num = 0;
+	uint16_t l_invalid_num = 0;
+	uint32_t l_rule_idx = 0;
+	uint32_t l_tcam_val = 0;
+	uint32_t l_tcam_num = 0;
+	uint32_t range_start = 0;
+	uint32_t range_end = 0;
+	uint32_t w32 = 0;
+	int32_t count_group = 0;
+	int32_t ret_code = TPM_RC_OK;
+	tpm_error_code_t tpm_ret_code = TPM_RC_OK;
+	uint32_t l_retry_time  = 0;
+#ifdef TPM_COUNTER_DEBUG_TIME
+	unsigned long t_start;
+	unsigned long t_dif;
+#endif
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "%s in, owner_id[%d], api_type[%d], lu_num[%d], lu_reset[%d]\n",
+		     __func__, owner_id, api_type, lu_num, lu_reset);
+
+	/* Get API section and PnC range ID */
+	ret_code = tpm_count_get_api_section_range_id(owner_id, api_type, &api_section, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Check the required number */
+	if (lu_num > TPM_MAX_LU_ENTRY_NUM) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "lu_num[%d] is illegal, allowed number[0~%d] \n", lu_num,
+			     TPM_MAX_LU_ENTRY_NUM);
+		return(ERR_GENERAL);
+	}
+
+	/* Get counter group number and mask all flag */
+	ret_code = tpm_db_pnc_get_lu_conf(range_id, &lu_conf);
+	IF_ERROR(ret_code);
+	count_group = lu_conf.cntr_grp;
+
+	/* Get range start number */
+	ret_code = tpm_db_pnc_rng_get_range_start_end(range_id, &range_start, &range_end);
+	IF_ERROR(ret_code);
+
+	/* Get valid LU entries */
+	memset(gs_tcam_array, 0, sizeof(gs_tcam_array));
+	memset(gs_valid_tcam_array, 0, sizeof(gs_valid_tcam_array));
+
+#ifdef TPM_COUNTER_DEBUG_TIME
+	t_start = MV_REG_READ(0xAC40C);
+#endif
+	for (l_lu_num = 0; l_lu_num < CONFIG_MV_PNC_TCAM_LINES; l_lu_num++) {
+		w32 = tpm_tcam_get_lu_entry(count_group);
+		if ((w32 & TPM_PNC_AGING_LOG_VALID_MASK) == 0) {
+			l_retry_time++;
+			if (l_retry_time > 1)
+				break;
+
+			tpm_tcam_set_triger();
+			mvOsUDelay(100);
+			if (l_lu_num > 0)
+				l_lu_num--;
+			else
+				l_lu_num = -1;
+
+			continue;
+		} else
+			l_retry_time = 0;
+
+		l_tcam_val = w32 & TPM_PNC_AGING_LOG_CNTR_IDX_MASK;
+
+		gs_tcam_array[l_tcam_num++] = l_tcam_val;
+
+		/*printk("l_tcam_val[%d], range_start[%d], range_end[%d] \n", l_tcam_val, range_start, range_end); */
+
+		/* Check whether the TCAM is in current PnC range */
+		if ((l_tcam_val < range_start) || (l_tcam_val > range_end))
+			l_invalid_num++;
+		else {
+			/* Get rule index */
+			ret_code = tpm_db_api_tcam_rule_idx_get(api_section, l_tcam_val, &l_rule_idx);
+			if (ret_code == TPM_DB_OK) {
+				/*IF_ERROR(ret_code); */
+
+				/* Save rule index, hit counter and valid TCAM index */
+				(count_array + l_valid_num)->rule_idx = l_rule_idx;
+				(count_array + l_valid_num)->hit_count = tpm_tcam_get_aging_cntr(l_tcam_val)&TPM_PNC_AGING_CNTR_MASK;
+				gs_valid_tcam_array[l_valid_num++] = l_tcam_val;
+
+				/* The required number */
+				if (l_valid_num >= lu_num)
+					break;
+			} else {
+				l_invalid_num++;
+			}
+		}
+		/* Triger LU */
+		if (!((l_tcam_num) % TPM_PNC_AGING_TID_NUM_PER_SCAN)) {
+			tpm_tcam_set_triger();
+			mvOsUDelay(100);
+		}
+	}
+
+	/* Save valid and unrelated number */
+	*valid_num = l_valid_num;
+	*unrelated_num = l_invalid_num;
+
+	/* Clear LU read flag */
+	for (l_lu_num = 0; l_lu_num < l_tcam_num; l_lu_num++)
+		tpm_tcam_clear_lu_read_flag(gs_tcam_array[l_lu_num]);
+
+	/* Reset counter if needed */
+	if (lu_reset != 0) {
+		tpm_ret_code = tpm_count_reset_pnc_age_group(owner_id, api_type);
+		if ((TPM_RC_OK != tpm_ret_code)) {
+			TPM_OS_ERROR(TPM_PNCL_MOD, "Failed to call tpm_count_reset_pnc_age_group, ret_code[%d] \n",
+				     tpm_ret_code);
+			return(ERR_GENERAL);
+		}
+/* Followings are old codes, just remain them for reference */
+/*
+	for(l_lu_num = 0; l_lu_num < l_valid_num; l_lu_num++)
+		tpm_tcam_clear_lu_read_cntr(gs_valid_tcam_array[l_lu_num]);
+*/
+	}
+
+#ifdef TPM_COUNTER_DEBUG_TIME
+	t_dif = MV_REG_READ(0xAC40C) - t_start;
+	printk(KERN_ERR "(victor) %s(%d):  %ld\n", __func__, __LINE__, t_dif);
+#endif
+	/* Debug info */
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "%s out, valid_num[%d], unrelated_num[%d]\n",
+		     __func__, *valid_num, *unrelated_num);
+	for (l_lu_num = 0; l_lu_num < *valid_num; l_lu_num++) {
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "Index[%d] rule_idx_array[%d], hit_count[%d]\n",
+			     l_lu_num, (count_array + l_lu_num)->rule_idx, (count_array + l_lu_num)->hit_count);
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_count_get_pnc_all_hit_counters
+*
+* DESCRIPTION: The API returns all PnC hit counters per API type lower than a given threshold
+*
+* INPUTS:   owner_id            - APP owner id  should be used for all API calls
+*           api_type            - TPM API group type
+*           high_thresh_pkts    - High threashold watermark, counters lower than will be returned
+*           counters_reset      - Reset API group type counters after read (0-false, 1-true)
+*           valid_counters      - The count_array size (entry number, not byte count)
+*
+* OUTPUTS:  valid_counters      - The valid number of entries copied to count_array
+*           count_array         - The PnC entries for the API type lower than high_thresh_pkts
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_get_pnc_all_hit_counters(uint32_t owner_id,
+						    tpm_api_type_t api_type,
+						    uint32_t high_thresh_pkts,
+						    uint8_t counters_reset,
+						    uint16_t *valid_counters,
+						    tpm_api_entry_count_t *count_array)
+{
+	tpm_api_sections_t api_section;
+	tpm_pnc_ranges_t   range_id;
+	uint16_t           count_array_size;
+	uint32_t           rule_idx;
+	uint32_t           tcam_val;
+	uint32_t           range_start;
+	uint32_t           range_end;
+	uint32_t           hit_counter;
+	uint16_t           cntrs_nr;
+	int32_t            ret_code;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "%s in, owner_id[%d], api_type[%d], counters_reset[%d] high_thresh_pkts[%d]\n",
+		     __func__, owner_id, api_type, counters_reset, high_thresh_pkts);
+
+	/* Get API section and PnC range ID */
+	ret_code = tpm_count_get_api_section_range_id(owner_id, api_type, &api_section, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Get range start number */
+	ret_code = tpm_db_pnc_rng_get_range_start_end(range_id, &range_start, &range_end);
+	IF_ERROR(ret_code);
+
+	if (*valid_counters > TPM_MAX_PNC_COUNTER_NUM) {
+	    TPM_OS_ERROR(TPM_PNCL_MOD, "valid_counters[%d] is illegal, allowed number[1~%d] \n",
+			    (*valid_counters), TPM_MAX_PNC_COUNTER_NUM);
+	    return(ERR_GENERAL);
+	}
+	/* save the array size */
+	count_array_size = *valid_counters;
+	cntrs_nr = 0;
+
+	/* traverse all pnc tcam lines */
+	for (tcam_val = range_start; tcam_val <= range_end; tcam_val++) {
+	/* Get rule index */
+		ret_code = tpm_db_api_tcam_rule_idx_get(api_section, tcam_val, &rule_idx);
+		if (ret_code == TPM_DB_OK) {
+			/* read counter from HW  */
+			hit_counter = tpm_tcam_get_aging_cntr(tcam_val);
+			hit_counter = (hit_counter & PNC_AGING_CNTR_MASK) >> PNC_AGING_CNTR_OFFS;
+
+			/* skip low counters */
+			if (hit_counter >= high_thresh_pkts)
+				continue;
+
+			/* Save rule index, hit counter and valid TCAM index */
+			count_array[cntrs_nr].rule_idx = rule_idx;
+			count_array[cntrs_nr].hit_count = hit_counter;
+
+			cntrs_nr++;
+
+			/* The table is full */
+			if (count_array_size == cntrs_nr)
+				break;
+		} else {
+			continue;
+		}
+	}
+
+	/* update the number of entries updated in count_array */
+	*valid_counters = cntrs_nr;
+
+	/* Reset counter if needed */
+	if (counters_reset != 0) {
+		tpm_error_code_t tpm_ret_code = tpm_count_reset_pnc_age_group(owner_id, api_type);
+
+		if (TPM_RC_OK != tpm_ret_code) {
+			TPM_OS_ERROR(TPM_PNCL_MOD, "Failed to call tpm_count_reset_pnc_age_group, ret_code[%d] \n", tpm_ret_code);
+			return(ERR_GENERAL);
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_count_set_pnc_counter_mask()
+*
+* DESCRIPTION: The API set the least used scanner ability, to mask or enable it
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type    - TPM API group type
+*           rule_idx     - The PnC rule index returned when created PnC rules
+*           lu_rule_mask - The least used scanner mask, 1: mask scanner,
+*                          0:enable scanner
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_set_pnc_counter_mask(uint32_t owner_id,
+						tpm_api_type_t api_type,
+						uint32_t rule_idx,
+						uint32_t lu_rule_mask)
+{
+	tpm_api_sections_t api_section;
+	tpm_pnc_ranges_t range_id;
+	int32_t tcam_num = 0;
+	int32_t ret_code = TPM_RC_OK;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "%s in, owner_id[%d], api_type[%d], rule_idx[%d], lu_rule_mask[%d]\n",
+		     __func__, owner_id, api_type, rule_idx, lu_rule_mask);
+
+	/* Get API section and PnC range ID */
+	ret_code = tpm_count_get_api_section_range_id(owner_id, api_type, &api_section, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Get TCAM number */
+	ret_code = tpm_db_api_tcam_num_get(api_section, rule_idx, &tcam_num);
+	IF_ERROR(ret_code);
+
+	/* Set to PnC TCAM aging counter register */
+	tpm_tcam_set_lu_mask((int32_t) tcam_num, (int32_t) lu_rule_mask);
+
+	return (TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_count_get_pnc_hit_count()
+*
+* DESCRIPTION: The API get the hit counter according to rule_idx
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type    - TPM API group type
+*           rule_idx     - The PnC rule index returned when created PnC rules
+*           hit_reset    - Should the API reset the hit counters after after reading
+*
+* OUTPUTS:
+*           rule_idx     - The hitted times of specific PnC rule
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_get_pnc_hit_count(uint32_t owner_id,
+					     tpm_api_type_t api_type,
+					     uint32_t rule_idx,
+					     uint8_t  hit_reset,
+					     uint32_t *hit_count)
+{
+	tpm_api_sections_t api_section;
+	tpm_pnc_ranges_t range_id;
+	int32_t tcam_num = 0;
+	int32_t ret_code = TPM_RC_OK;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "%s in, owner_id[%d], api_type[%d], rule_idx[%d]\n",
+		     __func__, owner_id, api_type, rule_idx);
+
+	/* Get API section and PnC range ID */
+	ret_code = tpm_count_get_api_section_range_id(owner_id, api_type, &api_section, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Get TCAM number */
+	ret_code = tpm_db_api_tcam_num_get(api_section, rule_idx, &tcam_num);
+	IF_ERROR(ret_code);
+
+	/* Set to PnC TCAM aging counter register */
+	*hit_count = tpm_tcam_get_aging_cntr((int32_t) tcam_num);
+
+	*hit_count &= TPM_PNC_AGING_CNTR_MASK;
+
+	if (hit_reset)
+		tpm_tcam_clear_aging_cntr((int32_t) tcam_num);
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "%s out, tcam_num[%d], hit_count[%d\n", __func__, tcam_num, *hit_count);
+
+	return (TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_count_set_pnc_lu_threshold()
+*
+* DESCRIPTION: The API set the theshold packets number for least used scanner
+*
+* INPUTS:   owner_id       - APP owner id  should be used for all API calls
+*           api_type      - TPM API group type
+*           lu_thresh_pkts - The theshold number(hitted packets number) to be used
+*                            for least used scanner
+*
+* OUTPUTS:
+*            None
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_set_pnc_lu_threshold(uint32_t owner_id,
+						tpm_api_type_t api_type,
+						uint32_t lu_thresh_pkts)
+{
+	tpm_api_lu_conf_t lu_conf;
+	tpm_pnc_ranges_t range_id;
+	int32_t ret_code = TPM_RC_OK;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "%s in, owner_id[%d], api_type[%d], lu_thresh_pkts[%d]\n",
+		     __func__, owner_id, api_type, lu_thresh_pkts);
+
+	/* Get PnC range ID */
+	ret_code = tpm_count_get_api_section_range_id(owner_id, api_type, NULL, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Get counter group number */
+	ret_code = tpm_db_pnc_get_lu_conf(range_id, &lu_conf);
+	IF_ERROR(ret_code);
+
+	/* Check LU threshold */
+	if (lu_thresh_pkts > TPM_MAX_LU_THRESH_VAL) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "lu_thresh_pkts[%d]is illegal, exceeds maximum value(%d)\n",
+			     lu_thresh_pkts, TPM_PNC_AGING_CNTR_MAX);
+		return (ERR_GENERAL);
+	}
+
+	tpm_tcam_set_lu_threshold(lu_conf.cntr_grp, lu_thresh_pkts);
+
+	return (TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_count_reset_pnc_age_group()
+*
+* DESCRIPTION: The API reset the hitted counter of all the PnC entries of specific
+*              group
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type    - TPM API group type
+*
+* OUTPUTS:
+*            None
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_reset_pnc_age_group(uint32_t owner_id,
+					       tpm_api_type_t api_type)
+{
+	tpm_api_lu_conf_t lu_conf;
+	tpm_pnc_ranges_t range_id;
+	int32_t ret_code = TPM_RC_OK;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "%s in, owner_id[%d], api_type[%d]\n", __func__, owner_id, api_type);
+
+	/* Get PnC range ID */
+	ret_code = tpm_count_get_api_section_range_id(owner_id, api_type, NULL, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Get counter group number */
+	ret_code = tpm_db_pnc_get_lu_conf(range_id, &lu_conf);
+	IF_ERROR(ret_code);
+
+	tpm_tcam_clear_lu_group(lu_conf.cntr_grp);
+
+	return (TPM_RC_OK);
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.h
new file mode 100755
index 0000000..b7198b4
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_counter.h
@@ -0,0 +1,338 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_api.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   Victor
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1
+*
+*
+*******************************************************************************/
+
+#ifndef _TPM_COUNTER_H_
+#define _TPM_COUNTER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TPM_PNC_AGING_CNTR_OFFS             0
+#define TPM_PNC_AGING_CNTR_MAX              0x3ffffff
+#define TPM_PNC_AGING_CNTR_MASK             (TPM_PNC_AGING_CNTR_MAX << TPM_PNC_AGING_CNTR_OFFS)
+
+#define TPM_PNC_AGING_LOG_CNTR_IDX_OFFS     0
+#define TPM_PNC_AGING_LOG_CNTR_IDX_MASK     (0x3FF << TPM_PNC_AGING_LOG_CNTR_IDX_OFFS)
+
+#define TPM_PNC_AGING_LOG_VALID_BIT         31
+#define TPM_PNC_AGING_LOG_VALID_MASK        (1 << TPM_PNC_AGING_LOG_VALID_BIT)
+
+#define TPM_PNC_AGING_TID_NUM_PER_SCAN      8
+
+/*******************************************************************************
+* tpm_tcam_set_cntr_group()
+*
+* DESCRIPTION: The API set the counter group of aging counter
+*
+* INPUTS:   tid   - TCAM aging entry
+*           group - TCAM aging counter group number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+void tpm_tcam_set_cntr_group(int32_t tid, int32_t group);
+
+/*******************************************************************************
+* tpm_tcam_get_cntr_group()
+*
+* DESCRIPTION: The API get the counter group of aging counter
+*
+* INPUTS:   tid   - TCAM aging entry
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           group - TCAM aging counter group number the PNC belong to
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+MV_U32 tpm_tcam_get_cntr_group(int32_t tid);
+
+/*******************************************************************************
+* tpm_tcam_set_lu_mask()
+*
+* DESCRIPTION: The API set the LU mask
+*
+* INPUTS:   tid   - TCAM entry number
+*           mask  - mask flag, 0: do not mask, 1:mask LU scan
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+void tpm_tcam_set_lu_mask(int32_t tid, int32_t mask);
+
+/*******************************************************************************
+* tpm_tcam_get_lu_mask()
+*
+* DESCRIPTION: The API get the LU mask flag
+*
+* INPUTS:   tid   - TCAM entry number
+*
+* OUTPUTS:
+*           None
+* RETURNS:
+*           mask flag, 0: do not mask, non-zero: mask LU scan
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+MV_U32 tpm_tcam_get_lu_mask(int32_t tid);
+
+/*******************************************************************************
+* tpm_count_get_pnc_lu_entry()
+*
+* DESCRIPTION: The API get least used PnC rule by in specific PnC range
+*
+* INPUTS:   owner_id        - APP owner id  should be used for all API calls
+*           api_type       - TPM API group type
+*           lu_num          - The required number of least used PnC entries
+*           lu_reset        - Whether need to reset counter after read LU
+*
+*
+* OUTPUTS:
+*           valid_num       - The valid number of least used PnC entries
+*           count_array     - The least used PnC entry index  and hit counter array
+*           unrelated_num   - The unlelated number of least used PnC entries
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_get_pnc_lu_entry(uint32_t owner_id,
+					    tpm_api_type_t api_type,
+					    uint16_t lu_num,
+					    uint8_t lu_reset,
+					    uint16_t *valid_num,
+					    tpm_api_entry_count_t *count_array,
+					    uint16_t *unrelated_num);
+
+/*******************************************************************************
+* tpm_count_get_pnc_all_hit_counters
+*
+* DESCRIPTION: The API returns all PnC hit counters per API type lower than a given threshold
+*
+* INPUTS:   owner_id            - APP owner id  should be used for all API calls
+*           api_type            - TPM API group type
+*           high_thresh_pkts    - High threashold watermark, counters lower than will be returned
+*           counters_reset      - Reset API group type counters after read (0-false, 1-true)
+*           valid_counters      - The count_array size (entry number, not byte count)
+*
+* OUTPUTS:  valid_counters      - The valid number of entries copied to count_array
+*           count_array         - The PnC entries for the API type lower than high_thresh_pkts
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_get_pnc_all_hit_counters(uint32_t owner_id,
+						    tpm_api_type_t api_type,
+						    uint32_t high_thresh_pkts,
+						    uint8_t counters_reset,
+						    uint16_t *valid_counters,
+						    tpm_api_entry_count_t *count_array);
+
+/*******************************************************************************
+* tpm_count_set_pnc_counter_mask()
+*
+* DESCRIPTION: The API set the least used scanner ability, to mask or enable it
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type    - TPM API group type
+*           rule_idx     - The PnC rule index returned when created PnC rules
+*           lu_rule_mask - The least used scanner mask, 1: maskscanner ,
+*                          0:enable scanner
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_set_pnc_counter_mask(uint32_t owner_id,
+						tpm_api_type_t api_type,
+						uint32_t rule_idx,
+						uint32_t lu_rule_mask);
+
+/*******************************************************************************
+* tpm_count_get_pnc_hit_count()
+*
+* DESCRIPTION: The API get the hit counter according to rule_idx
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type    - TPM API group type
+*           rule_idx     - The PnC rule index returned when created PnC rules
+*           hit_reset    - Should the API reset the hit counters after after reading
+*
+* OUTPUTS:
+*           rule_idx     - The hitted times of specific PnC rule
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_get_pnc_hit_count(uint32_t owner_id,
+					     tpm_api_type_t api_type,
+					     uint32_t rule_idx,
+					     uint8_t  hit_reset,
+					     uint32_t *hit_count);
+
+/*******************************************************************************
+* tpm_count_set_pnc_lu_threshold()
+*
+* DESCRIPTION: The API set the theshold packets number for least used scanner
+*
+* INPUTS:   owner_id       - APP owner id  should be used for all API calls
+*           api_type      - TPM API group type
+*           lu_thresh_pkts - The theshold number(hitted packets number) to be used
+*                            for least used scanner
+*
+* OUTPUTS:
+*            None
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_set_pnc_lu_threshold(uint32_t owner_id,
+						tpm_api_type_t api_type,
+						uint32_t lu_thresh_pkts);
+
+/*******************************************************************************
+* tpm_count_reset_pnc_age_group()
+*
+* DESCRIPTION: The API reset the hitted counter of all the PnC entries of specific
+*              group
+*
+* INPUTS:   owner_id     - APP owner id  should be used for all API calls
+*           api_type    - TPM API group type
+*
+* OUTPUTS:
+*            None
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_count_reset_pnc_age_group(uint32_t owner_id,
+					       tpm_api_type_t api_type);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* _TPM_COUNTER_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.c
new file mode 100755
index 0000000..1075e6b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.c
@@ -0,0 +1,552 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_cpu_port_fc.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager CPU port flow control module
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   KostaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1
+*
+*
+*******************************************************************************/
+#include <linux/version.h>
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_cpu_port_fc.h"
+
+static tpm_fc_info_t fc_info;
+
+/*******************************************************************************
+**
+**  tpm_fc_rate_limit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function periodically switches FC on/off on specific port
+**               if specific queue reaches pre-configured threshold
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void tpm_fc_rate_limit(void)
+{
+	MV_U32    queue_desc_number;
+	MV_U32    reg_val;
+
+	if (fc_info.cfg.tgt_port_changed == MV_TRUE) {
+		/* Enable FC for target port */
+		MV_U32   phy_addr = mvBoardPhyAddrGet(fc_info.cfg.tgt_port);
+
+		reg_val  = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(fc_info.cfg.tgt_port));
+		reg_val |= NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
+		reg_val |= NETA_SET_FLOW_CONTROL_MASK;
+		MV_REG_WRITE(NETA_GMAC_AN_CTRL_REG(fc_info.cfg.tgt_port), reg_val);
+
+		/* Reatart AN on target port PHY */
+		mvEthPhyRestartAN(phy_addr, 0);
+
+		fc_info.cfg.tgt_port_changed = MV_FALSE;
+	}
+
+	/* Manage FC mode on target port if needed */
+	reg_val  = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(fc_info.cfg.tgt_port));
+	reg_val &= ~ETH_TX_FC_MODE_MASK;
+
+	queue_desc_number = mvNetaTxqPendDescNumGet(fc_info.cfg.port, fc_info.cfg.tx_port, fc_info.cfg.tx_queue);
+	if (queue_desc_number >= fc_info.cfg.thresh_high)
+		reg_val |= ETH_TX_FC_SEND_PAUSE;
+	else if (queue_desc_number <= fc_info.cfg.thresh_low)
+		reg_val |= ETH_TX_FC_NO_PAUSE;
+	else
+		return;
+
+	MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(fc_info.cfg.tgt_port), reg_val);
+}
+
+/*******************************************************************************
+**
+**  tpm_fc_get_info
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns FC module configuration and statistics
+**
+**  PARAMETERS:  tpm_fc_info_t  **info
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void tpm_fc_get_info(tpm_fc_info_t **info)
+{
+	*info = &fc_info;
+}
+
+/*******************************************************************************
+**
+**  tpm_fc_clear_stat
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears FC module  statistics
+**
+**  PARAMETERS:  none
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void tpm_fc_clear_stat(void)
+{
+#ifdef TPM_FC_DEBUG
+	memset(&fc_info.stat, 0, sizeof(tpm_fc_stat_t));
+#endif
+}
+
+/*******************************************************************************
+**
+**  tpm_fc_set_config
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure Rate limiting parameters
+**
+**  PARAMETERS:  tpm_fc_cfg_t  *cfg
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void tpm_fc_set_config(tpm_fc_cfg_t *cfg)
+{
+	tpm_init_fc_params_t db_fc_conf;
+	
+	fc_info.cfg.thresh_high = cfg->thresh_high;
+	fc_info.cfg.thresh_low  = cfg->thresh_low;
+	fc_info.cfg.port        = cfg->port;
+
+	if (fc_info.cfg.tgt_port != cfg->tgt_port) {
+		fc_info.cfg.tgt_port         = cfg->tgt_port;
+		fc_info.cfg.tgt_port_changed = MV_TRUE;
+	}
+
+	fc_info.cfg.tx_port     = cfg->tx_port;
+	fc_info.cfg.tx_queue    = cfg->tx_queue;
+
+	/* update DB with new settings */
+	tpm_db_fc_conf_get(&db_fc_conf);
+	
+	db_fc_conf.port		= cfg->tx_port;
+	db_fc_conf.tgt_port 	= cfg->tgt_port;
+	db_fc_conf.thresh_high 	= cfg->thresh_high;
+	db_fc_conf.thresh_low 	= cfg->thresh_low;
+	db_fc_conf.tx_port	= cfg->tx_port; 
+	db_fc_conf.tx_queue	= cfg->tx_queue;
+
+	tpm_db_fc_conf_set(&db_fc_conf);
+}
+
+/*******************************************************************************
+**
+**  tpm_fc_set_period
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure Rate limiting parameters
+**
+**  PARAMETERS:  MV_U32 us_period
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+MV_STATUS tpm_fc_set_period(MV_U32 us_period)
+{
+	MV_U32 ns_period = us_period * 1000;
+	tpm_init_fc_params_t db_fc_conf;
+	
+	if (ns_period < us_period)
+		return (MV_ERROR);
+
+	/* update DB entry */
+	tpm_db_fc_conf_get(&db_fc_conf);
+       db_fc_conf.queue_sample_freq = us_period;
+	tpm_db_fc_conf_set(&db_fc_conf);
+
+	fc_info.cfg.hrt_hit_time = ktime_set(0, ns_period);
+
+	return (MV_OK);
+}
+
+#ifdef TPM_FC_DEBUG
+/*******************************************************************************
+**
+**  tpm_fc_set_oneshot
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure oneshot counter value
+**
+**  PARAMETERS:  MV_U32 oneshot
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+MV_STATUS tpm_fc_set_oneshot(MV_U32 oneshot)
+{
+	fc_info.cfg.oneshot_count = oneshot;
+
+	return (MV_OK);
+}
+#endif
+
+/*******************************************************************************
+**
+**  tpm_fc_hr_timer_handler
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: PON periodic high resolution timer handler
+**
+**  PARAMETERS:  none
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     hr_timer_RESTART
+**
+*******************************************************************************/
+static enum hrtimer_restart tpm_fc_hr_timer_handler(struct hrtimer *timer)
+{
+	ktime_t current_time    = timer->base->get_time();
+	s64     current_time_ns = ktime_to_ns(current_time);
+	s64     last_hit_ns     = ktime_to_ns(fc_info.hrt_last_hit);
+	s64     time_slip_ns;
+	s64     hit_time_ns     = ktime_to_ns(fc_info.cfg.hrt_hit_time);
+
+#ifdef TPM_FC_DEBUG
+	fc_info.stat.hrt_hits_num++;
+	if ((fc_info.cfg.oneshot_count != 0) && (fc_info.oneshot_stat.hrt_hits_num < fc_info.cfg.oneshot_count))
+		fc_info.oneshot_stat.hrt_hits_num++;
+#endif
+
+	/* Update timer for the next hit at the beginning for better precision */
+	hrtimer_forward(timer, current_time, fc_info.cfg.hrt_hit_time);
+
+	/* First compute the real timer period */
+	time_slip_ns = current_time_ns - last_hit_ns;
+
+	if (time_slip_ns < 0) {
+#ifdef TPM_FC_DEBUG
+		fc_info.stat.hrt_wraparound++;
+		if ((fc_info.cfg.oneshot_count != 0) && (fc_info.oneshot_stat.hrt_hits_num < fc_info.cfg.oneshot_count))
+			fc_info.oneshot_stat.hrt_wraparound++;
+#endif
+		time_slip_ns = KTIME_MAX - last_hit_ns + current_time_ns;
+	}
+
+	/* Update last hit with the current time */
+	fc_info.hrt_last_hit = current_time;
+
+#ifdef TPM_FC_DEBUG
+	if (fc_info.pre_stat_cnt) {
+		fc_info.pre_stat_cnt--;
+
+		/* Flow Control the port */
+		tpm_fc_rate_limit();
+		
+		return (HRTIMER_RESTART);
+	}
+#endif
+
+	/* Calculate the slip from the requested time period */
+	time_slip_ns -= hit_time_ns;
+
+#ifdef TPM_FC_DEBUG
+	/* Collect more statistics */
+	if (time_slip_ns != 0) {
+
+		/* Total counters */
+		fc_info.stat.hrt_lost_num++;
+
+		if (time_slip_ns > fc_info.stat.hrt_lost_max_ns)
+			fc_info.stat.hrt_lost_max_ns = time_slip_ns;
+
+		if (time_slip_ns >= (hit_time_ns << 1))
+			fc_info.stat.hrt_lost_200_up++;
+		else if (time_slip_ns >= (hit_time_ns + (hit_time_ns >> 1)))
+			fc_info.stat.hrt_lost_150_200++;
+		else if (time_slip_ns >= hit_time_ns)
+			fc_info.stat.hrt_lost_100_150++;
+		else if (time_slip_ns >= (hit_time_ns >> 1))
+			fc_info.stat.hrt_lost_50_100++;
+		else if (time_slip_ns >= (hit_time_ns >> 2))
+			fc_info.stat.hrt_lost_25_50++;
+		else
+			fc_info.stat.hrt_lost_25_less++;
+
+		/* One-shot counters */
+		if ((fc_info.cfg.oneshot_count != 0) && (fc_info.oneshot_stat.hrt_hits_num < fc_info.cfg.oneshot_count)) {
+			fc_info.oneshot_stat.hrt_lost_num++;
+
+			if (time_slip_ns > fc_info.oneshot_stat.hrt_lost_max_ns)
+				fc_info.oneshot_stat.hrt_lost_max_ns = time_slip_ns;
+			
+			if (time_slip_ns >= (hit_time_ns << 1))
+				fc_info.oneshot_stat.hrt_lost_200_up++;
+			else if (time_slip_ns >= (hit_time_ns + (hit_time_ns >> 1)))
+				fc_info.oneshot_stat.hrt_lost_150_200++;
+			else if (time_slip_ns >= hit_time_ns)
+				fc_info.oneshot_stat.hrt_lost_100_150++;
+			else if (time_slip_ns >= (hit_time_ns >> 1))
+				fc_info.oneshot_stat.hrt_lost_50_100++;
+			else if (time_slip_ns >= (hit_time_ns >> 2))
+				fc_info.oneshot_stat.hrt_lost_25_50++;
+			else
+				fc_info.oneshot_stat.hrt_lost_25_less++;
+		}
+	}
+#endif
+
+	/* Flow Control the port */
+	tpm_fc_rate_limit();
+
+	return (HRTIMER_RESTART);
+}
+
+
+/*******************************************************************************
+**
+**  tpm_fc_enable
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable the SW Flow-Control
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+MV_STATUS tpm_fc_enable(MV_BOOL enable)
+{
+	MV_BOOL fc_is_running = tpm_fc_is_running();
+	tpm_init_fc_params_t db_fc_conf;
+	MV_BOOL config_change = false;
+
+	if (MV_FALSE == enable)
+	{
+		/* Disable FC for target port if mode changed */
+		if (true == fc_is_running) {
+			MV_U32  phy_addr = mvBoardPhyAddrGet(fc_info.cfg.tgt_port);
+			MV_U32	reg_val;
+			
+			hrtimer_cancel(&fc_info.hr_timer);
+			
+			reg_val  = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(fc_info.cfg.tgt_port));
+			reg_val |= NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
+			reg_val &= ~NETA_SET_FLOW_CONTROL_MASK;
+			MV_REG_WRITE(NETA_GMAC_AN_CTRL_REG(fc_info.cfg.tgt_port), reg_val);
+
+			/* Reatart AN on target port PHY */
+			mvEthPhyRestartAN(phy_addr, 0);
+
+			/* set FC not running indication */
+			fc_info.magic = 0;
+			config_change = true;
+		}
+		
+#ifdef TPM_FC_DEBUG
+		fc_info.cfg.oneshot_count = 0;
+#endif
+	}
+	else
+	{
+		if (false == fc_is_running){
+#ifdef TPM_FC_DEBUG
+			/* clear up statistics */
+			memset(&fc_info.oneshot_stat, 0, sizeof(tpm_fc_stat_t));
+			memset(&fc_info.stat, 0, sizeof(tpm_fc_stat_t));
+			fc_info.pre_stat_cnt = 64;
+#endif
+			/* force port setting */
+			fc_info.cfg.tgt_port_changed = MV_TRUE;
+
+			/* set FC running indication */
+			fc_info.magic = TPM_FC_MAGIC_NUMBER;
+			
+			/* save the current time in the last hit */
+			fc_info.hrt_last_hit = ktime_get_real();
+			hrtimer_init(&fc_info.hr_timer, CLOCK_REALTIME, HRTIMER_MODE_REL);
+			fc_info.hr_timer.function = &tpm_fc_hr_timer_handler;
+			hrtimer_start(&fc_info.hr_timer, fc_info.cfg.hrt_hit_time, HRTIMER_MODE_REL);
+
+			config_change = true;
+		}
+	}
+
+	if (config_change) {
+		/* update current DB settings */
+		tpm_db_fc_conf_get(&db_fc_conf);
+		db_fc_conf.enabled = (enable == MV_TRUE) ? 1 : 0;
+		tpm_db_fc_conf_set(&db_fc_conf);
+	}
+
+
+	return (MV_OK);
+}
+
+/*******************************************************************************
+**
+**  tpm_fc_is_running
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Return the running status of FC engine
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     MV_TRUE/MV_FALSE
+**
+*******************************************************************************/
+MV_BOOL tpm_fc_is_running(void)
+{
+	if (fc_info.magic == TPM_FC_MAGIC_NUMBER)
+		return(MV_TRUE);
+	else
+		return(MV_FALSE);
+}
+
+/*******************************************************************************
+**
+**  tpm_fc_engine_init
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Init fc engine
+**
+**  PARAMETERS:  MV_U32           us_period
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     MV_OK/MV_ERROR
+**
+*******************************************************************************/
+int32_t tpm_fc_engine_init(void)
+{
+	tpm_init_fc_params_t 	db_fc_conf;
+	MV_U32 			ns_q_sample_freq;
+	MV_BOOL			fc_is_running;
+
+	/* save the current state, for runtime MIB reset */
+	fc_is_running = tpm_fc_is_running();
+
+	/* get current DB settings */
+	tpm_db_fc_conf_get(&db_fc_conf);
+
+	/* FC was enabled before MIB reset */
+	if (fc_is_running) {
+		TPM_OS_DEBUG(TPM_MTU_MOD, "SW port FC disabled!\n");
+		tpm_fc_enable(MV_FALSE);
+	}
+	
+	memset(&fc_info, 0, sizeof(tpm_fc_info_t));
+	
+	ns_q_sample_freq = db_fc_conf.queue_sample_freq * 1000;
+
+	if (ns_q_sample_freq < db_fc_conf.queue_sample_freq)
+		return (MV_ERROR);
+
+	fc_info.cfg.hrt_hit_time	= ktime_set(0, ns_q_sample_freq);
+	fc_info.cfg.thresh_high		= db_fc_conf.thresh_high;
+	fc_info.cfg.thresh_low		= db_fc_conf.thresh_low;
+	fc_info.cfg.port		= db_fc_conf.port;
+	fc_info.cfg.tgt_port		= db_fc_conf.tgt_port;
+	fc_info.cfg.tgt_port_changed	= MV_TRUE;
+
+#ifdef TPM_FC_DEBUG
+	fc_info.cfg.oneshot_count = 0;
+#endif
+
+	if (db_fc_conf.enabled){
+		TPM_OS_DEBUG(TPM_MTU_MOD, "SW port FC enabled!\n");
+		tpm_fc_enable(MV_TRUE);
+	}
+
+	return MV_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.h
new file mode 100755
index 0000000..64e833f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_cpu_port_fc.h
@@ -0,0 +1,278 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_ctc_cm.h
+*
+* DESCRIPTION:
+*               header file for tpm_cpu_port_fc.c
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   KostaP
+*
+* DATE CREATED: 6 June 2012
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1
+*
+*
+*******************************************************************************/
+#ifndef _TPM_CPU_PORT_FC_H_
+#define _TPM_CPU_PORT_FC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+#define TPM_FC_MAGIC_NUMBER		0xFCFACED
+#define TPM_FC_DEBUG
+
+typedef struct tpm_fc_cfg_t_ {
+	MV_U32   thresh_high;
+	MV_U32   thresh_low;
+	MV_U32   port;
+	MV_U32   tgt_port;
+	MV_BOOL  tgt_port_changed;
+	MV_U32   tx_port;
+	MV_U32   tx_queue;
+	ktime_t  hrt_hit_time;
+	ktime_t  hrt_hit_time_delay;
+	MV_U32   oneshot_count;
+
+} tpm_fc_cfg_t;
+
+#ifdef  TPM_FC_DEBUG
+typedef struct tpm_fc_stat_t_ {
+	MV_U32   hrt_hits_num;
+	MV_U32   hrt_lost_num;
+	MV_U32   hrt_wraparound;
+	s64      hrt_lost_max_ns;
+	s64      hrt_lost_200_up;  /* timer slips 200% and more than set time */
+	s64      hrt_lost_150_200; /* timer slips 150%-200% out of set time */
+	s64      hrt_lost_100_150; /* timer slips 100%-150% out of set time */
+	s64      hrt_lost_50_100;  /* timer slips 50%-100% out of set time */
+	s64      hrt_lost_25_50;   /* timer slips 25%-50% out of set time */
+	s64      hrt_lost_25_less; /* timer slips less than 25% out of set time */
+} tpm_fc_stat_t;
+#endif
+
+typedef struct tpm_fc_info_t_ {
+	tpm_fc_cfg_t    cfg;
+	MV_U32          magic;
+	struct hrtimer  hr_timer;
+	ktime_t  	hrt_last_hit;
+#ifdef  TPM_FC_DEBUG
+	tpm_fc_stat_t   stat;
+	tpm_fc_stat_t   oneshot_stat;
+	ktime_t  	oneshot_hrt_last_hit;
+	MV_U32      	pre_stat_cnt;
+#endif	
+} tpm_fc_info_t;
+
+/*******************************************************************************
+**
+**  tpm_fc_set_period
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure Rate limiting parameters
+**
+**  PARAMETERS:  MV_U32 us_period
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+MV_STATUS tpm_fc_set_period(MV_U32 us_period);
+
+/*******************************************************************************
+**
+**  tpm_fc_set_config
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure Rate limiting parameters
+**
+**  PARAMETERS:  tpm_fc_cfg_t  *cf
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void tpm_fc_set_config(tpm_fc_cfg_t *cfg);
+
+/*******************************************************************************
+**
+**  tpm_fc_set_oneshot
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure oneshot counter value
+**
+**  PARAMETERS:  MV_U32 oneshot
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+MV_STATUS tpm_fc_set_oneshot(MV_U32 oneshot);
+
+/*******************************************************************************
+**
+**  tpm_fc_enable
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure oneshot counter value
+**
+**  PARAMETERS:  MV_U32 oneshot
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+MV_STATUS tpm_fc_enable(MV_BOOL enable);
+
+
+/*******************************************************************************
+**
+**  tpm_fc_get_info
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns FC module configuration and statistics
+**
+**  PARAMETERS:  tpm_fc_info_t  **info
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void tpm_fc_get_info(tpm_fc_info_t **info);
+
+/*******************************************************************************
+**
+**  tpm_fc_clear_stat
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clears FC module  statistics
+**
+**  PARAMETERS:  none
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     void
+**
+*******************************************************************************/
+void tpm_fc_clear_stat(void);
+
+/*******************************************************************************
+**
+**  tpm_fc_engine_init
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Init fc engine
+**
+**  PARAMETERS:  none
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     MV_OK/MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS tpm_fc_engine_init(void);
+
+/*******************************************************************************
+**
+**  tpm_fc_is_running
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Return the running status of FC engine
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     none
+**
+**  RETURNS:     MV_TRUE/MV_FALSE
+**
+*******************************************************************************/
+MV_BOOL tpm_fc_is_running(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif    /* _TPM_CPU_PORT_FC_H_ */
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.c
new file mode 100755
index 0000000..e87c85f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.c
@@ -0,0 +1,787 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_ctc_cm.c
+*
+*
+*  MODULE : TPM
+*
+*  DESCRIPTION : This file config CTC CnM rule
+*
+*  MODIFICATION HISTORY:
+*           7Feb12   jinghua - initial version created.
+*
+* FILE REVISION NUMBER:
+*       Revision: 1.12
+*******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_ctc_cm.h"
+#include "tpm_pkt_proc_logic.h"
+
+#define IF_ERROR(ret)		\
+	if (ret != TPM_OK) {\
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, " recvd ret_code(%d)\n", ret);\
+		return(ret);\
+	}
+
+/*******************************************************************************
+* tpm_ctc_cm_rule_add()
+*
+* DESCRIPTION:    Main function for adding CnM API rule.
+*
+* INPUTS:
+* ipv4_key_idx       - key for IPv4 sub pattern.
+* Other inputs/outputs are same as API call
+*
+* OUTPUTS:
+* rule_index         - CTC CnM rule index
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_rule_add(uint32_t owner_id,
+				     tpm_src_port_type_t src_port,
+				     uint32_t precedence,
+				     tpm_parse_fields_t l2_parse_rule_bm,
+				     tpm_parse_fields_t ipv4_parse_rule_bm,
+				     tpm_parse_fields_t ipv6_parse_rule_bm,
+				     tpm_l2_acl_key_t   *l2_key,
+				     tpm_ipv4_acl_key_t *ipv4_key,
+				     tpm_ipv6_acl_key_t *ipv6_key,
+				     tpm_pkt_frwd_t *pkt_frwd,
+				     tpm_pkt_action_t pkt_act,
+				     uint32_t pbits,
+				     uint32_t ipv4_key_idx,
+				     uint32_t *rule_index)
+{
+	tpm_error_code_t ret_code = ERR_GENERAL;
+
+	if (l2_parse_rule_bm)
+		ret_code = tpm_proc_add_l2_cnm_rule(owner_id, src_port, precedence, l2_parse_rule_bm, l2_key,
+						    ipv4_key_idx, pkt_frwd, pkt_act, pbits, rule_index);
+	else if (ipv4_parse_rule_bm)
+		ret_code = tpm_proc_add_ipv4_cnm_rule(owner_id, src_port, precedence, ipv4_parse_rule_bm,
+						      ipv4_key, pkt_frwd, pkt_act, pbits, rule_index);
+	else if (ipv6_parse_rule_bm)
+		ret_code = tpm_proc_add_ipv6_cnm_rule(owner_id, src_port, precedence, ipv6_parse_rule_bm,
+						      ipv6_key, pkt_frwd, pkt_act, pbits, rule_index);
+	return ret_code;
+}
+
+/*******************************************************************************
+* tpm_ctc_cm_acl_rule_del()
+*
+* DESCRIPTION:    Main function for deleting CnM API rule.
+*
+* INPUTS:
+*
+* owner_id           - APP owner id  should be used for all API calls.
+* cm_rule            - CTC CnM rule data pointer
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_rule_del(uint32_t owner_id, tpm_db_ctc_cm_rule_entry_t  *cm_rule)
+{
+	tpm_error_code_t ret_code = ERR_GENERAL;
+
+	if ((cm_rule)->l2_parse_rule_bm)
+		ret_code = tpm_proc_del_l2_cnm_rule(owner_id, cm_rule->cm_main_rule_index);
+	else if ((cm_rule)->ipv4_parse_rule_bm)
+		ret_code = tpm_proc_del_ipv4_cnm_rule(owner_id, cm_rule->cm_main_rule_index);
+	else if ((cm_rule)->ipv6_parse_rule_bm)
+		ret_code = tpm_proc_del_ipv4_cnm_rule(owner_id, cm_rule->cm_main_rule_index);
+
+	return ret_code;
+}
+/*******************************************************************************
+* tpm_ctc_cm_add_rule_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_ctc_cm_acl_rule_add params.
+*
+* INPUTS:
+*                 - See tpm_ctc_cm_acl_rule_add
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_add_rule_check(uint32_t owner_id,
+					   tpm_src_port_type_t src_port,
+					   uint32_t precedence,
+					   tpm_parse_fields_t l2_parse_rule_bm,
+					   tpm_parse_fields_t ipv4_parse_rule_bm,
+					   tpm_parse_fields_t ipv6_parse_rule_bm,
+					   tpm_l2_acl_key_t *l2_key,
+					   tpm_ipv4_acl_key_t *ipv4_key,
+					   tpm_ipv6_acl_key_t *ipv6_key,
+					   tpm_pkt_frwd_t *pkt_frwd,
+					   tpm_pkt_action_t pkt_act,
+					   uint32_t pbits)
+{
+	int32_t int_ret_code;
+	uint32_t num_rules, dummy_entry = 0;
+	uint8_t is_range_full;
+	tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
+	tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win;
+
+	tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
+
+	/* if CTC CnM enabled */
+	if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "CTC CnM is disabled!\n");
+		return(ERR_GENERAL);
+	}
+
+	if (src_port < TPM_SRC_PORT_UNI_0 || src_port > TPM_SRC_PORT_UNI_VIRT) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "src_port (%d) illegal!\n", src_port);
+		return(ERR_SRC_PORT_INVALID);
+	}
+
+	if (!tpm_db_eth_port_valid(src_port)) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "src_port (%d) illegal!\n", src_port);
+		return(ERR_SRC_PORT_INVALID);
+	}
+
+	if (precedence >= TPM_MAX_NUM_CTC_PRECEDENCE) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "precedence (%d) illegal!\n", precedence);
+		return(ERR_CTC_CM_PREC_INVALID);
+	}
+
+	num_rules = tpm_db_ctc_cm_get_num_rules(src_port);
+	if (precedence > num_rules) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "precedence (%d) must be continous!\n", precedence);
+		return(ERR_CTC_CM_PREC_INVALID);
+	}
+
+	if (!l2_parse_rule_bm && !ipv4_parse_rule_bm && !ipv6_parse_rule_bm) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "both l2_parse_rule_bm and ipv4_parse_rule_bm are Zero!\n");
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	if (l2_parse_rule_bm & ~(TPM_L2_PARSE_MAC_DA | TPM_L2_PARSE_MAC_SA | TPM_L2_PARSE_ONE_VLAN_TAG |
+				 TPM_L2_PARSE_ETYPE)) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "l2_parse_rule_bm (%d) is invalid!\n", l2_parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	if (ipv4_parse_rule_bm & ~(TPM_IPv4_PARSE_SIP | TPM_IPv4_PARSE_DIP | TPM_IPv4_PARSE_DSCP |
+				   TPM_IPv4_PARSE_PROTO | TPM_PARSE_L4_SRC | TPM_PARSE_L4_DST)) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv4_parse_rule_bm (%d) is invalid!\n", ipv4_parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* ipv6_parse_rule_bm depends on ipv6 CnM parse window */
+	tpm_db_ctc_cm_ipv6_parse_win_get(&ctc_cm_ipv6_parse_win);
+	if(TPM_CTC_CM_IPv6_FIRST_24B == ctc_cm_ipv6_parse_win) {
+		if (ipv6_parse_rule_bm & ~(TPM_IPv6_PARSE_SIP | TPM_IPv6_PARSE_DSCP | TPM_IPv6_PARSE_NH |
+					   TPM_IPv6_PARSE_HOPL)) {
+			TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv6_parse_rule_bm (%d) is invalid!\n", ipv6_parse_rule_bm);
+			return(ERR_PARSE_MAP_INVALID);
+		}
+	} else {
+		if (ipv6_parse_rule_bm & ~(TPM_IPv6_PARSE_DIP | TPM_PARSE_L4_SRC | TPM_PARSE_L4_DST)) {
+			TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv6_parse_rule_bm (%d) is invalid!\n", ipv6_parse_rule_bm);
+			return(ERR_PARSE_MAP_INVALID);
+		}
+	}
+
+	if (l2_parse_rule_bm && (NULL == l2_key)) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "l2_key can not be NULL!\n");
+		return(ERR_NULL_POINTER);
+	}
+
+	if (ipv4_parse_rule_bm && (NULL == ipv4_key)) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv4_key can not be NULL!\n");
+		return(ERR_NULL_POINTER);
+	}
+
+	if (ipv6_parse_rule_bm && (NULL == ipv6_key)) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "ipv6_key can not be NULL!\n");
+		return(ERR_NULL_POINTER);
+	}
+
+	if (!pkt_act) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "pkt_act is Zero!\n");
+		return(ERR_ACTION_INVALID);
+	}
+
+	if ((pkt_act & (TPM_ACTION_SET_TARGET_PORT | TPM_ACTION_SET_TARGET_QUEUE)) &&
+		(NULL == pkt_frwd)) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "pkt_frwd is NULL when TPM_ACTION_SET_TARGET_PORT or"
+					     " TPM_ACTION_SET_TARGET_QUEUE!\n");
+		return(ERR_NULL_POINTER);
+	}
+
+	if (pkt_frwd->trg_port < TPM_TRG_PORT_WAN || pkt_frwd->trg_port > TPM_TRG_LLID_7) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "trg_port (%d) is invalid!\n", pkt_frwd->trg_port);
+		return(ERR_FRWD_INVALID);
+	}
+
+	if (pkt_act & ~(TPM_ACTION_SET_TARGET_PORT | TPM_ACTION_SET_TARGET_QUEUE | TPM_ACTION_SET_PKT_MOD)) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "pkt_act (%d) is invalid!\n", pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	if (pkt_act & TPM_ACTION_SET_PKT_MOD) {
+		if (pbits > 7) {
+			TPM_OS_ERROR(TPM_CTC_CM_MOD, "pbits (%d) is invalid!\n", pbits);
+			return(ERR_L2_KEY_INVALID);
+		}
+
+		int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pbits, &dummy_entry);
+		if (int_ret_code != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " unsupported p-bit value: %d\n", pbits);
+			return(ERR_MOD_INVALID);
+		}
+	}
+
+	if (l2_parse_rule_bm && ipv4_parse_rule_bm) {
+		is_range_full = tpm_proc_if_ipv4_pre_range_is_full(src_port, ipv4_parse_rule_bm, ipv4_key);
+		if (is_range_full != TPM_FALSE) {
+			TPM_OS_ERROR(TPM_CTC_CM_MOD, "not enough room for new ipv4 pre-filter key!\n");
+			return(ERR_OUT_OF_RESOURCES);
+		}
+	}
+
+	is_range_full = tpm_proc_if_cnm_main_range_is_full(src_port, precedence);
+	if (is_range_full != TPM_FALSE) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "not enough room for new cnm rule!\n");
+		return(ERR_OUT_OF_RESOURCES);
+	}
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_ctc_cm_acl_rule_add()
+*
+* DESCRIPTION:    Main function for adding CnM API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_acl_rule_add(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint32_t precedence,
+					 tpm_parse_fields_t l2_parse_rule_bm,
+					 tpm_parse_fields_t ipv4_parse_rule_bm,
+					 tpm_parse_fields_t ipv6_parse_rule_bm,
+					 tpm_l2_acl_key_t *l2_key,
+					 tpm_ipv4_acl_key_t *ipv4_key,
+					 tpm_ipv6_acl_key_t *ipv6_key,
+					 tpm_pkt_frwd_t *pkt_frwd,
+					 tpm_pkt_action_t pkt_act,
+					 uint32_t pbits)
+{
+	tpm_error_code_t            ret_code;
+	tpm_db_error_t              db_ret;
+	tpm_db_ctc_cm_rule_entry_t  cm_rule;
+	uint32_t                    ipv4_sub_pattern_key_idx = TPM_CNM_INVALID_IPV4_PRE_FILTER_KEY_ID;
+	uint32_t                    rule_index;
+	uint32_t                    rule_index_tmp;
+	uint32_t                    num_prec;
+	int32_t                     loop;
+	int32_t                     prece_tmp;
+
+	/* Check parameters */
+	ret_code = tpm_ctc_cm_add_rule_check(owner_id, src_port, precedence, l2_parse_rule_bm, ipv4_parse_rule_bm,
+					     ipv6_parse_rule_bm, l2_key, ipv4_key, ipv6_key, pkt_frwd, pkt_act, pbits);
+	IF_ERROR(ret_code);
+
+	/* add IPv4_Pre of Combo rule */
+	if (l2_parse_rule_bm && ipv4_parse_rule_bm) {
+		ret_code = tpm_proc_add_cnm_ipv4_pre_filter_key(owner_id, src_port, ipv4_parse_rule_bm, ipv4_key,
+								&ipv4_sub_pattern_key_idx);
+		IF_ERROR(ret_code);
+	}
+
+	/* insert new rule */
+	ret_code = tpm_ctc_cm_rule_add(owner_id, src_port, precedence, l2_parse_rule_bm, ipv4_parse_rule_bm,
+				       ipv6_parse_rule_bm, l2_key, ipv4_key, ipv6_key, pkt_frwd, pkt_act, pbits,
+				       ipv4_sub_pattern_key_idx, &rule_index);
+	IF_ERROR(ret_code);
+
+	/* update existing rules if needed */
+	num_prec = tpm_db_ctc_cm_get_num_rules(src_port);
+
+	/* from the lowest precedence to current precedence, decreased by 1 */
+	for (loop = num_prec; loop > precedence; loop--) {
+
+		prece_tmp = loop - 1;
+		db_ret = tpm_db_ctc_cm_rule_get(src_port, prece_tmp, &cm_rule);
+		if (TPM_DB_OK != db_ret) {
+			TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
+			return ERR_CTC_CM_DB_ERR;
+		}
+
+		/* first remvoe the old one, then add the new one  */
+		ret_code = tpm_ctc_cm_rule_del(owner_id, &cm_rule);
+		IF_ERROR(ret_code);
+
+		/* last prece is 7, do not need to add the rule which has just
+		 * been remvoed.
+		 */
+		if ((TPM_MAX_NUM_CTC_PRECEDENCE - 1) == prece_tmp)
+			continue;
+
+		/* add this rule with prece++ */
+		ret_code = tpm_ctc_cm_rule_add(owner_id, src_port, prece_tmp + 1, cm_rule.l2_parse_rule_bm,
+					       cm_rule.ipv4_parse_rule_bm, cm_rule.ipv6_parse_rule_bm,
+					       &(cm_rule.l2_key), &(cm_rule.ipv4_key), &(cm_rule.ipv6_key),
+					       &(cm_rule.pkt_frwd), (cm_rule.pkt_act), cm_rule.pbits,
+					       cm_rule.ipv4_sub_pattern_key, &rule_index_tmp);
+		IF_ERROR(ret_code);
+
+		/* overwrite DB entry of lower precedence */
+		db_ret = tpm_db_ctc_cm_rule_set(src_port, prece_tmp + 1, cm_rule.l2_parse_rule_bm,
+						cm_rule.ipv4_parse_rule_bm, cm_rule.ipv6_parse_rule_bm,
+						&(cm_rule.l2_key), &(cm_rule.ipv4_key), &(cm_rule.ipv6_key),
+						&(cm_rule.pkt_frwd), (cm_rule.pkt_act),
+						cm_rule.pbits, cm_rule.ipv4_sub_pattern_key, rule_index_tmp);
+		if (TPM_DB_OK != db_ret) {
+			TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
+			return ERR_CTC_CM_DB_ERR;
+		}
+
+	}
+
+	/* set db of this CnM rule */
+	db_ret = tpm_db_ctc_cm_rule_set(src_port, precedence, l2_parse_rule_bm, ipv4_parse_rule_bm,
+					ipv6_parse_rule_bm, l2_key, ipv4_key,
+					ipv6_key, pkt_frwd, pkt_act, pbits,
+					ipv4_sub_pattern_key_idx, rule_index);
+	if (TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
+		return ERR_CTC_CM_DB_ERR;
+	}
+
+	return TPM_RC_OK;
+}
+/*******************************************************************************
+* tpm_ctc_cm_del_rule_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_ctc_cm_del_rule_check params.
+*
+* INPUTS:
+*                 - See tpm_ctc_cm_del_rule_check
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_del_rule_check(uint32_t owner_id,
+					   tpm_src_port_type_t src_port,
+					   uint32_t precedence)
+{
+	tpm_db_error_t   db_ret;
+	tpm_db_ctc_cm_rule_entry_t    cm_rule;
+	tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
+
+	tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
+
+	/* if CTC CnM enabled */
+	if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "CTC CnM is disabled!\n");
+		return(ERR_GENERAL);
+	}
+
+	if (src_port < TPM_SRC_PORT_UNI_0 || src_port > TPM_SRC_PORT_UNI_VIRT) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "src_port (%d) illegal!\n", src_port);
+		return(ERR_SRC_PORT_INVALID);
+	}
+
+	if (precedence >= TPM_MAX_NUM_CTC_PRECEDENCE) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "precedence (%d) illegal!\n", precedence);
+		return(ERR_CTC_CM_PREC_INVALID);
+	}
+
+	db_ret = tpm_db_ctc_cm_rule_get(src_port, precedence, &cm_rule);
+	if (TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "get DB failed, ret_code: (%d), src_port: (%d), precedence: (%d)\n",
+			 db_ret, src_port, precedence);
+		return(ERR_CTC_CM_DB_ERR);
+	}
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_ctc_cm_acl_rule_del()
+*
+* DESCRIPTION:    Main function for deleting CnM API rule.
+*
+* INPUTS:
+*		  All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_acl_rule_del(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint32_t precedence)
+{
+	tpm_error_code_t ret_code;
+	tpm_db_error_t   db_ret;
+	tpm_db_ctc_cm_rule_entry_t  cm_rule;
+	uint32_t                    rule_index;
+	uint32_t                    num_prec;
+	uint32_t                    loop;
+
+	/* Check parameters */
+	ret_code = tpm_ctc_cm_del_rule_check(owner_id, src_port, precedence);
+	IF_ERROR(ret_code);
+
+	db_ret = tpm_db_ctc_cm_rule_get(src_port, precedence, &cm_rule);
+	if (TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "get DB failed, ret_code: (%d), src_port: (%d), precedence: (%d)\n",
+			     db_ret, src_port, precedence);
+		return(ERR_CTC_CM_DB_ERR);
+	}
+
+	/* remove rule */
+	ret_code = tpm_ctc_cm_rule_del(owner_id, &cm_rule);
+	IF_ERROR(ret_code);
+
+	/* remove IPv4_Pre of Combo rule */
+	if (cm_rule.l2_parse_rule_bm && cm_rule.ipv4_parse_rule_bm) {
+		ret_code = tpm_proc_del_cnm_ipv4_pre_filter_key(owner_id, src_port, cm_rule.ipv4_sub_pattern_key);
+		IF_ERROR(ret_code);
+	}
+
+	/* update existing rules if needed */
+	num_prec = tpm_db_ctc_cm_get_num_rules(src_port);
+
+	/* from the next lower-to current precedence to the lowest precedence, increased by 1 */
+	for (loop = precedence + 1; loop < num_prec; loop++) {
+
+		db_ret = tpm_db_ctc_cm_rule_get(src_port, loop, &cm_rule);
+		if (TPM_DB_OK != db_ret) {
+			TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
+			return ERR_CTC_CM_DB_ERR;
+		}
+
+		/* add this rule with prece++ */
+		ret_code = tpm_ctc_cm_rule_add(owner_id, src_port, loop - 1, cm_rule.l2_parse_rule_bm, cm_rule.ipv4_parse_rule_bm,
+					       cm_rule.ipv6_parse_rule_bm, &(cm_rule.l2_key), &(cm_rule.ipv4_key),
+					       &(cm_rule.ipv6_key), &(cm_rule.pkt_frwd),
+					       cm_rule.pkt_act, cm_rule.pbits, cm_rule.ipv4_sub_pattern_key, &rule_index);
+		IF_ERROR(ret_code);
+
+		/* overwrite DB entry of higher precedence */
+		db_ret = tpm_db_ctc_cm_rule_set(src_port, loop - 1, cm_rule.l2_parse_rule_bm, cm_rule.ipv4_parse_rule_bm,
+					cm_rule.ipv6_parse_rule_bm, &(cm_rule.l2_key),
+					&(cm_rule.ipv4_key), &(cm_rule.ipv6_key),
+					&(cm_rule.pkt_frwd), cm_rule.pkt_act,
+					cm_rule.pbits, cm_rule.ipv4_sub_pattern_key, rule_index);
+		if (TPM_DB_OK != db_ret) {
+			TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
+			return ERR_CTC_CM_DB_ERR;
+		}
+
+		/* remove the old one */
+		ret_code = tpm_ctc_cm_rule_del(owner_id, &cm_rule);
+		IF_ERROR(ret_code);
+	}
+
+	/* reset the db of last rule */
+	db_ret = tpm_db_ctc_cm_rule_delete(src_port, num_prec - 1);
+	if (TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, " DB failed, recvd ret_code(%d)\n", db_ret);
+		return ERR_CTC_CM_DB_ERR;
+	}
+
+	return ret_code;
+}
+
+/*******************************************************************************
+* tpm_ctc_cm_ipv4_rule2cm()
+*
+* DESCRIPTION:    check if this rule can goto CnM stage from IPv4 stage.
+*
+* INPUTS:
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+* pkt_act            - Action associated to the rule
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns true. On error returns false.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+bool tpm_ctc_cm_ipv4_rule2cm(tpm_parse_flags_t parse_flags_bm, tpm_rule_action_t *rule_action)
+{
+	tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
+
+	tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
+
+	if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
+		/* CTC CnM is disabled */
+		return false;
+	}
+
+	/* not MTM, not to CPU */
+	if (     (parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)
+	     && !(rule_action->pkt_act & TPM_ACTION_TO_CPU))
+		return true;
+	else
+		return false;
+}
+/*******************************************************************************
+* tpm_ctc_cm_l3_rule2cm_sram()
+*
+* DESCRIPTION:    check if this rule can goto CnM stage from ETH stage when building sram of ETH rule.
+*
+* INPUTS:
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+* pkt_act            - Action associated to the rule
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns true. On error returns false.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+bool tpm_ctc_cm_l3_rule2cm_sram(tpm_parse_flags_t parse_flags_bm, tpm_rule_action_t *rule_action)
+{
+	tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
+
+	tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
+
+	if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
+		/* CTC CnM is disabled */
+		return false;
+	}
+
+	/* [!mac-to-me] */
+	if (parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)
+		return true;
+	else
+		return false;
+}
+/*******************************************************************************
+* tpm_ctc_cm_l3_rule2cm_sram()
+*
+* DESCRIPTION:    check if this rule can goto CnM stage from ETH stage when building tcam of ETH rule.
+*
+* INPUTS:
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+* l3_key             - Structure for PPPoE proto or ether type. In order to define a rule for
+*                      any ether type, the ether type value should be set to 0xFFFF
+* rule_action        -used to get the next_stage of this rule
+
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns true. On error returns false.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+bool tpm_ctc_cm_l3_rule2cm_tcam(tpm_parse_flags_t parse_flags_bm, tpm_l3_type_key_t *l3_key, tpm_rule_action_t *rule_action)
+{
+	tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
+
+	tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
+
+	if (ctc_cm_enable == TPM_CTC_CM_DISABLED) {
+		/* CTC CnM is disabled */
+		return false;
+	}
+
+	/* not ipv4/6 or pppoe and [!mac-to-me] */
+	if (   (0x0800 != l3_key->ether_type_key)
+	    && (0x86dd != l3_key->ether_type_key)
+	    && (ETH_P_PPP_SES != l3_key->ether_type_key)
+	    && (parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)
+	    && (STAGE_CTC_CM == rule_action->next_phase))
+		return true;
+	else
+		return false;
+}
+
+/*******************************************************************************
+* tpm_ctc_cm_ipv6_acl_rule_add()
+*
+* DESCRIPTION:    Main function for adding CnM API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_ipv6_acl_rule_add(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      uint32_t precedence,
+					      tpm_parse_fields_t ipv6_parse_rule_bm,
+					      tpm_ipv6_acl_key_t *ipv6_key,
+					      tpm_pkt_frwd_t *pkt_frwd,
+					      tpm_pkt_action_t pkt_act,
+					      uint32_t pbits)
+{
+	tpm_error_code_t            ret_code;
+	tpm_parse_fields_t          ipv4_parse_rule_bm = 0;
+	tpm_parse_fields_t	    l2_parse_rule_bm = 0;
+	tpm_l2_acl_key_t            l2_key;
+	tpm_ipv4_acl_key_t          ipv4_key;
+
+	ret_code = tpm_ctc_cm_acl_rule_add(owner_id, src_port, precedence, l2_parse_rule_bm,
+					   ipv4_parse_rule_bm, ipv6_parse_rule_bm, &l2_key,
+					   &ipv4_key, ipv6_key, pkt_frwd, pkt_act, pbits);
+	IF_ERROR(ret_code);
+
+	return TPM_RC_OK;
+}
+/*******************************************************************************
+* tpm_ctc_cm_set_ipv6_parse_win()
+*
+* DESCRIPTION:    Main function for adding CnM API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_set_ipv6_parse_win(uint32_t owner_id, tpm_ctc_cm_ipv6_parse_win_t ipv6_parse_window)
+{
+	uint32_t                    entry_id;
+	uint32_t                    ipv6_rule_nums;
+	int32_t                     ret_code = TPM_OK;
+	tpm_db_ctc_cm_ipv6_parse_win_t ipv6_parse_win_orig;
+
+	tpm_db_ctc_cm_ipv6_parse_win_get(&ipv6_parse_win_orig);
+	if (ipv6_parse_window == ipv6_parse_win_orig) {
+		TPM_OS_INFO(TPM_CTC_CM_MOD, "ipv6 parse win remains the same\n");
+		return TPM_OK;
+	}
+
+	/* if there is still IPv6 CnM rule exist, reture error */
+	ipv6_rule_nums = tpm_db_ctc_cm_get_ipv6_num_rules();
+	if (0 != ipv6_rule_nums) {
+		TPM_OS_ERROR(TPM_CTC_CM_MOD, "there is still IPv6 CnM rule exist, remove first!\n");
+		return ERR_CTC_CM_DB_ERR;
+	}
+
+	/* get ipv6_ety_rule_num */
+	tpm_db_ctc_cm_ipv6_ety_rule_num_get(&entry_id);
+
+	ret_code = tpm_pncl_init_cnm_main_ety_ipv6(entry_id, ipv6_parse_window);
+	IF_ERROR(ret_code);
+
+	/* set new ipv6 parse window */
+	tpm_db_ctc_cm_ipv6_parse_win_set(ipv6_parse_window);
+
+	return TPM_RC_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.h
new file mode 100755
index 0000000..5f13837
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_ctc_cm.h
@@ -0,0 +1,198 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_ctc_cm.h
+*
+* DESCRIPTION:
+*               header file for tpm_ctc_cm.c
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   jinghua
+*
+* DATE CREATED: 7 Feb 2012
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.2
+*
+*
+*******************************************************************************/
+#ifndef _TPM_CTC_CM_H_
+#define _TPM_CTC_CM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+
+/*******************************************************************************
+* tpm_ctc_cm_acl_rule_add()
+*
+* DESCRIPTION:    Main function for adding CnM API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_acl_rule_add(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint32_t precedence,
+					 tpm_parse_fields_t l2_parse_rule_bm,
+					 tpm_parse_fields_t ipv4_parse_rule_bm,
+					 tpm_parse_fields_t ipv6_parse_rule_bm,
+					 tpm_l2_acl_key_t *l2_key,
+					 tpm_ipv4_acl_key_t *ipv4_key,
+					 tpm_ipv6_acl_key_t *ipv6_key,
+					 tpm_pkt_frwd_t *pkt_frwd,
+					 tpm_pkt_action_t pkt_act,
+					 uint32_t pbits);
+
+/*******************************************************************************
+* tpm_ctc_cm_acl_rule_del()
+*
+* DESCRIPTION:    Main function for deleting CnM API rule.
+*
+* INPUTS:
+*		  All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_acl_rule_del(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint32_t precedence);
+/*******************************************************************************
+* tpm_ctc_cm_ipv6_acl_rule_add()
+*
+* DESCRIPTION:    Main function for adding CnM API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_ipv6_acl_rule_add(uint32_t owner_id,
+					      tpm_src_port_type_t src_port,
+					      uint32_t precedence,
+					      tpm_parse_fields_t ipv6_parse_rule_bm,
+					      tpm_ipv6_acl_key_t *ipv6_key,
+					      tpm_pkt_frwd_t *pkt_frwd,
+					      tpm_pkt_action_t pkt_act,
+					      uint32_t pbits);
+
+bool tpm_ctc_cm_ipv4_rule2cm(tpm_parse_flags_t parse_flags_bm, tpm_rule_action_t *rule_action);
+bool tpm_ctc_cm_l3_rule2cm_sram(tpm_parse_flags_t parse_flags_bm, tpm_rule_action_t *rule_action);
+bool tpm_ctc_cm_l3_rule2cm_tcam(tpm_parse_flags_t parse_flags_bm, tpm_l3_type_key_t *l3_key, tpm_rule_action_t *rule_action);
+/*******************************************************************************
+* tpm_ctc_cm_set_ipv6_parse_win()
+*
+* DESCRIPTION:    Main function for adding CnM API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_ctc_cm_set_ipv6_parse_win(uint32_t owner_id, tpm_ctc_cm_ipv6_parse_win_t ipv6_parse_window);
+
+#ifdef __cplusplus
+}
+#endif
+#endif    /* _TPM_CTC_CM_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.c
new file mode 100755
index 0000000..ffa53d0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.c
@@ -0,0 +1,10583 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+*
+* tpm_db.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.4
+*
+*
+*******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+#include <linux/vmalloc.h>
+
+/* Local definitions */
+#define PNC_RANGE_OPER(x)         tpm_db.pnc_range[x].pnc_range_oper
+#define PNC_RANGE_CONF(x)         tpm_db.pnc_range[x].pnc_range_conf
+#define TPM_DBVAL_CON(dbval)      ((dbval == TPM_DB_VALID) ? TPM_TRUE : TPM_FALSE)
+#define TPM_DB_DIVIDED_BY_32(x)   (x >> 5)
+#define TPM_DB_MOD_32(x)          (x & 0x1f)
+
+#define MEM_MARGIN_PATTERN        (0xA3)
+#define API_ENT_I(api_sec, i) tpm_db.api_ent_mem_area[(tpm_db.api_section[api_sec].table_start) + i]
+#define IF_ERROR(ret) \
+	if (ret != TPM_DB_OK) { \
+		TPM_OS_ERROR(TPM_DB_MOD, " recvd ret_code(%d)\n", ret); \
+		return(ret); \
+	}
+#define IF_ERROR_I(ret, i) \
+	if (ret != TPM_DB_OK) { \
+		TPM_OS_ERROR(TPM_DB_MOD, " For index(%d), recvd ret_code(%d)\n", i, ret); \
+		return(ret); \
+	}
+
+/* TODO - change to static variable after updating print functions */
+tpm_db_t tpm_db;
+
+static uint32_t mem_alloc_start_ind;
+
+const char *entry_state_str[TPM_MOD_ENTRY_STATUS_MAX] = { "F", "B", "O", "R", "S" };
+
+uint32_t *tpm_db_mod2_jump_booked_entry_bm[TPM_MAX_NUM_GMACS];
+uint32_t *tpm_db_mod2_jump_occupied_entry_bm[TPM_MAX_NUM_GMACS];
+uint32_t *tpm_db_mod2_jump_split_mod_occupied_entry_bm[TPM_MAX_NUM_GMACS];
+uint32_t *tpm_db_mod2_jump_split_mod_all_entry_bm[TPM_MAX_NUM_GMACS];
+
+uint32_t tpm_db_mod2_jump_bm_group;
+
+uint32_t *tpm_db_mod2_chain_booked_entry_bm[TPM_MAX_NUM_GMACS][TPM_CHAIN_TYPE_MAX];
+uint32_t *tpm_db_mod2_chain_occupied_entry_bm[TPM_MAX_NUM_GMACS][TPM_CHAIN_TYPE_MAX];
+
+uint32_t tpm_db_mod2_chain_bm_group[TPM_CHAIN_TYPE_MAX];
+
+tpm_mod2_jump_pmt_info_t *tpm_db_mod2_jump_pmt_info[TPM_MAX_NUM_GMACS];
+tpm_mod2_chain_pmt_info_t *tpm_db_mod2_chain_pmt_info[TPM_MAX_NUM_GMACS];
+
+tpm_mod2_chain_info_t *tpm_db_mod2_chain_info[TPM_MAX_NUM_GMACS][TPM_CHAIN_TYPE_MAX];
+
+tpm_mod2_jump_cfg_t tpm_db_mod2_jump_area_cfg;
+tpm_mod2_chain_cfg_t tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAX];
+
+uint16_t tpm_mod2_chain_area_base;
+uint16_t tpm_mod2_total_chain_num;
+
+uint8_t tpm_mod2_multicast_mh_enable;
+uint8_t tpm_mod2_pppoe_add_mod_enable;
+uint8_t tpm_mod2_double_tag_enable;
+uint8_t tpm_mod2_udp_checksum_use_init_bm_enable;
+uint8_t tpm_mod2_udp_checksum_enable;
+
+tpm_db_mc_stream_entry_t *tpm_db_mc_stream_table[TPM_MC_MAX_STREAM_NUM];
+tpm_db_mc_mac_entry_t *tpm_db_mc_mac_table[TPM_MC_MAX_MAC_NUM];
+
+uint32_t tpm_db_mc_lpbk_entries_num;
+tpm_db_mc_lpbk_entry_t *tpm_db_mc_lpbk_table[TPM_MC_MAX_LPBK_ENTRIES_NUM];
+tpm_db_mc_vlan_entry_t *tpm_db_mc_vlan_xits_table[TPM_MC_MAX_MVLAN_XITS_NUM];
+
+uint8_t tpm_db_mc_virt_uni_entry_state_table[TPM_MC_MAX_STREAM_NUM];
+
+uint8_t tpm_db_mc_igmp_proxy_sa_mac[6];
+uint8_t tpm_db_mc_igmp_proxy_sa_mac_valid;
+
+/* Function Declarations */
+int32_t tpm_db_api_freeentry_get(tpm_api_sections_t api_section, int32_t *index);
+int32_t tpm_db_api_entry_ind_get(tpm_api_sections_t api_section, uint32_t rule_num, int32_t *index);
+int32_t tpm_db_mod_shdw_par_check(tpm_gmacs_enum_t gmac, uint32_t mod_entry);
+
+
+/*******************************************************************************
+* tpm_db_eth_port_conf_get()
+*
+* DESCRIPTION:      Function to get an ethernet port physical configuration from the DB
+*
+* INPUTS:
+* ext_port         - External Port Identifier, can be any positive number
+*
+* OUTPUTS:
+*                 - See explanation in tpm_db_eth_port_conf_t structure
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+bool tpm_db_eth_port_valid(tpm_src_port_type_t src_port_num)
+{
+	uint32_t i;
+
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if ((tpm_db.eth_ports[i].port_src == src_port_num)
+		    && (tpm_db.eth_ports[i].valid == TPM_DB_VALID))
+			return (true);
+	}
+
+	return false;
+}
+
+/*******************************************************************************
+* tpm_db_eth_port_conf_get()
+*
+* DESCRIPTION:      Function to get an ethernet port physical configuration from the DB
+*
+* INPUTS:
+* ext_port         - External Port Identifier, can be any positive number
+*
+* OUTPUTS:
+*                 - See explanation in tpm_db_eth_port_conf_t structure
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_eth_port_conf_get(tpm_src_port_type_t src_port_num,
+				 tpm_db_chip_conn_t *chip_con,
+				 tpm_db_int_conn_t *int_con,
+				 uint32_t *switch_port)
+{
+	uint32_t i;
+
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if ((tpm_db.eth_ports[i].port_src == src_port_num)
+		    && (tpm_db.eth_ports[i].valid == TPM_DB_VALID)) {
+			*chip_con = tpm_db.eth_ports[i].chip_connect;
+			*int_con = tpm_db.eth_ports[i].int_connect;
+			*switch_port = tpm_db.eth_ports[i].switch_port;
+			return (TPM_DB_OK);
+		}
+	}
+
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_eth_port_switch_port_get()
+*
+* DESCRIPTION:      Function to get an ethernet port physical configuration from the DB
+*
+* INPUTS:
+* ext_port         - UNI Port Identifier, can be any positive number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns the switch port number.
+* On error, TPM_DB_ERR_PORT_NUM = 0xFF is returned.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_eth_port_switch_port_get(tpm_src_port_type_t src_port)
+{
+	uint32_t i;
+
+       if (TPM_SRC_PORT_UNI_VIRT == src_port) {
+                if (TPM_DB_VALID == tpm_db.func_profile.virt_uni_info.enabled)
+                        return tpm_db.func_profile.virt_uni_info.switch_port;
+               else
+                        return TPM_DB_ERR_PORT_NUM;
+       } else if (TPM_SRC_PORT_WAN == src_port) {
+               for (i = TPM_ENUM_GMAC_0; i < TPM_MAX_GMAC; i++) {
+			/*  in case traffic from WAN, the dest is LAN,
+			    so we search for switch port connected to GMAC LAN functionality */
+                       if (TPM_GMAC_FUNC_LAN == tpm_db.gmac_func[i]){
+                               if (TPM_GMAC_CON_SWITCH_4 == tpm_db.gmac_port_conf[i].conn)
+                                       return TPM_GMAC0_AMBER_PORT_NUM;
+                               else
+                                       return TPM_GMAC1_AMBER_PORT_NUM;
+                       }
+               }
+       } else {
+               for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+                       if ((tpm_db.eth_ports[i].port_src == src_port) &&
+                           (TPM_DB_VALID == tpm_db.eth_ports[i].valid))
+                               return (tpm_db.eth_ports[i].switch_port);
+		}
+
+	}
+	return (TPM_DB_ERR_PORT_NUM);
+}
+bool tpm_db_gmac1_lpbk_en_get(void)
+{
+	return tpm_db.func_profile.gmac1_loopback_en;
+}
+void tpm_db_gmac1_lpbk_en_set(bool en)
+{
+	tpm_db.func_profile.gmac1_loopback_en = en;
+}
+bool tpm_db_cpu_wan_lpbk_en_get(void)
+{
+	return tpm_db.func_profile.cpu_wan_loopback_en;
+}
+void tpm_db_cpu_wan_lpbk_en_set(bool en)
+{
+	tpm_db.func_profile.cpu_wan_loopback_en = en;
+}
+
+int32_t tpm_db_get_valid_uni_ports_num(uint32_t *num_ports)
+{
+	uint32_t i, _num_ports = 0;
+
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (tpm_db.eth_ports[i].valid == TPM_DB_VALID) {
+			if (tpm_db.eth_ports[i].port_src >= TPM_SRC_PORT_UNI_0 &&
+				tpm_db.eth_ports[i].port_src <= TPM_SRC_PORT_UNI_7)
+				_num_ports++;
+		}
+	}
+
+    if (tpm_db.func_profile.virt_uni_info.enabled == TPM_DB_VALID)
+		_num_ports++;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_phy_convert_port_index()
+*
+* DESCRIPTION:      Function to get an ethernet port physical configuration from the DB
+*
+* INPUTS:
+* switch_port         - External Port Identifier, can be any positive number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns the switch port number.
+* On error, TPM_DB_ERR_PORT_NUM = 0xFF is returned.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_phy_convert_port_index(int32_t switch_port)
+{
+	uint32_t i;
+
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if ((tpm_db.eth_ports[i].switch_port == switch_port)
+		    && (tpm_db.eth_ports[i].valid == TPM_DB_VALID))
+			return (tpm_db.eth_ports[i].port_src);
+	}
+
+	return (TPM_DB_ERR_PORT_NUM);
+}
+EXPORT_SYMBOL(tpm_db_phy_convert_port_index);
+
+/*******************************************************************************
+* tpm_db_eth_cmplx_profile_set()
+*
+* DESCRIPTION:      Function to set the Ethernet Complex Profile in the DB
+*
+* INPUTS:
+* eth_cmplx_profile	- the profile enumartion number
+*
+* OUTPUTS:
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_eth_cmplx_profile_set(tpm_eth_complex_profile_t eth_cmplx_profile)
+{
+	tpm_db.eth_cmplx_profile = eth_cmplx_profile;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_eth_cmplx_profile_get()
+*
+* DESCRIPTION:      Function returns the Ethernet Complex Profile from the DB
+*
+* INPUTS:
+*
+* OUTPUTS:
+*		the profile enumartion number
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_eth_complex_profile_t tpm_db_eth_cmplx_profile_get(void)
+{
+	return tpm_db.eth_cmplx_profile;
+}
+
+
+/*******************************************************************************
+* tpm_db_mac_func_set()
+*
+* DESCRIPTION:	Sets all gmacs functionality according to EthCmplx profile
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*
+* COMMENTS:
+* 	On success, returns TPM_OK
+* 	On error, returns tpm_db_gmac_func_set error
+*******************************************************************************/
+int32_t tpm_db_mac_func_set(void)
+{
+	tpm_db_gmac_func_t pon = 0,
+			   gmac0 = 0,
+			   gmac1 = 0;
+	int32_t ret_code;
+
+	switch(tpm_db.eth_cmplx_profile)
+	{
+	case TPM_PON_WAN_DUAL_MAC_INT_SWITCH:
+		pon = TPM_GMAC_FUNC_WAN;
+		gmac0 = TPM_GMAC_FUNC_LAN;
+       	if (0 != tpm_db.func_profile.virt_uni_info.enabled)
+			gmac1 = TPM_GMAC_FUNC_VIRT_UNI;
+       	else
+			gmac1 = TPM_GMAC_FUNC_NONE;
+		break;
+
+	case TPM_PON_WAN_DUAL_MAC_EXT_SWITCH:
+       	/* ofer: phase#2, diferentiate between gmacs */
+		pon = TPM_GMAC_FUNC_WAN;
+		gmac0 = TPM_GMAC_FUNC_LAN;
+		gmac1 = TPM_GMAC_FUNC_NONE;
+		break;
+
+	case TPM_PON_WAN_G1_LAN_G0_INT_SWITCH:
+		pon = TPM_GMAC_FUNC_WAN;
+		gmac0 = TPM_GMAC_FUNC_LAN;
+		gmac1 = TPM_GMAC_FUNC_LAN_UNI;
+		break;
+
+	case TPM_PON_WAN_G0_INT_SWITCH:
+		pon = TPM_GMAC_FUNC_WAN;
+		gmac0 = TPM_GMAC_FUNC_LAN;
+		gmac1 = TPM_GMAC_FUNC_NONE;
+		break;
+
+	case TPM_PON_WAN_G0_SINGLE_PORT:
+		pon = TPM_GMAC_FUNC_WAN;
+		gmac0 = TPM_GMAC_FUNC_LAN;
+		gmac1 = TPM_GMAC_FUNC_NONE;
+		break;
+
+	case TPM_G0_WAN_G1_INT_SWITCH:
+		pon = TPM_GMAC_FUNC_NONE;
+		gmac0 = TPM_GMAC_FUNC_WAN;
+		gmac1 = TPM_GMAC_FUNC_LAN;
+		break;
+
+	case TPM_G1_WAN_G0_INT_SWITCH:
+		pon = TPM_GMAC_FUNC_NONE;
+		gmac0 = TPM_GMAC_FUNC_LAN;
+		gmac1 = TPM_GMAC_FUNC_WAN;
+		break;
+
+	case TPM_PON_G1_WAN_G0_INT_SWITCH:
+       	if (TPM_ENUM_PMAC == tpm_db.init_misc.backup_wan) {
+			pon = TPM_GMAC_FUNC_NONE;
+			gmac1 = TPM_GMAC_FUNC_WAN;
+		}else{
+			gmac1 = TPM_GMAC_FUNC_NONE;
+			pon = TPM_GMAC_FUNC_WAN;
+		}
+		gmac0 = TPM_GMAC_FUNC_LAN;
+		break;
+
+	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
+       	if (TPM_ENUM_PMAC == tpm_db.init_misc.backup_wan) {
+			pon = TPM_GMAC_FUNC_NONE;
+			gmac1 = TPM_GMAC_FUNC_WAN;
+		}else{
+			gmac1 = TPM_GMAC_FUNC_NONE;
+			pon = TPM_GMAC_FUNC_WAN;
+       	}
+		gmac0 = TPM_GMAC_FUNC_LAN_UNI;
+		break;
+
+	case TPM_PON_G0_WAN_G1_INT_SWITCH:
+       	if (TPM_ENUM_PMAC == tpm_db.init_misc.backup_wan) {
+			pon = TPM_GMAC_FUNC_NONE;
+			gmac0 = TPM_GMAC_FUNC_WAN;
+		}else{
+			gmac0 = TPM_GMAC_FUNC_NONE;
+			pon = TPM_GMAC_FUNC_WAN;
+       	}
+		gmac1 = TPM_GMAC_FUNC_LAN_UNI;
+		break;
+
+	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
+		if (TPM_ENUM_PMAC == tpm_db.init_misc.backup_wan) {
+			pon = TPM_GMAC_FUNC_NONE;
+			gmac0 = TPM_GMAC_FUNC_WAN;
+		}else{
+			gmac0 = TPM_GMAC_FUNC_NONE;
+			pon = TPM_GMAC_FUNC_WAN;
+       	}
+		gmac1 = TPM_GMAC_FUNC_LAN;
+		break;
+
+	case TPM_PON_WAN_G1_MNG_EXT_SWITCH:
+	case TPM_PON_WAN_G1_SINGLE_PORT:
+		pon = TPM_GMAC_FUNC_WAN;
+		gmac0 = TPM_GMAC_FUNC_NONE;
+		gmac1 = TPM_GMAC_FUNC_LAN_UNI;
+		break;
+
+	case TPM_PON_WAN_G0_G1_LPBK:
+		pon = TPM_GMAC_FUNC_WAN;
+		gmac0 = TPM_GMAC_FUNC_LAN_UNI;
+		gmac1 = TPM_GMAC_FUNC_LAN;
+		break;
+	}
+
+	ret_code = tpm_db_gmac_func_set(TPM_ENUM_PMAC, pon);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_gmac_func_set(TPM_ENUM_GMAC_0, gmac0);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_gmac_func_set(TPM_ENUM_GMAC_1, gmac1);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_db_eth_max_uni_port_set()
+*
+* DESCRIPTION:	Sets the max_uni_port_nr according to EthCmplx profile
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*
+* COMMENTS:
+* 	On success, returns TPM_OK
+* 	On error, returns tpm_db_gmac_func_set error
+*******************************************************************************/
+int32_t tpm_db_eth_max_uni_port_set(void)
+{
+	switch (tpm_db.eth_cmplx_profile) {
+	case TPM_PON_WAN_G0_SINGLE_PORT:
+	case TPM_PON_WAN_G1_SINGLE_PORT:
+	case TPM_PON_WAN_G0_G1_LPBK:
+		tpm_db.max_uni_port_nr = TPM_SRC_PORT_UNI_0;
+       	break;
+
+	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
+	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
+		tpm_db.max_uni_port_nr = TPM_SRC_PORT_UNI_1;
+       	break;
+
+	case TPM_PON_WAN_G0_INT_SWITCH:
+	case TPM_PON_WAN_G1_LAN_G0_INT_SWITCH:
+	case TPM_PON_WAN_DUAL_MAC_INT_SWITCH:
+       case TPM_G0_WAN_G1_INT_SWITCH:
+	case TPM_G1_WAN_G0_INT_SWITCH:
+	case TPM_PON_G1_WAN_G0_INT_SWITCH:
+	case TPM_PON_G0_WAN_G1_INT_SWITCH:
+		tpm_db.max_uni_port_nr = TPM_SRC_PORT_UNI_3;
+		break;
+
+	case TPM_PON_WAN_G1_MNG_EXT_SWITCH:
+		tpm_db.max_uni_port_nr = TPM_SRC_PORT_UNI_6;
+       	break;
+
+	case TPM_PON_WAN_DUAL_MAC_EXT_SWITCH:
+		tpm_db.max_uni_port_nr = TPM_SRC_PORT_UNI_7;
+       	break;
+
+	default:
+		return TPM_DB_ERR_REC_EXIST;
+	}
+
+	/* increment the counter since UNI enumeration starts @ zero */
+	tpm_db.max_uni_port_nr++;
+
+	return (TPM_DB_OK);
+}
+
+tpm_src_port_type_t tpm_db_trg_port_uni_any_bmp_get(bool inc_virt_uni)
+{
+	uint32_t dst_port, trg_port_uni_any_bmp = 0;
+	tpm_src_port_type_t src_port;
+
+	for (dst_port = TPM_TRG_UNI_0, src_port = TPM_SRC_PORT_UNI_0; 
+	     dst_port <= TPM_TRG_UNI_7; 
+	     dst_port = (dst_port << 1), src_port += 1) {
+
+		/* if port is valid */
+		if(tpm_db_eth_port_valid(src_port))
+			trg_port_uni_any_bmp |= dst_port;
+	}
+
+	if (tpm_db.func_profile.virt_uni_info.enabled != 0 && true == inc_virt_uni)
+		trg_port_uni_any_bmp |= TPM_TRG_UNI_VIRT;
+
+	return trg_port_uni_any_bmp;
+}
+
+bool tpm_db_gmac_valid(tpm_gmacs_enum_t gmac)
+{
+	if (((TPM_ENUM_PMAC == gmac) && (TPM_NONE != tpm_db.init_misc.pon_type)) ||
+	    ((1 == tpm_db.gmac_port_conf[gmac].valid) && (TPM_GMAC_CON_DISC != tpm_db.gmac_port_conf[gmac].conn)))
+	    return true;
+
+	return false;
+}
+
+/*******************************************************************************
+* tpm_db_to_lan_gmac_get()
+*
+* DESCRIPTION: returns the GMAC target for traffic to LAN according to target
+*		port bitmap
+* INPUTS:
+* trg_port	target port bitmap
+*
+* OUTPUTS:
+* pnc_target	gmac target
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_to_lan_gmac_get(tpm_trg_port_type_t trg_port, tpm_pnc_trg_t *pnc_target)
+{
+	uint32_t i;
+	tpm_pnc_trg_t gmac_vec = 0;
+	bool trg_port_on_switch = false;
+
+
+	if (NULL == pnc_target)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	*pnc_target = TPM_INVALID_PNC_TRG;
+
+	/* for UNI_ANY we search the gmac_func for lan cababilities */
+	if (TPM_TRG_PORT_UNI_ANY == trg_port) {
+	       for (i = TPM_ENUM_GMAC_0; i < TPM_MAX_GMAC; i++) {
+	       		if (!tpm_db_gmac_valid(i))
+					continue;
+			if (!tpm_db_gmac1_lpbk_en_get()) {
+				if (TPM_GMAC_FUNC_LAN == tpm_db.gmac_func[i]      ||
+				    TPM_GMAC_FUNC_LAN_UNI == tpm_db.gmac_func[i])
+					gmac_vec |= (TPM_ENUM_GMAC_0 == i) ? TPM_PNC_TRG_GMAC0 : TPM_PNC_TRG_GMAC1;
+			} else {
+				gmac_vec |= TPM_PNC_TRG_GMAC0;
+				break;
+			}
+		}
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "trg_port(%x) gmac_vec(%x)\n", trg_port, gmac_vec);
+		*pnc_target = gmac_vec;
+		return TPM_DB_OK;
+	}
+
+	/* if target is virt uni, search for the gmac that acts as LAN */
+	if (TPM_TRG_UNI_VIRT & trg_port) {
+		for (i = TPM_ENUM_GMAC_0; i < TPM_MAX_GMAC; i++) {
+			if (!tpm_db_gmac_valid(i))
+				continue;
+
+			/* need only virt uni lan ports */
+			if (TPM_GMAC_FUNC_LAN == tpm_db.gmac_func[i]){
+				 gmac_vec |= (TPM_ENUM_GMAC_0 == i) ? TPM_PNC_TRG_GMAC0 : TPM_PNC_TRG_GMAC1;
+				 break;
+			}
+		}
+	}
+
+	/* search ethernet ports */
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (TPM_DB_VALID != tpm_db.eth_ports[i].valid ||
+		    TPM_SRC_PORT_ILLEGAL == tpm_db.eth_ports[i].port_src ||
+		    TPM_SRC_PORT_WAN == tpm_db.eth_ports[i].port_src)
+       		continue;
+
+		if ((1 << tpm_db.eth_ports[i].port_src) & (trg_port >> TPM_TRG_UNI_OFFSET)){
+			if (TPM_INTCON_SWITCH == tpm_db.eth_ports[i].int_connect) {
+				/* port on switch, set the flag */
+				trg_port_on_switch = true;
+			} else if (TPM_INTCON_GMAC0 == tpm_db.eth_ports[i].int_connect){
+				/* port on GMAC0 */
+				gmac_vec |= TPM_PNC_TRG_GMAC0;
+			} else if (TPM_INTCON_GMAC1 == tpm_db.eth_ports[i].int_connect){
+				/* port on GMAC1 */
+				gmac_vec |= TPM_PNC_TRG_GMAC1;
+			}
+		}
+       }
+
+	/* if port connected to switch, search gmac_func for the connected GMAC */
+	if (true == trg_port_on_switch) {
+		for (i = TPM_ENUM_GMAC_0; i < TPM_MAX_GMAC; i++) {
+			if (!tpm_db_gmac_valid(i))
+				continue;
+
+			/* need only LAN ports */
+			if (TPM_GMAC_FUNC_LAN == tpm_db.gmac_func[i] ||
+			    TPM_GMAC_FUNC_LAN_UNI == tpm_db.gmac_func[i]){
+				if (TPM_GMAC_CON_SWITCH_4 == tpm_db.gmac_port_conf[i].conn ||
+				    TPM_GMAC_CON_SWITCH_5 == tpm_db.gmac_port_conf[i].conn) {
+					gmac_vec |= (TPM_ENUM_GMAC_0 == i) ? TPM_PNC_TRG_GMAC0 : TPM_PNC_TRG_GMAC1;
+				}
+			}
+		}
+	}
+
+	if (TPM_INVALID_PNC_TRG == gmac_vec)
+	      	return TPM_DB_ERR_REC_NOT_EXIST;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "trg_port(%x) gmac_vec(%x)\n", trg_port, gmac_vec);
+	*pnc_target = gmac_vec;
+	return TPM_DB_OK;
+}
+
+/*******************************************************************************
+* tpm_db_src_gmac_func_get()
+*
+* DESCRIPTION: returns the GMAC target for traffic to LAN according to target
+*		port bitmap
+* INPUTS:
+* trg_port	target port bitmap
+*
+* OUTPUTS:
+* pnc_target	gmac target
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_src_gmac_func_get(tpm_src_port_type_t src_port, tpm_db_gmac_func_t *gmac_func)
+{
+	uint32_t i;
+
+	if (NULL == gmac_func)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	*gmac_func = TPM_GMAC_FUNC_NONE;
+
+	if (TPM_SRC_PORT_WAN == src_port){
+		*gmac_func = TPM_GMAC_FUNC_WAN;
+		return TPM_DB_OK;
+	}
+
+	if (TPM_SRC_PORT_UNI_VIRT == src_port){
+		if (TPM_FALSE == tpm_db.func_profile.virt_uni_info.enabled)
+			return TPM_DB_ERR_REC_NOT_EXIST;
+
+		tpm_db_gmac_func_get(TPM_ENUM_GMAC_1, gmac_func);
+		return TPM_DB_OK;
+	}
+
+	/* start gmac ports */
+	for (i = 0; i < TPM_NUM_GMACS; i++) {
+		if (TPM_FALSE == tpm_db.gmac_port_conf[i].valid)
+       		continue;
+
+		if (tpm_db.gmac_port_conf[i].port_src == src_port){
+			*gmac_func = tpm_db.gmac_func[i];
+       		return TPM_DB_OK;
+		}
+	}
+
+	/* search switch ports */
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (TPM_DB_VALID != tpm_db.eth_ports[i].valid)
+       		continue;
+
+		/* port_src found on switch */
+		if (tpm_db.eth_ports[i].port_src == src_port){
+       		uint32_t j;
+
+			/* now search gmac table to find connecting port */
+			for (j = 0; j < TPM_NUM_GMACS-1; j++) {
+				if (TPM_FALSE == tpm_db.gmac_port_conf[j].valid)
+       				continue;
+
+				if ((TPM_SRC_PORT_ILLEGAL == tpm_db.gmac_port_conf[j].port_src) &&
+				    ((TPM_GMAC_CON_SWITCH_5 == tpm_db.gmac_port_conf[j].conn) ||
+				     (TPM_GMAC_CON_SWITCH_4 == tpm_db.gmac_port_conf[j].conn))){
+					*gmac_func = (TPM_ENUM_GMAC_0 == i) ? tpm_db.gmac_func[0] : tpm_db.gmac_func[1];
+					return TPM_DB_OK;
+				}
+       		}
+
+       	}
+       }
+
+	return TPM_DB_ERR_REC_NOT_EXIST;
+}
+
+int32_t tpm_db_src_port_on_switch(tpm_src_port_type_t src_port)
+{
+	uint32_t i;
+
+	/* switch ports can not act as WAN source port */
+	if (TPM_SRC_PORT_WAN == src_port)
+		return TPM_FALSE;
+
+	/* start gmac ports */
+	for (i = 0; i < TPM_NUM_GMACS; i++) {
+		if (TPM_FALSE == tpm_db.gmac_port_conf[i].valid)
+       		continue;
+
+		if (tpm_db.gmac_port_conf[i].port_src == src_port)
+			return TPM_FALSE;
+	}
+
+	/* search switch ports */
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (TPM_DB_VALID != tpm_db.eth_ports[i].valid)
+       		continue;
+
+		if (tpm_db.eth_ports[i].port_src == src_port)
+			return TPM_TRUE;
+	}
+	return TPM_FALSE;
+}
+
+/*******************************************************************************
+* tpm_db_trg_port_switch_port_get()
+*
+* DESCRIPTION:      Function to get the target port bitmap
+*
+* INPUTS:
+* ext_port         - External Port Identifier, can be any positive number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* The function returns the target ports bitmap for an external port.
+* In case of no matching - it returns empty bitmap 0x0.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_trg_port_switch_port_get(tpm_trg_port_type_t ext_port)
+{
+	uint32_t portVec = 0;
+
+	if (ext_port & TPM_TRG_PORT_UNI_ANY) {
+		ext_port |= (TPM_TRG_UNI_0 | TPM_TRG_UNI_1 | TPM_TRG_UNI_2 | TPM_TRG_UNI_3 |
+		 	    TPM_TRG_UNI_4 | TPM_TRG_UNI_5 | TPM_TRG_UNI_6 | TPM_TRG_UNI_7);
+
+		if (tpm_db.func_profile.virt_uni_info.enabled != 0)
+			ext_port |= TPM_TRG_UNI_VIRT;
+	}
+	if (ext_port & TPM_TRG_UNI_0)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_0);
+
+	if (ext_port & TPM_TRG_UNI_1)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_1);
+
+	if (ext_port & TPM_TRG_UNI_2)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_2);
+
+	if (ext_port & TPM_TRG_UNI_3)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_3);
+
+	if (ext_port & TPM_TRG_UNI_4)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_4);
+
+	if (ext_port & TPM_TRG_UNI_5)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_5);
+
+	if (ext_port & TPM_TRG_UNI_6)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_6);
+
+	if (ext_port & TPM_TRG_UNI_7)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_7);
+
+	if (ext_port & TPM_TRG_UNI_VIRT)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_UNI_VIRT);
+
+	if (ext_port & TPM_TRG_PORT_CPU)
+		portVec |= 1 << tpm_db_eth_port_switch_port_get(TPM_SRC_PORT_WAN);
+
+	return (portVec);
+}
+
+/*******************************************************************************
+* tpm_db_eth_port_conf_set()
+*
+* DESCRIPTION:      Function to set an ethernet physical and internal configuration in the DB
+*
+* INPUTS:
+* ext_port         - External Port Identifier, can be any positive number
+* other inputs     - See explanation in tpm_db_eth_port_conf_t structure
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_eth_port_conf_set(tpm_init_eth_port_conf_t *eth_port_conf)
+{
+	uint32_t i;
+	int32_t free_entry = -1;
+
+	if (NULL == eth_port_conf)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	TPM_OS_DEBUG(TPM_DB_MOD, "src_port (%d)\n", eth_port_conf->port_src);
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		/* Check entry does not exist */
+       	if ((tpm_db.eth_ports[i].port_src == eth_port_conf->port_src)
+		    && (tpm_db.eth_ports[i].valid == TPM_DB_VALID))
+			return (TPM_DB_ERR_REC_EXIST);
+
+		/* Find first invalid entry */
+		if ((free_entry == -1) && (tpm_db.eth_ports[i].valid == TPM_DB_INVALID))
+			free_entry = i;
+	}
+	/* No free Entry */
+	if (free_entry == -1)
+		return (TPM_DB_ERR_DB_TBL_FULL);
+
+	/* Set entry */
+	tpm_db.eth_ports[free_entry].port_src = eth_port_conf->port_src;
+	tpm_db.eth_ports[free_entry].int_connect = eth_port_conf->int_connect;
+	tpm_db.eth_ports[free_entry].chip_connect = eth_port_conf->chip_connect;
+	tpm_db.eth_ports[free_entry].switch_port = eth_port_conf->switch_port;
+	tpm_db.eth_ports[free_entry].valid = TPM_DB_VALID;
+
+	return (TPM_DB_OK);
+
+}
+
+int32_t tpm_db_gmac_conn_conf_set(tpm_init_gmac_conn_conf_t *gmac_port_conf, uint32_t arr_size)
+{
+	uint32_t i;
+
+	if (NULL == gmac_port_conf)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	for (i = 0; i < arr_size; i++) {
+		TPM_OS_DEBUG(TPM_DB_MOD, "gmac src_port (%d)\n", gmac_port_conf[i].port_src);
+
+		/* Set entry */
+		tpm_db.gmac_port_conf[i].port_src = gmac_port_conf[i].port_src;
+		tpm_db.gmac_port_conf[i].conn = gmac_port_conf[i].conn;
+		tpm_db.gmac_port_conf[i].valid = gmac_port_conf[i].valid;
+	}
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_tcont_llid_set()
+*
+* DESCRIPTION:      Function to set the GMAC connection and T-CONTs  in the DB
+*
+* INPUTS:
+* num_tcont_llid   - Number of T-CONTs/LLIDs
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_tcont_llid_set(uint32_t num_tcont_llid)
+{
+	tpm_db.num_valid_tcont_llid = num_tcont_llid;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_conn_get()
+*
+* DESCRIPTION:      Function to get the Connection of an Ethernet GMAC
+*
+* INPUTS:
+* gmac             - GMAC number
+* OUTPUTS:
+* gmac_con         - GMAC internal Physical connection (see tpm_db_gmac_conn_t)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_conn_get(tpm_gmacs_enum_t gmac, tpm_db_gmac_conn_t *gmac_con)
+{
+	if (gmac == TPM_ENUM_GMAC_0)
+		*gmac_con = tpm_db.gmac_port_conf[0].conn;
+	else if (gmac == TPM_ENUM_GMAC_1)
+		*gmac_con = tpm_db.gmac_port_conf[1].conn;
+	else
+		return (TPM_DB_ERR_INV_INPUT);
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_mh_en_conf_set()
+*
+* DESCRIPTION:      Function to set the GMAC connection and T-CONTs  in the DB
+*
+* INPUTS:
+* gmac             - GMAC
+* mh_en            - MH enable TRUE/FALSE
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_mh_en_conf_set(tpm_gmacs_enum_t gmac, uint32_t mh_en)
+{
+
+	tpm_db.gmac_mh_en[gmac] = mh_en;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_mh_en_conf_get()
+*
+* DESCRIPTION:      Function to set the GMAC connection and T-CONTs  in the DB
+*
+* INPUTS:
+* gmac             - GMAC
+*
+* OUTPUTS:
+* mh_en            - MH enable TRUE/FALSE
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_mh_en_conf_get(tpm_gmacs_enum_t gmac, uint32_t *mh_en)
+{
+
+	*mh_en = tpm_db.gmac_mh_en[gmac];
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_bm_bufs_conf_set()
+*
+* DESCRIPTION:      Function to set the GMAC number of Buffer Mngmt large_bufers, short_buffers
+*
+* INPUTS:
+* gmac              - GMAC
+* large_pkt_buffers - number of buffers in the GMAC long packets pool
+* small_pkt_buffers - number of buffers in the GMAC short packets pool
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_bm_bufs_conf_set(tpm_gmacs_enum_t gmac, uint32_t large_pkt_buffers, uint32_t small_pkt_buffers)
+{
+	tpm_db.gmac_bp_bufs[gmac].valid = TPM_DB_VALID;
+	tpm_db.gmac_bp_bufs[gmac].large_pkt_buffers = large_pkt_buffers;
+	tpm_db.gmac_bp_bufs[gmac].small_pkt_buffers = small_pkt_buffers;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_bm_bufs_conf_get()
+*
+* DESCRIPTION:      Function to set the GMAC number of Buffer Mngmt large_bufers, short_buffers
+*
+* INPUTS:
+* gmac              - GMAC
+* valid             - Is the entry valid in the db
+* large_pkt_buffers - number of buffers in the GMAC long packets pool
+* small_pkt_buffers - number of buffers in the GMAC short packets pool
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_bm_bufs_conf_get(tpm_gmacs_enum_t gmac,
+				     uint32_t *valid, uint32_t *large_pkt_buffers, uint32_t *small_pkt_buffers)
+{
+	if ((valid == NULL) || (gmac >= TPM_MAX_NUM_GMACS))
+		return (TPM_DB_ERR_INV_INPUT);
+	*valid = (tpm_db.gmac_bp_bufs[gmac].valid == TPM_DB_VALID ? 1 : 0);
+
+	if (large_pkt_buffers != NULL)
+		*large_pkt_buffers = tpm_db.gmac_bp_bufs[gmac].large_pkt_buffers;
+
+	if (small_pkt_buffers != NULL)
+		*small_pkt_buffers = tpm_db.gmac_bp_bufs[gmac].small_pkt_buffers;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_intport_int_con_get()
+*
+* DESCRIPTION:      Function returns internal connectivity of an internal port num
+*
+* INPUTS:
+* int_port_num     - Internal Port Identifier, UNI#0..UNI#4 or WAN Port
+*
+* OUTPUTS:
+* int_con          - Port internal L2 Connection (G0, G1, Amber switch)
+* switch_port      - Amber Switch Port number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_intport_int_con_get(tpm_src_port_type_t int_port_num,
+				   tpm_db_int_conn_t	*int_con,
+				   uint32_t		*switch_port)
+{
+	int32_t ret_code;
+	tpm_db_chip_conn_t dummy_chip_con;
+	tpm_db_int_conn_t l_int_conn;
+	uint32_t l_switch_port;
+
+	if (int_port_num == TPM_SRC_PORT_UNI_VIRT) {
+		*int_con = TPM_INTCON_SWITCH;
+		*switch_port = tpm_db.func_profile.virt_uni_info.switch_port;
+		return (TPM_DB_OK);
+	}
+
+	/* Get External Port Config */
+	ret_code = tpm_db_eth_port_conf_get(int_port_num,
+					    &dummy_chip_con,
+					    &l_int_conn,
+					    &l_switch_port);
+	IF_ERROR(ret_code);
+
+	/* Return data */
+	*int_con = l_int_conn;
+	*switch_port = l_switch_port;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_num_tcont_llid_get()
+*
+* DESCRIPTION:      Function to get the number of T-CONTs/LLIDs
+*
+* INPUTS:
+* OUTPUTS:
+* num_tcont_llid   - Number of GPON TCONTs or EPON LLIDs
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+*
+*******************************************************************************/
+int32_t tpm_db_num_tcont_llid_get(uint32_t *num_tcont_llid)
+{
+	*num_tcont_llid = tpm_db.num_valid_tcont_llid;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_tx_q_conf_set()
+*
+* DESCRIPTION:      Function to set the parameters of a Packet Processor Component Tx queue
+*
+* INPUTS:
+* tx_mod           - Tx module (G0, G1, or TCONT/LLID0-7)
+* OUTPUTS:
+* gmac_con         - GMAC0 connection
+* queue_num        - Queue number in this Tx
+* sched_method     - The Tx Scheduler this queue is added to (the WRR or the Strict scheduler)
+* queue_owner      - The single hardware owner, that is feeding this queue.
+*                    Can be the CPU, or one of the PAcket Processor Rx components.
+* owner_queue_num  - The relative queue number of the owner of this queue.
+* queue_weight     - Weight, if the queue is added to the WRR Scheduler.
+* queue_size       -
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_tx_q_conf_set(tpm_db_tx_mod_t tx_mod,
+				  uint32_t queue_num,
+				  tpm_db_sched_t sched_method,
+				  tpm_db_txq_owner_t queue_owner,
+				  uint32_t owner_queue_num, uint32_t queue_size, uint32_t queue_weight)
+{
+	tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].queue_owner = queue_owner;
+	tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].owner_queue_num = owner_queue_num;
+	tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].sched_method = sched_method;
+	tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].queue_size = queue_size;
+	tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].queue_weight = queue_weight;
+	tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].valid = TPM_DB_VALID;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_tx_q_conf_get()
+*
+* DESCRIPTION:      Function to set the parameters of a Packet Processor Tx Component
+*
+* INPUTS:
+* tx_mod           - Tx module (G0, G1, or TCONT/LLID0-7)
+* queue_num        - Queue number in this Tx
+*
+* OUTPUTS:
+* valid             - Queue exists
+* sched_method     - The Tx Scheduler this queue is added to (the WRR or the Strict scheduler)
+* queue_owner      - The single hardware owner, that is feeding this queue.
+*                    Can be the CPU, or one of the PAcket Processor Rx components.
+* owner_queue_num  - The relative queue number of the owner of this queue.
+* queue_weight     - Weight, if the queue is added to the WRR Scheduler.
+* queue_size       -
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_tx_q_conf_get(tpm_db_tx_mod_t tx_mod,
+				  uint32_t queue_num,
+				  uint32_t *valid,
+				  tpm_db_sched_t *sched_method,
+				  tpm_db_txq_owner_t *queue_owner,
+				  uint32_t *owner_queue_num, uint32_t *queue_size, uint32_t *queue_weight)
+{
+	if (valid == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].valid == TPM_DB_VALID) {
+		*valid = TPM_TRUE;
+		if (sched_method != NULL)
+			*sched_method = tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].sched_method;
+		if (queue_owner != NULL)
+			*queue_owner = tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].queue_owner;
+		if (owner_queue_num != NULL)
+			*owner_queue_num = tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].owner_queue_num;
+		if (queue_size != NULL)
+			*queue_size = tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].queue_size;
+		if (queue_weight != NULL)
+			*queue_weight = tpm_db.gmac_tx[tx_mod].tx_queue[queue_num].queue_weight;
+	} else {
+		*valid = TPM_FALSE;
+	}
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_rx_q_conf_set()
+*
+* DESCRIPTION:      Function to set the parameters of a Packet Processor Tx Component
+*
+* INPUTS:
+* gmac             - GMAC
+* OUTPUTS:
+* queue_num        - Queue number in this Tx
+* queue_size       -
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_rx_q_conf_set(tpm_gmacs_enum_t gmac, uint32_t queue_num, uint32_t queue_size)
+{
+	if ((gmac >= TPM_MAX_NUM_GMACS) || (queue_num >= TPM_MAX_NUM_RX_QUEUE))
+		return (TPM_DB_ERR_INV_INPUT);
+		
+	tpm_db.gmac_rx[gmac].rx_queue[queue_num].queue_size = queue_size;
+	tpm_db.gmac_rx[gmac].rx_queue[queue_num].valid = TPM_DB_VALID;
+
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_gmac_rx_q_conf_get(tpm_gmacs_enum_t gmac, uint32_t queue_num, uint32_t *valid, uint32_t *queue_size)
+{
+
+	if ((valid == NULL) || (gmac >= TPM_MAX_NUM_GMACS) || (queue_num >= TPM_MAX_NUM_RX_QUEUE))
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (tpm_db.gmac_rx[gmac].rx_queue[queue_num].valid == TPM_DB_VALID) {
+		*valid = TPM_TRUE;
+		if (queue_size != NULL)
+			*queue_size = tpm_db.gmac_rx[gmac].rx_queue[queue_num].queue_size;
+	} else
+		*valid = TPM_FALSE;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_tx_val_set()
+*
+* DESCRIPTION:      Function to set the parameters of a Tx module
+*
+* INPUTS:
+* tx_mod           - Tx Module to validate
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_tx_val_set(tpm_db_tx_mod_t tx_mod)
+{
+	tpm_db.gmac_tx[tx_mod].valid = TPM_DB_VALID;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_rx_val_set()
+*
+* DESCRIPTION:      Function to set the parameters of a Tx module
+*
+* INPUTS:
+* gmac           - GMAC to set active
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_rx_val_set(tpm_gmacs_enum_t gmac)
+{
+	tpm_db.gmac_rx[gmac].valid = TPM_DB_VALID;
+
+	return (TPM_DB_OK);
+}
+
+uint32_t tpm_db_gmac_rx_val_get(tpm_gmacs_enum_t gmac)
+{
+	if (tpm_db.gmac_rx[gmac].valid == TPM_DB_VALID)
+		return (TPM_TRUE);
+	else
+		return (TPM_FALSE);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_func_get()
+*
+* DESCRIPTION:      Check the Function of a GMAC (LAN, WAN or no function)
+*
+* INPUTS:
+* gmac              - GMAC to check
+* OUTPUTS:
+* gfunc             - Functionality the GMAC is performing (None, LAN or WAN)
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_func_get(tpm_gmacs_enum_t gmac, tpm_db_gmac_func_t *gfunc)
+{
+	if (gmac > TPM_MAX_GMAC)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	*gfunc = tpm_db.gmac_func[gmac];
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_func_set()
+*
+* DESCRIPTION:      Sets the Function of a GMAC (LAN, WAN or no function)
+*
+* INPUTS:
+* gmac              - GMAC to set
+* gfunc             - Functionality the GMAC is performing (None, LAN or WAN)
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_gmac_func_set(tpm_gmacs_enum_t gmac, tpm_db_gmac_func_t gfunc)
+{
+	if (gmac > TPM_MAX_GMAC)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	tpm_db.gmac_func[gmac] = gfunc;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_tx_val_get()
+*
+* DESCRIPTION:      Function check the validity of a Tx module
+*
+* INPUTS:
+* tx_mod           - Tx module to check
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+uint32_t tpm_db_gmac_tx_val_get(tpm_db_tx_mod_t tx_mod)
+{
+	if (tpm_db.gmac_tx[tx_mod].valid == TPM_DB_VALID)
+		return (TPM_TRUE);
+	else
+		return (TPM_FALSE);
+}
+
+/*******************************************************************************
+* tpm_db_gmac_lpk_queue_get()
+*
+* DESCRIPTION:      Function to get the queue id used to do gmac loopback on MC
+*
+* INPUTS:
+*	None
+* OUTPUTS:
+* gmac           - gmac on which loopback is done
+* queue_idx      - queue index which do loopback
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*******************************************************************************/
+uint32_t tpm_db_gmac_lpk_queue_get(tpm_gmacs_enum_t *gmac, uint32_t *queue_idx)
+{
+	uint32_t queue_id, q_valid, gmac_id;
+	tpm_db_txq_owner_t queue_owner, lpk_queue_owner = TPM_Q_OWNER_GMAC0;
+	tpm_db_gmac_func_t lpk_gmac_func;
+	tpm_db_tx_mod_t tx_mod;
+
+	/*check input parameters*/
+	if (NULL == gmac || NULL == queue_idx) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input \n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	/*check func profile*/
+	if (!tpm_db_gmac1_lpbk_en_get()) {
+		TPM_OS_ERROR(TPM_DB_MOD, "GMAC1 loopback has not been enabled!\n");
+		return TPM_FALSE;
+	}
+
+	/*Find the GMAC used to do loopback*/
+	for (gmac_id = TPM_ENUM_GMAC_0; gmac_id < TPM_MAX_NUM_GMACS; gmac_id ++) {
+		if (TPM_DB_OK == tpm_db_gmac_func_get(gmac_id, &lpk_gmac_func)) {
+			if (TPM_GMAC_FUNC_LAN == lpk_gmac_func)
+				break;
+		} else {
+			continue;
+		}
+	}
+
+	if (gmac_id == TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Loopback GMAC get failed \n");
+		return TPM_FALSE;
+	} else {
+		tx_mod = (tpm_db_tx_mod_t)gmac_id;
+		lpk_queue_owner = TPM_Q_OWNER_GMAC0;
+	}
+
+	/* get the Tx queue of GMAC1, if more than 1 queue belong to gmac0, lowest index is selected */
+	for (queue_id = 0; queue_id < TPM_MAX_NUM_TX_QUEUE; queue_id++) {
+		if (TPM_DB_OK != tpm_db_gmac_tx_q_conf_get(tx_mod, queue_id, &q_valid, NULL,
+							   &queue_owner, NULL, NULL, NULL))
+			continue;
+		if (q_valid == TPM_TRUE && queue_owner == lpk_queue_owner)
+					break;
+	}
+	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid Tx queue %d of GMAC1 assigned to GMAC0 \n", queue_id);
+		return ERR_SW_TM_QUEUE_INVALID;
+	}
+
+	*gmac = gmac_id;
+	*queue_idx = queue_id;
+
+	return (TPM_DB_OK);
+}
+
+
+/*******************************************************************************
+* tpm_db_pnc_rng_create()
+*
+* DESCRIPTION:      Function to create a range in the DB
+*
+* INPUTS:
+* pnc_range_conf      - Pointer to all config information needed for an entry
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_create(tpm_db_pnc_range_conf_t *pnc_range_conf)
+{
+	uint32_t i;
+	int32_t free_entry = -1;
+
+	/* Check NULL Pointer */
+	if (pnc_range_conf == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	/* Check range_id is not already in DB, and that DB is not full */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID && PNC_RANGE_CONF(i).range_id == pnc_range_conf->range_id)
+			return (TPM_DB_ERR_RANGE_EXIST);
+
+		if ((tpm_db.pnc_range[i].valid == TPM_DB_INVALID) && (free_entry == -1))
+			free_entry = i;
+	}
+	if (free_entry == -1)
+		return (TPM_DB_ERR_DB_TBL_FULL);
+
+	/* Copy Config Structure into DB */
+	memcpy(&(tpm_db.pnc_range[free_entry].pnc_range_conf), pnc_range_conf, sizeof(tpm_db_pnc_range_conf_t));
+
+	/* Init Operational Data */
+	PNC_RANGE_OPER(free_entry).free_entries = (pnc_range_conf->api_end - pnc_range_conf->api_start + 1);
+	PNC_RANGE_OPER(free_entry).num_resets = 0;
+
+	tpm_db.pnc_range[free_entry].valid = TPM_DB_VALID;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_delete()
+*
+* DESCRIPTION:      Initializes and invalidates PnC range
+*
+* INPUTS:
+* pnc_range         - The id of the pnc range that is deleted
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_delete(tpm_pnc_ranges_t pnc_range)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		/* Reset Operational values */
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID &&
+		    tpm_db.pnc_range[i].pnc_range_conf.range_id == pnc_range) {
+			memset(&(tpm_db.pnc_range[i]), 0, sizeof(tpm_pnc_ranges_t));
+			tpm_db.pnc_range[i].valid = TPM_DB_INVALID;
+		}
+	}
+	/* pnc_range not found */
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_reset()
+*
+* DESCRIPTION:      Resets PnC range, all entries are returned to free
+*
+* INPUTS:
+* pnc_range         - The id of the pnc range that is reset
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_reset(tpm_pnc_ranges_t pnc_range)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		/* reach the range to be reset */
+		if (tpm_db.pnc_range[i].pnc_range_conf.range_id == pnc_range) {
+			/* Reset Operational values */
+			if (tpm_db.pnc_range[i].valid == TPM_DB_VALID) {
+				/* both hardcoded and non-hardcoded entries will behave the same from free_entries point of view */
+				PNC_RANGE_OPER(i).free_entries =
+					PNC_RANGE_CONF(i).api_end - PNC_RANGE_CONF(i).api_start + 1;
+				(PNC_RANGE_OPER(i).num_resets)++;
+				return (TPM_DB_OK);
+			}
+		}
+	}
+	/* pnc_range not found */
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_free_ent_inc()
+*
+* DESCRIPTION:      Increases number of free entries for a PnC range
+*
+* INPUTS:
+* pnc_range         - The id of the pnc range that it's free entries is increased
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_free_ent_inc(tpm_pnc_ranges_t pnc_range)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID
+		    && tpm_db.pnc_range[i].pnc_range_conf.range_id == pnc_range) {
+			/* Check number of free entries is not too big */
+			if (PNC_RANGE_OPER(i).free_entries
+			    < (PNC_RANGE_CONF(i).api_end - PNC_RANGE_CONF(i).api_start + 1)) {
+				(PNC_RANGE_OPER(i).free_entries)++;
+				return (TPM_DB_OK);
+			} else
+				return (TPM_DB_ERR_DB_INCONSISTENCY);
+		}
+	}
+	/* pnc_range not found */
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_free_ent_dec()
+*
+* DESCRIPTION:      Decreases number of free entries for a PnC range
+*
+* INPUTS:
+* pnc_range         - The id of the pnc range that it's free entries is decreased
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_free_ent_dec(tpm_pnc_ranges_t pnc_range)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID && PNC_RANGE_CONF(i).range_id == pnc_range) {
+			TPM_OS_DEBUG(TPM_DB_MOD, "range_id(%d), free_ent(%d)\n", pnc_range,
+				     PNC_RANGE_OPER(i).free_entries);
+			/* Check number of free entries is not zero */
+			if (PNC_RANGE_OPER(i).free_entries > 0) {
+				(PNC_RANGE_OPER(i).free_entries)--;
+				return (TPM_DB_OK);
+			} else {
+				TPM_OS_ERROR(TPM_DB_MOD, "no free entries \n");
+				return (TPM_DB_ERR_DB_INCONSISTENCY);
+			}
+		}
+	}
+	/* pnc_range not found */
+	TPM_OS_ERROR(TPM_DB_MOD, "range_id(%d) not found\n", pnc_range);
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_get_lu_conf()
+*
+* DESCRIPTION:      Get PnC least used config for specific PnC range
+*
+* INPUTS:
+* range_id         - The PnC range id
+*
+* OUTPUTS:
+* lu_conf          - Least used configuration for PnC range
+
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_get_lu_conf(tpm_pnc_ranges_t range_id, tpm_api_lu_conf_t *lu_conf)
+{
+	tpm_pnc_ranges_t l_range_idx;
+
+	/* Check PnC range */
+	if ((range_id < 0) || (range_id > (TPM_MAX_NUM_RANGES - 1))) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Error, range_id(%d) is illegal \n", range_id);
+		return (TPM_DB_ERR_INV_INPUT);
+	}
+
+	/* Check input param */
+	if (lu_conf == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Error, lu_conf is NULL \n");
+		return (TPM_DB_ERR_INV_INPUT);
+	}
+
+	/* Get the config from TPM db */
+	for (l_range_idx = 0; l_range_idx < TPM_MAX_RANGE; l_range_idx++) {
+		if (tpm_db.pnc_range[l_range_idx].valid == TPM_DB_VALID
+				&& (PNC_RANGE_CONF(l_range_idx).range_id == range_id)) {
+			lu_conf->cntr_grp    = tpm_db.pnc_range[l_range_idx].pnc_range_conf.cntr_grp;
+			lu_conf->lu_mask     = tpm_db.pnc_range[l_range_idx].pnc_range_conf.lu_mask;
+			break;
+		}
+	}
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_api_start_inc()
+*
+* DESCRIPTION:      Increases number of free entries for a PnC range
+*
+* INPUTS:
+* pnc_range         - The id of the pnc range that it's free entries is increased
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_api_start_inc(tpm_pnc_ranges_t pnc_range)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID
+		    && tpm_db.pnc_range[i].pnc_range_conf.range_id == pnc_range) {
+			/* Check number of free entries is not too big */
+			if (PNC_RANGE_OPER(i).free_entries >= 1) {
+				(PNC_RANGE_CONF(i).api_start)++;
+				(PNC_RANGE_OPER(i).free_entries)--;
+				return (TPM_DB_OK);
+			} else
+				return (TPM_DB_ERR_DB_INCONSISTENCY);
+		}
+	}
+	/* pnc_range not found */
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_api_end_dec()
+*
+* DESCRIPTION:      Decrease number of api_end for a PnC range
+*                   The reason might be addition of an entry at the end of the range.
+*
+* INPUTS:
+* pnc_range         - The id of the pnc range that it's free entries is increased
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_api_end_dec(tpm_pnc_ranges_t pnc_range)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID
+		    && tpm_db.pnc_range[i].pnc_range_conf.range_id == pnc_range) {
+			/* Check number of free entries is not too big */
+			if (PNC_RANGE_OPER(i).free_entries >= 1) {
+				(PNC_RANGE_CONF(i).api_end)--;
+				(PNC_RANGE_OPER(i).free_entries)--;
+				return (TPM_DB_OK);
+			} else
+				return (TPM_DB_ERR_DB_INCONSISTENCY);
+		}
+	}
+	/* pnc_range not found */
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+int32_t tpm_db_api_section_get_from_api_type(tpm_api_type_t api_type, tpm_api_sections_t *api_section)
+{
+	int32_t error_code = TPM_DB_OK;
+
+	/*TODO - replace this w/ conf structure */
+
+	switch (api_type) {
+	case TPM_API_MAC_LEARN:
+		*api_section = TPM_PNC_MAC_LEARN_ACL;
+		break;
+	case TPM_API_CPU_LOOPBACK:
+		*api_section = TPM_CPU_LOOPBACK_ACL;
+		break;
+	case TPM_API_L2_PRIM:
+		*api_section = TPM_L2_PRIM_ACL;
+		break;
+	case TPM_API_L3_TYPE:
+		*api_section = TPM_L3_TYPE_ACL;
+		break;
+	case TPM_API_IPV4:
+		*api_section = TPM_IPV4_ACL;
+		break;
+	case TPM_API_IPV4_MC:
+		*api_section = TPM_IPV4_MC;
+		break;
+	case TPM_API_IPV6_GEN:
+		*api_section = TPM_IPV6_GEN_ACL;
+		break;
+	case TPM_API_IPV6_MC:
+		*api_section = TPM_IPV6_MC_ACL;
+		break;
+	case TPM_API_IPV6_DIP:
+		*api_section = TPM_IPV6_DIP_ACL;
+		break;
+	case TPM_API_IPV6_NH:
+		*api_section = TPM_IPV6_NH_ACL;
+		break;
+	case TPM_API_IPV6_L4:
+		*api_section = TPM_L4_ACL;
+		break;
+	case TPM_API_CNM:
+		*api_section = TPM_CNM_MAIN_ACL;
+		break;
+	default:
+		error_code = TPM_DB_ERR_REC_NOT_EXIST;
+	}
+
+	return (error_code);
+}
+
+
+int32_t tpm_db_api_type_get_from_api_section(tpm_api_sections_t api_section, tpm_api_type_t *api_type)
+{
+	int32_t error_code = TPM_DB_OK;
+
+	/*TODO - replace this w/ conf structure */
+
+	switch (api_section) {
+	case TPM_PNC_MAC_LEARN_ACL:
+		*api_type = TPM_API_MAC_LEARN;
+		break;
+	case TPM_CPU_LOOPBACK_ACL:
+		*api_type = TPM_API_CPU_LOOPBACK;
+		break;
+	case TPM_L2_PRIM_ACL:
+		*api_type = TPM_API_L2_PRIM;
+		break;
+	case TPM_L3_TYPE_ACL:
+		*api_type = TPM_API_L3_TYPE;
+		break;
+	case TPM_IPV4_ACL:
+		*api_type = TPM_API_IPV4;
+		break;
+	case TPM_IPV4_MC:
+		*api_type = TPM_API_IPV4_MC;
+		break;
+	case TPM_IPV6_GEN_ACL:
+		*api_type = TPM_API_IPV6_GEN;
+		break;
+	case TPM_IPV6_DIP_ACL:
+		*api_type = TPM_API_IPV6_DIP;
+		break;
+	case TPM_IPV6_NH_ACL:
+		*api_type = TPM_API_IPV6_NH;
+		break;
+	case TPM_L4_ACL:
+		*api_type = TPM_API_IPV6_L4;
+		break;
+	default:
+		error_code = TPM_DB_ERR_REC_NOT_EXIST;
+	}
+
+	return (error_code);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_get()
+*
+* DESCRIPTION:      Returns DB info of PnC range
+*
+* INPUTS:
+* pnc_range         - The id of the pnc range to get data for
+
+* OUTPUTS:
+* range_data       - Returned DB structure of returned entry.
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_get(tpm_pnc_ranges_t pnc_range, tpm_db_pnc_range_t *range_data)
+{
+	uint32_t i;
+
+	if ((pnc_range < 0) || (pnc_range > (TPM_MAX_NUM_RANGES - 1)))
+		return (TPM_DB_ERR_INV_INPUT);
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID && PNC_RANGE_CONF(i).range_id == pnc_range) {
+			memcpy(range_data, &(tpm_db.pnc_range[i]), sizeof(tpm_db_pnc_range_t));
+			return (TPM_DB_OK);
+		}
+	}
+
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_get_range_start_end()
+*
+* DESCRIPTION:      Returns DB info of PnC range
+*
+* INPUTS:
+* pnc_range         - The id of the pnc range to get data for
+
+* OUTPUTS:
+* range_start      - Returned the start of specific PnC range.
+* range_end        - Returned the end of specific PnC range.
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_get_range_start_end(tpm_pnc_ranges_t pnc_range, uint32_t *range_start, uint32_t *range_end)
+{
+	uint32_t i;
+
+	if ((pnc_range < 0) || (pnc_range > (TPM_MAX_NUM_RANGES - 1)))
+		return(TPM_DB_ERR_INV_INPUT);
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if ((tpm_db.pnc_range[i].valid == TPM_DB_VALID)
+				&& (PNC_RANGE_CONF(i).range_id == pnc_range)) {
+			*range_start = PNC_RANGE_CONF(i).range_start + PNC_RANGE_CONF(i).api_start;
+			*range_end   = PNC_RANGE_CONF(i).range_end;
+			return(TPM_DB_OK);
+		}
+	}
+
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_tbl_val_get_next()
+*
+* DESCRIPTION:      Returns DB info of PnC range
+*
+* INPUTS:
+* cur_ind          - The current index (handle) to the pnc_range table. Function returns the next valid
+*                    pnc range  entry > cur_index. cur_index < 0 indicates to return first valid entry in table,
+*                    valid next_ind values are 0 or higher
+* OUTPUTS:
+* next_ind         - See cur_ind. If end of table was reached before valid entry, (-1) is returned in next_ind
+* range_data       - Returned DB structure of returned entry. When entry is invalid, range_data filled with zero.
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_tbl_val_get_next(int32_t cur_ind, int32_t *next_ind, tpm_db_pnc_range_t *range_data)
+{
+	int32_t i;
+
+	/* Initialize first next_ind */
+	if (cur_ind < 0)
+		i = 0;
+	else
+		i = cur_ind + 1;
+
+	/* Check PnC range exists in DB */
+	for (; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID) {
+			/* Return Data Structure */
+			memcpy(range_data, &(tpm_db.pnc_range[i]), sizeof(tpm_db_pnc_range_t));
+			*next_ind = i;
+			return (TPM_DB_OK);
+		}
+	}
+	*next_ind = -1;
+
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_val_get_next()
+*
+* DESCRIPTION:      Returns DB info of the next valid PnC range.
+*                   Similar to "tpm_db_pnc_rng_tbl_val_get_next", but the handle is the range_id, not the table_index.
+*
+* INPUTS:
+* cur_range        - The current pnc_range  in  the pnc_range table. Function returns the next valid
+*                    pnc_range  > cur_range. cur_range < 0 indicates to return first valid entry in table,
+*                    valid next_ind values are 0 or higher
+* OUTPUTS:
+* next_range       - See cur_range. If end of table was reached before valid entry, (-1) is returned in next_range
+* range_data       - Returned DB structure of returned entry. When entry is invalid, range_data filled with zero.
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_val_get_next(tpm_pnc_ranges_t cur_range,
+				    tpm_pnc_ranges_t *next_range, tpm_db_pnc_range_t *range_data)
+{
+	uint32_t i;
+	uint32_t l_min_index = 0;	/* oren - add init value, need to check */
+	tpm_pnc_ranges_t l_min_range = TPM_MAX_RANGE + 1;
+
+	/* Check  smallest valid next_PnC range in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		/*printf("i(%d) valid(%x) range_id(%d), cur_range(%d) l_min_range(%d)\n",
+		   i,tpm_db.pnc_range[i].valid, PNC_RANGE_CONF(i).range_id, cur_range,l_min_range); */
+		if ((tpm_db.pnc_range[i].valid == TPM_DB_VALID) && (PNC_RANGE_CONF(i).range_id > cur_range)
+		    && (PNC_RANGE_CONF(i).range_id < l_min_range)) {
+			l_min_range = PNC_RANGE_CONF(i).range_id;
+			l_min_index = i;
+		}
+	}
+	if (l_min_range <= TPM_MAX_RANGE) {
+		/* Return Data Structure */
+		memcpy(range_data, &(tpm_db.pnc_range[l_min_index]), sizeof(tpm_db_pnc_range_t));
+		*next_range = l_min_range;
+		return (TPM_DB_OK);
+	}
+
+	/* No valid next range found */
+	*next_range = -1;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_conf_get()
+*
+* DESCRIPTION:      Returns DB info of PnC range
+*
+* INPUTS:
+* range_id         - Range number to retrieve configuration for
+
+* OUTPUTS:
+* range_conf       - Structure for pnc_range Configuration Info
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_conf_get(tpm_pnc_ranges_t range_id, tpm_db_pnc_range_conf_t *range_conf)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID
+		    && tpm_db.pnc_range[i].pnc_range_conf.range_id == range_id) {
+			/* Return Data Structure */
+			memcpy(range_conf, &(tpm_db.pnc_range[i].pnc_range_conf), sizeof(tpm_db_pnc_range_conf_t));
+			return (TPM_DB_OK);
+		}
+	}
+	/* pnc_range not found */
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_oper_get()
+*
+* DESCRIPTION:      Returns DB info of PnC range
+*
+* INPUTS:
+* range_id         - Range number to retrieve configuration for
+
+* OUTPUTS:
+* range_oper       - Structure for pnc_range Operational Info
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_oper_get(tpm_pnc_ranges_t range_id, tpm_db_pnc_range_oper_t *range_oper)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID
+		    && tpm_db.pnc_range[i].pnc_range_conf.range_id == range_id) {
+			/* Return Data Structure */
+			memcpy(range_oper, &(tpm_db.pnc_range[i].pnc_range_oper), sizeof(tpm_db_pnc_range_oper_t));
+			return (TPM_DB_OK);
+		}
+	}
+	/* pnc_range not found */
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_rng_free_ent_get()
+*
+* DESCRIPTION:      Returns number of free entries of PnC range
+*
+* INPUTS:
+* range_id         - Range number to retrieve number of free entries
+
+* OUTPUTS:
+* free_entries      - Number of free entries in Table
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_rng_free_ent_get(tpm_pnc_ranges_t range_id, uint32_t *free_entries)
+{
+	uint32_t i;
+
+	/* Check PnC range exists in DB */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+		if (tpm_db.pnc_range[i].valid == TPM_DB_VALID
+		    && tpm_db.pnc_range[i].pnc_range_conf.range_id == range_id) {
+			/* Return Free Entries */
+			*free_entries = PNC_RANGE_OPER(i).free_entries;
+			return (TPM_DB_OK);
+		}
+	}
+	/* pnc_range not found */
+	*free_entries = 0;
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_owner_set()
+*
+* DESCRIPTION:      Creates an owner_id in the DB.
+*
+* INPUTS:
+* owner_id         - Id of new owner
+
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_owner_set(uint32_t owner_id)
+{
+	uint32_t i;
+	int32_t free_ind = -1;
+
+	/* Check owner was not already set */
+	for (i = 0; i < TPM_MAX_API_TYPES; i++) {
+		if ((tpm_db.owners[i].valid == TPM_DB_VALID) && (tpm_db.owners[i].owner_id == owner_id))
+			return (TPM_DB_ERR_REC_EXIST);
+		if ((free_ind == -1) && (tpm_db.owners[i].valid == TPM_DB_INVALID))
+			free_ind = i;
+	}
+	if (free_ind == -1)
+		return (TPM_DB_ERR_DB_TBL_FULL);
+
+	/* Set on first free index */
+	tpm_db.owners[free_ind].valid = TPM_DB_VALID;
+	tpm_db.owners[free_ind].owner_id = owner_id;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_owner_get_next()
+*
+* DESCRIPTION:      Returns DB info of PnC range
+*
+* INPUTS:
+* cur_ind          - The current index (handle) to the owner table. Function returns the next
+*                    valid table entry > cur_index. cur_index < 0 indicates to return first valid entry in table,
+*                    valid next_ind values are 0 or higher.
+* OUTPUTS:
+* next_ind         - See cur_ind. If end of table was reached before valid entry, (-1) is returned in next_ind
+* owner            - Returns the owner of the next index.
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t. No more owners is not considered error.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_owner_get_next(int32_t cur_ind, int32_t *next_ind, uint32_t *owner)
+{
+	uint32_t i;
+
+	/* Initialize first next_ind */
+	if (cur_ind < 0)
+		i = 0;
+	else
+		i = cur_ind + 1;
+
+	/* Check owner exists in DB */
+	for (; i < TPM_MAX_API_TYPES; i++) {
+		if (tpm_db.owners[i].valid == TPM_DB_VALID) {	/* oren - changed = to ==, need to check */
+			/* Return Data Structure */
+			*next_ind = i;
+			*owner = tpm_db.owners[i].owner_id;
+			return (TPM_DB_OK);
+		}
+	}
+	/* No valid entry found */
+	*next_ind = -1;
+
+	return (TPM_DB_OK);
+}
+
+#if 0
+/*******************************************************************************
+* tpm_db_apig_set()
+*
+* DESCRIPTION:      Creates an API Group in the DB.
+*
+* INPUTS:
+* owner_id         - owner of the API Group
+* api_type        - API Group being created
+
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+int32_t tpm_db_apig_set(uint32_t owner_id, tpm_api_type_t api_type)
+{
+	uint32_t i;
+
+	/* Check owner exists */
+	for (i = 0; i < TPM_MAX_API_TYPES; i++) {
+		if ((tpm_db.owners[i].valid == TPM_DB_VALID) && (tpm_db.owners[i].owner_id == owner_id))
+			break;
+	}
+	if (i == TPM_MAX_API_TYPES)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	/* Check api_type does not exist */
+	if (tpm_db.api_groups[api_type].valid == TPM_DB_VALID)
+		return (TPM_DB_ERR_REC_EXIST);
+
+	tpm_db.api_groups[api_type].valid = TPM_DB_VALID;
+	tpm_db.api_groups[api_type].api_owner_id = owner_id;
+	tpm_db.api_groups[api_type].api_type = api_type;
+
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_apig_get_next()
+*
+* DESCRIPTION:      Returns DB info of API Group
+*
+* INPUTS:
+* cur_ind          - The current index (handle) to the owner table. Function returns the next
+*                    valid table entry > cur_index. cur_index < 0 indicates to return first valid entry in table,
+*                    valid next_ind values are 0 or higher.
+* OUTPUTS:
+* next_ind         - See cur_ind. If end of table was reached before valid entry, (-1) is returned in next_ind
+* api_type         - Returns the API Group.
+* owner            - Returns the owner of the API Group.
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_apig_get_next(int32_t cur_ind, int32_t *next_ind, uint32_t *owner, tpm_api_type_t *api_type)
+{
+	uint32_t i;
+
+	/* Initialize first next_ind */
+	if (cur_ind < 0)
+		i = 0;
+	else
+		i = cur_ind + 1;
+
+	/* Check API Group exists in DB */
+	for (; i < TPM_MAX_API_TYPES; i++) {
+		if (tpm_db.api_groups[i].valid == TPM_DB_VALID) {
+			/* Return Data  */
+			*next_ind = i;
+			*api_type = tpm_db.api_groups[i].api_type;
+			*owner = tpm_db.api_groups[i].api_owner_id;
+			return (TPM_DB_OK);
+		}
+	}
+	/* No valid entry found */
+	*next_ind = -1;
+	return (TPM_DB_OK);
+}
+#endif
+
+/*******************************************************************************
+* tpm_db_igmp_set_port_frwd_mode()
+*
+* DESCRIPTION:      Set the IGMP status of a UNI port or WAN port
+*
+* INPUTS:
+* src_port          - source port to set
+* igmp_state       - how to process IGMP packets
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_igmp_set_port_frwd_mode(uint32_t port, uint32_t mode)
+{
+	tpm_db.igmp_def.frwd_mode[port] = mode;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_igmp_get_port_frwd_mode()
+*
+* DESCRIPTION:      Get the IGMP status of a UNI port or WAN port
+*
+* INPUTS:
+* src_port          - source port to get
+*
+* OUTPUTS:
+* igmp_state       - how to process IGMP packets
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_igmp_get_port_frwd_mode(uint32_t port, uint32_t *mode)
+{
+	*mode = tpm_db.igmp_def.frwd_mode[port];
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_igmp_set_cpu_queue()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_igmp_set_cpu_queue(uint32_t queue)
+{
+	tpm_db.igmp_def.cpu_queue = queue;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_igmp_get_cpu_queue()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_igmp_get_cpu_queue(uint32_t *queue)
+{
+	*queue = tpm_db.igmp_def.cpu_queue;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_omci_type_set()
+*
+* DESCRIPTION:      Set OMCI ethertype
+*
+* INPUTS:
+* omci_etype       - OMCI Ethertype
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_omci_type_set(uint32_t omci_etype)
+{
+	tpm_db.init_misc.omci_etype = omci_etype;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_omci_type_get()
+*
+* DESCRIPTION:      Get OMCI ethertype
+*
+* OUTPUTS:
+* omci_etype       - OMCI Ethertype
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_omci_type_get(uint32_t *omci_etype)
+{
+	*omci_etype = tpm_db.init_misc.omci_etype;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_omci_channel_set()
+*
+* DESCRIPTION:      Set OMCI channel parameters
+*
+* INPUTS:
+* gemport       - OMCI GEM port ID
+* cpu_rx_q      - OMCI cpu rx queue
+* cpu_tx_q      - OMCI cpu tx queue
+* tcont_id      - OMCI tcont ID
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_omci_channel_set(uint16_t gemport, uint32_t cpu_rx_q, uint32_t cpu_tx_q, uint32_t tcont_id)
+{
+	tpm_db.init_misc.omci_gemport = gemport;
+	tpm_db.init_misc.oam_cpu_rx_q = cpu_rx_q;
+	tpm_db.init_misc.oam_cpu_tx_q = cpu_tx_q;
+	tpm_db.init_misc.oam_cpu_tx_port = tcont_id;
+	tpm_db.init_misc.oam_channel_configured = 1;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_omci_channel_remove()
+*
+* DESCRIPTION:      Remove OMCI channel parameters
+*
+* INPUTS:
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_omci_channel_remove(void)
+{
+	tpm_db.init_misc.omci_gemport = 0;
+	tpm_db.init_misc.oam_cpu_rx_q = 0;
+	tpm_db.init_misc.oam_cpu_tx_q = 0;
+	tpm_db.init_misc.oam_cpu_tx_port = 0;
+	tpm_db.init_misc.oam_channel_configured = 0;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_oam_loopback_state_get()
+*
+* DESCRIPTION:      Get OAM loopback configure state
+*
+* OUTPUTS:
+* omci_etype       - OMCI Ethertype
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_oam_loopback_state_get(uint32_t *loopback)
+{
+	*loopback = tpm_db.init_misc.oam_loopback_channel_configured;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_oam_loopback_channel_set()
+*
+* DESCRIPTION:      Set OAM loopback channel state
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_oam_loopback_channel_set(void)
+{
+	tpm_db.init_misc.oam_loopback_channel_configured = 1;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_omci_channel_remove()
+*
+* DESCRIPTION:      Remove OMCI channel parameters
+*
+* INPUTS:
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_oam_loopback_channel_remove(void)
+{
+	tpm_db.init_misc.oam_loopback_channel_configured = 0;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_omci_channel_get()
+*
+* DESCRIPTION:      Get OMCI channel parameters
+*
+* INPUTS:
+* gemport       - OMCI GEM port ID
+* cpu_rx_q      - OMCI cpu rx queue
+* cpu_tx_q      - OMCI cpu tx queue
+* tcont_id      - OMCI tcont ID
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_omci_channel_get(uint32_t *valid, uint16_t *gemport, uint32_t *cpu_rx_q, uint32_t *cpu_tx_q,
+				uint32_t *tcont_id)
+{
+	*gemport = tpm_db.init_misc.omci_gemport;
+	*cpu_rx_q = tpm_db.init_misc.oam_cpu_rx_q;
+	*cpu_tx_q = tpm_db.init_misc.oam_cpu_tx_q;
+	*tcont_id = tpm_db.init_misc.oam_cpu_tx_port;
+	*valid = tpm_db.init_misc.oam_channel_configured;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_oam_channel_set()
+*
+* DESCRIPTION:      Set OAM channel parameters
+*
+* INPUTS:
+* cpu_rx_q      - OAM cpu rx queue
+* cpu_tx_q      - OAM cpu tx queue
+* llid          - OAM LLID
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_oam_channel_set(uint32_t cpu_rx_q, uint32_t cpu_tx_q, uint32_t llid)
+{
+	tpm_db.init_misc.oam_cpu_rx_q = cpu_rx_q;
+	tpm_db.init_misc.oam_cpu_tx_q = cpu_tx_q;
+	tpm_db.init_misc.oam_cpu_tx_port = llid;
+	tpm_db.init_misc.oam_channel_configured = 1;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_oam_channel_remove()
+*
+* DESCRIPTION:      Remove OAM channel parameters
+*
+* INPUTS:
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_oam_channel_remove(void)
+{
+	tpm_db.init_misc.omci_gemport = 0;
+	tpm_db.init_misc.oam_cpu_rx_q = 0;
+	tpm_db.init_misc.oam_cpu_tx_q = 0;
+	tpm_db.init_misc.oam_cpu_tx_port = 0;
+	tpm_db.init_misc.oam_channel_configured = 0;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_oam_channel_get()
+*
+* DESCRIPTION:      Get OAM channel parameters
+*
+* INPUTS:
+* cpu_rx_q      - OAM cpu rx queue
+* cpu_tx_q      - OAM cpu tx queue
+* tcont_id      - OAM llid
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_oam_channel_get(uint32_t *valid, uint32_t *cpu_rx_q, uint32_t *cpu_tx_q, uint32_t *llid)
+{
+	*cpu_rx_q = tpm_db.init_misc.oam_cpu_rx_q;
+	*cpu_tx_q = tpm_db.init_misc.oam_cpu_tx_q;
+	*llid = tpm_db.init_misc.oam_cpu_tx_port;
+	*valid = tpm_db.init_misc.oam_channel_configured;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_init_deb_port_set()
+*
+* DESCRIPTION:      Set Init Debug Port
+*
+* INPUTS:
+* pnc_init_debug_port       - Set the debug Port, which will be preconfigured to send
+*                             all traffic to CPU (NFS port for development)
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+#if 0
+int32_t tpm_db_pnc_init_deb_port_set(uint32_t pnc_init_debug_port)
+{
+	tpm_db.init_misc.pnc_init_debug_port = pnc_init_debug_port;
+
+	return (TPM_DB_OK);
+
+}
+#endif
+
+/*******************************************************************************
+* tpm_db_pnc_init_deb_port_get()
+*
+* DESCRIPTION:      Get Debug Port
+*
+* OUTPUTS:
+* pnc_init_debug_port  - Get the debug Port, which will be preconfigured to send all
+*                        traffic to CPU (NFS port for development)
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+#if 0
+int32_t tpm_db_pnc_init_deb_port_get(uint32_t *pnc_init_debug_port)
+{
+	*pnc_init_debug_port = tpm_db.init_misc.pnc_init_debug_port;
+
+	return (TPM_DB_OK);
+}
+#endif
+
+/*******************************************************************************
+* tpm_db_init_done_set()
+*
+* DESCRIPTION:      Set TPM was successfully Initialized
+*
+* INPUTS:
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_init_done_set(void)
+{
+	tpm_db.init_misc.tpm_init_succeeded = TPM_DB_VALID;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_init_done_get()
+*
+* DESCRIPTION:      Get value if TPM was successfully Initialized
+*
+* OUTPUTS:
+* tpm_init_succeeded  -
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_init_done_get(void)
+{
+	if (tpm_db.init_misc.tpm_init_succeeded == TPM_DB_VALID)
+		return (1);
+	return (0);
+}
+
+/*******************************************************************************
+* tpm_db_pon_type_set()
+*
+* DESCRIPTION:      Set WAN technology
+*
+* INPUTS:
+* pon_type          - GPON, EPON, Ethernet or None
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pon_type_set(tpm_db_pon_type_t pon_type)
+{
+	tpm_db.init_misc.pon_type = pon_type;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pon_type_get()
+*
+* DESCRIPTION:      Get WAN technology
+*
+* OUTPUTS:
+* pon_type          - GPON, EPON, Ethernet or None
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pon_type_get(tpm_db_pon_type_t *pon_type)
+{
+	*pon_type = tpm_db.init_misc.pon_type;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_backup_wan_set()
+*
+* DESCRIPTION:      Set WAN technology
+*
+* INPUTS:
+* pon_type          - GPON, EPON, Ethernet or None
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_backup_wan_set(tpm_gmacs_enum_t backup_wan)
+{
+	tpm_db.init_misc.backup_wan = backup_wan;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_backup_wan_get()
+*
+* DESCRIPTION:      Set WAN technology
+*
+* INPUTS:
+* pon_type          - GPON, EPON, Ethernet or None
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_backup_wan_get(tpm_gmacs_enum_t *backup_wan)
+{
+	*backup_wan = tpm_db.init_misc.backup_wan;
+	return (TPM_DB_OK);
+}
+
+tpm_gmacs_enum_t tpm_db_active_wan_get()
+{
+	switch (tpm_db.eth_cmplx_profile) {
+	case TPM_PON_G1_WAN_G0_INT_SWITCH:
+		return (tpm_db.init_misc.backup_wan == TPM_ENUM_PMAC) ? TPM_ENUM_GMAC_1 : TPM_ENUM_PMAC;
+
+	case TPM_PON_G0_WAN_G1_INT_SWITCH:
+		return (tpm_db.init_misc.backup_wan == TPM_ENUM_PMAC) ? TPM_ENUM_GMAC_0 : TPM_ENUM_PMAC;
+
+	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
+		return (tpm_db.init_misc.backup_wan == TPM_ENUM_PMAC) ? TPM_ENUM_GMAC_0 : TPM_ENUM_PMAC;
+
+	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
+		return (tpm_db.init_misc.backup_wan == TPM_ENUM_PMAC) ? TPM_ENUM_GMAC_1 : TPM_ENUM_PMAC;
+
+	case TPM_G0_WAN_G1_INT_SWITCH:
+		return TPM_ENUM_GMAC_0;
+
+	case TPM_G1_WAN_G0_INT_SWITCH:
+		return TPM_ENUM_GMAC_1;
+
+	default:
+		return TPM_ENUM_PMAC;
+	}
+}
+
+/*******************************************************************************
+* tpm_db_pnc_mac_learn_enable_set()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_mac_learn_enable_set(tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable)
+{
+	tpm_db.init_misc.pnc_mac_learn_enable = pnc_mac_learn_enable;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_mac_learn_enable_get()
+*
+* DESCRIPTION:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_mac_learn_enable_get(tpm_init_pnc_mac_learn_enable_t *pnc_mac_learn_enable)
+{
+	*pnc_mac_learn_enable = tpm_db.init_misc.pnc_mac_learn_enable;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_fc_conf_set()
+*
+* DESCRIPTION:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_fc_conf_set(tpm_init_fc_params_t *port_fc_conf)
+{
+	memcpy(&tpm_db.port_fc_conf, port_fc_conf, sizeof(tpm_db_fc_params_t));
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_fc_conf_get()
+*
+* DESCRIPTION:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_fc_conf_get(tpm_init_fc_params_t *port_fc_conf)
+{
+	memcpy(port_fc_conf, &tpm_db.port_fc_conf, sizeof(tpm_db_fc_params_t));
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_switch_init_set()
+*
+* DESCRIPTION: Set Amber Initialization
+*
+* INPUTS:
+* switch_init
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_switch_init_set(uint32_t switch_init)
+{
+	tpm_db.func_profile.switch_init = switch_init;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_switch_init_get()
+*
+* DESCRIPTION: Get Amber Initialization
+*
+* INPUTS:
+* switch_init
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_switch_init_get(uint32_t *switch_init)
+{
+	*switch_init = tpm_db.func_profile.switch_init;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_ds_mh_set_conf_set()
+*
+* DESCRIPTION:      Set downstream marvell header source select
+*
+* INPUTS:
+* ds_mh_set_conf    - Allow set MH in Pnc or not
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_ds_mh_set_conf_set(tpm_db_mh_src_t ds_mh_set_conf)
+{
+	tpm_db.init_misc.ds_mh_set_conf = ds_mh_set_conf;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_ds_mh_get_conf_set()
+*
+* DESCRIPTION:      Set downstream marvell header source select
+*
+* INPUTS:
+*
+* OUTPUTS:
+* ds_mh_set_conf    - Allow set MH in Pnc or not
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_ds_mh_get_conf_set(tpm_db_mh_src_t *ds_mh_set_conf)
+{
+	*ds_mh_set_conf = tpm_db.init_misc.ds_mh_set_conf;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_cfg_pnc_parse_set()
+*
+* DESCRIPTION:      Set config PNC parse enabled/disabled in DB
+*
+* INPUTS:
+* cfg_pnc_parse          0=DISABLED  /  1=ENABLED
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_cfg_pnc_parse_set(tpm_init_cfg_pnc_parse_t cfg_pnc_parse)
+{
+	tpm_db.init_misc.cfg_pnc_parse = cfg_pnc_parse;
+
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_cpu_loopback_set()
+*
+* DESCRIPTION:      Set cpu loopback enabled/disabled in DB
+*
+* INPUTS:
+* cpu_loopback          0=DISABLED  /  1=ENABLED
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_cpu_loopback_set(tpm_init_cpu_loopback_t cpu_loopback)
+{
+	tpm_db.init_misc.cpu_loopback = cpu_loopback;
+
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_cfg_pnc_parse_get()
+*
+* DESCRIPTION:      Get config PNC parse enabled/disabled in DB
+*
+* OUTPUTS:
+* cfg_pnc_parse_val          0=DISABLED  /  1=ENABLED
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_cfg_pnc_parse_get(tpm_init_cfg_pnc_parse_t *cfg_pnc_parse_val)
+{
+	*cfg_pnc_parse_val = tpm_db.init_misc.cfg_pnc_parse;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_cpu_loopback_get()
+*
+* DESCRIPTION:      Get CPU loopback enabled/disabled in DB
+*
+* OUTPUTS:
+* cpu_loopback_val          0=DISABLED  /  1=ENABLED
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_cpu_loopback_get(tpm_init_cpu_loopback_t *cpu_loopback_val)
+{
+	*cpu_loopback_val = tpm_db.init_misc.cpu_loopback;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_double_tag_support_set()
+*
+* DESCRIPTION:      Set config double tagged supported in DB
+*
+* INPUTS:
+* dbl_tag          0=DISABLED  /  1=ENABLED
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_double_tag_support_set(tpm_init_double_tag_t dbl_tag)
+{
+	tpm_db.init_misc.dbl_tag = dbl_tag;
+
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_double_tag_support_get()
+*
+* DESCRIPTION:      Get config double tagged supported in DB
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_double_tag_support_get(tpm_init_double_tag_t *dbl_tag)
+{
+	*dbl_tag = tpm_db.init_misc.dbl_tag;
+
+	return (TPM_DB_OK);
+}
+
+#if 0
+/*******************************************************************************
+* tpm_db_default_tag_tpid_set()
+*
+* DESCRIPTION:      Set tpid of one/two vlan tag in DB
+*
+* INPUTS:
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_default_tag_tpid_set(uint16_t vlan1_tpid, uint16_t vlan2_tpid)
+{
+	tpm_db.init_misc.vlan1_tpid = vlan1_tpid;
+	tpm_db.init_misc.vlan2_tpid = vlan2_tpid;
+
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_default_tag_tpid_get()
+*
+* DESCRIPTION:      Get tpid of one/two vlan tag in DB
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_default_tag_tpid_get(uint16_t *vlan1_tpid, uint16_t *vlan2_tpid)
+{
+	*vlan1_tpid = tpm_db.init_misc.vlan1_tpid;
+	*vlan2_tpid = tpm_db.init_misc.vlan2_tpid;
+
+	return (TPM_DB_OK);
+}
+#endif
+
+/*******************************************************************************
+* tpm_db_default_tag_tpid_set()
+*
+* DESCRIPTION:      Set tpid of one/two vlan tag in DB
+*
+* INPUTS:
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_default_tag_tpid_set(tpm_init_tpid_opt_t *tag_tpid)
+{
+	memcpy(&tpm_db.init_misc.tag_tpid, tag_tpid, sizeof(tpm_init_tpid_opt_t));
+	return(TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_default_tag_tpid_get()
+*
+* DESCRIPTION:      Get tpid of one/two vlan tag in DB
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_default_tag_tpid_get(tpm_init_tpid_opt_t *tag_tpid)
+{
+	memcpy(tag_tpid, &tpm_db.init_misc.tag_tpid, sizeof(tpm_init_tpid_opt_t));
+	return(TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_virt_info_set()
+*
+* DESCRIPTION:      Set wifi via UNI in TPM DB
+*
+* INPUTS:
+* virt_uni_info.enabled          0=DISABLED  /  1=ENABLED
+* virt_uni_info.uni_port             port#
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_virt_info_set(tpm_init_virt_uni_t virt_uni_info)
+{
+	tpm_db.func_profile.virt_uni_info.enabled = virt_uni_info.enabled;
+	tpm_db.func_profile.virt_uni_info.uni_port = virt_uni_info.uni_port;
+	tpm_db.func_profile.virt_uni_info.switch_port = virt_uni_info.switch_port;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_virt_info_get()
+*
+* DESCRIPTION:      Get wifi via UNI in TPM DB
+*
+* OUTPUTS:
+* virt_uni_info.enabled          0=DISABLED  /  1=ENABLED
+* virt_uni_info.uni_port             port#
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_virt_info_get(tpm_init_virt_uni_t *virt_uni_info)
+{
+	virt_uni_info->enabled 		= tpm_db.func_profile.virt_uni_info.enabled;
+	virt_uni_info->uni_port 	= tpm_db.func_profile.virt_uni_info.uni_port;
+	virt_uni_info->switch_port 	= tpm_db.func_profile.virt_uni_info.switch_port;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_ipv6_5t_enable_set()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_ipv6_5t_enable_set(tpm_init_ipv6_5t_enable_t ipv6_5t_enable)
+{
+	tpm_db.init_misc.ipv6_5t_enable = ipv6_5t_enable;
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_ipv6_5t_enable_get()
+*
+* DESCRIPTION:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_ipv6_5t_enable_get(tpm_init_ipv6_5t_enable_t *ipv6_5t_enable)
+{
+	*ipv6_5t_enable = tpm_db.init_misc.ipv6_5t_enable;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_port_vector_tbl_info_set()
+*
+* DESCRIPTION:      Set MH port vector table in TPM DB.
+*
+* OUTPUTS:
+* tpm_mh_port_vector_tbl_new
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_port_vector_tbl_info_set(uint32_t reg_num, uint32_t uni_vector, uint16_t amber_port_vector,
+					uint32_t pnc_vector)
+{
+	if (TPM_TX_MAX_MH_REGS <= reg_num)
+		return TPM_DB_ERR_REC_INV;
+
+	tpm_db.tpm_mh_port_vector_tbl[reg_num].uni_vector = uni_vector;
+	tpm_db.tpm_mh_port_vector_tbl[reg_num].pnc_vector = pnc_vector;
+	tpm_db.tpm_mh_port_vector_tbl[reg_num].amber_port_vector = amber_port_vector;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_port_vector_tbl_info_get()
+*
+* DESCRIPTION:      Get MH port vector table in TPM DB.
+*
+* OUTPUTS:
+* tpm_mh_port_vector_tbl_new
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_port_vector_tbl_info_get(uint32_t reg_num, uint32_t *uni_vector, uint16_t *amber_port_vector,
+					uint32_t *pnc_vector)
+{
+	if (TPM_TX_MAX_MH_REGS <= reg_num)
+		return TPM_DB_ERR_REC_INV;
+
+	*uni_vector = tpm_db.tpm_mh_port_vector_tbl[reg_num].uni_vector;
+	*pnc_vector = tpm_db.tpm_mh_port_vector_tbl[reg_num].pnc_vector;
+	*amber_port_vector = tpm_db.tpm_mh_port_vector_tbl[reg_num].amber_port_vector;
+	return (TPM_DB_OK);
+}
+
+
+/*******************************************************************************
+* tpm_db_port_vector_tbl_info_search()
+*
+* DESCRIPTION:      Search in the MH port vector table in TPM DB for matching target port
+*
+* OUTPUTS:
+* tpm_mh_port_vector_tbl_new
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_port_vector_tbl_info_search(tpm_trg_port_type_t  trg_port, uint32_t *uni_vector,
+					    uint16_t *amber_port_vector, uint32_t *pnc_vector)
+{
+	uint32_t reg_num;
+
+	for (reg_num = 0; reg_num < TPM_TX_MAX_MH_REGS; reg_num++) {
+		if (trg_port == tpm_db.tpm_mh_port_vector_tbl[reg_num].uni_vector) {
+			*uni_vector = tpm_db.tpm_mh_port_vector_tbl[reg_num].uni_vector;
+			*pnc_vector = tpm_db.tpm_mh_port_vector_tbl[reg_num].pnc_vector;
+			*amber_port_vector = tpm_db.tpm_mh_port_vector_tbl[reg_num].amber_port_vector;
+			return TPM_DB_OK;
+		}
+	}
+
+	return TPM_DB_ERR_REC_INV;
+}
+
+
+
+/*******************************************************************************
+* tpm_db_api_section_ent_tbl_reset()
+*
+* DESCRIPTION:      Reset an API table/acl
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_ent_tbl_reset(uint32_t start_entry, uint32_t num_entries)
+{
+	uint32_t i;
+
+	/*Init API Rng Entries */
+	memset(&(tpm_db.api_ent_mem_area[mem_alloc_start_ind]), 0, (num_entries) * (sizeof(tpm_db_api_entry_t)));
+
+	/* Invalidate API Rng Entries */
+	for (i = start_entry; i < (start_entry + num_entries); i++)
+		tpm_db.api_ent_mem_area[i].valid = TPM_DB_INVALID;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_ent_tbl_get()
+*
+* DESCRIPTION:      get an API table/acl entry
+*
+* INPUTS:
+* api_sec      - Section of the API acl/table
+* index        - rule index
+* OUTPUTS:
+* api_ent_mem_area - table/acl entry
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_ent_tbl_get(tpm_api_sections_t api_sec, tpm_db_api_entry_t *api_ent_mem_area, uint32_t index)
+{
+	if (ILLEGAL_API_SEC(api_sec))
+		IF_ERROR_I(TPM_DB_ERR_REC_NOT_EXIST, api_sec);
+
+	if (NULL == api_ent_mem_area)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	memcpy(api_ent_mem_area, &tpm_db.api_ent_mem_area[(tpm_db.api_section[api_sec].table_start) + index], sizeof(tpm_db_api_entry_t));
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_init()
+*
+* DESCRIPTION:      Initialize an API table/acl
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* api_rng_size     - Size of the table/acl
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_init(tpm_api_sections_t api_section, tpm_pnc_ranges_t prim_pnc_range, uint32_t api_rng_size)
+{
+
+	/* Check that new api_rng table does not cross allocation boundaries */
+	if ((mem_alloc_start_ind + api_rng_size) > TPM_DB_API_ENTRIES_TBL_SIZE) {
+		TPM_OS_ERROR(TPM_DB_MOD, " API Range not created, Entries Area overflow, "
+			     "ind_start(%d), api_rng_size(%d), mem_area_size(%d) \n",
+			     mem_alloc_start_ind, api_rng_size, TPM_DB_API_ENTRIES_TBL_SIZE);
+
+		return (TPM_DB_ERR_DB_TBL_FULL);
+	}
+	if ((mem_alloc_start_ind + api_rng_size) > (TPM_DB_API_ENTRIES_TBL_SIZE - TPM_DB_API_SECTION_MARGIN_SIZE)) {
+		TPM_OS_WARN(TPM_DB_MOD, "Entries Area has less than calculated end margin, "
+			    "ind_start(%d), api_rng_size(%d), mem_area_size(%d)\n",
+			    mem_alloc_start_ind, api_rng_size, TPM_DB_API_ENTRIES_TBL_SIZE);
+	}
+
+	/*Init API Range */
+	memset(&(tpm_db.api_section[api_section]), 0, sizeof(tpm_db_api_section_t));
+
+	tpm_db_api_section_ent_tbl_reset(mem_alloc_start_ind, api_rng_size);
+
+	tpm_db.api_section[api_section].table_size = api_rng_size;
+	tpm_db.api_section[api_section].table_start = mem_alloc_start_ind;
+	tpm_db.api_section[api_section].valid = TPM_DB_VALID;
+	tpm_db.api_section[api_section].prim_pnc_range = prim_pnc_range;
+	tpm_db.api_section[api_section].last_valid_entry = -1;
+	tpm_db.api_section[api_section].last_valid_index = -1;
+	tpm_db.api_section[api_section].num_valid_entries = 0;
+
+	/* Forward to next 'API Entries table' start_index.
+	 * This also inserts 'margin_size' between subsequent 'API Entries table' */
+	mem_alloc_start_ind += (api_rng_size + TPM_DB_API_SECTION_MARGIN_SIZE);
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_entries_area_reset()
+*
+* DESCRIPTION:      Reset an API table/acl
+*
+* INPUTS:
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_entries_area_reset(void)
+{
+	/* Stripe API Entries Area */
+	memset(tpm_db.api_ent_mem_area, MEM_MARGIN_PATTERN, sizeof(tpm_db.api_ent_mem_area));
+
+	/* Reset Area Index, Start Area offset at margin_size */
+	mem_alloc_start_ind = TPM_DB_API_SECTION_MARGIN_SIZE;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_invalidate()
+*
+* DESCRIPTION:      Reset an API table/acl
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_invalidate(tpm_api_sections_t api_section)
+{
+	/*Init API Range */
+	memset(&(tpm_db.api_section[api_section]), 0, sizeof(tpm_db_api_section_t));
+
+	/* Invalidate Range */
+	tpm_db.api_section[api_section].valid = TPM_DB_INVALID;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_reset()
+*
+* DESCRIPTION:      Initialize an API table/acl
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_reset(tpm_api_sections_t api_section)
+{
+	/* prim_pnc_range, table_size, table_start attributes are retained from init */
+
+	tpm_db.api_section[api_section].num_valid_entries = 0;
+	tpm_db.api_section[api_section].last_valid_entry = -1;
+	tpm_db.api_section[api_section].last_valid_index = -1;
+
+	/* Invalidate all API entries */
+	tpm_db_api_section_ent_tbl_reset(tpm_db.api_section[api_section].table_start,
+					 tpm_db.api_section[api_section].table_size);
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_get()
+*
+* DESCRIPTION:      Get
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* OUTPUTS:
+* api_rng_size      - API range size
+* num_valid_entries- Number of valid entries
+* last_valid - Last valid entry
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_get(tpm_api_sections_t api_section,
+			       uint32_t 	*api_rng_size,
+			       uint32_t 	*num_valid_entries,
+			       tpm_pnc_ranges_t	*prim_pnc_range,
+			       int32_t 		*last_valid_entry,
+			       uint32_t 	*tbl_start)
+{
+	if (ILLEGAL_API_SEC(api_section))
+		IF_ERROR_I(TPM_DB_ERR_REC_NOT_EXIST, api_section);
+
+	if (tpm_db.api_section[api_section].valid == TPM_DB_INVALID)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	*api_rng_size = tpm_db.api_section[api_section].table_size;
+	*num_valid_entries = tpm_db.api_section[api_section].num_valid_entries;
+	*prim_pnc_range = tpm_db.api_section[api_section].prim_pnc_range;
+	*last_valid_entry = tpm_db.api_section[api_section].last_valid_entry;
+	*tbl_start = tpm_db.api_section[api_section].table_start;
+
+	TPM_OS_DEBUG(TPM_DB_MOD,
+		     "returned size(%d), num_entries(%d), prim_pnc_range(%d), last_valid_entry (%d) tbl_start(%d)\n",
+		     *api_rng_size, *num_valid_entries, *prim_pnc_range, *last_valid_entry, *tbl_start);
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_lastentry_get()
+*
+* DESCRIPTION:      Get
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* OUTPUTS:
+* last_valid - Last valid entry
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_lastentry_get(tpm_api_sections_t api_section, int32_t *last_valid_entry)
+{
+	if (tpm_db.api_section[api_section].valid == TPM_DB_INVALID)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	*last_valid_entry = tpm_db.api_section[api_section].last_valid_entry;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_main_pnc_get()
+*
+* DESCRIPTION:      Get
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* OUTPUTS:
+* prim_pnc_range - Primary PNC Range for this API ACL/Table
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_main_pnc_get(tpm_api_sections_t api_section, tpm_pnc_ranges_t *prim_pnc_range)
+{
+	if (tpm_db.api_section[api_section].valid == TPM_DB_INVALID)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	*prim_pnc_range = tpm_db.api_section[api_section].prim_pnc_range;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_num_entries_get()
+*
+* DESCRIPTION:      Get
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* OUTPUTS:
+* num_entries - Number of valid entries
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_num_entries_get(tpm_api_sections_t api_section, uint32_t *num_entries)
+{
+	if (tpm_db.api_section[api_section].valid == TPM_DB_INVALID)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	*num_entries = tpm_db.api_section[api_section].num_valid_entries;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_section_val_get_next()
+*
+* DESCRIPTION:      Get next valid API range
+*
+* INPUTS:
+* cur_api_section      - Section of the API acl/table
+* OUTPUTS:
+* api_rng_size      - API range size
+* num_valid_entries- Number of valid entries
+* last_valid - Last valid entry
+* next_section
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_val_get_next(int32_t cur_api_section,
+					int32_t *next_section,
+					uint32_t *api_rng_size,
+					uint32_t *num_valid_entries, int32_t *last_valid_entry, uint32_t *tbl_start)
+{
+	uint32_t x;
+
+	/* Check Params */
+	if (cur_api_section < -1 || cur_api_section >= TPM_MAX_NUM_API_SECTIONS)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	/* Initialize next section  */
+	x = (uint32_t) (cur_api_section + 1);
+
+	/* Check PnC range exists in DB */
+	for (; x < TPM_MAX_NUM_API_SECTIONS; x++) {
+		if (tpm_db.api_section[x].valid == TPM_DB_VALID) {
+			/* Return Data */
+			*api_rng_size = tpm_db.api_section[x].table_size;
+			*num_valid_entries = tpm_db.api_section[x].num_valid_entries;
+			*last_valid_entry = tpm_db.api_section[x].last_valid_entry;
+			*tbl_start = tpm_db.api_section[x].table_start;
+			*next_section = x;
+			return (TPM_DB_OK);
+		}
+	}
+	/* No valid entry found */
+	*next_section = -1;
+
+	return (TPM_DB_OK);
+}
+
+#if 0	/* YUVAL_OK */
+void tpm_db_api_area_bubble_sort(tpm_db_api_check_t *array, uint8_t num_elements)
+{
+	int32_t i, j;
+	tpm_db_api_check_t temp_var;
+
+	if (num_elements <= 1)
+		return;
+
+	for (i = 0; i < num_elements; i++) {
+		/* back through the area bringing smallest remaining element to position i */
+		for (j = num_elements - 1; j > i; j--) {
+			if (array[j - 1].table_start > array[j].table_start) {
+				memcpy(&temp_var, &(array[j]), sizeof(tpm_db_api_check_t));
+				memcpy(&(array[j]), &(array[j - 1]), sizeof(tpm_db_api_check_t));
+				memcpy(&(array[j - 1]), &temp_var, sizeof(tpm_db_api_check_t));
+
+			}
+		}
+	}
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_db_api_section_margins_check()
+*
+* DESCRIPTION:      Get next valid API range
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_rng_margins_self_check(void)
+{
+
+	tpm_api_sections_t cur_section = -1, next_section = 0;
+	int32_t last_valid;
+	int32_t ret_code, margin_area;
+	uint32_t margin_entry, api_rng_size = 0, num_valid_entries;
+	uint32_t tbl_start_ind = 0, table_size, margin_start_ind, area_num, num_ranges;
+	uint32_t i = 0, k = 0;
+	uint8_t *margin_p;
+	tpm_db_api_check_t api_sections_areas[TPM_MAX_NUM_API_SECTIONS];
+
+	/* Loop through valid API ranges read them into local array */
+	ret_code = tpm_db_api_section_val_get_next(cur_section, &next_section, &api_rng_size,
+						   &num_valid_entries, &last_valid, &tbl_start_ind);
+	IF_ERROR(ret_code);
+
+	while (next_section != TPM_INVALID_SECTION) {
+		api_sections_areas[i].table_size = api_rng_size;
+		api_sections_areas[i].table_start = tbl_start_ind;
+
+		cur_section = next_section;
+		i++;
+
+		ret_code = tpm_db_api_section_val_get_next(cur_section, &next_section, &api_rng_size,
+							   &num_valid_entries, &last_valid, &tbl_start_ind);
+		IF_ERROR(ret_code);
+	}
+
+	num_ranges = i;
+
+	/* Simple Ordering */
+	tpm_db_api_area_bubble_sort(api_sections_areas, num_ranges);
+	if (1) {
+		printk("%s (%d)\n", __func__, __LINE__);
+		for (k = 0; k < num_ranges; k++) {
+			printk("entry(%d) table_start(%d) table_size(%d)\n", k, api_sections_areas[k].table_start,
+			       api_sections_areas[k].table_size);
+		}
+	}
+
+	/* Check margins */
+	margin_start_ind = 0;
+	i = 0;
+
+	for (area_num = 0; area_num < num_ranges; area_num++) {
+		tbl_start_ind = api_sections_areas[area_num].table_start;
+		table_size = api_sections_areas[area_num].table_size;
+
+		margin_p = (uint8_t *) &(tpm_db.api_ent_mem_area[margin_start_ind]);
+		margin_area = (tbl_start_ind - margin_start_ind) * (sizeof(tpm_db_api_entry_t));
+		i = 0;
+
+		while (i < margin_area) {
+			if (*(margin_p + i) != MEM_MARGIN_PATTERN) {
+				/* Print complete tpm_db_api_entry_t from start to end, and also skips checking the rest of it */
+				margin_entry = i / (sizeof(tpm_db_api_entry_t));
+
+				printk("margin entry(%d):\n", margin_entry);
+				for (i = margin_entry * sizeof(tpm_db_api_entry_t);
+				     i < (margin_entry + 1) * sizeof(tpm_db_api_entry_t); i++) {
+					printk("%x ", *(margin_p + i));
+				}
+
+				/* i now points to start of next entry */
+			} else {
+				i++;
+			}
+		}
+		margin_start_ind = tbl_start_ind + api_sections_areas[area_num].table_size;
+	}
+
+	printk("===========================================\n");
+	return (TPM_OK);
+
+}
+#endif
+
+/*******************************************************************************
+* tpm_db_api_section_entry_add()
+*
+* DESCRIPTION:      Update Range params to add new entry
+*
+* INPUTS:
+* api_section       - Section of the API acl/table
+* new_last_valid    - Update the last valid entry with this value
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_section_entry_add(tpm_api_sections_t api_section, int32_t new_last_valid)
+{
+	if (tpm_db.api_section[api_section].valid == TPM_DB_INVALID)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	(tpm_db.api_section[api_section].num_valid_entries)++;
+	tpm_db.api_section[api_section].last_valid_entry = new_last_valid;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_freeentry_get()
+*
+* DESCRIPTION:      Get free API entry
+*
+* INPUTS:
+* api_section       - Section of the API acl/table
+* OUTPUTS:
+* ind               - Return Free Index
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_freeentry_get(tpm_api_sections_t api_section, int32_t *index)
+{
+	uint32_t i;
+
+	/* Find Empty Index */
+	for (i = 0; i < tpm_db.api_section[api_section].table_size; i++) {
+		if (API_ENT_I(api_section, i).valid == TPM_DB_INVALID)
+			break;
+	}
+	if (i == tpm_db.api_section[api_section].table_size) {
+		*index = -1;
+		return (TPM_DB_ERR_DB_TBL_FULL);
+	}
+
+	*index = i;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_entry_ind_get()
+*
+* DESCRIPTION:      Get Index (handle) of a rulenum
+*
+* INPUTS:
+* api_section       - Section of the API acl/table
+* rulenum           - Rulenum of the API acl/table
+* OUTPUTS:
+* index             - Return rule number's index
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_entry_ind_get(tpm_api_sections_t api_section, uint32_t rule_num, int32_t *index)
+{
+	int32_t i;
+
+	/* Find the rulenum index */
+	for (i = 0; i <= tpm_db.api_section[api_section].last_valid_index; i++) {
+		if (API_ENT_I(api_section, i).valid == TPM_DB_VALID && API_ENT_I(api_section, i).rule_num == rule_num)
+			break;
+	}
+
+	if (i > tpm_db.api_section[api_section].last_valid_index) {
+		*index = -1;
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+	}
+
+	*index = i;
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_api_tcam_rule_idx_get()
+*
+* DESCRIPTION:      Get PnC rule index by API section and TCAM number
+*
+* INPUTS:
+* api_section       - Section of the API acl/table
+* tcam_num          - TCAM number of the API acl/table
+* OUTPUTS:
+* rule_idx          - Return rule index for PnC rule
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_tcam_rule_idx_get(tpm_api_sections_t api_section, uint32_t tcam_num, uint32_t *rule_idx)
+{
+	int32_t i;
+
+	/* Find the rule index */
+	for (i = 0; i <= tpm_db.api_section[api_section].last_valid_index; i++) {
+		/*
+		   printk("tpm_db_api_tcam_rule_idx_get index[%d], valid[%d], num_pnc_ranges[%d], pnc_index[%d] \n",
+		   i, API_ENT_I(api_section, i).valid, API_ENT_I(api_section, i).pnc_tbl_conn.num_pnc_ranges,
+		   API_ENT_I(api_section, i).pnc_tbl_conn.pnc_conn_tbl[0].pnc_index);
+		 */
+		if (API_ENT_I(api_section, i).valid == TPM_DB_VALID
+		    && API_ENT_I(api_section, i).pnc_tbl_conn.num_pnc_ranges > 0
+		    && API_ENT_I(api_section, i).pnc_tbl_conn.pnc_conn_tbl[0].pnc_index == tcam_num)
+			break;
+	}
+
+	if (i > tpm_db.api_section[api_section].last_valid_index) {
+		*rule_idx = 0;
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+	}
+
+	*rule_idx = API_ENT_I(api_section, i).rule_idx;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_entry_set()
+*
+* DESCRIPTION:      Set an API Entry
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_num         - Rule number in the API range
+* bi_dir           - Is this rule Bi-directional
+* api_data         - The API key data for this entry
+* mod_con          - Definition of connection to modification tables
+* pnc_con          - Definition of connection to PNC tables
+* OUTPUTS:
+* rule_idx         - Unique Rule Identifier, that does not change over the life span of the rule.
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_entry_set(tpm_api_sections_t api_section,
+			     uint32_t rule_num,
+			     uint32_t bi_dir,
+			     tpm_rule_entry_t *api_data,
+			     tpm_db_mod_conn_t *mod_con, tpm_db_pnc_conn_t *pnc_con, uint32_t *rule_idx)
+{
+	int32_t ind;
+	static uint32_t l_rule_idx = 1000;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pnc_range_conf_t rangConf;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d), - rule_num(%d)\n", api_section, rule_num);
+
+	/* Find Empty Index */
+	tpm_db_api_freeentry_get(api_section, &ind);
+	if (ind == -1)
+		return (TPM_DB_ERR_DB_TBL_FULL);
+
+	/* Get Range_Id, rang configuration, to get range type */
+	ret_code = tpm_db_api_section_main_pnc_get(api_section, &range_id);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Fill in API entry */
+	memcpy(&(API_ENT_I(api_section, ind).api_rule_data), api_data, sizeof(tpm_rule_entry_t));
+	if (mod_con)
+		memcpy(&(API_ENT_I(api_section, ind).mod_tbl_conn), mod_con, sizeof(tpm_db_mod_conn_t));
+
+	memcpy(&(API_ENT_I(api_section, ind).pnc_tbl_conn), pnc_con, sizeof(tpm_db_pnc_conn_t));
+
+	API_ENT_I(api_section, ind).bi_dir = bi_dir;
+	if (TPM_RANGE_TYPE_ACL == rangConf.range_type)
+		API_ENT_I(api_section, ind).rule_idx = l_rule_idx;
+	else
+		API_ENT_I(api_section, ind).rule_idx = rule_num;
+
+	API_ENT_I(api_section, ind).rule_num = rule_num;
+	API_ENT_I(api_section, ind).valid = TPM_DB_VALID;
+
+	/* Increase highest tbl_index if needed */
+	if (ind > tpm_db.api_section[api_section].last_valid_index)
+		tpm_db.api_section[api_section].last_valid_index = ind;
+
+
+	/* Set last_valid to rule_num if needed */
+	if ((tpm_db.api_section[api_section].last_valid_entry < 0)
+	    || ((int32_t) rule_num > tpm_db.api_section[api_section].last_valid_entry))
+		tpm_db.api_section[api_section].last_valid_entry = (int32_t) rule_num;
+
+	(tpm_db.api_section[api_section].num_valid_entries)++;
+
+	if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+		*rule_idx = l_rule_idx;
+		l_rule_idx++;
+	} else
+		*rule_idx = rule_num;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_entry_invalidate()
+*
+* DESCRIPTION:      Invalidate an API Entry
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_num         - Rule number in the API range
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_entry_invalidate(tpm_api_sections_t api_section, uint32_t rule_num)
+{
+	int32_t ind;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d), - rule_num(%d)\n", api_section, rule_num);
+
+	/* Find rule_num Index */
+	tpm_db_api_entry_ind_get(api_section, rule_num, &ind);
+	if (ind == -1)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " ind(%d), \n", ind);
+
+	/* Invalidate the entry on the api_table */
+	memset(&(API_ENT_I(api_section, ind)), 0, sizeof(tpm_db_api_entry_t));
+	API_ENT_I(api_section, ind).valid = TPM_DB_INVALID;
+
+	/* Decrease highest tbl_index if needed */
+	if (ind == tpm_db.api_section[api_section].last_valid_index)
+		tpm_db.api_section[api_section].last_valid_index--;
+
+	/* Decrease last_valid if needed */
+	if ((int32_t) rule_num == tpm_db.api_section[api_section].last_valid_entry)
+		tpm_db.api_section[api_section].last_valid_entry--;
+
+	/* Decrease the number of valid entries */
+	(tpm_db.api_section[api_section].num_valid_entries)--;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " last_valid_entry(%d), num_valid_entries(%d), \n",
+		     tpm_db.api_section[api_section].last_valid_entry,
+		     tpm_db.api_section[api_section].num_valid_entries);
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_entry_rulenum_inc()
+*
+* DESCRIPTION:      Increase rulenum of a range of API entries
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_inc_start   - Start of Range of API entries to increase the rule_num
+* rule_inc_end     - End of Range of API entries to increase the rule_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_entry_rulenum_inc(tpm_api_sections_t api_section, uint32_t rule_inc_start, uint32_t rule_inc_end)
+{
+	int32_t i;
+	int32_t ind, ret_code;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d) - range_inc_start(%d) range_inc_end(%d) \n",
+		     api_section, rule_inc_start, rule_inc_end);
+
+	if (rule_inc_end >= (tpm_db.api_section[api_section].table_size - 1)) {
+		TPM_OS_ERROR(TPM_DB_MOD, " for api_section(%d), - range_inc_end(%d) too large \n",
+			     api_section, rule_inc_end);
+		return (TPM_DB_ERR_INV_INPUT);
+	}
+
+	/* Increase all entries */
+	for (i = rule_inc_end; i >= (int32_t) (rule_inc_start); i--) {
+		ret_code = tpm_db_api_entry_ind_get(api_section, i, &ind);
+		IF_ERROR_I(ret_code, i);
+		(API_ENT_I(api_section, ind).rule_num)++;
+	}
+
+	/* Increase last_valid rule_num, if necessary */
+	if (tpm_db.api_section[api_section].last_valid_entry == (int32_t) rule_inc_end)
+		(tpm_db.api_section[api_section].last_valid_entry)++;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_entry_rulenum_dec()
+*
+* DESCRIPTION:      Decrease rulenum of a range of API entries
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_dec_start   - Start of Range of API entries to decrease the rule_num
+* rule_dec_end     - End of Range of API entries to decrease the rule_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_entry_rulenum_dec(tpm_api_sections_t api_section, uint32_t rule_dec_start, uint32_t rule_dec_end)
+{
+
+	uint32_t i;
+	int32_t ind, ret_code;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d) - rule_dec_start(%d) rule_dec_end(%d) \n",
+		     api_section, rule_dec_start, rule_dec_end);
+
+	if (rule_dec_start == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, "for api_section(%d) -  rule_dec_start cannot be 0\n", api_section);
+		return (TPM_DB_ERR_INV_INPUT);
+	}
+
+	/* Decrease all entries */
+	for (i = rule_dec_start; i <= rule_dec_end; i++) {
+		ret_code = tpm_db_api_entry_ind_get(api_section, i, &ind);
+		IF_ERROR_I(ret_code, i);
+		(API_ENT_I(api_section, ind).rule_num)--;
+	}
+
+	/* Decrease last_valid, if it equaled last in range */
+	if (tpm_db.api_section[api_section].last_valid_entry == (int32_t) rule_dec_end)
+		(tpm_db.api_section[api_section].last_valid_entry)--;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_specific_pnc_dec()
+*
+* DESCRIPTION:      Decrease the connected PCN entry of a specific pnc range
+*                   for a range of API entries
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* range_id         - Pnc range id
+* rule_inc_start   - Start of Range of API entries to decrease the rule_num
+* rule_inc_end     - End of Range of API entries to decrease the rule_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_specific_pnc_dec(tpm_api_sections_t api_section,
+				    tpm_pnc_ranges_t range_id, uint32_t rule_inc_start, uint32_t rule_inc_end)
+{
+	uint32_t i, j;
+	int32_t ret_code, ind;
+	tpm_db_pnc_conn_t *pnc_tbl_conn;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d), range(%d) - rule_inc_start(%d) rule_inc_end(%d) \n",
+		     api_section, range_id, rule_inc_start, rule_inc_end);
+
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &range_conf);
+	IF_ERROR(ret_code);
+
+	/* Increase pnc_entries of all rule_nums in the range */
+	for (i = rule_inc_start; i <= rule_inc_end; i++) {
+		ret_code = tpm_db_api_entry_ind_get(api_section, i, &ind);
+		IF_ERROR_I(ret_code, i);
+		if (API_ENT_I(api_section, ind).valid == TPM_DB_INVALID)
+			continue;
+
+		pnc_tbl_conn = &(API_ENT_I(api_section, ind).pnc_tbl_conn);
+
+		/* Loop over all then pnc_entries of this api_entry */
+		for (j = 0; j < (pnc_tbl_conn->num_pnc_ranges); j++) {
+
+			if (pnc_tbl_conn->pnc_conn_tbl[j].pnc_range == (uint32_t) range_id)
+				pnc_tbl_conn->pnc_conn_tbl[j].pnc_index--;
+		}
+	}
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_specific_pnc_inc()
+*
+* DESCRIPTION:      Increase the connected PCN entry of a specific pnc range
+*                   for a range of API entries
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* range_id         - Pnc range id
+* rule_inc_start   - Start of Range of API entries to decrease the rule_num
+* rule_inc_end     - End of Range of API entries to decrease the rule_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_specific_pnc_inc(tpm_api_sections_t api_section,
+				    tpm_pnc_ranges_t range_id, uint32_t rule_inc_start, uint32_t rule_inc_end)
+{
+	uint32_t i, j;
+	int32_t ret_code, ind;
+	tpm_db_pnc_conn_t *pnc_tbl_conn;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d), range(%d) - rule_inc_start(%d) rule_inc_end(%d) \n",
+		     api_section, range_id, rule_inc_start, rule_inc_end);
+
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &range_conf);
+	IF_ERROR(ret_code);
+
+	/* Increase pnc_entries of all rule_nums in the range */
+	for (i = rule_inc_start; i <= rule_inc_end; i++) {
+		ret_code = tpm_db_api_entry_ind_get(api_section, i, &ind);
+		IF_ERROR_I(ret_code, i);
+
+		pnc_tbl_conn = &(API_ENT_I(api_section, ind).pnc_tbl_conn);
+
+		/* Loop over all then pnc_entries of this api_entry */
+		for (j = 0; j < (pnc_tbl_conn->num_pnc_ranges); j++) {
+
+			if (pnc_tbl_conn->pnc_conn_tbl[j].pnc_range == (uint32_t) range_id)
+				pnc_tbl_conn->pnc_conn_tbl[j].pnc_index++;
+		}
+	}
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_conn_inc()
+*
+* DESCRIPTION:      Increase the connected PCN entry for a range of API entries
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_inc_start   - Start of Range of API entries to decrease the rule_num
+* rule_inc_end     - End of Range of API entries to decrease the rule_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_conn_inc(tpm_api_sections_t api_section, uint32_t rule_inc_start, uint32_t rule_inc_end)
+{
+	int32_t i;
+	uint32_t j;
+	int32_t ind, ret_code;
+	tpm_db_pnc_conn_t *pnc_tbl_conn;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d) - rule_inc_start(%d) rule_inc_end(%d) \n",
+		     api_section, rule_inc_start, rule_inc_end);
+
+	if (rule_inc_end >= (tpm_db.api_section[api_section].table_size - 1)) {
+		TPM_OS_ERROR(TPM_DB_MOD, " for api_section(%d)- range_inc_end(%d) too large \n",
+			     api_section, rule_inc_end);
+		return (TPM_DB_ERR_INV_INPUT);
+	}
+
+	/* Increase pnc_entries of all rule_nums in the range */
+	for (i = rule_inc_end; i >= (int32_t) (rule_inc_start); i--) {
+		ret_code = tpm_db_api_entry_ind_get(api_section, i, &ind);
+		IF_ERROR_I(ret_code, i);
+		pnc_tbl_conn = &(API_ENT_I(api_section, ind).pnc_tbl_conn);
+
+		/* Loop over all then pnc_entries of this api_entry */
+		for (j = 0; j < (pnc_tbl_conn->num_pnc_ranges); j++) {
+			/* INcrease only the entries of the PNC Ranges that are TYPE_ACL */
+			ret_code = tpm_db_pnc_rng_conf_get(pnc_tbl_conn->pnc_conn_tbl[j].pnc_range, &range_conf);
+			IF_ERROR_I(ret_code, i);
+			if (range_conf.range_type == TPM_RANGE_TYPE_ACL)
+				pnc_tbl_conn->pnc_conn_tbl[j].pnc_index++;
+		}
+	}
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_conn_dec()
+*
+* DESCRIPTION:      Decrease the connected PCN entry for a range of API entries
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_dec_start   - Start of Range of API entries to decrease the rule_num
+* rule_dec_end     - End of Range of API entries to decrease the rule_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_conn_dec(tpm_api_sections_t api_section, uint32_t rule_dec_start, uint32_t rule_dec_end)
+{
+	uint32_t i, j;
+	int32_t ind, ret_code;
+	tpm_db_pnc_conn_t *pnc_tbl_conn;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, " api_section(%d) - rule_dec_start(%d) rule_dec_end(%d) \n",
+		     api_section, rule_dec_start, rule_dec_end);
+
+	if (rule_dec_start == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, " for api_section(%d) - rule_dec_start is zero \n", api_section);
+		return (TPM_DB_ERR_INV_INPUT);
+	}
+
+	/* Decrease pnc_entries of all rule_nums in the range */
+	for (i = rule_dec_start; i <= rule_dec_end; i++) {
+		ret_code = tpm_db_api_entry_ind_get(api_section, i, &ind);
+		IF_ERROR_I(ret_code, i);
+		pnc_tbl_conn = &(API_ENT_I(api_section, ind).pnc_tbl_conn);
+
+		/* Loop over all then pnc_entries of this api_entry */
+		for (j = 0; j < (pnc_tbl_conn->num_pnc_ranges); j++) {
+			/* Decrease only the entries of the PNC Ranges that are TYPE_ACL */
+			ret_code = tpm_db_pnc_rng_conf_get(pnc_tbl_conn->pnc_conn_tbl[j].pnc_range, &range_conf);
+			IF_ERROR_I(ret_code, i);
+			if (range_conf.range_type == TPM_RANGE_TYPE_ACL)
+				pnc_tbl_conn->pnc_conn_tbl[j].pnc_index--;
+		}
+	}
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_tcam_num_get()
+*
+* DESCRIPTION:      Get API TCAM number according to API section and rule index
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_idx         - Unique Rule Identifier, that does not change over the life span of the rule.
+*
+* OUTPUTS:
+* tcam_num         - PnC TCAM number
+*
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_tcam_num_get(tpm_api_sections_t api_section, uint32_t rule_idx, uint32_t *tcam_num)
+{
+	int32_t ret_code;
+	uint32_t rule_num;
+	uint32_t dummy_idx;
+	uint32_t bi_dir;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con = { 0, 0 };
+	tpm_db_pnc_conn_t pnc_con;
+
+	/* Get rule number */
+	ret_code = tpm_db_api_rulenum_get(api_section, rule_idx, &rule_num);
+	IF_ERROR(ret_code);
+
+	/* Get API entry */
+	ret_code = tpm_db_api_entry_get(api_section, rule_num, &dummy_idx, &bi_dir, &api_data, &mod_con, &pnc_con);
+	IF_ERROR(ret_code);
+
+	/* Get TCAM number, always return the first TCAM number even there are multiple  */
+	/* TCAM entries to one rule index                                                */
+	*tcam_num = pnc_con.pnc_conn_tbl[0].pnc_index;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_rulenum_get()
+*
+* DESCRIPTION:      Get  API Entry  Data
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_idx         - Unique Rule Identifier, that does not change over the life span of the rule.
+*
+* OUTPUTS:
+* rule_num         - The API entry number
+*
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_rulenum_get(tpm_api_sections_t api_section, uint32_t rule_idx, uint32_t *rule_num)
+{
+	int32_t i;
+
+	for (i = 0; i <= tpm_db.api_section[api_section].last_valid_index; i++) {
+		if (API_ENT_I(api_section, i).valid == TPM_DB_VALID && API_ENT_I(api_section, i).rule_idx == rule_idx) {
+			*rule_num = API_ENT_I(api_section, i).rule_num;
+			return (TPM_DB_OK);
+		}
+	}
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_api_rulenum_get_from_l2_key()
+*
+* DESCRIPTION:      Get  API Entry  Data
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* parse_bm         - fields to be parsed in the key.
+* l2_key           - structure of l2_key
+*
+* OUTPUTS:
+* rule_num         - The API entry number
+*
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_rulenum_get_from_l2_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
+					   tpm_l2_acl_key_t *l2_key, uint32_t *rule_num)
+{
+	int32_t i, cmp_res;
+
+	for (i = 0; i <= tpm_db.api_section[api_section].last_valid_index; i++) {
+		if (API_ENT_I(api_section, i).valid == TPM_DB_VALID) {
+			cmp_res = memcmp(&(API_ENT_I(api_section, i).api_rule_data.l2_prim_key.l2_key),
+					 l2_key, sizeof(tpm_l2_acl_key_t));
+			if (cmp_res == 0) {	/* found entry */
+				/* check the parse_bm */
+				if (parse_rule_bm == API_ENT_I(api_section, i).api_rule_data.l2_prim_key.parse_rule_bm) {
+					*rule_num = API_ENT_I(api_section, i).rule_num;
+					return (TPM_DB_OK);
+				}
+			}
+		}
+	}
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_api_rulenum_get_from_l3_key()
+*
+* DESCRIPTION:      Get  API Entry  Data
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* parse_bm         - fields to be parsed in the key.
+* l3_key           - structure of l3_key
+*
+* OUTPUTS:
+* rule_num         - The API entry number
+*
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_rulenum_get_from_l3_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
+					   tpm_l3_type_key_t *l3_key, uint32_t *rule_num)
+{
+	int32_t i, cmp_res;
+
+	for (i = 0; i <= tpm_db.api_section[api_section].last_valid_index; i++) {
+		if (API_ENT_I(api_section, i).valid == TPM_DB_VALID) {
+			cmp_res = memcmp(&API_ENT_I(api_section, i).api_rule_data.l3_type_key.l3_key,
+					 l3_key, sizeof(tpm_l3_type_key_t));
+			if (cmp_res == 0) {	/* found entry */
+				/* check the parse_bm */
+				if (parse_rule_bm == API_ENT_I(api_section, i).api_rule_data.l3_type_key.parse_rule_bm) {
+					*rule_num = API_ENT_I(api_section, i).rule_num;
+					return (TPM_DB_OK);
+				}
+			}
+		}
+	}
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_api_rulenum_get_from_ipv4_key()
+*
+* DESCRIPTION:      Get  API Entry  Data
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* parse_bm         - fields to be parsed in the key.
+* ipv4_key         - structure of ipv4_key
+*
+* OUTPUTS:
+* rule_num         - The API entry number
+*
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_rulenum_get_from_ipv4_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
+					     tpm_ipv4_acl_key_t *ipv4_key, uint32_t *rule_num)
+{
+	int32_t i, cmp_res;
+
+	for (i = 0; i <= tpm_db.api_section[api_section].last_valid_index; i++) {
+		if (API_ENT_I(api_section, i).valid == TPM_DB_VALID) {
+			cmp_res = memcmp(&API_ENT_I(api_section, i).api_rule_data.ipv4_key.ipv4_key,
+					 ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+			if (cmp_res == 0) {	/* found entry */
+				/* check the parse_bm */
+				if (parse_rule_bm == API_ENT_I(api_section, i).api_rule_data.ipv4_key.parse_rule_bm) {
+					*rule_num = API_ENT_I(api_section, i).rule_num;
+					return (TPM_DB_OK);
+				}
+			}
+		}
+	}
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_api_rulenum_get_from_ipv6_key()
+*
+* DESCRIPTION:      Get  API Entry  Data
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* parse_bm         - fields to be parsed in the key.
+* ipv6_key         - structure of ipv6_key
+*
+* OUTPUTS:
+* rule_num         - The API entry number
+*
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_rulenum_get_from_ipv6_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
+					     tpm_ipv6_acl_key_t *ipv6_key, uint32_t *rule_num)
+{
+	int32_t i, cmp_res;
+
+	for (i = 0; i <= tpm_db.api_section[api_section].last_valid_index; i++) {
+		if (API_ENT_I(api_section, i).valid == TPM_DB_VALID) {
+			cmp_res = memcmp(&API_ENT_I(api_section, i).api_rule_data.ipv6_key.ipv6_key,
+					 ipv6_key, sizeof(tpm_ipv6_acl_key_t));
+			if (cmp_res == 0) {	/* found entry */
+				/* check the parse_bm */
+				if (parse_rule_bm == API_ENT_I(api_section, i).api_rule_data.ipv6_key.parse_rule_bm) {
+					*rule_num = API_ENT_I(api_section, i).rule_num;
+					return (TPM_DB_OK);
+				}
+			}
+		}
+	}
+	return (TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_api_entry_get()
+*
+* DESCRIPTION:      Get  API Entry  Data
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* rule_num         - The API entry number
+*
+* OUTPUTS:
+* rule_idx         - Unique Rule Identifier, that does not change over the life span of the rule.
+* bi_dir           - Is this rule bi-directional (currently not used)
+* api_data         - All config information received for this API call
+* mod_con          - Connection to modification tables
+* pnc_con          - Connection to PNC
+*
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_entry_get(tpm_api_sections_t api_section,
+			     uint32_t rule_num,
+			     uint32_t *rule_idx,
+			     uint32_t *bi_dir,
+			     tpm_rule_entry_t *api_data, tpm_db_mod_conn_t *mod_con, tpm_db_pnc_conn_t *pnc_con)
+{
+	int32_t ind;
+
+	tpm_db_api_entry_ind_get(api_section, rule_num, &ind);
+	if (ind == -1)
+		return (TPM_DB_ERR_REC_NOT_EXIST);
+
+	memcpy(api_data, &(API_ENT_I(api_section, ind).api_rule_data), sizeof(tpm_rule_entry_t));
+	memcpy(mod_con, &(API_ENT_I(api_section, ind).mod_tbl_conn), sizeof(tpm_db_mod_conn_t));
+	memcpy(pnc_con, &(API_ENT_I(api_section, ind).pnc_tbl_conn), sizeof(tpm_db_pnc_conn_t));
+	*bi_dir = API_ENT_I(api_section, ind).bi_dir;
+	*rule_idx = API_ENT_I(api_section, ind).rule_idx;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_api_entry_valid_get_next()
+*
+* DESCRIPTION:      Get  Next API Entry  Data
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* cur_rule          - The current rule_num in  the API Range.
+*                     Function returns the next valid rule number next_rule  > cur_rule
+*
+* OUTPUTS:
+* next_rule        - See cur_rule. If end of table was reached before valid entry, (-1) is returned in next_rule
+*                    All of the following outputs relate to rule_num=next_rule.
+* rule_idx         - See tpm_db_api_entry_get
+* bi_dir           - See tpm_db_api_entry_get
+* api_data         - See tpm_db_api_entry_get
+* mod_con          - See tpm_db_api_entry_get
+* pnc_con          - See tpm_db_api_entry_get
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_api_entry_val_get_next(tpm_api_sections_t api_section,
+				      int32_t cur_rule,
+				      int32_t *next_rule,
+				      uint32_t *rule_idx,
+				      uint32_t *bi_dir,
+				      tpm_rule_entry_t *api_data,
+				      tpm_db_mod_conn_t *mod_con, tpm_db_pnc_conn_t *pnc_con)
+{
+	int32_t ind = -1;
+	int32_t i;
+	uint32_t min_rule, l_next_rule = ~0;
+	tpm_db_api_entry_t *api_tbl = &(API_ENT_I(api_section, 0));
+
+	/*TPM_OS_DEBUG(TPM_DB_MOD, "api_section(%d) cur_rule(%d)\n", api_section, cur_rule); */
+
+	if (cur_rule <= -1)
+		min_rule = 0;
+	else
+		min_rule = cur_rule + 1;
+
+	/*TPM_OS_DEBUG(TPM_DB_MOD, "min_rule(%d) \n", min_rule); */
+
+	for (i = 0; i <= tpm_db.api_section[api_section].last_valid_index; i++) {
+		if (((api_tbl + i)->valid == TPM_DB_VALID) &&
+		    ((api_tbl + i)->rule_num >= min_rule) && ((api_tbl + i)->rule_num < l_next_rule)) {
+			l_next_rule = (api_tbl + i)->rule_num;
+			ind = i;
+		}
+	}
+
+	/*TPM_OS_DEBUG(TPM_DB_MOD, "l_next_rule(%d) ind(%d) \n", l_next_rule, ind); */
+
+	if ((l_next_rule < (uint32_t) (~0)) && (ind != -1)) {
+		memcpy(api_data, &(API_ENT_I(api_section, ind).api_rule_data), sizeof(tpm_rule_entry_t));
+		memcpy(mod_con, &(API_ENT_I(api_section, ind).mod_tbl_conn), sizeof(tpm_db_mod_conn_t));
+		memcpy(pnc_con, &(API_ENT_I(api_section, ind).pnc_tbl_conn), sizeof(tpm_db_pnc_conn_t));
+		*bi_dir = API_ENT_I(api_section, ind).bi_dir;
+		*rule_idx = API_ENT_I(api_section, ind).rule_idx;
+
+		*next_rule = l_next_rule;
+	} else		/* Not found */
+		*next_rule = -1;
+
+	/*TPM_OS_DEBUG(TPM_DB_MOD, "next_rule(%d) \n", *next_rule); */
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_shdw_ent_set()
+*
+* DESCRIPTION:      Set PNC  Entry in Shadow Table
+*
+* INPUTS:
+* pnc_entry       - PnC Entry
+*
+* OUTPUTS:
+* pnc_data        - PnC Data
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_shdw_ent_set(uint32_t pnc_entry, tpm_pnc_all_t *pnc_data)
+{
+
+	TPM_OS_DEBUG(TPM_DB_MOD, "pnc_entry(%d)\n", pnc_entry);
+	if (pnc_entry >= TPM_PNC_SIZE)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	tpm_db.pnc_shadow[pnc_entry].valid = TPM_DB_VALID;
+	memcpy(&(tpm_db.pnc_shadow[pnc_entry].pnc_data), pnc_data, sizeof(tpm_pnc_all_t));
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_shdw_ent_inv()
+*
+* DESCRIPTION:      Invalidate PNC  Entry in Shadow Table
+*
+* INPUTS:
+* pnc_entry       - PnC Entry
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_shdw_ent_inv(uint32_t pnc_entry)
+{
+	if (pnc_entry >= TPM_PNC_SIZE)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	memset(&(tpm_db.pnc_shadow[pnc_entry].pnc_data), 0, sizeof(tpm_pnc_all_t));
+	tpm_db.pnc_shadow[pnc_entry].valid = TPM_DB_INVALID;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_shdw_ent_get()
+*
+* DESCRIPTION:      Get PNC Entry from Shadow Table
+*
+* INPUTS:
+* pnc_entry       - PnC Entry
+*
+* OUTPUTS:
+* valid           - Is the PNC Entry valid in Shadow
+* pnc_data        - PnC Data
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_shdw_ent_get(uint32_t pnc_entry, uint32_t *valid, tpm_pnc_all_t *pnc_data)
+{
+	if (pnc_entry >= TPM_PNC_SIZE)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	memcpy(pnc_data, &(tpm_db.pnc_shadow[pnc_entry].pnc_data), sizeof(tpm_pnc_all_t));
+	if (tpm_db.pnc_shadow[pnc_entry].valid == TPM_DB_VALID)
+		*valid = TPM_TRUE;
+	else
+		*valid = TPM_FALSE;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mod_shdw_par_check()
+*
+* DESCRIPTION:      Function checks legality of modification table params
+*
+* INPUTS:
+* gmac            - GMAC In
+* entry           - modification entry
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mod_shdw_par_check(tpm_gmacs_enum_t gmac, uint32_t mod_entry)
+{
+	if ((mod_entry >= TPM_MOD_TABL_SIZE)
+	    || /*(gmac < TPM_ENUM_GMAC_0) || */ (gmac >= TPM_MAX_NUM_GMACS))
+		return (TPM_DB_ERR_INV_INPUT);
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_pnc_shdw_ent_del()
+*
+* DESCRIPTION:      Function deletes a PNC entry and "pushes up" the PNC Range
+*
+* INPUTS:
+* pnc_start_entry   -
+* pnc_stop_entry    -
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_shdw_ent_del(uint32_t pnc_start_entry, uint32_t pnc_stop_entry)
+{
+	uint32_t i;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, "pnc_start_entry(%d) pnc_stop_entry(%d)\n", pnc_start_entry, pnc_stop_entry);
+
+	if ((pnc_start_entry >= TPM_PNC_SIZE) || (pnc_stop_entry >= TPM_PNC_SIZE))
+		return (TPM_DB_ERR_INV_INPUT);
+
+	/* Push up the existing range, except for the first one that is deleted */
+	for (i = pnc_start_entry; i < pnc_stop_entry; i++)
+		memcpy(&(tpm_db.pnc_shadow[i]), &(tpm_db.pnc_shadow[i + 1]), sizeof(tpm_db_pnc_shadow_t));
+
+	/* Set last entry in range to invalid */
+	memset(&(tpm_db.pnc_shadow[pnc_stop_entry].pnc_data), 0, sizeof(tpm_pnc_all_t));
+	tpm_db.pnc_shadow[pnc_stop_entry].valid = TPM_DB_INVALID;
+
+	return (TPM_DB_OK);
+
+}
+
+/*******************************************************************************
+* tpm_db_pnc_shdw_ent_ins()
+*
+* DESCRIPTION:      Function inserts an empty entry into a PNC Range ("pushes down the range")
+*
+* INPUTS:
+* pnc_start_entry   -
+* pnc_stop_entry    -
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_pnc_shdw_ent_ins(uint32_t pnc_start_entry, uint32_t pnc_stop_entry)
+{
+	int32_t i;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, "pnc_start_entry(%d) pnc_stop_entry(%d)\n", pnc_start_entry, pnc_stop_entry);
+
+	if ((pnc_start_entry >= (TPM_PNC_SIZE - 1)) || (pnc_stop_entry >= (TPM_PNC_SIZE - 1)))
+		return (TPM_DB_ERR_INV_INPUT);
+
+	/* Push down the existing range */
+	for (i = (int32_t) pnc_stop_entry; i >= (int32_t) pnc_start_entry; i--)
+		memcpy(&(tpm_db.pnc_shadow[i + 1]), &(tpm_db.pnc_shadow[i]), sizeof(tpm_db_pnc_shadow_t));
+
+	/* Set empty (invalid) entry */
+	memset(&(tpm_db.pnc_shadow[pnc_start_entry].pnc_data), 0, sizeof(tpm_pnc_all_t));
+	tpm_db.pnc_shadow[pnc_start_entry].valid = TPM_DB_INVALID;
+
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mod_etype_sel_get()
+*
+* DESCRIPTION:      Get select of Vlan Ethertype
+*
+* INPUTS:
+* tpid            - Requested Vlan tpid
+*
+*
+* OUTPUTS:
+* etype_sel       - selector that matches this tpid
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mod_etype_sel_get(uint32_t tpid, uint32_t *etype_sel)
+{
+	uint32_t i;
+
+	if (etype_sel == NULL) {
+		TPM_OS_DEBUG(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	for (i = 0; i < TPM_NUM_VLAN_ETYPE_REGS; i++) {
+		if (tpm_db.vlan_etype[i].tpid_ether_type == tpid && tpm_db.vlan_etype[i].valid == TPM_DB_VALID) {
+			*etype_sel = i;
+			return (TPM_DB_OK);
+		}
+	}
+	return (TPM_DB_ERR_REC_EXIST);
+}
+
+/*******************************************************************************
+* tpm_db_mod_etype_sel_free_get()
+*
+* DESCRIPTION:      Get an unused tpid selector
+*
+* INPUTS:
+*
+* OUTPUTS:
+* etype_sel       - selector
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mod_etype_sel_free_get(uint32_t *etype_sel)
+{
+	uint32_t i;
+
+	if (etype_sel == NULL) {
+		TPM_OS_DEBUG(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	for (i = 0; i < TPM_NUM_VLAN_ETYPE_REGS; i++) {
+		if (tpm_db.vlan_etype[i].valid == TPM_DB_INVALID) {
+			*etype_sel = i;
+			return (TPM_DB_OK);
+		}
+	}
+
+	return (TPM_DB_ERR_DB_TBL_FULL);
+}
+
+/*******************************************************************************
+* tpm_db_mod_etype_sel_set()
+*
+* DESCRIPTION:      Set a tpid in a selector
+*
+* INPUTS:
+* tpid            - Requested Vlan tpid
+* etype_sel       - selector that matches this tpid
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mod_etype_sel_set(uint32_t tpid, uint32_t etype_sel)
+{
+	if (etype_sel >= TPM_NUM_VLAN_ETYPE_REGS) {
+		TPM_OS_DEBUG(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	tpm_db.vlan_etype[etype_sel].valid = TPM_DB_VALID;
+	tpm_db.vlan_etype[etype_sel].tpid_ether_type = tpid;
+
+	return (TPM_DB_OK);
+}
+
+void tpm_db_set_mc_filter_mode(uint32_t mode)
+{
+	tpm_db.igmp_def.filter_mode = mode;
+}
+
+uint32_t tpm_db_get_mc_filter_mode(void)
+{
+	return tpm_db.igmp_def.filter_mode;
+}
+
+void tpm_db_set_mc_pppoe_enable(uint32_t enable)
+{
+	tpm_db.igmp_def.mc_pppoe_enable = enable;
+}
+
+uint8_t tpm_db_get_mc_pppoe_enable(void)
+{
+	return tpm_db.igmp_def.mc_pppoe_enable;
+}
+void tpm_db_split_mod_set_enable(tpm_db_split_mod_enable_t enable)
+{
+	tpm_db.split_mod_conf.split_mod_enable = enable;
+}
+
+tpm_db_split_mod_enable_t tpm_db_split_mod_get_enable(void)
+{
+	return tpm_db.split_mod_conf.split_mod_enable;
+}
+
+void tpm_db_split_mod_set_num_vlans(uint32_t num_vlans)
+{
+	/* as default, vlan 0 is added during Init */
+	tpm_db.split_mod_conf.num_vlans = (num_vlans + TPM_DB_SPLIT_MOD_INIT_VLANS_NUM);
+}
+
+uint32_t tpm_db_split_mod_get_num_vlans(void)
+{
+	return tpm_db.split_mod_conf.num_vlans;
+}
+void tpm_db_split_mod_set_mode(tpm_db_split_mod_mode_t mode)
+{
+	tpm_db.split_mod_conf.split_mod_mode = mode;
+}
+
+tpm_db_split_mod_mode_t tpm_db_split_mod_get_mode(void)
+{
+	return tpm_db.split_mod_conf.split_mod_mode;
+}
+void tpm_db_split_mod_set_num_p_bits(uint32_t num_p_bits, uint8_t  p_bits[TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX])
+{
+	tpm_db.split_mod_conf.num_p_bits = num_p_bits;
+	memcpy(&(tpm_db.split_mod_conf.p_bits), p_bits, TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX);
+}
+
+uint32_t tpm_db_split_mod_get_num_p_bits(void)
+{
+	return tpm_db.split_mod_conf.num_p_bits;
+}
+int32_t tpm_db_split_mod_get_p_bits_by_index(uint8_t  index, uint8_t  *p_bits)
+{
+	if (p_bits == NULL)
+		return TPM_DB_ERR_INV_INPUT;
+
+	*p_bits = index;
+	return TPM_DB_OK;
+}
+int32_t tpm_db_split_mod_get_index_by_p_bits(uint8_t  p_bits, uint32_t *index)
+{
+	uint32_t i;
+	for(i = 0; i < tpm_db.split_mod_conf.num_p_bits; i++)
+		if (p_bits == tpm_db.split_mod_conf.p_bits[i]) {
+			*index = p_bits;
+			return TPM_DB_OK;
+		}
+
+	return TPM_DB_ERR_REC_NOT_EXIST;
+}
+
+#if 0
+void tpm_db_set_mc_igmp_mode(uint32_t mode)
+{
+   tpm_db.igmp_def.igmp_mode = mode;
+}
+
+uint32_t tpm_db_get_mc_igmp_mode(void)
+{
+   return tpm_db.igmp_def.igmp_mode;
+}
+#endif
+void tpm_db_set_mc_per_uni_vlan_xlate(uint32_t enable)
+{
+	tpm_db.igmp_def.per_uni_vlan_xlat = enable;
+}
+
+uint8_t tpm_db_get_mc_per_uni_vlan_xlate(void)
+{
+	return tpm_db.igmp_def.per_uni_vlan_xlat;
+}
+
+void tpm_db_set_mc_hwf_queue(uint8_t hwf_queue)
+{
+	tpm_db.igmp_def.mc_hwf_queue = hwf_queue;
+}
+
+uint8_t tpm_db_get_mc_hwf_queue(void)
+{
+	return tpm_db.igmp_def.mc_hwf_queue;
+}
+
+void tpm_db_set_mc_cpu_queue(uint8_t cpu_queue)
+{
+	tpm_db.igmp_def.mc_cpu_queue = cpu_queue;
+}
+
+uint8_t tpm_db_get_mc_cpu_queue(void)
+{
+	return tpm_db.igmp_def.mc_cpu_queue;
+}
+
+void tpm_db_set_mc_igmp_proxy_sa_mac(uint8_t *sa_mac)
+{
+	memcpy(tpm_db_mc_igmp_proxy_sa_mac, sa_mac, 6 * sizeof(uint8_t));
+	tpm_db_mc_igmp_proxy_sa_mac_valid = 1;
+}
+
+void tpm_db_get_mc_igmp_proxy_sa_mac(uint8_t *sa_mac, uint8_t *valid)
+{
+	*valid = tpm_db_mc_igmp_proxy_sa_mac_valid;
+	if (tpm_db_mc_igmp_proxy_sa_mac_valid)
+		memcpy(sa_mac, tpm_db_mc_igmp_proxy_sa_mac, 6 * sizeof(uint8_t));
+}
+
+void tpm_db_set_mc_lpbk_enable(tpm_ip_ver_t ver, uint8_t enable)
+{
+	if (ver < TPM_IP_VER_MAX)
+		tpm_db.igmp_def.mc_lpbk_enable[ver] = enable;
+}
+
+void tpm_db_get_mc_lpbk_enable(tpm_ip_ver_t ver, uint8_t *enable)
+{
+	if (ver < TPM_IP_VER_MAX)
+		*enable = tpm_db.igmp_def.mc_lpbk_enable[ver];
+}
+
+int32_t tpm_db_set_mc_stream_entry(uint32_t stream_num, tpm_db_mc_stream_entry_t *mc_stream)
+{
+	if (tpm_db_mc_stream_table[stream_num] == NULL) {
+		tpm_db_mc_stream_table[stream_num] =
+		/*(tpm_db_mc_stream_entry_t *)*/ kmalloc(sizeof(tpm_db_mc_stream_entry_t), GFP_KERNEL);
+		if (tpm_db_mc_stream_table[stream_num] == NULL)
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+
+		memcpy(tpm_db_mc_stream_table[stream_num], mc_stream, sizeof(tpm_db_mc_stream_entry_t));
+	} else {
+		if (tpm_db_mc_stream_table[stream_num]->igmp_mode == mc_stream->igmp_mode &&
+		    tpm_db_mc_stream_table[stream_num]->mc_stream_pppoe == mc_stream->mc_stream_pppoe &&
+		    tpm_db_mc_stream_table[stream_num]->vid == mc_stream->vid &&
+		    tpm_db_mc_stream_table[stream_num]->src_valid == mc_stream->src_valid &&
+		    !memcmp(tpm_db_mc_stream_table[stream_num]->src_addr, mc_stream->src_addr, 4 * sizeof(uint8_t)) &&
+		    !memcmp(tpm_db_mc_stream_table[stream_num]->group_addr, mc_stream->group_addr, 4 * sizeof(uint8_t))) {
+			tpm_db_mc_stream_table[stream_num]->dest_port_bm = mc_stream->dest_port_bm;
+			tpm_db_mc_stream_table[stream_num]->u4_entry = mc_stream->u4_entry;
+		} else
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_mc_stream_entry(uint32_t stream_num, tpm_db_mc_stream_entry_t *mc_stream)
+{
+	if (tpm_db_mc_stream_table[stream_num] == NULL)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	memcpy(mc_stream, tpm_db_mc_stream_table[stream_num], sizeof(tpm_db_mc_stream_entry_t));
+	return TPM_DB_OK;
+}
+
+void tpm_db_reset_mc_stream_entry(uint32_t stream_num)
+{
+	if (tpm_db_mc_stream_table[stream_num] != NULL) {
+		kfree(tpm_db_mc_stream_table[stream_num]);
+		tpm_db_mc_stream_table[stream_num] = NULL;
+	}
+}
+
+int32_t tpm_db_set_ipv6_mc_stream_entry(uint32_t stream_num, tpm_db_ipv6_mc_stream_entry_t *mc_stream)
+{
+	if (0 == tpm_db.ipv6_mc_stream[stream_num].valid) {
+		memcpy(&(tpm_db.ipv6_mc_stream[stream_num]), mc_stream, sizeof(tpm_db_ipv6_mc_stream_entry_t));
+		tpm_db.ipv6_mc_stream[stream_num].valid = 1;
+	} else {
+		if (tpm_db.ipv6_mc_stream[stream_num].igmp_mode == mc_stream->igmp_mode &&
+			tpm_db.ipv6_mc_stream[stream_num].mc_stream_pppoe == mc_stream->mc_stream_pppoe &&
+			tpm_db.ipv6_mc_stream[stream_num].vid == mc_stream->vid &&
+			!memcmp(tpm_db.ipv6_mc_stream[stream_num].group_addr, mc_stream->group_addr, 16 * sizeof(uint8_t))) {
+			tpm_db.ipv6_mc_stream[stream_num].dest_port_bm = mc_stream->dest_port_bm;
+			tpm_db.ipv6_mc_stream[stream_num].u4_entry = mc_stream->u4_entry;
+		} else
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_ipv6_mc_stream_entry(uint32_t stream_num, tpm_db_ipv6_mc_stream_entry_t *mc_stream)
+{
+	if (0 == tpm_db.ipv6_mc_stream[stream_num].valid)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	memcpy(mc_stream, &(tpm_db.ipv6_mc_stream[stream_num]), sizeof(tpm_db_ipv6_mc_stream_entry_t));
+	return TPM_DB_OK;
+}
+
+void tpm_db_reset_ipv6_mc_stream_entry(uint32_t stream_num)
+{
+	memset(&(tpm_db.ipv6_mc_stream[stream_num]), 0, sizeof(tpm_db_ipv6_mc_stream_entry_t));
+}
+
+int32_t tpm_db_increase_mc_mac_port_user_num(uint8_t *mac_addr, uint32_t uni_port)
+{
+	uint32_t entry_id, first_free = TPM_MC_MAX_MAC_NUM;
+	uint32_t port_nr;
+	
+	for (entry_id = 0; entry_id < TPM_MC_MAX_MAC_NUM; entry_id++) {
+		if (tpm_db_mc_mac_table[entry_id] != NULL) {
+			if (!memcmp(tpm_db_mc_mac_table[entry_id]->mac_addr, mac_addr, 6 * sizeof(uint8_t)))
+				break;
+		} else if (first_free == TPM_MC_MAX_MAC_NUM)
+			first_free = entry_id;
+	}
+
+	if (entry_id == TPM_MC_MAX_MAC_NUM) {
+		if (first_free == TPM_MC_MAX_MAC_NUM)
+			return TPM_DB_ERR_DB_TBL_FULL;
+
+		tpm_db_mc_mac_table[first_free] =
+		/*(tpm_db_mc_mac_entry_t *)*/ kmalloc(sizeof(tpm_db_mc_mac_entry_t), GFP_KERNEL);
+		if (tpm_db_mc_mac_table[first_free] == NULL)
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+
+		memset(tpm_db_mc_mac_table[first_free], 0, sizeof(tpm_db_mc_mac_entry_t));
+		memcpy(tpm_db_mc_mac_table[first_free]->mac_addr, mac_addr, 6 * sizeof(uint8_t));
+		entry_id = first_free;
+	}
+
+	switch (uni_port) {
+	case TPM_TRG_UNI_0:	port_nr = TPM_SRC_PORT_UNI_0;	break;
+	case TPM_TRG_UNI_1:	port_nr = TPM_SRC_PORT_UNI_1;	break;
+	case TPM_TRG_UNI_2:	port_nr = TPM_SRC_PORT_UNI_2;	break;
+	case TPM_TRG_UNI_3:	port_nr = TPM_SRC_PORT_UNI_3;	break;
+	case TPM_TRG_UNI_4:	port_nr = TPM_SRC_PORT_UNI_4;	break;
+	case TPM_TRG_UNI_5:	port_nr = TPM_SRC_PORT_UNI_5;	break;
+	case TPM_TRG_UNI_6:	port_nr = TPM_SRC_PORT_UNI_6;	break;
+	case TPM_TRG_UNI_7:	port_nr = TPM_SRC_PORT_UNI_7;	break;
+	case TPM_TRG_UNI_VIRT:	port_nr = TPM_SRC_PORT_UNI_VIRT;break;
+	default:
+		return TPM_DB_ERR_INV_INPUT;
+	}
+	tpm_db_mc_mac_table[entry_id]->user_num[port_nr] += 1;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_decrease_mc_mac_port_user_num(uint8_t *mac_addr, uint32_t uni_port)
+{
+	uint32_t entry_id;
+	uint32_t port_nr;
+
+	for (entry_id = 0; entry_id < TPM_MC_MAX_MAC_NUM; entry_id++) {
+		if (tpm_db_mc_mac_table[entry_id] != NULL) {
+			if (!memcmp(tpm_db_mc_mac_table[entry_id]->mac_addr, mac_addr, 6 * sizeof(uint8_t)))
+				break;
+		}
+	}
+
+	if (entry_id == TPM_MC_MAX_MAC_NUM)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	switch (uni_port) {
+	case TPM_TRG_UNI_0:	port_nr = TPM_SRC_PORT_UNI_0;	break;
+	case TPM_TRG_UNI_1:	port_nr = TPM_SRC_PORT_UNI_1;	break;
+	case TPM_TRG_UNI_2:	port_nr = TPM_SRC_PORT_UNI_2;	break;
+	case TPM_TRG_UNI_3:	port_nr = TPM_SRC_PORT_UNI_3;	break;
+	case TPM_TRG_UNI_4:	port_nr = TPM_SRC_PORT_UNI_4;	break;
+	case TPM_TRG_UNI_5:	port_nr = TPM_SRC_PORT_UNI_5;	break;
+	case TPM_TRG_UNI_6:	port_nr = TPM_SRC_PORT_UNI_6;	break;
+	case TPM_TRG_UNI_7:	port_nr = TPM_SRC_PORT_UNI_7;	break;
+	case TPM_TRG_UNI_VIRT:	port_nr = TPM_SRC_PORT_UNI_VIRT;break;
+	default:
+		return TPM_DB_ERR_INV_INPUT;
+	}
+	tpm_db_mc_mac_table[entry_id]->user_num[port_nr] -= 1;
+
+	return TPM_DB_OK;
+}
+
+uint8_t tpm_db_get_mc_mac_port_user_num(uint8_t *mac_addr, uint32_t uni_port)
+{
+	uint32_t entry_id;
+	uint32_t port_nr;
+
+	for (entry_id = 0; entry_id < TPM_MC_MAX_MAC_NUM; entry_id++) {
+		if (tpm_db_mc_mac_table[entry_id] != NULL) {
+			if (!memcmp(tpm_db_mc_mac_table[entry_id]->mac_addr, mac_addr, 6 * sizeof(uint8_t)))
+				break;
+		}
+	}
+
+	if (entry_id == TPM_MC_MAX_MAC_NUM)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	switch (uni_port) {
+	case TPM_TRG_UNI_0:	port_nr = TPM_SRC_PORT_UNI_0;	break;
+	case TPM_TRG_UNI_1:	port_nr = TPM_SRC_PORT_UNI_1;	break;
+	case TPM_TRG_UNI_2:	port_nr = TPM_SRC_PORT_UNI_2;	break;
+	case TPM_TRG_UNI_3:	port_nr = TPM_SRC_PORT_UNI_3;	break;
+	case TPM_TRG_UNI_4:	port_nr = TPM_SRC_PORT_UNI_4;	break;
+	case TPM_TRG_UNI_5:	port_nr = TPM_SRC_PORT_UNI_5;	break;
+	case TPM_TRG_UNI_6:	port_nr = TPM_SRC_PORT_UNI_6;	break;
+	case TPM_TRG_UNI_7:	port_nr = TPM_SRC_PORT_UNI_7;	break;
+	case TPM_TRG_UNI_VIRT:	port_nr = TPM_SRC_PORT_UNI_VIRT;break;
+	default:
+		return 0;
+	}
+	
+	if (TRG_UNI(uni_port)) {
+		if (port_nr < TPM_MAX_NUM_UNI_PORTS)
+			return tpm_db_mc_mac_table[entry_id]->user_num[port_nr];
+	}
+	
+	return 0;
+}
+
+void tpm_db_reset_mc_mac_entry(uint8_t *mac_addr)
+{
+	uint32_t entry_id;
+
+	for (entry_id = 0; entry_id < TPM_MC_MAX_MAC_NUM; entry_id++) {
+		if (tpm_db_mc_mac_table[entry_id] != NULL) {
+			if (!memcmp(tpm_db_mc_mac_table[entry_id]->mac_addr, mac_addr, 6 * sizeof(uint8_t))) {
+				kfree(tpm_db_mc_mac_table[entry_id]);
+				tpm_db_mc_mac_table[entry_id] = NULL;
+				return;
+			}
+		}
+	}
+}
+
+uint32_t tpm_db_mc_lpbk_entries_num_get(void)
+{
+	return tpm_db_mc_lpbk_entries_num;
+}
+
+int32_t tpm_db_mc_lpbk_entry_set(uint32_t ip_ver, uint16_t mvlan, uint16_t in_vid, uint16_t out_vid, uint32_t rule_num,
+				 uint32_t mod_entry)
+{
+	static uint32_t _rule_index = 1000;
+	uint32_t entry_id, first_free = TPM_MC_MAX_MVLAN_XITS_NUM;
+	tpm_db_mc_lpbk_entry_t *lpbk_entry = NULL;
+	tpm_db_mc_vlan_entry_t *mvlan_entry = NULL;
+
+	if (rule_num >= TPM_MC_MAX_LPBK_ENTRIES_NUM)
+		return TPM_DB_ERR_DB_TBL_FULL;
+
+	if (rule_num > tpm_db_mc_lpbk_entries_num)
+		return TPM_DB_ERR_INV_INPUT;
+
+	for (entry_id = 0; entry_id < TPM_MC_MAX_MVLAN_XITS_NUM; entry_id++) {
+		if (tpm_db_mc_vlan_xits_table[entry_id] != NULL) {
+			if (mvlan == tpm_db_mc_vlan_xits_table[entry_id]->mvlan &&
+				ip_ver == tpm_db_mc_vlan_xits_table[entry_id]->ip_ver) {
+				mvlan_entry = tpm_db_mc_vlan_xits_table[entry_id];
+				break;
+			}
+		} else if (first_free == TPM_MC_MAX_MVLAN_XITS_NUM)
+			first_free = entry_id;
+	}
+
+	if (entry_id == TPM_MC_MAX_MVLAN_XITS_NUM) {
+		if (first_free == TPM_MC_MAX_MVLAN_XITS_NUM)
+			return TPM_DB_ERR_DB_TBL_FULL;
+
+		mvlan_entry = /*(tpm_db_mc_vlan_entry_t *)*/ kmalloc(sizeof(tpm_db_mc_vlan_entry_t), GFP_KERNEL);
+		if (mvlan_entry == NULL)
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+
+		memset(mvlan_entry, 0, sizeof(tpm_db_mc_vlan_entry_t));
+		mvlan_entry->mvlan = mvlan;
+		mvlan_entry->ip_ver = ip_ver;
+
+		tpm_db_mc_vlan_xits_table[first_free] = mvlan_entry;
+	}
+
+	first_free = TPM_DB_MAX_TRANSITION_NUM;
+
+	for (entry_id = 0; entry_id < TPM_DB_MAX_TRANSITION_NUM; entry_id++) {
+		if (mvlan_entry->xits[entry_id].valid == 0) {
+			first_free = entry_id;
+			break;
+		}
+	}
+
+	if (first_free == TPM_DB_MAX_TRANSITION_NUM)
+		return TPM_DB_ERR_DB_TBL_FULL;
+
+	lpbk_entry = /*(tpm_db_mc_lpbk_entry_t *)*/ kmalloc(sizeof(tpm_db_mc_lpbk_entry_t), GFP_KERNEL);
+	if (lpbk_entry == NULL)
+		return TPM_DB_ERR_MEM_ALLOC_FAIL;
+
+	memset(lpbk_entry, 0, sizeof(tpm_db_mc_lpbk_entry_t));
+
+	mvlan_entry->xits[first_free].valid = 1;
+	mvlan_entry->xits[first_free].in_vid = in_vid;
+	mvlan_entry->xits[first_free].out_vid = out_vid;
+	mvlan_entry->xits[first_free].lpbk_entry = lpbk_entry;
+	mvlan_entry->xits_num++;
+
+	_rule_index++;
+
+	lpbk_entry->rule_index = _rule_index;
+	lpbk_entry->mod_cmd = mod_entry;
+
+	for (entry_id = tpm_db_mc_lpbk_entries_num; entry_id > rule_num; entry_id--)
+		tpm_db_mc_lpbk_table[entry_id] = tpm_db_mc_lpbk_table[entry_id - 1];
+
+	tpm_db_mc_lpbk_table[rule_num] = lpbk_entry;
+	tpm_db_mc_lpbk_entries_num++;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mc_vlan_xits_num_get(uint32_t ip_ver, uint16_t mvlan, uint32_t *xits_num)
+{
+	uint32_t entry_id;
+
+	for (entry_id = 0; entry_id < TPM_MC_MAX_MVLAN_XITS_NUM; entry_id++) {
+		if (tpm_db_mc_vlan_xits_table[entry_id] != NULL) {
+			if (tpm_db_mc_vlan_xits_table[entry_id]->mvlan == mvlan &&
+				tpm_db_mc_vlan_xits_table[entry_id]->ip_ver == ip_ver) {
+				*xits_num = tpm_db_mc_vlan_xits_table[entry_id]->xits_num;
+				return TPM_DB_OK;
+			}
+		}
+	}
+
+	return TPM_DB_ERR_REC_NOT_EXIST;
+}
+
+int32_t tpm_db_mc_vlan_xit_entry_get(uint32_t ip_ver, uint16_t mvlan, uint32_t xit_id, uint32_t *rule_index, uint32_t *mod_entry)
+{
+	uint32_t entry_id, xit_cnt = 0;
+	uint8_t found;
+	tpm_db_mc_vlan_entry_t *mvlan_entry = NULL;
+	tpm_db_mc_lpbk_entry_t *lpbk_entry = NULL;
+
+	for (entry_id = 0; entry_id < TPM_MC_MAX_MVLAN_XITS_NUM; entry_id++) {
+		if (tpm_db_mc_vlan_xits_table[entry_id] != NULL) {
+			if (tpm_db_mc_vlan_xits_table[entry_id]->mvlan == mvlan &&
+				tpm_db_mc_vlan_xits_table[entry_id]->ip_ver == ip_ver) {
+				mvlan_entry = tpm_db_mc_vlan_xits_table[entry_id];
+				break;
+			}
+		}
+	}
+
+	if (mvlan_entry == NULL)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	found = 0;
+	for (entry_id = 0; entry_id < TPM_DB_MAX_TRANSITION_NUM; entry_id++) {
+		if (xit_cnt == xit_id) {
+			found = 1;
+			break;
+		}
+		xit_cnt++;
+	}
+
+	if (found == 0)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	lpbk_entry = mvlan_entry->xits[entry_id].lpbk_entry;
+
+	*rule_index = lpbk_entry->rule_index;
+	*mod_entry = lpbk_entry->mod_cmd;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mc_lpbk_rule_num_get(uint32_t rule_index, uint32_t *rule_num)
+{
+	uint32_t entry_id;
+
+	for (entry_id = 0; entry_id < tpm_db_mc_lpbk_entries_num; entry_id++) {
+		if (tpm_db_mc_lpbk_table[entry_id] != NULL) {
+			if (tpm_db_mc_lpbk_table[entry_id]->rule_index == rule_index) {
+				*rule_num = entry_id;
+				return TPM_DB_OK;
+			}
+		}
+	}
+
+	return TPM_DB_ERR_REC_NOT_EXIST;
+}
+
+int32_t tpm_db_mc_lpbk_entry_invalidate(uint32_t rule_num)
+{
+	uint32_t entry_id, xit_id;
+	uint8_t found;
+	tpm_db_mc_lpbk_entry_t *lpbk_entry = NULL;
+	tpm_db_mc_vlan_entry_t *mvlan_entry = NULL;
+
+	if (rule_num > tpm_db_mc_lpbk_entries_num)
+		return TPM_DB_ERR_INV_INPUT;
+
+	lpbk_entry = tpm_db_mc_lpbk_table[rule_num];
+
+	for (entry_id = rule_num; entry_id < (tpm_db_mc_lpbk_entries_num - 1); entry_id++)
+		tpm_db_mc_lpbk_table[entry_id] = tpm_db_mc_lpbk_table[entry_id + 1];
+
+	kfree(lpbk_entry);
+	tpm_db_mc_lpbk_table[tpm_db_mc_lpbk_entries_num - 1] = NULL;
+	tpm_db_mc_lpbk_entries_num--;
+
+	found = 0;
+	for (entry_id = 0; entry_id < TPM_MC_MAX_MVLAN_XITS_NUM; entry_id++) {
+		mvlan_entry = tpm_db_mc_vlan_xits_table[entry_id];
+		if (mvlan_entry != NULL) {
+			if (mvlan_entry->xits_num > 0) {
+				for (xit_id = 0; xit_id < TPM_DB_MAX_TRANSITION_NUM; xit_id++) {
+					if (mvlan_entry->xits[xit_id].valid) {
+						if (lpbk_entry == mvlan_entry->xits[xit_id].lpbk_entry) {
+							mvlan_entry->xits[xit_id].valid = 0;
+							found = 1;
+							break;
+						}
+					}
+				}
+
+				if (found) {
+					mvlan_entry->xits_num--;
+					if (mvlan_entry->xits_num == 0) {
+						kfree(mvlan_entry);
+						tpm_db_mc_vlan_xits_table[entry_id] = NULL;
+					}
+					break;
+				}
+			}
+		}
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mc_alloc_virt_uni_entry(uint32_t *entry_id)
+{
+	uint32_t free;
+
+	for (free = 0; free < TPM_MC_MAX_STREAM_NUM; free++) {
+		if (tpm_db_mc_virt_uni_entry_state_table[free] == 0) {
+			tpm_db_mc_virt_uni_entry_state_table[free] = 1;
+			*entry_id = free;
+			return TPM_DB_OK;
+		}
+	}
+
+	return TPM_DB_ERR_DB_TBL_FULL;
+}
+
+int32_t tpm_db_mc_free_virt_uni_entry(uint32_t entry_id)
+{
+	if (entry_id >= TPM_MC_MAX_STREAM_NUM)
+		return TPM_DB_ERR_REC_INV;
+
+	tpm_db_mc_virt_uni_entry_state_table[entry_id] = 0;
+	return TPM_DB_OK;
+}
+
+void tpm_db_mc_rule_reset(void)
+{
+	uint32_t i;
+
+	/* Reset multicast stream table */
+	for (i = 0; i < TPM_MC_MAX_STREAM_NUM; i++) {
+		if (tpm_db_mc_stream_table[i] != NULL) {
+			kfree(tpm_db_mc_stream_table[i]);
+			tpm_db_mc_stream_table[i] = NULL;
+		}
+	}
+
+	/* Reset multicast mac table */
+	for (i = 0; i < TPM_MC_MAX_MAC_NUM; i++) {
+		if (tpm_db_mc_mac_table[i] != NULL) {
+			kfree(tpm_db_mc_mac_table[i]);
+			tpm_db_mc_mac_table[i] = NULL;
+		}
+	}
+
+	/* Reset multicast loopback tables */
+	tpm_db_mc_lpbk_entries_num = 0;
+	for (i = 0; i < TPM_MC_MAX_LPBK_ENTRIES_NUM; i++) {
+		if (tpm_db_mc_lpbk_table[i] != NULL) {
+			kfree(tpm_db_mc_lpbk_table[i]);
+			tpm_db_mc_lpbk_table[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < TPM_MC_MAX_MVLAN_XITS_NUM; i++) {
+		if (tpm_db_mc_vlan_xits_table[i] != NULL) {
+			kfree(tpm_db_mc_vlan_xits_table[i]);
+			tpm_db_mc_vlan_xits_table[i] = NULL;
+		}
+	}
+
+	/* Reset state table of virt_uni entries */
+	memset(tpm_db_mc_virt_uni_entry_state_table, 0, TPM_MC_MAX_STREAM_NUM * sizeof(uint8_t));
+
+	/* reset IPv6 MC rule */
+	memset(tpm_db.ipv6_mc_stream, 0, sizeof(tpm_db.ipv6_mc_stream));
+	
+}
+int32_t tpm_db_mc_vlan_get_ai_bit_by_vid(uint32_t mc_vlan, uint32_t *ai_bit)
+{
+	uint32_t i;
+	int32_t ret_val;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc_vlan(%d) \n", mc_vlan);
+
+	/* first, get ai bits if mc vlan already exists */
+	ret_val = tpm_db_mc_vlan_get_ai_bit(mc_vlan, ai_bit);
+	if (TPM_DB_OK == ret_val) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc vlan already exists, ai bits(%d)\n", *ai_bit);
+		return TPM_DB_OK;
+	}
+
+	/* alloc a new ai bits */
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if (!tpm_db.mc_ai_bits_table[i].valid) {
+			tpm_db.mc_ai_bits_table[i].valid = true;
+			tpm_db.mc_ai_bits_table[i].mc_vlan = mc_vlan;
+			tpm_db.mc_ai_bits_table[i].pnc_index_num = 0;
+			memset(tpm_db.mc_ai_bits_table[i].pnc_index, 0xff,
+			       sizeof(tpm_db.mc_ai_bits_table[i].pnc_index));
+			*ai_bit = i;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " alloc a new ai bits(%d)\n", i);
+			return TPM_DB_OK;
+		}
+	}
+	return (TPM_DB_ERR_DB_TBL_FULL);
+}
+
+bool tpm_db_mc_vlan_l2_rule_exist(uint32_t mc_vlan, uint32_t rule_num)
+{
+	uint32_t loop_in;
+	uint32_t i;
+	uint32_t ret_code;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pnc_range_conf_t rangConf;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc_vlan(%d), rule_num(%d) \n", mc_vlan, rule_num);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_L2_PRIM_ACL, &range_id);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	if (TPM_OK != ret_code) {
+		TPM_OS_ERROR(TPM_DB_MOD, " recvd ret_code(%d)\n", ret_code);
+		return false;
+	}
+
+	if (TPM_RANGE_TYPE_TABLE != rangConf.range_type) {
+		/* not TABLE mode */
+		return false;
+	}
+
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if ((mc_vlan == tpm_db.mc_ai_bits_table[i].mc_vlan) && (tpm_db.mc_ai_bits_table[i].valid)) {
+			for (loop_in = 0; loop_in < TPM_MC_VLAN_MAX_PNC_RULE_NUM; loop_in++) {
+				if (rule_num == tpm_db.mc_ai_bits_table[i].pnc_index[loop_in])
+					return true;
+			}
+		}
+	}
+	return false;
+}
+
+int32_t tpm_db_mc_vlan_set_ai_bit_pnc_index(uint32_t mc_vlan, uint32_t l2_pnc_rule_index)
+{
+	uint32_t i;
+	uint32_t loop_in;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc_vlan(%d) l2_pnc_rule_index(%d)\n", mc_vlan, l2_pnc_rule_index);
+
+	/* in table mode, and rule_num already exist, do not record again */
+	if (tpm_db_mc_vlan_l2_rule_exist(mc_vlan, l2_pnc_rule_index))
+		return TPM_DB_OK;
+
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if ((mc_vlan == tpm_db.mc_ai_bits_table[i].mc_vlan) && (tpm_db.mc_ai_bits_table[i].valid)) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " ai_index(%d)\n", i);
+			for (loop_in = 0; loop_in < TPM_MC_VLAN_MAX_PNC_RULE_NUM; loop_in++) {
+				if (~0 == tpm_db.mc_ai_bits_table[i].pnc_index[loop_in]) {
+					tpm_db.mc_ai_bits_table[i].pnc_index[loop_in] = l2_pnc_rule_index;
+					tpm_db.mc_ai_bits_table[i].pnc_index_num++;
+					return TPM_DB_OK;
+				}
+			}
+			return TPM_DB_ERR_DB_TBL_FULL;
+		}
+	}
+	return (TPM_DB_ERR_DB_TBL_FULL);
+}
+
+int32_t tpm_db_mc_vlan_get_pnc_index_free_slot(uint32_t mc_vlan, uint32_t rule_num)
+{
+	uint32_t i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc_vlan(%d) \n", mc_vlan);
+
+	/* in table mode, and rule_num already exist, always has free slot */
+	if (tpm_db_mc_vlan_l2_rule_exist(mc_vlan, rule_num))
+		return 1;
+
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if ((mc_vlan == tpm_db.mc_ai_bits_table[i].mc_vlan) && (tpm_db.mc_ai_bits_table[i].valid)) {
+
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " ai_index(%d), pnc_index_num(%d)\n",
+				i, tpm_db.mc_ai_bits_table[i].pnc_index_num);
+			/* ACL mode */
+			if (TPM_MC_VLAN_MAX_PNC_RULE_NUM <= tpm_db.mc_ai_bits_table[i].pnc_index_num)
+				return 0;
+			return (TPM_MC_VLAN_MAX_PNC_RULE_NUM - tpm_db.mc_ai_bits_table[i].pnc_index_num);
+		}
+	}
+	return TPM_MC_VLAN_MAX_PNC_RULE_NUM;
+}
+
+int32_t tpm_db_mc_vlan_reset_ai_bit(uint32_t l2_pnc_rule_index)
+{
+	uint32_t i;
+	uint32_t loop_in;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "l2_pnc_rule_index(%d)\n", l2_pnc_rule_index);
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if (!tpm_db.mc_ai_bits_table[i].valid)
+			continue;
+
+		for (loop_in = 0; loop_in < TPM_MC_VLAN_MAX_PNC_RULE_NUM; loop_in++) {
+			if (l2_pnc_rule_index == tpm_db.mc_ai_bits_table[i].pnc_index[loop_in]) {
+				tpm_db.mc_ai_bits_table[i].pnc_index_num--;
+				tpm_db.mc_ai_bits_table[i].pnc_index[loop_in] = ~0;
+
+				if (0 == tpm_db.mc_ai_bits_table[i].pnc_index_num) {
+					TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " remove this mc vlan(%d), ai_bits(%d)\n",
+						     tpm_db.mc_ai_bits_table[i].mc_vlan, i);
+					tpm_db.mc_ai_bits_table[i].valid = false;
+					tpm_db.mc_ai_bits_table[i].mc_vlan = 0;
+					memset(tpm_db.mc_ai_bits_table[i].pnc_index, 0xff,
+					       sizeof(tpm_db.mc_ai_bits_table[i].pnc_index));
+				} else {
+					TPM_OS_DEBUG(TPM_TPM_LOG_MOD,
+						     " decrease pnc_index_num of this mc vlan(%d), pnc_index_num(%d)\n",
+						     tpm_db.mc_ai_bits_table[i].mc_vlan,
+						     tpm_db.mc_ai_bits_table[i].pnc_index_num);
+				}
+
+				return TPM_DB_OK;
+			}
+		}
+		continue;
+	}
+	return (TPM_DB_ERR_DB_TBL_FULL);
+}
+
+int32_t tpm_db_mc_vlan_reset_mc_vlan(uint32_t mc_vlan)
+{
+	uint32_t i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vlan);
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if ((tpm_db.mc_ai_bits_table[i].valid) && (mc_vlan == tpm_db.mc_ai_bits_table[i].mc_vlan)) {
+			if (0 == tpm_db.mc_ai_bits_table[i].pnc_index_num) {
+				tpm_db.mc_ai_bits_table[i].valid = false;
+				tpm_db.mc_ai_bits_table[i].mc_vlan = 0;
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " reset this vlan(%d)\n", mc_vlan);
+			}
+			return TPM_DB_OK;
+		}
+	}
+	return (TPM_DB_ERR_DB_TBL_FULL);
+}
+
+int32_t tpm_db_mc_vlan_get_ai_bit(uint32_t mc_vlan, uint32_t *ai_bit)
+{
+	uint32_t i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vlan);
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if (mc_vlan == tpm_db.mc_ai_bits_table[i].mc_vlan) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " ai_index(%d)\n", i);
+			*ai_bit = i;
+			return TPM_DB_OK;
+		}
+	}
+	return (TPM_DB_ERR_INV_INPUT);
+}
+
+int32_t tpm_db_set_mc_vid_cfg(uint32_t mc_vid, tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config)
+{
+	uint32_t i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vid);
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if (false == tpm_db.mc_vid_port_cfg[i].valid) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc_vid_index(%d)\n", i);
+			tpm_db.mc_vid_port_cfg[i].valid = true;
+			tpm_db.mc_vid_port_cfg[i].mc_vid = mc_vid;
+			memcpy(&tpm_db.mc_vid_port_cfg[i].mc_vid_port_vids, mc_vid_uniports_config,
+			       sizeof(tpm_mc_vid_port_vid_set_t));
+			return TPM_DB_OK;
+		}
+	}
+	return (TPM_DB_ERR_INV_INPUT);
+}
+
+int32_t tpm_db_get_mc_vid_cfg(uint32_t mc_vid, tpm_mc_vid_port_cfg_t **mc_vid_uniports_config)
+{
+	uint32_t i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vid);
+
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if ((true == tpm_db.mc_vid_port_cfg[i].valid) && (mc_vid == tpm_db.mc_vid_port_cfg[i].mc_vid)) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc_vid_index(%d)\n", i);
+			*mc_vid_uniports_config = &(tpm_db.mc_vid_port_cfg[i].mc_vid_port_vids[0]);
+			return TPM_DB_OK;
+		}
+	}
+
+	return (TPM_DB_ERR_INV_INPUT);
+}
+
+bool tpm_db_mc_vid_exist(uint32_t mc_vid)
+{
+	uint32_t i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vid);
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if ((true == tpm_db.mc_vid_port_cfg[i].valid) && (mc_vid == tpm_db.mc_vid_port_cfg[i].mc_vid)) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc_vid_index(%d)\n", i);
+			return true;
+		}
+	}
+	return (false);
+}
+
+uint32_t tpm_db_remove_mc_vid_cfg(uint32_t mc_vid)
+{
+	uint32_t i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vid);
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if ((true == tpm_db.mc_vid_port_cfg[i].valid) && (mc_vid == tpm_db.mc_vid_port_cfg[i].mc_vid)) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mc_vid_index(%d)\n", i);
+			tpm_db.mc_vid_port_cfg[i].valid = false;
+			tpm_db.mc_vid_port_cfg[i].mc_vid = 0;
+			return TPM_DB_OK;
+		}
+	}
+	return (TPM_DB_ERR_INV_INPUT);
+}
+/*******************************************************************************
+* tpm_db_mc_cfg_reset()
+*
+* DESCRIPTION:      Reset MC configuration part in DB. Set all structures to 0,
+*                   and all valid fields to false
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_db_mc_cfg_reset(void)
+{
+    memset(&tpm_db.mc_ai_bits_table, 0, sizeof(tpm_db.mc_ai_bits_table));
+    memset(&tpm_db.mc_vid_port_cfg, 0, sizeof(tpm_db.mc_vid_port_cfg));
+
+    tpm_db_mc_igmp_proxy_sa_mac_valid = 0;
+    memset(tpm_db_mc_igmp_proxy_sa_mac, 0, 6 * sizeof(uint8_t));
+
+    return;
+}
+
+void tpm_db_mod2_init_jump_area_cfg(void)
+{
+	tpm_db_mod2_jump_area_cfg.base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_jump_area_cfg.total_num = 0;
+	tpm_db_mod2_jump_area_cfg.split_num = 0;
+
+	tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_PMAC] = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_jump_area_cfg.next_split[TPM_ENUM_GMAC_0] = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_jump_area_cfg.next_split[TPM_ENUM_GMAC_1] = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_jump_area_cfg.next_split[TPM_ENUM_PMAC] = TPM_MOD2_NULL_ENT_IDX;
+
+	tpm_db_mod2_jump_area_cfg.split_pbit_num = 0;
+}
+
+void tpm_db_mod2_init_chain_cfg(void)
+{
+	tpm_mod2_multicast_mh_enable = 1;
+	tpm_mod2_pppoe_add_mod_enable = 1;
+	tpm_mod2_double_tag_enable = 1;
+	tpm_mod2_udp_checksum_use_init_bm_enable = 0;
+	tpm_mod2_udp_checksum_enable = 1;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].subr_chain = 1;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].max_size = TPM_MOD2_MAX_MH_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].subr_chain = 1;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].max_size = TPM_MOD2_MAX_MAC_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].subr_chain = 1;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].max_size = TPM_MOD2_MAX_VLAN_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].subr_chain = 1;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].max_size = TPM_MOD2_MAX_PPPOE_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].subr_chain = 1;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].max_size = TPM_MOD2_MAX_IPV6_PPPOE_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].subr_chain = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].max_size = TPM_MOD2_MAX_L2_TWO_TAG_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].subr_chain = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].max_size = TPM_MOD2_MAX_IPV4_NAPT_W_PPPOE_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].subr_chain = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].max_size = TPM_MOD2_MAX_IPV4_MC_W_MH_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].subr_chain = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].max_size = TPM_MOD2_MAX_ROUTE_W_PPPOE_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].base_entry = TPM_MOD2_NULL_ENT_IDX;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].subr_chain = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].max_size = TPM_MOD2_MAX_IPV6_MC_W_MH_CHAIN_SIZE;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].total_num = 0;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].next_free[TPM_ENUM_GMAC_0] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].next_free[TPM_ENUM_GMAC_1] = TPM_MOD2_INVALID_CHAIN_ID;
+	tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].next_free[TPM_ENUM_PMAC] = TPM_MOD2_INVALID_CHAIN_ID;
+
+}
+
+void tpm_db_mod2_init_pmt_info(void)
+{
+	tpm_mod2_chain_area_base = TPM_MOD2_NULL_ENT_IDX;
+	tpm_mod2_total_chain_num = 0;
+
+	memset(tpm_db_mod2_jump_pmt_info, 0, TPM_MAX_NUM_GMACS * sizeof(tpm_mod2_jump_pmt_info_t *));
+	memset(tpm_db_mod2_chain_pmt_info, 0, TPM_MAX_NUM_GMACS * sizeof(tpm_mod2_jump_pmt_info_t *));
+}
+
+void tpm_db_mod2_init_chain_info(void)
+{
+	memset(tpm_db_mod2_jump_booked_entry_bm, 0, TPM_MAX_NUM_GMACS * sizeof(uint32_t *));
+	memset(tpm_db_mod2_jump_occupied_entry_bm, 0, TPM_MAX_NUM_GMACS * sizeof(uint32_t *));
+
+	tpm_db_mod2_jump_bm_group = 0;
+
+	memset(tpm_db_mod2_chain_booked_entry_bm, 0, TPM_MAX_NUM_GMACS * TPM_CHAIN_TYPE_MAX * sizeof(uint32_t *));
+	memset(tpm_db_mod2_chain_occupied_entry_bm, 0, TPM_MAX_NUM_GMACS * TPM_CHAIN_TYPE_MAX * sizeof(uint32_t *));
+
+	memset(tpm_db_mod2_chain_bm_group, 0, TPM_CHAIN_TYPE_MAX * sizeof(uint32_t));
+
+	memset(tpm_db_mod2_chain_info, 0, TPM_MAX_NUM_GMACS * TPM_CHAIN_TYPE_MAX * sizeof(tpm_mod2_chain_info_t *));
+}
+
+void tpm_db_mod2_set_chain_num(tpm_chain_type_t chain_type, uint16_t chain_num)
+{
+	if (chain_type < TPM_CHAIN_TYPE_MAX && chain_type != TPM_CHAIN_TYPE_NONE)
+		tpm_db_mod2_chain_cfg[chain_type].total_num = chain_num;
+}
+
+uint16_t tpm_db_mod2_get_chain_max_size(tpm_chain_type_t chain_type)
+{
+	if (chain_type < TPM_CHAIN_TYPE_MAX && chain_type != TPM_CHAIN_TYPE_NONE)
+		return tpm_db_mod2_chain_cfg[chain_type].max_size;
+
+	return 0;
+}
+
+void tpm_db_mod2_set_multicast_mh_state(uint8_t enable)
+{
+	if (enable) {
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].max_size = TPM_MOD2_MAX_IPV4_MC_W_MH_CHAIN_SIZE;
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].max_size = TPM_MOD2_MAX_IPV6_MC_W_MH_CHAIN_SIZE;
+	} else {
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].max_size = TPM_MOD2_MAX_IPV4_MC_WO_MH_CHAIN_SIZE;
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].max_size = TPM_MOD2_MAX_IPV6_MC_WO_MH_CHAIN_SIZE;
+	}
+
+	tpm_mod2_multicast_mh_enable = enable;
+}
+
+uint8_t tpm_db_mod2_get_multicast_mh_state(void)
+{
+	return tpm_mod2_multicast_mh_enable;
+}
+
+void tpm_db_mod2_set_pppoe_add_mod_state(uint8_t enable)
+{
+	if (enable) {
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].max_size = TPM_MOD2_MAX_IPV4_NAPT_W_PPPOE_CHAIN_SIZE;
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].max_size = TPM_MOD2_MAX_ROUTE_W_PPPOE_CHAIN_SIZE;
+	} else {
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].max_size = TPM_MOD2_MAX_IPV4_NAPT_WO_PPPOE_CHAIN_SIZE;
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].max_size = TPM_MOD2_MAX_ROUTE_WO_PPPOE_CHAIN_SIZE;
+	}
+
+	tpm_mod2_pppoe_add_mod_enable = enable;
+}
+
+uint8_t tpm_db_mod2_get_pppoe_add_mod_state(void)
+{
+	return tpm_mod2_pppoe_add_mod_enable;
+}
+
+void tpm_db_mod2_set_double_tag_state(uint8_t enable)
+{
+	if (enable)
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].max_size = TPM_MOD2_MAX_L2_TWO_TAG_CHAIN_SIZE;
+	else
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].max_size = TPM_MOD2_MAX_L2_ONE_TAG_CHAIN_SIZE;
+
+	tpm_mod2_double_tag_enable = enable;
+}
+
+uint8_t tpm_db_mod2_get_double_tag_state(void)
+{
+	return tpm_mod2_double_tag_enable;
+}
+
+void tpm_db_mod2_set_udp_checksum_use_init_bm_state(uint8_t enable)
+{
+	tpm_mod2_udp_checksum_use_init_bm_enable = enable;
+}
+
+uint8_t tpm_db_mod2_get_udp_checksum_init_bm_state(void)
+{
+	return tpm_mod2_udp_checksum_use_init_bm_enable;
+}
+
+void tpm_db_mod2_set_udp_checksum_state(uint8_t enable)
+{
+	tpm_mod2_udp_checksum_enable = enable;
+}
+
+uint8_t tpm_db_mod2_get_udp_checksum_state(void)
+{
+	return tpm_mod2_udp_checksum_enable;
+}
+
+int32_t tpm_db_mod2_set_jump_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id, tpm_mod2_entry_t *pattern)
+{
+	tpm_mod2_jump_pmt_info_t *info_p = NULL;
+
+	if (pattern == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (entry_id >= tpm_db_mod2_jump_area_cfg.total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	info_p = &tpm_db_mod2_jump_pmt_info[gmac_port][entry_id];
+
+	if (info_p->status != TPM_MOD_ENTRY_BOOKED) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid entry status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+
+	memcpy(&(info_p->pattern), pattern, sizeof(tpm_mod2_entry_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_activate_jump_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id)
+{
+	tpm_mod2_jump_pmt_info_t *info_p = NULL;
+	uint32_t i, j, mask;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (entry_id >= tpm_db_mod2_jump_area_cfg.total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	info_p = &tpm_db_mod2_jump_pmt_info[gmac_port][entry_id];
+
+	if (info_p->status != TPM_MOD_ENTRY_BOOKED) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid entry status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+	/* TODO: Check if the entry is split mod entry */
+
+	i = j = 0;
+	j = entry_id & 0x1f;
+	i = entry_id >> 5;
+	mask = 1 << j;
+
+	tpm_db_mod2_jump_booked_entry_bm[gmac_port][i] &= ~mask;
+
+	if (tpm_db_mod2_jump_split_mod_all_entry_bm[gmac_port][i] & mask) {
+		/* this is a split mod entry */
+		info_p->status = TPM_MOD_ENTRY_SPLIT_MOD;
+		tpm_db_mod2_jump_split_mod_occupied_entry_bm[gmac_port][i] |= mask;
+	}
+	else {
+		info_p->status = TPM_MOD_ENTRY_OCCUPIED;
+		tpm_db_mod2_jump_occupied_entry_bm[gmac_port][i] |= mask;
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_get_jump_entry_pattern_data(tpm_gmacs_enum_t gmac_port, uint16_t entry_id,
+						tpm_mod2_entry_t *pattern)
+{
+	tpm_mod2_jump_pmt_info_t *info_p = NULL;
+
+	if (pattern == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (entry_id >= tpm_db_mod2_jump_area_cfg.total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	info_p = &tpm_db_mod2_jump_pmt_info[gmac_port][entry_id];
+
+	if (    (info_p->status != TPM_MOD_ENTRY_OCCUPIED)
+		 && (info_p->status != TPM_MOD_ENTRY_SPLIT_MOD)) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid entry status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+
+	memcpy(pattern, &(info_p->pattern), sizeof(tpm_mod2_entry_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_del_jump_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id)
+{
+	tpm_mod2_jump_pmt_info_t *info_p = NULL;
+	uint32_t i, j, mask;
+	/*uint16_t jump_to; */
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (entry_id >= tpm_db_mod2_jump_area_cfg.total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	info_p = &tpm_db_mod2_jump_pmt_info[gmac_port][entry_id];
+
+	if (   info_p->status != TPM_MOD_ENTRY_OCCUPIED
+		&& info_p->status != TPM_MOD_ENTRY_SPLIT_MOD) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid entry status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+
+	/* delete jump entry in db */
+	memset(info_p, 0, sizeof(tpm_mod2_jump_pmt_info_t));
+
+	/* TODO: Check if the entry is split mod entry */
+
+	info_p->status = TPM_MOD_ENTRY_FREE;
+
+	i = j = 0;
+	j = entry_id & 0x1f;
+	i = entry_id >> 5;
+	mask = 1 << j;
+
+	if (tpm_db_mod2_jump_split_mod_all_entry_bm[gmac_port][i] & mask) {
+		/* this is a split mod pmt entry */
+		tpm_db_mod2_jump_split_mod_occupied_entry_bm[gmac_port][i] &= ~mask;
+	} 
+	else {
+		tpm_db_mod2_jump_occupied_entry_bm[gmac_port][i] &= ~mask;
+	}
+
+    tpm_db_mod2_flush_jump_area(gmac_port, entry_id, 1, 0);
+
+	return TPM_DB_OK;
+}
+
+uint16_t tpm_db_mod2_find_matched_chain(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t total_num,
+					tpm_mod2_chain_info_t *chains, tpm_mod2_chain_pmt_info_t *pmt_data,
+					uint16_t entry_num, tpm_mod2_entry_t *pattern)
+{
+	uint16_t chain_id, entry_id;
+	uint32_t bm_idx, data;
+	uint32_t *booked_bm = NULL, *occupied_bm = NULL;
+	tpm_mod2_chain_pmt_info_t *pmt_ptr = NULL;
+
+	booked_bm = tpm_db_mod2_chain_booked_entry_bm[gmac_port][chain_type];
+	occupied_bm = tpm_db_mod2_chain_occupied_entry_bm[gmac_port][chain_type];
+
+	for (bm_idx = 0; bm_idx < tpm_db_mod2_chain_bm_group[chain_type]; bm_idx++) {
+		data = (booked_bm[bm_idx] | occupied_bm[bm_idx]);
+		if (data) {
+			chain_id = bm_idx << 5;	/* multiply 32 */
+			while (data) {
+				if (data & 0x1) {
+					if (entry_num == chains[chain_id].entry_num) {
+						pmt_ptr = &pmt_data[chains[chain_id].base_entry];
+						for (entry_id = 0; entry_id < entry_num; entry_id++) {
+							if (memcmp
+							    (&(pmt_ptr[entry_id].pattern), &pattern[entry_id],
+							     sizeof(tpm_mod2_entry_t))) {
+								break;
+							}
+						}
+
+						if (entry_id == entry_num)
+							return chain_id;
+					}
+				}
+				chain_id++;
+				data = data >> 1;
+			}
+		}
+	}
+
+	return TPM_MOD2_INVALID_CHAIN_ID;
+}
+
+void tpm_db_mod2_increase_chain_user(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id)
+{
+	tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].user_num++;
+}
+
+void tpm_db_mod2_decrease_chain_user(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id)
+{
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].user_num != 0)
+		tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].user_num--;
+}
+
+uint16_t tpm_db_mod2_chain_user_num(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id)
+{
+	return tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].user_num;
+}
+
+uint16_t tpm_db_mod2_get_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t entry_num,
+				     tpm_mod2_entry_t *pattern)
+{
+	if (pattern == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_MOD2_INVALID_CHAIN_ID;
+	}
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_MOD2_INVALID_CHAIN_ID;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type\n");
+		return TPM_MOD2_INVALID_CHAIN_ID;
+	}
+
+	if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type] == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain info\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	if (tpm_db_mod2_chain_pmt_info[gmac_port] == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid pmt data\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	return tpm_db_mod2_find_matched_chain(gmac_port, chain_type,
+					      tpm_db_mod2_chain_cfg[chain_type].total_num,
+					      tpm_db_mod2_chain_info[gmac_port][chain_type],
+					      tpm_db_mod2_chain_pmt_info[gmac_port], entry_num, pattern);
+}
+
+int32_t tpm_db_mod2_set_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id,
+				    uint16_t entry_num, tpm_mod2_entry_t *pattern)
+{
+	uint16_t /*match_chain, */ base_offset, entry_idx;
+	tpm_mod2_chain_info_t *info_p;
+	tpm_mod2_chain_pmt_info_t *pmt_array;
+
+	if (pattern == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Zero chain\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	if (chain_id >= tpm_db_mod2_chain_cfg[chain_type].total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain index\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type] == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain info\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	info_p = &tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id];
+	if (info_p->status == TPM_MOD_ENTRY_OCCUPIED) {
+		tpm_db_mod2_increase_chain_user(gmac_port, chain_type, chain_id);
+	} else if (info_p->status == TPM_MOD_ENTRY_BOOKED) {
+		if (tpm_db_mod2_chain_user_num(gmac_port, chain_type, chain_id) == 0) {
+			base_offset = tpm_db_mod2_chain_cfg[chain_type].base_entry - tpm_mod2_chain_area_base
+			    + chain_id * tpm_db_mod2_chain_cfg[chain_type].max_size;
+
+			pmt_array = &tpm_db_mod2_chain_pmt_info[gmac_port][base_offset];
+
+			for (entry_idx = 0; entry_idx < entry_num; entry_idx++) {
+				if (pmt_array[entry_idx].status != TPM_MOD_ENTRY_FREE) {
+					TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain status\n");
+					return TPM_DB_ERR_REC_STATUS_ERR;
+				}
+
+				pmt_array[entry_idx].status = TPM_MOD_ENTRY_BOOKED;
+				pmt_array[entry_idx].chain_type = chain_type;
+				pmt_array[entry_idx].chain_id = chain_id;
+				memcpy(&pmt_array[entry_idx].pattern, &pattern[entry_idx], sizeof(tpm_mod2_entry_t));
+			}
+
+			info_p->base_entry = base_offset;
+			info_p->entry_num = entry_num;
+		}
+
+		tpm_db_mod2_increase_chain_user(gmac_port, chain_type, chain_id);
+	} else {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid entry status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_activate_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id)
+{
+	tpm_mod2_chain_info_t *info_p;
+	uint32_t i, j, mask;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Zero chain\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	if (chain_id >= tpm_db_mod2_chain_cfg[chain_type].total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain index\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type] == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain info\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	info_p = &tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id];
+
+	if (info_p->status == TPM_MOD_ENTRY_BOOKED) {
+		info_p->status = TPM_MOD_ENTRY_OCCUPIED;
+
+		i = j = 0;
+		j = chain_id & 0x1f;
+		i = chain_id >> 5;
+		mask = 1 << j;
+
+		tpm_db_mod2_chain_booked_entry_bm[gmac_port][chain_type][i] &= ~mask;
+		tpm_db_mod2_chain_occupied_entry_bm[gmac_port][chain_type][i] |= mask;
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_activate_chain_pmt_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id)
+{
+	uint16_t base_offset, entry_idx, entry_num;
+	tpm_mod2_chain_info_t *info_p = NULL;
+	tpm_mod2_chain_pmt_info_t *pmt_array = NULL;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Zero chain\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	if (chain_id >= tpm_db_mod2_chain_cfg[chain_type].total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain index\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type] == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain info\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	info_p = &tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id];
+
+	if (info_p->status != TPM_MOD_ENTRY_BOOKED) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+
+	base_offset = info_p->base_entry;
+	entry_num = info_p->entry_num;
+
+	pmt_array = &tpm_db_mod2_chain_pmt_info[gmac_port][base_offset];
+
+	for (entry_idx = 0; entry_idx < entry_num; entry_idx++)
+		pmt_array[entry_idx].status = TPM_MOD_ENTRY_OCCUPIED;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_if_chain_pmt_entries_exist(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+					       uint16_t chain_id, uint8_t *exist)
+{
+	uint16_t base_offset, entry_idx, entry_num;
+	tpm_mod2_chain_info_t *info_p = NULL;
+	tpm_mod2_chain_pmt_info_t *pmt_array = NULL;
+
+	if (exist == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Zero chain\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	if (chain_id >= tpm_db_mod2_chain_cfg[chain_type].total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain index\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type] == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain info\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	info_p = &tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id];
+
+	*exist = 0;
+
+	if (info_p->status == TPM_MOD_ENTRY_BOOKED) {
+		base_offset = info_p->base_entry;
+		entry_num = info_p->entry_num;
+
+		pmt_array = &tpm_db_mod2_chain_pmt_info[gmac_port][base_offset];
+
+		for (entry_idx = 0; entry_idx < entry_num; entry_idx++) {
+			if (pmt_array[entry_idx].status != TPM_MOD_ENTRY_OCCUPIED)
+				break;
+		}
+
+		if (entry_idx == entry_num)
+			*exist = 1;
+
+	} else if (info_p->status == TPM_MOD_ENTRY_OCCUPIED)
+		*exist = 1;
+	else {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_get_chain_entry_num(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+					uint16_t chain_id, uint16_t *entry_num)
+{
+	tpm_mod2_chain_info_t *info_p;
+
+	if (entry_num == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	*entry_num = 0;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Zero chain\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	if (chain_id >= tpm_db_mod2_chain_cfg[chain_type].total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain index\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type] == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain info\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	info_p = &tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id];
+	if (info_p->status != TPM_MOD_ENTRY_OCCUPIED) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+
+	*entry_num = info_p->entry_num;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_get_chain_entry_pattern_data(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+						 uint16_t chain_id, uint16_t pattern_id, tpm_mod2_entry_t *pattern)
+{
+	tpm_mod2_chain_info_t *info_p;
+	tpm_mod2_chain_pmt_info_t *entry_p;
+
+	if (pattern == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Zero chain\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	if (chain_id >= tpm_db_mod2_chain_cfg[chain_type].total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain index\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type] == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain info\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	info_p = &tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id];
+	if (info_p->status != TPM_MOD_ENTRY_OCCUPIED) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+
+	if (pattern_id >= info_p->entry_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid pattern index\n");
+		return TPM_DB_ERR_DB_TBL_INV;
+	}
+
+	entry_p = &tpm_db_mod2_chain_pmt_info[gmac_port][info_p->base_entry + pattern_id];
+	if (entry_p->status != TPM_MOD_ENTRY_OCCUPIED) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid entry status\n");
+		return TPM_DB_ERR_REC_STATUS_ERR;
+	}
+	memcpy(pattern, &(entry_p->pattern), sizeof(tpm_mod2_entry_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_del_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id)
+{
+	uint16_t /*entry_offset, chain_type, chain_id, */ entry_num, /*jump_to, */ entry_index;
+	uint8_t remove_it;
+	tpm_mod2_chain_info_t *info_p = NULL;
+	tpm_mod2_chain_pmt_info_t *pmt_array = NULL;
+	uint32_t i, j, mask;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain type \n");
+		return TPM_DB_ERR_REC_INV;
+	}
+
+	if (chain_id > tpm_db_mod2_chain_cfg[chain_type].total_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain id \n");
+		return TPM_DB_ERR_REC_INV;
+	}
+
+	info_p = &tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id];
+
+	if (info_p->status != TPM_MOD_ENTRY_OCCUPIED) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid chain entry \n");
+		return TPM_DB_ERR_REC_INV;
+	}
+
+	pmt_array = &tpm_db_mod2_chain_pmt_info[gmac_port][info_p->base_entry];
+
+	tpm_db_mod2_decrease_chain_user(gmac_port, chain_type, chain_id);
+
+	remove_it = 0;
+	if (tpm_db_mod2_chain_user_num(gmac_port, chain_type, chain_id) == 0)
+		remove_it = 1;
+
+	entry_num = info_p->entry_num;
+
+	for (entry_index = 0; entry_index < entry_num; entry_index++) {
+		if (remove_it) {
+			memset(&pmt_array[entry_index], 0, sizeof(tpm_mod2_chain_pmt_info_t));
+			pmt_array[entry_index].status = TPM_MOD_ENTRY_FREE;
+		}
+	}
+
+	if (remove_it) {
+		memset(info_p, 0, sizeof(tpm_mod2_chain_info_t));
+		info_p->status = TPM_MOD_ENTRY_FREE;
+
+		i = j = 0;
+		j = chain_id & 0x1f;
+		i = chain_id >> 5;
+		mask = 1 << j;
+
+		tpm_db_mod2_chain_occupied_entry_bm[gmac_port][chain_type][i] &= ~mask;
+
+		tpm_db_mod2_flush_chain_entry(gmac_port, chain_type, chain_id, 1, 0);
+	}
+
+	return TPM_DB_OK;
+}
+
+void tpm_db_mod2_update_next_free_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type)
+{
+	uint16_t chain_id;
+	uint32_t bm_idx, bit_idx, data;
+	uint32_t *booked_bm = NULL, *occupied_bm = NULL;
+
+	booked_bm = tpm_db_mod2_chain_booked_entry_bm[gmac_port][chain_type];
+	occupied_bm = tpm_db_mod2_chain_occupied_entry_bm[gmac_port][chain_type];
+
+	for (bm_idx = 0; bm_idx < tpm_db_mod2_chain_bm_group[chain_type]; bm_idx++) {
+		data = ((booked_bm[bm_idx] | occupied_bm[bm_idx]) ^ 0xffffffff);
+		if (data) {
+			chain_id = bm_idx << 5;	/* multiply 32 */
+			bit_idx = 0;
+			while (data) {
+				if (data & 0x1) {
+					chain_id += bit_idx;
+					if (chain_id < tpm_db_mod2_chain_cfg[chain_type].total_num) {
+						tpm_db_mod2_chain_cfg[chain_type].next_free[gmac_port] = chain_id;
+						return;
+					}
+					break;
+				}
+				bit_idx++;
+				data = data >> 1;
+			}
+		}
+	}
+
+	tpm_db_mod2_chain_cfg[chain_type].next_free[gmac_port] = TPM_MOD2_INVALID_CHAIN_ID;
+	return;
+}
+
+uint16_t tpm_db_mod2_get_next_free_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type)
+{
+	uint16_t next_free;
+	uint32_t i, j, mask;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS)
+		return TPM_MOD2_INVALID_CHAIN_ID;
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE)
+		return TPM_MOD2_INVALID_CHAIN_ID;
+
+	next_free = tpm_db_mod2_chain_cfg[chain_type].next_free[gmac_port];
+	if (next_free != TPM_MOD2_INVALID_CHAIN_ID) {
+		tpm_db_mod2_chain_info[gmac_port][chain_type][next_free].status = TPM_MOD_ENTRY_BOOKED;
+
+		i = j = 0;
+		j = TPM_DB_MOD_32(next_free);
+		i = TPM_DB_DIVIDED_BY_32(next_free);
+		mask = 1 << j;
+
+		tpm_db_mod2_chain_booked_entry_bm[gmac_port][chain_type][i] |= mask;
+	}
+
+	tpm_db_mod2_update_next_free_chain_entry(gmac_port, chain_type);
+
+	return next_free;
+}
+
+uint16_t tpm_db_mod2_convert_chain_to_pmt_entry(tpm_chain_type_t chain_type, uint16_t chain_id)
+{
+	tpm_mod2_chain_cfg_t *cfg_p = NULL;
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE)
+		return TPM_MOD2_NULL_ENT_IDX;
+
+	cfg_p = &tpm_db_mod2_chain_cfg[chain_type];
+
+	if (chain_id >= cfg_p->total_num)
+		return TPM_MOD2_NULL_ENT_IDX;
+
+	return (chain_id * cfg_p->max_size + cfg_p->base_entry);
+}
+
+int32_t tpm_db_mod2_get_chain_id_by_pmt_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id,
+					      tpm_chain_type_t *chain_type, uint16_t *chain_id)
+{
+	uint16_t entry_offset;
+	tpm_mod2_chain_pmt_info_t *pmt_array = NULL;
+
+	if (chain_type == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_id == NULL) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (entry_id >= TPM_MOD2_TOTAL_PMT_SIZE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	entry_offset = entry_id - tpm_mod2_chain_area_base;
+	if (entry_offset >= tpm_mod2_total_chain_num) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	pmt_array = &tpm_db_mod2_chain_pmt_info[gmac_port][entry_offset];
+
+	if (pmt_array->status != TPM_MOD_ENTRY_OCCUPIED) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid pmt entry \n");
+		return TPM_DB_ERR_REC_INV;
+	}
+
+	*chain_type = pmt_array->chain_type;
+	*chain_id = pmt_array->chain_id;
+
+	return TPM_DB_OK;
+}
+
+void tpm_db_mod2_update_next_free_jump_entry(tpm_gmacs_enum_t gmac_port)
+{
+	uint16_t entry_id /*, total_num */ ;
+	/*tpm_mod2_jump_pmt_info_t *info_array = NULL; */
+	uint32_t bm_idx, bit_idx, data;
+	uint32_t *booked_bm = NULL, *occupied_bm = NULL, *split_mod_occupied_bm = NULL;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return;
+	}
+
+	booked_bm = tpm_db_mod2_jump_booked_entry_bm[gmac_port];
+	occupied_bm = tpm_db_mod2_jump_occupied_entry_bm[gmac_port];
+	split_mod_occupied_bm = tpm_db_mod2_jump_split_mod_all_entry_bm[gmac_port];
+#if 0
+	info_array = tpm_db_mod2_jump_pmt_info[gmac_port];
+	total_num  = tpm_db_mod2_jump_area_cfg.total_num;
+
+	for (entry_id = 0; entry_id < total_num; entry_id++)
+#endif
+	for (bm_idx = 0; bm_idx < tpm_db_mod2_jump_bm_group; bm_idx++) {
+		/*if (info_array[entry_id].status == TPM_MOD_ENTRY_FREE) */
+		data = ((booked_bm[bm_idx] | occupied_bm[bm_idx] | split_mod_occupied_bm[bm_idx]) ^ 0xffffffff);
+		if (data) {
+			entry_id = bm_idx << 5;	/* multiply 32 */
+			bit_idx = 0;
+			while (data) {
+				if (data & 0x1) {
+					entry_id += bit_idx;
+					if (entry_id < tpm_db_mod2_jump_area_cfg.total_num) {
+						tpm_db_mod2_jump_area_cfg.next_free[gmac_port] = entry_id;
+						return;
+					}
+					break;
+				}
+				bit_idx++;
+				data = data >> 1;
+			}
+		}
+	}
+
+	tpm_db_mod2_jump_area_cfg.next_free[gmac_port] = TPM_MOD2_NULL_ENT_IDX;
+	return;
+}
+
+uint16_t tpm_db_mod2_get_next_free_jump_entry(tpm_gmacs_enum_t gmac_port)
+{
+	uint16_t next_free;
+	uint32_t i, j, mask;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS)
+		return TPM_MOD2_NULL_ENT_IDX;
+
+	next_free = tpm_db_mod2_jump_area_cfg.next_free[gmac_port];
+	if (next_free != TPM_MOD2_NULL_ENT_IDX) {
+		tpm_db_mod2_jump_pmt_info[gmac_port][next_free].status = TPM_MOD_ENTRY_BOOKED;
+
+		i = j = 0;
+		j = TPM_DB_MOD_32(next_free);
+		i = TPM_DB_DIVIDED_BY_32(next_free);
+		mask = 1 << j;
+
+		tpm_db_mod2_jump_booked_entry_bm[gmac_port][i] |= mask;
+	}
+
+	tpm_db_mod2_update_next_free_jump_entry(gmac_port);
+
+	return next_free;
+}
+
+uint32_t tpm_db_mod2_split_mod_get_vlan_num_in_use(tpm_gmacs_enum_t gmac_port)
+{
+	uint32_t i;
+	uint32_t vlan_num = 0;
+
+	for (i = 0; i < TPM_DB_SPLIT_MOD_NUM_VLANS_MAX; i++) {
+		if (tpm_db.split_mod_conf.gmac_vlan_conf[gmac_port].split_mod_vlan[i].valid)
+			vlan_num++; 
+	}
+
+	return vlan_num;
+}
+
+uint16_t tpm_db_mod2_get_next_split_mod_free_jump_entry(tpm_gmacs_enum_t gmac_port, tpm_pkt_mod_t *mod_data)
+{
+	uint16_t next_free;
+	uint32_t i, j, mask;
+	uint32_t vlan_index, db_ret;
+	uint32_t  pbit_index = 0;
+	tpm_vlan_key_t  *vlan_out;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS)
+		return TPM_MOD2_NULL_ENT_IDX;
+
+	db_ret = tpm_db_mod2_split_mod_get_vlan_index(gmac_port, mod_data, &vlan_index);
+	if (TPM_DB_OK != db_ret)
+		return TPM_MOD2_NULL_ENT_IDX;
+
+	/* get next_free pmt index from vid index */
+	if (0 == vlan_index)
+		/* first vlan, means vlan 0, default */
+		next_free = 1;
+	else
+		next_free = (16 * vlan_index);
+
+	if (VLANOP_EXT_TAG_MOD_INS == mod_data->vlan_mod.vlan_op)
+		vlan_out = &mod_data->vlan_mod.vlan2_out;
+	else
+		vlan_out = &mod_data->vlan_mod.vlan1_out;
+	
+	if (0 == vlan_out->pbit_mask)
+		/* pbit AS_IS */
+		pbit_index = 0;
+	else {
+		pbit_index = vlan_out->pbit;
+		if (next_free != 1)
+			pbit_index++;
+	}
+	
+	next_free += pbit_index;
+	
+	if (next_free != TPM_MOD2_NULL_ENT_IDX) {
+		tpm_db_mod2_jump_pmt_info[gmac_port][next_free].status = TPM_MOD_ENTRY_BOOKED;
+
+		i = j = 0;
+		j = TPM_DB_MOD_32(next_free);
+		i = TPM_DB_DIVIDED_BY_32(next_free);
+		mask = 1 << j;
+
+		tpm_db_mod2_jump_booked_entry_bm[gmac_port][i] |= mask;
+	}
+
+	return next_free;
+}
+int32_t tpm_db_mod2_split_mod_insert_vlan(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data)
+{
+	uint32_t i;
+	uint32_t vlan_num;
+
+	/* check vlan num right now */
+	vlan_num = tpm_db_mod2_split_mod_get_vlan_num_in_use(port);
+	if (vlan_num >= tpm_db_split_mod_get_num_vlans()){
+		TPM_OS_ERROR(TPM_DB_MOD, "already has %d num_vlans\n", vlan_num - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM);
+		return TPM_DB_ERR_DB_TBL_FULL;
+	}
+	
+	for (i = 0; i < TPM_DB_SPLIT_MOD_NUM_VLANS_MAX; i++) {
+		if (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].valid) 
+			continue;
+
+		//here finds a spot
+		tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].valid = 1;
+		
+		if (mod_data->vlan_mod.vlan1_out.vid_mask)
+			tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_1 = mod_data->vlan_mod.vlan1_out.vid;
+		
+		if (mod_data->vlan_mod.vlan2_out.vid_mask)
+			tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_2 = mod_data->vlan_mod.vlan2_out.vid;
+
+		if (mod_data->vlan_mod.vlan1_out.tpid_mask)
+			tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].tpid_1 = mod_data->vlan_mod.vlan1_out.tpid;
+
+		if (mod_data->vlan_mod.vlan2_out.tpid_mask)
+			tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].tpid_2 = mod_data->vlan_mod.vlan2_out.tpid;
+
+		tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_op = mod_data->vlan_mod.vlan_op;
+		tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].user_num = 1;
+
+		return TPM_DB_OK;
+	}
+
+	return TPM_DB_ERR_DB_TBL_FULL;
+}
+int32_t tpm_db_mod2_split_mod_get_vlan_index(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data, uint32_t *index)
+{
+	uint32_t i;
+	//printk("input: port: %d, vlan_op: %d, vlan1: %d(%d), vlan2: %d(%d)\n", 
+		//port, mod_data->vlan_mod.vlan_op, mod_data->vlan_mod.vlan1_out.vid, mod_data->vlan_mod.vlan1_out.vid_mask,
+		//mod_data->vlan_mod.vlan2_out.vid, mod_data->vlan_mod.vlan2_out.vid_mask);
+	for (i = 0; i < TPM_DB_SPLIT_MOD_NUM_VLANS_MAX; i++) {
+		//printk("output: port: %d, vlan_op: %d, vlan1: %d, vlan2: %d\n", 
+			//tpm_db.split_mod_conf.gmac_vlan_conf[i].gmac_port, tpm_db.split_mod_conf.gmac_vlan_conf[i].vlan_op,
+			//tpm_db.split_mod_conf.gmac_vlan_conf[i].vlan_1, tpm_db.split_mod_conf.gmac_vlan_conf[i].vlan_2);
+		if (!tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].valid)
+			continue;
+
+		if (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_op != mod_data->vlan_mod.vlan_op)
+			continue;
+
+		if (    (mod_data->vlan_mod.vlan1_out.vid_mask)
+			 && (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_1 != mod_data->vlan_mod.vlan1_out.vid))
+			continue;
+
+		if (    (mod_data->vlan_mod.vlan2_out.vid_mask)
+			 && (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_2 != mod_data->vlan_mod.vlan2_out.vid))
+			continue;
+
+		if (    (mod_data->vlan_mod.vlan1_out.tpid_mask)
+			 && (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].tpid_1 != mod_data->vlan_mod.vlan1_out.tpid))
+			continue;
+
+		if (    (mod_data->vlan_mod.vlan2_out.tpid_mask)
+			 && (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].tpid_2 != mod_data->vlan_mod.vlan2_out.tpid))
+			continue;
+
+		if (    (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_1)
+			 && (!mod_data->vlan_mod.vlan1_out.vid_mask))
+			continue;
+
+		if (    (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].vlan_2)
+			 && (!mod_data->vlan_mod.vlan2_out.vid_mask))
+			continue;
+
+		if (    (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].tpid_1)
+			 && (!mod_data->vlan_mod.vlan1_out.tpid_mask))
+			continue;
+
+		if (    (tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[i].tpid_2)
+			 && (!mod_data->vlan_mod.vlan2_out.tpid_mask))
+			continue;
+
+		//here finds the vlan
+		*index = i;
+		return TPM_DB_OK;
+	}
+
+	return TPM_DB_ERR_REC_NOT_EXIST;
+}
+
+int32_t tpm_db_mod2_split_mod_increase_vlan_user_num(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data)
+{
+	uint32_t index;
+	int32_t int_ret_code;
+
+	int_ret_code = tpm_db_mod2_split_mod_get_vlan_index(port, mod_data, &index);
+	if (TPM_DB_OK != int_ret_code) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "failed to get split mod vlan index\n");
+		return TPM_DB_ERR_REC_NOT_EXIST;
+	}
+
+	tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[index].user_num++;
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_split_mod_decrease_vlan_user_num(tpm_gmacs_enum_t port, 
+						     uint32_t       vlan_index,
+						     uint32_t      *user_num)
+{
+	if (port > TPM_MAX_GMAC) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid port: %d\n", port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+	
+	if (vlan_index >= TPM_DB_SPLIT_MOD_NUM_VLANS_MAX) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid vlan_index: %d\n", vlan_index);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+	
+	if (!tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[vlan_index].valid) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid vlan entry: %d\n", vlan_index);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[vlan_index].user_num--;
+	*user_num = tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[vlan_index].user_num;
+
+	if (!tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[vlan_index].user_num) {
+		TPM_OS_INFO(TPM_DB_MOD, "user num is 0, remove this vlan\n");
+		memset(&(tpm_db.split_mod_conf.gmac_vlan_conf[port].split_mod_vlan[vlan_index]), 0, sizeof(tpm_db_split_mod_vlan_t));
+	}
+
+	return TPM_DB_OK;
+}
+
+uint8_t tpm_db_mod2_rollback_jump_area(tpm_gmacs_enum_t gmac_port, uint16_t entry_id, uint8_t on_failure)
+{
+	/*uint16_t entry_idx, total_num; */
+	uint8_t dirty = 0;
+	tpm_mod2_jump_pmt_info_t *info_array = NULL;
+	uint32_t i, j, mask;
+
+	if (tpm_db_mod2_jump_pmt_info[gmac_port] == NULL)
+		return 0;
+
+	info_array = tpm_db_mod2_jump_pmt_info[gmac_port];
+	if (info_array[entry_id].status == TPM_MOD_ENTRY_BOOKED) {
+		/* TODO: check if the pmt entry is for split mod */
+		i = j = 0;
+		j = entry_id & 0x1f;
+		i = entry_id >> 5;
+		mask = 1 << j;
+
+		tpm_db_mod2_jump_booked_entry_bm[gmac_port][i] &= ~mask;
+
+		info_array[entry_id].status = TPM_MOD_ENTRY_FREE;
+		dirty = 1;
+	} else if (info_array[entry_id].status == TPM_MOD_ENTRY_OCCUPIED) {
+		if (on_failure) {
+			/* TODO: check if the pmt entry is for split mod */
+			i = j = 0;
+			j = entry_id & 0x1f;
+			i = entry_id >> 5;
+			mask = 1 << j;
+
+			tpm_db_mod2_jump_occupied_entry_bm[gmac_port][i] &= ~mask;
+
+			info_array[entry_id].status = TPM_MOD_ENTRY_FREE;
+			dirty = 1;
+		}
+	}
+
+	return dirty;
+}
+
+uint8_t tpm_db_mod2_rollback_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+					 uint16_t chain_id, uint8_t on_failure)
+{
+	uint8_t dirty = 0;
+	uint16_t entry_index, entry_num;
+	tpm_mod2_chain_info_t *info_array = NULL;
+	tpm_mod2_chain_pmt_info_t *pmt_array = NULL;
+	uint32_t i, j, mask;
+
+	if (tpm_db_mod2_chain_info[gmac_port][chain_type] == NULL)
+		return 0;
+
+	info_array = tpm_db_mod2_chain_info[gmac_port][chain_type];
+	if (info_array[chain_id].status == TPM_MOD_ENTRY_BOOKED) {
+		tpm_db_mod2_decrease_chain_user(gmac_port, chain_type, chain_id);
+
+		if (tpm_db_mod2_chain_user_num(gmac_port, chain_type, chain_id) == 0) {
+			pmt_array = &tpm_db_mod2_chain_pmt_info[gmac_port][info_array[chain_id].base_entry];
+
+			entry_num = info_array[chain_id].entry_num;
+
+			for (entry_index = 0; entry_index < entry_num; entry_index++) {
+				memset(&pmt_array[entry_index], 0, sizeof(tpm_mod2_chain_pmt_info_t));
+				pmt_array[entry_index].status = TPM_MOD_ENTRY_FREE;
+			}
+
+			i = j = 0;
+			j = chain_id & 0x1f;
+			i = chain_id >> 5;
+			mask = 1 << j;
+
+			tpm_db_mod2_chain_booked_entry_bm[gmac_port][chain_type][i] &= ~mask;
+			info_array[chain_id].status = TPM_MOD_ENTRY_FREE;
+			dirty = 1;
+		}
+	} else if (info_array[chain_id].status == TPM_MOD_ENTRY_OCCUPIED) {
+		if (on_failure)
+			tpm_db_mod2_decrease_chain_user(gmac_port, chain_type, chain_id);
+
+		if (tpm_db_mod2_chain_user_num(gmac_port, chain_type, chain_id) == 0) {
+			pmt_array = &tpm_db_mod2_chain_pmt_info[gmac_port][info_array[chain_id].base_entry];
+
+			entry_num = info_array[chain_id].entry_num;
+
+			for (entry_index = 0; entry_index < entry_num; entry_index++) {
+				memset(&pmt_array[entry_index], 0, sizeof(tpm_mod2_chain_pmt_info_t));
+				pmt_array[entry_index].status = TPM_MOD_ENTRY_FREE;
+			}
+
+			i = j = 0;
+			j = chain_id & 0x1f;
+			i = chain_id >> 5;
+			mask = 1 << j;
+
+			tpm_db_mod2_chain_occupied_entry_bm[gmac_port][chain_type][i] &= ~mask;
+
+			info_array[chain_id].status = TPM_MOD_ENTRY_FREE;
+			dirty = 1;
+		}
+	}
+	return dirty;
+}
+
+int32_t tpm_db_mod2_flush_jump_area(tpm_gmacs_enum_t gmac_port, uint16_t entry_id,
+				    uint8_t updt_next_free, uint8_t on_failure)
+{
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_rollback_jump_area(gmac_port, entry_id, on_failure) || updt_next_free)
+		tpm_db_mod2_update_next_free_jump_entry(gmac_port);
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_flush_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+				      uint16_t chain_id, uint8_t updt_next_free, uint8_t on_failure)
+{
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Invalid input\n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE)
+		return TPM_DB_ERR_INV_INPUT;
+
+    if (tpm_db_mod2_rollback_chain_entry(gmac_port, chain_type, chain_id, on_failure) || updt_next_free)
+		tpm_db_mod2_update_next_free_chain_entry(gmac_port, chain_type);
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_validate_chain_config(void)
+{
+	uint16_t chain_type, total_entries, jump_entries, napt_chains, l2_chains, free_entries;
+	uint16_t split_jump_entries, split_jump_free_entries, least_jump_entries;
+	uint8_t naptv4_unlimited, l2_unlimited, main_chain_empty, subr_chain_empty;
+	uint32_t split_vlan_num, split_pbit_num;
+
+	main_chain_empty = subr_chain_empty = 1;
+	/* check subroutine chain size */
+	if (tpm_db_mod2_get_multicast_mh_state()) {
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].total_num == 0) {
+			TPM_OS_WARN(TPM_DB_MOD, "Zero mh chain \n");
+		} else {
+			if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].total_num == TPM_CHAIN_NUM_UNLIMITED) {
+				TPM_OS_ERROR(TPM_DB_MOD, "Invalid unlimited chain type %d \n", TPM_CHAIN_TYPE_MH);
+				return TPM_DB_ERR_INV_INPUT;
+			}
+			subr_chain_empty = 0;
+		}
+	} else {
+		TPM_OS_WARN(TPM_DB_MOD, "multicast mh is disabled, mh chain size should be zero \n");
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].total_num = 0;
+	}
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].total_num == 0) {
+		TPM_OS_WARN(TPM_DB_MOD, "Zero mac chain \n");
+	} else {
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].total_num == TPM_CHAIN_NUM_UNLIMITED) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Invalid unlimited chain type %d \n", TPM_CHAIN_TYPE_MAC);
+			return TPM_DB_ERR_INV_INPUT;
+		}
+		subr_chain_empty = 0;
+	}
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].total_num == 0) {
+		TPM_OS_WARN(TPM_DB_MOD, "Zero vlan chain \n");
+	} else {
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].total_num == TPM_CHAIN_NUM_UNLIMITED) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Invalid unlimited chain type %d \n", TPM_CHAIN_TYPE_VLAN);
+			return TPM_DB_ERR_INV_INPUT;
+		}
+		subr_chain_empty = 0;
+	}
+
+	if (tpm_db_mod2_get_pppoe_add_mod_state()) {
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num != 0 ||
+			tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].total_num != 0) {
+			if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].total_num == 0) {
+				TPM_OS_WARN(TPM_DB_MOD, "Zero pppoev4 chain \n");
+			} else {
+				if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].total_num == TPM_CHAIN_NUM_UNLIMITED) {
+					TPM_OS_ERROR(TPM_DB_MOD, "Invalid unlimited chain type %d \n", TPM_CHAIN_TYPE_PPPOE);
+					return TPM_DB_ERR_INV_INPUT;
+				}
+				subr_chain_empty = 0;
+			}
+		}
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].total_num != 0 ||
+			tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].total_num) {
+			if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].total_num == 0) {
+				TPM_OS_WARN(TPM_DB_MOD, "Zero pppoev6 chain \n");
+			} else {
+				if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].total_num == TPM_CHAIN_NUM_UNLIMITED) {
+					TPM_OS_ERROR(TPM_DB_MOD, "Invalid unlimited chain type %d \n", TPM_CHAIN_TYPE_IPV6_PPPOE);
+					return TPM_DB_ERR_INV_INPUT;
+				}
+				subr_chain_empty = 0;
+			}
+		}
+	} else {
+		TPM_OS_WARN(TPM_DB_MOD, "pppoe mod is disabled, pppoe chain size should be zero \n");
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].total_num = 0;
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].total_num = 0;
+	}
+
+	if (subr_chain_empty) {
+		TPM_OS_ERROR(TPM_DB_MOD, "All subr chain is zero \n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num == 0) {
+		TPM_OS_WARN(TPM_DB_MOD, "Zero l2 main chain \n");
+	} else {
+		main_chain_empty = 0;
+	}
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num == 0) {
+		TPM_OS_WARN(TPM_DB_MOD, "Zero naptv4 main chain \n");
+	} else {
+		main_chain_empty = 0;
+	}
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].total_num == 0) {
+		TPM_OS_WARN(TPM_DB_MOD, "Zero mcv4 main chain \n");
+	} else {
+		main_chain_empty = 0;
+	}
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].total_num == 0) {
+		TPM_OS_WARN(TPM_DB_MOD, "Zero routev6 main chain \n");
+	} else {
+		main_chain_empty = 0;
+	}
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].total_num == 0) {
+		TPM_OS_WARN(TPM_DB_MOD, "Zero mcv6 main chain \n");
+	} else {
+		main_chain_empty = 0;
+	}
+	if (main_chain_empty) {
+		TPM_OS_ERROR(TPM_DB_MOD, "All main chain is zero \n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	/* check total pmt entries for all the chains */
+	total_entries = 0;
+	naptv4_unlimited = l2_unlimited = 0;
+	for (chain_type = TPM_CHAIN_TYPE_MH; chain_type < TPM_CHAIN_TYPE_MAX; chain_type++) {
+		if (tpm_db_mod2_chain_cfg[chain_type].total_num == TPM_CHAIN_NUM_UNLIMITED) {
+			if (naptv4_unlimited || l2_unlimited) {
+				TPM_OS_ERROR(TPM_DB_MOD, "Only one chain type could be assigned unlimited size \n");
+				return TPM_DB_ERR_INV_INPUT;
+			}
+
+			if (chain_type == TPM_CHAIN_TYPE_IPV4_NAPT) {
+				naptv4_unlimited = 1;
+				continue;
+			} else if (chain_type == TPM_CHAIN_TYPE_L2) {
+				l2_unlimited = 1;
+				continue;
+			} else {
+				TPM_OS_ERROR(TPM_DB_MOD, "Invalid unlimited chain type %d \n", chain_type);
+				return TPM_DB_ERR_INV_INPUT;
+			}
+		}
+		total_entries +=
+		    tpm_db_mod2_chain_cfg[chain_type].max_size * tpm_db_mod2_chain_cfg[chain_type].total_num;
+		if (total_entries >= TPM_MOD2_TOTAL_PMT_SIZE) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Not enough chain area space \n");
+			return TPM_DB_ERR_INV_INPUT;
+		}
+	}
+
+	/*the jump entries need at least without split mod*/
+	if (l2_unlimited)
+		least_jump_entries = tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].total_num;
+	else if (naptv4_unlimited)
+		least_jump_entries = tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].total_num;
+	else
+		least_jump_entries = tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].total_num +
+				tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].total_num;
+
+	/*take split mod in consider*/
+	split_jump_entries = 0;
+	split_jump_free_entries = 0;
+	if (TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) {
+		split_vlan_num = tpm_db_split_mod_get_num_vlans() - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM;
+		split_pbit_num = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
+		split_jump_entries = 16 * 2/*init added*/ +
+					(split_vlan_num - 1) * 16/*internal VLAN*/ +
+					split_pbit_num + 1/*last VLAN*/;
+		split_jump_free_entries = 2 * (15 - split_pbit_num)/*init occupy*/ + 
+					(split_vlan_num - 1) * (16 - split_pbit_num - 1)/*internal VLAN*/;
+	}
+
+	if (l2_unlimited) {
+		if (split_jump_free_entries >= least_jump_entries)
+			free_entries = TPM_MOD2_TOTAL_PMT_SIZE - total_entries - split_jump_entries;
+		else
+			free_entries = TPM_MOD2_TOTAL_PMT_SIZE - total_entries - split_jump_entries -
+				(least_jump_entries - split_jump_free_entries);
+		l2_chains = free_entries / (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].max_size + 1);
+		if (l2_chains == 0) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Zero naptv4 main chain \n");
+			return TPM_DB_ERR_INV_INPUT;
+		}
+		total_entries += l2_chains * tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].max_size;
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num = l2_chains;
+	} else if (naptv4_unlimited) {
+		if (split_jump_free_entries >= least_jump_entries)
+			free_entries = TPM_MOD2_TOTAL_PMT_SIZE - total_entries - split_jump_entries;
+		else
+			free_entries = TPM_MOD2_TOTAL_PMT_SIZE - total_entries - split_jump_entries -
+				(least_jump_entries - split_jump_free_entries);
+		napt_chains = free_entries / (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].max_size + 1);
+		if (napt_chains == 0) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Zero naptv4 main chain \n");
+			return TPM_DB_ERR_INV_INPUT;
+		}
+		total_entries += napt_chains * tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].max_size;
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num = napt_chains;
+	}
+
+	if (total_entries >= TPM_MOD2_TOTAL_PMT_SIZE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Zero jump area \n");
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	jump_entries = TPM_MOD2_TOTAL_PMT_SIZE - total_entries;
+	if (jump_entries > TPM_MOD2_MAX_JUMP_ENTRIES_NUM)
+		jump_entries = TPM_MOD2_MAX_JUMP_ENTRIES_NUM;
+
+	if ((tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num +
+	     tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num +
+	     tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].total_num +
+	     tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].total_num +
+	     tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].total_num) > jump_entries - (split_jump_entries - split_jump_free_entries))
+		TPM_OS_WARN(TPM_DB_MOD, "jump entries are not enough for main chain \n");
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].total_num > 32)
+		TPM_OS_WARN(TPM_DB_MOD, "mh sub chain is too large \n");
+
+	if ((tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num < tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].total_num)
+	    && (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num <
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].total_num))
+		TPM_OS_WARN(TPM_DB_MOD, "mac sub chain is too large \n");
+
+	if (((tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num + (split_jump_entries - split_jump_free_entries) <
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].total_num))
+	    && ((tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num + (split_jump_entries - split_jump_free_entries) <
+		tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].total_num)))
+		TPM_OS_WARN(TPM_DB_MOD, "vlan sub chain is too large \n");
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num <
+	    tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].total_num)
+		TPM_OS_WARN(TPM_DB_MOD, "pppoe sub chain is too large \n");
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_L2].total_num > 0) {
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].total_num == 0) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Zero vlan subr chain while naptv4 main chain is activated \n");
+			return TPM_DB_ERR_INV_INPUT;
+		}
+	}
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_NAPT].total_num > 0) {
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].total_num == 0) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Zero mac subr chain while naptv4 main chain is activated \n");
+			return TPM_DB_ERR_INV_INPUT;
+		}
+
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].total_num == 0) {
+			TPM_OS_WARN(TPM_DB_MOD, "Zero vlan subr chain while naptv4 main chain is activated \n");
+		}
+
+		if (tpm_db_mod2_get_pppoe_add_mod_state()) {
+			if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_PPPOE].total_num == 0) {
+				TPM_OS_WARN(TPM_DB_MOD,
+					     "Zero pppoe subr chain while naptv4 main chain is activated \n");
+			}
+		}
+	}
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_ROUTE].total_num > 0) {
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MAC].total_num == 0) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Zero mac subr chain while routev6 main chain is activated \n");
+			return TPM_DB_ERR_INV_INPUT;
+		}
+
+		if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_VLAN].total_num == 0) {
+			TPM_OS_WARN(TPM_DB_MOD, "Zero vlan subr chain while routev6 main chain is activated \n");
+		}
+
+		if (tpm_db_mod2_get_pppoe_add_mod_state()) {
+			if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_PPPOE].total_num == 0) {
+				TPM_OS_WARN(TPM_DB_MOD,
+					     "Zero pppoe subr chain while routev6 main chain is activated \n");
+			}
+		}
+	}
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV4_MC].total_num > 0) {
+		if (tpm_db_mod2_get_multicast_mh_state()) {
+			if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].total_num == 0) {
+				TPM_OS_WARN(TPM_DB_MOD, "Zero mh subr chain while mcv4 main chain is activated \n");
+			}
+		}
+	}
+
+	if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_IPV6_MC].total_num > 0) {
+		if (tpm_db_mod2_get_multicast_mh_state()) {
+			if (tpm_db_mod2_chain_cfg[TPM_CHAIN_TYPE_MH].total_num == 0) {
+				TPM_OS_WARN(TPM_DB_MOD, "Zero mh subr chain while mcv6 main chain is activated \n");
+			}
+		}
+	}
+
+	if (jump_entries < split_jump_entries)
+		TPM_OS_WARN(TPM_DB_MOD, "jump entries are not enough for split mod \n");
+
+	/* TODO: Check if jump entries are  enough for split modification */
+
+	tpm_mod2_chain_area_base = jump_entries + 1;
+	tpm_mod2_total_chain_num = total_entries;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_setup_jump_area(tpm_gmacs_enum_t port)
+{
+	uint32_t info_size, bm_size /*, port */ ;
+	uint32_t	vlan_nums;
+	uint32_t	p_bits_nums;
+	uint32_t	i, j;
+	uint32_t	loop;
+	uint32_t	loop_in;
+	uint32_t	cur_entry, mask;
+
+	tpm_db_mod2_jump_area_cfg.base_entry = 0;
+	tpm_db_mod2_jump_area_cfg.total_num = tpm_mod2_chain_area_base;
+#if 0
+	tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_GMAC_0] = 1;
+	tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_GMAC_1] = 1;
+	tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_PMAC]   = 1;
+#endif
+	tpm_db_mod2_jump_area_cfg.next_free[port] = 1;
+
+	info_size = tpm_db_mod2_jump_area_cfg.total_num * sizeof(tpm_mod2_jump_pmt_info_t);
+	if (tpm_db_mod2_jump_area_cfg.total_num % 32) {
+		bm_size = (tpm_db_mod2_jump_area_cfg.total_num / 32 + 1) * sizeof(uint32_t);
+		tpm_db_mod2_jump_bm_group = tpm_db_mod2_jump_area_cfg.total_num / 32 + 1;
+	} else {
+		bm_size = (tpm_db_mod2_jump_area_cfg.total_num / 32) * sizeof(uint32_t);
+		tpm_db_mod2_jump_bm_group = tpm_db_mod2_jump_area_cfg.total_num / 32;
+	}
+
+	/*for (port = TPM_ENUM_GMAC_0; port < TPM_MAX_NUM_GMACS; port++) */
+	{
+		if (tpm_db_mod2_jump_pmt_info[port] != NULL) {
+			vfree(tpm_db_mod2_jump_pmt_info[port]);
+			tpm_db_mod2_jump_pmt_info[port] = NULL;
+		}
+		tpm_db_mod2_jump_pmt_info[port] = (tpm_mod2_jump_pmt_info_t *) vmalloc(info_size);
+		if (tpm_db_mod2_jump_pmt_info[port] == NULL) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+		}
+		memset(tpm_db_mod2_jump_pmt_info[port], 0, info_size);
+		tpm_db_mod2_jump_pmt_info[port][0].status = TPM_MOD_ENTRY_OCCUPIED;
+
+		if (tpm_db_mod2_jump_booked_entry_bm[port] != NULL) {
+			vfree(tpm_db_mod2_jump_booked_entry_bm[port]);
+			tpm_db_mod2_jump_booked_entry_bm[port] = NULL;
+		}
+		tpm_db_mod2_jump_booked_entry_bm[port] = (uint32_t *) vmalloc(bm_size);
+		if (tpm_db_mod2_jump_booked_entry_bm[port] == NULL) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+		}
+		memset(tpm_db_mod2_jump_booked_entry_bm[port], 0, bm_size);
+
+		if (tpm_db_mod2_jump_occupied_entry_bm[port] != NULL) {
+			vfree(tpm_db_mod2_jump_occupied_entry_bm[port]);
+			tpm_db_mod2_jump_occupied_entry_bm[port] = NULL;
+		}
+		tpm_db_mod2_jump_occupied_entry_bm[port] = (uint32_t *) vmalloc(bm_size);
+		if (tpm_db_mod2_jump_occupied_entry_bm[port] == NULL) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+		}
+		memset(tpm_db_mod2_jump_occupied_entry_bm[port], 0, bm_size);
+		tpm_db_mod2_jump_occupied_entry_bm[port][0] |= 0x1;
+		
+		if (tpm_db_mod2_jump_split_mod_occupied_entry_bm[port] != NULL) {
+			vfree(tpm_db_mod2_jump_split_mod_occupied_entry_bm[port]);
+			tpm_db_mod2_jump_split_mod_occupied_entry_bm[port] = NULL;
+		}
+		tpm_db_mod2_jump_split_mod_occupied_entry_bm[port] = (uint32_t *) vmalloc(bm_size);
+		if (tpm_db_mod2_jump_split_mod_occupied_entry_bm[port] == NULL) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+		}
+		memset(tpm_db_mod2_jump_split_mod_occupied_entry_bm[port], 0xff, bm_size);
+		tpm_db_mod2_jump_split_mod_occupied_entry_bm[port][0] |= 0x1;
+
+		if (tpm_db_mod2_jump_split_mod_all_entry_bm[port] != NULL) {
+			vfree(tpm_db_mod2_jump_split_mod_all_entry_bm[port]);
+			tpm_db_mod2_jump_split_mod_all_entry_bm[port] = NULL;
+		}
+		tpm_db_mod2_jump_split_mod_all_entry_bm[port] = (uint32_t *) vmalloc(bm_size);
+		if (tpm_db_mod2_jump_split_mod_all_entry_bm[port] == NULL) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+		}
+		memset(tpm_db_mod2_jump_split_mod_all_entry_bm[port], 0, bm_size);
+	}
+
+	/* split mod init */
+	if (TPM_SPLIT_MOD_DISABLED == tpm_db_split_mod_get_enable())
+	{
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "SPLIT_MOD_DISABLED\n");
+		return(TPM_OK);
+	}
+	
+	vlan_nums = tpm_db_split_mod_get_num_vlans();
+	p_bits_nums = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
+
+	
+	tpm_db_mod2_jump_area_cfg.next_free[port] = p_bits_nums + 1;
+	//tpm_db_mod2_jump_area_cfg.next_split[port] = 16;
+
+	for (loop = 0; loop <= vlan_nums; loop++) {
+		for (loop_in = 0; loop_in <= p_bits_nums; loop_in++) {
+			cur_entry = (loop * 16) + loop_in;
+			i = j = 0;
+			j = cur_entry & 0x1f;
+			i = cur_entry >> 5;
+			mask = 1 << j;
+			tpm_db_mod2_jump_split_mod_all_entry_bm[port][i] |= mask;
+			//tpm_db_mod2_jump_occupied_entry_bm[port][i] |= mask;
+			//tpm_db_mod2_jump_split_mod_occupied_entry_bm[port][i] &= (~mask);
+		}
+	}
+	//tpm_db_mod2_jump_split_mod_occupied_entry_bm[port][0] |= (0x1);
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_setup_chain_area(tpm_gmacs_enum_t port)
+{
+	uint32_t size, /* port, */ chain;
+	uint16_t base;
+
+	printk(" ===== chain_area: base entry 0x%0x ===== \r\n", tpm_mod2_chain_area_base);
+
+	/*for (port = TPM_ENUM_GMAC_0; port < TPM_MAX_NUM_GMACS; port++) */
+	{
+		printk("[GMAC%d]:\r\n", port);
+		base = tpm_mod2_chain_area_base;
+		for (chain = TPM_CHAIN_TYPE_MH; chain < TPM_CHAIN_TYPE_MAX; chain++) {
+			if (tpm_db_mod2_chain_cfg[chain].total_num != 0) {
+				tpm_db_mod2_chain_cfg[chain].base_entry = base;
+				tpm_db_mod2_chain_cfg[chain].next_free[TPM_ENUM_GMAC_0] = 0;
+				tpm_db_mod2_chain_cfg[chain].next_free[TPM_ENUM_GMAC_1] = 0;
+				tpm_db_mod2_chain_cfg[chain].next_free[TPM_ENUM_PMAC] = 0;
+
+				size = tpm_db_mod2_chain_cfg[chain].total_num * sizeof(tpm_mod2_chain_info_t);
+
+				printk("\t chain-%d, 0x%0x - 0x%0x, chain_num: %d\r\n",
+				       chain, base,
+				       base +
+				       tpm_db_mod2_chain_cfg[chain].total_num * tpm_db_mod2_chain_cfg[chain].max_size -
+				       1, tpm_db_mod2_chain_cfg[chain].total_num);
+
+				if (tpm_db_mod2_chain_info[port][chain] != NULL) {
+					vfree(tpm_db_mod2_chain_info[port][chain]);
+					tpm_db_mod2_chain_info[port][chain] = NULL;
+				}
+				tpm_db_mod2_chain_info[port][chain] = (tpm_mod2_chain_info_t *) vmalloc(size);
+				if (tpm_db_mod2_chain_info[port][chain] == NULL) {
+					TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+					return TPM_DB_ERR_MEM_ALLOC_FAIL;
+				}
+				memset(tpm_db_mod2_chain_info[port][chain], 0, size);
+
+				if (tpm_db_mod2_chain_cfg[chain].total_num % 32) {
+					size = (tpm_db_mod2_chain_cfg[chain].total_num / 32 + 1) * sizeof(uint32_t);
+					tpm_db_mod2_chain_bm_group[chain] =
+					    tpm_db_mod2_chain_cfg[chain].total_num / 32 + 1;
+				} else {
+					size = (tpm_db_mod2_chain_cfg[chain].total_num / 32) * sizeof(uint32_t);
+					tpm_db_mod2_chain_bm_group[chain] = tpm_db_mod2_chain_cfg[chain].total_num / 32;
+				}
+
+				if (tpm_db_mod2_chain_booked_entry_bm[port][chain] != NULL) {
+					vfree(tpm_db_mod2_chain_booked_entry_bm[port][chain]);
+					tpm_db_mod2_chain_booked_entry_bm[port][chain] = NULL;
+				}
+				tpm_db_mod2_chain_booked_entry_bm[port][chain] = (uint32_t *) vmalloc(size);
+				if (tpm_db_mod2_chain_booked_entry_bm[port][chain] == NULL) {
+					TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+					return TPM_DB_ERR_MEM_ALLOC_FAIL;
+				}
+				memset(tpm_db_mod2_chain_booked_entry_bm[port][chain], 0, size);
+
+				if (tpm_db_mod2_chain_occupied_entry_bm[port][chain] != NULL) {
+					vfree(tpm_db_mod2_chain_occupied_entry_bm[port][chain]);
+					tpm_db_mod2_chain_occupied_entry_bm[port][chain] = NULL;
+				}
+				tpm_db_mod2_chain_occupied_entry_bm[port][chain] = (uint32_t *) vmalloc(size);
+				if (tpm_db_mod2_chain_occupied_entry_bm[port][chain] == NULL) {
+					TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+					return TPM_DB_ERR_MEM_ALLOC_FAIL;
+				}
+				memset(tpm_db_mod2_chain_occupied_entry_bm[port][chain], 0, size);
+
+				base += tpm_db_mod2_chain_cfg[chain].total_num * tpm_db_mod2_chain_cfg[chain].max_size;
+			}
+		}
+
+		if (tpm_db_mod2_chain_pmt_info[port] != NULL) {
+			vfree(tpm_db_mod2_chain_pmt_info[port]);
+			tpm_db_mod2_chain_pmt_info[port] = NULL;
+		}
+		size = tpm_mod2_total_chain_num * sizeof(tpm_mod2_chain_pmt_info_t);
+		tpm_db_mod2_chain_pmt_info[port] = (tpm_mod2_chain_pmt_info_t *) vmalloc(size);
+		if (tpm_db_mod2_chain_pmt_info[port] == NULL) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Memory allocation failure \n");
+			return TPM_DB_ERR_MEM_ALLOC_FAIL;
+		}
+		memset(tpm_db_mod2_chain_pmt_info[port], 0, size);
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_setup(void)
+{
+	uint32_t port;
+
+	if (tpm_db_mod2_validate_chain_config() != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Chain config validation failure \n");
+		return TPM_FAIL;
+	}
+
+	for (port = TPM_ENUM_GMAC_0; port < TPM_MAX_NUM_GMACS; port++) {
+		if (tpm_db_mod2_setup_jump_area(port) != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Failed to setup jump area \n");
+			return TPM_FAIL;
+		}
+		if (tpm_db_mod2_setup_chain_area(port) != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_DB_MOD, "Failed to setup chain area \n");
+			return TPM_FAIL;
+		}
+	}
+
+	/* init split mod data */
+	memset(&(tpm_db.split_mod_conf.gmac_vlan_conf), 0, sizeof(tpm_db.split_mod_conf.gmac_vlan_conf));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_mod2_inv_mac_entries(tpm_gmacs_enum_t gmac_port)
+{
+	if (tpm_db_mod2_setup_jump_area(gmac_port) != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Failed to setup jump area \n");
+		return TPM_FAIL;
+	}
+	if (tpm_db_mod2_setup_chain_area(gmac_port) != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_DB_MOD, "Failed to setup chain area \n");
+		return TPM_FAIL;
+	}
+
+	return TPM_DB_OK;
+}
+
+void tpm_db_mod2_show_jump_pmt_entries(tpm_gmacs_enum_t gmac_port)
+{
+	uint16_t entry_idx;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS)
+		return;
+
+	printk("              STATUS        OPCODE | DATA | LAST | UPDT_IP | UPDT_CHK \r\n");
+	for (entry_idx = 0; entry_idx < tpm_db_mod2_jump_area_cfg.total_num; entry_idx++) {
+		if (tpm_db_mod2_jump_pmt_info[gmac_port][entry_idx].status != TPM_MOD_ENTRY_FREE) {
+			printk("[PMT 0x%04x]: %s             0x%04x | 0x%04x | %d | %d | %d \r\n", entry_idx,
+			       entry_state_str[tpm_db_mod2_jump_pmt_info[gmac_port][entry_idx].status],
+			       tpm_db_mod2_jump_pmt_info[gmac_port][entry_idx].pattern.opcode,
+			       tpm_db_mod2_jump_pmt_info[gmac_port][entry_idx].pattern.data,
+			       tpm_db_mod2_jump_pmt_info[gmac_port][entry_idx].pattern.last,
+			       tpm_db_mod2_jump_pmt_info[gmac_port][entry_idx].pattern.updt_ipv4,
+			       tpm_db_mod2_jump_pmt_info[gmac_port][entry_idx].pattern.updt_tcp);
+		}
+	}
+}
+
+void tpm_db_mod2_show_jump_cfg_data(void)
+{
+	uint32_t i;
+	printk("[JUMP AREA]: base_entry 0x%04x, total_num %d, split_mod_num %d, split_mod_pbit_num %d\r\n",
+	       tpm_db_mod2_jump_area_cfg.base_entry, tpm_db_mod2_jump_area_cfg.total_num,
+	       tpm_db_mod2_jump_area_cfg.split_num, tpm_db_mod2_jump_area_cfg.split_pbit_num);
+
+	printk("[NEXT FREE]: GMAC0(G/S)       GMAC1(G/S)       PMAC(G/S)    \r\n");
+	printk("[NEXT FREE]: 0x%04x/0x%04x    0x%04x/0x%04x    0x%04x/0x%04x    \r\n",
+	       tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_GMAC_0],
+	       tpm_db_mod2_jump_area_cfg.next_split[TPM_ENUM_GMAC_0],
+	       tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_GMAC_1],
+	       tpm_db_mod2_jump_area_cfg.next_split[TPM_ENUM_GMAC_1],
+	       tpm_db_mod2_jump_area_cfg.next_free[TPM_ENUM_PMAC], tpm_db_mod2_jump_area_cfg.next_split[TPM_ENUM_PMAC]);
+#if 1
+	printk("[BOOKED_MAP]:\r\n");
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		 printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_booked_entry_bm[TPM_ENUM_GMAC_0][i]);
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_booked_entry_bm[TPM_ENUM_GMAC_1][i]);
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_booked_entry_bm[TPM_ENUM_PMAC][i]);
+
+	printk("[OCCUPIED_MAP]:\r\n");
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_occupied_entry_bm[TPM_ENUM_GMAC_0][i]);
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_occupied_entry_bm[TPM_ENUM_GMAC_1][i]);
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_occupied_entry_bm[TPM_ENUM_PMAC][i]);
+
+	printk("[SPLIT MOD OCCUPIED_MAP]:\r\n");
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_split_mod_occupied_entry_bm[TPM_ENUM_GMAC_0][i]);
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_split_mod_occupied_entry_bm[TPM_ENUM_GMAC_1][i]);
+
+	for (i = 0; i < tpm_db_mod2_jump_bm_group; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_jump_split_mod_occupied_entry_bm[TPM_ENUM_PMAC][i]);
+#endif
+}
+
+void tpm_db_mod2_show_chain_pmt_entries(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type)
+{
+	uint16_t entry_idx, pmt_idx, entry_num;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS)
+		return;
+
+	if (chain_type >= TPM_CHAIN_TYPE_MAX)
+		return;
+
+	printk("              STATUS  CHAIN/ID     OPCODE | DATA | LAST | UPDT_IP | UPDT_CHK \r\n");
+	if (chain_type == TPM_CHAIN_TYPE_NONE) {
+		for (chain_type = TPM_CHAIN_TYPE_MH; chain_type < TPM_CHAIN_TYPE_MAX; chain_type++) {
+			if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0)
+				continue;
+
+			entry_num = tpm_db_mod2_chain_cfg[chain_type].total_num * tpm_db_mod2_chain_cfg[chain_type].max_size;
+
+			for (entry_idx = 0; entry_idx < entry_num; entry_idx++) {
+				pmt_idx = entry_idx + tpm_db_mod2_chain_cfg[chain_type].base_entry - tpm_mod2_chain_area_base;
+				if (tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].status != TPM_MOD_ENTRY_FREE) {
+					printk("[PMT 0x%04x]: %s       %d/%d          0x%04x | 0x%04x | %d | %d | %d \r\n",
+					       tpm_mod2_chain_area_base + pmt_idx,
+					       entry_state_str[tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].status],
+					       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].chain_type,
+					       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].chain_id,
+					       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.opcode,
+					       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.data,
+					       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.last,
+					       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.updt_ipv4,
+					       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.updt_tcp);
+				}
+			}
+		}
+	} else {
+		if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0)
+			return;
+
+		entry_num = tpm_db_mod2_chain_cfg[chain_type].total_num * tpm_db_mod2_chain_cfg[chain_type].max_size;
+
+		for (entry_idx = 0; entry_idx < entry_num; entry_idx++) {
+			pmt_idx = entry_idx + tpm_db_mod2_chain_cfg[chain_type].base_entry - tpm_mod2_chain_area_base;
+			if (tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].status != TPM_MOD_ENTRY_FREE) {
+				printk("[PMT 0x%04x]: %s       %d/%d          0x%04x | 0x%04x | %d | %d | %d \r\n",
+				       tpm_mod2_chain_area_base + pmt_idx,
+				       entry_state_str[tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].status],
+				       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].chain_type,
+				       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].chain_id,
+				       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.opcode,
+				       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.data,
+				       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.last,
+				       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.updt_ipv4,
+				       tpm_db_mod2_chain_pmt_info[gmac_port][pmt_idx].pattern.updt_tcp);
+			}
+		}
+	}
+}
+
+void tpm_db_mod2_show_chain_info_entries(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id)
+{
+    uint32_t i;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS)
+		return;
+
+	if (chain_type > TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE)
+		return;
+
+	if (tpm_db_mod2_chain_cfg[chain_type].total_num == 0)
+		return;
+
+	printk("[CHAIN-%d Valid Entries]:\r\n", chain_type);
+
+	if (chain_id == TPM_MOD2_INVALID_CHAIN_ID) {
+		for (chain_id = 0; chain_id < tpm_db_mod2_chain_cfg[chain_type].total_num; chain_id++) {
+			if (tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].status != TPM_MOD_ENTRY_FREE) {
+				if (chain_id < tpm_db_mod2_chain_cfg[chain_type].total_num) {
+					printk("                   STATUS   BASE_ENTR   ENTR_NUM USER_NUM\r\n");
+					printk("[CHAIN-%d  0x%04x]: %s        0x%04x      %d        %d \r\n",
+					       chain_type, chain_id,
+					       entry_state_str[tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].
+							       status],
+					       tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].base_entry +
+					       tpm_mod2_chain_area_base,
+					       tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].entry_num,
+					       tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].user_num);
+				}
+			}
+		}
+	} else {
+		if (tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].status != TPM_MOD_ENTRY_FREE) {
+			if (chain_id < tpm_db_mod2_chain_cfg[chain_type].total_num) {
+				printk("[CHAIN-%d  0x%04x]: %s        0x%04x     %d      %d \r\n", chain_type, chain_id,
+				       entry_state_str[tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].status],
+				       tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].base_entry +
+				       tpm_mod2_chain_area_base,
+				       tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].entry_num,
+				       tpm_db_mod2_chain_info[gmac_port][chain_type][chain_id].user_num);
+			}
+		}
+	}
+#if 1
+	printk("[CHAIN-%d BOOKED_MAP]:\r\n", chain_type);
+
+	for (i = 0; i < tpm_db_mod2_chain_bm_group[chain_type]; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_chain_booked_entry_bm[gmac_port][chain_type][i]);
+
+	printk("[CHAIN-%d OCCUPIED_MAP]:\r\n", chain_type);
+
+	for (i = 0; i < tpm_db_mod2_chain_bm_group[chain_type]; i++)
+		printk("%02d - 0x%08x\r\n", i, tpm_db_mod2_chain_occupied_entry_bm[gmac_port][chain_type][i]);
+#endif
+	printk("\r\n");
+}
+
+void tpm_db_mod2_show_all_chain(tpm_gmacs_enum_t gmac_port)
+{
+	uint16_t chain_idx;
+
+	for (chain_idx = TPM_CHAIN_TYPE_MH; chain_idx < TPM_CHAIN_TYPE_MAX; chain_idx++)
+		tpm_db_mod2_show_chain_info_entries(gmac_port, chain_idx, TPM_MOD2_INVALID_CHAIN_ID);
+}
+
+void tpm_db_mod2_show_chain_cfg_data(tpm_chain_type_t chain_type)
+{
+	if (chain_type >= TPM_CHAIN_TYPE_MAX || chain_type == TPM_CHAIN_TYPE_NONE)
+		return;
+
+	printk("[CHAIN   %d]: base_entry 0x%04x, total_num %d, max_size %d, subr_chain %d\r\n", chain_type,
+	       tpm_db_mod2_chain_cfg[chain_type].base_entry, tpm_db_mod2_chain_cfg[chain_type].total_num,
+	       tpm_db_mod2_chain_cfg[chain_type].max_size, tpm_db_mod2_chain_cfg[chain_type].subr_chain);
+	printk("[NEXT FREE]: GMAC0     GMAC1     PMAC    \r\n");
+	printk("[NEXT FREE]: 0x%04x    0x%04x    0x%04x    \r\n",
+	       tpm_db_mod2_chain_cfg[chain_type].next_free[TPM_ENUM_GMAC_0],
+	       tpm_db_mod2_chain_cfg[chain_type].next_free[TPM_ENUM_GMAC_1],
+	       tpm_db_mod2_chain_cfg[chain_type].next_free[TPM_ENUM_PMAC]);
+}
+
+/*******************************************************************************
+* tpm_db_mod2_init()
+*
+* DESCRIPTION: The API initializes shadow DB and modification patterns
+*
+* INPUTS:   None
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_db_mod2_init(void)
+{
+	tpm_db_mod2_init_jump_area_cfg();
+	tpm_db_mod2_init_chain_cfg();
+
+	tpm_db_mod2_init_pmt_info();
+	tpm_db_mod2_init_chain_info();
+
+	return TPM_DB_OK;
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv4_us()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_set_ipv4_mtu_us(uint32_t mtu)
+{
+	tpm_db.tpm_mtu_cfg.ipv4_mtu_us = mtu;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv4_mtu_us()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_get_ipv4_mtu_us(uint32_t *mtu)
+{
+	*mtu = tpm_db.tpm_mtu_cfg.ipv4_mtu_us;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv4_pppoe_mtu_us()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_set_ipv4_pppoe_mtu_us(uint32_t mtu)
+{
+	tpm_db.tpm_mtu_cfg.ipv4_pppoe_mtu_us = mtu;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv4_pppoe_mtu_us()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_get_ipv4_pppoe_mtu_us(uint32_t *mtu)
+{
+	*mtu = tpm_db.tpm_mtu_cfg.ipv4_pppoe_mtu_us;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv6_mtu_us()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_set_ipv6_mtu_us(uint32_t mtu)
+{
+	tpm_db.tpm_mtu_cfg.ipv6_mtu_us = mtu;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv6_mtu_us()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_get_ipv6_mtu_us(uint32_t *mtu)
+{
+	*mtu = tpm_db.tpm_mtu_cfg.ipv6_mtu_us;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv6_pppoe_mtu_us()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_set_ipv6_pppoe_mtu_us(uint32_t mtu)
+{
+	tpm_db.tpm_mtu_cfg.ipv6_pppoe_mtu_us = mtu;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv6_pppoe_mtu_us()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_get_ipv6_pppoe_mtu_us(uint32_t *mtu)
+{
+	*mtu = tpm_db.tpm_mtu_cfg.ipv6_pppoe_mtu_us;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv4_mtu_ds()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_set_ipv4_mtu_ds(uint32_t mtu)
+{
+	tpm_db.tpm_mtu_cfg.ipv4_mtu_ds = mtu;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv4_mtu_ds()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_get_ipv4_mtu_ds(uint32_t *mtu)
+{
+	*mtu = tpm_db.tpm_mtu_cfg.ipv4_mtu_ds;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_set_ipv6_mtu_ds(uint32_t mtu)
+{
+	tpm_db.tpm_mtu_cfg.ipv6_mtu_ds = mtu;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_mtu_get_ipv6_mtu_ds(uint32_t *mtu)
+{
+	*mtu = tpm_db.tpm_mtu_cfg.ipv6_mtu_ds;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_set_num_vlan_tags(uint32_t number)
+{
+	tpm_db.num_vlan_tags = number;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_get_num_vlan_tags(uint32_t *number)
+{
+	*number = tpm_db.num_vlan_tags;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_set_pppoe_add_enable(tpm_db_pppoe_add_enable_t enable)
+{
+	tpm_db.tpm_pppoe_add_enable = enable;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_get_pppoe_add_enable(tpm_db_pppoe_add_enable_t *enable)
+{
+	*enable = tpm_db.tpm_pppoe_add_enable;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_set_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Set queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+* igmp_snoop       - queue number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_set_mtu_enable(tpm_db_mtu_setting_enable_t enable)
+{
+	tpm_db.tpm_mtu_cfg.mtu_enable = enable;
+	return (TPM_DB_OK);
+}
+
+/*******************************************************************************
+* tpm_db_mtu_get_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Get queue number which IGMP packets are forwarded to
+*
+* INPUTS:
+*
+* OUTPUTS:
+* igmp_snoop       - queue number
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_get_mtu_enable(tpm_db_mtu_setting_enable_t *enable)
+{
+	*enable = tpm_db.tpm_mtu_cfg.mtu_enable;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_set_cpu_rx_queue(uint32_t cpu_rx_queue)
+{
+	tpm_db.cpu_rx_queue = cpu_rx_queue;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_get_cpu_rx_queue(uint32_t *cpu_rx_queue)
+{
+	*cpu_rx_queue = tpm_db.cpu_rx_queue;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_set_ttl_illegal_action(uint32_t ttl_illegal_action)
+{
+	tpm_db.ttl_illegal_action = ttl_illegal_action;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_get_ttl_illegal_action(uint32_t *ttl_illegal_action)
+{
+	*ttl_illegal_action = tpm_db.ttl_illegal_action;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_set_tcp_flag_check(uint32_t tcp_flag_check)
+{
+	tpm_db.tcp_flag_check = tcp_flag_check;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_get_tcp_flag_check(uint32_t *tcp_flag_check)
+{
+	*tcp_flag_check = tpm_db.tcp_flag_check;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_set_mru(uint32_t mru)
+{
+	tpm_db.tpm_mtu_cfg.mru = mru;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_get_mru(uint32_t *mru)
+{
+	*mru = tpm_db.tpm_mtu_cfg.mru;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_set_catch_all_pkt_action(tpm_init_pnc_last_init_t catch_all_pkt_action)
+{
+	tpm_db.catch_all_pkt_action = catch_all_pkt_action;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_get_catch_all_pkt_action(tpm_init_pnc_last_init_t *catch_all_pkt_action)
+{
+	*catch_all_pkt_action = tpm_db.catch_all_pkt_action;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_set_switch_dev_num(int32_t switch_dev_num)
+{
+	tpm_db.switch_dev_num = switch_dev_num;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_get_switch_dev_num(int32_t *switch_dev_num)
+{
+	*switch_dev_num = tpm_db.switch_dev_num;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_set_ety_dsa_enable(tpm_db_ety_dsa_enable_t ety_dsa_enable)
+{
+	tpm_db.func_profile.ety_dsa_enable = ety_dsa_enable;
+	return (TPM_DB_OK);
+}
+
+int32_t tpm_db_get_ety_dsa_enable(tpm_db_ety_dsa_enable_t *ety_dsa_enable)
+{
+	*ety_dsa_enable = tpm_db.func_profile.ety_dsa_enable;
+	return (TPM_DB_OK);
+}
+
+void tpm_db_show_mtu_cfg(void)
+{
+	tpm_db_mtu_setting_enable_t mtu_setting_enable;
+	uint32_t mtu, mru;
+	uint32_t num_vlan_tags;
+	tpm_db_pppoe_add_enable_t pppoe_add_enable;
+
+	tpm_db_get_mtu_enable(&mtu_setting_enable);
+	printk("mtu_config: %d, \n", mtu_setting_enable);
+
+	tpm_db_mtu_get_ipv4_mtu_us(&mtu);
+	printk("ipv4_mtu_us: %d, \n", mtu);
+
+	tpm_db_mtu_get_ipv4_pppoe_mtu_us(&mtu);
+	printk("ipv4_pppoe_mtu_us: %d, \n", mtu);
+
+	tpm_db_mtu_get_ipv6_mtu_us(&mtu);
+	printk("ipv6_mtu_us: %d, \n", mtu);
+
+	tpm_db_mtu_get_ipv6_pppoe_mtu_us(&mtu);
+	printk("ipv6_pppoe_mtu_us: %d, \n", mtu);
+
+	tpm_db_mtu_get_ipv4_mtu_ds(&mtu);
+	printk("ipv4_mtu_ds: %d, \n", mtu);
+
+	tpm_db_mtu_get_ipv6_mtu_ds(&mtu);
+	printk("ipv6_mtu_ds: %d, \n", mtu);
+
+	tpm_db_get_pppoe_add_enable(&pppoe_add_enable);
+	printk("pppoe_add_enable: %d, \n", pppoe_add_enable);
+
+	tpm_db_get_num_vlan_tags(&num_vlan_tags);
+	printk("num_vlan_tags: %d, \n", num_vlan_tags);
+
+	tpm_db_get_mru(&mru);
+	printk("mru: %d, \n", mru);
+}
+
+void tpm_db_api_busy_init(void)
+{
+	memset(tpm_db.tpm_busy_apis, TPM_DB_API_NOT_BUSY, sizeof(tpm_db.tpm_busy_apis));
+}
+
+uint32_t tpm_db_get_api_busy(tpm_api_type_t api_type)
+{
+	uint32_t i;
+
+	for (i=0;i<TPM_MAX_PARALLEL_API_CALLS;i++) {
+		if (tpm_db.tpm_busy_apis[api_type][i] != TPM_DB_API_NOT_BUSY)
+			return(TPM_TRUE);
+	}
+	return(TPM_FALSE);
+}
+
+uint32_t tpm_db_get_api_rule_num_busy(tpm_api_type_t api_type, uint32_t rule_num)
+{
+	uint32_t i;
+
+	for (i=0;i<TPM_MAX_PARALLEL_API_CALLS;i++) {
+		if ( tpm_db.tpm_busy_apis[api_type][i] == rule_num)
+			return(TPM_TRUE);
+	}
+	return(TPM_FALSE);
+}
+
+
+void tpm_db_get_api_all_busy(tpm_api_type_t api_type, uint32_t *num_busy, uint32_t *rule_num_list)
+{
+	uint32_t i, l_num_busy=0;
+
+	for (i=0;i<TPM_MAX_PARALLEL_API_CALLS;i++) {
+		if ( tpm_db.tpm_busy_apis[api_type][i] != TPM_DB_API_NOT_BUSY) {
+			rule_num_list[l_num_busy] = tpm_db.tpm_busy_apis[api_type][i];
+			l_num_busy++;
+		}
+	}
+	*num_busy = l_num_busy;
+	return;
+}
+
+
+
+uint32_t tpm_db_set_api_busy(tpm_api_type_t api_type, uint32_t rule_num)
+{
+	uint32_t i;
+
+	for (i=0;i<TPM_MAX_PARALLEL_API_CALLS;i++) {
+		if ( tpm_db.tpm_busy_apis[api_type][i] == TPM_DB_API_NOT_BUSY){
+			tpm_db.tpm_busy_apis[api_type][i] = rule_num;
+			return (TPM_DB_OK);
+		}
+	}
+	return(TPM_DB_ERR_DB_TBL_FULL);
+}
+
+
+uint32_t tpm_db_set_api_free(tpm_api_type_t api_type, uint32_t rule_num)
+{
+	uint32_t i;
+
+	for (i=0;i<TPM_MAX_PARALLEL_API_CALLS;i++) {
+		if ( tpm_db.tpm_busy_apis[api_type][i] == rule_num){
+			tpm_db.tpm_busy_apis[api_type][i] = -1;
+			return (TPM_DB_OK);
+		}
+	}
+	return(TPM_DB_ERR_REC_NOT_EXIST);
+}
+
+
+
+uint32_t tpm_db_find_matched_ipv6_gen_key(tpm_ipv6_gen_acl_key_t *gen_key)
+{
+	uint32_t i;
+	tpm_db_ipv6_gen_key_t *key_array = &tpm_db.ipv6_key_shadow.gen_key[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_KEY_NUM; i++) {
+		if (key_array[i].valid == TPM_FALSE)
+			continue;
+		if (!memcmp(&key_array[i].gen_key, gen_key, sizeof(tpm_ipv6_gen_acl_key_t)))
+			return i;
+	}
+
+	return TPM_DB_INVALID_IPV6_KEY_ID;
+}
+
+uint32_t tpm_db_get_ipv6_gen_key_user_num(uint32_t key_id)
+{
+	return tpm_db.ipv6_key_shadow.gen_key[key_id].user_num;
+}
+
+void tpm_db_increase_ipv6_gen_key_user_num(uint32_t key_id)
+{
+	tpm_db.ipv6_key_shadow.gen_key[key_id].user_num++;
+}
+
+void tpm_db_decrease_ipv6_gen_key_user_num(uint32_t key_id)
+{
+	if (tpm_db.ipv6_key_shadow.gen_key[key_id].user_num > 0)
+		tpm_db.ipv6_key_shadow.gen_key[key_id].user_num--;
+}
+
+uint32_t tpm_db_set_ipv6_gen_key(tpm_ipv6_gen_acl_key_t *gen_key)
+{
+	uint32_t i, key_id = TPM_DB_INVALID_IPV6_KEY_ID;
+	tpm_db_ipv6_gen_key_t *key_array = &tpm_db.ipv6_key_shadow.gen_key[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_KEY_NUM; i++) {
+		if (key_array[i].valid == TPM_FALSE) {
+			key_id = i;
+			break;
+		}
+	}
+
+	if (key_id == TPM_DB_INVALID_IPV6_KEY_ID) {
+		return TPM_DB_INVALID_IPV6_KEY_ID;
+	}
+
+	memset(&key_array[key_id], 0, sizeof(tpm_db_ipv6_gen_key_t));
+
+	key_array[key_id].valid = TPM_TRUE;
+	memcpy(&key_array[i].gen_key, gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+
+	return key_id;
+}
+
+int32_t tpm_db_get_ipv6_gen_key(uint32_t key_id, tpm_ipv6_gen_acl_key_t *gen_key)
+{
+	tpm_db_ipv6_gen_key_t *key_array = &tpm_db.ipv6_key_shadow.gen_key[0];
+
+	if (key_id >= TPM_DB_IPV6_MAX_KEY_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (key_array[key_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_INV;
+
+	memcpy(gen_key, &key_array[key_id].gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_del_ipv6_gen_key(uint32_t key_id)
+{
+	uint32_t user_num;
+	tpm_db_ipv6_gen_key_t *key_array = &tpm_db.ipv6_key_shadow.gen_key[0];
+
+	if (key_id >= TPM_DB_IPV6_MAX_KEY_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (key_array[key_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_STATUS_ERR;
+
+	user_num = tpm_db_get_ipv6_gen_key_user_num(key_id);
+
+	if (user_num == 0)
+		memset(&key_array[key_id], 0, sizeof(tpm_db_ipv6_gen_key_t));
+
+	return TPM_DB_OK;
+}
+
+uint32_t tpm_db_find_matched_ipv6_dip_key(tpm_ipv6_addr_key_t *dip_key)
+{
+	uint32_t i;
+	tpm_db_ipv6_dip_key_t *key_array = &tpm_db.ipv6_key_shadow.dip_key[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_KEY_NUM; i++) {
+		if (key_array[i].valid == TPM_FALSE)
+			continue;
+		if (!memcmp(&key_array[i].dip_key, dip_key, sizeof(tpm_ipv6_addr_key_t)))
+			return i;
+	}
+
+	return TPM_DB_INVALID_IPV6_KEY_ID;
+}
+
+uint32_t tpm_db_get_ipv6_dip_key_user_num(uint32_t key_id)
+{
+	return tpm_db.ipv6_key_shadow.dip_key[key_id].user_num;
+}
+
+void tpm_db_increase_ipv6_dip_key_user_num(uint32_t key_id)
+{
+	tpm_db.ipv6_key_shadow.dip_key[key_id].user_num++;
+}
+
+void tpm_db_decrease_ipv6_dip_key_user_num(uint32_t key_id)
+{
+	if (tpm_db.ipv6_key_shadow.dip_key[key_id].user_num > 0)
+		tpm_db.ipv6_key_shadow.dip_key[key_id].user_num--;
+}
+
+uint32_t tpm_db_set_ipv6_dip_key(tpm_ipv6_addr_key_t *dip_key)
+{
+	uint32_t i, key_id = TPM_DB_INVALID_IPV6_KEY_ID;
+	tpm_db_ipv6_dip_key_t *key_array = &tpm_db.ipv6_key_shadow.dip_key[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_KEY_NUM; i++) {
+		if (key_array[i].valid == TPM_FALSE) {
+			key_id = i;
+			break;
+		}
+	}
+
+	if (key_id == TPM_DB_INVALID_IPV6_KEY_ID) {
+		return TPM_DB_INVALID_IPV6_KEY_ID;
+	}
+
+	memset(&key_array[key_id], 0, sizeof(tpm_db_ipv6_dip_key_t));
+
+	key_array[key_id].valid = TPM_TRUE;
+	memcpy(&key_array[i].dip_key, dip_key, sizeof(tpm_ipv6_addr_key_t));
+
+	return key_id;
+}
+
+int32_t tpm_db_get_ipv6_dip_key(uint32_t key_id, tpm_ipv6_addr_key_t *dip_key)
+{
+	tpm_db_ipv6_dip_key_t *key_array = &tpm_db.ipv6_key_shadow.dip_key[0];
+
+	if (key_id >= TPM_DB_IPV6_MAX_KEY_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (key_array[key_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_INV;
+
+	memcpy(dip_key, &key_array[key_id].dip_key, sizeof(tpm_ipv6_addr_key_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_del_ipv6_dip_key(uint32_t key_id)
+{
+	uint32_t user_num;
+	tpm_db_ipv6_dip_key_t *key_array = &tpm_db.ipv6_key_shadow.dip_key[0];
+
+	if (key_id >= TPM_DB_IPV6_MAX_KEY_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (key_array[key_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_STATUS_ERR;
+
+	user_num = tpm_db_get_ipv6_gen_key_user_num(key_id);
+
+	if (user_num == 0)
+		memset(&key_array[key_id], 0, sizeof(tpm_db_ipv6_dip_key_t));
+
+	return TPM_DB_OK;
+}
+
+uint32_t tpm_db_find_matched_ipv6_l4_key(uint32_t protocol, tpm_l4_ports_key_t *l4_key)
+{
+	uint32_t i;
+	tpm_db_ipv6_l4_key_t *key_array = &tpm_db.ipv6_key_shadow.l4_key[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_KEY_NUM; i++) {
+		if (key_array[i].valid == TPM_FALSE)
+			continue;
+		if (!memcmp(&key_array[i].l4_key, l4_key, sizeof(tpm_l4_ports_key_t)) &&
+			key_array[i].protocol == protocol)
+			return i;
+	}
+
+	return TPM_DB_INVALID_IPV6_KEY_ID;
+}
+
+uint32_t tpm_db_get_ipv6_l4_key_user_num(uint32_t key_id)
+{
+	return tpm_db.ipv6_key_shadow.l4_key[key_id].user_num;
+}
+
+void tpm_db_increase_ipv6_l4_key_user_num(uint32_t key_id)
+{
+	tpm_db.ipv6_key_shadow.l4_key[key_id].user_num++;
+}
+
+void tpm_db_decrease_ipv6_l4_key_user_num(uint32_t key_id)
+{
+	if (tpm_db.ipv6_key_shadow.l4_key[key_id].user_num > 0)
+		tpm_db.ipv6_key_shadow.l4_key[key_id].user_num--;
+}
+
+uint32_t tpm_db_set_ipv6_l4_key(uint32_t protocol, tpm_l4_ports_key_t *l4_key)
+{
+	uint32_t i, key_id = TPM_DB_INVALID_IPV6_KEY_ID;
+	tpm_db_ipv6_l4_key_t *key_array = &tpm_db.ipv6_key_shadow.l4_key[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_KEY_NUM; i++) {
+		if (key_array[i].valid == TPM_FALSE) {
+			key_id = i;
+			break;
+		}
+	}
+
+	if (key_id == TPM_DB_INVALID_IPV6_KEY_ID) {
+		return TPM_DB_INVALID_IPV6_KEY_ID;
+	}
+
+	memset(&key_array[key_id], 0, sizeof(tpm_db_ipv6_l4_key_t));
+
+	key_array[key_id].valid = TPM_TRUE;
+	memcpy(&key_array[i].l4_key, l4_key, sizeof(tpm_l4_ports_key_t));
+	key_array[key_id].protocol = protocol;
+
+	return key_id;
+}
+
+int32_t tpm_db_get_ipv6_l4_key(uint32_t key_id, uint32_t *protocol, tpm_l4_ports_key_t *l4_key)
+{
+	tpm_db_ipv6_l4_key_t *key_array = &tpm_db.ipv6_key_shadow.l4_key[0];
+
+	if (key_id >= TPM_DB_IPV6_MAX_KEY_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (key_array[key_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_INV;
+
+	memcpy(l4_key, &key_array[key_id].l4_key, sizeof(tpm_l4_ports_key_t));
+	*protocol = key_array[key_id].protocol;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_del_ipv6_l4_key(uint32_t key_id)
+{
+	uint32_t user_num;
+	tpm_db_ipv6_l4_key_t *key_array = &tpm_db.ipv6_key_shadow.l4_key[0];
+
+	if (key_id >= TPM_DB_IPV6_MAX_KEY_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (key_array[key_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_STATUS_ERR;
+
+	user_num = tpm_db_get_ipv6_l4_key_user_num(key_id);
+
+	if (user_num == 0)
+		memset(&key_array[key_id], 0, sizeof(tpm_db_ipv6_l4_key_t));
+
+	return TPM_DB_OK;
+}
+
+uint32_t tpm_db_find_matched_ipv6_l4_subflow(uint32_t src_dir, uint32_t parse_bm, uint32_t protocol, tpm_l4_ports_key_t *l4_key)
+{
+	int32_t ret;
+	uint32_t i, _protocol;
+	tpm_db_ipv6_l4_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[0];
+	tpm_l4_ports_key_t _l4_key;
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_SUBFLOW_NUM; i++) {
+		if (flow_array[i].valid == TPM_FALSE)
+			continue;
+
+		if (parse_bm == flow_array[i].parse_bm) {
+			memset(&_l4_key, 0, sizeof(tpm_l4_ports_key_t));
+			ret = tpm_db_get_ipv6_l4_key(flow_array[i].l4_key, &_protocol, &_l4_key);
+			if (ret != TPM_DB_OK)
+				break;
+
+			if (_protocol != protocol)
+				continue;
+
+			if (parse_bm & TPM_PARSE_L4_SRC) {
+				if (_l4_key.l4_src_port != l4_key->l4_src_port)
+					continue;
+			}
+
+			if (parse_bm & TPM_PARSE_L4_DST) {
+				if (_l4_key.l4_dst_port != l4_key->l4_dst_port)
+					continue;
+			}
+
+			return i;
+		}
+	}
+
+	if (i < TPM_DB_IPV6_MAX_SUBFLOW_NUM)
+		TPM_OS_WARN(TPM_DB_MOD, "Warning: DB inconsistency\n");
+
+	return TPM_DB_INVALID_IPV6_FLOW_ID;
+}
+
+uint32_t tpm_db_get_ipv6_l4_subflow_user_num(uint32_t src_dir, uint32_t flow_id)
+{
+	return tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[flow_id].user_num;
+}
+
+void tpm_db_increase_ipv6_l4_subflow_user_num(uint32_t src_dir, uint32_t flow_id)
+{
+	tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[flow_id].user_num++;
+}
+
+void tpm_db_decrease_ipv6_l4_subflow_user_num(uint32_t src_dir, uint32_t flow_id)
+{
+	if (tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[flow_id].user_num > 0)
+		tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[flow_id].user_num--;
+}
+
+uint32_t tpm_db_get_free_ipv6_l4_subflow(uint32_t src_dir)
+{
+	uint32_t i;
+	tpm_db_ipv6_l4_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_SUBFLOW_NUM; i++) {
+		if (flow_array[i].valid == TPM_FALSE)
+			return i;
+	}
+
+	return TPM_DB_INVALID_IPV6_FLOW_ID;
+}
+
+int32_t tpm_db_set_ipv6_l4_subflow(uint32_t src_dir, uint32_t flow_id, uint32_t parse_bm, uint32_t protocol, tpm_l4_ports_key_t *l4_key)
+{
+	uint32_t l4_key_id;
+	tpm_db_ipv6_l4_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[0];
+
+	if (flow_id >= TPM_DB_IPV6_MAX_SUBFLOW_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (flow_array[flow_id].valid != TPM_FALSE)
+		return TPM_DB_ERR_REC_STATUS_ERR;
+
+	l4_key_id = tpm_db_find_matched_ipv6_l4_key(protocol, l4_key);
+
+	if (l4_key_id == TPM_DB_INVALID_IPV6_KEY_ID) {
+		l4_key_id = tpm_db_set_ipv6_l4_key(protocol, l4_key);
+		if (l4_key_id == TPM_DB_INVALID_IPV6_KEY_ID) {
+			return TPM_DB_ERR_DB_TBL_FULL;
+		}
+	}
+
+	tpm_db_increase_ipv6_l4_key_user_num(l4_key_id);
+
+	memset(&flow_array[flow_id], 0, sizeof(tpm_db_ipv6_l4_flow_t));
+
+	flow_array[flow_id].valid = TPM_TRUE;
+	flow_array[flow_id].parse_bm = parse_bm;
+	flow_array[flow_id].l4_key = l4_key_id;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_ipv6_l4_subflow(uint32_t src_dir, uint32_t flow_id, uint32_t *parse_bm, uint32_t *protocol, tpm_l4_ports_key_t *l4_key)
+{
+	int32_t ret;
+	tpm_db_ipv6_l4_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[0];
+	uint32_t _protocol;
+	tpm_l4_ports_key_t _l4_key;
+
+	if (flow_id >= TPM_DB_IPV6_MAX_SUBFLOW_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (flow_array[flow_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_INV;
+
+	memset(&_l4_key, 0, sizeof(tpm_l4_ports_key_t));
+	ret = tpm_db_get_ipv6_l4_key(flow_array[flow_id].l4_key, &_protocol, &_l4_key);
+
+	if (ret != TPM_DB_OK)
+		return TPM_DB_ERR_REC_STATUS_ERR;
+
+	*parse_bm = flow_array[flow_id].parse_bm;
+	*protocol = _protocol;
+	memcpy(l4_key, &_l4_key, sizeof(tpm_l4_ports_key_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_del_ipv6_l4_subflow(uint32_t src_dir, uint32_t flow_id)
+{
+	uint32_t user_num;
+	tpm_db_ipv6_l4_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[0];
+
+	if (flow_id >= TPM_DB_IPV6_MAX_SUBFLOW_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (flow_array[flow_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_INV;
+
+
+	user_num = tpm_db_get_ipv6_l4_subflow_user_num(src_dir, flow_id);
+	if (user_num == 0) {
+		tpm_db_decrease_ipv6_l4_key_user_num(flow_array[flow_id].l4_key);
+		tpm_db_del_ipv6_l4_key(flow_array[flow_id].l4_key);
+		memset(&flow_array[flow_id], 0, sizeof(tpm_db_ipv6_l4_flow_t));
+	}
+
+	return TPM_DB_OK;
+}
+
+uint32_t tpm_db_find_matched_ipv6_gen_subflow(uint32_t src_dir, uint32_t parse_bm, uint32_t protocol,
+											tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key)
+{
+	uint32_t i, l4_key_id, gen_key_id;
+	tpm_db_ipv6_gen_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_SUBFLOW_NUM; i++) {
+		if (flow_array[i].valid == TPM_FALSE)
+			continue;
+
+		if (parse_bm == flow_array[i].parse_bm) {
+			if (flow_array[i].l4_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+				l4_key_id = tpm_db_find_matched_ipv6_l4_key(protocol, l4_key);
+				if (l4_key_id == TPM_DB_INVALID_IPV6_KEY_ID)
+					continue;
+				if (l4_key_id != flow_array[i].l4_key)
+					continue;
+			}
+
+			if (flow_array[i].gen_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+				gen_key_id = tpm_db_find_matched_ipv6_gen_key(gen_key);
+				if (gen_key_id == TPM_DB_INVALID_IPV6_KEY_ID)
+					continue;
+				if (gen_key_id != flow_array[i].gen_key)
+					continue;
+			}
+
+			return i;
+		}
+	}
+
+	return TPM_DB_INVALID_IPV6_FLOW_ID;
+}
+
+uint32_t tpm_db_get_ipv6_gen_subflow_user_num(uint32_t src_dir, uint32_t flow_id)
+{
+	return tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[flow_id].user_num;
+}
+
+void tpm_db_increase_ipv6_gen_subflow_user_num(uint32_t src_dir, uint32_t flow_id)
+{
+	tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[flow_id].user_num++;
+}
+
+void tpm_db_decrease_ipv6_gen_subflow_user_num(uint32_t src_dir, uint32_t flow_id)
+{
+	if (tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[flow_id].user_num > 0)
+		tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[flow_id].user_num--;
+}
+
+uint32_t tpm_db_get_free_ipv6_gen_subflow(uint32_t src_dir)
+{
+	uint32_t i;
+	tpm_db_ipv6_gen_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_SUBFLOW_NUM; i++) {
+		if (flow_array[i].valid == TPM_FALSE)
+			return i;
+	}
+
+	return TPM_DB_INVALID_IPV6_FLOW_ID;
+}
+
+int32_t tpm_db_set_ipv6_gen_subflow(uint32_t src_dir, uint32_t flow_id, uint32_t parse_bm, uint32_t protocol,
+									tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key)
+{
+	uint32_t l4_parse_bm, gen_parse_bm, l4_flow_id, l4_key_id, gen_key_id;
+	tpm_db_ipv6_gen_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[0];
+
+	l4_key_id = gen_key_id = TPM_DB_INVALID_IPV6_KEY_ID;
+	l4_flow_id = TPM_DB_INVALID_IPV6_FLOW_ID;
+
+	if (flow_id >= TPM_DB_IPV6_MAX_SUBFLOW_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (flow_array[flow_id].valid != TPM_FALSE)
+		return TPM_DB_ERR_REC_STATUS_ERR;
+
+	l4_parse_bm = parse_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+
+	if (l4_parse_bm != 0) {
+		l4_flow_id = tpm_db_find_matched_ipv6_l4_subflow(src_dir, l4_parse_bm, protocol, l4_key);
+
+		if (l4_flow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+
+		l4_key_id = tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[l4_flow_id].l4_key;
+	}
+
+	gen_parse_bm = parse_bm & ~TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+
+	if (gen_parse_bm != 0) {
+		gen_key_id = tpm_db_find_matched_ipv6_gen_key(gen_key);
+
+		if (gen_key_id == TPM_DB_INVALID_IPV6_KEY_ID) {
+			gen_key_id = tpm_db_set_ipv6_gen_key(gen_key);
+			if (gen_key_id == TPM_DB_INVALID_IPV6_KEY_ID) {
+				return TPM_DB_ERR_DB_TBL_FULL;
+			}
+		}
+	}
+
+	if (l4_flow_id != TPM_DB_INVALID_IPV6_FLOW_ID)
+		tpm_db_increase_ipv6_l4_subflow_user_num(src_dir, l4_flow_id);
+
+	if (gen_key_id != TPM_DB_INVALID_IPV6_KEY_ID)
+		tpm_db_increase_ipv6_gen_key_user_num(gen_key_id);
+
+	memset(&flow_array[flow_id], 0, sizeof(tpm_db_ipv6_gen_flow_t));
+
+	flow_array[flow_id].valid = TPM_TRUE;
+	flow_array[flow_id].parse_bm = parse_bm;
+	flow_array[flow_id].l4_key = l4_key_id;
+	flow_array[flow_id].gen_key = gen_key_id;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_ipv6_gen_subflow(uint32_t src_dir, uint32_t flow_id, uint32_t *parse_bm, uint32_t *protocol,
+				    tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key)
+{
+	int32_t ret;
+	tpm_db_ipv6_gen_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[0];
+	uint32_t _protocol = 0;
+	tpm_l4_ports_key_t _l4_key;
+	tpm_ipv6_gen_acl_key_t _gen_key;
+
+	if (flow_id >= TPM_DB_IPV6_MAX_SUBFLOW_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (flow_array[flow_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_INV;
+
+	if (flow_array[flow_id].l4_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+		memset(&_l4_key, 0, sizeof(tpm_l4_ports_key_t));
+		ret = tpm_db_get_ipv6_l4_key(flow_array[flow_id].l4_key, &_protocol, &_l4_key);
+
+		if (ret != TPM_DB_OK)
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+	}
+
+	if (flow_array[flow_id].gen_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+		memset(&_gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+		ret = tpm_db_get_ipv6_gen_key(flow_array[flow_id].gen_key, &_gen_key);
+
+		if (ret != TPM_DB_OK)
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+	}
+
+	*parse_bm = flow_array[flow_id].parse_bm;
+	*protocol = _protocol;
+	memcpy(l4_key, &_l4_key, sizeof(tpm_l4_ports_key_t));
+	memcpy(gen_key, &_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_del_ipv6_gen_subflow(uint32_t src_dir, uint32_t flow_id)
+{
+	int32_t ret;
+	uint32_t user_num, l4_flow_id, l4_parse_bm, protocol;
+	tpm_db_ipv6_gen_flow_t *flow_array = &tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[0];
+	tpm_l4_ports_key_t l4_key;
+
+	if (flow_id >= TPM_DB_IPV6_MAX_SUBFLOW_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (flow_array[flow_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_STATUS_ERR;
+
+	user_num = tpm_db_get_ipv6_gen_subflow_user_num(src_dir, flow_id);
+	if (user_num == 0) {
+		if (flow_array[flow_id].gen_key != TPM_DB_INVALID_IPV6_KEY_ID)
+			tpm_db_decrease_ipv6_gen_key_user_num(flow_array[flow_id].gen_key);
+
+		tpm_db_del_ipv6_gen_key(flow_array[flow_id].gen_key);
+
+		if (flow_array[flow_id].l4_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+			memset(&l4_key, 0, sizeof(tpm_l4_ports_key_t));
+			ret = tpm_db_get_ipv6_l4_key(flow_array[flow_id].l4_key, &protocol, &l4_key);
+
+			if (ret != TPM_DB_OK)
+				return TPM_DB_ERR_DB_INCONSISTENCY;
+
+			l4_parse_bm = flow_array[flow_id].parse_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+			l4_flow_id = tpm_db_find_matched_ipv6_l4_subflow(src_dir, l4_parse_bm, protocol, &l4_key);
+
+			if (l4_flow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+				return TPM_DB_ERR_DB_INCONSISTENCY;
+
+			tpm_db_decrease_ipv6_l4_subflow_user_num(src_dir, l4_flow_id);
+		}
+
+		memset(&flow_array[flow_id], 0, sizeof(tpm_db_ipv6_gen_flow_t));
+	}
+	return TPM_DB_OK;
+}
+
+uint32_t tpm_db_find_matched_ipv6_5t_flow(uint32_t src_dir, uint32_t parse_bm, uint32_t is_pppoe, uint32_t protocol,
+							tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key, tpm_ipv6_addr_key_t *dip_key)
+{
+	uint32_t i, key_id;
+	tpm_db_ipv6_5t_flow_shadow_t *flow_array = &tpm_db.ipv6_5t_flow_shadow[0];
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_5T_FLOW_NUM; i++) {
+		if (flow_array[i].valid == TPM_FALSE)
+			continue;
+
+		if (parse_bm == flow_array[i].parse_bm &&
+			src_dir == flow_array[i].src_dir &&
+			is_pppoe == flow_array[i].is_pppoe) {
+			if (flow_array[i].l4_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+				key_id = tpm_db_find_matched_ipv6_l4_key(protocol, l4_key);
+				if (key_id == TPM_DB_INVALID_IPV6_KEY_ID)
+					continue;
+				if (key_id != flow_array[i].l4_key)
+					continue;
+			}
+
+			if (flow_array[i].gen_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+				key_id = tpm_db_find_matched_ipv6_gen_key(gen_key);
+				if (key_id == TPM_DB_INVALID_IPV6_KEY_ID)
+					continue;
+				if (key_id != flow_array[i].gen_key)
+					continue;
+			}
+
+			if (flow_array[i].dip_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+				key_id = tpm_db_find_matched_ipv6_dip_key(dip_key);
+				if (key_id == TPM_DB_INVALID_IPV6_KEY_ID)
+					continue;
+				if (key_id != flow_array[i].dip_key)
+					continue;
+			}
+
+			return i;
+		}
+	}
+
+	return TPM_DB_INVALID_IPV6_FLOW_ID;
+}
+
+int32_t tpm_db_set_ipv6_5t_flow(uint32_t src_dir, uint32_t parse_bm,  uint32_t is_pppoe, uint32_t protocol,
+							tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key, tpm_ipv6_addr_key_t *dip_key)
+{
+	uint32_t i, _parse_bm, subflow_id, l4_key_id, gen_key_id, dip_key_id, flow_id = TPM_DB_INVALID_IPV6_FLOW_ID;
+	tpm_db_ipv6_5t_flow_shadow_t *flow_array = &tpm_db.ipv6_5t_flow_shadow[0];
+
+	l4_key_id = gen_key_id = dip_key_id = TPM_DB_INVALID_IPV6_KEY_ID;
+
+	for (i = 0; i < TPM_DB_IPV6_MAX_5T_FLOW_NUM; i++) {
+		if (flow_array[i].valid == TPM_FALSE) {
+			flow_id = i;
+			break;
+		}
+	}
+
+	if (flow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+		return TPM_DB_ERR_DB_TBL_FULL;
+
+	_parse_bm = parse_bm & ~TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
+	if (_parse_bm != 0) {
+		dip_key_id = tpm_db_find_matched_ipv6_dip_key(dip_key);
+		if (dip_key_id == TPM_DB_INVALID_IPV6_KEY_ID) {
+			dip_key_id = tpm_db_set_ipv6_dip_key(dip_key);
+			if (dip_key_id == TPM_DB_INVALID_IPV6_KEY_ID)
+				return TPM_DB_ERR_DB_INCONSISTENCY;
+		}
+	}
+
+	_parse_bm = parse_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
+	if (_parse_bm != 0) {
+		subflow_id = tpm_db_find_matched_ipv6_gen_subflow(src_dir, _parse_bm, protocol, l4_key, gen_key);
+		if (subflow_id != TPM_DB_INVALID_IPV6_FLOW_ID) {
+			tpm_db_increase_ipv6_gen_subflow_user_num(src_dir, subflow_id);
+			gen_key_id = tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[subflow_id].gen_key;
+			l4_key_id = tpm_db.ipv6_subflow_shadow[src_dir].gen_flow[subflow_id].l4_key;
+		} else {
+			_parse_bm = parse_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+			if (_parse_bm != 0) {
+				subflow_id = tpm_db_find_matched_ipv6_l4_subflow(src_dir, _parse_bm, protocol, l4_key);
+				if (subflow_id != TPM_DB_INVALID_IPV6_FLOW_ID) {
+					tpm_db_increase_ipv6_l4_subflow_user_num(src_dir, subflow_id);
+					l4_key_id = tpm_db.ipv6_subflow_shadow[src_dir].l4_flow[subflow_id].l4_key;
+				}
+			}
+		}
+	}
+
+	if (dip_key_id != TPM_DB_INVALID_IPV6_KEY_ID)
+		tpm_db_increase_ipv6_dip_key_user_num(dip_key_id);
+
+	memset(&flow_array[flow_id], 0, sizeof(tpm_db_ipv6_5t_flow_shadow_t));
+
+	flow_array[flow_id].valid = TPM_TRUE;
+	flow_array[flow_id].src_dir = src_dir;
+	flow_array[flow_id].parse_bm = parse_bm;
+	flow_array[flow_id].is_pppoe = is_pppoe;
+	flow_array[flow_id].gen_key = gen_key_id;
+	flow_array[flow_id].dip_key = dip_key_id;
+	flow_array[flow_id].l4_key = l4_key_id;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_ipv6_5t_flow(uint32_t flow_id, uint32_t *src_dir, uint32_t *parse_bm, uint32_t *is_pppoe, uint32_t *protocol,
+							tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key, tpm_ipv6_addr_key_t *dip_key)
+{
+	int32_t ret;
+	tpm_db_ipv6_5t_flow_shadow_t *flow_array = &tpm_db.ipv6_5t_flow_shadow[0];
+	tpm_l4_ports_key_t _l4_key;
+	tpm_ipv6_gen_acl_key_t _gen_key;
+	tpm_ipv6_addr_key_t _dip_key;
+	uint32_t _protocol = 0;
+
+	memset(&_l4_key, 0, sizeof(tpm_l4_ports_key_t));
+	memset(&_gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+	memset(&_dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+
+	if (flow_id >= TPM_DB_IPV6_MAX_5T_FLOW_NUM)
+		return TPM_DB_ERR_INV_INPUT;
+
+	if (flow_array[flow_id].valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_INV;
+
+	if (flow_array[flow_id].l4_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+		ret = tpm_db_get_ipv6_l4_key(flow_array[flow_id].l4_key, &_protocol, &_l4_key);
+		if (ret != TPM_DB_OK)
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+	}
+
+	if (flow_array[flow_id].gen_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+		ret = tpm_db_get_ipv6_gen_key(flow_array[flow_id].gen_key, &_gen_key);
+		if (ret != TPM_DB_OK)
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+	}
+
+	if (flow_array[flow_id].dip_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+		ret = tpm_db_get_ipv6_dip_key(flow_array[flow_id].dip_key, &_dip_key);
+		if (ret != TPM_DB_OK)
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+	}
+
+	*src_dir = flow_array[flow_id].src_dir;
+	*parse_bm = flow_array[flow_id].parse_bm;
+	*is_pppoe = flow_array[flow_id].is_pppoe;
+	*protocol = _protocol;
+	memcpy(l4_key, &_l4_key, sizeof(tpm_l4_ports_key_t));
+	memcpy(gen_key, &_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+	memcpy(dip_key, &_dip_key, sizeof(tpm_ipv6_addr_key_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_del_ipv6_5t_flow(uint32_t flow_id)
+{
+	int32_t ret;
+	tpm_db_ipv6_5t_flow_shadow_t *flow_array = &tpm_db.ipv6_5t_flow_shadow[0];
+	tpm_l4_ports_key_t l4_key;
+	tpm_ipv6_gen_acl_key_t gen_key;
+	tpm_ipv6_addr_key_t dip_key;
+	uint32_t src_dir, parse_bm, protocol, subflow_bm, subflow_id, is_pppoe;
+
+
+	ret = tpm_db_get_ipv6_5t_flow(flow_id, &src_dir, &parse_bm, &is_pppoe, &protocol, &l4_key, &gen_key, &dip_key);
+
+	if (ret != TPM_DB_OK)
+		return TPM_DB_ERR_REC_INV;
+
+	subflow_bm = parse_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
+	if (subflow_bm != 0) {
+		subflow_id = tpm_db_find_matched_ipv6_gen_subflow(src_dir, subflow_bm, protocol, &l4_key, &gen_key);
+		if (subflow_id != TPM_DB_INVALID_IPV6_FLOW_ID)
+			tpm_db_decrease_ipv6_gen_subflow_user_num(src_dir, subflow_id);
+		else {
+			subflow_bm = parse_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+			if (subflow_bm != 0) {
+				subflow_id = tpm_db_find_matched_ipv6_l4_subflow(src_dir, subflow_bm, protocol, &l4_key);
+				if (subflow_id != TPM_DB_INVALID_IPV6_FLOW_ID)
+					tpm_db_decrease_ipv6_l4_subflow_user_num(src_dir, subflow_id);
+			}
+		}
+	}
+
+	if (flow_array[flow_id].dip_key != TPM_DB_INVALID_IPV6_KEY_ID) {
+		tpm_db_decrease_ipv6_dip_key_user_num(flow_array[flow_id].dip_key);
+		tpm_db_del_ipv6_dip_key(flow_array[flow_id].dip_key);
+	}
+
+	memset(&flow_array[flow_id], 0, sizeof(tpm_db_ipv6_5t_flow_shadow_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_init_ipv6_5t_flow_reset(void)
+{
+	memset(&tpm_db.ipv6_key_shadow, 0, sizeof(tpm_db_ipv6_key_shadow_t));
+	memset(tpm_db.ipv6_subflow_shadow, 0, TPM_NUM_DIRECTIONS * sizeof(tpm_db_ipv6_subflow_shadow_t));
+	memset(tpm_db.ipv6_5t_flow_shadow, 0, TPM_DB_IPV6_MAX_5T_FLOW_NUM * sizeof(tpm_db_ipv6_5t_flow_shadow_t));
+
+	return TPM_DB_OK;
+}
+int32_t tpm_db_ctc_cm_rule_set(tpm_src_port_type_t src_port,
+			       uint32_t precedence,
+			       tpm_parse_fields_t l2_parse_rule_bm,
+			       tpm_parse_fields_t ipv4_parse_rule_bm,
+			       tpm_parse_fields_t ipv6_parse_rule_bm,
+			       tpm_l2_acl_key_t *l2_key,
+			       tpm_ipv4_acl_key_t *ipv4_key,
+			       tpm_ipv6_acl_key_t *ipv6_key,
+			       tpm_pkt_frwd_t *pkt_frwd,
+			       tpm_pkt_action_t pkt_act,
+			       uint32_t pbits,
+			       uint32_t ipv4_sub_pattern_index,
+			       uint32_t rule_index)
+{
+	tpm_db_ctc_cm_rule_entry_t *rule_entry;
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if(precedence >= TPM_MAX_NUM_CTC_PRECEDENCE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input precedence(%d)\n", precedence);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	rule_entry = &tpm_db.ctc_cm_data.cm_rule[src_port][precedence];
+
+	rule_entry->l2_parse_rule_bm   = l2_parse_rule_bm;
+	rule_entry->ipv4_parse_rule_bm = ipv4_parse_rule_bm;
+	rule_entry->ipv6_parse_rule_bm = ipv6_parse_rule_bm;
+	memcpy(&rule_entry->l2_key, l2_key, sizeof(tpm_l2_acl_key_t));
+	memcpy(&rule_entry->ipv4_key, ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+	memcpy(&rule_entry->ipv6_key, ipv6_key, sizeof(tpm_ipv6_acl_key_t));
+	memcpy(&rule_entry->pkt_frwd, pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	rule_entry->pkt_act                = pkt_act;
+	rule_entry->pbits                  = pbits;
+	rule_entry->cm_main_rule_index     = rule_index;
+	rule_entry->ipv4_sub_pattern_key   = ipv4_sub_pattern_index;
+	rule_entry->valid                  = 1;
+
+	if(l2_parse_rule_bm & ipv4_parse_rule_bm)
+		rule_entry->rule_type = TPM_CTC_CM_COMBO;
+	else if(l2_parse_rule_bm)
+		rule_entry->rule_type = TPM_CTC_CM_L2;
+	else if(ipv4_parse_rule_bm)
+		rule_entry->rule_type = TPM_CTC_CM_IPv4;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_ctc_cm_rule_delete(tpm_src_port_type_t src_port, uint32_t precedence)
+{
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if(precedence >= TPM_MAX_NUM_CTC_PRECEDENCE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input precedence(%d)\n", precedence);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	memset(&tpm_db.ctc_cm_data.cm_rule[src_port][precedence], 0, sizeof(tpm_db_ctc_cm_rule_entry_t));
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_ctc_cm_rule_get(tpm_src_port_type_t src_port, uint32_t precedence, tpm_db_ctc_cm_rule_entry_t *cm_rule)
+{
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if(precedence >= TPM_MAX_NUM_CTC_PRECEDENCE) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input precedence(%d)\n", precedence);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	memcpy(cm_rule, &tpm_db.ctc_cm_data.cm_rule[src_port][precedence], sizeof(tpm_db_ctc_cm_rule_entry_t));
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_ctc_cm_get_num_rules(tpm_src_port_type_t src_port)
+{
+	int32_t loop;
+	int32_t num_rules = 0;
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	for(loop = 0; loop < TPM_MAX_NUM_CTC_PRECEDENCE; loop++)
+		if(tpm_db.ctc_cm_data.cm_rule[src_port][loop].valid)
+			num_rules++;
+
+	return num_rules;
+}
+
+int32_t tpm_db_ctc_cm_get_ipv6_num_rules(void)
+{
+	int32_t loop;
+	int32_t num_rules = 0;
+	tpm_src_port_type_t src_port;
+
+	for (src_port = TPM_SRC_PORT_UNI_0; src_port < TPM_MAX_NUM_UNI_PORTS; src_port++)
+		for(loop = 0; loop < TPM_MAX_NUM_CTC_PRECEDENCE; loop++)
+			if(    (tpm_db.ctc_cm_data.cm_rule[src_port][loop].valid)
+			    && (tpm_db.ctc_cm_data.cm_rule[src_port][loop].ipv6_parse_rule_bm))
+				num_rules++;
+
+	return num_rules;
+}
+
+int32_t tpm_db_ctc_cm_db_reset(void)
+{
+	memset(&tpm_db.ctc_cm_data.cm_rule, 0, sizeof(tpm_db.ctc_cm_data.cm_rule));
+	memset(&tpm_db.ctc_cm_data.ipv4_pre_table, 0, sizeof(tpm_db_cnm_ipv4_pre_table_t));
+	memset(&tpm_db.ctc_cm_data.ipv4_pre_filter, 0, TPM_MAX_NUM_UNI_PORTS * sizeof(tpm_db_cnm_ipv4_pre_filter_t));
+	tpm_db.ctc_cm_data.ipv6_parse_win = tpm_db.ctc_cm_data.ipv6_parse_win_original;
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_ipv6_mc_sip_db_reset(void)
+{
+	memset(&tpm_db.ipv6_mc_sip, 0, sizeof(tpm_db.ipv6_mc_sip));
+	/* reserve the first IPv6 MC SIP entry for not matching any SIP */
+	tpm_db.ipv6_mc_sip[0].valid = 1;
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_ipv6_mc_sip_index_get(uint8_t  *src_ip)
+{
+	uint32_t i;
+	int32_t ret;
+	tpm_db_pnc_range_t range_data;
+
+	/*check param*/
+	if (src_ip == NULL)
+		return 0;
+
+	ret = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_SIP, &range_data);
+	if(ret != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_DB_MOD, "TPM_PNC_IPV6_MC_SIP is not created!\n");
+		return 0;
+	}
+
+	for (i = 1; i < range_data.pnc_range_conf.range_size; i++) {
+		if (tpm_db.ipv6_mc_sip[i].valid == 0)
+			continue;
+
+		if (memcmp(tpm_db.ipv6_mc_sip[i].src_ip, src_ip, 16)== 0)
+			return i;
+	}
+
+	/* does not find this src_ip */
+	return 0;
+}
+
+int32_t tpm_db_ipv6_mc_sip_add(uint8_t  *src_ip)
+{
+	uint32_t i;
+	int32_t ret;
+	tpm_db_pnc_range_t range_data;
+
+	/*check param*/
+	if (src_ip == NULL)
+		return 0;
+
+	ret = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_SIP, &range_data);
+	if(ret != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_DB_MOD, "TPM_PNC_IPV6_MC_SIP is not created!\n");
+		return 0;
+	}
+
+	for (i = 1; i < range_data.pnc_range_conf.range_size; i++) {
+		if (tpm_db.ipv6_mc_sip[i].valid == 1)
+			continue;
+
+		memcpy(tpm_db.ipv6_mc_sip[i].src_ip, src_ip, 16);
+		tpm_db.ipv6_mc_sip[i].valid = 1;
+		tpm_db.ipv6_mc_sip[i].reference_num = 1;
+		return i;
+	}
+
+	/* do not have slot for this src_ip */
+	return 0;
+}
+int32_t tpm_db_ipv6_mc_sip_ref_num_inc(uint8_t  src_ip_index)
+{
+	/*check param*/
+	if (src_ip_index >= TPM_MC_IPv6_SIP_NUM_MAX)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (tpm_db.ipv6_mc_sip[src_ip_index].valid == 0)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	tpm_db.ipv6_mc_sip[src_ip_index].reference_num++;
+
+	return TPM_DB_OK;
+}
+int32_t tpm_db_ipv6_mc_sip_ref_num_dec(uint8_t  src_ip_index, uint8_t  *new_ref_num)
+{
+	/*check param*/
+	if (src_ip_index >= TPM_MC_IPv6_SIP_NUM_MAX)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (tpm_db.ipv6_mc_sip[src_ip_index].valid == 0)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (tpm_db.ipv6_mc_sip[src_ip_index].reference_num == 0)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	tpm_db.ipv6_mc_sip[src_ip_index].reference_num--;
+
+	*new_ref_num = tpm_db.ipv6_mc_sip[src_ip_index].reference_num;
+	/* if new ref num is 0, remove this SIP in DB */
+	if (tpm_db.ipv6_mc_sip[src_ip_index].reference_num == 0) {
+		memset(&tpm_db.ipv6_mc_sip[src_ip_index], 0, sizeof(tpm_db.ipv6_mc_sip[src_ip_index]));
+	}
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_ipv6_mc_sip_free_slot_num_get(void)
+{
+	uint32_t i;
+	int32_t ret;
+	tpm_db_pnc_range_t range_data;
+	uint32_t free_slot_num = 0;
+
+	ret = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_SIP, &range_data);
+	if(ret != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_DB_MOD, "TPM_PNC_IPV6_MC_SIP is not created!\n");
+		return 0;
+	}
+
+	for (i = 1; i < range_data.pnc_range_conf.range_size; i++) {
+		if (tpm_db.ipv6_mc_sip[i].valid == 1)
+			continue;
+		free_slot_num++;
+	}
+
+	return free_slot_num;
+}
+
+int32_t tpm_db_ctc_cm_enable_set(tpm_db_ctc_cm_enable_t ctc_cm_enable)
+{
+	tpm_db.ctc_cm_data.enable = ctc_cm_enable;
+	return(TPM_DB_OK);
+}
+
+int32_t tpm_db_ctc_cm_enable_get(tpm_db_ctc_cm_enable_t *ctc_cm_enable)
+{
+	*ctc_cm_enable = tpm_db.ctc_cm_data.enable;
+	return(TPM_DB_OK);
+}
+int32_t tpm_db_ctc_cm_ipv6_parse_win_set(tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win)
+{
+	tpm_db.ctc_cm_data.ipv6_parse_win = ctc_cm_ipv6_parse_win;
+	return(TPM_DB_OK);
+}
+int32_t tpm_db_ctc_cm_ipv6_parse_win_orig_set(tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win)
+{
+	tpm_db.ctc_cm_data.ipv6_parse_win_original = ctc_cm_ipv6_parse_win;
+	return(TPM_DB_OK);
+}
+
+int32_t tpm_db_ctc_cm_ipv6_parse_win_get(tpm_db_ctc_cm_ipv6_parse_win_t *ctc_cm_ipv6_parse_win)
+{
+	*ctc_cm_ipv6_parse_win = tpm_db.ctc_cm_data.ipv6_parse_win;
+	return(TPM_DB_OK);
+}
+int32_t tpm_db_ctc_cm_ipv6_ety_rule_num_set(uint32_t ipv6_ety_rule_num)
+{
+	tpm_db.ctc_cm_data.ipv6_ety_rule_num = ipv6_ety_rule_num;
+	return(TPM_DB_OK);
+}
+
+int32_t tpm_db_ctc_cm_ipv6_ety_rule_num_get(uint32_t *ipv6_ety_rule_num)
+{
+	*ipv6_ety_rule_num = tpm_db.ctc_cm_data.ipv6_ety_rule_num;
+	return(TPM_DB_OK);
+}
+
+int32_t tpm_db_add_ipv4_pre_rule(tpm_src_port_type_t src_port, uint32_t key_pattern, uint32_t *rule_num)
+{
+	uint32_t rule_index, i, j;
+	uint32_t *rule_table = &tpm_db.ctc_cm_data.ipv4_pre_table.rule_index[0];
+
+	if (rule_num == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	rule_index = TPM_DB_CNM_GEN_IPV4_PRE_RULE_INDEX(src_port, key_pattern);
+	if (rule_index == TPM_DB_CNM_INVALID_IPV4_PRE_RULE_INDEX)
+		return TPM_DB_ERR_INV_INPUT;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, "add rule_index(0x%x)\n", rule_index);
+
+	for (i = 0; i < tpm_db.ctc_cm_data.ipv4_pre_table.num_rules; i++) {
+		if (rule_index == rule_table[i]) {
+			TPM_OS_ERROR(TPM_DB_MOD, " ipv4_pre_rule already exists!\n");
+			return TPM_DB_ERR_DB_INCONSISTENCY;
+		} else if (rule_index > rule_table[i]) {
+			break;
+		}
+	}
+
+	for (j = tpm_db.ctc_cm_data.ipv4_pre_table.num_rules; j > i; j--)
+		rule_table[j] = rule_table[j - 1];
+
+	rule_table[j] = rule_index;
+	tpm_db.ctc_cm_data.ipv4_pre_table.num_rules++;
+
+	*rule_num = i;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_del_ipv4_pre_rule(tpm_src_port_type_t src_port, uint32_t key_pattern, uint32_t *rule_num)
+{
+	uint32_t rule_index, i, j;
+	uint32_t *rule_table = &tpm_db.ctc_cm_data.ipv4_pre_table.rule_index[0];
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	rule_index = TPM_DB_CNM_GEN_IPV4_PRE_RULE_INDEX(src_port, key_pattern);
+	if (rule_index == TPM_DB_CNM_INVALID_IPV4_PRE_RULE_INDEX)
+		return TPM_DB_ERR_REC_EXIST;
+
+	TPM_OS_DEBUG(TPM_DB_MOD, "delete rule_index(0x%x)\n", rule_index);
+
+	for (i = 0; i < tpm_db.ctc_cm_data.ipv4_pre_table.num_rules; i++) {
+		if (rule_index == rule_table[i])
+			break;
+	}
+
+	if (i == tpm_db.ctc_cm_data.ipv4_pre_table.num_rules) {
+		TPM_OS_ERROR(TPM_DB_MOD, " ipv4_pre_rule does not exist!\n");
+		return TPM_DB_ERR_REC_NOT_EXIST;
+	}
+
+	for (j = i; j < tpm_db.ctc_cm_data.ipv4_pre_table.num_rules; j++)
+		rule_table[j] = rule_table[j + 1];
+
+	rule_table[j] = TPM_DB_CNM_INVALID_IPV4_PRE_RULE_INDEX;
+	tpm_db.ctc_cm_data.ipv4_pre_table.num_rules--;
+
+	*rule_num = i;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_ipv4_pre_rule_num(uint32_t *num_rules)
+{
+	*num_rules = tpm_db.ctc_cm_data.ipv4_pre_table.num_rules;
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_alloc_ipv4_pre_filter_key(tpm_src_port_type_t src_port, uint32_t *key_idx)
+{
+	uint32_t i;
+
+	/*check param*/
+	if (key_idx == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].num_keys >= TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM)
+		return TPM_DB_ERR_DB_TBL_FULL;
+
+	for (i = 0; i < TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM; i++) {
+		if (tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].key[i].valid == TPM_FALSE)
+			break;
+	}
+
+	if (i >= TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM)
+		return TPM_DB_ERR_DB_INCONSISTENCY;
+
+	*key_idx = i;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_set_ipv4_pre_filter_key(tpm_src_port_type_t src_port,
+				       uint32_t key_idx,
+				       tpm_parse_fields_t parse_rule_bm,
+				       tpm_ipv4_acl_key_t *ipv4_key)
+{
+	tpm_db_cnm_ipv4_pre_filter_key_t *key = NULL;
+
+	/*check param*/
+	if (ipv4_key == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (key_idx >= TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM)
+		return TPM_DB_ERR_REC_INV;
+
+	key = &tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].key[key_idx];
+
+	if (key->valid != TPM_FALSE)
+		return TPM_DB_ERR_REC_EXIST;
+
+	key->valid = TPM_TRUE;
+	key->num_users = 0;
+	key->parse_rule_bm = parse_rule_bm;
+	memcpy(&key->ipv4_key, ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+
+	tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].num_keys++;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_del_ipv4_pre_filter_key(tpm_src_port_type_t src_port, uint32_t key_idx)
+{
+	tpm_db_cnm_ipv4_pre_filter_key_t *key = NULL;
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (key_idx >= TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM)
+		return TPM_DB_ERR_REC_INV;
+
+	key = &tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].key[key_idx];
+
+	if (key->valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	memset(key, 0, sizeof(tpm_db_cnm_ipv4_pre_filter_key_t));
+
+	tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].num_keys--;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_set_gmac_rate_limit(tpm_db_tx_mod_t gmac_i,
+				   uint32_t queue,
+				   uint32_t bucket_size,
+				   uint32_t rate_limit)
+{
+	/*check param*/
+	if (gmac_i >= TPM_MAX_NUM_TX_PORTS)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (queue >= TPM_MAX_NUM_TX_QUEUE)
+		return TPM_DB_ERR_INV_INPUT;
+
+	tpm_db.gmac_tx[gmac_i].tx_queue[queue].bucket_size = bucket_size;
+	tpm_db.gmac_tx[gmac_i].tx_queue[queue].rate_limit = rate_limit;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_gmac_rate_limit(tpm_gmacs_enum_t gmac_i,
+				   uint32_t queue,
+				   uint32_t *bucket_size,
+				   uint32_t *rate_limit)
+{
+	/*check param*/
+	if (gmac_i >= TPM_MAX_NUM_TX_PORTS)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (queue >= TPM_MAX_NUM_TX_QUEUE)
+		return TPM_DB_ERR_INV_INPUT;
+
+	*bucket_size = tpm_db.gmac_tx[gmac_i].tx_queue[queue].bucket_size;
+	*rate_limit = tpm_db.gmac_tx[gmac_i].tx_queue[queue].rate_limit;
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_ipv4_pre_filter_key_num(tpm_src_port_type_t src_port, uint32_t *num_keys)
+{
+	/*check param*/
+	if (num_keys == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	*num_keys = tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].num_keys;
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_ipv4_pre_filter_key(tpm_src_port_type_t src_port, 
+				       uint32_t key_idx, 
+				       tpm_parse_fields_t *parse_rule_bm, 
+				       tpm_ipv4_acl_key_t *ipv4_key)
+{
+	tpm_db_cnm_ipv4_pre_filter_key_t *key = NULL;
+
+	/*check param*/
+	if (parse_rule_bm == NULL || ipv4_key == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (key_idx >= TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM)
+		return TPM_DB_ERR_REC_INV;
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	key = &tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].key[key_idx];
+
+	if (key->valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	*parse_rule_bm = key->parse_rule_bm;
+	memcpy(ipv4_key, &key->ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_find_ipv4_pre_filter_key(tpm_src_port_type_t src_port,
+					tpm_parse_fields_t parse_rule_bm,
+					tpm_ipv4_acl_key_t *ipv4_key,
+					uint32_t *key_idx)
+{
+	tpm_db_cnm_ipv4_pre_filter_key_t *key = &tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].key[0];
+	uint32_t i;
+
+	/*check param*/
+	if (key_idx == NULL || ipv4_key == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	for (i = 0; i < TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM; i++) {
+		if (key[i].valid == TPM_FALSE)
+			continue;
+		if (key[i].parse_rule_bm != parse_rule_bm)
+			continue;
+		if (parse_rule_bm & TPM_IPv4_PARSE_SIP) {
+			if (memcmp(ipv4_key->ipv4_src_ip_add, key[i].ipv4_key.ipv4_src_ip_add, 4 * sizeof(uint8_t)) ||
+				memcmp(ipv4_key->ipv4_src_ip_add_mask, key[i].ipv4_key.ipv4_src_ip_add_mask, 4 * sizeof(uint8_t)))
+				continue;
+		}
+		if (parse_rule_bm & TPM_IPv4_PARSE_DIP) {
+			if (memcmp(ipv4_key->ipv4_dst_ip_add, key[i].ipv4_key.ipv4_dst_ip_add, 4 * sizeof(uint8_t)) ||
+				memcmp(ipv4_key->ipv4_dst_ip_add_mask, key[i].ipv4_key.ipv4_dst_ip_add_mask, 4 * sizeof(uint8_t)))
+				continue;
+		}
+		if (parse_rule_bm & TPM_IPv4_PARSE_DSCP) {
+			if ((ipv4_key->ipv4_dscp & ipv4_key->ipv4_dscp_mask) != (key[i].ipv4_key.ipv4_dscp & key[i].ipv4_key.ipv4_dscp_mask))
+				continue;
+		}
+		if (parse_rule_bm & TPM_IPv4_PARSE_PROTO) {
+			if (ipv4_key->ipv4_proto != key[i].ipv4_key.ipv4_proto)
+				continue;
+		}
+		if (parse_rule_bm & TPM_PARSE_L4_SRC) {
+			if (ipv4_key->l4_src_port != key[i].ipv4_key.l4_src_port)
+				continue;
+		}
+		if (parse_rule_bm & TPM_PARSE_L4_DST) {
+			if (ipv4_key->l4_dst_port != key[i].ipv4_key.l4_dst_port)
+				continue;
+		}
+		*key_idx = i;
+		return TPM_DB_OK;
+	}
+
+	*key_idx = TPM_CNM_INVALID_IPV4_PRE_FILTER_KEY_ID;
+	return TPM_DB_ERR_REC_NOT_EXIST;
+}
+
+int32_t tpm_db_inc_ipv4_pre_filter_key_user_num(tpm_src_port_type_t src_port, uint32_t key_idx)
+{
+	tpm_db_cnm_ipv4_pre_filter_key_t *key = NULL;
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (key_idx >= TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM)
+		return TPM_DB_ERR_REC_INV;
+
+	key = &tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].key[key_idx];
+
+	if (key->valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	key->num_users++;
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_dec_ipv4_pre_filter_key_user_num(tpm_src_port_type_t src_port, uint32_t key_idx)
+{
+	tpm_db_cnm_ipv4_pre_filter_key_t *key = NULL;
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	if (key_idx >= TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM)
+		return TPM_DB_ERR_REC_INV;
+
+	key = &tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].key[key_idx];
+
+	if (key->valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	if (key->num_users > 0)
+		key->num_users--;
+	return TPM_DB_OK;
+}
+
+int32_t tpm_db_get_ipv4_pre_filter_key_user_num(tpm_src_port_type_t src_port, uint32_t key_idx, uint32_t *num_users)
+{
+	tpm_db_cnm_ipv4_pre_filter_key_t *key = NULL;
+
+	/*check param*/
+	if (num_users == NULL)
+		return (TPM_DB_ERR_INV_INPUT);
+
+	if (key_idx >= TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM)
+		return TPM_DB_ERR_REC_INV;
+
+	if(src_port >= TPM_MAX_NUM_UNI_PORTS) {
+		TPM_OS_ERROR(TPM_DB_MOD, "invalid input Src Port(%d)\n", src_port);
+		return TPM_DB_ERR_INV_INPUT;
+	}
+
+	key = &tpm_db.ctc_cm_data.ipv4_pre_filter[src_port].key[key_idx];
+
+	if (key->valid == TPM_FALSE)
+		return TPM_DB_ERR_REC_NOT_EXIST;
+
+	*num_users = key->num_users;
+	return TPM_DB_OK;
+}
+
+/*******************************************************************************
+* tpm_db_init()
+*
+* DESCRIPTION:      Perform DB Initialization. Set all structures to 0, and all valid fields to TPM_DB_INVALID
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_db_init(void)
+{
+	uint32_t i, j;
+
+	/* Erase DB */
+	memset(&tpm_db, 0, sizeof(tpm_db_t));
+
+	/* Set All entries in all structures to invalid */
+
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+		tpm_db.eth_ports[i].valid = TPM_DB_INVALID;
+
+	/* GMAC Connect */
+	for (i = 0; i < TPM_NUM_GMACS; i++)
+		tpm_db.gmac_port_conf[i].valid = TPM_DB_INVALID;
+	tpm_db.num_valid_tcont_llid = 0;
+
+	/* GMAC Func. */
+	for (i = 0; i < TPM_MAX_NUM_GMACS; i++)
+		tpm_db.gmac_func[i] = TPM_GMAC_FUNC_NONE;
+
+	for (i = 0; i < TPM_MAX_NUM_TX_PORTS; i++) {
+		tpm_db.gmac_tx[i].valid = TPM_DB_INVALID;
+		for (j = 0; j < TPM_MAX_NUM_TX_QUEUE; j++)
+			tpm_db.gmac_tx[i].tx_queue[j].valid = TPM_DB_INVALID;
+	}
+
+	/* IGMP */
+	tpm_db.igmp_def.frwd_mode[TPM_SRC_PORT_WAN] = TPM_IGMP_FRWD_MODE_DROP;
+	for (i = TPM_SRC_PORT_UNI_0; i <= TPM_SRC_PORT_UNI_7; i++)
+		 tpm_db.igmp_def.frwd_mode[i] = TPM_IGMP_FRWD_MODE_DROP;
+	tpm_db.igmp_def.cpu_queue = 0;
+
+	tpm_db.igmp_def.mc_lpbk_enable[TPM_IP_VER_4] = TPM_FALSE;
+	tpm_db.igmp_def.mc_lpbk_enable[TPM_IP_VER_6] = TPM_FALSE;
+
+	/* Misc. */
+	tpm_db.init_misc.omci_etype = TPM_DB_INVALID;
+	tpm_db.init_misc.pnc_init_debug_port = TPM_DB_INVALID;
+	tpm_db.init_misc.pon_type = TPM_DB_INVALID;
+	tpm_db.init_misc.ds_mh_set_conf = TPM_DB_INVALID;
+	tpm_db.init_misc.cfg_pnc_parse = TPM_DB_INVALID;
+	tpm_db.init_misc.cpu_loopback = TPM_DB_INVALID;
+	tpm_db.init_misc.tpm_init_succeeded = TPM_DB_INVALID;
+	tpm_db.func_profile.virt_uni_info.enabled = TPM_DB_INVALID;
+	tpm_db.func_profile.virt_uni_info.switch_port = TPM_DB_INVALID;
+	tpm_db.func_profile.virt_uni_info.uni_port = TPM_DB_INVALID;
+
+	/* Ownership */
+	for (i = 0; i < TPM_MAX_API_TYPES; i++)
+		tpm_db.owners[i].valid = TPM_DB_INVALID;
+
+	/* API Ranges */
+	for (i = 0; i < TPM_MAX_NUM_API_SECTIONS; i++) {
+		for (j = 0; j < TPM_NUM_DIRECTIONS; j++)
+			tpm_db_api_section_invalidate(i);
+	}
+
+	/* API_Busy */
+	tpm_db_api_busy_init();
+
+	/* API Entries Area, stripe whole area */
+	tpm_db_api_entries_area_reset();
+
+	/* PNC Tables */
+	for (i = 0; i < TPM_MAX_NUM_RANGES; i++)
+		tpm_db.pnc_range[i].valid = TPM_DB_INVALID;
+
+	for (i = 0; i < TPM_PNC_SIZE; i++)
+		tpm_db.pnc_shadow[i].valid = TPM_DB_INVALID;
+
+	/* Modification Tables */
+	tpm_db_mod2_init();
+
+	/* Vlan Ethertype */
+	for (i = 0; i < TPM_NUM_VLAN_ETYPE_REGS; i++)
+		tpm_db.vlan_etype[i].valid = TPM_DB_INVALID;
+
+	/* Multicast Tables */
+	tpm_db_mc_lpbk_entries_num = 0;
+	memset(tpm_db_mc_stream_table, 0, TPM_MC_MAX_STREAM_NUM * sizeof(tpm_db_mc_stream_entry_t *));
+	memset(tpm_db_mc_mac_table, 0, TPM_MC_MAX_MAC_NUM * sizeof(tpm_db_mc_mac_entry_t *));
+	memset(tpm_db_mc_lpbk_table, 0, TPM_MC_MAX_LPBK_ENTRIES_NUM * sizeof(tpm_db_mc_lpbk_entry_t *));
+	memset(tpm_db_mc_vlan_xits_table, 0, TPM_MC_MAX_MVLAN_XITS_NUM * sizeof(tpm_db_mc_vlan_entry_t *));
+	memset(tpm_db_mc_virt_uni_entry_state_table, 0, TPM_MC_MAX_STREAM_NUM * sizeof(uint8_t));
+	tpm_db_mc_igmp_proxy_sa_mac_valid = 0;
+	memset(tpm_db_mc_igmp_proxy_sa_mac, 0, 6 * sizeof(uint8_t));
+
+	/* IPV6 Flow Tables */
+	tpm_db_init_ipv6_5t_flow_reset();
+
+	/* CTC CnM db */
+	tpm_db_ctc_cm_db_reset();
+
+	/* IPv6 MC SIP db */
+	tpm_db_ipv6_mc_sip_db_reset();
+
+	return (TPM_DB_OK);
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.h
new file mode 100755
index 0000000..0ada80e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_db.h
@@ -0,0 +1,1360 @@
+
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_db.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.4
+*
+*
+*******************************************************************************/
+#ifndef _TPM_DB_H_
+#define _TPM_DB_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+
+typedef enum tpm_db_error {
+	TPM_DB_OK = TPM_OK,
+	TPM_DB_ERR_DB_TBL_FULL,
+	TPM_DB_ERR_DB_TBL_INV,
+	TPM_DB_ERR_INV_INPUT,
+	TPM_DB_ERR_DB_INCONSISTENCY,
+	TPM_DB_ERR_RANGE_EXIST,
+	TPM_DB_ERR_REC_NOT_EXIST,
+	TPM_DB_ERR_REC_EXIST,
+	TPM_DB_ERR_REC_INV,
+	TPM_DB_ERR_REC_STATUS_ERR,
+	TPM_DB_ERR_MEM_ALLOC_FAIL,
+	TPM_DB_ERR_PORT_NUM = 0xFF
+} tpm_db_error_t;
+
+/* Possible roles an Ethernet GMAC or PON MAC can play */
+typedef enum {
+	TPM_GMAC_FUNC_NONE,
+	TPM_GMAC_FUNC_LAN,
+	TPM_GMAC_FUNC_WAN,
+	TPM_GMAC_FUNC_LAN_AND_WAN,
+	TPM_GMAC_FUNC_VIRT_UNI,
+	TPM_GMAC_FUNC_LAN_UNI
+} tpm_db_gmac_func_t;
+
+typedef enum {
+	TPM_MOD_ENTRY_FREE,
+	TPM_MOD_ENTRY_BOOKED,
+	TPM_MOD_ENTRY_OCCUPIED,
+	TPM_MOD_ENTRY_RESERVED,
+	TPM_MOD_ENTRY_SPLIT_MOD,
+	TPM_MOD_ENTRY_STATUS_MAX,
+} tpm_mod_entry_status_t;
+
+typedef enum {
+	TPM_PNC_RNG_LAST_INIT_DEF,	/* Last entry in PnC range is regular entry */
+	TPM_PNC_RNG_LAST_INIT_DROP,	/* Last entry in PnC range is hardcoded to DROP */
+	TPM_PNC_RNG_LAST_INIT_TRAP	/* Last entry in PnC range is hardcoded to TRAP to CPU */
+} tpm_db_pnc_rng_last_ent_t;
+
+typedef tpm_init_sched_t tpm_db_sched_t;
+typedef tpm_init_port_admin_t tpm_db_port_admin_t;
+typedef tpm_init_port_speed_t tpm_db_port_speed_t;
+typedef tpm_init_port_duplex_t tpm_db_port_duplex_t;
+typedef tpm_init_chip_conn_t tpm_db_chip_conn_t;
+typedef tpm_init_int_conn_t tpm_db_int_conn_t;
+typedef tpm_init_gmac_conn_t tpm_db_gmac_conn_t;
+typedef tpm_init_gmac_bufs_t tpm_db_gmac_bufs_t;
+typedef tpm_init_gmac_rx_t tpm_db_gmac_rx_t;
+typedef tpm_init_gmac_rxq_t tpm_db_gmac_rxq_t;
+typedef tpm_init_txq_owner_t tpm_db_txq_owner_t;
+typedef tpm_init_pon_type_t tpm_db_pon_type_t;
+typedef tpm_init_tx_mod_t tpm_db_tx_mod_t;
+typedef tpm_init_mh_src_t tpm_db_mh_src_t;
+typedef tpm_init_mtu_setting_enable_t tpm_db_mtu_setting_enable_t;
+typedef tpm_init_pppoe_add_enable_t tpm_db_pppoe_add_enable_t;
+typedef tpm_init_ttl_illegal_action_t tpm_db_ttl_illegal_action_t;
+typedef tpm_init_fc_params_t tpm_db_fc_params_t;
+typedef tpm_init_tcp_flag_check_t tpm_db_tcp_flag_check_t;
+typedef tpm_init_ety_dsa_enable_t tpm_db_ety_dsa_enable_t;
+typedef tpm_init_split_mod_enable_t tpm_db_split_mod_enable_t;
+typedef tpm_init_ctc_cm_enable_t    tpm_db_ctc_cm_enable_t;
+typedef tpm_init_split_mod_mode_t    tpm_db_split_mod_mode_t;
+typedef tpm_ctc_cm_ipv6_parse_win_t tpm_db_ctc_cm_ipv6_parse_win_t;
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+
+#define TPM_DB_TOTAL_API_SIZE               (512)
+
+/* Defines the amount of memory margin (in units of tpm_db_api_entry_t),
+	between each pair of API Range Entries Table. */
+#define TPM_DB_API_SECTION_MARGIN_SIZE      (3)
+
+#define TPM_DB_API_NOT_BUSY		    (-1)
+
+/* Define total   Margin memory allocated for the margin between each pair
+	of API Range tables, + before the first API Range Entries table.
+	(in units of tpm_db_api_entry_t) */
+#define TPM_DB_API_SECTION_MARGIN_ALLOC     \
+	(TPM_DB_API_SECTION_MARGIN_SIZE * (TPM_MAX_NUM_API_SECTIONS * TPM_NUM_DIRECTIONS + 1))
+
+/* Total table size is tot_num_api_entries + tot_margin */
+#define TPM_DB_API_ENTRIES_TBL_SIZE         (TPM_DB_TOTAL_API_SIZE + TPM_DB_API_SECTION_MARGIN_ALLOC)
+#define TPM_DB_VALID                        (1)
+#define TPM_DB_INVALID                      (0xBEEF)
+#define TPM_DB_INVALID_OWNER                (0xFF)
+
+#define TPM_MOD2_NULL_ENT_IDX               (0x1000)
+
+#define TPM_MOD2_MAIN_CHAIN_SIZE            (19)
+#define TPM_MOD2_SUBR_MAC_CHAIN_SIZE        (3)
+#define TPM_MOD2_SUBR_IP_CHAIN_SIZE         (2)
+
+#define TPM_MOD2_JUMP_AREA_SIZE             (203)
+#define TPM_MOD2_MAIN_AREA_SIZE             (TPM_MOD2_MAIN_CHAIN_SIZE * TPM_MOD2_JUMP_AREA_SIZE)
+#define TPM_MOD2_SUBR_AREA_SIZE             (0)
+#define TPM_MOD2_APPL_SUBR_AREA_SIZE        (35)
+
+#define TPM_MC_VID_NUM_MAX                  (1 << TPM_NUM_MC_VID_BITS)
+#define TPM_MC_VLAN_MAX_PNC_RULE_NUM        (16)
+
+#define TPM_MC_IPv6_SIP_NUM_MAX             (8)
+
+#define TPM_MOD2_MAX_MH_CHAIN_SIZE                   (1)
+#define TPM_MOD2_MAX_MAC_CHAIN_SIZE                  (3)
+#define TPM_MOD2_MAX_VLAN_CHAIN_SIZE                 (2)
+#define TPM_MOD2_MAX_PPPOE_CHAIN_SIZE                (2)
+#define TPM_MOD2_MAX_IPV6_PPPOE_CHAIN_SIZE           (5)
+#define TPM_MOD2_MAX_L2_TWO_TAG_CHAIN_SIZE           (4)
+#define TPM_MOD2_MAX_L2_ONE_TAG_CHAIN_SIZE           (3)
+#define TPM_MOD2_MAX_IPV4_NAPT_W_PPPOE_CHAIN_SIZE    (14)	/* Single Vlan Modification */
+#define TPM_MOD2_MAX_IPV4_NAPT_WO_PPPOE_CHAIN_SIZE   (13)
+#define TPM_MOD2_MAX_IPV4_MC_W_MH_CHAIN_SIZE         (8)	/* PPPoE + Proxy (Single Vlan Modification) */
+#define TPM_MOD2_MAX_IPV4_MC_WO_MH_CHAIN_SIZE        (7)
+#define TPM_MOD2_MAX_ROUTE_W_PPPOE_CHAIN_SIZE   (7)
+#define TPM_MOD2_MAX_ROUTE_WO_PPPOE_CHAIN_SIZE  (6)
+#define TPM_MOD2_MAX_IPV6_MC_W_MH_CHAIN_SIZE         (8)
+#define TPM_MOD2_MAX_IPV6_MC_WO_MH_CHAIN_SIZE        (7)
+
+#define TPM_MOD2_TOTAL_PMT_SIZE                (4096 - 1/* zero entry is reserved */)
+#define TPM_MOD2_MAX_JUMP_ENTRIES_NUM          (1024 - 1/* zero entry is reserved */)
+
+#define TPM_DB_IPV6_MAX_KEY_NUM               (128)
+
+#define TPM_DB_IPV6_MAX_SUBFLOW_NUM           ((1 << TPM_NUM_IPV6_SUBFLOW_BITS) - 1)
+#define TPM_DB_IPV6_MAX_5T_FLOW_NUM           (128)
+
+#define TPM_DB_INVALID_IPV6_KEY_ID            (0xFFFF)
+#define TPM_DB_INVALID_IPV6_FLOW_ID           (0xFFFF)
+
+#define TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK  (TPM_IPv6_PARSE_NH | TPM_PARSE_L4_SRC | TPM_PARSE_L4_DST)
+#define TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK (TPM_IPv6_PARSE_SIP | TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK)
+
+#define TPM_DB_SPLIT_MOD_P_BIT_MAX (7)
+#define TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX (8)
+#define TPM_DB_SPLIT_MOD_P_BIT_NO_SET (0)
+#define TPM_DB_SPLIT_MOD_NUM_VLANS_MAX (18)
+#define TPM_DB_SPLIT_MOD_INIT_VLANS_NUM (2)
+
+#define TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM    (TPM_CNM_IPV4_PRE_FILTER_KEY_MAX)
+#define TPM_DB_CNM_MAX_IPV4_PRE_FILTER_RULE_NUM   (TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_PORT * TPM_MAX_NUM_UNI_PORTS)
+
+#define TPM_DB_CNM_INVALID_IPV4_PRE_RULE_INDEX    (0x0)
+
+#define TPM_DB_CNM_GEN_IPV4_PRE_RULE_INDEX(p, k)  \
+			((((k) & TPM_DB_CNM_IPV4_PRE_RULE_INDEX_KEY_MASK) << TPM_DB_CNM_IPV4_PRE_RULE_INDEX_KEY_OFFSET) | \
+			(((p) & TPM_DB_CNM_IPV4_PRE_RULE_INDEX_PORT_MASK) << TPM_DB_CNM_IPV4_PRE_RULE_INDEX_PORT_OFFSET))
+
+#define TPM_DB_CNM_IPV4_PRE_RULE_INDEX_PORT_OFFSET    (0)
+#define TPM_DB_CNM_IPV4_PRE_RULE_INDEX_PORT_LEN       (16)
+#define TPM_DB_CNM_IPV4_PRE_RULE_INDEX_PORT_MASK      ((1 << TPM_DB_CNM_IPV4_PRE_RULE_INDEX_PORT_LEN) - 1)
+
+#define TPM_DB_CNM_IPV4_PRE_RULE_INDEX_KEY_OFFSET     (16)
+#define TPM_DB_CNM_IPV4_PRE_RULE_INDEX_KEY_LEN        (16)
+#define TPM_DB_CNM_IPV4_PRE_RULE_INDEX_KEY_MASK       ((1 << TPM_DB_CNM_IPV4_PRE_RULE_INDEX_KEY_LEN) - 1)
+
+/*************************************************************/
+/*               STRUCTURES                                  */
+/*************************************************************/
+
+/*****************************/
+/* API DB related structures */
+/*****************************/
+
+/* Structure represents the connection between an API call and the modification table entry (if exists)
+ * that implemented the modification request in that API call */
+typedef struct {
+	uint32_t mod_cmd_ind;	/* Index to the modification command table related to this API entry */
+	tpm_gmacs_enum_t mod_cmd_mac; /* Only a single "dest MAC" can be set.If none are set, mod_cmd_ind is not used. */
+} tpm_db_mod_conn_t;
+
+/* Structure represents the connection between an API call and a PnC entry that implemented
+ * or partially implemented that API call */
+typedef struct {
+	uint32_t pnc_range;	/* The pnc_range where the API call was implemented */
+	uint32_t pnc_index;	/* The index in the PnC range where the API call is implemented */
+} tpm_db_pnc_conn_entry_t;
+
+/* Structure represents the connection between an API call and all the PnC entries that implemented the API call */
+typedef struct {
+	uint32_t num_pnc_ranges;	/* Number of PNC entries associated with this API entry,
+					 * equals to '1' unless the API call spans over multiple PnC ranges,
+					 * e.g. IPv6 DIP+SIP */
+	/* Upto TPM_MAX_API_MULTI_RANGES PnC entries may be needed to implement an API call */
+	tpm_db_pnc_conn_entry_t pnc_conn_tbl[TPM_MAX_API_MULTI_RANGES];
+} tpm_db_pnc_conn_t;
+
+/* Structure represents an API call, including all param data and the link to Pnc and modif_table implementation */
+typedef struct {
+	uint32_t valid;		/* invalid - 0xBEEF */
+	uint32_t bi_dir;	/* Some API entries may be bi-directional */
+	uint32_t rule_num;	/* Current rule number in acl/table */
+	uint32_t rule_idx;	/* Original rule number in acl/table, when entry was created */
+	tpm_rule_entry_t api_rule_data;	/* tpm_rule_entry_t is defined in tpm_types.h */
+	tpm_db_mod_conn_t mod_tbl_conn;	/* API connection to the modification table */
+	tpm_db_pnc_conn_t pnc_tbl_conn;	/* API connection to the PnC */
+} tpm_db_api_entry_t;
+
+/* Structure represents an API acl/table */
+typedef struct {
+	uint32_t valid;
+	/* The primary pnc_range_id, for those api_sections that a uniquely linked onc_range. */
+	tpm_pnc_ranges_t prim_pnc_range;
+	uint32_t table_size;	/* (cont.) e.g. - All API's except for IPV6, IPV6 MC */
+	uint32_t table_start;	/* Start index in the api_ent_mem_area */
+	uint32_t num_valid_entries;
+	int32_t last_valid_entry;	/* Equals to rule with highest rulenum in the api_table */
+	int32_t last_valid_index;	/* Highest Occupied Index in the api_table */
+} tpm_db_api_section_t;
+
+typedef struct {
+	uint32_t table_size;	/* (cont.) e.g. - All API's except for IPV6, IPV6 MC */
+	uint32_t table_start;	/* Start index in the api_ent_mem_area */
+} tpm_db_api_check_t;
+
+/*****************************/
+/* PNC  related structures   */
+/*****************************/
+
+typedef struct {
+	tpm_range_type_t range_type;	/* Pnc Range type, ACL or Table */
+	/* PnC range LookupId. If range spans over multiple lookupIds
+		(e.g. IPV6 DIP/DIP), this is the first one. */
+	uint32_t base_lu_id;
+	/* Determines the minimum reset_level that will perform a reset to this PnC range */
+	tpm_reset_level_enum_t min_reset_level;
+	uint32_t num_luids;	/* Number of LookupIds this PnC range spans over, usually '1'.
+					* Multiple lu_ids, when PnC range must support large number of sessions in the TCAM */
+	tpm_pnc_ranges_t range_id;
+	uint32_t range_start;	/* Range's Physical PnC start entry */
+	uint32_t range_end;	/* Range's Physical PnC end entry */
+	uint32_t range_size;	/* Range's Physical PnC size */
+	uint32_t cntr_grp;	/* Range's counter group number, from 0 to 3 */
+	/* Range's least used mask flag, 1: mask least used functions,
+		0:enbale least used function of this PnC range */
+	uint32_t lu_mask;
+	uint32_t api_start;	/* First available entry for api's. (Relative to range_start) */
+	uint32_t api_end;	/* Last available entry for api's. (Relative to range_start) */
+	/* How to init last entry of the PNC range (drop, trap to CPU, or no special treatment). */
+	tpm_db_pnc_rng_last_ent_t init_last_entry;
+	/* For pnc_ranges with multiple lu_id, init_last_entry must be repeated for each lu_id. */
+	/* GMAC's that are included in TCAM in last_entry (drop/trap) treatment. */
+	tpm_gmac_bm_t last_ent_portid;
+} tpm_db_pnc_range_conf_t;
+
+/* Structure represents a PnC range */
+typedef struct {
+	uint32_t free_entries;	/* Number of unused PnC entries in Range */
+	uint32_t num_resets;	/* Number of resets the range has been through */
+} tpm_db_pnc_range_oper_t;
+
+/* Structure represents a PnC range */
+typedef struct {
+	uint32_t valid;	/* invalid - 0xBEEF */
+	tpm_db_pnc_range_conf_t pnc_range_conf;
+	tpm_db_pnc_range_oper_t pnc_range_oper;
+} tpm_db_pnc_range_t;
+
+/* Structure represents DB info for a PnC entry */
+typedef struct {
+	uint32_t valid;		/* invalid - 0xBEEF */
+	tpm_pnc_all_t pnc_data;	/* Shadow of the PnC configuration of this entry */
+} tpm_db_pnc_shadow_t;
+
+typedef struct {
+	uint32_t valid;			/* invalid - 0xBEEF */
+	uint32_t tpid_ether_type;	/* Modification data associated with this entry */
+} tpm_db_etype_sel_t;
+
+typedef struct {
+	uint32_t tpm_reserved;	/* Reserved modification entries for TPM rules */
+} tpm_db_mod_config_t;
+
+typedef struct {
+	tpm_mod2_entry_t entry;	/* Modification table entry */
+	uint16_t pnc_num_ref;	/* Number of references from Pnc entries to this modification rule */
+	uint16_t owner;		/* Owner of modification entry - TPM rule or CPU application */
+	uint32_t valid;
+} tpm_db_mod2_shadow_t;
+
+typedef struct {
+	uint8_t mac[TPM_SA_LEN];
+	uint16_t mod_idx;	/* Start index of the commands chain in the modification table */
+	uint16_t mod_num_ref;	/* Number of references from modification table to this MAC entry */
+	uint32_t valid;
+
+} tpm_mod2_mac_translation_t;
+
+typedef struct {
+	uint8_t ip[TPM_IPV4_SIP_LEN];
+	uint16_t mod_idx;	/* Start index of the commands chain in the modification table */
+	uint16_t mod_num_ref;	/* Number of references from modification table to this MAC entry */
+	uint32_t valid;
+
+} tpm_mod2_ip_translation_t;
+
+/*typedef uint16_t (*parse_jump_index_func_t)(tpm_mod2_entry_t *pattern); */
+
+typedef struct {
+	tpm_mod_entry_status_t status;
+	tpm_mod2_entry_t pattern;
+} tpm_mod2_jump_pmt_info_t;
+
+typedef struct {
+	tpm_mod_entry_status_t status;
+	tpm_chain_type_t chain_type;
+	tpm_mod2_entry_t pattern;
+	uint16_t chain_id;
+} tpm_mod2_chain_pmt_info_t;
+
+typedef struct {
+	tpm_mod_entry_status_t status;
+	uint16_t base_entry;
+	uint16_t entry_num;
+	uint16_t user_num;
+} tpm_mod2_chain_info_t;
+
+typedef struct {
+	uint16_t base_entry;
+	uint16_t total_num;
+	uint16_t split_num;
+	uint16_t next_free[TPM_MAX_NUM_GMACS];
+	uint16_t next_split[TPM_MAX_NUM_GMACS];
+	uint16_t split_pbit_num;
+} tpm_mod2_jump_cfg_t;
+
+typedef struct {
+	uint16_t base_entry;
+	uint16_t subr_chain;
+	uint16_t total_num;
+	uint16_t max_size;
+	uint16_t next_free[TPM_MAX_NUM_GMACS];
+} tpm_mod2_chain_cfg_t;
+
+/*****************************/
+/* API Ownership Structures  */
+/*****************************/
+/*
+TBD
+Structures
+API Group enum
+*/
+/*****************************/
+/* Initialization Structures */
+/*****************************/
+
+typedef struct {
+	uint32_t omci_etype;
+	uint32_t tpm_init_succeeded;
+
+	uint32_t oam_channel_configured;/* omci or oam channel configured */
+	uint16_t omci_gemport;
+	uint32_t oam_cpu_rx_q;		/* omci cpu rx q or oam cpu rx q */
+	uint32_t oam_cpu_tx_q;		/* omci cpu tx q or oam cpu tx q */
+	uint32_t oam_cpu_tx_port;	/* omci tcount or oam llid */
+
+	uint32_t pnc_init_debug_port;
+	uint32_t oam_loopback_channel_configured;
+	tpm_db_pon_type_t pon_type;
+	tpm_gmacs_enum_t backup_wan;
+
+	tpm_db_mh_src_t ds_mh_set_conf;
+
+	tpm_init_cfg_pnc_parse_t cfg_pnc_parse;
+
+	tpm_init_cpu_loopback_t cpu_loopback;
+
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	tpm_init_double_tag_t dbl_tag;
+
+#if 0
+	uint16_t vlan1_tpid;
+	uint16_t vlan2_tpid;
+#endif
+	tpm_init_tpid_opt_t tag_tpid;
+	tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable;
+
+} tpm_db_misc_t;
+
+/* Structure holds the IGMP/MLD settings */
+typedef struct {
+	uint32_t frwd_mode[TPM_MAX_NUM_PORTS];
+	uint32_t cpu_queue;
+	tpm_mc_filter_mode_t filter_mode;
+	/*tpm_mc_igmp_mode_t      igmp_mode; */
+	uint8_t per_uni_vlan_xlat;
+	uint8_t mc_pppoe_enable;
+	uint8_t mc_hwf_queue;
+	uint8_t mc_cpu_queue;
+	uint8_t mc_lpbk_enable[TPM_IP_VER_MAX];
+} tpm_db_igmp_t;
+
+/* Structure holds the physical connections of all external Ethernet ports */
+typedef struct {
+	uint32_t valid;
+	tpm_src_port_type_t port_src;		/* Port number according to Device port numbering scheme 	*/
+	tpm_db_chip_conn_t chip_connect;	/* Connection to physical output lines on SoC 			*/
+	tpm_db_int_conn_t int_connect;		/* Internal Ethernet device port is connected to 		*/
+	uint32_t switch_port;			/* Port of Internal_Switch, the port is connected to 		*/
+} tpm_db_eth_port_conf_t;
+
+/* Structure holds the physical connections of the KW2 SoC */
+typedef struct {
+	uint32_t		valid;
+	tpm_init_gmac_conn_t	conn;
+	tpm_src_port_type_t	port_src;
+} tpm_db_gmac_conn_conf_t;
+
+typedef struct {
+	uint32_t valid;
+	tpm_db_sched_t sched_method;
+	tpm_db_txq_owner_t queue_owner;
+	uint32_t owner_queue_num;
+	uint32_t queue_size;
+	uint32_t queue_weight;
+	uint32_t bucket_size;
+	uint32_t rate_limit;
+} tpm_db_gmac_txq_t;
+
+/*Structure defines the details of a Packet Processor Tx component  */
+typedef struct {
+	uint32_t valid;						/* Defines if the Tx component is used */
+	tpm_db_gmac_txq_t tx_queue[TPM_MAX_NUM_TX_QUEUE];	/* Config. of each of the 8 Tx queue of this Tx component */
+} tpm_db_gmac_tx_t;
+
+#if 0
+/* Structure contains user ownership of an API Group */
+typedef struct {
+	uint32_t valid;
+	uint32_t api_owner_id;
+	tpm_api_type_t api_type;
+} tpm_db_api_group_t;
+#endif
+
+/* */
+typedef struct {
+	uint32_t valid;
+	uint32_t owner_id;
+} tpm_db_owners_t;
+
+/* Structure for defining MH_select to uni_vector and to amber_port_vector */
+typedef struct {
+	uint32_t uni_vector;
+	uint16_t amber_port_vector;
+	uint32_t pnc_vector;
+} tpm_db_tx_ds_mh_sel_mapping_t;
+
+typedef struct {
+	tpm_init_mtu_setting_enable_t mtu_enable;
+	uint32_t ipv4_mtu_us;
+	uint32_t ipv4_pppoe_mtu_us;
+	uint32_t ipv6_mtu_us;
+	uint32_t ipv6_pppoe_mtu_us;
+	uint32_t ipv4_mtu_ds;
+	uint32_t ipv6_mtu_ds;
+	uint32_t mru;
+} tpm_db_mtu_t;
+
+typedef struct {
+	uint32_t mc_vlan;
+	uint32_t valid;
+	uint32_t pnc_index_num;
+	uint32_t pnc_index[TPM_MC_VLAN_MAX_PNC_RULE_NUM];
+} tpm_db_mc_ai_bits_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t pnc_index_num;
+	uint32_t reference_num;
+	uint8_t  src_ip[16];
+} tpm_db_ipv6_mc_sip_t;
+
+typedef struct {
+	tpm_mc_vid_port_cfg_t mc_vid_port_vids[TPM_MAX_NUM_UNI_PORTS];
+	uint32_t valid;
+	uint32_t mc_vid;
+} tpm_mc_vid_cfg_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t user_num;
+	tpm_ipv6_gen_acl_key_t gen_key;
+} tpm_db_ipv6_gen_key_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t user_num;
+	tpm_ipv6_addr_key_t dip_key;
+} tpm_db_ipv6_dip_key_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t user_num;
+	uint32_t protocol;
+	tpm_l4_ports_key_t l4_key;
+} tpm_db_ipv6_l4_key_t;
+
+typedef struct {
+	tpm_db_ipv6_gen_key_t gen_key[TPM_DB_IPV6_MAX_KEY_NUM];
+	tpm_db_ipv6_dip_key_t dip_key[TPM_DB_IPV6_MAX_KEY_NUM];
+	tpm_db_ipv6_l4_key_t l4_key[TPM_DB_IPV6_MAX_KEY_NUM];
+} tpm_db_ipv6_key_shadow_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t user_num;
+	tpm_parse_fields_t parse_bm;
+	uint32_t l4_key;
+} tpm_db_ipv6_l4_flow_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t user_num;
+	tpm_parse_fields_t parse_bm;
+	uint32_t gen_key;
+	uint32_t l4_key;
+} tpm_db_ipv6_gen_flow_t;
+
+typedef struct {
+	tpm_db_ipv6_l4_flow_t l4_flow[TPM_DB_IPV6_MAX_SUBFLOW_NUM];
+	tpm_db_ipv6_gen_flow_t gen_flow[TPM_DB_IPV6_MAX_SUBFLOW_NUM];
+} tpm_db_ipv6_subflow_shadow_t;
+
+typedef struct {
+	uint32_t valid;
+	tpm_dir_t src_dir;
+	tpm_parse_fields_t parse_bm;
+	uint32_t is_pppoe;
+	uint32_t gen_key;
+	uint32_t dip_key;
+	uint32_t l4_key;
+} tpm_db_ipv6_5t_flow_shadow_t;
+
+typedef struct {
+	uint32_t igmp_mode;
+	uint8_t mc_stream_pppoe;
+	uint8_t valid;
+	uint16_t vid;
+	uint8_t group_addr[16];
+	uint8_t src_addr[16];
+	uint8_t ignore_src_addr;
+	uint32_t dest_port_bm;
+	uint32_t u4_entry;
+} tpm_db_ipv6_mc_stream_entry_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t user_num;
+	tpm_vlan_oper_t   vlan_op;
+	uint32_t vlan_1;
+	uint32_t vlan_2;
+	uint32_t tpid_1;
+	uint32_t tpid_2;
+} tpm_db_split_mod_vlan_t;
+
+typedef struct {
+	tpm_db_split_mod_vlan_t split_mod_vlan[TPM_DB_SPLIT_MOD_NUM_VLANS_MAX];
+} tpm_db_split_mod_gmac_vlan_t;
+
+typedef struct {
+	tpm_db_split_mod_enable_t   split_mod_enable;
+	tpm_db_split_mod_mode_t   split_mod_mode;
+	uint32_t num_p_bits;
+	uint32_t num_vlans;
+	uint8_t  p_bits[8];
+	tpm_db_split_mod_gmac_vlan_t     gmac_vlan_conf[TPM_MAX_NUM_GMACS];
+} tpm_db_split_mod_t;
+
+typedef enum {
+	TPM_CTC_CM_L2,
+	TPM_CTC_CM_IPv4,
+	TPM_CTC_CM_COMBO
+} tpm_ctc_cm_rule_type_t;
+
+typedef struct {
+	uint32_t                    valid;
+	uint32_t                    cm_main_rule_index;
+	uint32_t                    ipv4_sub_pattern_key;
+	tpm_ctc_cm_rule_type_t      rule_type;
+	tpm_parse_fields_t          l2_parse_rule_bm;
+	tpm_parse_fields_t          ipv4_parse_rule_bm;
+	tpm_parse_fields_t          ipv6_parse_rule_bm;
+	tpm_l2_acl_key_t            l2_key;
+	tpm_ipv4_acl_key_t          ipv4_key;
+	tpm_ipv6_acl_key_t          ipv6_key;
+	tpm_pkt_frwd_t              pkt_frwd;
+	tpm_pkt_action_t            pkt_act;
+	uint32_t                    pbits;
+} tpm_db_ctc_cm_rule_entry_t;
+
+typedef struct {
+	uint32_t num_rules;
+	uint32_t rule_index[TPM_DB_CNM_MAX_IPV4_PRE_FILTER_RULE_NUM];
+} tpm_db_cnm_ipv4_pre_table_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t num_users;
+    tpm_parse_fields_t parse_rule_bm;
+    tpm_ipv4_acl_key_t ipv4_key;
+} tpm_db_cnm_ipv4_pre_filter_key_t;
+
+typedef struct {
+	uint32_t num_keys;
+	tpm_db_cnm_ipv4_pre_filter_key_t key[TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM];
+} tpm_db_cnm_ipv4_pre_filter_t;
+
+typedef struct {
+	tpm_db_ctc_cm_enable_t enable;
+	tpm_db_ctc_cm_ipv6_parse_win_t ipv6_parse_win;
+	/* init value from XML */
+	tpm_db_ctc_cm_ipv6_parse_win_t ipv6_parse_win_original;
+	uint32_t ipv6_ety_rule_num;
+	tpm_db_cnm_ipv4_pre_table_t ipv4_pre_table;
+	tpm_db_cnm_ipv4_pre_filter_t ipv4_pre_filter[TPM_MAX_NUM_UNI_PORTS];
+	/* U0~U7 and vir_uni, 8 prec */
+	tpm_db_ctc_cm_rule_entry_t cm_rule[TPM_MAX_NUM_UNI_PORTS][TPM_MAX_NUM_CTC_PRECEDENCE];
+} tpm_db_ctc_cm_t;
+
+typedef struct {
+	bool switch_init;
+	bool gmac1_loopback_en;
+	bool cpu_wan_loopback_en;
+	tpm_db_ety_dsa_enable_t  ety_dsa_enable;
+	tpm_init_virt_uni_t virt_uni_info;
+
+} tpm_db_func_profile_t;
+
+typedef struct {
+	/* Physical chip config */
+	tpm_eth_complex_profile_t eth_cmplx_profile;
+	tpm_src_port_type_t max_uni_port_nr;
+	tpm_db_eth_port_conf_t eth_ports[TPM_MAX_NUM_ETH_PORTS];
+	uint32_t num_valid_tcont_llid;
+	tpm_db_gmac_tx_t gmac_tx[TPM_MAX_NUM_TX_PORTS];
+	tpm_init_fc_params_t	port_fc_conf;
+	tpm_db_gmac_rx_t gmac_rx[TPM_MAX_NUM_GMACS];
+
+	/* GMAC Functional Info */
+	tpm_db_gmac_func_t gmac_func[TPM_MAX_NUM_GMACS];
+
+	tpm_db_gmac_conn_conf_t gmac_port_conf[TPM_NUM_GMACS];
+
+	/* GMAC Marvell Header Info */
+	uint32_t gmac_mh_en[TPM_MAX_NUM_GMACS];
+
+	/* GMAC Buffer Mngmt Pools buffers Info */
+	tpm_db_gmac_bufs_t gmac_bp_bufs[TPM_MAX_NUM_GMACS];
+
+	/* IGMP */
+	tpm_db_igmp_t igmp_def;
+
+	/* Misc. */
+	tpm_db_misc_t init_misc;
+
+	/* Ownership */
+	tpm_db_owners_t owners[TPM_MAX_API_TYPES];
+#if 0
+	tpm_db_api_group_t api_groups[TPM_MAX_API_TYPES];
+#endif
+
+	/* API Ranges and Entries */
+	tpm_db_api_section_t api_section[TPM_MAX_NUM_API_SECTIONS];
+
+	/* Memory place holder array to be used for the api_section api_entry tables */
+	tpm_db_api_entry_t api_ent_mem_area[TPM_DB_API_ENTRIES_TBL_SIZE];
+
+	/* PNC Ranges */
+	tpm_db_pnc_range_t pnc_range[TPM_MAX_NUM_RANGES];
+
+	/* PNC Shadow Table */
+	tpm_db_pnc_shadow_t pnc_shadow[TPM_PNC_SIZE];
+
+	/* EtherType registers */
+	tpm_db_etype_sel_t vlan_etype[TPM_NUM_VLAN_ETYPE_REGS];
+
+	/* MH register selection per UNI and SWITCH port */
+	tpm_db_tx_ds_mh_sel_mapping_t tpm_mh_port_vector_tbl[TPM_TX_MAX_MH_REGS];
+
+	/* mtu setting */
+	tpm_db_mtu_t tpm_mtu_cfg;
+	tpm_db_pppoe_add_enable_t tpm_pppoe_add_enable;
+	uint32_t num_vlan_tags;
+	uint32_t cpu_rx_queue;
+	tpm_db_ttl_illegal_action_t ttl_illegal_action;
+	tpm_db_tcp_flag_check_t tcp_flag_check;
+	tpm_db_mc_ai_bits_t mc_ai_bits_table[TPM_MC_VID_NUM_MAX];
+
+	/* MC IPv6 SIP data */
+	tpm_db_ipv6_mc_sip_t ipv6_mc_sip[TPM_MC_IPv6_SIP_NUM_MAX];
+
+	/* MC VID setting */
+	tpm_mc_vid_cfg_t mc_vid_port_cfg[TPM_MC_VID_NUM_MAX];
+
+	tpm_init_pnc_last_init_t catch_all_pkt_action;
+	uint32_t                 switch_dev_num;
+
+	tpm_db_ipv6_key_shadow_t ipv6_key_shadow;
+	tpm_db_ipv6_subflow_shadow_t ipv6_subflow_shadow[TPM_NUM_DIRECTIONS];
+	tpm_db_ipv6_5t_flow_shadow_t ipv6_5t_flow_shadow[TPM_DB_IPV6_MAX_5T_FLOW_NUM];
+
+	tpm_db_ipv6_mc_stream_entry_t  ipv6_mc_stream[TPM_MC_MAX_STREAM_NUM];
+	tpm_db_split_mod_t   split_mod_conf;
+
+	
+	/* Array indicates which API's are currently called for synch purposes.
+	   When API is not in called, invalid=-1 When API is called, it will set it's rule_num */
+	int32_t tpm_busy_apis[TPM_MAX_API_TYPES][TPM_MAX_PARALLEL_API_CALLS];
+	tpm_db_ctc_cm_t    ctc_cm_data;
+
+	/* func profile, based on chip type and board profile */
+	tpm_db_func_profile_t    func_profile;
+
+} tpm_db_t;
+
+typedef struct {
+	uint32_t igmp_mode;
+	uint8_t mc_stream_pppoe;
+	uint8_t src_valid;
+	uint16_t vid;
+	uint8_t group_addr[4];
+	uint8_t src_addr[4];
+	uint32_t dest_port_bm;
+	uint32_t u4_entry;
+} tpm_db_mc_stream_entry_t;
+
+typedef struct {
+	uint8_t mac_addr[6];
+	uint8_t user_num[TPM_MAX_NUM_UNI_PORTS];
+} tpm_db_mc_mac_entry_t;
+
+typedef struct {
+	uint32_t rule_index;
+	uint32_t mod_cmd;
+} tpm_db_mc_lpbk_entry_t;
+
+#define TPM_DB_MAX_TRANSITION_NUM    (TPM_MAX_NUM_UNI_PORTS)
+
+typedef struct {
+	uint8_t valid;
+	uint16_t in_vid;
+	uint16_t out_vid;
+	tpm_db_mc_lpbk_entry_t *lpbk_entry;
+} tpm_db_mc_vid_transit_t;
+
+typedef struct {
+	uint32_t ip_ver;
+	uint16_t mvlan;
+	uint16_t xits_num;
+	tpm_db_mc_vid_transit_t xits[TPM_DB_MAX_TRANSITION_NUM];
+} tpm_db_mc_vlan_entry_t;
+
+/************/
+/*  APIs    */
+/************/
+
+/* Init */
+
+int32_t tpm_db_init(void);
+
+/* Ethernet Port Config */
+bool tpm_db_eth_port_valid(tpm_src_port_type_t src_port_num);
+int32_t tpm_db_eth_port_conf_get(tpm_src_port_type_t src_port_num,
+				  tpm_db_chip_conn_t *chip_con,
+				  tpm_db_int_conn_t *int_con,
+				  uint32_t *switch_port);
+int32_t tpm_db_eth_port_switch_port_get(uint32_t ext_port);
+int32_t tpm_db_get_valid_uni_ports_num(uint32_t *num_ports);
+int32_t tpm_db_phy_convert_port_index(int32_t switch_port);
+int32_t tpm_db_trg_port_switch_port_get(tpm_trg_port_type_t ext_port);
+int32_t tpm_db_eth_port_conf_set(tpm_init_eth_port_conf_t *eth_port_conf);
+int32_t tpm_db_gmac_conn_conf_set(tpm_init_gmac_conn_conf_t *gmac_port_conf, uint32_t arr_size);
+
+/* GMAC Config */
+int32_t tpm_db_gmac_tcont_llid_set(uint32_t num_tcont_llid);
+int32_t tpm_db_gmac_conn_get(tpm_gmacs_enum_t gmac, tpm_db_gmac_conn_t *gmac_con);
+int32_t tpm_db_gmac_mh_en_conf_set(tpm_gmacs_enum_t gmac, uint32_t mh_en);
+int32_t tpm_db_gmac_mh_en_conf_get(tpm_gmacs_enum_t gmac, uint32_t *mh_en);
+int32_t tpm_db_gmac_bm_bufs_conf_set(tpm_gmacs_enum_t gmac, uint32_t large_pkt_buffers,
+					uint32_t small_pkt_buffers);
+int32_t tpm_db_gmac_bm_bufs_conf_get(tpm_gmacs_enum_t gmac, uint32_t *valid, uint32_t *large_pkt_buffers,
+					uint32_t *small_pkt_buffers);
+int32_t tpm_db_num_tcont_llid_get(uint32_t *num_tcont_llid);
+
+int32_t tpm_db_gmac_func_get(tpm_gmacs_enum_t gmac, tpm_db_gmac_func_t *gfunc);
+int32_t tpm_db_gmac_func_set(tpm_gmacs_enum_t gmac, tpm_db_gmac_func_t gfunc);
+
+/* TX Entities and queues Config */
+int32_t tpm_db_gmac_tx_q_conf_set(tpm_db_tx_mod_t tx_mod,
+					uint32_t queue_num,
+					tpm_db_sched_t sched_method,
+					tpm_db_txq_owner_t queue_owner,
+					uint32_t owner_queue_num, uint32_t queue_size, uint32_t queue_weight);
+
+int32_t tpm_db_gmac_tx_q_conf_get(tpm_db_tx_mod_t tx_mod,
+					uint32_t queue_num,
+					uint32_t *valid,
+					tpm_db_sched_t *sched_method,
+					tpm_db_txq_owner_t *queue_owner,
+					uint32_t *owner_queue_num, uint32_t *queue_size, uint32_t *queue_weight);
+
+int32_t tpm_db_gmac_tx_val_set(tpm_db_tx_mod_t tx_mod);
+uint32_t tpm_db_gmac_tx_val_get(tpm_db_tx_mod_t tx_mod);
+uint32_t tpm_db_gmac_lpk_queue_get(tpm_gmacs_enum_t *gmac, uint32_t *queue_idx);
+
+/* RX queues Config */
+int32_t tpm_db_gmac_rx_val_set(tpm_gmacs_enum_t gmac);
+uint32_t tpm_db_gmac_rx_val_get(tpm_gmacs_enum_t gmac);
+
+int32_t tpm_db_gmac_rx_q_conf_set(tpm_gmacs_enum_t gmac, uint32_t queue_num, uint32_t queue_size);
+
+int32_t tpm_db_gmac_rx_q_conf_get(tpm_gmacs_enum_t gmac,
+					uint32_t queue_num, uint32_t *valid, uint32_t *queue_size);
+
+/* Get params by Internal Port (WAN, UNI#0, etc). */
+int32_t tpm_db_intport_int_con_get(tpm_src_port_type_t int_port_num, tpm_db_int_conn_t *int_con,
+					uint32_t *switch_port);
+
+/* Ownership */
+int32_t tpm_db_owner_set(uint32_t owner_id);
+/* TODO - tpm_db_owner_del(uint32_t owner_id); */
+int32_t tpm_db_owner_get_next(int32_t cur_ind, int32_t *next_ind, uint32_t *owner);
+
+#if 0
+	int32_t tpm_db_apig_set(uint32_t owner_id, tpm_api_type_t api_type);
+/* TODO - tpm_db_apig_get(...) */
+	int32_t tpm_db_apig_get_next(int32_t cur_ind, int32_t *next_ind, uint32_t *owner, tpm_api_type_t *api_type);
+#endif
+
+/* IGMP */
+/*int32_t tpm_db_igmp_set(uint32_t igmp_snoop, uint32_t igmp_cpu_queue);*/
+/*int32_t tpm_db_igmp_get(uint32_t *igmp_snoop, uint32_t *igmp_cpu_queue); */
+int32_t tpm_db_igmp_set_port_frwd_mode(uint32_t port, uint32_t mode);
+int32_t tpm_db_igmp_get_port_frwd_mode(uint32_t port, uint32_t *mode);
+int32_t tpm_db_igmp_set_cpu_queue(uint32_t queue);
+int32_t tpm_db_igmp_get_cpu_queue(uint32_t *queue);
+
+/* MISC */
+int32_t tpm_db_omci_type_set(uint32_t omci_etype);
+int32_t tpm_db_omci_type_get(uint32_t *omci_etype);
+int32_t tpm_db_omci_channel_get(uint32_t *valid, uint16_t *gemport, uint32_t *cpu_rx_q, uint32_t *cpu_tx_q,
+				uint32_t *tcont_id);
+int32_t tpm_db_omci_channel_set(uint16_t gemport, uint32_t cpu_rx_q, uint32_t cpu_tx_q, uint32_t tcont_id);
+int32_t tpm_db_omci_channel_remove(void);
+
+int32_t tpm_db_oam_channel_get(uint32_t *valid, uint32_t *cpu_rx_q, uint32_t *cpu_tx_q, uint32_t *llid);
+int32_t tpm_db_oam_channel_set(uint32_t cpu_rx_q, uint32_t cpu_tx_q, uint32_t llid);
+int32_t tpm_db_oam_channel_remove(void);
+
+int32_t tpm_db_oam_loopback_state_get(uint32_t *loopback);
+int32_t tpm_db_oam_loopback_channel_set(void);
+int32_t tpm_db_oam_loopback_channel_remove(void);
+
+int32_t tpm_db_pon_type_set(tpm_db_pon_type_t pon_type);
+int32_t tpm_db_pon_type_get(tpm_db_pon_type_t *pon_type);
+
+int32_t tpm_db_ds_mh_set_conf_set(tpm_db_mh_src_t ds_mh_set_conf);
+int32_t tpm_db_ds_mh_get_conf_set(tpm_db_mh_src_t *ds_mh_set_conf);
+
+int32_t tpm_db_backup_wan_set(tpm_gmacs_enum_t backup_wan);
+int32_t tpm_db_backup_wan_get(tpm_gmacs_enum_t *backup_wan);
+tpm_gmacs_enum_t tpm_db_active_wan_get(void);
+
+#if 0				/*Keep to be added in future version */
+	int32_t tpm_db_pnc_init_deb_port_set(uint32_t pnc_init_debug_port);
+	int32_t tpm_db_pnc_init_deb_port_get(uint32_t *pnc_init_debug_port);
+#endif
+int32_t tpm_db_init_done_set(void);
+int32_t tpm_db_init_done_get(void);
+
+int32_t tpm_db_cfg_pnc_parse_set(tpm_init_cfg_pnc_parse_t cfg_pnc_parse);
+int32_t tpm_db_cfg_pnc_parse_get(tpm_init_cfg_pnc_parse_t *cfg_pnc_parse_val);
+
+int32_t tpm_db_cpu_loopback_set(tpm_init_cpu_loopback_t cpu_loopback);
+int32_t tpm_db_cpu_loopback_get(tpm_init_cpu_loopback_t *cpu_loopback_val);
+
+int32_t tpm_db_double_tag_support_set(tpm_init_double_tag_t dbl_tag);
+int32_t tpm_db_double_tag_support_get(tpm_init_double_tag_t *dbl_tag);
+
+#if 0
+int32_t tpm_db_default_tag_tpid_set(uint16_t vlan1_tpid, uint16_t vlan2_tpid);
+int32_t tpm_db_default_tag_tpid_get(uint16_t *vlan1_tpid, uint16_t *vlan2_tpid);
+#endif
+int32_t tpm_db_default_tag_tpid_set(tpm_init_tpid_opt_t *tag_tpid);
+int32_t tpm_db_default_tag_tpid_get(tpm_init_tpid_opt_t *tag_tpid);
+
+int32_t tpm_db_virt_info_set(tpm_init_virt_uni_t virt_uni_info);
+int32_t tpm_db_virt_info_get(tpm_init_virt_uni_t *virt_uni_info);
+
+int32_t tpm_db_ipv6_5t_enable_set(tpm_init_ipv6_5t_enable_t ipv6_5t_enable);
+int32_t tpm_db_ipv6_5t_enable_get(tpm_init_ipv6_5t_enable_t *ipv6_5t_enable);
+
+int32_t tpm_db_port_vector_tbl_info_get(uint32_t reg_num, uint32_t *uni_vector, uint16_t *amber_port_vector,
+					uint32_t *pnc_vector);
+int32_t tpm_db_port_vector_tbl_info_set(uint32_t reg_num, uint32_t un_vector, uint16_t amber_port_vector,
+					uint32_t pnc_vector);
+int32_t tpm_db_port_vector_tbl_info_search(tpm_trg_port_type_t  trg_port, uint32_t *uni_vector,
+					    uint16_t *amber_port_vector, uint32_t *pnc_vector);
+/* API Section */
+int32_t tpm_db_api_section_init(tpm_api_sections_t api_section, tpm_pnc_ranges_t prim_pnc_range,
+				uint32_t api_rng_size);
+int32_t tpm_db_api_section_invalidate(tpm_api_sections_t api_section);
+
+int32_t tpm_db_api_section_get_from_api_type(tpm_api_type_t api_type, tpm_api_sections_t *api_section);
+int32_t tpm_db_api_type_get_from_api_section(tpm_api_sections_t api_section, tpm_api_type_t *api_type);
+int32_t tpm_db_api_section_reset(tpm_api_sections_t api_section);
+int32_t tpm_db_api_section_get(tpm_api_sections_t api_section, uint32_t *api_rng_size,
+				uint32_t *num_valid_entries, tpm_pnc_ranges_t * prim_pnc_range,
+				int32_t *last_valid, uint32_t *tbl_start);
+int32_t tpm_db_api_section_lastentry_get(tpm_api_sections_t api_section, int32_t *last_valid_entry);
+int32_t tpm_db_api_section_main_pnc_get(tpm_api_sections_t api_section, tpm_pnc_ranges_t *prim_pnc_range);
+int32_t tpm_db_api_section_num_entries_get(tpm_api_sections_t api_section, uint32_t *num_entries);
+int32_t tpm_db_api_section_val_get_next(int32_t cur_api_section, int32_t *next_section,
+					uint32_t *api_rng_size, uint32_t *num_valid_entries,
+					int32_t *last_valid_entry, uint32_t * tbl_start);
+int32_t tpm_db_api_section_ent_tbl_get(tpm_api_sections_t api_sec,
+					tpm_db_api_entry_t *api_ent_mem_area,
+					uint32_t index);
+
+
+int32_t tpm_db_api_section_entry_add(tpm_api_sections_t api_section, int32_t new_last_valid);
+int32_t tpm_db_api_entries_area_reset(void);
+
+/* API Entry */
+int32_t tpm_db_api_entry_set(tpm_api_sections_t api_section,
+				uint32_t rule_num, uint32_t bi_dir, tpm_rule_entry_t *api_data,
+				tpm_db_mod_conn_t *mod_con, tpm_db_pnc_conn_t *pnc_con, uint32_t *rule_idx);
+
+/*TODO: int32_t tpm_db_api_entry_del(tpm_api_sections_t api_section, uint32_t dir, uint32_t rule_num); */
+int32_t tpm_db_api_entry_rulenum_inc(tpm_api_sections_t api_section, uint32_t rule_inc_start,
+					uint32_t rule_inc_end);
+int32_t tpm_db_api_entry_rulenum_dec(tpm_api_sections_t api_section, uint32_t rule_dec_start,
+					uint32_t rule_dec_end);
+int32_t tpm_db_api_entry_get(tpm_api_sections_t api_section, uint32_t rule_num, uint32_t *rule_idx,
+				uint32_t *bi_dir, tpm_rule_entry_t *api_data, tpm_db_mod_conn_t *mod_con,
+				tpm_db_pnc_conn_t *pnc_con);
+
+int32_t tpm_db_api_tcam_num_get(tpm_api_sections_t api_section, uint32_t rule_idx, uint32_t *tcam_num);
+int32_t tpm_db_api_rulenum_get(tpm_api_sections_t api_section, uint32_t rule_idx, uint32_t *rule_num);
+int32_t tpm_db_api_rulenum_get_from_l2_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
+						tpm_l2_acl_key_t *l2_key, uint32_t *rule_num);
+int32_t tpm_db_api_rulenum_get_from_l3_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
+						tpm_l3_type_key_t *l3_key, uint32_t *rule_num);
+int32_t tpm_db_api_rulenum_get_from_ipv4_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
+						tpm_ipv4_acl_key_t *ipv4_key, uint32_t *rule_num);
+int32_t tpm_db_api_rulenum_get_from_ipv6_key(tpm_api_sections_t api_section, tpm_parse_fields_t parse_rule_bm,
+						tpm_ipv6_acl_key_t *ipv6_key, uint32_t *rule_num);
+
+int32_t tpm_db_api_entry_val_get_next(tpm_api_sections_t api_section, int32_t cur_rule, int32_t *next_rule,
+					uint32_t *rule_idx, uint32_t *bi_dir, tpm_rule_entry_t *api_data,
+					tpm_db_mod_conn_t *mod_con, tpm_db_pnc_conn_t *pnc_con);
+int32_t tpm_db_api_entry_invalidate(tpm_api_sections_t api_section, uint32_t rule_num);
+int32_t tpm_db_api_entry_ind_get(tpm_api_sections_t api_section, uint32_t rule_num, int32_t *index);
+int32_t tpm_db_api_tcam_rule_idx_get(tpm_api_sections_t api_section, uint32_t tcam_num, uint32_t *rule_idx);
+
+int32_t tpm_db_pnc_conn_inc(tpm_api_sections_t api_section, uint32_t rule_inc_start, uint32_t rule_inc_end);
+int32_t tpm_db_pnc_conn_dec(tpm_api_sections_t api_section, uint32_t rule_dec_start, uint32_t rule_dec_end);
+int32_t tpm_db_pnc_get_lu_conf(tpm_pnc_ranges_t range_id, tpm_api_lu_conf_t *lu_conf);
+
+int32_t tpm_db_api_specific_pnc_inc(tpm_api_sections_t api_section,
+					tpm_pnc_ranges_t range_id, uint32_t rule_inc_start, uint32_t rule_inc_end);
+int32_t tpm_db_api_specific_pnc_dec(tpm_api_sections_t api_section,
+					tpm_pnc_ranges_t range_id, uint32_t rule_inc_start, uint32_t rule_inc_end);
+/* PnC Range */
+/*Set */
+int32_t tpm_db_pnc_rng_create(tpm_db_pnc_range_conf_t *pnc_range_conf);
+int32_t tpm_db_pnc_rng_delete(tpm_pnc_ranges_t pnc_range);
+int32_t tpm_db_pnc_rng_reset(tpm_pnc_ranges_t pnc_range);
+int32_t tpm_db_pnc_rng_free_ent_inc(tpm_pnc_ranges_t pnc_range);
+int32_t tpm_db_pnc_rng_free_ent_dec(tpm_pnc_ranges_t pnc_range);
+int32_t tpm_db_pnc_rng_api_start_inc(tpm_pnc_ranges_t pnc_range);
+int32_t tpm_db_pnc_rng_api_end_dec(tpm_pnc_ranges_t pnc_range);
+/*Get */
+int32_t tpm_db_pnc_rng_get(tpm_pnc_ranges_t pnc_range, tpm_db_pnc_range_t *range_data);
+int32_t tpm_db_pnc_rng_get_range_start_end(tpm_pnc_ranges_t pnc_range, uint32_t *range_start,
+						uint32_t *range_end);
+
+/*int32_t tpm_db_pnc_rng_tbl_val_get_next(int32_t cur_ind, int32_t *next_ind, tpm_db_pnc_range_t *range_data); */
+int32_t tpm_db_pnc_rng_val_get_next(tpm_pnc_ranges_t cur_range, tpm_pnc_ranges_t *next_range,
+					tpm_db_pnc_range_t *range_data);
+int32_t tpm_db_pnc_rng_conf_get(tpm_pnc_ranges_t range_id, tpm_db_pnc_range_conf_t *range_conf);
+int32_t tpm_db_pnc_rng_oper_get(tpm_pnc_ranges_t range_id, tpm_db_pnc_range_oper_t *range_oper);
+int32_t tpm_db_pnc_rng_free_ent_get(tpm_pnc_ranges_t range_id, uint32_t *free_entries);
+
+/* PnC Shadow */
+int32_t tpm_db_pnc_shdw_ent_set(uint32_t pnc_entry, tpm_pnc_all_t *pnc_data);
+int32_t tpm_db_pnc_shdw_ent_inv(uint32_t pnc_entry);
+int32_t tpm_db_pnc_shdw_ent_ins(uint32_t pnc_start_entry, uint32_t pnc_stop_entry);
+int32_t tpm_db_pnc_shdw_ent_del(uint32_t pnc_start_entry, uint32_t pnc_stop_entry);
+int32_t tpm_db_pnc_shdw_ent_get(uint32_t pnc_entry, uint32_t *valid, tpm_pnc_all_t *pnc_data);
+
+/* Mod2 Shadow */
+int32_t tpm_db_mod2_set_jump_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id, tpm_mod2_entry_t *pattern);
+int32_t tpm_db_mod2_activate_jump_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id);
+int32_t tpm_db_mod2_get_jump_entry_pattern_data(tpm_gmacs_enum_t gmac_port, uint16_t entry_id,
+						tpm_mod2_entry_t *pattern);
+int32_t tpm_db_mod2_del_jump_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id);
+int32_t tpm_db_mod2_get_chain_entry_num(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+					uint16_t chain_id, uint16_t *entry_num);
+int32_t tpm_db_mod2_get_chain_entry_pattern_data(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+							uint16_t chain_id, uint16_t pattern_id,
+							tpm_mod2_entry_t *pattern);
+int32_t tpm_db_mod2_del_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id);
+int32_t  tpm_db_mod2_flush_jump_area(tpm_gmacs_enum_t gmac_port, uint16_t entry_id,
+				     uint8_t updt_next_free, uint8_t on_failure);
+int32_t  tpm_db_mod2_flush_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id,
+				       uint8_t updt_next_free, uint8_t on_failure);
+int32_t tpm_db_mod2_set_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type, uint16_t chain_id,
+					uint16_t entry_num, tpm_mod2_entry_t *pattern);
+int32_t tpm_db_mod2_activate_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+						uint16_t chain_id);
+int32_t tpm_db_mod2_activate_chain_pmt_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+						uint16_t chain_id);
+int32_t tpm_db_mod2_if_chain_pmt_entries_exist(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+						uint16_t chain_id, uint8_t *exist);
+uint16_t tpm_db_mod2_get_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+					uint16_t entry_num, tpm_mod2_entry_t *pattern);
+uint16_t tpm_db_mod2_get_next_free_chain_entry(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type);
+uint16_t tpm_db_mod2_convert_chain_to_pmt_entry(tpm_chain_type_t chain_type, uint16_t chain_id);
+int32_t tpm_db_mod2_get_chain_id_by_pmt_entry(tpm_gmacs_enum_t gmac_port, uint16_t entry_id,
+						tpm_chain_type_t *chain_type, uint16_t *chain_id);
+uint16_t tpm_db_mod2_get_next_free_jump_entry(tpm_gmacs_enum_t gmac_port);
+
+uint16_t tpm_db_mod2_get_next_split_mod_free_jump_entry(tpm_gmacs_enum_t gmac_port, tpm_pkt_mod_t *mod_data);
+//void tpm_db_mod2_update_split_mod_next_free_jump_entry(tpm_gmacs_enum_t gmac_port);
+int32_t tpm_db_mod2_split_mod_insert_vlan(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data);
+int32_t tpm_db_mod2_split_mod_get_vlan_index(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data, uint32_t *index);
+int32_t tpm_db_mod2_split_mod_increase_vlan_user_num(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data);
+int32_t tpm_db_mod2_split_mod_decrease_vlan_user_num(tpm_gmacs_enum_t port, 
+													 uint32_t       vlan_index,
+													 uint32_t      *user_num);
+void tpm_db_mod2_set_multicast_mh_state(uint8_t enable);
+void tpm_db_mod2_set_pppoe_add_mod_state(uint8_t enable);
+void tpm_db_mod2_set_double_tag_state(uint8_t enable);
+void tpm_db_mod2_set_udp_checksum_use_init_bm_state(uint8_t enable);
+void tpm_db_mod2_set_udp_checksum_state(uint8_t enable);
+void tpm_db_mod2_set_chain_num(tpm_chain_type_t chain_type, uint16_t chain_num);
+uint16_t tpm_db_mod2_get_chain_max_size(tpm_chain_type_t chain_type);
+uint8_t tpm_db_mod2_get_multicast_mh_state(void);
+uint8_t tpm_db_mod2_get_pppoe_add_mod_state(void);
+uint8_t tpm_db_mod2_get_double_tag_state(void);
+uint8_t tpm_db_mod2_get_udp_checksum_init_bm_state(void);
+uint8_t tpm_db_mod2_get_udp_checksum_state(void);
+int32_t tpm_db_mod2_setup(void);
+int32_t tpm_db_mod2_inv_mac_entries(tpm_gmacs_enum_t gmac_port);
+
+void tpm_db_mod2_show_jump_pmt_entries(tpm_gmacs_enum_t gmac_port);
+void tpm_db_mod2_show_jump_cfg_data(void);
+void tpm_db_mod2_show_chain_pmt_entries(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type);
+void tpm_db_mod2_show_chain_info_entries(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+						uint16_t chain_id);
+void tpm_db_mod2_show_chain_cfg_data(tpm_chain_type_t chain_type);
+void tpm_db_mod2_show_all_chain(tpm_gmacs_enum_t gmac_port);
+
+/* Vlan Ethertype Shadow */
+int32_t tpm_db_mod_etype_sel_get(uint32_t tpid, uint32_t *etype_sel);
+int32_t tpm_db_mod_etype_sel_free_get(uint32_t *etype_sel);
+int32_t tpm_db_mod_etype_sel_set(uint32_t tpid, uint32_t etype_sel);
+
+/* Multicast Shadow */
+void tpm_db_set_mc_filter_mode(uint32_t mode);
+void tpm_db_set_mc_pppoe_enable(uint32_t enable);
+void tpm_db_split_mod_set_enable(tpm_db_split_mod_enable_t enable);
+tpm_db_split_mod_enable_t tpm_db_split_mod_get_enable(void);
+void tpm_db_split_mod_set_num_vlans(uint32_t num_vlans);
+uint32_t tpm_db_split_mod_get_num_vlans(void);
+void tpm_db_split_mod_set_mode(tpm_db_split_mod_mode_t mode);
+tpm_db_split_mod_mode_t tpm_db_split_mod_get_mode(void);
+void tpm_db_split_mod_set_num_p_bits(uint32_t num_p_bits, uint8_t  p_bits[8]);
+uint32_t tpm_db_split_mod_get_num_p_bits(void);
+int32_t tpm_db_split_mod_get_p_bits_by_index(uint8_t  index, uint8_t  *p_bits);
+int32_t tpm_db_split_mod_get_index_by_p_bits(uint8_t  p_bits, uint32_t *index);
+void tpm_db_set_mc_per_uni_vlan_xlate(uint32_t enable);
+void tpm_db_set_mc_hwf_queue(uint8_t hwf_queue);
+void tpm_db_set_mc_cpu_queue(uint8_t cpu_queue);
+void tpm_db_set_mc_igmp_proxy_sa_mac(uint8_t *sa_mac);
+uint32_t tpm_db_get_mc_filter_mode(void);
+uint8_t tpm_db_get_mc_pppoe_enable(void);
+uint8_t tpm_db_get_mc_per_uni_vlan_xlate(void);
+uint8_t tpm_db_get_mc_hwf_queue(void);
+uint8_t tpm_db_get_mc_cpu_queue(void);
+void tpm_db_get_mc_igmp_proxy_sa_mac(uint8_t *sa_mac, uint8_t *valid);
+int32_t tpm_db_set_mc_stream_entry(uint32_t stream_num, tpm_db_mc_stream_entry_t *mc_stream);
+int32_t tpm_db_get_mc_stream_entry(uint32_t stream_num, tpm_db_mc_stream_entry_t *mc_stream);
+void tpm_db_reset_mc_stream_entry(uint32_t stream_num);
+int32_t tpm_db_set_ipv6_mc_stream_entry(uint32_t stream_num, tpm_db_ipv6_mc_stream_entry_t *mc_stream);
+int32_t tpm_db_get_ipv6_mc_stream_entry(uint32_t stream_num, tpm_db_ipv6_mc_stream_entry_t *mc_stream);
+void tpm_db_reset_ipv6_mc_stream_entry(uint32_t stream_num);
+int32_t tpm_db_increase_mc_mac_port_user_num(uint8_t *mac_addr, uint32_t uni_port);
+int32_t tpm_db_decrease_mc_mac_port_user_num(uint8_t *mac_addr, uint32_t uni_port);
+uint8_t tpm_db_get_mc_mac_port_user_num(uint8_t *mac_addr, uint32_t uni_port);
+void tpm_db_reset_mc_mac_entry(uint8_t *mac_addr);
+uint32_t tpm_db_mc_lpbk_entries_num_get(void);
+int32_t tpm_db_mc_lpbk_entry_set(uint32_t ip_ver, uint16_t mvlan, uint16_t in_vid, uint16_t out_vid, uint32_t rule_num,
+					uint32_t mod_entry);
+int32_t tpm_db_mc_vlan_xits_num_get(uint32_t ip_ver, uint16_t mvlan, uint32_t *xits_num);
+int32_t tpm_db_mc_vlan_xit_entry_get(uint32_t ip_ver, uint16_t mvlan, uint32_t xit_id, uint32_t *rule_index,
+					uint32_t *mod_entry);
+int32_t tpm_db_mc_lpbk_rule_num_get(uint32_t rule_index, uint32_t *rule_num);
+int32_t tpm_db_mc_lpbk_entry_invalidate(uint32_t rule_num);
+int32_t tpm_db_mc_alloc_virt_uni_entry(uint32_t *entry_id);
+int32_t tpm_db_mc_free_virt_uni_entry(uint32_t entry_id);
+int32_t tpm_db_mc_vlan_set_ai_bit_pnc_index(uint32_t mc_vlan, uint32_t l2_pnc_rule_index);
+int32_t tpm_db_mc_vlan_get_ai_bit_by_vid(uint32_t mc_vlan, uint32_t *ai_bit);
+int32_t tpm_db_mc_vlan_reset_ai_bit(uint32_t l2_pnc_rule_index);
+int32_t tpm_db_mc_vlan_get_pnc_index_free_slot(uint32_t mc_vlan, uint32_t rule_num);
+int32_t tpm_db_mc_vlan_get_ai_bit(uint32_t mc_vlan, uint32_t *ai_bit);
+int32_t tpm_db_mc_vlan_reset_mc_vlan(uint32_t mc_vlan);
+uint32_t tpm_db_remove_mc_vid_cfg(uint32_t mc_vid);
+bool tpm_db_mc_vid_exist(uint32_t mc_vid);
+int32_t tpm_db_set_mc_vid_cfg(uint32_t mc_vid, tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config);
+int32_t tpm_db_get_mc_vid_cfg(uint32_t mc_vid, tpm_mc_vid_port_cfg_t **mc_vid_uniports_config);
+void     tpm_db_mc_rule_reset(void);
+void     tpm_db_mc_cfg_reset(void);
+void tpm_db_set_mc_lpbk_enable(tpm_ip_ver_t ver, uint8_t enable);
+void tpm_db_get_mc_lpbk_enable(tpm_ip_ver_t ver, uint8_t *enable);
+
+/* MTU shadow */
+int32_t tpm_db_mtu_set_ipv4_mtu_us(uint32_t mtu);
+int32_t tpm_db_mtu_get_ipv4_mtu_us(uint32_t *mtu);
+int32_t tpm_db_mtu_set_ipv4_pppoe_mtu_us(uint32_t mtu);
+int32_t tpm_db_mtu_get_ipv4_pppoe_mtu_us(uint32_t *mtu);
+int32_t tpm_db_mtu_set_ipv6_mtu_us(uint32_t mtu);
+int32_t tpm_db_mtu_get_ipv6_mtu_us(uint32_t *mtu);
+int32_t tpm_db_mtu_set_ipv6_pppoe_mtu_us(uint32_t mtu);
+int32_t tpm_db_mtu_get_ipv6_pppoe_mtu_us(uint32_t *mtu);
+int32_t tpm_db_mtu_set_ipv4_mtu_ds(uint32_t mtu);
+int32_t tpm_db_mtu_get_ipv4_mtu_ds(uint32_t *mtu);
+int32_t tpm_db_mtu_set_ipv6_mtu_ds(uint32_t mtu);
+int32_t tpm_db_mtu_get_ipv6_mtu_ds(uint32_t *mtu);
+int32_t tpm_db_get_pppoe_add_enable(tpm_db_pppoe_add_enable_t *enable);
+int32_t tpm_db_set_pppoe_add_enable(tpm_db_pppoe_add_enable_t enable);
+int32_t tpm_db_get_num_vlan_tags(uint32_t *number);
+int32_t tpm_db_set_num_vlan_tags(uint32_t number);
+
+int32_t tpm_db_get_mtu_enable(tpm_db_mtu_setting_enable_t *enable);
+int32_t tpm_db_set_mtu_enable(tpm_db_mtu_setting_enable_t enable);
+
+int32_t tpm_db_set_cpu_rx_queue(uint32_t cpu_rx_queue);
+int32_t tpm_db_get_cpu_rx_queue(uint32_t *cpu_rx_queue);
+int32_t tpm_db_set_ttl_illegal_action(uint32_t ttl_illegal_action);
+int32_t tpm_db_get_ttl_illegal_action(uint32_t *ttl_illegal_action);
+int32_t tpm_db_set_tcp_flag_check(uint32_t tcp_flag_check);
+int32_t tpm_db_get_tcp_flag_check(uint32_t *tcp_flag_check);
+int32_t tpm_db_set_mru(uint32_t mru);
+int32_t tpm_db_get_mru(uint32_t *mru);
+int32_t tpm_db_set_catch_all_pkt_action(tpm_init_pnc_last_init_t catch_all_pkt_action);
+int32_t tpm_db_get_catch_all_pkt_action(tpm_init_pnc_last_init_t *catch_all_pkt_action);
+int32_t tpm_db_set_switch_dev_num(int32_t switch_dev_num);
+int32_t tpm_db_get_switch_dev_num(int32_t *switch_dev_num);
+int32_t tpm_db_set_ety_dsa_enable(tpm_db_ety_dsa_enable_t ety_dsa_enable);
+int32_t tpm_db_get_ety_dsa_enable(tpm_db_ety_dsa_enable_t *ety_dsa_enable);
+
+/* IPV6 5T flow shadow */
+uint32_t tpm_db_find_matched_ipv6_l4_subflow(uint32_t src_dir, uint32_t parse_bm, uint32_t protocol, tpm_l4_ports_key_t *l4_key);
+uint32_t tpm_db_get_ipv6_l4_subflow_user_num(uint32_t src_dir, uint32_t flow_id);
+uint32_t tpm_db_get_free_ipv6_l4_subflow(uint32_t src_dir);
+int32_t  tpm_db_set_ipv6_l4_subflow(uint32_t src_dir, uint32_t flow_id, uint32_t parse_bm, uint32_t protocol, tpm_l4_ports_key_t *l4_key);
+int32_t  tpm_db_get_ipv6_l4_subflow(uint32_t src_dir, uint32_t flow_id, uint32_t *parse_bm, uint32_t *protocol, tpm_l4_ports_key_t *l4_key);
+int32_t  tpm_db_del_ipv6_l4_subflow(uint32_t src_dir, uint32_t flow_id);
+
+uint32_t tpm_db_find_matched_ipv6_gen_subflow(uint32_t src_dir, uint32_t parse_bm, uint32_t protocol, tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key);
+uint32_t tpm_db_get_ipv6_gen_subflow_user_num(uint32_t src_dir, uint32_t flow_id);
+uint32_t tpm_db_get_free_ipv6_gen_subflow(uint32_t src_dir);
+int32_t  tpm_db_set_ipv6_gen_subflow(uint32_t src_dir, uint32_t flow_id, uint32_t parse_bm, uint32_t protocol, tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key);
+int32_t  tpm_db_get_ipv6_gen_subflow(uint32_t src_dir, uint32_t flow_id, uint32_t *parse_bm, uint32_t *protocol, tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key);
+int32_t  tpm_db_del_ipv6_gen_subflow(uint32_t src_dir, uint32_t flow_id);
+
+uint32_t tpm_db_find_matched_ipv6_5t_flow(uint32_t src_dir, uint32_t parse_bm, uint32_t is_pppoe, uint32_t protocol, tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key, tpm_ipv6_addr_key_t *dip_key);
+int32_t  tpm_db_set_ipv6_5t_flow(uint32_t src_dir, uint32_t parse_bm, uint32_t is_pppoe, uint32_t protocol, tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key, tpm_ipv6_addr_key_t *dip_key);
+int32_t  tpm_db_get_ipv6_5t_flow(uint32_t flow_id, uint32_t *src_dir, uint32_t *parse_bm, uint32_t *is_pppoe, uint32_t *protocol, tpm_l4_ports_key_t *l4_key, tpm_ipv6_gen_acl_key_t *gen_key, tpm_ipv6_addr_key_t *dip_key);
+int32_t  tpm_db_del_ipv6_5t_flow(uint32_t flow_id);
+int32_t  tpm_db_init_ipv6_5t_flow_reset(void);
+
+int32_t tpm_db_ctc_cm_rule_set(tpm_src_port_type_t src_port,
+			       uint32_t precedence,
+			       tpm_parse_fields_t l2_parse_rule_bm,
+			       tpm_parse_fields_t ipv4_parse_rule_bm,
+			       tpm_parse_fields_t ipv6_parse_rule_bm,
+			       tpm_l2_acl_key_t *l2_key,
+			       tpm_ipv4_acl_key_t *ipv4_key,
+			       tpm_ipv6_acl_key_t *ipv6_key,
+			       tpm_pkt_frwd_t *pkt_frwd,
+			       tpm_pkt_action_t pkt_act,
+			       uint32_t pbits,
+			       uint32_t ipv4_sub_pattern_index,
+			       uint32_t rule_index);
+int32_t tpm_db_ctc_cm_rule_delete(tpm_src_port_type_t src_port, uint32_t precedence);
+int32_t tpm_db_ctc_cm_rule_get(tpm_src_port_type_t src_port, uint32_t precedence, tpm_db_ctc_cm_rule_entry_t *cm_rule);
+int32_t tpm_db_ctc_cm_get_num_rules(tpm_src_port_type_t src_port);
+int32_t tpm_db_ctc_cm_get_ipv6_num_rules(void);
+
+int32_t tpm_db_ctc_cm_db_reset(void);
+int32_t tpm_db_ipv6_mc_sip_db_reset(void);
+int32_t tpm_db_ipv6_mc_sip_index_get(uint8_t  *src_ip);
+int32_t tpm_db_ipv6_mc_sip_free_slot_num_get(void);
+int32_t tpm_db_ipv6_mc_sip_add(uint8_t  *src_ip);
+int32_t tpm_db_ipv6_mc_sip_ref_num_inc(uint8_t  src_ip_index);
+int32_t tpm_db_ipv6_mc_sip_ref_num_dec(uint8_t  src_ip_index, uint8_t  *new_ref_num);
+
+int32_t tpm_db_ctc_cm_enable_set(tpm_db_ctc_cm_enable_t ctc_cm_enable);
+int32_t tpm_db_ctc_cm_enable_get(tpm_db_ctc_cm_enable_t *ctc_cm_enable);
+
+int32_t tpm_db_ctc_cm_ipv6_parse_win_set(tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win);
+int32_t tpm_db_ctc_cm_ipv6_parse_win_orig_set(tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win);
+int32_t tpm_db_ctc_cm_ipv6_parse_win_get(tpm_db_ctc_cm_ipv6_parse_win_t *ctc_cm_ipv6_parse_win);
+int32_t tpm_db_ctc_cm_ipv6_ety_rule_num_set(uint32_t ipv6_ety_rule_num);
+int32_t tpm_db_ctc_cm_ipv6_ety_rule_num_get(uint32_t *ipv6_ety_rule_num);
+
+uint32_t tpm_db_get_api_busy(tpm_api_type_t api_type);
+uint32_t tpm_db_get_api_rule_num_busy(tpm_api_type_t api_type, uint32_t rule_num);
+void     tpm_db_get_api_all_busy(tpm_api_type_t api_type, uint32_t *num_busy, uint32_t *rule_num_list);
+uint32_t tpm_db_set_api_busy(tpm_api_type_t api_type, uint32_t rule_num);
+uint32_t tpm_db_set_api_free(tpm_api_type_t api_type, uint32_t rule_num);
+
+void tpm_db_show_mtu_cfg(void);
+
+int32_t tpm_db_eth_cmplx_profile_set(tpm_eth_complex_profile_t eth_cmplx_profile);
+tpm_eth_complex_profile_t tpm_db_eth_cmplx_profile_get(void);
+int32_t tpm_db_mac_func_set(void);
+int32_t tpm_db_eth_max_uni_port_set(void);
+tpm_src_port_type_t tpm_db_trg_port_uni_any_bmp_get(bool);
+int32_t tpm_db_to_lan_gmac_get(tpm_trg_port_type_t trg_port, tpm_pnc_trg_t *pnc_target);
+int32_t tpm_db_src_gmac_func_get(tpm_src_port_type_t src_port, tpm_db_gmac_func_t *gmac_func);
+int32_t tpm_db_src_port_on_switch(tpm_src_port_type_t src_port);
+bool    tpm_db_gmac_valid(tpm_gmacs_enum_t gmac);
+
+int32_t tpm_db_add_ipv4_pre_rule(tpm_src_port_type_t src_port, uint32_t key_pattern, uint32_t *rule_num);
+int32_t tpm_db_del_ipv4_pre_rule(tpm_src_port_type_t src_port, uint32_t key_pattern, uint32_t *rule_num);
+int32_t tpm_db_get_ipv4_pre_rule_num(uint32_t *num_rules);
+int32_t tpm_db_alloc_ipv4_pre_filter_key(tpm_src_port_type_t src_port, uint32_t *key_idx);
+int32_t tpm_db_set_ipv4_pre_filter_key(tpm_src_port_type_t src_port, uint32_t key_idx, tpm_parse_fields_t parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+int32_t tpm_db_del_ipv4_pre_filter_key(tpm_src_port_type_t src_port, uint32_t key_idx);
+int32_t tpm_db_get_ipv4_pre_filter_key_num(tpm_src_port_type_t src_port, uint32_t *num_keys);
+int32_t tpm_db_get_ipv4_pre_filter_key(tpm_src_port_type_t src_port, uint32_t key_idx, tpm_parse_fields_t *parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+int32_t tpm_db_find_ipv4_pre_filter_key(tpm_src_port_type_t src_port, tpm_parse_fields_t parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key, uint32_t *key_idx);
+int32_t tpm_db_inc_ipv4_pre_filter_key_user_num(tpm_src_port_type_t src_port, uint32_t key_idx);
+int32_t tpm_db_dec_ipv4_pre_filter_key_user_num(tpm_src_port_type_t src_port, uint32_t key_idx);
+int32_t tpm_db_get_ipv4_pre_filter_key_user_num(tpm_src_port_type_t src_port, uint32_t key_idx, uint32_t *num_users);
+int32_t tpm_db_set_gmac_rate_limit(tpm_db_tx_mod_t gmac_i,
+				   uint32_t queue,
+				   uint32_t bucket_size,
+				   uint32_t rate_limit);
+int32_t tpm_db_get_gmac_rate_limit(tpm_gmacs_enum_t gmac_i,
+				   uint32_t queue,
+				   uint32_t *bucket_size,
+				   uint32_t *rate_limit);
+int32_t tpm_db_fc_conf_set(tpm_init_fc_params_t *port_fc_conf);
+int32_t tpm_db_fc_conf_get(tpm_init_fc_params_t *port_fc_conf);
+/* switch_init */
+int32_t tpm_db_switch_init_set(uint32_t switch_init);
+int32_t tpm_db_switch_init_get(uint32_t *switch_init);
+int32_t tpm_db_pnc_mac_learn_enable_set(tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable);
+int32_t tpm_db_pnc_mac_learn_enable_get(tpm_init_pnc_mac_learn_enable_t *pnc_mac_learn_enable);
+
+bool tpm_db_gmac1_lpbk_en_get(void);
+void tpm_db_gmac1_lpbk_en_set(bool en);
+bool tpm_db_cpu_wan_lpbk_en_get(void);
+void tpm_db_cpu_wan_lpbk_en_set(bool en);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* _TPM_DB_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_header.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_header.h
new file mode 100755
index 0000000..7ae56cb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_header.h
@@ -0,0 +1,141 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : tpm_header.h                                               **
+**                                                                           **
+**  DESCRIPTION : This file tpm module header files                          **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   10Aug10  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+#ifndef _TPM_HEADER_H
+#define _TPM_HEADER_H
+
+/* Include Files
+------------------------------------------------------------------------------*/
+
+#include "pnc/mvPnc.h"
+#include "pnc/mvTcam.h"
+#include "pnc/mvPnc.h"
+#include "bm/mvBmRegs.h"
+#include "gbe/mvNeta.h"
+#include "pmt/mvPmt.h"
+#include "mvSysHwConfig.h"
+#include "eth-phy/mvEthPhy.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "msApiDefs.h"
+#include "msApi.h"
+#include "msApiPrototype.h"
+#include <gtHwCntl.h>
+#include "mv_switch.h"
+#include "mv_switch_wrap.h"
+#include "net_dev/mv_netdev.h"
+
+#include "tpm_db.h"
+#include "tpm_init.h"
+#include "tpm_api.h"
+#include "tpm_trace.h"
+#include "tpm_print.h"
+#include "tpm_mng_if.h"
+#include "tpm_usr_if.h"
+#include "tpm_pnc_logic.h"
+#include "tpm_sysfs.h"
+#include "tpm_pkt_proc_logic.h"
+#include "tpm_tm.h"
+#include "tpm_pnc_mgr.h"
+#include "tpm_modz2_mgr.h"
+#include "tpm_switch_mgr.h"
+#include "tpm_alarm.h"
+
+#include "tpm_mtu.h"
+#include "tpm_counter.h"
+
+#include "tpm_ctc_cm.h"
+
+#include "tpm_self_check.h"
+#include "tpm_cpu_port_fc.h"
+
+/* Definitions
+------------------------------------------------------------------------------*/
+
+/* Enums
+------------------------------------------------------------------------------*/
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _TPM_HEADER_H */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.c
new file mode 100755
index 0000000..d484f8d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.c
@@ -0,0 +1,4060 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_init.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.13
+*
+*
+*******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+/* Global  Variables */
+extern spinlock_t tpmPncLock;
+extern spinlock_t tpmModLock;
+extern spinlock_t tpmTcamAgingLock;
+
+/* Local definitions */
+#define TPM_L2_BASE_LUID   0
+#define TPM_L3_BASE_LUID   (TPM_L2_BASE_LUID + 1)
+#define TPM_IPV4_BASE_LUID (TPM_L3_BASE_LUID + 1)
+#define TPM_IPV6_BASE_LUID (TPM_IPV4_BASE_LUID + 3)
+
+#define IF_ERROR(ret)       \
+	if (ret != TPM_OK) {\
+		TPM_OS_ERROR(TPM_INIT_MOD, " recvd ret_code(%d)\n", ret);\
+		return(ret);\
+	}
+#define IF_ERROR_I(ret, i)  \
+	if (ret != TPM_OK) {\
+		TPM_OS_ERROR(TPM_INIT_MOD, " For index(%d), recvd ret_code(%d)\n", i, ret);\
+		return(ret);\
+	}
+
+/* Local Variables */
+static tpm_init_t tpm_init;
+
+static tpm_tx_mod_hal_map_t tpm_tx_mod_hal_attrs[TPM_MAX_NUM_TX_PORTS] = {
+	/* <TCONT number> */
+	/*TPM_TX_MOD_GMAC0 */ {0, 0},
+	/*TPM_TX_MOD_GMAC1 */ {1, 0},
+	/*TPM_TX_MOD_PMAC_0 */ {2, 0},
+	/*TPM_TX_MOD_PMAC_1 */ {2, 1},
+	/*TPM_TX_MOD_PMAC_2 */ {2, 2},
+	/*TPM_TX_MOD_PMAC_3 */ {2, 3},
+	/*TPM_TX_MOD_PMAC_4 */ {2, 4},
+	/*TPM_TX_MOD_PMAC_5 */ {2, 5},
+	/*TPM_TX_MOD_PMAC_6 */ {2, 6},
+	/*TPM_TX_MOD_PMAC_7 */ {2, 7}
+};
+
+
+#define INIT_GMAC_VALID(gmac)							\
+	(((TPM_ENUM_PMAC == gmac) && (TPM_NONE != tpm_init.pon_type)) ||	\
+	 ((1 == tpm_init.gmac_port_conf[gmac].valid) && (TPM_GMAC_CON_DISC != tpm_init.gmac_port_conf[gmac].conn)))
+
+uint32_t opt_tbl[] = { 	ESC_OPT_RGMIIA_MAC0, ESC_OPT_RGMIIA_MAC1, ESC_OPT_RGMIIA_SW_P5, ESC_OPT_RGMIIA_SW_P6,
+			 	ESC_OPT_RGMIIB_MAC0, ESC_OPT_MAC0_2_SW_P4, ESC_OPT_MAC1_2_SW_P5, ESC_OPT_GEPHY_MAC1,
+			    	ESC_OPT_GEPHY_SW_P0, ESC_OPT_GEPHY_SW_P5, ESC_OPT_FE3PHY, ESC_OPT_SGMII_2_SW_P1, ESC_OPT_SGMII,
+				ESC_OPT_QSGMII,	ESC_OPT_SATA, ESC_OPT_SGMII_2_5 };
+char *opt_str_tlb[] = { "RGMIIA_MAC0", "RGMIIA_MAC1", "RGMIIA_SW_P5", "RGMIIA_SW_P6",
+		 	"RGMIIB_MAC0", "MAC0_2_SW_P4", "MAC1_2_SW_P5", "GEPHY_MAC1",
+		    	"GEPHY_SW_P0", "GEPHY_SW_P5", "FE3PHY", "PCS", "SGMII", "QSGMII", "SATA" , "SGMII_2_5"};
+char *prof_str_tlb[] = { "", "PON_WAN_DUAL_MAC_INT_SWITCH", 	"PON_WAN_G0_INT_SWITCH",
+			"PON_WAN_G1_LAN_G0_INT_SWITCH", 	"G0_WAN_G1_INT_SWITCH",
+		 	"G1_WAN_G0_INT_SWITCH", 		"PON_G1_WAN_G0_INT_SWITCH",
+			"PON_G0_WAN_G1_INT_SWITCH",		"PON_WAN_DUAL_MAC_EXT_SWITCH",
+		    	"PON_WAN_G1_MNG_EXT_SWITCH",		"PON_WAN_G0_SINGLE_PORT",
+			"PON_WAN_G1_SINGLE_PORT",		"PON_G1_WAN_G0_SINGLE_PORT",
+			"PON_G0_WAN_G1_SINGLE_PORT",		"PON_WAN_G0_G1_LPBK"};
+
+static tpm_pnc_range_lookup_map_t pnc_range_lookup_tbl[TPM_MAX_NUM_RANGES] = {
+/*  Range_num             lu_id  last_range  valid */
+	{TPM_PNC_MNGMT_DS, 0, 0, 1},
+	{TPM_PNC_MAC_LEARN, 0, 1, 1},
+	{TPM_PNC_CPU_WAN_LPBK_US, 0, 0, 1},
+	{TPM_PNC_NUM_VLAN_TAGS, 0, 0, 1},
+	{TPM_PNC_MULTI_LPBK, 0, 0, 1},
+	{TPM_PNC_VIRT_UNI, 0, 0, 1},
+	{TPM_PNC_LOOP_DET_US, 0, 0, 1},
+	{TPM_PNC_L2_MAIN, 0, 1, 1},
+	{TPM_PNC_ETH_TYPE, 1, 1, 1},
+	{TPM_PNC_IGMP, 2, 0, 1},
+	{TPM_PNC_IPV4_MC_DS, 2, 0, 1},
+	{TPM_PNC_IPV4_MAIN, 2, 1, 1},
+	{TPM_PNC_TCP_FLAG, 3, 1, 1},
+	{TPM_PNC_TTL, 4, 1, 1},
+	{TPM_PNC_IPV4_PROTO, 5, 0, 1},
+	{TPM_PNC_IPV4_FRAG, 5, 0, 1},
+	{TPM_PNC_IPV4_LEN, 5, 1, 1},
+	{TPM_PNC_IPV6_NH, 6, 1, 1},
+	{TPM_PNC_IPV6_L4_MC_DS, 7, 1, 1},
+	{TPM_PNC_IPV6_L4, 7, 1, 1},
+	{TPM_PNC_IPV6_HOPL, 8, 1, 1},
+	{TPM_PNC_IPV6_MC_SIP, 8, 1, 1},
+	{TPM_PNC_IPV6_GEN, 8, 1, 1},
+	{TPM_PNC_IPV6_MC_DS, 9, 1, 1},
+	{TPM_PNC_IPV6_DIP, 9, 1, 1},
+	{TPM_PNC_CNM_IPV4_PRE, 10, 1, 1},
+	/* The range 'TPM_PNC_CNM_MAIN' spans over two lookup ids.
+		LU_ID_CNM_BASE := 11
+		LU_ID_L2_CNM   := LU_ID_CNM_BASE+0[/11]
+		LU_ID_IPV4_CNM := LU_ID_CNM_BASE+1[/12] */
+	{TPM_PNC_CNM_MAIN, 11, 1, 1},
+	{TPM_PNC_CATCH_ALL, 0, 0, 1},
+
+};
+
+bool tpm_init_gmac_in_gateway_mode(tpm_gmacs_enum_t gmac_i)
+{
+	struct eth_port *pp = NULL;
+
+	pp = mv_eth_port_by_id(gmac_i);
+	if (!pp) {
+		TPM_OS_WARN(TPM_INIT_MOD, "Port (%d) has not been initialized\n", gmac_i);
+		return true;
+	}
+
+	if (pp->flags & MV_ETH_F_SWITCH) {
+		TPM_OS_INFO(TPM_INIT_MOD, "Port (%d) is in GateWay mode, driver has already set MH\n", gmac_i);
+		return true;
+	}
+
+	return false;
+}
+
+uint32_t tpm_init_check_gmac_mh_gtwy_mode(tpm_gmacs_enum_t gmac_i, uint32_t mh)
+{
+	struct eth_port *pp = NULL;
+
+	pp = mv_eth_port_by_id(gmac_i);
+	if (!pp) {
+		TPM_OS_WARN(TPM_INIT_MOD, "Port (%d) has not been initialized\n", gmac_i);
+		return TPM_OK;
+	}
+
+	if (tpm_init_gmac_in_gateway_mode(gmac_i) && (0 == mh)) {
+		/* Port is in GateWay mode, MH must be enabled */
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+void tpm_init_config_params_init(tpm_init_t *tpm_init_params)
+{
+	tpm_init.omci_etype = tpm_init_params->omci_etype;
+	tpm_init.pon_type = tpm_init_params->pon_type;
+	tpm_init.ds_mh_set_conf = tpm_init_params->ds_mh_set_conf;
+	tpm_init.validation_en = tpm_init_params->validation_en;
+	tpm_init.igmp_snoop = tpm_init_params->igmp_snoop;
+	tpm_init.igmp_cpu_queue = tpm_init_params->igmp_cpu_queue;
+	memcpy(&(tpm_init.igmp_pkt_frwd_mod), &(tpm_init_params->igmp_pkt_frwd_mod),
+	       sizeof(tpm_init.igmp_pkt_frwd_mod));
+	tpm_init.num_tcont_llid = tpm_init_params->num_tcont_llid;
+	tpm_init.gmac0_mh_en = tpm_init_params->gmac0_mh_en;
+	tpm_init.gmac1_mh_en = tpm_init_params->gmac1_mh_en;
+#if 0				/*Keep to be added in future version */
+	tpm_init.deb_port_valid = tpm_init_params->deb_port_valid;
+	tpm_init.deb_port = tpm_init_params->deb_port;
+#endif
+	tpm_init.cfg_pnc_parse = tpm_init_params->cfg_pnc_parse;
+	tpm_init.cpu_loopback = tpm_init_params->cpu_loopback;
+	tpm_init.trace_debug_info = tpm_init_params->trace_debug_info;
+	tpm_init.virt_uni_info.enabled = tpm_init_params->virt_uni_info.enabled;
+	tpm_init.virt_uni_info.uni_port = tpm_init_params->virt_uni_info.uni_port;
+	tpm_init.virt_uni_info.switch_port = tpm_init_params->virt_uni_info.switch_port;
+	tpm_init.ipv6_5t_enable = tpm_init_params->ipv6_5t_enable;
+	tpm_init.ctc_cm_enable = tpm_init_params->ctc_cm_enable;
+	tpm_init.ctc_cm_ipv6_parse_window = tpm_init_params->ctc_cm_ipv6_parse_window;
+	tpm_init.pnc_mac_learn_enable = tpm_init_params->pnc_mac_learn_enable;
+#if 0
+	tpm_init.vlan1_tpid = tpm_init_params->vlan1_tpid;
+	tpm_init.vlan2_tpid = tpm_init_params->vlan2_tpid;
+#endif
+
+	memcpy(&(tpm_init.eth_port_conf), &(tpm_init_params->eth_port_conf),
+	       ((sizeof(tpm_init_eth_port_conf_t)) * TPM_MAX_NUM_ETH_PORTS));
+	memcpy(&(tpm_init.gmac_tx), &(tpm_init_params->gmac_tx), ((sizeof(tpm_init_gmac_tx_t)) * TPM_MAX_NUM_TX_PORTS));
+	memcpy(&(tpm_init.gmac_rx), &(tpm_init_params->gmac_rx), ((sizeof(tpm_init_gmac_rx_t)) * TPM_MAX_NUM_GMACS));
+	memcpy(&(tpm_init.gmac_bp_bufs), &(tpm_init_params->gmac_bp_bufs),
+	       ((sizeof(tpm_init_gmac_bufs_t)) * TPM_MAX_NUM_GMACS));
+	memcpy(&(tpm_init.pnc_range), &(tpm_init_params->pnc_range),
+	       ((sizeof(tpm_init_pnc_range_t)) * TPM_MAX_NUM_RANGES));
+	memcpy(&(tpm_init.vlan_etypes), &(tpm_init_params->vlan_etypes),
+	       ((sizeof(uint32_t)) * TPM_NUM_VLAN_ETYPE_REGS));
+	memcpy(&(tpm_init.tpid_opt), &(tpm_init_params->tpid_opt), sizeof(tpm_init_tpid_opt_t));
+	memcpy(&(tpm_init.mod_config), &(tpm_init_params->mod_config), sizeof(tpm_init_mod_params_t));
+	memcpy(&(tpm_init.mod_chain), &(tpm_init_params->mod_chain), sizeof(tpm_init_mod_chain_t));
+	memcpy(&(tpm_init.mc_setting), &(tpm_init_params->mc_setting), sizeof(tpm_init_mc_setting_t));
+
+	memcpy(&(tpm_init.mtu_config), &(tpm_init_params->mtu_config), sizeof(tpm_init_mtu_params_t));
+	memcpy(&(tpm_init.port_fc_conf), &(tpm_init_params->port_fc_conf), sizeof(tpm_init_fc_params_t));
+	tpm_init.pppoe_add_enable = tpm_init_params->pppoe_add_enable;
+	tpm_init.num_vlan_tags = tpm_init_params->num_vlan_tags;
+	tpm_init.cpu_rx_queue = tpm_init_params->cpu_rx_queue;
+	tpm_init.ttl_illegal_action = tpm_init_params->ttl_illegal_action;
+	tpm_init.tcp_flag_check = tpm_init_params->tcp_flag_check;
+	tpm_init.catch_all_pkt_action = tpm_init_params->catch_all_pkt_action;
+	tpm_init.ety_dsa_enable = tpm_init_params->ety_dsa_enable;
+
+	tpm_init.eth_cmplx_profile = tpm_init_params->eth_cmplx_profile;
+	memcpy(&(tpm_init.gmac_port_conf), &(tpm_init_params->gmac_port_conf),
+		sizeof(tpm_init.gmac_port_conf));
+	tpm_init.backup_wan = tpm_init_params->backup_wan;
+	memcpy(&(tpm_init.split_mod_config), &(tpm_init_params->split_mod_config), sizeof(tpm_init_split_mod_params_t));
+	tpm_init.switch_init = tpm_init_params->switch_init;
+}
+
+void tpm_init_pon_type_get(void)
+{
+	if (tpm_init.pon_type == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		tpm_init.pon_type = TPM_NONE;
+
+		if (tpm_init.validation_en == TPM_VALID_ENABLED)
+			TPM_OS_ERROR(TPM_INIT_MOD, "\n PON_TYPE - missing initialization. ");
+	}
+}
+
+void tpm_init_ds_mh_set_conf_get(void)
+{
+	if (tpm_init.ds_mh_set_conf == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		tpm_init.ds_mh_set_conf = TPM_MH_SRC_RX_CTRL;
+		if (tpm_init.validation_en == TPM_VALID_ENABLED)
+			TPM_OS_WARN(TPM_INIT_MOD,
+				    " MH_SRC_RX_CTRL - missing initialization - set to default = TPM_MH_SRC_RX_CTRL = 0. \n");
+	}
+}
+
+void tpm_init_validation_get(void)
+{
+	if (tpm_init.validation_en == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.validation_en = TPM_VALID_DISABLED;
+}
+
+void tpm_init_cfg_pnc_parse_get(void)
+{
+	if (tpm_init.cfg_pnc_parse == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.cfg_pnc_parse = TPM_CFG_PNC_PARSE_ENABLED;
+}
+
+void tpm_init_cpu_loopback_get(void)
+{
+	if (tpm_init.cpu_loopback == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.cpu_loopback = TPM_CPU_LOOPBACK_DISABLED;
+}
+
+void tpm_init_trace_debug_info_get(void)
+{
+	if (tpm_init.trace_debug_info == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.trace_debug_info = 0xE000FFFF;
+
+	/* update the global param with debug info from xml */
+	tpm_glob_trace = tpm_init.trace_debug_info;
+}
+
+void tpm_init_vitual_uni_info_get(void)
+{
+	if (tpm_init.virt_uni_info.enabled == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		tpm_init.virt_uni_info.enabled = 0;
+		tpm_init.virt_uni_info.uni_port = TPM_SRC_PORT_UNI_VIRT;
+		tpm_init.virt_uni_info.switch_port = 5;
+	}
+}
+
+void tpm_init_omci_get(void)
+{
+	if (tpm_init.omci_etype == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		tpm_init.omci_etype = 0xBABA;
+		if (tpm_init.validation_en == TPM_VALID_ENABLED)
+			TPM_OS_ERROR(TPM_INIT_MOD, "\n OMCI type - missing initialization. ");
+	}
+}
+
+void tpm_init_igmp_get(void)
+{
+	tpm_src_port_type_t src_port;
+
+	if (tpm_init.igmp_snoop == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		tpm_init.igmp_snoop = 1;
+		if (tpm_init.validation_en == TPM_VALID_ENABLED)
+			TPM_OS_ERROR(TPM_INIT_MOD, "IGMP snooping - missing initialization. \n ");
+	}
+
+	if (tpm_init.igmp_cpu_queue == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		tpm_init.igmp_cpu_queue = 0;
+		if (tpm_init.validation_en == TPM_VALID_ENABLED)
+			TPM_OS_ERROR(TPM_INIT_MOD, "IGMP cpu_queue - missing initialization. \n ");
+	}
+
+	for (src_port = TPM_SRC_PORT_UNI_0; src_port <= TPM_SRC_PORT_UNI_VIRT; src_port++) {
+		if (tpm_init.igmp_pkt_frwd_mod[src_port] == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+			tpm_init.igmp_pkt_frwd_mod[src_port] = TPM_IGMP_FRWD_MODE_SNOOPING;
+			if (tpm_init.validation_en == TPM_VALID_ENABLED)
+				TPM_OS_ERROR(TPM_INIT_MOD, "IGMP pkt_frwd_mod port: %d - missing initialization. \n ",
+					     src_port);
+		}
+	}
+
+}
+
+void tpm_init_mc_get(void)
+{
+
+	if (tpm_init.mc_setting.filter_mode == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mc_setting.filter_mode = TPM_MC_COMBINED_IP_MAC_FILTER;
+#if 0
+	if (tpm_init.mc_setting.igmp_mode == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+	   tpm_init.mc_setting.igmp_mode = TPM_MC_IGMP_SNOOPING;
+#endif
+	if (tpm_init.mc_setting.per_uni_vlan_xlat == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mc_setting.per_uni_vlan_xlat = false;
+
+	if (tpm_init.mc_setting.mc_pppoe_enable == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mc_setting.mc_pppoe_enable = false;
+
+	if (tpm_init.mc_setting.ipv4_mc_support == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mc_setting.ipv4_mc_support = TPM_TRUE;
+
+	if (tpm_init.mc_setting.ipv6_mc_support == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mc_setting.ipv6_mc_support = TPM_FALSE;
+
+}
+
+uint32_t tpm_init_pkt_len_max_us_get(void)
+{
+	if (TPM_GPON == tpm_init.pon_type)
+		return 2000;
+	else
+		return 1593;
+}
+
+uint32_t tpm_init_ipv4_mtu_us_default_get(void)
+{
+	uint32_t ipv4_mtu_default;
+
+	ipv4_mtu_default = tpm_init_pkt_len_max_us_get();
+
+	/* vlan */
+	ipv4_mtu_default -= (4 * tpm_init.num_vlan_tags);
+	/* da + sa + ety */
+	ipv4_mtu_default -= 14;
+
+	return ipv4_mtu_default;
+}
+
+uint32_t tpm_init_ipv4_pppoe_mtu_us_default_get(void)
+{
+	uint32_t ipv4_pppoe_mtu_default;
+
+	ipv4_pppoe_mtu_default = tpm_init_pkt_len_max_us_get();
+
+	if (TPM_PPPOE_ADD_ENABLED == tpm_init.pppoe_add_enable)
+		ipv4_pppoe_mtu_default -= 8;
+
+	ipv4_pppoe_mtu_default -= (4 * tpm_init.num_vlan_tags);
+	/* da + sa + ety */
+	ipv4_pppoe_mtu_default -= 14;
+
+	return ipv4_pppoe_mtu_default;
+}
+
+uint32_t tpm_init_ipv6_mtu_us_default_get(void)
+{
+	uint32_t ipv6_mtu_default;
+
+	ipv6_mtu_default = tpm_init_pkt_len_max_us_get();
+
+	ipv6_mtu_default -= (4 * tpm_init.num_vlan_tags);
+
+	/* in ipv6 header, payload length does not contain the ipv6 header itself */
+	ipv6_mtu_default -= 40;
+	/* da + sa + ety */
+	ipv6_mtu_default -= 14;
+
+	return ipv6_mtu_default;
+}
+
+uint32_t tpm_init_ipv6_pppoe_mtu_us_default_get(void)
+{
+	uint32_t ipv6_pppoe_mtu_default;
+
+	ipv6_pppoe_mtu_default = tpm_init_pkt_len_max_us_get();
+
+	if (TPM_PPPOE_ADD_ENABLED == tpm_init.pppoe_add_enable)
+		ipv6_pppoe_mtu_default -= 8;
+
+	ipv6_pppoe_mtu_default -= (4 * tpm_init.num_vlan_tags);
+
+	/* in ipv6 header, payload length does not contain the ipv6 header itself */
+	ipv6_pppoe_mtu_default -= 40;
+	/* da + sa + ety */
+	ipv6_pppoe_mtu_default -= 14;
+
+	return ipv6_pppoe_mtu_default;
+}
+
+void tpm_init_mtu_get(void)
+{
+
+	if (tpm_init.pppoe_add_enable == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.pppoe_add_enable = TPM_PPPOE_ADD_ENABLED;
+
+	if (tpm_init.num_vlan_tags == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.num_vlan_tags = 1;
+
+	if (tpm_init.mtu_config.mtu_enable == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mtu_config.mtu_enable = TPM_MTU_CHECK_ENABLED;
+
+	if (tpm_init.mtu_config.ipv4_mtu_us == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mtu_config.ipv4_mtu_us = tpm_init_ipv4_mtu_us_default_get();
+
+	if (tpm_init.mtu_config.ipv6_mtu_us == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mtu_config.ipv6_mtu_us = tpm_init_ipv6_mtu_us_default_get();
+
+	if (tpm_init.cpu_rx_queue == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.cpu_rx_queue = 0;
+
+	if (tpm_init.ttl_illegal_action == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.ttl_illegal_action = TPM_TTL_ZERO_ACTION_NOTHING;
+
+	if (tpm_init.tcp_flag_check == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.tcp_flag_check = TPM_TCP_FLAG_NOT_CHECK;
+
+	/* if the pppoe is not enabled, do not need to set
+	   ipv4_pppoe_mtu_us and ipv6_pppoe_mtu_us */
+	if (TPM_PPPOE_ADD_DISABLED == tpm_init.pppoe_add_enable)
+		return;
+
+	if (tpm_init.mtu_config.ipv4_pppoe_mtu_us == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mtu_config.ipv4_pppoe_mtu_us = tpm_init_ipv4_pppoe_mtu_us_default_get();
+
+	if (tpm_init.mtu_config.ipv6_pppoe_mtu_us == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.mtu_config.ipv6_pppoe_mtu_us = tpm_init_ipv6_pppoe_mtu_us_default_get();
+
+	/* in DS, mtu is optional, so do not set default value */
+
+}
+
+void tpm_init_pnc_config_get(void)
+{
+	if (tpm_init.catch_all_pkt_action == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.catch_all_pkt_action = TPM_PNC_LAST_ENTRY_INIT_DROP;
+}
+
+void tpm_init_ety_dsa_enable_get(void)
+{
+	if (tpm_init.ety_dsa_enable == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.ety_dsa_enable = TPM_ETY_DSA_DISABLE;
+}
+
+void tpm_init_ctc_cm_enable_get(void)
+{
+	if (tpm_init.ctc_cm_enable == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.ctc_cm_enable = TPM_CTC_CM_DISABLED;
+}
+
+void tpm_init_ctc_cm_ipv6_parse_window_get(void)
+{
+	if (tpm_init.ctc_cm_ipv6_parse_window == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.ctc_cm_ipv6_parse_window = TPM_CTC_CM_IPv6_FIRST_24B;
+}
+
+void tpm_init_split_mod_get(void)
+{
+	uint32_t i = 0;
+	if (tpm_init.split_mod_config.split_mod_enable == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.split_mod_config.split_mod_enable = TPM_SPLIT_MOD_DISABLED;
+	if (tpm_init.split_mod_config.p_bit_num == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		tpm_init.split_mod_config.p_bit_num = 8;
+		for(i = 0; i < tpm_init.split_mod_config.p_bit_num; i++) {
+			tpm_init.split_mod_config.p_bit[i] = i;
+		}
+	}
+	if (tpm_init.split_mod_config.vlan_num == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.split_mod_config.vlan_num = 10;
+	if (tpm_init.split_mod_config.split_mod_mode == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.split_mod_config.split_mod_mode = TPM_SPLIT_MOD_MODE_CTC;
+}
+void tpm_init_switch_init_get(void)
+{
+	if (tpm_init.switch_init == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		if (   tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_SINGLE_PORT
+		    || tpm_init.eth_cmplx_profile == TPM_PON_WAN_G1_SINGLE_PORT
+		    || tpm_init.eth_cmplx_profile == TPM_PON_G1_WAN_G0_SINGLE_PORT
+		    || tpm_init.eth_cmplx_profile == TPM_PON_G0_WAN_G1_SINGLE_PORT
+		    || tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK)
+			tpm_init.switch_init = 0;
+		else
+			tpm_init.switch_init = 1;
+	}
+}
+
+void tpm_init_ipv6_5t_enable_get(void)
+{
+	if (tpm_init.ipv6_5t_enable == MV_TPM_UN_INITIALIZED_INIT_PARAM)
+		tpm_init.ipv6_5t_enable = TPM_IPV6_5T_DISABLED;
+}
+
+#define	HW_OPT_ON(on, hw) ((hw & on)  == on)
+#define	VALID_ONLY(on, hw) (((hw & on)  == on) & ((hw & ~on)  == 0))
+
+void tpm_init_eth_cmplx_setup_error_print(uint32_t hwEthCmplx, bool sysfs_call)
+{
+	uint32_t i,j, off = 0;
+	char buff[1024];
+	uint32_t profile[8]= {0};
+
+	off += sprintf(buff+off, "\nSelected Eth Complex Profile: %s", prof_str_tlb[tpm_init.eth_cmplx_profile]);
+	off += sprintf(buff+off, "\nHW enabled options:\n\t");
+	for (i = 0;  i<sizeof(opt_tbl)/sizeof(uint32_t); i++) {
+		if (opt_tbl[i] & hwEthCmplx)
+			off += sprintf(buff+off, "%s ", opt_str_tlb[i]);
+	}
+
+	switch (tpm_init.eth_cmplx_profile)
+	{
+	case TPM_PON_WAN_DUAL_MAC_INT_SWITCH:
+		profile[0] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
+		profile[1] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII;
+		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6;
+		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY;
+		break;
+
+	case TPM_PON_WAN_G0_INT_SWITCH:
+		profile[0] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_FE3PHY | ESC_OPT_GEPHY_SW_P0;
+		profile[1] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII;
+		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6;
+		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_FE3PHY | ESC_OPT_RGMIIA_SW_P6;
+		break;
+
+	case TPM_PON_WAN_G1_LAN_G0_INT_SWITCH:
+		profile[0] = ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
+		profile[1] = ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII;
+		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY;
+		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY;
+		profile[4] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII;
+		break;
+
+	case TPM_G0_WAN_G1_INT_SWITCH:
+		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
+		profile[1] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII;
+		break;
+
+	case TPM_G1_WAN_G0_INT_SWITCH:
+		profile[0] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
+        profile[1] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_FE3PHY;
+		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_QSGMII;
+		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY;
+		profile[4] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY;
+		profile[5] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII;
+		profile[6] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6;
+		break;
+
+	case TPM_PON_G1_WAN_G0_INT_SWITCH:
+		profile[0] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
+		profile[1] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_QSGMII;
+		profile[2] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY;
+		profile[3] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY;
+		profile[4] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII;
+		profile[5] = ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6;
+		break;
+
+	case TPM_PON_G0_WAN_G1_INT_SWITCH:
+		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY;
+		profile[1] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII;
+		break;
+
+	case TPM_PON_WAN_DUAL_MAC_EXT_SWITCH:
+		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1;
+		break;
+
+	case TPM_PON_WAN_G1_MNG_EXT_SWITCH:
+		profile[0] = ESC_OPT_GEPHY_MAC1;
+		break;
+
+	case TPM_PON_WAN_G0_SINGLE_PORT:
+		profile[0] = ESC_OPT_RGMIIB_MAC0;
+		break;
+
+	case TPM_PON_WAN_G1_SINGLE_PORT:
+		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1;
+		profile[1] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_GEPHY_MAC1;
+		break;
+
+	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
+		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1;
+		break;
+
+	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
+		profile[0] = ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1;
+		break;
+
+	case TPM_PON_WAN_G0_G1_LPBK:
+		if (DB_88F6535_BP_ID == mvBoardIdGet())
+			profile[0] = ESC_OPT_RGMIIA_MAC0 | ESC_OPT_GEPHY_MAC1;
+		if (DB_88F6601_BP_ID == mvBoardIdGet())
+			profile[0] = ESC_OPT_SGMII | ESC_OPT_GEPHY_MAC0 | ESC_OPT_LP_SERDES_FE_GE_PHY;
+		if (RD_88F6601_MC_ID == mvBoardIdGet())
+			profile[0] = ESC_OPT_GEPHY_MAC0;
+		break;
+	}
+
+	off += sprintf(buff+off, "\nProfile supported options:\n");
+	for (i = 0; profile[i]; i++) {
+		off += sprintf(buff+off, "\t");
+		for (j = 0; j<32; j++) {
+			if (profile[i] & (1<<j)) {
+				off += sprintf(buff+off, "%s ", opt_str_tlb[j]);
+			}
+		}
+		off += sprintf(buff+off, "\n");
+	}
+
+	off += sprintf(buff+off, "\n");
+	if (true == sysfs_call)
+		printk("%s", buff);
+	else
+		TPM_OS_ERROR(TPM_INIT_MOD, "%s", buff);
+}
+
+
+static uint32_t tpm_init_eth_cmplx_update_conf(void)
+{
+	uint32_t i;
+	uint32_t hwEthCmplx = mvBoardEthComplexConfigGet();
+
+	if (hwEthCmplx & (ESC_OPT_AUTO | ESC_OPT_ILLEGAL))
+	{
+		TPM_OS_ERROR(TPM_INIT_MOD, "\n Illegal values in mvBoardEthComplexConfigGet 0x%x\n", hwEthCmplx);
+       	return TPM_FAIL;
+	}
+
+	if (tpm_init.eth_cmplx_profile == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		if (TPM_VALID_ENABLED == tpm_init.validation_en){
+			TPM_OS_ERROR(TPM_INIT_MOD, "\n ETH COMPLEX PROFILE - missing initialization\n");
+       		return TPM_FAIL;
+		}
+	}
+
+	/* set default values for all ports and GMACs */
+	switch (tpm_init.eth_cmplx_profile)
+	{
+	case TPM_PON_WAN_DUAL_MAC_INT_SWITCH:
+		if (!VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_MAC1_2_SW_P5| ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY), hwEthCmplx))
+			goto setup_err;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_SWITCH_4;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_SWITCH_5;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+			if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
+
+				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
+				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
+				    (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 0))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+				else if (HW_OPT_ON(ESC_OPT_RGMIIA_SW_P6, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 6))
+				 	tpm_init.eth_port_conf[i].chip_connect =TPM_CONN_RGMII1;
+				else if (HW_OPT_ON(ESC_OPT_FE3PHY, hwEthCmplx) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port >= 1) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_FE_PHY;
+				else
+				{
+					TPM_OS_WARN(TPM_INIT_MOD, "switch port %d could not be configured\n",
+						tpm_init.eth_port_conf[i].switch_port);
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_DISC;
+				}
+			}
+		}
+
+		if (tpm_init.virt_uni_info.enabled) {
+			tpm_init.virt_uni_info.uni_port = TPM_SRC_PORT_UNI_VIRT;
+			tpm_init.virt_uni_info.switch_port = TPM_GMAC1_AMBER_PORT_NUM;
+		}
+		break;
+
+	case TPM_PON_WAN_G0_INT_SWITCH:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		if (!VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY), hwEthCmplx))
+			goto setup_err;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_SWITCH_4;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_FALSE;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_DISC;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+			if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
+
+				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
+				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
+				    (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
+			 	    (tpm_init.eth_port_conf[i].switch_port == 0))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+				else if (HW_OPT_ON(ESC_OPT_RGMIIA_SW_P6, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 6))
+					tpm_init.eth_port_conf[i].chip_connect =TPM_CONN_RGMII1;
+				else if (HW_OPT_ON(ESC_OPT_FE3PHY, hwEthCmplx) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port >= 1) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_FE_PHY;
+				else
+				{
+					TPM_OS_WARN(TPM_INIT_MOD, "switch port %d could not be configured\n",
+						tpm_init.eth_port_conf[i].switch_port);
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_DISC;
+				}
+			}
+		}
+		break;
+
+	case TPM_PON_WAN_G1_LAN_G0_INT_SWITCH:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_SWITCH_4;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		// tpm_init.gmac_port_conf[1].port_src = according to XML
+		// tpm_init.gmac_port_conf[1].conn = configured above
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+       		if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
+
+				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
+				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
+				    (tpm_init.eth_port_conf[i].switch_port <= 3))
+       				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 0))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+				else if (HW_OPT_ON(ESC_OPT_RGMIIA_SW_P6, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 6))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+				else if (HW_OPT_ON(ESC_OPT_FE3PHY, hwEthCmplx) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port >= 1) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_FE_PHY;
+				else
+				{
+					TPM_OS_WARN(TPM_INIT_MOD, "switch port %d could not be configured\n",
+						tpm_init.eth_port_conf[i].switch_port);
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_DISC;
+				}
+			}
+
+		if (VALID_ONLY((ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+		    VALID_ONLY((ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII), hwEthCmplx))
+		{
+			for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+				if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+					tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+					tpm_init.eth_port_conf[i].port_src = tpm_init.gmac_port_conf[1].port_src;
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+					tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+					tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+					break;
+				}
+		} else if (VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+			   VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+			   VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII), hwEthCmplx) ||
+			   VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6), hwEthCmplx))
+		{
+				for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+					if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+						tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+						tpm_init.eth_port_conf[i].port_src = tpm_init.gmac_port_conf[1].port_src;
+						tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+						tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+						tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_GE_PHY;
+						break;
+       				 }
+		} else
+			goto setup_err;
+
+		break;
+
+	case TPM_G0_WAN_G1_INT_SWITCH:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII), hwEthCmplx))
+			goto setup_err;
+
+		tpm_init.pon_type = TPM_NONE;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_WAN;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_RGMII2;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_SWITCH_5;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_FALSE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+       		if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
+
+				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
+				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
+				    (tpm_init.eth_port_conf[i].switch_port <= 3))
+       				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 0))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+				else if (HW_OPT_ON(ESC_OPT_RGMIIB_MAC0, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 5))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII2;
+				else if (HW_OPT_ON(ESC_OPT_FE3PHY, hwEthCmplx) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port >= 1) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_FE_PHY;
+				else
+				{
+					TPM_OS_WARN(TPM_INIT_MOD, "switch port %d could not be configured\n",
+						tpm_init.eth_port_conf[i].switch_port);
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_DISC;
+				}
+			}
+
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+			if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+				 tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+				 tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_WAN;
+				 tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII2;
+				 tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC0;
+				 break;
+			}
+		}
+		break;
+
+	case TPM_G1_WAN_G0_INT_SWITCH:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		tpm_init.pon_type = TPM_NONE;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_SWITCH_4;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_WAN;
+		// tpm_init.gmac_port_conf[1].conn = set below
+
+		tpm_init.gmac_port_conf[2].valid = TPM_FALSE;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+       		if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
+
+				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
+				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
+				    (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
+					(tpm_init.eth_port_conf[i].switch_port == 0))
+       				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+				else if (HW_OPT_ON(ESC_OPT_RGMIIA_SW_P6, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 6))
+       				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+				else if (HW_OPT_ON(ESC_OPT_FE3PHY, hwEthCmplx) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port >= 1) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_FE_PHY;
+				else
+				{
+					TPM_OS_WARN(TPM_INIT_MOD, "switch port %d could not be configured\n",
+						tpm_init.eth_port_conf[i].switch_port);
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_DISC;
+				}
+			}
+
+		if (VALID_ONLY((ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+               VALID_ONLY((ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+		    VALID_ONLY((ESC_OPT_RGMIIA_MAC1 | ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_QSGMII), hwEthCmplx)){
+			for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+				if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+					tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+					tpm_init.eth_port_conf[i].port_src = tpm_init.gmac_port_conf[1].port_src;
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+					tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+					tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+					break;
+				}
+			}
+		} else if (VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+			   VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+			   VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII), hwEthCmplx) ||
+			   VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII | ESC_OPT_RGMIIA_SW_P6), hwEthCmplx)){
+			for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+				if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+					tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+					tpm_init.eth_port_conf[i].port_src = tpm_init.gmac_port_conf[1].port_src;
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+					tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+					tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_GE_PHY;
+					break;
+       			 }
+			}
+		} else
+			goto setup_err;
+
+		break;
+
+	case TPM_PON_G1_WAN_G0_INT_SWITCH:
+		if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.backup_wan)
+			tpm_init.backup_wan = TPM_ENUM_GMAC_1;
+
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_SWITCH_4;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_WAN;
+		// tpm_init.gmac_port_conf[1].conn = set in XML
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+       		if (TPM_TRUE == tpm_init.eth_port_conf[i].valid) {
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
+
+				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
+				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
+				    (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 0))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+				else if (HW_OPT_ON(ESC_OPT_RGMIIA_SW_P6, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 6))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+				else if (HW_OPT_ON(ESC_OPT_FE3PHY, hwEthCmplx) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port >= 1) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_FE_PHY;
+				else
+				{
+					TPM_OS_WARN(TPM_INIT_MOD, "switch port %d could not be configured\n",
+						tpm_init.eth_port_conf[i].switch_port);
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_DISC;
+				}
+			}
+
+		if (VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+		    VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_RGMIIA_MAC1 | ESC_OPT_QSGMII), hwEthCmplx))	{
+			for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+				if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+					tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+					tpm_init.eth_port_conf[i].port_src = tpm_init.gmac_port_conf[1].port_src;
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+					tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+					tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+					break;
+				}
+		} else if (VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+			   VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_SW_P6 | ESC_OPT_FE3PHY), hwEthCmplx) ||
+			   VALID_ONLY((ESC_OPT_MAC0_2_SW_P4 | ESC_OPT_GEPHY_MAC1 | ESC_OPT_QSGMII), hwEthCmplx)){
+				for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+					if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+						tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+						tpm_init.eth_port_conf[i].port_src = tpm_init.gmac_port_conf[1].port_src;
+						tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+						tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+						tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_GE_PHY;
+						break;
+       				 }
+		} else
+			goto setup_err;
+
+		break;
+
+	case TPM_PON_G0_WAN_G1_INT_SWITCH:
+		if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.backup_wan)
+			tpm_init.backup_wan = TPM_ENUM_GMAC_1;
+
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_GEPHY_SW_P0 | ESC_OPT_FE3PHY), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_MAC1_2_SW_P5 | ESC_OPT_QSGMII), hwEthCmplx))
+			goto setup_err;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_WAN;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_RGMII2;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_SWITCH_5;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+       		if (TPM_TRUE == tpm_init.eth_port_conf[i].valid){
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_SWITCH;
+
+				if (HW_OPT_ON(ESC_OPT_QSGMII, hwEthCmplx) &&
+				    (tpm_init.eth_port_conf[i].switch_port >= 0) &&
+				    (tpm_init.eth_port_conf[i].switch_port <= 3))
+       				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_QSGMII;
+				else if (HW_OPT_ON(ESC_OPT_GEPHY_SW_P0, hwEthCmplx) &&
+					 (tpm_init.eth_port_conf[i].switch_port == 0))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+				else if (HW_OPT_ON(ESC_OPT_FE3PHY, hwEthCmplx) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port >= 1) &&
+				    	 (tpm_init.eth_port_conf[i].switch_port <= 3))
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_FE_PHY;
+				else
+				{
+					TPM_OS_WARN(TPM_INIT_MOD, "switch port %d could not be configured\n",
+						tpm_init.eth_port_conf[i].switch_port);
+					tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_DISC;
+				}
+			}
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+			if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+				tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+				tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_WAN;
+				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC0;
+				break;
+			}
+		}
+		break;
+
+	case TPM_PON_WAN_DUAL_MAC_EXT_SWITCH:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1), hwEthCmplx))
+			goto setup_err;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_RGMII2;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
+		}
+		break;
+
+	case TPM_PON_WAN_G1_MNG_EXT_SWITCH:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		if (!VALID_ONLY((ESC_OPT_GEPHY_MAC1), hwEthCmplx))
+			goto setup_err;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_FALSE;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++)
+			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
+
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+			if (TPM_FALSE == tpm_init.eth_port_conf[i].valid){
+				tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+				tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_0;
+				tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_GE_PHY;
+				tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+				break;
+			}
+		}
+		break;
+
+	case TPM_PON_WAN_G0_SINGLE_PORT:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		/* FIXME - Add correct condition, after answers from lsp team.
+		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0), hwEthCmplx))
+			goto setup_err;*/
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_UNI_0;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_RGMII2;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_FALSE;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_DISC;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		i = 0;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_0;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII2;
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC0;
+		i++;
+		for (; i < TPM_MAX_NUM_ETH_PORTS; i++)
+			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
+		break;
+
+	case TPM_PON_WAN_G1_SINGLE_PORT:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		if (!VALID_ONLY((ESC_OPT_RGMIIA_MAC1), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_GEPHY_MAC1), hwEthCmplx))
+			goto setup_err;
+
+		if (HW_OPT_ON((ESC_OPT_RGMIIA_MAC1), hwEthCmplx)){
+			 tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+			 tpm_init.eth_port_conf[0].chip_connect = TPM_CONN_RGMII1;
+		}else if (HW_OPT_ON((ESC_OPT_GEPHY_MAC1), hwEthCmplx)){
+			 tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_GE_PHY;
+			 tpm_init.eth_port_conf[0].chip_connect = TPM_CONN_GE_PHY;
+		}
+
+		tpm_init.gmac_port_conf[0].valid = TPM_FALSE;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_DISC;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_UNI_0;
+		// tpm_init.gmac_port_conf[1].conn = set above
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		i = 0;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_0;
+		//tpm_init.eth_port_conf[i].chip_connect = set by XML
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+		i++;
+
+		for (; i < TPM_MAX_NUM_ETH_PORTS; i++)
+			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
+		break;
+
+	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		if ((TPM_ENUM_GMAC_0 != tpm_init.backup_wan) && (TPM_ENUM_GMAC_1 != tpm_init.backup_wan) &&
+		    (TPM_ENUM_PMAC   != tpm_init.backup_wan)) {
+			TPM_OS_ERROR(TPM_INIT_MOD, "\n tpm_init.backup_wan (%x) is not set\n",
+					tpm_init.backup_wan);
+			goto setup_err;
+		}
+
+		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_MAC0), hwEthCmplx))
+			goto setup_err;
+
+		if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.backup_wan)
+			tpm_init.backup_wan = TPM_ENUM_GMAC_1;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_UNI_0;
+
+		if (HW_OPT_ON(ESC_OPT_RGMIIB_MAC0, hwEthCmplx))
+			tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_RGMII2;
+		else if (HW_OPT_ON(ESC_OPT_RGMIIA_MAC0, hwEthCmplx))
+			tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_RGMII1;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_WAN;
+
+		if (HW_OPT_ON(ESC_OPT_RGMIIA_MAC1, hwEthCmplx))
+			tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+		else if (HW_OPT_ON(ESC_OPT_GEPHY_MAC1, hwEthCmplx))
+			tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_GE_PHY;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		i = 0;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_0;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC0;
+		i++;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_WAN;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+		i++;
+		for (; i < TPM_MAX_NUM_ETH_PORTS; i++)
+			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
+		break;
+
+	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		if ((TPM_ENUM_GMAC_0 != tpm_init.backup_wan) && (TPM_ENUM_GMAC_1 != tpm_init.backup_wan) &&
+		    (TPM_ENUM_PMAC   != tpm_init.backup_wan)) {
+			TPM_OS_ERROR(TPM_INIT_MOD, "\n tpm_init.backup_wan (%x) is not set\n",
+					tpm_init.backup_wan);
+			goto setup_err;
+		}
+		if (!VALID_ONLY((ESC_OPT_RGMIIB_MAC0 | ESC_OPT_RGMIIA_MAC1), hwEthCmplx) &&
+		    !VALID_ONLY((ESC_OPT_GEPHY_MAC1 | ESC_OPT_RGMIIA_MAC0), hwEthCmplx))
+			goto setup_err;
+
+		if (MV_TPM_UN_INITIALIZED_INIT_PARAM == tpm_init.backup_wan)
+			tpm_init.backup_wan = TPM_ENUM_GMAC_0;
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_WAN;
+
+		if (HW_OPT_ON(ESC_OPT_RGMIIB_MAC0, hwEthCmplx))
+			tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_RGMII2;
+		else if (HW_OPT_ON(ESC_OPT_RGMIIA_MAC0, hwEthCmplx))
+			tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_RGMII1;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_UNI_0;
+
+		if (HW_OPT_ON(ESC_OPT_RGMIIA_MAC1, hwEthCmplx))
+			tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_RGMII1;
+		else if (HW_OPT_ON(ESC_OPT_GEPHY_MAC1, hwEthCmplx))
+			tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_GE_PHY;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		i = 0;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_WAN;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC1;
+		i++;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_0;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC0;
+		i++;
+		for (; i < TPM_MAX_NUM_ETH_PORTS; i++)
+			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
+		break;
+
+	case TPM_PON_WAN_G0_G1_LPBK:
+		if (1 == tpm_init.virt_uni_info.enabled)
+			goto virt_uni_err;
+
+		/* FIXME - Add correct condition, after answers from lsp team. */
+		/*if (!VALID_ONLY((ESC_OPT_SGMII | ESC_OPT_GEPHY_MAC0 | ESC_OPT_LP_SERDES_FE_GE_PHY), hwEthCmplx))
+			goto setup_err;*/
+
+		tpm_init.gmac_port_conf[0].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[0].port_src = TPM_SRC_PORT_UNI_0;
+		tpm_init.gmac_port_conf[0].conn = TPM_GMAC_CON_GE_PHY;
+
+		tpm_init.gmac_port_conf[1].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[1].port_src = TPM_SRC_PORT_ILLEGAL;
+		tpm_init.gmac_port_conf[1].conn = TPM_GMAC_CON_GE_PHY;
+
+		tpm_init.gmac_port_conf[2].valid = TPM_TRUE;
+		tpm_init.gmac_port_conf[2].port_src = TPM_SRC_PORT_WAN;
+
+		i = 0;
+		tpm_init.eth_port_conf[i].valid = TPM_TRUE;
+		tpm_init.eth_port_conf[i].port_src = TPM_SRC_PORT_UNI_0;
+		tpm_init.eth_port_conf[i].chip_connect = TPM_CONN_RGMII1;
+		tpm_init.eth_port_conf[i].int_connect = TPM_INTCON_GMAC0;
+		i++;
+		for (; i < TPM_MAX_NUM_ETH_PORTS; i++)
+			tpm_init.eth_port_conf[i].valid = TPM_FALSE;
+		break;
+	}
+
+	return TPM_OK;
+
+setup_err:
+	TPM_OS_ERROR(TPM_INIT_MOD, "\n\nHW enabled options and Eth Complex setting do not comply!");
+	tpm_init_eth_cmplx_setup_error_print(hwEthCmplx, false);
+	return (TPM_FAIL);
+
+virt_uni_err:
+	TPM_OS_ERROR(TPM_INIT_MOD, "\n Virt-UNI not supported in profile %s\n",	prof_str_tlb[tpm_init.eth_cmplx_profile]);
+	return (TPM_FAIL);
+}
+
+uint32_t tpm_init_tcont_llid_get(void)
+{
+	if (tpm_init.num_tcont_llid == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		tpm_init.num_tcont_llid = 1;	/* for ZTE fix - changed from 8; */
+		if (tpm_init.validation_en == TPM_VALID_ENABLED)
+			TPM_OS_WARN(TPM_INIT_MOD, "\n TCONT / LLID - missing initialization - set to default <8>.\n ");
+	}
+	return (TPM_OK);
+}
+
+void tpm_init_gmac_mh_en_get(void)
+{
+	if (tpm_init.gmac0_mh_en == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		if (tpm_init_gmac_in_gateway_mode(TPM_ENUM_GMAC_0))
+			tpm_init.gmac0_mh_en = TPM_TRUE;
+		else
+			tpm_init.gmac0_mh_en = TPM_FALSE;
+		if (tpm_init.validation_en == TPM_VALID_ENABLED)
+			TPM_OS_ERROR(TPM_INIT_MOD, "\n GMAC_0 MH - missing initialization. ");
+	} else if (tpm_init.gmac0_mh_en == 2) {
+		if (tpm_init.gmac_port_conf[0].conn == TPM_GMAC_CON_SWITCH_4)
+			tpm_init.gmac0_mh_en = 1;
+		else
+			tpm_init.gmac0_mh_en = 0;
+	}
+
+	if (tpm_init.gmac1_mh_en == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+		if (tpm_init_gmac_in_gateway_mode(TPM_ENUM_GMAC_1))
+			tpm_init.gmac1_mh_en = TPM_TRUE;
+		else
+			tpm_init.gmac1_mh_en = TPM_FALSE;
+		if (tpm_init.validation_en == TPM_VALID_ENABLED)
+			TPM_OS_ERROR(TPM_INIT_MOD, "\n GMAC_1 MH - missing initialization. ");
+	} else if (tpm_init.gmac1_mh_en == 2) {
+		if (tpm_init.gmac_port_conf[1].conn == TPM_GMAC_CON_SWITCH_5)
+			tpm_init.gmac1_mh_en = 1;
+		else
+			tpm_init.gmac1_mh_en = 0;
+	}
+}
+
+void tpm_init_lookup_get(tpm_pnc_ranges_t range_num, uint32_t *lu_id, uint32_t *last_lu_range, uint32_t *valid)
+{
+	uint32_t i;
+
+	*valid = 0;
+
+	for (i = 0; i < (sizeof(pnc_range_lookup_tbl) / sizeof(pnc_range_lookup_tbl[0])); i++) {
+		if (range_num == pnc_range_lookup_tbl[i].pnc_range) {
+			*lu_id = pnc_range_lookup_tbl[i].lookup_id;
+			*last_lu_range = pnc_range_lookup_tbl[i].last_lookup_range;
+			*valid = pnc_range_lookup_tbl[i].valid;
+		}
+	}
+	return;
+}
+
+int32_t tpm_init_config_params_update(void)
+{
+
+	int32_t rc;
+
+	tpm_init_trace_debug_info_get();
+	tpm_init_pon_type_get();
+	tpm_init_ds_mh_set_conf_get();
+	tpm_init_ipv6_5t_enable_get();
+	tpm_init_ctc_cm_ipv6_parse_window_get();
+	tpm_init_ctc_cm_enable_get();
+	tpm_init_vitual_uni_info_get();
+	tpm_init_omci_get();
+	tpm_init_igmp_get();
+	tpm_init_cpu_loopback_get();
+	tpm_init_mtu_get();
+	tpm_init_cfg_pnc_parse_get();
+	tpm_init_mc_get();
+	rc = tpm_init_eth_cmplx_update_conf();
+	if (rc != TPM_OK) {
+		TPM_OS_FATAL(TPM_INIT_MOD, "\n Ethernet Complex configuration failed!\n");
+		return (TPM_FAIL);
+	}
+
+	rc = tpm_init_tcont_llid_get();	/* LLID / TCONT taken from XML */
+	if (rc != TPM_OK) {
+		TPM_OS_FATAL(TPM_INIT_MOD, "\n GMAC internal configuration READ failed!.\n");
+		return (TPM_FAIL);
+	}
+
+	tpm_init_gmac_mh_en_get();
+	tpm_init_pnc_config_get();
+	tpm_init_ety_dsa_enable_get();
+	tpm_init_split_mod_get();
+	tpm_init_switch_init_get();
+
+	return (TPM_OK);
+}
+
+int32_t tpm_init_info_validate(void)
+{
+	int i = 0, j = 0, rc = 0;
+	tpm_init_tx_mod_t tx_mod;
+	unsigned int config_pnc_parser_val;
+	int txp, txq, min_tcont_llid;
+	tpm_gmacs_enum_t gmac_i;
+	uint8_t found_ipv4_pre, found_cnm_main;
+	uint32_t ipv4_pre_size, cnm_main_size, exp_range_size, num_uni_ports = 0;
+	uint32_t gmac0_owner = 0;
+	uint32_t cpu_owner = 0;
+
+	/********************************************************************/
+	if (tpm_init.validation_en == TPM_VALID_ENABLED) {
+	/******************** EPON/GPON system - check num of LLID / TCONT : legal values: 1..8 *********************/
+		if ((tpm_init.pon_type == TPM_EPON) || (tpm_init.pon_type == TPM_GPON)) {
+			if ((tpm_init.num_tcont_llid <= 0) || (tpm_init.num_tcont_llid > 8)) {
+				TPM_OS_FATAL(TPM_INIT_MOD, "\n TCONT/LLID: illegal value(%d) => legal values <1-8>.\n",
+					tpm_init.num_tcont_llid);
+				return (TPM_FAIL);
+			}
+		}
+	/***** EPON case: validate vs .config value for EPON *****/
+		if (tpm_init.pon_type == TPM_EPON) {
+			min_tcont_llid = min(TPM_GPON_MAX_NUM_OF_T_CONTS, TPM_EPON_MAX_MAC_NUM);
+			if (tpm_init.num_tcont_llid > min_tcont_llid) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n LLID: illegal value(%d) => max legal value defined in kernel is %d.\n",
+					tpm_init.num_tcont_llid, TPM_EPON_MAX_MAC_NUM);
+				return (TPM_FAIL);
+			}
+		}
+	/***** GPON case: validate vs .config value for GPON *****/
+		if (tpm_init.pon_type == TPM_GPON) {
+			if (tpm_init.num_tcont_llid > TPM_GPON_MAX_NUM_OF_T_CONTS) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n TCONT: illegal value(%d) => max legal value defined in kernel is %d.\n",
+					tpm_init.num_tcont_llid, TPM_GPON_MAX_NUM_OF_T_CONTS);
+				return (TPM_FAIL);
+			}
+		}
+#if 0				/*Keep to be added in future version */
+	/******************** Debug port setting - validation **********************************/
+		if ((tpm_init.deb_port_valid != 0) && (tpm_init.deb_port_valid != 1)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n Debug port valid is wrong => legal values <0=invalid/1=valid>. \n");
+			return (TPM_FAIL);
+		}
+		if ((tpm_init.deb_port_valid == 1) &&
+		    ((tpm_init.deb_port < TPM_SRC_PORT_UNI_0) || (tpm_init.deb_port > TPM_SRC_PORT_UNI_3))) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n Bad debug port => legal values <TPM_SRC_PORT_UNI_0-TPM_SRC_PORT_UNI_3>. \n");
+			return (TPM_FAIL);
+		}
+#endif
+		/********************* pon type validation *********************************************/
+		/* for FPGA systems - the WAN tech is defined as TPM_NONE */
+		if (tpm_init.pon_type > TPM_NONE) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n pon type: wrong init value(%d) => legal values "
+				"<%d=TPM_EPON/%d=TPM_GPON/%d=TPM_P2P/%d=TPM_NONE>. \n",
+				tpm_init.pon_type, TPM_EPON, TPM_GPON, TPM_P2P, TPM_NONE);
+			return (TPM_FAIL);
+		}
+
+		/********************* CFG PNC PARSE validation *******************************************/
+		if ((tpm_init.cfg_pnc_parse < TPM_CFG_PNC_PARSE_DISABLED)
+		    || (tpm_init.cfg_pnc_parse > TPM_CFG_PNC_PARSE_ENABLED)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n CFG PNC parse: wrong init value(%d) => legal values <0=DISABLED/1=ENABLED. \n",
+				tpm_init.cfg_pnc_parse);
+			return (TPM_FAIL);
+		}
+		/* get the config_pnc_parser value */
+		config_pnc_parser_val = mv_eth_ctrl_pnc_get();
+
+        /* logical validation */
+
+#ifdef CONFIG_MV_ETH_PNC
+		if (tpm_init.cfg_pnc_parse == 0) {
+			if (config_pnc_parser_val == 0) {
+				/* the intention is to give the control to mv neta PNC configuration
+				   do not permit moving from 0 to 1 */
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n CFG PNC bad value: PNC in LSP cannot move from 0 to 1 \n");
+				return (TPM_FAIL);
+			} else {
+				/* config_pnc_parser == 1 */
+				/* nothing to do - the control is in LSP config */
+			}
+		}
+		if (tpm_init.cfg_pnc_parse == 1) {
+			if (config_pnc_parser_val == 0) {
+				/* nothing to do - the control is in TPM */
+			} else {	/* config_pnc_parser == 1 */
+				/* set the config_pnc_parser to 0 - control is set to TPM */
+				rc = mv_eth_ctrl_pnc(0);
+				if (rc != 0) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n Failed to SET the config PNC parse parameter. \n");
+					return (TPM_FAIL);
+				}
+			}
+		}
+#else
+		/* if compilation flag is turned off - there are no relevant functions for PNC_PARSER
+		   therefore do not permit the flag to be 0 - meaning the LSP is taking the responsibility */
+		if (tpm_init.cfg_pnc_parse == 0) {
+			TPM_OS_FATAL(TPM_INIT_MOD, "\n CFG PNC bad value: PNC in LSP does not support PNC PARSER \n");
+			return (TPM_FAIL);
+		} else {
+			if (config_pnc_parser_val == 0) {
+				/*do nothing */
+			} else {
+				/* set the config_pnc_parser to 0 - control is set to TPM */
+				rc = mv_eth_ctrl_pnc(0);
+				if (rc != 0) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n Failed to SET the config PNC parse parameter. \n");
+					return (TPM_FAIL);
+				}
+			}
+		}
+#endif
+
+	/********************* CPU loopback type validation  ********************************************/
+		if ((tpm_init.cpu_loopback < TPM_CPU_LOOPBACK_DISABLED)
+		    || (tpm_init.cpu_loopback > TPM_CPU_LOOPBACK_ENABLED)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n CPU loopback type: wrong init value(%d) => legal values <0=disabled/1=enabled. \n",
+				tpm_init.cpu_loopback);
+			return (TPM_FAIL);
+		}
+
+	/********************* TRACE DEBUG INFO validation *******************************************/
+		if (tpm_init.trace_debug_info == 0) {
+			TPM_OS_WARN(TPM_INIT_MOD,
+				"\n TRACE DEBUG info: init value is %d - no ERRORs will be displayed. \n ",
+				tpm_init.trace_debug_info);
+		}
+
+	/********************* IGMP snooping validation *********************************************/
+		if ((tpm_init.igmp_snoop != 0) && (tpm_init.igmp_snoop != 1)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n IGMP snooping: wrong init value(%d) => legal values <0=disabled/1=enabled>. \n",
+				     tpm_init.igmp_snoop);
+			return (TPM_FAIL);
+		}
+		if (tpm_init.igmp_snoop == 1) {
+			if (tpm_init.igmp_cpu_queue > 7) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					     "\n IGMP snooping: wrong CPU queue(%d) => legal values <0-7>. \n",
+					     tpm_init.igmp_cpu_queue);
+				return (TPM_FAIL);
+			}
+		}
+
+	/********************* Multicast validation *********************************************/
+		if (tpm_init.mc_setting.per_uni_vlan_xlat) {
+			if (tpm_init.mc_setting.filter_mode != TPM_MC_COMBINED_IP_MAC_FILTER) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					     "\n multicast per uni vlan translation is not supported in filter_mode (%d). \n",
+					     tpm_init.mc_setting.filter_mode);
+				return (TPM_FAIL);
+			}
+#if 0
+			if (tpm_init.mc_setting.igmp_mode == TPM_MC_IGMP_SNOOPING && tpm_init.mc_setting.mc_pppoe_enable) {
+			   TPM_OS_FATAL(TPM_INIT_MOD, "\n multicast per uni vlan translation is not supported "
+						"in igmp snooping over pppoe. \n");
+			   return(TPM_FAIL);
+			}
+#endif
+		}
+
+		/* check that igmp_cpu_queue is CPU's reserved queue */
+		/* oct*>>> to do - if per system Q6 is the IGMP CPU - check in all GMACs that Q6 is of CPU ownership */
+
+		if (tpm_init.mc_setting.mc_hwf_queue > 7) {
+			TPM_OS_FATAL(TPM_INIT_MOD, "\n MC setting: wrong MC HWF queue(%d) => legal values <0-7>. \n",
+				     tpm_init.mc_setting.mc_hwf_queue);
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.mc_setting.mc_cpu_queue > 7) {
+			TPM_OS_FATAL(TPM_INIT_MOD, "\n MC setting: wrong MC CPU queue(%d) => legal values <0-7>. \n",
+				     tpm_init.mc_setting.mc_cpu_queue);
+			return (TPM_FAIL);
+		}
+
+	/********************** GMAC_0 connectivity validation *************************************/
+		if ((tpm_init.gmac_port_conf[0].conn < TPM_GMAC_CON_DISC) || (tpm_init.gmac_port_conf[0].conn > TPM_GMAC_CON_GE_PHY)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n GMAC_0 connectivity: wrong init value(%d) => legal values <0-7> \n",
+				     tpm_init.gmac_port_conf[0].conn);
+			return (TPM_FAIL);
+		}
+	/********************** GMAC_1 connectivity validation *************************************/
+		if ((tpm_init.gmac_port_conf[1].conn < TPM_GMAC_CON_DISC) || (tpm_init.gmac_port_conf[1].conn > TPM_GMAC_CON_GE_PHY)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n GMAC_1 connectivity: wrong init value(%d) => legal values <0-7> \n",
+				     tpm_init.gmac_port_conf[1].conn);
+			return (TPM_FAIL);
+		}
+	/********************** GMAC_0 MH enable validation   *************************************/
+		if ((tpm_init.gmac0_mh_en != 0) && (tpm_init.gmac0_mh_en != 1)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n GMAC_0 MH enable: wrong init value(%d) => legal values <0=disabled,1=enabled> \n",
+				     tpm_init.gmac0_mh_en);
+			return (TPM_FAIL);
+		}
+		rc = tpm_init_check_gmac_mh_gtwy_mode(TPM_ENUM_GMAC_0, tpm_init.gmac0_mh_en);
+		if (rc != TPM_OK) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n GMAC_0 is in GateWay mode, MH can not be disabled\n");
+			return (TPM_FAIL);
+		}
+	/********************** GMAC_1 MH enable validation   *************************************/
+		if ((tpm_init.gmac1_mh_en != 0) && (tpm_init.gmac1_mh_en != 1)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n GMAC_1 MH enable: wrong init value(%d) => legal values <0=disabled,1=enabled> \n",
+				     tpm_init.gmac1_mh_en);
+			return (TPM_FAIL);
+		}
+		rc = tpm_init_check_gmac_mh_gtwy_mode(TPM_ENUM_GMAC_1, tpm_init.gmac1_mh_en);
+		if (rc != TPM_OK) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n GMAC_1 is in GateWay mode, MH can not be disabled\n");
+			return (TPM_FAIL);
+		}
+	/********************** GMAC_ Buffer Mngmt Pool_sizes validation ***********************************/
+		for (i = 0; i < sizeof(tpm_init.gmac_bp_bufs) / sizeof(tpm_init_gmac_bufs_t); i++) {
+			if (tpm_init.gmac_bp_bufs[i].valid) {
+				if (((tpm_init.gmac_bp_bufs[i].large_pkt_buffers != 0) &&
+				     (tpm_init.gmac_bp_bufs[i].large_pkt_buffers < MV_BM_POOL_CAP_MIN)) ||
+				    ((tpm_init.gmac_bp_bufs[i].small_pkt_buffers != 0) &&
+				     (tpm_init.gmac_bp_bufs[i].small_pkt_buffers < MV_BM_POOL_CAP_MIN))) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n GMAC%d BM Pool has too small buffer assigment "
+						"large_buf %d, small_buf %d\n",
+						i, tpm_init.gmac_bp_bufs[i].large_pkt_buffers,
+						tpm_init.gmac_bp_bufs[i].small_pkt_buffers);
+					return (TPM_FAIL);
+				}
+			}
+		}
+	/********************** PNC MH enabled allow for DS   *************************************/
+		if ((tpm_init.ds_mh_set_conf != 0) && (tpm_init.ds_mh_set_conf != 1)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n PNC - DS MH allow: wrong init value(%d) => "
+				"legal values <0=MH not allowed/DS,1=MH allowed/DS> \n",
+				tpm_init.ds_mh_set_conf);
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.port_fc_conf.enabled) {
+			MV_U32 device_id = mvCtrlModelGet();
+
+			if (device_id != MV_6601_DEV_ID) {
+				TPM_OS_FATAL(TPM_INIT_MOD, "\n port SW Flow-Control is not supported by this device");
+				return (TPM_FAIL);
+			}
+
+			if ((tpm_init.port_fc_conf.port > TPM_MAX_GMAC) 	||
+			    (tpm_init.port_fc_conf.tgt_port > TPM_MAX_GMAC)	||
+			    (tpm_init.port_fc_conf.tx_port > TPM_MAX_GMAC)){
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n port SW Flow-Control invalid port number:"
+					"port=%d tgt_port=%d tx_port=%d\n",
+					tpm_init.port_fc_conf.port,
+					tpm_init.port_fc_conf.tgt_port,
+					tpm_init.port_fc_conf.tx_port);
+				return (TPM_FAIL);
+			}
+
+			if (tpm_init.port_fc_conf.tx_queue >= TPM_MAX_NUM_TX_QUEUE){
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n port SW Flow-Control invalid port number: tx_queue=%d",
+					tpm_init.port_fc_conf.tx_queue);
+				return (TPM_FAIL);
+			}
+		}
+	/********************** ethernet ports validation ******************************************/
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+			if (tpm_init.eth_port_conf[i].valid == TPM_TRUE) {
+				if ((tpm_init.eth_port_conf[i].chip_connect < TPM_CONN_DISC) ||
+						(tpm_init.eth_port_conf[i].chip_connect > TPM_CONN_RGMII2)) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n ETH_port[(%d)]: chip_connect - wrong init value(%d)"
+						" => legal values <0-5> \n",
+						i, tpm_init.eth_port_conf[i].chip_connect);
+					return (TPM_FAIL);
+				}
+				if ((tpm_init.eth_port_conf[i].int_connect < TPM_INTCON_GMAC0) ||
+						(tpm_init.eth_port_conf[i].int_connect > TPM_INTCON_SWITCH)) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n ETH_port[(%d)]: chip_connect - wrong init "
+						"value(%d) => legal values <0-2> \n",
+						i, tpm_init.eth_port_conf[i].int_connect);
+					return (TPM_FAIL);
+				}
+				if ((tpm_init.eth_port_conf[i].int_connect == TPM_INTCON_SWITCH) &&
+						(tpm_init.eth_port_conf[i].switch_port > 6)) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n ETH_port[(%d)]: switch_port - wrong init "
+						"value(%d) => legal values <0-6> \n",
+						i, tpm_init.eth_port_conf[i].switch_port);
+					return (TPM_FAIL);
+				}
+
+				if ((tpm_init.eth_port_conf[i].int_connect == TPM_INTCON_SWITCH) &&
+					 (tpm_init.eth_port_conf[i].switch_port <= 6)) {
+					num_uni_ports++;
+				}
+			}
+		}
+	/********************* Virtual UNI validation *************************************/
+
+		if ((tpm_init.virt_uni_info.enabled < TPM_VIRT_UNI_DISABLED) ||
+				(tpm_init.virt_uni_info.enabled > TPM_VIRT_UNI_ENABLED)) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+				"\n Virtual UNI: wrong init value(%d) => legal "
+				"values <0=TPM_WIFI_VIRT_UNI_DISABLED/1=TPM_VIRT_UNI_ENABLED. \n",
+				tpm_init.virt_uni_info.enabled);
+			return (TPM_FAIL);
+		}
+		if (tpm_init.virt_uni_info.enabled == TPM_VIRT_UNI_ENABLED) {
+		/*oct* - open this validation in next LSP - meantime it works only on RD */
+#if 0
+			/* check that GMAC1 is connected to internal switch port #5 */
+			rc = mvBoardIsInternalSwitchConnected(1);
+			if (rc == 0) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n WiFi virtual UNI: feature ENABLED - GMAC1 "
+					"is NOT HW-connected to Switch  port #5. \n");
+				return (TPM_FAIL);
+			}
+#endif
+			/* fail eth complex other than dual MAC */
+			if (TPM_PON_WAN_DUAL_MAC_INT_SWITCH != tpm_init.eth_cmplx_profile)
+			{
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n Virtual UNI suppoerted only by ethernet Complex %x (used %x) \n",
+					TPM_PON_WAN_DUAL_MAC_INT_SWITCH, tpm_init.eth_cmplx_profile);
+				return (TPM_FAIL);
+			}
+
+			/* currently support only UNI_VIRT port for WIFI virtual UNI port */
+			if (tpm_init.virt_uni_info.uni_port != TPM_SRC_PORT_UNI_VIRT) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n Virtual UNI: wrong port value(%d) => "
+					"legal values <0-%d> - default value<%d. \n",
+					tpm_init.virt_uni_info.uni_port, TPM_SRC_PORT_UNI_VIRT ,TPM_SRC_PORT_UNI_VIRT);
+				return (TPM_FAIL);
+			}
+
+			num_uni_ports++;
+
+			/* if feature enabled and missing PNC range in the xml - return ERROR */
+			for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+				if (tpm_init.pnc_range[i].range_num == TPM_PNC_VIRT_UNI) {
+					if (tpm_init.pnc_range[i].valid != TPM_TRUE) {
+						TPM_OS_FATAL(TPM_INIT_MOD,
+							"\n Virtual UNI: feature ENABLED - missing "
+							"PNC range <TPM_PNC_VIRT_UNI> in XML config file. \n");
+						return (TPM_FAIL);
+					}
+				}
+			}	/* for */
+			/* TODO: check all GMAC1 TX queues are owned by CPU */
+
+		}
+
+		/*if wifi feature enabled - end validation */
+	/********************* PNC validations *****************************************************/
+		found_ipv4_pre = found_cnm_main = TPM_FALSE;
+		ipv4_pre_size = cnm_main_size = 0;
+
+		/* Validate total number of Pnc Entries */
+		for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+			if (tpm_init.pnc_range[i].valid == TPM_TRUE) {
+				j += tpm_init.pnc_range[i].range_size;
+				if (tpm_init.pnc_range[i].range_num >= TPM_MAX_NUM_RANGES) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"PNC range[%d]: range_num - wrong init value(%d) => "
+						"legal values <0-%d>\n",
+						i, tpm_init.pnc_range[i].range_num, TPM_MAX_RANGE);
+					return (TPM_FAIL);
+				}
+				if (tpm_init.pnc_range[i].range_type > TPM_RANGE_TYPE_TABLE) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"PNC range[%d]: range_type - wrong init value(%d) => "
+						"legal values <0=TYPE_ACL,1=TYPE_TABLE>\n",
+						i, tpm_init.pnc_range[i].range_type);
+					return (TPM_FAIL);
+				}
+				if ((tpm_init.pnc_range[i].cntr_grp < 0) || (tpm_init.pnc_range[i].cntr_grp > 3)) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						     "PNC range[%d] cntr_grp - wrong init value(%d) => legal values <0-3>\n",
+						     i, tpm_init.pnc_range[i].cntr_grp);
+					return (TPM_FAIL);
+				}
+				if ((tpm_init.pnc_range[i].lu_mask < 0) || (tpm_init.pnc_range[i].lu_mask > 1)) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						     "PNC range[%d] lu_mask - wrong init value(%d) => legal values <0-1>\n",
+						     i, tpm_init.pnc_range[i].lu_mask);
+					return (TPM_FAIL);
+				}
+				if (tpm_init.pnc_range[i].range_num == TPM_PNC_CNM_IPV4_PRE) {
+					found_ipv4_pre = TPM_TRUE;
+					ipv4_pre_size = tpm_init.pnc_range[i].range_size;
+				} else if (tpm_init.pnc_range[i].range_num == TPM_PNC_CNM_MAIN) {
+					found_cnm_main = TPM_TRUE;
+					cnm_main_size = tpm_init.pnc_range[i].range_size;
+				}
+			}
+		}
+		if (j > TPM_PNC_SIZE) {
+			TPM_OS_FATAL(TPM_INIT_MOD, "Sum of Pnc ranges(%d) is bigger than PnC size(%d)\n", j,
+				     TPM_PNC_SIZE);
+			return (TPM_FAIL);
+		}
+
+	/********************* MOD validations *****************************************************/
+		/* Validate TPM reserved modification entries */
+	/********************* TX module validations *****************************************************/
+
+		for (tx_mod = TPM_TX_MOD_GMAC0; tx_mod < TPM_MAX_NUM_TX_PORTS; (tx_mod)++) {
+			/* validate gmac_tx - according to tpm_init.num_tcont_llid */
+			if (tx_mod >= TPM_TX_MOD_PMAC_0) {
+				if (((tx_mod - TPM_TX_MOD_GMAC1) > tpm_init.num_tcont_llid) &&
+				    (tpm_init.gmac_tx[tx_mod].valid == 1)) {
+					tpm_init.gmac_tx[tx_mod].valid = 0;
+					TPM_OS_WARN(TPM_INIT_MOD,
+						    " Illegal TCONT/LLID %d configuration - max legal value is %d.\n ",
+						    tx_mod, tpm_init.num_tcont_llid);
+				}
+			}
+			for (i = 0; i < TPM_MAX_NUM_TX_QUEUE; i++) {
+				if (tpm_init.gmac_tx[tx_mod].tx_queue[i].valid != 1)
+					continue;
+
+				if ((tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner < TPM_Q_OWNER_CPU) ||
+				    (tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner >= TPM_Q_OWNER_MAX)) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"TX module queue [%d]: queue_owner - wrong init value(%d)"
+						" => legal values <%d-%d>\n",
+						tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner,
+						TPM_Q_OWNER_CPU, TPM_Q_OWNER_PMAC);
+					return (TPM_FAIL);
+				}
+				if (tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num >= TPM_MAX_NUM_TX_QUEUE) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"TX module queue [%d]: owner_queue_num - wrong init value(%d) "
+						"is bigger than maximum queue number (%d)\n",
+						tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num,
+						TPM_MAX_NUM_TX_QUEUE - 1);
+					return (TPM_FAIL);
+				}
+				if ((tpm_init.gmac_tx[tx_mod].tx_queue[i].sched_method < TPM_SCHED_SP) ||
+				    (tpm_init.gmac_tx[tx_mod].tx_queue[i].sched_method > TPM_SCHED_WRR)) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"TX module queue [%d]: sched_method  - wrong init value(%d) => "
+						"legal values <%d-%d>\n\n",
+						tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num,
+						TPM_SCHED_SP, TPM_SCHED_WRR);
+					return (TPM_FAIL);
+				}
+				if (tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_weight > TPM_MAX_WRR_WEIGHT) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+						"TX module queue [%d]: queue_weight  - wrong init value(%d) "
+						"=> legal values <0-%d>\n\n",
+						tx_mod, tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_weight,
+						TPM_MAX_WRR_WEIGHT);
+					return (TPM_FAIL);
+				}
+			}
+		}
+
+		/********* per GMAC - validate that default TCONT & Queue - are not set as HWF in xml *****/
+		for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+			rc = mv_eth_get_txq_cpu_def(gmac_i, &txp, &txq, 0);
+			if (rc != 0) {
+				TPM_OS_WARN(TPM_INIT_MOD, "\n Failed to GET the default queue per GMAC%d - rc= %d. \n",
+					    gmac_i, rc);
+       			continue;
+			}
+			if (gmac_i >= TPM_TX_MOD_PMAC_0) {
+				if (tpm_init.gmac_tx[gmac_i + txp].tx_queue[txq].queue_owner != TPM_Q_OWNER_CPU) {
+					TPM_OS_WARN(TPM_INIT_MOD,
+						" Default TX queue(%d) per GMAC (%d) must not be set in "
+						"hardware forwarding mode in config params.\n\n", txq, gmac_i);
+				}
+			} else {
+				if (tpm_init.gmac_tx[gmac_i].tx_queue[txq].queue_owner != TPM_Q_OWNER_CPU) {
+					TPM_OS_WARN(TPM_INIT_MOD,
+						" Default TX queue(%d) per GMAC (%d) must not be set in "
+						"hardware forwarding mode in config params.\n\n", txq, gmac_i);
+				}
+			}
+		}
+
+		/*****split mod setting validation******/
+		if (tpm_init.split_mod_config.split_mod_enable == TPM_SPLIT_MOD_ENABLED) {
+			if(tpm_init.split_mod_config.vlan_num > (TPM_DB_SPLIT_MOD_NUM_VLANS_MAX - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM)) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+				     "\n Split Mod VLAN num %d, it should not larger than %d \n",
+				     tpm_init.split_mod_config.vlan_num, (TPM_DB_SPLIT_MOD_NUM_VLANS_MAX - TPM_DB_SPLIT_MOD_INIT_VLANS_NUM));
+				return (TPM_FAIL);
+			}
+			if (tpm_init.split_mod_config.p_bit_num > TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX || tpm_init.split_mod_config.p_bit_num == TPM_DB_SPLIT_MOD_P_BIT_NO_SET) {
+				TPM_OS_FATAL(TPM_INIT_MOD, "\n Split Mod P_bit number out of range.\n");
+				return (TPM_FAIL);
+			}
+			for (i = 0; i < tpm_init.split_mod_config.p_bit_num; i++) {
+				if(tpm_init.split_mod_config.p_bit[i] > TPM_DB_SPLIT_MOD_P_BIT_MAX) {
+					TPM_OS_FATAL(TPM_INIT_MOD,
+				     		"\n Split Mod P_bit %d No Valid\n",
+						tpm_init.split_mod_config.p_bit[i]);
+					return (TPM_FAIL);
+				}
+				for (j = i + 1; j < tpm_init.split_mod_config.p_bit_num; j++) {
+					if(tpm_init.split_mod_config.p_bit[i] == tpm_init.split_mod_config.p_bit[j]) {
+						TPM_OS_FATAL(TPM_INIT_MOD,
+				     			"\n Split Mod P_bit %d Repeat\n",
+							tpm_init.split_mod_config.p_bit[i]);
+						return (TPM_FAIL);
+					}
+				}
+			}
+		}
+
+		/********************* CTC CNM validation *************************************/
+		if (tpm_init.ctc_cm_enable != TPM_CTC_CM_DISABLED) {
+			if (tpm_init.split_mod_config.split_mod_enable == TPM_SPLIT_MOD_DISABLED) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n CTC CM: CTC CnM is enabled while split modification is disabled! \n");
+				return (TPM_FAIL);
+			}
+
+			if (!found_ipv4_pre) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n CTC CM: CTC CnM is enabled while CNM_IPV4_PRE range size is Zero! \n");
+				return (TPM_FAIL);
+			} else {
+				exp_range_size = num_uni_ports * TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_PORT + 1;
+				if (exp_range_size > ipv4_pre_size) {
+					TPM_OS_WARN(TPM_INIT_MOD,
+						"\n CTC CM: CNM IPV4 PRE FILTER is not enough for "
+						"L2 & IPV4 combo rules (%d/%d) of %d UNI ports! \n",
+						exp_range_size, ipv4_pre_size, num_uni_ports);
+				}
+			}
+
+			if (!found_cnm_main) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n CTC CM: CTC CnM is enabled while CNM_MAIN range size is Zero! \n");
+				return (TPM_FAIL);
+			} else {
+				exp_range_size = num_uni_ports * TPM_MAX_NUM_CTC_PRECEDENCE + 2;
+				if (exp_range_size > cnm_main_size) {
+					TPM_OS_WARN(TPM_INIT_MOD,
+						"\n CTC CM: CNM MAIN is not enough for "
+						"8 precedence rules (%d/%d) of %d UNI ports! \n",
+						exp_range_size, cnm_main_size, num_uni_ports);
+				}
+			}
+		} else {
+			if (found_ipv4_pre) {
+				TPM_OS_WARN(TPM_INIT_MOD,
+					"\n CTC CM: Since CTC CnM is disabled, CNM_IPV4_PRE range size should be Zero! \n");
+			}
+			if (found_cnm_main) {
+				TPM_OS_WARN(TPM_INIT_MOD,
+					"\n CTC CM: Since CTC CnM is disabled, CNM_MAIN range size should be Zero! \n");
+			}
+		}
+	}
+
+	/********************* No switch init(MC) validation *************************************/
+	if (tpm_init.switch_init == 0) {
+		if (tpm_init.virt_uni_info.enabled == TPM_VIRT_UNI_ENABLED) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n No Switch Init: Virt UNI is not supported! \n");
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.mc_setting.per_uni_vlan_xlat) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n No Switch Init: MC Per UNI Xlate is not supported! \n");
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.mc_setting.filter_mode != TPM_MC_ALL_CPU_FRWD && tpm_init.mc_setting.filter_mode != TPM_MC_IP_ONLY_FILTER) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n No Switch Init: MC filter mode(%d) not supported! \n", tpm_init.mc_setting.filter_mode);
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.ety_dsa_enable == TPM_ETY_DSA_ENABLE) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n No Switch Init: DSA is not supported! \n");
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.gmac0_mh_en == 1) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n No Switch Init: GMAC0 Marvell header should disabled! \n");
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.pnc_range[TPM_PNC_MAC_LEARN].range_size == 0) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n No Switch Init: PNC range[%d] size is 0! \n", TPM_PNC_MAC_LEARN);
+			return (TPM_FAIL);
+		}
+
+		if (tpm_init.pnc_mac_learn_enable == TPM_PNC_MAC_LEARN_DISABLED &&
+		    tpm_init.pnc_range[TPM_PNC_MAC_LEARN].range_size > 1) {
+			TPM_OS_WARN(TPM_INIT_MOD,
+					"\n No Switch Init: MAC learn disabled, PNC range[%d] size is too bigger! \n", TPM_PNC_MAC_LEARN);
+		}
+
+		if (tpm_init.pnc_mac_learn_enable == TPM_PNC_MAC_LEARN_ENABLED &&
+		    tpm_init.pnc_range[TPM_PNC_MAC_LEARN].range_size <= 1) {
+			TPM_OS_WARN(TPM_INIT_MOD,
+					"\n No Switch Init: MAC learn enabled, PNC range[%d] size is too small! \n", TPM_PNC_MAC_LEARN);
+		}
+	} else if ((tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_SINGLE_PORT ||
+		    tpm_init.eth_cmplx_profile == TPM_PON_WAN_G1_SINGLE_PORT ||
+		    tpm_init.eth_cmplx_profile == TPM_PON_G1_WAN_G0_SINGLE_PORT ||
+		    tpm_init.eth_cmplx_profile == TPM_PON_G0_WAN_G1_SINGLE_PORT ||
+		    tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK)
+		 && tpm_init.switch_init == 1) {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n Switch can not be Init at this profile: [%d]! \n", tpm_init.eth_cmplx_profile);
+			tpm_init.switch_init = 0;
+	}
+
+	/* check XML Tx queue for MC chip with profile TPM_PON_WAN_G0_G1_LPBK */
+	if((MV_6601_DEV_ID == mvCtrlModelGet()) && (TPM_PON_WAN_G0_G1_LPBK == tpm_init.eth_cmplx_profile)) {
+		/* check GMAC1 Tx queue configuration in XML */
+		if (tpm_init.gmac_tx[TPM_TX_MOD_GMAC1].valid == TPM_TRUE) {
+			for (i = 0; i < TPM_MAX_NUM_TX_QUEUE; i++) {
+				if (tpm_init.gmac_tx[TPM_TX_MOD_GMAC1].tx_queue[i].valid == TPM_TRUE) {
+					if (tpm_init.gmac_tx[TPM_TX_MOD_GMAC1].tx_queue[i].queue_owner == TPM_Q_OWNER_GMAC0)
+						gmac0_owner++;
+					if (tpm_init.gmac_tx[TPM_TX_MOD_GMAC1].tx_queue[i].queue_owner == TPM_Q_OWNER_CPU)
+						cpu_owner++;
+				}
+			}
+			if (gmac0_owner == 0) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n TPM_PON_WAN_G0_G1_LPBK: MC chip GMAC1 Tx queue no assigned to GMAC0 \n");
+				return (TPM_FAIL);
+			} else if (gmac0_owner > 1) {
+				TPM_OS_WARN(TPM_INIT_MOD,
+						"\n TPM_PON_WAN_G0_G1_LPBK: One GMAC1 Tx queue assigned to GMAC0 enough! \n");
+			}
+			if (cpu_owner == 0) {
+				TPM_OS_FATAL(TPM_INIT_MOD,
+						"\n TPM_PON_WAN_G0_G1_LPBK: MC chip GMAC1 Tx queue no assigned to CPU \n");
+				return (TPM_FAIL);
+			}
+		} else {
+			TPM_OS_FATAL(TPM_INIT_MOD,
+					"\n TPM_PON_WAN_G0_G1_LPBK: MC chip GMAC1 Invalid! \n");
+			return (TPM_FAIL);
+		}
+
+		/* check PON Tx queue configuration in XML */
+		for (i = TPM_TX_MOD_PMAC_0; i < TPM_MAX_NUM_TX_PORTS; i++) {
+			if (tpm_init.gmac_tx[i].valid == TPM_TRUE) {
+				for(j = 0; j < TPM_MAX_NUM_TX_QUEUE; j++) {
+					if (tpm_init.gmac_tx[i].tx_queue[j].valid != TPM_TRUE ||
+					    tpm_init.gmac_tx[i].tx_queue[j].queue_owner != TPM_Q_OWNER_GMAC1) {
+						TPM_OS_WARN(TPM_INIT_MOD,
+							"\n TPM_PON_WAN_G0_G1_LPBK: All PON-%d Tx queue should be assign to GMAC1! \n", (i - TPM_TX_MOD_PMAC_0));
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_init_tx_mod_set()
+*
+* DESCRIPTION:      Set the configuration of a Tx module
+*
+* INPUTS:
+* tx_mod           -
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+void tpm_init_tx_mod_set(tpm_db_tx_mod_t tx_mod)
+{
+	uint32_t i;
+
+	for (i = 0; i < TPM_MAX_NUM_TX_QUEUE; i++) {
+		if (tpm_init.gmac_tx[tx_mod].tx_queue[i].valid == TPM_TRUE) {
+			tpm_db_gmac_tx_q_conf_set(tx_mod, i,
+						  tpm_init.gmac_tx[tx_mod].tx_queue[i].sched_method,
+						  tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_owner,
+						  tpm_init.gmac_tx[tx_mod].tx_queue[i].owner_queue_num,
+						  tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_size,
+						  tpm_init.gmac_tx[tx_mod].tx_queue[i].queue_weight);
+		}
+	}
+
+}
+
+/*******************************************************************************
+* tpm_init_gmac_rxq_set()
+*
+* DESCRIPTION:      Set the queue configuration of a GMAC
+*
+* INPUTS:
+* tx_mod           -
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+void tpm_init_gmac_rxq_set(tpm_gmacs_enum_t gmac)
+{
+	uint32_t i;
+
+	for (i = 0; i < TPM_MAX_NUM_TX_QUEUE; i++) {
+		if (tpm_init.gmac_rx[gmac].rx_queue[i].valid == TPM_TRUE)
+			tpm_db_gmac_rx_q_conf_set(gmac, i, tpm_init.gmac_rx[gmac].rx_queue[i].queue_size);
+	}
+}
+
+/*******************************************************************************
+* tpm_init_pncranges_set()
+*
+* DESCRIPTION:      Initialize the PnC ranges
+*
+* INPUTS:
+* tx_mod           -
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+int32_t tpm_init_pncranges_set(tpm_reset_level_enum_t reset_type)
+{
+	tpm_db_pnc_range_conf_t pnc_range_conf;
+	uint32_t cur_pnc_entry = 0;
+	uint32_t luid = 0, last_lu_range, val;
+	uint32_t i;
+	tpm_pnc_ranges_t cur_range;
+	int32_t ret_code;
+
+	/* Init basics which are same for all Ranges */
+	pnc_range_conf.num_luids = 1;
+
+	/* Insert valid PnC Ranges by enum order */
+	for (cur_range = 0; cur_range <= TPM_MAX_RANGE; cur_range++) {
+		/* Search Input Table */
+		for (i = 0; i < TPM_MAX_NUM_RANGES; i++) {
+			if ((tpm_init.pnc_range[i].range_num == cur_range) && (tpm_init.pnc_range[i].valid == TPM_TRUE)
+			    && (tpm_init.pnc_range[i].range_size > 0)) {
+				pnc_range_conf.range_id = tpm_init.pnc_range[i].range_num;
+				pnc_range_conf.min_reset_level = tpm_init.pnc_range[i].min_reset_level;
+				pnc_range_conf.range_type = tpm_init.pnc_range[i].range_type;
+				pnc_range_conf.range_size = tpm_init.pnc_range[i].range_size;
+				pnc_range_conf.range_start = cur_pnc_entry;
+				pnc_range_conf.range_end = cur_pnc_entry + tpm_init.pnc_range[i].range_size - 1;
+				pnc_range_conf.cntr_grp = tpm_init.pnc_range[i].cntr_grp;
+				pnc_range_conf.lu_mask = tpm_init.pnc_range[i].lu_mask;
+				pnc_range_conf.api_start = 0;
+				/* For the dscp_ds or dscp_us range, reserve hardcoded  entry at the beginning
+				 * of the pnc_range (see tpm_proc_ipv4_dscp_init) */
+				if (tpm_init.pnc_range[i].range_size < (pnc_range_conf.api_start + 1)) {
+					TPM_OS_ERROR(TPM_INIT_MOD,
+						"pnc_range(%d) cannot set first api_entry to (%d), pnc_range  "
+						"is too small\n",
+						cur_range, pnc_range_conf.api_start);
+					return (TPM_FAIL);
+				}
+				tpm_init_lookup_get(tpm_init.pnc_range[i].range_num, &luid, &last_lu_range, &val);
+				if (val == 0) {
+					TPM_OS_ERROR(TPM_INIT_MOD, "pnc_range(%d) has no defined lookup_id\n",
+						     cur_range);
+					return (TPM_FAIL);
+				}
+
+				pnc_range_conf.base_lu_id = luid;
+
+				/* Set PortId for last entry drop/trap usage, currently last entry will be valid for all active gmacs */
+				pnc_range_conf.last_ent_portid = tpm_proc_all_gmac_bm();
+
+				/* Depending if this is last Range of a LookupId, reserve last entry for debug */
+				if (0 && last_lu_range == 1) {	/* YUVAL_NOW, add xml_param here */
+					if (tpm_init.pnc_range[i].range_size < ((pnc_range_conf.api_start + 1) + 1)) {
+						TPM_OS_ERROR(TPM_INIT_MOD,
+							"pnc_range(%d) cannot set last entry to trap, pnc_range "
+							" is is too small\n",
+							cur_range);
+						return (TPM_FAIL);
+					}
+					/* TODO - this is harcdoded to trap, should be configurable trap/drop/default */
+					pnc_range_conf.init_last_entry = TPM_PNC_RNG_LAST_INIT_TRAP;
+					pnc_range_conf.api_end = pnc_range_conf.range_size - 2;
+				} else {
+					pnc_range_conf.init_last_entry = TPM_PNC_RNG_LAST_INIT_DEF;
+					pnc_range_conf.api_end = pnc_range_conf.range_size - 1;
+				}
+
+				/* Create or Reset the Range (Delete+Create), or skip resetting it */
+				if (reset_type < pnc_range_conf.min_reset_level) {
+					TPM_OS_DEBUG(TPM_INIT_MOD, " skip resetting range (%d)\n",
+						     pnc_range_conf.range_id);
+				} else {
+					TPM_OS_DEBUG(TPM_INIT_MOD, " set range (%d)\n", pnc_range_conf.range_id);
+					/* Never mind if it did or did not exist */
+					ret_code = tpm_db_pnc_rng_delete(pnc_range_conf.range_id);
+					ret_code = tpm_db_pnc_rng_create(&pnc_range_conf);
+					IF_ERROR(ret_code);
+				}
+				cur_pnc_entry += tpm_init.pnc_range[i].range_size;
+
+				TPM_OS_DEBUG(TPM_INIT_MOD,
+					     "\t rng_type(%d)  rng_id(%d)    rng_start(%d)     rng_end(%d)\n"
+					     "\t rng_size(%d)  cntr_grp(%d)  lu_mask(%d)   api_start(%d) \n"
+					     "\t api_end(%d)   lu_id(%d)\n"
+					     "\t init_last_e(%d) last_ent_port_id(%x)\n",
+					     pnc_range_conf.range_type,
+					     pnc_range_conf.range_id,
+					     pnc_range_conf.range_start,
+					     pnc_range_conf.range_end,
+					     pnc_range_conf.range_size,
+					     pnc_range_conf.cntr_grp,
+					     pnc_range_conf.lu_mask,
+					     pnc_range_conf.api_start,
+					     pnc_range_conf.api_end,
+					     pnc_range_conf.base_lu_id,
+					     pnc_range_conf.init_last_entry, pnc_range_conf.last_ent_portid);
+
+				TPM_OS_DEBUG(TPM_INIT_MOD, "cur_pnc_entry(%d)\n", cur_pnc_entry);
+				break;
+			}
+		}
+	}
+	return (TPM_OK);
+}
+
+int32_t tpm_init_api_rng_init(tpm_pnc_ranges_t range, tpm_api_sections_t api_sec, tpm_dir_t dir)
+{
+	int32_t ret_code;
+	uint32_t api_size;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	ret_code = tpm_db_pnc_rng_conf_get(range, &range_conf);
+	if (ret_code != TPM_OK) {
+		TPM_OS_WARN(TPM_INIT_MOD, " PNC Range(%d) was not created - rc(%d) \n", range, ret_code);
+	} else {
+		api_size = (range_conf.api_end - range_conf.api_start + 1);
+		ret_code = tpm_db_api_section_init(api_sec, range, api_size);
+		IF_ERROR(ret_code);
+		return (ret_code);
+	}
+	return (TPM_OK);
+}
+
+int32_t tpm_init_api_rng_init_all(void)
+{
+	int32_t ret_code;
+	/* Init the API Entries Memeory Area */
+	tpm_db_api_entries_area_reset();
+
+	/* Init API Ranges - MAC LEARN */
+	ret_code = tpm_init_api_rng_init(TPM_PNC_MAC_LEARN, TPM_PNC_MAC_LEARN_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
+	/* Init API Ranges - CPU WAN LPBK */
+	ret_code = tpm_init_api_rng_init(TPM_PNC_CPU_WAN_LPBK_US, TPM_CPU_LOOPBACK_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
+	/* Init API Ranges - L2DS, L2US */
+	ret_code = tpm_init_api_rng_init(TPM_PNC_L2_MAIN, TPM_L2_PRIM_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
+	/* Init API Ranges - L3DS, L3US */
+	ret_code = tpm_init_api_rng_init(TPM_PNC_ETH_TYPE, TPM_L3_TYPE_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
+	/* Init API Ranges - IPV4 US, IPV4 DS */
+	ret_code = tpm_init_api_rng_init(TPM_PNC_IPV4_MAIN, TPM_IPV4_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
+	/* Init API Ranges - IPV4 MC */
+	ret_code = tpm_init_api_rng_init(TPM_PNC_IPV4_MC_DS, TPM_IPV4_MC, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_init_api_rng_init(TPM_PNC_IPV6_GEN, TPM_IPV6_GEN_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+	ret_code = tpm_init_api_rng_init(TPM_PNC_IPV6_NH, TPM_IPV6_NH_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+	ret_code = tpm_init_api_rng_init(TPM_PNC_IPV6_DIP, TPM_IPV6_DIP_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+	ret_code = tpm_init_api_rng_init(TPM_PNC_IPV6_L4, TPM_L4_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+	ret_code = tpm_init_api_rng_init(TPM_PNC_IPV6_MC_DS, TPM_IPV6_MC_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_init_api_rng_init(TPM_PNC_CNM_MAIN, TPM_CNM_MAIN_ACL, TPM_DIR_DS);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+
+uint16_t tpm_init_uni_amber_vec_map(uint16_t uni_vec)
+{
+	uint16_t amber_vec = 0;
+	uint16_t amber_port = 0;
+	uint32_t uni_i;
+	tpm_src_port_type_t uni_src_port;
+
+	for (uni_i = 0; uni_i < TPM_MAX_NUM_ETH_PORTS; uni_i++) {
+		if (uni_vec & (1 << uni_i)) {
+			uni_src_port = TPM_SRC_PORT_UNI_0 + uni_i;
+			amber_port = (uint16_t) tpm_db_eth_port_switch_port_get(uni_src_port);
+			amber_vec |= (1 << amber_port);
+		}
+	}
+	return (amber_vec);
+}
+
+int32_t tpm_init_port_vector_tbl(void)
+{
+	uint32_t i, pnc_vector, tbl_entry, uni_port_nr;
+	int32_t ret_code, virt_uni_amber_port_bmp = 0;
+	tpm_init_virt_uni_t virt_uni_info;
+	uint16_t amber_port_vector;
+	uint32_t trg_port_uni_vec = 0, uni_vector, uni_vector_bmp;
+
+	/* use all 16 registers with straight mapping uni_vector to amber_port_vector
+	   only UNI_0 - UNI_3 are used */
+	ret_code = tpm_db_virt_info_get(&virt_uni_info);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " tpm_db_virt_info_get ret_code(%d)\n", ret_code);
+		return (ret_code);
+	}
+
+	/* virt uni not enabled */
+	if (virt_uni_info.enabled == 0) {
+		/* Convert UNI_Vector to Amber Vector, applies to uni_0..7, uni_vector from 0x00 to 0xFF */
+		for (i = 0; i < TPM_TX_MAX_MH_REGS; i++) {
+			amber_port_vector = tpm_init_uni_amber_vec_map(i + 1);
+			tpm_db_port_vector_tbl_info_set(i, i + 1, amber_port_vector, 0);
+		}
+		return TPM_DB_OK;
+       }
+
+	/* virt uni enabled */
+
+	/* first map all 8 UNI ports */
+	amber_port_vector = 0;
+	pnc_vector = 1;
+	tbl_entry = 0;
+	uni_vector_bmp = 0;
+	uni_port_nr = TPM_SRC_PORT_UNI_0;
+	for (uni_vector = TPM_TRG_UNI_0; uni_vector <= TPM_TRG_UNI_VIRT; uni_vector = uni_vector << 1) {
+       	uint16_t switch_port = tpm_db_eth_port_switch_port_get(uni_port_nr);
+
+		if (TPM_DB_ERR_PORT_NUM != switch_port){
+       		tpm_db_port_vector_tbl_info_set(tbl_entry, uni_vector, (1 << switch_port),
+							pnc_vector << TPM_MH_RI_OFFSET);
+
+			/* save the internal switch vector for later use */
+			amber_port_vector |= (1 << switch_port);
+
+			/* save the virt uni and target port vec w/o virt port for later use */
+			if ((1 == virt_uni_info.enabled) && (uni_port_nr == virt_uni_info.uni_port))
+				virt_uni_amber_port_bmp = (1 << switch_port);
+			else
+				uni_vector_bmp |= uni_vector;
+
+			trg_port_uni_vec |= (pnc_vector << TPM_MH_RI_OFFSET);
+		}
+		pnc_vector++;
+		tbl_entry++;
+		uni_port_nr++;
+      	}
+
+	/* now add UNI_ANY mapping */
+	tpm_db_port_vector_tbl_info_set(tbl_entry, TPM_TRG_PORT_UNI_ANY, amber_port_vector,
+					pnc_vector << TPM_MH_RI_OFFSET);
+	tbl_entry++;
+
+	/* now add UNI_ANY_SPECIAL mapping (exluding virt-uni port) */
+	if (1 == virt_uni_info.enabled)
+		amber_port_vector &= ~virt_uni_amber_port_bmp;
+
+	tpm_db_port_vector_tbl_info_set(tbl_entry, uni_vector_bmp, amber_port_vector, trg_port_uni_vec);
+
+	return TPM_DB_OK;
+}
+
+int32_t tpm_init_info_set(void)
+{
+	int32_t ret_code;
+	uint32_t i;
+	tpm_src_port_type_t src_port;
+
+	tpm_db_eth_cmplx_profile_set(tpm_init.eth_cmplx_profile);
+	ret_code = tpm_db_eth_max_uni_port_set();
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_pon_type_set(tpm_init.pon_type);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_backup_wan_set(tpm_init.backup_wan);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_ds_mh_set_conf_set(tpm_init.ds_mh_set_conf);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_cfg_pnc_parse_set(tpm_init.cfg_pnc_parse);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_cpu_loopback_set(tpm_init.cpu_loopback);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_ipv6_5t_enable_set(tpm_init.ipv6_5t_enable);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_ctc_cm_enable_set(tpm_init.ctc_cm_enable);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_ctc_cm_ipv6_parse_win_set(tpm_init.ctc_cm_ipv6_parse_window);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_ctc_cm_ipv6_parse_win_orig_set(tpm_init.ctc_cm_ipv6_parse_window);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_virt_info_set(tpm_init.virt_uni_info);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_double_tag_support_set((tpm_init.num_vlan_tags > 1) ? 1 : 0);
+	IF_ERROR(ret_code);
+#if 0
+	ret_code = tpm_db_default_tag_tpid_set(tpm_init.vlan1_tpid, tpm_init.vlan2_tpid);
+	IF_ERROR(ret_code);
+#endif
+	ret_code = tpm_db_default_tag_tpid_set(&tpm_init.tpid_opt);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_switch_init_set(tpm_init.switch_init);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_pnc_mac_learn_enable_set(tpm_init.pnc_mac_learn_enable);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_fc_conf_set(&tpm_init.port_fc_conf);
+	IF_ERROR(ret_code);
+
+	/* Set GMAC Logical Functions */
+
+	/* PON_MAC */
+	if (tpm_db_active_wan_get() == TPM_ENUM_PMAC)
+		if ((tpm_init.pon_type == TPM_GPON || tpm_init.pon_type == TPM_EPON) &&
+		    (tpm_init.pon_type != TPM_P2P)) {
+			ret_code = tpm_db_omci_type_set(tpm_init.omci_etype);
+			IF_ERROR(ret_code);
+		}
+
+	/* set GMAC/PMAC functionality */
+	tpm_db_mac_func_set();
+
+#if 0				/*Keep to be added in future version */
+	/* Set Debug Port */
+	if (tpm_init.deb_port_valid == 1) {
+		ret_code = tpm_db_pnc_init_deb_port_set(tpm_init.deb_port);
+		IF_ERROR(ret_code);
+	}
+#endif
+
+	/* Set IGMP Conf */
+	for (src_port = TPM_SRC_PORT_UNI_0; src_port <= TPM_SRC_PORT_WAN; src_port++) {
+		tpm_db_igmp_set_port_frwd_mode(src_port, tpm_init.igmp_pkt_frwd_mod[src_port]);
+		printk(KERN_INFO "TPM_SRC_PORT: %d, value: %d\n", src_port, tpm_init.igmp_pkt_frwd_mod[src_port]);
+	}
+	tpm_db_igmp_set_cpu_queue(tpm_init.igmp_cpu_queue);
+	/*printk("TPM_SRC_PORT_WAN: %d, TPM_SRC_PORT_UNI_0: %d, TPM_SRC_PORT_UNI_1: %d, TPM_SRC_PORT_UNI_2: %d, "
+	   "TPM_SRC_PORT_UNI_3: %d, igmp_cpu_queue: %d\n",
+	   tpm_init.igmp_pkt_frwd_mod[4],tpm_init.igmp_pkt_frwd_mod[0],tpm_init.igmp_pkt_frwd_mod[1],
+	   tpm_init.igmp_pkt_frwd_mod[2],tpm_init.igmp_pkt_frwd_mod[3],tpm_init.igmp_cpu_queue); */
+
+	/* Set ethernet Port Config */
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (TPM_TRUE == tpm_init.eth_port_conf[i].valid) {
+			ret_code = tpm_db_eth_port_conf_set(&tpm_init.eth_port_conf[i]);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Set GMAC Port Config */
+	ret_code = tpm_db_gmac_conn_conf_set(tpm_init.gmac_port_conf, TPM_NUM_GMACS);
+	IF_ERROR(ret_code);
+
+	/* Init MH Tx Amber Port Vectors Table */
+	tpm_init_port_vector_tbl();
+
+	/* Set tcont_llid */
+	ret_code = tpm_db_gmac_tcont_llid_set(tpm_init.num_tcont_llid);
+	IF_ERROR(ret_code);
+
+	/* Set GMAC mh_enable */
+	ret_code = tpm_db_gmac_mh_en_conf_set(TPM_ENUM_GMAC_0, tpm_init.gmac0_mh_en);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_gmac_mh_en_conf_set(TPM_ENUM_GMAC_1, tpm_init.gmac1_mh_en);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_gmac_mh_en_conf_set(TPM_ENUM_PMAC, TPM_TRUE);
+	IF_ERROR(ret_code);
+
+	/* Set GMAC BM pools */
+	for (i = 0; i < sizeof(tpm_init.gmac_bp_bufs) / sizeof(tpm_init_gmac_bufs_t); i++) {
+		if (tpm_init.gmac_bp_bufs[i].valid == TPM_TRUE) {
+			tpm_db_gmac_bm_bufs_conf_set(i,
+						     tpm_init.gmac_bp_bufs[i].large_pkt_buffers,
+						     tpm_init.gmac_bp_bufs[i].small_pkt_buffers);
+		}
+	}
+
+	/* Set GMAC/TCONT Tx Queues */
+
+	/* GMAC0 tx */
+	if (tpm_init.gmac_port_conf[0].conn != TPM_GMAC_CON_DISC) {
+		tpm_db_gmac_tx_val_set(TPM_TX_MOD_GMAC0);
+		tpm_init_tx_mod_set(TPM_TX_MOD_GMAC0);
+
+	}
+	/* GMAC1 tx */
+	if (tpm_init.gmac_port_conf[1].conn != TPM_GMAC_CON_DISC) {
+		tpm_db_gmac_tx_val_set(TPM_TX_MOD_GMAC1);
+		tpm_init_tx_mod_set(TPM_TX_MOD_GMAC1);
+	}
+	/* TCONTs */
+	for (i = TPM_TX_MOD_PMAC_0; i < (TPM_TX_MOD_PMAC_0 + tpm_init.num_tcont_llid); i++) {
+		tpm_db_gmac_tx_val_set(i);
+		tpm_init_tx_mod_set(i);
+	}
+
+	/* Set GMAC Rx Queues */
+
+	/* GMAC0 rx */
+	if (tpm_init.gmac_port_conf[0].conn != TPM_GMAC_CON_DISC) {
+		tpm_db_gmac_rx_val_set(TPM_ENUM_GMAC_0);
+		tpm_init_gmac_rxq_set(TPM_ENUM_GMAC_0);
+	}
+
+	/* GMAC1 rx */
+	if (tpm_init.gmac_port_conf[1].conn != TPM_GMAC_CON_DISC) {
+		tpm_db_gmac_rx_val_set(TPM_ENUM_GMAC_1);
+		tpm_init_gmac_rxq_set(TPM_ENUM_GMAC_1);
+	}
+	/* PMAC Rx */
+	if (tpm_init.pon_type == TPM_GPON || tpm_init.pon_type == TPM_EPON) {
+		tpm_db_gmac_rx_val_set(TPM_ENUM_PMAC);
+		tpm_init_gmac_rxq_set(TPM_ENUM_PMAC);
+	}
+
+	/* Init PNC Ranges */
+	/* Init ALL PnC Ranges in the DB, even PnC Ranges with highest reset_level */
+	ret_code = tpm_init_pncranges_set(TPM_ENUM_MAX_RESET_LEVEL + 1);
+	IF_ERROR(ret_code);
+
+	/* Init API Ranges */
+	ret_code = tpm_init_api_rng_init_all();
+	IF_ERROR(ret_code);
+
+	tpm_db_mod2_set_udp_checksum_use_init_bm_state(tpm_init.mod_config.udp_checksum_use_init_bm);
+	tpm_db_mod2_set_udp_checksum_state(tpm_init.mod_config.udp_checksum_update);
+
+	for (i = 0; i < tpm_init.mod_chain.chain_num; i++)
+		tpm_db_mod2_set_chain_num(tpm_init.mod_chain.chain_data[i].type, tpm_init.mod_chain.chain_data[i].num);
+
+	/*** Set state of MH modification in PMT for Multicast ***/
+
+	/* For ip_only_filter_mode, multicast will ALWAYS update the MH, and NEVER use the MH_tx_registers
+	   This way it works the same way for both with_virtual_uni and without_virtual_uni */
+	if (tpm_init.mc_setting.filter_mode == TPM_MC_IP_ONLY_FILTER)
+		tpm_db_mod2_set_multicast_mh_state(1);
+	else {
+		/* For mac_ip_combo_filter_mode, MH is not modified.
+		 * The MH_tx_register are set to :
+		 *   - no_uni_translation  - The "broadcast register", to all_uni_ports.
+		 *   - yes_uni_translation - to switch_port of GMAC1.
+		 * For other modes (not supported yet), it will be same as mac_ip_combo_filter_mode
+		 */
+		if (tpm_init.mc_setting.per_uni_vlan_xlat)
+			tpm_db_mod2_set_multicast_mh_state(1);
+		else
+			tpm_db_mod2_set_multicast_mh_state(0);
+	}
+	/* Set system support for adding PPPoE header as part of PMT modification */
+	tpm_db_mod2_set_pppoe_add_mod_state(tpm_init.pppoe_add_enable);
+
+	/* Set modification double_tag according to num_vlan_tags parameter */
+	tpm_db_mod2_set_double_tag_state((tpm_init.num_vlan_tags >= 2));
+
+	/* set mtu config */
+	tpm_db_mtu_set_ipv4_mtu_us(tpm_init.mtu_config.ipv4_mtu_us);
+
+	tpm_db_mtu_set_ipv4_pppoe_mtu_us(tpm_init.mtu_config.ipv4_pppoe_mtu_us);
+
+	tpm_db_mtu_set_ipv6_mtu_us(tpm_init.mtu_config.ipv6_mtu_us);
+
+	tpm_db_mtu_set_ipv6_pppoe_mtu_us(tpm_init.mtu_config.ipv6_pppoe_mtu_us);
+
+	tpm_db_mtu_set_ipv4_mtu_ds(tpm_init.mtu_config.ipv4_mtu_ds);
+
+	tpm_db_mtu_set_ipv6_mtu_ds(tpm_init.mtu_config.ipv6_mtu_ds);
+
+	tpm_db_set_pppoe_add_enable(tpm_init.pppoe_add_enable);
+
+	tpm_db_set_num_vlan_tags(tpm_init.num_vlan_tags);
+
+	tpm_db_set_mtu_enable(tpm_init.mtu_config.mtu_enable);
+
+	tpm_db_set_cpu_rx_queue(tpm_init.cpu_rx_queue);
+
+	tpm_db_set_ttl_illegal_action(tpm_init.ttl_illegal_action);
+
+	tpm_db_set_tcp_flag_check(tpm_init.tcp_flag_check);
+
+	tpm_db_set_mc_filter_mode(tpm_init.mc_setting.filter_mode);
+	/*tpm_db_set_mc_igmp_mode(tpm_init.mc_setting.igmp_mode); */
+	tpm_db_set_mc_per_uni_vlan_xlate(tpm_init.mc_setting.per_uni_vlan_xlat);
+	tpm_db_set_mc_lpbk_enable(TPM_IP_VER_4, (uint8_t)tpm_init.mc_setting.ipv4_mc_support);
+	tpm_db_set_mc_lpbk_enable(TPM_IP_VER_6, (uint8_t)tpm_init.mc_setting.ipv6_mc_support);
+	tpm_db_set_mc_pppoe_enable(tpm_init.mc_setting.mc_pppoe_enable);
+	tpm_db_set_mc_hwf_queue(tpm_init.mc_setting.mc_hwf_queue);
+	tpm_db_set_mc_cpu_queue(tpm_init.mc_setting.mc_cpu_queue);
+
+	tpm_db_set_catch_all_pkt_action(tpm_init.catch_all_pkt_action);
+	tpm_db_set_ety_dsa_enable(tpm_init.ety_dsa_enable);
+
+	/* set split mod config */
+	tpm_db_split_mod_set_enable(tpm_init.split_mod_config.split_mod_enable);
+	tpm_db_split_mod_set_num_vlans(tpm_init.split_mod_config.vlan_num);
+	tpm_db_split_mod_set_num_p_bits(tpm_init.split_mod_config.p_bit_num, tpm_init.split_mod_config.p_bit);
+	tpm_db_split_mod_set_mode(tpm_init.split_mod_config.split_mod_mode);
+
+	/* set function profile */
+	if (tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK)
+		tpm_db_gmac1_lpbk_en_set(true);
+	else
+		tpm_db_gmac1_lpbk_en_set(false);
+
+	/* set CPU WAN loopback en */
+	if (    (tpm_init.eth_cmplx_profile == TPM_PON_WAN_G0_G1_LPBK)
+	     || (tpm_init.gmac_port_conf[TPM_ENUM_GMAC_0].conn == TPM_GMAC_CON_SWITCH_5))
+		tpm_db_cpu_wan_lpbk_en_set(true);
+	else
+		tpm_db_cpu_wan_lpbk_en_set(false);
+
+	tpm_db_switch_init_set(tpm_init.switch_init);
+
+	return (TPM_OK);
+}
+
+void tpm_init_locks_init(void)
+{
+	spin_lock_init(&tpmPncLock);
+	spin_lock_init(&tpmModLock);
+	spin_lock_init(&tpmTcamAgingLock);
+}
+
+/* Note : The function assumes that the port numbers in the LSP are identical
+ * to the GMAC numbers (port 0 = GMAC0, etc. )*/
+void tpm_init_hwf_set(void)
+{
+	int tx_num, q_num, dest_port, dest_port_txp, owner_rx_port;
+
+	for (tx_num = TPM_TX_MOD_GMAC0; tx_num < TPM_MAX_NUM_TX_PORTS; tx_num++) {
+		dest_port = tpm_tx_mod_hal_attrs[tx_num].hal_port;
+		dest_port_txp = tpm_tx_mod_hal_attrs[tx_num].hal_txp;
+		if (!tpm_init.gmac_tx[tx_num].valid)
+       		continue;
+
+		for (q_num = 0; q_num < TPM_MAX_NUM_TX_QUEUE; q_num++) {
+			if (tpm_init.gmac_tx[tx_num].tx_queue[q_num].valid) {
+				/* No HW forwarding for CPU */
+				if (tpm_init.gmac_tx[tx_num].tx_queue[q_num].queue_owner != TPM_Q_OWNER_CPU) {
+					owner_rx_port =
+					    tpm_init.gmac_tx[tx_num].tx_queue[q_num].queue_owner - 1;
+					if (mv_eth_ctrl_txq_hwf_own(dest_port, dest_port_txp, q_num, owner_rx_port)){
+						TPM_OS_ERROR(TPM_INIT_MOD,
+				    		"mv_eth_ctrl_txq_hwf_own err GMAC = %d TCONT = %d Q = %d HWF: owner_rx %d\n",
+						     dest_port, dest_port_txp, q_num, owner_rx_port);
+					}
+
+					mvNetaHwfTxqEnable(owner_rx_port, dest_port, dest_port_txp, q_num, 1);
+
+					TPM_OS_DEBUG(TPM_INIT_MOD,
+						     "GMAC = %d TCONT = %d Q = %d HWF: owner_rx %d\n",
+						     dest_port, dest_port_txp, q_num, owner_rx_port);
+				}
+			} else {
+				if (mv_eth_ctrl_txq_hwf_own(dest_port, dest_port_txp, q_num, -1)){
+						TPM_OS_DEBUG(TPM_INIT_MOD,
+				    		"mv_eth_ctrl_txq_hwf_own err GMAC = %d TCONT = %d Q = %d HWF: owner_rx -1\n",
+						     dest_port, dest_port_txp, q_num);
+				}
+				mvNetaHwfTxqEnable(0, dest_port, dest_port_txp, q_num, 0);
+				TPM_OS_DEBUG(TPM_INIT_MOD, "GMAC = %d TCONT = %d Q = %d CPU owner\n",
+					     dest_port, dest_port_txp, q_num);
+			}
+		}	/* All queues */
+	}			/* All TX ports */
+}
+
+/* Note : The function assumes that the port numbers in the LSP are
+ * identical to the GMAC numbers (port 0 = GMAC0, etc. )*/
+void tpm_init_txq_size_set(void)
+{
+	int tx_num, q_num, dest_port, prev_dest_port = 0xFF, dest_port_txp, status;
+	uint32_t q_valid, q_size;
+
+	for (tx_num = TPM_TX_MOD_GMAC0; tx_num < TPM_MAX_NUM_TX_PORTS; tx_num++) {
+		dest_port = tpm_tx_mod_hal_attrs[tx_num].hal_port;
+		dest_port_txp = tpm_tx_mod_hal_attrs[tx_num].hal_txp;
+
+		if ((dest_port == 0 && tpm_init.gmac_port_conf[0].conn == TPM_GMAC_CON_DISC) ||
+		    (dest_port == 1 && tpm_init.gmac_port_conf[1].conn == TPM_GMAC_CON_DISC)) {
+			continue;
+		}
+
+		if (mv_eth_ctrl_port_started_get(dest_port)) {
+			if (prev_dest_port != dest_port)
+				TPM_OS_WARN(TPM_INIT_MOD,
+					    "port%d already started, tx_queue sizes will not be updated\n", dest_port);
+			prev_dest_port = dest_port;
+			continue;
+		}
+
+		for (q_num = 0; q_num < TPM_MAX_NUM_TX_QUEUE; q_num++) {
+
+			if (TPM_DB_OK != tpm_db_gmac_tx_q_conf_get(tx_num, q_num, &q_valid,
+								   NULL, NULL, NULL, &q_size, NULL)){
+				TPM_OS_WARN(TPM_INIT_MOD,
+					    "Could not get port(%d) tx_queue sizes\n", dest_port);
+				continue;
+			}
+
+			if (!q_valid)
+				q_size = 0;
+
+			status = mv_eth_ctrl_txq_size_set(dest_port, dest_port_txp, q_num, q_size);
+			if (status) {
+				TPM_OS_DEBUG(TPM_INIT_MOD, "mv_eth_ctrl_txq_size_set err, port = %d TCONT = %d Q = %d size = %d\n",
+					     dest_port, dest_port_txp, q_num, q_size);
+			}
+		}		/* All TX queues */
+	}			/* All TX ports */
+}
+
+/* Note : The function assumes that the port numbers in the LSP are
+ * identical to the GMAC numbers (port 0 = GMAC0, etc. )*/
+void tpm_init_rxq_size_set(void)
+{
+	tpm_gmacs_enum_t gmac_num;
+	int q_num, status;
+	uint32_t q_valid, q_size, rc;
+
+	for (gmac_num = TPM_ENUM_GMAC_0; gmac_num < TPM_MAX_NUM_GMACS; gmac_num++) {
+		if (!tpm_db_gmac_rx_val_get(gmac_num))
+			continue;
+		/* treat only valid ports */
+		if (!INIT_GMAC_VALID(gmac_num))
+			continue;
+
+		if (mv_eth_ctrl_port_started_get(gmac_num)) {
+			TPM_OS_WARN(TPM_INIT_MOD, "port%d already started, rx_queue sizes will not be updated\n", gmac_num);
+			continue;
+		}
+		for (q_num = 0; q_num < TPM_MAX_NUM_RX_QUEUE; q_num++) {
+			rc = tpm_db_gmac_rx_q_conf_get(gmac_num, q_num, &q_valid, &q_size);
+
+			if (TPM_DB_OK != rc) {
+				TPM_OS_WARN(TPM_INIT_MOD, "tpm_db_gmac_rx_q_conf_get port%d error\n", gmac_num);
+				continue;
+			}
+			if (q_valid)
+				status = mv_eth_ctrl_rxq_size_set(gmac_num, q_num, q_size);
+			else
+				status = mv_eth_ctrl_rxq_size_set(gmac_num, q_num, 0);
+
+			if (status)
+				TPM_OS_DEBUG(TPM_INIT_MOD, "gmac_num = %d  Q = %d size = %d\n", gmac_num, q_num, q_size);
+		}		/* All RX queues */
+	}			/* All GMACs */
+}
+
+int32_t tpm_init_mh_select(void)
+{
+	tpm_gmacs_enum_t gmac_i;
+	tpm_db_gmac_func_t gmac_func;
+
+	/* MH select config */
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		tpm_db_gmac_func_get(gmac_i, &gmac_func);
+
+		if ((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_WAN)) {
+			switch (tpm_init.ds_mh_set_conf) {
+			case TPM_MH_SRC_RX_CTRL:
+				mvNetaHwfMhSrcSet(gmac_i, MV_NETA_HWF_MH_REG);
+				mvNetaHwfMhSelSet(gmac_i, (uint8_t) NETA_MH_REPLACE_MH_REG(0));
+				/* Keep all TX_MH_registers(1-15) 'Zero' !! */
+				break;
+			case TPM_MH_SRC_PNC_RI:
+				mvNetaHwfMhSrcSet(gmac_i, MV_NETA_HWF_MH_PNC);
+				mvNetaHwfMhSelSet(gmac_i, (uint8_t) NETA_MH_DONT_CHANGE);
+				break;
+			default:
+				TPM_OS_ERROR(TPM_INIT_MOD, " Unknown d/s MH source (%d)\n", tpm_init.ds_mh_set_conf);
+				return (TPM_FAIL);
+			}
+		} else if ((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_LAN)) {
+			mvNetaHwfMhSrcSet(gmac_i, MV_NETA_HWF_MH_REG);
+			mvNetaHwfMhSelSet(gmac_i, (uint8_t) NETA_MH_REPLACE_GPON_HDR);
+		}
+	}
+
+	return (TPM_OK);
+}
+
+int32_t tpm_init_tx_queue_sched(void)
+{
+
+	tpm_init_tx_mod_t tx_mod;
+	tpm_db_sched_t sched_method;
+	uint32_t queue_weight = 0;
+	int32_t ret_code = TPM_OK;
+	int i = 0, port = 0, sched_ent = 0;
+	uint32_t q_valid;
+
+	for (tx_mod = TPM_TX_MOD_GMAC0; tx_mod < TPM_MAX_NUM_TX_PORTS; (tx_mod)++) {
+
+		for (i = 0; i < TPM_MAX_NUM_TX_QUEUE; i++) {
+
+			ret_code = tpm_db_gmac_tx_q_conf_get(tx_mod, i, &q_valid, &sched_method,
+							     NULL, NULL, NULL, &queue_weight);
+			if (q_valid == TPM_FALSE)
+				continue;
+
+			if (tx_mod == TPM_TX_MOD_GMAC0) {
+				port = SW_GMAC_0;
+				sched_ent = 0;
+			} else if (tx_mod >= TPM_TX_MOD_PMAC_0) {
+				port = PON_PORT;
+				sched_ent = tx_mod - TPM_TX_MOD_PMAC_0;
+			} else {
+				ret_code = TPM_FAIL;
+				break;
+			}
+
+			switch (sched_method) {
+			case TPM_SCHED_SP:
+				mvNetaTxqFixPrioSet(port, sched_ent, i);
+				break;
+
+			case TPM_SCHED_WRR:
+				mvNetaTxqWrrPrioSet(port, sched_ent, i, queue_weight);
+				break;
+
+			default:
+				printk(KERN_ERR " Unknown scheduling method command \n");
+				return (TPM_NOT_FOUND);
+
+			}
+		}
+	}
+
+	return ret_code;
+}
+
+int32_t tpm_init_switch(void)
+{
+	uint32_t i;
+	uint32_t sw_port_bmp = 0;
+	unsigned char gq_da[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01 };
+	tpm_gmacs_enum_t gmac_i;
+	int32_t switch_port;
+
+	/* no need to initialize switch for these profiles */
+	switch (tpm_init.eth_cmplx_profile) {
+	case TPM_PON_WAN_DUAL_MAC_EXT_SWITCH:
+	case TPM_PON_WAN_G1_MNG_EXT_SWITCH:
+	case TPM_PON_WAN_G0_SINGLE_PORT:
+	case TPM_PON_WAN_G1_SINGLE_PORT:
+	case TPM_PON_G1_WAN_G0_SINGLE_PORT:
+	case TPM_PON_G0_WAN_G1_SINGLE_PORT:
+	case TPM_PON_WAN_G0_G1_LPBK:
+		return (TPM_OK);
+       default:
+       	break;
+	}
+
+	mv_switch_drv_init();
+
+	/* Set 802.1q mode => fallback for all ports */
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (TPM_FALSE == tpm_init.eth_port_conf[i].valid)
+           		continue;
+
+		/* need only switch ports */
+		if (TPM_INTCON_SWITCH != tpm_init.eth_port_conf[i].int_connect)
+			continue;
+
+	    	if (mv_switch_set_vid_filter_per_port(tpm_init.eth_port_conf[i].switch_port, GT_FALSE))
+			TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_set_vid_filter_per_port err. sw port %d\n",
+					    tpm_init.eth_port_conf[i].switch_port);
+	}
+
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		switch_port = -1;
+
+		if (TPM_GMAC_CON_SWITCH_4 == tpm_init.gmac_port_conf[gmac_i].conn)
+			switch_port = TPM_GMAC0_AMBER_PORT_NUM;
+		else if (TPM_GMAC_CON_SWITCH_5 == tpm_init.gmac_port_conf[gmac_i].conn){
+			if (1 == tpm_init.virt_uni_info.enabled || tpm_init.mc_setting.per_uni_vlan_xlat == 1)
+				switch_port = tpm_init.virt_uni_info.switch_port;
+			else
+				switch_port = TPM_GMAC1_AMBER_PORT_NUM;
+		 }
+		 if (switch_port != -1) {
+       		 if (mv_switch_set_vid_filter_per_port(switch_port, GT_FALSE))
+				 TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_set_vid_filter_per_port err. sw port %d\n",
+					    switch_port);
+		}
+	}
+
+	/* Enable BC floods */
+	mv_switch_set_broadcast_flood(GT_TRUE);
+
+	/* Disable unknown MC floods for all UNI ports */
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (TPM_FALSE == tpm_init.eth_port_conf[i].valid)
+           		continue;
+
+		/* need only switch ports */
+		if (TPM_INTCON_SWITCH != tpm_init.eth_port_conf[i].int_connect)
+			continue;
+
+		if (mv_switch_set_unknown_multicast_flood(tpm_init.eth_port_conf[i].switch_port, GT_FALSE))
+			TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_set_unknown_multicast_flood err. sw port %d\n",
+					    tpm_init.eth_port_conf[i].switch_port);
+	}
+
+	/*set default VLAN ID to 0 */
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (TPM_FALSE == tpm_init.eth_port_conf[i].valid)
+           		continue;
+
+		/* need only switch ports */
+		if (TPM_INTCON_SWITCH != tpm_init.eth_port_conf[i].int_connect)
+			continue;
+
+		if (mv_switch_set_port_def_vlan(tpm_init.eth_port_conf[i].switch_port, 0))
+			TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_set_port_def_vlan err. sw port %d\n",
+					    tpm_init.eth_port_conf[i].switch_port);
+	}
+
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (TPM_FALSE == tpm_init.gmac_port_conf[gmac_i].valid)
+			continue;
+
+		switch_port = -1;
+
+		if (TPM_GMAC_CON_SWITCH_4 == tpm_init.gmac_port_conf[gmac_i].conn)
+			switch_port = TPM_GMAC0_AMBER_PORT_NUM;
+		else if (TPM_GMAC_CON_SWITCH_5 == tpm_init.gmac_port_conf[gmac_i].conn){
+			if (1 == tpm_init.virt_uni_info.enabled)
+				switch_port = tpm_init.virt_uni_info.switch_port;
+			else
+				switch_port = TPM_GMAC1_AMBER_PORT_NUM;
+		}
+
+		if (switch_port != -1) {
+			if (mv_switch_set_port_def_vlan(switch_port, 0))
+				TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_set_vid_filter_per_port err. sw port %d\n",
+					    switch_port);
+		}
+	}
+
+	switch_port = -1;
+
+	/* Add all ports to the member list of default VID(0) */
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (TPM_FALSE == tpm_init.gmac_port_conf[gmac_i].valid)
+			continue;
+
+		if (TPM_GMAC_CON_SWITCH_5 == tpm_init.gmac_port_conf[gmac_i].conn){
+			if (1 == tpm_init.virt_uni_info.enabled)
+				switch_port = tpm_init.virt_uni_info.switch_port;
+			else
+				switch_port = TPM_GMAC1_AMBER_PORT_NUM;
+
+       		 if (mv_switch_port_add_vid(switch_port, 0, TPM_GMAC0_AMBER_PORT_NUM))
+				 TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_set_port_def_vlan err. sw port %d\n",
+					    switch_port);
+		}
+	}
+
+	if (switch_port != -1) {
+		for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+			if (TPM_FALSE == tpm_init.eth_port_conf[i].valid)
+				continue;
+
+			/* need only switch ports */
+			if (TPM_INTCON_SWITCH != tpm_init.eth_port_conf[i].int_connect)
+				continue;
+
+			if (switch_port != -1) {
+				if (mv_switch_port_add_vid(tpm_init.eth_port_conf[i].switch_port, 0, switch_port))
+					TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_port_add_vid err. sw port %d\n",
+						tpm_init.eth_port_conf[i].switch_port);
+			}
+		}
+	}
+
+
+	/* config amber port#5 - same as UNI ports */
+
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (TPM_FALSE == tpm_init.gmac_port_conf[gmac_i].valid)
+			continue;
+
+		if (TPM_GMAC_CON_SWITCH_4 == tpm_init.gmac_port_conf[gmac_i].conn)
+			sw_port_bmp |= 1 << TPM_GMAC0_AMBER_PORT_NUM;
+		else if (TPM_GMAC_CON_SWITCH_5 == tpm_init.gmac_port_conf[gmac_i].conn)
+			sw_port_bmp |= 1 << TPM_GMAC1_AMBER_PORT_NUM;
+	}
+
+
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (TPM_FALSE == tpm_init.eth_port_conf[i].valid)
+           		continue;
+
+		/* need only switch ports */
+		if (TPM_INTCON_SWITCH != tpm_init.eth_port_conf[i].int_connect)
+			continue;
+
+		sw_port_bmp |= 1 << tpm_init.eth_port_conf[i].switch_port;
+	}
+	if (mv_switch_mac_addr_set(gq_da, 0, sw_port_bmp, 1))
+		TPM_OS_WARN(TPM_INIT_MOD, "mv_switch_mac_addr_set err. sw_port_bmp 0X%x\n", sw_port_bmp);
+
+	return (TPM_OK);
+}
+
+int32_t tpm_init_mh_conf_set(void)
+{
+	tpm_gmacs_enum_t gmac_i;
+	uint32_t amber_port_num, mh_en;
+	/*uint16_t amber_port_cfg_reg; */
+
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		/* if port in GateWay mode, do not set MH */
+		if (tpm_init_gmac_in_gateway_mode(gmac_i))
+			continue;
+
+		amber_port_num = -1;
+
+		switch (gmac_i) {
+		case TPM_ENUM_GMAC_0:
+			mh_en = tpm_init.gmac0_mh_en;
+			if (TPM_GMAC_CON_SWITCH_4 == tpm_init.gmac_port_conf[gmac_i].conn)
+				amber_port_num = TPM_GMAC0_AMBER_PORT_NUM;
+			break;
+		case TPM_ENUM_GMAC_1:
+			mh_en = tpm_init.gmac1_mh_en;
+			if (TPM_GMAC_CON_SWITCH_5 == tpm_init.gmac_port_conf[gmac_i].conn)
+				amber_port_num = TPM_GMAC1_AMBER_PORT_NUM;
+			break;
+		case TPM_ENUM_PMAC:
+			mh_en = 1;
+			/*no amber port */
+			break;
+		default:
+			TPM_OS_ERROR(TPM_INIT_MOD, " Unknown GMAC (%d)\n", gmac_i);
+			return (TPM_FAIL);
+		}
+
+		/* Configure PP */
+		TPM_OS_DEBUG(TPM_INIT_MOD, "GMAC(%d) mh_en(%d)\n", gmac_i, mh_en);
+		printk("GMAC(%d) mh_en(%d) amber_port_num(%d)\n", gmac_i, mh_en,amber_port_num);
+		if (mh_en == TPM_TRUE)
+		{
+			if (mv_eth_ctrl_flag(gmac_i, MV_ETH_F_MH, 1)){
+				TPM_OS_ERROR(TPM_INIT_MOD, " mv_eth_ctrl_flag err port %d flag %X VAL %X\n",
+					gmac_i, MV_ETH_F_MH, 1);
+				return (TPM_FAIL);
+			}
+		}
+		else
+			if (mv_eth_ctrl_flag(gmac_i, MV_ETH_F_MH, 0)){
+				TPM_OS_ERROR(TPM_INIT_MOD, " mv_eth_ctrl_flag err port %d flag %X VAL %X\n",
+					gmac_i, MV_ETH_F_MH, 0);
+				return (TPM_FAIL);
+       		}
+		/* Configure Amber */
+		if (amber_port_num != -1)
+			mv_switch_set_marvell_header_mode(amber_port_num, mh_en);
+	}
+	return (TPM_OK);
+}
+
+int32_t tpm_init_mh_reg_set(void)
+{
+	tpm_gmacs_enum_t gmac_i;
+	uint32_t pp_port_num;
+	uint32_t num_txp = 0, txp_i = 0, tx_reg_i = 0;
+	tpm_db_gmac_func_t gmac_func;
+	uint32_t gmac_mh_en;
+	uint16_t regVal;
+	uint16_t amber_port_vector;
+	uint32_t pnc_vector, uni_vector;
+
+	/* MH Select Tx registers config */
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		if (tpm_db_gmac_func_get(gmac_i, &gmac_func) != TPM_OK) {
+			TPM_OS_ERROR(TPM_INIT_MOD, " tpm_db_gmac_func_get err port %d\n", gmac_i);
+			return (TPM_FAIL);
+		}
+		if (tpm_db_gmac_mh_en_conf_get(gmac_i, &gmac_mh_en) != TPM_OK) {
+			TPM_OS_ERROR(TPM_INIT_MOD, " tpm_db_gmac_mh_en_conf_get err port %d\n", gmac_i);
+			return (TPM_FAIL);
+		}
+		pp_port_num = TPM_GMAC_TO_PP_PORT(gmac_i);
+
+		if (((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_LAN)) &&
+		    gmac_mh_en && (tpm_init.ds_mh_set_conf == TPM_MH_SRC_PNC_RI)) {
+			/* Set MH Tx registers to full table */
+			for (tx_reg_i = 0; tx_reg_i < TPM_TX_MAX_MH_REGS; tx_reg_i++) {
+				regVal = 0;	/* Marvell Header (FID, LearnDisable) fields are both zero */
+				if (tpm_db_port_vector_tbl_info_get(tx_reg_i, &uni_vector,
+								     &amber_port_vector, &pnc_vector) != TPM_OK) {
+						TPM_OS_ERROR(TPM_INIT_MOD, "tpm_db_port_vector_tbl_info_get err tx_reg %d\n",
+								tx_reg_i);
+						return (TPM_FAIL);
+				}
+				regVal = amber_port_vector;
+				if (mvNetaTxMhRegSet(pp_port_num, 0 /*txp */ , tx_reg_i, regVal)) {
+					TPM_OS_ERROR(TPM_INIT_MOD,
+						     "mvNetaTxMhRegSet err pp_port_num %d tx_reg %d regVal 0x%x\n",
+						     pp_port_num, tx_reg_i, regVal);
+					return (TPM_FAIL);
+				}
+			}
+		} else {
+			/* Get GMAC number of tx_modules & default register value */
+			if (gmac_i != TPM_ENUM_PMAC) {
+				num_txp = 1;
+				/* Marvell Header -  FID/LearnDisable fields are zero */
+				/*                   VLANTable field is  (re)set to 'all_other_switch_ports' */
+
+				if (gmac_i == TPM_ENUM_GMAC_0)
+					regVal = 0x3f & (~(1 << TPM_GMAC0_AMBER_PORT_NUM));
+				else
+					regVal = 0x3f & (~(1 << TPM_GMAC1_AMBER_PORT_NUM));
+			} else {
+				if (tpm_db_num_tcont_llid_get(&num_txp) != TPM_OK) {
+					TPM_OS_ERROR(TPM_INIT_MOD,
+						     "tpm_db_num_tcont_llid_get err\n");
+					return (TPM_FAIL);
+				}
+				regVal = 0;
+			}
+
+			/* Set MH_tx registers for all tx_modules */
+			for (txp_i = 0; txp_i < num_txp; txp_i++) {
+				for (tx_reg_i = 0; tx_reg_i < TPM_TX_MAX_MH_REGS; tx_reg_i++)
+					if (mvNetaTxMhRegSet(pp_port_num, txp_i, tx_reg_i, regVal)) {
+						TPM_OS_ERROR(TPM_INIT_MOD,
+						     "mvNetaTxMhRegSet err pp_port_num %d txp %d tx_reg 0x%x, regVal 0x%X\n",
+						     pp_port_num, txp_i, tx_reg_i, regVal);
+						return (TPM_FAIL);
+					 }
+			}
+
+		}
+	}
+
+	return (TPM_OK);
+}
+int32_t tpm_init_get_gmac_queue_rate_limit(void)
+{
+	tpm_db_tx_mod_t tx_mod_i;
+	tpm_gmacs_enum_t gmac_i;
+	uint32_t txp_i = 0;
+	uint32_t size = 0, queue = 0, rate = 0;
+
+	for (tx_mod_i = 0; tx_mod_i < TPM_MAX_NUM_TX_PORTS; tx_mod_i++) {
+		if (TPM_FALSE == tpm_db_gmac_tx_val_get(tx_mod_i)) {
+			TPM_OS_INFO(TPM_INIT_MOD, "tx_mod_i (%d) is invalid\n", tx_mod_i);
+			continue;
+		}
+
+		if (tx_mod_i < TPM_TX_MOD_PMAC_0) {
+			gmac_i = tx_mod_i;
+		} else {
+			gmac_i = TPM_ENUM_PMAC;
+			txp_i = tx_mod_i - TPM_TX_MOD_PMAC_0;
+		}
+		/* get Tx queue bucket size */
+		for (queue = 0; queue < TPM_MAX_NUM_TX_QUEUE; queue++) {
+#ifdef MV_ETH_WRR_NEW
+			size = MV_REG_READ(NETA_TXQ_TOKEN_SIZE_REG(gmac_i, txp_i, queue));
+			rate = MV_REG_READ(NETA_TXQ_REFILL_REG(gmac_i, txp_i, queue));
+#else /* Old WRR/EJP module */
+			/* token size and rate are in the same reg */
+			rate = MV_REG_READ(ETH_TXQ_TOKEN_CFG_REG(gmac_i, txp_i, queue));
+#endif /* MV_ETH_WRR_NEW */
+			TPM_OS_INFO(TPM_INIT_MOD, "gmac_i (%d), txp_i (%d), queue (%d), size (%d), rate (%d)\n",
+				gmac_i, txp_i, queue, size, rate);
+			tpm_db_set_gmac_rate_limit(tx_mod_i, queue, size, rate);
+		}
+	}
+	return (TPM_OK);
+}
+int32_t tpm_init_set_gmac_queue_rate_limit(void)
+{
+	tpm_db_tx_mod_t tx_mod_i;
+	tpm_gmacs_enum_t gmac_i;
+	uint32_t txp_i = 0;
+	uint32_t size = 0, queue = 0, rate = 0;
+
+	for (tx_mod_i = 0; tx_mod_i < TPM_MAX_NUM_TX_PORTS; tx_mod_i++) {
+		if (TPM_FALSE == tpm_db_gmac_tx_val_get(tx_mod_i))
+			continue;
+
+		if (tx_mod_i < TPM_TX_MOD_PMAC_0) {
+			gmac_i = tx_mod_i;
+		} else {
+			gmac_i = TPM_ENUM_PMAC;
+			txp_i = tx_mod_i - TPM_TX_MOD_PMAC_0;
+		}
+		/* get Tx queue bucket size */
+		for (queue = 0; queue < TPM_MAX_NUM_TX_QUEUE; queue++) {
+			tpm_db_get_gmac_rate_limit(tx_mod_i, queue, &size, &rate);
+			TPM_OS_INFO(TPM_INIT_MOD, "gmac_i (%d), txp_i (%d), queue (%d), size (%d), rate (%d)\n",
+				gmac_i, txp_i, queue, size, rate);
+#ifdef MV_ETH_WRR_NEW
+			MV_REG_WRITE(NETA_TXQ_REFILL_REG(gmac_i, txp_i, queue), rate);
+			MV_REG_WRITE(NETA_TXQ_TOKEN_SIZE_REG(gmac_i, txp_i, queue), size);
+#else /* Old WRR/EJP module */
+			MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(gmac_i, txp_i, queue), rate);
+#endif /* MV_ETH_WRR_NEW */
+		}
+	}
+	return (TPM_OK);
+}
+int32_t tpm_init_reset_gmac_queue_rate_limit(void)
+{
+	static uint32_t first_time = 0;
+	int32_t tpm_ret = 0;
+
+	if (first_time == 0) {
+		/* tpm module start up, do not reset gmac q */
+		TPM_OS_INFO(TPM_INIT_MOD, "tpm module start up, get gmac queue rate limit\n");
+		first_time = 1;
+
+		/* get queue rate limit */
+		tpm_ret = tpm_init_get_gmac_queue_rate_limit();
+		IF_ERROR(tpm_ret);
+
+		return (TPM_OK);
+	}
+
+	TPM_OS_INFO(TPM_INIT_MOD, "tpm mib-reset, reset gmac queue rage limit\n");
+
+	/* set queue rate limit */
+	tpm_ret = tpm_init_set_gmac_queue_rate_limit();
+	IF_ERROR(tpm_ret);
+
+	return (TPM_OK);
+}
+
+int32_t tpm_init_mh(void)
+{
+	if (tpm_init_mh_select() != TPM_OK) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "tpm_init_mh_select err\n");
+		return (TPM_FAIL);
+	}
+	if (tpm_init_mh_conf_set() != TPM_OK) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "tpm_init_mh_conf_set err\n");
+		return (TPM_FAIL);
+	}
+	if (tpm_init_mh_reg_set() != TPM_OK) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "tpm_init_mh_reg_set err\n");
+		return (TPM_FAIL);
+	}
+
+	return (TPM_OK);
+}
+
+int32_t tpm_init_bm_pool(void)
+{
+	int status;
+	tpm_gmacs_enum_t gmac_i;
+	uint32_t val, large_buf, small_buf;
+
+	for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		tpm_db_gmac_bm_bufs_conf_get(gmac_i, &val, &large_buf, &small_buf);
+		if (val) {
+			if ((gmac_i == 0 && tpm_init.gmac_port_conf[0].conn == TPM_GMAC_CON_DISC) ||
+			    (gmac_i == 1 && tpm_init.gmac_port_conf[1].conn == TPM_GMAC_CON_DISC))
+				continue;
+
+			if (mv_eth_ctrl_port_started_get(gmac_i)) {
+				TPM_OS_WARN(TPM_INIT_MOD, "port%d already started, port bm_pools will not be updated\n",
+					    gmac_i);
+				continue;
+			}
+
+#ifdef CONFIG_MV_ETH_BM_CPU
+			status = mv_eth_ctrl_port_buf_num_set(TPM_GMAC_TO_PP_PORT(gmac_i), large_buf, small_buf);
+#else
+			status = mv_eth_bm_config_buf_num_set(TPM_GMAC_TO_PP_PORT(gmac_i), large_buf, small_buf);
+#endif
+			if (status) {
+				TPM_OS_ERROR(TPM_INIT_MOD, "BM Pool error gmac(%d) large_buf(%d), small_buf(%d)\n",
+					     gmac_i, large_buf, small_buf);
+				return (TPM_FAIL);
+			}
+		}
+	}
+	return (TPM_OK);
+}
+
+int32_t tpm_init_ipg(void)
+{
+	int status;
+	tpm_gmacs_enum_t gmac_i;
+	uint16_t ipg_val, preamble;
+	uint8_t port;
+	tpm_db_gmac_func_t gmac_func;
+	tpm_db_gmac_conn_t gmac_con;
+	MV_BOOL link_is_up;
+
+
+	for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		tpm_db_gmac_conn_get(gmac_i, &gmac_con);
+		tpm_db_gmac_func_get(gmac_i, &gmac_func);
+
+		if (gmac_func != TPM_GMAC_FUNC_NONE) {
+
+			if ((gmac_i == 0 && tpm_init.gmac0_mh_en != TPM_FALSE && gmac_con == TPM_GMAC_CON_SWITCH_4) ||
+			    (gmac_i == 1 && tpm_init.gmac1_mh_en != TPM_FALSE && gmac_con == TPM_GMAC_CON_SWITCH_5)) {
+				mvNetaPortDisable(gmac_i);
+				mvNetaHwfEnable(gmac_i, 0);
+				ipg_val = mvNetaPortIpgGet(gmac_i);
+				ipg_val -= TPM_MH_LEN;
+				mvNetaPortIpgSet(gmac_i, ipg_val);
+				mvNetaHwfEnable(gmac_i, 1);
+				status = mvNetaPortEnable(gmac_i);
+				if (status != MV_OK) {
+					link_is_up = mvNetaLinkIsUp(gmac_i);
+
+					if (link_is_up)
+						mvNetaPortUp(gmac_i);
+				}
+
+				if (gmac_i == 0)
+					port = TPM_GMAC0_AMBER_PORT_NUM;
+				else
+					port = TPM_GMAC1_AMBER_PORT_NUM;
+
+				/* TODO: Need to check if switch is attached to GMAC */
+				status = mv_switch_get_port_preamble(port, &preamble);
+				if (status) {
+					TPM_OS_ERROR(TPM_INIT_MOD, "Fail to get port(%d) preamble_len\n", port);
+					return (TPM_FAIL);
+				}
+				preamble -= TPM_MH_LEN;
+				status = mv_switch_set_port_preamble(port, preamble);
+				if (status) {
+					TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set port(%d) preamble_len(%d)\n"
+						     , port, preamble);
+					return (TPM_FAIL);
+				}
+			}
+		}
+	}
+
+	return (TPM_OK);
+}
+
+int32_t tpm_init_ethertype_dsa_tag(void)
+{
+	uint16_t  reg_tmp = 0;
+	uint8_t   ret;
+	int       cpu_port = 4;
+	int       frame_mode_reg = 4;
+	int       portetype_reg = 0xf;
+	int       switch_dev_num_reg = 0x1c;
+	int       rsvd2cpu2x_reg = 2;
+	int       rsvd2cpu0x_reg = 3;
+	tpm_db_ety_dsa_enable_t ety_dsa_enable;
+
+	tpm_db_get_ety_dsa_enable(&ety_dsa_enable);
+
+	if (TPM_ETY_DSA_DISABLE == ety_dsa_enable)
+		return TPM_OK;
+
+	/*
+	For switch port 4: change the Frame Mode (Port reg offset 0x04) to Ethertype_DSA.
+	For switch port 4: set Port EType register (Port reg offset 0x0F) to 0xDABC.
+	Set zero to MGMT Enables 0x register (Global 2 offset 0x03) and MGMT Enables 2x register (Global 2 offset 0x02).
+	*/
+
+	/* get Frame Mode reg from HW */
+	ret = mv_switch_reg_read(cpu_port, frame_mode_reg, MV_SWITCH_PORT_ACCESS, &reg_tmp);
+	if (0 != ret) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to get cpu port frame mode reg, ret(%d)\n", ret);
+		return (TPM_FAIL);
+	}
+
+	/* set bits 8, 9 to 11, as Ethertype_DSA */
+	reg_tmp |= (3 << 8);
+	ret = mv_switch_reg_write(cpu_port, frame_mode_reg, MV_SWITCH_PORT_ACCESS, reg_tmp);
+	if (0 != ret) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set cpu port frame mode reg, ret(%d)\n", ret);
+		return (TPM_FAIL);
+	}
+
+	/* set PortEType reg to HW */
+	reg_tmp = TPM_ETHERTYPE_DSA_TAG;
+	ret = mv_switch_reg_write(cpu_port, portetype_reg, MV_SWITCH_PORT_ACCESS, reg_tmp);
+	if (0 != ret) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set cpu port PortEType reg, ret(%d)\n", ret);
+		return (TPM_FAIL);
+	}
+
+	/* get switch_dev_num value reg from HW */
+	ret = mv_switch_reg_read(0, switch_dev_num_reg, MV_SWITCH_GLOBAL_ACCESS, &reg_tmp);
+	if (0 != ret) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to get switch_dev_num reg, ret(%d)\n", ret);
+		return (TPM_FAIL);
+	}
+	tpm_db_set_switch_dev_num((reg_tmp & 0x1f));
+
+	/* set PortEType reg to HW */
+	reg_tmp = 0;
+	ret = mv_switch_reg_write(0, rsvd2cpu2x_reg, MV_SWITCH_GLOBAL2_ACCESS, reg_tmp);
+	if (0 != ret) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set zero to rsvd2cpu2x reg, ret(%d)\n", ret);
+		return (TPM_FAIL);
+	}
+	ret = mv_switch_reg_write(0, rsvd2cpu0x_reg, MV_SWITCH_GLOBAL2_ACCESS, reg_tmp);
+	if (0 != ret) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "Fail to set zero to rsvd2cpu0x reg, ret(%d)\n", ret);
+		return (TPM_FAIL);
+	}
+
+	return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_init_gmac_loopback()
+*
+* DESCRIPTION:      Initialize the GMAC to loopback mode if necessary, and force
+*		gmac linkup to 1G
+*
+* INPUTS:
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+int32_t tpm_init_gmac_loopback(int port)
+{
+	uint32_t regVal;
+
+	mvNetaPortDisable(port);
+	mvNetaHwfEnable(port, 0);
+
+	mvNetaForceLinkModeSet(port, 1, 0);/*for link up*/
+	mvNetaSpeedDuplexSet(port, MV_ETH_SPEED_1000, MV_ETH_DUPLEX_FULL);/*set 1G*/
+
+	mvNetaHwfEnable(port, 1);
+	mvNetaPortEnable(port);
+
+	MV_REG_WRITE(NETA_GMAC_CTRL_1_REG(port), 0x31); /* set gmac to loopback mode */
+
+	regVal = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(port));
+	regVal |=  NETA_FORCE_LINK_FAIL_MASK;  			/* enable Force Link Pass 	*/
+	regVal |=  NETA_SET_GMII_SPEED_1000_MASK;  		/* set GMII Speed 1000		*/
+	regVal &= ~NETA_ENABLE_SPEED_AUTO_NEG_MASK;  		/* disable AutoNeg speed 	*/
+	regVal |=  NETA_SET_FLOW_CONTROL_MASK;  		/* enable AutoNeg FC		*/
+	regVal |=  NETA_FLOW_CONTROL_ADVERTISE_MASK;  		/* enable advertise FC		*/
+	regVal &= ~NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;  	/* disable AutoNeg FC		*/
+	regVal |=  NETA_SET_FULL_DUPLEX_MASK;			/* enable full duplex mode	*/
+	regVal &= ~NETA_ENABLE_DUPLEX_AUTO_NEG_MASK;		/* disable duplex AutoNeg 	*/
+	MV_REG_WRITE(NETA_GMAC_AN_CTRL_REG(port), regVal);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_init_system_mib_reset()
+*
+* DESCRIPTION:      Initialize the dynamic parts of the system hardware
+*
+* INPUTS:
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+int32_t tpm_init_system_mib_reset(tpm_reset_level_enum_t reset_type)
+{
+	tpm_pnc_ranges_t cur_range = TPM_INVALID_RANGE, next_range = 0;
+	tpm_db_pnc_range_t next_range_data;
+	tpm_db_pnc_range_conf_t range_conf;
+	uint32_t switch_init;
+	int32_t ret_code;
+	tpm_db_ttl_illegal_action_t ttl_illegal_action;
+	tpm_db_tcp_flag_check_t tcp_flag_check;
+	tpm_gmacs_enum_t gmac_i;
+	tpm_db_gmac_func_t gfunc;
+
+	TPM_OS_DEBUG(TPM_INIT_MOD, "\n");
+
+	ret_code = tpm_db_mod2_setup();
+	IF_ERROR(ret_code);
+
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		tpm_db_gmac_func_get(gmac_i, &gfunc);
+		if (gfunc != TPM_GMAC_FUNC_NONE) {
+			ret_code = tpm_mod2_mac_inv(gmac_i);
+			IF_ERROR(ret_code);
+		}
+
+		ret_code = tpm_mod2_split_mod_init(gmac_i);
+		IF_ERROR(ret_code);
+	}
+	/* Init Tx queue rate limit */
+	ret_code = tpm_init_reset_gmac_queue_rate_limit();
+	IF_ERROR(ret_code);
+
+	/* Init Amber Switch */
+	tpm_db_switch_init_get(&switch_init);
+	if (switch_init)
+		tpm_init_switch();
+	else
+		/* Init GMAC1 in loopback mod if no switch*/
+		tpm_init_gmac_loopback(TPM_ENUM_GMAC_1);
+	/*Init TX scheduling */
+	ret_code = tpm_init_tx_queue_sched();
+	IF_ERROR(ret_code);
+
+	/* Initialize (wipe out) the PNC ranges in PnC HW */
+	tpm_db_pnc_rng_val_get_next(cur_range, &next_range, &next_range_data);
+	TPM_OS_DEBUG(TPM_INIT_MOD, "next_range(%d)\n", next_range);
+	while (next_range != TPM_INVALID_RANGE) {
+		if (reset_type >= next_range_data.pnc_range_conf.min_reset_level) {
+			ret_code = tpm_pncl_range_reset(next_range);
+			IF_ERROR(ret_code);
+		}
+		cur_range = next_range;
+		tpm_db_pnc_rng_val_get_next(cur_range, &next_range, &next_range_data);
+		TPM_OS_DEBUG(TPM_INIT_MOD, "next_range(%d)\n", next_range);
+	}
+	/* Initialize the PNC Hardcoded Ranges */
+	/* @Wilson
+	   New bi-direction range: NUM_VLAN_TAGS three hardcoded rules
+	*/
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_NUM_VLAN_TAGS, &range_conf);
+	if (ret_code == TPM_DB_OK) {
+		ret_code = tpm_proc_l2_num_vlan_tags_init();
+		IF_ERROR(ret_code);
+	} else
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_NUM_VLAN_TAGS);
+
+	tpm_db_get_ttl_illegal_action(&ttl_illegal_action);
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TTL, &range_conf);
+	if (TPM_TTL_ZERO_ACTION_NOTHING == ttl_illegal_action) {
+		if (ret_code == TPM_DB_OK) {
+			/* do not check ttl, no need to create ttl range */
+			TPM_OS_WARN(TPM_INIT_MOD, "do not check ttl, no need to create ttl range\n");
+		}
+	} else {
+		if ((ret_code != TPM_DB_OK) || (range_conf.range_size < 4)) {
+			/* check ttl, need to create ttl range */
+			TPM_OS_WARN(TPM_INIT_MOD, "check ttl, need to create ttl range with size of 4\n");
+		} else {
+			ret_code = tpm_proc_ipv4_ttl_init(ttl_illegal_action);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_L4_MC_DS, &range_conf);
+	if (ret_code == TPM_DB_OK) {
+		if (range_conf.range_size > 1)
+			/* SIZE too big, it is a waste */
+			TPM_OS_WARN(TPM_INIT_MOD, "TPM_PNC_IPV6_L4_MC_DS SIZE should be 1, too big now, it is a waste\n");
+		ret_code = tpm_proc_ipv6_l4_mc_ds_init();
+		IF_ERROR(ret_code);
+	} else
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_IPV6_L4_MC_DS);
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_MC_SIP, &range_conf);
+	if (ret_code == TPM_DB_OK) {
+		if (range_conf.range_size > 8)
+			/* SIZE too big, it is a waste */
+			TPM_OS_WARN(TPM_INIT_MOD, "TPM_PNC_IPV6_MC_SIP SIZE should be 8, too big now, it is a waste\n");
+		if (range_conf.range_size < 8)
+			/* SIZE too small, it might not be enough */
+			TPM_OS_WARN(TPM_INIT_MOD, "TPM_PNC_IPV6_MC_SIP SIZE should be 8, a little bit smaller now\n");
+		ret_code = tpm_proc_ipv6_mc_sip_init();
+		IF_ERROR(ret_code);
+	} else
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_IPV6_L4_MC_DS);
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_HOPL, &range_conf);
+	if (TPM_TTL_ZERO_ACTION_NOTHING == ttl_illegal_action) {
+		if (ret_code == TPM_DB_OK) {
+			/* do not check ttl, no need to create hoplimit range */
+			TPM_OS_WARN(TPM_INIT_MOD, "do not check hoplimit, no need to create hoplimit range\n");
+		}
+	} else {
+		if ((ret_code != TPM_DB_OK) || (range_conf.range_size < 3)) {
+			/* check hoplimit, need to create hoplimit range */
+			TPM_OS_WARN(TPM_INIT_MOD, "check hoplimit, need to create hoplimit range with size of 3\n");
+		} else {
+			ret_code = tpm_proc_ipv6_hoplimit_init(ttl_illegal_action);
+			IF_ERROR(ret_code);
+		}
+	}
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IGMP, &range_conf);
+	if (ret_code == TPM_DB_OK) {
+		ret_code = tpm_proc_ipv4_igmp_init();
+		IF_ERROR(ret_code);
+	} else
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_IGMP);
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_PROTO, &range_conf);
+	if (ret_code == TPM_DB_OK) {
+		ret_code = tpm_proc_ipv4_proto_init();
+		IF_ERROR(ret_code);
+	} else
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_IPV4_PROTO);
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_FRAG, &range_conf);
+	if (ret_code == TPM_DB_OK) {
+		ret_code = tpm_proc_ipv4_frag_init();
+		IF_ERROR(ret_code);
+	} else
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_IPV4_FRAG);
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CATCH_ALL, &range_conf);
+	if (ret_code == TPM_DB_OK) {
+		ret_code = tpm_proc_catch_all_init();
+		IF_ERROR(ret_code);
+	} else
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_CATCH_ALL);
+
+	tpm_db_get_tcp_flag_check(&tcp_flag_check);
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TCP_FLAG, &range_conf);
+	if (TPM_TCP_FLAG_NOT_CHECK == tcp_flag_check) {
+		if (ret_code == TPM_DB_OK) {
+			/* do not check tcp flag, no need to create tcp flag range */
+			TPM_OS_WARN(TPM_INIT_MOD, "do not check tcp flag, no need to create tcp flag range\n");
+		}
+	} else {
+		if ((ret_code != TPM_DB_OK) || (range_conf.range_size < 4)) {
+			/* check tcp flag, need to create tcp flag range */
+			TPM_OS_WARN(TPM_INIT_MOD, "check tcp flag, need to create tcp flag range with size of 4\n");
+		} else {
+			ret_code = tpm_proc_tcp_flag_init();
+			IF_ERROR(ret_code);
+		}
+	}
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_VIRT_UNI, &range_conf);
+	if (ret_code == TPM_DB_OK) {
+		ret_code = tpm_proc_virt_uni_init();
+		IF_ERROR(ret_code);
+	} else
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) not initialized\n", TPM_PNC_VIRT_UNI);
+
+	ret_code = tpm_proc_mtu_init();
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_init_ethertype_dsa_tag();
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_fc_engine_init();
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_init_vlan_etype_set()
+*
+* DESCRIPTION:      Set configured VLAN ETYs in the TPM DB and hardware
+*
+* INPUTS:
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+int32_t tpm_init_vlan_etype_set(void)
+{
+	int32_t ret_code = TPM_OK;
+	uint32_t etype_sel;
+	int i;
+
+	for (i = 0; i < TPM_NUM_VLAN_ETYPE_REGS; i++) {
+		if (tpm_init.vlan_etypes[i] != MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+			ret_code = tpm_mod2_tpid_get(tpm_init.vlan_etypes[i], &etype_sel);
+			IF_ERROR(ret_code);
+		}
+
+	}
+
+	return (ret_code);
+}
+
+/*******************************************************************************
+* tpm_pnc_init_temp()
+*
+* DESCRIPTION:      when TPM is responsible to configure the PNC:
+*                   * PNC clean ALL
+*                   * Add entry #0 for HW forwarding enabled
+*
+* INPUTS:
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+void tpm_pnc_init_temp(void)
+{
+	int rc;
+	unsigned int config_pnc_parser_val;
+
+	/* get the config_pnc_parser value */
+	config_pnc_parser_val = mv_eth_ctrl_pnc_get();
+	if (config_pnc_parser_val == 0) {
+		rc = tcam_hw_init();
+		if (rc != TPM_OK)
+			TPM_OS_WARN(TPM_INIT_MOD, " recvd ret_code(%d)\n", rc);
+		pnc_def_entry_init(0, 0);	/* rxq =0 */
+	}
+	return;
+}
+
+/*******************************************************************************
+* tpm_init_system_init()
+*
+* DESCRIPTION:      Initialize the system hardware.
+*                   First all the one-time Inits are performed,
+*                   and then a call to the dynamic sections is performed by calling mib_reset
+*
+* INPUTS:
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+int32_t tpm_init_system_init(tpm_reset_level_enum_t reset_type)
+{
+	int32_t ret_code;
+	tpm_db_gmac_func_t gfunc;
+	tpm_db_gmac_conn_t gconn = TPM_GMAC_CON_DISC;
+	tpm_gmacs_enum_t gmac_i;
+	uint16_t txp;
+
+	TPM_OS_DEBUG(TPM_INIT_MOD, "\n");
+
+	/* Init Vlan Ethertype Registers */
+	ret_code = tpm_init_vlan_etype_set();
+	IF_ERROR(ret_code);
+
+	/* Init HW Modification table and registers */
+	for (gmac_i = 0; gmac_i < TPM_MAX_NUM_GMACS; gmac_i++) {
+		if (!INIT_GMAC_VALID(gmac_i))
+			continue;
+
+		tpm_db_gmac_func_get(gmac_i, &gfunc);
+		if (gmac_i != TPM_ENUM_PMAC)
+			tpm_db_gmac_conn_get(gmac_i, &gconn);
+
+		if (gfunc != TPM_GMAC_FUNC_NONE &&
+				(gconn != TPM_GMAC_CON_DISC || gmac_i == TPM_ENUM_PMAC)) {
+			/*ret_code = tpm_mod2_inv_all(); */
+			ret_code = tpm_mod2_mac_inv(gmac_i);
+			IF_ERROR(ret_code);
+			if (gmac_i == TPM_ENUM_PMAC) {
+				for (txp = 0; txp < 8; txp++)
+					ret_code = tpm_mod2_registers_init(gmac_i, txp);
+			} else
+				ret_code = tpm_mod2_registers_init(gmac_i, 0);
+
+			IF_ERROR(ret_code);
+		}
+	}
+	/* temporarily = clean the PNC if needed */
+	tpm_pnc_init_temp();
+
+	/* Init hardware forwarding configuration */
+	tpm_init_hwf_set();
+
+	/* Init tx_queue sizes */
+	tpm_init_txq_size_set();
+
+	/* Init rx_queue sizes */
+	tpm_init_rxq_size_set();
+
+	/* Init marvell header configuration */
+	ret_code = tpm_init_mh();
+	IF_ERROR(ret_code);
+
+	/* Init Buffer Mngmt Pool configuration */
+	tpm_init_bm_pool();
+
+	/* Init IPG */
+	tpm_init_ipg();
+
+	ret_code = tpm_init_system_mib_reset(reset_type);
+	IF_ERROR(ret_code);
+
+	return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_module_init()
+*
+* DESCRIPTION:      Initialize the TPM module
+*
+* INPUTS:
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+int32_t tpm_module_init(void)
+{
+	int32_t ret_code;
+
+	/* Reset DB */
+	ret_code = tpm_db_init();
+	if (ret_code != TPM_DB_OK) {
+		printk(KERN_ERR "Error in Init DB\n");
+		return (TPM_FAIL);
+	}
+
+	ret_code = tpm_mod2_init();
+	if (ret_code != TPM_OK) {
+		printk(KERN_ERR "Error in Init MOD2\n");
+		return (TPM_FAIL);
+	}
+
+	return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_module_start()
+*
+* DESCRIPTION:      Initialize the TPM module
+*
+* INPUTS:
+
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+int32_t tpm_module_start(tpm_init_t *tpm_init)
+{
+	int32_t ret_code;
+	static uint32_t first_time = 0;
+
+	if (first_time == 0) {
+
+		/* Initialize XML configuration to the init database */
+		tpm_init_config_params_init(tpm_init);
+
+		/* Update database hardcoded configuration */
+		ret_code = tpm_init_config_params_update();
+		if (ret_code != TPM_OK) {
+			printk(KERN_ERR "Error in Init Configuration \n");
+			return (TPM_FAIL);
+		}
+
+		/* Check all Configuration params are consistent */
+		ret_code = tpm_init_info_validate();
+		if (ret_code != TPM_OK) {
+			printk(KERN_ERR "Error in Init Info Validate \n");
+			return (TPM_FAIL);
+		}
+
+		/* Transform raw form Init Info into TPM format and update DB
+		 * Involves internal mapping logic */
+		ret_code = tpm_init_info_set();
+		if (ret_code != TPM_OK) {
+			printk(KERN_ERR "Error in  Init Info Set \n");
+			return (TPM_FAIL);
+		}
+
+		/* Initialize TPM Locks */
+		tpm_init_locks_init();
+
+		/* Initialize System (HW) */
+		/* In HW reset all PnC Ranges, except for those that should never be reset (e.g. PNC_INIT_US for NFS) */
+		ret_code = tpm_init_system_init(TPM_ENUM_RESET_LEVEL1);
+		if (ret_code != TPM_OK) {
+			printk(KERN_ERR "\n= TPM Module - Error in System Init =\n");
+			return (TPM_FAIL);
+		} else {
+			printk(KERN_INFO "\n= TPM Module Init ended successfully =\n");
+			tpm_db_init_done_set();
+		}
+
+	} else
+		TPM_OS_INFO(TPM_INIT_MOD, " skipped\n");
+
+	first_time++;
+
+	return (TPM_OK);
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.h
new file mode 100755
index 0000000..311a5be
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_init.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_init.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1.1.1
+*
+*
+*******************************************************************************/
+#ifndef _TPM_INIT_H_
+#define _TPM_INIT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#include "boardEnv/mvBoardEnvLib.h"
+
+/************/
+/*  APIs    */
+/************/
+
+int32_t tpm_init_pncranges_set(tpm_reset_level_enum_t reset_type);
+int32_t tpm_init_system_init(tpm_reset_level_enum_t reset_type);
+int32_t tpm_init_system_mib_reset(tpm_reset_level_enum_t reset_type);
+int32_t tpm_init_api_rng_init_all(void);
+int32_t tpm_module_init(void);
+int32_t tpm_module_start(tpm_init_t *tpm_init);
+void tpm_init_params_get(tpm_init_t *tpm_init_params);
+
+#endif /* _TPM_INIT_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_internal_types.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_internal_types.h
new file mode 100755
index 0000000..947432a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_internal_types.h
@@ -0,0 +1,626 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_internal_types.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.3
+*
+*
+*******************************************************************************/
+
+#ifndef _TPM_INT_TYPES_H_
+#define _TPM_INT_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+
+#define TPM_MAX_NUM_GEM_PORT		(4096)
+
+#define TPM_CHAIN_NUM_UNLIMITED		(0x1000)
+
+#define FROM_SPEC_UNI(src)		(src >= TPM_SRC_PORT_UNI_0 && src <= TPM_SRC_PORT_UNI_VIRT)
+
+/* PNC Target TXP, in exact numbering scheme, do not change !! */
+typedef enum {
+	TPM_INVALID_PNC_TRG = -1,
+	TPM_PNC_TRG_CPU,
+	TPM_PNC_TRG_GMAC0,
+	TPM_PNC_TRG_GMAC1,
+	TPM_PNC_TRG_PMAC0,
+	TPM_PNC_TRG_PMAC1,
+	TPM_PNC_TRG_PMAC2,
+	TPM_PNC_TRG_PMAC3,
+	TPM_PNC_TRG_PMAC4,
+	TPM_PNC_TRG_PMAC5,
+	TPM_PNC_TRG_PMAC6,
+	TPM_PNC_TRG_PMAC7
+} tpm_pnc_trg_t;
+
+typedef enum {
+	TPM_INVALID_GMAC = -1,
+	TPM_ENUM_GMAC_0,
+	TPM_ENUM_GMAC_1,
+	TPM_ENUM_PMAC,
+	TPM_MAX_GMAC = TPM_ENUM_PMAC,
+	TPM_MAX_NUM_GMACS
+} tpm_gmacs_enum_t;
+
+typedef enum {
+	TPM_INT_CALL = 0,
+	TPM_EXT_CALL
+} tpm_caller_t;
+
+
+#define TPM_MAX_VID			(4096)	/* legal VLAN ID = 0-4095 */
+#define TPM_MAX_NUM_CTC_PRECEDENCE		(8)	
+
+#define PON_PORT			(2)
+#define SW_GMAC_0			(0)
+#define SW_GMAC_1			(1)
+
+
+/* MH configuration - fixed values - will be supported via xml params */
+#define TPM_GMAC0_AMBER_PORT_NUM	4
+#define TPM_GMAC1_AMBER_PORT_NUM	5
+
+/* Hardware GMAC number to HAL Port number conversion, note that the numbers are currently equal */
+#define TPM_GMAC0_PP_PORT_NUM		0
+#define TPM_GMAC1_PP_PORT_NUM		1
+#define TPM_PMAC_PP_PORT_NUM		2
+
+/* retrieve the num of TCONTs and LLIDs from the .config - kernel global params */
+#define TPM_GPON_MAX_NUM_OF_T_CONTS	(CONFIG_MV_PON_TCONTS)
+#define TPM_EPON_MAX_MAC_NUM		(CONFIG_MV_EPON_LLID)
+/* Currently hardcoded, must update if pp_port_numbers will be reshuffled */
+#define TPM_GMAC_TO_PP_PORT(x)		(x)
+
+#define TPM_NUM_MC_VID_BITS		     (2)
+
+#define TPM_NUM_IPV6_SUBFLOW_BITS_P1 (1)
+#define TPM_NUM_IPV6_SUBFLOW_BITS_P2 (2)
+#define TPM_NUM_IPV6_SUBFLOW_BITS    (TPM_NUM_IPV6_SUBFLOW_BITS_P1 + TPM_NUM_IPV6_SUBFLOW_BITS_P2)
+
+#define TPM_NUM_IPV6_MC_SIP_BITS_P1 (1)
+#define TPM_NUM_IPV6_MC_SIP_BITS_P2 (2)
+#define TPM_NUM_IPV6_MC_SIP_BITS    (TPM_NUM_IPV6_MC_SIP_BITS_P1 + TPM_NUM_IPV6_MC_SIP_BITS_P2)
+
+#define ILLEGAL_API(api_type)		((api_type >= TPM_API_TYPE_ILLEGAL) || (api_type < 0))
+
+#define TPM_INTERNAL_OWNER_ID		(0xABBACDDC)
+
+
+typedef enum {
+	TPM_INVALID_SECTION = -1,
+	TPM_PNC_MAC_LEARN_ACL,
+	TPM_CPU_LOOPBACK_ACL,
+	TPM_L2_PRIM_ACL,
+	TPM_L3_TYPE_ACL,
+	TPM_IPV4_ACL,
+	TPM_IPV4_MC,
+	TPM_IPV6_GEN_ACL,
+	TPM_IPV6_DIP_ACL,
+	TPM_IPV6_MC_ACL,
+	TPM_IPV6_NH_ACL,
+	TPM_L4_ACL,
+	TPM_CNM_MAIN_ACL,
+	TPM_MAX_NUM_API_SECTIONS	/* Equals to number of entries in enum */
+} tpm_api_sections_t;
+
+#define ILLEGAL_API_SEC(api_sec)	((api_sec >= TPM_MAX_NUM_API_SECTIONS) || (api_sec < 0))
+
+typedef enum {
+	TPM_AI_DS_MAC_IP_SES,
+	TPM_AI_US_MAC_IP_SES,
+	TPM_AI_IPV6_DS_SIP_SES,
+	TPM_AI_IPV6_US_SIP_SES,
+	TPM_AI_IPV6_DS_NH_SES,
+	TPM_AI_IPV6_US_NH_SES,
+	TPM_AI_IPV6_DS_5T_SES,
+	TPM_AI_IPV6_US_5T_SES
+} tpm_ai_ses_type_t;
+
+typedef enum {
+	SES_IN,
+	SES_OUT
+} tpm_ai_con_type_t;
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+
+/* Amber related */
+#define  TPM_AMBER_MH_EN_MASK              (0x800)
+/* End Amber related */
+
+/* Following are derivatives of the TPM_PARSE_FLAGs in tpm_types.h */
+#define TPM_PARSE_FLAG_TAG1_MASK	(TPM_PARSE_FLAG_TAG1_TRUE | TPM_PARSE_FLAG_TAG1_FALSE)
+#define TPM_PARSE_FLAG_TAG2_MASK	(TPM_PARSE_FLAG_TAG2_TRUE | TPM_PARSE_FLAG_TAG2_FALSE)
+#define TPM_PARSE_FLAG_MTM_MASK		(TPM_PARSE_FLAG_MTM_TRUE | TPM_PARSE_FLAG_MTM_FALSE)
+#define TPM_PARSE_FLAG_TO_CPU_MASK	(TPM_PARSE_FLAG_TO_CPU_TRUE | TPM_PARSE_FLAG_TO_CPU_FALSE)
+#define TPM_PARSE_FLAG_L4P_MASK		(TPM_PARSE_FLAG_L4_TCP | TPM_PARSE_FLAG_L4_UDP)
+#define TPM_PARSE_FLAG_PPPOE_MASK	(TPM_PARSE_FLAG_PPPOE_TRUE | TPM_PARSE_FLAG_PPPOE_FALSE)
+#define TPM_PARSE_FLAG_PPPOE_ADD_MASK	(TPM_PARSE_FLAG_PPPOE_ADD_TRUE | TPM_PARSE_FLAG_PPPOE_ADD_FALSE)
+#define TPM_PARSE_FLAG_NO_PROTO_MASK	(TPM_PARSE_FLAG_NO_PROTO_TRUE | TPM_PARSE_FLAG_NO_PROTO_FALSE)
+#define TPM_PARSE_FLAG_NO_FRAG_MASK	(TPM_PARSE_FLAG_NO_FRAG_TRUE | TPM_PARSE_FLAG_NO_FRAG_FALSE)
+#define TPM_PARSE_FLAG_MC_VID_MASK	(TPM_PARSE_FLAG_MC_VID_TRUE | TPM_PARSE_FLAG_MC_VID_FALSE)
+#define TPM_PARSE_FLAG_NH2_ITER_MASK	(TPM_PARSE_FLAG_NH2_ITER_TRUE | TPM_PARSE_FLAG_NH2_ITER_FALSE)
+#define TPM_PARSE_FLAG_CNM_IPV4_MASK	(TPM_PARSE_FLAG_CNM_IPV4_TRUE | TPM_PARSE_FLAG_CNM_IPV4_FALSE)
+#define TPM_PARSE_FLAG_SPLIT_MOD_MASK	(TPM_PARSE_FLGA_SPLIT_MOD_TRUE | TPM_PARSE_FLGA_SPLIT_MOD_FALSE)
+
+#define TPM_L2_PARSE_BM_MASK		\
+		(TPM_L2_PARSE_MAC_DA | TPM_L2_PARSE_MAC_SA | TPM_L2_PARSE_ONE_VLAN_TAG | TPM_L2_PARSE_TWO_VLAN_TAG |\
+		TPM_L2_PARSE_ETYPE | TPM_L2_PARSE_PPPOE_SES | TPM_L2_PARSE_PPP_PROT | TPM_L2_PARSE_GEMPORT)
+#define TPM_L3_PARSE_BM_MASK		(TPM_L2_PARSE_ETYPE | TPM_L2_PARSE_PPPOE_SES | TPM_L2_PARSE_PPP_PROT)
+#define TPM_IPV4_PARSE_BM_MASK		\
+		(TPM_IPv4_PARSE_SIP | TPM_IPv4_PARSE_DIP | TPM_IPv4_PARSE_DSCP | TPM_IPv4_PARSE_PROTO |\
+		TPM_PARSE_L4_SRC|TPM_PARSE_L4_DST)
+#define TPM_IPV6_GEN_BM_MASK		(TPM_IPv6_PARSE_SIP | TPM_IPv6_PARSE_DSCP | TPM_IPv6_PARSE_HOPL)
+#define TPM_IPV6_L4_BM_MASK			(TPM_PARSE_L4_SRC | TPM_PARSE_L4_DST)
+
+/* in PARSE_FLAG_BM - bit#0 and bit#1 - TRUE and FALSE - should not be set simultaneously */
+#define TPM_PARSE_FLAG_CHECK_TRUE_FALSE		(0x0003)
+/* number of pairs of TRUE/FALSE bits present in the  PARSE_FLAG_BM:
+   TAG1 / TAG2 / MTM / TO_CPU / L2                                   */
+#define  TPM_PARSE_FLAG_CHECK_FIELD_NUMBER	(6)
+
+/* Following additional TPM_PARSE_FLAGs  for internal use, they must co-exist (not overlap)
+   with existing TPM_PARSE_FLAGs in types.h */
+#define TPM_PARSE_FLAG_UNI_PORT_PARSE		(0x00000001LL)
+#define TPM_PARSE_FLAG_PPPOE_ADD_TRUE		(0x00000002LL)
+#define TPM_PARSE_FLAG_PPPOE_ADD_FALSE		(0x00000004LL)
+#define TPM_PARSE_FLAG_NO_PROTO_TRUE		(0x00000008LL)
+#define TPM_PARSE_FLAG_NO_PROTO_FALSE		(0x00000010LL)
+#define TPM_PARSE_FLAG_NO_FRAG_TRUE			(0x00000020LL)
+#define TPM_PARSE_FLAG_NO_FRAG_FALSE		(0x00000040LL)
+#define TPM_PARSE_FLAG_MC_VID_TRUE			(0x00000080LL)
+#define TPM_PARSE_FLAG_MC_VID_FALSE			(0x00000100LL)
+#define TPM_PARSE_FLAG_MC_VID_PARSE			(0x00000200LL)
+#define TPM_PARSE_FLAG_NH2_ITER_TRUE		(0x00000400LL)
+#define TPM_PARSE_FLAG_NH2_ITER_FALSE		(0x00000800LL)
+#define TPM_PARSE_FLAG_IPV6_SUBFLOW_PARSE	(0x00001000LL)
+#define TPM_PARSE_FLAG_CNM_IPV4_TRUE        (0x00002000LL)
+#define TPM_PARSE_FLAG_CNM_IPV4_FALSE       (0x00004000LL)
+#define TPM_PARSE_FLGA_SPLIT_MOD_TRUE       (0x00008000LL)
+#define TPM_PARSE_FLGA_SPLIT_MOD_FALSE      (0x00010000LL)
+#define TPM_PARSE_FLAG_IPV4_PRE_KEY_PARSE   (0x00020000LL)
+#define TPM_PARSE_FLAG_CNM_PREC_PARSE       (0x00040000LL)
+#define TPM_PARSE_FLAG_IPV6_MC_SIP_PARSE    (0x00080000LL)
+
+/* Following additional TPM_ACTIONs for internal use, they must co-exist (not overlap)
+   with existing TPM_ACTIONs in types.h */
+#define TPM_ACTION_SET_UNI_PORT			(0x00000001LL)	/* Set UNI Port */
+#define TPM_ACTION_SET_TAG1				(0x00000002LL)	/* Set TAG1 */
+#define TPM_ACTION_SET_TAG2				(0x00000004LL)	/* Set TAG2 */
+#define TPM_ACTION_SET_L4P_TOG_UDP		(0x00000008LL)	/* Set L4 proto toggle bit to '1' (=UDP) */
+#define TPM_ACTION_SET_L4P_TOG_TCP		(0x00000010LL)	/* Set L4 proto toggle bit to '0' (=TCP) */
+#define TPM_ACTION_UNSET_DNRT			(0x00000020LL)	/* Unset DNRT bit */
+#define TPM_ACTION_UNSET_MC_VID_VALID	(0x00000040LL)	/* Unset MC_VID valid bit */
+#define TPM_ACTION_SET_PPPOE			(0x00000080LL)	/* Set PPPOE packet */
+#define TPM_ACTION_UNSET_PPPOE			(0x00000100LL)	/* Set not PPPOE packet */
+#define TPM_ACTION_SET_NO_PROTO_CHECK	(0x00000200LL)	/* Set no IPV4 proto check */
+#define TPM_ACTION_SET_NO_FRAG_CHECK	(0x00000400LL)	/* Set no IPV4 fragment check */
+#define TPM_ACTION_SET_ADD_PPPOE		(0x00000800LL)	/* Set PPPOE header is added */
+#define TPM_ACTION_UNSET_UNI_PORT		(0x00001000LL)	/* UnSet UNI Port */
+#define TPM_ACTION_SET_NH2_ITER			(0x00002000LL)	/* Set NH2 iteration */
+#define TPM_ACTION_UNSET_NH2_ITER		(0x00004000LL)	/* Unset NH2 iteration */
+#define TPM_ACTION_SET_IPV6_SUBFLOW     (0x00008000LL)	/* Set IPV6 subflow */
+#define TPM_ACTION_UNSET_IPV6_SUBFLOW   (0x00010000LL)	/* Unset IPV6 subflow */
+#define TPM_ACTION_SET_CNM_IPV4         (0x00020000LL)
+#define TPM_ACTION_UNSET_CNM_IPV4       (0x00040000LL)
+#define TPM_ACTION_SET_SPLIT_MOD        (0x00080000LL)
+#define TPM_ACTION_UNSET_SPLIT_MOD      (0x00100000LL)
+#define TPM_ACTION_SET_IPV4_PRE_KEY     (0x00200000LL)
+#define TPM_ACTION_UNSET_IPV4_PRE_KEY   (0x00400000LL)
+#define TPM_ACTION_SET_CNM_PREC         (0x00800000LL)
+#define TPM_ACTION_UNSET_CNM_PREC       (0x01000000LL)
+
+#define     TPM_MAX_WRR_WEIGHT             (255)
+
+#define      TPM_MH_LEN                    (2)
+#define      TPM_DA_LEN                    (6)
+#define      TPM_SA_LEN                    (6)
+#define      TPM_VLAN_LEN                  (4)
+#define      TPM_ETYPE_LEN                 (2)
+#define      TPM_PPPOE_HDR_LEN             (8)
+#define      TPM_PPPOE_SES_LEN             (2)
+#define      TPM_PPP_PROTO_LEN             (2)
+#define      TPM_IPV4_VER_IHL_LEN          (1)
+#define      TPM_IPV4_DSCP_LEN             (1)
+#define      TPM_IPV4_TOTLEN_LEN           (2)
+#define      TPM_IPV4_IDENT_LEN            (2)
+#define      TPM_IPV4_FLAG_OFF_LEN         (2)
+#define      TPM_IPV4_TTL_LEN              (1)
+#define      TPM_IPV4_PROTO_LEN            (1)
+#define      TPM_IPV4_SIP_LEN              (4)
+#define      TPM_IPV4_DIP_LEN              (4)
+#define      TPM_IPV4_L4_PORT_LEN          (2)
+
+#define      TPM_TCP_DUMMY_LEN             (13)
+#define      TPM_TCP_FLAGS_LEN             (1)
+
+#define      TPM_IPV6_VER_DSCP_LEN         (1)
+#define      TPM_IPV6_DSCP_FLOW_LEN        (1)
+#define      TPM_IPV6_FLOW_LEN             (2)
+#define      TPM_IPV6_PLLEN_LEN			   (2)
+#define      TPM_IPV6_NH_LEN               (1)
+#define      TPM_IPV6_HOPLIM_LEN           (1)
+#define      TPM_IPV6_SIP_LEN			   (16)
+#define      TPM_IPV6_DIP_LEN			   (16)
+#define      TPM_L4_SPORT_LEN              (2)
+#define      TPM_L4_DPORT_LEN              (2)
+#define      TPM_UDP_LEN_LEN               (2)
+#define      TPM_L4_CHECKSUM_LEN           (2)
+#define      TPM_TCP_SEQ_NUM_LEN	       (4)
+#define      TPM_TCP_ACK_NUM_LEN	       (4)
+#define      TPM_TCP_OFFSET_LEN            (1)
+#define      TPM_TCP_FLAGS_LEN             (1)
+#define      TPM_TCP_WIN_LEN               (2)
+#define      TPM_TCP_URGTPTR_LEN           (2)
+
+#define      TPM_VLAN_CFI_OFFSET           (12)
+#define      TPM_VLAN_PBIT_OFFSET          (13)
+#define      TPM_VLAN_VID_OFFSET           (0)
+
+#define      TPM_IPV4_IHL_OFFSET           (0)	/* Offset in the VER_IHL byte */
+#define      TPM_IPV4_IHL_MASK             (0x0F)	/* Mask in the  IHL byte */
+
+#define      TPM_IPV4_VER_OFFSET           (4)	/* Offset in the VER_IHL byte */
+#define      TPM_IPV4_VER_MASK             (0x0F)	/* Mask in the VER byte */
+
+#define      TPM_IPV4_FRAG_OFFSET          (0)	/* Offset in the FLAGS_FRAGMENT 2_byte */
+#define      TPM_IPV4_FRAG_MASK            (0x1FFF)	/* Mask in the FRAGMENT byte */
+
+#define      TPM_IPV4_MF_OFFSET            (13)	/* Offset in the FLAGS_FRAGMENT 2_byte */
+#define      TPM_IPV4_MF_MASK              (0x01)	/* Mask in the  FLAGS byte */
+
+#define      TPM_IPV4_TOT_LEN_MASK         (0xFFFF)
+#define      TPM_IPV4_IDENT_MASK           (0xFFFF)
+#define      TPM_IPV4_TTL_MASK             (0xFF)
+
+#define     MH_UNI_PORT_MASK                (0x000F)
+#define     MH_UNI_PORT_OFFSET              (0)
+#define     MH_GEM_PORT_MASK                (0x0FFF)
+#define     MH_GEM_PORT_OFFSET              (0)
+
+/* Maximum number of pnc ranges a single API can be spanned upon.
+ * Max. is currently two, to support IPV6 session DIP + SIP Routing + DSCP API call */
+#define     TPM_MAX_API_MULTI_RANGES        (3)
+
+#define     TPM_MAX_AI_REFS                 (4)
+
+#define     TPM_BM_GMAC_0                   (0x04)
+#define     TPM_BM_GMAC_1                   (0x10)
+#define     TPM_BM_PMAC                     (0x01)
+
+/* Bitmap of the GMACs */
+typedef uint32_t tpm_gmac_bm_t;
+
+/* TODO - add Amber to part of dynamc Init */
+#define TPM_AMBER                           (1)
+
+/* Direction Bitmap*/
+#define TPM_BM_DIR_DS                       (1<<TPM_DIR_DS)
+#define TPM_BM_DIR_US                       (1<<TPM_DIR_US)
+#define TPM_BM_DIR_BIDIR                    (TPM_BM_DIR_DS|TPM_BM_DIR_US)
+
+#define TPM_RESERVED_WINDOW_SIZE_DEFAULT     0
+
+typedef enum {
+	TPM_IP_VER_4,
+	TPM_IP_VER_6,
+	TPM_IP_VER_MAX,
+} tpm_ip_ver_t;
+
+/* TPM flowid update values */
+#define     TPM_FLOW_ID_31_16            (0x02)
+#define     TPM_FLOW_ID_15_00            (0x01)
+
+#define     TPM_TCAM_PKT_WIDTH           (24)
+
+#define     TPM_SWITCH_NUM_PORTS         (6)
+
+#define     TPM_PNC_LU_REG0              (0)
+#define     TPM_PNC_LU_REG1              (1)
+#define     TPM_PNC_LU_REG2              (2)
+#define     TPM_PNC_ETY_REG              (3)
+
+#define     TPM_PNC_CNM_L2_REG           (5)  /* KEEP IT ZERO, DON'T TOUCH IT!! THIS IS FOR CNM L2 LOOKUP. */
+#define     TPM_PNC_IPV6_DIP_REG         (6)
+#define     TPM_PNC_NOSHIFT_UPDATE_REG   (7)
+
+#define     TPM_MAX_NUM_TCONT            (8)
+#define     TPM_MAX_NUM_GIG_MAC          (2)
+#define     TPM_MAX_MOD_RANGES           (1)
+#define     TPM_MOD_TABL_SIZE            (256)
+
+#define     TPM_PNC_SIZE                 (512)
+
+#define     TPM_TX_MAX_MH_REGS           (15)
+
+/* TPM modification (z2) definitions */
+#define     TPM_MOD2_TABL_SIZE              (4095)
+#define     TPM_MOD2_MAC_TRANSLATIONS_NUM   (100)
+#define     TPM_MOD2_IP_TRANSLATIONS_NUM    (200)
+#define     TPM_MAX_MOD2_FLOWS              ((TPM_MOD2_MAC_TRANSLATIONS_NUM) + (TPM_MOD2_IP_TRANSLATIONS_NUM))
+
+#define     TPM_MOD2_DSCP_DATA_MASK         (0x00FC)	/* IPv4 DSCP */
+#define     TPM_MOD2_DSCP_DATA_BIT          (2)
+
+#define     TPM_MOD2_TC_DATA_MASK           (0x0FC0)	/* IPv6 DSCP */
+#define     TPM_MOD2_TC_DATA_BIT            (6)
+
+#define     TPM_PNC_ANY_LUID             (0xFFFF)
+
+#define     TPM_TRUE                     (1)
+#define     TPM_FALSE                    (0)
+
+#define     TPM_OK                       (0)
+#define     TPM_FAIL                     (1)
+#define     TPM_NOT_FOUND                (2)
+
+#define     TPM_MC_MAX_STREAM_NUM        (256)
+#define     TPM_MC_MAX_MAC_NUM           (256)
+#define     TPM_MAX_CPU_LOOPBACK_NUM     (4096)
+#define     TPM_MAX_CPU_LOOPBACK_ENTRY   (64)
+#define     TPM_MC_MAX_LPBK_ENTRIES_NUM  (128)
+
+#define     TPM_MAX_LU_THRESH_VAL         (0x3ffffff)
+#define     TPM_MC_MAX_MVLAN_XITS_NUM    (16)
+
+typedef enum {
+	TPM_MOD_MH_SET,	/* 0 - Update the Marvell Header */
+	TPM_MOD_MAC_DA_SET,	/* 1 - Update the MAC DA Address */
+	TPM_MOD_MAC_SA_SET,	/* 2 - Update the MAC SA Address */
+	TPM_MOD_VLAN_MOD,	/* 3 - Update the VLAN Tags (add/del/update) */
+	TPM_MOD_PPPOE_DEL,	/* 4 - Delete a PPPoE encapsulation */
+	TPM_MOD_PPPOE_ADD,	/* 5 - Add a PPPoE encapsulation */
+	TPM_MOD_DSCP_SET,	/* 6 - Set the DSCP value */
+	TPM_MOD_TTL_DEC,	/* 7 - Decrease the TTL value */
+	TPM_MOD_IPV4_UPDATE,	/* 8 - Update the IPv4 Header */
+	TPM_MOD_IPV4_SRC_SET,	/* 9 - Set the IPV4 Source Address */
+	TPM_MOD_IPV4_DST_SET,	/* 10 - Set the IPV4 Destination Address */
+	TPM_MOD_IPV6_UPDATE,	/* 11 - Update the IPv6 Header */
+	TPM_MOD_HOPLIM_DEC,	/* 12 - Decrease the Hop Limit value */
+	TPM_MOD_IPV6_SRC_SET,	/* 13 - Set the IPV6 Source Address */
+	TPM_MOD_IPV6_DST_SET,	/* 14 - Set the IPV6 Destination Address */
+	TPM_MOD_L4_SRC_SET,	/* 15 - Set the L4 Source Port (UDP or TCP) */
+	TPM_MOD_L4_DST_SET,	/* 16 - Set the L4 Destination Port (UDP or TCP) */
+
+	TPM_MAX_PKT_MOD_FLAGS
+} tpm_pkt_mod_flags_t;
+
+typedef enum {
+	TPM_AREA_TYPE_JUMP = 0,
+	TPM_AREA_TYPE_CHAIN,
+	TPM_AREA_TYPE_MAX,
+} tpm_area_type_t;
+
+typedef enum {
+	TPM_CHAIN_TYPE_NONE = 0,
+	TPM_CHAIN_TYPE_MH,
+	TPM_CHAIN_TYPE_MAC,
+	TPM_CHAIN_TYPE_VLAN,
+	TPM_CHAIN_TYPE_PPPOE,
+	TPM_CHAIN_TYPE_IPV6_PPPOE,
+	TPM_CHAIN_TYPE_L2,
+	TPM_CHAIN_TYPE_IPV4_NAPT,
+	TPM_CHAIN_TYPE_IPV4_MC,
+	TPM_CHAIN_TYPE_ROUTE,
+	TPM_CHAIN_TYPE_IPV6_MC,
+	TPM_CHAIN_TYPE_MAX,
+} tpm_chain_type_t;
+
+/******************* Internal modification flags *****************************/
+typedef enum {
+	TPM_MOD_INT_L4_TCP,	/* Update TCP checksum */
+	TPM_MOD_INT_L4_UDP,	/* Update UDP checksum */
+	TPM_MOD_INT_SPLIT_MOD,	/* First part of split modification */
+	TPM_MOD_INT_UDP_CHECKSUM,	/* Update UDP checksum - user control */
+	TPM_MAX_INT_MOD_FLAGS
+} tpm_pkt_int_mod_flags_t;
+
+/* CNM related */
+
+typedef enum {
+	TPM_CNM_IPV4_PRE_FILTER_KEY_1 = 0,
+	TPM_CNM_IPV4_PRE_FILTER_KEY_2,
+	TPM_CNM_IPV4_PRE_FILTER_KEY_3,
+	TPM_CNM_IPV4_PRE_FILTER_KEY_MAX,
+} tpm_cnm_ipv4_pre_filter_key_id_t;
+
+#define TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK    (1 << TPM_CNM_IPV4_PRE_FILTER_KEY_1)
+#define TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK    (1 << TPM_CNM_IPV4_PRE_FILTER_KEY_2)
+#define TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK    (1 << TPM_CNM_IPV4_PRE_FILTER_KEY_3)
+
+#define TPM_CNM_INVALID_IPV4_PRE_FILTER_KEY_ID    (0xFF)
+
+#define TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_KEY     (4)
+#define TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_PORT    (7)
+
+
+/*************************************************************/
+/*               STRUCTURES                                  */
+/*************************************************************/
+
+/* Structure for mapping tx_mod to HAL port and txp  */
+typedef struct {
+	uint32_t hal_port;
+	uint32_t hal_txp;
+} tpm_tx_mod_hal_map_t;
+
+/* Structure for mapping pnc_range to lookup_id */
+typedef struct {
+	tpm_pnc_ranges_t pnc_range;
+	uint32_t lookup_id;
+	uint32_t last_lookup_range;
+	uint32_t valid;
+} tpm_pnc_range_lookup_map_t;
+
+typedef struct {
+	uint32_t            enum_in;
+	uint8_t str_out[50];
+} tpm_str_map_t;
+
+/*****************************/
+/* PNC  related structures   */
+/*****************************/
+
+/* Structure represents 24byte packet data in TCAM */
+typedef struct {
+	uint8_t pkt_byte[TPM_TCAM_PKT_WIDTH];
+} tpm_pkt_data_t;
+
+/* Structure represents 24byte mask on packet data in TCAM */
+typedef tpm_pkt_data_t tpm_pkt_mask_t;
+
+/* Structure represents complete TCAM key */
+typedef struct {
+	uint32_t lu_id;	/*  TPM_PNC_ANY_LUID , for unmasking LU_ID */
+	tpm_gmac_bm_t port_ids;
+	tpm_pkt_data_t pkt_data;
+	tpm_pkt_mask_t pkt_mask;
+	uint32_t add_info_data;
+	uint32_t add_info_mask;
+} tpm_tcam_all_t;
+
+/* Structure represents complete SRAM entry */
+typedef struct {
+	uint32_t next_lu_id;
+	uint32_t lookup_done;
+	uint32_t pnc_queue;	/* 0xFFFF, don't update queue */
+	uint32_t res_info_15_0_data;
+	uint32_t res_info_15_0_mask;
+	uint32_t res_info_23_16_data;
+	uint32_t res_info_23_16_mask;
+	uint32_t add_info_data;
+	uint32_t add_info_mask;
+	uint32_t flowid_val;
+	uint32_t flowid_updt_mask;
+	uint32_t shift_updt_reg;
+	uint32_t shift_updt_val;
+	uint32_t next_lu_off_reg;
+} tpm_sram_all_t;
+
+/* Structure represents PnC entry, (TCAM, SRAM) without Index */
+typedef struct {
+	tpm_tcam_all_t tcam_entry;
+	tpm_sram_all_t sram_entry;
+} tpm_pnc_all_t;
+
+#define TPM_MOD2_MAX_PATTERN_ENTRIES    (20)
+
+/* Max number of modification pattern sets:
+	1  - jump entry
+	7 - main chains
+*/
+#define TPM_MOD2_MAX_PATTERN_SETS       (8)
+
+/* Structure for fields that may need to be parsed for internal functions (e.g. creating hardcoded pnc entries),
+   these fields are not exposed to the API's */
+typedef struct {
+	uint8_t ipv4_ver;
+	uint8_t ipv4_ver_mask;	/* 0-MASK ,  1-PARSE */
+	uint8_t ipv4_ihl;
+	uint8_t ipv4_ihl_mask;	/* 0-MASK ,  1-PARSE */
+	uint16_t ipv4_totlen;
+	uint16_t ipv4_totlen_mask;	/* 16-bits */
+	uint16_t ipv4_ident;
+	uint16_t ipv4_flags;	/* MF Flag at bit 0 */
+	uint16_t ipv4_flags_mask;	/* 0-MASK ,  1-PARSE */
+	uint8_t ipv4_frag_offset;
+	uint8_t ipv4_frag_offset_mask;	/* 0-MASK ,  1-PARSE */
+	uint8_t ipv4_ttl;
+} tpm_ipv4_add_key_t;
+
+typedef struct {
+	uint8_t ipv6_hopl;
+	uint16_t ipv6_totlen;
+	uint16_t ipv6_totlen_mask;	/* 16-bits */
+} tpm_ipv6_add_key_t;
+
+typedef struct {
+	uint8_t tcp_flags;
+	uint8_t tcp_flags_mask;	/* Bit7-0 - signal each of the TCP flags */
+} tpm_tcp_key_t;
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* _TPM_INT_TYPES_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.c
new file mode 100755
index 0000000..99f1d34
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.c
@@ -0,0 +1,281 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : tpm_mempool.c                                              **
+**                                                                           **
+**  DESCRIPTION : This file tpm memory pool manager                          **
+******************************************************************************/
+#include <linux/slab.h>
+#include "tpm_mempool.h"
+
+bool tpm_common_mempool_check_internal(tpm_common_mempool_t *pool,
+				       void *ptr,
+				       tpm_common_mpool_hdr_t *hdr,
+				       tpm_common_mpool_ftr_t *ftr)
+{
+	if (!ptr) {
+		printk(KERN_ERR "illegal ptr NULL");
+		return false;
+	}
+
+	if (!TPM_COMMON_MPOOL_CHECK_ALIGNED4(ptr)) {
+		printk(KERN_ERR "ptr not aligned %p", ptr);
+		return false;
+	}
+
+	if (hdr->magic != TPM_COMMON_MPOOL_HDR_MAGIC) {
+		printk(KERN_ERR "illegal hdr magic %x for ptr %p", hdr->magic, ptr);
+		return false;
+	}
+
+	if (ftr->magic != TPM_COMMON_MPOOL_FTR_MAGIC) {
+		printk(KERN_ERR "illegal ftr magic %x for ptr %p", ftr->magic, ptr);
+		return false;
+	}
+
+	if (hdr->pool != pool || ftr->pool != pool) {
+		printk(KERN_ERR "inconsistent size hdr->pool: %p ftr->pool: %p for ptr %p", hdr->pool, ftr->pool, ptr);
+		return false;
+	}
+
+	if (!(hdr->flags & TPM_COMMON_MPOOL_HDR_FLAGS_ALLOCATED)) {
+		printk(KERN_ERR "ptr %p was not allocated", ptr);
+		return false;
+	}
+	return true;
+}
+
+void *tpm_common_mempool_alloc(tpm_common_mempool_t * pool)
+{
+	tpm_common_mpool_hdr_t *hdr;
+
+	if (!pool || !pool->head || pool->number_of_free_entries == 0)
+		return NULL;
+
+	spin_lock_bh(&pool->lock);
+	hdr = pool->head;
+	pool->head = pool->head->next;
+
+	if (!pool->head)
+		pool->tail = NULL;
+
+	hdr->flags = TPM_COMMON_MPOOL_HDR_FLAGS_ALLOCATED;
+	pool->number_of_free_entries--;
+	spin_unlock_bh(&pool->lock);
+	return ((uint8_t *) hdr + sizeof(tpm_common_mpool_hdr_t));
+}
+
+void tpm_common_mempool_free(tpm_common_mempool_t *pool, void *ptr)
+{
+	tpm_common_mpool_hdr_t *hdr;
+	tpm_common_mpool_ftr_t *ftr;
+
+	if (!pool || !ptr)
+		return;
+
+	if (!TPM_COMMON_MPOOL_CHECK_ALIGNED4(ptr)) {
+		printk(KERN_ERR "ptr not aligned %p", ptr);
+		return;
+	}
+	spin_lock_bh(&pool->lock);
+	hdr = (tpm_common_mpool_hdr_t *) ((uint8_t *) ptr - sizeof(tpm_common_mpool_hdr_t));
+	ftr = (tpm_common_mpool_ftr_t *) ((uint8_t *) ptr + pool->data_size);
+
+	if (!tpm_common_mempool_check_internal(pool, ptr, hdr, ftr)) {
+		printk(KERN_ERR "invalid ptr %p", ptr);
+		spin_unlock_bh(&pool->lock);
+		return;
+	}
+
+	hdr->flags ^= TPM_COMMON_MPOOL_HDR_FLAGS_ALLOCATED;
+	hdr->next = NULL;
+
+	if (!pool->head)
+		pool->head = pool->tail = hdr;
+	else {
+		pool->tail->next = hdr;
+		pool->tail = hdr;
+	}
+
+	pool->number_of_free_entries++;
+	spin_unlock_bh(&pool->lock);
+}
+
+tpm_common_mempool_t *tpm_common_mempool_create(uint32_t number_of_entries,
+						uint32_t entry_size,
+						int32_t priority)
+{
+	uint32_t i;
+	uint32_t aligned_entry_size;
+	uint32_t pool_entry_size;
+	tpm_common_mpool_hdr_t *hdr;
+	tpm_common_mpool_hdr_t *next_hdr;
+	tpm_common_mpool_ftr_t *ftr;
+	tpm_common_mempool_t *pool;
+
+	aligned_entry_size = TPM_COMMON_MPOOL_ALIGN4(entry_size);
+	pool_entry_size =
+	    TPM_COMMON_MPOOL_ALIGN4(sizeof(tpm_common_mpool_hdr_t) + aligned_entry_size +
+				    sizeof(tpm_common_mpool_ftr_t));
+	pool = kmalloc((sizeof(tpm_common_mempool_t) + pool_entry_size * number_of_entries), priority);
+
+	if (!pool)
+		return NULL;
+
+	pool->entry_size = entry_size;
+	pool->number_of_entries = number_of_entries;
+	pool->data_size = aligned_entry_size;
+	pool->pool_entry_size = pool_entry_size;
+	pool->number_of_free_entries = number_of_entries;
+	pool->mem = (uint8_t *) (pool + 1);
+	pool->head = (tpm_common_mpool_hdr_t *) pool->mem;
+	spin_lock_init(&pool->lock);
+
+	for (i = 0; i < number_of_entries; i++) {
+		hdr = (tpm_common_mpool_hdr_t *) &pool->mem[pool_entry_size * i];
+		ftr =
+		    (tpm_common_mpool_ftr_t *) ((uint8_t *) hdr + sizeof(tpm_common_mpool_hdr_t) + aligned_entry_size);
+		hdr->magic = TPM_COMMON_MPOOL_HDR_MAGIC;
+		hdr->pool = pool;
+		hdr->flags = 0;
+		ftr->magic = TPM_COMMON_MPOOL_FTR_MAGIC;
+		ftr->pool = pool;
+
+		if (i < (number_of_entries - 1))
+			next_hdr = (tpm_common_mpool_hdr_t *) &pool->mem[pool_entry_size * (i + 1)];
+		else {
+			pool->tail = hdr;
+			next_hdr = NULL;
+		}
+
+		hdr->next = next_hdr;
+	}
+	return pool;
+}
+
+void tpm_common_mempool_destroy(tpm_common_mempool_t *pool)
+{
+	if (!pool)
+		return;
+
+	kfree(pool);
+}
+
+int32_t tpm_common_mempool_get_number_of_free_entries(tpm_common_mempool_t *pool)
+{
+	if (!pool)
+		return -1;
+
+	return (int32_t) pool->number_of_free_entries;
+}
+
+int32_t tpm_common_mempool_get_number_of_entries(tpm_common_mempool_t *pool)
+{
+	if (!pool)
+		return -1;
+
+	return (int32_t) pool->number_of_entries;
+}
+
+int32_t tpm_common_mempool_get_entry_size(tpm_common_mempool_t *pool)
+{
+	if (!pool)
+		return -1;
+
+	return (int32_t) pool->entry_size;
+}
+
+tpm_common_mempool_t *tpm_common_mempool_get(void *ptr)
+{
+	tpm_common_mpool_hdr_t *hdr;
+	tpm_common_mpool_ftr_t *ftr;
+
+	if (!ptr)
+		return NULL;
+
+	if (!TPM_COMMON_MPOOL_CHECK_ALIGNED4(ptr))
+		return NULL;
+
+	hdr = (tpm_common_mpool_hdr_t *) ((uint8_t *) ptr - sizeof(tpm_common_mpool_hdr_t));
+	
+	if (!hdr)
+		return NULL;
+		
+	ftr = (tpm_common_mpool_ftr_t *) ((uint8_t *) ptr + hdr->pool->data_size);
+
+	if (hdr->magic != TPM_COMMON_MPOOL_HDR_MAGIC) {
+		printk(KERN_ERR "illegal hdr magic %x for ptr %p", hdr->magic, ptr);
+		return NULL;
+	}
+	if (ftr->magic != TPM_COMMON_MPOOL_FTR_MAGIC) {
+		printk(KERN_ERR "illegal ftr magic %x for ptr %p", ftr->magic, ptr);
+		return NULL;
+	}
+	if ((!hdr->pool) || (hdr->pool != ftr->pool)) {
+		printk(KERN_ERR "inconsistent size hdr->pool: %p ftr->pool: %p for ptr %p", hdr->pool, ftr->pool, ptr);
+		return false;
+	}
+	return hdr->pool;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.h
new file mode 100755
index 0000000..2eabf27
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mempool.h
@@ -0,0 +1,123 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : tpm_mempool.h                                              **
+**                                                                           **
+**  DESCRIPTION : This file tpm memory pool manager                          **
+******************************************************************************/
+#ifndef _TPM_MEMPOOL_H
+#define _TPM_MEMPOOL_H
+
+#include <linux/spinlock.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct tpm_common_mempool tpm_common_mempool_t;
+typedef struct tpm_common_mpool_hdr {
+	struct tpm_common_mpool_hdr *next;
+	tpm_common_mempool_t *pool;
+	uint32_t flags;
+	uint32_t magic;
+} tpm_common_mpool_hdr_t;
+
+typedef struct {
+	uint32_t magic;
+	tpm_common_mempool_t *pool;
+} tpm_common_mpool_ftr_t;
+
+struct tpm_common_mempool {
+	tpm_common_mpool_hdr_t *head;
+	tpm_common_mpool_hdr_t *tail;
+	uint32_t number_of_free_entries;
+	spinlock_t lock;
+	uint32_t data_size;	/* size of data section in pool entry */
+	uint32_t pool_entry_size;	/* size of pool entry */
+	/* parameters passed on init */
+	uint32_t number_of_entries;
+	uint32_t entry_size;
+	uint8_t *mem;
+};
+
+void *tpm_common_mempool_alloc(tpm_common_mempool_t *pool);
+void tpm_common_mempool_free(tpm_common_mempool_t *pool, void *mem);
+tpm_common_mempool_t *tpm_common_mempool_get(void *mem);
+tpm_common_mempool_t *tpm_common_mempool_create(uint32_t number_of_entries, uint32_t entry_size,
+						int32_t priority);
+void tpm_common_mempool_destroy(tpm_common_mempool_t *pool);
+int32_t tpm_common_mempool_get_number_of_free_entries(tpm_common_mempool_t *pool);
+int32_t tpm_common_mempool_get_number_of_entries(tpm_common_mempool_t *pool);
+int32_t tpm_common_mempool_get_entry_size(tpm_common_mempool_t *pool);
+
+#define TPM_COMMON_MPOOL_HDR_FLAGS_ALLOCATED	0x00000001
+#define TPM_COMMON_MPOOL_HDR_MAGIC		0xa5a5a508
+#define TPM_COMMON_MPOOL_FTR_MAGIC		0xa5a5a509
+#define TPM_COMMON_MPOOL_ALIGN4(size)		((size)+4) & 0xFFFFFFFC;
+#define TPM_COMMON_MPOOL_CHECK_ALIGNED4(ptr)	((((uint32_t)(ptr)) & 0x00000003) == 0)
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* _TPM_MEMPOOL_H */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.c
new file mode 100755
index 0000000..75e6b8c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.c
@@ -0,0 +1,1263 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_mtu.c
+*
+*
+*  MODULE : TPM
+*
+*  DESCRIPTION : This file config tpm mtu
+*
+*  MODIFICATION HISTORY:
+*           15Aug11   jinghua - initial version created.
+*
+* FILE REVISION NUMBER:
+*       Revision: 1.12
+*******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_mtu.h"
+#include "tpm_pkt_proc_logic.h"
+
+tpm_mtu_pnc_cfg_t g_tpm_mtu_cfg;
+tpm_mtu_pnc_entries_t g_tpm_mtu_pnc_entry_tmp;
+
+#define IF_ERROR(ret)		\
+	if (ret != TPM_OK) {\
+		TPM_OS_ERROR(TPM_MTU_MOD, " recvd ret_code(%d)\n", ret);\
+		return(ret);\
+	}
+
+uint32_t tpm_mtu_get_pnc_free_index(void)
+{
+	static uint32_t l_rule_idx = 100;
+	return (l_rule_idx++);
+}
+
+int32_t tpm_mtu_del_acl_pnc_entry(uint32_t ethertype, uint32_t pnc_index)
+{
+	tpm_db_pnc_range_t range_data;
+	uint32_t pnc_range_id;
+	uint32_t pnc_start, pnc_stop;
+	int32_t int_ret_code;
+	tpm_mtu_pnc_index_t *pnc_index_cfg;
+	int32_t loop;
+
+	/* Get pnc_range_id */
+	if (TPM_MTU_IPV4 == ethertype) {
+		pnc_range_id = TPM_PNC_IPV4_LEN;
+		pnc_index_cfg = &(g_tpm_mtu_cfg.ipv4_mtu_cfg.pncIndex_cfg);
+	} else {
+		/*pnc_range_id = TPM_PNC_IPV6_LEN; 
+		pnc_index_cfg = &(g_tpm_mtu_cfg.ipv6_mtu_cfg.pncIndex_cfg);*/
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "there is no length check for IPv6\n");
+		return ERR_GENERAL;
+	}
+
+	/*** Calculate PNC Entry ***/
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(pnc_range_id, &range_data);
+	IF_ERROR(int_ret_code);
+
+	for (loop = 0; loop < pnc_index_cfg->pncNumber; loop++) {
+		if (pnc_index == pnc_index_cfg->pncIndex[loop])
+			break;
+	}
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d), pncIndex(%d)\n", loop, pnc_index);
+
+	/* Pull range from this index untill last used entry in Pnc range */
+	pnc_start = range_data.pnc_range_conf.range_start + loop;
+	pnc_stop = range_data.pnc_range_conf.range_start + pnc_index_cfg->pncNumber - 1;
+
+	int_ret_code = tpm_pncl_entry_delete(pnc_start, pnc_stop);
+	IF_ERROR(int_ret_code);
+
+	/* Increase number of free entries in pnc_range */
+	int_ret_code = tpm_db_pnc_rng_free_ent_inc(pnc_range_id);
+	IF_ERROR(int_ret_code);
+
+	/* update the pnc index cfg */
+	if (pnc_index_cfg->pncNumber > 1) {
+		for (; loop < pnc_index_cfg->pncNumber - 1; loop++)
+			pnc_index_cfg->pncIndex[loop] = pnc_index_cfg->pncIndex[loop + 1];
+	}
+
+	pnc_index_cfg->pncNumber--;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_index_cfg->pncNumber : %d, pncIndex: %d\n", pnc_index_cfg->pncNumber,
+		     pnc_index);
+
+	return (TPM_OK);
+}
+
+int32_t tpm_mtu_create_acl_pnc_entry(uint32_t rule_num, uint32_t ethertype,
+				     tpm_pncl_pnc_full_t *pnc_data, uint32_t *pnc_index)
+{
+	tpm_db_pnc_range_t range_data;
+	uint32_t pnc_range_id;
+	uint32_t pnc_range_start, api_start, pnc_stop_entry, pnc_entries_number, pnc_entry;
+	int32_t int_ret_code;
+	tpm_mtu_pnc_index_t *pnc_index_cfg;
+	int loop;
+
+	/* Get pnc_range_id */
+	if (TPM_MTU_IPV4 == ethertype) {
+		pnc_range_id = TPM_PNC_IPV4_LEN;
+		pnc_index_cfg = &(g_tpm_mtu_cfg.ipv4_mtu_cfg.pncIndex_cfg);
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "there is no length check for IPv6\n");
+		return ERR_GENERAL;
+		/*pnc_range_id = TPM_PNC_IPV6_LEN; 
+		pnc_index_cfg = &(g_tpm_mtu_cfg.ipv6_mtu_cfg.pncIndex_cfg);*/
+	}
+
+	/*** Calculate PNC Entry ***/
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(pnc_range_id, &range_data);
+	IF_ERROR(int_ret_code);
+
+	pnc_range_start = range_data.pnc_range_conf.range_start;
+	api_start = range_data.pnc_range_conf.api_start;
+
+	/* Calculate absolute PNC entry number to execute */
+	pnc_entry = (pnc_range_start + api_start) + rule_num;
+
+	/* Get number of existing pnc entries */
+	pnc_entries_number = pnc_index_cfg->pncNumber;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d), pnc_entries_number(%d)\n", rule_num, pnc_entries_number);
+
+	/* Call PNC Entry Insert, if this is not the api_section's new last entry */
+	if (rule_num < pnc_entries_number) {
+		pnc_stop_entry = (pnc_range_start + api_start) + (pnc_entries_number - 1);
+		int_ret_code = tpm_pncl_entry_insert(pnc_entry, pnc_stop_entry, pnc_data);
+		IF_ERROR(int_ret_code);
+	} else {		/* Otherwise just set the entry (no insertion) */
+
+		int_ret_code = tpm_pncl_entry_set(pnc_entry, pnc_data);
+		IF_ERROR(int_ret_code);
+	}
+
+	/* Decrease number of free entries in pnc_range */
+	int_ret_code = tpm_db_pnc_rng_free_ent_dec(pnc_range_id);
+	IF_ERROR(int_ret_code);
+
+	/* update the pnc index cfg */
+	*pnc_index = tpm_mtu_get_pnc_free_index();
+
+	if (pnc_index_cfg->pncNumber > 0) {
+		for (loop = pnc_index_cfg->pncNumber - 1; loop >= rule_num; loop--) {
+			pnc_index_cfg->pncIndex[loop + 1] = pnc_index_cfg->pncIndex[loop];
+			if (0 == loop)
+				break;
+		}
+
+	}
+
+	pnc_index_cfg->pncIndex[rule_num] = *pnc_index;
+	pnc_index_cfg->pncNumber++;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_index_cfg->pncNumber : %d, pncIndex: %d\n", pnc_index_cfg->pncNumber,
+		     pnc_index_cfg->pncIndex[rule_num]);
+
+	return (TPM_OK);
+}
+
+tpm_error_code_t tpm_mtu_ipv4_default_pnc_entry_insert(void)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries, pnc_entry;
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "\n");
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_LEN, &range_data);
+	IF_ERROR(int_ret_code);
+
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_end;
+
+	/*************************************************/
+	/* Basic TCAM/SRAM Config, valid for all entries */
+	/*************************************************/
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+
+	pnc_data.pncl_tcam.lu_id = range_data.pnc_range_conf.base_lu_id;
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER;
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	pnc_data.pncl_sram.next_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER;
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV4_LEN, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	int_ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_IPV4_LEN);
+	IF_ERROR(int_ret_code);
+
+	return (TPM_RC_OK);
+}
+
+#if 0
+tpm_error_code_t tpm_mtu_ipv6_default_pnc_entry_insert(void)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries, ipv6_frag_type_lu, pnc_entry;
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data, nextphase_range_data;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&nextphase_range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "\n");
+
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_TCP_FLAG, &nextphase_range_data);
+	IF_ERROR(int_ret_code);
+	ipv6_frag_type_lu = nextphase_range_data.pnc_range_conf.base_lu_id;
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_LEN, &range_data);
+	IF_ERROR(int_ret_code);
+
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_end;
+
+	/*************************************************/
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+
+	pnc_data.pncl_tcam.lu_id = range_data.pnc_range_conf.base_lu_id;
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.ipv6_subf = TPM_IPv6_PARSE_VER;
+	pnc_data.pncl_tcam.ipv6_parse_bm = 0;
+
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+	pnc_data.pncl_sram.next_offset.offset_sub.ipv6_subf = TPM_IPv6_PARSE_VER;
+	pnc_data.pncl_sram.sram_updt_bm = 0;
+	pnc_data.pncl_sram.next_lu_id = ipv6_frag_type_lu;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV6_LEN, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	return (TPM_RC_OK);
+
+}
+#endif
+
+void tpm_mtu_printBinary(uint32_t inValue)
+{
+	uint32_t desArray[16] = { 0 };
+	uint32_t i;
+	for (i = 0; i < 16; i++) {
+		if (0 != (inValue & (1 << i)))
+			desArray[i] = 1;
+	}
+
+	for (i = 16; i > 0; i--)
+		printk("%d", desArray[i - 1]);
+
+	return;
+}
+
+uint32_t tpm_mtu_get_binary_length(uint32_t inValue)
+{
+	uint32_t i;
+	for (i = 16; i > 0; i--) {
+		if (0 != (inValue & (1 << (i - 1))))
+			return i;
+	}
+
+	return 0;
+}
+
+void tpm_mtu_add_len_chk_entry(uint32_t pkt_value, uint32_t pkt_mask)
+{
+/*    printf("\npkt_value: ");
+    printBinary(pkt_value);
+    printf(" ,   %d", pkt_value);
+    printf("\npkt_mask : ");
+    printBinary(pkt_mask);
+    printf(" ,   %d", pkt_mask);
+    printf("\n===========================================================");
+*/
+	g_tpm_mtu_pnc_entry_tmp.pktMask[g_tpm_mtu_pnc_entry_tmp.pncEntryNum] = pkt_mask;
+	g_tpm_mtu_pnc_entry_tmp.pktValue[g_tpm_mtu_pnc_entry_tmp.pncEntryNum] = pkt_value;
+	g_tpm_mtu_pnc_entry_tmp.pncEntryNum++;
+
+	return;
+}
+
+void tpm_mtu_caculate_value_mask(uint32_t min, uint32_t max)
+{
+	uint32_t max_tmp, min_tmp;
+	uint32_t max_length = 0, min_length = 0;
+	uint32_t i = 0, tmp_range_max;
+	uint32_t pkt_value, pkt_mask;
+
+	memset(&g_tpm_mtu_pnc_entry_tmp, 0, sizeof(g_tpm_mtu_pnc_entry_tmp));
+
+	if (min > max)
+		return;
+
+	min++;
+	max_length = tpm_mtu_get_binary_length(max);
+	min_length = tpm_mtu_get_binary_length(min);
+
+	/* get the length of the max */
+	max_tmp = max;
+	min_tmp = min;
+
+	for (i = 0; i < max_length; i++) {
+		tmp_range_max = min_tmp | (0xffff >> (15 - i));
+
+		if (max == min_tmp) {
+			pkt_mask = 0xffff;
+
+			pkt_value = min_tmp;
+
+			tpm_mtu_add_len_chk_entry(pkt_value, pkt_mask);
+
+			return;
+		}
+
+		if (max == tmp_range_max) {
+			if (0 != (min_tmp & (1 << i)))
+				pkt_mask = 0xffff << i;
+			else
+				pkt_mask = 0xffff << (i + 1);
+
+			pkt_value = min_tmp & pkt_mask;
+
+			tpm_mtu_add_len_chk_entry(pkt_value, pkt_mask);
+
+			return;
+		}
+
+		if (0 != (min_tmp & (1 << i))) {
+			/*here we get the 1. */
+			if (max > tmp_range_max) {
+				/*here we get the 1 in min_tmp. */
+				pkt_mask = 0xffff << i;
+
+				pkt_value = min_tmp & pkt_mask;
+
+				tpm_mtu_add_len_chk_entry(pkt_value, pkt_mask);
+
+				min_tmp = min_tmp + (1 << i);
+			} else {
+				/*here we get some problem. */
+				break;
+			}
+		} else {
+			if (max > tmp_range_max)
+				continue;
+			else {
+				/*here we get some problem. */
+				break;
+			}
+		}
+	}
+
+	if (i == max_length) {
+		/* here we got nothing left to do */
+		return;
+	}
+
+	/* here is for the thing like this:
+	   min: 10000
+	   max: 10100
+	   in this case, i = 2;
+	 */
+	for (; i > 0; i--) {
+		if (GET_BIT(max, i) == GET_BIT(min_tmp, i))
+			continue;
+
+		pkt_mask = 0xffff << i;
+
+		pkt_value = min_tmp & pkt_mask;
+
+		tpm_mtu_add_len_chk_entry(pkt_value, pkt_mask);
+
+		min_tmp = min_tmp + (1 << i);
+	}
+
+	/* here we set the last one, i = 0
+	   min: 10100
+	   max: 10100
+	   or
+	   min: 10100
+	   max: 10101
+	 */
+	if (GET_BIT(max, i) == GET_BIT(min_tmp, i))
+		pkt_mask = 0xffff;
+	else
+		pkt_mask = 0xffff << 1;
+
+	pkt_value = min_tmp;
+
+	tpm_mtu_add_len_chk_entry(pkt_value, pkt_mask);
+
+	return;
+}
+
+tpm_error_code_t tpm_mtu_ipv4_len_entry_create(uint32_t len_start,
+					       uint32_t len_mask,
+					       bool pppoe_only,
+					       uint32_t direction, uint32_t rule_num, uint32_t *rule_idx)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t cpu_rx_queue;
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	TPM_OS_DEBUG(TPM_MTU_MOD, "\n");
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_LEN, &range_data);
+	IF_ERROR(int_ret_code);
+
+	free_entries = range_data.pnc_range_oper.free_entries;
+
+	if (free_entries < 1) {
+		TPM_OS_WARN(TPM_MTU_MOD, "PNC length range(%d) too small, can not insert anymore \n", TPM_PNC_IPV4_LEN);
+		return TPM_FAIL;
+	}
+
+	/*************************************************/
+	/* Basic TCAM/SRAM Config, valid for all entries */
+	/*************************************************/
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+
+	pnc_data.pncl_tcam.lu_id = range_data.pnc_range_conf.base_lu_id;
+	if (TPM_DOWNSTREAM == direction) {
+		/* Get PMAC(s) */
+		tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	} else {
+		/* Get GMAC(s) */
+		tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_UNI_ANY, &gmac_bm);
+	}
+	pnc_data.pncl_tcam.port_ids = gmac_bm;
+
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER;
+	pnc_data.pncl_tcam.ipv4_parse_bm = TPM_IPv4_PARSE_TOTLEN;
+
+	/* Only check length for packets that are not already going to CPU */
+	pnc_data.pncl_tcam.add_info_data = (0 << TPM_AI_TO_CPU_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_TO_CPU_MASK;
+
+	/* Only check length for packets that are MTM */
+	pnc_data.pncl_tcam.add_info_data = (1 << TPM_AI_MTM_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_MTM_MASK;
+
+	tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+
+	pnc_data.pncl_sram.pnc_queue = cpu_rx_queue;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	pnc_data.pncl_sram.next_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER;
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_TXP | TPM_PNCL_SET_LUD;
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+
+	/* Signal the packet is going to CPU */
+	pnc_data.pncl_sram.add_info_data |= (1 << TPM_AI_TO_CPU_BIT_OFF);
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TO_CPU_MASK;
+
+	if (free_entries == 0) {
+		TPM_OS_ERROR(TPM_MTU_MOD, "No free entries\n");
+		return (TPM_FAIL);
+	}
+
+	/* Build Tcam Entry */
+	pnc_data.pncl_tcam.pkt_key.ipv4_add_key.ipv4_totlen = len_start;
+	pnc_data.pncl_tcam.pkt_key.ipv4_add_key.ipv4_totlen_mask = len_mask;
+
+	if (pppoe_only) {
+		/* YUVAL - this only handles pppoe_add, which is ok as long as L2_hwf does not need to be len_checked */
+		pnc_data.pncl_tcam.add_info_data |= (1 << TPM_AI_PPPOE_ADD_BIT_OFF);
+		pnc_data.pncl_tcam.add_info_mask |= TPM_AI_PPPOE_ADD_MASK;
+
+	}
+
+	/*** Insert the PNC Entry ***/
+	int_ret_code = tpm_mtu_create_acl_pnc_entry(rule_num, TPM_MTU_IPV4, &pnc_data, rule_idx);
+	IF_ERROR(int_ret_code);
+
+	TPM_OS_INFO(TPM_MTU_MOD,
+		    "insert new len chk PNC rule: pktValue(%d), pktMask(%d), pnc_entry(%d), pncIndex(%d),\n", len_start,
+		    len_mask, rule_num, *rule_idx);
+
+	return (TPM_OK);
+}
+
+tpm_error_code_t tpm_mtu_safety_net_entry_create(uint32_t *entry_index, uint32_t direction, uint32_t ethertype)
+{
+	tpm_error_code_t tpm_ret;
+	uint32_t safety_net_entry;
+
+	TPM_OS_INFO(TPM_MTU_MOD, "direction(%d), ethertype(%d), \n", direction, ethertype);
+
+	if (TPM_MTU_IPV4 == ethertype) {
+		safety_net_entry = g_tpm_mtu_cfg.ipv4_mtu_cfg.mtu_ds_cfg.pncEntryNum
+		    + g_tpm_mtu_cfg.ipv4_mtu_cfg.mtu_pppoe2ipoe_us_cfg.pncEntryNum
+		    + g_tpm_mtu_cfg.ipv4_mtu_cfg.mtu_ipoe2max_us_cfg.pncEntryNum;
+
+		tpm_ret = tpm_mtu_ipv4_len_entry_create(g_tpm_mtu_cfg.safety_net_value,
+							g_tpm_mtu_cfg.safety_net_mask,
+							false, direction, safety_net_entry, entry_index);
+	} else
+		tpm_ret = TPM_OK;
+
+	TPM_OS_INFO(TPM_MTU_MOD, "entry_index(%d)\n", *entry_index);
+
+	return tpm_ret;
+}
+
+uint32_t tpm_mtu_update_pnc(tpm_mtu_pnc_entries_t *mtu_cfg,
+			    uint32_t start_pnc_entry,
+			    uint32_t ethertype, uint32_t direction, uint32_t free_pnc_entry_number, bool pppoe_only)
+{
+	uint32_t pnc_entry_num_tmp;
+	uint32_t pnc_entry_num_original;
+	tpm_error_code_t tpm_ret;
+	uint32_t safety_net_entry;
+	tpm_src_port_type_t src_port;
+
+	pnc_entry_num_tmp = 0;
+	pnc_entry_num_original = 0;
+
+	TPM_OS_INFO(TPM_MTU_MOD, "direction(%d), ethertype(%d), start_pnc_entry(%d), free_pnc_entry_number(%d),\n",
+		    direction, ethertype, start_pnc_entry, free_pnc_entry_number);
+
+	if (TPM_MTU_IPV6 == ethertype)
+		return TPM_OK;
+
+	/* insert safety net first */
+	tpm_ret = tpm_mtu_safety_net_entry_create(&safety_net_entry, direction, ethertype);
+	if (TPM_RC_OK != tpm_ret) {
+		TPM_OS_ERROR(TPM_MTU_MOD, "fail to insert safety net pnc entry, number: %d\n", pnc_entry_num_tmp);
+		return TPM_FAIL;
+	}
+
+	if (TPM_DOWNSTREAM == direction)
+		src_port = TPM_SRC_PORT_WAN;
+	else
+		src_port = TPM_SRC_PORT_UNI_ANY;
+
+	while ((free_pnc_entry_number > 0) && (pnc_entry_num_tmp < g_tpm_mtu_pnc_entry_tmp.pncEntryNum)) {
+		/* insert new */
+		tpm_ret = tpm_mtu_ipv4_len_entry_create(g_tpm_mtu_pnc_entry_tmp.pktValue[pnc_entry_num_tmp],
+							g_tpm_mtu_pnc_entry_tmp.pktMask[pnc_entry_num_tmp],
+							pppoe_only,
+							direction,
+							pnc_entry_num_tmp + start_pnc_entry,
+							&g_tpm_mtu_pnc_entry_tmp.pncIndex[pnc_entry_num_tmp]);
+		if (TPM_RC_OK != tpm_ret) {
+			TPM_OS_ERROR(TPM_MTU_MOD, "fail to insert len chk pnc entry, number: %d\n", pnc_entry_num_tmp);
+			return TPM_FAIL;
+		}
+
+		pnc_entry_num_tmp++;
+		free_pnc_entry_number--;
+
+		TPM_OS_INFO(TPM_MTU_MOD, "pnc_entry_inert_num(%d), free_pnc_entry_number(%d)\n",
+			    pnc_entry_num_tmp, free_pnc_entry_number);
+	}
+
+	while (pnc_entry_num_original < mtu_cfg->pncEntryNum) {
+		/* remove old one */
+		tpm_ret = tpm_mtu_del_acl_pnc_entry(ethertype, mtu_cfg->pncIndex[pnc_entry_num_original]);
+		IF_ERROR(tpm_ret);
+
+		TPM_OS_INFO(TPM_MTU_MOD, "remove (%d) PNC entry pncIndex(%d)\n",
+			    pnc_entry_num_original, mtu_cfg->pncIndex[pnc_entry_num_original]);
+
+		pnc_entry_num_original++;
+
+		/* insert new one if there is */
+		if (pnc_entry_num_tmp < g_tpm_mtu_pnc_entry_tmp.pncEntryNum) {
+			tpm_ret = tpm_mtu_ipv4_len_entry_create(g_tpm_mtu_pnc_entry_tmp.pktValue[pnc_entry_num_tmp],
+								g_tpm_mtu_pnc_entry_tmp.pktMask[pnc_entry_num_tmp],
+								pppoe_only,
+								direction,
+								pnc_entry_num_tmp + start_pnc_entry,
+								&g_tpm_mtu_pnc_entry_tmp.pncIndex[pnc_entry_num_tmp]);
+			if (TPM_RC_OK != tpm_ret) {
+				TPM_OS_ERROR(TPM_MTU_MOD, "fail to insert len chk pnc entry, number: %d\n",
+					     pnc_entry_num_tmp);
+				return TPM_FAIL;
+			}
+			TPM_OS_INFO(TPM_MTU_MOD, "pnc_entry_inert_num(%d)\n", pnc_entry_num_tmp);
+		}
+
+		pnc_entry_num_tmp++;
+	}
+
+	/* set the config */
+	memcpy(mtu_cfg, &g_tpm_mtu_pnc_entry_tmp, sizeof(g_tpm_mtu_pnc_entry_tmp));
+
+	/* remove safety net */
+	tpm_ret = tpm_mtu_del_acl_pnc_entry(ethertype, safety_net_entry);
+	IF_ERROR(tpm_ret);
+
+	return TPM_OK;
+}
+
+uint32_t tpm_proc_set_mtu(uint32_t ethertype, uint32_t direction, uint32_t mtu)
+{
+
+/*
+	1. If ipv4_pppoe_mtu has been set,
+
+		if ipv4_pppoe_mtu > ipv4_MTU, return error.
+		else use algorism to get the PNC entries for (ipv4_pppoe_MTU to ipv4_MTU) with pppoe AI bits
+
+	2. Use algorism to get the PNC entries for (ipv4_MTU to tpm_max_pkt_len)
+
+	3. If the PNC entries number for this two sets is bigger than the size of IPv4 len check range,
+		return error and quit;
+
+	4. If any of the two sets of PNC entries for pkt len check have already been set,
+		use the algorism in section 3.4 to update the PNC entries.
+*/
+
+	tpm_mtu_ethtype_pnc_cfg_t *ethtype_pnc_cfg;
+	uint32_t pppoe_mtu;
+	uint32_t pre_mtu;
+	uint32_t new_pnc_entry_num = 0;
+	uint32_t free_entry_number;
+	uint32_t int_ret_code;
+	tpm_mtu_pnc_entries_t *mtu_cfg;
+	tpm_db_mtu_setting_enable_t enable;
+	tpm_db_pppoe_add_enable_t pppoe_add_enable;
+
+	tpm_db_get_mtu_enable(&enable);
+	if (TPM_MTU_CHECK_DISABLED == enable) {
+		TPM_OS_WARN(TPM_MTU_MOD, "mtu check is not enabled!\n");
+		return TPM_OK;
+	}
+
+	tpm_db_get_pppoe_add_enable(&pppoe_add_enable);
+
+	if (TPM_MTU_IPV4 == ethertype) {
+		ethtype_pnc_cfg = &(g_tpm_mtu_cfg.ipv4_mtu_cfg);
+		tpm_db_mtu_get_ipv4_pppoe_mtu_us(&pppoe_mtu);
+	} else {
+		ethtype_pnc_cfg = &(g_tpm_mtu_cfg.ipv6_mtu_cfg);
+		tpm_db_mtu_get_ipv6_pppoe_mtu_us(&pppoe_mtu);
+	}
+
+	if ((TPM_UPSTREAM == direction) && (pppoe_mtu >= mtu)) {
+		/* pppoe_mtu is bigger than ipoe_mtu, does not make sense */
+		TPM_OS_WARN(TPM_MTU_MOD, "pppoe_mtu is bigger than ipoe_mtu, does not make sense\n");
+	}
+
+	TPM_OS_DEBUG(TPM_MTU_MOD, "pppoe_mtu: %d, ipoe_mtu: %d\n", pppoe_mtu, mtu);
+
+	/* get PNC entries */
+	tpm_mtu_caculate_value_mask(mtu, g_tpm_mtu_cfg.sys_pkt_len_max);
+
+	new_pnc_entry_num = g_tpm_mtu_pnc_entry_tmp.pncEntryNum;
+
+	if ((TPM_UPSTREAM == direction) && (TPM_PPPOE_ADD_ENABLED == pppoe_add_enable)) {
+		/* pppoe_mtu to ipoe need to be calculate again */
+		tpm_mtu_caculate_value_mask(pppoe_mtu, mtu);
+		new_pnc_entry_num += g_tpm_mtu_pnc_entry_tmp.pncEntryNum;
+		new_pnc_entry_num += ethtype_pnc_cfg->mtu_ds_cfg.pncEntryNum;
+	} else {
+		new_pnc_entry_num += ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg.pncEntryNum;
+		new_pnc_entry_num += ethtype_pnc_cfg->mtu_ipoe2max_us_cfg.pncEntryNum;
+	}
+
+	TPM_OS_DEBUG(TPM_MTU_MOD, "new_pnc_entry_num: %d\n", new_pnc_entry_num);
+
+	if ((ethtype_pnc_cfg->rangeSize) < new_pnc_entry_num) {
+		TPM_OS_ERROR(TPM_MTU_MOD,
+			     "the new pnc entry number is bigger than the range size,  range size: %d, new size: %d\n",
+			     (ethtype_pnc_cfg->rangeSize), new_pnc_entry_num);
+
+		return TPM_FAIL;
+	}
+
+	if (TPM_UPSTREAM == direction) {
+		if (TPM_MTU_IPV4 == ethertype)
+			tpm_db_mtu_get_ipv4_mtu_us(&pre_mtu);
+		else
+			tpm_db_mtu_get_ipv6_mtu_us(&pre_mtu);
+
+		mtu_cfg = &ethtype_pnc_cfg->mtu_ipoe2max_us_cfg;
+	} else {
+		if (TPM_MTU_IPV4 == ethertype)
+			tpm_db_mtu_get_ipv4_mtu_ds(&pre_mtu);
+		else
+			tpm_db_mtu_get_ipv6_mtu_ds(&pre_mtu);
+
+		mtu_cfg = &ethtype_pnc_cfg->mtu_ds_cfg;
+	}
+
+	free_entry_number = (ethtype_pnc_cfg->rangeSize) -
+		(ethtype_pnc_cfg->mtu_ipoe2max_us_cfg.pncEntryNum + ethtype_pnc_cfg->mtu_ds_cfg.pncEntryNum
+		+ ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg.pncEntryNum);
+
+	if (TPM_DOWNSTREAM == direction) {
+		/* IN DS, ONLY mtu to max would be updated */
+		/* get PNC entries */
+		tpm_mtu_caculate_value_mask(mtu, g_tpm_mtu_cfg.sys_pkt_len_max);
+
+		/* update the PNC entry on HW */
+		int_ret_code = tpm_mtu_update_pnc(mtu_cfg,
+						  ethtype_pnc_cfg->mtu_ipoe2max_us_cfg.pncEntryNum +
+						  ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg.pncEntryNum, ethertype,
+						  direction, free_entry_number, false);
+
+		IF_ERROR(int_ret_code);
+
+		return TPM_OK;
+	}
+
+	/* IN US, both mtu to max and pppoe to mtu need to be updated */
+	if (pre_mtu > mtu) {
+		/* mtu getting smaller, handle mtu to max first */
+		/* get PNC entries */
+		tpm_mtu_caculate_value_mask(mtu, g_tpm_mtu_cfg.sys_pkt_len_max);
+
+		/* update the PNC entry on HW */
+		int_ret_code = tpm_mtu_update_pnc(mtu_cfg, ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg.pncEntryNum,
+						  ethertype, direction, free_entry_number, false);
+		IF_ERROR(int_ret_code);
+
+		/* handle pppoe to mtu */
+		if (TPM_PPPOE_ADD_DISABLED == pppoe_add_enable) {
+			/* no pppoe_mtu */
+			TPM_OS_DEBUG(TPM_MTU_MOD, "no pppoe_mtu, return\n");
+			return TPM_OK;
+		}
+
+		/* update free entry number */
+		free_entry_number = (ethtype_pnc_cfg->rangeSize) -
+			(ethtype_pnc_cfg->mtu_ipoe2max_us_cfg.pncEntryNum + ethtype_pnc_cfg->mtu_ds_cfg.pncEntryNum
+			+ ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg.pncEntryNum);
+
+		/* get PNC entries */
+		tpm_mtu_caculate_value_mask(pppoe_mtu, mtu);
+
+		/* update the PNC entry on HW */
+		int_ret_code =
+		    tpm_mtu_update_pnc(&(ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg), 0, ethertype, direction,
+				       free_entry_number, true);
+
+		IF_ERROR(int_ret_code);
+	} else {
+		/* mtu getting bigger, handle pppoe to mtu first */
+		if (TPM_PPPOE_ADD_ENABLED == pppoe_add_enable) {
+			/* no pppoe_mtu */
+			TPM_OS_DEBUG(TPM_MTU_MOD, " pppoe_mtu ENABLED, handle pppoe to mtu first\n");
+			/* get PNC entries */
+			tpm_mtu_caculate_value_mask(pppoe_mtu, mtu);
+
+			/* update the PNC entry on HW */
+			int_ret_code =
+				tpm_mtu_update_pnc(&(ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg), 0, ethertype, direction,
+						free_entry_number, true);
+
+			IF_ERROR(int_ret_code);
+		}
+
+		/* handle mtu to max */
+
+		/* update free entry number */
+		free_entry_number = (ethtype_pnc_cfg->rangeSize) -
+			(ethtype_pnc_cfg->mtu_ipoe2max_us_cfg.pncEntryNum + ethtype_pnc_cfg->mtu_ds_cfg.pncEntryNum
+			+ ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg.pncEntryNum);
+
+		/* get PNC entries */
+		tpm_mtu_caculate_value_mask(mtu, g_tpm_mtu_cfg.sys_pkt_len_max);
+
+		/* update the PNC entry on HW */
+		int_ret_code = tpm_mtu_update_pnc(mtu_cfg, ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg.pncEntryNum,
+						ethertype, direction, free_entry_number, false);
+
+		IF_ERROR(int_ret_code);
+	}
+
+	return TPM_OK;
+}
+
+uint32_t tpm_proc_set_pppoe_mtu(uint32_t ethertype, uint32_t direction, uint32_t pppoe_mtu)
+{
+	/*
+	   1. if ipv4_ mtu has been set,
+	   if  ipv4_pppoe_mtu > ipv4_mtu, generate a warning.
+	   else use algorism to get the PNC entries for (ipv4_pppoe_max to ipv4_mtu) with pppoe AI bits
+	   else
+	   use algorism to get the PNC entries for (ipv4_pppoe_max  to   tpm_max_pkt_len) with pppoe AI bits.
+
+	   2. if ipv4_mtu has been set, use algorism to get the PNC entries for
+	   (ipv4_mtu to tpm_mtu)
+
+	   3. if the PNC entries number for this two sets is bigger than the size of
+	   IPv4 len check range, return error and quit;
+
+	   4. if any of the two sets of PNC entries for pkt len check
+	   have already been set, , use the algorism in section 3.4 to update the PNC entries
+	 */
+
+	tpm_mtu_ethtype_pnc_cfg_t *ethtype_pnc_cfg;
+	uint32_t mtu_tmp;
+	uint32_t new_pnc_entry_num;
+	uint32_t free_entry_number;
+	tpm_db_mtu_setting_enable_t enable;
+	tpm_db_pppoe_add_enable_t pppoe_add_enable;
+
+	tpm_db_get_mtu_enable(&enable);
+	if (TPM_MTU_CHECK_DISABLED == enable) {
+		TPM_OS_WARN(TPM_MTU_MOD, "mtu check is not enabled!\n");
+		return TPM_OK;
+	}
+
+	tpm_db_get_pppoe_add_enable(&pppoe_add_enable);
+	if (TPM_PPPOE_ADD_DISABLED == pppoe_add_enable) {
+		TPM_OS_WARN(TPM_MTU_MOD, "pppoe mtu check is not enabled!\n");
+		return TPM_OK;
+	}
+
+	if (TPM_DOWNSTREAM == direction) {
+		/* no pppoe mtu in DS */
+		TPM_OS_WARN(TPM_MTU_MOD, " no pppoe mtu in DS\n");
+		return TPM_OK;
+	}
+
+	if (TPM_MTU_IPV4 == ethertype)
+		ethtype_pnc_cfg = &(g_tpm_mtu_cfg.ipv4_mtu_cfg);
+	else
+		ethtype_pnc_cfg = &(g_tpm_mtu_cfg.ipv6_mtu_cfg);
+
+	if (TPM_MTU_IPV4 == ethertype) {
+		ethtype_pnc_cfg = &(g_tpm_mtu_cfg.ipv4_mtu_cfg);
+		tpm_db_mtu_get_ipv4_mtu_us(&mtu_tmp);
+	} else {
+		ethtype_pnc_cfg = &(g_tpm_mtu_cfg.ipv6_mtu_cfg);
+		tpm_db_mtu_get_ipv6_mtu_us(&mtu_tmp);
+	}
+
+	if (MV_TPM_UN_INITIALIZED_INIT_PARAM == mtu_tmp) {
+		/* no ipoe mtu set */
+		mtu_tmp = g_tpm_mtu_cfg.sys_pkt_len_max;
+	}
+
+	if (pppoe_mtu >= mtu_tmp) {
+		/* pppoe_mtu is bigger than ipoe_mtu, does not make sense */
+		TPM_OS_WARN(TPM_MTU_MOD, "pppoe_mtu is bigger than ipoe_mtu, does not make sense\n");
+	}
+
+	TPM_OS_DEBUG(TPM_MTU_MOD, "pppoe_mtu: %d, ipoe_mtu: %d\n", pppoe_mtu, mtu_tmp);
+
+	/* get PNC entries */
+	tpm_mtu_caculate_value_mask(pppoe_mtu, mtu_tmp);
+
+	new_pnc_entry_num = ethtype_pnc_cfg->mtu_ipoe2max_us_cfg.pncEntryNum + ethtype_pnc_cfg->mtu_ds_cfg.pncEntryNum
+		+ g_tpm_mtu_pnc_entry_tmp.pncEntryNum;
+
+	if ((ethtype_pnc_cfg->rangeSize) < new_pnc_entry_num) {
+		/* the new pnc entry number is bigger than the range size
+		 */
+		TPM_OS_ERROR(TPM_MTU_MOD,
+				"the new pnc entry number is bigger than the range size,  range size: %d, new size: %d\n",
+				(ethtype_pnc_cfg->rangeSize), new_pnc_entry_num);
+
+		return TPM_FAIL;
+	}
+
+	free_entry_number = (ethtype_pnc_cfg->rangeSize) -
+		(ethtype_pnc_cfg->mtu_ipoe2max_us_cfg.pncEntryNum + ethtype_pnc_cfg->mtu_ds_cfg.pncEntryNum
+		+ ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg.pncEntryNum);
+
+	/* update the PNC entry on HW */
+	tpm_mtu_update_pnc(&ethtype_pnc_cfg->mtu_pppoe2ipoe_us_cfg, 0, ethertype, direction, free_entry_number, true);
+
+	if (TPM_MTU_IPV4 == ethertype)
+		tpm_db_mtu_set_ipv4_pppoe_mtu_us(pppoe_mtu);
+	else
+		tpm_db_mtu_set_ipv6_pppoe_mtu_us(pppoe_mtu);
+
+	return TPM_OK;
+}
+
+void tpm_mtu_set_mru(void)
+{
+	uint32_t mru = 1500;
+	tpm_db_pon_type_t pon_type;
+	uint32_t num_vlan_tags;
+	tpm_db_pppoe_add_enable_t pppoe_add_enable;
+	tpm_db_mtu_setting_enable_t mtu_enable;
+	tpm_gmacs_enum_t act_wan= tpm_db_active_wan_get();
+
+	tpm_db_pon_type_get(&pon_type);
+	tpm_db_get_num_vlan_tags(&num_vlan_tags);
+	tpm_db_get_mtu_enable(&mtu_enable);
+
+	tpm_db_get_pppoe_add_enable(&pppoe_add_enable);
+
+	if (TPM_ENUM_PMAC == act_wan){
+       	switch (pon_type) {
+		case TPM_P2P:
+			mru = 2048;
+       		break;
+
+		case TPM_EPON:
+			mru = 1593;
+			break;
+
+		case TPM_GPON:
+			/* [YuvalC] According to current info, for GPON 2048 bytes.
+		           define it 2032 for now, to be on the safe side. */
+		    	mru = 2032;
+		    	break;
+
+		default:
+			TPM_OS_WARN(TPM_MTU_MOD, "act_wan is PMAC but no valid pon_type (%d)\n", pon_type);
+			return;
+       	}
+	} else if (TPM_ENUM_GMAC_0 == act_wan || TPM_ENUM_GMAC_1 == act_wan)
+		mru = 2048;
+
+	mru -= ((num_vlan_tags) * 4);
+
+	if (TPM_PPPOE_ADD_ENABLED == pppoe_add_enable && TPM_MTU_CHECK_DISABLED == mtu_enable) {
+		mru -= 8;
+		/*  This mru_reduction is only needed when mtu is disabled,
+		 */
+	}
+
+	tpm_db_set_mru(mru);
+
+}
+
+int32_t tpm_proc_mtu_check_cpu_queue_size(uint32_t queue)
+{
+	tpm_db_gmac_conn_t gmac_con;
+	uint32_t valid;
+	uint32_t queue_size;
+	/*tpm_db_pon_type_t pon_type; */
+
+	/* GMAC0 rx */
+	tpm_db_gmac_conn_get(TPM_ENUM_GMAC_0, &gmac_con);
+	if (TPM_GMAC_CON_DISC != gmac_con) {
+		tpm_db_gmac_rx_q_conf_get(TPM_ENUM_GMAC_0, queue, &valid, &queue_size);
+		if (0 == queue_size) {
+			TPM_OS_WARN(TPM_MTU_MOD, "cpu rx queue size is 0 from GMAC_0!\n");
+			return TPM_FAIL;
+		}
+	}
+
+	/* GMAC1 rx */
+	tpm_db_gmac_conn_get(TPM_ENUM_GMAC_1, &gmac_con);
+	if (TPM_GMAC_CON_DISC != gmac_con) {
+		tpm_db_gmac_rx_q_conf_get(TPM_ENUM_GMAC_1, queue, &valid, &queue_size);
+		if (0 == queue_size) {
+			TPM_OS_WARN(TPM_MTU_MOD, "cpu rx queue size is 0 from GMAC_1!\n");
+			return TPM_FAIL;
+		}
+	}
+
+	/* PMAC Rx */
+#if 0
+	tpm_db_pon_type_get(&pon_type);
+	if (TPM_GPON == pon_type || TPM_EPON == pon_type) {
+		/* do not need to check */
+		return TPM_OK;
+	}
+#endif
+	tpm_db_gmac_conn_get(TPM_ENUM_PMAC, &gmac_con);
+	if (TPM_GMAC_CON_DISC != gmac_con) {
+		tpm_db_gmac_rx_q_conf_get(TPM_ENUM_PMAC, queue, &valid, &queue_size);
+		if (0 == queue_size) {
+			TPM_OS_WARN(TPM_MTU_MOD, "cpu rx queue size is 0 from TPM_ENUM_PMAC!\n");
+			return TPM_FAIL;
+		}
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mtu_init(void)
+{
+	tpm_db_mtu_setting_enable_t enable;
+	tpm_db_pnc_range_conf_t range_conf;
+	int32_t ret_code;
+	int32_t mtu_tmp, cpu_rx_queue;
+
+	TPM_OS_DEBUG(TPM_MTU_MOD, "MTU init started!\n");
+
+	/* Phase I - set MRU */
+	tpm_mtu_set_mru();
+
+	tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+	ret_code = tpm_proc_mtu_check_cpu_queue_size(cpu_rx_queue);
+	if (ret_code != TPM_OK) {
+		TPM_OS_WARN(TPM_MTU_MOD, "check_cpu_queue_size failed\n");
+		return TPM_FAIL;
+	}
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_LEN, &range_conf);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_WARN(TPM_MTU_MOD, " no ipv4 PNC range\n");
+		return TPM_FAIL;
+	}
+	tpm_db_get_mtu_enable(&enable);
+	if (TPM_MTU_CHECK_DISABLED == enable) {
+	/* range size smaller than 2, illegal */
+		if (range_conf.range_size < 2) {
+			TPM_OS_ERROR(TPM_INIT_MOD, "PNC range(%d) too small to be initialized, "
+						   "current size(%d). Min size should be 2 \n",
+				     TPM_PNC_IPV4_LEN, range_conf.range_size);
+			return TPM_FAIL;
+		} else if (range_conf.range_size > 2) {
+			TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) too big, current size(%d). "
+						  "it is a waste with MTU disabled, size should be 2\n",
+				    TPM_PNC_IPV4_LEN, range_conf.range_size);
+		}
+	} else {
+	/* range size smaller than 2, illegal */
+		if (range_conf.range_size <= 2) {
+			TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) too small to be initialized, size(%d) \n",
+				    TPM_PNC_IPV4_LEN, range_conf.range_size);
+			return TPM_FAIL;
+		}
+	}
+
+	/* create default rule for ipv4 packets */
+	tpm_mtu_ipv4_default_pnc_entry_insert();
+
+	/* Phase II - Set MTU entries, only if */
+	if (TPM_MTU_CHECK_DISABLED == enable) {
+		TPM_OS_WARN(TPM_MTU_MOD, "mtu check is not enabled!\n");
+		return TPM_OK;
+	}
+
+	memset(&g_tpm_mtu_cfg, 0, sizeof(g_tpm_mtu_cfg));
+	g_tpm_mtu_cfg.sys_pkt_len_max = 2048;
+
+	/* safety net is from 1536 to 2047 */
+	g_tpm_mtu_cfg.safety_net_value = 0x600;
+	g_tpm_mtu_cfg.safety_net_mask = 0xfe00;
+
+	/*************************************************/
+	/* IPv4 MTU init                                 */
+	/*************************************************/
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_LEN, &range_conf);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_WARN(TPM_MTU_MOD, " no ipv4 PNC range\n");
+		return TPM_FAIL;
+	}
+	/* range size smaller than 2, illegal */
+	if (range_conf.range_size <= 2) {
+		TPM_OS_WARN(TPM_INIT_MOD, "PNC range(%d) too small to be initialized, size(%d) \n", TPM_PNC_IPV4_LEN,
+			    range_conf.range_size);
+		return TPM_FAIL;
+	}
+
+	/* we need to reserve 3 PNC entry for default and safety net     */
+	g_tpm_mtu_cfg.ipv4_mtu_cfg.rangeSize = range_conf.range_size - 3;
+
+	/*************************************************/
+	/* IPv6 MTU init                                 */
+	/*************************************************/
+#if 0
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_LEN, &range_conf);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_WARN(TPM_MTU_MOD, " no ipv6 PNC range\n");
+		return TPM_FAIL;
+	}
+	if (range_conf.range_size <= 2) {
+		TPM_OS_WARN(TPM_MTU_MOD, "PNC range(%d) too small to be initialized, size(%d) \n", TPM_PNC_IPV6_LEN,
+			    range_conf.range_size);
+		return TPM_FAIL;
+	}
+#endif
+	/* we need to reserve 3 PNC entry for default and safety net     */
+	g_tpm_mtu_cfg.ipv6_mtu_cfg.rangeSize = range_conf.range_size - 3;
+
+	/*tpm_mtu_ipv6_default_pnc_entry_insert(); */
+
+	/* set ipv4 US */
+	tpm_db_mtu_get_ipv4_mtu_us(&mtu_tmp);
+	tpm_proc_set_mtu(TPM_MTU_IPV4, TPM_UPSTREAM, mtu_tmp);
+	tpm_db_mtu_get_ipv4_pppoe_mtu_us(&mtu_tmp);
+	tpm_proc_set_pppoe_mtu(TPM_MTU_IPV4, TPM_UPSTREAM, mtu_tmp);
+
+	/* set ipv6 US
+	   tpm_db_mtu_get_ipv6_mtu_us(&mtu_tmp);
+	   tpm_proc_set_mtu(TPM_MTU_IPV6, TPM_UPSTREAM, mtu_tmp);
+	   tpm_db_mtu_get_ipv6_pppoe_mtu_us(&mtu_tmp);
+	   tpm_proc_set_pppoe_mtu(TPM_MTU_IPV6, TPM_UPSTREAM, mtu_tmp);
+	 */
+
+	/* set ipv4 DS */
+	tpm_db_mtu_get_ipv4_mtu_ds(&mtu_tmp);
+	tpm_proc_set_mtu(TPM_MTU_IPV4, TPM_DOWNSTREAM, mtu_tmp);
+
+	/* set ipv6 DS
+	   tpm_db_mtu_get_ipv6_mtu_ds(&mtu_tmp);
+	   tpm_proc_set_mtu(TPM_MTU_IPV6, TPM_DOWNSTREAM, mtu_tmp);
+	 */
+
+	return TPM_OK;
+}
+
+int32_t tpm_mtu_get_pnc_entry_from_index(int32_t index)
+{
+	int32_t loop;
+
+	for (loop = 0; loop < g_tpm_mtu_cfg.ipv4_mtu_cfg.pncIndex_cfg.pncNumber; loop++) {
+		if (index == g_tpm_mtu_cfg.ipv4_mtu_cfg.pncIndex_cfg.pncIndex[loop])
+			return loop;
+	}
+
+	return 0;
+}
+
+void tpm_mtu_print_len_chk_entry(tpm_mtu_pnc_entries_t *mtu_pnc_entries)
+{
+	int32_t entry_number;
+	int32_t loop, int_ret_code;
+	tpm_db_pnc_range_t range_data;
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_LEN, &range_data);
+	if (TPM_OK != int_ret_code) {
+		printk(KERN_WARNING "there is no Len check range\n");
+		return;
+	}
+
+	for (loop = 0; loop < mtu_pnc_entries->pncEntryNum; loop++) {
+		entry_number = tpm_mtu_get_pnc_entry_from_index(mtu_pnc_entries->pncIndex[loop]);
+		entry_number += range_data.pnc_range_conf.range_start;
+		printk("PNC entry number: %d\n", entry_number);
+		printk("length start: %d\n", mtu_pnc_entries->pktValue[loop]);
+		tpm_mtu_printBinary(mtu_pnc_entries->pktValue[loop]);
+		printk("\n");
+		tpm_mtu_printBinary(mtu_pnc_entries->pktMask[loop]);
+		printk("\n");
+	}
+
+}
+
+void tpm_mtu_print_len_chk_range(void)
+{
+	printk("==========================\n");
+	printk(" TPM IPv4 Length Check Range                \n");
+	printk("==========================\n");
+	printk(" Range size                        : %d\n", g_tpm_mtu_cfg.ipv4_mtu_cfg.rangeSize);
+	printk(" Current PNC entry number: %d\n", g_tpm_mtu_cfg.ipv4_mtu_cfg.pncIndex_cfg.pncNumber);
+
+	printk("__________________________\n");
+	printk("US pppoe to ipoe\n");
+	tpm_mtu_print_len_chk_entry(&g_tpm_mtu_cfg.ipv4_mtu_cfg.mtu_pppoe2ipoe_us_cfg);
+	printk("__________________________\n");
+	printk("US ipoe to max length \n");
+	tpm_mtu_print_len_chk_entry(&g_tpm_mtu_cfg.ipv4_mtu_cfg.mtu_ipoe2max_us_cfg);
+	printk("__________________________\n");
+	printk("DS ipoe to max length \n");
+	tpm_mtu_print_len_chk_entry(&g_tpm_mtu_cfg.ipv4_mtu_cfg.mtu_ds_cfg);
+	printk("__________________________\n");
+
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.h
new file mode 100755
index 0000000..82c7836
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_mtu.h
@@ -0,0 +1,142 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_mtu.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   jinghua
+*
+* DATE CREATED: 17 Aug 2011
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.2
+*
+*
+*******************************************************************************/
+#ifndef _TPM_MTU_H_
+#define _TPM_MTU_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+
+#define GET_BIT(VALUE, I)		((VALUE) & (1 << (I)))
+
+#define TPM_MTU_MAX_PNC_ENTRY_NUM	25
+
+typedef struct {
+	uint32_t pncEntryNum;
+	uint32_t pktMask[TPM_MTU_MAX_PNC_ENTRY_NUM];
+	uint32_t pktValue[TPM_MTU_MAX_PNC_ENTRY_NUM];
+	uint32_t pncIndex[TPM_MTU_MAX_PNC_ENTRY_NUM];
+} tpm_mtu_pnc_entries_t;
+
+typedef struct {
+	uint32_t pncNumber;
+	uint32_t pncIndex[3 * TPM_MTU_MAX_PNC_ENTRY_NUM];
+} tpm_mtu_pnc_index_t;
+
+typedef struct {
+	uint32_t rangeSize;
+	tpm_mtu_pnc_index_t pncIndex_cfg;
+	tpm_mtu_pnc_entries_t mtu_pppoe2ipoe_us_cfg;
+	tpm_mtu_pnc_entries_t mtu_ipoe2max_us_cfg;
+	tpm_mtu_pnc_entries_t mtu_ds_cfg;
+} tpm_mtu_ethtype_pnc_cfg_t;
+
+typedef struct {
+	uint32_t sys_pkt_len_max;
+	uint32_t safety_net_value;
+	uint32_t safety_net_mask;
+	tpm_mtu_ethtype_pnc_cfg_t ipv4_mtu_cfg;
+	tpm_mtu_ethtype_pnc_cfg_t ipv6_mtu_cfg;
+} tpm_mtu_pnc_cfg_t;
+
+/*************************************************************/
+/*               APIs                                        */
+/*************************************************************/
+
+int32_t tpm_proc_mtu_init(void);
+
+uint32_t tpm_proc_set_pppoe_mtu(uint32_t ethertype, uint32_t direction, uint32_t pppoe_mtu);
+uint32_t tpm_proc_set_mtu(uint32_t ethertype, uint32_t direction, uint32_t mtu);
+void tpm_mtu_print_len_chk_range(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* _TPM_PNCL_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.c
new file mode 100755
index 0000000..ea0a0a0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.c
@@ -0,0 +1,16173 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/*******************************************************************************
+* tpm_pkt_proc_logic.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.7
+*
+*
+*******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+/* Local definitions */
+
+typedef tpm_error_code_t (*tpm_proc_common_int_del_func_t) (uint32_t, uint32_t);
+
+int32_t tpm_proc_virt_uni_trg_port_validation(tpm_trg_port_type_t trg_port);
+
+
+
+#define IPV6_MOD(mod_bm)		(mod_bm & (TPM_IPV6_UPDATE | TPM_HOPLIM_DEC | TPM_IPV6_DST_SET | TPM_IPV6_SRC_SET))
+#define IPV4_MOD(mod_bm)		(mod_bm & (TPM_IPV4_UPDATE | TPM_TTL_DEC | TPM_IPV4_DST_SET | TPM_IPV4_SRC_SET))
+
+#define L4_CHECK_MOD(mod_bm)		((mod_bm & TPM_IPV4_DST_SET) || (mod_bm & TPM_IPV4_SRC_SET) || \
+						(mod_bm & TPM_L4_DST_SET) || (mod_bm & TPM_L4_SRC_SET))
+
+#define PARSE_FLAG_CHECK(val, bit)  ((val >> bit) & TPM_PARSE_FLAG_CHECK_TRUE_FALSE)
+
+#define IF_ERROR(ret)	\
+		if (ret != TPM_OK) {\
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " recvd ret_code(%d)\n", ret);\
+			return(ret);\
+		}
+#define IF_ERROR_I(ret, i)	\
+		if (ret != TPM_OK) {\
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " recvd ret_code(%d), ind(%d)\n", ret, i);\
+			return(ret);\
+		}
+
+#define MULTI_IP_2_MAC(macAdd, multiIp)		((uint8_t *)(macAdd))[0] = (uint8_t) 0x01;  \
+						((uint8_t *)(macAdd))[1] = (uint8_t) 0x00;  \
+						((uint8_t *)(macAdd))[2] = (uint8_t) 0x5e;  \
+						((uint8_t *)(macAdd))[3] = (uint8_t) multiIp[1];   \
+						((uint8_t *)(macAdd))[4] = (uint8_t) multiIp[2];   \
+						((uint8_t *)(macAdd))[5] = (uint8_t) multiIp[3];
+#define MULTI_IPV6_2_MAC(macAdd, multiIp)	((uint8_t *)(macAdd))[0] = (uint8_t) 0x33;  \
+						((uint8_t *)(macAdd))[1] = (uint8_t) 0x33;  \
+						((uint8_t *)(macAdd))[2] = (uint8_t) multiIp[12];  \
+						((uint8_t *)(macAdd))[3] = (uint8_t) multiIp[13];   \
+						((uint8_t *)(macAdd))[4] = (uint8_t) multiIp[14];   \
+						((uint8_t *)(macAdd))[5] = (uint8_t) multiIp[15];
+
+#define NO_FREE_ENTRIES()	\
+		if (free_entries == 0) {\
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "No free entries\n");\
+			return(TPM_FAIL);\
+		}
+
+/* Local variables */
+
+spinlock_t tpm_proc_api_call_lock;
+
+static tpm_cpu_loopback_t gs_cpu_loopback[TPM_MAX_CPU_LOOPBACK_NUM];
+static uint32_t gn_cpu_lpbk_entry_num = 0;
+
+static uint8_t tpm_igmp_gen_query_mac[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01};
+static uint8_t tpm_mld_gen_query_mac[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01};
+
+/* Bitmap of PNC port_ids */
+static uint32_t gmac_pnc_bm[3] = { TPM_BM_GMAC_0, TPM_BM_GMAC_1, TPM_BM_PMAC};
+
+
+
+static tpm_api_sup_param_val_t api_sup_param_val[] = {
+	/* tpm_pnc_api_num		Supported parse field bits
+		Supported parse flag bits
+		Forbidden actions */
+	{TPM_ADD_L2_PRIM_ACL_RULE,      TPM_L2_PARSE_BM_MASK,
+		(TPM_PARSE_FLAG_TAG1_MASK | TPM_PARSE_FLAG_TAG2_MASK),
+		(0)},
+	{TPM_ADD_L3_TYPE_ACL_RULE,      TPM_L3_PARSE_BM_MASK,
+		(TPM_PARSE_FLAG_TAG1_MASK | TPM_PARSE_FLAG_TAG2_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+	{TPM_ADD_IPV4_ACL_RULE, TPM_IPV4_PARSE_BM_MASK,
+		(TPM_PARSE_FLAG_TAG1_MASK | TPM_PARSE_FLAG_PPPOE_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+	{TPM_ADD_IPV6_NH_ACL_RULE,      0,
+		(TPM_PARSE_FLAG_PPPOE_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+	{TPM_ADD_IPV6_GEN_ACL_RULE, TPM_IPV6_GEN_BM_MASK,
+		(TPM_PARSE_FLAG_TAG1_MASK | TPM_PARSE_FLAG_PPPOE_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+	{TPM_ADD_IPV6_DIP_ACL_RULE, TPM_IPv6_PARSE_DIP,
+		(TPM_PARSE_FLAG_TAG1_MASK | TPM_PARSE_FLAG_PPPOE_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+	{TPM_ADD_IPV6_L4_PORTS_ACL_RULE, TPM_IPV6_L4_BM_MASK,
+		(TPM_PARSE_FLAG_L4P_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+	{TPM_ADD_IPV6_GEN_5T_RULE, TPM_IPV6_GEN_BM_MASK | TPM_IPV6_L4_BM_MASK,
+		(TPM_PARSE_FLAG_L4P_MASK | TPM_PARSE_FLAG_PPPOE_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+	{TPM_ADD_IPV6_DIP_5T_RULE, TPM_IPv6_PARSE_DIP | TPM_IPV6_GEN_BM_MASK | TPM_IPV6_L4_BM_MASK,
+		(TPM_PARSE_FLAG_L4P_MASK | TPM_PARSE_FLAG_PPPOE_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+	{TPM_ADD_IPV6_L4_PORTS_5T_RULE, TPM_IPV6_L4_BM_MASK,
+		(TPM_PARSE_FLAG_L4P_MASK | TPM_PARSE_FLAG_PPPOE_MASK | TPM_PARSE_FLAG_MTM_MASK | TPM_PARSE_FLAG_TO_CPU_MASK),
+		(TPM_ACTION_MTM | TPM_ACTION_SPEC_MC_VID)},
+};
+
+
+/* Function Declarations */
+int32_t tpm_proc_calc_cnm_rule_num(tpm_src_port_type_t src_port, uint32_t precedence, uint32_t *rule_num);
+
+int32_t tpm_proc_check_cnm_ipv4_pre_filter_triple_key_rule(tpm_src_port_type_t src_port, uint32_t partner_key_bm, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+int32_t tpm_proc_check_cnm_ipv4_pre_filter_double_key_rule(tpm_src_port_type_t src_port, uint32_t partner_key_bm, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+int32_t tpm_proc_check_cnm_ipv4_pre_filter_single_key_rule(tpm_src_port_type_t src_port, uint32_t partner_key_bm, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_triple_key_rule(tpm_src_port_type_t src_port, uint32_t key_idx, uint32_t key_pattern, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_double_key_rule(tpm_src_port_type_t src_port, uint32_t key_idx, uint32_t key_pattern, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_single_key_rule(tpm_src_port_type_t src_port, uint32_t key_idx, uint32_t key_pattern, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+int32_t tpm_proc_del_cnm_ipv4_pre_filter_rule(uint32_t src_port, uint32_t key_pattern, uint32_t key_idx);
+
+tpm_cnm_ipv4_pre_filter_rule_oper_t gs_cnm_ipv4_pre_filter_rule_oper[TPM_CNM_IPV4_PRE_FILTER_KEY_MAX][TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_KEY] =
+{
+	/* TPM_CNM_IPV4_PRE_FILTER_KEY_1 */
+	{
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_triple_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_triple_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_single_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_single_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+	},
+
+	/* TPM_CNM_IPV4_PRE_FILTER_KEY_2 */
+	{
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_triple_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_triple_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_single_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_single_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+	},
+
+	/* TPM_CNM_IPV4_PRE_FILTER_KEY_3 */
+	{
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_triple_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_triple_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_1_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_2_MASK|TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_double_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+		{
+			TPM_CNM_IPV4_PRE_FILTER_KEY_3_MASK,
+			tpm_proc_check_cnm_ipv4_pre_filter_single_key_rule,
+			tpm_proc_add_cnm_ipv4_pre_filter_single_key_rule,
+			tpm_proc_del_cnm_ipv4_pre_filter_rule,
+		},
+	},
+
+};
+
+uint32_t sg_l2_cnm_prec_ind[TPM_MAX_NUM_CTC_PRECEDENCE] = {0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x3, 0x7};
+uint32_t sg_ipv4_cnm_prec_mask[TPM_MAX_NUM_CTC_PRECEDENCE] = {0x0, 0x0, 0x1, 0x1, 0x2, 0x2, 0x4, 0x4};
+
+
+/* Local Functions */
+
+/* Function Declarations */
+tpm_error_code_t tpm_owner_id_check(tpm_api_type_t api_type, uint32_t owner_id);
+int32_t tpm_proc_multicast_reset(void);
+
+uint32_t tpm_proc_bc_check(tpm_l2_acl_key_t *l2_key)
+{
+	uint32_t i;
+
+	for (i = 0; i < 6; i++) {
+		if ((l2_key->mac.mac_da[i] & l2_key->mac.mac_da_mask[i]) != 0xFF)
+			return(TPM_FALSE);
+	}
+
+	return(TPM_TRUE);
+}
+
+
+uint32_t tpm_proc_mc_check(tpm_l2_acl_key_t *l2_key)
+{
+
+	if ((l2_key->mac.mac_da[0] & l2_key->mac.mac_da_mask[0]) & 0x01)
+		return(TPM_TRUE);
+
+	return(TPM_FALSE);
+}
+
+/*******************************************************************************
+* tpm_proc_src_port_gmac_bm_map()
+*
+* DESCRIPTION:    The function correlates a source_port to it's Rx GMAC(s) by means of the GMAC Functionality
+*
+*
+* INPUTS:
+* src_port         - source port in API format
+*
+* OUTPUTS:
+* gmac_bm          - Bitmap of the GMACs relevant to set in TCAM
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_src_port_gmac_bm_map(tpm_src_port_type_t src_port,
+				      tpm_gmac_bm_t *gmac_bm)
+{
+	tpm_gmacs_enum_t gmac_i;
+	tpm_gmac_bm_t l_gmac_bm = 0;
+	tpm_db_gmac_func_t gmac_func;
+
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i <= TPM_MAX_GMAC; gmac_i++) {
+		if (!tpm_db_gmac_valid(gmac_i))
+			continue;
+
+		tpm_db_gmac_func_get(gmac_i, &gmac_func);
+
+		/* WAN possiblilties */
+		if (FROM_WAN(src_port) && GMAC_IS_WAN(gmac_func))
+			l_gmac_bm |= gmac_pnc_bm[gmac_i];
+
+		/* LAN possiblilties  (Note: can be from both WAN or LAN) */
+
+		/* From UNI_$, but not Virtual_Port */
+		if (src_port == TPM_SRC_PORT_UNI_VIRT) {
+			if (GMAC_IS_UNI_LAN(gmac_func)) {
+				l_gmac_bm = gmac_pnc_bm[gmac_i];
+				break;
+			}
+
+			if (GMAC_IS_LAN(gmac_func))
+				l_gmac_bm = gmac_pnc_bm[gmac_i];
+		/* Any other UNI */
+		} else if (FROM_SPEC_UNI(src_port) && GMAC_IS_LAN(gmac_func)) {
+			l_gmac_bm = gmac_pnc_bm[gmac_i];
+			break;
+		/* Any remaining LAN option (UNI_ANY or WAN_OR_LAN) */
+		} else if (FROM_LAN(src_port) && (GMAC_IS_UNI_LAN(gmac_func) || GMAC_IS_LAN(gmac_func)))
+			l_gmac_bm |= gmac_pnc_bm[gmac_i];
+	}
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "gmac_bm(0x%x)\n", l_gmac_bm);
+	*gmac_bm = l_gmac_bm;
+	return(TPM_OK);
+}
+
+void tpm_proc_set_int_structs(tpm_pncl_pnc_full_t *pnc_data, tpm_pncl_offset_t *start_offset,
+			      tpm_rule_entry_t *api_data, tpm_db_pnc_conn_t *pnc_conn,
+			      tpm_db_pnc_range_t *range_data)
+{
+	/* Set Structs to zero */
+	memset(pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(api_data, 0, sizeof(tpm_rule_entry_t));
+	memset(pnc_conn, 0, sizeof(tpm_db_pnc_conn_t));
+	memset(range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	return;
+}
+
+int32_t tpm_proc_create_acl_pnc_entry(tpm_api_sections_t api_section, uint32_t rule_num,
+				      tpm_pncl_pnc_full_t *pnc_data, uint32_t *pnc_entry, uint32_t *api_rng_entries)
+{
+
+	tpm_db_pnc_range_t range_data;
+	uint32_t pnc_range_id;
+	uint32_t pnc_range_start, api_start, pnc_stop_entry, l_api_rng_entries;
+	int32_t int_ret_code;
+
+	/* Get pnc_range_id */
+	int_ret_code = tpm_db_api_section_main_pnc_get(api_section, &pnc_range_id);
+	IF_ERROR(int_ret_code);
+
+	/*** Calculate PNC Entry ***/
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(pnc_range_id, &range_data);
+	IF_ERROR(int_ret_code);
+
+	pnc_range_start = range_data.pnc_range_conf.range_start;
+	api_start = range_data.pnc_range_conf.api_start;
+
+	/* Get number of existing api entries */
+	int_ret_code = tpm_db_api_section_num_entries_get(api_section, &l_api_rng_entries);
+	IF_ERROR(int_ret_code);
+
+	/* Calculate absolute PNC entry number to execute */
+	*pnc_entry = (pnc_range_start + api_start) + rule_num;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d), l_api_rng_entries(%d)\n", rule_num, l_api_rng_entries);
+
+	/* Call PNC Entry Insert, if this is not the api_section's new last entry */
+	if (rule_num < l_api_rng_entries) {
+		pnc_stop_entry = (pnc_range_start + api_start) + (l_api_rng_entries - 1);
+		int_ret_code = tpm_pncl_entry_insert(*pnc_entry, pnc_stop_entry, pnc_data);
+		IF_ERROR(int_ret_code);
+	} else {		/* Otherwise just set the entry (no insertion) */
+
+		int_ret_code = tpm_pncl_entry_set(*pnc_entry, pnc_data);
+		IF_ERROR(int_ret_code);
+	}
+
+	/* Decrease number of free entries in pnc_range */
+	int_ret_code = tpm_db_pnc_rng_free_ent_dec(pnc_range_id);
+	IF_ERROR(int_ret_code);
+
+	*api_rng_entries = l_api_rng_entries;
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_create_table_pnc_entry(tpm_api_sections_t api_section, uint32_t rule_num, uint32_t update_sram,
+					tpm_pncl_pnc_full_t *pnc_data, uint32_t *pnc_entry,
+					uint32_t *api_rng_entries)
+{
+
+	tpm_db_pnc_range_t range_data;
+	uint32_t pnc_range_id;
+	uint32_t pnc_range_start, api_start, l_api_rng_entries;
+	int32_t int_ret_code;
+
+	/* Get pnc_range_id */
+	int_ret_code = tpm_db_api_section_main_pnc_get(api_section, &pnc_range_id);
+	IF_ERROR(int_ret_code);
+
+	/*** Calculate PNC Entry ***/
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(pnc_range_id, &range_data);
+	IF_ERROR(int_ret_code);
+
+	/* check the rule_number */
+	if (rule_num > range_data.pnc_range_conf.api_end) {
+		/* rule_number out of range */
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " rule_num(%d) out of range, range api_end(%d)\n",
+			     rule_num, range_data.pnc_range_conf.api_end);
+		return(TPM_FAIL);
+	}
+	pnc_range_start = range_data.pnc_range_conf.range_start;
+	api_start = range_data.pnc_range_conf.api_start;
+
+	/* Get number of existing api entries */
+	int_ret_code = tpm_db_api_section_num_entries_get(api_section, &l_api_rng_entries);
+	IF_ERROR(int_ret_code);
+
+	/* Calculate absolute PNC entry number to execute */
+	*pnc_entry = (pnc_range_start + api_start) + rule_num;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d), l_api_rng_entries(%d)\n", rule_num, l_api_rng_entries);
+
+	if (update_sram) {
+		/* Just update sram  */
+		int_ret_code = tpm_pncl_update_sram(*pnc_entry, pnc_data);
+		IF_ERROR(int_ret_code);
+	} else {
+		/* Just set the entry (no insertion) */
+		int_ret_code = tpm_pncl_entry_set(*pnc_entry, pnc_data);
+		IF_ERROR(int_ret_code);
+
+		/* Decrease number of free entries in pnc_range */
+		int_ret_code = tpm_db_pnc_rng_free_ent_dec(pnc_range_id);
+		IF_ERROR(int_ret_code);
+	}
+
+	*api_rng_entries = l_api_rng_entries;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_trg_port_gmac_map()
+*
+* DESCRIPTION:    The function correlates a source_port to it's Rx GMAC(s) by means of the GMAC Functionality
+*
+*
+* INPUTS:
+* trg_port         - source port in API format
+*
+* OUTPUTS:
+* gmac_port        - Target GMAC
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_trg_port_gmac_map(tpm_trg_port_type_t trg_port, tpm_gmacs_enum_t *gmac_port)
+{
+	tpm_gmacs_enum_t gmac_i;
+	tpm_db_gmac_func_t gmac_func;
+	tpm_eth_complex_profile_t profile;
+
+	if (gmac_port == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid pointer-NULL \n");
+		return(ERR_GENERAL);
+	}
+
+	/* get board profile */
+	profile = tpm_db_eth_cmplx_profile_get();
+
+	(*gmac_port) = -1;
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i <= TPM_MAX_GMAC; gmac_i++) {
+		if (!tpm_db_gmac_valid(gmac_i))
+			continue;
+
+		tpm_db_gmac_func_get(gmac_i, &gmac_func);
+
+		if (((TRG_WAN(trg_port)) && GMAC_IS_WAN(gmac_func))
+		    || ((TRG_UNI(trg_port)) && ((!tpm_db_gmac1_lpbk_en_get()) ? GMAC_IS_LAN(gmac_func) : GMAC_IS_UNI_LAN(gmac_func)))) {
+			(*gmac_port) = gmac_i;
+			break;
+		}
+	}
+	return(TPM_OK);
+}
+
+uint32_t tpm_proc_gmac1_phy_src_port(tpm_src_port_type_t src_port)
+{
+	tpm_db_gmac_func_t gmac_func;
+
+	if (src_port == TPM_SRC_PORT_UNI_VIRT) {
+		tpm_db_gmac_func_get(TPM_ENUM_GMAC_1, &gmac_func);
+		if (gmac_func != TPM_GMAC_FUNC_VIRT_UNI)
+			return(TPM_TRUE);
+	}
+
+	return(TPM_FALSE);
+}
+
+/*******************************************************************************
+* tpm_proc_all_gmac_bm()
+*
+* DESCRIPTION:  Gets a TCAMport_bitmap of all active GMACs
+*
+* INPUTS:
+*
+* RETURNS:
+* Returns a bitmap of all the active GMACs
+*
+* COMMENTS:  Perfom only DB integrity checks, not data correctness checks
+*
+*******************************************************************************/
+uint32_t tpm_proc_all_gmac_bm(void)
+{
+	tpm_gmacs_enum_t gmac_i;
+	tpm_gmac_bm_t l_gmac_bm = 0;
+	tpm_db_gmac_func_t gmac_func;
+
+	for (gmac_i = TPM_ENUM_GMAC_0; gmac_i <= TPM_MAX_GMAC; gmac_i++) {
+		if (!tpm_db_gmac_valid(gmac_i))
+			continue;
+
+		tpm_db_gmac_func_get(gmac_i, &gmac_func);
+
+		if (gmac_func != TPM_GMAC_FUNC_NONE)
+			l_gmac_bm |= gmac_pnc_bm[gmac_i];
+	}
+	return(l_gmac_bm);
+}
+
+int32_t tpm_proc_create_mod(tpm_pkt_action_t pkt_act, tpm_trg_port_type_t trg_port, tpm_pkt_mod_t *pkt_mod,
+			    tpm_pkt_mod_bm_t pkt_mod_bm, tpm_pkt_mod_int_bm_t int_mod_bm, uint32_t *mod_entry,
+			    uint32_t *trg_gmac)
+{
+	int32_t ret_code;
+
+	if (SET_MOD(pkt_act)) {
+		/* Currently supporting Vlan operation only */
+		/* Get dest. gmac */
+		tpm_proc_trg_port_gmac_map(trg_port, trg_gmac);
+		if (*trg_gmac == -1) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "pkt modification not possible on this target gmac(%d) \n",
+				     *trg_gmac);
+			return(ERR_ACTION_INVALID);
+		}
+
+		ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, *trg_gmac, pkt_mod_bm, int_mod_bm, pkt_mod, mod_entry);
+		IF_ERROR(ret_code);
+	}
+	return(TPM_OK);
+}
+
+void tpm_proc_set_api_moddata(tpm_pkt_action_t pkt_act, uint32_t trg_gmac, tpm_db_mod_conn_t *mod_con,
+			      uint32_t mod_entry)
+{
+	/* Set modification data in API data */
+	if (SET_MOD(pkt_act)) {
+		mod_con->mod_cmd_ind = mod_entry;
+		mod_con->mod_cmd_mac = trg_gmac;
+	} else {
+		mod_con->mod_cmd_ind = 0;
+		mod_con->mod_cmd_mac = TPM_INVALID_GMAC;
+	}
+	return;
+}
+
+int32_t tpm_proc_check_missing_data(tpm_rule_action_t *rule_action,
+				    tpm_pkt_mod_t *pkt_mod,
+				    tpm_pkt_frwd_t *pkt_frwd,
+				    void *parsing_key,
+				    tpm_pkt_action_t pkt_act,
+				    tpm_parse_fields_t parse_rule_bm)
+{
+
+	/* Check keys exist for parse fields */
+	if (rule_action == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "rule_action cannot be NULL\n");
+		return(ERR_ACTION_INVALID);
+	}
+
+	if ((pkt_mod == NULL) && (SET_MOD(pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Mod requested with NULL pointer\n");
+		return(ERR_MOD_INVALID);
+	}
+
+	if ((pkt_frwd == NULL) && ((SET_TARGET_PORT(pkt_act)) || SET_TARGET_QUEUE(pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target set requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	if ((parsing_key == NULL) && (parse_rule_bm != 0)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parsing requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_check_valid_target(tpm_dir_t dir,
+				    tpm_db_pon_type_t pon_type,
+				    tpm_trg_port_type_t trg_port,
+				    uint8_t trg_queue,
+				    tpm_pkt_action_t pkt_act)
+{
+
+	tpm_init_virt_uni_t virt_uni_info;
+	int32_t ret_code;
+	tpm_gmacs_enum_t act_wan= tpm_db_active_wan_get();
+
+	/* Check Valid Target */
+	if (SET_TARGET_PORT(pkt_act)) {
+		if (TO_PON(dir, trg_port, pon_type, act_wan) ||
+		    TO_ETHWAN(dir, trg_port, act_wan) || TO_CPU(trg_port)) {
+		    /* PON CPU is OK */
+		} else if (TO_LAN(dir, trg_port)){
+			/* check target uni port valid or not */
+			ret_code = tpm_proc_check_dst_uni_port(trg_port);
+			IF_ERROR(ret_code);
+		} else {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "* dir=%d, trg_port=%d, pon_type=%d *\r\n", dir, trg_port,
+				     pon_type);
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Illegal Target Port\n");
+			return(ERR_FRWD_INVALID);
+		}
+	}
+	/* check valid target when virt uni via GMAC1 feature is enabled */
+	/* not all target port combinations are supported when WiFi via GMAC1 = UNI_4 feature is enabled */
+	ret_code = tpm_db_virt_info_get(&virt_uni_info);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " virt uni recvd ret_code(%d)\n", ret_code);
+		return(ERR_FRWD_INVALID);
+	}
+	if ((virt_uni_info.enabled == 1) && (dir == TPM_DIR_DS) && (SET_TARGET_PORT(pkt_act))) {
+		/* virt uni feature is enabled - validate and recalculate the mh_reg */
+		ret_code = tpm_proc_virt_uni_trg_port_validation(trg_port);
+		if (ret_code != TPM_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "* dir=%d, trg_port=%d, pon_type=%d *\r\n", dir, trg_port,
+				     pon_type);
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Illegal Virt UNI Target Port.\n");
+			return(ERR_FRWD_INVALID);
+		}
+	}
+
+	/* Check Valid Queue */
+	/* TODO - Check Queue depending on actual queues in target or in Rx */
+	if (SET_TARGET_QUEUE(pkt_act) && (trg_queue >= TPM_MAX_NUM_TX_QUEUE)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target Queue Out of Range\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_check_pkt_action(tpm_pkt_action_t pkt_act,
+				  tpm_trg_port_type_t trg_port,
+				  tpm_pkt_mod_t *pkt_mod,
+				  tpm_pkt_mod_bm_t pkt_mod_bm)
+{
+	if (PKT_DROP(pkt_act)) {
+		if (SET_TARGET_PORT(pkt_act) || SET_TARGET_QUEUE(pkt_act) || SET_MOD(pkt_act) || SET_CPU(pkt_act)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet dropped action, no other packet actions are allowed \n");
+			return(ERR_ACTION_INVALID);
+		}
+	}
+	if (SET_CPU(pkt_act)) {
+		if ((!SET_TARGET_PORT(pkt_act)) || (trg_port != TPM_TRG_PORT_CPU)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,"trg_port %x \n", trg_port);
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+				     "For packet TO_CPU action, target port should be set and equal to CPU port.\n");
+			return(ERR_ACTION_INVALID);
+		}
+	}
+
+	if (SET_MOD(pkt_act)) {
+		/* if split mod, do not check trgt port */
+		if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable())
+			&& (pkt_mod_bm == TPM_VLAN_MOD)
+			&& (pkt_mod->vlan_mod.vlan_op == VLANOP_SPLIT_MOD_PBIT)) {
+
+		} else if ((!SET_TARGET_PORT(pkt_act)) || (trg_port == TPM_TRG_PORT_CPU)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+				     "For rule SET_MOD action, target port should be set and should not be CPU port. \n");
+			return(ERR_ACTION_INVALID);
+		}
+	}
+
+	return(TPM_OK);
+}
+
+#if 0				/*Phase1 - no longer has below limitation */
+int32_t tpm_proc_pkt_mod_check(tpm_pkt_action_t pkt_act, tpm_pkt_mod_bm_t pkt_mod_bm, tpm_pkt_mod_t *pkt_mod)
+{
+	if (SET_MOD(pkt_act)) {
+		if (pkt_mod_bm != TPM_VLAN_MOD) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Support only VLAN operations \n");
+			return(ERR_MOD_INVALID);
+		}
+		if (pkt_mod->vlan_mod.vlan_op >= VLANOP_ILLEGAL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Illegal VLAN Operation \n");
+			return(ERR_MOD_INVALID);
+		}
+	}
+	return(TPM_OK);
+}
+#endif
+
+/* in PARSE_FLAG_BM - bit#0 and bit#1 - TRUE and FALSE - should not be set simultaneously
+   check pairs of bits in the parse_flags_bm for validation */
+int32_t tpm_proc_check_parse_flag_valid(tpm_parse_flags_t parse_flags_bm)
+{
+	int32_t i;
+
+	for (i = 0; i < TPM_PARSE_FLAG_CHECK_FIELD_NUMBER; i++) {
+		if (PARSE_FLAG_CHECK(parse_flags_bm, i * 2) == TPM_PARSE_FLAG_CHECK_TRUE_FALSE)
+			return(ERR_PARSE_MAP_INVALID);
+	}
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_src_port_check()
+*
+* DESCRIPTION:    The function checks if the requested source port is legit.
+*
+* INPUTS:
+* src_port         - source port in API format
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_src_port_check(tpm_src_port_type_t src_port)
+{
+	tpm_db_pon_type_t pon_type;
+	int32_t ret_code;
+	tpm_db_chip_conn_t dummy_chip_con;
+	tpm_db_int_conn_t dummy_int_conn;
+	uint32_t dummy_switch_port;
+	tpm_init_virt_uni_t virt_uni_info;
+
+	/* Check Port exists */
+	if (src_port == TPM_SRC_PORT_WAN) {
+		if (TPM_ENUM_PMAC == tpm_db_active_wan_get()){
+       		tpm_db_pon_type_get(&pon_type);
+			if (pon_type >= TPM_NONE) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "No pon_type defined (0x%x)\n", pon_type);
+				return(TPM_FAIL);
+			}
+		}
+	} else if (FROM_SPEC_UNI(src_port) && (src_port != TPM_SRC_PORT_UNI_VIRT)) {
+		/* Check if port exists */
+		ret_code = tpm_db_eth_port_conf_get(src_port,
+						    &dummy_chip_con,
+						    &dummy_int_conn,
+						    &dummy_switch_port);
+		if (ret_code != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Source UNI Port (%d) is not valid port \n", src_port);
+			return(TPM_FAIL);
+		}
+	} else if (src_port == TPM_SRC_PORT_UNI_ANY)
+		return(TPM_OK);
+	else if (src_port == TPM_SRC_PORT_UNI_VIRT) {
+		tpm_db_virt_info_get(&virt_uni_info);
+		if (TPM_VIRT_UNI_DISABLED == virt_uni_info.enabled) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "UNI_VIRT is not enabled\n");
+			return(ERR_SRC_PORT_INVALID);
+		}
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Source UNI Port (%d) out of range \n", src_port);
+		return(TPM_FAIL);
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_src_port_dir_map()
+*
+* DESCRIPTION:    The function maps the source port to the packet direction.
+*
+* INPUTS:
+* src_port         - source port in API format
+*
+* OUTPUTS:
+* dir              - Upstream or downstream direction
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_src_port_dir_map(tpm_src_port_type_t src_port, tpm_dir_t *dir)
+{
+	if (src_port == TPM_SRC_PORT_WAN)
+		(*dir) = TPM_DIR_DS;
+	else
+		(*dir) = TPM_DIR_US;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " Source port(%d), direction(%d) \n", src_port, (*dir));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_setstage_done()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* rule_action      -
+* sram_data
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_proc_setstage_done(tpm_rule_action_t *rule_action, tpm_pncl_sram_data_t *sram_data)
+{
+	sram_data->next_lu_id = 0;
+	sram_data->next_lu_off_reg = 0;
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_LUD;
+	return;
+}
+
+/*******************************************************************************
+* tpm_proc_set_mod()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* rule_action      -
+* sram_data
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_proc_set_mod(tpm_rule_action_t *rule_action, tpm_pncl_sram_data_t *sram_data, uint32_t mod_cmd)
+{
+	if (SET_MOD(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_cmd;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_cmd);
+	}
+}
+
+/*******************************************************************************
+* tpm_proc_set_cust_cpu_packet_parse()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* rule_action      -
+* sram_data
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_proc_set_cust_cpu_packet_parse(tpm_rule_action_t *rule_action, tpm_pncl_sram_data_t *sram_data)
+{
+	/* set the RI = TPM_PNCL_SET_RX_SPECIAL for packets with CUSTOMIZE flag */
+	if (SET_CUST(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_RX_SPECIAL;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Customization flag.\n");
+	}
+
+}
+
+/*******************************************************************************
+* tpm_proc_set_trgt()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* rule_action      -
+* sram_data
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_set_trgt_queue(tpm_rule_action_t *rule_action,
+				tpm_pkt_frwd_t *pkt_frwd,
+				tpm_dir_t dir,
+				tpm_db_pon_type_t pon_type,
+				tpm_pncl_sram_data_t *sram_data)
+{
+	uint32_t i;
+
+	if (SET_TARGET_PORT(rule_action->pkt_act)) {
+		tpm_gmacs_enum_t act_wan= tpm_db_active_wan_get();
+
+		/* Add Target Txp to update BM */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
+
+		/* Set PNC FlowId Target */
+		if (TO_PON(dir, pkt_frwd->trg_port, pon_type, act_wan)) {
+			for (i = 0; i < 8; i++) {
+				if (pkt_frwd->trg_port == (uint32_t) (TPM_TRG_TCONT_0 << i))
+					break;
+			}
+			sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_PMAC0 + i;
+		} else if (TO_ETHWAN(dir, pkt_frwd->trg_port, act_wan)) {
+			switch (act_wan) {
+			case TPM_ENUM_GMAC_0:
+				sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_GMAC0;
+				break;
+			case TPM_ENUM_GMAC_1:
+				sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_GMAC1;
+				break;
+			default:
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Set Target, act_wan(%d) invalid",act_wan);
+				return(TPM_FAIL);
+			}
+		} else if (TO_LAN(dir, pkt_frwd->trg_port)) {
+			tpm_trg_port_type_t pnc_target;
+
+			if (tpm_db_to_lan_gmac_get(pkt_frwd->trg_port, &pnc_target) != TPM_DB_OK){
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_db_to_lan_gmac_get failed trg_port 0x%x\n",
+					     pkt_frwd->trg_port);
+				return(TPM_FAIL);
+       		}
+			sram_data->flow_id_sub.pnc_target = pnc_target;
+		} else if (TO_CPU(pkt_frwd->trg_port)) {
+			sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+		} else {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Set Target received, no legitimate Target Found \n");
+			return(TPM_FAIL);
+		}
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Target(%d)\n", sram_data->flow_id_sub.pnc_target);
+		/* If target is GPON, set GEM and MH */
+		if (TO_GPON(dir, pkt_frwd->trg_port, pon_type, act_wan)) {
+			sram_data->mh_reg.mh_set = TPM_TRUE;
+			sram_data->mh_reg.mh_reg = 1;
+			sram_data->sram_updt_bm |= TPM_PNCL_SET_GEM;
+			sram_data->flow_id_sub.gem_port = pkt_frwd->gem_port;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set GemPort(%d)\n", pkt_frwd->gem_port);
+		}
+	}
+	if (SET_TARGET_QUEUE(rule_action->pkt_act)) {
+		/* Set Queue */
+		sram_data->pnc_queue = pkt_frwd->trg_queue;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Tx Queue (%x)\n", pkt_frwd->trg_queue);
+	} else {
+		sram_data->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "No Tx Queue Updat\n");
+	}
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_api_ent_check()
+*
+* DESCRIPTION:    The function checks if there is a free_entry to add an API entry
+*
+* INPUTS:
+* section          - Section of the API acl/table
+* api_rng_type     - The Type of the API, ACL or Table
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_add_api_ent_check(tpm_api_sections_t section, tpm_range_type_t api_rng_type, uint32_t rule_num)
+{
+	int32_t ret_code, last_valid;
+	uint32_t api_rng_size, num_valid_entries, tbl_start;
+	tpm_pnc_ranges_t prim_pnc_range;
+
+	/* TODO - make the api_rng_type part of the api_rng database configuration */
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " api_sec(%d), api_rng_type(%d) \n", section, api_rng_type);
+
+	/* Check API range exists */
+	ret_code = tpm_db_api_section_get(section, &api_rng_size,
+					  &num_valid_entries, &prim_pnc_range, &last_valid, &tbl_start);
+	IF_ERROR(ret_code);
+
+	/* Check possible to add another entry */
+	if (num_valid_entries > (api_rng_size-1)) {
+		/* If the range mode is table, it is unnecessary to check */
+		if (api_rng_type == TPM_RANGE_TYPE_ACL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " api_sec(%d), has no free entries \n", section);
+			return(TPM_FAIL);
+		}
+	}
+	/* Check last_valid consistency, for acl type range */
+	if (api_rng_type == TPM_RANGE_TYPE_ACL) {
+		if (last_valid != ((int32_t) (num_valid_entries) - (int32_t) (1))) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "DB problem, api_section(%d),num_entries(%d),last_valid(%d)\n",
+				     section, num_valid_entries, last_valid);
+			return(TPM_FAIL);
+		}
+
+		/* make sure in api table there will not be a gap after insert this rule */
+		if (rule_num > num_valid_entries) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "api table there will not be a gap after insert the api,"
+				     "api_section(%d), num_entries(%d),last_valid(%d), rule_num(%d)\n",
+				     section, num_valid_entries, last_valid, rule_num);
+			return(TPM_FAIL);
+		}
+	}
+	return(TPM_OK);
+}
+
+
+int32_t tpm_proc_check_api_busy(tpm_api_type_t api_type, uint32_t rule_num)
+{
+	uint32_t  db_ret_code;
+	int32_t rc_code = TPM_RC_OK;
+	tpm_api_sections_t api_section;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t rangConf;
+
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "api_type(%d) rule_num(%d)\n", api_type, rule_num);
+
+
+	/* Get api_section, range_Id, range configuration, to get range type */
+	db_ret_code = tpm_db_api_section_get_from_api_type(api_type, &api_section);
+	IF_ERROR(db_ret_code);
+	db_ret_code = tpm_db_api_section_main_pnc_get(api_section, &range_id);
+	IF_ERROR(db_ret_code);
+	db_ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(db_ret_code);
+
+
+	/* Check API Section Busy */
+	/* In ACL Mode   - concurrency not supported.
+	   In TABLE Mode - concurrency supported, but not on the same entry */
+
+	spin_lock_bh(&tpm_proc_api_call_lock);
+	if ((rangConf.range_type == TPM_RANGE_TYPE_ACL) && ((tpm_db_get_api_busy(api_type))== TPM_TRUE))
+		rc_code = ERR_API_BUSY;
+	else if ((rangConf.range_type == TPM_RANGE_TYPE_TABLE) &&
+		 ((tpm_db_get_api_rule_num_busy(api_type, rule_num)) == TPM_TRUE))
+		rc_code = ERR_API_BUSY;
+	else {
+		db_ret_code = tpm_db_set_api_busy(api_type, rule_num);
+		if (db_ret_code != TPM_DB_OK)
+			rc_code = ERR_API_BUSY; /* Table full */
+	}
+	spin_unlock_bh(&tpm_proc_api_call_lock);
+	return(rc_code);
+}
+
+
+int32_t tpm_proc_api_busy_done(tpm_api_type_t api_type, uint32_t rule_num)
+{
+	int32_t rc_code = TPM_RC_OK;
+	uint32_t  db_ret_code;
+
+	spin_lock_bh(&tpm_proc_api_call_lock);
+	db_ret_code = tpm_db_set_api_free(api_type, rule_num);
+	if (db_ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Error releasing api_busy: api_type(%d) rule_num(%d)\n", api_type, rule_num);
+		rc_code = ERR_GENERAL;
+	}
+	spin_unlock_bh(&tpm_proc_api_call_lock);
+	return(rc_code);
+}
+
+
+
+int32_t tpm_proc_parse_flag_ai_tcam_build(tpm_ai_vectors_t *ai_fields,
+					  uint32_t parse_flags,
+					  long long parse_int_flags,
+					  uint32_t *ai_data,
+					  uint32_t *ai_mask)
+{
+	uint32_t ai_val;
+	tpm_init_double_tag_t dbl_tag;
+	tpm_src_port_type_t src_port_tmp;
+
+	/* Parsing flags */
+
+	/*BIT_0 */
+	if (parse_flags & TPM_PARSE_FLAG_TAG1_MASK) {
+		ai_val = ((parse_flags & TPM_PARSE_FLAG_TAG1_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_TAG1_BIT_OFF);
+		*ai_mask |= TPM_AI_TAG1_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_NH2_ITER_MASK) {
+		ai_val = ((parse_int_flags & TPM_PARSE_FLAG_NH2_ITER_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_TAG1_BIT_OFF);
+		*ai_mask |= TPM_AI_TAG1_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_IPV6_SUBFLOW_PARSE) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " ipv6 ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= (((ai_fields->ipv6_subflow) << TPM_AI_IPV6_SUBFLOW_PART1_BIT_OFF) & TPM_AI_IPV6_SUBFLOW_PART1_MASK);
+		*ai_mask |= TPM_AI_IPV6_SUBFLOW_PART1_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_IPV6_MC_SIP_PARSE) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " ipv6 ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= (((ai_fields->ipv6_mc_sip_indx) << TPM_AI_IPV6_MC_SIP_PART1_BIT_OFF) & TPM_AI_IPV6_MC_SIP_PART1_MASK);
+		*ai_mask |= TPM_AI_IPV6_MC_SIP_PART1_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_CNM_IPV4_MASK) {
+		ai_val = ((parse_int_flags & TPM_PARSE_FLAG_CNM_IPV4_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_CNM_IPV4_BIT_OFF);
+		*ai_mask |= TPM_AI_CNM_IPV4_MASK;
+	}
+
+	/*BIT_1 */
+	if (parse_flags & TPM_PARSE_FLAG_TAG2_MASK) {
+		tpm_db_double_tag_support_get(&dbl_tag);
+		if (TPM_DOUBLE_TAG_ENABLED == dbl_tag) {
+			ai_val = ((parse_flags & TPM_PARSE_FLAG_TAG2_TRUE) ? 1 : 0);
+			*ai_data |= (ai_val << TPM_AI_TAG2_BIT_OFF);
+			*ai_mask |= TPM_AI_TAG2_MASK;
+		} else {
+			ai_val = ((parse_flags & TPM_PARSE_FLAG_TAG1_TRUE) ? 1 : 0);
+			*ai_data |= (ai_val << TPM_AI_TAG1_BIT_OFF);
+			*ai_mask |= TPM_AI_TAG1_MASK;
+		}
+	}
+
+	if (parse_flags & TPM_PARSE_FLAG_PPPOE_MASK) {
+		ai_val = ((parse_flags & TPM_PARSE_FLAG_PPPOE_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_PPPOE_BIT_OFF);
+		*ai_mask |= TPM_AI_PPPOE_MASK;
+	}
+
+	if (parse_flags & TPM_PARSE_FLAG_L4P_MASK) {
+		ai_val = ((parse_flags & TPM_PARSE_FLAG_L4_UDP) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_L4P_BIT_OFF);
+		*ai_mask |= TPM_AI_L4P_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_IPV4_PRE_KEY_PARSE) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " ipv4 pre-filter key ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= (ai_fields->ipv4_pre_key << TPM_AI_CNM_IPV4_PRE_KEY_BIT_OFF);
+		*ai_mask |= (ai_fields->ipv4_pre_key << TPM_AI_CNM_IPV4_PRE_KEY_BIT_OFF);
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_CNM_PREC_PARSE) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " cnm precedence ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= (ai_fields->cnm_prec << TPM_AI_CNM_PREC_BIT_OFF);
+		*ai_mask |= (ai_fields->cnm_prec << TPM_AI_CNM_PREC_BIT_OFF);
+	}
+
+	/*BIT_2 */
+	if (parse_flags & TPM_PARSE_FLAG_MTM_MASK) {
+		ai_val = ((parse_flags & TPM_PARSE_FLAG_MTM_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_MTM_BIT_OFF);
+		*ai_mask |= TPM_AI_MTM_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_IPV6_MC_SIP_PARSE) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " ipv6 ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= (((ai_fields->ipv6_mc_sip_indx >> (TPM_AI_IPV6_MC_SIP_PART1_BIT_OFF + 1))
+			      << TPM_AI_IPV6_MC_SIP_PART2_BIT_OFF) & TPM_AI_IPV6_MC_SIP_PART2_MASK);
+		*ai_mask |= TPM_AI_IPV6_MC_SIP_PART2_MASK;
+	}
+
+	/*BIT_3 */
+	if (parse_flags & TPM_PARSE_FLAG_TO_CPU_MASK) {
+		ai_val = ((parse_flags & TPM_PARSE_FLAG_TO_CPU_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_TO_CPU_BIT_OFF);
+		*ai_mask |= TPM_AI_TO_CPU_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_SPLIT_MOD_MASK) {
+		ai_val = ((parse_int_flags & TPM_PARSE_FLGA_SPLIT_MOD_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_SPLIT_MOD_BIT_OFF);
+		*ai_mask |= TPM_AI_SPLIT_MOD_MASK;
+	}
+
+	/*BIT_4 */
+	if (parse_int_flags & TPM_PARSE_FLAG_UNI_PORT_PARSE) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " src_port ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+		if (ai_fields->src_port == TPM_SRC_PORT_UNI_VIRT)
+			src_port_tmp = TPM_SRC_PORT_UNI_7;
+		else
+			src_port_tmp = ai_fields->src_port;
+
+		*ai_data |= ((src_port_tmp - TPM_SRC_PORT_UNI_0) << TPM_AI_UNI_BIT_OFF);
+		*ai_mask |= TPM_AI_UNI_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_PPPOE_ADD_MASK) {
+		ai_val = ((parse_int_flags & TPM_PARSE_FLAG_PPPOE_ADD_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_PPPOE_ADD_BIT_OFF);
+		*ai_mask |= TPM_AI_PPPOE_ADD_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_MC_VID_PARSE) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " vid ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= ((ai_fields->mc_vid_entry) << TPM_AI_MC_VID_BIT_OFF);
+		*ai_mask |= TPM_AI_MC_VID_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_IPV6_SUBFLOW_PARSE) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " ipv6 ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= (((ai_fields->ipv6_subflow >> TPM_AI_IPV6_SUBFLOW_PART1_BIT_SIZE) << TPM_AI_IPV6_SUBFLOW_PART2_BIT_OFF) & TPM_AI_IPV6_SUBFLOW_PART2_MASK);
+		*ai_mask |= TPM_AI_IPV6_SUBFLOW_PART2_MASK;
+	}
+
+	/*BIT_5 */
+
+	if (parse_int_flags & TPM_PARSE_FLAG_NO_PROTO_MASK) {
+		ai_val = ((parse_int_flags & TPM_PARSE_FLAG_NO_PROTO_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_NO_PROTO_BIT_OFF);
+		*ai_mask |= TPM_AI_NO_PROTO_MASK;
+	}
+
+	/*BIT_6 */
+
+	if (parse_int_flags & TPM_PARSE_FLAG_NO_FRAG_MASK) {
+		ai_val = ((parse_int_flags & TPM_PARSE_FLAG_NO_FRAG_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_NO_FRAG_BIT_OFF);
+		*ai_mask |= TPM_AI_NO_FRAG_MASK;
+	}
+
+	if (parse_int_flags & TPM_PARSE_FLAG_MC_VID_MASK) {
+		ai_val = ((parse_int_flags & TPM_PARSE_FLAG_MC_VID_TRUE) ? 1 : 0);
+		*ai_data |= (ai_val << TPM_AI_MC_VID_VALID_BIT_OFF);
+		*ai_mask |= TPM_AI_MC_VID_VALID_MASK;
+	}
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_static_ai_sram_build(tpm_ai_vectors_t *ai_fields,
+				      tpm_pkt_action_t pkt_action,
+				      long long int_pkt_action,
+				      uint32_t *ai_data,
+				      uint32_t *ai_mask)
+{
+	tpm_src_port_type_t src_port_tmp;
+
+	/* Important Note: All TPM_ACTION_UNSET_XXX must be done first, because other bits may re-raise them */
+	if (int_pkt_action & TPM_ACTION_UNSET_DNRT) {
+		*ai_data &= ~(TPM_AI_DNRT_MASK);
+		*ai_mask |= TPM_AI_DNRT_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_UNSET_UNI_PORT) {
+		*ai_data &= ~(TPM_AI_UNI_MASK);
+		*ai_mask |= TPM_AI_UNI_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_UNSET_IPV6_SUBFLOW) {
+		*ai_data &= ~TPM_AI_IPV6_SUBFLOW_PART1_MASK;
+		*ai_mask |= TPM_AI_IPV6_SUBFLOW_PART1_MASK;
+
+		*ai_data &= ~TPM_AI_IPV6_SUBFLOW_PART2_MASK;
+		*ai_mask |= TPM_AI_IPV6_SUBFLOW_PART2_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_UNSET_PPPOE) {
+		*ai_data &= ~(TPM_AI_PPPOE_MASK);
+		*ai_mask |= TPM_AI_PPPOE_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_UNSET_NH2_ITER) {
+		*ai_data &= ~(TPM_AI_NH2_ITER_MASK);
+		*ai_mask |= TPM_AI_NH2_ITER_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_UNSET_CNM_IPV4) {
+		*ai_data &= ~(TPM_AI_CNM_IPV4_MASK);
+		*ai_mask |= TPM_AI_CNM_IPV4_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_UNSET_SPLIT_MOD) {
+		*ai_data &= ~(TPM_AI_SPLIT_MOD_MASK);
+		*ai_mask |= TPM_AI_SPLIT_MOD_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_UNSET_IPV4_PRE_KEY) {
+		*ai_data &= ~TPM_AI_CNM_IPV4_PRE_KEY_MASK;
+		*ai_mask |= TPM_AI_CNM_IPV4_PRE_KEY_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_UNSET_CNM_PREC) {
+		*ai_data &= ~TPM_AI_CNM_PREC_MASK;
+		*ai_mask |= TPM_AI_CNM_PREC_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_TAG1) {
+		*ai_data |= (1 << TPM_AI_TAG1_BIT_OFF);
+		*ai_mask |= TPM_AI_TAG1_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_TAG2) {
+		*ai_data |= (1 << TPM_AI_TAG1_BIT_OFF);
+		*ai_mask |= TPM_AI_TAG2_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_PPPOE) {
+		*ai_data |= (1 << TPM_AI_PPPOE_BIT_OFF);
+		*ai_mask |= TPM_AI_PPPOE_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_L4P_TOG_UDP) {
+		*ai_data |= (1 << TPM_AI_L4P_BIT_OFF);
+		*ai_mask |= TPM_AI_L4P_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_L4P_TOG_TCP) {
+		*ai_data |= (0 << TPM_AI_L4P_BIT_OFF);
+		*ai_mask |= TPM_AI_L4P_MASK;
+	}
+
+	if (pkt_action & TPM_ACTION_MTM) {
+		*ai_data |= (1 << TPM_AI_MTM_BIT_OFF);
+		*ai_mask |= TPM_AI_MTM_MASK;
+	}
+
+	if (pkt_action & TPM_ACTION_TO_CPU) {
+		*ai_data |= (1 << TPM_AI_TO_CPU_BIT_OFF);
+		*ai_mask |= TPM_AI_TO_CPU_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_ADD_PPPOE) {
+		*ai_data |= (1 << TPM_AI_PPPOE_ADD_BIT_OFF);
+		*ai_mask |= TPM_AI_PPPOE_ADD_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_UNI_PORT) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " uni_ports ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+		if (ai_fields->src_port == TPM_SRC_PORT_UNI_VIRT)
+			src_port_tmp = TPM_SRC_PORT_UNI_7;
+		else
+			src_port_tmp = ai_fields->src_port;
+
+		*ai_data |= ((src_port_tmp - TPM_SRC_PORT_UNI_0) << TPM_AI_UNI_BIT_OFF);
+		*ai_mask |= TPM_AI_UNI_MASK;
+	}
+
+	if (pkt_action & TPM_ACTION_SPEC_MC_VID) {
+		/* Set mc_valid bit */
+		*ai_data |= (1 << TPM_AI_MC_VID_VALID_BIT_OFF);
+		*ai_mask |= TPM_AI_MC_VID_VALID_MASK;
+
+		/* Set mc_vid vector */
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " vid ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+		*ai_data |= ((ai_fields->mc_vid_entry) << TPM_AI_MC_VID_BIT_OFF);
+		*ai_mask |= TPM_AI_MC_VID_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_NO_PROTO_CHECK) {
+		*ai_data |= (1 << TPM_AI_NO_PROTO_BIT_OFF);
+		*ai_mask |= TPM_AI_NO_PROTO_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_NO_FRAG_CHECK) {
+		*ai_data |= (1 << TPM_AI_NO_FRAG_BIT_OFF);
+		*ai_mask |= TPM_AI_NO_FRAG_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_NH2_ITER) {
+		*ai_data |= (1 << TPM_AI_NH2_ITER_BIT_OFF);
+		*ai_mask |= TPM_AI_NH2_ITER_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_IPV6_SUBFLOW) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " ipv6 ai vector cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= (((ai_fields->ipv6_subflow) << TPM_AI_IPV6_SUBFLOW_PART1_BIT_OFF) & TPM_AI_IPV6_SUBFLOW_PART1_MASK);
+		*ai_mask |= TPM_AI_IPV6_SUBFLOW_PART1_MASK;
+
+		*ai_data |= (((ai_fields->ipv6_subflow >> TPM_AI_IPV6_SUBFLOW_PART1_BIT_SIZE) << TPM_AI_IPV6_SUBFLOW_PART2_BIT_OFF) & TPM_AI_IPV6_SUBFLOW_PART2_MASK);
+		*ai_mask |= TPM_AI_IPV6_SUBFLOW_PART2_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_CNM_IPV4) {
+		*ai_data |= (1 << TPM_AI_CNM_IPV4_BIT_OFF);
+		*ai_mask |= TPM_AI_CNM_IPV4_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_SPLIT_MOD) {
+		*ai_data |= (1 << TPM_AI_SPLIT_MOD_BIT_OFF);
+		*ai_mask |= TPM_AI_SPLIT_MOD_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_IPV4_PRE_KEY) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " ipv4 pre filter key pattern cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= ((ai_fields->ipv4_pre_key << TPM_AI_CNM_IPV4_PRE_KEY_BIT_OFF) & TPM_AI_CNM_IPV4_PRE_KEY_MASK);
+		*ai_mask |= TPM_AI_CNM_IPV4_PRE_KEY_MASK;
+	}
+
+	if (int_pkt_action & TPM_ACTION_SET_CNM_PREC) {
+		if (ai_fields == NULL) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " cnm precedence pattern cannot be null pointer\n");
+			return(TPM_FAIL);
+		}
+
+		*ai_data |= ((ai_fields->cnm_prec << TPM_AI_CNM_PREC_BIT_OFF) & TPM_AI_CNM_PREC_MASK);
+		*ai_mask |= TPM_AI_CNM_PREC_MASK;
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_virt_uni_trg_port_validation()
+*
+* DESCRIPTION:
+*   In case feature Virtual UNI_4 is enabled - only following target port are allowed:
+*       TPM_TRG_UNI_0                       (0x0100)
+*       TPM_TRG_UNI_1                       (0x0200)
+*       TPM_TRG_UNI_2                       (0x0400)
+*       TPM_TRG_UNI_3                       (0x0800)
+*       TPM_TRG_PORT_UNI_ANY                (0x4000)
+* INPUTS:
+* tpm_trg_port_type_t     trg_port
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_virt_uni_trg_port_validation(tpm_trg_port_type_t trg_port)
+{
+
+	if ((trg_port == TPM_TRG_UNI_0) ||
+	    (trg_port == TPM_TRG_UNI_1) ||
+	    (trg_port == TPM_TRG_UNI_2) ||
+	    (trg_port == TPM_TRG_UNI_3) ||
+	    (trg_port == TPM_TRG_UNI_4) ||
+	    (trg_port == TPM_TRG_UNI_5) ||
+	    (trg_port == TPM_TRG_UNI_6) ||
+	    (trg_port == TPM_TRG_UNI_7) ||
+	    (trg_port == TPM_TRG_UNI_VIRT) ||
+	    (trg_port == TPM_TRG_PORT_UNI_ANY) ||
+	    (trg_port == TPM_TRG_PORT_CPU) ||
+	    (trg_port == (TPM_TRG_UNI_0 | TPM_TRG_UNI_1 | TPM_TRG_UNI_2 | TPM_TRG_UNI_3 |
+			  TPM_TRG_UNI_4 | TPM_TRG_UNI_5 | TPM_TRG_UNI_6 | TPM_TRG_UNI_7)))
+		return TPM_OK;
+	else
+		return TPM_FAIL;
+}
+
+/*******************************************************************************
+* tpm_proc_set_RI_mh()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* rule_action
+* pkt_frwd
+* dir
+* sram_data
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_set_RI_mh(tpm_rule_action_t *rule_action,
+			   tpm_pkt_frwd_t *pkt_frwd,
+			   tpm_dir_t dir,
+			   tpm_pncl_sram_data_t *sram_data)
+{
+	uint32_t i;
+	int32_t ret_code;
+	tpm_db_mh_src_t ds_mh_src;
+	tpm_init_virt_uni_t virt_uni_info;
+	uint16_t amber_port_vector;
+	uint32_t pnc_vector, uni_vector;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "tpm_proc_set_RI_mh: dir(%d), trg_port(0x%x) \r\n", dir, pkt_frwd->trg_port);
+
+	tpm_db_ds_mh_get_conf_set(&ds_mh_src);
+
+	if ((SET_TARGET_PORT(rule_action->pkt_act)) &&
+	    (TO_LAN(dir, pkt_frwd->trg_port)) && (ds_mh_src == TPM_MH_SRC_PNC_RI)) {
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_MH_RI;
+		sram_data->mh_reg.mh_set = TPM_TRUE;
+
+		/* target port validation -
+		   not all target port combinations are supported when WiFi via GMAC1 = UNI_4 feature is enabled */
+		ret_code = tpm_db_virt_info_get(&virt_uni_info);
+		if (ret_code != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Virt UNI recvd ret_code(%d)\n", ret_code);
+			return(ret_code);
+		}
+		if ((virt_uni_info.enabled == 1) && (dir == TPM_DIR_DS)) {
+			/* Virt UNI feature is enabled - validate and recalculate the mh_reg */
+			ret_code = tpm_proc_virt_uni_trg_port_validation(pkt_frwd->trg_port);
+			if (ret_code != TPM_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Virt UNI trg_port validation failed. (%d)\n", ret_code);
+				return(ret_code);
+			}
+
+			/* get the MH_REG from the DB */
+			ret_code = tpm_db_port_vector_tbl_info_search(pkt_frwd->trg_port, &uni_vector,
+									   &amber_port_vector, &pnc_vector);
+			if (ret_code != TPM_DB_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+					" Unable to retrieve port vector table from DB. (0x%x)\n", pkt_frwd->trg_port);
+				return(ret_code);
+			}
+			sram_data->mh_reg.mh_reg = pnc_vector;
+		} else {
+			for (i = 0; i < TPM_MAX_NUM_UNI_PORTS; i++) {
+				if ((pkt_frwd->trg_port & (TPM_TRG_UNI_0 << i)) ||
+				    (pkt_frwd->trg_port & TPM_TRG_PORT_UNI_ANY))
+					sram_data->mh_reg.mh_reg |= (TPM_MH_RI_BIT14 << i);
+			}
+
+		}
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_owner_id_check()
+*
+* DESCRIPTION:    The function checks if the owner_id is the valid owner of api_type
+*
+* INPUTS:
+* owner_id         - API Group owner
+* api_type        - API group the owner requests to act upon
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_owner_id_check(tpm_api_type_t api_type, uint32_t owner_id)
+{
+	/* TODO Implement */
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_cpu_loopback_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_proc_add_cpu_loopback_rule params.
+*
+* INPUTS:
+* owner_id         - See tpm_proc_add_l2_prim_acl_rule
+* rule_num         - See tpm_proc_add_l2_prim_acl_rule
+* pkt_frwd         - See tpm_proc_add_l2_prim_acl_rule
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_cpu_loopback_check(uint32_t owner_id, uint32_t rule_num, tpm_pkt_frwd_t *pkt_frwd)
+{
+	int32_t ret_code;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_CPU_LOOPBACK, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	ret_code = tpm_proc_add_api_ent_check(TPM_CPU_LOOPBACK_ACL, TPM_RANGE_TYPE_ACL, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_l2_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_proc_add_l2_prim_acl_rule params.
+*
+* INPUTS:
+* owner_id         - See tpm_proc_add_l2_prim_acl_rule
+* src_port         - See tpm_proc_add_l2_prim_acl_rule
+* rule_num         - See tpm_proc_add_l2_prim_acl_rule
+* parse_rule_bm    - See tpm_proc_add_l2_prim_acl_rule
+* l2_key           - See tpm_proc_add_l2_prim_acl_rule
+* pkt_frwd         - See tpm_proc_add_l2_prim_acl_rule
+* pkt_mod          - See tpm_proc_add_l2_prim_acl_rule
+* rule_action      - See tpm_proc_add_l2_prim_acl_rule
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_l2_check(uint32_t owner_id,
+				       tpm_src_port_type_t src_port,
+				       uint32_t rule_num,
+				       tpm_parse_fields_t parse_rule_bm,
+				       tpm_l2_acl_key_t *l2_key,
+				       tpm_parse_flags_t parse_flags_bm,
+				       tpm_pkt_frwd_t *pkt_frwd,
+				       tpm_pkt_mod_bm_t pkt_mod_bm,
+				       tpm_pkt_mod_t *pkt_mod,
+				       tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_dir_t dir;
+	tpm_db_pon_type_t pon_type;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pnc_range_conf_t rangConf;
+	int32_t mc_vlan_free_slot;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Check Source Port */
+	ret_code = tpm_proc_src_port_check(src_port);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_SRC_PORT_INVALID);
+
+	/* Get Range_Id, rang configuration, to get range type */
+	ret_code = tpm_db_api_section_main_pnc_get(TPM_L2_PRIM_ACL, &range_id);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Check necessary pointers are valid */
+	ret_code =
+	tpm_proc_check_missing_data(rule_action, pkt_mod, pkt_frwd, (void *)l2_key, rule_action->pkt_act,
+				    parse_rule_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check parse_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_L2_PRIM_ACL_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check Vlan Tag TPID mask */
+	if (parse_rule_bm & (TPM_L2_PARSE_TWO_VLAN_TAG | TPM_L2_PARSE_ONE_VLAN_TAG)) {
+		if ((l2_key->vlan1.tpid_mask != 0) && (l2_key->vlan1.tpid_mask != 0xffff)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid vlan1 tpid mask(0x%x) \n", l2_key->vlan1.tpid_mask);
+			return(ERR_L2_KEY_INVALID);
+		}
+
+		if (parse_rule_bm & TPM_L2_PARSE_ONE_VLAN_TAG) {
+			if ((l2_key->vlan2.tpid_mask != 0) && (l2_key->vlan2.tpid_mask != 0xffff)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid vlan2 tpid mask(0x%x) \n", l2_key->vlan2.tpid_mask);
+				return(ERR_L2_KEY_INVALID);
+			}
+		}
+	}
+
+	/* Cannot do Double Vlan Tag with looking into PPPoE (up to 24Bytes) with MH */
+	if ((parse_rule_bm & TPM_L2_PARSE_TWO_VLAN_TAG) &&
+	    ((parse_rule_bm & TPM_L2_PARSE_PPP_PROT) || (parse_rule_bm & TPM_L2_PARSE_PPPOE_SES))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parse map of Double Vlan Tag + PPPoE not supported\n");
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Cannot do Single or Double Vlan Tag with checking   PPP protocol (up to 24Bytes) with MH */
+	if (((parse_rule_bm & TPM_L2_PARSE_TWO_VLAN_TAG) || (parse_rule_bm & TPM_L2_PARSE_ONE_VLAN_TAG))
+	    && (parse_rule_bm & TPM_L2_PARSE_PPP_PROT)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parse map of Single Vlan Tag + PPPoE proto not supported\n");
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_L2_PRIM_ACL_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/*do not allow user to create VLANOP_NOOP l2 PNC with no vlan parse flag.*/
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(TPM_VLAN_MOD == pkt_mod_bm) &&
+		(VLANOP_NOOP == pkt_mod->vlan_mod.vlan_op)) {
+		if (!(parse_flags_bm &
+			(TPM_PARSE_FLAG_TAG1_TRUE |
+			TPM_PARSE_FLAG_TAG2_TRUE |
+			TPM_PARSE_FLAG_TAG1_FALSE |
+			TPM_PARSE_FLAG_TAG2_FALSE))) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x), "
+				"when split mod VLANOP_NOOP it must TAG FLAG be set\n", parse_flags_bm);
+			return(ERR_PARSE_MAP_INVALID);
+		}
+	}
+
+	/* check VLAN OP p_bit mask */
+	if (pkt_mod_bm & TPM_VLAN_MOD) {
+		if (VLANOP_EXT_TAG_INS == pkt_mod->vlan_mod.vlan_op) {
+			if (pkt_mod->vlan_mod.vlan1_out.pbit_mask != 0xff) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid p_bit mask for VLAN Op (0x%x) \n", VLANOP_EXT_TAG_INS);
+				return(ERR_GENERAL);
+		    }
+		}
+		if (VLANOP_INS_2TAG == pkt_mod->vlan_mod.vlan_op) {
+			if (pkt_mod->vlan_mod.vlan1_out.pbit_mask != 0xff ||
+			    pkt_mod->vlan_mod.vlan2_out.pbit_mask != 0xff) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid p_bit mask for VLAN Op (0x%x) \n", VLANOP_INS_2TAG);
+				return(ERR_GENERAL);
+		    }
+		}
+		if (VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid VLAN Op (0x%x), do not support in L2 \n", VLANOP_SPLIT_MOD_PBIT);
+			return(ERR_GENERAL);
+		}
+	}
+
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Packet Modification */
+#if 0
+	tpm_proc_pkt_mod_check(rule_action->pkt_act, pkt_mod_bm, pkt_mod);
+	IF_ERROR(ret_code);
+#endif
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_L2_PRIM, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	ret_code = tpm_proc_add_api_ent_check(TPM_L2_PRIM_ACL, rangConf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	/* Check parse_rules */
+
+	/* Check gem_port only for GPON DS */
+	if ((parse_rule_bm & TPM_L2_PARSE_GEMPORT) && ((dir != TPM_DIR_DS) || (pon_type != TPM_GPON)))
+		IF_ERROR(ERR_PARSE_MAP_INVALID);
+
+	/* Check forwarding rule, currently only support STAGE_DONE */
+	if (rule_action->next_phase != STAGE_L3_TYPE && rule_action->next_phase != STAGE_DONE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+	/* Check that for l2_hwf rules (not mtm, not to_cpu), if the parsing is not done, the uni_port is specifc.
+	 * Otherwise, rules in following sections cannot rely on the uni_port */
+	if (((rule_action->pkt_act & (TPM_ACTION_TO_CPU | TPM_ACTION_MTM)) == 0) &&
+	    (rule_action->next_phase != STAGE_DONE)) {
+		if (!(FROM_SPEC_UNI(src_port)) && (src_port != TPM_SRC_PORT_WAN)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+				     " For L2_HWF rule (not mtm, not to_cpu), specific uni must be specified \n");
+			return(ERR_SRC_PORT_INVALID);
+		}
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+
+	/* Check mc vlan set */
+	if (TPM_ACTION_SPEC_MC_VID & rule_action->pkt_act) {
+		if (src_port != TPM_SRC_PORT_WAN) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Multicast Vlan-ID can only be assigned in downstream \n");
+			return(ERR_ACTION_INVALID);
+		}
+		if (0 == l2_key->vlan1.vid_mask) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " To spec MC vlan, Vlan-ID must be specified \n");
+			return(ERR_ACTION_INVALID);
+		} else if (l2_key->vlan1.vid == 0 || l2_key->vlan1.vid >= 4096) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Invalid multicast Vlan-ID is assigned \n");
+			return(ERR_L2_KEY_INVALID);
+		}
+		mc_vlan_free_slot = tpm_db_mc_vlan_get_pnc_index_free_slot(l2_key->vlan1.vid, rule_num);
+		if (0 == mc_vlan_free_slot) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " No more free slot for l2 rule of this MC vlan\n");
+			return(ERR_GENERAL);
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_gen_check(uint32_t owner_id,
+					       tpm_src_port_type_t src_port,
+					       uint32_t rule_num,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_pkt_mod_bm_t pkt_mod_bm,
+					       tpm_pkt_mod_t *pkt_mod,
+					       tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_dir_t dir;
+	tpm_db_pon_type_t pon_type;
+	tpm_db_pnc_range_t range_data;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Check 5_tuple feature is disabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable != TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	/* Check Source Port */
+	ret_code = tpm_proc_src_port_check(src_port);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_SRC_PORT_INVALID);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Check necessary pointers are valid */
+	ret_code =
+	tpm_proc_check_missing_data(rule_action, pkt_mod, pkt_frwd, (void *)ipv6_gen_key, rule_action->pkt_act,
+				    parse_rule_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check parse_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_IPV6_GEN_ACL_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+
+	}
+
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_IPV6_GEN_ACL_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Packet Modification */
+#if 0
+	tpm_proc_pkt_mod_check(rule_action->pkt_act, pkt_mod_bm, pkt_mod);
+	IF_ERROR(ret_code);
+#endif
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_IPV6_GEN, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_GEN, &range_data);
+
+	ret_code = tpm_proc_add_api_ent_check(TPM_IPV6_GEN_ACL, range_data.pnc_range_conf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		if ((rule_num < range_data.pnc_range_conf.api_start) || (rule_num > range_data.pnc_range_conf.api_end))
+			IF_ERROR(ERR_RULE_NUM_INVALID);
+	}
+
+	/* Check forwarding rule, currently only support STAGE_DONE */
+	if (rule_action->next_phase != STAGE_IPv6_DIP && rule_action->next_phase != STAGE_DONE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_IPV6_GEN_ACL_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_dip_check(uint32_t owner_id,
+					     tpm_src_port_type_t src_port,
+					     uint32_t rule_num,
+					     tpm_parse_fields_t parse_rule_bm,
+					     tpm_parse_flags_t parse_flags_bm,
+					     tpm_ipv6_addr_key_t *ipv6_dip_key,
+					     tpm_pkt_frwd_t *pkt_frwd,
+					     tpm_pkt_mod_bm_t pkt_mod_bm,
+					     tpm_pkt_mod_t *pkt_mod,
+					     tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_dir_t dir;
+	tpm_db_pon_type_t pon_type;
+	tpm_db_pnc_range_t range_data;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+
+	/* Check 5_tuple feature is disabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable != TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	/* Check Source Port */
+	ret_code = tpm_proc_src_port_check(src_port);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_SRC_PORT_INVALID);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Check necessary pointers are valid */
+	ret_code =
+	tpm_proc_check_missing_data(rule_action, pkt_mod, pkt_frwd, (void *)ipv6_dip_key, rule_action->pkt_act,
+				    parse_rule_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check parse_rule_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_IPV6_DIP_ACL_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+
+	}
+
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_IPV6_DIP_ACL_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Packet Modification */
+#if 0
+	tpm_proc_pkt_mod_check(rule_action->pkt_act, pkt_mod_bm, pkt_mod);
+	IF_ERROR(ret_code);
+#endif
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_IPV6_DIP, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_DIP, &range_data);
+
+	ret_code = tpm_proc_add_api_ent_check(TPM_IPV6_DIP_ACL, range_data.pnc_range_conf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		if ((rule_num < range_data.pnc_range_conf.api_start) || (rule_num > range_data.pnc_range_conf.api_end))
+			IF_ERROR(ERR_RULE_NUM_INVALID);
+	}
+
+	/* Check forwarding rule, currently only support STAGE_DONE */
+	if (rule_action->next_phase != STAGE_IPv6_NH && rule_action->next_phase != STAGE_DONE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_IPV6_DIP_ACL_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_l4ports_check(uint32_t owner_id,
+						 tpm_src_port_type_t src_port,
+						 uint32_t rule_num,
+						 tpm_parse_fields_t parse_rule_bm,
+						 tpm_parse_flags_t parse_flags_bm,
+						 tpm_l4_ports_key_t *l4_key,
+						 tpm_pkt_frwd_t *pkt_frwd,
+						 tpm_pkt_mod_bm_t pkt_mod_bm,
+						 tpm_pkt_mod_t *pkt_mod,
+						 tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_dir_t dir;
+	tpm_db_pon_type_t pon_type;
+	tpm_db_pnc_range_t range_data;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Check 5_tuple feature is disabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable != TPM_IPV6_5T_DISABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	/* Check Source Port */
+	ret_code = tpm_proc_src_port_check(src_port);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_SRC_PORT_INVALID);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Check necessary pointers are valid */
+	ret_code =
+	tpm_proc_check_missing_data(rule_action, pkt_mod, pkt_frwd, (void *)l4_key, rule_action->pkt_act,
+				    parse_rule_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check parse_rule_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_IPV6_L4_PORTS_ACL_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_IPV6_L4_PORTS_ACL_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Packet Modification */
+#if 0
+	tpm_proc_pkt_mod_check(rule_action->pkt_act, pkt_mod_bm, pkt_mod);
+	IF_ERROR(ret_code);
+#endif
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_IPV6_L4, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_L4, &range_data);
+
+	ret_code = tpm_proc_add_api_ent_check(TPM_L4_ACL, range_data.pnc_range_conf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		if ((rule_num < range_data.pnc_range_conf.api_start) || (rule_num > range_data.pnc_range_conf.api_end))
+			IF_ERROR(ERR_RULE_NUM_INVALID);
+	}
+
+	/* Check forwarding rule,  STAGE_DONE */
+	if (rule_action->next_phase != STAGE_IPv6_GEN && rule_action->next_phase != STAGE_DONE
+	    && rule_action->next_phase != STAGE_CTC_CM) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_IPV6_L4_PORTS_ACL_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	/* Check if next stage CTC CnM  */
+	if ((rule_action->next_phase == STAGE_CTC_CM) && !(parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "next stage is CnM, packets must be MTM_FALSE\n");
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_nh_check(uint32_t owner_id,
+					    uint32_t rule_num,
+					    tpm_nh_iter_t nh_iter,
+					    tpm_parse_flags_t parse_flags_bm,
+					    uint32_t nh,
+					    tpm_pkt_frwd_t *pkt_frwd,
+					    tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_t range_data;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_pkt_mod_bm_t pkt_mod_bm = 0;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Check keys exist for parse fields */
+	if (rule_action == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "rule_action cannot be NULL\n");
+		return(ERR_ACTION_INVALID);
+	}
+
+	if ((pkt_frwd == NULL) && ((SET_TARGET_PORT(rule_action->pkt_act)) || SET_TARGET_QUEUE(rule_action->pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target set requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	/* Check Valid Target, ==> only allowed to direct to CPU */
+	if (SET_TARGET_PORT(rule_action->pkt_act)) {
+		if (TO_CPU(pkt_frwd->trg_port)) {
+			/*cont */
+		} else {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "* trg_port=%d *\r\n", pkt_frwd->trg_port);
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Illegal Target Port\n");
+			return(ERR_FRWD_INVALID);
+		}
+	}
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Valid Queue */
+	/* TODO - Check Queue depending on actual queues in target or in Rx */
+	if (SET_TARGET_QUEUE(rule_action->pkt_act) && (pkt_frwd->trg_queue >= TPM_MAX_NUM_TX_QUEUE)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target Queue Out of Range\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	/* Check rule_num, and api_section is active */
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_NH, &range_data);
+
+	ret_code = tpm_proc_add_api_ent_check(TPM_IPV6_NH_ACL, range_data.pnc_range_conf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		if ((rule_num < range_data.pnc_range_conf.api_start) || (rule_num > range_data.pnc_range_conf.api_end))
+			IF_ERROR(ERR_RULE_NUM_INVALID);
+	}
+
+	/* Check forwarding rule */
+	if (rule_action->next_phase != STAGE_IPV6_L4 &&
+		rule_action->next_phase != STAGE_IPv6_NH &&
+		rule_action->next_phase != STAGE_IPv6_GEN &&
+		rule_action->next_phase != STAGE_CTC_CM &&
+		rule_action->next_phase != STAGE_DONE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	if (rule_action->next_phase == STAGE_IPV6_L4) {
+		if (nh != IPPROTO_UDP && nh != IPPROTO_TCP) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase is IPV6_L4 while NH(%d) is not UDP or TCP \n", nh);
+			return(ERR_NEXT_PHASE_INVALID);
+		}
+	}
+
+	if (rule_action->next_phase == STAGE_IPv6_NH && nh_iter == NH_ITER_1) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Multiple Ext Hdr is not supported \n");
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check if next stage CTC CnM  */
+	if (rule_action->next_phase == STAGE_CTC_CM) {
+		if (nh == IPPROTO_UDP || nh == IPPROTO_TCP) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next Phase is CTC_CM while NH(%d) is UDP or TCP \n", nh);
+			return(ERR_NEXT_PHASE_INVALID);
+		}
+		if (0 == (parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage is CnM, packets must be MTM_FALSE\n");
+			return(ERR_NEXT_PHASE_INVALID);
+		}
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, &pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_IPV6_NH_ACL_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_ipv4_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_proc_add_ipv4_acl_rule params.
+*
+* INPUTS:
+* - See tpm_proc_add_ipv4_acl_rule
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_ipv4_check(uint32_t owner_id,
+					 tpm_src_port_type_t src_port,
+					 uint32_t rule_num,
+					 tpm_parse_fields_t parse_rule_bm,
+					 tpm_parse_flags_t parse_flags_bm,
+					 tpm_ipv4_acl_key_t *ipv4_key,
+					 tpm_pkt_frwd_t *pkt_frwd,
+					 tpm_pkt_mod_t *pkt_mod,
+					 tpm_rule_action_t *rule_action,
+					 tpm_pkt_mod_bm_t pkt_mod_bm)
+{
+	int32_t ret_code;
+	tpm_dir_t dir;
+	tpm_db_pon_type_t pon_type;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pnc_range_conf_t rangConf;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Check Source Port */
+	ret_code = tpm_proc_src_port_check(src_port);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_SRC_PORT_INVALID);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id, rang configuration, to get range type */
+	ret_code = tpm_db_api_section_main_pnc_get(TPM_IPV4_ACL, &range_id);
+	IF_ERROR(ret_code);
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Check necessary pointers are valid */
+	ret_code =
+	tpm_proc_check_missing_data(rule_action, pkt_mod, pkt_frwd, (void *)ipv4_key, rule_action->pkt_act,
+				    parse_rule_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check Packet Modification */
+#if 0
+	tpm_proc_pkt_mod_check(rule_action->pkt_act, pkt_mod_bm, pkt_mod);
+	IF_ERROR(ret_code);
+#endif
+
+	/* Check parse_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_IPV4_ACL_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_IPV4_ACL_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_IPV4, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	ret_code = tpm_proc_add_api_ent_check(TPM_IPV4_ACL, rangConf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	/* Check forwarding rule, support STAGE_DONE */
+	if (    rule_action->next_phase != STAGE_DONE
+		 && rule_action->next_phase != STAGE_CTC_CM) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_IPV4_ACL_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	if(rule_action->next_phase == STAGE_CTC_CM) {
+		if(!tpm_ctc_cm_ipv4_rule2cm(parse_flags_bm, rule_action)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "next stage is CTC_CM, parse flag must be MTM_FALSE, and action can not be TO_CPU\n");
+			return(ERR_NEXT_PHASE_INVALID);
+		}
+		if(FROM_WAN(src_port)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "next stage is CTC_CM, Src Port can not be WAN\n");
+			return(ERR_SRC_PORT_INVALID);
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_del_l2_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_proc_del_l2_prim_acl_rule params.
+*
+* INPUTS:
+* owner_id         - See tpm_proc_del_l2_prim_acl_rule
+* src_port         - See tpm_proc_del_l2_prim_acl_rule
+* rule_idx         - See tpm_proc_del_l2_prim_acl_rule
+* parse_rule_bm    - See tpm_proc_del_l2_prim_acl_rule
+* l2_key           - See tpm_proc_del_l2_prim_acl_rule
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_l2_check(uint32_t owner_id,
+				       tpm_src_port_type_t src_port,
+				       uint32_t rule_idx,
+				       tpm_parse_fields_t parse_rule_bm,
+				       tpm_l2_acl_key_t *l2_key)
+{
+	int32_t ret_code;
+	uint32_t rule_num;
+	tpm_dir_t dir;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* check that rule_idx or parse_bm or l2_key are valid - for deletion */
+	if ((rule_idx == 0) && ((l2_key == NULL) || (parse_rule_bm == 0)))
+		IF_ERROR(ERR_DELETE_KEY_INVALID);
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_L2_PRIM, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check Source Port */
+	ret_code = tpm_proc_src_port_check(src_port);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_SRC_PORT_INVALID);
+
+	/* Get Direction, Important before other tests */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+
+	/* Check valid rule_idx */
+
+	if (rule_idx != 0) {	/* when rule_idx = 0 -> caller indicates to work according to the l2_key */
+
+		ret_code = tpm_db_api_rulenum_get(TPM_L2_PRIM_ACL, rule_idx, &rule_num);
+		if (ret_code != TPM_OK)
+			IF_ERROR(ERR_RULE_IDX_INVALID);
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_common_pncl_info_get()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* dir              - Direction of the API acl/table
+* api_rule_num     - Rulenum in the API table
+*
+* OUTPUTS:
+* pnc_entry        - PnC Entry matching this api_table/rule_num
+* lu_id            - LookupId of this PNC Range
+* start_offset     - Logical TCAM start offset of this API Table
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_common_pncl_info_get(tpm_pnc_ranges_t range_id, uint32_t *lu_id, tpm_pncl_offset_t *start_offset)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "range_id(%d)\n", range_id);
+
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &range_conf);
+	IF_ERROR(ret_code);
+
+	*lu_id = range_conf.base_lu_id;
+	start_offset->range_id = range_id;
+
+	if (range_id == TPM_PNC_L2_MAIN || range_id == TPM_PNC_MAC_LEARN) {
+		start_offset->offset_base = TPM_PNCL_ZERO_OFFSET;
+		start_offset->offset_sub.subf = TPM_L2_PARSE_MH;
+	} else if (range_id == TPM_PNC_ETH_TYPE) {
+		start_offset->offset_base = TPM_PNCL_L3_OFFSET;
+		start_offset->offset_sub.subf = TPM_L2_PARSE_ETYPE;
+	} else if ((range_id == TPM_PNC_IPV4_MAIN)
+		   || (range_id == TPM_PNC_IPV4_MC_DS)
+		   || (range_id == TPM_PNC_IPV4_PROTO)
+		   || (range_id == TPM_PNC_CNM_IPV4_PRE)
+		   || (range_id == TPM_PNC_IGMP)) {
+		start_offset->offset_base = TPM_PNCL_IPV4_OFFSET;
+		start_offset->offset_sub.subf = TPM_IPv4_PARSE_VER_OR_IHL;
+	} else if (    (range_id == TPM_PNC_IPV6_NH)
+		    || (range_id == TPM_PNC_IPV6_GEN)
+		    || (range_id == TPM_PNC_IPV6_MC_SIP)) {
+		start_offset->offset_base = TPM_PNCL_IPV6_OFFSET;
+		start_offset->offset_sub.subf = TPM_IPv6_PARSE_VER_OR_DSCP;
+	} else if ((range_id == TPM_PNC_IPV6_DIP)
+		   || (range_id == TPM_PNC_IPV6_MC_DS)) {
+		start_offset->offset_base = TPM_PNCL_IPV6_OFFSET;
+		start_offset->offset_sub.subf = TPM_IPv6_PARSE_DIP;
+	} else if (range_id == TPM_PNC_IPV6_L4) {
+		start_offset->offset_base = TPM_PNCL_L4_OFFSET;
+		start_offset->offset_sub.subf = TPM_PARSE_L4_SRC;
+	} else if (range_id == TPM_PNC_CNM_MAIN) {
+		/* Dummy */
+	} else {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "range id not supported %d\n", range_id);
+		return(TPM_FAIL);
+	}
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_pnc_con_del()
+*
+* DESCRIPTION:     Function deletes a pnc connection structure
+*
+* INPUTS:
+* pnc_con          - APIPNC Table  Configuration
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_pnc_con_del(tpm_db_pnc_conn_t *pnc_con)
+{
+	uint32_t i, cur_pnc_range, cur_pnc_index, pnc_start, pnc_stop;
+	int32_t ret_code;
+	tpm_db_pnc_range_t range_data;
+
+	for (i = 0; i < (pnc_con->num_pnc_ranges); i++) {
+		cur_pnc_index = pnc_con->pnc_conn_tbl[i].pnc_index;
+		cur_pnc_range = pnc_con->pnc_conn_tbl[i].pnc_range;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "range(%d), ind(%d) \n", cur_pnc_range, cur_pnc_index);
+
+		ret_code = tpm_db_pnc_rng_get(cur_pnc_range, &range_data);
+		IF_ERROR(ret_code);
+
+		if (range_data.pnc_range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+			pnc_start = cur_pnc_index;
+			/* Pull range from this index untill last used entry in Pnc range */
+			pnc_stop = range_data.pnc_range_conf.range_start +
+				   (range_data.pnc_range_conf.api_end - range_data.pnc_range_oper.free_entries);
+
+			ret_code = tpm_pncl_entry_delete(pnc_start, pnc_stop);
+			IF_ERROR(ret_code);
+		} else {
+			ret_code = tpm_pncl_entry_reset(cur_pnc_index);
+			IF_ERROR(ret_code);
+		}
+		/* Increase number of free entries in pnc_range */
+		ret_code = tpm_db_pnc_rng_free_ent_inc(cur_pnc_range);
+		IF_ERROR(ret_code);
+	}
+	/* Init the pnc_con structure */
+	memset(pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_split_mod_stage1_check()
+*
+* DESCRIPTION:    function to check the mod in L2 observe to split mod or not
+*
+* INPUTS:
+*           pkt_mod_bm
+*           pkt_mod
+*
+* OUTPUTS:
+*
+* RETURNS:
+*           if the mod observe to split mod, return true, or return false
+*
+* COMMENTS:
+*
+*******************************************************************************/
+bool tpm_split_mod_stage1_check(tpm_pkt_mod_bm_t pkt_mod_bm,
+				tpm_pkt_mod_t *pkt_mod,
+				tpm_rule_action_t *rule_action,
+				bool check_vlan_noop)
+{
+	bool temp;
+
+	if (NULL == pkt_mod)
+		return false;
+
+	if (rule_action->pkt_act & TPM_ACTION_SPEC_MC_VID)
+		return false;
+
+	if (STAGE_DONE == rule_action->next_phase)
+		return false;
+
+	if (check_vlan_noop) {
+		if(VLANOP_NOOP == pkt_mod->vlan_mod.vlan_op)
+			temp = true;
+		else
+			temp = false;
+	} else {
+		temp = false;
+	}
+
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(TPM_VLAN_MOD == pkt_mod_bm) &&
+		((VLANOP_EXT_TAG_MOD == pkt_mod->vlan_mod.vlan_op) ||
+			(VLANOP_EXT_TAG_INS == pkt_mod->vlan_mod.vlan_op) ||
+			(VLANOP_EXT_TAG_MOD_INS == pkt_mod->vlan_mod.vlan_op) || temp)) {
+
+		/* L2 {VID+p-bit} translation. In GPON mode
+		 * not set the SPLIT_MOD AI bit
+		 */
+		if (TPM_SPLIT_MOD_MODE_CTC == tpm_db_split_mod_get_mode())
+			return true;
+		else if ((VLANOP_EXT_TAG_MOD == pkt_mod->vlan_mod.vlan_op) &&
+			(pkt_mod->vlan_mod.vlan1_out.vid_mask == 0xffff) &&
+			(pkt_mod->vlan_mod.vlan1_out.pbit_mask == 0xff))
+			return false;
+		else
+			return true;
+	} else {
+		return false;
+	}
+
+}
+
+/*******************************************************************************
+* tpm_proc_l2_tcam_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* src_port          - packet source port
+* dir               - Packet direction
+* rule_num          - API rule number
+* l2_key            - layer2 key data
+* parse_rule_bm     - Parse rules bitmap
+* OUTPUTS:
+* l2_tcam_data      - Logical TCAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_l2_tcam_build(tpm_src_port_type_t src_port,
+			       tpm_dir_t dir,
+			       uint32_t rule_num,
+			       tpm_l2_acl_key_t *l2_key,
+			       tpm_parse_fields_t parse_rule_bm,
+			       tpm_parse_flags_t parse_flags_bm,
+			       tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t src_port_field;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) parse_rule_bm(%x) parse_flag_bm(%x) \n",
+		     src_port, dir, rule_num, parse_rule_bm, parse_flags_bm);
+
+	/* L2 Parsing, according to bm in param */
+	tcam_data->l2_parse_bm = parse_rule_bm;
+
+	/* Build the AI bits according to parse_flags */
+	/* Parse the vlan tag number AI bits */
+	src_port_field.src_port = src_port;
+	tpm_proc_parse_flag_ai_tcam_build(&src_port_field, parse_flags_bm, 0, &(tcam_data->add_info_data),
+					  &(tcam_data->add_info_mask));
+
+	/*Parse MH for specific src_port or for gemport_parse request */
+	if (((FROM_SPEC_UNI(src_port)) && (!tpm_proc_gmac1_phy_src_port(src_port))) ||
+	    (parse_rule_bm & TPM_L2_PARSE_GEMPORT))
+		tcam_data->l2_parse_bm |= TPM_L2_PARSE_MH;
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = src_port;
+	if (l2_key)
+		memcpy(&(tcam_data->pkt_key.l2_key), l2_key, sizeof(tpm_l2_acl_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_L2_MAIN, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_l2_sram_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* src_port          - packet source port
+* dir               - Packet direction
+* rule_num          - API rule number
+* pon_type          - WAN technology
+* l2_key            - layer2 key data
+* parse_rule_bm     - Parse rules bitmap
+* pkt_frwd          - See xxx
+* rule_action       - See xxx
+*
+* OUTPUTS:
+* l2_sram_data      - Logical SRAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_l2_sram_build(tpm_src_port_type_t src_port,
+			       tpm_dir_t dir,
+			       uint32_t rule_num,
+			       tpm_db_pon_type_t pon_type,
+			       tpm_pkt_frwd_t *pkt_frwd,
+			       tpm_rule_action_t *rule_action,
+			       uint32_t mod_cmd,
+			       tpm_pncl_sram_data_t *sram_data,
+			       tpm_l2_acl_key_t *l2_key,
+			       tpm_pkt_mod_t *pkt_mod,
+			       tpm_pkt_mod_bm_t pkt_mod_bm)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_ai_vectors_t ai_vector;
+	uint32_t ai_bits;
+	long long int_pkt_act = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) \n", src_port, dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Unset DNRT bit (Do not Repeat Tags Phase), the bit is leftover from previous hardcoded Vlan_tags phase */
+	int_pkt_act |= TPM_ACTION_UNSET_DNRT;
+
+	/* Set UNI Port */
+	if (FROM_SPEC_UNI(src_port)) {
+		int_pkt_act |= TPM_ACTION_SET_UNI_PORT;
+		ai_vector.src_port = src_port;
+	}
+	/* alloc AI bits if spec mc vlan.
+	 * Set_uni_port and mc_vid cannot happen at same time */
+	else if (rule_action->pkt_act & TPM_ACTION_SPEC_MC_VID) {
+		ret_code = tpm_db_mc_vlan_get_ai_bit_by_vid(l2_key->vlan1.vid, &ai_bits);
+		IF_ERROR(ret_code);
+
+		ai_vector.mc_vid_entry = ai_bits;
+	}
+
+	/* all tag/untag PNC with VLANOP_NOOP will set split mod AI */
+	if (tpm_split_mod_stage1_check(pkt_mod_bm, pkt_mod, rule_action, true)) {
+
+		/* all tag/untag PNC with VLANOP_NOOP will set split mod AI */
+		int_pkt_act |= TPM_ACTION_SET_SPLIT_MOD;
+	}
+
+	/* Set AI Bits */
+	tpm_proc_static_ai_sram_build(&ai_vector, rule_action->pkt_act, int_pkt_act,
+				      &(sram_data->add_info_data), &(sram_data->add_info_mask));
+
+	/* Update dummy register (offset automatically=zero) */
+	/* The L3_offset_register was already updated in the TPM_PNC_NUM_VLAN_TAGS range */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	if (rule_action->next_phase == STAGE_DONE) {
+		tpm_proc_setstage_done(rule_action, sram_data);
+
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_L3 | TPM_PNCL_SET_L4);
+		/* Set L3, L4 to OTHER */
+		sram_data->l3_type = TPM_PNCL_L3_OTHER;
+		sram_data->l4_type = TPM_PNCL_L4_OTHER;
+	} else if (rule_action->next_phase == STAGE_L3_TYPE) {
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_ETH_TYPE, &range_conf);
+		IF_ERROR(ret_code);
+
+		sram_data->next_lu_id = range_conf.base_lu_id;
+		sram_data->next_lu_off_reg = TPM_PNC_ETY_REG;
+
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage not supported\n");
+		return(TPM_FAIL);
+	}
+
+	/* Signal specific packet types to CPU */
+	if (tpm_proc_bc_check(l2_key))
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_BC;
+	else if (tpm_proc_mc_check(l2_key))
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_MC;
+	else
+		sram_data->sram_updt_bm	|= TPM_PNCL_SET_UC;
+
+	/* Set Modification */
+	tpm_proc_set_mod(rule_action, sram_data, mod_cmd);
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ipv4_tcam_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* src_port          - packet source port
+* dir               - Packet direction
+* rule_num          - API rule number
+* l2_key            - layer2 key data
+* parse_rule_bm     - Parse rules bitmap
+* OUTPUTS:
+* tcam_data         - Logical TCAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_ipv4_tcam_build(tpm_src_port_type_t src_port,
+				 tpm_dir_t dir,
+				 uint32_t rule_num,
+				 tpm_ipv4_acl_key_t *ipv4_key,
+				 tpm_parse_fields_t parse_rule_bm,
+				 tpm_parse_flags_t parse_flags_bm,
+				 tpm_rule_action_t *rule_action,
+				 tpm_pkt_mod_t *pkt_mod,
+				 tpm_pkt_mod_bm_t pkt_mod_bm,
+				 tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	uint8_t l4_parse = 0, l4_hdr_update = 0;
+	/*uint8_t l4_hdr_update=0; */
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t src_port_field;
+	long long parse_int_flags_bm = 0;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) parse_rule_bm(%d) \n",
+		     src_port, dir, rule_num, parse_rule_bm);
+
+	/* IPV4 Parsing, according to bm in param */
+	tcam_data->ipv4_parse_bm = parse_rule_bm;
+
+	/*Also Check ipv4_ver */
+	tcam_data->ipv4_parse_bm |= TPM_IPv4_PARSE_VER;
+	tcam_data->pkt_key.ipv4_add_key.ipv4_ver = 0x4;
+	tcam_data->pkt_key.ipv4_add_key.ipv4_ver_mask = 1;
+
+	/* If (this rule looks at L4 ports) THEN
+	   packet MUST not be fragmented AND
+	   packet MUST not have options (ihl=0x5). */
+	l4_parse = ((parse_rule_bm & TPM_PARSE_L4_SRC) || (parse_rule_bm & TPM_PARSE_L4_DST));
+
+	/* If (this rule does not look at L4 data,
+	   however it is performing packet modification that effects the L4 checksum) THEN
+	   packet must not be fragmented  */
+	l4_hdr_update = ((SET_MOD(rule_action->pkt_act)) && (L4_CHECK_MOD(pkt_mod_bm)));
+
+	if (l4_parse || l4_hdr_update) {
+		/* Must not be fragmented */
+		tcam_data->ipv4_parse_bm |= (TPM_IPv4_PARSE_FLAG_MF | TPM_IPv4_PARSE_FRAG_OFFSET);
+		tcam_data->pkt_key.ipv4_add_key.ipv4_frag_offset = 0;
+		tcam_data->pkt_key.ipv4_add_key.ipv4_frag_offset_mask = 1;
+		tcam_data->pkt_key.ipv4_add_key.ipv4_flags = 0;
+		tcam_data->pkt_key.ipv4_add_key.ipv4_flags_mask = 1;
+		if (l4_parse) {
+			/* No options */
+			tcam_data->ipv4_parse_bm |= (TPM_IPv4_PARSE_IHL);
+			tcam_data->pkt_key.ipv4_add_key.ipv4_ihl = 0x5;
+			tcam_data->pkt_key.ipv4_add_key.ipv4_ihl_mask = 1;
+		}
+	}
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port))
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+
+	/* set CTC CnM */
+	/*if Ipv4 split, check AI bit, update tcam*/
+	if ((STAGE_CTC_CM == rule_action->next_phase) || ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) &&
+		(0xff == pkt_mod->vlan_mod.vlan1_out.pbit_mask) &&
+		(pkt_mod_bm == TPM_VLAN_MOD))) {
+
+		/*if Ipv4 split or CTC CnM, check AI bit, update tcam*/
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+
+	/* Add AI bits (src_port, parse_flag_bits) */
+	src_port_field.src_port = src_port;
+	tpm_proc_parse_flag_ai_tcam_build(&src_port_field,
+					  parse_flags_bm, parse_int_flags_bm, &(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = src_port;
+	if (ipv4_key)
+		memcpy(&(tcam_data->pkt_key.ipv4_key), ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV4_MAIN, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ipv4_dscp_sram_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* rule_num          - API rule number
+* target_queue      - CPU (Rx) or Hwf (Tx) Queue to set to
+* rule_num          - API rule number
+*
+* OUTPUTS:
+* l2_sram_data      - Logical SRAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_ipv4_dscp_sram_build(uint32_t rule_num, uint8_t target_queue, tpm_pncl_sram_data_t *sram_data)
+{
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "rule_num(%d) \n", rule_num);
+
+	sram_data->add_info_data = 0;
+	sram_data->add_info_mask = 0;
+	sram_data->mh_reg.mh_set = TPM_FALSE;
+	sram_data->mh_reg.mh_reg = 0;
+	sram_data->next_lu_id = 0;
+	sram_data->next_lu_off_reg = 0;
+	sram_data->next_offset.offset_base = 0;
+	sram_data->next_offset.offset_sub.ipv4_subf = 0;
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Set Queue */
+	sram_data->pnc_queue = target_queue;
+	/* Set Lookup Done */
+	sram_data->sram_updt_bm = TPM_PNCL_SET_LUD;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "shift_updt_reg(%d), add_in_data(%x) add_in_mask(%x)",
+		     sram_data->shift_updt_reg, sram_data->add_info_data, sram_data->add_info_mask);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ipv4_sram_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* src_port          - packet source port
+* dir               - Packet direction
+* rule_num          - API rule number
+* pon_type          - WAN technology
+* l2_key            - layer2 key data
+* ipv4_parse_bm     - Parse rules bitmap
+* pkt_frwd          - See xxx
+* rule_action       - See xxx
+*
+* OUTPUTS:
+* l2_sram_data      - Logical SRAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_ipv4_sram_build(tpm_src_port_type_t src_port,
+				 tpm_dir_t dir,
+				 uint32_t rule_num,
+				 tpm_db_pon_type_t pon_type,
+				 tpm_ipv4_acl_key_t *ipv4_key,
+				 tpm_parse_fields_t ipv4_parse_bm,
+				 tpm_parse_flags_t parse_flags_bm,
+				 tpm_pkt_frwd_t *pkt_frwd,
+				 tpm_rule_action_t *rule_action,
+				 uint32_t mod_cmd,
+				 tpm_pkt_mod_bm_t pkt_mod_bm,
+				 tpm_pkt_mod_t	  *pkt_mod,
+				 tpm_pncl_sram_data_t *sram_data)
+{
+	uint32_t l4_parse = 0;
+	tpm_db_pnc_range_conf_t range_conf;
+	long long int_pkt_act = 0;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) \n", src_port, dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Check and set values for STAGE_DONE */
+	if (rule_action->next_phase == STAGE_DONE) {
+		/* DO NOTHING */
+		/* Note: Also for STAGE_DONE,
+		   the packet_len_check and ipv4_pkt_type lookups are performed. */
+	} else if (rule_action->next_phase != STAGE_CTC_CM) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage not supported\n");
+		return(TPM_FAIL);
+	}
+
+	/* Set next offset and update register */
+	sram_data->shift_updt_reg = TPM_PNC_LU_REG1;
+	sram_data->next_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	sram_data->next_offset.offset_sub.ipv4_subf = 0xFFFF;	/* For IPV4, this sets the offset to 126 */
+
+	/* If the l4_proto is parsed, then set udp/tcp/other, no need to parse again in later stage */
+	if (ipv4_parse_bm & TPM_IPv4_PARSE_PROTO) {
+		/* Set correct protocol */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_L4;
+
+		if (ipv4_key->ipv4_proto == IPPROTO_UDP)
+			sram_data->l4_type = TPM_PNCL_L4_UDP;
+		else if (ipv4_key->ipv4_proto == IPPROTO_TCP)
+			sram_data->l4_type = TPM_PNCL_L4_TCP;
+		else
+			sram_data->l4_type = TPM_PNCL_L4_OTHER;
+
+		/* No need to check proto in later stage */
+		int_pkt_act |= TPM_ACTION_SET_NO_PROTO_CHECK;
+	}
+
+	/*** Set next lookup configuration ***/
+
+	/* Following applies only to ROUTED/NAPT streams (mac-to-me=1), and not TO_CPU */
+	if ((parse_flags_bm & TPM_PARSE_FLAG_MTM_TRUE) &&
+	    ((parse_flags_bm & TPM_PARSE_FLAG_TO_CPU_TRUE) == 0) && ((rule_action->pkt_act & TPM_ACTION_TO_CPU) == 0)) {
+		/* For TCP NAPT, check the tcp_flags */
+		l4_parse = ((ipv4_parse_bm & TPM_PARSE_L4_SRC) || (ipv4_parse_bm & TPM_PARSE_L4_DST));
+		if (l4_parse && (sram_data->l4_type == TPM_PNCL_L4_TCP)) {
+			sram_data->next_lu_off_reg = TPM_PNC_LU_REG1;
+			ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TCP_FLAG, &range_conf);
+			IF_ERROR(ret_code);
+		}
+		/* For any other NAPT/ROUTE, check TTL */
+		else {
+			ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TTL, &range_conf);
+			IF_ERROR(ret_code);
+		}
+	} else if (rule_action->next_phase == STAGE_CTC_CM){
+		/* go to CTC stage */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_IPV4_PRE, &range_conf);
+		IF_ERROR(ret_code);
+
+		/* set IPv4 AI and set L4 type */
+		sram_data->l4_type = TPM_PNCL_L4_OTHER;
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_L4;
+
+		sram_data->next_lu_off_reg = TPM_PNC_LU_REG0;
+		/* set action IPv4 */
+		int_pkt_act = TPM_ACTION_SET_CNM_IPV4;
+	} else {  /* All others - Next lu_id = IPV4_PROTO/IPV4_FRAG/IPV4_LEN */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_PROTO, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_off_reg = TPM_PNC_LU_REG0;
+	}
+
+	sram_data->next_lu_id = range_conf.base_lu_id;
+
+	/* If fragmented packets are not allowed (set in tpm_proc_ipv4_tcam_build funct),
+	   no need to do additional parsing stage  */
+	/* TODO: A full check should also check the values of MF, FRAG_OFFSET,
+	   not just check they are part of the parse_rule_bm */
+	if (ipv4_parse_bm & (TPM_IPv4_PARSE_FLAG_MF | TPM_IPv4_PARSE_FRAG_OFFSET)) {
+		sram_data->l3_type = TPM_PNCL_L3_IPV4_NFRAG;
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_L3;
+		int_pkt_act |= TPM_ACTION_SET_NO_FRAG_CHECK;
+	}
+
+	if (pkt_mod_bm & TPM_PPPOE_ADD)
+		int_pkt_act |= TPM_ACTION_SET_ADD_PPPOE;
+
+	/* Reset AI bits for uni_ports  */
+	if (rule_action->next_phase != STAGE_CTC_CM)
+		int_pkt_act |= TPM_ACTION_UNSET_UNI_PORT;
+
+	/* Build AI_bits according to pkt_actions bitmap */
+
+	/* Set AI bits */
+	tpm_proc_static_ai_sram_build(NULL,
+				      rule_action->pkt_act, int_pkt_act, &(sram_data->add_info_data), &(sram_data->add_info_mask));
+
+	/* Set Modification */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) {
+		/* split mod stage-2 */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_SPLIT_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_cmd;
+	}
+	else {
+		tpm_proc_set_mod(rule_action, sram_data, mod_cmd);
+	}
+
+	/* Set Target and Queue */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD,
+		     "next_lu_id(%d), next_lu_off_reg(%d), next_off_base(%d), next_off_subf(%x), shift_updt_reg(%d)\n"
+		     "add_info_data(%x) add_info_mask(%x)\n", sram_data->next_lu_id, sram_data->next_lu_off_reg,
+		     sram_data->next_offset.offset_base, sram_data->next_offset.offset_sub.ipv4_subf,
+		     sram_data->shift_updt_reg, sram_data->add_info_data, sram_data->add_info_mask);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_gen_tcam_build(tpm_src_port_type_t src_port,
+				       tpm_dir_t dir,
+				       uint32_t rule_num,
+				       tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+				       tpm_parse_fields_t parse_rule_bm,
+				       tpm_parse_flags_t parse_flags_bm,
+				       tpm_pkt_mod_t *pkt_mod,
+				       tpm_pkt_mod_bm_t pkt_mod_bm,
+				       tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t src_port_field;
+	long long parse_int_flags_bm = 0;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) parse_rule_bm(%x) parse_flag_bm(%x) \n",
+		     src_port, dir, rule_num, parse_rule_bm, parse_flags_bm);
+
+	/* IPV6 parsing, according to parse_rule */
+	tcam_data->ipv6_parse_bm = parse_rule_bm;
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port))
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+
+	/* set CTC CnM */
+	/*if Ipv6 split, check AI bit, update tcam*/
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) &&
+		(0xff == pkt_mod->vlan_mod.vlan1_out.pbit_mask) &&
+		(pkt_mod_bm == TPM_VLAN_MOD)) {
+
+		/*if Ipv6 split or CTC CnM, check AI bit, update tcam*/
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+
+	/* Build the AI bits according to parse_flags */
+	src_port_field.src_port = src_port;
+	tpm_proc_parse_flag_ai_tcam_build(&src_port_field,
+					  parse_flags_bm, parse_int_flags_bm, &(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = src_port;
+	if (ipv6_gen_key)
+		memcpy(&(tcam_data->pkt_key.ipv6_gen_key), ipv6_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_GEN, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_gen_sram_build(tpm_src_port_type_t src_port,
+				       tpm_dir_t dir,
+				       uint32_t rule_num,
+				       tpm_db_pon_type_t pon_type,
+				       tpm_pkt_frwd_t *pkt_frwd,
+				       tpm_rule_action_t *rule_action,
+				       uint32_t mod_cmd,
+				       tpm_pncl_sram_data_t *sram_data)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) \n", src_port, dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Set L3 */
+	sram_data->l3_type = TPM_PNCL_L3_IPV6;
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_L3;
+
+	if (rule_action->next_phase == STAGE_DONE) {
+		tpm_proc_setstage_done(rule_action, sram_data);
+
+		/* Update dummy register (offset automatically=zero) */
+		sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	} else if (rule_action->next_phase == STAGE_IPv6_DIP) {
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_DIP, &range_conf);
+		IF_ERROR(ret_code);
+
+		sram_data->next_lu_id = range_conf.base_lu_id;
+		sram_data->next_lu_off_reg = TPM_PNC_IPV6_DIP_REG;
+
+		sram_data->next_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+		sram_data->next_offset.offset_sub.ipv6_subf = TPM_IPv6_PARSE_DIP;
+		sram_data->shift_updt_reg = TPM_PNC_IPV6_DIP_REG;
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage not supported\n");
+		return(TPM_FAIL);
+	}
+
+	/* Set Modification */
+	tpm_proc_set_mod(rule_action, sram_data, mod_cmd);
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_dip_tcam_build(tpm_src_port_type_t src_port,
+				     tpm_dir_t dir,
+				     uint32_t rule_num,
+				     tpm_ipv6_addr_key_t *ipv6_dip_key,
+				     tpm_parse_fields_t parse_rule_bm,
+				     tpm_parse_flags_t parse_flags_bm,
+				     tpm_pkt_mod_t *pkt_mod,
+				     tpm_pkt_mod_bm_t pkt_mod_bm,
+				     tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	int32_t ret_code;
+	tpm_ai_vectors_t src_port_field;
+	long long parse_int_flags_bm = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) parse_rule_bm(%x) parse_flag_bm(%x) \n",
+		     src_port, dir, rule_num, parse_rule_bm, parse_flags_bm);
+
+	/* IPV6 parsing, according to parse_rule */
+	tcam_data->ipv6_parse_bm = parse_rule_bm;
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port))
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+
+	/* Build the AI bits according to parse_flags */
+	/* set CTC CnM */
+	/*if Ipv6 split, check AI bit, update tcam*/
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) &&
+		(0xff == pkt_mod->vlan_mod.vlan1_out.pbit_mask) &&
+		(pkt_mod_bm == TPM_VLAN_MOD)) {
+
+		/*if Ipv6 split or CTC CnM, check AI bit, update tcam*/
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+
+	src_port_field.src_port = src_port;
+	tpm_proc_parse_flag_ai_tcam_build(&src_port_field,
+					  parse_flags_bm, parse_int_flags_bm, &(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = src_port;
+
+	if (ipv6_dip_key)
+		memcpy(&(tcam_data->pkt_key.ipv6_dip_key), ipv6_dip_key, sizeof(tpm_ipv6_addr_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_DIP, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_dip_sram_build(tpm_src_port_type_t src_port,
+				     tpm_dir_t dir,
+				     uint32_t rule_num,
+				     tpm_db_pon_type_t pon_type,
+				     tpm_pkt_frwd_t *pkt_frwd,
+				     tpm_rule_action_t *rule_action,
+				     uint32_t mod_cmd,
+				     tpm_pncl_sram_data_t *sram_data)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) \n", src_port, dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Update dummy register (offset automatically=zero) */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Next Stage */
+	if (rule_action->next_phase == STAGE_DONE) {
+		tpm_proc_setstage_done(rule_action, sram_data);
+
+	} else if (rule_action->next_phase == STAGE_IPv6_NH) {
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_NH, &range_conf);
+		IF_ERROR(ret_code);
+
+		/* Next phase offset already exists in REG_0 */
+		sram_data->next_lu_id = range_conf.base_lu_id;
+		sram_data->next_lu_off_reg = TPM_PNC_LU_REG0;
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage not supported\n");
+		return(TPM_FAIL);
+	}
+
+	/* Set Modification */
+	tpm_proc_set_mod(rule_action, sram_data, mod_cmd);
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_nh_tcam_build(uint32_t rule_num,
+				    tpm_nh_iter_t nh_iter,
+				    uint32_t nh,
+				    tpm_parse_flags_t parse_flags_bm,
+				    tpm_rule_action_t *rule_action,
+				    tpm_pncl_tcam_data_t *tcam_data)
+{
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	long long parse_int_flags_bm = 0;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d) \n", rule_num);
+
+	if (nh != TPM_NH_RESERVED)
+		tcam_data->ipv6_parse_bm = TPM_IPv6_PARSE_NH;
+	else
+		tcam_data->ipv6_parse_bm = 0;
+
+	if (nh_iter == NH_ITER_0)
+		parse_int_flags_bm = TPM_PARSE_FLAG_NH2_ITER_FALSE;
+	else
+		parse_int_flags_bm = TPM_PARSE_FLAG_NH2_ITER_TRUE;
+
+	if (STAGE_CTC_CM == rule_action->next_phase) {
+		/*if next stage is CTC CnM, check AI bit, update tcam*/
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+
+	/* Insert AI_BITS */
+	tpm_proc_parse_flag_ai_tcam_build(NULL,
+					  parse_flags_bm, parse_int_flags_bm, &(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Rule applies to LAN GMAC and WAN GMAC, use "special purpose" src_port */
+	tcam_data->port_ids = tpm_proc_all_gmac_bm();
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = TPM_SRC_PORT_WAN_OR_LAN;
+	tcam_data->pkt_key.ipv6_key.ipv6_next_header = nh;
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_NH, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+
+	if (nh_iter == NH_ITER_1) {
+		start_offset.offset_base = TPM_PNCL_IPV6_EXT_OFFSET;
+		start_offset.offset_sub.subf = TPM_IPv6_PARSE_NH;
+	}
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_nh_sram_build(uint32_t rule_num,
+					tpm_nh_iter_t nh_iter,
+					uint32_t nh,
+				    tpm_db_pon_type_t pon_type,
+				    tpm_pkt_frwd_t *pkt_frwd,
+				    tpm_rule_action_t *rule_action,
+				    tpm_pncl_sram_data_t *sram_data)
+{
+
+	tpm_db_pnc_range_conf_t range_conf;
+	int32_t ret_code;
+	tpm_dir_t dir;
+	long long int_pkt_act = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d) \n", rule_num);
+
+	memset(sram_data, 0, sizeof(tpm_pncl_sram_data_t));
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+	dir = TPM_DIR_DS;	/*dummy_dir for bi_dir function */
+
+	/* Default, don't set MH */
+	sram_data->mh_reg.mh_set = TPM_FALSE;
+
+	/* Set the L4 protocol & the L4 AI bits, if udp or tcp */
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_L4;
+	if (nh == IPPROTO_UDP) {
+		sram_data->l4_type = TPM_PNCL_L4_UDP;
+		int_pkt_act |= TPM_ACTION_SET_L4P_TOG_UDP;
+	} else if (nh == IPPROTO_TCP) {
+		sram_data->l4_type = TPM_PNCL_L4_TCP;
+		int_pkt_act |= TPM_ACTION_SET_L4P_TOG_TCP;
+	} else
+		sram_data->l4_type = TPM_PNCL_L4_OTHER;
+
+	if (nh_iter == NH_ITER_0) {
+		/* Calculated value, from start of IPV6_HDR untill end of it */
+		sram_data->next_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+		sram_data->next_offset.offset_sub.ipv6_subf = 0xffff;	/* End of IPV6 Header */
+	} else {
+		/* Calculated value, from start of IPV6_HDR untill end of it */
+		sram_data->next_offset.offset_base = TPM_PNCL_IPV6_EXT_OFFSET;
+		sram_data->next_offset.offset_sub.ipv6_subf = 0xffff;	/* For IPV6 Ext Header, this sets the offset to 127 */
+	}
+
+	/* Sram update */
+	if (rule_action->next_phase == STAGE_IPV6_L4) {
+		/* Update PNC_REG_1 (L4_OFFSET_REG) with the IPV6_HDR_LEN (40) */
+		sram_data->shift_updt_reg = TPM_PNC_LU_REG1;	/* update L4_OFFSET_REG */
+		sram_data->next_lu_off_reg = TPM_PNC_LU_REG1;	/* lookup reg 1 */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_L4, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+		int_pkt_act |= TPM_ACTION_UNSET_NH2_ITER;
+	} else if (rule_action->next_phase == STAGE_IPv6_NH) {
+		/* Update PNC_REG_1 (L4_OFFSET_REG) with the IPV6_HDR_LEN (40) */
+		sram_data->shift_updt_reg = TPM_PNC_LU_REG1;	/* update L4_OFFSET_REG */
+		sram_data->next_lu_off_reg = TPM_PNC_LU_REG1;	/* lookup reg 1 */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_NH, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+		int_pkt_act |= TPM_ACTION_SET_NH2_ITER;
+	} else if (rule_action->next_phase == STAGE_IPv6_GEN) {
+		sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_GEN, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+		int_pkt_act |= TPM_ACTION_UNSET_NH2_ITER;
+	} else if (rule_action->next_phase == STAGE_CTC_CM) {
+		sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+		sram_data->next_lu_off_reg = TPM_PNC_CNM_L2_REG;
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_MAIN, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+		int_pkt_act |= TPM_ACTION_UNSET_CNM_IPV4 | TPM_ACTION_UNSET_IPV4_PRE_KEY;
+	} else if (rule_action->next_phase == STAGE_DONE)
+		tpm_proc_setstage_done(rule_action, sram_data);
+	else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " next phase not supported (%d)\n", rule_action->next_phase);
+		return(TPM_FAIL);
+	}
+
+	/* Set AI bits */
+	tpm_proc_static_ai_sram_build(NULL,
+				      rule_action->pkt_act, int_pkt_act, &(sram_data->add_info_data), &(sram_data->add_info_mask));
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_l4ports_tcam_build(tpm_src_port_type_t src_port,
+					 tpm_dir_t dir,
+					 uint32_t rule_num,
+					 tpm_l4_ports_key_t *l4_key,
+					 tpm_parse_fields_t parse_rule_bm,
+					 tpm_parse_flags_t parse_flags_bm,
+					 tpm_rule_action_t *rule_action,
+					 tpm_pkt_mod_t *pkt_mod,
+					 tpm_pkt_mod_bm_t pkt_mod_bm,
+					 tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t src_port_field;
+	long long parse_int_flags_bm = 0;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) parse_rule_bm(%x) parse_flag_bm(%x) \n",
+		     src_port, dir, rule_num, parse_rule_bm, parse_flags_bm);
+
+	/* L4 ports parsing, according to parse_rule */
+	tcam_data->l4_parse_bm = parse_rule_bm;
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port))
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+
+	/* Build the AI bits according to parse_flags */
+	src_port_field.src_port = src_port;
+	/*if Ipv6 split, check AI bit, update tcam*/
+	if ((STAGE_CTC_CM == rule_action->next_phase) || ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) &&
+		(0xff == pkt_mod->vlan_mod.vlan1_out.pbit_mask) &&
+		(pkt_mod_bm == TPM_VLAN_MOD))) {
+
+		/*if Ipv6 split or CTC CnM, check AI bit, update tcam*/
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+	tpm_proc_parse_flag_ai_tcam_build(&src_port_field,
+					  parse_flags_bm, parse_int_flags_bm, &(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = src_port;
+
+	if (l4_key)
+		memcpy(&(tcam_data->pkt_key.l4_ports_key), l4_key, sizeof(tpm_l4_ports_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_L4, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_l4ports_sram_build(tpm_src_port_type_t src_port,
+					 tpm_dir_t dir,
+					 uint32_t rule_num,
+					 tpm_db_pon_type_t pon_type,
+					 tpm_pkt_frwd_t *pkt_frwd,
+					 tpm_rule_action_t *rule_action,
+					 uint32_t mod_cmd,
+					 tpm_pncl_sram_data_t *sram_data)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) \n", src_port, dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Update dummy register (offset automatically=zero) */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Next Stage */
+	if (rule_action->next_phase == STAGE_DONE)
+		tpm_proc_setstage_done(rule_action, sram_data);
+	else if (rule_action->next_phase == STAGE_CTC_CM) {
+		/* nothing to Update */
+		sram_data->next_lu_off_reg = TPM_PNC_CNM_L2_REG;
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_MAIN, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+
+		sram_data->add_info_data &= ~(TPM_AI_CNM_IPV4_MASK | TPM_AI_CNM_IPV4_PRE_KEY_MASK);
+		sram_data->add_info_mask |= (TPM_AI_CNM_IPV4_MASK | TPM_AI_CNM_IPV4_PRE_KEY_MASK);
+	}
+	else if (rule_action->next_phase == STAGE_IPv6_GEN) {
+		/* nothing to Update */
+		sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+		sram_data->next_lu_off_reg = 0; /* lookup reg 1 */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_GEN, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+	}
+	else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage not supported\n");
+		return(TPM_FAIL);
+	}
+
+	/* Set Modification */
+	tpm_proc_set_mod(rule_action, sram_data, mod_cmd);
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_api_entry_rulenum_inc()
+*
+* DESCRIPTION:    Function increases the rule_number for a range of api_rule_nums
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* dir              - Direction of the API acl/table
+* rule_inc_start   - First entry to increase rule_num
+* rule_inc_end     - Last entry to increase rule_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_api_entry_rulenum_inc(tpm_api_sections_t api_section, uint32_t rule_inc_start, uint32_t rule_inc_end)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " api_section(%d), rule_dec_start(%d), rule_dec_end(%d)\n",
+		     api_section, rule_inc_start, rule_inc_end);
+
+	/* Increase the pnc_connection of the API's in the range */
+	ret_code = tpm_db_pnc_conn_inc(api_section, rule_inc_start, rule_inc_end);
+	IF_ERROR(ret_code);
+
+	/* Increase the rule_num of the API's in the range */
+	ret_code = tpm_db_api_entry_rulenum_inc(api_section, rule_inc_start, rule_inc_end);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_api_entry_rulenum_dec()
+*
+* DESCRIPTION:    Function decreases the rule_number for a range of api_rule_nums
+*
+* INPUTS:
+* api_section      - Section of the API acl/table
+* dir              - Direction of the API acl/table
+* rule_dec_start   - First entry to decrease rule_num
+* rule_dec_end     - Last entry to decrease rule_num
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_api_entry_rulenum_dec(tpm_api_sections_t api_section, uint32_t rule_dec_start, uint32_t rule_dec_end)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " api_section(%d, rule_dec_start(%d), rule_dec_end(%d)\n",
+		     api_section, rule_dec_start, rule_dec_end);
+
+	/* Decrease the pnc_connection of the API's in the range */
+	ret_code = tpm_db_pnc_conn_dec(api_section, rule_dec_start, rule_dec_end);
+	IF_ERROR(ret_code);
+
+	/* Decrease the rule_num of the API's in the range */
+	ret_code = tpm_db_api_entry_rulenum_dec(api_section, rule_dec_start, rule_dec_end);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_get_cpu_lpbk_entry_num()
+*
+* DESCRIPTION: The API get the entry number from CPU loopback DB
+*
+* INPUTS:
+*         None
+*
+* OUTPUTS:
+*         None
+*
+* RETURNS:
+* CPU loopback entry number.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+uint32_t tpm_proc_get_cpu_lpbk_entry_num(void)
+{
+	return gn_cpu_lpbk_entry_num;
+}
+
+/*******************************************************************************
+* tpm_proc_increase_cpu_lpbk_entry_num()
+*
+* DESCRIPTION: The API get the entry number from CPU loopback DB
+*
+* INPUTS:
+*         None
+*
+* OUTPUTS:
+*         None
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_increase_cpu_lpbk_entry_num(void)
+{
+	gn_cpu_lpbk_entry_num++;
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_decrease_cpu_lpbk_entry_num()
+*
+* DESCRIPTION: The API get the entry number from CPU loopback DB
+*
+* INPUTS:
+*         None
+*
+* OUTPUTS:
+*         None
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_decrease_cpu_lpbk_entry_num(void)
+{
+	if (gn_cpu_lpbk_entry_num > 0)
+		gn_cpu_lpbk_entry_num--;
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_check_cpu_wan_loopback_param()
+*
+* DESCRIPTION: The API check the parameters of CPU loopback
+*
+* INPUTS:
+*           trg_port    - target tcont/LLID bitmap
+*           trg_queue   - target queue, 0-7
+*           gem_port    - target gem port ID
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_check_cpu_wan_loopback_param(uint32_t owner_id, tpm_pkt_frwd_t *pkt_frwd)
+{
+	tpm_gmacs_enum_t act_wan = tpm_db_active_wan_get();
+	tpm_db_pon_type_t pon_type;
+
+	tpm_db_pon_type_get(&pon_type);
+
+	if (TO_PON(TPM_DIR_US, pkt_frwd->trg_port, pon_type, act_wan) ||
+	    TO_ETHWAN(TPM_DIR_US, pkt_frwd->trg_port, act_wan)) {
+		/*cont */
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "*Illegal Target Port: dir=%d, trg_port=%08x, pon_type=%d *\r\n",
+			     TPM_DIR_US, pkt_frwd->trg_port, pon_type);
+		return(ERR_FRWD_INVALID);
+	}
+
+	if (pkt_frwd->trg_queue >= TPM_MAX_NUM_TX_QUEUE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "trg_queue[%d] is illegal\n", pkt_frwd->trg_queue);
+		return ERR_GENERAL;
+	}
+
+	if (pkt_frwd->gem_port >= TPM_MAX_NUM_GEM_PORT) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "gem_port[%d] is illegal\n", pkt_frwd->gem_port);
+		return ERR_GENERAL;
+	}
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_calc_flow_id()
+*
+* DESCRIPTION:    Calculate flow id according to frwd information.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_calc_flow_id(uint32_t owner_id, tpm_pkt_frwd_t *pkt_frwd, uint16_t *flow_id)
+{
+	uint32_t llid_idx = 0;
+
+	/*GPON mode */
+	if (pkt_frwd->gem_port)
+		*flow_id = pkt_frwd->gem_port;
+	/*EPON mode */
+	else {
+		/* Convert target port bitmap to llid number */
+		for (llid_idx = 0; llid_idx < 8; llid_idx++) {
+			if ((1 << llid_idx) & pkt_frwd->trg_port)
+				break;
+		}
+
+		/* Set default llid index */
+		if (llid_idx >= 8)
+			llid_idx = 0;
+
+		*flow_id = (llid_idx * TPM_MAX_NUM_TX_QUEUE) + pkt_frwd->trg_queue;
+	}
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_init_cpu_wan_loopback()
+*
+* DESCRIPTION: The API initialize CPU egress loopback data
+*
+* INPUTS:
+*
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_proc_init_cpu_wan_loopback(void)
+{
+
+	/* PnC and Modification Initialization are handled in global Init procedures,
+	   and not in this function. */
+
+	memset((uint8_t *) &gs_cpu_loopback[0], 0, sizeof(gs_cpu_loopback));
+	gn_cpu_lpbk_entry_num = 0;
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_init_cpu_wan_loopback()
+*
+* DESCRIPTION: The API initialize CPU egress loopback data
+*
+* INPUTS:
+*           flow_id - Flow ID as the index of loopback db
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           The pointer to specific CPU WAN loopback entry
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_cpu_loopback_t *tpm_proc_get_loopback_entry(uint16_t flow_id)
+{
+	if (flow_id >= TPM_MAX_CPU_LOOPBACK_NUM) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " flow_id[%d] is illegal\n", flow_id);
+
+		return NULL;
+	}
+
+	return &gs_cpu_loopback[flow_id];
+}
+
+/*******************************************************************************
+* tpm_proc_add_cpu_loopback_rule()
+*
+* DESCRIPTION:    Main function for adding cpu loopback rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_cpu_loopback_rule(uint32_t owner_id,
+						uint32_t rule_num,
+						uint32_t *rule_idx,
+						tpm_pkt_frwd_t *pkt_frwd)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint16_t flow_id = 0;
+	uint32_t pnc_entry = 0;
+	uint32_t mod_entry = 0;
+	uint32_t api_rng_entries = 0;
+	uint32_t l_rule_idx = 0;
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+
+	tpm_pkt_mod_t pkt_mod;
+	tpm_l2_acl_key_t l2_key;
+	tpm_rule_action_t rule_action;
+
+	if (!tpm_db_cpu_wan_lpbk_en_get()){
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "CPU WAN loopback has not been enabled\n");
+		IF_ERROR(ERR_FEAT_UNSUPPORT);
+	}
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_num(%d)\n", owner_id, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_cpu_loopback_check(owner_id, rule_num, pkt_frwd);
+	IF_ERROR(ret_code);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_CPU_LOOPBACK_ACL, &range_id);
+
+	/*********** Create Modification Entries **********/
+	memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
+	pkt_mod.vlan_mod.vlan_op = VLANOP_EXT_TAG_DEL;
+	ret_code =
+	tpm_proc_create_mod(TPM_ACTION_SET_PKT_MOD, pkt_frwd->trg_port, &pkt_mod, TPM_VLAN_MOD, 0, &mod_entry,
+			    &trg_gmac);
+	IF_ERROR(ret_code);
+
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	memset(&l2_key, 0, sizeof(tpm_l2_acl_key_t));
+	l2_key.vlan1.tpid = TPM_MOD2_CPU_LOOPBACK_ETY;
+	l2_key.vlan1.tpid_mask = 0xffff;
+	l2_key.vlan1.vid_mask = 0xffff;
+	ret_code = tpm_proc_calc_flow_id(TPM_MOD_OWNER_TPM, pkt_frwd, &flow_id);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return(ret_code);
+	}
+	l2_key.vlan1.vid = flow_id;
+
+	int_ret_code =
+	tpm_proc_l2_tcam_build(TPM_SRC_PORT_UNI_ANY, TPM_DIR_US, rule_num, &l2_key, TPM_L2_PARSE_ONE_VLAN_TAG, 0,
+			       &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	memset(&rule_action, 0, sizeof(tpm_rule_action_t));
+	rule_action.next_phase = STAGE_DONE;
+	rule_action.pkt_act = TPM_ACTION_SET_TARGET_PORT | TPM_ACTION_SET_TARGET_QUEUE | TPM_ACTION_SET_PKT_MOD;
+	int_ret_code =
+	tpm_proc_l2_sram_build(TPM_SRC_PORT_UNI_ANY, TPM_DIR_US, rule_num, pon_type, pkt_frwd, &rule_action,
+			       mod_entry, &(pnc_data.pncl_sram), &l2_key, &pkt_mod, 0);
+	IF_ERROR(int_ret_code);
+
+	/*** Insert the PNC Entry ***/
+	tpm_proc_create_acl_pnc_entry(TPM_CPU_LOOPBACK_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+	IF_ERROR(int_ret_code);
+
+	/*********** Update API Range in DB **********/
+
+	/* Set PNC API data */
+	api_data.l2_prim_key.src_port = TPM_SRC_PORT_UNI_ANY;
+	api_data.l2_prim_key.parse_rule_bm = TPM_L2_PARSE_ONE_VLAN_TAG;
+	api_data.l2_prim_key.parse_flags_bm = 0;
+	api_data.l2_prim_key.pkt_mod_bm = TPM_VLAN_MOD;
+	memcpy(&(api_data.l2_prim_key.rule_action), &rule_action, sizeof(tpm_rule_action_t));
+	memcpy(&(api_data.l2_prim_key.l2_key), &l2_key, sizeof(tpm_l2_acl_key_t));
+	memcpy(&(api_data.l2_prim_key.pkt_mod), &pkt_mod, sizeof(tpm_pkt_mod_t));
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.l2_prim_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.l2_prim_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	/* Set API modification data */
+	tpm_proc_set_api_moddata(rule_action.pkt_act, trg_gmac, &mod_con, mod_entry);
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+	if (rule_num < api_rng_entries) {
+		int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_CPU_LOOPBACK_ACL, rule_num, (api_rng_entries - 1));
+		IF_ERROR(int_ret_code);
+	}
+
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_CPU_LOOPBACK_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_cpu_wan_loopback()
+*
+* DESCRIPTION: The API add CPU egress loopback modification and PnC rules for
+*              specific Tcont/queue/gem_port
+*
+* INPUTS:   owner_id    - APP owner id  should be used for all API calls.
+*           pkt_frwd    - packet forwarding info: target tcont/LLID number, 0-7
+*                         target queue, 0-7, target gem port ID
+*
+*
+* OUTPUTS:
+*           mod_idx     - Returned by HW modification, to fill Tx description
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_cpu_wan_loopback(uint32_t owner_id, tpm_pkt_frwd_t *pkt_frwd, uint32_t *mod_idx)
+{
+	int32_t ret_code;
+	tpm_init_cpu_loopback_t cpu_loopback_val;
+	tpm_pkt_mod_t mod_data;
+	uint32_t rule_idx = 0;
+	uint16_t flow_id = 0;
+	tpm_cpu_loopback_t *lpbk_entry = NULL;
+	uint32_t lpbk_num = 0;
+
+	if (!tpm_db_cpu_wan_lpbk_en_get()){
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "CPU WAN loopback has not been enabled\n");
+		IF_ERROR(ERR_FEAT_UNSUPPORT);
+	}
+
+	/* Verify whether input parameters are legal */
+	ret_code = tpm_proc_check_cpu_wan_loopback_param(owner_id, pkt_frwd);
+	if (ret_code != TPM_RC_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return(ret_code);
+	}
+
+	/* Get flow ID */
+	ret_code = tpm_proc_calc_flow_id(TPM_MOD_OWNER_TPM, pkt_frwd, &flow_id);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return(ret_code);
+	}
+
+	/* Get CPU WAN loopback entry from DB */
+	lpbk_entry = tpm_proc_get_loopback_entry(flow_id);
+	if (lpbk_entry == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return ERR_GENERAL;
+	}
+
+	/* Check whether the target has already been created, this validation is put at the */
+	/* first because of performance consideration.                                      */
+	if (TPM_TRUE == lpbk_entry->in_use) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "CPU loopback: target already exsit, return \r\n");
+		*mod_idx = lpbk_entry->mod_idx;
+		return TPM_RC_OK;
+	}
+
+	/* Get CPU loopback state: disabled / enabled */
+	ret_code = tpm_db_cpu_loopback_get(&cpu_loopback_val);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return(ret_code);
+	}
+
+	/* Do nothing if CPU loopback function is disabled */
+	if (TPM_CPU_LOOPBACK_DISABLED == cpu_loopback_val) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "CPU loopback disabled, return \r\n");
+		return TPM_RC_OK;
+	}
+
+	/* Check whether CPU loopback entry number exceed the Max value */
+	lpbk_num = tpm_proc_get_cpu_lpbk_entry_num();
+	if (lpbk_num > TPM_MAX_CPU_LOOPBACK_ENTRY) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]:(%d) Exceed MAX entry number\r\n", __func__, __LINE__,
+			     lpbk_num);
+		return ERR_GENERAL;
+	}
+
+	/* Add modification rules to GMAC1, and get mod index */
+	memset((uint8_t *) &mod_data, 0, sizeof(tpm_pkt_mod_t));
+	mod_data.vlan_mod.vlan_op = VLANOP_EXT_TAG_INS;
+	mod_data.vlan_mod.vlan1_out.tpid = TPM_MOD2_CPU_LOOPBACK_ETY;
+	mod_data.vlan_mod.vlan1_out.tpid_mask = TPM_MOD2_NEW_TPID;
+	mod_data.vlan_mod.vlan1_out.vid = flow_id;
+	mod_data.vlan_mod.vlan1_out.vid_mask = TPM_MOD2_NEW_VID;
+	mod_data.vlan_mod.vlan1_out.cfi = 0;
+	mod_data.vlan_mod.vlan1_out.cfi_mask = TPM_MOD2_NEW_CFI;
+	mod_data.vlan_mod.vlan1_out.pbit = 0;
+	mod_data.vlan_mod.vlan1_out.pbit_mask = TPM_MOD2_NEW_PBIT;
+	ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_1, TPM_VLAN_MOD, 0, &mod_data, mod_idx);
+	if (ret_code != TPM_RC_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return(ret_code);
+	}
+
+	/* Add PnC rules including modification to GMAC0 and PON MAC */
+	/* Rule number will always be 0 in ACL mode */
+	ret_code = tpm_proc_add_cpu_loopback_rule(TPM_MOD_OWNER_TPM, 0, &rule_idx, pkt_frwd);
+	if (ret_code != TPM_RC_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return(ret_code);
+	}
+
+	/* Save to DB */
+	lpbk_entry->trg_port = pkt_frwd->trg_port;
+	lpbk_entry->trg_queue = pkt_frwd->trg_queue;
+	lpbk_entry->gem_port = pkt_frwd->gem_port;
+	lpbk_entry->mod_idx = *mod_idx;
+	lpbk_entry->rule_idx = rule_idx;
+	lpbk_entry->in_use = TPM_TRUE;
+
+	tpm_proc_increase_cpu_lpbk_entry_num();
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_del_cpu_wan_loopback()
+*
+* DESCRIPTION: The API delete CPU egress loopback modification and PnC rules for
+*              specific Tcont/queue/gem_port
+*
+* INPUTS:   owner_id    - APP owner id  should be used for all API calls.
+*           pkt_frwd    - packet forwarding info: target tcont/LLID number, 0-7
+*                         target queue, 0-7, target gem port ID
+*
+* OUTPUTS:
+*           NONE
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_cpu_wan_loopback(uint32_t owner_id, tpm_pkt_frwd_t *pkt_frwd)
+{
+	int32_t ret_code;
+	tpm_init_cpu_loopback_t cpu_loopback_val;
+	uint16_t flow_id = 0;
+	tpm_cpu_loopback_t *lpbk_entry = NULL;
+
+	if (!tpm_db_cpu_wan_lpbk_en_get()){
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "CPU WAN loopback has not been enabled\n");
+		IF_ERROR(ERR_FEAT_UNSUPPORT);
+	}
+
+	/* Verify whether input parameters are legal */
+	ret_code = tpm_proc_check_cpu_wan_loopback_param(owner_id, pkt_frwd);
+	if (ret_code != TPM_RC_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return(ret_code);
+	}
+
+	/* Get CPU loopback state: disabled / enabled */
+	ret_code = tpm_db_cpu_loopback_get(&cpu_loopback_val);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " recvd ret_code(%d)\r\n", ret_code);
+		return(ret_code);
+	}
+
+	/* Do nothing if CPU loopback function is disabled */
+	if (TPM_CPU_LOOPBACK_DISABLED == cpu_loopback_val) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "CPU loopback disabled, return \r\n");
+		return TPM_RC_OK;
+	}
+
+	/* Get flow ID */
+	ret_code = tpm_proc_calc_flow_id(TPM_MOD_OWNER_TPM, pkt_frwd, &flow_id);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return(ret_code);
+	}
+
+	/* Get CPU WAN loopback entry from DB */
+	lpbk_entry = tpm_proc_get_loopback_entry(flow_id);
+	if (lpbk_entry == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "%s[Line(%d)]: recvd ret_code(%d) \r\n", __func__, __LINE__,
+			     ret_code);
+		return ERR_GENERAL;
+	}
+
+	/* Delete related GMAC1 mod and PnC rule if the entry already exsit */
+	if (TPM_TRUE == lpbk_entry->in_use) {
+		/* Delete GMAC1 modification */
+		ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_1, lpbk_entry->mod_idx);
+		if (ret_code != TPM_RC_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " tpm_mod2_entry_del error, ret_code(%d)\r\n", ret_code);
+			return(ret_code);
+		}
+
+		/* Delete PnC rule and PON MAC modification */
+		ret_code = tpm_proc_del_acl_rule(TPM_CPU_LOOPBACK_ACL, TPM_MOD_OWNER_TPM, lpbk_entry->rule_idx, TPM_FALSE);
+		if (ret_code != TPM_RC_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " tpm_proc_del_acl_rule error, ret_code(%d)\r\n", ret_code);
+			return(ret_code);
+		}
+
+		/* Delete entry from DB */
+		memset(lpbk_entry, 0, sizeof(tpm_cpu_loopback_t));
+		lpbk_entry->in_use = TPM_FALSE;
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "loopback entry non-existing, recvd ret_code(%d) \r\n", ret_code);
+		return ERR_GENERAL;
+	}
+
+
+	tpm_proc_decrease_cpu_lpbk_entry_num();
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_add_l2_prim_acl_rule()
+*
+* DESCRIPTION:    Main function for adding L2 API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_l2_prim_acl_rule(uint32_t owner_id,
+					       tpm_src_port_type_t src_port,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l2_acl_key_t *l2_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_pkt_mod_t *pkt_mod,
+					       tpm_pkt_mod_bm_t pkt_mod_bm,
+					       tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0, bi_dir = 0, update_sram_only = 0;
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_dir_t dir = 0;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	tpm_db_pnc_range_conf_t rangConf;
+	tpm_api_lu_conf_t lu_conf;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d)\n", owner_id, src_port, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_l2_check(owner_id, src_port, rule_num, parse_rule_bm,
+					 l2_key, parse_flags_bm, pkt_frwd, pkt_mod_bm, pkt_mod, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Get direction */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_L2_PRIM_ACL, &range_id);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Only do it in table mode */
+	if (TPM_RANGE_TYPE_TABLE == rangConf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_L2_PRIM_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d) already exists\n",
+				     owner_id, src_port, rule_num);
+
+			/* TCAM Key and modification info are not changed, only update SRAM */
+			if ((0 == memcmp(l2_key, &api_data.l2_prim_key.l2_key, sizeof(tpm_l2_acl_key_t)))
+			    && (src_port == api_data.l2_prim_key.src_port)
+			    && (parse_rule_bm == api_data.l2_prim_key.parse_rule_bm)
+			    && (parse_flags_bm == api_data.l2_prim_key.parse_flags_bm)
+			    && (SET_MOD(rule_action->pkt_act) == SET_MOD(api_data.l2_prim_key.rule_action.pkt_act))) {
+				/* No modification */
+				if (!SET_MOD(rule_action->pkt_act))
+					update_sram_only = 1;
+				/* There are modification, then check furthur */
+				else if ((pkt_mod_bm == api_data.l2_prim_key.pkt_mod_bm)
+					 && (0 ==
+					     memcmp(pkt_mod, &api_data.l2_prim_key.pkt_mod, sizeof(tpm_pkt_mod_t)))) {
+					update_sram_only = 1;
+					mod_entry = mod_con.mod_cmd_ind;
+					trg_gmac = mod_con.mod_cmd_mac;
+				}
+			}
+
+			/* TCAM Key or modification info is changed */
+			if (!update_sram_only) {
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD,
+					     " owner(%d) src_port(%d), rule_num(%d) TCAM key/modification changed\n",
+					     owner_id, src_port, rule_num);
+
+				tpm_proc_del_l2_prim_acl_rule(owner_id, rule_num, TPM_INT_CALL);
+				IF_ERROR(ret_code);
+			}
+		}
+	}
+
+	if (!update_sram_only) {
+		if (SET_MOD(rule_action->pkt_act)) {
+			if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+				return(ERR_MOD_INVALID);
+			} else if (trg_gmac == TPM_INVALID_GMAC) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+				return(ERR_MOD_INVALID);
+			}
+		}
+
+		/* if split mod is enable, add split rule if possible*/
+		if (tpm_split_mod_stage1_check(pkt_mod_bm, pkt_mod, rule_action, false)) {
+			/* split mod stage-1 */
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod stage-1\n");
+			/* get mod index from p-bit value */
+			ret_code = tpm_mod2_split_mod_create_l2_pmts(trg_gmac, pkt_mod, false);
+			if (TPM_RC_OK != ret_code)
+			{
+				TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to add pmt split mod stage-1\n");
+				return(TPM_FAIL);
+			}
+			int_ret_code = tpm_db_mod2_split_mod_get_vlan_index(trg_gmac, pkt_mod, &mod_entry);
+			if (TPM_DB_OK != int_ret_code) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-1, failed to get pmt entry\n");
+				return ERR_MOD_INVALID;
+			}
+
+			mod_entry *= 16;
+
+			/* VLANOP_EXT_TAG_MOD_INS mod insert VLAN p_bit*/
+			if (VLANOP_EXT_TAG_MOD_INS == pkt_mod->vlan_mod.vlan_op) {
+				if (pkt_mod->vlan_mod.vlan2_out.pbit_mask == 0xff)
+					mod_entry += (pkt_mod->vlan_mod.vlan2_out.pbit + 1);
+			} else {
+				if (pkt_mod->vlan_mod.vlan1_out.pbit_mask == 0xff)
+					mod_entry += (pkt_mod->vlan_mod.vlan1_out.pbit + 1);
+			}
+
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+		} else if((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+							(TPM_VLAN_MOD == pkt_mod_bm) &&
+							(VLANOP_NOOP == pkt_mod->vlan_mod.vlan_op) &&
+							(parse_flags_bm & TPM_PARSE_FLAG_TAG1_FALSE)) {
+			/*In L2 range, all untag PNC with VLANOP_NOOP will set PMT to 16*/
+			mod_entry = 16;
+		} else {
+		    /*********** Create Modification Entries **********/
+			ret_code =
+			tpm_proc_create_mod(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm,
+					    0 /*int_mod_bm */ ,
+					    &mod_entry, &trg_gmac);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_l2_tcam_build(src_port, dir, rule_num, l2_key, parse_rule_bm,
+					      parse_flags_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_l2_sram_build(src_port, dir, rule_num, pon_type, pkt_frwd, rule_action,
+					      mod_entry, &(pnc_data.pncl_sram), l2_key, pkt_mod, pkt_mod_bm);
+	IF_ERROR(int_ret_code);
+
+	if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_L2_PRIM_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+	/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_L2_PRIM_ACL, rule_num, update_sram_only, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+	if (!update_sram_only) {
+		/* Set PNC API data */
+		api_data.l2_prim_key.src_port = src_port;
+		api_data.l2_prim_key.parse_rule_bm = parse_rule_bm;
+		api_data.l2_prim_key.parse_flags_bm = parse_flags_bm;
+		api_data.l2_prim_key.pkt_mod_bm = pkt_mod_bm;
+		memcpy(&(api_data.l2_prim_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+		if (l2_key)
+			memcpy(&(api_data.l2_prim_key.l2_key), l2_key, sizeof(tpm_l2_acl_key_t));
+
+		if (pkt_frwd != NULL)
+			memcpy(&(api_data.l2_prim_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+		else
+			memset(&(api_data.l2_prim_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+		if (pkt_mod != NULL)
+			memcpy(&(api_data.l2_prim_key.pkt_mod), pkt_mod, sizeof(tpm_pkt_mod_t));
+		else
+			memset(&(api_data.l2_prim_key.pkt_mod), 0, sizeof(tpm_pkt_mod_t));
+
+		/* Set API modification data */
+		tpm_proc_set_api_moddata(rule_action->pkt_act, trg_gmac, &mod_con, mod_entry);
+
+		/* Set Pnc Connection data */
+		pnc_conn.num_pnc_ranges = 1;
+		pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+		pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+		if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+			/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+			if (rule_num < api_rng_entries) {
+				int_ret_code =
+				tpm_proc_api_entry_rulenum_inc(TPM_L2_PRIM_ACL, rule_num, (api_rng_entries - 1));
+				IF_ERROR(int_ret_code);
+			}
+		}
+
+		/* Set new API Entry */
+		int_ret_code = tpm_db_api_entry_set(TPM_L2_PRIM_ACL, rule_num, 0 /*bi_dir */ ,
+						    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+		IF_ERROR(int_ret_code);
+
+		/* Return Output */
+		*rule_idx = l_rule_idx;
+
+		/* Set aging counter group nunmber and msk */
+		int_ret_code = tpm_db_pnc_get_lu_conf(TPM_PNC_L2_MAIN, &lu_conf);
+		IF_ERROR(int_ret_code);
+		tpm_tcam_set_lu_mask(pnc_entry, (int32_t) lu_conf.lu_mask);
+		tpm_tcam_set_cntr_group(pnc_entry, (int32_t) lu_conf.cntr_grp);
+
+		/* alloc rule index if spec mc vlan */
+		if ((rule_action->pkt_act & TPM_ACTION_SPEC_MC_VID) && (dir == TPM_DIR_DS)) {
+			ret_code = tpm_db_mc_vlan_set_ai_bit_pnc_index(l2_key->vlan1.vid, l_rule_idx);
+			IF_ERROR(ret_code);
+		}
+	} else {
+		if (pkt_frwd != NULL)
+			memcpy(&(api_data.l2_prim_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+		else
+			memset(&(api_data.l2_prim_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+		int_ret_code = tpm_db_api_entry_invalidate(TPM_L2_PRIM_ACL, rule_num);
+		IF_ERROR(int_ret_code);
+
+		/* Set new API Entry */
+		int_ret_code = tpm_db_api_entry_set(TPM_L2_PRIM_ACL, rule_num, 0 /*bi_dir */ ,
+						    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+		IF_ERROR(int_ret_code);
+
+		/* Return Output */
+		*rule_idx = l_rule_idx;
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_pnc_create(tpm_pnc_ranges_t range_id, uint32_t pnc_entry, tpm_pncl_pnc_full_t *pnc_data)
+{
+
+	int32_t int_ret_code;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_pncl_entry_set(pnc_entry, pnc_data);
+	IF_ERROR(int_ret_code);
+
+	/* Decrease number of free entries in pnc_range */
+	int_ret_code = tpm_db_pnc_rng_free_ent_dec(range_id);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_l2_num_vlan_tags_init()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_l2_num_vlan_tags_init(void)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries, l2_lu, pnc_entry, dtag_entries, exp_entry;
+	tpm_db_pnc_range_t range_data;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_init_tpid_opt_t tpid_opt;
+	tpm_init_double_tag_t dbl_tag;
+	uint32_t i;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&tpid_opt, 0, sizeof(tpm_init_tpid_opt_t));
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_NUM_VLAN_TAGS, &range_data);
+	IF_ERROR(int_ret_code);
+	l2_lu = range_data.pnc_range_conf.base_lu_id;
+	free_entries = range_data.pnc_range_oper.free_entries;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "free_ent(%d)\n", free_entries);
+
+	/* Get tag TPID options */
+	int_ret_code = tpm_db_default_tag_tpid_get(&tpid_opt);
+	IF_ERROR(int_ret_code);
+
+	if (tpid_opt.opt_num == 0) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "none vlan tpid option! \n");
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	dtag_entries = 0;
+	for (i = 0; i < tpid_opt.opt_num; i++) {
+		if (tpid_opt.opt[i].v2_tpid != MV_TPM_UN_INITIALIZED_INIT_PARAM)
+			dtag_entries++;
+	}
+
+	if (dtag_entries == tpid_opt.opt_num) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "none single tag tpid option! \n");
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	exp_entry = tpid_opt.opt_num;
+
+	tpm_db_double_tag_support_get(&dbl_tag);
+	if (dbl_tag == TPM_DOUBLE_TAG_DISABLED)
+		exp_entry -= dtag_entries;
+
+	if ((exp_entry+1) > free_entries) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "not enough tag_num rules! (%d/%d)\n", free_entries, tpid_opt.opt_num+1);
+		IF_ERROR(ERR_GENERAL);
+	} else if ((exp_entry+1) < free_entries)
+		TPM_OS_WARN(TPM_TPM_LOG_MOD, "too much tag_num rules, waste. (%d/%d)\n", free_entries, tpid_opt.opt_num+1);
+
+	pnc_entry = range_data.pnc_range_conf.range_start+range_data.pnc_range_conf.api_start;
+	/* Basic TCAM/SRAM Config, valid for all following entries */
+	/* L2 LUID */
+	pnc_data.pncl_tcam.lu_id = range_data.pnc_range_conf.base_lu_id;
+	/* Bi-direction */
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+	/* Current Offset */
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
+	/* Set parse type for key */
+	pnc_data.pncl_tcam.l3_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv6_parse_bm = 0;
+	pnc_data.pncl_tcam.tcp_parse_bm = 0;
+	/* Set DO_NOT_REPEAT_TAG AI filter */
+	pnc_data.pncl_tcam.add_info_data = 0 << TPM_AI_DNRT_BIT_OFF;
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_DNRT_MASK;
+	/* Next LUID is still L2 */
+	pnc_data.pncl_sram.next_lu_id = range_data.pnc_range_conf.base_lu_id;
+	/* Using off_reg 1 */
+	pnc_data.pncl_sram.next_lu_off_reg = 1;
+	/* Update off_reg 0 -> ETY */
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_sram.next_offset.offset_sub.ipv4_subf = TPM_L2_PARSE_ETYPE;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_ETY_REG;
+	/* No queue update */
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	/* No ResultInfo&FlowId update */
+	pnc_data.pncl_sram.sram_updt_bm = 0;
+
+
+	/*************************************/
+	/* CREATE ENTRIES FOR DOUBLE TAGGED **/
+	/*************************************/
+
+	if (dbl_tag == TPM_DOUBLE_TAG_ENABLED) {
+		/* Set L2 key value */
+		pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_TWO_VLAN_TAG;
+
+		/* Set DO_NOT_REPEAT_TAG AI filter */
+		pnc_data.pncl_sram.add_info_data = 1 << TPM_AI_DNRT_BIT_OFF;
+		pnc_data.pncl_sram.add_info_mask = TPM_AI_DNRT_MASK;
+		/* Set DOUBLE_TAG AI filter */
+		pnc_data.pncl_sram.add_info_data |= 1 << TPM_AI_TAG1_BIT_OFF;
+		pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG1_MASK;
+		pnc_data.pncl_sram.add_info_data |= 1 << TPM_AI_TAG2_BIT_OFF;
+		pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG2_MASK;
+
+		/* Set VLAN Result_Info bit */
+		pnc_data.pncl_sram.sram_updt_bm  |= TPM_PNCL_SET_TAGGED;
+
+		for (i = 0; i < tpid_opt.opt_num; i++) {
+			if (tpid_opt.opt[i].v2_tpid != MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+				/* Set TPID of vlan tag */
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid = tpid_opt.opt[i].v1_tpid;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid_mask = 0xffff;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.pbit_mask = 0;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.cfi_mask = 0;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.vid_mask = 0;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.tpid = tpid_opt.opt[i].v2_tpid;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.tpid_mask = 0xffff;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.pbit_mask = 0;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.cfi_mask = 0;
+				pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.vid_mask = 0;
+
+				/* Create Entry in PnC */
+				int_ret_code = tpm_proc_pnc_create(TPM_PNC_NUM_VLAN_TAGS, pnc_entry, &pnc_data);
+				IF_ERROR(int_ret_code);
+				free_entries--;
+				pnc_entry++;
+			}
+		}
+	}
+
+
+	/*************************************/
+	/* CREATE ENTRIES FOR SINGLE TAGGED **/
+	/*************************************/
+
+	/* Set L2 key value */
+	pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_ONE_VLAN_TAG;
+
+	/* Set DO_NOT_REPEAT_TAG AI filter */
+	pnc_data.pncl_sram.add_info_data = 1 << TPM_AI_DNRT_BIT_OFF;
+	pnc_data.pncl_sram.add_info_mask = TPM_AI_DNRT_MASK;
+	/* Set SINGLE_TAG AI filter */
+	pnc_data.pncl_sram.add_info_data |= 0 << TPM_AI_TAG2_BIT_OFF;
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG2_MASK;
+	pnc_data.pncl_sram.add_info_data |= 1 << TPM_AI_TAG1_BIT_OFF;
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG1_MASK;
+
+	for (i = 0; i < tpid_opt.opt_num; i++) {
+		if (tpid_opt.opt[i].v2_tpid == MV_TPM_UN_INITIALIZED_INIT_PARAM) {
+			/* Set TPID of vlan tag */
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid = tpid_opt.opt[i].v1_tpid;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid_mask = 0xffff;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.pbit_mask = 0;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.cfi_mask = 0;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.vid_mask = 0;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.tpid = 0;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.tpid_mask = 0;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.pbit_mask = 0;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.cfi_mask = 0;
+			pnc_data.pncl_tcam.pkt_key.l2_key.vlan2.vid_mask = 0;
+
+			/* Create Entry in PnC */
+			int_ret_code = tpm_proc_pnc_create(TPM_PNC_NUM_VLAN_TAGS, pnc_entry, &pnc_data);
+			IF_ERROR(int_ret_code);
+			free_entries--;
+			pnc_entry++;
+		}
+	}
+
+	/*************************************/
+	/* CREATE ENTRIES FOR UNTAGGED      **/
+	/*************************************/
+
+	/* Set L2 key value */
+	pnc_data.pncl_tcam.l2_parse_bm = 0;
+
+	/* Set DO_NOT_REPEAT_TAG AI filter */
+	pnc_data.pncl_sram.add_info_data = 1 << TPM_AI_DNRT_BIT_OFF;
+	pnc_data.pncl_sram.add_info_mask = TPM_AI_DNRT_MASK;
+	/* Set ZERO_TAG AI filter */
+	pnc_data.pncl_sram.add_info_data |= 0 << TPM_AI_TAG2_BIT_OFF;
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG2_MASK;
+	pnc_data.pncl_sram.add_info_data |= 0 << TPM_AI_TAG1_BIT_OFF;
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TAG1_MASK;
+
+	/* Do NOT set VLAN Result_Info bit */
+	pnc_data.pncl_sram.sram_updt_bm = 0;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_NUM_VLAN_TAGS, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ipv4_proto_init()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_ipv4_proto_init(void)
+{
+
+	int32_t int_ret_code;
+	uint32_t free_entries, pnc_entry, ipv4_proto_lu, ipv4_frag_lu;
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Get NExt range IPV4_FRAG lu_id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_FRAG, &range_data);
+	IF_ERROR(int_ret_code);
+	ipv4_frag_lu = range_data.pnc_range_conf.base_lu_id;
+
+	/* Get IPV4_PROTO lu_id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_PROTO, &range_data);
+	IF_ERROR(int_ret_code);
+	ipv4_proto_lu = range_data.pnc_range_conf.base_lu_id;
+
+	/* Get pnc_range tcam_start_entry, and number of free entries */
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_start;
+
+	/*************************************/
+	/* CREATE ENTRIES FOR TCP UDP and    */
+	/* other ipv4 proto                ** */
+	/*************************************/
+
+	/* Basic TCAM/SRAM Config, valid for all following entries */
+	pnc_data.pncl_tcam.lu_id = ipv4_proto_lu;
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER;
+	pnc_data.pncl_tcam.ipv4_parse_bm = TPM_IPv4_PARSE_PROTO;
+
+	pnc_data.pncl_tcam.add_info_data = (0 << TPM_AI_NO_PROTO_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_NO_PROTO_MASK;
+
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	/* Update dummy register (offset automatically=zero) */
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_L4;
+	pnc_data.pncl_sram.next_lu_off_reg = TPM_PNC_LU_REG0;
+	pnc_data.pncl_sram.next_lu_id = ipv4_frag_lu;
+
+	/* Do not repeat this stage again */
+	pnc_data.pncl_sram.add_info_data = (1 << TPM_AI_NO_PROTO_BIT_OFF);
+	pnc_data.pncl_sram.add_info_mask = TPM_AI_NO_PROTO_MASK;
+
+	/***********************************************************/
+	/* Create  TCP, for  packets                               */
+	/***********************************************************/
+
+	NO_FREE_ENTRIES();
+
+	pnc_data.pncl_tcam.pkt_key.ipv4_key.ipv4_proto = IPPROTO_TCP;
+
+	/* Build SRAM Entry */
+	pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_TCP;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV4_PROTO, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/***********************************/
+	/* Create  UDP                     */
+	/***********************************/
+	NO_FREE_ENTRIES();
+	/* Build Tcam Entry */
+	pnc_data.pncl_tcam.pkt_key.ipv4_key.ipv4_proto = IPPROTO_UDP;
+
+	/* Build SRAM Entry */
+	pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_UDP;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV4_PROTO, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/**************************************/
+	/* Create Others                      */
+	/**************************************/
+	NO_FREE_ENTRIES();
+	/* Build Tcam Entry */
+
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+
+	/* Build SRAM Entry */
+	pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_OTHER;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV4_PROTO, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ipv4_frag_opt_init()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_ipv4_frag_init(void)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries, pnc_entry, ipv4_frag_lu, ipv4_len_lu;
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Get Next Range IPV4 LEN Lookup */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_LEN, &range_data);
+	IF_ERROR(int_ret_code);
+	ipv4_len_lu = range_data.pnc_range_conf.base_lu_id;
+
+	/* Get Range IPV4 FRAG Lookup */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_FRAG, &range_data);
+	IF_ERROR(int_ret_code);
+	ipv4_frag_lu = range_data.pnc_range_conf.base_lu_id;
+
+	/* Get number of entries */
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_start;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "free_ent(%d)\n", free_entries);
+
+	/* Basic TCAM/SRAM Config, valid for all following entries */
+	pnc_data.pncl_tcam.lu_id = ipv4_frag_lu;
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER;
+
+	/* frag_offset an MF TCAM keys */
+	pnc_data.pncl_tcam.pkt_key.ipv4_add_key.ipv4_flags = 0;
+	pnc_data.pncl_tcam.pkt_key.ipv4_add_key.ipv4_flags_mask = 1;
+	pnc_data.pncl_tcam.pkt_key.ipv4_add_key.ipv4_frag_offset = 0;
+	pnc_data.pncl_tcam.pkt_key.ipv4_add_key.ipv4_frag_offset_mask = 1;
+
+	/* Only look at ai_no_frag=0 */
+	pnc_data.pncl_tcam.add_info_data = (0 << TPM_AI_NO_FRAG_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_NO_FRAG_MASK;
+
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	/* Update dummy register (offset automatically=zero) */
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.next_lu_off_reg = TPM_PNC_LU_REG0;
+	pnc_data.pncl_sram.next_lu_id = ipv4_len_lu;
+
+	/* Signal the packet is not going through this range again */
+	pnc_data.pncl_sram.add_info_data = (1 << TPM_AI_NO_FRAG_BIT_OFF);
+	pnc_data.pncl_sram.add_info_mask = TPM_AI_NO_FRAG_MASK;
+
+	/* Set fragment information */
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_L3;
+
+	/*********************************************/
+	/* Create to CPU Unfragmented packets        */
+	/*********************************************/
+
+	NO_FREE_ENTRIES();
+
+	/*** Build Tcam Entry ***/
+
+	/* Only Unfragmented MF=0, frag_offset=0 */
+	pnc_data.pncl_tcam.ipv4_parse_bm = TPM_IPv4_PARSE_FLAG_MF | TPM_IPv4_PARSE_FRAG_OFFSET;
+
+	/* Only to_cpu packets */
+	pnc_data.pncl_tcam.add_info_data |= (1 << TPM_AI_TO_CPU_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask |= TPM_AI_TO_CPU_MASK;
+
+	/*** Build SRAM Entry ***/
+
+	/* Packet not fragmented */
+	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_IPV4_NFRAG;
+
+	/* LookupDone - it is to CPU */
+	pnc_data.pncl_sram.sram_updt_bm |= TPM_PNCL_SET_LUD;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV4_FRAG, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/***********************************************************/
+	/* Create to CPU Frag packets                              */
+	/***********************************************************/
+	NO_FREE_ENTRIES();
+
+	/* Don't check fragmented */
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+
+	/*** Build SRAM Entry ***/
+
+	/* Packet=fragmented */
+	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_IPV4_FRAG;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV4_FRAG, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/**************************************/
+	/* Create Non-CPU Non-Frag,           */
+	/**************************************/
+	NO_FREE_ENTRIES();
+
+	/*** Build Tcam Entry ***/
+
+	/* MF=0, frag_offset=0 */
+	pnc_data.pncl_tcam.ipv4_parse_bm = TPM_IPv4_PARSE_FLAG_MF | TPM_IPv4_PARSE_FRAG_OFFSET;
+
+	/* Don't check CPU/Non-CPU  */
+	pnc_data.pncl_tcam.add_info_mask &= (~TPM_AI_TO_CPU_MASK);
+
+	/*** Build SRAM Entry ***/
+
+	/* Lookup not done, it is not to CPU */
+	pnc_data.pncl_sram.sram_updt_bm &= (~TPM_PNCL_SET_LUD);
+
+	/* Packet=not_fragmented */
+	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_IPV4_NFRAG;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV4_FRAG, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/***********************************************************/
+	/* Create Non-CPU Frag packets                            */
+	/***********************************************************/
+	NO_FREE_ENTRIES();
+
+	/* Don't check fragmented */
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+
+	/*** Build SRAM Entry ***/
+
+	/* Packet=fragmented */
+	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_IPV4_FRAG;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV4_FRAG, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_tcp_flag_init()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_tcp_flag_init(void)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries, tcp_flag_lu, ttl_lu, pnc_entry;
+	int32_t cpu_rx_queue;
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "\n");
+
+	/* Get default CPU Rx queue */
+	tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+
+	/* Get Next Range TTL Info */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_TTL, &range_data);
+	if (int_ret_code != TPM_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " To create TCP Flag range, TPM_PNC_TTL range must exist \n");
+		return(int_ret_code);
+	}
+	ttl_lu = range_data.pnc_range_conf.base_lu_id;
+
+	/* Get TCP_FLAG Range Info */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_TCP_FLAG, &range_data);
+	IF_ERROR(int_ret_code);
+	tcp_flag_lu = range_data.pnc_range_conf.base_lu_id;
+
+	/* Set common TCAM params */
+	pnc_data.pncl_tcam.lu_id = tcp_flag_lu;
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_TCP_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.tcp_subf = TPM_PARSE_L4_SRC;
+
+	/* Set common SRAM params */
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_TCP_OFFSET;
+	pnc_data.pncl_sram.next_offset.offset_sub.tcp_subf = TPM_PARSE_TCPFLAGS;
+	pnc_data.pncl_sram.pnc_queue = cpu_rx_queue;
+	pnc_data.pncl_sram.next_lu_id = ttl_lu;
+	pnc_data.pncl_sram.next_lu_off_reg = TPM_PNC_LU_REG0;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Get pnc_range tcam_start_entry, and number of free entries */
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_start;
+
+	/********************/
+	/* Create FIN FLAG=1 */
+	/*******************/
+	NO_FREE_ENTRIES();
+	/* Build PnC Entry */
+	/* Double check - only check packets that are MTM */
+	pnc_data.pncl_tcam.add_info_data |= (1 << TPM_AI_MTM_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask |= TPM_AI_MTM_MASK;
+
+	pnc_data.pncl_tcam.tcp_parse_bm = TPM_PARSE_TCPFLAGS;
+	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags = TPM_TCP_FIN;
+	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags_mask = TPM_TCP_FIN;
+
+	/* Build SRAM Entry */
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_TXP;
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+
+	/* Signal the packet is going to CPU */
+	pnc_data.pncl_sram.add_info_data |= (1 << TPM_AI_TO_CPU_BIT_OFF);
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TO_CPU_MASK;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TCP_FLAG, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/********************/
+	/* Create RES FLAG=1 */
+	/********************/
+	NO_FREE_ENTRIES();
+	/* Build PnC Entry (similar to previous entry */
+	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags = TPM_TCP_RES;
+	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags_mask = TPM_TCP_RES;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TCP_FLAG, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/***************/
+	/* All Others  */
+	/***************/
+	NO_FREE_ENTRIES();
+
+	/* Build TCAM Entry */
+	pnc_data.pncl_tcam.add_info_data = 0;
+	pnc_data.pncl_tcam.add_info_mask = 0;
+	pnc_data.pncl_tcam.tcp_parse_bm = 0;
+	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags = 0;
+	pnc_data.pncl_tcam.pkt_key.tcp_key.tcp_flags_mask = 0;
+
+	/* Build SRAM Entry */
+	pnc_data.pncl_sram.sram_updt_bm = 0;
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TCP_FLAG, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_virt_uni_init()
+*
+* DESCRIPTION:
+* The function is responsible for adding a new entry in the PNC range of TPM_PNC_VIRT_UNI.
+* The entry is added in case the xml parameters are defining this entry - even though the
+* wifi_virt_uni_enable feature is disabled.
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_virt_uni_init(void)
+{
+
+	int32_t int_ret_code;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_db_pnc_range_t range_data;
+	uint32_t free_entries, pnc_entry;
+	tpm_init_virt_uni_t virt_uni;
+	tpm_db_gmac_func_t g_func;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " WiFi entry \n");
+
+
+	/* TODO: Currently hardcoded to G1 */
+	tpm_db_gmac_func_get(TPM_ENUM_GMAC_1, &g_func);
+
+	if (g_func != TPM_GMAC_FUNC_VIRT_UNI) {
+		return(TPM_OK);
+	}
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_VIRT_UNI, &range_data);
+	IF_ERROR(int_ret_code);
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry =
+	range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_start +
+	(range_data.pnc_range_conf.range_size - 1);
+
+	tpm_db_virt_info_get(&virt_uni);
+
+	/* Build PnC Entry */
+	pnc_data.pncl_tcam.lu_id = range_data.pnc_range_conf.base_lu_id;
+	pnc_data.pncl_tcam.port_ids = gmac_pnc_bm[TPM_ENUM_GMAC_1];
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
+
+	if (virt_uni.enabled == 1) {
+		NO_FREE_ENTRIES();
+
+		/* Build SRAM Entry */
+		pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_TXP | TPM_PNCL_SET_LUD;
+		pnc_data.pncl_sram.pnc_queue = 0;	/* hardcoded - send to Q0 to CPU */
+		pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+
+		/* Create Entry in PnC */
+		int_ret_code = tpm_proc_pnc_create(TPM_PNC_VIRT_UNI, pnc_entry, &pnc_data);
+		IF_ERROR(int_ret_code);
+
+		free_entries--;
+		pnc_entry--;
+
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
+			NO_FREE_ENTRIES();
+
+			pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_MAC_DA;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[0] = 0x01;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[0] = 0xff;
+
+			/* Build SRAM Entry */
+			pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD;
+			pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+
+			/* Create Entry in PnC */
+			int_ret_code = tpm_proc_pnc_create(TPM_PNC_VIRT_UNI, pnc_entry, &pnc_data);
+			IF_ERROR(int_ret_code);
+
+			free_entries--;
+			pnc_entry--;
+
+			NO_FREE_ENTRIES();
+
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[0] = 0x33;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[0] = 0xff;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[1] = 0x33;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[1] = 0xff;
+
+			/* Create Entry in PnC */
+			int_ret_code = tpm_proc_pnc_create(TPM_PNC_VIRT_UNI, pnc_entry, &pnc_data);
+			IF_ERROR(int_ret_code);
+
+			free_entries--;
+			pnc_entry--;
+
+			NO_FREE_ENTRIES();
+
+			pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_MAC_DA;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[0] = 0x01;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[1] = 0x00;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[2] = 0x5e;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[3] = 0x00;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[4] = 0x00;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[5] = 0x01;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[0] = 0xff;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[1] = 0xff;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[2] = 0xff;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[3] = 0xff;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[4] = 0xff;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da_mask[5] = 0xff;
+
+			/* Build SRAM Entry */
+			pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_TXP | TPM_PNCL_SET_LUD;
+			pnc_data.pncl_sram.pnc_queue = 1;	/* hardcoded - send to Q1 to CPU */
+			pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+
+			/* Create Entry in PnC */
+			int_ret_code = tpm_proc_pnc_create(TPM_PNC_VIRT_UNI, pnc_entry, &pnc_data);
+			IF_ERROR(int_ret_code);
+
+			free_entries--;
+			pnc_entry--;
+
+			NO_FREE_ENTRIES();
+
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[0] = 0x33;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[1] = 0x33;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[2] = 0x00;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[3] = 0x00;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[4] = 0x00;
+			pnc_data.pncl_tcam.pkt_key.l2_key.mac.mac_da[5] = 0x01;
+
+			/* Create Entry in PnC */
+			int_ret_code = tpm_proc_pnc_create(TPM_PNC_VIRT_UNI, pnc_entry, &pnc_data);
+			IF_ERROR(int_ret_code);
+
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ipv4_ttl_init()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_ipv4_ttl_init(uint32_t ttl_illegal_action)
+{
+
+	int32_t int_ret_code;
+	uint32_t free_entries, pnc_entry, ttl_lu, ipv4_proto_lu;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data, nextphase_range_data;
+	int32_t cpu_rx_queue;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&nextphase_range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "ttl_illegal_action(%d)\n", ttl_illegal_action);
+
+	/* Get default CPU Rx queue */
+	tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+
+	/* Get TCP_FLAG Range Info */
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_TTL, &range_data);
+	IF_ERROR(int_ret_code);
+	ttl_lu = range_data.pnc_range_conf.base_lu_id;
+
+	/* Get Next Range IPV4_PROTO LU_ID */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_PROTO, &nextphase_range_data);
+	IF_ERROR(int_ret_code);
+	ipv4_proto_lu = nextphase_range_data.pnc_range_conf.base_lu_id;
+
+	/* Get pnc_range tcam_start_entry, and number of free entries */
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start;
+
+	/* Set common TCAM params */
+	pnc_data.pncl_tcam.lu_id = ttl_lu;
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER;
+	pnc_data.pncl_tcam.pkt_key.ipv4_add_key.ipv4_ttl = 0;
+
+	/* Set common SRAM params */
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_IPv4_PARSE_VER;
+	pnc_data.pncl_sram.next_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.next_lu_id = ipv4_proto_lu;
+
+	/******************/
+	/* Create TTL=0   */
+	/******************/
+	/* Parse the TTL */
+	pnc_data.pncl_tcam.ipv4_parse_bm = TPM_IPv4_PARSE_TTL;
+
+	/* Double check - check only packets that are MTM */
+	pnc_data.pncl_tcam.add_info_data = (1 << TPM_AI_MTM_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_MTM_MASK;
+
+	/* Packet forwarded to CPU */
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_TXP;
+	pnc_data.pncl_sram.pnc_queue = cpu_rx_queue;
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+
+	/* or packet is dropped */
+	if (TPM_TTL_ZERO_ACTION_DROP == ttl_illegal_action)
+		pnc_data.pncl_sram.sram_updt_bm |= TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD;
+
+	/* Signal the packet is going to CPU */
+	pnc_data.pncl_sram.add_info_data |= (1 << TPM_AI_TO_CPU_BIT_OFF);
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TO_CPU_MASK;
+
+	NO_FREE_ENTRIES();
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TTL, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/******************/
+	/* Create TTL=1   */
+	/******************/
+	NO_FREE_ENTRIES();
+	/* Build PnC Entry, see TTL=0 */
+	pnc_data.pncl_tcam.pkt_key.ipv4_add_key.ipv4_ttl = 1;
+
+	/* Build SRAM Entry, see TTL=0,
+	   but always send to CPU, don't drop */
+	pnc_data.pncl_sram.sram_updt_bm &= (~(TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD));
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TTL, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/********************/
+	/* Create TTL>1     */
+	/********************/
+	/* All packets */
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+
+	/* Don't update anything (next_lu_id same as previous) */
+	pnc_data.pncl_sram.sram_updt_bm = 0;
+	pnc_data.pncl_sram.add_info_data = 0;
+	pnc_data.pncl_sram.add_info_mask = 0;
+
+	NO_FREE_ENTRIES();
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_TTL, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ipv4_igmp_init()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_ipv4_igmp_init(void)
+{
+	tpm_error_code_t ret_code = TPM_RC_OK;
+	uint32_t mode;
+	uint32_t cpu_queue;
+	tpm_src_port_type_t src_port;
+
+	/*set cpu queue */
+	tpm_db_igmp_get_cpu_queue(&cpu_queue);
+	tpm_set_igmp_cpu_rx_queue(cpu_queue);
+
+	/*set igmp packet forward mode */
+	for (src_port = TPM_SRC_PORT_UNI_0; src_port <= TPM_SRC_PORT_UNI_7; src_port++) {
+		if (tpm_db_eth_port_switch_port_get(src_port) == TPM_DB_ERR_PORT_NUM)
+       		continue;
+
+		tpm_db_igmp_get_port_frwd_mode(src_port, &mode);
+		ret_code = tpm_proc_add_uni_port_igmp_rule(src_port, mode);
+		IF_ERROR(ret_code);
+	}
+
+	tpm_db_igmp_get_port_frwd_mode(TPM_SRC_PORT_WAN, &mode);
+	ret_code = tpm_proc_add_wan_port_igmp_rule(mode);
+	IF_ERROR(ret_code);
+
+	return ret_code;
+}
+
+/*******************************************************************************
+* tpm_proc_mib_reset()
+*
+* DESCRIPTION:      Performs MIB reset
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_mib_reset(uint32_t owner_id, tpm_reset_level_enum_t reset_level)
+{
+	int32_t int_ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "\n");
+
+	if (reset_level > TPM_ENUM_MAX_RESET_LEVEL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Illegal reset_level (%d) \n", reset_level);
+		return(ERR_GENERAL);
+	}
+	/* Init CPU WAN loopback DB */
+	int_ret_code = tpm_proc_init_cpu_wan_loopback();
+
+	/* Init Multicast DB */
+	int_ret_code = tpm_proc_multicast_reset();
+	IF_ERROR(int_ret_code);
+
+	/* Init PnC Ranges in DB */
+	int_ret_code = tpm_init_pncranges_set(reset_level);
+	IF_ERROR(int_ret_code);
+
+	/* Init API Ranges in DB */
+	int_ret_code = tpm_init_api_rng_init_all();
+	IF_ERROR(int_ret_code);
+
+	/* Init IPV6 5t flows */
+	int_ret_code = tpm_db_init_ipv6_5t_flow_reset();
+	IF_ERROR(int_ret_code);
+
+	/* Init CnM DB */
+	int_ret_code = tpm_db_ctc_cm_db_reset();
+	IF_ERROR(int_ret_code);
+
+	/* Init IPv6 MC SIP db */
+	tpm_db_ipv6_mc_sip_db_reset();
+
+	/* Init Hardware */
+	int_ret_code = tpm_init_system_mib_reset(reset_level);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_int_del_acl_rule(tpm_api_sections_t api_section, uint32_t owner_id, uint32_t rule_idx)
+{
+
+	int32_t ret_code;
+	uint32_t rule_num, dummy_idx, bi_dir, api_rng_entries;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+	tpm_db_pnc_conn_t pnc_con;
+	tpm_db_pnc_range_conf_t rangConf;
+	tpm_pnc_ranges_t range_id = 0;
+
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+	memset(&api_data, 0, sizeof(tpm_rule_entry_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " api_section(%d) owner(%d) rule_idx (%d)", api_section, owner_id, rule_idx);
+
+	/* Get Range_Id */
+	ret_code = tpm_db_api_section_main_pnc_get(api_section, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Get the rule_num */
+	ret_code = tpm_db_api_rulenum_get(api_section, rule_idx, &rule_num);
+	if (ret_code == TPM_DB_ERR_REC_NOT_EXIST) {
+		TPM_OS_ERROR(TPM_DB_MOD, " The rule non-exist!\n");
+		return ERR_RULE_IDX_INVALID;
+	}
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "with rule_num(%d)\n", rule_num);
+	/*IF_ERROR(ret_code);*/
+
+	ret_code = tpm_db_api_entry_get(api_section, rule_num, &dummy_idx, &bi_dir, &api_data, &mod_con, &pnc_con);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_api_section_num_entries_get(api_section, &api_rng_entries);
+	IF_ERROR(ret_code);
+
+	/* Delete PNC Entry */
+	ret_code = tpm_proc_pnc_con_del(&pnc_con);
+	IF_ERROR(ret_code);
+
+	/* Release related modification entry  (Important, after deleting PNC Entries) */
+	if (mod_con.mod_cmd_mac != TPM_INVALID_GMAC) {
+		/* handle split mod */
+		ret_code = tpm_mod2_split_mod_try_pmt_entry_del(api_section, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
+		if (TPM_OK != ret_code) {
+			/* this is not split mod entry, remove it */
+			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
+		}
+	}
+	IF_ERROR(ret_code);
+
+	/* Delete API Rule Entry */
+	ret_code = tpm_db_api_entry_invalidate(api_section, rule_num);
+	IF_ERROR(ret_code);
+
+	if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+		/* Decrease rule_numbers and PnC entries of the existing API entries that were "pulled up" */
+		ret_code = tpm_proc_api_entry_rulenum_dec(api_section, (rule_num + 1), (api_rng_entries - 1));
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_acl_rule(tpm_api_sections_t api_section, uint32_t owner_id, uint32_t rule_idx, uint32_t busy_check)
+{
+	tpm_error_code_t ret_code, busy_ret_code = TPM_RC_OK;
+	tpm_api_type_t api_type;
+
+	/* Check API_type Busy */
+	if (busy_check) {
+		ret_code = tpm_db_api_type_get_from_api_section(api_section, &api_type);
+		IF_ERROR(ret_code);
+		ret_code = tpm_proc_check_api_busy(api_type, rule_idx);
+		IF_ERROR(ret_code);
+	}
+
+	ret_code = tpm_proc_int_del_acl_rule(api_section, owner_id, rule_idx);
+
+	/* Free API_type */
+	if (busy_check)
+		busy_ret_code = tpm_proc_api_busy_done(api_type, rule_idx);
+
+	IF_ERROR(ret_code);
+	IF_ERROR(busy_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+
+/*******************************************************************************
+* tpm_add_ipv4_acl_rule()
+*
+* DESCRIPTION:      Creates a new IPv4 processing ACL.
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_ipv4_acl_rule(uint32_t owner_id,
+					    tpm_src_port_type_t src_port,
+					    uint32_t rule_num,
+					    uint32_t *rule_idx,
+					    tpm_parse_fields_t parse_rule_bm,
+					    tpm_parse_flags_t parse_flags_bm,
+					    tpm_ipv4_acl_key_t *ipv4_key,
+					    tpm_pkt_frwd_t *pkt_frwd,
+					    tpm_pkt_mod_t *pkt_mod,
+					    tpm_pkt_mod_bm_t pkt_mod_bm,
+					    tpm_rule_action_t *rule_action)
+{
+
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code, int_mod_bm;
+	tpm_gmacs_enum_t trg_gmac;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0, bi_dir = 0, update_sram_only = 0;
+	tpm_dir_t dir = 0;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	tpm_db_pnc_range_conf_t rangConf;
+	tpm_api_lu_conf_t lu_conf;
+	tpm_trg_port_type_t trg_port;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d)\n", owner_id, src_port, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv4_check(owner_id, src_port, rule_num, parse_rule_bm, parse_flags_bm,
+					   ipv4_key, pkt_frwd, pkt_mod, rule_action, pkt_mod_bm);
+	IF_ERROR(ret_code);
+
+	/* Get direction */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	ret_code = tpm_db_api_section_main_pnc_get(TPM_IPV4_ACL, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Only do it in table mode */
+	if (TPM_RANGE_TYPE_TABLE == rangConf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_IPV4_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d) already exists\n",
+				     owner_id, src_port, rule_num);
+
+			/* TCAM Key and modification info are not changed, only update SRAM */
+			if ((0 == memcmp(ipv4_key, &api_data.ipv4_key.ipv4_key, sizeof(tpm_ipv4_acl_key_t)))
+			    && (src_port == api_data.ipv4_key.src_port)
+			    && (parse_rule_bm == api_data.ipv4_key.parse_rule_bm)
+			    && (parse_flags_bm == api_data.ipv4_key.parse_flags_bm)
+			    && (SET_MOD(rule_action->pkt_act) == SET_MOD(api_data.ipv4_key.rule_action.pkt_act))
+			    && (SET_UDP_CHKSUM_CALC(rule_action->pkt_act) == \
+					SET_UDP_CHKSUM_CALC(api_data.ipv4_key.rule_action.pkt_act))) {
+				/* No modification */
+					if (!SET_MOD(rule_action->pkt_act))
+						update_sram_only = 1;
+				/* There are modification, then check furthur */
+					else if ((pkt_mod_bm == api_data.ipv4_key.pkt_mod_bm)
+						 && (0 == memcmp(pkt_mod, &api_data.ipv4_key.pkt_mod, sizeof(tpm_pkt_mod_t)))) {
+						update_sram_only = 1;
+						mod_entry = mod_con.mod_cmd_ind;
+						trg_gmac = mod_con.mod_cmd_mac;
+					}
+				}
+
+			/* TCAM Key or modification info is changed */
+			if (!update_sram_only) {
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD,
+					     " owner(%d) src_port(%d), rule_num(%d) TCAM key/modification changed\n",
+					     owner_id, src_port, rule_num);
+
+				tpm_proc_del_ipv4_acl_rule(owner_id, rule_num, TPM_INT_CALL);
+				IF_ERROR(ret_code);
+			}
+		}
+	}
+
+	if (!update_sram_only) {
+		/* if split mod stage-2 */
+		if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+			VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op &&
+			(pkt_mod_bm == TPM_VLAN_MOD)) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod stage-2\n");
+
+			/* in this case, trgt port should be set in L2 stage, IPv4 only perform pbit mod,
+			   so here src port is used for get DS or US info, which tells the Dst GMAC.
+			 */
+			if (SET_TARGET_PORT(rule_action->pkt_act))
+				trg_port = pkt_frwd->trg_port;
+			else if (FROM_LAN(src_port))
+				trg_port = TPM_TRG_PORT_WAN;
+			else
+				trg_port = TPM_TRG_PORT_UNI_ANY;
+
+			if (tpm_proc_trg_port_gmac_map(trg_port, &trg_gmac)) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+				return(ERR_MOD_INVALID);
+			} else if (trg_gmac == TPM_INVALID_GMAC) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+				return(ERR_MOD_INVALID);
+			}
+
+			/* get mod index from p-bit value */
+			int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pkt_mod->vlan_mod.vlan1_out.pbit, &mod_entry);
+			if (TPM_DB_OK != int_ret_code) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-2, illeagal p-bit value: %d\n",
+					pkt_mod->vlan_mod.vlan1_out.pbit);
+				return ERR_MOD_INVALID;
+			}
+
+			/* the first PMT is for p-bit AS-IS */
+			mod_entry++;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+		} else {
+			/* Check if UDP or TCP or nothing */
+			int_mod_bm = 0;
+			if (parse_rule_bm & TPM_IPv4_PARSE_PROTO) {
+				if (ipv4_key->ipv4_proto == IPPROTO_TCP)
+					int_mod_bm = TPM_INT_L4_TCP;
+				else if (ipv4_key->ipv4_proto == IPPROTO_UDP) {
+					int_mod_bm = TPM_INT_L4_UDP;
+					/* Set internal_bm according to API Action */
+					if (rule_action->pkt_act & TPM_ACTION_UDP_CHKSUM_CALC)
+						int_mod_bm = TPM_INT_L4_UDP | TPM_INT_UDP_CHECKSUM;
+				}
+			}
+			ret_code =
+			tpm_proc_create_mod(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm, int_mod_bm,
+					    &mod_entry, &trg_gmac);
+			IF_ERROR(ret_code);
+		}
+	}
+
+
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ipv4_tcam_build(src_port, dir, rule_num, ipv4_key, parse_rule_bm,
+					parse_flags_bm, rule_action, pkt_mod, pkt_mod_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code =  tpm_proc_ipv4_sram_build(src_port, dir, rule_num, pon_type, ipv4_key,
+						 pnc_data.pncl_tcam.ipv4_parse_bm, parse_flags_bm,
+						 pkt_frwd, rule_action, mod_entry, pkt_mod_bm, pkt_mod, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+		/*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_IPV4_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_IPV4_ACL, rule_num, update_sram_only, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+	if (!update_sram_only) {
+		/* Set API data */
+		api_data.ipv4_key.src_port = src_port;
+		api_data.ipv4_key.parse_rule_bm = parse_rule_bm;
+		api_data.ipv4_key.parse_flags_bm = parse_flags_bm;
+		api_data.ipv4_key.pkt_mod_bm = pkt_mod_bm;
+		memcpy(&(api_data.ipv4_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+		if (ipv4_key)
+			memcpy(&(api_data.ipv4_key.ipv4_key), ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+
+		if (pkt_frwd != NULL)
+			memcpy(&(api_data.ipv4_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+		else
+			memset(&(api_data.ipv4_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+		if (pkt_mod != NULL)
+			memcpy(&(api_data.ipv4_key.pkt_mod), pkt_mod, sizeof(tpm_pkt_mod_t));
+		else
+			memset(&(api_data.ipv4_key.pkt_mod), 0, sizeof(tpm_pkt_mod_t));
+
+		/* Set modification data */
+		tpm_proc_set_api_moddata(rule_action->pkt_act, trg_gmac, &mod_con, mod_entry);
+
+		/* Set Pnc Connection data */
+		pnc_conn.num_pnc_ranges = 1;
+		pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+		pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+		if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+			/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+			if (rule_num < api_rng_entries) {
+				int_ret_code =
+				tpm_proc_api_entry_rulenum_inc(TPM_IPV4_ACL, rule_num, (api_rng_entries - 1));
+				IF_ERROR(int_ret_code);
+			}
+		}
+
+		/* Set new API Entry */
+		int_ret_code = tpm_db_api_entry_set(TPM_IPV4_ACL, rule_num, 0 /*bi_dir */ ,
+						    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+		IF_ERROR(int_ret_code);
+
+		/* Return Output */
+		*rule_idx = l_rule_idx;
+	} else {
+		if (pkt_frwd != NULL)
+			memcpy(&(api_data.ipv4_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+		else
+			memset(&(api_data.ipv4_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+		int_ret_code = tpm_db_api_entry_invalidate(TPM_IPV4_ACL, rule_num);
+		IF_ERROR(int_ret_code);
+
+		/* Set new API Entry */
+		int_ret_code = tpm_db_api_entry_set(TPM_IPV4_ACL, rule_num, 0 /*bi_dir */ ,
+						    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+		IF_ERROR(int_ret_code);
+
+		/* Return Output */
+		*rule_idx = l_rule_idx;
+	}
+
+	/* Set aging counter group nunmber and mask */
+	int_ret_code = tpm_db_pnc_get_lu_conf(TPM_PNC_IPV4_MAIN, &lu_conf);
+	IF_ERROR(int_ret_code);
+	tpm_tcam_set_lu_mask(pnc_conn.pnc_conn_tbl[0].pnc_index, (int32_t) lu_conf.lu_mask);
+	tpm_tcam_set_cntr_group(pnc_conn.pnc_conn_tbl[0].pnc_index, (int32_t) lu_conf.cntr_grp);
+
+	return(TPM_RC_OK);
+
+}
+
+/*******************************************************************************
+* tpm_del_ipv4_acl_rule()
+*
+* DESCRIPTION:      Delete a  IPv4 processing ACL.
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_ipv4_acl_rule(uint32_t owner_id, uint32_t rule_idx, uint32_t ext_call)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	ret_code = tpm_proc_del_acl_rule(TPM_IPV4_ACL, owner_id, rule_idx, ext_call);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_check_dst_uni_port()
+*
+* DESCRIPTION:    The function checks Dst port params.
+*
+* INPUTS:
+* dest_port_bm     -
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_check_dst_uni_port(tpm_trg_port_type_t dest_port_bm)
+{
+	uint32_t dst_port;
+	tpm_src_port_type_t src_port;
+	tpm_init_virt_uni_t virt_uni_info;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "dest_port_bm(0x%x)\n", dest_port_bm);
+
+	for (dst_port = TPM_TRG_UNI_0, src_port = TPM_SRC_PORT_UNI_0;
+	     dst_port <= TPM_TRG_UNI_7;
+	     dst_port = (dst_port << 1), src_port += 1) {
+
+		if(0 == (dest_port_bm & dst_port))
+			continue;
+
+		/* if port is valid */
+		if(!tpm_db_eth_port_valid(src_port)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "dest_port(0x%x) is not valid\n", dst_port);
+			return ERR_MC_DST_PORT_INVALID;
+		}
+	}
+
+	/* check vir uni */
+	tpm_db_virt_info_get(&virt_uni_info);
+	if (    (TPM_VIRT_UNI_DISABLED == virt_uni_info.enabled)
+	     && (dest_port_bm & TPM_TRG_UNI_VIRT)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "TPM_TRG_UNI_VIRT is not enabled\n");
+		return ERR_MC_DST_PORT_INVALID;
+	}
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_add_ipv4_mc_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_proc_add_ipv4_mc_stream params.
+*
+* INPUTS:
+* owner_id         - See tpm_proc_add_ipv4_mc_stream
+* stream_num       - See tpm_proc_add_ipv4_mc_stream
+* vid              - See tpm_proc_add_ipv4_mc_stream
+* ipv4_src_add     - See tpm_proc_add_ipv4_mc_stream
+* ipv4_dst_add     - See tpm_proc_add_ipv4_mc_stream
+* ignore_ipv4_src  - See tpm_proc_add_ipv4_mc_stream
+* dest_port_bm     - See tpm_proc_add_ipv4_mc_stream
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_ipv4_mc_check(uint32_t owner_id,
+					    uint32_t stream_num,
+					    tpm_mc_igmp_mode_t igmp_mode,
+					    uint8_t mc_stream_pppoe,
+					    uint16_t vid,
+					    uint8_t ipv4_src_add[4],
+					    uint8_t ipv4_dst_add[4],
+					    uint8_t ignore_ipv4_src,
+					    tpm_trg_port_type_t dest_port_bm,
+					    tpm_mc_filter_mode_t filter_mode)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code, index;
+	tpm_db_pnc_range_t range_data;
+	uint32_t ai_bit;
+	tpm_init_virt_uni_t virt_uni;
+	uint32_t pnc_rng_free_size;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	ret_code = tpm_owner_id_check(TPM_API_IPV4_MC, owner_id);
+	IF_ERROR(ret_code);
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_MC_DS, &range_data);
+	IF_ERROR(int_ret_code);
+
+	if (stream_num >= range_data.pnc_range_conf.range_size)
+		IF_ERROR(ERR_MC_STREAM_INVALID);
+
+	ret_code = tpm_proc_check_dst_uni_port(dest_port_bm);
+	IF_ERROR(ret_code);
+
+	/*check virt range size if necessary*/
+	if(filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0 && (dest_port_bm & TPM_TRG_UNI_VIRT) != 0) {
+			ret_code = tpm_db_pnc_rng_free_ent_get(TPM_PNC_VIRT_UNI, &pnc_rng_free_size);
+			IF_ERROR(ret_code);
+			if(pnc_rng_free_size == 0)
+				IF_ERROR(ERR_OUT_OF_RESOURCES);
+		}
+	}
+
+	/* fix bug of adding 1-2-3 instead of 0-1-2 => when 3 is over-writing the hardcoded entry */
+	if ((stream_num < range_data.pnc_range_conf.api_start) || (stream_num > range_data.pnc_range_conf.api_end))
+		IF_ERROR(ERR_MC_STREAM_INVALID);
+
+	tpm_db_api_entry_ind_get(TPM_IPV4_MC, stream_num, &index);
+	if (-1 != index)
+		IF_ERROR(ERR_MC_STREAM_EXISTS);
+
+	tpm_db_virt_info_get(&virt_uni);
+
+	if (vid == 0xffff) {
+		if (tpm_db_get_mc_filter_mode() == TPM_MC_IP_ONLY_FILTER) {
+			if (virt_uni.enabled) {
+				TPM_OS_WARN(TPM_TPM_LOG_MOD,
+					    " filter mode fall back to MC_COMBINED_MAC_IP_FILTER \r\n");
+			}
+		}
+
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+				    "when mc_per_uni_vlan_xlate is enabled, untagged mcast stream is not supported, "
+				    "and MC VID must be specified \r\n");
+			IF_ERROR(ERR_SW_VID_INVALID);
+		}
+	} else {
+		if (tpm_db_mc_vlan_get_ai_bit(vid, &ai_bit) != TPM_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+				    "MC VID must be configured first \r\n");
+			IF_ERROR(ERR_SW_VID_INVALID);
+		}
+	}
+
+	if (mc_stream_pppoe) {
+		if (tpm_db_get_mc_pppoe_enable() == 0)
+			IF_ERROR(ERR_FEAT_UNSUPPORT);
+
+		if (igmp_mode == TPM_MC_IGMP_SNOOPING && tpm_db_get_mc_per_uni_vlan_xlate())
+			IF_ERROR(ERR_FEAT_UNSUPPORT);
+	}
+
+	if ((ipv4_dst_add[0] < 224) || (ipv4_dst_add[0] > 239))
+		IF_ERROR(ERR_IPV4_MC_DST_IP_INVALID);
+
+	if (dest_port_bm & TPM_TRG_UNI_VIRT) {
+		if (virt_uni.enabled == 0)
+			IF_ERROR(ERR_MC_DST_PORT_INVALID);
+	}
+
+	if (dest_port_bm & TPM_TRG_PORT_CPU) {
+		if (dest_port_bm & (~TPM_TRG_PORT_CPU))
+			IF_ERROR(ERR_MC_DST_PORT_INVALID);
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_ipv4_mc_tcam_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* stream_num          - MC stream number
+* ipv4_src_add        - IPv4 source IP address in network order.
+* ipv4_dst_add        - IPv4 destination IP address in network order.
+* ignore_ipv4_src     - when set to 1 - the IP source is not part of the key.
+* tcam_data           - Logical TCAM Structure
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_ipv4_mc_tcam_build(tpm_mc_filter_mode_t filter_mode,
+				    uint32_t stream_num,
+				    uint16_t vid,
+				    uint8_t mc_stream_pppoe,
+				    uint8_t ipv4_src_add[4],
+				    uint8_t ipv4_dst_add[4],
+				    uint8_t ignore_ipv4_src,
+				    tpm_pncl_tcam_data_t *tcam_data)
+{
+	int32_t int_ret_code;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id, ai_bits;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t vid_ai_field;
+	tpm_parse_flags_t parse_flags_bm = 0;
+	long long parse_int_flags_bm = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " stream_num(%d), sip(%02x%02x%02x%02x), dip(%02x%02x%02x%02x), ignore_src(%d)\n",
+		     stream_num, ipv4_src_add[0], ipv4_src_add[1], ipv4_src_add[2], ipv4_src_add[3],
+		     ipv4_dst_add[0], ipv4_dst_add[1], ipv4_dst_add[2], ipv4_dst_add[3], ignore_ipv4_src);
+
+	tcam_data->l2_parse_bm = 0;
+	tcam_data->l3_parse_bm = 0;
+	tcam_data->ipv6_parse_bm = 0;
+	tcam_data->add_info_mask = 0;
+	tcam_data->add_info_data = 0;
+	if (ignore_ipv4_src)
+		tcam_data->ipv4_parse_bm = TPM_IPv4_PARSE_DIP;
+	else
+		tcam_data->ipv4_parse_bm = TPM_IPv4_PARSE_DIP | TPM_IPv4_PARSE_SIP;
+
+	/* src port */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	if (vid != 0xFFFF) {
+		int_ret_code = tpm_db_mc_vlan_get_ai_bit(vid, &ai_bits);
+		IF_ERROR(int_ret_code);
+
+		vid_ai_field.mc_vid_entry = ai_bits;
+
+		parse_int_flags_bm |= TPM_PARSE_FLAG_MC_VID_TRUE;
+		parse_int_flags_bm |= TPM_PARSE_FLAG_MC_VID_PARSE;
+	} else
+		parse_int_flags_bm |= TPM_PARSE_FLAG_MC_VID_FALSE;
+
+	if (mc_stream_pppoe)
+		parse_flags_bm |= TPM_PARSE_FLAG_PPPOE_TRUE;
+	else
+		parse_flags_bm |= TPM_PARSE_FLAG_PPPOE_FALSE;
+
+	/* Update the AI bits */
+	tpm_proc_parse_flag_ai_tcam_build(&vid_ai_field, parse_flags_bm, parse_int_flags_bm, &(tcam_data->add_info_data),
+					  &(tcam_data->add_info_mask));
+
+	/* Copy in logical PnC Key */
+	if (!ignore_ipv4_src) {
+		memcpy(tcam_data->pkt_key.ipv4_key.ipv4_src_ip_add, ipv4_src_add, sizeof(ipv4_src_add));
+		memset(tcam_data->pkt_key.ipv4_key.ipv4_src_ip_add_mask, 0xff, 4);
+	}
+	memcpy(tcam_data->pkt_key.ipv4_key.ipv4_dst_ip_add, ipv4_dst_add, sizeof(ipv4_dst_add));
+	memset(tcam_data->pkt_key.ipv4_key.ipv4_dst_ip_add_mask, 0xff, 4);
+
+	/* Get PNC Range information */
+	int_ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV4_MC_DS, &lu_id, &start_offset);
+	IF_ERROR(int_ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&tcam_data->start_offset, &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_l2_sram_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* src_port          - packet source port
+* dir               - Packet direction
+* rule_num          - API rule number
+* pon_type          - WAN technology
+* l2_key            - layer2 key data
+* parse_rule_bm     - Parse rules bitmap
+* pkt_frwd          - See xxx
+* rule_action       - See xxx
+*
+* OUTPUTS:
+* l2_sram_data      - Logical SRAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_ipv4_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
+				    tpm_mc_igmp_mode_t igmp_mode,
+				    tpm_trg_port_type_t target_port,
+				    uint32_t mod_entry,
+				    tpm_pncl_sram_data_t *sram_data)
+{
+	tpm_db_mh_src_t ds_mh_src;
+	tpm_init_virt_uni_t virt_uni;
+	tpm_db_pnc_range_conf_t range_conf;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " target_port(%d)\n", target_port);
+
+	/* Update dummy register (offset automatically=zero) */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	sram_data->sram_updt_bm = 0;
+
+	/*Set next lookup */
+	sram_data->next_lu_off_reg = 0;
+	/* For igmp_proxy, check TTL, for igmp_snooping do not */
+	if (igmp_mode == TPM_MC_IGMP_PROXY) {
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_TTL, &range_conf);
+		IF_ERROR(ret_code);
+	} else {
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_PROTO, &range_conf);
+		IF_ERROR(ret_code);
+	}
+	sram_data->next_lu_id = range_conf.base_lu_id;
+
+	/* Set MH */
+	if (tpm_db_get_mc_per_uni_vlan_xlate() == 0) {
+		tpm_db_ds_mh_get_conf_set(&ds_mh_src);
+
+		if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+			if (TPM_MH_SRC_PNC_RI == ds_mh_src) {
+				sram_data->sram_updt_bm |= TPM_PNCL_SET_MH_RI;
+				sram_data->mh_reg.mh_set = TPM_TRUE;
+
+				tpm_db_virt_info_get(&virt_uni);
+				if (virt_uni.enabled)
+					sram_data->mh_reg.mh_reg = (TPM_MH_RI_BIT16 | TPM_MH_RI_BIT15);
+				else
+					sram_data->mh_reg.mh_reg = (TPM_MH_RI_BIT17 | TPM_MH_RI_BIT16 |
+								    TPM_MH_RI_BIT15 | TPM_MH_RI_BIT14);
+			} else {
+				sram_data->mh_reg.mh_set = TPM_FALSE;
+				sram_data->mh_reg.mh_reg = 0;
+			}
+		} else if (filter_mode == TPM_MC_IP_ONLY_FILTER) {
+			/* Target UNI is set by Modification Entry */
+		}
+	} else {
+		/* Target UNI is set by Modification Entry */
+	}
+
+	/* Set modification command */
+	if (mod_entry != 0) {
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_entry;
+	}
+
+	/* Reset AI bits for following LU */
+	sram_data->add_info_data = 0;
+	sram_data->add_info_mask = (TPM_AI_MC_VID_MASK | TPM_AI_MC_VID_VALID_MASK);
+	if (TPM_MC_IGMP_PROXY == igmp_mode) {
+	/* set MTM AI since in proxy mode */
+		sram_data->add_info_data |= (1 << TPM_AI_MTM_BIT_OFF);
+		sram_data->add_info_mask |= TPM_AI_MTM_MASK;
+	}
+
+	/* Final Fragment and L4 is detremined in separate stage */
+	sram_data->l3_type = TPM_PNCL_L3_IPV4_NFRAG;
+	sram_data->l4_type = TPM_PNCL_L4_OTHER;
+
+	/* Set Target Port */
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
+	if (target_port == TPM_TRG_PORT_CPU) {
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+		sram_data->pnc_queue = tpm_db_get_mc_cpu_queue();
+	} else {
+		tpm_pnc_trg_t pnc_target;
+		ret_code = tpm_db_to_lan_gmac_get(target_port, &pnc_target);
+		IF_ERROR(ret_code);
+		sram_data->flow_id_sub.pnc_target = pnc_target;
+		sram_data->pnc_queue = tpm_db_get_mc_hwf_queue();
+	}
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_create_ipv4_mc_mod(tpm_mc_filter_mode_t filter_mode,
+				    tpm_mc_igmp_mode_t igmp_mode,
+				    uint8_t mc_stream_pppoe,
+				    uint16_t vid,
+				    uint8_t *group_addr,
+				    uint32_t dest_port_bm,
+				    uint32_t *mod_entry)
+{
+	int32_t ret_code;
+	tpm_pkt_mod_bm_t pkt_mod_bm = 0;
+	tpm_pkt_mod_t pkt_mod;
+	uint8_t mc_mac[6];
+	uint32_t lpbk_port_bm = 0, entry_id;
+	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
+	uint8_t valid;
+	uint32_t mh_en;
+	uint32_t switch_init;
+	/*struct net_device *dev = NULL;*/
+
+	memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
+
+	/*get MH EN */
+	ret_code = tpm_db_gmac_mh_en_conf_get(TPM_ENUM_GMAC_0, &mh_en);
+	IF_ERROR(ret_code);
+
+	/*get switch init*/
+	ret_code = tpm_db_switch_init_get(&switch_init);
+	IF_ERROR(ret_code);
+
+	if (filter_mode == TPM_MC_IP_ONLY_FILTER && mh_en) {
+		/* TODO: Check virt_port status. If it is not enabled, set target_port via MH_Tx_reg in RI. */
+		pkt_mod_bm |= TPM_MH_SET;
+		pkt_mod.mh_mod = tpm_db_trg_port_switch_port_get(dest_port_bm);
+	}
+
+	if (tpm_db_get_mc_per_uni_vlan_xlate() == 0) {
+		if (vid != 0xffff) {
+			if (tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg) == TPM_OK) {
+				for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
+					if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSLATE) {
+						pkt_mod_bm |= TPM_VLAN_MOD;
+
+						pkt_mod.vlan_mod.vlan_op = VLANOP_EXT_TAG_MOD;
+						pkt_mod.vlan_mod.vlan1_out.tpid = 0x8100;
+						pkt_mod.vlan_mod.vlan1_out.pbit = 0;
+						pkt_mod.vlan_mod.vlan1_out.pbit_mask = 0x0;
+						pkt_mod.vlan_mod.vlan1_out.cfi = 0;
+						pkt_mod.vlan_mod.vlan1_out.cfi_mask = 0x0;
+						pkt_mod.vlan_mod.vlan1_out.vid = mc_vid_cfg[entry_id].uni_port_vid;
+						pkt_mod.vlan_mod.vlan1_out.vid_mask = 0xffff;
+						break;
+					} else if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP) {
+						/* Just for MC, no switch */
+						if (switch_init == 0) {
+							pkt_mod_bm |= TPM_VLAN_MOD;
+
+							pkt_mod.vlan_mod.vlan_op = VLANOP_EXT_TAG_DEL;
+							break;
+						}
+					}
+				}
+			} else
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " not found mv_vlan_cfg %d, assume as transparent! \n", vid);
+		}
+	} else if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		pkt_mod_bm |= TPM_MH_SET;
+
+		ret_code = tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg);
+		IF_ERROR(ret_code);
+
+		for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
+			if (mc_vid_cfg[entry_id].tpm_src_port != TPM_SRC_PORT_UNI_VIRT) {
+				if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSPARENT ||
+				    mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP) {
+					lpbk_port_bm |=
+					TPM_TRG_UNI_0 << (mc_vid_cfg[entry_id].tpm_src_port - TPM_SRC_PORT_UNI_0);
+				}
+			}
+		}
+		lpbk_port_bm |= TPM_TRG_UNI_VIRT;
+
+		pkt_mod.mh_mod = tpm_db_trg_port_switch_port_get(lpbk_port_bm);
+	}
+
+	if (igmp_mode == TPM_MC_IGMP_PROXY) {
+#if 0
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+		dev = dev_get_by_name("eth0");
+#else
+		dev = dev_get_by_name(&init_net, "eth0");
+#endif
+		if (dev == NULL)
+			IF_ERROR(ERR_GENERAL);
+
+		pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+		pkt_mod.mac_mod.mac_sa[0] = ((uint8_t *) dev->dev_addr)[0];
+		pkt_mod.mac_mod.mac_sa[1] = ((uint8_t *) dev->dev_addr)[1];
+		pkt_mod.mac_mod.mac_sa[2] = ((uint8_t *) dev->dev_addr)[2];
+		pkt_mod.mac_mod.mac_sa[3] = ((uint8_t *) dev->dev_addr)[3];
+		pkt_mod.mac_mod.mac_sa[4] = ((uint8_t *) dev->dev_addr)[4];
+		pkt_mod.mac_mod.mac_sa[5] = ((uint8_t *) dev->dev_addr)[5];
+
+		pkt_mod.mac_mod.mac_sa_mask[0] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[1] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[2] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[3] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[4] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[5] = 0xff;
+#endif
+
+		pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+		tpm_db_get_mc_igmp_proxy_sa_mac(mc_mac, &valid);
+
+		if (valid) {
+			memcpy(pkt_mod.mac_mod.mac_sa, mc_mac, 6 * sizeof(uint8_t));
+			memset(pkt_mod.mac_mod.mac_sa_mask, 0xff, 6 * sizeof(uint8_t));
+		} else
+			IF_ERROR(ERR_GENERAL);
+
+		if (mc_stream_pppoe) {
+			pkt_mod_bm |= (TPM_MAC_DA_SET | TPM_PPPOE_DEL);
+			MULTI_IP_2_MAC(mc_mac, group_addr);
+			memcpy(pkt_mod.mac_mod.mac_da, mc_mac, 6 * sizeof(uint8_t));
+			memset(pkt_mod.mac_mod.mac_da_mask, 0xff, 6 * sizeof(uint8_t));
+		}
+	}
+
+	if (pkt_mod_bm != 0) {
+		ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, pkt_mod_bm, TPM_INT_MC_MOD, &pkt_mod, mod_entry);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_uni_port_igmp_rule()
+*
+* DESCRIPTION:    Create IGMP rule for UNI port.
+*
+* INPUTS:
+* src_port        - uni port to set
+* state           - how to process IGMP packets
+*
+* OUTPUTS:
+*           NONE
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_uni_port_igmp_rule(tpm_src_port_type_t src_port, tpm_igmp_frwd_mode_t mode)
+{
+	int32_t ret_code;
+	tpm_pncl_pnc_full_t igmp_pnc_data;
+	tpm_gmac_bm_t gmac_bm;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_conf_t range_conf;
+	uint32_t cpu_queue;
+	tpm_db_pnc_range_t range_data;
+	uint32_t pnc_entry;
+	int32_t lPort = 0;
+	uint32_t is_switch_port = 1;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, " UNI-%d IGMP Forward Mode -- %d.\r\n", src_port, mode);
+
+	memset(&igmp_pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+
+	/* build TCAM */
+	igmp_pnc_data.pncl_tcam.l2_parse_bm = 0;
+	igmp_pnc_data.pncl_tcam.l3_parse_bm = 0;
+	igmp_pnc_data.pncl_tcam.ipv6_parse_bm = 0;
+	igmp_pnc_data.pncl_tcam.ipv4_parse_bm = TPM_IPv4_PARSE_PROTO;
+
+	if (src_port < TPM_SRC_PORT_UNI_0 || src_port > TPM_SRC_PORT_UNI_VIRT) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " invalid src_port %d\n", src_port);
+		return(ERR_SRC_PORT_INVALID);
+	}
+
+	is_switch_port = tpm_db_src_port_on_switch(src_port);
+
+	if (is_switch_port == 1) {
+		lPort = tpm_db_eth_port_switch_port_get(src_port);
+		if (lPort == TPM_DB_ERR_PORT_NUM) {
+			printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __func__, __LINE__, src_port);
+			return ERR_SRC_PORT_INVALID;
+		}
+
+		igmp_pnc_data.pncl_tcam.add_info_data = ((lPort) << TPM_AI_UNI_BIT_OFF);
+		igmp_pnc_data.pncl_tcam.add_info_mask = AI_TO_MASK(TPM_AI_UNI_BIT_OFF, TPM_AI_UNI_BIT_SIZE);
+	}
+
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	igmp_pnc_data.pncl_tcam.port_ids = gmac_bm;
+	igmp_pnc_data.pncl_tcam.pkt_key.ipv4_key.ipv4_proto = IPPROTO_IGMP;
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IGMP, &range_conf);
+	IF_ERROR(ret_code);
+	igmp_pnc_data.pncl_tcam.lu_id = range_conf.base_lu_id;
+	start_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	start_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER_OR_IHL;
+	memcpy(&igmp_pnc_data.pncl_tcam.start_offset, &start_offset, sizeof(tpm_pncl_offset_t));
+
+	/* build SRAM */
+	igmp_pnc_data.pncl_sram.next_lu_id = 0;
+	igmp_pnc_data.pncl_sram.next_lu_off_reg = 0;
+	igmp_pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	igmp_pnc_data.pncl_sram.next_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER_OR_IHL;
+	igmp_pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	switch (mode) {
+	case TPM_IGMP_FRWD_MODE_DROP:
+		igmp_pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_DISC;
+		break;
+
+	case TPM_IGMP_FRWD_MODE_FORWARD:
+		igmp_pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD;
+		igmp_pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+		break;
+
+	case TPM_IGMP_FRWD_MODE_SNOOPING:
+		tpm_db_igmp_get_cpu_queue(&cpu_queue);
+		igmp_pnc_data.pncl_sram.pnc_queue = cpu_queue;
+		igmp_pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_TXP | TPM_PNCL_SET_IGMP;
+		igmp_pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+		break;
+
+	default:
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " invalid state %d\n", mode);
+		return(ERR_PORT_IGMP_FRWD_MODE_INVALID);
+	}
+
+	igmp_pnc_data.pncl_sram.mh_reg.mh_set = TPM_FALSE;
+	igmp_pnc_data.pncl_sram.mh_reg.mh_reg = 0;
+	igmp_pnc_data.pncl_sram.add_info_data = 0;
+	igmp_pnc_data.pncl_sram.add_info_mask = 0;
+	igmp_pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_IPV4_NFRAG;
+	igmp_pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_OTHER;
+	igmp_pnc_data.pncl_sram.sram_updt_bm |= (TPM_PNCL_SET_L3 | TPM_PNCL_SET_L4);
+	igmp_pnc_data.pncl_sram.flow_id_sub.gem_port = 0;	/* ? */
+	igmp_pnc_data.pncl_sram.flow_id_sub.mod_cmd = 0;
+
+	/* set PNC entry */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_IGMP, &range_data);
+	IF_ERROR(ret_code);
+	/* since WAN port will use the first entry of this range,
+       UNI port must start with the second one.
+	 */
+	pnc_entry = range_data.pnc_range_conf.range_start + src_port - TPM_SRC_PORT_UNI_0 + 1;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_entry(%d)\n", pnc_entry);
+	if (pnc_entry > range_data.pnc_range_conf.range_end) {
+		TPM_OS_ERROR(TPM_INIT_MOD, " IGMP range is not big enough for PNC entry of src_port %d\n", src_port);
+		return(ERR_RULE_NUM_INVALID);
+	}
+
+	ret_code = tpm_pncl_entry_set(pnc_entry, &igmp_pnc_data);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_wan_port_igmp_rule()
+*
+* DESCRIPTION:    Create IGMP rule for PON port.
+*
+* INPUTS:
+* state           - how to process IGMP packets
+*
+* OUTPUTS:
+*           NONE
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_wan_port_igmp_rule(tpm_igmp_frwd_mode_t mode)
+{
+	int32_t ret_code;
+	tpm_pncl_pnc_full_t igmp_pnc_data;
+	tpm_gmac_bm_t gmac_bm;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_conf_t range_conf;
+	uint32_t cpu_queue;
+	tpm_db_pnc_range_t range_data;
+	uint32_t pnc_entry;
+
+	TPM_OS_INFO(TPM_TPM_LOG_MOD, " PON IGMP Forward Mode -- %d.\r\n", mode);
+
+	memset(&igmp_pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+
+	/* build TCAM */
+	igmp_pnc_data.pncl_tcam.l2_parse_bm = 0;
+	igmp_pnc_data.pncl_tcam.l3_parse_bm = 0;
+	igmp_pnc_data.pncl_tcam.ipv6_parse_bm = 0;
+	igmp_pnc_data.pncl_tcam.ipv4_parse_bm = TPM_IPv4_PARSE_PROTO;
+	igmp_pnc_data.pncl_tcam.add_info_mask = 0;
+	igmp_pnc_data.pncl_tcam.add_info_data = 0;
+
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	igmp_pnc_data.pncl_tcam.port_ids = gmac_bm;
+	igmp_pnc_data.pncl_tcam.pkt_key.ipv4_key.ipv4_proto = IPPROTO_IGMP;
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IGMP, &range_conf);
+	IF_ERROR(ret_code);
+	igmp_pnc_data.pncl_tcam.lu_id = range_conf.base_lu_id;
+	start_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	start_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER_OR_IHL;
+	memcpy(&igmp_pnc_data.pncl_tcam.start_offset, &start_offset, sizeof(tpm_pncl_offset_t));
+
+	/* build SRAM */
+	igmp_pnc_data.pncl_sram.next_lu_id = 0;
+	igmp_pnc_data.pncl_sram.next_lu_off_reg = 0;
+	igmp_pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	igmp_pnc_data.pncl_sram.next_offset.offset_sub.ipv4_subf = TPM_IPv4_PARSE_VER_OR_IHL;
+	igmp_pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	switch (mode) {
+	case TPM_IGMP_FRWD_MODE_DROP:
+		igmp_pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_DISC;
+		break;
+
+	case TPM_IGMP_FRWD_MODE_FORWARD:
+		igmp_pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD;
+		igmp_pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+		break;
+
+	case TPM_IGMP_FRWD_MODE_SNOOPING:
+		tpm_db_igmp_get_cpu_queue(&cpu_queue);
+		igmp_pnc_data.pncl_sram.pnc_queue = cpu_queue;
+		igmp_pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_TXP | TPM_PNCL_SET_IGMP;
+		igmp_pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+		break;
+
+	default:
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " invalid state %d\n", mode);
+		return(ERR_PORT_IGMP_FRWD_MODE_INVALID);
+	}
+
+	igmp_pnc_data.pncl_sram.mh_reg.mh_set = TPM_FALSE;
+	igmp_pnc_data.pncl_sram.mh_reg.mh_reg = 0;
+	igmp_pnc_data.pncl_sram.add_info_data = 0;
+	igmp_pnc_data.pncl_sram.add_info_mask = 0;
+	igmp_pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_IPV4_NFRAG;
+	igmp_pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_OTHER;
+	igmp_pnc_data.pncl_sram.sram_updt_bm |= (TPM_PNCL_SET_L3 | TPM_PNCL_SET_L4);
+	igmp_pnc_data.pncl_sram.flow_id_sub.gem_port = 0;	/* ? */
+	igmp_pnc_data.pncl_sram.flow_id_sub.mod_cmd = 0;
+
+	/* set PNC entry */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_IGMP, &range_data);
+	IF_ERROR(ret_code);
+	pnc_entry = range_data.pnc_range_conf.range_start;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_entry(%d)\n", pnc_entry);
+	if (pnc_entry > range_data.pnc_range_conf.range_end) {
+		TPM_OS_ERROR(TPM_INIT_MOD, " IGMP range is not big enough for PNC entry of WAN port\n");
+		return(ERR_RULE_NUM_INVALID);
+	}
+
+	ret_code = tpm_pncl_entry_set(pnc_entry, &igmp_pnc_data);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_del_port_igmp_rule()
+*
+* DESCRIPTION:    Create IGMP rule for PON port.
+*
+* INPUTS:
+* src_port        - port rule to delete
+*
+* OUTPUTS:
+*           NONE
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_port_igmp_rule(tpm_src_port_type_t src_port)
+{
+	int32_t ret_code;
+	tpm_db_pnc_conn_t pnc_con;
+	tpm_db_pnc_range_t range_data;
+
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+
+	if (src_port >= TPM_SRC_PORT_UNI_ANY) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " invalid src_port %d\n", src_port);
+		return(ERR_SRC_PORT_INVALID);
+	}
+
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_IGMP, &range_data);
+	IF_ERROR(ret_code);
+
+	pnc_con.num_pnc_ranges = 1;
+	pnc_con.pnc_conn_tbl[0].pnc_range = TPM_PNC_IGMP;
+	pnc_con.pnc_conn_tbl[0].pnc_index = range_data.pnc_range_conf.range_start + src_port;
+
+	/* set PNC entry */
+	ret_code = tpm_proc_pnc_con_del(&pnc_con);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+int32_t tpm_proc_mc_create_virt_uni_pnc_entry(uint32_t rule_num,
+						uint16_t uni_vid,
+						uint8_t group_addr[16],
+						bool    ipv6_flag)
+{
+	int32_t ret_code;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_l2_acl_key_t l2_key;
+	uint8_t mc_mac[6];
+	uint32_t pnc_entry = 0, pnc_range_start = 0, api_start = 0;
+
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&l2_key, 0, sizeof(tpm_l2_acl_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_VIRT_UNI, &range_conf);
+	IF_ERROR(ret_code);
+	pnc_range_start = range_conf.range_start;
+	api_start = range_conf.api_start;
+
+	if (rule_num >= (range_conf.range_size - 3)) {
+		/* Excludes three default rules:
+		   1. forward all queries to virt_uni
+		   2. discard all other mc streams
+		   3. forward all unicast to virt_uni */
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+	}
+
+	/* Build tcam data */
+	pnc_data.pncl_tcam.lu_id = range_conf.base_lu_id;
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.subf = TPM_L2_PARSE_MH;
+
+	/* Get GMAC(s) */
+	pnc_data.pncl_tcam.port_ids = gmac_pnc_bm[TPM_ENUM_GMAC_1];
+
+	/* Set L2 filter */
+	pnc_data.pncl_tcam.l2_parse_bm = (TPM_L2_PARSE_MH | TPM_L2_PARSE_MAC_DA);
+
+	pnc_data.pncl_tcam.pkt_key.src_port = TPM_SRC_PORT_UNI_VIRT;
+
+	if (ipv6_flag) {
+		MULTI_IPV6_2_MAC(mc_mac, group_addr);
+	}
+	else {
+		MULTI_IP_2_MAC(mc_mac, group_addr);
+	}
+
+	memcpy(&(l2_key.mac.mac_da), mc_mac, 6 * sizeof(uint8_t));
+	memset(&(l2_key.mac.mac_da_mask), 0xff, 6 * sizeof(uint8_t));
+
+	if (uni_vid != 0xffff) {
+		pnc_data.pncl_tcam.l2_parse_bm |= TPM_L2_PARSE_ONE_VLAN_TAG;
+
+		l2_key.vlan1.tpid = 0x8100;
+		l2_key.vlan1.tpid_mask = 0xffff;
+		l2_key.vlan1.pbit = 0;
+		l2_key.vlan1.pbit_mask = 0;
+		l2_key.vlan1.cfi = 0;
+		l2_key.vlan1.cfi_mask = 0;
+		l2_key.vlan1.vid = uni_vid;
+		l2_key.vlan1.vid_mask = 0xffff;
+	}
+
+	/* Copy L2 key */
+	memcpy(&(pnc_data.pncl_tcam.pkt_key.l2_key), &l2_key, sizeof(tpm_l2_acl_key_t));
+
+	/* Build sram data */
+	pnc_data.pncl_sram.sram_updt_bm |= (TPM_PNCL_SET_TXP | TPM_PNCL_SET_LUD | TPM_PNCL_SET_MC);
+
+	/* No next lookup */
+	pnc_data.pncl_sram.next_lu_id = 0;
+	pnc_data.pncl_sram.next_lu_off_reg = 0;
+
+	/* Update dummy register (offset automatically=zero) */
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Set txp and txq */
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+	pnc_data.pncl_sram.pnc_queue = 1;	/* set default virt_uni mc queue via XML */
+
+	/* Calculate absolute PNC entry number to execute */
+	pnc_entry = (pnc_range_start + api_start) + rule_num;
+
+	ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+	IF_ERROR(ret_code);
+
+	/* Decrease number of free entries in pnc_range */
+	ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_VIRT_UNI);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_delete_virt_uni_pnc_entry(uint32_t rule_num)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+	uint32_t pnc_range_start = 0, api_start = 0, pnc_entry = 0;
+
+	/* Get PNC Range Start */
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_VIRT_UNI, &range_conf);
+	IF_ERROR(ret_code);
+	pnc_range_start = range_conf.range_start;
+	api_start = range_conf.api_start;
+
+	/* Pull range from this index untill last used entry in Pnc range */
+	pnc_entry = (pnc_range_start + api_start) + rule_num;
+
+	/* Delete PNC entry */
+	ret_code = tpm_pncl_entry_delete(pnc_entry, pnc_entry);
+	IF_ERROR(ret_code);
+
+	/* Increase number of free entries in pnc_range */
+	ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_VIRT_UNI);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+tpm_error_code_t tpm_proc_add_ipv4_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
+						uint32_t stream_num,
+						tpm_mc_igmp_mode_t igmp_mode,
+						uint8_t mc_stream_pppoe,
+						uint16_t vid,
+						uint8_t ipv4_src_add[4],
+						uint8_t ipv4_dst_add[4],
+						uint8_t ignore_ipv4_src,
+						uint32_t dest_port_bm)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_range_t range_data;
+	tpm_db_mc_stream_entry_t mc_stream;
+	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
+
+	int32_t ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, rule_num = 0xffff;
+	uint32_t pnc_range_start = 0, api_start = 0, rule_idx = 0;
+	uint32_t entry_id;
+	uint16_t u4_vid;
+
+	memset(&mc_stream, 0, sizeof(tpm_db_mc_stream_entry_t));
+
+	/* In MC_MAC_ONLY_FILTER mode, forward all multicast traffic to internal switch by default rule. */
+	if (filter_mode != TPM_MC_MAC_ONLY_FILTER) {
+		/* Set Structs to zero */
+		tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+		/*********** Create Modification Entries **********/
+		ret_code =
+		tpm_proc_create_ipv4_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe, vid, ipv4_dst_add,
+					    dest_port_bm, &mod_entry);
+		IF_ERROR(ret_code);
+
+		/*********** Create PNC Entries **********/
+		/* Build PnC Entry */
+		ret_code =
+		tpm_proc_ipv4_mc_tcam_build(filter_mode, stream_num, vid, mc_stream_pppoe, ipv4_src_add,
+					    ipv4_dst_add, ignore_ipv4_src, &(pnc_data.pncl_tcam));
+		IF_ERROR(ret_code);
+
+		/* Build SRAM Entry */
+		ret_code =
+		tpm_proc_ipv4_mc_sram_build(filter_mode, igmp_mode, dest_port_bm, mod_entry, &(pnc_data.pncl_sram));
+		IF_ERROR(ret_code);
+
+		/*** Calculate PNC Entry ***/
+
+		/* Get PNC Range Start */
+		ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_MC_DS, &range_data);
+		IF_ERROR(ret_code);
+		pnc_range_start = range_data.pnc_range_conf.range_start;
+		api_start = range_data.pnc_range_conf.api_start;
+
+		/* Calculate absolute PNC entry number to execute */
+		pnc_entry = (pnc_range_start + api_start) + stream_num;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " stream_num(%d), pnc_entry(%d)\n", stream_num, pnc_entry);
+
+		ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+		IF_ERROR(ret_code);
+
+		/* Decrease number of free entries in pnc_range */
+		ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_IPV4_MC_DS);
+		IF_ERROR(ret_code);
+
+		/*********** Update API Range in DB **********/
+
+		/* Set API data */
+		memcpy(api_data.ipv4_mc_key.ipv4_src_add, ipv4_src_add, sizeof(ipv4_src_add));
+		memcpy(api_data.ipv4_mc_key.ipv4_dest_add, ipv4_dst_add, sizeof(ipv4_dst_add));
+		api_data.ipv4_mc_key.ignore_ipv4_src = ignore_ipv4_src;
+		api_data.ipv4_mc_key.dest_port_bm = dest_port_bm;
+		api_data.ipv4_mc_key.vid = vid;
+
+		/* Set Pnc Connection data */
+		pnc_conn.num_pnc_ranges = 1;
+		pnc_conn.pnc_conn_tbl[0].pnc_range = TPM_PNC_IPV4_MC_DS;
+		pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+		/* Set Modification Connection data */
+		mod_con.mod_cmd_ind = mod_entry;
+		mod_con.mod_cmd_mac = TPM_PNC_TRG_GMAC0;
+
+		/* Set new API Entry */
+		ret_code = tpm_db_api_entry_set(TPM_IPV4_MC, stream_num, 0 /*bi_dir */ ,
+						&api_data, &mod_con, &pnc_conn, &rule_idx);
+		IF_ERROR(ret_code);
+
+		if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+			if (tpm_db_get_mc_per_uni_vlan_xlate() != 0 && (dest_port_bm & TPM_TRG_UNI_VIRT) != 0) {
+				ret_code = tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg);
+				IF_ERROR(ret_code);
+
+				for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
+					if (mc_vid_cfg[entry_id].tpm_src_port == TPM_SRC_PORT_UNI_VIRT)
+						break;
+				}
+				if (entry_id == TPM_MAX_NUM_UNI_PORTS) {
+					TPM_OS_DEBUG(TPM_TPM_LOG_MOD,
+						     " virt_uni is unable to join the group when "
+						     "virt_uni is not the member of multicast vlan \n");
+				} else if (mc_vid_cfg[entry_id].mc_uni_port_mode != TPM_MC_UNI_MODE_EXCLUDE) {
+					if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSPARENT)
+						u4_vid = vid;
+					else if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP)
+						u4_vid = 0xffff;
+					else
+						u4_vid = mc_vid_cfg[entry_id].uni_port_vid;
+
+					ret_code = tpm_db_mc_alloc_virt_uni_entry(&rule_num);
+					IF_ERROR(ret_code);
+
+					ret_code =
+					tpm_proc_mc_create_virt_uni_pnc_entry(rule_num, u4_vid, ipv4_dst_add, false);
+					IF_ERROR(ret_code);
+				}
+			}
+		}
+	}
+
+	/* Set new stream entry */
+	mc_stream.igmp_mode = igmp_mode;
+	mc_stream.mc_stream_pppoe = mc_stream_pppoe;
+	mc_stream.src_valid = ignore_ipv4_src;
+	mc_stream.vid = vid;
+	mc_stream.dest_port_bm = dest_port_bm;
+	mc_stream.u4_entry = rule_num;
+	memcpy(mc_stream.group_addr, ipv4_dst_add, 4 * sizeof(uint8_t));
+	if (ignore_ipv4_src)
+		memcpy(mc_stream.src_addr, ipv4_src_add, 4 * sizeof(uint8_t));
+
+	ret_code = tpm_db_set_mc_stream_entry(stream_num, &mc_stream);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_update_ipv4_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
+						   uint32_t stream_num,
+						   tpm_mc_igmp_mode_t igmp_mode,
+						   uint8_t mc_stream_pppoe,
+						   uint16_t vid,
+						   uint8_t ipv4_src_add[4],
+						   uint8_t ipv4_dst_add[4],
+						   uint8_t ignore_ipv4_src,
+						   uint32_t dest_port_bm)
+{
+	tpm_db_pnc_range_t range_data;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_mc_stream_entry_t mc_stream;
+	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
+
+	int32_t ret_code;
+	uint32_t bi_dir = 0, rule_idx = 0, pnc_entry = 0, mod_entry = 0, rule_num = 0xffff;
+	uint32_t entry_id;
+	uint16_t u4_vid;
+
+	memset(&mc_stream, 0, sizeof(tpm_db_mc_stream_entry_t));
+
+	/* Only MC_IP_ONLY_FILTER mode, update the multicast group member ports by mh_mod. */
+	if (filter_mode == TPM_MC_IP_ONLY_FILTER) {
+		/* Get PNC Range Start */
+		ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_MC_DS, &range_data);
+		IF_ERROR(ret_code);
+
+		if (stream_num >= range_data.pnc_range_conf.range_size)
+			IF_ERROR(ERR_MC_STREAM_INVALID);
+
+		/* Get old API Entry */
+		ret_code = tpm_db_api_entry_get(TPM_IPV4_MC, stream_num, &rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		IF_ERROR(ret_code);
+
+		pnc_entry = pnc_conn.pnc_conn_tbl[0].pnc_index;
+
+		/* Create new Modification Entry */
+		ret_code = tpm_proc_create_ipv4_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe,
+						       vid, ipv4_dst_add, dest_port_bm, &mod_entry);
+		IF_ERROR(ret_code);
+
+		/* Rebuild PnC Entry */
+		ret_code = tpm_proc_ipv4_mc_tcam_build(filter_mode, stream_num, vid, mc_stream_pppoe, ipv4_src_add,
+						       ipv4_dst_add, ignore_ipv4_src, &(pnc_data.pncl_tcam));
+		IF_ERROR(ret_code);
+
+		/* Rebuild SRAM Entry */
+		ret_code =
+		tpm_proc_ipv4_mc_sram_build(filter_mode, igmp_mode, dest_port_bm, mod_entry, &(pnc_data.pncl_sram));
+		IF_ERROR(ret_code);
+
+		/* Update only Sram of PNC Entry */
+		ret_code = tpm_pncl_update_sram(pnc_entry, &pnc_data);
+		IF_ERROR(ret_code);
+
+		/* Delete old Modification Entry */
+		if (mod_con.mod_cmd_ind != 0) {
+			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, mod_con.mod_cmd_ind);
+			IF_ERROR(ret_code);
+		}
+		/* Update new Modification Entry */
+		mod_con.mod_cmd_ind = mod_entry;
+
+		/* Invalidate old API Entry */
+		ret_code = tpm_db_api_entry_invalidate(TPM_IPV4_MC, stream_num);
+		IF_ERROR(ret_code);
+
+		/* Set new API Entry */
+		mod_con.mod_cmd_ind = mod_entry;
+		ret_code = tpm_db_api_entry_set(TPM_IPV4_MC, stream_num, 0 /*bi_dir */ ,
+						&api_data, &mod_con, &pnc_conn, &rule_idx);
+		IF_ERROR(ret_code);
+	}
+
+	if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
+			ret_code = tpm_db_get_mc_stream_entry(stream_num, &mc_stream);
+			IF_ERROR(ret_code);
+
+			rule_num = mc_stream.u4_entry;
+
+			if ((dest_port_bm & TPM_TRG_UNI_VIRT) != 0 && (mc_stream.dest_port_bm & TPM_TRG_UNI_VIRT) == 0) {
+				ret_code = tpm_db_mc_alloc_virt_uni_entry(&rule_num);
+				IF_ERROR(ret_code);
+
+				ret_code = tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg);
+				IF_ERROR(ret_code);
+
+				for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
+					if (mc_vid_cfg[entry_id].tpm_src_port == TPM_SRC_PORT_UNI_VIRT)
+						break;
+				}
+				if (entry_id == TPM_MAX_NUM_UNI_PORTS) {
+					TPM_OS_DEBUG(TPM_TPM_LOG_MOD,
+						     " virt_uni is unable to join the group when "
+						     "virt_uni is not the member of multicast vlan \n");
+				} else {
+					if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSPARENT)
+						u4_vid = vid;
+					else if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP)
+						u4_vid = 0xffff;
+					else
+						u4_vid = mc_vid_cfg[entry_id].uni_port_vid;
+
+					ret_code =
+					tpm_proc_mc_create_virt_uni_pnc_entry(rule_num, u4_vid, ipv4_dst_add, false);
+					IF_ERROR(ret_code);
+				}
+			} else if ((dest_port_bm & TPM_TRG_UNI_VIRT) == 0 && (mc_stream.dest_port_bm & TPM_TRG_UNI_VIRT) != 0) {
+				if (rule_num != 0xffff) {
+					ret_code = tpm_proc_mc_delete_virt_uni_pnc_entry(rule_num);
+					IF_ERROR(ret_code);
+					ret_code = tpm_db_mc_free_virt_uni_entry(rule_num);
+					IF_ERROR(ret_code);
+					rule_num = 0xffff;
+				}
+			}
+		}
+	}
+
+	/* Update stream entry */
+	mc_stream.igmp_mode = igmp_mode;
+	mc_stream.mc_stream_pppoe = mc_stream_pppoe;
+	mc_stream.src_valid = ignore_ipv4_src;
+	mc_stream.vid = vid;
+	mc_stream.dest_port_bm = dest_port_bm;
+	mc_stream.u4_entry = rule_num;
+	memcpy(mc_stream.group_addr, ipv4_dst_add, 4 * sizeof(uint8_t));
+	if (ignore_ipv4_src)
+		memcpy(mc_stream.src_addr, ipv4_src_add, 4 * sizeof(uint8_t));
+
+	ret_code = tpm_db_set_mc_stream_entry(stream_num, &mc_stream);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_delete_ipv4_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
+						   uint32_t stream_num,
+						   uint32_t dest_port_bm,
+						   uint32_t u4_entry)
+{
+	tpm_db_pnc_range_t range_data;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_conn_t pnc_conn;
+
+	int32_t ret_code;
+	uint32_t bi_dir = 0, rule_idx = 0;
+	uint32_t pnc_range_start = 0, api_start = 0, pnc_entry = 0;
+
+	if (filter_mode != TPM_MC_MAC_ONLY_FILTER) {
+		/* Get PNC Range Start */
+		ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV4_MC_DS, &range_data);
+		IF_ERROR(ret_code);
+
+		if (stream_num >= range_data.pnc_range_conf.range_size)
+			IF_ERROR(ERR_MC_STREAM_INVALID);
+
+		/* Check parameters */
+		ret_code = tpm_db_api_entry_get(TPM_IPV4_MC, stream_num, &rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		IF_ERROR(ret_code);
+
+		/* Delete PNC Entry */
+#if 0
+		ret_code = tpm_proc_pnc_con_del(&pnc_conn);
+		IF_ERROR(ret_code);
+#endif
+		pnc_range_start = range_data.pnc_range_conf.range_start;
+		api_start = range_data.pnc_range_conf.api_start;
+
+		/* Pull range from this index untill last used entry in Pnc range */
+		pnc_entry = (pnc_range_start + api_start) + stream_num;
+
+		/* Delete PNC entry */
+		ret_code = tpm_pncl_entry_delete(pnc_entry, pnc_entry);
+		IF_ERROR(ret_code);
+
+		/* Increase number of free entries in pnc_range */
+		ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_IPV4_MC_DS);
+		IF_ERROR(ret_code);
+
+		if (mod_con.mod_cmd_ind != 0) {
+			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, mod_con.mod_cmd_ind);
+			IF_ERROR(ret_code);
+		}
+
+		/* Delete API Rule Entry */
+		ret_code = tpm_db_api_entry_invalidate(TPM_IPV4_MC, stream_num);
+		IF_ERROR(ret_code);
+	}
+
+	if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
+			if (u4_entry != 0xffff) {
+				ret_code = tpm_proc_mc_delete_virt_uni_pnc_entry(u4_entry);
+				IF_ERROR(ret_code);
+
+				ret_code = tpm_db_mc_free_virt_uni_entry(u4_entry);
+				IF_ERROR(ret_code);
+			}
+		}
+	}
+
+	/* Remove stream entry */
+	tpm_db_reset_mc_stream_entry(stream_num);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_set_ipv4_mc_switch(tpm_mc_filter_mode_t filter_mode,
+					     uint8_t mc_mac[6],
+					     uint32_t old_target,
+					     uint32_t new_target)
+{
+	int32_t ret_code;
+	uint32_t trg_port_bm = 0, diff_target = 0;
+	uint32_t port;
+	uint32_t switch_init = 0;
+
+	/*get switch init*/
+	ret_code = tpm_db_switch_init_get(&switch_init);
+	IF_ERROR(ret_code);
+
+	if (!switch_init) {
+		/* no switch, no ATU operation */
+		TPM_OS_INFO(TPM_TPM_LOG_MOD, "no switch, no ATU operation\n");
+		return TPM_RC_OK;
+	}
+
+	diff_target = old_target ^ new_target;
+	port = TPM_TRG_UNI_0;
+
+	while (port != TPM_TRG_PORT_CPU) {
+		if (diff_target & port) {
+			if (old_target & port) {
+				ret_code = tpm_db_decrease_mc_mac_port_user_num(mc_mac, port);
+				IF_ERROR(ret_code);
+
+				if (tpm_db_get_mc_mac_port_user_num(mc_mac, port) != 0)
+					new_target |= port;
+			} else {
+				ret_code = tpm_db_increase_mc_mac_port_user_num(mc_mac, port);
+				IF_ERROR(ret_code);
+			}
+		}
+
+		port = port << 1;
+	}
+
+	if (new_target != 0)
+		new_target |= TPM_TRG_PORT_CPU;	/* igmp report to CPU */
+
+	switch (filter_mode) {
+	case TPM_MC_COMBINED_IP_MAC_FILTER:
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0 && new_target != 0)
+			new_target |= TPM_TRG_UNI_VIRT;	/* loopback G1 */
+	case TPM_MC_MAC_ONLY_FILTER:
+		trg_port_bm = tpm_db_trg_port_switch_port_get(new_target);
+		break;
+	case TPM_MC_IP_ONLY_FILTER:
+		trg_port_bm = 0x3F;	/* all uni ports + CPU + G1/wifi */
+		break;
+	default:
+		break;
+	}
+
+	if (new_target == 0) {
+		ret_code = tpm_sw_del_static_mac(TPM_MOD_OWNER_TPM, mc_mac);
+		IF_ERROR(ret_code);
+		tpm_db_reset_mc_mac_entry(mc_mac);
+	} else {
+		ret_code = tpm_sw_set_static_mac_w_ports_mask(TPM_MOD_OWNER_TPM, trg_port_bm, mc_mac);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_ipv4_mc_stream()
+*
+* DESCRIPTION:    Main function for adding IPv4 multicast streams.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_ipv4_mc_stream(uint32_t owner_id,
+					     uint32_t stream_num,
+					     tpm_mc_igmp_mode_t igmp_mode,
+					     uint8_t mc_stream_pppoe,
+					     uint16_t vid,
+					     uint8_t ipv4_src_add[4],
+					     uint8_t ipv4_dst_add[4],
+					     uint8_t ignore_ipv4_src,
+					     tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code;
+	tpm_mc_filter_mode_t filter_mode;
+	uint8_t mc_mac[6];
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) stream_num(%d), igmp_mode(%d), mc_stream_pppoe(%d), vid(%d) "
+		     "sip(0x%02x%02x%02x%02x), dip(0x%02x%02x%02x%02x), ignore_ipv4_src(%d), dest_port_bm(0x%x)\n",
+		     owner_id, stream_num, igmp_mode, mc_stream_pppoe, vid, ipv4_src_add[0], ipv4_src_add[1],
+		     ipv4_src_add[2], ipv4_src_add[3], ipv4_dst_add[0], ipv4_dst_add[1], ipv4_dst_add[2],
+		     ipv4_dst_add[3], ignore_ipv4_src, dest_port_bm);
+
+	filter_mode = tpm_db_get_mc_filter_mode();
+	if (filter_mode == TPM_MC_ALL_CPU_FRWD) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " illegal mc_filter_mod (%d)\n", filter_mode);
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	if (dest_port_bm & TPM_TRG_PORT_UNI_ANY)
+		dest_port_bm = tpm_db_trg_port_uni_any_bmp_get(true);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv4_mc_check(owner_id, stream_num, igmp_mode, mc_stream_pppoe, vid,
+					      ipv4_src_add, ipv4_dst_add, ignore_ipv4_src, dest_port_bm, filter_mode);
+	IF_ERROR(ret_code);
+
+	/* Create PNC entry */
+	ret_code = tpm_proc_add_ipv4_mc_pnc_entry(filter_mode, stream_num, igmp_mode, mc_stream_pppoe, vid,
+						  ipv4_src_add, ipv4_dst_add, ignore_ipv4_src, dest_port_bm);
+	IF_ERROR(ret_code);
+
+	/* Set switch port_map for multicast MAC, but don't overwrite 224.0.0.1 (IGMP General Query) MAC */
+	MULTI_IP_2_MAC(mc_mac, ipv4_dst_add);
+	if (memcmp(mc_mac, tpm_igmp_gen_query_mac, 6) != 0) {
+		ret_code = tpm_proc_set_ipv4_mc_switch(filter_mode, mc_mac, 0, dest_port_bm);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_updt_ipv4_mc_stream()
+*
+* DESCRIPTION:    Main function for updating IPv4 multicast streams.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_updt_ipv4_mc_stream(uint32_t owner_id, uint32_t stream_num, tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code;
+	tpm_mc_filter_mode_t filter_mode;
+	uint8_t mc_mac[6];
+	tpm_init_virt_uni_t virt_uni;
+	tpm_db_mc_stream_entry_t mc_stream;
+
+	memset(&virt_uni, 0, sizeof(tpm_init_virt_uni_t));
+	memset(&mc_stream, 0, sizeof(tpm_db_mc_stream_entry_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) stream_num(%d),dest_port_bm(0x%x)\n",
+		     owner_id, stream_num, dest_port_bm);
+
+	filter_mode = tpm_db_get_mc_filter_mode();
+	if (filter_mode == TPM_MC_ALL_CPU_FRWD) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " illegal mc_filter_mod (%d)\n", filter_mode);
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	tpm_db_virt_info_get(&virt_uni);
+
+	if (dest_port_bm & TPM_TRG_UNI_VIRT) {
+		if (virt_uni.enabled == 0)
+			IF_ERROR(ERR_MC_DST_PORT_INVALID);
+	}
+
+	if (dest_port_bm & TPM_TRG_PORT_CPU) {
+		if (dest_port_bm & (~TPM_TRG_PORT_CPU))
+			IF_ERROR(ERR_MC_DST_PORT_INVALID);
+	}
+
+	if (dest_port_bm & TPM_TRG_PORT_UNI_ANY)
+		dest_port_bm = tpm_db_trg_port_uni_any_bmp_get(true);
+
+	ret_code = tpm_proc_check_dst_uni_port(dest_port_bm);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_get_mc_stream_entry(stream_num, &mc_stream);
+	IF_ERROR(ret_code);
+
+	if (((dest_port_bm & TPM_TRG_PORT_CPU) != 0 && (mc_stream.dest_port_bm & TPM_TRG_PORT_CPU) == 0) ||
+	    ((dest_port_bm & TPM_TRG_PORT_CPU) == 0 && (mc_stream.dest_port_bm & TPM_TRG_PORT_CPU) != 0)) {
+		ret_code = tpm_proc_delete_ipv4_mc_pnc_entry(filter_mode, stream_num,
+														mc_stream.dest_port_bm, mc_stream.u4_entry);
+		IF_ERROR(ret_code);
+
+		ret_code = tpm_proc_add_ipv4_mc_pnc_entry(filter_mode, stream_num, mc_stream.igmp_mode,
+													mc_stream.mc_stream_pppoe, mc_stream.vid,
+													mc_stream.src_addr, mc_stream.group_addr,
+													mc_stream.src_valid, dest_port_bm);
+	} else {
+		ret_code = tpm_proc_update_ipv4_mc_pnc_entry(filter_mode, stream_num, mc_stream.igmp_mode,
+														mc_stream.mc_stream_pppoe, mc_stream.vid,
+														mc_stream.src_addr, mc_stream.group_addr,
+														mc_stream.src_valid, dest_port_bm);
+	}
+	IF_ERROR(ret_code);
+
+	/* Set switch port_map for multicast MAC, but don't overwrite 224.0.0.1 (IGMP General Query) MAC */
+	MULTI_IP_2_MAC(mc_mac, mc_stream.group_addr);
+	if (memcmp(mc_mac, tpm_igmp_gen_query_mac, 6) != 0) {
+		ret_code = tpm_proc_set_ipv4_mc_switch(filter_mode, mc_mac, mc_stream.dest_port_bm, dest_port_bm);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_del_ipv4_mc_stream()
+*
+* DESCRIPTION:      Deletes an existing IPv4 MC stream.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* stream_num         - MC stream number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_ipv4_mc_stream(uint32_t owner_id, uint32_t stream_num)
+{
+
+	int32_t ret_code;
+	tpm_mc_filter_mode_t filter_mode;
+	uint8_t mc_mac[6];
+	tpm_db_mc_stream_entry_t mc_stream;
+
+	memset(&mc_stream, 0, sizeof(tpm_db_mc_stream_entry_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) stream_num(%d)\n", owner_id, stream_num);
+
+	filter_mode = tpm_db_get_mc_filter_mode();
+	if (filter_mode == TPM_MC_ALL_CPU_FRWD) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " illegal mc_filter_mod (%d)\n", filter_mode);
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	ret_code = tpm_db_get_mc_stream_entry(stream_num, &mc_stream);
+	IF_ERROR(ret_code);
+
+	ret_code =
+	tpm_proc_delete_ipv4_mc_pnc_entry(filter_mode, stream_num, mc_stream.dest_port_bm, mc_stream.u4_entry);
+	IF_ERROR(ret_code);
+
+	/* Set switch VID and multicast MAC */
+	MULTI_IP_2_MAC(mc_mac, mc_stream.group_addr);
+	/* Make sure that donot remove the mac 01-00-5e-00-00-01 from Switch which is used by Genery Query */
+	if (memcmp(mc_mac, tpm_igmp_gen_query_mac, 6) != 0) {
+		ret_code = tpm_proc_set_ipv4_mc_switch(filter_mode, mc_mac, mc_stream.dest_port_bm, 0);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************/
+/*     Multicast Loopback      */
+/*******************************/
+
+int32_t tpm_proc_mc_lpbk_xlat_tcam_build(tpm_ip_ver_t ip_ver, uint16_t mvlan, uint16_t in_vid, tpm_pncl_tcam_data_t *tcam_data)
+{
+	int32_t ret_code;
+	uint8_t first_lpbk;
+	tpm_l2_acl_key_t l2_key;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mvlan(%d), in_vid(%d) \n", mvlan, in_vid);
+
+	tcam_data->l2_parse_bm = 0;
+	memset(&l2_key, 0, sizeof(tpm_l2_acl_key_t));
+
+	first_lpbk = 0;
+	if (mvlan == in_vid)
+		first_lpbk = 1;
+
+	/* Get PNC Range information */
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_MULTI_LPBK, &range_conf);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = range_conf.base_lu_id;
+	tcam_data->start_offset.range_id = TPM_PNC_MULTI_LPBK;
+	tcam_data->start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	tcam_data->start_offset.offset_sub.subf = TPM_L2_PARSE_MH;
+
+	/* Get GMAC(s) */
+	tcam_data->port_ids = gmac_pnc_bm[TPM_ENUM_GMAC_1];
+
+	/* Parse MH for src_port filter */
+	tcam_data->l2_parse_bm |= TPM_L2_PARSE_MH;
+	if (first_lpbk)
+		tcam_data->pkt_key.src_port = TPM_SRC_PORT_WAN;
+	else
+		tcam_data->pkt_key.src_port = TPM_SRC_PORT_UNI_VIRT;
+
+	/* Parse MC DA filter */
+	tcam_data->l2_parse_bm |= TPM_L2_PARSE_MAC_DA;
+	if (ip_ver == TPM_IP_VER_4) {
+		l2_key.mac.mac_da[0] = 0x01;
+		l2_key.mac.mac_da[1] = 0x00;
+		l2_key.mac.mac_da[2] = 0x5e;
+		l2_key.mac.mac_da_mask[0] = 0xff;
+		l2_key.mac.mac_da_mask[1] = 0xff;
+		l2_key.mac.mac_da_mask[2] = 0xff;
+	} else {
+		l2_key.mac.mac_da[0] = 0x33;
+		l2_key.mac.mac_da[1] = 0x33;
+		l2_key.mac.mac_da_mask[0] = 0xff;
+		l2_key.mac.mac_da_mask[1] = 0xff;
+	}
+
+	/* Parse VLAN filter */
+	if (first_lpbk) {
+		tcam_data->l2_parse_bm |= TPM_L2_PARSE_ONE_VLAN_TAG;
+		l2_key.vlan1.tpid = 0x8100;
+		l2_key.vlan1.tpid_mask = 0xffff;
+		l2_key.vlan1.pbit = 0;
+		l2_key.vlan1.pbit_mask = 0;
+		l2_key.vlan1.cfi = 0;
+		l2_key.vlan1.cfi_mask = 0;
+		l2_key.vlan1.vid = in_vid;
+		l2_key.vlan1.vid_mask = 0xffff;
+	} else {
+		tcam_data->l2_parse_bm |= TPM_L2_PARSE_TWO_VLAN_TAG;
+
+		l2_key.vlan1.tpid = 0x8100;
+		l2_key.vlan1.tpid_mask = 0xffff;
+		l2_key.vlan1.pbit = 0;
+		l2_key.vlan1.pbit_mask = 0;
+		l2_key.vlan1.cfi = 0;
+		l2_key.vlan1.cfi_mask = 0;
+		l2_key.vlan1.vid = mvlan;
+		l2_key.vlan1.vid_mask = 0xffff;
+
+		l2_key.vlan2.tpid = 0x8100;
+		l2_key.vlan2.tpid_mask = 0xffff;
+		l2_key.vlan2.pbit = 0;
+		l2_key.vlan2.pbit_mask = 0;
+		l2_key.vlan2.cfi = 0;
+		l2_key.vlan2.cfi_mask = 0;
+		l2_key.vlan2.vid = in_vid;
+		l2_key.vlan2.vid_mask = 0xffff;
+	}
+
+	/* Copy in logical PnC Key */
+	memcpy(&(tcam_data->pkt_key.l2_key), &l2_key, sizeof(tpm_l2_acl_key_t));
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_lpbk_xlat_sram_build(uint32_t mod_entry, tpm_pncl_sram_data_t *sram_data)
+{
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " mod_entry(%d) \n", mod_entry);
+
+	/* Set sram_updt bitmap */
+	sram_data->sram_updt_bm |= (TPM_PNCL_SET_TXP | TPM_PNCL_SET_MOD | TPM_PNCL_SET_LUD | TPM_PNCL_SET_MC);
+
+	/* No next lookup */
+	sram_data->next_lu_id = 0;
+	sram_data->next_lu_off_reg = 0;
+
+	/* Update dummy register (offset automatically=zero) */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Set txp and txq */
+	sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_GMAC1;
+	sram_data->pnc_queue = 1;	/* set default mc_lpbk queue via XML */
+
+	/* Set modification command */
+	sram_data->flow_id_sub.mod_cmd = mod_entry;
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_create_lpbk_xlate_mod(uint16_t mvlan, uint16_t in_vid, uint16_t out_vid,
+					  tpm_trg_port_type_t port_bm, uint32_t *mod_entry)
+{
+	int32_t ret_code;
+	uint8_t first_lpbk;
+	tpm_pkt_mod_bm_t mod_bm;
+	tpm_pkt_mod_t mod_data;
+
+	memset(&mod_data, 0, sizeof(tpm_pkt_mod_t));
+
+	first_lpbk = 0;
+	if (mvlan == in_vid)
+		first_lpbk = 1;
+
+	/* Set loopback target ports */
+	mod_bm = TPM_MH_SET;
+	mod_data.mh_mod = tpm_db_trg_port_switch_port_get(port_bm | TPM_TRG_UNI_VIRT);
+
+	/* Set vlan modification data */
+	if (port_bm & TPM_TRG_UNI_VIRT) {
+		if (first_lpbk) {
+			if (mvlan == out_vid) {
+				/* uni-4 is transparent port while all the other uni_ports are transparent ports or strip ports. */
+				/* Noop, just do a dummy loopback! */
+			} else if (out_vid == 0xffff) {
+				mod_bm |= TPM_VLAN_MOD;
+				/* uni-4 is strip port and remove outer vlan tag */
+				mod_data.vlan_mod.vlan_op = VLANOP_EXT_TAG_DEL;
+			} else {
+				mod_bm |= TPM_VLAN_MOD;
+				/* uni-4 is translated port and replace outer vlan tag */
+				mod_data.vlan_mod.vlan_op = VLANOP_EXT_TAG_MOD;
+				mod_data.vlan_mod.vlan1_out.tpid = 0x8100;
+				mod_data.vlan_mod.vlan1_out.pbit = 0;
+				mod_data.vlan_mod.vlan1_out.pbit_mask = 0x0;
+				mod_data.vlan_mod.vlan1_out.cfi = 0;
+				mod_data.vlan_mod.vlan1_out.cfi_mask = 0x0;
+				mod_data.vlan_mod.vlan1_out.vid = out_vid;
+				mod_data.vlan_mod.vlan1_out.vid_mask = 0xffff;
+			}
+		} else {
+			mod_bm |= TPM_VLAN_MOD;
+
+			if (mvlan == out_vid) {
+				/* uni-4 is transparent port while at least one of the other uni_ports is translated ports. */
+				/* remove inner vlan tag */
+				mod_data.vlan_mod.vlan_op = VLANOP_EXT_TAG_DEL_INT_MOD;
+				mod_data.vlan_mod.vlan2_out.tpid = 0x8100;
+				mod_data.vlan_mod.vlan2_out.pbit = 0;
+				mod_data.vlan_mod.vlan2_out.pbit_mask = 0x0;
+				mod_data.vlan_mod.vlan2_out.cfi = 0;
+				mod_data.vlan_mod.vlan2_out.cfi_mask = 0x0;
+				mod_data.vlan_mod.vlan2_out.vid = out_vid;
+				mod_data.vlan_mod.vlan2_out.vid_mask = 0xffff;
+			} else if (out_vid == 0xffff) {
+				/* uni-4 is strip port and remove outer and inner vlan tag */
+				mod_data.vlan_mod.vlan_op = VLANOP_DEL_2TAG;
+			} else {
+				/* uni-4 is translated port and remove outer vlan tag, replace inner vlan tag */
+				mod_data.vlan_mod.vlan_op = VLANOP_EXT_TAG_DEL_INT_MOD;
+				mod_data.vlan_mod.vlan2_out.tpid = 0x8100;
+				mod_data.vlan_mod.vlan2_out.pbit = 0;
+				mod_data.vlan_mod.vlan2_out.pbit_mask = 0x0;
+				mod_data.vlan_mod.vlan2_out.cfi = 0;
+				mod_data.vlan_mod.vlan2_out.cfi_mask = 0x0;
+				mod_data.vlan_mod.vlan2_out.vid = out_vid;
+				mod_data.vlan_mod.vlan2_out.vid_mask = 0xffff;
+			}
+		}
+	} else {
+		if (out_vid == 0xffff || mvlan == out_vid) {
+			TPM_OS_WARN(TPM_PNCL_MOD, "Input vlan equals to output vlan, should be transparent, not translate!\n");
+			return ERR_GENERAL;
+		}
+		mod_bm |= TPM_VLAN_MOD;
+
+		if (first_lpbk) {
+			mod_data.vlan_mod.vlan_op = VLANOP_EXT_TAG_MOD_INS;
+			mod_data.vlan_mod.vlan1_out.tpid = 0x8100;
+			mod_data.vlan_mod.vlan1_out.pbit = 0;
+			mod_data.vlan_mod.vlan1_out.pbit_mask = 0x0;
+			mod_data.vlan_mod.vlan1_out.cfi = 0;
+			mod_data.vlan_mod.vlan1_out.cfi_mask = 0x0;
+			mod_data.vlan_mod.vlan1_out.vid = mvlan;
+			mod_data.vlan_mod.vlan1_out.vid_mask = 0xffff;
+			mod_data.vlan_mod.vlan2_out.tpid = 0x8100;
+			mod_data.vlan_mod.vlan2_out.pbit = 0;
+			mod_data.vlan_mod.vlan2_out.pbit_mask = 0xff;
+			mod_data.vlan_mod.vlan2_out.cfi = 0;
+			mod_data.vlan_mod.vlan2_out.cfi_mask = 0xff;
+			mod_data.vlan_mod.vlan2_out.vid = out_vid;
+			mod_data.vlan_mod.vlan2_out.vid_mask = 0xffff;
+		} else {
+			mod_data.vlan_mod.vlan_op = VLANOP_INT_TAG_MOD;
+			mod_data.vlan_mod.vlan2_out.tpid = 0x8100;
+			mod_data.vlan_mod.vlan2_out.pbit = 0;
+			mod_data.vlan_mod.vlan2_out.pbit_mask = 0xff;
+			mod_data.vlan_mod.vlan2_out.cfi = 0;
+			mod_data.vlan_mod.vlan2_out.cfi_mask = 0xff;
+			mod_data.vlan_mod.vlan2_out.vid = out_vid;
+			mod_data.vlan_mod.vlan2_out.vid_mask = 0xffff;
+		}
+	}
+
+	/* Create modification entry */
+	ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_1, mod_bm, TPM_INT_MC_MOD, &mod_data, mod_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_lpbk_calc_rule_num(uint32_t *rule_num)
+{
+	int32_t ret_code;
+	uint32_t _rule_num;
+	tpm_db_pnc_range_t range_data;
+
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_MULTI_LPBK, &range_data);
+	IF_ERROR(ret_code);
+
+	_rule_num = tpm_db_mc_lpbk_entries_num_get();
+
+	if (_rule_num > range_data.pnc_range_conf.range_size)
+		return TPM_FAIL;
+
+	*rule_num = _rule_num;
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_lpbk_create_acl_rule(uint32_t rule_num, tpm_pncl_pnc_full_t *pnc_data)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_t range_data;
+	uint32_t pnc_range_start = 0, pnc_entries_num = 0, api_start = 0, pnc_entry = 0, pnc_stop_entry = 0;
+
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Get PNC Range Start */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_MULTI_LPBK, &range_data);
+	IF_ERROR(ret_code);
+	pnc_range_start = range_data.pnc_range_conf.range_start;
+	api_start = range_data.pnc_range_conf.api_start;
+
+	/* Calculate absolute PNC entry number to execute */
+	pnc_entry = (pnc_range_start + api_start) + rule_num;
+
+	/* Get existing PNC entry number */
+	pnc_entries_num = tpm_db_mc_lpbk_entries_num_get();
+
+	/* Call PNC Entry Insert, if this is not the api_section's new last entry */
+	if (rule_num < pnc_entries_num) {
+		pnc_stop_entry = (pnc_range_start + api_start) + (pnc_entries_num - 1);
+		ret_code = tpm_pncl_entry_insert(pnc_entry, pnc_stop_entry, pnc_data);
+		IF_ERROR(ret_code);
+	} else {		/* Otherwise just set the entry (no insertion) */
+
+		ret_code = tpm_pncl_entry_set(pnc_entry, pnc_data);
+		IF_ERROR(ret_code);
+	}
+
+	/* Decrease number of free entries in pnc_range */
+	ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_MULTI_LPBK);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_lpbk_delete_acl_rule(uint32_t rule_num)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_t range_data;
+	uint32_t pnc_range_start = 0, pnc_entries_num = 0, api_start = 0, pnc_start_entry = 0, pnc_stop_entry = 0;
+
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Get PNC Range Start */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_MULTI_LPBK, &range_data);
+	IF_ERROR(ret_code);
+	pnc_range_start = range_data.pnc_range_conf.range_start;
+	api_start = range_data.pnc_range_conf.api_start;
+
+	/* Get existing PNC entry number */
+	pnc_entries_num = tpm_db_mc_lpbk_entries_num_get();
+
+	/* Pull range from this index untill last used entry in Pnc range */
+	pnc_start_entry = (pnc_range_start + api_start) + rule_num;
+	pnc_stop_entry = (pnc_range_start + api_start) + (pnc_entries_num - 1);
+
+	/* Delete PNC entry */
+	ret_code = tpm_pncl_entry_delete(pnc_start_entry, pnc_stop_entry);
+	IF_ERROR(ret_code);
+
+	/* Increase number of free entries in pnc_range */
+	ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_MULTI_LPBK);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_set_translation_uni_x_first(tpm_ip_ver_t ip_ver, uint16_t mvlan, uint16_t out_vid, tpm_trg_port_type_t port_bm)
+{
+	int32_t ret_code;
+	uint32_t rule_num = 0, mod_entry = 0;
+	tpm_pncl_pnc_full_t pnc_data;
+
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+
+	/*********** Create Modification Entries **********/
+	ret_code = tpm_proc_mc_create_lpbk_xlate_mod(mvlan, mvlan, out_vid, port_bm, &mod_entry);
+	IF_ERROR(ret_code);
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code = tpm_proc_mc_lpbk_xlat_tcam_build(ip_ver, mvlan, mvlan, &(pnc_data.pncl_tcam));
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code = tpm_proc_mc_lpbk_xlat_sram_build(mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(ret_code);
+
+	/* Calculate ACL Rule Num */
+	ret_code = tpm_proc_mc_lpbk_calc_rule_num(&rule_num);
+	IF_ERROR(ret_code);
+
+	/* Set MULTI_LPBK ACL Rule */
+	ret_code = tpm_proc_mc_lpbk_create_acl_rule(rule_num, &pnc_data);
+	IF_ERROR(ret_code);
+
+	/* Set MULTI_LPBK Rule DB */
+	ret_code = tpm_db_mc_lpbk_entry_set(ip_ver, mvlan, mvlan, out_vid, rule_num, mod_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_set_translation_uni_x_next(tpm_ip_ver_t ip_ver, uint16_t mvlan, uint16_t in_vid, uint16_t out_vid,
+					       tpm_trg_port_type_t port_bm)
+{
+	int32_t ret_code;
+	uint32_t rule_num = 0, mod_entry = 0;
+	tpm_pncl_pnc_full_t pnc_data;
+
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+
+	/*********** Create Modification Entries **********/
+	ret_code = tpm_proc_mc_create_lpbk_xlate_mod(mvlan, in_vid, out_vid, port_bm, &mod_entry);
+	IF_ERROR(ret_code);
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code = tpm_proc_mc_lpbk_xlat_tcam_build(ip_ver, mvlan, in_vid, &(pnc_data.pncl_tcam));
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code = tpm_proc_mc_lpbk_xlat_sram_build(mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(ret_code);
+
+	/* Calculate ACL Rule Num */
+	ret_code = tpm_proc_mc_lpbk_calc_rule_num(&rule_num);
+	IF_ERROR(ret_code);
+
+	/* Set MULTI_LPBK ACL Rule */
+	ret_code = tpm_proc_mc_lpbk_create_acl_rule(rule_num, &pnc_data);
+	IF_ERROR(ret_code);
+
+	/* Set MULTI_LPBK Rule DB */
+	ret_code = tpm_db_mc_lpbk_entry_set(ip_ver, mvlan, in_vid, out_vid, rule_num, mod_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_set_translation_max_uni_first(tpm_ip_ver_t ip_ver, uint16_t mvlan, uint16_t out_vid)
+{
+	int32_t ret_code;
+	uint32_t rule_num = 0, mod_entry = 0, port_bm = TPM_TRG_UNI_VIRT;
+	tpm_pncl_pnc_full_t pnc_data;
+
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+
+	/*********** Create Modification Entries **********/
+	ret_code = tpm_proc_mc_create_lpbk_xlate_mod(mvlan, mvlan, out_vid, port_bm, &mod_entry);
+	IF_ERROR(ret_code);
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code = tpm_proc_mc_lpbk_xlat_tcam_build(ip_ver, mvlan, mvlan, &(pnc_data.pncl_tcam));
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code = tpm_proc_mc_lpbk_xlat_sram_build(mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(ret_code);
+
+	/* Calculate ACL Rule Num */
+	ret_code = tpm_proc_mc_lpbk_calc_rule_num(&rule_num);
+	IF_ERROR(ret_code);
+
+	/* Set MULTI_LPBK ACL Rule */
+	ret_code = tpm_proc_mc_lpbk_create_acl_rule(rule_num, &pnc_data);
+	IF_ERROR(ret_code);
+
+	/* Set MULTI_LPBK Rule DB */
+	ret_code = tpm_db_mc_lpbk_entry_set(ip_ver, mvlan, mvlan, out_vid, rule_num, mod_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_set_translation_max_uni_next(tpm_ip_ver_t ip_ver, uint16_t mvlan, uint16_t in_vid, uint16_t out_vid)
+{
+	int32_t ret_code;
+	uint32_t rule_num = 0, mod_entry = 0, port_bm = TPM_TRG_UNI_VIRT;
+	tpm_pncl_pnc_full_t pnc_data;
+
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+
+	/*********** Create Modification Entries **********/
+	ret_code = tpm_proc_mc_create_lpbk_xlate_mod(mvlan, in_vid, out_vid, port_bm, &mod_entry);
+	IF_ERROR(ret_code);
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code = tpm_proc_mc_lpbk_xlat_tcam_build(ip_ver, mvlan, in_vid, &(pnc_data.pncl_tcam));
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code = tpm_proc_mc_lpbk_xlat_sram_build(mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(ret_code);
+
+	/* Calculate ACL Rule Num */
+	ret_code = tpm_proc_mc_lpbk_calc_rule_num(&rule_num);
+	IF_ERROR(ret_code);
+
+	/* Set MULTI_LPBK ACL Rule */
+	ret_code = tpm_proc_mc_lpbk_create_acl_rule(rule_num, &pnc_data);
+	IF_ERROR(ret_code);
+
+	/* Set MULTI_LPBK Rule DB */
+	ret_code = tpm_db_mc_lpbk_entry_set(ip_ver, mvlan, in_vid, out_vid, rule_num, mod_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_reset_translation(uint16_t mvlan)
+{
+	int32_t ret_code;
+	uint32_t xits_num = 0, xit_id, rule_index, rule_num, mod_entry;
+	uint32_t ip_ver;
+	uint8_t lpbk_enable;
+
+	for (ip_ver = TPM_IP_VER_4; ip_ver < TPM_IP_VER_MAX; ip_ver++) {
+		tpm_db_get_mc_lpbk_enable(ip_ver, &lpbk_enable);
+		if (lpbk_enable == TPM_FALSE)
+			continue;
+		ret_code = tpm_db_mc_vlan_xits_num_get(ip_ver, mvlan, &xits_num);
+		if (ret_code == TPM_OK) {
+			for (xit_id = 0; xit_id < xits_num; xit_id++) {
+				ret_code = tpm_db_mc_vlan_xit_entry_get(ip_ver, mvlan, xit_id, &rule_index, &mod_entry);
+				IF_ERROR(ret_code);
+
+				ret_code = tpm_db_mc_lpbk_rule_num_get(rule_index, &rule_num);
+				IF_ERROR(ret_code);
+
+				ret_code = tpm_proc_mc_lpbk_delete_acl_rule(rule_num);
+				IF_ERROR(ret_code);
+
+				ret_code = tpm_db_mc_lpbk_entry_invalidate(rule_num);
+				IF_ERROR(ret_code);
+
+				if (mod_entry != 0) {
+					ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_1, mod_entry);
+					IF_ERROR(ret_code);
+				}
+			}
+		}
+	}
+	return TPM_OK;
+}
+
+int32_t tpm_proc_mc_refresh_translation(uint16_t mvlan)
+{
+	int32_t ret_code;
+	uint32_t stream_id;
+	tpm_db_mc_stream_entry_t stream_data;
+	tpm_trg_port_type_t dest_port_bm;
+
+	for (stream_id = 0; stream_id < TPM_MC_MAX_STREAM_NUM; stream_id++) {
+		if (tpm_db_get_mc_stream_entry(stream_id, &stream_data) == TPM_OK) {
+			if (stream_data.vid == mvlan) {
+				if (tpm_db_get_mc_per_uni_vlan_xlate() == 0) {
+					ret_code = tpm_proc_del_ipv4_mc_stream(0, stream_id);
+					IF_ERROR(ret_code);
+
+					ret_code = tpm_proc_add_ipv4_mc_stream(0, stream_id, stream_data.igmp_mode,
+									       stream_data.mc_stream_pppoe,
+									       stream_data.vid, stream_data.src_addr,
+									       stream_data.group_addr,
+									       stream_data.src_valid,
+									       stream_data.dest_port_bm);
+					IF_ERROR(ret_code);
+				} else {
+					if (stream_data.u4_entry != 0xffff) {
+						dest_port_bm = (~TPM_TRG_UNI_VIRT) & stream_data.dest_port_bm;
+						ret_code = tpm_proc_updt_ipv4_mc_stream(0, stream_id, dest_port_bm);
+						IF_ERROR(ret_code);
+
+						dest_port_bm |= TPM_TRG_UNI_VIRT;
+						ret_code = tpm_proc_updt_ipv4_mc_stream(0, stream_id, dest_port_bm);
+						IF_ERROR(ret_code);
+					}
+				}
+			}
+		}
+	}
+
+	return TPM_OK;
+}
+
+void tpm_proc_mc_vid_remove_ai_bits(tpm_rule_action_t *rule_action,
+				    tpm_src_port_type_t src_port,
+				    tpm_l2_acl_key_t *l2_key,
+				    tpm_error_code_t ret_code)
+{
+	tpm_dir_t dir = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "\n");
+
+	/* Get direction */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+
+	if ((TPM_RC_OK == ret_code) || (TPM_DIR_US == dir)) {
+		/* no need to remove mc_vid */
+		return;
+	}
+
+	if (TPM_ACTION_SPEC_MC_VID & rule_action->pkt_act) {
+		ret_code = tpm_db_mc_vlan_reset_mc_vlan(l2_key->vlan1.vid);
+		/* no need to check if this action failed */
+	}
+
+	return;
+}
+
+tpm_error_code_t tpm_proc_add_mc_vid_cfg_vtu(uint32_t mc_vid, tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config)
+{
+	tpm_error_code_t ret;
+	uint32_t i;
+	uint32_t uni_xlate_enable;
+	uint32_t switch_init;
+	tpm_init_virt_uni_t    virt_uni_info;
+	tpm_src_port_type_t switch_api_port;
+	tpm_mc_vid_port_cfg_t *vir_uni_cfg = NULL;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vid);
+
+	if (tpm_db_switch_init_get(&switch_init))
+		return ERR_GENERAL;
+
+	if (switch_init == 0) {
+		/* do not have switch */
+		TPM_OS_INFO(TPM_PNCL_MOD, "do not have switch, no VTU operation\n");
+		return TPM_RC_OK;
+	}
+
+	uni_xlate_enable = tpm_db_get_mc_per_uni_vlan_xlate();
+	tpm_db_virt_info_get(&virt_uni_info);
+
+
+	for (i = 0; i < TPM_MAX_NUM_UNI_PORTS; i++) {
+		if (TPM_SRC_PORT_UNI_VIRT == mc_vid_uniports_config->mc_vid_port_vids[i].tpm_src_port) {
+			vir_uni_cfg = &(mc_vid_uniports_config->mc_vid_port_vids[i]);
+			continue;
+		}
+		if (TPM_MC_UNI_MODE_EXCLUDE == mc_vid_uniports_config->mc_vid_port_vids[i].mc_uni_port_mode)
+			continue;
+
+		switch_api_port = mc_vid_uniports_config->mc_vid_port_vids[i].tpm_src_port;
+
+		ret = tpm_sw_port_add_vid(0, switch_api_port, mc_vid);
+		if (TPM_RC_OK != ret) {
+			TPM_OS_ERROR(TPM_PNCL_MOD, "add port(%d) into vlan(%d) failed\n", switch_api_port, mc_vid);
+			return ERR_GENERAL;
+		}
+
+		if (uni_xlate_enable) {
+			if (TPM_MC_UNI_MODE_TRANSPARENT == mc_vid_uniports_config->mc_vid_port_vids[i].mc_uni_port_mode) {
+				/* egress mode set to as-is */
+				ret = tpm_sw_set_port_vid_egress_mode(0, switch_api_port, mc_vid, MEMBER_EGRESS_UNMODIFIED);
+			} else {
+				/* egress mode set to un-tag */
+				ret = tpm_sw_set_port_vid_egress_mode(0, switch_api_port, mc_vid, MEMBER_EGRESS_UNTAGGED);
+			}
+		} else {
+			if (TPM_MC_UNI_MODE_STRIP == mc_vid_uniports_config->mc_vid_port_vids[i].mc_uni_port_mode) {
+				/* egress mode set to un-tag */
+				ret = tpm_sw_set_port_vid_egress_mode(0, switch_api_port, mc_vid, MEMBER_EGRESS_UNTAGGED);
+			} else {
+				/* egress mode set to as-is */
+				ret = tpm_sw_set_port_vid_egress_mode(0, switch_api_port, mc_vid, MEMBER_EGRESS_UNMODIFIED);
+			}
+		}
+
+		if (TPM_RC_OK != ret) {
+			TPM_OS_ERROR(TPM_PNCL_MOD, "set port(%d) egress mode failed\n",
+				     switch_api_port);
+			return ERR_GENERAL;
+		}
+
+	}
+
+	if (TPM_VIRT_UNI_DISABLED == virt_uni_info.enabled) {
+		TPM_OS_INFO(TPM_PNCL_MOD, "virtual uni is disabled, do not need to set VTU of uni_4!\n");
+		return TPM_RC_OK;
+	}
+
+	if (uni_xlate_enable) {
+		ret = tpm_sw_port_add_vid(0, TPM_SRC_PORT_UNI_VIRT, mc_vid);
+		if (TPM_RC_OK != ret) {
+			TPM_OS_ERROR(TPM_PNCL_MOD, "add port(%d) into vlan failed\n", TPM_SRC_PORT_UNI_VIRT);
+			return ERR_GENERAL;
+		}
+	} else if (NULL != vir_uni_cfg) {
+		if (TPM_MC_UNI_MODE_EXCLUDE == vir_uni_cfg->mc_uni_port_mode) {
+			/* do not add port into VTU */
+		} else {
+			ret = tpm_sw_port_add_vid(0, TPM_SRC_PORT_UNI_VIRT, mc_vid);
+			if (TPM_RC_OK != ret) {
+				TPM_OS_ERROR(TPM_PNCL_MOD, "add port(%d) into vlan failed\n", TPM_SRC_PORT_UNI_VIRT);
+				return ERR_GENERAL;
+			}
+
+			if (TPM_MC_UNI_MODE_STRIP == vir_uni_cfg->mc_uni_port_mode) {
+				/* egress mode set to un-tag */
+				ret = tpm_sw_set_port_vid_egress_mode(0, TPM_SRC_PORT_UNI_VIRT, mc_vid, MEMBER_EGRESS_UNTAGGED);
+			} else if (TPM_MC_UNI_MODE_TRANSPARENT == vir_uni_cfg->mc_uni_port_mode) {
+				/* egress mode set to as-is */
+				ret = tpm_sw_set_port_vid_egress_mode(0, TPM_SRC_PORT_UNI_VIRT, mc_vid, MEMBER_EGRESS_UNMODIFIED);
+			}
+		}
+	}
+
+	return TPM_RC_OK;
+}
+
+tpm_error_code_t tpm_proc_del_mc_vid_cfg_vtu(uint32_t mc_vid)
+{
+	tpm_error_code_t ret;
+	tpm_db_error_t db_ret;
+	uint32_t vtu_vid;
+	uint32_t i;
+	uint32_t uni_xlate_enable;
+	tpm_mc_vid_port_cfg_t *mc_vid_uniports_config = NULL;
+	uint32_t switch_init;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vid);
+
+	if (tpm_db_switch_init_get(&switch_init))
+		return ERR_GENERAL;
+
+	if (switch_init == 0) {
+		/* do not have switch */
+		TPM_OS_INFO(TPM_PNCL_MOD, "do not have switch, no VTU operation\n");
+		return TPM_RC_OK;
+	}
+
+	uni_xlate_enable = tpm_db_get_mc_per_uni_vlan_xlate();
+
+	db_ret = tpm_db_get_mc_vid_cfg(mc_vid, &mc_vid_uniports_config);
+	if (TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "get db of vlan(%d) failed\n", mc_vid);
+		return ERR_GENERAL;
+	}
+
+	for (i = 0; i < TPM_MAX_NUM_UNI_PORTS; i++) {
+		if (TPM_SRC_PORT_UNI_VIRT == mc_vid_uniports_config[i].tpm_src_port)
+			continue;
+
+		if (TPM_MC_UNI_MODE_EXCLUDE == mc_vid_uniports_config[i].mc_uni_port_mode)
+			continue;
+
+		if (uni_xlate_enable)
+			vtu_vid = mc_vid;
+		else
+			vtu_vid	= mc_vid_uniports_config[i].uni_port_vid;
+
+		ret = tpm_sw_port_del_vid(0, mc_vid_uniports_config[i].tpm_src_port, vtu_vid);
+		if (TPM_RC_OK != ret) {
+			TPM_OS_ERROR(TPM_PNCL_MOD, "del port(%d) into vlan(%d) failed\n",
+				     mc_vid_uniports_config[i].tpm_src_port, vtu_vid);
+			return ERR_GENERAL;
+		}
+	}
+
+	return TPM_RC_OK;
+}
+
+tpm_error_code_t tpm_proc_add_mc_vid_cfg(uint32_t mc_vid, tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config)
+{
+	uint32_t ret;
+	uint32_t i, in_loop;
+	uint32_t out_vid = 0;
+	uint32_t vtu_vid = mc_vid;
+	uint32_t tranparent_port_num = 0;
+	uint32_t ip_ver;
+	uint8_t lpbk_enable = TPM_FALSE;
+	tpm_mc_vid_t mc_vid_cfg_tmp;
+	tpm_mc_vid_port_cfg_t *vir_uni_cfg = NULL;
+	tpm_init_virt_uni_t virt_uni_info;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vid);
+
+	memset(&mc_vid_cfg_tmp, 0, sizeof(mc_vid_cfg_tmp));
+
+	for (i = 0; i < TPM_MAX_NUM_UNI_PORTS; i++) {
+		if (TPM_SRC_PORT_UNI_VIRT == mc_vid_uniports_config->mc_vid_port_vids[i].tpm_src_port) {
+			vir_uni_cfg = &mc_vid_uniports_config->mc_vid_port_vids[i];
+			continue;
+		}
+
+		if (TPM_MC_UNI_MODE_TRANSPARENT == mc_vid_uniports_config->mc_vid_port_vids[i].mc_uni_port_mode)
+			tranparent_port_num++;
+
+		/* do not care TRANSPARENT and TRIP */
+		if (TPM_MC_UNI_MODE_TRANSLATE != mc_vid_uniports_config->mc_vid_port_vids[i].mc_uni_port_mode)
+			continue;
+
+		/* here got a translate */
+		for (in_loop = 0; in_loop < mc_vid_cfg_tmp.vid_num; in_loop++) {
+			if (mc_vid_uniports_config->mc_vid_port_vids[i].uni_port_vid ==
+			    mc_vid_cfg_tmp.mc_vid_port[in_loop].mc_vid) {
+				mc_vid_cfg_tmp.mc_vid_port[in_loop].port_bm |=
+				(TPM_TRG_UNI_0 << (mc_vid_uniports_config->mc_vid_port_vids[i].tpm_src_port - TPM_SRC_PORT_UNI_0));
+				break;
+			}
+		}
+
+		if (mc_vid_cfg_tmp.vid_num == in_loop) {
+			mc_vid_cfg_tmp.mc_vid_port[in_loop].port_bm =
+				(TPM_TRG_UNI_0 << (mc_vid_uniports_config->mc_vid_port_vids[i].tpm_src_port - TPM_SRC_PORT_UNI_0));
+			mc_vid_cfg_tmp.mc_vid_port[in_loop].mc_vid =
+				mc_vid_uniports_config->mc_vid_port_vids[i].uni_port_vid;
+			mc_vid_cfg_tmp.vid_num++;
+		}
+	}
+
+	/* validation */
+	if (!tpm_db_get_mc_per_uni_vlan_xlate()) {
+		/* all the ports should have the same xlate, or strip */
+		if (mc_vid_cfg_tmp.vid_num > 1) {
+			TPM_OS_ERROR(TPM_PNCL_MOD,
+				     "with mc_per_uni_vlan_xlate disabled, all the ports should have the same xlate\n");
+			return ERR_GENERAL;
+		}
+
+		/* there should be no transparent and xlate port at the same time */
+		if ((0 != tranparent_port_num) && (0 != mc_vid_cfg_tmp.vid_num)) {
+			TPM_OS_ERROR(TPM_PNCL_MOD,
+				     "with mc_per_uni_vlan_xlate disabled, "\
+				     "there should be no transparent and xlate port at the same time\n");
+			return ERR_GENERAL;
+		}
+
+		if (mc_vid_cfg_tmp.vid_num > 0)
+			vtu_vid = mc_vid_cfg_tmp.mc_vid_port[0].mc_vid;
+
+	}
+
+	ret = tpm_proc_add_mc_vid_cfg_vtu(vtu_vid, mc_vid_uniports_config);
+	if (TPM_RC_OK != ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "set VTU failed, ret: %d\n", ret);
+		return ret;
+	}
+
+	/* add to db */
+	ret = tpm_db_set_mc_vid_cfg(mc_vid, mc_vid_uniports_config);
+	if (TPM_DB_OK != ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "add mc vid xlate to DB failed, ret: %d\n", ret);
+		return ret;
+	}
+
+	if (!tpm_db_get_mc_per_uni_vlan_xlate()) {
+		/* mc_per_uni_vlan_xlate is disabled, do not add xlate PNC rules */
+		return TPM_RC_OK;
+	}
+
+	/* deal with IPV4 to V6 */
+	for (ip_ver = TPM_IP_VER_4; ip_ver < TPM_IP_VER_MAX; ip_ver++) {
+		tpm_db_get_mc_lpbk_enable(ip_ver, &lpbk_enable);
+		if (lpbk_enable == TPM_FALSE)
+			continue;
+		/* first deal with U0 to U3 */
+		for (i = 0; i < mc_vid_cfg_tmp.vid_num; i++) {
+			if (0 == i) {
+				/* first xlate */
+				ret =
+				tpm_proc_mc_set_translation_uni_x_first(ip_ver, mc_vid, mc_vid_cfg_tmp.mc_vid_port[i].mc_vid,
+									mc_vid_cfg_tmp.mc_vid_port[i].port_bm);
+				if (TPM_RC_OK != ret) {
+					TPM_OS_ERROR(TPM_PNCL_MOD, "add mc vid xlate failed, ret: %d\n", ret);
+					return ret;
+				}
+			} else {
+				ret = tpm_proc_mc_set_translation_uni_x_next(ip_ver, mc_vid, mc_vid_cfg_tmp.mc_vid_port[i - 1].mc_vid,
+									     mc_vid_cfg_tmp.mc_vid_port[i].mc_vid,
+									     mc_vid_cfg_tmp.mc_vid_port[i].port_bm);
+
+				if (TPM_RC_OK != ret) {
+					TPM_OS_ERROR(TPM_PNCL_MOD, "add mc vid xlate failed, ret: %d\n", ret);
+					return ret;
+				}
+			}
+		}
+	}
+
+	/* deal with U4 */
+	tpm_db_virt_info_get(&virt_uni_info);
+	if (   (TPM_VIRT_UNI_DISABLED == virt_uni_info.enabled)
+		|| (NULL == vir_uni_cfg)){
+		/* VIRT_UNI_DISABLED, or nothing to do */
+		return TPM_RC_OK;
+	}
+	if (TPM_MC_UNI_MODE_EXCLUDE == vir_uni_cfg->mc_uni_port_mode) {
+		/* not member, nothing to do */
+		return TPM_RC_OK;
+	} else if (TPM_MC_UNI_MODE_TRANSPARENT == vir_uni_cfg->mc_uni_port_mode)
+		out_vid = mc_vid;
+	else if (TPM_MC_UNI_MODE_STRIP == vir_uni_cfg->mc_uni_port_mode)
+		out_vid = 0xffff;
+	else if (TPM_MC_UNI_MODE_TRANSLATE == vir_uni_cfg->mc_uni_port_mode)
+		out_vid = vir_uni_cfg->uni_port_vid;
+
+	for (ip_ver = TPM_IP_VER_4; ip_ver < TPM_IP_VER_MAX; ip_ver++) {
+		tpm_db_get_mc_lpbk_enable(ip_ver, &lpbk_enable);
+		if (lpbk_enable == TPM_FALSE)
+			continue;
+		if (0 == mc_vid_cfg_tmp.vid_num) {
+			/* U4 is the first xlate */
+			ret = tpm_proc_mc_set_translation_max_uni_first(ip_ver, mc_vid, out_vid);
+			if (TPM_RC_OK != ret) {
+				TPM_OS_ERROR(TPM_PNCL_MOD, "add U4 mc vid xlate failed, ret: %d\n", ret);
+				return ret;
+			}
+		} else {
+			ret = tpm_proc_mc_set_translation_max_uni_next(ip_ver, mc_vid, mc_vid_cfg_tmp.mc_vid_port[i - 1].mc_vid, out_vid);
+			if (TPM_RC_OK != ret) {
+				TPM_OS_ERROR(TPM_PNCL_MOD, "add U4 mc vid xlate failed, ret: %d\n", ret);
+				return ret;
+			}
+		}
+	}
+
+	return TPM_RC_OK;
+}
+
+tpm_error_code_t tpm_proc_remove_mc_vid_cfg(uint32_t mc_vid)
+{
+	tpm_error_code_t ret;
+	tpm_db_error_t db_ret;
+
+	ret = tpm_proc_mc_reset_translation(mc_vid);
+	if (TPM_RC_OK != ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "remove VID failed, ret: %d\n", ret);
+		return ret;
+	}
+
+	ret = tpm_proc_del_mc_vid_cfg_vtu(mc_vid);
+	if (TPM_RC_OK != ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "remove VID MTU, ret: %d\n", ret);
+		return ret;
+	}
+
+	db_ret = tpm_db_remove_mc_vid_cfg(mc_vid);
+	if (TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "del mc vid xlate from DB failed, ret: %d\n", db_ret);
+		return ERR_GENERAL;
+	}
+
+	return TPM_RC_OK;
+}
+
+tpm_error_code_t tpm_proc_update_mc_vid_cfg(uint32_t mc_vid, tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config)
+{
+	tpm_error_code_t ret;
+
+	ret = tpm_proc_remove_mc_vid_cfg(mc_vid);
+	if (TPM_RC_OK != ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "remove VID failed, ret: %d\n", ret);
+		return ret;
+	}
+
+	ret = tpm_proc_add_mc_vid_cfg(mc_vid, mc_vid_uniports_config);
+	if (TPM_RC_OK != ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "add VID failed, ret: %d\n", ret);
+		return ret;
+	}
+
+	return TPM_RC_OK;
+}
+
+tpm_error_code_t tpm_proc_set_mc_vid_port_vids(uint32_t owner_id,
+					       uint32_t mc_vid,
+					       tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config)
+{
+	uint32_t ret;
+	int32_t db_ret;
+	uint32_t i;
+	bool already_exist;
+	tpm_src_port_type_t src_port;
+	tpm_init_virt_uni_t virt_uni_info;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "mc_vlan(%d)\n", mc_vid);
+
+	for (src_port = TPM_SRC_PORT_UNI_0; src_port <= TPM_SRC_PORT_UNI_7; src_port++) {
+
+		if (TPM_MC_UNI_MODE_EXCLUDE == mc_vid_uniports_config->mc_vid_port_vids[src_port].mc_uni_port_mode)
+			continue;
+
+		/* if port is valid */
+		if(!tpm_db_eth_port_valid(src_port)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "uni_port(%x) is not valid, should be EXCLUDE mode\n", src_port);
+			return ERR_MC_DST_PORT_INVALID;
+		}
+	}
+
+	/* check vir uni */
+	db_ret = tpm_db_virt_info_get(&virt_uni_info);
+	if (TPM_DB_OK != db_ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "get virt uni cfg failed, ret: %d\n", db_ret);
+		return ERR_GENERAL;
+	}
+	if (    (TPM_VIRT_UNI_DISABLED == virt_uni_info.enabled)
+	     && (TPM_MC_UNI_MODE_EXCLUDE != mc_vid_uniports_config->mc_vid_port_vids[TPM_SRC_PORT_UNI_VIRT].mc_uni_port_mode)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "TPM_TRG_UNI_VIRT is not enabled, should be EXCLUDE mode\n");
+		return ERR_MC_DST_PORT_INVALID;
+	}
+
+	/* if all the ports are TPM_MC_UNI_MODE_EXCLUDE, remove this VID
+	   if this VID already exists, update it.
+	   else add this VID
+	 */
+	already_exist = tpm_db_mc_vid_exist(mc_vid);
+
+	for (i = 0; i < TPM_MAX_NUM_UNI_PORTS; i++) {
+		if (TPM_MC_UNI_MODE_EXCLUDE == mc_vid_uniports_config->mc_vid_port_vids[i].mc_uni_port_mode)
+			continue;
+
+		if (true == already_exist) {
+			/* VID already exists, update it */
+			ret = tpm_proc_update_mc_vid_cfg(mc_vid, mc_vid_uniports_config);
+			if (TPM_RC_OK != ret) {
+				TPM_OS_ERROR(TPM_PNCL_MOD, "update VID failed, ret: %d\n", ret);
+				return ERR_GENERAL;
+			}
+		} else {
+			/* VID not exists, add it */
+			ret = tpm_proc_add_mc_vid_cfg(mc_vid, mc_vid_uniports_config);
+			if (TPM_RC_OK != ret) {
+				TPM_OS_ERROR(TPM_PNCL_MOD, "add VID failed, ret: %d\n", ret);
+				return ERR_GENERAL;
+			}
+		}
+
+		return TPM_RC_OK;
+	}
+
+	/* all the ports are TPM_MC_UNI_MODE_EXCLUDE, remove this VID */
+	if (false == already_exist) {
+		/* VID not exists, error */
+		TPM_OS_ERROR(TPM_PNCL_MOD, "all the ports are TPM_MC_UNI_MODE_EXCLUDE, VID not exists, error\n");
+		return ERR_GENERAL;
+	}
+
+	ret = tpm_proc_remove_mc_vid_cfg(mc_vid);
+	if (TPM_RC_OK != ret) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "VID not exists, error\n");
+		return ERR_GENERAL;
+	}
+
+	return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_multicast_reset()
+*
+* DESCRIPTION:    Main function for reset multicast configurations and shadows.
+*
+* INPUTS:
+*
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_multicast_reset(void)
+{
+    /* reset multicast configuration database:
+	   1. MC VID AI-bits allocation
+	   2. MC VID per-port config
+	   3. IGMP proxy sa addr */
+	tpm_db_mc_cfg_reset();
+
+    /* reset multicast rules database:
+	   1. MC stream table
+	   2. MC mac table
+	   3. MC lpbk table
+	   4. virt_uni entry table */
+	tpm_db_mc_rule_reset();
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_del_l2_prim_acl_rule()
+*
+* DESCRIPTION:    Main function for deleting L2 API rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_l2_prim_acl_rule(uint32_t owner_id, uint32_t rule_idx, uint32_t ext_call)
+{
+
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	ret_code = tpm_proc_del_acl_rule(TPM_L2_PRIM_ACL, owner_id, rule_idx, ext_call);
+	IF_ERROR(ret_code);
+
+	/* release mc AI bits */
+	tpm_db_mc_vlan_reset_ai_bit(rule_idx);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_get_next_valid_rule()
+*
+* DESCRIPTION:    Main function for getting next rule.
+*
+* INPUTS:
+*           All inputs/outputs are same as API call
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_get_next_valid_rule(uint32_t owner_id,
+					      int32_t current_index,
+					      tpm_api_type_t rule_type,
+					      int32_t *next_index,
+					      uint32_t *rule_idx,
+					      tpm_rule_entry_t *tpm_rule)
+{
+	int32_t int_ret_code;
+	uint32_t bi_dir = 0;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_conn_t pnc_con;
+	tpm_api_sections_t api_section;
+
+	if (!next_index || !tpm_rule)
+		return ERR_NULL_POINTER;
+
+	tpm_db_api_section_get_from_api_type(rule_type, &api_section);
+
+	int_ret_code = tpm_db_api_entry_val_get_next(api_section, current_index,
+						     next_index, rule_idx, &bi_dir, tpm_rule, &mod_con, &pnc_con);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_omci_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the OMCI management protocol.
+*                   The API sets the gemportid, the Rx input queue in the CPU, and the
+*                   Tx T-CONT and queue parameters, which are configured in the driver.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* gem_port           - for OMCI Rx frames - the gem port wherefrom the OMCI frames are received.
+* cpu_rx_queue       - for OMCI Rx frames - the CPU rx queue number.
+* tcont_num          - for OMCI Tx frames - the TCONT number where to send the OMCI frames.
+* cpu_tx_queue       - for OMCI Tx frames - the CPU tx queue number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_omci_add_channel(uint32_t owner_id,
+					   tpm_gem_port_key_t gem_port,
+					   uint32_t cpu_rx_queue,
+					   tpm_trg_port_type_t tcont_num,
+					   uint32_t cpu_tx_queue)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t pnc_entry;
+	tpm_db_pnc_range_t range_data;
+	int32_t int_ret_code;
+	tpm_error_code_t ret_code;
+	uint32_t valid, rxq, txq, txp;
+	uint16_t gem;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "owner(%d),gemport(%d),rx_q(%d),tcont(%d),tx_q(%d)\n",
+		     owner_id, gem_port, cpu_rx_queue, tcont_num, cpu_tx_queue);
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	tpm_db_omci_channel_get(&valid, &gem, &rxq, &txq, &txp);
+	if (valid)
+		IF_ERROR(ERR_MNGT_CREATE_DUPLICATE_CHANNEL);
+
+	ret_code = tpm_owner_id_check(TPM_API_MGMT, owner_id);
+	IF_ERROR(ret_code);
+
+	/* build TCAM */
+	pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_GEMPORT;
+	pnc_data.pncl_tcam.l3_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv6_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+	pnc_data.pncl_tcam.add_info_mask = 0;
+	pnc_data.pncl_tcam.add_info_data = 0;
+	/* src port */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	pnc_data.pncl_tcam.port_ids = gmac_bm;
+	pnc_data.pncl_tcam.pkt_key.l2_key.gem_port = gem_port;
+	pnc_data.pncl_tcam.lu_id = 0;
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
+
+	/* Build SRAM */
+	pnc_data.pncl_sram.next_lu_id = 0;
+	pnc_data.pncl_sram.next_lu_off_reg = 0;
+	pnc_data.pncl_sram.next_offset.offset_base = 0;
+	pnc_data.pncl_sram.next_offset.offset_sub.l2_subf = 0;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.pnc_queue = cpu_rx_queue;
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_TXP | TPM_PNCL_SET_RX_SPECIAL;
+	pnc_data.pncl_sram.mh_reg.mh_set = TPM_FALSE;
+	pnc_data.pncl_sram.mh_reg.mh_reg = 0;
+	pnc_data.pncl_sram.add_info_data = 0;
+	pnc_data.pncl_sram.add_info_mask = 0;
+	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_OTHER;
+	pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_OTHER;
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+	pnc_data.pncl_sram.flow_id_sub.mod_cmd = 0;
+	pnc_data.pncl_sram.flow_id_sub.gem_port = 0;
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_MNGMT_DS, &range_data);
+	IF_ERROR(int_ret_code);
+	pnc_entry = range_data.pnc_range_conf.range_start;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_entry(%d)\n", pnc_entry);
+	/* Decrease number of free entries in pnc_range */
+	int_ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_MNGMT_DS);
+	IF_ERROR(int_ret_code);
+	int_ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	{
+		char cmd[64];
+		uint32_t tcontid = 0;
+
+		if (tcont_num == TPM_TRG_TCONT_0)
+			tcontid = 0;
+		else if (tcont_num == TPM_TRG_TCONT_1)
+			tcontid = 1;
+		else if (tcont_num == TPM_TRG_TCONT_2)
+			tcontid = 2;
+		else if (tcont_num == TPM_TRG_TCONT_3)
+			tcontid = 3;
+		else if (tcont_num == TPM_TRG_TCONT_4)
+			tcontid = 4;
+		else if (tcont_num == TPM_TRG_TCONT_5)
+			tcontid = 5;
+		else if (tcont_num == TPM_TRG_TCONT_6)
+			tcontid = 6;
+		else if (tcont_num == TPM_TRG_TCONT_7)
+			tcontid = 7;
+
+		/*sprintf(cmd, "echo %d  > /sys/devices/platform/neta/pon/omci_gp", gem_port); */
+		pnc_mh_omci(gem_port, 0x0FFF, cpu_rx_queue);
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " %s\n", cmd);
+	}
+
+	/* update database */
+	tpm_db_omci_channel_set(gem_port, cpu_rx_queue, cpu_tx_queue, tcont_num);
+
+	return(TPM_RC_OK);
+
+}
+
+/*******************************************************************************
+* tpm_proc_omci_del_channel()
+*
+* DESCRIPTION:      Deletes an existing communication channel for the OMCI management protocol.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_omci_del_channel(uint32_t owner_id)
+{
+	int32_t ret_code;
+	tpm_db_pnc_conn_t pnc_con;
+	uint32_t oam_configured, cpu_rx_queue, cpu_tx_queue, llid_num;
+	tpm_db_pnc_range_t range_data;
+
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d)\n", owner_id);
+
+	ret_code = tpm_owner_id_check(TPM_API_MGMT, owner_id);
+	IF_ERROR(ret_code);
+
+	tpm_db_oam_channel_get(&oam_configured, &cpu_rx_queue, &cpu_tx_queue, &llid_num);
+	if (!oam_configured)
+		IF_ERROR(ERR_MNGT_DEL_CHANNEL_INVALID);
+
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_MNGMT_DS, &range_data);
+	IF_ERROR(ret_code);
+
+	pnc_con.num_pnc_ranges = 1;
+	pnc_con.pnc_conn_tbl[0].pnc_range = TPM_PNC_MNGMT_DS;
+	pnc_con.pnc_conn_tbl[0].pnc_index = range_data.pnc_range_conf.range_start;
+
+	/* Delete PNC Entry */
+	ret_code = tpm_proc_pnc_con_del(&pnc_con);
+	IF_ERROR(ret_code);
+
+	tpm_db_omci_channel_remove();
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_oam_epon_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the OAM EPON management protocol.
+*                   The API sets the Rx input queue in the CPU, and the
+*                   Tx T-CONT and queue parameters, which are configured in the driver.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* cpu_rx_queue       - for OAM (EPON) Rx frames - the CPU rx queue number.
+* llid_num           - for OAM (EPON)Tx frames - the LLID number where to send the OMCI frames.
+* cpu_tx_queue       - for OAM (EPON) Tx frames - the CPU tx queue number.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_oam_epon_add_channel(uint32_t owner_id, uint32_t cpu_rx_queue, tpm_trg_port_type_t llid_num)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t pnc_entry;
+	tpm_db_pnc_range_t range_data;
+	int32_t int_ret_code;
+	tpm_error_code_t ret_code;
+	uint32_t valid, rxq, txq, txp;
+	uint16_t gem;
+	uint32_t q_size;
+	uint32_t dummy_cpu_tx_queue = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "owner(%d), rx_q(%d),llid(%d),tx_q(%d)\n",
+		     owner_id, cpu_rx_queue, llid_num, dummy_cpu_tx_queue);
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	tpm_db_omci_channel_get(&valid, &gem, &rxq, &txq, &txp);
+	if (valid)
+		IF_ERROR(ERR_MNGT_CREATE_DUPLICATE_CHANNEL);
+
+	ret_code = tpm_owner_id_check(TPM_API_MGMT, owner_id);
+	IF_ERROR(ret_code);
+
+	/* validate cpu_rx_queue - should be an existing queue of PON MAC - defined previously */
+	tpm_db_gmac_rx_q_conf_get(TPM_ENUM_PMAC, cpu_rx_queue, &valid, &q_size);
+	if (!valid)
+		TPM_OS_WARN(TPM_INIT_MOD, "OAM CPU RX queue is not valid: queue(%d) \n", cpu_rx_queue);
+
+	/* build TCAM */
+	pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_ETYPE;
+	pnc_data.pncl_tcam.l3_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv6_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+	pnc_data.pncl_tcam.add_info_mask = 0;
+	pnc_data.pncl_tcam.add_info_data = 0;
+
+	/* src port */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	pnc_data.pncl_tcam.port_ids = gmac_bm;
+	pnc_data.pncl_tcam.pkt_key.l2_key.ether_type = 0x8809;
+	pnc_data.pncl_tcam.lu_id = 0;
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
+
+	/* Build SRAM */
+	pnc_data.pncl_sram.next_lu_id = 0;
+	pnc_data.pncl_sram.next_lu_off_reg = 0;
+	pnc_data.pncl_sram.next_offset.offset_base = 0;
+	pnc_data.pncl_sram.next_offset.offset_sub.l2_subf = 0;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.pnc_queue = cpu_rx_queue;
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_TXP | TPM_PNCL_SET_RX_SPECIAL;
+	pnc_data.pncl_sram.mh_reg.mh_set = TPM_FALSE;
+	pnc_data.pncl_sram.mh_reg.mh_reg = 0;
+	pnc_data.pncl_sram.add_info_data = 0;
+	pnc_data.pncl_sram.add_info_mask = 0;
+	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_OTHER;
+	pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_OTHER;
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+	pnc_data.pncl_sram.flow_id_sub.mod_cmd = 0;
+	pnc_data.pncl_sram.flow_id_sub.gem_port = 0;
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_MNGMT_DS, &range_data);
+	IF_ERROR(int_ret_code);
+	pnc_entry = range_data.pnc_range_conf.range_start;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_entry(%d)\n", pnc_entry);
+
+	/* Decrease number of free entries in pnc_range */
+	int_ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_MNGMT_DS);
+	IF_ERROR(int_ret_code);
+
+	int_ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	{
+		uint32_t llid = 0;
+
+		if (llid_num == TPM_TRG_LLID_0)
+			llid = 0;
+		else if (llid_num == TPM_TRG_LLID_1)
+			llid = 1;
+		else if (llid_num == TPM_TRG_LLID_2)
+			llid = 2;
+		else if (llid_num == TPM_TRG_LLID_3)
+			llid = 3;
+		else if (llid_num == TPM_TRG_LLID_4)
+			llid = 4;
+		else if (llid_num == TPM_TRG_LLID_5)
+			llid = 5;
+		else if (llid_num == TPM_TRG_LLID_6)
+			llid = 6;
+		else if (llid_num == TPM_TRG_LLID_7)
+			llid = 7;
+
+		pnc_eoam(cpu_rx_queue);
+	}
+
+	/* update database */
+	tpm_db_oam_channel_set(cpu_rx_queue, dummy_cpu_tx_queue, llid_num);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_loop_detect_add_channel()
+*
+* DESCRIPTION:      Establishes a communication channel for the loop detection management protocol.
+*                   The API sets the Rx input queue in the CPU, and the
+*                   Tx T-CONT and queue parameters, which are configured in the driver.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_loop_detect_add_channel(uint32_t owner_id)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t pnc_entry;
+	tpm_db_pnc_range_t range_data;
+	int32_t int_ret_code;
+	tpm_error_code_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "owner(%d)\n", owner_id);
+
+	ret_code = tpm_owner_id_check(TPM_API_MGMT, owner_id);
+	IF_ERROR(ret_code);
+
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+
+	/* build TCAM */
+	pnc_data.pncl_tcam.l2_parse_bm = TPM_L2_PARSE_ONE_VLAN_TAG | TPM_L2_PARSE_ETYPE;
+	pnc_data.pncl_tcam.l3_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv6_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+	pnc_data.pncl_tcam.add_info_mask = 0;
+	pnc_data.pncl_tcam.add_info_data = 0;
+
+	/* src port */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_UNI_ANY, &gmac_bm);
+	pnc_data.pncl_tcam.port_ids = gmac_bm;
+	pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid = 0x8100;
+	pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid_mask = 0xffff;
+	pnc_data.pncl_tcam.pkt_key.l2_key.ether_type = 0xA0A0;
+	pnc_data.pncl_tcam.lu_id = 0;
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
+
+	/* Build SRAM */
+	pnc_data.pncl_sram.next_lu_id = 0;
+	pnc_data.pncl_sram.next_lu_off_reg = 0;
+	pnc_data.pncl_sram.next_offset.offset_base = 0;
+	pnc_data.pncl_sram.next_offset.offset_sub.l2_subf = 0;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.pnc_queue = 0;	/*send to queue 0 by default */
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_TXP | TPM_PNCL_SET_RX_SPECIAL;
+	pnc_data.pncl_sram.mh_reg.mh_set = TPM_FALSE;
+	pnc_data.pncl_sram.mh_reg.mh_reg = 0;
+	pnc_data.pncl_sram.add_info_data = 0;
+	pnc_data.pncl_sram.add_info_mask = 0;
+	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_OTHER;
+	pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_OTHER;
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+	pnc_data.pncl_sram.flow_id_sub.mod_cmd = 0;
+	pnc_data.pncl_sram.flow_id_sub.gem_port = 0;
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_LOOP_DET_US, &range_data);
+	IF_ERROR(int_ret_code);
+	pnc_entry = range_data.pnc_range_conf.range_start;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_entry(%d)\n", pnc_entry);
+	int_ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_LOOP_DET_US);
+	IF_ERROR(int_ret_code);
+	int_ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_oam_epon_del_channel()
+*
+* DESCRIPTION:      Deletes an existing communication channel for the OAM EPON management protocol.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_oam_epon_del_channel(uint32_t owner_id)
+{
+	int32_t ret_code;
+	tpm_db_pnc_conn_t pnc_con;
+	uint32_t oam_configured, cpu_rx_queue, cpu_tx_queue, llid_num;
+	tpm_db_pnc_range_t range_data;
+
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d)\n", owner_id);
+
+	ret_code = tpm_owner_id_check(TPM_API_MGMT, owner_id);
+	IF_ERROR(ret_code);
+
+	tpm_db_oam_channel_get(&oam_configured, &cpu_rx_queue, &cpu_tx_queue, &llid_num);
+	if (!oam_configured)
+		IF_ERROR(ERR_MNGT_DEL_CHANNEL_INVALID);
+
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_MNGMT_DS, &range_data);
+	IF_ERROR(ret_code);
+
+	pnc_con.num_pnc_ranges = 1;
+	pnc_con.pnc_conn_tbl[0].pnc_range = TPM_PNC_MNGMT_DS;
+	pnc_con.pnc_conn_tbl[0].pnc_index = range_data.pnc_range_conf.range_start;
+
+	/* Delete PNC Entry */
+	ret_code = tpm_proc_pnc_con_del(&pnc_con);
+	IF_ERROR(ret_code);
+
+	tpm_db_oam_channel_remove();
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_oam_loopback_add_channel ()
+*
+* DESCRIPTION:      Establishes a communication channel for the OAM loopback.
+*
+*
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_oam_loopback_add_channel(uint32_t owner_id)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t pnc_entry, pnc_stop_entry, api_rng_entries;
+	tpm_db_pnc_range_t range_data;
+	int32_t int_ret_code;
+	tpm_error_code_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "owner(%d)\n", owner_id);
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	ret_code = tpm_owner_id_check(TPM_API_MGMT, owner_id);
+	IF_ERROR(ret_code);
+
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+
+	/* build TCAM */
+	pnc_data.pncl_tcam.l2_parse_bm = 0;
+	pnc_data.pncl_tcam.l3_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv6_parse_bm = 0;
+	pnc_data.pncl_tcam.ipv4_parse_bm = 0;
+	pnc_data.pncl_tcam.add_info_mask = 0;
+	pnc_data.pncl_tcam.add_info_data = 0;
+
+	/* src port */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	pnc_data.pncl_tcam.port_ids = gmac_bm;
+	pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid = 0;
+	pnc_data.pncl_tcam.pkt_key.l2_key.vlan1.tpid_mask = 0;
+	pnc_data.pncl_tcam.pkt_key.l2_key.ether_type = 0;
+	pnc_data.pncl_tcam.lu_id = 0;
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
+
+	/* Build SRAM */
+	pnc_data.pncl_sram.next_lu_id = 0;
+	pnc_data.pncl_sram.next_lu_off_reg = 0;
+	pnc_data.pncl_sram.next_offset.offset_base = 0;
+	pnc_data.pncl_sram.next_offset.offset_sub.l2_subf = 0;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.pnc_queue = 1;	/*send to queue 1 by default */
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD | TPM_PNCL_SET_TXP;
+	pnc_data.pncl_sram.mh_reg.mh_set = TPM_FALSE;
+	pnc_data.pncl_sram.mh_reg.mh_reg = 0;
+	pnc_data.pncl_sram.add_info_data = 0;
+	pnc_data.pncl_sram.add_info_mask = 0;
+	pnc_data.pncl_sram.l3_type = TPM_PNCL_L3_OTHER;
+	pnc_data.pncl_sram.l4_type = TPM_PNCL_L4_OTHER;
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_PMAC0;
+	pnc_data.pncl_sram.flow_id_sub.mod_cmd = 0;
+	pnc_data.pncl_sram.flow_id_sub.gem_port = 0;
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_L2_MAIN, &range_data);
+	IF_ERROR(int_ret_code);
+	/*rule 1 is special for OAM loopback. */
+	pnc_entry = range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_start;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pnc_entry(%d)\n", pnc_entry);
+
+	int_ret_code = tpm_db_api_section_num_entries_get(TPM_L2_PRIM_ACL, &api_rng_entries);
+	IF_ERROR(int_ret_code);
+
+	if (api_rng_entries > 0) {
+		pnc_stop_entry = pnc_entry + api_rng_entries - 1;
+		int_ret_code = tpm_pncl_entry_insert(pnc_entry, pnc_stop_entry, &pnc_data);
+		IF_ERROR(int_ret_code);
+	} else {
+		int_ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+		IF_ERROR(int_ret_code);
+	}
+
+	int_ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_L2_MAIN);
+	IF_ERROR(int_ret_code);
+
+	/*update datebase */
+	tpm_db_oam_loopback_channel_set();
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_oam_loopback_del_channel ()
+*
+* DESCRIPTION:      Deletes an existing communication channel for the OAM loopback.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_oam_loopback_del_channel(uint32_t owner_id)
+{
+
+	int32_t ret_code;
+	tpm_db_pnc_conn_t pnc_con;
+	uint32_t oam_loopback_configured;
+	tpm_db_pnc_range_t range_data;
+
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d)\n", owner_id);
+
+	ret_code = tpm_owner_id_check(TPM_API_MGMT, owner_id);
+	IF_ERROR(ret_code);
+
+	tpm_db_oam_loopback_state_get(&oam_loopback_configured);
+	if (!oam_loopback_configured)
+		IF_ERROR(ERR_MNGT_DEL_CHANNEL_INVALID);
+
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_L2_MAIN, &range_data);
+	IF_ERROR(ret_code);
+
+	pnc_con.num_pnc_ranges = 1;
+	pnc_con.pnc_conn_tbl[0].pnc_range = TPM_PNC_L2_MAIN;
+	pnc_con.pnc_conn_tbl[0].pnc_index = range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_start;
+
+	ret_code = tpm_proc_pnc_con_del(&pnc_con);
+	IF_ERROR(ret_code);
+
+	tpm_db_oam_loopback_channel_remove();
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_l3_check()
+*
+* DESCRIPTION:      The function checks consistency of the tpm_proc_add_l3_type_acl_rule params..
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+* l3_key             - Structure for PPPoE proto or ether type. In order to define a rule for
+*                      any ether type, the ether type value should be set to 0xFFFF
+* action_drop        - If this stage is dropping the packet.
+* next_phase         - Set the next parsing stage for the packet.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_l3_check(uint32_t owner_id,
+				       tpm_src_port_type_t src_port,
+				       uint32_t rule_num,
+				       tpm_parse_fields_t parse_rule_bm,
+				       tpm_parse_flags_t parse_flags_bm,
+				       tpm_l3_type_key_t *l3_key,
+				       tpm_pkt_frwd_t *pkt_frwd,
+				       tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_dir_t dir;
+	tpm_db_pon_type_t pon_type;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_pkt_mod_bm_t pkt_mod_bm = 0;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Check Source Port */
+	ret_code = tpm_proc_src_port_check(src_port);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_SRC_PORT_INVALID);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Check parse_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_L3_TYPE_ACL_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_L3_TYPE_ACL_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check necessary pointers are valid */
+	ret_code =
+	tpm_proc_check_missing_data(rule_action, NULL /*pkt_mod */ , pkt_frwd, (void *)l3_key, rule_action->pkt_act,
+				    parse_rule_bm);
+	IF_ERROR(ret_code);
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_L3_TYPE, owner_id);
+	IF_ERROR(ret_code);
+
+	/* Check rule_num, and api_section is active */
+	ret_code = tpm_proc_add_api_ent_check(TPM_L3_TYPE_ACL, TPM_RANGE_TYPE_ACL, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	/* Check forwarding rule, currently only support STAGE_DONE */
+	if (rule_action->next_phase != STAGE_IPv4 && rule_action->next_phase != STAGE_IPv6_NH &&
+	    rule_action->next_phase != STAGE_IPv6_GEN && rule_action->next_phase != STAGE_DONE &&
+	    rule_action->next_phase != STAGE_CTC_CM) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, &pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_L3_TYPE_ACL_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	if (rule_action->next_phase == STAGE_CTC_CM) {
+		if (!tpm_ctc_cm_l3_rule2cm_sram(parse_flags_bm, rule_action)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "next stage is CTC_CM, parse_flag must be MTM_FALSE or CTC CM is disabled\n");
+			return(ERR_NEXT_PHASE_INVALID);
+		}
+		if (FROM_WAN(src_port)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "next stage is CTC_CM, Src Port can not be WAN\n");
+			return(ERR_SRC_PORT_INVALID);
+		}
+		if ((parse_rule_bm & TPM_L2_PARSE_ETYPE) &&
+			(l3_key->ether_type_key == 0x0800)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "next stage is CTC_CM, ETY can not be IPv4\n");
+			return(ERR_ACTION_INVALID);
+		}
+		if ((parse_rule_bm & TPM_L2_PARSE_PPP_PROT) &&
+			(l3_key->pppoe_key.ppp_proto == 0x0021)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "next stage is CTC_CM, ETY can not be IPv4 (over PPPoE)\n");
+			return(ERR_ACTION_INVALID);
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_l3_tcam_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* src_port          - packet source port
+* dir               - Packet direction
+* rule_num          - API rule number
+* l3_key            - layer2 key data
+* parse_rule_bm     - Parse rules bitmap
+* parse_flags_bm    - Parse flags in prim ACL rule
+* rule_action       - rule action of this rule
+* OUTPUTS:
+* l3_tcam_data      - Logical TCAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_l3_tcam_build(tpm_src_port_type_t src_port,
+			       tpm_dir_t dir,
+			       uint32_t rule_num,
+			       tpm_l3_type_key_t *l3_key,
+			       tpm_parse_fields_t parse_rule_bm,
+			       tpm_parse_flags_t parse_flags_bm,
+			       tpm_rule_action_t *rule_action,
+			       tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t src_port_field;
+	long long parse_int_flags_bm = 0;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) parse_rule_bm(%d) \n",
+		     src_port, dir, rule_num, parse_rule_bm);
+
+	/* L3 Parsing, according to bm in param */
+	tcam_data->l3_parse_bm = parse_rule_bm;
+	/* If PPPoe, fill in pppoe_ses ethertype, incase user forgot */
+	if (parse_rule_bm & (TPM_L2_PARSE_PPPOE_SES | TPM_L2_PARSE_PPP_PROT)) {
+		l3_key->ether_type_key = ETH_P_PPP_SES;
+		tcam_data->l3_parse_bm |= TPM_L2_PARSE_ETYPE;
+	}
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port))
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+
+	/* set CTC CnM */
+	if(tpm_ctc_cm_l3_rule2cm_tcam(parse_flags_bm, l3_key, rule_action)) {
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+
+	/* Parse the AI flag bits */
+	src_port_field.src_port = src_port;
+	tpm_proc_parse_flag_ai_tcam_build(&src_port_field, parse_flags_bm, parse_int_flags_bm, &(tcam_data->add_info_data),
+					  &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	if (l3_key) {
+		memcpy(&(tcam_data->pkt_key.l3_key.ether_type_key), &l3_key->ether_type_key,
+		       sizeof(tpm_ether_type_key_t));
+		memcpy(&(tcam_data->pkt_key.l3_key.pppoe_key), &l3_key->pppoe_key, sizeof(tpm_pppoe_key_t));
+	}
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_ETH_TYPE, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_l3_sram_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* src_port          - packet source port
+* dir               - Packet direction
+* rule_num          - API rule number
+* pon_type          - WAN technology
+* action_drop       - drop or not
+* parse_flags_bm    - Parse flags in prim ACL
+* next_phase        - next stage
+*
+* OUTPUTS:
+* l3_sram_data      - Logical SRAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_l3_sram_build(tpm_src_port_type_t src_port,
+			       tpm_dir_t dir,
+			       uint32_t rule_num,
+			       uint8_t is_pppoe,
+			       tpm_db_pon_type_t pon_type,
+			       tpm_pkt_frwd_t *pkt_frwd,
+			       tpm_rule_action_t *rule_action,
+			       tpm_parse_flags_t parse_flags_bm,
+			       tpm_pncl_sram_data_t *sram_data)
+{
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_ai_vectors_t src_port_field;
+	long long int_pkt_act = 0;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), dir(%d), rule_num(%d) \n", src_port, dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Set pppoe_bit */
+	if (is_pppoe == TPM_TRUE) {
+		int_pkt_act |= TPM_ACTION_SET_PPPOE;
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_PPPOE;
+	} else
+		int_pkt_act |= TPM_ACTION_UNSET_PPPOE;
+
+	/* Set AI Bits */
+	src_port_field.src_port = src_port;
+	/* if L3 is IPv6, reset AI NH2_lu */
+	if (STAGE_IPv6_NH == rule_action->next_phase)
+		int_pkt_act |= TPM_ACTION_UNSET_NH2_ITER;
+	else if (STAGE_CTC_CM == rule_action->next_phase)
+		int_pkt_act |= TPM_ACTION_UNSET_CNM_IPV4 | TPM_ACTION_UNSET_IPV4_PRE_KEY;
+
+	tpm_proc_static_ai_sram_build(&src_port_field,
+				      rule_action->pkt_act, int_pkt_act, &(sram_data->add_info_data), &(sram_data->add_info_mask));
+
+	/* Default, don't set MH */
+	sram_data->mh_reg.mh_reg = 0;
+
+	/* Update L3_offset_register with etype/pppoe length */
+	sram_data->shift_updt_reg = 0;	/* update reg 0 */
+	sram_data->next_offset.offset_base = TPM_PNCL_L3_OFFSET;
+	sram_data->next_offset.offset_sub.l3_subf = 0xffff;	/* End of Ether_type/pppoe parsing */
+
+	if (rule_action->next_phase == STAGE_DONE) {
+		tpm_proc_setstage_done(rule_action, sram_data);
+
+		/* Set L3, L4 to OTHER */
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_L3 | TPM_PNCL_SET_L4);
+		sram_data->l3_type = TPM_PNCL_L3_OTHER;
+		sram_data->l4_type = TPM_PNCL_L4_OTHER;
+	} else if ((rule_action->next_phase == STAGE_IPv4) || (rule_action->next_phase == STAGE_IPv6_NH)) {
+		/* next lookup at reg0 */
+		sram_data->next_lu_off_reg = 0;
+
+		if (rule_action->next_phase == STAGE_IPv6_NH) {
+			ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_NH, &range_conf);
+			IF_ERROR(ret_code);
+			sram_data->l3_type = TPM_PNCL_L3_IPV6;
+			sram_data->sram_updt_bm |= TPM_PNCL_SET_L3;
+		}
+		if (rule_action->next_phase == STAGE_IPv4) {
+			ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_MAIN, &range_conf);
+			IF_ERROR(ret_code);
+			/* Note: l3_type cannot be set, since ipv4_fragmentation is not known yet*/
+		}
+		sram_data->next_lu_id = range_conf.base_lu_id;
+	} else if (rule_action->next_phase == STAGE_CTC_CM) {
+		/* next lookup at reg0 */
+		sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+		sram_data->next_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+		sram_data->next_offset.offset_sub.l2_subf = 0;
+		sram_data->next_lu_off_reg = TPM_PNC_CNM_L2_REG;
+
+		/* Set L3, L4 to OTHER */
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_L3 | TPM_PNCL_SET_L4);
+		sram_data->l3_type = TPM_PNCL_L3_OTHER;
+		sram_data->l4_type = TPM_PNCL_L4_OTHER;
+
+		/* set next loopup id */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_MAIN, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " next phase not supported (%d)\n", rule_action->next_phase);
+		return(TPM_FAIL);
+	}
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_l3_type_acl_rule()
+*
+* DESCRIPTION:      Creates a new L3 type (ether type of pppoe proto) processing ACL.
+*                   It is used for operations that are not possible to be performed
+*                   in a single ACL or to ease the primary ACL processing
+*                   (as a helper of the primary L2 ACL).
+*                   The L3 type ACL is optional.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_num           - Entry index to be added in the current ACL
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+* parse_flags_bm     - Bitmap containing the significant flags result of the primary ACL filtering.
+* l3_key             - Structure for PPPoE proto or ether type. In order to define a rule for
+*                      any ether type, the ether type value should be set to 0xFFFF
+* action_drop        - If this stage is dropping the packet.
+* next_phase         - Set the next parsing stage for the packet.
+*
+* OUTPUTS:
+*  rule_idx         - Unique rule identification number, which is used when deleting the rule.
+*                     (this is not the rule_num)
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_l3_type_acl_rule(uint32_t owner_id,
+					       tpm_src_port_type_t src_port,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l3_type_key_t *l3_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0;
+	uint8_t is_pppoe = TPM_FALSE;
+	tpm_dir_t dir = 0;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	tpm_api_lu_conf_t lu_conf;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d)\n", owner_id, src_port, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_l3_check(owner_id, src_port, rule_num, parse_rule_bm,
+					 parse_flags_bm, l3_key, pkt_frwd, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Get direction */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_L3_TYPE_ACL, &range_id);
+
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_l3_tcam_build(src_port, dir, rule_num, l3_key, parse_rule_bm,
+					      parse_flags_bm, rule_action, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	if (pnc_data.pncl_tcam.pkt_key.l3_key.ether_type_key == ETH_P_PPP_SES)
+		is_pppoe = TPM_TRUE;
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_l3_sram_build(src_port, dir, rule_num, is_pppoe, pon_type, pkt_frwd,
+					      rule_action, parse_flags_bm, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	/*** Insert the PNC Entry ***/
+	tpm_proc_create_acl_pnc_entry(TPM_L3_TYPE_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+	IF_ERROR(int_ret_code);
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	api_data.l3_type_key.src_port = src_port;
+	api_data.l3_type_key.parse_rule_bm = parse_rule_bm;
+	api_data.l3_type_key.parse_flags_bm = parse_flags_bm;
+	memcpy(&(api_data.l3_type_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+	if (l3_key)
+		memcpy(&(api_data.l3_type_key.l3_key), l3_key, sizeof(tpm_l3_type_key_t));
+
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.l3_type_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.l3_type_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	/* Set API modification data */
+	tpm_proc_set_api_moddata(rule_action->pkt_act, TPM_INVALID_GMAC	/*DO NOT SUPPORT L3 MOD!! */ , &mod_con,
+				 mod_entry);
+
+	/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+	if (rule_num < api_rng_entries) {
+		int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_L3_TYPE_ACL, rule_num, (api_rng_entries - 1));
+		IF_ERROR(int_ret_code);
+	}
+
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_L3_TYPE_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Set aging counter group nunmber and msk */
+	int_ret_code = tpm_db_pnc_get_lu_conf(TPM_PNC_ETH_TYPE, &lu_conf);
+	IF_ERROR(int_ret_code);
+	tpm_tcam_set_lu_mask(pnc_entry, (int32_t) lu_conf.lu_mask);
+	tpm_tcam_set_cntr_group(pnc_entry, (int32_t) lu_conf.cntr_grp);
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_del_l3_type_acl_rule()
+*
+* DESCRIPTION:      Deletes an existing ethernet type or PPPoE proto access-list entry .
+*                   Any of the existing access-list entries may be deleted. The src_port parameter
+*                   determines if the rule to be deleted belongs to the upstream access-list
+*                   or the downstream access-list. All parameters are compulsory. If the rule number
+*                   does not match the internally stored src_port and parsing key
+*                   (parse_rule_bm and l3_key), the API will return an error.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* src_port           - The packet originating source port. The parameter has a double function:
+*                       . The source port is part of the rules parsing key.
+*                       . The source port determines if the acl entry being
+*                         created is for the upstream acl or the downstream acl.
+*                      In case of an upstream entry, the parameter determines if the packet
+*                      arrives from a specific LAN port or ANY LAN port.
+* rule_idx           - Unique rule idenitifcation number specifying the rule to be deleted.
+* parse_rule_bm      - Bitmap containing the significant flags for parsing fields of the packet.
+* l3_key             - Information to create a parsing key for PPPoE proto or Ethernet type key.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_l3_type_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call)
+{
+
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	ret_code = tpm_proc_del_acl_rule(TPM_L3_TYPE_ACL, owner_id, rule_idx, ext_call);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_erase_section()
+*
+* DESCRIPTION:      Erases a section per an application group.
+*
+* INPUTS:
+* owner_id           - APP owner id  should be used for all API calls.
+* api_type          - the API group area to be deleted.
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_erase_section(uint32_t owner_id, tpm_api_type_t api_type)
+{
+	tpm_error_code_t ret_code;
+	tpm_api_sections_t api_section;
+	int32_t next_idx = 0, cur_idx = -1;
+	uint32_t rule_idx, rule_num, dummy_idx, bi_dir;
+	tpm_rule_entry_t tpm_rule;
+	tpm_db_pnc_conn_t pnc_con;
+	tpm_db_mod_conn_t mod_con;
+	tpm_rule_entry_t api_data;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) api_type(%d)\n", owner_id, api_type);
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(api_type, owner_id);
+	IF_ERROR(ret_code);
+
+	if (ILLEGAL_API(api_type))
+		IF_ERROR(ERR_API_TYPE_INVALID);
+
+	tpm_db_api_section_get_from_api_type(api_type, &api_section);
+
+	while (next_idx != -1) {
+		ret_code = tpm_get_next_valid_rule(owner_id, cur_idx, api_type, &next_idx, &rule_idx, &tpm_rule);
+		IF_ERROR(ret_code);
+		ret_code = tpm_db_api_rulenum_get(api_section, rule_idx, &rule_num);
+		IF_ERROR(ret_code);
+		ret_code =
+		tpm_db_api_entry_get(api_section, rule_num, &dummy_idx, &bi_dir, &api_data, &mod_con, &pnc_con);
+		IF_ERROR(ret_code);
+
+		/* Delete PNC Entry */
+		ret_code = tpm_proc_pnc_con_del(&pnc_con);
+		IF_ERROR(ret_code);
+		/* Release related modification entry  (Important, after deleting PNC Entries) */
+		if (mod_con.mod_cmd_mac != TPM_INVALID_GMAC)
+			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, mod_con.mod_cmd_mac, mod_con.mod_cmd_ind);
+
+		IF_ERROR(ret_code);
+	}
+	tpm_db_api_section_reset(api_section);
+	IF_ERROR(ret_code);
+
+	return ret_code;
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_nh_acl_rule(uint32_t owner_id,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_nh_iter_t nh_iter,
+					       uint32_t nh,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t api_rng_entries = 0;
+	uint32_t l_rule_idx = 0;
+	uint32_t bi_dir = 0;
+	uint32_t pnc_entry, mod_entry = 0;
+	tpm_dir_t dir = 0;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d), rule_num(%d)\n", owner_id, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv6_nh_check(owner_id, rule_num, nh_iter, parse_flags_bm, nh, pkt_frwd, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Simulate DS only (BI_DIR) */
+	dir = TPM_DIR_DS;
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_IPV6_NH_ACL, &range_id);
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ipv6_nh_tcam_build(rule_num, nh_iter, nh,
+				parse_flags_bm, rule_action, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code =
+	tpm_proc_ipv6_nh_sram_build(rule_num, nh_iter, nh, pon_type, pkt_frwd, rule_action, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	/*********** Remove Current Entries **********/
+	tpm_db_pnc_rng_get(range_id, &range_data);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_IPV6_NH_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_num(%d) already exists\n", owner_id, rule_num);
+
+			ret_code = tpm_proc_del_ipv6_nh_acl_rule(owner_id, l_rule_idx, TPM_INT_CALL);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*** Insert the PNC Entry ***/
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_IPV6_NH_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_IPV6_NH_ACL, rule_num, TPM_FALSE, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	api_data.ipv6_nh_key.nh_iter = nh_iter;
+	api_data.ipv6_nh_key.nh = nh;
+	api_data.ipv6_nh_key.parse_rule_bm = TPM_IPv6_PARSE_NH;
+	api_data.ipv6_nh_key.parse_flags_bm = parse_flags_bm;
+	if (rule_action != NULL)
+		memcpy(&(api_data.ipv6_nh_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+	else
+		memset(&(api_data.ipv6_nh_key.rule_action), 0, sizeof(tpm_rule_action_t));
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.ipv6_nh_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.ipv6_nh_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	/* Set API modification data */
+	tpm_proc_set_api_moddata(rule_action->pkt_act, TPM_INVALID_GMAC	/*DO NOT SUPPORT NH MOD!! */ , &mod_con,
+				 mod_entry);
+
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_IPV6_NH_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(int_ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_IPV6_NH_ACL, rule_num, 1 /*bi_dir */ ,
+					    &api_data, &mod_con	/*no mod_con */ , &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_ipv6_nh_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	ret_code = tpm_proc_del_acl_rule(TPM_IPV6_NH_ACL, owner_id, rule_idx, ext_call);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_gen_acl_rule(uint32_t owner_id,
+						  tpm_src_port_type_t src_port,
+						  uint32_t rule_num,
+						  uint32_t *rule_idx,
+						  tpm_parse_fields_t parse_rule_bm,
+						  tpm_parse_flags_t parse_flags_bm,
+						  tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+						  tpm_pkt_frwd_t *pkt_frwd,
+						  tpm_pkt_mod_t *pkt_mod,
+						  tpm_pkt_mod_bm_t pkt_mod_bm,
+						  tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0;
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_dir_t dir = 0;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	uint32_t bi_dir = 0;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d)\n", owner_id, src_port, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv6_gen_check(owner_id, src_port, rule_num, parse_rule_bm, parse_flags_bm,
+						 ipv6_gen_key, pkt_frwd, pkt_mod_bm, pkt_mod, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Get direction */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_IPV6_GEN_ACL, &range_id);
+
+	/*********** Create Modification Entries **********/
+
+	/* if split mod stage-2 */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op &&
+		(pkt_mod_bm == TPM_VLAN_MOD)) {
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod stage-2\n");
+
+		if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+			return(ERR_MOD_INVALID);
+		} else if (trg_gmac == TPM_INVALID_GMAC) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+			return(ERR_MOD_INVALID);
+		}
+
+		/* get mod index from p-bit value */
+		int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pkt_mod->vlan_mod.vlan1_out.pbit, &mod_entry);
+		if (TPM_DB_OK != int_ret_code) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-2, illeagal p-bit value: %d\n",
+				pkt_mod->vlan_mod.vlan1_out.pbit);
+			return ERR_MOD_INVALID;
+		}
+
+		/* the first PMT is for p-bit AS-IS */
+		mod_entry++;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+	} else {
+		ret_code =
+		tpm_proc_create_mod(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm, 0 /*int_mod_bm */ ,
+				    &mod_entry, &trg_gmac);
+		IF_ERROR(ret_code);
+	}
+
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ipv6_gen_tcam_build(src_port, dir, rule_num, ipv6_gen_key,
+						      parse_rule_bm, parse_flags_bm, pkt_mod,
+						      pkt_mod_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_ipv6_gen_sram_build(src_port, dir, rule_num, pon_type, pkt_frwd, rule_action,
+						      mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	/*********** Remove Current Entries **********/
+	tpm_db_pnc_rng_get(range_id, &range_data);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_IPV6_GEN_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_num(%d) already exists\n", owner_id, rule_num);
+
+			ret_code = tpm_proc_del_ipv6_gen_acl_rule(owner_id, l_rule_idx, TPM_INT_CALL);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*** Insert the PNC Entry ***/
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_IPV6_GEN_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_IPV6_GEN_ACL, rule_num, TPM_FALSE, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	api_data.ipv6_gen_key.src_port = src_port;
+	api_data.ipv6_gen_key.parse_rule_bm = parse_rule_bm;
+	api_data.ipv6_gen_key.parse_flags_bm = parse_flags_bm;
+	api_data.ipv6_gen_key.pkt_mod_bm = pkt_mod_bm;
+
+	memcpy(&(api_data.ipv6_gen_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+	if (ipv6_gen_key)
+		memcpy(&(api_data.ipv6_gen_key.ipv6_gen_key), ipv6_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.ipv6_gen_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.ipv6_gen_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	if (pkt_mod != NULL)
+		memcpy(&(api_data.ipv6_gen_key.pkt_mod), pkt_mod, sizeof(tpm_pkt_mod_t));
+	else
+		memset(&(api_data.ipv6_gen_key.pkt_mod), 0, sizeof(tpm_pkt_mod_t));
+
+	/* Set modification data */
+	tpm_proc_set_api_moddata(rule_action->pkt_act, trg_gmac, &mod_con, mod_entry);
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_IPV6_GEN_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(int_ret_code);
+		}
+	}
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_IPV6_GEN_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_ipv6_gen_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	ret_code = tpm_proc_del_acl_rule(TPM_IPV6_GEN_ACL, owner_id, rule_idx, ext_call);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_dip_acl_rule(uint32_t owner_id,
+						tpm_src_port_type_t src_port,
+						uint32_t rule_num,
+						uint32_t *rule_idx,
+						tpm_parse_fields_t parse_rule_bm,
+						tpm_parse_flags_t parse_flags_bm,
+						tpm_ipv6_addr_key_t *ipv6_dip_key,
+						tpm_pkt_frwd_t *pkt_frwd,
+						tpm_pkt_mod_t *pkt_mod,
+						tpm_pkt_mod_bm_t pkt_mod_bm,
+						tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0;
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_dir_t dir = 0;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	uint32_t bi_dir = 0;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d)\n", owner_id, src_port, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv6_dip_check(owner_id, src_port, rule_num, parse_rule_bm, parse_flags_bm,
+					       ipv6_dip_key, pkt_frwd, pkt_mod_bm, pkt_mod, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Get direction */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_IPV6_DIP_ACL, &range_id);
+
+	/*********** Create Modification Entries **********/
+	/* if split mod stage-2 */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op &&
+		(pkt_mod_bm == TPM_VLAN_MOD)) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod stage-2\n");
+
+		if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+			return(ERR_MOD_INVALID);
+		} else if (trg_gmac == TPM_INVALID_GMAC) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+			return(ERR_MOD_INVALID);
+		}
+
+		/* get mod index from p-bit value */
+		int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pkt_mod->vlan_mod.vlan1_out.pbit, &mod_entry);
+		if (TPM_DB_OK != int_ret_code) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-2, illeagal p-bit value: %d\n",
+				pkt_mod->vlan_mod.vlan1_out.pbit);
+			return ERR_MOD_INVALID;
+		}
+
+		/* the first PMT is for p-bit AS-IS */
+		mod_entry++;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+	} else {
+		ret_code =
+		tpm_proc_create_mod(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm, 0 /*int_mod_bm */ ,
+				    &mod_entry, &trg_gmac);
+		IF_ERROR(ret_code);
+	}
+
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ipv6_dip_tcam_build(src_port, dir, rule_num, ipv6_dip_key,
+						    parse_rule_bm, parse_flags_bm, pkt_mod,
+						    pkt_mod_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_ipv6_dip_sram_build(src_port, dir, rule_num, pon_type, pkt_frwd, rule_action,
+						    mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	/*********** Remove Current Entries **********/
+	tpm_db_pnc_rng_get(range_id, &range_data);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_IPV6_DIP_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_num(%d) already exists\n", owner_id, rule_num);
+
+			ret_code = tpm_proc_del_ipv6_dip_acl_rule(owner_id, l_rule_idx, TPM_INT_CALL);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*** Insert the PNC Entry ***/
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_IPV6_DIP_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_IPV6_DIP_ACL, rule_num, TPM_FALSE, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	api_data.ipv6_dip_key.src_port = src_port;
+	api_data.ipv6_dip_key.parse_rule_bm = parse_rule_bm;
+	api_data.ipv6_dip_key.parse_flags_bm = parse_flags_bm;
+	api_data.ipv6_dip_key.pkt_mod_bm = pkt_mod_bm;
+
+	memcpy(&(api_data.ipv6_dip_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+	if (ipv6_dip_key)
+		memcpy(&(api_data.ipv6_dip_key.ipv6_dipkey), ipv6_dip_key, sizeof(tpm_ipv6_addr_key_t));
+
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.ipv6_dip_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.ipv6_dip_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	if (pkt_mod != NULL)
+		memcpy(&(api_data.ipv6_dip_key.pkt_mod), pkt_mod, sizeof(tpm_pkt_mod_t));
+	else
+		memset(&(api_data.ipv6_dip_key.pkt_mod), 0, sizeof(tpm_pkt_mod_t));
+
+	/* Set modification data */
+	tpm_proc_set_api_moddata(rule_action->pkt_act, trg_gmac, &mod_con, mod_entry);
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_IPV6_DIP_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(int_ret_code);
+		}
+	}
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_IPV6_DIP_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_ipv6_dip_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	ret_code = tpm_proc_del_acl_rule(TPM_IPV6_DIP_ACL, owner_id, rule_idx, ext_call);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_l4_ports_acl_rule(uint32_t owner_id,
+						     tpm_src_port_type_t src_port,
+						     uint32_t rule_num,
+						     uint32_t *rule_idx,
+						     tpm_parse_fields_t parse_rule_bm,
+						     tpm_parse_flags_t parse_flags_bm,
+						     tpm_l4_ports_key_t *l4_key,
+						     tpm_pkt_frwd_t *pkt_frwd,
+						     tpm_pkt_mod_t *pkt_mod,
+						     tpm_pkt_mod_bm_t pkt_mod_bm,
+						     tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0;
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_dir_t dir = 0;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	uint32_t bi_dir = 0;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d)\n", owner_id, src_port, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv6_l4ports_check(owner_id, src_port, rule_num, parse_rule_bm, parse_flags_bm,
+						   l4_key, pkt_frwd, pkt_mod_bm, pkt_mod, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Get direction */
+	tpm_proc_src_port_dir_map(src_port, &dir);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_L4_ACL, &range_id);
+
+	/*********** Create Modification Entries **********/
+	/* if split mod stage-2 */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op &&
+		(pkt_mod_bm == TPM_VLAN_MOD)) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod stage-2\n");
+
+		if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+			return(ERR_MOD_INVALID);
+		} else if (trg_gmac == TPM_INVALID_GMAC) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+			return(ERR_MOD_INVALID);
+		}
+
+		/* get mod index from p-bit value */
+		int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pkt_mod->vlan_mod.vlan1_out.pbit, &mod_entry);
+		if (TPM_DB_OK != int_ret_code) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-2, illeagal p-bit value: %d\n",
+				pkt_mod->vlan_mod.vlan1_out.pbit);
+			return ERR_MOD_INVALID;
+		}
+
+		/* the first PMT is for p-bit AS-IS */
+		mod_entry++;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+	} else {
+		/*int_mod_bm must be modified in Phase2 */
+		ret_code =
+		tpm_proc_create_mod(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm, 0 /*int_mod_bm */ ,
+				    &mod_entry, &trg_gmac);
+		IF_ERROR(ret_code);
+	}
+
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ipv6_l4ports_tcam_build(src_port, dir, rule_num, l4_key,
+							parse_rule_bm, parse_flags_bm, rule_action,
+							pkt_mod, pkt_mod_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_ipv6_l4ports_sram_build(src_port, dir, rule_num, pon_type, pkt_frwd, rule_action,
+							mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	/*********** Remove Current Entries **********/
+	tpm_db_pnc_rng_get(range_id, &range_data);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_L4_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_num(%d) already exists\n", owner_id, rule_num);
+
+			ret_code = tpm_proc_del_ipv6_l4_ports_acl_rule(owner_id, l_rule_idx, TPM_INT_CALL);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*** Insert the PNC Entry ***/
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_L4_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_L4_ACL, rule_num, TPM_FALSE, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	api_data.ipv6_l4_key.src_port = src_port;
+	api_data.ipv6_l4_key.parse_rule_bm = parse_rule_bm;
+	api_data.ipv6_l4_key.parse_flags_bm = parse_flags_bm;
+	api_data.ipv6_l4_key.pkt_mod_bm = pkt_mod_bm;
+
+	memcpy(&(api_data.ipv6_l4_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+	if (l4_key)
+		memcpy(&(api_data.ipv6_l4_key.l4_key), l4_key, sizeof(tpm_l4_ports_key_t));
+
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.ipv6_l4_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.ipv6_l4_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	if (pkt_mod != NULL)
+		memcpy(&(api_data.ipv6_l4_key.pkt_mod), pkt_mod, sizeof(tpm_pkt_mod_t));
+	else
+		memset(&(api_data.ipv6_l4_key.pkt_mod), 0, sizeof(tpm_pkt_mod_t));
+
+	/* Set modification data */
+	tpm_proc_set_api_moddata(rule_action->pkt_act, trg_gmac, &mod_con, mod_entry);
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_L4_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(int_ret_code);
+		}
+	}
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_L4_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_ipv6_l4_ports_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call)
+{
+
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	ret_code = tpm_proc_del_acl_rule(TPM_L4_ACL, owner_id, rule_idx, ext_call);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_catch_all_init(void)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries, pnc_entry, cpu_def_rx_queue;
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_db_pnc_range_t range_data;
+	tpm_init_pnc_last_init_t catch_all_pkt_action;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_CATCH_ALL, &range_data);
+	IF_ERROR(int_ret_code);
+
+	/* Get number of entries */
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start + range_data.pnc_range_conf.api_start;
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "free_ent(%d)\n", free_entries);
+
+	tpm_db_get_catch_all_pkt_action(&catch_all_pkt_action);
+
+	/* TCAM  : Any LU_ID, all GMACs */
+	pnc_data.pncl_tcam.lu_id = TPM_PNC_ANY_LUID;
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+
+	/* Fictive L2 table */
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
+
+	 /*SRAM*/
+	/* LookupDone */
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_LUD;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Trap or drop packets */
+	if (TPM_PNC_LAST_ENTRY_INIT_TRAP == catch_all_pkt_action) {
+		/* Get CPU Queue */
+		tpm_db_get_cpu_rx_queue(&cpu_def_rx_queue);
+
+		/* Set Target to CPU */
+		pnc_data.pncl_sram.sram_updt_bm |= TPM_PNCL_SET_TXP;
+		pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+
+		/* Set Queue to default CPU Queue */
+		pnc_data.pncl_sram.pnc_queue = cpu_def_rx_queue;
+	} else {
+		/* Discard packet */
+		pnc_data.pncl_sram.sram_updt_bm |= TPM_PNCL_SET_DISC;
+	}
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_CATCH_ALL, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+void tpm_proc_check_ipv6_gen_5t_key(uint32_t parse_bm, tpm_ipv6_gen_acl_key_t *gen_key)
+{
+	if ((parse_bm & TPM_IPv6_PARSE_SIP) == 0) {
+		memset(gen_key->ipv6_src_ip_add, 0, 16 * sizeof(uint8_t));
+		memset(gen_key->ipv6_src_ip_add_mask, 0, 16 * sizeof(uint8_t));
+	}
+
+	if ((parse_bm & TPM_IPv6_PARSE_DSCP) == 0) {
+		gen_key->ipv6_dscp = 0;
+		gen_key->ipv6_dscp_mask = 0;
+	}
+
+	if ((parse_bm & TPM_IPv6_PARSE_HOPL) == 0) {
+		gen_key->hop_limit = 0;
+	}
+}
+
+void tpm_proc_check_ipv6_dip_5t_key(uint32_t parse_bm, tpm_ipv6_addr_key_t *dip_key)
+{
+	if ((parse_bm & TPM_IPv6_PARSE_DIP) == 0) {
+		memset(dip_key->ipv6_ip_add, 0, 16 * sizeof(uint8_t));
+		memset(dip_key->ipv6_ip_add_mask, 0, 16 * sizeof(uint8_t));
+	}
+}
+
+void tpm_proc_check_ipv6_l4_ports_5t_key(uint32_t parse_bm, tpm_l4_ports_key_t *l4_key)
+{
+	if ((parse_bm & TPM_PARSE_L4_SRC) == 0) {
+		l4_key->l4_src_port = 0;
+	}
+
+	if ((parse_bm & TPM_PARSE_L4_DST) == 0) {
+		l4_key->l4_dst_port = 0;
+	}
+}
+
+uint8_t tpm_proc_check_ipv6_5t_flow_a_equal_b(uint32_t parse_bm,
+												uint32_t proto_a,
+												tpm_l4_ports_key_t *l4_key_a,
+												tpm_ipv6_gen_acl_key_t *gen_key_a,
+												tpm_ipv6_addr_key_t *dip_key_a,
+												uint32_t proto_b,
+												tpm_l4_ports_key_t *l4_key_b,
+												tpm_ipv6_gen_acl_key_t *gen_key_b,
+												tpm_ipv6_addr_key_t *dip_key_b)
+{
+	if (parse_bm & TPM_IPv6_PARSE_NH) {
+		if (proto_a != proto_b)
+			return TPM_FALSE;
+	}
+
+	if (parse_bm & TPM_IPV6_L4_BM_MASK) {
+		if (parse_bm & TPM_PARSE_L4_SRC) {
+			if (l4_key_a->l4_src_port != l4_key_b->l4_src_port)
+				return TPM_FALSE;
+		}
+		if (parse_bm & TPM_PARSE_L4_DST) {
+			if (l4_key_a->l4_dst_port != l4_key_b->l4_dst_port)
+				return TPM_FALSE;
+		}
+	}
+
+	if (parse_bm & TPM_IPV6_GEN_BM_MASK) {
+		if (parse_bm & TPM_IPv6_PARSE_SIP) {
+			if (memcmp(gen_key_a->ipv6_src_ip_add, gen_key_b->ipv6_src_ip_add, 16 * sizeof(uint8_t)) ||
+				memcmp(gen_key_a->ipv6_src_ip_add_mask, gen_key_b->ipv6_src_ip_add_mask, 16 * sizeof(uint8_t)))
+				return TPM_FALSE;
+		}
+	}
+
+	if (parse_bm & TPM_IPv6_PARSE_DIP) {
+		if (memcmp(dip_key_a->ipv6_ip_add, dip_key_b->ipv6_ip_add, 16 * sizeof(uint8_t)) ||
+			memcmp(dip_key_a->ipv6_ip_add_mask, dip_key_b->ipv6_ip_add_mask, 16 * sizeof(uint8_t)))
+			return TPM_FALSE;
+	}
+
+	return TPM_TRUE;
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_gen_5t_check(uint32_t owner_id,
+												tpm_dir_t dir,
+												uint32_t rule_num,
+												tpm_parse_fields_t parse_rule_bm,
+												tpm_parse_flags_t parse_flags_bm,
+												tpm_l4_ports_key_t *l4_key,
+												tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+												tpm_pkt_frwd_t *pkt_frwd,
+												tpm_pkt_mod_bm_t pkt_mod_bm,
+												tpm_pkt_mod_t *pkt_mod,
+												tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_db_pon_type_t pon_type;
+	uint32_t i, subflow_bm, subflow_id, protocol = 0, _subflow_bm, _protocol, _dir, _is_pppoe;
+	tpm_db_pnc_range_t range_data;
+	tpm_l4_ports_key_t _l4_key;
+	tpm_ipv6_gen_acl_key_t _gen_key;
+	tpm_ipv6_addr_key_t _dip_key, dip_key;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	memset(&dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Check 5_tuple feature is enabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable != TPM_IPV6_5T_ENABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	/* Check necessary pointers are valid */
+
+	if (rule_action == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "rule_action cannot be NULL\n");
+		return(ERR_ACTION_INVALID);
+	}
+
+	if ((pkt_mod == NULL) && (SET_MOD(rule_action->pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Mod requested with NULL pointer\n");
+		return(ERR_MOD_INVALID);
+	}
+
+	if ((pkt_frwd == NULL) && ((SET_TARGET_PORT(rule_action->pkt_act)) || SET_TARGET_QUEUE(rule_action->pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target set requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	if ((l4_key == NULL) || (ipv6_gen_key == NULL)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parsing requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check parse_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_IPV6_GEN_5T_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_IPV6_GEN_5T_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_IPV6_GEN, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_GEN, &range_data);
+
+	ret_code = tpm_proc_add_api_ent_check(TPM_IPV6_GEN_ACL, range_data.pnc_range_conf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	/* Check forwarding rule, currently only support STAGE_DONE */
+	if (rule_action->next_phase != STAGE_IPv6_DIP && rule_action->next_phase != STAGE_DONE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_IPV6_GEN_ACL_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	/* Check 5T-flow keys */
+	tpm_proc_check_ipv6_l4_ports_5t_key(parse_rule_bm, l4_key);
+	tpm_proc_check_ipv6_gen_5t_key(parse_rule_bm, ipv6_gen_key);
+
+	if (parse_rule_bm & TPM_IPV6_L4_BM_MASK) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) == 0)
+			return(ERR_IPV6_KEY_INVALID);
+	}
+
+	subflow_bm = parse_rule_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
+	if (subflow_bm != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+				protocol = IPPROTO_TCP;
+			else
+				protocol = IPPROTO_UDP;
+			subflow_bm |= TPM_IPv6_PARSE_NH;
+		}
+		subflow_id = tpm_db_find_matched_ipv6_gen_subflow(dir, subflow_bm, protocol, l4_key, ipv6_gen_key);
+		if (subflow_id != TPM_DB_INVALID_IPV6_FLOW_ID)
+			return ERR_IPV6_5T_RULE_EXISTS;
+
+		if (rule_action->next_phase == STAGE_DONE) {
+			for (i = 0; i < TPM_DB_IPV6_MAX_5T_FLOW_NUM; i++) {
+				memset(&_l4_key, 0, sizeof(tpm_l4_ports_key_t));
+				memset(&_gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+				memset(&_dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+				ret_code = tpm_db_get_ipv6_5t_flow(i, &_dir, &_subflow_bm, &_is_pppoe, &_protocol, &_l4_key, &_gen_key, &_dip_key);
+				if (ret_code != TPM_DB_OK)
+					continue;
+
+				if ((subflow_bm & _subflow_bm) == subflow_bm) {
+					if (tpm_proc_check_ipv6_5t_flow_a_equal_b(subflow_bm, protocol, l4_key, ipv6_gen_key, &dip_key,
+															_protocol, &_l4_key, &_gen_key, &_dip_key))
+						return ERR_IPV6_5T_FLOW_PARTIAL_MATCHED;
+				} else if ((subflow_bm & _subflow_bm) == _subflow_bm) {
+					if (tpm_proc_check_ipv6_5t_flow_a_equal_b(_subflow_bm, _protocol, &_l4_key, &_gen_key, &_dip_key,
+															protocol, l4_key, ipv6_gen_key, &dip_key))
+						return ERR_IPV6_5T_FLOW_PARTIAL_MATCHED;
+				}
+			}
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_dip_5t_check(uint32_t owner_id,
+												tpm_dir_t dir,
+												uint32_t rule_num,
+												tpm_parse_fields_t parse_rule_bm,
+												tpm_parse_flags_t parse_flags_bm,
+												tpm_l4_ports_key_t *l4_key,
+												tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+												tpm_ipv6_addr_key_t *ipv6_dip_key,
+												tpm_pkt_frwd_t *pkt_frwd,
+												tpm_pkt_mod_bm_t pkt_mod_bm,
+												tpm_pkt_mod_t *pkt_mod,
+												tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_db_pon_type_t pon_type;
+	uint32_t i, flow_bm, flow_id, protocol = 0, is_pppoe, _flow_bm, _protocol, _dir, _is_pppoe;
+	tpm_db_pnc_range_t range_data;
+	tpm_l4_ports_key_t _l4_key;
+	tpm_ipv6_gen_acl_key_t _gen_key;
+	tpm_ipv6_addr_key_t _dip_key;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Check 5_tuple feature is enabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable != TPM_IPV6_5T_ENABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	/* Check necessary pointers are valid */
+
+	if (rule_action == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "rule_action cannot be NULL\n");
+		return(ERR_ACTION_INVALID);
+	}
+
+	if ((pkt_mod == NULL) && (SET_MOD(rule_action->pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Mod requested with NULL pointer\n");
+		return(ERR_MOD_INVALID);
+	}
+
+	if ((pkt_frwd == NULL) && ((SET_TARGET_PORT(rule_action->pkt_act)) || SET_TARGET_QUEUE(rule_action->pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target set requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	if ((l4_key == NULL) || (ipv6_gen_key == NULL) || (ipv6_dip_key == NULL)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parsing requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check parse_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_IPV6_DIP_5T_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_IPV6_DIP_5T_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_IPV6_DIP, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_DIP, &range_data);
+
+	ret_code = tpm_proc_add_api_ent_check(TPM_IPV6_DIP_ACL, range_data.pnc_range_conf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	/* Check forwarding rule, currently only support STAGE_DONE */
+	if (rule_action->next_phase != STAGE_DONE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_IPV6_DIP_ACL_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	/* Check 5T-flow keys */
+	tpm_proc_check_ipv6_l4_ports_5t_key(parse_rule_bm, l4_key);
+	tpm_proc_check_ipv6_gen_5t_key(parse_rule_bm, ipv6_gen_key);
+	tpm_proc_check_ipv6_dip_5t_key(parse_rule_bm, ipv6_dip_key);
+
+	if (parse_rule_bm & TPM_IPV6_L4_BM_MASK) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) == 0)
+			return(ERR_IPV6_KEY_INVALID);
+	}
+
+	if (parse_rule_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK) {
+		flow_bm = parse_rule_bm;
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+				protocol = IPPROTO_TCP;
+			else
+				protocol = IPPROTO_UDP;
+			flow_bm |= TPM_IPv6_PARSE_NH;
+		}
+		if ((parse_flags_bm & TPM_PARSE_FLAG_PPPOE_TRUE) != 0)
+			is_pppoe = TPM_TRUE;
+		else
+			is_pppoe = TPM_FALSE;
+		flow_id = tpm_db_find_matched_ipv6_5t_flow(dir, flow_bm, is_pppoe, protocol, l4_key, ipv6_gen_key, ipv6_dip_key);
+		if (flow_id != TPM_DB_INVALID_IPV6_FLOW_ID)
+			return ERR_IPV6_5T_RULE_EXISTS;
+
+		for (i = 0; i < TPM_DB_IPV6_MAX_5T_FLOW_NUM; i++) {
+			memset(&_l4_key, 0, sizeof(tpm_l4_ports_key_t));
+			memset(&_gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+			memset(&_dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+			ret_code = tpm_db_get_ipv6_5t_flow(i, &_dir, &_flow_bm, &_is_pppoe, &_protocol, &_l4_key, &_gen_key, &_dip_key);
+			if (ret_code != TPM_DB_OK)
+				continue;
+
+			if ((flow_bm & _flow_bm) == flow_bm) {
+				if (tpm_proc_check_ipv6_5t_flow_a_equal_b(flow_bm, protocol, l4_key, ipv6_gen_key, ipv6_dip_key,
+														_protocol, &_l4_key, &_gen_key, &_dip_key))
+					return ERR_IPV6_5T_FLOW_PARTIAL_MATCHED;
+			} else if ((flow_bm & _flow_bm) == _flow_bm) {
+				if (tpm_proc_check_ipv6_5t_flow_a_equal_b(_flow_bm, _protocol, &_l4_key, &_gen_key, &_dip_key,
+														protocol, l4_key, ipv6_gen_key, ipv6_dip_key))
+					return ERR_IPV6_5T_FLOW_PARTIAL_MATCHED;
+			}
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_l4_ports_5t_check(uint32_t owner_id,
+						     tpm_dir_t dir,
+						     uint32_t rule_num,
+						     tpm_parse_fields_t parse_rule_bm,
+						     tpm_parse_flags_t parse_flags_bm,
+						     tpm_l4_ports_key_t *l4_key,
+						     tpm_pkt_frwd_t *pkt_frwd,
+						     tpm_pkt_mod_bm_t pkt_mod_bm,
+						     tpm_pkt_mod_t *pkt_mod,
+						     tpm_rule_action_t *rule_action)
+{
+	int32_t ret_code;
+	tpm_db_pon_type_t pon_type;
+	uint32_t i, subflow_bm, subflow_id, protocol = 0, _subflow_bm, _protocol, _dir, _is_pppoe;
+	tpm_db_pnc_range_t range_data;
+	tpm_l4_ports_key_t _l4_key;
+	tpm_ipv6_gen_acl_key_t _gen_key, gen_key;
+	tpm_ipv6_addr_key_t _dip_key, dip_key;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	memset(&gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+	memset(&dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	/* Get Direction, PON type, Important before other tests */
+	tpm_db_pon_type_get(&pon_type);
+
+
+	/* Check 5_tuple feature is enabled */
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable != TPM_IPV6_5T_ENABLED)
+		return ERR_IPV6_API_ILLEGAL_CALL;
+
+	/* Check necessary pointers are valid */
+
+	if (rule_action == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "rule_action cannot be NULL\n");
+		return(ERR_ACTION_INVALID);
+	}
+
+	if ((pkt_mod == NULL) && (SET_MOD(rule_action->pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Mod requested with NULL pointer\n");
+		return(ERR_MOD_INVALID);
+	}
+
+	if ((pkt_frwd == NULL) && ((SET_TARGET_PORT(rule_action->pkt_act)) || SET_TARGET_QUEUE(rule_action->pkt_act))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target set requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	if (l4_key == NULL) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Parsing requested with NULL pointer\n");
+		return(ERR_FRWD_INVALID);
+	}
+
+	/* Check Target_port and Queue are valid */
+	ret_code =
+	tpm_proc_check_valid_target(dir, pon_type, pkt_frwd->trg_port, pkt_frwd->trg_queue, rule_action->pkt_act);
+	IF_ERROR(ret_code);
+
+	/* Check parse_bm */
+	if (parse_rule_bm & (~(api_sup_param_val[TPM_ADD_IPV6_L4_PORTS_5T_RULE].sup_parse_fields))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_rule_bm(0x%x) \n", parse_rule_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+
+	/* Check parse_flags_bm */
+	if (parse_flags_bm & (~(api_sup_param_val[TPM_ADD_IPV6_L4_PORTS_5T_RULE].sup_parse_flags))) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid parse_flags_bm (0x%x) \n", parse_flags_bm);
+		return(ERR_PARSE_MAP_INVALID);
+	}
+	/* Check parse_flags_bm - TRUE and FALSE are not set together */
+	ret_code = tpm_proc_check_parse_flag_valid(parse_flags_bm);
+	IF_ERROR(ret_code);
+
+	/* Check owner_id */
+	ret_code = tpm_owner_id_check(TPM_API_IPV6_L4, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+
+	/* Check rule_num, and api_section is active */
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_L4, &range_data);
+
+	ret_code = tpm_proc_add_api_ent_check(TPM_L4_ACL, range_data.pnc_range_conf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+
+	/* Check forwarding rule, currently only support STAGE_DONE */
+	if (rule_action->next_phase != STAGE_IPv6_GEN && rule_action->next_phase != STAGE_DONE
+		&& rule_action->next_phase != STAGE_CTC_CM) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " Next Phase (%d) is not supported \n", rule_action->next_phase);
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check rule action */
+	ret_code = tpm_proc_check_pkt_action(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm);
+	IF_ERROR(ret_code);
+	if (rule_action->pkt_act & api_sup_param_val[TPM_ADD_IPV6_L4_PORTS_5T_RULE].forbidden_actions) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Packet Action (0x%x) includes forbidden action\n", rule_action->pkt_act);
+		return(ERR_ACTION_INVALID);
+	}
+
+	/* Check if next stage CTC CnM  */
+	if ((rule_action->next_phase == STAGE_CTC_CM) && !(parse_flags_bm & TPM_PARSE_FLAG_MTM_FALSE)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "next stage is CnM, packets must be MTM_FALSE\n");
+		return(ERR_NEXT_PHASE_INVALID);
+	}
+
+	/* Check 5T-flow keys */
+	tpm_proc_check_ipv6_l4_ports_5t_key(parse_rule_bm, l4_key);
+
+	if (parse_rule_bm & TPM_IPV6_L4_BM_MASK) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) == 0)
+			return(ERR_IPV6_KEY_INVALID);
+	}
+
+	subflow_bm = parse_rule_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+	if (subflow_bm != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+				protocol = IPPROTO_TCP;
+			else
+				protocol = IPPROTO_UDP;
+			subflow_bm |= TPM_IPv6_PARSE_NH;
+		}
+		subflow_id = tpm_db_find_matched_ipv6_l4_subflow(dir, subflow_bm, protocol, l4_key);
+		if (subflow_id != TPM_DB_INVALID_IPV6_FLOW_ID)
+			return ERR_IPV6_5T_RULE_EXISTS;
+
+		if (rule_action->next_phase == STAGE_DONE) {
+			for (i = 0; i < TPM_DB_IPV6_MAX_5T_FLOW_NUM; i++) {
+				memset(&_l4_key, 0, sizeof(tpm_l4_ports_key_t));
+				memset(&_gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+				memset(&_dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+				ret_code = tpm_db_get_ipv6_5t_flow(i, &_dir, &_subflow_bm, &_is_pppoe, &_protocol, &_l4_key, &_gen_key, &_dip_key);
+				if (ret_code != TPM_DB_OK)
+					continue;
+
+				if ((subflow_bm & _subflow_bm) == subflow_bm) {
+					if (tpm_proc_check_ipv6_5t_flow_a_equal_b(subflow_bm, protocol, l4_key, &gen_key, &dip_key,
+															_protocol, &_l4_key, &_gen_key, &_dip_key))
+						return ERR_IPV6_5T_FLOW_PARTIAL_MATCHED;
+				} else if ((subflow_bm & _subflow_bm) == _subflow_bm) {
+					if (tpm_proc_check_ipv6_5t_flow_a_equal_b(_subflow_bm, _protocol, &_l4_key, &_gen_key, &_dip_key,
+															protocol, l4_key, &gen_key, &dip_key))
+						return ERR_IPV6_5T_FLOW_PARTIAL_MATCHED;
+				}
+			}
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+
+int32_t tpm_proc_ipv6_gen_5t_tcam_build(tpm_dir_t dir,
+					uint32_t rule_num,
+					tpm_l4_ports_key_t *l4_key,
+					tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					tpm_parse_fields_t parse_rule_bm,
+					tpm_parse_flags_t parse_flags_bm,
+					tpm_rule_action_t *rule_action,
+					tpm_pkt_mod_t *pkt_mod,
+					tpm_pkt_mod_bm_t pkt_mod_bm,
+					tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_src_port_type_t src_port;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t subflow_field;
+	int32_t ret_code;
+	uint32_t subflow_bm, subflow_id, protocol = 0;
+	long long parse_int_flags_bm = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " dir(%d), rule_num(%d) parse_rule_bm(%x) parse_flag_bm(%x) \n",
+		     	dir, rule_num, parse_rule_bm, parse_flags_bm);
+
+	/* IPV6 parsing, according to parse_rule */
+	tcam_data->ipv6_parse_bm = parse_rule_bm & TPM_IPV6_GEN_BM_MASK;
+
+	/* Build the AI bits according to parse_flags */
+	subflow_bm = parse_rule_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+	if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+			protocol = IPPROTO_TCP;
+		else {
+			protocol = IPPROTO_UDP;
+			if (dir == TPM_DIR_DS)
+				parse_int_flags_bm |= TPM_PARSE_FLAG_MC_VID_FALSE;
+		}
+		subflow_bm |= TPM_IPv6_PARSE_NH;
+	}
+	if (subflow_bm != 0) {
+		subflow_id = tpm_db_find_matched_ipv6_l4_subflow(dir, subflow_bm, protocol, l4_key);
+		if (subflow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+			return TPM_FAIL;
+		subflow_field.ipv6_subflow = subflow_id + 1;
+		parse_int_flags_bm |= TPM_PARSE_FLAG_IPV6_SUBFLOW_PARSE;
+	}
+	parse_flags_bm &= ~TPM_PARSE_FLAG_L4P_MASK;
+	/*if Ipv6 split, check AI bit, update tcam*/
+	if ((STAGE_CTC_CM == rule_action->next_phase) || ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) &&
+		(0xff == pkt_mod->vlan_mod.vlan1_out.pbit_mask) &&
+		(pkt_mod_bm == TPM_VLAN_MOD))) {
+
+		/*if Ipv6 split or CTC CnM, check AI bit, update tcam*/
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+	tpm_proc_parse_flag_ai_tcam_build(&subflow_field, parse_flags_bm, parse_int_flags_bm,
+					  				&(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	if (dir == TPM_DIR_DS)
+		src_port = TPM_SRC_PORT_WAN;
+	else
+		src_port = TPM_SRC_PORT_UNI_ANY;
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = src_port;
+	if (ipv6_gen_key)
+		memcpy(&(tcam_data->pkt_key.ipv6_gen_key), ipv6_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_GEN, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_dip_5t_tcam_build(tpm_dir_t dir,
+					uint32_t rule_num,
+					tpm_l4_ports_key_t *l4_key,
+					tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					tpm_ipv6_addr_key_t *ipv6_dip_key,
+					tpm_parse_fields_t parse_rule_bm,
+					tpm_parse_flags_t parse_flags_bm,
+					tpm_rule_action_t *rule_action,
+					tpm_pkt_mod_t *pkt_mod,
+					tpm_pkt_mod_bm_t pkt_mod_bm,
+					tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_src_port_type_t src_port;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t subflow_field;
+	int32_t ret_code;
+	uint32_t subflow_bm, subflow_id, protocol = 0;
+	long long parse_int_flags_bm = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " dir(%d), rule_num(%d) parse_rule_bm(%x) parse_flag_bm(%x) \n",
+		     	dir, rule_num, parse_rule_bm, parse_flags_bm);
+
+	/* IPV6 parsing, according to parse_rule */
+	tcam_data->ipv6_parse_bm = parse_rule_bm & TPM_IPv6_PARSE_DIP;
+
+	/* Build the AI bits according to parse_flags */
+	if ((parse_rule_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK) ||
+		(parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK)){
+		subflow_bm = parse_rule_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+				protocol = IPPROTO_TCP;
+			else
+				protocol = IPPROTO_UDP;
+			parse_flags_bm &= ~TPM_PARSE_FLAG_L4P_MASK;
+			subflow_bm |= TPM_IPv6_PARSE_NH;
+		}
+		subflow_id = tpm_db_find_matched_ipv6_gen_subflow(dir, subflow_bm, protocol, l4_key, ipv6_gen_key);
+		if (subflow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+			return TPM_FAIL;
+		subflow_field.ipv6_subflow = subflow_id + 1;
+		parse_int_flags_bm |= TPM_PARSE_FLAG_IPV6_SUBFLOW_PARSE;
+	}
+	/*if Ipv6 split, check AI bit, update tcam*/
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) &&
+		(0xff == pkt_mod->vlan_mod.vlan1_out.pbit_mask) &&
+		(pkt_mod_bm == TPM_VLAN_MOD)){
+
+		/*if Ipv6 split or CTC CnM, check AI bit, update tcam*/
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+
+	tpm_proc_parse_flag_ai_tcam_build(&subflow_field, parse_flags_bm, parse_int_flags_bm,
+					  				&(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	if (dir == TPM_DIR_DS)
+		src_port = TPM_SRC_PORT_WAN;
+	else
+		src_port = TPM_SRC_PORT_UNI_ANY;
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = src_port;
+	if (ipv6_dip_key)
+		memcpy(&(tcam_data->pkt_key.ipv6_dip_key), ipv6_dip_key, sizeof(tpm_ipv6_addr_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_DIP, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_l4_ports_5t_tcam_build(tpm_dir_t dir,
+					     uint32_t rule_num,
+					     tpm_l4_ports_key_t *l4_key,
+					     tpm_parse_fields_t parse_rule_bm,
+					     tpm_parse_flags_t parse_flags_bm,
+					     tpm_rule_action_t *rule_action,
+					     tpm_pkt_mod_t *pkt_mod,
+					     tpm_pkt_mod_bm_t pkt_mod_bm,
+					     tpm_pncl_tcam_data_t *tcam_data)
+{
+	tpm_src_port_type_t src_port;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	long long parse_int_flags_bm = 0;
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " dir(%d), rule_num(%d) parse_rule_bm(%x) parse_flag_bm(%x) \n",
+		     	dir, rule_num, parse_rule_bm, parse_flags_bm);
+
+	/* IPV6 parsing, according to parse_rule */
+	tcam_data->l4_parse_bm = parse_rule_bm;
+
+	if (parse_flags_bm & TPM_PARSE_FLAG_L4_UDP) {
+		if (dir == TPM_DIR_DS)
+			parse_int_flags_bm |= TPM_PARSE_FLAG_MC_VID_FALSE;
+	}
+	/*if Ipv6 split, check AI bit, update tcam*/
+	if ((STAGE_CTC_CM == rule_action->next_phase) || ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		(VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) &&
+		(0xff == pkt_mod->vlan_mod.vlan1_out.pbit_mask) &&
+		(pkt_mod_bm == TPM_VLAN_MOD))) {
+
+		/*if Ipv6 split or CTC CnM, check AI bit, update tcam*/
+		parse_int_flags_bm |= TPM_PARSE_FLGA_SPLIT_MOD_TRUE;
+	}
+
+	/* Build the AI bits according to parse_flags */
+	tpm_proc_parse_flag_ai_tcam_build(NULL, parse_flags_bm, parse_int_flags_bm,
+					  &(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	if (dir == TPM_DIR_DS)
+		src_port = TPM_SRC_PORT_WAN;
+	else
+		src_port = TPM_SRC_PORT_UNI_ANY;
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	/* Copy in logical PnC Key */
+	tcam_data->pkt_key.src_port = src_port;
+	if (l4_key)
+		memcpy(&(tcam_data->pkt_key.l4_ports_key), l4_key, sizeof(tpm_l4_ports_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_L4, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_gen_5t_sram_build(tpm_dir_t dir,
+					uint32_t rule_num,
+					tpm_db_pon_type_t pon_type,
+					uint32_t ipv6_gen_subflow,
+					tpm_pkt_frwd_t *pkt_frwd,
+					tpm_rule_action_t *rule_action,
+					long long int_pkt_act,
+					tpm_pkt_mod_t *pkt_mod,
+					uint32_t mod_cmd,
+					tpm_pncl_sram_data_t *sram_data)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_ai_vectors_t subflow_field;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " dir(%d), rule_num(%d) \n", dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Set AI Bits */
+	subflow_field.ipv6_subflow = ipv6_gen_subflow + 1;
+	tpm_proc_static_ai_sram_build(&subflow_field, rule_action->pkt_act, int_pkt_act,
+								&(sram_data->add_info_data), &(sram_data->add_info_mask));
+
+	/* Set L3 */
+	sram_data->l3_type = TPM_PNCL_L3_IPV6;
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_L3;
+
+	if (rule_action->next_phase == STAGE_DONE) {
+		tpm_proc_setstage_done(rule_action, sram_data);
+
+		/* Update dummy register (offset automatically=zero) */
+		sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	} else if (rule_action->next_phase == STAGE_IPv6_DIP) {
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_DIP, &range_conf);
+		IF_ERROR(ret_code);
+
+		sram_data->next_lu_id = range_conf.base_lu_id;
+		sram_data->next_lu_off_reg = TPM_PNC_IPV6_DIP_REG;
+
+		sram_data->next_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+		sram_data->next_offset.offset_sub.ipv6_subf = TPM_IPv6_PARSE_DIP;
+		sram_data->shift_updt_reg = TPM_PNC_IPV6_DIP_REG;
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage not supported\n");
+		return(TPM_FAIL);
+	}
+
+	/* Set Modification */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) {
+		/* split mod stage-2 */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_SPLIT_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_cmd;
+	}
+	else {
+		tpm_proc_set_mod(rule_action, sram_data, mod_cmd);
+	}
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_dip_5t_sram_build(tpm_dir_t dir,
+					uint32_t rule_num,
+					tpm_db_pon_type_t pon_type,
+					tpm_pkt_frwd_t *pkt_frwd,
+					tpm_rule_action_t *rule_action,
+					long long int_pkt_act,
+					tpm_pkt_mod_t *pkt_mod,
+					uint32_t mod_cmd,
+					tpm_pncl_sram_data_t *sram_data)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " dir(%d), rule_num(%d) \n", dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Set AI Bits */
+	tpm_proc_static_ai_sram_build(NULL, rule_action->pkt_act, int_pkt_act,
+								&(sram_data->add_info_data), &(sram_data->add_info_mask));
+
+	/* Next Stage */
+	if (rule_action->next_phase == STAGE_DONE) {
+		tpm_proc_setstage_done(rule_action, sram_data);
+		sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	} else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage not supported\n");
+		return(TPM_FAIL);
+	}
+
+	/* Set Modification */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) {
+		/* split mod stage-2 */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_SPLIT_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_cmd;
+	}
+	else {
+		tpm_proc_set_mod(rule_action, sram_data, mod_cmd);
+	}
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_l4_ports_5t_sram_build(tpm_dir_t dir,
+					     uint32_t rule_num,
+					     tpm_db_pon_type_t pon_type,
+					     uint32_t ipv6_l4_subflow,
+					     tpm_pkt_frwd_t *pkt_frwd,
+					     tpm_rule_action_t *rule_action,
+					     long long int_pkt_act,
+					     tpm_pkt_mod_t *pkt_mod,
+					     uint32_t mod_cmd,
+					     tpm_pncl_sram_data_t *sram_data)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_ai_vectors_t subflow_field;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " dir(%d), rule_num(%d) \n", dir, rule_num);
+
+	/* If packet Drop, nothing else to do */
+	if (PKT_DROP(rule_action->pkt_act)) {
+		sram_data->sram_updt_bm |= (TPM_PNCL_SET_DISC | TPM_PNCL_SET_LUD);
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Packet Drop\n");
+		return(TPM_OK);
+	}
+
+	/* Set AI Bits */
+	subflow_field.ipv6_subflow = ipv6_l4_subflow + 1;
+	tpm_proc_static_ai_sram_build(&subflow_field, rule_action->pkt_act, int_pkt_act,
+								&(sram_data->add_info_data), &(sram_data->add_info_mask));
+
+	/* Set L3 */
+	sram_data->l3_type = TPM_PNCL_L3_IPV6;
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_L3;
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	if (rule_action->next_phase == STAGE_DONE)
+		tpm_proc_setstage_done(rule_action, sram_data);
+	else if (rule_action->next_phase == STAGE_CTC_CM) {
+		/* nothing to Update */
+		sram_data->next_lu_off_reg = TPM_PNC_CNM_L2_REG;
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_MAIN, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+	}
+	else if (rule_action->next_phase == STAGE_IPv6_GEN) {
+		/* nothing to Update */
+		sram_data->next_lu_off_reg = TPM_PNC_LU_REG0; /* lookup reg 0 */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_GEN, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id;
+	}
+	else {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Next stage not supported\n");
+		return(TPM_FAIL);
+	}
+
+	/* Set Modification */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op) {
+		/* split mod stage-2 */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_SPLIT_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_cmd;
+	}
+	else {
+		tpm_proc_set_mod(rule_action, sram_data, mod_cmd);
+	}
+
+	/* For Target set PNC TXP, GemPort */
+	ret_code = tpm_proc_set_trgt_queue(rule_action, pkt_frwd, dir, pon_type, sram_data);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_proc_set_RI_mh(rule_action, pkt_frwd, dir, sram_data);
+	IF_ERROR(ret_code);
+
+	/* Set Customization flag */
+	tpm_proc_set_cust_cpu_packet_parse(rule_action, sram_data);
+
+	return(TPM_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_gen_5t_rule(uint32_t owner_id,
+					       tpm_dir_t src_dir,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l4_ports_key_t *l4_key,
+					       tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_pkt_mod_t *pkt_mod,
+					       tpm_pkt_mod_bm_t pkt_mod_bm,
+					       tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0, bi_dir = 0, is_pppoe;
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+
+	uint32_t subflow_bm, subflow_id, protocol = 0;
+	tpm_ipv6_addr_key_t dip_key;
+	long long int_pkt_act = 0;
+
+	memset(&dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_dir(%d), rule_num(%d)\n", owner_id, src_dir, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv6_gen_5t_check(owner_id, src_dir, rule_num, parse_rule_bm, parse_flags_bm,
+						 					l4_key, ipv6_gen_key, pkt_frwd, pkt_mod_bm, pkt_mod, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_IPV6_GEN_ACL, &range_id);
+
+
+	/*********** Remove Current Entries **********/
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_GEN, &range_data);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_IPV6_GEN_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_num(%d) already exists\n", owner_id, rule_num);
+
+			ret_code = tpm_proc_del_ipv6_gen_5t_rule(owner_id, l_rule_idx, TPM_INT_CALL);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*********** Create Subflow Entries **********/
+	subflow_bm = parse_rule_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
+	if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+			protocol = IPPROTO_TCP;
+		else
+			protocol = IPPROTO_UDP;
+		subflow_bm |= TPM_IPv6_PARSE_NH;
+	}
+	subflow_id = TPM_DB_INVALID_IPV6_FLOW_ID;
+	if (subflow_bm != 0 && rule_action->next_phase != STAGE_DONE) {
+		int_pkt_act |= TPM_ACTION_SET_IPV6_SUBFLOW;
+
+		subflow_id = tpm_db_get_free_ipv6_gen_subflow(src_dir);
+		if (subflow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+			return ERR_IPV6_5T_FLOW_AI_BITS_EXHAUSED;
+	} else {
+		int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
+	}
+
+	/*********** Create Modification Entries **********/
+	/* if split mod stage-2 */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op &&
+		(pkt_mod_bm == TPM_VLAN_MOD)) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod stage-2\n");
+
+		if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+			return(ERR_MOD_INVALID);
+		} else if (trg_gmac == TPM_INVALID_GMAC) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+			return(ERR_MOD_INVALID);
+		}
+
+		/* get mod index from p-bit value */
+		int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pkt_mod->vlan_mod.vlan1_out.pbit, &mod_entry);
+		if (TPM_DB_OK != int_ret_code) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-2, illeagal p-bit value: %d\n",
+				pkt_mod->vlan_mod.vlan1_out.pbit);
+			return ERR_MOD_INVALID;
+		}
+
+		/* the first PMT is for p-bit AS-IS */
+		mod_entry++;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+	} else {
+		ret_code =
+		tpm_proc_create_mod(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm, 0 /*int_mod_bm */ ,
+				    &mod_entry, &trg_gmac);
+		IF_ERROR(ret_code);
+	}
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ipv6_gen_5t_tcam_build(src_dir, rule_num, l4_key, ipv6_gen_key,
+		      					parse_rule_bm, parse_flags_bm, rule_action,
+		      					pkt_mod, pkt_mod_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_ipv6_gen_5t_sram_build(src_dir, rule_num, pon_type, subflow_id,
+							pkt_frwd, rule_action, int_pkt_act,
+							pkt_mod, mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	/*** Insert the PNC Entry ***/
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_IPV6_GEN_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_IPV6_GEN_ACL, rule_num, TPM_FALSE, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	if (src_dir == TPM_DIR_DS)
+		api_data.ipv6_gen_key.src_port = TPM_SRC_PORT_WAN;
+	else
+		api_data.ipv6_gen_key.src_port = TPM_SRC_PORT_UNI_ANY;
+	api_data.ipv6_gen_key.parse_rule_bm = parse_rule_bm;
+	api_data.ipv6_gen_key.parse_flags_bm = parse_flags_bm;
+	api_data.ipv6_gen_key.pkt_mod_bm = pkt_mod_bm;
+
+	memcpy(&(api_data.ipv6_gen_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+	if (l4_key)
+		memcpy(&(api_data.ipv6_gen_key.l4_key), l4_key, sizeof(tpm_l4_ports_key_t));
+	if (ipv6_gen_key)
+		memcpy(&(api_data.ipv6_gen_key.ipv6_gen_key), ipv6_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.ipv6_gen_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.ipv6_gen_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	if (pkt_mod != NULL)
+		memcpy(&(api_data.ipv6_gen_key.pkt_mod), pkt_mod, sizeof(tpm_pkt_mod_t));
+	else
+		memset(&(api_data.ipv6_gen_key.pkt_mod), 0, sizeof(tpm_pkt_mod_t));
+
+	/* Set modification data */
+	tpm_proc_set_api_moddata(rule_action->pkt_act, trg_gmac, &mod_con, mod_entry);
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+		if (rule_num < api_rng_entries) {
+			int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_IPV6_GEN_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(int_ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_IPV6_GEN_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Set 5T Flow Entry */
+	if (subflow_id != TPM_DB_INVALID_IPV6_FLOW_ID) {
+		int_ret_code = tpm_db_set_ipv6_gen_subflow(src_dir, subflow_id, subflow_bm, protocol, l4_key, ipv6_gen_key);
+		IF_ERROR(int_ret_code);
+	}
+	if (rule_action->next_phase == STAGE_DONE) {
+		if (subflow_bm != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_PPPOE_TRUE) != 0)
+				is_pppoe = TPM_TRUE;
+			else
+				is_pppoe = TPM_FALSE;
+			int_ret_code = tpm_db_set_ipv6_5t_flow(src_dir, subflow_bm, is_pppoe, protocol, l4_key, ipv6_gen_key, &dip_key);
+			IF_ERROR(int_ret_code);
+		}
+	}
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_dip_5t_rule(uint32_t owner_id,
+					       tpm_dir_t src_dir,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l4_ports_key_t *l4_key,
+					       tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					       tpm_ipv6_addr_key_t *ipv6_dip_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_pkt_mod_t *pkt_mod,
+					       tpm_pkt_mod_bm_t pkt_mod_bm,
+					       tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0, bi_dir = 0, is_pppoe;
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+
+	uint32_t flow_bm, protocol = 0;
+	long long int_pkt_act = 0;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_dir(%d), rule_num(%d)\n", owner_id, src_dir, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv6_dip_5t_check(owner_id, src_dir, rule_num, parse_rule_bm, parse_flags_bm,
+						 				l4_key, ipv6_gen_key, ipv6_dip_key, pkt_frwd, pkt_mod_bm, pkt_mod, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_IPV6_DIP_ACL, &range_id);
+
+
+	/*********** Remove Current Entries **********/
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_DIP, &range_data);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_IPV6_DIP_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_num(%d) already exists\n", owner_id, rule_num);
+
+			ret_code = tpm_proc_del_ipv6_dip_5t_rule(owner_id, l_rule_idx, TPM_INT_CALL);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*********** Create Subflow Entries **********/
+	int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
+	flow_bm = parse_rule_bm & (TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK | TPM_IPv6_PARSE_DIP);
+	if (parse_rule_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+				protocol = IPPROTO_TCP;
+			else
+				protocol = IPPROTO_UDP;
+			flow_bm |= TPM_IPv6_PARSE_NH;
+		}
+	}
+
+	/*********** Create Modification Entries **********/
+	/* if split mod stage-2 */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op &&
+		(pkt_mod_bm == TPM_VLAN_MOD)) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod stage-2\n");
+
+		if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+			return(ERR_MOD_INVALID);
+		} else if (trg_gmac == TPM_INVALID_GMAC) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+			return(ERR_MOD_INVALID);
+		}
+
+		/* get mod index from p-bit value */
+		int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pkt_mod->vlan_mod.vlan1_out.pbit, &mod_entry);
+		if (TPM_DB_OK != int_ret_code) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-2, illeagal p-bit value: %d\n",
+				pkt_mod->vlan_mod.vlan1_out.pbit);
+			return ERR_MOD_INVALID;
+		}
+
+		/* the first PMT is for p-bit AS-IS */
+		mod_entry++;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+	} else {
+		ret_code =
+		tpm_proc_create_mod(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm, 0 /*int_mod_bm */ ,
+				    &mod_entry, &trg_gmac);
+		IF_ERROR(ret_code);
+	}
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ipv6_dip_5t_tcam_build(src_dir, rule_num, l4_key, ipv6_gen_key, ipv6_dip_key,
+						      	parse_rule_bm, parse_flags_bm, rule_action,
+						      	pkt_mod, pkt_mod_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_ipv6_dip_5t_sram_build(src_dir, rule_num, pon_type,
+							pkt_frwd, rule_action, int_pkt_act,
+							pkt_mod, mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	/*** Insert the PNC Entry ***/
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_IPV6_DIP_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_IPV6_DIP_ACL, rule_num, TPM_FALSE, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	if (src_dir == TPM_DIR_DS)
+		api_data.ipv6_dip_key.src_port = TPM_SRC_PORT_WAN;
+	else
+		api_data.ipv6_dip_key.src_port = TPM_SRC_PORT_UNI_ANY;
+	api_data.ipv6_dip_key.parse_rule_bm = parse_rule_bm;
+	api_data.ipv6_dip_key.parse_flags_bm = parse_flags_bm;
+	api_data.ipv6_dip_key.pkt_mod_bm = pkt_mod_bm;
+
+	memcpy(&(api_data.ipv6_dip_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+	if (l4_key)
+		memcpy(&(api_data.ipv6_dip_key.l4_key), l4_key, sizeof(tpm_l4_ports_key_t));
+	if (ipv6_gen_key)
+		memcpy(&(api_data.ipv6_dip_key.ipv6_gen_key), ipv6_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+	if (ipv6_dip_key)
+		memcpy(&(api_data.ipv6_dip_key.ipv6_dipkey), ipv6_dip_key, sizeof(tpm_ipv6_addr_key_t));
+
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.ipv6_dip_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.ipv6_dip_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	if (pkt_mod != NULL)
+		memcpy(&(api_data.ipv6_dip_key.pkt_mod), pkt_mod, sizeof(tpm_pkt_mod_t));
+	else
+		memset(&(api_data.ipv6_dip_key.pkt_mod), 0, sizeof(tpm_pkt_mod_t));
+
+	/* Set modification data */
+	tpm_proc_set_api_moddata(rule_action->pkt_act, trg_gmac, &mod_con, mod_entry);
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+		if (rule_num < api_rng_entries) {
+			int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_IPV6_DIP_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(int_ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_IPV6_DIP_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Set 5T Flow Entry */
+	if (flow_bm != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_PPPOE_TRUE) != 0)
+			is_pppoe = TPM_TRUE;
+		else
+			is_pppoe = TPM_FALSE;
+		int_ret_code = tpm_db_set_ipv6_5t_flow(src_dir, flow_bm, is_pppoe, protocol, l4_key, ipv6_gen_key, ipv6_dip_key);
+		IF_ERROR(int_ret_code);
+	}
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_l4_ports_5t_rule(uint32_t owner_id,
+						    tpm_dir_t src_dir,
+						    uint32_t rule_num,
+						    uint32_t *rule_idx,
+						    tpm_parse_fields_t parse_rule_bm,
+						    tpm_parse_flags_t parse_flags_bm,
+						    tpm_l4_ports_key_t *l4_key,
+						    tpm_pkt_frwd_t *pkt_frwd,
+						    tpm_pkt_mod_t *pkt_mod,
+						    tpm_pkt_mod_bm_t pkt_mod_bm,
+						    tpm_rule_action_t *rule_action)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, api_rng_entries = 0;
+	uint32_t l_rule_idx = 0, bi_dir = 0;
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_pnc_ranges_t range_id = 0;
+	tpm_db_pon_type_t pon_type = 0;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+
+	uint32_t subflow_bm, subflow_id, protocol = 0, is_pppoe;
+	tpm_ipv6_gen_acl_key_t gen_key;
+	tpm_ipv6_addr_key_t dip_key;
+	long long int_pkt_act = 0;
+
+	memset(&gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+	memset(&dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_dir(%d), rule_num(%d)\n", owner_id, src_dir, rule_num);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv6_l4_ports_5t_check(owner_id, src_dir, rule_num, parse_rule_bm, parse_flags_bm,
+						 					l4_key, pkt_frwd, pkt_mod_bm, pkt_mod, rule_action);
+	IF_ERROR(ret_code);
+
+	/* Get pon_type */
+	tpm_db_pon_type_get(&pon_type);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_L4_ACL, &range_id);
+
+
+	/*********** Remove Current Entries **********/
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_L4, &range_data);
+
+	if (TPM_RANGE_TYPE_TABLE == range_data.pnc_range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_L4_ACL, rule_num, &l_rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_num(%d) already exists\n", owner_id, rule_num);
+
+			ret_code = tpm_proc_del_ipv6_l4_ports_5t_rule(owner_id, rule_num, TPM_INT_CALL);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*********** Create Subflow Entries **********/
+	subflow_bm = parse_rule_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+	if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+			protocol = IPPROTO_TCP;
+		else
+			protocol = IPPROTO_UDP;
+		subflow_bm |= TPM_IPv6_PARSE_NH;
+	}
+	subflow_id = TPM_DB_INVALID_IPV6_FLOW_ID;
+	if (rule_action->next_phase == STAGE_CTC_CM) {
+		/* do not touch sub-flow AI, because they are for UNI also */
+		int_pkt_act |= TPM_ACTION_UNSET_CNM_IPV4 | TPM_ACTION_UNSET_IPV4_PRE_KEY;
+	} else if (subflow_bm != 0 && rule_action->next_phase != STAGE_DONE) {
+		int_pkt_act |= TPM_ACTION_SET_IPV6_SUBFLOW;
+
+		subflow_id = tpm_db_get_free_ipv6_l4_subflow(src_dir);
+		if (subflow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+			return ERR_IPV6_5T_FLOW_AI_BITS_EXHAUSED;
+	} else {
+		int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
+	}
+
+	/*********** Create Modification Entries **********/
+	/* if split mod stage-2 */
+	if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) &&
+		VLANOP_SPLIT_MOD_PBIT == pkt_mod->vlan_mod.vlan_op &&
+		(pkt_mod_bm == TPM_VLAN_MOD)) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod stage-2\n");
+
+		if (tpm_proc_trg_port_gmac_map(pkt_frwd->trg_port, &trg_gmac)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "tpm_proc_trg_port_gmac_map failed \n");
+			return(ERR_MOD_INVALID);
+		} else if (trg_gmac == TPM_INVALID_GMAC) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Target gmac invalid (%d) \n", trg_gmac);
+			return(ERR_MOD_INVALID);
+		}
+
+		/* get mod index from p-bit value */
+		int_ret_code = tpm_db_split_mod_get_index_by_p_bits(pkt_mod->vlan_mod.vlan1_out.pbit, &mod_entry);
+		if (TPM_DB_OK != int_ret_code) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "split mod stage-2, illeagal p-bit value: %d\n",
+				pkt_mod->vlan_mod.vlan1_out.pbit);
+			return ERR_MOD_INVALID;
+		}
+
+		/* the first PMT is for p-bit AS-IS */
+		mod_entry++;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Modification mod_cmd(%d)\n", mod_entry);
+	} else {
+		ret_code =
+		tpm_proc_create_mod(rule_action->pkt_act, pkt_frwd->trg_port, pkt_mod, pkt_mod_bm, 0 /*int_mod_bm */ ,
+				    &mod_entry, &trg_gmac);
+		IF_ERROR(ret_code);
+	}
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_ipv6_l4_ports_5t_tcam_build(src_dir, rule_num, l4_key,
+						      	parse_rule_bm, parse_flags_bm, rule_action,
+						      	pkt_mod, pkt_mod_bm, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	/* Build SRAM Entry */
+	int_ret_code = tpm_proc_ipv6_l4_ports_5t_sram_build(src_dir, rule_num, pon_type, subflow_id,
+							pkt_frwd, rule_action, int_pkt_act,
+							pkt_mod, mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	/*** Insert the PNC Entry ***/
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+	    /*** Insert the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_acl_pnc_entry(TPM_L4_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code =
+		tpm_proc_create_table_pnc_entry(TPM_L4_ACL, rule_num, TPM_FALSE, &pnc_data, &pnc_entry,
+						&api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	if (src_dir == TPM_DIR_DS)
+		api_data.ipv6_l4_key.src_port = TPM_SRC_PORT_WAN;
+	else
+		api_data.ipv6_l4_key.src_port = TPM_SRC_PORT_UNI_ANY;
+	api_data.ipv6_l4_key.parse_rule_bm = parse_rule_bm;
+	api_data.ipv6_l4_key.parse_flags_bm = parse_flags_bm;
+	api_data.ipv6_l4_key.pkt_mod_bm = pkt_mod_bm;
+
+	memcpy(&(api_data.ipv6_l4_key.rule_action), rule_action, sizeof(tpm_rule_action_t));
+	if (l4_key)
+		memcpy(&(api_data.ipv6_l4_key.l4_key), l4_key, sizeof(tpm_l4_ports_key_t));
+
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.ipv6_l4_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.ipv6_l4_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	if (pkt_mod != NULL)
+		memcpy(&(api_data.ipv6_l4_key.pkt_mod), pkt_mod, sizeof(tpm_pkt_mod_t));
+	else
+		memset(&(api_data.ipv6_l4_key.pkt_mod), 0, sizeof(tpm_pkt_mod_t));
+
+	/* Set modification data */
+	tpm_proc_set_api_moddata(rule_action->pkt_act, trg_gmac, &mod_con, mod_entry);
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+	if (TPM_RANGE_TYPE_ACL == range_data.pnc_range_conf.range_type) {
+		if (rule_num < api_rng_entries) {
+			int_ret_code = tpm_proc_api_entry_rulenum_inc(TPM_L4_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(int_ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	int_ret_code = tpm_db_api_entry_set(TPM_L4_ACL, rule_num, 0 /*bi_dir */ ,
+					    &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(int_ret_code);
+
+	/* Set 5T Flow Entry */
+	if (subflow_id != TPM_DB_INVALID_IPV6_FLOW_ID) {
+		int_ret_code = tpm_db_set_ipv6_l4_subflow(src_dir, subflow_id, subflow_bm, protocol, l4_key);
+		IF_ERROR(int_ret_code);
+	}
+	if (rule_action->next_phase == STAGE_DONE) {
+		if (subflow_bm != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_PPPOE_TRUE) != 0)
+				is_pppoe = TPM_TRUE;
+			else
+				is_pppoe = TPM_FALSE;
+			int_ret_code = tpm_db_set_ipv6_5t_flow(src_dir, subflow_bm, is_pppoe, protocol, l4_key, &gen_key, &dip_key);
+			IF_ERROR(int_ret_code);
+		}
+	}
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	return(TPM_RC_OK);
+}
+
+
+tpm_error_code_t tpm_proc_int_del_5t_rule(tpm_api_type_t api_type, tpm_proc_common_int_del_func_t int_del_func,
+					  uint32_t busy_check, uint32_t owner_id, uint32_t rule_idx)
+{
+	int32_t ret_code, busy_ret_code = TPM_RC_OK;
+
+	/* Check API_type busy */
+	if (TPM_TRUE == busy_check) {
+		ret_code = tpm_proc_check_api_busy(api_type, rule_idx);
+		IF_ERROR(ret_code);
+	}
+
+	/* Call internal function */
+	ret_code = (*int_del_func)(owner_id, rule_idx);
+
+	/* Free API_type */
+	if (TPM_TRUE == busy_check)
+		busy_ret_code = tpm_proc_api_busy_done(api_type, rule_idx);
+
+	IF_ERROR(ret_code);
+	IF_ERROR(busy_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_int_del_ipv6_gen_5t_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	int32_t ret_code;
+	uint32_t rule_num, dummy_idx, src_dir, bi_dir, is_pppoe;
+	tpm_db_pnc_range_t range_data;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+	tpm_db_pnc_conn_t pnc_con;
+
+	uint32_t parse_rule_bm, parse_flags_bm, flow_bm, flow_id, flow_user, protocol = 0;
+	tpm_rule_action_t rule_action;
+	tpm_l4_ports_key_t *l4_key = NULL;
+	tpm_ipv6_gen_acl_key_t *gen_key = NULL;
+	tpm_ipv6_addr_key_t dip_key;
+
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+	memset(&api_data, 0, sizeof(tpm_rule_entry_t));
+	memset(&rule_action, 0, sizeof(rule_action));
+	memset(&dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_GEN, &range_data);
+
+	/* Get the rule_num */
+	if (range_data.pnc_range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+		ret_code = tpm_db_api_rulenum_get(TPM_IPV6_GEN_ACL, rule_idx, &rule_num);
+		if (ret_code == TPM_DB_ERR_REC_NOT_EXIST) {
+			TPM_OS_ERROR(TPM_DB_MOD, " The rule non-exist!\n");
+			return ERR_RULE_IDX_INVALID;
+		}
+	} else
+		rule_num = rule_idx;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "with rule_num(%d)\n", rule_num);
+
+	ret_code = tpm_db_api_entry_get(TPM_IPV6_GEN_ACL, rule_num, &dummy_idx, &bi_dir, &api_data, &mod_con, &pnc_con);
+	IF_ERROR(ret_code);
+
+	tpm_proc_src_port_dir_map(api_data.ipv6_gen_key.src_port, &src_dir);
+
+	parse_rule_bm = api_data.ipv6_gen_key.parse_rule_bm;
+	parse_flags_bm = api_data.ipv6_gen_key.parse_flags_bm;
+	rule_action = api_data.ipv6_gen_key.rule_action;
+
+	l4_key = &api_data.ipv6_gen_key.l4_key;
+	gen_key = &api_data.ipv6_gen_key.ipv6_gen_key;
+
+
+	flow_bm = parse_rule_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
+	if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+			protocol = IPPROTO_TCP;
+		else
+			protocol = IPPROTO_UDP;
+		flow_bm |= TPM_IPv6_PARSE_NH;
+	}
+	if (flow_bm != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_PPPOE_TRUE) != 0)
+			is_pppoe = TPM_TRUE;
+		else
+			is_pppoe = TPM_FALSE;
+		flow_id = tpm_db_find_matched_ipv6_5t_flow(src_dir, flow_bm, is_pppoe, protocol, l4_key, gen_key, &dip_key);
+		if (flow_id != TPM_DB_INVALID_IPV6_FLOW_ID) {
+			ret_code = tpm_db_del_ipv6_5t_flow(flow_id);
+			IF_ERROR(ret_code);
+		}
+		if (rule_action.next_phase != STAGE_DONE) {
+			flow_id = tpm_db_find_matched_ipv6_gen_subflow(src_dir, flow_bm, protocol, l4_key, gen_key);
+			if (flow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+				IF_ERROR(ERR_GENERAL);
+
+			flow_user = tpm_db_get_ipv6_gen_subflow_user_num(src_dir, flow_id);
+
+			if (flow_user == 0) {
+				ret_code = tpm_db_del_ipv6_gen_subflow(src_dir, flow_id);
+				IF_ERROR(ret_code);
+			} else {
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d) is used by other ipv6 flows! \n", rule_num);
+				IF_ERROR(ERR_IPV6_5T_RULE_IN_USE);
+			}
+		}
+	}
+	/* Call generic del function without locking, since locking has already been done */
+	ret_code = tpm_proc_del_acl_rule(TPM_IPV6_GEN_ACL, owner_id, rule_idx, TPM_FALSE);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_ipv6_gen_5t_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d), ext_call(%d)", owner_id, rule_idx, ext_call);
+
+	ret_code = tpm_proc_int_del_5t_rule(TPM_API_IPV6_GEN, &tpm_proc_int_del_ipv6_gen_5t_rule,
+					    ext_call, owner_id, rule_idx);
+	return(ret_code);
+}
+
+
+tpm_error_code_t tpm_proc_int_del_ipv6_dip_5t_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	int32_t ret_code;
+	uint32_t rule_num, dummy_idx, src_dir, bi_dir, is_pppoe;
+	tpm_db_pnc_range_t range_data;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con = {0, 0};
+	tpm_db_pnc_conn_t pnc_con;
+
+	uint32_t parse_rule_bm, parse_flags_bm, flow_bm, flow_id, protocol = 0;
+	tpm_rule_action_t rule_action;
+	tpm_l4_ports_key_t *l4_key = NULL;
+	tpm_ipv6_gen_acl_key_t *gen_key = NULL;
+	tpm_ipv6_addr_key_t *dip_key = NULL;
+
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+	memset(&api_data, 0, sizeof(tpm_rule_entry_t));
+	memset(&rule_action, 0, sizeof(rule_action));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_DIP, &range_data);
+
+	/* Get the rule_num */
+	if (range_data.pnc_range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+		ret_code = tpm_db_api_rulenum_get(TPM_IPV6_DIP_ACL, rule_idx, &rule_num);
+		if (ret_code == TPM_DB_ERR_REC_NOT_EXIST) {
+			TPM_OS_ERROR(TPM_DB_MOD, " The rule non-exist!\n");
+			return ERR_RULE_IDX_INVALID;
+		}
+	} else
+		rule_num = rule_idx;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "with rule_num(%d)\n", rule_num);
+
+	ret_code = tpm_db_api_entry_get(TPM_IPV6_DIP_ACL, rule_num, &dummy_idx, &bi_dir, &api_data, &mod_con, &pnc_con);
+	IF_ERROR(ret_code);
+
+	tpm_proc_src_port_dir_map(api_data.ipv6_dip_key.src_port, &src_dir);
+
+	parse_rule_bm = api_data.ipv6_dip_key.parse_rule_bm;
+	parse_flags_bm = api_data.ipv6_dip_key.parse_flags_bm;
+	rule_action = api_data.ipv6_dip_key.rule_action;
+
+	l4_key = &api_data.ipv6_dip_key.l4_key;
+	gen_key = &api_data.ipv6_dip_key.ipv6_gen_key;
+	dip_key = &api_data.ipv6_dip_key.ipv6_dipkey;
+
+
+	flow_bm = parse_rule_bm & (TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK | TPM_IPv6_PARSE_DIP);
+	if (flow_bm != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+				protocol = IPPROTO_TCP;
+			else
+				protocol = IPPROTO_UDP;
+			flow_bm |= TPM_IPv6_PARSE_NH;
+		}
+		if ((parse_flags_bm & TPM_PARSE_FLAG_PPPOE_TRUE) != 0)
+			is_pppoe = TPM_TRUE;
+		else
+			is_pppoe = TPM_FALSE;
+		flow_id = tpm_db_find_matched_ipv6_5t_flow(src_dir, flow_bm, is_pppoe, protocol, l4_key, gen_key, dip_key);
+		if (flow_id != TPM_DB_INVALID_IPV6_FLOW_ID) {
+			ret_code = tpm_db_del_ipv6_5t_flow(flow_id);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Call generic del function without locking, since locking has already been done */
+	ret_code = tpm_proc_del_acl_rule(TPM_IPV6_DIP_ACL, owner_id, rule_idx, TPM_FALSE);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_ipv6_dip_5t_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d), ext_call(%d)", owner_id, rule_idx, ext_call);
+
+	ret_code = tpm_proc_int_del_5t_rule(TPM_IPV6_DIP_ACL, &tpm_proc_int_del_ipv6_dip_5t_rule,
+					    ext_call, owner_id, rule_idx);
+	return(ret_code);
+}
+
+tpm_error_code_t tpm_proc_int_del_ipv6_l4_ports_5t_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	int32_t ret_code;
+	uint32_t rule_num, dummy_idx, src_dir, bi_dir, is_pppoe;
+	tpm_db_pnc_range_t range_data;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+	tpm_db_pnc_conn_t pnc_con;
+
+	uint32_t parse_rule_bm, parse_flags_bm, flow_bm, flow_id, flow_user, protocol = 0;
+	tpm_rule_action_t rule_action;
+	tpm_l4_ports_key_t *l4_key = NULL;
+	tpm_ipv6_gen_acl_key_t gen_key;
+	tpm_ipv6_addr_key_t dip_key;
+
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+	memset(&api_data, 0, sizeof(tpm_rule_entry_t));
+	memset(&rule_action, 0, sizeof(rule_action));
+	memset(&gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+	memset(&dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_idx);
+
+	tpm_db_pnc_rng_get(TPM_PNC_IPV6_L4, &range_data);
+
+	/* Get the rule_num */
+	if (range_data.pnc_range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+		ret_code = tpm_db_api_rulenum_get(TPM_L4_ACL, rule_idx, &rule_num);
+		if (ret_code == TPM_DB_ERR_REC_NOT_EXIST) {
+			TPM_OS_ERROR(TPM_DB_MOD, " The rule non-exist!\n");
+			return ERR_RULE_IDX_INVALID;
+		}
+	} else
+		rule_num = rule_idx;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "with rule_num(%d)\n", rule_num);
+
+	ret_code = tpm_db_api_entry_get(TPM_L4_ACL, rule_num, &dummy_idx, &bi_dir, &api_data, &mod_con, &pnc_con);
+	IF_ERROR(ret_code);
+
+	tpm_proc_src_port_dir_map(api_data.ipv6_l4_key.src_port, &src_dir);
+
+	parse_rule_bm = api_data.ipv6_l4_key.parse_rule_bm;
+	parse_flags_bm = api_data.ipv6_l4_key.parse_flags_bm;
+	rule_action = api_data.ipv6_l4_key.rule_action;
+
+	l4_key = &api_data.ipv6_l4_key.l4_key;
+
+
+	flow_bm = parse_rule_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+	if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+			protocol = IPPROTO_TCP;
+		else
+			protocol = IPPROTO_UDP;
+		flow_bm |= TPM_IPv6_PARSE_NH;
+	}
+	if (flow_bm != 0) {
+		if ((parse_flags_bm & TPM_PARSE_FLAG_PPPOE_TRUE) != 0)
+			is_pppoe = TPM_TRUE;
+		else
+			is_pppoe = TPM_FALSE;
+		flow_id = tpm_db_find_matched_ipv6_5t_flow(src_dir, flow_bm, is_pppoe, protocol, l4_key, &gen_key, &dip_key);
+		if (flow_id != TPM_DB_INVALID_IPV6_FLOW_ID) {
+			ret_code = tpm_db_del_ipv6_5t_flow(flow_id);
+			IF_ERROR(ret_code);
+		}
+		if (rule_action.next_phase != STAGE_DONE) {
+			flow_id = tpm_db_find_matched_ipv6_l4_subflow(src_dir, flow_bm, protocol, l4_key);
+			if (flow_id == TPM_DB_INVALID_IPV6_FLOW_ID)
+				IF_ERROR(ERR_GENERAL);
+
+			flow_user = tpm_db_get_ipv6_l4_subflow_user_num(src_dir, flow_id);
+
+			if (flow_user == 0) {
+				ret_code = tpm_db_del_ipv6_l4_subflow(src_dir, flow_id);
+				IF_ERROR(ret_code);
+			} else {
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_num(%d) is used by other ipv6 flows! \n", rule_num);
+				IF_ERROR(ERR_IPV6_5T_RULE_IN_USE);
+			}
+		}
+	}
+
+	/* Call generic del function without locking, since locking has already been done */
+	ret_code = tpm_proc_del_acl_rule(TPM_L4_ACL, owner_id, rule_idx, TPM_FALSE);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_ipv6_l4_ports_5t_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d), ext_call(%d)", owner_id, rule_idx, ext_call);
+
+	ret_code = tpm_proc_int_del_5t_rule(TPM_L4_ACL, &tpm_proc_int_del_ipv6_l4_ports_5t_rule,
+					    ext_call, owner_id, rule_idx);
+	return(ret_code);
+}
+
+
+int32_t tpm_proc_ipv6_mc_tcam_build(tpm_mc_filter_mode_t filter_mode,
+				    uint32_t stream_num,
+				    uint16_t vid,
+				    uint8_t mc_stream_pppoe,
+				    uint8_t ipv6_dst_add[16],
+				    uint8_t sip_index,
+				    uint8_t ignore_sip,
+				    tpm_pncl_tcam_data_t *tcam_data)
+{
+	int32_t int_ret_code;
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id, ai_bits;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t vid_ai_field;
+	tpm_parse_flags_t parse_flags_bm = 0;
+	long long parse_int_flags_bm = 0;
+
+	tcam_data->l2_parse_bm = 0;
+	tcam_data->l3_parse_bm = 0;
+	tcam_data->ipv4_parse_bm = 0;
+	tcam_data->add_info_mask = 0;
+	tcam_data->add_info_data = 0;
+	tcam_data->ipv6_parse_bm = TPM_IPv6_PARSE_DIP;
+
+	/* src port */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	if (vid != 0xFFFF) {
+		int_ret_code = tpm_db_mc_vlan_get_ai_bit(vid, &ai_bits);
+		IF_ERROR(int_ret_code);
+
+		vid_ai_field.mc_vid_entry = ai_bits;
+
+		parse_int_flags_bm |= TPM_PARSE_FLAG_MC_VID_TRUE;
+		parse_int_flags_bm |= TPM_PARSE_FLAG_MC_VID_PARSE;
+	} else
+		parse_int_flags_bm |= TPM_PARSE_FLAG_MC_VID_FALSE;
+
+	if (mc_stream_pppoe)
+		parse_flags_bm |= TPM_PARSE_FLAG_PPPOE_TRUE;
+	else
+		parse_flags_bm |= TPM_PARSE_FLAG_PPPOE_FALSE;
+
+	if (!ignore_sip) {
+		parse_int_flags_bm |= TPM_PARSE_FLAG_IPV6_MC_SIP_PARSE;
+		vid_ai_field.ipv6_mc_sip_indx = sip_index;
+	}
+
+	/* Update the AI bits */
+	tpm_proc_parse_flag_ai_tcam_build(&vid_ai_field, parse_flags_bm, parse_int_flags_bm, &(tcam_data->add_info_data),
+					  &(tcam_data->add_info_mask));
+
+	/* Copy in logical PnC Key */
+	memcpy(tcam_data->pkt_key.ipv6_dip_key.ipv6_ip_add, ipv6_dst_add, 16 * sizeof(uint8_t));
+	memset(tcam_data->pkt_key.ipv6_dip_key.ipv6_ip_add_mask, 0xff, 16);
+
+	/* Get PNC Range information */
+	int_ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_MC_DS, &lu_id, &start_offset);
+	IF_ERROR(int_ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&tcam_data->start_offset, &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
+				    tpm_mc_igmp_mode_t igmp_mode,
+				    tpm_trg_port_type_t target_port,
+				    uint32_t mod_entry,
+				    tpm_pncl_sram_data_t *sram_data)
+{
+	tpm_db_mh_src_t ds_mh_src;
+	tpm_init_virt_uni_t virt_uni;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " target_port(%d)\n", target_port);
+
+	/* Update dummy register (offset automatically=zero) */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	sram_data->sram_updt_bm = TPM_PNCL_SET_LUD;
+
+	/* Set MH */
+	if (tpm_db_get_mc_per_uni_vlan_xlate() == 0) {
+		tpm_db_ds_mh_get_conf_set(&ds_mh_src);
+
+		if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+			if (TPM_MH_SRC_PNC_RI == ds_mh_src) {
+				sram_data->sram_updt_bm |= TPM_PNCL_SET_MH_RI;
+				sram_data->mh_reg.mh_set = TPM_TRUE;
+
+				tpm_db_virt_info_get(&virt_uni);
+				if (virt_uni.enabled)
+					sram_data->mh_reg.mh_reg = (TPM_MH_RI_BIT16 | TPM_MH_RI_BIT15);
+				else
+					sram_data->mh_reg.mh_reg = (TPM_MH_RI_BIT17 | TPM_MH_RI_BIT16 |
+								    TPM_MH_RI_BIT15 | TPM_MH_RI_BIT14);
+			} else {
+				sram_data->mh_reg.mh_set = TPM_FALSE;
+				sram_data->mh_reg.mh_reg = 0;
+			}
+		} else if (filter_mode == TPM_MC_IP_ONLY_FILTER) {
+			/* Target UNI is set by Modification Entry */
+		}
+	} else {
+		/* Target UNI is set by Modification Entry */
+	}
+
+	/* Set modification command */
+	if (mod_entry != 0) {
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_entry;
+	}
+
+	/* Set Target Port */
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
+	if (target_port == TPM_TRG_PORT_CPU) {
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+		sram_data->pnc_queue = tpm_db_get_mc_cpu_queue();
+	} else {
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_GMAC0;
+		sram_data->pnc_queue = tpm_db_get_mc_hwf_queue();
+	}
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_ipv6_mc_sip_entry_create(uint32_t sip_index, uint8_t *ipv6_src_add)
+{
+	int32_t int_ret_code;
+	uint32_t pnc_entry, lu_id;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data;
+	tpm_gmac_bm_t gmac_bm;
+	uint8_t ipv6_src_zero[16];
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&ipv6_src_zero, 0, sizeof(ipv6_src_zero));
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_SIP, &range_data);
+	IF_ERROR(int_ret_code);
+	lu_id = range_data.pnc_range_conf.base_lu_id;
+
+	pnc_entry = range_data.pnc_range_conf.range_start + sip_index;
+
+	/* Set common TCAM params */
+	/* Get PNC Range information */
+	int_ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_MC_SIP, &lu_id, &start_offset);
+	IF_ERROR(int_ret_code);
+	pnc_data.pncl_tcam.lu_id = lu_id;
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	pnc_data.pncl_tcam.port_ids = gmac_bm;
+	memcpy(&(pnc_data.pncl_tcam.start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+	pnc_data.pncl_tcam.ipv6_parse_bm = TPM_IPv6_PARSE_SIP;
+
+	/* Set common SRAM params */
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+	pnc_data.pncl_sram.next_offset.offset_sub.ipv6_subf = TPM_IPv6_PARSE_DIP;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_IPV6_DIP_REG;
+	pnc_data.pncl_sram.next_lu_off_reg = TPM_PNC_IPV6_DIP_REG; /* lookup reg 6 */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_DS, &range_data);
+	IF_ERROR(int_ret_code);
+	pnc_data.pncl_sram.next_lu_id = range_data.pnc_range_conf.base_lu_id;
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+
+	/* Double check - check only packets that are MC */
+	pnc_data.pncl_tcam.add_info_data = (1 << TPM_AI_MC_VID_VALID_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_MC_VID_VALID_MASK;
+
+	if (0 == memcmp(ipv6_src_zero, ipv6_src_add, sizeof(ipv6_src_zero))) {
+		/* this is the default rule */
+		pnc_data.pncl_sram.add_info_data &= ~(TPM_AI_IPV6_MC_SIP_PART1_MASK);
+		pnc_data.pncl_sram.add_info_data &= ~(TPM_AI_IPV6_MC_SIP_PART2_MASK);
+	} else {
+		/* update MC_SIP AI to sip_index */
+		pnc_data.pncl_sram.add_info_data |= ((sip_index << TPM_AI_IPV6_MC_SIP_PART1_BIT_OFF)& TPM_AI_IPV6_MC_SIP_PART1_MASK);
+		pnc_data.pncl_sram.add_info_data |= (((sip_index >> (TPM_AI_IPV6_MC_SIP_PART1_BIT_OFF + 1))
+			<< TPM_AI_IPV6_MC_SIP_PART2_BIT_OFF)& TPM_AI_IPV6_MC_SIP_PART2_MASK);
+		memcpy(pnc_data.pncl_tcam.pkt_key.ipv6_gen_key.ipv6_src_ip_add, ipv6_src_add, 16);
+		memset(pnc_data.pncl_tcam.pkt_key.ipv6_gen_key.ipv6_src_ip_add_mask, 0xff, 16);
+
+		pnc_entry--;
+	}
+
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_IPV6_MC_SIP_PART1_MASK;
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_IPV6_MC_SIP_PART2_MASK;
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV6_MC_SIP, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	return TPM_RC_OK;
+}
+int32_t tpm_proc_ipv6_mc_sip_entry_del(uint32_t sip_index)
+{
+	int32_t int_ret_code;
+	uint32_t pnc_entry;
+	tpm_db_pnc_range_t range_data;
+
+	/* Get Range data */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_SIP, &range_data);
+	IF_ERROR(int_ret_code);
+
+	pnc_entry = range_data.pnc_range_conf.range_start + sip_index - 1;
+
+	/* del Entry in PnC */
+	int_ret_code = tpm_pncl_entry_reset(pnc_entry);
+	IF_ERROR(int_ret_code);
+
+	/* Increase number of free entries in pnc_range */
+	int_ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_IPV6_MC_SIP);
+	IF_ERROR(int_ret_code);
+
+	return TPM_RC_OK;
+}
+
+int32_t tpm_proc_create_ipv6_mc_mod(tpm_mc_filter_mode_t filter_mode,
+				    tpm_mc_igmp_mode_t igmp_mode,
+				    uint8_t mc_stream_pppoe,
+				    uint16_t vid,
+				    uint8_t *group_addr,
+				    uint32_t dest_port_bm,
+				    uint32_t *mod_entry)
+{
+	int32_t ret_code;
+	tpm_pkt_mod_bm_t pkt_mod_bm = 0;
+	tpm_pkt_mod_t pkt_mod;
+	uint8_t mc_mac[6];
+	uint32_t lpbk_port_bm = 0, entry_id;
+	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
+	uint8_t valid;
+	uint32_t switch_init;
+	uint32_t mh_en;
+	/*struct net_device *dev = NULL;*/
+
+	memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
+
+	/*get switch init*/
+	ret_code = tpm_db_switch_init_get(&switch_init);
+	IF_ERROR(ret_code);
+
+	/*get MH EN */
+	ret_code = tpm_db_gmac_mh_en_conf_get(TPM_ENUM_GMAC_0, &mh_en);
+	IF_ERROR(ret_code);
+
+	if (filter_mode == TPM_MC_IP_ONLY_FILTER && mh_en) {
+		/* TODO: Check virt_port status. If it is not enabled, set target_port via MH_Tx_reg in RI. */
+		pkt_mod_bm |= TPM_MH_SET;
+		pkt_mod.mh_mod = tpm_db_trg_port_switch_port_get(dest_port_bm);
+	}
+
+	if (tpm_db_get_mc_per_uni_vlan_xlate() == 0) {
+		if (vid != 0xffff) {
+			if (tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg) == TPM_OK) {
+				for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
+					if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSLATE) {
+						pkt_mod_bm |= TPM_VLAN_MOD;
+
+						pkt_mod.vlan_mod.vlan_op = VLANOP_EXT_TAG_MOD;
+						pkt_mod.vlan_mod.vlan1_out.tpid = 0x8100;
+						pkt_mod.vlan_mod.vlan1_out.pbit = 0;
+						pkt_mod.vlan_mod.vlan1_out.pbit_mask = 0x0;
+						pkt_mod.vlan_mod.vlan1_out.cfi = 0;
+						pkt_mod.vlan_mod.vlan1_out.cfi_mask = 0x0;
+						pkt_mod.vlan_mod.vlan1_out.vid = mc_vid_cfg[entry_id].uni_port_vid;
+						pkt_mod.vlan_mod.vlan1_out.vid_mask = 0xffff;
+						break;
+					} else if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP) {
+						/* Just for MC, no switch */
+						if (switch_init == 0) {
+							pkt_mod_bm |= TPM_VLAN_MOD;
+
+							pkt_mod.vlan_mod.vlan_op = VLANOP_EXT_TAG_DEL;
+							break;
+						}
+					}
+				}
+			} else
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " not found mv_vlan_cfg %d, assume as transparent! \n", vid);
+		}
+	} else if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		pkt_mod_bm |= TPM_MH_SET;
+
+		ret_code = tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg);
+		IF_ERROR(ret_code);
+
+		for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
+			if (mc_vid_cfg[entry_id].tpm_src_port != TPM_SRC_PORT_UNI_VIRT) {
+				if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSPARENT ||
+				    mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP) {
+					lpbk_port_bm |=
+					TPM_TRG_UNI_0 << (mc_vid_cfg[entry_id].tpm_src_port - TPM_SRC_PORT_UNI_0);
+				}
+			}
+		}
+		lpbk_port_bm |= TPM_TRG_UNI_VIRT;
+
+		pkt_mod.mh_mod = tpm_db_trg_port_switch_port_get(lpbk_port_bm);
+	}
+
+	if (igmp_mode == TPM_MC_IGMP_PROXY) {
+#if 0
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+		dev = dev_get_by_name("eth0");
+#else
+		dev = dev_get_by_name(&init_net, "eth0");
+#endif
+		if (dev == NULL)
+			IF_ERROR(ERR_GENERAL);
+
+		pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+		pkt_mod.mac_mod.mac_sa[0] = ((uint8_t *) dev->dev_addr)[0];
+		pkt_mod.mac_mod.mac_sa[1] = ((uint8_t *) dev->dev_addr)[1];
+		pkt_mod.mac_mod.mac_sa[2] = ((uint8_t *) dev->dev_addr)[2];
+		pkt_mod.mac_mod.mac_sa[3] = ((uint8_t *) dev->dev_addr)[3];
+		pkt_mod.mac_mod.mac_sa[4] = ((uint8_t *) dev->dev_addr)[4];
+		pkt_mod.mac_mod.mac_sa[5] = ((uint8_t *) dev->dev_addr)[5];
+
+		pkt_mod.mac_mod.mac_sa_mask[0] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[1] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[2] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[3] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[4] = 0xff;
+		pkt_mod.mac_mod.mac_sa_mask[5] = 0xff;
+#endif
+
+		pkt_mod_bm |= (TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+		tpm_db_get_mc_igmp_proxy_sa_mac(mc_mac, &valid);
+
+		if (valid) {
+			memcpy(pkt_mod.mac_mod.mac_sa, mc_mac, 6 * sizeof(uint8_t));
+			memset(pkt_mod.mac_mod.mac_sa_mask, 0xff, 6 * sizeof(uint8_t));
+		} else
+			IF_ERROR(ERR_GENERAL);
+
+		if (mc_stream_pppoe) {
+			pkt_mod_bm |= (TPM_MAC_DA_SET | TPM_PPPOE_DEL);
+			MULTI_IPV6_2_MAC(mc_mac, group_addr);
+			memcpy(pkt_mod.mac_mod.mac_da, mc_mac, 6 * sizeof(uint8_t));
+			memset(pkt_mod.mac_mod.mac_da_mask, 0xff, 6 * sizeof(uint8_t));
+		}
+	}
+
+	if (pkt_mod_bm != 0) {
+		ret_code = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0,
+			pkt_mod_bm, TPM_INT_MC_MOD, &pkt_mod, mod_entry);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_OK);
+}
+tpm_error_code_t tpm_proc_add_ipv6_mc_check(uint32_t owner_id,
+						uint32_t stream_num,
+						tpm_mc_igmp_mode_t igmp_mode,
+						uint8_t mc_stream_pppoe,
+						uint16_t vid,
+						uint8_t ipv6_src_add[16],
+						uint8_t ipv6_dst_add[16],
+						uint8_t ignore_ipv6_src,
+						tpm_trg_port_type_t dest_port_bm,
+						tpm_mc_filter_mode_t filter_mode)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code, index;
+	tpm_db_pnc_range_t range_data;
+	uint32_t ai_bit;
+	tpm_init_virt_uni_t virt_uni;
+	uint32_t pnc_rng_free_size;
+
+	/* Check TPM was successfully initialized */
+	if (!tpm_db_init_done_get())
+		IF_ERROR(ERR_SW_NOT_INIT);
+
+	ret_code = tpm_owner_id_check(TPM_API_IPV6_MC, owner_id);
+	IF_ERROR(ret_code);
+
+	/* Get PNC Range Start */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_DS, &range_data);
+	IF_ERROR(int_ret_code);
+
+	if (stream_num >= range_data.pnc_range_conf.range_size)
+		IF_ERROR(ERR_MC_STREAM_INVALID);
+
+	ret_code = tpm_proc_check_dst_uni_port(dest_port_bm);
+	IF_ERROR(ret_code);
+
+	/*check virt range size if necessary*/
+	if(filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		if ((tpm_db_get_mc_per_uni_vlan_xlate() != 0) && ((dest_port_bm & TPM_TRG_UNI_VIRT) != 0)) {
+			int_ret_code = tpm_db_pnc_rng_free_ent_get(TPM_PNC_VIRT_UNI, &pnc_rng_free_size);
+			IF_ERROR(int_ret_code);
+			if(pnc_rng_free_size == 0)
+				IF_ERROR(ERR_OUT_OF_RESOURCES);
+		}
+	}
+
+	/* fix bug of adding 1-2-3 instead of 0-1-2 => when 3 is over-writing the hardcoded entry */
+	if ((stream_num < range_data.pnc_range_conf.api_start) || (stream_num > range_data.pnc_range_conf.api_end))
+		IF_ERROR(ERR_MC_STREAM_INVALID);
+
+	tpm_db_api_entry_ind_get(TPM_IPV6_MC_ACL, stream_num, &index);
+	if (-1 != index)
+		IF_ERROR(ERR_MC_STREAM_EXISTS);
+
+	tpm_db_virt_info_get(&virt_uni);
+
+	if (vid == 0xffff) {
+		if (tpm_db_get_mc_filter_mode() == TPM_MC_IP_ONLY_FILTER) {
+			if (virt_uni.enabled) {
+				TPM_OS_WARN(TPM_TPM_LOG_MOD,
+					    " filter mode fall back to MC_COMBINED_MAC_IP_FILTER \r\n");
+			}
+		}
+
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+				    "when mc_per_uni_vlan_xlate is enabled, untagged mcast stream is not supported, "
+				    "and MC VID must be specified \r\n");
+			IF_ERROR(ERR_SW_VID_INVALID);
+		}
+	} else {
+		if (tpm_db_mc_vlan_get_ai_bit(vid, &ai_bit) != TPM_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD,
+				    "MC VID must be configured first \r\n");
+			IF_ERROR(ERR_SW_VID_INVALID);
+		}
+	}
+
+	if (mc_stream_pppoe) {
+		if (tpm_db_get_mc_pppoe_enable() == 0)
+			IF_ERROR(ERR_FEAT_UNSUPPORT);
+
+		if (igmp_mode == TPM_MC_IGMP_SNOOPING && tpm_db_get_mc_per_uni_vlan_xlate())
+			IF_ERROR(ERR_FEAT_UNSUPPORT);
+	}
+
+	if (ipv6_dst_add[0] != 0xff)
+		IF_ERROR(ERR_IPV6_MC_DST_IP_INVALID);
+
+	if (dest_port_bm & TPM_TRG_UNI_VIRT) {
+		if (virt_uni.enabled == 0)
+			IF_ERROR(ERR_MC_DST_PORT_INVALID);
+	}
+
+	if (dest_port_bm & TPM_TRG_PORT_CPU) {
+		if (dest_port_bm & (~TPM_TRG_PORT_CPU))
+			IF_ERROR(ERR_MC_DST_PORT_INVALID);
+	}
+
+	/* check if there is MC SIP slot */
+	if(0 == ignore_ipv6_src) {
+		if(!tpm_db_ipv6_mc_sip_index_get(ipv6_src_add)) {
+			/* this is a new MC SIP */
+			if(!tpm_db_ipv6_mc_sip_free_slot_num_get())
+				IF_ERROR(ERR_OUT_OF_RESOURCES);
+		}
+	}
+
+	return(TPM_RC_OK);
+}
+tpm_error_code_t tpm_proc_add_ipv6_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
+						uint32_t stream_num,
+						tpm_mc_igmp_mode_t igmp_mode,
+						uint8_t mc_stream_pppoe,
+						uint16_t vid,
+						uint8_t ipv6_src_add[16],
+						uint8_t ipv6_dst_add[16],
+						uint8_t ignore_ipv6_src,
+						uint32_t dest_port_bm)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_range_t range_data;
+	tpm_db_ipv6_mc_stream_entry_t mc_stream;
+	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
+
+	int32_t ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, rule_num = 0xffff;
+	uint32_t pnc_range_start = 0, api_start = 0, rule_idx = 0;
+	uint32_t entry_id;
+	uint16_t u4_vid;
+	int32_t  sip_index = 0;
+
+	memset(&mc_stream, 0, sizeof(tpm_db_mc_stream_entry_t));
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	/*********** Create Modification Entries **********/
+	ret_code =
+	tpm_proc_create_ipv6_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe, vid, ipv6_dst_add,
+				    dest_port_bm, &mod_entry);
+	IF_ERROR(ret_code);
+
+	/* Handle IPv6 SSM */
+	if (0 == ignore_ipv6_src) {
+		/* get index of this IPv6 MC SIP */
+		sip_index = tpm_db_ipv6_mc_sip_index_get(ipv6_src_add);
+		if (0 == sip_index) {
+			/* this is a new SIP, add into DB */
+			sip_index = tpm_db_ipv6_mc_sip_add(ipv6_src_add);
+
+			/* create PNC entry in range TPM_PNC_IPV6_MC_SIP */
+			ret_code = tpm_proc_ipv6_mc_sip_entry_create(sip_index, ipv6_src_add);
+
+		} else {
+			/* this is a exising SIP, add reference number in DB */
+			ret_code = tpm_db_ipv6_mc_sip_ref_num_inc(sip_index);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code =
+	tpm_proc_ipv6_mc_tcam_build(filter_mode, stream_num, vid, mc_stream_pppoe,
+				    ipv6_dst_add, sip_index, ignore_ipv6_src, &(pnc_data.pncl_tcam));
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code =
+	tpm_proc_ipv6_mc_sram_build(filter_mode, igmp_mode, dest_port_bm, mod_entry, &(pnc_data.pncl_sram));
+	IF_ERROR(ret_code);
+
+	/*** Calculate PNC Entry ***/
+
+	/* Get PNC Range Start */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_DS, &range_data);
+	IF_ERROR(ret_code);
+	pnc_range_start = range_data.pnc_range_conf.range_start;
+	api_start = range_data.pnc_range_conf.api_start;
+
+	/* Calculate absolute PNC entry number to execute */
+	pnc_entry = (pnc_range_start + api_start) + stream_num;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " stream_num(%d), pnc_entry(%d)\n", stream_num, pnc_entry);
+
+	ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+	IF_ERROR(ret_code);
+
+	/* Decrease number of free entries in pnc_range */
+	ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_IPV6_MC_DS);
+	IF_ERROR(ret_code);
+
+	/*********** Update API Range in DB **********/
+
+	/* Set API data */
+	memcpy(api_data.ipv6_mc_key.ipv6_dest_add, ipv6_dst_add, 16 * sizeof(uint8_t));
+	api_data.ipv6_mc_key.dest_port_bm = dest_port_bm;
+	api_data.ipv6_mc_key.vid = vid;
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = TPM_PNC_IPV6_MC_DS;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	/* Set Modification Connection data */
+	mod_con.mod_cmd_ind = mod_entry;
+	mod_con.mod_cmd_mac = TPM_PNC_TRG_GMAC0;
+
+	/* Set new API Entry */
+	ret_code = tpm_db_api_entry_set(TPM_IPV6_MC_ACL, stream_num, 0 /*bi_dir */ ,
+					&api_data, &mod_con, &pnc_conn, &rule_idx);
+	IF_ERROR(ret_code);
+
+	if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0 && (dest_port_bm & TPM_TRG_UNI_VIRT) != 0) {
+			ret_code = tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg);
+			IF_ERROR(ret_code);
+
+			for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
+				if (mc_vid_cfg[entry_id].tpm_src_port == TPM_SRC_PORT_UNI_VIRT)
+					break;
+			}
+			if (entry_id == TPM_MAX_NUM_UNI_PORTS) {
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD,
+						 " virt_uni is unable to join the group when "
+						 "virt_uni is not the member of multicast vlan \n");
+			} else if (mc_vid_cfg[entry_id].mc_uni_port_mode != TPM_MC_UNI_MODE_EXCLUDE) {
+				if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSPARENT)
+					u4_vid = vid;
+				else if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP)
+					u4_vid = 0xffff;
+				else
+					u4_vid = mc_vid_cfg[entry_id].uni_port_vid;
+
+				ret_code = tpm_db_mc_alloc_virt_uni_entry(&rule_num);
+				IF_ERROR(ret_code);
+
+				ret_code =
+				tpm_proc_mc_create_virt_uni_pnc_entry(rule_num, u4_vid, ipv6_dst_add, true);
+				IF_ERROR(ret_code);
+			}
+		}
+	}
+
+	/* Set new stream entry */
+	mc_stream.igmp_mode = igmp_mode;
+	mc_stream.mc_stream_pppoe = mc_stream_pppoe;
+	mc_stream.vid = vid;
+	mc_stream.dest_port_bm = dest_port_bm;
+	mc_stream.u4_entry = rule_num;
+	mc_stream.ignore_src_addr = ignore_ipv6_src;
+	memcpy(mc_stream.group_addr, ipv6_dst_add, 16 * sizeof(uint8_t));
+	memcpy(mc_stream.src_addr, ipv6_src_add, 16 * sizeof(uint8_t));
+
+	ret_code = tpm_db_set_ipv6_mc_stream_entry(stream_num, &mc_stream);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_add_ipv6_mc_stream(uint32_t owner_id,
+					     uint32_t stream_num,
+					     tpm_mc_igmp_mode_t igmp_mode,
+					     uint8_t mc_stream_pppoe,
+					     uint16_t vid,
+					     uint8_t ipv6_src_add[16],
+					     uint8_t ipv6_dst_add[16],
+					     uint8_t ignore_ipv6_src,
+					     tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code;
+	tpm_mc_filter_mode_t filter_mode;
+	uint8_t mc_mac[6];
+	tpm_init_virt_uni_t virt_uni;
+
+	memset(&virt_uni, 0, sizeof(tpm_init_virt_uni_t));
+
+	/*
+	filter_mode = tpm_db_get_mc_filter_mode();
+	right now we only have TPM_MC_COMBINED_IP_MAC_FILTER mode
+	*/
+	filter_mode = TPM_MC_COMBINED_IP_MAC_FILTER;
+	if (filter_mode == TPM_MC_ALL_CPU_FRWD) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " illegal mc_filter_mod (%d)\n", filter_mode);
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	if (dest_port_bm & TPM_TRG_PORT_UNI_ANY)
+		dest_port_bm = tpm_db_trg_port_uni_any_bmp_get(true);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_ipv6_mc_check(owner_id, stream_num, igmp_mode, mc_stream_pppoe, vid,
+						  ipv6_src_add, ipv6_dst_add, ignore_ipv6_src,
+						  dest_port_bm, filter_mode);
+	IF_ERROR(ret_code);
+
+	/* Create PNC entry */
+	ret_code = tpm_proc_add_ipv6_mc_pnc_entry(filter_mode, stream_num, igmp_mode, mc_stream_pppoe, vid,
+						  ipv6_src_add, ipv6_dst_add, ignore_ipv6_src, dest_port_bm);
+	IF_ERROR(ret_code);
+
+	/* Set switch port_map for multicast MAC, but don't overwrite FF02::1 (MLD General Query) MAC */
+	MULTI_IPV6_2_MAC(mc_mac, ipv6_dst_add);
+	if (memcmp(mc_mac, tpm_mld_gen_query_mac, 6) != 0) {
+		ret_code = tpm_proc_set_ipv4_mc_switch(filter_mode, mc_mac, 0, dest_port_bm);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_delete_ipv6_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
+						   uint32_t stream_num,
+						   uint32_t dest_port_bm,
+						   uint32_t u4_entry)
+{
+	tpm_db_pnc_range_t range_data;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_ipv6_mc_stream_entry_t mc_stream;
+
+	int32_t ret_code;
+	uint32_t bi_dir = 0, rule_idx = 0;
+	uint32_t pnc_range_start = 0, api_start = 0, pnc_entry = 0;
+	uint32_t sip_index = 0;
+	uint8_t	 new_ref_num = 0;
+
+	if (filter_mode != TPM_MC_MAC_ONLY_FILTER) {
+		/* Get PNC Range Start */
+		ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_DS, &range_data);
+		IF_ERROR(ret_code);
+
+		if (stream_num >= range_data.pnc_range_conf.range_size)
+			IF_ERROR(ERR_MC_STREAM_INVALID);
+
+		/* Check parameters */
+		ret_code = tpm_db_api_entry_get(TPM_IPV6_MC_ACL, stream_num, &rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		IF_ERROR(ret_code);
+
+		/* Delete PNC Entry */
+#if 0
+		ret_code = tpm_proc_pnc_con_del(&pnc_conn);
+		IF_ERROR(ret_code);
+#endif
+		pnc_range_start = range_data.pnc_range_conf.range_start;
+		api_start = range_data.pnc_range_conf.api_start;
+
+		/* Pull range from this index untill last used entry in Pnc range */
+		pnc_entry = (pnc_range_start + api_start) + stream_num;
+
+		/* Delete PNC entry */
+		ret_code = tpm_pncl_entry_delete(pnc_entry, pnc_entry);
+		IF_ERROR(ret_code);
+
+		/* Increase number of free entries in pnc_range */
+		ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_IPV6_MC_DS);
+		IF_ERROR(ret_code);
+
+		if (mod_con.mod_cmd_ind != 0) {
+			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, mod_con.mod_cmd_ind);
+			IF_ERROR(ret_code);
+		}
+
+		/* Delete API Rule Entry */
+		ret_code = tpm_db_api_entry_invalidate(TPM_IPV6_MC_ACL, stream_num);
+		IF_ERROR(ret_code);
+
+		/* remove SIP PNC entry */
+		ret_code = tpm_db_get_ipv6_mc_stream_entry(stream_num, &mc_stream);
+		IF_ERROR(ret_code);
+		if (0 == mc_stream.ignore_src_addr) {
+			/* get index of this IPv6 MC SIP */
+			sip_index = tpm_db_ipv6_mc_sip_index_get(mc_stream.src_addr);
+			if (0 == sip_index) {
+				/* SIP is not in DB, error */
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, "get index of IPv6 MC SIP failed!\n");
+				return(ERR_IPV6_MC_SRC_IP_INVALID);
+			}
+
+			/* dec reference number in DB */
+			ret_code = tpm_db_ipv6_mc_sip_ref_num_dec(sip_index, &new_ref_num);
+			IF_ERROR(ret_code);
+
+			/* if new ref num is 0, remove this SIP in PNC */
+			if (new_ref_num == 0) {
+				ret_code = tpm_proc_ipv6_mc_sip_entry_del(sip_index);
+				IF_ERROR(ret_code);
+			}
+		}
+
+	}
+
+	if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
+			if (u4_entry != 0xffff) {
+				ret_code = tpm_proc_mc_delete_virt_uni_pnc_entry(u4_entry);
+				IF_ERROR(ret_code);
+
+				ret_code = tpm_db_mc_free_virt_uni_entry(u4_entry);
+				IF_ERROR(ret_code);
+			}
+		}
+	}
+
+	/* Remove stream entry */
+	tpm_db_reset_ipv6_mc_stream_entry(stream_num);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_update_ipv6_mc_pnc_entry(tpm_mc_filter_mode_t filter_mode,
+						   uint32_t stream_num,
+						   tpm_mc_igmp_mode_t igmp_mode,
+						   uint8_t mc_stream_pppoe,
+						   uint16_t vid,
+						   uint8_t ipv6_dst_add[16],
+						   uint8_t sip_index,
+						   uint8_t ignore_sip,
+						   uint32_t dest_port_bm)
+{
+	tpm_db_pnc_range_t range_data;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_ipv6_mc_stream_entry_t mc_stream;
+	tpm_mc_vid_port_cfg_t *mc_vid_cfg = NULL;
+
+	int32_t ret_code;
+	uint32_t bi_dir = 0, rule_idx = 0, pnc_entry = 0, mod_entry = 0, rule_num = 0xffff;
+	uint32_t entry_id;
+	uint16_t u4_vid;
+
+	memset(&mc_stream, 0, sizeof(tpm_db_ipv6_mc_stream_entry_t));
+
+	/* Only MC_IP_ONLY_FILTER mode, update the multicast group member ports by mh_mod. */
+	if (filter_mode == TPM_MC_IP_ONLY_FILTER) {
+		/* Get PNC Range Start */
+		ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_DS, &range_data);
+		IF_ERROR(ret_code);
+
+		if (stream_num >= range_data.pnc_range_conf.range_size)
+			IF_ERROR(ERR_MC_STREAM_INVALID);
+
+		/* Get old API Entry */
+		ret_code = tpm_db_api_entry_get(TPM_IPV6_MC_ACL, stream_num, &rule_idx, &bi_dir,
+						&api_data, &mod_con, &pnc_conn);
+		IF_ERROR(ret_code);
+
+		pnc_entry = pnc_conn.pnc_conn_tbl[0].pnc_index;
+
+		/* Create new Modification Entry */
+		ret_code = tpm_proc_create_ipv6_mc_mod(filter_mode, igmp_mode, mc_stream_pppoe,
+						       vid, ipv6_dst_add, dest_port_bm, &mod_entry);
+		IF_ERROR(ret_code);
+
+		/* Rebuild PnC Entry */
+		ret_code = tpm_proc_ipv6_mc_tcam_build(filter_mode, stream_num, vid, mc_stream_pppoe,
+						       ipv6_dst_add, sip_index, ignore_sip, &(pnc_data.pncl_tcam));
+		IF_ERROR(ret_code);
+
+		/* Rebuild SRAM Entry */
+		ret_code =
+		tpm_proc_ipv6_mc_sram_build(filter_mode, igmp_mode, dest_port_bm, mod_entry, &(pnc_data.pncl_sram));
+		IF_ERROR(ret_code);
+
+		/* Update only Sram of PNC Entry */
+		ret_code = tpm_pncl_update_sram(pnc_entry, &pnc_data);
+		IF_ERROR(ret_code);
+
+		/* Delete old Modification Entry */
+		if (mod_con.mod_cmd_ind != 0) {
+			ret_code = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, TPM_ENUM_GMAC_0, mod_con.mod_cmd_ind);
+			IF_ERROR(ret_code);
+		}
+
+		/* Update new Modification Entry */
+		mod_con.mod_cmd_ind = mod_entry;
+
+		/* Invalidate old API Entry */
+		ret_code = tpm_db_api_entry_invalidate(TPM_IPV6_MC_ACL, stream_num);
+		IF_ERROR(ret_code);
+
+		/* Set new API Entry */
+		mod_con.mod_cmd_ind = mod_entry;
+		ret_code = tpm_db_api_entry_set(TPM_IPV6_MC_ACL, stream_num, 0 /*bi_dir */ ,
+						&api_data, &mod_con, &pnc_conn, &rule_idx);
+		IF_ERROR(ret_code);
+	}
+
+	if (filter_mode == TPM_MC_COMBINED_IP_MAC_FILTER) {
+		if (tpm_db_get_mc_per_uni_vlan_xlate() != 0) {
+			ret_code = tpm_db_get_ipv6_mc_stream_entry(stream_num, &mc_stream);
+			IF_ERROR(ret_code);
+
+			rule_num = mc_stream.u4_entry;
+
+			if ((dest_port_bm & TPM_TRG_UNI_VIRT) != 0 && (mc_stream.dest_port_bm & TPM_TRG_UNI_VIRT) == 0) {
+				ret_code = tpm_db_mc_alloc_virt_uni_entry(&rule_num);
+				IF_ERROR(ret_code);
+
+				ret_code = tpm_db_get_mc_vid_cfg(vid, &mc_vid_cfg);
+				IF_ERROR(ret_code);
+
+				for (entry_id = 0; entry_id < TPM_MAX_NUM_UNI_PORTS; entry_id++) {
+					if (mc_vid_cfg[entry_id].tpm_src_port == TPM_SRC_PORT_UNI_VIRT)
+						break;
+				}
+				if (entry_id == TPM_MAX_NUM_UNI_PORTS) {
+					TPM_OS_DEBUG(TPM_TPM_LOG_MOD,
+						     " virt_uni is unable to join the group when "
+						     "virt_uni is not the member of multicast vlan \n");
+				} else {
+					if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_TRANSPARENT)
+						u4_vid = vid;
+					else if (mc_vid_cfg[entry_id].mc_uni_port_mode == TPM_MC_UNI_MODE_STRIP)
+						u4_vid = 0xffff;
+					else
+						u4_vid = mc_vid_cfg[entry_id].uni_port_vid;
+
+					ret_code =
+					tpm_proc_mc_create_virt_uni_pnc_entry(rule_num, u4_vid, ipv6_dst_add, true);
+					IF_ERROR(ret_code);
+				}
+			} else if ((dest_port_bm & TPM_TRG_UNI_VIRT) == 0 && (mc_stream.dest_port_bm & TPM_TRG_UNI_VIRT) != 0) {
+				if (rule_num != 0xffff) {
+					ret_code = tpm_proc_mc_delete_virt_uni_pnc_entry(rule_num);
+					IF_ERROR(ret_code);
+					ret_code = tpm_db_mc_free_virt_uni_entry(rule_num);
+					IF_ERROR(ret_code);
+					rule_num = 0xffff;
+				}
+		}
+		}
+	}
+
+	/* Update stream entry */
+	mc_stream.igmp_mode = igmp_mode;
+	mc_stream.mc_stream_pppoe = mc_stream_pppoe;
+	mc_stream.vid = vid;
+	mc_stream.dest_port_bm = dest_port_bm;
+	mc_stream.u4_entry = rule_num;
+	memcpy(mc_stream.group_addr, ipv6_dst_add, 16 * sizeof(uint8_t));
+
+	ret_code = tpm_db_set_ipv6_mc_stream_entry(stream_num, &mc_stream);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_updt_ipv6_mc_stream(uint32_t owner_id, uint32_t stream_num, tpm_trg_port_type_t dest_port_bm)
+{
+	tpm_error_code_t ret_code;
+	tpm_mc_filter_mode_t filter_mode;
+	uint8_t mc_mac[6];
+	tpm_init_virt_uni_t virt_uni;
+	tpm_db_ipv6_mc_stream_entry_t mc_stream;
+	uint8_t sip_index = 0;
+
+	memset(&virt_uni, 0, sizeof(tpm_init_virt_uni_t));
+	memset(&mc_stream, 0, sizeof(tpm_db_mc_stream_entry_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) stream_num(%d),dest_port_bm(0x%x)\n",
+		     owner_id, stream_num, dest_port_bm);
+
+	/*
+	filter_mode = tpm_db_get_mc_filter_mode();
+	right now we only have TPM_MC_COMBINED_IP_MAC_FILTER mode
+	*/
+	filter_mode = TPM_MC_COMBINED_IP_MAC_FILTER;
+	if (filter_mode == TPM_MC_ALL_CPU_FRWD) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " illegal mc_filter_mod (%d)\n", filter_mode);
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	tpm_db_virt_info_get(&virt_uni);
+
+	if (dest_port_bm & TPM_TRG_UNI_VIRT) {
+		if (virt_uni.enabled == 0)
+			IF_ERROR(ERR_MC_DST_PORT_INVALID);
+	}
+
+	if (dest_port_bm & TPM_TRG_PORT_CPU) {
+		if (dest_port_bm & (~TPM_TRG_PORT_CPU))
+			IF_ERROR(ERR_MC_DST_PORT_INVALID);
+	}
+
+	if (dest_port_bm & TPM_TRG_PORT_UNI_ANY)
+		dest_port_bm = tpm_db_trg_port_uni_any_bmp_get(true);
+
+	ret_code = tpm_proc_check_dst_uni_port(dest_port_bm);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_get_ipv6_mc_stream_entry(stream_num, &mc_stream);
+	IF_ERROR(ret_code);
+
+	/* get sip_index */
+	if (0 == mc_stream.ignore_src_addr) {
+		/* get index of this IPv6 MC SIP */
+		sip_index = tpm_db_ipv6_mc_sip_index_get(mc_stream.src_addr);
+		if (0 == sip_index) {
+			/* SIP is not in DB, error */
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "get index of IPv6 MC SIP failed!\n");
+			return(ERR_IPV6_MC_SRC_IP_INVALID);
+		}
+	}
+
+	if (((dest_port_bm & TPM_TRG_PORT_CPU) != 0 && (mc_stream.dest_port_bm & TPM_TRG_PORT_CPU) == 0) ||
+	    ((dest_port_bm & TPM_TRG_PORT_CPU) == 0 && (mc_stream.dest_port_bm & TPM_TRG_PORT_CPU) != 0)) {
+		ret_code = tpm_proc_delete_ipv6_mc_pnc_entry(filter_mode, stream_num,
+							     mc_stream.dest_port_bm, mc_stream.u4_entry);
+		IF_ERROR(ret_code);
+
+		ret_code = tpm_proc_add_ipv6_mc_pnc_entry(filter_mode, stream_num, mc_stream.igmp_mode,
+							  mc_stream.mc_stream_pppoe, mc_stream.vid,
+							  mc_stream.group_addr, mc_stream.src_addr,
+							  mc_stream.ignore_src_addr, dest_port_bm);
+	} else {
+		ret_code = tpm_proc_update_ipv6_mc_pnc_entry(filter_mode, stream_num, mc_stream.igmp_mode,
+							     mc_stream.mc_stream_pppoe, mc_stream.vid,
+							     mc_stream.group_addr, sip_index, mc_stream.ignore_src_addr,
+							     dest_port_bm);
+	}
+	IF_ERROR(ret_code);
+
+	/* Set switch port_map for multicast MAC, but don't overwrite FF02::1 (MLD General Query) MAC */
+	MULTI_IPV6_2_MAC(mc_mac, mc_stream.group_addr);
+	if (memcmp(mc_mac, tpm_mld_gen_query_mac, 6) != 0) {
+		ret_code = tpm_proc_set_ipv4_mc_switch(filter_mode, mc_mac, mc_stream.dest_port_bm, dest_port_bm);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_del_ipv6_mc_stream(uint32_t owner_id, uint32_t stream_num)
+{
+
+	int32_t ret_code;
+	tpm_mc_filter_mode_t filter_mode;
+	uint8_t mc_mac[6];
+	tpm_db_ipv6_mc_stream_entry_t mc_stream;
+
+	memset(&mc_stream, 0, sizeof(tpm_db_ipv6_mc_stream_entry_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) stream_num(%d)\n", owner_id, stream_num);
+
+	/*
+	filter_mode = tpm_db_get_mc_filter_mode();
+	right now we only have TPM_MC_COMBINED_IP_MAC_FILTER mode
+	*/
+	filter_mode = TPM_MC_COMBINED_IP_MAC_FILTER;
+	if (filter_mode == TPM_MC_ALL_CPU_FRWD) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " illegal mc_filter_mod (%d)\n", filter_mode);
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	ret_code = tpm_db_get_ipv6_mc_stream_entry(stream_num, &mc_stream);
+	IF_ERROR(ret_code);
+
+	ret_code =
+	tpm_proc_delete_ipv6_mc_pnc_entry(filter_mode, stream_num, mc_stream.dest_port_bm, mc_stream.u4_entry);
+	IF_ERROR(ret_code);
+
+	/* Set switch VID and multicast MAC */
+	MULTI_IPV6_2_MAC(mc_mac, mc_stream.group_addr);
+	/* Set switch port_map for multicast MAC, but don't overwrite FF02::1 (MLD General Query) MAC */
+	if (memcmp(mc_mac, tpm_mld_gen_query_mac, 6) != 0) {
+		ret_code = tpm_proc_set_ipv4_mc_switch(filter_mode, mc_mac, mc_stream.dest_port_bm, 0);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_ipv6_hoplimit_init(uint32_t hoplimit_illegal_action)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries, pnc_entry, hoplimit_lu;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data;
+	int32_t cpu_rx_queue;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "hoplimit_illegal_action(%d)\n", hoplimit_illegal_action);
+
+	/* Get default CPU Rx queue */
+	tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_HOPL, &range_data);
+	IF_ERROR(int_ret_code);
+	hoplimit_lu = range_data.pnc_range_conf.base_lu_id;
+
+	/* Get pnc_range tcam_start_entry, and number of free entries */
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start;
+
+	/* Set common TCAM params */
+	pnc_data.pncl_tcam.lu_id = hoplimit_lu;
+	pnc_data.pncl_tcam.port_ids = tpm_proc_all_gmac_bm();
+	pnc_data.pncl_tcam.start_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+	pnc_data.pncl_tcam.start_offset.offset_sub.ipv6_subf = TPM_IPv6_PARSE_VER;
+	pnc_data.pncl_tcam.pkt_key.ipv6_add_key.ipv6_hopl = 0;
+
+	/* Set common SRAM params */
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+	pnc_data.pncl_sram.next_offset.offset_sub.ipv6_subf = TPM_IPv6_PARSE_VER;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.sram_updt_bm |= TPM_PNCL_SET_LUD;
+
+	/***********************/
+	/* Create HopLimit=0   */
+	/***********************/
+	/* Parse the HopLimit  */
+	pnc_data.pncl_tcam.ipv6_parse_bm = TPM_IPv6_PARSE_HOPL;
+
+	/* Double check - check only packets that are MTM */
+	pnc_data.pncl_tcam.add_info_data = (1 << TPM_AI_MTM_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_MTM_MASK;
+
+	/* Packet forwarded to CPU */
+	pnc_data.pncl_sram.sram_updt_bm = TPM_PNCL_SET_TXP;
+	pnc_data.pncl_sram.pnc_queue = cpu_rx_queue;
+	pnc_data.pncl_sram.flow_id_sub.pnc_target = TPM_PNC_TRG_CPU;
+
+	/* or packet is dropped */
+	if (TPM_TTL_ZERO_ACTION_DROP == hoplimit_illegal_action)
+		pnc_data.pncl_sram.sram_updt_bm |= TPM_PNCL_SET_DISC;
+
+	/* Signal the packet is going to CPU */
+	pnc_data.pncl_sram.add_info_data |= (1 << TPM_AI_TO_CPU_BIT_OFF);
+	pnc_data.pncl_sram.add_info_mask |= TPM_AI_TO_CPU_MASK;
+
+	NO_FREE_ENTRIES();
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV6_HOPL, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	/***********************/
+	/* Create HopLimit=1   */
+	/***********************/
+	NO_FREE_ENTRIES();
+	/* Build PnC Entry, see HopLimit=0 */
+	pnc_data.pncl_tcam.pkt_key.ipv6_gen_key.hop_limit = 1;
+
+	/* Build SRAM Entry, see HopLimit=0,
+	   but always send to CPU, don't drop */
+	pnc_data.pncl_sram.sram_updt_bm &= (~(TPM_PNCL_SET_DISC));
+
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV6_HOPL, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+	free_entries--;
+	pnc_entry++;
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_ipv6_mc_sip_init(void)
+{
+	int32_t int_ret_code;
+	uint32_t sip_index;
+	uint8_t  ipv6_mc[16];
+	tpm_db_pnc_range_t range_data;
+	tpm_pncl_pnc_full_t pnc_data;
+
+	/* Set Structs to zero */
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&ipv6_mc, 0, sizeof(ipv6_mc));
+
+	/* Get Range data */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_MC_SIP, &range_data);
+	IF_ERROR(int_ret_code);
+	pnc_data.pncl_sram.next_lu_id = range_data.pnc_range_conf.base_lu_id;
+	pnc_data.pncl_sram.sram_updt_bm = 0;
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+
+	sip_index = range_data.pnc_range_conf.range_size - 1;
+
+
+	int_ret_code = tpm_proc_ipv6_mc_sip_entry_create(sip_index, ipv6_mc);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+tpm_error_code_t tpm_proc_ipv6_l4_mc_ds_init(void)
+{
+	int32_t int_ret_code;
+	uint32_t free_entries, pnc_entry, lu_id;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_db_pnc_range_t range_data;
+	tpm_gmac_bm_t gmac_bm;
+
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&start_offset, 0, sizeof(tpm_pncl_offset_t));
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Get Range_Id */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_L4_MC_DS, &range_data);
+	IF_ERROR(int_ret_code);
+	lu_id = range_data.pnc_range_conf.base_lu_id;
+
+	/* Get pnc_range tcam_start_entry, and number of free entries */
+	free_entries = range_data.pnc_range_oper.free_entries;
+	pnc_entry = range_data.pnc_range_conf.range_start;
+
+	/* Set common TCAM params */
+	/* Get PNC Range information */
+	int_ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_IPV6_L4, &lu_id, &start_offset);
+	IF_ERROR(int_ret_code);
+	pnc_data.pncl_tcam.lu_id = lu_id;
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &gmac_bm);
+	pnc_data.pncl_tcam.port_ids = gmac_bm;
+	memcpy(&(pnc_data.pncl_tcam.start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	/* Set common SRAM params */
+	pnc_data.pncl_sram.next_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+	pnc_data.pncl_sram.next_offset.offset_sub.ipv6_subf = TPM_IPv6_PARSE_VER;
+	pnc_data.pncl_sram.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	pnc_data.pncl_sram.next_lu_off_reg = TPM_PNC_LU_REG0; /* lookup reg 0 */
+	int_ret_code = tpm_db_pnc_rng_get(TPM_PNC_IPV6_HOPL, &range_data);
+	IF_ERROR(int_ret_code);
+	pnc_data.pncl_sram.next_lu_id = range_data.pnc_range_conf.base_lu_id;
+	pnc_data.pncl_sram.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+
+	/* Double check - check only packets that are MC */
+	pnc_data.pncl_tcam.add_info_data = (1 << TPM_AI_MC_VID_VALID_BIT_OFF);
+	pnc_data.pncl_tcam.add_info_mask = TPM_AI_MC_VID_VALID_MASK;
+
+	NO_FREE_ENTRIES();
+	/* Create Entry in PnC */
+	int_ret_code = tpm_proc_pnc_create(TPM_PNC_IPV6_L4_MC_DS, pnc_entry, &pnc_data);
+	IF_ERROR(int_ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/***************************/
+/**          CNM Functions            **/
+/***************************/
+
+uint8_t tpm_proc_if_ipv4_pre_filter_key_conflict(uint32_t parse_bm_key_a,
+						uint32_t parse_bm_key_b,
+						tpm_ipv4_acl_key_t *key_a,
+						tpm_ipv4_acl_key_t *key_b)
+{
+	uint32_t com_parse_bm = parse_bm_key_a & parse_bm_key_b;
+
+	if (com_parse_bm != 0)
+	{
+		if (com_parse_bm & TPM_IPv4_PARSE_SIP) {
+			if (memcmp(key_a->ipv4_src_ip_add, key_b->ipv4_src_ip_add, 4 * sizeof(uint8_t)) ||
+				memcmp(key_a->ipv4_src_ip_add_mask, key_b->ipv4_src_ip_add_mask, 4 * sizeof(uint8_t)))
+				return TPM_TRUE;
+		}
+		if (com_parse_bm & TPM_IPv4_PARSE_DIP) {
+			if (memcmp(key_a->ipv4_dst_ip_add, key_b->ipv4_dst_ip_add, 4 * sizeof(uint8_t)) ||
+				memcmp(key_a->ipv4_dst_ip_add_mask, key_b->ipv4_dst_ip_add_mask, 4 * sizeof(uint8_t)))
+				return TPM_TRUE;
+		}
+		if (com_parse_bm & TPM_IPv4_PARSE_DSCP) {
+			if ((key_a->ipv4_dscp & key_a->ipv4_dscp_mask) != (key_b->ipv4_dscp & key_b->ipv4_dscp_mask))
+				return TPM_TRUE;
+		}
+		if (com_parse_bm & TPM_IPv4_PARSE_PROTO) {
+			if (key_a->ipv4_proto != key_b->ipv4_proto)
+				return TPM_TRUE;
+		}
+		if (com_parse_bm & TPM_PARSE_L4_SRC) {
+			if (key_a->l4_src_port != key_b->l4_src_port)
+				return TPM_TRUE;
+		}
+		if (com_parse_bm & TPM_PARSE_L4_DST) {
+			if (key_a->l4_dst_port != key_b->l4_dst_port)
+				return TPM_TRUE;
+		}
+	}
+
+	return TPM_FALSE;
+}
+
+uint8_t tpm_proc_if_ipv4_pre_range_is_full(tpm_src_port_type_t src_port,
+					   tpm_parse_fields_t ipv4_parse_rule_bm,
+					   tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	uint32_t key_idx, num_keys, num_rules = 1, i, j;
+	tpm_db_pnc_range_oper_t range_oper;
+	tpm_parse_fields_t parse_bm[TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM-1] = {0, 0};
+	tpm_ipv4_acl_key_t key[TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM-1];
+	uint8_t is_conflict = TPM_FALSE;
+
+	memset(&range_oper, 0, sizeof(tpm_db_pnc_range_oper_t));
+
+	ret_code = tpm_db_find_ipv4_pre_filter_key(src_port, ipv4_parse_rule_bm, ipv4_key, &key_idx);
+	if (ret_code != TPM_DB_OK) {
+		tpm_db_get_ipv4_pre_filter_key_num(src_port, &num_keys);
+		if (num_keys >= 3)
+			return TPM_TRUE;
+	} else
+		return TPM_FALSE;
+
+	tpm_db_pnc_rng_oper_get(TPM_PNC_CNM_IPV4_PRE, &range_oper);
+	if (range_oper.free_entries == 0)
+		return TPM_TRUE;
+
+	if ((num_keys == 1 && range_oper.free_entries < 2) ||
+		(num_keys == 2 && range_oper.free_entries < 4)) {
+		for (i = j = 0; i < TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM; i++) {
+			ret_code = tpm_db_get_ipv4_pre_filter_key(src_port, i, &parse_bm[j], &key[j]);
+			if (ret_code == TPM_DB_OK)
+				j++;
+		}
+
+		is_conflict = tpm_proc_if_ipv4_pre_filter_key_conflict(ipv4_parse_rule_bm, parse_bm[0], ipv4_key, &key[0]);
+		if (!is_conflict)
+			num_rules++;
+
+		if (num_keys == 2) {
+			is_conflict = tpm_proc_if_ipv4_pre_filter_key_conflict(ipv4_parse_rule_bm, parse_bm[1], ipv4_key, &key[1]);
+			if (!is_conflict)
+				num_rules++;
+
+			is_conflict = tpm_proc_if_ipv4_pre_filter_key_conflict(parse_bm[0], parse_bm[1], &key[0], &key[1]);
+			if (!is_conflict)
+				num_rules++;
+		}
+
+		if (range_oper.free_entries < num_rules)
+			return TPM_TRUE;
+	}
+
+	return TPM_FALSE;
+}
+
+uint8_t tpm_proc_if_cnm_main_range_is_full(tpm_src_port_type_t src_port, uint32_t precedence)
+{
+	int32_t ret_code;
+	uint32_t rule_num;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	memset(&range_conf, 0, sizeof(tpm_db_pnc_range_conf_t));
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_MAIN, &range_conf);
+	if (ret_code != TPM_OK)
+		return TPM_TRUE;
+
+	tpm_proc_calc_cnm_rule_num(src_port, precedence, &rule_num);
+
+	/* Check rule_num, and api_section is active */
+	ret_code = tpm_proc_add_api_ent_check(TPM_CNM_MAIN_ACL, range_conf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		return TPM_TRUE;
+
+	return TPM_FALSE;
+}
+
+int32_t tpm_proc_merge_ipv4_pre_filter_key_b_to_a(uint32_t *parse_bm_key_a,
+						 uint32_t parse_bm_key_b,
+						 tpm_ipv4_acl_key_t *key_a,
+						 tpm_ipv4_acl_key_t *key_b)
+{
+	uint32_t diff_parse_bm_b_to_a = (~(*parse_bm_key_a)) & parse_bm_key_b;
+
+	if (diff_parse_bm_b_to_a != 0)
+	{
+		if (diff_parse_bm_b_to_a & TPM_IPv4_PARSE_SIP) {
+			memcpy(key_a->ipv4_src_ip_add, key_b->ipv4_src_ip_add, 4 * sizeof(uint8_t));
+			memcpy(key_a->ipv4_src_ip_add_mask, key_b->ipv4_src_ip_add_mask, 4 * sizeof(uint8_t));
+		}
+		if (diff_parse_bm_b_to_a & TPM_IPv4_PARSE_DIP) {
+			memcpy(key_a->ipv4_dst_ip_add, key_b->ipv4_dst_ip_add, 4 * sizeof(uint8_t));
+			memcpy(key_a->ipv4_dst_ip_add_mask, key_b->ipv4_dst_ip_add_mask, 4 * sizeof(uint8_t));
+		}
+		if (diff_parse_bm_b_to_a & TPM_IPv4_PARSE_DSCP) {
+			key_a->ipv4_dscp = key_b->ipv4_dscp;
+			key_a->ipv4_dscp_mask = key_b->ipv4_dscp_mask;
+		}
+		if (diff_parse_bm_b_to_a & TPM_IPv4_PARSE_PROTO)
+			key_a->ipv4_proto = key_b->ipv4_proto;
+		if (diff_parse_bm_b_to_a & TPM_PARSE_L4_SRC)
+			key_a->l4_src_port = key_b->l4_src_port;
+		if (diff_parse_bm_b_to_a & TPM_PARSE_L4_DST)
+			key_a->l4_dst_port = key_b->l4_dst_port;
+
+		*parse_bm_key_a |= diff_parse_bm_b_to_a;
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_check_cnm_ipv4_pre_filter_triple_key_rule(tpm_src_port_type_t src_port,
+							   uint32_t partner_key_bm,
+							   tpm_parse_fields_t ipv4_parse_rule_bm,
+							   tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	uint32_t num_keys = 0, i, j;
+	tpm_parse_fields_t parse_bm[TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM-1] = {0, 0};
+	tpm_ipv4_acl_key_t key[TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM-1];
+	uint8_t is_conflict = TPM_FALSE;
+
+	memset(key, 0, sizeof(key));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " check src_port(%d), partner_key_bm(0x%x)\n", src_port, partner_key_bm);
+
+	tpm_db_get_ipv4_pre_filter_key_num(src_port, &num_keys);
+	if (num_keys < 2) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " not enough keys(%d) to set triple key rule - SKIP!\n", num_keys);
+		return TPM_FAIL;
+	}
+
+	for (i = 0, j = 0; i < TPM_CNM_IPV4_PRE_FILTER_KEY_MAX; i++) {
+		if ((1 << i) & partner_key_bm) {
+			ret_code = tpm_db_get_ipv4_pre_filter_key(src_port, i, &parse_bm[j], &key[j]);
+			if (ret_code != TPM_DB_OK) {
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " fail to get ipv4 pre-filter key(%d)!\n", i);
+				return TPM_FAIL;
+			}
+			j++;
+		}
+	}
+
+	is_conflict = tpm_proc_if_ipv4_pre_filter_key_conflict(ipv4_parse_rule_bm, parse_bm[0], ipv4_key, &key[0]);
+	if (is_conflict) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " new key conflicts with FIRST existing key!\n");
+		return TPM_FAIL;
+	}
+
+	is_conflict = tpm_proc_if_ipv4_pre_filter_key_conflict(ipv4_parse_rule_bm, parse_bm[1], ipv4_key, &key[1]);
+	if (is_conflict) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " new key conflicts with SECOND existing key!\n");
+		return TPM_FAIL;
+	}
+
+	is_conflict = tpm_proc_if_ipv4_pre_filter_key_conflict(parse_bm[0], parse_bm[1], &key[0], &key[1]);
+	if (is_conflict) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " FIRST existing key conflicts with SECOND existing key!\n");
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_check_cnm_ipv4_pre_filter_double_key_rule(tpm_src_port_type_t src_port,
+							   uint32_t partner_key_bm,
+							   tpm_parse_fields_t ipv4_parse_rule_bm,
+							   tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	uint32_t num_keys = 0, i;
+	tpm_parse_fields_t parse_bm = 0;
+	tpm_ipv4_acl_key_t key;
+	uint8_t is_conflict = TPM_FALSE;
+
+	memset(&key, 0, sizeof(tpm_ipv4_acl_key_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " check src_port(%d), partner_key_bm(0x%x)\n", src_port, partner_key_bm);
+
+	tpm_db_get_ipv4_pre_filter_key_num(src_port, &num_keys);
+	if (num_keys < 1) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " not enough keys(%d) to set triple key rule - SKIP!\n", num_keys);
+		return TPM_FAIL;
+	}
+
+	for (i = 0; i < TPM_CNM_IPV4_PRE_FILTER_KEY_MAX; i++) {
+		if ((1 << i) & partner_key_bm) {
+			ret_code = tpm_db_get_ipv4_pre_filter_key(src_port, i, &parse_bm, &key);
+			if (ret_code != TPM_DB_OK) {
+				TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " fail to get ipv4 pre-filter key(%d)!\n", i);
+				return TPM_FAIL;
+			}
+		}
+	}
+
+	is_conflict = tpm_proc_if_ipv4_pre_filter_key_conflict(ipv4_parse_rule_bm, parse_bm, ipv4_key, &key);
+	if (is_conflict) {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " new key conflicts with existing key!\n");
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_check_cnm_ipv4_pre_filter_single_key_rule(tpm_src_port_type_t src_port,
+							   uint32_t partner_key_bm,
+							   tpm_parse_fields_t ipv4_parse_rule_bm,
+							   tpm_ipv4_acl_key_t *ipv4_key)
+{
+	return TPM_OK;
+}
+
+int32_t tpm_proc_cnm_ipv4_pre_tcam_build(tpm_src_port_type_t src_port,
+					 tpm_parse_fields_t ipv4_parse_rule_bm,
+					 tpm_ipv4_acl_key_t *ipv4_key,
+					 tpm_pncl_tcam_data_t *tcam_data)
+{
+	int32_t ret_code;
+
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t src_port_field;
+	long long parse_int_flags_bm = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), parse_rule_bm(%d) \n",
+		     src_port, ipv4_parse_rule_bm);
+
+	/* IPV4 Parsing, according to bm in param */
+	tcam_data->ipv4_parse_bm = ipv4_parse_rule_bm;
+
+	parse_int_flags_bm |= TPM_PARSE_FLAG_CNM_IPV4_TRUE;
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port))
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+
+	/* Parse the AI flag bits */
+	src_port_field.src_port = src_port;
+	tpm_proc_parse_flag_ai_tcam_build(&src_port_field, 0, parse_int_flags_bm,
+									&(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	if (ipv4_key) {
+		memcpy(&(tcam_data->pkt_key.ipv4_key), ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+	}
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_CNM_IPV4_PRE, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_cnm_ipv4_pre_sram_build(uint32_t key_pattern, tpm_pncl_sram_data_t *sram_data)
+{
+	tpm_db_pnc_range_conf_t range_conf;
+	long long int_pkt_act = 0;
+	tpm_ai_vectors_t key_field;
+	int32_t ret_code;
+
+	memset(&key_field, 0, sizeof(tpm_ai_vectors_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " key_pattern(0x%x)n", key_pattern);
+
+	/* Set next offset and update register */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/*** Set next lookup configuration ***/
+
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_MAIN, &range_conf);
+	IF_ERROR(ret_code);
+	sram_data->next_lu_id = range_conf.base_lu_id;
+	sram_data->next_lu_off_reg = TPM_PNC_CNM_L2_REG;
+
+	sram_data->next_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	sram_data->next_offset.offset_sub.l2_subf = TPM_L2_PARSE_MH;
+
+	/* Set AI bits for IPV4 Pre-filter key pattern  */
+	int_pkt_act |= TPM_ACTION_SET_IPV4_PRE_KEY;
+
+	key_field.ipv4_pre_key = key_pattern;
+
+	/* Set AI bits */
+	tpm_proc_static_ai_sram_build(&key_field, 0, int_pkt_act, &(sram_data->add_info_data), &(sram_data->add_info_mask));
+
+	return(TPM_OK);
+}
+
+
+int32_t tpm_proc_set_ipv4_pre_filter_pnc_entry(tpm_src_port_type_t src_port,
+					       uint32_t rule_num,
+					       uint32_t key_pattern,
+					       tpm_parse_fields_t ipv4_parse_rule_bm,
+					       tpm_ipv4_acl_key_t *ipv4_key)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+
+	int32_t ret_code;
+	uint32_t pnc_entry = 0, num_valid_rules = 0, pnc_start_entry = 0, pnc_stop_entry = 0;
+	uint32_t pnc_range_start = 0, api_start = 0;
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code = tpm_proc_cnm_ipv4_pre_tcam_build(src_port, ipv4_parse_rule_bm, ipv4_key, &pnc_data.pncl_tcam);
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code = tpm_proc_cnm_ipv4_pre_sram_build(key_pattern, &pnc_data.pncl_sram);
+	IF_ERROR(ret_code);
+
+	/*** Calculate PNC Entry ***/
+
+	/* Get PNC Range Start */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_CNM_IPV4_PRE, &range_data);
+	IF_ERROR(ret_code);
+	pnc_range_start = range_data.pnc_range_conf.range_start;
+	api_start = range_data.pnc_range_conf.api_start;
+
+	/* Calculate absolute PNC entry number to execute */
+	pnc_entry = (pnc_range_start + api_start) + rule_num;
+
+	/* Get valid IPV4 PRE rule number */
+	tpm_db_get_ipv4_pre_rule_num(&num_valid_rules);
+	/* Decrease by 1 for the new rule */
+	num_valid_rules--;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " set pnc_entry(%d), num_valid_rules(%d)\n", pnc_entry, num_valid_rules);
+
+	/* Call PNC Entry Insert, if this is not the api_section's new last entry */
+	if (rule_num < num_valid_rules) {
+		pnc_start_entry = pnc_entry;
+		pnc_stop_entry = (pnc_range_start + api_start) + (num_valid_rules - 1);
+		ret_code = tpm_pncl_entry_insert(pnc_start_entry, pnc_stop_entry, &pnc_data);
+		IF_ERROR(ret_code);
+	} else {
+		/* Otherwise just set the entry (no insertion) */
+		ret_code = tpm_pncl_entry_set(pnc_entry, &pnc_data);
+		IF_ERROR(ret_code);
+	}
+
+	/* Decrease number of free entries in pnc_range */
+	ret_code = tpm_db_pnc_rng_free_ent_dec(TPM_PNC_CNM_IPV4_PRE);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_unset_ipv4_pre_filter_pnc_entry(uint32_t rule_num)
+{
+	tpm_db_pnc_range_t range_data;
+
+	int32_t ret_code;
+	uint32_t num_valid_rules = 0, pnc_start_entry = 0, pnc_stop_entry = 0;
+	uint32_t pnc_range_start = 0, api_start = 0;
+
+	/* Get PNC Range Start */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_CNM_IPV4_PRE, &range_data);
+	IF_ERROR(ret_code);
+	pnc_range_start = range_data.pnc_range_conf.range_start;
+	api_start = range_data.pnc_range_conf.api_start;
+
+	/* Get valid IPV4 PRE rule number */
+	tpm_db_get_ipv4_pre_rule_num(&num_valid_rules);
+	/* Increased by 1 for the new rule */
+	num_valid_rules++;
+
+	/* Calculate absolute PNC entry number to execute */
+	pnc_start_entry = (pnc_range_start + api_start) + rule_num;
+	pnc_stop_entry = (pnc_range_start + api_start) + (num_valid_rules - 1);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " delete pnc_start_entry(%d), pnc_stop_entry(%d)\n",
+									pnc_start_entry, pnc_stop_entry);
+
+	ret_code = tpm_pncl_entry_delete(pnc_start_entry, pnc_stop_entry);
+	IF_ERROR(ret_code);
+
+	/* Decrease number of free entries in pnc_range */
+	ret_code = tpm_db_pnc_rng_free_ent_inc(TPM_PNC_CNM_IPV4_PRE);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_triple_key_rule(tpm_src_port_type_t src_port,
+							 uint32_t key_idx,
+							 uint32_t key_pattern,
+							 tpm_parse_fields_t ipv4_parse_rule_bm,
+							 tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	uint32_t partner_key_bm = 0, rule_num = 0, i, j;
+	tpm_parse_fields_t parse_bm[TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM-1] = {0, 0};
+	tpm_ipv4_acl_key_t key[TPM_DB_CNM_MAX_IPV4_PRE_FILTER_KEY_NUM-1];
+	tpm_parse_fields_t merge_parse_bm = 0;
+	tpm_ipv4_acl_key_t merge_key;
+
+	memset(key, 0, sizeof(key));
+	memset(&merge_key, 0, sizeof(tpm_ipv4_acl_key_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " add src_port(%d), key_idx(%d), key_pattern(0x%x)\n", src_port, key_idx, key_pattern);
+
+	partner_key_bm = key_pattern & ~(1 << key_idx);
+
+	for (i = 0, j = 0; i < TPM_CNM_IPV4_PRE_FILTER_KEY_MAX; i++) {
+		if ((1 << i) & partner_key_bm) {
+			ret_code = tpm_db_get_ipv4_pre_filter_key(src_port, i, &parse_bm[j], &key[j]);
+			if (ret_code != TPM_DB_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to get ipv4 pre-filter key(%d)!\n", i);
+				return TPM_FAIL;
+			}
+			j++;
+		}
+	}
+
+	tpm_proc_merge_ipv4_pre_filter_key_b_to_a(&merge_parse_bm, ipv4_parse_rule_bm, &merge_key, ipv4_key);
+	tpm_proc_merge_ipv4_pre_filter_key_b_to_a(&merge_parse_bm, parse_bm[0], &merge_key, &key[0]);
+	tpm_proc_merge_ipv4_pre_filter_key_b_to_a(&merge_parse_bm, parse_bm[1], &merge_key, &key[1]);
+
+	ret_code = tpm_db_add_ipv4_pre_rule(src_port, (key_pattern << (TPM_CNM_IPV4_PRE_FILTER_KEY_MAX << 1)), &rule_num);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to add ipv4 pre-filter rule!\n");
+		return TPM_FAIL;
+	}
+	ret_code = tpm_proc_set_ipv4_pre_filter_pnc_entry(src_port, rule_num, key_pattern, merge_parse_bm, &merge_key);
+	if (ret_code != TPM_DB_OK) {
+		tpm_db_del_ipv4_pre_rule(src_port, (key_pattern << (TPM_CNM_IPV4_PRE_FILTER_KEY_MAX << 1)), &rule_num);
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to set ipv4 pre-filter pnc_entry(%d)!\n", rule_num);
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_double_key_rule(tpm_src_port_type_t src_port,
+							 uint32_t key_idx,
+							 uint32_t key_pattern,
+							 tpm_parse_fields_t ipv4_parse_rule_bm,
+							 tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	uint32_t partner_key_bm = 0, rule_num = 0, i;
+	tpm_parse_fields_t parse_bm = 0;
+	tpm_ipv4_acl_key_t key;
+	tpm_parse_fields_t merge_parse_bm = 0;
+	tpm_ipv4_acl_key_t merge_key;
+
+	memset(&key, 0, sizeof(tpm_ipv4_acl_key_t));
+	memset(&merge_key, 0, sizeof(tpm_ipv4_acl_key_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " add src_port(%d), key_idx(%d), key_pattern(0x%x)\n", src_port, key_idx, key_pattern);
+
+	partner_key_bm = key_pattern & ~(1 << key_idx);
+
+	for (i = 0; i < TPM_CNM_IPV4_PRE_FILTER_KEY_MAX; i++) {
+		if ((1 << i) & partner_key_bm) {
+			ret_code = tpm_db_get_ipv4_pre_filter_key(src_port, i, &parse_bm, &key);
+			if (ret_code != TPM_DB_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to get ipv4 pre-filter key(%d)!\n", i);
+				return TPM_FAIL;
+			}
+		}
+	}
+
+	tpm_proc_merge_ipv4_pre_filter_key_b_to_a(&merge_parse_bm, ipv4_parse_rule_bm, &merge_key, ipv4_key);
+	tpm_proc_merge_ipv4_pre_filter_key_b_to_a(&merge_parse_bm, parse_bm, &merge_key, &key);
+
+	ret_code = tpm_db_add_ipv4_pre_rule(src_port, (key_pattern << TPM_CNM_IPV4_PRE_FILTER_KEY_MAX), &rule_num);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to add ipv4 pre-filter rule!\n");
+		return TPM_FAIL;
+	}
+	ret_code = tpm_proc_set_ipv4_pre_filter_pnc_entry(src_port, rule_num, key_pattern, merge_parse_bm, &merge_key);
+	if (ret_code != TPM_DB_OK) {
+		tpm_db_del_ipv4_pre_rule(src_port, (key_pattern << TPM_CNM_IPV4_PRE_FILTER_KEY_MAX), &rule_num);
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to set ipv4 pre-filter pnc_entry(%d)!\n", rule_num);
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_single_key_rule(tpm_src_port_type_t src_port,
+							 uint32_t key_idx,
+							 uint32_t key_pattern,
+							 tpm_parse_fields_t ipv4_parse_rule_bm,
+							 tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	uint32_t rule_num = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " add src_port(%d), key_idx(%d), key_pattern(0x%x)\n", src_port, key_idx, key_pattern);
+
+	ret_code = tpm_db_add_ipv4_pre_rule(src_port, key_pattern, &rule_num);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to add ipv4 pre-filter rule!\n");
+		return TPM_FAIL;
+	}
+	ret_code = tpm_proc_set_ipv4_pre_filter_pnc_entry(src_port, rule_num, key_pattern, ipv4_parse_rule_bm, ipv4_key);
+	if (ret_code != TPM_DB_OK) {
+		tpm_db_del_ipv4_pre_rule(src_port, key_pattern, &rule_num);
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to set ipv4 pre-filter pnc_entry(%d)!\n", rule_num);
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_del_cnm_ipv4_pre_filter_rule(uint32_t src_port, uint32_t key_pattern, uint32_t key_idx)
+{
+	int32_t ret_code;
+	uint32_t rule_num = 0, num_keys = 0, _key_pattern = 0, i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " del src_port(%d), key_idx(%d), key_pattern(0x%x)\n", src_port, key_idx, key_pattern);
+
+	for (i = 0; i < TPM_CNM_IPV4_PRE_FILTER_KEY_MAX; i++) {
+		if ((1 << i) & key_pattern)
+			num_keys++;
+	}
+
+	if (num_keys == 1)
+		_key_pattern = key_pattern;
+	else
+		_key_pattern = key_pattern << (TPM_CNM_IPV4_PRE_FILTER_KEY_MAX << (num_keys - 2));
+
+	ret_code = tpm_db_del_ipv4_pre_rule(src_port, _key_pattern, &rule_num);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to delete ipv4 pre-filter rule!\n");
+		return TPM_FAIL;
+	}
+	ret_code = tpm_proc_unset_ipv4_pre_filter_pnc_entry(rule_num);
+	if (ret_code != TPM_DB_OK) {
+		tpm_db_add_ipv4_pre_rule(src_port, _key_pattern, &rule_num);
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to unset ipv4 pre-filter pnc_entry(%d)!\n", rule_num);
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_check_cnm_ipv4_pre_filter_key_rule(uint32_t key_idx,
+						    uint32_t rule_type,
+						    tpm_src_port_type_t src_port,
+						    tpm_parse_fields_t ipv4_parse_rule_bm,
+						    tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	tpm_cnm_ipv4_pre_filter_rule_oper_t *rule_oper = &gs_cnm_ipv4_pre_filter_rule_oper[key_idx][rule_type];
+	uint32_t partner_key_bm;
+
+	partner_key_bm = rule_oper->key_pattern & ~(1 << key_idx);
+	ret_code = rule_oper->check_cnm_ipv4_pre_filter(src_port, partner_key_bm, ipv4_parse_rule_bm, ipv4_key);
+
+	return ret_code;
+}
+
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_key_rule(uint32_t key_idx,
+						  uint32_t rule_type,
+						  tpm_src_port_type_t src_port,
+						  tpm_parse_fields_t ipv4_parse_rule_bm,
+						  tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	tpm_cnm_ipv4_pre_filter_rule_oper_t *rule_oper = &gs_cnm_ipv4_pre_filter_rule_oper[key_idx][rule_type];
+
+	ret_code = rule_oper->add_cnm_ipv4_pre_filter(src_port, key_idx, rule_oper->key_pattern,
+						      ipv4_parse_rule_bm, ipv4_key);
+
+	return ret_code;
+}
+
+int32_t tpm_proc_del_cnm_ipv4_pre_filter_key_rule(uint32_t key_idx,
+						  uint32_t rule_type,
+						  tpm_src_port_type_t src_port,
+						  tpm_parse_fields_t ipv4_parse_rule_bm,
+						  tpm_ipv4_acl_key_t *ipv4_key)
+{
+	int32_t ret_code;
+	tpm_cnm_ipv4_pre_filter_rule_oper_t *rule_oper = &gs_cnm_ipv4_pre_filter_rule_oper[key_idx][rule_type];
+
+	ret_code = rule_oper->del_cnm_ipv4_pre_filter(src_port, rule_oper->key_pattern, key_idx);
+
+	return ret_code;
+}
+
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_key(uint32_t owner_id,
+					     tpm_src_port_type_t src_port,
+					     tpm_parse_fields_t ipv4_parse_rule_bm,
+					     tpm_ipv4_acl_key_t *ipv4_key,
+					     uint32_t *key_idx)
+{
+	int32_t ret_code;
+	uint32_t _key_idx, i;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), ipv4_parse_rule_bm(0x%x)\n", src_port, ipv4_parse_rule_bm);
+
+	ret_code = tpm_db_find_ipv4_pre_filter_key(src_port, ipv4_parse_rule_bm, ipv4_key, &_key_idx);
+	if (ret_code != TPM_DB_OK)
+	{
+		ret_code = tpm_db_alloc_ipv4_pre_filter_key(src_port, &_key_idx);
+		if (ret_code != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " no room for new ipv4 pre-filter key!\n");
+			IF_ERROR(ERR_GENERAL);
+		}
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " alloc new key(%d)\n", _key_idx);
+
+
+		for (i = 0; i < TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_KEY; i++) {
+			ret_code = tpm_proc_check_cnm_ipv4_pre_filter_key_rule(_key_idx, i, src_port, ipv4_parse_rule_bm, ipv4_key);
+			if (ret_code == TPM_DB_OK) {
+				ret_code = tpm_proc_add_cnm_ipv4_pre_filter_key_rule(_key_idx, i, src_port, ipv4_parse_rule_bm, ipv4_key);
+				if (ret_code != TPM_DB_OK) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to add src_port(%d) key(%d), rule(%d)!\n",
+								src_port, _key_idx, i);
+					IF_ERROR(ERR_GENERAL);
+				}
+			}
+		}
+
+		ret_code = tpm_db_set_ipv4_pre_filter_key(src_port, _key_idx, ipv4_parse_rule_bm, ipv4_key);
+		if (ret_code != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to set ipv4 pre-filter key(%d) to db!\n", _key_idx);
+			IF_ERROR(ERR_GENERAL);
+		}
+	} else
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " find existing key(%d)\n", _key_idx);
+
+	tpm_db_inc_ipv4_pre_filter_key_user_num(src_port, _key_idx);
+	*key_idx = _key_idx;
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_del_cnm_ipv4_pre_filter_key(uint32_t owner_id, tpm_src_port_type_t src_port, uint32_t key_idx)
+{
+	int32_t ret_code;
+	tpm_parse_fields_t ipv4_parse_rule_bm = 0;
+	tpm_ipv4_acl_key_t ipv4_key;
+	uint32_t num_users = 0, i;
+
+	memset(&ipv4_key, 0, sizeof(tpm_ipv4_acl_key_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), key_idx(%d)\n", src_port, key_idx);
+
+	ret_code = tpm_db_get_ipv4_pre_filter_key(src_port, key_idx, &ipv4_parse_rule_bm, &ipv4_key);
+	if (ret_code != TPM_DB_OK) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " not find ipv4 pre-filter key(%d)!\n", key_idx);
+		IF_ERROR(ERR_GENERAL);
+	}
+
+	tpm_db_dec_ipv4_pre_filter_key_user_num(src_port, key_idx);
+
+	tpm_db_get_ipv4_pre_filter_key_user_num(src_port, key_idx, &num_users);
+	if (num_users == 0) {
+		for (i = 0; i < TPM_CNM_MAX_IPV4_PRE_FILTER_RULE_PER_KEY; i++) {
+			ret_code = tpm_proc_check_cnm_ipv4_pre_filter_key_rule(key_idx, i, src_port, ipv4_parse_rule_bm, &ipv4_key);
+			if (ret_code == TPM_DB_OK) {
+				ret_code = tpm_proc_del_cnm_ipv4_pre_filter_key_rule(key_idx, i, src_port, ipv4_parse_rule_bm, &ipv4_key);
+				if (ret_code != TPM_DB_OK) {
+					TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to del src_port(%d) key(%d), rule(%d)!\n",
+								src_port, key_idx, i);
+					IF_ERROR(ERR_GENERAL);
+				}
+			}
+		}
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " del ipv4 pre-filter key(%d)\n", key_idx);
+
+		ret_code = tpm_db_del_ipv4_pre_filter_key(src_port, key_idx);
+		if (ret_code != TPM_DB_OK) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " fail to del ipv4 pre-filter key(%d)!\n", key_idx);
+			IF_ERROR(ERR_GENERAL);
+		}
+	}
+
+	return TPM_OK;
+}
+
+
+int32_t tpm_proc_cnm_l2_tcam_build(tpm_src_port_type_t src_port,
+				   tpm_parse_fields_t l2_parse_rule_bm,
+				   tpm_l2_acl_key_t *l2_key,
+				   uint32_t ipv4_key_idx,
+				   tpm_pncl_tcam_data_t *tcam_data)
+{
+	int32_t ret_code;
+
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t ai_vectors;
+	long long parse_int_flags_bm = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), parse_rule_bm(%d), ipv4_key_idx(%d) \n",
+		     src_port, l2_parse_rule_bm, ipv4_key_idx);
+
+	/* IPV4 Parsing, according to bm in param */
+	tcam_data->l2_parse_bm = l2_parse_rule_bm;
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port)) {
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+		ai_vectors.src_port = src_port;
+	}
+
+	/* Parse the AI flag bits */
+	if (ipv4_key_idx != TPM_CNM_INVALID_IPV4_PRE_FILTER_KEY_ID) {
+		parse_int_flags_bm |= TPM_PARSE_FLAG_IPV4_PRE_KEY_PARSE;
+		ai_vectors.ipv4_pre_key = 1 << ipv4_key_idx;
+	}
+	tpm_proc_parse_flag_ai_tcam_build(&ai_vectors, 0, parse_int_flags_bm,
+									&(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	if (l2_key) {
+		memcpy(&(tcam_data->pkt_key.l2_key), l2_key, sizeof(tpm_l2_acl_key_t));
+	}
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_CNM_MAIN, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id + TPM_CNM_L2_MAIN_LUID_OFFSET;
+	start_offset.offset_base = TPM_PNCL_ZERO_OFFSET;
+	start_offset.offset_sub.subf = TPM_L2_PARSE_MH;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_cnm_l2_sram_build(uint32_t precedence,
+				   tpm_pkt_frwd_t *pkt_frwd,
+				   tpm_pkt_action_t pkt_act,
+				   uint32_t mod_cmd,
+				   tpm_pncl_sram_data_t *sram_data)
+{
+	tpm_db_pnc_range_conf_t range_conf;
+	long long int_pkt_act = 0;
+	tpm_ai_vectors_t key_field;
+	tpm_db_pon_type_t pon_type;
+	uint32_t i;
+	int32_t ret_code;
+
+	memset(&key_field, 0, sizeof(tpm_ai_vectors_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " precedence(%d), pkt_act(%d), mod_cmd(%d) \n", precedence, pkt_act, mod_cmd);
+
+	/* Set next offset and update register */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Update split modification */
+	if (SET_MOD(pkt_act)) {
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_SPLIT_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_cmd;
+	}
+
+	/*** Set next lookup configuration ***/
+	if (precedence == 0) {
+		sram_data->next_lu_id = 0;
+		sram_data->next_lu_off_reg = 0;
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_LUD;
+	} else {
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_MAIN, &range_conf);
+		IF_ERROR(ret_code);
+		sram_data->next_lu_id = range_conf.base_lu_id + TPM_CNM_ETY_MAIN_LUID_OFFSET;
+		sram_data->next_lu_off_reg = TPM_PNC_ETY_REG;
+
+		sram_data->next_offset.offset_base = TPM_PNCL_L3_OFFSET;
+		sram_data->next_offset.offset_sub.l3_subf = 0xffff;
+
+		/* Set AI bits for CNM precedence  */
+		int_pkt_act |= TPM_ACTION_SET_CNM_PREC;
+
+		key_field.cnm_prec = sg_l2_cnm_prec_ind[precedence];
+
+		/* Set AI bits */
+		tpm_proc_static_ai_sram_build(&key_field, 0, int_pkt_act, &(sram_data->add_info_data), &(sram_data->add_info_mask));
+	}
+
+	if (SET_TARGET_PORT(pkt_act)) {
+		/* Add Target Txp to update BM */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
+
+		/* Set PNC FlowId Target */
+		for (i = 0; i < 8; i++) {
+			if (pkt_frwd->trg_port == (uint32_t)(TPM_TRG_TCONT_0 << i))
+				break;
+		}
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_PMAC0 + i;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Target(%d)\n", sram_data->flow_id_sub.pnc_target);
+
+		/* If target is GPON, set GEM and MH */
+		tpm_db_pon_type_get(&pon_type);
+		if (pon_type == TPM_GPON) {
+			sram_data->mh_reg.mh_set = TPM_TRUE;
+			sram_data->mh_reg.mh_reg = 1;
+			sram_data->sram_updt_bm |= TPM_PNCL_SET_GEM;
+			sram_data->flow_id_sub.gem_port = pkt_frwd->gem_port;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set GemPort(%d)\n", pkt_frwd->gem_port);
+		}
+	}
+
+	if (SET_TARGET_QUEUE(pkt_act)) {
+		/* Set Queue */
+		sram_data->pnc_queue = pkt_frwd->trg_queue;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Tx Queue (%x) \n", pkt_frwd->trg_queue);
+	} else {
+		sram_data->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "No Tx Queue Update \n");
+	}
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_cnm_ipv6_tcam_build(tpm_src_port_type_t src_port,
+				     uint32_t precedence,
+				     tpm_parse_fields_t ipv6_parse_rule_bm,
+				     tpm_ipv6_acl_key_t *ipv6_key,
+				     tpm_pncl_tcam_data_t *tcam_data)
+{
+	int32_t ret_code;
+
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t ai_vectors;
+	long long parse_int_flags_bm = 0;
+	tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win;
+
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), parse_rule_bm(%d) \n",
+		     src_port, ipv6_parse_rule_bm);
+
+	/* ipv6 Parsing, according to bm in param */
+	tcam_data->ipv6_parse_bm = ipv6_parse_rule_bm;
+
+	parse_int_flags_bm |= TPM_PARSE_FLAG_CNM_PREC_PARSE;
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port))
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+
+	/* Parse the AI flag bits */
+	ai_vectors.src_port = src_port;
+	ai_vectors.cnm_prec = sg_ipv4_cnm_prec_mask[precedence];
+	tpm_proc_parse_flag_ai_tcam_build(&ai_vectors, 0, parse_int_flags_bm,
+					  &(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	if (ipv6_key) {
+		memcpy(&(tcam_data->pkt_key.ipv6_key), ipv6_key, sizeof(tpm_ipv6_acl_key_t));
+	}
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_CNM_MAIN, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id + TPM_CNM_IPV6_MAIN_LUID_OFFSET;
+
+	/* start_offset depends on ipv6 CnM parse window */
+	tpm_db_ctc_cm_ipv6_parse_win_get(&ctc_cm_ipv6_parse_win);
+
+	if(TPM_CTC_CM_IPv6_FIRST_24B == ctc_cm_ipv6_parse_win) {
+		start_offset.offset_base = TPM_PNCL_IPV6_OFFSET;
+		start_offset.offset_sub.subf = TPM_IPv6_PARSE_VER;
+		memcpy(&(tcam_data->pkt_key.ipv6_gen_key.ipv6_src_ip_add),
+			ipv6_key->ipv6_src_ip_add, sizeof(ipv6_key->ipv6_src_ip_add));
+		memcpy(&(tcam_data->pkt_key.ipv6_gen_key.ipv6_src_ip_add_mask),
+			ipv6_key->ipv6_src_ip_add_mask, sizeof(ipv6_key->ipv6_src_ip_add_mask));
+		tcam_data->pkt_key.ipv6_gen_key.ipv6_dscp = ipv6_key->ipv6_dscp;
+		tcam_data->pkt_key.ipv6_gen_key.ipv6_dscp_mask = ipv6_key->ipv6_dscp_mask;
+		tcam_data->pkt_key.ipv6_gen_key.hop_limit = ipv6_key->ipv6_hoplimit;
+	} else {
+		start_offset.offset_base = TPM_PNCL_IPV6_DIP_OFFSET;
+		start_offset.offset_sub.subf = TPM_IPv6_PARSE_DIP;
+		memcpy(&(tcam_data->pkt_key.ipv6_dip_key.ipv6_ip_add),
+			ipv6_key->ipv6_dst_ip_add, sizeof(ipv6_key->ipv6_dst_ip_add));
+		memcpy(&(tcam_data->pkt_key.ipv6_dip_key.ipv6_ip_add_mask),
+			ipv6_key->ipv6_dst_ip_add_mask, sizeof(ipv6_key->ipv6_dst_ip_add_mask));
+		tcam_data->pkt_key.l4_ports_key.l4_dst_port = ipv6_key->l4_dst_port;
+		tcam_data->pkt_key.l4_ports_key.l4_src_port = ipv6_key->l4_src_port;
+	}
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_cnm_ipv6_sram_build(tpm_pkt_frwd_t *pkt_frwd,
+				     tpm_pkt_action_t pkt_act,
+				     uint32_t mod_cmd,
+				     tpm_pncl_sram_data_t *sram_data)
+{
+	tpm_ai_vectors_t key_field;
+	tpm_db_pon_type_t pon_type;
+	uint32_t i;
+
+	memset(&key_field, 0, sizeof(tpm_ai_vectors_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pkt_act(%d), mod_cmd(%d) \n", pkt_act, mod_cmd);
+
+	/* Set next offset and update register */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/*** Set next lookup configuration ***/
+	sram_data->next_lu_id = 0;
+	sram_data->next_lu_off_reg = 0;
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_LUD;
+
+	/* Update split modification */
+	if (SET_MOD(pkt_act)) {
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_SPLIT_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_cmd;
+	}
+
+	if (SET_TARGET_PORT(pkt_act)) {
+		/* Add Target Txp to update BM */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
+
+		/* Set PNC FlowId Target */
+		for (i = 0; i < 8; i++) {
+			if (pkt_frwd->trg_port == (uint32_t)(TPM_TRG_TCONT_0 << i))
+				break;
+		}
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_PMAC0 + i;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Target(%d)\n", sram_data->flow_id_sub.pnc_target);
+
+		/* If target is GPON, set GEM and MH */
+		tpm_db_pon_type_get(&pon_type);
+		if (pon_type == TPM_GPON) {
+			sram_data->mh_reg.mh_set = TPM_TRUE;
+			sram_data->mh_reg.mh_reg = 1;
+			sram_data->sram_updt_bm |= TPM_PNCL_SET_GEM;
+			sram_data->flow_id_sub.gem_port = pkt_frwd->gem_port;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set GemPort(%d)\n", pkt_frwd->gem_port);
+		}
+	}
+
+	if (SET_TARGET_QUEUE(pkt_act)) {
+		/* Set Queue */
+		sram_data->pnc_queue = pkt_frwd->trg_queue;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Tx Queue (%x)\n", pkt_frwd->trg_queue);
+	} else {
+		sram_data->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "No Tx Queue Update \n");
+	}
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_cnm_ipv4_tcam_build(tpm_src_port_type_t src_port,
+				     uint32_t precedence,
+				     tpm_parse_fields_t ipv4_parse_rule_bm,
+				     tpm_ipv4_acl_key_t *ipv4_key,
+				     tpm_pncl_tcam_data_t *tcam_data)
+{
+	int32_t ret_code;
+
+	tpm_gmac_bm_t gmac_bm;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+	tpm_ai_vectors_t ai_vectors;
+	long long parse_int_flags_bm = 0;
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " src_port(%d), parse_rule_bm(%d) \n",
+		     src_port, ipv4_parse_rule_bm);
+
+	/* IPV4 Parsing, according to bm in param */
+	tcam_data->ipv4_parse_bm = ipv4_parse_rule_bm;
+
+	parse_int_flags_bm |= TPM_PARSE_FLAG_CNM_PREC_PARSE | TPM_PARSE_FLAG_CNM_IPV4_TRUE;
+
+	/* Parse the uni_port AI bits */
+	if (FROM_SPEC_UNI(src_port))
+		parse_int_flags_bm |= TPM_PARSE_FLAG_UNI_PORT_PARSE;
+
+	/* Parse the AI flag bits */
+	ai_vectors.src_port = src_port;
+	ai_vectors.cnm_prec = sg_ipv4_cnm_prec_mask[precedence];
+	tpm_proc_parse_flag_ai_tcam_build(&ai_vectors, 0, parse_int_flags_bm,
+									&(tcam_data->add_info_data), &(tcam_data->add_info_mask));
+
+	/* Get GMAC(s) */
+	tpm_proc_src_port_gmac_bm_map(src_port, &gmac_bm);
+	tcam_data->port_ids = gmac_bm;
+
+	if (ipv4_key) {
+		memcpy(&(tcam_data->pkt_key.ipv4_key), ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+	}
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_CNM_MAIN, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id + TPM_CNM_IPV4_MAIN_LUID_OFFSET;
+	start_offset.offset_base = TPM_PNCL_IPV4_OFFSET;
+	start_offset.offset_sub.subf = TPM_IPv4_PARSE_VER;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_cnm_ipv4_sram_build(tpm_pkt_frwd_t *pkt_frwd,
+				     tpm_pkt_action_t pkt_act,
+				     uint32_t mod_cmd,
+				     tpm_pncl_sram_data_t *sram_data)
+{
+	tpm_ai_vectors_t key_field;
+	tpm_db_pon_type_t pon_type;
+	uint32_t i;
+
+	memset(&key_field, 0, sizeof(tpm_ai_vectors_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " pkt_act(%d), mod_cmd(%d) \n", pkt_act, mod_cmd);
+
+	/* Set next offset and update register */
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/*** Set next lookup configuration ***/
+	sram_data->next_lu_id = 0;
+	sram_data->next_lu_off_reg = 0;
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_LUD;
+
+	/* Update split modification */
+	if (SET_MOD(pkt_act)) {
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_SPLIT_MOD;
+		sram_data->flow_id_sub.mod_cmd = mod_cmd;
+	}
+
+	if (SET_TARGET_PORT(pkt_act)) {
+		/* Add Target Txp to update BM */
+		sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
+
+		/* Set PNC FlowId Target */
+		for (i = 0; i < 8; i++) {
+			if (pkt_frwd->trg_port == (uint32_t)(TPM_TRG_TCONT_0 << i))
+				break;
+		}
+		sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_PMAC0 + i;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Target(%d)\n", sram_data->flow_id_sub.pnc_target);
+
+		/* If target is GPON, set GEM and MH */
+		tpm_db_pon_type_get(&pon_type);
+		if (pon_type == TPM_GPON) {
+			sram_data->mh_reg.mh_set = TPM_TRUE;
+			sram_data->mh_reg.mh_reg = 1;
+			sram_data->sram_updt_bm |= TPM_PNCL_SET_GEM;
+			sram_data->flow_id_sub.gem_port = pkt_frwd->gem_port;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set GemPort(%d)\n", pkt_frwd->gem_port);
+		}
+	}
+
+	if (SET_TARGET_QUEUE(pkt_act)) {
+		/* Set Queue */
+		sram_data->pnc_queue = pkt_frwd->trg_queue;
+
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "Set Tx Queue (%x)\n", pkt_frwd->trg_queue);
+	} else {
+		sram_data->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "No Tx Queue Update \n");
+	}
+
+	return(TPM_OK);
+}
+
+int32_t tpm_proc_calc_cnm_rule_num(tpm_src_port_type_t src_port, uint32_t precedence, uint32_t *rule_num)
+{
+	uint32_t num_rules = 0, i;
+
+	for (i = TPM_SRC_PORT_UNI_0; i < src_port; i++)
+		num_rules += tpm_db_ctc_cm_get_num_rules(i);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " total rule num before src_port(%d): %d\n", src_port, num_rules);
+
+	*rule_num = precedence + num_rules;
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_calc_cnm_precedence(tpm_src_port_type_t src_port, uint32_t rule_num, uint32_t *precedence)
+{
+	uint32_t i;
+	uint32_t num_rules = 0;
+
+	if (NULL == precedence) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " invalid pointer--precedence!\n");
+		return ERR_GENERAL;
+	}
+
+	for (i = TPM_SRC_PORT_UNI_0; i < src_port; i++)
+		num_rules += tpm_db_ctc_cm_get_num_rules(i);
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " total rule num before src_port(%d): %d\n", src_port, num_rules);
+
+	if (rule_num < num_rules) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " rule num(%d) before src_port(%d) greater than current rule index(%d)!\n", num_rules, src_port, rule_num);
+		return ERR_GENERAL;
+	}
+
+	if ((rule_num - num_rules) >= TPM_MAX_NUM_CTC_PRECEDENCE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " calculated precedence(%d) invalid!\n", rule_num - num_rules);
+		return ERR_CTC_CM_PREC_INVALID;
+	}
+
+	*precedence = rule_num - num_rules;
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_add_l2_cnm_rule(uint32_t owner_id,
+				 tpm_src_port_type_t src_port,
+				 uint32_t precedence,
+				 tpm_parse_fields_t l2_parse_rule_bm,
+				 tpm_l2_acl_key_t *l2_key,
+				 uint32_t ipv4_key_idx,
+				 tpm_pkt_frwd_t *pkt_frwd,
+				 tpm_pkt_action_t pkt_act,
+				 uint32_t pbits,
+				 uint32_t *rule_idx)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_db_mod_conn_t mod_con;
+
+	int32_t ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, rule_num = 0, _rule_idx = 0, bi_dir, api_rng_entries;
+
+	memset(&range_conf, 0, sizeof(tpm_db_pnc_range_conf_t));
+	memset(&mod_con, 0, sizeof(tpm_db_mod_conn_t));
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_CNM_MAIN_ACL, &range_id);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &range_conf);
+	IF_ERROR(ret_code);
+
+	/* Calculate rule num */
+	tpm_proc_calc_cnm_rule_num(src_port, precedence, &rule_num);
+
+	if (TPM_RANGE_TYPE_TABLE == range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_CNM_MAIN_ACL, rule_num, &_rule_idx, &bi_dir, &api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d) already exists\n",
+				     owner_id, src_port, rule_num);
+
+			tpm_proc_del_l2_cnm_rule(owner_id, rule_num);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Get split modification update */
+	if (SET_MOD(pkt_act)) {
+		if (tpm_db_split_mod_get_enable() == TPM_SPLIT_MOD_ENABLED) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod for prec-0 \n");
+
+			/* get mod index from p-bit value */
+			ret_code = tpm_db_split_mod_get_index_by_p_bits(pbits, &mod_entry);
+			if (ret_code != TPM_DB_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, " unsupported p-bit value: %d\n", pbits);
+				return ERR_MOD_INVALID;
+			}
+
+			/* skip first PMT for p-bit AS-IS */
+			mod_entry++;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " updated mod_cmd(%d) \n", mod_entry);
+		} else {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " split_mod is in-active \n");
+			return ERR_MOD_INVALID;
+		}
+	}
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code = tpm_proc_cnm_l2_tcam_build(src_port, l2_parse_rule_bm, l2_key, ipv4_key_idx, &pnc_data.pncl_tcam);
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code = tpm_proc_cnm_l2_sram_build(precedence, pkt_frwd, pkt_act, mod_entry, &pnc_data.pncl_sram);
+	IF_ERROR(ret_code);
+
+
+	if (range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+	    /*** Insert the PNC Entry ***/
+		ret_code = tpm_proc_create_acl_pnc_entry(TPM_CNM_MAIN_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		ret_code = tpm_proc_create_table_pnc_entry(TPM_CNM_MAIN_ACL, rule_num, 0, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+	/* Set PNC API data */
+	api_data.cnm_key.src_port = src_port;
+	api_data.cnm_key.l2_parse_rule_bm = l2_parse_rule_bm;
+	api_data.cnm_key.pkt_act = pkt_act;
+	api_data.cnm_key.pbits = pbits;
+	if (l2_key)
+		memcpy(&(api_data.cnm_key.l2_key), l2_key, sizeof(tpm_l2_acl_key_t));
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.cnm_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.cnm_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	if (range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			ret_code = tpm_proc_api_entry_rulenum_inc(TPM_CNM_MAIN_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	ret_code = tpm_db_api_entry_set(TPM_CNM_MAIN_ACL, rule_num, 0 /*bi_dir */, &api_data, &mod_con, &pnc_conn, &_rule_idx);
+	IF_ERROR(ret_code);
+
+	/* Return Output */
+	*rule_idx = _rule_idx;
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_add_ipv4_cnm_rule(uint32_t owner_id,
+				   tpm_src_port_type_t src_port,
+				   uint32_t precedence,
+				   tpm_parse_fields_t ipv4_parse_rule_bm,
+				   tpm_ipv4_acl_key_t *ipv4_key,
+				   tpm_pkt_frwd_t *pkt_frwd,
+				   tpm_pkt_action_t pkt_act,
+				   uint32_t pbits,
+				   uint32_t *rule_idx)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_db_mod_conn_t mod_con;
+
+	int32_t ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, rule_num = 0, _rule_idx = 0, bi_dir, api_rng_entries;
+
+	memset(&range_conf, 0, sizeof(tpm_db_pnc_range_conf_t));
+	memset(&mod_con, 0, sizeof(tpm_db_mod_conn_t));
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_CNM_MAIN_ACL, &range_id);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &range_conf);
+	IF_ERROR(ret_code);
+
+	/* Calculate rule num */
+	tpm_proc_calc_cnm_rule_num(src_port, precedence, &rule_num);
+
+	if (TPM_RANGE_TYPE_TABLE == range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_CNM_MAIN_ACL, rule_num, &_rule_idx, &bi_dir, &api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d) already exists\n",
+				     owner_id, src_port, rule_num);
+
+			tpm_proc_del_ipv4_cnm_rule(owner_id, rule_num);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Get split modification update */
+	if (SET_MOD(pkt_act)) {
+		if (tpm_db_split_mod_get_enable() == TPM_SPLIT_MOD_ENABLED) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod for prec-0 \n");
+
+			/* get mod index from p-bit value */
+			ret_code = tpm_db_split_mod_get_index_by_p_bits(pbits, &mod_entry);
+			if (ret_code != TPM_DB_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, " unsupported p-bit value: %d\n", pbits);
+				return ERR_MOD_INVALID;
+			}
+
+			/* skip first PMT for p-bit AS-IS */
+			mod_entry++;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " updated mod_cmd(%d) \n", mod_entry);
+		} else {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " split_mod is in-active \n");
+			return ERR_MOD_INVALID;
+		}
+	}
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code = tpm_proc_cnm_ipv4_tcam_build(src_port, precedence, ipv4_parse_rule_bm, ipv4_key, &pnc_data.pncl_tcam);
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code = tpm_proc_cnm_ipv4_sram_build(pkt_frwd, pkt_act, mod_entry, &pnc_data.pncl_sram);
+	IF_ERROR(ret_code);
+
+
+	if (range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+	    /*** Insert the PNC Entry ***/
+		ret_code = tpm_proc_create_acl_pnc_entry(TPM_CNM_MAIN_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		ret_code = tpm_proc_create_table_pnc_entry(TPM_CNM_MAIN_ACL, rule_num, 0, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+	/* Set PNC API data */
+	api_data.cnm_key.src_port = src_port;
+	api_data.cnm_key.ipv4_parse_rule_bm = ipv4_parse_rule_bm;
+	api_data.cnm_key.pkt_act = pkt_act;
+	api_data.cnm_key.pbits = pbits;
+	if (ipv4_key)
+		memcpy(&(api_data.cnm_key.ipv4_key), ipv4_key, sizeof(tpm_ipv4_acl_key_t));
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.cnm_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.cnm_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	if (range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			ret_code = tpm_proc_api_entry_rulenum_inc(TPM_CNM_MAIN_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	ret_code = tpm_db_api_entry_set(TPM_CNM_MAIN_ACL, rule_num, 0 /*bi_dir */, &api_data, &mod_con, &pnc_conn, &_rule_idx);
+	IF_ERROR(ret_code);
+
+	/* Return Output */
+	*rule_idx = _rule_idx;
+
+	return TPM_OK;
+}
+
+int32_t tpm_proc_add_ipv6_cnm_rule(uint32_t owner_id,
+				   tpm_src_port_type_t src_port,
+				   uint32_t precedence,
+				   tpm_parse_fields_t ipv6_parse_rule_bm,
+				   tpm_ipv6_acl_key_t *ipv6_key,
+				   tpm_pkt_frwd_t *pkt_frwd,
+				   tpm_pkt_action_t pkt_act,
+				   uint32_t pbits,
+				   uint32_t *rule_idx)
+{
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pncl_offset_t start_offset;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_pnc_range_t range_data;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_db_mod_conn_t mod_con;
+
+	int32_t ret_code;
+	uint32_t pnc_entry = 0, mod_entry = 0, rule_num = 0, _rule_idx = 0, bi_dir, api_rng_entries;
+
+	memset(&range_conf, 0, sizeof(tpm_db_pnc_range_conf_t));
+	memset(&mod_con, 0, sizeof(tpm_db_mod_conn_t));
+
+	/* Set Structs to zero */
+	tpm_proc_set_int_structs(&pnc_data, &start_offset, &api_data, &pnc_conn, &range_data);
+
+	/* Get Range_Id */
+	tpm_db_api_section_main_pnc_get(TPM_CNM_MAIN_ACL, &range_id);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &range_conf);
+	IF_ERROR(ret_code);
+
+	/* Calculate rule num */
+	tpm_proc_calc_cnm_rule_num(src_port, precedence, &rule_num);
+
+	if (TPM_RANGE_TYPE_TABLE == range_conf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_CNM_MAIN_ACL, rule_num, &_rule_idx, &bi_dir, &api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) src_port(%d), rule_num(%d) already exists\n",
+				     owner_id, src_port, rule_num);
+
+			tpm_proc_del_ipv6_cnm_rule(owner_id, rule_num);
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Get split modification update */
+	if (SET_MOD(pkt_act)) {
+		if (tpm_db_split_mod_get_enable() == TPM_SPLIT_MOD_ENABLED) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " split mod for prec-0 \n");
+
+			/* get mod index from p-bit value */
+			ret_code = tpm_db_split_mod_get_index_by_p_bits(pbits, &mod_entry);
+			if (ret_code != TPM_DB_OK) {
+				TPM_OS_ERROR(TPM_TPM_LOG_MOD, " unsupported p-bit value: %d\n", pbits);
+				return ERR_MOD_INVALID;
+			}
+
+			/* skip first PMT for p-bit AS-IS */
+			mod_entry++;
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " updated mod_cmd(%d) \n", mod_entry);
+		} else {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " split_mod is in-active \n");
+			return ERR_MOD_INVALID;
+		}
+	}
+
+	/*********** Create PNC Entries **********/
+	/* Build PnC Entry */
+	ret_code = tpm_proc_cnm_ipv6_tcam_build(src_port, precedence, ipv6_parse_rule_bm, ipv6_key, &pnc_data.pncl_tcam);
+	IF_ERROR(ret_code);
+
+	/* Build SRAM Entry */
+	ret_code = tpm_proc_cnm_ipv6_sram_build(pkt_frwd, pkt_act, mod_entry, &pnc_data.pncl_sram);
+	IF_ERROR(ret_code);
+
+
+	if (range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+	    /*** Insert the PNC Entry ***/
+		ret_code = tpm_proc_create_acl_pnc_entry(TPM_CNM_MAIN_ACL, rule_num, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		ret_code = tpm_proc_create_table_pnc_entry(TPM_CNM_MAIN_ACL, rule_num, 0, &pnc_data, &pnc_entry, &api_rng_entries);
+		IF_ERROR(ret_code);
+	}
+
+	/*********** Update API Range in DB **********/
+	/* Set PNC API data */
+	api_data.cnm_key.src_port = src_port;
+	api_data.cnm_key.ipv6_parse_rule_bm = ipv6_parse_rule_bm;
+	api_data.cnm_key.pkt_act = pkt_act;
+	api_data.cnm_key.pbits = pbits;
+	if (ipv6_key)
+		memcpy(&(api_data.cnm_key.ipv6_key), ipv6_key, sizeof(tpm_ipv6_acl_key_t));
+	if (pkt_frwd != NULL)
+		memcpy(&(api_data.cnm_key.pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	else
+		memset(&(api_data.cnm_key.pkt_frwd), 0, sizeof(tpm_pkt_frwd_t));
+
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	if (range_conf.range_type == TPM_RANGE_TYPE_ACL) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			ret_code = tpm_proc_api_entry_rulenum_inc(TPM_CNM_MAIN_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	ret_code = tpm_db_api_entry_set(TPM_CNM_MAIN_ACL, rule_num, 0 /*bi_dir */, &api_data, &mod_con, &pnc_conn, &_rule_idx);
+	IF_ERROR(ret_code);
+
+	/* Return Output */
+	*rule_idx = _rule_idx;
+
+	return TPM_OK;
+}
+
+
+int32_t tpm_proc_del_cnm_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	int32_t ret_code;
+	uint32_t rule_num, dummy_idx, bi_dir, api_rng_entries;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con = { 0, 0};
+	tpm_db_pnc_conn_t pnc_con;
+	tpm_db_pnc_range_conf_t rang_conf;
+	tpm_pnc_ranges_t range_id = 0;
+
+	memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+	memset(&api_data, 0, sizeof(tpm_rule_entry_t));
+
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " rule_idx (%d)", rule_idx);
+
+	/* Get Range_Id */
+	ret_code = tpm_db_api_section_main_pnc_get(TPM_CNM_MAIN_ACL, &range_id);
+	IF_ERROR(ret_code);
+
+	/* Get Range Conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rang_conf);
+	IF_ERROR(ret_code);
+
+	/* Get the rule_num */
+	ret_code = tpm_db_api_rulenum_get(TPM_CNM_MAIN_ACL, rule_idx, &rule_num);
+	if (ret_code == TPM_DB_ERR_REC_NOT_EXIST) {
+		TPM_OS_ERROR(TPM_DB_MOD, " The rule non-exist!\n");
+		return ERR_RULE_IDX_INVALID;
+	}
+	TPM_OS_DEBUG(TPM_TPM_LOG_MOD, "with rule_num(%d)\n", rule_num);
+	/*IF_ERROR(ret_code);*/
+
+	ret_code = tpm_db_api_entry_get(TPM_CNM_MAIN_ACL, rule_num, &dummy_idx, &bi_dir, &api_data, &mod_con, &pnc_con);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_db_api_section_num_entries_get(TPM_CNM_MAIN_ACL, &api_rng_entries);
+	IF_ERROR(ret_code);
+
+	/* Delete PNC Entry */
+	ret_code = tpm_proc_pnc_con_del(&pnc_con);
+	IF_ERROR(ret_code);
+
+	/* Delete API Rule Entry */
+	ret_code = tpm_db_api_entry_invalidate(TPM_CNM_MAIN_ACL, rule_num);
+	IF_ERROR(ret_code);
+
+	if (TPM_RANGE_TYPE_ACL == rang_conf.range_type) {
+		/* Decrease rule_numbers and PnC entries of the existing API entries that were "pulled up" */
+		ret_code = tpm_proc_api_entry_rulenum_dec(TPM_CNM_MAIN_ACL, (rule_num + 1), (api_rng_entries - 1));
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_RC_OK);
+}
+int32_t tpm_proc_del_ipv6_cnm_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	int32_t ret_code;
+
+	ret_code = tpm_proc_del_cnm_rule(owner_id, rule_idx);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+int32_t tpm_proc_del_l2_cnm_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	int32_t ret_code;
+
+	ret_code = tpm_proc_del_cnm_rule(owner_id, rule_idx);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+int32_t tpm_proc_del_ipv4_cnm_rule(uint32_t owner_id, uint32_t rule_idx)
+{
+	int32_t ret_code;
+
+	ret_code = tpm_proc_del_cnm_rule(owner_id, rule_idx);
+	IF_ERROR(ret_code);
+
+	return(TPM_RC_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_mac_learn_tcam_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* rule_num          - API rule number
+* src_mac_addr      - layer2 key data
+* OUTPUTS:
+* l2_tcam_data      - Logical TCAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_mac_learn_tcam_build(uint32_t rule_num,
+				      tpm_l2_acl_key_t *src_mac_addr,
+				      tpm_pncl_tcam_data_t *tcam_data)
+{
+	int32_t ret_code;
+	uint32_t lu_id;
+	tpm_pncl_offset_t start_offset;
+
+	/* L2 Parsing, according to bm in param */
+	tcam_data->l2_parse_bm = TPM_L2_PARSE_MAC_SA;
+	tcam_data->port_ids = TPM_BM_GMAC_0;
+
+	/* Copy in logical PnC Key */
+	if (src_mac_addr)
+		memcpy(&(tcam_data->pkt_key.l2_key), src_mac_addr, sizeof(tpm_l2_acl_key_t));
+
+	/* Get PNC Range information */
+	ret_code = tpm_proc_common_pncl_info_get(TPM_PNC_MAC_LEARN, &lu_id, &start_offset);
+	IF_ERROR(ret_code);
+	tcam_data->lu_id = lu_id;
+	memcpy(&(tcam_data->start_offset), &start_offset, sizeof(tpm_pncl_offset_t));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_mac_learn_sram_build()
+*
+* DESCRIPTION:     Function builds a logical TCAM entry from the API data
+*
+* INPUTS:
+* queue             - queue to update
+*
+* OUTPUTS:
+* l2_sram_data      - Logical SRAM Structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_proc_mac_learn_sram_build(uint32_t queue,
+				      tpm_pncl_sram_data_t *sram_data)
+{
+
+	sram_data->next_lu_id = 0;
+	sram_data->next_lu_off_reg = 0;
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_LUD;
+	sram_data->shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	if (queue > 7)
+		sram_data->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	else
+		sram_data->pnc_queue = queue;
+	sram_data->flow_id_sub.pnc_target = TPM_PNC_TRG_GMAC1;
+	sram_data->sram_updt_bm |= TPM_PNCL_SET_TXP;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_proc_add_mac_learn_check()
+*
+* DESCRIPTION:    The function checks consistency of the tpm_proc_add_static_mac_rule params.
+*
+* INPUTS:
+* owner_id         -
+* rule_num         - See tpm_proc_add_l2_prim_acl_rule
+* queue            - See tpm_proc_add_l2_prim_acl_rule
+* src_mac_addr     - See tpm_proc_add_l2_prim_acl_rule
+* rule_idx         - See tpm_proc_add_l2_prim_acl_rule
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_mac_learn_check(uint32_t owner_id,
+					      uint32_t rule_num,
+					      uint32_t queue,
+					      tpm_l2_acl_key_t *src_mac_addr,
+					      uint32_t *rule_idx)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t rangConf;
+	uint32_t l_api_rng_entries;
+
+	/* Get Range_Id */
+	ret_code = tpm_db_api_section_main_pnc_get(TPM_PNC_MAC_LEARN_ACL, &range_id);
+	IF_ERROR(ret_code);
+	/* Get range conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+	/* Get number of existing api entries */
+	int_ret_code = tpm_db_api_section_num_entries_get(TPM_PNC_MAC_LEARN_ACL, &l_api_rng_entries);
+	IF_ERROR(int_ret_code);
+	/*check if there are free entry*/
+	if (l_api_rng_entries >= (rangConf.api_end - rangConf.api_start + 1)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, " api_sec(%d), has no free entries \n", TPM_PNC_MAC_LEARN_ACL);
+		return(TPM_FAIL);
+	}
+
+	ret_code = tpm_owner_id_check(TPM_API_MAC_LEARN, owner_id);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_OWNER_INVALID);
+	/* Check rule_num, and api_section is active */
+	ret_code = tpm_proc_add_api_ent_check(TPM_PNC_MAC_LEARN_ACL, rangConf.range_type, rule_num);
+	if (ret_code != TPM_OK)
+		IF_ERROR(ERR_RULE_NUM_INVALID);
+	/* Check src_mac_addr */
+	if (NULL != src_mac_addr) {
+		if (!(src_mac_addr->mac.mac_sa_mask[0] ||
+		      src_mac_addr->mac.mac_sa_mask[1] ||
+		      src_mac_addr->mac.mac_sa_mask[2] ||
+		      src_mac_addr->mac.mac_sa_mask[3] ||
+		      src_mac_addr->mac.mac_sa_mask[4] ||
+		      src_mac_addr->mac.mac_sa_mask[5]))
+		      IF_ERROR(ERR_L2_KEY_INVALID);
+	} else {
+		IF_ERROR(ERR_L2_KEY_INVALID);
+	}
+
+	if (queue > 7)
+		TPM_OS_WARN(TPM_TPM_LOG_MOD, " Invalid Queue(0x%x)\n", queue);
+
+	if (NULL == rule_idx)
+		IF_ERROR(ERR_NULL_POINTER);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_add_static_mac_rule()
+*
+* DESCRIPTION:    Main function for adding source MAC address learn API rule.
+*
+* INPUTS:
+* queue             - queue to update on GMAC1
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_mac_learn_rule(uint32_t owner_id,
+					     uint32_t rule_num,
+					     uint32_t queue,
+					     tpm_l2_acl_key_t *src_mac_addr,
+					     uint32_t *rule_idx)
+{
+	tpm_error_code_t ret_code;
+	int32_t int_ret_code;
+	uint32_t pnc_entry = 0, api_rng_entries = 0;
+	tpm_pnc_ranges_t range_id;
+	tpm_db_pnc_range_conf_t rangConf;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_rule_entry_t api_data;
+	tpm_db_pnc_conn_t pnc_conn;
+	tpm_db_mod_conn_t mod_con;
+	tpm_api_lu_conf_t lu_conf;
+	uint32_t l_rule_idx, bi_dir;
+
+	/* Get Range_Id */
+	ret_code = tpm_db_api_section_main_pnc_get(TPM_PNC_MAC_LEARN_ACL, &range_id);
+	IF_ERROR(ret_code);
+	/* Get range conf */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &rangConf);
+	IF_ERROR(ret_code);
+
+	/* Check parameters */
+	ret_code = tpm_proc_add_mac_learn_check(owner_id, rule_num, queue, src_mac_addr, rule_idx);
+	IF_ERROR(ret_code);
+
+	if (TPM_RANGE_TYPE_TABLE == rangConf.range_type) {
+		/* Try to getting the current entry */
+		ret_code = tpm_db_api_entry_get(TPM_PNC_MAC_LEARN_ACL, rule_num, &l_rule_idx, &bi_dir, &api_data, &mod_con, &pnc_conn);
+		/* if current entry with this rule num is valid */
+		if (TPM_DB_OK == ret_code) {
+			TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d), rule_num(%d) already exists\n", owner_id, rule_num);
+			ret_code = tpm_proc_del_static_mac_rule(owner_id, src_mac_addr);
+			IF_ERROR(ret_code);
+		}
+	}
+	/* Set Structs to zero */
+	memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+	memset(&api_data, 0, sizeof(tpm_rule_entry_t));
+	memset(&pnc_conn, 0, sizeof(tpm_db_pnc_conn_t));
+	memset(&mod_con, 0, sizeof(tpm_db_mod_conn_t));
+
+	/*********** Create PNC Entries **********/
+
+	/* Build PnC Entry */
+	int_ret_code = tpm_proc_mac_learn_tcam_build(rule_num, src_mac_addr, &(pnc_data.pncl_tcam));
+	IF_ERROR(int_ret_code);
+
+	int_ret_code = tpm_proc_mac_learn_sram_build(queue, &(pnc_data.pncl_sram));
+	IF_ERROR(int_ret_code);
+
+	if (TPM_RANGE_TYPE_ACL == rangConf.range_type) {
+		/*** Insert the PNC Entry ***/
+		int_ret_code = tpm_proc_create_acl_pnc_entry(TPM_PNC_MAC_LEARN_ACL,
+							     rule_num,
+							     &pnc_data,
+							     &pnc_entry,
+							     &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	} else {
+		/*** Set the PNC Entry ***/
+		int_ret_code = tpm_proc_create_table_pnc_entry(TPM_PNC_MAC_LEARN_ACL,
+							       rule_num,
+							       0,
+							       &pnc_data,
+							       &pnc_entry,
+							       &api_rng_entries);
+		IF_ERROR(int_ret_code);
+	}
+	/*********** Update API Range in DB **********/
+	/* Set PNC API data */
+	api_data.l2_prim_key.parse_rule_bm = TPM_L2_PARSE_MAC_SA;
+	memcpy(&(api_data.l2_prim_key.l2_key), src_mac_addr, sizeof(tpm_l2_acl_key_t));
+	/* Invalide mod */
+	mod_con.mod_cmd_ind = 0;
+	mod_con.mod_cmd_mac = TPM_INVALID_GMAC;
+	/* Set Pnc Connection data */
+	pnc_conn.num_pnc_ranges = 1;
+	pnc_conn.pnc_conn_tbl[0].pnc_range = range_id;
+	pnc_conn.pnc_conn_tbl[0].pnc_index = pnc_entry;
+
+	if (rangConf.range_type == TPM_RANGE_TYPE_ACL) {
+		/* Increase rule_numbers and PnC entries of the existing API entries that were "moved down" */
+		if (rule_num < api_rng_entries) {
+			ret_code = tpm_proc_api_entry_rulenum_inc(TPM_PNC_MAC_LEARN_ACL, rule_num, (api_rng_entries - 1));
+			IF_ERROR(ret_code);
+		}
+	}
+
+	/* Set new API Entry */
+	ret_code = tpm_db_api_entry_set(TPM_PNC_MAC_LEARN_ACL, rule_num, 0, &api_data, &mod_con, &pnc_conn, &l_rule_idx);
+	IF_ERROR(ret_code);
+
+	/* Return Output */
+	*rule_idx = l_rule_idx;
+
+	/* Set aging counter group nunmber and msk */
+	int_ret_code = tpm_db_pnc_get_lu_conf(range_id, &lu_conf);
+	IF_ERROR(int_ret_code);
+	tpm_tcam_set_lu_mask(pnc_entry, (int32_t) lu_conf.lu_mask);
+	tpm_tcam_set_cntr_group(pnc_entry, (int32_t) lu_conf.cntr_grp);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_find_mac_addr_db()
+*
+* DESCRIPTION:    To find MAC address for mac learn in DB
+*
+* INPUTS:
+* src_mac_addr             - address to search
+*
+* OUTPUTS:
+* addr_exist               - the address exist in DB or not, 0-not, 1-exist
+* rule_num                 - the unique rule index to pnc rule, will be used in pnc del
+* tbl_num                  - the table serial number, unique
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_find_mac_addr_db(tpm_l2_acl_key_t *src_mac_addr, int32_t *addr_exist, uint32_t *rule_num, uint32_t *tbl_num)
+{
+	tpm_error_code_t ret_code;
+	tpm_db_api_entry_t api_ent_mem_area;
+	uint32_t valid_entry_num = 0;
+	uint32_t api_rng_size, tbl_start;
+	int32_t apisec_last_valid_index;
+	int32_t rule_index;
+	tpm_rule_entry_t tpm_rule;
+	tpm_pnc_ranges_t pnc_range;
+
+	/* get API section info */
+	ret_code = tpm_db_api_section_get(TPM_PNC_MAC_LEARN_ACL,
+					  &api_rng_size,
+					  &valid_entry_num,
+					  &pnc_range,
+					  &apisec_last_valid_index,
+					  &tbl_start);
+	IF_ERROR(ret_code);
+	if (valid_entry_num == 0) {
+		*addr_exist = 0;
+		*rule_num = 0;
+		*tbl_num = 0;
+		return TPM_OK;
+	}
+
+	for (rule_index = 0; rule_index < (api_rng_size - 1); rule_index++) {
+		/* clear structure */
+		memset(&tpm_rule, 0, sizeof(tpm_rule_entry_t));
+		memset(&api_ent_mem_area, 0, sizeof(tpm_db_api_entry_t));
+
+		ret_code = tpm_db_api_section_ent_tbl_get(TPM_PNC_MAC_LEARN_ACL, &api_ent_mem_area, rule_index);
+		IF_ERROR(ret_code);
+		/*get tpm_rule*/
+		if (api_ent_mem_area.valid == TPM_DB_VALID) {
+			memcpy(&tpm_rule, &(api_ent_mem_area.api_rule_data), sizeof(tpm_rule_entry_t));
+			if (!memcmp(&tpm_rule.l2_prim_key.l2_key.mac, &(src_mac_addr->mac), sizeof(tpm_mac_key_t))) {
+				*addr_exist = 1;
+				*rule_num = api_ent_mem_area.rule_idx;
+				*tbl_num = api_ent_mem_area.rule_num;
+				return TPM_OK;
+			}
+		}
+	}
+
+	*addr_exist = 0;
+	*rule_num = 0;
+	*tbl_num = 0;
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_add_static_mac_rule()
+*
+* DESCRIPTION:    Main function for adding source MAC address learn API rule.
+*
+* INPUTS:
+* src_mac_addr             - address to learn
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_add_static_mac_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable = TPM_PNC_MAC_LEARN_DISABLED;
+	uint32_t rule_idx;
+	int32_t addr_exist = 0;
+	uint32_t rule_num = 0;
+	uint32_t queue_idx = 1;
+	tpm_gmacs_enum_t gmac_num;
+	uint32_t tbl_num = 0;
+
+	/* check whether mac_learn_enable is enabled or not */
+	ret_code = tpm_db_pnc_mac_learn_enable_get(&pnc_mac_learn_enable);
+	IF_ERROR(ret_code);
+	if (pnc_mac_learn_enable == TPM_PNC_MAC_LEARN_DISABLED) {
+		printk("MAC learn is not enabled\n");
+		return TPM_FAIL;
+	}
+
+	if (src_mac_addr == NULL) {
+		printk("NULL pointer\n");
+		return TPM_FAIL;
+	}
+	/* check whether the MAC exist in system or not */
+	ret_code = tpm_proc_find_mac_addr_db(src_mac_addr, &addr_exist, &rule_num, &tbl_num);
+	IF_ERROR(ret_code);
+	if (addr_exist)
+		return TPM_OK;
+	/* Get Tx queue */
+	if (tpm_db_gmac_lpk_queue_get(&gmac_num, &queue_idx)) {
+		printk("Loopback Tx queue index get failed\n");
+		return TPM_FAIL;
+	}
+	/* rule num is always 0 */
+	ret_code = tpm_proc_add_mac_learn_rule(TPM_MOD_OWNER_TPM, 0, queue_idx, src_mac_addr, &rule_idx);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+
+/*******************************************************************************
+* tpm_proc_del_static_mac_rule()
+*
+* DESCRIPTION:    Main function for deleting source MAC address learn API rule.
+*
+* INPUTS:
+* owner_id
+* rule_idx
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_del_static_mac_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr)
+{
+	tpm_error_code_t ret_code;
+	tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable = TPM_PNC_MAC_LEARN_DISABLED;
+	int32_t addr_exist = 0;
+	uint32_t rule_num = 0;
+	uint32_t tbl_num = 0;
+
+	/* check whether mac_learn_enable is enabled or not */
+	ret_code = tpm_db_pnc_mac_learn_enable_get(&pnc_mac_learn_enable);
+	IF_ERROR(ret_code);
+	if (pnc_mac_learn_enable == TPM_PNC_MAC_LEARN_DISABLED) {
+		printk("MAC learn is not enabled\n");
+		return TPM_FAIL;
+	}
+
+	/* check whether the MAC exist in system or not */
+	ret_code = tpm_proc_find_mac_addr_db(src_mac_addr, &addr_exist, &rule_num, &tbl_num);
+	IF_ERROR(ret_code);
+	if (addr_exist == 0) {
+		printk("The src mac entry not exist\n");
+		return TPM_FAIL;
+	} else {
+		TPM_OS_DEBUG(TPM_TPM_LOG_MOD, " owner(%d) rule_idx(%d)", owner_id, rule_num);
+
+		ret_code = tpm_proc_del_acl_rule(TPM_PNC_MAC_LEARN_ACL, owner_id, rule_num, TPM_EXT_CALL);
+		IF_ERROR(ret_code);
+	}
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_mac_learn_default_rule_act_set()
+*
+* DESCRIPTION:    Function used to set mac learn default rule action dynamiclly.
+*
+* INPUTS:
+* owner_id   - see L2 rule add
+* mac_conf   - default rule conf, 3 options: trap to CPU, drop packet, frwd to GMAC1
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_mac_learn_default_rule_act_set(uint32_t owner_id, tpm_unknown_mac_conf_t mac_conf)
+{
+	tpm_error_code_t ret_code;
+	tpm_db_pnc_range_t range_data;
+	tpm_pnc_all_t pnc_entry;
+	uint32_t entry_id;
+	int32_t cpu_rx_queue;
+	uint32_t queue_id;
+	tpm_gmacs_enum_t lpk_gmac;
+	uint32_t switch_init;
+
+	/* check switch init */
+	ret_code = tpm_db_switch_init_get(&switch_init);
+	IF_ERROR(ret_code);
+	if (switch_init != 0) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Switch is initialized, no need for PnC MAC learn \n");
+		return TPM_FAIL;
+	}
+	/*check MAC learn defaut rule conf*/
+	if (mac_conf < TPM_UNK_MAC_TRAP || mac_conf > TPM_UNK_MAC_CONTINUE) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "Invalid MAC learn default rule conf(%d) \n", mac_conf);
+		return ERR_UNKNOWN_MAC_CONF_INVALID;
+	}
+
+	/* Set Structs to zero */
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+
+	/* Get default rul entry ID */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_MAC_LEARN, &range_data);
+	IF_ERROR(ret_code);
+	entry_id = range_data.pnc_range_conf.range_end;
+
+	/* construct default rule */
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id;
+	/* Set port_id */
+	pnc_entry.tcam_entry.port_ids = TPM_BM_GMAC_0;
+	/* Set LU Done */
+	pnc_entry.sram_entry.lookup_done = TPM_TRUE;
+
+	pnc_entry.sram_entry.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	pnc_entry.sram_entry.flowid_updt_mask = TPM_TXP_FL_UPDT_MASK;
+	switch (mac_conf) {
+	case TPM_UNK_MAC_TRAP:
+		/* Get default CPU queue */
+		tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+		/* Trap to CPU */
+		pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_CPU << TPM_TXP_FL_SHIFT);
+		pnc_entry.sram_entry.pnc_queue = cpu_rx_queue;
+		/* Set result info */
+		pnc_entry.sram_entry.res_info_15_0_data |= (1 << TPM_PNC_RI_MAC_LEARN_BIT);
+		pnc_entry.sram_entry.res_info_15_0_mask |= (1 << TPM_PNC_RI_MAC_LEARN_BIT);
+		break;
+	case TPM_UNK_MAC_DROP:
+		/* Drop the packet */
+		pnc_entry.sram_entry.res_info_15_0_data |= (1 << TPM_PNC_RI_DISC_BIT);
+		pnc_entry.sram_entry.res_info_15_0_mask |= (1 << TPM_PNC_RI_DISC_BIT);
+		break;
+	case TPM_UNK_MAC_CONTINUE:
+		if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac, &queue_id)) {
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "loopback gmac queue get failed \n");
+			return TPM_FAIL;
+		}
+		/* Frwd to loopback GMAC1 */
+		pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_GMAC1 << TPM_TXP_FL_SHIFT);
+		pnc_entry.sram_entry.pnc_queue = queue_id;
+		break;
+	default:
+		break;
+	}
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_proc_mac_learn_entry_num_get()
+*
+* DESCRIPTION:    Function used to set mac learn default rule action dynamiclly.
+*
+* INPUTS:
+* none
+*
+* OUTPUTS:
+* entry_num  - current MAC learn entry count in MAC_LEARN range, not including default one
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_proc_mac_learn_entry_num_get(uint32_t *entry_num)
+{
+	tpm_error_code_t ret_code;
+	uint32_t valid_entry_num = 0;
+	uint32_t api_rng_size, tbl_start;
+	int32_t apisec_last_valid_index;
+	tpm_pnc_ranges_t pnc_range;
+	tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable = TPM_PNC_MAC_LEARN_DISABLED;
+
+	/* check whether mac_learn_enable is enabled or not */
+	ret_code = tpm_db_pnc_mac_learn_enable_get(&pnc_mac_learn_enable);
+	IF_ERROR(ret_code);
+	if (pnc_mac_learn_enable == TPM_PNC_MAC_LEARN_DISABLED) {
+		printk("MAC learn is not enabled\n");
+		return TPM_FAIL;
+	}
+
+	/* get API section info */
+	ret_code = tpm_db_api_section_get(TPM_PNC_MAC_LEARN_ACL,
+					  &api_rng_size,
+					  &valid_entry_num,
+					  &pnc_range,
+					  &apisec_last_valid_index,
+					  &tbl_start);
+	IF_ERROR(ret_code);
+
+	*entry_num = valid_entry_num;
+
+	return TPM_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.h
new file mode 100755
index 0000000..2899e15
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pkt_proc_logic.h
@@ -0,0 +1,874 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_pkt_proc_logic.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.3
+*
+*
+*******************************************************************************/
+#ifndef _TPM_PKT_PROCL_H_
+#define _TPM_PKT_PROCL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+#define MASK_AI(value)   (0x7f & (value))
+
+#define AI_TO_MASK(off, size)   (((1<<size) - 1) << off)
+
+/* Definitions for statically configured AI bits */
+
+#define      TPM_AI_TAG1_BIT_OFF                (0)
+#define      TPM_AI_TAG1_BIT_SIZE               (1)
+#define      TPM_AI_TAG1_MASK                   (AI_TO_MASK(TPM_AI_TAG1_BIT_OFF, TPM_AI_TAG1_BIT_SIZE))
+
+#define      TPM_AI_NH2_ITER_BIT_OFF            (0)
+#define      TPM_AI_NH2_ITER_BIT_SIZE           (1)
+#define      TPM_AI_NH2_ITER_MASK               (AI_TO_MASK(TPM_AI_NH2_ITER_BIT_OFF, TPM_AI_NH2_ITER_BIT_SIZE))
+
+#define      TPM_AI_L4P_BIT_OFF                 (0)
+#define      TPM_AI_L4P_BIT_SIZE                (1)
+#define      TPM_AI_L4P_MASK                    (AI_TO_MASK(TPM_AI_L4P_BIT_OFF, TPM_AI_L4P_BIT_SIZE))
+
+#define      TPM_AI_IPV6_SUBFLOW_PART1_BIT_OFF  (0)
+#define      TPM_AI_IPV6_SUBFLOW_PART1_BIT_SIZE (TPM_NUM_IPV6_SUBFLOW_BITS_P1)
+#define      TPM_AI_IPV6_SUBFLOW_PART1_MASK     (AI_TO_MASK(TPM_AI_IPV6_SUBFLOW_PART1_BIT_OFF, \
+															TPM_AI_IPV6_SUBFLOW_PART1_BIT_SIZE))
+#define      TPM_AI_IPV6_MC_SIP_PART1_BIT_OFF  (0)
+#define      TPM_AI_IPV6_MC_SIP_PART1_BIT_SIZE (TPM_NUM_IPV6_MC_SIP_BITS_P1)
+#define      TPM_AI_IPV6_MC_SIP_PART1_MASK     (AI_TO_MASK(TPM_AI_IPV6_MC_SIP_PART1_BIT_OFF, \
+							   TPM_AI_IPV6_MC_SIP_PART1_BIT_SIZE))
+
+#define      TPM_AI_CNM_IPV4_BIT_OFF            (0)
+#define      TPM_AI_CNM_IPV4_BIT_SIZE           (1)
+#define      TPM_AI_CNM_IPV4_MASK               (AI_TO_MASK(TPM_AI_CNM_IPV4_BIT_OFF, TPM_AI_CNM_IPV4_BIT_SIZE))
+
+#define      TPM_AI_TAG2_BIT_OFF                (1)
+#define      TPM_AI_TAG2_BIT_SIZE               (1)
+#define      TPM_AI_TAG2_MASK                   (AI_TO_MASK(TPM_AI_TAG2_BIT_OFF, TPM_AI_TAG2_BIT_SIZE))
+
+#define      TPM_AI_PPPOE_BIT_OFF               (1)
+#define      TPM_AI_PPPOE_BIT_SIZE              (1)
+#define      TPM_AI_PPPOE_MASK                  (AI_TO_MASK(TPM_AI_PPPOE_BIT_OFF, TPM_AI_PPPOE_BIT_SIZE))
+
+#define      TPM_AI_CNM_IPV4_PRE_KEY_BIT_OFF    (1)
+#define      TPM_AI_CNM_IPV4_PRE_KEY_BIT_SIZE   (3)
+#define      TPM_AI_CNM_IPV4_PRE_KEY_MASK       (AI_TO_MASK(TPM_AI_CNM_IPV4_PRE_KEY_BIT_OFF, \
+							    TPM_AI_CNM_IPV4_PRE_KEY_BIT_SIZE))
+
+#define      TPM_AI_CNM_PREC_BIT_OFF            (1)
+#define      TPM_AI_CNM_PREC_BIT_SIZE           (3)
+#define      TPM_AI_CNM_PREC_MASK               (AI_TO_MASK(TPM_AI_CNM_PREC_BIT_OFF, TPM_AI_CNM_PREC_BIT_SIZE))
+
+#define      TPM_AI_DNRT_BIT_OFF                (2)
+#define      TPM_AI_DNRT_BIT_SIZE               (1)
+#define      TPM_AI_DNRT_MASK                   (AI_TO_MASK(TPM_AI_DNRT_BIT_OFF, TPM_AI_DNRT_BIT_SIZE))
+
+#define      TPM_AI_MTM_BIT_OFF                 (2)
+#define      TPM_AI_MTM_BIT_SIZE                (1)
+#define      TPM_AI_MTM_MASK                    (AI_TO_MASK(TPM_AI_MTM_BIT_OFF, TPM_AI_MTM_BIT_SIZE))
+
+#define      TPM_AI_IPV6_MC_SIP_PART2_BIT_OFF   (2)
+#define      TPM_AI_IPV6_MC_SIP_PART2_BIT_SIZE  (TPM_NUM_IPV6_MC_SIP_BITS_P2)
+#define      TPM_AI_IPV6_MC_SIP_PART2_MASK      (AI_TO_MASK(TPM_AI_IPV6_MC_SIP_PART2_BIT_OFF, \
+							    TPM_AI_IPV6_MC_SIP_PART2_BIT_SIZE))
+#define      TPM_AI_TO_CPU_BIT_OFF              (3)
+#define      TPM_AI_TO_CPU_BIT_SIZE             (1)
+#define      TPM_AI_TO_CPU_MASK                 (AI_TO_MASK(TPM_AI_TO_CPU_BIT_OFF, TPM_AI_TO_CPU_BIT_SIZE))
+
+#define      TPM_AI_SPLIT_MOD_BIT_OFF           (3)
+#define      TPM_AI_SPLIT_MOD_BIT_SIZE          (1)
+#define      TPM_AI_SPLIT_MOD_MASK              (AI_TO_MASK(TPM_AI_SPLIT_MOD_BIT_OFF, TPM_AI_SPLIT_MOD_BIT_SIZE))
+
+#define      TPM_AI_UNI_BIT_OFF                 (4)
+#define      TPM_AI_UNI_BIT_SIZE                (3)
+#define      TPM_AI_UNI_MASK                    (AI_TO_MASK(TPM_AI_UNI_BIT_OFF, TPM_AI_UNI_BIT_SIZE))
+
+#define      TPM_AI_MC_VID_BIT_OFF              (4)
+#define      TPM_AI_MC_VID_BIT_SIZE             (TPM_NUM_MC_VID_BITS)
+#define      TPM_AI_MC_VID_MASK                 (AI_TO_MASK(TPM_AI_MC_VID_BIT_OFF, TPM_AI_MC_VID_BIT_SIZE))
+
+#define      TPM_AI_PPPOE_ADD_BIT_OFF           (4)
+#define      TPM_AI_PPPOE_ADD_BIT_SIZE          (1)
+#define      TPM_AI_PPPOE_ADD_MASK              (AI_TO_MASK(TPM_AI_PPPOE_ADD_BIT_OFF, TPM_AI_PPPOE_ADD_BIT_SIZE))
+
+#define      TPM_AI_IPV6_SUBFLOW_PART2_BIT_OFF  (4)
+#define      TPM_AI_IPV6_SUBFLOW_PART2_BIT_SIZE (TPM_NUM_IPV6_SUBFLOW_BITS_P2)
+#define      TPM_AI_IPV6_SUBFLOW_PART2_MASK     (AI_TO_MASK(TPM_AI_IPV6_SUBFLOW_PART2_BIT_OFF, \
+															TPM_AI_IPV6_SUBFLOW_PART2_BIT_SIZE))
+
+#define      TPM_AI_NO_PROTO_BIT_OFF            (5)
+#define      TPM_AI_NO_PROTO_BIT_SIZE           (1)
+#define      TPM_AI_NO_PROTO_MASK               (AI_TO_MASK(TPM_AI_NO_PROTO_BIT_OFF, TPM_AI_NO_PROTO_BIT_SIZE))
+
+#define      TPM_AI_NO_FRAG_BIT_OFF             (6)
+#define      TPM_AI_NO_FRAG_BIT_SIZE            (1)
+#define      TPM_AI_NO_FRAG_MASK                (AI_TO_MASK(TPM_AI_NO_FRAG_BIT_OFF, TPM_AI_NO_FRAG_BIT_SIZE))
+
+#define      TPM_AI_MC_VID_VALID_BIT_OFF        (6)
+#define      TPM_AI_MC_VID_VALID_BIT_SIZE       (1)
+#define      TPM_AI_MC_VID_VALID_MASK           (AI_TO_MASK(TPM_AI_MC_VID_VALID_BIT_OFF, TPM_AI_MC_VID_VALID_BIT_SIZE))
+
+/* End of  statically configured AI bits */
+
+#define      TPM_MAX_AS_SES_TBL_SIZE           (128)
+
+#define      TPM_TCP_FIN                       (0x1)
+#define      TPM_TCP_RES                       (0x4)
+
+#define     TPM_NH_RESERVED                    (0xFFFF)
+#define     TPM_ETHERTYPE_DSA_TAG              (0xDABC)
+
+#define PKT_DROP(pkt_act)           (pkt_act & TPM_ACTION_DROP_PK)
+#define SET_TARGET_PORT(pkt_act)    (pkt_act & TPM_ACTION_SET_TARGET_PORT)
+#define SET_TARGET_QUEUE(pkt_act)   (pkt_act & TPM_ACTION_SET_TARGET_QUEUE)
+#define SET_CPU(pkt_act)            (pkt_act & TPM_ACTION_TO_CPU)
+#define SET_MOD(pkt_act)            (pkt_act & TPM_ACTION_SET_PKT_MOD)
+#define SET_CUST(pkt_act)           (pkt_act & TPM_ACTION_CUST_CPU_PKT_PARSE)
+#define SET_UDP_CHKSUM_CALC(pkt_act) (pkt_act & TPM_ACTION_UDP_CHKSUM_CALC)
+
+#define TO_PON(dir, trg, wan, act_wan)		\
+	 (TRG_PON(trg) && (TPM_ENUM_PMAC == act_wan) && (dir == TPM_DIR_US) && \
+	 (wan == TPM_EPON || wan == TPM_GPON || wan == TPM_P2P))
+#define TO_GPON(dir, trg, wan, act_wan)	\
+	(TRG_PON(trg) && (dir == TPM_DIR_US) && (wan == TPM_GPON) && (act_wan == TPM_ENUM_PMAC))
+#define TO_EPON(dir, trg, wan, act_wan)	\
+	(TRG_PON(trg) && (dir == TPM_DIR_US) && (wan == TPM_EPON) && (act_wan == TPM_ENUM_PMAC))
+#define TO_ETHWAN(dir, trg, act_wan)		\
+	((trg == TPM_TRG_PORT_WAN) && (dir == TPM_DIR_US) && ((act_wan == TPM_ENUM_GMAC_0) || (act_wan == TPM_ENUM_GMAC_1)))
+#define TO_LAN(dir, trg)            (TRG_UNI(trg) && (dir == TPM_DIR_DS))
+#define TO_CPU(trg)                 (TRG_CPU(trg))
+
+/* TODO - TPM_TRG_UNI_4 should be from DB, not hardcoded */
+#define TRG_UNI(trg)                (trg & \
+				     (TPM_TRG_UNI_0|TPM_TRG_UNI_1|TPM_TRG_UNI_2|TPM_TRG_UNI_3|TPM_TRG_UNI_4| \
+				      TPM_TRG_UNI_5|TPM_TRG_UNI_6|TPM_TRG_UNI_7|TPM_TRG_UNI_VIRT|TPM_TRG_PORT_UNI_ANY))
+#define TRG_PON(trg)                (trg >= TPM_TRG_TCONT_0 && trg <= TPM_TRG_TCONT_7)
+#define TRG_WAN(trg)                ((trg >= TPM_TRG_TCONT_0 && trg <= TPM_TRG_TCONT_7) || (trg == TPM_TRG_PORT_WAN))
+#define TRG_CPU(trg)                (trg == TPM_TRG_PORT_CPU)
+
+#define FROM_WAN(src)               ((src == TPM_SRC_PORT_WAN) || (src == TPM_SRC_PORT_WAN_OR_LAN))
+#define FROM_SPEC_UNI(src)          (src >= TPM_SRC_PORT_UNI_0 && src <= TPM_SRC_PORT_UNI_VIRT)
+#define FROM_LAN(src)               (src != TPM_SRC_PORT_WAN)
+
+#define GMAC_IS_LAN(gmac_func)          ((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_LAN))
+#define GMAC_IS_WAN(gmac_func)          ((gmac_func == TPM_GMAC_FUNC_LAN_AND_WAN) || (gmac_func == TPM_GMAC_FUNC_WAN))
+#define GMAC_IS_UNI_LAN(gmac_func)      (gmac_func == TPM_GMAC_FUNC_LAN_UNI)
+#define GMAC_IS_UNI_VIRT(gmac_func)     (gmac_func == TPM_GMAC_FUNC_VIRT_UNI)
+
+
+#define TPM_CNM_L2_MAIN_LUID_OFFSET      (0)
+#define TPM_CNM_ETY_MAIN_LUID_OFFSET     (1)
+#define TPM_CNM_IPV4_MAIN_LUID_OFFSET    (2)
+#define TPM_CNM_IPV6_MAIN_LUID_OFFSET    (3)
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+
+typedef enum {
+	TTL_ZERO_DROP,
+	TTL_ZERO_TO_CPU
+} ttl_illegal_action_t;
+
+typedef enum {
+	TPM_ADD_L2_PRIM_ACL_RULE,
+	TPM_ADD_L3_TYPE_ACL_RULE,
+	TPM_ADD_IPV4_ACL_RULE,
+	TPM_ADD_IPV6_NH_ACL_RULE,
+	TPM_ADD_IPV6_GEN_ACL_RULE,
+	TPM_ADD_IPV6_DIP_ACL_RULE,
+	TPM_ADD_IPV6_L4_PORTS_ACL_RULE,
+	TPM_ADD_IPV6_GEN_5T_RULE,
+	TPM_ADD_IPV6_DIP_5T_RULE,
+	TPM_ADD_IPV6_L4_PORTS_5T_RULE,
+	TPM_NUM_AI_APIS
+} tpm_pnc_apis;
+
+/*************************************************************/
+/*               STRUCTURES                                  */
+/*************************************************************/
+
+typedef struct {
+	tpm_src_port_type_t src_port;
+	uint32_t mc_vid_entry;
+	uint32_t ipv6_subflow;
+	uint32_t ipv4_pre_key;
+	uint32_t cnm_prec;
+	uint32_t ipv6_mc_sip_indx;
+} tpm_ai_vectors_t;
+
+typedef struct {
+	tpm_pnc_apis api_num;
+	tpm_parse_fields_t sup_parse_fields;
+	tpm_parse_flags_t sup_parse_flags;
+	tpm_pkt_action_t forbidden_actions;
+} tpm_api_sup_param_val_t;
+
+/* Structure for add mc vid */
+typedef struct {
+	uint32_t port_bm;
+	uint32_t mc_vid;
+} tpm_mc_vid_port_t;
+
+typedef struct {
+	uint32_t vid_num;
+	tpm_mc_vid_port_t mc_vid_port[TPM_MAX_NUM_UNI_PORTS];
+} tpm_mc_vid_t;
+
+/* CNM related */
+typedef int32_t (* check_cnm_ipv4_pre_filter_key_fn_t)(tpm_src_port_type_t src_port, uint32_t partner_key_bm, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+typedef int32_t (* add_cnm_ipv4_pre_filter_key_fn_t)(tpm_src_port_type_t src_port, uint32_t key_idx, uint32_t key_pattern, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+typedef int32_t (* del_cnm_ipv4_pre_filter_key_fn_t)(tpm_src_port_type_t src_port, uint32_t key_pattern, uint32_t key_idx);
+
+
+typedef struct {
+	uint32_t key_pattern;
+	check_cnm_ipv4_pre_filter_key_fn_t check_cnm_ipv4_pre_filter;
+	add_cnm_ipv4_pre_filter_key_fn_t add_cnm_ipv4_pre_filter;
+	del_cnm_ipv4_pre_filter_key_fn_t del_cnm_ipv4_pre_filter;
+} tpm_cnm_ipv4_pre_filter_rule_oper_t;
+
+
+/* API's */
+
+tpm_error_code_t tpm_proc_mib_reset(uint32_t owner_id, tpm_reset_level_enum_t reset_level);
+
+uint32_t tpm_proc_get_cpu_lpbk_entry_num(void);
+
+tpm_error_code_t tpm_proc_increase_cpu_lpbk_entry_num(void);
+
+tpm_error_code_t tpm_proc_decrease_cpu_lpbk_entry_num(void);
+
+tpm_error_code_t tpm_proc_check_cpu_wan_loopback_param(uint32_t owner_id, tpm_pkt_frwd_t *pkt_frwd);
+
+tpm_error_code_t tpm_proc_calc_flow_id(uint32_t owner_id, tpm_pkt_frwd_t *pkt_frwd, uint16_t *flow_id);
+
+int32_t tpm_proc_init_cpu_wan_loopback(void);
+
+tpm_cpu_loopback_t *tpm_proc_get_loopback_entry(uint16_t flow_id);
+
+tpm_error_code_t tpm_proc_add_cpu_loopback_rule(uint32_t owner_id,
+						uint32_t rule_num,
+						uint32_t *rule_idx,
+						tpm_pkt_frwd_t *pkt_frwd);
+
+tpm_error_code_t tpm_proc_add_cpu_wan_loopback(uint32_t owner_id,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       uint32_t *mod_idx);
+
+tpm_error_code_t tpm_proc_del_cpu_wan_loopback(uint32_t owner_id, tpm_pkt_frwd_t *pkt_frwd);
+
+int32_t tpm_proc_l2_tcam_build(tpm_src_port_type_t src_port,
+			       tpm_dir_t dir,
+			       uint32_t rule_num,
+			       tpm_l2_acl_key_t *l2_key,
+			       tpm_parse_fields_t parse_rule_bm,
+			       tpm_parse_flags_t parse_flags_bm,
+			       tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_l2_sram_build(tpm_src_port_type_t src_port,
+			       tpm_dir_t dir,
+			       uint32_t rule_num,
+			       tpm_db_pon_type_t pon_type,
+			       tpm_pkt_frwd_t *pkt_frwd,
+			       tpm_rule_action_t *rule_action,
+			       uint32_t mod_cmd,
+			       tpm_pncl_sram_data_t *sram_data,
+			       tpm_l2_acl_key_t *l2_key,
+			       tpm_pkt_mod_t *pkt_mod,
+			       tpm_pkt_mod_bm_t pkt_mod_bm);
+
+tpm_error_code_t tpm_proc_add_l2_prim_acl_rule(uint32_t owner_id,
+					       tpm_src_port_type_t src_port,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l2_acl_key_t *l2_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_pkt_mod_t *pkt_mod,
+					       tpm_pkt_mod_bm_t pkt_mod_bm,
+					       tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_add_ipv4_acl_rule(uint32_t owner_id,
+					    tpm_src_port_type_t src_port,
+					    uint32_t rule_num,
+					    uint32_t *rule_idx,
+					    tpm_parse_fields_t parse_rule_bm,
+					    tpm_parse_flags_t parse_flags_bm,
+					    tpm_ipv4_acl_key_t *ipv4_key,
+					    tpm_pkt_frwd_t *pkt_frwd,
+					    tpm_pkt_mod_t *pkt_mod,
+					    tpm_pkt_mod_bm_t pkt_mod_bm,
+					    tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_add_l3_type_acl_rule(uint32_t owner_id,
+					       tpm_src_port_type_t src_port,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l3_type_key_t *l3_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_get_next_valid_rule(uint32_t owner_id,
+					      int32_t current_index,
+					      tpm_api_type_t rule_type,
+					      int32_t *next_index,
+					      uint32_t *rule_idx,
+					      tpm_rule_entry_t *tpm_rule);
+
+tpm_error_code_t tpm_proc_omci_add_channel(uint32_t owner_id,
+					   tpm_gem_port_key_t gem_port,
+					   uint32_t cpu_rx_queue,
+					   tpm_trg_port_type_t tcont_num,
+					   uint32_t cpu_tx_queue);
+
+tpm_error_code_t tpm_proc_omci_del_channel(uint32_t owner_id);
+
+tpm_error_code_t tpm_proc_oam_epon_add_channel(uint32_t owner_id,
+					       uint32_t cpu_rx_queue,
+					       tpm_trg_port_type_t llid_num);
+
+tpm_error_code_t tpm_proc_loop_detect_add_channel(uint32_t owner_id);
+
+tpm_error_code_t tpm_proc_oam_loopback_add_channel(uint32_t owner_id);
+
+tpm_error_code_t tpm_proc_oam_loopback_del_channel(uint32_t owner_id);
+
+tpm_error_code_t tpm_proc_oam_epon_del_channel(uint32_t owner_id);
+
+int32_t tpm_proc_l3_tcam_build(tpm_src_port_type_t src_port,
+			       tpm_dir_t dir,
+			       uint32_t rule_num,
+			       tpm_l3_type_key_t *l3_key,
+			       tpm_parse_fields_t parse_rule_bm,
+			       tpm_parse_flags_t parse_flags_bm,
+			       tpm_rule_action_t *rule_action,
+			       tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_l3_sram_build(tpm_src_port_type_t src_port,
+			       tpm_dir_t dir,
+			       uint32_t rule_num,
+			       uint8_t is_pppoe,
+			       tpm_db_pon_type_t pon_type,
+			       tpm_pkt_frwd_t *pkt_frwd,
+			       tpm_rule_action_t *rule_action,
+			       tpm_parse_flags_t parse_flags_bm,
+			       tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_del_l3_type_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+
+tpm_error_code_t tpm_proc_erase_section(uint32_t owner_id, tpm_api_type_t api_type);
+
+tpm_error_code_t tpm_proc_del_ipv4_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+
+tpm_error_code_t tpm_proc_add_ipv4_mc_stream(uint32_t owner_id,
+					     uint32_t stream_num,
+					     tpm_mc_igmp_mode_t igmp_mode,
+					     uint8_t mc_stream_pppoe,
+					     uint16_t vid,
+					     uint8_t ipv4_src_add[4],
+					     uint8_t ipv4_dst_add[4],
+					     uint8_t ignore_ipv4_src,
+					     tpm_trg_port_type_t dest_port_bm);
+
+int32_t tpm_proc_ipv4_sram_build(tpm_src_port_type_t src_port,
+				 tpm_dir_t dir,
+				 uint32_t rule_num,
+				 tpm_db_pon_type_t pon_type,
+				 tpm_ipv4_acl_key_t *ipv4_key,
+				 tpm_parse_fields_t ipv4_parse_bm,
+				 tpm_parse_flags_t parse_flags_bm,
+				 tpm_pkt_frwd_t *pkt_frwd,
+				 tpm_rule_action_t *rule_action,
+				 uint32_t mod_cmd,
+				 tpm_pkt_mod_bm_t pkt_mod_bm,
+				 tpm_pkt_mod_t *pkt_mod,
+				 tpm_pncl_sram_data_t *sram_data);
+
+int32_t tpm_proc_ipv4_tcam_build(tpm_src_port_type_t src_port,
+				 tpm_dir_t dir,
+				 uint32_t rule_num,
+				 tpm_ipv4_acl_key_t *ipv4_key,
+				 tpm_parse_fields_t parse_rule_bm,
+				 tpm_parse_flags_t parse_flags_bm,
+				 tpm_rule_action_t *rule_action,
+				 tpm_pkt_mod_t *pkt_mod,
+				 tpm_pkt_mod_bm_t pkt_mod_bm,
+				 tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv4_mc_tcam_build(tpm_mc_filter_mode_t filter_mode,
+				    uint32_t stream_num,
+				    uint16_t vid,
+				    uint8_t mc_stream_pppoe,
+				    uint8_t ipv4_src_add[4],
+				    uint8_t ipv4_dst_add[4],
+				    uint8_t ignore_ipv4_src,
+				    tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv4_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
+				    tpm_mc_igmp_mode_t igmp_mode,
+				    tpm_trg_port_type_t target_port,
+				    uint32_t mod_entry,
+				    tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_updt_ipv4_mc_stream(uint32_t owner_id,
+					      uint32_t stream_num, tpm_trg_port_type_t dest_port_bm);
+
+tpm_error_code_t tpm_proc_del_ipv4_mc_stream(uint32_t owner_id, uint32_t stream_num);
+
+int32_t tpm_proc_ipv6_mc_tcam_build(tpm_mc_filter_mode_t filter_mode,
+				    uint32_t stream_num,
+				    uint16_t vid,
+				    uint8_t mc_stream_pppoe,
+				    uint8_t ipv6_dst_add[16],
+				    uint8_t sip_index,
+				    uint8_t ignore_sip,
+				    tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv6_mc_sram_build(tpm_mc_filter_mode_t filter_mode,
+				    tpm_mc_igmp_mode_t igmp_mode,
+				    tpm_trg_port_type_t target_port,
+				    uint32_t mod_entry,
+				    tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_add_ipv6_mc_stream(uint32_t owner_id,
+					     uint32_t stream_num,
+					     tpm_mc_igmp_mode_t igmp_mode,
+					     uint8_t mc_stream_pppoe,
+					     uint16_t vid,
+					     uint8_t ipv6_src_add[16],
+					     uint8_t ipv6_dst_add[16],
+					     uint8_t ignore_ipv6_src,
+					     tpm_trg_port_type_t dest_port_bm);
+
+tpm_error_code_t tpm_proc_updt_ipv6_mc_stream(uint32_t owner_id,
+					      uint32_t stream_num, tpm_trg_port_type_t dest_port_bm);
+tpm_error_code_t tpm_proc_del_ipv6_mc_stream(uint32_t owner_id, uint32_t stream_num);
+
+tpm_error_code_t tpm_proc_del_l2_prim_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+
+int32_t tpm_proc_src_port_gmac_bm_map(tpm_src_port_type_t src_port, tpm_gmac_bm_t *gmac_bm);
+
+tpm_error_code_t tpm_proc_l2_num_vlan_tags_init(void);
+tpm_error_code_t tpm_proc_ipv4_ttl_init(uint32_t ttl_illegal_action);
+tpm_error_code_t tpm_proc_tcp_flag_init(void);
+tpm_error_code_t tpm_proc_ipv4_len_init(void);
+tpm_error_code_t tpm_proc_ipv4_igmp_init(void);
+tpm_error_code_t tpm_proc_ipv4_proto_init(void);
+tpm_error_code_t tpm_proc_ipv4_frag_init(void);
+
+tpm_error_code_t tpm_proc_virt_uni_init(void);
+
+tpm_error_code_t tpm_proc_add_uni_port_igmp_rule(tpm_src_port_type_t src_port, tpm_igmp_frwd_mode_t mode);
+tpm_error_code_t tpm_proc_add_wan_port_igmp_rule(tpm_igmp_frwd_mode_t mode);
+tpm_error_code_t tpm_proc_del_port_igmp_rule(tpm_src_port_type_t src_port);
+
+int32_t tpm_proc_ipv6_nh_tcam_build(uint32_t rule_num,
+				    tpm_nh_iter_t nh_iter,
+				    uint32_t nh,
+				    tpm_parse_flags_t parse_flags_bm,
+				    tpm_rule_action_t *rule_action,
+				    tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv6_nh_sram_build(uint32_t rule_num,
+				    tpm_nh_iter_t nh_iter,
+				    uint32_t nh,
+				    tpm_db_pon_type_t pon_type,
+				    tpm_pkt_frwd_t *pkt_frwd,
+				    tpm_rule_action_t *rule_action,
+				    tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_add_ipv6_nh_acl_rule(uint32_t owner_id,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_nh_iter_t nh_iter,
+					       uint32_t nh,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_del_ipv6_nh_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+
+int32_t tpm_proc_ipv6_gen_tcam_build(tpm_src_port_type_t src_port,
+				     tpm_dir_t dir,
+				     uint32_t rule_num,
+				     tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+				     tpm_parse_fields_t parse_rule_bm,
+				     tpm_parse_flags_t parse_flags_bm,
+				     tpm_pkt_mod_t *pkt_mod,
+				     tpm_pkt_mod_bm_t pkt_mod_bm,
+				     tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv6_gen_sram_build(tpm_src_port_type_t src_port,
+				     tpm_dir_t dir,
+				     uint32_t rule_num,
+				     tpm_db_pon_type_t pon_type,
+				     tpm_pkt_frwd_t *pkt_frwd,
+				     tpm_rule_action_t *rule_action,
+				     uint32_t mod_cmd,
+				     tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_add_ipv6_gen_acl_rule(uint32_t owner_id,
+						tpm_src_port_type_t src_port,
+						uint32_t rule_num,
+						uint32_t *rule_idx,
+						tpm_parse_fields_t parse_rule_bm,
+						tpm_parse_flags_t parse_flags_bm,
+						tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+						tpm_pkt_frwd_t *pkt_frwd,
+						tpm_pkt_mod_t *pkt_mod,
+						tpm_pkt_mod_bm_t pkt_mod_bm,
+						tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_del_ipv6_gen_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+
+int32_t tpm_proc_ipv6_dip_tcam_build(tpm_src_port_type_t src_port,
+				     tpm_dir_t dir,
+				     uint32_t rule_num,
+				     tpm_ipv6_addr_key_t *ipv6_dip_key,
+				     tpm_parse_fields_t parse_rule_bm,
+				     tpm_parse_flags_t parse_flags_bm,
+				     tpm_pkt_mod_t *pkt_mod,
+				     tpm_pkt_mod_bm_t pkt_mod_bm,
+				     tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv6_dip_sram_build(tpm_src_port_type_t src_port,
+				     tpm_dir_t dir,
+				     uint32_t rule_num,
+				     tpm_db_pon_type_t pon_type,
+				     tpm_pkt_frwd_t *pkt_frwd,
+				     tpm_rule_action_t *rule_action,
+				     uint32_t mod_cmd,
+				     tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_add_ipv6_dip_acl_rule(uint32_t owner_id,
+						tpm_src_port_type_t src_port,
+						uint32_t rule_num,
+						uint32_t *rule_idx,
+						tpm_parse_fields_t parse_rule_bm,
+						tpm_parse_flags_t parse_flags_bm,
+						tpm_ipv6_addr_key_t *ipv6_dip_key,
+						tpm_pkt_frwd_t *pkt_frwd,
+						tpm_pkt_mod_t *pkt_mod,
+						tpm_pkt_mod_bm_t pkt_mod_bm,
+						tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_del_ipv6_dip_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+
+int32_t tpm_proc_ipv6_l4ports_tcam_build(tpm_src_port_type_t src_port,
+					 tpm_dir_t dir,
+					 uint32_t rule_num,
+					 tpm_l4_ports_key_t *l4_key,
+					 tpm_parse_fields_t parse_rule_bm,
+					 tpm_parse_flags_t parse_flags_bm,
+					 tpm_rule_action_t *rule_action,
+					 tpm_pkt_mod_t *pkt_mod,
+					 tpm_pkt_mod_bm_t pkt_mod_bm,
+					 tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv6_l4ports_sram_build(tpm_src_port_type_t src_port,
+					 tpm_dir_t dir,
+					 uint32_t rule_num,
+					 tpm_db_pon_type_t pon_type,
+					 tpm_pkt_frwd_t *pkt_frwd,
+					 tpm_rule_action_t *rule_action,
+					 uint32_t mod_cmd,
+					 tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_add_ipv6_l4_ports_acl_rule(uint32_t owner_id,
+						     tpm_src_port_type_t src_port,
+						     uint32_t rule_num,
+						     uint32_t *rule_idx,
+						     tpm_parse_fields_t parse_rule_bm,
+						     tpm_parse_flags_t parse_flags_bm,
+						     tpm_l4_ports_key_t *l4_key,
+						     tpm_pkt_frwd_t *pkt_frwd,
+						     tpm_pkt_mod_t *pkt_mod,
+						     tpm_pkt_mod_bm_t pkt_mod_bm,
+						     tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_del_ipv6_l4_ports_acl_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+
+tpm_error_code_t tpm_proc_del_acl_rule(tpm_api_sections_t api_section, uint32_t owner_id, uint32_t rule_idx, uint32_t busy_check);
+
+tpm_error_code_t tpm_proc_pnc_create(tpm_pnc_ranges_t range_id,
+				     uint32_t pnc_entry,
+				     tpm_pncl_pnc_full_t *pnc_data);
+
+uint32_t tpm_proc_all_gmac_bm(void);
+
+void tpm_proc_mc_vid_remove_ai_bits
+(tpm_rule_action_t *rule_action,
+ tpm_src_port_type_t src_port, tpm_l2_acl_key_t *l2_key, tpm_error_code_t ret_code);
+
+tpm_error_code_t tpm_proc_add_mc_vid_cfg(uint32_t mc_vid, tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config);
+
+tpm_error_code_t tpm_proc_remove_mc_vid_cfg(uint32_t mc_vid);
+
+tpm_error_code_t tpm_proc_update_mc_vid_cfg(uint32_t mc_vid,
+					    tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config);
+tpm_error_code_t tpm_proc_set_mc_vid_port_vids(uint32_t owner_id,
+					       uint32_t mc_vid,
+					       tpm_mc_vid_port_vid_set_t *mc_vid_uniports_config);
+
+tpm_error_code_t tpm_proc_catch_all_init(void);
+
+int32_t tpm_proc_ipv6_gen_5t_tcam_build(tpm_dir_t dir,
+					uint32_t rule_num,
+					tpm_l4_ports_key_t *l4_key,
+					tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					tpm_parse_fields_t parse_rule_bm,
+					tpm_parse_flags_t parse_flags_bm,
+					tpm_rule_action_t *rule_action,
+					tpm_pkt_mod_t *pkt_mod,
+					tpm_pkt_mod_bm_t pkt_mod_bm,
+					tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv6_gen_5t_sram_build(tpm_dir_t dir,
+					uint32_t rule_num,
+					tpm_db_pon_type_t pon_type,
+					uint32_t ipv6_gen_subflow,
+					tpm_pkt_frwd_t *pkt_frwd,
+					tpm_rule_action_t *rule_action,
+					long long int_pkt_act,
+					tpm_pkt_mod_t *pkt_mod,
+					uint32_t mod_cmd,
+					tpm_pncl_sram_data_t *sram_data);
+
+int32_t tpm_proc_ipv6_dip_5t_tcam_build(tpm_dir_t dir,
+					uint32_t rule_num,
+					tpm_l4_ports_key_t *l4_key,
+					tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					tpm_ipv6_addr_key_t *ipv6_dip_key,
+					tpm_parse_fields_t parse_rule_bm,
+					tpm_parse_flags_t parse_flags_bm,
+					tpm_rule_action_t *rule_action,
+					tpm_pkt_mod_t *pkt_mod,
+					tpm_pkt_mod_bm_t pkt_mod_bm,
+					tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv6_dip_5t_sram_build(tpm_dir_t dir,
+					uint32_t rule_num,
+					tpm_db_pon_type_t pon_type,
+					tpm_pkt_frwd_t *pkt_frwd,
+					tpm_rule_action_t *rule_action,
+					long long int_pkt_act,
+					tpm_pkt_mod_t *pkt_mod,
+					uint32_t mod_cmd,
+					tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_add_ipv6_gen_5t_rule(uint32_t owner_id,
+					       tpm_dir_t src_dir,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l4_ports_key_t *l4_key,
+					       tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_pkt_mod_t *pkt_mod,
+					       tpm_pkt_mod_bm_t pkt_mod_bm,
+					       tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_add_ipv6_dip_5t_rule(uint32_t owner_id,
+					       tpm_dir_t src_dir,
+					       uint32_t rule_num,
+					       uint32_t *rule_idx,
+					       tpm_parse_fields_t parse_rule_bm,
+					       tpm_parse_flags_t parse_flags_bm,
+					       tpm_l4_ports_key_t *l4_key,
+					       tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+					       tpm_ipv6_addr_key_t *ipv6_dip_key,
+					       tpm_pkt_frwd_t *pkt_frwd,
+					       tpm_pkt_mod_t *pkt_mod,
+					       tpm_pkt_mod_bm_t pkt_mod_bm,
+					       tpm_rule_action_t *rule_action);
+
+int32_t tpm_proc_ipv6_l4_ports_5t_tcam_build(tpm_dir_t dir,
+					     uint32_t rule_num,
+					     tpm_l4_ports_key_t *l4_key,
+					     tpm_parse_fields_t parse_rule_bm,
+					     tpm_parse_flags_t parse_flags_bm,
+					     tpm_rule_action_t *rule_action,
+					     tpm_pkt_mod_t *pkt_mod,
+					     tpm_pkt_mod_bm_t pkt_mod_bm,
+					     tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_ipv6_l4_ports_5t_sram_build(tpm_dir_t dir,
+					     uint32_t rule_num,
+					     tpm_db_pon_type_t pon_type,
+					     uint32_t ipv6_l4_subflow,
+					     tpm_pkt_frwd_t *pkt_frwd,
+					     tpm_rule_action_t *rule_action,
+					     long long int_pkt_act,
+					     tpm_pkt_mod_t *pkt_mod,
+					     uint32_t mod_cmd,
+					     tpm_pncl_sram_data_t *sram_data);
+
+tpm_error_code_t tpm_proc_add_ipv6_l4_ports_5t_rule(uint32_t owner_id,
+						    tpm_dir_t src_dir,
+						    uint32_t rule_num,
+						    uint32_t *rule_idx,
+						    tpm_parse_fields_t parse_rule_bm,
+						    tpm_parse_flags_t parse_flags_bm,
+						    tpm_l4_ports_key_t *l4_key,
+						    tpm_pkt_frwd_t *pkt_frwd,
+						    tpm_pkt_mod_t *pkt_mod,
+						    tpm_pkt_mod_bm_t pkt_mod_bm,
+						    tpm_rule_action_t *rule_action);
+
+tpm_error_code_t tpm_proc_del_ipv6_gen_5t_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+tpm_error_code_t tpm_proc_del_ipv6_dip_5t_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+tpm_error_code_t tpm_proc_del_ipv6_l4_ports_5t_rule(uint32_t owner_id, uint32_t rule_idx, tpm_caller_t ext_call);
+tpm_error_code_t tpm_proc_ipv6_hoplimit_init(uint32_t hoplimit_illegal_action);
+tpm_error_code_t tpm_proc_send_genquery_to_uni(tpm_trg_port_type_t dest_port_bm, uint32_t packet_num);
+tpm_error_code_t tpm_proc_ipv6_l4_mc_ds_init(void);
+tpm_error_code_t tpm_proc_ipv6_mc_sip_init(void);
+
+int32_t tpm_proc_cnm_l2_tcam_build(tpm_src_port_type_t src_port,
+				   tpm_parse_fields_t l2_parse_rule_bm,
+				   tpm_l2_acl_key_t *l2_key,
+				   uint32_t ipv4_key_idx,
+				   tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_cnm_l2_sram_build(uint32_t precedence,
+				   tpm_pkt_frwd_t *pkt_frwd,
+				   tpm_pkt_action_t pkt_act,
+				   uint32_t mod_cmd,
+				   tpm_pncl_sram_data_t *sram_data);
+
+int32_t tpm_proc_cnm_ipv4_tcam_build(tpm_src_port_type_t src_port,
+				     uint32_t precedence,
+				     tpm_parse_fields_t ipv4_parse_rule_bm,
+				     tpm_ipv4_acl_key_t *ipv4_key,
+				     tpm_pncl_tcam_data_t *tcam_data);
+
+int32_t tpm_proc_cnm_ipv4_sram_build(tpm_pkt_frwd_t *pkt_frwd,
+				     tpm_pkt_action_t pkt_act,
+				     uint32_t mod_cmd,
+				     tpm_pncl_sram_data_t *sram_data);
+
+uint8_t tpm_proc_if_ipv4_pre_range_is_full(tpm_src_port_type_t src_port, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key);
+uint8_t tpm_proc_if_cnm_main_range_is_full(tpm_src_port_type_t src_port, uint32_t precedence);
+int32_t tpm_proc_add_cnm_ipv4_pre_filter_key(uint32_t owner_id, tpm_src_port_type_t src_port, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key, uint32_t *key_idx);
+int32_t tpm_proc_del_cnm_ipv4_pre_filter_key(uint32_t owner_id, tpm_src_port_type_t src_port, uint32_t key_idx);
+int32_t tpm_proc_add_l2_cnm_rule(uint32_t owner_id, tpm_src_port_type_t src_port, uint32_t precedence, tpm_parse_fields_t l2_parse_rule_bm, tpm_l2_acl_key_t *l2_key, uint32_t ipv4_key_idx, tpm_pkt_frwd_t *pkt_frwd, tpm_pkt_action_t pkt_act, uint32_t pbits, uint32_t *rule_idx);
+int32_t tpm_proc_del_l2_cnm_rule(uint32_t owner_id, uint32_t rule_idx);
+int32_t tpm_proc_add_ipv4_cnm_rule(uint32_t owner_id, tpm_src_port_type_t src_port, uint32_t precedence, tpm_parse_fields_t ipv4_parse_rule_bm, tpm_ipv4_acl_key_t *ipv4_key, tpm_pkt_frwd_t *pkt_frwd, tpm_pkt_action_t pkt_act, uint32_t pbits, uint32_t *rule_idx);
+int32_t tpm_proc_add_ipv6_cnm_rule(uint32_t owner_id,
+				   tpm_src_port_type_t src_port,
+				   uint32_t precedence,
+				   tpm_parse_fields_t ipv6_parse_rule_bm,
+				   tpm_ipv6_acl_key_t *ipv6_key,
+				   tpm_pkt_frwd_t *pkt_frwd,
+				   tpm_pkt_action_t pkt_act,
+				   uint32_t pbits,
+				   uint32_t *rule_idx);
+int32_t tpm_proc_del_ipv4_cnm_rule(uint32_t owner_id, uint32_t rule_idx);
+int32_t tpm_proc_del_ipv6_cnm_rule(uint32_t owner_id, uint32_t rule_idx);
+int32_t tpm_proc_calc_cnm_rule_num(tpm_src_port_type_t src_port, uint32_t precedence, uint32_t *rule_num);
+tpm_error_code_t tpm_proc_find_mac_addr_db(tpm_l2_acl_key_t *src_mac_addr, int32_t *addr_exist, uint32_t *rule_num, uint32_t *tbl_num);
+tpm_error_code_t tpm_proc_add_static_mac_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr);
+tpm_error_code_t tpm_proc_del_static_mac_rule(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr);
+tpm_error_code_t tpm_proc_mac_learn_default_rule_act_set(uint32_t owner_id, tpm_unknown_mac_conf_t mac_conf);
+tpm_error_code_t tpm_proc_mac_learn_entry_num_get(uint32_t *entry_num);
+
+
+int32_t tpm_proc_check_api_busy(tpm_api_type_t api_type, uint32_t rule_num);
+int32_t tpm_proc_api_busy_done(tpm_api_type_t api_type, uint32_t rule_num);
+int32_t tpm_proc_src_port_dir_map(tpm_src_port_type_t src_port, tpm_dir_t *dir);
+
+bool tpm_split_mod_stage1_check(tpm_pkt_mod_bm_t pkt_mod_bm,
+				tpm_pkt_mod_t *pkt_mod,
+				tpm_rule_action_t *rule_action,
+				bool check_vlan_noop);
+int32_t tpm_proc_calc_cnm_precedence(tpm_src_port_type_t src_port, uint32_t rule_num, uint32_t *precedence);
+
+tpm_error_code_t tpm_proc_check_dst_uni_port(tpm_trg_port_type_t dest_port_bm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* _TPM_PKT_PROCL_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.c
new file mode 100755
index 0000000..733e952
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.c
@@ -0,0 +1,3581 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_pnc_logic.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.4
+*
+*
+*******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+typedef int32_t(*tpm_parse_func_t) (uint32_t, tpm_pkt_data_t *, tpm_pkt_mask_t *, tpm_pncl_tcam_data_t *);
+
+/* Local Structures */
+
+/* Structure for parsing tables */
+typedef struct {
+	uint32_t mandatory;
+	uint32_t parse_bm;
+	uint32_t field_len;
+	uint32_t shift_len;
+	tpm_parse_func_t parse_func;
+	char field_name[30];
+} tpm_parse_tbl_t;
+
+/* Local definitions */
+
+#define IF_ERROR(ret)		\
+		if (ret != TPM_OK) {\
+			TPM_OS_ERROR(TPM_PNCL_MOD, " recvd ret_code(%d)\n", ret);\
+			return(ret);\
+		}
+#define IF_ERROR_I(ret, i)	\
+		if (ret != TPM_OK) {\
+			TPM_OS_ERROR(TPM_PNCL_MOD, " recvd ret_code(%d), ind(%d)\n", ret, i);\
+			return(ret);\
+		}
+
+/* Function Declarations */
+
+int32_t tpm_pncl_mh_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			  tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_da_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			  tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_sa_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			  tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_vlan_parse(uint32_t offset, uint32_t sec_vlan_tag, tpm_pkt_data_t *pkt_data,
+			    tpm_pkt_mask_t *pkt_mask, tpm_pncl_tcam_data_t * tcam_in);
+int32_t tpm_pncl_vlan1_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			     tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_vlan2_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			     tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_etype_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			     tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_pppoe_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			     tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_l3_etype_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_l3_pppoe_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_ver_ihl_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				    tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_tot_len_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				    tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_ident_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				  tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_flag_ttl_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_flag_off_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_dscp_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				 tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_proto_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				  tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_sip_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_dip_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_l4_src_port_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+					tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv4_l4_dst_port_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+					tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_l4_src_port_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+					tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_l4_dst_port_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+					tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_l4_src_port_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_l4_dst_port_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_tcp_flags_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				 tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_ver_dscp_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				     tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_dscp_flow_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				      tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_flow_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				 tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_pllen_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				  tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_nh_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_hoplim_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_sip_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_dip_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_udp_len_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_l4_checksum_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_tcp_seq_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_tcp_ack_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_tcp_offset_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				  tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_ipv6_tcp_flags_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				      tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_tcp_win_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_tcp_urgtptr_parse(uint32_t offset, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in);
+
+int32_t tpm_pncl_pkt_data_parse(tpm_pncl_tcam_data_t *tcam_in, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask);
+
+int32_t tpm_pncl_log_offset_get(tpm_pncl_offset_t *logic_offset, uint32_t *parse_tbl_ind);
+int32_t tpm_pncl_shift_calc(tpm_pncl_offset_t *start_offset, tpm_pncl_offset_t *stop_offset,
+			    tpm_pncl_parse_bm_t l2_parse_bm, uint32_t *calc_shift);
+int32_t tpm_pncl_tcam_map(tpm_pncl_tcam_data_t *tcam_in, tpm_tcam_all_t *tcam_out);
+int32_t tpm_pncl_flowid_map(tpm_pncl_flowid_t *flowid_in, tpm_pncl_sram_updt_bm_t sram_bm_in, uint32_t *flowid_val,
+			    uint32_t *flowid_updt_mask);
+int32_t tpm_pncl_res_info_map(tpm_pncl_sram_data_t *sram_in, tpm_sram_all_t *sram_out);
+int32_t tpm_pncl_sram_map(tpm_pncl_sram_data_t *sram_in, tpm_sram_all_t *sram_out, tpm_pncl_tcam_data_t *tcam_in);
+int32_t tpm_pncl_set_ri_bit(tpm_sram_all_t *sram_out, uint32_t ri_bit, uint32_t ri_val);
+int32_t tpm_pncl_set_l4(tpm_pncl_l4_type_t l4_type, tpm_sram_all_t *sram_out);
+int32_t tpm_pncl_set_l3(tpm_pncl_l3_type_t l3_type, tpm_sram_all_t *sram_out);
+
+/* L2 Parsing Table */
+/*    MAND.           PARSE_BM                FIELD_LEN     SHIFT TO NEXT     PARSING FUNCTION     TEXT */
+static tpm_parse_tbl_t pncl_l2_parse_tbl[] = {
+	{TPM_TRUE, TPM_L2_PARSE_MH, TPM_MH_LEN, TPM_MH_LEN, &tpm_pncl_mh_parse, "MH"},
+	{TPM_TRUE, TPM_L2_PARSE_MAC_DA, TPM_DA_LEN, TPM_DA_LEN, &tpm_pncl_da_parse, "DA"},
+	{TPM_TRUE, TPM_L2_PARSE_MAC_SA, TPM_SA_LEN, TPM_SA_LEN, &tpm_pncl_sa_parse, "SA"},
+	{TPM_FALSE, TPM_PNCL_ONE_TWO_VLAN_TAG, TPM_VLAN_LEN, TPM_VLAN_LEN, &tpm_pncl_vlan1_parse, "VLAN1"},
+	{TPM_FALSE, TPM_L2_PARSE_TWO_VLAN_TAG, TPM_VLAN_LEN, TPM_VLAN_LEN, &tpm_pncl_vlan2_parse, "VLAN2"},
+	{TPM_TRUE, TPM_L2_PARSE_ETYPE, TPM_ETYPE_LEN, TPM_ETYPE_LEN, &tpm_pncl_etype_parse, "ETHER_TYPE"},
+	{TPM_FALSE, TPM_L2_PARSE_PPPOE_HDR, TPM_PPPOE_HDR_LEN, TPM_PPPOE_HDR_LEN, &tpm_pncl_pppoe_parse, "PPPOE"}
+};
+
+/* L3 Parsing Table */
+/*    MAND.           PARSE_BM                FIELD_LEN     SHIFT TO NEXT     PARSING FUNCTION     TEXT */
+static tpm_parse_tbl_t pncl_l3_parse_tbl[] = {
+	{TPM_TRUE, TPM_L2_PARSE_ETYPE, TPM_ETYPE_LEN, TPM_ETYPE_LEN, &tpm_pncl_l3_etype_parse, "ETHER_TYPE"},
+	{TPM_FALSE, TPM_L2_PARSE_PPPOE_HDR, TPM_PPPOE_HDR_LEN, TPM_PPPOE_HDR_LEN, &tpm_pncl_l3_pppoe_parse,
+		"PPPOE HDR"},
+};
+
+/* IPv4 Parsing Table */
+/*    MAND.           PARSE_BM                FIELD_LEN            SHIFT TO NEXT     PARSING FUNCTION     TEXT */
+static tpm_parse_tbl_t pncl_ipv4_parse_tbl[] = {
+	{TPM_TRUE, TPM_IPv4_PARSE_VER_OR_IHL, TPM_IPV4_VER_IHL_LEN, TPM_IPV4_VER_IHL_LEN, &tpm_pncl_ipv4_ver_ihl_parse,
+		"IPv4 Ver&IHL"},
+	{TPM_TRUE, TPM_IPv4_PARSE_DSCP, TPM_IPV4_DSCP_LEN, TPM_IPV4_DSCP_LEN, &tpm_pncl_ipv4_dscp_parse, "IPv4 DSCP"},
+	{TPM_TRUE, TPM_IPv4_PARSE_TOTLEN, TPM_IPV4_TOTLEN_LEN, TPM_IPV4_TOTLEN_LEN, &tpm_pncl_ipv4_tot_len_parse,
+		"IPv4 TotalLength"},
+	{TPM_TRUE, TPM_IPv4_PARSE_IDENT, TPM_IPV4_IDENT_LEN, TPM_IPV4_IDENT_LEN, &tpm_pncl_ipv4_ident_parse,
+		"IPv4 Idenitification"},
+	{TPM_TRUE, TPM_IPv4_PARSE_MF_OR_FRAG, TPM_IPV4_FLAG_OFF_LEN, TPM_IPV4_FLAG_OFF_LEN, &tpm_pncl_flag_off_parse,
+		"IPv4 MF Flag and Offset"},
+	{TPM_TRUE, TPM_IPv4_PARSE_TTL, TPM_IPV4_TTL_LEN, TPM_IPV4_TTL_LEN, &tpm_pncl_flag_ttl_parse, "IPv4 TTL"},
+	{TPM_TRUE, TPM_IPv4_PARSE_PROTO, TPM_IPV4_PROTO_LEN, TPM_IPV4_PROTO_LEN + 2, &tpm_pncl_ipv4_proto_parse,
+		"IPv4 PROTO"},
+	{TPM_TRUE, TPM_IPv4_PARSE_SIP, TPM_IPV4_SIP_LEN, TPM_IPV4_SIP_LEN, &tpm_pncl_ipv4_sip_parse, "IPv4 SIP"},
+	{TPM_TRUE, TPM_IPv4_PARSE_DIP, TPM_IPV4_DIP_LEN, TPM_IPV4_DIP_LEN, &tpm_pncl_ipv4_dip_parse, "IPv4 DIP"},
+	{TPM_TRUE, TPM_PARSE_L4_SRC, TPM_IPV4_L4_PORT_LEN, TPM_IPV4_L4_PORT_LEN, &tpm_pncl_ipv4_l4_src_port_parse,
+		"IPV4_L4_SRC"},
+	{TPM_TRUE, TPM_PARSE_L4_DST, TPM_IPV4_L4_PORT_LEN, TPM_IPV4_L4_PORT_LEN, &tpm_pncl_ipv4_l4_dst_port_parse,
+		"IPV4_L4_DST"}
+};
+
+/* IPv6 Parsing Table */
+/*    MAND.           PARSE_BM                FIELD_LEN     SHIFT TO NEXT
+		PARSING FUNCTION     		TEXT */
+static tpm_parse_tbl_t pncl_ipv6_parse_tbl[] = {
+	{TPM_TRUE, TPM_IPv6_PARSE_VER_OR_DSCP, TPM_IPV6_VER_DSCP_LEN, TPM_IPV6_VER_DSCP_LEN,
+		&tpm_pncl_ipv6_ver_dscp_parse,  "IPv6 Ver&DSCP"},
+	{TPM_TRUE, TPM_IPv6_PARSE_DSCP_OR_FLOW, TPM_IPV6_DSCP_FLOW_LEN, TPM_IPV6_DSCP_FLOW_LEN,
+		&tpm_pncl_ipv6_dscp_flow_parse, "IPv6 DSCP&Flow"},
+	{TPM_TRUE, TPM_IPv6_PARSE_FLOW, TPM_IPV6_FLOW_LEN, TPM_IPV6_FLOW_LEN,
+		&tpm_pncl_ipv6_flow_parse,      "IPv6 Flow"},
+	{TPM_TRUE, TPM_IPv6_PARSE_PLLEN, TPM_IPV6_PLLEN_LEN, TPM_IPV6_PLLEN_LEN,
+		&tpm_pncl_ipv6_pllen_parse,     "IPv6 Payload len"},
+	{TPM_TRUE, TPM_IPv6_PARSE_NH, TPM_IPV6_NH_LEN, TPM_IPV6_NH_LEN,
+		&tpm_pncl_ipv6_nh_parse,        "IPv6 Next header"},
+	{TPM_TRUE, TPM_IPv6_PARSE_HOPL, TPM_IPV6_HOPLIM_LEN, TPM_IPV6_HOPLIM_LEN,
+		&tpm_pncl_ipv6_hoplim_parse,    "IPv6 hop limit"},
+	{TPM_TRUE, TPM_IPv6_PARSE_SIP, TPM_IPV6_SIP_LEN, TPM_IPV6_SIP_LEN,
+		&tpm_pncl_ipv6_sip_parse,       "IPv6 SIP"},
+	{TPM_TRUE, TPM_IPv6_PARSE_DIP, TPM_IPV6_DIP_LEN, TPM_IPV6_DIP_LEN,
+		&tpm_pncl_ipv6_dip_parse,       "IPv6 DIP"},
+};
+
+/* IPv6 Ext Hdr Parsing Table */
+/*    MAND.           PARSE_BM                FIELD_LEN     SHIFT TO NEXT
+		PARSING FUNCTION     		TEXT */
+static tpm_parse_tbl_t pncl_ipv6_ext_hdr_parse_tbl[] = {
+	{TPM_TRUE, TPM_IPv6_PARSE_NH, TPM_IPV6_NH_LEN, TPM_IPV6_NH_LEN,
+		&tpm_pncl_ipv6_nh_parse,        "IPv6 Next header"},
+};
+
+static tpm_parse_tbl_t pncl_ipv6_dip_parse_tbl[] = {
+	{TPM_TRUE, TPM_IPv6_PARSE_DIP, TPM_IPV6_DIP_LEN, TPM_IPV6_DIP_LEN,
+		&tpm_pncl_ipv6_dip_parse,       "IPv6 DIP"},
+	{TPM_TRUE, TPM_PARSE_L4_SRC, TPM_L4_SPORT_LEN, TPM_L4_SPORT_LEN,
+		&tpm_pncl_l4_src_port_parse,	"L4 source port"},
+	{TPM_TRUE, TPM_PARSE_L4_DST, TPM_L4_DPORT_LEN, TPM_L4_DPORT_LEN,
+		&tpm_pncl_l4_dst_port_parse,	"L4 dest port"},
+};
+
+/* TCP Parsing Table */
+/*    MAND.           PARSE_BM                FIELD_LEN     SHIFT TO NEXT
+		PARSING FUNCTION     		TEXT */
+static tpm_parse_tbl_t pncl_tcp_parse_tbl[] = {
+	{TPM_TRUE, TPM_PARSE_L4_SRC, TPM_L4_SPORT_LEN, TPM_L4_SPORT_LEN,
+		&tpm_pncl_l4_src_port_parse,    "L4 source port"},
+	{TPM_TRUE, TPM_PARSE_L4_DST, TPM_L4_DPORT_LEN, TPM_L4_DPORT_LEN,
+		&tpm_pncl_l4_dst_port_parse,    "L4 dest port"},
+	{TPM_TRUE, TPM_PARSE_TCPSEQ_NUM, TPM_TCP_SEQ_NUM_LEN, TPM_TCP_SEQ_NUM_LEN,
+		&tpm_pncl_tcp_seq_parse,        "TCP Seq Num"},
+	{TPM_TRUE, TPM_PARSE_TCPACK_NUM, TPM_TCP_ACK_NUM_LEN, TPM_TCP_ACK_NUM_LEN,
+		&tpm_pncl_tcp_ack_parse,        "TCP Ack Num"},
+	{TPM_TRUE, TPM_PARSE_TCPOFFSET, TPM_TCP_OFFSET_LEN, TPM_TCP_OFFSET_LEN,
+		&tpm_pncl_tcp_offset_parse,     "TCP Offset"},
+	{TPM_TRUE, TPM_PARSE_TCPFLAGS, TPM_TCP_FLAGS_LEN, TPM_TCP_FLAGS_LEN,
+		&tpm_pncl_tcp_flags_parse,      "TCP Flags"},
+	{TPM_TRUE, TPM_PARSE_TCPWIN, TPM_TCP_WIN_LEN, TPM_TCP_WIN_LEN,
+		&tpm_pncl_tcp_win_parse,        "TCP Window"},
+	{TPM_TRUE, TPM_PARSE_L4_CHECKSUM, TPM_L4_CHECKSUM_LEN, TPM_L4_CHECKSUM_LEN,
+		&tpm_pncl_l4_checksum_parse,    "L4 checksum"},
+	{TPM_TRUE, TPM_PARSE_TCPURGTPTR, TPM_TCP_URGTPTR_LEN, TPM_TCP_URGTPTR_LEN,
+		&tpm_pncl_tcp_urgtptr_parse,    "TCP Urgent Ptr"},
+};
+
+/* L4 Ports Parsing Table */
+/*    MAND.           PARSE_BM                FIELD_LEN     SHIFT TO NEXT     PARSING FUNCTION     TEXT */
+static tpm_parse_tbl_t pncl_l4_ports_parse_tbl[] = {
+	{TPM_TRUE, TPM_PARSE_L4_SRC, TPM_L4_SPORT_LEN, TPM_L4_SPORT_LEN, &tpm_pncl_l4_src_port_parse, "L4 source port"},
+	{TPM_TRUE, TPM_PARSE_L4_DST, TPM_L4_DPORT_LEN, TPM_L4_DPORT_LEN, &tpm_pncl_l4_dst_port_parse, "L4 dest port"},
+};
+
+/*******************************************************************************
+* tpm_pncl_print_pncl()
+*
+* DESCRIPTION:     The function prints
+*
+* INPUTS:
+* pnc_data            -  PNC entry in logical format
+*
+* OUTPUTS:
+*
+* RETURNS:
+*
+*******************************************************************************/
+void tpm_pncl_print_pncl(tpm_pncl_pnc_full_t *pnc_data)
+{
+	tpm_pncl_pkt_key_t *l_pkt_key = &(pnc_data->pncl_tcam.pkt_key);
+
+	/* TODO - Organize printout to Table */
+	printk(KERN_INFO "TCAM Logical:\n");
+	printk("lu_id(%02d), port_ids(%02x), start_offset_base(%02d), start_offset_sub(%x)\n",
+	       pnc_data->pncl_tcam.lu_id,
+	       pnc_data->pncl_tcam.port_ids,
+	       pnc_data->pncl_tcam.start_offset.offset_base, pnc_data->pncl_tcam.start_offset.offset_sub.l2_subf);
+	TPM_OS_DEB_WAIT();
+
+	if (pnc_data->pncl_tcam.add_info_mask != 0)
+		printk("ai_data(%x),  ai_mask(%x)\n",
+		       pnc_data->pncl_tcam.add_info_data, pnc_data->pncl_tcam.add_info_mask);
+
+	printk("l2_bm(0x%x), l3_bm(0x%x), ipv4bm(0x%x), ipv6_bm(0x%x)\n",
+	       pnc_data->pncl_tcam.l2_parse_bm,
+	       pnc_data->pncl_tcam.l3_parse_bm, pnc_data->pncl_tcam.ipv4_parse_bm, pnc_data->pncl_tcam.ipv6_parse_bm);
+
+	TPM_OS_DEB_WAIT();
+
+	printk("src_port(%d), gem_port(%x)\n", l_pkt_key->src_port, l_pkt_key->l2_key.gem_port);
+	printk("L2 ethertype(%04x), pppoe_ses(%d), pppoe_proto(%x)\n",
+	       l_pkt_key->l2_key.ether_type,
+	       l_pkt_key->l2_key.pppoe_hdr.ppp_session, l_pkt_key->l2_key.pppoe_hdr.ppp_proto);
+
+	TPM_OS_DEB_WAIT();
+	printk("L3 ethertype(%04x), pppoe_ses(%d), pppoe_proto(%x)\n",
+	       l_pkt_key->l3_key.ether_type_key,
+	       l_pkt_key->l3_key.pppoe_key.ppp_session, l_pkt_key->l3_key.pppoe_key.ppp_proto);
+
+	TPM_OS_DEB_WAIT();
+	tpm_print_mac_key(&(l_pkt_key->l2_key.mac));
+
+	TPM_OS_DEB_WAIT();
+	printk("\nVLAN 1:\n");
+	tpm_print_vlan_key(&(l_pkt_key->l2_key.vlan1));
+	printk("\nVLAN 2:\n");
+	tpm_print_vlan_key(&(l_pkt_key->l2_key.vlan2));
+	TPM_OS_DEB_WAIT();
+
+	tpm_print_ipv4_key(&(l_pkt_key->ipv4_key), &(l_pkt_key->ipv4_add_key));
+	TPM_OS_DEB_WAIT();
+
+	printk("ipv6 L4 Src Port(%d), pv6 L4 Dst Port(%d)\n",
+	       pnc_data->pncl_tcam.pkt_key.l4_ports_key.l4_src_port, pnc_data->pncl_tcam.pkt_key.l4_ports_key.l4_dst_port);
+
+	printk("\nSRAM\n");
+	printk("next_lu_id(%d), next_lu_off_reg(%d), shift_updt_reg(%d)\n",
+	       pnc_data->pncl_sram.next_lu_id, pnc_data->pncl_sram.next_lu_off_reg, pnc_data->pncl_sram.shift_updt_reg);
+	printk("next_off_base(%d), lx_subf(%X)\n",
+	       pnc_data->pncl_sram.next_offset.offset_base, pnc_data->pncl_sram.next_offset.offset_sub.l2_subf);
+	TPM_OS_DEB_WAIT();
+	printk("sram_updt_bm(0x%x), l3_type(%d), l4_type(%d), mh_reg(%d,%d), pkt_col(%d)\n",
+	       pnc_data->pncl_sram.sram_updt_bm,
+	       pnc_data->pncl_sram.l3_type,
+	       pnc_data->pncl_sram.l4_type,
+	       pnc_data->pncl_sram.mh_reg.mh_set, pnc_data->pncl_sram.mh_reg.mh_reg, pnc_data->pncl_sram.pkt_col);
+
+	TPM_OS_DEB_WAIT();
+	printk("pnc_queue(%d), flow_id_gem(%d), flow_id_mod(%d), flow_id_txp(%d), \n",
+	       pnc_data->pncl_sram.pnc_queue,
+	       pnc_data->pncl_sram.flow_id_sub.gem_port,
+	       pnc_data->pncl_sram.flow_id_sub.mod_cmd, pnc_data->pncl_sram.flow_id_sub.pnc_target);
+
+	TPM_OS_DEB_WAIT();
+	if (pnc_data->pncl_sram.add_info_mask != 0)
+		printk("ai_data(%x),  ai_mask(%x)\n",
+		       pnc_data->pncl_sram.add_info_data, pnc_data->pncl_sram.add_info_mask);
+}
+
+/*******************************************************************************
+* tpm_pncl_mh_parse()
+*
+* DESCRIPTION:     The function creates the TCAM Marvell Header parsing format,
+*                  according to the information that must be parsed (Amber MH, or GPON Header)
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function (should always be zero)
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physicalTCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_mh_parse(uint32_t offset,
+			  tpm_pkt_data_t *pkt_data,
+			  tpm_pkt_mask_t *pkt_mask,
+			  tpm_pncl_tcam_data_t *tcam_in)
+{
+	tpm_db_int_conn_t int_con;
+	uint32_t switch_port;
+	int32_t ret_code;
+	uint16_t mh = 0;
+	tpm_db_pon_type_t pon_type;
+
+	/* Parse MH, depending on field parse request */
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* US, specific UNI Port */
+	if (FROM_SPEC_UNI(tcam_in->pkt_key.src_port)) {
+		/* Get Amber Switch Port */
+		ret_code = tpm_db_intport_int_con_get(tcam_in->pkt_key.src_port, &int_con, &switch_port);
+		IF_ERROR(ret_code);
+
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "MH set by UNI_Port_%d -> switch_port(%d)\n",
+			     (tcam_in->pkt_key.src_port - TPM_SRC_PORT_UNI_0), switch_port);
+
+		/* Translate switch_port to Marvell Header */
+		if (int_con == TPM_INTCON_SWITCH)
+			mh = (switch_port << MH_UNI_PORT_OFFSET);
+		else {		/* UNI Port, not connected to Switch */
+			mh = 0;
+		}
+
+		/* Update TCAM Data and Mask */
+		*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(mh);
+		*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(MH_UNI_PORT_MASK);
+
+	}
+	/* DS, set MH according to Gemport */
+	else if (tcam_in->l2_parse_bm & TPM_L2_PARSE_GEMPORT) {	/* Specific GPON gemport */
+		/* Double-check WAN technology */
+		ret_code = tpm_db_pon_type_get(&pon_type);
+		IF_ERROR(ret_code);
+		if (pon_type != TPM_GPON) {
+			TPM_OS_ERROR(TPM_PNCL_MOD, " MH set requested for non-GPON WAN technology \n");
+			return(TPM_FAIL);
+		}
+		mh = ((tcam_in->pkt_key.l2_key.gem_port) << MH_GEM_PORT_OFFSET);
+
+		/* Update TCAM Data and Mask */
+		*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(mh);
+		*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(MH_GEM_PORT_MASK);
+
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "MH from GemPort\n");
+	} else {
+		if (tcam_in->pkt_key.src_port == TPM_SRC_PORT_WAN) {
+			/* DS, from WAN, no MH need to be parsed */
+			mh = 0;
+			/* Update TCAM Data and Mask */
+			*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(mh);
+			*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(MH_UNI_PORT_MASK);
+		} else {
+			TPM_OS_ERROR(TPM_PNCL_MOD, "Unrecognized MH parsing request received\n");
+			return(TPM_FAIL);
+		}
+	}
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "MH(%02x%02x) MH_mask(%02x%02x) \n",
+		     pkt_data->pkt_byte[offset],
+		     pkt_data->pkt_byte[offset + 1], pkt_mask->pkt_byte[offset], pkt_mask->pkt_byte[offset + 1]);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_da_parse()
+*
+* DESCRIPTION:     The function creates the TCAM MAC DA parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_da_parse(uint32_t offset,
+			  tpm_pkt_data_t *pkt_data,
+			  tpm_pkt_mask_t *pkt_mask,
+			  tpm_pncl_tcam_data_t *tcam_in)
+{
+	uint32_t i;
+	for (i = 0; i < TPM_DA_LEN; i++) {
+		pkt_data->pkt_byte[offset] = tcam_in->pkt_key.l2_key.mac.mac_da[i];
+		pkt_mask->pkt_byte[offset] = tcam_in->pkt_key.l2_key.mac.mac_da_mask[i];
+		offset++;
+	}
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_sa_parse()
+*
+* DESCRIPTION:     The function creates the TCAM MAC SA parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_sa_parse(uint32_t offset,
+			  tpm_pkt_data_t *pkt_data,
+			  tpm_pkt_mask_t *pkt_mask,
+			  tpm_pncl_tcam_data_t *tcam_in)
+{
+	uint32_t i;
+	for (i = 0; i < TPM_DA_LEN; i++) {
+		pkt_data->pkt_byte[offset] = tcam_in->pkt_key.l2_key.mac.mac_sa[i];
+		pkt_mask->pkt_byte[offset] = tcam_in->pkt_key.l2_key.mac.mac_sa_mask[i];
+		offset++;
+	}
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_vlan_parse()
+*
+* DESCRIPTION:     The function creates a TCAM Vlan Tag parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+* sec_vlan_tag     - States if this is second Vlan Tag
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS: Used by tpm_pncl_vlan1_parse, tpm_pncl_vlan2_parse
+*
+*******************************************************************************/
+int32_t tpm_pncl_vlan_parse(uint32_t offset,
+			    uint32_t sec_vlan_tag,
+			    tpm_pkt_data_t *pkt_data,
+			    tpm_pkt_mask_t *pkt_mask,
+			    tpm_pncl_tcam_data_t *tcam_in)
+{
+	tpm_vlan_key_t *vlan_key;
+	uint16_t temp_data;
+	uint16_t temp_mask;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d), sec_vlan_tag(%d)\n", offset, sec_vlan_tag);
+
+	if (sec_vlan_tag == 0)
+		vlan_key = &(tcam_in->pkt_key.l2_key.vlan1);
+	else
+		vlan_key = &(tcam_in->pkt_key.l2_key.vlan2);
+
+	/* Vlan Ethertype */
+#if 0
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(vlan_key->tpid);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+#endif
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(((vlan_key->tpid) & (vlan_key->tpid_mask)));
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons((0xFFFF & (vlan_key->tpid_mask)));
+
+	offset += 2;
+
+	/* VID, pbits, cfi */
+	temp_data = (((vlan_key->cfi) & (vlan_key->cfi_mask)) << TPM_VLAN_CFI_OFFSET) +
+		    (((vlan_key->pbit) & (vlan_key->pbit_mask)) << TPM_VLAN_PBIT_OFFSET) +
+		    (((vlan_key->vid) & (vlan_key->vid_mask)) << TPM_VLAN_VID_OFFSET);
+
+	temp_mask = ((0x01 & vlan_key->cfi_mask) << TPM_VLAN_CFI_OFFSET) +
+		    ((0x07 & vlan_key->pbit_mask) << TPM_VLAN_PBIT_OFFSET) +
+		    ((0x0FFF & vlan_key->vid_mask) << TPM_VLAN_VID_OFFSET);
+
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(temp_data);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(temp_mask);
+
+	return(TPM_OK);
+
+}
+
+/*******************************************************************************
+* tpm_pncl_vlan1_parse()
+*
+* DESCRIPTION:     The function creates a TCAM first Vlan Tag parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_vlan1_parse(uint32_t offset,
+			     tpm_pkt_data_t *pkt_data,
+			     tpm_pkt_mask_t *pkt_mask,
+			     tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+	tpm_pncl_vlan_parse(offset, 0, pkt_data, pkt_mask, tcam_in);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_vlan2_parse()
+*
+* DESCRIPTION:     The function creates a TCAM second Vlan Tag parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_vlan2_parse(uint32_t offset,
+			     tpm_pkt_data_t *pkt_data,
+			     tpm_pkt_mask_t *pkt_mask,
+			     tpm_pncl_tcam_data_t *tcam_in)
+{
+	tpm_pncl_vlan_parse(offset, 1, pkt_data, pkt_mask, tcam_in);
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_etype_parse()
+*
+* DESCRIPTION:     The function creates a TCAM Ethertype parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_etype_parse(uint32_t offset,
+			     tpm_pkt_data_t *pkt_data,
+			     tpm_pkt_mask_t *pkt_mask,
+			     tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.l2_key.ether_type);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_pppoe_parse()
+*
+* DESCRIPTION:     The function creates a TCAM PPPoE header parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_pppoe_parse(uint32_t offset,
+			     tpm_pkt_data_t *pkt_data,
+			     tpm_pkt_mask_t *pkt_mask,
+			     tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	if (tcam_in->l2_parse_bm & TPM_L2_PARSE_PPPOE_SES) {
+		/* Update TCAM Data and Mask */
+		*(uint16_t *) (&(pkt_data->pkt_byte[offset + 2])) =
+		htons(tcam_in->pkt_key.l2_key.pppoe_hdr.ppp_session);
+		*(uint16_t *) (&(pkt_mask->pkt_byte[offset + 2])) = htons(0xFFFF);
+	}
+	if (tcam_in->l2_parse_bm & TPM_L2_PARSE_PPP_PROT) {
+		/* Update TCAM Data and Mask */
+		*(uint16_t *) (&(pkt_data->pkt_byte[offset + 6])) = htons(tcam_in->pkt_key.l2_key.pppoe_hdr.ppp_proto);
+		*(uint16_t *) (&(pkt_mask->pkt_byte[offset + 6])) = htons(0xFFFF);
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_l3_etype_parse()
+*
+* DESCRIPTION:     The function creates a TCAM L3 Ethertype parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_l3_etype_parse(uint32_t offset,
+				tpm_pkt_data_t *pkt_data,
+				tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.l3_key.ether_type_key);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_l3_pppoe_parse()
+*
+* DESCRIPTION:     The function creates a TCAM PPPoE header parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_l3_pppoe_parse(uint32_t offset,
+				tpm_pkt_data_t *pkt_data,
+				tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	if (tcam_in->l3_parse_bm & TPM_L2_PARSE_PPPOE_SES) {
+		/* Update TCAM Data and Mask */
+		*(uint16_t *) (&(pkt_data->pkt_byte[offset + 2])) =
+		htons(tcam_in->pkt_key.l3_key.pppoe_key.ppp_session);
+		*(uint16_t *) (&(pkt_mask->pkt_byte[offset + 2])) = htons(0xFFFF);
+	}
+	if (tcam_in->l3_parse_bm & TPM_L2_PARSE_PPP_PROT) {
+		/* Update TCAM Data and Mask */
+		*(uint16_t *) (&(pkt_data->pkt_byte[offset + 6])) = htons(tcam_in->pkt_key.l3_key.pppoe_key.ppp_proto);
+		*(uint16_t *) (&(pkt_mask->pkt_byte[offset + 6])) = htons(0xFFFF);
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_ver_ihl_parse()
+*
+* DESCRIPTION:     The function creates a TCAM ipv4 version and IHL parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_ver_ihl_parse(uint32_t offset,
+				    tpm_pkt_data_t *pkt_data,
+				    tpm_pkt_mask_t *pkt_mask,
+				    tpm_pncl_tcam_data_t *tcam_in)
+{
+	uint16_t temp_data = 0;
+	uint16_t temp_mask = 0;
+	tpm_ipv4_add_key_t *ipv4_add_key;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	ipv4_add_key = &(tcam_in->pkt_key.ipv4_add_key);
+
+	/* Add IHL if requested */
+	temp_data |=
+	(ipv4_add_key->ipv4_ihl_mask) * ((ipv4_add_key->ipv4_ihl & TPM_IPV4_IHL_MASK) << TPM_IPV4_IHL_OFFSET);
+	temp_mask |= (ipv4_add_key->ipv4_ihl_mask) * (TPM_IPV4_IHL_MASK << TPM_IPV4_IHL_OFFSET);
+
+	/* Add IP Version if requested */
+	temp_data |=
+	(ipv4_add_key->ipv4_ver_mask) * ((ipv4_add_key->ipv4_ver & TPM_IPV4_VER_MASK) << TPM_IPV4_VER_OFFSET);
+	temp_mask |= (ipv4_add_key->ipv4_ver_mask) * (TPM_IPV4_VER_MASK << TPM_IPV4_VER_OFFSET);
+
+	/* Update TCAM Data and Mask */
+	*(uint8_t *) (&(pkt_data->pkt_byte[offset])) = temp_data;
+	*(uint8_t *) (&(pkt_mask->pkt_byte[offset])) = temp_mask;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_tot_len_parse()
+*
+* DESCRIPTION:     The function creates a TCAM ipv4 version and IHL parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_tot_len_parse(uint32_t offset,
+				    tpm_pkt_data_t *pkt_data,
+				    tpm_pkt_mask_t *pkt_mask,
+				    tpm_pncl_tcam_data_t *tcam_in)
+{
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv4_add_key.ipv4_totlen);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv4_add_key.ipv4_totlen_mask);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_flag_ttl_parse()
+*
+* DESCRIPTION:     The function creates a TCAM ipv4 version and IHL parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_flag_ttl_parse(uint32_t offset,
+				tpm_pkt_data_t *pkt_data,
+				tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in)
+{
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	*(uint8_t *) (&(pkt_data->pkt_byte[offset])) = tcam_in->pkt_key.ipv4_add_key.ipv4_ttl;
+	*(uint8_t *) (&(pkt_mask->pkt_byte[offset])) = TPM_IPV4_TTL_MASK;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_ident_parse()
+*
+* DESCRIPTION:     The function creates a TCAM ipv4 version and IHL parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_ident_parse(uint32_t offset,
+				  tpm_pkt_data_t *pkt_data,
+				  tpm_pkt_mask_t *pkt_mask,
+				  tpm_pncl_tcam_data_t *tcam_in)
+{
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv4_add_key.ipv4_ident);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = TPM_IPV4_IDENT_MASK;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_flag_off_parse()
+*
+* DESCRIPTION:     The function creates a TCAM ipv4 version and IHL parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_flag_off_parse(uint32_t offset,
+				tpm_pkt_data_t *pkt_data,
+				tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in)
+{
+	uint16_t temp_data = 0;
+	uint16_t temp_mask = 0;
+	tpm_ipv4_add_key_t *ipv4_add_key;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	ipv4_add_key = &(tcam_in->pkt_key.ipv4_add_key);
+
+	/* Add Fragment Offset if requested */
+	temp_data |= ((ipv4_add_key->ipv4_frag_offset_mask) *
+		      ((ipv4_add_key->ipv4_frag_offset) & TPM_IPV4_FRAG_MASK)) << TPM_IPV4_FRAG_OFFSET;
+
+	temp_mask |= ((ipv4_add_key->ipv4_frag_offset_mask) * TPM_IPV4_FRAG_MASK) << TPM_IPV4_FRAG_OFFSET;
+
+	/* Add MH Flag if requested */
+	temp_data |= ((ipv4_add_key->ipv4_flags_mask) *
+		      ((ipv4_add_key->ipv4_flags) & TPM_IPV4_MF_MASK)) << TPM_IPV4_MF_OFFSET;
+
+	temp_mask |= ((ipv4_add_key->ipv4_flags_mask) * TPM_IPV4_MF_MASK) << TPM_IPV4_MF_OFFSET;
+
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(temp_data);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(temp_mask);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_dscp_parse()
+*
+* DESCRIPTION:     The function creates a TCAM ipv4 DSCP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_dscp_parse(uint32_t offset,
+				 tpm_pkt_data_t *pkt_data,
+				 tpm_pkt_mask_t *pkt_mask,
+				 tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	*(uint8_t *) (&(pkt_data->pkt_byte[offset])) = ((tcam_in->pkt_key.ipv4_key.ipv4_dscp) & 0x3F) << 2;
+	*(uint8_t *) (&(pkt_mask->pkt_byte[offset])) = ((tcam_in->pkt_key.ipv4_key.ipv4_dscp_mask) & 0x3F) << 2;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_proto_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv4 protocol parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_proto_parse(uint32_t offset,
+				  tpm_pkt_data_t *pkt_data,
+				  tpm_pkt_mask_t *pkt_mask,
+				  tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	*(uint8_t *) (&(pkt_data->pkt_byte[offset])) = (tcam_in->pkt_key.ipv4_key.ipv4_proto);
+	*(uint8_t *) (&(pkt_mask->pkt_byte[offset])) = (0xFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_sip_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv4 source IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_sip_parse(uint32_t offset,
+				tpm_pkt_data_t *pkt_data,
+				tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	memcpy(&(pkt_data->pkt_byte[offset]), tcam_in->pkt_key.ipv4_key.ipv4_src_ip_add, 4);
+	memcpy(&(pkt_mask->pkt_byte[offset]), tcam_in->pkt_key.ipv4_key.ipv4_src_ip_add_mask, 4);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_dip_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv4 destination IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_dip_parse(uint32_t offset,
+				tpm_pkt_data_t *pkt_data,
+				tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	memcpy(&(pkt_data->pkt_byte[offset]), tcam_in->pkt_key.ipv4_key.ipv4_dst_ip_add, 4);
+	memcpy(&(pkt_mask->pkt_byte[offset]), tcam_in->pkt_key.ipv4_key.ipv4_dst_ip_add_mask, 4);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_l4_src_port_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv4 destination IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_l4_src_port_parse(uint32_t offset,
+					tpm_pkt_data_t *pkt_data,
+					tpm_pkt_mask_t *pkt_mask,
+					tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv4_key.l4_src_port);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv4_l4_dst_port_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv4 destination IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv4_l4_dst_port_parse(uint32_t offset,
+					tpm_pkt_data_t *pkt_data,
+					tpm_pkt_mask_t *pkt_mask,
+					tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv4_key.l4_dst_port);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_l4_src_port_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 destination IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_l4_src_port_parse(uint32_t offset,
+					tpm_pkt_data_t *pkt_data,
+					tpm_pkt_mask_t *pkt_mask,
+					tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv6_key.l4_src_port);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_l4_dst_port_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 destination IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_l4_dst_port_parse(uint32_t offset,
+					tpm_pkt_data_t *pkt_data,
+					tpm_pkt_mask_t *pkt_mask,
+					tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv6_key.l4_dst_port);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_l4_src_port_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 destination IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_l4_src_port_parse(uint32_t offset,
+				   tpm_pkt_data_t *pkt_data,
+				   tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.l4_ports_key.l4_src_port);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_l4_dst_port_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 destination IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_l4_dst_port_parse(uint32_t offset,
+				   tpm_pkt_data_t *pkt_data,
+				   tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.l4_ports_key.l4_dst_port);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(0xFFFF);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_tcp_flags_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv4 destination IP parsing format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_tcp_flags_parse(uint32_t offset,
+				 tpm_pkt_data_t *pkt_data,
+				 tpm_pkt_mask_t *pkt_mask,
+				 tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	pkt_data->pkt_byte[offset] = tcam_in->pkt_key.tcp_key.tcp_flags;
+	pkt_mask->pkt_byte[offset] = tcam_in->pkt_key.tcp_key.tcp_flags_mask;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_ver_dscp_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 Version and DSCP parse format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_ver_dscp_parse(uint32_t offset,
+				     tpm_pkt_data_t *pkt_data,
+				     tpm_pkt_mask_t *pkt_mask,
+				     tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "ipv6 key, dscp: %d, mask: %d\n",
+		     tcam_in->pkt_key.ipv6_gen_key.ipv6_dscp, tcam_in->pkt_key.ipv6_gen_key.ipv6_dscp_mask);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care version */
+	pkt_data->pkt_byte[offset] |= (tcam_in->pkt_key.ipv6_gen_key.ipv6_dscp & 0x3c) >> 2;
+	pkt_mask->pkt_byte[offset] |= (tcam_in->pkt_key.ipv6_gen_key.ipv6_dscp_mask & 0x3c) >> 2;
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_dscp_flow_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 DSCP and FLOW parse format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_dscp_flow_parse(uint32_t offset,
+				      tpm_pkt_data_t *pkt_data,
+				      tpm_pkt_mask_t *pkt_mask,
+				      tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "ipv6 key, dscp: %d, mask: %d\n",
+		     tcam_in->pkt_key.ipv6_gen_key.ipv6_dscp, tcam_in->pkt_key.ipv6_gen_key.ipv6_dscp_mask);
+	/* Update TCAM Data and Mask */
+	/* We don't care flow */
+	pkt_data->pkt_byte[offset] |= (tcam_in->pkt_key.ipv6_gen_key.ipv6_dscp & 0x03) << 6;
+	pkt_mask->pkt_byte[offset] |= (tcam_in->pkt_key.ipv6_gen_key.ipv6_dscp_mask & 0x03) << 6;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_flow_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 FLOW parse format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_flow_parse(uint32_t offset,
+				 tpm_pkt_data_t *pkt_data,
+				 tpm_pkt_mask_t *pkt_mask,
+				 tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care flow */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_IPV6_FLOW_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_IPV6_FLOW_LEN);
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_pllen_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 Payload len parse format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_pllen_parse(uint32_t offset,
+				  tpm_pkt_data_t *pkt_data,
+				  tpm_pkt_mask_t *pkt_mask,
+				  tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	*(uint16_t *) (&(pkt_data->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv6_add_key.ipv6_totlen);
+	*(uint16_t *) (&(pkt_mask->pkt_byte[offset])) = htons(tcam_in->pkt_key.ipv6_add_key.ipv6_totlen_mask);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_nh_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 Next Header parse format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_nh_parse(uint32_t offset,
+			       tpm_pkt_data_t *pkt_data,
+			       tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	pkt_data->pkt_byte[offset] = tcam_in->pkt_key.ipv6_key.ipv6_next_header;
+	pkt_mask->pkt_byte[offset] = 0xFF;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_hoplim_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 Hop Limit parse format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_hoplim_parse(uint32_t offset,
+				   tpm_pkt_data_t *pkt_data,
+				   tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+
+	/*memset(&pkt_data->pkt_byte[offset], 0x0, TPM_IPV6_HOPLIM_LEN);*/
+	/*memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_IPV6_HOPLIM_LEN);*/
+	pkt_data->pkt_byte[offset] = tcam_in->pkt_key.ipv6_gen_key.hop_limit;
+	pkt_mask->pkt_byte[offset] = 0xff;
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_ipv6_sip_parse()
+*
+* DESCRIPTION:     The function creates a TCAM IPv6 SIP parse format.
+*
+* INPUTS:
+* offset           - Offset in PNC TCAM when starting the function
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_ipv6_sip_parse(uint32_t offset,
+				tpm_pkt_data_t *pkt_data,
+				tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	memcpy(&(pkt_data->pkt_byte[offset]), tcam_in->pkt_key.ipv6_gen_key.ipv6_src_ip_add, 16);
+	memcpy(&(pkt_mask->pkt_byte[offset]), tcam_in->pkt_key.ipv6_gen_key.ipv6_src_ip_add_mask, 16);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_ipv6_dip_parse(uint32_t offset,
+				tpm_pkt_data_t *pkt_data,
+				tpm_pkt_mask_t *pkt_mask,
+				tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	memcpy(&(pkt_data->pkt_byte[offset]), tcam_in->pkt_key.ipv6_dip_key.ipv6_ip_add, 16);
+	memcpy(&(pkt_mask->pkt_byte[offset]), tcam_in->pkt_key.ipv6_dip_key.ipv6_ip_add_mask, 16);
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_udp_len_parse(uint32_t offset,
+			       tpm_pkt_data_t *pkt_data,
+			       tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_UDP_LEN_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_UDP_LEN_LEN);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_l4_checksum_parse(uint32_t offset,
+				   tpm_pkt_data_t *pkt_data,
+				   tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_L4_CHECKSUM_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_L4_CHECKSUM_LEN);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_tcp_seq_parse(uint32_t offset,
+			       tpm_pkt_data_t *pkt_data,
+			       tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_TCP_SEQ_NUM_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_TCP_SEQ_NUM_LEN);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_tcp_ack_parse(uint32_t offset,
+			       tpm_pkt_data_t *pkt_data,
+			       tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_TCP_ACK_NUM_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_TCP_ACK_NUM_LEN);
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_tcp_offset_parse(uint32_t offset,
+				  tpm_pkt_data_t *pkt_data,
+				  tpm_pkt_mask_t *pkt_mask,
+				  tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_TCP_OFFSET_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_TCP_OFFSET_LEN);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_ipv6_tcp_flags_parse(uint32_t offset,
+				      tpm_pkt_data_t *pkt_data,
+				      tpm_pkt_mask_t *pkt_mask,
+				      tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_TCP_FLAGS_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_TCP_FLAGS_LEN);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_tcp_win_parse(uint32_t offset,
+			       tpm_pkt_data_t *pkt_data,
+			       tpm_pkt_mask_t *pkt_mask,
+			       tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_TCP_WIN_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_TCP_WIN_LEN);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_tcp_urgtptr_parse(uint32_t offset,
+				   tpm_pkt_data_t *pkt_data,
+				   tpm_pkt_mask_t *pkt_mask,
+				   tpm_pncl_tcam_data_t *tcam_in)
+{
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " offset_in(%d)\n", offset);
+
+	/* Update TCAM Data and Mask */
+	/* We don't care */
+	memset(&pkt_data->pkt_byte[offset], 0x0, TPM_TCP_URGTPTR_LEN);
+	memset(&pkt_mask->pkt_byte[offset], 0x0, TPM_TCP_URGTPTR_LEN);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_get_parse_tbl(tpm_pncl_offset_t *logic_offset,
+			       tpm_parse_tbl_t **tbl, uint32_t *tbl_size)
+{
+	if (logic_offset->offset_base == TPM_PNCL_ZERO_OFFSET) {
+		*tbl = pncl_l2_parse_tbl;
+		*tbl_size = sizeof(pncl_l2_parse_tbl) / sizeof(tpm_parse_tbl_t);
+	} else if (logic_offset->offset_base == TPM_PNCL_L3_OFFSET) {
+		*tbl = pncl_l3_parse_tbl;
+		*tbl_size = sizeof(pncl_l3_parse_tbl) / sizeof(tpm_parse_tbl_t);
+	} else if (logic_offset->offset_base == TPM_PNCL_IPV4_OFFSET) {
+		*tbl = pncl_ipv4_parse_tbl;
+		*tbl_size = sizeof(pncl_ipv4_parse_tbl) / sizeof(tpm_parse_tbl_t);
+	} else if (logic_offset->offset_base == TPM_PNCL_IPV6_OFFSET) {
+		*tbl = pncl_ipv6_parse_tbl;
+		*tbl_size = sizeof(pncl_ipv6_parse_tbl) / sizeof(tpm_parse_tbl_t);
+	} else if (logic_offset->offset_base == TPM_PNCL_IPV6_DIP_OFFSET) {
+		*tbl = pncl_ipv6_dip_parse_tbl;
+		*tbl_size = sizeof(pncl_ipv6_dip_parse_tbl) / sizeof(tpm_parse_tbl_t);
+	} else if (logic_offset->offset_base == TPM_PNCL_IPV6_EXT_OFFSET) {
+		*tbl = pncl_ipv6_ext_hdr_parse_tbl;
+		*tbl_size = sizeof(pncl_ipv6_ext_hdr_parse_tbl) / sizeof(tpm_parse_tbl_t);
+	} else if (logic_offset->offset_base == TPM_PNCL_TCP_OFFSET) {
+		*tbl = pncl_tcp_parse_tbl;
+		*tbl_size = sizeof(pncl_tcp_parse_tbl) / sizeof(tpm_parse_tbl_t);
+	} else if (logic_offset->offset_base == TPM_PNCL_L4_OFFSET) {
+		*tbl = pncl_l4_ports_parse_tbl;
+		*tbl_size = sizeof(pncl_l4_ports_parse_tbl) / sizeof(tpm_parse_tbl_t);
+	} else {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "Unsupported offset_base %d \n", logic_offset->offset_base);
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_pncl_log_offset_get()
+*
+* DESCRIPTION:     This function takes a TCAM logical Offset field and logical Offset sub-field,
+*                  (See tpm_pncl_offset_t) and returns the matching entry in the parsing function table
+*                  pncl_l2_parse_tbl.
+* INPUTS:
+* logic_offset     - Pointer to offset bas & offset sub-field
+*
+* OUTPUTS:
+* parse_tbl_ind   - pointer to physical TCAM packet data (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_log_offset_get(tpm_pncl_offset_t *logic_offset, uint32_t *parse_tbl_ind)
+{
+	uint32_t i;
+	int32_t ret_code;
+	tpm_parse_tbl_t *tbl;
+	uint32_t tbl_size;
+
+	/* Reset output */
+	*parse_tbl_ind = 0;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "log_offset_base(%d) , log_offset_sub(%x)\n",
+		     logic_offset->offset_base, logic_offset->offset_sub.subf);
+
+	ret_code = tpm_pncl_get_parse_tbl(logic_offset, &tbl, &tbl_size);
+	IF_ERROR(ret_code);
+
+	for (i = 0; i < tbl_size; i++) {
+		if (tbl[i].parse_bm & logic_offset->offset_sub.subf) {
+			*parse_tbl_ind = i;
+			break;
+		}
+	}
+
+	if (i == tbl_size) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "No start offset sub-field found \n");
+		return(TPM_FAIL);
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_pkt_data_parse()
+*
+* DESCRIPTION: Function translates Logical TCAM structure to physical TCAM packet data and mask
+*
+* INPUTS:
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* pkt_data         - pointer to physical TCAM packet data (24 bytes)
+* pkt_mask         - pointer to physical TCAM packet mask (24 bytes)
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_pkt_data_parse(tpm_pncl_tcam_data_t *tcam_in, tpm_pkt_data_t *pkt_data, tpm_pkt_mask_t *pkt_mask)
+{
+	int32_t ret_code;
+	int32_t white_space;
+	uint32_t start_ind, i;
+	uint32_t tcam_offset = 0, field_len, shift_len, size;
+	tpm_parse_tbl_t *parse_table;
+	tpm_pncl_parse_bm_t parse_bm;
+
+	tpm_pkt_data_t l_pkt_data;
+	tpm_pkt_mask_t l_pkt_mask;
+
+	memset(&l_pkt_data, 0, sizeof(tpm_pkt_data_t));
+	memset(&l_pkt_mask, 0, sizeof(tpm_pkt_mask_t));
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "\n");
+
+	/* Loop over L2 fields, starting from the start_offset sub_field */
+	/* 1 - Find start Offset */
+	ret_code = tpm_pncl_log_offset_get(&(tcam_in->start_offset), &start_ind);
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "start_offset_bm(%x), start_index(%d) \n",
+		     tcam_in->start_offset.offset_sub.subf, start_ind);
+	IF_ERROR(ret_code);
+
+	ret_code = tpm_pncl_get_parse_tbl(&tcam_in->start_offset, &parse_table, &size);
+	IF_ERROR(ret_code);
+
+	if (tcam_in->start_offset.offset_base == TPM_PNCL_ZERO_OFFSET) {
+		parse_bm = tcam_in->l2_parse_bm;
+	} else if (tcam_in->start_offset.offset_base == TPM_PNCL_L3_OFFSET) {
+		parse_bm = tcam_in->l3_parse_bm;
+	} else if (tcam_in->start_offset.offset_base == TPM_PNCL_IPV4_OFFSET) {
+		parse_bm = tcam_in->ipv4_parse_bm;
+	} else if ((tcam_in->start_offset.offset_base == TPM_PNCL_IPV6_OFFSET)
+		   || (tcam_in->start_offset.offset_base == TPM_PNCL_IPV6_EXT_OFFSET)
+		   || (tcam_in->start_offset.offset_base == TPM_PNCL_IPV6_DIP_OFFSET)
+		  ) {
+		parse_bm = tcam_in->ipv6_parse_bm;
+	} else if (tcam_in->start_offset.offset_base == TPM_PNCL_TCP_OFFSET) {
+		parse_bm = tcam_in->tcp_parse_bm;
+	} else if (tcam_in->start_offset.offset_base == TPM_PNCL_L4_OFFSET) {
+		parse_bm = tcam_in->l4_parse_bm;
+	}
+
+	else {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "Invalid base offset %d\n", tcam_in->start_offset.offset_base);
+		return(TPM_FAIL);
+	}
+
+	/* 2 - Perform Parsing Loop */
+	for (i = start_ind; i < size; i++) {
+		field_len = parse_table[i].field_len;
+		shift_len = parse_table[i].shift_len;
+
+		/* 1 - Field must be parsed */
+		if (parse_table[i].parse_bm & parse_bm) {
+			/* Cannot parse pass TCAM length */
+			if ((tcam_offset + field_len) > TPM_TCAM_PKT_WIDTH) {
+				TPM_OS_ERROR(TPM_PNCL_MOD, "TCAM Width passed \n");
+				return(TPM_FAIL);
+			}
+			/* Parse the field, by func */
+			(*(parse_table[i].parse_func)) (tcam_offset, &l_pkt_data, &l_pkt_mask, tcam_in);
+			tcam_offset += field_len;
+
+			/* Must skip untill next field, "skip" means to write masked bytes to TCAM packet data and TCAM mask */
+			white_space = shift_len - field_len;
+			/* TODO : Check shift_len - field_len > 0 */
+
+		} else if (parse_table[i].mandatory)	/* 2 - Must skip entire current field untill next field */
+			white_space = shift_len - 0;
+		else	/* 3 - Field doesn't exist in packet, no parsing or skipping */
+			white_space = 0;
+
+		/* 4 - Perform generic skipping for all three cases above (no skipping for case 3) */
+		if ((tcam_offset + white_space) > TPM_TCAM_PKT_WIDTH)
+			white_space = TPM_TCAM_PKT_WIDTH - tcam_offset;
+
+		memset(&(l_pkt_data.pkt_byte[tcam_offset]), 0, white_space);
+		memset(&(l_pkt_mask.pkt_byte[tcam_offset]), 0, white_space);
+		tcam_offset += white_space;
+	}
+
+	/* Set TCAM Data & Mask */
+	memcpy(pkt_data, &l_pkt_data, TPM_TCAM_PKT_WIDTH);
+	memcpy(pkt_mask, &l_pkt_mask, TPM_TCAM_PKT_WIDTH);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_shift_calc()
+*
+* DESCRIPTION: Function receives a logical start_offset, stop_offset and parsing bitmap,
+*              and calculates the shift_length from start_offset up untill stop_offset
+*              The parse bitmap is important, because it indicates which optional fields exist,
+*              e.g. Vlan Tags, PPPoE etc.
+* INPUTS:
+* start_offset     - Start offset structure
+* stop_offset      - Stop offset structure
+* l2_parse_bm      - Parse bitmap field.
+*
+* OUTPUTS:
+* calc_shift       - Calculated Shift in bytes
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_shift_calc(tpm_pncl_offset_t *start_offset,
+			    tpm_pncl_offset_t *stop_offset,
+			    tpm_pncl_parse_bm_t parse_bm,
+			    uint32_t *calc_shift)
+{
+	uint32_t start_ind, stop_ind, t_calc_shift = 0;
+	uint32_t i;
+	uint32_t ret_code, size;
+	tpm_parse_tbl_t *parse_table;
+	tpm_pncl_parse_bm_t stop_offset_bm;
+
+	if (start_offset->offset_base != stop_offset->offset_base) {
+		TPM_OS_ERROR(TPM_PNCL_MOD, "start base offset %d != stop base offset %d\n",
+			     start_offset->offset_base, stop_offset->offset_base);
+		return(TPM_FAIL);
+	}
+
+	ret_code = tpm_pncl_get_parse_tbl(start_offset, &parse_table, &size);
+	IF_ERROR(ret_code);
+
+	stop_offset_bm = stop_offset->offset_sub.subf;
+
+	/* Get Start Index */
+	ret_code = tpm_pncl_log_offset_get(start_offset, &start_ind);
+	IF_ERROR(ret_code);
+
+	/* Get Stop Index */
+	if (stop_offset_bm == 0)
+		stop_ind = 0;
+	else if (stop_offset_bm == 0xFFFF) {
+		stop_ind = size;
+
+		if (stop_offset->offset_base == TPM_PNCL_IPV4_OFFSET) {
+			*calc_shift = 126;
+			return(TPM_OK);
+		}
+
+		if (stop_offset->offset_base == TPM_PNCL_IPV6_EXT_OFFSET) {
+			*calc_shift = 127;
+			return(TPM_OK);
+		}
+	} else {
+		ret_code = tpm_pncl_log_offset_get(stop_offset, &stop_ind);
+		IF_ERROR(ret_code);
+	}
+	if (stop_ind < start_ind)
+		TPM_OS_DEBUG(TPM_PNCL_MOD, " stop field < start field, shift=0 \n");
+
+	/* Calc Shift until end (not including last!) */
+	for (i = start_ind; i < stop_ind; i++) {
+		/* Shift is added to sum if (field is mandatory) or
+		 * (field is optional, but it was parsed in TCAM, so it exists) */
+		if (parse_table[i].mandatory == TPM_TRUE || ((parse_table[i].parse_bm & parse_bm) > 0))
+			t_calc_shift += parse_table[i].shift_len;
+	}
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " Calculated PNC shift =(%d)\n", t_calc_shift);
+
+	*calc_shift = t_calc_shift;
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_tcam_map()
+*
+* DESCRIPTION:    Function maps a Logical TCAM structure to a pseudo-physical TCAM Entry
+*
+*
+*
+* INPUTS:
+* tcam_in          - Logical TCAM structure
+*
+* OUTPUTS:
+* tcam_out         - Physical TCAM Entry
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_tcam_map(tpm_pncl_tcam_data_t *tcam_in, tpm_tcam_all_t *tcam_out)
+{
+	int32_t ret_code;
+	tpm_tcam_all_t temp_tcam_out;
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "\n");
+
+	/* AI bits are unchanged */
+	temp_tcam_out.add_info_data = tcam_in->add_info_data;
+	temp_tcam_out.add_info_mask = tcam_in->add_info_mask;
+
+	/* Lookup is unchanged */
+	temp_tcam_out.lu_id = tcam_in->lu_id;
+
+	/* Port Id mask is unchanged */
+	temp_tcam_out.port_ids = tcam_in->port_ids;
+
+	/**** Packet Data parsing ****/
+	ret_code = tpm_pncl_pkt_data_parse(tcam_in, &(temp_tcam_out.pkt_data), &(temp_tcam_out.pkt_mask));
+	IF_ERROR(ret_code);
+
+	/* Set Output */
+	memcpy(tcam_out, &temp_tcam_out, sizeof(tpm_tcam_all_t));
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_flowid_map()
+*
+* DESCRIPTION:    Function maps a Logical Flowid and SRAM bitmap to a pseudo-physical FlowId value and update mask
+*
+*
+* INPUTS:
+* flowid_in       - Flowid Data
+* sram_bm_in      - Logical SRAM bitmap
+*
+* OUTPUTS:
+* flowid_val      - Physical SRAM flowid value
+* flowid_updt_mask- pseudo-physical flowid update mask (mapping to physical maps performed in tpm_pnc_mgr)
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_flowid_map(tpm_pncl_flowid_t *flowid_in,
+			    tpm_pncl_sram_updt_bm_t sram_bm_in,
+			    uint32_t *flowid_val, uint32_t *flowid_updt_mask)
+{
+
+	*flowid_val = 0;
+	*flowid_updt_mask = 0;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "\n");
+	if (sram_bm_in & TPM_PNCL_SET_GEM) {
+		*flowid_val |= (flowid_in->gem_port << TPM_GEM_FL_SHIFT);
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "flow_id after gem_addition(%x)\n", *flowid_val);
+		*flowid_updt_mask |= TPM_GEM_FL_UPDT_MASK;
+	}
+	if (sram_bm_in & TPM_PNCL_SET_TXP) {
+		*flowid_val |= (flowid_in->pnc_target << TPM_TXP_FL_SHIFT);
+		*flowid_updt_mask |= TPM_TXP_FL_UPDT_MASK;
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "flow_id after txp_addition(%x)\n", *flowid_val);
+	}
+	if (sram_bm_in & TPM_PNCL_SET_MOD) {
+		*flowid_val |= (flowid_in->mod_cmd << TPM_MOD_FL_SHIFT);
+		*flowid_updt_mask |= TPM_MOD_FL_UPDT_MASK;
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "flow_id after pkt_mod_addition(%x)\n", *flowid_val);
+	}
+	if (sram_bm_in & TPM_PNCL_SET_SPLIT_MOD) {
+		*flowid_val |= (flowid_in->mod_cmd << TPM_MOD_FL_SHIFT);
+		*flowid_updt_mask |= TPM_MOD_FL_SPLIT_MOD_UPDT_MASK;
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "flow_id after pkt_mod_addition(%x)\n", *flowid_val);
+	}
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "flow_id log_mask(%x)\n", *flowid_updt_mask);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_res_info_map()
+*
+* DESCRIPTION:   The function maps info from the SRAM Logical format
+*                into the Result Info bits in the SRAM pseudo-physical format
+*
+* INPUTS:
+* sram_in        - Sram logical structure
+*
+* OUTPUTS:
+* sram_out       - SRAM pseudo-physical structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_res_info_map(tpm_pncl_sram_data_t *sram_in, tpm_sram_all_t *sram_out)
+{
+
+	sram_out->res_info_23_16_data = 0;
+	sram_out->res_info_23_16_mask = 0;
+	sram_out->res_info_15_0_data = 0;
+	sram_out->res_info_15_0_mask = 0;
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_DISC)
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_DISC_BIT, 1);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_IGMP)
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_RX_SPECIAL_BIT, 1);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_RX_SPECIAL)
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_RX_SPECIAL_BIT, 1);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_L3)
+		tpm_pncl_set_l3(sram_in->l3_type, sram_out);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_L4)
+		tpm_pncl_set_l4(sram_in->l4_type, sram_out);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_COL)
+		;/* TODO : Fill in code */
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_BC)
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_BC_BIT, 1);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_MC)
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_MC_BIT, 1);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_UC)
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_UC_BIT, 1);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_MH_RI) {
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "mapping <TPM_PNCL_SET_MH_RI>: mh_set(%d), mh_reg(0x%x)\r\n",
+			     sram_in->mh_reg.mh_set, sram_in->mh_reg.mh_reg);
+		if (sram_in->mh_reg.mh_set) {
+			if (sram_in->mh_reg.mh_reg & TPM_MH_RI_BIT14)
+				tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_MH_BIT_14, 1);
+
+			if (sram_in->mh_reg.mh_reg & TPM_MH_RI_BIT15)
+				tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_MH_BIT_15, 1);
+
+			if (sram_in->mh_reg.mh_reg & TPM_MH_RI_BIT16)
+				tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_MH_BIT_16, 1);
+
+			if (sram_in->mh_reg.mh_reg & TPM_MH_RI_BIT17)
+				tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_MH_BIT_17, 1);
+		}
+	}
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_PPPOE)
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_PPPOE_BIT, 1);
+
+	if (sram_in->sram_updt_bm & TPM_PNCL_SET_TAGGED)
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_VLAN_BIT, 1);
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "sram_out: res_info_23_16_data(0x%x) res_info_15_0_data(0x%x)\r\n"
+		     "          res_info_23_16_mask(0x%x) res_info_15_0_mask(0x%x)\r\n",
+		     sram_out->res_info_23_16_data, sram_out->res_info_15_0_data,
+		     sram_out->res_info_23_16_mask, sram_out->res_info_15_0_mask);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_sram_map()
+*
+* DESCRIPTION:   The function maps the Logical SRAM format into a pseudo-physical SRAM format
+*                To perform the mapping, certain TCAM fields are needed as well
+*
+* INPUTS:
+* tcam_in        - Logical TCAM structure
+* sram_in        - SRAM logical structure
+*
+* OUTPUTS:
+* sram_out       - SRAM pseudo-physical structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_sram_map(tpm_pncl_sram_data_t *sram_in, tpm_sram_all_t *sram_out, tpm_pncl_tcam_data_t *tcam_in)
+{
+	uint32_t calc_shift;
+	uint32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "\n");
+
+	/* Next LU */
+	sram_out->next_lu_id = sram_in->next_lu_id;
+	sram_out->next_lu_off_reg = sram_in->next_lu_off_reg;
+	sram_out->lookup_done = (((sram_in->sram_updt_bm & TPM_PNCL_SET_LUD) > 0) ? 1 : 0);
+
+	/* AI */
+	sram_out->add_info_data = sram_in->add_info_data;
+	sram_out->add_info_mask = sram_in->add_info_mask;
+
+	/* Queue */
+	sram_out->pnc_queue = sram_in->pnc_queue;
+
+	/* Shift Reg */
+	sram_out->shift_updt_reg = sram_in->shift_updt_reg;
+
+	/* Calculate Shift Value, if a shift_register must be updated */
+	if ((sram_out->shift_updt_reg != TPM_PNC_NOSHIFT_UPDATE_REG) && (!(sram_in->sram_updt_bm & TPM_PNCL_SET_DISC))) {
+		if (tcam_in->start_offset.offset_base == TPM_PNCL_ZERO_OFFSET) {
+			ret_code =
+			tpm_pncl_shift_calc(&(tcam_in->start_offset), &(sram_in->next_offset), tcam_in->l2_parse_bm,
+					    &calc_shift);
+			IF_ERROR(ret_code);
+		} else if (tcam_in->start_offset.offset_base == TPM_PNCL_L3_OFFSET) {
+			ret_code =
+			tpm_pncl_shift_calc(&(tcam_in->start_offset), &(sram_in->next_offset), tcam_in->l3_parse_bm,
+					    &calc_shift);
+			IF_ERROR(ret_code);
+		} else if (tcam_in->start_offset.offset_base == TPM_PNCL_IPV4_OFFSET) {
+			ret_code =
+			tpm_pncl_shift_calc(&(tcam_in->start_offset), &(sram_in->next_offset),
+					    tcam_in->ipv4_parse_bm, &calc_shift);
+			IF_ERROR(ret_code);
+		} else if ((tcam_in->start_offset.offset_base == TPM_PNCL_IPV6_OFFSET) ||
+					(tcam_in->start_offset.offset_base == TPM_PNCL_IPV6_EXT_OFFSET)/*||
+			(tcam_in->start_offset.offset_base == TPM_PNCL_IPV6_DIP_OFFSET) */) {
+			ret_code =
+			tpm_pncl_shift_calc(&(tcam_in->start_offset), &(sram_in->next_offset),
+					    tcam_in->ipv6_parse_bm, &calc_shift);
+			IF_ERROR(ret_code);
+		} else if (tcam_in->start_offset.offset_base == TPM_PNCL_TCP_OFFSET) {
+			ret_code =
+			tpm_pncl_shift_calc(&(tcam_in->start_offset), &(sram_in->next_offset),
+					    tcam_in->tcp_parse_bm, &calc_shift);
+			IF_ERROR(ret_code);
+		} else {
+			TPM_OS_ERROR(TPM_PNCL_MOD, "invalid offset base %d\n", tcam_in->start_offset.offset_base);
+			IF_ERROR(TPM_FAIL);
+		}
+
+		sram_out->shift_updt_val = calc_shift;
+	} else
+		sram_out->shift_updt_val = 0;
+
+	/* FlowId */
+	tpm_pncl_flowid_map(&(sram_in->flow_id_sub), sram_in->sram_updt_bm, &(sram_out->flowid_val),
+			    &(sram_out->flowid_updt_mask));
+
+	/* Result Info */
+	tpm_pncl_res_info_map(sram_in, sram_out);
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "ai_data(%x) ai_mask(%x) ri_15_0_d(%x) ri_15_0_m(%x) ri_23_16_d(%x) ri_23_16_m(%x)\n"
+		     "flowid_updt_mask(%x) flowid_val(%x) pnc_queue(%x)\n"
+		     "next_lu_reg(%d) next_lu_id(%d) shift_updt_reg(%d), shift_updt_val(%d)\n",
+		     sram_out->add_info_data,
+		     sram_out->add_info_mask,
+		     sram_out->res_info_15_0_data,
+		     sram_out->res_info_15_0_mask,
+		     sram_out->res_info_23_16_data,
+		     sram_out->res_info_23_16_mask,
+		     sram_out->flowid_updt_mask,
+		     sram_out->flowid_val,
+		     sram_out->pnc_queue,
+		     sram_out->next_lu_off_reg,
+		     sram_out->next_lu_id,
+		     sram_out->shift_updt_reg,
+		     sram_out->shift_updt_val);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_set_ri_bit()
+*
+* DESCRIPTION:   The function sets a single Result Info bit in the pseudo-phsical SRAM structure.
+*
+* INPUTS:
+* ri_bit         - Result Info bit number
+* ri_val         - Result Info bit value
+*
+* OUTPUTS:
+* sram_out       - SRAM pseudo-physical structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_set_ri_bit(tpm_sram_all_t *sram_out, uint32_t ri_bit, uint32_t ri_val)
+{
+	/*TODO - check data */
+	if (ri_bit < 16) {
+		sram_out->res_info_15_0_data |= (ri_val << ri_bit);
+		sram_out->res_info_15_0_mask |= (1 << ri_bit);
+	} else {
+		sram_out->res_info_23_16_data |= (ri_val << (ri_bit - 16));
+		sram_out->res_info_23_16_mask |= (1 << (ri_bit - 16));
+	}
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_set_l3()
+*
+* DESCRIPTION:   The function sets a single Result Info bit in the pseudo-phsical SRAM structure.
+*
+* INPUTS:
+* l3_type         - Logical L3_type
+*
+* OUTPUTS:
+* sram_out       - SRAM pseudo-physical structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_set_l3(tpm_pncl_l3_type_t l3_type, tpm_sram_all_t *sram_out)
+{
+	switch (l3_type) {
+	case TPM_PNCL_L3_OTHER:
+		break;
+	case TPM_PNCL_L3_IPV6:
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_L3_OFF_BIT, 1);
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "l3_type(%d)\n", l3_type);
+		break;
+	case TPM_PNCL_L3_IPV4_NFRAG:
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "l3_type(%d)\n", l3_type);
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_L3_OFF_BIT, 1);
+		tpm_pncl_set_ri_bit(sram_out, (TPM_PNC_RI_L3_OFF_BIT + 1), 1);
+		break;
+	case TPM_PNCL_L3_IPV4_FRAG:
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "l3_type(%d)\n", l3_type);
+		tpm_pncl_set_ri_bit(sram_out, (TPM_PNC_RI_L3_OFF_BIT + 1), 1);
+		break;
+	case TPM_PNCL_L3_IPV4_FFRAG:
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "l3_type(%d)\n", l3_type);
+		tpm_pncl_set_ri_bit(sram_out, (TPM_PNC_RI_L3_OFF_BIT + 1), 1);
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_L3_FF_BIT, 1);
+		break;
+	default:
+		return(TPM_FAIL);
+	}
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_set_l4()
+*
+* DESCRIPTION:   The function sets a single Result Info bit in the pseudo-phsical SRAM structure.
+*
+* INPUTS:
+* l4_type         - Logical L4_type
+*
+* OUTPUTS:
+* sram_out       - SRAM pseudo-physical structure
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_set_l4(tpm_pncl_l4_type_t l4_type, tpm_sram_all_t *sram_out)
+{
+	switch (l4_type) {
+	case TPM_PNCL_L4_OTHER:
+		tpm_pncl_set_ri_bit(sram_out, (TPM_PNC_RI_L4_OFF_BIT + 1), 1);
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "l4_type(%d)\n", l4_type);
+		break;
+	case TPM_PNCL_L4_TCP:
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "l4_type(%d)\n", l4_type);
+		break;
+	case TPM_PNCL_L4_UDP:
+		tpm_pncl_set_ri_bit(sram_out, TPM_PNC_RI_L4_OFF_BIT, 1);
+		TPM_OS_DEBUG(TPM_PNCL_MOD, "l4_type(%d)\n", l4_type);
+		break;
+	default:
+		TPM_OS_ERROR(TPM_PNCL_MOD, "l4_type(%d)\n", l4_type);
+		return(TPM_FAIL);
+	}
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_update_sram()
+*
+* DESCRIPTION:   The function sets a PNC Entry.
+*                It maps TCAM/SRAM logical to physical structures and updates HW and PNC Shadow Tables.
+* INPUTS:
+* pnc_entry      - Pnc Entry number (0-511)
+* pnc_data       - PNC pseudo-physical data (TCAM+SRAM)
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_update_sram(uint32_t pnc_entry, tpm_pncl_pnc_full_t *pnc_data)
+{
+	tpm_pnc_all_t pnc_out;
+	int32_t ret_code;
+
+	memset(&pnc_out, 0, sizeof(tpm_pnc_all_t));
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "pnc_entry(%d)\n", pnc_entry);
+	TPM_OS_COND_DEBUG(TPM_PNCL_MOD) {
+		tpm_pncl_print_pncl(pnc_data);
+	}
+
+	/* TODO : check pnc_entry value */
+	/* TODO : check pointer */
+
+	/* TCAM Translate */
+	ret_code = tpm_pncl_tcam_map(&(pnc_data->pncl_tcam), &(pnc_out.tcam_entry));
+	IF_ERROR(ret_code);
+
+	/* SRAM  Translate */
+	ret_code = tpm_pncl_sram_map(&(pnc_data->pncl_sram), &(pnc_out.sram_entry), &(pnc_data->pncl_tcam));
+	IF_ERROR(ret_code);
+
+	/* TODO: validate */
+
+	/* Call HW */
+	tpm_pnc_set(pnc_entry, 1 /*sram_update */ , &pnc_out);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(pnc_entry, &pnc_out);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_entry_set()
+*
+* DESCRIPTION:   The function sets a PNC Entry.
+*                It maps TCAM/SRAM logical to physical structures and updates HW and PNC Shadow Tables.
+* INPUTS:
+* pnc_entry      - Pnc Entry number (0-511)
+* pnc_data       - PNC pseudo-physical data (TCAM+SRAM)
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_entry_set(uint32_t pnc_entry, tpm_pncl_pnc_full_t *pnc_data)
+{
+	tpm_pnc_all_t pnc_out;
+	int32_t ret_code;
+	memset(&pnc_out, 0, sizeof(tpm_pnc_all_t));
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "pnc_entry(%d)\n", pnc_entry);
+	TPM_OS_COND_DEBUG(TPM_PNCL_MOD) {
+		tpm_pncl_print_pncl(pnc_data);
+	}
+
+	/* TODO : check pnc_entry value */
+	/* TODO : check pointer */
+
+	/* TCAM Translate */
+	ret_code = tpm_pncl_tcam_map(&(pnc_data->pncl_tcam), &(pnc_out.tcam_entry));
+	IF_ERROR(ret_code);
+
+	/* SRAM  Translate */
+	ret_code = tpm_pncl_sram_map(&(pnc_data->pncl_sram), &(pnc_out.sram_entry), &(pnc_data->pncl_tcam));
+	IF_ERROR(ret_code);
+
+	/* TODO: validate */
+
+	/* Call HW */
+	tpm_pnc_set(pnc_entry, 0 /*sram_update */ , &pnc_out);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(pnc_entry, &pnc_out);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_entry_insert()
+*
+* DESCRIPTION:   The function inserts a PNC Entry.
+*                It inserts an empty entry into a range and then sets the entry.
+* INPUTS:
+* pnc_ins_entry  - Pnc Entry first entry to "move down", also the entry to set
+* pnc_stop_entry - Pnc last entry to "move"down"
+* pnc_data       - PNC pseudo-physical data (TCAM+SRAM)
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_entry_insert(uint32_t pnc_ins_entry, uint32_t pnc_stop_entry, tpm_pncl_pnc_full_t *pnc_data)
+{
+
+	int32_t ret_code;
+
+	/* TODO : check pnc_entry value */
+	/* TODO : check pointer */
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "pnc_ins_entry(%d) pnc_stop_entry(%d)\n", pnc_ins_entry, pnc_stop_entry);
+
+	/* Insert empty entry in HW */
+	tpm_pnc_entry_insert(pnc_ins_entry, pnc_stop_entry);
+
+	/* Update PNC Shadow  */
+	ret_code = tpm_db_pnc_shdw_ent_ins(pnc_ins_entry, pnc_stop_entry);
+	IF_ERROR(ret_code);
+
+	/* Set new PNC entry */
+	ret_code = tpm_pncl_entry_set(pnc_ins_entry, pnc_data);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_entry_reset()
+*
+* DESCRIPTION:   The function resets a PNC Entry.
+*                It updates HW and PNC Shadow Tables.
+* INPUTS:
+* pnc_entry      - Pnc Entry number (0-511)
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_entry_reset(uint32_t pnc_entry)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "pnc_entry(%d)\n", pnc_entry);
+
+	/* TODO : check pnc_entry value */
+
+	/* Call HW */
+	ret_code = tpm_pnc_entry_inv(pnc_entry);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_inv(pnc_entry);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_entry_delete()
+*
+* DESCRIPTION:   The function deletes a PNC Entry. It "pushes up" a range of PNC entries
+*                following the entry to be deleted. It updates HW and PNC Shadow Tables.
+* INPUTS:
+* pnc_del_entry  - Pnc Entry to delete, the following entry is the frist entry to "push Up"
+* pnc_stop_entry - Pnc last entry to "push Up"
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_entry_delete(uint32_t pnc_del_entry, uint32_t pnc_stop_entry)
+{
+	int32_t ret_code;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "pnc_del_entry(%d) pnc_stop_entry(%d)\n", pnc_del_entry, pnc_stop_entry);
+
+	if ((pnc_del_entry > pnc_stop_entry) || (pnc_stop_entry > TPM_PNC_SIZE))
+		TPM_OS_ERROR(TPM_PNCL_MOD, "pnc_del_entry(%d) pnc_stop_entry(%d)\n", pnc_del_entry, pnc_stop_entry);
+
+	/* Call HW */
+	ret_code = tpm_pnc_entry_delete(pnc_del_entry, pnc_stop_entry);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_del(pnc_del_entry, pnc_stop_entry);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_pkt_trap()
+*
+* DESCRIPTION:   The function sets an entry to "CPU trap"
+*                The function purpose is to catch  packets that for unknown reason have not been caught
+*                by previous rules in a lookup_id
+*
+* INPUTS:
+* entry          - Pnc Entry number
+* lu_id          - lu_id to set in TCAM. The function only traps packets with  this lu_id
+* gmac_bm        - gmac bitmap to set in TCAM port_id field. The function only traps packets from GMACs in the bitmap.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_pkt_trap(uint32_t entry, uint32_t lu_id, tpm_gmac_bm_t gmac_bm)
+{
+	uint32_t ret_code;
+
+	tpm_pnc_all_t pnc_entry;
+
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " pnc_entry(%d) lu_id(%d) gmac_bm(%x)\n", entry, lu_id, gmac_bm);
+
+	/* Set LU Done */
+	pnc_entry.sram_entry.lookup_done = 1;
+
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = lu_id;
+
+	/* Set port_ids */
+	pnc_entry.tcam_entry.port_ids = gmac_bm;
+
+	/* Set high FlowId to Pnc Entry, as indication to CPU, which PnC entry performed a trap */
+	pnc_entry.sram_entry.flowid_val = (entry << TPM_PKT_TRAP_FL_SHIFT);
+	pnc_entry.sram_entry.flowid_updt_mask = TPM_PKT_TRAP_UPDT_MASK;
+
+	/* Set Target to CPU */
+	pnc_entry.sram_entry.flowid_val |= (TPM_PNC_TRG_CPU << TPM_TXP_FL_SHIFT);
+	pnc_entry.sram_entry.flowid_updt_mask |= TPM_TXP_FL_UPDT_MASK;
+
+	/* Set Result Info Ind. to CPU */
+	tpm_pncl_set_ri_bit(&(pnc_entry.sram_entry), TPM_PNC_RI_TRAP_BIT, 1);
+
+	/* If debug, then print entry */
+	TPM_OS_COND_DEBUG(TPM_PNCL_MOD) {
+		tpm_pnc_print_sw_entry(&pnc_entry);
+	}
+	/* Write to PNC */
+	tpm_pnc_set(entry, 0, &pnc_entry);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_pkt_drop()
+*
+* DESCRIPTION:   The function sets an entry to drop. It sets only lu_id, port_id in TCAM, empty
+*                and leaves the packet part (24 bytes). The function purpose is to drop packets t
+*                hat for unknown reason have not been caught by previous rules in a lookup_id
+*
+* INPUTS:
+* entry          - Pnc Entry number
+* lu_id          - lookup_id to set in TCAM. The function only drops packets with this lu_id
+* gmac_bm        - gmac bitmap to set in TCAM port_id field. The function only drops packets from GMACs in the bitmap.
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_pkt_drop(uint32_t entry, uint32_t lu_id, tpm_gmac_bm_t gmac_bm)
+{
+	uint32_t ret_code;
+	tpm_pnc_all_t pnc_entry;
+
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, " pnc_entry(%d) lu_id(%d) gmac_bm(%x)\n", entry, lu_id, gmac_bm);
+
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = lu_id;
+
+	/* Set port_ids */
+	pnc_entry.tcam_entry.port_ids = gmac_bm;
+
+	/* Set LU Done */
+	pnc_entry.sram_entry.lookup_done = 1;
+
+	/* Set Discard */
+	tpm_pncl_set_ri_bit(&(pnc_entry.sram_entry), TPM_PNC_RI_DISC_BIT, 1);
+
+	/* Write to PNC */
+	tpm_pnc_set(entry, 0, &pnc_entry);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_init_ipv6_last_entry(uint32_t entry, uint32_t lu_id, uint32_t next_lu_id)
+{
+	uint32_t ret_code;
+	tpm_pnc_all_t pnc_entry;
+	tpm_gmac_bm_t l_gmac_bm;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "entry(%d) lu_id(%d), next_lu_id(%d)\n", entry, lu_id, next_lu_id);
+
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = lu_id;
+
+	/* Set port_ids, both dir */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN, &l_gmac_bm);
+	pnc_entry.tcam_entry.port_ids |= l_gmac_bm;
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_UNI_ANY, &l_gmac_bm);
+	pnc_entry.tcam_entry.port_ids |= l_gmac_bm;
+
+	/* Set LU Done */
+	pnc_entry.sram_entry.next_lu_id = next_lu_id;
+
+	/* Write to PNC */
+	tpm_pnc_set(entry, 0, &pnc_entry);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_ipv6_shift2dip(tpm_sram_all_t *sram_entry)
+{
+	/*TODO  check pointer */
+
+	/* in ipv6, use the 3rd shift offset table for now, need further discussion.
+	 * it is like in excel column "shift update" says "[2] = 24",
+	 * "Nxt LU offset Ind" says " 2 ".
+	 */
+	sram_entry->next_lu_off_reg = 2;
+	sram_entry->shift_updt_reg = 2;
+	sram_entry->shift_updt_val = 24;
+
+	return TPM_OK;
+}
+
+int32_t tpm_pncl_init_ipv4_mc_range(void)
+{
+	int32_t ret_code = TPM_OK;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_pnc_all_t pnc_entry;
+	tpm_gmac_bm_t l_gmac_bm;
+	tpm_mc_filter_mode_t filter_mode;
+	uint32_t cpu_rx_queue;
+
+	/* Get DB Info, check PnC config */
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV4_MC_DS, &range_conf);
+	IF_ERROR(ret_code);
+
+	filter_mode = tpm_db_get_mc_filter_mode();
+	tpm_db_get_cpu_rx_queue(&cpu_rx_queue);
+
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_conf.base_lu_id;
+
+	/* Set port_ids, both dir */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN_OR_LAN, &l_gmac_bm);
+	pnc_entry.tcam_entry.port_ids |= l_gmac_bm;
+
+	/* Set LU Done */
+	pnc_entry.sram_entry.lookup_done = 1;
+
+	pnc_entry.sram_entry.flowid_updt_mask = TPM_TXP_FL_UPDT_MASK;
+	if (TPM_MC_ALL_CPU_FRWD == filter_mode)
+		pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_CPU << TPM_TXP_FL_SHIFT);
+	else if (TPM_MC_MAC_ONLY_FILTER == filter_mode) {
+		pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_GMAC0 << TPM_TXP_FL_SHIFT);
+		pnc_entry.sram_entry.pnc_queue = 1;
+
+		tpm_pncl_set_ri_bit(&pnc_entry.sram_entry, TPM_PNC_RI_MH_BIT_14, 1);
+		tpm_pncl_set_ri_bit(&pnc_entry.sram_entry, TPM_PNC_RI_MH_BIT_15, 1);
+		tpm_pncl_set_ri_bit(&pnc_entry.sram_entry, TPM_PNC_RI_MH_BIT_16, 1);
+		tpm_pncl_set_ri_bit(&pnc_entry.sram_entry, TPM_PNC_RI_MH_BIT_17, 1);
+	} else
+		/* Set Discard */
+		tpm_pncl_set_ri_bit(&(pnc_entry.sram_entry), TPM_PNC_RI_DISC_BIT, 1);
+
+	/* the first byte of DIP is 224 to 239, high 3 bits are 1s */
+	pnc_entry.tcam_entry.pkt_data.pkt_byte[16] = 0xE0;
+	pnc_entry.tcam_entry.pkt_mask.pkt_byte[16] = 0xE0;
+
+	/* Write to PNC */
+	tpm_pnc_set(range_conf.range_end, 0, &pnc_entry);
+
+	/* fix bug for IPv4MC - default last entry in range is DISCARDING all MC
+	   - but num of free entries / api_end - is not decremented */
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_IPV4_MC_DS);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(range_conf.range_end, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_pncl_init_ipv4_ranges()
+*
+* DESCRIPTION:  Functions resets a IPv4 PnC range, in HW and in DB.
+*
+*
+* INPUTS:
+* range_id       - range_id number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_init_ipv4_ranges(tpm_pnc_ranges_t range_id)
+{
+	int32_t ret_code = TPM_OK;
+
+	if (range_id == TPM_PNC_IPV4_MC_DS)
+		ret_code = tpm_pncl_init_ipv4_mc_range();
+
+	/* No other cases yet */
+	return ret_code;
+}
+
+/*******************************************************************************
+* tpm_pncl_init_ipv6_mc_range()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_pncl_init_ipv6_mc_range(void)
+{
+	int32_t ret_code = TPM_OK;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_pnc_all_t pnc_entry;
+	tpm_gmac_bm_t l_gmac_bm;
+
+	/*
+		In TPM_PNC_IPV6_MC, add a default PNC entry at the end
+		to discard all the DS un-match IPv6 MC packets
+	*/
+
+	/* Get DB Info, check PnC config */
+	ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_IPV6_MC_DS, &range_conf);
+	IF_ERROR(ret_code);
+
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_conf.base_lu_id;
+
+	/* Set port_ids, both dir */
+	tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_WAN_OR_LAN, &l_gmac_bm);
+	pnc_entry.tcam_entry.port_ids |= l_gmac_bm;
+
+	/* Set LU Done */
+	pnc_entry.sram_entry.lookup_done = 1;
+
+	pnc_entry.sram_entry.flowid_updt_mask = TPM_TXP_FL_UPDT_MASK;
+
+	tpm_pncl_set_ri_bit(&(pnc_entry.sram_entry), TPM_PNC_RI_DISC_BIT, 1);
+
+	/* the first byte of DIP is 0xff */
+	pnc_entry.tcam_entry.pkt_data.pkt_byte[0] = 0xff;
+	pnc_entry.tcam_entry.pkt_mask.pkt_byte[0] = 0xff;
+
+	/* Write to PNC */
+	tpm_pnc_set(range_conf.range_end, 0, &pnc_entry);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_IPV6_MC_DS);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(range_conf.range_end, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_pncl_init_ipv6_ranges()
+*
+* DESCRIPTION:  Functions resets a IPv4 PnC range, in HW and in DB.
+*
+*
+* INPUTS:
+* range_id       - range_id number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_init_ipv6_ranges(tpm_pnc_ranges_t range_id)
+{
+	int32_t ret_code = TPM_OK;
+
+	if (range_id == TPM_PNC_IPV6_MC_DS)
+		ret_code = tpm_pncl_init_ipv6_mc_range();
+
+	/* No other cases yet */
+	return ret_code;
+}
+
+
+int32_t tpm_pncl_init_cnm_ipv4_pre_range(void)
+{
+	int32_t ret_code = TPM_OK;
+	tpm_db_pnc_range_conf_t range_conf;
+	tpm_pnc_all_t pnc_entry;
+	uint32_t entry_id;
+	tpm_gmac_bm_t gmac_bm;
+
+	tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
+
+	/* Set Structs to zero */
+	memset(&range_conf, 0, sizeof(tpm_db_pnc_range_conf_t));
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+
+	tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
+
+	/* default rule:
+	 *	create default PNC rules in CnM_IPv4_Pre, go to CnM_MAIN
+	 */
+	if (ctc_cm_enable != TPM_CTC_CM_DISABLED) {
+		/* Get DB Info, check PnC config */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_IPV4_PRE, &range_conf);
+		IF_ERROR(ret_code);
+
+		entry_id = range_conf.range_end;
+
+		/* Set Lookup Id */
+		pnc_entry.tcam_entry.lu_id = range_conf.base_lu_id;
+
+		/* Set port_ids, both dir */
+		ret_code = tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_UNI_ANY, &gmac_bm);
+		IF_ERROR(ret_code);
+		pnc_entry.tcam_entry.port_ids = gmac_bm;
+
+		/* Get DB Info, check PnC config */
+		ret_code = tpm_db_pnc_rng_conf_get(TPM_PNC_CNM_MAIN, &range_conf);
+		IF_ERROR(ret_code);
+
+		/* Set Next LUID  */
+		pnc_entry.sram_entry.next_lu_id = range_conf.base_lu_id + TPM_CNM_L2_MAIN_LUID_OFFSET;
+		pnc_entry.sram_entry.next_lu_off_reg = TPM_PNC_CNM_L2_REG;
+
+		pnc_entry.sram_entry.add_info_data &= ~TPM_AI_CNM_IPV4_PRE_KEY_MASK;
+		pnc_entry.sram_entry.add_info_mask = TPM_AI_CNM_IPV4_PRE_KEY_MASK;
+
+		pnc_entry.sram_entry.pnc_queue = 0xFFFF;
+		pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+		/* Write to PNC */
+		tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+		ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_CNM_IPV4_PRE);
+		IF_ERROR(ret_code);
+
+		/* Write to Shadow */
+		ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+		IF_ERROR(ret_code);
+	}
+
+	return(TPM_OK);
+}
+int32_t tpm_pncl_init_cnm_main_ety_ipv6(uint32_t entry_id, tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win)
+{
+	int32_t ret_code = TPM_OK;
+	tpm_db_pnc_range_t range_data;
+	tpm_pnc_all_t pnc_entry;
+	tpm_gmac_bm_t gmac_bm;
+
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+
+	/* Set Structs to zero */
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	/* Get DB Info, check PnC config */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_CNM_MAIN, &range_data);
+	IF_ERROR(ret_code);
+
+	/* Set port_ids, US dir */
+	ret_code = tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_UNI_ANY, &gmac_bm);
+	IF_ERROR(ret_code);
+	pnc_entry.tcam_entry.port_ids = gmac_bm;
+
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id + TPM_CNM_ETY_MAIN_LUID_OFFSET;
+
+	/* Set Next LUID  */
+	pnc_entry.sram_entry.next_lu_id = range_data.pnc_range_conf.base_lu_id + TPM_CNM_IPV6_MAIN_LUID_OFFSET;
+
+	pnc_entry.sram_entry.pnc_queue = 0xFFFF;
+
+	/* depends on ipv6 CnM parse window */
+	if(TPM_CTC_CM_IPv6_FIRST_24B == ctc_cm_ipv6_parse_win) {
+		pnc_entry.sram_entry.next_lu_off_reg = TPM_PNC_LU_REG0;
+		pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+	} else {
+		pnc_entry.sram_entry.next_lu_off_reg = TPM_PNC_IPV6_DIP_REG;
+		pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_IPV6_DIP_REG;
+		pnc_entry.sram_entry.shift_updt_val = 26;
+	}
+
+	/* ETY = 0x86dd */
+	pnc_entry.tcam_entry.pkt_data.pkt_byte[0] = 0x86;
+	pnc_entry.tcam_entry.pkt_data.pkt_byte[1] = 0xDD;
+	pnc_entry.tcam_entry.pkt_mask.pkt_byte[0] = 0xFF;
+	pnc_entry.tcam_entry.pkt_mask.pkt_byte[1] = 0xFF;
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return TPM_OK;
+}
+
+int32_t tpm_pncl_init_cnm_main_range(void)
+{
+	int32_t ret_code = TPM_OK;
+	tpm_db_pnc_range_t range_data;
+	tpm_pnc_all_t pnc_entry;
+	uint32_t free_entry = 0, entry_id;
+	tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win;
+	tpm_gmac_bm_t gmac_bm;
+
+	tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
+
+	/* Set Structs to zero */
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+
+	tpm_db_ctc_cm_enable_get(&ctc_cm_enable);
+
+	if (ctc_cm_enable == TPM_CTC_CM_DISABLED)
+		return TPM_OK;
+
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+
+	/* Get DB Info, check PnC config */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_CNM_MAIN, &range_data);
+	IF_ERROR(ret_code);
+
+	free_entry = range_data.pnc_range_oper.free_entries;
+	entry_id = range_data.pnc_range_conf.range_end;
+
+	/* default rule #1:
+	 *	create three default PNC rules in CnM_MAIN, CnM_IPv4 DONE
+	 */
+
+	if (free_entry == 0) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "No free entries\n");
+		return(TPM_FAIL);
+	}
+
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id + TPM_CNM_IPV4_MAIN_LUID_OFFSET;
+	/* Set port_ids, US dir */
+	ret_code = tpm_proc_src_port_gmac_bm_map(TPM_SRC_PORT_UNI_ANY, &gmac_bm);
+	IF_ERROR(ret_code);
+	pnc_entry.tcam_entry.port_ids = gmac_bm;
+
+	/* Set Next LUID  */
+	pnc_entry.sram_entry.lookup_done = TPM_TRUE;
+
+	pnc_entry.sram_entry.pnc_queue = 0xFFFF;
+	pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_CNM_MAIN);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	free_entry--;
+	entry_id--;
+
+	/* default rule #2:
+	 *	create three default PNC rules in CnM_MAIN, CnM_IPv6 DONE
+	 */
+	if (free_entry == 0) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "No free entries\n");
+		return(TPM_FAIL);
+	}
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id + TPM_CNM_IPV6_MAIN_LUID_OFFSET;
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_CNM_MAIN);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	free_entry--;
+	entry_id--;
+
+	/* default rule #3:
+	 *	create default PNC rules in CnM_MAIN, CnM_ETY L2 done
+	 */
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id + TPM_CNM_ETY_MAIN_LUID_OFFSET;
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_CNM_MAIN);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	free_entry--;
+	entry_id--;
+
+	/* default rule #4:
+	 *	create default PNC rules in CnM_MAIN, CnM_ETY IPv4 goto CnM_IPv4
+	 */
+
+	pnc_entry.sram_entry.lookup_done = TPM_FALSE;
+
+	/* Set Next LUID  */
+	pnc_entry.sram_entry.next_lu_id = range_data.pnc_range_conf.base_lu_id + TPM_CNM_IPV4_MAIN_LUID_OFFSET;
+	pnc_entry.sram_entry.next_lu_off_reg = TPM_PNC_LU_REG0;
+
+	pnc_entry.sram_entry.pnc_queue = 0xFFFF;
+	pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* ETY = 0x0800 */
+	pnc_entry.tcam_entry.pkt_data.pkt_byte[0] = 0x08;
+	pnc_entry.tcam_entry.pkt_data.pkt_byte[1] = 0x00;
+	pnc_entry.tcam_entry.pkt_mask.pkt_byte[0] = 0xFF;
+	pnc_entry.tcam_entry.pkt_mask.pkt_byte[1] = 0xFF;
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_CNM_MAIN);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	free_entry--;
+	entry_id--;
+	/* default rule #5:
+	 *	create default PNC rules in CnM_MAIN, CnM_ETY IPv6 goto CnM_IPv6
+	 */
+	tpm_db_ctc_cm_ipv6_parse_win_get(&ctc_cm_ipv6_parse_win);
+	ret_code = tpm_pncl_init_cnm_main_ety_ipv6(entry_id, ctc_cm_ipv6_parse_win);
+	IF_ERROR(ret_code);
+
+	/* record ipv6_ety_rule_num */
+	tpm_db_ctc_cm_ipv6_ety_rule_num_set(entry_id);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_CNM_MAIN);
+	IF_ERROR(ret_code);
+
+	free_entry--;
+	entry_id--;
+
+	/* default rule #6:
+	 *	create default PNC rules in CnM_MAIN, CnM_l2 go to CnM_ETY
+	 */
+
+	if (free_entry == 0) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "No free entries\n");
+		return(TPM_FAIL);
+	}
+
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id + TPM_CNM_L2_MAIN_LUID_OFFSET;
+
+	/* Set port_ids, US dir */
+	pnc_entry.tcam_entry.port_ids = gmac_bm;
+
+	/* Set Next LUID  */
+	pnc_entry.sram_entry.next_lu_id = range_data.pnc_range_conf.base_lu_id + TPM_CNM_ETY_MAIN_LUID_OFFSET;
+	pnc_entry.sram_entry.next_lu_off_reg = TPM_PNC_ETY_REG;
+
+	pnc_entry.sram_entry.add_info_data = TPM_AI_CNM_PREC_MASK;
+	pnc_entry.sram_entry.add_info_mask = TPM_AI_CNM_PREC_MASK;
+
+	pnc_entry.sram_entry.pnc_queue = 0xFFFF;
+	pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_CNM_MAIN);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+int32_t tpm_pncl_init_cnm_ranges(tpm_pnc_ranges_t range_id)
+{
+	int32_t ret_code = TPM_OK;
+
+	if (range_id == TPM_PNC_CNM_IPV4_PRE)
+		ret_code = tpm_pncl_init_cnm_ipv4_pre_range();
+	else if (range_id == TPM_PNC_CNM_MAIN)
+		ret_code = tpm_pncl_init_cnm_main_range();
+
+	/* No other cases yet */
+	return ret_code;
+}
+
+/*******************************************************************************
+* tpm_pncl_init_mac_learn_range()
+*
+* DESCRIPTION:  Functions init MAC learn range default rule
+*
+*
+* INPUTS:
+* range_id       - range_id number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_init_mac_learn_range(void)
+{
+	int32_t ret_code = TPM_OK;
+	tpm_db_pnc_range_t range_data;
+	tpm_pnc_all_t pnc_entry;
+	uint32_t free_entry = 0, entry_id;
+	uint32_t queue_id;
+	tpm_gmacs_enum_t lpk_gmac;
+
+	/* Set Structs to zero */
+	memset(&range_data, 0, sizeof(tpm_db_pnc_range_t));
+	memset(&pnc_entry, 0, sizeof(tpm_pnc_all_t));
+
+	/* check gmac1 loopback en */
+	if (!tpm_db_gmac1_lpbk_en_get())
+		return(TPM_OK);
+
+	/* Get DB Info, check PnC config */
+	ret_code = tpm_db_pnc_rng_get(TPM_PNC_MAC_LEARN, &range_data);
+	IF_ERROR(ret_code);
+
+	free_entry = range_data.pnc_range_oper.free_entries;
+	entry_id = range_data.pnc_range_conf.range_end;
+	/* check the free size in the range for default rule*/
+	if (free_entry == 0) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "No free entries\n");
+		return(TPM_FAIL);
+	}
+
+	/* construct default rule */
+	/* Set Lookup Id */
+	pnc_entry.tcam_entry.lu_id = range_data.pnc_range_conf.base_lu_id;
+	/* Set port_id */
+	pnc_entry.tcam_entry.port_ids = TPM_BM_GMAC_0;
+	/* Set LU Done */
+	pnc_entry.sram_entry.lookup_done = TPM_TRUE;
+
+	pnc_entry.sram_entry.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+	pnc_entry.sram_entry.shift_updt_reg = TPM_PNC_NOSHIFT_UPDATE_REG;
+
+	pnc_entry.sram_entry.flowid_updt_mask = TPM_TXP_FL_UPDT_MASK;
+
+	/*forward packet to GMAC1 as default*/
+	if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac, &queue_id)) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "loopback gmac queue get failed \n");
+		return TPM_FAIL;
+	}
+	/* Set target GMAC1 */
+	pnc_entry.sram_entry.flowid_val = (TPM_PNC_TRG_GMAC1 << TPM_TXP_FL_SHIFT);
+	pnc_entry.sram_entry.pnc_queue = queue_id;
+
+	/* Write to PNC */
+	tpm_pnc_set(entry_id, 0, &pnc_entry);
+
+	ret_code = tpm_db_pnc_rng_api_end_dec(TPM_PNC_MAC_LEARN);
+	IF_ERROR(ret_code);
+
+	/* Write to Shadow */
+	ret_code = tpm_db_pnc_shdw_ent_set(entry_id, &pnc_entry);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_pncl_init_mac_learn_ranges()
+*
+* DESCRIPTION:  Functions init MAC learn range
+*
+*
+* INPUTS:
+* range_id       - range_id number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_init_mac_learn_ranges(tpm_pnc_ranges_t range_id)
+{
+	int32_t ret_code = TPM_OK;
+
+	if (range_id == TPM_PNC_MAC_LEARN)
+		ret_code = tpm_pncl_init_mac_learn_range();
+
+	return ret_code;
+}
+
+/*******************************************************************************
+* tpm_pncl_range_reset()
+*
+* DESCRIPTION:  Functions resets a PnC range, in HW and in DB.
+*
+*
+* INPUTS:
+* range_id       - range_id number
+*
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_pncl_range_reset(tpm_pnc_ranges_t range_id)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_conf_t range_conf;
+	uint32_t switch_init;
+
+	TPM_OS_DEBUG(TPM_PNCL_MOD, "range_id(%d)\n", range_id);
+
+	/* Get DB Info, check PnC config */
+	ret_code = tpm_db_pnc_rng_conf_get(range_id, &range_conf);
+	IF_ERROR(ret_code);
+
+	/* Update HW */
+	if (range_conf.range_size > 1)	/* Invalidate all entries, except last */
+		tpm_pnc_range_inv(range_conf.range_start, (range_conf.range_end - 1));
+
+	/* get switch_init */
+	ret_code = tpm_db_switch_init_get(&switch_init);
+	IF_ERROR(ret_code);
+
+	/* Handle Range's last Pnc Entry */
+	if (range_id == TPM_PNC_IPV4_MC_DS) {
+		ret_code = tpm_pncl_init_ipv4_ranges(range_id);
+		IF_ERROR(ret_code);
+	} else if (range_id == TPM_PNC_IPV6_MC_DS) {
+		ret_code = tpm_pncl_init_ipv6_ranges(range_id);
+		IF_ERROR(ret_code);
+	} else if (range_id == TPM_PNC_CNM_IPV4_PRE ||
+			   range_id == TPM_PNC_CNM_MAIN) {
+		ret_code = tpm_pncl_init_cnm_ranges(range_id);
+		IF_ERROR(ret_code);
+	} else if (range_id == TPM_PNC_MAC_LEARN) {
+		ret_code = tpm_pncl_init_mac_learn_ranges(range_id);
+		IF_ERROR(ret_code);
+	} else {
+		if (range_conf.init_last_entry == TPM_PNC_RNG_LAST_INIT_TRAP) {
+			ret_code = tpm_pncl_pkt_trap(range_conf.range_end,
+						     range_conf.base_lu_id, range_conf.last_ent_portid);
+			IF_ERROR(ret_code);
+		} else if (range_conf.init_last_entry == TPM_PNC_RNG_LAST_INIT_DROP) {
+			ret_code = tpm_pncl_pkt_drop(range_conf.range_end,
+						     range_conf.base_lu_id, range_conf.last_ent_portid);
+			IF_ERROR(ret_code);
+		} else
+			tpm_pnc_entry_inv(range_conf.range_end);
+	}
+	/* Update DB */
+	ret_code = tpm_db_pnc_rng_reset(range_id);
+	IF_ERROR(ret_code);
+
+	return(TPM_OK);
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.h
new file mode 100755
index 0000000..271f82f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_pnc_logic.h
@@ -0,0 +1,350 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_pnc_logic.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.2
+*
+*******************************************************************************/
+#ifndef _TPM_PNCL_H_
+#define _TPM_PNCL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+typedef enum {
+	TPM_PNCL_ZERO_OFFSET,	/* Offset 0 */
+	TPM_PNCL_L3_OFFSET,	/* L3 Header offset */
+	TPM_PNCL_IPV4_OFFSET,	/* IPV4 Header offset */
+	TPM_PNCL_IPV6_OFFSET,	/* IPV6 Header offset */
+	TPM_PNCL_IPV6_EXT_OFFSET,	/* IPV6 Ext Header offset */
+	TPM_PNCL_IPV6_DIP_OFFSET,	/* IPV6 DIP offset */
+	TPM_PNCL_TCP_OFFSET,	/* TCP Header offset */
+	TPM_PNCL_L4_OFFSET	/* UDP/TCP Header offset, used for L4 ports only */
+} tpm_pncl_offset_base_t;
+
+typedef enum {
+	TPM_PNCL_L3_OTHER,
+	TPM_PNCL_L3_IPV6,
+	TPM_PNCL_L3_IPV4_FRAG,
+	TPM_PNCL_L3_IPV4_FFRAG,
+	TPM_PNCL_L3_IPV4_NFRAG
+} tpm_pncl_l3_type_t;
+
+typedef enum {
+	TPM_PNCL_L4_OTHER,
+	TPM_PNCL_L4_TCP,
+	TPM_PNCL_L4_UDP,
+	TPM_PNCL_L4_IGMP,
+	TPM_PNCL_L4_ICMP
+} tpm_pncl_l4_type_t;
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+
+#define     TPM_PNCL_NO_QUEUE_UPDATE        0xFFFF
+
+/* SRAM Update sub-fields update mask */
+#define     TPM_PNCL_SET_GEM             0x1
+#define     TPM_PNCL_SET_TXP             0x2
+#define     TPM_PNCL_SET_MOD             0x4
+#define     TPM_PNCL_SET_DISC            0x8
+#define     TPM_PNCL_SET_RX_SPECIAL      0x10
+#define     TPM_PNCL_SET_LUD             0x20
+#define     TPM_PNCL_SET_L3              0x40
+#define     TPM_PNCL_SET_L4              0x80
+#define     TPM_PNCL_SET_COL             0x100
+#define     TPM_PNCL_SET_IGMP            0x200
+#define     TPM_PNCL_SET_MH_RI           0x400
+#define     TPM_PNCL_SET_BC              0x800
+#define     TPM_PNCL_SET_MC              0x1000
+#define     TPM_PNCL_SET_UC              0x2000
+#define     TPM_PNCL_SET_PPPOE           0x4000
+#define     TPM_PNCL_SET_TAGGED          0x8000
+#define     TPM_PNCL_SET_SPLIT_MOD       0x10000
+
+typedef uint32_t tpm_pncl_sram_updt_bm_t;
+
+#define     TPM_MH_RI_BIT14       0x00004000
+#define     TPM_MH_RI_BIT15       0x00008000
+#define     TPM_MH_RI_BIT16       0x00010000
+#define     TPM_MH_RI_BIT17       0x00020000
+#define     TPM_MH_RI_OFFSET      14
+
+/* TPM flowid shift values */
+#define     TPM_GEM_FL_SHIFT            (12)
+#define     TPM_TXP_FL_SHIFT            (24)
+#define     TPM_MOD_FL_SHIFT            (00)
+#define     TPM_PKT_TRAP_FL_SHIFT       (00)
+
+/* TPM flowid update values */
+#define     TPM_FLOW_NIB_0              (0x01)
+#define     TPM_FLOW_NIB_1              (0x02)
+#define     TPM_FLOW_NIB_2              (0x04)
+#define     TPM_FLOW_NIB_3              (0x08)
+#define     TPM_FLOW_NIB_4              (0x10)
+#define     TPM_FLOW_NIB_5              (0x20)
+#define     TPM_FLOW_NIB_6              (0x40)
+#define     TPM_FLOW_NIB_7              (0x80)
+
+#define     TPM_TXP_FL_UPDT_MASK        (TPM_FLOW_NIB_6)
+#define     TPM_GEM_FL_UPDT_MASK        (TPM_FLOW_NIB_5|TPM_FLOW_NIB_4|TPM_FLOW_NIB_3)
+#define     TPM_MOD_FL_UPDT_MASK        (TPM_FLOW_NIB_2|TPM_FLOW_NIB_1|TPM_FLOW_NIB_0)
+#define     TPM_PKT_TRAP_UPDT_MASK      (TPM_FLOW_NIB_3|TPM_FLOW_NIB_2|TPM_FLOW_NIB_1|TPM_FLOW_NIB_0)
+#define     TPM_MOD_FL_SPLIT_MOD_UPDT_MASK        (TPM_FLOW_NIB_0)
+
+/* PNC - Parse fields - bitmap ****************/
+/* These bitmap values are internal, they are complimentary to the values in tpm_types.h
+ * must have different values */
+#define                 TPM_L2_PARSE_MH                 (0x8000)
+#define                 TPM_L2_PARSE_PPPOE_CTRL         (0x4000)
+#define                 TPM_L2_PARSE_PPPOE_HDR		(TPM_L2_PARSE_PPPOE_CTRL | \
+								TPM_L2_PARSE_PPPOE_SES | TPM_L2_PARSE_PPP_PROT)
+#define                 TPM_PNCL_ONE_TWO_VLAN_TAG       (TPM_L2_PARSE_ONE_VLAN_TAG|TPM_L2_PARSE_TWO_VLAN_TAG)
+
+/* These bitmap values are internal, they are complimentary to the values in tpm_types.h
+ * MUST!! have different values, than the values there */
+#define                 TPM_IPv4_PARSE_VER               (0x8000)	/* parse IPv4 Version */
+#define                 TPM_IPv4_PARSE_IHL               (0x4000)	/* parse IPv4 IHL */
+#define                 TPM_IPv4_PARSE_VER_OR_IHL        (TPM_IPv4_PARSE_VER|TPM_IPv4_PARSE_IHL)
+#define                 TPM_IPv4_PARSE_TOTLEN            (0x2000)	/* parse IPv4 Total Len */
+#define                 TPM_IPv4_PARSE_IDENT             (0x1000)	/* parse IPv4  Identification field */
+#define                 TPM_IPv4_PARSE_FLAG_MF           (0x0800)	/* parse IPv4  MF Flag */
+#define                 TPM_IPv4_PARSE_FRAG_OFFSET       (0x0400)	/* parse IPv4  Offset */
+#define                 TPM_IPv4_PARSE_MF_OR_FRAG        (TPM_IPv4_PARSE_FLAG_MF|TPM_IPv4_PARSE_FRAG_OFFSET)
+#define                 TPM_IPv4_PARSE_TTL               (0x0200)	/* parse IPv4  TTL */
+
+#define                 TPM_TCP_PARSE_DUMMY              (0x8000)
+#define                 TPM_TCP_PARSE_FLAGS              (0x4000)
+
+/* These bitmap values are internal, they are complimentary to the values in tpm_types.h
+ * must have different values, than the values there */
+#define                 TPM_IPv6_PARSE_VER               (0x10000)	/* parse IPv6 Version */
+#define                 TPM_IPv6_PARSE_VER_OR_DSCP       (TPM_IPv6_PARSE_VER|TPM_IPv6_PARSE_DSCP)
+#define 				TPM_IPv6_PARSE_FLOW              (0x20000)	/* parse IPv6 Flow Label */
+#define                 TPM_IPv6_PARSE_DSCP_OR_FLOW      (TPM_IPv6_PARSE_DSCP|TPM_IPv6_PARSE_FLOW)
+#define                 TPM_IPv6_PARSE_PLLEN             (0x40000)	/* parse IPv6 Payload Len */
+#define                 TPM_IPv6_PARSE_HOPLIM            (0x80000)	/* parse IPv6  Hop Limit */
+
+#define                 TPM_PARSE_L4_CHECKSUM       (0x10000)	/* parse L4 Checksum */
+
+#define                 TPM_PARSE_UDP_LEN           (0x20000)	/* parse UDP Len */
+
+#define                 TPM_PARSE_TCPSEQ_NUM       (0x020000)	/* parse TCP Seq num */
+#define                 TPM_PARSE_TCPACK_NUM       (0x040000)	/* parse TCP Ack num */
+#define                 TPM_PARSE_TCPOFFSET        (0x080000)	/* parse TCP Offset */
+#define                 TPM_PARSE_TCPFLAGS         (0x100000)	/* parse TCP Flags */
+#define                 TPM_PARSE_TCPWIN           (0x200000)	/* parse TCP window */
+#define                 TPM_PARSE_TCPURGTPTR       (0x400000)	/* parse TCP urgent pointer */
+
+#define                 TPM_IPv6_PARSE_ICMP_TYPE         (0x20000)	/* parse IPv6 ICMP Type */
+#define                 TPM_IPv6_PARSE_ICMP_CODE         (0x40000)	/* parse IPv6 ICMP Code */
+
+typedef uint32_t tpm_pncl_parse_bm_t;
+
+#define                 TPM_PNC_RI_DISC_BIT             (0)
+#define                 TPM_PNC_RI_L4_OFF_BIT           (1)
+#define                 TPM_PNC_RI_L3_OFF_BIT           (3)
+#define                 TPM_PNC_RI_L3_FF_BIT            (5)
+#define                 TPM_PNC_RI_MAC_LEARN_BIT        (9)/*Just for media convert MAC learning*/
+#define                 TPM_PNC_RI_MC_BIT               (10)
+#define                 TPM_PNC_RI_BC_BIT               (11)
+#define                 TPM_PNC_RI_UC_BIT               (12)
+#define                 TPM_PNC_RI_PPPOE_BIT            (13)
+#define                 TPM_PNC_RI_MH_BIT_14            (14)
+#define                 TPM_PNC_RI_MH_BIT_15            (15)
+#define                 TPM_PNC_RI_MH_BIT_16            (16)
+#define                 TPM_PNC_RI_MH_BIT_17            (17)
+/* BIT18 is used by NFP */
+#define                 TPM_PNC_RI_VLAN_BIT             (19)
+#define                 TPM_PNC_RI_RX_SPECIAL_BIT       (20)
+#define                 TPM_PNC_RI_TRAP_BIT             (21) /* Internal to TPM, driver is not aware of this */
+
+typedef struct {
+	uint32_t mh_set;
+	uint32_t mh_reg;
+} tpm_pncl_mh_reg_t;
+
+typedef struct {
+	tpm_src_port_type_t src_port;	/* Specific UNI port in MH/DSA Tag */
+	tpm_l2_acl_key_t l2_key;	/* L2 fields to parse */
+	tpm_l3_type_key_t l3_key;	/* L3 fields to parse */
+	tpm_ipv4_acl_key_t ipv4_key;	/* IPv4 fields to parse */
+	tpm_ipv4_add_key_t ipv4_add_key;	/* Additional IPv4 fields to parse, that are not exposed to the API */
+	tpm_ipv6_acl_key_t ipv6_key;	/* IPv6 fields to parse */
+	tpm_ipv6_add_key_t ipv6_add_key;	/* Additional IPv6 fields to parse, that are not exposed to the API */
+	tpm_tcp_key_t tcp_key;	/* TCP fields to parse */
+	tpm_l4_ports_key_t l4_ports_key;	/* L4 Ports to parse */
+	tpm_ipv6_gen_acl_key_t ipv6_gen_key;
+	tpm_ipv6_addr_key_t ipv6_dip_key;
+} tpm_pncl_pkt_key_t;
+
+/* Structure indicates next logical offset.  There are few type of offset,
+ * Either one of the L1/L2/L3 Header Offsets, or a specific sub-field in a header.
+ * Specific sub-field
+ */
+typedef struct {
+	tpm_pnc_ranges_t range_id;	/* Determine which pnc range it is working on */
+	tpm_pncl_offset_base_t offset_base;	/* Determine if one of L1/L2/L3 Header offset, or specific sub-field offset */
+	union {
+		tpm_pncl_parse_bm_t l2_subf;	/* Specific sub-field to offset to, if empty, start at offset_base */
+		tpm_pncl_parse_bm_t l3_subf;	/* Specific sub-field to offset to, if empty, start at offset_base */
+		tpm_pncl_parse_bm_t ipv4_subf;	/* Specific sub-field to offset to, if empty, start at offset_base */
+		tpm_pncl_parse_bm_t ipv6_subf;	/* Specific sub-field to offset to, if empty, start at offset_base */
+		tpm_pncl_parse_bm_t subf;	/* Easy for coding, we can use it in any case */
+		tpm_pncl_parse_bm_t tcp_subf;	/* Specific sub-field to offset to, if empty, start at offset_base */
+	} offset_sub;
+} tpm_pncl_offset_t;
+
+typedef struct {
+	uint32_t lu_id;
+	tpm_gmac_bm_t port_ids;	/* GMAC(s) relevant to this entry */
+	tpm_pncl_offset_t start_offset;	/* Single bit raised to indicate start of packet */
+	tpm_pncl_pkt_key_t pkt_key;
+	tpm_pncl_parse_bm_t l2_parse_bm;	/* L2 Parsing bitmap for TCAM entry */
+	tpm_pncl_parse_bm_t l3_parse_bm;	/* L2 Parsing bitmap for TCAM entry */
+	tpm_pncl_parse_bm_t ipv4_parse_bm;	/* IPV4 Parsing bitmap for TCAM entry */
+	tpm_pncl_parse_bm_t ipv6_parse_bm;	/* IPV6 Parsing bitmap for TCAM entry */
+	tpm_pncl_parse_bm_t tcp_parse_bm;	/* TCP Parsing bitmap for TCAM entry */
+	tpm_pncl_parse_bm_t l4_parse_bm;	/* UDP/TCP L4 ports Parsing bitmap for TCAM entry */
+	uint32_t add_info_data;
+	uint32_t add_info_mask;
+} tpm_pncl_tcam_data_t;
+
+typedef struct {
+	uint32_t gem_port;
+	uint32_t mod_cmd;
+	tpm_pnc_trg_t pnc_target;
+} tpm_pncl_flowid_t;
+
+typedef struct {
+	/* Next LU */
+	uint32_t next_lu_id;
+	uint32_t next_lu_off_reg;
+
+	/* Next Shift Offset */
+	tpm_pncl_offset_t next_offset;	/* Next Offset Sub-field */
+	uint32_t shift_updt_reg;
+	/* Queue Update */
+	uint32_t pnc_queue;	/* pnc_queue=TPM_PNCL_NO_QUEUE_UPDATE -  don't set queue */
+
+	/* Sram ResultInfo&FlowId update Bitmap */
+	tpm_pncl_sram_updt_bm_t sram_updt_bm;
+	tpm_pncl_mh_reg_t mh_reg;
+	tpm_pncl_l3_type_t l3_type;
+	tpm_pncl_l4_type_t l4_type;
+	uint32_t pkt_col;
+	/* Add Info Update */
+	uint32_t add_info_data;
+	uint32_t add_info_mask;
+	/* flowid values */
+	tpm_pncl_flowid_t flow_id_sub;
+} tpm_pncl_sram_data_t;
+
+typedef struct {
+	tpm_pncl_tcam_data_t pncl_tcam;
+	tpm_pncl_sram_data_t pncl_sram;
+} tpm_pncl_pnc_full_t;
+
+/*************************************************************/
+/*               APIs                                        */
+/*************************************************************/
+
+int32_t tpm_pncl_pkt_trap(uint32_t entry, uint32_t lu_id, tpm_gmac_bm_t gmac_bm);
+int32_t tpm_pncl_pkt_drop(uint32_t entry, uint32_t lu_id, tpm_gmac_bm_t gmac_bm);
+int32_t tpm_pncl_range_reset(tpm_pnc_ranges_t range_id);
+int32_t tpm_pncl_entry_set(uint32_t pnc_entry, tpm_pncl_pnc_full_t *pnc_data);
+int32_t tpm_pncl_entry_insert(uint32_t pnc_ins_entry, uint32_t pnc_stop_entry, tpm_pncl_pnc_full_t *pnc_data);
+int32_t tpm_pncl_update_sram(uint32_t pnc_entry, tpm_pncl_pnc_full_t *pnc_data);
+int32_t tpm_pncl_init_cnm_main_ety_ipv6(uint32_t entry_id, tpm_db_ctc_cm_ipv6_parse_win_t ctc_cm_ipv6_parse_win);
+
+int32_t tpm_pncl_entry_delete(uint32_t pnc_del_entry, uint32_t pnc_stop_entry);
+int32_t tpm_pncl_entry_reset(uint32_t pnc_entry);
+
+int32_t tpm_proc_trg_port_gmac_map(tpm_trg_port_type_t trg_port, tpm_gmacs_enum_t *gmac_port);
+
+int32_t tpm_pncl_tcam_map(tpm_pncl_tcam_data_t *tcam_in, tpm_tcam_all_t *tcam_out);
+
+int32_t tpm_pncl_sram_map(tpm_pncl_sram_data_t *sram_in, tpm_sram_all_t *sram_out, tpm_pncl_tcam_data_t *tcam_in);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* _TPM_PNCL_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.c
new file mode 100755
index 0000000..caa9ea0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.c
@@ -0,0 +1,2537 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_print.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.3
+*
+*
+*******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_sysfs_utils.h"
+
+/*TODO - currently some printing funtions are directly accessing DB */
+extern tpm_db_t tpm_db;
+
+#define DWORD_LEN       32
+
+/* start offset of api_dump_ipv4_parse_bm, should be bigger than l2_parse_bm
+   right now the biggest l2_parse_bm is TPM_L2_PARSE_GEMPORT with offset 8
+ */
+#define API_DUMP_IPV4_PARSE_BM_START       12
+
+/* offset of api_dump_ipv6_parse_bm, should be bigger than ipv4_parse_bm + API_DUMP_IPV4_PARSE_BM_START
+   right now the biggest ipv4_parse_bm is TPM_IPv4_PARSE_PROTO with offset 4
+ */
+#define API_DUMP_IPV6_PARSE_BM_START       24
+
+#define TPM_DBVAL_CON(dbval)	((dbval == TPM_DB_VALID) ? TPM_TRUE : TPM_FALSE)
+#define DIR2STR(dir)		((dir == TPM_DIR_DS) ? "DS" : "US")
+#define IF_ERROR(ret)		\
+		if (ret != TPM_DB_OK) {\
+			TPM_OS_ERROR(TPM_CLI_MOD, "%s(%d):  recev'd error code (%d)\n", __func__, __LINE__, ret);\
+			return;\
+		}
+
+db_enum_string_t tpm_db_chip_conn_str[] = {
+	BuildEnumString(TPM_CONN_DISC),
+	BuildEnumString(TPM_CONN_QSGMII),
+	BuildEnumString(TPM_CONN_FE_PHY),
+	BuildEnumString(TPM_CONN_GE_PHY),
+	BuildEnumString(TPM_CONN_RGMII1),
+	BuildEnumString(TPM_CONN_RGMII2),
+};
+
+db_enum_string_t tpm_db_int_conn_str[] = {
+	BuildEnumString(TPM_INTCON_GMAC0),
+	BuildEnumString(TPM_INTCON_GMAC1),
+	BuildEnumString(TPM_INTCON_SWITCH),
+};
+
+db_enum_string_t tpm_db_sched_str[] = {
+	BuildEnumString(TPM_SCHED_SP),
+	BuildEnumString(TPM_SCHED_WRR),
+};
+
+db_enum_string_t tpm_db_txq_owner_str[] = {
+	BuildEnumString(TPM_Q_OWNER_CPU),
+	BuildEnumString(TPM_Q_OWNER_GMAC0),
+	BuildEnumString(TPM_Q_OWNER_GMAC1),
+	BuildEnumString(TPM_Q_OWNER_PMAC),
+};
+
+db_enum_string_t tpm_db_gmac_conn_str[] = {
+	BuildEnumString(TPM_GMAC_CON_DISC),
+	BuildEnumString(TPM_GMAC_CON_QSGMII),
+	BuildEnumString(TPM_GMAC_CON_SWITCH_4),
+	BuildEnumString(TPM_GMAC_CON_SWITCH_5),
+	BuildEnumString(TPM_GMAC_CON_SWITCH_6),
+	BuildEnumString(TPM_GMAC_CON_RGMII1),
+	BuildEnumString(TPM_GMAC_CON_RGMII2),
+	BuildEnumString(TPM_GMAC_CON_GE_PHY),
+};
+
+db_enum_string_t tpm_db_gmac_func_str[] = {
+	BuildEnumString(TPM_GMAC_FUNC_NONE),
+	BuildEnumString(TPM_GMAC_FUNC_LAN),
+	BuildEnumString(TPM_GMAC_FUNC_WAN),
+	BuildEnumString(TPM_GMAC_FUNC_LAN_AND_WAN),
+	BuildEnumString(TPM_GMAC_FUNC_VIRT_UNI),
+	BuildEnumString(TPM_GMAC_FUNC_LAN_UNI),
+};
+
+db_enum_string_t tpm_pnc_ranges_str[] = {
+	BuildEnumString(TPM_PNC_MNGMT_DS),
+	BuildEnumString(TPM_PNC_MAC_LEARN),
+	BuildEnumString(TPM_PNC_CPU_WAN_LPBK_US),
+	BuildEnumString(TPM_PNC_NUM_VLAN_TAGS),
+	BuildEnumString(TPM_PNC_VIRT_UNI),
+	BuildEnumString(TPM_PNC_MULTI_LPBK),
+	BuildEnumString(TPM_PNC_LOOP_DET_US),
+	BuildEnumString(TPM_PNC_L2_MAIN),
+	BuildEnumString(TPM_PNC_ETH_TYPE),
+	BuildEnumString(TPM_PNC_IGMP),
+	BuildEnumString(TPM_PNC_IPV4_MC_DS),
+	BuildEnumString(TPM_PNC_IPV4_MAIN),
+	BuildEnumString(TPM_PNC_TCP_FLAG),
+	BuildEnumString(TPM_PNC_TTL),
+	BuildEnumString(TPM_PNC_IPV4_PROTO),
+	BuildEnumString(TPM_PNC_IPV4_FRAG),
+	BuildEnumString(TPM_PNC_IPV4_LEN),
+	BuildEnumString(TPM_PNC_IPV6_HOPL),
+	BuildEnumString(TPM_PNC_IPV6_GEN),
+	BuildEnumString(TPM_PNC_IPV6_MC_SIP),
+	BuildEnumString(TPM_PNC_IPV6_DIP),
+	BuildEnumString(TPM_PNC_IPV6_MC_DS),
+	BuildEnumString(TPM_PNC_IPV6_NH),
+	BuildEnumString(TPM_PNC_IPV6_L4_MC_DS),
+	BuildEnumString(TPM_PNC_IPV6_L4),
+	BuildEnumString(TPM_PNC_CNM_IPV4_PRE),
+	BuildEnumString(TPM_PNC_CNM_MAIN),
+	BuildEnumString(TPM_PNC_CATCH_ALL),
+};
+
+db_enum_string_t tpm_api_range_type_str[] = {
+	BuildEnumString(TPM_RANGE_TYPE_ACL),
+	BuildEnumString(TPM_RANGE_TYPE_TABLE),
+};
+
+db_enum_string_t tpm_db_pnc_last_init_str[] = {
+	BuildEnumString(TPM_PNC_RNG_LAST_INIT_DEF),
+	BuildEnumString(TPM_PNC_RNG_LAST_INIT_DROP),
+	BuildEnumString(TPM_PNC_RNG_LAST_INIT_TRAP),
+};
+
+static tpm_str_map_t api_section_str[] = {
+	{TPM_L2_PRIM_ACL, "TPM_L2_PRIM_ACL"},
+	{TPM_L3_TYPE_ACL, "TPM_L3_TYPE_ACL"},
+	{TPM_IPV4_ACL, "TPM_IPV4_ACL"},
+	{TPM_IPV4_MC, "TPM_IPV4_MC"},
+	{TPM_IPV6_GEN_ACL, "TPM_IPV6_GEN_ACL"},
+	{TPM_IPV6_DIP_ACL, "TPM_IPV6_DIP_ACL"},
+	{TPM_IPV6_NH_ACL, "TPM_IPV6_NH_ACL"},
+	{TPM_L4_ACL, "TPM_L4_ACL"},
+};
+
+static tpm_str_map_t api_type_str[] = {
+	{TPM_API_MGMT, "MNGMT"},
+	{TPM_API_CPU_LOOPBACK, "CPU_LOOPBACK"},
+	{TPM_API_L2_PRIM, "L2      "},
+	{TPM_API_L3_TYPE, "L3      "},
+	{TPM_API_IPV4, "IPV4    "},
+	{TPM_API_IPV4_MC, "IPV4_MC "},
+	{TPM_API_IPV6_GEN, "IPV6_GEN"},
+	{TPM_API_IPV6_DIP, "IPV6_DIP"},
+	{TPM_API_IPV6_NH, "IPV6_NH "},
+	{TPM_API_IPV6_L4, "L4      "},
+};
+
+
+/********************************************************************************/
+/*                                Print Utils                                   */
+/********************************************************************************/
+char *db_mac_to_str(uint8_t * addr, char *str)
+{
+	if ((str != NULL) && (addr != NULL)) {
+		str[0] = '\0';
+		sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+		return str;
+	}
+
+	return NULL;
+}
+
+char *db_ipv4_to_str(uint8_t * ipaddr, char *str)
+{
+	if ((str != NULL) && (ipaddr != NULL)) {
+		str[0] = '\0';
+		sprintf(str, "%u.%u.%u.%u", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+		return str;
+	}
+
+	return NULL;
+}
+
+char *db_ipv6_to_str(uint8_t * ipaddr, char *str)
+{
+	int i, j;
+	uint16_t addr[DB_IPV6_ADDR_LEN / 2];
+
+	if ((str != NULL) && (ipaddr != NULL)) {
+		for (i = 0, j = 0; i < DB_IPV6_ADDR_LEN; j++) {
+			addr[j] = (ipaddr[i] << 8) | ipaddr[i + 1];
+			i += 2;
+		}
+
+		str[0] = '\0';
+		sprintf(str,
+			"%x:%x:%x:%x:%x:%x:%x:%x",
+			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]);
+		return str;
+	}
+
+	return NULL;
+}
+
+/*******************************************************************************
+* api_sec_to_str()
+*
+* DESCRIPTION:      Convert api section to string
+*
+* INPUTS:
+* api_section      - API Section to retrieve configuration for
+*
+* RETURNS:
+* On success, return pointer to entry in api_section_str[], on error return NULL.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static uint8_t *api_sec_to_str(tpm_api_sections_t api_section)
+{
+	uint32_t i;
+
+	for (i = 0; i < (sizeof(api_section_str) / sizeof(tpm_str_map_t)); i++) {
+		if (api_section_str[i].enum_in == api_section)
+			return (&(api_section_str[i].str_out[0]));
+	}
+	return (NULL);
+}
+
+/*******************************************************************************
+* api_type_to_str()
+*
+* DESCRIPTION:      Convert api section to string
+*
+* INPUTS:
+* tpm_api_type_t    - API Type to retrieve configuration for
+*
+* RETURNS:
+* On success, return pointer to entry in api_type_str[], on error return NULL.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static uint8_t *api_type_to_str(tpm_api_type_t api_type)
+{
+	uint32_t i;
+
+	for (i = 0; i < (sizeof(api_type_str) / sizeof(tpm_str_map_t)); i++) {
+		if (api_type_str[i].enum_in == api_type)
+			return (&(api_type_str[i].str_out[0]));
+	}
+	return (NULL);
+}
+
+/*******************************************************************************
+* pnc_rng_to_str()
+*
+* DESCRIPTION:      Convert Pnc Range  to string
+*
+* INPUTS:
+* api_section      - API Section to retrieve configuration for
+*
+* RETURNS:
+* On success, return pointer to entry in api_section_str[], on error return NULL.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static uint8_t *pnc_rng_to_str(tpm_pnc_ranges_t range)
+{
+	uint32_t i;
+
+	for (i = 0; i < (sizeof(tpm_pnc_ranges_str) / sizeof(db_enum_string_t)); i++) {
+		if (tpm_pnc_ranges_str[i].enumPar == range)
+			return (&(tpm_pnc_ranges_str[i].enumString[0]));
+	}
+	return (NULL);
+}
+
+/*******************************************************************************
+* tpm_print_mac_key()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* mac_key       - Print mac key
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_mac_key(tpm_mac_key_t *mac_key)
+{
+	char smac_str[DB_MAC_STR_LEN] = { '\0' };
+	char dmac_str[DB_MAC_STR_LEN] = { '\0' };
+
+	printk("=========================================\n");
+	printk("          DA                SA           \n");
+	printk("        DA mask           SA mask        \n");
+	printk("=========================================\n");
+	printk("  %s   %s\n", db_mac_to_str(mac_key->mac_da, dmac_str),
+	       db_mac_to_str(mac_key->mac_sa, smac_str));
+	printk("  %s   %s\n", db_mac_to_str(mac_key->mac_da_mask, dmac_str),
+	       db_mac_to_str(mac_key->mac_sa_mask, smac_str));
+	printk("=========================================\n");
+	return;
+}
+
+/*******************************************************************************
+* tpm_print_cpu_lpbk_entry()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*   None
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_cpu_lpbk_entry(void)
+{
+	uint16_t flow_id;
+	tpm_cpu_loopback_t *lpbk_entry = NULL;
+
+	print_horizontal_line(60);
+	printk("  Index  trg_port  trg_queue  gem_port  rule_idx  mod_idx \n");
+	print_horizontal_line(60);
+
+	for (flow_id = 0; flow_id < TPM_MAX_CPU_LOOPBACK_NUM; flow_id++) {
+		lpbk_entry = tpm_proc_get_loopback_entry(flow_id);
+
+		if ((lpbk_entry != NULL) && (lpbk_entry->in_use == TPM_TRUE)) {
+			printk("  %4.4d   0x%4.4x    %1.1d          %4.4d      %4.4d      %4.4d \n",
+			       flow_id, lpbk_entry->trg_port, lpbk_entry->trg_queue,
+			       lpbk_entry->gem_port, lpbk_entry->rule_idx, lpbk_entry->mod_idx);
+		}
+
+	}
+
+	print_horizontal_line(60);
+}
+
+/*******************************************************************************
+* tpm_print_tcam_lu_entry()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*   None
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_tcam_lu_entry(uint32_t owner_id, uint32_t api_group, uint32_t lu_num, uint32_t lu_reset)
+{
+	uint16_t rule_num;
+	tpm_error_code_t ret_code;
+	uint16_t valid_num;
+	tpm_api_entry_count_t count_array[TPM_MAX_LU_ENTRY_NUM];
+	uint16_t unrelated_num;
+
+	ret_code = tpm_get_pnc_lu_entry(owner_id, api_group, (uint16_t) lu_num, lu_reset, &valid_num,
+					count_array, &unrelated_num);
+
+	if (ret_code != TPM_RC_OK) {
+		printk(KERN_ERR "Failed to call tpm_count_get_pnc_lu_entry, ret_code[%d] \n", ret_code);
+		return;
+	}
+
+	printk("\n");
+	print_horizontal_line(60);
+	printk("  Input owner_id[%d], api_group[%d], lu_num[%d] lu_reset[%d]\n",
+	       owner_id, api_group, lu_num, lu_reset);
+	printk("  output valid_num[%d], unrelated_num[%d]\n", valid_num, unrelated_num);
+	print_horizontal_line(60);
+	printk("  Index    rule_idx    hit_counter \n");
+	print_horizontal_line(60);
+
+	for (rule_num = 0; rule_num < valid_num; rule_num++) {
+		printk("  %4.4d     %4.4d        %6.6d\n",
+		       rule_num, count_array[rule_num].rule_idx, count_array[rule_num].hit_count);
+	}
+
+	print_horizontal_line(60);
+}
+/*******************************************************************************
+* tpm_print_pnc_all_hit_counters()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*   None
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_pnc_all_hit_counters(uint32_t                owner_id,
+				    tpm_api_type_t          api_type,
+				    uint32_t                high_thresh_pkts,
+				    uint8_t                 counters_reset,
+				    uint16_t                valid_counters,
+				    tpm_api_entry_count_t  *count_array)
+{
+	uint16_t              rule_num;
+
+	printk("\n");
+	print_horizontal_line(60);
+	printk("  Input owner_id[%d], api_type[%d], high_thresh_pkts[%d] counters_reset[%d]\n",
+	       owner_id, api_type, high_thresh_pkts, counters_reset);
+	printk("  Output valid_counters[%d]\n", valid_counters);
+	print_horizontal_line(60);
+	printk("  Index    rule_idx    hit_counter \n");
+	print_horizontal_line(60);
+
+	for (rule_num = 0; rule_num < valid_counters; rule_num++) {
+		printk("  %4.4d     %4.4d        %6.6d\n",
+		       rule_num, count_array[rule_num].rule_idx, count_array[rule_num].hit_count);
+	}
+
+	print_horizontal_line(60);
+}
+
+/*******************************************************************************
+* tpm_print_vlan_key()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* vlan_key      - Print CPU WAN loopback entry
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_vlan_key(tpm_vlan_key_t *vlan_key)
+{
+	print_horizontal_line(49);
+	printk("  TPID  VID  VID mask CFI CFI mask PBIT PBIT mask\n");
+	print_horizontal_line(49);
+	printk("  %4.4x  %4.4x  %4d   %4.4x    %1.1x     %1.1x      %2.2x     %2.2x\n",
+	       vlan_key->tpid, vlan_key->tpid_mask, vlan_key->vid, vlan_key->vid_mask,
+	       vlan_key->cfi, vlan_key->cfi_mask, vlan_key->pbit, vlan_key->pbit_mask);
+	print_horizontal_line(49);
+}
+
+/*******************************************************************************
+* tpm_print_ipv4_key()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* ipv4_key      - Print ipv4 key
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_ipv4_key(tpm_ipv4_acl_key_t *ipv4_key, tpm_ipv4_add_key_t *ipv4_add_key)
+{
+	printk("IPV4:\n");
+	printk("=======================================================\n");
+	printk("    DST_IP       SRC_IP     DSCP PROT L4_DST L4_SRC\n");
+	printk("=======================================================\n");
+	printk("  %02x.%02x.%02x.%02x  %02x.%02x.%02x.%02x   %02x   %02x   %02x     %02x\n"
+	       "  %02x.%02x.%02x.%02x  %02x.%02x.%02x.%02x   %02x \n",
+	       ipv4_key->ipv4_dst_ip_add[0], ipv4_key->ipv4_dst_ip_add[1], ipv4_key->ipv4_dst_ip_add[2],
+	       ipv4_key->ipv4_dst_ip_add[3], ipv4_key->ipv4_src_ip_add[0], ipv4_key->ipv4_src_ip_add[1],
+	       ipv4_key->ipv4_src_ip_add[2], ipv4_key->ipv4_src_ip_add[3], ipv4_key->ipv4_dscp, ipv4_key->ipv4_proto,
+	       ipv4_key->l4_dst_port, ipv4_key->l4_src_port, ipv4_key->ipv4_dst_ip_add_mask[0],
+	       ipv4_key->ipv4_dst_ip_add_mask[1], ipv4_key->ipv4_dst_ip_add_mask[2], ipv4_key->ipv4_dst_ip_add_mask[3],
+	       ipv4_key->ipv4_src_ip_add_mask[0], ipv4_key->ipv4_src_ip_add_mask[1], ipv4_key->ipv4_src_ip_add_mask[2],
+	       ipv4_key->ipv4_src_ip_add_mask[3], ipv4_key->ipv4_dscp_mask);
+	if (ipv4_add_key != NULL) {
+		printk("=======================================================\n");
+		printk("    IP_VER  IP_IHL  IP_LEN  IP_FLAG  IP_FRAG IP_TTL \n");
+		printk("=======================================================\n");
+		printk("     %01x        %01x     %04x      %02x      %04x   %02x   \n"
+		       "     %01x        %01x      %01x        %01x        %01x \n",
+		       ipv4_add_key->ipv4_ver, ipv4_add_key->ipv4_ihl, ipv4_add_key->ipv4_totlen,
+		       ipv4_add_key->ipv4_flags, ipv4_add_key->ipv4_frag_offset, ipv4_add_key->ipv4_ttl,
+		       ipv4_add_key->ipv4_ver_mask, ipv4_add_key->ipv4_ihl_mask, ipv4_add_key->ipv4_totlen_mask,
+		       ipv4_add_key->ipv4_flags_mask, ipv4_add_key->ipv4_frag_offset_mask);
+		printk("=======================================================\n");
+	}
+}
+
+/*******************************************************************************
+* tpm_print_l2_key()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* l2_key      - Print l2 key
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_l2_key(tpm_l2_acl_key_t *l2_key)
+{
+	printk("\nL2 KEY:\n");
+
+	tpm_print_mac_key(&(l2_key->mac));
+	TPM_OS_DEB_WAIT();
+	printk("\nVLAN 1:\n");
+	tpm_print_vlan_key(&(l2_key->vlan1));
+	printk("\nVLAN 2:\n");
+	tpm_print_vlan_key(&(l2_key->vlan2));
+	TPM_OS_DEB_WAIT();
+	printk("L2 ethertype(%04x), pppoe_ses(%d), pppoe_proto(%x)\n",
+	       l2_key->ether_type, l2_key->pppoe_hdr.ppp_session, l2_key->pppoe_hdr.ppp_proto);
+	printk("gem_port(%x)\n", l2_key->gem_port);
+	printk("=======================================================\n");
+}
+
+/*******************************************************************************
+* tpm_print_l3_key()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* l3_key      - Print l2 key
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_l3_key(tpm_l3_type_key_t *l3_key)
+{
+	printk("L3 KEY:\n");
+	printk("L3 ethertype(%04x), pppoe_ses(%d), pppoe_proto(%x)\n",
+	       l3_key->ether_type_key, l3_key->pppoe_key.ppp_session, l3_key->pppoe_key.ppp_proto);
+	printk("=======================================================\n");
+}
+
+/*******************************************************************************
+* tpm_print_etherports()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+* vlan_key      - Print vlan key
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_etherports(void)
+{
+	uint32_t i;
+
+	printk("======================================================\n");
+	printk(" TPM ethernet ports:                                  \n");
+	printk("======================================================\n");
+	printk("     ext   switch       chip             internal     \n");
+	printk("                     connection         connection    \n");
+	printk("======================================================\n");
+	for (i = 0; i < TPM_MAX_NUM_ETH_PORTS; i++) {
+		if (tpm_db.eth_ports[i].valid == TPM_DB_VALID) {
+			printk(" %1d   %3d   ", i, tpm_db.eth_ports[i].port_src);
+
+			if (tpm_db.eth_ports[i].int_connect == TPM_INTCON_SWITCH)
+				printk(" %3d    ", tpm_db.eth_ports[i].switch_port);
+			else
+				printk("%8s", " ");
+
+			printk("%15s  %17s \n",
+			       tpm_db_chip_conn_str[tpm_db.eth_ports[i].chip_connect].enumString,
+			       tpm_db_int_conn_str[tpm_db.eth_ports[i].int_connect].enumString);
+		}
+	}
+	printk("======================================================\n");
+	return;
+}
+
+/*******************************************************************************
+* tpm_print_rx_modules()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_rx_modules(void)
+{
+	uint32_t i, j, q_val, q_size;
+
+	printk("============================================================\n");
+	printk(" TPM GMAC RX Queues:                                            \n");
+	printk("============================================================\n");
+	printk(" Queue  size\n");
+	printk("============================================================\n");
+
+	for (i = 0; i < TPM_MAX_NUM_GMACS; i++) {
+		if (tpm_db_gmac_rx_val_get(i)) {
+			printk("GMAC - %d\n", i);
+
+			for (j = 0; j < TPM_MAX_NUM_RX_QUEUE; j++) {
+
+				tpm_db_gmac_rx_q_conf_get(i, j, &q_val, &q_size);
+				if (q_val)
+					printk("q%1d  rxq_size %4d\n", j, q_size);
+			}
+		}
+	}
+	printk("======================================================\n");
+	return;
+}
+
+/*******************************************************************************
+* tpm_print_tx_modules()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+* RETURNS:
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpm_print_tx_modules(void)
+{
+	uint32_t i, j;
+
+	printk("============================================================\n");
+	printk(" TPM TX modules:                                            \n");
+	printk("============================================================\n");
+	printk(" Queue      Sched          Q-owner      owner   size  weight\n");
+	printk("                                        q-num               \n");
+	printk("============================================================\n");
+
+	for (i = 0; i < TPM_MAX_NUM_TX_PORTS; i++) {
+		if (tpm_db.gmac_tx[i].valid == TPM_DB_VALID) {
+			printk("TX Device - %d\n", i);
+
+			for (j = 0; j < TPM_MAX_NUM_TX_QUEUE; j++) {
+				if (tpm_db.gmac_tx[i].tx_queue[j].valid == TPM_DB_VALID) {
+					printk("   %1d   %13s  %17s   %1d     %4d  %5d\n",
+					       j,
+					       tpm_db_sched_str[tpm_db.gmac_tx[i].tx_queue[j].sched_method].enumString,
+					       tpm_db_txq_owner_str[tpm_db.gmac_tx[i].tx_queue[j].queue_owner].
+					       enumString, tpm_db.gmac_tx[i].tx_queue[j].owner_queue_num,
+					       tpm_db.gmac_tx[i].tx_queue[j].queue_size,
+					       tpm_db.gmac_tx[i].tx_queue[j].queue_weight);
+				}
+			}
+
+		}
+	}
+	printk("======================================================\n");
+	return;
+}
+
+void tpm_print_gmac_config(void)
+{
+	printk("=========================================================\n");
+	printk(" TPM GMAC configuration:                                 \n");
+	printk("=========================================================\n");
+	printk("    Num                     Connection                   \n");
+	printk(" tcont/llid         G0                      G1           \n");
+	printk("    %4.4x    %18s  %18s\n",
+	       tpm_db.num_valid_tcont_llid,
+	       tpm_db_gmac_conn_str[tpm_db.gmac_port_conf[0].conn].enumString,
+	       tpm_db_gmac_conn_str[tpm_db.gmac_port_conf[1].conn].enumString);
+	printk("                    mh_en                  mh_en    \n");
+	printk("                      %1d                      %1d\n",
+	       tpm_db.gmac_mh_en[1], tpm_db.gmac_mh_en[0]);
+
+	printk("====================================================\n");
+	return;
+}
+
+void tpm_print_gmac_func(void)
+{
+	printk("=============================================================\n");
+	printk(" TPM GMAC functions:                                         \n");
+	printk("=============================================================\n");
+	printk("        PMAC                 G0                   G1         \n");
+	printk("=============================================================\n");
+	printk(" %18s  %18s  %18s\n",
+	       tpm_db_gmac_func_str[tpm_db.gmac_func[2]].enumString,
+	       tpm_db_gmac_func_str[tpm_db.gmac_func[0]].enumString,
+	       tpm_db_gmac_func_str[tpm_db.gmac_func[1]].enumString);
+	printk("====================================================\n");
+	return;
+}
+
+void tpm_print_bm_buffers(void)
+{
+	uint32_t i, valid, large_pkt_buf, small_pkt_buf;
+
+	printk("=============================================================\n");
+	printk(" Buffer Mngmt Pools:                                         \n");
+	printk("=============================================================\n");
+	printk("        Pool   cfg_val  large_bufs   small_bufs   \n");
+	printk("=============================================================\n");
+	for (i = 0; i < TPM_MAX_NUM_GMACS; i++) {
+		tpm_db_gmac_bm_bufs_conf_get(i, &valid, &large_pkt_buf, &small_pkt_buf);
+		printk("          %d     %d          %d          %d\n",
+		       i, valid, large_pkt_buf, small_pkt_buf);
+	}
+	printk("====================================================\n");
+	return;
+}
+
+void tpm_print_igmp(void)
+{
+#if 0
+	printk("===================\n");
+	printk(" IGMP:             \n");
+	printk("===================\n");
+	printk("Valid  Snoop  CPU-q\n");
+	printk("===================\n");
+	printk(" %3s    %3d    %2d \n",
+	       (tpm_db.igmp_def.valid == TPM_DB_VALID ? "yes" : "no"),
+	       tpm_db.igmp_def.igmp_snoop, tpm_db.igmp_def.igmp_cpu_queue);
+	printk("========================\n");
+	return;
+#endif
+
+	printk("===================\n");
+	printk(" Multicast:   value\n");
+	printk("===================\n");
+	printk("Filter mode        %d\n", tpm_db.igmp_def.filter_mode);
+	printk("Per UNI Vlan Xlate %d\n", tpm_db.igmp_def.per_uni_vlan_xlat);
+	printk("MC PPPoE enable    %d\n", tpm_db.igmp_def.mc_pppoe_enable);
+	printk("MC hwf queue       %d\n", tpm_db.igmp_def.mc_hwf_queue);
+	printk("MC cpu queue       %d\n", tpm_db.igmp_def.mc_cpu_queue);
+	printk("===================\n");
+	return;
+}
+
+void tpm_print_misc(void)
+{
+	char *gmac_name[] = {"GMAC_0","GMAC_1","PMAC"};
+	char *pon_type[] = {"EPON","GPON","P2P","NONE"};
+
+	printk("==========================\n");
+	printk(" TPM misc:          value \n");
+	printk("==========================\n");
+	printk("OMCI ETY            %4.4x\n", tpm_db.init_misc.omci_etype);
+	printk("Debug port          %4d\n", tpm_db.init_misc.pnc_init_debug_port);
+	printk("PON type            %s\n", pon_type[tpm_db.init_misc.pon_type]);
+
+	if ((tpm_db.init_misc.backup_wan < TPM_MAX_GMAC) && (tpm_db.init_misc.backup_wan >= TPM_ENUM_GMAC_0))
+		printk("Backup WAN          %s\n", gmac_name[tpm_db.init_misc.backup_wan]);
+	else
+		printk("Backup WAN          N/A");
+	printk("DS MH select source %4d\n", tpm_db.init_misc.ds_mh_set_conf);
+	printk("CFG PNC parse       %4d\n", tpm_db.init_misc.cfg_pnc_parse);
+	printk("CPU loopback        %4d\n", tpm_db.init_misc.cpu_loopback);
+	printk("Double Tag support  %4d\n", tpm_db.init_misc.dbl_tag);
+	printk("IPV6 5T enable      %4d\n", tpm_db.init_misc.ipv6_5t_enable);
+	printk("Virtual UNI-en:%4d uni-src %4d switch port %4d\n",
+	       tpm_db.func_profile.virt_uni_info.enabled,
+	       tpm_db.func_profile.virt_uni_info.uni_port,
+	       tpm_db.func_profile.virt_uni_info.switch_port);
+	printk("===============================\n");
+	printk("TRACE DEBUG info    0x%08x\n", tpm_glob_trace);
+	printk("===============================\n");
+
+	return;
+}
+
+void tpm_print_owners(void)
+{
+
+	printk("\ntpm_print_owners : owners tables NOT USED YET \n");
+
+	return;
+}
+
+void tpm_print_vlan_etype(void)
+{
+	uint32_t i;
+
+	printk("========================\n");
+	printk(" VLAN ETYs:             \n");
+	printk("========================\n");
+	for (i = 0; i < TPM_NUM_VLAN_ETYPE_REGS; i++) {
+		if (tpm_db.vlan_etype[i].valid == TPM_DB_VALID)
+			printk(" %2d   %4.4x\n", i, tpm_db.vlan_etype[i].tpid_ether_type);
+	}
+
+	return;
+}
+
+void tpm_print_valid_api_sections(void)
+{
+	tpm_api_sections_t cur_section = -1, next_section;
+	int32_t last_valid;
+	int32_t ret_code;
+	uint32_t api_rng_size, num_valid_entries, tbl_start_ind;
+
+	printk("==================================================\n");
+	printk(" Valid API ranges:                         \n");
+	printk("==================================================\n");
+	printk("      Name       Size    Num     Last   Tbl\n");
+	printk("                         entries  valid  Start\n");
+	printk("==================================================\n");
+
+	/* Loop through valid API ranges and print them */
+	ret_code = tpm_db_api_section_val_get_next(cur_section, &next_section,
+						   &api_rng_size, &num_valid_entries, &last_valid, &tbl_start_ind);
+	IF_ERROR(ret_code);
+
+	while (next_section != TPM_INVALID_SECTION) {
+		printk("%15s  %4d    %4d    %4d    %4d\n",
+		       api_sec_to_str(next_section), api_rng_size, num_valid_entries, last_valid, tbl_start_ind);
+
+		cur_section = next_section;
+		ret_code = tpm_db_api_section_val_get_next(cur_section, &next_section,
+							   &api_rng_size, &num_valid_entries, &last_valid,
+							   &tbl_start_ind);
+		IF_ERROR(ret_code);
+	}
+	printk("===========================================\n");
+	return;
+}
+
+void tpm_print_full_api_section(tpm_api_sections_t api_section)
+{
+	uint32_t rule_idx, bi_dir, i;
+	int32_t ret_code;
+	int32_t cur_rule, next_rule, last_valid;
+	uint32_t api_rng_size, num_valid_entries, tbl_start_ind;
+	tpm_pnc_ranges_t prim_pnc_range;
+	tpm_rule_entry_t api_data;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_conn_t pnc_con;
+
+	/* Print API Range Header */
+	printk("====================================================\n");
+	printk(" Full API range:                          \n");
+	printk("====================================================\n");
+	printk("      Name       Size    Num     Last    Start \n");
+	printk("                         entries  valid     Ind  \n");
+	printk("====================================================\n");
+
+	ret_code =
+	    tpm_db_api_section_get(api_section, &api_rng_size, &num_valid_entries, &prim_pnc_range, &last_valid,
+				   &tbl_start_ind);
+	if (ret_code != TPM_OK) {
+		printk("%15s - invalid \n", api_sec_to_str(api_section));
+		return;
+	}
+
+	printk("%15s %4d    %4d    %4d    %4d\n",
+	       api_sec_to_str(api_section), api_rng_size, num_valid_entries, last_valid, tbl_start_ind);
+
+	cur_rule = -1;
+
+	tpm_db_api_entry_val_get_next(api_section, cur_rule, &next_rule, &rule_idx, &bi_dir,
+				      &api_data, &mod_con, &pnc_con);
+
+	printk("=========================================================\n");
+	printk("  Rule  Rule  Bi-dir  Mod  Mod |  Ranges    PnC    PnC   \n");
+	printk("  num   idx           cmd  bm  |  total    range  index  \n");
+	printk("=========================================================\n");
+
+	while (next_rule != -1) {
+		printk("  %3d  %5d   %3s    %3d  %2d    %4d",
+		       next_rule, rule_idx,
+		       (bi_dir ? "yes" : "no"), mod_con.mod_cmd_ind, mod_con.mod_cmd_mac, pnc_con.num_pnc_ranges);
+
+		for (i = 0; i < pnc_con.num_pnc_ranges; i++) {
+			printk("   %02d     %03d\n",
+			       pnc_con.pnc_conn_tbl[i].pnc_range, pnc_con.pnc_conn_tbl[i].pnc_index);
+		}
+
+		cur_rule = next_rule;
+		tpm_db_api_entry_val_get_next(api_section, cur_rule, &next_rule, &rule_idx, &bi_dir,
+					      &api_data, &mod_con, &pnc_con);
+	}
+	printk("=================================================================\n");
+	return;
+}
+
+void tpm_print_valid_pnc_ranges(void)
+{
+	int32_t ret_code;
+	tpm_db_pnc_range_t range_data;
+	tpm_pnc_ranges_t cur_range, next_range;
+
+	/* Print PNC Range Header */
+	printk("==============================================================================================\n");
+	printk(" Valid PnC ranges:                                                                            \n");
+	printk("==============================================================================================\n");
+	printk(" Range                        LU   Res Size Aging LU      Range         API      RSRV  Free     Num         Last    \n");
+	printk("                                   Lvl      group skip  Start  End   Start  End  entr  entr     rsts        init        \n");
+	printk("==============================================================================================\n");
+
+	cur_range = -1;
+
+	ret_code = tpm_db_pnc_rng_val_get_next(cur_range, &next_range, &range_data);
+	IF_ERROR(ret_code);
+
+	while (next_range != -1) {
+		printk(" %24s    %2d   %2d %4d  %4d  %2d    %4d   %4d  %4d  %4d  %4d  %4d  %s\n",
+		       pnc_rng_to_str(next_range),
+		       range_data.pnc_range_conf.base_lu_id,
+		       range_data.pnc_range_conf.min_reset_level,
+		       range_data.pnc_range_conf.range_size,
+		       range_data.pnc_range_conf.cntr_grp,
+		       range_data.pnc_range_conf.lu_mask,
+		       range_data.pnc_range_conf.range_start,
+		       range_data.pnc_range_conf.range_end,
+		       range_data.pnc_range_conf.api_start,
+		       range_data.pnc_range_conf.api_end,
+		       range_data.pnc_range_oper.free_entries,
+		       range_data.pnc_range_oper.num_resets,
+		       tpm_db_pnc_last_init_str[range_data.pnc_range_conf.init_last_entry].enumString);
+		cur_range = next_range;
+		ret_code = tpm_db_pnc_rng_val_get_next(cur_range, &next_range, &range_data);
+		IF_ERROR(ret_code);
+	}
+	printk("================================================================================\n");
+	return;
+}
+
+void tpm_print_pnc_shadow_range(uint32_t valid_only, uint32_t start, uint32_t end)
+{
+	uint32_t i;
+	uint32_t valid_entry;
+	tpm_pnc_all_t pnc_data;
+
+	printk("======================================================================\n");
+	printk(" Valid PnC shadow range:                                              \n");
+	printk("======================================================================\n");
+
+	if ((end >= (TPM_PNC_SIZE)) || (start > end)) {
+		printk("Invalid params: start(%d) end(%d)\n", start, end);
+		return;
+	}
+
+	for (i = start; i <= end; i++) {
+		tpm_db_pnc_shdw_ent_get(i, &valid_entry, &pnc_data);
+		if ((valid_only == TPM_FALSE) || (valid_entry == TPM_TRUE)) {
+			printk("PNC Shadow Entry (%d)\n", i);
+			tpm_pnc_print_sw_entry(&pnc_data);
+		}
+	}
+	return;
+}
+
+void tpm_print_mh_port_vector_table(void)
+{
+	uint32_t i;
+
+	printk("======================================================================\n");
+	printk(" MH port vector table:                                                \n");
+	printk("======================================================================\n");
+	printk("=  REG#     UNI_VEC                 PNC_VEC               AMBER_VEC  =\n");
+	printk("======================================================================\n");
+
+	for (i = 0; i < TPM_TX_MAX_MH_REGS; i++) {
+		printk("= %02d      0x%05x                0x%08x                 0x%04x   ==\n",
+		       i, tpm_db.tpm_mh_port_vector_tbl[i].uni_vector,
+		       tpm_db.tpm_mh_port_vector_tbl[i].pnc_vector, tpm_db.tpm_mh_port_vector_tbl[i].amber_port_vector);
+	}
+	printk("======================================================================\n");
+	return;
+}
+
+void tpm_print_init_tables(void)
+{
+	tpm_print_etherports();
+	tpm_print_rx_modules();
+	tpm_print_tx_modules();
+	tpm_print_gmac_config();
+	tpm_print_gmac_func();
+	tpm_print_bm_buffers();
+	tpm_print_igmp();
+	tpm_print_misc();
+	tpm_print_owners();
+	tpm_print_vlan_etype();
+	tpm_print_mh_port_vector_table();
+}
+
+void tpm_print_api_dump_head(void)
+{
+	printk("==========================================================================================================================================================\n");
+	printk("=  Section    Rule   Rule   PNC     Src_Port     Parse_BM      Parse_Flag_BM     Next       Pkt_Action          Target_Port         Mod_BM        Mod.   =\n");
+	printk("=             No.    Ind.   Entry                                                Phase                       (Gem_Port)(Queue)                    Entry  =\n");
+	printk("==========================================================================================================================================================\n");
+}
+
+char *tpm_db_params_illegal_str = "??";
+
+char *tpm_db_api_type_str[TPM_MAX_API_TYPES] = {
+	"MGNT",
+	"MAC_LEARN",
+	"CPU_LPBK",
+	"L2",
+	"L3",
+	"IPV4",
+	"IPV4_MC",
+	"IPV6_GEN",
+	"IPV6_DIP",
+	"IPV6_MC",
+	"IPV6_NH",
+	"IPV6_L4",
+	"CTC_CNM"
+};
+
+char *tpm_db_src_port_str[] = {
+       "UNI_0",
+	"UNI_1",
+	"UNI_2",
+	"UNI_3",
+	"UNI_4",
+	"UNI_5",
+	"UNI_6",
+	"UNI_7",
+	"UNI_VIRT",
+	"WAN",
+	"UNI_ANY",
+	"PORT_ANY",
+};
+
+char *tpm_db_next_phase_str[] = {
+	"L2",
+	"L3",
+	"IPv4",
+	"IPv6_GEN",
+	"IPv6_DIP",
+	"IPv6_NH",
+	"IPV6_L4",
+	"CTC_CM",
+	"DONE",
+};
+
+tpm_str_map_t tpm_db_none_parse_type_str[] = {
+	{0, ""}
+};
+
+tpm_str_map_t tpm_db_l2_parse_type[] = {
+	{TPM_L2_PARSE_MAC_DA, "DA"},
+	{TPM_L2_PARSE_MAC_SA, "SA"},
+	{TPM_L2_PARSE_ONE_VLAN_TAG, "ONE_TAG"},
+	{TPM_L2_PARSE_TWO_VLAN_TAG, "TWO_TAGS"},
+	{TPM_L2_PARSE_ETYPE, "ETYPE"},
+	{TPM_L2_PARSE_PPPOE_SES, "PPPOE_SES"},
+	{TPM_L2_PARSE_PPP_PROT, "PPP_PROT"},
+	{TPM_L2_PARSE_GEMPORT, "GEMPORT"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_l3_parse_type[] = {
+	{TPM_L2_PARSE_ETYPE, "ETYPE"},
+	{TPM_L2_PARSE_PPPOE_SES, "PPPOE_SES"},
+	{TPM_L2_PARSE_PPP_PROT, "PPP_PROT"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_ipv4_parse_type[] = {
+	{TPM_IPv4_PARSE_SIP,        "IPV4_SRC"},
+	{TPM_IPv4_PARSE_DIP,        "IPV4_DST"},
+	{TPM_IPv4_PARSE_DSCP, "DSCP"},
+	{TPM_IPv4_PARSE_PROTO,      "L4_PROTO"},
+	{TPM_PARSE_L4_SRC, "L4_SRC"},
+	{TPM_PARSE_L4_DST, "L4_DST"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_ipv4_mc_parse_type[] = {
+	{TPM_IPv4_PARSE_SIP, "SIP"},
+	{TPM_IPv4_PARSE_DIP, "DIP"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_ipv6_gen_parse_type[] = {
+	{TPM_IPv6_PARSE_SIP, "SIP"},
+	{TPM_IPv6_PARSE_DSCP, "DSCP"},
+	{TPM_IPv6_PARSE_HOPL, "HOPL"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_ipv6_gen_5t_parse_type[] = {
+	{TPM_IPv6_PARSE_SIP, "SIP"},
+	{TPM_PARSE_L4_SRC, "L4_SRC"},
+	{TPM_PARSE_L4_DST, "L4_DST"},
+	{0, ""},
+};
+
+
+tpm_str_map_t tpm_db_ipv6_dip_parse_type[] = {
+	{TPM_IPv6_PARSE_DIP, "DIP"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_ipv6_dip_5t_parse_type[] = {
+	{TPM_IPv6_PARSE_SIP, "SIP"},
+	{TPM_IPv6_PARSE_DIP, "DIP"},
+	{TPM_PARSE_L4_SRC, "L4_SRC"},
+	{TPM_PARSE_L4_DST, "L4_DST"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_ipv6_mc_parse_type[] = {
+	{TPM_IPv4_PARSE_DIP, "DIP"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_ipv6_nh_parse_type[] = {
+	{TPM_IPv6_PARSE_NH, "NH"},
+	{0, ""},
+};
+
+tpm_str_map_t tpm_db_ipv6_l4_parse_type[] = {
+	{TPM_PARSE_L4_SRC, "L4_SRC"},
+	{TPM_PARSE_L4_DST, "L4_DST"},
+	{0, ""},
+};
+tpm_str_map_t tpm_db_ctc_cm_parse_type[] = {
+	{TPM_L2_PARSE_MAC_DA, "DA"},
+	{TPM_L2_PARSE_MAC_SA, "SA"},
+	{TPM_L2_PARSE_ONE_VLAN_TAG, "ONE_TAG"},
+	{TPM_L2_PARSE_TWO_VLAN_TAG, "TWO_TAGS"},
+	{TPM_L2_PARSE_ETYPE, "ETYPE"},
+	{TPM_L2_PARSE_PPPOE_SES, "PPPOE_SES"},
+	{TPM_L2_PARSE_PPP_PROT, "PPP_PROT"},
+
+	{TPM_IPv4_PARSE_SIP << API_DUMP_IPV4_PARSE_BM_START,        "IPV4_SIP"},
+	{TPM_IPv4_PARSE_DIP << API_DUMP_IPV4_PARSE_BM_START,        "IPV4_DIP"},
+	{TPM_IPv4_PARSE_DSCP << API_DUMP_IPV4_PARSE_BM_START,       "IPV4_DSCP"},
+	{TPM_IPv4_PARSE_PROTO << API_DUMP_IPV4_PARSE_BM_START,      "IPV4_PROTO"},
+	{TPM_PARSE_L4_SRC << API_DUMP_IPV4_PARSE_BM_START,          "L4_SRC"},
+	{TPM_PARSE_L4_DST << API_DUMP_IPV4_PARSE_BM_START,          "L4_DST"},
+
+	{TPM_IPv6_PARSE_SIP << API_DUMP_IPV6_PARSE_BM_START,        "IPV6_SIP"},
+	{TPM_IPv6_PARSE_DSCP << API_DUMP_IPV6_PARSE_BM_START,       "IPV6_DSCP"},
+	{TPM_IPv6_PARSE_HOPL << API_DUMP_IPV6_PARSE_BM_START,       "IPV6_HOPL"},
+	{TPM_IPv6_PARSE_DIP << API_DUMP_IPV6_PARSE_BM_START,        "IPV6_DIP"},
+	{TPM_IPv6_PARSE_NH << API_DUMP_IPV6_PARSE_BM_START,         "IPV6_NH"},
+	{TPM_PARSE_L4_SRC << API_DUMP_IPV6_PARSE_BM_START,          "L4_SRC"},
+	{TPM_PARSE_L4_DST << API_DUMP_IPV6_PARSE_BM_START,          "L4_DST"},
+	{0, ""},
+};
+
+tpm_str_map_t *tpm_db_parse_type_str[TPM_MAX_API_TYPES] = {
+	/* TPM_API_MGMT */
+	tpm_db_none_parse_type_str,
+	/* TPM_API_MAC_LEARN */
+	tpm_db_none_parse_type_str,
+	/* TPM_API_CPU_LOOPBACK */
+	tpm_db_none_parse_type_str,
+	/* TPM_API_L2_PRIM */
+	tpm_db_l2_parse_type,
+	/* TPM_API_L3_TYPE */
+	tpm_db_l3_parse_type,
+	/* TPM_API_IPV4 */
+	tpm_db_ipv4_parse_type,
+	/* TPM_API_IPV4_MC */
+	tpm_db_ipv4_mc_parse_type,
+	/* TPM_API_IPV6_GEN */
+	tpm_db_ipv6_gen_parse_type,
+	/* TPM_API_IPV6_DIP */
+	tpm_db_ipv6_dip_parse_type,
+	/* TPM_API_IPV6_MC */
+	tpm_db_ipv6_mc_parse_type,
+	/* TPM_API_IPV6_NH */
+	tpm_db_ipv6_nh_parse_type,
+	/* TPM_API_IPV6_L4 */
+	tpm_db_ipv6_l4_parse_type,
+	/* TPM_API_CTC_CM */
+	tpm_db_ctc_cm_parse_type,
+};
+
+tpm_str_map_t tpm_db_parse_flag_type_str[] = {
+	{TPM_PARSE_FLAG_TAG1_TRUE, "TAG1_TRUE"},
+	{TPM_PARSE_FLAG_TAG1_FALSE, "TAG1_FALSE"},
+	{TPM_PARSE_FLAG_TAG2_TRUE, "TAG2_TRUE"},
+	{TPM_PARSE_FLAG_TAG2_FALSE, "TAG2_FALSE"},
+	{TPM_PARSE_FLAG_MTM_TRUE, "MTM_TRUE"},
+	{TPM_PARSE_FLAG_MTM_FALSE, "MTM_FALSE"},
+	{TPM_PARSE_FLAG_TO_CPU_TRUE, "TO_CPU_TRUE"},
+	{TPM_PARSE_FLAG_TO_CPU_FALSE, "TO_CPU_FALSE"},
+	{TPM_PARSE_FLAG_L4_UDP, "L4_UDP"},
+	{TPM_PARSE_FLAG_L4_TCP, "L4_TCP"},
+	{TPM_PARSE_FLAG_PPPOE_TRUE, "PPPOE_TRUE"},
+	{TPM_PARSE_FLAG_PPPOE_FALSE, "PPPOE_FALSE"},
+};
+
+tpm_str_map_t tpm_db_action_type_str[] = {
+	{TPM_ACTION_DROP_PK, "DROP_PK"},
+	{TPM_ACTION_SET_TARGET_PORT, "SET_TRG_PORT"},
+	{TPM_ACTION_SET_TARGET_QUEUE, "SET_TRG_Q"},
+	{TPM_ACTION_SET_PKT_MOD, "SET_PKT_MOD"},
+	{TPM_ACTION_TO_CPU, "TO_CPU"},
+	{TPM_ACTION_MTM, "MTM"},
+	{TPM_ACTION_CUST_CPU_PKT_PARSE, "CUST_PKT_PARSE"},
+	{TPM_ACTION_SPEC_MC_VID, "SPEC_MC_VID"},
+	{TPM_ACTION_UDP_CHKSUM_CALC, "UDP_CHKSUM_CALC"},
+};
+
+tpm_str_map_t tpm_db_target_type_str[] =
+{
+	{TPM_TRG_PORT_WAN,           "WAN_PORT"},
+	{TPM_TRG_TCONT_0,            "TCONT_0"},
+	{TPM_TRG_TCONT_1,            "TCONT_1"},
+	{TPM_TRG_TCONT_2,            "TCONT_2"},
+	{TPM_TRG_TCONT_3,            "TCONT_3"},
+	{TPM_TRG_TCONT_4,            "TCONT_4"},
+	{TPM_TRG_TCONT_5,            "TCONT_5"},
+	{TPM_TRG_TCONT_6,            "TCONT_6"},
+	{TPM_TRG_TCONT_7,            "TCONT_7"},
+	{TPM_TRG_LLID_0,             "LLID_0"},
+	{TPM_TRG_LLID_1,             "LLID_1"},
+	{TPM_TRG_LLID_2,             "LLID_2"},
+	{TPM_TRG_LLID_3,             "LLID_3"},
+	{TPM_TRG_LLID_4,             "LLID_4"},
+	{TPM_TRG_LLID_5,             "LLID_5"},
+	{TPM_TRG_LLID_6,             "LLID_6"},
+	{TPM_TRG_LLID_7,             "LLID_7"},
+	{TPM_TRG_UNI_0,              "UNI_0"},
+	{TPM_TRG_UNI_1,              "UNI_1"},
+	{TPM_TRG_UNI_2,              "UNI_2"},
+	{TPM_TRG_UNI_3,              "UNI_3"},
+	{TPM_TRG_UNI_4,              "UNI_4"},
+	{TPM_TRG_UNI_5,              "UNI_5"},
+	{TPM_TRG_UNI_6,              "UNI_6"},
+	{TPM_TRG_UNI_7,              "UNI_7"},
+	{TPM_TRG_UNI_VIRT,           "UNI_VIRT"},
+	{TPM_TRG_PORT_CPU,           "CPU"},
+	{TPM_TRG_PORT_UNI_ANY,       "UNI_ANY"},
+	{TPM_TRG_PORT_UNI_CPU_LOOP,  "UNI_CPU_LOOP"}
+};
+tpm_str_map_t tpm_db_mod_type_str[] = {
+	{TPM_MH_SET, "MH_SET"},
+	{TPM_MAC_DA_SET, "DA_SET"},
+	{TPM_MAC_SA_SET, "SA_SET"},
+	{TPM_VLAN_MOD, "VLAN_MOD"},
+	{TPM_PPPOE_DEL, "PPPOE_DEL"},
+	{TPM_PPPOE_ADD, "PPPOE_ADD"},
+	{TPM_DSCP_SET, "DSCP_SET"},
+	{TPM_TTL_DEC, "TTL_DEC"},
+	{TPM_IPV4_UPDATE, "IPV4_UPDATE"},
+	{TPM_IPV4_SRC_SET, "IPV4_SRC_SET"},
+	{TPM_IPV4_DST_SET, "IPV4_DST_SET"},
+	{TPM_IPV6_UPDATE, "IPV6_UPDATE"},
+	{TPM_HOPLIM_DEC, "HOPLIM_DEC"},
+	{TPM_IPV6_SRC_SET, "IPV6_SRC_SET"},
+	{TPM_IPV6_DST_SET, "IPV6_DST_SET"},
+	{TPM_L4_SRC_SET, "L4_SRC_SET"},
+	{TPM_L4_DST_SET, "L4_DST_SET"},
+};
+
+char *tpm_db_mc_uni_mode_str[] = {
+	"EXCLUDE",
+	"TRANSPARENT",
+	"STRIP",
+	"TRANSLATE",
+};
+
+char *db_parse_type_to_str(uint32_t api_type, uint32_t parse_type)
+{
+	uint32_t i;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+
+	if (parse_type == 0)
+		return "";
+
+	if (api_type >= TPM_MAX_API_TYPES)
+		return tpm_db_params_illegal_str;
+
+	tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	if (ipv6_5t_enable == TPM_IPV6_5T_ENABLED) {
+		tpm_db_parse_type_str[TPM_API_IPV6_GEN] = tpm_db_ipv6_gen_5t_parse_type;
+		tpm_db_parse_type_str[TPM_API_IPV6_DIP] = tpm_db_ipv6_dip_5t_parse_type;
+	}
+
+	for (i = 0; tpm_db_parse_type_str[api_type][i].enum_in != 0; i++) {
+		if (tpm_db_parse_type_str[api_type][i].enum_in == parse_type)
+			return (&(tpm_db_parse_type_str[api_type][i].str_out[0]));
+	}
+
+	return tpm_db_params_illegal_str;
+}
+
+char *db_parse_flag_type_to_str(uint32_t parse_flag_type)
+{
+	uint32_t i;
+
+	if (parse_flag_type == 0)
+		return "";
+
+	for (i = 0; i < (sizeof(tpm_db_parse_flag_type_str) / sizeof(tpm_str_map_t)); i++) {
+		if (tpm_db_parse_flag_type_str[i].enum_in == parse_flag_type)
+			return (&(tpm_db_parse_flag_type_str[i].str_out[0]));
+	}
+
+	return tpm_db_params_illegal_str;
+}
+
+char *db_target_type_to_str(uint32_t action_type, tpm_pkt_frwd_t  *pkt_frwd)
+{
+	static char target_str[50];
+	char *port_str = "";
+	char gem_str[10] = "";
+	char q_str[10] = "";
+	uint32_t i;
+	tpm_dir_t            dir;
+	tpm_db_pon_type_t    pon_type;
+	tpm_gmacs_enum_t     act_wan = tpm_db_active_wan_get();
+
+	memset(target_str, 0, sizeof(target_str));
+
+	if (SET_TARGET_PORT(action_type)) {
+		for (i = 0; i < (sizeof(tpm_db_target_type_str)/sizeof(tpm_str_map_t)); i++) {
+			if (tpm_db_target_type_str[i].enum_in == pkt_frwd->trg_port) {
+				port_str = &(tpm_db_target_type_str[i].str_out[0]);
+				break;
+			}
+		}
+
+		dir = TPM_DIR_US;
+	/* Get pon_type */
+		tpm_db_pon_type_get(&pon_type);
+
+		if (TO_GPON(dir, pkt_frwd->trg_port, pon_type, act_wan)) {
+			sprintf(gem_str, "%03d",  pkt_frwd->gem_port);
+		}
+	}
+
+	if (SET_TARGET_QUEUE(action_type))
+		sprintf(q_str, "Q%d",  pkt_frwd->trg_queue);
+
+
+	sprintf(target_str, " %-9s %3s | %2s ", port_str, gem_str, q_str);
+
+	return target_str;
+}
+char *db_action_type_to_str(uint32_t action_type)
+{
+	uint32_t i;
+
+	if (action_type == 0)
+		return "";
+
+	for (i = 0; i < (sizeof(tpm_db_action_type_str) / sizeof(tpm_str_map_t)); i++) {
+		if (tpm_db_action_type_str[i].enum_in == action_type)
+			return (&(tpm_db_action_type_str[i].str_out[0]));
+	}
+
+	return tpm_db_params_illegal_str;
+}
+
+char *db_mod_type_to_str(uint32_t mod_type)
+{
+	uint32_t i;
+
+	if (mod_type == 0)
+		return "";
+
+	for (i = 0; i < (sizeof(tpm_db_mod_type_str) / sizeof(tpm_str_map_t)); i++) {
+		if (tpm_db_mod_type_str[i].enum_in == mod_type)
+			return (&(tpm_db_mod_type_str[i].str_out[0]));
+	}
+
+	return tpm_db_params_illegal_str;
+}
+
+void tpm_print_api_dump_line(uint8_t first_rule,
+			     uint8_t first_line,
+			     uint32_t api_type,
+			     uint32_t rule_num,
+			     uint32_t rule_idx,
+			     uint32_t pnc_entry,
+			     uint32_t src_port,
+			     uint32_t parse_type,
+			     uint32_t parse_flag_type,
+			     uint32_t next_phase,
+			     uint32_t action_type,
+			     uint32_t mod_type,
+			     uint32_t mod_entry,
+			     uint32_t set_port_q,
+			     tpm_pkt_frwd_t *pkt_frwd)
+{
+	char rule_num_str[8] = "";
+	char rule_idx_str[8] = "";
+	char pnc_entry_str[8] = "";
+	char mod_entry_str[8] = "";
+
+	char *empty_str = "";
+
+	char *api_type_str = empty_str;
+	char *src_port_str = empty_str;
+	char *next_phase_str = empty_str;
+
+	char *parse_type_str = empty_str;
+	char *parse_flag_type_str = empty_str;
+	char *action_type_str = empty_str;
+	char *mod_type_str = empty_str;
+	char *target_port_q_str   = empty_str;
+
+	if (first_line) {
+		sprintf(rule_num_str, "%03d", rule_num);
+		sprintf(rule_idx_str, "%03d", rule_idx);
+		sprintf(pnc_entry_str, "%03d", pnc_entry);
+		if (mod_entry != 0)
+			sprintf(mod_entry_str, "%04d", mod_entry);
+
+		if (first_rule) {
+			if (api_type < TPM_MAX_API_TYPES)
+				api_type_str = tpm_db_api_type_str[api_type];
+			else
+				api_type_str = tpm_db_params_illegal_str;
+		}
+
+		if (src_port <= TPM_SRC_PORT_WAN_OR_LAN)
+			src_port_str = tpm_db_src_port_str[src_port];
+		else
+			src_port_str = tpm_db_params_illegal_str;
+
+		if (next_phase <= STAGE_DONE)
+			next_phase_str = tpm_db_next_phase_str[next_phase];
+		else
+			next_phase_str = tpm_db_params_illegal_str;
+
+	}
+
+	if (parse_type != 0)
+		parse_type_str = db_parse_type_to_str(api_type, parse_type);
+
+	if (parse_flag_type != 0)
+		parse_flag_type_str = db_parse_flag_type_to_str(parse_flag_type);
+
+	if (action_type != 0) {
+		action_type_str = db_action_type_to_str(action_type);
+	}
+
+	if (set_port_q != 0)
+		target_port_q_str = db_target_type_to_str(set_port_q, pkt_frwd);
+
+	if (mod_type != 0)
+		mod_type_str = db_mod_type_to_str(mod_type);
+
+    printk("=  %8s | %4s | %4s | %5s | %8s | %13s | %13s | %8s | %16s |%20s| %12s | %6s  =\n",
+		api_type_str, rule_num_str, rule_idx_str, pnc_entry_str,
+		src_port_str, parse_type_str, parse_flag_type_str,
+	       next_phase_str, action_type_str, target_port_q_str, mod_type_str, mod_entry_str);
+}
+
+void tpm_print_api_dump_rule(uint8_t first_rule,
+				tpm_api_type_t api_type,
+				uint32_t rule_num,
+				uint32_t rule_idx, uint32_t pnc_entry, uint32_t mod_entry, tpm_rule_entry_t *rule)
+{
+	uint8_t first_line = TPM_TRUE;
+	uint32_t src_port = TPM_SRC_PORT_ILLEGAL;
+	uint32_t next_phase = STAGE_DONE;
+	uint32_t parse_bm = 0;
+	uint32_t parse_flag_bm = 0;
+	uint32_t action_bm = 0;
+	uint32_t mod_bm = 0;
+	uint32_t tgt_port_bm = 0;
+	uint32_t parse_type = 0x1;
+	uint32_t parse_flag_type = 0x1;
+	uint32_t action_type = 0x1;
+	uint32_t mod_type = 0x1;
+	uint32_t tgt_port = 0x1;
+	uint32_t bit_cnt;
+	uint32_t set_port_q = 0;
+	tpm_pkt_frwd_t *pkt_frwd = NULL;
+	tpm_pkt_frwd_t mc_frwd;
+
+	if (rule == NULL)
+		return;
+
+	switch (api_type) {
+	case TPM_API_L2_PRIM:
+		src_port = rule->l2_prim_key.src_port;
+		next_phase = rule->l2_prim_key.rule_action.next_phase;
+		parse_bm = rule->l2_prim_key.parse_rule_bm;
+		parse_flag_bm = rule->l2_prim_key.parse_flags_bm;
+		action_bm = rule->l2_prim_key.rule_action.pkt_act;
+		mod_bm = rule->l2_prim_key.pkt_mod_bm;
+		pkt_frwd = &rule->l2_prim_key.pkt_frwd;
+		break;
+
+	case TPM_API_L3_TYPE:
+		src_port = rule->l3_type_key.src_port;
+		next_phase = rule->l3_type_key.rule_action.next_phase;
+		parse_bm = rule->l3_type_key.parse_rule_bm;
+		parse_flag_bm = rule->l3_type_key.parse_flags_bm;
+		action_bm = rule->l3_type_key.rule_action.pkt_act;
+		pkt_frwd  = &rule->l3_type_key.pkt_frwd;
+		break;
+
+	case TPM_API_IPV4:
+		src_port = rule->ipv4_key.src_port;
+		next_phase = rule->ipv4_key.rule_action.next_phase;
+		parse_bm = rule->ipv4_key.parse_rule_bm;
+		parse_flag_bm = rule->ipv4_key.parse_flags_bm;
+		action_bm = rule->ipv4_key.rule_action.pkt_act;
+		mod_bm = rule->ipv4_key.pkt_mod_bm;
+		pkt_frwd = &rule->ipv4_key.pkt_frwd;
+		break;
+
+	case TPM_API_IPV4_MC:
+		src_port = TPM_SRC_PORT_WAN;
+		parse_bm = TPM_IPv4_PARSE_DIP;
+		if (rule->ipv4_mc_key.ignore_ipv4_src == 0)
+			parse_bm |= TPM_IPv4_PARSE_SIP;
+		mod_bm = 0;	/* ?? */
+		/*mc_frwd is only used to print target port and target queue for api_dump*/
+		action_bm = TPM_ACTION_SET_TARGET_PORT | TPM_ACTION_SET_TARGET_QUEUE;
+		mc_frwd.trg_port = rule->ipv4_mc_key.dest_port_bm;
+		mc_frwd.trg_queue = tpm_db.igmp_def.mc_hwf_queue;
+		pkt_frwd = &mc_frwd;
+		break;
+
+	case TPM_API_IPV6_GEN:
+		src_port = rule->ipv6_gen_key.src_port;
+		next_phase = rule->ipv6_gen_key.rule_action.next_phase;
+		parse_bm = rule->ipv6_gen_key.parse_rule_bm;
+		parse_flag_bm = rule->ipv6_gen_key.parse_flags_bm;
+		action_bm = rule->ipv6_gen_key.rule_action.pkt_act;
+		mod_bm = rule->ipv6_gen_key.pkt_mod_bm;
+		pkt_frwd = &rule->ipv6_gen_key.pkt_frwd;
+		break;
+
+	case TPM_API_IPV6_DIP:
+		src_port = rule->ipv6_dip_key.src_port;
+		next_phase = rule->ipv6_dip_key.rule_action.next_phase;
+		parse_bm = rule->ipv6_dip_key.parse_rule_bm;
+		parse_flag_bm = rule->ipv6_dip_key.parse_flags_bm;
+		action_bm = rule->ipv6_dip_key.rule_action.pkt_act;
+		mod_bm = rule->ipv6_dip_key.pkt_mod_bm;
+		pkt_frwd = &rule->ipv6_dip_key.pkt_frwd;
+		break;
+
+	case TPM_API_IPV6_NH:
+		src_port = TPM_SRC_PORT_WAN_OR_LAN;
+		next_phase = rule->ipv6_nh_key.rule_action.next_phase;
+		parse_bm = rule->ipv6_nh_key.parse_rule_bm;
+		parse_flag_bm = rule->ipv6_nh_key.parse_flags_bm;
+		action_bm = rule->ipv6_nh_key.rule_action.pkt_act;
+		pkt_frwd = &rule->ipv6_nh_key.pkt_frwd;
+		break;
+
+	case TPM_API_IPV6_L4:
+		src_port = rule->ipv6_l4_key.src_port;
+		next_phase = rule->ipv6_l4_key.rule_action.next_phase;
+		parse_bm = rule->ipv6_l4_key.parse_rule_bm;
+		parse_flag_bm = rule->ipv6_l4_key.parse_flags_bm;
+		action_bm = rule->ipv6_l4_key.rule_action.pkt_act;
+		mod_bm = rule->ipv6_l4_key.pkt_mod_bm;
+		pkt_frwd = &rule->ipv6_l4_key.pkt_frwd;
+		break;
+
+	case TPM_API_IPV6_MC:
+		src_port = TPM_SRC_PORT_WAN;
+		parse_bm = TPM_IPv6_PARSE_DIP;
+		mod_bm = 0;	/* ?? */
+		/*mc_frwd is only used to print target port and target queue for api_dump*/
+		action_bm = TPM_ACTION_SET_TARGET_PORT | TPM_ACTION_SET_TARGET_QUEUE;
+		mc_frwd.trg_port = rule->ipv6_mc_key.dest_port_bm;
+		mc_frwd.trg_queue = tpm_db.igmp_def.mc_hwf_queue;
+		pkt_frwd = &mc_frwd;
+		break;
+
+	case TPM_API_CNM:
+		src_port = rule->cnm_key.src_port;
+		parse_bm = rule->cnm_key.l2_parse_rule_bm;
+		parse_bm |= (rule->cnm_key.ipv4_parse_rule_bm << API_DUMP_IPV4_PARSE_BM_START);
+		parse_bm |= (rule->cnm_key.ipv6_parse_rule_bm << API_DUMP_IPV6_PARSE_BM_START);
+		action_bm = rule->cnm_key.pkt_act;
+		pkt_frwd = &rule->cnm_key.pkt_frwd;
+		break;
+	default:
+		return;
+	}
+
+	action_bm &= 0xFFFF;	/* DON'T show the internal actions! */
+	tgt_port_bm = pkt_frwd->trg_port;
+
+	set_port_q = action_bm & (TPM_ACTION_SET_TARGET_PORT | TPM_ACTION_SET_TARGET_QUEUE);
+
+	do {
+		if (parse_bm != 0) {
+			for (bit_cnt = 0; (parse_bm & 0x1) == 0; parse_bm = parse_bm >> 1, bit_cnt++)
+				;
+			parse_type = parse_type << bit_cnt;
+		} else
+			parse_type = 0;
+
+		if (parse_flag_bm != 0) {
+			for (bit_cnt = 0; (parse_flag_bm & 0x1) == 0; parse_flag_bm = parse_flag_bm >> 1, bit_cnt++)
+				;
+			parse_flag_type = parse_flag_type << bit_cnt;
+		} else
+			parse_flag_type = 0;
+
+		if (action_bm != 0) {
+			for (bit_cnt = 0; (action_bm & 0x1) == 0; action_bm = action_bm >> 1, bit_cnt++)
+				;
+			action_type = action_type << bit_cnt;
+		} else
+			action_type = 0;
+
+		if (mod_bm != 0) {
+			for (bit_cnt = 0; (mod_bm & 0x1) == 0; mod_bm = mod_bm >> 1, bit_cnt++)
+				;
+			mod_type = mod_type << bit_cnt;
+		} else
+			mod_type = 0;
+
+		if (tgt_port_bm != 0) {
+			for (bit_cnt = 0; (tgt_port_bm & 0x1) == 0; tgt_port_bm = tgt_port_bm >> 1, bit_cnt++)
+				;
+			tgt_port = tgt_port << bit_cnt;
+			pkt_frwd->trg_port = tgt_port;
+		} else
+			pkt_frwd->trg_port = 0;
+
+
+		tpm_print_api_dump_line(first_rule, first_line, api_type, rule_num, rule_idx,
+					pnc_entry, src_port, parse_type, parse_flag_type, next_phase,
+					action_type, mod_type, mod_entry, set_port_q, pkt_frwd);
+
+		first_line = TPM_FALSE;
+		set_port_q &= ~TPM_ACTION_SET_TARGET_QUEUE;
+
+		parse_bm &= ~0x1;
+		parse_flag_bm &= ~0x1;
+		action_bm &= ~0x1;
+		mod_bm &= ~0x1;
+		tgt_port_bm &= ~0x1;
+
+		if ((parse_bm == 0) && (parse_flag_bm == 0) && (action_bm == 0) && (mod_bm == 0) && (tgt_port_bm == 0))
+			break;
+
+	} while (TPM_TRUE);
+
+}
+
+void tpm_print_api_dump(tpm_api_type_t api_type)
+{
+	int8_t first_rule = 1;
+	int32_t current_rule, rcode;
+	int32_t rule_index;
+	int32_t bi_dir;
+	int32_t next_rule;
+	int32_t rule_num;
+	tpm_rule_entry_t tpm_rule;
+	tpm_error_code_t tpm_ret;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_conn_t pnc_con;
+	tpm_api_sections_t api_section;
+	char *api_type_str = "";
+
+	tpm_print_api_dump_head();
+
+	tpm_db_api_section_get_from_api_type(api_type, &api_section);
+	current_rule = -1;
+
+	tpm_ret = tpm_db_api_entry_val_get_next(api_section, current_rule, &next_rule, &rule_index,
+						&bi_dir, &tpm_rule, &mod_con, &pnc_con);
+
+	if (-1 == next_rule) {
+		if (api_type < TPM_MAX_API_TYPES)
+			api_type_str = tpm_db_api_type_str[api_type];
+		else
+			api_type_str = tpm_db_params_illegal_str;
+
+		printk("=  %8s | %4s | %4s | %5s | %8s | %13s | %13s | %8s | %16s |%20s| %12s | %5s   =\n",
+		       api_type_str, "", "", "", "", "", "", "", "", "", "", "");
+	}
+
+	while (-1 != next_rule) {
+		if (first_rule == 0)
+			printk("=           |------+------+-------+----------+---------------+---------------+----------+------------------+--------------------+--------------+---------=\n");
+		/* Get the rule_num */
+		rcode = tpm_db_api_rulenum_get(api_section, rule_index, &rule_num);
+		if (rcode != TPM_DB_OK) {
+			printk("get DB failed: %d\n", rcode);
+			return;
+		}
+
+		tpm_print_api_dump_rule(first_rule, api_type, rule_num, rule_index, pnc_con.pnc_conn_tbl[0].pnc_index,
+					mod_con.mod_cmd_ind, &tpm_rule);
+
+		tpm_ret = tpm_db_api_entry_val_get_next(api_section, next_rule, &next_rule, &rule_index,
+							&bi_dir, &tpm_rule, &mod_con, &pnc_con);
+		first_rule = 0;
+	}
+
+	printk("==========================================================================================================================================================\n");
+	return;
+}
+
+void tpm_print_api_dump_all(void)
+{
+	tpm_api_type_t api_type;
+
+	tpm_api_sections_t api_section;
+	uint32_t api_rng_size;
+	uint32_t num_valid_entries;
+	tpm_pnc_ranges_t prim_pnc_range;
+	int32_t last_valid_entry;
+	uint32_t tbl_start;
+	tpm_db_pnc_range_conf_t range_conf;
+
+	printk("\n");
+	for (api_type = TPM_API_L2_PRIM; api_type < TPM_MAX_API_TYPES; api_type++) {
+		tpm_db_api_section_get_from_api_type(api_type, &api_section);
+		tpm_db_api_section_get(api_section, &api_rng_size, &num_valid_entries,
+					&prim_pnc_range, &last_valid_entry, &tbl_start);
+
+		/* Get Range Conf */
+		tpm_db_pnc_rng_conf_get(prim_pnc_range, &range_conf);
+
+		tpm_print_api_dump(api_type);
+		printk("\n");
+	}
+
+	return;
+}
+
+int tpm_print_sram_next_lookup(struct tcam_entry *te, char *buf)
+{
+	unsigned int word;
+	unsigned int lookup;
+
+	word = LU_DONE_OFFS / DWORD_LEN;
+	lookup = te->sram.word[word] >> (LU_DONE_OFFS % DWORD_LEN);
+	lookup &= 0x1;
+
+	if (lookup)
+		return sprintf(buf, " D");
+
+	word = LU_ID_OFFS / DWORD_LEN;
+	lookup = te->sram.word[word] >> (LU_ID_OFFS % DWORD_LEN);
+	lookup &= LU_MASK;
+
+	return sprintf(buf, " %d", lookup);
+}
+
+int tpm_print_sram_next_lookup_shift(struct tcam_entry *te, char *buf)
+{
+	unsigned int word, value;
+
+	word = NEXT_LU_SHIFT_OFFS / DWORD_LEN;
+	value = te->sram.word[word] >> (NEXT_LU_SHIFT_OFFS % DWORD_LEN);
+	value &= SHIFT_IDX_MASK;
+
+	if (value)
+		return sprintf(buf, " %1d", value);
+
+	return sprintf(buf, " -");
+}
+
+int tpm_print_sram_shift_update(struct tcam_entry *te, char *buf)
+{
+	unsigned int word;
+	unsigned int index;
+	unsigned int value;
+
+	word = SHIFT_VAL_OFFS / DWORD_LEN;
+	value = te->sram.word[word] >> (SHIFT_VAL_OFFS % DWORD_LEN);
+	value &= SHIFT_VAL_MASK;
+
+	word = SHIFT_IDX_OFFS / DWORD_LEN;
+	index = te->sram.word[word] >> (SHIFT_IDX_OFFS % DWORD_LEN);
+	index &= SHIFT_IDX_MASK;
+
+	if (value)
+		return sprintf(buf, " [%2.2d]=%3.3d", index, value);
+
+	return sprintf(buf, " [ 0]= 0");
+}
+
+int tpm_print_sram_rxq(struct tcam_entry *te, char *buf)
+{
+	unsigned int rxq, force;
+
+	rxq = sram_sw_get_rxq(te, &force);
+	if (rxq)
+		return sprintf(buf, " %1.1sQ%1.1d", force ? "f" : " ", rxq);
+
+	return sprintf(buf, " ---");
+}
+
+int tpm_print_sram_ainfo(struct tcam_entry *te, char *buf)
+{
+	unsigned int word, shift, data, mask;
+	int i, off = 0;
+
+	word = AI_VALUE_OFFS / DWORD_LEN;
+	shift = AI_VALUE_OFFS % DWORD_LEN;
+	data = ((te->sram.word[word] >> shift) & AI_MASK);
+	shift = AI_MASK_OFFS % DWORD_LEN;
+	mask = ((te->sram.word[word] >> shift) & AI_MASK);
+
+	if (mask) {
+		for (i = 0; i < AI_BITS; i++) {
+			if (mask & (1 << i))
+				off += sprintf(buf + off, "%d", ((data & (1 << i)) != 0));
+			else
+				off += sprintf(buf + off, "x");
+		}
+	} else
+		off += sprintf(buf + off, "-------");
+
+	return off;
+}
+
+int tpm_print_tcam_ainfo(struct tcam_entry *te, char *buf)
+{
+	int i, data, mask;
+	int off = 0;
+
+	mask = ((te->mask.u.word[AI_WORD] >> AI_OFFS) & AI_MASK);
+	if (mask == 0)
+		off += sprintf(buf + off, "-------");
+	else {
+		data = ((te->data.u.word[AI_WORD] >> AI_OFFS) & AI_MASK);
+		for (i = 0; i < AI_BITS; i++)
+			if (mask & (1 << i))
+				off += sprintf(buf + off, "%d", ((data & (1 << i)) != 0));
+			else
+				off += sprintf(buf + off, "x");
+	}
+
+	return off;
+}
+
+int tpm_print_tcam_port_mask(unsigned int port_mask, char *buf)
+{
+	int off = 0;
+
+	if (port_mask & 1)
+		off += sprintf(buf + off, "--,");
+	else
+		off += sprintf(buf + off, "P ,");
+
+	if (port_mask & 4)
+		off += sprintf(buf + off, "--,");
+	else
+		off += sprintf(buf + off, "G0,");
+
+	if (port_mask & 0x10)
+		off += sprintf(buf + off, "--");
+	else
+		off += sprintf(buf + off, "G1");
+
+	return off;
+}
+
+int tpm_print_sram_rinfo(struct tcam_entry *te, char *buf, unsigned int buf_len)
+{
+	unsigned int word, shift, rinfo_val, rinfo_mask;
+	int off = 0;
+	int i;
+
+	word = RI_VALUE_OFFS / DWORD_LEN;
+	shift = RI_VALUE_OFFS % DWORD_LEN;
+	rinfo_val = ((te->sram.word[word] >> shift) & RI_MASK);
+
+	word = RI_MASK_OFFS / DWORD_LEN;
+	shift = RI_MASK_OFFS % DWORD_LEN;
+	rinfo_mask = ((te->sram.word[word] >> shift) & RI_MASK);
+	word++;
+	rinfo_mask |= (te->sram.word[word] & 0x3FFFF) << 6;
+
+	if (rinfo_val & 1)
+		/* discard */
+		off += sprintf(buf + off, "DIS ");
+
+	/* L4 */
+	if ((rinfo_val & 0x6) == 0x2)
+		/* UDP */
+		off += sprintf(buf + off, "UDP ");
+	else if ((rinfo_val & 0x6) == 0x6)
+		/* other */
+		off += sprintf(buf + off, "L4-OTH ");
+#if 0
+    this code snippet is ifdefed till mask bits are supported in LSP
+    to refrain from flooding with TCP
+	else if ((rinfo_val & 0x6) == 0x0)
+		/* TCP */
+		off += sprintf(buf + off, "TCP ");
+#endif
+
+	/* L3 */
+	if ((rinfo_val & 0x18) == 0x18)
+		/* IPv4 not fragmented */
+		off += sprintf(buf + off, "IPV4_NF ");
+	else if ((rinfo_val & 0x18) == 0x8)
+		/* IPv6 */
+		off += sprintf(buf + off, "IPV6 ");
+	else if ((rinfo_val & 0x18) == 0x10)
+		/* IPv4 fragmented */
+		off += sprintf(buf + off, "IPV4_FR ");
+#if 0
+    this code snippet is ifdefed till mask bits are supported in LSP
+    to refrain from flooding with L3_OTH
+	else if ((rinfo_val & 0x18) == 0x0)
+		/* other */
+		off += sprintf(buf + off, "L3_OTH ");
+#endif
+
+#if 0
+	/* First fragmented */
+	if (rinfo_val & 0x20)
+		off += sprintf(buf + off, "ff ");
+#endif
+
+	/* Filtering method */
+	if (rinfo_val & 0x1c0)
+		off += sprintf(buf + off, "ERR FM-%d ", (rinfo_val & 0x1c0) >> 6);
+
+	/* packet discard decision */
+	if (rinfo_val & 0x200)
+		off += sprintf(buf + off, "COL ");
+
+#if 0
+	/* TX port */
+	if (rinfo_val & 0x3c00)
+		off += sprintf(buf + off, "txp-%d ", (rinfo_val & 0x3c00) >> 10);
+#endif
+
+	/* Marvell Header */
+	if (rinfo_val & 0x3c000)
+		off += sprintf(buf + off, "MH_REG-%d ", (rinfo_val & 0x3c000) >> 14);
+
+#if 0
+	if (rinfo_val & 0x3c0000)
+		off += sprintf(buf + off, "gen-%d ", (rinfo_val & 0x3c0000) >> 14);
+
+	if (rinfo_val & 0xc00000)
+		off += sprintf(buf + off, "prof-%d ", (rinfo_val & 0xc00000) >> 18);
+#endif
+
+	for (i = off; i < buf_len; i++)
+		off += sprintf(buf + off, " ");
+
+	return off;
+}
+
+int tpm_print_tcam(unsigned int print_index, struct tcam_entry *te, char *buf)
+{
+	unsigned int    *p_data = (unsigned int *)&te->data;
+	unsigned int    *p_sram = (unsigned int *)&te->sram;
+	unsigned int    *p_mask = (unsigned int *)&te->mask;
+	unsigned int    value;
+	unsigned int    mask;
+	unsigned int    off = 0;
+	int             i;
+	unsigned int    port_val, port_mask, lookup_val, lookup_mask;
+	unsigned int    bitmap_mask;
+	unsigned int    shift;
+
+	/* hw entry id */
+	if (print_index)
+		off += sprintf(buf + off, "[%4d]\n", te->ctrl.index);
+
+	/* get LU value/mask */
+	tcam_sw_get_lookup(te, &lookup_val, &lookup_mask);
+
+	/* print the LU value */
+	off += sprintf(buf + off, "    %1.1x ", lookup_val);
+
+	/* print the port */
+	tcam_sw_get_port(te, &port_val, &port_mask);
+	off += tpm_print_tcam_port_mask(port_mask, buf + off);
+	off += sprintf(buf+off, "  ");
+
+	/* print tcam data bits */
+	i = 0;
+	while (i < TCAM_LEN - 1) {
+		value = MV_BYTE_SWAP_32BIT(MV_32BIT_LE_FAST(p_data[i]));
+		mask  = MV_BYTE_SWAP_32BIT(MV_32BIT_LE_FAST(p_mask[i]));
+
+		for (shift = 28, bitmap_mask = 0xf0000000; bitmap_mask; shift -= 4) {
+			if (bitmap_mask & mask)
+				off += sprintf(buf + off, "%1.1x", (bitmap_mask & value) >> shift);
+			else
+				off += sprintf(buf + off, "-");
+			bitmap_mask = bitmap_mask >> 4;
+		}
+		off += sprintf(buf + off, " ");
+		i++;
+	}
+
+	/* print sram next LU */
+	off += tpm_print_sram_next_lookup(te, buf + off);
+
+	/* print sram next LU shift */
+	off += tpm_print_sram_next_lookup_shift(te, buf + off);
+
+	/* print sram next shift update */
+	off += tpm_print_sram_shift_update(te, buf + off);
+
+	/* print sram next RX queue */
+	off += tpm_print_sram_rxq(te, buf + off);
+
+	/* print entry name */
+	if (!strncmp("empty", te->ctrl.text, 5))
+		off += sprintf(buf + off, "                 ");
+	else
+		off += sprintf(buf + off, " %-16s", te->ctrl.text);
+	off += sprintf(buf+off, " ");
+
+	/* print sram aditional info (AI) */
+	off += tpm_print_sram_ainfo(te, buf + off);
+
+	/* print sram flow ID value */
+	off += sprintf(buf + off, " %8.8x", p_sram[0]);
+
+	off += sprintf(buf + off, "\n");
+
+	/* print the LU mask */
+	off += sprintf(buf + off, "    %1.1x ", lookup_mask);
+
+	/* print tcam aditional info (AI) */
+	off += tpm_print_tcam_ainfo(te, buf + off);
+	off += sprintf(buf + off, "   ");
+
+	/* print the tcam mask bits */
+	i = 0;
+	while (i < TCAM_LEN - 1) {
+		mask  = MV_BYTE_SWAP_32BIT(MV_32BIT_LE_FAST(p_mask[i]));
+
+		for (shift = 28, bitmap_mask = 0xf0000000; bitmap_mask; shift -= 4) {
+			if (bitmap_mask & mask)
+				off += sprintf(buf + off, "%1.1x", (bitmap_mask & mask) >> shift);
+			else
+				off += sprintf(buf + off, "-");
+			bitmap_mask = bitmap_mask >> 4;
+		}
+		off += sprintf(buf + off, " ");
+		i++;
+	}
+	off += sprintf(buf + off, " ");
+
+	/* print sram result info */
+	off += tpm_print_sram_rinfo(te, buf + off, 42);
+
+	/* print sram flow ID mask */
+	value = p_sram[1];
+	for (bitmap_mask = 0x80; bitmap_mask; shift--) {
+		if (bitmap_mask & value)
+			off += sprintf(buf + off, "f");
+		else
+			off += sprintf(buf + off, "0");
+		bitmap_mask = bitmap_mask >> 1;
+	}
+
+	off += sprintf(buf + off, "\n");
+
+	return off;
+}
+
+void tpm_print_pnc_field_desc(void)
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    printk("    ------------------------------ T C A M -------------------------  --------------- S R A M ----------------------------\n");
+    printk("    +--- LU ID                                            Shift Update ---+    Entry name ---+    modL [3:0]   GEM [23:12]\n");
+    printk("    | +--- Port/s                                  Next LU Shift reg ---+ |                  |    modM [7:4]   txp [27:24]\n");
+    printk("    | |        +--- words value                             Next LU --+ | |  RxQ -+   +------+    modH [9:8]    +-- FlowID\n");
+    printk("    | |        |                                                      | | |       |   |                +--AI    |\n");
+    printk("    . [.,..,.] [......0 .......1 .......2 .......3 .......4 ......5]  . . [.....] [.] [..............] [.....]  [........]\n");
+    printk("    . [.....]  [......0 .......1 .......2 .......3 .......4 ......5]  [.......................................] [........]\n");
+    printk("    | |                                                            |  |                                        |\n");
+    printk("    | +--- AI                                                      |  |                         FlowID mask ---+\n");
+    printk("    +--- LU ID mask                                  words mask ---+  +--- SRAM RI\n");
+#endif
+}
+
+int tpm_print_pnc(void)
+{
+	int i;
+	struct tcam_entry te;
+	char buff[1024];
+
+	tpm_print_pnc_field_desc();
+	for (i = 0; i < CONFIG_MV_PNC_TCAM_LINES; i++) {
+		tcam_sw_clear(&te);
+		tcam_hw_read(&te, i);
+		if (te.ctrl.flags & TCAM_F_INV)
+			continue;
+		tpm_print_tcam(1, &te, buff);
+		printk(buff);
+	}
+
+	return 0;
+}
+unsigned int tpm_tcam_hw_hits_hist_print(unsigned int   seq,
+					 unsigned int   shift,
+					 unsigned int   last_val,
+					 unsigned int   new_val,
+					 unsigned int   print_pnc)
+{
+	unsigned int off = 0;
+	unsigned int pnc_new_entry  = (new_val >> shift) & 0x3FF;
+	unsigned int pnc_last_entry = (last_val >> shift) & 0x3FF;
+	char         buff[1024];
+
+	off += sprintf(buff + off, "%d - %3.3d", seq, pnc_new_entry);
+	if (pnc_new_entry != 0) {
+		if (pnc_new_entry == pnc_last_entry)
+			off += sprintf(buff + off, " *\n");
+		else
+			off += sprintf(buff + off, "\n");
+
+		if (print_pnc) {
+			struct tcam_entry te;
+
+			tcam_sw_clear(&te);
+			tcam_hw_read(&te, pnc_new_entry);
+			if (!(te.ctrl.flags & TCAM_F_INV))
+				off += tpm_print_tcam(0, &te, buff + off);
+		}
+		if (pnc_new_entry == pnc_last_entry) {
+			printk(buff);
+			return 0;
+		}
+	}
+	off += sprintf(buff + off, "\n");
+	printk(buff);
+
+	return 0;
+}
+
+
+void tpm_tcam_hw_record(int port)
+{
+	MV_REG_WRITE(MV_PNC_HIT_SEQ0_REG, (port << 1) | 1);
+}
+
+
+int tpm_tcam_hw_hits(unsigned int print_pnc)
+{
+	unsigned int            new_val;
+	static unsigned int     last_read[3] = {0, 0, 0};
+
+	printk("seq hit recurring\n");
+	printk("--- --- ---------\n");
+
+	new_val = MV_REG_READ(MV_PNC_HIT_SEQ0_REG);
+	tpm_tcam_hw_hits_hist_print(0, 10, last_read[0], new_val, print_pnc);
+	tpm_tcam_hw_hits_hist_print(1, 20, last_read[0], new_val, print_pnc);
+	last_read[0] = new_val;
+
+	new_val = MV_REG_READ(MV_PNC_HIT_SEQ1_REG);
+	tpm_tcam_hw_hits_hist_print(2,  0, last_read[1], new_val, print_pnc);
+	tpm_tcam_hw_hits_hist_print(3, 10, last_read[1], new_val, print_pnc);
+	tpm_tcam_hw_hits_hist_print(4, 20, last_read[1], new_val, print_pnc);
+	last_read[1] = new_val;
+
+	new_val = MV_REG_READ(MV_PNC_HIT_SEQ2_REG);
+	tpm_tcam_hw_hits_hist_print(5,  0, last_read[2], new_val, print_pnc);
+	tpm_tcam_hw_hits_hist_print(6, 10, last_read[2], new_val, print_pnc);
+	tpm_tcam_hw_hits_hist_print(7, 20, last_read[2], new_val, print_pnc);
+	last_read[2] = new_val;
+
+	return 0;
+}
+
+int tpm_age_pnc_dump(void)
+{
+	unsigned int        tid, reg_val;
+	char                buff[1024];
+	struct tcam_entry   te;
+	unsigned int        off;
+
+	for (tid = 0; tid < CONFIG_MV_PNC_TCAM_LINES; tid++) {
+		reg_val = mvPncAgingCntrRead(tid);
+
+		if (!(reg_val & PNC_AGING_CNTR_MASK))
+			continue;
+
+		off = 0;
+		off += sprintf(buff + off, "[%4d]: gr=%d - %10u", tid,
+			       ((reg_val & PNC_AGING_GROUP_ALL_MASK) >> PNC_AGING_GROUP_OFFS),
+			       ((reg_val & PNC_AGING_CNTR_MASK) >> PNC_AGING_CNTR_OFFS));
+
+		if (reg_val & PNC_AGING_READ_LU_LOG_MASK)
+			off += sprintf(buff + off, ", LU_READ");
+
+		if (reg_val & PNC_AGING_READ_MU_LOG_MASK)
+			off += sprintf(buff + off, ", MU_READ");
+
+		if (reg_val & PNC_AGING_SKIP_LU_SCAN_MASK)
+			off += sprintf(buff + off, ", LU_SKIP");
+
+		if (reg_val & PNC_AGING_SKIP_MU_SCAN_MASK)
+			off += sprintf(buff + off, ", MU_SKIP");
+
+		off += sprintf(buff + off, "\n");
+		printk(buff);
+
+		tcam_sw_clear(&te);
+		tcam_hw_read(&te, tid);
+
+		if (!(te.ctrl.flags & TCAM_F_INV)) {
+			tpm_print_tcam(0, &te, buff);
+			printk(buff);
+		}
+	}
+
+	return 0;
+}
+
+int tpm_age_pnc_dump_live(void)
+{
+	unsigned int        tid, reg_val;
+	unsigned int        off;
+	struct tcam_entry   te;
+	char                buff[1024];
+	unsigned int        tpm_age_first[CONFIG_MV_PNC_TCAM_LINES];
+
+	for (tid = 0; tid < CONFIG_MV_PNC_TCAM_LINES; tid++)
+		tpm_age_first[tid] = mvPncAgingCntrRead(tid);
+
+	msleep(1000);
+
+	for (tid = 0; tid < CONFIG_MV_PNC_TCAM_LINES; tid++) {
+		reg_val = mvPncAgingCntrRead(tid);
+
+		if (!(reg_val & PNC_AGING_CNTR_MASK))
+			continue;
+
+		if (tpm_age_first[tid] == reg_val)
+			continue;
+
+		off = 0;
+		off += sprintf(buff + off, "[%4d]: gr=%d - %10u", tid,
+			       ((reg_val & PNC_AGING_GROUP_ALL_MASK) >> PNC_AGING_GROUP_OFFS),
+			       ((reg_val & PNC_AGING_CNTR_MASK) >> PNC_AGING_CNTR_OFFS));
+
+		if (reg_val & PNC_AGING_READ_LU_LOG_MASK)
+			off += sprintf(buff + off, ", LU_READ");
+
+		if (reg_val & PNC_AGING_READ_MU_LOG_MASK)
+			off += sprintf(buff + off, ", MU_READ");
+
+		if (reg_val & PNC_AGING_SKIP_LU_SCAN_MASK)
+			off += sprintf(buff + off, ", LU_SKIP");
+
+		if (reg_val & PNC_AGING_SKIP_MU_SCAN_MASK)
+			off += sprintf(buff + off, ", MU_SKIP");
+
+		off += sprintf(buff + off, "\n");
+		printk(buff);
+
+		tcam_sw_clear(&te);
+		tcam_hw_read(&te, tid);
+
+		if (!(te.ctrl.flags & TCAM_F_INV)) {
+			tpm_print_tcam(0, &te, buff);
+			printk(buff);
+		}
+	}
+	return 0;
+}
+
+void tpm_print_mc_vlan_cfg_head(void)
+{
+	print_horizontal_line(65);
+	printk("=    MC VLAN      MC AI       Port        Mode      UNI MC VLAN =\n");
+	print_horizontal_line(65);
+}
+
+void tpm_print_mc_vlan_cfg(tpm_mc_vid_cfg_t *mc_vid_cfg)
+{
+	int32_t src_port;
+	char *src_port_str = "";
+	char *mc_mode_str  = "";
+
+	for (src_port = 0; src_port < TPM_MAX_NUM_UNI_PORTS; src_port++) {
+		src_port_str = tpm_db_src_port_str[mc_vid_cfg->mc_vid_port_vids[src_port].tpm_src_port];
+		mc_mode_str  = tpm_db_mc_uni_mode_str[mc_vid_cfg->mc_vid_port_vids[src_port].mc_uni_port_mode];
+		printk("=  %11s | %8s |   %4s  |  %11s |", "", "", src_port_str, mc_mode_str);
+
+		if (TPM_MC_UNI_MODE_TRANSLATE == mc_vid_cfg->mc_vid_port_vids[src_port].mc_uni_port_mode)
+			printk("  %4d %4s=\n", mc_vid_cfg->mc_vid_port_vids[src_port].uni_port_vid, "");
+		else
+			printk("%11s=\n", "");
+	}
+	return;
+}
+
+void tpm_print_mc_vlan_cfg_all(void)
+{
+	uint32_t i, rcode;
+	uint32_t ai_bit;
+	uint32_t first_rule = 1;
+
+	tpm_print_mc_vlan_cfg_head();
+	for (i = 0; i < TPM_MC_VID_NUM_MAX; i++) {
+		if (true == tpm_db.mc_vid_port_cfg[i].valid) {
+			if (!first_rule)
+				printk("=--------------|----------|----------|--------------|-----------=\n");
+
+			rcode = tpm_db_mc_vlan_get_ai_bit(tpm_db.mc_vid_port_cfg[i].mc_vid, &ai_bit);
+			if (rcode != TPM_DB_OK) {
+				printk("get DB failed: %d\n", rcode);
+				return;
+			}
+			printk("=     %4d     |    %2x    |%10s|%14s|%11s=\n",
+				tpm_db.mc_vid_port_cfg[i].mc_vid, ai_bit, "", "", "");
+
+			tpm_print_mc_vlan_cfg(&tpm_db.mc_vid_port_cfg[i]);
+			first_rule = 0;
+		}
+	}
+	print_horizontal_line(65);
+
+	return;
+}
+
+void tpm_print_section_free_szie(tpm_api_type_t api_type)
+{
+	int32_t section_free_szie = 0;
+	tpm_error_code_t rcode;
+
+	rcode = tpm_get_section_free_size(api_type, &section_free_szie);
+	if (rcode == TPM_OK)
+		printk("Section free size: %4d\n", section_free_szie);
+
+	return;
+}
+
+void tpm_print_gpon_omci_channel(void)
+{
+	uint32_t is_valid;
+	tpm_gem_port_key_t gem_port = 0;
+	uint32_t cpu_rx_queue;
+	uint32_t cpu_tx_queue = 0;
+	tpm_trg_port_type_t tcont_num;
+	tpm_error_code_t rcode;
+
+	rcode = tpm_omci_get_channel(&is_valid, &gem_port, &cpu_rx_queue, &tcont_num, &cpu_tx_queue);
+	if (rcode == TPM_OK)
+		printk("Valid = %d GEM = %d CPU_RX queue = %d CPU_TX queue = %d Tcont = 0x%4.4x\n",
+		is_valid, gem_port, cpu_rx_queue, cpu_tx_queue, tcont_num);
+
+	return;
+}
+
+void tpm_print_epon_oam_channel(void)
+{
+	uint32_t is_valid;
+	uint32_t cpu_rx_queue;
+	tpm_trg_port_type_t llid_num;
+	tpm_error_code_t rcode;
+
+	rcode = tpm_oam_epon_get_channel(&is_valid, &cpu_rx_queue, &llid_num);
+	if (rcode == TPM_OK)
+		printk("Valid = %d RX queue = %d LLID = 0x%4.4x\n", is_valid, cpu_rx_queue, llid_num);
+
+	return;
+}
+
+void tpm_print_busy_apis(void)
+{
+	tpm_api_type_t i;
+	uint32_t temp_api_busy_rulenums[TPM_MAX_PARALLEL_API_CALLS];
+	uint32_t num_busy, j;
+
+	for (i=0;i<TPM_MAX_API_TYPES;i++) {
+		memset(&temp_api_busy_rulenums[0], 0, sizeof(temp_api_busy_rulenums));
+		tpm_db_get_api_all_busy(i, &num_busy, &temp_api_busy_rulenums[0]);
+		if (num_busy > 0) {
+			printk("%s:\t",api_type_to_str(i));
+			for (j=0;j<num_busy;j++) {
+				printk("%d\t",temp_api_busy_rulenums[j]);
+			}
+			printk("\n");
+		}
+	}
+}
+
+void tpm_print_fc(unsigned int print_only)
+{
+	tpm_fc_info_t   *p_fc_inf = NULL;
+
+	if (print_only == 0) {
+		printk(KERN_INFO "Resetting Flow Control engine statistics\n");
+		tpm_fc_clear_stat();
+	} else if (print_only != 1) {
+		printk(KERN_INFO "UNEXPECTED PARAMETER (%d)\n", print_only);
+		return;
+	}
+
+	tpm_fc_get_info(&p_fc_inf);
+	if (p_fc_inf == NULL) {
+		printk(KERN_INFO "UNEXPECTED ERROR\n");
+		return;
+	}
+
+	printk(KERN_INFO "---------------------------------------------------------------------------------\n");
+	printk(KERN_INFO "FC is %s\n", (tpm_fc_is_running() == MV_TRUE) ? "ENABLED" : "DISABLED");
+	printk(KERN_INFO "The Flow Control engine settings:\n");
+	printk(KERN_INFO "\t Threshold: High = %ld, Low = %ld\n",
+	       (long)p_fc_inf->cfg.thresh_high,
+	       (long)p_fc_inf->cfg.thresh_low);
+	printk(KERN_INFO "\t Port %d, Target port = %d, TX port = %d, TX Queue = %d\n",
+	       p_fc_inf->cfg.port,
+	       p_fc_inf->cfg.tgt_port,
+	       p_fc_inf->cfg.tx_port,
+	       p_fc_inf->cfg.tx_queue);
+	printk(KERN_INFO "\t Queue status is checked every %lld ns\n", ktime_to_ns(p_fc_inf->cfg.hrt_hit_time));
+
+#ifdef TPM_FC_DEBUG
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "Latched statistics for oneshot counter configured to %d hits\n", p_fc_inf->cfg.oneshot_count);
+	printk(KERN_INFO "\t Total timer hits = %ld, Total late hits = %ld, timer wraprarounds = %ld \n",
+		   (long)p_fc_inf->oneshot_stat.hrt_hits_num,
+		   (long)p_fc_inf->oneshot_stat.hrt_lost_num,
+		   (long)p_fc_inf->oneshot_stat.hrt_wraparound);
+	printk(KERN_INFO "\t Highest \"late than expected\" period = %lld ns\n", p_fc_inf->oneshot_stat.hrt_lost_max_ns);
+	printk(KERN_INFO "\t Number of late hits of \"higher than expected\" period distribution in %%:\n");
+	printk(KERN_INFO "\t >200%%    - %lld\n", p_fc_inf->oneshot_stat.hrt_lost_200_up);
+	printk(KERN_INFO "\t 150-200%% - %lld\n", p_fc_inf->oneshot_stat.hrt_lost_150_200);
+	printk(KERN_INFO "\t 100-150%% - %lld\n", p_fc_inf->oneshot_stat.hrt_lost_100_150);
+	printk(KERN_INFO "\t 50-100%%  - %lld\n", p_fc_inf->oneshot_stat.hrt_lost_50_100);
+	printk(KERN_INFO "\t 25-50%%   - %lld\n", p_fc_inf->oneshot_stat.hrt_lost_25_50);
+	printk(KERN_INFO "\t <25%%     - %lld\n", p_fc_inf->oneshot_stat.hrt_lost_25_less);
+	printk(KERN_INFO "\n");
+
+	printk(KERN_INFO "Full statistics since start/reset\n");
+	printk(KERN_INFO "\t Total timer hits = %ld, Total late hits = %ld, timer wraprarounds = %ld \n",
+	       (long)p_fc_inf->stat.hrt_hits_num,
+	       (long)p_fc_inf->stat.hrt_lost_num,
+	       (long)p_fc_inf->stat.hrt_wraparound);
+	printk(KERN_INFO "\t Highest \"late than expected\" period = %lld ns\n", p_fc_inf->stat.hrt_lost_max_ns);
+	printk(KERN_INFO "\t Number of late hits of \"higher than expected\" period distribution in %%:\n");
+	printk(KERN_INFO "\t >200%%    - %lld\n", p_fc_inf->stat.hrt_lost_200_up);
+	printk(KERN_INFO "\t 150-200%% - %lld\n", p_fc_inf->stat.hrt_lost_150_200);
+	printk(KERN_INFO "\t 100-150%% - %lld\n", p_fc_inf->stat.hrt_lost_100_150);
+	printk(KERN_INFO "\t 50-100%%  - %lld\n", p_fc_inf->stat.hrt_lost_50_100);
+	printk(KERN_INFO "\t 25-50%%   - %lld\n", p_fc_inf->stat.hrt_lost_25_50);
+	printk(KERN_INFO "\t <25%%     - %lld\n", p_fc_inf->stat.hrt_lost_25_less);
+	printk(KERN_INFO "---------------------------------------------------------------------------------\n");
+#endif
+}
+
+void tpm_print_mac_learn_entry_count(void)
+{
+	uint32_t entry_count = 0;
+	tpm_error_code_t rcode;
+
+	rcode = tpm_mac_learn_entry_num_get(&entry_count);
+	if (rcode == TPM_OK)
+		printk("MAC learn entry count: %d\n", entry_count);
+
+	return;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.h
new file mode 100755
index 0000000..d1909fb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_print.h
@@ -0,0 +1,151 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_print.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1.1.1
+*
+*
+*******************************************************************************/
+
+#ifndef _TPM_PRINT_H_
+#define _TPM_PRINT_H_
+
+/********************************************************************************/
+/*                                Print Utils                                   */
+/********************************************************************************/
+#define DB_MAC_STR_LEN      25
+#define DB_IPV4_STR_LEN     17
+#define DB_IPV6_STR_LEN     40
+#define DB_IPV6_ADDR_LEN    16
+#define PRINT_PNC_ENTRY         1
+#define DONT_PRINT_PNC_ENTRY    0
+
+#define BuildEnumString(param) { param, #param"\0" }
+
+typedef struct {
+	int enumPar;
+	char enumString[128];
+} db_enum_string_t;
+
+char *db_mac_to_str(uint8_t *addr, char *str);
+char *db_ipv4_to_str(uint8_t *ipaddr, char *str);
+char *db_ipv6_to_str(uint8_t *ipaddr, char *str);
+
+/* TODO - following functions should use db functions, instead of accessing DB directly */
+void tpm_print_etherports(void);
+void tpm_print_tx_modules(void);
+void tpm_print_rx_modules(void);
+void tpm_print_gmac_config(void);
+void tpm_print_gmac_func(void);
+void tpm_print_igmp(void);
+void tpm_print_misc(void);
+void tpm_print_owners(void);
+void tpm_print_vlan_etype(void);
+void tpm_print_mac_key(tpm_mac_key_t *mac_key);
+void tpm_print_cpu_lpbk_entry(void);
+void tpm_print_tcam_lu_entry(uint32_t owner_id, uint32_t api_group, uint32_t lu_num, uint32_t lu_reset);
+void tpm_print_pnc_all_hit_counters(uint32_t owner_id, tpm_api_type_t api_type, uint32_t high_thresh_pkts,
+				    uint8_t counters_reset, uint16_t valid_counters,
+				    tpm_api_entry_count_t *count_array);
+
+void tpm_print_vlan_key(tpm_vlan_key_t *vlan_key);
+void tpm_print_ipv4_key(tpm_ipv4_acl_key_t *ipv4_key, tpm_ipv4_add_key_t *ipv4_add_key);
+void tpm_print_l2_key(tpm_l2_acl_key_t *l2_key);
+void tpm_print_l3_key(tpm_l3_type_key_t *l3_key);
+
+void tpm_print_valid_api_sections(void);
+void tpm_print_full_api_section(tpm_api_sections_t api_section);
+void tpm_print_pnc_shadow_range(uint32_t valid_only, uint32_t start, uint32_t end);
+void tpm_print_valid_pnc_ranges(void);
+void tpm_print_init_tables(void);
+void tpm_print_api_dump_all(void);
+int tpm_print_pnc(void);
+int  tpm_tcam_hw_hits(unsigned int print_pnc);
+void tpm_tcam_hw_record(int port);
+int  tpm_age_pnc_dump(void);
+int  tpm_age_pnc_dump_live(void);
+void tpm_print_pnc_field_desc(void);
+void tpm_print_mc_vlan_cfg_all(void);
+void tpm_print_section_free_szie(tpm_api_type_t api_type);
+void tpm_print_gpon_omci_channel(void);
+void tpm_print_epon_oam_channel(void);
+void tpm_print_busy_apis(void);
+void tpm_print_fc(unsigned int print_only);
+void tpm_init_eth_cmplx_setup_error_print(uint32_t hwEthCmplx, bool sysfs_call);
+void tpm_print_mac_learn_entry_count(void);
+
+
+#endif /* _TPM_PRINT_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_setup.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_setup.c
new file mode 100755
index 0000000..1438a48
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_setup.c
@@ -0,0 +1,918 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "globals.h"
+#include "errorCode.h"
+#include "OsGlueLayer.h"
+*/
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_types.h"
+#include "tpm_internal_types.h"
+#include "tpm_mng_if.h"
+#include "tpm_xml_params.h"
+
+tpm_init_t tpm_setup;
+int tpmDrvFd;
+/*GL_SEMAPHORE_ID tpmApiSemId;*/
+extern int32_t tpm_module_start(tpm_init_t *tpm_init);
+extern char *g_pstr_xml_cfg_file;
+
+int32_t tpm_init_pon_type_get_para(void)
+{
+
+	int32_t	rc = TPM_OK;
+	int 	app_rc;
+
+	app_rc = get_pon_type_param(&(tpm_setup.pon_type));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.pon_type = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_omci_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_omci_etype_param(&(tpm_setup.omci_etype));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.omci_etype = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+#if 0
+int32_t tpm_init_debport_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_debug_port_params(&(tpm_setup.deb_port_valid), &(tpm_setup.deb_port));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+
+	return rc;
+}
+#endif
+
+/* jinghua add for MTU setting */
+int32_t tpm_init_mtu_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_ipv4_mtu_us(&(tpm_setup.mtu_config.ipv4_mtu_us));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mtu_config.ipv4_mtu_us = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_ipv4_pppoe_mtu_us(&(tpm_setup.mtu_config.ipv4_pppoe_mtu_us));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mtu_config.ipv4_pppoe_mtu_us = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_ipv6_mtu_us(&(tpm_setup.mtu_config.ipv6_mtu_us));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mtu_config.ipv6_mtu_us = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_ipv6_pppoe_mtu_us(&(tpm_setup.mtu_config.ipv6_pppoe_mtu_us));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mtu_config.ipv6_pppoe_mtu_us = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_ipv6_mtu_ds(&(tpm_setup.mtu_config.ipv6_mtu_ds));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mtu_config.ipv6_mtu_ds = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_ipv4_mtu_ds(&(tpm_setup.mtu_config.ipv4_mtu_ds));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mtu_config.ipv4_mtu_ds = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_pppoe_add_enable(&(tpm_setup.pppoe_add_enable));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.pppoe_add_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_num_vlan_tags(&(tpm_setup.num_vlan_tags));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.num_vlan_tags = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_mtu_enable(&(tpm_setup.mtu_config.mtu_enable));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mtu_config.mtu_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_cpu_rx_queue(&(tpm_setup.cpu_rx_queue));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.cpu_rx_queue = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_ttl_illegal_action(&(tpm_setup.ttl_illegal_action));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.ttl_illegal_action = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_tcp_flag_check(&(tpm_setup.tcp_flag_check));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.tcp_flag_check = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_igmp_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+	tpm_src_port_type_t src_port;
+	uint32_t mode;
+
+	app_rc = get_igmp_snoop_params_enable(&(tpm_setup.igmp_snoop));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.igmp_snoop = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_igmp_snoop_params_cpu_queue(&(tpm_setup.igmp_cpu_queue));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.igmp_cpu_queue = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	for (src_port = TPM_SRC_PORT_UNI_0; src_port <= TPM_SRC_PORT_WAN; src_port++) {
+		app_rc = get_igmp_snoop_params_port_frwd_mode(&mode, src_port);
+		if (app_rc == TPM_FAIL)
+			rc = TPM_FAIL;
+		else if (app_rc == TPM_NOT_FOUND)
+			tpm_setup.igmp_pkt_frwd_mod[src_port] = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+		else
+			tpm_setup.igmp_pkt_frwd_mod[src_port] = mode;
+	}
+
+	return rc;
+}
+
+int32_t tpm_init_mc_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_mc_filter_mode(&(tpm_setup.mc_setting.filter_mode));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mc_setting.filter_mode = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+/*
+	app_rc = get_igmp_mode(&(tpm_setup.mc_setting.igmp_mode));
+	if (app_rc == TPM_FAIL)
+	{
+	   rc = TPM_FAIL;
+	}
+	else if (app_rc == TPM_NOT_FOUND)
+	{
+	   tpm_setup.mc_setting.igmp_mode = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+	}
+*/
+	app_rc = get_mc_per_uni_vlan_xlat(&(tpm_setup.mc_setting.per_uni_vlan_xlat));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mc_setting.per_uni_vlan_xlat = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_mc_pppoe_enable(&(tpm_setup.mc_setting.mc_pppoe_enable));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mc_setting.mc_pppoe_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_mc_queue(&(tpm_setup.mc_setting.mc_hwf_queue), &(tpm_setup.mc_setting.mc_cpu_queue));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND) {
+		tpm_setup.mc_setting.mc_hwf_queue = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+		tpm_setup.mc_setting.mc_cpu_queue = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+	}
+	
+	app_rc = get_ipv4_mc_support(&tpm_setup.mc_setting.ipv4_mc_support);
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mc_setting.ipv4_mc_support = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_ipv6_mc_support(&tpm_setup.mc_setting.ipv6_mc_support);
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.mc_setting.ipv6_mc_support = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_gmac_conn_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_gmac_conn_params(&(tpm_setup.num_tcont_llid));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.num_tcont_llid = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_eth_cmplx_profile_get_para(void)
+{
+	int32_t	rc = TPM_OK;
+	int 	app_rc;
+
+	app_rc = get_eth_cmplx_profile_params(&(tpm_setup.eth_cmplx_profile));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.eth_cmplx_profile = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_eth_port_conf_get_para(void)
+{
+	int32_t	rc = TPM_OK;
+	int 	app_rc;
+
+	app_rc = get_eth_port_conf_params(&(tpm_setup.eth_port_conf[0]), TPM_MAX_NUM_ETH_PORTS);
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+	{
+		int32_t i;
+		for (i=0; i < TPM_MAX_NUM_ETH_PORTS; i++){
+			tpm_setup.eth_port_conf[i].valid = TPM_FALSE;
+		}
+	}
+	return rc;
+}
+
+int32_t tpm_init_gmac_port_conf_get_para(void)
+{
+	int32_t	rc = TPM_OK;
+	int 	app_rc;
+
+	app_rc = get_gmac_port_conf_params(&(tpm_setup.gmac_port_conf[0]), TPM_NUM_GMACS);
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+	{
+		int32_t i;
+		for (i=0; i < TPM_NUM_GMACS; i++){
+			tpm_setup.gmac_port_conf[i].valid = TPM_FALSE;
+		}
+	}
+
+	return rc;
+}
+
+int32_t tpm_init_backup_wan_get_para(void)
+{
+	int32_t	rc = TPM_OK;
+	int 	app_rc;
+
+	app_rc = get_backup_wan_params(&(tpm_setup.backup_wan));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.backup_wan = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_gmac_mh_en_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_gmac_mh_en_params(&(tpm_setup.gmac0_mh_en), &(tpm_setup.gmac1_mh_en));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND) {
+		tpm_setup.gmac0_mh_en = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+		tpm_setup.gmac1_mh_en = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+	}
+	return rc;
+}
+
+int32_t tpm_init_gmac_pool_bufs_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_gmac_pool_bufs_params(&(tpm_setup.gmac_bp_bufs[0]), TPM_MAX_NUM_GMACS);
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+
+	return rc;
+}
+
+int32_t tpm_init_gmac_rx_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_gmac_rxq_params(&(tpm_setup.gmac_rx[0]), TPM_MAX_NUM_GMACS, TPM_MAX_NUM_RX_QUEUE);
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+
+	return rc;
+}
+
+int32_t tpm_init_gmac_tx_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_gmac_tx_params(&(tpm_setup.gmac_tx[0]), TPM_MAX_NUM_TX_PORTS, TPM_MAX_NUM_TX_QUEUE);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+
+	return rc;
+}
+
+int32_t tpm_init_pnc_config_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_pnc_range_params(&(tpm_setup.pnc_range[0]), TPM_MAX_NUM_RANGES);
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+
+	app_rc = get_catch_all_pkt_action(&(tpm_setup.catch_all_pkt_action));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.catch_all_pkt_action = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_ds_mh_config_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_ds_mh_config_params(&(tpm_setup.ds_mh_set_conf));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.ds_mh_set_conf = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_validation_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_validation_enabled_config_params(&(tpm_setup.validation_en));
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.validation_en = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_vlan_etypes_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_vlan_mod_vlan_tpid_params(&(tpm_setup.vlan_etypes[0]), TPM_NUM_VLAN_ETYPE_REGS);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.vlan_etypes[0] = 0x8100;
+
+	return rc;
+}
+
+int32_t tpm_init_mod_config_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_modification_params(&(tpm_setup.mod_config));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+
+	app_rc = get_chain_config_params(&(tpm_setup.mod_chain));
+	if (app_rc == TPM_FAIL)
+		rc |= TPM_FAIL;
+
+	return rc;
+}
+
+int32_t tpm_init_cfg_pnc_parse_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_cfg_pnc_parse_param(&(tpm_setup.cfg_pnc_parse));
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.cfg_pnc_parse = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_cpu_loopback_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_cpu_loopback_param(&(tpm_setup.cpu_loopback));
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.cpu_loopback = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_trace_debug_info_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_trace_debug_info_param(&(tpm_setup.trace_debug_info));
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.trace_debug_info = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_vitual_uni_info_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_vitual_uni_enable_params(&(tpm_setup.virt_uni_info.enabled));
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND) {
+		tpm_setup.virt_uni_info.enabled = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+		tpm_setup.virt_uni_info.uni_port = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+		tpm_setup.virt_uni_info.switch_port = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+	}
+
+	return rc;
+}
+
+int32_t tpm_init_default_tag_tpid_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+#if 0
+	app_rc = get_default_vlan_tpid_params(&(tpm_setup.vlan1_tpid), &(tpm_setup.vlan2_tpid));
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND) {
+		tpm_setup.vlan1_tpid = 0x8100;
+		tpm_setup.vlan2_tpid = 0x8100;
+	}
+#endif
+
+	app_rc = get_default_vlan_tpid_params(&tpm_setup.tpid_opt.opt_num, tpm_setup.tpid_opt.opt);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND) {
+		tpm_setup.tpid_opt.opt_num = 2;
+
+		tpm_setup.tpid_opt.opt[0].v1_tpid = 0x8100;
+		tpm_setup.tpid_opt.opt[0].v2_tpid = 0x8100;
+
+		tpm_setup.tpid_opt.opt[1].v1_tpid = 0x8100;
+		tpm_setup.tpid_opt.opt[1].v2_tpid = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+	}
+
+	return rc;
+}
+
+
+int32_t tpm_init_fc_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_fc_def_params(&tpm_setup.port_fc_conf);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND) {
+		tpm_setup.port_fc_conf.enabled 		= 0;
+		tpm_setup.port_fc_conf.port 		= 1;
+		tpm_setup.port_fc_conf.queue_sample_freq = 1000;
+		tpm_setup.port_fc_conf.tgt_port 	= 1;
+		tpm_setup.port_fc_conf.thresh_high 	= 0xffffffff;
+		tpm_setup.port_fc_conf.thresh_low 	= 0xffffffff;
+		tpm_setup.port_fc_conf.tx_port 		= 1;
+	}
+
+	return rc;
+}
+
+
+int32_t tpm_init_ety_dsa_enable_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_ety_dsa_enable(&tpm_setup.ety_dsa_enable);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.ety_dsa_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_ipv6_5t_enable_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_ipv6_5t_enable(&tpm_setup.ipv6_5t_enable);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.ipv6_5t_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_split_mod_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_split_mod_enable(&tpm_setup.split_mod_config.split_mod_enable);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.split_mod_config.split_mod_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_split_mot_p_bits(&tpm_setup.split_mod_config.p_bit[0], &tpm_setup.split_mod_config.p_bit_num);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.split_mod_config.p_bit_num = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_split_mod_vlan_num(&tpm_setup.split_mod_config.vlan_num);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.split_mod_config.vlan_num = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	app_rc = get_split_mod_mode(&tpm_setup.split_mod_config.split_mod_mode);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.split_mod_config.split_mod_mode = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_ctc_cm_enable_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_ctc_cm_enable(&tpm_setup.ctc_cm_enable);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.ctc_cm_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+
+int32_t tpm_init_ctc_cm_ipv6_parse_window_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+	app_rc = get_ctc_cm_ipv6_parse_window(&tpm_setup.ctc_cm_ipv6_parse_window);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.ctc_cm_ipv6_parse_window = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+int32_t tpm_init_pnc_mac_learn_enable_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_pnc_mac_learn_enable(&tpm_setup.pnc_mac_learn_enable);
+
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.pnc_mac_learn_enable = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	return rc;
+}
+int32_t tpm_init_switch_init_get_para(void)
+{
+	int32_t rc = TPM_OK;
+	int app_rc;
+
+	app_rc = get_switch_init_params(&(tpm_setup.switch_init));
+	if (app_rc == TPM_FAIL)
+		rc = TPM_FAIL;
+	else if (app_rc == TPM_NOT_FOUND)
+		tpm_setup.switch_init = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+	return rc;
+}
+
+/*******************************************************************************
+* module_tpmSetup()
+*
+* DESCRIPTION:
+*
+* INPUTS:
+*
+*
+* OUTPUTS:
+*
+*
+* RETURNS:
+*
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t module_tpmSetup(tpm_setup_t *tpm_initp)
+{
+	int32_t rc;
+
+	if (0 != tpm_initp->xml_file_path[0]) {
+		g_pstr_xml_cfg_file = tpm_initp->xml_file_path;
+		printk(KERN_ERR "ERROR: (%s:%d) change to cfg file path: %s \n", __func__, __LINE__,
+		       g_pstr_xml_cfg_file);
+	} else {
+		printk(KERN_ERR "WARNING: using default (%s:%d) cfg file path: %s \n", __func__, __LINE__,
+		       g_pstr_xml_cfg_file);
+	}
+
+	tpm_init_validation_get_para();
+
+	/* Initialized as sem_full
+	if (osSemCreate(&tpmApiSemId, "/TpmApiSem", 1, SEM_Q_FIFO, TRUE) != IAMBA_OK) {
+		printf("module_tpmSetup: Failed to create TPM API semaphore\n\r");
+		return ERROR;
+	}
+	 */
+
+	tpm_init_pon_type_get_para();
+	tpm_init_vlan_etypes_get_para();
+	tpm_init_vitual_uni_info_get_para();
+	tpm_init_default_tag_tpid_get_para();
+	tpm_init_cfg_pnc_parse_get_para();
+	tpm_init_cpu_loopback_get_para();
+	tpm_init_trace_debug_info_get_para();
+	tpm_init_omci_get_para();
+#if 0
+	tpm_init_debport_get_para();
+#endif
+	tpm_init_igmp_get_para();
+	tpm_init_mc_get_para();
+	/* jinghua add for MTU setting */
+	tpm_init_mtu_get_para();
+	tpm_init_fc_get_para();
+	tpm_init_eth_cmplx_profile_get_para();
+	tpm_init_eth_port_conf_get_para();
+	tpm_init_gmac_port_conf_get_para();
+	tpm_init_backup_wan_get_para();
+	tpm_init_gmac_conn_get_para();
+	tpm_init_gmac_rx_get_para();
+	tpm_init_gmac_tx_get_para();
+	tpm_init_gmac_mh_en_get_para();
+	tpm_init_gmac_pool_bufs_para();
+	tpm_init_pnc_config_get_para();
+	tpm_init_ds_mh_config_get_para();
+	tpm_init_mod_config_get_para();
+	tpm_init_ety_dsa_enable_get_para();
+	tpm_init_ipv6_5t_enable_get_para();
+	tpm_init_split_mod_get_para();
+	tpm_init_ctc_cm_enable_get_para();
+	tpm_init_ctc_cm_ipv6_parse_window_get_para();
+	tpm_init_pnc_mac_learn_enable_get_para();
+	tpm_init_switch_init_get_para();
+
+	free_xml_head_ptr();
+
+	rc = tpm_module_start(&tpm_setup);
+	if (rc != TPM_OK)
+		return (rc);
+
+	return (TPM_OK);
+}
+
+#if 0
+/*******************************************************************************
+* getTpmDrvFd()
+*
+* DESCRIPTION:   Get TPM driver file descriptor
+*
+* INPUTS:
+*
+*
+* OUTPUTS:
+*
+*
+* RETURNS:
+*
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int getTpmDrvFd(void)
+{
+	return (tpmDrvFd);
+}
+
+/*******************************************************************************
+* ponKernelExist()
+*
+* DESCRIPTION:   Verify whether the TPM driver exists
+*
+* INPUTS:
+*
+*
+* OUTPUTS:
+*
+*
+* RETURNS:
+*
+*
+* COMMENTS:
+*
+*******************************************************************************/
+void tpmKernelExist(void)
+{
+	FILE *fptr;
+	uint8_t *filename = "/proc/devices";
+	uint8_t line[120];
+	uint8_t *token;
+	uint8_t *search = " \n\r";
+
+	fptr = fopen(filename, "r");
+	if (fptr == 0) {
+		printf("%s: failed to open %s\n", __func__, filename);
+		return;
+	}
+
+	while (1) {
+		if (fgets(line, sizeof(line), fptr) != 0) {
+			token = strtok(line, search);
+			if (token != NULL) {
+				token = strtok(NULL, search);
+				if (token != NULL) {
+					if (strcmp("tpm", token) == 0) {
+						tpmDrvFd = open("/dev/tpm", O_RDWR);
+						if (tpmDrvFd < 0) {
+							printf("Failed to open /dev/tpm\n\r");
+							return;
+						}
+
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	fclose(fptr);
+}
+
+char *get_TPM_sw_version()
+{
+	return (TPM_SW_VERSION);
+}
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs.h
new file mode 100755
index 0000000..6c8603a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs.h
@@ -0,0 +1,90 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/*******************************************************************************
+* tpm_print.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1.1.1
+*
+*
+*******************************************************************************/
+
+#ifndef _TPM_SYSFS_H_
+#define _TPM_SYSFS_H_
+
+int tpm_sysfs_print_init(void);
+int tpm_sysfs_trace_init(void);
+
+#endif /* _TPM_SYSFS_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs_print.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs_print.c
new file mode 100755
index 0000000..de6ab9a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs_print.c
@@ -0,0 +1,536 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+static ssize_t tpm_sysfs_print_help(char *buf)
+{
+	int off = 0;
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+	off += sprintf(buf + off,
+		"cat help                                          - show this help\n");
+	off += sprintf(buf + off,
+		"cat etherports                                    - show TPM DB ethernet port configuration\n");
+	off += sprintf(buf + off, "cat rx_modules                                    - show TPM DB  rx configuration \n");
+	off += sprintf(buf + off,
+		"cat tx_modules                                    - show TPM DB tx modules configuration\n");
+	off += sprintf(buf + off, "cat gmac_cfg                                      - show TPM DB GMAC configuration\n");
+	off += sprintf(buf + off,
+		"cat gmac_func                                     - show TPM DB GMAC function configuration \n");
+	off += sprintf(buf + off, "cat igmp_cfg                                      - show TPM DB IGMP configuration \n");
+	off += sprintf(buf + off,
+		"cat misc_cfg                                      - show TPM DB Misc. configuration \n");
+	off += sprintf(buf + off,
+		"cat vlan_etype                                    - show TPM DB VLAN ethertypes configuration \n");
+	off += sprintf(buf + off,
+		"cat valid_api_section                             - show TPM DB API ranges configuration \n");
+	off += sprintf(buf + off,
+		"cat valid_pnc_range                               - show TPM DB PNC Ranges configuration \n");
+	off += sprintf(buf + off,
+		"cat init_tables                                   - show TPM DB Initialization configuration \n");
+	off += sprintf(buf + off,
+		"cat mtu_cfg                                       - show MTU running configuration \n");
+	off += sprintf(buf + off,
+		"cat tcam_hw_hits                                  - show TCAM HW entries hit table\n");
+	off += sprintf(buf + off,
+		"cat show_omci_channel                             - show gpon OMCI channel info\n");
+	off += sprintf(buf + off,
+		"cat show_oam_channel                              - show epon OAM channel info\n");
+	off += sprintf(buf + off,
+		"cat tcam_hw_hits_dump                             "\
+		"- show TCAM HW entries hit table including per hit TCAM/SRAM data\n");
+	off += sprintf(buf+off,
+		"cat api_dump                                      "
+		"- show TPM DB all API types (l2/l3/ipv4/ipv4mc/ipv6 api's)\n");
+	off += sprintf(buf+off,
+		"cat busy_apis                                      "
+		"- debug info. Show TPM API's that are in an active API call. Should always be empty. \n");
+	off += sprintf(buf + off,
+		"cat show_mac_learn_entry_count                     "
+		"- show MAC learn entry count. \n");
+	off += sprintf(buf + off,
+		 "cat show_fc_config                                - show FC engine configuration/statistics\n");
+	off += sprintf(buf + off,
+		 "echo 0 > show_fc_config                           - clear FC engine statistics\n");
+	off += sprintf(buf + off,
+		"echo section                 > api_section        "
+		"- show TPM DB specific API Section full configuration \n");
+	off += sprintf(buf + off,
+		"echo valid_only st end       > pnc_shadow_range   "
+		"- show TPM DB shadow PNC tables (start_entry, end_entry)\n");
+	off += sprintf(buf + off,
+		"echo <port>                  > tcam_hw_hits       "
+		"- start recording for port (GMAC0-%d GMAC1-%d PONMAC-%d)\n", TPM_ENUM_GMAC_0, TPM_ENUM_GMAC_1, TPM_ENUM_PMAC);
+#else
+	printk(KERN_WARNING "%s: sysfs help is not compiled (CONFIG_MV_TPM_SYSFS_HELP)\n", __func__);
+#endif
+	return off;
+}
+
+static ssize_t tpm_sysfs_print_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int off = 0;
+	const char *name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "help"))
+		off = tpm_sysfs_print_help(buf);
+	else if (!strcmp(name, "etherports"))
+		tpm_print_etherports();
+	else if (!strcmp(name, "rx_modules"))
+		tpm_print_rx_modules();
+	else if (!strcmp(name, "tx_modules"))
+		tpm_print_tx_modules();
+	else if (!strcmp(name, "gmac_cfg"))
+		tpm_print_gmac_config();
+	else if (!strcmp(name, "gmac_func"))
+		tpm_print_gmac_func();
+	else if (!strcmp(name, "igmp_cfg"))
+		tpm_print_igmp();
+	else if (!strcmp(name, "misc_cfg"))
+		tpm_print_misc();
+	else if (!strcmp(name, "vlan_etype"))
+		tpm_print_vlan_etype();
+	else if (!strcmp(name, "valid_api_section"))
+		tpm_print_valid_api_sections();
+	else if (!strcmp(name, "valid_pnc_range"))
+		tpm_print_valid_pnc_ranges();
+	else if (!strcmp(name, "init_tables"))
+		tpm_print_init_tables();
+	else if (!strcmp(name, "mtu_cfg"))
+		tpm_db_show_mtu_cfg();
+	else if (!strcmp(name, "length_check_range"))
+		tpm_mtu_print_len_chk_range();
+	else if (!strcmp(name, "api_dump"))
+		tpm_print_api_dump_all();
+	else if (!strcmp(name, "pnc_dump"))
+	      tpm_print_pnc();
+	else if (!strcmp(name, "tcam_hw_hits"))
+		return tpm_tcam_hw_hits(DONT_PRINT_PNC_ENTRY);
+	else if (!strcmp(name, "tcam_hw_hits_dump"))
+		return tpm_tcam_hw_hits(PRINT_PNC_ENTRY);
+	else if (!strcmp(name, "age_pnc_dump"))
+		return tpm_age_pnc_dump();
+	else if (!strcmp(name, "age_pnc_dump_live"))
+		return tpm_age_pnc_dump_live();
+	else if (!strcmp(name, "age_pnc_dump_hdrs"))
+		tpm_print_pnc_field_desc();
+	else if (!strcmp(name, "age_dump"))
+		mvPncAgingDump(0);
+	else if (!strcmp(name, "age_dump_all"))
+		mvPncAgingDump(1);
+	else if (!strcmp(name, "mc_vlan_dump"))
+		tpm_print_mc_vlan_cfg_all();
+	else if (!strcmp(name, "show_omci_channel"))
+		tpm_print_gpon_omci_channel();
+	else if (!strcmp(name, "show_oam_channel"))
+		tpm_print_epon_oam_channel();
+	else if (!strcmp(name, "busy_apis"))
+		tpm_print_busy_apis();
+	else if (!strcmp(name, "show_mac_learn_entry_count"))
+		tpm_print_mac_learn_entry_count();
+	else if (!strcmp(name, "show_fc_config"))
+		tpm_print_fc(1);
+	else
+		off = tpm_sysfs_print_help(buf);
+
+	return off;
+}
+
+#if 0				/*Keep as placeholder*/
+static ssize_t tpm_sysfs_print_1_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char *name = attr->attr.name;
+	unsigned int v;
+	unsigned long flags;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read input */
+	v = 0;
+
+	sscanf(buf, "%x", &v);
+
+	raw_local_irq_save(flags);
+
+	if (!strcmp(name, "place_holder"))
+		XXXXX(v);
+	else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	raw_local_irq_restore(flags);
+
+	return len;
+}
+#endif
+
+static ssize_t tpm_sysfs_print_2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char *name = attr->attr.name;
+	unsigned int p;
+	/*unsigned long flags;*/
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read input */
+	sscanf(buf, "%d", &p);
+
+	/*raw_local_irq_save(flags);*/
+
+	if (!strcmp(name, "api_section"))
+		tpm_print_full_api_section(p);
+	else if (!strcmp(name, "tcam_hw_hits"))
+		tpm_tcam_hw_record(p);
+	else if (!strcmp(name, "show_fc_config"))
+		tpm_print_fc(p);
+	else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	/*raw_local_irq_restore(flags);*/
+
+	return len;
+}
+
+static ssize_t tpm_sysfs_print_6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char *name = attr->attr.name;
+	unsigned int p, v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0;
+	/*unsigned long flags;*/
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read input */
+	sscanf(buf, "%d %d %d %d %x %x", &p, &v1, &v2, &v3, &v4, &v5);
+
+	/*raw_local_irq_save(flags);*/
+
+	if (!strcmp(name, "pnc_shadow_range"))
+		tpm_print_pnc_shadow_range(p, v1, v2);
+	else
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	/*raw_local_irq_restore(flags);*/
+
+	return len;
+}
+
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static ssize_t tpm_sysfs_mod2_help(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf + off,
+		"cat help_mod2_print                                           - show this help\n");
+	off += sprintf(buf + off,
+		"cat show_jump_cfg                                             - show jump area configuration\n");
+	off += sprintf(buf + off,
+		"echo chain_type                    > show_chain_cfg           - show chain configuration\n");
+	off += sprintf(buf + off,
+		"     chain_type:                   "
+		"[1-mh|2-mac|3-vlan|4-pppoe|5-l2_main|6-ipv4_napt|7-ipv4_mc|8-route]\n");
+	off += sprintf(buf + off,
+		"echo gmac_port                     > show_jump_pmt_entries    - show the pmt entries of gmac port\n");
+	off += sprintf(buf + off, "     gmac_port :                   [0-2]\n");
+	off += sprintf(buf + off,
+		"echo gmac_port chain_type          > show_chain_pmt_entries   - show the pmt entries of gmac port\n");
+	off += sprintf(buf + off, "     gmac_port :                   [0-2]\n");
+	off += sprintf(buf + off,
+		"     chain_type:                   "
+		"[0-all|1-mh|2-mac|3-vlan|4-pppoe|5-l2_main|6-ipv4_napt|7-ipv4_mc|8-route]\n");
+	off += sprintf(buf + off,
+		"echo gmac_port chain_type chain_id > show_chain_db_entry      - show one chain data base entry\n");
+	off += sprintf(buf + off, "     gmac_port :                   [0-2]\n");
+	off += sprintf(buf + off,
+		"     chain_type:                   "
+		"[1-mh|2-mac|3-vlan|4-pppoe|5-l2_main|6-ipv4_napt|7-ipv4_mc|8-route]\n");
+	off += sprintf(buf + off, "     chain_id  :                   chain index\n");
+	off += sprintf(buf + off,
+		"echo gmac_port chain_type          > show_chain_db            "
+		"- show all the chain database entries of one chain type\n");
+	off += sprintf(buf + off, "     gmac_port :                   [0-2]\n");
+	off += sprintf(buf + off,
+		"     chain_type:                   "
+		"[1-mh|2-mac|3-vlan|4-pppoe|5-l2_main|6-ipv4_napt|7-ipv4_mc|8-route]\n");
+	off += sprintf(buf + off,
+		"echo gmac_port                     > show_all_chain           "
+		"- show all the chain database entries\n");
+	off += sprintf(buf + off, "     gmac_port :                   [0-2]\n");
+	off += sprintf(buf + off,
+		"echo api_type                      > show_section_free_size   "
+		"- show specific API Section free size \n");
+	off += sprintf(buf + off,
+		"     api_type:                   "
+		"  [0-mgmt|1-cpu_lpk|2-l2|3-l3|4-ipv4|5-ipv4_mc|6-ipv6_gen|7-ipv6_dip|8-ipv6_nh|9-ipv6_l4]\n");
+
+	return off;
+}
+
+static ssize_t tpm_sysfs_mod2_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int off = 0;
+	const char *name = attr->attr.name;
+
+	if (!strcmp(name, "show_jump_cfg"))
+		tpm_db_mod2_show_jump_cfg_data();
+	else
+		off = tpm_sysfs_mod2_help(buf);
+
+	return off;
+}
+#else
+static ssize_t tpm_sysfs_mod2_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	printk(KERN_WARNING "%s: sysfs help is not compiled (CONFIG_MV_TPM_SYSFS_HELP)\n", __func__);
+	return 0;
+}
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+static ssize_t tpm_sysfs_mod2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char *name = attr->attr.name;
+	uint8_t arg_num;
+	uint32_t v1, v2, v3;
+
+	if (!strcmp(name, "show_chain_cfg")) {
+		arg_num = sscanf(buf, "%d", &v1);
+		if (arg_num == 1)
+			tpm_db_mod2_show_chain_cfg_data(v1);
+	} else if (!strcmp(name, "show_jump_pmt_entries")) {
+		arg_num = sscanf(buf, "%d", &v1);
+		if (arg_num == 1)
+			tpm_db_mod2_show_jump_pmt_entries(v1);
+	} else if (!strcmp(name, "show_chain_pmt_entries")) {
+		arg_num = sscanf(buf, "%d %d", &v1, &v2);
+		if (arg_num == 2)
+			tpm_db_mod2_show_chain_pmt_entries(v1, v2);
+	} else if (!strcmp(name, "show_chain_db_entry")) {
+		arg_num = sscanf(buf, "%d %d %d", &v1, &v2, &v3);
+		if (arg_num == 3)
+			tpm_db_mod2_show_chain_info_entries(v1, v2, v3);
+	} else if (!strcmp(name, "show_chain_db")) {
+		arg_num = sscanf(buf, "%d %d", &v1, &v2);
+		if (arg_num == 2)
+			tpm_db_mod2_show_chain_info_entries(v1, v2, 0xffff);
+	} else if (!strcmp(name, "show_all_chain")) {
+		arg_num = sscanf(buf, "%d", &v1);
+		if (arg_num == 1)
+			tpm_db_mod2_show_all_chain(v1);
+	} else if (!strcmp(name, "show_section_free_size")) {
+		arg_num = sscanf(buf, "%d", &v1);
+		if (arg_num == 1)
+			tpm_print_section_free_szie(v1);
+	}
+
+	return len;
+}
+
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static DEVICE_ATTR(help, S_IRUSR, tpm_sysfs_print_show, NULL);
+#endif
+static DEVICE_ATTR(etherports, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(rx_modules, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(tx_modules, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(gmac_cfg, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(gmac_func, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(igmp_cfg, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(misc_cfg, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(vlan_etype, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(valid_api_section, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(valid_pnc_range, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(init_tables, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(mtu_cfg, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(api_dump, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(show_omci_channel, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(show_oam_channel, S_IRUSR, tpm_sysfs_print_show, NULL);
+
+
+static DEVICE_ATTR(length_check_range, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(pnc_dump, S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(tcam_hw_hits,           S_IRUSR | S_IWUSR, tpm_sysfs_print_show, tpm_sysfs_print_2_store);
+static DEVICE_ATTR(tcam_hw_hits_dump,      S_IRUSR | S_IWUSR, tpm_sysfs_print_show, tpm_sysfs_print_2_store);
+static DEVICE_ATTR(age_pnc_dump,           S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(age_pnc_dump_live,      S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(age_pnc_dump_hdrs,      S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(age_dump,               S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(age_dump_all,           S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(mc_vlan_dump,           S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(busy_apis,              S_IRUSR, tpm_sysfs_print_show, NULL);
+static DEVICE_ATTR(show_mac_learn_entry_count, S_IRUSR, tpm_sysfs_print_show, NULL);
+
+static DEVICE_ATTR(api_section, S_IWUSR, tpm_sysfs_print_show, tpm_sysfs_print_2_store);
+static DEVICE_ATTR(pnc_shadow_range, S_IWUSR, tpm_sysfs_print_show, tpm_sysfs_print_6_store);
+
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static DEVICE_ATTR(help_mod2_print, S_IRUSR, tpm_sysfs_mod2_show, NULL);
+#endif
+static DEVICE_ATTR(show_jump_cfg, S_IRUSR, tpm_sysfs_mod2_show, NULL);
+static DEVICE_ATTR(show_chain_cfg, S_IWUSR, tpm_sysfs_mod2_show, tpm_sysfs_mod2_store);
+static DEVICE_ATTR(show_jump_pmt_entries, S_IWUSR, tpm_sysfs_mod2_show, tpm_sysfs_mod2_store);
+static DEVICE_ATTR(show_chain_pmt_entries, S_IWUSR, tpm_sysfs_mod2_show, tpm_sysfs_mod2_store);
+static DEVICE_ATTR(show_chain_db_entry, S_IWUSR, tpm_sysfs_mod2_show, tpm_sysfs_mod2_store);
+static DEVICE_ATTR(show_chain_db, S_IWUSR, tpm_sysfs_mod2_show, tpm_sysfs_mod2_store);
+static DEVICE_ATTR(show_all_chain, S_IWUSR, tpm_sysfs_mod2_show, tpm_sysfs_mod2_store);
+static DEVICE_ATTR(show_section_free_size, S_IWUSR, tpm_sysfs_mod2_show, tpm_sysfs_mod2_store);
+
+static DEVICE_ATTR(show_fc_config,          S_IRUSR | S_IWUSR, tpm_sysfs_print_show, tpm_sysfs_print_2_store);
+
+static struct attribute *tpm_print_attrs[] = {
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+	&dev_attr_help.attr,
+#endif
+	&dev_attr_etherports.attr,
+	&dev_attr_rx_modules.attr,
+	&dev_attr_tx_modules.attr,
+	&dev_attr_gmac_cfg.attr,
+	&dev_attr_gmac_func.attr,
+	&dev_attr_igmp_cfg.attr,
+	&dev_attr_misc_cfg.attr,
+	&dev_attr_vlan_etype.attr,
+	&dev_attr_valid_api_section.attr,
+	&dev_attr_valid_pnc_range.attr,
+	&dev_attr_init_tables.attr,
+	&dev_attr_api_section.attr,
+	&dev_attr_pnc_shadow_range.attr,
+	&dev_attr_mtu_cfg.attr,
+	&dev_attr_length_check_range.attr,
+	&dev_attr_api_dump.attr,
+	&dev_attr_pnc_dump.attr,
+	&dev_attr_tcam_hw_hits.attr,
+	&dev_attr_tcam_hw_hits_dump.attr,
+	&dev_attr_age_pnc_dump.attr,
+	&dev_attr_age_pnc_dump_live.attr,
+	&dev_attr_age_pnc_dump_hdrs.attr,
+	&dev_attr_age_dump.attr,
+	&dev_attr_age_dump_all.attr,
+	&dev_attr_mc_vlan_dump.attr,
+	&dev_attr_show_omci_channel.attr,
+	&dev_attr_show_oam_channel.attr,
+	&dev_attr_busy_apis.attr,
+	&dev_attr_show_mac_learn_entry_count.attr,
+	&dev_attr_show_fc_config.attr,
+
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+	&dev_attr_help_mod2_print.attr,
+#endif
+	&dev_attr_show_jump_cfg.attr,
+	&dev_attr_show_chain_cfg.attr,
+	&dev_attr_show_jump_pmt_entries.attr,
+	&dev_attr_show_chain_pmt_entries.attr,
+	&dev_attr_show_chain_db_entry.attr,
+	&dev_attr_show_chain_db.attr,
+	&dev_attr_show_all_chain.attr,
+	&dev_attr_show_section_free_size.attr,
+
+	NULL
+};
+
+static struct attribute_group tpm_print_group = {
+	.name = "print",
+	.attrs = tpm_print_attrs,
+};
+
+int tpm_sysfs_print_init(void)
+{
+	int err;
+	struct device *pd;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "tpm");
+	if (!pd) {
+		platform_device_register_simple("tpm", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "tpm");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR "%s: cannot find tpm device\n", __func__);
+		pd = &platform_bus;
+	}
+
+	err = sysfs_create_group(&pd->kobj, &tpm_print_group);
+	if (err) {
+		printk(KERN_ERR "sysfs group failed %d\n", err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+/*module_init(xxx); */
+
+MODULE_AUTHOR("Yuval Caduri");
+MODULE_DESCRIPTION("sysfs for TPM Print");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs_trace.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs_trace.c
new file mode 100755
index 0000000..0933a4f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_sysfs_trace.c
@@ -0,0 +1,211 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+static ssize_t tpm_sysfs_trace_help(char *buf)
+{
+	int off = 0;
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+	off += sprintf(buf + off, "cat help                   - show this help\n");
+	off += sprintf(buf + off, "cat trace                  - show TPM Trace configuration\n");
+	off += sprintf(buf + off,
+		"echo level  > trace_level  - "
+		"Set TPM Global Trace level (0-none, 1-debug, 2-info, 3-warn, 4-err, 5-fatal)\n");
+	off += sprintf(buf + off,
+		"echo mod en > trace_module - Trace en/dis TPM module"
+		"(0-db, 1-pnc_logic, 2-init, 5-proc_logic, 6-cli, 7-pnc_hw, 9-mod)\n");
+#else
+	printk(KERN_WARNING "%s: sysfs help is not compiled (CONFIG_MV_TPM_SYSFS_HELP)\n", __func__);
+#endif
+	return off;
+}
+
+static ssize_t tpm_sysfs_trace_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int off = 0;
+	const char *name = attr->attr.name;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "trace"))
+		off = tpm_trace_status_print();
+	else
+		off = tpm_sysfs_trace_help(buf);
+
+	return off;
+}
+
+static ssize_t tpm_sysfs_trace_1_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char *name = attr->attr.name;
+	unsigned int v;
+	/*unsigned long flags;*/
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read input */
+	v = 0;
+
+	sscanf(buf, "%x", &v);
+
+	/*raw_local_irq_save(flags);*/
+
+	if (!strcmp(name, "trace_level"))
+		tpm_trace_set(v);
+	else
+		printk(KERN_INFO "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	/*raw_local_irq_restore(flags);*/
+
+	return len;
+}
+
+static ssize_t tpm_sysfs_trace_2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char *name = attr->attr.name;
+	unsigned int p, v;
+	/*unsigned long flags;*/
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read input */
+	v = 0;
+	sscanf(buf, "%d %x", &p, &v);
+
+	/*raw_local_irq_save(flags);*/
+
+	if (!strcmp(name, "trace_module"))
+		tpm_trace_module_set(p, v);
+	else
+		printk(KERN_INFO "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+
+	/*raw_local_irq_restore(flags);*/
+
+	return len;
+}
+
+static DEVICE_ATTR(trace_level, S_IWUSR, tpm_sysfs_trace_show, tpm_sysfs_trace_1_store);
+static DEVICE_ATTR(trace_module, S_IWUSR, tpm_sysfs_trace_show, tpm_sysfs_trace_2_store);
+static DEVICE_ATTR(trace, S_IRUSR, tpm_sysfs_trace_show, NULL);
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static DEVICE_ATTR(help, S_IRUSR, tpm_sysfs_trace_show, NULL);
+#endif
+static struct attribute *tpm_trace_attrs[] = {
+	&dev_attr_trace_level.attr,
+	&dev_attr_trace_module.attr,
+	&dev_attr_trace.attr,
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+	&dev_attr_help.attr,
+#endif
+	NULL
+};
+
+static struct attribute_group tpm_trace_group = {
+	.name = "trace",
+	.attrs = tpm_trace_attrs,
+};
+
+int tpm_sysfs_trace_init(void)
+{
+	int err;
+	struct device *pd;
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "tpm");
+	if (!pd) {
+		platform_device_register_simple("tpm", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "tpm");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR "%s: cannot find tpm device\n", __func__);
+		pd = &platform_bus;
+	}
+
+	err = sysfs_create_group(&pd->kobj, &tpm_trace_group);
+	if (err) {
+		printk(KERN_INFO "sysfs group failed %d\n", err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+/*module_init(xxx); */
+
+MODULE_AUTHOR("Yuval Caduri");
+MODULE_DESCRIPTION("sysfs for TPM Trace");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.c
new file mode 100755
index 0000000..3c88ca6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.c
@@ -0,0 +1,499 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/*******************************************************************************
+* tpm_tm.c
+*
+*
+*  MODULE : TPM
+*
+*  DESCRIPTION : This file config tpm traffic mng
+*
+*  MODIFICATION HISTORY:
+*           15Aug10   Orenbh - initial version created.
+*
+* FILE REVISION NUMBER:
+*       Revision: 1.1.1.1
+*******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+/*******************************************************************************
+* tpm_tm_set_wan_egr_queue_sched()
+*
+* DESCRIPTION:      Configures the scheduling mode per WAN queue.
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       sched_ent         - entity for setting the scheduling mode: ex:TPM_TRG_PORT_WAN
+*       sched_mode        - scheduler mode per port: strict(0) / wrr(1)
+*       queue_id          - queue number
+*       wrr_weight        - weight value when WRR scheduling (1-256)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_egr_queue_sched(IN uint32_t owner_id,
+						IN tpm_trg_port_type_t sched_ent,
+						IN tpm_pp_sched_type_t sched_mode,
+						IN uint8_t queue_id,
+						IN uint16_t wrr_weight)
+{
+	tpm_error_code_t retVal = TPM_RC_OK;
+	uint32_t i = 0;
+	uint32_t num_tcont_llid = 0;
+
+	printk(KERN_INFO "==ENTER==%s: owner_id[%d],sched_ent[%d],sched_mode[%d],"
+		"             queue_id[%d], wrr_weight[%d]\n\r",
+		__func__, owner_id, sched_ent, sched_mode, queue_id, wrr_weight);
+
+	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
+		printk(KERN_INFO "==ERROE==%s: Invalid queue number: owner_id[%d],sched_ent[%d],sched_mode[%d],"
+			"                                    queue_id[%d], wrr_weight[%d]\n\r",
+			__func__, owner_id, sched_ent, sched_mode, queue_id, wrr_weight);
+		return ERR_SW_TM_QUEUE_INVALID;
+	}
+
+	if ((sched_mode == TPM_PP_SCHED_WRR) && (wrr_weight > TPM_MAX_WRR_WEIGHT)) {
+
+		printk(KERN_INFO "==ERROE==%s: WRR weight is out of rage: owner_id[%d],sched_mode[%d],"
+			"                                   queue_id[%d], wrr_weight[%d]\n\r",
+			__func__, owner_id, sched_mode, queue_id, wrr_weight);
+		return ERR_SW_TM_QUEUE_INVALID;
+	}
+
+	tpm_db_num_tcont_llid_get(&num_tcont_llid);
+	for (i = 0; i < num_tcont_llid; i++) {
+		if (sched_ent & 0x1) {
+			switch (sched_mode) {
+			case TPM_PP_SCHED_STRICT:
+				mvNetaTxqFixPrioSet(PON_PORT, i, queue_id);
+				break;
+
+			case TPM_PP_SCHED_WRR:
+				mvNetaTxqWrrPrioSet(PON_PORT, i, queue_id, wrr_weight);
+				break;
+
+			default:
+				printk(KERN_ERR " Unknown TXQ command \n");
+				return ERR_GENERAL;
+			}
+		}
+		sched_ent = sched_ent >> 1;
+		if (sched_ent == 0)
+			break;
+	}
+	if ((sched_ent != 0) && (i == num_tcont_llid - 1))
+		printk(KERN_INFO "TCONT doesn't not exist\n");
+
+	printk(KERN_INFO "==EXIT== %s:\n\r", __func__);
+
+	return retVal;
+}
+EXPORT_SYMBOL(tpm_tm_set_wan_egr_queue_sched);
+
+/*******************************************************************************
+* tpm_tm_set_wan_sched_egr_rate_lim()
+*
+* DESCRIPTION:      Configures the egress rate limit of upstream traffic.
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       sched_ent         - entity for setting the rate limit: ex:TPM_TRG_PORT_WAN
+*       rate_limit_val    - egress rate limit value
+*       bucket_size       - bucket size value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success, the function returns TPM_RC_OK. On error different types are returned
+*       according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_sched_egr_rate_lim(IN uint32_t owner_id,
+						IN tpm_trg_port_type_t sched_ent,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size)
+{
+	uint32_t i = 0;
+	uint32_t num_tcont_llid = 0;
+
+	printk(KERN_INFO "==ENTER==%s: owner_id[%d],sched_ent[%d],rate_limit_val[%d], bucket_size[%d]\n\r",
+		__func__, owner_id, sched_ent, rate_limit_val, bucket_size);
+
+	tpm_db_num_tcont_llid_get(&num_tcont_llid);
+	for (i = 0; i < num_tcont_llid; i++) {
+		if (sched_ent & 0x1) {
+
+			if (mvNetaTxpBurstSet(PON_PORT, i, bucket_size) != MV_OK) {
+				printk(KERN_INFO
+					"==ERROE==%s: Invalid bucket size value: "
+					"owner_id[%d],sched_ent[%d] bucket_size[%d]\n\r",
+					__func__, owner_id, i, bucket_size);
+				return ERR_SW_TM_BUCKET_SIZE_INVALID;
+			}
+			mvNetaTxpRateSet(PON_PORT, i, rate_limit_val);
+		}
+		sched_ent = sched_ent >> 1;
+		if (sched_ent == 0)
+			break;
+	}
+	if ((sched_ent != 0) && (i == num_tcont_llid - 1))
+		printk(KERN_INFO "TCONT doesn't not exist\n");
+
+	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+
+	return TPM_RC_OK;
+
+}
+EXPORT_SYMBOL(tpm_tm_set_wan_sched_egr_rate_lim);
+
+/*******************************************************************************
+* tpm_tm_set_wan_queue_egr_rate_lim()
+*
+* DESCRIPTION:      Configures the upstream traffic egress rate limit for a specific
+*                   queue of an upstream scheduling entity.
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       sched_ent         - entity for setting the rate limit: ex:TPM_TRG_PORT_WAN
+*       queue_id          - queue number
+*       rate_limit_val    - egress rate limit value
+*       bucket_size       - bucket size value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success, the function returns TPM_RC_OK. On error different types are returned
+*       according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_queue_egr_rate_lim(IN uint32_t owner_id,
+						IN tpm_trg_port_type_t sched_ent,
+						IN uint32_t queue_id,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size)
+{
+	uint32_t i = 0;
+	uint32_t num_tcont_llid = 0;
+
+	printk(KERN_INFO "==ENTER==%s: owner_id[%d],sched_ent[%d],queue_id[%d]"
+		"             rate_limit_val[%d], bucket_size[%d] \n\r",
+		__func__, owner_id, sched_ent, queue_id, rate_limit_val, bucket_size);
+
+	tpm_db_num_tcont_llid_get(&num_tcont_llid);
+
+	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
+
+		printk(KERN_INFO "==ERROE==%s: Invalid queue number: owner_id[%d],sched_ent[%d],queue_id[%d]"
+			"                                   rate_limit_val[%d], bucket_size[%d] \n\r",
+			__func__, owner_id, sched_ent, queue_id, rate_limit_val, bucket_size);
+		return ERR_SW_TM_QUEUE_INVALID;
+	}
+
+	for (i = 0; i < num_tcont_llid; i++) {
+		if (sched_ent & 0x1) {
+
+			if (mvNetaTxqBurstSet(PON_PORT, i, queue_id, bucket_size) != MV_OK) {
+				printk(KERN_INFO
+					"==ERROE==%s: Invalid bucket size value: owner_id[%d], sched_ent[%d], queue_id[%d]"
+					"             rate_limit_val[%d], bucket_size[%d] \n\r", __func__, owner_id,
+					i, queue_id, rate_limit_val, bucket_size);
+				return ERR_SW_TM_BUCKET_SIZE_INVALID;
+			}
+			mvNetaTxqRateSet(PON_PORT, i, queue_id, rate_limit_val);
+		}
+		sched_ent = sched_ent >> 1;
+		if (sched_ent == 0)
+			break;
+	}
+	if ((sched_ent != 0) && (i == num_tcont_llid - 1))
+		printk(KERN_INFO "TCONT doesn't not exist\n");
+
+	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_tm_set_wan_queue_egr_rate_lim);
+
+/*******************************************************************************
+* tpm_tm_set_wan_ingr_queue_sched()
+*
+* DESCRIPTION:      Configures the scheduling mode per all downstream traffic from the WAN.
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       sched_mode        - scheduler mode per port: strict(0) / wrr(1)
+*       queue_id          - queue number
+*       wrr_weight        - weight value when WRR scheduling (1-256)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_ingr_queue_sched(IN uint32_t owner_id,
+						IN tpm_pp_sched_type_t sched_mode,
+						IN uint8_t queue_id,
+						IN uint16_t wrr_weight)
+{
+	uint32_t tmp_tcont = 0;
+
+	printk(KERN_INFO "==ENTER==%s: owner_id[%d],sched_mode[%d],"
+		"             queue_id[%d], wrr_weight[%d]\n\r",
+		__func__, owner_id, sched_mode, queue_id, wrr_weight);
+
+	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
+
+		printk(KERN_INFO "==ERROE==%s: Invalid queue number: owner_id[%d],sched_mode[%d],"
+			"                                   queue_id[%d], wrr_weight[%d]\n\r",
+			__func__, owner_id, sched_mode, queue_id, wrr_weight);
+		return ERR_SW_TM_QUEUE_INVALID;
+	}
+
+	if ((sched_mode == TPM_PP_SCHED_WRR) && (wrr_weight > TPM_MAX_WRR_WEIGHT)) {
+
+		printk(KERN_INFO "==ERROE==%s: WRR weight is out of rage: owner_id[%d],sched_mode[%d],"
+			"                                   queue_id[%d], wrr_weight[%d]\n\r",
+			__func__, owner_id, sched_mode, queue_id, wrr_weight);
+		return ERR_SW_TM_QUEUE_INVALID;
+	}
+
+	switch (sched_mode) {
+	case TPM_PP_SCHED_STRICT:
+		mvNetaTxqFixPrioSet(SW_GMAC_0, tmp_tcont, queue_id);
+		break;
+
+	case TPM_PP_SCHED_WRR:
+		mvNetaTxqWrrPrioSet(SW_GMAC_0, tmp_tcont, queue_id, wrr_weight);
+		break;
+
+	default:
+		printk(KERN_ERR " Unknown TXQ command \n");
+		return ERR_GENERAL;
+
+	}
+
+	printk(KERN_INFO "==EXIT== %s:\n\r", __func__);
+
+	return TPM_RC_OK;
+
+}
+EXPORT_SYMBOL(tpm_tm_set_wan_ingr_queue_sched);
+
+/*******************************************************************************
+* tpm_tm_set_wan_ingr_rate_lim()
+*
+* DESCRIPTION:      Configures the rate limit of all downstream traffic from the WAN.
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       rate_limit_val    - ingress rate limit value
+*       bucket_size       - bucket size value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success, the function returns TPM_RC_OK. On error different types are returned
+*       according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_ingr_rate_lim(IN uint32_t owner_id,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size)
+{
+	uint32_t tmp_tcont = 0;
+
+	printk(KERN_INFO "==ENTER==%s: owner_id[%d],rate_limit_val[%d] bucket_size[%d]\n\r",
+		__func__, owner_id, rate_limit_val, bucket_size);
+
+	if (mvNetaTxpBurstSet(SW_GMAC_0, tmp_tcont, bucket_size) != MV_OK) {
+		printk(KERN_INFO
+			"==ERROE==%s: Invalid bucket size value: owner_id[%d],rate_limit_val[%d] bucket_size[%d]\n\r",
+			__func__, owner_id, rate_limit_val, bucket_size);
+		return ERR_SW_TM_BUCKET_SIZE_INVALID;
+	}
+
+	mvNetaTxpRateSet(SW_GMAC_0, tmp_tcont, rate_limit_val);
+
+	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_tm_set_wan_ingr_rate_lim);
+
+/*******************************************************************************
+* tpm_tm_set_wan_q_ingr_rate_lim()
+*
+* DESCRIPTION:      Configures the egress rate limit of a specific queue for
+*                   downstream traffic.
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       queue_id          - queue number
+*       rate_limit_val    - ingress rate limit value
+*       bucket_size       - bucket size value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success, the function returns TPM_RC_OK. On error different types are returned
+*       according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_q_ingr_rate_lim(IN uint32_t owner_id,
+						IN uint32_t queue_id,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size)
+{
+	uint32_t tmp_tcont = 0;
+
+	printk(KERN_INFO "==ENTER==%s: owner_id[%d], queue_id[%d]"
+		"             rate_limit_val[%d], bucket_size[%d] \n\r",
+		__func__, owner_id, queue_id, rate_limit_val, bucket_size);
+
+	if (queue_id >= TPM_MAX_NUM_TX_QUEUE) {
+		printk(KERN_INFO "==ERROE==%s: Invalid queue number: owner_id[%d], queue_id[%d]"
+			"                                   rate_limit_val[%d], bucket_size[%d] \n\r",
+			__func__, owner_id, queue_id, rate_limit_val, bucket_size);
+		return ERR_SW_TM_QUEUE_INVALID;
+	}
+
+	if (mvNetaTxqBurstSet(SW_GMAC_0, tmp_tcont, queue_id, bucket_size) != MV_OK) {
+		printk(KERN_INFO "==ERROE==%s: Invalid bucket size value: owner_id[%d], queue_id[%d]"
+			"              rate_limit_val[%d], bucket_size[%d] \n\r",
+			__func__, owner_id, queue_id, rate_limit_val, bucket_size);
+		return ERR_SW_TM_BUCKET_SIZE_INVALID;
+	}
+
+	mvNetaTxqRateSet(SW_GMAC_0, tmp_tcont, queue_id, rate_limit_val);
+
+	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+
+	return TPM_RC_OK;
+}
+EXPORT_SYMBOL(tpm_tm_set_wan_q_ingr_rate_lim);
+
+/*******************************************************************************
+* tpm_tm_set_gmac0_ingr_rate_lim()
+*
+* DESCRIPTION:      Configures the ingress rate limit of US for MC only
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       rate_limit_val    - ingress rate limit value
+*       bucket_size       - bucket size value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success, the function returns TPM_RC_OK. On error different types are returned
+*       according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_gmac0_ingr_rate_lim(IN uint32_t owner_id,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size)
+{
+	uint32_t tmp_tcont = 0;
+	uint32_t queue_id;
+	tpm_gmacs_enum_t lpk_gmac;
+
+	printk(KERN_INFO "==ENTER==%s: owner_id[%d], rate_limit_val[%d], bucket_size[%d] \n\r",
+		__func__, owner_id, rate_limit_val, bucket_size);
+
+	/*Get Tx queue on loopback gmac*/
+	if (TPM_DB_OK != tpm_db_gmac_lpk_queue_get(&lpk_gmac, &queue_id)) {
+		printk(KERN_INFO "==ERROR==%s: loopback gmac queue get failed \n\r", __func__);
+		return ERR_GENERAL;
+	}
+
+	if (mvNetaTxqBurstSet((int)lpk_gmac, tmp_tcont, queue_id, bucket_size) != MV_OK) {
+		printk(KERN_INFO "==ERROR==%s: Invalid bucket size value: owner_id[%d], queue_id[%d]"
+			"              rate_limit_val[%d], bucket_size[%d] \n\r",
+			__func__, owner_id, queue_id, rate_limit_val, bucket_size);
+		return ERR_SW_TM_BUCKET_SIZE_INVALID;
+	}
+
+	mvNetaTxqRateSet(SW_GMAC_1, tmp_tcont, queue_id, rate_limit_val);
+
+	printk(KERN_INFO "==EXIT== %s: \n\r", __func__);
+
+	return TPM_RC_OK;
+
+}
+EXPORT_SYMBOL(tpm_tm_set_gmac0_ingr_rate_lim);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.h
new file mode 100755
index 0000000..dabec88
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_tm.h
@@ -0,0 +1,253 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_tm.h
+*
+*
+*  MODULE : TPM
+*
+*  DESCRIPTION : This file config tpm
+*
+*  MODIFICATION HISTORY:
+*           15Aug10   Orenbh  - initial version created.
+*
+* FILE REVISION NUMBER:
+*       Revision: 1.1.1.1
+*******************************************************************************/
+
+#ifndef _TPM_TM_H_
+#define _TPM_TM_H_
+
+#define  IN
+#define  OUT
+
+/*******************************************************************************
+* tpm_tm_set_wan_egr_queue_sched()
+*
+* DESCRIPTION:      Configures the scheduling mode per WAN queue.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* sched_ent         - entity for setting the scheduling mode: ex:TPM_TRG_PORT_WAN
+* sched_mode        - scheduler mode per port: strict(0) / wrr(1)
+* queue_id          - queue number
+* wrr_weight        - weight value when WRR scheduling (1-256)
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_egr_queue_sched(IN uint32_t owner_id,
+						IN tpm_trg_port_type_t sched_ent,
+						IN tpm_pp_sched_type_t sched_mode,
+						IN uint8_t queue_id,
+						IN uint16_t wrr_weight);
+
+/*******************************************************************************
+* tpm_tm_set_wan_sched_egr_rate_lim()
+*
+* DESCRIPTION:      Configures the egress rate limit of upstream traffic.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* sched_ent         - entity for setting the rate limit: ex:TPM_TRG_PORT_WAN
+* rate_limit_val    - egress rate limit value
+* bucket_size       - bucket size value
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_sched_egr_rate_lim(IN uint32_t owner_id,
+						IN tpm_trg_port_type_t sched_ent,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size);
+
+/*******************************************************************************
+* tpm_tm_set_wan_queue_egr_rate_lim()
+*
+* DESCRIPTION:      Configures the upstream traffic egress rate limit for a specific
+*                   queue of an upstream scheduling entity.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* sched_ent         - entity for setting the rate limit: ex:TPM_TRG_PORT_WAN
+* queue_id          - queue number
+* rate_limit_val    - egress rate limit value
+* bucket_size       - bucket size value
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_queue_egr_rate_lim(IN uint32_t owner_id,
+						IN tpm_trg_port_type_t sched_ent,
+						IN uint32_t queue_id,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size);
+/*******************************************************************************
+* tpm_tm_set_wan_ingr_queue_sched()
+*
+* DESCRIPTION:      Configures the scheduling mode per all downstream traffic from the WAN.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* sched_mode        - scheduler mode per port: strict(0) / wrr(1)
+* queue_id          - queue number
+* wrr_weight        - weight value when WRR scheduling (1-256)
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_ingr_queue_sched(IN uint32_t owner_id,
+						IN tpm_pp_sched_type_t sched_mode,
+						IN uint8_t queue_id,
+						IN uint16_t wrr_weight);
+
+/*******************************************************************************
+* tpm_tm_set_wan_ingr_rate_lim()
+*
+* DESCRIPTION:      Configures the rate limit of all downstream traffic from the WAN.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* rate_limit_val    - ingress rate limit value
+* bucket_size       - bucket size value
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_ingr_rate_lim(IN uint32_t owner_id,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size);
+
+/*******************************************************************************
+* tpm_tm_set_wan_q_ingr_rate_lim()
+*
+* DESCRIPTION:      Configures the egress rate limit of a specific queue for
+*                   downstream traffic.
+*
+* INPUTS:
+* owner_id          - APP owner id  should be used for all API calls.
+* queue_id          - queue number
+* rate_limit_val    - ingress rate limit value
+* bucket_size       - bucket size value
+*
+* OUTPUTS:
+*  None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_wan_q_ingr_rate_lim(IN uint32_t owner_id,
+						IN uint32_t queue_id,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size);
+
+/*******************************************************************************
+* tpm_tm_set_gmac0_ingr_rate_lim()
+*
+* DESCRIPTION:      Configures the ingress rate limit of US for MC only
+*
+* INPUTS:
+*       owner_id          - APP owner id  should be used for all API calls.
+*       rate_limit_val    - ingress rate limit value
+*       bucket_size       - bucket size value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success, the function returns TPM_RC_OK. On error different types are returned
+*       according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_tm_set_gmac0_ingr_rate_lim(IN uint32_t owner_id,
+						IN uint32_t rate_limit_val,
+						IN uint32_t bucket_size);
+#endif /* _TPM_TM_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_trace.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_trace.c
new file mode 100755
index 0000000..43e8150
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_trace.c
@@ -0,0 +1,363 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/*******************************************************************************
+* tpm_trace.c
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1.1.1
+*
+*
+*******************************************************************************/
+#define _TPM_TRACE_C_
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+/* Global variables */
+uint32_t tpm_glob_trace = TPM_WARN_TRACE_LEVEL | TPM_ALL_MOD;
+/*uint32_t tpm_glob_trace = TPM_DEBUG_TRACE_LEVEL | TPM_ALL_MOD; */
+
+unsigned long print_wait_time;
+
+/*******************************************************************************
+* tpm_trace_enable_module()
+*
+* DESCRIPTION:      Enables tracing for a TPM module
+*
+* INPUTS:
+* module         - Module to enable tracing for (see tpm_trace.h for list)
+
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static tpm_error_code_t tpm_trace_enable_module(uint32_t module)
+{
+	tpm_error_code_t rc = TPM_RC_OK;
+
+	if (module == TPM_APPL_MAX_MOD)
+		tpm_glob_trace |= TPM_ALL_MOD; /* TPM trace is enabled for all applications */
+	else {
+		switch (module) {
+		case TPM_APPL_DB_MOD:
+			tpm_glob_trace |= TPM_DB_MOD;
+			break;
+
+		case TPM_APPL_PNCL_MOD:
+			tpm_glob_trace |= TPM_PNCL_MOD;
+			break;
+
+		case TPM_APPL_INIT_MOD:
+			tpm_glob_trace |= TPM_INIT_MOD;
+			break;
+
+		case TPM_APPL_HWM_MOD:
+			tpm_glob_trace |= TPM_HWM_MOD;
+			break;
+
+		case TPM_APPL_MODL_MOD:
+			tpm_glob_trace |= TPM_MODL_MOD;
+			break;
+
+		case TPM_APPL_TPM_LOG_MOD:
+			tpm_glob_trace |= TPM_TPM_LOG_MOD;
+			break;
+
+		case TPM_APPL_CLI_MOD:
+			tpm_glob_trace |= TPM_CLI_MOD;
+			break;
+
+		case TPM_APPL_PNC_HM_MOD:
+			tpm_glob_trace |= TPM_PNC_HM_MOD;
+			break;
+
+		case TPM_APPL_MODZ1_HM_MOD:
+			tpm_glob_trace |= TPM_MODZ1_HM_MOD;
+			break;
+
+		case TPM_APPL_MODZ2_HM_MOD:
+			tpm_glob_trace |= TPM_MODZ2_HM_MOD;
+			break;
+
+		default:
+			rc = ERR_GENERAL;
+			printk(KERN_ERR "Invalid application module - %d\n", module);
+			break;
+		}
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* tpm_trace_disable_module()
+*
+* DESCRIPTION:     Disables tracing for a TPM module
+*
+* INPUTS:
+* module         - Module to disable tracing for (see tpm_trace.h for list)
+
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static tpm_error_code_t tpm_trace_disable_module(uint32_t module)
+{
+	tpm_error_code_t rc = TPM_RC_OK;
+
+	if (module == TPM_APPL_MAX_MOD)
+		tpm_glob_trace &= ~(TPM_ALL_MOD); /* TPM trace is disabled for all applications */
+	else {
+		switch (module) {
+		case TPM_APPL_DB_MOD:
+			tpm_glob_trace &= ~(TPM_DB_MOD);
+			break;
+
+		case TPM_APPL_PNCL_MOD:
+			tpm_glob_trace &= ~(TPM_PNCL_MOD);
+			break;
+
+		case TPM_APPL_INIT_MOD:
+			tpm_glob_trace &= ~(TPM_INIT_MOD);
+			break;
+
+		case TPM_APPL_HWM_MOD:
+			tpm_glob_trace &= ~(TPM_HWM_MOD);
+			break;
+
+		case TPM_APPL_MODL_MOD:
+			tpm_glob_trace &= ~(TPM_MODL_MOD);
+			break;
+
+		case TPM_APPL_TPM_LOG_MOD:
+			tpm_glob_trace &= ~(TPM_TPM_LOG_MOD);
+			break;
+
+		case TPM_APPL_CLI_MOD:
+			tpm_glob_trace &= ~(TPM_CLI_MOD);
+			break;
+
+		case TPM_APPL_PNC_HM_MOD:
+			tpm_glob_trace &= ~(TPM_PNC_HM_MOD);
+			break;
+
+		case TPM_APPL_MODZ1_HM_MOD:
+			tpm_glob_trace &= ~(TPM_MODZ1_HM_MOD);
+			break;
+
+		case TPM_APPL_MODZ2_HM_MOD:
+			tpm_glob_trace &= ~(TPM_MODZ2_HM_MOD);
+			break;
+
+		default:
+			rc = ERR_GENERAL;
+			printk(KERN_ERR "Invalid application module - %d\n", module);
+			break;
+		}
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* tpm_trace_set()
+*
+* DESCRIPTION:     Disables tracing for a TPM module
+*
+* INPUTS:
+*           level  - trace level
+
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_trace_set(uint32_t level)
+{
+	tpm_error_code_t rc = TPM_RC_OK;
+	uint32_t temp_gl_trace;
+
+	if (level >= TPM_APPL_LEVEL_MAX) {
+		printk(KERN_ERR "Invalid level - %d\n", level);
+		rc = ERR_GENERAL;
+	} else {
+		if (level == TPM_APPL_LEVEL_NONE)
+			tpm_glob_trace &= ~(TPM_ALL_TRACE_LEVEL);
+		else {
+			temp_gl_trace = tpm_glob_trace & TPM_ALL_MOD;
+
+			switch (level) {
+			case TPM_APPL_LEVEL_DEBUG:
+				tpm_glob_trace = temp_gl_trace | TPM_DEBUG_TRACE_LEVEL;
+				break;
+
+			case TPM_APPL_LEVEL_INFO:
+				tpm_glob_trace = temp_gl_trace | TPM_INFO_TRACE_LEVEL;
+				break;
+
+			case TPM_APPL_LEVEL_WARN:
+				tpm_glob_trace = temp_gl_trace | TPM_WARN_TRACE_LEVEL;
+				break;
+
+			case TPM_APPL_LEVEL_ERROR:
+				tpm_glob_trace = temp_gl_trace | TPM_ERROR_TRACE_LEVEL;
+				break;
+
+			case TPM_APPL_LEVEL_FATAL:
+				tpm_glob_trace = temp_gl_trace | TPM_FATAL_TRACE_LEVEL;
+				break;
+			}
+		}
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* tpm_trace_module_set()
+*
+* DESCRIPTION:     Set trace module
+*
+* INPUTS:
+* module         - Module to disable tracing for (see tpm_trace.h for list)
+
+* OUTPUTS:
+*
+* RETURNS:
+* On success, the function returns TPM_DB_OK. On error different types are returned
+* according to the case - see tpm_db_err_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_trace_module_set(uint32_t module, uint32_t en_dis)
+{
+	tpm_error_code_t rc = TPM_RC_OK;
+
+	if (en_dis)
+		rc = tpm_trace_enable_module(module);
+	else
+		rc = tpm_trace_disable_module(module);
+
+	return rc;
+}
+
+tpm_error_code_t tpm_trace_status_print(void)
+{
+	tpm_error_code_t rc = TPM_RC_OK;
+	uint16_t module;
+
+	module = tpm_glob_trace & TPM_ALL_MOD;
+
+	printk(KERN_WARNING "===================================\n");
+	printk(KERN_WARNING "Trace levels:\n");
+	printk(KERN_WARNING "===================================\n");
+	printk(KERN_WARNING "Fatal errors                     %s\n", (tpm_glob_trace&TPM_FATAL_MASK) ? "+" : "-");
+	printk(KERN_WARNING "Errors                           %s\n", (tpm_glob_trace&TPM_ERROR_MASK) ? "+" : "-");
+	printk(KERN_WARNING "Warnings                         %s\n", (tpm_glob_trace&TPM_WARN_MASK) ? "+" : "-");
+	printk(KERN_WARNING "Information messages             %s\n", (tpm_glob_trace&TPM_INFO_MASK) ? "+" : "-");
+	printk(KERN_WARNING "Debug messages                   %s\n", (tpm_glob_trace&TPM_DEBUG_MASK) ? "+" : "-");
+	printk(KERN_WARNING "===================================\n");
+	printk(KERN_WARNING "Application modules:\n");
+	printk(KERN_WARNING "===================================\n");
+	printk(KERN_WARNING "DB                               %s\n", (module&TPM_DB_MOD) ? "+" : "-");
+	printk(KERN_WARNING "PNCL                             %s\n", (module&TPM_PNCL_MOD) ? "+" : "-");
+	printk(KERN_WARNING "INIT                             %s\n", (module&TPM_INIT_MOD) ? "+" : "-");
+	printk(KERN_WARNING "HWM                              %s\n", (module&TPM_HWM_MOD) ? "+" : "-");
+	printk(KERN_WARNING "MODL                             %s\n", (module&TPM_MODL_MOD) ? "+" : "-");
+	printk(KERN_WARNING "TPM LOG                          %s\n", (module&TPM_TPM_LOG_MOD) ? "+" : "-");
+	printk(KERN_WARNING "CLI                              %s\n", (module&TPM_CLI_MOD) ? "+" : "-");
+	printk(KERN_WARNING "PNC HM                           %s\n", (module&TPM_PNC_HM_MOD) ? "+" : "-");
+	printk(KERN_WARNING "MODZ1 HM                         %s\n", (module&TPM_MODZ1_HM_MOD) ? "+" : "-");
+	printk(KERN_WARNING "MODZ2 HM                         %s\n", (module&TPM_MODZ2_HM_MOD) ? "+" : "-");
+	printk(KERN_WARNING "===================================\n");
+
+	return rc;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_trace.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_trace.h
new file mode 100755
index 0000000..4aab384
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_trace.h
@@ -0,0 +1,220 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/*******************************************************************************
+* tpm_trace.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager - trace definition.
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.1.1.1
+*
+*
+*******************************************************************************/
+
+#ifndef _TPM_TRACE_H_
+#define _TPM_TRACE_H_
+
+#include "mvOs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GLOB_TRACE      tpm_glob_trace
+
+#define TPM_FATAL_MASK  0x80000000	/*Currently, not used */
+#define TPM_ERROR_MASK  0x40000000
+#define TPM_WARN_MASK   0x20000000
+#define TPM_INFO_MASK   0x10000000
+#define TPM_DEBUG_MASK  0x08000000
+
+#define TPM_FATAL_TRACE_LEVEL   0x80000000	/*Currently, not used */
+#define TPM_ERROR_TRACE_LEVEL   0xC0000000
+#define TPM_WARN_TRACE_LEVEL    0xE0000000
+#define TPM_INFO_TRACE_LEVEL    0xF0000000
+#define TPM_DEBUG_TRACE_LEVEL   0xF8000000
+
+#define TPM_ALL_TRACE_LEVEL     0xFFFF0000
+
+
+#define tpm_printf      printk
+
+#define TPM_DB_MOD          (0x00000001)
+#define TPM_PNCL_MOD        (0x00000002)
+#define TPM_INIT_MOD        (0x00000004)
+#define TPM_HWM_MOD         (0x00000008)
+#define TPM_MODL_MOD        (0x00000010)
+#define TPM_TPM_LOG_MOD     (0x00000020)
+#define TPM_CLI_MOD         (0x00000040)
+#define TPM_PNC_HM_MOD      (0x00000080)
+#define TPM_MODZ1_HM_MOD    (0x00000100)
+#define TPM_MODZ2_HM_MOD    (0x00000200)
+#define TPM_MTU_MOD         (0x00000400)
+#define TPM_CTC_CM_MOD      (0x00000800)
+
+#define TPM_ALL_MOD         (0x0000FFFF)
+
+typedef enum tpm_appl_mod {
+	TPM_APPL_DB_MOD,
+	TPM_APPL_PNCL_MOD,
+	TPM_APPL_INIT_MOD,
+	TPM_APPL_HWM_MOD,
+	TPM_APPL_MODL_MOD,
+	TPM_APPL_TPM_LOG_MOD,
+	TPM_APPL_CLI_MOD,
+	TPM_APPL_PNC_HM_MOD,
+	TPM_APPL_MODZ1_HM_MOD,
+	TPM_APPL_MODZ2_HM_MOD,
+
+	/* TPM_APPL_MAX_MOD must be always last */
+	TPM_APPL_MAX_MOD
+} tpm_appl_mod_t;
+
+typedef enum tpm_appl_level {
+	TPM_APPL_LEVEL_NONE,
+	TPM_APPL_LEVEL_DEBUG,
+	TPM_APPL_LEVEL_INFO,
+	TPM_APPL_LEVEL_WARN,
+	TPM_APPL_LEVEL_ERROR,
+	TPM_APPL_LEVEL_FATAL,
+
+	/* TPM_APPL_LEVEL_MAX must be always last */
+	TPM_APPL_LEVEL_MAX
+} tpm_appl_level_t;
+
+#define TPM_OS_COND_DEBUG(module) if ((module & GLOB_TRACE) && (TPM_DEBUG_MASK & GLOB_TRACE))
+
+#ifdef TPM_PRINT_WAIT  /* See types.h */
+#define TPM_OS_DEBUG(module , format , ...) \
+		{
+			if ((module & GLOB_TRACE) && (TPM_DEBUG_MASK & GLOB_TRACE)) { \
+				tpm_printf("%s(%d):  "format , __func__ , __LINE__ , ##__VA_ARGS__); \
+				print_wait_time = (jiffies + 2); \
+				while (jiffies < print_wait_time) \
+					schedule(); \
+			} \
+		}
+#else
+#define TPM_OS_DEBUG(module , format , ...) \
+		{ \
+			if ((module & GLOB_TRACE) && (TPM_DEBUG_MASK & GLOB_TRACE)) \
+				tpm_printf("%s(%d):  "format , __func__ , __LINE__ , ##__VA_ARGS__); \
+		}
+#endif
+
+#define TPM_OS_INFO(module , format , ...)  \
+		{ \
+			if ((module & GLOB_TRACE) && (TPM_INFO_MASK & GLOB_TRACE))  \
+				tpm_printf("%s(%d):  "format , __func__ , __LINE__ , ##__VA_ARGS__); \
+		}
+#define TPM_OS_WARN(module , format , ...)  \
+		{ \
+			if ((module & GLOB_TRACE) && (TPM_WARN_MASK & GLOB_TRACE))  \
+				tpm_printf("(warn)  %s(%d):  "format , __func__ , __LINE__ , ##__VA_ARGS__); \
+		}
+#define TPM_OS_ERROR(module , format , ...) \
+		{ \
+			if ((module & GLOB_TRACE) && (TPM_ERROR_MASK & GLOB_TRACE)) \
+				tpm_printf("(error) %s(%d):  "format , __func__ , __LINE__ , ##__VA_ARGS__); \
+		}
+#define TPM_OS_FATAL(module , format , ...) \
+		tpm_printf("(fatal) %s(%d):  "format , __func__ , __LINE__ , ##__VA_ARGS__);
+
+#ifdef TPM_PRINT_WAIT
+#define TPM_OS_DEB_WAIT() \
+		{\
+			print_wait_time = (jiffies + 2);\
+			while (jiffies < print_wait_time)\
+				schedule();\
+		}
+#else
+#define TPM_OS_DEB_WAIT()
+#endif
+
+#ifndef _TPM_TRACE_C_
+	extern uint32_t tpm_glob_trace;
+
+	extern unsigned long print_wait_time;
+#endif
+
+/* TODO - Change following  to compilation flags */
+#define TPM_KERNEL_DEBUG
+
+	tpm_error_code_t tpm_trace_status_print(void);
+	tpm_error_code_t tpm_trace_set(uint32_t level);
+	tpm_error_code_t tpm_trace_module_set(uint32_t module, uint32_t flag);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_types.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_types.h
new file mode 100755
index 0000000..8053dd7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_types.h
@@ -0,0 +1,1497 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_types.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager - types definition.
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               Revision: 1.4
+*
+*
+*******************************************************************************/
+
+#ifndef _TPM_TYPES_H_
+#define _TPM_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************/
+/********************************** Administrative ****************************/
+/******************************************************************************/
+
+/* API group ownership error codes */
+typedef enum tpm_api_ownership_error {
+	API_OWNERSHIP_SUCCESS,
+	API_OWNERID_UNKNOWN,
+	API_TYPE_UNKNOWN,
+	API_OWNED,
+	API_OWNERSHIP_ERROR
+} tpm_api_ownership_error_t;
+
+
+/* Maximum number of parallel running API calls to a certain API */
+#define TPM_MAX_PARALLEL_API_CALLS	(4)
+
+/******************************************************************************/
+/********************************** Packet Processing *************************/
+/******************************************************************************/
+
+/*************************************/
+/* Packet Processor API Types  *******/
+/*************************************/
+typedef enum {
+	TPM_API_MGMT,
+	TPM_API_MAC_LEARN,
+	TPM_API_CPU_LOOPBACK,
+	TPM_API_L2_PRIM,
+	TPM_API_L3_TYPE,
+	TPM_API_IPV4,
+	TPM_API_IPV4_MC,
+	TPM_API_IPV6_GEN,
+	TPM_API_IPV6_DIP,
+	TPM_API_IPV6_MC,
+	TPM_API_IPV6_NH,
+	TPM_API_IPV6_L4,
+	TPM_API_CNM,
+	TPM_API_TYPE_ILLEGAL,
+	TPM_MAX_API_TYPES = TPM_API_TYPE_ILLEGAL
+} tpm_api_type_t;
+
+/*************************************/
+/* Parse fields **********************/
+/* tpm_parse_fields_t bitmap **********/
+/*************************************/
+
+#define     TPM_L2_PARSE_MAC_DA             (0x0001)	/* parsing DEST MAC Address */
+#define     TPM_L2_PARSE_MAC_SA             (0x0002)	/* parsing SRC MAC Address */
+#define     TPM_L2_PARSE_ONE_VLAN_TAG       (0x0004)	/* parsing external VLAN tag */
+#define     TPM_L2_PARSE_TWO_VLAN_TAG       (0x0008)	/* parsing external and inner VLAN tag */
+#define     TPM_L2_PARSE_ETYPE              (0x0010)	/* parsing Ether type */
+#define     TPM_L2_PARSE_PPPOE_SES          (0x0020)	/* parsing PPPOE session */
+#define     TPM_L2_PARSE_PPP_PROT           (0x0040)	/* parsing PPP protocol */
+#define     TPM_L2_PARSE_GEMPORT            (0x0080)	/* parsing the GEM port */
+
+#define     TPM_IPv4_PARSE_SIP              (0x0001)	/* parsing IPv4 Source IP address */
+#define     TPM_IPv4_PARSE_DIP              (0x0002)	/* parsing IPv4 Dest IP address */
+#define     TPM_IPv4_PARSE_DSCP             (0x0004)	/* parsing IPv4 DSCP */
+#define     TPM_IPv4_PARSE_PROTO            (0x0008)	/* parsing IPv4 protocol */
+
+#define     TPM_IPv6_PARSE_SIP              (0x0001)	/* parsing IPv6 Source IP address */
+#define     TPM_IPv6_PARSE_DIP              (0x0002)	/* parsing IPv6 Dest IP address */
+#define     TPM_IPv6_PARSE_DSCP             (0x0004)	/* parsing IPv6 DSCP */
+#define     TPM_IPv6_PARSE_NH               (0x0008)	/* parsing IPv6 next hop */
+#define     TPM_IPv6_PARSE_HOPL             (0x0040)	/* parsing IPv6 hop limit */
+/* for CnM IPv6, there is the possibility that parse_bm has IPv6_HOPL, L4_SRC and L4_DST together,
+   so they can not have the same value, that is the reason HOPL is changed from 0x10 to 0x40, since
+   L4_SRC has 0x10 and L4_DST has 0x20
+*/
+
+/* Both for IPV4 and IPV6 */
+#define     TPM_PARSE_L4_SRC                (0x0010)	/* parsing L4 source port */
+#define     TPM_PARSE_L4_DST                (0x0020)	/* parsing L4 destination port */
+
+typedef uint32_t tpm_parse_fields_t;
+
+/*************************************/
+/* Parse flags ***********************/
+/* tpm_parse_flags_t bitmap **********/
+/*************************************/
+#define     TPM_PARSE_FLAG_TAG1_TRUE        (0x00001)
+#define     TPM_PARSE_FLAG_TAG1_FALSE       (0x00002)
+#define     TPM_PARSE_FLAG_TAG1_DC          (0x0)
+#define     TPM_PARSE_FLAG_TAG2_TRUE        (0x00004)
+#define     TPM_PARSE_FLAG_TAG2_FALSE       (0x00008)
+#define     TPM_PARSE_FLAG_TAG2_DC          (0x0)
+#define     TPM_PARSE_FLAG_MTM_TRUE         (0x00010)
+#define     TPM_PARSE_FLAG_MTM_FALSE        (0x00020)
+#define     TPM_PARSE_FLAG_MTM_DC           (0x0)
+#define     TPM_PARSE_FLAG_TO_CPU_TRUE      (0x00040)
+#define     TPM_PARSE_FLAG_TO_CPU_FALSE     (0x00080)
+#define     TPM_PARSE_FLAG_TO_CPU_DC        (0x0)
+#define     TPM_PARSE_FLAG_L4_UDP           (0x00100)
+#define     TPM_PARSE_FLAG_L4_TCP           (0x00200)
+#define     TPM_PARSE_FLAG_L4_DC            (0x0)
+#define     TPM_PARSE_FLAG_PPPOE_TRUE       (0x00400)
+#define     TPM_PARSE_FLAG_PPPOE_FALSE      (0x00800)
+#define     TPM_PARSE_FLAG_PPPOE_DC         (0x0)
+
+typedef uint32_t tpm_parse_flags_t;
+
+/* Source port - used to specify through which port the packet entered the processor  */
+typedef enum {
+	TPM_SRC_PORT_UNI_0,		/* upstream */
+	TPM_SRC_PORT_UNI_1,		/* upstream */
+	TPM_SRC_PORT_UNI_2,		/* upstream */
+	TPM_SRC_PORT_UNI_3,		/* upstream */
+	TPM_SRC_PORT_UNI_4,		/* upstream */
+	TPM_SRC_PORT_UNI_5,		/* upstream */
+	TPM_SRC_PORT_UNI_6,		/* upstream */
+	TPM_SRC_PORT_UNI_7,		/* upstream */
+	TPM_SRC_PORT_UNI_VIRT,		/* upstream */
+	TPM_SRC_PORT_WAN,		/* downstram */
+	TPM_SRC_PORT_UNI_ANY,		/* upstream - all UNI ports */
+	TPM_SRC_PORT_WAN_OR_LAN,	/* Any Port, currently not supported */
+	TPM_SRC_PORT_ILLEGAL = 0xFF
+} tpm_src_port_type_t;
+
+/* Source Port derivatives : */
+#define     TPM_MAX_NUM_UNI_PORTS           (TPM_SRC_PORT_UNI_VIRT - TPM_SRC_PORT_UNI_0 + 1)
+#define     TPM_MAX_NUM_ETH_PORTS           (1/*wan*/+TPM_MAX_NUM_UNI_PORTS)
+#define     TPM_RATE_LIMIT_MIN_VAL          (64)
+
+/***********************************************/
+/* Target port - bitmap ************************/
+/* Used for forwarding decision making *********/
+/* For EPON/GPON - same bitmap for LLID/TCONTs */
+/***********************************************/
+#define	TPM_TRG_PORT_WAN		(0x00000001)	/* upstream */
+
+#define	TPM_TRG_TCONT_0			(0x00000001)	/* upstream */
+#define	TPM_TRG_TCONT_1			(0x00000002)	/* upstream */
+#define	TPM_TRG_TCONT_2			(0x00000004)	/* upstream */
+#define	TPM_TRG_TCONT_3			(0x00000008)	/* upstream */
+#define	TPM_TRG_TCONT_4			(0x00000010)	/* upstream */
+#define	TPM_TRG_TCONT_5			(0x00000020)	/* upstream */
+#define	TPM_TRG_TCONT_6			(0x00000040)	/* upstream */
+#define	TPM_TRG_TCONT_7			(0x00000080)	/* upstream */
+#define	TPM_TRG_LLID_0 			(0x00000001)	/* upstream */
+#define	TPM_TRG_LLID_1 			(0x00000002)	/* upstream */
+#define	TPM_TRG_LLID_2 			(0x00000004)	/* upstream */
+#define	TPM_TRG_LLID_3 			(0x00000008)	/* upstream */
+#define	TPM_TRG_LLID_4 			(0x00000010)	/* upstream */
+#define	TPM_TRG_LLID_5 			(0x00000020)	/* upstream */
+#define	TPM_TRG_LLID_6 			(0x00000040)	/* upstream */
+#define	TPM_TRG_LLID_7			(0x00000080)	/* upstream */
+#define	TPM_TRG_UNI_0			(0x00000100)	/* downstream */
+#define	TPM_TRG_UNI_1			(0x00000200)	/* downstream */
+#define	TPM_TRG_UNI_2			(0x00000400)	/* downstream */
+#define	TPM_TRG_UNI_3			(0x00000800)	/* downstream */
+#define	TPM_TRG_UNI_4			(0x00001000)	/* downstream */
+#define	TPM_TRG_UNI_5			(0x00002000)	/* downstream */
+#define	TPM_TRG_UNI_6			(0x00004000)	/* downstream */
+#define	TPM_TRG_UNI_7			(0x00008000)	/* downstream */
+#define	TPM_TRG_UNI_VIRT		(0x00010000)	/* downstream */
+
+#define	TPM_TRG_PORT_CPU		(0x00020000)	/* upstream / downstream - CPU port */
+#define	TPM_TRG_PORT_UNI_ANY		(0x00040000)	/* downstream - all UNI ports */
+#define	TPM_TRG_PORT_UNI_CPU_LOOP	(0x00080000)	/* downstream - loop to the CPU port */
+#define	TPM_TRG_PORT_ILLEGAL		(0xFFFFFFFF)	/* illegal port number value */
+#define	TPM_TRG_UNI_OFFSET		8
+#define	TPM_TRG_UNI_MASK		0x1FF
+
+
+/* target port type - bitmap */
+typedef uint32_t tpm_trg_port_type_t;	/*ex: TPM_TRG_PORT_WAN or TPM_TRG_TCONT_0 */
+/* YUVAL_NOW - add allowed bitmaps here */
+
+/* GPON GEM port id */
+typedef uint16_t tpm_gem_port_key_t;
+
+/* Structure for packet forwarding decision making */
+typedef struct tpm_pkt_frwd {
+	tpm_trg_port_type_t trg_port;	/* Bitmap of the ports where the packet is targeted */
+					/*(ATTENTION - today only single target port in bm */
+	uint8_t trg_queue;		/* Queue id for the target port. */
+	uint8_t dummy;
+	tpm_gem_port_key_t gem_port;	/* GEM port id. */
+} tpm_pkt_frwd_t;
+
+/* Next Parsing Stage options */
+typedef enum tpm_parse_stage {
+	STAGE_L2_PRIM,
+	STAGE_L3_TYPE,
+	STAGE_IPv4,
+	STAGE_IPv6_GEN,
+	STAGE_IPv6_DIP,
+	STAGE_IPv6_NH,
+	STAGE_IPV6_L4,
+	STAGE_CTC_CM,
+	STAGE_DONE
+} tpm_parse_stage_t;
+
+/*************************************/
+/* Classifying flags rules - bitmap **/
+/* tpm_pkt_action_t bitmap **********/
+/*************************************/
+#define     TPM_ACTION_DROP_PK              (0x001)	/* drop packet */
+#define     TPM_ACTION_SET_TARGET_PORT      (0x002)	/* set forwarding dest Tx_port(GPON:+GemPort) */
+#define     TPM_ACTION_SET_TARGET_QUEUE     (0x004)	/* set forwarding dest Tx_queue */
+#define     TPM_ACTION_SET_PKT_MOD          (0x008)	/* set packet modification command */
+#define     TPM_ACTION_TO_CPU               (0x010)	/* packet should be trapped to CPU */
+#define     TPM_ACTION_MTM                  (0x020)	/* packet is MAC-to-ME */
+#define     TPM_ACTION_CUST_CPU_PKT_PARSE   (0x040)	/* packet should be sent to Customization package */
+#define     TPM_ACTION_SPEC_MC_VID          (0x080)	/* Specific multicast VID  */
+#define     TPM_ACTION_UDP_CHKSUM_CALC      (0x100)	/* UDP Checksum should be updated, due to non-zero udp_checksum */
+
+typedef uint32_t tpm_pkt_action_t;	/*ex: TPM_ACTION_DROP_PK */
+
+/*****************/
+/* Packet Action */
+/*****************/
+typedef struct tpm_rule_action {
+	tpm_pkt_action_t pkt_act;
+	tpm_parse_stage_t next_phase;
+} tpm_rule_action_t;
+
+/******************* Packet fields modification command bitmap ***************/
+#define    TPM_MH_SET                       0x00001
+#define    TPM_MAC_DA_SET                   0x00002	/*Update the MAC DA Address */
+#define    TPM_MAC_SA_SET                   0x00004	/*Update the MAC SA Address */
+#define    TPM_VLAN_MOD                     0x00008	/*Update the VLAN Tags (add/del/update) */
+#define    TPM_PPPOE_DEL                    0x00010	/*Delete a PPPoE encapsulation */
+#define    TPM_PPPOE_ADD                    0x00020	/*Add a PPPoE encapsulation */
+#define    TPM_DSCP_SET                     0x00040	/* Set the DSCP value */
+#define    TPM_TTL_DEC                      0x00080	/* Decrease the TTL value */
+#define    TPM_IPV4_UPDATE                  0x00100	/*Update the IPv4 Header */
+#define    TPM_IPV4_SRC_SET                 0x00200	/* Set the IPV4 Source Address */
+#define    TPM_IPV4_DST_SET                 0x00400	/* Set the IPV4 Destination Address */
+#define    TPM_IPV6_UPDATE                  0x00800	/* Update the IPv6 Header */
+#define    TPM_HOPLIM_DEC                   0x01000	/* Decrease the Hop Limit value */
+#define    TPM_IPV6_SRC_SET                 0x02000	/* Set the IPV6 Source Address */
+#define    TPM_IPV6_DST_SET                 0x04000	/* Set the IPV6 Destination Address */
+#define    TPM_L4_SRC_SET                   0x08000	/* Set the L4 Source Port (UDP or TCP) */
+#define    TPM_L4_DST_SET                   0x10000	/* Set the L4 Destination Port (UDP or TCP) */
+
+typedef uint32_t tpm_pkt_mod_bm_t;	/*ex: TPM_MAC_DA_SET | TPM_MAC_SA_SET .... */
+#define    TPM_CHAIN_NUM_UNLIMITED          (0x1000)
+
+/* Add. Modification flags, used only for tpm_mod_entry_set API */
+#define     TPM_INT_L4_TCP        (0x0001)
+#define     TPM_INT_L4_UDP        (0x0002)
+#define     TPM_INT_SPLIT_MOD     (0x0004)
+#define     TPM_INT_UDP_CHECKSUM  (0x0008)
+#define     TPM_INT_MC_MOD        (0x0010)
+
+typedef uint32_t tpm_pkt_mod_int_bm_t;  /*ex: TPM_INT_L4_TCP | TPM_INT_L4_UDP ....*/
+
+/****************************************************************/
+/*          L2/L3 ACL rule related structures                   */
+/****************************************************************/
+
+/* L2 MAC key structure */
+typedef struct tpm_mac_key {
+	uint8_t mac_da[6];
+	uint8_t mac_da_mask[6];
+	uint8_t mac_sa[6];
+	uint8_t mac_sa_mask[6];
+} tpm_mac_key_t;
+
+/* L2 VLAN key structure */
+typedef struct tpm_vlan_key {
+	uint16_t tpid;
+	uint16_t tpid_mask;
+	uint16_t vid;
+	uint16_t vid_mask;
+	uint8_t cfi;
+	uint8_t cfi_mask;
+	uint8_t pbit;
+	uint8_t pbit_mask;
+} tpm_vlan_key_t;
+
+/* Ethernet type - for example 0x0800 */
+typedef uint16_t tpm_ether_type_key_t;
+
+/* PPP key structure */
+typedef struct tpm_pppoe_key {
+	uint16_t ppp_session;
+	uint16_t ppp_proto;
+} tpm_pppoe_key_t;
+
+/* L2 ACL key structure - for creating a new L2 ACL rule */
+typedef struct tpm_l2_acl_key {
+	tpm_mac_key_t mac;
+	tpm_vlan_key_t vlan1;
+	tpm_vlan_key_t vlan2;
+	tpm_pppoe_key_t pppoe_hdr;
+	tpm_ether_type_key_t ether_type;
+	tpm_gem_port_key_t gem_port;
+} tpm_l2_acl_key_t;
+
+/****************************************************************/
+/*          L3 Type - ACL key structure                         */
+/****************************************************************/
+typedef struct tpm_l3_type_key {
+	tpm_ether_type_key_t ether_type_key;
+	uint16_t dummy;
+	tpm_pppoe_key_t pppoe_key;
+} tpm_l3_type_key_t;
+
+/****************************************************************/
+/*          IPv4 - ACL key structure                            */
+/****************************************************************/
+typedef struct tpm_ipv4_acl_key {
+	uint8_t ipv4_dscp;
+	uint8_t ipv4_dscp_mask;
+	uint8_t ipv4_proto;
+	uint8_t dummy;
+	uint8_t ipv4_src_ip_add[4];
+	uint8_t ipv4_src_ip_add_mask[4];
+	uint8_t ipv4_dst_ip_add[4];
+	uint8_t ipv4_dst_ip_add_mask[4];
+	uint16_t l4_src_port;
+	uint16_t l4_dst_port;
+} tpm_ipv4_acl_key_t;
+
+/****************************************************************/
+/*          IPv6 - ACL key structure                            */
+/****************************************************************/
+
+typedef enum tpm_nh_iter {
+	NH_ITER_0,
+	NH_ITER_1,
+} tpm_nh_iter_t;
+
+typedef struct tpm_ipv6_gen_acl_key {
+	uint8_t ipv6_dscp;
+	uint8_t ipv6_dscp_mask;
+	uint8_t hop_limit;
+	uint8_t dummy;
+	uint8_t ipv6_src_ip_add[16];
+	uint8_t ipv6_src_ip_add_mask[16];
+} tpm_ipv6_gen_acl_key_t;
+
+typedef struct tpm_ipv6_acl_key {
+	uint8_t ipv6_dscp;
+	uint8_t ipv6_dscp_mask;
+	uint8_t ipv6_next_header;
+	uint8_t ipv6_hoplimit;
+	uint8_t ipv6_src_ip_add[16];
+	uint8_t ipv6_src_ip_add_mask[16];
+	uint8_t ipv6_dst_ip_add[16];
+	uint8_t ipv6_dst_ip_add_mask[16];
+	uint16_t l4_src_port;
+	uint16_t l4_dst_port;
+} tpm_ipv6_acl_key_t;
+
+typedef struct tpm_ipv6_addr_key {
+	uint8_t ipv6_ip_add[16];
+	uint8_t ipv6_ip_add_mask[16];
+} tpm_ipv6_addr_key_t;
+
+typedef struct tpm_l4_ports_key {
+	uint16_t l4_src_port;
+	uint16_t l4_dst_port;
+} tpm_l4_ports_key_t;
+
+/****************************************************************/
+/*          IPV4 Multicast definitions                          */
+/****************************************************************/
+typedef enum tpm_mc_port_mode {
+	TPM_MC_UNI_MODE_EXCLUDE,
+	TPM_MC_UNI_MODE_TRANSPARENT,
+	TPM_MC_UNI_MODE_STRIP,
+	TPM_MC_UNI_MODE_TRANSLATE
+} tpm_mc_port_mode_t;
+
+typedef struct tpm_mc_vid_port_cfg {
+	tpm_src_port_type_t tpm_src_port;
+	tpm_mc_port_mode_t mc_uni_port_mode;
+	uint32_t uni_port_vid;
+} tpm_mc_vid_port_cfg_t;
+
+typedef struct {
+	tpm_mc_vid_port_cfg_t mc_vid_port_vids[TPM_MAX_NUM_UNI_PORTS];
+} tpm_mc_vid_port_vid_set_t;
+
+/* Port IGMP forward mode */
+typedef enum {
+	TPM_IGMP_FRWD_MODE_DROP,
+	TPM_IGMP_FRWD_MODE_FORWARD,
+	TPM_IGMP_FRWD_MODE_SNOOPING,
+} tpm_igmp_frwd_mode_t;
+
+/****************************************************************/
+/*          Packet modification structures                      */
+/****************************************************************/
+
+/* VLAN modification commands */
+typedef enum tpm_vlan_oper {
+	VLANOP_NOOP,	/* no VLAN operation performed */
+	VLANOP_EXT_TAG_MOD,	/* modify external tag */
+	VLANOP_EXT_TAG_DEL,	/* delete external tag */
+	VLANOP_EXT_TAG_INS,	/* insert(prepend) external tag */
+	VLANOP_EXT_TAG_MOD_INS,	/* modify existing external tag and insert(prepend) new tag */
+	VLANOP_INS_2TAG,	/* insert(prepend) 2 new tags */
+	VLANOP_MOD_2TAG,	/* modify 2 tags */
+	VLANOP_SWAP_TAGS,	/* swap internal and external tags */
+	VLANOP_DEL_2TAG,	/* delete 2 existing tags */
+	VLANOP_INT_TAG_MOD,	/* modify existing internal tag */
+	VLANOP_EXT_TAG_DEL_INT_MOD,	/* delete existing external tag and modify internal tag */
+	VLANOP_SPLIT_MOD_PBIT, /* split mod stage 2, only modify p-bit */
+	VLANOP_ILLEGAL,	/* illegal VLAN operation */
+
+	VLANOP_MAX_NUM
+} tpm_vlan_oper_t;
+
+typedef enum tpm_mod_owner {
+	TPM_MOD_OWNER_TPM,
+	TPM_MOD_OWNER_CPU,
+	TPM_MAX_MOD_OWNERS
+} tpm_mod_owner_t;
+
+typedef struct tpm_vlan_mod {
+	tpm_vlan_oper_t vlan_op;	/* Vlan operation/modification command */
+	tpm_vlan_key_t vlan1_out;	/* structure for outer VLAN key */
+	tpm_vlan_key_t vlan2_out;	/* structure for inner VLAN key. */
+} tpm_vlan_mod_t;
+
+typedef struct tpm_pkt_mod {
+	uint16_t mh_mod;
+	tpm_vlan_mod_t vlan_mod;
+	tpm_mac_key_t mac_mod;
+	tpm_pppoe_key_t pppoe_mod;
+	union {
+		tpm_ipv4_acl_key_t ipv4_mod;
+		tpm_ipv6_acl_key_t ipv6_mod;
+	} l3;
+} tpm_pkt_mod_t;
+
+/****************************************************************/
+/*          CPU loopback related structures                     */
+/****************************************************************/
+
+typedef struct {
+	uint32_t in_use;
+	uint32_t trg_port;
+	uint8_t trg_queue;
+	uint16_t gem_port;
+	uint32_t rule_idx;	/* PnC rule index returned when add PnC rule to GMAC0 and mod to PON MAC for CPU loopback */
+	uint32_t mod_idx;	/* Modification index returned when add mod to GMAC1 for CPU loopback */
+} tpm_cpu_loopback_t;
+
+/****************************************************************/
+/*          PnC aging counter structure & defines               */
+/****************************************************************/
+
+typedef struct {
+	uint32_t rule_idx;
+	uint32_t hit_count;
+} tpm_api_entry_count_t;
+
+typedef struct {
+	uint32_t cntr_grp;
+	uint32_t lu_mask;
+} tpm_api_lu_conf_t;
+
+#define TPM_MAX_LU_ENTRY_NUM  (100)	/* Max. allowed returned LU entries in single API call */
+#define TPM_MAX_MOD_RULE_NUM  (32)	/* YUVAL_NOW - add description here */
+#define TPM_MAX_PNC_COUNTER_NUM  (450)  /* Max allowed returned PNC counter entries in single API call
+					   Root cause for not using 512 is 4K copy_to_user limitation  */
+
+/****************************************************************/
+/*          Generic key structure from PnC - for GetNext entry  */
+/****************************************************************/
+
+typedef struct tpm_rule_l2_prim_key {
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_l2_acl_key_t l2_key;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_pkt_mod_bm_t pkt_mod_bm;
+	tpm_rule_action_t rule_action;
+} tpm_rule_l2_prim_key_t;
+
+typedef struct tpm_rule_l3_type_key {
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_l3_type_key_t l3_key;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_rule_action_t rule_action;
+} tpm_rule_l3_type_key_t;
+
+typedef struct tpm_rule_ipv4_key {
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_ipv4_acl_key_t ipv4_key;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_pkt_mod_bm_t pkt_mod_bm;
+	tpm_rule_action_t rule_action;
+} tpm_rule_ipv4_key_t;
+
+typedef struct tpm_rule_ipv4_mc_key {
+	uint16_t vid;
+	uint8_t ipv4_src_add[4];
+	uint8_t ipv4_dest_add[4];
+	uint8_t ignore_ipv4_src;
+	tpm_trg_port_type_t dest_port_bm;
+} tpm_rule_ipv4_mc_key_t;
+
+typedef struct tpm_rule_ipv6_mc_key {
+	uint16_t vid;
+	uint8_t ipv6_dest_add[16];
+	tpm_trg_port_type_t dest_port_bm;
+} tpm_rule_ipv6_mc_key_t;
+
+typedef struct tpm_rule_ipv6_key {
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_src_port_type_t src_port;
+	tpm_ipv6_acl_key_t ipv6_key;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_rule_action_t rule_action;
+} tpm_rule_ipv6_key_t;
+
+typedef struct tpm_rule_ipv6_gen_key {
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_src_port_type_t src_port;
+	tpm_l4_ports_key_t l4_key;
+	tpm_ipv6_gen_acl_key_t ipv6_gen_key;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_pkt_mod_bm_t pkt_mod_bm;
+	tpm_rule_action_t rule_action;
+} tpm_rule_ipv6_gen_key_t;
+
+typedef struct tpm_rule_ipv6_dip_key {
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_src_port_type_t src_port;
+	tpm_l4_ports_key_t l4_key;
+	tpm_ipv6_gen_acl_key_t ipv6_gen_key;
+	tpm_ipv6_addr_key_t ipv6_dipkey;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_pkt_mod_bm_t pkt_mod_bm;
+	tpm_rule_action_t rule_action;
+} tpm_rule_ipv6_dip_key_t;
+
+typedef struct tpm_rule_ipv6_l4_key {
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_src_port_type_t src_port;
+	tpm_l4_ports_key_t l4_key;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_pkt_mod_bm_t pkt_mod_bm;
+	tpm_rule_action_t rule_action;
+} tpm_rule_ipv6_l4_key_t;
+
+typedef struct tpm_rule_ipv6_nh_key {
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_nh_iter_t nh_iter;
+	uint32_t nh;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_rule_action_t rule_action;
+} tpm_rule_ipv6_nh_key_t;
+
+typedef struct tpm_rule_cnm_key {
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t l2_parse_rule_bm;
+	tpm_parse_fields_t ipv4_parse_rule_bm;
+	tpm_parse_fields_t ipv6_parse_rule_bm;
+	tpm_l2_acl_key_t l2_key;
+	tpm_ipv4_acl_key_t ipv4_key;
+	tpm_ipv6_acl_key_t ipv6_key;
+	uint32_t pbits;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_pkt_action_t pkt_act;
+} tpm_rule_cnm_key_t;
+
+typedef union tpm_rule_entry {
+	tpm_rule_l2_prim_key_t l2_prim_key;
+	tpm_rule_l3_type_key_t l3_type_key;
+	tpm_rule_ipv4_key_t ipv4_key;
+	tpm_rule_ipv6_key_t ipv6_key;
+	tpm_rule_ipv4_mc_key_t ipv4_mc_key;
+	tpm_rule_ipv6_gen_key_t ipv6_gen_key;
+	tpm_rule_ipv6_mc_key_t ipv6_mc_key;
+	tpm_rule_ipv6_dip_key_t ipv6_dip_key;
+	tpm_rule_ipv6_nh_key_t ipv6_nh_key;
+	tpm_rule_ipv6_l4_key_t ipv6_l4_key;
+	tpm_rule_cnm_key_t cnm_key;
+} tpm_rule_entry_t;
+
+/*MRU type*/
+typedef enum {
+	TPM_NETA_MTU_GMAC0,
+	TPM_NETA_MTU_GMAC1,
+	TPM_NETA_MTU_PONMAC,
+	TPM_NETA_MTU_SWITCH
+} tpm_mru_type_t;
+
+/******************************************************************************/
+/********************************** Switch defs *******************************/
+/******************************************************************************/
+#define MEMBER_EGRESS_UNMODIFIED	0
+#define NOT_A_MEMBER			1
+#define MEMBER_EGRESS_UNTAGGED		2
+#define MEMBER_EGRESS_TAGGED		3
+
+typedef enum {
+	TPM_FLOOD_UNKNOWN_UNICAST,
+	TPM_FLOOD_UNKNOWN_MULTI_BROAD_CAST,
+} tpm_flood_type_t;
+
+/* switch scheduler type */
+typedef enum tpm_sw_sched_type {
+	TPM_SW_SCHED_WRR_ALL_Q,
+	TPM_SW_SCHED_STRICT_Q3_WRR_Q210,
+	TPM_SW_SCHED_STRICT_Q32_WRR_Q10,
+	TPM_SW_SCHED_STRICT_ALL_Q,
+	TPM_SW_SCHED_ILLEGAL
+} tpm_sw_sched_type_t;
+
+/*
+* typedef: enum tpm_phy_speed_t
+*
+* Description: Enumeration of Phy Speed
+*
+* Enumerations:
+*	TPM_PHY_SPEED_10_MBPS   - 10Mbps
+*	TPM_PHY_SPEED_100_MBPS	- 100Mbps
+*	TPM_PHY_SPEED_1000_MBPS - 1000Mbps
+*/
+typedef enum {
+	TPM_PHY_SPEED_10_MBPS,
+	TPM_PHY_SPEED_100_MBPS,
+	TPM_PHY_SPEED_1000_MBPS
+} tpm_phy_speed_t;
+
+/* switch mirror type */
+
+
+/* Switch mirror type
+typedef struct {
+	uint32_t sport;
+	uint32_t dport;
+	tpm_sw_mirror_type_t mode;
+	bool enable;
+} tpm_sw_mirror_t;*/
+
+/*
+ *  typedef: enum tpm_limit_mode_t
+ *
+ *  Description: Enumeration of the port ingress/egress rate limit counting mode.
+ *
+ *  Enumerations:
+ *      TPM_SW_LIMIT_FRAME -
+ *                Count the number of frames
+ *      TPM_SW_LIMIT_LAYER1 -
+ *                Count all Layer 1 bytes:
+ *                Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
+ *      TPM_SW_LIMIT_LAYER2 -
+ *                Count all Layer 2 bytes: Frame's DA to CRC
+ *      TPM_SW_LIMIT_LAYER3 -
+ *                Count all Layer 3 bytes:
+ *                Frame's DA to CRC - 18 - 4 (if frame is tagged)
+ */
+typedef enum {
+	TPM_SW_LIMIT_FRAME = 0,
+	TPM_SW_LIMIT_LAYER1,
+	TPM_SW_LIMIT_LAYER2,
+	TPM_SW_LIMIT_LAYER3
+} tpm_limit_mode_t;
+
+/*
+* typedef: enum tpm_autoneg_mode_t
+*
+* Description: Enumeration of Autonegotiation mode.
+*Auto for both speed and duplex.
+*Auto for speed only and Full duplex.
+*Auto for speed only and Half duplex. (1000Mbps is not supported)
+*Auto for duplex only and speed 1000Mbps.
+*Auto for duplex only and speed 100Mbps.
+*Auto for duplex only and speed 10Mbps.
+*1000Mbps Full duplex.
+*100Mbps Full duplex.
+*100Mbps Half duplex.
+*10Mbps Full duplex.
+*10Mbps Half duplex.
+*/
+typedef enum {
+	TPM_SPEED_AUTO_DUPLEX_AUTO,
+	TPM_SPEED_1000_DUPLEX_AUTO,
+	TPM_SPEED_100_DUPLEX_AUTO,
+	TPM_SPEED_10_DUPLEX_AUTO,
+	TPM_SPEED_AUTO_DUPLEX_FULL,
+	TPM_SPEED_AUTO_DUPLEX_HALF,
+	TPM_SPEED_1000_DUPLEX_FULL,
+	TPM_SPEED_1000_DUPLEX_HALF,
+	TPM_SPEED_100_DUPLEX_FULL,
+	TPM_SPEED_100_DUPLEX_HALF,
+	TPM_SPEED_10_DUPLEX_FULL,
+	TPM_SPEED_10_DUPLEX_HALF
+} tpm_autoneg_mode_t;
+
+/*
+* typedef: enum tpm_phy_loopback_mode_t
+*
+* Description: Enumeration of Phy loopback mode
+*
+* Enumerations:
+	TPM_PHY_INTERNAL_LOOPBACK: internal loopback mode
+	TPM_PHY_EXTERNAL_LOOPBACK:external loopback mode
+*/
+typedef enum {
+	TPM_PHY_INTERNAL_LOOPBACK,
+	TPM_PHY_EXTERNAL_LOOPBACK
+} tpm_phy_loopback_mode_t;
+
+/*
+* typedef: enum tpm_vlan_member_mode_t
+*
+* Description: Enumeration of VLAN member mode
+*
+*/
+typedef enum {
+	TPM_VLAN_EGRESS_UNMODIFIED,
+	TPM_VLAN_NOT_A_MEMBER,
+	TPM_VLAN_EGRESS_UNTAGGED,
+	TPM_VLAN_EGRESS_TAGGED
+} tpm_vlan_member_mode_t;
+
+/* switch mirror type */
+typedef enum {
+	TPM_SW_MIRROR_INGRESS,
+	TPM_SW_MIRROR_EGRESS
+} tpm_sw_mirror_type_t;
+
+/* Switch mirror type */
+typedef struct {
+	uint32_t sport;
+	uint32_t dport;
+	tpm_sw_mirror_type_t mode;
+	bool enable;
+	uint8_t dummy1;
+	uint16_t dummy2;
+} tpm_sw_mirror_t;
+
+/*  typedef: struct tpm_sw_pirl_customer_t*/
+typedef struct {
+	uint32_t ebsLimit;
+	uint32_t cbsLimit;
+	uint32_t bktIncrement;
+	uint32_t bktRateFactor;
+	bool isValid;
+	uint8_t dummy1;
+	uint16_t dummy2;
+} tpm_sw_pirl_customer_t;
+
+/******************* Scheduler definitions *****************************/
+#define     TPM_PP_SCHED_STRICT             (0x001)	/* strict priority */
+#define     TPM_PP_SCHED_WRR                (0x002)	/* WRR - weighted round robin */
+
+/* Packet Processor - scheduler type - bitmap - ex: TPM_PP_SCHED_STRICT | TPM_PP_SCHED_WRR */
+typedef uint32_t tpm_pp_sched_type_t;
+
+/* Ethernet counters 1 */
+typedef struct {
+	uint32_t fcsErrors;
+	uint32_t excessiveCollisionCounter;
+	uint32_t lateCollisionCounter;
+	uint32_t frameTooLongs;
+	uint32_t bufferOverflowsOnReceive;
+	uint32_t bufferOverflowsOnTransmit;
+	uint32_t singleCollisionFrameCounter;
+	uint32_t multipleCollisionsFrameCounter;
+	uint32_t sqeCounter;
+	uint32_t deferredTransmissionCounter;
+	uint32_t internalMacTransmitErrorCounter;
+	uint32_t carrierSenseErrorCounter;
+	uint32_t alignmentErrorCounter;
+	uint32_t internalMacReceiveErrorCounter;
+
+} tpm_swport_pm_1_t;
+
+/* Ethernet counters 3 */
+typedef struct {
+	uint32_t dropEvents;
+	uint32_t octets;
+	uint32_t packets;
+	uint32_t broadcastPackets;
+	uint32_t multicastPackets;
+	uint32_t undersizePackets;
+	uint32_t fragments;
+	uint32_t jabbers;
+	uint32_t packets_64Octets;
+	uint32_t packets_65_127Octets;
+	uint32_t packets_128_255Octets;
+	uint32_t packets_256_511Octets;
+	uint32_t packets_512_1023Octets;
+	uint32_t packets_1024_1518Octets;
+} tpm_swport_pm_3_t;
+
+/******************************************************************************/
+/********************************** Initialisation defs ***********************/
+/******************************************************************************/
+
+#define MV_TPM_UN_INITIALIZED_INIT_PARAM   (0xFFFF)
+
+/* UpStream and DownStream general convention */
+#define TPM_DOWNSTREAM          (0)
+#define TPM_UPSTREAM            (1)
+
+/* Definitions for array sizes */
+#define     TPM_NUM_GMACS                   (3)
+#define     TPM_MAX_NUM_TX_QUEUE            (8)
+#define     TPM_MAX_NUM_RX_QUEUE            (8)
+#define     TPM_MAX_NUM_PORTS               (10)	/* WAN 1 + UNI 0..7 + 1 VIRT_UNI see  tpm_src_port_type_t */
+#define     TPM_NUM_VLAN_ETYPE_REGS         (4)
+#define     TPM_MAX_MOD_CHAIN_NUM           (16)
+#define     TPM_MAX_TPID_COMB_NUM           (16)
+
+typedef enum {
+	TPM_DIR_DS,
+	TPM_DIR_US,
+	TPM_NUM_DIRECTIONS
+} tpm_dir_t;
+
+typedef enum {
+	TPM_PON_WAN_DUAL_MAC_INT_SWITCH = 1,
+	TPM_PON_WAN_G0_INT_SWITCH,
+	TPM_PON_WAN_G1_LAN_G0_INT_SWITCH,
+	TPM_G0_WAN_G1_INT_SWITCH,
+	TPM_G1_WAN_G0_INT_SWITCH,
+	TPM_PON_G1_WAN_G0_INT_SWITCH,
+	TPM_PON_G0_WAN_G1_INT_SWITCH,
+	TPM_PON_WAN_DUAL_MAC_EXT_SWITCH,
+	TPM_PON_WAN_G1_MNG_EXT_SWITCH,
+	TPM_PON_WAN_G0_SINGLE_PORT,
+	TPM_PON_WAN_G1_SINGLE_PORT,
+	TPM_PON_G1_WAN_G0_SINGLE_PORT,
+	TPM_PON_G0_WAN_G1_SINGLE_PORT,
+	TPM_PON_WAN_G0_G1_LPBK
+} tpm_eth_complex_profile_t;
+
+typedef enum {
+	TPM_PNC_LAST_ENTRY_INIT_DROP,	/* Last (default) entry in PnC is hardcoded to DROP */
+	TPM_PNC_LAST_ENTRY_INIT_TRAP	/* Last (default) entry in PnC is hardcoded to TRAP to CPU */
+} tpm_init_pnc_last_init_t;
+
+typedef enum {
+	TPM_SCHED_SP,
+	TPM_SCHED_WRR
+} tpm_init_sched_t;
+
+typedef enum {
+	TPM_PORT_DOWN,
+	TPM_PORT_UP
+} tpm_init_port_admin_t;
+
+typedef enum {
+	TPM_SPEED_10M,
+	TPM_SPEED_100M,
+	TPM_SPEED_1G,
+	TPM_SPEED_AUTO
+} tpm_init_port_speed_t;
+
+typedef enum {
+	TPM_DUP_HALF,
+	TPM_DUP_FULL,
+	TPM_DUP_AUTO
+} tpm_init_port_duplex_t;
+
+typedef enum {
+	TPM_CONN_DISC,
+	TPM_CONN_QSGMII,
+	TPM_CONN_FE_PHY,
+	TPM_CONN_GE_PHY,
+	TPM_CONN_RGMII1,
+	TPM_CONN_RGMII2
+} tpm_init_chip_conn_t;
+
+/* Possible internal ethernet connnection devices for an external ethernet port */
+typedef enum {
+	TPM_INTCON_GMAC0,
+	TPM_INTCON_GMAC1,
+	TPM_INTCON_SWITCH
+} tpm_init_int_conn_t;
+
+/* Possible Physical internal connections for a Packet Processor Ethernet GMAC (GMAC0/GMAC1) */
+typedef enum {
+	TPM_GMAC_CON_DISC,	/* Disconnected */
+	TPM_GMAC_CON_QSGMII,	/* Quad SGMII */
+	TPM_GMAC_CON_SWITCH_4,	/* Amber Switch Port #4 */
+	TPM_GMAC_CON_SWITCH_5,	/* Amber Switch Port #5 */
+	TPM_GMAC_CON_SWITCH_6,	/* Amber Switch Port #6 */
+	TPM_GMAC_CON_RGMII1,
+	TPM_GMAC_CON_RGMII2,
+	TPM_GMAC_CON_GE_PHY	/* Internal Gig PHY */
+} tpm_init_gmac_conn_t;
+
+typedef enum {
+	TPM_Q_OWNER_CPU,
+	TPM_Q_OWNER_GMAC0,
+	TPM_Q_OWNER_GMAC1,
+	TPM_Q_OWNER_PMAC,
+	TPM_Q_OWNER_MAX
+} tpm_init_txq_owner_t;
+
+typedef enum {
+	TPM_EPON,
+	TPM_GPON,
+	TPM_P2P,
+	TPM_NONE
+} tpm_init_pon_type_t;
+
+typedef enum {
+	TPM_ACTIVE_WAN,
+	TPM_STNDBY_WAN
+} tpm_init_wan_mode_t;
+
+typedef enum {
+	TPM_TX_MOD_GMAC0,	/* = TPM_ENUM_GMAC_0 */
+	TPM_TX_MOD_GMAC1,	/*= TPM_ENUM_GMAC_1 */
+	TPM_TX_MOD_PMAC_0,	/* = TPM_ENUM_PMAC */
+	TPM_TX_MOD_PMAC_1,
+	TPM_TX_MOD_PMAC_2,
+	TPM_TX_MOD_PMAC_3,
+	TPM_TX_MOD_PMAC_4,
+	TPM_TX_MOD_PMAC_5,
+	TPM_TX_MOD_PMAC_6,
+	TPM_TX_MOD_PMAC_7,
+	TPM_MAX_NUM_TX_PORTS
+} tpm_init_tx_mod_t;
+
+typedef struct {
+	uint32_t omci_etype;
+
+	uint32_t oam_channel_configured;	/* omci or oam channel configured */
+	uint16_t omci_gemport;
+	uint32_t oam_cpu_rx_q;	/* omci cpu rx q or oam cpu rx q */
+	uint32_t oam_cpu_tx_q;	/* omci cpu tx q or oam cpu tx q */
+	uint32_t oam_cpu_tx_port;	/* omci tcount or oam llid */
+	uint32_t pnc_init_debug_port;
+	tpm_init_pon_type_t pon_type;
+
+} tpm_init_misc_t;
+
+/* Structure holds the IGMP/MLD settings */
+typedef struct {
+	uint32_t valid;
+	uint32_t igmp_snoop;
+	uint32_t igmp_cpu_queue;
+} tpm_init_igmp_t;
+
+/* Structure holds the physical connections of all external Ethernet ports */
+typedef struct {
+	uint32_t		valid;
+	tpm_init_gmac_conn_t	conn;
+	tpm_src_port_type_t	port_src;
+} tpm_init_gmac_conn_conf_t;
+
+/* Structure holds the BM Pool Buffers for small packets
+ * (contribution to shared pool) and large packets(pool per port) */
+typedef struct {
+	uint32_t valid;
+	uint32_t small_pkt_buffers;	/* Defines number of small packet pool BM buffers */
+	uint32_t large_pkt_buffers;	/* Defines number of large packet pool BM buffers */
+} tpm_init_gmac_bufs_t;
+
+/* Structure holds the physical connections of all external Ethernet ports */
+typedef struct {
+	uint32_t valid;
+	tpm_src_port_type_t port_src;		/* Port number according to Device port numbering scheme	*/
+	tpm_init_chip_conn_t chip_connect;	/* Connection to physical output lines on SoC			*/
+	tpm_init_int_conn_t int_connect;	/* Internal Ethernet device port is connected to		*/
+	uint32_t switch_port;			/* Port of Internal_Switch, the port is connected to		*/
+} tpm_init_eth_port_conf_t;
+
+typedef struct {
+	uint32_t valid;
+	tpm_init_sched_t sched_method;
+	tpm_init_txq_owner_t queue_owner;
+	uint32_t owner_queue_num;
+	uint32_t queue_size;
+	uint32_t queue_weight;
+} tpm_init_gmac_txq_t;
+
+typedef struct {
+	uint32_t valid;
+	uint32_t queue_size;
+} tpm_init_gmac_rxq_t;
+
+/*Structure defines the details of a Packet Processor Tx component  */
+typedef struct {
+	uint32_t valid;	/* Defines if the Tx component is used */
+	tpm_init_gmac_txq_t tx_queue[TPM_MAX_NUM_TX_QUEUE];	/* Config. of each of the 8 Tx queue of this Tx component */
+} tpm_init_gmac_tx_t;
+
+typedef struct {
+	uint32_t valid;	/* Defines if any of the GMAC queues are defined */
+	tpm_init_gmac_rxq_t rx_queue[TPM_MAX_NUM_RX_QUEUE];	/* Config. of each of the 8 Rx queue of this GMAC component */
+} tpm_init_gmac_rx_t;
+
+typedef enum {
+	TPM_INVALID_RANGE = -1,
+	TPM_MIN_RANGE,
+	TPM_PNC_MNGMT_DS = TPM_MIN_RANGE,
+	TPM_PNC_MAC_LEARN,
+	TPM_PNC_CPU_WAN_LPBK_US,
+	TPM_PNC_NUM_VLAN_TAGS,
+	TPM_PNC_MULTI_LPBK,
+	TPM_PNC_VIRT_UNI,
+	TPM_PNC_LOOP_DET_US,
+	TPM_PNC_L2_MAIN,
+	TPM_PNC_ETH_TYPE,
+	TPM_PNC_IGMP,
+	TPM_PNC_IPV4_MC_DS,
+	TPM_PNC_IPV4_MAIN,
+	TPM_PNC_TCP_FLAG,
+	TPM_PNC_TTL,
+	TPM_PNC_IPV4_PROTO,
+	TPM_PNC_IPV4_FRAG,
+	TPM_PNC_IPV4_LEN,
+	TPM_PNC_IPV6_NH,
+	TPM_PNC_IPV6_L4_MC_DS,
+	TPM_PNC_IPV6_L4,
+	TPM_PNC_IPV6_HOPL,
+	TPM_PNC_IPV6_MC_SIP,
+	TPM_PNC_IPV6_GEN,
+	TPM_PNC_IPV6_MC_DS,
+	TPM_PNC_IPV6_DIP,
+	TPM_PNC_CNM_IPV4_PRE,
+	TPM_PNC_CNM_MAIN,
+	TPM_PNC_CATCH_ALL,
+	TPM_MAX_RANGE = TPM_PNC_CATCH_ALL,
+	TPM_MAX_NUM_RANGES
+} tpm_pnc_ranges_t;
+
+typedef enum {
+	TPM_RANGE_TYPE_ACL,
+	TPM_RANGE_TYPE_TABLE
+} tpm_range_type_t;
+
+typedef enum {
+	TPM_MH_SRC_RX_CTRL = 0,
+	TPM_MH_SRC_PNC_RI,
+} tpm_init_mh_src_t;
+
+typedef enum {
+	TPM_VALID_DISABLED = 0,
+	TPM_VALID_ENABLED
+} tpm_init_tpm_validation_t;
+
+typedef enum {
+	TPM_ENUM_RESET_LEVEL0,
+	TPM_ENUM_RESET_LEVEL1,
+	TPM_ENUM_MAX_RESET_LEVEL = TPM_ENUM_RESET_LEVEL1
+} tpm_reset_level_enum_t;
+
+typedef enum {
+	TPM_IPV6_5T_DISABLED = 0,
+	TPM_IPV6_5T_ENABLED,
+} tpm_init_ipv6_5t_enable_t;
+
+typedef enum {
+	TPM_CTC_CM_DISABLED = 0,
+	TPM_CTC_CM_ENABLED,
+} tpm_init_ctc_cm_enable_t;
+
+typedef enum {
+	TPM_CTC_CM_IPv6_FIRST_24B = 0,
+	TPM_CTC_CM_IPv6_SECOND_24B,
+} tpm_ctc_cm_ipv6_parse_win_t;
+typedef enum {
+	TPM_SPLIT_MOD_MODE_CTC = 0,
+	TPM_SPLIT_MOD_MODE_TR156,
+} tpm_init_split_mod_mode_t;
+typedef enum {
+	TPM_PNC_MAC_LEARN_DISABLED = 0,
+	TPM_PNC_MAC_LEARN_ENABLED,
+} tpm_init_pnc_mac_learn_enable_t;
+
+typedef enum {
+	TPM_VIRT_UNI_DISABLED = 0,
+	TPM_VIRT_UNI_ENABLED
+} tpm_init_virt_uni_enable_t;
+
+typedef enum {
+	TPM_CFG_PNC_PARSE_DISABLED,
+	TPM_CFG_PNC_PARSE_ENABLED
+} tpm_init_cfg_pnc_parse_t;
+
+typedef enum {
+	TPM_CPU_LOOPBACK_DISABLED,
+	TPM_CPU_LOOPBACK_ENABLED
+} tpm_init_cpu_loopback_t;
+
+typedef enum {
+	TPM_DOUBLE_TAG_DISABLED,
+	TPM_DOUBLE_TAG_ENABLED
+} tpm_init_double_tag_t;
+
+typedef enum {
+	TPM_CFG_MODE_APPL = 0,
+	TPM_CFG_MODE_KERNEL
+} tpm_config_mode_t;
+
+typedef enum {
+	TPM_FLUSH_ATU_ALL = 0,
+	TPM_FLUSH_ATU_DYNAMIC
+} tpm_flush_atu_type_t;
+
+typedef struct {
+	tpm_pnc_ranges_t range_num;
+	tpm_range_type_t range_type;
+	uint32_t range_size;	/* Range's Physical PnC size */
+	uint32_t cntr_grp;
+	uint32_t lu_mask;
+	tpm_reset_level_enum_t min_reset_level;
+	uint32_t valid;
+} tpm_init_pnc_range_t;
+
+typedef struct {
+	uint16_t v1_tpid;
+	uint16_t v2_tpid;
+} tpm_init_tpid_comb_t;
+
+typedef struct {
+	uint32_t opt_num;
+	tpm_init_tpid_comb_t opt[TPM_MAX_TPID_COMB_NUM];
+} tpm_init_tpid_opt_t;
+
+typedef struct {
+	tpm_init_virt_uni_enable_t enabled;
+	tpm_src_port_type_t uni_port;
+	uint32_t switch_port;
+} tpm_init_virt_uni_t;
+
+typedef struct {
+	uint32_t udp_checksum_use_init_bm;
+	uint32_t udp_checksum_update;
+} tpm_init_mod_params_t;
+
+typedef struct {
+	uint16_t opcode;
+	uint16_t data;
+	uint8_t last;
+	uint8_t updt_ipv4;
+	uint8_t updt_tcp;
+	uint8_t dummy;
+} tpm_mod2_entry_t;
+
+typedef struct {
+	uint32_t entry_id;
+	tpm_mod2_entry_t entry_data;
+} tpm_mod_rule_t;
+
+typedef enum {
+	TPM_MTU_CHECK_DISABLED = 0,
+	TPM_MTU_CHECK_ENABLED
+} tpm_init_mtu_setting_enable_t;
+
+typedef enum {
+	TPM_TTL_ZERO_ACTION_NOTHING = 0,
+	TPM_TTL_ZERO_ACTION_DROP,
+	TPM_TTL_ZERO_ACTION_TO_CPU
+} tpm_init_ttl_illegal_action_t;
+
+typedef enum {
+	TPM_TCP_FLAG_NOT_CHECK = 0,
+	TPM_TCP_FLAG_CHECK
+} tpm_init_tcp_flag_check_t;
+
+typedef enum {
+	TPM_ETY_DSA_DISABLE = 0,
+	TPM_ETY_DSA_ENABLE
+} tpm_init_ety_dsa_enable_t;
+
+typedef enum {
+	TPM_PPPOE_ADD_DISABLED = 0,
+	TPM_PPPOE_ADD_ENABLED
+} tpm_init_pppoe_add_enable_t;
+typedef enum {
+	TPM_SPLIT_MOD_DISABLED = 0,
+	TPM_SPLIT_MOD_ENABLED
+} tpm_init_split_mod_enable_t;
+
+typedef enum {
+	TPM_MC_ALL_CPU_FRWD,
+	TPM_MC_MAC_ONLY_FILTER,
+	TPM_MC_COMBINED_IP_MAC_FILTER,
+	TPM_MC_IP_ONLY_FILTER,
+	TPM_MC_FILTER_MODE_MAX,
+} tpm_mc_filter_mode_t;
+
+typedef enum {
+	TPM_MC_IGMP_SNOOPING,
+	TPM_MC_IGMP_PROXY,
+	TPM_MC_IGMP_MODE_MAX,
+} tpm_mc_igmp_mode_t;
+
+typedef enum {
+	TPM_MTU_IPV4,	/* IPV4 */
+	TPM_MTU_IPV6,	/* IPV6 */
+} tpm_mtu_ethertype_t;
+
+typedef enum {
+	TPM_SELF_CHECK_LEVEL0,
+	TPM_SELF_CHECK_LEVEL1,
+	TPM_ENUM_MAX_CHECK_LEVEL = TPM_SELF_CHECK_LEVEL1
+} tpm_self_check_level_enum_t;
+
+typedef enum tpm_unknown_mac_conf {
+	TPM_UNK_MAC_TRAP,/*default rule trap packet to CPU*/
+	TPM_UNK_MAC_DROP,/*default rule drop the packet*/
+	TPM_UNK_MAC_CONTINUE/*default rule frwd packet to GMAC1*/
+} tpm_unknown_mac_conf_t;
+
+typedef struct {
+	tpm_init_mtu_setting_enable_t mtu_enable;
+	uint32_t ipv4_mtu_us;
+	uint32_t ipv4_pppoe_mtu_us;
+	uint32_t ipv6_mtu_us;
+	uint32_t ipv6_pppoe_mtu_us;
+	uint32_t ipv4_mtu_ds;
+	uint32_t ipv6_mtu_ds;
+} tpm_init_mtu_params_t;
+
+typedef struct {
+	uint32_t type;
+	uint32_t num;
+} tpm_init_chain_data_t;
+
+typedef struct {
+	uint32_t chain_num;
+	tpm_init_chain_data_t chain_data[TPM_MAX_MOD_CHAIN_NUM];
+} tpm_init_mod_chain_t;
+
+typedef struct {
+	tpm_mc_filter_mode_t filter_mode;
+	uint32_t per_uni_vlan_xlat;
+	uint32_t mc_pppoe_enable;
+	uint32_t mc_hwf_queue;
+	uint32_t mc_cpu_queue;
+	uint32_t ipv4_mc_support;
+	uint32_t ipv6_mc_support;
+} tpm_init_mc_setting_t;
+
+typedef struct {
+	tpm_init_split_mod_enable_t split_mod_enable;
+	uint8_t p_bit[8];
+	uint32_t p_bit_num;
+	uint32_t vlan_num;
+	tpm_init_split_mod_mode_t split_mod_mode;
+} tpm_init_split_mod_params_t;
+
+typedef struct {
+	uint8_t		enabled;
+	uint8_t		port;
+	uint8_t		tx_port;
+	uint8_t		tx_queue;
+	uint32_t	tgt_port;
+	uint32_t	queue_sample_freq;
+	uint32_t	thresh_high;
+	uint32_t	thresh_low;
+} tpm_init_fc_params_t;
+
+typedef struct {
+	uint32_t omci_etype;
+	tpm_init_pon_type_t pon_type;
+	uint32_t igmp_snoop;
+	uint32_t igmp_cpu_queue;
+	uint32_t igmp_pkt_frwd_mod[TPM_MAX_NUM_ETH_PORTS+1]; /* save space for UNI_ANY */
+	uint32_t num_tcont_llid;
+	tpm_init_gmac_bufs_t gmac_bp_bufs[TPM_NUM_GMACS];
+	uint32_t gmac0_mh_en;
+	uint32_t gmac1_mh_en;
+	tpm_init_fc_params_t		port_fc_conf;
+	tpm_eth_complex_profile_t	eth_cmplx_profile;
+	tpm_init_eth_port_conf_t	eth_port_conf[TPM_MAX_NUM_ETH_PORTS];
+	tpm_init_gmac_conn_conf_t	gmac_port_conf[TPM_NUM_GMACS];
+	uint32_t			backup_wan;
+
+	tpm_init_gmac_tx_t gmac_tx[TPM_MAX_NUM_TX_PORTS];
+	tpm_init_gmac_rx_t gmac_rx[TPM_NUM_GMACS];
+	tpm_init_pnc_range_t pnc_range[TPM_MAX_NUM_RANGES];
+	tpm_init_pnc_last_init_t catch_all_pkt_action;
+
+	tpm_init_mh_src_t ds_mh_set_conf;
+	tpm_init_tpm_validation_t validation_en;
+	tpm_init_tpid_opt_t tpid_opt;
+	uint32_t vlan_etypes[TPM_NUM_VLAN_ETYPE_REGS];
+	tpm_init_mod_params_t mod_config;
+	tpm_init_mod_chain_t mod_chain;
+	tpm_init_cfg_pnc_parse_t cfg_pnc_parse;
+	tpm_init_cpu_loopback_t cpu_loopback;
+	uint32_t trace_debug_info;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable;
+	tpm_init_ctc_cm_enable_t ctc_cm_enable;
+	tpm_ctc_cm_ipv6_parse_win_t  ctc_cm_ipv6_parse_window;
+	tpm_init_virt_uni_t virt_uni_info;
+
+#if 0
+	uint16_t vlan1_tpid;
+	uint16_t vlan2_tpid;
+#endif
+
+	tpm_init_mtu_params_t mtu_config;
+	tpm_init_pppoe_add_enable_t pppoe_add_enable;
+	uint32_t num_vlan_tags;
+	uint32_t cpu_rx_queue;
+	tpm_init_ttl_illegal_action_t ttl_illegal_action;
+	tpm_init_tcp_flag_check_t tcp_flag_check;
+	tpm_init_ety_dsa_enable_t ety_dsa_enable;
+
+	tpm_init_mc_setting_t mc_setting;
+	tpm_init_split_mod_params_t split_mod_config;
+	uint32_t switch_init;
+	tpm_init_pnc_mac_learn_enable_t pnc_mac_learn_enable;
+} tpm_init_t;
+
+#define XML_FILE_PATH_LENGTH  (64)
+typedef struct {
+	char xml_file_path[XML_FILE_PATH_LENGTH];
+} tpm_setup_t;
+
+/******************* TPM global ERROR codes  **************************/
+typedef enum tpm_error_code {
+	TPM_RC_OK,	/*Return ok (=0). */
+	ERR_GENERAL,	/*General purpose error. */
+	ERR_OWNER_INVALID,	/*Illegal owner id. */
+	ERR_SRC_PORT_INVALID,	/*Illegal source port. */
+	ERR_RULE_NUM_INVALID,	/*Illegal rule number. */
+	ERR_RULE_IDX_INVALID,	/*Illegal rule idx. */
+	ERR_PARSE_MAP_INVALID,	/*Illegal parse mapping. */
+	ERR_VLAN_OP_INVALID,	/*Illegal VLAN operation. */
+	ERR_L2_KEY_INVALID,	/*Illegal key information for creating the ACL rule. */
+	ERR_FRWD_INVALID,	/*Illegal forwarding decision for packet. */
+	ERR_MOD_INVALID,	/*Illegal modification command on packet. */
+	ERR_ACTION_INVALID,	/*Illegal action on the packet. */
+	ERR_NEXT_PHASE_INVALID,	/*Illegal next phase for  ACL */
+	ERR_RULE_KEY_MISMATCH,	/*Inconsistency between rule_num, src_port, l2_acl_key. */
+	ERR_IPV4_NO_CONT_L4,	/*There is no continuous block with L4 src port and destination port in packet. */
+	ERR_IPV6_ADD_FAIL,	/*Inconsistency in the building of the IPv6 rule. */
+	ERR_MC_STREAM_INVALID,	/*Illegal stream number. */
+	ERR_MC_STREAM_EXISTS,	/*Stream number already exists. */
+	ERR_MC_DST_PORT_INVALID,	/*Destination port bitmap does not match the UNI ports. */
+	ERR_IPV4_MC_DST_IP_INVALID,	/*Destination IP address is not in the MC range. */
+	ERR_IPV6_MC_DST_IP_INVALID,	/*Destination IPv6 address is not in the MC range. */
+	ERR_IPV6_MC_SRC_IP_INVALID,	/*SRC IPv6 address is not in the MC_SIP range. */
+	ERR_OMCI_TCONT_INVALID,	/*Illegal TCONT. */
+	ERR_MNGT_TX_Q_INVALID,	/*Illegal management TX queue. */
+	ERR_MNGT_CREATE_DUPLICATE_CHANNEL,	/*Create channel that already exists, */
+	ERR_MNGT_DEL_CHANNEL_INVALID,	/*Delete an unexisting management channel. */
+	ERR_OAM_LLID_INVALID,	/*Illegal LLID. */
+	ERR_CFG_GETNEXT_INDEX_INVALID,	/*Illegal get_next index for retrieving existing configuration. */
+	ERR_CFG_GETNEXT_DIRECTION_INVALID,	/*Illegal direction set (0-upstream, 1-downstream). */
+	ERR_CFG_GET_CHANNEL_INVALID,	/*Get an unexisting management channel. */
+	ERR_SW_MAC_INVALID,	/*Illegal MAC address. */
+	ERR_SW_MAC_STATIC_NOT_FOUND,	/*Delete an unexisting static MAC. */
+	ERR_SW_MAC_PER_PORT_INVALID,	/*Illegal limit of MAC per port (1-265). */
+	ERR_SW_NUM_OF_MAC_PER_PORT_INVALID,	/*Illegal limit of MAC per port (1-265). */
+	ERR_SW_VID_INVALID,	/*Illegal VLAN ID. */
+	ERR_SW_TM_QUEUE_INVALID,	/*Illegal queue id. */
+	ERR_SW_TM_WEIGHT_INVALID,	/*Illegal weight value. */
+	ERR_SW_TM_WRR_MODE_INVALID,	/*Illegal WRR mode. */
+	ERR_API_TYPE_INVALID,	/*Illegal API type */
+	ERR_DIR_INVALID,	/*Illegal direction value */
+	ERR_NULL_POINTER,	/* NULL pointer */
+	ERR_IGMP_NOT_ENABLED,	/* Try to disable IGMP which was not enabled */
+	ERR_OUT_OF_RESOURCES,	/* No more resources of certain type */
+	ERR_AI_SESS_EXISTS,	/* AI Session already exists */
+	ERR_AI_SESS_DELETING,	/* AI Session was deleted in this API call */
+	ERR_SW_TM_BUCKET_SIZE_INVALID,	/*Illegal bucket size. */
+	ERR_SW_TM_RATE_LIMIT_INVALID,	/*Illegal rate limit. */
+	ERR_DELETE_KEY_INVALID,	/* Illegal combination of key / rule_index for delete action */
+	ERR_L3_KEY_INVALID,	/*Illegal key information for creating the ACL rule. */
+	ERR_IPV4_KEY_INVALID,	/*Illegal key information for creating the ACL rule. */
+	ERR_IPV6_KEY_INVALID,	/*Illegal key information for creating the ACL rule. */
+	ERR_PORT_IGMP_FRWD_MODE_INVALID,	/*Illegal IGMP forward mode. */
+	ERR_IPV6_API_ILLEGAL_CALL,  /* Invoke the IPV6 API which is forbidden in current mode */
+	ERR_IPV6_5T_RULE_EXISTS,	/* IPV6 rule already exists */
+	ERR_IPV6_5T_FLOW_PARTIAL_MATCHED,	/* IPV6 5-tuple flow is a subflow of another flow */
+	ERR_IPV6_5T_RULE_IN_USE,	/* Try to delete a rule which is referred by other flows */
+	ERR_IPV6_5T_FLOW_AI_BITS_EXHAUSED, /* No enough AI resource for new subflow */
+	ERR_SW_NOT_INIT,	/* TPM was not successfully intiailized . */
+	ERR_FEAT_UNSUPPORT,	/* TPM feature not supported  . */
+	ERR_API_BUSY,
+	ERR_CTC_CM_DB_ERR,  /* CTC CnM DB Error */
+	ERR_CTC_CM_PREC_INVALID,   /* CTC CnM Precedence invalid */
+	ERR_TPMCHECK_DB_CHAIN_TYPE_MISMATCH,/*DB main chain type check FAIL */
+	ERR_TPMCHECK_HW_CHAIN_TYPE_MISMATCH,/*HW main chain type check FAIL */
+	ERR_TPMCHECK_BOTH_CHAIN_TYPE_MISMATCH,/*HW & DB main chain type check FAIL */
+	ERR_TPMCHECK_DB_MISMATCH,/*tpm check with DB FAIL */
+	ERR_TPMCHECK_HW_MISMATCH,/*tpm check with HW FAIL */
+	ERR_TPMCHECK_PNC_DB_MISMATCH,/*DB PNC check FAIL */
+	ERR_TPMCHECK_PNC_HW_MISMATCH,/*HW PNC check FAIL */
+	ERR_TPMCHECK_PMT_DB_MISMATCH,/*DB PMT check FAIL */
+	ERR_TPMCHECK_PMT_HW_MISMATCH,/*HW PMT check FAIL */
+	ERR_UNKNOWN_MAC_CONF_INVALID,/*Illegal MAC learn default conf*/
+} tpm_error_code_t;
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.c
new file mode 100755
index 0000000..49f9876
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.c
@@ -0,0 +1,3791 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_types.h"
+#include "tpm_internal_types.h"
+#include "tpm_xml_params.h"
+#include "ezxml.h"
+
+char *g_pstr_xml_cfg_file = US_XML_CFG_FILE;
+static ezxml_t g_p_xmlHead = NULL;
+
+/*******************************************************************************
+*                          Internal functions
+*******************************************************************************/
+static ezxml_t get_xml_head_ptr(char *cfg_file)
+{
+	if (g_p_xmlHead == NULL) {
+		g_p_xmlHead = ezxml_parse_file(cfg_file);
+
+		if (g_p_xmlHead == NULL)
+			printk(KERN_ERR "Failed to open XML configuration file - %s\n", cfg_file);
+	}
+
+	return g_p_xmlHead;
+}
+
+void free_xml_head_ptr(void)
+{
+	if (g_p_xmlHead != NULL) {
+		ezxml_free(g_p_xmlHead);
+		g_p_xmlHead = NULL;
+	}
+}
+
+static uint32_t get_dig_number(const char *arg)
+{
+	uint32_t val = 0;
+
+	if ((arg[1] == 'x') || (arg[1] == 'X'))
+		sscanf(&arg[2], "%x", &val);
+	else
+		val = simple_strtoul(arg, NULL, 10);
+
+	return val;
+}
+
+static int get_int_param(ezxml_t xml, char *name, uint32_t *num)
+{
+	ezxml_t xmlElement;
+
+	xmlElement = ezxml_child(xml, name);
+	if (xmlElement == NULL)
+		return US_RC_NOT_FOUND;
+	else if (xmlElement->txt == NULL) {
+		printk(KERN_ERR "NULL value for %s in XML config. file\n", name);
+		return US_RC_NOT_FOUND;
+	}
+
+	*num = get_dig_number(xmlElement->txt);
+	return US_RC_OK;
+}
+
+static int get_char_param(ezxml_t xml, char *name, uint8_t *str, uint8_t len)
+{
+	ezxml_t xmlElement;
+
+	xmlElement = ezxml_child(xml, name);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file\n", name);
+		return US_RC_NOT_FOUND;
+	} else if (xmlElement->txt == NULL) {
+		printk(KERN_ERR "NULL value for %s in XML config. file\n", name);
+		return US_RC_NOT_FOUND;
+	}
+
+	memcpy(str, xmlElement->txt, len);
+	str[len] = 0;
+	return US_RC_OK;
+}
+
+static int get_debug_port_attrs(ezxml_t xml, uint32_t *num, uint32_t *valid)
+{
+	const char *attr_str;
+	int rc = US_RC_FAIL;
+
+	attr_str = ezxml_attr(xml, US_XML_ID_ATTR);
+	if (attr_str != NULL) {
+		*num = get_dig_number(attr_str);
+		attr_str = ezxml_attr(xml, US_XML_VALID_ATTR);
+		if (attr_str != NULL) {
+			*valid = get_dig_number(attr_str);
+			rc = US_RC_OK;
+		} else
+			printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_VALID_ATTR);
+	} else
+		printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+
+	return rc;
+}
+
+static int get_rx_queue_attrs(ezxml_t xml, uint32_t gmac, tpm_init_gmac_rx_t *gmac_rx, int max_rx_queues_num)
+{
+	const char *attr_str;
+	int que_id;
+
+	attr_str = ezxml_attr(xml, US_XML_ID_ATTR);
+	if (attr_str == NULL) {
+		printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+		return (US_RC_FAIL);
+	}
+	que_id = get_dig_number(attr_str);
+
+	if (que_id >= max_rx_queues_num) {
+		printk(KERN_ERR "%s: Invalid ID number %s\n", __func__, attr_str);
+		return (US_RC_FAIL);
+	}
+
+	attr_str = ezxml_attr(xml, US_XML_SIZE_ATTR);
+	if (attr_str == NULL) {
+		printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_SIZE_ATTR);
+		return (US_RC_FAIL);
+	}
+
+	gmac_rx[gmac].rx_queue[que_id].queue_size = get_dig_number(attr_str);
+	gmac_rx[gmac].valid = 1;
+	gmac_rx[gmac].rx_queue[que_id].valid = 1;
+
+	return US_RC_OK;
+}
+
+static int get_tx_queue_attrs(ezxml_t xml, uint32_t port, tpm_init_gmac_tx_t *gmac_tx, int max_tx_queues_num)
+{
+	const char *attr_str;
+	int que_id;
+	int rc = US_RC_FAIL;
+
+	attr_str = ezxml_attr(xml, US_XML_ID_ATTR);
+	if (attr_str != NULL) {
+		que_id = get_dig_number(attr_str);
+
+		if (que_id < max_tx_queues_num) {
+			attr_str = ezxml_attr(xml, US_XML_QUEUE_SHED_ATTR);
+			if (attr_str != NULL) {
+				gmac_tx[port].tx_queue[que_id].sched_method = get_dig_number(attr_str);
+				attr_str = ezxml_attr(xml, US_XML_QUEUE_OWNER_ATTR);
+				if (attr_str != NULL) {
+					gmac_tx[port].tx_queue[que_id].queue_owner = get_dig_number(attr_str);
+					attr_str = ezxml_attr(xml, US_XML_QUEUE_OW_Q_NUM_ATTR);
+					if (attr_str != NULL) {
+						gmac_tx[port].tx_queue[que_id].owner_queue_num =
+							get_dig_number(attr_str);
+						attr_str = ezxml_attr(xml, US_XML_SIZE_ATTR);
+						if (attr_str != NULL) {
+							gmac_tx[port].tx_queue[que_id].queue_size =
+								get_dig_number(attr_str);
+							attr_str = ezxml_attr(xml, US_XML_QUEUE_WEIGHT_ATTR);
+							if (attr_str != NULL) {
+								gmac_tx[port].tx_queue[que_id].queue_weight =
+									get_dig_number(attr_str);
+								gmac_tx[port].valid = 1;
+								gmac_tx[port].tx_queue[que_id].valid = 1;
+								rc = US_RC_OK;
+							} else
+								printk(KERN_ERR "%s: Failed to get %s\n", __func__,
+									US_XML_QUEUE_WEIGHT_ATTR);
+						} else
+							printk(KERN_ERR "%s: Failed to get %s\n", __func__,
+								US_XML_SIZE_ATTR);
+					} else
+						printk(KERN_ERR "%s: Failed to get %s\n", __func__,
+							US_XML_QUEUE_OW_Q_NUM_ATTR);
+				} else
+					printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_QUEUE_OWNER_ATTR);
+			} else
+				printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_QUEUE_SHED_ATTR);
+		} else
+			printk(KERN_ERR "%s: Invalid ID number %s\n", __func__, attr_str);
+	} else
+		printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+
+	return rc;
+}
+
+static int get_pnc_range_attrs(ezxml_t xml, tpm_init_pnc_range_t *pnc_range, int max_pnc_ranges)
+{
+	const char *attr_str;
+	int range_num;
+	int rc = US_RC_FAIL;
+
+	attr_str = ezxml_attr(xml, US_XML_NUM_ATTR);
+	if (attr_str != NULL) {
+		range_num = get_dig_number(attr_str);
+		if (range_num < max_pnc_ranges) {
+			pnc_range[range_num].range_num = range_num;
+			attr_str = ezxml_attr(xml, US_XML_TYPE_ATTR);
+			if (attr_str != NULL) {
+				pnc_range[range_num].range_type = get_dig_number(attr_str);
+				attr_str = ezxml_attr(xml, US_XML_SIZE_ATTR);
+				if (attr_str != NULL) {
+					pnc_range[range_num].range_size = get_dig_number(attr_str);
+					attr_str = ezxml_attr(xml, US_XML_TPM_CNTR_GRP_ATTR);
+					if (attr_str != NULL) {
+						pnc_range[range_num].cntr_grp = get_dig_number(attr_str);
+						attr_str = ezxml_attr(xml, US_XML_TPM_LU_MASK_ATTR);
+						if (attr_str != NULL) {
+							pnc_range[range_num].lu_mask = get_dig_number(attr_str);
+							attr_str = ezxml_attr(xml, US_XML_TPM_MIN_RES_LVL_ATTR);
+							if (attr_str != NULL) {
+								pnc_range[range_num].min_reset_level =
+									get_dig_number(attr_str);
+								pnc_range[range_num].valid = 1;
+								rc = US_RC_OK;
+							} else
+								printk(KERN_ERR "%s: Failed to get %s\n", __func__,
+									US_XML_TPM_MIN_RES_LVL_ATTR);
+						} else
+							printk(KERN_ERR "%s: Failed to get %s\n", __func__,
+								US_XML_TPM_LU_MASK_ATTR);
+					} else
+						printk(KERN_ERR "%s: Failed to get %s\n", __func__,
+							US_XML_TPM_CNTR_GRP_ATTR);
+				} else
+					printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_SIZE_ATTR);
+			} else
+				printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_TYPE_ATTR);
+		} else
+			printk(KERN_ERR "%s: Invalid Range number %s\n", __func__, attr_str);
+	} else
+		printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_NUM_ATTR);
+
+	return rc;
+}
+
+static int get_mod_chain_attrs(ezxml_t xml, tpm_init_chain_data_t *chain_data)
+{
+	const char *attr_str;
+	int rc = US_RC_FAIL;
+
+	attr_str = ezxml_attr(xml, US_XML_TPM_CHAIN_TYPE_ATTR);
+	if (attr_str != NULL) {
+		chain_data->type = get_dig_number(attr_str);
+		attr_str = ezxml_attr(xml, US_XML_TPM_CHAIN_NUM_ATTR);
+		if (attr_str != NULL) {
+			chain_data->num = get_dig_number(attr_str);
+			return US_RC_OK;
+		} else
+			printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_TPM_CHAIN_NUM_ATTR);
+	} else
+		printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_TPM_CHAIN_TYPE_ATTR);
+
+	return rc;
+}
+
+static int get_vlan_ety_attrs(ezxml_t xml, uint32_t *etypes, int max_etypes)
+{
+	const char *attr_str;
+	int reg_id;
+	int rc = US_RC_FAIL;
+
+	attr_str = ezxml_attr(xml, US_XML_ID_ATTR);
+	if (attr_str != NULL) {
+		reg_id = get_dig_number(attr_str);
+		if (reg_id < max_etypes) {
+			attr_str = ezxml_attr(xml, US_XML_TYPE_ATTR);
+			if (attr_str != NULL) {
+				etypes[reg_id] = get_dig_number(attr_str);
+				rc = US_RC_OK;
+			} else
+				printk(KERN_ERR  "%s: Failed to get %s\n", __func__, US_XML_TYPE_ATTR);
+		} else
+			printk(KERN_ERR "%s: Invalid ID number %s\n", __func__, attr_str);
+	} else
+		printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+
+	return rc;
+}
+
+static int get_filter_tpid_attrs(ezxml_t xml, tpm_init_tpid_comb_t *tpid)
+{
+	const char *attr_str;
+	const char *v1_tpid = NULL;
+	const char *v2_tpid = NULL;
+	int rc = US_RC_FAIL;
+
+	attr_str = ezxml_attr(xml, US_XML_TYPE_ATTR);
+	if (attr_str != NULL) {
+		v1_tpid = attr_str;
+		v2_tpid = strstr(attr_str, ",");
+
+		tpid->v1_tpid = get_dig_number(v1_tpid);
+		if (v2_tpid != NULL) {
+			v2_tpid++;
+			tpid->v2_tpid = get_dig_number(v2_tpid);
+		} else
+			tpid->v2_tpid = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+		rc = US_RC_OK;
+	} else
+		printk("%s: Failed to get %s\n", __func__, US_XML_TYPE_ATTR);
+
+	return rc;
+}
+
+/*******************************************************************************
+* get_pon_type_param()
+*
+* DESCRIPTION:      Get WAN type from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  pon_type - EPON, GPON, ETH or P2P
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_pon_type_param(tpm_init_pon_type_t *pon_type)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+	uint32_t local_pon_type;
+
+	if (pon_type == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*pon_type = TPM_NONE;
+
+	xmlHead = ezxml_parse_file(US_XML_CFG_FILE_GLOBAL);
+	if (xmlHead == NULL) {
+		printk(KERN_ERR "Failed to open XML configuration file - %s\n", US_XML_CFG_FILE_GLOBAL);
+		return US_RC_FAIL;
+	}
+
+ 	xmlElement = ezxml_child(xmlHead, US_XML_WAN_E);
+ 	if (xmlElement == NULL) {
+ 		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_WAN_E, US_XML_CFG_FILE_GLOBAL);
+ 		rc = US_RC_NOT_FOUND;
+ 	} else
+ 		rc = get_int_param(xmlElement, US_XML_PON_TYPE_E, &local_pon_type);
+
+	if (rc == US_RC_OK) {
+		*pon_type = (tpm_init_pon_type_t) local_pon_type;
+
+#ifdef US_DEBUG_PRINT
+	{
+       	char * pon_str[] = {"EPON", "GPON", "P2P", "NONE"};
+		printk("pon_type = %s \n", pon_str[*pon_type]);
+	}
+#endif
+	}
+
+	ezxml_free(xmlHead);
+	return rc;
+}
+
+/*******************************************************************************
+* get_omci_etype_param()
+*
+* DESCRIPTION:      Get OMCI ETY from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  ety - Ethernet type
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_omci_etype_param(uint32_t *ety)
+{
+	int rc;
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+
+	if (ety == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*ety = 0;
+
+	xmlHead = ezxml_parse_file(US_XML_CFG_FILE_OMCI);
+	if (xmlHead == NULL) {
+		printk(KERN_ERR "Failed to open XML configuration file - %s\n", US_XML_CFG_FILE_OMCI);
+		return US_RC_FAIL;
+	}
+
+	xmlElement = ezxml_child(xmlHead, US_XML_OMCI_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_OMCI_E, US_XML_CFG_FILE_OMCI);
+		rc = US_RC_NOT_FOUND;
+	} else
+		rc = get_int_param(xmlElement, US_XML_OMCI_ETY_E, ety);
+
+	if (rc == US_RC_OK) {
+#ifdef US_DEBUG_PRINT
+		printk("OMCI ETY = 0x%4.4X\n", *ety);
+#endif
+	}
+
+	ezxml_free(xmlHead);
+	return rc;
+}
+
+/*******************************************************************************
+* get_debug_port_params()
+*
+* DESCRIPTION:      Get debug port from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  valid - whether the debug port is valid
+*           num   - debug port number
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_debug_port_params(uint32_t *valid, uint32_t *num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if ((valid == NULL) || (num == NULL)) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*valid = 0;
+	*num = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_PORT_INIT_E, 0, US_XML_DEBUG_PORT_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_DEBUG_PORT_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		get_debug_port_attrs(xmlElement, num, valid);
+
+#ifdef US_DEBUG_PRINT
+		printk("DEBUG port = %d valid = %d\n", *num, *valid);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_fc_def_params
+*
+* DESCRIPTION:      Get FC default parameters from XML configuration file
+*
+* INPUTS:
+*
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_fc_def_params(tpm_init_fc_params_t *port_fc_conf)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t u32_value;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_FC_PARAMS_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_FC_PARAMS_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc |= get_int_param(xmlElement, US_XML_ENABLED_E, &u32_value);
+		port_fc_conf->enabled = (uint8_t)u32_value;
+		rc |= get_int_param(xmlElement, US_XML_PORT_E, &u32_value);
+		port_fc_conf->port = (uint8_t)u32_value;
+       	rc |= get_int_param(xmlElement, US_XML_TX_PORT_E, &u32_value);
+		port_fc_conf->tx_port = (uint8_t)u32_value;
+		rc |= get_int_param(xmlElement, US_XML_TX_Q_E, &u32_value);
+		port_fc_conf->tx_queue = (uint8_t)u32_value;
+
+		rc |= get_int_param(xmlElement, US_XML_Q_SAMPLE_FREQ_E, &port_fc_conf->queue_sample_freq);
+		rc |= get_int_param(xmlElement, US_XML_THRESH_HIGH_E,	&port_fc_conf->thresh_high);
+		rc |= get_int_param(xmlElement, US_XML_THRESH_LOW_E, 	&port_fc_conf->thresh_low);
+		rc |= get_int_param(xmlElement, US_XML_TGT_PORT_E, 	&port_fc_conf->tgt_port);
+
+#ifdef US_DEBUG_PRINT
+		printk("SW port FC %s\n", (port_fc_conf->enabled) ? "Enabled" : "Disabled");
+		if (port_fc_conf->enabled) {
+       		printk(" port %d\n", port_fc_conf->port);
+			printk(" tgt_port %d\n", port_fc_conf->tgt_port);
+			printk(" tx_port %d\n", port_fc_conf->tx_port);
+			printk(" tx_queue %d\n", port_fc_conf->tx_queue);
+			printk(" queue_sample_freq %d\n", port_fc_conf->queue_sample_freq);
+			printk(" thresh_high %d\n", port_fc_conf->thresh_high);
+			printk(" thresh_low %d\n", port_fc_conf->thresh_low);
+		}
+#endif
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* get_igmp_snoop_params_enable()
+*
+* DESCRIPTION:      Get IGMP snooping parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - whether the IGMP snooping is enabled
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_igmp_snoop_params_enable(uint32_t *enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_IGMP_SNOOP_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_IGMP_SNOOP_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_ENABLED_E, enable);
+
+#ifdef US_DEBUG_PRINT
+		printk("IGMP snooping: enable %d \n", *enable);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_igmp_snoop_params_cpu_queue()
+*
+* DESCRIPTION:      Get IGMP snooping parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - whether the IGMP snooping is enabled
+*           que    - queue number
+*           all    - whether all packets should be verified
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_igmp_snoop_params_cpu_queue(uint32_t *que)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (que == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*que = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_IGMP_SNOOP_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_IGMP_SNOOP_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IGMP_CPU_Q_E, que);
+
+#ifdef US_DEBUG_PRINT
+		printk("IGMP snooping:  que %d\n", *que);
+#endif
+	}
+
+ /*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_igmp_snoop_params_port_frwd_mode()
+*
+* DESCRIPTION:      Get IGMP snooping parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - whether the IGMP snooping is enabled
+*           que    - queue number
+*           all    - whether all packets should be verified
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_igmp_snoop_params_port_frwd_mode(uint32_t *mode, tpm_src_port_type_t port)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	char *xml_param_str;
+
+	if (mode == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	switch (port) {
+	case TPM_SRC_PORT_WAN:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_WAN;
+		break;
+	case TPM_SRC_PORT_UNI_0:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_0;
+		break;
+	case TPM_SRC_PORT_UNI_1:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_1;
+		break;
+	case TPM_SRC_PORT_UNI_2:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_2;
+		break;
+	case TPM_SRC_PORT_UNI_3:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_3;
+		break;
+	case TPM_SRC_PORT_UNI_4:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_4;
+		break;
+	case TPM_SRC_PORT_UNI_5:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_5;
+		break;
+	case TPM_SRC_PORT_UNI_6:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_6;
+		break;
+	case TPM_SRC_PORT_UNI_7:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_7;
+		break;
+	case TPM_SRC_PORT_UNI_VIRT:
+		xml_param_str = US_XML_IGMP_PKT_FRWD_MODE_UNI_VIRT;
+		break;
+	case TPM_SRC_PORT_UNI_ANY:
+		return US_RC_NOT_FOUND;
+
+	default:
+#ifdef US_DEBUG_PRINT
+			printk(KERN_ERR "illegal input SRC port: %d\n", port);
+#endif
+			return US_RC_FAIL;
+	}
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_IGMP_SNOOP_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_IGMP_SNOOP_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+
+		rc = get_int_param(xmlElement, xml_param_str, mode);
+
+#ifdef US_DEBUG_PRINT
+		printk("igmp_mode port(%d), mode(%d) \n", port, *mode);
+#endif
+	}
+
+ /*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_gmac_mh_en_params()
+*
+* DESCRIPTION:      Get GMAC Marvell Header enable parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  gmac0_mh_en  - GMAC0 Marvell Header Enable configuration
+*           gmac1_mh_en  - GMAC0 Marvell Header Enable configuration
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_gmac_mh_en_params(uint32_t *gmac0_mh_en, uint32_t *gmac1_mh_en)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if ((gmac0_mh_en == NULL) || (gmac1_mh_en == NULL)) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*gmac0_mh_en = 0;
+	*gmac1_mh_en = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_PORT_INIT_E, 0, US_XML_GMAC_CONFIG_E, 0, US_XML_GMAC_MH_ENA_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_GMAC_MH_ENA_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_GMAC_0_MH_ENA_E, gmac0_mh_en);
+		rc |= get_int_param(xmlElement, US_XML_GMAC_1_MH_ENA_E, gmac1_mh_en);
+#ifdef US_DEBUG_PRINT
+		printk("======================================\n");
+		printk("        GMAC Marvell Header Enable    \n");
+		printk("======================================\n");
+		printk("gmac0_mh_en %d \n", *gmac0_mh_en);
+		printk("gmac1_mh_en %d \n", *gmac1_mh_en);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_gmac_conn_params()
+*
+* DESCRIPTION:      Get GMAC connection parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  num_tcont_llid  - TCONT/LLID number
+*           gmac0_con       - GMAC0 connection type
+*           gmac1_con       - GMAC1 connection type
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_gmac_conn_params(uint32_t *num_tcont_llid)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (num_tcont_llid == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*num_tcont_llid = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_PORT_INIT_E, 0, US_XML_GMAC_CONFIG_E, 0, US_XML_GMAC_CONN_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_GMAC_CONN_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_TCONT_LLID_E, num_tcont_llid);
+#ifdef US_DEBUG_PRINT
+		printk("======================================\n");
+		printk("        GMAC connection               \n");
+		printk("======================================\n");
+		printk("num_tcont_llid %d \n", *num_tcont_llid);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_gmac_pool_bufs_params()
+*
+* DESCRIPTION:      Get GMAC Buffer Pool parameters from XML configuration file
+*
+* INPUTS:   max_gmacs_num    - MAX GMACs in the system
+*
+* OUTPUTS:  gmac_bufs       - pointer to the gmac_buffer pool data
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_gmac_pool_bufs_params(tpm_init_gmac_bufs_t *gmac_bufs, int max_gmacs_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	ezxml_t xmlGmac;
+	const char *xmlStr;
+	int rc = US_RC_OK;
+	uint32_t gmac;
+	uint32_t large_pkt_pool_bufs;
+	uint32_t small_pkt_pool_bufs;
+
+	if (gmac_bufs == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	if (max_gmacs_num == 0) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: Invalid max_gmacs_num \n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	memset(gmac_bufs, 0, sizeof(tpm_init_gmac_bufs_t) * max_gmacs_num);
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_PORT_INIT_E, 0, US_XML_GMAC_CONFIG_E, 0, US_XML_GMAC_BM_BUF_E, -1);
+	if (xmlElement == NULL)
+		rc = US_RC_FAIL;
+	else {
+		xmlGmac = ezxml_child(xmlElement, US_XML_GMAC_E);
+		if (xmlGmac) {
+			for (; xmlGmac; xmlGmac = xmlGmac->next) {
+				xmlStr = ezxml_attr(xmlGmac, US_XML_ID_ATTR);
+				if (xmlStr == NULL) {
+					printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+					rc = US_RC_FAIL;
+					break;
+				}
+				gmac = get_dig_number(xmlStr);
+				if (gmac > (max_gmacs_num - 1)) {
+					printk(KERN_ERR "%s: Invalid GMAC id number - %s\n", __func__, xmlStr);
+					rc = US_RC_FAIL;
+					break;
+				}
+
+				xmlStr = ezxml_attr(xmlGmac, US_XML_LARGE_POOL_BUF_ATTR);
+				if (xmlStr == NULL) {
+					printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_LARGE_POOL_BUF_ATTR);
+					rc = US_RC_FAIL;
+					break;
+				}
+				large_pkt_pool_bufs = get_dig_number(xmlStr);
+
+				xmlStr = ezxml_attr(xmlGmac, US_XML_SHORT_POOL_BUF_ATTR);
+				if (xmlStr == NULL) {
+					printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_SHORT_POOL_BUF_ATTR);
+					rc = US_RC_FAIL;
+					break;
+				}
+				small_pkt_pool_bufs = get_dig_number(xmlStr);
+
+				gmac_bufs[gmac].valid = 1;
+				gmac_bufs[gmac].large_pkt_buffers = large_pkt_pool_bufs;
+				gmac_bufs[gmac].small_pkt_buffers = small_pkt_pool_bufs;
+			}
+		}
+#ifdef US_DEBUG_PRINT
+		printk("======================================\n");
+		printk("               GMAC BUFS              \n");
+		printk("======================================\n");
+		for (gmac = 0; gmac < max_gmacs_num; gmac++) {
+			if (gmac_bufs[gmac].valid) {
+				printk("gmac %d  large_bufs %d  small_bufs %d\n",
+				       gmac, gmac_bufs[gmac].large_pkt_buffers, gmac_bufs[gmac].small_pkt_buffers);
+			}
+		}
+		printk("======================================\n");
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+
+/*******************************************************************************
+* get_eth_cmplx_profile_params()
+*
+* DESCRIPTION:      Get GMAC connection parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  num_tcont_llid  - TCONT/LLID number
+*           gmac0_con       - GMAC0 connection type
+*           gmac1_con       - GMAC1 connection type
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_eth_cmplx_profile_params(tpm_eth_complex_profile_t *eth_cmplx_profile)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (eth_cmplx_profile == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*eth_cmplx_profile = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_ETH_CMPLX_CONFIG_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_ETH_CMPLX_CONFIG_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_ETH_PROFILE_E, eth_cmplx_profile);
+#ifdef US_DEBUG_PRINT
+		printk("======================================\n");
+		printk("            ETH COMPLEX               \n");
+		printk("======================================\n");
+		printk("eth_cmplx_profile %d \n", *eth_cmplx_profile);
+#endif
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* get_gmac_port_conf_params()
+*
+* DESCRIPTION:      Get GMAC Buffer Pool parameters from XML configuration file
+*
+* INPUTS:   max_gmacs_num    - MAX GMACs in the system
+*
+* OUTPUTS:  gmac_bufs       - pointer to the gmac_buffer pool data
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_gmac_port_conf_params(tpm_init_gmac_conn_conf_t *gmac_port_conf, int max_gmac_port_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	ezxml_t xmlPort;
+	const char *xmlStr;
+	int rc = US_RC_OK;
+	uint32_t port_src;
+	uint32_t port_nr;
+
+	if ((gmac_port_conf == NULL) || (max_gmac_port_num == 0)) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: gmac_port_conf=%p max_gmac_port_num=%d\n",
+		       __func__, gmac_port_conf, max_gmac_port_num);
+#endif
+		return US_RC_FAIL;
+	}
+
+	memset(gmac_port_conf, 0, sizeof(tpm_init_gmac_conn_conf_t) * max_gmac_port_num);
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+
+	xmlElement = ezxml_get(xmlHead, US_XML_ETH_CMPLX_CONFIG_E, 0, US_XML_GMAC_PORTS_E, -1);
+	if (xmlElement == NULL)
+		return US_RC_NOT_FOUND;
+
+	xmlPort = ezxml_child(xmlElement, US_XML_PORT_E);
+	if (xmlPort == NULL)
+		return US_RC_FAIL;
+
+	for (; xmlPort; xmlPort = xmlPort->next) {
+		/* mandatory field */
+		xmlStr = ezxml_attr(xmlPort, US_XML_ID_ATTR);
+		if (xmlStr == NULL) {
+			printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+			rc = US_RC_FAIL;
+			break;
+		}
+		port_nr = get_dig_number(xmlStr);
+		if (port_nr > (max_gmac_port_num - 1)) {
+			printk(KERN_ERR "%s: Invalid PORT id number - %s\n", __func__, xmlStr);
+			rc = US_RC_FAIL;
+			break;
+		}
+
+		/* optional field */
+		port_src = TPM_SRC_PORT_ILLEGAL;
+		xmlStr = ezxml_attr(xmlPort, US_XML_ETH_PORT_SRC_ATTR);
+		if (xmlStr != NULL)
+			port_src = get_dig_number(xmlStr);
+
+		gmac_port_conf[port_nr].valid = 1;
+		gmac_port_conf[port_nr].port_src = port_src;
+	}
+
+#ifdef US_DEBUG_PRINT
+	 printk("======================================\n");
+	 printk("              GMAC PORTS              \n");
+	 printk("======================================\n");
+	 for (port_nr = 0; port_nr < max_gmac_port_num; port_nr++) {
+	 	if (gmac_port_conf[port_nr].valid) {
+	 		printk("port %d  port_src %d\n",
+	 		       port_nr, gmac_port_conf[port_nr].port_src);
+	 	}
+	 }
+	 printk("======================================\n");
+#endif
+
+	return rc;
+}
+
+
+/*******************************************************************************
+* get_eth_port_conf_params()
+*
+* DESCRIPTION:      Get GMAC Buffer Pool parameters from XML configuration file
+*
+* INPUTS:   max_gmacs_num    - MAX GMACs in the system
+*
+* OUTPUTS:  gmac_bufs       - pointer to the gmac_buffer pool data
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_eth_port_conf_params(tpm_init_eth_port_conf_t *eth_port_bufs, int max_eth_port_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	ezxml_t xmlPort;
+	const char *xmlStr;
+	int rc = US_RC_OK;
+	uint32_t switch_port;
+	uint32_t port_src;
+	uint32_t port_nr;
+
+	if ((eth_port_bufs == NULL) || (max_eth_port_num == 0)) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: eth_port_bufs=%p max_eth_port_num=%d\n", __func__, eth_port_bufs, max_eth_port_num);
+#endif
+		return US_RC_FAIL;
+	}
+
+	memset(eth_port_bufs, 0, sizeof(tpm_init_eth_port_conf_t) * max_eth_port_num);
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_ETH_CMPLX_CONFIG_E, 0, US_XML_ETH_SW_PORT_ATTR, -1);
+	if (xmlElement == NULL)
+		return US_RC_NOT_FOUND;
+
+	xmlPort = ezxml_child(xmlElement, US_XML_PORT_E);
+	if (xmlPort == NULL)
+		return US_RC_FAIL;
+
+	for (port_nr = 0; xmlPort && (port_nr < max_eth_port_num); xmlPort = xmlPort->next, port_nr++) {
+		/* mandatory field */
+		xmlStr = ezxml_attr(xmlPort, US_XML_ID_ATTR);
+		if (xmlStr == NULL) {
+			printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+			rc = US_RC_FAIL;
+			break;
+		}
+		switch_port = get_dig_number(xmlStr);
+		if (switch_port > 6) {
+			printk(KERN_ERR "%s: Invalid PORT id number - %s\n", __func__, xmlStr);
+			rc = US_RC_FAIL;
+			break;
+		}
+		
+		/* mandatory field */
+		xmlStr = ezxml_attr(xmlPort, US_XML_ETH_PORT_SRC_ATTR);
+		if (xmlStr == NULL) {
+			printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ETH_PORT_SRC_ATTR);
+			rc = US_RC_FAIL;
+			break;
+		}
+		port_src = get_dig_number(xmlStr);
+
+		eth_port_bufs[port_nr].valid = 1;
+		eth_port_bufs[port_nr].switch_port = switch_port;
+		eth_port_bufs[port_nr].port_src = port_src;
+       }
+#ifdef US_DEBUG_PRINT
+	printk("======================================\n");
+	printk("               ETH PORTS              \n");
+	printk("======================================\n");
+	for (port_nr = 0; port_nr < max_eth_port_num; port_nr++) {
+		if (eth_port_bufs[port_nr].valid) {
+			printk("%d)  src_port %d  switch_port %d\n",
+			       port_nr,
+			       eth_port_bufs[port_nr].port_src, 
+			       eth_port_bufs[port_nr].switch_port);
+		}
+	}
+	printk("======================================\n");
+#endif
+
+	return rc;
+}
+
+/*******************************************************************************
+* get_backup_wan_params()
+*
+* DESCRIPTION:      Get GMAC connection parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  num_tcont_llid  - TCONT/LLID number
+*           gmac0_con       - GMAC0 connection type
+*           gmac1_con       - GMAC1 connection type
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_backup_wan_params(uint32_t *backup_wan)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (backup_wan == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*backup_wan = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_ETH_CMPLX_CONFIG_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_ETH_CMPLX_CONFIG_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_BACKUP_WAN_E, backup_wan);
+#ifdef US_DEBUG_PRINT
+		printk("======================================\n");
+		printk("            ETH COMPLEX               \n");
+		printk("======================================\n");
+		printk("backup_wan %d \n", *backup_wan);
+#endif
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* get_gmac_rxq_params()
+*
+* DESCRIPTION:
+*
+* INPUTS:   max_gmacs_num    - MAX GMACs in the system
+*           max_rx_queues_num - MAX possible rx_queues per GMAC
+*
+* OUTPUTS:  gmac_rx             - pointer to the gmac rx_queues data
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_gmac_rxq_params(tpm_init_gmac_rx_t *gmac_rx, int max_gmacs_num, int max_rx_queues_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	const char *xmlStr;
+	ezxml_t xmlGmac, xmlQue;
+	int rc = US_RC_OK;
+	uint32_t gmac;
+	uint32_t stop_parsing = 0;
+
+	if (gmac_rx == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	if (max_gmacs_num == 0) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: Invalid max_gmacs_num \n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+	if (max_rx_queues_num == 0) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: Invalid max_tx_queues_num \n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	memset(gmac_rx, 0, sizeof(tpm_init_gmac_rx_t) * max_gmacs_num);
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_PORT_INIT_E, 0, US_XML_GMAC_CONFIG_E, 0, US_XML_GMAC_RXQUEUES_E, -1);
+	if (xmlElement == NULL)
+		rc = US_RC_FAIL;
+	else {
+		xmlGmac = ezxml_child(xmlElement, US_XML_GMAC_E);
+		if (xmlGmac) {
+			for (; (xmlGmac && !stop_parsing); xmlGmac = xmlGmac->next) {
+				xmlStr = ezxml_attr(xmlGmac, US_XML_ID_ATTR);
+				if (xmlStr == NULL) {
+					printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+					rc = US_RC_FAIL;
+					break;
+				}
+				gmac = get_dig_number(xmlStr);
+				if (gmac > (max_gmacs_num - 1)) {
+					printk(KERN_ERR "%s: Invalid GMAC id number - %s\n", __func__, xmlStr);
+					rc = US_RC_FAIL;
+					break;
+				}
+
+				/* Get GMAC rx queue sizes */
+				for (xmlQue = ezxml_child(xmlGmac, US_XML_QUEUE_E); xmlQue; xmlQue = xmlQue->next) {
+					rc = get_rx_queue_attrs(xmlQue, gmac, gmac_rx, max_rx_queues_num);
+
+					if (rc != US_RC_OK) {
+						stop_parsing = 1;
+						break;
+					}
+				}
+
+			}
+		}
+#ifdef US_DEBUG_PRINT
+		{
+
+			uint32_t rxq;
+			printk("======================================\n");
+			printk("               GMAC RXQs              \n");
+			printk("======================================\n");
+			for (gmac = 0; gmac < max_gmacs_num; gmac++) {
+				if (gmac_rx[gmac].valid) {
+					for (rxq = 0; rxq < max_rx_queues_num; rxq++) {
+						if (gmac_rx[gmac].rx_queue[rxq].valid) {
+							printk("gmac %d rxq %d size %d\n",
+							       gmac, rxq, gmac_rx[gmac].rx_queue[rxq].queue_size);
+						}
+					}
+				}
+			}
+			printk("======================================\n");
+		}
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_gmac_tx_params()
+*
+* DESCRIPTION:      Get GMAC TX parameters from XML configuration file
+*
+* INPUTS:   max_tx_ports_num    - MAX TX ports in the system
+*           max_tx_queues_num   - MAX TX queues per port
+*
+* OUTPUTS:  gmac_tx             - pointer to the TX port data
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_gmac_tx_params(tpm_init_gmac_tx_t *gmac_tx, int max_tx_ports_num, int max_tx_queues_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	ezxml_t xmlGmac;
+	ezxml_t xmlQueMap;
+	ezxml_t xmlQue;
+	int rc = US_RC_OK;
+	uint32_t port;
+	const char *xmlStr;
+	uint8_t stop_parsing = 0;
+
+	if (gmac_tx == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	if ((max_tx_ports_num == 0) || (max_tx_queues_num == 0)) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: Invalid max_int_ports_num \n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	memset(gmac_tx, 0, sizeof(tpm_init_gmac_tx_t) * max_tx_ports_num);
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_PORT_INIT_E, 0, US_XML_TX_MOD_PARAMS_E, -1);
+	if (xmlElement == NULL)
+		rc = US_RC_FAIL;
+	else {
+		for (xmlGmac = ezxml_child(xmlElement, US_XML_TX_MOD_E);
+		     xmlGmac && !stop_parsing; xmlGmac = xmlGmac->next) {
+			xmlStr = ezxml_attr(xmlGmac, US_XML_ID_ATTR);
+			if (xmlStr == NULL) {
+				printk(KERN_ERR "%s: Failed to get %s\n", __func__, US_XML_ID_ATTR);
+				rc = US_RC_FAIL;
+				break;
+			}
+
+			port = get_dig_number(xmlStr);
+			if (port > max_tx_ports_num) {
+				printk(KERN_ERR "%s: Invalid GMAC id number - %s\n", __func__, xmlStr);
+				rc = US_RC_FAIL;
+				break;
+			}
+
+			xmlQueMap = ezxml_child(xmlGmac, US_XML_QUEUE_MAP_E);
+			for (xmlQue = ezxml_child(xmlQueMap, US_XML_QUEUE_E); xmlQue; xmlQue = xmlQue->next) {
+				rc = get_tx_queue_attrs(xmlQue, port, gmac_tx, max_tx_queues_num);
+
+				if (rc != US_RC_OK) {
+					stop_parsing = 1;
+					break;
+				}
+			}
+		}
+
+#ifdef US_DEBUG_PRINT
+		{
+			int que;
+
+			printk("======================================\n");
+			printk("               GMAC TX                \n");
+			printk("======================================\n");
+			for (port = 0; port < max_tx_ports_num; port++) {
+				if (gmac_tx[port].valid) {
+					printk("TX port %d  \n", port);
+					printk("------------\n");
+
+					for (que = 0; que < max_tx_queues_num; que++) {
+						if (gmac_tx[port].tx_queue[que].valid) {
+							printk(KERN_INFO
+								"TX queue %d: valid %d owner %d owner num %d "
+								"size %d weight %d sched %d\n",
+								que, gmac_tx[port].tx_queue[que].valid,
+								gmac_tx[port].tx_queue[que].queue_owner,
+								gmac_tx[port].tx_queue[que].owner_queue_num,
+								gmac_tx[port].tx_queue[que].queue_size,
+								gmac_tx[port].tx_queue[que].queue_weight,
+								gmac_tx[port].tx_queue[que].sched_method);
+						}
+					}
+					/*} */
+				}
+				printk("======================================\n");
+			}
+		}
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_pnc_range_params()
+*
+* DESCRIPTION:      Get PnC ranges parameters from XML configuration file
+*
+* INPUTS:   max_pnc_ranges_num  - MAX PnC ranges in the system
+*
+* OUTPUTS:  pnc_range           - pointer to the internal PnC range table
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_pnc_range_params(tpm_init_pnc_range_t *pnc_range, int max_pnc_ranges_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	ezxml_t xmlRange;
+	int rc = US_RC_OK;
+
+	if (pnc_range == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	if (max_pnc_ranges_num == 0) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: Invalid max_pnc_ranges_num \n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	memset(pnc_range, 0, sizeof(tpm_init_pnc_range_t) * max_pnc_ranges_num);
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_PNC_E, 0, US_XML_TPM_PNC_RANGE_PARAMS_E, -1);
+	if (xmlElement == NULL)
+		rc = US_RC_FAIL;
+	else {
+		for (xmlRange = ezxml_child(xmlElement, US_XML_TPM_PNC_RANGE_E); xmlRange; xmlRange = xmlRange->next) {
+			rc = get_pnc_range_attrs(xmlRange, pnc_range, max_pnc_ranges_num);
+
+			if (rc != US_RC_OK)
+				break;
+		}
+
+#ifdef US_DEBUG_PRINT
+		{
+			int range;
+
+			printk("======================================\n");
+			printk("              PnC range               \n");
+			printk("======================================\n");
+			for (range = 0; range < max_pnc_ranges_num; range++) {
+				if (pnc_range[range].valid)
+					printk("%d: num %d type %d size %d cntr_grp %d "
+						"lu_mask %d min_res_level %d\n",
+						range,
+						pnc_range[range].range_num,
+						pnc_range[range].range_type,
+						pnc_range[range].range_size,
+						pnc_range[range].cntr_grp,
+						pnc_range[range].lu_mask, pnc_range[range].min_reset_level);
+			}
+			printk("======================================\n");
+		}
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_ds_mh_config_params()
+*
+* DESCRIPTION:      Get downstream MH parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  ds_mh_set - from PnC RI or Rx ctrl reg
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_ds_mh_config_params(tpm_init_mh_src_t *dsMhConf)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (dsMhConf == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*dsMhConf = TPM_MH_SRC_RX_CTRL;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_TPM_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else
+		rc = get_int_param(xmlElement, US_XML_DS_MH_SET_E, &val);
+
+	if (rc == US_RC_OK) {
+		*dsMhConf = (tpm_init_mh_src_t) val;
+
+#ifdef US_DEBUG_PRINT
+		printk("dsMhConf = %d\n", *dsMhConf);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_validation_enabled_config_params()
+*
+* DESCRIPTION:      Get validation enable parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  validation_enabled - enable or not TPM validation
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_validation_enabled_config_params(tpm_init_tpm_validation_t *validEn)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+	uint32_t val;
+
+	if (validEn == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*validEn = TPM_VALID_DISABLED;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_TPM_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else
+		rc = get_int_param(xmlElement, US_XML_VALID_EN_E, &val);
+
+	if (rc == US_RC_OK) {
+		*validEn = (tpm_init_tpm_validation_t) val;
+
+#ifdef US_DEBUG_PRINT
+		printk("validEn = %d\n", *validEn);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_epon_connect_tpm_params()
+*
+* DESCRIPTION:      Get EPON connect TPM APIS parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  connected - disconnect or connected.
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_epon_connect_tpm_params(PON_connect_type_t *connected)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+	uint32_t val;
+
+	if (connected == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*connected = ONU_PON_CONNECT;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_EPON_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_EPON_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else
+		rc = get_int_param(xmlElement, US_XML_EPON_CONNECT_E, &val);
+
+	if (rc == US_RC_OK) {
+		*connected = (PON_connect_type_t) val;
+
+#ifdef US_DEBUG_PRINT
+		printk("connected = %d\n", *connected);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_epon_oam_rx_q_params()
+*
+* DESCRIPTION:      Get EPON CPU OAM RX Q parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  OAM CPU RX Queue value
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_epon_oam_rx_q_params(uint32_t *oam_cpu_rx_queue)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+	uint32_t val;
+
+	if (oam_cpu_rx_queue == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	/* default queue is 7 - highest queue */
+	*oam_cpu_rx_queue = 7;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_EPON_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_EPON_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else
+		rc = get_int_param(xmlElement, US_XML_EPON_OAM_RXQ_E, &val);
+
+	if (rc == US_RC_OK) {
+		*oam_cpu_rx_queue = val;
+
+#ifdef US_DEBUG_PRINT
+		printk("oam_cpu_rx_queue = %d\n", *oam_cpu_rx_queue);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_cfg_pnc_parse_param()
+*
+* DESCRIPTION:      Get mode of how to configure the PNC PARSE in LSP
+*
+* INPUTS:
+*
+* OUTPUTS:  cfgPncParse - enabled/disabled
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_cfg_pnc_parse_param(tpm_init_cfg_pnc_parse_t *cfgPncParse)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+	uint32_t val;
+
+	if (cfgPncParse == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*cfgPncParse = TPM_NONE;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL)
+		rc = US_RC_NOT_FOUND;
+	else
+		rc = get_int_param(xmlElement, US_XML_CFG_PNC_PARSER, &val);
+
+	if (rc == US_RC_OK) {
+		*cfgPncParse = (tpm_init_cfg_pnc_parse_t) val;
+
+#ifdef US_DEBUG_PRINT
+		printk("cfgPncParse = %d\n", *cfgPncParse);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_cpu_loopback_param()
+*
+* DESCRIPTION:      Get CPU egress loopback state
+*
+* INPUTS:
+*
+* OUTPUTS:  cfgCpuLoopback - enabled/disabled
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_cpu_loopback_param(tpm_init_cpu_loopback_t *cpuLoopback)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+	uint32_t val;
+
+	if (cpuLoopback == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*cpuLoopback = TPM_NONE;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL)
+		rc = US_RC_NOT_FOUND;
+	else
+		rc = get_int_param(xmlElement, US_XML_CFG_CPU_LOOPBACK, &val);
+
+	if (rc == US_RC_OK) {
+		*cpuLoopback = (tpm_init_cpu_loopback_t) val;
+
+#ifdef US_DEBUG_PRINT
+		printk("cfgCpuLoopback = %d\n", *cpuLoopback);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_trace_debug_info_param()
+*
+* DESCRIPTION:      Get mode of how to configure the PNC PARSE in LSP
+*
+* INPUTS:
+*
+* OUTPUTS:  cfgPncParse - enabled/disabled
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_trace_debug_info_param(uint32_t *trace_debug_info)
+{
+
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+	uint32_t val;
+
+	if (trace_debug_info == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*trace_debug_info = 0x00000000;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL)
+		rc = US_RC_NOT_FOUND;
+	else
+		rc = get_int_param(xmlElement, US_XML_TRACE_DEBUG_info, &val);
+
+	if (rc == US_RC_OK) {
+		*trace_debug_info = val;
+
+#ifdef US_DEBUG_PRINT
+		printk("trace_debug_info = 0x%x\n", *trace_debug_info);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_vitual_uni_enable_params()
+*
+* DESCRIPTION:      Get WiFi via GMAC1 feature parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - whether the WiFi via GMAC1 is enabled
+*           port   - port number for WiFi identification
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_vitual_uni_enable_params(uint32_t *enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val1;
+
+	if (enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+
+		printk(KERN_ERR "get_wifi_vitual_uni_enable_params => NULL pointer\n");
+		return US_RC_FAIL;
+	}
+
+	*enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL)
+		rc = US_RC_NOT_FOUND;
+	else {
+		rc = get_int_param(xmlElement, US_XML_WIFI_ENABLED, &val1);
+		/* add port parameter to the XML - in the future - meantime default port: UNI_4 = 5 */
+		/*        rc |= get_int_param (xmlElement, US_XML_WIFI_PORT, &val2);*/
+	}
+
+	if (rc == US_RC_OK) {
+		*enable = val1;
+
+#ifdef US_DEBUG_PRINT
+		printk("wifi_vir_uni_enable => en= %d\n", *enable);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+
+}
+
+#if 0
+/*******************************************************************************
+* get_default_vlan_tpid_params()
+*
+* DESCRIPTION:      Get double tag support parameter from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - whether the WiFi via GMAC1 is enabled
+*           port   - port number for WiFi identification
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_default_vlan_tpid_params(uint16_t *v1_tpid, uint16_t *v2_tpid)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val1, val2;
+
+	if ((v1_tpid == NULL) || (v2_tpid == NULL)) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+
+		return US_RC_FAIL;
+	}
+
+	*v1_tpid = *v2_tpid = 0x8100;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL)
+		rc = US_RC_NOT_FOUND;
+	else {
+		rc |= get_int_param(xmlElement, US_XML_DEF_V1_TPID, &val1);
+		rc |= get_int_param(xmlElement, US_XML_DEF_V2_TPID, &val2);
+	}
+
+	if (rc == US_RC_OK) {
+		*v1_tpid = val1;
+		*v2_tpid = val2;
+
+#ifdef US_DEBUG_PRINT
+		printk(KERN_INFO"get_double_tag_support_params => v1_tpid= 0x%x  v2_tpid= 0x%x\n", *v1_tpid, *v2_tpid);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+
+}
+#endif
+
+/*******************************************************************************
+* get_default_vlan_tpid_params()
+*
+* DESCRIPTION:      Get double tag support parameter from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - whether the WiFi via GMAC1 is enabled
+*           port   - port number for WiFi identification
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_default_vlan_tpid_params(uint32_t *opt_num, tpm_init_tpid_comb_t *opt)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	ezxml_t xmlTpid;
+	int optNum;
+	int rc;
+
+	if ((opt_num == NULL) || (opt == NULL)) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	optNum = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_VLAN_FILTER_TPID_E, -1);
+	if (xmlElement == NULL) {
+		printk("Failed to find %s in XML config. file %s\n", US_XML_TPM_VLAN_FILTER_TPID_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else {
+		for (xmlTpid = ezxml_child(xmlElement, US_XML_TPM_FILTER_TPID_E); \
+			xmlTpid && (optNum < TPM_MAX_TPID_COMB_NUM); \
+			xmlTpid = xmlTpid->next, optNum++) {
+			rc = get_filter_tpid_attrs(xmlTpid, &(opt[optNum]));
+			if (rc != US_RC_OK)
+			break;
+		}
+		*opt_num = optNum;
+	}
+
+	return rc;
+}
+
+/*******************************************************************************
+* get_pon_def_params()
+*
+* DESCRIPTION: Get PON default parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  param[PON_XML_DEF_PAR_SERIAL_NUM]		- serial number
+*           param[PON_XML_DEF_PAR_PASSWORD]			- password
+*           param[PON_XML_DEF_PAR_DIS_SERIAL_NUM]	- whether SN should be disabled
+*           param[PON_XML_DEF_PARAM_CLEAR_GEM]		- whether gem ports should be removed on reset
+*           param[PON_XML_DEF_PARAM_CLEAR_TCONT]	- whether tconts should be removed on reset
+*   		param[PON_XML_DEF_PARAM_SERIAL_NUM_SRC]	- whether serial number should be taken from xml
+*   													or should the digit part be taken from MAC address
+*   		param[PON_XML_DEF_PARAM_XVR_POLARITY]	- tranceiver polarity
+*   		param[PON_XML_DEF_PARAM_DG_POLARITY]	- dying gasp polarity
+*   		param[PON_XML_DEF_PARAM_RESTORE_GEM]	- whether restore or not GEM ports after returning
+*   													from state-7 (EMG STOP)
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_pon_def_params (void  **param)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+	int	paramIdx;
+	unsigned char   *sn = (unsigned char *)param[PON_XML_DEF_PAR_SERIAL_NUM];
+	unsigned char   *pswd = (unsigned char *)param[PON_XML_DEF_PAR_PASSWORD];
+
+	if (param == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: parameters list is a NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	for (paramIdx = PON_XML_DEF_PAR_SERIAL_NUM; paramIdx < PON_XML_DEF_PARAM_MAX; paramIdx++) {
+		if (param[paramIdx] == NULL) {
+#ifdef US_DEBUG_PRINT
+			printk(KERN_ERR "%s: parameter #%d is a NULL pointer\n", __func__, paramIdx);
+#endif
+			return US_RC_FAIL;
+		}
+	}
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_PON_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_PON_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+
+	} else {
+
+		sn[0] = '\0';
+		rc = get_char_param(xmlElement, US_XML_PON_SN_E, sn, US_XML_PON_SN_LEN);
+		pswd[0] = '\0';
+		rc |= get_char_param(xmlElement, US_XML_PON_PASSWD_E, pswd, US_XML_PON_PASSWD_LEN);
+		*(uint32_t *)param[PON_XML_DEF_PAR_DIS_SERIAL_NUM] = 0;
+		rc |= get_int_param(xmlElement, US_XML_PON_DIS_SN_E, (uint32_t *)param[PON_XML_DEF_PAR_DIS_SERIAL_NUM]);
+		*(uint32_t *)param[PON_XML_DEF_PARAM_CLEAR_GEM] = 0;
+		rc |= get_int_param (xmlElement, US_XML_PON_GEM_RST_E, (uint32_t *)param[PON_XML_DEF_PARAM_CLEAR_GEM]);
+		*(uint32_t *)param[PON_XML_DEF_PARAM_CLEAR_TCONT] = 0;
+		rc |= get_int_param(xmlElement, US_XML_PON_TCONT_RST_E, (uint32_t *)param[PON_XML_DEF_PARAM_CLEAR_TCONT]);
+		*(uint32_t *)param[PON_XML_DEF_PARAM_SERIAL_NUM_SRC] = 0;
+		rc |= get_int_param(xmlElement, US_XML_PON_SN_SRC_E, (uint32_t *)param[PON_XML_DEF_PARAM_SERIAL_NUM_SRC]);
+		*(uint32_t *)param[PON_XML_DEF_PARAM_XVR_POLARITY] = 0;
+		rc |= get_int_param(xmlElement, US_XML_PON_XVR_POL_E, (uint32_t *)param[PON_XML_DEF_PARAM_XVR_POLARITY]);
+		*(uint32_t *)param[PON_XML_DEF_PARAM_DG_POLARITY] = 1;
+		rc |= get_int_param(xmlElement, US_XML_PON_DG_POL_E, (uint32_t *)param[PON_XML_DEF_PARAM_DG_POLARITY]);
+		*(uint32_t *)param[PON_XML_DEF_PARAM_RESTORE_GEM] = 1;
+		rc |= get_int_param(xmlElement, US_XML_PON_GEM_RESTOR_E, (uint32_t *)param[PON_XML_DEF_PARAM_RESTORE_GEM]);
+
+#ifdef US_DEBUG_PRINT
+		printk(KERN_DEBUG "PON default params: SN %s pswd %s dis %d\n", sn, pswd,
+			   *(uint32_t *)param[PON_XML_DEF_PAR_DIS_SERIAL_NUM]);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_epon_def_params()
+*
+* DESCRIPTION: Get EPON default parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  dba_mode      - DBA mode is either 0 for SW or 1 for HW
+*           xvr_pol       - XVR polarity (0 - high, 1 - low)
+*           dg_pol        - Dying Gasp polarity (1 - high, 0 - low)
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_epon_def_params(unsigned long *xvr_pol, unsigned long *dg_pol)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_EPON_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_EPON_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else {
+		*xvr_pol = 0;
+		rc = get_int_param(xmlElement, US_XML_EPON_XVR_POL_E, (uint32_t *) xvr_pol);
+		*dg_pol = 1;
+		rc |= get_int_param(xmlElement, US_XML_EPON_DG_POL_E, (uint32_t *) dg_pol);
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_pon_dg_polarity()
+*
+* DESCRIPTION: Get PON Dying Gasp polarity value from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  dg_pol - Daing Gasp polarity is either 0 for high or 1 for low
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_pon_dg_polarity(unsigned long *dg_pol)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_PON_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_PON_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else {
+		*dg_pol = 1;
+		rc = get_int_param(xmlElement, US_XML_PON_DG_POL_E, (uint32_t *) dg_pol);
+		if (rc == US_RC_NOT_FOUND) {
+			printk(KERN_ERR "Failed to find %s tag in XML config. file \n", US_XML_PON_DG_POL_E);
+			*dg_pol = 1;
+			rc = US_RC_OK;
+		}
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+
+}
+
+/*******************************************************************************
+* get_vlan_etypes_params()
+*
+* DESCRIPTION:      Get VLAN ETY parameters from XML configuration file
+*
+* INPUTS:   vlan_ety_reg_num    - Number of VLAN ETY registers in the system
+*
+* OUTPUTS:  mod_tpid            - pointer to the VLANs ETY table
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_vlan_mod_vlan_tpid_params(uint32_t *mod_vlan_tpid, int mod_vlan_tpid_reg_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	ezxml_t xmlEty;
+	int rc = US_RC_OK, i;
+
+	if (mod_vlan_tpid == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	if (mod_vlan_tpid_reg_num == 0) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: Invalid vlan_ety_reg_num \n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	for (i = 0; i < mod_vlan_tpid_reg_num; i++)
+		mod_vlan_tpid[i] = MV_TPM_UN_INITIALIZED_INIT_PARAM;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_MOD_VLAN_TPID_E, -1);
+	if (xmlElement == NULL)
+		rc = US_RC_NOT_FOUND;
+	else {
+		for (xmlEty = ezxml_child(xmlElement, US_XML_TPM_MOD_TPID_E); xmlEty; xmlEty = xmlEty->next) {
+			rc = get_vlan_ety_attrs(xmlEty, mod_vlan_tpid, mod_vlan_tpid_reg_num);
+
+			if (rc != US_RC_OK)
+				break;
+		}
+
+#ifdef US_DEBUG_PRINT
+		{
+			int reg;
+
+			printk("============================\n");
+			printk("  Reg#   VLAN etype   \n");
+			printk("============================\n");
+			for (reg = 0; reg < mod_vlan_tpid_reg_num; reg++)
+				printk("   %d        0x%x\n", reg, mod_vlan_tpid[reg]);
+
+			printk("============================\n");
+		}
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_modification_params()
+*
+* DESCRIPTION: Get TPM modification parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  config  - configuration parameters of Modification table
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_modification_params(tpm_init_mod_params_t *config)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (config == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	config->udp_checksum_use_init_bm = 0;
+	config->udp_checksum_update = 0;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_MOD_E, -1);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_TPM_MOD_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc |= get_int_param(xmlElement, US_XML_TPM_MOD_UDP_CKS_USE_INIT_E, &config->udp_checksum_use_init_bm);
+		rc |= get_int_param(xmlElement, US_XML_TPM_MOD_UDP_CKS_CALC_E, &config->udp_checksum_update);
+
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_chain_config_params()
+*
+* DESCRIPTION:      Get num_vlan_tags parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  num_vlan_tags - vlan nmuber
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_chain_config_params(tpm_init_mod_chain_t *mod_chain)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	ezxml_t xmlChain;
+	int chainNum;
+	int rc;
+
+	if (mod_chain == NULL)
+		return US_RC_FAIL;
+
+	memset(mod_chain, 0, sizeof(tpm_init_mod_chain_t));
+	chainNum = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_MOD_E, 0, US_XML_TPM_MOD_CHAIN_PARAM_E, -1);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TPM_MOD_CHAIN_PARAM_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else {
+		for (xmlChain = ezxml_child(xmlElement, US_XML_TPM_MOD_CHAIN_E);
+		     xmlChain && (chainNum < TPM_MAX_MOD_CHAIN_NUM); xmlChain = xmlChain->next, chainNum++) {
+			rc = get_mod_chain_attrs(xmlChain, &(mod_chain->chain_data[chainNum]));
+
+			if (rc != US_RC_OK)
+				break;
+		}
+
+		mod_chain->chain_num = chainNum;
+	}
+
+	return rc;
+}
+
+/* jinghua add for MTU setting */
+/*******************************************************************************
+* get_mtu_enable()
+*
+* DESCRIPTION:      Get mtu enable parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - mtu enable
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_mtu_enable(tpm_init_mtu_setting_enable_t *enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MTU_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MTU_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_MTU_SETTING_ENABLE_E, &val);
+		if (rc == US_RC_OK) {
+			*enable = (tpm_init_mtu_setting_enable_t) val;
+
+#ifdef US_DEBUG_PRINT
+			printk("US_XML_MTU_SETTING_ENABLE_E: enable %d \n", *enable);
+#endif
+		}
+
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_ipv4_mtu_us()
+*
+* DESCRIPTION:      Get ipv4 mtu parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  mtu - ipv4 mtu
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_ipv4_mtu_us(uint32_t *mtu)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mtu == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mtu = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MTU_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MTU_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV4_MTU_US_E, mtu);
+
+#ifdef US_DEBUG_PRINT
+		printk("IPV4_MTU: mtu %d \n", *mtu);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_ipv4_pppoe_mtu_us()
+*
+* DESCRIPTION:      Get ipv4 pppoe mtu parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  mtu - ipv4 pppoe mtu
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_ipv4_pppoe_mtu_us(uint32_t *mtu)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mtu == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mtu = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MTU_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MTU_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV4_PPPOE_MTU_US_E, mtu);
+
+#ifdef US_DEBUG_PRINT
+		printk("IPV4_PPPOE_MTU: mtu %d \n", *mtu);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_ipv6_mtu_us()
+*
+* DESCRIPTION:      Get ipv6 mtu parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  mtu - ipv6 mtu
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_ipv6_mtu_us(uint32_t *mtu)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mtu == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mtu = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MTU_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MTU_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV6_MTU_US_E, mtu);
+
+#ifdef US_DEBUG_PRINT
+		printk("IPV6_MTU: mtu %d \n", *mtu);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_ipv6_pppoe_mtu_us()
+*
+* DESCRIPTION:      Get ipv6 pppoe mtu parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  mtu - ipv6 pppoe mtu
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_ipv6_pppoe_mtu_us(uint32_t *mtu)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mtu == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mtu = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MTU_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MTU_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV6_PPPOE_MTU_US_E, mtu);
+
+#ifdef US_DEBUG_PRINT
+		printk("IPV6_PPPOE_MTU: mtu %d \n", *mtu);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_ipv4_mtu_ds()
+*
+* DESCRIPTION:      Get ipv4 mtu parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  mtu - ipv4 mtu
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_ipv4_mtu_ds(uint32_t *mtu)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mtu == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mtu = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MTU_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MTU_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV4_MTU_DS_E, mtu);
+
+#ifdef US_DEBUG_PRINT
+		printk("IPV4_MTU: mtu %d \n", *mtu);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_ipv6_mtu_ds()
+*
+* DESCRIPTION:      Get ipv6 mtu parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  mtu - ipv6 mtu
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_ipv6_mtu_ds(uint32_t *mtu)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mtu == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mtu = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MTU_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MTU_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV6_MTU_DS_E, mtu);
+
+#ifdef US_DEBUG_PRINT
+		printk("IPV6_MTU: mtu %d \n", *mtu);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_pppoe_add_enable()
+*
+* DESCRIPTION:      Get get_pppoe_add_enable parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - pppoe_enable
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_pppoe_add_enable(tpm_init_pppoe_add_enable_t *enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TRAFFIC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TRAFFIC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_PPPOE_ENABLE_E, &val);
+		if (rc == US_RC_OK) {
+			*enable = (tpm_init_pppoe_add_enable_t) val;
+
+#ifdef US_DEBUG_PRINT
+			printk("PPPOE_ENABLE: enable %d \n", *enable);
+#endif
+		}
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_num_vlan_tags()
+*
+* DESCRIPTION:      Get num_vlan_tags parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  num_vlan_tags - vlan nmuber
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_num_vlan_tags(uint32_t *num_vlan_tags)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (num_vlan_tags == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*num_vlan_tags = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TRAFFIC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TRAFFIC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_NUM_VLAN_TAGS_E, num_vlan_tags);
+
+#ifdef US_DEBUG_PRINT
+		printk("num_vlan_tags %d \n", *num_vlan_tags);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_cpu_rx_queue(uint32_t *cpu_rx_queue)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (cpu_rx_queue == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*cpu_rx_queue = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TRAFFIC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TRAFFIC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_CPU_RX_QUEUE_E, cpu_rx_queue);
+
+#ifdef US_DEBUG_PRINT
+		printk("cpu_rx_queue %d \n", *cpu_rx_queue);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_ttl_illegal_action(uint32_t *ttl_illegal_action)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (ttl_illegal_action == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*ttl_illegal_action = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TRAFFIC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TRAFFIC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_TTL_ZERO_ACTION_E, ttl_illegal_action);
+
+#ifdef US_DEBUG_PRINT
+		printk("ttl_illegal_action %d \n", *ttl_illegal_action);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_tcp_flag_check(uint32_t *tcp_flag_check)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (tcp_flag_check == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*tcp_flag_check = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TRAFFIC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TRAFFIC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_TCP_FLAG_CHECK_E, tcp_flag_check);
+
+#ifdef US_DEBUG_PRINT
+		printk("tcp_flag_check %d \n", *tcp_flag_check);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_mc_filter_mode(tpm_mc_filter_mode_t *mc_filter_mode)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mc_filter_mode == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mc_filter_mode = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_MC_FILTER_MODE_E, mc_filter_mode);
+
+#ifdef US_DEBUG_PRINT
+		printk("mc_filter_mode %d \n", *mc_filter_mode);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_mc_per_uni_vlan_xlat(uint32_t *mc_per_uni_vlan_xlat)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mc_per_uni_vlan_xlat == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mc_per_uni_vlan_xlat = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_MC_PER_UNI_VLAN_XLAT_E, mc_per_uni_vlan_xlat);
+
+#ifdef US_DEBUG_PRINT
+		printk("mc_per_uni_vlan_xlat %d \n", *mc_per_uni_vlan_xlat);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_mc_pppoe_enable(uint32_t *mc_pppoe_enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (mc_pppoe_enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*mc_pppoe_enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_MC_PPPOE_ENABLE_E, mc_pppoe_enable);
+
+#ifdef US_DEBUG_PRINT
+		printk("mc_pppoe_enable %d \n", *mc_pppoe_enable);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_mc_queue(uint32_t *hwf_queue, uint32_t *cpu_queue)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (hwf_queue == NULL || cpu_queue == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*hwf_queue = 0;
+	*cpu_queue = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_MC_HWF_Q_E, hwf_queue);
+
+#ifdef US_DEBUG_PRINT
+		printk("mc_hwf_queue %d \n", *hwf_queue);
+#endif
+
+		if (*hwf_queue >= 8) {
+			printk(KERN_ERR "%s: Invalid mc_hwf_queue %d\n", __func__, *hwf_queue);
+			rc = US_RC_FAIL;
+		}
+
+		rc = get_int_param(xmlElement, US_XML_MC_CPU_Q_E, cpu_queue);
+
+#ifdef US_DEBUG_PRINT
+		printk("mc_cpu_queue %d \n", *cpu_queue);
+#endif
+
+		if (*cpu_queue >= 8) {
+			printk(KERN_ERR "%s: Invalid mc_cpu_queue %d\n", __func__, *cpu_queue);
+			rc = US_RC_FAIL;
+		}
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_catch_all_pkt_action(uint32_t *catch_all_pkt_action)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (catch_all_pkt_action == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*catch_all_pkt_action = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_PNC_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_TPM_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_CATCH_ALL_PKT_ACTION_E, catch_all_pkt_action);
+
+#ifdef US_DEBUG_PRINT
+		printk("catch_all_pkt_action %d \n", *catch_all_pkt_action);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_ety_dsa_enable(uint32_t *ety_dsa_enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (ety_dsa_enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*ety_dsa_enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TRAFFIC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_TRAFFIC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_ETY_DSA_ENABLE_E, ety_dsa_enable);
+
+#ifdef US_DEBUG_PRINT
+		printk("ety_dsa_enable %d \n", *ety_dsa_enable);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_ipv6_5t_enable(uint32_t *ipv6_5t_enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (ipv6_5t_enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*ipv6_5t_enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_TPM_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV6_5T_ENA_E, ipv6_5t_enable);
+
+#ifdef US_DEBUG_PRINT
+		printk("ipv6_5t_enable %d \n", *ipv6_5t_enable);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_ipv4_mc_support(uint32_t *ipv4_mc_support)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (ipv4_mc_support == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*ipv4_mc_support = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV4_MC_SUPPORT_E, ipv4_mc_support);
+
+#ifdef US_DEBUG_PRINT
+		printk("ipv4_mc_support %d \n", *ipv4_mc_support);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_ipv6_mc_support(uint32_t *ipv6_mc_support)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (ipv6_mc_support == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*ipv6_mc_support = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_MC_SETTING_E);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_MC_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_IPV6_MC_SUPPORT_E, ipv6_mc_support);
+
+#ifdef US_DEBUG_PRINT
+		printk("ipv6_mc_support %d \n", *ipv6_mc_support);
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_split_mod_enable()
+*
+* DESCRIPTION:      Get split mod enable parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  enable - split enable
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_split_mod_enable(uint32_t *split_mod_enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (split_mod_enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*split_mod_enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_MOD_E, 0, US_XML_SPLIT_MOD_SETTING_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_SPLIT_MOD_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_SPLIT_MOD_ENABLE_E, &val);
+		if (rc == US_RC_OK) {
+			*split_mod_enable = (tpm_init_split_mod_enable_t) val;
+
+#ifdef US_DEBUG_PRINT
+			printk("split_mod_enable %d \n", *split_mod_enable);
+#endif
+		}
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_split_mod_mode(tpm_init_split_mod_mode_t *split_mod_mode)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (split_mod_mode == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*split_mod_mode = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TPM_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_SPLIT_MOD_MODE_E, &val);
+		if (rc == US_RC_OK) {
+			*split_mod_mode = (tpm_init_split_mod_mode_t)val;
+
+#ifdef US_DEBUG_PRINT
+			printk("split_mod_mode %d \n", *split_mod_mode);
+#endif
+		}
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+static int get_pbit_param(ezxml_t xml, char *name, uint8_t *pbit, uint32_t *pbit_num)
+{
+	ezxml_t xmlElement;
+	char tmp[30];
+	uint8_t len,i,j,k;
+
+	memset(tmp, '\0', 30);
+
+	xmlElement = ezxml_child(xml, name);
+	if (xmlElement == NULL)
+		return US_RC_NOT_FOUND;
+	else if (xmlElement->txt == NULL) {
+		printk(KERN_ERR "NULL value for %s in XML config. file\n", name);
+		return US_RC_NOT_FOUND;
+	}
+	len = strlen(xmlElement->txt);
+	for (i = 0, j = 0, k = 0; i < len;) {
+		while((xmlElement->txt[i] != ',') && (i < len)) {
+			if (xmlElement->txt[i] != ' ') {
+				tmp[k] = xmlElement->txt[i];
+				k++;
+			}
+			i++;
+		}
+		pbit[j] = get_dig_number(tmp);
+		memset(tmp, '\0', 30);
+		j++;
+		i++;
+		k = 0;
+	}
+	/*get valid pbit num*/
+	*pbit_num = j;
+
+	return US_RC_OK;
+}
+
+/*******************************************************************************
+* get_split_mot_p_bits()
+*
+* DESCRIPTION:      Get split mod p_bits supported parameters from XML configuration file
+*
+* INPUTS:
+*
+* OUTPUTS:  p_bits[] - p_bit supported
+*	    p_bit_num - number of valid p_bit
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_split_mot_p_bits(uint8_t *p_bits, uint32_t *p_bit_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint8_t i = 0;
+
+	if (p_bits == NULL || p_bit_num == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	memset(p_bits,0xFF,8);
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_MOD_E, 0, US_XML_SPLIT_MOD_SETTING_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_SPLIT_MOD_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_pbit_param(xmlElement, US_XML_SPLIT_MOD_P_BITS_E, &p_bits[0], p_bit_num);
+
+#ifdef US_DEBUG_PRINT
+		printk("split_mod_p_bit: ");
+		for (i = 0; i < 8; i++) {
+			if (p_bits[i] != 0xFF)
+				printk("%d ", p_bits[i]);
+		}
+		printk("\n");
+#endif
+	}
+
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+/*******************************************************************************
+* get_split_mod_vlan_num()
+*
+* DESCRIPTION:      Get vlan number that needs split pbit and vid modification
+*
+* INPUTS:
+*
+* OUTPUTS:  split_vlan_num - vlan nmuber
+*
+* RETURNS:  US_RC_OK, US_RC_FAIL or US_RC_NOT_FOUND
+*
+*******************************************************************************/
+int get_split_mod_vlan_num(uint32_t *split_vlan_num)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+
+	if (split_vlan_num == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*split_vlan_num = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, 0, US_XML_TPM_MOD_E, 0, US_XML_SPLIT_MOD_SETTING_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_SPLIT_MOD_SETTING_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_SPLIT_MOD_VLAN_NUM_E, split_vlan_num);
+
+#ifdef US_DEBUG_PRINT
+		printk("split_vlan_num %d \n", *split_vlan_num);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_ctc_cm_enable(uint32_t *ctc_cm_enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (ctc_cm_enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*ctc_cm_enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TPM_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_CTC_CNM_ENA_E, &val);
+		if (rc == US_RC_OK) {
+			*ctc_cm_enable = (tpm_init_ctc_cm_enable_t)val;
+
+#ifdef US_DEBUG_PRINT
+			printk("ctc_cnm_enable %d \n", *ctc_cm_enable);
+#endif
+		}
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+int get_ctc_cm_ipv6_parse_window(uint32_t *ctc_cm_ipv6_parse_window)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (ctc_cm_ipv6_parse_window == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*ctc_cm_ipv6_parse_window = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TPM_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_CTC_CNM_IPv6_PARSE_WIN_E, &val);
+		if (rc == US_RC_OK) {
+			*ctc_cm_ipv6_parse_window = val;
+
+#ifdef US_DEBUG_PRINT
+			printk("ipv6_parse_window_t %d \n", *ctc_cm_ipv6_parse_window);
+#endif
+		}
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+int get_pnc_mac_learn_enable(uint32_t *pnc_mac_learn_enable)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (pnc_mac_learn_enable == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	*pnc_mac_learn_enable = 0;
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_get(xmlHead, US_XML_TPM_E, -1);
+	if (xmlElement == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n",
+			US_XML_TPM_E, g_pstr_xml_cfg_file);
+#endif
+		rc = US_RC_NOT_FOUND;
+	} else {
+		rc = get_int_param(xmlElement, US_XML_PNC_MAC_LEARN_ENA_E, &val);
+		if (rc == US_RC_OK) {
+			*pnc_mac_learn_enable = (tpm_init_pnc_mac_learn_enable_t)val;
+
+#ifdef US_DEBUG_PRINT
+			printk("pnc_mac_learn_enable %d \n", *pnc_mac_learn_enable);
+#endif
+		}
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+int get_switch_init_params(uint32_t *switch_init)
+{
+	ezxml_t xmlHead;
+	ezxml_t xmlElement;
+	int rc = US_RC_OK;
+	uint32_t val;
+
+	if (switch_init == NULL) {
+#ifdef US_DEBUG_PRINT
+		printk(KERN_ERR "%s: NULL pointer\n", __func__);
+#endif
+		return US_RC_FAIL;
+	}
+
+	xmlHead = get_xml_head_ptr(g_pstr_xml_cfg_file);
+
+	if (xmlHead == NULL)
+		return US_RC_FAIL;
+
+	xmlElement = ezxml_child(xmlHead, US_XML_TPM_E);
+	if (xmlElement == NULL) {
+		printk(KERN_ERR "Failed to find %s in XML config. file %s\n", US_XML_TPM_E, g_pstr_xml_cfg_file);
+		rc = US_RC_NOT_FOUND;
+	} else
+		rc = get_int_param(xmlElement, US_XML_SWITCH_INIT_E, &val);
+
+	if (rc == US_RC_OK) {
+		*switch_init = val;
+
+#ifdef US_DEBUG_PRINT
+		printk("switch_init = %d\n", *switch_init);
+#endif
+	}
+	/*ezxml_free(xmlHead); */
+	return rc;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.h
new file mode 100755
index 0000000..ac14460
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/core/tpm_xml_params.h
@@ -0,0 +1,378 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+#ifndef _TPM_XML_PARAMS_H_
+#define _TPM_XML_PARAMS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define US_XML_PON_SN_LEN          (8)
+#define US_XML_PON_PASSWD_LEN      (10)
+
+#define US_RC_OK           0
+#define US_RC_FAIL         1
+#define US_RC_NOT_FOUND    2
+
+typedef enum {
+	NONE_SW_APP = 0,
+	EPON_SW_APP,
+	GPON_SW_APP,
+	GBE_SW_APP,
+	P2P_SW_APP,
+
+	MAX_SW_APP
+} us_sw_app_t;
+
+typedef enum {
+	US_DISABLED = 0,
+	US_ENABLED
+} us_enabled_t;
+
+typedef enum {
+	US_OFF = 0,
+	US_ON
+} us_state_t;
+
+typedef enum {
+	ONU_PON_DISCONNECT = 0,
+	ONU_PON_CONNECT
+} PON_connect_type_t;
+
+typedef enum {
+	PON_XML_DEF_PAR_SERIAL_NUM         = 0,
+	PON_XML_DEF_PAR_PASSWORD           = 1,
+	PON_XML_DEF_PAR_DIS_SERIAL_NUM     = 2,
+	PON_XML_DEF_PARAM_CLEAR_GEM        = 3,
+	PON_XML_DEF_PARAM_CLEAR_TCONT      = 4,
+	PON_XML_DEF_PARAM_SERIAL_NUM_SRC   = 5,
+	PON_XML_DEF_PARAM_XVR_POLARITY     = 6,
+	PON_XML_DEF_PARAM_DG_POLARITY      = 7,
+	PON_XML_DEF_PARAM_RESTORE_GEM      = 8,
+	PON_XML_DEF_PARAM_MAX
+
+} PON_XML_DEF_PARAMS;
+
+#define US_RC_OK           0
+#define US_RC_FAIL         1
+#define US_RC_NOT_FOUND    2
+
+#define US_XML_CFG_FILE            "/etc/xml_params/tpm_xml_cfg_file.xml"
+#define US_XML_CFG_FILE_OMCI       "/etc/xml_params/omci_xml_cfg_file.xml"
+#define US_XML_CFG_FILE_PON        "/etc/xml_params/pon_xml_cfg_file.xml"
+#define US_XML_CFG_FILE_GLOBAL     "/etc/xml_params/pon_type_xml_cfg_file.xml"
+
+#define US_DEBUG_PRINT
+
+#define US_XML_PON_E               "PON"
+#define US_XML_PON_TYPE_E          "WAN_type"
+#define US_XML_PON_TYPE_FORCE_E    "WAN_type_force"
+#define US_XML_PON_SN_E            "PON_serial_num"
+#define US_XML_PON_PASSWD_E        "PON_passwd"
+#define US_XML_PON_DIS_SN_E        "PON_dis_sn"
+#define US_XML_PON_GEM_RST_E       "PON_gem_reset"
+#define US_XML_PON_TCONT_RST_E     "PON_tcont_reset"
+#define US_XML_PON_SN_SRC_E        "PON_serial_src"
+#define US_XML_PON_DG_POL_E        "PON_DG_polarity"
+#define US_XML_PON_XVR_POL_E       "PON_XVR_polarity"
+#define US_XML_PON_GEM_RESTOR_E    "PON_gem_restore"
+
+#define US_XML_EPON_E               "EPON"
+#define US_XML_EPON_CONNECT_E       "EPON_connect_tpm"
+#define US_XML_EPON_DG_POL_E        "EPON_DG_polarity"
+#define US_XML_EPON_XVR_POL_E       "EPON_XVR_polarity"
+#define US_XML_EPON_OAM_RXQ_E       "EPON_OAM_RX_queue"
+
+#define US_XML_OMCI_E              "OMCI"
+#define US_XML_OMCI_ETY_E          "OMCI_ETY"
+
+#define US_XML_IGMP_SNOOP_E        "igmp_snoop"
+#define US_XML_IGMP_SNOOP_ALL_E    "snoop_all"
+#define US_XML_ENABLED_E           "enabled"
+#define US_XML_IGMP_CPU_Q_E        "igmp_cpu_rx_queue"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_0           "igmp_frwrd_mode_uni0"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_1           "igmp_frwrd_mode_uni1"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_2           "igmp_frwrd_mode_uni2"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_3           "igmp_frwrd_mode_uni3"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_4           "igmp_frwrd_mode_uni4"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_5           "igmp_frwrd_mode_uni5"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_6           "igmp_frwrd_mode_uni6"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_7           "igmp_frwrd_mode_uni7"
+#define US_XML_IGMP_PKT_FRWD_MODE_UNI_VIRT        "igmp_frwrd_mode_uni_virt"
+#define US_XML_IGMP_PKT_FRWD_MODE_WAN             "igmp_frwrd_mode_wan"
+
+#define US_XML_PORT_INIT_E         "port_init"
+#define US_XML_DEBUG_PORT_E        "debug_port"
+#define US_XML_INT_PORT_E          "int_port"
+
+#define US_XML_ETH_PORT_PARAMS_E   "Ethernet_parameters"
+#define US_XML_ETH_PORT_E          "Ethernet"
+#define US_XML_ETH_CHIP_CONN_ATTR  "chip_connect"
+#define US_XML_ETH_INT_CONN_ATTR   "int_connect"
+#define US_XML_ETH_SW_PORT_ATTR    "switch_ports"
+#define US_XML_GMAC_PORTS_E        "gmac_ports"
+#define US_XML_ETH_ADMIN_ATTR      "admin_state"
+#define US_XML_ETH_SPEED_ATTR      "speed"
+#define US_XML_ETH_DUPLEX_ATTR     "duplex"
+#define US_XML_ETH_PORT_SRC_ATTR   "src_port"
+#define US_XML_ETH_PORT_CHIPCON_ATTR "chip_conn"
+#define US_XML_ETH_GMAC_CONN_ATTR  "conn"
+#define US_XML_ETH_PORT_INTCON_ATTR "intr_conn"
+#define US_XML_ETH_CMPLX_CONFIG_E  "eth_complex_config"
+#define US_XML_WAN_E		    "WAN"
+#define US_XML_BACKUP_WAN_E        "backup_wan"
+#define US_XML_VIRTUAL_UNI_E       "virtual_uni"
+
+#define US_XML_ETH_PROFILE_E       "profile"
+
+#define US_XML_GMAC_CONFIG_E       "gmac_config"
+#define US_XML_GMAC_CONN_E         "pon_config"
+#define US_XML_TCONT_LLID_E        "num_tcont_llid"
+#define US_XML_GMAC_MH_ENA_E       "gmac_mh_en"
+#define US_XML_GMAC_0_MH_ENA_E     "gmac0_mh_en"
+#define US_XML_GMAC_1_MH_ENA_E     "gmac1_mh_en"
+
+#define US_XML_GMAC_BM_BUF_E       "gmac_bm_buffers"
+#define US_XML_LARGE_POOL_BUF_ATTR "large_pkt_pool_bufs"
+#define US_XML_SHORT_POOL_BUF_ATTR "small_pkt_pool_bufs"
+
+#define US_XML_GMAC_RXQUEUES_E     "gmac_rx_queues"
+
+#define US_XML_TX_MOD_PARAMS_E     "tx_module_parameters"
+#define US_XML_TX_MOD_E            "tx_mod"
+#define US_XML_QUEUE_MAP_E         "queue_map"
+#define US_XML_QUEUE_E             "queue"
+#define US_XML_QUEUE_SHED_ATTR     "sched_method"
+#define US_XML_QUEUE_OWNER_ATTR    "owner"
+#define US_XML_QUEUE_OW_Q_NUM_ATTR "owner_q_num"
+#define US_XML_QUEUE_WEIGHT_ATTR   "weight"
+
+#define US_XML_FC_PARAMS_E         "flow_control"
+#define US_XML_Q_SAMPLE_FREQ_E     "queue_sample_freq"
+#define US_XML_THRESH_HIGH_E       "thresh_high"
+#define US_XML_THRESH_LOW_E        "thresh_low"
+#define US_XML_TGT_PORT_E          "tgt_port"
+#define US_XML_TX_PORT_E           "tx_port"
+#define US_XML_TX_Q_E              "tx_queue"
+
+
+#define US_XML_TPM_E               "TPM"
+#define US_XML_DS_MH_SET_E         "ds_mh_set"
+#define US_XML_VALID_EN_E          "validation_enable"
+#define US_XML_CFG_PNC_PARSER      "pnc_config"
+#define US_XML_CFG_CPU_LOOPBACK    "cpu_wan_egr_loopback"
+#define US_XML_TRACE_DEBUG_info    "trace_debug_info"
+#define US_XML_IPV6_5T_ENA_E       "ipv6_5t_enable"
+#define US_XML_CTC_CNM_ENA_E       "ctc_cnm_enable"
+#define US_XML_WIFI_ENABLED        "gmac1_virt_uni"
+#define US_XML_IPV4_MC_SUPPORT_E   "ipv4_mc_support"
+#define US_XML_IPV6_MC_SUPPORT_E   "ipv6_mc_support"
+#define US_XML_CTC_CNM_IPv6_PARSE_WIN_E       "ctc_cnm_ipv6_parsing_window"
+#define US_XML_PNC_MAC_LEARN_ENA_E "pnc_mac_learn_enable"
+#define US_XML_SWITCH_INIT_E       "switch_init"
+
+/*#define US_XML_WIFI_PORT           "Vitual_UNI_GMAC1_port"*/
+
+#if 0
+#define US_XML_DEF_V1_TPID         "vlan1_tpid"
+#define US_XML_DEF_V2_TPID         "vlan2_tpid"
+#endif
+#define US_XML_TPM_VLAN_FILTER_TPID_E     "vlan_filter_tpid"
+#define US_XML_TPM_FILTER_TPID_E          "filter_tpid"
+
+
+#define US_XML_TPM_PNC_E                  "PnC"
+#define US_XML_TPM_PNC_RANGE_PARAMS_E     "range_parameters"
+#define US_XML_TPM_PNC_RANGE_E            "range"
+#define US_XML_TPM_CNTR_GRP_ATTR          "cntr_grp"
+#define US_XML_TPM_LU_MASK_ATTR           "lu_mask"
+#define US_XML_TPM_MIN_RES_LVL_ATTR       "min_reset_level"
+#define US_XML_TPM_MOD_VLAN_TPID_E        "vlan_mod_tpid"
+#define US_XML_TPM_MOD_TPID_E             "mod_tpid"
+#define US_XML_TPM_MOD_E                  "modification"
+#define US_XML_TPM_MOD_UDP_CKS_USE_INIT_E "udp_checksum_use_init"
+#define US_XML_TPM_MOD_UDP_CKS_CALC_E     "udp_checksum_calc"
+#define US_XML_SPLIT_MOD_SETTING_E        "split_mod"
+#define US_XML_SPLIT_MOD_ENABLE_E         "enable"
+#define US_XML_SPLIT_MOD_P_BITS_E         "p_bits"
+#define US_XML_SPLIT_MOD_VLAN_NUM_E       "vlan_num"
+#define US_XML_SPLIT_MOD_MODE_E           "split_mod_mode"
+
+
+#define US_XML_TPM_MOD_CHAIN_PARAM_E     "chain_parameters"
+#define US_XML_TPM_MOD_CHAIN_E           "chain"
+#define US_XML_TPM_CHAIN_ID_ATTR         "id"
+#define US_XML_TPM_CHAIN_TYPE_ATTR       "type"
+#define US_XML_TPM_CHAIN_NUM_ATTR        "num"
+
+#define US_XML_ID_ATTR             "id"
+#define US_XML_GMAC_E              "gmac"
+#define US_XML_PORT_E              "port"
+#define US_XML_SIZE_ATTR           "size"
+#define US_XML_NUM_ATTR            "num"
+#define US_XML_TYPE_ATTR           "type"
+#define US_XML_VALID_ATTR          "valid"
+
+
+#define US_XML_MTU_SETTING_E          "mtu_setting"
+
+#define US_XML_MTU_SETTING_ENABLE_E   "mtu_setting_enabled"
+#define US_XML_IPV4_MTU_US_E          "ipv4_mtu_us"
+#define US_XML_IPV4_PPPOE_MTU_US_E    "ipv4_pppoe_mtu_us"
+#define US_XML_IPV6_MTU_US_E          "ipv6_mtu_us"
+#define US_XML_IPV6_PPPOE_MTU_US_E    "ipv6_pppoe_mtu_us"
+#define US_XML_IPV4_MTU_DS_E          "ipv4_mtu_ds"
+#define US_XML_IPV6_MTU_DS_E          "ipv6_mtu_ds"
+
+#define US_XML_TRAFFIC_SETTING_E      "traffic_setting"
+#define US_XML_PPPOE_ENABLE_E         "pppoe_add_enable"
+#define US_XML_NUM_VLAN_TAGS_E        "num_vlan_tags"
+#define US_XML_CPU_RX_QUEUE_E         "cpu_trap_rx_queue"
+#define US_XML_TTL_ZERO_ACTION_E      "ttl_illegal_action"
+#define US_XML_TCP_FLAG_CHECK_E       "tcp_flag_check"
+#define US_XML_ETY_DSA_ENABLE_E       "ety_dsa_enable"
+
+
+#define US_XML_MC_SETTING_E                  "multicast"
+#define US_XML_MC_FILTER_MODE_E              "mc_filter_mode"
+#define US_XML_MC_PER_UNI_VLAN_XLAT_E        "mc_per_uni_vlan_xlat"
+#define US_XML_MC_PPPOE_ENABLE_E             "mc_pppoe_enable"
+#define US_XML_MC_HWF_Q_E                    "mc_hwf_queue"
+#define US_XML_MC_CPU_Q_E                    "mc_cpu_queue"
+#define US_XML_CATCH_ALL_PKT_ACTION_E        "catch_all_pkt_action"
+
+/*******************************************************************************
+*                             Configuration functions
+*******************************************************************************/
+int get_pon_type_param(tpm_init_pon_type_t *pon_type);
+int get_omci_etype_param(uint32_t *ety);
+int get_debug_port_params(uint32_t *valid, uint32_t *num);
+int get_igmp_snoop_params_enable(uint32_t *enable);
+int get_igmp_snoop_params_cpu_queue(uint32_t *que);
+int get_igmp_snoop_params_port_frwd_mode(uint32_t *mode, tpm_src_port_type_t port);
+int get_gmac_conn_params(uint32_t *num_tcont_llid);
+int get_gmac_mh_en_params(uint32_t *gmac0_mh_en, uint32_t *gmac1_mh_en);
+int get_eth_cmplx_profile_params(tpm_eth_complex_profile_t *eth_cmplx_profile);
+int get_gmac_port_conf_params(tpm_init_gmac_conn_conf_t *gmac_port_conf_bufs, int max_gmac_port_num);
+int get_eth_port_conf_params(tpm_init_eth_port_conf_t *eth_port_bufs, int max_eth_port_num);
+int get_backup_wan_params(uint32_t *backup_wan);
+
+int get_gmac_pool_bufs_params(tpm_init_gmac_bufs_t *gmac_bufs, int max_gmacs_num);
+int get_trace_debug_info_param(uint32_t *trace_debug_info);
+int get_validation_enabled_config_params(tpm_init_tpm_validation_t *validEn);
+int get_vitual_uni_enable_params(uint32_t *enable);
+#if 0
+int get_default_vlan_tpid_params(uint16_t *v1_tpid, uint16_t *v2_tpid);
+#endif
+int get_default_vlan_tpid_params(uint32_t *opt_num, tpm_init_tpid_comb_t *opt);
+int get_fc_def_params(tpm_init_fc_params_t *port_fc_conf);
+int get_gmac_rxq_params(tpm_init_gmac_rx_t *gmac_rx, int max_gmacs_num, int max_rx_queues_num);
+int get_gmac_tx_params(tpm_init_gmac_tx_t *gmac_tx, int max_tx_ports_num, int max_tx_queues_num);
+int get_pnc_range_params(tpm_init_pnc_range_t *pnc_range, int max_pnc_ranges_num);
+int get_ds_mh_config_params(tpm_init_mh_src_t *dsMhConf);
+int get_vlan_mod_vlan_tpid_params(uint32_t *mod_vlan_tpid, int mod_vlan_tpid_reg_num);
+int get_modification_params(tpm_init_mod_params_t *config);
+int get_chain_config_params(tpm_init_mod_chain_t *mod_chain);
+int get_cfg_pnc_parse_param(tpm_init_cfg_pnc_parse_t *cfgPncParse);
+int get_cpu_loopback_param(tpm_init_cpu_loopback_t *cpuLoopback);
+
+void free_xml_head_ptr(void);
+
+/* jinghua add for MTU setting */
+
+int get_ipv4_mtu_us(uint32_t *mtu);
+int get_ipv4_pppoe_mtu_us(uint32_t *mtu);
+int get_ipv6_mtu_us(uint32_t *mtu);
+int get_ipv6_pppoe_mtu_us(uint32_t *mtu);
+int get_ipv4_mtu_ds(uint32_t *mtu);
+int get_ipv6_mtu_ds(uint32_t *mtu);
+int get_pppoe_add_enable(tpm_init_pppoe_add_enable_t *enable);
+int get_num_vlan_tags(uint32_t *num_vlan_tags);
+int get_mtu_enable(tpm_init_mtu_setting_enable_t *enable);
+int get_cpu_rx_queue(uint32_t *cpu_rx_queue);
+int get_ttl_illegal_action(uint32_t *ttl_illegal_action);
+int get_tcp_flag_check(uint32_t *tcp_flag_check);
+
+int get_mc_filter_mode(tpm_mc_filter_mode_t *mc_filter_mode);
+int get_mc_per_uni_vlan_xlat(uint32_t *mc_per_uni_vlan_xlat);
+int get_mc_pppoe_enable(uint32_t *mc_pppoe_enable);
+int get_mc_queue(uint32_t *hwf_queue, uint32_t *cpu_queue);
+int get_catch_all_pkt_action(uint32_t *catch_all_pkt_action);
+int get_ety_dsa_enable(uint32_t *ety_dsa_enable);
+int get_ipv6_5t_enable(uint32_t *ipv6_5t_enable);
+int get_ipv4_mc_support(uint32_t *ipv4_mc_support);
+int get_ipv6_mc_support(uint32_t *ipv6_mc_support);
+int get_split_mod_enable(uint32_t *split_mod_enable);
+int get_split_mot_p_bits(uint8_t *p_bits, uint32_t *p_bit_num);
+int get_split_mod_vlan_num(uint32_t *split_vlan_num);
+int get_split_mod_mode(tpm_init_split_mod_mode_t *split_mod_mode);
+int get_ctc_cm_enable(uint32_t *ctc_cm_enable);
+int get_ctc_cm_ipv6_parse_window(uint32_t *ctc_cm_ipv6_parse_window);
+int get_pnc_mac_learn_enable(uint32_t *pnc_mac_learn_enable);
+int get_switch_init_params(uint32_t *switch_init);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* _PARAMS_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_bring_up.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_bring_up.c
new file mode 100755
index 0000000..b87da74
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_bring_up.c
@@ -0,0 +1,135 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : tpm_bring_up.c                                             **
+**                                                                           **
+**  DESCRIPTION : This file implements TPM BringUp handling                  **
+*******************************************************************************
+*                                                                             *                              
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   11Aug10  Yuval Caduri   created                                         *  
+* =========================================================================== *      
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/                                               
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+
+static int __init mv_tpm_module_init(void)
+{
+  tpm_module_init();
+
+  /* create mng interface */
+  tpm_module_mng_if_create();
+
+  /* create user interface */
+  tpm_module_usr_if_create();
+
+  printk(KERN_INFO "= TPM Module Init ended successfully =\n");
+
+  return(0);
+}
+
+static void __exit mv_tpm_module_exit(void)
+{
+  printk(KERN_INFO "= TPM Module Exit =\n");
+
+  /* release allocated memory */
+  /*  - TODO - */
+
+  /* release rtos resources */
+  /*  - TODO - */
+
+  /* release mng interface */
+  tpm_module_mng_if_release();
+}
+
+module_init(mv_tpm_module_init);
+module_exit(mv_tpm_module_exit);
+
+MODULE_AUTHOR("Yuval Caduri");
+MODULE_DESCRIPTION("TPM Driver for Marvell MV65xxx");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.c
new file mode 100755
index 0000000..e6ad713
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.c
@@ -0,0 +1,3640 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+        this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : tpm_mng_if.c                                               **
+**                                                                           **
+**  DESCRIPTION : This file implements ONU TPM Management Interface          **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   11Aug10  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include <linux/thread_info.h>
+#include <linux/version.h>
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_mempool.h"
+
+
+
+
+/* Local Structures
+------------------------------------------------------------------------------*/
+/* Mempools used by ioctl, 3 size: Small, Medium Large and Huge */
+typedef struct
+{
+    tpm_common_mempool_t *mpool_s;
+    tpm_common_mempool_t *mpool_m;
+    tpm_common_mempool_t *mpool_l;
+    tpm_common_mempool_t *mpool_h;
+} tpm_ioctl_mpools_t;
+
+#define MPOOL_S_MAX_BUFF_SIZE   300
+#define MPOOL_M_MAX_BUFF_SIZE  1024
+#define MPOOL_L_MAX_BUFF_SIZE  2048
+#define MPOOL_H_MAX_BUFF_SIZE  4096
+
+/* TPM Char Device Structure */
+/* ========================= */
+typedef struct
+{
+  tpm_ioctl_admin_t           tpm_ioctl_admin;
+  tpm_ioctl_add_acl_rule_t    tpm_ioctl_add_acl_rule;
+  tpm_ioctl_del_acl_rule_t    tpm_ioctl_del_acl_rule;
+  tpm_ioctl_ctrl_acl_rule_t   tpm_ioctl_ctrl_acl_rule;
+  tpm_ioctl_mc_rule_t         tpm_ioctl_mc_rule;
+  tpm_ioctl_mng_ch_t          tpm_ioctl_mng_ch;
+  tpm_ioctl_sw_mac_security_t tpm_ioctl_sw_mac_security;
+  tpm_ioctl_sw_vlan_filter_t  tpm_ioctl_sw_vlan_filter;
+  tpm_ioctl_sw_tm_t           tpm_ioctl_sw_tm;
+  tpm_ioctl_tm_tm_t           tpm_ioctl_tm_tm;
+  tpm_ioctl_igmp_t            tpm_ioctl_igmp;
+  tpm_ioctl_mib_reset_t       tpm_ioctl_mib_reset;
+  tpm_ioctl_swport_pm_3_t     apm_ioctl_pm_ethernet_3;
+  tpm_ioctl_rx_igmp_t         tpm_ioctl_rx_igmp;
+  tpm_ioctl_tx_igmp_t         tpm_ioctl_tx_igmp;
+  tpm_ioctl_cpu_lpbk_t        tpm_ioctl_cpu_lpbk;
+  tpm_ioctl_age_count_t       tpm_ioctl_age_count;
+  tpm_ioctl_mc_vid_t          tpm_ioctl_mc_vid;
+  struct cdev  cdev;
+}tpm_module_cdev_t;
+
+
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+extern GT_QD_DEV *qd_dev;
+extern int32_t module_tpmSetup(tpm_setup_t *tpm_initp);
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+struct semaphore    tpm_sfs_2_ioctl_sem;
+tpm_ioctl_mng_t     tpm_sfs_2_ioctl_command;
+#endif
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+static int        deviceOpen = 0;
+tpm_module_cdev_t tpm_dev;
+static tpm_ioctl_mpools_t  tpm_ioctl_mpools= {0,0,0,0};
+
+/* udev class's */
+struct class  *tpm_udev_class;
+struct device *tpm_udev_dev;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+
+/*******************************************************************************
+**
+**  mv_tpm_cdev_ioctl
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function execute IO commands
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**               unsigned int cmd
+**               unsigned long arg
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+int mv_tpm_cdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+                      unsigned long arg)
+{
+
+  tpm_init_t                    *tpm_initp      = NULL;
+  void                          *mpool_s_buff   = NULL;
+  void                          *mpool_m_buff   = NULL;
+  void                          *mpool_l_buff   = NULL;
+  void                          *mpool_h_buff   = NULL;
+  tpm_ioctl_mib_reset_t         tpm_mib_reset_param;
+  GT_STATUS                     rc = GT_OK;
+  tpm_error_code_t              rcode;
+  int                           ret = -EINVAL;
+
+
+  //onuTpmIrqLock();
+
+  /* Init Struct created by malloc, due to kernel_stack_size limit reached */
+  /* TODO: Seperate init_api's into seperate ioctl */
+
+  switch(cmd)
+  {
+      /* =========================== */
+      /* ====== Init Section ======= */
+      /* =========================== */
+      case MV_TPM_IOCTL_INIT_SECTION:
+          tpm_initp = (tpm_init_t *) kmalloc(sizeof(tpm_init_t), GFP_USER);
+          if (tpm_initp == NULL)
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) kmalloc failed\n", __FUNCTION__, __LINE__);
+              ret = -ENOMEM;
+              goto ioctlErr;
+          }
+
+          if(copy_from_user(tpm_initp, (tpm_init_t*)arg, sizeof(tpm_init_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          rcode = tpm_module_start(tpm_initp);
+          if(rcode != TPM_OK)
+            goto ioctlErr;
+
+          ret=0;
+          break;
+
+      case MV_TPM_IOCTL_SETUP_SECTION:
+      {
+          tpm_setup_t *tpm_setup = (tpm_setup_t *)tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_setup == NULL)
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+              ret = -ENOMEM;
+              goto ioctlErr;
+          }
+          mpool_s_buff = tpm_setup;
+
+          if(copy_from_user(tpm_setup, (tpm_setup_t*)arg, sizeof(tpm_setup_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+          rcode = module_tpmSetup(tpm_setup);
+          if(rcode != TPM_OK)
+            goto ioctlErr;
+          ret=0;
+          break;
+      }
+
+      /* =========================== */
+      /* ====== Admin Section ====== */
+      /* =========================== */
+      case MV_TPM_IOCTL_ADMIN_SECTION:
+      {
+          tpm_ioctl_admin_t *tpm_admin = (tpm_ioctl_admin_t *)tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_admin == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_admin;
+
+          if(copy_from_user(tpm_admin, (tpm_ioctl_admin_t*)arg, sizeof(tpm_ioctl_admin_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_admin->amdin_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_CRT_OWNER =============== */
+              case MV_TPM_IOCTL_CRT_OWNER:
+
+                  rcode = tpm_create_ownerid(&(tpm_admin->owner_id));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_admin_t*)arg, tpm_admin, sizeof(tpm_ioctl_admin_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+
+              /* ====== MV_TPM_IOCTL_REQ_API_G_OWNER ========= */
+              case MV_TPM_IOCTL_REQ_API_G_OWNER:
+
+                  tpm_admin->api_ownership_error = tpm_request_api_ownership(tpm_admin->owner_id,
+                                                                             tpm_admin->api_type);
+
+                  if(copy_to_user((tpm_ioctl_admin_t*)arg, tpm_admin, sizeof(tpm_ioctl_admin_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+
+              /* ====== MV_TPM_IOCTL_GET_API_G_OWNER ========= */
+              case MV_TPM_IOCTL_GET_API_G_OWNER:
+
+                  tpm_admin->api_ownership_error = tpm_request_api_ownership(tpm_admin->owner_id,
+                                                                             tpm_admin->api_type);
+
+                  if(copy_to_user((tpm_ioctl_admin_t*)arg, tpm_admin, sizeof(tpm_ioctl_admin_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_DEL_SECTION ========= */
+              case MV_TPM_IOCTL_DEL_SECTION:
+
+                  rcode = tpm_erase_section(tpm_admin->owner_id,
+                                            tpm_admin->api_type);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_GET_SECTION_SIZE ========= */
+              case MV_TPM_IOCTL_GET_SECTION_SIZE:
+
+                  rcode = tpm_get_section_free_size(tpm_admin->api_type,
+                                                    &(tpm_admin->section_size));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_admin_t*)arg, tpm_admin, sizeof(tpm_ioctl_admin_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== ACL Rule Add Section ====== */
+      /* ================================== */
+      case MV_TPM_IOCTL_ADD_ACL_SECTION:
+      {
+          tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = (tpm_ioctl_add_acl_rule_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+
+          if (tpm_add_acl_rule == NULL)
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+              ret = -ENOMEM;
+              goto ioctlErr;
+          }
+          mpool_s_buff = tpm_add_acl_rule;
+          if(copy_from_user(tpm_add_acl_rule, (tpm_ioctl_add_acl_rule_t*)arg, sizeof(tpm_ioctl_add_acl_rule_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_add_acl_rule->add_acl_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_ADD_L2_ACL_RULE ========= */
+              case MV_TPM_IOCTL_ADD_L2_ACL_RULE:
+
+                  rcode = tpm_add_l2_rule( tpm_add_acl_rule->owner_id,
+                                           tpm_add_acl_rule->src_port,
+                                           tpm_add_acl_rule->rule_num,
+                                          &(tpm_add_acl_rule->rule_idx),
+                                           tpm_add_acl_rule->parse_rule_bm,
+                                           tpm_add_acl_rule->l2_acl_rule.parse_flags_bm,
+                                          &(tpm_add_acl_rule->l2_acl_rule.l2_key),
+                                          &(tpm_add_acl_rule->l2_acl_rule.pkt_frwd),
+                                          &(tpm_add_acl_rule->l2_acl_rule.pkt_mod),
+                                           tpm_add_acl_rule->l2_acl_rule.pkt_mod_bm,
+                                          &(tpm_add_acl_rule->l2_acl_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_MAC_LEARN_ACL_RULE ========= */
+              case MV_TPM_IOCTL_ADD_MAC_LEARN_ACL_RULE:
+                  rcode = tpm_add_mac_learn_rule(tpm_add_acl_rule->owner_id,
+                                                 &(tpm_add_acl_rule->l2_acl_rule.l2_key));
+                  if(rcode != TPM_OK)
+                      goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                      printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                      goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SET_MAC_LEARN_DEFAULT_ACTION ========= */
+              case MV_TPM_IOCTL_SET_MAC_LEARN_DEFAULT_ACTION:
+                  rcode = tpm_mac_learn_default_rule_act_set(tpm_add_acl_rule->owner_id,
+                                                             tpm_add_acl_rule->l2_acl_rule.mac_conf);
+                  if(rcode != TPM_OK)
+                      goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                      printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                      goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_L3_ACL_RULE ========= */
+              case MV_TPM_IOCTL_ADD_L3_ACL_RULE:
+
+                  rcode = tpm_add_l3_type_rule(  tpm_add_acl_rule->owner_id,
+                                                 tpm_add_acl_rule->src_port,
+                                                 tpm_add_acl_rule->rule_num,
+                                                &(tpm_add_acl_rule->rule_idx),
+                                                 tpm_add_acl_rule->parse_rule_bm,
+                                                 tpm_add_acl_rule->l3_acl_rule.parse_flags_bm,
+                                                &(tpm_add_acl_rule->l3_acl_rule.l3_key),
+                                                &(tpm_add_acl_rule->l3_acl_rule.pkt_frwd),
+                                                &(tpm_add_acl_rule->l3_acl_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_IPv4_ACL_RULE ========= */
+              case MV_TPM_IOCTL_ADD_IPv4_ACL_RULE:
+
+                  rcode = tpm_add_ipv4_rule(  tpm_add_acl_rule->owner_id,
+                                              tpm_add_acl_rule->src_port,
+                                              tpm_add_acl_rule->rule_num,
+                                             &(tpm_add_acl_rule->rule_idx),
+                                              tpm_add_acl_rule->parse_rule_bm,
+                                              tpm_add_acl_rule->ipv4_acl_rule.parse_flags_bm,
+                                             &(tpm_add_acl_rule->ipv4_acl_rule.ipv4_key),
+                                             &(tpm_add_acl_rule->ipv4_acl_rule.pkt_frwd),
+                                             &(tpm_add_acl_rule->ipv4_acl_rule.pkt_mod),
+                                              tpm_add_acl_rule->ipv4_acl_rule.pkt_mod_bm,
+                                             &(tpm_add_acl_rule->ipv4_acl_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_IPv6_ACL_RULE ========= */
+              case MV_TPM_IOCTL_ADD_IPV6_GEN_ACL_RULE:
+
+                  rcode = tpm_add_ipv6_gen_rule(  tpm_add_acl_rule->owner_id,
+                                                    tpm_add_acl_rule->src_port,
+                                                    tpm_add_acl_rule->rule_num,
+                                                  &(tpm_add_acl_rule->rule_idx),
+                                                    tpm_add_acl_rule->parse_rule_bm,
+                                                    tpm_add_acl_rule->ipv6_gen_acl_rule.parse_flags_bm,
+                                                  &(tpm_add_acl_rule->ipv6_gen_acl_rule.ipv6_gen_key),
+                                                  &(tpm_add_acl_rule->ipv6_gen_acl_rule.pkt_frwd),
+                                                  &(tpm_add_acl_rule->ipv6_gen_acl_rule.pkt_mod),
+                                                    tpm_add_acl_rule->ipv6_gen_acl_rule.pkt_mod_bm,
+                                                  &(tpm_add_acl_rule->ipv6_gen_acl_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_ADD_IPV6_NH_ACL_RULE:
+
+                  rcode = tpm_add_ipv6_nh_rule(  tpm_add_acl_rule->owner_id,
+                                                 tpm_add_acl_rule->rule_num,
+                                               &(tpm_add_acl_rule->rule_idx),
+                                                 tpm_add_acl_rule->parse_rule_bm,
+                                                 tpm_add_acl_rule->ipv6_nh_acl_rule.nh_iter,
+                                                 tpm_add_acl_rule->ipv6_nh_acl_rule.nh,
+                                               &(tpm_add_acl_rule->ipv6_nh_acl_rule.pkt_frwd),
+                                               &(tpm_add_acl_rule->ipv6_nh_acl_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_ADD_IPV6_DIP_ACL_RULE:
+
+                  rcode = tpm_add_ipv6_dip_rule(  tpm_add_acl_rule->owner_id,
+                                                  tpm_add_acl_rule->src_port,
+                                                  tpm_add_acl_rule->rule_num,
+                                                &(tpm_add_acl_rule->rule_idx),
+                                                  tpm_add_acl_rule->parse_rule_bm,
+                                                  tpm_add_acl_rule->ipv6_dip_acl_rule.parse_flags_bm,
+                                                &(tpm_add_acl_rule->ipv6_dip_acl_rule.ipv6_dip_key),
+                                                &(tpm_add_acl_rule->ipv6_dip_acl_rule.pkt_frwd),
+                                                &(tpm_add_acl_rule->ipv6_dip_acl_rule.pkt_mod),
+                                                  tpm_add_acl_rule->ipv6_dip_acl_rule.pkt_mod_bm,
+                                                &(tpm_add_acl_rule->ipv6_dip_acl_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_ADD_IPV6_L4_PORTS_ACL_RULE:
+
+                  rcode = tpm_add_ipv6_l4_ports_rule(  tpm_add_acl_rule->owner_id,
+                                                       tpm_add_acl_rule->src_port,
+                                                       tpm_add_acl_rule->rule_num,
+                                                     &(tpm_add_acl_rule->rule_idx),
+                                                       tpm_add_acl_rule->parse_rule_bm,
+                                                       tpm_add_acl_rule->ipv6_l4_ports_acl_rule.parse_flags_bm,
+                                                     &(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.l4_key),
+                                                     &(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_frwd),
+                                                     &(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_mod),
+                                                       tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_mod_bm,
+                                                     &(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_IPv6_5T_RULE ========= */
+              case MV_TPM_IOCTL_ADD_IPV6_GEN_5T_RULE:
+
+                  rcode = tpm_add_ipv6_gen_5t_rule( tpm_add_acl_rule->owner_id,
+                                                    tpm_add_acl_rule->src_dir,
+                                                    tpm_add_acl_rule->rule_num,
+                                                  &(tpm_add_acl_rule->rule_idx),
+                                                    tpm_add_acl_rule->parse_rule_bm,
+                                                    tpm_add_acl_rule->ipv6_gen_5t_rule.parse_flags_bm,
+                                                  &(tpm_add_acl_rule->ipv6_gen_5t_rule.l4_key),
+                                                  &(tpm_add_acl_rule->ipv6_gen_5t_rule.ipv6_gen_key),
+                                                  &(tpm_add_acl_rule->ipv6_gen_5t_rule.pkt_frwd),
+                                                  &(tpm_add_acl_rule->ipv6_gen_5t_rule.pkt_mod),
+                                                    tpm_add_acl_rule->ipv6_gen_5t_rule.pkt_mod_bm,
+                                                  &(tpm_add_acl_rule->ipv6_gen_5t_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_ADD_IPV6_DIP_5T_RULE:
+
+                  rcode = tpm_add_ipv6_dip_5t_rule( tpm_add_acl_rule->owner_id,
+                                                    tpm_add_acl_rule->src_dir,
+                                                    tpm_add_acl_rule->rule_num,
+                                                  &(tpm_add_acl_rule->rule_idx),
+                                                    tpm_add_acl_rule->parse_rule_bm,
+                                                    tpm_add_acl_rule->ipv6_dip_5t_rule.parse_flags_bm,
+                                                  &(tpm_add_acl_rule->ipv6_dip_5t_rule.l4_key),
+                                                  &(tpm_add_acl_rule->ipv6_dip_5t_rule.ipv6_gen_key),
+                                                  &(tpm_add_acl_rule->ipv6_dip_5t_rule.ipv6_dip_key),
+                                                  &(tpm_add_acl_rule->ipv6_dip_5t_rule.pkt_frwd),
+                                                  &(tpm_add_acl_rule->ipv6_dip_5t_rule.pkt_mod),
+                                                    tpm_add_acl_rule->ipv6_dip_5t_rule.pkt_mod_bm,
+                                                  &(tpm_add_acl_rule->ipv6_dip_5t_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_ADD_IPV6_L4_PORTS_5T_RULE:
+
+                  rcode = tpm_add_ipv6_l4_ports_5t_rule(  tpm_add_acl_rule->owner_id,
+                                                          tpm_add_acl_rule->src_dir,
+                                                          tpm_add_acl_rule->rule_num,
+                                                        &(tpm_add_acl_rule->rule_idx),
+                                                          tpm_add_acl_rule->parse_rule_bm,
+                                                          tpm_add_acl_rule->ipv6_l4_ports_acl_rule.parse_flags_bm,
+                                                        &(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.l4_key),
+                                                        &(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_frwd),
+                                                        &(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_mod),
+                                                          tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_mod_bm,
+                                                        &(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.rule_action));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+		  
+	      /* ====== MV_TPM_IOCTL_ADD_CTC_CM_ACL_RULE ========= */
+	      case MV_TPM_IOCTL_ADD_CTC_CM_ACL_RULE:
+	      	  rcode = tpm_add_ctc_cm_acl_rule(tpm_add_acl_rule->owner_id,
+		  				tpm_add_acl_rule->src_port,
+		  				tpm_add_acl_rule->ctc_cm_acl_rule.precedence,
+		  				tpm_add_acl_rule->ctc_cm_acl_rule.l2_parse_rule_bm,
+		  				tpm_add_acl_rule->ctc_cm_acl_rule.ipv4_parse_rule_bm,
+		  				&tpm_add_acl_rule->ctc_cm_acl_rule.l2_key,
+		  				&tpm_add_acl_rule->ctc_cm_acl_rule.ipv4_key,
+		  				&tpm_add_acl_rule->ctc_cm_acl_rule.pkt_frwd,
+		  				tpm_add_acl_rule->ctc_cm_acl_rule.pkt_act,
+		  				tpm_add_acl_rule->ctc_cm_acl_rule.p_bits);
+		  if (rcode != TPM_OK)
+		  	goto ioctlErr;
+
+		  if (copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t))) {
+		  	printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+			goto ioctlErr;
+		  }
+		  ret = 0;
+	      	  break;
+	      /* ====== MV_TPM_IOCTL_ADD_CTC_CM_ACL_RULE ========= */
+	      case MV_TPM_IOCTL_ADD_CTC_CM_IPV6_ACL_RULE:
+	          rcode = tpm_add_ctc_cm_ipv6_acl_rule(tpm_add_acl_rule->owner_id,
+				    tpm_add_acl_rule->src_port,
+				    tpm_add_acl_rule->ctc_cm_acl_rule.precedence,
+				    tpm_add_acl_rule->ctc_cm_acl_rule.ipv6_parse_rule_bm,
+				    &tpm_add_acl_rule->ctc_cm_acl_rule.ipv6_key,
+				    &tpm_add_acl_rule->ctc_cm_acl_rule.pkt_frwd,
+				    tpm_add_acl_rule->ctc_cm_acl_rule.pkt_act,
+				    tpm_add_acl_rule->ctc_cm_acl_rule.p_bits);
+	           if (rcode != TPM_OK)
+		         goto ioctlErr;
+
+                   if (copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t))) {
+		           printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+		           goto ioctlErr;
+	           }
+	           ret = 0;
+	           break;
+
+              /* ====== MV_TPM_IOCTL_SET_MOD_RULE ========= */
+              case MV_TPM_IOCTL_SET_MOD_RULE:
+
+                  rcode = tpm_mod_entry_set (  tpm_add_acl_rule->mod_rule.trg_port,
+                                               tpm_add_acl_rule->mod_rule.mod_bm,
+                                               tpm_add_acl_rule->mod_rule.int_bm,
+                                               &(tpm_add_acl_rule->mod_rule.mod_data),
+                                               &(tpm_add_acl_rule->rule_idx) );
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_add_acl_rule_t*)arg, tpm_add_acl_rule, sizeof(tpm_ioctl_add_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== ACL Rule Del Section ====== */
+      /* ================================== */
+      case MV_TPM_IOCTL_DEL_ACL_SECTION:
+      {
+          tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = (tpm_ioctl_del_acl_rule_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_del_acl_rule == NULL)
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+              ret = -ENOMEM;
+              goto ioctlErr;
+          }
+          mpool_s_buff = tpm_del_acl_rule;
+
+          if(copy_from_user(tpm_del_acl_rule, (tpm_ioctl_del_acl_rule_t*)arg, sizeof(tpm_ioctl_del_acl_rule_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_del_acl_rule->del_acl_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_DEL_L2_ACL_RULE ========= */
+              case MV_TPM_IOCTL_DEL_L2_ACL_RULE:
+
+                  rcode = tpm_del_l2_rule(  tpm_del_acl_rule->owner_id,
+                                            tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+		  /* ====== MV_TPM_IOCTL_DEL_MAC_LEARN_ACL_RULE ========= */
+		  case MV_TPM_IOCTL_DEL_MAC_LEARN_ACL_RULE:
+		      rcode = tpm_del_mac_learn_rule(tpm_del_acl_rule->owner_id,
+						     &tpm_del_acl_rule->l2_key);
+		      if(rcode != TPM_OK)
+			goto ioctlErr;
+
+		      if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+		      {
+			printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+			goto ioctlErr;
+		      }
+
+		      ret = 0;
+		      break;
+
+              /* ====== MV_TPM_IOCTL_DEL_L3_ACL_RULE ========= */
+              case MV_TPM_IOCTL_DEL_L3_ACL_RULE:
+
+                  rcode = tpm_del_l3_type_rule(  tpm_del_acl_rule->owner_id,
+                                                 tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_DEL_IPv4_ACL_RULE ========= */
+              case MV_TPM_IOCTL_DEL_IPv4_ACL_RULE:
+
+                  rcode = tpm_del_ipv4_rule(  tpm_del_acl_rule->owner_id,
+                                              tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_DEL_IPv6_ACL_RULE ========= */
+              case MV_TPM_IOCTL_DEL_IPV6_GEN_ACL_RULE:
+
+                  rcode = tpm_del_ipv6_gen_rule(  tpm_del_acl_rule->owner_id,
+                                                    tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_DEL_IPV6_NH_ACL_RULE:
+
+                  rcode = tpm_del_ipv6_nh_rule(  tpm_del_acl_rule->owner_id,
+                                                 tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_DEL_IPV6_DIP_ACL_RULE:
+
+                  rcode = tpm_del_ipv6_dip_rule(  tpm_del_acl_rule->owner_id,
+                                                  tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_DEL_IPV6_L4_PORTS_ACL_RULE:
+
+                  rcode = tpm_del_ipv6_l4_ports_rule(  tpm_del_acl_rule->owner_id,
+                                                       tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_DEL_IPv6_5T_RULE ========= */
+              case MV_TPM_IOCTL_DEL_IPV6_GEN_5T_RULE:
+
+                  rcode = tpm_del_ipv6_gen_5t_rule(  tpm_del_acl_rule->owner_id,
+                                                     tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_DEL_IPV6_DIP_5T_RULE:
+
+                  rcode = tpm_del_ipv6_dip_5t_rule(  tpm_del_acl_rule->owner_id,
+                                                     tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_DEL_IPV6_L4_PORTS_5T_RULE:
+
+                  rcode = tpm_del_ipv6_l4_ports_5t_rule(  tpm_del_acl_rule->owner_id,
+                                                          tpm_del_acl_rule->rule_idx);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+	       /* ====== MV_TPM_IOCTL_DEL_CTC_CM_ACL_RULE ========= */
+	       case MV_TPM_IOCTL_DEL_CTC_CM_ACL_RULE:
+		  
+		   rcode = tpm_del_ctc_cm_acl_rule(tpm_del_acl_rule->owner_id,
+						tpm_del_acl_rule->src_port,
+						tpm_del_acl_rule->precedence);
+		  
+		   if (rcode != TPM_OK)
+		   	goto ioctlErr;
+		  
+		   if (copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t))) {
+			printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+			goto ioctlErr;
+		   }
+		  
+		   ret = 0;
+		   break;
+
+              /* ====== MV_TPM_IOCTL_DEL_MOD_RULE ========= */
+              case MV_TPM_IOCTL_DEL_MOD_RULE:
+
+                  rcode = tpm_mod_entry_del ( tpm_del_acl_rule->trg_port,
+                                              tpm_del_acl_rule->rule_idx );
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+	          /* ====== MV_TPM_IOCTL_INV_MOD_RULES ========= */
+	          case MV_TPM_IOCTL_INV_MOD_RULES:
+
+	              rcode = tpm_mod_mac_inv ( tpm_del_acl_rule->trg_port );
+	              if(rcode != TPM_OK)
+	                goto ioctlErr;
+
+	              if(copy_to_user((tpm_ioctl_del_acl_rule_t*)arg, tpm_del_acl_rule, sizeof(tpm_ioctl_del_acl_rule_t)))
+	              {
+	                printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+	                goto ioctlErr;
+	              }
+
+	              ret = 0;
+	              break;
+
+	            default:
+	              printk(KERN_ERR "ERROR: (%s:%d) invalid cmd(%d)\n", __FUNCTION__, __LINE__, tpm_del_acl_rule->del_acl_cmd);
+	              ret = -EINVAL;
+	          }
+	          break;
+      }
+
+      /* ================================== */
+      /* ====== ACL Rule Ctrl Section ===== */
+      /* ================================== */
+      case MV_TPM_IOCTL_CTRL_ACL_SECTION:
+      {
+          tpm_ioctl_ctrl_acl_rule_t *tpm_ctrl_acl_rule = (tpm_ioctl_ctrl_acl_rule_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_ctrl_acl_rule == NULL)
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+              ret = -ENOMEM;
+              goto ioctlErr;
+          }
+          mpool_s_buff = tpm_ctrl_acl_rule;
+
+          if(copy_from_user(tpm_ctrl_acl_rule, (tpm_ioctl_ctrl_acl_rule_t*)arg, sizeof(tpm_ioctl_ctrl_acl_rule_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_ctrl_acl_rule->ctrl_acl_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_GET_NEXT_VALID_RULE ========= */
+              case MV_TPM_IOCTL_GET_NEXT_VALID_RULE:
+
+                  rcode = tpm_get_next_valid_rule(  tpm_ctrl_acl_rule->owner_id,
+                                                    tpm_ctrl_acl_rule->current_index,
+                                                    tpm_ctrl_acl_rule->rule_type,
+                                                  &(tpm_ctrl_acl_rule->next_index),
+                                                  &(tpm_ctrl_acl_rule->rule_idx),
+                                                  &(tpm_ctrl_acl_rule->tpm_rule));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_ctrl_acl_rule_t*)arg, tpm_ctrl_acl_rule, sizeof(tpm_ioctl_ctrl_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+               /* ====== MV_TPM_IOCTL_GET_MAC_LEARN_ENTRY_NUM ========= */
+               case MV_TPM_IOCTL_GET_MAC_LEARN_ENTRY_NUM:
+                  rcode = tpm_mac_learn_entry_num_get(&(tpm_ctrl_acl_rule->entry_count));
+                  if (rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_ctrl_acl_rule_t*)arg, tpm_ctrl_acl_rule, sizeof(tpm_ioctl_ctrl_acl_rule_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== Mod Rule GET Section  ===== */
+      /* ================================== */
+      case MV_TPM_IOCTL_GET_MOD_SECTION:
+      {
+          tpm_ioctl_get_mod_rule_t *tpm_get_mod_rule = (tpm_ioctl_get_mod_rule_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_m);
+          if (tpm_get_mod_rule == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_m);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_m_buff = tpm_get_mod_rule;
+
+          if(copy_from_user(tpm_get_mod_rule, (tpm_ioctl_get_mod_rule_t*)arg, sizeof(tpm_ioctl_get_mod_rule_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_get_mod_rule->get_mod_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_GET_MOD_RULE ========= */
+              case MV_TPM_IOCTL_GET_MOD_RULE:
+
+                  rcode = tpm_mod_entry_get (tpm_get_mod_rule->trg_port,
+                                             tpm_get_mod_rule->rule_idx,
+                                            &(tpm_get_mod_rule->valid_num),
+                                            &(tpm_get_mod_rule->pnc_ref),
+                                             tpm_get_mod_rule->rule);
+
+                  if(copy_to_user((tpm_ioctl_get_mod_rule_t*)arg, tpm_get_mod_rule, sizeof(tpm_ioctl_get_mod_rule_t)))
+                  {
+                      printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                      goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              default:
+                  ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ===== MC Stream Rule Section ===== */
+      /* ================================== */
+      case MV_TPM_IOCTL_MC_STREAM_SECTION:
+      {
+          tpm_ioctl_mc_rule_t *tpm_mc_rule = (tpm_ioctl_mc_rule_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_mc_rule == NULL)
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+              ret = -ENOMEM;
+              goto ioctlErr;
+          }
+          mpool_s_buff = tpm_mc_rule;
+
+          if(copy_from_user(tpm_mc_rule, (tpm_ioctl_mc_rule_t*)arg, sizeof(tpm_ioctl_mc_rule_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_mc_rule->mc_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_ADD_IPv4_MC_STREAM ========= */
+              case MV_TPM_IOCTL_ADD_IPv4_MC_STREAM:
+
+
+                  rcode = tpm_add_ipv4_mc_stream(  tpm_mc_rule->owner_id,
+                                                   tpm_mc_rule->stream_num,
+                                                   tpm_mc_rule->igmp_mode,
+                                                   tpm_mc_rule->mc_stream_pppoe,
+                                                   tpm_mc_rule->vid,
+                                                 &(tpm_mc_rule->ipv4_mc.ipv4_src_add[0]),
+                                                 &(tpm_mc_rule->ipv4_mc.ipv4_dst_add[0]),
+                                                   tpm_mc_rule->ipv4_mc.ignore_ipv4_src,
+                                                   tpm_mc_rule->dest_port_bm);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_MOD_IPv4_MC_STREAM ========= */
+              case MV_TPM_IOCTL_MOD_IPv4_MC_STREAM:
+
+                  rcode = tpm_updt_ipv4_mc_stream(tpm_mc_rule->owner_id,
+                                                  tpm_mc_rule->stream_num,
+                                                  tpm_mc_rule->dest_port_bm);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_DEL_IPv4_MC_STREAM ========= */
+              case MV_TPM_IOCTL_DEL_IPv4_MC_STREAM:
+
+                  rcode = tpm_del_ipv4_mc_stream(tpm_mc_rule->owner_id,
+                                                 tpm_mc_rule->stream_num);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+			  /* ====== MV_TPM_IOCTL_ADD_IPv6_MC_STREAM ========= */
+			  case MV_TPM_IOCTL_ADD_IPv6_MC_STREAM:
+
+				  rcode = tpm_add_ipv6_mc_stream(  tpm_mc_rule->owner_id,
+								   tpm_mc_rule->stream_num,
+								   tpm_mc_rule->igmp_mode,
+								   tpm_mc_rule->mc_stream_pppoe,
+								   tpm_mc_rule->vid,
+								   &(tpm_mc_rule->ipv6_mc.ipv6_src_add[0]),
+								   &(tpm_mc_rule->ipv6_mc.ipv6_dst_add[0]),
+								   tpm_mc_rule->ipv6_mc.ignore_ipv6_src,
+								   tpm_mc_rule->dest_port_bm);
+				  if(rcode != TPM_OK)
+					goto ioctlErr;
+
+				  ret = 0;
+				  break;
+
+			  /* ====== MV_TPM_IOCTL_MOD_IPv6_MC_STREAM ========= */
+			  case MV_TPM_IOCTL_MOD_IPv6_MC_STREAM:
+
+				  rcode = tpm_updt_ipv6_mc_stream(tpm_mc_rule->owner_id,
+												  tpm_mc_rule->stream_num,
+												  tpm_mc_rule->dest_port_bm);
+				  if(rcode != TPM_OK)
+					goto ioctlErr;
+
+				  ret = 0;
+				  break;
+
+			  /* ====== MV_TPM_IOCTL_DEL_IPv6_MC_STREAM ========= */
+			  case MV_TPM_IOCTL_DEL_IPv6_MC_STREAM:
+
+				  rcode = tpm_del_ipv6_mc_stream(tpm_mc_rule->owner_id,
+												 tpm_mc_rule->stream_num);
+				  if(rcode != TPM_OK)
+					goto ioctlErr;
+
+				  ret = 0;
+				  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== Mng Rule Section ========== */
+      /* ================================== */
+  case MV_TPM_IOCTL_MNG_SECTION:
+  {
+      tpm_ioctl_mng_ch_t *tpm_mng_ch = (tpm_ioctl_mng_ch_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_mng_ch == NULL)
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+              ret = -ENOMEM;
+              goto ioctlErr;
+          }
+          mpool_s_buff = tpm_mng_ch;
+
+          if(copy_from_user(tpm_mng_ch, (tpm_ioctl_mng_ch_t*)arg, sizeof(tpm_ioctl_mng_ch_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_mng_ch->mng_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_ADD_OMCI_CHNL ========= */
+              case MV_TPM_IOCTL_ADD_OMCI_CHNL:
+
+                  rcode = tpm_omci_add_channel(tpm_mng_ch->tpm_ioctl_omci_ch.owner_id,
+                                               tpm_mng_ch->tpm_ioctl_omci_ch.gem_port,
+                                               tpm_mng_ch->tpm_ioctl_omci_ch.cpu_rx_queue,
+                                               tpm_mng_ch->tpm_ioctl_omci_ch.tcont_num,
+                                               tpm_mng_ch->tpm_ioctl_omci_ch.cpu_tx_queue);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_DEL_OMCI_CHNL ========= */
+              case MV_TPM_IOCTL_DEL_OMCI_CHNL:
+
+                  rcode = tpm_omci_del_channel(tpm_mng_ch->tpm_ioctl_omci_ch.owner_id);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_GET_OMCI_CHNL ========= */
+              case MV_TPM_IOCTL_GET_OMCI_CHNL:
+
+                  rcode = tpm_omci_get_channel(&(tpm_mng_ch->tpm_ioctl_omci_ch.is_valid),
+                                               &(tpm_mng_ch->tpm_ioctl_omci_ch.gem_port),
+                                               &(tpm_mng_ch->tpm_ioctl_omci_ch.cpu_rx_queue),
+                                               &(tpm_mng_ch->tpm_ioctl_omci_ch.tcont_num),
+                                               &(tpm_mng_ch->tpm_ioctl_omci_ch.cpu_tx_queue));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_mng_ch_t*)arg, tpm_mng_ch, sizeof(tpm_ioctl_mng_ch_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_OAM_CHNL ========= */
+              case MV_TPM_IOCTL_ADD_OAM_CHNL:
+
+                  rcode = tpm_oam_epon_add_channel(tpm_mng_ch->tpm_ioctl_oam_ch.owner_id,
+                                                   tpm_mng_ch->tpm_ioctl_oam_ch.cpu_rx_queue,
+                                                   tpm_mng_ch->tpm_ioctl_oam_ch.llid_num);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_LOOP_DETECT_CHNL ========= */
+              case MV_TPM_IOCTL_ADD_LOOP_DETECT_CHNL:
+
+                  rcode = tpm_loop_detect_add_channel(tpm_mng_ch->tpm_ioctl_oam_ch.owner_id);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_DEL_OAM_CHNL ========= */
+              case MV_TPM_IOCTL_DEL_OAM_CHNL:
+
+                  rcode = tpm_oam_epon_del_channel(tpm_mng_ch->tpm_ioctl_oam_ch.owner_id);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_GET_OAM_CHNL ========= */
+              case MV_TPM_IOCTL_GET_OAM_CHNL:
+
+                  rcode = tpm_oam_epon_get_channel(&(tpm_mng_ch->tpm_ioctl_oam_ch.is_valid),
+                                                   &(tpm_mng_ch->tpm_ioctl_oam_ch.cpu_rx_queue),
+                                                   &(tpm_mng_ch->tpm_ioctl_oam_ch.llid_num));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_mng_ch_t*)arg, tpm_mng_ch, sizeof(tpm_ioctl_mng_ch_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_ADD_LOOP_DETECT_CHNL ========= */
+              case MV_TPM_IOCTL_ADD_OAM_LOOPBACK_CHNL:
+
+                  rcode = tpm_oam_loopback_add_channel(tpm_mng_ch->tpm_ioctl_oam_ch.owner_id);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_DEL_OAM_LOOPBACK_CHNL:
+
+                  rcode = tpm_oam_loopback_del_channel(tpm_mng_ch->tpm_ioctl_oam_ch.owner_id);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+        }
+
+      /* ================================== */
+      /* ====== Switch Security Section === */
+      /* ================================== */
+      case MV_TPM_IOCTL_SW_SECURITY_SECTION:
+      {
+          tpm_ioctl_sw_mac_security_t *tpm_sw_mac_security = (tpm_ioctl_sw_mac_security_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_sw_mac_security == NULL)
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+              ret = -ENOMEM;
+              goto ioctlErr;
+          }
+          mpool_s_buff = tpm_sw_mac_security;
+
+          if(copy_from_user(tpm_sw_mac_security, (tpm_ioctl_sw_mac_security_t*)arg, sizeof(tpm_ioctl_sw_mac_security_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_sw_mac_security->sw_security_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_SW_ADD_STATIC_MAC ========= */
+              case MV_TPM_IOCTL_SW_ADD_STATIC_MAC:
+                  rcode = tpm_sw_add_static_mac(  tpm_sw_mac_security->owner_id,
+                                                  tpm_sw_mac_security->port,
+                                                &(tpm_sw_mac_security->static_mac[0]));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_DEL_STATIC_MAC ========= */
+              case MV_TPM_IOCTL_SW_DEL_STATIC_MAC:
+                  rcode = tpm_sw_del_static_mac(  tpm_sw_mac_security->owner_id,
+                                                &(tpm_sw_mac_security->static_mac[0]));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_SET_PORT_MAC_LIMIT ========= */
+              case MV_TPM_IOCTL_SW_SET_PORT_MAC_LIMIT:
+                  rcode = tpm_sw_set_port_max_macs(tpm_sw_mac_security->owner_id,
+                                                   tpm_sw_mac_security->port,
+                                                   tpm_sw_mac_security->mac_per_port);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_SET_MAC_AGE_TIME ========= */
+              case MV_TPM_IOCTL_SW_SET_MAC_AGE_TIME:
+                  rcode = tpm_sw_set_mac_age_time(tpm_sw_mac_security->owner_id,
+                                                  tpm_sw_mac_security->mac_age_time);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_GET_MAC_AGE_TIME ========= */
+              case MV_TPM_IOCTL_SW_GET_MAC_AGE_TIME:
+                  rcode = tpm_sw_get_mac_age_time(tpm_sw_mac_security->owner_id,
+                                                 &(tpm_sw_mac_security->mac_age_time));
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_sw_mac_security_t*)arg, tpm_sw_mac_security, sizeof(tpm_ioctl_sw_mac_security_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_SET_MAC_LEARN ========= */
+              case MV_TPM_IOCTL_SW_SET_MAC_LEARN:
+                  rcode = tpm_sw_set_mac_learn(tpm_sw_mac_security->owner_id,
+                                               tpm_sw_mac_security->port,
+                                               tpm_sw_mac_security->enable_mac_learn);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_GET_MAC_LEARN ========= */
+              case MV_TPM_IOCTL_SW_GET_MAC_LEARN:
+                  rcode = tpm_sw_get_mac_learn(  tpm_sw_mac_security->owner_id,
+                                                 tpm_sw_mac_security->port,
+                                               &(tpm_sw_mac_security->enable_mac_learn));
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_sw_mac_security_t*)arg, tpm_sw_mac_security, sizeof(tpm_ioctl_sw_mac_security_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SET_MTU_SIZE ========= */
+              case MV_TPM_IOCTL_SET_MTU_SIZE:
+                  rcode = tpm_set_mtu_size(tpm_sw_mac_security->owner_id,
+                                           tpm_sw_mac_security->mtu_type,
+                                           tpm_sw_mac_security->mtu_size);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_GET_MTU_SIZE ========= */
+              case MV_TPM_IOCTL_GET_MTU_SIZE:
+                  rcode = tpm_get_mtu_size(  tpm_sw_mac_security->owner_id,
+                                             tpm_sw_mac_security->mtu_type,
+                                           &(tpm_sw_mac_security->mtu_size));
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_sw_mac_security_t*)arg, tpm_sw_mac_security, sizeof(tpm_ioctl_sw_mac_security_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_SET_PORT_FLOOD ========= */
+              case MV_TPM_IOCTL_SW_SET_PORT_FLOOD:
+                  rcode = tpm_sw_set_port_flooding(tpm_sw_mac_security->owner_id,
+                                                   tpm_sw_mac_security->port,
+                                                   tpm_sw_mac_security->flood_mode,
+                                                   tpm_sw_mac_security->allow_flood);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_GET_PORT_FLOOD ========= */
+              case MV_TPM_IOCTL_SW_GET_PORT_FLOOD:
+                  rcode = tpm_sw_get_port_flooding(  tpm_sw_mac_security->owner_id,
+                                                     tpm_sw_mac_security->port,
+                                                     tpm_sw_mac_security->flood_mode,
+                                                   &(tpm_sw_mac_security->allow_flood));
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_sw_mac_security_t*)arg, tpm_sw_mac_security, sizeof(tpm_ioctl_sw_mac_security_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_CLEAR_DYNAMIC_MAC ========= */
+              case MV_TPM_IOCTL_SW_CLEAR_DYNAMIC_MAC:
+                  rcode = tpm_sw_clear_dynamic_mac(tpm_sw_mac_security->owner_id);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_SET_MIRROR ========= */
+              case MV_TPM_IOCTL_SW_SET_MIRROR:
+                  rcode = tpm_sw_set_port_mirror(tpm_sw_mac_security->owner_id,
+                                                 tpm_sw_mac_security->port_mirror.sport,
+                                                 tpm_sw_mac_security->port_mirror.dport,
+                                                 tpm_sw_mac_security->port_mirror.mode,
+                                                 tpm_sw_mac_security->port_mirror.enable);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_GET_MIRROR ========= */
+              case MV_TPM_IOCTL_SW_GET_MIRROR:
+                  rcode = tpm_sw_get_port_mirror(  tpm_sw_mac_security->owner_id,
+                                                   tpm_sw_mac_security->port_mirror.sport,
+                                                   tpm_sw_mac_security->port_mirror.dport,
+                                                   tpm_sw_mac_security->port_mirror.mode,
+                                                 &(tpm_sw_mac_security->port_mirror.enable));
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_sw_mac_security_t*)arg, tpm_sw_mac_security, sizeof(tpm_ioctl_sw_mac_security_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_SET_ISOLATE_PORT_VECTOR ========= */
+              case MV_TPM_IOCTL_SW_SET_ISOLATE_PORT_VECTOR:
+                  rcode = tpm_sw_set_isolate_eth_port_vector(tpm_sw_mac_security->owner_id,
+                                                             tpm_sw_mac_security->port,
+                                                             tpm_sw_mac_security->port_vector);
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+	          /* ====== MV_TPM_IOCTL_SW_GET_ISOLATE_PORT_VECTOR ========= */
+              case MV_TPM_IOCTL_SW_GET_ISOLATE_PORT_VECTOR:
+                  rcode = tpm_sw_get_isolate_eth_port_vector(  tpm_sw_mac_security->owner_id,
+                                                               tpm_sw_mac_security->port,
+                                                             &(tpm_sw_mac_security->port_vector));
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_sw_mac_security_t*)arg, tpm_sw_mac_security, sizeof(tpm_ioctl_sw_mac_security_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== Switch Vlan Section ======= */
+      /* ================================== */
+      case MV_TPM_IOCTL_SW_VLAN_SECTION:
+      {
+        tpm_ioctl_sw_vlan_filter_t *tpm_sw_vlan_filter = (tpm_ioctl_sw_vlan_filter_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+        if (tpm_sw_vlan_filter == NULL)
+        {
+          printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+          ret = -ENOMEM;
+          goto ioctlErr;
+        }
+        mpool_s_buff = tpm_sw_vlan_filter;
+
+        if(copy_from_user(tpm_sw_vlan_filter, (tpm_ioctl_sw_vlan_filter_t*)arg, sizeof(tpm_ioctl_sw_vlan_filter_t)))
+        {
+          printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+          goto ioctlErr;
+        }
+
+         switch (tpm_sw_vlan_filter->sw_vlan_cmd)
+        {
+          /* ====== MV_TPM_IOCTL_SW_SET_PORT_TAGGED ========= */
+          case MV_TPM_IOCTL_SW_SET_PORT_TAGGED:
+            rcode = tpm_sw_set_port_tagged(tpm_sw_vlan_filter->owner_id,
+                                           tpm_sw_vlan_filter->port,
+                                           tpm_sw_vlan_filter->allow_tagged);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_SET_PORT_UNTAGGED ========= */
+          case MV_TPM_IOCTL_SW_SET_PORT_UNTAGGED:
+            rcode = tpm_sw_set_port_untagged(tpm_sw_vlan_filter->owner_id,
+                                             tpm_sw_vlan_filter->port,
+                                             tpm_sw_vlan_filter->allow_untagged);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_ADD_VID ========= */
+          case MV_TPM_IOCTL_SW_PORT_ADD_VID:
+            rcode = tpm_sw_port_add_vid(tpm_sw_vlan_filter->owner_id,
+                                        tpm_sw_vlan_filter->port,
+                                        tpm_sw_vlan_filter->vid);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_DEL_VID ========= */
+          case MV_TPM_IOCTL_SW_PORT_DEL_VID:
+            rcode = tpm_sw_port_del_vid(tpm_sw_vlan_filter->owner_id,
+                                        tpm_sw_vlan_filter->port,
+                                        tpm_sw_vlan_filter->vid);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_CLEAR_VID ========= */
+          case MV_TPM_IOCTL_SW_PORT_CLEAR_VID:
+            rcode = tpm_sw_clear_vid_per_port(tpm_sw_vlan_filter->owner_id,
+                                              tpm_sw_vlan_filter->port);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_ADD_ALL_VID ========= */
+          case MV_TPM_IOCTL_SW_PORT_ADD_ALL_VID:
+            rcode = tpm_sw_add_all_vid_per_port(tpm_sw_vlan_filter->owner_id,
+                                                tpm_sw_vlan_filter->port);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_ADD_VID_GROUP ========= */
+          case MV_TPM_IOCTL_SW_ADD_VID_GROUP:
+            rcode = tpm_sw_port_add_vid_group(tpm_sw_vlan_filter->owner_id,
+                                              tpm_sw_vlan_filter->port,
+                                              (uint8_t)tpm_sw_vlan_filter->egress_mode,
+                                              tpm_sw_vlan_filter->min_vid,
+                                              tpm_sw_vlan_filter->max_vid);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_DEL_VID_GROUP ========= */
+          case MV_TPM_IOCTL_SW_DEL_VID_GROUP:
+            rcode = tpm_sw_port_del_vid_group(tpm_sw_vlan_filter->owner_id,
+                                              tpm_sw_vlan_filter->port,
+                                              tpm_sw_vlan_filter->min_vid,
+                                              tpm_sw_vlan_filter->max_vid);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_SER_VID_FILTER ========= */
+          case MV_TPM_IOCTL_SW_PORT_SER_VID_FILTER:
+            rcode = tpm_sw_port_set_vid_filter(tpm_sw_vlan_filter->owner_id,
+                                                tpm_sw_vlan_filter->port,
+                                                tpm_sw_vlan_filter->vid_filter);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_VLAN_EGRESS_MODE ========= */
+          case MV_TPM_IOCTL_SW_PORT_VLAN_EGRESS_MODE:
+            rcode = tpm_sw_set_port_vid_egress_mode(tpm_sw_vlan_filter->owner_id,
+                                                    tpm_sw_vlan_filter->port,
+                                                    tpm_sw_vlan_filter->vid,
+                                                    tpm_sw_vlan_filter->egress_mode);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_SET_DEFAULT_VLAN ========= */
+          case MV_TPM_IOCTL_SW_PORT_SET_DEFAULT_VLAN:
+            rcode = tpm_sw_set_port_def_vlan(tpm_sw_vlan_filter->owner_id,
+                                             tpm_sw_vlan_filter->port,
+                                             tpm_sw_vlan_filter->vid);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_GET_DEFAULT_VLAN ========= */
+          case MV_TPM_IOCTL_SW_PORT_GET_DEFAULT_VLAN:
+            rcode = tpm_sw_get_port_def_vlan(tpm_sw_vlan_filter->owner_id,
+                                             tpm_sw_vlan_filter->port,
+                                             &(tpm_sw_vlan_filter->vid));
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+
+            if(copy_to_user((tpm_ioctl_sw_vlan_filter_t*)arg, tpm_sw_vlan_filter, sizeof(tpm_ioctl_sw_vlan_filter_t)))
+            {
+              printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+              goto ioctlErr;
+            }
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_SET_DEFAULT_PRIORITY ========= */
+          case MV_TPM_IOCTL_SW_PORT_SET_DEFAULT_PRIORITY:
+            rcode = tpm_sw_set_port_def_pri(tpm_sw_vlan_filter->owner_id,
+                                            tpm_sw_vlan_filter->port,
+                                            tpm_sw_vlan_filter->pri);
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+            ret = 0;
+            break;
+
+          /* ====== MV_TPM_IOCTL_SW_PORT_GET_DEFAULT_PRIORITY ========= */
+          case MV_TPM_IOCTL_SW_PORT_GET_DEFAULT_PRIORITY:
+            rcode = tpm_sw_get_port_def_pri(tpm_sw_vlan_filter->owner_id,
+                                            tpm_sw_vlan_filter->port,
+                                            &(tpm_sw_vlan_filter->pri));
+            if(rcode != TPM_OK)
+              goto ioctlErr;
+
+            if(copy_to_user((tpm_ioctl_sw_vlan_filter_t*)arg, tpm_sw_vlan_filter, sizeof(tpm_ioctl_sw_vlan_filter_t)))
+            {
+              printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+              goto ioctlErr;
+            }
+            ret = 0;
+            break;
+          default:
+            ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== Switch TM Section ========= */
+      /* ================================== */
+      case MV_TPM_IOCTL_SW_TM_SECTION:
+      {
+          tpm_ioctl_sw_tm_t *tpm_sw_tm = (tpm_ioctl_sw_tm_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_sw_tm == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_sw_tm;
+
+          if(copy_from_user(tpm_sw_tm, (tpm_ioctl_sw_tm_t*)arg, sizeof(tpm_ioctl_sw_tm_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_sw_tm->sw_tm_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_SW_SET_UNI_SCHED ========= */
+              case MV_TPM_IOCTL_SW_SET_UNI_SCHED:
+                  rcode = tpm_sw_set_uni_sched(tpm_sw_tm->owner_id,
+                                               tpm_sw_tm->uni_port,
+                                               tpm_sw_tm->sw_sched_mode);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_UNI_QUE_WEIGHT ========= */
+              case MV_TPM_IOCTL_SW_UNI_QUE_WEIGHT:
+                  rcode = tpm_sw_set_uni_q_weight(tpm_sw_tm->owner_id,
+                                                  tpm_sw_tm->queue_id,
+                                                  tpm_sw_tm->weight);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_UNI_INGR_POLICE_RATE ========= */
+              case MV_TPM_IOCTL_SW_SET_UNI_INGR_POLICE_RATE:
+                  rcode = tpm_sw_set_uni_ingr_police_rate(tpm_sw_tm->owner_id,
+                                                          tpm_sw_tm->uni_port,
+                                                          tpm_sw_tm->limit_mode,
+                                                          tpm_sw_tm->cir,
+                                                          tpm_sw_tm->cbs,
+                                                          tpm_sw_tm->ebs);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_GET_UNI_INGR_POLICE_RATE ========= */
+              case MV_TPM_IOCTL_SW_GET_UNI_INGR_POLICE_RATE:
+
+                  rcode = tpm_sw_get_uni_ingr_police_rate(  tpm_sw_tm->owner_id,
+                                                            tpm_sw_tm->uni_port,
+                                                          &(tpm_sw_tm->limit_mode),
+                                                          &(tpm_sw_tm->cir),
+                                                          &(tpm_sw_tm->cbs),
+                                                          &(tpm_sw_tm->ebs));
+
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_sw_tm_t*)arg, tpm_sw_tm, sizeof(tpm_ioctl_sw_tm_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_UNI_TC_INGR_POLICE_RATE ========= */
+              case MV_TPM_IOCTL_SW_UNI_TC_INGR_POLICE_RATE:
+                  rcode = tpm_sw_set_uni_tc_ingr_police_rate(tpm_sw_tm->owner_id,
+                                                             tpm_sw_tm->uni_port,
+                                                             tpm_sw_tm->tc,
+                                                             tpm_sw_tm->cir,
+                                                             tpm_sw_tm->cbs);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_SET_UNI_EGR_RATE_LIMIT ========= */
+              case MV_TPM_IOCTL_SW_SET_UNI_EGR_RATE_LIMIT:
+                  rcode = tpm_sw_set_uni_egr_rate_limit(tpm_sw_tm->owner_id,
+                                                        tpm_sw_tm->uni_port,
+                                                        tpm_sw_tm->limit_mode,
+                                                        tpm_sw_tm->rate_limit_val);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_GET_UNI_EGR_RATE_LIMIT ========= */
+              case MV_TPM_IOCTL_SW_GET_UNI_EGR_RATE_LIMIT:
+                  rcode = tpm_sw_get_uni_egr_rate_limit(  tpm_sw_tm->owner_id,
+                                                          tpm_sw_tm->uni_port,
+                                                        &(tpm_sw_tm->limit_mode),
+                                                        &(tpm_sw_tm->rate_limit_val));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_sw_tm_t*)arg, tpm_sw_tm, sizeof(tpm_ioctl_sw_tm_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== Switch PHY Section ========= */
+      /* ================================== */
+      case MV_TPM_IOCTL_SW_PHY_SECTION:
+      {
+          tpm_ioctl_sw_phy_t *tpm_sw_phy = (tpm_ioctl_sw_phy_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_sw_phy == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_sw_phy;
+
+          if(copy_from_user(tpm_sw_phy, (tpm_ioctl_sw_phy_t*)arg, sizeof(tpm_ioctl_sw_phy_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_sw_phy->sw_phy_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_SW_PHY_SET_AUTONEG_MODE ========= */
+              case MV_TPM_IOCTL_SW_PHY_SET_AUTONEG_MODE:
+                  rcode = tpm_phy_set_port_autoneg_mode(tpm_sw_phy->owner_id,
+                                                        tpm_sw_phy->port,
+                                                        tpm_sw_phy->port_autoneg_state,
+                                                        tpm_sw_phy->port_autoneg_mode);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_AUTONEG_MODE ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_AUTONEG_MODE:
+                  rcode = tpm_phy_get_port_autoneg_mode(  tpm_sw_phy->owner_id,
+                                                          tpm_sw_phy->port,
+                                                        &(tpm_sw_phy->port_autoneg_state),
+                                                        &(tpm_sw_phy->port_autoneg_mode));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_RESTART_AUTONEG ========= */
+              case MV_TPM_IOCTL_SW_PHY_RESTART_AUTONEG:
+                  rcode = tpm_phy_restart_port_autoneg(tpm_sw_phy->owner_id,
+                                                       tpm_sw_phy->port);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_SET_PORT_STATE ========= */
+              case MV_TPM_IOCTL_SW_PHY_SET_PORT_STATE:
+                  rcode = tpm_phy_set_port_admin_state(tpm_sw_phy->owner_id,
+                                                       tpm_sw_phy->port,
+                                                       tpm_sw_phy->phy_port_state);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_PORT_STATE ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_PORT_STATE:
+                  rcode = tpm_phy_get_port_admin_state(  tpm_sw_phy->owner_id,
+                                                         tpm_sw_phy->port,
+                                                       &(tpm_sw_phy->phy_port_state));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_LINK_STATUS ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_LINK_STATUS:
+                  rcode = tpm_phy_get_port_link_status(  tpm_sw_phy->owner_id,
+                                                         tpm_sw_phy->port,
+                                                       &(tpm_sw_phy->port_link_status));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_DUPLEX_STATUS ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_DUPLEX_STATUS:
+                  rcode = tpm_phy_get_port_duplex_status(  tpm_sw_phy->owner_id,
+                                                           tpm_sw_phy->port,
+                                                         &(tpm_sw_phy->port_duplex_enable));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_SPEED_MODE ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_SPEED_MODE:
+                  rcode = tpm_phy_get_port_speed_mode(  tpm_sw_phy->owner_id,
+                                                        tpm_sw_phy->port,
+                                                      &(tpm_sw_phy->port_speed));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_SET_PORT_FLOW_CONTROL ========= */
+              case MV_TPM_IOCTL_SW_PHY_SET_PORT_FLOW_CONTROL:
+                  rcode = tpm_phy_set_port_flow_control_support(tpm_sw_phy->owner_id,
+                                                                tpm_sw_phy->port,
+                                                                tpm_sw_phy->port_pause_state);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_PORT_FLOW_CONTROL ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_PORT_FLOW_CONTROL:
+                  rcode = tpm_phy_get_port_flow_control_support(  tpm_sw_phy->owner_id,
+                                                                  tpm_sw_phy->port,
+                                                                &(tpm_sw_phy->port_pause_state));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_PORT_FC_STATE ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_PORT_FC_STATE:
+                  rcode = tpm_phy_get_port_flow_control_state(  tpm_sw_phy->owner_id,
+                                                                tpm_sw_phy->port,
+                                                              &(tpm_sw_phy->port_pause_state));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_SET_PORT_SPEED ========= */
+              case MV_TPM_IOCTL_SW_PHY_SET_PORT_SPEED:
+                  rcode = tpm_phy_set_port_speed(tpm_sw_phy->owner_id,
+                                                 tpm_sw_phy->port,
+                                                 tpm_sw_phy->port_speed);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_PORT_SPEED ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_PORT_SPEED:
+                  rcode = tpm_phy_get_port_speed(  tpm_sw_phy->owner_id,
+                                                   tpm_sw_phy->port,
+                                                 &(tpm_sw_phy->port_speed));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_SET_PORT_LOOPBACK ========= */
+              case MV_TPM_IOCTL_SW_PHY_SET_PORT_LOOPBACK:
+                  rcode = tpm_phy_set_port_loopback(tpm_sw_phy->owner_id,
+                                                    tpm_sw_phy->port,
+                                                    tpm_sw_phy->port_loopback_mode,
+                                                    tpm_sw_phy->port_loopback_state);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_PORT_LOOPBACK ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_PORT_LOOPBACK:
+                  rcode = tpm_phy_get_port_loopback(  tpm_sw_phy->owner_id,
+                                                      tpm_sw_phy->port,
+                                                      tpm_sw_phy->port_loopback_mode,
+                                                    &(tpm_sw_phy->port_loopback_state));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_SET_PORT_DUPLEX_MODE ========= */
+              case MV_TPM_IOCTL_SW_PHY_SET_PORT_DUPLEX_MODE:
+                  rcode = tpm_phy_set_port_duplex_mode(tpm_sw_phy->owner_id,
+                                                       tpm_sw_phy->port,
+                                                       tpm_sw_phy->port_duplex_enable);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_GET_PORT_DUPLEX_MODE ========= */
+              case MV_TPM_IOCTL_SW_PHY_GET_PORT_DUPLEX_MODE:
+                  rcode = tpm_phy_get_port_duplex_mode(  tpm_sw_phy->owner_id,
+                                                         tpm_sw_phy->port,
+                                                       &(tpm_sw_phy->port_duplex_enable));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SW_PHY_CONVERT_PORT_INDEX ========= */
+              case MV_TPM_IOCTL_SW_PHY_CONVERT_PORT_INDEX:
+                  rcode = tpm_phy_convert_port_index( tpm_sw_phy->owner_id,
+                                                      tpm_sw_phy->switch_port_id,
+                                                     &(tpm_sw_phy->extern_port_id));
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+             default:
+               ret = -EINVAL;
+          }
+          if (ret == 0 && (tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_AUTONEG_MODE ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_LINK_STATUS   ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_PORT_FLOW_CONTROL    ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_PORT_SPEED    ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_PORT_LOOPBACK ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_PORT_DUPLEX_MODE    ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_LINK_STATUS    ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_DUPLEX_STATUS    ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_SPEED_MODE    ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_PORT_STATE||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_GET_PORT_FC_STATE ||
+                           tpm_sw_phy->sw_phy_cmd == MV_TPM_IOCTL_SW_PHY_CONVERT_PORT_INDEX))
+          {
+              if(copy_to_user((tpm_ioctl_sw_phy_t*)arg, tpm_sw_phy, sizeof(tpm_ioctl_sw_phy_t)))
+              {
+                printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                goto ioctlErr;
+              }
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ===== Packet Processor Section === */
+      /* ================================== */
+      case MV_TPM_IOCTL_PP_TM_SECTION:
+      {
+          tpm_ioctl_tm_tm_t *tpm_tm_tm = (tpm_ioctl_tm_tm_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_tm_tm == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_tm_tm;
+
+          if(copy_from_user(tpm_tm_tm, (tpm_ioctl_tm_tm_t*)arg, sizeof(tpm_ioctl_tm_tm_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_tm_tm->pp_tm_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_TM_SET_WAN_EGR_QUE_SCHED ========= */
+              case MV_TPM_IOCTL_TM_SET_WAN_EGR_QUE_SCHED:
+
+                  rcode = tpm_tm_set_wan_egr_queue_sched(tpm_tm_tm->owner_id,
+                                                         tpm_tm_tm->sched_ent,
+                                                         tpm_tm_tm->pp_sched_mode,
+                                                         tpm_tm_tm->queue_id,
+                                                         tpm_tm_tm->wrr_weight);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_TM_SET_WAN_SCHED_EGR_RATE_LIMIT ========= */
+              case MV_TPM_IOCTL_TM_SET_WAN_SCHED_EGR_RATE_LIMIT:
+
+                  rcode = tpm_tm_set_wan_sched_egr_rate_lim(tpm_tm_tm->owner_id,
+                                                            tpm_tm_tm->sched_ent,
+                                                            tpm_tm_tm->rate_limit_val,
+                                                            tpm_tm_tm->bucket_size);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_TM_SET_WAN_QUE_EGR_RATE_LIMIT ========= */
+              case MV_TPM_IOCTL_TM_SET_WAN_QUE_EGR_RATE_LIMIT:
+
+                  rcode = tpm_tm_set_wan_queue_egr_rate_lim(tpm_tm_tm->owner_id,
+                                                            tpm_tm_tm->sched_ent,
+                                                            tpm_tm_tm->queue_id,
+                                                            tpm_tm_tm->rate_limit_val,
+                                                            tpm_tm_tm->bucket_size);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_TM_SET_WAN_INGR_QUE_SCHED  =========*/
+              case MV_TPM_IOCTL_TM_SET_WAN_INGR_QUE_SCHED:
+
+                rcode = tpm_tm_set_wan_ingr_queue_sched(tpm_tm_tm->owner_id,
+                                                        tpm_tm_tm->pp_sched_mode,
+                                                        tpm_tm_tm->queue_id,
+                                                        tpm_tm_tm->wrr_weight);
+                if(rcode != TPM_OK)
+                  goto ioctlErr;
+
+                ret = 0;
+                break;
+
+              /* ====== MV_TPM_IOCTL_TM_SET_WAN_INGR_RATE_LIMIT ========= */
+              case MV_TPM_IOCTL_TM_SET_WAN_INGR_RATE_LIMIT:
+
+                  rcode = tpm_tm_set_wan_ingr_rate_lim(tpm_tm_tm->owner_id,
+                                                       tpm_tm_tm->rate_limit_val,
+                                                       tpm_tm_tm->bucket_size);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_TM_SET_WAN_QUE_INGR_RATE_LIMIT ========= */
+              case MV_TPM_IOCTL_TM_SET_WAN_QUE_INGR_RATE_LIMIT:
+
+                  rcode = tpm_tm_set_wan_q_ingr_rate_lim(tpm_tm_tm->owner_id,
+                                                         tpm_tm_tm->queue_id,
+                                                         tpm_tm_tm->rate_limit_val,
+                                                         tpm_tm_tm->bucket_size);
+                  if(rcode != TPM_OK)
+                    goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_TM_SET_GMAC0_INGR_RATE_LIMIT ========= */
+              case MV_TPM_IOCTL_TM_SET_GMAC0_INGR_RATE_LIMIT:
+
+                  rcode = tpm_tm_set_gmac0_ingr_rate_lim(tpm_tm_tm->owner_id,
+                                                         tpm_tm_tm->rate_limit_val,
+                                                         tpm_tm_tm->bucket_size);
+                  if(rcode != TPM_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== IGMP Section ============== */
+      /* ================================== */
+      case MV_TPM_IOCTL_IGMP_SECTION:
+      {
+          tpm_ioctl_igmp_t *tpm_igmp = (tpm_ioctl_igmp_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_igmp == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_igmp;
+
+          if(copy_from_user(tpm_igmp, (tpm_ioctl_igmp_t*)arg, sizeof(tpm_ioctl_igmp_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_igmp->igmp_cmd)
+          {
+              case MV_TPM_IOCTL_IGMP_SET_PORT_FRWD_MODE:
+                  rcode = tpm_set_port_igmp_frwd_mode(tpm_igmp->src_port, tpm_igmp->frwd_mode);
+                  if(rcode != TPM_OK)
+                     goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_IGMP_GET_PORT_FRWD_MODE:
+                  rcode = tpm_get_port_igmp_frwd_mode(tpm_igmp->src_port, &(tpm_igmp->frwd_mode));
+                  if(rcode != TPM_OK)
+                     goto ioctlErr;
+                  if(copy_to_user((tpm_ioctl_igmp_t*)arg, tpm_igmp, sizeof(tpm_ioctl_igmp_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_IGMP_SET_CPU_RX_Q:
+                  rcode = tpm_set_igmp_cpu_rx_queue(tpm_igmp->cpu_queue);
+                  if(rcode != TPM_OK)
+                     goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_IGMP_GET_CPU_RX_Q:
+                  rcode = tpm_get_igmp_cpu_rx_queue(&(tpm_igmp->cpu_queue));
+                  if(rcode != TPM_OK)
+                     goto ioctlErr;
+                  if(copy_to_user((tpm_ioctl_igmp_t*)arg, tpm_igmp, sizeof(tpm_ioctl_igmp_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_SET_IGMP_PROXY_SA_MAC:
+                  rcode = tpm_set_igmp_proxy_sa_mac(tpm_igmp->sa_mac);
+				  if(rcode != TPM_OK)
+                     goto ioctlErr;
+                  ret = 0;
+                  break;
+
+              case MV_TPM_IOCTL_GET_IGMP_PROXY_SA_MAC:
+                  rcode = tpm_get_igmp_proxy_sa_mac(tpm_igmp->sa_mac);
+				  if(rcode != TPM_OK)
+                     goto ioctlErr;
+                  if(copy_to_user((tpm_ioctl_igmp_t*)arg, tpm_igmp, sizeof(tpm_ioctl_igmp_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== Print Section ============= */
+      /* ================================== */
+      case MV_TPM_IOCTL_PRINT_SECTION:
+      {
+          tpm_ioctl_print_t *tpm_print = (tpm_ioctl_print_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_print == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_print;
+
+          if(copy_from_user(tpm_print, (tpm_ioctl_print_t*)arg, sizeof(tpm_ioctl_print_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_print->print_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_PRINT_ETHER_PORTS ========= */
+              case MV_TPM_IOCTL_PRINT_ETHER_PORTS:
+
+                  tpm_print_etherports();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_TX_MODULES ========= */
+              case MV_TPM_IOCTL_PRINT_TX_MODULES:
+
+                  tpm_print_tx_modules();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_RX_MODULES ========= */
+              case MV_TPM_IOCTL_PRINT_RX_MODULES:
+
+                  tpm_print_rx_modules();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_GMAC_CONFIG ========= */
+              case MV_TPM_IOCTL_PRINT_GMAC_CONFIG:
+
+                  tpm_print_gmac_config();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_GMAC_FUNC ========= */
+              case MV_TPM_IOCTL_PRINT_GMAC_FUNC:
+
+                  tpm_print_gmac_func();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_IGMP ========= */
+              case MV_TPM_IOCTL_PRINT_IGMP:
+
+                  tpm_print_igmp();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_MISC ========= */
+              case MV_TPM_IOCTL_PRINT_MISC:
+
+                  tpm_print_misc();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_OWNERS ========= */
+              case MV_TPM_IOCTL_PRINT_OWNERS:
+
+                  tpm_print_owners();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_VLAN_TYPE ========= */
+              case MV_TPM_IOCTL_PRINT_VLAN_TYPE:
+
+                  tpm_print_vlan_etype();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_VALID_API_SECTIONS ========= */
+              case MV_TPM_IOCTL_PRINT_VALID_API_SECTIONS:
+
+                  tpm_print_valid_api_sections();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_FULL_API_SECTIONS ========= */
+              case MV_TPM_IOCTL_PRINT_FULL_API_SECTIONS:
+
+                  tpm_print_full_api_section(tpm_print->api_section);
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_PNC_SHADOW_RANGE ========= */
+              case MV_TPM_IOCTL_PRINT_PNC_SHADOW_RANGE:
+
+                  tpm_print_pnc_shadow_range(tpm_print->valid,
+                                             tpm_print->start,
+                                             tpm_print->end);
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_VALID_PNC_RANGES ========= */
+              case MV_TPM_IOCTL_PRINT_VALID_PNC_RANGES:
+
+                  tpm_print_valid_pnc_ranges();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_INIT_TABLES ========= */
+              case MV_TPM_IOCTL_PRINT_INIT_TABLES:
+
+                  tpm_print_init_tables();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_MOD2_JUMP_ALL ========= */
+              case MV_TPM_IOCTL_PRINT_MOD2_JUMP_ALL:
+                  tpm_mod2_print_jump_all(tpm_print->gmac);
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_MOD2_MAIN_ALL ========= */
+              case MV_TPM_IOCTL_PRINT_MOD2_MAIN_ALL:
+                  tpm_mod2_print_main_all(tpm_print->gmac);
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_MOD2_CFG ========= */
+              case MV_TPM_IOCTL_PRINT_MOD2_CFG:
+                  tpm_mod2_print_config(tpm_print->gmac);
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_PRINT_MOD2_RULE ========= */
+              case MV_TPM_IOCTL_PRINT_MOD2_RULE:
+                  tpm_mod2_print_rule(tpm_print->gmac,
+                                      tpm_print->entry);
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================== */
+      /* ====== Trace Section ============= */
+      /* ================================== */
+      case MV_TPM_IOCTL_TRACE_SECTION:
+      {
+          tpm_ioctl_trace_t *tpm_trace = (tpm_ioctl_trace_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_trace == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_trace;
+
+          if(copy_from_user(tpm_trace, (tpm_ioctl_trace_t*)arg, sizeof(tpm_ioctl_trace_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_trace->trace_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_TRACE_STATUS ========= */
+              case MV_TPM_IOCTL_TRACE_STATUS:
+
+                  tpm_trace_status_print();
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_TRACE_SET ========= */
+              case MV_TPM_IOCTL_TRACE_SET:
+
+                  tpm_trace_set(tpm_trace->level);
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_TRACE_MODULE_SET ========= */
+              case MV_TPM_IOCTL_TRACE_MODULE_SET:
+
+                  tpm_trace_module_set(tpm_trace->module,
+                                       tpm_trace->flag);
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ================================ */
+      /* ====== MIB Reset Section ======= */
+      /* ================================ */
+      case MV_TPM_IOCTL_RESET_SECTION:
+
+          if(copy_from_user(&tpm_mib_reset_param, (tpm_ioctl_mib_reset_t*)arg, sizeof(tpm_ioctl_mib_reset_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+          rcode = tpm_mib_reset(tpm_mib_reset_param.owner_id, tpm_mib_reset_param.reset_level);
+          if(rcode != TPM_OK)
+            goto ioctlErr;
+
+          ret=0;
+          break;
+
+      /* ================================ */
+      /* ====== ALARM  Section ======= */
+      /* ================================ */
+      case MV_TPM_IOCTL_ALARM_SECTION:
+      {
+          tpm_ioctl_alarm_t *tpm_alarm = (tpm_ioctl_alarm_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_alarm == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_alarm;
+
+          if(copy_from_user(tpm_alarm, (tpm_ioctl_alarm_t*)arg, sizeof(tpm_ioctl_alarm_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+          switch (tpm_alarm->alarm_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_ALARM_GET_ETH_PORT ========= */
+              case MV_TPM_IOCTL_ALARM_GET_ETH_PORT:
+
+                  rcode = tpm_alarm_get_eth_port(tpm_alarm->owner_id, &tpm_alarm->alarm_type, &tpm_alarm->port_bitmap[0][0]);
+                  if(rcode != TPM_OK)
+                     goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_alarm_t*)arg, tpm_alarm, sizeof(tpm_ioctl_alarm_t)))
+                  {
+                    printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                    goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              default:
+                ret = -EINVAL;
+          }
+
+          ret=0;
+          break;
+      }
+
+      /* ================================= */
+      /* ====== TPM PM clear Section   ======= */
+      /* ================================= */
+      case MV_TPM_IOCTL_COUNTER_CLEAR_SECTION:
+      {
+          tpm_ioctl_swport_pm_3_t *tpm_ioctl_swport_pm_3 = (tpm_ioctl_swport_pm_3_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_ioctl_swport_pm_3 == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_ioctl_swport_pm_3;
+
+          if(copy_from_user(tpm_ioctl_swport_pm_3, (tpm_ioctl_swport_pm_3_t *)arg, sizeof(tpm_ioctl_swport_pm_3_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          rc = tpm_sw_clear_port_counter(tpm_ioctl_swport_pm_3->owner_id, tpm_ioctl_swport_pm_3->port);
+          if (rc != TPM_OK)
+            goto ioctlErr;
+
+          ret=0;
+          break;
+      }
+
+      /* ====================================== */
+      /* ====== TPM Data Path Section   ======= */
+      /* ====================================== */
+
+      case MV_TPM_IOCTL_RX_IGMP:
+      {
+          tpm_ioctl_rx_igmp_t *tpm_ioctl_rx_igmp = (tpm_ioctl_rx_igmp_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_l);
+          if (tpm_ioctl_rx_igmp == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_l);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_l_buff = tpm_ioctl_rx_igmp;
+
+          tpm_ioctl_rx_igmp->owner_id = ((tpm_ioctl_rx_igmp_t*)arg)->owner_id;
+
+          rcode = tpm_rx_igmp_frame(  tpm_ioctl_rx_igmp->owner_id,
+                                    &(tpm_ioctl_rx_igmp->src_llid),
+                                    &(tpm_ioctl_rx_igmp->src_port),
+                                      tpm_ioctl_rx_igmp->buf,
+                                    &(tpm_ioctl_rx_igmp->len));
+          if (rcode != TPM_RC_OK)
+            goto ioctlErr;
+
+          ret = 0;
+
+          if(copy_to_user((tpm_ioctl_rx_igmp_t*)arg, tpm_ioctl_rx_igmp, sizeof(tpm_ioctl_rx_igmp_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          break;
+      }
+
+     case MV_TPM_IOCTL_TX_IGMP:
+     {
+         tpm_ioctl_tx_igmp_t *tpm_ioctl_tx_igmp = (tpm_ioctl_tx_igmp_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_l);
+         if (tpm_ioctl_tx_igmp == NULL)
+         {
+           printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_m);
+           ret = -ENOMEM;
+            goto ioctlErr;
+         }
+         mpool_l_buff = tpm_ioctl_tx_igmp;
+
+        if(copy_from_user(tpm_ioctl_tx_igmp, (tpm_ioctl_tx_igmp_t *)arg, sizeof(tpm_ioctl_tx_igmp_t)))
+        {
+          printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+          goto ioctlErr;
+        }
+        rcode = tpm_tx_igmp_frame(tpm_ioctl_tx_igmp->owner_id,
+                                    tpm_ioctl_tx_igmp->tgt_port,
+                                    tpm_ioctl_tx_igmp->tgt_queue,
+                                    tpm_ioctl_tx_igmp->gem_port,
+                                    tpm_ioctl_tx_igmp->buf,
+                                    tpm_ioctl_tx_igmp->len);
+        if (rcode != TPM_RC_OK)
+          goto ioctlErr;
+
+        ret = 0;
+
+        break;
+      }
+
+      /* ================================= */
+      /* ====== APM PM 1 Section   ======= */
+      /* ================================= */
+      case MV_APM_IOCTL_PM_1_SWPORT_SECTION:
+      {
+          tpm_ioctl_swport_pm_1_t *tpm_ioctl_swport_pm_1 = (tpm_ioctl_swport_pm_1_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_ioctl_swport_pm_1 == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_ioctl_swport_pm_1;
+
+          if(copy_from_user(tpm_ioctl_swport_pm_1, (tpm_ioctl_swport_pm_1_t *)arg, sizeof(tpm_ioctl_swport_pm_1_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          rcode = tpm_sw_pm_1_read(  tpm_ioctl_swport_pm_1->owner_id,
+                                     tpm_ioctl_swport_pm_1->port,
+                                   &(tpm_ioctl_swport_pm_1->tpm_swport_pm_1));
+          if(rcode != TPM_OK)
+             goto ioctlErr;
+
+          if(copy_to_user((tpm_ioctl_swport_pm_1_t *)arg, tpm_ioctl_swport_pm_1, sizeof(tpm_ioctl_swport_pm_1_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          ret=0;
+          break;
+      }
+
+      /* ================================= */
+      /* ====== APM PM 3 Section   ======= */
+      /* ================================= */
+      case MV_APM_IOCTL_PM_3_SWPORT_SECTION:
+      {
+          tpm_ioctl_swport_pm_3_t *tpm_ioctl_swport_pm_3 = (tpm_ioctl_swport_pm_3_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_ioctl_swport_pm_3 == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_ioctl_swport_pm_3;
+
+          if(copy_from_user(tpm_ioctl_swport_pm_3, (tpm_ioctl_swport_pm_3_t *)arg, sizeof(tpm_ioctl_swport_pm_3_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          rcode = tpm_sw_pm_3_read(  tpm_ioctl_swport_pm_3->owner_id,
+                                     tpm_ioctl_swport_pm_3->port,
+                                   &(tpm_ioctl_swport_pm_3->tpm_swport_pm_3));
+          if(rcode != TPM_OK)
+             goto ioctlErr;
+
+
+          if(copy_to_user((tpm_ioctl_swport_pm_3_t *)arg, tpm_ioctl_swport_pm_3, sizeof(tpm_ioctl_swport_pm_3_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          ret=0;
+          break;
+      }
+
+  /* ====================================== */
+  /* ====== CPU WAN loopback Section  ===== */
+  /* ====================================== */
+      case MV_TPM_IOCTL_CPU_LPBK_SECTION:
+      {
+          tpm_ioctl_cpu_lpbk_t *tpm_ioctl_cpu_lpbk = (tpm_ioctl_cpu_lpbk_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_ioctl_cpu_lpbk == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_ioctl_cpu_lpbk;
+
+          if(copy_from_user(tpm_ioctl_cpu_lpbk, (tpm_ioctl_cpu_lpbk_t*)arg, sizeof(tpm_ioctl_cpu_lpbk_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_ioctl_cpu_lpbk->cpu_lpbk_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_ADD_CPU_WAN_LPBK ========= */
+              case MV_TPM_IOCTL_ADD_CPU_WAN_LPBK:
+
+                  rcode = tpm_add_cpu_wan_loopback (  tpm_ioctl_cpu_lpbk->owner_id,
+                                                    &(tpm_ioctl_cpu_lpbk->pkt_frwd),
+                                                    &(tpm_ioctl_cpu_lpbk->mod_idx));
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  if(copy_to_user((tpm_ioctl_cpu_lpbk_t*)arg, tpm_ioctl_cpu_lpbk, sizeof(tpm_ioctl_cpu_lpbk_t)))
+                  {
+                      printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                      goto ioctlErr;
+                  }
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_DEL_CPU_WAN_LPBK ========= */
+              case MV_TPM_IOCTL_DEL_CPU_WAN_LPBK:
+
+                  rcode = tpm_del_cpu_wan_loopback (  tpm_ioctl_cpu_lpbk->owner_id,
+                                                    &(tpm_ioctl_cpu_lpbk->pkt_frwd));
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              default:
+                  ret = -EINVAL;
+          }
+          break;
+      }
+
+      /* ======================================= */
+      /* ====== CPU Aging counter Section  ===== */
+      /* ======================================= */
+      case MV_TPM_IOCTL_AGE_COUNT_SECTION:
+      {
+          uint32_t  age_count_cmd;
+
+          /* AGE_COUNT_SECTION uses two structure types, first identify the type */
+          if(copy_from_user(&age_count_cmd, (uint32_t*)arg, sizeof(uint32_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          /* HIT_COUNTERS uses huge buffer pool */
+          if (age_count_cmd == MV_TPM_IOCTL_GET_ALL_HIT_COUNTERS)
+          {
+            tpm_ioctl_pnc_hit_cnt_t *tpm_ioctl_pnc_hit_cnt =
+                (tpm_ioctl_pnc_hit_cnt_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_h);
+            if (tpm_ioctl_pnc_hit_cnt == NULL)
+            {
+                printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", 
+                        __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_h);
+                ret = -ENOMEM;
+                goto ioctlErr;
+            }
+            mpool_h_buff = tpm_ioctl_pnc_hit_cnt;
+
+            /* copy the data from user space */
+            if(copy_from_user(tpm_ioctl_pnc_hit_cnt, (tpm_ioctl_pnc_hit_cnt_t*)arg, sizeof(tpm_ioctl_pnc_hit_cnt_t)))
+            {
+              printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+              goto ioctlErr;
+            }
+
+            rcode = tpm_get_pnc_all_hit_counters (tpm_ioctl_pnc_hit_cnt->owner_id,
+                                                  tpm_ioctl_pnc_hit_cnt->api_type,
+                                                  tpm_ioctl_pnc_hit_cnt->high_thresh_pkts,
+                                                  tpm_ioctl_pnc_hit_cnt->counter_reset,
+                                                 &(tpm_ioctl_pnc_hit_cnt->valid_counters),
+                                                 &(tpm_ioctl_pnc_hit_cnt->count_array[0]));
+
+            if (rcode != TPM_RC_OK)
+                goto ioctlErr;
+
+            ret = 0;
+
+            /* copy back the returned data to user space */
+            if(copy_to_user((tpm_ioctl_pnc_hit_cnt_t*)arg, tpm_ioctl_pnc_hit_cnt, sizeof(tpm_ioctl_pnc_hit_cnt_t)))
+            {
+                printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+                goto ioctlErr;
+            }
+          } /* MV_TPM_IOCTL_GET_ALL_HIT_COUNTERS */
+          else
+          {
+            tpm_ioctl_age_count_t *tpm_ioctl_age_count = 
+                (tpm_ioctl_age_count_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_m);
+            if (tpm_ioctl_age_count == NULL)
+            {
+                printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n",
+                        __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_m);
+                ret = -ENOMEM;
+                goto ioctlErr;
+            }
+            mpool_m_buff = tpm_ioctl_age_count;
+
+          if(copy_from_user(tpm_ioctl_age_count, (tpm_ioctl_age_count_t*)arg, sizeof(tpm_ioctl_age_count_t)))
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+          }
+
+          switch (tpm_ioctl_age_count->age_count_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_GET_LU_ENTRIES ========= */
+              case MV_TPM_IOCTL_GET_LU_ENTRIES:
+
+                  rcode = tpm_get_pnc_lu_entry (tpm_ioctl_age_count->owner_id,
+                                                tpm_ioctl_age_count->api_type,
+                                                tpm_ioctl_age_count->lu_num,
+                                                tpm_ioctl_age_count->lu_reset,
+                                                &(tpm_ioctl_age_count->valid_num),
+                                                &(tpm_ioctl_age_count->count_array[0]),
+                                                &(tpm_ioctl_age_count->unrelated_num));
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SET_LU_COUNT_MASK ========= */
+              case MV_TPM_IOCTL_SET_LU_COUNT_MASK:
+
+                  rcode = tpm_set_pnc_counter_mask (tpm_ioctl_age_count->owner_id,
+                                                    tpm_ioctl_age_count->api_type,
+                                                    tpm_ioctl_age_count->rule_idx,
+                                                    tpm_ioctl_age_count->lu_rule_mask);
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_GET_HIT_COUNT ========= */
+              case MV_TPM_IOCTL_GET_HIT_COUNT:
+
+                  rcode = tpm_get_pnc_hit_count (tpm_ioctl_age_count->owner_id,
+                                                 tpm_ioctl_age_count->api_type,
+                                                 tpm_ioctl_age_count->rule_idx,
+                                                 tpm_ioctl_age_count->hit_reset,
+                                                 &(tpm_ioctl_age_count->hit_count));
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SET_LU_THESHOLD ========= */
+              case MV_TPM_IOCTL_SET_LU_THESHOLD:
+
+                  rcode = tpm_set_pnc_lu_threshold (tpm_ioctl_age_count->owner_id,
+                                                    tpm_ioctl_age_count->api_type,
+                                                    tpm_ioctl_age_count->lu_thresh_pkts);
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_RESET_COUNT_GROUP ========= */
+              case MV_TPM_IOCTL_RESET_COUNT_GROUP:
+
+                  rcode = tpm_reset_pnc_age_group (tpm_ioctl_age_count->owner_id,
+                                                   tpm_ioctl_age_count->api_type);
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              default:
+                  ret = -EINVAL;
+          }
+
+          if (ret == 0 &&
+              (tpm_ioctl_age_count->age_count_cmd == MV_TPM_IOCTL_GET_LU_ENTRIES ||
+               tpm_ioctl_age_count->age_count_cmd == MV_TPM_IOCTL_GET_HIT_COUNT))
+          {
+            if(copy_to_user((tpm_ioctl_age_count_t*)arg, tpm_ioctl_age_count, sizeof(tpm_ioctl_age_count_t)))
+            {
+              printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__);
+              goto ioctlErr;
+            }
+          }
+        }
+        break;
+      } /* MV_TPM_IOCTL_AGE_COUNT_SECTION */
+
+      /* ======================================= */
+      /* ====== MC VLAN Section  ===== */
+      /* ======================================= */
+      case MV_TPM_IOCTL_MC_VLAN_SECTION:
+      {
+          tpm_ioctl_mc_vid_t *tpm_ioctl_mc_vid = (tpm_ioctl_mc_vid_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+          if (tpm_ioctl_mc_vid == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_s_buff = tpm_ioctl_mc_vid;
+
+          if(copy_from_user(tpm_ioctl_mc_vid, (tpm_ioctl_mc_vid_t*)arg, sizeof(tpm_ioctl_mc_vid_t)))
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+              goto ioctlErr;
+          }
+
+          switch (tpm_ioctl_mc_vid->mc_vid_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_SET_MC_VID_PORT_VIDS ========= */
+              case MV_TPM_IOCTL_SET_MC_VID_PORT_VIDS:
+
+                  rcode = tpm_set_mc_vid_port_vids(  tpm_ioctl_mc_vid->owner_id,
+                                                     tpm_ioctl_mc_vid->mc_vid,
+                                                   &(tpm_ioctl_mc_vid->port_vid_set));
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              default:
+                  ret = -EINVAL;
+          }
+
+          break;
+      }
+
+      /* ======================================= */
+      /* ====== MC VLAN Section  ===== */
+      /* ======================================= */
+      case MV_TPM_IOCTL_MTU_SECTION:
+      {
+          tpm_ioctl_mtu_t *tpm_ioctl_mtu = (tpm_ioctl_mtu_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_m);
+          if (tpm_ioctl_mtu == NULL)
+          {
+            printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_m);
+            ret = -ENOMEM;
+            goto ioctlErr;
+          }
+          mpool_m_buff = tpm_ioctl_mtu;
+
+          if(copy_from_user(tpm_ioctl_mtu, (tpm_ioctl_mtu_t*)arg, sizeof(tpm_ioctl_mtu_t)))
+          {
+              printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+              goto ioctlErr;
+          }
+
+          switch (tpm_ioctl_mtu->mtu_setting_cmd)
+          {
+              /* ====== MV_TPM_IOCTL_SET_MTU_ADMIN ========= */
+              case MV_TPM_IOCTL_SET_MTU_ADMIN:
+
+                  rcode = tpm_db_set_mtu_enable(  tpm_ioctl_mtu->enable);
+
+                  if (rcode != TPM_DB_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+              /* ====== MV_TPM_IOCTL_SET_MTU ========= */
+              case MV_TPM_IOCTL_SET_MTU:
+
+                  rcode = tpm_proc_set_mtu(tpm_ioctl_mtu->ethertype,
+                                           tpm_ioctl_mtu->direction,
+                                           tpm_ioctl_mtu->mtu);
+
+                  if (rcode != TPM_RC_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+
+              /* ====== MV_TPM_IOCTL_SET_PPPOE_MTU ========= */
+              case MV_TPM_IOCTL_SET_PPPOE_MTU:
+
+                  rcode = tpm_proc_set_pppoe_mtu(tpm_ioctl_mtu->ethertype,
+                                                 tpm_ioctl_mtu->direction,
+                                                 tpm_ioctl_mtu->pppoe_mtu);
+
+                  if (rcode != TPM_DB_OK)
+                      goto ioctlErr;
+
+                  ret = 0;
+                  break;
+              default:
+                  ret = -EINVAL;
+          }
+
+          break;
+      }
+
+  /* ====== TPM SELF CHECK Section  ===== */
+  case MV_TPM_IOCTL_TPM_CHECK_SECTION:
+  {
+	tpm_ioctl_tpm_check_t *tpm_ioctl_tpm_check = (tpm_ioctl_tpm_check_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+	if (NULL == tpm_ioctl_tpm_check) {
+		printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+		ret = -ENOMEM;
+		goto ioctlErr;
+	}
+	mpool_s_buff = tpm_ioctl_tpm_check;
+  	if(copy_from_user(tpm_ioctl_tpm_check, (tpm_ioctl_tpm_check_t*)arg, sizeof(tpm_ioctl_tpm_check_t)))
+        {
+            printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+            goto ioctlErr;
+        }
+        rcode = tpm_rule_self_check(tpm_ioctl_tpm_check->owner_id, tpm_ioctl_tpm_check->check_level);
+        if(rcode != TPM_OK)
+          goto ioctlErr;
+
+        ret=0;
+        break;
+  }
+
+  case MV_TPM_IOCTL_FLUSH_ATU_SECTION:
+  {
+	tpm_ioctl_flush_atu_t *tpm_ioctl_flush_atu = (tpm_ioctl_flush_atu_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+	if (NULL == tpm_ioctl_flush_atu) {
+		printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+		ret = -ENOMEM;
+		goto ioctlErr;
+	}
+	mpool_s_buff = tpm_ioctl_flush_atu;
+	if (copy_from_user(tpm_ioctl_flush_atu, (tpm_ioctl_flush_atu_t*)arg, sizeof(tpm_ioctl_flush_atu_t))) {
+		printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+		goto ioctlErr;
+	}
+	rcode = tpm_flush_atu(tpm_ioctl_flush_atu->owner_id, tpm_ioctl_flush_atu->flush_type, tpm_ioctl_flush_atu->db_num);
+	if (rcode != TPM_OK)
+          goto ioctlErr;
+
+        ret = 0;
+	break;
+  }
+
+  case MV_TPM_IOCTL_FLUSH_VTU_SECTION:
+  {
+	tpm_ioctl_flush_vtu_t *tpm_ioctl_flush_vtu = (tpm_ioctl_flush_vtu_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+	if (NULL == tpm_ioctl_flush_vtu) {
+		printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+		ret = -ENOMEM;
+		goto ioctlErr;
+	}
+	mpool_s_buff = tpm_ioctl_flush_vtu;
+	if (copy_from_user(tpm_ioctl_flush_vtu, (tpm_ioctl_flush_vtu_t*)arg, sizeof(tpm_ioctl_flush_vtu_t))) {
+		printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+		goto ioctlErr;
+	}
+	rcode = tpm_flush_vtu(tpm_ioctl_flush_vtu->owner_id);
+	if (rcode != TPM_OK)
+          goto ioctlErr;
+
+        ret = 0;
+	break;
+  }
+
+  case MV_TPM_IOCTL_SET_IPV6_CM_PARSE_WIN_SECTION:
+  {
+      tpm_ioctl_ipv6_parse_window_t *ipv6_parse_window = (tpm_ioctl_ipv6_parse_window_t *) tpm_common_mempool_alloc(tpm_ioctl_mpools.mpool_s);
+      if (NULL == ipv6_parse_window) {
+          printk(KERN_ERR "ERROR: (%s:%d) tpm_common_mempool_alloc(%p) failed\n", __FUNCTION__, __LINE__, tpm_ioctl_mpools.mpool_s);
+          ret = -ENOMEM;
+          goto ioctlErr;
+      }
+      mpool_s_buff = ipv6_parse_window;
+      if (copy_from_user(ipv6_parse_window, (tpm_ioctl_ipv6_parse_window_t*)arg, sizeof(tpm_ioctl_ipv6_parse_window_t))) {
+          printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+          goto ioctlErr;
+      }
+      rcode = tpm_ctc_cm_set_ipv6_parse_window(ipv6_parse_window->owner_id, ipv6_parse_window->ipv6_parse_window);
+      if (rcode != TPM_OK)
+          goto ioctlErr;
+
+      ret = 0;
+      break;
+  }
+
+  default:
+        ret = -EINVAL;
+  }
+
+ioctlErr:
+    if (mpool_s_buff != NULL)
+        tpm_common_mempool_free(tpm_ioctl_mpools.mpool_s, mpool_s_buff);
+    else if (mpool_m_buff != NULL)
+        tpm_common_mempool_free(tpm_ioctl_mpools.mpool_m, mpool_m_buff);
+    else if (mpool_l_buff != NULL)
+        tpm_common_mempool_free(tpm_ioctl_mpools.mpool_l, mpool_l_buff);
+    else if (mpool_h_buff != NULL)
+        tpm_common_mempool_free(tpm_ioctl_mpools.mpool_h, mpool_h_buff);
+    else if (tpm_initp != NULL)
+        kfree(tpm_initp);
+
+    return(ret);
+}
+
+/*******************************************************************************
+**
+**  mv_tpm_cdev_open
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function opens the TPM Char device
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+int mv_tpm_cdev_open(struct inode *inode, struct file *filp)
+{
+  tpm_module_cdev_t *dev;
+
+  //if (deviceOpen)
+  //  return(-EBUSY);
+
+  deviceOpen++;
+  try_module_get(THIS_MODULE);
+
+  /* find the device structure */
+  dev = container_of(inode->i_cdev, tpm_module_cdev_t, cdev);
+  filp->private_data = dev;
+
+  return(0);
+}
+
+/*******************************************************************************
+**
+**  mv_tpm_cdev_release
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function releases the TPM Char device
+**
+**  PARAMETERS:  struct inode *inode
+**               struct file *filp
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     (0)
+**
+*******************************************************************************/
+int mv_tpm_cdev_release(struct inode *inode, struct file *filp)
+{
+  deviceOpen--;
+  module_put(THIS_MODULE);
+
+  return(0);
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+/*******************************************************************************
+**  mv_tpm_cdev_read
+**  ___________________________________________________________________________
+**
+**  DESCRIPTION: The function waites for data to be written to tpm_sfs_2_ioctl_command
+**               and copies it to user space to be used by IOCTLed
+**
+**  PARAMETERS:  struct file *file- file descriptor
+**               char __user *buf-  user buffer
+**               size_t count-      user buffer byte size
+**
+**  OUTPUTS:    loff_t *ppos-      position in file
+**
+**  RETURNS:    number of bytes read
+**
+*******************************************************************************/
+static ssize_t mv_tpm_cdev_read(struct file *file, char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+    int val;
+
+    val = down_interruptible(&tpm_sfs_2_ioctl_sem);
+    if (val != 0)
+    {
+        return val;
+    }
+
+    if(copy_to_user(buf, &tpm_sfs_2_ioctl_command, sizeof(tpm_ioctl_mng_t)))
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) copy_from_user failed\n", __FUNCTION__, __LINE__);
+        return -EFAULT;
+    }
+
+    return sizeof(tpm_ioctl_mng_t);
+}
+#endif
+
+/*******************************************************************************
+**  TPM device operations
+*******************************************************************************/
+struct file_operations tpmCdevFops =
+{
+  .owner   = THIS_MODULE,
+  .open    = mv_tpm_cdev_open,
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+  .read    = mv_tpm_cdev_read,
+#endif
+  .release = mv_tpm_cdev_release,
+  .ioctl   = mv_tpm_cdev_ioctl
+};
+
+/*******************************************************************************
+**  tpm_init_ioctl_mempools
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function allocates 3 memory pools for IOCTL operations
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     TPM_OK or TPM_FAIL
+**
+*******************************************************************************/
+static int32_t tpm_init_ioctl_mempools(void)
+{
+    if (tpm_ioctl_mpools.mpool_s == NULL){
+        uint32_t i;
+        uint32_t max_val= 0;
+        uint32_t struct_size[]= {
+            sizeof(tpm_setup_t),                sizeof(tpm_ioctl_admin_t),          sizeof(tpm_ioctl_add_acl_rule_t),
+            sizeof(tpm_ioctl_del_acl_rule_t),   sizeof(tpm_ioctl_ctrl_acl_rule_t),  sizeof(tpm_ioctl_mc_rule_t),
+            sizeof(tpm_ioctl_mng_ch_t),         sizeof(tpm_ioctl_sw_mac_security_t),sizeof(tpm_ioctl_sw_vlan_filter_t),
+            sizeof(tpm_ioctl_sw_tm_t),          sizeof(tpm_ioctl_sw_phy_t),         sizeof(tpm_ioctl_tm_tm_t),
+            sizeof(tpm_ioctl_print_t),          sizeof(tpm_ioctl_trace_t),          sizeof(tpm_ioctl_igmp_t),
+            sizeof(tpm_ioctl_alarm_t),          sizeof(tpm_ioctl_swport_pm_1_t),    sizeof(tpm_ioctl_swport_pm_3_t),
+            sizeof(tpm_ioctl_cpu_lpbk_t),       sizeof(tpm_ioctl_mtu_t),            sizeof(tpm_ioctl_mc_vid_t),
+            0 };
+
+        /* find the max truct size */
+        for (i=0; struct_size[i] != 0; i++){
+            printk(KERN_DEBUG "struct_size[%d] = %d\n", i, struct_size[i]);
+            if (struct_size[i] > max_val)
+                max_val= struct_size[i];
+        }
+
+        /* validate that max_val does not exceed threashold */
+        if (max_val > MPOOL_S_MAX_BUFF_SIZE){
+            printk(KERN_ERR "ERROR: (%s:%d) requested buffer size is too large %d/%d (requested/max_val)\n",
+                   __FUNCTION__, __LINE__, max_val, MPOOL_S_MAX_BUFF_SIZE);
+            return TPM_FAIL;
+        }
+
+        tpm_ioctl_mpools.mpool_s = tpm_common_mempool_create(i, max_val, GFP_USER);
+        if (NULL == tpm_ioctl_mpools.mpool_s){
+            printk(KERN_ERR "ERROR: (%s:%d) failed allocating tpm_ioctl_mpools.mpool_s\n",
+                   __FUNCTION__, __LINE__);
+            return TPM_FAIL;
+        }
+        printk(KERN_INFO "(%s:%d) init tpm_ioctl_mpools.mpool_s, number_of_entries=%d, entry_size=%d pool=0x%p\n",
+               __FUNCTION__, __LINE__, i, max_val, tpm_ioctl_mpools.mpool_s);
+    }
+
+    if (tpm_ioctl_mpools.mpool_m == NULL){
+        uint32_t i;
+        uint32_t max_val= 0;
+        uint32_t struct_size[]= {
+            sizeof(tpm_ioctl_get_mod_rule_t),   sizeof(tpm_ioctl_age_count_t),  0 };
+
+        /* find the max truct size */
+        for (i=0; struct_size[i] != 0; i++){
+            printk(KERN_DEBUG "struct_size[%d] = %d\n", i, struct_size[i]);
+            if (struct_size[i] > max_val)
+                max_val= struct_size[i];
+        }
+
+        /* validate that max_val does not exceed threashold */
+        if (max_val > MPOOL_M_MAX_BUFF_SIZE){
+            printk(KERN_ERR "ERROR: (%s:%d) requested buffer size is too large %d/%d (requested/max_val)\n",
+                   __FUNCTION__, __LINE__, max_val, MPOOL_M_MAX_BUFF_SIZE);
+            return TPM_FAIL;
+        }
+
+        tpm_ioctl_mpools.mpool_m = tpm_common_mempool_create(i, max_val, GFP_USER);
+        if (NULL == tpm_ioctl_mpools.mpool_m){
+            printk(KERN_ERR "ERROR: (%s:%d) failed allocating tpm_ioctl_mpools.mpool_m\n",
+                   __FUNCTION__, __LINE__);
+            return TPM_FAIL;
+        }
+        printk(KERN_INFO "(%s:%d) init tpm_ioctl_mpools.mpool_m, number_of_entries=%d, entry_size=%d pool=0x%p\n",
+               __FUNCTION__, __LINE__, i, max_val, tpm_ioctl_mpools.mpool_m);
+    }
+
+    if (tpm_ioctl_mpools.mpool_l == NULL){
+        uint32_t i;
+        uint32_t max_val= 0;
+        uint32_t struct_size[]= {
+            sizeof(tpm_ioctl_tx_igmp_t),        sizeof(tpm_ioctl_rx_igmp_t),    0 };
+
+        /* find the max truct size */
+        for (i=0; struct_size[i] != 0; i++){
+            printk(KERN_DEBUG "struct_size[%d] = %d\n", i, struct_size[i]);
+            if (struct_size[i] > max_val)
+                max_val= struct_size[i];
+        }
+
+        /* validate that max_val does not exceed threashold */
+        if (max_val > MPOOL_L_MAX_BUFF_SIZE){
+            printk(KERN_ERR "ERROR: (%s:%d) requested buffer size is too large %d/%d (requested/max_val)\n",
+                   __FUNCTION__, __LINE__, max_val, MPOOL_L_MAX_BUFF_SIZE);
+            return TPM_FAIL;
+        }
+
+        tpm_ioctl_mpools.mpool_l = tpm_common_mempool_create(i, max_val, GFP_USER);
+        if (NULL == tpm_ioctl_mpools.mpool_l){
+            printk(KERN_ERR "ERROR: (%s:%d) failed allocating tpm_ioctl_mpools.mpool_l\n",
+                   __FUNCTION__, __LINE__);
+            return TPM_FAIL;
+        }
+        printk(KERN_INFO "(%s:%d) init tpm_ioctl_mpools.mpool_l, number_of_entries=%d, entry_size=%d pool=0x%p\n",
+               __FUNCTION__, __LINE__, i, max_val, tpm_ioctl_mpools.mpool_l);
+    }
+
+    if (tpm_ioctl_mpools.mpool_h == NULL){
+        uint32_t i;
+        uint32_t max_val= 0;
+        uint32_t struct_size[]= {
+            sizeof(tpm_ioctl_pnc_hit_cnt_t),    0 };
+
+        /* find the max truct size */
+        for (i=0; struct_size[i] != 0; i++){
+            printk(KERN_DEBUG "struct_size[%d] = %d\n", i, struct_size[i]);
+            if (struct_size[i] > max_val)
+                max_val= struct_size[i];
+        }
+
+        /* validate that max_val does not exceed threashold */
+        if (max_val > MPOOL_H_MAX_BUFF_SIZE){
+            printk(KERN_ERR "ERROR: (%s:%d) Huge mempool requested buffer size is too large %d/%d (requested/max_val)\n",
+                   __FUNCTION__, __LINE__, max_val, MPOOL_L_MAX_BUFF_SIZE);
+            return TPM_FAIL;
+        }
+
+        tpm_ioctl_mpools.mpool_h = tpm_common_mempool_create(i, max_val, GFP_USER);
+        if (NULL == tpm_ioctl_mpools.mpool_h){
+            printk(KERN_ERR "ERROR: (%s:%d) failed allocating tpm_ioctl_mpools.mpool_h\n",
+                   __FUNCTION__, __LINE__);
+            return TPM_FAIL;
+        }
+        printk(KERN_INFO "(%s:%d) init tpm_ioctl_mpools.mpool_h, number_of_entries=%d, entry_size=%d pool=0x%p\n",
+               __FUNCTION__, __LINE__, i, max_val, tpm_ioctl_mpools.mpool_h);
+    }
+
+    return TPM_OK;
+}
+
+
+/*******************************************************************************
+**
+**  tpm_destroy_ioctl_mempools
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function destroys 3 pool memory for IOCTL operations
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     TPM_OK or TPM_FAIL
+**
+*******************************************************************************/
+static int32_t tpm_destroy_ioctl_mempools(void)
+{
+      if (tpm_ioctl_mpools.mpool_s != NULL){
+        tpm_common_mempool_destroy(tpm_ioctl_mpools.mpool_s);
+        tpm_ioctl_mpools.mpool_s = NULL;
+      }
+      if (tpm_ioctl_mpools.mpool_m != NULL){
+        tpm_common_mempool_destroy(tpm_ioctl_mpools.mpool_m);
+        tpm_ioctl_mpools.mpool_m = NULL;
+      }
+      if (tpm_ioctl_mpools.mpool_l != NULL){
+        tpm_common_mempool_destroy(tpm_ioctl_mpools.mpool_l);
+        tpm_ioctl_mpools.mpool_l = NULL;
+      }
+      if (tpm_ioctl_mpools.mpool_h != NULL){
+        tpm_common_mempool_destroy(tpm_ioctl_mpools.mpool_h);
+        tpm_ioctl_mpools.mpool_h = NULL;
+      }
+      return TPM_OK;
+}
+
+/*******************************************************************************
+**
+**  tpm_module_mng_if_create
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function create management interface - char device
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     TPM_OK or TPM_FAIL
+**
+*******************************************************************************/
+int32_t tpm_module_mng_if_create(void)
+{
+  int   rcode;
+  dev_t dev;
+
+  dev   = MKDEV(MV_TPM_MAJOR, 0);
+  rcode = register_chrdev_region(dev, TPM_NUM_DEVICES, TPM_DEV_NAME);
+  if(rcode < 0)
+  {
+    printk(KERN_ERR "ERROR: (%s:%d) Pon Char Device\n", __FUNCTION__, __LINE__);
+    return(TPM_FAIL);
+  }
+  /* initialize ioctl mempools */
+  if (tpm_init_ioctl_mempools() != TPM_OK)
+    return(TPM_FAIL);
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+  /* initialize ioctl debug semaphore, used for signalling between user space and sysfs  */
+  sema_init(&tpm_sfs_2_ioctl_sem, 0);
+#endif
+
+  cdev_init(&tpm_dev.cdev, &tpmCdevFops);
+  tpm_dev.cdev.owner = THIS_MODULE;
+  tpm_dev.cdev.ops   = &tpmCdevFops;
+
+  rcode = cdev_add(&tpm_dev.cdev, dev, 1);
+  if(rcode < 0)
+  {
+    printk(KERN_ERR "ERROR: (%s:%d) Gpon Char Device Add\n", __FUNCTION__, __LINE__);
+
+    cdev_del(&tpm_dev.cdev);
+    unregister_chrdev_region(dev, TPM_NUM_DEVICES);
+
+    return(TPM_FAIL);
+  }
+
+  /* create device for udev */
+  tpm_udev_class = class_create(THIS_MODULE, TPM_DEV_NAME);
+  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+    tpm_udev_dev   = device_create(tpm_udev_class, NULL, dev, TPM_DEV_NAME);
+  #else
+      tpm_udev_dev   = device_create(tpm_udev_class, NULL, dev, NULL, TPM_DEV_NAME);
+  #endif
+  return(TPM_OK);
+}
+
+/*******************************************************************************
+**
+**  tpm_module_mng_if_release
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function release management interface - char device
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     TPM_OK or TPM_FAIL
+**
+*******************************************************************************/
+int32_t tpm_module_mng_if_release(void)
+{
+  dev_t dev = MKDEV(MV_TPM_MAJOR, 0);
+
+  if (tpm_destroy_ioctl_mempools() != TPM_OK)
+    return(TPM_FAIL);
+
+  device_destroy(tpm_udev_class, dev);
+  class_unregister(tpm_udev_class);
+  class_destroy(tpm_udev_class);
+
+  unregister_chrdev_region(dev, TPM_NUM_DEVICES);
+
+  return(MV_OK);
+}
+
+
+EXPORT_SYMBOL(tpm_sw_add_static_mac);
+EXPORT_SYMBOL(tpm_sw_del_static_mac);
+EXPORT_SYMBOL(tpm_sw_set_port_max_macs);
+EXPORT_SYMBOL(tpm_sw_set_mac_age_time);
+EXPORT_SYMBOL(tpm_sw_get_mac_age_time);
+EXPORT_SYMBOL(tpm_sw_set_mac_learn);
+EXPORT_SYMBOL(tpm_sw_get_mac_learn);
+EXPORT_SYMBOL(tpm_set_mtu_size);
+EXPORT_SYMBOL(tpm_get_mtu_size);
+//EXPORT_SYMBOL(tpm_sw_set_port_flooding);
+//EXPORT_SYMBOL(tpm_sw_get_port_flooding);
+EXPORT_SYMBOL(tpm_sw_clear_dynamic_mac);
+EXPORT_SYMBOL(tpm_sw_set_port_mirror);
+EXPORT_SYMBOL(tpm_sw_get_port_mirror);
+EXPORT_SYMBOL(tpm_sw_set_isolate_eth_port_vector);
+EXPORT_SYMBOL(tpm_sw_get_isolate_eth_port_vector);
+EXPORT_SYMBOL(tpm_sw_set_port_tagged);
+EXPORT_SYMBOL(tpm_sw_set_port_untagged);
+EXPORT_SYMBOL(tpm_sw_set_port_def_vlan);
+EXPORT_SYMBOL(tpm_sw_get_port_def_vlan);
+EXPORT_SYMBOL(tpm_sw_set_port_def_pri);
+EXPORT_SYMBOL(tpm_sw_get_port_def_pri);
+EXPORT_SYMBOL(tpm_sw_port_add_vid);
+EXPORT_SYMBOL(tpm_sw_clear_vid_per_port);
+EXPORT_SYMBOL(tpm_sw_add_all_vid_per_port);
+EXPORT_SYMBOL(tpm_sw_port_add_vid_group);
+EXPORT_SYMBOL(tpm_sw_port_del_vid_group);
+EXPORT_SYMBOL(tpm_sw_set_port_vid_egress_mode);
+EXPORT_SYMBOL(tpm_sw_port_del_vid);
+EXPORT_SYMBOL(tpm_sw_port_set_vid_filter);
+EXPORT_SYMBOL(tpm_sw_set_uni_sched);
+EXPORT_SYMBOL(tpm_sw_set_uni_q_weight);
+EXPORT_SYMBOL(tpm_sw_set_uni_ingr_police_rate);
+EXPORT_SYMBOL(tpm_sw_get_uni_ingr_police_rate);
+EXPORT_SYMBOL(tpm_sw_set_uni_tc_ingr_police_rate);
+EXPORT_SYMBOL(tpm_sw_set_uni_egr_rate_limit);
+EXPORT_SYMBOL(tpm_sw_get_uni_egr_rate_limit);
+EXPORT_SYMBOL(tpm_phy_convert_port_index);
+EXPORT_SYMBOL(tpm_phy_set_port_autoneg_mode);
+EXPORT_SYMBOL(tpm_phy_get_port_autoneg_mode);
+EXPORT_SYMBOL(tpm_phy_restart_port_autoneg);
+EXPORT_SYMBOL(tpm_phy_set_port_admin_state);
+EXPORT_SYMBOL(tpm_phy_get_port_admin_state);
+EXPORT_SYMBOL(tpm_phy_set_port_flow_control_support);
+EXPORT_SYMBOL(tpm_phy_get_port_flow_control_support);
+EXPORT_SYMBOL(tpm_phy_get_port_flow_control_state);
+EXPORT_SYMBOL(tpm_phy_get_port_link_status);
+EXPORT_SYMBOL(tpm_phy_get_port_duplex_status);
+EXPORT_SYMBOL(tpm_phy_get_port_speed_mode);
+EXPORT_SYMBOL(tpm_phy_set_port_loopback);
+EXPORT_SYMBOL(tpm_phy_get_port_loopback);
+EXPORT_SYMBOL(tpm_phy_set_port_duplex_mode);
+EXPORT_SYMBOL(tpm_phy_get_port_duplex_mode);
+EXPORT_SYMBOL(tpm_phy_set_port_speed);
+EXPORT_SYMBOL(tpm_phy_get_port_speed);
+EXPORT_SYMBOL(tpm_alarm_get_eth_port);
+EXPORT_SYMBOL(tpm_sw_pm_1_read);
+EXPORT_SYMBOL(tpm_sw_pm_3_read);
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.h
new file mode 100755
index 0000000..ce4787c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_mng_if.h
@@ -0,0 +1,1048 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+        this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#ifndef _TPM_MNG_IF_H_
+#define _TPM_MNG_IF_H_
+
+/* Include Files
+------------------------------------------------------------------------------*/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define TPM_NUM_DEVICES     (1)
+#define TPM_DEV_NAME        ("tpm")
+#define MV_TPM_IOCTL_MAGIC  ('T')
+
+#define MAX_ETH_PORT_ALARM 10
+#define MAX_FRAME_SIZE     1600
+
+#define MV_TPM_IOCTL_INIT_SECTION          _IOW(MV_TPM_IOCTL_MAGIC,   1, unsigned int)
+#define MV_TPM_IOCTL_ADMIN_SECTION         _IOWR(MV_TPM_IOCTL_MAGIC,  2, unsigned int)
+#define MV_TPM_IOCTL_ADD_ACL_SECTION       _IOW(MV_TPM_IOCTL_MAGIC,   3, unsigned int)
+#define MV_TPM_IOCTL_DEL_ACL_SECTION       _IOW(MV_TPM_IOCTL_MAGIC,   4, unsigned int)
+#define MV_TPM_IOCTL_CTRL_ACL_SECTION      _IOWR(MV_TPM_IOCTL_MAGIC,  5, unsigned int)
+#define MV_TPM_IOCTL_MC_STREAM_SECTION     _IOW(MV_TPM_IOCTL_MAGIC,   6, unsigned int)
+#define MV_TPM_IOCTL_MNG_SECTION           _IOWR(MV_TPM_IOCTL_MAGIC,  7, unsigned int)
+#define MV_TPM_IOCTL_SW_SECURITY_SECTION   _IOW(MV_TPM_IOCTL_MAGIC,   8, unsigned int)
+#define MV_TPM_IOCTL_SW_VLAN_SECTION       _IOW(MV_TPM_IOCTL_MAGIC,   9, unsigned int)
+#define MV_TPM_IOCTL_SW_TM_SECTION         _IOW(MV_TPM_IOCTL_MAGIC,  10, unsigned int)
+#define MV_TPM_IOCTL_IGMP_SECTION          _IOW(MV_TPM_IOCTL_MAGIC,  11, unsigned int)
+#define MV_TPM_IOCTL_PP_TM_SECTION         _IOW(MV_TPM_IOCTL_MAGIC,  12, unsigned int)
+#define MV_TPM_IOCTL_PRINT_SECTION         _IOW(MV_TPM_IOCTL_MAGIC,  13, unsigned int)
+#define MV_TPM_IOCTL_TRACE_SECTION         _IOW(MV_TPM_IOCTL_MAGIC,  14, unsigned int)
+#define MV_TPM_IOCTL_SW_PHY_SECTION        _IOW(MV_TPM_IOCTL_MAGIC,  15, unsigned int)
+#define MV_TPM_IOCTL_RESET_SECTION         _IOW(MV_TPM_IOCTL_MAGIC,  16, unsigned int)
+#define MV_TPM_IOCTL_ALARM_SECTION         _IOW(MV_TPM_IOCTL_MAGIC,  17, unsigned int)
+#define MV_TPM_IOCTL_COUNTER_CLEAR_SECTION _IOW(MV_TPM_IOCTL_MAGIC,  18, unsigned int)
+#define MV_TPM_IOCTL_GET_MOD_SECTION       _IOWR(MV_TPM_IOCTL_MAGIC, 19, unsigned int)
+#define MV_TPM_IOCTL_RX_IGMP               _IOWR(MV_TPM_IOCTL_MAGIC, 20, unsigned int)
+#define MV_TPM_IOCTL_TX_IGMP               _IOW(MV_TPM_IOCTL_MAGIC,  21, unsigned int)
+#define MV_TPM_IOCTL_SETUP_SECTION         _IOW(MV_TPM_IOCTL_MAGIC,  22, unsigned int)
+#define MV_TPM_IOCTL_CPU_LPBK_SECTION      _IOWR(MV_TPM_IOCTL_MAGIC, 23, unsigned int)
+#define MV_TPM_IOCTL_AGE_COUNT_SECTION     _IOWR(MV_TPM_IOCTL_MAGIC, 24, unsigned int)
+#define MV_TPM_IOCTL_MC_VLAN_SECTION       _IOWR(MV_TPM_IOCTL_MAGIC, 25, unsigned int)
+#define MV_TPM_IOCTL_MTU_SECTION           _IOWR(MV_TPM_IOCTL_MAGIC, 26, unsigned int)
+#define MV_TPM_IOCTL_TPM_CHECK_SECTION     _IOW(MV_TPM_IOCTL_MAGIC,  27, unsigned int)
+#define MV_TPM_IOCTL_FLUSH_ATU_SECTION     _IOWR(MV_TPM_IOCTL_MAGIC, 28, unsigned int)
+#define MV_TPM_IOCTL_FLUSH_VTU_SECTION     _IOWR(MV_TPM_IOCTL_MAGIC, 29, unsigned int)
+#define MV_TPM_IOCTL_SET_IPV6_CM_PARSE_WIN_SECTION     _IOWR(MV_TPM_IOCTL_MAGIC, 30, unsigned int)
+
+
+#define MV_APM_IOCTL_MAGIC  ('A')
+
+#define MV_APM_IOCTL_PM_1_SWPORT_SECTION   _IOWR(MV_APM_IOCTL_MAGIC,  1, unsigned int)
+#define MV_APM_IOCTL_PM_3_SWPORT_SECTION   _IOWR(MV_APM_IOCTL_MAGIC,  2, unsigned int)
+
+
+/* Enums
+------------------------------------------------------------------------------*/
+
+typedef enum tpm_ioctl_cmd_type
+{
+    MV_TPM_IOCTL_INIT =  1,
+    MV_TPM_IOCTL_CRT_OWNER,
+    MV_TPM_IOCTL_REQ_API_G_OWNER,
+    MV_TPM_IOCTL_GET_API_G_OWNER,
+    MV_TPM_IOCTL_DEL_SECTION,
+    MV_TPM_IOCTL_GET_SECTION_SIZE,
+    MV_TPM_IOCTL_ADD_L2_ACL_RULE,
+    MV_TPM_IOCTL_ADD_L3_ACL_RULE,
+    MV_TPM_IOCTL_ADD_IPv4_ACL_RULE,
+    MV_TPM_IOCTL_DEL_L2_ACL_RULE,
+    MV_TPM_IOCTL_DEL_L3_ACL_RULE,
+    MV_TPM_IOCTL_DEL_IPv4_ACL_RULE,
+    MV_TPM_IOCTL_GET_NEXT_VALID_RULE,
+    MV_TPM_IOCTL_ADD_IPv4_MC_STREAM,
+    MV_TPM_IOCTL_MOD_IPv4_MC_STREAM,
+    MV_TPM_IOCTL_DEL_IPv4_MC_STREAM,
+    MV_TPM_IOCTL_ADD_OMCI_CHNL,
+    MV_TPM_IOCTL_DEL_OMCI_CHNL,
+    MV_TPM_IOCTL_GET_OMCI_CHNL,
+    MV_TPM_IOCTL_ADD_OAM_CHNL,
+    MV_TPM_IOCTL_DEL_OAM_CHNL,
+    MV_TPM_IOCTL_GET_OAM_CHNL,
+    MV_TPM_IOCTL_SW_ADD_STATIC_MAC,
+    MV_TPM_IOCTL_SW_DEL_STATIC_MAC,
+    MV_TPM_IOCTL_SW_SET_PORT_MAC_LIMIT,
+    MV_TPM_IOCTL_SW_SET_PORT_FLOOD,
+    MV_TPM_IOCTL_SW_SET_PORT_TAGGED,
+    MV_TPM_IOCTL_SW_SET_PORT_UNTAGGED,
+    MV_TPM_IOCTL_SW_PORT_ADD_VID,
+    MV_TPM_IOCTL_SW_PORT_DEL_VID,
+    MV_TPM_IOCTL_SW_PORT_SER_VID_FILTER,
+    MV_TPM_IOCTL_SW_SET_UNI_SCHED,
+    MV_TPM_IOCTL_SW_UNI_QUE_WEIGHT,
+    MV_TPM_IOCTL_SW_SET_UNI_INGR_POLICE_RATE,
+    MV_TPM_IOCTL_SW_UNI_TC_INGR_POLICE_RATE,
+    MV_TPM_IOCTL_SW_SET_UNI_EGR_RATE_LIMIT,
+    MV_TPM_IOCTL_TM_SET_WAN_EGR_QUE_SCHED,
+    MV_TPM_IOCTL_TM_SET_WAN_INGR_QUE_SCHED,
+    MV_TPM_IOCTL_TM_SET_WAN_SCHED_EGR_RATE_LIMIT,
+    MV_TPM_IOCTL_TM_SET_WAN_QUE_EGR_RATE_LIMIT,
+    MV_TPM_IOCTL_TM_SET_WAN_INGR_RATE_LIMIT,
+    MV_TPM_IOCTL_TM_SET_WAN_QUE_INGR_RATE_LIMIT,
+    MV_TPM_IOCTL_IGMP_SET_PORT_FRWD_MODE,
+    MV_TPM_IOCTL_IGMP_GET_PORT_FRWD_MODE,
+    MV_TPM_IOCTL_PRINT_ETHER_PORTS,
+    MV_TPM_IOCTL_PRINT_TX_MODULES,
+    MV_TPM_IOCTL_PRINT_GMAC_CONFIG,
+    MV_TPM_IOCTL_PRINT_GMAC_FUNC,
+    MV_TPM_IOCTL_PRINT_EXT_PORT_MAP,        /*not used anymore - can be reused*/
+    MV_TPM_IOCTL_PRINT_IGMP,
+    MV_TPM_IOCTL_PRINT_MISC,
+    MV_TPM_IOCTL_PRINT_OWNERS,
+    MV_TPM_IOCTL_PRINT_API_GROUP,           /*not used anymore - can be reused*/
+    MV_TPM_IOCTL_PRINT_VLAN_TYPE,
+    MV_TPM_IOCTL_PRINT_VALID_API_SECTIONS,
+    MV_TPM_IOCTL_PRINT_FULL_API_SECTIONS,
+    MV_TPM_IOCTL_PRINT_MOD_SHADOW_RANGE,    /*not used anymore - can be reused*/
+    MV_TPM_IOCTL_PRINT_PNC_SHADOW_RANGE,
+    MV_TPM_IOCTL_PRINT_VALID_PNC_RANGES,
+    MV_TPM_IOCTL_PRINT_INIT_TABLES,
+
+    MV_TPM_IOCTL_PRINT_MOD2_TMP_PATTERN,
+    MV_TPM_IOCTL_PRINT_MOD2_JUMP_RANGE,     /*not used anymore - can be reused*/
+    MV_TPM_IOCTL_PRINT_MOD2_JUMP_ALL,
+    MV_TPM_IOCTL_PRINT_MOD2_MAIN_RANGE,     /*not used anymore - can be reused*/
+    MV_TPM_IOCTL_PRINT_MOD2_MAIN_ALL,
+    MV_TPM_IOCTL_PRINT_MOD2_CFG,
+    MV_TPM_IOCTL_PRINT_MOD2_RULE,
+
+    MV_TPM_IOCTL_TRACE_STATUS,
+    MV_TPM_IOCTL_TRACE_SET,
+    MV_TPM_IOCTL_TRACE_MODULE_SET,
+
+    MV_TPM_IOCTL_RESERVED_1,
+    MV_TPM_IOCTL_RESERVED_2,
+
+    MV_TPM_IOCTL_SW_PHY_SET_AUTONEG_MODE,
+    MV_TPM_IOCTL_SW_PHY_GET_AUTONEG_MODE,
+    MV_TPM_IOCTL_SW_PHY_RESTART_AUTONEG,
+    MV_TPM_IOCTL_SW_PHY_SET_PORT_STATE,
+    MV_TPM_IOCTL_SW_PHY_GET_PORT_STATE,
+    MV_TPM_IOCTL_SW_PHY_GET_LINK_STATUS,
+    MV_TPM_IOCTL_SW_PHY_SET_PORT_FLOW_CONTROL,
+    MV_TPM_IOCTL_SW_PHY_GET_PORT_FLOW_CONTROL,
+    MV_TPM_IOCTL_SW_PHY_SET_PORT_SPEED,
+    MV_TPM_IOCTL_SW_PHY_GET_PORT_SPEED,
+    MV_TPM_IOCTL_SW_PORT_VLAN_EGRESS_MODE,
+    MV_TPM_IOCTL_SW_PORT_SET_DEFAULT_VLAN,
+    MV_TPM_IOCTL_SW_PORT_GET_DEFAULT_VLAN,
+    MV_TPM_IOCTL_SW_PORT_SET_DEFAULT_PRIORITY,
+    MV_TPM_IOCTL_SW_PORT_GET_DEFAULT_PRIORITY,
+    MV_TPM_IOCTL_SW_PORT_CLEAR_VID,
+    MV_TPM_IOCTL_SW_PHY_SET_PORT_LOOPBACK,
+    MV_TPM_IOCTL_SW_PHY_GET_PORT_LOOPBACK,
+
+    MV_TPM_IOCTL_ALARM_GET_ETH_PORT,
+    MV_TPM_IOCTL_SW_PHY_CONVERT_PORT_INDEX,
+    MV_TPM_IOCTL_ADD_LOOP_DETECT_CHNL,
+    MV_TPM_IOCTL_ADD_OAM_LOOPBACK_CHNL,
+    MV_TPM_IOCTL_DEL_OAM_LOOPBACK_CHNL,
+    MV_TPM_IOCTL_SW_PHY_SET_PORT_DUPLEX_MODE,
+    MV_TPM_IOCTL_SW_SET_MAC_AGE_TIME,
+    MV_TPM_IOCTL_SW_GET_MAC_AGE_TIME,
+    MV_TPM_IOCTL_SW_SET_MAC_LEARN,
+    MV_TPM_IOCTL_SW_GET_PORT_FLOOD,
+
+    MV_TPM_IOCTL_RESERVED_3,
+    MV_TPM_IOCTL_RESERVED_4,
+    MV_TPM_IOCTL_RESERVED_5,
+    MV_TPM_IOCTL_RESERVED_6,
+
+    MV_TPM_IOCTL_SW_PHY_GET_DUPLEX_STATUS,
+    MV_TPM_IOCTL_SW_PHY_GET_SPEED_MODE,
+    MV_TPM_IOCTL_SW_CLEAR_DYNAMIC_MAC,
+    MV_TPM_IOCTL_SW_SET_MIRROR,
+    MV_TPM_IOCTL_SW_GET_MIRROR,
+    MV_TPM_IOCTL_SW_GET_MAC_LEARN,
+    MV_TPM_IOCTL_SW_PHY_GET_PORT_DUPLEX_MODE,
+    MV_TPM_IOCTL_SET_MTU_SIZE,
+    MV_TPM_IOCTL_GET_MTU_SIZE,
+    MV_TPM_IOCTL_GET_PM_COUNTERS,
+    MV_TPM_IOCTL_CLEAR_PM_COUNTERS,
+    MV_TPM_IOCTL_SW_SET_ISOLATE_PORT_VECTOR,
+    MV_TPM_IOCTL_SW_GET_UNI_EGR_RATE_LIMIT,
+    MV_TPM_IOCTL_SW_GET_UNI_INGR_POLICE_RATE,
+
+    MV_TPM_IOCTL_SET_MOD_RULE,
+    MV_TPM_IOCTL_DEL_MOD_RULE,
+    MV_TPM_IOCTL_GET_MOD_RULE,
+    MV_TPM_IOCTL_INV_MOD_RULES,
+
+    MV_TPM_IOCTL_PRINT_RX_MODULES,
+    MV_TPM_IOCTL_SW_PORT_ADD_ALL_VID,
+    MV_TPM_IOCTL_SW_GET_ISOLATE_PORT_VECTOR,
+    MV_TPM_IOCTL_SW_PHY_GET_PORT_FC_STATE,
+    MV_TPM_IOCTL_SW_ADD_VID_GROUP,
+    MV_TPM_IOCTL_SW_DEL_VID_GROUP,
+    MV_TPM_IOCTL_IGMP_SET_CPU_RX_Q,
+    MV_TPM_IOCTL_IGMP_GET_CPU_RX_Q,
+
+    MV_TPM_IOCTL_ADD_CPU_WAN_LPBK,
+    MV_TPM_IOCTL_DEL_CPU_WAN_LPBK,
+
+    MV_TPM_IOCTL_GET_LU_ENTRIES,
+    MV_TPM_IOCTL_GET_ALL_HIT_COUNTERS,
+    MV_TPM_IOCTL_SET_LU_COUNT_MASK,
+    MV_TPM_IOCTL_GET_HIT_COUNT,
+    MV_TPM_IOCTL_SET_LU_THESHOLD,
+    MV_TPM_IOCTL_RESET_COUNT_GROUP,
+
+    MV_TPM_IOCTL_ADD_IPV6_NH_ACL_RULE,
+    MV_TPM_IOCTL_DEL_IPV6_NH_ACL_RULE,
+    MV_TPM_IOCTL_ADD_IPV6_GEN_ACL_RULE,
+    MV_TPM_IOCTL_DEL_IPV6_GEN_ACL_RULE,
+    MV_TPM_IOCTL_ADD_IPV6_DIP_ACL_RULE,
+    MV_TPM_IOCTL_DEL_IPV6_DIP_ACL_RULE,
+    MV_TPM_IOCTL_ADD_IPV6_L4_PORTS_ACL_RULE,
+    MV_TPM_IOCTL_DEL_IPV6_L4_PORTS_ACL_RULE,
+
+    MV_TPM_IOCTL_SET_MC_VID_PORT_VIDS,
+    MV_TPM_IOCTL_SET_MTU_ADMIN,
+    MV_TPM_IOCTL_SET_MTU,
+    MV_TPM_IOCTL_SET_PPPOE_MTU,
+
+    MV_TPM_IOCTL_SET_IGMP_PROXY_SA_MAC,
+    MV_TPM_IOCTL_GET_IGMP_PROXY_SA_MAC,
+	MV_TPM_IOCTL_ADD_IPv6_MC_STREAM,
+	MV_TPM_IOCTL_MOD_IPv6_MC_STREAM,
+	MV_TPM_IOCTL_DEL_IPv6_MC_STREAM,
+
+    MV_TPM_IOCTL_ADD_IPV6_GEN_5T_RULE,
+    MV_TPM_IOCTL_DEL_IPV6_GEN_5T_RULE,
+    MV_TPM_IOCTL_ADD_IPV6_DIP_5T_RULE,
+    MV_TPM_IOCTL_DEL_IPV6_DIP_5T_RULE,
+    MV_TPM_IOCTL_ADD_IPV6_L4_PORTS_5T_RULE,
+    MV_TPM_IOCTL_DEL_IPV6_L4_PORTS_5T_RULE,
+
+    MV_TPM_IOCTL_ADD_CTC_CM_ACL_RULE,
+    MV_TPM_IOCTL_DEL_CTC_CM_ACL_RULE,
+    MV_TPM_IOCTL_ADD_CTC_CM_IPV6_ACL_RULE,
+    MV_TPM_IOCTL_SET_CTC_CM_IPV6_PARSE_WIN,
+    MV_TPM_IOCTL_ADD_MAC_LEARN_ACL_RULE,
+    MV_TPM_IOCTL_DEL_MAC_LEARN_ACL_RULE,
+    MV_TPM_IOCTL_SET_MAC_LEARN_DEFAULT_ACTION,
+    MV_TPM_IOCTL_TM_SET_GMAC0_INGR_RATE_LIMIT,
+    MV_TPM_IOCTL_GET_MAC_LEARN_ENTRY_NUM,
+
+} tpm_ioctl_cmd_type_t;
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+
+/* Print Section
+** ==============
+** Function list:
+** 1.  tpm_print_etherports
+** 2.  tpm_print_tx_modules
+** 3.  tpm_print_gmac_config
+** 4.  tpm_print_gmac_func
+** 5.  tpm_print_ext_port_map
+** 6.  tpm_print_igmp
+** 7.  tpm_print_misc
+** 8.  tpm_print_owners
+** 9.
+** 10. tpm_print_vlan_etype
+** 11. tpm_print_valid_api_sections
+** 12. tpm_print_full_api_section
+** 13. tpm_print_mod_shadow_range
+** 14. tpm_print_pnc_shadow_range
+** 15. tpm_print_valid_pnc_ranges
+** 16. tpm_print_init_tables
+** 17. tpm_mod2_print_tmp_pattern
+** 18. tpm_mod2_print_jump_range
+** 19. tpm_mod2_print_jump_all
+** 20. tpm_mod2_print_main_range
+** 21. tpm_mod2_print_main_all
+** 22. tpm_mod2_print_config
+*/
+typedef struct
+{
+    uint32_t           print_cmd;
+    tpm_api_sections_t api_section;
+    tpm_gmacs_enum_t   gmac;
+    uint32_t           valid;
+    uint32_t           start;
+    uint32_t           end;
+    uint32_t           dir;
+    uint32_t           entry;
+    uint32_t           num;
+} tpm_ioctl_print_t;
+
+/* Trace Section
+** ==============
+** Function list:
+** 1.  tpm_trace_status_print
+** 2.  tpm_trace_set
+** 3.  tpm_trace_module_set
+*/
+
+typedef struct
+{
+    uint32_t trace_cmd;
+    uint32_t level;
+    uint32_t module;
+    uint32_t flag;
+} tpm_ioctl_trace_t;
+
+/* Admin Section
+** ==============
+** Function list:
+** 1. tpm_create_ownerid
+** 2. tpm_request_api_ownership
+** 3. tpm_get_api_ownership
+** 4. tpm_erase_section
+** 5. tpm_get_section_free_size
+*/
+
+typedef struct
+{
+    uint32_t                  amdin_cmd;
+    uint32_t                  owner_id;
+    tpm_api_type_t            api_type;
+    tpm_api_ownership_error_t api_ownership_error;
+    int32_t                   section_size;
+    uint8_t                   section_dir;
+    uint8_t                   dummy1;
+    uint16_t                  dummy2;
+} tpm_ioctl_admin_t;
+
+/* ACL Rule Add Section
+** ====================
+** Function list:
+** 1. tpm_add_l2_rule
+** 2. tpm_add_l3_type_rule
+** 3. tpm_add_ipv4_rule
+** 4. tpm_add_ipv6_gen_rule
+** 5. tpm_add_ipv6_nh_rule
+** 6. tpm_add_ipv6_dip_rule
+** 7. tpm_add_ipv6_l4_ports_rule
+** 8. tpm_mod_entry_set
+** 9. tpm_add_ipv6_gen_5t_rule
+** 10. tpm_add_ipv6_dip_5t_rule
+** 11. tpm_add_ipv6_l4_ports_5t_rule
+** 12. tpm_add_ctc_cm_acl_rule
+*/
+
+/* L2 */
+typedef struct
+{
+    tpm_l2_acl_key_t   l2_key;
+    tpm_pkt_frwd_t     pkt_frwd;
+    tpm_pkt_mod_t      pkt_mod;
+    tpm_rule_action_t  rule_action;
+    tpm_parse_flags_t  parse_flags_bm;
+    tpm_pkt_mod_bm_t   pkt_mod_bm;
+    tpm_unknown_mac_conf_t mac_conf;/*Just for PnC MAC learn*/
+} l2_acl_rule_t;
+
+/* L3 */
+typedef struct
+{
+    tpm_l3_type_key_t   l3_key;
+    tpm_pkt_frwd_t      pkt_frwd;
+    tpm_rule_action_t   rule_action;
+    tpm_parse_flags_t   parse_flags_bm;
+} l3_acl_rule_t;
+
+/* IPv4 */
+typedef struct
+{
+    tpm_parse_flags_t   parse_flags_bm;
+    tpm_ipv4_acl_key_t  ipv4_key;
+    tpm_pkt_frwd_t      pkt_frwd;
+    tpm_pkt_mod_t       pkt_mod;
+    tpm_pkt_mod_bm_t    pkt_mod_bm;
+    tpm_rule_action_t   rule_action;
+} ipv4_acl_rule_t;
+
+/* IPv6 */
+typedef struct
+{
+    tpm_parse_flags_t   parse_flags_bm;
+    tpm_ipv6_gen_acl_key_t ipv6_gen_key;
+    tpm_pkt_frwd_t      pkt_frwd;
+    tpm_pkt_mod_t       pkt_mod;
+    tpm_pkt_mod_bm_t    pkt_mod_bm;
+    tpm_rule_action_t   rule_action;
+} ipv6_gen_acl_rule_t;
+
+typedef struct
+{
+	tpm_nh_iter_t            nh_iter;
+    uint32_t                 nh;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_rule_action_t        rule_action;
+} ipv6_nh_acl_rule_t;
+
+typedef struct
+{
+    tpm_parse_flags_t        parse_flags_bm;
+    tpm_ipv6_addr_key_t      ipv6_dip_key;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_pkt_mod_t            pkt_mod;
+    tpm_pkt_mod_bm_t         pkt_mod_bm;
+    tpm_rule_action_t        rule_action;
+} ipv6_dip_acl_rule_t;
+
+typedef struct
+{
+    tpm_parse_flags_t        parse_flags_bm;
+    tpm_l4_ports_key_t       l4_key;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_pkt_mod_t            pkt_mod;
+    tpm_pkt_mod_bm_t         pkt_mod_bm;
+    tpm_rule_action_t        rule_action;
+} ipv6_l4_ports_acl_rule_t;
+
+/* IPv6 5 tuple */
+typedef struct
+{
+    tpm_parse_flags_t      parse_flags_bm;
+    tpm_l4_ports_key_t     l4_key;
+    tpm_ipv6_gen_acl_key_t ipv6_gen_key;
+    tpm_pkt_frwd_t         pkt_frwd;
+    tpm_pkt_mod_t          pkt_mod;
+    tpm_pkt_mod_bm_t       pkt_mod_bm;
+    tpm_rule_action_t      rule_action;
+} ipv6_gen_5t_rule_t;
+
+typedef struct
+{
+    tpm_parse_flags_t        parse_flags_bm;
+    tpm_l4_ports_key_t       l4_key;
+    tpm_ipv6_gen_acl_key_t   ipv6_gen_key;
+    tpm_ipv6_addr_key_t      ipv6_dip_key;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_pkt_mod_t            pkt_mod;
+    tpm_pkt_mod_bm_t         pkt_mod_bm;
+    tpm_rule_action_t        rule_action;
+} ipv6_dip_5t_rule_t;
+
+typedef struct
+{
+    tpm_parse_flags_t        parse_flags_bm;
+    tpm_l4_ports_key_t       l4_key;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_pkt_mod_t            pkt_mod;
+    tpm_pkt_mod_bm_t         pkt_mod_bm;
+    tpm_rule_action_t        rule_action;
+} ipv6_l4_ports_5t_rule_t;
+
+/* CTC CnM */
+typedef struct
+{
+    uint32_t           precedence;
+    uint32_t           p_bits;
+    tpm_parse_fields_t l2_parse_rule_bm;
+    tpm_parse_fields_t ipv4_parse_rule_bm;
+    tpm_parse_fields_t ipv6_parse_rule_bm;
+    tpm_l2_acl_key_t   l2_key;
+    tpm_ipv4_acl_key_t ipv4_key;
+    tpm_ipv6_acl_key_t ipv6_key;
+    tpm_pkt_frwd_t     pkt_frwd;
+    tpm_pkt_action_t   pkt_act;
+} ctc_cm_acl_rule_t;
+
+/* Pkt modification */
+typedef struct
+{
+    tpm_trg_port_type_t  trg_port;
+    tpm_pkt_mod_bm_t     mod_bm;
+    tpm_pkt_mod_int_bm_t int_bm;
+    tpm_pkt_mod_t        mod_data;
+} pkt_mod_rule_t;
+
+typedef struct
+{
+    uint32_t             add_acl_cmd;
+    uint32_t             owner_id;
+    tpm_src_port_type_t  src_port;
+	tpm_dir_t            src_dir;
+    uint32_t             rule_num;
+    uint32_t             rule_idx;
+    tpm_parse_fields_t   parse_rule_bm;
+
+    union
+    {
+      l2_acl_rule_t            l2_acl_rule;
+      l3_acl_rule_t            l3_acl_rule;
+      ipv4_acl_rule_t          ipv4_acl_rule;
+      ipv6_gen_acl_rule_t      ipv6_gen_acl_rule;
+      ipv6_nh_acl_rule_t       ipv6_nh_acl_rule;
+      ipv6_dip_acl_rule_t      ipv6_dip_acl_rule;
+      ipv6_l4_ports_acl_rule_t ipv6_l4_ports_acl_rule;
+      ipv6_gen_5t_rule_t       ipv6_gen_5t_rule;
+      ipv6_dip_5t_rule_t       ipv6_dip_5t_rule;
+      ipv6_l4_ports_5t_rule_t  ipv6_l4_ports_5t_rule;
+      ctc_cm_acl_rule_t        ctc_cm_acl_rule;
+      pkt_mod_rule_t           mod_rule;
+    };
+} tpm_ioctl_add_acl_rule_t;
+
+/* ACL Rule Delete Section
+** =======================
+** Function list:
+** 1. tpm_del_l2_rule
+** 2. tpm_del_l3_type_rule
+** 3. tpm_del_ipv4_rule
+** 4. tpm_del_ipv6_gen_rule
+** 5. tpm_del_ipv6_nh_rule
+** 6. tpm_del_ipv6_dip_rule
+** 7. tpm_del_ipv6_l4_ports_rule
+** 8. tpm_mod_entry_del
+** 9. tpm_mod_mac_inv
+** 10. tpm_del_ipv6_gen_5t_rule
+** 11. tpm_del_ipv6_dip_5t_rule
+** 12. tpm_del_ipv6_l4_ports_5t_rule
+** 13. tpm_del_ctc_cm_acl_rule
+*/
+
+typedef struct
+{
+    uint32_t             del_acl_cmd;
+    uint32_t             owner_id;
+    tpm_src_port_type_t  src_port;
+    tpm_trg_port_type_t  trg_port;
+    uint32_t             rule_idx;
+    uint32_t           	 precedence;
+    tpm_parse_fields_t   parse_rule_bm;
+    tpm_l2_acl_key_t     l2_key;/*for MAC learn*/
+} tpm_ioctl_del_acl_rule_t;
+
+/* Modification Rule Get Section
+** =======================
+** Function list:
+** 1. tpm_mod_entry_get
+*/
+typedef struct
+{
+    uint32_t            get_mod_cmd;
+    tpm_trg_port_type_t trg_port;
+    uint32_t            rule_idx;
+    uint16_t            pnc_ref;
+    uint16_t            valid_num;
+    tpm_mod_rule_t      rule[TPM_MAX_MOD_RULE_NUM];
+} tpm_ioctl_get_mod_rule_t;
+
+/* ACL Ctrl Rule Section
+** =====================
+** Function list:
+** 1. tpm_get_next_valid_rule
+*/
+
+typedef struct
+{
+    uint32_t         ctrl_acl_cmd;
+    uint32_t         owner_id;
+    int32_t          current_index;
+    uint32_t         next_index;
+    uint32_t         rule_idx;
+    tpm_api_type_t   rule_type;
+    uint8_t          direction;
+    uint8_t          dummy1;
+    uint16_t         dummy2;
+    tpm_rule_entry_t tpm_rule;
+    uint32_t         entry_count;
+} tpm_ioctl_ctrl_acl_rule_t;
+
+/* MC Rule Section
+** ===============
+** Function list:
+** 1. tpm_add_ipv4_mc_stream
+** 2. tpm_updt_ipv4_mc_stream
+** 3. tpm_del_ipv4_mc_stream
+** 4. tpm_add_ipv6_mc_stream
+** 5. tpm_updt_ipv6_mc_stream
+** 6. tpm_del_ipv6_mc_stream
+*/
+
+/* IPv4 */
+typedef struct
+{
+    uint8_t  ipv4_src_add[4];
+    uint8_t  ipv4_dst_add[4];
+    uint8_t  ignore_ipv4_src;
+    uint8_t  dummy1;
+    uint16_t dummy2;
+} ipv4_mc_rule_t;
+
+/* IPv6 */
+typedef struct
+{
+    uint32_t vid;
+    uint8_t  ipv6_src_add[16];
+    uint8_t  ipv6_dst_add[16];
+    uint8_t  ignore_ipv6_src;
+    uint8_t  dummy1;
+    uint16_t dummy2;
+} ipv6_mc_rule_t;
+
+typedef struct
+{
+    uint32_t             mc_cmd;
+    uint32_t             owner_id;
+    uint32_t             stream_num;
+    tpm_mc_igmp_mode_t   igmp_mode;
+    uint8_t              mc_stream_pppoe;
+    uint16_t             vid;
+    tpm_trg_port_type_t  dest_port_bm;
+
+    union
+    {
+      ipv4_mc_rule_t  ipv4_mc;
+      ipv6_mc_rule_t  ipv6_mc;
+    };
+} tpm_ioctl_mc_rule_t;
+
+/* Mng Rule Section
+** ================
+** Function list:
+** 1. tpm_omci_add_channel
+** 2. tpm_omci_del_channel
+** 3. tpm_omci_get_channel
+** 4. tpm_oam_epon_add_channel
+** 5. tpm_oam_epon_del_channel
+** 6. tpm_oam_epon_get_channel
+*/
+
+typedef struct
+{
+    uint32_t              owner_id;
+    uint32_t              is_valid;
+    uint32_t              cpu_rx_queue;
+    tpm_trg_port_type_t   tcont_num;
+    uint32_t              cpu_tx_queue;
+    tpm_gem_port_key_t    gem_port;
+    uint16_t              dummy;
+} tpm_ioctl_omci_ch_t;
+
+typedef struct
+{
+    uint32_t              owner_id;
+    uint32_t              is_valid;
+    uint32_t              cpu_rx_queue;
+    tpm_trg_port_type_t   llid_num;
+} tpm_ioctl_oam_ch_t;
+
+typedef struct
+{
+    uint32_t              mng_cmd;
+    tpm_ioctl_omci_ch_t   tpm_ioctl_omci_ch;
+    tpm_ioctl_oam_ch_t    tpm_ioctl_oam_ch;
+} tpm_ioctl_mng_ch_t;
+
+/* Switch Section
+** ==============
+** Function list:
+** 1. tpm_sw_add_static_mac
+** 2. tpm_sw_del_static_mac
+** 3. tpm_sw_set_port_max_macs
+** 4. tpm_sw_set_port_flooding
+**
+** 5. tpm_sw_set_port_tagged
+** 6. tpm_sw_set_port_untagged
+** 7. tpm_sw_port_add_vid
+** 8. tpm_sw_port_del_vid
+** 9. tpm_sw_port_set_vid_filter
+**
+** 10.tpm_sw_set_uni_sched
+** 11.tpm_sw_set_uni_q_weight
+** 12.tpm_sw_set_uni_ingr_police_rate
+** 13.tpm_sw_set_uni_tc_ingr_police_rate
+** 14.tpm_sw_set_uni_egr_rate_limit
+*/
+
+/* Switch MAC security */
+typedef struct
+{
+    uint32_t              sw_security_cmd;
+    uint32_t              owner_id;
+    tpm_src_port_type_t   port;
+    uint8_t               static_mac[6];
+    uint8_t               mac_per_port;
+    uint8_t               allow_flood;
+    bool                  enable_mac_learn;
+    tpm_flood_type_t      flood_mode;
+    uint32_t              mac_age_time;
+    tpm_sw_mirror_t       port_mirror;
+    tpm_mru_type_t        mtu_type;
+    uint32_t              mtu_size;
+    uint32_t              port_vector;
+} tpm_ioctl_sw_mac_security_t;
+
+/* Switch Vlan filtering */
+typedef struct
+{
+    uint32_t              sw_vlan_cmd;
+    uint32_t              owner_id;
+    tpm_src_port_type_t   port;
+    uint16_t              vid;
+    uint8_t               pri;
+    uint8_t               vid_filter;
+    uint8_t               allow_tagged;
+    uint8_t               allow_untagged;
+    uint8_t               egress_mode;
+    uint8_t               dummy;
+    uint16_t              min_vid;
+    uint16_t              max_vid;
+} tpm_ioctl_sw_vlan_filter_t;
+
+/* Switch Traffic management */
+typedef struct
+{
+    uint32_t            sw_tm_cmd;
+    uint32_t            owner_id;
+    tpm_src_port_type_t uni_port;
+    tpm_sw_sched_type_t sw_sched_mode;
+    uint8_t             queue_id;
+    uint8_t             weight;
+    uint16_t            dummy;
+    uint32_t            limit_mode;
+    uint32_t            cir;
+    uint32_t            cbs;
+    uint32_t            ebs;
+    uint32_t            tc;
+    uint32_t            rate_limit_val;
+} tpm_ioctl_sw_tm_t;
+
+/* Switch PHY port management */
+typedef struct
+{
+    uint32_t                sw_phy_cmd;
+    uint32_t                owner_id;
+    tpm_src_port_type_t     port;
+    tpm_phy_speed_t         port_speed;
+    tpm_phy_loopback_mode_t port_loopback_mode;
+    tpm_src_port_type_t     extern_port_id;
+    uint32_t                switch_port_id;
+    tpm_autoneg_mode_t      port_autoneg_mode;
+    bool                    phy_port_state;
+    bool                    port_autoneg_state;
+    bool                    port_link_status;
+    bool                    port_pause_state;
+    bool                    port_duplex_enable;
+    bool                    port_loopback_state;
+    uint16_t                dummy;
+} tpm_ioctl_sw_phy_t;
+
+/* Packet Processor Section
+** ========================
+** Function list:
+** 1. tpm_tm_set_wan_egr_queue_sched
+** 2. tpm_tm_set_wan_sched_egr_rate_lim
+** 3. tpm_tm_set_wan_queue_egr_rate_lim
+** 4. tpm_tm_set_wan_ingr_rate_lim
+** 5. tpm_tm_set_wan_q_ingr_rate_lim
+*/
+
+/* Packet Processor Traffic management */
+typedef struct
+{
+    uint32_t            pp_tm_cmd;
+    uint32_t            owner_id;
+    tpm_trg_port_type_t sched_ent;
+    tpm_trg_port_type_t uni_port;
+    tpm_pp_sched_type_t pp_sched_mode;
+    uint32_t            queue_id;
+    uint32_t            wrr_weight;
+    uint32_t            rate_limit_val;
+    uint32_t            bucket_size;
+} tpm_ioctl_tm_tm_t;
+
+/* IGMP Section
+** =============
+** Function list:
+** 1. tpm_proc_enable_igmp
+** 2. tpm_proc_edisable_igmp
+*/
+
+/* Packet Processor Traffic management */
+typedef struct
+{
+    uint32_t             igmp_cmd;
+    uint32_t             owner_id;
+    tpm_src_port_type_t  src_port;
+    tpm_igmp_frwd_mode_t frwd_mode;
+    uint32_t             cpu_queue;
+    uint8_t              sa_mac[6];
+} tpm_ioctl_igmp_t;
+
+
+/* MIB Reset Section
+** =============
+** Function list:
+** 1. tpm_proc_enable_igmp
+*/
+
+/* MIB reset */
+typedef struct
+{
+    uint32_t               owner_id;
+    tpm_reset_level_enum_t reset_level;
+} tpm_ioctl_mib_reset_t;
+
+/* ALARM Section */
+typedef struct
+{
+    uint32_t            alarm_cmd;
+    uint32_t            owner_id;
+    uint32_t            alarm_type;
+    uint8_t             port_bitmap[2][MAX_ETH_PORT_ALARM];
+} tpm_ioctl_alarm_t;
+
+
+/* Management structure for Ethernet counters 1 */
+typedef struct
+{
+  tpm_src_port_type_t  port;
+  uint32_t             owner_id;
+  tpm_swport_pm_1_t    tpm_swport_pm_1;
+
+} tpm_ioctl_swport_pm_1_t;
+
+
+/* Management structure for Ethernet counters 3 */
+typedef struct
+{
+  tpm_src_port_type_t  port;
+  uint32_t             owner_id;
+  tpm_swport_pm_3_t    tpm_swport_pm_3;
+
+} tpm_ioctl_swport_pm_3_t;
+
+
+typedef struct
+{
+    uint32_t             owner_id;
+    tpm_trg_port_type_t  tgt_port;
+    uint8_t              tgt_queue;
+    uint8_t              dummy;
+    uint16_t             gem_port;
+    uint8_t              buf[MAX_FRAME_SIZE];
+    uint32_t             len;
+} tpm_ioctl_tx_igmp_t;
+
+typedef struct
+{
+    uint32_t             owner_id;
+    uint8_t              dummy[2];
+    uint16_t             src_llid;
+    tpm_src_port_type_t  src_port;
+    uint8_t              buf[MAX_FRAME_SIZE];
+    uint32_t             len;
+} tpm_ioctl_rx_igmp_t;
+
+
+typedef struct
+{
+    uint32_t             cpu_lpbk_cmd;
+    uint32_t             owner_id;
+    tpm_pkt_frwd_t       pkt_frwd;
+    uint32_t             mod_idx;
+} tpm_ioctl_cpu_lpbk_t;
+
+typedef struct
+{
+    uint32_t             owner_id;
+} tpm_ioctl_flush_vtu_t;
+typedef struct
+{
+    uint32_t             owner_id;
+    tpm_flush_atu_type_t flush_type;
+    uint16_t             db_num;
+} tpm_ioctl_flush_atu_t;
+
+typedef struct
+{
+    uint32_t              age_count_cmd;
+    uint32_t              owner_id;
+    tpm_api_type_t        api_type;
+    uint32_t              lu_thresh_pkts;
+    uint32_t              rule_idx;
+    uint32_t              lu_rule_mask;
+    uint32_t              hit_count;
+    uint16_t              lu_num;
+    uint16_t              valid_num;
+    uint16_t              unrelated_num;
+    uint8_t               lu_reset;
+    uint8_t               hit_reset;
+    tpm_api_entry_count_t count_array[TPM_MAX_LU_ENTRY_NUM];
+} tpm_ioctl_age_count_t;
+
+typedef struct
+{
+    uint32_t              age_count_cmd;
+    uint32_t              owner_id;
+    tpm_api_type_t        api_type;
+    uint32_t              high_thresh_pkts;
+    uint16_t              valid_counters;
+    uint8_t               counter_reset;
+    uint8_t               dummy;
+    tpm_api_entry_count_t count_array[TPM_MAX_PNC_COUNTER_NUM];
+} tpm_ioctl_pnc_hit_cnt_t;
+
+typedef struct
+{
+    uint32_t                  mc_vid_cmd;
+    uint32_t                  owner_id;
+    uint32_t                  mc_vid;
+    tpm_mc_vid_port_vid_set_t port_vid_set;
+} tpm_ioctl_mc_vid_t;
+
+typedef struct
+{
+    uint32_t                  mtu_setting_cmd;
+    uint32_t                  mtu;
+    uint32_t                  pppoe_mtu;
+    tpm_mtu_ethertype_t       ethertype;
+    uint32_t                  direction;
+    tpm_init_mtu_setting_enable_t  enable;
+} tpm_ioctl_mtu_t;
+
+/* TPM check */
+typedef struct
+{
+    uint32_t               owner_id;
+    tpm_self_check_level_enum_t check_level;
+} tpm_ioctl_tpm_check_t;
+
+/* ipv6 parse window */
+typedef struct
+{
+    uint32_t               owner_id;
+    tpm_ctc_cm_ipv6_parse_win_t ipv6_parse_window;
+} tpm_ioctl_ipv6_parse_window_t;
+
+/* this union aggregates all ioctl commands supported by SFS_TO_IOCTL mode */
+typedef union  tpm_cmd_data
+{
+    tpm_ioctl_add_acl_rule_t    tpm_add_acl_rule;
+    tpm_ioctl_del_acl_rule_t    tpm_del_acl_rule;
+    tpm_ioctl_ctrl_acl_rule_t   tpm_ctrl_acl_rule;
+    tpm_ioctl_mc_rule_t         tpm_mc_rule;
+    tpm_ioctl_igmp_t            tpm_igmp;
+    tpm_ioctl_cpu_lpbk_t        tpm_ioctl_cpu_lpbk;
+    tpm_ioctl_mib_reset_t       tpm_mib_reset_param;
+    tpm_ioctl_age_count_t       tpm_ioctl_age_count;
+    tpm_ioctl_pnc_hit_cnt_t     tpm_ioctl_pnc_hit_cnt;
+    tpm_ioctl_mtu_t		        tpm_ioctl_mtu_set;
+    tpm_ioctl_sw_mac_security_t	tpm_ioctl_sw_mac_set;
+    tpm_ioctl_tm_tm_t		    tpm_ioctl_tm_tm;
+    tpm_ioctl_mng_ch_t		    tpm_mng_channel;
+    tpm_ioctl_get_mod_rule_t	tpm_ioctl_get_mod;
+    tpm_ioctl_tpm_check_t       tpm_check_param;
+    tpm_ioctl_flush_vtu_t       tpm_ioctl_flush_vtu;
+    tpm_ioctl_flush_atu_t       tpm_ioctl_flush_atu;
+    tpm_ioctl_ipv6_parse_window_t   tpm_ipv6_parse_window;
+} tpm_cmd_data_t;
+
+/* this structure is used for passing sysfs request from kernel to userspace
+   to be ioctl (SFS_TO_IOCTL mode)  */
+typedef struct
+{
+    unsigned int    cmd;            /* the ioctl command            */
+    tpm_cmd_data_t  tpm_cmd_data;   /* the ioctl additional data    */
+} tpm_ioctl_mng_t;
+
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+int32_t tpm_module_mng_if_create(void);
+int32_t tpm_module_mng_if_release(void);
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _TPM_MNG_IF_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.c
new file mode 100755
index 0000000..2f33320
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.c
@@ -0,0 +1,1979 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*******************************************************************************
+* tpm_self_check.c
+*
+* DESCRIPTION:
+*       API definitions for TPM checks the hw and the db are synchronized or not
+
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*******************************************************************************/
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_sysfs_utils.h"
+
+#define IF_ERROR(ret)	\
+		if (ret != TPM_OK) {\
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, " recvd ret_code(%d)\n", ret);\
+			return(ret);\
+		}
+
+#define TPM_CHECK_DIV_BY_32(x)   ((x) >> 5)
+#define TPM_CHECK_MOD_32(x)      ((x) & 0x1f)
+
+extern char *tpm_db_api_type_str[TPM_MAX_API_TYPES];
+extern char *opCodeOperationStr[30];
+
+/*******************************************************************************
+* pnc_mismatch_info_show - Show detailed difference between two tpm rule entry
+*
+* INPUT:
+*       tpm_pnc_all_t *entry1
+*       tpm_pnc_all_t *entry2
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*
+* COMMENTS:
+* None
+*******************************************************************************/
+static void pnc_mismatch_info_show(tpm_pnc_all_t *entry1, tpm_pnc_all_t *entry2)
+{
+	if (entry1 == NULL || entry2 == NULL)
+		return;
+
+	printk("======================================================================================\n");
+
+	printk("Tcam mismatch element:  ");
+
+	if (memcmp(&entry1->tcam_entry.lu_id, &entry2->tcam_entry.lu_id, sizeof(uint32_t)))
+		printk("Lookup ID, ");
+	if (memcmp(&entry1->tcam_entry.port_ids, &entry2->tcam_entry.port_ids, sizeof(tpm_gmac_bm_t)))
+		printk("Port ID, ");
+	if (memcmp(&entry1->tcam_entry.add_info_data, &entry2->tcam_entry.add_info_data, sizeof(uint32_t)))
+		printk("AddInfo data, ");
+	if (memcmp(&entry1->tcam_entry.add_info_mask, &entry2->tcam_entry.add_info_mask, sizeof(uint32_t)))
+		printk("AddInfo mask, ");
+	if (memcmp(&entry1->tcam_entry.pkt_data.pkt_byte[0], &entry2->tcam_entry.pkt_data.pkt_byte[0],
+			TPM_TCAM_PKT_WIDTH * sizeof(uint8_t)))
+		printk("Header data");
+
+	printk("\n");
+
+	printk("Sram mismatch element:  ");
+
+	if (memcmp(&entry1->sram_entry.add_info_data, &entry2->sram_entry.add_info_data, sizeof(uint32_t)))
+		printk("Additional Info, ");
+	if (memcmp(&entry1->sram_entry.add_info_mask, &entry2->sram_entry.add_info_mask, sizeof(uint32_t)))
+		printk("Add Info Mask, ");
+	if (memcmp(&entry1->sram_entry.flowid_updt_mask, &entry2->sram_entry.flowid_updt_mask, sizeof(uint32_t)))
+		printk("FlowID_updt_mask, ");
+	if (memcmp(&entry1->sram_entry.flowid_val, &entry2->sram_entry.flowid_val, sizeof(uint32_t)))
+		printk("Flow ID, ");
+	if (memcmp(&entry1->sram_entry.lookup_done, &entry2->sram_entry.lookup_done, sizeof(uint32_t)))
+		printk("Lookup done, ");
+	if (memcmp(&entry1->sram_entry.next_lu_id, &entry2->sram_entry.next_lu_id, sizeof(uint32_t)))
+		printk("Next_lu_id, ");
+	if (memcmp(&entry1->sram_entry.next_lu_off_reg, &entry2->sram_entry.next_lu_off_reg, sizeof(uint32_t)))
+		printk("Next_lu_off_reg, ");
+	if (memcmp(&entry1->sram_entry.pnc_queue, &entry2->sram_entry.pnc_queue, sizeof(uint32_t)))
+		printk("Pnc queue, ");
+	if (memcmp(&entry1->sram_entry.res_info_15_0_data, &entry2->sram_entry.res_info_15_0_data, sizeof(uint32_t)))
+		printk("Res_info_15_0, ");
+	if (memcmp(&entry1->sram_entry.res_info_15_0_mask, &entry2->sram_entry.res_info_15_0_mask, sizeof(uint32_t)))
+		printk("Res_info_15_0 mask, ");
+	if (memcmp(&entry1->sram_entry.res_info_23_16_data, &entry2->sram_entry.res_info_23_16_data, sizeof(uint32_t)))
+		printk("Res_info_23_16, ");
+	if (memcmp(&entry1->sram_entry.res_info_23_16_mask, &entry2->sram_entry.res_info_23_16_mask, sizeof(uint32_t)))
+		printk("Res_info_23_16 mask, ");
+	if (memcmp(&entry1->sram_entry.shift_updt_reg, &entry2->sram_entry.shift_updt_reg, sizeof(uint32_t)))
+		printk("Shift_updt_reg, ");
+	if (memcmp(&entry1->sram_entry.shift_updt_val, &entry2->sram_entry.shift_updt_val, sizeof(uint32_t)))
+		printk("Shift_updt_val, ");
+
+	printk("\n======================================================================================\n\n");
+}
+
+/*******************************************************************************
+* tran_tcam_entry_to_pnc_all_t - translate tcam_entry structure to tpm_pnc_all_t
+*
+* INPUT:
+*	in_tcam: source struct tcam_entry
+*	rule_action: rule action of pnc rule
+*	api_section: pnc rule belong to
+*
+* OUTPUT:
+*	out_pnc: target tpm_pnc_all_t structure
+*
+* RETURN:None
+*******************************************************************************/
+static void tran_tcam_entry_to_pnc_all_t(tpm_pnc_all_t *out_pnc,
+					 struct tcam_entry *in_tcam,
+					 tpm_rule_action_t *rule_action,
+					 tpm_api_sections_t api_section)
+{
+	unsigned int lookup_mask;
+	int tcam_off;
+
+	/*check parameters*/
+	if (out_pnc == NULL || in_tcam == NULL || rule_action == NULL) {
+		printk(KERN_ERR "NULL pointer\n");
+		return;
+	}
+	if (api_section > TPM_CNM_MAIN_ACL || api_section < TPM_CPU_LOOPBACK_ACL) {
+		printk(KERN_ERR "api_section out of range\n");
+		return;
+	}
+	/*get tcam entry*/
+	tcam_sw_get_lookup(in_tcam, &(out_pnc->tcam_entry.lu_id), &lookup_mask);
+	out_pnc->tcam_entry.port_ids = (~(in_tcam->mask.u.word[PORT_WORD] >> PORT_OFFS)) & PORT_MASK;
+	tcam_sw_get_ainfo(in_tcam,
+			&(out_pnc->tcam_entry.add_info_data),
+			&(out_pnc->tcam_entry.add_info_mask));
+	/* Get tcam packet data */
+	for (tcam_off = 0; tcam_off < TPM_TCAM_PKT_WIDTH; tcam_off++) {
+		out_pnc->tcam_entry.pkt_data.pkt_byte[tcam_off] = in_tcam->data.u.byte[tcam_off];
+		out_pnc->tcam_entry.pkt_mask.pkt_byte[tcam_off] = in_tcam->mask.u.byte[tcam_off];
+	}
+	/*Get sram entry*/
+	out_pnc->sram_entry.flowid_val = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(FLOW_VALUE_OFFS)] >>
+							TPM_CHECK_MOD_32(FLOW_VALUE_OFFS)) & FLOW_VALUE_MASK;
+	out_pnc->sram_entry.flowid_updt_mask = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(FLOW_CTRL_OFFS)] >>
+							TPM_CHECK_MOD_32(FLOW_CTRL_OFFS)) & FLOW_CTRL_MASK;
+	out_pnc->sram_entry.res_info_15_0_data = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RI_VALUE_OFFS)] >>
+							TPM_CHECK_MOD_32(RI_VALUE_OFFS)) & RI_VALUE_15_0_MASK;
+	out_pnc->sram_entry.res_info_23_16_data = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RI_VALUE_OFFS)] >>
+							(TPM_CHECK_MOD_32(RI_VALUE_OFFS) + 16)) & RI_VALUE_23_16_MASK;
+	out_pnc->sram_entry.res_info_15_0_mask = in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RI_MASK_OFFS)] &
+							RI_VALUE_15_0_MASK;
+	out_pnc->sram_entry.res_info_23_16_mask = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RI_MASK_OFFS)] >> 16) &
+							RI_VALUE_23_16_MASK;
+	out_pnc->sram_entry.res_info_15_0_data = out_pnc->sram_entry.res_info_15_0_data &
+							out_pnc->sram_entry.res_info_15_0_mask;
+	out_pnc->sram_entry.res_info_23_16_data = out_pnc->sram_entry.res_info_23_16_data &
+							out_pnc->sram_entry.res_info_23_16_mask;
+	out_pnc->sram_entry.shift_updt_val = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(SHIFT_VAL_OFFS)] >>
+							TPM_CHECK_MOD_32(SHIFT_VAL_OFFS)) & SHIFT_VAL_MASK;
+	out_pnc->sram_entry.shift_updt_reg = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(SHIFT_IDX_OFFS)] >>
+							TPM_CHECK_MOD_32(SHIFT_IDX_OFFS)) & SHIFT_IDX_MASK;
+
+	/*update target queue, supposed that API DB is always right, here to avoid error*/
+	if (SET_TARGET_QUEUE(rule_action->pkt_act) ||
+				(api_section == TPM_IPV4_MC) ||
+				(api_section == TPM_IPV6_MC_ACL))
+		out_pnc->sram_entry.pnc_queue = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(RXQ_QUEUE_OFFS)] >>
+							TPM_CHECK_MOD_32(RXQ_QUEUE_OFFS)) & RXQ_MASK;
+	else
+		out_pnc->sram_entry.pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+
+	out_pnc->sram_entry.next_lu_off_reg = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(NEXT_LU_SHIFT_OFFS)] >>
+							TPM_CHECK_MOD_32(NEXT_LU_SHIFT_OFFS)) & NEXT_LU_SHIFT_MASK;
+	out_pnc->sram_entry.lookup_done = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(LU_DONE_OFFS)] >>
+							TPM_CHECK_MOD_32(LU_DONE_OFFS)) & LU_DONE_MASK;
+	out_pnc->sram_entry.add_info_data = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(AI_VALUE_OFFS)] >>
+							TPM_CHECK_MOD_32(AI_VALUE_OFFS)) & AI_MASK;
+	out_pnc->sram_entry.add_info_mask = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(AI_MASK_OFFS)] >>
+							TPM_CHECK_MOD_32(AI_MASK_OFFS)) & AI_MASK;
+	out_pnc->sram_entry.next_lu_id = (in_tcam->sram.word[TPM_CHECK_DIV_BY_32(LU_ID_OFFS)] >>
+							TPM_CHECK_MOD_32(LU_ID_OFFS)) & LU_MASK;
+
+	return;
+}
+
+/*******************************************************************************
+* tpm_check_update_sram - update sram according to some special condition
+*                       - packet drop, flowid_update_mask
+*                       - just to avoid meaningless pnc check error
+* INPUT:
+*	rule_action
+* OUTPUT:
+*	sram_entry
+* RETURN:None
+*******************************************************************************/
+static void tpm_check_update_sram(tpm_sram_all_t *sram_entry, tpm_rule_action_t *rule_action)
+{
+	uint32_t mask = 0;
+	uint32_t loop;
+
+	if (NULL == sram_entry || NULL == rule_action)
+		return;
+
+	/*update flow id*/
+	for (loop = 0; loop < 8; loop++) {
+		if ((1 << loop) & sram_entry->flowid_updt_mask)
+			mask |= (0xF << (4 * loop));
+	}
+	sram_entry->flowid_val = sram_entry->flowid_val & mask;
+
+	/*update pnc queue, if rule action is drop, set pnc queue to 0xFFFF*/
+	if (PKT_DROP(rule_action->pkt_act))
+		sram_entry->pnc_queue = TPM_PNCL_NO_QUEUE_UPDATE;
+}
+
+int32_t tpm_check_main_chain_type(tpm_gmacs_enum_t gmac_port, tpm_pkt_mod_bm_t mod_bm, tpm_pkt_mod_int_bm_t int_mod_bm,
+				  uint16_t jump_idx, tpm_main_chain_check_type_t *result)
+{
+	tpm_chain_type_t main_chain_type, db_main_chain_type, hw_main_chain_type;
+	uint16_t main_chain_entry, main_idx;
+	int32_t ret;
+	uint8_t error_db, error_hw;
+
+	error_db = 0;
+	error_hw = 0;
+	/* Get main chain type from mod_bm */
+	main_chain_type = tpm_mod2_parse_chain_type(mod_bm, int_mod_bm);
+
+	/*Get main chain type from db*/
+	ret = tpm_mod2_main_chain_index_get(gmac_port, jump_idx, &main_chain_entry, TPM_CHECK_MAIN_CHAIN_IDX_DB);
+	if (ret)
+		return TPM_FAIL;
+	ret = tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port, main_chain_entry, &db_main_chain_type, &main_idx);
+	if (ret)
+		return TPM_FAIL;
+	if (main_chain_type != db_main_chain_type)
+		error_db++;
+
+	/*Get main chain type from HW*/
+	ret = tpm_mod2_main_chain_index_get(gmac_port, jump_idx, &main_chain_entry, TPM_CHECK_MAIN_CHAIN_IDX_HW);
+	if (ret)
+		return TPM_FAIL;
+	ret = tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port, main_chain_entry, &hw_main_chain_type, &main_idx);
+	if (ret)
+		return TPM_FAIL;
+	if (main_chain_type != hw_main_chain_type)
+		error_hw++;
+
+	if (error_db && error_hw)
+		*result = TPMCHECK_BOTH_CHAIN_TYPE_MISMATCH;
+	else if (error_db)
+		*result = TPMCHECK_DB_CHAIN_TYPE_MISMATCH;
+	else if (error_hw)
+		*result = TPMCHECK_HW_CHAIN_TYPE_MISMATCH;
+	else
+		*result = TPMCHECK_CHAIN_TYPE_OK;
+
+	return TPM_OK;
+}
+
+static void tpm_check_pmt_mismatch_show_header(void)
+{
+    printk("======================================================================================\n");
+    printk(" Info_Src  Index    OpCode     Operation   Data  Last  IPv4    L4   \n");
+    printk("                                                      update update \n");
+    printk("======================================================================================\n");
+}
+
+/*******************************************************************************
+* tpm_pmt_check - check PMT entries
+*
+* INPUT:
+*       tpm_gmacs_enum_t gmac_port
+*	tpm_mod_pattern_data_t *pattern_data
+*	tpm_self_check_enable_t check_with, check with DB or HW
+*
+* OUTPUT:
+*	tpm_self_check_result_t *result, record check result
+*
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+static int32_t tpm_pmt_check(tpm_gmacs_enum_t gmac_port, tpm_mod_pattern_data_t *pattern_data,
+			     tpm_error_code_t *result, tpm_self_check_enable_t check_with)
+{
+	uint32_t set_id, line_id;
+	tpm_pattern_entry_t *entry_p = NULL;
+	uint16_t pmt_entry;
+	MV_NETA_PMT pEntry;
+	tpm_mod2_entry_t pattern_jump, pattern_chain;
+	/*error flag*/
+	int8_t modification_data = 0;
+	int8_t mod_command = 0;
+	int8_t up_ipv4_checksum = 0;
+	int8_t up_tcp_udp_checksum = 0;
+	int8_t last = 0;
+	int8_t hw_error_count, sw_error_count;
+
+	if (gmac_port >= TPM_MAX_NUM_GMACS) {
+		printk("Invalid parameter: port %d\n", gmac_port);
+		return TPM_FAIL;
+	}
+
+	if (NULL == pattern_data) {
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+		return TPM_FAIL;
+	}
+
+	hw_error_count = 0;
+	sw_error_count = 0;
+
+	for (set_id = 0; set_id < TPM_MOD2_MAX_PATTERN_SETS; set_id++) {
+		if (pattern_data->pattern_set[set_id].is_valid) {
+			entry_p = &(pattern_data->pattern_set[set_id]);
+			if (set_id == 0)
+				pmt_entry = entry_p->index;
+			else
+				pmt_entry = tpm_db_mod2_convert_chain_to_pmt_entry(entry_p->chain_type, entry_p->index);
+
+			for (line_id = 0; line_id < TPM_MOD2_MAX_PATTERN_ENTRIES && line_id < entry_p->line_num;
+				line_id++) {
+				if (check_with == TPM_CHECK_WITH_HW) {
+					/*read HW PMT table*/
+					if (tpm_mod2_neta_pmt_get(gmac_port, pmt_entry + line_id, &pEntry)) {
+						TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get hw jump data\n");
+						return TPM_FAIL;
+					}
+
+					/*compare HW PMT*/
+					if ((pEntry.word & MV_NETA_PMT_DATA_MASK) != entry_p->line[line_id].data)
+						modification_data = 1;
+					if (((pEntry.word >> MV_NETA_PMT_CMD_OFFS) & (MV_NETA_PMT_CMD_ALL_MASK >>
+							MV_NETA_PMT_CMD_OFFS)) != entry_p->line[line_id].opcode)
+						mod_command = 1;
+					if (((pEntry.word >> MV_NETA_PMT_IP4_CSUM_BIT) & (MV_NETA_PMT_IP4_CSUM_MASK >>
+							MV_NETA_PMT_IP4_CSUM_BIT)) != entry_p->line[line_id].updt_ipv4)
+						up_ipv4_checksum = 1;
+					if (((pEntry.word >> MV_NETA_PMT_L4_CSUM_BIT) & (MV_NETA_PMT_L4_CSUM_MASK >>
+							MV_NETA_PMT_L4_CSUM_BIT)) != entry_p->line[line_id].updt_tcp)
+						up_tcp_udp_checksum = 1;
+					if (((pEntry.word >> MV_NETA_PMT_LAST_BIT) & (MV_NETA_PMT_LAST_MASK >>
+							MV_NETA_PMT_LAST_BIT)) != entry_p->line[line_id].last)
+						last = 1;
+
+					/*show HW error info*/
+					if (modification_data || mod_command || up_ipv4_checksum ||
+						up_tcp_udp_checksum || last) {
+						hw_error_count++;
+						printk("\nPMT Mismatch: [set %d] area_type %d, chain_type %d, "
+							"chain_index %d ,line_num %d\r\n",
+							set_id, entry_p->area_type, entry_p->chain_type,
+							entry_p->index, entry_p->line_num);
+						tpm_check_pmt_mismatch_show_header();
+						printk(" %5s      %03d      0x%2x %15s  0x%4.4x  %1d     "
+							"%1d      %1d\n",
+							"Build",
+							line_id,
+							entry_p->line[line_id].opcode,
+							opCodeOperationStr[entry_p->line[line_id].opcode],
+							entry_p->line[line_id].data, entry_p->line[line_id].last,
+							entry_p->line[line_id].updt_ipv4,
+							entry_p->line[line_id].updt_tcp);
+						printk(" %5s      %03d      0x%2x %15s  0x%4.4x  %1d     "
+							"%1d      %1d\n",
+							"HWPMT",
+							line_id,
+							((pEntry.word >> MV_NETA_PMT_CMD_OFFS) &
+							(MV_NETA_PMT_CMD_ALL_MASK >> MV_NETA_PMT_CMD_OFFS)),
+							opCodeOperationStr[((pEntry.word >> MV_NETA_PMT_CMD_OFFS) &
+							(MV_NETA_PMT_CMD_ALL_MASK >> MV_NETA_PMT_CMD_OFFS))],
+							(pEntry.word & MV_NETA_PMT_DATA_MASK),
+							((pEntry.word >> MV_NETA_PMT_LAST_BIT) &
+							(MV_NETA_PMT_LAST_MASK >> MV_NETA_PMT_LAST_BIT)),
+							((pEntry.word >> MV_NETA_PMT_IP4_CSUM_BIT) &
+							(MV_NETA_PMT_IP4_CSUM_MASK >> MV_NETA_PMT_IP4_CSUM_BIT)),
+							((pEntry.word >> MV_NETA_PMT_L4_CSUM_BIT) &
+							(MV_NETA_PMT_L4_CSUM_MASK >> MV_NETA_PMT_L4_CSUM_BIT)));
+					}
+
+					/*clear error flags*/
+					modification_data = 0;
+					mod_command = 0;
+					up_ipv4_checksum = 0;
+					up_tcp_udp_checksum = 0;
+					last = 0;
+				} else if (check_with == TPM_CHECK_WITH_DB) {
+					/*read PMT db info*/
+					if (set_id == 0) {
+						if (tpm_mod2_db_jump_pattern_data_get(gmac_port, entry_p->index,
+											&pattern_jump)) {
+							TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Get Jump pattern failed\n");
+							return TPM_FAIL;
+						}
+					} else {
+						if (tpm_mod2_db_chain_pattern_data_get(gmac_port, entry_p->chain_type,
+									entry_p->index, line_id, &pattern_chain)) {
+							TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Get Chain pattern failed\n");
+							return TPM_FAIL;
+						}
+					}
+
+					/*compare to db*/
+					if (set_id == 0) {
+						if (pattern_jump.data != entry_p->line[line_id].data)
+							modification_data = 1;
+						if (pattern_jump.opcode != entry_p->line[line_id].opcode)
+							mod_command = 1;
+						if (pattern_jump.updt_ipv4 != entry_p->line[line_id].updt_ipv4)
+							up_ipv4_checksum = 1;
+						if (pattern_jump.updt_tcp != entry_p->line[line_id].updt_tcp)
+							up_tcp_udp_checksum = 1;
+						if (pattern_jump.last != entry_p->line[line_id].last)
+							last = 1;
+					} else {
+						if (pattern_chain.data != entry_p->line[line_id].data)
+							modification_data = 1;
+						if (pattern_chain.opcode != entry_p->line[line_id].opcode)
+							mod_command = 1;
+						if (pattern_chain.updt_ipv4 != entry_p->line[line_id].updt_ipv4)
+							up_ipv4_checksum = 1;
+						if (pattern_chain.updt_tcp != entry_p->line[line_id].updt_tcp)
+							up_tcp_udp_checksum = 1;
+						if (pattern_chain.last != entry_p->line[line_id].last)
+							last = 1;
+					}
+
+					/*show SW error info*/
+					if (modification_data || mod_command || up_ipv4_checksum ||
+									up_tcp_udp_checksum || last) {
+						sw_error_count++;
+						printk("\nPMT Mismatch: [set %d] area_type %d, chain_type %d, "
+							"chain_index %d ,line_num %d\r\n",
+							set_id, entry_p->area_type, entry_p->chain_type,
+							entry_p->index, entry_p->line_num);
+						tpm_check_pmt_mismatch_show_header();
+						printk(" %5s      %03d      0x%2x %15s  0x%4.4x  "
+							"%1d     %1d      %1d\n",
+							"Build",
+							line_id,
+							entry_p->line[line_id].opcode,
+							opCodeOperationStr[entry_p->line[line_id].opcode],
+							entry_p->line[line_id].data, entry_p->line[line_id].last,
+							entry_p->line[line_id].updt_ipv4,
+							entry_p->line[line_id].updt_tcp);
+						if (set_id == 0) {
+							printk(" %5s      %03d      0x%2x %15s  0x%4.4x  "
+								"%1d     %1d      %1d\n",
+								"DB",
+								line_id,
+								pattern_jump.opcode,
+								opCodeOperationStr[pattern_jump.opcode],
+								pattern_jump.data, pattern_jump.last,
+								pattern_jump.updt_ipv4, pattern_jump.updt_tcp);
+						} else {
+
+							printk(" %5s      %03d      0x%2x %15s  0x%4.4x  "
+								"%1d     %1d      %1d\n",
+								"DB",
+								line_id,
+								pattern_chain.opcode,
+								opCodeOperationStr[pattern_chain.opcode],
+								pattern_chain.data, pattern_chain.last,
+								pattern_chain.updt_ipv4, pattern_chain.updt_tcp);
+						}
+					}
+
+					/*clear error flags*/
+					modification_data = 0;
+					mod_command = 0;
+					up_ipv4_checksum = 0;
+					up_tcp_udp_checksum = 0;
+					last = 0;
+				}
+			}
+
+		}
+	}
+
+	/*record check result*/
+	if (hw_error_count)
+		*result = ERR_TPMCHECK_PMT_HW_MISMATCH;
+	else if (sw_error_count)
+		*result = ERR_TPMCHECK_PMT_DB_MISMATCH;
+	else
+		*result = TPM_RC_OK;
+
+	return TPM_OK;
+}
+
+int32_t tpm_check_param_check(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+			      tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+			      tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+			      tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	if (pon_type < TPM_EPON || pon_type > TPM_P2P) {
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "PON type is invalid\n");
+		return TPM_FAIL;
+	}
+
+	if (tpm_rule == NULL ||
+		mod_con == NULL ||
+		api_ent_mem_area == NULL ||
+		pnc_data == NULL ||
+		mod_entry == NULL ||
+		pkt_mod == NULL ||
+		pkt_mod_bm == NULL ||
+		int_mod_bm == NULL ||
+		trg_port == NULL ||
+		rule_action == NULL) {
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Pointer invalid (NULL)\n");
+		return TPM_FAIL;
+	}
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* api_data2pnc_data_l2 - translate L2 APi data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*	trg_port
+*	rule_action
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_l2(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+			     tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+			     tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+			     tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_l2_acl_key_t l2_key;
+	tpm_dir_t dir = 0;
+	tpm_pkt_frwd_t pkt_frwd;
+	uint32_t rule_num;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	src_port = tpm_rule->l2_prim_key.src_port;
+	memcpy(&l2_key, &(tpm_rule->l2_prim_key.l2_key), sizeof(tpm_l2_acl_key_t));
+	parse_rule_bm = tpm_rule->l2_prim_key.parse_rule_bm;
+	parse_flags_bm = tpm_rule->l2_prim_key.parse_flags_bm;
+	memcpy(&pkt_frwd, &(tpm_rule->l2_prim_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
+	memcpy(rule_action, &(tpm_rule->l2_prim_key.rule_action), sizeof(tpm_rule_action_t));
+	*mod_entry = mod_con->mod_cmd_ind;
+	*trg_port = tpm_rule->l2_prim_key.pkt_frwd.trg_port;
+	memcpy(pkt_mod, &(tpm_rule->l2_prim_key.pkt_mod), sizeof(tpm_pkt_mod_t));
+	*pkt_mod_bm = tpm_rule->l2_prim_key.pkt_mod_bm;
+	*int_mod_bm = 0;
+	rule_num = api_ent_mem_area->rule_idx;
+	/* Get direction */
+	tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
+	IF_ERROR(tpm_ret);
+	/*******************generate PnC Rule Start********************/
+	/*generate tcam */
+	tpm_ret = tpm_proc_l2_tcam_build(src_port,
+					 dir,
+					 rule_num,
+					 &l2_key,
+					 parse_rule_bm,
+					 parse_flags_bm,
+					 &(pnc_data->pncl_tcam));
+	IF_ERROR(tpm_ret);
+	/*generate sram*/
+	tpm_ret = tpm_proc_l2_sram_build(src_port,
+					 dir,
+					 rule_num,
+					 pon_type,
+					 &pkt_frwd,
+					 rule_action,
+					 mod_con->mod_cmd_ind,
+					 &(pnc_data->pncl_sram),
+					 &l2_key,
+					 &(tpm_rule->l2_prim_key.pkt_mod),
+					 tpm_rule->l2_prim_key.pkt_mod_bm);
+	IF_ERROR(tpm_ret);
+
+	return TPM_OK;
+
+}
+
+/*******************************************************************************
+* api_data2pnc_data_l3 - translate L3 APi data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*	rule_action
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_l3(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+			     tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+			     tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+			     tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_l3_type_key_t l3_key;
+	tpm_dir_t dir = 0;
+	tpm_pkt_frwd_t pkt_frwd;
+	uint8_t l3_is_pppoe = TPM_FALSE;
+	uint32_t rule_num;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	src_port = tpm_rule->l3_type_key.src_port;
+	memcpy(&l3_key, &(tpm_rule->l3_type_key.l3_key), sizeof(tpm_l3_type_key_t));
+	parse_rule_bm = tpm_rule->l3_type_key.parse_rule_bm;
+	parse_flags_bm = tpm_rule->l3_type_key.parse_flags_bm;
+	memcpy(&pkt_frwd, &(tpm_rule->l3_type_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
+	memcpy(rule_action, &(tpm_rule->l3_type_key.rule_action), sizeof(tpm_rule_action_t));
+	*mod_entry = mod_con->mod_cmd_ind;
+	rule_num = api_ent_mem_area->rule_idx;
+	/* Get direction */
+	tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
+	IF_ERROR(tpm_ret);
+	/*******************generate PnC Rule Start********************/
+	/*generate tcam */
+	tpm_ret = tpm_proc_l3_tcam_build(src_port,
+					 dir,
+					 rule_num,
+					 &l3_key,
+					 parse_rule_bm,
+					 parse_flags_bm,
+					 rule_action,
+					 &(pnc_data->pncl_tcam));
+	IF_ERROR(tpm_ret);
+	/*generate sram*/
+	if (pnc_data->pncl_tcam.pkt_key.l3_key.ether_type_key == ETH_P_PPP_SES)
+		l3_is_pppoe = TPM_TRUE;
+	tpm_ret = tpm_proc_l3_sram_build(src_port,
+					 dir,
+					 rule_num,
+					 l3_is_pppoe,
+					 pon_type,
+					 &pkt_frwd,
+					 rule_action,
+					 parse_flags_bm,
+					 &(pnc_data->pncl_sram));
+	IF_ERROR(tpm_ret);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* api_data2pnc_data_ipv4 - translate IPV4 ACL API data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*	rule_action
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_ipv4(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+			       tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+			       tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+			       tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_ipv4_acl_key_t ipv4_acl_key;
+	tpm_dir_t dir = 0;
+	tpm_pkt_frwd_t pkt_frwd;
+	uint32_t rule_num;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	src_port = tpm_rule->ipv4_key.src_port;
+	memcpy(&ipv4_acl_key, &(tpm_rule->ipv4_key.ipv4_key), sizeof(tpm_ipv4_acl_key_t));
+	parse_rule_bm = tpm_rule->ipv4_key.parse_rule_bm;
+	parse_flags_bm = tpm_rule->ipv4_key.parse_flags_bm;
+	memcpy(&pkt_frwd, &(tpm_rule->ipv4_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
+	memcpy(rule_action, &(tpm_rule->ipv4_key.rule_action), sizeof(tpm_rule_action_t));
+	*mod_entry = mod_con->mod_cmd_ind;
+	*trg_port = tpm_rule->ipv4_key.pkt_frwd.trg_port;
+	memcpy(pkt_mod, &(tpm_rule->ipv4_key.pkt_mod), sizeof(tpm_pkt_mod_t));
+	*pkt_mod_bm = tpm_rule->ipv4_key.pkt_mod_bm;
+	*int_mod_bm = 0;
+	rule_num = api_ent_mem_area->rule_idx;
+	/* Get direction */
+	tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
+	IF_ERROR(tpm_ret);
+	/*******************generate PnC Rule Start********************/
+	/*generate tcam */
+	tpm_ret = tpm_proc_ipv4_tcam_build(src_port,
+					   dir,
+					   rule_num,
+					   &ipv4_acl_key,
+					   parse_rule_bm,
+					   parse_flags_bm,
+					   rule_action,
+					   &(tpm_rule->ipv4_key.pkt_mod),
+					   tpm_rule->ipv4_key.pkt_mod_bm,
+					   &(pnc_data->pncl_tcam));
+	IF_ERROR(tpm_ret);
+
+	/*generate sram*/
+	tpm_ret = tpm_proc_ipv4_sram_build(src_port,
+					   dir,
+					   rule_num,
+					   pon_type,
+					   &ipv4_acl_key,
+					   pnc_data->pncl_tcam.ipv4_parse_bm,
+					   parse_flags_bm,
+					   &pkt_frwd,
+					   rule_action,
+					   mod_con->mod_cmd_ind,
+					   tpm_rule->ipv4_key.pkt_mod_bm,
+					   &(tpm_rule->ipv4_key.pkt_mod),
+					   &(pnc_data->pncl_sram));
+	IF_ERROR(tpm_ret);
+	/*update L4 checksum*/
+	if (parse_rule_bm & TPM_IPv4_PARSE_PROTO) {
+		if (ipv4_acl_key.ipv4_proto == IPPROTO_TCP)
+			*int_mod_bm = TPM_INT_L4_TCP;
+		else if (ipv4_acl_key.ipv4_proto == IPPROTO_UDP) {
+			*int_mod_bm = TPM_INT_L4_UDP;
+			/* Set internal_bm according to API Action */
+			if (rule_action->pkt_act & TPM_ACTION_UDP_CHKSUM_CALC)
+				*int_mod_bm = TPM_INT_L4_UDP | TPM_INT_UDP_CHECKSUM;
+		}
+	}
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* api_data2pnc_data_ipv4_mc - translate IPV4 MC API data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_ipv4_mc(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+				  tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+				  tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+				  tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_db_mc_stream_entry_t mc_stream_entry;
+	tpm_mc_filter_mode_t filter_mode;
+	uint8_t mc_stream_pppoe, ignore_ipv4_src, ipv4_src_add[4], ipv4_dst_add[4];
+	uint16_t mc_vid;
+	uint32_t stream_num, igmp_mode, dest_port_bm;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	filter_mode = tpm_db_get_mc_filter_mode();
+	stream_num = api_ent_mem_area->rule_num;
+	tpm_ret = tpm_db_get_mc_stream_entry(stream_num, &mc_stream_entry);
+	IF_ERROR(tpm_ret);
+	mc_stream_pppoe = mc_stream_entry.mc_stream_pppoe;
+	igmp_mode = mc_stream_entry.igmp_mode;
+	dest_port_bm = mc_stream_entry.dest_port_bm;
+	memcpy(ipv4_src_add, tpm_rule->ipv4_mc_key.ipv4_src_add, sizeof(ipv4_src_add));
+	memcpy(ipv4_dst_add, tpm_rule->ipv4_mc_key.ipv4_dest_add, sizeof(ipv4_dst_add));
+	rule_action->pkt_act = 0;
+	mc_vid = tpm_rule->ipv4_mc_key.vid;
+	ignore_ipv4_src = tpm_rule->ipv4_mc_key.ignore_ipv4_src;
+	*mod_entry = mod_con->mod_cmd_ind;
+
+	/*******************generate PnC Rule Start********************/
+	/*generate tcam entry*/
+	tpm_ret = tpm_proc_ipv4_mc_tcam_build(filter_mode,
+					      stream_num,
+					      mc_vid,
+					      mc_stream_pppoe,
+					      ipv4_src_add,
+					      ipv4_dst_add,
+					      ignore_ipv4_src,
+					      &(pnc_data->pncl_tcam));
+	IF_ERROR(tpm_ret);
+	/* Build SRAM Entry */
+	tpm_ret = tpm_proc_ipv4_mc_sram_build(filter_mode,
+					      igmp_mode,
+					      dest_port_bm,
+					      mod_con->mod_cmd_ind,
+					      &(pnc_data->pncl_sram));
+	IF_ERROR(tpm_ret);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* api_data2pnc_data_ipv6_gen - translate IPV6 GEN API data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*	rule_action
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_ipv6_gen(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+				   tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+				   tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+				   tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_dir_t dir = 0;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_rule_ipv6_gen_key_t ipv6_gen_acl_key;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable = TPM_IPV6_5T_DISABLED;
+	long long int_pkt_act = 0;
+	uint32_t subflow_bm, subflow_id, protocol = 0;
+	uint32_t rule_num;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	src_port = tpm_rule->ipv6_gen_key.src_port;
+	memcpy(&ipv6_gen_acl_key, &(tpm_rule->ipv6_gen_key), sizeof(tpm_rule_ipv6_gen_key_t));
+	parse_rule_bm = tpm_rule->ipv6_gen_key.parse_rule_bm;
+	parse_flags_bm = tpm_rule->ipv6_gen_key.parse_flags_bm;
+	memcpy(&pkt_frwd, &(tpm_rule->ipv6_gen_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
+	memcpy(rule_action, &(tpm_rule->ipv6_gen_key.rule_action), sizeof(tpm_rule_action_t));
+	*mod_entry = mod_con->mod_cmd_ind;
+	*trg_port = tpm_rule->ipv6_gen_key.pkt_frwd.trg_port;
+	memcpy(pkt_mod, &(tpm_rule->ipv6_gen_key.pkt_mod), sizeof(tpm_pkt_mod_t));
+	*pkt_mod_bm = tpm_rule->ipv6_gen_key.pkt_mod_bm;
+	*int_mod_bm = 0;
+	rule_num = api_ent_mem_area->rule_idx;
+	/*check ipv6_5t is enable or not*/
+	tpm_ret = tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	IF_ERROR(tpm_ret);
+	/* Get direction */
+	tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
+	IF_ERROR(tpm_ret);
+
+	/*******************generate PnC Rule Start********************/
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED) {
+		/*generate tcam */
+		tpm_ret = tpm_proc_ipv6_gen_tcam_build(src_port,
+						       dir,
+						       rule_num,
+						       &ipv6_gen_acl_key.ipv6_gen_key,
+						       parse_rule_bm,
+						       parse_flags_bm,
+						       pkt_mod,
+						       *pkt_mod_bm,
+						       &(pnc_data->pncl_tcam));
+		IF_ERROR(tpm_ret);
+		/*generate sram*/
+		tpm_ret = tpm_proc_ipv6_gen_sram_build(src_port,
+						       dir,
+						       rule_num,
+						       pon_type,
+						       &pkt_frwd,
+						       rule_action,
+						       mod_con->mod_cmd_ind,
+						       &(pnc_data->pncl_sram));
+		IF_ERROR(tpm_ret);
+	} else {
+		/*********** Get Subflow Info **********/
+		subflow_bm = parse_rule_bm & TPM_DB_IPV6_GEN_SUBFLOW_PARSE_BM_MASK;
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+				protocol = IPPROTO_TCP;
+			else
+				protocol = IPPROTO_UDP;
+			subflow_bm |= TPM_IPv6_PARSE_NH;
+		}
+		subflow_id = TPM_DB_INVALID_IPV6_FLOW_ID;
+		if (subflow_bm != 0 && rule_action->next_phase != STAGE_DONE) {
+			int_pkt_act |= TPM_ACTION_SET_IPV6_SUBFLOW;
+			subflow_id = tpm_db_find_matched_ipv6_gen_subflow(dir,
+									  subflow_bm,
+									  protocol,
+									  &ipv6_gen_acl_key.l4_key,
+									  &ipv6_gen_acl_key.ipv6_gen_key);
+			if (subflow_id == TPM_DB_INVALID_IPV6_FLOW_ID) {
+				printk("Subflow_id get Failed\n");
+				return TPM_FAIL;
+			}
+		} else {
+			int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
+		}
+		/*generate tcam */
+		tpm_ret = tpm_proc_ipv6_gen_5t_tcam_build(dir,
+							  rule_num,
+							  &ipv6_gen_acl_key.l4_key,
+							  &ipv6_gen_acl_key.ipv6_gen_key,
+							  parse_rule_bm,
+							  parse_flags_bm,
+							  rule_action,
+							  pkt_mod,
+							  *pkt_mod_bm,
+							  &(pnc_data->pncl_tcam));
+		IF_ERROR(tpm_ret);
+		/*generate sram*/
+		tpm_ret = tpm_proc_ipv6_gen_5t_sram_build(dir,
+							  rule_num,
+							  pon_type,
+							  subflow_id,
+							  &pkt_frwd,
+							  rule_action,
+							  int_pkt_act,
+							  pkt_mod,
+							  mod_con->mod_cmd_ind,
+							  &(pnc_data->pncl_sram));
+		IF_ERROR(tpm_ret);
+	}
+
+	return TPM_OK;
+}
+
+
+/*******************************************************************************
+* api_data2pnc_data_ipv6_dip - translate IPV6 DIP API data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*	rule_action
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_ipv6_dip(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+				   tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+				   tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+				   tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_dir_t dir = 0;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_rule_ipv6_gen_key_t ipv6_gen_acl_key;
+	tpm_rule_ipv6_dip_key_t ipv6_dip_key;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable = TPM_IPV6_5T_DISABLED;
+	long long int_pkt_act = 0;
+	uint32_t rule_num;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	src_port = tpm_rule->ipv6_dip_key.src_port;
+	memcpy(&ipv6_dip_key, &(tpm_rule->ipv6_dip_key), sizeof(tpm_rule_ipv6_dip_key_t));
+	parse_rule_bm = tpm_rule->ipv6_dip_key.parse_rule_bm;
+	parse_flags_bm = tpm_rule->ipv6_dip_key.parse_flags_bm;
+	memcpy(&pkt_frwd, &(tpm_rule->ipv6_dip_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
+	memcpy(rule_action, &(tpm_rule->ipv6_dip_key.rule_action), sizeof(tpm_rule_action_t));
+	*mod_entry = mod_con->mod_cmd_ind;
+	*trg_port = tpm_rule->ipv6_dip_key.pkt_frwd.trg_port;
+	memcpy(pkt_mod, &(tpm_rule->ipv6_dip_key.pkt_mod), sizeof(tpm_pkt_mod_t));
+	*pkt_mod_bm = tpm_rule->ipv6_dip_key.pkt_mod_bm;
+	*int_mod_bm = 0;
+	rule_num = api_ent_mem_area->rule_idx;
+	/*check ipv6_5t is enable or not*/
+	tpm_ret = tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	IF_ERROR(tpm_ret);
+	/* Get direction */
+	tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
+	IF_ERROR(tpm_ret);
+	/*******************generate PnC Rule Start********************/
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED) {
+		/*generate tcam */
+		tpm_ret = tpm_proc_ipv6_dip_tcam_build(src_port,
+						       dir,
+						       rule_num,
+						       &ipv6_dip_key.ipv6_dipkey,
+						       parse_rule_bm,
+						       parse_flags_bm,
+						       pkt_mod,
+						       *pkt_mod_bm,
+						       &(pnc_data->pncl_tcam));
+		IF_ERROR(tpm_ret);
+		/*generate sram*/
+		tpm_ret = tpm_proc_ipv6_dip_sram_build(src_port,
+						       dir,
+						       rule_num,
+						       pon_type,
+						       &pkt_frwd,
+						       rule_action,
+						       mod_con->mod_cmd_ind,
+						       &(pnc_data->pncl_sram));
+		IF_ERROR(tpm_ret);
+	} else {
+		int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
+		/*generate tcam */
+		memcpy(&ipv6_gen_acl_key, &(tpm_rule->ipv6_gen_key), sizeof(tpm_rule_ipv6_gen_key_t));
+		tpm_ret = tpm_proc_ipv6_dip_5t_tcam_build(dir,
+							  rule_num,
+							  &ipv6_dip_key.l4_key,
+							  &ipv6_gen_acl_key.ipv6_gen_key,
+							  &ipv6_dip_key.ipv6_dipkey,
+							  parse_rule_bm,
+							  parse_flags_bm,
+							  rule_action,
+							  pkt_mod,
+							  *pkt_mod_bm,
+							  &(pnc_data->pncl_tcam));
+		IF_ERROR(tpm_ret);
+		/*generate sram*/
+		tpm_ret = tpm_proc_ipv6_dip_5t_sram_build(dir,
+							  rule_num,
+							  pon_type,
+							  &pkt_frwd,
+							  rule_action,
+							  int_pkt_act,
+							  pkt_mod,
+							  mod_con->mod_cmd_ind,
+							  &(pnc_data->pncl_sram));
+		IF_ERROR(tpm_ret);
+	}
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* api_data2pnc_data_ipv6_mc - translate IPV6 MC API data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_ipv6_mc(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+				  tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+				  tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+				  tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_mc_filter_mode_t filter_mode;
+	uint8_t mc_stream_pppoe;
+	uint16_t mc_vid;
+	uint32_t stream_num, igmp_mode, dest_port_bm;
+	tpm_db_ipv6_mc_stream_entry_t ipv6_mc_stream_entry;
+	uint8_t ipv6_dst_add[16];
+	int32_t tpm_ret = 0;
+	uint8_t sip_index = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	filter_mode = tpm_db_get_mc_filter_mode();
+	stream_num = api_ent_mem_area->rule_num;
+	tpm_ret = tpm_db_get_ipv6_mc_stream_entry(stream_num, &ipv6_mc_stream_entry);
+	IF_ERROR(tpm_ret);
+	mc_stream_pppoe = ipv6_mc_stream_entry.mc_stream_pppoe;
+	igmp_mode = ipv6_mc_stream_entry.igmp_mode;
+	dest_port_bm = ipv6_mc_stream_entry.dest_port_bm;
+	memcpy(ipv6_dst_add, tpm_rule->ipv6_mc_key.ipv6_dest_add, sizeof(ipv6_dst_add));
+	rule_action->pkt_act = 0;
+	mc_vid = tpm_rule->ipv6_mc_key.vid;
+	*mod_entry = mod_con->mod_cmd_ind;
+
+	/* get sip_index */
+	if (0 == ipv6_mc_stream_entry.ignore_src_addr) {
+		/* get index of this IPv6 MC SIP */
+		sip_index = tpm_db_ipv6_mc_sip_index_get(ipv6_mc_stream_entry.src_addr);
+		if (0 == sip_index) {
+			/* SIP is not in DB, error */
+			TPM_OS_ERROR(TPM_TPM_LOG_MOD, "get index of IPv6 MC SIP failed!\n");
+			return(ERR_IPV6_MC_SRC_IP_INVALID);
+		}
+	}
+
+	/*generate tcam entry*/
+	tpm_ret = tpm_proc_ipv6_mc_tcam_build(filter_mode,
+					      stream_num,
+					      mc_vid,
+					      mc_stream_pppoe,
+					      ipv6_dst_add,
+					      sip_index,
+					      ipv6_mc_stream_entry.ignore_src_addr,
+					      &(pnc_data->pncl_tcam));
+	IF_ERROR(tpm_ret);
+	/*generate sram*/
+	tpm_ret = tpm_proc_ipv6_mc_sram_build(filter_mode,
+					      igmp_mode,
+					      dest_port_bm,
+					      mod_con->mod_cmd_ind,
+					      &(pnc_data->pncl_sram));
+	IF_ERROR(tpm_ret);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* api_data2pnc_data_ipv6_nh - translate IPV6 NH API data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*	rule_action
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_ipv6_nh(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+				  tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+				  tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+				  tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_rule_ipv6_nh_key_t ipv6_nh_key;
+	tpm_nh_iter_t nh_iter;
+	uint32_t rule_num;
+	uint32_t nh;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	memcpy(&ipv6_nh_key, &(tpm_rule->ipv6_nh_key), sizeof(tpm_rule_ipv6_nh_key_t));
+	parse_rule_bm = ipv6_nh_key.parse_rule_bm;
+	parse_flags_bm = ipv6_nh_key.parse_flags_bm;
+	nh = ipv6_nh_key.nh;
+	nh_iter = ipv6_nh_key.nh_iter;
+	memcpy(&pkt_frwd, &(ipv6_nh_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
+	memcpy(rule_action, &(ipv6_nh_key.rule_action), sizeof(tpm_rule_action_t));
+	*mod_entry = mod_con->mod_cmd_ind;
+	rule_num = api_ent_mem_area->rule_idx;
+
+	/*******************generate PnC Rule Start********************/
+	/*generate tcam */
+	tpm_ret = tpm_proc_ipv6_nh_tcam_build(rule_num,
+					      nh_iter,
+					      nh,
+					      parse_flags_bm,
+					      rule_action,
+					      &(pnc_data->pncl_tcam));
+	IF_ERROR(tpm_ret);
+	/*generate sram*/
+	tpm_ret = tpm_proc_ipv6_nh_sram_build(rule_num,
+					      nh_iter,
+					      nh,
+					      pon_type,
+					      &pkt_frwd,
+					      rule_action,
+					      &(pnc_data->pncl_sram));
+	IF_ERROR(tpm_ret);
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* api_data2pnc_data_ipv6_l4 - translate IPV6 L4 API data to PNC data
+*
+* INPUT:
+*       pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*	rule_action
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_ipv6_l4(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+				  tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+				  tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+				  tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t parse_rule_bm;
+	tpm_parse_flags_t parse_flags_bm;
+	tpm_dir_t dir = 0;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_rule_ipv6_l4_key_t ipv6_l4_key;
+	tpm_init_ipv6_5t_enable_t ipv6_5t_enable = TPM_IPV6_5T_DISABLED;
+	long long int_pkt_act = 0;
+	uint32_t subflow_bm, subflow_id, protocol = 0;
+	uint32_t rule_num;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	src_port = tpm_rule->ipv6_l4_key.src_port;
+	memcpy(&ipv6_l4_key, &(tpm_rule->ipv6_l4_key), sizeof(tpm_rule_ipv6_l4_key_t));
+	parse_rule_bm = tpm_rule->ipv6_l4_key.parse_rule_bm;
+	parse_flags_bm = tpm_rule->ipv6_l4_key.parse_flags_bm;
+	memcpy(&pkt_frwd, &(tpm_rule->ipv6_l4_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
+	memcpy(rule_action, &(tpm_rule->ipv6_l4_key.rule_action), sizeof(tpm_rule_action_t));
+	*mod_entry = mod_con->mod_cmd_ind;
+	*trg_port = tpm_rule->ipv6_l4_key.pkt_frwd.trg_port;
+	memcpy(pkt_mod, &(tpm_rule->ipv6_l4_key.pkt_mod), sizeof(tpm_pkt_mod_t));
+	*pkt_mod_bm = tpm_rule->ipv6_l4_key.pkt_mod_bm;
+	*int_mod_bm = 0;
+	rule_num = api_ent_mem_area->rule_idx;
+
+	/*check ipv6_5t is enable or not*/
+	tpm_ret = tpm_db_ipv6_5t_enable_get(&ipv6_5t_enable);
+	IF_ERROR(tpm_ret);
+
+	/* Get direction */
+	tpm_ret = tpm_proc_src_port_dir_map(src_port, &dir);
+	IF_ERROR(tpm_ret);
+
+	if (ipv6_5t_enable == TPM_IPV6_5T_DISABLED) {
+		/*generate tcam */
+		tpm_ret = tpm_proc_ipv6_l4ports_tcam_build(src_port,
+							   dir,
+							   rule_num,
+							   &ipv6_l4_key.l4_key,
+							   parse_rule_bm,
+							   parse_flags_bm,
+							   rule_action,
+							   pkt_mod,
+							   *pkt_mod_bm,
+							   &(pnc_data->pncl_tcam));
+		IF_ERROR(tpm_ret);
+
+		/*generate sram*/
+		tpm_ret = tpm_proc_ipv6_l4ports_sram_build(src_port,
+							   dir,
+							   rule_num,
+							   pon_type,
+							   &pkt_frwd,
+							   rule_action,
+							   mod_con->mod_cmd_ind,
+							   &(pnc_data->pncl_sram));
+		IF_ERROR(tpm_ret);
+	} else {
+		/*********** Get Subflow Info **********/
+		subflow_bm = parse_rule_bm & TPM_DB_IPV6_L4_SUBFLOW_PARSE_BM_MASK;
+		if ((parse_flags_bm & TPM_PARSE_FLAG_L4P_MASK) != 0) {
+			if ((parse_flags_bm & TPM_PARSE_FLAG_L4_TCP) != 0)
+				protocol = IPPROTO_TCP;
+			else
+				protocol = IPPROTO_UDP;
+			subflow_bm |= TPM_IPv6_PARSE_NH;
+		}
+		subflow_id = TPM_DB_INVALID_IPV6_FLOW_ID;
+		if (subflow_bm != 0 && rule_action->next_phase != STAGE_DONE) {
+			int_pkt_act |= TPM_ACTION_SET_IPV6_SUBFLOW;
+			subflow_id = tpm_db_find_matched_ipv6_l4_subflow(dir,
+									 subflow_bm,
+									 protocol,
+									 &ipv6_l4_key.l4_key);
+			if (subflow_id == TPM_DB_INVALID_IPV6_FLOW_ID) {
+				printk("Subflow_id get Failed\n");
+				return TPM_FAIL;
+			}
+		} else {
+			int_pkt_act |= TPM_ACTION_UNSET_IPV6_SUBFLOW;
+		}
+		/*generate tcam */
+		tpm_ret = tpm_proc_ipv6_l4_ports_5t_tcam_build(dir,
+							       rule_num,
+							       &ipv6_l4_key.l4_key,
+							       parse_rule_bm,
+							       parse_flags_bm,
+							       rule_action,
+							       pkt_mod,
+							       *pkt_mod_bm,
+							       &(pnc_data->pncl_tcam));
+		IF_ERROR(tpm_ret);
+
+		tpm_ret = tpm_proc_ipv6_l4_ports_5t_sram_build(dir,
+							       rule_num,
+							       pon_type,
+							       subflow_id,
+							       &pkt_frwd,
+							       rule_action,
+							       int_pkt_act,
+							       pkt_mod,
+							       mod_con->mod_cmd_ind,
+							       &(pnc_data->pncl_sram));
+		IF_ERROR(tpm_ret);
+	}
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* api_data2pnc_data_ipv4_cnm - translate IPV4 CnM API data to PNC data
+*
+* INPUT:
+*	pon_type
+*	tpm_rule
+*	mod_con
+*	api_ent_mem_area
+*
+* OUTPUT:
+*	pnc_data
+*	mod_entry
+*	pkt_mod
+*	pkt_mod_bm
+*	int_mod_bm
+*	rule_action
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t api_data2pnc_data_ipv4_cnm(tpm_db_pon_type_t pon_type, tpm_rule_entry_t *tpm_rule, tpm_db_mod_conn_t *mod_con,
+				   tpm_db_api_entry_t *api_ent_mem_area, tpm_pncl_pnc_full_t *pnc_data, uint32_t *mod_entry,
+				   tpm_pkt_mod_t *pkt_mod, tpm_pkt_mod_bm_t *pkt_mod_bm, tpm_pkt_mod_int_bm_t *int_mod_bm,
+				   tpm_trg_port_type_t *trg_port, tpm_rule_action_t *rule_action)
+{
+	tpm_src_port_type_t src_port;
+	tpm_parse_fields_t l2_parse_rule_bm;
+	tpm_parse_fields_t ipv4_parse_rule_bm;
+	tpm_pkt_frwd_t pkt_frwd;
+	tpm_l2_acl_key_t l2_key;
+	tpm_ipv4_acl_key_t ipv4_key;
+	tpm_pkt_action_t pkt_act;
+	tpm_db_ctc_cm_rule_entry_t cnm_rule;
+	uint32_t jump_idx = 0;
+	uint32_t precedence = 0;
+	uint32_t rule_num, pbits;
+	uint32_t ipv4_pre_key_idx = TPM_CNM_INVALID_IPV4_PRE_FILTER_KEY_ID;
+	int32_t tpm_ret = 0;
+
+	/*params check*/
+	tpm_ret = tpm_check_param_check(pon_type, tpm_rule, mod_con, api_ent_mem_area, pnc_data, mod_entry,
+					pkt_mod, pkt_mod_bm, int_mod_bm, trg_port, rule_action);
+	IF_ERROR(tpm_ret);
+
+	/*get params from API db*/
+	src_port = tpm_rule->cnm_key.src_port;
+	ipv4_parse_rule_bm = tpm_rule->cnm_key.ipv4_parse_rule_bm;
+	pkt_act = tpm_rule->cnm_key.pkt_act;
+	pbits = tpm_rule->cnm_key.pbits;
+	l2_parse_rule_bm = tpm_rule->cnm_key.l2_parse_rule_bm;
+	memcpy(&l2_key, &(tpm_rule->cnm_key.l2_key), sizeof(tpm_l2_acl_key_t));
+	memcpy(&ipv4_key, &(tpm_rule->cnm_key.ipv4_key), sizeof(tpm_ipv4_acl_key_t));
+	memcpy(&pkt_frwd, &(tpm_rule->cnm_key.pkt_frwd), sizeof(tpm_pkt_frwd_t));
+	memcpy(&rule_action->pkt_act, &(tpm_rule->cnm_key.pkt_act), sizeof(tpm_pkt_action_t));
+	*mod_entry = mod_con->mod_cmd_ind;
+	*trg_port = tpm_rule->cnm_key.pkt_frwd.trg_port;
+	*pkt_mod_bm = 0;
+	*int_mod_bm = 0;
+	rule_num = api_ent_mem_area->rule_num;
+
+	/*check whether CnM_MAIN_L2 or CnM_MAIN_IPv4*/
+	/*get rule precedence*/
+	tpm_ret = tpm_proc_calc_cnm_precedence(src_port, rule_num, &precedence);
+	IF_ERROR(tpm_ret);
+	/*get cnm rule*/
+	tpm_ret = tpm_db_ctc_cm_rule_get(src_port, precedence, &cnm_rule);
+	IF_ERROR(tpm_ret);
+	/* Get split modification update */
+	if (SET_MOD(pkt_act)) {
+		if (tpm_db_split_mod_get_enable() == TPM_SPLIT_MOD_ENABLED) {
+			/* get mod index from p-bit value */
+			tpm_ret = tpm_db_split_mod_get_index_by_p_bits(pbits, &jump_idx);
+			IF_ERROR(tpm_ret);
+			/* skip first PMT for p-bit AS-IS */
+			jump_idx++;
+		} else {
+			printk("split mod is not active\n");
+			return TPM_FAIL;
+		}
+	}
+	/*check l2_parse_rule_bm*/
+	if (cnm_rule.l2_parse_rule_bm) {
+		/*is CnM L2*/
+		/*get ipv4 pre key index for comb rule if it is*/
+		tpm_ret = tpm_db_find_ipv4_pre_filter_key(src_port,
+							  cnm_rule.ipv4_parse_rule_bm,
+							  &cnm_rule.ipv4_key,
+							  &ipv4_pre_key_idx);
+		/*rebuild tcam*/
+		tpm_ret = tpm_proc_cnm_l2_tcam_build(src_port,
+						     l2_parse_rule_bm,
+						     &l2_key,
+						     ipv4_pre_key_idx,
+						     &pnc_data->pncl_tcam);
+		IF_ERROR(tpm_ret);
+		/*rebuild sram*/
+		tpm_ret = tpm_proc_cnm_l2_sram_build(precedence,
+						     &pkt_frwd,
+						     pkt_act,
+						     jump_idx,
+						     &pnc_data->pncl_sram);
+		IF_ERROR(tpm_ret);
+	} else if ((cnm_rule.ipv4_parse_rule_bm) && (!cnm_rule.l2_parse_rule_bm)) {
+		/*is CnM IPV4*/
+		/*rebuild tcam*/
+		tpm_ret = tpm_proc_cnm_ipv4_tcam_build(src_port,
+						       precedence,
+						       ipv4_parse_rule_bm,
+						       &ipv4_key,
+						       &pnc_data->pncl_tcam);
+		IF_ERROR(tpm_ret);
+		/*rebuild sram*/
+		tpm_ret = tpm_proc_cnm_ipv4_sram_build(&pkt_frwd,
+						       pkt_act,
+						       jump_idx,
+						       &pnc_data->pncl_sram);
+		IF_ERROR(tpm_ret);
+	} else {
+		/*error*/
+		printk("Invalid CnM parse rule bm!\n");
+		tpm_ret = TPM_FAIL;
+		IF_ERROR(tpm_ret);
+	}
+
+	return TPM_OK;
+}
+
+/*pnc rebuild functions array*/
+static tpm_check_rebuild_pnc_t tpm_check_rebuild_pnc_array[TPM_MAX_NUM_API_SECTIONS] = {
+								tpm_check_param_check,
+								api_data2pnc_data_l2,
+								api_data2pnc_data_l3,
+								api_data2pnc_data_ipv4,
+								api_data2pnc_data_ipv4_mc,
+								api_data2pnc_data_ipv6_gen,
+								api_data2pnc_data_ipv6_dip,
+								api_data2pnc_data_ipv6_mc,
+								api_data2pnc_data_ipv6_nh,
+								api_data2pnc_data_ipv6_l4,
+								api_data2pnc_data_ipv4_cnm};
+
+/*******************************************************************************
+* tpm_pmt_rebuild_and_check()
+*
+* DESCRIPTION: The API is to rebuild mod pattern data and check it with HW PMT and DB.
+*
+* INPUTS:   api_type    - the rule to check belong to
+*           rule_index  - the rule index in rule's API range
+*           trg_port    - targe port
+*           pkt_mod_bm  - set of flags described which fields in the packet
+*                         to be changed
+*           int_mod_bm  - set of internal flags
+*           mod_data    - modification entry data
+*           mod_entry   - start entry number which has been set for this
+*                         modification <j>
+*
+* OUTPUTS:
+*           pmt_hw_error_count - check result for HW
+*           pmt_sw_error_count - check result for SW
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_pmt_rebuild_and_check(tpm_api_type_t api_type,
+				  uint32_t rule_index,
+				  tpm_trg_port_type_t trg_port,
+				  tpm_pkt_mod_bm_t pkt_mod_bm,
+				  tpm_pkt_mod_int_bm_t int_mod_bm,
+				  tpm_pkt_mod_t *pkt_mod,
+				  uint32_t *mod_entry,
+				  uint32_t *pmt_hw_error_count,
+				  uint32_t *pmt_sw_error_count)
+{
+	tpm_gmacs_enum_t trg_gmac;
+	tpm_mod_pattern_data_t pattern_data;
+	tpm_main_chain_check_type_t main_chain_check;
+	tpm_error_code_t pmt_check_result;
+	int32_t tpm_ret = 0;
+
+	tpm_ret = tpm_proc_trg_port_gmac_map(trg_port, &trg_gmac);
+	IF_ERROR(tpm_ret);
+
+	/*check main chain type*/
+	if (tpm_check_main_chain_type(trg_gmac, pkt_mod_bm, int_mod_bm, *mod_entry,
+				      &main_chain_check)) {
+		printk("(Warn) main chain type check failed, API: %s, PnC index %d\n",
+			tpm_db_api_type_str[api_type], rule_index);
+	} else if (main_chain_check) {
+		printk("main chain type mismatch, API: %s, PnC index %d\n",
+			tpm_db_api_type_str[api_type], rule_index);
+	}
+
+	/*clear structure*/
+	memset(&pattern_data, 0, sizeof(tpm_mod_pattern_data_t));
+
+	/*build internal mod pattern data*/
+	tpm_ret = tpm_mod2_fill_in_pattern(trg_gmac,
+					   pkt_mod_bm,
+					   int_mod_bm,
+					   pkt_mod,
+					   mod_entry,
+					   &pattern_data,
+					   TPM_CHECK_MAIN_CHAIN_IDX_DB);
+	IF_ERROR(tpm_ret);
+	/*check with DB*/
+	if (tpm_pmt_check(trg_gmac, &pattern_data, &pmt_check_result,
+			  TPM_CHECK_WITH_DB)) {
+		printk("SW PMT check error, API type: %s, PnC rule index %d\n",
+			tpm_db_api_type_str[api_type], rule_index);
+	} else if (pmt_check_result) {
+		*pmt_sw_error_count = *pmt_sw_error_count + 1;
+		printk("SW PMT mismatch, API type: %s, PnC rule index %d\n",
+			tpm_db_api_type_str[api_type], rule_index);
+	}
+	/*clear structure*/
+	memset(&pattern_data, 0, sizeof(tpm_mod_pattern_data_t));
+
+	/*build internal mod pattern data*/
+	tpm_ret = tpm_mod2_fill_in_pattern(trg_gmac,
+					   pkt_mod_bm,
+					   int_mod_bm,
+					   pkt_mod,
+					   mod_entry,
+					   &pattern_data,
+					   TPM_CHECK_MAIN_CHAIN_IDX_HW);
+	IF_ERROR(tpm_ret);
+	/*check with HW*/
+	if (tpm_pmt_check(trg_gmac, &pattern_data, &pmt_check_result,
+			  TPM_CHECK_WITH_HW)) {
+		printk("HW PMT check error, API type: %s, PnC rule index %d\n",
+			tpm_db_api_type_str[api_type], rule_index);
+	} else if (pmt_check_result) {
+		*pmt_hw_error_count = *pmt_hw_error_count + 1;
+		printk("HW PMT mismatch, API type: %s, PnC rule index %d\n",
+			tpm_db_api_type_str[api_type], rule_index);
+	}
+
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_self_check - Check existed TPM rules and PMT table
+*
+* INPUT:
+*       owner_id
+*	check_level, 0--only check, 1--if there's error in HW table,
+*					it will try to correct it, done later
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+* It is APIs caller responsibility to maintain the correct number of each rule.
+*******************************************************************************/
+tpm_error_code_t tpm_self_check(uint32_t owner_id, tpm_self_check_level_enum_t check_level)
+{
+	tpm_api_type_t api_type;
+	tpm_db_api_entry_t api_ent_mem_area;
+	tpm_pncl_pnc_full_t pnc_data;
+	tpm_pnc_all_t pnc_out;
+	tpm_rule_entry_t tpm_rule;
+	tpm_api_sections_t api_section;
+	tpm_db_mod_conn_t mod_con;
+	tpm_db_pnc_conn_t pnc_con;
+	tpm_pkt_mod_int_bm_t int_mod_bm = 0;
+	tpm_pkt_mod_bm_t pkt_mod_bm = 0;
+	tpm_rule_action_t rule_action;
+	tpm_db_pon_type_t pon_type = 0;
+	struct tcam_entry hw_te;
+	tpm_pnc_all_t read_pnc;
+	tpm_pnc_all_t shadow_pnc;
+	tpm_trg_port_type_t trg_port = 0;
+	tpm_pkt_mod_t pkt_mod;
+	tpm_vlan_key_t *vlan_out = NULL;
+	tpm_db_ctc_cm_enable_t ctc_cm_enable = TPM_CTC_CM_DISABLED;
+	uint8_t p_bits_tpm;
+	uint32_t loop;
+	uint32_t rule_num, rule_index, bi_dir;
+	int32_t apisec_last_valid_index;
+	uint32_t mod_entry = 0;
+	uint32_t valid_entry_num = 0;
+	uint32_t shadow_ent_valid;
+	uint32_t hw_jump_idx, shadow_jump_idx;
+	uint32_t p_bits_nums;
+	/*error statisc*/
+	uint32_t pnc_hw_error_count = 0;
+	uint32_t pnc_sw_error_count = 0;
+	uint32_t pmt_hw_error_count = 0;
+	uint32_t pmt_sw_error_count = 0;
+	uint32_t unnormal_end_count = 0;
+	uint32_t section_valid_entry_count = 0;/*the count of api section with valid entry*/
+
+	int32_t tpm_ret = 0;
+
+	/* Get pon_type */
+	if (tpm_db_pon_type_get(&pon_type))
+		return ERR_GENERAL;
+	/* get ctc cm enable status */
+	if (tpm_db_ctc_cm_enable_get(&ctc_cm_enable))
+		return ERR_GENERAL;
+
+	for (api_type = TPM_API_L2_PRIM; api_type <= TPM_API_CNM; api_type++) {
+		/*check whether CnM is enable or not*/
+		if ((api_type == TPM_API_CNM) && (TPM_CTC_CM_DISABLED == ctc_cm_enable))
+			continue;
+		/* Get the api_section */
+		tpm_ret = tpm_db_api_section_get_from_api_type(api_type, &api_section);
+		if (tpm_ret != TPM_RC_OK) {
+			printk("Get API_SECTION Failed-%s\n", tpm_db_api_type_str[api_type]);
+			continue;
+		}
+
+		valid_entry_num = 0;
+		if (tpm_db_api_section_num_entries_get(api_section, &valid_entry_num))
+			continue;
+
+		if (valid_entry_num == 0)
+			continue;
+
+		section_valid_entry_count++;
+
+		/*get the last valid rule index in the api_section*/
+		if (tpm_db_api_section_lastentry_get(api_section, &apisec_last_valid_index))
+			continue;
+
+		/* Get the rulenum index */
+		for (rule_index = 0; rule_index <= apisec_last_valid_index; rule_index++) {
+			/*clear structure*/
+			memset(&pnc_data, 0, sizeof(tpm_pncl_pnc_full_t));
+			memset(&pnc_out, 0, sizeof(tpm_pnc_all_t));
+			memset(&hw_te, 0, sizeof(struct tcam_entry));
+			memset(&read_pnc, 0, sizeof(tpm_pnc_all_t));
+			memset(&shadow_pnc, 0, sizeof(tpm_pnc_all_t));
+			memset(&tpm_rule, 0, sizeof(tpm_rule_entry_t));
+			memset(&rule_action, 0, sizeof(tpm_rule_action_t));
+			memset(&mod_con, 0, sizeof(tpm_db_mod_conn_t));
+			memset(&pnc_con, 0, sizeof(tpm_db_pnc_conn_t));
+			memset(&api_ent_mem_area, 0, sizeof(tpm_db_api_entry_t));
+
+			/*get api section table entry*/
+			if (tpm_db_api_section_ent_tbl_get(api_section, &api_ent_mem_area, rule_index))
+				break;
+
+			if (api_ent_mem_area.valid == TPM_DB_VALID) {
+				/*get tpm_rule*/
+				memcpy(&tpm_rule, &(api_ent_mem_area.api_rule_data),
+					sizeof(tpm_rule_entry_t));
+				memcpy(&mod_con, &(api_ent_mem_area.mod_tbl_conn),
+					sizeof(tpm_db_mod_conn_t));
+				memcpy(&pnc_con, &(api_ent_mem_area.pnc_tbl_conn), sizeof(tpm_db_pnc_conn_t));
+				bi_dir = api_ent_mem_area.bi_dir;
+				rule_num = api_ent_mem_area.rule_idx;
+				tpm_ret = tpm_check_rebuild_pnc_array[api_section](pon_type,
+										   &tpm_rule,
+										   &mod_con,
+										   &api_ent_mem_area,
+										   &pnc_data,
+										   &mod_entry,
+										   &pkt_mod,
+										   &pkt_mod_bm,
+										   &int_mod_bm,
+										   &trg_port,
+										   &rule_action);
+				if (tpm_ret) {
+					printk("API type: %s, the %d th PnC Rule Rebuild Failed\n",
+						tpm_db_api_type_str[api_type], rule_index);
+					unnormal_end_count++;
+					break;
+				}
+				/* TCAM map to tpm_tcam_all_t of tpm_pnc_all_t */
+				tpm_ret = tpm_pncl_tcam_map(&(pnc_data.pncl_tcam), &(pnc_out.tcam_entry));
+				IF_ERROR(tpm_ret);
+
+				/* SRAM  map to tpm_sram_all_t of tpm_pnc_all_t */
+				tpm_ret = tpm_pncl_sram_map(&(pnc_data.pncl_sram),
+							    &(pnc_out.sram_entry),
+							    &(pnc_data.pncl_tcam));
+				IF_ERROR(tpm_ret);
+
+				/*read Pnc from HW table*/
+				tpm_ret = tcam_hw_read(&hw_te, pnc_con.pnc_conn_tbl[0].pnc_index);
+				IF_ERROR(tpm_ret);
+				/*translate tcam_entry to tpm_pnc_all_t*/
+				tran_tcam_entry_to_pnc_all_t(&read_pnc, &hw_te, &rule_action, api_section);
+
+				/*read PnC from PnC shadow table*/
+				tpm_ret = tpm_db_pnc_shdw_ent_get(pnc_con.pnc_conn_tbl[0].pnc_index,
+								  &shadow_ent_valid,
+								  &shadow_pnc);
+				IF_ERROR(tpm_ret);
+
+				/*check PNC*/
+				tpm_check_update_sram(&pnc_out.sram_entry, &rule_action);
+				tpm_check_update_sram(&shadow_pnc.sram_entry, &rule_action);
+				if (memcmp(&pnc_out, &read_pnc, sizeof(tpm_pnc_all_t))) {
+					printk("HW PNC mismatch, API type: %s, PnC rule index %d\n",
+						tpm_db_api_type_str[api_type], rule_index);
+					pnc_mismatch_info_show(&pnc_out, &read_pnc);
+					pnc_hw_error_count++;
+					/*correct the bad tpm rule, TODO done in future*/
+					/*if (check_level == TPM_SELF_CHECK_LEVEL1)*/
+				}
+				if (memcmp(&pnc_out, &shadow_pnc, sizeof(tpm_pnc_all_t))) {
+					printk("SW PNC mismatch, API type: %s, PnC rule index %d\n",
+						tpm_db_api_type_str[api_type], rule_index);
+					pnc_mismatch_info_show(&pnc_out, &shadow_pnc);
+					pnc_sw_error_count++;
+				}
+
+				/*******************check PMT if necessary********************/
+				/*check precondition: SET_MOD, jump_entry index is same in API DB, TPM DB and HW*/
+				/*get HW JUPM Index*/
+				hw_jump_idx = read_pnc.sram_entry.flowid_val & 0xFFF;
+				/*get shadow JUPM Index*/
+				shadow_jump_idx = shadow_pnc.sram_entry.flowid_val & 0xFFF;
+				if (SET_MOD(rule_action.pkt_act) &&
+				    (hw_jump_idx == shadow_jump_idx) &&
+				    (hw_jump_idx == mod_entry)) {
+					/*only modify VLAN and VLAN OP is NOOP, do not check*/
+					if (TPM_VLAN_MOD == pkt_mod_bm && VLANOP_NOOP == pkt_mod.vlan_mod.vlan_op)
+						continue;
+					if ((TPM_API_L2_PRIM == api_type) &&
+					    tpm_split_mod_stage1_check(pkt_mod_bm, &pkt_mod, &rule_action, false)) {
+						int_mod_bm = TPM_INT_SPLIT_MOD;
+						p_bits_nums = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
+						/* VLANOP_EXT_TAG_MOD_INS mod insert VLAN p_bit */
+						if (VLANOP_EXT_TAG_MOD_INS == pkt_mod.vlan_mod.vlan_op)
+							vlan_out = &pkt_mod.vlan_mod.vlan2_out;
+						else
+							vlan_out = &pkt_mod.vlan_mod.vlan1_out;
+						/* AS-IS pmt check */
+						vlan_out->pbit_mask = 0;
+						mod_entry = mod_entry / 16;
+						mod_entry *= 16;
+						tpm_ret = tpm_pmt_rebuild_and_check(api_type,
+										    rule_index,
+										    trg_port,
+										    pkt_mod_bm,
+										    int_mod_bm,
+										    &pkt_mod,
+										    &mod_entry,
+										    &pmt_hw_error_count,
+										    &pmt_sw_error_count);
+						IF_ERROR(tpm_ret);
+						/* supported pbits pmt check */
+						vlan_out->pbit_mask = 0xFF;
+						for (loop = 0; loop < p_bits_nums; loop++) {
+							tpm_ret = tpm_db_split_mod_get_p_bits_by_index(loop, &p_bits_tpm);
+							IF_ERROR(tpm_ret);
+							vlan_out->pbit = p_bits_tpm;
+							mod_entry++;
+							tpm_ret = tpm_pmt_rebuild_and_check(api_type,
+											    rule_index,
+											    trg_port,
+											    pkt_mod_bm,
+											    int_mod_bm,
+											    &pkt_mod,
+											    &mod_entry,
+											    &pmt_hw_error_count,
+											    &pmt_sw_error_count);
+							IF_ERROR(tpm_ret);
+						}
+					} else {
+						/* Normal PMT check */
+						tpm_ret = tpm_pmt_rebuild_and_check(api_type,
+										    rule_index,
+										    trg_port,
+										    pkt_mod_bm,
+										    int_mod_bm,
+										    &pkt_mod,
+										    &mod_entry,
+										    &pmt_hw_error_count,
+										    &pmt_sw_error_count);
+						IF_ERROR(tpm_ret);
+					}
+				}
+
+			}
+		}
+	}
+
+	if (section_valid_entry_count) {
+		if (unnormal_end_count) {
+			if ((pnc_hw_error_count == 0) && (pnc_sw_error_count == 0))
+				printk("\nPartly PNC Check, OK\n");
+			if ((pmt_hw_error_count == 0) && (pmt_sw_error_count == 0))
+				printk("Partly PMT Check, OK\n");
+		} else {
+			if ((pnc_hw_error_count == 0) && (pnc_sw_error_count == 0))
+				printk("\nPNC Check, OK\n");
+			if ((pmt_hw_error_count == 0) && (pmt_sw_error_count == 0))
+				printk("PMT Check, OK\n");
+		}
+	} else {
+		printk("(Warn)No Valid Rule exist, Nothing to check\n");
+	}
+
+	return TPM_RC_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.h
new file mode 100755
index 0000000..a911b9b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_self_check.h
Binary files differ
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.c
new file mode 100755
index 0000000..5a0ea1e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.c
@@ -0,0 +1,1689 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+        this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_sysfs_help.h"
+
+
+
+/**********************************************************************/
+/* ===================================================================*/
+/*             TPM SYSFS CFG HELP FUNCTION                            */
+/* ================================================================== */
+
+
+/*******************************************************************************
+**
+**  sfs_tpm_cfg_index
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_tpm_cfg_index(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "==================================================================================================\n");
+    off += sprintf(buf+off, "cat help_tpm_cfg_index                        - show this help\n");
+    off += sprintf(buf+off, "cat help_frwd_rule_cfg                        - show frwd rule help\n");
+    off += sprintf(buf+off, "cat help_igmp_cfg                             - show IGMP configuration help\n");
+    off += sprintf(buf+off, "cat help_ipv4_key_cfg                         - show IPV4 key ACL help\n");
+    off += sprintf(buf+off, "cat help_ipv4_rule_add                        - show add IPV4 rule help\n");
+
+    off += sprintf(buf+off, "cat help_ipv6_dip_key_cfg                     - show IPV6 DIP key ACL help\n");
+    off += sprintf(buf+off, "cat help_ipv6_ctc_cm_key_cfg                  - show IPV6 CTC key ACL help\n");
+    off += sprintf(buf+off, "cat help_ipv6_dip_rule_add                    - show add IPV6 DIP rule help\n");
+    off += sprintf(buf+off, "cat help_ipv6_l4_ports_rule_add               - show add IPV6 L4 ports rule help\n");
+    off += sprintf(buf+off, "cat help_ipv6_nh_rule_add                     - show add IPV6 NH rule help\n");
+    off += sprintf(buf+off, "cat help_ipv6_gen_key_cfg                     - show IPV6 key ACL help\n");
+    off += sprintf(buf+off, "cat help_ipv6_gen_rule_add                    - show add IPV6 rule help\n");
+
+    off += sprintf(buf+off, "cat help_ctc_cm_rule_add                      - show add CTC CnM rule help\n");
+
+    off += sprintf(buf+off, "cat help_key_rule_delete                      - show key delete from DB table (mod/frwd/vlan/l2/l3/ipv4) help\n");
+    off += sprintf(buf+off, "cat help_l2_key_cfg                           - show L2 key ACL help\n");
+    off += sprintf(buf+off, "cat help_l2_rule_add                          - show add L2 rule help\n");
+    off += sprintf(buf+off, "cat help_l3_key_cfg                           - show L3 key ACL help\n");
+    off += sprintf(buf+off, "cat help_l3_rule_add                          - show add L3 rule help\n");
+    off += sprintf(buf+off, "cat help_mc_ipvx_stream_add                   - show add multicast IPV4 stream help\n");
+    off += sprintf(buf+off, "cat help_mib_reset                            - show MIB reset help\n");
+    off += sprintf(buf+off, "cat help_mod_rule_cfg                         - show mod rule help\n");
+    off += sprintf(buf+off, "cat help_no_mc_stream_add                     - show delete multicast stream help\n");
+    off += sprintf(buf+off, "cat help_no_oam_omci_channel                  - show delete OAM/OMCI channel help\n");
+    off += sprintf(buf+off, "cat help_no_rule_add                          - show delete L2/L3/IPV4/IPV6_xxx/DSCP IPV4/DSCP IPV6/CTC CnM rule help\n");
+    off += sprintf(buf+off, "cat help_oam_omci_channel                     - show OAM/OMCI channel configuration help\n");
+    off += sprintf(buf+off, "cat help_pkt_mod_add                          - show packet modification add help\n");
+    off += sprintf(buf+off, "cat help_pkt_mod_get_del_purge                - show packet modification display, delete. purge help\n");
+    off += sprintf(buf+off, "cat help_rate_limit                           - show queue rate limit/scheduling, entity rate limit help\n");
+    off += sprintf(buf+off, "cat help_rule_table_display                   - show rule table display help\n");
+    off += sprintf(buf+off, "cat help_vlan_rule_cfg                        - show vlan rule help\n");
+    off += sprintf(buf+off, "cat help_delete_entry_rule_table              - show delete rule entry help\n");
+    off += sprintf(buf+off, "cat help_tpm_self_check                       - show TPM check help\n");
+    off += sprintf(buf+off, "cat help_mac_learn_rule_add                   - show add MAC learn rule help\n");
+    off += sprintf(buf+off, "cat help_mac_learn_def_act_set                - show set action of mac learn default rule help\n");
+
+    off += sprintf(buf+off, "==================================================================================================\n");
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_frwd_rule_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_frwd_rule_cfg(char* buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "echo [rule_name] [port_bitmap] [queue] [gem_port]  > frwd_rule_set    - set a forwarding rule\n");
+	off += sprintf(buf+off, "\trule_name           (max 16 chars)Rule name\n");
+	off += sprintf(buf+off, "\tport_bitmap         (hex) see below\n");
+	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_WAN           %#.5X     TPM_TRG_TCONT_0      %#.5X\n",TPM_TRG_PORT_WAN, TPM_TRG_TCONT_0);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_1            %#.5X     TPM_TRG_TCONT_2      %#.5X\n",TPM_TRG_TCONT_1, TPM_TRG_TCONT_2);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_3            %#.5X     TPM_TRG_TCONT_4      %#.5X\n",TPM_TRG_TCONT_3, TPM_TRG_TCONT_4);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_5            %#.5X     TPM_TRG_TCONT_6      %#.5X\n",TPM_TRG_TCONT_5, TPM_TRG_TCONT_6);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_7            %#.5X     TPM_TRG_LLID_0       %#.5X\n",TPM_TRG_TCONT_7, TPM_TRG_LLID_0);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_1             %#.5X     TPM_TRG_LLID_2       %#.5X\n",TPM_TRG_LLID_1, TPM_TRG_LLID_2);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_3             %#.5X     TPM_TRG_LLID_4       %#.5X\n",TPM_TRG_LLID_3, TPM_TRG_LLID_4);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_5             %#.5X     TPM_TRG_LLID_6       %#.5X\n",TPM_TRG_LLID_5, TPM_TRG_LLID_6);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_7             %#.5X     TPM_TRG_UNI_0        %#.5X\n",TPM_TRG_LLID_7, TPM_TRG_UNI_0);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_1              %#.5X     TPM_TRG_UNI_2        %#.5X\n",TPM_TRG_UNI_1, TPM_TRG_UNI_2);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_3              %#.5X     TPM_TRG_UNI_4        %#.5X\n",TPM_TRG_UNI_3, TPM_TRG_UNI_4);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_5              %#.5X     TPM_TRG_UNI_6        %#.5X\n",TPM_TRG_UNI_5, TPM_TRG_UNI_6);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_7              %#.5X     TPM_TRG_UNI_VIRT     %#.5X\n",TPM_TRG_UNI_7, TPM_TRG_UNI_VIRT);
+	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_CPU           %#.5X     TPM_TRG_PORT_UNI_ANY %#.5X\n",TPM_TRG_PORT_CPU, TPM_TRG_PORT_UNI_ANY);
+	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_UNI_CPU_LOOP  %#.5X\n", TPM_TRG_PORT_UNI_CPU_LOOP);
+	off += sprintf(buf+off, "\tqueue               (dec)Queue number\n");
+	off += sprintf(buf+off, "\tgem_port            (dec)GEM port\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_vlan_rule_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_vlan_rule_cfg(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [rule_name] [tpid] [tpid_mask] [vid] [vid_mask] [cfi] [cfi_mask] [pbit] [pbit_mask] > vlan_rule_set        - set a VLAN rule\n");
+    off += sprintf(buf+off, "\trule_name           (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\ttpid                (hex)TPID VLAN Ethertype\n");
+    off += sprintf(buf+off, "\ttpid_mask            (hex)TPID mask\n");
+    off += sprintf(buf+off, "\tvid                 (dec)VID\n");
+    off += sprintf(buf+off, "\tvid_mask            (hex)VID mask\n");
+    off += sprintf(buf+off, "\tcfi                 (dec)CFI\n");
+    off += sprintf(buf+off, "\tcfi_mask            (hex)CFI mask\n");
+    off += sprintf(buf+off, "\tpbit                (dec)P-bits\n");
+    off += sprintf(buf+off, "\tpbit_mask           (hex)P-bits mask\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_mod_rule_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_mod_rule_cfg(char* buf)
+{
+    int off = 0;
+#if 0
+    off += sprintf(buf+off, "echo [rule_name] [proto]                                    > mod_proto_rule_set   - set protocol part of mod rule\n");
+    off += sprintf(buf+off, "\trule_name           (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tprotocol_type       (hex)Protocol\n");
+#endif
+    off += sprintf(buf+off, "echo [rule_name] [mh2b]                                     > mod_mh_rule_set   - set protocol part of mod rule\n");
+    off += sprintf(buf+off, "\trule_name           (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\t                     'dbg_entry' is reserved for PMT debugging\n");
+    off += sprintf(buf+off, "\tmh2b                (hex)2 Bytes Marvell Header\n");
+
+    off += sprintf(buf+off, "\necho [rule_name]   [operation] [vlan_rule_1] [vlan_rule_2] > mod_vlan_rule_set    - set VLAN part of mod rule\n");
+    off += sprintf(buf+off, "\trule_name           (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tvlan_rule_1         (str)VLAN rule (Use vlan_empty for absent rule)\n");
+    off += sprintf(buf+off, "\tvlan_rule_2         (str)VLAN rule (Use vlan_empty for absent rule)\n");
+    off += sprintf(buf+off, "\toperation           (str)VLAN operation\n");
+    off += sprintf(buf+off, "\t\tnone      ext_tag_mod  ext_tag_del  ext_tag_ins  ext_tag_mod_ins  ins_2tag\n");
+    off += sprintf(buf+off, "\t\tmod_2tag  swap_tags    del_2tags    int_tag_mod  split_mod_pbit   ext_tag_del_int_mod\n");
+#if 0
+    off += sprintf(buf+off, "\necho [rule_name] [dscp] [dscpmask]                         > mod_dscp_rule_set      - set dscp part of mod rule\n");
+    off += sprintf(buf+off, "\trule_name           (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tdscp                (dec)DSCP value\n");
+    off += sprintf(buf+off, "\tdscp_mask           (hex)DSCP mask\n");
+#endif
+    off += sprintf(buf+off, "\necho [rule_name] [session] [protocol_type]                 > mod_pppoe_rule_set     - set PPPoE part of mod rule\n");
+    off += sprintf(buf+off, "\trule_name           (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tsession             (dec)Session number\n");
+    off += sprintf(buf+off, "\tprotocol_type       (hex)Protocol type\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [src_port] [dst_port]                     > mod_ipv4_port_rule_set - set IPV4 port part of mod rule\n");
+    off += sprintf(buf+off, "echo [rule_name] [src_port] [dst_port]                       > mod_ipv6_port_rule_set - set IPV6 port part of mod rule\n");
+    off += sprintf(buf+off, "\trule_name           (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tsrc_port            (dec)Source port\n");
+    off += sprintf(buf+off, "\tdst_port            (dec)Destination port\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [srcip] [srcip_mask] [dstip] [dstip_mask] > mod_ipv6_addr_rule_set - set IPV6 address part of mod rule\n");
+    off += sprintf(buf+off, "echo [rule_name] [srcip] [srcip_mask] [dstip] [dstip_mask] > mod_ipv4_addr_rule_set - set IPV4 address part of mod rule\n");
+    off += sprintf(buf+off, "echo [rule_name] [SA] [SA_mask] [DA] [DA_mask]             > mod_mac_addr_rule_set  - set MAC address part of mod rule\n");
+    off += sprintf(buf+off, "\trule_name            (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tMAC  address/mask    aa:bb:cc:dd:ee:ff  where each part is hexadecimal in range 0..FF\n");
+    off += sprintf(buf+off, "\tIPV4 address/mask    w.x.y.z  where each part is decimal value in range 0..255\n");
+    off += sprintf(buf+off, "\tIPV6 address/mask    aaaa:bbbb:cccc:dddd:eeee:ffff:gggg:hhhh  where each part is hexadecimal in range 0..FFFF\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_l2_key_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_l2_key_cfg(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [rule_name] [ether_type]                     > l2_key_ethertype_rule_set  - set ethertype part of L2 ACL key\n");
+    off += sprintf(buf+off, "\trule_name         (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tether_type        (hex)Ethernet type\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [gem_port]                     > l2_key_gemport_rule_set    - set gemport part of L2 ACL key\n");
+    off += sprintf(buf+off, "\trule_name         (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tgem_port          (dec)Ethernet type\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [SA] [SA_mask] [DA] [DA_mask]  > l2_key_mac_addr_rule_set   - set MAC address part of L2 ACL rule\n");
+    off += sprintf(buf+off, "\trule_name         (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tMAC address       aa:bb:cc:dd:ee:ff  where each part is hexadecimal in range 0..FF\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [vlan_rule_1] [vlan_rule_2]    > l2_key_vlan_rule_set       - set VLAN part of L2 ACL rule\n");
+    off += sprintf(buf+off, "\trule_name         (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tvlan_rule_1       (str)VLAN rule name (Use vlan_empty for absent rule)\n");
+    off += sprintf(buf+off, "\tvlan_rule_2       (str)VLAN rule name (Use vlan_empty for absent rule)\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [session] [protocol_type]      > l2_key_pppoe_rule_set      - set PPPoE part of L2 ACL rule\n");
+    off += sprintf(buf+off, "\trule_name         (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tsession           (dec)Session number\n");
+    off += sprintf(buf+off, "\tprotocol_type     (hex)Protocol type\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_l3_key_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_l3_key_cfg(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [rule_name] [ether_type]              > l3_key_ethertype_rule_set  - set ethertype part of L3 ACL key\n");
+    off += sprintf(buf+off, "\trule_name       (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tether_type      (hex)Ethernet type\n");
+
+    off += sprintf(buf+off, "echo [rule name] [session] [protocol_type] > l3_key_pppoe_rule_set      - set PPPoE part of L3 ACL rule\n");
+    off += sprintf(buf+off, "\trule_name       (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tsession         (dec)Session number\n");
+    off += sprintf(buf+off, "\tprotocol_type   (hex)Protocol type\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv4_key_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv4_key_cfg(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [rule_name] [proto]                           > ipv4_key_proto_rule_set - set protocol part of IPV4 ACL rule\n");
+    off += sprintf(buf+off, "\trule_name        (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tproto            (dec)Protocol 0-255\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [dscp] [dscpmask]               > ipv4_key_dscp_rule_set  - set dscp part of IPV4 ACL rule\n");
+    off += sprintf(buf+off, "\trule_name      (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tdscp            (dec)DSCP value 0-63\n");
+    off += sprintf(buf+off, "\tdscp_mask       (hex)DSCP mask  0x0-0xFF\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [src_port] [dst_port]           > ipv4_key_port_rule_set  - set IPV4 port part of IPV4 ACL rule\n");
+    off += sprintf(buf+off, "\trule_name       (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tsrc_port        (dec)Source port\n");
+    off += sprintf(buf+off, "\tdst_port        (dec)Destination port\n");
+
+    off += sprintf(buf+off, "\necho [rule_name] [srcip] [srcip_mask] [dstip] [dstip_mask] > ipv4_key_addr_rule_set  - set IPV4 address part of IPV4 ACL rule\n");
+    off += sprintf(buf+off, "\trule_name       (max 16 chars)Rule name\n");
+    off += sprintf(buf+off, "\tIPV4 address     w.x.y.z  where each part is decimal value in range 0..255\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_mtu_cfg - see
+**
+*******************************************************************************/
+int sfs_help_mtu_cfg(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [enable]                                    > enable_mtu  - enable mtu checking\n");
+    off += sprintf(buf+off, "\tenable                      (dec)0 disable, 1 enable\n");
+    off += sprintf(buf+off, "echo [ipv4_or_ipv6] [direction] [mtu_value]      > set_mtu  - set mtu\n");
+    off += sprintf(buf+off, "\tipv4_or_ipv6                (dec)0 for IPv4, 1 for IPv6\n");
+    off += sprintf(buf+off, "\tdirection                   (dec)0 for DS, 1 for US\n");
+    off += sprintf(buf+off, "\tmtu_value                   (dec)mtu value\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [ipv4_or_ipv6] [direction] [pppoe_mtu_value] > set_pppoe_mtu  - set pppoe mtu\n");
+    off += sprintf(buf+off, "\tipv4_or_ipv6                (dec)0 for IPv4, 1 for IPv6\n");
+    off += sprintf(buf+off, "\tdirection                   (dec)0 for DS, 1 for US\n");
+    off += sprintf(buf+off, "\tpppoe_mtu_value             (dec)pppoe mtu value\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv6_gen_key_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_gen_key_cfg(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [key_name] [DSCP] [DSCP Mask] > ipv6_gen_key_dscp_rule_set  - set dscp key\n");
+    off += sprintf(buf+off, "\tkey_name           (max 16 chars)Key name\n");
+    off += sprintf(buf+off, "\tDSCP               (dec)DSCP\n");
+    off += sprintf(buf+off, "\tDSCP Mask          (hex)DSCP Mask\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [Key_name] [srcip] [srcip_mask] > ipv6_gen_key_sip_rule_set      - set sip key\n");
+    off += sprintf(buf+off, "\tKey_name           (max 16 chars)Key name\n");
+    off += sprintf(buf+off, "\tIPV6 address/mask  aaaa:bbbb:cccc:dddd:eeee:ffff:gggg:hhhh  where each part is hexadecimal in range 0..FFFF\n");
+
+    return(off);
+}
+/*******************************************************************************
+**
+**  sfs_help_ipv6_dip_key_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_dip_key_cfg(char* buf)
+{
+    int off = 0;
+    off += sprintf(buf+off, "echo [Key_name] [dip] [dip_mask] > ipv6_dip_key_rule_set      - set dip key\n");
+    off += sprintf(buf+off, "\tKey_name                (max 16 chars)Key name\n");
+    off += sprintf(buf+off, "\tIPV6 dip address        aaaa:bbbb:cccc:dddd:eeee:ffff:gggg:hhhh  where each part is hexadecimal in range 0..FFFF\n");
+    off += sprintf(buf+off, "\tIPV6 dip address mask   aaaa:bbbb:cccc:dddd:eeee:ffff:gggg:hhhh  where each part is hexadecimal in range 0..FFFF\n");
+
+    return(off);
+}
+/*******************************************************************************
+**
+**  sfs_help_ipv6_ctc_cm_key_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_ctc_cm_key_cfg(char* buf)
+{
+    int off = 0;
+    off += sprintf(buf+off, "echo [ipv6_ctc_Key_name] [ipv6_gen_Key_name] [ipv6_dip_Key_name] [ipv6_l4_Key_name] "
+    "[ipv6_nh] [ipv6_hoplimit] > ipv6_ctc_cm_key_rule_set      - set IPv6 CTC CnM key\n");
+    off += sprintf(buf+off, "\tIPV6 ctc Key name                (max 32 chars)Key name\n");
+    off += sprintf(buf+off, "\tIPV6 gen Key name                (max 32 chars)Key name\n");
+    off += sprintf(buf+off, "\tIPV6 dip Key name                (max 32 chars)Key name\n");
+    off += sprintf(buf+off, "\tIPV6 l4 Key name                 (max 32 chars)Key name\n");
+    off += sprintf(buf+off, "\tIPV6 ipv6 nh                     (dec)Next Header\n");
+    off += sprintf(buf+off, "\tIPV6 ipv6 hoplimit               (dec)Hop Limit\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv6_l4_key_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_l4_key_cfg(char* buf)
+{
+    int off = 0;
+    off += sprintf(buf+off, "echo [Key_name] [src_port] [dst_port] > ipv6_l4_key_rule_set  - set l4 key\n");
+    off += sprintf(buf+off, "\tKey_name                (max 16 chars)Key name\n");
+    off += sprintf(buf+off, "\tsrc_port                (dec)Source port\n");
+    off += sprintf(buf+off, "\tdst_port                (dec)Destination port\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_rule_table_display - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_rule_table_display(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "\necho [table_name]         > rule_table_display  - display table rules\n");
+    off += sprintf(buf+off, "\ttable_name    (str)frwd/vlan/mod/l2/l3/ipv4/ipv6_dip/ipv6_gen/ipv6_l4\n");
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_key_rule_delete - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_key_rule_delete(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [table_name] [rule_name]   > no_rule_set         - clear rule from table\n");
+    off += sprintf(buf+off, "\ttable_name        (str)frwd/vlan/mod/l2key/l3key/ipv4key/ipv6_dip/ipv6_gen/ipv6_l4\n");
+
+    off += sprintf(buf+off, "\trule_name         (str)Name of entry in table\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_l2_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_l2_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [key_name] [frwd_name] [mod_name] [pkt_mod_bm] > l2_rule_add\n");
+    off += sprintf(buf+off, "Creates a new primary L2 processing ACL\n");
+
+    off += sprintf(buf+off, "\towner_id        (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_port        The packet originating source port (WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT/UNI_ANY)\n");
+    off += sprintf(buf+off, "\trule_num        (dec)Entry number to be added to the current ACL\n");
+    off += sprintf(buf+off, "\tparse_rule_bm   (hex)Bitmap containing the significant flags for parsing fields of the packet:\n");
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_MAC_DA             %#.4X\n", TPM_L2_PARSE_MAC_DA);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_MAC_SA             %#.4X\n", TPM_L2_PARSE_MAC_SA);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_ONE_VLAN_TAG       %#.4X\n", TPM_L2_PARSE_ONE_VLAN_TAG);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_TWO_VLAN_TAG       %#.4X\n", TPM_L2_PARSE_TWO_VLAN_TAG);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_ETYPE              %#.4X\n", TPM_L2_PARSE_ETYPE);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_PPPOE_SES          %#.4X\n", TPM_L2_PARSE_PPPOE_SES);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_PPP_PROT           %#.4X\n", TPM_L2_PARSE_PPP_PROT);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_GEMPORT            %#.4X\n", TPM_L2_PARSE_GEMPORT);
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG1_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG1_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG2_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG2_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG2_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG2_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE         %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE        %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_TRUE      %#.4X\n", TPM_PARSE_FLAG_TO_CPU_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_FALSE     %#.4X\n", TPM_PARSE_FLAG_TO_CPU_FALSE);
+    off += sprintf(buf+off, "\taction          (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK              %#.4X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT      %#.4X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE     %#.4X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.4X\n", TPM_ACTION_SET_PKT_MOD);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.4X\n", TPM_ACTION_TO_CPU);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_MTM                  %#.4X\n", TPM_ACTION_MTM);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.4X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SPEC_MC_VID          %#.4X\n", TPM_ACTION_SPEC_MC_VID);
+    off += sprintf(buf+off, "\tnext_phase      (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/done)\n");
+    off += sprintf(buf+off, "\tkey_name        (str)Name of L2 key data which has been defined by user [or l2_key_empty]\n");
+    off += sprintf(buf+off, "\tfrwd_name       (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    off += sprintf(buf+off, "\tmod_name        (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
+    off += sprintf(buf+off, "\tpkt_mod_bm      (str)Bit map of pkt modification data \n");
+    off += sprintf(buf+off, "\t\tTPM_MAC_DA_SET                  %#.6X\n", TPM_MAC_DA_SET);
+    off += sprintf(buf+off, "\t\tTPM_MAC_SA_SET                  %#.6X\n", TPM_MAC_SA_SET);
+    off += sprintf(buf+off, "\t\tTPM_VLAN_MOD                    %#.6X\n", TPM_VLAN_MOD);
+    off += sprintf(buf+off, "\t\tTPM_PPPOE_DEL                   %#.6X\n", TPM_PPPOE_DEL);
+    off += sprintf(buf+off, "\t\tTPM_PPPOE_ADD                   %#.6X\n", TPM_PPPOE_ADD);
+    off += sprintf(buf+off, "\t\tTPM_DSCP_SET                    %#.6X\n", TPM_DSCP_SET);
+    off += sprintf(buf+off, "\t\tTPM_TTL_DEC                     %#.6X\n", TPM_TTL_DEC);
+    off += sprintf(buf+off, "\t\tTPM_IPV4_UPDATE                 %#.6X\n", TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\tTPM_IPV4_SRC_SET                %#.6X\n", TPM_IPV4_SRC_SET);
+    off += sprintf(buf+off, "\t\tTPM_IPV4_DST_SET                %#.6X\n", TPM_IPV4_DST_SET);
+    off += sprintf(buf+off, "\t\tTPM_IPV6_UPDATE                 %#.6X\n", TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\tTPM_HOPLIM_DEC                  %#.6X\n", TPM_HOPLIM_DEC);
+    off += sprintf(buf+off, "\t\tTPM_IPV6_SRC_SET                %#.6X\n", TPM_IPV6_SRC_SET);
+    off += sprintf(buf+off, "\t\tTPM_IPV6_DST_SET                %#.6X\n", TPM_IPV6_DST_SET);
+    off += sprintf(buf+off, "\t\tTPM_L4_SRC_SET                  %#.6X\n", TPM_L4_SRC_SET);
+    off += sprintf(buf+off, "\t\tTPM_L4_DST_SET                  %#.6X\n", TPM_L4_DST_SET);
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_l3_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_l3_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [key_name] [frwd_name] > l3_rule_add\n");
+
+    off += sprintf(buf+off, "Creates a new L3 type processing ACL\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_port         The packet originating source port (WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT/UNI_ANY)\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+    off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_ETYPE              %#.4X\n", TPM_L2_PARSE_ETYPE);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_PPPOE_SES          %#.4X\n", TPM_L2_PARSE_PPPOE_SES);
+    off += sprintf(buf+off, "\t\tTPM_L2_PARSE_PPP_PROT           %#.4X\n", TPM_L2_PARSE_PPP_PROT);
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG1_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG1_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG2_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG2_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG2_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG2_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE         %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE        %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_TRUE      %#.4X\n", TPM_PARSE_FLAG_TO_CPU_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_FALSE     %#.4X\n", TPM_PARSE_FLAG_TO_CPU_FALSE);
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK              %#.2X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT      %#.2X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE     %#.2X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.2X\n", TPM_ACTION_SET_PKT_MOD);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/ctc_cm/done)\n");
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    off += sprintf(buf+off, "\tkey_name         (str)Name of L3 key data which has been defined by user [or l3_key_empty]\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv4_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv4_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [mod_bm] [key_name] [frwd_name] [mod_name] > ipv4_rule_add\n");
+    off += sprintf(buf+off, "Creates a new IPv4 processing ACL\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_port         (str)The packet originating source port (WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT/UNI_ANY)\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+    off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+    off += sprintf(buf+off, "\t\tTPM_IPv4_PARSE_SIP              %#.4X\n", TPM_IPv4_PARSE_SIP);
+    off += sprintf(buf+off, "\t\tTPM_IPv4_PARSE_DIP              %#.4X\n", TPM_IPv4_PARSE_DIP);
+    off += sprintf(buf+off, "\t\tTPM_IPv4_PARSE_DSCP             %#.4X\n", TPM_IPv4_PARSE_DSCP);
+    off += sprintf(buf+off, "\t\tTPM_IPv4_PARSE_PROTO            %#.4X\n", TPM_IPv4_PARSE_PROTO);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_SRC                %#.4X\n", TPM_PARSE_L4_SRC);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_DST                %#.4X\n", TPM_PARSE_L4_DST);
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG1_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG1_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE         %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE        %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_TRUE      %#.4X\n", TPM_PARSE_FLAG_TO_CPU_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_FALSE     %#.4X\n", TPM_PARSE_FLAG_TO_CPU_FALSE);
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK              %#.4X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT      %#.4X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE     %#.4X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.4X\n", TPM_ACTION_SET_PKT_MOD);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.4X\n", TPM_ACTION_TO_CPU);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.4X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_UDP_CHKSUM_CALC      %#.4X\n", TPM_ACTION_UDP_CHKSUM_CALC);
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/ctc_cm/done)\n");
+    off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
+    off += sprintf(buf+off, "\t\tTPM_VLAN_MOD                    %#.4X\n", TPM_VLAN_MOD);
+    off += sprintf(buf+off, "\t\tThis is the only packet modification supported in this version. \n");
+    off += sprintf(buf+off, "\tkey_name         (str)Name of IPv4 key data which has been defined by user [or ipv4_key_empty]\n");
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    off += sprintf(buf+off, "\tmod_name         (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv6_gen_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_gen_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [mod_bm] [key_name] [frwd_name] [mod_name] > ipv6_gen_rule_add\n");
+    off += sprintf(buf+off, "Creates a new IPv6 gen processing ACL\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_port         (str)The packet originating source port (WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT/UNI_ANY)\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+
+    off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+    off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_SIP              %#.4X\n", TPM_IPv6_PARSE_SIP);
+    off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_DSCP             %#.4X\n", TPM_IPv6_PARSE_DSCP);
+    off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_HOPL             %#.4X\n", TPM_IPv6_PARSE_HOPL);
+
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG1_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG1_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE         %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE        %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_TRUE      %#.4X\n", TPM_PARSE_FLAG_TO_CPU_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_FALSE     %#.4X\n", TPM_PARSE_FLAG_TO_CPU_FALSE);
+
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK              %#.2X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT      %#.2X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE     %#.2X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.2X\n", TPM_ACTION_SET_PKT_MOD);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
+
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/done)\n");
+
+    off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
+    off += sprintf(buf+off, "\t\tTPM_VLAN_MOD                    %#.4X\n", TPM_VLAN_MOD);
+    off += sprintf(buf+off, "\t\tThis is the only packet modification supported in this version. \n");
+    off += sprintf(buf+off, "\tkey_name         (str)Name of IPv6 gen key data which has been defined by user [or ipv6_gen_key_empty]\n");
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    off += sprintf(buf+off, "\tmod_name         (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
+
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv6_nh_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_nh_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [rule_num] [parse_flags_bm] [action] [next_phase] [nh_iter] [nh] [frwd_name] > ipv6_nh_acl_rule_add\n");
+    off += sprintf(buf+off, "Creates a new IPv6 NH processing ACL\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE         %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE        %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_TRUE      %#.4X\n", TPM_PARSE_FLAG_TO_CPU_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_FALSE     %#.4X\n", TPM_PARSE_FLAG_TO_CPU_FALSE);
+
+
+
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK              %#.2X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT      %#.2X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE     %#.2X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.2X\n", TPM_ACTION_SET_PKT_MOD);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
+
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ipv6_nh/ipv6_l4/ipv6_gen/ctc_cm/done)\n");
+
+    off += sprintf(buf+off, "\tnh_iter          (dec)0:First Next Header 1:Extension Header\n");
+    off += sprintf(buf+off, "\tnh               (hex)Code of Next Header\n");
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    return(off);
+}
+
+
+/*******************************************************************************
+**
+**  sfs_help_mc_ipvx_stream_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_mc_ipvx_stream_add(char* buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "IPV4: echo [owner_id] [stream] [igmp_mode] [mc_stream_pppoe] [vid] [src_ip] [dst_ip] [ignore] [target_ports] > mc_ipv4_stream_add\n");
+	off += sprintf(buf+off, "Creates a new multicast stream\n");
+
+	off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\tstream           (dec)Stream number\n");
+	off += sprintf(buf+off, "\tigmp_mode        (dec)0-snooping/1-proxy\n");
+	off += sprintf(buf+off, "\tmc_pppoe         (str)true/false.\n");
+	off += sprintf(buf+off, "\tvid              (dec)Vlan Id. When Id is 65535, MC packet is untagged or do not need MC VID check\n");
+	off += sprintf(buf+off, "\tsrc_ip           Source IP address\n");
+	off += sprintf(buf+off, "\tdst_ip           Destination IP address\n");
+	off += sprintf(buf+off, "\tignore           (str)true/false. When true, the source IP address is not part of the key\n");
+	off += sprintf(buf+off, "\ttarget_ports     (hex)Bitmap of port targets \n");
+	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_WAN            %#.4X\n", TPM_TRG_PORT_WAN);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_0             %#.4X\n", TPM_TRG_TCONT_0);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_1             %#.4X\n", TPM_TRG_TCONT_1);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_2             %#.4X\n", TPM_TRG_TCONT_2);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_3             %#.4X\n", TPM_TRG_TCONT_3);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_4             %#.4X\n", TPM_TRG_TCONT_4);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_5             %#.4X\n", TPM_TRG_TCONT_5);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_6             %#.4X\n", TPM_TRG_TCONT_6);
+	off += sprintf(buf+off, "\t\tTPM_TRG_TCONT_7             %#.4X\n", TPM_TRG_TCONT_7);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_0              %#.4X\n", TPM_TRG_LLID_0);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_1              %#.4X\n", TPM_TRG_LLID_1);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_2              %#.4X\n", TPM_TRG_LLID_2);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_3              %#.4X\n", TPM_TRG_LLID_3);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_4              %#.4X\n", TPM_TRG_LLID_4);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_5              %#.4X\n", TPM_TRG_LLID_5);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_6              %#.4X\n", TPM_TRG_LLID_6);
+	off += sprintf(buf+off, "\t\tTPM_TRG_LLID_7              %#.4X\n", TPM_TRG_LLID_7);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_0               %#.5X\n", TPM_TRG_UNI_0);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_1               %#.5X\n", TPM_TRG_UNI_1);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_2               %#.5X\n", TPM_TRG_UNI_2);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_3               %#.5X\n", TPM_TRG_UNI_3);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_4               %#.5X\n", TPM_TRG_UNI_4);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_5               %#.5X\n", TPM_TRG_UNI_5);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_6               %#.5X\n", TPM_TRG_UNI_6);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_7               %#.5X\n", TPM_TRG_UNI_7);
+	off += sprintf(buf+off, "\t\tTPM_TRG_UNI_VIRT            %#.5X\n", TPM_TRG_UNI_VIRT);
+	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_CPU            %#.5X\n", TPM_TRG_PORT_CPU);
+	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_UNI_ANY        %#.5X\n", TPM_TRG_PORT_UNI_ANY);
+	off += sprintf(buf+off, "\t\tTPM_TRG_PORT_UNI_CPU_LOOP   %#.5X\n", TPM_TRG_PORT_UNI_CPU_LOOP);
+
+	off += sprintf(buf+off, "\n\tIPV4 address: dst_ip 224.x.y.z  - 239.x.y.z.  Source address w.x.y.z. Each part is decimal value in range 0..255.\n");
+	off += sprintf(buf+off, "\n\n");
+	off += sprintf(buf+off, "echo [owner_id] [stream] [target_ports] > mc_ipv4_stream_update\n");
+	off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\tstream           (dec)Stream number\n");
+	off += sprintf(buf+off, "\ttarget_ports     (hex)Bitmap of port targets - SEE ABOVE\n");
+
+	off += sprintf(buf+off, "\nIPV6: echo [owner_id] [stream] [igmp_mode] [mc_stream_pppoe] [vid] [src_ip] [dst_ip] [ignore] [target_ports] > mc_ipv6_stream_add\n");
+	off += sprintf(buf+off, "Creates a new multicast stream, params refer to IPv4 MC stream add interface, except dst_ip.\n");
+	off += sprintf(buf+off, "\tIPV6 address: ff00:aabb:bbcc:ccdd:ddee:eeff:1111:2222. Each part is Hex value in range 0..ffff.\n");
+	off += sprintf(buf+off, "\n\n");
+	off += sprintf(buf+off, "echo [owner_id] [stream] [target_ports] > mc_ipv6_stream_update\n");
+	off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\tstream           (dec)Stream number\n");
+	off += sprintf(buf+off, "\ttarget_ports     (hex)Bitmap of port targets - SEE ABOVE\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_igmp_cfg - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_igmp_cfg(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_port] [frwd_mode] > igmp_port_forward_mode_cfg\n");
+    off += sprintf(buf+off, "Configures port forward mode\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_port         (str)Source port - WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_ANY\n");
+    off += sprintf(buf+off, "\tfrwd_mode        (str)Forwarding mode - drop/frwd/snoop\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [owner_id] [queue] > igmp_cpu_queue_cfg\n");
+    off += sprintf(buf+off, "Configures CPU queue for IGMP\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tqueue            (dec)CPU queue 0-7\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [owner_id] [sa_mac] > igmp_proxy_sa_mac\n");
+    off += sprintf(buf+off, "Configures the sa_mac for IGMP proxy\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsa_mac           (hex)Mac address in format, aa:bb:cc:dd:ee:ff\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [owner_id] > mc_vid_key_reset\n");
+    off += sprintf(buf+off, "reset the mc_uni_xlate configuration for all the UNI ports\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [src_port] [mc_uni_xlate_mode] [mc_uni_xlate_vid] > mc_vid_key_set\n");
+    off += sprintf(buf+off, "Configures mc_uni_xlate_mode\n");
+    off += sprintf(buf+off, "\tsrc_port                    (str)Source port - UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT\n");
+    off += sprintf(buf+off, "\tmc_uni_xlate_mode           (dec)uni_xlate_mode\n");
+    off += sprintf(buf+off, "\t\texclude             0\n");
+    off += sprintf(buf+off, "\t\ttransparent         1\n");
+    off += sprintf(buf+off, "\t\tstrip               2\n");
+    off += sprintf(buf+off, "\t\ttranslate           3\n");
+    off += sprintf(buf+off, "\tuni_vid                      (dec)mc uni vid\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [owner_id] [mc_vid] > mc_vid_cfg_set\n");
+    off += sprintf(buf+off, "Configures mc vid, first use mc_vid_key_reset, then mc_vid_key_set to set per uni xlate, at last use mc_vid_cfg_set\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tmc_vid           (dec)mc_vid\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_no_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_no_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [rule_idx]            > no_rule_add_l2                - delete L2 rule from hardware\n");
+    off += sprintf(buf+off, "echo [owner_id] [rule_idx]            > no_rule_add_l3                - delete L3 rule from hardware\n");
+    off += sprintf(buf+off, "echo [owner_id] [rule_idx]            > no_rule_add_ipv4              - delete IPv4 rule from hardware\n");
+    off += sprintf(buf+off, "echo [owner_id] [rule_idx]            > no_rule_add_ipv6_dip_acl      - delete a IPv6 DIP ACL\n");
+    off += sprintf(buf+off, "echo [owner_id] [rule_idx]            > no_rule_add_ipv6_gen_acl      - delete a IPv6 gen ACL\n");
+    off += sprintf(buf+off, "echo [owner_id] [rule_idx]            > no_rule_add_ipv6_l4_ports_acl - delete a IPv6 L4 ports ACL\n");
+    off += sprintf(buf+off, "echo [owner_id] [rule_idx]            > no_rule_add_ipv6_nh_acl       - delete a IPv6 NH ACL\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\trule_idx         (dec)Rule Id returned from the create call\n");
+
+    off += sprintf(buf+off, "\necho [owner_id] [src_port] [precedence]    > no_rule_add_ctc_cm_acl  - delete a CTC cm rule from hardware\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_port         (str)The packet originating source port (UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT)\n");
+    off += sprintf(buf+off, "\tprecedence       (dec)Precedence - 0..7\n");
+
+    off += sprintf(buf+off, "echo [owner_id] [l2key_name]          > no_rule_add_mac_learn         - delete MAC learn rule from hardware\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tl2key_name       (str)Name of L2 key data which define src MAC addr, empty is not allowed\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_no_mc_stream_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_no_mc_stream_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [stream]   > no_mc_stream_add_ipv4   - delete IPV4 multicast stream from hardware\n");
+    off += sprintf(buf+off, "\towner_id   (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tstream     (dec)Stream Id used in the mc create call\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_oam_omci_channel - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_oam_omci_channel(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [rx_q] [llid]             > oam_channel - create OAM management channel\n");
+    off += sprintf(buf+off, "\towner_id   (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\trx_q       (dec)Receive queue\n");
+    off += sprintf(buf+off, "\tllid       (hex)LLID for management\n");
+    off += sprintf(buf+off, "\t\tLLID_0  0x01     LLID_1  0x02    LLID_2  0x04     LLID_3  0x08\n");
+    off += sprintf(buf+off, "\t\tLLID_4  0x10     LLID_5  0x20    LLID_6  0x40     LLID_7  0x80\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [owner_id] [gem_port] [rx_q] [tx_q] [tcont] > omci_channel - create OMCI management channel\n");
+    off += sprintf(buf+off, "\towner_id   (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tgem_port   (dec)OMCI gem port\n");
+    off += sprintf(buf+off, "\trx_q       (dec)Receive queue\n");
+    off += sprintf(buf+off, "\ttx_q       (dec)Transmit queue\n");
+    off += sprintf(buf+off, "\ttcont      (hex)T-CONT for management\n");
+    off += sprintf(buf+off, "\t\tTCONT_0  0x01     TCONT_1  0x02    TCONT_2  0x04     TCONT_3  0x08\n");
+    off += sprintf(buf+off, "\t\tTCONT_4  0x10     TCONT_5  0x20    TCONT_6  0x40     TCONT_7  0x80\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_no_oam_omci_channel - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_no_oam_omci_channel(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] > no_oam_channel   - delete OAM management channel from hardware\n");
+    off += sprintf(buf+off, "echo [owner_id] > no_omci_channel  - delete OMCI management channel from hardware\n");
+    off += sprintf(buf+off, "\towner_id   (dec)Application owner ID\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_setup - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_setup(char* buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "echo [owner_id] [wan_type] [filename] > setup   - tpm setup \n");
+	off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\t[wan_type]       (dec)EPON 0 or GPON 1\n");
+	off += sprintf(buf+off, "\t[filename]       FILENAME/default\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_mib_reset - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_mib_reset(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [reset_level] > mib_reset   - MIB reset\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[reset_level]    (dec)Reset level 0 or 1\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_erase_section - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_erase_section(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [api_type] > erase_section   - erase spceified API section\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[api_type]       (dec)the API PnC section to be deleted\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_flush_vtu - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_flush_vtu(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] > flush_vtu   - flush VTU on Switch\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_flush_atu - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_flush_atu(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] > flush_atu   - flush ATU on Switch\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tflush_type       (dec)0-flush all/1-flush dynamic\n");
+    off += sprintf(buf+off, "\tdb_num           (dec)only 0 is valid since there is only one ATU db\n");
+
+    return(off);
+}
+
+
+/*******************************************************************************
+**
+**  sfs_help_cfg_cpu_lpbk - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_cfg_cpu_lpbk(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [trg_port] [trg_queue] [gem port]  > add_cpu_lpbk   - Add CPU WAN loopback\n");
+    off += sprintf(buf+off, "\t[owner_id ]       (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[trg_port ]       (hex)tcont/llid bitmap, 0x01:tcont0/llid0,..., 0x80: tcont7/llid7\n");
+    off += sprintf(buf+off, "\t[trg_queue]       (dec)Target queue number, 0~7\n");
+    off += sprintf(buf+off, "\t[gem port ]       (dec)GEM port number, 0<gem port<4096, fill 0 in EPON mode\n");
+    off += sprintf(buf+off, "echo [owner_id] [trg_port] [trg_queue] [gem port]  > del_cpu_lpbk   - Del CPU WAN loopback\n");
+    off += sprintf(buf+off, "\t[owner_id ]       (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[trg_port ]       (hex)tcont/llid bitmap, 0x01:tcont0/llid0,..., 0x80: tcont7/llid7\n");
+    off += sprintf(buf+off, "\t[trg_queue]       (dec)Target queue number, 0~7\n");
+    off += sprintf(buf+off, "\t[gem port ]       (dec)GEM port number, 0<gem port<4096, fill 0 in EPON mode\n");
+    off += sprintf(buf+off, "echo [owner_id]                                    > dump_cpu_lpbk  - Dump all valid loopback entry from DB \n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_cfg_age_count - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_cfg_age_count(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [api_group] [lu_num] [lu_reset]        > get_lu_entry   - Get least used PnC entires\n");
+    off += sprintf(buf+off, "\t[owner_id ]       (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[api_group]       (dec)PnC API group, supported TPM API group,l2[%d], L3[%d], L4[%d] \n", TPM_API_L2_PRIM, TPM_API_L3_TYPE, TPM_API_IPV4);
+    off += sprintf(buf+off, "\t[lu_num   ]       (dec)required LU number queue number, 1~100\n");
+    off += sprintf(buf+off, "\t[lu_reset ]       (dec)Whether need to reset PnC aging counter after read it.1: reset after read, 0: do not reset\n");
+    off += sprintf(buf+off, "echo [owner_id] [api_group] [rule_idx] [lu_rule_mask]  > set_count_mask  - Set least used mask of specific PnC entry\n");
+    off += sprintf(buf+off, "\t[owner_id ]       (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[api_group]       (dec)PnC API group, supported TPM API group,l2[%d], L3[%d], L4[%d] \n", TPM_API_L2_PRIM, TPM_API_L3_TYPE, TPM_API_IPV4);
+    off += sprintf(buf+off, "\t[rule_idx ]       (dec)rule index returned when add L2/L3/L4 PnC rules\n");
+    off += sprintf(buf+off, "\t[lu_rule_mask]    (dec)Whether need to mask least used loopup for specific PnC rule.1: mask, 0: enable\n");
+    off += sprintf(buf+off, "echo [owner_id] [api_group] [rule_idx] [hit_reset]     > get_hit_count   - Get hitted counter for specific PnC rules\n");
+    off += sprintf(buf+off, "\t[owner_id ]       (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[api_group]       (dec)PnC API group, supported TPM API group,l2[%d], L3[%d], L4[%d] \n", TPM_API_L2_PRIM, TPM_API_L3_TYPE, TPM_API_IPV4);
+    off += sprintf(buf+off, "\t[rule_idx ]       (dec)rule index returned when add L2/L3/L4 PnC rules\n");
+    off += sprintf(buf+off, "echo [owner_id] [api_group] [lu_thresh_pkts]           > set_lu_thresh   - Set least used threshold for specific counter group\n");
+    off += sprintf(buf+off, "\t[owner_id ]       (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[api_group]       (dec)PnC API group, supported TPM API group,l2[%d], L3[%d], L4[%d] \n", TPM_API_L2_PRIM, TPM_API_L3_TYPE, TPM_API_IPV4);
+    off += sprintf(buf+off, "\t[lu_thresh_pkts ] (dec)Least used lookup threshold in number of packets, 0~67108863\n");
+    off += sprintf(buf+off, "echo [owner_id] [api_group]                            > reset_age_group - Reset aging counter for all the PnC rules in one couter group\n");
+    off += sprintf(buf+off, "\t[owner_id ]       (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[api_group]       (dec)PnC API group, supported TPM API group,l2[%d], L3[%d], L4[%d] \n", TPM_API_L2_PRIM, TPM_API_L3_TYPE, TPM_API_IPV4);
+
+    off += sprintf(buf+off, "echo [owner_id] [api_group] [high_thresh_pkts] [counters_reset] [valid_counters] > get_all_hit_counters - Get all PnC  entires for the API group lower than threshold\n");
+    off += sprintf(buf+off, "\t[owner_id ]       (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\t[api_group]       (dec)PnC API group, supported TPM API group,l2[%d], L3[%d], L4[%d] \n", TPM_API_L2_PRIM, TPM_API_L3_TYPE, TPM_API_IPV4);
+    off += sprintf(buf+off, "\t[high_thresh_pkts](dec)counter high threshold watermark\n");
+    off += sprintf(buf+off, "\t[counters_reset]  (dec)Whether need to reset PnC aging counter after read it.1: reset after read, 0: do not reset\n");
+    off += sprintf(buf+off, "\t[valid_counters]  (dec)The number of entries to read, returns the actually read counters\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_rate_limit - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_rate_limit(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [direction] [sched_entity] [que] [rate_limit] [bucket_size]  > rate_limit_queue_set -  set queue rate limit\n");
+    off += sprintf(buf+off, "\towner_id        (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tdirection       Upstream or downstream (us/ds)\n");
+    off += sprintf(buf+off, "\tsched_entity    WAN/TCONT_0/TCONT_1/../TCONT_7/UNI_ANY\n");
+    off += sprintf(buf+off, "\tque             (dec)Queue id - 0..7\n");
+    off += sprintf(buf+off, "\trate_limit      (dec)> 64\n");
+    off += sprintf(buf+off, "\tbucket_size     (dec)TBD\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [owner_id] [direction] [sched_entity] [rate_limit] [bucket_size]  > rate_limit_if_set   - set interface rate limit\n");
+    off += sprintf(buf+off, "\towner_id        Application owner ID\n");
+    off += sprintf(buf+off, "\tdirection       Upstream or downstream (us/ds)\n");
+    off += sprintf(buf+off, "\tsched_entity    WAN/TCONT_0/TCONT_1/../TCONT_7/UNI_ANY\n");
+    off += sprintf(buf+off, "\trate_limit      (dec)> 64\n");
+    off += sprintf(buf+off, "\tbucket_size     (dec)TBD\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [owner_id] [direction] [sched_entity] [mode] [que] [wrr_weight] > scheduling_mode_queue_set   - configure queue scheduling mode\n");
+    off += sprintf(buf+off, "\towner_id        Application owner ID\n");
+    off += sprintf(buf+off, "\tdirection       Upstream or downstream (us/ds)\n");
+    off += sprintf(buf+off, "\tsched_entity    WAN/TCONT_0/TCONT_1/../TCONT_7/UNI_ANY\n");
+    off += sprintf(buf+off, "\tmode            Strict or weighted round robin - strict/wrr \n");
+    off += sprintf(buf+off, "\tque             (dec)Queue id - 0..7\n");
+    off += sprintf(buf+off, "\twrr_weight      (dec)Weight for wrr\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [owner_id] [rate_limit] [bucket_size] > gmac0_ingr_rate_limit_set - set ingress rate limit for GMAC0 only when no switch init\n");
+    off += sprintf(buf+off, "\towner_id        (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\trate_limit      (dec)> 64\n");
+    off += sprintf(buf+off, "\tbucket_size     (dec)TBD\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [thresh_high] [thresh_low] [port] [tx_port] [tx_queue] [tgt_port] > "
+     					"fc_config_set   - configure CPU port flow control\n");
+    off += sprintf(buf+off, "\tthresh_high     (dec)High threshold (decriptors amount)\n");
+    off += sprintf(buf+off, "\tthresh_low      (dec)Low threshold (decriptors amount)\n");
+    off += sprintf(buf+off, "\tport            (dec)Port to monitor \n");
+    off += sprintf(buf+off, "\ttx_port         (dec)TX port\n");
+    off += sprintf(buf+off, "\ttx_queue        (dec)TX queue\n");
+    off += sprintf(buf+off, "\ttgt_port        (dec)Port to apply FC\n");
+
+    off += sprintf(buf+off, "\n");
+    off += sprintf(buf+off, "echo [us_period] > fc_us_period_set - configure flow control period\n");
+    off += sprintf(buf+off, "\tus_period       (dec)Flow control engine monitoring priod (us)\n");
+    off += sprintf(buf+off, "\n");
+#ifdef TPM_FC_DEBUG
+    off += sprintf(buf+off, "echo [oneshot_hits] > fc_oneshot_set - configure oneshot statistic count\n");
+    off += sprintf(buf+off, "\toneshot_hits    (dec)Flow control engine monitoring oneshot statistics hits count\n");
+    off += sprintf(buf+off, "\t                Setting this value to 0 resets oneshot statistics counters\n");
+    off += sprintf(buf+off, "\n");
+#endif
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_pkt_mod_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_pkt_mod_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo  [trg_port] [mod_bm] [flag] [mod_name] > pkt_mod_eng_entry_add   - add packet modification to mod rule\n");
+    off += sprintf(buf+off, "\ttrg_port   Target port - WAN/TCONT_0/TCONT_1/TCONT_2/TCONT_3/TCONT_4/TCONT_5/TCONT_6/TCONT_7/UNI_ANY\n");
+    off += sprintf(buf+off, "\tmod_bm     (hex)Modification bitmap:\n");
+
+    /* VLAN Operation only */
+    off += sprintf(buf+off, "\t\t0x%05x - VLAN\n", TPM_VLAN_MOD);
+
+    /* IPv4 Napt */
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | TTL | SIP | L4_SRC\n",
+        TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_L4_SRC_SET);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | TTL | DIP | L4_DST\n",
+        TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_DST_SET | TPM_L4_DST_SET);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | VLAN | SIP | L4_SRC | TTL\n",
+        TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_L4_SRC_SET);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | VLAN | DIP | L4_DST | TTL\n",
+        TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_DST_SET | TPM_L4_DST_SET);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | PPPoE ADD | SIP | L4_SRC | TTL\n",
+        TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_ADD | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_L4_SRC_SET);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | PPPoE DEL | DIP | L4_DST | TTL\n",
+        TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_DST_SET | TPM_L4_DST_SET);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | VLAN | PPPoE ADD | SIP | L4_SRC | TTL\n",
+        TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_ADD | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_L4_SRC_SET);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | VLAN | PPPoE DEL | DIP | L4_DST | TTL\n",
+        TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_DST_SET | TPM_L4_DST_SET);
+
+    /* IPv6 Route */
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | DA | SA | HOPLIM\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | DA | SA | VLAN | HOPLIM\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | DA | SA | PPPoE ADD | HOPLIM\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_ADD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | DA | SA | PPPoE DEL | HOPLIM\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | DA | SA | VLAN | PPPoE ADD | HOPLIM\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_ADD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | DA | SA | VLAN | PPPoE DEL | HOPLIM\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+
+    /* IPv4 Route */
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | TTL\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | VLAN | TTL\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | PPPoE ADD | TTL\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_ADD | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | PPPoE DEL | TTL\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | VLAN | PPPoE ADD | TTL\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_ADD | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | VLAN | PPPoE DEL | TTL\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+
+    /* (IPv4) Multicast */
+    off += sprintf(buf+off, "\t\t0x%05x - MH\n", TPM_MH_SET);
+    off += sprintf(buf+off, "\t\t0x%05x - MH | VLAN\n", TPM_MH_SET | TPM_VLAN_MOD);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | MH | SA | TTL\n", TPM_MH_SET | TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | MH | SA | VLAN | TTL\n", TPM_MH_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | MH | DA | SA | PPPoE DEL | TTL\n", TPM_MH_SET | TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | MH | DA | SA | VLAN | PPPoE DEL | TTL\n", TPM_MH_SET | TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | SA | TTL\n", TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | SA | VLAN | TTL\n", TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | PPPoE DEL | TTL\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv4 | DA | SA | VLAN | PPPoE DEL | TTL\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE);
+
+	/* (IPv6) Multicast */
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | MH | SA | HOPLIM\n", TPM_MH_SET | TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | MH | SA | VLAN | HOPLIM\n", TPM_MH_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | MH | DA | SA | PPPoE DEL | HOPLIM\n", TPM_MH_SET | TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | MH | DA | SA | VLAN | PPPoE DEL | HOPLIM\n", TPM_MH_SET | TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | SA | HOPLIM\n", TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | SA | VLAN | HOPLIM\n", TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | DA | SA | PPPoE DEL | HOPLIM\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+    off += sprintf(buf+off, "\t\t0x%05x - IPv6 | DA | SA | VLAN | PPPoE DEL | HOPLIM\n", TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE);
+
+    off += sprintf(buf+off, "\tflag       (hex)Additional packet data:\n");
+    off += sprintf(buf+off, "\t\t0x%03x - TCP\n", TPM_INT_L4_TCP);
+    off += sprintf(buf+off, "\t\t0x%03x - UDP\n", TPM_INT_L4_UDP);
+    off += sprintf(buf+off, "\t\t0x%03x - Split modification flag\n", TPM_INT_SPLIT_MOD);
+    off += sprintf(buf+off, "\t\t0x%03x - Update UDP checksum\n", TPM_INT_UDP_CHECKSUM);
+    off += sprintf(buf+off, "\t\t0x%03x - Multicast modification\n", TPM_INT_MC_MOD);
+
+    off += sprintf(buf+off, "\tmod_name   Name of pkt modification data which has been defined by user\n");
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_pkt_mod_eng - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_pkt_mod_get_del_purge(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo  [trg_port] [mod_idx]       > pkt_mod_eng_entry_del   - delete packet modification from mod rule\n");
+    off += sprintf(buf+off, "echo  [trg_port] [mod_idx]       > pkt_mod_eng_entry_show  - show packet modification\n");
+    off += sprintf(buf+off, "echo  [trg_port]                 > pkt_mod_eng_purge       - delete all packet modifications for given port\n");
+    off += sprintf(buf+off, "\ttrg_port   Target port - WAN/TCONT_0/TCONT_1/TCONT_2/TCONT_3/TCONT_4/TCONT_5/TCONT_6/TCONT_7/UNI_ANY\n");
+    off += sprintf(buf+off, "\tmod_idx    (dec)Modification entry returned from pkt_mod_eng_entry_add\n");
+
+    return(off);
+}
+
+/* jinghuaxxxxxx */
+/*******************************************************************************
+**
+**  sys_help_ipv6_dip_acl_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sys_help_ipv6_dip_acl_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [mod_bm] [key_name] [frwd_name] [mod_name] > ipv6_dip_rule_add\n");
+    off += sprintf(buf+off, "Creates a new IPv6 processing ACL\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_port         (str)The packet originating source port (WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT/UNI_ANY)\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+
+    off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+    off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_DIP              %#.4X\n", TPM_IPv6_PARSE_DIP);
+
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_TRUE        %#.4X\n", TPM_PARSE_FLAG_TAG1_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TAG1_FALSE       %#.4X\n", TPM_PARSE_FLAG_TAG1_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE         %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE        %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_TRUE      %#.4X\n", TPM_PARSE_FLAG_TO_CPU_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_FALSE     %#.4X\n", TPM_PARSE_FLAG_TO_CPU_FALSE);
+
+
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK              %#.2X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT      %#.2X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE     %#.2X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.2X\n", TPM_ACTION_SET_PKT_MOD);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
+
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (l2/l3/ipv4/ipv6_gen/ipv6_dip/ipv6_nh/ipv6_l4/done)\n");
+
+    off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
+    off += sprintf(buf+off, "\t\tTPM_VLAN_MOD                    %#.4X\n", TPM_VLAN_MOD);
+    off += sprintf(buf+off, "\t\tThis is the only packet modification supported in this version. \n");
+
+    off += sprintf(buf+off, "\tkey_name         (str)Name of IPv6 key data which has been defined by user [or ipv6_dip_key_empty]\n");
+
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+
+    off += sprintf(buf+off, "\tmod_name         (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
+
+    return(off);
+}
+
+#if 0
+ int sys_help_del_ipv6_dip_acl_rule          (char *buf)
+{
+     int off = 0;
+
+     off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_idx] [parse_rule_bm] [l2_key_name]    > no_rule_add_l2   - delete L2 rule from hardware\n");
+     off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_idx] [parse_rule_bm] [l3_key_name]    > no_rule_add_l3   - delete L3 rule from hardware\n");
+     off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_idx] [parse_rule_bm] [ipv4_key_name]  > no_rule_add_ipv4 - delete IPV4 rule from hardware\n");
+     off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_idx] [parse_rule_bm] [ipv6_key_name]  > no_rule_add_ipv6 - delete IPV6 rule from hardware\n");
+     off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+     off += sprintf(buf+off, "\tsrc_port         WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_ANY\n");
+     off += sprintf(buf+off, "\trule_idx         (dec)Rule Id returned from the create call\n");
+     off += sprintf(buf+off, "\tparse_rule_bm    (hex)Parsing fields bitmap used when the rule was created\n");
+     off += sprintf(buf+off, "\tkey_name         The key name used when the rule was created\n");
+     off += sprintf(buf+off, "\necho [owner_id] [rule_idx]  > no_rule_add_dscp_ipv4 - delete DSCP IPV4 rule from hardware\n");
+     off += sprintf(buf+off, "echo [owner_id] [rule_idx]  > no_rule_add_dscp_ipv6 - delete DSCP IPV6 rule from hardware\n");
+     off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+     off += sprintf(buf+off, "\trule_idx         (dec)Rule Id returned from the create call\n");
+
+
+     off += sprintf(buf+off, "rule del ipv6 <owner_id> <src_port> <rule_index> \n");
+     off += sprintf(buf+off, "delete an existing IPv6 processing ACL\n");
+
+     off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+     off += sprintf(buf+off, "\tsrc_port          (str)The packet originating source port (WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_ANY)\n");
+     off += sprintf(buf+off, "\rule_index         (dec)Entry index was given when adding the ACL\n");
+
+    return(off);
+}
+int sys_help_del_ipv6_l4_ports_acl_rule     (char *buf)
+ {
+      int off = 0;
+
+      off += sprintf(buf+off, "rule del ipv6 <owner_id>  <rule_index> \n");
+      off += sprintf(buf+off, "delete an existing IPv6 l4 processing ACL\n");
+
+      off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+      off += sprintf(buf+off, "\tsrc_port          (str)The packet originating source port (WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_ANY)\n");
+      off += sprintf(buf+off, "\rule_index         (dec)Entry index was given when adding the ACL\n");
+
+     return(off);
+ }
+
+#endif
+/*******************************************************************************
+**
+**  sfs_help_pkt_mod_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_l4_ports_rule_add     (char *buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_port] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [l4_src_port] [l4_dst_port] [mod_bm] [frwd_name] [mod_name] > ipv6_l4_ports_acl_rule_add\n");
+    off += sprintf(buf+off, "Creates a new IPv6 l4 processing ACL\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_port         (str)The packet originating source port (WAN/UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT/UNI_ANY)\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+
+    off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_SRC                %#.4X\n", TPM_PARSE_L4_SRC);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_DST                %#.4X\n", TPM_PARSE_L4_DST);
+
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE         %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE        %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_TRUE      %#.4X\n", TPM_PARSE_FLAG_TO_CPU_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_TO_CPU_FALSE     %#.4X\n", TPM_PARSE_FLAG_TO_CPU_FALSE);
+
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK              %#.2X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT      %#.2X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE     %#.2X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD          %#.2X\n", TPM_ACTION_SET_PKT_MOD);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_TO_CPU               %#.2X\n", TPM_ACTION_TO_CPU);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_CUST_CPU_PKT_PARSE   %#.2X\n", TPM_ACTION_CUST_CPU_PKT_PARSE);
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ipv6_gen/ipv6_dip/ctc_cm/done)\n");
+    off += sprintf(buf+off, "\tl4_src_port      (dec)L4 source port\n");
+    off += sprintf(buf+off, "\tl4_dst_port      (dec)L4 destination port\n");
+
+
+
+    off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
+    off += sprintf(buf+off, "\t\tTPM_VLAN_MOD                    %#.4X\n", TPM_VLAN_MOD);
+    off += sprintf(buf+off, "\t\tThis is the only packet modification supported in this version. \n");
+
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    off += sprintf(buf+off, "\tmod_name         (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
+
+
+    return(off);
+ }
+
+/*******************************************************************************
+**
+**  sfs_help_delete_entry_rule_table - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_delete_entry_rule_table(char *buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [rule_name]     > delete_entry_frwd_rule_table                - delete a forwarding rule entry\n");
+    off += sprintf(buf+off, "echo [rule_name]     > delete_entry_mod_rule_table                 - delete a modification rule entry\n");
+    off += sprintf(buf+off, "echo [rule_name]     > delete_entry_vlan_rule_table                - delete a VLAN rule entry\n");
+    off += sprintf(buf+off, "echo [l2key_name]    > delete_entry_l2_rule_table                  - delete a L2 key entry\n");
+    off += sprintf(buf+off, "echo [l3key_name]    > delete_entry_l3_rule_table                  - delete a L3 key entry\n");
+    off += sprintf(buf+off, "echo [ipv4key_name]  > delete_entry_ipv4_rule_table                - delete a ipv4 key entry\n");
+    off += sprintf(buf+off, "echo [ipv6_gen]      > delete_entry_ipv6_gen_rule_table            - delete a ipv6_gen key entry\n");
+    off += sprintf(buf+off, "echo [ipv6_dip]      > delete_entry_ipv6_dip_rule_table            - delete a ipv6_dip key entry\n");
+    off += sprintf(buf+off, "echo [ipv6_l4]       > delete_entry_ipv6_l4_rule_table             - delete a ipv6_l4 key entry\n");
+
+    return(off);
+}
+
+
+int sfs_help_send_genquery_to_uni(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "echo [target_ports]	[pkt_num]  > send_genquery_to_uni\n");
+	off += sprintf(buf+off, "send general query to uni ports\n");
+    off += sprintf(buf+off, "\ttarget_ports                  (hex)Bitmap of port targets \n");
+    off += sprintf(buf+off, "\t\tTPM_TRG_UNI_0               %#.4X\n", TPM_TRG_UNI_0);
+    off += sprintf(buf+off, "\t\tTPM_TRG_UNI_1               %#.4X\n", TPM_TRG_UNI_1);
+    off += sprintf(buf+off, "\t\tTPM_TRG_UNI_2               %#.4X\n", TPM_TRG_UNI_2);
+    off += sprintf(buf+off, "\t\tTPM_TRG_UNI_3               %#.4X\n", TPM_TRG_UNI_3);
+    off += sprintf(buf+off, "\t\tTPM_TRG_UNI_4               %#.4X\n", TPM_TRG_UNI_4);
+    off += sprintf(buf+off, "\t\tTPM_TRG_PORT_UNI_ANY        %#.4X\n", TPM_TRG_PORT_UNI_ANY);
+	off += sprintf(buf+off, "\tpkt_num                       (dec)general query packet number send to each UNI port\n");
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv6_gen_5t_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_gen_5t_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_dir] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [mod_bm] [l4_key_name] [gen_key_name] [frwd_name] [mod_name] > ipv6_gen_5t_rule_add\n");
+    off += sprintf(buf+off, "Creates a new IPv6 SIP processing rule of 5-tuple\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_dir          (str)The packet direction (US/DS)\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+
+    off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_SRC                 %#.4X\n", TPM_PARSE_L4_SRC);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_DST                 %#.4X\n", TPM_PARSE_L4_DST);
+    off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_SIP               %#.4X\n", TPM_IPv6_PARSE_SIP);
+
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_L4_UDP            %#.4X\n", TPM_PARSE_FLAG_L4_UDP);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_L4_TCP            %#.4X\n", TPM_PARSE_FLAG_L4_TCP);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE          %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE         %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_PPPOE_TRUE        %#.4X\n", TPM_PARSE_FLAG_PPPOE_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_PPPOE_FALSE       %#.4X\n", TPM_PARSE_FLAG_PPPOE_FALSE);
+
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK               %#.2X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT       %#.2X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE      %#.2X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD           %#.2X\n", TPM_ACTION_SET_PKT_MOD);
+
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ipv6_dip/done)\n");
+
+    off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
+    off += sprintf(buf+off, "\tl4_key_name      (str)Name of IPv6 l4 ports key data which has been defined by user [or ipv6_l4_key_empty]\n");
+    off += sprintf(buf+off, "\tgen_key_name     (str)Name of IPv6 gen key data which has been defined by user [or ipv6_gen_key_empty]\n");
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    off += sprintf(buf+off, "\tmod_name         (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv6_dip_5t_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_dip_5t_rule_add(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_dir] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [mod_bm] [l4_key_name] [gen_key_name] [dip_key_name] [frwd_name] [mod_name] > ipv6_dip_5t_rule_add\n");
+    off += sprintf(buf+off, "Creates a new IPv6 DIP processing rule of 5-tuple\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_dir          (str)The packet direction (US/DS)\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+
+    off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_SRC                 %#.4X\n", TPM_PARSE_L4_SRC);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_DST                 %#.4X\n", TPM_PARSE_L4_DST);
+    off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_SIP               %#.4X\n", TPM_IPv6_PARSE_SIP);
+    off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_DIP               %#.4X\n", TPM_IPv6_PARSE_DIP);
+
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_L4_UDP            %#.4X\n", TPM_PARSE_FLAG_L4_UDP);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_L4_TCP            %#.4X\n", TPM_PARSE_FLAG_L4_TCP);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE          %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE         %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_PPPOE_TRUE        %#.4X\n", TPM_PARSE_FLAG_PPPOE_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_PPPOE_FALSE       %#.4X\n", TPM_PARSE_FLAG_PPPOE_FALSE);
+
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK               %#.2X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT       %#.2X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE      %#.2X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD           %#.2X\n", TPM_ACTION_SET_PKT_MOD);
+
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (done)\n");
+    off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
+    off += sprintf(buf+off, "\tl4_key_name      (str)Name of IPv6 key data which has been defined by user [or ipv6_l4_key_empty]\n");
+    off += sprintf(buf+off, "\tgen_key_name     (str)Name of IPv6 key data which has been defined by user [or ipv6_gen_key_empty]\n");
+    off += sprintf(buf+off, "\tdip_key_name     (str)Name of IPv6 key data which has been defined by user [or ipv6_dip_key_empty]\n");
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    off += sprintf(buf+off, "\tmod_name         (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ipv6_l4_ports_5t_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ipv6_l4_ports_5t_rule_add(char *buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [src_dir] [rule_num] [parse_rule_bm] [parse_flags_bm] [action] [next_phase] [mod_bm] [l4_key_name] [frwd_name] [mod_name] > ipv6_l4_ports_5t_rule_add\n");
+    off += sprintf(buf+off, "Creates a new IPv6 L4 ports processing rule of 5-tuple\n");
+
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tsrc_dir          (str)The packet direction (US/DS)\n");
+    off += sprintf(buf+off, "\trule_num         (dec)Entry number to be added to the current ACL\n");
+
+    off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_SRC                 %#.4X\n", TPM_PARSE_L4_SRC);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_L4_DST                 %#.4X\n", TPM_PARSE_L4_DST);
+
+    off += sprintf(buf+off, "\tparse_flags_bm   (hex)Bitmap containing the significant flags result of the primary ACL filtering\n");
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_L4_UDP            %#.4X\n", TPM_PARSE_FLAG_L4_UDP);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_L4_TCP            %#.4X\n", TPM_PARSE_FLAG_L4_TCP);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_TRUE          %#.4X\n", TPM_PARSE_FLAG_MTM_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_MTM_FALSE         %#.4X\n", TPM_PARSE_FLAG_MTM_FALSE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_PPPOE_TRUE        %#.4X\n", TPM_PARSE_FLAG_PPPOE_TRUE);
+    off += sprintf(buf+off, "\t\tTPM_PARSE_FLAG_PPPOE_FALSE       %#.4X\n", TPM_PARSE_FLAG_PPPOE_FALSE);
+
+    off += sprintf(buf+off, "\taction           (hex)Action associated with the rule:\n");
+    off += sprintf(buf+off, "\t\tTPM_ACTION_DROP_PK               %#.2X\n", TPM_ACTION_DROP_PK);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT       %#.2X\n", TPM_ACTION_SET_TARGET_PORT);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE      %#.2X\n", TPM_ACTION_SET_TARGET_QUEUE);
+    off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD           %#.2X\n", TPM_ACTION_SET_PKT_MOD);
+
+    off += sprintf(buf+off, "\tnext_phase       (str)Parse stage (ipv6_gen/ctc_cm/done)\n");
+    off += sprintf(buf+off, "\tmod_bm           (hex)Packet fields modification command bitmap:\n");
+    off += sprintf(buf+off, "\tl4_key_name      (str)Name of IPv6 key data which has been defined by user [or ipv6_l4_key_empty]\n");
+    off += sprintf(buf+off, "\tfrwd_name        (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+    off += sprintf(buf+off, "\tmod_name         (str)Name of pkt modification data which has been defined by user [or mod_empty]\n");
+
+    return(off);
+ }
+
+/*******************************************************************************
+**
+**  sfs_help_ctc_cm_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ctc_cm_rule_add(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "echo [owner_id] [src_port] [precedence] [l2_parse_rule_bm] [ipv4_parse_rule_bm] [action] [l2_key_name] [ipv4_key_name] [frwd_name] [p_bits] > ctc_cm_acl_rule_add\n");
+	off += sprintf(buf+off, "Creates a CTC CnM rule\n");
+
+	off += sprintf(buf+off, "\towner_id           (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\tsrc_port           (str)The packet originating source port (UNI_0/UNI_1/UNI_2/UNI_3/UNI_4/UNI_5/UNI_6/UNI_7/UNI_VIRT)\n");
+	off += sprintf(buf+off, "\tprecedence         (dec)Precedence - 0..7\n");
+
+	off += sprintf(buf+off, "\tl2_parse_rule_bm   (hex)Bitmap containing the significant flags for parsing fields of the packet:\n");
+	off += sprintf(buf+off, "\t\tTPM_L2_PARSE_MAC_DA             %#.4X\n", TPM_L2_PARSE_MAC_DA);
+	off += sprintf(buf+off, "\t\tTPM_L2_PARSE_MAC_SA             %#.4X\n", TPM_L2_PARSE_MAC_SA);
+	off += sprintf(buf+off, "\t\tTPM_L2_PARSE_ONE_VLAN_TAG       %#.4X\n", TPM_L2_PARSE_ONE_VLAN_TAG);
+	off += sprintf(buf+off, "\t\tTPM_L2_PARSE_ETYPE              %#.4X\n", TPM_L2_PARSE_ETYPE);
+
+	off += sprintf(buf+off, "\tipv4_parse_rule_bm (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+	off += sprintf(buf+off, "\t\tTPM_IPv4_PARSE_SIP                 %#.4X\n", TPM_IPv4_PARSE_SIP);
+	off += sprintf(buf+off, "\t\tTPM_IPv4_PARSE_DIP                 %#.4X\n", TPM_IPv4_PARSE_DIP);
+	off += sprintf(buf+off, "\t\tTPM_IPv4_PARSE_DSCP                %#.4X\n", TPM_IPv4_PARSE_DSCP);
+	off += sprintf(buf+off, "\t\tTPM_IPv4_PARSE_PROTO               %#.4X\n", TPM_IPv4_PARSE_PROTO);
+	off += sprintf(buf+off, "\t\tTPM_PARSE_L4_SRC                   %#.4X\n", TPM_PARSE_L4_SRC);
+	off += sprintf(buf+off, "\t\tTPM_PARSE_L4_DST                   %#.4X\n", TPM_PARSE_L4_DST);
+
+	off += sprintf(buf+off, "\taction	           (hex)Action associated with the rule:\n");
+	off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_PORT      %#.4X\n", TPM_ACTION_SET_TARGET_PORT);
+	off += sprintf(buf+off, "\t\tTPM_ACTION_SET_TARGET_QUEUE     %#.4X\n", TPM_ACTION_SET_TARGET_QUEUE);
+	off += sprintf(buf+off, "\t\tTPM_ACTION_SET_PKT_MOD	        %#.4X\n", TPM_ACTION_SET_PKT_MOD);
+
+	off += sprintf(buf+off, "\tl2_key_name        (str)Name of L2 key data which has been defined by user [or l2_key_empty]\n");
+	off += sprintf(buf+off, "\tipv4_key_name      (str)Name of IPV4 key data which has been defined by user [or ipv4_key_empty]\n");
+	off += sprintf(buf+off, "\tfrwd_name          (str)Name of pkt forwarding data which has been defined by user [or frwd_empty]\n");
+	off += sprintf(buf+off, "\tp_bits             (dec)P_bit  - 0..7\n");
+
+	off += sprintf(buf+off, "\necho [owner_id] [src_port] [precedence] [ipv6_parse_rule_bm] [action] [ipv6_key_name] [frwd_name] [p_bits] > ctc_cm_ipv6_acl_rule_add\n");
+	off += sprintf(buf+off, "Creates a CTC CnM rule\n");
+
+	off += sprintf(buf+off, "\towner_id           (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\tparse_rule_bm    (hex)Bitmap containing the significant flags for parsing fields of the packet\n");
+	off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_SIP              %#.4X\n", TPM_IPv6_PARSE_SIP);
+	off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_DIP              %#.4X\n", TPM_IPv6_PARSE_DIP);
+	off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_DSCP             %#.4X\n", TPM_IPv6_PARSE_DSCP);
+	off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_NH               %#.4X\n", TPM_IPv6_PARSE_NH);
+	off += sprintf(buf+off, "\t\tTPM_IPv6_PARSE_HOPL             %#.4X\n", TPM_IPv6_PARSE_HOPL);
+	off += sprintf(buf+off, "\t\tTPM_PARSE_L4_SRC                %#.4X\n", TPM_PARSE_L4_SRC);
+	off += sprintf(buf+off, "\t\tTPM_PARSE_L4_DST                %#.4X\n", TPM_PARSE_L4_DST);
+
+	return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_ctc_cm_set_ipv6_parse_win - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_ctc_cm_set_ipv6_parse_win(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "echo [owner_id] [ipv6_parse_win] > ctc_cm_set_ipv6_parse_win   - set ipv6 parse window\n");
+    off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+    off += sprintf(buf+off, "\tipv6_parse_win   (dec)ipv6 parse window\n");
+    off += sprintf(buf+off, "\t\tTPM_CTC_CM_IPv6_FIRST_24B	 %d\n", TPM_CTC_CM_IPv6_FIRST_24B);
+    off += sprintf(buf+off, "\t\tTPM_CTC_CM_IPv6_SECOND_24B	 %d\n", TPM_CTC_CM_IPv6_SECOND_24B);
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_help_tpm_self_check - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_tpm_self_check(char* buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "echo [owner_id] [check_level] > tpm_self_check   - tpm rules check\n");
+	off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\t[check_level]    (dec)0: check without correct; 1: check with correct\n");
+
+	return(off);
+}
+
+
+/*******************************************************************************
+**
+**  sfs_help_mac_learn_rule_add - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_mac_learn_rule_add(char* buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "echo [owner_id] [l2_key_name] > mac_learn_rule_add\n");
+	off += sprintf(buf+off, "Creates a new L2 MAC learn rule ACL\n");
+	off += sprintf(buf+off, "\towner_id         (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\tl2_key_name      (str)Name of L2 key data which define src MAC addr, empty is not allowed \n");
+
+	return(off);
+
+}
+
+/*******************************************************************************
+**
+**  sfs_help_mac_learn_def_act_set - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_help_mac_learn_def_act_set(char* buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "echo [owner_id] [mac_conf] > mac_learn_default_rule_act_set\n");
+	off += sprintf(buf+off, "Set the action of mac learn default rule\n");
+	off += sprintf(buf+off, "\towner_id        (dec)Application owner ID\n");
+	off += sprintf(buf+off, "\tmac_conf        (hex)Action associated with mac learn default rule: \n");
+	off += sprintf(buf+off, "\t\tTPM_UNK_MAC_TRAP,     (trap packet to CPU)     %#.2X\n", TPM_UNK_MAC_TRAP);
+	off += sprintf(buf+off, "\t\tTPM_UNK_MAC_DROP,     (drop the packet)        %#.2X\n", TPM_UNK_MAC_DROP);
+	off += sprintf(buf+off, "\t\tTPM_UNK_MAC_CONTINUE, (frwd packet to GMAC1)   %#.2X\n", TPM_UNK_MAC_CONTINUE);
+
+	return(off);
+
+}
+
+
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.h
new file mode 100755
index 0000000..6bac650
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_help.h
@@ -0,0 +1,199 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_usr_tpmsysfs_help.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   Zeev
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               $Revision: 1.1.1.1 $
+*
+*
+*******************************************************************************/
+#ifndef _TPM_USR_TPM_SYSFS_HELP_H_
+#define _TPM_USR_TPM_SYSFS_HELP_H_
+
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+extern int sfs_tpm_cfg_index                (char *buf);
+extern int sfs_help_frwd_rule_cfg           (char *buf);
+extern int sfs_help_vlan_rule_cfg           (char *buf);
+extern int sfs_help_mod_rule_cfg            (char *buf);
+extern int sfs_help_l2_key_cfg              (char *buf);
+extern int sfs_help_l3_key_cfg              (char *buf);
+extern int sfs_help_ipv4_key_cfg            (char *buf);
+extern int sfs_help_mtu_cfg                 (char *buf);
+extern int sfs_help_ipv6_gen_key_cfg        (char *buf);
+extern int sfs_help_rule_table_display      (char *buf);
+extern int sfs_help_ipv6_dip_key_cfg        (char *buf);
+extern int sfs_help_ipv6_l4_key_cfg         (char *buf);
+extern int sfs_help_ipv6_ctc_cm_key_cfg     (char *buf);
+extern int sfs_help_key_rule_delete         (char *buf);
+extern int sfs_help_l2_rule_add             (char *buf);
+extern int sfs_help_l3_rule_add             (char *buf);
+extern int sfs_help_ipv4_rule_add           (char *buf);
+extern int sfs_help_ipv6_gen_rule_add       (char *buf);
+extern int sfs_help_ipv6_nh_rule_add        (char *buf);
+extern int sfs_help_mc_ipvx_stream_add      (char *buf);
+extern int sfs_help_igmp_cfg                (char *buf);
+extern int sfs_help_no_rule_add             (char *buf);
+extern int sfs_help_no_mc_stream_add        (char *buf);
+extern int sfs_help_oam_omci_channel        (char *buf);
+extern int sfs_help_no_oam_omci_channel     (char *buf);
+extern int sfs_help_setup                   (char *buf);
+extern int sfs_help_mib_reset               (char *buf);
+extern int sfs_help_cfg_cpu_lpbk            (char *buf);
+extern int sfs_help_cfg_age_count           (char *buf);
+extern int sfs_help_rate_limit              (char *buf);
+extern int sfs_help_pkt_mod_add             (char *buf);
+extern int sfs_help_pkt_mod_get_del_purge   (char *buf);
+
+/* jinghuaxxxxxx */
+extern int sys_help_ipv6_dip_acl_rule_add   (char *buf);
+//extern int sys_help_del_ipv6_dip_acl_rule (char *buf);
+extern int sfs_help_ipv6_l4_ports_rule_add  (char *buf);
+
+extern int sfs_help_delete_entry_rule_table (char *buf);
+extern int sfs_help_send_genquery_to_uni    (char *buf);
+
+//extern int sys_help_del_ipv6_l4_ports_acl_rule  (char *buf);
+/* jinghuaxxxxxx */
+
+extern int sfs_help_ipv6_gen_5t_rule_add     (char *buf);
+extern int sfs_help_ipv6_dip_5t_rule_add     (char *buf);
+extern int sfs_help_ipv6_l4_ports_5t_rule_add(char *buf);
+extern int sfs_help_ctc_cm_set_ipv6_parse_win(char *buf);
+
+extern int sfs_help_ctc_cm_rule_add         (char *buf);
+
+extern int sfs_help_erase_section           (char *buf);
+extern int sfs_help_tpm_self_check          (char* buf);
+extern int sfs_help_flush_vtu               (char *buf);
+extern int sfs_help_flush_atu               (char *buf);
+extern int sfs_help_mac_learn_rule_add      (char *buf);
+extern int sfs_help_mac_learn_def_act_set   (char* buf);
+#else
+
+#define  sfs_tpm_cfg_index                NULL
+#define  sfs_help_frwd_rule_cfg           NULL
+#define  sfs_help_vlan_rule_cfg           NULL
+#define  sfs_help_mod_rule_cfg            NULL
+#define  sfs_help_l2_key_cfg              NULL
+#define  sfs_help_l3_key_cfg              NULL
+#define  sfs_help_ipv4_key_cfg            NULL
+#define  sfs_help_mtu_cfg                 NULL
+#define  sfs_help_ipv6_gen_key_cfg        NULL
+#define  sfs_help_rule_table_display      NULL
+#define  sfs_help_ipv6_ctc_cm_key_cfg     NULL
+#define  sfs_help_ipv6_dip_key_cfg        NULL
+#define  sfs_help_ipv6_l4_key_cfg         NULL
+#define  sfs_help_key_rule_delete         NULL
+#define  sfs_help_l2_rule_add             NULL
+#define  sfs_help_l3_rule_add             NULL
+#define  sfs_help_ipv4_rule_add           NULL
+#define  sfs_help_ipv6_gen_rule_add       NULL
+#define  sfs_help_ipv6_nh_rule_add        NULL
+#define  sfs_help_mc_ipvx_stream_add      NULL
+#define  sfs_help_igmp_cfg                NULL
+#define  sfs_help_no_rule_add             NULL
+#define  sfs_help_no_mc_stream_add        NULL
+#define  sfs_help_oam_omci_channel        NULL
+#define  sfs_help_no_oam_omci_channel     NULL
+#define  sfs_help_setup                   NULL
+#define  sfs_help_mib_reset               NULL
+#define  sfs_help_erase_section           NULL
+#define  sfs_help_cfg_cpu_lpbk            NULL
+#define  sfs_help_cfg_age_count           NULL
+#define  sfs_help_rate_limit              NULL
+#define  sfs_help_pkt_mod_add             NULL
+#define  sfs_help_pkt_mod_get_del_purge   NULL
+#define  sys_help_ipv6_dip_acl_rule_add   NULL
+#define  sfs_help_ipv6_l4_ports_rule_add  NULL
+#define  sfs_help_delete_entry_rule_table NULL
+#define  sfs_help_send_genquery_to_uni    NULL
+#define  sfs_help_tpm_self_check          NULL
+
+
+#define  sfs_help_ipv6_gen_5t_rule_add       NULL
+#define  sfs_help_ipv6_dip_5t_rule_add       NULL
+#define  sfs_help_ipv6_l4_ports_5t_rule_add  NULL
+#define  sfs_help_ctc_cm_set_ipv6_parse_win  NULL
+
+#define sfs_help_ctc_cm_rule_add          NULL
+#define sfs_help_flush_vtu           NULL
+#define sfs_help_flush_atu           NULL
+#define sfs_help_mac_learn_rule_add       NULL
+#define sfs_help_mac_learn_def_act_set    NULL
+
+
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+#endif  /* _TPM_USR_TPM_SYSFS_HELP_H_*/
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.c
new file mode 100755
index 0000000..702bba6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.c
@@ -0,0 +1,6378 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+        this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <linux/ctype.h>
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_sysfs_utils.h"
+#include "tpm_sysfs_help.h"
+#include "tpm_sysfs_hwcall.h"
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+extern struct semaphore    tpm_sfs_2_ioctl_sem;
+extern tpm_ioctl_mng_t     tpm_sfs_2_ioctl_command;
+ #define PR_RULE_IDX(rule_idx)  {}
+ #define PR_HIT_COUNT(hit_count){}
+ #define PR_RESULT              {}
+ #define PR_MAC_COUNT           {}
+#else
+ #define PR_RULE_IDX(rule_idx)  {printk(KERN_INFO "OK. rule_idx = %d\n", rule_idx);}
+ #define PR_HIT_COUNT(hit_count){printk(KERN_INFO "OK. hit_count = %d\n", hit_count);}
+ #define PR_RESULT              {printk(KERN_INFO "OK.\n");}
+ #define PR_MAC_COUNT(count)    {printk(KERN_INFO "OK. mac_learn_entry_count = %d\n", count);}
+#endif
+
+static char *l2_key_empty_name   = "l2_key_empty";
+static char *l3_key_empty_name   = "l3_key_empty";
+static char *ipv4_key_empty_name = "ipv4_key_empty";
+static char *ipv6_key_empty_name = "ipv6_key_empty";
+static char *frwd_empty_name     = "frwd_empty";
+static char *mod_empty_name      = "mod_empty";
+char *ipv6_gen_key_empty_name = "ipv6_gen_key_empty";
+char *ipv6_dip_key_empty_name = "ipv6_dip_key_empty";
+char *ipv6_l4_key_empty_name = "ipv6_l4_key_empty";
+
+extern int32_t module_tpmSetup(tpm_setup_t *tpm_initp);
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_l2_rule_bounce(uint32_t                owner_id,
+                                        tpm_src_port_type_t     src_port,
+                                        uint32_t                rule_num,
+                                        uint32_t               *rule_idx,
+                                        tpm_parse_fields_t      parse_rule_bm,
+                                        tpm_parse_flags_t       parse_flags_bm,
+                                        tpm_l2_acl_key_t       *l2_key,
+                                        tpm_pkt_frwd_t         *pkt_frwd,
+                                        tpm_pkt_mod_t          *pkt_mod,
+                                        tpm_pkt_mod_bm_t        pkt_mod_bm,
+                                        tpm_rule_action_t      *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                   = MV_TPM_IOCTL_ADD_L2_ACL_RULE;
+    tpm_add_acl_rule->owner_id                      = owner_id;
+    tpm_add_acl_rule->src_port                      = src_port;
+    tpm_add_acl_rule->rule_num                      = rule_num;
+    tpm_add_acl_rule->parse_rule_bm                 = parse_rule_bm;
+    tpm_add_acl_rule->l2_acl_rule.parse_flags_bm    = parse_flags_bm;
+    tpm_add_acl_rule->l2_acl_rule.pkt_mod_bm        = pkt_mod_bm;
+    memcpy(&(tpm_add_acl_rule->l2_acl_rule.l2_key),         (void*)l2_key,      sizeof(tpm_l2_acl_key_t));
+    memcpy(&(tpm_add_acl_rule->l2_acl_rule.pkt_frwd),       (void*)pkt_frwd,    sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->l2_acl_rule.pkt_mod),        (void*)pkt_mod,     sizeof(tpm_pkt_mod_t));
+    memcpy(&(tpm_add_acl_rule->l2_acl_rule.rule_action),    (void*)rule_action, sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_l2_rule tpm_add_l2_rule_bounce
+#else
+ #define _tpm_add_l2_rule tpm_add_l2_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l2_rule_add
+*
+* DESCRIPTION:
+*           This function creates a L2 rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l2_rule_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l2ruleadd_owner=0, l2ruleadd_srcport, l2ruleadd_rulenum, l2ruleadd_parserulebm, l2ruleadd_parseflagbm, l2ruleadd_action,  l2ruleadd_nextphase,
+        l2ruleadd_l2keyname, l2ruleadd_frwdname, l2ruleadd_modname, l2ruleadd_pktmodbm, l2ruleadd_max
+    } l2ruleadd_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    char                     srcport_str[20];
+    char                     uc_srcport_str[20];
+    int                      indx;
+    uint32_t                 src_port;
+    uint32_t                 rulenum;
+    uint32_t                 parserulebm;
+    uint32_t                 parseflagbm;
+    uint32_t                 pkt_mod_bm;
+    uint32_t                 action;
+    char                     nextphase_str[20];
+    uint32_t                 nextphase;
+    char                     l2keyname[20];
+    char                     frwdname[20];
+    char                     modname[20];
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    tpmcfg_frwd_entry_t      *pdbfrwdentry  = 0;
+    tpmcfg_l2_key_entry_t    *pdbl2keyentry = 0;
+    tpmcfg_mod_entry_t       *pdbmodentry = 0;
+    //Used in API call
+    tpm_rule_action_t        rule_action;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_l2_acl_key_t         l2_acl;
+    tpm_pkt_mod_t            pkt_mod;
+    uint32_t                 rule_idx;
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != l2ruleadd_max)
+    {
+        parm_error_completion(numparms, l2ruleadd_max, buf, sfs_help_l2_rule_add);
+//        if (numparms == 1 && buf[0] == '?')
+//        {
+//            char helpbuf[3000];
+//            int  helpbuf_len;
+//
+//            helpbuf_len = sfs_help_l2_rule_add(helpbuf);
+//            print_help_buffer(helpbuf, helpbuf_len);
+//        }
+//        else
+//        {
+//            printk(KERN_INFO "Parse problem: expected %d parameters, found %d\n", l2ruleadd_max, numparms);
+//        }
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x 0x%x %s %s %s %s 0x%x",  &ownerid, srcport_str, &rulenum, &parserulebm,
+                                       &parseflagbm, &action, nextphase_str, l2keyname, frwdname, modname, &pkt_mod_bm);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], parserulebm[0x%x], action[0x%x], nextphase_str[%s], l2keyname[%s], frwdname[%s], modname[%s], pkt_mod_bm[0x%x]\n",
+               len, parsedargs, ownerid, srcport_str, rulenum, parserulebm, action, nextphase_str, l2keyname, frwdname, modname, pkt_mod_bm);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+        uc_srcport_str[strlen(srcport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_port[%s]\n", srcport_str);
+        }
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        }
+        else if (((pdbl2keyentry = find_tpm_l2_key_entry_by_name(l2keyname)) == 0) && strcmp(l2keyname, l2_key_empty_name) != 0)
+        {
+            printk(KERN_INFO "L2 key entry [%s] not found\n", l2keyname);
+        }
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && strcmp(frwdname, frwd_empty_name) != 0)
+        {
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        }
+        else if (((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0) && strcmp(modname, mod_empty_name) != 0)
+        {
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        }
+        else
+        {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbl2keyentry != 0)  memcpy(&l2_acl, &pdbl2keyentry->l2_acl, sizeof(tpm_l2_acl_key_t));
+            else                     memset(&l2_acl, 0,                      sizeof(tpm_l2_acl_key_t));
+
+            if (pdbfrwdentry != 0)   memcpy(&pkt_frwd, &pdbfrwdentry->frwd,  sizeof(tpm_pkt_frwd_t));
+            else                     memset(&pkt_frwd, 0,                    sizeof(tpm_pkt_frwd_t));
+
+            if (pdbmodentry != 0)    memcpy(&pkt_mod, &pdbmodentry->mod,     sizeof(tpm_pkt_mod_t));
+            else                     memset(&pkt_mod, 0,                     sizeof(tpm_pkt_mod_t));
+
+            if ((rc = _tpm_add_l2_rule(ownerid,
+                                       src_port,
+                                       rulenum,
+                                       &rule_idx,
+                                       parserulebm,
+                                       parseflagbm,
+                                       &l2_acl,
+                                       &pkt_frwd,
+                                       &pkt_mod,
+                                       pkt_mod_bm,
+                                       &rule_action)) == TPM_RC_OK)
+                PR_RULE_IDX(rule_idx)
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_l2_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_l3_type_rule_bounce(uint32_t               owner_id,
+                                             tpm_src_port_type_t     src_port,
+                                             uint32_t                rule_num,
+                                             uint32_t               *rule_idx,
+                                             tpm_parse_fields_t      parse_rule_bm,
+                                             tpm_parse_flags_t       parse_flags_bm,
+                                             tpm_l3_type_key_t      *l3_key,
+                                             tpm_pkt_frwd_t         *pkt_frwd,
+                                             tpm_rule_action_t      *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                   = MV_TPM_IOCTL_ADD_L3_ACL_RULE;
+    tpm_add_acl_rule->owner_id                      = owner_id;
+    tpm_add_acl_rule->src_port                      = src_port;
+    tpm_add_acl_rule->rule_num                      = rule_num;
+    tpm_add_acl_rule->parse_rule_bm                 = parse_rule_bm;
+    tpm_add_acl_rule->l3_acl_rule.parse_flags_bm    = parse_flags_bm;
+    memcpy(&(tpm_add_acl_rule->l3_acl_rule.l3_key),         (void*)l3_key,      sizeof(tpm_l3_type_key_t));
+    memcpy(&(tpm_add_acl_rule->l3_acl_rule.pkt_frwd),       (void*)pkt_frwd,    sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->l3_acl_rule.rule_action),    (void*)rule_action, sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_l3_type_rule tpm_add_l3_type_rule_bounce
+#else
+ #define _tpm_add_l3_type_rule tpm_add_l3_type_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l3_rule_add
+*
+* DESCRIPTION:
+*           This function creates a L3 rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l3_rule_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l3ruleadd_owner=0, l3ruleadd_srcport, l3ruleadd_rulenum, l3ruleadd_parserulebm, l3ruleadd_parseflagsbm, l3ruleadd_action, l3ruleadd_nextphase,
+        l2ruleadd_frwdname, l3ruleadd_l3keyname, l3ruleadd_max
+    } l3ruleadd_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    char                     srcport_str[20];
+    char                     uc_srcport_str[20];
+    int                      indx;
+    uint32_t                 src_port;
+    uint32_t                 rulenum;
+    uint32_t                 parserulebm;
+    uint32_t                 parseflagbm;
+    uint32_t                 action;
+    char                     nextphase_str[20];
+    uint32_t                 nextphase;
+    char                     frwdname[20];
+    char                     l3keyname[20];
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    tpmcfg_l3_key_entry_t    *pdbl3keyentry = 0;
+    tpmcfg_frwd_entry_t      *pdbfrwdentry  = 0;
+    // Used in API call
+    tpm_rule_action_t        rule_action;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_l3_type_key_t        l3_acl;
+    uint32_t                 rule_idx;
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != l3ruleadd_max)
+    {
+        parm_error_completion(numparms, l3ruleadd_max, buf, sfs_help_l3_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x 0x%x %s %s %s",
+                            &ownerid, srcport_str, &rulenum, &parserulebm, &parseflagbm, &action, nextphase_str, l3keyname, frwdname);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], parserulebm[0x%x], parseflagbm[0x%x], action[0x%x], nextphase_str[%s], l3keyname[%s], frwdname[%s]\n",
+               len, parsedargs, ownerid, srcport_str, rulenum, parserulebm, parseflagbm, action, nextphase_str, l3keyname, frwdname);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+        uc_srcport_str[strlen(srcport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_port[%s]\n", uc_srcport_str);
+        }
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        }
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && strcmp(frwdname, frwd_empty_name) != 0)
+        {
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        }
+        else if (((pdbl3keyentry = find_tpm_l3_key_entry_by_name(l3keyname)) == 0) && strcmp(l3keyname, l3_key_empty_name) != 0)
+        {
+            printk(KERN_INFO "L3 key entry [%s] not found\n", l3keyname);
+        }
+        else
+        {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbl3keyentry != 0)  memcpy(&l3_acl, &pdbl3keyentry->l3_acl, sizeof(tpm_l3_type_key_t));
+            else                     memset(&l3_acl, 0,                      sizeof(tpm_l3_type_key_t));
+
+            if (pdbfrwdentry != 0)   memcpy(&pkt_frwd, &pdbfrwdentry->frwd,  sizeof(tpm_pkt_frwd_t));
+            else                     memset(&pkt_frwd, 0,                    sizeof(tpm_pkt_frwd_t));
+
+            if ((rc = _tpm_add_l3_type_rule(ownerid,
+                                            src_port,
+                                            rulenum,
+                                            &rule_idx,
+                                            parserulebm,
+                                            parseflagbm,
+                                            &l3_acl,
+                                            &pkt_frwd,
+                                            &rule_action)) == TPM_RC_OK)
+                PR_RULE_IDX(rule_idx)
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_l3_type_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv4_rule_bounce(uint32_t                owner_id,
+                                          tpm_src_port_type_t     src_port,
+                                          uint32_t                rule_num,
+                                          uint32_t               *rule_idx,
+                                          tpm_parse_fields_t      parse_rule_bm,
+                                          tpm_parse_flags_t       parse_flags_bm,
+                                          tpm_ipv4_acl_key_t     *ipv4_key,
+                                          tpm_pkt_frwd_t         *pkt_frwd,
+                                          tpm_pkt_mod_t          *pkt_mod,
+                                          tpm_pkt_mod_bm_t        pkt_mod_bm,
+                                          tpm_rule_action_t      *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                   = MV_TPM_IOCTL_ADD_IPv4_ACL_RULE;
+    tpm_add_acl_rule->owner_id                      = owner_id;
+    tpm_add_acl_rule->src_port                      = src_port;
+    tpm_add_acl_rule->rule_num                      = rule_num;
+    tpm_add_acl_rule->parse_rule_bm                 = parse_rule_bm;
+    tpm_add_acl_rule->ipv4_acl_rule.parse_flags_bm  = parse_flags_bm;
+    tpm_add_acl_rule->ipv4_acl_rule.pkt_mod_bm      = pkt_mod_bm;
+    memcpy(&(tpm_add_acl_rule->ipv4_acl_rule.ipv4_key),     (void*)ipv4_key,    sizeof(tpm_ipv4_acl_key_t));
+    memcpy(&(tpm_add_acl_rule->ipv4_acl_rule.pkt_frwd),     (void*)pkt_frwd,    sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->ipv4_acl_rule.pkt_mod),      (void*)pkt_mod,     sizeof(tpm_pkt_mod_t));
+    memcpy(&(tpm_add_acl_rule->ipv4_acl_rule.rule_action),  (void*)rule_action, sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv4_rule tpm_add_ipv4_rule_bounce
+#else
+ #define _tpm_add_ipv4_rule tpm_add_ipv4_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv4_rule_add
+*
+* DESCRIPTION:
+*           This function creates a IPV4 rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv4_rule_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv4ruleadd_owner=0, ipv4ruleadd_srcport,   ipv4ruleadd_rulenum,  ipv4ruleadd_parserulebm, ipv4ruleadd_parseflagsbm,
+        ipv4ruleadd_action,  ipv4ruleadd_nextphase, ipv4ruleadd_frwdname, ipv4ruleadd_ipv4keyname,   ipv4ruleadd_modbm,
+        ipv4ruleadd_modname, ipv4ruleadd_max
+    } ipv4ruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    char                     srcport_str[20];
+    char                     uc_srcport_str[20];
+    int                      indx;
+    uint32_t                 src_port;
+    uint32_t                 rulenum;
+    uint32_t                 parserulebm;
+    uint32_t                 parseflagsbm;
+    uint32_t                 action;
+    uint32_t                 nextphase;
+    char                     nextphase_str[20];
+    uint32_t                 modbm;
+    char                     ipv4keyname[20];
+    char                     frwdname[20];
+    char                     modname[20];
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    tpmcfg_ipv4_key_entry_t  *pdbipv4keyentry = 0;
+    tpmcfg_frwd_entry_t      *pdbfrwdentry    = 0;
+    tpmcfg_mod_entry_t       *pdbmodentry     = 0;
+    // Used in API call
+    tpm_rule_action_t        rule_action;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_pkt_mod_t            pkt_mod;
+    tpm_ipv4_acl_key_t       ipv4_acl;
+    uint32_t                 rule_idx;
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv4ruleadd_max)
+    {
+        parm_error_completion(numparms, ipv4ruleadd_max, buf, sfs_help_ipv4_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x 0x%x %s 0x%x %s %s %s", &ownerid, srcport_str, &rulenum, &parserulebm, &parseflagsbm,
+                            &action, nextphase_str, &modbm, ipv4keyname, frwdname, modname);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], parserulebm[0x%x], parseflagsbm[0x%x], action[0x%x], nextphase_str[%s], modbm[0x%x], ipv4keyname[%s], frwdname[%s], modname[%s]\n",
+//               len, parsedargs, ownerid, srcport_str, rulenum, parserulebm, parseflagsbm, action, nextphase_str, modbm, ipv4keyname, frwdname, modname);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+        uc_srcport_str[strlen(srcport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_port[%s]\n", srcport_str);
+        }
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        }
+        else if (((pdbipv4keyentry = find_tpm_ipv4_key_entry_by_name(ipv4keyname)) == 0) && strcmp(ipv4keyname, ipv4_key_empty_name) != 0)
+        {
+            printk(KERN_INFO "IPV4 key entry [%s] not found\n", ipv4keyname);
+        }
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && strcmp(frwdname, frwd_empty_name) != 0)
+        {
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        }
+        else if (((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0) && strcmp(modname, mod_empty_name) != 0)
+        {
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        }
+        else
+        {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbipv4keyentry != 0)  memcpy(&ipv4_acl, &pdbipv4keyentry->ipv4_acl, sizeof(tpm_ipv4_acl_key_t));
+            else                       memset(&ipv4_acl, 0,                          sizeof(tpm_ipv4_acl_key_t));
+
+            if (pdbfrwdentry != 0)     memcpy(&pkt_frwd, &pdbfrwdentry->frwd,        sizeof(tpm_pkt_frwd_t));
+            else                       memset(&pkt_frwd, 0,                          sizeof(tpm_pkt_frwd_t));
+
+            if (pdbmodentry != 0)      memcpy(&pkt_mod, &pdbmodentry->mod,           sizeof(tpm_pkt_mod_t));
+            else                       memset(&pkt_mod, 0,                           sizeof(tpm_pkt_mod_t));
+
+            if ((rc = _tpm_add_ipv4_rule(ownerid,
+                                         src_port,
+                                         rulenum,
+                                         &rule_idx,
+                                         parserulebm,
+                                         parseflagsbm,
+                                         &ipv4_acl,
+                                         &pkt_frwd,
+                                         &pkt_mod,
+                                         modbm,
+                                         &rule_action)) == TPM_RC_OK)
+                PR_RULE_IDX(rule_idx)
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv4_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv4_mc_stream_bounce(uint32_t                 owner_id,
+                                              uint32_t                  stream_num,
+                                              tpm_mc_igmp_mode_t        igmp_mode,
+                                              uint8_t                   mc_stream_pppoe,
+                                              uint16_t                  vid,
+                                              uint8_t                   ipv4_src_add[4],
+                                              uint8_t                   ipv4_dst_add[4],
+                                              uint8_t                   ignore_ipv4_src,
+                                              tpm_trg_port_type_t       dest_port_bm)
+{
+    tpm_ioctl_mc_rule_t *tpm_mc_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mc_rule;
+
+    tpm_sfs_2_ioctl_command.cmd             = MV_TPM_IOCTL_MC_STREAM_SECTION;
+    tpm_mc_rule->mc_cmd                     = MV_TPM_IOCTL_ADD_IPv4_MC_STREAM;
+    tpm_mc_rule->stream_num                 = stream_num;
+    tpm_mc_rule->igmp_mode                  = igmp_mode;
+    tpm_mc_rule->mc_stream_pppoe            = mc_stream_pppoe;
+    tpm_mc_rule->vid                        = vid;
+    tpm_mc_rule->ipv4_mc.ignore_ipv4_src    = ignore_ipv4_src;
+    tpm_mc_rule->dest_port_bm               = dest_port_bm;
+    memcpy(&(tpm_mc_rule->ipv4_mc.ipv4_src_add[0]), ipv4_src_add, sizeof(uint8_t)*4);
+    memcpy(&(tpm_mc_rule->ipv4_mc.ipv4_dst_add[0]), ipv4_dst_add, sizeof(uint8_t)*4);
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv4_mc_stream tpm_add_ipv4_mc_stream_bounce
+#else
+ #define _tpm_add_ipv4_mc_stream tpm_add_ipv4_mc_stream
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mc_ipv4_stream_add
+*
+* DESCRIPTION:
+*           This function creates a multicast IPV4 rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mc_ipv4_stream_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mcipv4add_owner=0, mcipv4add_stream, mcipv4add_mode,   mcipv4add_pppoe,        mcipv4add_vid,
+        mcipv4add_src_ip,  mcipv4add_dst_ip, mcipv4add_ignore, mcipv4add_target_ports, mcipv4add_max
+    } mcipv4add_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 stream;
+    uint32_t                 mode;
+    char                     mc_pppoe_str[20];
+    uint32_t                 mc_stream_pppoe;
+    uint32_t                 vid;
+    char                     srcip_str[30];
+    char                     dstip_str[30];
+    uint32_t                 temp_srcip[4];
+    uint32_t                 temp_dstip[4];
+    uint8_t                  srcip[4];
+    uint8_t                  dstip[4];
+    char                     ignore_str[20];
+    uint32_t                 ignore;
+    uint32_t                 target_ports;
+    int                      parsedargs;
+    int                      numparms;
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != mcipv4add_max)
+    {
+        parm_error_completion(numparms, mcipv4add_max, buf, sfs_help_mc_ipvx_stream_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d %d %s %d %s %s %s 0x%x",
+                            &ownerid, &stream, &mode, mc_pppoe_str, &vid, srcip_str, dstip_str, ignore_str, &target_ports);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], stream[%d], vid[%d], srcip_str[%s], dstip_str[%s], ignore_str[%s], target_ports[0x%x]\n",
+//               len, parsedargs, ownerid, stream, vid, srcip_str, dstip_str, ignore_str, target_ports);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_bool_value(mc_pppoe_str, &mc_stream_pppoe) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid ignore[%s]\n", ignore_str);
+        }
+        else if (parse_ipv4_address(srcip_str, temp_srcip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_ip [%s]\n", srcip_str);
+        }
+        else if (parse_ipv4_address(dstip_str, temp_dstip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dst_ip [%s]\n", dstip_str);
+        }
+        else if (get_bool_value(ignore_str, &ignore) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid ignore[%s]\n", ignore_str);
+        }
+        else
+        {
+            int indx;
+
+            for (indx = 0; indx < sizeof(srcip); indx++)
+            {
+                srcip[indx] = (uint8_t)temp_srcip[indx];
+                dstip[indx] = (uint8_t)temp_dstip[indx];
+            }
+
+            if ((rc = _tpm_add_ipv4_mc_stream(ownerid,
+                                              stream,
+                                              mode,
+                                              (uint8_t)mc_stream_pppoe,
+                                              vid,
+                                              srcip,
+                                              dstip,
+                                              (uint8_t)ignore,
+                                              target_ports)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv4_mc_stream failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_mc_stream_bounce(uint32_t owner_id,
+						uint32_t stream_num,
+						tpm_mc_igmp_mode_t igmp_mode,
+						uint8_t mc_stream_pppoe,
+						uint16_t vid,
+						uint8_t ipv6_src_add[16],
+						uint8_t ipv6_dst_add[16],
+						uint8_t ignore_ipv6_src,
+						tpm_trg_port_type_t dest_port_bm)
+{
+    tpm_ioctl_mc_rule_t *tpm_mc_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mc_rule;
+
+    tpm_sfs_2_ioctl_command.cmd             = MV_TPM_IOCTL_MC_STREAM_SECTION;
+    tpm_mc_rule->mc_cmd                     = MV_TPM_IOCTL_ADD_IPv6_MC_STREAM;
+    tpm_mc_rule->stream_num                 = stream_num;
+    tpm_mc_rule->igmp_mode                  = igmp_mode;
+    tpm_mc_rule->mc_stream_pppoe            = mc_stream_pppoe;
+    tpm_mc_rule->vid                        = vid;
+    tpm_mc_rule->dest_port_bm               = dest_port_bm;
+    memcpy(&(tpm_mc_rule->ipv6_mc.ipv6_dst_add[0]), ipv6_dst_add, sizeof(uint8_t) * 16);
+    memcpy(&(tpm_mc_rule->ipv6_mc.ipv6_src_add[0]), ipv6_src_add, sizeof(uint8_t) * 16);
+    tpm_mc_rule->ipv6_mc.ignore_ipv6_src = ignore_ipv6_src;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_mc_stream tpm_add_ipv6_mc_stream_bounce
+#else
+ #define _tpm_add_ipv6_mc_stream tpm_add_ipv6_mc_stream
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mc_ipv6_stream_add
+*
+* DESCRIPTION:
+*           This function creates a multicast ipv6 rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mc_ipv6_stream_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mcipv6add_owner=0, mcipv6add_stream, mcipv6add_mode,   mcipv6add_pppoe,        mcipv6add_vid,
+        mcipv6add_src_ip, mcipv6add_dst_ip, mcipv6add_ignor_src_ip, mcipv6add_target_ports, mcipv6add_max
+    } mcipv6add_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 stream;
+    uint32_t                 mode;
+    char                     mc_pppoe_str[20];
+    uint32_t                 mc_stream_pppoe;
+    uint32_t                 vid;
+    char                     dstip_str[60];
+    uint32_t                 temp_dstip[16];
+    char                     srcip_str[60];
+    uint32_t                 temp_srcip[16];
+    uint8_t                  dstip[16];
+    uint8_t                  srcip[16];
+    uint32_t                 ignor_srcip;
+    char                     ignore_str[20];
+    uint32_t                 target_ports;
+    int                      parsedargs;
+    int                      numparms;
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != mcipv6add_max)
+    {
+        parm_error_completion(numparms, mcipv6add_max, buf, sfs_help_mc_ipvx_stream_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d %d %s %d %s %s %s 0x%x",
+                            &ownerid, &stream, &mode, mc_pppoe_str, &vid, srcip_str, dstip_str, ignore_str, &target_ports);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], stream[%d], vid[%d], srcip_str[%s],  "
+		"dstip_str[%s],  ignor_srcip[%s], target_ports[0x%x]\n",
+               len, parsedargs, ownerid, stream, vid, srcip_str, dstip_str, ignore_str, target_ports);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_bool_value(mc_pppoe_str, &mc_stream_pppoe) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid mc_pppoe_str[%s]\n", mc_pppoe_str);
+        }
+        else if (parse_ipv6_address(dstip_str, temp_dstip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dst_ip [%s]\n", dstip_str);
+        }
+        else if (parse_ipv6_address(srcip_str, temp_srcip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip_str [%s]\n", srcip_str);
+	}
+	else if (get_bool_value(ignore_str, &ignor_srcip) == GT_FALSE)
+	{
+	    printk(KERN_INFO "Invalid ignore[%s]\n", ignore_str);
+        }
+        else
+        {
+            int indx;
+
+            for (indx = 0; indx < sizeof(dstip); indx++)
+            {
+                dstip[indx] = (uint8_t)temp_dstip[indx];
+                srcip[indx] = (uint8_t)temp_srcip[indx];
+            }
+
+            if ((rc = _tpm_add_ipv6_mc_stream(ownerid,
+                                              stream,
+                                              mode,
+                                              (uint8_t)mc_stream_pppoe,
+                                              vid,
+                                              srcip,
+                                              dstip,
+                                              ignor_srcip,
+                                              target_ports)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv6_mc_stream failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_set_port_igmp_frwd_mode_bounce(tpm_src_port_type_t  src_port,
+                                                    tpm_igmp_frwd_mode_t mode)
+{
+    tpm_ioctl_igmp_t *tpm_igmp = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_igmp;
+
+    tpm_sfs_2_ioctl_command.cmd   = MV_TPM_IOCTL_IGMP_SECTION;
+    tpm_igmp->igmp_cmd          = MV_TPM_IOCTL_IGMP_SET_PORT_FRWD_MODE;
+    tpm_igmp->src_port          = src_port;
+    tpm_igmp->frwd_mode         = mode;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_set_port_igmp_frwd_mode tpm_set_port_igmp_frwd_mode_bounce
+#else
+ #define _tpm_set_port_igmp_frwd_mode tpm_set_port_igmp_frwd_mode
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_igmp_port_forward_mode_cfg
+*
+* DESCRIPTION:
+*           This function creates a multicast IPV4 rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void  sfs_tpm_cfg_set_igmp_port_forward_mode_cfg (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        igmpfrwd_owner=0, igmpfrwd_src_port, igmpfrwd_mode, igmpfrwd_max
+    } igmpfrwd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;          // NOTE: not used in API!!
+    char                     srcport_str[30];
+    char                     uc_srcport_str[30];
+    int                      indx;
+    uint32_t                 src_port;
+    char                     mode_str[30];
+    uint32_t                 mode;
+    int                      parsedargs;
+    int                      numparms;
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != igmpfrwd_max)
+    {
+        parm_error_completion(numparms, igmpfrwd_max, buf, sfs_help_igmp_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %s", &ownerid, srcport_str, mode_str);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], mode_str[%s]\n",
+//               len, parsedargs, ownerid, srcport_str, mode_str);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+        uc_srcport_str[strlen(srcport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_igmp_srcport_value(uc_srcport_str, &src_port) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_port [%s]\n", srcport_str);
+        }
+        else if (get_igmp_mode_value(mode_str, &mode) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid mode [%s]\n", mode_str);
+        }
+        else
+        {
+            if ((rc = _tpm_set_port_igmp_frwd_mode(src_port,
+                                                   mode)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_set_port_igmp_frwd_mode failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_set_igmp_cpu_rx_queue_bounce(uint32_t  queue)
+{
+    tpm_ioctl_igmp_t *tpm_igmp = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_igmp;
+
+    tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_IGMP_SECTION;
+    tpm_igmp->igmp_cmd          = MV_TPM_IOCTL_IGMP_SET_CPU_RX_Q;
+    tpm_igmp->cpu_queue         = queue;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_set_igmp_cpu_rx_queue tpm_set_igmp_cpu_rx_queue_bounce
+#else
+ #define _tpm_set_igmp_cpu_rx_queue tpm_set_igmp_cpu_rx_queue
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_igmp_cpu_queue_cfg
+*
+* DESCRIPTION:
+*           This function configres the CPU queue for IGMP
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_igmp_cpu_queue_cfg (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        igmpcpuq_owner=0, igmpcpuq_queue, igmpcpuq_max
+    } igmpcpuq_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;             // NOTE: not used in API!!
+    uint32_t                 que;
+    int                      parsedargs;
+    int                      numparms;
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != igmpcpuq_max)
+    {
+        parm_error_completion(numparms, igmpcpuq_max, buf, sfs_help_igmp_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &que);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], que[%d]\n",
+//               len, parsedargs, ownerid, que);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (que >= TPM_MAX_NUM_RX_QUEUE)  // Hope this a good choice
+        {
+            printk(KERN_INFO "Invalid queue [%d]\n", que);
+        }
+        else
+        {
+            if ((rc = _tpm_set_igmp_cpu_rx_queue(que)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_set_igmp_cpu_rx_queue failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_set_igmp_proxy_sa_mac_bounce(uint8_t *sa_mac)
+{
+	tpm_ioctl_igmp_t *tpm_igmp_set_sa_mac = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_igmp;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_IGMP_SECTION;
+	tpm_igmp_set_sa_mac->igmp_cmd = MV_TPM_IOCTL_SET_IGMP_PROXY_SA_MAC;
+	memcpy(tpm_igmp_set_sa_mac->sa_mac, (void *)sa_mac, 6);
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+ #define _tpm_set_igmp_proxy_sa_mac tpm_set_igmp_proxy_sa_mac_bounce
+#else
+ #define _tpm_set_igmp_proxy_sa_mac tpm_set_igmp_proxy_sa_mac
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_igmp_proxy_sa_mac
+*
+* DESCRIPTION:
+*           This function configures the sa_mac for IGMP proxy
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_igmp_proxy_sa_mac (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        igmpproxysa_owner=0, igmpproxysa_mac, igmpproxysa_max
+    } igmpproxysa_parm_indx_t;
+
+    // shell line parsing
+    unsigned int             ownerid, i;
+    uint8_t                  mac[6];
+    uint32_t                 temp_mac[6];
+    int                      parsedargs;
+    int                      numparms;
+    // Used in API call
+    tpm_error_code_t         rc;
+
+
+    numparms = count_parameters(buf);
+    if (numparms != igmpproxysa_max)
+    {
+        parm_error_completion(numparms, igmpproxysa_max, buf, sfs_help_igmp_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %02x:%02x:%02x:%02x:%02x:%02x",
+                            &ownerid, &temp_mac[0], &temp_mac[1], &temp_mac[2], &temp_mac[3], &temp_mac[4], &temp_mac[5]);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], sa_mac[%02x:%02x:%02x:%02x:%02x:%02x]\n",
+//               len, parsedargs, ownerid, temp_mac[0], temp_mac[1], temp_mac[2], temp_mac[3], temp_mac[4], temp_mac[5]);
+
+        if (parsedargs != 7)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, 7);
+        }
+        else
+        {
+            for (i=0;i<6;i++)
+            {
+                mac[i] = temp_mac[i];
+            }
+            if ((rc = _tpm_set_igmp_proxy_sa_mac (mac)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_set_igmp_proxy_sa_mac failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_l2_rule_bounce(uint32_t        owner_id,
+                                        uint32_t        rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd   = MV_TPM_IOCTL_DEL_L2_ACL_RULE;
+    tpm_del_acl_rule->owner_id      = owner_id;
+    tpm_del_acl_rule->rule_idx      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_l2_rule tpm_del_l2_rule_bounce
+#else
+ #define _tpm_del_l2_rule tpm_del_l2_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_l2
+*
+* DESCRIPTION:
+*           This function deletes a L2 HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_l2  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        noruleaddl2_owner=0,  noruleaddl2_ruleidx,  noruleaddl2_max
+    } noruleaddl2_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noruleaddl2_max)
+    {
+        parm_error_completion(numparms, noruleaddl2_max, buf, sfs_help_no_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+        //printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rule_idx[%d]\n",
+        //       len, parsedargs, ownerid, rule_idx);
+
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_del_l2_rule(ownerid,
+                                       rule_idx)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_del_l2_prim_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_l3_type_rule_bounce(uint32_t           owner_id,
+                                             uint32_t           rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd   = MV_TPM_IOCTL_DEL_L3_ACL_RULE;
+    tpm_del_acl_rule->owner_id      = owner_id;
+    tpm_del_acl_rule->rule_idx      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_l3_type_rule tpm_del_l3_type_rule_bounce
+#else
+ #define _tpm_del_l3_type_rule tpm_del_l3_type_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_l3
+*
+* DESCRIPTION:
+*           This function deletes a L3 HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_l3  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        noruleaddl3_owner=0,  noruleaddl3_ruleidx,  noruleaddl3_max
+    } noruleaddl3_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noruleaddl3_max)
+    {
+        parm_error_completion(numparms, noruleaddl3_max, buf, sfs_help_no_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rule_idx[%d], parserulebm[0x%x], keyname[%s]\n",
+//               len, parsedargs, ownerid, srcport_str, rule_idx, parserulebm, keyname);
+
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_del_l3_type_rule(ownerid,
+                                            rule_idx)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_del_l3_type_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv4_rule_bounce(uint32_t          owner_id,
+                                          uint32_t          rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd   = MV_TPM_IOCTL_DEL_IPv4_ACL_RULE;
+    tpm_del_acl_rule->owner_id      = owner_id;
+    tpm_del_acl_rule->rule_idx      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv4_rule tpm_del_ipv4_rule_bounce
+#else
+ #define _tpm_del_ipv4_rule tpm_del_ipv4_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ipv4
+*
+* DESCRIPTION:
+*           This function deletes a IPV4 HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ipv4  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        noruleaddipv4_owner=0,  noruleaddipv4_ruleidx, noruleaddipv4_max
+    } noruleaddipv4_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noruleaddipv4_max)
+    {
+        parm_error_completion(numparms, noruleaddipv4_max, buf, sfs_help_no_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d",
+                            &ownerid, &rule_idx);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rule_idx[%d], parserulebm[0x%x], keyname[%s]\n",
+//               len, parsedargs, ownerid, srcport_str, rule_idx, parserulebm, keyname);
+
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_del_ipv4_rule(ownerid,
+                                         rule_idx)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_del_ipv4_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv4_mc_stream_bounce(uint32_t     owner_id,
+                                              uint32_t      stream_num)
+{
+    tpm_ioctl_mc_rule_t *tpm_mc_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mc_rule;
+
+    tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MC_STREAM_SECTION;
+    tpm_mc_rule->mc_cmd         = MV_TPM_IOCTL_DEL_IPv4_MC_STREAM;
+    tpm_mc_rule->owner_id       = owner_id;
+    tpm_mc_rule->stream_num     = stream_num;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv4_mc_stream tpm_del_ipv4_mc_stream_bounce
+#else
+ #define _tpm_del_ipv4_mc_stream tpm_del_ipv4_mc_stream
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_mc_stream_add_ipv4
+*
+* DESCRIPTION:
+*           This function deletes a DSCP IPV6 HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_mc_stream_add_ipv4  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        nostreamaddipv4_owner=0, nostreamaddipv4_ruleidx,  nostreamaddipv4_max
+    } nostreamaddipv4_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 stream;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != nostreamaddipv4_max)
+    {
+        parm_error_completion(numparms, nostreamaddipv4_max, buf, sfs_help_no_mc_stream_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &stream);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], stream[%d]\n", len, parsedargs, ownerid, stream);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if ((rc = _tpm_del_ipv4_mc_stream(ownerid,
+                                               stream)) == TPM_RC_OK)
+        {
+            printk(KERN_INFO "OK\n");
+        }
+        else
+        {
+            printk(KERN_INFO "%s: tpm_del_ipv4_mc_stream failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv6_mc_stream_bounce(uint32_t     owner_id,
+                                              uint32_t      stream_num)
+{
+    tpm_ioctl_mc_rule_t *tpm_mc_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mc_rule;
+
+    tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MC_STREAM_SECTION;
+    tpm_mc_rule->mc_cmd         = MV_TPM_IOCTL_DEL_IPv6_MC_STREAM;
+    tpm_mc_rule->owner_id       = owner_id;
+    tpm_mc_rule->stream_num     = stream_num;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv6_mc_stream tpm_del_ipv6_mc_stream_bounce
+#else
+ #define _tpm_del_ipv6_mc_stream tpm_del_ipv6_mc_stream
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_mc_stream_add_ipv6
+*
+* DESCRIPTION:
+*           This function deletes a DSCP IPV6 HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_mc_stream_add_ipv6  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        nostreamaddipv6_owner=0, nostreamaddipv6_ruleidx,  nostreamaddipv6_max
+    } nostreamaddipv6_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 stream;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != nostreamaddipv6_max)
+    {
+        parm_error_completion(numparms, nostreamaddipv6_max, buf, sfs_help_no_mc_stream_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &stream);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], stream[%d]\n", len, parsedargs, ownerid, stream);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if ((rc = _tpm_del_ipv6_mc_stream(ownerid,
+                                               stream)) == TPM_RC_OK)
+        {
+            printk(KERN_INFO "OK\n");
+        }
+        else
+        {
+            printk(KERN_INFO "%s: tpm_del_ipv6_mc_stream failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_proc_set_enable_mtu_bounce(tpm_init_mtu_setting_enable_t enable)
+{
+	tpm_ioctl_mtu_t *tpm_mtu_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_mtu_set;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MTU_SECTION;
+	tpm_mtu_set->mtu_setting_cmd = MV_TPM_IOCTL_SET_MTU_ADMIN;
+	tpm_mtu_set->enable = enable;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+ #define _tpm_proc_set_enable_mtu tpm_proc_set_enable_mtu_bounce
+#else
+ #define _tpm_proc_set_enable_mtu tpm_db_set_mtu_enable
+#endif
+
+void sfs_tpm_cfg_set_mtu_enable (const char *buf, size_t len)
+{
+	typedef enum
+	{
+		mtu_enable=0, mtu_enable_max
+	} mtu_enable_indx_t;
+	/*shell line parsing*/
+	int enable;
+
+	int parsedargs;
+	int numparms;
+
+	/*used in API call*/
+	tpm_error_code_t rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != mtu_enable_max)
+		parm_error_completion(numparms, mtu_enable_max, buf, sfs_help_setup);
+	else {
+		/*get parameters*/
+		parsedargs = sscanf(buf, "%d", &enable);
+		if (parsedargs != numparms)
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		else if ((enable != 1) && (enable != 0))
+			printk(KERN_INFO "Invalid enable[%d]\n", enable);
+		else {
+			if ((rc = _tpm_proc_set_enable_mtu(enable)) == TPM_RC_OK)
+				printk(KERN_INFO "OK\n");
+			else
+				printk(KERN_INFO "%s: tpm_proc_set_enable_mtu failed, rc[%d] - %s\n",
+				__FUNCTION__, rc, get_tpm_err_str(rc));
+		}
+	}
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_proc_set_mtu_bounce(uint32_t ipv4_or_ipv6,
+					uint32_t direction,
+					uint32_t mtu)
+{
+	tpm_ioctl_mtu_t *tpm_mtu_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_mtu_set;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MTU_SECTION;
+	tpm_mtu_set->mtu_setting_cmd = MV_TPM_IOCTL_SET_MTU;
+	tpm_mtu_set->ethertype = ipv4_or_ipv6;
+	tpm_mtu_set->direction = direction;
+	tpm_mtu_set->mtu = mtu;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+ #define _tpm_proc_set_mtu tpm_proc_set_mtu_bounce
+#else
+ #define _tpm_proc_set_mtu tpm_proc_set_mtu
+#endif
+
+void sfs_tpm_cfg_set_mtu (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mtu_ipv4_or_ipv6=0,  mtu_direction, mtu_value,  mtu_max
+    } mtu_indx_t;
+    // shell line parsing
+    uint32_t                 ipv4_or_ipv6;
+    uint32_t                 direction;
+    uint32_t                 mtu;
+
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+    tpm_setup_t              setup;
+
+    memset(&setup, 0, sizeof(tpm_setup_t));
+
+    numparms = count_parameters(buf);
+    if (numparms != mtu_max)
+    {
+        parm_error_completion(numparms, mtu_max, buf, sfs_help_setup);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d %d", &ipv4_or_ipv6, &direction, &mtu);
+        printk(KERN_INFO "ipv4_or_ipv6=%d, direction=%d. mtu[%d],\n", ipv4_or_ipv6, direction, mtu);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (ipv4_or_ipv6 >= 2)
+        {
+            printk(KERN_INFO "Invalid ipv4_or_ipv6[%d]\n", ipv4_or_ipv6);
+        }
+        else if (direction >= 2)
+        {
+            printk(KERN_INFO "Invalid direction[%d]\n", direction);
+        }
+        else
+        {
+            if ((rc = _tpm_proc_set_mtu(ipv4_or_ipv6, direction, mtu)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_proc_set_mtu failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_proc_set_pppoe_mtu_bounce(uint32_t ipv4_or_ipv6,
+					uint32_t direction,
+					uint32_t pppoe_mtu)
+{
+	tpm_ioctl_mtu_t *tpm_mtu_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_mtu_set;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MTU_SECTION;
+	tpm_mtu_set->mtu_setting_cmd = MV_TPM_IOCTL_SET_PPPOE_MTU;
+	tpm_mtu_set->ethertype = ipv4_or_ipv6;
+	tpm_mtu_set->direction = direction;
+	tpm_mtu_set->pppoe_mtu= pppoe_mtu;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+ #define _tpm_proc_set_pppoe_mtu tpm_proc_set_pppoe_mtu_bounce
+#else
+ #define _tpm_proc_set_pppoe_mtu tpm_proc_set_pppoe_mtu
+#endif
+
+
+void sfs_tpm_cfg_set_pppoe_mtu (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        pppoe_mtu_ipv4_or_ipv6=0,  pppoe_mtu_direction, pppoe_mtu_value,  pppoe_mtu_max
+    } pppoe_mtu_indx_t;
+    // shell line parsing
+    uint32_t                 ipv4_or_ipv6;
+    uint32_t                 direction;
+    uint32_t                 pppoe_mtu;
+
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+    tpm_setup_t              setup;
+
+    memset(&setup, 0, sizeof(tpm_setup_t));
+
+    numparms = count_parameters(buf);
+    if (numparms != pppoe_mtu_max)
+    {
+        parm_error_completion(numparms, pppoe_mtu_max, buf, sfs_help_setup);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d %d", &ipv4_or_ipv6, &direction, &pppoe_mtu);
+        printk(KERN_INFO "ipv4_or_ipv6=%d, direction=%d. pppoe_mtu[%d],\n", ipv4_or_ipv6, direction, pppoe_mtu);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (ipv4_or_ipv6 >= 2)
+        {
+            printk(KERN_INFO "Invalid ipv4_or_ipv6[%d]\n", ipv4_or_ipv6);
+        }
+        else if (direction >= 2)
+        {
+            printk(KERN_INFO "Invalid direction[%d]\n", direction);
+        }
+        else
+        {
+            if ((rc = _tpm_proc_set_pppoe_mtu(ipv4_or_ipv6, direction, pppoe_mtu)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_proc_set_pppoe_mtu failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv6_gen_rule_bounce(uint32_t            owner_id,
+                                                uint32_t            rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd                   = MV_TPM_IOCTL_DEL_IPV6_GEN_ACL_RULE;
+    tpm_del_acl_rule->owner_id                      = owner_id;
+    tpm_del_acl_rule->rule_idx                      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv6_gen_rule tpm_del_ipv6_gen_rule_bounce
+#else
+ #define _tpm_del_ipv6_gen_rule tpm_del_ipv6_gen_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ipv6_gen_acl
+*
+* DESCRIPTION:
+*           This function deletes a IPV6 HW gen ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ipv6_gen_acl (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        noipv6gen_owner=0, noipv6gen_ruleidx, noipv6gen_max
+    } noipv6genruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noipv6gen_max)
+    {
+        parm_error_completion(numparms, noipv6gen_max, buf, sfs_help_no_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rule_idx[%d]\n",
+               len, parsedargs, ownerid, rule_idx);
+
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_del_ipv6_gen_rule(ownerid,
+                                               rule_idx)) == TPM_RC_OK)
+                PR_RESULT
+            else
+            {
+                printk(KERN_INFO "%s: tpm_del_ipv6_gen_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_gen_rule_bounce(uint32_t                    owner_id,
+                                                tpm_src_port_type_t         src_port,
+                                                uint32_t                    rule_num,
+                                                uint32_t                   *rule_idx,
+                                                tpm_parse_fields_t          parse_rule_bm,
+                                                tpm_parse_flags_t           parse_flags_bm,
+                                                tpm_ipv6_gen_acl_key_t   *ipv6_gen_key,
+                                                tpm_pkt_frwd_t             *pkt_frwd,
+                                                tpm_pkt_mod_t              *pkt_mod,
+                                                tpm_pkt_mod_bm_t            pkt_mod_bm,
+                                                tpm_rule_action_t          *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                             = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                           = MV_TPM_IOCTL_ADD_IPV6_GEN_ACL_RULE;
+    tpm_add_acl_rule->owner_id                              = owner_id;
+    tpm_add_acl_rule->src_port                              = src_port;
+    tpm_add_acl_rule->rule_num                              = rule_num;
+    tpm_add_acl_rule->parse_rule_bm                         = parse_rule_bm;
+    tpm_add_acl_rule->ipv6_gen_acl_rule.parse_flags_bm    = parse_flags_bm;
+    tpm_add_acl_rule->ipv6_gen_acl_rule.pkt_mod_bm        = pkt_mod_bm;
+
+    memcpy(&(tpm_add_acl_rule->ipv6_gen_acl_rule.ipv6_gen_key), ipv6_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_gen_acl_rule.pkt_frwd),       pkt_frwd,       sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_gen_acl_rule.pkt_mod),        pkt_mod,        sizeof(tpm_pkt_mod_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_gen_acl_rule.rule_action),    rule_action,    sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_gen_rule tpm_add_ipv6_gen_rule_bounce
+#else
+ #define _tpm_add_ipv6_gen_rule tpm_add_ipv6_gen_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_gen_rule_add
+*
+* DESCRIPTION:
+*           This function create IPv6 general rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_gen_rule_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6ruleadd_owner=0, ipv6ruleadd_srcport,   ipv6ruleadd_rulenum,  ipv6ruleadd_parserulebm,      ipv6ruleadd_parseflagsbm,
+        ipv6ruleadd_action,  ipv6ruleadd_nextphase, ipv6ruleadd_modbm,    ipv6ruleadd_ipv6genkeyname, ipv6ruleadd_frwdname,
+        ipv6ruleadd_modname, ipv6ruleadd_max
+    } ipv4ruleadd_parm_indx_t;
+
+    uint32_t            owner_id;
+    tpm_src_port_type_t src_port;
+    uint32_t            rule_num;
+    uint32_t            rule_idx;
+    tpm_parse_fields_t  parse_rule_bm;
+    tpm_parse_flags_t   parse_flags_bm;
+    tpm_ipv6_gen_acl_key_t ipv6_gen_key;
+    tpm_pkt_frwd_t      pkt_frwd;
+    tpm_pkt_mod_t       pkt_mod;
+    tpm_pkt_mod_bm_t    pkt_mod_bm;
+    tpm_rule_action_t   rule_action;
+
+    tpmcfg_ipv6_gen_key_entry_t *pdbipv6genkeyentry = 0;
+    tpmcfg_frwd_entry_t           *pdbfrwdentry         = 0;
+    tpmcfg_mod_entry_t            *pdbmodentry          = 0;
+
+    tpm_error_code_t    rc;
+    int                 indx;
+    int                 parsedargs;
+    int                 numparms;
+    uint32_t            action;
+    uint32_t            nextphase;
+    char                srcport_str[20];
+    char                uc_srcport_str[20];
+    char                nextphase_str[20];
+    char                ipv6genkeyname[30];
+    char                frwdname[20];
+    char                modname[20];
+
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6ruleadd_max)
+    {
+        parm_error_completion(numparms, ipv6ruleadd_max, buf, sfs_help_ipv6_gen_rule_add);
+    }
+    else
+    {
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x  0x%x %s 0x%x %s %s %s",
+                            &owner_id, srcport_str, &rule_num, &parse_rule_bm, &parse_flags_bm,
+                            &action, nextphase_str, &pkt_mod_bm, ipv6genkeyname, frwdname, modname);
+                printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], parserulebm[0x%x], parseflagsbm[0x%x], action[0x%x], nextphase_str[%s], modbm[0x%x], ipv6keyname[%s], frwdname[%s], modname[%s]\n",
+                       len, parsedargs, owner_id, srcport_str, rule_num, parse_rule_bm, parse_flags_bm, action, nextphase_str, pkt_mod_bm, ipv6genkeyname, frwdname, modname);
+
+        for (indx = 0; indx < strlen(srcport_str); indx++)
+        {
+            uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+        }
+        uc_srcport_str[strlen(srcport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_port[%s]\n", srcport_str);
+        }
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        }
+        else if (((pdbipv6genkeyentry = find_tpm_ipv6_gen_key_entry_by_name(ipv6genkeyname)) == 0) && \
+                    strcmp(ipv6genkeyname, ipv6_gen_key_empty_name) != 0)
+        {
+            printk(KERN_INFO "IPV4 key entry [%s] not found\n", ipv6genkeyname);
+        }
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && \
+                    strcmp(frwdname, frwd_empty_name) != 0)
+        {
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        }
+        else if (((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0) && \
+                    strcmp(modname, mod_empty_name) != 0)
+        {
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        }
+        else
+        {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbipv6genkeyentry != 0)
+                memcpy(&ipv6_gen_key, &pdbipv6genkeyentry->ipv6gen_acl, sizeof(tpm_ipv6_gen_acl_key_t));
+            else
+                memset(&ipv6_gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+
+            if (pdbfrwdentry != 0)
+                memcpy(&pkt_frwd, &pdbfrwdentry->frwd, sizeof(tpm_pkt_frwd_t));
+            else
+                memset(&pkt_frwd, 0, sizeof(tpm_pkt_frwd_t));
+
+            if (pdbmodentry != 0)
+                memcpy(&pkt_mod, &pdbmodentry->mod, sizeof(tpm_pkt_mod_t));
+            else
+                memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
+
+            if (TPM_RC_OK == (rc = _tpm_add_ipv6_gen_rule(owner_id,
+                                                            src_port,
+                                                            rule_num,
+                                                            &rule_idx,
+                                                            parse_rule_bm,
+                                                            parse_flags_bm,
+                                                            &ipv6_gen_key,
+                                                            &pkt_frwd,
+                                                            &pkt_mod,
+                                                            pkt_mod_bm,
+                                                            &rule_action)) )
+                PR_RULE_IDX(rule_idx)
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv6_gen_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_oam_epon_add_channel_bounce(uint32_t owner_id,
+						uint32_t cpu_rx_queue,
+						tpm_trg_port_type_t llid_num)
+{
+	tpm_ioctl_mng_ch_t *tpm_oam_epon_chan = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mng_channel;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MNG_SECTION;
+	tpm_oam_epon_chan->mng_cmd = MV_TPM_IOCTL_ADD_OAM_CHNL;
+	tpm_oam_epon_chan->tpm_ioctl_oam_ch.owner_id = owner_id;
+	tpm_oam_epon_chan->tpm_ioctl_oam_ch.cpu_rx_queue = cpu_rx_queue;
+	tpm_oam_epon_chan->tpm_ioctl_oam_ch.llid_num = llid_num;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+ #define _tpm_oam_epon_add_channel tpm_oam_epon_add_channel_bounce
+#else
+ #define _tpm_oam_epon_add_channel tpm_oam_epon_add_channel
+#endif
+/*******************************************************************************
+* sfs_tpm_cfg_set_oam_channel
+*
+* DESCRIPTION:
+*           This function creates OAM channel HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_oam_channel  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        oam_owner=0, oam_rxq,  oam_llid,  oam_max
+    } oam_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 rx_q;
+    uint32_t                 llid;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != oam_max)
+    {
+        parm_error_completion(numparms, oam_max, buf, sfs_help_oam_omci_channel);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d 0x%x", &ownerid, &rx_q, &llid);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rxq[%d], llid[0x%x]\n", len, parsedargs, ownerid, rx_q, llid);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if ((rc = _tpm_oam_epon_add_channel (ownerid,
+                                                 rx_q,
+                                                 llid)) == TPM_RC_OK)
+        {
+            printk(KERN_INFO "OK\n");
+        }
+        else
+        {
+            printk(KERN_INFO "%s: tpm_oam_epon_add_channel failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_omci_add_channel_bounce(uint32_t owner_id,
+						tpm_gem_port_key_t gem_port,
+						uint32_t cpu_rx_queue,
+						tpm_trg_port_type_t tcont_num,
+						uint32_t cpu_tx_queue)
+{
+	tpm_ioctl_mng_ch_t *tpm_omci_gpon_chan = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mng_channel;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MNG_SECTION;
+	tpm_omci_gpon_chan->mng_cmd = MV_TPM_IOCTL_ADD_OMCI_CHNL;
+	tpm_omci_gpon_chan->tpm_ioctl_omci_ch.owner_id = owner_id;
+	tpm_omci_gpon_chan->tpm_ioctl_omci_ch.gem_port = gem_port;
+	tpm_omci_gpon_chan->tpm_ioctl_omci_ch.cpu_rx_queue = cpu_rx_queue;
+	tpm_omci_gpon_chan->tpm_ioctl_omci_ch.tcont_num = tcont_num;
+	tpm_omci_gpon_chan->tpm_ioctl_omci_ch.cpu_tx_queue = cpu_tx_queue;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+ #define _tpm_omci_add_channel tpm_omci_add_channel_bounce
+#else
+ #define _tpm_omci_add_channel tpm_omci_add_channel
+#endif
+/*******************************************************************************
+* sfs_tpm_cfg_set_omci_channel
+*
+* DESCRIPTION:
+*           This function creates creates an OMCI channel HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_omci_channel  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        omci_owner=0, omci_gemport,  omci_rxq,  omci_txq,  omci_tcont,  omci_max
+    } omci_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 gemport;
+    uint32_t                 rx_q;
+    uint32_t                 tx_q;
+    uint32_t                 tcont;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != omci_max)
+    {
+        parm_error_completion(numparms, omci_max, buf, sfs_help_oam_omci_channel);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d %d %d 0x%x", &ownerid, &gemport, &rx_q, &tx_q, &tcont);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], gemport[%d], rx_q[%d], tx_q[%d], tcont[0x%x]\n",
+//               len, parsedargs, ownerid, gemport, rx_q, tx_q, tcont);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (gemport >= 255)
+        {
+            printk(KERN_INFO "invalid gemport[%d]\n", gemport);
+        }
+        else
+        {
+            if ((rc = _tpm_omci_add_channel (ownerid,
+                                            (uint16_t)gemport,
+                                            rx_q,
+                                            tcont,
+                                            tx_q)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_omci_add_channel failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_oam_epon_del_channel_bounce(uint32_t owner_id)
+{
+	tpm_ioctl_mng_ch_t *tpm_oam_epon_chan = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mng_channel;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MNG_SECTION;
+	tpm_oam_epon_chan->mng_cmd = MV_TPM_IOCTL_DEL_OAM_CHNL;
+	tpm_oam_epon_chan->tpm_ioctl_oam_ch.owner_id = owner_id;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+ #define _tpm_oam_epon_del_channel tpm_oam_epon_del_channel_bounce
+#else
+ #define _tpm_oam_epon_del_channel tpm_oam_epon_del_channel
+#endif
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_oam_channel
+*
+* DESCRIPTION:
+*           This function deletes OAM channel HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_oam_channel  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        nooam_owner=0, nooam_max
+    } oam_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+
+    if (numparms == 1 && buf[0] == '?')
+    {
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+        char helpbuf[1000];
+        int  helpbuf_len;
+
+        helpbuf_len = sfs_help_no_oam_omci_channel(helpbuf);
+        print_help_buffer(helpbuf, helpbuf_len);
+#else
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", nooam_max, numparms);
+#endif
+    }
+    else if (numparms != 1)
+    {
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", nooam_max, numparms);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d", &ownerid);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d]\n", len, parsedargs, ownerid);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if ((rc = _tpm_oam_epon_del_channel (ownerid)) == TPM_RC_OK)
+        {
+            printk(KERN_INFO "OK\n");
+        }
+        else
+        {
+            printk(KERN_INFO "%s: tpm_oam_epon_del_channel failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_omci_del_channel_bounce(uint32_t owner_id)
+{
+	tpm_ioctl_mng_ch_t *tpm_omci_gpon_chan = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mng_channel;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MNG_SECTION;
+	tpm_omci_gpon_chan->mng_cmd = MV_TPM_IOCTL_DEL_OMCI_CHNL;
+	tpm_omci_gpon_chan->tpm_ioctl_omci_ch.owner_id = owner_id;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+ #define _tpm_omci_del_channel tpm_omci_del_channel_bounce
+#else
+ #define _tpm_omci_del_channel tpm_omci_del_channel
+#endif
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_omci_channel
+*
+* DESCRIPTION:
+*           This function creates creates an OMCI channel HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_omci_channel  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        noomci_owner=0, noomci_max
+    } noomci__parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+
+    if (numparms == 1 && buf[0] == '?')
+    {
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+        char helpbuf[1000];
+        int  helpbuf_len;
+
+        helpbuf_len = sfs_help_no_oam_omci_channel(helpbuf);
+        print_help_buffer(helpbuf, helpbuf_len);
+#else
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", noomci_max, numparms);
+#endif
+    }
+    else if (numparms != 1)
+    {
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", noomci_max, numparms);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d ", &ownerid);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d]\n", len, parsedargs, ownerid);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if ((rc = _tpm_omci_del_channel (ownerid)) == TPM_RC_OK)
+        {
+            printk(KERN_INFO "OK\n");
+        }
+        else
+        {
+            printk(KERN_INFO "%s: tpm_omci_del_channel failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_setup
+*
+* DESCRIPTION:
+*           This function initializes tpm module
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_setup  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        /*setup_ponype=0,  */setup_filename=0, setup_max
+    } setup_parm_indx_t;
+    // shell line parsing
+    /*uint32_t                 pon_type;*/
+    char                     filename[XML_FILE_PATH_LENGTH];
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+    tpm_setup_t              setup;
+
+    memset(&setup, 0, sizeof(tpm_setup_t));
+
+    numparms = count_parameters(buf);
+    if (numparms != setup_max)
+    {
+        parm_error_completion(numparms, setup_max, buf, sfs_help_setup);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s", filename);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], level[%d]\n", len, parsedargs, ownerid, level);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        /*else if (pon_type >= TPM_NONE)
+        {
+            printk(KERN_INFO "Invalid pon_type[%d]\n", pon_type);
+        }*/
+        else
+        {
+            /*setup.pon_type = pon_type;*/
+            if (strcmp(filename, "default"))
+            {
+                strcpy(setup.xml_file_path, filename);
+            }
+            if ((rc = module_tpmSetup(&setup)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: module_tpmSetup failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_mib_reset_bounce(uint32_t     owner_id,
+                                      uint32_t     level)
+{
+    tpm_ioctl_mib_reset_t *tpm_mib_reset_param = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mib_reset_param;
+
+    tpm_sfs_2_ioctl_command.cmd         = MV_TPM_IOCTL_RESET_SECTION;
+    tpm_mib_reset_param->owner_id       = owner_id;
+    tpm_mib_reset_param->reset_level    = level;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_mib_reset tpm_mib_reset_bounce
+#else
+ #define _tpm_mib_reset tpm_mib_reset
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mib_reset
+*
+* DESCRIPTION:
+*           This function creates does a MIB reset
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mib_reset  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mibreset_owner=0, mibreset_gemport,  mibreset_max
+    } mibreset_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 level;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != mibreset_max)
+    {
+        parm_error_completion(numparms, mibreset_max, buf, sfs_help_mib_reset);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &level);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], level[%d]\n", len, parsedargs, ownerid, level);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (level > TPM_ENUM_MAX_RESET_LEVEL)
+        {
+            printk(KERN_INFO "Invalid level[%d]\n", level);
+        }
+        else
+        {
+            if ((rc = _tpm_mib_reset(ownerid,
+                                     level)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_mib_reset failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_erase_section
+*
+* DESCRIPTION:
+*           This function erases a section per an application group.
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len     - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_erase_section(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		section_owner_id=0, section_api_type, erase_section_max
+	} erase_section_parm_indx_t;
+	/*shell line parsing*/
+	uint32_t                 ownerid;
+	uint32_t                 api_type;
+	int                      parsedargs;
+	int                      numparms;
+	tpm_error_code_t         rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != erase_section_max)
+		parm_error_completion(numparms, erase_section_max, buf, sfs_help_erase_section);
+	else {
+		/*get parameters*/
+		parsedargs = sscanf(buf, "%d %d", &ownerid, &api_type);
+		if(parsedargs != numparms)
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		else if (api_type > TPM_MAX_API_TYPES)
+			printk(KERN_INFO "Invalid api type[%d]\n", api_type);
+		else {
+			if ((rc = tpm_erase_section(ownerid, api_type)) == TPM_RC_OK)
+				printk(KERN_INFO "OK\n");
+			else
+				printk(KERN_INFO "%s: tpm_erase_section failed, rc[%d] - %s\n",
+				__FUNCTION__, rc, get_tpm_err_str(rc));
+		}
+	}
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_cpu_wan_loopback_bounce(uint32_t         owner_id,
+                                                 tpm_pkt_frwd_t  *pkt_frwd,
+                                                 uint32_t        *mod_idx)
+{
+    tpm_ioctl_cpu_lpbk_t *tpm_ioctl_cpu_lpbk = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_cpu_lpbk;
+
+    tpm_sfs_2_ioctl_command.cmd         = MV_TPM_IOCTL_CPU_LPBK_SECTION;
+    tpm_ioctl_cpu_lpbk->cpu_lpbk_cmd    = MV_TPM_IOCTL_ADD_CPU_WAN_LPBK;
+    tpm_ioctl_cpu_lpbk->owner_id        = owner_id;
+    memcpy(&(tpm_ioctl_cpu_lpbk->pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_cpu_wan_loopback tpm_add_cpu_wan_loopback_bounce
+#else
+ #define _tpm_add_cpu_wan_loopback tpm_add_cpu_wan_loopback
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_add_cpu_lpbk
+*
+* DESCRIPTION:
+*           This function adds CPU WAN loopback
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_add_cpu_lpbk  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        lpbk_owner=0, lpbk_port, lpbk_que, lpbk_gem, lpbk_max
+    } lpbk_parm_indx_t;
+    uint32_t            ownerid;
+    uint32_t            temp_port;
+    uint32_t            temp_que;
+    uint32_t            temp_gem;
+    int                 parsedargs;
+    int                 numparms;
+    tpm_error_code_t    rc;
+    tpm_pkt_frwd_t      frwd_entry;
+    uint32_t            mod_idx;
+
+    numparms = count_parameters(buf);
+    if (numparms != lpbk_max)
+    {
+        parm_error_completion(numparms, lpbk_max, buf, sfs_help_cfg_cpu_lpbk);
+    }
+    else
+    {
+        /* Get parameters */
+        parsedargs = sscanf(buf, "%d 0x%x %d %d", &ownerid, &temp_port, &temp_que, &temp_gem);
+/*
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%s] temp_port[0x%x],temp_que[%d],temp_gem[%d]\n",
+               len, parsedargs, ownerid, temp_port, temp_que, temp_gem);
+*/
+        if (temp_que > 7)
+        {
+            printk(KERN_INFO "Invalid queue [%d]\n", temp_que);
+        }
+        else if (temp_gem > 4095)
+        {
+            printk(KERN_INFO "Invalid gem port [%d]\n", temp_gem);
+        }
+        else
+        {
+            frwd_entry.trg_port  = (tpm_trg_port_type_t)temp_port;
+            frwd_entry.trg_queue = (uint8_t)temp_que;
+            frwd_entry.gem_port  = (uint16_t)temp_gem;
+
+            rc = _tpm_add_cpu_wan_loopback(TPM_MOD_OWNER_TPM, &frwd_entry, &mod_idx);
+            if(TPM_RC_OK != rc)
+            {
+                printk(KERN_ERR "Failed to call tpm_add_cpu_wan_loopback, ret_code[%d]\n", rc);
+            }
+            else
+            {
+                printk(KERN_ERR "Call tpm_add_cpu_wan_loopback successfully, mod_idx[%d]\n", mod_idx);
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_cpu_wan_loopback_bounce(uint32_t         owner_id,
+                                                 tpm_pkt_frwd_t  *pkt_frwd)
+{
+    tpm_ioctl_cpu_lpbk_t *tpm_ioctl_cpu_lpbk = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_cpu_lpbk;
+
+    tpm_sfs_2_ioctl_command.cmd         = MV_TPM_IOCTL_CPU_LPBK_SECTION;
+    tpm_ioctl_cpu_lpbk->cpu_lpbk_cmd    = MV_TPM_IOCTL_DEL_CPU_WAN_LPBK;
+    tpm_ioctl_cpu_lpbk->owner_id        = owner_id;
+    memcpy(&(tpm_ioctl_cpu_lpbk->pkt_frwd), pkt_frwd, sizeof(tpm_pkt_frwd_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_cpu_wan_loopback tpm_del_cpu_wan_loopback_bounce
+#else
+ #define _tpm_del_cpu_wan_loopback tpm_del_cpu_wan_loopback
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_del_cpu_lpbk
+*
+* DESCRIPTION:
+*           This function delete CPU WAN loopback
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_del_cpu_lpbk  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        lpbk_owner=0, lpbk_port, lpbk_que, lpbk_gem, lpbk_max
+    } lpbk_parm_indx_t;
+    uint32_t            ownerid;
+    uint32_t            temp_port;
+    uint32_t            temp_que;
+    uint32_t            temp_gem;
+    int                 parsedargs;
+    int                 numparms;
+    tpm_error_code_t    rc;
+    tpm_pkt_frwd_t      frwd_entry;
+
+    numparms = count_parameters(buf);
+    if (numparms != lpbk_max)
+    {
+        parm_error_completion(numparms, lpbk_max, buf, sfs_help_cfg_cpu_lpbk);
+    }
+    else
+    {
+        /* Get parameters */
+        parsedargs = sscanf(buf, "%d 0x%x %d %d", &ownerid, &temp_port, &temp_que, &temp_gem);
+/*
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%s] temp_port[0x%x],temp_que[%d],temp_gem[%d]\n",
+               len, parsedargs, ownerid, temp_port, temp_que, temp_gem);
+*/
+        if (temp_que > 7)
+        {
+            printk(KERN_INFO "Invalid queue [%d]\n", temp_que);
+        }
+        else if (temp_gem > 4095)
+        {
+            printk(KERN_INFO "Invalid gem port [%d]\n", temp_gem);
+        }
+        else
+        {
+            frwd_entry.trg_port  = (tpm_trg_port_type_t)temp_port;
+            frwd_entry.trg_queue = (uint8_t)temp_que;
+            frwd_entry.gem_port  = (uint16_t)temp_gem;
+
+            rc = _tpm_del_cpu_wan_loopback(TPM_MOD_OWNER_TPM, &frwd_entry);
+            if(TPM_RC_OK != rc)
+            {
+                printk(KERN_ERR "Failed to call tpm_del_cpu_wan_loopback, ret_code[%d]\n", rc);
+            }
+            else
+            {
+                printk(KERN_ERR "Call tpm_del_cpu_wan_loopback successfully\n");
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_dump_cpu_lpbk
+*
+* DESCRIPTION:
+*           This function dumps all valid CPU WAN loopback entries from DB
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_dump_cpu_lpbk  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        lpbk_owner=0, lpbk_max
+    } lpbk_parm_indx_t;
+    uint32_t            ownerid;
+    int                 parsedargs;
+    int                 numparms;
+
+    numparms = count_parameters(buf);
+    if (numparms != lpbk_max)
+    {
+        parm_error_completion(numparms, lpbk_max, buf, sfs_help_cfg_cpu_lpbk);
+    }
+    else
+    {
+        /* Get parameters */
+        parsedargs = sscanf(buf, "%d", &ownerid);
+        /*
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%s]\n",
+               len, parsedargs, ownerid);
+        */
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            tpm_print_cpu_lpbk_entry();
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_get_lu_entry
+*
+* DESCRIPTION:
+*           This function dumps least used PnC entries
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_get_lu_entry (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        age_owner_id=0, age_api_group, age_lu_num, age_lu_reset, age_max
+    } age_parm_indx_t;
+    uint32_t            owner_id;
+    uint32_t            api_group;
+    uint32_t            lu_num;
+    uint32_t            lu_reset;
+    int                 parsed_args_num;
+    int                 param_num;
+
+    param_num = count_parameters(buf);
+    if (param_num != age_max)
+    {
+        parm_error_completion(param_num, age_max, buf, sfs_help_cfg_age_count);
+    }
+    else
+    {
+        /* Get parameters */
+        parsed_args_num = sscanf(buf, "%d %d %d %d", &owner_id, &api_group, &lu_num, &lu_reset);
+        /*
+        printk(KERN_INFO "len=%d, parsed_args_num[%d], ownerid[%d], api_group[%d], lu_num[%d], lu_reset[%d]\n",
+               len, parsed_args_num, owner_id, api_group, lu_num, lu_reset);
+        */
+
+        if (parsed_args_num != param_num)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsed_args_num, param_num);
+        }
+        else
+        {
+            if((lu_num <= 0) || ( lu_num > TPM_MAX_LU_ENTRY_NUM))
+            {
+                printk(KERN_INFO "lu_num[%d] is illegal, allowed lu_num[1~%d]\n", lu_num, TPM_MAX_LU_ENTRY_NUM);
+                return;
+            }
+
+            tpm_print_tcam_lu_entry(owner_id, api_group, lu_num, lu_reset);
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_get_pnc_all_hit_counters_bounce(uint32_t               owner_id,
+                                                    tpm_api_type_t          api_type,
+                                                    uint32_t                high_thresh_pkts,
+                                                    uint8_t                 counters_reset,
+                                                    uint16_t               *valid_counters,
+                                                    tpm_api_entry_count_t  *count_array)
+{
+    tpm_ioctl_pnc_hit_cnt_t *tpm_ioctl_pnc_hit_cnt = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_pnc_hit_cnt;
+
+    tpm_sfs_2_ioctl_command.cmd             = MV_TPM_IOCTL_AGE_COUNT_SECTION;
+    tpm_ioctl_pnc_hit_cnt->age_count_cmd    = MV_TPM_IOCTL_GET_ALL_HIT_COUNTERS;
+    tpm_ioctl_pnc_hit_cnt->owner_id         = owner_id;
+    tpm_ioctl_pnc_hit_cnt->api_type         = api_type;
+    tpm_ioctl_pnc_hit_cnt->high_thresh_pkts = high_thresh_pkts;
+    tpm_ioctl_pnc_hit_cnt->counter_reset    = counters_reset;
+    tpm_ioctl_pnc_hit_cnt->valid_counters   = *valid_counters;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_get_pnc_all_hit_counters tpm_get_pnc_all_hit_counters_bounce
+ #define _tpm_print_pnc_all_hit_counters(a,b,c,d,e,f)
+#else
+ #define _tpm_get_pnc_all_hit_counters tpm_get_pnc_all_hit_counters
+ #define _tpm_print_pnc_all_hit_counters(a,b,c,d,e,f) tpm_print_pnc_all_hit_counters(a,b,c,d,e,f)
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_get_pnc_all_hit_counters
+*
+* DESCRIPTION:
+*           This function prints all pnc hit counters per API type masking out
+*           high counter values according to high_thresh_pkts
+* INPUTS:
+*       buf - Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_get_pnc_all_hit_counters (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        age_owner_id=0, age_api_type, age_high_thresh_pkts, age_counters_reset, age_valid_counters, age_max
+    } age_parm_indx_t;
+    uint32_t                owner_id;
+    uint32_t                api_type;
+    uint32_t                high_thresh_pkts;
+    uint32_t                counters_reset;
+    uint32_t                valid_counters;
+    int                     parsed_args_num;
+    int                     param_num;
+    tpm_error_code_t        ret_code;
+	tpm_api_entry_count_t   count_array[CONFIG_MV_PNC_TCAM_LINES];
+
+    param_num = count_parameters(buf);
+    if (param_num != age_max)
+    {
+        parm_error_completion(param_num, age_max, buf, sfs_help_cfg_age_count);
+    }
+    else
+    {
+        /* Get parameters */
+        parsed_args_num = sscanf(buf, "%d %d %d %d %d", &owner_id, &api_type, &high_thresh_pkts,
+                                 &counters_reset, &valid_counters);
+
+        if (parsed_args_num != param_num)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsed_args_num, param_num);
+        }
+        else
+        {
+            ret_code = _tpm_get_pnc_all_hit_counters(owner_id,
+                                                     api_type,
+                                                     high_thresh_pkts,
+                                                     counters_reset,
+                                                    (uint16_t*)&valid_counters,
+                                                    &(count_array[0]));
+
+            if (TPM_RC_OK == ret_code)
+            {
+                _tpm_print_pnc_all_hit_counters(owner_id,
+                                                api_type, high_thresh_pkts,
+                                                (uint8_t)counters_reset,
+                                                valid_counters,
+                                                &(count_array[0]));
+            }
+            else
+            {
+                printk(KERN_INFO "%s: _tpm_get_pnc_all_hit_counters failed, rc[%d] - %s\n",
+                       __FUNCTION__, ret_code, get_tpm_err_str(ret_code));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_set_pnc_counter_mask_bounce(uint32_t           owner_id,
+                                                 tpm_api_type_t     api_type,
+                                                 uint32_t           rule_idx,
+                                                 uint32_t           lu_rule_mask)
+{
+    tpm_ioctl_age_count_t *tpm_ioctl_age_count = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_age_count;
+
+    tpm_sfs_2_ioctl_command.cmd         = MV_TPM_IOCTL_AGE_COUNT_SECTION;
+    tpm_ioctl_age_count->age_count_cmd  = MV_TPM_IOCTL_SET_LU_COUNT_MASK;
+    tpm_ioctl_age_count->owner_id       = owner_id;
+    tpm_ioctl_age_count->api_type       = api_type;
+    tpm_ioctl_age_count->rule_idx       = rule_idx;
+    tpm_ioctl_age_count->lu_rule_mask   = lu_rule_mask;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_set_pnc_counter_mask tpm_set_pnc_counter_mask_bounce
+#else
+ #define _tpm_set_pnc_counter_mask tpm_set_pnc_counter_mask
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_count_mask
+*
+* DESCRIPTION:
+*           This function sets count mask
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_count_mask (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        age_owner_id=0, age_api_group, age_rule_idx, age_lu_rule_mask, age_max
+    } age_parm_indx_t;
+    uint32_t            owner_id;
+    uint32_t            api_group;
+    uint32_t            rule_idx;
+    uint32_t            lu_rule_mask;
+    int                 parsed_args_num;
+    int                 param_num;
+    tpm_error_code_t    ret_code;
+
+    param_num = count_parameters(buf);
+    if (param_num != age_max)
+    {
+        parm_error_completion(param_num, age_max, buf, sfs_help_cfg_age_count);
+    }
+    else
+    {
+        /* Get parameters */
+        parsed_args_num = sscanf(buf, "%d %d %d %d", &owner_id, &api_group, &rule_idx, &lu_rule_mask);
+        /*
+        printk(KERN_INFO "len=%d, parsed_args_num[%d], ownerid[%d], api_group[%d], rule_idx[%d], lu_rule_mask[%d]\n",
+               len, parsed_args_num, owner_id, api_group, rule_idx, lu_rule_mask);
+        */
+
+        if (parsed_args_num != param_num)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsed_args_num, param_num);
+        }
+        else
+        {
+            if ((ret_code = _tpm_set_pnc_counter_mask(owner_id,
+                                                      api_group,
+                                                      rule_idx,
+                                                      lu_rule_mask)) == TPM_RC_OK)
+                PR_RESULT
+            else
+                printk(KERN_INFO "%s: tpm_set_pnc_counter_mask failed, rc[%d] - %s\n", __FUNCTION__,
+                       ret_code, get_tpm_err_str(ret_code));
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_get_pnc_hit_count_bounce(uint32_t             owner_id,
+                                              tpm_api_type_t       api_type,
+                                              uint32_t             rule_idx,
+                                              uint8_t              hit_reset,
+                                              uint32_t            *hit_count)
+{
+    tpm_ioctl_age_count_t *tpm_ioctl_age_count = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_age_count;
+
+    tpm_sfs_2_ioctl_command.cmd         = MV_TPM_IOCTL_AGE_COUNT_SECTION;
+    tpm_ioctl_age_count->age_count_cmd  = MV_TPM_IOCTL_GET_HIT_COUNT;
+    tpm_ioctl_age_count->owner_id       = owner_id;
+    tpm_ioctl_age_count->api_type       = api_type;
+    tpm_ioctl_age_count->rule_idx       = rule_idx;
+    tpm_ioctl_age_count->hit_reset      = hit_reset;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_get_pnc_hit_count tpm_get_pnc_hit_count_bounce
+#else
+ #define _tpm_get_pnc_hit_count tpm_get_pnc_hit_count
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_get_hit_count
+*
+* DESCRIPTION:
+*           This function sets count mask
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_get_hit_count (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        age_owner_id=0, age_api_group, age_rule_idx, age_hit_reset, age_max
+    } age_parm_indx_t;
+    uint32_t            owner_id;
+    uint32_t            api_group;
+    uint32_t            rule_idx;
+    int                 parsed_args_num;
+    int                 param_num;
+    uint32_t            hit_count = 0;
+    uint32_t            hit_reset;
+    tpm_error_code_t    ret_code;
+
+    param_num = count_parameters(buf);
+    if (param_num != age_max)
+    {
+        parm_error_completion(param_num, age_max, buf, sfs_help_cfg_age_count);
+    }
+    else
+    {
+        /* Get parameters */
+        parsed_args_num = sscanf(buf, "%d %d %d %d", &owner_id, &api_group, &rule_idx, &hit_reset);
+        /*
+        printk(KERN_INFO "len=%d, parsed_args_num[%d], ownerid[%d], range_id[%d], rule_idx[%d]\n",
+               len, parsed_args_num, owner_id, range_id, rule_idx);
+        */
+        if (parsed_args_num != param_num)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsed_args_num, param_num);
+        }
+        else
+        {
+            if ((ret_code = _tpm_get_pnc_hit_count(owner_id,
+                                                   api_group,
+                                                   rule_idx,
+                                                   (uint8_t)hit_reset,
+                                                   &hit_count)) == TPM_RC_OK)
+                PR_HIT_COUNT(hit_count)
+            else
+                printk(KERN_INFO "%s: tpm_get_pnc_hit_count failed, rc[%d] - %s\n", __FUNCTION__,
+                       ret_code, get_tpm_err_str(ret_code));
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_set_pnc_lu_threshold_bounce(uint32_t             owner_id,
+                                                 tpm_api_type_t       api_type,
+                                                 uint32_t             lu_thresh_pkts)
+{
+    tpm_ioctl_age_count_t *tpm_ioctl_age_count = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_age_count;
+
+    tpm_sfs_2_ioctl_command.cmd         = MV_TPM_IOCTL_AGE_COUNT_SECTION;
+    tpm_ioctl_age_count->age_count_cmd  = MV_TPM_IOCTL_SET_LU_THESHOLD;
+    tpm_ioctl_age_count->owner_id       = owner_id;
+    tpm_ioctl_age_count->api_type       = api_type;
+    tpm_ioctl_age_count->lu_thresh_pkts = lu_thresh_pkts;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_set_pnc_lu_threshold tpm_set_pnc_lu_threshold_bounce
+#else
+ #define _tpm_set_pnc_lu_threshold tpm_set_pnc_lu_threshold
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_lu_thresh
+*
+* DESCRIPTION:
+*           This function sets count mask
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_lu_thresh (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        age_owner_id=0, age_api_group, age_lu_thresh_pkts, age_max
+    } age_parm_indx_t;
+    uint32_t            owner_id;
+    uint32_t            api_group;
+    uint32_t            lu_thresh_pkts;
+    int                 parsed_args_num;
+    int                 param_num;
+    tpm_error_code_t    ret_code;
+
+    param_num = count_parameters(buf);
+    if (param_num != age_max)
+    {
+        parm_error_completion(param_num, age_max, buf, sfs_help_cfg_age_count);
+    }
+    else
+    {
+        /* Get parameters */
+        parsed_args_num = sscanf(buf, "%d %d %d", &owner_id, &api_group, &lu_thresh_pkts);
+        /*
+        printk(KERN_INFO "len=%d, parsed_args_num[%d], ownerid[%d], api_group[%d], rule_idx[%d]\n",
+               len, parsed_args_num, owner_id, api_group, rule_idx);
+        */
+
+        if (parsed_args_num != param_num)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsed_args_num, param_num);
+        }
+        else
+        {
+            if ((ret_code = _tpm_set_pnc_lu_threshold(owner_id,
+                                                     api_group,
+                                                     lu_thresh_pkts)) == TPM_RC_OK)
+                PR_RESULT
+            else
+                printk(KERN_INFO "%s: tpm_set_pnc_lu_threshold failed, rc[%d] - %s\n", __FUNCTION__,
+                       ret_code, get_tpm_err_str(ret_code));
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_reset_pnc_age_group_bounce(uint32_t                owner_id,
+                                                tpm_api_type_t          api_type)
+{
+    tpm_ioctl_age_count_t *tpm_ioctl_age_count = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_age_count;
+
+    tpm_sfs_2_ioctl_command.cmd         = MV_TPM_IOCTL_AGE_COUNT_SECTION;
+    tpm_ioctl_age_count->age_count_cmd  = MV_TPM_IOCTL_RESET_COUNT_GROUP;
+    tpm_ioctl_age_count->owner_id       = owner_id;
+    tpm_ioctl_age_count->api_type       = api_type;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_reset_pnc_age_group tpm_reset_pnc_age_group_bounce
+#else
+ #define _tpm_reset_pnc_age_group tpm_reset_pnc_age_group
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_reset_age_group
+*
+* DESCRIPTION:
+*           This function sets count mask
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_reset_age_group (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        age_owner_id=0, age_api_group,  age_max
+    } age_parm_indx_t;
+    uint32_t            owner_id;
+    uint32_t            api_group;
+    int                 parsed_args_num;
+    int                 param_num;
+    tpm_error_code_t    ret_code;
+
+    param_num = count_parameters(buf);
+    if (param_num != age_max)
+    {
+        parm_error_completion(param_num, age_max, buf, sfs_help_cfg_age_count);
+    }
+    else
+    {
+        /* Get parameters */
+        parsed_args_num = sscanf(buf, "%d %d", &owner_id, &api_group);
+        /*
+        printk(KERN_INFO "len=%d, parsed_args_num[%d], ownerid[%d], api_group[%d]\n",
+               len, parsed_args_num, owner_id, api_group);
+        */
+
+        if (parsed_args_num != param_num)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsed_args_num, param_num);
+        }
+        else
+        {
+            if ((ret_code = _tpm_reset_pnc_age_group(owner_id,
+                                                     api_group)) == TPM_RC_OK)
+                PR_RESULT
+            else
+                printk(KERN_INFO "%s: tpm_reset_pnc_age_group failed, rc[%d] - %s\n", __FUNCTION__,
+                       ret_code, get_tpm_err_str(ret_code));
+        }
+    }
+}
+
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_tm_set_wan_q_ingr_rate_lim_bounce(uint32_t owner_id,
+							uint32_t queue_id,
+							uint32_t rate_limit_val,
+							uint32_t bucket_size)
+{
+	tpm_ioctl_tm_tm_t *tpm_tm_tm_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_tm_tm;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_PP_TM_SECTION;
+	tpm_tm_tm_set->pp_tm_cmd = MV_TPM_IOCTL_TM_SET_WAN_QUE_INGR_RATE_LIMIT;
+	tpm_tm_tm_set->owner_id = owner_id;
+	tpm_tm_tm_set->queue_id = queue_id;
+	tpm_tm_tm_set->rate_limit_val = rate_limit_val;
+	tpm_tm_tm_set->bucket_size = bucket_size;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+
+ tpm_error_code_t tpm_tm_set_wan_queue_egr_rate_lim_bounce(uint32_t owner_id,
+ 							tpm_trg_port_type_t sched_ent,
+							uint32_t queue_id,
+							uint32_t rate_limit_val,
+							uint32_t bucket_size)
+ {
+	 tpm_ioctl_tm_tm_t *tpm_tm_tm_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_tm_tm;
+
+	 tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_PP_TM_SECTION;
+	 tpm_tm_tm_set->pp_tm_cmd = MV_TPM_IOCTL_TM_SET_WAN_QUE_EGR_RATE_LIMIT;
+	 tpm_tm_tm_set->owner_id = owner_id;
+	 tpm_tm_tm_set->sched_ent = sched_ent;
+	 tpm_tm_tm_set->queue_id = queue_id;
+	 tpm_tm_tm_set->rate_limit_val = rate_limit_val;
+	 tpm_tm_tm_set->bucket_size = bucket_size;
+
+	 up(&tpm_sfs_2_ioctl_sem);
+
+	 return TPM_RC_OK;
+ }
+
+ #define _tpm_tm_set_wan_q_ingr_rate_lim tpm_tm_set_wan_q_ingr_rate_lim_bounce
+ #define _tpm_tm_set_wan_queue_egr_rate_lim tpm_tm_set_wan_queue_egr_rate_lim_bounce
+#else
+ #define _tpm_tm_set_wan_q_ingr_rate_lim tpm_tm_set_wan_q_ingr_rate_lim
+ #define _tpm_tm_set_wan_queue_egr_rate_lim tpm_tm_set_wan_queue_egr_rate_lim
+#endif
+/*******************************************************************************
+* sfs_tpm_cfg_set_rate_limit_queue_set
+*
+* DESCRIPTION:
+*           This function sets rate limit on queue
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_rate_limit_queue_set       (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        qratelim_owner=0, qratelim_direction, qratelim_if, qratelim_que, qratelim_rate_limit, qratelim_bucket_size, qratelim_max
+    } qratelim_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    char                     direction_str[20];
+    uint32_t                 direction;
+    char                     entity_str[20];
+    char                     uc_entity_str[20];
+    int                      indx;
+    uint32_t                 entity;
+    uint32_t                 que;
+    uint32_t                 rate_limit;
+    uint32_t                 bucket_size;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != qratelim_max)
+    {
+        parm_error_completion(numparms, qratelim_max, buf, sfs_help_rate_limit);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %s %d %d %d", &ownerid, direction_str, entity_str, &que, &rate_limit, &bucket_size);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], direction_str[%s], entity_str[%s], que[%d], rate_limit[%d], bucket_size[%d]\n",
+//               len, parsedargs, ownerid, direction_str, entity_str, que, rate_limit, bucket_size);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(entity_str); indx++) uc_entity_str[indx] = (char)toupper(entity_str[indx]);
+        uc_entity_str[strlen(entity_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_direction_value(direction_str, &direction) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid direction[%s]\n", direction_str);
+        }
+        else if (get_sched_entity_value(uc_entity_str, &entity) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid sched_entity[%s] %s\n", entity_str, uc_entity_str);
+        }
+        else if ((direction == TPM_UPSTREAM   && que >= TPM_MAX_NUM_TX_QUEUE) ||
+                 (direction == TPM_DOWNSTREAM && que >= TPM_MAX_NUM_RX_QUEUE))
+        {
+            printk(KERN_INFO "Invalid queue[%d]\n", que);
+        }
+        else
+        {
+            if (direction == TPM_DOWNSTREAM)
+            {
+                if ((rc = _tpm_tm_set_wan_q_ingr_rate_lim (ownerid,
+                                                          // entity,
+                                                          que,
+                                                          rate_limit,
+                                                          bucket_size)) == TPM_RC_OK)
+                {
+                    printk(KERN_INFO "OK\n");
+                }
+                else
+                {
+                    printk(KERN_INFO "%s: tpm_tm_set_wan_q_ingr_rate_lim failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+                }
+            }
+            else
+            {
+                if ((rc = _tpm_tm_set_wan_queue_egr_rate_lim (ownerid,
+                                                             entity,
+                                                             que,
+                                                             rate_limit,
+                                                             bucket_size)) == TPM_RC_OK)
+                {
+                    printk(KERN_INFO "OK\n");
+                }
+                else
+                {
+                    printk(KERN_INFO "%s: tpm_tm_set_wan_queue_egr_rate_lim failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+                }
+            }
+        }
+    }
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_tm_set_wan_ingr_queue_sched_bounce(uint32_t owner_id,
+							tpm_pp_sched_type_t sched_mode,
+							uint8_t queue_id,
+							uint16_t wrr_weight)
+{
+	tpm_ioctl_tm_tm_t *tpm_tm_tm_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_tm_tm;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_PP_TM_SECTION;
+	tpm_tm_tm_set->pp_tm_cmd = MV_TPM_IOCTL_TM_SET_WAN_INGR_QUE_SCHED;
+	tpm_tm_tm_set->owner_id = owner_id;
+	tpm_tm_tm_set->pp_sched_mode = sched_mode;
+	tpm_tm_tm_set->queue_id = queue_id;
+	tpm_tm_tm_set->wrr_weight = wrr_weight;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+
+ tpm_error_code_t tpm_tm_set_wan_egr_queue_sched_bounce(uint32_t owner_id,
+							tpm_trg_port_type_t sched_ent,
+							tpm_pp_sched_type_t sched_mode,
+							uint8_t queue_id,
+							uint16_t wrr_weight)
+ {
+	 tpm_ioctl_tm_tm_t *tpm_tm_tm_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_tm_tm;
+
+	 tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_PP_TM_SECTION;
+	 tpm_tm_tm_set->pp_tm_cmd = MV_TPM_IOCTL_TM_SET_WAN_EGR_QUE_SCHED;
+	 tpm_tm_tm_set->owner_id = owner_id;
+	 tpm_tm_tm_set->sched_ent = sched_ent;
+	 tpm_tm_tm_set->pp_sched_mode = sched_mode;
+	 tpm_tm_tm_set->queue_id = queue_id;
+	 tpm_tm_tm_set->wrr_weight = wrr_weight;
+
+	 up(&tpm_sfs_2_ioctl_sem);
+
+	 return TPM_RC_OK;
+ }
+
+ #define _tpm_tm_set_wan_ingr_queue_sched tpm_tm_set_wan_ingr_queue_sched_bounce
+ #define _tpm_tm_set_wan_egr_queue_sched tpm_tm_set_wan_egr_queue_sched_bounce
+#else
+ #define _tpm_tm_set_wan_ingr_queue_sched tpm_tm_set_wan_ingr_queue_sched
+ #define _tpm_tm_set_wan_egr_queue_sched tpm_tm_set_wan_egr_queue_sched
+#endif
+/*******************************************************************************
+* sfs_tpm_cfg_set_scheduling_mode_queue_set
+*
+* DESCRIPTION:
+*           This function configures queue operation mode (per IF, per direction)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_scheduling_mode_queue_set       (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        sched_owner=0, sched_direction, sched_if, sched_que, sched_rate_limit, sched_bucket_size, sched_max
+    } sched_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    char                     direction_str[20];
+    uint32_t                 direction;
+    char                     entity_str[20];
+    char                     uc_entity_str[20];
+    int                      indx;
+    uint32_t                 entity;
+    char                     mode_str[20];
+    uint32_t                 mode;
+    uint32_t                 que;
+    uint32_t                 wrr_weight;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != sched_max)
+    {
+        parm_error_completion(numparms, sched_max, buf, sfs_help_rate_limit);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %s %s %d %d", &ownerid, direction_str, entity_str, mode_str, &que, &wrr_weight);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], direction_str[%s], entity_str[%s], mode[%s], que[%d], wrr_weight[%d]\n",
+//               len, parsedargs, ownerid, direction_str, entity_str, mode_str, que, wrr_weight);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(entity_str); indx++) uc_entity_str[indx] = (char)toupper(entity_str[indx]);
+        uc_entity_str[strlen(entity_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_direction_value(direction_str, &direction) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid direction[%s]\n", direction_str);
+        }
+        else if (get_sched_entity_value(uc_entity_str, &entity) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid sched_entity[%s] %s\n", entity_str, uc_entity_str);
+        }
+        else if (get_scheduling_mode_value(mode_str, &mode) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid mode[%s]\n", mode_str);
+        }
+        else if ((direction == TPM_UPSTREAM   && que >= TPM_MAX_NUM_TX_QUEUE) ||
+                 (direction == TPM_DOWNSTREAM && que >= TPM_MAX_NUM_RX_QUEUE))
+        {
+            printk(KERN_INFO "Invalid queue[%d]\n", que);
+        }
+        else
+        {
+            if (direction == TPM_DOWNSTREAM)
+            {
+                if ((rc = _tpm_tm_set_wan_ingr_queue_sched (ownerid,
+                                                           mode,
+                                                           que,
+                                                           wrr_weight)) == TPM_RC_OK)
+                {
+                    printk(KERN_INFO "OK\n");
+                }
+                else
+                {
+                    printk(KERN_INFO "%s: tpm_tm_set_wan_ingr_queue_sched failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+                }
+            }
+            else
+            {
+                if ((rc = _tpm_tm_set_wan_egr_queue_sched (ownerid,
+                                                          entity,
+                                                          mode,
+                                                          que,
+                                                          wrr_weight)) == TPM_RC_OK)
+                {
+                    printk(KERN_INFO "OK\n");
+                }
+                else
+                {
+                    printk(KERN_INFO "%s: tpm_tm_set_wan_egr_queue_sched failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+                }
+            }
+        }
+    }
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_tm_set_wan_ingr_rate_lim_bounce(uint32_t owner_id,
+							uint32_t rate_limit_val,
+							uint32_t bucket_size)
+{
+	tpm_ioctl_tm_tm_t *tpm_tm_tm_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_tm_tm;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_PP_TM_SECTION;
+	tpm_tm_tm_set->pp_tm_cmd = MV_TPM_IOCTL_TM_SET_WAN_INGR_RATE_LIMIT;
+	tpm_tm_tm_set->owner_id = owner_id;
+	tpm_tm_tm_set->rate_limit_val = rate_limit_val;
+	tpm_tm_tm_set->bucket_size = bucket_size;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+
+ tpm_error_code_t tpm_tm_set_wan_sched_egr_rate_lim_bounce(uint32_t owner_id,
+ 							tpm_trg_port_type_t sched_ent,
+							uint32_t rate_limit_val,
+							uint32_t bucket_size)
+ {
+	 tpm_ioctl_tm_tm_t *tpm_tm_tm_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_tm_tm;
+
+	 tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_PP_TM_SECTION;
+	 tpm_tm_tm_set->pp_tm_cmd = MV_TPM_IOCTL_TM_SET_WAN_SCHED_EGR_RATE_LIMIT;
+	 tpm_tm_tm_set->owner_id = owner_id;
+	 tpm_tm_tm_set->sched_ent = sched_ent;
+	 tpm_tm_tm_set->rate_limit_val = rate_limit_val;
+	 tpm_tm_tm_set->bucket_size = bucket_size;
+
+	 up(&tpm_sfs_2_ioctl_sem);
+
+	 return TPM_RC_OK;
+ }
+
+ #define _tpm_tm_set_wan_ingr_rate_lim tpm_tm_set_wan_ingr_rate_lim_bounce
+ #define _tpm_tm_set_wan_sched_egr_rate_lim tpm_tm_set_wan_sched_egr_rate_lim_bounce
+#else
+ #define _tpm_tm_set_wan_ingr_rate_lim tpm_tm_set_wan_ingr_rate_lim
+ #define _tpm_tm_set_wan_sched_egr_rate_lim tpm_tm_set_wan_sched_egr_rate_lim
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_rate_limit_if_set
+*
+* DESCRIPTION:
+*           This function sets rate limit on interface
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_rate_limit_if_set          (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        entratelim_owner=0, entratelim_direction, entratelim_if, entratelim_rate_limit, entratelim_bucket_size, entratelim_max
+    } entratelim_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    char                     direction_str[20];
+    uint32_t                 direction;
+    char                     entity_str[20];
+    char                     uc_entity_str[20];
+    int                      indx;
+    uint32_t                 entity;
+    uint32_t                 rate_limit;
+    uint32_t                 bucket_size;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != entratelim_max)
+    {
+        parm_error_completion(numparms, entratelim_max, buf, sfs_help_rate_limit);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %s %d %d", &ownerid, direction_str, entity_str, &rate_limit, &bucket_size);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], direction_str[%s], entity_str[%s], rate_limit[%d], bucket_size[%d]\n",
+//               len, parsedargs, ownerid, direction_str, entity_str, rate_limit, bucket_size);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(entity_str); indx++) uc_entity_str[indx] = (char)toupper(entity_str[indx]);
+        uc_entity_str[strlen(entity_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_direction_value(direction_str, &direction) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid direction[%s]\n", direction_str);
+        }
+        else if (get_sched_entity_value(uc_entity_str, &entity) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid sched_entity[%s]\n", entity_str);
+        }
+        else
+        {
+            if (direction == TPM_DOWNSTREAM)
+            {
+                if ((rc = _tpm_tm_set_wan_ingr_rate_lim (ownerid,
+                                                        rate_limit,
+                                                        bucket_size)) == TPM_RC_OK)
+                {
+                    printk(KERN_INFO "OK\n");
+                }
+                else
+                {
+                    printk(KERN_INFO "%s: tpm_tm_set_wan_ingr_rate_lim failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+                }
+            }
+            else
+            {
+                if ((rc = _tpm_tm_set_wan_sched_egr_rate_lim (ownerid,
+                                                             entity,
+                                                             rate_limit,
+                                                             bucket_size)) == TPM_RC_OK)
+                {
+                    printk(KERN_INFO "OK\n");
+                }
+                else
+                {
+                    printk(KERN_INFO "%s: tpm_tm_set_wan_sched_egr_rate_lim failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+                }
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_tm_set_gmac0_ingr_rate_lim_bounce(uint32_t owner_id,
+						       uint32_t rate_limit_val,
+						       uint32_t bucket_size)
+{
+	tpm_ioctl_tm_tm_t *tpm_tm_tm_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_tm_tm;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_PP_TM_SECTION;
+	tpm_tm_tm_set->pp_tm_cmd = MV_TPM_IOCTL_TM_SET_GMAC0_INGR_RATE_LIMIT;
+	tpm_tm_tm_set->owner_id = owner_id;
+	tpm_tm_tm_set->rate_limit_val = rate_limit_val;
+	tpm_tm_tm_set->bucket_size = bucket_size;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+}
+
+ #define _tpm_tm_set_gmac0_ingr_rate_lim tpm_tm_set_gmac0_ingr_rate_lim_bounce
+#else
+ #define _tpm_tm_set_gmac0_ingr_rate_lim tpm_tm_set_gmac0_ingr_rate_lim
+#endif
+/*******************************************************************************
+* sfs_tpm_cfg_set_gmac0_ingr_rate_limit
+*
+* DESCRIPTION:
+*           This function sets rate limit on queue
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_gmac0_ingr_rate_limit(const char *buf, size_t len)
+{
+    typedef enum
+    {
+        qratelim_owner=0, qratelim_rate_limit, qratelim_bucket_size, qratelim_max
+    } qratelim_parm_indx_t;
+    /* shell line parsing */
+    uint32_t                 ownerid;
+    uint32_t                 rate_limit;
+    uint32_t                 bucket_size;
+    int                      parsedargs;
+    int                      numparms;
+    /* Used in API call */
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != qratelim_max) {
+        parm_error_completion(numparms, qratelim_max, buf, sfs_help_rate_limit);
+    } else {
+        /* Get parameters */
+        parsedargs = sscanf(buf, "%d %d %d", &ownerid, &rate_limit, &bucket_size);
+        if (parsedargs != numparms) {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        } else {
+            if ((rc = _tpm_tm_set_gmac0_ingr_rate_lim(ownerid,
+                                                      rate_limit,
+                                                      bucket_size)) == TPM_RC_OK)
+                printk(KERN_INFO "OK\n");
+            else
+                printk(KERN_INFO "%s: tpm_tm_set_gmac0_ingr_rate_lim failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_dip_rule_bounce(uint32_t              owner_id,
+                                              tpm_src_port_type_t   src_port,
+                                              uint32_t              rule_num,
+                                              uint32_t             *rule_idx,
+                                              tpm_parse_fields_t    parse_rule_bm,
+                                              tpm_parse_flags_t     parse_flags_bm,
+                                              tpm_ipv6_addr_key_t  *ipv6_dip_key,
+                                              tpm_pkt_frwd_t       *pkt_frwd,
+                                              tpm_pkt_mod_t        *pkt_mod,
+                                              tpm_pkt_mod_bm_t      pkt_mod_bm,
+                                              tpm_rule_action_t    *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                             = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                           = MV_TPM_IOCTL_ADD_IPV6_DIP_ACL_RULE;
+    tpm_add_acl_rule->owner_id                              = owner_id;
+    tpm_add_acl_rule->src_port                              = src_port;
+    tpm_add_acl_rule->rule_num                              = rule_num;
+    tpm_add_acl_rule->parse_rule_bm                         = parse_rule_bm;
+    tpm_add_acl_rule->ipv6_dip_acl_rule.parse_flags_bm      = parse_flags_bm;
+    tpm_add_acl_rule->ipv6_dip_acl_rule.pkt_mod_bm          = pkt_mod_bm;
+
+    memcpy(&(tpm_add_acl_rule->ipv6_dip_acl_rule.ipv6_dip_key), ipv6_dip_key,   sizeof(tpm_ipv6_addr_key_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_dip_acl_rule.pkt_frwd),     pkt_frwd,       sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_dip_acl_rule.pkt_mod),      pkt_mod,        sizeof(tpm_pkt_mod_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_dip_acl_rule.rule_action),  rule_action,    sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_dip_rule tpm_add_ipv6_dip_rule_bounce
+#else
+ #define _tpm_add_ipv6_dip_rule tpm_add_ipv6_dip_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_dip_acl_rule_add
+*
+* DESCRIPTION:
+*           This function creates a IPV6 DIP rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_dip_acl_rule_add  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6ruleadd_owner=0, ipv6ruleadd_srcport,   ipv6ruleadd_rulenum,  ipv6ruleadd_parserulebm, ipv6ruleadd_parseflagsbm,
+        ipv6ruleadd_action,  ipv6ruleadd_nextphase, ipv6ruleadd_modbm,    ipv6ruleadd_ipv6dipkeyname, ipv6ruleadd_frwdname,
+        ipv6ruleadd_modname, ipv6dipruleadd_max
+    } ipv6dipruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    char                     srcport_str[20];
+    char                     uc_srcport_str[20];
+    int                      indx;
+    uint32_t                 src_port;
+    unsigned int             rulenum;
+    unsigned int             parserulebm;
+    unsigned int             parseflagsbm;
+    unsigned int             action;
+    unsigned int             nextphase;
+    char                     nextphase_str[20];
+    unsigned int             modbm;
+    char                     ipv6keyname[30];
+    char                     frwdname[20];
+    char                     modname[20];
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    tpmcfg_ipv6_dip_key_entry_t  *pdbipv6keyentry = 0;
+    tpm_ipv6_addr_key_t    ipv6AddrKey;
+    tpmcfg_frwd_entry_t      *pdbfrwdentry    = 0;
+    tpmcfg_mod_entry_t       *pdbmodentry     = 0;
+    // Used in API call
+    tpm_rule_action_t        rule_action;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_pkt_mod_t            pkt_mod;
+    //tpm_ipv6_acl_key_t       ipv6_acl;
+    uint32_t                 rule_idx;
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6dipruleadd_max)
+    {
+        parm_error_completion(numparms, ipv6dipruleadd_max, buf, sys_help_ipv6_dip_acl_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x 0x%x %s 0x%x %s %s %s",
+                            &ownerid, srcport_str, &rulenum, &parserulebm, &parseflagsbm, &action,
+                            nextphase_str, &modbm, ipv6keyname, frwdname, modname);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], parserulebm[0x%x], parseflagsbm[0x%x], action[0x%x], nextphase_str[%s], modbm[0x%x], ipv6keyname[%s], frwdname[%s], modname[%s]\n",
+               len, parsedargs, ownerid, srcport_str, rulenum, parserulebm, parseflagsbm, action, nextphase_str, modbm, ipv6keyname, frwdname, modname);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+        uc_srcport_str[strlen(srcport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_port[%s]\n", srcport_str);
+        }
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        }
+        else if (((pdbipv6keyentry = find_tpm_ipv6_dip_key_entry_by_name(ipv6keyname)) == 0) && strcmp(ipv6keyname, ipv6_dip_key_empty_name) != 0)
+        {
+            printk(KERN_INFO "IPV6 key entry [%s] not found\n", ipv6keyname);
+        }
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && strcmp(frwdname, frwd_empty_name) != 0)
+        {
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        }
+        else if (((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0) && strcmp(modname, mod_empty_name) != 0)
+        {
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        }
+        else
+        {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbipv6keyentry != 0)
+            {
+                memcpy(&(ipv6AddrKey.ipv6_ip_add), &(pdbipv6keyentry->ipv6_addr.ipv6_ip_add), sizeof(pdbipv6keyentry->ipv6_addr.ipv6_ip_add));
+                memcpy(&(ipv6AddrKey.ipv6_ip_add_mask), &(pdbipv6keyentry->ipv6_addr.ipv6_ip_add_mask), sizeof(pdbipv6keyentry->ipv6_addr.ipv6_ip_add_mask));
+            }
+            else                       memset(&ipv6AddrKey, 0,                          sizeof(ipv6AddrKey));
+
+            if (pdbfrwdentry != 0)     memcpy(&pkt_frwd, &pdbfrwdentry->frwd,    sizeof(tpm_pkt_frwd_t));
+            else                       memset(&pkt_frwd, 0,                      sizeof(tpm_pkt_frwd_t));
+
+            if (pdbmodentry != 0)      memcpy(&pkt_mod, &pdbmodentry->mod,      sizeof(tpm_pkt_mod_t));
+            else                       memset(&pkt_mod, 0,                      sizeof(tpm_pkt_mod_t));
+
+            if ((rc = _tpm_add_ipv6_dip_rule(ownerid,
+                                             src_port,
+                                             rulenum,
+                                             &rule_idx,
+                                             parserulebm,
+                                             parseflagsbm,
+                                             &ipv6AddrKey,
+                                             &pkt_frwd,
+                                             &pkt_mod,
+                                             modbm,
+                                             &rule_action)) == TPM_RC_OK)
+                PR_RULE_IDX(rule_idx)
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv6_dip_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv6_dip_rule_bounce(uint32_t              owner_id,
+                                              uint32_t              rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd                   = MV_TPM_IOCTL_DEL_IPV6_DIP_ACL_RULE;
+    tpm_del_acl_rule->owner_id                      = owner_id;
+    tpm_del_acl_rule->rule_idx                      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv6_dip_rule tpm_del_ipv6_dip_rule_bounce
+#else
+ #define _tpm_del_ipv6_dip_rule tpm_del_ipv6_dip_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ipv6_dip
+*
+* DESCRIPTION:
+*           This function deletes a IPV6 HW rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ipv6_dip  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        noruleaddipv6_owner=0,  noruleaddipv6_ruleidx, noruleaddipv6_max
+    } noruleaddipv6_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 rule_idx;
+//    uint32_t                 parserulebm;
+//    char                     keyname[20];
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+//    tpmcfg_ipv6_dip_key_entry_t  *pdbipv6keyentry = 0;
+    //Used in API call
+    //tpm_ipv6_acl_key_t       ipv6_acl;
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noruleaddipv6_max)
+    {
+        parm_error_completion(numparms, noruleaddipv6_max, buf, sfs_help_no_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        // Zeev
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+//        parsedargs = sscanf(buf, "%d %s %d 0x%x %s",
+//                            &ownerid, srcport_str, &rule_idx, &parserulebm, keyname);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rule_idx[%d], parserulebm[0x%x], keyname[%s]\n",
+//               len, parsedargs, ownerid, srcport_str, rule_idx, parserulebm, keyname);
+
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+//        else if ((pdbipv6keyentry = find_tpm_ipv6_dip_key_entry_by_name(keyname)) == 0)
+//        {
+//            printk(KERN_INFO "key entry [%s] not found\n", keyname);
+//        }
+        else
+        {
+            //memcpy(&ipv6_acl, &pdbipv6keyentry->ipv6_acl, sizeof(tpm_ipv6_acl_key_t));
+
+            if ((rc = _tpm_del_ipv6_dip_rule(ownerid,
+                                             rule_idx)) == TPM_RC_OK)
+                PR_RESULT
+            else
+            {
+                printk(KERN_INFO "%s: tpm_del_ipv6_dip_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_l4_ports_rule_bounce(uint32_t                owner_id,
+                                                   tpm_src_port_type_t     src_port,
+                                                   uint32_t                rule_num,
+                                                   uint32_t               *rule_idx,
+                                                   tpm_parse_fields_t      parse_rule_bm,
+                                                   tpm_parse_flags_t       parse_flags_bm,
+                                                   tpm_l4_ports_key_t     *l4_key,
+                                                   tpm_pkt_frwd_t         *pkt_frwd,
+                                                   tpm_pkt_mod_t          *pkt_mod,
+                                                   tpm_pkt_mod_bm_t        pkt_mod_bm,
+                                                   tpm_rule_action_t      *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                             = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                           = MV_TPM_IOCTL_ADD_IPV6_L4_PORTS_ACL_RULE;
+    tpm_add_acl_rule->owner_id                              = owner_id;
+    tpm_add_acl_rule->src_port                              = src_port;
+    tpm_add_acl_rule->rule_num                              = rule_num;
+    tpm_add_acl_rule->parse_rule_bm                         = parse_rule_bm;
+    tpm_add_acl_rule->ipv6_l4_ports_acl_rule.parse_flags_bm = parse_flags_bm;
+    tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_mod_bm     = pkt_mod_bm;
+
+    memcpy(&(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.l4_key),      l4_key,         sizeof(tpm_l4_ports_key_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_frwd),    pkt_frwd,       sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.pkt_mod),     pkt_mod,        sizeof(tpm_pkt_mod_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_l4_ports_acl_rule.rule_action), rule_action,    sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_l4_ports_rule tpm_add_ipv6_l4_ports_rule_bounce
+#else
+ #define _tpm_add_ipv6_l4_ports_rule tpm_add_ipv6_l4_ports_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_l4_ports_acl_rule_add
+*
+* DESCRIPTION:
+*           This function adds a IPV6 HW L4 ports ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_l4_ports_acl_rule_add (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6l4ports_owner=0, ipv6l4ports_srcport,   ipv6l4ports_rulenum,  ipv6l4ports_parserulebm, ipv6l4ports_parseflagsbm,
+        ipv6l4ports_action,   ipv6l4ports_next_phase, ipv6l4ports_src_port, ipv6l4ports_dst_port,    ipv6l4ports_modbm,
+        ipv6l4ports_frwdname, ipv6l4ports_modname,    ipv6l4ports_max
+    } ipv6l4ports_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    char                     srcport_str[20];
+    char                     uc_srcport_str[20];
+    int                      indx;
+    uint32_t                 src_port;
+    unsigned int             rulenum;
+    unsigned int             parserulebm;
+    unsigned int             parseflagsbm;
+
+    uint32_t                 temp_l4_src_port;
+    uint32_t                 temp_l4_dst_port;
+
+    char                     frwdname[20];
+
+    char                     modname[20];
+    unsigned int             modbm;
+
+    unsigned int             action;
+    unsigned int             nextphase;
+    char                     nextphase_str[20];
+
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    tpmcfg_frwd_entry_t      *pdbfrwdentry    = 0;
+    tpmcfg_mod_entry_t       *pdbmodentry     = 0;
+    // Used in API call
+    tpm_l4_ports_key_t       l4_key;
+    tpm_rule_action_t        rule_action;
+    tpm_pkt_frwd_t           pkt_frwd;
+    tpm_pkt_mod_t            pkt_mod;
+    uint32_t                 rule_idx;
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6l4ports_max)
+    {
+        parm_error_completion(numparms, ipv6l4ports_max, buf, sfs_help_ipv6_l4_ports_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x  0x%x %s %d %d  0x%x %s %s",
+                            &ownerid, srcport_str, &rulenum, &parserulebm, &parseflagsbm, &action, nextphase_str,
+                            &temp_l4_src_port, &temp_l4_dst_port, &modbm, frwdname, modname);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], parserulebm[0x%x], parseflagsbm[0x%x], action[0x%x], nextphase_str[%s], l4_src_port[%d], l4_dst_port[%d], modbm[0x%x], frwdname[%s], modname[%s]\n",
+               len, parsedargs, ownerid, srcport_str, rulenum, parserulebm, parseflagsbm, action, nextphase_str, temp_l4_src_port, temp_l4_dst_port, modbm, frwdname, modname);
+
+        // Minimal help for src_port upper/lower case support
+        for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+        uc_srcport_str[strlen(srcport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_port[%s]\n", srcport_str);
+        }
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && strcmp(frwdname, frwd_empty_name) != 0)
+        {
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        }
+        else if (((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0) && strcmp(modname, mod_empty_name) != 0)
+        {
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        }
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        }
+        else
+        {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            l4_key.l4_dst_port = (uint16_t)temp_l4_dst_port;
+            l4_key.l4_src_port = (uint16_t)temp_l4_src_port;
+
+            if (pdbfrwdentry != 0)     memcpy(&pkt_frwd, &pdbfrwdentry->frwd,    sizeof(tpm_pkt_frwd_t));
+            else                       memset(&pkt_frwd, 0,                      sizeof(tpm_pkt_frwd_t));
+
+            if (pdbmodentry != 0)      memcpy(&pkt_mod, &pdbmodentry->mod,      sizeof(tpm_pkt_mod_t));
+            else                       memset(&pkt_mod, 0,                      sizeof(tpm_pkt_mod_t));
+
+            if ((rc = _tpm_add_ipv6_l4_ports_rule(ownerid,
+                                                  src_port,
+                                                  rulenum,
+                                                  &rule_idx,
+                                                  parserulebm,
+                                                  parseflagsbm,
+                                                  &l4_key,
+                                                  &pkt_frwd,
+                                                  &pkt_mod,
+                                                  modbm,
+                                                  &rule_action)) == TPM_RC_OK)
+                PR_RULE_IDX(rule_idx)
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv6_l4_ports_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv6_l4_ports_rule_bounce(uint32_t              owner_id,
+                                                   uint32_t              rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd                   = MV_TPM_IOCTL_DEL_IPV6_L4_PORTS_ACL_RULE;
+    tpm_del_acl_rule->owner_id                      = owner_id;
+    tpm_del_acl_rule->rule_idx                      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv6_l4_ports_rule tpm_del_ipv6_l4_ports_rule_bounce
+#else
+ #define _tpm_del_ipv6_l4_ports_rule tpm_del_ipv6_l4_ports_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_acl
+*
+* DESCRIPTION:
+*           This function deletes a IPV6 HW L4 ports ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_acl (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        noipv6l4ports_owner=0, noipv6l4ports_ruleidx, noipv6l4ports_max
+    } noipv6l4portsruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noipv6l4ports_max)
+    {
+        parm_error_completion(numparms, noipv6l4ports_max, buf, sfs_help_no_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rule_idx[%d]\n",
+               len, parsedargs, ownerid, rule_idx);
+
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_del_ipv6_l4_ports_rule(ownerid,
+                                                  rule_idx)) == TPM_RC_OK)
+                PR_RESULT
+            else
+            {
+                printk(KERN_INFO "%s: tpm_del_ipv6_l4_ports_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_nh_rule_bounce(uint32_t           owner_id,
+                                            uint32_t            rule_num,
+                                            uint32_t           *rule_idx,
+                                            tpm_parse_flags_t   parse_flags_bm,
+                                            tpm_nh_iter_t       nh_iter,
+                                            uint32_t            nh,
+                                            tpm_pkt_frwd_t     *pkt_frwd,
+                                            tpm_rule_action_t  *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                   = MV_TPM_IOCTL_ADD_IPV6_NH_ACL_RULE;
+    tpm_add_acl_rule->owner_id                      = owner_id;
+    tpm_add_acl_rule->rule_num                      = rule_num;
+    tpm_add_acl_rule->parse_rule_bm                 = parse_flags_bm;
+    tpm_add_acl_rule->ipv6_nh_acl_rule.nh_iter      = nh_iter;
+    tpm_add_acl_rule->ipv6_nh_acl_rule.nh           = nh;
+    memcpy(&(tpm_add_acl_rule->ipv6_nh_acl_rule.pkt_frwd),      pkt_frwd,       sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->ipv6_nh_acl_rule.rule_action),   rule_action,    sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_nh_rule tpm_add_ipv6_nh_rule_bounce
+#else
+ #define _tpm_add_ipv6_nh_rule tpm_add_ipv6_nh_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_nh_acl_rule_add
+*
+* DESCRIPTION:
+*           This function adds a IPV6 HW NH (Next Header) ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_nh_acl_rule_add    (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6nh_owner=0,   ipv6nh_rulenum,   ipv6nh_parseflagsbm, ipv6nh_action, ipv6nh_nextphase, ipv6nh_nhiter,
+         ipv6nh_nh,       ipv6nh_frwdname,  ipv6nh_max
+    } ipv6nhruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    unsigned int             rulenum;
+    unsigned int             parseflagsbm;
+    unsigned int             nh_iter;
+    unsigned int             nh;
+    unsigned int             action;
+    unsigned int             nextphase;
+    char                     nextphase_str[20];
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    char                     frwdname[20];
+    tpmcfg_frwd_entry_t      *pdbfrwdentry    = 0;
+    // Used in API call
+    tpm_rule_action_t        rule_action;
+    tpm_pkt_frwd_t           pkt_frwd;
+    uint32_t                 rule_idx;
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6nh_max)
+    {
+        parm_error_completion(numparms, ipv6nh_max, buf, sfs_help_ipv6_nh_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d 0x%x 0x%x %s %d 0x%x %s",
+                            &ownerid, &rulenum, &parseflagsbm, &action, nextphase_str, &nh_iter, &nh, frwdname);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rulenum[%d], parseflagsbm[0x%x], action[0x%x], nextphase_str[%s], nh_iter[%d], nh[0x%x], frwdname[%s]\n",
+               len, parsedargs, ownerid, rulenum, parseflagsbm, action, nextphase_str, nh_iter, nh, frwdname);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && strcmp(frwdname, frwd_empty_name) != 0)
+        {
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        }
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        }
+        else
+        {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbfrwdentry != 0)     memcpy(&pkt_frwd, &pdbfrwdentry->frwd,    sizeof(tpm_pkt_frwd_t));
+            else                       memset(&pkt_frwd, 0,                      sizeof(tpm_pkt_frwd_t));
+
+            if ((rc = _tpm_add_ipv6_nh_rule(ownerid,
+                                            rulenum,
+                                            &rule_idx,
+                                            parseflagsbm,
+                                            nh_iter,
+                                            nh,
+                                            &pkt_frwd,
+                                            &rule_action)) == TPM_RC_OK)
+                PR_RULE_IDX(rule_idx)
+            else
+            {
+                printk(KERN_INFO "%s: tpm_add_ipv6_nh_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv6_nh_rule_bounce(uint32_t           owner_id,
+                                            uint32_t            rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd                   = MV_TPM_IOCTL_DEL_IPV6_NH_ACL_RULE;
+    tpm_del_acl_rule->owner_id                      = owner_id;
+    tpm_del_acl_rule->rule_idx                      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv6_nh_rule tpm_del_ipv6_nh_rule_bounce
+#else
+ #define _tpm_del_ipv6_nh_rule tpm_del_ipv6_nh_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ipv6_nh_acl
+*
+* DESCRIPTION:
+*           This function deletes a IPV6 HW nh_acl rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ipv6_nh_acl    (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        noipv6nh_owner=0, noipv6nh_ruleidx, noipv6nh_max
+    } noipv6nhruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noipv6nh_max)
+    {
+        parm_error_completion(numparms, noipv6nh_max, buf, sfs_help_no_rule_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rule_idx[%d]\n",len, parsedargs, ownerid, rule_idx);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_del_ipv6_nh_rule(ownerid,
+                                            rule_idx)) == TPM_RC_OK)
+                PR_RESULT
+            else
+            {
+                printk(KERN_INFO "%s: tpm_del_ipv6_nh_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ctc_cm_acl_rule_bounce(uint32_t owner_id,
+						tpm_src_port_type_t src_port,
+						uint32_t precedence,
+						tpm_parse_fields_t l2_parse_rule_bm,
+						tpm_parse_fields_t ipv4_parse_rule_bm,
+						tpm_l2_acl_key_t *l2_key,
+						tpm_ipv4_acl_key_t *ipv4_key,
+						tpm_pkt_frwd_t *pkt_frwd,
+						tpm_pkt_action_t *pkt_act,
+						uint32_t pbits)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                          = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                        = MV_TPM_IOCTL_ADD_CTC_CM_ACL_RULE;
+    tpm_add_acl_rule->owner_id                           = owner_id;
+    tpm_add_acl_rule->src_port                           = src_port;
+    tpm_add_acl_rule->ctc_cm_acl_rule.precedence         = precedence;
+    tpm_add_acl_rule->ctc_cm_acl_rule.l2_parse_rule_bm   = l2_parse_rule_bm;
+    tpm_add_acl_rule->ctc_cm_acl_rule.ipv4_parse_rule_bm = ipv4_parse_rule_bm;
+    tpm_add_acl_rule->ctc_cm_acl_rule.p_bits             = pbits;
+
+    memcpy(&(tpm_add_acl_rule->ctc_cm_acl_rule.l2_key),        l2_key,       sizeof(tpm_l2_acl_key_t));
+    memcpy(&(tpm_add_acl_rule->ctc_cm_acl_rule.ipv4_key),      ipv4_key,     sizeof(tpm_ipv4_acl_key_t));
+    memcpy(&(tpm_add_acl_rule->ctc_cm_acl_rule.pkt_frwd),      pkt_frwd,     sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->ctc_cm_acl_rule.pkt_act),       pkt_act,      sizeof(tpm_pkt_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ctc_cm_acl_rule tpm_add_ctc_cm_acl_rule_bounce
+#else
+ #define _tpm_add_ctc_cm_acl_rule tpm_add_ctc_cm_acl_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ctc_cm_rule_add
+*
+* DESCRIPTION:
+*           This function adds a CnM ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ctc_cm_rule_add (const char *buf, size_t len)
+{
+	typedef enum
+	{
+	    cnmruleadd_owner=0, cnmruleadd_srcport, cnmruleadd_precedence, cnmruleadd_l2parserulebm,
+	    cnmruleadd_ipv4parserulebm, cnmruleadd_action, cnmruleadd_l2keyname, cnmruleadd_ipv4keyname,
+	    cnmruleadd_frwdname, cnmruleadd_pbits, cnmruleadd_max
+	} cnmruleadd_parm_indx_t;
+	/*shell line parsing*/
+	uint32_t             	  owner_id;
+	char                      srcport_str[20];
+	char                      uc_srcport_str[20];
+	int                       indx;
+	tpm_src_port_type_t 	  src_port;
+	uint32_t            	  precedence;
+	tpm_parse_fields_t  	  l2_parse_rule_bm;
+	tpm_parse_fields_t  	  ipv4_parse_rule_bm;
+	char                      l2keyname[20];
+	tpm_l2_acl_key_t   	  l2_key;
+	char                      ipv4keyname[20];
+	tpm_ipv4_acl_key_t 	  ipv4_key;
+	char                      frwdname[20];
+	tpm_pkt_frwd_t     	  pkt_frwd;
+	tpm_pkt_action_t 	  action;
+	uint32_t            	  pbits;
+	int                       parsedargs;
+	int                       numparms;
+	/*DB*/
+	tpmcfg_l2_key_entry_t    *pdbl2keyentry   = NULL;
+	tpmcfg_ipv4_key_entry_t  *pdbipv4keyentry = NULL;
+	tpmcfg_frwd_entry_t      *pdbfrwdentry    = NULL;
+
+	tpm_error_code_t         rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != cnmruleadd_max) {
+	    parm_error_completion(numparms, cnmruleadd_max, buf, sfs_help_ctc_cm_rule_add);
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x 0x%x %s %s %s %d",  &owner_id, srcport_str, &precedence,
+			&l2_parse_rule_bm, &ipv4_parse_rule_bm, &action, l2keyname, ipv4keyname, frwdname, &pbits);
+
+		for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+		uc_srcport_str[strlen(srcport_str)] = 0;
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE) {
+			printk(KERN_INFO "Invalid src_port[%s]\n", srcport_str);
+		} else if (((pdbl2keyentry = find_tpm_l2_key_entry_by_name(l2keyname)) == 0) && strcmp(l2keyname, l2_key_empty_name) != 0) {
+			printk(KERN_INFO "L2 key entry [%s] not found\n", l2keyname);
+		} else if (((pdbipv4keyentry = find_tpm_ipv4_key_entry_by_name(ipv4keyname)) == 0) && strcmp(ipv4keyname, ipv4_key_empty_name) != 0) {
+			printk(KERN_INFO "IPV4 key entry [%s] not found\n", ipv4keyname);
+		} else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && strcmp(frwdname, frwd_empty_name)!= 0) {
+			printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+		} else {
+			if (pdbl2keyentry != NULL)
+				memcpy(&l2_key, &(pdbl2keyentry->l2_acl), sizeof(tpm_l2_acl_key_t));
+			else
+				memset(&l2_key, 0, sizeof(tpm_l2_acl_key_t));
+
+			if (pdbipv4keyentry != NULL)
+				memcpy(&ipv4_key, &(pdbipv4keyentry->ipv4_acl), sizeof(tpm_ipv4_acl_key_t));
+			else
+				memset(&ipv4_key, 0, sizeof(tpm_ipv4_acl_key_t));
+
+			if (pdbfrwdentry != NULL)
+				memcpy(&pkt_frwd, &(pdbfrwdentry->frwd), sizeof(tpm_pkt_frwd_t));
+			else
+				memset(&pkt_frwd, 0, sizeof(tpm_pkt_frwd_t));
+
+			if ((rc = _tpm_add_ctc_cm_acl_rule(owner_id,
+						src_port,
+						precedence,
+						l2_parse_rule_bm,
+						ipv4_parse_rule_bm,
+						&l2_key,
+						&ipv4_key,
+						&pkt_frwd,
+						action,
+						pbits)) == TPM_RC_OK)
+				printk(KERN_INFO "OK. precedence = %d\n", precedence);
+			else
+				printk(KERN_INFO "%s: tpm_add_ctc_cm_acl_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+
+		}
+	}
+
+}
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ctc_cm_ipv6_acl_rule_bounce(uint32_t owner_id,
+						     tpm_src_port_type_t src_port,
+						     uint32_t precedence,
+						     tpm_parse_fields_t ipv6_parse_rule_bm,
+						     tpm_ipv4_acl_key_t *ipv6_key,
+						     tpm_pkt_frwd_t *pkt_frwd,
+						     tpm_pkt_action_t *pkt_act,
+						     uint32_t pbits)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                          = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                        = MV_TPM_IOCTL_ADD_CTC_CM_ACL_RULE;
+    tpm_add_acl_rule->owner_id                           = owner_id;
+    tpm_add_acl_rule->src_port                           = src_port;
+    tpm_add_acl_rule->ctc_cm_acl_rule.precedence         = precedence;
+    tpm_add_acl_rule->ctc_cm_acl_rule.ipv6_parse_rule_bm = ipv6_parse_rule_bm;
+    tpm_add_acl_rule->ctc_cm_acl_rule.p_bits             = pbits;
+
+    memcpy(&(tpm_add_acl_rule->ctc_cm_acl_rule.ipv6_key),      ipv6_key,     sizeof(tpm_ipv6_acl_key_t));
+    memcpy(&(tpm_add_acl_rule->ctc_cm_acl_rule.pkt_frwd),      pkt_frwd,     sizeof(tpm_pkt_frwd_t));
+    memcpy(&(tpm_add_acl_rule->ctc_cm_acl_rule.pkt_act),       pkt_act,      sizeof(tpm_pkt_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ctc_cm_ipv6_acl_rule tpm_add_ctc_cm_ipv6_acl_rule_bounce
+#else
+ #define _tpm_add_ctc_cm_ipv6_acl_rule tpm_add_ctc_cm_ipv6_acl_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ctc_cm_ipv6_rule_add
+*
+* DESCRIPTION:
+*           This function adds a CnM IPv6 ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ctc_cm_ipv6_rule_add (const char *buf, size_t len)
+{
+	typedef enum
+	{
+	    cnmruleadd_owner=0, cnmruleadd_srcport, cnmruleadd_precedence,
+	    cnmruleadd_ipv6parserulebm, cnmruleadd_action, cnmruleadd_ipv6keyname,
+	    cnmruleadd_frwdname, cnmruleadd_pbits, cnmruleipv6add_max
+	} cnmruleadd_parm_indx_t;
+	/*shell line parsing*/
+	uint32_t		  owner_id;
+	char			  srcport_str[20];
+	char			  uc_srcport_str[20];
+	int			  indx;
+	tpm_src_port_type_t	  src_port;
+	uint32_t		  precedence;
+	tpm_parse_fields_t	  ipv6_parse_rule_bm;
+	char			  ipv6keyname[20];
+	tpm_ipv6_acl_key_t	  ipv6_key;
+	char			  frwdname[20];
+	tpm_pkt_frwd_t		  pkt_frwd;
+	tpm_pkt_action_t	  action;
+	uint32_t		  pbits;
+	int			  parsedargs;
+	int			  numparms;
+	/*DB*/
+	tpmcfg_ipv6_key_entry_t  *pdbipv6keyentry = NULL;
+	tpmcfg_frwd_entry_t	 *pdbfrwdentry	  = NULL;
+
+	tpm_error_code_t	 rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != cnmruleipv6add_max) {
+	    parm_error_completion(numparms, cnmruleipv6add_max, buf, sfs_help_ctc_cm_rule_add);
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x %s %s %d",  &owner_id, srcport_str, &precedence,
+			&ipv6_parse_rule_bm, &action, ipv6keyname, frwdname, &pbits);
+
+		for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+		uc_srcport_str[strlen(srcport_str)] = 0;
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE) {
+			printk(KERN_INFO "Invalid src_port[%s]\n", srcport_str);
+		} else if (((pdbipv6keyentry = find_tpm_ipv6_key_entry_by_name(ipv6keyname)) == 0) && strcmp(ipv6keyname, ipv6_key_empty_name) != 0) {
+			printk(KERN_INFO "ipv6 key entry [%s] not found\n", ipv6keyname);
+		} else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && strcmp(frwdname, frwd_empty_name)!= 0) {
+			printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+		} else {
+			if (pdbipv6keyentry != NULL)
+				memcpy(&ipv6_key, &(pdbipv6keyentry->ipv6_acl), sizeof(tpm_ipv6_acl_key_t));
+			else
+				memset(&ipv6_key, 0, sizeof(tpm_ipv6_acl_key_t));
+
+			if (pdbfrwdentry != NULL)
+				memcpy(&pkt_frwd, &(pdbfrwdentry->frwd), sizeof(tpm_pkt_frwd_t));
+			else
+				memset(&pkt_frwd, 0, sizeof(tpm_pkt_frwd_t));
+
+			if ((rc = _tpm_add_ctc_cm_ipv6_acl_rule(owner_id,
+						src_port,
+						precedence,
+						ipv6_parse_rule_bm,
+						&ipv6_key,
+						&pkt_frwd,
+						action,
+						pbits)) == TPM_RC_OK)
+				printk(KERN_INFO "OK. precedence = %d\n", precedence);
+			else
+				printk(KERN_INFO "%s: tpm_add_ctc_cm_acl_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+
+		}
+	}
+
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ctc_cm_acl_rule_bounce(uint32_t owner_id,
+						tpm_src_port_type_t src_port,
+						uint32_t precedence)
+{
+	tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+	tpm_sfs_2_ioctl_command.cmd			= MV_TPM_IOCTL_DEL_ACL_SECTION;
+	tpm_del_acl_rule->del_acl_cmd			= MV_TPM_IOCTL_DEL_CTC_CM_ACL_RULE;
+	tpm_del_acl_rule->owner_id			= owner_id;
+	tpm_del_acl_rule->src_port			= src_port;
+	tpm_del_acl_rule->precedence			= precedence;
+
+	up(&tpm_sfs_2_ioctl_sem);
+
+	return TPM_RC_OK;
+
+}
+ #define _tpm_del_ctc_cm_acl_rule tpm_del_ctc_cm_acl_rule_bounce
+#else
+ #define _tpm_del_ctc_cm_acl_rule tpm_del_ctc_cm_acl_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ctc_cm_acl
+*
+* DESCRIPTION:
+*           This function deletes a ctc CnM HW acl rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len     - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ctc_cm_acl(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		noctccm_owner=0, noctccm_srcport, noctccm_precedence, noctccm_max
+	} noctccmruleadd_parm_indx_t;
+	/*shell line parsing*/
+	uint32_t             	  owner_id;
+	char                      srcport_str[20];
+	char                      uc_srcport_str[20];
+	tpm_src_port_type_t 	  src_port;
+	uint32_t            	  precedence;
+	int                       parsedargs;
+	int                       numparms;
+	int                       indx;
+
+	tpm_error_code_t         rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != noctccm_max) {
+	    parm_error_completion(numparms, noctccm_max, buf, sfs_help_no_rule_add);
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d %s %d",  &owner_id, srcport_str, &precedence);
+
+		for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+		uc_srcport_str[strlen(srcport_str)] = 0;
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE) {
+			printk(KERN_INFO "Invalid src_port[%s]\n", srcport_str);
+		} else {
+			if ((rc = _tpm_del_ctc_cm_acl_rule(owner_id,
+							src_port,
+							precedence)) == TPM_RC_OK)
+                		PR_RESULT
+			else
+		                printk(KERN_INFO "%s: tpm_del_ctc_cm_acl_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+		}
+	}
+
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_updt_ipv4_mc_stream_bounce(uint32_t            owner_id,
+                                                uint32_t            stream_num,
+                                                tpm_trg_port_type_t dest_port_bm)
+{
+    tpm_ioctl_mc_rule_t *tpm_mc_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mc_rule;
+
+    tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MC_STREAM_SECTION;
+    tpm_mc_rule->mc_cmd         = MV_TPM_IOCTL_MOD_IPv4_MC_STREAM;
+    tpm_mc_rule->stream_num     = stream_num;
+    tpm_mc_rule->dest_port_bm   = dest_port_bm;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_updt_ipv4_mc_stream tpm_updt_ipv4_mc_stream_bounce
+#else
+ #define _tpm_updt_ipv4_mc_stream tpm_updt_ipv4_mc_stream
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mc_ipv4_stream_update
+*
+* DESCRIPTION:
+*           This function updates a IPv4 multicast stream
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mc_ipv4_stream_update    (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv4strupdt_owner=0, ipv4strupdt_stream_num, ipv4strupdt_dest_port_bm, ipv4strupdt_max
+    } noipv6nhruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 stream_num;
+    uint32_t                 dest_port_bm;
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv4strupdt_max)
+    {
+        parm_error_completion(numparms, ipv4strupdt_max, buf, sfs_help_mc_ipvx_stream_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d 0x%x", &ownerid, &stream_num, &dest_port_bm);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], stream_num[%d], dest_port_bm[0x%x]\n",
+               len, parsedargs, ownerid, stream_num, dest_port_bm);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_updt_ipv4_mc_stream(ownerid,
+                                               stream_num,
+                                               dest_port_bm)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK.\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_updt_ipv4_mc_stream failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_updt_ipv6_mc_stream_bounce(uint32_t            owner_id,
+                                                uint32_t            stream_num,
+                                                tpm_trg_port_type_t dest_port_bm)
+{
+    tpm_ioctl_mc_rule_t *tpm_mc_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_mc_rule;
+
+    tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_MC_STREAM_SECTION;
+    tpm_mc_rule->mc_cmd         = MV_TPM_IOCTL_MOD_IPv6_MC_STREAM;
+    tpm_mc_rule->stream_num     = stream_num;
+    tpm_mc_rule->dest_port_bm   = dest_port_bm;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_updt_ipv6_mc_stream tpm_updt_ipv6_mc_stream_bounce
+#else
+ #define _tpm_updt_ipv6_mc_stream tpm_updt_ipv6_mc_stream
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mc_ipv6_stream_update
+*
+* DESCRIPTION:
+*           This function updates a ipv6 multicast stream
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mc_ipv6_stream_update    (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6strupdt_owner=0, ipv6strupdt_stream_num, ipv6strupdt_dest_port_bm, ipv6strupdt_max
+    } noipv6nhruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 stream_num;
+    uint32_t                 dest_port_bm;
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6strupdt_max)
+    {
+        parm_error_completion(numparms, ipv6strupdt_max, buf, sfs_help_mc_ipvx_stream_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d 0x%x", &ownerid, &stream_num, &dest_port_bm);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], stream_num[%d], dest_port_bm[0x%x]\n",
+               len, parsedargs, ownerid, stream_num, dest_port_bm);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_updt_ipv6_mc_stream(ownerid,
+                                               stream_num,
+                                               dest_port_bm)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK.\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_updt_ipv6_mc_stream failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+void sfs_tpm_cfg_set_mc_vid_key_reset    (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mcvidkeyreset_owner=0,  mcvidkeyreset_max
+    } mcvidkeyreset_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    int                      parsedargs;
+    int                      numparms;
+
+    numparms = count_parameters(buf);
+    if (numparms != mcvidkeyreset_max)
+    {
+        parm_error_completion(numparms, mcvidkeyreset_max, buf, sfs_help_igmp_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d", &ownerid);
+        printk(KERN_INFO "parsedargs=%d. ownerid[%d]\n", parsedargs, ownerid);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            tpm_reset_mc_vid_key ();
+            printk(KERN_INFO "OK.\n");
+        }
+    }
+}
+
+void sfs_tpm_cfg_set_mc_vid_key_set    (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mcvidkeyset_src_port=0, mcvidkeyset_mc_uni_xlate_mode, mcvidkeyset_mc_uni_xlate_vid, mcvidkeyset_max
+    } mcvidkeyset_parm_indx_t;
+    // shell line parsing
+    char                     srcport_str[30];
+    char                     uc_srcport_str[30];
+    uint32_t                 src_port;
+    uint32_t                 mc_uni_xlate_mode;
+    uint32_t                 mc_uni_xlate_vid;
+    int                      parsedargs;
+    int                      numparms;
+    int                      indx;
+
+    numparms = count_parameters(buf);
+    if (numparms != mcvidkeyset_max)
+    {
+        parm_error_completion(numparms, mcvidkeyset_max, buf, sfs_help_igmp_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d %d", srcport_str, &mc_uni_xlate_mode, &mc_uni_xlate_vid);
+        printk(KERN_INFO "len=%d, parsedargs=%d. src_port[%s], mc_uni_xlate_mode[%d], mc_uni_xlate_vid[%d]\n",
+               len, parsedargs, srcport_str, mc_uni_xlate_mode, mc_uni_xlate_vid);
+
+         for (indx = 0; indx < strlen(srcport_str); indx++) uc_srcport_str[indx] = (char)toupper(srcport_str[indx]);
+        uc_srcport_str[strlen(srcport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_srcport_value(uc_srcport_str, &src_port) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid src_port [%s]\n", srcport_str);
+        }
+        else
+        {
+            if ( GT_TRUE == tpm_set_mc_vid_key (src_port,
+                                               mc_uni_xlate_mode,
+                                               mc_uni_xlate_vid) )
+            {
+                printk(KERN_INFO "OK.\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_set_mc_vid_key failed\n", __FUNCTION__);
+            }
+        }
+    }
+}
+void sfs_tpm_cfg_set_mc_vid_cfg_set    (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mcvidcfgset_owner=0, mcvidcfgset_mc_vid, mcvidcfgset_max
+    } mcvidcfgset_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 mc_vid;
+    int                      parsedargs;
+    int                      numparms;
+
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != mcvidcfgset_max)
+    {
+        parm_error_completion(numparms, mcvidcfgset_max, buf, sfs_help_igmp_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &mc_vid);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], mc_vid[%d]\n",
+               len, parsedargs, ownerid, mc_vid);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = tpm_set_mc_vid_cfg (mc_vid)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK.\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_set_mc_vid_cfg failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+void sfs_tpm_cfg_send_genquery_to_uni  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        sendgenquerytouni_target_ports=0, sendgenquerytouni_packet_num, sendgenquerytouni_max
+    } sendgenquerytouni_parm_indx_t;
+    // shell line parsing
+    uint32_t                 packet_num;
+    uint32_t                 target_ports;
+    int                      parsedargs;
+    int                      numparms;
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != sendgenquerytouni_max)
+    {
+        parm_error_completion(numparms, sendgenquerytouni_max, buf, sfs_help_send_genquery_to_uni);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "0x%x %d ", &target_ports, &packet_num);
+        printk(KERN_INFO "len=%d, parsedargs=%d. target_ports[0x%x]. packet_num[%d]\n",
+               len, parsedargs, target_ports, packet_num);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+        	rc = tpm_proc_send_genquery_to_uni(target_ports, packet_num);
+            if (TPM_RC_OK == rc)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_send_genquery_to_uni failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_gen_5t_rule_bounce(uint32_t owner_id,
+										tpm_dir_t src_dir,
+										uint32_t rule_num,
+										uint32_t *rule_idx,
+										tpm_parse_fields_t parse_rule_bm,
+										tpm_parse_flags_t parse_flags_bm,
+										tpm_l4_ports_key_t *l4_key,
+										tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+										tpm_pkt_frwd_t *pkt_frwd,
+										tpm_pkt_mod_t *pkt_mod,
+										tpm_pkt_mod_bm_t pkt_mod_bm,
+										tpm_rule_action_t *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd      = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd    = MV_TPM_IOCTL_ADD_IPV6_GEN_5T_RULE;
+    tpm_add_acl_rule->owner_id       = owner_id;
+    tpm_add_acl_rule->src_dir        = src_dir;
+    tpm_add_acl_rule->rule_num       = rule_num;
+    tpm_add_acl_rule->parse_rule_bm  = parse_rule_bm;
+    tpm_add_acl_rule->ipv6_gen_5t_rule.parse_flags_bm = parse_flags_bm;
+    tpm_add_acl_rule->ipv6_gen_5t_rule.pkt_mod_bm     = pkt_mod_bm;
+
+	memcpy(&tpm_add_acl_rule->ipv6_gen_5t_rule.l4_key, l4_key, sizeof(tpm_l4_ports_key_t));
+	memcpy(&tpm_add_acl_rule->ipv6_gen_5t_rule.ipv6_gen_key, ipv6_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+	memcpy(&tpm_add_acl_rule->ipv6_gen_5t_rule.pkt_frwd, pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	memcpy(&tpm_add_acl_rule->ipv6_gen_5t_rule.pkt_mod, pkt_mod, sizeof(tpm_pkt_mod_t));
+	memcpy(&tpm_add_acl_rule->ipv6_gen_5t_rule.rule_action, rule_action, sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_gen_5t_rule tpm_add_ipv6_gen_5t_rule_bounce
+#else
+ #define _tpm_add_ipv6_gen_5t_rule tpm_add_ipv6_gen_5t_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_gen_rule_add
+*
+* DESCRIPTION:
+*           This function create IPv6 general rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_gen_5t_rule_add(const char *buf, size_t len)
+{
+    typedef enum {
+        ipv6ruleadd_owner=0, ipv6ruleadd_srcdir,    ipv6ruleadd_rulenum,  ipv6ruleadd_parserulebm,   ipv6ruleadd_parseflagsbm,
+        ipv6ruleadd_action,  ipv6ruleadd_nextphase, ipv6ruleadd_modbm,    ipv6ruleadd_ipv6l4keyname, ipv6ruleadd_ipv6genkeyname,
+        ipv6ruleadd_frwdname,ipv6ruleadd_modname,   ipv6ruleadd_max
+    } ipv4ruleadd_parm_indx_t;
+
+    uint32_t            owner_id;
+    tpm_dir_t           src_dir;
+    uint32_t            rule_num;
+    uint32_t            rule_idx;
+    tpm_parse_fields_t  parse_rule_bm;
+    tpm_parse_flags_t   parse_flags_bm;
+    tpm_l4_ports_key_t     l4_key;
+    tpm_ipv6_gen_acl_key_t ipv6_gen_key;
+    tpm_pkt_frwd_t      pkt_frwd;
+    tpm_pkt_mod_t       pkt_mod;
+    tpm_pkt_mod_bm_t    pkt_mod_bm;
+    tpm_rule_action_t   rule_action;
+
+    tpmcfg_ipv6_l4_ports_key_entry_t *pdbipv6l4keyentry  = 0;
+    tpmcfg_ipv6_gen_key_entry_t      *pdbipv6genkeyentry = 0;
+    tpmcfg_frwd_entry_t              *pdbfrwdentry       = 0;
+    tpmcfg_mod_entry_t               *pdbmodentry        = 0;
+
+    tpm_error_code_t    rc;
+    int                 indx;
+    int                 parsedargs;
+    int                 numparms;
+    uint32_t            action;
+    uint32_t            nextphase;
+    char                srcdir_str[20];
+    char                uc_srcdir_str[20];
+    char                nextphase_str[20];
+    char                ipv6l4keyname[30];
+    char                ipv6genkeyname[30];
+    char                frwdname[20];
+    char                modname[20];
+
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6ruleadd_max)
+        parm_error_completion(numparms, ipv6ruleadd_max, buf, sfs_help_ipv6_gen_5t_rule_add);
+    else {
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x 0x%x %s 0x%x %s %s %s %s",
+                            &owner_id, srcdir_str, &rule_num, &parse_rule_bm, &parse_flags_bm,
+                            &action, nextphase_str, &pkt_mod_bm, ipv6l4keyname, ipv6genkeyname, frwdname, modname);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], parserulebm[0x%x], parseflagsbm[0x%x], action[0x%x], nextphase_str[%s], modbm[0x%x], ipv6l4keyname[%s], ipv6genkeyname[%s], frwdname[%s], modname[%s]\n",
+               len, parsedargs, owner_id, srcdir_str, rule_num, parse_rule_bm, parse_flags_bm, action, nextphase_str, pkt_mod_bm, ipv6l4keyname, ipv6genkeyname, frwdname, modname);
+
+        for (indx = 0; indx < strlen(srcdir_str); indx++)
+			uc_srcdir_str[indx] = (char)toupper(srcdir_str[indx]);
+
+        uc_srcdir_str[strlen(srcdir_str)] = 0;
+
+        if (parsedargs != numparms)
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        else if (get_srcdir_value(uc_srcdir_str, &src_dir) == GT_FALSE)
+            printk(KERN_INFO "Invalid src_port[%s]\n", srcdir_str);
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        else if (((pdbipv6l4keyentry = find_tpm_ipv6_l4_ports_key_entry_by_name(ipv6l4keyname)) == 0) && \
+                    strcmp(ipv6l4keyname, ipv6_l4_key_empty_name) != 0)
+            printk(KERN_INFO "L4 ports key entry [%s] not found\n", ipv6genkeyname);
+        else if (((pdbipv6genkeyentry = find_tpm_ipv6_gen_key_entry_by_name(ipv6genkeyname)) == 0) && \
+                    strcmp(ipv6genkeyname, ipv6_gen_key_empty_name) != 0)
+            printk(KERN_INFO "IPV6 gen key entry [%s] not found\n", ipv6genkeyname);
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && \
+                    strcmp(frwdname, frwd_empty_name) != 0)
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        else if (((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0) && \
+                    strcmp(modname, mod_empty_name) != 0)
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        else {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbipv6l4keyentry != 0)
+                memcpy(&l4_key, &pdbipv6l4keyentry->l4_ports, sizeof(tpm_l4_ports_key_t));
+            else
+                memset(&l4_key, 0, sizeof(tpm_l4_ports_key_t));
+
+            if (pdbipv6genkeyentry != 0)
+                memcpy(&ipv6_gen_key, &pdbipv6genkeyentry->ipv6gen_acl, sizeof(tpm_ipv6_gen_acl_key_t));
+            else
+                memset(&ipv6_gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+
+            if (pdbfrwdentry != 0)
+                memcpy(&pkt_frwd, &pdbfrwdentry->frwd, sizeof(tpm_pkt_frwd_t));
+            else
+                memset(&pkt_frwd, 0, sizeof(tpm_pkt_frwd_t));
+
+            if (pdbmodentry != 0)
+                memcpy(&pkt_mod, &pdbmodentry->mod, sizeof(tpm_pkt_mod_t));
+            else
+                memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
+
+            if (TPM_RC_OK == (rc = _tpm_add_ipv6_gen_5t_rule(owner_id,
+                                                            src_dir,
+                                                            rule_num,
+                                                            &rule_idx,
+                                                            parse_rule_bm,
+                                                            parse_flags_bm,
+                                                            &l4_key,
+                                                            &ipv6_gen_key,
+                                                            &pkt_frwd,
+                                                            &pkt_mod,
+                                                            pkt_mod_bm,
+                                                            &rule_action)) )
+                PR_RULE_IDX(rule_idx)
+            else
+                printk(KERN_INFO "%s: tpm_add_ipv6_gen_5t_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv6_gen_5t_rule_bounce(uint32_t        owner_id,
+                                        		 uint32_t        rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd   = MV_TPM_IOCTL_DEL_IPV6_GEN_5T_RULE;
+    tpm_del_acl_rule->owner_id      = owner_id;
+    tpm_del_acl_rule->rule_idx      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv6_gen_5t_rule tpm_del_ipv6_gen_5t_rule_bounce
+#else
+ #define _tpm_del_ipv6_gen_5t_rule tpm_del_ipv6_gen_5t_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ipv6_gen_5t
+*
+* DESCRIPTION:
+*           This function deletes a IPV6 HW gen ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ipv6_gen_5t(const char *buf, size_t len)
+{
+    typedef enum {
+        noipv6gen_owner=0, noipv6gen_ruleidx, noipv6gen_max
+    } noipv6genruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noipv6gen_max)
+        parm_error_completion(numparms, noipv6gen_max, buf, sfs_help_no_rule_add);
+    else {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rule_idx[%d]\n",
+               len, parsedargs, ownerid, rule_idx);
+
+
+        if (parsedargs != numparms)
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        else {
+            if ((rc = _tpm_del_ipv6_gen_5t_rule(ownerid, rule_idx)) == TPM_RC_OK)
+                PR_RESULT
+            else
+                printk(KERN_INFO "%s: tpm_del_ipv6_gen_5t_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_dip_5t_rule_bounce(uint32_t owner_id,
+												tpm_dir_t src_dir,
+												uint32_t rule_num,
+												uint32_t *rule_idx,
+												tpm_parse_fields_t parse_rule_bm,
+												tpm_parse_flags_t parse_flags_bm,
+												tpm_l4_ports_key_t *l4_key,
+												tpm_ipv6_gen_acl_key_t *ipv6_gen_key,
+												tpm_ipv6_addr_key_t *ipv6_dip_key,
+												tpm_pkt_frwd_t *pkt_frwd,
+												tpm_pkt_mod_t *pkt_mod,
+												tpm_pkt_mod_bm_t pkt_mod_bm,
+												tpm_rule_action_t *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd      = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd    = MV_TPM_IOCTL_ADD_IPV6_DIP_5T_RULE;
+    tpm_add_acl_rule->owner_id       = owner_id;
+    tpm_add_acl_rule->src_dir        = src_dir;
+    tpm_add_acl_rule->rule_num       = rule_num;
+    tpm_add_acl_rule->parse_rule_bm  = parse_rule_bm;
+    tpm_add_acl_rule->ipv6_dip_5t_rule.parse_flags_bm = parse_flags_bm;
+    tpm_add_acl_rule->ipv6_dip_5t_rule.pkt_mod_bm     = pkt_mod_bm;
+
+	memcpy(&tpm_add_acl_rule->ipv6_dip_5t_rule.l4_key, l4_key, sizeof(tpm_l4_ports_key_t));
+	memcpy(&tpm_add_acl_rule->ipv6_dip_5t_rule.ipv6_gen_key, ipv6_gen_key, sizeof(tpm_ipv6_gen_acl_key_t));
+	memcpy(&tpm_add_acl_rule->ipv6_dip_5t_rule.ipv6_dip_key, ipv6_dip_key, sizeof(tpm_ipv6_addr_key_t));
+	memcpy(&tpm_add_acl_rule->ipv6_dip_5t_rule.pkt_frwd, pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	memcpy(&tpm_add_acl_rule->ipv6_dip_5t_rule.pkt_mod, pkt_mod, sizeof(tpm_pkt_mod_t));
+	memcpy(&tpm_add_acl_rule->ipv6_dip_5t_rule.rule_action, rule_action, sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_dip_5t_rule tpm_add_ipv6_dip_5t_rule_bounce
+#else
+ #define _tpm_add_ipv6_dip_5t_rule tpm_add_ipv6_dip_5t_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_dip_5t_rule_add
+*
+* DESCRIPTION:
+*           This function create IPv6 general rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_dip_5t_rule_add(const char *buf, size_t len)
+{
+    typedef enum {
+        ipv6ruleadd_owner=0,        ipv6ruleadd_srcdir,    ipv6ruleadd_rulenum,  ipv6ruleadd_parserulebm,   ipv6ruleadd_parseflagsbm,
+        ipv6ruleadd_action,         ipv6ruleadd_nextphase, ipv6ruleadd_modbm,    ipv6ruleadd_ipv6l4keyname, ipv6ruleadd_ipv6genkeyname,
+        ipv6ruleadd_ipv6dipkeyname, ipv6ruleadd_frwdname,ipv6ruleadd_modname,   ipv6ruleadd_max
+    } ipv4ruleadd_parm_indx_t;
+
+    uint32_t            owner_id;
+    tpm_dir_t           src_dir;
+    uint32_t            rule_num;
+    uint32_t            rule_idx;
+    tpm_parse_fields_t  parse_rule_bm;
+    tpm_parse_flags_t   parse_flags_bm;
+    tpm_l4_ports_key_t     l4_key;
+    tpm_ipv6_gen_acl_key_t ipv6_gen_key;
+    tpm_ipv6_addr_key_t    ipv6_dip_key;
+    tpm_pkt_frwd_t      pkt_frwd;
+    tpm_pkt_mod_t       pkt_mod;
+    tpm_pkt_mod_bm_t    pkt_mod_bm;
+    tpm_rule_action_t   rule_action;
+
+    tpmcfg_ipv6_l4_ports_key_entry_t *pdbipv6l4keyentry  = 0;
+    tpmcfg_ipv6_gen_key_entry_t      *pdbipv6genkeyentry = 0;
+    tpmcfg_ipv6_dip_key_entry_t      *pdbipv6dipkeyentry = 0;
+    tpmcfg_frwd_entry_t              *pdbfrwdentry       = 0;
+    tpmcfg_mod_entry_t               *pdbmodentry        = 0;
+
+    tpm_error_code_t    rc;
+    int                 indx;
+    int                 parsedargs;
+    int                 numparms;
+    uint32_t            action;
+    uint32_t            nextphase;
+    char                srcdir_str[20];
+    char                uc_srcdir_str[20];
+    char                nextphase_str[20];
+    char                ipv6l4keyname[30];
+    char                ipv6genkeyname[30];
+    char                ipv6dipkeyname[30];
+    char                frwdname[20];
+    char                modname[20];
+
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6ruleadd_max)
+        parm_error_completion(numparms, ipv6ruleadd_max, buf, sfs_help_ipv6_dip_5t_rule_add);
+    else {
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x 0x%x %s 0x%x %s %s %s %s %s",
+                            &owner_id, srcdir_str, &rule_num, &parse_rule_bm, &parse_flags_bm,
+                            &action, nextphase_str, &pkt_mod_bm, ipv6l4keyname, ipv6genkeyname,
+                            ipv6dipkeyname, frwdname, modname);
+        printk("len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], "\
+			"parserulebm[0x%x], parseflagsbm[0x%x], action[0x%x], nextphase_str[%s], modbm[0x%x], "\
+			"ipv6l4keyname[%s], ipv6genkeyname[%s], ipv6dipkeyname[%s], frwdname[%s], modname[%s]\n",
+            len, parsedargs, owner_id, srcdir_str, rule_num,
+            parse_rule_bm, parse_flags_bm, action, nextphase_str, pkt_mod_bm,
+            ipv6l4keyname, ipv6genkeyname, ipv6dipkeyname, frwdname, modname);
+
+        for (indx = 0; indx < strlen(srcdir_str); indx++)
+			uc_srcdir_str[indx] = (char)toupper(srcdir_str[indx]);
+
+        uc_srcdir_str[strlen(srcdir_str)] = 0;
+
+        if (parsedargs != numparms)
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        else if (get_srcdir_value(uc_srcdir_str, &src_dir) == GT_FALSE)
+            printk(KERN_INFO "Invalid src_port[%s]\n", srcdir_str);
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        else if (((pdbipv6l4keyentry = find_tpm_ipv6_l4_ports_key_entry_by_name(ipv6l4keyname)) == 0) && \
+                    strcmp(ipv6l4keyname, ipv6_l4_key_empty_name) != 0)
+            printk(KERN_INFO "L4 ports key entry [%s] not found\n", ipv6l4keyname);
+        else if (((pdbipv6genkeyentry = find_tpm_ipv6_gen_key_entry_by_name(ipv6genkeyname)) == 0) && \
+                    strcmp(ipv6genkeyname, ipv6_gen_key_empty_name) != 0)
+            printk(KERN_INFO "IPV6 gen key entry [%s] not found\n", ipv6genkeyname);
+        else if (((pdbipv6dipkeyentry = find_tpm_ipv6_dip_key_entry_by_name(ipv6dipkeyname)) == 0) && \
+                    strcmp(ipv6dipkeyname, ipv6_dip_key_empty_name) != 0)
+            printk(KERN_INFO "IPV6 dip key entry [%s] not found\n", ipv6dipkeyname);
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && \
+                    strcmp(frwdname, frwd_empty_name) != 0)
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        else if (((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0) && \
+                    strcmp(modname, mod_empty_name) != 0)
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        else {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbipv6l4keyentry != 0)
+                memcpy(&l4_key, &pdbipv6l4keyentry->l4_ports, sizeof(tpm_l4_ports_key_t));
+            else
+                memset(&l4_key, 0, sizeof(tpm_l4_ports_key_t));
+
+            if (pdbipv6genkeyentry != 0)
+                memcpy(&ipv6_gen_key, &pdbipv6genkeyentry->ipv6gen_acl, sizeof(tpm_ipv6_gen_acl_key_t));
+            else
+                memset(&ipv6_gen_key, 0, sizeof(tpm_ipv6_gen_acl_key_t));
+
+            if (pdbipv6dipkeyentry != 0)
+                memcpy(&ipv6_dip_key, &pdbipv6dipkeyentry->ipv6_addr, sizeof(tpm_ipv6_addr_key_t));
+            else
+                memset(&ipv6_dip_key, 0, sizeof(tpm_ipv6_addr_key_t));
+
+            if (pdbfrwdentry != 0)
+                memcpy(&pkt_frwd, &pdbfrwdentry->frwd, sizeof(tpm_pkt_frwd_t));
+            else
+                memset(&pkt_frwd, 0, sizeof(tpm_pkt_frwd_t));
+
+            if (pdbmodentry != 0)
+                memcpy(&pkt_mod, &pdbmodentry->mod, sizeof(tpm_pkt_mod_t));
+            else
+                memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
+
+            if (TPM_RC_OK == (rc = _tpm_add_ipv6_dip_5t_rule(owner_id,
+                                                            src_dir,
+                                                            rule_num,
+                                                            &rule_idx,
+                                                            parse_rule_bm,
+                                                            parse_flags_bm,
+                                                            &l4_key,
+                                                            &ipv6_gen_key,
+                                                            &ipv6_dip_key,
+                                                            &pkt_frwd,
+                                                            &pkt_mod,
+                                                            pkt_mod_bm,
+                                                            &rule_action)) )
+                PR_RULE_IDX(rule_idx)
+            else
+                printk(KERN_INFO "%s: tpm_add_ipv6_dip_5t_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv6_dip_5t_rule_bounce(uint32_t        owner_id,
+                                        		 uint32_t        rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd   = MV_TPM_IOCTL_DEL_IPV6_DIP_5T_RULE;
+    tpm_del_acl_rule->owner_id      = owner_id;
+    tpm_del_acl_rule->rule_idx      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv6_dip_5t_rule tpm_del_ipv6_dip_5t_rule_bounce
+#else
+ #define _tpm_del_ipv6_dip_5t_rule tpm_del_ipv6_dip_5t_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ipv6_dip_5t
+*
+* DESCRIPTION:
+*           This function deletes a IPV6 HW gen ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ipv6_dip_5t(const char *buf, size_t len)
+{
+    typedef enum {
+        noipv6dip_owner=0, noipv6dip_ruleidx, noipv6dip_max
+    } noipv6dipruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noipv6dip_max)
+        parm_error_completion(numparms, noipv6dip_max, buf, sfs_help_no_rule_add);
+    else {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rule_idx[%d]\n",
+               len, parsedargs, ownerid, rule_idx);
+
+
+        if (parsedargs != numparms)
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        else {
+            if ((rc = _tpm_del_ipv6_dip_5t_rule(ownerid, rule_idx)) == TPM_RC_OK)
+                PR_RESULT
+            else
+                printk(KERN_INFO "%s: tpm_del_ipv6_dip_5t_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_ipv6_l4_ports_5t_rule_bounce(uint32_t owner_id,
+													tpm_dir_t src_dir,
+													uint32_t rule_num,
+													uint32_t *rule_idx,
+													tpm_parse_fields_t parse_rule_bm,
+													tpm_parse_flags_t parse_flags_bm,
+													tpm_l4_ports_key_t *l4_key,
+													tpm_pkt_frwd_t *pkt_frwd,
+													tpm_pkt_mod_t *pkt_mod,
+													tpm_pkt_mod_bm_t pkt_mod_bm,
+													tpm_rule_action_t *rule_action)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd      = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd    = MV_TPM_IOCTL_ADD_IPV6_L4_PORTS_5T_RULE;
+    tpm_add_acl_rule->owner_id       = owner_id;
+    tpm_add_acl_rule->src_dir        = src_dir;
+    tpm_add_acl_rule->rule_num       = rule_num;
+    tpm_add_acl_rule->parse_rule_bm  = parse_rule_bm;
+    tpm_add_acl_rule->ipv6_l4_ports_5t_rule.parse_flags_bm = parse_flags_bm;
+    tpm_add_acl_rule->ipv6_l4_ports_5t_rule.pkt_mod_bm     = pkt_mod_bm;
+
+	memcpy(&tpm_add_acl_rule->ipv6_l4_ports_5t_rule.l4_key, l4_key, sizeof(tpm_l4_ports_key_t));
+	memcpy(&tpm_add_acl_rule->ipv6_l4_ports_5t_rule.pkt_frwd, pkt_frwd, sizeof(tpm_pkt_frwd_t));
+	memcpy(&tpm_add_acl_rule->ipv6_l4_ports_5t_rule.pkt_mod, pkt_mod, sizeof(tpm_pkt_mod_t));
+	memcpy(&tpm_add_acl_rule->ipv6_l4_ports_5t_rule.rule_action, rule_action, sizeof(tpm_rule_action_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_ipv6_l4_ports_5t_rule tpm_add_ipv6_l4_ports_5t_rule_bounce
+#else
+ #define _tpm_add_ipv6_l4_ports_5t_rule tpm_add_ipv6_l4_ports_5t_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_l4_ports_5t_rule_add
+*
+* DESCRIPTION:
+*           This function create IPv6 general rule (PNC)
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_l4_ports_5t_rule_add(const char *buf, size_t len)
+{
+    typedef enum {
+        ipv6ruleadd_owner=0, ipv6ruleadd_srcdir,    ipv6ruleadd_rulenum,  ipv6ruleadd_parserulebm,   ipv6ruleadd_parseflagsbm,
+        ipv6ruleadd_action,  ipv6ruleadd_nextphase, ipv6ruleadd_modbm,    ipv6ruleadd_ipv6l4keyname, ipv6ruleadd_frwdname,
+        ipv6ruleadd_modname, ipv6ruleadd_max
+    } ipv4ruleadd_parm_indx_t;
+
+    uint32_t            owner_id;
+    tpm_dir_t           src_dir;
+    uint32_t            rule_num;
+    uint32_t            rule_idx;
+    tpm_parse_fields_t  parse_rule_bm;
+    tpm_parse_flags_t   parse_flags_bm;
+    tpm_l4_ports_key_t  l4_key;
+    tpm_pkt_frwd_t      pkt_frwd;
+    tpm_pkt_mod_t       pkt_mod;
+    tpm_pkt_mod_bm_t    pkt_mod_bm;
+    tpm_rule_action_t   rule_action;
+
+    tpmcfg_ipv6_l4_ports_key_entry_t *pdbipv6l4keyentry  = 0;
+    tpmcfg_frwd_entry_t              *pdbfrwdentry       = 0;
+    tpmcfg_mod_entry_t               *pdbmodentry        = 0;
+
+    tpm_error_code_t    rc;
+    int                 indx;
+    int                 parsedargs;
+    int                 numparms;
+    uint32_t            action;
+    uint32_t            nextphase;
+    char                srcdir_str[20];
+    char                uc_srcdir_str[20];
+    char                nextphase_str[20];
+    char                ipv6l4keyname[30];
+    char                frwdname[20];
+    char                modname[20];
+
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6ruleadd_max)
+        parm_error_completion(numparms, ipv6ruleadd_max, buf, sfs_help_ipv6_l4_ports_5t_rule_add);
+    else {
+        parsedargs = sscanf(buf, "%d %s %d 0x%x 0x%x 0x%x %s 0x%x %s %s %s",
+                            &owner_id, srcdir_str, &rule_num, &parse_rule_bm, &parse_flags_bm,
+                            &action, nextphase_str, &pkt_mod_bm, ipv6l4keyname, frwdname, modname);
+        printk("len=%d, parsedargs=%d. ownerid[%d], srcport_str[%s], rulenum[%d], "\
+			"parserulebm[0x%x], parseflagsbm[0x%x], action[0x%x], nextphase_str[%s], "\
+			"modbm[0x%x], ipv6l4keyname[%s], frwdname[%s], modname[%s]\n",
+            len, parsedargs, owner_id, srcdir_str, rule_num,
+            parse_rule_bm, parse_flags_bm, action, nextphase_str,
+            pkt_mod_bm, ipv6l4keyname, frwdname, modname);
+
+        for (indx = 0; indx < strlen(srcdir_str); indx++)
+			uc_srcdir_str[indx] = (char)toupper(srcdir_str[indx]);
+
+        uc_srcdir_str[strlen(srcdir_str)] = 0;
+
+        if (parsedargs != numparms)
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        else if (get_srcdir_value(uc_srcdir_str, &src_dir) == GT_FALSE)
+            printk(KERN_INFO "Invalid src_port[%s]\n", srcdir_str);
+        else if (get_phase_value(nextphase_str, &nextphase) == GT_FALSE)
+            printk(KERN_INFO "Invalid next_phase[%s]\n", nextphase_str);
+        else if (((pdbipv6l4keyentry = find_tpm_ipv6_l4_ports_key_entry_by_name(ipv6l4keyname)) == 0) && \
+                    strcmp(ipv6l4keyname, ipv6_l4_key_empty_name) != 0)
+            printk(KERN_INFO "L4 ports key entry [%s] not found\n", ipv6l4keyname);
+        else if (((pdbfrwdentry = find_tpm_pkt_frwd_entry_by_name(frwdname)) == 0) && \
+                    strcmp(frwdname, frwd_empty_name) != 0)
+            printk(KERN_INFO "frwd entry [%s] not found\n", frwdname);
+        else if (((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0) && \
+                    strcmp(modname, mod_empty_name) != 0)
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        else {
+            rule_action.next_phase = nextphase;
+            rule_action.pkt_act    = action;
+
+            if (pdbipv6l4keyentry != 0)
+                memcpy(&l4_key, &pdbipv6l4keyentry->l4_ports, sizeof(tpm_l4_ports_key_t));
+            else
+                memset(&l4_key, 0, sizeof(tpm_l4_ports_key_t));
+
+            if (pdbfrwdentry != 0)
+                memcpy(&pkt_frwd, &pdbfrwdentry->frwd, sizeof(tpm_pkt_frwd_t));
+            else
+                memset(&pkt_frwd, 0, sizeof(tpm_pkt_frwd_t));
+
+            if (pdbmodentry != 0)
+                memcpy(&pkt_mod, &pdbmodentry->mod, sizeof(tpm_pkt_mod_t));
+            else
+                memset(&pkt_mod, 0, sizeof(tpm_pkt_mod_t));
+
+            if (TPM_RC_OK == (rc = _tpm_add_ipv6_l4_ports_5t_rule(owner_id,
+	                                                            src_dir,
+	                                                            rule_num,
+	                                                            &rule_idx,
+	                                                            parse_rule_bm,
+	                                                            parse_flags_bm,
+	                                                            &l4_key,
+	                                                            &pkt_frwd,
+	                                                            &pkt_mod,
+	                                                            pkt_mod_bm,
+	                                                            &rule_action)) )
+                PR_RULE_IDX(rule_idx)
+            else
+                printk(KERN_INFO "%s: tpm_add_ipv6_l4_ports_5t_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_ipv6_l4_ports_5t_rule_bounce(uint32_t        owner_id,
+                                        		      uint32_t        rule_idx)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd   = MV_TPM_IOCTL_DEL_IPV6_DIP_5T_RULE;
+    tpm_del_acl_rule->owner_id      = owner_id;
+    tpm_del_acl_rule->rule_idx      = rule_idx;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_del_ipv6_l4_ports_5t_rule tpm_del_ipv6_l4_ports_5t_rule_bounce
+#else
+ #define _tpm_del_ipv6_l4_ports_5t_rule tpm_del_ipv6_l4_ports_5t_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_5t
+*
+* DESCRIPTION:
+*           This function deletes a IPV6 HW gen ACL rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_5t(const char *buf, size_t len)
+{
+    typedef enum {
+        noipv6l4_owner=0, noipv6l4_ruleidx, noipv6l4_max
+    } noipv6l4ruleadd_parm_indx_t;
+    // shell line parsing
+    unsigned int             ownerid;
+    uint32_t                 rule_idx;
+    int                      parsedargs;
+    int                      numparms;
+    // DB
+    // Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != noipv6l4_max)
+        parm_error_completion(numparms, noipv6l4_max, buf, sfs_help_no_rule_add);
+    else {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &rule_idx);
+        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], rule_idx[%d]\n",
+               len, parsedargs, ownerid, rule_idx);
+
+
+        if (parsedargs != numparms)
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        else {
+            if ((rc = _tpm_del_ipv6_l4_ports_5t_rule(ownerid, rule_idx)) == TPM_RC_OK)
+                PR_RESULT
+            else
+                printk(KERN_INFO "%s: tpm_del_ipv6_l4_ports_5t_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+        }
+    }
+}
+
+/*tpm self check*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_rule_self_check_bounce(uint32_t owner_id,uint32_t level)
+{
+    tpm_ioctl_tpm_check_t *tpm_check_param = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_check_param;
+
+    tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_TPM_CHECK_SECTION;
+    tpm_check_param->owner_id = owner_id;
+    tpm_check_param->check_level = level;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_rule_self_check tpm_rule_self_check_bounce
+#else
+ #define _tpm_rule_self_check tpm_rule_self_check
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_rule_self_check
+*
+* DESCRIPTION:
+*           This function creates does a tpm rule check
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_rule_self_check (const char *buf, size_t len)
+{
+	typedef enum
+	{
+		tpm_self_check_owner=0, tpm_self_check_level, tpm_self_check_max
+	} tpm_check_parm_indx_t;
+	// shell line parsing
+	uint32_t                 ownerid;
+	uint32_t                 level;
+	int                      parsedargs;
+	int                      numparms;
+	//Used in API call
+	tpm_error_code_t         rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != tpm_self_check_max) {
+		parm_error_completion(numparms, tpm_self_check_max, buf, sfs_help_mib_reset);
+	} else {
+		// Get parameters
+		parsedargs = sscanf(buf, "%d %d", &ownerid, &level);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else if (level > TPM_ENUM_MAX_CHECK_LEVEL) {
+			printk(KERN_INFO "Invalid level[%d]\n", level);
+		} else {
+			if ((rc = _tpm_rule_self_check(ownerid, level)) != TPM_RC_OK) {
+				printk(KERN_INFO "%s: tpm_rule_self_check failed, rc[%d] - %s\n",
+				       __FUNCTION__, rc, get_tpm_err_str(rc));
+			}
+		}
+	}
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_flush_vtu_bounce(uint32_t     owner_id)
+{
+    tpm_ioctl_flush_vtu_t *tpm_flush_vtu = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_flush_vtu;
+
+    tpm_sfs_2_ioctl_command.cmd   = MV_TPM_IOCTL_FLUSH_VTU_SECTION;
+    tpm_flush_vtu->owner_id       = owner_id;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_flush_vtu tpm_flush_vtu_bounce
+#else
+ #define _tpm_flush_vtu tpm_flush_vtu
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_flush_vtu
+*
+* DESCRIPTION:
+*           This function flush vtu of the switch
+* INPUTS:
+*       buf - Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_flush_vtu  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        flush_vtu_owner=0,  flush_vtu_max
+    } flush_vtu_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != flush_vtu_max)
+    {
+        parm_error_completion(numparms, flush_vtu_max, buf, sfs_help_flush_vtu);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d", &ownerid);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d]\n", len, parsedargs, ownerid);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else
+        {
+            if ((rc = _tpm_flush_vtu(ownerid)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_flush_vtu failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_flush_atu_bounce(uint32_t owner_id, tpm_flush_atu_type_t flush_type, uint16_t db_num)
+{
+    tpm_ioctl_flush_atu_t *tpm_flush_atu = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_flush_atu;
+
+    tpm_sfs_2_ioctl_command.cmd         = MV_TPM_IOCTL_FLUSH_ATU_SECTION;
+    tpm_flush_atu->owner_id       = owner_id;
+    tpm_flush_atu->flush_type     = flush_type;
+    tpm_flush_atu->db_num         = db_num;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_flush_atu tpm_flush_atu_bounce
+#else
+ #define _tpm_flush_atu tpm_flush_atu
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_flush_atu
+*
+* DESCRIPTION:
+*           This function flush atu of the switch
+* INPUTS:
+*       buf - Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_flush_atu  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        flush_atu_owner=0, flush_atu_type, flush_atu_dbnum, flush_atu_max
+    } flush_atu_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 flush_type;
+    uint32_t                 db_num;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != flush_atu_max)
+    {
+        parm_error_completion(numparms, flush_atu_max, buf, sfs_help_flush_atu);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d %d", &ownerid, &flush_type, &db_num);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], flush_type[%d], db_num[%d]\n",
+//                          len, parsedargs, ownerid, flush_type, db_num);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (flush_type > TPM_FLUSH_ATU_DYNAMIC)
+        {
+            printk(KERN_INFO "Invalid flush_type[%d]\n", flush_type);
+        }
+        else
+        {
+            if ((rc = _tpm_flush_atu(ownerid, flush_type, db_num)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_flush_atu failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_ctc_cm_set_ipv6_parse_win_bounce(uint32_t owner_id, tpm_ctc_cm_ipv6_parse_win_t ipv6_parse_window)
+{
+    tpm_ioctl_ipv6_parse_window_t *ipv6_parse_window = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ipv6_parse_window;
+
+    tpm_sfs_2_ioctl_command.cmd           = MV_TPM_IOCTL_SET_IPV6_CM_PARSE_WIN_SECTION;
+    ipv6_parse_window->owner_id           = owner_id;
+    ipv6_parse_window->ipv6_parse_window  = ipv6_parse_window;
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_ctc_cm_set_ipv6_parse_win tpm_ctc_cm_set_ipv6_parse_win_bounce
+#else
+ #define _tpm_ctc_cm_set_ipv6_parse_win tpm_ctc_cm_set_ipv6_parse_win
+#endif
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_add_mac_learn_rule_bounce(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                   = MV_TPM_IOCTL_ADD_MAC_LEARN_ACL_RULE;
+    tpm_add_acl_rule->owner_id                      = owner_id;
+    memcpy(&(tpm_add_acl_rule->l2_acl_rule.l2_key), (void*)src_mac_addr, sizeof(tpm_l2_acl_key_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_add_mac_learn_rule tpm_add_mac_learn_rule_bounce
+#else
+ #define _tpm_add_mac_learn_rule tpm_add_mac_learn_rule
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_ctc_cm_set_ipv6_parse_win
+*
+* DESCRIPTION:
+*           This function set_ipv6_parse_win
+* INPUTS:
+*       buf - Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_ctc_cm_set_ipv6_parse_win  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ctc_cm_set_ipv6_parse_win_owner=0, ctc_cm_set_ipv6_parse_win, ctc_cm_set_ipv6_parse_win_max
+    } ctc_cm_set_ipv6_parse_win_parm_indx_t;
+    // shell line parsing
+    uint32_t                 ownerid;
+    uint32_t                 ipv6_parse_win;
+    int                      parsedargs;
+    int                      numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != ctc_cm_set_ipv6_parse_win_max)
+    {
+        parm_error_completion(numparms, ctc_cm_set_ipv6_parse_win_max, buf, sfs_help_ctc_cm_set_ipv6_parse_win);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%d %d", &ownerid, &ipv6_parse_win);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. ownerid[%d], ipv6_parse_win[%d]\n",
+//                          len, parsedargs, ownerid, db_num);
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (ipv6_parse_win > TPM_CTC_CM_IPv6_SECOND_24B)
+        {
+            printk(KERN_INFO "Invalid ipv6_parse_win[%d]\n", ipv6_parse_win);
+        }
+        else
+        {
+            if ((rc = _tpm_ctc_cm_set_ipv6_parse_win(ownerid, (tpm_ctc_cm_ipv6_parse_win_t)ipv6_parse_win)) == TPM_RC_OK)
+            {
+                printk(KERN_INFO "OK\n");
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_ctc_cm_set_ipv6_parse_win failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+/*******************************************************************************
+* sfs_tpm_cfg_set_mac_learn_rule_add
+*
+* DESCRIPTION:
+*           This function creates a L2 mac learn rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mac_learn_rule_add(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		mac_learn_add_owner=0, mac_learn_add_l2keyname, mac_learn_add_max
+	} mac_learn_add_parm_indx_t;
+	/* shell line parsing */
+	uint32_t ownerid;
+	char l2keyname[20];
+	int parsedargs;
+	int numparms;
+	/* DB */
+	tpmcfg_l2_key_entry_t *pdbl2keyentry = 0;
+
+	/* Used in API call */
+	tpm_l2_acl_key_t l2_acl;
+	tpm_error_code_t rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != mac_learn_add_max) {
+		parm_error_completion(numparms, mac_learn_add_max, buf, sfs_help_mac_learn_rule_add);
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d %s", &ownerid, l2keyname);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else if (((pdbl2keyentry = find_tpm_l2_key_entry_by_name(l2keyname)) == 0)) {
+			printk(KERN_INFO "L2 MAC addr key entry [%s] not found\n", l2keyname);
+			return;
+		} else {
+			memcpy(&l2_acl, &pdbl2keyentry->l2_acl, sizeof(tpm_l2_acl_key_t));
+			if ((rc = _tpm_add_mac_learn_rule(ownerid, &l2_acl)) == TPM_RC_OK)
+				printk("OK\n");
+			else
+				printk(KERN_INFO "%s: tpm_add_mac_learn_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+		}
+	}
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_del_mac_learn_rule_bounce(uint32_t owner_id, tpm_l2_acl_key_t *src_mac_addr)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd   = MV_TPM_IOCTL_DEL_MAC_LEARN_ACL_RULE;
+    tpm_del_acl_rule->owner_id      = owner_id;
+    memcpy(&(tpm_del_acl_rule->l2_key), (void*)src_mac_addr, sizeof(tpm_l2_acl_key_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+#define _tpm_del_mac_learn_rule tpm_del_mac_learn_rule_bounce
+#else
+#define _tpm_del_mac_learn_rule tpm_del_mac_learn_rule
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_no_rule_add_mac_learn
+*
+* DESCRIPTION:
+*           This function deletes a L2 mac learn rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len     - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_no_rule_add_mac_learn(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		noruleadd_maclearn_owner=0, noruleadd_maclearn_l2keyname, noruleadd_maclearn_max
+	} noruleadd_maclearn_parm_indx_t;
+	/* shell line parsing */
+	uint32_t ownerid;
+	int parsedargs;
+	int numparms;
+	char l2keyname[20];
+	tpmcfg_l2_key_entry_t *pdbl2keyentry = 0;
+	/* Used in API call */
+	tpm_l2_acl_key_t l2_acl;
+	tpm_error_code_t rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != noruleadd_maclearn_max) {
+		parm_error_completion(numparms, noruleadd_maclearn_max, buf, sfs_help_no_rule_add);
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d %s", &ownerid, l2keyname);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else if (((pdbl2keyentry = find_tpm_l2_key_entry_by_name(l2keyname)) == 0)) {
+			printk(KERN_INFO "L2 MAC addr key entry [%s] not found\n", l2keyname);
+			return;
+		} else {
+			memcpy(&l2_acl, &pdbl2keyentry->l2_acl, sizeof(tpm_l2_acl_key_t));
+			if ((rc = _tpm_del_mac_learn_rule(ownerid, &l2_acl)) == TPM_RC_OK)
+				printk(KERN_INFO "OK\n");
+			else
+				printk(KERN_INFO "%s: tpm_del_mac_learn_rule failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+		}
+	}
+}
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_mac_learn_default_rule_act_set_bounce(uint32_t owner_id, tpm_unknown_mac_conf_t mac_conf)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd     = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd   = MV_TPM_IOCTL_SET_MAC_LEARN_DEFAULT_ACTION;
+    tpm_add_acl_rule->owner_id      = owner_id;
+    tpm_add_acl_rule->l2_acl_rule.mac_conf = mac_conf;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+#define _tpm_mac_learn_default_rule_act_set tpm_mac_learn_default_rule_act_set_bounce
+#else
+#define _tpm_mac_learn_default_rule_act_set tpm_mac_learn_default_rule_act_set
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mac_learn_default_rule_action
+*
+* DESCRIPTION:
+*           This function set the action for mac learn default rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len     - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mac_learn_default_rule_action(const char *buf, size_t len)
+{
+	typedef enum
+	{
+		default_rule_action_owner=0, default_rule_action_act, default_rule_action_max
+	} default_rule_action_parm_indx_t;
+	/* shell line parsing */
+	uint32_t ownerid;
+	int parsedargs;
+	int numparms;
+	tpm_unknown_mac_conf_t mac_conf;
+	/* Used in API call */
+	tpm_error_code_t rc;
+
+	numparms = count_parameters(buf);
+	if (numparms != default_rule_action_max) {
+		parm_error_completion(numparms, default_rule_action_max, buf, sfs_help_mac_learn_def_act_set);
+	} else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d %x", &ownerid, &mac_conf);
+
+		if (parsedargs != numparms) {
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		} else {
+			if ((rc = _tpm_mac_learn_default_rule_act_set(ownerid, mac_conf)) == TPM_RC_OK)
+				printk(KERN_INFO "OK\n");
+			else
+				printk(KERN_INFO "%s: tpm_mac_learn_default_rule_act_set failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+		}
+	}
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_fc
+*
+* DESCRIPTION:
+*           This function configures SW flow control
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len     - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_fc(const char *buf, size_t len)
+{
+	typedef enum {
+		fc_thresh_high = 0,
+		fc_thresh_low,
+		fc_port,
+		fc_tgt_port,
+		fc_tx_port,
+		fc_tx_queue,
+		fc_max
+	} fc_parm_indx_t;
+	/* shell line parsing */
+	tpm_fc_cfg_t cfg;
+	int parsedargs;
+	int numparms;
+
+	numparms = count_parameters(buf);
+	if (numparms != fc_max)
+		parm_error_completion(numparms, fc_max, buf, sfs_help_rate_limit);
+	else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d %d %d %d %d %d",
+				    &cfg.thresh_high, &cfg.thresh_low,
+				    &cfg.port, &cfg.tx_port, &cfg.tx_queue, &cfg.tgt_port);
+
+		if (parsedargs != numparms)
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		else {
+			tpm_fc_set_config(&cfg);
+			printk(KERN_INFO "OK\n");
+
+		}
+	}
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_fc_period
+*
+* DESCRIPTION:
+*           This function configures SW flow control engine minitoring period
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len     - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_fc_period(const char *buf, size_t len)
+{
+	typedef enum {
+		fc_period = 0,
+		fc_max
+	} fc_parm_indx_t;
+	/* shell line parsing */
+	uint32_t period;
+	int parsedargs;
+	int numparms;
+	MV_STATUS ret_code;
+
+	numparms = count_parameters(buf);
+	if (numparms != fc_max)
+		parm_error_completion(numparms, fc_max, buf, sfs_help_rate_limit);
+	else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d", &period);
+
+		if (parsedargs != numparms)
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		else {
+			ret_code = tpm_fc_set_period(period);
+			if (ret_code != MV_OK)
+				printk(KERN_INFO "%s: tpm_fc_set_period() failed!\n", __func__);
+			else
+				printk(KERN_INFO "OK\n");
+		}
+	}
+}
+
+#ifdef TPM_FC_DEBUG
+/*******************************************************************************
+* sfs_tpm_cfg_set_fc_oneshot
+*
+* DESCRIPTION:
+*   		This function configures SW flow control engine minitoring
+*   		oneshot count for statistics
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len     - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_fc_oneshot(const char *buf, size_t len)
+{
+	typedef enum {
+		fc_oneshot = 0,
+		fc_max
+	} fc_parm_indx_t;
+	/* shell line parsing */
+	uint32_t oneshot;
+	int parsedargs;
+	int numparms;
+	MV_STATUS ret_code;
+
+	numparms = count_parameters(buf);
+	if (numparms != fc_max)
+		parm_error_completion(numparms, fc_max, buf, sfs_help_rate_limit);
+	else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d", &oneshot);
+
+		if (parsedargs != numparms)
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		else {
+			ret_code = tpm_fc_set_oneshot(oneshot);
+			if (ret_code != MV_OK)
+				printk(KERN_INFO "%s: tpm_fc_set_oneshot() failed!\n", __func__);
+			else
+				printk(KERN_INFO "OK\n");
+		}
+	}
+}
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_fc_enable
+*
+* DESCRIPTION:
+*   		This function configures SW flow control engine minitoring
+*   		oneshot count for statistics
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len     - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_fc_enable(const char *buf, size_t len)
+{
+	typedef enum {
+		_fc_enable = 0,
+		fc_max
+	} fc_parm_indx_t;
+	/* shell line parsing */
+	uint32_t fc_enable;
+	int parsedargs;
+	int numparms;
+	MV_STATUS ret_code;
+
+	numparms = count_parameters(buf);
+	if (numparms != fc_max)
+		parm_error_completion(numparms, fc_max, buf, sfs_help_rate_limit);
+	else {
+		/* Get parameters */
+		parsedargs = sscanf(buf, "%d", &fc_enable);
+
+		if (parsedargs != numparms)
+			printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+		else {
+			ret_code = tpm_fc_enable((fc_enable == 0) ? MV_FALSE : MV_TRUE);
+			if (ret_code != MV_OK)
+				printk(KERN_INFO "%s: tpm_fc_enable() failed!\n", __func__);
+			else
+				printk(KERN_INFO "OK\n");
+		}
+	}
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.h
new file mode 100755
index 0000000..62d755b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_hwcall.h
@@ -0,0 +1,180 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_usr_tpmsysfs_db.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   Zeev
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               $Revision: 1.1.1.1 $
+*
+*
+*******************************************************************************/
+#ifndef _TPM_USR_TPM_SYSFS_HWCALL_H_
+#define _TPM_USR_TPM_SYSFS_HWCALL_H_
+
+extern void sfs_tpm_cfg_set_l2_rule_add                  (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_l3_rule_add                  (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv4_rule_add                (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_gen_rule_add            (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mc_ipv4_stream_add           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mc_ipv4_stream_update        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mc_ipv6_stream_add           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mc_ipv6_stream_update        (const char *buf, size_t len);
+
+extern void sfs_tpm_cfg_set_igmp_port_forward_mode_cfg   (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_igmp_cpu_queue_cfg           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_igmp_proxy_sa_mac            (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_l2               (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_l3               (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ipv4             (const char *buf, size_t len);
+
+extern void sfs_tpm_cfg_set_no_mc_stream_add_ipv6        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_mc_stream_add_ipv4        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_oam_channel                  (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_omci_channel                 (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_oam_channel               (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_omci_channel              (const char *buf, size_t len);
+extern void sfs_tpm_cfg_setup                            (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mib_reset                    (const char *buf, size_t len);
+extern void sfs_tpm_cfg_add_cpu_lpbk                     (const char *buf, size_t len);
+extern void sfs_tpm_cfg_del_cpu_lpbk                     (const char *buf, size_t len);
+extern void sfs_tpm_cfg_dump_cpu_lpbk                    (const char *buf, size_t len);
+extern void sfs_tpm_cfg_get_lu_entry                     (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_count_mask                   (const char *buf, size_t len);
+extern void sfs_tpm_cfg_get_hit_count                    (const char *buf, size_t len);
+extern void sfs_tpm_cfg_get_pnc_all_hit_counters         (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_lu_thresh                    (const char *buf, size_t len);
+extern void sfs_tpm_cfg_reset_age_group                  (const char *buf, size_t len);
+
+extern void sfs_tpm_cfg_set_rate_limit_queue_set         (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_scheduling_mode_queue_set    (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_rate_limit_if_set            (const char *buf, size_t len);
+
+/* jinghuaxxxxxx */
+extern void sfs_tpm_cfg_set_ipv6_dip_key_rule            (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_l4_key_rule             (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_dip_acl_rule_add        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ipv6_dip         (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_l4_ports_acl_rule_add   (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_acl(const char *buf, size_t len);
+/* jinghuaxxxxxx */
+
+extern void sfs_tpm_cfg_set_ipv6_gen_5t_rule_add         (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ipv6_gen_5t      (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_dip_5t_rule_add         (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ipv6_dip_5t      (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_l4_ports_5t_rule_add    (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_5t (const char *buf, size_t len);
+
+// zeev
+extern void sfs_tpm_cfg_set_ipv6_nh_acl_rule_add         (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ipv6_nh_acl      (const char *buf, size_t len);
+
+extern void sfs_tpm_cfg_set_ctc_cm_rule_add              (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_ctc_cm_acl       (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ctc_cm_ipv6_rule_add         (const char *buf, size_t len);
+extern void sfs_tpm_cfg_ctc_cm_set_ipv6_parse_win        (const char *buf, size_t len);
+
+extern void sfs_tpm_cfg_set_no_rule_add_ipv6_gen_acl     (const char *buf, size_t len);
+
+extern void sfs_tpm_cfg_set_mtu_enable                   (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mtu                          (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_pppoe_mtu                    (const char *buf, size_t len);
+
+
+extern void sfs_tpm_cfg_set_mc_vid_key_reset             (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mc_vid_key_set               (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mc_vid_cfg_set               (const char *buf, size_t len);
+extern void sfs_tpm_cfg_send_genquery_to_uni             (const char *buf, size_t len);
+
+extern void sfs_tpm_cfg_set_erase_section                (const char *buf, size_t len);
+extern void sfs_tpm_rule_self_check                      (const char *buf, size_t len);
+extern void sfs_tpm_cfg_flush_atu                        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_flush_vtu                        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mac_learn_rule_add           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_no_rule_add_mac_learn        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mac_learn_default_rule_action(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_gmac0_ingr_rate_limit        (const char *buf, size_t len);
+
+/* KostaP */
+extern void sfs_tpm_cfg_set_fc(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_fc_period(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_fc_oneshot(const char *buf, size_t len);
+extern void sfs_tpm_cfg_fc_enable(const char *buf, size_t len);
+
+extern char *ipv6_gen_key_empty_name;
+extern char *ipv6_dip_key_empty_name;
+extern char *ipv6_l4_key_empty_name;
+
+#endif  /* _TPM_USR_TPM_SYSFS_HWCALL_H_*/
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.c
new file mode 100755
index 0000000..cdb9456
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.c
@@ -0,0 +1,3067 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+        this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <linux/ctype.h>
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_sysfs_utils.h"
+#include "tpm_sysfs_help.h"
+#include "tpm_sysfs_hwcall.h"
+#include "tpm_sysfs_rule_db.h"
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+extern struct semaphore    tpm_sfs_2_ioctl_sem;
+extern tpm_ioctl_mng_t     tpm_sfs_2_ioctl_command;
+ #define PR_RULE_IDX(rule_idx)  {}
+ #define PR_RESULT              {}
+#else
+ #define PR_RULE_IDX(rule_idx)  {printk(KERN_INFO "OK. rule_idx = %d\n", rule_idx);}
+ #define PR_RESULT              {printk(KERN_INFO "OK.\n");}
+#endif
+
+const char *vlan_empty_name = "vlan_empty";
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            TPM SYS FS                                      */
+/* ========================================================================== */
+/********************************************************************************************/
+/* =========================================================================================*/
+/*             TPM CFG FORWARDING FUNCTIONS                                                 */
+/* ======================================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_frwd_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies forwarding rule
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_frwd_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        frpi_name=0, frpi_port, frpi_que, frpi_gem, frpi_max
+    } frwd_rule_parm_indx_t;
+    unsigned int        temp_port;
+    unsigned int        temp_que;
+    unsigned int        temp_gem;
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_frwd_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != frpi_max)
+    {
+        parm_error_completion(numparms, frpi_max, buf, sfs_help_frwd_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s 0x%x %d %d", name, &temp_port, &temp_que,&temp_gem);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_port[0x%x],temp_que[%d],temp_gem[%d]\n",
+//               len, parsedargs, name, temp_port, temp_que, temp_gem);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_que > 255)
+        {
+            printk(KERN_INFO "Invalid queue [%d]\n", temp_que);
+        }
+        else if (temp_gem > 4095)
+        {
+            printk(KERN_INFO "Invalid gem port [%d]\n", temp_gem);
+        }
+        else
+        {
+            if ((pentry = find_tpm_pkt_frwd_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_pkt_frwd_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Packet Forward DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->frwd.trg_port  = (tpm_trg_port_type_t)temp_port;
+                pentry->frwd.trg_queue = (uint8_t)temp_que;
+                pentry->frwd.gem_port  = (uint16_t)temp_gem;
+            }
+        }
+    }
+}
+
+/********************************************************************************************/
+/* =========================================================================================*/
+/*             TPM CFG VLAN FUNCTIONS                                                       */
+/* ======================================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_vlan_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies VLAN rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_vlan_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        vrpi_name=0, vrpi_tpid, vrpi_tpid_mask, vrpi_vid, vrpi_vid_mask, vrpi_cfi, vrpi_cfi_mask, vrpi_pbit,
+		vrpi_pbit_mask, vrpi_max
+    } vlan_rule_parm_indx_t;
+    unsigned int        temp_tpid;
+    unsigned int        temp_tpid_mask;
+    unsigned int        temp_vid;
+    unsigned int        temp_vid_mask;
+    unsigned int        temp_cfi;
+    unsigned int        temp_cfi_mask;
+    unsigned int        temp_pbit;
+    unsigned int        temp_pbit_mask;
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms = 0;
+    tpmcfg_vlan_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != vrpi_max)
+    {
+        parm_error_completion(numparms, vrpi_max, buf, sfs_help_vlan_rule_cfg);
+//        if (numparms == 1 && buf[0] == '?')
+//        {
+//            char helpbuf[3000];
+//            int  helpbuf_len;
+//
+//            helpbuf_len = sfs_help_vlan_rule_cfg(helpbuf);
+//            print_help_buffer(helpbuf, helpbuf_len);
+//        }
+//        else
+//        {
+//            printk(KERN_INFO "Parse problem: expected %d parameters, found %d\n", vrpi_max, numparms);
+//        }
+    }
+    else
+    {
+        parsedargs = sscanf(buf, "%s 0x%x 0x%x %d 0x%x %d 0x%x %d 0x%x", name, &temp_tpid, &temp_tpid_mask, &temp_vid,
+							&temp_vid_mask, &temp_cfi, &temp_cfi_mask, &temp_pbit, &temp_pbit_mask);
+//        printk(KERN_INFO "len=%d. pardeargs=%d. rulename[%s] temp_tpid[0x%x], temp_tpid_mask[0x%x], vid[%d/0x%x], cfi[%d/0x%x],"
+//						"pbit[%d/0x%x]\n", len, parsedargs, name, temp_tpid, temp_vid, temp_vid_mask,
+//               				 temp_cfi, temp_cfi_mask, temp_pbit, temp_pbit_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_tpid > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid TPID [0x%x]\n", temp_tpid);
+        }
+        else if (temp_tpid_mask > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid TPID mask [0x%x]\n", temp_tpid_mask);
+        }
+        else if (temp_vid > 4095)
+        {
+            printk(KERN_INFO "Invalid VID [%d]\n", temp_vid);
+        }
+        else if (temp_vid_mask > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid VID mask [0x%x]\n", temp_vid_mask);
+        }
+        else if (temp_cfi > 1)
+        {
+            printk(KERN_INFO "Invalid CFI [%d]\n", temp_cfi);
+        }
+        else if (temp_cfi_mask > 0xFF)
+        {
+            printk(KERN_INFO "Invalid CFI mask [0x%x]\n", temp_cfi_mask);
+        }
+        else if (temp_pbit > 7)
+        {
+            printk(KERN_INFO "Invalid pbit [%d]\n", temp_pbit);
+        }
+        else if (temp_pbit_mask > 0xFF)
+        {
+            printk(KERN_INFO "Invalid pbit mask [0x%x]\n", temp_pbit_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_vlan_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_vlan_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "VLAN DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->vlan.tpid      = (uint16_t)temp_tpid;
+                pentry->vlan.tpid_mask = (uint16_t)temp_tpid_mask;
+                pentry->vlan.vid       = (uint16_t)temp_vid;
+                pentry->vlan.vid_mask  = (uint16_t)temp_vid_mask;
+                pentry->vlan.cfi       = (uint8_t) temp_cfi;
+                pentry->vlan.cfi_mask  = (uint8_t) temp_cfi_mask;
+                pentry->vlan.pbit      = (uint8_t) temp_pbit;
+                pentry->vlan.pbit_mask = (uint8_t) temp_pbit_mask;
+            }
+        }
+    }
+}
+
+/********************************************************************************************/
+/* =========================================================================================*/
+/*             TPM CFG MOD  FUNCTIONS                                                       */
+/* ======================================================================================== */
+#if 0
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_proto_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies protocol part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_proto_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mprpi_name=0, mprpi_protocol, mprpi_max
+    } mod_proto_rule_parm_indx_t;
+    unsigned int        temp_protocol;
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mprpi_max)
+    {
+        parm_error_completion(numparms, mprpi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d", name, &temp_protocol);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_protocol[0x%x]\n",
+//               len, parsedargs, name, temp_protocol);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_protocol > 255)
+        {
+            printk(KERN_INFO "Invalid protocol [%d]\n", temp_protocol);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_IP_PROTO;
+                pentry->mod.l3.ipv4_mod.ipv4_proto  = (uint8_t)temp_protocol;
+            }
+        }
+    }
+}
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_vlan_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies vlan part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_vlan_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mvrpi_name=0, mvrpi_oper, mvrpi_vlan1, mvrpi_vlan2, mvrpi_max
+    } mod_vlan_rule_parm_indx_t;
+    char                name[100];
+    uint32_t            vlan_op;
+    char                vlan_op_str[30];
+    char                vlan1_name[100];
+    char                vlan2_name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_mod_entry_t  *pentry;
+    tpmcfg_vlan_entry_t *pvlan1entry = 0;
+    tpmcfg_vlan_entry_t *pvlan2entry = 0;
+
+    numparms = count_parameters(buf);
+    if (numparms != mvrpi_max)
+    {
+        parm_error_completion(numparms, mvrpi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %s %s %s", name, vlan_op_str, vlan1_name, vlan2_name);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] vlan_op_str[%s] vlan1_name[%s] vlan2_name[%s]\n",
+//               len, parsedargs, name, vlan_op_str, vlan1_name, vlan2_name);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (get_vlan_op_value(vlan_op_str, &vlan_op) == GT_FALSE)     // TBD-ZG make symbolic
+        {
+            printk(KERN_INFO "Invalid vlan_op[%s]\n", vlan_op_str);
+        }
+        else if (((pvlan1entry = find_tpm_vlan_entry_by_name(vlan1_name)) == 0) && strcmp(vlan1_name, vlan_empty_name) != 0)
+        {
+            printk(KERN_INFO "vlan1 entry [%s] not found\n", vlan1_name);
+        }
+        else if (((pvlan2entry = find_tpm_vlan_entry_by_name(vlan2_name)) == 0) && strcmp(vlan2_name, vlan_empty_name) != 0)
+        {
+            printk(KERN_INFO "vlan2 entry [%s] not found\n", vlan2_name);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_VLAN;
+
+                pentry->mod.vlan_mod.vlan_op = vlan_op;
+
+                if (pvlan1entry != 0)
+                {
+                    memcpy(&pentry->mod.vlan_mod.vlan1_out, &pvlan1entry->vlan, sizeof(pentry->mod.vlan_mod.vlan1_out));
+                }
+                else
+                {
+                    memset(&pentry->mod.vlan_mod.vlan1_out, 0, sizeof(pentry->mod.vlan_mod.vlan1_out));
+                }
+
+                if (pvlan2entry != 0)
+                {
+                    memcpy(&pentry->mod.vlan_mod.vlan2_out, &pvlan2entry->vlan, sizeof(pentry->mod.vlan_mod.vlan2_out));
+                }
+                else
+                {
+                    memset(&pentry->mod.vlan_mod.vlan2_out, 0, sizeof(pentry->mod.vlan_mod.vlan2_out));
+                }
+            }
+        }
+    }
+}
+
+#if 0
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_dscp_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies DSCP part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_dscp_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mdspi_name=0, mdspi_dscp, mdspi_dscpmask, mdspi_max
+    } mod_dscp_rule_parm_indx_t;
+    unsigned int        temp_dscp;
+    unsigned int        temp_dscp_mask;
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mdspi_max)
+    {
+        parm_error_completion(numparms, mdspi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d 0x%x", name, &temp_dscp, &temp_dscp_mask);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_dscp[%d] temp_dscp_mask[0x%x]\n",
+//               len, parsedargs, name, temp_dscp, temp_dscp_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_dscp > 63)
+        {
+            printk(KERN_INFO "Invalid dscp [%d]\n", temp_dscp);
+        }
+        else if (temp_dscp_mask > 0xFF)
+        {
+            printk(KERN_INFO "Invalid dscp mask [0x%x]\n", temp_dscp_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_DSCP;
+                pentry->mod.l3.ipv4_mod.ipv4_dscp      = (uint8_t)temp_dscp;
+                pentry->mod.l3.ipv4_mod.ipv4_dscp_mask = (uint8_t)temp_dscp_mask;
+            }
+        }
+    }
+}
+#endif
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_ipv4_addr_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies IPV4 address part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_ipv4_addr_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mipv4addpi_name=0, mipv4addpi_srcip, mipv4addpi_srcipmask, mipv4addpi_dstip, mipv4addpi_dstipmask, mipv4addpi_max
+    } mod_ipv4add_rule_parm_indx_t;
+    char                temp_srcip[30];
+    char                temp_srcip_mask[30];
+    char                temp_dstip[30];
+    char                temp_dstip_mask[30];
+    uint32_t            srcip[4];
+    uint32_t            srcip_mask[4];
+    uint32_t            dstip[4];
+    uint32_t            dstip_mask[4];
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mipv4addpi_max)
+    {
+        parm_error_completion(numparms, mipv4addpi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %s %s %s %s", name, temp_srcip, temp_srcip_mask, temp_dstip, temp_dstip_mask);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_srcip[%s] temp_srcip_mask[%s] temp_dstip[%s] temp_dstip_mask[%s]\n",
+//               len, parsedargs, name, temp_srcip, temp_srcip_mask, temp_dstip, temp_dstip_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (parse_ipv4_address(temp_srcip, srcip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip [%s]\n", temp_srcip);
+        }
+        else if (parse_ipv4_address(temp_srcip_mask, srcip_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip mask [%s]\n", temp_srcip_mask);
+        }
+        else if (parse_ipv4_address(temp_dstip, dstip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dstip [%s]\n", temp_dstip);
+        }
+        else if (parse_ipv4_address(temp_dstip_mask, dstip_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dstip mask [%s]\n", temp_dstip_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else if (pentry->flags & MOD_ENTRY_FLAG_IPV6)
+            {
+                printk(KERN_INFO "IPV6 already defined for this entry!\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_IPV4;
+                pentry->mod.l3.ipv4_mod.ipv4_src_ip_add[0] = (uint8_t)srcip[0]; pentry->mod.l3.ipv4_mod.ipv4_src_ip_add[1] = (uint8_t)srcip[1];
+                pentry->mod.l3.ipv4_mod.ipv4_src_ip_add[2] = (uint8_t)srcip[2]; pentry->mod.l3.ipv4_mod.ipv4_src_ip_add[3] = (uint8_t)srcip[3];
+                pentry->mod.l3.ipv4_mod.ipv4_src_ip_add_mask[0] = (uint8_t)srcip_mask[0]; pentry->mod.l3.ipv4_mod.ipv4_src_ip_add_mask[1] = (uint8_t)srcip_mask[1];
+                pentry->mod.l3.ipv4_mod.ipv4_src_ip_add_mask[2] = (uint8_t)srcip_mask[2]; pentry->mod.l3.ipv4_mod.ipv4_src_ip_add_mask[3] = (uint8_t)srcip_mask[3];
+                pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add[0] = (uint8_t)dstip[0]; pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add[1] = (uint8_t)dstip[1];
+                pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add[2] = (uint8_t)dstip[2]; pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add[3] = (uint8_t)dstip[3];
+                pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add_mask[0] = (uint8_t)dstip_mask[0]; pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add_mask[1] = (uint8_t)dstip_mask[1];
+                pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add_mask[2] = (uint8_t)dstip_mask[2]; pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add_mask[3] = (uint8_t)dstip_mask[3];
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_ipv4_port_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies IPV4 port part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_ipv4_port_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mipv4portpi_name=0, mipv4portpi_srcport, mipv4portpi_dstport, mipv4portpi_max
+    } mod_ipv4port_rule_parm_indx_t;
+    unsigned int        temp_src_port;
+    unsigned int        temp_dst_port;
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mipv4portpi_max)
+    {
+        parm_error_completion(numparms, mipv4portpi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d %d", name, &temp_src_port, &temp_dst_port);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_src_port[%d] temp_dst_port[%d]\n",
+//               len, parsedargs, name, temp_src_port, temp_dst_port);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_src_port > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid srcport [%d]\n", temp_src_port);
+        }
+        else if (temp_dst_port > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid dstport [%d]\n", temp_dst_port);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else if (pentry->flags & MOD_ENTRY_FLAG_IPV6)
+            {
+                printk(KERN_INFO "IPV6 already defined for this entry!\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_IPV4;
+                pentry->mod.l3.ipv4_mod.l4_src_port = (uint16_t)temp_src_port;
+                pentry->mod.l3.ipv4_mod.l4_dst_port = (uint16_t)temp_dst_port;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_ipv6_addr_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies IPV6 address part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_ipv6_addr_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mipv6addpi_name=0, mipv6addpi_srcip, mipv6addpi_srcipmask, mipv6addpi_dstip, mipv6addpi_dstipmask, mipv6addpi_max
+    } mod_ipv6add_rule_parm_indx_t;
+    char                     temp_srcip[60];
+    char                     temp_srcip_mask[60];
+    char                     temp_dstip[60];
+    char                     temp_dstip_mask[60];
+    uint32_t                 srcip[16];
+    uint32_t                 srcip_mask[16];
+    uint32_t                 dstip[16];
+    uint32_t                 dstip_mask[16];
+    char                     name[100];
+    int                      parsedargs;
+    int                      numparms;
+    int                      indx;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mipv6addpi_max)
+    {
+        parm_error_completion(numparms, mipv6addpi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %s %s %s %s", name, temp_srcip, temp_srcip_mask, temp_dstip, temp_dstip_mask);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_srcip[%s] temp_srcip_mask[%s] temp_dstip[%s] temp_dstip_mask[%s]\n",
+//               len, parsedargs, name, temp_srcip, temp_srcip_mask, temp_dstip, temp_dstip_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (parse_ipv6_address(temp_srcip, srcip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip [%s]\n", temp_srcip);
+        }
+        else if (parse_ipv6_address(temp_srcip_mask, srcip_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip mask [%s]\n", temp_srcip_mask);
+        }
+        else if (parse_ipv6_address(temp_dstip, dstip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dstip [%s]\n", temp_dstip);
+        }
+        else if (parse_ipv6_address(temp_dstip_mask, dstip_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dstip mask [%s]\n", temp_dstip_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else if (pentry->flags & MOD_ENTRY_FLAG_IPV4)
+            {
+                printk(KERN_INFO "IPV4 already defined for this entry!\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_IPV6;
+                for (indx = 0; indx < 16; indx++)
+                {
+                    pentry->mod.l3.ipv6_mod.ipv6_src_ip_add[indx] = (uint8_t)srcip[indx];
+                    pentry->mod.l3.ipv6_mod.ipv6_src_ip_add_mask[indx] = (uint8_t)srcip_mask[indx];
+                    pentry->mod.l3.ipv6_mod.ipv6_dst_ip_add[indx] = (uint8_t)dstip[indx];
+                    pentry->mod.l3.ipv6_mod.ipv6_dst_ip_add_mask[indx] = (uint8_t)dstip_mask[indx];
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_ipv6_port_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies IPV6 port part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_ipv6_port_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mipv6portpi_name=0, mipv6portpi_srcport, mipv6portpi_dstport, mipv6portpi_max
+    } mod_ipv6port_rule_parm_indx_t;
+    unsigned int             temp_src_port;
+    unsigned int             temp_dst_port;
+    char                     name[100];
+    int                      parsedargs;
+    int                      numparms;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mipv6portpi_max)
+    {
+        parm_error_completion(numparms, mipv6portpi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d %d", name, &temp_src_port, &temp_dst_port);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_src_port[%d] temp_dst_port[%d]\n",
+//               len, parsedargs, name, temp_src_port, temp_dst_port);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_src_port > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid srcport [%d]\n", temp_src_port);
+        }
+        else if (temp_dst_port > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid dstport [%d]\n", temp_dst_port);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else if (pentry->flags & MOD_ENTRY_FLAG_IPV4)
+            {
+                printk(KERN_INFO "IPV4 already defined for this entry!\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_IPV6;
+                pentry->mod.l3.ipv6_mod.l4_src_port = (uint16_t)temp_src_port;
+                pentry->mod.l3.ipv6_mod.l4_dst_port = (uint16_t)temp_dst_port;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_mac_addr_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies MAC address part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_mac_addr_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mmacpi_name=0, mmacpi_srcip, mmacpi_srcipmask, mmacpi_dstip, mmacpi_dstipmask, mmacpi_max
+    } mod_mac_rule_parm_indx_t;
+    char                temp_sa[30];
+    char                temp_sa_mask[30];
+    char                temp_da[30];
+    char                temp_da_mask[30];
+    uint32_t            sa[6];
+    uint32_t            sa_mask[6];
+    uint32_t            da[6];
+    uint32_t            da_mask[6];
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mmacpi_max)
+    {
+        parm_error_completion(numparms, mmacpi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %s %s %s %s", name, temp_sa, temp_sa_mask, temp_da, temp_da_mask);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_sa[%s] temp_sa_mask[%s] temp_da[%s] temp_da_mask[%s]\n",
+//               len, parsedargs, name, temp_sa, temp_sa_mask, temp_da, temp_da_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (parse_mac_address(temp_sa, sa) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid SA [%s]\n", temp_sa);
+        }
+        else if (parse_mac_address(temp_sa_mask, sa_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid SA mask [%s]\n", temp_sa_mask);
+        }
+        else if (parse_mac_address(temp_da, da) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid DA [%s]\n", temp_da);
+        }
+        else if (parse_mac_address(temp_da_mask, da_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid DA mask [%s]\n", temp_da_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_MAC;
+                pentry->mod.mac_mod.mac_sa[0] = (uint8_t)sa[0]; pentry->mod.mac_mod.mac_sa[1] = (uint8_t)sa[1]; pentry->mod.mac_mod.mac_sa[2] = (uint8_t)sa[2];
+                pentry->mod.mac_mod.mac_sa[3] = (uint8_t)sa[3]; pentry->mod.mac_mod.mac_sa[4] = (uint8_t)sa[4]; pentry->mod.mac_mod.mac_sa[5] = (uint8_t)sa[5];
+
+                pentry->mod.mac_mod.mac_sa_mask[0] = (uint8_t)sa_mask[0]; pentry->mod.mac_mod.mac_sa_mask[1] = (uint8_t)sa_mask[1]; pentry->mod.mac_mod.mac_sa_mask[2] = (uint8_t)sa_mask[2];
+                pentry->mod.mac_mod.mac_sa_mask[3] = (uint8_t)sa_mask[3]; pentry->mod.mac_mod.mac_sa_mask[4] = (uint8_t)sa_mask[4]; pentry->mod.mac_mod.mac_sa_mask[5] = (uint8_t)sa_mask[5];
+
+                pentry->mod.mac_mod.mac_da[0] = (uint8_t)da[0]; pentry->mod.mac_mod.mac_da[1] = (uint8_t)da[1]; pentry->mod.mac_mod.mac_da[2] = (uint8_t)da[2];
+                pentry->mod.mac_mod.mac_da[3] = (uint8_t)da[3]; pentry->mod.mac_mod.mac_da[4] = (uint8_t)da[4]; pentry->mod.mac_mod.mac_da[5] = (uint8_t)da[5];
+
+                pentry->mod.mac_mod.mac_da_mask[0] = (uint8_t)da_mask[0]; pentry->mod.mac_mod.mac_da_mask[1] = (uint8_t)da_mask[1]; pentry->mod.mac_mod.mac_da_mask[2] = (uint8_t)da_mask[2];
+                pentry->mod.mac_mod.mac_da_mask[3] = (uint8_t)da_mask[3]; pentry->mod.mac_mod.mac_da_mask[4] = (uint8_t)da_mask[4]; pentry->mod.mac_mod.mac_da_mask[5] = (uint8_t)da_mask[5];
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_mh_addr_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies marvell header part of modification rule
+*
+* See sfs_tpm_cfg_set_mod_mh_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_mh_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mmacpi_name=0, mmacpi_mh2b, mmacpi_max
+    } mod_mac_rule_parm_indx_t;
+    uint32_t            mh2b = 0;
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mmacpi_max)
+    {
+        parm_error_completion(numparms, mmacpi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s 0x%2x", name, &mh2b);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] mh2b[0x%x]\n"
+//               len, parsedargs, name, mh2b);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (mh2b == 0)
+        {
+            printk(KERN_INFO "Invalid mh2b [0x%2x]\n", mh2b);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_MH;
+                pentry->mod.mh_mod = mh2b;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_mod_pppoe_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies PPPoE part of modification rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_mod_pppoe_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        mpppoepi_name=0, mpppoepi_session, mpppoepi_prototype, mpppoepi_max
+    } mod_pppoe_rule_parm_indx_t;
+    unsigned int        temp_session;
+    unsigned int        temp_prototype;
+    char                name[100];
+    int                 parsedargs;
+    int                 numparms;
+    tpmcfg_mod_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != mpppoepi_max)
+    {
+        parm_error_completion(numparms, mpppoepi_max, buf, sfs_help_mod_rule_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d 0x%x", name, &temp_session, &temp_prototype);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_session[%d] temp_prototype[0x%x]\n",
+//               len, parsedargs, name, temp_session, temp_prototype);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_session > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid session [%d]\n", temp_session);
+        }
+        else if (temp_prototype > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid protocol type [0x%x]\n", temp_prototype);
+        }
+        else
+        {
+            if ((pentry = find_tpm_mod_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_mod_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "Mod DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->flags |= MOD_ENTRY_FLAG_PPPOE;
+                pentry->mod.pppoe_mod.ppp_session = (uint16_t)temp_session;
+                pentry->mod.pppoe_mod.ppp_proto   = (uint16_t)temp_prototype;
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_mod_entry_set_bounce(tpm_trg_port_type_t   trg_port,
+                                          tpm_pkt_mod_bm_t      mod_bm,
+                                          tpm_pkt_mod_int_bm_t  int_mod_bm,
+                                          tpm_pkt_mod_t        *mod_data,
+                                          uint32_t             *mod_entry)
+{
+    tpm_ioctl_add_acl_rule_t *tpm_add_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_add_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_ADD_ACL_SECTION;
+    tpm_add_acl_rule->add_acl_cmd                   = MV_TPM_IOCTL_SET_MOD_RULE;
+    tpm_add_acl_rule->mod_rule.trg_port             = trg_port;
+    tpm_add_acl_rule->mod_rule.mod_bm               = mod_bm;
+    tpm_add_acl_rule->mod_rule.int_bm               = int_mod_bm;
+    memcpy(&(tpm_add_acl_rule->mod_rule.mod_data), (void*)mod_data, sizeof(tpm_pkt_mod_t));
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_mod_entry_set tpm_mod_entry_set_bounce
+#else
+ #define _tpm_mod_entry_set tpm_mod_entry_set
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_pkt_mod_eng_entry_add
+*
+* DESCRIPTION:
+*           This function adds packet modification to specified port
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_pkt_mod_eng_entry_add      (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        pktmodadd_trgport=0, pktmodadd_modbm, pktmodadd_int_modbm, pktmodadd_modname, pktmodadd_max
+    } pktmodadd_parm_indx_t;
+    // shell line parsing
+    char                trgport_str[20];
+    char                uc_trgport_str[20];
+    int                 indx;
+    uint32_t            trgport;
+    uint32_t            mod_bm;
+    uint32_t            int_mod_bm;
+    char                modname[20];
+    tpm_pkt_mod_t       mod_data;
+    uint32_t            mod_entry = 0;
+    int                 parsedargs;
+    int                 numparms;
+    // DB
+    tpmcfg_mod_entry_t  *pdbmodentry = 0;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != pktmodadd_max)
+    {
+        parm_error_completion(numparms, pktmodadd_max, buf, sfs_help_pkt_mod_add);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s 0x%x 0x%x %s", trgport_str, &mod_bm, &int_mod_bm, modname);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. trgport_str[%s], mod_bm[0x%x], flag[0x%x], modname[%s]\n",
+//               len, parsedargs, trgport_str, mod_bm, int_mod_bm, modname);
+
+        // Minimal help for trgport upper/lower case support
+        for (indx = 0; indx < strlen(trgport_str); indx++) uc_trgport_str[indx] = (char)toupper(trgport_str[indx]);
+        uc_trgport_str[strlen(trgport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_sched_entity_value(uc_trgport_str, &trgport) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid trg_port[%s]\n", trgport_str);
+        }
+        else if ((pdbmodentry = find_tpm_mod_entry_by_name(modname)) == 0)
+        {
+            printk(KERN_INFO "mod entry [%s] not found\n", modname);
+        }
+        else
+        {
+            memcpy(&mod_data, &pdbmodentry->mod, sizeof(mod_data));
+
+            if ((rc = _tpm_mod_entry_set(trgport,
+                                         mod_bm,
+                                         int_mod_bm,
+                                         &mod_data,
+                                         &mod_entry)) == TPM_RC_OK)
+            {
+                PR_RULE_IDX(mod_entry)
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_mod_entry_set failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+static char* opCodeOperationStr[30] =
+{
+    "NOOP",
+    "ADD",
+    "CONF_VLAN",
+    "ADD_VLAN",
+    "CONF_DSA1",
+    "CONF_DSA2",
+    "ADD_DSA",
+    "DEL",
+    "REP2",
+    "REP_LSB",
+    "REP_MSB",
+    "REP_VLAN",
+    "DEC_TTL_LSB",
+    "DEC_TTL_MSB",
+    "ADD_CALC_LEN",
+    "REP_LEN",
+    "REP_IP_CHKSUM",
+    "REP_L4_CHKSUM",
+    "SKIP",
+    "JUMP",
+    "JUMP_SKIP2",
+    "JUMP_SUBR",
+    "PPPOE",
+    "STORE",
+    "ADD_IP_CHKSUM",
+    "RESERVED",
+    "RESERVED",
+    "RESERVED",
+    "RESERVED",
+    "RESERVED"
+};
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_mod_entry_get_bounce(tpm_trg_port_type_t trg_port,
+					uint32_t mod_entry,
+					uint16_t *valid_cmds,
+					uint16_t *pnc_ref,
+					tpm_mod_rule_t *rule)
+{
+	tpm_ioctl_get_mod_rule_t *tpm_get_mod_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_get_mod;
+
+	tpm_sfs_2_ioctl_command.cmd   = MV_TPM_IOCTL_GET_MOD_SECTION;
+	tpm_get_mod_rule->get_mod_cmd = MV_TPM_IOCTL_GET_MOD_RULE;
+	tpm_get_mod_rule->trg_port    = trg_port;
+	tpm_get_mod_rule->rule_idx    = mod_entry;
+	//tpm_get_mod_rule->valid_num   = *valid_cmds;
+	//tpm_get_mod_rule->pnc_ref     = *pnc_ref;
+	up(&tpm_sfs_2_ioctl_sem);
+	//pnc_ref = &tpm_get_mod_rule->pnc_ref;//     = pnc_ref;
+	//rule = tpm_get_mod_rule->rule;// = rule;
+	//up(&tpm_sfs_2_ioctl_sem);
+	return TPM_RC_OK;
+}
+ #define _tpm_mod_entry_get tpm_mod_entry_get_bounce
+#else
+ #define _tpm_mod_entry_get tpm_mod_entry_get
+#endif
+/*******************************************************************************
+* sfs_tpm_cfg_set_pkt_mod_eng_entry_show
+*
+* DESCRIPTION:
+*           This function displays specific packet modification
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_pkt_mod_eng_entry_show     (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        pktmodshow_trgport=0, pktmodshow_modentry, pktmodshow_max
+    } pktmoddel_parm_indx_t;
+    // shell line parsing
+    char                trgport_str[20];
+    char                uc_trgport_str[20];
+    int                 indx;
+    uint32_t            trgport;
+    uint32_t            mod_entry;
+    uint16_t            valid_cmds;
+    uint16_t            pnc_ref;
+    tpm_mod_rule_t      rule[TPM_MAX_MOD_RULE_NUM];
+    int                 parsedargs;
+    int                 numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != pktmodshow_max)
+    {
+        parm_error_completion(numparms, pktmodshow_max, buf, sfs_help_pkt_mod_get_del_purge);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d", trgport_str, &mod_entry);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. trgport_str[%s], mod_entry[%d]\n", len, parsedargs, trgport_str, mod_entry);
+
+        // Minimal help for trgport upper/lower case support
+        for (indx = 0; indx < strlen(trgport_str); indx++) uc_trgport_str[indx] = (char)toupper(trgport_str[indx]);
+        uc_trgport_str[strlen(trgport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_sched_entity_value(uc_trgport_str, &trgport) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid trg_port[%s]\n", trgport_str);
+        }
+        else
+        {
+            if ((rc = _tpm_mod_entry_get(trgport,
+                                         mod_entry,
+                                         &valid_cmds,
+                                         &pnc_ref,
+                                         rule)) == TPM_RC_OK)
+            {
+#ifndef CONFIG_MV_TPM_SFS_2_IOCTL
+                uint16_t         rule_idx;
+
+                printk("==========================================================\n");
+                printk(" Index  OpCode    Operation      Data  Last  IPv4    L4   \n");
+                printk("                                            update update \n");
+                printk("==========================================================\n");
+
+                for (rule_idx = 0; rule_idx < valid_cmds; rule_idx++)
+                {
+                    printk(" %03d      0x%2x  %15s  0x%4.4x  %1d     %1d      %1d\n",
+                           rule[rule_idx].entry_id, rule[rule_idx].entry_data.opcode,
+                           opCodeOperationStr[rule[rule_idx].entry_data.opcode],
+                           rule[rule_idx].entry_data.data, rule[rule_idx].entry_data.last,
+                           rule[rule_idx].entry_data.updt_ipv4, rule[rule_idx].entry_data.updt_tcp);
+                }
+#endif
+            }
+            else
+            {
+                printk(KERN_INFO "%s: tpm_mod_entry_get failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_mod_entry_del_bounce(tpm_trg_port_type_t  trg_port,
+                                          uint32_t             mod_entry)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd                   = MV_TPM_IOCTL_DEL_MOD_RULE;
+    tpm_del_acl_rule->trg_port                      = trg_port;
+    tpm_del_acl_rule->rule_idx                      = mod_entry;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_mod_entry_del tpm_mod_entry_del_bounce
+#else
+ #define _tpm_mod_entry_del tpm_mod_entry_del
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_pkt_mod_eng_entry_del
+*
+* DESCRIPTION:
+*           This function deletes single packet modification from supplied port
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_pkt_mod_eng_entry_del      (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        pktmoddel_trgport=0, pktmoddel_modentry, pktmoddel_max
+    } pktmoddel_parm_indx_t;
+    // shell line parsing
+    char                trgport_str[20];
+    char                uc_trgport_str[20];
+    int                 indx;
+    uint32_t            trgport;
+    uint32_t            mod_entry;
+    int                 parsedargs;
+    int                 numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms != pktmoddel_max)
+    {
+        parm_error_completion(numparms, pktmoddel_max, buf, sfs_help_pkt_mod_get_del_purge);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d", trgport_str, &mod_entry);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. trgport_str[%s], mod_entry[%d]\n", len, parsedargs, trgport_str, mod_entry);
+
+        // Minimal help for trgport upper/lower case support
+        for (indx = 0; indx < strlen(trgport_str); indx++) uc_trgport_str[indx] = (char)toupper(trgport_str[indx]);
+        uc_trgport_str[strlen(trgport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_sched_entity_value(uc_trgport_str, &trgport) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid trg_port[%s]\n", trgport_str);
+        }
+        else
+        {
+            if ((rc = _tpm_mod_entry_del(trgport,
+                                         mod_entry)) == TPM_RC_OK)
+                PR_RESULT
+            else
+            {
+                printk(KERN_INFO "%s: tpm_mod_entry_del failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+tpm_error_code_t tpm_mod_mac_inv_bounce(tpm_trg_port_type_t  trg_port)
+{
+    tpm_ioctl_del_acl_rule_t *tpm_del_acl_rule = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_del_acl_rule;
+
+    tpm_sfs_2_ioctl_command.cmd                     = MV_TPM_IOCTL_DEL_ACL_SECTION;
+    tpm_del_acl_rule->del_acl_cmd                   = MV_TPM_IOCTL_INV_MOD_RULES;
+    tpm_del_acl_rule->trg_port                      = trg_port;
+
+    up(&tpm_sfs_2_ioctl_sem);
+
+    return TPM_RC_OK;
+}
+ #define _tpm_mod_mac_inv tpm_mod_mac_inv_bounce
+#else
+ #define _tpm_mod_mac_inv tpm_mod_mac_inv
+#endif
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_pkt_mod_eng_purge
+*
+* DESCRIPTION:
+*           This function removes all packet modification from supplied port
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_pkt_mod_eng_purge          (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        pktmodadd_trgport, pktmodpurge_max
+    } pktmodpurge_parm_indx_t;
+    // shell line parsing
+    char                trgport_str[20];
+    char                uc_trgport_str[20];
+    int                 indx;
+    uint32_t            trgport;
+    int                 parsedargs;
+    int                 numparms;
+    //Used in API call
+    tpm_error_code_t         rc;
+
+    numparms = count_parameters(buf);
+    if (numparms == 1 && buf[0] == '?')
+    {
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+        char helpbuf[1000];
+        int  helpbuf_len;
+
+        helpbuf_len = sfs_help_pkt_mod_get_del_purge(helpbuf);
+        print_help_buffer(helpbuf, helpbuf_len);
+#else
+	printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", pktmodpurge_max, numparms);
+#endif
+    }
+    else if (numparms != 1)
+    {
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", pktmodpurge_max, numparms);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s", trgport_str);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. trgport_str[%s]\n", len, parsedargs, trgport_str);
+
+        // Minimal help for trgport upper/lower case support
+        for (indx = 0; indx < strlen(trgport_str); indx++) uc_trgport_str[indx] = (char)toupper(trgport_str[indx]);
+        uc_trgport_str[strlen(trgport_str)] = 0;
+
+        if (parsedargs != numparms)
+        {
+            printk(KERN_INFO "Parse failure - %d/%d parameters were parsed\n", parsedargs, numparms);
+        }
+        else if (get_sched_entity_value(uc_trgport_str, &trgport) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid trg_port[%s]\n", trgport_str);
+        }
+        else
+        {
+            if ((rc = _tpm_mod_mac_inv(trgport)) == TPM_RC_OK)
+                PR_RESULT
+            else
+            {
+                printk(KERN_INFO "%s: tpm_mod_mac_inv failed, rc[%d] - %s\n", __FUNCTION__, rc, get_tpm_err_str(rc));
+            }
+        }
+    }
+}
+
+/********************************************************************************************/
+/* =========================================================================================*/
+/*             TPM CFG L2 KEY FUNCTIONS                                                   */
+/* ======================================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l2_key_ethertype_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies ethertype part part of L2 ACL key
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l2_key_ethertype_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l2etypi_name=0, l2etypi_ety, l2etypi_max
+    } l2_ety_rule_parm_indx_t;
+    unsigned int          temp_ety;
+    char                  name[100];
+    int                   parsedargs;
+    int                   numparms;
+    tpmcfg_l2_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != l2etypi_max)
+    {
+        parm_error_completion(numparms, l2etypi_max, buf, sfs_help_l2_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s 0x%x", name, &temp_ety);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_ety[0x%x]\n",
+//               len, parsedargs, name, temp_ety);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_ety > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid ethertype [0x%x]\n", temp_ety);
+        }
+        else
+        {
+            if ((pentry = find_tpm_l2_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_l2_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "L2 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->l2_acl.ether_type  = (uint16_t)temp_ety;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l2_key_gemport_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies gemport part part of L2 ACL key
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l2_key_gemport_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l2gempi_name=0, l2gempi_ety, l2gempi_max
+    } l2_gemport_rule_parm_indx_t;
+    unsigned int          temp_gemport;
+    char                  name[100];
+    int                   parsedargs;
+    int                   numparms;
+    tpmcfg_l2_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != l2gempi_max)
+    {
+        parm_error_completion(numparms, l2gempi_max, buf, sfs_help_l2_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d", name, &temp_gemport);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_gemport[%d]\n",
+//               len, parsedargs, name, temp_gemport);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_gemport > 4095)
+        {
+            printk(KERN_INFO "Invalid gemport [%d]\n", temp_gemport);
+        }
+        else
+        {
+            if ((pentry = find_tpm_l2_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_l2_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "L2 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->l2_acl.gem_port  = (uint16_t)temp_gemport;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l2_key_mac_addr_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies MAC address part of L2 ACL key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l2_key_mac_addr_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l2macpi_name=0, l2macpi_srcip, l2macpi_srcipmask, l2macpi_dstip, l2macpi_dstipmask, l2macpi_max
+    } l2_mac_rule_parm_indx_t;
+    char                  temp_sa[30];
+    char                  temp_sa_mask[30];
+    char                  temp_da[30];
+    char                  temp_da_mask[30];
+    uint32_t              sa[6];
+    uint32_t              sa_mask[6];
+    uint32_t              da[6];
+    uint32_t              da_mask[6];
+    char                  name[100];
+    int                   parsedargs;
+    int                   numparms;
+    tpmcfg_l2_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != l2macpi_max)
+    {
+        parm_error_completion(numparms, l2macpi_max, buf, sfs_help_l2_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %s %s %s %s", name, temp_sa, temp_sa_mask, temp_da, temp_da_mask);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_sa[%s] temp_sa_mask[%s] temp_da[%s] temp_da_mask[%s]\n",
+//               len, parsedargs, name, temp_sa, temp_sa_mask, temp_da, temp_da_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (parse_mac_address(temp_sa, sa) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid SA [%s]\n", temp_sa);
+        }
+        else if (parse_mac_address(temp_sa_mask, sa_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid SA mask [%s]\n", temp_sa_mask);
+        }
+        else if (parse_mac_address(temp_da, da) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid DA [%s]\n", temp_da);
+        }
+        else if (parse_mac_address(temp_da_mask, da_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid DA mask [%s]\n", temp_da_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_l2_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_l2_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "L2 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->l2_acl.mac.mac_sa[0] = (uint8_t)sa[0]; pentry->l2_acl.mac.mac_sa[1] = (uint8_t)sa[1]; pentry->l2_acl.mac.mac_sa[2] = (uint8_t)sa[2];
+                pentry->l2_acl.mac.mac_sa[3] = (uint8_t)sa[3]; pentry->l2_acl.mac.mac_sa[4] = (uint8_t)sa[4]; pentry->l2_acl.mac.mac_sa[5] = (uint8_t)sa[5];
+
+                pentry->l2_acl.mac.mac_sa_mask[0] = (uint8_t)sa_mask[0]; pentry->l2_acl.mac.mac_sa_mask[1] = (uint8_t)sa_mask[1]; pentry->l2_acl.mac.mac_sa_mask[2] = (uint8_t)sa_mask[2];
+                pentry->l2_acl.mac.mac_sa_mask[3] = (uint8_t)sa_mask[3]; pentry->l2_acl.mac.mac_sa_mask[4] = (uint8_t)sa_mask[4]; pentry->l2_acl.mac.mac_sa_mask[5] = (uint8_t)sa_mask[5];
+
+                pentry->l2_acl.mac.mac_da[0] = (uint8_t)da[0]; pentry->l2_acl.mac.mac_da[1] = (uint8_t)da[1]; pentry->l2_acl.mac.mac_da[2] = (uint8_t)da[2];
+                pentry->l2_acl.mac.mac_da[3] = (uint8_t)da[3]; pentry->l2_acl.mac.mac_da[4] = (uint8_t)da[4]; pentry->l2_acl.mac.mac_da[5] = (uint8_t)da[5];
+
+                pentry->l2_acl.mac.mac_da_mask[0] = (uint8_t)da_mask[0]; pentry->l2_acl.mac.mac_da_mask[1] = (uint8_t)da_mask[1]; pentry->l2_acl.mac.mac_da_mask[2] = (uint8_t)da_mask[2];
+                pentry->l2_acl.mac.mac_da_mask[3] = (uint8_t)da_mask[3]; pentry->l2_acl.mac.mac_da_mask[4] = (uint8_t)da_mask[4]; pentry->l2_acl.mac.mac_da_mask[5] = (uint8_t)da_mask[5];
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l2_key_pppoe_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies PPPoE part of L2 ACL key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l2_key_pppoe_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l2pppoepi_name=0, l2pppoepi_session, l2pppoepi_prototype, l2pppoepi_max
+    } l2_pppoe_rule_parm_indx_t;
+    unsigned int          temp_session;
+    unsigned int          temp_prototype;
+    char                  name[100];
+    int                   parsedargs;
+    int                   numparms;
+    tpmcfg_l2_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != l2pppoepi_max)
+    {
+        parm_error_completion(numparms, l2pppoepi_max, buf, sfs_help_l2_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d 0x%x", name, &temp_session, &temp_prototype);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_session[%d] temp_prototype[0x%x]\n",
+//               len, parsedargs, name, temp_session, temp_prototype);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_session > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid session [%d]\n", temp_session);
+        }
+        else if (temp_prototype > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid protocol type [0x%x]\n", temp_prototype);
+        }
+        else
+        {
+            if ((pentry = find_tpm_l2_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_l2_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "L2 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->l2_acl.pppoe_hdr.ppp_session = (uint16_t)temp_session;
+                pentry->l2_acl.pppoe_hdr.ppp_proto   = (uint16_t)temp_prototype;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l2_key_vlan_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies vlan part of L2 ACL key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l2_key_vlan_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l2vrpi_name=0, l2vrpi_vlan1, l2vrpi_vlan2, l2vrpi_max
+    } l2_vlan_rule_parm_indx_t;
+    char                  name[100];
+    char                  vlan1_name[100];
+    char                  vlan2_name[100];
+    int                   parsedargs;
+    int                   numparms;
+    tpmcfg_l2_key_entry_t *pentry;
+    tpmcfg_vlan_entry_t   *pvlan1entry = 0;
+    tpmcfg_vlan_entry_t   *pvlan2entry = 0;
+
+    numparms = count_parameters(buf);
+    if (numparms != l2vrpi_max)
+    {
+        parm_error_completion(numparms, l2vrpi_max, buf, sfs_help_l2_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %s %s", name, vlan1_name, vlan2_name);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] vlan1_name[%s] vlan2_name[%s]\n",
+//               len, parsedargs, name, vlan1_name, vlan2_name);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (((pvlan1entry = find_tpm_vlan_entry_by_name(vlan1_name)) == 0) && strcmp(vlan1_name, vlan_empty_name) != 0)
+        {
+            printk(KERN_INFO "vlan1 entry [%s] not found\n", vlan1_name);
+        }
+        else if (((pvlan2entry = find_tpm_vlan_entry_by_name(vlan2_name)) == 0) && strcmp(vlan2_name, vlan_empty_name) != 0)
+        {
+            printk(KERN_INFO "vlan2 entry [%s] not found\n", vlan2_name);
+        }
+        else
+        {
+            if ((pentry = find_tpm_l2_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_l2_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "L2 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+
+                if (pvlan1entry != 0)
+                {
+                    memcpy(&pentry->l2_acl.vlan1, &pvlan1entry->vlan, sizeof(pentry->l2_acl.vlan1));
+                }
+                else
+                {
+                    memset(&pentry->l2_acl.vlan1, 0, sizeof(pentry->l2_acl.vlan1));
+                }
+
+                if (pvlan2entry != 0)
+                {
+                    memcpy(&pentry->l2_acl.vlan2, &pvlan2entry->vlan, sizeof(pentry->l2_acl.vlan2));
+                }
+                else
+                {
+                    memset(&pentry->l2_acl.vlan2, 0, sizeof(pentry->l2_acl.vlan2));
+                }
+            }
+        }
+    }
+}
+
+
+/********************************************************************************************/
+/* =========================================================================================*/
+/*             TPM CFG L3 KEY FUNCTIONS                                                   */
+/* ======================================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l3_key_ethertype_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies ethertype part part of L3 ACL key
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l3_key_ethertype_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l3etypi_name=0, l3etypi_ety, l3etypi_max
+    } l3_ety_rule_parm_indx_t;
+    unsigned int          temp_ety;
+    char                  name[100];
+    int                   parsedargs;
+    int                   numparms;
+    tpmcfg_l3_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != l3etypi_max)
+    {
+        parm_error_completion(numparms, l3etypi_max, buf, sfs_help_l3_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s 0x%x", name, &temp_ety);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_ety[0x%x]\n", len, parsedargs, name, temp_ety);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_ety > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid ethertype [0x%x]\n", temp_ety);
+        }
+        else
+        {
+            if ((pentry = find_tpm_l3_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_l3_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "L3 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->l3_acl.ether_type_key  = (uint16_t)temp_ety;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_l3_key_pppoe_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies PPPoE part of L3 ACL key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_l3_key_pppoe_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        l3pppoepi_name=0, l3pppoepi_session, l3pppoepi_prototype, l3pppoepi_max
+    } l3_pppoe_rule_parm_indx_t;
+    unsigned int          temp_session;
+    unsigned int          temp_prototype;
+    char                  name[100];
+    int                   parsedargs;
+    int                   numparms;
+    tpmcfg_l3_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != l3pppoepi_max)
+    {
+        parm_error_completion(numparms, l3pppoepi_max, buf, sfs_help_l3_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d 0x%x", name, &temp_session, &temp_prototype);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_session[%d] temp_prototype[0x%x]\n",
+//               len, parsedargs, name, temp_session, temp_prototype);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_session > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid session [%d]\n", temp_session);
+        }
+        else if (temp_prototype > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid protocol type [0x%x]\n", temp_prototype);
+        }
+        else
+        {
+            if ((pentry = find_tpm_l3_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_l3_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "L3 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->l3_acl.pppoe_key.ppp_session = (uint16_t)temp_session;
+                pentry->l3_acl.pppoe_key.ppp_proto   = (uint16_t)temp_prototype;
+            }
+        }
+    }
+}
+
+/********************************************************************************************/
+/* =========================================================================================*/
+/*             TPM CFG IPV4 KEY FUNCTIONS                                                   */
+/* ======================================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv4_key_addr_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies address part of IPV4 key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv4_key_addr_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv4addpi_name=0, ipv4addpi_srcip, ipv4addpi_srcipmask, ipv4addpi_dstip, ipv4addpi_dstipmask, ipv4addpi_max
+    } ipv4_add_rule_parm_indx_t;
+    char                     temp_srcip[30];
+    char                     temp_srcip_mask[30];
+    char                     temp_dstip[30];
+    char                     temp_dstip_mask[30];
+    uint32_t                 srcip[4];
+    uint32_t                 srcip_mask[4];
+    uint32_t                 dstip[4];
+    uint32_t                 dstip_mask[4];
+    char                     name[100];
+    int                      parsedargs;
+    int                      numparms;
+    tpmcfg_ipv4_key_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv4addpi_max)
+    {
+        parm_error_completion(numparms, ipv4addpi_max, buf, sfs_help_ipv4_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %s %s %s %s", name, temp_srcip, temp_srcip_mask, temp_dstip, temp_dstip_mask);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_srcip[%s] temp_srcip_mask[%s] temp_dstip[%s] temp_dstip_mask[%s]\n",
+//               len, parsedargs, name, temp_srcip, temp_srcip_mask, temp_dstip, temp_dstip_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (parse_ipv4_address(temp_srcip, srcip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip [%s]\n", temp_srcip);
+        }
+        else if (parse_ipv4_address(temp_srcip_mask, srcip_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip mask [%s]\n", temp_srcip_mask);
+        }
+        else if (parse_ipv4_address(temp_dstip, dstip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dstip [%s]\n", temp_dstip);
+        }
+        else if (parse_ipv4_address(temp_dstip_mask, dstip_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid dstip mask [%s]\n", temp_dstip_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_ipv4_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_ipv4_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "IPV4 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->ipv4_acl.ipv4_src_ip_add[0] = (uint8_t)srcip[0]; pentry->ipv4_acl.ipv4_src_ip_add[1] = (uint8_t)srcip[1];
+                pentry->ipv4_acl.ipv4_src_ip_add[2] = (uint8_t)srcip[2]; pentry->ipv4_acl.ipv4_src_ip_add[3] = (uint8_t)srcip[3];
+                pentry->ipv4_acl.ipv4_src_ip_add_mask[0] = (uint8_t)srcip_mask[0]; pentry->ipv4_acl.ipv4_src_ip_add_mask[1] = (uint8_t)srcip_mask[1];
+                pentry->ipv4_acl.ipv4_src_ip_add_mask[2] = (uint8_t)srcip_mask[2]; pentry->ipv4_acl.ipv4_src_ip_add_mask[3] = (uint8_t)srcip_mask[3];
+                pentry->ipv4_acl.ipv4_dst_ip_add[0] = (uint8_t)dstip[0]; pentry->ipv4_acl.ipv4_dst_ip_add[1] = (uint8_t)dstip[1];
+                pentry->ipv4_acl.ipv4_dst_ip_add[2] = (uint8_t)dstip[2]; pentry->ipv4_acl.ipv4_dst_ip_add[3] = (uint8_t)dstip[3];
+                pentry->ipv4_acl.ipv4_dst_ip_add_mask[0] = (uint8_t)dstip_mask[0]; pentry->ipv4_acl.ipv4_dst_ip_add_mask[1] = (uint8_t)dstip_mask[1];
+                pentry->ipv4_acl.ipv4_dst_ip_add_mask[2] = (uint8_t)dstip_mask[2]; pentry->ipv4_acl.ipv4_dst_ip_add_mask[3] = (uint8_t)dstip_mask[3];
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv4_key_port_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies port part of IPV4 key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv4_key_port_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv4portpi_name=0, ipv4portpi_srcport, ipv4portpi_dstport, ipv4portpi_max
+    } ipv4port_rule_parm_indx_t;
+    unsigned int             temp_src_port;
+    unsigned int             temp_dst_port;
+    char                     name[100];
+    int                      parsedargs;
+    int                      numparms;
+    tpmcfg_ipv4_key_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv4portpi_max)
+    {
+        parm_error_completion(numparms, ipv4portpi_max, buf, sfs_help_ipv4_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d %d", name, &temp_src_port, &temp_dst_port);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_src_port[%d] temp_dst_port[%d]\n",
+//               len, parsedargs, name, temp_src_port, temp_dst_port);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_src_port > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid srcport [%d]\n", temp_src_port);
+        }
+        else if (temp_dst_port > 0xFFFF)
+        {
+            printk(KERN_INFO "Invalid dstport [%d]\n", temp_dst_port);
+        }
+        else
+        {
+            if ((pentry = find_tpm_ipv4_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_ipv4_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "IPV4 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->ipv4_acl.l4_src_port = (uint16_t)temp_src_port;
+                pentry->ipv4_acl.l4_dst_port = (uint16_t)temp_dst_port;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv4_key_protocol_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies protocol part of IPV4 ACL rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv4_key_protocol_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv4protopi_name=0, ipv4protopi_protocol, ipv4protopi_max
+    } ipv4proto_rule_parm_indx_t;
+    unsigned int             temp_protocol;
+    char                     name[100];
+    int                      parsedargs;
+    int                      numparms;
+    tpmcfg_ipv4_key_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv4protopi_max)
+    {
+        parm_error_completion(numparms, ipv4protopi_max, buf, sfs_help_ipv4_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d", name, &temp_protocol);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_protocol[0x%x]\n",
+//               len, parsedargs, name, temp_protocol);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_protocol > 255)
+        {
+            printk(KERN_INFO "Invalid protocol [%d]\n", temp_protocol);
+        }
+        else
+        {
+            if ((pentry = find_tpm_ipv4_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_ipv4_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "IPV4 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->ipv4_acl.ipv4_proto  = (uint8_t)temp_protocol;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv4_key_dscp_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies DSCP part of IPV4 ACL rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv4_key_dscp_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv4dscppi_name=0, ipv4dscppi_dscp, ipv4dscppi_dscpmask, ipv4dscppi_max
+    } ipv4dscp_rule_parm_indx_t;
+    unsigned int             temp_dscp;
+    unsigned int             temp_dscp_mask;
+    char                     name[100];
+    int                      parsedargs;
+    int                      numparms;
+    tpmcfg_ipv4_key_entry_t  *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv4dscppi_max)
+    {
+        parm_error_completion(numparms, ipv4dscppi_max, buf, sfs_help_ipv4_key_cfg);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %d 0x%x", name, &temp_dscp, &temp_dscp_mask);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s] temp_dscp[%d] temp_dscp_mask[0x%x]\n",
+//               len, parsedargs, name, temp_dscp, temp_dscp_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_dscp > 63)
+        {
+            printk(KERN_INFO "Invalid dscp [%d]\n", temp_dscp);
+        }
+        else if (temp_dscp_mask > 0xFF)
+        {
+            printk(KERN_INFO "Invalid dscp mask [0x%x]\n", temp_dscp_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_ipv4_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_ipv4_key_entry();
+
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "IPV4 key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->ipv4_acl.ipv4_dscp      = (uint8_t)temp_dscp;
+                pentry->ipv4_acl.ipv4_dscp_mask = (uint8_t)temp_dscp_mask;
+            }
+        }
+    }
+}
+
+
+/********************************************************************************************/
+/* =========================================================================================*/
+/*             TPM CFG IPV6 KEY FUNCTIONS                                                   */
+/* ======================================================================================== */
+
+
+
+/********************************************************************************************/
+/* =========================================================================================*/
+/*             TPM CFG IPV6 GEN KEY FUNCTIONS                                             */
+/* ======================================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_gen_key_sip_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies source ip address part of IPV6 gen key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_gen_key_sip_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6gen_name=0, ipv6gen_srcip, ipv6gen_srcipmask, ipv6gen_max
+    } ipv6gensip_rule_parm_indx_t;
+    char     temp_srcip[60];
+    char     temp_srcip_mask[60];
+    uint32_t srcip[16];
+    uint32_t srcip_mask[16];
+    char     name[100];
+    int      parsedargs;
+    int      numparms;
+    int      indx;
+    tpmcfg_ipv6_gen_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6gen_max)
+    {
+        parm_error_completion(numparms, ipv6gen_max, buf, sfs_help_ipv6_gen_key_cfg);
+    }
+    else
+    {
+        parsedargs = sscanf(buf, "%s %s %s", name, temp_srcip, temp_srcip_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (parse_ipv6_address(temp_srcip, srcip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip [%s]\n", temp_srcip);
+        }
+        else if (parse_ipv6_address(temp_srcip_mask, srcip_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid srcip mask [%s]\n", temp_srcip_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_ipv6_gen_key_entry_by_name(name)) == 0)
+            {
+                pentry = find_free_tpm_ipv6_gen_key_entry();
+            }
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "IPV6 gen key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                for (indx = 0; indx < 16; indx++)
+                {
+                    pentry->ipv6gen_acl.ipv6_src_ip_add[indx]      = (uint8_t)srcip[indx];
+                    pentry->ipv6gen_acl.ipv6_src_ip_add_mask[indx] = (uint8_t)srcip_mask[indx];
+                }
+            }
+        }
+    }
+}
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_ctc_cm_key_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies CTC CnM of IPV6 gen key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_ctc_cm_key_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6ctc_name=0, ipv6gen_name, ipv6dip_name, ipv6l4_name, ipv6nh, ipv6hoplimit, ipv6ctc_max
+    } ipv6ctc_rule_parm_indx_t;
+    uint32_t ipv6_nh;
+    uint32_t ipv6_hoplimit;
+    char     ctc_key_name[40];
+    char     gen_key_name[40];
+    char     dip_key_name[40];
+    char     l4_key_name[40];
+    int      parsedargs;
+    int      numparms;
+    int      indx;
+    tpmcfg_ipv6_key_entry_t *pctc_entry;
+    tpmcfg_ipv6_gen_key_entry_t *pgen_entry;
+    tpmcfg_ipv6_dip_key_entry_t *pdip_entry;
+    tpmcfg_ipv6_l4_ports_key_entry_t  *pl4_entry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6ctc_max)
+    {
+        parm_error_completion(numparms, ipv6ctc_max, buf, sfs_help_ipv6_ctc_cm_key_cfg);
+    }
+    else
+    {
+        parsedargs = sscanf(buf, "%s %s %s %s %d %d", ctc_key_name, gen_key_name, dip_key_name,
+                            l4_key_name, &ipv6_nh, &ipv6_hoplimit);
+
+        if (strlen(ctc_key_name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", ctc_key_name);
+        }
+        else if (strlen(gen_key_name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", gen_key_name);
+        }
+        else if (strlen(dip_key_name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", dip_key_name);
+        }
+        else if (strlen(l4_key_name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", l4_key_name);
+        }
+        else if (ipv6_nh > 0xff)
+        {
+            printk(KERN_INFO "Invalid ipv6_nh [%d]\n", ipv6_nh);
+        }
+        else if (ipv6_hoplimit > 0xff)
+        {
+            printk(KERN_INFO "Invalid ipv6_hoplimit [%d]\n", ipv6_hoplimit);
+        }
+        else
+        {
+            if (    ((pgen_entry = find_tpm_ipv6_gen_key_entry_by_name(gen_key_name)) == 0)
+                  && (strcmp(gen_key_name, ipv6_gen_key_empty_name) != 0))
+            {
+		printk(KERN_INFO "ipv6 gen key entry [%s] not found\n", gen_key_name);
+		return;
+            }
+            if (    ((pdip_entry = find_tpm_ipv6_dip_key_entry_by_name(dip_key_name)) == 0)
+                  && (strcmp(dip_key_name, ipv6_dip_key_empty_name) != 0))
+            {
+		printk(KERN_INFO "ipv6 dip key entry [%s] not found\n", dip_key_name);
+		return;
+            }
+            if (    ((pl4_entry = find_tpm_ipv6_l4_ports_key_entry_by_name(l4_key_name)) == 0)
+                  && (strcmp(l4_key_name, ipv6_l4_key_empty_name) != 0))
+            {
+		printk(KERN_INFO "ipv6 l4 key entry [%s] not found\n", l4_key_name);
+		return;
+            }
+
+            if ((pctc_entry = find_tpm_ipv6_key_entry_by_name(ctc_key_name)) == 0)
+            {
+                pctc_entry = find_free_tpm_ipv6_key_entry();
+            }
+            if (pctc_entry == 0)
+            {
+                printk(KERN_INFO "IPV6 key DB full\n");
+                return;
+            }
+            else
+            {
+                strcpy(pctc_entry->name, ctc_key_name);
+                for (indx = 0; indx < 16; indx++)
+                {
+                    if (pdip_entry) {
+		        pctc_entry->ipv6_acl.ipv6_dst_ip_add[indx]	= (uint8_t)pdip_entry->ipv6_addr.ipv6_ip_add[indx];
+		        pctc_entry->ipv6_acl.ipv6_dst_ip_add_mask[indx] = (uint8_t)pdip_entry->ipv6_addr.ipv6_ip_add_mask[indx];
+		    }
+                    if (pgen_entry) {
+			pctc_entry->ipv6_acl.ipv6_src_ip_add[indx]      = (uint8_t)pgen_entry->ipv6gen_acl.ipv6_src_ip_add[indx];
+			pctc_entry->ipv6_acl.ipv6_src_ip_add_mask[indx] = (uint8_t)pgen_entry->ipv6gen_acl.ipv6_src_ip_add_mask[indx];
+		    }
+                }
+		if (pgen_entry) {
+		    pctc_entry->ipv6_acl.ipv6_dscp_mask = (uint8_t)pgen_entry->ipv6gen_acl.ipv6_dscp_mask;
+		    pctc_entry->ipv6_acl.ipv6_dscp = (uint8_t)pgen_entry->ipv6gen_acl.ipv6_dscp;
+		}
+		if (pl4_entry) {
+		    pctc_entry->ipv6_acl.l4_src_port = (uint16_t)pl4_entry->l4_ports.l4_src_port;
+		    pctc_entry->ipv6_acl.l4_dst_port = (uint16_t)pl4_entry->l4_ports.l4_dst_port;
+		}
+		pctc_entry->ipv6_acl.ipv6_next_header= (uint8_t)ipv6_nh;
+		pctc_entry->ipv6_acl.ipv6_hoplimit = (uint8_t)ipv6_hoplimit;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_dip_key_dip_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies source ip address part of IPV6 dip key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_dip_key_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6dip_name=0, ipv6dip_ip, ipv6dip_ipmask, ipv6dip_max
+    } ipv6dip_rule_parm_indx_t;
+    char     temp_ip[60];
+    char     temp_ip_mask[60];
+    uint32_t ip[16];
+    uint32_t ip_mask[16];
+    char     name[100];
+    int      parsedargs;
+    int      numparms;
+    int      indx;
+    tpmcfg_ipv6_dip_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6dip_max)
+    {
+        parm_error_completion(numparms, ipv6dip_max, buf, sfs_help_ipv6_dip_key_cfg);
+    }
+    else
+    {
+        parsedargs = sscanf(buf, "%s %s %s", name, temp_ip, temp_ip_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (parse_ipv6_address(temp_ip, ip) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid ip [%s]\n", temp_ip);
+        }
+        else if (parse_ipv6_address(temp_ip_mask, ip_mask) == GT_FALSE)
+        {
+            printk(KERN_INFO "Invalid ip mask [%s]\n", temp_ip_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_ipv6_dip_key_entry_by_name(name)) == 0)
+            {
+                pentry = find_free_tpm_ipv6_dip_key_entry();
+            }
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "IPV6 dip key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                for (indx = 0; indx < 16; indx++)
+                {
+                    pentry->ipv6_addr.ipv6_ip_add[indx]      = (uint8_t)ip[indx];
+                    pentry->ipv6_addr.ipv6_ip_add_mask[indx] = (uint8_t)ip_mask[indx];
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_l4_key_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies source ip address part of IPV6 dip key rule
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_l4_key_rule(const char *buf, size_t len)
+{
+    typedef enum {
+        ipv6l4key_name=0, ipv6l4key_srcport, ipv6l4key_dstport, ipv6l4key_max
+    } ipv6l4_key_parm_indx_t;
+    uint32_t src_port, dst_port;
+    char     name[100];
+    int      parsedargs;
+    int      numparms;
+    tpmcfg_ipv6_l4_ports_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6l4key_max)
+        parm_error_completion(numparms, ipv6l4key_max, buf, sfs_help_ipv6_l4_key_cfg);
+    else {
+        parsedargs = sscanf(buf, "%s %d %d", name, &src_port, &dst_port);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        else {
+            if ((pentry = find_tpm_ipv6_l4_ports_key_entry_by_name(name)) == 0)
+                pentry = find_free_tpm_ipv6_l4_ports_key_entry();
+			
+            if (pentry == 0)
+                printk(KERN_INFO "IPV6 L4 ports key DB full\n");
+            else {
+                strcpy(pentry->name, name);
+				pentry->l4_ports.l4_dst_port = dst_port;
+				pentry->l4_ports.l4_src_port = src_port;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_ipv6_gen_key_dscp_rule
+*
+* DESCRIPTION:
+*           This function adds/modifies DSCP part of IPV6 ACL rule
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_ipv6_gen_key_dscp_rule  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ipv6gendscp_name=0, ipv6gendscp_dscp, ipv6gendscp_dscpmask, ipv6gendscp_max
+    } ipv6gendscp_rule_parm_indx_t;
+    unsigned int             temp_dscp;
+    unsigned int             temp_dscp_mask;
+    char                     name[100];
+    int                      parsedargs;
+    int                      numparms;
+    tpmcfg_ipv6_gen_key_entry_t *pentry;
+
+    numparms = count_parameters(buf);
+    if (numparms != ipv6gendscp_max)
+    {
+        parm_error_completion(numparms, ipv6gendscp_max, buf, sfs_help_ipv6_gen_key_cfg);
+    }
+    else
+    {
+        parsedargs = sscanf(buf, "%s %d 0x%x", name, &temp_dscp, &temp_dscp_mask);
+
+        if (strlen(name) > DB_TPMCFG_MAX_NAME)
+        {
+            printk(KERN_INFO "Name too long [%s]\n", name);
+        }
+        else if (temp_dscp > 63)
+        {
+            printk(KERN_INFO "Invalid dscp [%d]\n", temp_dscp);
+        }
+        else if (temp_dscp_mask > 0xFF)
+        {
+            printk(KERN_INFO "Invalid dscp mask [0x%x]\n", temp_dscp_mask);
+        }
+        else
+        {
+            if ((pentry = find_tpm_ipv6_gen_key_entry_by_name(name)) == 0)
+            {
+                pentry = find_free_tpm_ipv6_gen_key_entry();
+            }
+            if (pentry == 0)
+            {
+                printk(KERN_INFO "IPV6 gen key DB full\n");
+            }
+            else
+            {
+                strcpy(pentry->name, name);
+                pentry->ipv6gen_acl.ipv6_dscp      = (uint8_t)temp_dscp;
+                pentry->ipv6gen_acl.ipv6_dscp_mask = (uint8_t)temp_dscp_mask;
+            }
+        }
+    }
+}
+
+typedef struct
+{
+    char    *table_name;
+    GT_BOOL (*clear_rule)(char *buf);
+    void    (*display_table)(void);
+} table_rule_operation_t;
+
+static table_rule_operation_t table_rule_operation_ara[] =
+{
+    {"frwd",         del_tpm_pkt_frwd_entry_by_name,          show_tpm_pkt_frwd_db},
+    {"vlan",         del_tpm_vlan_entry_by_name,              show_tpm_vlan_db},
+    {"mod",          del_tpm_mod_entry_by_name,               show_tpm_mod_db},
+    {"l2key",        del_tpm_l2_key_entry_by_name,            show_tpm_l2_key_db},
+    {"l3key",        del_tpm_l3_key_entry_by_name,            show_tpm_l3_key_db},
+    {"ipv4key",      del_tpm_ipv4_key_entry_by_name,          show_tpm_ipv4_key_db},
+    // The following "duplicate" entries for alternate access to mdelete entry functionality
+    {"l2",           del_tpm_l2_key_entry_by_name,            show_tpm_l2_key_db},
+    {"l3",           del_tpm_l3_key_entry_by_name,            show_tpm_l3_key_db},
+    {"ipv4",         del_tpm_ipv4_key_entry_by_name,          show_tpm_ipv4_key_db},
+    {"ipv6_dip",     del_tpm_ipv6_dip_key_entry_by_name,      show_tpm_ipv6_dip_key_db},
+    {"ipv6_gen",     del_tpm_ipv6_gen_key_entry_by_name,      show_tpm_ipv6_gen_key_db},
+    {"ipv6_l4",      del_tpm_ipv6_l4_ports_key_entry_by_name, show_tpm_ipv6_l4_ports_key_db},
+    {"ipv6_ctc",     del_tpm_ipv6_key_entry_by_name,          show_tpm_ipv6_key_db},
+};
+static int num_table_operations = sizeof(table_rule_operation_ara)/sizeof(table_rule_operation_ara[0]);
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_key_rule_delete
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_key_rule_delete  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ruleclearpi_table=0, ruleclearpi_rule, ruleclearpi_max
+    } ruleclear_rule_parm_indx_t;
+    char                     table[100];
+    char                     rulename[100];
+    int                      parsedargs;
+    int                      numparms;
+    int                      indx;
+    GT_BOOL                  found = GT_FALSE;
+    GT_BOOL                  rc;
+    table_rule_operation_t   *ptableop;
+
+    numparms = count_parameters(buf);
+    if (numparms != ruleclearpi_max)
+    {
+        parm_error_completion(numparms, ruleclearpi_max, buf, sfs_help_key_rule_delete);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s %s", table, rulename);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. table[%s] rulename[%s]\n",
+//               len, parsedargs, table, rulename);
+
+        for (indx = 0; indx < num_table_operations; indx++)
+        {
+            ptableop = &table_rule_operation_ara[indx];
+            if (!strcmp(table, ptableop->table_name))
+            {
+                found = GT_TRUE;
+                rc = (ptableop->clear_rule)(rulename);
+                break;
+            }
+        }
+
+        if (found == GT_FALSE)
+        {
+            printk("%s: Table %s not found\n", __FUNCTION__, table);
+        }
+        else if (rc == GT_FALSE)
+        {
+            printk("%s: Table %s does not have entry named %s\n", __FUNCTION__, table, rulename);
+        }
+//        else
+//        {
+//            (ptableop->display_table)();
+//        }
+    }
+}
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_rule_table_display
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_rule_table_display  (const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ruledisppi_table=0, ruledisppi_table_max
+    } ruledisp_rule_parm_indx_t;
+    char                     table[100];
+    int                      parsedargs;
+    int                      numparms;
+    int                      indx;
+    GT_BOOL                  found = GT_FALSE;
+    table_rule_operation_t   *ptableop;
+
+    numparms = count_parameters(buf);
+
+    if (numparms == 1 && buf[0] == '?')
+    {
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+        char helpbuf[1000];
+        int  helpbuf_len;
+
+        helpbuf_len = sfs_help_rule_table_display(helpbuf);
+        print_help_buffer(helpbuf, helpbuf_len);
+#else
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", ruledisppi_table_max, numparms);
+#endif
+    }
+    else if (numparms != 1)
+    {
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", ruledisppi_table_max, numparms);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s", table);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. table[%s]\n", len, parsedargs, table);
+
+        for (indx = 0; indx < num_table_operations; indx++)
+        {
+            ptableop = &table_rule_operation_ara[indx];
+            if (!strcmp(table, ptableop->table_name))
+            {
+                found = GT_TRUE;
+                (ptableop->display_table)();
+                break;
+            }
+        }
+
+        if (found == GT_FALSE)
+        {
+            printk("%s: Table %s not found\n", __FUNCTION__, table);
+        }
+    }
+}
+
+/*******************************************************************************
+* delete_rule_from_table
+*
+* DESCRIPTION:
+*           This function deletes entry in rule table
+*
+*
+*******************************************************************************/
+static void delete_rule_from_table(char *table, const char *buf, size_t len)
+{
+    typedef enum
+    {
+        ruledelpi_rule=0, ruledelpi_max
+    } ruledel_rule_parm_indx_t;
+    char                     rulename[100];
+    int                      parsedargs;
+    int                      numparms;
+    int                      indx;
+    GT_BOOL                  found = GT_FALSE;
+    GT_BOOL                  rc;
+    table_rule_operation_t   *ptableop;
+
+    numparms = count_parameters(buf);
+    if (numparms == 1 && buf[0] == '?')
+    {
+        printk(KERN_INFO "echo [rule_name] > delete_entry_%s_rule_table\n", table);
+    }
+    else if (numparms != 1)
+    {
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", ruledelpi_max, numparms);
+    }
+    else
+    {
+        // Get parameters
+        parsedargs = sscanf(buf, "%s", rulename);
+//        printk(KERN_INFO "len=%d, parsedargs=%d. rulename[%s]\n", len, parsedargs, rulename);
+
+        for (indx = 0; indx < num_table_operations; indx++)
+        {
+            ptableop = &table_rule_operation_ara[indx];
+            if (!strcmp(table, ptableop->table_name))
+            {
+                found = GT_TRUE;
+                rc = (ptableop->clear_rule)(rulename);
+                break;
+            }
+        }
+
+        if (found == GT_FALSE)
+        {
+            printk("%s: Table %s not found\n", __FUNCTION__, table);
+        }
+        else if (rc == GT_FALSE)
+        {
+            printk("%s: Table %s does not have entry named %s\n", __FUNCTION__, table, rulename);
+        }
+    }
+
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_l2_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_l2_rule_table  (const char *buf, size_t len)
+{
+    delete_rule_from_table("l2key", buf, len);
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_l3_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_l3_rule_table  (const char *buf, size_t len)
+{
+    delete_rule_from_table("l3key", buf, len);
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_ipv4_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_ipv4_rule_table(const char *buf, size_t len)
+{
+    delete_rule_from_table("ipv4key", buf, len);
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_ipv6_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_ipv6_rule_table(const char *buf, size_t len)
+{
+    delete_rule_from_table("ipv6key", buf, len);
+}
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_ipv6_dip_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_ipv6_dip_rule_table(const char *buf, size_t len)
+{
+    delete_rule_from_table("ipv6_dip", buf, len);
+}
+
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_ipv6_gen_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_ipv6_gen_rule_table(const char *buf, size_t len)
+{
+    delete_rule_from_table("ipv6_gen", buf, len);
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_ipv6_gen_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_ipv6_l4_rule_table(const char *buf, size_t len)
+{
+    delete_rule_from_table("ipv6_l4", buf, len);
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_frwd_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_frwd_rule_table(const char *buf, size_t len)
+{
+    delete_rule_from_table("frwd", buf, len);
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_vlan_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_vlan_rule_table(const char *buf, size_t len)
+{
+    delete_rule_from_table("vlan", buf, len);
+}
+
+/*******************************************************************************
+* sfs_tpm_cfg_set_delete_entry_mod_rule_table
+*
+* DESCRIPTION:
+*           This function removes named rule from specified table
+*
+* See sfs_tpm_cfg_set_frwd_rule() for INPUTS, OUTPUTS, RETURNS and COMMENTS details
+*
+*******************************************************************************/
+void sfs_tpm_cfg_set_delete_entry_mod_rule_table (const char *buf, size_t len)
+{
+    delete_rule_from_table("mod", buf, len);
+}
+
+
+
+
+#if 0
+// The show_tpm_XYZ_key_db() routines must be made more flexible - take char *buf parameter
+// and return number of characters to print.
+// If called from the functions below, the buf argument is passed
+// If called from a store function, the argument wll be zero and the routine uses a local buffer
+// Messy, this way or that - since the file may be too big for sysfs store invocation
+/*******************************************************************************
+**
+**  sfs_show_l2_rule_table
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_show_l2_rule_table   (char *buf)
+{
+    show_tpm_l2_key_db();
+}
+
+/*******************************************************************************
+**
+**  sfs_show_l3_rule_table - see header of sfs_show_l2_rule_table
+**
+*******************************************************************************/
+int sfs_show_l3_rule_table   (char *buf)
+{
+    show_tpm_l3_key_db();
+}
+
+/*******************************************************************************
+**
+**  sfs_show_ipv4_rule_table - see header of sfs_show_l2_rule_table
+**
+*******************************************************************************/
+int sfs_show_ipv4_rule_table (char *buf)
+{
+    show_tpm_ipv4_key_db();
+}
+
+/*******************************************************************************
+**
+**  sfs_show_ipv6_rule_table - see header of sfs_tpm_cfg_index
+**
+*******************************************************************************/
+int sfs_show_ipv6_rule_table (char *buf)
+{
+    show_tpm_ipv6_key_db();
+}
+
+/*******************************************************************************
+**
+**  sfs_show_frwd_rule_table - see header of sfs_show_l2_rule_table
+**
+*******************************************************************************/
+int sfs_show_frwd_rule_table (char *buf)
+{
+    show_tpm_pkt_frwd_db()
+}
+
+/*******************************************************************************
+**
+**  sfs_show_vlan_rule_table - see header of sfs_show_l2_rule_table
+**
+*******************************************************************************/
+int sfs_show_vlan_rule_table (char *buf)
+{
+    show_tpm_vlan_db();
+}
+
+/*******************************************************************************
+**
+**  sfs_show_mod_rule_table - see header of sfs_show_l2_rule_table
+**
+*******************************************************************************/
+int sfs_show_mod_rule_table  (char *buf)
+{
+    show_tpm_mod_db()
+}
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.h
new file mode 100755
index 0000000..fce17e9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_rule_db.h
@@ -0,0 +1,142 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_usr_tpmsysfs_if.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   Zeev
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               $Revision: 1.1.1.1 $
+*
+*
+*******************************************************************************/
+#ifndef _TPM_USR_TPM_SYSFS_RULE_DB_H_
+#define _TPM_USR_TPM_SYSFS_RULE_DB_H_
+
+extern void sfs_tpm_cfg_set_frwd_rule                   (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_vlan_rule                   (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_proto_rule              (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_mh_rule                 (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_vlan_rule               (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_dscp_rule               (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_ipv4_addr_rule          (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_ipv4_port_rule          (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_ipv6_addr_rule          (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_ipv6_port_rule          (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_mac_addr_rule           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_mod_pppoe_rule              (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_pkt_mod_eng_entry_add       (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_pkt_mod_eng_entry_show      (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_pkt_mod_eng_entry_del       (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_pkt_mod_eng_purge           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_l2_key_ethertype_rule       (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_l2_key_gemport_rule         (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_l2_key_mac_addr_rule        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_l2_key_pppoe_rule           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_l2_key_vlan_rule            (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_l3_key_ethertype_rule       (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_l3_key_pppoe_rule           (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv4_key_addr_rule          (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv4_key_port_rule          (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv4_key_protocol_rule      (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv4_key_dscp_rule          (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_gen_key_sip_rule       (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_ctc_cm_key_rule        (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_ipv6_gen_key_dscp_rule      (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_key_rule_delete             (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_rule_table_display          (const char *buf, size_t len);
+
+extern void sfs_tpm_cfg_set_delete_entry_l2_rule_table  (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_l3_rule_table  (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_ipv4_rule_table(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_ipv6_rule_table(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_ipv6_dip_rule_table(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_ipv6_gen_rule_table(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_ipv6_l4_rule_table (const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_frwd_rule_table(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_vlan_rule_table(const char *buf, size_t len);
+extern void sfs_tpm_cfg_set_delete_entry_mod_rule_table (const char *buf, size_t len);
+
+
+
+#if 0
+extern int sfs_show_l2_rule_table                     (char *buf);
+extern int sfs_show_l3_rule_table                     (char *buf);
+extern int sfs_show_ipv4_rule_table                   (char *buf);
+extern int sfs_show_ipv6_rule_table                   (char *buf);
+extern int sfs_show_frwd_rule_table                   (char *buf);
+extern int sfs_show_vlan_rule_table                   (char *buf);
+extern int sfs_show_mod_rule_table                    (char *buf);
+#endif
+
+#endif  /* _sfs_tpm_cfg_setTPM_USR_TPM_SYSFS_RULE_DB_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.c
new file mode 100755
index 0000000..c211f34
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.c
@@ -0,0 +1,1257 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+        this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_sysfs_help.h"
+#include "tpm_sysfs_rule_db.h"
+#include "tpm_sysfs_hwcall.h"
+#include "tpm_sysfs_utils.h"
+#include "tpm_sysfs_setup.h"
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM CFG SYS FS STORE ROUTINE SWITCHER                          */
+/* ========================================================================== */
+
+typedef struct
+{
+    char *sysfs_name;
+    void (*sysfs_func)( const char *buf, size_t len);
+} store_sysfs_name_func_t;
+
+static store_sysfs_name_func_t store_sysfs_name_func_ara[] =
+{
+    {"frwd_rule_set",                      sfs_tpm_cfg_set_frwd_rule},
+    {"vlan_rule_set",                      sfs_tpm_cfg_set_vlan_rule},
+    {"mod_mh_rule_set",                    sfs_tpm_cfg_set_mod_mh_rule},
+    {"mod_vlan_rule_set",                  sfs_tpm_cfg_set_mod_vlan_rule},
+    {"mod_ipv4_addr_rule_set",             sfs_tpm_cfg_set_mod_ipv4_addr_rule},
+    {"mod_ipv4_port_rule_set",             sfs_tpm_cfg_set_mod_ipv4_port_rule},
+    {"mod_ipv6_addr_rule_set",             sfs_tpm_cfg_set_mod_ipv6_addr_rule},
+    {"mod_ipv6_port_rule_set",             sfs_tpm_cfg_set_mod_ipv6_port_rule},
+    {"mod_mac_addr_rule_set",              sfs_tpm_cfg_set_mod_mac_addr_rule},
+    {"mod_pppoe_rule_set",                 sfs_tpm_cfg_set_mod_pppoe_rule},
+    {"l2_key_ethertype_rule_set",          sfs_tpm_cfg_set_l2_key_ethertype_rule},
+    {"l2_key_gemport_rule_set",            sfs_tpm_cfg_set_l2_key_gemport_rule},
+    {"l2_key_mac_addr_rule_set",           sfs_tpm_cfg_set_l2_key_mac_addr_rule},
+    {"l2_key_pppoe_rule_set",              sfs_tpm_cfg_set_l2_key_pppoe_rule},
+    {"l2_key_vlan_rule_set",               sfs_tpm_cfg_set_l2_key_vlan_rule},
+    {"l3_key_ethertype_rule_set",          sfs_tpm_cfg_set_l3_key_ethertype_rule},
+    {"l3_key_pppoe_rule_set",              sfs_tpm_cfg_set_l3_key_pppoe_rule},
+    {"ipv4_key_addr_rule_set",             sfs_tpm_cfg_set_ipv4_key_addr_rule},
+    {"ipv4_key_port_rule_set",             sfs_tpm_cfg_set_ipv4_key_port_rule},
+    {"ipv4_key_proto_rule_set",            sfs_tpm_cfg_set_ipv4_key_protocol_rule},
+    {"ipv4_key_dscp_rule_set",             sfs_tpm_cfg_set_ipv4_key_dscp_rule},
+    {"ipv6_ctc_cm_key_rule_set",           sfs_tpm_cfg_set_ipv6_ctc_cm_key_rule},
+    {"ipv6_gen_key_sip_rule_set",          sfs_tpm_cfg_set_ipv6_gen_key_sip_rule},
+    {"ipv6_gen_key_dscp_rule_set",         sfs_tpm_cfg_set_ipv6_gen_key_dscp_rule},
+    {"key_rule_delete",                    sfs_tpm_cfg_set_key_rule_delete},
+    {"rule_table_display",                 sfs_tpm_cfg_set_rule_table_display},
+    {"l2_rule_add",                        sfs_tpm_cfg_set_l2_rule_add},
+    {"l3_rule_add",                        sfs_tpm_cfg_set_l3_rule_add},
+    {"ipv4_rule_add",                      sfs_tpm_cfg_set_ipv4_rule_add},
+    {"ipv6_gen_rule_add",                  sfs_tpm_cfg_set_ipv6_gen_rule_add},
+    {"mc_ipv4_stream_add",                 sfs_tpm_cfg_set_mc_ipv4_stream_add},
+    {"mc_ipv4_stream_update",              sfs_tpm_cfg_set_mc_ipv4_stream_update},
+	{"mc_ipv6_stream_add",				   sfs_tpm_cfg_set_mc_ipv6_stream_add},
+	{"mc_ipv6_stream_update",			   sfs_tpm_cfg_set_mc_ipv6_stream_update},
+    {"igmp_port_forward_mode_cfg",         sfs_tpm_cfg_set_igmp_port_forward_mode_cfg},
+    {"mc_vid_key_reset",                   sfs_tpm_cfg_set_mc_vid_key_reset},
+    {"mc_vid_key_set",                     sfs_tpm_cfg_set_mc_vid_key_set},
+    {"mc_vid_cfg_set",                     sfs_tpm_cfg_set_mc_vid_cfg_set},
+    {"igmp_cpu_queue_cfg",                 sfs_tpm_cfg_set_igmp_cpu_queue_cfg},
+    {"igmp_proxy_sa_mac",                  sfs_tpm_cfg_set_igmp_proxy_sa_mac},
+    {"no_rule_add_l2",                     sfs_tpm_cfg_set_no_rule_add_l2},
+    {"no_rule_add_l3",                     sfs_tpm_cfg_set_no_rule_add_l3},
+    {"no_rule_add_ipv4",                   sfs_tpm_cfg_set_no_rule_add_ipv4},
+	{"no_mc_stream_add_ipv6",			   sfs_tpm_cfg_set_no_mc_stream_add_ipv6},
+    {"no_mc_stream_add_ipv4",              sfs_tpm_cfg_set_no_mc_stream_add_ipv4},
+    {"oam_channel",                        sfs_tpm_cfg_set_oam_channel},
+    {"omci_channel",                       sfs_tpm_cfg_set_omci_channel},
+    {"no_oam_channel",                     sfs_tpm_cfg_set_no_oam_channel},
+    {"no_omci_channel",                    sfs_tpm_cfg_set_no_omci_channel},
+    {"tpm_setup",                          sfs_tpm_cfg_setup},
+    {"mib_reset",                          sfs_tpm_cfg_set_mib_reset},
+    {"erase_section",                      sfs_tpm_cfg_set_erase_section},
+    {"add_cpu_lpbk",                       sfs_tpm_cfg_add_cpu_lpbk},
+    {"del_cpu_lpbk",                       sfs_tpm_cfg_del_cpu_lpbk},
+    {"dump_cpu_lpbk",                      sfs_tpm_cfg_dump_cpu_lpbk},
+    {"get_lu_entry",                       sfs_tpm_cfg_get_lu_entry},
+    {"set_count_mask",                     sfs_tpm_cfg_set_count_mask},
+    {"get_hit_count",                      sfs_tpm_cfg_get_hit_count},
+    {"get_pnc_all_hit_cntrs",              sfs_tpm_cfg_get_pnc_all_hit_counters},
+    {"set_lu_thresh",                      sfs_tpm_cfg_set_lu_thresh},
+    {"reset_age_group",                    sfs_tpm_cfg_reset_age_group},
+    {"rate_limit_queue_set",               sfs_tpm_cfg_set_rate_limit_queue_set},
+    {"scheduling_mode_queue_set",          sfs_tpm_cfg_set_scheduling_mode_queue_set},
+    {"rate_limit_if_set",                  sfs_tpm_cfg_set_rate_limit_if_set},
+    {"pkt_mod_eng_entry_add",              sfs_tpm_cfg_set_pkt_mod_eng_entry_add},
+    {"pkt_mod_eng_entry_show",             sfs_tpm_cfg_set_pkt_mod_eng_entry_show},
+    {"pkt_mod_eng_entry_del",              sfs_tpm_cfg_set_pkt_mod_eng_entry_del},
+    {"pkt_mod_eng_purge",                  sfs_tpm_cfg_set_pkt_mod_eng_purge},
+    {"delete_entry_l2_rule_table",         sfs_tpm_cfg_set_delete_entry_l2_rule_table},
+    {"delete_entry_l3_rule_table",         sfs_tpm_cfg_set_delete_entry_l3_rule_table},
+    {"delete_entry_ipv4_rule_table",       sfs_tpm_cfg_set_delete_entry_ipv4_rule_table},
+    {"delete_entry_ipv6_gen_rule_table",   sfs_tpm_cfg_set_delete_entry_ipv6_gen_rule_table},
+    {"delete_entry_ipv6_dip_rule_table",   sfs_tpm_cfg_set_delete_entry_ipv6_dip_rule_table},
+    {"delete_entry_ipv6_l4_rule_table",    sfs_tpm_cfg_set_delete_entry_ipv6_l4_rule_table},
+    {"delete_entry_frwd_rule_table",       sfs_tpm_cfg_set_delete_entry_frwd_rule_table},
+    {"delete_entry_vlan_rule_table",       sfs_tpm_cfg_set_delete_entry_vlan_rule_table},
+    {"delete_entry_mod_rule_table",        sfs_tpm_cfg_set_delete_entry_mod_rule_table},
+
+    /* jinghuaxxxxxx */
+    {"ipv6_dip_key_rule_set",              sfs_tpm_cfg_set_ipv6_dip_key_rule},
+    {"ipv6_l4_key_rule_set",               sfs_tpm_cfg_set_ipv6_l4_key_rule},
+    {"ipv6_dip_rule_add",                  sfs_tpm_cfg_set_ipv6_dip_acl_rule_add},
+    {"no_rule_add_ipv6_dip_acl",           sfs_tpm_cfg_set_no_rule_add_ipv6_dip},
+    {"ipv6_l4_ports_acl_rule_add",         sfs_tpm_cfg_set_ipv6_l4_ports_acl_rule_add},
+    {"no_rule_add_ipv6_l4_ports_acl",      sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_acl},
+
+    {"ipv6_gen_5t_rule_add",               sfs_tpm_cfg_set_ipv6_gen_5t_rule_add},
+    {"no_rule_add_ipv6_gen_5t",            sfs_tpm_cfg_set_no_rule_add_ipv6_gen_5t},
+    {"ipv6_dip_5t_rule_add",               sfs_tpm_cfg_set_ipv6_dip_5t_rule_add},
+    {"no_rule_add_ipv6_dip_5t",            sfs_tpm_cfg_set_no_rule_add_ipv6_dip_5t},
+    {"ipv6_l4_ports_5t_rule_add",          sfs_tpm_cfg_set_ipv6_l4_ports_5t_rule_add},
+    {"no_rule_add_ipv6_l4_ports_5t",       sfs_tpm_cfg_set_no_rule_add_ipv6_l4_ports_5t},
+
+    // zeev
+    {"ipv6_nh_acl_rule_add",               sfs_tpm_cfg_set_ipv6_nh_acl_rule_add},
+    {"no_rule_add_ipv6_nh_acl",            sfs_tpm_cfg_set_no_rule_add_ipv6_nh_acl},
+    {"no_rule_add_ipv6_gen_acl",           sfs_tpm_cfg_set_no_rule_add_ipv6_gen_acl},
+
+    {"ctc_cm_acl_rule_add",                sfs_tpm_cfg_set_ctc_cm_rule_add},
+    {"ctc_cm_ipv6_acl_rule_add",	   sfs_tpm_cfg_set_ctc_cm_ipv6_rule_add},
+    {"ctc_cm_set_ipv6_parse_win",	   sfs_tpm_cfg_ctc_cm_set_ipv6_parse_win},
+    {"no_rule_add_ctc_cm_acl",             sfs_tpm_cfg_set_no_rule_add_ctc_cm_acl},
+
+    {"enable_mtu",                         sfs_tpm_cfg_set_mtu_enable},
+    {"set_mtu",                            sfs_tpm_cfg_set_mtu},
+    {"set_pppoe_mtu",                      sfs_tpm_cfg_set_pppoe_mtu},
+    {"send_genquery_to_uni",               sfs_tpm_cfg_send_genquery_to_uni},
+    {"flush_atu",                          sfs_tpm_cfg_flush_atu},
+    {"flush_vtu",                          sfs_tpm_cfg_flush_vtu},
+
+    {"tpm_self_check",                     sfs_tpm_rule_self_check},
+    {"mac_learn_rule_add",                 sfs_tpm_cfg_set_mac_learn_rule_add},
+    {"no_rule_add_mac_learn",              sfs_tpm_cfg_set_no_rule_add_mac_learn},
+    {"mac_learn_default_rule_act_set",     sfs_tpm_cfg_set_mac_learn_default_rule_action},
+    {"gmac0_ingr_rate_limit_set",          sfs_tpm_cfg_set_gmac0_ingr_rate_limit},
+
+    /* KostaP */
+    {"fc_config_set",                      sfs_tpm_cfg_set_fc},
+    {"fc_us_period_set",                   sfs_tpm_cfg_set_fc_period},
+#ifdef TPM_FC_DEBUG
+    {"fc_oneshot_set",                     sfs_tpm_cfg_set_fc_oneshot},
+#endif
+    {"fc_enable",                  	    sfs_tpm_cfg_fc_enable}
+};
+static int num_store_name_funcs = sizeof(store_sysfs_name_func_ara)/sizeof(store_sysfs_name_func_ara[0]);
+
+static ssize_t tpm_cfg_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t len)
+{
+    const char*             name = attr->attr.name;
+/*    unsigned long           flags  = 0;*/
+    store_sysfs_name_func_t *pnamefunc;
+    int                     indx;
+    GT_BOOL                 found = GT_FALSE;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+//     raw_local_irq_save(flags);
+
+    for (indx = 0; indx < num_store_name_funcs; indx++){
+        pnamefunc = &store_sysfs_name_func_ara[indx];
+        if (!strcmp(name, pnamefunc->sysfs_name)) {
+            found = GT_TRUE;
+            (pnamefunc->sysfs_func)(buf, len);
+            break;
+        }
+    }
+
+    if (found == GT_FALSE){
+        printk("%s: operation <%s> not found\n", __FUNCTION__, attr->attr.name);
+    }
+
+//     raw_local_irq_restore(flags);
+
+    return(len);
+}
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM CFG SYS FS ROUTINE SHOW SWITCHER                           */
+/* ========================================================================== */
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+
+typedef struct
+{
+    char *sysfs_name;
+    int (*sysfs_func)( char *buf);
+    } show_sysfs_name_func_t;
+
+static show_sysfs_name_func_t show_sysfs_name_func_ara[] =
+{
+    {"help_tpm_cfg_index",           sfs_tpm_cfg_index},
+    {"help_frwd_rule_cfg",           sfs_help_frwd_rule_cfg},
+    {"help_vlan_rule_cfg",           sfs_help_vlan_rule_cfg},
+    {"help_mod_rule_cfg",            sfs_help_mod_rule_cfg},
+    {"help_l2_key_cfg",              sfs_help_l2_key_cfg},
+    {"help_l3_key_cfg",              sfs_help_l3_key_cfg},
+    {"help_ipv4_key_cfg",            sfs_help_ipv4_key_cfg},
+    {"help_rule_table_display",      sfs_help_rule_table_display},
+    {"help_l2_rule_add",             sfs_help_l2_rule_add},
+    {"help_l3_rule_add",             sfs_help_l3_rule_add},
+    {"help_ipv4_rule_add",           sfs_help_ipv4_rule_add},
+    {"help_ipv6_dip_rule_add",       sys_help_ipv6_dip_acl_rule_add},
+    {"help_ipv6_gen_rule_add",       sfs_help_ipv6_gen_rule_add},
+    {"help_mc_ipvx_stream_add",      sfs_help_mc_ipvx_stream_add},
+    {"help_igmp_cfg",                sfs_help_igmp_cfg},
+    {"help_no_rule_add",             sfs_help_no_rule_add},
+    {"help_key_rule_delete",         sfs_help_key_rule_delete},
+    {"help_no_mc_stream_add",        sfs_help_no_mc_stream_add},
+    {"help_oam_omci_channel",        sfs_help_oam_omci_channel},
+    {"help_no_oam_omci_channel",     sfs_help_no_oam_omci_channel},
+    {"help_tpm_setup",               sfs_help_setup},
+    {"help_mib_reset",               sfs_help_mib_reset},
+    {"help_cfg_cpu_lpbk",            sfs_help_cfg_cpu_lpbk},
+    {"help_cfg_age_count",           sfs_help_cfg_age_count},
+    {"help_rate_limit",              sfs_help_rate_limit},
+    {"help_pkt_mod_add",             sfs_help_pkt_mod_add},
+    {"help_pkt_mod_get_del_purge",   sfs_help_pkt_mod_get_del_purge},
+    {"help_ipv6_nh_rule_add",        sfs_help_ipv6_nh_rule_add},
+    {"help_ipv6_l4_ports_rule_add",  sfs_help_ipv6_l4_ports_rule_add},
+    {"help_ipv6_l4_key_cfg",         sfs_help_ipv6_l4_key_cfg},
+    {"help_ipv6_dip_key_cfg",        sfs_help_ipv6_dip_key_cfg},
+    {"help_ipv6_gen_key_cfg",	     sfs_help_ipv6_gen_key_cfg},
+    {"help_ipv6_ctc_cm_key_cfg",     sfs_help_ipv6_ctc_cm_key_cfg},
+    {"help_mtu_cfg",                 sfs_help_mtu_cfg},
+    {"help_delete_entry_rule_table", sfs_help_delete_entry_rule_table},
+    {"help_erase_section",           sfs_help_erase_section},
+    {"help_send_genquery_to_uni",    sfs_help_send_genquery_to_uni},
+    {"help_tpm_self_check",          sfs_help_tpm_self_check},
+    {"help_ipv6_gen_5t_rule_add",      sfs_help_ipv6_gen_5t_rule_add},
+    {"help_ipv6_dip_5t_rule_add",      sfs_help_ipv6_dip_5t_rule_add},
+    {"help_ipv6_l4_ports_5t_rule_add", sfs_help_ipv6_l4_ports_5t_rule_add},
+
+    {"help_ctc_cm_rule_add",           sfs_help_ctc_cm_rule_add},
+    {"help_ctc_cm_set_ipv6_parse_win", sfs_help_ctc_cm_set_ipv6_parse_win},
+
+    {"help_flush_atu",               sfs_help_flush_atu},
+    {"help_flush_vtu",               sfs_help_flush_vtu},
+    {"help_mac_learn_rule_add",      sfs_help_mac_learn_rule_add},
+    {"help_mac_learn_def_act_set",   sfs_help_mac_learn_def_act_set},
+
+};
+static int num_show_name_funcs = sizeof(show_sysfs_name_func_ara)/sizeof(show_sysfs_name_func_ara[0]);
+
+
+static ssize_t tpm_cfg_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+    const char*            name = attr->attr.name;
+    show_sysfs_name_func_t *pnamefunc;
+    int                    indx;
+    GT_BOOL                found = GT_FALSE;
+    int                    buflen = 0;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    for (indx = 0; indx < num_show_name_funcs; indx++){
+        pnamefunc = &show_sysfs_name_func_ara[indx];
+        if (!strcmp(name, pnamefunc->sysfs_name)) {
+            found = GT_TRUE;
+            buflen = (pnamefunc->sysfs_func)(buf);
+            break;
+        }
+    }
+    if (found == GT_FALSE){
+        printk("%s: operation <%s> not found\n", __FUNCTION__, attr->attr.name);
+    }
+    return buflen;
+}
+#else
+static ssize_t tpm_cfg_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+	printk(KERN_WARNING "%s: sysfs help is not compiled (CONFIG_MV_TPM_SYSFS_HELP)\n", __FUNCTION__);
+	return 0;
+}
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            Cfg SW Attributes                               */
+/* ========================================================================== */
+
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+// help
+static DEVICE_ATTR(help_tpm_cfg_index,                              S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_frwd_rule_cfg,                              S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_vlan_rule_cfg,                              S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_mod_rule_cfg,                               S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_l2_key_cfg,                                 S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_l3_key_cfg,                                 S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv4_key_cfg,                               S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_gen_key_cfg,                           S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_dip_key_cfg,                           S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_ctc_cm_key_cfg,                        S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_l4_key_cfg,                            S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_rule_table_display,                         S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(help_l2_rule_add,                                S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_mac_learn_rule_add,                         S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_mac_learn_def_act_set,                      S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_l3_rule_add,                                S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv4_rule_add,                              S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_dip_rule_add,                          S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_gen_rule_add,                          S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_nh_rule_add,                           S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_l4_ports_rule_add,                     S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_gen_5t_rule_add,                       S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_dip_5t_rule_add,                       S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ipv6_l4_ports_5t_rule_add,                  S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ctc_cm_rule_add,                            S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_ctc_cm_set_ipv6_parse_win,                  S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_mc_ipvx_stream_add,                         S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_igmp_cfg,                                   S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_no_rule_add,                                S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_key_rule_delete,                            S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_no_mc_stream_add,                           S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_oam_omci_channel,                           S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_no_oam_omci_channel,                        S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_tpm_setup,                                  S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_mib_reset,                                  S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_cfg_cpu_lpbk,                               S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_cfg_age_count,                              S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_rate_limit,                                 S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_pkt_mod_add,                                S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_pkt_mod_get_del_purge,                      S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_mtu_cfg,                                    S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_delete_entry_rule_table,                    S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_erase_section,                              S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_send_genquery_to_uni,                       S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_tpm_self_check,                             S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_flush_atu,                                  S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(help_flush_vtu,                                  S_IRUSR, tpm_cfg_show, tpm_cfg_store);
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+// rule set
+static DEVICE_ATTR(frwd_rule_set,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(vlan_rule_set,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mod_mh_rule_set,                                 S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mod_vlan_rule_set,                               S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mod_ipv4_addr_rule_set,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mod_ipv4_port_rule_set,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mod_ipv6_addr_rule_set,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mod_ipv6_port_rule_set,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mod_pppoe_rule_set,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mod_mac_addr_rule_set,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(l2_key_ethertype_rule_set,                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(l2_key_gemport_rule_set,                         S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(l2_key_mac_addr_rule_set,                        S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(l2_key_pppoe_rule_set,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(l2_key_vlan_rule_set,                            S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(l3_key_ethertype_rule_set,                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(l3_key_pppoe_rule_set,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(ipv4_key_proto_rule_set,                         S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv4_key_dscp_rule_set,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv4_key_addr_rule_set,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv4_key_port_rule_set,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+
+static DEVICE_ATTR(ipv6_gen_key_sip_rule_set,                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_ctc_cm_key_rule_set,                        S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_gen_key_dscp_rule_set,                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_dip_key_rule_set,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_l4_key_rule_set,                            S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(key_rule_delete,                                 S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(rule_table_display,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_l2_rule_table,                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_l3_rule_table,                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_ipv4_rule_table,                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_ipv6_gen_rule_table,                S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_ipv6_dip_rule_table,                S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_ipv6_l4_rule_table,                 S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_frwd_rule_table,                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_vlan_rule_table,                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(delete_entry_mod_rule_table,                     S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+// Rule add
+static DEVICE_ATTR(l2_rule_add,                                     S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mac_learn_rule_add,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mac_learn_default_rule_act_set,                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(l3_rule_add,                                     S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv4_rule_add,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_gen_rule_add,                               S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_dip_rule_add,                               S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_ipv4_stream_add,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_ipv4_stream_update,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_ipv6_stream_add,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_ipv6_stream_update,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_nh_acl_rule_add,                            S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_l4_ports_acl_rule_add,                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(ipv6_gen_5t_rule_add,                            S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_dip_5t_rule_add,                            S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ipv6_l4_ports_5t_rule_add,                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(ctc_cm_acl_rule_add,                             S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ctc_cm_ipv6_acl_rule_add,                        S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(ctc_cm_set_ipv6_parse_win,                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(igmp_port_forward_mode_cfg,                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(igmp_cpu_queue_cfg,                              S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(igmp_proxy_sa_mac,                               S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_vid_key_reset,                                S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_vid_key_set,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mc_vid_cfg_set,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(no_rule_add_l2,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_l3,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_ipv4,                                S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_mc_stream_add_ipv4,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_mc_stream_add_ipv6,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_ipv6_nh_acl,                         S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_ipv6_l4_ports_acl,                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_ipv6_dip_acl,                        S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_ipv6_gen_acl,                        S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(no_rule_add_ipv6_gen_5t,                         S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_ipv6_dip_5t,                         S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_ipv6_l4_ports_5t,                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(no_rule_add_ctc_cm_acl,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_rule_add_mac_learn,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+
+static DEVICE_ATTR(oam_channel,                                     S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(omci_channel,                                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_oam_channel,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(no_omci_channel,                                 S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(tpm_setup,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(mib_reset,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(add_cpu_lpbk,                                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(del_cpu_lpbk,                                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(dump_cpu_lpbk,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(get_lu_entry,                                    S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(set_count_mask,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(get_hit_count,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(get_pnc_all_hit_cntrs,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(set_lu_thresh,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(reset_age_group,                                 S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(rate_limit_queue_set,                            S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(gmac0_ingr_rate_limit_set,                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(scheduling_mode_queue_set,                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(rate_limit_if_set,                               S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(pkt_mod_eng_entry_add,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(pkt_mod_eng_entry_show,                          S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(pkt_mod_eng_entry_del,                           S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(pkt_mod_eng_purge,                               S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(enable_mtu,                                      S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(set_mtu,                                         S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(set_pppoe_mtu,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(send_genquery_to_uni,                            S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(erase_section,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(tpm_self_check,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(flush_atu,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(flush_vtu,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+
+static DEVICE_ATTR(fc_config_set,                                   S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(fc_us_period_set,                                S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+static DEVICE_ATTR(fc_enable,                                       S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+#ifdef TPM_FC_DEBUG
+static DEVICE_ATTR(fc_oneshot_set,                                  S_IWUSR, tpm_cfg_show, tpm_cfg_store);
+#endif
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_mngt SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_mngt_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+
+    &dev_attr_help_oam_omci_channel.attr,
+    &dev_attr_help_no_oam_omci_channel.attr,
+#endif
+    &dev_attr_oam_channel.attr,
+    &dev_attr_omci_channel.attr,
+    &dev_attr_no_oam_channel.attr,
+    &dev_attr_no_omci_channel.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_mngt_sw_group =
+{
+    .name = "cfg_mngt",
+    .attrs = tpm_cfg_mngt_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_mod SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_mod_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_mod_rule_cfg.attr,
+    &dev_attr_help_rule_table_display.attr,
+    &dev_attr_help_pkt_mod_add.attr,
+    &dev_attr_help_pkt_mod_get_del_purge.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_mod_mh_rule_set.attr,
+    &dev_attr_mod_vlan_rule_set.attr,
+    &dev_attr_mod_ipv4_addr_rule_set.attr,
+    &dev_attr_mod_ipv4_port_rule_set.attr,
+    &dev_attr_mod_ipv6_addr_rule_set.attr,
+    &dev_attr_mod_ipv6_port_rule_set.attr,
+    &dev_attr_mod_pppoe_rule_set.attr,
+    &dev_attr_mod_mac_addr_rule_set.attr,
+    &dev_attr_pkt_mod_eng_entry_add.attr,
+    &dev_attr_pkt_mod_eng_entry_show.attr,
+    &dev_attr_pkt_mod_eng_entry_del.attr,
+    &dev_attr_pkt_mod_eng_purge.attr,
+
+    &dev_attr_delete_entry_mod_rule_table.attr,
+    &dev_attr_rule_table_display.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_mod_sw_group =
+{
+    .name = "cfg_mod",
+    .attrs = tpm_cfg_mod_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_l2 SYS FS STORE ROUTINE SWITCHER                       */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_l2_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_l2_key_cfg.attr,
+    &dev_attr_help_rule_table_display.attr,
+    &dev_attr_help_l2_rule_add.attr,
+    &dev_attr_help_no_rule_add.attr,
+    &dev_attr_help_delete_entry_rule_table.attr,
+    &dev_attr_help_mac_learn_rule_add.attr,
+    &dev_attr_help_mac_learn_def_act_set.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_l2_key_ethertype_rule_set.attr,
+    &dev_attr_l2_key_gemport_rule_set.attr,
+    &dev_attr_l2_key_mac_addr_rule_set.attr,
+    &dev_attr_l2_key_pppoe_rule_set.attr,
+    &dev_attr_l2_key_vlan_rule_set.attr,
+
+    &dev_attr_delete_entry_l2_rule_table.attr,
+    &dev_attr_rule_table_display.attr,
+
+    &dev_attr_l2_rule_add.attr,
+    &dev_attr_no_rule_add_l2.attr,
+
+    &dev_attr_mac_learn_rule_add.attr,
+    &dev_attr_mac_learn_default_rule_act_set.attr,
+    &dev_attr_no_rule_add_mac_learn.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_l2_sw_group =
+{
+    .name = "cfg_l2",
+    .attrs = tpm_cfg_l2_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_l3 SYS FS STORE ROUTINE SWITCHER                       */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_l3_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_l3_key_cfg.attr,
+    &dev_attr_help_rule_table_display.attr,
+    &dev_attr_help_l3_rule_add.attr,
+    &dev_attr_help_no_rule_add.attr,
+    &dev_attr_help_delete_entry_rule_table.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_l3_key_ethertype_rule_set.attr,
+    &dev_attr_l3_key_pppoe_rule_set.attr,
+
+    &dev_attr_delete_entry_l3_rule_table.attr,
+    &dev_attr_rule_table_display.attr,
+
+    &dev_attr_l3_rule_add.attr,
+    &dev_attr_no_rule_add_l3.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_l3_sw_group =
+{
+    .name = "cfg_l3",
+    .attrs = tpm_cfg_l3_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_ipv4 SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_ipv4_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_ipv4_key_cfg.attr,
+    &dev_attr_help_rule_table_display.attr,
+    &dev_attr_help_ipv4_rule_add.attr,
+    &dev_attr_help_no_rule_add.attr,
+    &dev_attr_help_delete_entry_rule_table.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_ipv4_key_proto_rule_set.attr,
+    &dev_attr_ipv4_key_dscp_rule_set.attr,
+    &dev_attr_ipv4_key_addr_rule_set.attr,
+    &dev_attr_ipv4_key_port_rule_set.attr,
+
+    &dev_attr_delete_entry_ipv4_rule_table.attr,
+    &dev_attr_rule_table_display.attr,
+
+    &dev_attr_ipv4_rule_add.attr,
+    &dev_attr_no_rule_add_ipv4.attr,
+
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_ipv4_sw_group =
+{
+    .name = "cfg_ipv4",
+    .attrs = tpm_cfg_ipv4_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_ipv6 SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_ipv6_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_ipv6_gen_key_cfg.attr,
+    &dev_attr_help_ipv6_ctc_cm_key_cfg.attr,
+    &dev_attr_help_ipv6_dip_key_cfg.attr,
+    &dev_attr_help_ipv6_l4_key_cfg.attr,
+    &dev_attr_help_rule_table_display.attr,
+    &dev_attr_help_ipv6_gen_rule_add.attr,
+    &dev_attr_help_ipv6_dip_rule_add.attr,
+    &dev_attr_help_ipv6_nh_rule_add.attr,
+    &dev_attr_help_ipv6_l4_ports_rule_add.attr,
+    &dev_attr_help_ipv6_gen_5t_rule_add.attr,
+    &dev_attr_help_ipv6_dip_5t_rule_add.attr,
+    &dev_attr_help_ipv6_l4_ports_5t_rule_add.attr,
+    &dev_attr_help_no_rule_add.attr,
+    &dev_attr_help_delete_entry_rule_table.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_ipv6_dip_key_rule_set.attr,
+    &dev_attr_ipv6_l4_key_rule_set.attr,
+    &dev_attr_ipv6_ctc_cm_key_rule_set.attr,
+    &dev_attr_ipv6_gen_key_sip_rule_set.attr,
+    &dev_attr_ipv6_gen_key_dscp_rule_set.attr,
+    &dev_attr_delete_entry_ipv6_gen_rule_table.attr,
+    &dev_attr_delete_entry_ipv6_dip_rule_table.attr,
+    &dev_attr_delete_entry_ipv6_l4_rule_table.attr,
+    &dev_attr_rule_table_display.attr,
+
+    &dev_attr_ipv6_gen_rule_add.attr,
+    &dev_attr_ipv6_dip_rule_add.attr,
+    &dev_attr_ipv6_nh_acl_rule_add.attr,
+    &dev_attr_ipv6_l4_ports_acl_rule_add.attr,
+    &dev_attr_no_rule_add_ipv6_nh_acl.attr,
+    &dev_attr_no_rule_add_ipv6_l4_ports_acl.attr,
+    &dev_attr_no_rule_add_ipv6_gen_acl.attr,
+    &dev_attr_no_rule_add_ipv6_dip_acl.attr,
+
+    &dev_attr_ipv6_gen_5t_rule_add.attr,
+    &dev_attr_ipv6_dip_5t_rule_add.attr,
+    &dev_attr_ipv6_l4_ports_5t_rule_add.attr,
+    &dev_attr_no_rule_add_ipv6_gen_5t.attr,
+    &dev_attr_no_rule_add_ipv6_dip_5t.attr,
+    &dev_attr_no_rule_add_ipv6_l4_ports_5t.attr,
+
+    NULL
+};
+
+static struct attribute *tpm_cfg_mtu_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_mtu_cfg.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+    &dev_attr_enable_mtu.attr,
+    &dev_attr_set_mtu.attr,
+    &dev_attr_set_pppoe_mtu.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_ipv6_sw_group =
+{
+    .name = "cfg_ipv6",
+    .attrs = tpm_cfg_ipv6_sw_attrs
+};
+
+static struct attribute_group tpm_cfg_mtu_sw_group =
+{
+    .name = "cfg_mtu",
+    .attrs = tpm_cfg_mtu_sw_attrs
+};
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_frwd SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_frwd_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_frwd_rule_cfg.attr,
+    &dev_attr_help_rule_table_display.attr,
+    &dev_attr_help_delete_entry_rule_table.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_frwd_rule_set.attr,
+
+    &dev_attr_delete_entry_frwd_rule_table.attr,
+    &dev_attr_rule_table_display.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_frwd_sw_group =
+{
+    .name = "cfg_frwd",
+    .attrs = tpm_cfg_frwd_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_vlan SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_vlan_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_vlan_rule_cfg.attr,
+    &dev_attr_help_rule_table_display.attr,
+    &dev_attr_help_delete_entry_rule_table.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_vlan_rule_set.attr,
+
+    &dev_attr_delete_entry_vlan_rule_table.attr,
+    &dev_attr_rule_table_display.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_vlan_sw_group =
+{
+    .name = "cfg_vlan",
+    .attrs = tpm_cfg_vlan_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_traffic SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_traffic_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_rate_limit.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_rate_limit_queue_set.attr,
+    &dev_attr_scheduling_mode_queue_set.attr,
+    &dev_attr_rate_limit_if_set.attr,
+    &dev_attr_gmac0_ingr_rate_limit_set.attr,
+    &dev_attr_fc_config_set.attr,
+    &dev_attr_fc_us_period_set.attr,
+    &dev_attr_fc_enable.attr,
+#ifdef TPM_FC_DEBUG
+    &dev_attr_fc_oneshot_set.attr,
+#endif
+
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_traffic_sw_group =
+{
+    .name = "cfg_traffic",
+    .attrs = tpm_cfg_traffic_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_mc SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_mc_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_mc_ipvx_stream_add.attr,
+    &dev_attr_help_igmp_cfg.attr,
+    &dev_attr_help_no_mc_stream_add.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_mc_ipv4_stream_add.attr,
+    &dev_attr_igmp_port_forward_mode_cfg.attr,
+    &dev_attr_igmp_cpu_queue_cfg.attr,
+    &dev_attr_igmp_proxy_sa_mac.attr,
+    &dev_attr_no_mc_stream_add_ipv4.attr,
+    &dev_attr_mc_ipv4_stream_update.attr,
+
+    &dev_attr_mc_vid_key_reset.attr,
+    &dev_attr_mc_vid_key_set.attr,
+    &dev_attr_mc_vid_cfg_set.attr,
+
+    &dev_attr_mc_ipv6_stream_add.attr,
+    &dev_attr_no_mc_stream_add_ipv6.attr,
+    &dev_attr_mc_ipv6_stream_update.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_mc_sw_group =
+{
+    .name = "cfg_mc",
+    .attrs = tpm_cfg_mc_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_misc SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_misc_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_tpm_setup.attr,
+    &dev_attr_help_mib_reset.attr,
+    &dev_attr_help_erase_section.attr,
+    &dev_attr_help_send_genquery_to_uni.attr,
+    &dev_attr_help_tpm_self_check.attr,
+    &dev_attr_help_flush_atu.attr,
+    &dev_attr_help_flush_vtu.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_tpm_setup.attr,
+
+    &dev_attr_send_genquery_to_uni.attr,
+
+    &dev_attr_mib_reset.attr,
+    &dev_attr_erase_section.attr,
+    &dev_attr_tpm_self_check.attr,
+    &dev_attr_flush_vtu.attr,
+    &dev_attr_flush_atu.attr,
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_misc_sw_group =
+{
+    .name = "cfg_misc",
+    .attrs = tpm_cfg_misc_sw_attrs
+};
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_cpu_lpbk SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_cpu_lpbk_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_cfg_cpu_lpbk.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+    &dev_attr_add_cpu_lpbk.attr,
+    &dev_attr_del_cpu_lpbk.attr,
+    &dev_attr_dump_cpu_lpbk.attr,
+    NULL
+};
+
+static struct attribute_group tpm_cfg_cpu_lpbk_sw_group =
+{
+    .name = "cfg_cpu_lpbk",
+    .attrs = tpm_cfg_cpu_lpbk_sw_attrs
+};
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_age_count SYS FS STORE ROUTINE SWITCHER                */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_age_count_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_cfg_age_count.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+    &dev_attr_get_lu_entry.attr,
+    &dev_attr_set_count_mask.attr,
+    &dev_attr_get_hit_count.attr,
+    &dev_attr_get_pnc_all_hit_cntrs.attr,
+    &dev_attr_set_lu_thresh.attr,
+    &dev_attr_reset_age_group.attr,
+    NULL
+};
+
+static struct attribute_group tpm_cfg_age_count_sw_group =
+{
+    .name = "cfg_age_count",
+    .attrs = tpm_cfg_age_count_sw_attrs
+};
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg_ctc_cm SYS FS STORE ROUTINE SWITCHER                     */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_ctc_cm_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_ctc_cm_rule_add.attr,
+    &dev_attr_help_ctc_cm_set_ipv6_parse_win.attr,
+    &dev_attr_help_no_rule_add.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+    &dev_attr_ctc_cm_acl_rule_add.attr,
+    &dev_attr_ctc_cm_ipv6_acl_rule_add.attr,
+    &dev_attr_ctc_cm_set_ipv6_parse_win.attr,
+    &dev_attr_no_rule_add_ctc_cm_acl.attr,
+    NULL
+};
+
+static struct attribute_group tpm_cfg_ctc_cm_sw_group =
+{
+    .name = "cfg_ctc_cm",
+    .attrs = tpm_cfg_ctc_cm_sw_attrs
+};
+
+//#if 0
+
+// !!@@##$$%%
+//
+// KEEP THIS - WE MAY GO BACK TO FLAT cfg FOLDER
+//
+// !!@@##$$%%
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg SYS FS STORE ROUTINE SWITCHER                          */
+/* ========================================================================== */
+
+static struct attribute *tpm_cfg_flat_sw_attrs[] =
+{
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_tpm_cfg_index.attr,
+    &dev_attr_help_frwd_rule_cfg.attr,
+    &dev_attr_help_vlan_rule_cfg.attr,
+    &dev_attr_help_mod_rule_cfg.attr,
+    &dev_attr_help_l2_key_cfg.attr,
+    &dev_attr_help_l3_key_cfg.attr,
+    &dev_attr_help_ipv4_key_cfg.attr,
+    &dev_attr_help_ipv6_l4_key_cfg.attr,
+    &dev_attr_help_ipv6_ctc_cm_key_cfg.attr,
+    &dev_attr_help_ipv6_dip_key_cfg.attr,
+    &dev_attr_help_ipv6_gen_key_cfg.attr,
+    &dev_attr_help_rule_table_display.attr,
+
+    &dev_attr_help_l2_rule_add.attr,
+    &dev_attr_help_l3_rule_add.attr,
+    &dev_attr_help_ipv4_rule_add.attr,
+    &dev_attr_help_ipv6_gen_rule_add.attr,
+    &dev_attr_help_ipv6_dip_rule_add.attr,
+    &dev_attr_help_ipv6_nh_rule_add.attr,
+    &dev_attr_help_ipv6_l4_ports_rule_add.attr,
+    &dev_attr_help_mc_ipvx_stream_add.attr,
+    &dev_attr_help_igmp_cfg.attr,
+    &dev_attr_help_no_rule_add.attr,
+    &dev_attr_help_key_rule_delete.attr,
+    &dev_attr_help_no_mc_stream_add.attr,
+    &dev_attr_help_oam_omci_channel.attr,
+    &dev_attr_help_no_oam_omci_channel.attr,
+    &dev_attr_help_tpm_setup.attr,
+    &dev_attr_help_mib_reset.attr,
+    &dev_attr_help_cfg_cpu_lpbk.attr,
+    &dev_attr_help_rate_limit.attr,
+    &dev_attr_help_pkt_mod_add.attr,
+    &dev_attr_help_pkt_mod_get_del_purge.attr,
+
+    &dev_attr_help_ipv6_gen_5t_rule_add.attr,
+    &dev_attr_help_ipv6_dip_5t_rule_add.attr,
+    &dev_attr_help_ipv6_l4_ports_5t_rule_add.attr,
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+    &dev_attr_frwd_rule_set.attr,
+
+    &dev_attr_vlan_rule_set.attr,
+    &dev_attr_mod_vlan_rule_set.attr,
+    &dev_attr_mod_ipv4_addr_rule_set.attr,
+    &dev_attr_mod_ipv4_port_rule_set.attr,
+    &dev_attr_mod_ipv6_addr_rule_set.attr,
+    &dev_attr_mod_ipv6_port_rule_set.attr,
+    &dev_attr_mod_pppoe_rule_set.attr,
+    &dev_attr_mod_mac_addr_rule_set.attr,
+
+    &dev_attr_l2_key_ethertype_rule_set.attr,
+    &dev_attr_l2_key_gemport_rule_set.attr,
+    &dev_attr_l2_key_mac_addr_rule_set.attr,
+    &dev_attr_l2_key_pppoe_rule_set.attr,
+    &dev_attr_l2_key_vlan_rule_set.attr,
+
+    &dev_attr_l3_key_ethertype_rule_set.attr,
+    &dev_attr_l3_key_pppoe_rule_set.attr,
+
+    &dev_attr_ipv4_key_proto_rule_set.attr,
+    &dev_attr_ipv4_key_dscp_rule_set.attr,
+    &dev_attr_ipv4_key_addr_rule_set.attr,
+    &dev_attr_ipv4_key_port_rule_set.attr,
+
+    &dev_attr_ipv6_ctc_cm_key_rule_set.attr,
+    &dev_attr_ipv6_gen_key_sip_rule_set.attr,
+    &dev_attr_ipv6_gen_key_dscp_rule_set.attr,
+    &dev_attr_ipv6_dip_key_rule_set.attr,
+    &dev_attr_ipv6_l4_key_rule_set.attr,
+
+    &dev_attr_key_rule_delete.attr,
+    &dev_attr_rule_table_display.attr,
+
+    &dev_attr_l2_rule_add.attr,
+    &dev_attr_l3_rule_add.attr,
+    &dev_attr_ipv4_rule_add.attr,
+    &dev_attr_ipv6_gen_rule_add.attr,
+    &dev_attr_ipv6_dip_rule_add.attr,
+    &dev_attr_mc_ipv4_stream_add.attr,
+    &dev_attr_mc_ipv4_stream_update.attr,
+    &dev_attr_mc_ipv6_stream_add.attr,
+    &dev_attr_mc_ipv6_stream_update.attr,
+    &dev_attr_ipv6_nh_acl_rule_add.attr,
+    &dev_attr_ipv6_l4_ports_acl_rule_add.attr,
+
+    &dev_attr_ipv6_gen_5t_rule_add.attr,
+    &dev_attr_ipv6_dip_5t_rule_add.attr,
+    &dev_attr_ipv6_l4_ports_5t_rule_add.attr,
+
+    &dev_attr_igmp_port_forward_mode_cfg.attr,
+    &dev_attr_igmp_cpu_queue_cfg.attr,
+    &dev_attr_igmp_proxy_sa_mac.attr,
+
+    &dev_attr_no_rule_add_l2.attr,
+    &dev_attr_no_rule_add_l3.attr,
+    &dev_attr_no_rule_add_ipv4.attr,
+    &dev_attr_no_rule_add_ipv6_nh_acl.attr,
+    &dev_attr_no_rule_add_ipv6_l4_ports_acl.attr,
+    &dev_attr_no_rule_add_ipv6_gen_acl.attr,
+    &dev_attr_no_mc_stream_add_ipv6.attr,
+    &dev_attr_no_mc_stream_add_ipv4.attr,
+
+    &dev_attr_no_rule_add_ipv6_gen_5t.attr,
+    &dev_attr_no_rule_add_ipv6_dip_5t.attr,
+    &dev_attr_no_rule_add_ipv6_l4_ports_5t.attr,
+
+    &dev_attr_oam_channel.attr,
+    &dev_attr_omci_channel.attr,
+    &dev_attr_no_oam_channel.attr,
+    &dev_attr_no_omci_channel.attr,
+
+    &dev_attr_tpm_setup.attr,
+    &dev_attr_mib_reset.attr,
+
+    &dev_attr_rate_limit_queue_set.attr,
+    &dev_attr_scheduling_mode_queue_set.attr,
+    &dev_attr_rate_limit_if_set.attr,
+    &dev_attr_pkt_mod_eng_entry_add.attr,
+    &dev_attr_pkt_mod_eng_entry_show.attr,
+    &dev_attr_pkt_mod_eng_entry_del.attr,
+    &dev_attr_pkt_mod_eng_purge.attr,
+
+
+    NULL
+};
+
+static struct attribute_group tpm_cfg_flat_sw_group =
+{
+    .name = "cfg_flat",
+    .attrs = tpm_cfg_flat_sw_attrs
+};
+//#endif
+
+
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*             TPM cfg SETUP: incl. folder creation + FS population           */
+/* ========================================================================== */
+
+typedef struct
+{
+    char                   *folder_name;
+    struct attribute_group *pattrgroup;
+} attr_group_pair_t;
+
+static attr_group_pair_t attr_group_pair_ara[] =
+{
+    {"cfg_mngt",               &tpm_cfg_mngt_sw_group},
+    {"cfg_mod",                &tpm_cfg_mod_sw_group},
+    {"cfg_frwd",               &tpm_cfg_frwd_sw_group},
+    {"cfg_vlan",               &tpm_cfg_vlan_sw_group},
+    {"cfg_l2",                 &tpm_cfg_l2_sw_group},
+    {"cfg_l3",                 &tpm_cfg_l3_sw_group},
+    {"cfg_ipv4",               &tpm_cfg_ipv4_sw_group},
+    {"cfg_ipv6",               &tpm_cfg_ipv6_sw_group},
+    {"cfg_mc",                 &tpm_cfg_mc_sw_group},
+    {"cfg_traffic",            &tpm_cfg_traffic_sw_group},
+    {"cfg_misc",               &tpm_cfg_misc_sw_group},
+    {"cfg_cpu_lpbk",           &tpm_cfg_cpu_lpbk_sw_group},
+    {"cfg_age_count",          &tpm_cfg_age_count_sw_group},
+    {"cfg_flat",               &tpm_cfg_flat_sw_group},
+    {"cfg_mtu",                &tpm_cfg_mtu_sw_group},
+    {"cfg_ctc_cm",             &tpm_cfg_ctc_cm_sw_group},
+};
+static int num_attr_group_pairs = sizeof(attr_group_pair_ara)/sizeof(attr_group_pair_ara[0]);
+
+int tpm_sysfs_init(void)
+{
+    int           err;
+    struct device *pd;
+    int           indx;
+
+    tpm_sysfs_rule_db_init();
+
+    pd = bus_find_device_by_name(&platform_bus_type, NULL, "tpm");
+    if (!pd) {
+        platform_device_register_simple("tpm", -1, NULL, 0);
+        pd = bus_find_device_by_name(&platform_bus_type, NULL, "tpm");
+    }
+
+    if (!pd) {
+        printk(KERN_ERR"%s: cannot find tpm device\n", __FUNCTION__);
+        pd = &platform_bus;
+    }
+
+    for (indx = 0; indx < num_attr_group_pairs; indx++)
+    {
+        attr_group_pair_t *ppair;
+
+        ppair = &attr_group_pair_ara[indx];
+
+        err = sysfs_create_group(&pd->kobj, ppair->pattrgroup);
+        if (err)
+        {
+            printk(KERN_INFO "sysfs_create_group failed for %s, err = %d\n", ppair->folder_name, err);
+            goto out;
+        }
+    }
+    printk(KERN_INFO "= SW Module SYS FS Init for tpm ended successfully =\n");
+
+out:
+    return err;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.h
new file mode 100755
index 0000000..96aabe8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_setup.h
@@ -0,0 +1,89 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_sysfs_setup.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   Zeev
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               $Revision: 1.1.1.1 $
+*
+*
+*******************************************************************************/
+#ifndef _TPM_USR_TPM_SYSFS_SETUP_H_
+#define _TPM_USR_TPM_SYSFS_SETUP_H_
+
+extern int tpm_sysfs_init(void);
+
+
+#endif  /* _TPM_USR_TPM_SYSFS_SETUP_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.c
new file mode 100755
index 0000000..be993dc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.c
@@ -0,0 +1,1874 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_sysfs_utils.h"
+
+tpm_mc_vid_port_vid_set_t mc_vid_key;
+
+
+uint8_t g_gen_query_pkt[] =
+{
+	0x01, 0x00, 0x5E, 0x00, 0x00, 0x01,
+	0x54, 0xE6, 0xFC, 0x63, 0x36, 0x74,
+	0xda, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reserve for Ethertype DSA tag */
+	0x81, 0x00, 0x00, 0x11,
+	0x08, 0x00, 0x46, 0xEE, 0x00, 0x20,
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+	0x82, 0x3F, 0xC0, 0xA8, 0x01, 0x01,
+	0xE0, 0x00, 0x00, 0x01, 0x94, 0x04,
+	0x00, 0x00, 0x11, 0x64, 0xEE, 0x9B,
+	0x00, 0x00, 0x00, 0x00, 0x9E, 0xA0,
+	0x01, 0x00, 0x5E, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x54, 0xE6, 0xFC, 0x63,
+	0x70, 0xF7, 0xDC, 0x59
+};
+
+/********************************************************************************/
+/*                          Miscellaneous                   */
+/********************************************************************************/
+
+/*******************************************************************************
+* print_help_buffer
+*
+* DESCRIPTION:
+*           This function prints help buffer
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void print_help_buffer(char *helpbuf, int len)
+{
+#if 1
+    int  indx;
+    char savech;
+
+    for (indx = 0; indx < len; indx += 1000)
+    {
+        if (indx + 1000 < len)
+        {
+            savech = helpbuf[indx + 1000];
+            helpbuf[indx + 1000] = 0;
+            printk(KERN_INFO "%s", &helpbuf[indx]);
+            helpbuf[indx + 1000] = savech;
+        }
+        else
+        {
+            printk(KERN_INFO "%s", &helpbuf[indx]);
+        }
+    }
+#else
+    printk(KERN_INFO "%s", helpbuf);
+#endif
+}
+
+/*******************************************************************************
+* parm_error_completion
+*
+* DESCRIPTION:
+*           This function prints out help message if buffer holds 1 parameter that
+*           starts '?'; else it prints out incorrect number of parameters message
+* INPUTS:
+*       buf	- Shell parameters as char buffer
+*       len - Number of characters in buffer
+*
+*******************************************************************************/
+void parm_error_completion(int numparms, int reqdparms, const char *buf, int (*help_text_routine)(char *))
+{
+    if (numparms == 1 && buf[0] == '?' && help_text_routine != NULL)
+    {
+        char helpbuf[4000];
+        int  helpbuf_len;
+
+        helpbuf_len = help_text_routine(helpbuf);
+        print_help_buffer(helpbuf, helpbuf_len);
+    }
+    else
+    {
+        printk(KERN_INFO "Parse problem: parameters expected/found %d/%d\n", reqdparms, numparms);
+    }
+}
+
+/*******************************************************************************
+* count_parameters
+*
+* DESCRIPTION:
+*           This function counts the number of parameters provided
+* INPUTS:
+*       buf	- buffer with parameter string
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       int
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+int count_parameters (const char *buf)
+{
+    char                bufcopy[513];
+    char                **ap, *argv[20];
+    char                *inputstring = bufcopy;
+    int                 numparms = 0;
+
+    strcpy(bufcopy, buf);
+
+    for (ap = argv; ap < &argv[15] && (*ap = strsep(&inputstring, " \t")) != NULL;)
+    {
+        if (**ap != '\0')
+        {
+            ap++;
+            numparms++;
+        }
+    }
+    return numparms;
+}
+
+/*******************************************************************************
+* print_horizontal_line
+*
+* DESCRIPTION:
+*           This function prints a horizontal line using the "=" sign and places CRLF
+* INPUTS:
+*       char_count  - the horizontal line length
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       int
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void print_horizontal_line(unsigned int char_count)
+{
+    unsigned int cnt;
+    for (cnt = 0; cnt < char_count; cnt++)
+        printk("=");
+    printk("\n");
+}
+
+/********************************************************************************/
+/*                          String-int map lookups                              */
+/********************************************************************************/
+
+
+/*******************************************************************************
+* map_string_to_value
+*
+* DESCRIPTION:
+*           This function maps a string in a given map table to its value
+* INPUTS:
+*       buf	- buffer with parameter string
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       int
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+static GT_BOOL map_string_to_value (string_enum_pair_db_t *db, char *str, unsigned int *value)
+{
+    int                indx;
+    string_enum_pair_t *pentry;
+
+    for (indx = 0; indx < db->num_entries; indx++)
+    {
+        pentry = &db->string_enum_pair[indx];
+        if (strcmp(str, pentry->str) == 0)
+        {
+            *value = pentry->value;
+            return GT_TRUE;
+        }
+    }
+    return GT_FALSE;
+}
+
+/*******************************************************************************
+* map_value_to_string
+*
+* DESCRIPTION:
+*           This function maps a value to string in a given map table
+* INPUTS:
+*       value	- int enumaeration
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       char *. The matching string or "<unknown>"
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+static char *map_value_to_string (string_enum_pair_db_t *db, int value)
+{
+    int                indx;
+    string_enum_pair_t *pentry;
+    static char *unknown_str = "<unknown>";
+
+    for (indx = 0; indx < db->num_entries; indx++)
+    {
+        pentry = &db->string_enum_pair[indx];
+        if (value == pentry->value)
+        {
+            return pentry->str;
+        }
+    }
+    return unknown_str;
+}
+
+//--------------------------------------------------------------------------
+
+static string_enum_pair_t phase_string_enum_pair_ara[] =
+{
+    {STAGE_L2_PRIM,  "l2"   },
+    {STAGE_L3_TYPE,  "l3"   },
+    {STAGE_IPv4,     "ipv4" },
+    {STAGE_IPv6_GEN,   "ipv6_gen" },
+    {STAGE_IPv6_DIP,   "ipv6_dip" },
+    {STAGE_IPv6_NH,    "ipv6_nh"  },
+	{STAGE_IPV6_L4,    "ipv6_l4"  },
+    {STAGE_CTC_CM,    "ctc_cm"  },
+    {STAGE_DONE,     "done" },
+};
+
+static string_enum_pair_db_t  phase_string_enum_pair_db =
+{
+    phase_string_enum_pair_ara,
+    sizeof(phase_string_enum_pair_ara)/sizeof(phase_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_phase_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&phase_string_enum_pair_db, str, value);
+}
+
+//---------------------------------------------------------------------------
+
+static string_enum_pair_t srcport_string_enum_pair_ara[] =
+{
+	{TPM_SRC_PORT_UNI_0,    "UNI_0"   },
+	{TPM_SRC_PORT_UNI_1,    "UNI_1"   },
+	{TPM_SRC_PORT_UNI_2,    "UNI_2"   },
+	{TPM_SRC_PORT_UNI_3,    "UNI_3"   },
+	{TPM_SRC_PORT_UNI_4,    "UNI_4"   },
+	{TPM_SRC_PORT_UNI_5,    "UNI_5"   },
+	{TPM_SRC_PORT_UNI_6,    "UNI_6"   },
+	{TPM_SRC_PORT_UNI_7,    "UNI_7"   },
+	{TPM_SRC_PORT_UNI_VIRT, "UNI_VIRT" },
+	{TPM_SRC_PORT_WAN,      "WAN"     },
+	{TPM_SRC_PORT_UNI_ANY,  "UNI_ANY" },
+};
+
+static string_enum_pair_db_t  srcport_string_enum_pair_db =
+{
+    srcport_string_enum_pair_ara,
+    sizeof(srcport_string_enum_pair_ara)/sizeof(srcport_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_srcport_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&srcport_string_enum_pair_db, str, value);
+}
+
+//---------------------------------------------------------------------------
+
+static string_enum_pair_t srcdir_string_enum_pair_ara[] =
+{
+    {TPM_DIR_DS,            "DS" },
+    {TPM_DIR_US,            "US" },
+};
+
+static string_enum_pair_db_t srcdir_string_enum_pair_db =
+{
+    srcdir_string_enum_pair_ara,
+    sizeof(srcdir_string_enum_pair_ara)/sizeof(srcdir_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_srcdir_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&srcdir_string_enum_pair_db, str, value);
+}
+
+//-----------------------------------------------------------------------------
+
+static string_enum_pair_t bool_string_enum_pair_ara[] =
+{
+    {GT_FALSE,  "false"},
+    {GT_TRUE,   "true" },
+};
+
+static string_enum_pair_db_t  bool_string_enum_pair_db =
+{
+    bool_string_enum_pair_ara,
+    sizeof(bool_string_enum_pair_ara)/sizeof(bool_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_bool_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&bool_string_enum_pair_db, str, value);
+}
+
+//---------------------------------------------------------------------------
+
+static string_enum_pair_t igmp_mode_string_enum_pair_ara[] =
+{
+    {TPM_IGMP_FRWD_MODE_DROP,       "drop" },
+    {TPM_IGMP_FRWD_MODE_FORWARD,    "frwd" },
+    {TPM_IGMP_FRWD_MODE_SNOOPING,   "snoop"},
+};
+
+static string_enum_pair_db_t  igmp_mode_string_enum_pair_db =
+{
+    igmp_mode_string_enum_pair_ara,
+    sizeof(igmp_mode_string_enum_pair_ara)/sizeof(igmp_mode_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_igmp_mode_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&igmp_mode_string_enum_pair_db, str, value);
+}
+
+//---------------------------------------------------------------------------
+
+static string_enum_pair_t igmp_srcport_string_enum_pair_ara[] =
+{
+    {TPM_SRC_PORT_WAN,      "WAN"     },
+    {TPM_SRC_PORT_UNI_0,    "UNI_0"   },
+    {TPM_SRC_PORT_UNI_1,    "UNI_1"   },
+    {TPM_SRC_PORT_UNI_2,    "UNI_2"   },
+    {TPM_SRC_PORT_UNI_3,    "UNI_3"   },
+};
+
+static string_enum_pair_db_t  igmp_srcport_string_enum_pair_db =
+{
+    igmp_srcport_string_enum_pair_ara,
+    sizeof(igmp_srcport_string_enum_pair_ara)/sizeof(igmp_srcport_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_igmp_srcport_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&igmp_srcport_string_enum_pair_db, str, value);
+}
+
+//---------------------------------------------------------------------------
+
+static string_enum_pair_t lx_ipvy_string_enum_pair_ara[] =
+{
+    {TPM_SRC_PORT_WAN,      "l2"     },
+    {TPM_SRC_PORT_UNI_0,    "l3"     },
+    {TPM_SRC_PORT_UNI_1,    "ipv4"   },
+    {TPM_SRC_PORT_UNI_2,    "ipv6"   },
+};
+
+static string_enum_pair_db_t  lx_ipvy_string_enum_pair_db =
+{
+    lx_ipvy_string_enum_pair_ara,
+    sizeof(lx_ipvy_string_enum_pair_ara)/sizeof(lx_ipvy_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_lx_ipvy_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&lx_ipvy_string_enum_pair_db, str, value);
+}
+
+//---------------------------------------------------------------------------
+static string_enum_pair_t direction_string_enum_pair_ara[] =
+{
+    {TPM_DOWNSTREAM,      "ds"  },
+    {TPM_UPSTREAM,        "us"  },
+};
+
+static string_enum_pair_db_t  direction_string_enum_pair_db =
+{
+    direction_string_enum_pair_ara,
+    sizeof(direction_string_enum_pair_ara)/sizeof(direction_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_direction_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&direction_string_enum_pair_db, str, value);
+}
+
+//-----------------------------------------------------------------------------
+static string_enum_pair_t scheduling_mode_string_enum_pair_ara[] =
+{
+    {TPM_PP_SCHED_STRICT,      "strict"  },
+    {TPM_PP_SCHED_WRR,         "wrr"     },
+};
+
+static string_enum_pair_db_t  scheduling_mode_string_enum_pair_db =
+{
+    scheduling_mode_string_enum_pair_ara,
+    sizeof(scheduling_mode_string_enum_pair_ara)/sizeof(scheduling_mode_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_scheduling_mode_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&scheduling_mode_string_enum_pair_db, str, value);
+}
+
+//-----------------------------------------------------------------------------
+static string_enum_pair_t sched_entity_string_enum_pair_ara[] =
+{
+    {TPM_TRG_PORT_WAN,       "WAN"      },
+    {TPM_TRG_TCONT_0,        "TCONT_0"  },
+    {TPM_TRG_TCONT_1,        "TCONT_1"  },
+    {TPM_TRG_TCONT_2,        "TCONT_2"  },
+    {TPM_TRG_TCONT_3,        "TCONT_3"  },
+    {TPM_TRG_TCONT_4,        "TCONT_4"  },
+    {TPM_TRG_TCONT_5,        "TCONT_5"  },
+    {TPM_TRG_TCONT_6,        "TCONT_6"  },
+    {TPM_TRG_TCONT_7,        "TCONT_7"  },
+    {TPM_TRG_PORT_UNI_ANY,   "UNI_ANY"  },
+};
+
+static string_enum_pair_db_t  sched_entity_string_enum_pair_db =
+{
+    sched_entity_string_enum_pair_ara,
+    sizeof(sched_entity_string_enum_pair_ara)/sizeof(sched_entity_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_sched_entity_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&sched_entity_string_enum_pair_db, str, value);
+}
+
+//-----------------------------------------------------------------------------
+static string_enum_pair_t vlan_op_string_enum_pair_ara[] =
+{
+    {0,    "none"                },
+    {1,    "ext_tag_mod"         },
+    {2,    "ext_tag_del"         },
+    {3,    "ext_tag_ins"         },
+    {4,    "ext_tag_mod_ins"     },
+    {5,    "ins_2tag"            },
+    {6,    "mod_2tag"            },
+    {7,    "swap_tags"           },
+    {8,    "del_2tags"           },
+    {9,    "int_tag_mod"         },
+    {10,   "ext_tag_del_int_mod" },
+	{11,   "split_mod_pbit"      },
+};
+
+static string_enum_pair_db_t  vlan_op_string_enum_pair_db =
+{
+    vlan_op_string_enum_pair_ara,
+    sizeof(vlan_op_string_enum_pair_ara)/sizeof(vlan_op_string_enum_pair_ara[0])
+};
+
+GT_BOOL get_vlan_op_value(char *str, unsigned int *value)
+{
+    return map_string_to_value(&vlan_op_string_enum_pair_db, str, value);
+}
+
+char *get_vlan_op_str(int value)
+{
+    return map_value_to_string(&vlan_op_string_enum_pair_db, value);
+}
+
+//-----------------------------------------------------------------------------
+
+static string_enum_pair_t tpm_err_string_enum_pair_ara[] =
+{
+    {TPM_RC_OK,                         "TPM_RC_OK"},
+    {ERR_GENERAL,                       "ERR_GENERAL"},
+    {ERR_OWNER_INVALID,                 "ERR_OWNER_INVALID"},
+    {ERR_SRC_PORT_INVALID,              "ERR_SRC_PORT_INVALID"},
+    {ERR_RULE_NUM_INVALID,              "ERR_RULE_NUM_INVALID"},
+    {ERR_RULE_IDX_INVALID,              "ERR_RULE_IDX_INVALID"},
+    {ERR_PARSE_MAP_INVALID,             "ERR_PARSE_MAP_INVALID"},
+    {ERR_VLAN_OP_INVALID,               "ERR_VLAN_OP_INVALID"},
+    {ERR_L2_KEY_INVALID,                "ERR_L2_KEY_INVALID"},
+    {ERR_FRWD_INVALID,                  "ERR_FRWD_INVALID"},
+    {ERR_MOD_INVALID,                   "ERR_MOD_INVALID"},
+    {ERR_ACTION_INVALID,                "ERR_ACTION_INVALID"},
+    {ERR_NEXT_PHASE_INVALID,            "ERR_NEXT_PHASE_INVALID"},
+    {ERR_RULE_KEY_MISMATCH,             "ERR_RULE_KEY_MISMATCH"},
+    {ERR_IPV4_NO_CONT_L4,               "ERR_IPV4_NO_CONT_L4"},
+    {ERR_IPV6_ADD_FAIL,                 "ERR_IPV6_ADD_FAIL"},
+    {ERR_MC_STREAM_INVALID,             "ERR_MC_STREAM_INVALID"},
+    {ERR_MC_STREAM_EXISTS ,             "ERR_MC_STREAM_EXISTS "},
+    {ERR_MC_DST_PORT_INVALID,           "ERR_MC_DST_PORT_INVALID"},
+    {ERR_IPV4_MC_DST_IP_INVALID,        "ERR_IPV4_MC_DST_IP_INVALID"},
+    {ERR_IPV6_MC_DST_IP_INVALID,        "ERR_IPV6_MC_DST_IP_INVALID"},
+    {ERR_OMCI_TCONT_INVALID,            "ERR_OMCI_TCONT_INVALID"},
+    {ERR_MNGT_TX_Q_INVALID,             "ERR_MNGT_TX_Q_INVALID"},
+    {ERR_MNGT_CREATE_DUPLICATE_CHANNEL, "ERR_MNGT_CREATE_DUPLICATE_CHANNEL"},
+    {ERR_MNGT_DEL_CHANNEL_INVALID,      "ERR_MNGT_DEL_CHANNEL_INVALID"},
+    {ERR_OAM_LLID_INVALID,              "ERR_OAM_LLID_INVALID"},
+    {ERR_CFG_GETNEXT_INDEX_INVALID,     "ERR_CFG_GETNEXT_INDEX_INVALID"},
+    {ERR_CFG_GETNEXT_DIRECTION_INVALID, "ERR_CFG_GETNEXT_DIRECTION_INVALID"},
+    {ERR_CFG_GET_CHANNEL_INVALID,       "ERR_CFG_GET_CHANNEL_INVALID"},
+    {ERR_SW_MAC_INVALID,                "ERR_SW_MAC_INVALID"},
+    {ERR_SW_MAC_STATIC_NOT_FOUND,       "ERR_SW_MAC_STATIC_NOT_FOUND"},
+    {ERR_SW_MAC_PER_PORT_INVALID,       "ERR_SW_MAC_PER_PORT_INVALID"},
+    {ERR_SW_NUM_OF_MAC_PER_PORT_INVALID,"ERR_SW_NUM_OF_MAC_PER_PORT_INVALID"},
+    {ERR_SW_VID_INVALID,                "ERR_SW_VID_INVALID"},
+    {ERR_SW_TM_QUEUE_INVALID,           "ERR_SW_TM_QUEUE_INVALID"},
+    {ERR_SW_TM_WEIGHT_INVALID,          "ERR_SW_TM_WEIGHT_INVALID"},
+    {ERR_SW_TM_WRR_MODE_INVALID,        "ERR_SW_TM_WRR_MODE_INVALID"},
+    {ERR_API_TYPE_INVALID,              "ERR_API_TYPE_INVALID"},
+    {ERR_DIR_INVALID,                   "ERR_DIR_INVALID"},
+    {ERR_NULL_POINTER,                  "ERR_NULL_POINTER"},
+    {ERR_IGMP_NOT_ENABLED,              "ERR_IGMP_NOT_ENABLED"},
+    {ERR_OUT_OF_RESOURCES,              "ERR_OUT_OF_RESOURCES"},
+    {ERR_AI_SESS_EXISTS,                "ERR_AI_SESS_EXISTS"},
+    {ERR_AI_SESS_DELETING,              "ERR_AI_SESS_DELETING"},
+    {ERR_SW_TM_BUCKET_SIZE_INVALID,     "ERR_SW_TM_BUCKET_SIZE_INVALID"},
+    {ERR_SW_TM_RATE_LIMIT_INVALID,      "ERR_SW_TM_RATE_LIMIT_INVALID"},
+    {ERR_DELETE_KEY_INVALID,            "ERR_DELETE_KEY_INVALID"},
+    {ERR_L3_KEY_INVALID,                "ERR_L3_KEY_INVALID"},
+    {ERR_IPV4_KEY_INVALID,              "ERR_IPV4_KEY_INVALID"},
+    {ERR_IPV6_KEY_INVALID,              "ERR_IPV6_KEY_INVALID"},
+    {ERR_PORT_IGMP_FRWD_MODE_INVALID,   "ERR_PORT_IGMP_FRWD_MODE_INVALID"},
+    {ERR_IPV6_API_ILLEGAL_CALL,         "ERR_IPV6_API_ILLEGAL_CALL"},
+    {ERR_IPV6_5T_RULE_EXISTS,           "ERR_IPV6_5T_RULE_EXISTS"},
+    {ERR_IPV6_5T_FLOW_PARTIAL_MATCHED,  "ERR_IPV6_5T_FLOW_PARTIAL_MATCHED"},
+    {ERR_IPV6_5T_RULE_IN_USE,           "ERR_IPV6_5T_RULE_IN_USE"},
+    {ERR_IPV6_5T_FLOW_AI_BITS_EXHAUSED, "ERR_IPV6_5T_FLOW_AI_BITS_EXHAUSED"},
+    {ERR_SW_NOT_INIT,                   "ERR_SW_NOT_INIT"},
+};
+
+
+static string_enum_pair_db_t  tpm_err_string_enum_pair_db =
+{
+    tpm_err_string_enum_pair_ara,
+    sizeof(tpm_err_string_enum_pair_ara)/sizeof(tpm_err_string_enum_pair_ara[0])
+};
+
+char *get_tpm_err_str(int value)
+{
+    return map_value_to_string(&tpm_err_string_enum_pair_db, value);
+}
+
+
+/*******************************************************************************
+
+* parse_ipv4_address
+*
+* DESCRIPTION:
+*           This function parses IPV4 address
+* INPUTS:
+*       buf	- buffer with parameter string
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       GT_BOOL
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_BOOL parse_ipv4_address (char *buf, uint32_t *ipv4addr_parts)
+{
+    if (4 == sscanf(buf, "%d.%d.%d.%d", &ipv4addr_parts[0], &ipv4addr_parts[1], &ipv4addr_parts[2], &ipv4addr_parts[3]))
+    {
+        if (ipv4addr_parts[0] <= 255 && ipv4addr_parts[1] <= 255 && ipv4addr_parts[2] <= 255 && ipv4addr_parts[3] <= 255)
+        {
+            return GT_TRUE;
+        }
+    }
+    return GT_FALSE;
+}
+
+/*******************************************************************************
+* parse_ipv6_address
+*
+* DESCRIPTION:
+*           This function parses IPV4 address
+* INPUTS:
+*       buf	- buffer with parameter string
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       GT_BOOL
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_BOOL parse_ipv6_address (char *buf, uint32_t *ipv6addr_parts)
+{
+    if (8 == sscanf(buf, "%x:%x:%x:%x:%x:%x:%x:%x",
+                    &ipv6addr_parts[0], &ipv6addr_parts[2],  &ipv6addr_parts[4],  &ipv6addr_parts[6],
+                    &ipv6addr_parts[8], &ipv6addr_parts[10], &ipv6addr_parts[12], &ipv6addr_parts[14]));
+    {
+        if (ipv6addr_parts[0] <= 0xFFFF && ipv6addr_parts[2] <= 0xFFFF  && ipv6addr_parts[4] <= 0xFFFF  && ipv6addr_parts[6] <= 0xFFFF &&
+            ipv6addr_parts[8] <= 0xFFFF && ipv6addr_parts[10] <= 0xFFFF && ipv6addr_parts[12] <= 0xFFFF && ipv6addr_parts[14] <= 0xFFFF)
+        {
+            // Note the order
+            ipv6addr_parts[1]  = ipv6addr_parts[0]  & 0xFF;   ipv6addr_parts[0]  = ipv6addr_parts[0]  >> 8;
+            ipv6addr_parts[3]  = ipv6addr_parts[2]  & 0xFF;   ipv6addr_parts[2]  = ipv6addr_parts[2]  >> 8;
+            ipv6addr_parts[5]  = ipv6addr_parts[4]  & 0xFF;   ipv6addr_parts[4]  = ipv6addr_parts[4]  >> 8;
+            ipv6addr_parts[7]  = ipv6addr_parts[6]  & 0xFF;   ipv6addr_parts[6]  = ipv6addr_parts[6]  >> 8;
+            ipv6addr_parts[9]  = ipv6addr_parts[8]  & 0xFF;   ipv6addr_parts[8]  = ipv6addr_parts[8]  >> 8;
+            ipv6addr_parts[11] = ipv6addr_parts[10] & 0xFF;   ipv6addr_parts[10] = ipv6addr_parts[10] >> 8;
+            ipv6addr_parts[13] = ipv6addr_parts[12] & 0xFF;   ipv6addr_parts[12] = ipv6addr_parts[12] >> 8;
+            ipv6addr_parts[15] = ipv6addr_parts[14] & 0xFF;   ipv6addr_parts[14] = ipv6addr_parts[14] >> 8;
+
+            return GT_TRUE;
+        }
+    }
+    return GT_FALSE;
+}
+
+/*******************************************************************************
+* parse_mac_address
+*
+* DESCRIPTION:
+*           This function parses MAC address
+* INPUTS:
+*       buf	- buffer with parameter string
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       GT_BOOL
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_BOOL parse_mac_address (char *buf, uint32_t *macaddr_parts)
+{
+    if (6 == sscanf(buf, "%x:%x:%x:%x:%x:%x", &macaddr_parts[0], &macaddr_parts[1], &macaddr_parts[2], &macaddr_parts[3],
+                    &macaddr_parts[4], &macaddr_parts[5]))
+    {
+        if (macaddr_parts[0] <= 255 && macaddr_parts[1] <= 255 && macaddr_parts[2] <= 255 && macaddr_parts[3] <= 255 &&
+            macaddr_parts[4] <= 255 && macaddr_parts[5] <= 255)
+        {
+            return GT_TRUE;
+        }
+    }
+    return GT_FALSE;
+}
+
+
+
+/********************************************************************************/
+/*                          Packet Forward rule table and API                   */
+/********************************************************************************/
+
+static tpmcfg_frwd_entry_t  tpm_sysfs_frwd_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_frwd_rule_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_frwd_entry_t),
+    .entryAra           = tpm_sysfs_frwd_table
+};
+
+
+static void init_tpm_pkt_frwd_db(void)
+{
+    tpmcfg_frwd_entry_t *pentry = (tpmcfg_frwd_entry_t *)tpm_frwd_rule_db.entryAra;
+    int                 indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_frwd_rule_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+    }
+}
+
+
+static void format_ipv4_addr(uint8_t *ipaddr, char *str)
+{
+    sprintf(str, "%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+}
+
+static void format_ipv6_addr(uint8_t *ipaddr, char *str)
+{
+    uint16_t p1 = (ipaddr[0] << 8)  | ipaddr[1];
+    uint16_t p2 = (ipaddr[2] << 8)  | ipaddr[3];
+    uint16_t p3 = (ipaddr[4] << 8)  | ipaddr[5];
+    uint16_t p4 = (ipaddr[6] << 8)  | ipaddr[7];
+    uint16_t p5 = (ipaddr[8] << 8)  | ipaddr[9];
+    uint16_t p6 = (ipaddr[10] << 8) | ipaddr[11];
+    uint16_t p7 = (ipaddr[12] << 8) | ipaddr[13];
+    uint16_t p8 = (ipaddr[14] << 8) | ipaddr[15];
+
+    sprintf(str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+static void format_mac_addr(uint8_t *macaddr, char *str)
+{
+    sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
+}
+
+tpmcfg_frwd_entry_t *find_tpm_pkt_frwd_entry_by_name(char *name)
+{
+    tpmcfg_frwd_entry_t *pentry = (tpmcfg_frwd_entry_t *)tpm_frwd_rule_db.entryAra;
+    int                 indx;
+
+    for (indx = 0; indx < tpm_frwd_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_frwd_entry_t *find_free_tpm_pkt_frwd_entry   (void)
+{
+    tpmcfg_frwd_entry_t *pentry = (tpmcfg_frwd_entry_t *)tpm_frwd_rule_db.entryAra;
+    int                 indx;
+
+    for (indx = 0; indx < tpm_frwd_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL        del_tpm_pkt_frwd_entry_by_name  (char *name)
+{
+    tpmcfg_frwd_entry_t *pentry = (tpmcfg_frwd_entry_t *)tpm_frwd_rule_db.entryAra;
+    int                 indx;
+
+    for (indx = 0; indx < tpm_frwd_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            memset(&pentry->frwd, 0, sizeof(pentry->frwd));
+            pentry->name[0] = 0;
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_pkt_frwd_db   (void)
+{
+    tpmcfg_frwd_entry_t *pentry = (tpmcfg_frwd_entry_t *)tpm_frwd_rule_db.entryAra;
+    int                 indx;
+
+    printk(KERN_INFO "%16s  target-port  queue gem-port\n", "name");
+    for (indx = 0; indx < tpm_frwd_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            printk(KERN_INFO "%16s  0x%04x      %-3d    %d\n", pentry->name, pentry->frwd.trg_port, pentry->frwd.trg_queue, pentry->frwd.gem_port);
+        }
+    }
+}
+
+
+/********************************************************************************/
+/*                          VLAN rule table and API                             */
+/********************************************************************************/
+
+static tpmcfg_vlan_entry_t  tpm_sysfs_vlan_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_vlan_rule_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_vlan_entry_t),
+    .entryAra           = tpm_sysfs_vlan_table
+};
+
+
+static void init_tpm_vlan_db(void)
+{
+    tpmcfg_vlan_entry_t *pentry = (tpmcfg_vlan_entry_t *)tpm_vlan_rule_db.entryAra;
+    int                 indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_vlan_rule_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+    }
+}
+
+tpmcfg_vlan_entry_t *find_tpm_vlan_entry_by_name(char *name)
+{
+    tpmcfg_vlan_entry_t *pentry = (tpmcfg_vlan_entry_t *)tpm_vlan_rule_db.entryAra;
+    int                 indx;
+
+    for (indx = 0; indx < tpm_vlan_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_vlan_entry_t *find_free_tpm_vlan_entry   (void)
+{
+    tpmcfg_vlan_entry_t *pentry = (tpmcfg_vlan_entry_t *)tpm_vlan_rule_db.entryAra;
+    int                 indx;
+
+    for (indx = 0; indx < tpm_vlan_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL        del_tpm_vlan_entry_by_name  (char *name)
+{
+    tpmcfg_vlan_entry_t *pentry = (tpmcfg_vlan_entry_t *)tpm_vlan_rule_db.entryAra;
+    int                 indx;
+
+    for (indx = 0; indx < tpm_vlan_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            pentry->name[0] = 0;
+            memset(&pentry->vlan, 0, sizeof(pentry->vlan));
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_vlan_db   (void)
+{
+    tpmcfg_vlan_entry_t *pentry = (tpmcfg_vlan_entry_t *)tpm_vlan_rule_db.entryAra;
+    int                 indx;
+
+    for (indx = 0; indx < tpm_vlan_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            printk(KERN_INFO "%s: tpid 0x%x, tpid_mask 0x%x, VID %d/0x%x, CFI %d/0x%x, pbit %d/0x%x\n", pentry->name,
+                   pentry->vlan.tpid, pentry->vlan.tpid_mask, pentry->vlan.vid, pentry->vlan.vid_mask,
+                   pentry->vlan.cfi, pentry->vlan.cfi_mask, pentry->vlan.pbit, pentry->vlan.pbit_mask);
+        }
+    }
+}
+
+/********************************************************************************/
+/*                          Mod (packet modification) rule table and API        */
+/********************************************************************************/
+
+/*
+ *  Wilson:
+ *   DB_TPMCFG_MAX_ENTRIES are for ACL rules while one entry,
+ *   which is named as 'dbg_entry', is reserved for mod_eng debug only.
+ *   The 'dbg_entry' is the last entry in 'tpm_sysfs_mod_table'.
+ */
+
+static tpmcfg_mod_entry_t  tpm_sysfs_mod_table[DB_TPMCFG_MAX_ENTRIES+1];
+
+static tpm_generic_rule_db_t tpm_mod_rule_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_mod_entry_t),
+    .entryAra           = tpm_sysfs_mod_table
+};
+
+
+static void init_tpm_mod_db(void)
+{
+    tpmcfg_mod_entry_t *pentry = (tpmcfg_mod_entry_t *)tpm_mod_rule_db.entryAra;
+    int                 indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_mod_rule_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+        pentry->flags   = 0;
+    }
+
+    strcpy(pentry->name, "dbg_entry");
+    pentry->flags = 0;
+}
+
+
+
+tpmcfg_mod_entry_t *find_tpm_mod_entry_by_name(char *name)
+{
+    tpmcfg_mod_entry_t *pentry = (tpmcfg_mod_entry_t *)tpm_mod_rule_db.entryAra;
+    int                 indx;
+
+    if (strcmp(name, "dbg_entry") == 0)
+        return &(tpm_sysfs_mod_table[DB_TPMCFG_MAX_ENTRIES]);
+
+    for (indx = 0; indx < tpm_mod_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_mod_entry_t *find_free_tpm_mod_entry   (void)
+{
+    tpmcfg_mod_entry_t *pentry = (tpmcfg_mod_entry_t *)tpm_mod_rule_db.entryAra;
+    int                 indx;
+
+    for (indx = 0; indx < tpm_mod_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL        del_tpm_mod_entry_by_name  (char *name)
+{
+    tpmcfg_mod_entry_t *pentry = (tpmcfg_mod_entry_t *)tpm_mod_rule_db.entryAra;
+    int                 indx;
+
+    if (strcmp(name, "dbg_entry") == 0)
+    {
+        memset(&pentry->mod, 0, sizeof(pentry->mod));
+        pentry->flags = 0;
+        return GT_TRUE;
+    }
+
+    for (indx = 0; indx < tpm_mod_rule_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            pentry->name[0] = 0;
+            memset(&pentry->mod, 0, sizeof(pentry->mod));
+            pentry->flags = 0;
+            return GT_TRUE;
+        }
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_mod_db   (void)
+{
+    tpmcfg_mod_entry_t  *pentry = (tpmcfg_mod_entry_t *)tpm_mod_rule_db.entryAra;
+    int                 indx;
+    int                 off = 0;
+    char                buf[800];
+    char                d1[60];
+    char                d2[60];
+    char                d1_mask[60];
+    char                d2_mask[60];
+
+    for (indx = 0; indx < tpm_mod_rule_db.max_num_entries+1; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            off += sprintf(buf+off, "%s: flags 0x%x\n",
+                           pentry->name, pentry->flags);
+
+            if (pentry->flags & MOD_ENTRY_FLAG_MH)
+            {
+                off += sprintf(buf+off, "\tMH 0x%x\n", pentry->mod.mh_mod);
+            }
+
+            if (pentry->flags & MOD_ENTRY_FLAG_MAC)
+            {
+                format_mac_addr(pentry->mod.mac_mod.mac_sa, d1);
+                format_mac_addr(pentry->mod.mac_mod.mac_sa_mask, d1_mask);
+                format_mac_addr(pentry->mod.mac_mod.mac_da, d2);
+                format_mac_addr(pentry->mod.mac_mod.mac_da_mask, d2_mask);
+
+                off += sprintf(buf+off, "\tMAC SA %s/%s, DA %s/%s\n", d1, d1_mask, d2, d2_mask);
+            }
+
+            if (pentry->flags & MOD_ENTRY_FLAG_VLAN)
+            {
+                off += sprintf(buf+off, "\t%-19s  VLAN_1 - tpid 0x%x, VID %d/0x%x, CFI %d/0x%x, pbit %d/0x%x\n",
+                               get_vlan_op_str(pentry->mod.vlan_mod.vlan_op), pentry->mod.vlan_mod.vlan1_out.tpid,
+                               pentry->mod.vlan_mod.vlan1_out.vid, pentry->mod.vlan_mod.vlan1_out.vid_mask,
+                               pentry->mod.vlan_mod.vlan1_out.cfi, pentry->mod.vlan_mod.vlan1_out.cfi_mask,
+                               pentry->mod.vlan_mod.vlan1_out.pbit, pentry->mod.vlan_mod.vlan1_out.pbit_mask);
+
+                off += sprintf(buf+off, "\t                     VLAN_2 - tpid 0x%x, VID %d/0x%x, CFI %d/0x%x, pbit %d/0x%x\n",
+                               pentry->mod.vlan_mod.vlan2_out.tpid,
+                               pentry->mod.vlan_mod.vlan2_out.vid, pentry->mod.vlan_mod.vlan2_out.vid_mask,
+                               pentry->mod.vlan_mod.vlan2_out.cfi, pentry->mod.vlan_mod.vlan2_out.cfi_mask,
+                               pentry->mod.vlan_mod.vlan2_out.pbit, pentry->mod.vlan_mod.vlan2_out.pbit_mask);
+            }
+            if (pentry->flags & MOD_ENTRY_FLAG_IPV4)
+            {
+                format_ipv4_addr(pentry->mod.l3.ipv4_mod.ipv4_src_ip_add, d1);
+                format_ipv4_addr(pentry->mod.l3.ipv4_mod.ipv4_src_ip_add_mask, d1_mask);
+                format_ipv4_addr(pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add, d2);
+                format_ipv4_addr(pentry->mod.l3.ipv4_mod.ipv4_dst_ip_add_mask, d2_mask);
+
+                off += sprintf(buf+off, "\tIPV4: src_ip_add %s/%s, dst_ip_add %s/%s\n", d1, d1_mask, d2, d2_mask);
+
+                off += sprintf(buf+off, "\tl3.l4_src_port %d, l3.l4_dst_port %d\n",
+                               pentry->mod.l3.ipv4_mod.l4_src_port, pentry->mod.l3.ipv4_mod.l4_dst_port);
+            }
+            else if (pentry->flags & MOD_ENTRY_FLAG_IPV6)
+            {
+                format_ipv6_addr(pentry->mod.l3.ipv6_mod.ipv6_src_ip_add, d1);
+                format_ipv6_addr(pentry->mod.l3.ipv6_mod.ipv6_src_ip_add_mask, d1_mask);
+                format_ipv6_addr(pentry->mod.l3.ipv6_mod.ipv6_dst_ip_add, d2);
+                format_ipv6_addr(pentry->mod.l3.ipv6_mod.ipv6_dst_ip_add_mask, d2_mask);
+
+                off += sprintf(buf+off, "\tIPV6: src_ip_add %s/%s\n\t      dst_ip_add %s/%s\n", d1, d1_mask, d2, d2_mask);
+
+                off += sprintf(buf+off, "\tl4_src_port %d, l4_dst_port %d\n",
+                               pentry->mod.l3.ipv6_mod.l4_src_port, pentry->mod.l3.ipv6_mod.l4_dst_port);
+            }
+
+
+            if (pentry->flags & MOD_ENTRY_FLAG_PPPOE)
+            {
+                off += sprintf(buf+off, "\tPPPoE session %d, protocol type 0x%x\n",
+                               pentry->mod.pppoe_mod.ppp_session, pentry->mod.pppoe_mod.ppp_proto);
+            }
+
+            printk(KERN_INFO "%s\n", buf);
+            off = 0;
+        }
+    }
+}
+
+/********************************************************************************/
+/*                          L2 ACL table and API                                */
+/********************************************************************************/
+
+static tpmcfg_l2_key_entry_t  tpm_sysfs_l2_key_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_l2_key_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_l2_key_entry_t),
+    .entryAra           = tpm_sysfs_l2_key_table
+};
+
+
+static void init_tpm_l2_key_db(void)
+{
+    tpmcfg_l2_key_entry_t *pentry = (tpmcfg_l2_key_entry_t *)tpm_l2_key_db.entryAra;
+    int                   indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_l2_key_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+    }
+}
+
+tpmcfg_l2_key_entry_t *find_tpm_l2_key_entry_by_name(char *name)
+{
+    tpmcfg_l2_key_entry_t *pentry = (tpmcfg_l2_key_entry_t *)tpm_l2_key_db.entryAra;
+    int                   indx;
+
+    for (indx = 0; indx < tpm_l2_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_l2_key_entry_t *find_free_tpm_l2_key_entry   (void)
+{
+    tpmcfg_l2_key_entry_t *pentry = (tpmcfg_l2_key_entry_t *)tpm_l2_key_db.entryAra;
+    int                   indx;
+
+    for (indx = 0; indx < tpm_l2_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL        del_tpm_l2_key_entry_by_name  (char *name)
+{
+    tpmcfg_l2_key_entry_t *pentry = (tpmcfg_l2_key_entry_t *)tpm_l2_key_db.entryAra;
+    int                   indx;
+
+    for (indx = 0; indx < tpm_l2_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            pentry->name[0] = 0;
+            memset(&pentry->l2_acl, 0, sizeof(pentry->l2_acl));
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_l2_key_db   (void)
+{
+    tpmcfg_l2_key_entry_t *pentry = (tpmcfg_l2_key_entry_t *)tpm_l2_key_db.entryAra;
+    char                  buf[800];
+    int                   indx;
+    int                   off = 0;
+    char                  d1[60];
+    char                  d2[60];
+    char                  d1_mask[60];
+    char                  d2_mask[60];
+
+    for (indx = 0; indx < tpm_l2_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            off += sprintf(buf+off, "%s: \n", pentry->name);
+
+            off += sprintf(buf+off, "\tVLAN_1 - tpid 0x%x/0x%x, VID %d/0x%x, CFI %d/0x%x, pbit %d/0x%x\n",
+                           pentry->l2_acl.vlan1.tpid, pentry->l2_acl.vlan1.tpid_mask,
+                           pentry->l2_acl.vlan1.vid,  pentry->l2_acl.vlan1.vid_mask,
+                           pentry->l2_acl.vlan1.cfi,  pentry->l2_acl.vlan1.cfi_mask,
+                           pentry->l2_acl.vlan1.pbit, pentry->l2_acl.vlan1.pbit_mask);
+
+            off += sprintf(buf+off, "\tVLAN_2 - tpid 0x%x/0x%x, VID %d/0x%x, CFI %d/0x%x, pbit %d/0x%x\n",
+                           pentry->l2_acl.vlan2.tpid, pentry->l2_acl.vlan2.tpid_mask,
+                           pentry->l2_acl.vlan2.vid,  pentry->l2_acl.vlan2.vid_mask,
+                           pentry->l2_acl.vlan2.cfi,  pentry->l2_acl.vlan2.cfi_mask,
+                           pentry->l2_acl.vlan2.pbit, pentry->l2_acl.vlan2.pbit_mask);
+
+            off += sprintf(buf+off, "\tethertype 0x%x, gemport %d, PPPoE: session %d, protocol type 0x%x\n",
+                           pentry->l2_acl.ether_type, pentry->l2_acl.gem_port,
+                           pentry->l2_acl.pppoe_hdr.ppp_session, pentry->l2_acl.pppoe_hdr.ppp_proto);
+
+            format_mac_addr(pentry->l2_acl.mac.mac_sa, d1);
+            format_mac_addr(pentry->l2_acl.mac.mac_sa_mask, d1_mask);
+            format_mac_addr(pentry->l2_acl.mac.mac_da, d2);
+            format_mac_addr(pentry->l2_acl.mac.mac_da_mask, d2_mask);
+
+            off += sprintf(buf+off, "\tMAC SA %s/%s, DA %s/%s\n", d1, d1_mask, d2, d2_mask);
+
+            printk(KERN_INFO "%s\n", buf);
+            off = 0;
+        }
+    }
+}
+
+/********************************************************************************/
+/*                          L3 ACL table and API                                */
+/********************************************************************************/
+
+static tpmcfg_l3_key_entry_t  tpm_sysfs_l3_key_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_l3_key_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_l3_key_entry_t),
+    .entryAra           = tpm_sysfs_l3_key_table
+};
+
+
+static void init_tpm_l3_key_db(void)
+{
+    tpmcfg_l3_key_entry_t *pentry = (tpmcfg_l3_key_entry_t *)tpm_l3_key_db.entryAra;
+    int                   indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_l3_key_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+    }
+}
+
+tpmcfg_l3_key_entry_t *find_tpm_l3_key_entry_by_name(char *name)
+{
+    tpmcfg_l3_key_entry_t *pentry = (tpmcfg_l3_key_entry_t *)tpm_l3_key_db.entryAra;
+    int                   indx;
+
+    for (indx = 0; indx < tpm_l3_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_l3_key_entry_t *find_free_tpm_l3_key_entry   (void)
+{
+    tpmcfg_l3_key_entry_t *pentry = (tpmcfg_l3_key_entry_t *)tpm_l3_key_db.entryAra;
+    int                   indx;
+
+    for (indx = 0; indx < tpm_l3_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL        del_tpm_l3_key_entry_by_name  (char *name)
+{
+    tpmcfg_l3_key_entry_t *pentry = (tpmcfg_l3_key_entry_t *)tpm_l3_key_db.entryAra;
+    int                   indx;
+
+    for (indx = 0; indx < tpm_l3_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            pentry->name[0] = 0;
+            memset(&pentry->l3_acl, 0, sizeof(pentry->l3_acl));
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_l3_key_db   (void)
+{
+    tpmcfg_l3_key_entry_t *pentry = (tpmcfg_l3_key_entry_t *)tpm_l3_key_db.entryAra;
+    char                  buf[800];
+    int                   indx;
+    int                   off = 0;
+
+    for (indx = 0; indx < tpm_l3_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            off += sprintf(buf+off, "%s: \n", pentry->name);
+
+            off += sprintf(buf+off, "\tethertype 0x%x, PPPoE: session %d, protocol type 0x%x\n",
+                           pentry->l3_acl.ether_type_key, pentry->l3_acl.pppoe_key.ppp_session, pentry->l3_acl.pppoe_key.ppp_proto);
+
+            printk(KERN_INFO "%s\n", buf);
+            off = 0;
+        }
+    }
+}
+
+/********************************************************************************/
+/*                          IPV4 ACL table and API                              */
+/********************************************************************************/
+
+static tpmcfg_ipv4_key_entry_t  tpm_sysfs_ipv4_key_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_ipv4_key_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_ipv4_key_entry_t),
+    .entryAra           = tpm_sysfs_ipv4_key_table
+};
+
+
+static void init_tpm_ipv4_key_db(void)
+{
+    tpmcfg_ipv4_key_entry_t *pentry = (tpmcfg_ipv4_key_entry_t *)tpm_ipv4_key_db.entryAra;
+    int                     indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_ipv4_key_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+    }
+}
+
+tpmcfg_ipv4_key_entry_t *find_tpm_ipv4_key_entry_by_name(char *name)
+{
+    tpmcfg_ipv4_key_entry_t *pentry = (tpmcfg_ipv4_key_entry_t *)tpm_ipv4_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv4_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_ipv4_key_entry_t *find_free_tpm_ipv4_key_entry   (void)
+{
+    tpmcfg_ipv4_key_entry_t *pentry = (tpmcfg_ipv4_key_entry_t *)tpm_ipv4_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv4_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL        del_tpm_ipv4_key_entry_by_name  (char *name)
+{
+    tpmcfg_ipv4_key_entry_t *pentry = (tpmcfg_ipv4_key_entry_t *)tpm_ipv4_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv4_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            pentry->name[0] = 0;
+            memset(&pentry->ipv4_acl, 0, sizeof(pentry->ipv4_acl));
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_ipv4_key_db   (void)
+{
+    tpmcfg_ipv4_key_entry_t *pentry = (tpmcfg_ipv4_key_entry_t *)tpm_ipv4_key_db.entryAra;
+    char                    buf[800];
+    int                     indx;
+    int                     off = 0;
+    char                    d1[60];
+    char                    d2[60];
+    char                    d1_mask[60];
+    char                    d2_mask[60];
+
+    for (indx = 0; indx < tpm_ipv4_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            off += sprintf(buf+off, "%s: \n",
+                           pentry->name);
+
+            off += sprintf(buf+off, "\tdscp %d/0x%x, protocol %d, src_port %d, dst_port %d\n",
+                           pentry->ipv4_acl.ipv4_dscp, pentry->ipv4_acl.ipv4_dscp_mask,
+                           pentry->ipv4_acl.ipv4_proto, pentry->ipv4_acl.l4_src_port, pentry->ipv4_acl.l4_dst_port);
+
+            format_ipv4_addr(pentry->ipv4_acl.ipv4_src_ip_add, d1);
+            format_ipv4_addr(pentry->ipv4_acl.ipv4_src_ip_add_mask, d1_mask);
+            format_ipv4_addr(pentry->ipv4_acl.ipv4_dst_ip_add, d2);
+            format_ipv4_addr(pentry->ipv4_acl.ipv4_dst_ip_add_mask, d2_mask);
+
+            off += sprintf(buf+off, "\tsrc_ip_add %s/%s, dst_ip_add %s/%s\n", d1, d1_mask, d2, d2_mask);
+
+            printk(KERN_INFO "%s\n", buf);
+            off = 0;
+        }
+    }
+}
+
+/********************************************************************************/
+/*                          IPV6 ACL table and API        */
+/********************************************************************************/
+
+static tpmcfg_ipv6_key_entry_t  tpm_sysfs_ipv6_key_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_ipv6_key_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_ipv6_key_entry_t),
+    .entryAra           = tpm_sysfs_ipv6_key_table
+};
+
+static void init_tpm_ipv6_key_db(void)
+{
+    tpmcfg_ipv6_key_entry_t *pentry = (tpmcfg_ipv6_key_entry_t *)tpm_ipv6_key_db.entryAra;
+    int                     indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_ipv6_key_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+    }
+}
+
+tpmcfg_ipv6_key_entry_t *find_tpm_ipv6_key_entry_by_name(char *name)
+{
+    tpmcfg_ipv6_key_entry_t *pentry = (tpmcfg_ipv6_key_entry_t *)tpm_ipv6_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_ipv6_key_entry_t *find_free_tpm_ipv6_key_entry   (void)
+{
+    tpmcfg_ipv6_key_entry_t *pentry = (tpmcfg_ipv6_key_entry_t *)tpm_ipv6_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL        del_tpm_ipv6_key_entry_by_name  (char *name)
+{
+    tpmcfg_ipv6_key_entry_t *pentry = (tpmcfg_ipv6_key_entry_t *)tpm_ipv6_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            pentry->name[0] = 0;
+            memset(&pentry->ipv6_acl, 0, sizeof(pentry->ipv6_acl));
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_ipv6_key_db   (void)
+{
+    tpmcfg_ipv6_key_entry_t *pentry = (tpmcfg_ipv6_key_entry_t *)tpm_ipv6_key_db.entryAra;
+    char                    buf[800];
+    int                     indx;
+    int                     off = 0;
+    char                    d1[60];
+    char                    d2[60];
+    char                    d1_mask[60];
+    char                    d2_mask[60];
+
+    for (indx = 0; indx < tpm_ipv6_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            off += sprintf(buf+off, "%s: \n", pentry->name);
+
+            off += sprintf(buf+off, "\tdscp %d/0x%x, next_header %d, src_port %d, dst_port %d\n",
+                           pentry->ipv6_acl.ipv6_dscp, pentry->ipv6_acl.ipv6_dscp_mask,
+                           pentry->ipv6_acl.ipv6_next_header, pentry->ipv6_acl.l4_src_port, pentry->ipv6_acl.l4_dst_port);
+
+            format_ipv6_addr(pentry->ipv6_acl.ipv6_src_ip_add, d1);
+            format_ipv6_addr(pentry->ipv6_acl.ipv6_src_ip_add_mask, d1_mask);
+            format_ipv6_addr(pentry->ipv6_acl.ipv6_dst_ip_add, d2);
+            format_ipv6_addr(pentry->ipv6_acl.ipv6_dst_ip_add_mask, d2_mask);
+
+            off += sprintf(buf+off, "\tsrc_ip_add %s/%s, dst_ip_add %s/%s\n", d1, d1_mask, d2, d2_mask);
+
+            printk(KERN_INFO "%s\n", buf);
+            off = 0;
+        }
+    }
+}
+
+
+/********************************************************************************/
+/*                          IPV6 gen ACL table and API        */
+/********************************************************************************/
+
+static tpmcfg_ipv6_key_entry_t tpm_sysfs_ipv6_gen_key_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_ipv6_gen_key_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_ipv6_key_entry_t),
+    .entryAra           = tpm_sysfs_ipv6_gen_key_table
+};
+
+
+static void init_tpm_ipv6_gen_key_db(void)
+{
+    tpmcfg_ipv6_gen_key_entry_t *pentry = (tpmcfg_ipv6_gen_key_entry_t *)tpm_ipv6_gen_key_db.entryAra;
+    int                     indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_ipv6_gen_key_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+    }
+}
+
+tpmcfg_ipv6_gen_key_entry_t *find_tpm_ipv6_gen_key_entry_by_name(char *name)
+{
+    tpmcfg_ipv6_gen_key_entry_t *pentry = (tpmcfg_ipv6_gen_key_entry_t *)tpm_ipv6_gen_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_gen_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_ipv6_gen_key_entry_t *find_free_tpm_ipv6_gen_key_entry(void)
+{
+    tpmcfg_ipv6_gen_key_entry_t *pentry = (tpmcfg_ipv6_gen_key_entry_t *)tpm_ipv6_gen_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_gen_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL del_tpm_ipv6_gen_key_entry_by_name(char *name)
+{
+    tpmcfg_ipv6_gen_key_entry_t *pentry = (tpmcfg_ipv6_gen_key_entry_t *)tpm_ipv6_gen_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_gen_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            pentry->name[0] = 0;
+            memset(&pentry->ipv6gen_acl, 0, sizeof(pentry->ipv6gen_acl));
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_ipv6_gen_key_db(void)
+{
+    tpmcfg_ipv6_gen_key_entry_t *pentry = (tpmcfg_ipv6_gen_key_entry_t *)tpm_ipv6_gen_key_db.entryAra;
+    char                    buf[800];
+    int                     indx;
+    int                     off = 0;
+    char                    d1[60];
+    char                    d1_mask[60];
+
+    for (indx = 0; indx < tpm_ipv6_gen_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            off += sprintf(buf+off, "%s: \n", pentry->name);
+
+            off += sprintf(buf+off, "\tdscp %d/0x%x, hop_limit %d\n",
+                           pentry->ipv6gen_acl.ipv6_dscp, pentry->ipv6gen_acl.ipv6_dscp_mask,
+                           pentry->ipv6gen_acl.hop_limit);
+
+            format_ipv6_addr(pentry->ipv6gen_acl.ipv6_src_ip_add, d1);
+            format_ipv6_addr(pentry->ipv6gen_acl.ipv6_src_ip_add_mask, d1_mask);
+
+            off += sprintf(buf+off, "\tsrc_ip_add %s/%s\n", d1, d1_mask);
+
+            printk(KERN_INFO "%s\n", buf);
+            off = 0;
+        }
+    }
+}
+
+static tpmcfg_ipv6_dip_key_entry_t tpm_sysfs_ipv6_dip_key_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_ipv6_dip_key_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_ipv6_dip_key_entry_t),
+    .entryAra           = tpm_sysfs_ipv6_dip_key_table
+};
+
+
+static void init_tpm_ipv6_dip_key_db(void)
+{
+    tpmcfg_ipv6_dip_key_entry_t *pentry = (tpmcfg_ipv6_dip_key_entry_t *)tpm_ipv6_dip_key_db.entryAra;
+    int                     indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_ipv6_dip_key_db.max_num_entries; indx++, pentry++)
+    {
+        pentry->name[0] = 0;
+    }
+}
+
+tpmcfg_ipv6_dip_key_entry_t *find_tpm_ipv6_dip_key_entry_by_name(char *name)
+{
+    tpmcfg_ipv6_dip_key_entry_t *pentry = (tpmcfg_ipv6_dip_key_entry_t *)tpm_ipv6_dip_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_dip_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0) return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_ipv6_dip_key_entry_t *find_free_tpm_ipv6_dip_key_entry(void)
+{
+    tpmcfg_ipv6_dip_key_entry_t *pentry = (tpmcfg_ipv6_dip_key_entry_t *)tpm_ipv6_dip_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_dip_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] == 0) return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL del_tpm_ipv6_dip_key_entry_by_name(char *name)
+{
+    tpmcfg_ipv6_dip_key_entry_t *pentry = (tpmcfg_ipv6_dip_key_entry_t *)tpm_ipv6_dip_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_dip_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (strcmp(pentry->name, name) == 0)
+        {
+            pentry->name[0] = 0;
+            memset(&pentry->ipv6_addr, 0, sizeof(pentry->ipv6_addr));
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_ipv6_dip_key_db(void)
+{
+    tpmcfg_ipv6_dip_key_entry_t *pentry = (tpmcfg_ipv6_dip_key_entry_t *)tpm_ipv6_dip_key_db.entryAra;
+    char                    buf[800];
+    int                     indx;
+    int                     off = 0;
+    char                    d1[60];
+//    char                    d2[60];
+    char                    d1_mask[60];
+//    char                    d2_mask[60];
+
+    for (indx = 0; indx < tpm_ipv6_dip_key_db.max_num_entries; indx++, pentry++)
+    {
+        if (pentry->name[0] != 0)
+        {
+            off += sprintf(buf+off, "%s: \n", pentry->name);
+
+            format_ipv6_addr(pentry->ipv6_addr.ipv6_ip_add, d1);
+            format_ipv6_addr(pentry->ipv6_addr.ipv6_ip_add_mask, d1_mask);
+
+            off += sprintf(buf+off, "\tdst_ip_add %s/%s\n", d1, d1_mask);
+
+            printk(KERN_INFO "%s\n", buf);
+            off = 0;
+        }
+    }
+}
+
+static tpmcfg_ipv6_l4_ports_key_entry_t  tpm_sysfs_ipv6_l4_ports_key_table[DB_TPMCFG_MAX_ENTRIES];
+
+static tpm_generic_rule_db_t tpm_ipv6_l4_ports_key_db =
+{
+    .max_num_entries    = DB_TPMCFG_MAX_ENTRIES,
+    .num_entries        = 0,
+    .size_entry         = sizeof(tpmcfg_ipv6_l4_ports_key_entry_t),
+    .entryAra           = tpm_sysfs_ipv6_l4_ports_key_table
+};
+
+static void init_tpm_ipv6_l4_ports_key_db(void)
+{
+    tpmcfg_ipv6_l4_ports_key_entry_t *pentry = (tpmcfg_ipv6_l4_ports_key_entry_t *)tpm_ipv6_l4_ports_key_db.entryAra;
+    int indx;
+
+    printk(KERN_INFO "%s: Clearing DB\n", __FUNCTION__);
+    for (indx = 0; indx < tpm_ipv6_l4_ports_key_db.max_num_entries; indx++, pentry++)
+        pentry->name[0] = 0;
+}
+
+tpmcfg_ipv6_l4_ports_key_entry_t *find_tpm_ipv6_l4_ports_key_entry_by_name(char *name)
+{
+    tpmcfg_ipv6_l4_ports_key_entry_t *pentry = (tpmcfg_ipv6_l4_ports_key_entry_t *)tpm_ipv6_l4_ports_key_db.entryAra;
+    int indx;
+
+    for (indx = 0; indx < tpm_ipv6_l4_ports_key_db.max_num_entries; indx++, pentry++) {
+        if (strcmp(pentry->name, name) == 0) 
+			return pentry;
+    }
+    return 0;
+}
+
+tpmcfg_ipv6_l4_ports_key_entry_t *find_free_tpm_ipv6_l4_ports_key_entry(void)
+{
+    tpmcfg_ipv6_l4_ports_key_entry_t *pentry = (tpmcfg_ipv6_l4_ports_key_entry_t *)tpm_ipv6_l4_ports_key_db.entryAra;
+    int indx;
+
+    for (indx = 0; indx < tpm_ipv6_l4_ports_key_db.max_num_entries; indx++, pentry++) {
+        if (pentry->name[0] == 0) 
+			return pentry;
+    }
+    return 0;
+}
+
+GT_BOOL del_tpm_ipv6_l4_ports_key_entry_by_name(char *name)
+{
+    tpmcfg_ipv6_l4_ports_key_entry_t *pentry = (tpmcfg_ipv6_l4_ports_key_entry_t *)tpm_ipv6_l4_ports_key_db.entryAra;
+    int                     indx;
+
+    for (indx = 0; indx < tpm_ipv6_l4_ports_key_db.max_num_entries; indx++, pentry++) {
+        if (strcmp(pentry->name, name) == 0) {
+            pentry->name[0] = 0;
+            memset(&pentry->l4_ports, 0, sizeof(pentry->l4_ports));
+            return GT_TRUE;
+        };
+    }
+    return GT_FALSE;
+}
+
+void show_tpm_ipv6_l4_ports_key_db(void)
+{
+    tpmcfg_ipv6_l4_ports_key_entry_t *pentry = (tpmcfg_ipv6_l4_ports_key_entry_t *)tpm_ipv6_l4_ports_key_db.entryAra;
+    char                    buf[800];
+    int                     indx;
+    int                     off = 0;
+
+    for (indx = 0; indx < tpm_ipv6_l4_ports_key_db.max_num_entries; indx++, pentry++) {
+        if (pentry->name[0] != 0) {
+            off += sprintf(buf+off, "%s: \n", pentry->name);
+
+            off += sprintf(buf+off, "\tsrc_port %d, dst_port %d\n", 
+						pentry->l4_ports.l4_src_port, pentry->l4_ports.l4_dst_port);
+
+            printk(KERN_INFO "%s\n", buf);
+            off = 0;
+        }
+    }
+}
+
+
+void tpm_reset_mc_vid_key(void)
+{
+    tpm_src_port_type_t                 src_port;
+    
+    memset(&mc_vid_key, 0, sizeof(mc_vid_key));
+    
+    for ( src_port = TPM_SRC_PORT_UNI_0; src_port <= TPM_SRC_PORT_UNI_VIRT; src_port++)
+    {
+        mc_vid_key.mc_vid_port_vids[src_port - TPM_SRC_PORT_UNI_0].tpm_src_port = src_port;
+    }
+    
+    return;
+}
+
+GT_BOOL tpm_set_mc_vid_key(
+    uint32_t                 src_port,
+    uint32_t                 mc_uni_xlate_mode,
+    uint32_t                 mc_uni_xlate_vid
+)
+{
+    if (src_port < TPM_SRC_PORT_UNI_0 || src_port > TPM_SRC_PORT_UNI_VIRT)
+    {
+        printk(KERN_INFO "illegal input src port(%d)\n", src_port);
+        return GT_FALSE;
+    }
+    
+    mc_vid_key.mc_vid_port_vids[src_port - TPM_SRC_PORT_UNI_0].mc_uni_port_mode = mc_uni_xlate_mode;
+    mc_vid_key.mc_vid_port_vids[src_port - TPM_SRC_PORT_UNI_0].tpm_src_port = src_port;
+    mc_vid_key.mc_vid_port_vids[src_port - TPM_SRC_PORT_UNI_0].uni_port_vid = mc_uni_xlate_vid;
+    
+    return GT_TRUE;
+}
+
+tpm_error_code_t tpm_set_mc_vid_cfg(
+    uint32_t                 mc_vid
+)
+{
+    tpm_error_code_t ret;
+    
+    ret = tpm_proc_set_mc_vid_port_vids (0, mc_vid, &mc_vid_key);
+    return ret;
+}
+
+// Intialization of database
+void tpm_sysfs_rule_db_init(void)
+{
+    init_tpm_pkt_frwd_db();
+    init_tpm_vlan_db();
+    init_tpm_mod_db();
+    init_tpm_l2_key_db();
+    init_tpm_l3_key_db();
+    init_tpm_ipv4_key_db();
+    init_tpm_ipv6_key_db();
+    init_tpm_ipv6_dip_key_db();
+    init_tpm_ipv6_gen_key_db();
+	init_tpm_ipv6_l4_ports_key_db();
+}
+tpm_error_code_t tpm_proc_send_genquery_to_uni(tpm_trg_port_type_t dest_port_bm, uint32_t packet_num)
+{
+	int32_t switch_dev_num;
+	uint8_t loop;
+	uint8_t loop_in;
+	uint32_t trg_port;
+	uint32_t switch_port_bm;
+	tpm_error_code_t ret_code;
+	tpm_db_ety_dsa_enable_t ety_dsa_enable;
+
+	tpm_db_get_ety_dsa_enable(&ety_dsa_enable);
+	if (TPM_ETY_DSA_DISABLE == ety_dsa_enable) {
+		TPM_OS_ERROR(TPM_TPM_LOG_MOD, "ety_dsa is not enabled!\n");
+		return TPM_OK;
+	}
+	/* fill in the switch dev_num */
+	tpm_db_get_switch_dev_num(&switch_dev_num);
+	switch_dev_num &= 0x1f;
+	g_gen_query_pkt[16] = (0x40 | switch_dev_num);
+
+	switch_port_bm = tpm_db_trg_port_switch_port_get(dest_port_bm);
+	for (loop = 0, trg_port = 1; loop <= 7; loop++, trg_port = trg_port << 1) {
+		if (0 == (trg_port & switch_port_bm))
+			continue;
+
+		g_gen_query_pkt[17] = (loop << 3);
+
+		for (loop_in = 0; loop_in < packet_num; loop_in++) {
+			g_gen_query_pkt[23] = (loop_in + 1);
+			ret_code = tpm_tx_igmp_frame(0, TPM_TRG_PORT_UNI_ANY, 7, 0, g_gen_query_pkt, sizeof(g_gen_query_pkt));
+			if (ret_code != TPM_OK) {\
+				TPM_OS_ERROR(TPM_CLI_MOD, " recvd ret_code(%d)\n", ret_code);\
+				return(ret_code);\
+			}
+		}
+	}
+
+
+	return(TPM_RC_OK);
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.h
new file mode 100755
index 0000000..ddf2bcf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_sysfs_utils.h
@@ -0,0 +1,295 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_usr_tpmsysfs_db.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   Zeev
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               $Revision: 1.1.1.1 $
+*
+*
+*******************************************************************************/
+#ifndef _TPM_USR_TPM_SYSFS_DB_H_
+#define _TPM_USR_TPM_SYSFS_DB_H_
+
+#define DB_TPMCFG_MAX_NAME         32
+#define DB_TPMCFG_MAX_ENTRIES      512
+
+
+extern void tpm_sysfs_rule_db_init(void);
+
+
+//
+// Miscellaneous
+//
+// Internal rule type classification
+typedef enum
+{
+    rule_type_l2, rule_type_l3, rule_type_ipv4, rule_type_ipv6
+} rule_type_t;
+
+typedef struct
+{
+    int  value;
+    char *str;
+} string_enum_pair_t;
+
+typedef struct
+{
+    string_enum_pair_t *string_enum_pair;
+    int                num_entries;
+} string_enum_pair_db_t;
+extern GT_BOOL get_srcport_value        (char *str, unsigned int *value);
+extern GT_BOOL get_srcdir_value         (char *str, unsigned int *value);
+extern GT_BOOL get_phase_value          (char *str, unsigned int *value);
+extern GT_BOOL get_bool_value           (char *str, unsigned int *value);
+extern GT_BOOL get_igmp_mode_value      (char *str, unsigned int *value);
+extern GT_BOOL get_igmp_srcport_value   (char *str, unsigned int *value);
+extern GT_BOOL get_lx_ipvy_value        (char *str, unsigned int *value);
+extern GT_BOOL get_direction_value      (char *str, unsigned int *value);
+extern GT_BOOL get_scheduling_mode_value(char *str, unsigned int *value);
+extern GT_BOOL get_sched_entity_value   (char *str, unsigned int *value);
+extern GT_BOOL get_vlan_op_value        (char *str, unsigned int *value);
+
+extern char *get_tpm_err_str(int value);
+
+
+extern GT_BOOL parse_ipv4_address (char *buf, uint32_t *ipv4addr_parts);
+extern GT_BOOL parse_ipv6_address (char *buf, uint32_t *ipv6addr_parts);
+extern GT_BOOL parse_mac_address  (char *buf, uint32_t *macaddr_parts);
+
+
+
+extern int  count_parameters     (const char *buf);
+extern void print_horizontal_line(unsigned int char_count);
+extern void print_help_buffer    (char *helpbuf, int len);
+extern void parm_error_completion(int numparms, int reqdparms, const char *buf, int (*help_text_routine)(char *));
+
+
+//
+// Common DB structure for entries
+//
+typedef struct
+{
+    int  max_num_entries;
+    int  num_entries;
+    int  size_entry;
+    void *entryAra;
+} tpm_generic_rule_db_t;
+
+
+// Frwd packet entry and DB API
+typedef struct
+{
+    char                name[DB_TPMCFG_MAX_NAME+1];
+    tpm_pkt_frwd_t      frwd;
+} tpmcfg_frwd_entry_t;
+
+extern tpmcfg_frwd_entry_t *find_tpm_pkt_frwd_entry_by_name(char *name);
+extern tpmcfg_frwd_entry_t *find_free_tpm_pkt_frwd_entry   (void);
+extern GT_BOOL             del_tpm_pkt_frwd_entry_by_name  (char *name);
+extern void                show_tpm_pkt_frwd_db(void);
+
+
+
+// VLAN entry and DB API
+typedef struct
+{
+    char                name[DB_TPMCFG_MAX_NAME+1];
+    tpm_vlan_key_t      vlan;
+} tpmcfg_vlan_entry_t;
+
+extern tpmcfg_vlan_entry_t *find_tpm_vlan_entry_by_name(char *name);
+extern tpmcfg_vlan_entry_t *find_free_tpm_vlan_entry   (void);
+extern GT_BOOL             del_tpm_vlan_entry_by_name  (char *name);
+extern void                show_tpm_vlan_db(void);
+
+
+// Mod (packet modification) entry and DB API
+//
+// Flags to indicate which fields are defined
+#define MOD_ENTRY_FLAG_IPV4        0x1
+#define MOD_ENTRY_FLAG_IPV6        0x2
+#define MOD_ENTRY_FLAG_PPPOE       0x4
+#define MOD_ENTRY_FLAG_MAC         0x8
+#define MOD_ENTRY_FLAG_VLAN        0x10
+#define MOD_ENTRY_FLAG_MH          0x20
+
+typedef struct
+{
+    char                name[DB_TPMCFG_MAX_NAME+1];
+    tpm_pkt_mod_t       mod;
+    uint32_t            flags;
+} tpmcfg_mod_entry_t;
+
+extern tpmcfg_mod_entry_t  *find_tpm_mod_entry_by_name(char *name);
+extern tpmcfg_mod_entry_t  *find_free_tpm_mod_entry   (void);
+extern GT_BOOL             del_tpm_mod_entry_by_name  (char *name);
+extern void                show_tpm_mod_db(void);
+
+// L2 ACL entry and DB API
+typedef struct
+{
+    char                   name[DB_TPMCFG_MAX_NAME+1];
+    tpm_l2_acl_key_t       l2_acl;
+} tpmcfg_l2_key_entry_t;
+
+extern tpmcfg_l2_key_entry_t  *find_tpm_l2_key_entry_by_name(char *name);
+extern tpmcfg_l2_key_entry_t  *find_free_tpm_l2_key_entry  (void);
+extern GT_BOOL                del_tpm_l2_key_entry_by_name  (char *name);
+extern void                   show_tpm_l2_key_db(void);
+
+// L3 ACL entry and DB API
+typedef struct
+{
+    char                   name[DB_TPMCFG_MAX_NAME+1];
+    tpm_l3_type_key_t      l3_acl;
+} tpmcfg_l3_key_entry_t;
+
+extern tpmcfg_l3_key_entry_t  *find_tpm_l3_key_entry_by_name(char *name);
+extern tpmcfg_l3_key_entry_t  *find_free_tpm_l3_key_entry  (void);
+extern GT_BOOL                del_tpm_l3_key_entry_by_name  (char *name);
+extern void                   show_tpm_l3_key_db(void);
+
+// IPV4 ACL entry and DB API
+typedef struct
+{
+    char                   name[DB_TPMCFG_MAX_NAME+1];
+    tpm_ipv4_acl_key_t     ipv4_acl;
+} tpmcfg_ipv4_key_entry_t;
+
+extern tpmcfg_ipv4_key_entry_t  *find_tpm_ipv4_key_entry_by_name(char *name);
+extern tpmcfg_ipv4_key_entry_t  *find_free_tpm_ipv4_key_entry  (void);
+extern GT_BOOL                  del_tpm_ipv4_key_entry_by_name  (char *name);
+extern void                     show_tpm_ipv4_key_db(void);
+
+// IPV6 ACL entry and DB API
+typedef struct
+{
+    char               name[DB_TPMCFG_MAX_NAME+1];
+    tpm_ipv6_acl_key_t ipv6_acl;
+} tpmcfg_ipv6_key_entry_t;
+
+extern tpmcfg_ipv6_key_entry_t  *find_tpm_ipv6_key_entry_by_name(char *name);
+extern tpmcfg_ipv6_key_entry_t  *find_free_tpm_ipv6_key_entry(void);
+extern GT_BOOL                   del_tpm_ipv6_key_entry_by_name(char *name);
+extern void                      show_tpm_ipv6_key_db(void);
+
+// IPV6 gen ACL entry and DB API
+typedef struct
+{
+    char                   name[DB_TPMCFG_MAX_NAME+1];
+    tpm_ipv6_gen_acl_key_t ipv6gen_acl;
+} tpmcfg_ipv6_gen_key_entry_t;
+
+typedef struct
+{
+    char                name[DB_TPMCFG_MAX_NAME+1];
+    tpm_ipv6_addr_key_t ipv6_addr;
+} tpmcfg_ipv6_dip_key_entry_t;
+
+typedef struct
+{
+    char                name[DB_TPMCFG_MAX_NAME+1];
+    tpm_l4_ports_key_t  l4_ports;
+} tpmcfg_ipv6_l4_ports_key_entry_t;
+
+extern tpmcfg_ipv6_gen_key_entry_t       *find_tpm_ipv6_gen_key_entry_by_name(char *name);
+extern tpmcfg_ipv6_gen_key_entry_t       *find_free_tpm_ipv6_gen_key_entry(void);
+extern GT_BOOL                            del_tpm_ipv6_gen_key_entry_by_name(char *name);
+extern void                               show_tpm_ipv6_gen_key_db(void);
+extern tpmcfg_ipv6_dip_key_entry_t       *find_tpm_ipv6_dip_key_entry_by_name(char *name);
+extern tpmcfg_ipv6_dip_key_entry_t       *find_free_tpm_ipv6_dip_key_entry(void);
+extern GT_BOOL                            del_tpm_ipv6_dip_key_entry_by_name(char *name);
+extern void                               show_tpm_ipv6_dip_key_db(void);
+extern tpmcfg_ipv6_l4_ports_key_entry_t  *find_tpm_ipv6_l4_ports_key_entry_by_name(char *name);
+extern tpmcfg_ipv6_l4_ports_key_entry_t  *find_free_tpm_ipv6_l4_ports_key_entry(void);
+extern GT_BOOL                            del_tpm_ipv6_l4_ports_key_entry_by_name(char *name);
+extern void                               show_tpm_ipv6_l4_ports_key_db(void);
+
+
+extern void tpm_reset_mc_vid_key(void);
+
+extern GT_BOOL tpm_set_mc_vid_key(
+    uint32_t                 src_port,
+    uint32_t                 mc_uni_xlate_mode,
+    uint32_t                 mc_uni_xlate_vid
+);
+extern tpm_error_code_t tpm_set_mc_vid_cfg(
+    uint32_t                 mc_vid
+);
+tpm_error_code_t tpm_proc_send_genquery_to_uni(tpm_trg_port_type_t dest_port_bm, uint32_t packet_num);
+
+
+#endif  /* _TPM_USR_TPM_SYSFS_DB_H_*/
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.c
new file mode 100755
index 0000000..c38ab83
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.c
@@ -0,0 +1,4252 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+        this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+#include "tpm_sysfs_setup.h"
+
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+extern struct semaphore    tpm_sfs_2_ioctl_sem;
+extern tpm_ioctl_mng_t     tpm_sfs_2_ioctl_command;
+#endif
+
+const char *sw_qos_init_pri_str[] =
+{
+    "USE_PORTS_DEF",
+    "TAG_PRI_ONLY",
+    "IP_PRI_ONLY",
+    "TAG_AND_IP_PRI",
+    "UNKNOWN"
+};
+
+
+/* ========================================================================== */
+/*                            Debug SW Attributes                                 */
+/* ========================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_sw_set_global_reg
+*
+* DESCRIPTION:
+*       This function set value to the global register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_global_reg
+(
+    IN uint32_t             owner_id,
+    IN uint8_t              regAddr,
+    IN uint16_t             data
+)
+{
+    tpm_sw_set_global_reg(owner_id, regAddr, data);
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_global_reg
+*
+* DESCRIPTION:
+*           This function gets value from the global register.
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_global_reg
+(
+    IN  uint32_t             owner_id,
+    IN  uint8_t              regAddr
+)
+{
+    uint16_t             data;
+
+    tpm_sw_get_global_reg(owner_id, regAddr, &data);
+
+    printk(KERN_INFO " regAddr[0x%x] data[0x%x]\n",regAddr,data);
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_reg
+*
+* DESCRIPTION:
+*       This function sets value to the port register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_reg
+(
+    IN uint32_t             owner_id,
+    IN uint32_t             lport,
+    IN uint8_t              regAddr,
+    IN uint16_t             data
+)
+{
+    tpm_sw_set_port_reg(owner_id, lport, regAddr, data);
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_reg
+*
+* DESCRIPTION:
+*           This function gets value from the port register.
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_reg
+(
+    IN  uint32_t            owner_id,
+    IN  uint8_t             lport,
+    IN  uint8_t             regAddr
+)
+{
+    uint16_t             data;
+
+    tpm_sw_get_port_reg(owner_id, lport,regAddr, &data);
+
+    printk(KERN_INFO " lport[%d] regAddr[0x%x] data[0x%x]\n",lport, regAddr, data);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_cntrs
+*
+* DESCRIPTION:
+*           This function gets all counters of the given port
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_cntrs
+(
+    IN  uint32_t            owner_id,
+    IN  uint8_t             lport
+)
+{
+
+    tpm_sw_print_port_counters(owner_id, lport);
+
+    return;
+}
+
+
+/*******************************************************************************
+* sfs_tpm_sw_get_fdb
+*
+* DESCRIPTION:
+*           This function gets all counters of the given port
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       db_num      - ATU MAC Address Database number. If multiple address
+*                     databases are not being used, DBNum should be zero.
+*                     If multiple address databases are being used, this value
+*                     should be set to the desired address database number.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_fdb
+(
+    IN  uint32_t            owner_id,
+    IN  uint16_t            db_num
+)
+{
+
+    tpm_sw_get_fdb(owner_id,db_num);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_init
+*
+* DESCRIPTION:
+*           This function init Amber DB
+* INPUTS:
+*       NONE.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       There is a temprorary function.
+*
+*******************************************************************************/
+
+void sfs_tpm_sw_init
+(
+    void
+)
+{
+    tpm_sw_init();
+
+    return;
+}
+
+
+/*******************************************************************************
+* sfs_tpm_sw_set_debug_trace_flag
+*
+* DESCRIPTION:
+*           This function sets TPM trace flag
+* INPUTS:
+*       NONE.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+
+void sfs_tpm_sw_set_debug_trace_flag
+(
+    IN  uint32_t    enDis
+)
+{
+    tpm_sw_set_debug_trace_flag(enDis);
+
+    return;
+}
+
+
+/*******************************************************************************
+**
+**  sfs_tpm_sw_get_help_show
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_tpm_sw_dbg_help_show(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "========================================================================================================================\n");
+    off += sprintf(buf+off, "                                          Debug Switch Commands\n");
+    off += sprintf(buf+off, "                                          Insert all parameters in Decimal\n");
+    off += sprintf(buf+off, "========================================================================================================================\n");
+    off += sprintf(buf+off, "cat help_sw_dbg                                                    - show this help\n");
+    off += sprintf(buf+off, "echo [owner_id] [regAddr] [data]                > set_global_reg   - sets value to the global register\n");
+    off += sprintf(buf+off, "echo [owner_id] [regAddr]                       > get_global_reg   - gets value of the global register\n");
+    off += sprintf(buf+off, "echo [owner_id] [lport 1 -3] [regAddr]  [data]  > set_port_reg     - sets value to the port register\n");
+    off += sprintf(buf+off, "echo [owner_id] [lport 1 -3] [regAddr]          > get_port_reg     - gets value of the port register\n");
+    off += sprintf(buf+off, "echo [owner_id] [lport 1 -3]                    > get_port_cntrs   - gets and clear all RMON counters of the given port\n");
+    off += sprintf(buf+off, "echo [owner_id] [db_num = 0 or other]           > get_fdb          - gets all FDB table.\n");
+    off += sprintf(buf+off, "echo                                            > sw_init          - Init the Amber SW API DB\n");
+    off += sprintf(buf+off, "echo [debug_trace 0 - 1]                        > debug_trace      - Enable/disable TPM switch trace\n");
+    off += sprintf(buf+off, "========================================================================================================================\n");
+
+    return(off);
+}
+
+
+static ssize_t dbg_sw_store(struct device *dev,
+                         struct device_attribute *attr,
+                         const char *buf, size_t len)
+{
+    const char* name = attr->attr.name;
+//     unsigned long flags  = 0;
+    unsigned int  param1 = 0;
+    unsigned int  param2 = 0;
+    unsigned int  param3 = 0;
+    unsigned int  param4 = 0;
+
+    if (!capable(CAP_NET_ADMIN))
+    return -EPERM;
+
+    sscanf(buf, "%d %d %d %d", &param1, &param2,&param3,&param4);
+
+    printk(KERN_INFO "param1[%d],param2[%d],param3[%d],param4[%d]\n",
+          param1,param2,param3,param4);
+
+//     raw_local_irq_save(flags);
+
+    if (!strcmp(name, "set_global_reg"))
+        sfs_tpm_sw_set_global_reg((MV_U32)param1,(MV_U32)param2, (MV_U32)param3);
+
+    else if (!strcmp(name, "get_global_reg"))
+        sfs_tpm_sw_get_global_reg((MV_U32)param1,(MV_U32)param2);
+
+    else if (!strcmp(name, "set_port_reg"))
+        sfs_tpm_sw_set_port_reg((MV_U32)param1 ,(MV_U32)param2 ,(MV_U8)param3,(MV_U8)param4);
+
+    else if (!strcmp(name, "get_port_reg"))
+        sfs_tpm_sw_get_port_reg((MV_U32)param1 ,(MV_U32)param2 ,(MV_U8)param3);
+
+    else if (!strcmp(name, "get_port_cntrs"))
+        sfs_tpm_sw_get_port_cntrs((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_fdb"))
+        sfs_tpm_sw_get_fdb((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "sw_init"))
+        sfs_tpm_sw_init();
+
+    else if (!strcmp(name, "debug_trace"))
+        sfs_tpm_sw_set_debug_trace_flag((MV_U32)param1);
+
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+//     raw_local_irq_restore(flags);
+
+    return(len);
+}
+
+/* ========================================================================== */
+/*                            Info Commands                                   */
+/* ========================================================================== */
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static ssize_t dbg_sw_show(struct device *dev,
+                        struct device_attribute *attr,
+                        char *buf)
+{
+  const char* name = attr->attr.name;
+
+  if (!capable(CAP_NET_ADMIN))
+      return -EPERM;
+
+  if (!strcmp(name, "help_sw_dbg"))
+      return (sfs_tpm_sw_dbg_help_show(buf));
+
+  return 0;
+}
+#else
+static ssize_t dbg_sw_show(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+	printk(KERN_WARNING "%s: sysfs help is not compiled (CONFIG_MV_TPM_SYSFS_HELP)\n", __FUNCTION__);
+	return 0;
+}
+#endif
+
+/* ========================================================================== */
+/*                            get SW Attributes                                 */
+/* ========================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_admin
+*
+* DESCRIPTION:
+*       This function return the port administration state, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_admin
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    bool port_state;
+
+    tpm_phy_get_port_admin_state(owner_id, (tpm_src_port_type_t)lport, &port_state);
+
+    printk(KERN_INFO "The administration state of lport[%d] is [%s]\n", lport, ((true==port_state)? "enabled":"disabled"));
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_link_status
+*
+* DESCRIPTION:
+*       This function return the port flow control status, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_link_status
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+	bool link_status;
+
+    tpm_phy_get_port_link_status(owner_id, (tpm_src_port_type_t)lport, &link_status);
+
+    printk(KERN_INFO "The current link status of lport[%d] is [%s]\n", lport, ((true==link_status)? "UP":"DOWN"));
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_autoneg
+*
+* DESCRIPTION:
+*       This function return the port auto negotiation state and mode.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_autoneg
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    bool               autoneg_state;
+    tpm_autoneg_mode_t autoneg_mode;
+
+    tpm_phy_get_port_autoneg_mode(owner_id, (tpm_src_port_type_t)lport, &autoneg_state, &autoneg_mode);
+
+    printk(KERN_INFO "The auto negotiation state of lport[%d] is [%s], mode[%d](0:SPEED_AUTO_DUPLEX_AUTO, 1:SPEED_1000_DUPLEX_AUTO, 2:SPEED_100_DUPLEX_AUTO, 3:SPEED_10_DUPLEX_AUTO, 4:SPEED_AUTO_DUPLEX_FULL, 5:SPEED_AUTO_DUPLEX_HALF, 6:SPEED_1000_DUPLEX_FULL, 7:SPEED_1000_DUPLEX_HALF, 8:SPEED_100_DUPLEX_FULL, 9:SPEED_100_DUPLEX_HALF, 10:SPEED_10_DUPLEX_FULL, 11:SPEED_10_DUPLEX_HALF)\n", lport, ((true==autoneg_state)? "enabled":"disabled"), autoneg_mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_duplex_config
+*
+* DESCRIPTION:
+*       This function return the port duplex mode, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_duplex_config
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    bool duplex_mode;
+
+    tpm_phy_get_port_duplex_mode(owner_id, (tpm_src_port_type_t)lport, &duplex_mode);
+
+    printk(KERN_INFO "The duplex configuration of lport[%d] is [%s]\n", lport, ((true==duplex_mode)? "enabled":"disabled"));
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_duplex_status
+*
+* DESCRIPTION:
+*       This function return the port duplex current status, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_duplex_status
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    bool duplex_status;
+
+    tpm_phy_get_port_duplex_status(owner_id, (tpm_src_port_type_t)lport, &duplex_status);
+
+    printk(KERN_INFO "The duplex status of lport[%d] is [%s]\n", lport, ((true==duplex_status)? "enabled":"disabled"));
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_fc_config
+*
+* DESCRIPTION:
+*       This function return the port flow control configuration state, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_fc_config
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    bool fc_state;
+
+    tpm_phy_get_port_flow_control_support(owner_id, (tpm_src_port_type_t)lport, &fc_state);
+
+    printk(KERN_INFO "The flow control configuration of lport[%d] is [%s]\n", lport, ((true==fc_state)? "enabled":"disabled"));
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_fc_status
+*
+* DESCRIPTION:
+*       This function return the port flow control status, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_fc_status
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    bool fc_state;
+
+    tpm_phy_get_port_flow_control_state(owner_id, (tpm_src_port_type_t)lport, &fc_state);
+
+    printk(KERN_INFO "The flow control status of lport[%d] is [%s]\n", lport, ((true==fc_state)? "enabled":"disabled"));
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_speed_config
+*
+* DESCRIPTION:
+*       This function return the port speed configuration state, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_speed_config
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    tpm_phy_speed_t speed;
+
+    tpm_phy_get_port_speed(owner_id, (tpm_src_port_type_t)lport, &speed);
+
+    printk(KERN_INFO "The speed configuration of lport[%d] is [%d]('0'-10M, '1'-100M, '2'-1000M)\n", lport, speed);
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_speed_status
+*
+* DESCRIPTION:
+*       This function return the port speed status, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_speed_status
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    MV_U32   speed;
+
+    tpm_phy_get_port_speed_mode(owner_id, (tpm_src_port_type_t)lport, &speed);
+
+    printk(KERN_INFO "The speed status of lport[%d] is [%d]('0'-10M, '1'-100M, '2'-1000M)\n", lport, speed);
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_isolate_vector
+*
+* DESCRIPTION:
+*       This function return the port isolation vector, enabled or isolated.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_isolate_vector
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    MV_U32   vector;
+
+    tpm_sw_get_isolate_eth_port_vector(owner_id, (tpm_src_port_type_t)lport, &vector);
+
+    printk(KERN_INFO "The isolation vector of lport[%d] is [0x%02x]('0'-isolate, '1'-enable, bit0-UNI0, bit1-UNI1...)\n", lport, vector);
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_loopback
+*
+* DESCRIPTION:
+*       This function return the port loopback status, enabled or disabled.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*       mode         - 0:internal loopback, 1:external loopback.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_loopback
+(
+    MV_U32                owner_id,
+    MV_U32                lport,
+    MV_U32                mode
+)
+{
+    tpm_phy_loopback_mode_t loopback_mode;
+    bool                    status;
+
+    if(mode > TPM_PHY_EXTERNAL_LOOPBACK)
+        loopback_mode = TPM_PHY_EXTERNAL_LOOPBACK;
+    else
+        loopback_mode = (tpm_phy_loopback_mode_t)mode;
+
+    tpm_phy_get_port_loopback(owner_id, (tpm_src_port_type_t)lport, loopback_mode, &status);
+
+    printk(KERN_INFO "The [%d]('0'-internal, '1'-external) loopback status of lport[%d] is [%s]\n", loopback_mode, lport, ((true==status)? "enabled":"disabled"));
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_mac_age_time
+*
+* DESCRIPTION:
+*       The API Configures the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_mac_age_time
+(
+    IN uint32_t                 owner_id
+)
+{
+    MV_U32      time_out;
+
+    tpm_sw_get_mac_age_time(owner_id, &time_out);
+
+    printk(KERN_INFO "The time out is [%d]\n",time_out);
+
+     return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_max_macs
+*
+* DESCRIPTION:
+*       This function return the limit number of MAC addresses per lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_max_macs
+(
+    MV_U32                owner_id,
+    MV_U32                lport
+)
+{
+    uint32_t               limit;
+
+    tpm_sw_get_port_max_macs(owner_id, (tpm_src_port_type_t)lport, &limit);
+
+    printk(KERN_INFO "The limit number of MAC addresses per lport[%d] is [%d]\n",lport,limit);
+
+    return;
+
+}
+
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_mac_learn
+*
+* DESCRIPTION:
+*       This function return MAC learning state.
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*
+* OUTPUTS:
+        NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_mac_learn
+(
+    MV_U32      owner_id,
+    MV_U32      lport
+)
+{
+    bool   status;
+
+    tpm_sw_get_mac_learn(owner_id, (tpm_src_port_type_t)lport, &status);
+
+    printk(KERN_INFO "The MAC learning status of lport[%d] is [%s]\n", lport, ((true==status)? "enabled":"disabled"));
+
+    return;
+
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_flooding
+*
+* DESCRIPTION:
+*       This function gets Forward Unknown mode of a switch lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       egress_port     - Egress lport for applying the flood settings.
+
+*
+* OUTPUTS:
+*       mode  - NONE.
+*
+* RETURNS:
+*      None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_flooding
+(
+    MV_U32           owner_id,
+    MV_U32           lport
+)
+{
+    uint8_t          mode;
+
+    tpm_sw_get_port_flooding(owner_id, (tpm_src_port_type_t)lport, TPM_FLOOD_UNKNOWN_UNICAST, &mode);
+
+    printk(KERN_INFO "The Forward Unknown mode of a switch lport[%d] is [%d]\n",lport,mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_mc_flooding
+*
+* DESCRIPTION:
+*       This function gets Forward Unknown Multicast mode of a switch lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       egress_port     - Egress lport for applying the flood settings.
+
+*
+* OUTPUTS:
+*       mode  - NONE.
+*
+* RETURNS:
+*      None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_mc_flooding
+(
+    MV_U32           owner_id,
+    MV_U32           lport
+)
+{
+    uint8_t          mode;
+
+    tpm_sw_get_port_flooding (owner_id, (tpm_src_port_type_t)lport, TPM_FLOOD_UNKNOWN_MULTI_BROAD_CAST,&mode);
+
+    printk(KERN_INFO "The Forward Unknown Multicast mode of a switch lport[%d] is [%d]\n",lport,mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_bc_flooding
+*
+* DESCRIPTION:
+*       This function gets Forward Broadcast mode of a switch lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       egress_port     - Egress lport for applying the flood settings.
+
+*
+* OUTPUTS:
+*       mode  - NONE.
+*
+* RETURNS:
+*      None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_bc_flooding
+(
+    MV_U32           owner_id
+)
+{
+
+    bool  mode;
+
+    tpm_sw_get_broadcast_flood(owner_id, &mode);
+
+    printk(KERN_INFO "The Broadcast flooding is [%s]\n",(mode==true)?"allowed":"forbidden");
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_tagged
+*
+* DESCRIPTION:
+*       The API gets DiscardTagged bit for the given lport
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport         -  lport for applying the filtering of tagged packets.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*      None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_tagged
+(
+    MV_U32    owner_id,
+    MV_U32    lport
+)
+{
+
+    uint32_t     mode;
+
+    tpm_sw_get_port_tagged(owner_id, (tpm_src_port_type_t)lport, &mode);
+
+    printk(KERN_INFO "The DiscardTagged bit for the given lport[%d] is [%d]\n",lport, mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_untagged
+*
+* DESCRIPTION:
+*       The API  gets DiscardUntagged bit for the given lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport         -  lport for applying the filtering of tagged packets.
+
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_untagged
+(
+    MV_U32    owner_id,
+    MV_U32    lport
+)
+{
+
+    uint32_t     mode;
+
+    tpm_sw_get_port_untagged(owner_id, (tpm_src_port_type_t)lport, &mode);
+
+    printk(KERN_INFO "The DiscardUnTagged bit for the given lport[%d] is [%d]\n",lport, mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_def_vlan
+*
+* DESCRIPTION:
+*       The API gets port default vlan id.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       lport       - lport for applying the filtering of tagged packets.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_def_vlan
+(
+    MV_U32    owner_id,
+    MV_U32    lport
+)
+{
+    MV_U16    vid;
+    tpm_sw_get_port_def_vlan(owner_id,(tpm_src_port_type_t)lport,&vid);
+    printk(KERN_INFO "The default vlan id of port[%d] is [%d]\n",lport,vid);
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_def_pri
+*
+* DESCRIPTION:
+*       The API gets port default priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       lport       - lport for applying the filtering of tagged packets.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_def_pri
+(
+    MV_U32    owner_id,
+    MV_U32    lport
+)
+{
+    MV_U8     pri;
+
+    tpm_sw_get_port_def_pri(owner_id,(tpm_src_port_type_t)lport,&pri);
+    printk(KERN_INFO "The default priority of port[%d] is [%d]\n",lport,pri);
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_vid
+*
+* DESCRIPTION:
+*       The API look for vid in VTU DB.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       vid     -  lport for adding the vid.
+
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_vid
+(
+    MV_U32    owner_id,
+    MV_U32    vid
+)
+{
+
+  MV_U32 found;
+
+  tpm_sw_port_get_vid(owner_id, (tpm_src_port_type_t)vid ,&found);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_vid_filter
+*
+* DESCRIPTION:
+*        This routine gets protected mode of a switch lport.
+*        When this mode is set to GT_TRUE, frames are allowed to egress lport
+*        defined by the 802.1Q VLAN membership for the frame's VID 'AND'
+*        by the lport's VLANTable if 802.1Q is enabled on the lport. Both must
+*        allow the frame to Egress.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport        -  lport for setting the filtering mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*        NONE
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void  sfs_tpm_sw_get_port_vid_filter
+(
+    MV_U32    owner_id,
+    MV_U32    lport
+)
+{
+
+    uint32_t     mode;
+
+    tpm_sw_get_vid_filter_per_port(owner_id, (tpm_src_port_type_t)lport, &mode);
+
+    printk(KERN_INFO "The protected mode of a switch lport[%d] is [%d]\n", lport, mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*        This routine retrieves the port's ingress data limit based on burst size.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+
+*
+* OUTPUTS:
+*       NONE.
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_uni_ingr_police_rate
+(
+    MV_U32      owner_id,
+    MV_U32      uni_port
+)
+{
+    MV_U32  count_mode;
+    MV_U32  cir;
+    MV_U32  cbs;
+    MV_U32  ebs;
+
+    tpm_sw_get_uni_ingr_police_rate(owner_id,(tpm_src_port_type_t)uni_port,&count_mode,&cir, &cbs, &ebs);
+
+    printk(KERN_INFO "The uni_port[%d] ingress data limit mode[%d], cir[%d] cbs[%d] ebs[%d]\r\n",
+           uni_port, count_mode, cir, cbs, ebs);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures a policer function for a traffic class for an Ethernet UNI lport.
+*       There are 4 globally defined traffic classes in the integrated switch.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*       tc       - traffic class ( a combination of p-bits and DSCP values).
+*
+* OUTPUTS:
+*       NONE.
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_uni_tc_ingr_police_rate
+(
+    MV_U32      owner_id,
+    MV_U32      uni_port
+
+)
+{
+	uint32_t	cir[5];
+	uint32_t	tc[5];
+	uint32_t	cbs[5];
+	uint32_t	i;
+
+	tpm_sw_get_uni_tc_ingr_police_rate(owner_id,(tpm_src_port_type_t)uni_port,tc,cir,cbs);
+
+	printk(KERN_INFO "The uni_port[%d]: \n",uni_port);
+	for(i = 0; i < 5; i ++) {
+		if(tc[i])
+			printk(KERN_INFO "                ingress data limit[%d] for tc[0x%x]\n", cir[i] ,tc[i]);
+	}
+
+	return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API return the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*       trg_lport            - uni lport for configuring the egress rate limit.
+
+*
+* OUTPUTS:
+*       NONE.
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_uni_egr_rate_limit
+(
+    MV_U32              owner_id,
+    MV_U32              trg_lport
+)
+{
+    tpm_limit_mode_t  mode;
+    MV_U32            frame_rate_limit_val;
+
+    tpm_sw_get_uni_egr_rate_limit(owner_id,(tpm_src_port_type_t)trg_lport,&mode, &frame_rate_limit_val);
+
+    printk(KERN_INFO "The egress frame rate limit is [%d] mode[%d] for trg_lport[%d]\n",
+           frame_rate_limit_val, mode, trg_lport);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_vlan_ports
+*
+* DESCRIPTION:
+*           This routine gets the port VLAN group port membership list.
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*       lport               - logical port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_vlan_ports
+(
+    IN uint32_t                 owner_id,
+    IN uint32_t                 lport
+)
+{
+   uint32_t             memPorts[TPM_MAX_NUM_PORTS];
+   uint8_t              memPortsLen;
+   uint32_t             i;
+
+   memset(memPorts, 0, sizeof(GT_LPORT)*TPM_MAX_NUM_PORTS);
+
+   tpm_sw_get_port_vlan_ports(owner_id, (tpm_src_port_type_t)lport, memPorts, &memPortsLen);
+
+   for (i = 0; i < memPortsLen; i++)
+   {
+       if (memPorts[i] > 0)
+       {
+           printk("memPorts[%d] = %02d\n\r",i,memPorts[i]);
+       }
+
+   }
+
+     return;
+}
+
+
+/*******************************************************************************
+* sfs_tpm_sw_get_ingress_limit_mode
+*
+* DESCRIPTION:
+*           This routine gets the port's rate control ingress limit mode.
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*       lport               - logical port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_ingress_limit_mode
+(
+    uint32_t             owner_id,
+    uint32_t             lport
+)
+{
+    GT_RATE_LIMIT_MODE   mode;
+
+
+   tpm_sw_get_ingress_limit_mode(owner_id, (tpm_src_port_type_t)lport, &mode);
+
+   printk("lport [%d] mode[%d]\n\r",lport,mode);
+
+   return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_priority_selection
+*
+* DESCRIPTION:
+*       This function gets initial QPri and FPri selection.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to set init pri.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_priority_selection
+(
+    uint32_t owner_id,
+    uint8_t  lport
+)
+{
+    uint8_t init_pri;
+    bool    tag_if_both;
+
+    tpm_sw_get_priority_selection(owner_id,(tpm_src_port_type_t)lport,&init_pri,&tag_if_both);
+
+    printk("UNI port[%d] init_pri[%s] tag_if_both[%s]\n\r",lport,
+            sw_qos_init_pri_str[init_pri < PRI_SEL_TYPE_MAX ? init_pri : PRI_SEL_TYPE_MAX], (tag_if_both==true)?"TRUE":"FALSE");
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This function gets tag priority mapping.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       tag_pri     - Source tag priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_tag_pri_mapping
+(
+    IN  uint32_t owner_id,
+    IN  uint8_t  tag_pri
+)
+{
+    uint8_t q_pri;
+
+    tpm_sw_get_tag_pri_mapping(owner_id,tag_pri,&q_pri);
+
+    printk("tag_pri[%d] -> q_pri[%d]\n\r",tag_pri,q_pri);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This function gets the queue priority for a dscp value mapping to.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       dscp        - Source dscp value.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_ip_pri_mapping
+(
+    IN  uint32_t owner_id,
+    IN  uint8_t  dscp
+)
+{
+    uint8_t q_pri;
+
+    tpm_sw_get_ip_pri_mapping(owner_id,dscp,&q_pri);
+
+    printk("dscp[%d] -> q_pri[%d]\n\r",dscp,q_pri);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_gmac_mtu
+*
+* DESCRIPTION:
+*       This function gets the MTU of GMAC.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       gmac        - GMAC, '0'-GMAC0, '1'-GMAC1, '02'-PONMAC, '3'-switch.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_gmac_mtu
+(
+    IN  uint32_t  owner_id,
+    IN  uint32_t  gmac
+)
+{
+    tpm_mru_type_t type;
+    uint32_t       mtu;
+
+    if(gmac > TPM_NETA_MTU_SWITCH)
+        type = TPM_NETA_MTU_SWITCH;
+    else
+        type = (tpm_mru_type_t)gmac;
+
+    tpm_get_mtu_size(owner_id, type, &mtu);
+
+    printk("The MTU of GMAC[%d]('0'-GMAC0, '1'-GMAC1, '02'-PONMAC, '3'-switch) is [%d]\n\r", gmac, mtu);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_get_port_mirror
+*
+* DESCRIPTION:
+*       This function gets port mirror state.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - src UNI port(1-4).
+*       dst_port    - dst UNI port(1-4).
+*       mode        - mirror mode, '0'-ingress mirror, '1'-egress mirror.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+*
+*******************************************************************************/
+void sfs_tpm_sw_get_port_mirror
+(
+    IN  uint32_t  owner_id,
+    IN  uint32_t  src_port,
+    IN  uint32_t  dst_port,
+    IN  uint32_t  mode
+)
+{
+    tpm_sw_mirror_type_t mirror_mode;
+    bool                 mirror_state;
+
+    if(mode > TPM_SW_MIRROR_EGRESS)
+        mirror_mode = TPM_SW_MIRROR_EGRESS;
+    else
+        mirror_mode = (tpm_sw_mirror_type_t)mode;
+
+    tpm_sw_get_port_mirror(owner_id, src_port, dst_port, mirror_mode, &mirror_state);
+
+    printk("The src_port[%d] dst_port[%d] mode[%d]('0'-ingress, '1'-egress) mirror status is [%s]\n\r", src_port, dst_port, mirror_mode, ((true==mirror_state)? "enabled":"disabled"));
+}
+
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+/*******************************************************************************
+**
+**  sfs_tpm_sw_get_help_show
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_tpm_sw_get_help_show(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "========================================================================================================================\n");
+    off += sprintf(buf+off, "                                          Configuration Switch Commands\n");
+    off += sprintf(buf+off, "                                          Insert all parameters in Decimal\n");
+    off += sprintf(buf+off, "========================================================================================================================\n");
+    off += sprintf(buf+off, "cat help_sw_get_info                                                  - show this help\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_admin              - get port administration state\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_link_status        - get port current link status\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_autoneg            - get port auto negotiation state and mode\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_duplex_config      - get port duplex configuration\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_duplex_status      - get port duplex current status\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_fc_config          - get port flow control configuration\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_fc_status          - get port flow control current status\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_speed_config       - get port speed configuration\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_speed_status       - get port speed current status\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_isolate_vector     - get port isolation vector\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [mode]   > get_port_loopback           - get port loopback status, mode('0'-internal, '1'-external)\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id]                         > get_mac_age_time            - get the MAC aging time\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_max_macs           - get port maximum number of allowed MAC address to be learned\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_mac_learn          - get port MAC learning state, disabled or enabled\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_flooding           - get Forward Unknown mode\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_mc_flooding        - get Forward Unknown mode\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id]                         > get_bc_flooding             - get Forward Unknown mode\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_tagged             - get DiscardTagged bits\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_untagged           - get DiscardUntagged bit\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_vid_filter         - get the filtering mod VID\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_def_vlan           - get port default vlan\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_def_pri            - get port default priority\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [vid 0-4095]            > get_port_vid                - get port VID if it exist\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_uni_ingr_police_rate    - get the port's ingress data limit by burst size\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_uni_tc_ingr_police_rate - get the port's ingress data limit for tc\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_uni_egr_rate_limit      - get the port's egress frame rate limit\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_port_vlan_ports         - get the port VLAN group port membership list\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]          > get_init_pri                - get initial priority\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [pri 0-7]               > get_tag_pri_mapping         - get tag pri mapping\n");
+    off += sprintf(buf+off, "echo [owner_id] [dscp 0-63]             > get_ip_pri_mapping          - get ip pri mapping\n");
+    off += sprintf(buf+off, "echo [owner_id] [gmac]                  > get_gmac_mtu                - get GMAC MTU ('0'-GMAC0, '1'-GMAC1, '2'-PMAC, '3'-switch)\n");
+    off += sprintf(buf+off, "echo [owner_id] [sport][dport][mode]    > get_port_mirror             - get port mirro, src port/dst port(uni port 1-4), mode('0'-ingress, '1'-egress)\n");
+    off += sprintf(buf+off, "========================================================================================================================\n");
+
+    return(off);
+}
+#endif
+
+/* ========================================================================== */
+/*                            Info Group                                      */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Info Commands                                   */
+/* ========================================================================== */
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static ssize_t get_sw_show(struct device *dev,
+                        struct device_attribute *attr,
+                        char *buf)
+{
+  const char* name = attr->attr.name;
+
+  if (!capable(CAP_NET_ADMIN))
+      return -EPERM;
+
+  if (!strcmp(name, "help_sw_get_info"))
+      return (sfs_tpm_sw_get_help_show(buf));
+
+  return 0;
+}
+#else
+static ssize_t get_sw_show(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+	printk(KERN_WARNING "%s: sysfs help is not compiled (CONFIG_MV_TPM_SYSFS_HELP)\n", __FUNCTION__);
+	return 0;
+}
+#endif
+
+static ssize_t get_sw_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t len)
+{
+    const char* name = attr->attr.name;
+//     unsigned long flags;
+    unsigned int  param1 = 0;
+    unsigned int  param2 = 0;
+    unsigned int  param3 = 0;
+    unsigned int  param4 = 0;
+
+    if (!capable(CAP_NET_ADMIN))
+    return -EPERM;
+
+    if (!strcmp(name, "get_port_mirror"))
+    {
+        sscanf(buf, "%d %d %d %d",
+               &param1, &param2, &param3, &param4);
+    }
+    else
+    {
+        sscanf(buf, "%d %d %d", &param1, &param2, &param3);
+    }
+
+    printk(KERN_INFO "param1[%d],param2[%d],param3[%d]\n",param1,param2,param3);
+
+//     raw_local_irq_save(flags);
+
+    if (!strcmp(name, "get_port_admin"))
+        sfs_tpm_sw_get_port_admin((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_link_status"))
+        sfs_tpm_sw_get_port_link_status((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_autoneg"))
+        sfs_tpm_sw_get_port_autoneg((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_duplex_config"))
+        sfs_tpm_sw_get_port_duplex_config((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_duplex_status"))
+        sfs_tpm_sw_get_port_duplex_status((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_fc_config"))
+        sfs_tpm_sw_get_port_fc_config((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_fc_status"))
+        sfs_tpm_sw_get_port_fc_status((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_speed_config"))
+        sfs_tpm_sw_get_port_speed_config((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_speed_status"))
+        sfs_tpm_sw_get_port_speed_status((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_isolate_vector"))
+        sfs_tpm_sw_get_port_isolate_vector((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_loopback"))
+        sfs_tpm_sw_get_port_loopback((MV_U32)param1, (MV_U32)param2, (MV_U32)param3);
+
+    else if (!strcmp(name, "get_port_max_macs"))
+        sfs_tpm_sw_get_port_max_macs((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_mac_learn"))
+        sfs_tpm_sw_get_port_mac_learn((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_flooding"))
+        sfs_tpm_sw_get_port_flooding((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_mc_flooding"))
+        sfs_tpm_sw_get_port_mc_flooding((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_bc_flooding"))
+        sfs_tpm_sw_get_bc_flooding((MV_U32)param1);
+
+    else if (!strcmp(name, "get_port_tagged"))
+        sfs_tpm_sw_get_port_tagged((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_untagged"))
+      sfs_tpm_sw_get_port_untagged((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_def_vlan"))
+      sfs_tpm_sw_get_port_def_vlan((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_def_pri"))
+        sfs_tpm_sw_get_port_def_pri((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_vid"))
+        sfs_tpm_sw_get_port_vid((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_vid_filter"))
+      sfs_tpm_sw_get_port_vid_filter((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_uni_ingr_police_rate"))
+        sfs_tpm_sw_get_uni_ingr_police_rate((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_uni_tc_ingr_police_rate"))
+        sfs_tpm_sw_get_uni_tc_ingr_police_rate((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_uni_egr_rate_limit"))
+        sfs_tpm_sw_get_uni_egr_rate_limit((MV_U32)param1, (MV_U32)param2);
+
+    else if (!strcmp(name, "get_mac_age_time"))
+        sfs_tpm_sw_get_mac_age_time((MV_U32)param1);
+
+    else if (!strcmp(name, "get_port_vlan_ports"))
+        sfs_tpm_sw_get_port_vlan_ports((MV_U32)param1,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_port_vlan_ports"))
+        sfs_tpm_sw_get_port_vlan_ports((MV_U32)param1,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_ingress_limit_mode"))
+        sfs_tpm_sw_get_ingress_limit_mode((MV_U32)param1,(MV_U32)param2);
+
+    else if (!strcmp(name, "get_init_pri"))
+        sfs_tpm_sw_get_priority_selection((MV_U32)param1,(MV_U8)param2);
+
+    else if (!strcmp(name, "get_tag_pri_mapping"))
+        sfs_tpm_sw_get_tag_pri_mapping((MV_U32)param1,(MV_U8)param2);
+
+    else if (!strcmp(name, "get_ip_pri_mapping"))
+        sfs_tpm_sw_get_ip_pri_mapping((MV_U32)param1,(MV_U8)param2);
+
+    else if (!strcmp(name, "get_gmac_mtu"))
+        sfs_tpm_sw_get_gmac_mtu((MV_U32)param1,(MV_U8)param2);
+
+    else if (!strcmp(name, "get_port_mirror"))
+        sfs_tpm_sw_get_port_mirror((MV_U32)param1, (MV_U32)param2, (MV_U32)param3, (MV_U32)param4);
+
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+//     raw_local_irq_restore(flags);
+
+    return(len);
+}
+
+/* ========================================================================== */
+/*                            Set SW Attributes                                 */
+/* ========================================================================== */
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_admin
+*
+* DESCRIPTION:
+*       This function set the port administration state
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       state         - port administration state, 1:enable, 0:disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_admin
+(
+    MV_U32               owner_id,
+    MV_U32               lport,
+    MV_U32               state
+)
+{
+    bool admin_state;
+
+    admin_state = ((1 == state) ? true: false);
+    tpm_phy_set_port_admin_state(owner_id, (tpm_src_port_type_t)lport, admin_state);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_autoneg
+*
+* DESCRIPTION:
+*       This function set the port auto negotiation
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       state         - port auto negotiation  state, 1:enable, 0:disable.
+*       mode          - port auto negotiation  mode:
+*                       Auto for both speed and duplex.
+*                       Auto for speed only and Full duplex.
+*                       Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                       Auto for duplex only and speed 1000Mbps.
+*                       Auto for duplex only and speed 100Mbps.
+*                       Auto for duplex only and speed 10Mbps.
+*                       1000Mbps Full duplex.
+*                       100Mbps Full duplex.
+*                       100Mbps Half duplex.
+*                       10Mbps Full duplex.
+*                       10Mbps Half duplex.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_autoneg
+(
+    MV_U32               owner_id,
+    MV_U32               lport,
+    MV_U32               state,
+    MV_U32               mode
+)
+{
+    bool               autoneg_state;
+    tpm_autoneg_mode_t autoneg_mode;
+
+    autoneg_state = ((1 == state) ? true: false);
+
+    autoneg_mode = ((mode > TPM_SPEED_10_DUPLEX_HALF ) ? TPM_SPEED_10_DUPLEX_HALF: (tpm_autoneg_mode_t)mode);
+    tpm_phy_set_port_autoneg_mode(owner_id, (tpm_src_port_type_t)lport, autoneg_state, autoneg_mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_restart_autoneg
+*
+* DESCRIPTION:
+*       This function restart the port auto negotiation
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_restart_autoneg
+(
+    MV_U32               owner_id,
+    MV_U32               lport
+)
+{
+    tpm_phy_restart_port_autoneg(owner_id, (tpm_src_port_type_t)lport);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_duplex
+*
+* DESCRIPTION:
+*       This function set the port duplex mode
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       mode          - port duplex mode, 1:enable, 0:disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_duplex
+(
+    MV_U32               owner_id,
+    MV_U32               lport,
+    MV_U32               mode
+)
+{
+    bool duplex_mode;
+
+    duplex_mode = ((1 == mode) ? true: false);
+    tpm_phy_set_port_duplex_mode(owner_id, (tpm_src_port_type_t)lport, duplex_mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_fc
+*
+* DESCRIPTION:
+*       This function set the port flow control
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       state         - port flow control configuration, 1:enable, 0:disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_fc
+(
+    MV_U32      owner_id,
+    MV_U32      lport,
+    MV_U32      state
+)
+{
+    bool fc_state;
+
+    fc_state = ((1 == state) ? true: false);
+    tpm_phy_set_port_flow_control_support(owner_id, (tpm_src_port_type_t)lport, fc_state);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_speed
+*
+* DESCRIPTION:
+*       This function set the port speed
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       speed_mode    - speed mode, '0'-10M, '1'-100M, '2'-1000M.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_speed
+(
+    MV_U32               owner_id,
+    MV_U32               lport,
+    MV_U32               speed_mode
+)
+{
+    tpm_phy_speed_t speed;
+
+    if((tpm_phy_speed_t)speed_mode > TPM_PHY_SPEED_1000_MBPS)
+        speed = (tpm_phy_speed_t)TPM_PHY_SPEED_1000_MBPS;
+    else
+        speed = (tpm_phy_speed_t)speed_mode;
+
+    tpm_phy_set_port_speed(owner_id, (tpm_src_port_type_t)lport, speed);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_isolate_vector
+*
+* DESCRIPTION:
+*       This function set the port isolation vector
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       vector        - '0'-isolate, '1'-enable, bit0-UNI0, bit1-UNI1...
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_isolate_vector
+(
+    MV_U32               owner_id,
+    MV_U32               lport,
+    MV_U32               vector
+)
+{
+    tpm_sw_set_isolate_eth_port_vector(owner_id, (tpm_src_port_type_t)lport, vector);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_loopback
+*
+* DESCRIPTION:
+*       This function set the port loopback
+*
+* INPUTS:
+*       owner_id      - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       mode          - '0'-internal loopback, '1'-external loopback
+*       state         - '0'-disable, '1'-enable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_loopback
+(
+    MV_U32               owner_id,
+    MV_U32               lport,
+    MV_U32               mode,
+    MV_U32               state
+)
+{
+    tpm_phy_loopback_mode_t loopback_mode;
+    bool                    loopback_state;
+
+    if(mode > TPM_PHY_EXTERNAL_LOOPBACK)
+        loopback_mode = TPM_PHY_EXTERNAL_LOOPBACK;
+    else
+        loopback_mode = (tpm_phy_loopback_mode_t)mode;
+
+    loopback_state = ((1 == state) ? true: false);
+
+    tpm_phy_set_port_loopback(owner_id, (tpm_src_port_type_t)lport, loopback_mode, loopback_state);
+
+    return;
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+void tpm_sw_add_static_mac_bounce(uint32_t owner_id,
+				uint32_t lport,
+				uint8_t static_mac[6])
+{
+	tpm_ioctl_sw_mac_security_t *tpm_sw_mac_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_sw_mac_set;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_SW_SECURITY_SECTION;
+	tpm_sw_mac_set->sw_security_cmd = MV_TPM_IOCTL_SW_ADD_STATIC_MAC;
+	tpm_sw_mac_set->owner_id = owner_id;
+	tpm_sw_mac_set->port = lport;
+	memcpy(tpm_sw_mac_set->static_mac, (void*)static_mac, sizeof(uint8_t)*6);
+
+	up(&tpm_sfs_2_ioctl_sem);
+}
+ #define _tpm_sw_add_static_mac tpm_sw_add_static_mac_bounce
+#else
+ #define _tpm_sw_add_static_mac tpm_sw_add_static_mac
+#endif
+
+/*******************************************************************************
+* sfs_tpm_sw_add_static_mac
+*
+* DESCRIPTION:
+*       This function creates a static MAC entry in the MAC address table for a
+*       specific lport in the integrated switch
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*       static_mac    - 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_add_static_mac
+(
+    MV_U32               owner_id,
+    MV_U32               lport,
+    MV_U8                static_mac[6]
+)
+{
+    _tpm_sw_add_static_mac(owner_id,(tpm_src_port_type_t)lport,static_mac);
+
+    return;
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+void tpm_sw_del_static_mac_bounce(uint32_t owner_id,
+				uint8_t static_mac[6])
+{
+	tpm_ioctl_sw_mac_security_t *tpm_sw_mac_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_sw_mac_set;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_SW_SECURITY_SECTION;
+	tpm_sw_mac_set->sw_security_cmd = MV_TPM_IOCTL_SW_DEL_STATIC_MAC;
+	tpm_sw_mac_set->owner_id = owner_id;
+	memcpy(tpm_sw_mac_set->static_mac, (void*)static_mac, sizeof(uint8_t)*6);
+
+	up(&tpm_sfs_2_ioctl_sem);
+}
+ #define _tpm_sw_del_static_mac tpm_sw_del_static_mac_bounce
+#else
+ #define _tpm_sw_del_static_mac tpm_sw_del_static_mac
+#endif
+/*******************************************************************************
+* sfs_tpm_sw_del_static_mac
+*
+* DESCRIPTION:
+*       This function removes an existing static MAC entry from the MAC address
+*       table  in the integrated switch.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       static_mac    - 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_del_static_mac
+(
+    MV_U32        owner_id,
+    MV_U8         static_mac[6]
+)
+{
+    _tpm_sw_del_static_mac(owner_id,static_mac);
+
+     return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_clear_dynamic_mac
+*
+* DESCRIPTION:
+*       This function removes all dynamic MAC address in the integrated switch.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_clear_dynamic_mac
+(
+    MV_U32        owner_id
+)
+{
+    tpm_sw_clear_dynamic_mac(owner_id);
+
+     return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_add_static_mac
+*
+* DESCRIPTION:
+*       This function creates a static MAC entry in the MAC address table for a
+*       specific lport in the integrated switch
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*       static_mac    - 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_static_mac_w_mask
+(
+    MV_U32               owner_id,
+    MV_U32               ports_mask,
+    MV_U8                static_mac[6]
+)
+{
+    tpm_sw_set_static_mac_w_ports_mask(owner_id,ports_mask,static_mac);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_mac_age_time
+*
+* DESCRIPTION:
+*       The API Configures the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*       time_out            - table size
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_mac_age_time
+(
+    IN uint32_t                 owner_id,
+    IN uint32_t                    time_out
+)
+{
+    tpm_sw_set_mac_age_time(owner_id, time_out);
+
+    return;
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+void tpm_sw_set_port_max_macs_bounce(uint32_t owner_id,
+				uint32_t lport,
+				uint8_t mac_per_port)
+{
+	tpm_ioctl_sw_mac_security_t *tpm_sw_mac_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_sw_mac_set;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_SW_SECURITY_SECTION;
+	tpm_sw_mac_set->sw_security_cmd = MV_TPM_IOCTL_SW_SET_PORT_MAC_LIMIT;
+	tpm_sw_mac_set->owner_id = owner_id;
+	tpm_sw_mac_set->port = lport;
+	tpm_sw_mac_set->mac_per_port = mac_per_port;
+
+	up(&tpm_sfs_2_ioctl_sem);
+}
+ #define _tpm_sw_set_port_max_macs tpm_sw_set_port_max_macs_bounce
+#else
+ #define _tpm_sw_set_port_max_macs tpm_sw_set_port_max_macs
+#endif
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_max_macs
+*
+* DESCRIPTION:
+*       This function limits the number of MAC addresses per lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport         - Packet origination.
+*       mac_per_port - maximum number of MAC addresses per lport (1-255).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_max_macs
+(
+    MV_U32                  owner_id,
+    MV_U32                  lport,
+    MV_U8                     mac_per_port
+)
+{
+    tpm_sw_set_port_max_macs(owner_id,(tpm_src_port_type_t)lport,mac_per_port);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_mac_learn
+*
+* DESCRIPTION:
+*       This function set MAC learning ability of given lport
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport        - Packet origination.
+*       state        - MAC learning state. 0:disable, 1:enable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_mac_learn
+(
+    MV_U32      owner_id,
+    MV_U32      lport,
+    MV_U8       state
+)
+{
+    bool mac_state;
+
+    mac_state = ((1 == state) ? true: false);
+
+    tpm_sw_set_mac_learn(owner_id, (tpm_src_port_type_t)lport, mac_state);
+
+    return;
+}
+
+/*Evan*/
+#ifdef CONFIG_MV_TPM_SFS_2_IOCTL
+void tpm_sw_set_port_flooding_bounce(uint32_t owner_id,
+					tpm_src_port_type_t src_port,
+					tpm_flood_type_t    flood_mode,
+					uint8_t             allow_flood)
+{
+	tpm_ioctl_sw_mac_security_t *tpm_sw_mac_set = &tpm_sfs_2_ioctl_command.tpm_cmd_data.tpm_ioctl_sw_mac_set;
+
+	tpm_sfs_2_ioctl_command.cmd = MV_TPM_IOCTL_SW_SECURITY_SECTION;
+	tpm_sw_mac_set->sw_security_cmd = MV_TPM_IOCTL_SW_SET_PORT_FLOOD;
+	tpm_sw_mac_set->owner_id = owner_id;
+	tpm_sw_mac_set->port = src_port;
+	tpm_sw_mac_set->flood_mode = flood_mode;
+	tpm_sw_mac_set->allow_flood = allow_flood;
+
+	up(&tpm_sfs_2_ioctl_sem);
+}
+ #define _tpm_sw_set_port_flooding tpm_sw_set_port_flooding_bounce
+#else
+ #define _tpm_sw_set_port_flooding tpm_sw_set_port_flooding
+#endif
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_flooding
+*
+* DESCRIPTION:
+*       This function control the flooding behavior (unknown Dest MAC address) per lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       egress_port     - Egress lport for applying the flood settings.
+*       allow_flood  - permit flooding of unknown DA: set to 1,
+*                      do not permit flooding of uknown DA: set to 0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*      None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_flooding
+(
+    MV_U32           owner_id,
+    MV_U32           lport,
+    MV_U32           allow_flood
+)
+{
+    _tpm_sw_set_port_flooding(owner_id,(tpm_src_port_type_t)lport, TPM_FLOOD_UNKNOWN_UNICAST, allow_flood);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_mc_flooding
+*
+* DESCRIPTION:
+*       This function control the flooding behavior (unknown GDA) per lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       egress_port     - Egress lport for applying the flood settings.
+*       allow_flood  - permit flooding of unknown multicast: set to 1,
+*                      do not permit flooding of uknown multicast: set to 0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*      None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_mc_flooding
+(
+    MV_U32           owner_id,
+    MV_U32           lport,
+    MV_U32           allow_flood
+)
+{
+    tpm_sw_set_port_flooding (owner_id,(tpm_src_port_type_t)lport,TPM_FLOOD_UNKNOWN_MULTI_BROAD_CAST, allow_flood);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_bc_flooding
+*
+* DESCRIPTION:
+*       This function control the flooding behavior (broadcast address) per lport.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       allow_flood  - permit flooding of BC: set to 1,
+*                      do not permit flooding of BC: set to 0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*      None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_bc_flooding
+(
+    MV_U32           owner_id,
+    MV_U32           always_on
+)
+{
+    bool lFloodOn;
+    if(!always_on)
+        lFloodOn = true;
+    else
+        lFloodOn = false;
+    tpm_sw_set_broadcast_flood(owner_id,lFloodOn);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_tagged
+*
+* DESCRIPTION:
+*       The API allows or drops tagged packets on a per lport basis.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport         -  lport for applying the filtering of tagged packets.
+*       allow_tagged - set to 1 = allow tagged packets per lport
+*                      set to 0 = drop tagged packets per lport.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_tagged
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U8     allow_tagged
+)
+{
+    tpm_sw_set_port_tagged(owner_id,(tpm_src_port_type_t)lport,allow_tagged);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_untagged
+*
+* DESCRIPTION:
+*       The API allows or drops untagged packets on a per lport basis.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       lport         -  lport for applying the filtering of tagged packets.
+*       allow_untagged - set to 1 = allow tagged packets per lport
+*                      set to 0 = drop tagged packets per lport.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_untagged
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U8     allow_untagged
+)
+{
+    tpm_sw_set_port_untagged(owner_id,(tpm_src_port_type_t)lport,allow_untagged);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_def_vlan
+*
+* DESCRIPTION:
+*       The API sets port default vlan id.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       lport       - lport for applying the filtering of tagged packets.
+*       vid        - the port vlan id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_def_vlan
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U16    vid
+)
+{
+    tpm_sw_set_port_def_vlan(owner_id,(tpm_src_port_type_t)lport,vid);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_def_pri
+*
+* DESCRIPTION:
+*       The API sets port default priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       lport       - lport for applying the filtering of tagged packets.
+*       pri        - the port priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_def_pri
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U8     pri
+)
+{
+    tpm_sw_set_port_def_pri(owner_id,(tpm_src_port_type_t)lport,pri);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_port_add_vid
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of allowed VIDs per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       lport    -  lport for adding the vid.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_port_add_vid
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U16    vid
+)
+{
+    tpm_sw_port_add_vid(owner_id,(tpm_src_port_type_t)lport,vid);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_del_port_vid
+*
+* DESCRIPTION:
+*       The API delete the existed VID from the list of VIDs allowed per lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       lport    -  lport for deleting the VID.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_del_port_vid
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U16    vid
+)
+{
+    tpm_sw_port_del_vid(owner_id,(tpm_src_port_type_t)lport,vid);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_port_add_gvid
+*
+* DESCRIPTION:
+*       The API adds a group of VID to the list of allowed VIDs per lport.
+*
+* INPUTS:
+*       owner_id  - APP owner id - should be used for all API calls.
+*       lport     - lport for adding the vid.
+*       egr_mode  - VLAN egress mode.
+*       min_vid   - minimum VID.
+*       max_vid   - maximum VID.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_port_add_gvid
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U16    egr_mode,
+    MV_U16    min_vid,
+    MV_U16    max_vid
+)
+{
+    MV_U16    mode;
+
+    if(egr_mode > MEMBER_EGRESS_TAGGED)
+        mode = MEMBER_EGRESS_UNMODIFIED;
+    else
+        mode = egr_mode;
+
+    tpm_sw_port_add_vid_group(owner_id, (tpm_src_port_type_t)lport, (MV_U8)mode, min_vid, max_vid);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_del_port_gvid
+*
+* DESCRIPTION:
+*       The API delete the existed VID from the list of VIDs allowed per lport.
+*
+* INPUTS:
+*       owner_id  - APP owner id - should be used for all API calls.
+*       lport     - lport for deleting the VID.
+*       min_vid   - minimum VID.
+*       max_vid   - maximum VID.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_del_port_gvid
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U16    min_vid,
+    MV_U16    max_vid
+)
+{
+    tpm_sw_port_del_vid_group(owner_id, (tpm_src_port_type_t)lport, min_vid, max_vid);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_vid_egress_mode
+*
+* DESCRIPTION:
+*       The API sets the egress mode for a member port of a vlan.
+*
+* INPUTS:
+*       owner_id  - APP owner id - should be used for all API calls.
+*       lport     - logic port id to set
+*       vid       - vlan id
+*       eMode     - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_vid_egress_mode
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U16    vid,
+    MV_U8     eMode
+)
+{
+    tpm_sw_set_port_vid_egress_mode(owner_id,(tpm_src_port_type_t)lport,vid,eMode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_vid_filter_per_port
+*
+* DESCRIPTION:
+*       The API sets the filtering mode of a certain lport.
+*       If the lport is in filtering mode, only the VIDs added by the
+*       tpm_sw_port_add_vid API will be allowed to ingress and egress the lport.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport        -  lport for setting the filtering mode.
+*       vid_filter  - set to 1 - means the lport will DROP all packets which are NOT in
+*                    the allowed VID list (built using API tpm_sw_port_add_vid).
+*                    set to 0 - means that the list of VIDs allowed
+*                    per lport has no significance (the list is not deleted).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void  sfs_tpm_sw_set_vid_filter_per_port
+(
+    MV_U32    owner_id,
+    MV_U32    lport,
+    MV_U8     vid_filter
+)
+{
+    tpm_sw_port_set_vid_filter(owner_id,(tpm_src_port_type_t)lport,vid_filter);
+
+    return;
+}
+
+/*******************************************************************************
+* tpm_sw_set_uni_q_weight
+*
+* DESCRIPTION:
+*       The API configures the weight of a queue for all
+*       Ethernet UNI ports in the integrated switch.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       weight   - weight value per queue (1-8).queue (value 1-3).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_uni_q_weight
+(
+    MV_U32        owner_id,
+    MV_U8         queue_id,
+    MV_U8         weight
+)
+{
+    tpm_sw_set_uni_q_weight(owner_id,queue_id,weight);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures an ingress policing function for an Ethernet UNI lport.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*       mode     - policing mode.
+*       cir      - commited info rate.
+*       cbs      - commited burst rate
+*       ebs      - extra burst rate
+
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_uni_ingr_police_rate
+(
+    MV_U32      owner_id,
+    MV_U32      uni_port,
+    MV_U32      mode,
+    MV_U32      cir,
+    MV_U32      cbs,
+    MV_U32      ebs
+)
+{
+    MV_U32 count_mode;
+
+    if(mode > GT_PIRL_ELIMIT_LAYER3)
+        count_mode  = GT_PIRL_ELIMIT_LAYER2;
+    else
+        count_mode  = mode;
+
+    tpm_sw_set_uni_ingr_police_rate(owner_id, (tpm_src_port_type_t)uni_port, count_mode, cir, cbs, ebs);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures a policer function for a traffic class for an Ethernet UNI lport.
+*       There are 4 globally defined traffic classes in the integrated switch.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       uni_port - uni lport for configuring the ingress policer function.
+*       tc       - traffic class ( a combination of p-bits and DSCP values).
+*       cir      - comited info rate.
+*       cbs      - comited burst rate.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_uni_tc_ingr_police_rate
+(
+    MV_U32      owner_id,
+    MV_U32      uni_port,
+    MV_U32      tc,
+    MV_U32      cir,
+    MV_U32      cbs
+)
+{
+    tpm_sw_set_uni_tc_ingr_police_rate(owner_id,(tpm_src_port_type_t)uni_port,tc,cir,cbs);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API Configures the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*       trg_lport            - uni lport for configuring the egress rate limit.
+*       kb_rate_limit_val  - egress rate limit value.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_uni_egr_rate_limit
+(
+    IN uint32_t     owner_id,
+    IN uint32_t     trg_lport,
+    IN uint32_t     set_uni_egr_rate_limit
+)
+{
+    tpm_sw_set_uni_egr_rate_limit(owner_id,(tpm_src_port_type_t)trg_lport,TPM_SW_LIMIT_LAYER2,set_uni_egr_rate_limit);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API Configures the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id            - APP owner id - should be used for all API calls.
+*       size            - table size
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_atu_size
+(
+    IN uint32_t   owner_id,
+    IN uint32_t   size
+)
+{
+    tpm_sw_set_atu_size(owner_id, size);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_vlan_ports
+*
+* DESCRIPTION:
+*       The API Configures the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - logical port number to set.
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_vlan_ports
+(
+    IN uint32_t             owner_id,
+    IN uint32_t             lport,
+    IN uint32_t             memPorts[],
+    IN uint8_t              memPortsLen
+)
+{
+    tpm_sw_set_port_vlan_ports(owner_id,(tpm_src_port_type_t)lport,memPorts,memPortsLen);
+
+    return;
+}
+
+
+/*******************************************************************************
+* sfs_tpm_sw_set_ingress_limit_mode
+*
+* DESCRIPTION:
+*      This routine sets the port's rate control ingress limit mode.
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - logical port number to set.
+*       mode         - rate control ingress limit mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*      None
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_ingress_limit_mode
+(
+    IN uint32_t                 owner_id,
+    IN uint32_t                 lport,
+    IN GT_RATE_LIMIT_MODE       mode
+)
+{
+    tpm_sw_set_ingress_limit_mode(owner_id,(tpm_src_port_type_t)lport,mode);
+
+    return;
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_priority_selection
+*
+* DESCRIPTION:
+*       This function sets initial QPri and FPri selection.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to set init pri.
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_priority_selection
+(
+    IN uint32_t owner_id,
+    IN uint8_t  lport,
+    IN uint8_t  init_pri,
+    IN GT_BOOL  tag_if_both
+)
+{
+    bool lTag;
+    if(GT_TRUE == tag_if_both)
+        lTag = true;
+    else
+        lTag = false;
+    tpm_sw_set_priority_selection(owner_id,(tpm_src_port_type_t)lport,init_pri,lTag);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This function maps a tag priority to a queue priority.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       tag_pri     - Source tag priority number.
+*       q_pri       - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_tag_pri_mapping
+(
+    IN  uint32_t owner_id,
+    IN  uint8_t  tag_pri,
+    IN  uint8_t  q_pri
+)
+{
+    tpm_sw_set_tag_pri_mapping(owner_id,tag_pri,q_pri);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This function maps a dscp value to a queue priority.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       dscp        - Source dscp value.
+*       q_pri       - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_ip_pri_mapping
+(
+    IN  uint32_t owner_id,
+    IN  uint8_t  dscp,
+    IN  uint8_t  q_pri
+)
+{
+    tpm_sw_set_ip_pri_mapping(owner_id,dscp,q_pri);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_gmac_mtu
+*
+* DESCRIPTION:
+*       This function set the MTU of GMAC.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       gmac        - GMAC, '0'-GMAC0, '1'-GMAC1, '02'-PONMAC, '3'-switch.
+*       mtu         - MTU size.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_gmac_mtu
+(
+    IN  uint32_t  owner_id,
+    IN  uint32_t  gmac,
+    IN  uint32_t  mtu
+)
+{
+
+    tpm_mru_type_t type;
+    if(gmac > TPM_NETA_MTU_SWITCH)
+        type = TPM_NETA_MTU_SWITCH;
+    else
+        type = (tpm_mru_type_t)gmac;
+
+    tpm_set_mtu_size(owner_id, type, mtu);
+}
+
+/*******************************************************************************
+* sfs_tpm_sw_set_port_mirror
+*
+* DESCRIPTION:
+*       This function set port mirror.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - src UNI port(1-4).
+*       dst_port    - dst UNI port(1-4).
+*       mode        - mirror mode, '0'-ingress mirror, '1'-egress mirror.
+*       state       - mirror state, '0'-disable, '1'-enable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+*
+*******************************************************************************/
+void sfs_tpm_sw_set_port_mirror
+(
+    IN  uint32_t  owner_id,
+    IN  uint32_t  src_port,
+    IN  uint32_t  dst_port,
+    IN  uint32_t  mode,
+    IN  uint32_t  state
+)
+{
+    tpm_sw_mirror_type_t mirror_mode;
+    bool                 mirror_state;
+
+    if(mode > TPM_SW_MIRROR_EGRESS)
+        mirror_mode = TPM_SW_MIRROR_EGRESS;
+    else
+        mirror_mode = (tpm_sw_mirror_type_t)mode;
+
+    mirror_state = ((1 == state) ? true: false);
+
+    tpm_sw_set_port_mirror(owner_id, src_port, dst_port, mirror_mode, mirror_state);
+}
+
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+/*******************************************************************************
+**
+**  sfs_tpm_sw_set_help_show
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_tpm_sw_set_help_show_1(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "==============================================================================================================================================\n");
+    off += sprintf(buf+off, "                                 Configuration Switch Commands  [DEC]                                                                         \n");
+    off += sprintf(buf+off, "==============================================================================================================================================\n");
+    off += sprintf(buf+off, "cat help_sw_set_cfg_1                                                                                           - show this help\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [state('1'-enable,'0'-disable)]                    > set_port_admin              - set port administration state\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [state('1'-enable,'0'-disable)] [mode('0'~'11')]   > set_port_autoneg            - set port auto negotiation\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d]                                                    > restart_autoneg             - restart port auto negotiation\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [mode('1'-enable,'0'-disable)]                     > set_port_duplex             - set port duplex mode\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [state('1'-enable,'0'-disable)]                    > set_port_fc                 - set port flow control\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [mode('0'-10M,'1'-100M,'2'-1000M)]                 > set_port_speed              - set port speed mode\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [vector('0'-isolate,'1'-enable, bit0-UNI0...]      > set_port_isolate_vector     - set port isolation vector\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [mode('0'-internal,'1'-external)] [state]          > set_port_loopback           - set port loopback state, enable or disable it. \n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] mac[6] mac[5] mac[4] mac[3] mac[2] mac[1]          > add_static_mac              - add static mac to port\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] mac[6], mac[5] mac[4] mac[3]  mac[2], mac[1]                      > del_static_mac              - delete static mac\n");
+    off += sprintf(buf+off, "echo [owner_id]                                                                   > clear_dynamic_mac           - clear all dynamic mac\n");
+    off += sprintf(buf+off, "echo [owner_id] [port_mask] mac[6] mac[5] mac[4] mac[3] mac[2] mac[1]             > set_static_mac_w_mask       - set static mac with port vector\n");
+    off += sprintf(buf+off, "echo [owner_id] [time_out(sec)]                                                   > set_mac_age_time            - set the MAC aging time\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [mac_pe_port(0 - 255)]                             > set_port_max_macs           - set the maximum MAC address of given port\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [state('1'-enable,'0'-disable)]                    > set_port_mac_learn          - set port MAC learning state\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [size 0(256) - 5(8192)]                                           > set_atu_size                - set the FDB size \n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [allow_flood ('1'-permit,'0'-not)]                 > set_port_flooding           - permit flooding of unknown DA\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [allow_flood ('1'-permit,'0'-not)]                 > set_port_mc_flooding        - permit flooding of unknown multicast\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [always_on ('1'-permit,'0'-use mc rules)]                         > set_bc_flooding             - permit flooding of broadcast\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [allow_tagged('1'-drop,  '0'-not)]                 > set_port_tagged             - allows or drops tagged packets\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [allow_untagged('1'-drop,'0'-not)]                 > set_port_untagged           - allows or drops untagged packets\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [vid_filter('1'-Drop,'0'-not)]                     > set_vid_filter_per_port     - set the filtering mod VID\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "====================================================================================================================================================\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_tpm_sw_set_help_show_2
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_tpm_sw_set_help_show_2(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "==============================================================================================================================================\n");
+    off += sprintf(buf+off, "                                 Configuration Switch Commands  [DEC]                                                                         \n");
+    off += sprintf(buf+off, "==============================================================================================================================================\n");
+    off += sprintf(buf+off, "cat help_sw_set_cfg_2                                                                                           - show this help\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [vid(1-4094)]                                      > set_port_def_vlan           - set port default vid\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [pri(0-7)]                                         > set_port_def_pri            - set port default pri\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [vid(1-4094)]                                      > add_port_vid                - add a VID to lport\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [vid(1-4094)]                                      > del_port_vid                - delete the existed VID from given port\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [egr_mode] [min_vid(0-4095)] [max_vid(0-4095)]     > add_port_gvid               - add a group of VID to lport and set egress mode('0'-AS_IS, '2'-RM_TAG, '3'-ADD_TAG)\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [min_vid(0-4095)] [max_vid(0-4095)]                > del_port_gvid               - delete a group of VID from lport\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [vid(1-4094)] [egr_mode]                           > set_port_vid_egr_mode       - set the egress modee('0'-AS_IS, '2'-RM_TAG, '3'-ADD_TAG)\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [queue_id 1-3]  [weight 1-8]                                      > set_uni_q_weight            - configure the weight of a queues\n");
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] rate [egr_rate_limit_menu]                         > set_uni_egr_rate_limit      - set egress frame rate limit\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] mode[rate_limit_menu] [cir] [cbs] [ebs]            > set_uni_ingr_police_rate    - set ingress policing\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] tc[1-4] cir[rate_limit_menu] cbs[0 ~ 0xFFFF)       > set_uni_tc_ingr_police_rate - set ingress policing\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] mode [rate_limit_menu]                             > set_ingress_limit_mode      - set ingress policing mode\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] Port[6]Port[5]Port[4]Port[3]Port[2]Port[1]len[1-6] > set_port_vlan_ports         - add lport to VLAN group membership\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [UNI port %.1d-%.1d] [init_pri_menu] [tag_if_both 0-1]                  > set_init_pri                - set initial priority\n", TPM_SRC_PORT_UNI_0, TPM_SRC_PORT_UNI_3);
+    off += sprintf(buf+off, "echo [owner_id] [pri 0-7] [q 0-3]                                                 > set_tag_pri_mapping         - map tag pri to queue\n");
+    off += sprintf(buf+off, "echo [owner_id] [dscp 0-63] [q 0-3]                                               > set_ip_pri_mapping          - map ip pri to queue\n");
+    off += sprintf(buf+off, "echo [owner_id] [gmac('0'-GMAC0, '1'-GMAC1, '2'-PMAC, '3'-switch)] [mtu]          > set_gmac_mtu                - set GMAC MTU\n");
+    off += sprintf(buf+off, "echo [owner_id] [src port] [dst port] [mode('0'-ingress), '1'-egress] [state]     > set_port_mirror             - set port mirror, src/dst port is UNI port(1-4), state('1'-enable,'0'-disable)\n");
+    off += sprintf(buf+off, "====================================================================================================================================================\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_tpm_sw_rate_limit_menu
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_tpm_sw_rate_limit_menu(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "==================================================================================================\n");
+    off += sprintf(buf+off, "                                 rate limit menu                                                  \n");
+    off += sprintf(buf+off, "==================================================================================================\n");
+    off += sprintf(buf+off, "cir allowed values are: 64, 128, 192, 256, 320,,..., 960,1000, 2000..., 100000,110000, 120000,..,200000\n");
+    off += sprintf(buf+off, "mode enumeration values are: '0'-All,'1'-LIMIT_FLOOD,'2'-LIMIT_BRDCST_MLTCST,'3'-LIMIT_BRDCST\n");
+    off += sprintf(buf+off, "==================================================================================================\n");
+
+    return(off);
+}
+/*******************************************************************************
+**
+**  sfs_tpm_sw_egr_rate_limit_menu
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_tpm_sw_egr_rate_limit_menu(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "==================================================================================================\n");
+    off += sprintf(buf+off, "                                egress rate limit menu \n");
+    off += sprintf(buf+off, "==================================================================================================\n");
+    off += sprintf(buf+off, "rate allowed values are: 0(MAX) 7600,..,7600+n*64,9600, 100000 110000, 120000,..., 1000000\n");
+    off += sprintf(buf+off, "==================================================================================================\n");
+
+    return(off);
+}
+
+/*******************************************************************************
+**
+**  sfs_tpm_sw_init_pri_menu
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function print cfg help
+**
+**  PARAMETERS:  char* buf
+**
+**  OUTPUTS:     char* buf
+**
+**  RETURNS:     message length
+**
+*******************************************************************************/
+int sfs_tpm_sw_init_pri_menu(char* buf)
+{
+    int off = 0;
+
+    off += sprintf(buf+off, "==================================================================================================\n");
+    off += sprintf(buf+off, "                                 initial priority menu           \n");
+    off += sprintf(buf+off, "==================================================================================================\n");
+    off += sprintf(buf+off, "mode enumeration values are: '0'-USE_PORTS_DEF,'1'-TAG_PRI_ONLY,'2'-IP_PRI_ONLY,'3'-IP_AND_TAG_PRI\n");
+    off += sprintf(buf+off, "==================================================================================================\n");
+
+    return(off);
+}
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                            Cfg Commands                                    */
+/* ========================================================================== */
+/* ========================================================================== */
+/*                            Cfg Commands                                    */
+/* ========================================================================== */
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static ssize_t set_sw_show(struct device *dev,
+                        struct device_attribute *attr,
+                        char *buf)
+{
+    const char* name = attr->attr.name;
+
+    if (!capable(CAP_NET_ADMIN))
+        return -EPERM;
+
+    if (!strcmp(name, "help_sw_set_cfg_1"))
+        return (sfs_tpm_sw_set_help_show_1(buf));
+    if (!strcmp(name, "help_sw_set_cfg_2"))
+        return (sfs_tpm_sw_set_help_show_2(buf));
+    else if (!strcmp(name, "rate_limit_menu"))
+        return (sfs_tpm_sw_rate_limit_menu(buf));
+    else if (!strcmp(name, "egr_rate_limit_menu"))
+        return (sfs_tpm_sw_egr_rate_limit_menu(buf));
+    else if (!strcmp(name, "init_pri_menu"))
+        return (sfs_tpm_sw_init_pri_menu(buf));
+
+    return 0;
+}
+#else
+static ssize_t set_sw_show(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+	printk(KERN_WARNING "%s: sysfs help is not compiled (CONFIG_MV_TPM_SYSFS_HELP)\n", __FUNCTION__);
+    return 0;
+}
+#endif /* CONFIG_MV_TPM_SYSFS_HELP */
+
+
+static ssize_t set_sw_store(struct device *dev,
+                         struct device_attribute *attr,
+                         const char *buf, size_t len)
+{
+    const char* name = attr->attr.name;
+//     unsigned long flags  = 0;
+    unsigned int  param1 = 0;
+    unsigned int  param2 = 0;
+    unsigned int  param3 = 0;
+    unsigned int  param4 = 0;
+    unsigned int  param5 = 0;
+    unsigned int  param6 = 0;
+    unsigned int  param7 = 0;
+    unsigned int  param8 = 0;
+    unsigned int  param9 = 0;
+    MV_U8         static_mac[6] = {0,0,0,0,0,0};
+    MV_U32        memPorts[6];
+
+    if (!capable(CAP_NET_ADMIN))
+    return -EPERM;
+
+    if (!strcmp(name, "add_static_mac"))
+    {
+        sscanf(buf, "%d %d %d %d %d %d %d %d",
+               &param1, &param2,&param3,&param4,
+               &param5, &param6,&param7,&param8);
+
+        static_mac[0] = param3;
+        static_mac[1] = param4;
+        static_mac[2] = param5;
+        static_mac[3] = param6;
+        static_mac[4] = param7;
+        static_mac[5] = param8;
+
+    }
+    else if (!strcmp(name, "del_static_mac"))
+    {
+        sscanf(buf, "%d %d %d %d %d %d %d ",
+               &param1, &param2,&param3,
+               &param4,&param5, &param6,&param7);
+
+        static_mac[0] = param2;
+        static_mac[1] = param3;
+        static_mac[2] = param4;
+        static_mac[3] = param5;
+        static_mac[4] = param6;
+        static_mac[5] = param7;
+    }
+    else if (!strcmp(name, "clear_dynamic_mac"))
+    {
+        sscanf(buf, "%d ",
+               &param1);
+
+    }
+    else if (!strcmp(name, "set_static_mac_w_mask"))
+    {
+        sscanf(buf, "%d %d %d %d %d %d %d %d",
+               &param1, &param2,&param3,&param4,
+               &param5, &param6,&param7,&param8);
+
+        static_mac[0] = param3;
+        static_mac[1] = param4;
+        static_mac[2] = param5;
+        static_mac[3] = param6;
+        static_mac[4] = param7;
+        static_mac[5] = param8;
+
+    }
+    else if (!strcmp(name, "add_port_gvid"))
+    {
+        sscanf(buf, "%d %d %d %d %d",
+               &param1, &param2,&param3,&param4,&param5);
+    }
+    else if (!strcmp(name, "set_port_mirror"))
+    {
+        sscanf(buf, "%d %d %d %d %d",
+               &param1, &param2,&param3,&param4,&param5);
+    }
+    else if (!strcmp(name, "set_uni_ingr_police_rate"))
+    {
+        sscanf(buf, "%d %d %d %d %d %d",
+               &param1, &param2, &param3,
+               &param4, &param5, &param6);
+    }
+    else if (!strcmp(name, "set_uni_tc_ingr_police_rate"))
+    {
+        sscanf(buf, "%d %d %d %d %d ",
+               &param1, &param2,&param3,
+               &param4,&param5);
+    }
+    else if (!strcmp(name, "set_port_vlan_ports"))
+    {
+        sscanf(buf, "%d %d %d %d %d %d %d %d %d",
+               &param1, &param2,&param3,&param4,
+               &param5, &param6,&param7,&param8,&param9);
+
+        memPorts[0] = param3;
+        memPorts[1] = param4;
+        memPorts[2] = param5;
+        memPorts[3] = param6;
+        memPorts[4] = param7;
+        memPorts[5] = param8;
+    }
+    else if (!strcmp(name, "set_init_pri"))
+    {
+        sscanf(buf, "%d %d %d %d",
+               &param1,&param2,&param3,&param4);
+    }
+    else if (!strcmp(name, "set_tag_pri_mapping"))
+    {
+        sscanf(buf, "%d %d %d",
+               &param1,&param2,&param3);
+    }
+    else if (!strcmp(name, "set_ip_pri_mapping"))
+    {
+        sscanf(buf, "%d %d %d",
+               &param1,&param2,&param3);
+    }
+    else
+    {
+        sscanf(buf, "%d %d %d %d",
+               &param1, &param2,&param3,&param4);
+    }
+
+    printk(KERN_INFO "param1[%d],param2[%d],param3[%d],param4[%d],param5[%d],param6[%d],param7[%d],param8[%d] param9[%d] \n",
+          param1,param2,param3,param4,
+          param5,param6,param7,param8,param9);
+
+//     raw_local_irq_save(flags);
+
+    if (!strcmp(name, "set_port_admin"))
+        sfs_tpm_sw_set_port_admin((MV_U32)param1,(MV_U32)param2, (MV_U32)param3);
+
+    else if (!strcmp(name, "set_port_autoneg"))
+        sfs_tpm_sw_set_port_autoneg((MV_U32)param1,(MV_U32)param2, (MV_U32)param3, (MV_U32)param4);
+
+    else if (!strcmp(name, "restart_autoneg"))
+        sfs_tpm_sw_restart_autoneg((MV_U32)param1,(MV_U32)param2);
+
+    else if (!strcmp(name, "set_port_duplex"))
+        sfs_tpm_sw_set_port_duplex((MV_U32)param1,(MV_U32)param2, (MV_U32)param3);
+
+    else if (!strcmp(name, "set_port_fc"))
+        sfs_tpm_sw_set_port_fc((MV_U32)param1,(MV_U32)param2, (MV_U32)param3);
+
+    else if (!strcmp(name, "set_port_speed"))
+        sfs_tpm_sw_set_port_speed((MV_U32)param1,(MV_U32)param2, (MV_U32)param3);
+
+    else if (!strcmp(name, "set_port_isolate_vector"))
+        sfs_tpm_sw_set_port_isolate_vector((MV_U32)param1,(MV_U32)param2, (MV_U32)param3);
+
+    else if (!strcmp(name, "set_port_loopback"))
+        sfs_tpm_sw_set_port_loopback((MV_U32)param1,(MV_U32)param2, (MV_U32)param3, (MV_U32)param4);
+
+    else if (!strcmp(name, "add_static_mac"))
+        sfs_tpm_sw_add_static_mac((MV_U32)param1,(MV_U32)param2, static_mac);
+
+    else if (!strcmp(name, "del_static_mac"))
+        sfs_tpm_sw_del_static_mac((MV_U32)param1, static_mac);
+
+    else if (!strcmp(name, "clear_dynamic_mac"))
+        sfs_tpm_sw_clear_dynamic_mac((MV_U32)param1);
+
+    else if (!strcmp(name, "set_static_mac_w_mask"))
+        sfs_tpm_sw_set_static_mac_w_mask((MV_U32)param1,(MV_U32)param2, static_mac);
+
+    else if (!strcmp(name, "set_port_max_macs"))
+        sfs_tpm_sw_set_port_max_macs((MV_U32)param1 ,(MV_U32)param2 ,(MV_U8)param3);
+
+    else if (!strcmp(name, "set_port_mac_learn"))
+        sfs_tpm_sw_set_port_mac_learn((MV_U32)param1 ,(MV_U32)param2 ,(MV_U8)param3);
+
+    else if
+        (!strcmp(name, "set_atu_size"))
+                sfs_tpm_sw_set_atu_size((MV_U32)param1,(MV_U32)param2);
+    else if
+        (!strcmp(name, "set_mac_age_time"))
+                sfs_tpm_sw_set_mac_age_time((MV_U32)param1,(MV_U32)param2);
+
+    else if (!strcmp(name, "set_port_flooding"))
+        sfs_tpm_sw_set_port_flooding((MV_U32)param1 ,(MV_U32)param2 ,(MV_U32)param3);
+
+    else if (!strcmp(name, "set_port_mc_flooding"))
+        sfs_tpm_sw_set_port_mc_flooding((MV_U32)param1 ,(MV_U32)param2 ,(MV_U32)param3);
+
+    else if (!strcmp(name, "set_bc_flooding"))
+        sfs_tpm_sw_set_bc_flooding((MV_U32)param1 ,(MV_U32)param2);
+
+    else if (!strcmp(name, "set_port_tagged"))
+        sfs_tpm_sw_set_port_tagged((MV_U32)param1 ,(MV_U32)param2 ,(MV_U8)param3);
+
+    else if (!strcmp(name, "set_port_untagged"))
+        sfs_tpm_sw_set_port_untagged((MV_U32)param1 ,(MV_U32)param2 ,(MV_U8)param3);
+
+    else if (!strcmp(name, "set_port_def_vlan"))
+        sfs_tpm_sw_set_port_def_vlan((MV_U32)param1 ,(MV_U32)param2 ,(MV_U16)param3);
+
+    else if (!strcmp(name, "set_port_def_pri"))
+        sfs_tpm_sw_set_port_def_pri((MV_U32)param1 ,(MV_U32)param2 ,(MV_U8)param3);
+
+    else if (!strcmp(name, "add_port_vid"))
+        sfs_tpm_sw_port_add_vid((MV_U32)param1 ,(MV_U32)param2 ,(MV_U16)param3);
+
+    else if (!strcmp(name, "del_port_vid"))
+        sfs_tpm_sw_del_port_vid((MV_U32)param1 ,(MV_U32)param2 ,(MV_U16)param3);
+
+    else if (!strcmp(name, "add_port_gvid"))
+        sfs_tpm_sw_port_add_gvid((MV_U32)param1 ,(MV_U32)param2 ,(MV_U16)param3, (MV_U16)param4, (MV_U16)param5);
+
+    else if (!strcmp(name, "del_port_gvid"))
+        sfs_tpm_sw_del_port_gvid((MV_U32)param1 ,(MV_U32)param2 ,(MV_U16)param3, (MV_U16)param4);
+
+    else if (!strcmp(name, "set_port_vid_egr_mode"))
+        sfs_tpm_sw_set_port_vid_egress_mode((MV_U32)param1 ,(MV_U32)param2 ,(MV_U16)param3 ,(MV_U8)param4);
+
+    else if (!strcmp(name, "set_uni_q_weight"))
+        sfs_tpm_sw_set_uni_q_weight((MV_U32)param1 ,(MV_U32)param2,(MV_U32)param3);
+
+    else if (!strcmp(name, "set_vid_filter_per_port"))
+        sfs_tpm_sw_set_vid_filter_per_port((MV_U32)param1 ,(MV_U32)param2 ,(MV_U8)param3);
+
+    else if (!strcmp(name, "set_uni_egr_rate_limit"))
+        sfs_tpm_sw_set_uni_egr_rate_limit((MV_U32)param1, (MV_U32)param2,
+                                        (MV_U32)param3);
+
+    else if (!strcmp(name, "set_uni_ingr_police_rate"))
+        sfs_tpm_sw_set_uni_ingr_police_rate((MV_U32)param1, (MV_U32)param2,
+                                            (MV_U32)param3, (MV_U32)param4,
+                                            (MV_U32)param5, (MV_U32)param6);
+    else if (!strcmp(name, "set_uni_tc_ingr_police_rate"))
+        sfs_tpm_sw_set_uni_tc_ingr_police_rate((MV_U32)param1, (MV_U32)param2,
+                                           (MV_U32)param3,(MV_U32)param4,
+                                           (MV_U32)param5);
+    else if
+        (!strcmp(name, "set_ingress_limit_mode"))
+                sfs_tpm_sw_set_ingress_limit_mode((MV_U32)param1,(MV_U32)param2,(MV_U32)param3);
+
+    else if
+        (!strcmp(name, "set_port_vlan_ports"))
+                sfs_tpm_sw_set_port_vlan_ports((MV_U32)param1,(MV_U32)param2, memPorts,(MV_U32)param9);
+
+    else if
+        (!strcmp(name, "set_init_pri"))
+                sfs_tpm_sw_set_priority_selection((MV_U32)param1,(MV_U8)param2,(MV_U8)param3,(MV_U8)param4);
+    else if
+        (!strcmp(name, "set_tag_pri_mapping"))
+                sfs_tpm_sw_set_tag_pri_mapping((MV_U32)param1,(MV_U8)param2,(MV_U8)param3);
+    else if
+        (!strcmp(name, "set_ip_pri_mapping"))
+                sfs_tpm_sw_set_ip_pri_mapping((MV_U32)param1,(MV_U8)param2,(MV_U8)param3);
+    else if
+        (!strcmp(name, "set_gmac_mtu"))
+                sfs_tpm_sw_set_gmac_mtu((MV_U32)param1,(MV_U32)param2,(MV_U32)param3);
+
+    else if
+        (!strcmp(name, "set_port_mirror"))
+                sfs_tpm_sw_set_port_mirror((MV_U32)param1,(MV_U32)param2,(MV_U32)param3,(MV_U32)param4,(MV_U32)param5);
+    else
+        printk("%s: illegal operation <%s>\n", __FUNCTION__, attr->attr.name);
+
+//     raw_local_irq_restore(flags);
+
+    return(len);
+}
+
+
+/* ========================================================================== */
+/*                            Debug SW Attributes                             */
+/* ========================================================================== */
+static DEVICE_ATTR(set_global_reg,          S_IWUSR, dbg_sw_show, dbg_sw_store);
+static DEVICE_ATTR(get_global_reg,          S_IWUSR, dbg_sw_show, dbg_sw_store);
+static DEVICE_ATTR(set_port_reg,            S_IWUSR, dbg_sw_show, dbg_sw_store);
+static DEVICE_ATTR(get_port_reg,            S_IWUSR, dbg_sw_show, dbg_sw_store);
+static DEVICE_ATTR(get_port_cntrs,          S_IWUSR, dbg_sw_show, dbg_sw_store);
+static DEVICE_ATTR(get_fdb,                 S_IWUSR, dbg_sw_show, dbg_sw_store);
+static DEVICE_ATTR(sw_init,                 S_IWUSR, dbg_sw_show, dbg_sw_store);
+static DEVICE_ATTR(debug_trace,             S_IWUSR, dbg_sw_show, dbg_sw_store);
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static DEVICE_ATTR(help_sw_dbg,             S_IRUSR, dbg_sw_show, dbg_sw_store);
+#endif
+
+
+static struct attribute *dbg_sw_attrs[] =
+{
+    &dev_attr_set_global_reg.attr,
+    &dev_attr_get_global_reg.attr,
+    &dev_attr_set_port_reg.attr,
+    &dev_attr_get_port_reg.attr,
+    &dev_attr_get_port_cntrs.attr,
+    &dev_attr_get_fdb.attr,
+    &dev_attr_sw_init.attr,
+    &dev_attr_debug_trace.attr,
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_sw_dbg.attr,
+#endif
+    NULL
+};
+
+static struct attribute_group dbg_sw_group =
+{
+    .name = "debug",
+    .attrs = dbg_sw_attrs
+};
+
+
+
+/* ========================================================================== */
+/*                            Info SW Attributes                              */
+/* ========================================================================== */
+
+static DEVICE_ATTR(get_port_admin,                  S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_link_status,            S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_autoneg,                S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_duplex_config,          S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_duplex_status,          S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_fc_config,              S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_fc_status,              S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_speed_config,           S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_speed_status,           S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_isolate_vector,         S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_loopback,               S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_mac_age_time,                S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_max_macs,               S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_mac_learn,              S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_flooding,               S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_mc_flooding,            S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_bc_flooding,                 S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_tagged,                 S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_untagged,               S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_def_vlan,               S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_def_pri,                S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_vid,                    S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_vid_filter,             S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_uni_ingr_police_rate,        S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_uni_tc_ingr_police_rate,     S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_uni_egr_rate_limit,          S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_vlan_ports,             S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_ingress_limit_mode,          S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_init_pri,                    S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_tag_pri_mapping,             S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_ip_pri_mapping,              S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_gmac_mtu,                    S_IWUSR, get_sw_show, get_sw_store);
+static DEVICE_ATTR(get_port_mirror,                 S_IWUSR, get_sw_show, get_sw_store);
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static DEVICE_ATTR(help_sw_get_info,                S_IRUSR, get_sw_show, get_sw_store);
+#endif
+
+
+static struct attribute *get_sw_attrs[] =
+{
+    &dev_attr_get_port_admin.attr,
+    &dev_attr_get_port_link_status.attr,
+    &dev_attr_get_port_autoneg.attr,
+    &dev_attr_get_port_duplex_config.attr,
+    &dev_attr_get_port_duplex_status.attr,
+    &dev_attr_get_port_fc_config.attr,
+    &dev_attr_get_port_fc_status.attr,
+    &dev_attr_get_port_speed_config.attr,
+    &dev_attr_get_port_speed_status.attr,
+    &dev_attr_get_port_isolate_vector.attr,
+    &dev_attr_get_port_loopback.attr,
+    &dev_attr_get_mac_age_time.attr,
+    &dev_attr_get_port_max_macs.attr,
+    &dev_attr_get_port_mac_learn.attr,
+    &dev_attr_get_port_flooding.attr,
+    &dev_attr_get_port_mc_flooding.attr,
+    &dev_attr_get_bc_flooding.attr,
+    &dev_attr_get_port_tagged.attr,
+    &dev_attr_get_port_untagged.attr,
+    &dev_attr_get_port_def_vlan.attr,
+    &dev_attr_get_port_def_pri.attr,
+    &dev_attr_get_port_vid.attr,
+    &dev_attr_get_port_vid_filter.attr,
+    &dev_attr_get_uni_ingr_police_rate.attr,
+    &dev_attr_get_uni_tc_ingr_police_rate.attr,
+    &dev_attr_get_uni_egr_rate_limit.attr,
+    &dev_attr_get_port_vlan_ports.attr,
+    &dev_attr_get_ingress_limit_mode.attr,
+    &dev_attr_get_init_pri.attr,
+    &dev_attr_get_tag_pri_mapping.attr,
+    &dev_attr_get_ip_pri_mapping.attr,
+    &dev_attr_get_gmac_mtu.attr,
+    &dev_attr_get_port_mirror.attr,
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_sw_get_info.attr,
+#endif
+    NULL
+};
+
+static struct attribute_group get_sw_group =
+{
+    .name = "info",
+    .attrs = get_sw_attrs
+};
+
+
+/* ========================================================================== */
+/*                            Cfg SW Attributes                               */
+/* ========================================================================== */
+static DEVICE_ATTR(set_port_admin,                  S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_autoneg,                S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(restart_autoneg,                 S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_duplex,                 S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_fc,                     S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_speed,                  S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_isolate_vector,         S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_loopback,               S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(add_static_mac,                  S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(del_static_mac,                  S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(clear_dynamic_mac,               S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_static_mac_w_mask,           S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_mac_age_time,                S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_max_macs,               S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_mac_learn,              S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_flooding,               S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_mc_flooding,            S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_bc_flooding,                 S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_tagged,                 S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_untagged,               S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_def_vlan,               S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_def_pri,                S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(add_port_vid,                    S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(del_port_vid,                    S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(add_port_gvid,                   S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(del_port_gvid,                   S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_vid_egr_mode,           S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_vid_filter_per_port,         S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_uni_q_weight,                S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_uni_ingr_police_rate,        S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_uni_tc_ingr_police_rate,     S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_uni_egr_rate_limit,          S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_atu_size,                    S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_vlan_ports,             S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_ingress_limit_mode,          S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_init_pri,                    S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_tag_pri_mapping,             S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_ip_pri_mapping,              S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_gmac_mtu,                    S_IWUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(set_port_mirror,                 S_IWUSR, set_sw_show, set_sw_store);
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+static DEVICE_ATTR(help_sw_set_cfg_1,               S_IRUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(help_sw_set_cfg_2,               S_IRUSR, set_sw_show, set_sw_store);
+#endif
+static DEVICE_ATTR(rate_limit_menu,                 S_IRUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(egr_rate_limit_menu,             S_IRUSR, set_sw_show, set_sw_store);
+static DEVICE_ATTR(init_pri_menu,                   S_IRUSR, set_sw_show, set_sw_store);
+
+
+static struct attribute *set_sw_attrs[] = {
+    &dev_attr_set_port_admin.attr,
+    &dev_attr_set_port_autoneg.attr,
+    &dev_attr_restart_autoneg.attr,
+    &dev_attr_set_port_duplex.attr,
+    &dev_attr_set_port_fc.attr,
+    &dev_attr_set_port_speed.attr,
+    &dev_attr_set_port_isolate_vector.attr,
+    &dev_attr_set_port_loopback.attr,
+    &dev_attr_add_static_mac.attr,
+    &dev_attr_del_static_mac.attr,
+    &dev_attr_clear_dynamic_mac.attr,
+    &dev_attr_set_static_mac_w_mask.attr,
+    &dev_attr_set_mac_age_time.attr,
+    &dev_attr_set_port_max_macs.attr,
+    &dev_attr_set_port_mac_learn.attr,
+    &dev_attr_set_port_flooding.attr,
+    &dev_attr_set_port_mc_flooding.attr,
+    &dev_attr_set_bc_flooding.attr,
+    &dev_attr_set_port_tagged.attr,
+    &dev_attr_set_port_untagged.attr,
+    &dev_attr_set_port_def_vlan.attr,
+    &dev_attr_set_port_def_pri.attr,
+    &dev_attr_add_port_vid.attr,
+    &dev_attr_del_port_vid.attr,
+    &dev_attr_add_port_gvid.attr,
+    &dev_attr_del_port_gvid.attr,
+    &dev_attr_set_port_vid_egr_mode.attr,
+    &dev_attr_set_vid_filter_per_port.attr,
+    &dev_attr_set_uni_q_weight.attr,
+    &dev_attr_set_uni_ingr_police_rate.attr,
+    &dev_attr_set_uni_tc_ingr_police_rate.attr,
+    &dev_attr_set_uni_egr_rate_limit.attr,
+    &dev_attr_set_atu_size.attr,
+    &dev_attr_set_port_vlan_ports.attr,
+    &dev_attr_set_ingress_limit_mode.attr,
+    &dev_attr_set_init_pri.attr,
+    &dev_attr_set_tag_pri_mapping.attr,
+    &dev_attr_set_ip_pri_mapping.attr,
+    &dev_attr_set_gmac_mtu.attr,
+    &dev_attr_set_port_mirror.attr,
+#ifdef CONFIG_MV_TPM_SYSFS_HELP
+    &dev_attr_help_sw_set_cfg_1.attr,
+    &dev_attr_help_sw_set_cfg_2.attr,
+#endif
+    &dev_attr_rate_limit_menu.attr,
+    &dev_attr_egr_rate_limit_menu.attr,
+    &dev_attr_init_pri_menu.attr,
+    NULL
+};
+
+static struct attribute_group set_sw_group =
+{
+  .name = "cfg",
+  .attrs = set_sw_attrs
+};
+/******************************************************************************/
+/* ========================================================================== */
+/*                            SW SYS FS                                       */
+/* ========================================================================== */
+/******************************************************************************/
+int sw_sysfs_init(void)
+{
+    int err;
+    struct device *pd;
+
+    pd = bus_find_device_by_name(&platform_bus_type, NULL, "tpm_sw");
+    if (!pd)
+    {
+        platform_device_register_simple("tpm_sw", -1, NULL, 0);
+        pd = bus_find_device_by_name(&platform_bus_type, NULL, "tpm_sw");
+    }
+
+    if (!pd)
+    {
+        printk(KERN_ERR"%s: cannot find tpm_sw device\n", __FUNCTION__);
+        pd = &platform_bus;
+    }
+
+    err = sysfs_create_group(&pd->kobj, &set_sw_group);
+    if (err)
+    {
+        printk(KERN_INFO "sysfs group failed %d\n", err);
+        goto out;
+    }
+
+    err = sysfs_create_group(&pd->kobj, &get_sw_group);
+    if (err)
+    {
+        printk(KERN_INFO "sysfs group failed %d\n", err);
+        goto out;
+    }
+
+    err = sysfs_create_group(&pd->kobj, &dbg_sw_group);
+    if (err)
+    {
+        printk(KERN_INFO "sysfs group failed %d\n", err);
+        goto out;
+    }
+
+    printk(KERN_INFO "= SW Module SYS FS Init ended successfully =\n");
+
+    out:
+    return err;
+}
+
+/*******************************************************************************
+**
+**  tpm_module_usr_if_create
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function create user interface - sys fs
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS tpm_module_usr_if_create(void)
+{
+  if (sw_sysfs_init() != 0)
+    return(MV_ERROR);
+
+  if (tpm_sysfs_init() != 0)
+    return(MV_ERROR);
+
+  if (tpm_sysfs_print_init() != 0)
+    return(MV_ERROR);
+
+  if (tpm_sysfs_trace_init() != 0)
+    return(MV_ERROR);
+#if 0 //See  tpm_sysfs_config_init module for explanation
+  if (tpm_sysfs_config_init() != 0)
+    return(MV_ERROR);
+#endif
+
+  return(MV_OK);
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.h
new file mode 100755
index 0000000..b48506c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/perf/tpm_usr_if.h
@@ -0,0 +1,88 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_usr_if.h
+*
+* DESCRIPTION:
+*               Traffic Processor Manager = TPM
+*
+* DEPENDENCIES:
+*               None
+*
+* CREATED BY:   OctaviaP
+*
+* DATE CREATED:
+*
+* FILE REVISION NUMBER:
+*               $Revision: 1.1.1.1 $
+*
+*
+*******************************************************************************/
+#ifndef _TPM_USR_IF_H_
+#define _TPM_USR_IF_H_
+
+MV_STATUS tpm_module_usr_if_create(void);
+
+#endif  /* _TPM_USR_IF_H_*/
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_alarm.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_alarm.c
new file mode 100755
index 0000000..5511689
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_alarm.c
@@ -0,0 +1,200 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/******************************************************************************
+* tpm_alarm.c
+*
+*
+*  MODULE : TPM Alarm
+*
+*  DESCRIPTION : This file config tpm alarm
+*
+*  MODIFICATION HISTORY:
+*           12Dec2010   Victor  - initial version created.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1.8 $
+*******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+extern  uint32_t trace_sw_dbg_flag; 
+static uint32_t gportLosPreviousAlarm = 0;
+
+/*******************************************************************************
+* tpm_alarm_get_eth_port
+*
+* DESCRIPTION:
+*       This function gets eth port alarm.
+*
+* INPUTS:
+*       owner_id	 - APP owner id , should be used for all API calls.
+*
+* OUTPUTS:
+*       alarm_type  - eth alarm type
+*		 port_bitmap	- port bitmap
+* RETURNS:
+*       On success -  TPM_RC_OK. 
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_alarm_get_eth_port
+(
+	uint32_t owner_id,
+	uint32_t *alarm_type,
+	uint8_t *port_bitmap
+)
+{
+	tpm_error_code_t retVal = TPM_RC_OK;
+	uint32_t i;
+	uint32_t ethPreviousAlarmState;
+	uint32_t ethCurrentAlarmState;
+	uint32_t ethChangedAlarm;
+	uint8_t reportBitmap;
+	uint8_t clearBitmap;
+
+	if (trace_sw_dbg_flag)
+	{
+		printk(KERN_INFO"==ENTER==%s: owner_id[%d]",
+			 	__FUNCTION__,owner_id);
+	}
+
+	*alarm_type = 0;
+	
+	/*Get eth port los alarm*/
+	if(ONU_EPON_ALARM_ETH_DEF_STATE & ONU_EPON_ALARM_ETH_PORT_LOS)
+	{
+		/* get the prvious eth port los alarm status */
+		ethPreviousAlarmState = gportLosPreviousAlarm;
+
+		/* get the current eth port los alarm status */
+		retVal = mv_switch_get_port_los_alarm(&ethCurrentAlarmState);
+		if (retVal != TPM_RC_OK)
+		{
+			printk(KERN_ERR
+			"%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+		}
+
+		/*port alarm exists, report or clear*/
+		if((ethCurrentAlarmState ^ ethPreviousAlarmState) != 0)
+		{
+			if (trace_sw_dbg_flag)
+			{
+				printk(KERN_INFO"%s: owner_id[%d]  ethPreviousAlarmState[%08x] ethCurrentAlarmState[%08x]\r\n",
+					 	__FUNCTION__,owner_id, ethPreviousAlarmState, ethCurrentAlarmState);
+			}
+			
+			/*get changed alarm*/
+			ethChangedAlarm = (ethCurrentAlarmState ^ ethPreviousAlarmState);
+
+			/* check port los alarm*/	
+			reportBitmap = 0;
+			clearBitmap = 0;
+			for(i=0; i<TPM_MAX_NUM_ETH_PORTS; i++)
+			{
+				if(ethChangedAlarm & (1 << i))
+				{
+					/*save report port los alarm*/
+					if(ethCurrentAlarmState & (1 << i))
+					{
+						reportBitmap |= (1 << i);
+					}
+					else /*save clear port los alarm*/
+					{
+						clearBitmap |= (1 << i);
+					}
+				}
+			}
+			
+			/*if report port los alarm exists*/
+			if(reportBitmap)
+			{
+				*alarm_type |= ONU_EPON_ALARM_ETH_PORT_LOS;
+				port_bitmap[MAX_ETH_PORT_ALARM+ONU_EPON_ALARM_ETH_PORT_LOS-1] = reportBitmap;
+			}
+			
+			/*if clear port los alarm exists*/
+			if(clearBitmap)
+			{
+				*alarm_type |= ONU_EPON_ALARM_ETH_PORT_LOS_CLEAR;
+				port_bitmap[ONU_EPON_ALARM_ETH_PORT_LOS-1] = clearBitmap;
+			}
+		}
+
+		/* save current eth port los alarm status */
+		gportLosPreviousAlarm = ethCurrentAlarmState;
+	}
+	
+	if (trace_sw_dbg_flag)
+	{
+		printk(KERN_INFO
+			"==EXIT== %s: alarm_type=%08x, port_bitmap[%02x][%02x]\n\r",__FUNCTION__, *alarm_type,port_bitmap[ONU_EPON_ALARM_ETH_PORT_LOS-1],
+			port_bitmap[MAX_ETH_PORT_ALARM+ONU_EPON_ALARM_ETH_PORT_LOS-1] );
+	}
+
+	return retVal;
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_alarm.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_alarm.h
new file mode 100755
index 0000000..28cc21a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_alarm.h
@@ -0,0 +1,155 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* tpm_alarm.h 
+*
+*
+*  MODULE : TPM Alarm
+*
+*  DESCRIPTION : This file config tpm alarm
+*
+*  MODIFICATION HISTORY:
+*           12Dec2010   Victor  - initial version created.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1.3 $
+*******************************************************************************/
+
+#ifndef __INC_TPM_ALARM_CONFIG
+#define __INC_TPM_ALARM_CONFIG
+
+/* Include Files
+------------------------------------------------------------------------------*/
+ 
+/* Definitions
+------------------------------------------------------------------------------*/ 
+#define                           IN 
+#define                           OUT
+
+#define ONU_EPON_ALARM_ETH_PORT_AUTONEG_FAIL  (0x0001) 
+#define ONU_EPON_ALARM_ETH_PORT_LOS   (0x0002) 
+#define ONU_EPON_ALARM_ETH_PORT_FAIL  (0x0004)
+#define ONU_EPON_ALARM_ETH_PORT_LOOPBACK  (0x0008)
+#define ONU_EPON_ALARM_ETH_PORT_CONGESTION    (0x0010)
+
+#define ONU_EPON_ALARM_ETH_PORT_AUTONEG_FAIL_CLEAR  (0x0001<<16) 
+#define ONU_EPON_ALARM_ETH_PORT_LOS_CLEAR   (0x0002<<16) 
+#define ONU_EPON_ALARM_ETH_PORT_FAIL_CLEAR  (0x0004<<16)
+#define ONU_EPON_ALARM_ETH_PORT_LOOPBACK_CLEAR  (0x0008<<16)
+#define ONU_EPON_ALARM_ETH_PORT_CONGESTION_CLEAR    (0x0010<<16)
+
+#define ONU_EPON_ALARM_ETH_DEF_STATE (ONU_EPON_ALARM_ETH_PORT_AUTONEG_FAIL	| \
+                                  ONU_EPON_ALARM_ETH_PORT_LOS			| \
+                                  ONU_EPON_ALARM_ETH_PORT_FAIL			| \
+                                  ONU_EPON_ALARM_ETH_PORT_LOOPBACK		| \
+                                  ONU_EPON_ALARM_ETH_PORT_CONGESTION)
+
+/* Enums
+------------------------------------------------------------------------------*/ 
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+/* ONU EPON ETH port Alarm table */
+typedef struct
+{
+	uint32_t			 alarm_type;
+	uint8_t				 port_bitmap[MAX_ETH_PORT_ALARM];
+}S_OnuEponEthAlarmTbl;
+
+
+/* Global variables
+------------------------------------------------------------------------------*/
+//S_OnuEponEthAlarmTbl g_onuEponAlarmEth;
+
+/* Global functions
+------------------------------------------------------------------------------*/
+ /*******************************************************************************
+* tpm_alarm_get_eth_port
+*
+* DESCRIPTION:
+*       This function gets eth port alarm.
+*
+* INPUTS:
+*       owner_id	 - APP owner id , should be used for all API calls.
+*
+* OUTPUTS:
+*       alarm_type  - eth alarm type
+*		 port_bitmap	- port bitmap
+* RETURNS:
+*       On success -  TPM_RC_OK. 
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_alarm_get_eth_port
+(
+	uint32_t  owner_id,
+	uint32_t *alarm_type,
+	uint8_t  *port_bitmap
+);
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.c
new file mode 100755
index 0000000..c93c182
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.c
@@ -0,0 +1,4967 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+/* Local variables */
+//spinlock_t tpmModLock;
+
+spinlock_t tpmMod2JumpEntryLock;
+spinlock_t tpmMod2ChainEntryLock;
+spinlock_t tpmMod2PmtHwLock;
+
+
+
+/*******************************************************************************
+                               Global definitions
+*******************************************************************************/
+#define TPM_IPV6_ADDR_LEN    (16)
+
+/* Null MAC address */
+uint8_t null_mac_address[TPM_SA_LEN] = {0,0,0,0,0,0};
+/* Null IPv4 address */
+uint8_t null_ipv4_address[TPM_IPV4_SIP_LEN] = {0,0,0,0};
+/* Null IPv6 address */
+uint8_t null_ipv6_address[TPM_IPV6_ADDR_LEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+/* NULL VLAN key */
+tpm_vlan_key_t null_vlan_key = {0,0,0,0,0,0,0};
+
+
+/*******************************************************************************
+                        PROTOTYPES for internal using
+*******************************************************************************/
+int32_t tpm_mod2_process_mh_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_da_set (tpm_gmacs_enum_t      gmac_port,
+                                 uint32_t                bm,
+                                 uint16_t                cmd_idx,
+                                 uint8_t                *skip,
+                                 tpm_pkt_mod_t          *mod_data,
+                                 tpm_mod_pattern_data_t *pattern_data,
+                                 tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_sa_set (tpm_gmacs_enum_t      gmac_port,
+                                 uint32_t                bm,
+                                 uint16_t                cmd_idx,
+                                 uint8_t                *skip,
+                                 tpm_pkt_mod_t          *mod_data,
+                                 tpm_mod_pattern_data_t *pattern_data,
+                                 tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_vlan_mod (tpm_gmacs_enum_t      gmac_port,
+                                   uint32_t                bm,
+                                   uint16_t                cmd_idx,
+                                   uint8_t                *skip,
+                                   tpm_pkt_mod_t          *mod_data,
+                                   tpm_mod_pattern_data_t *pattern_data,
+                                   tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_pppoe_del (tpm_gmacs_enum_t      gmac_port,
+                                    uint32_t                bm,
+                                    uint16_t                cmd_idx,
+                                    uint8_t                *skip,
+                                    tpm_pkt_mod_t          *mod_data,
+                                    tpm_mod_pattern_data_t *pattern_data,
+                                    tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_pppoe_add (tpm_gmacs_enum_t      gmac_port,
+                                    uint32_t                bm,
+                                    uint16_t                cmd_idx,
+                                    uint8_t                *skip,
+                                    tpm_pkt_mod_t          *mod_data,
+                                    tpm_mod_pattern_data_t *pattern_data,
+                                    tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_ipv4_update (tpm_gmacs_enum_t      gmac_port,
+                                      uint32_t                bm,
+                                      uint16_t                cmd_idx,
+                                      uint8_t                *skip,
+                                      tpm_pkt_mod_t          *mod_data,
+                                      tpm_mod_pattern_data_t *pattern_data,
+                                      tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_dscp_set (tpm_gmacs_enum_t      gmac_port,
+                                   uint32_t                bm,
+                                   uint16_t                cmd_idx,
+                                   uint8_t                *skip,
+                                   tpm_pkt_mod_t          *mod_data,
+                                   tpm_mod_pattern_data_t *pattern_data,
+                                   tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_ttl_dec (tpm_gmacs_enum_t      gmac_port,
+                                  uint32_t                bm,
+                                  uint16_t                cmd_idx,
+                                  uint8_t                *skip,
+                                  tpm_pkt_mod_t          *mod_data,
+                                  tpm_mod_pattern_data_t *pattern_data,
+                                  tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_v4_sip_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_v4_dip_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_hoplim_dec (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_l4_src_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_l4_dst_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check);
+int32_t tpm_mod2_process_l4_checksum_set(tpm_gmacs_enum_t      gmac_port,
+                                         uint32_t                bm,
+                                         uint16_t                cmd_idx,
+                                         uint8_t                *skip,
+                                         tpm_pkt_mod_t          *mod_data,
+                                         tpm_mod_pattern_data_t *pattern_data,
+                                         tpm_self_check_enable_t is_tpm_check);
+
+
+
+tpm_mod_flag_bm_entry_t tpm_mod2_jump_pattern =
+/*=============================================================================================*/
+/*  <skip_before><skip_no_parse><mask><process_function>    <opcode>                <mod_data><last><ip4updt><L4updt>*/
+{        0,             0,        0,         NULL,     {{TPM_MOD2_OPCODE_JUMP,          0xFFFF,    0,     0,      0 }}};
+
+tpm_mod_flag_bm_entry_t tpm_mod2_jump_skip2_pattern =
+/*=============================================================================================*/
+/*  <skip_before><skip_no_parse><mask><process_function>    <opcode>                <mod_data><last><ip4updt><L4updt>*/
+{        0,             0,        0,         NULL,     {{TPM_MOD2_OPCODE_JUMP_SKIP2,    0xFFFF,    0,     0,      0 }}};
+
+tpm_mod_flag_bm_entry_t tpm_mod2_jump_subr_pattern =
+/*=============================================================================================*/
+/*  <skip_before><skip_no_parse><mask><process_function>    <opcode>                <mod_data><last><ip4updt><L4updt>*/
+{        0,             0,        0,         NULL,     {{TPM_MOD2_OPCODE_JUMP_SUBR,     0xFFFF,    0,     0,      0 }}};
+
+tpm_mod_flag_bm_entry_t tpm_mod2_skip_pattern =
+/*=============================================================================================*/
+/*  <skip_before><skip_no_parse><mask><process_function>    <opcode>                <mod_data><last><ip4updt><L4updt>*/
+{        0,             0,        0,         NULL,     {{TPM_MOD2_OPCODE_SKIP,          0xFFFF,    0,     0,      0 }}};
+
+tpm_mod_flag_bm_entry_t tpm_mod2_ipv6_tc_pattern =
+/*=============================================================================================*/
+/*  <skip_before><skip_no_parse><mask>            <process_function>*/
+{        2,             4,       TPM_DSCP_SET,    tpm_mod2_process_dscp_set,
+/*         <opcode>                <mod_data><last><ip4updt><L4updt>*/
+    {{TPM_MOD2_OPCODE_REP2,          0x6000,    0,     0,      0 },}
+};
+
+tpm_mod_flag_bm_entry_t tpm_mod2_ipv6_pppoe_pattern =
+/*=============================================================================================*/
+/*  <skip_before><skip_no_parse><mask>            <process_function>*/
+{        2,             4,       TPM_DSCP_SET,    tpm_mod2_process_pppoe_add,
+/*         <opcode>                <mod_data><last><ip4updt><L4updt>*/
+    {{TPM_MOD2_OPCODE_REP2,          0x8864,    0,     0,      0 },
+     {TPM_MOD2_OPCODE_ADD,           0x1100,    0,     0,      0 },
+     {TPM_MOD2_OPCODE_ADD,           0x0000,    0,     0,      0 },
+     {TPM_MOD2_OPCODE_ADD_CALC_LEN,  0x7000,    0,     0,      0 },
+     {TPM_MOD2_OPCODE_ADD,           0x0057,    0,     0,      0 }}
+};
+
+
+tpm_mod_flag_bm_entry_t tpm_mod2_pattern_array[TPM_MAX_PKT_MOD_FLAGS] =
+/*=============================================================================================*/
+{
+    /* TPM_MH_SET            -   Update the Marvell Header*/
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           0/*skip w/ jump*/, TPM_MH_SET,         tpm_mod2_process_mh_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_MAC_DA_SET     -   Update the MAC DA Address*/
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           6,        TPM_MAC_DA_SET,     tpm_mod2_process_da_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     0,      0 },
+         {TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     0,      0 },
+         {TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_MAC_SA_SET     -   Update the MAC SA Address*/
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           6,        TPM_MAC_SA_SET,     tpm_mod2_process_sa_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     0,      0 },
+         {TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     0,      0 },
+         {TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_VLAN_MOD       -   Update the VLAN Tags (add/del/update)*/
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           0,        TPM_VLAN_MOD,       tpm_mod2_process_vlan_mod,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_NOOP,           0xFFFF,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_PPPOE_DEL      -   Delete a PPPoE encapsulation*/
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           0,        TPM_PPPOE_DEL,      tpm_mod2_process_pppoe_del,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP2,          0x0800,    0,     0,      0 },
+         {TPM_MOD2_OPCODE_DEL,           0x0004,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_PPPOE_ADD      -   Add a PPPoE encapsulation*/
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           0,        TPM_PPPOE_ADD,      tpm_mod2_process_pppoe_add,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_PPPOE,          0xFFFF,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_DSCP_SET       -   Set the DSCP value */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0/* Don't care ety */,           2/* Don't care ety */,        TPM_DSCP_SET,       tpm_mod2_process_dscp_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP_LSB,        0x0300,    0,     1,      0 }},
+    },
+
+    /* TPM_MOD_TTL_DEC        -   Decrease the TTL value */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           8,        TPM_TTL_DEC,        tpm_mod2_process_ttl_dec,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_DEC_TTL_MSB,    0x0300,    0,     1,      0 }},
+    },
+
+    /* TPM_MOD_IPV4_UPDATE    -   Update the IPv4 Header*/
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           2,        TPM_IPV4_UPDATE,    tpm_mod2_process_ipv4_update,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP_IP_CHKSUM,  0x0000,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_IPV4_SRC_SET   -   Set the IPV4 Source Address */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           4,        TPM_IPV4_SRC_SET,   tpm_mod2_process_v4_sip_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     1,      1 },
+         {TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     1,      1 }},
+    },
+
+    /* TPM_MOD_IPV4_DST_SET   -   Set the IPV4 Destination Address */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           4,         TPM_IPV4_DST_SET,   tpm_mod2_process_v4_dip_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     1,      1 },
+         {TPM_MOD2_OPCODE_REP2,          0xFFFF,    0,     1,      1 }},
+    },
+
+    /* TPM_MOD_IPV6_UPDATE    -   Update the IPv6 Header */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           0,         TPM_IPV6_UPDATE,   NULL,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_NOOP,           0xFFFF,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_HOPLIM_DEC     -   Decrease the Hop Limit value */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           6,        TPM_HOPLIM_DEC,     tpm_mod2_process_hoplim_dec,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_DEC_TTL_LSB,    0x0200,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_IPV6_SRC_SET   -   Set the IPV6 Source Address */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,          16,        TPM_IPV6_SRC_SET,   NULL,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_NOOP,           0xFFFF,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_IPV6_DST_SET   -   Set the IPV6 Destination Address */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,          16,        TPM_IPV6_DST_SET,   NULL,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_NOOP,           0xFFFF,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_L4_SRC_SET     -   Set the L4 Source Port (UDP or TCP) */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           2,        TPM_L4_SRC_SET,     tpm_mod2_process_l4_src_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP2,           0xFFFF,    0,     0,      1 }},
+    },
+
+    /* TPM_MOD_L4_DST_SET     -   Set the L4 Destination Port (UDP or TCP) */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        0,           2,        TPM_L4_DST_SET,     tpm_mod2_process_l4_dst_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP2,           0xFFFF,    0,     0,      1 }},
+    },
+
+};
+
+tpm_mod_flag_bm_entry_t tpm_mod2_int_pattern_array[TPM_MAX_INT_MOD_FLAGS] =
+/*=============================================================================================*/
+{
+    /* TPM_MOD_INT_L4_TCP     -   Update TCP checksum */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {       12,          14,        TPM_INT_L4_TCP,     tpm_mod2_process_l4_checksum_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP_L4_CHKSUM,  0x0000,    0,     0,      0 }},
+    },
+
+    /* TPM_MOD_INT_L4_UDP     -   Update UDP checksum */
+    /*  <skip_before><skip_no_parse><mask>              <process_function>         */
+    {        2,           4,        TPM_INT_L4_UDP,     tpm_mod2_process_l4_checksum_set,
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_REP_L4_CHKSUM,  0x0000,    0,     0,      0 }},
+    },
+};
+
+tpm_mod_vlan_entry_t tpm_mod2_vlan_pattern_array[VLANOP_MAX_NUM] =
+/*=============================================================================================*/
+{
+    /* VLANOP_NOOP                 -        no VLAN operation performed */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+        {{TPM_MOD2_OPCODE_NOOP,           0xFFFF,    0,     0,      0 }},  /* VLAN 1 */
+
+        {{TPM_MOD2_OPCODE_NOOP,           0xFFFF,    0,     0,      0 }},  /* VLAN 2 */
+    },
+
+    /* VLANOP_EXT_TAG_MOD          -        modify external tag */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 1 */
+        {TPM_MOD2_OPCODE_REP_VLAN,       0xFFFF,    0,     0,      0 }},
+    },
+
+    /* VLANOP_EXT_TAG_DEL          -        delete external tag */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_DEL,            0x0002,    0,     0,      0 }},   /* VLAN 1 */
+    },
+
+    /* VLANOP_EXT_TAG_INS          -        insert(prepend) external tag */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 1 */
+        {TPM_MOD2_OPCODE_ADD_VLAN,       0xFFFF,    0,     0,      0 }},
+    },
+
+    /* VLANOP_EXT_TAG_MOD_INS      -        modify existing external tag and insert(prepend) new tag */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 1 */
+        {TPM_MOD2_OPCODE_ADD_VLAN,       0xFFFF,    0,     0,      0 }},
+
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 2 */
+        {TPM_MOD2_OPCODE_REP_VLAN,       0xFFFF,    0,     0,      0 }},
+    },
+
+    /* VLANOP_INS_2TAG             -        insert(prepend) 2 new tags */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 1 */
+        {TPM_MOD2_OPCODE_ADD_VLAN,       0xFFFF,    0,     0,      0 }},
+
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 2 */
+        {TPM_MOD2_OPCODE_ADD_VLAN,       0xFFFF,    0,     0,      0 }},
+    },
+
+    /* VLANOP_MOD_2TAG             -        modify 2 tags */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 1 */
+        {TPM_MOD2_OPCODE_REP_VLAN,       0xFFFF,    0,     0,      0 }},
+
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 2 */
+        {TPM_MOD2_OPCODE_REP_VLAN,       0xFFFF,    0,     0,      0 }},
+    },
+
+    /* VLANOP_SWAP_TAGS            -        swap internal and external tags */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 1 */
+        {TPM_MOD2_OPCODE_REP_VLAN,       0xFFFF,    0,     0,      0 }},
+
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },    /* VLAN 2 */
+        {TPM_MOD2_OPCODE_REP_VLAN,       0xFFFF,    0,     0,      0 }},
+    },
+
+    /* VLANOP_DEL_2TAG             -        delete 2 existing tags */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_DEL,            0x0002,    0,     0,      0 }},   /* VLAN 1 */
+
+       {{TPM_MOD2_OPCODE_DEL,            0x0002,    0,     0,      0 }},   /* VLAN 2 */
+    },
+
+    /* VLANOP_INT_TAG_MOD          -        modify existing internal tag */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_SKIP,           0x0004,    0,     0,      0 }},  /* VLAN 1 */
+
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },   /* VLAN 2 */
+        {TPM_MOD2_OPCODE_REP_VLAN,       0xFFFF,    0,     0,      0 }},
+    },
+
+    /* VLANOP_EXT_TAG_DEL_INT_MOD  -        delete existing external tag and modify internal tag */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_DEL,            0x0002,    0,     0,      0 }},  /* VLAN 1 */
+
+       {{TPM_MOD2_OPCODE_CONF_VLAN,      0xFFFF,    0,     0,      0 },   /* VLAN 2 */
+        {TPM_MOD2_OPCODE_REP_VLAN,       0xFFFF,    0,     0,      0 }},
+    },
+
+    /* VLANOP_ILLEGAL              -        illegal VLAN operation */
+    {
+        /*    <opcode>                 <mod_data><last><ip4updt><L4updt>           */
+       {{TPM_MOD2_OPCODE_NOOP,           0xFFFF,    0,     0,      0 }},  /* VLAN 1 */
+
+       {{TPM_MOD2_OPCODE_NOOP,           0xFFFF,    0,     0,      0 }},  /* VLAN 2 */
+    },
+};
+
+tpm_chain_map_t tpm_mod2_chain_map[] =
+{
+    {TPM_CHAIN_TYPE_L2,         TPM_VLAN_MOD,                                                                                                                       TPM_MOD2_DONT_CARE_INT_BM},
+
+    {TPM_CHAIN_TYPE_IPV4_NAPT,  TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_L4_SRC_SET,                                TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_IPV4_NAPT,  TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_DST_SET | TPM_L4_DST_SET,                                TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_IPV4_NAPT,  TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_L4_SRC_SET,                 TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_IPV4_NAPT,  TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_DST_SET | TPM_L4_DST_SET,                 TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_IPV4_NAPT,  TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_ADD | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_L4_SRC_SET,                TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_IPV4_NAPT,  TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_DST_SET | TPM_L4_DST_SET,                TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_IPV4_NAPT,  TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_ADD | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_L4_SRC_SET, TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_IPV4_NAPT,  TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_DST_SET | TPM_L4_DST_SET, TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                                 TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                  TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_ADD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                 TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                 TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_ADD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                  TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                  TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE,								       TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE,						       TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_ADD | TPM_TTL_DEC | TPM_IPV4_UPDATE,						       TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE,						       TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_ADD | TPM_TTL_DEC | TPM_IPV4_UPDATE,				       TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_ROUTE, TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE,				       TPM_MOD2_DONT_CARE_INT_BM},
+
+    {TPM_CHAIN_TYPE_MH,         TPM_MH_SET,                                                                                                                         TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_L2,         TPM_MH_SET | TPM_VLAN_MOD,                                                                                                          TPM_MOD2_DONT_CARE_INT_BM},
+    {TPM_CHAIN_TYPE_IPV4_MC,    TPM_MH_SET | TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE,                                                                        TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV4_MC,    TPM_MH_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE,                                                         TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV4_MC,    TPM_MAC_DA_SET | TPM_MH_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE,                                       TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV4_MC,    TPM_MAC_DA_SET | TPM_MH_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE,                        TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV4_MC,    TPM_MAC_SA_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE,                                                                                     TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV4_MC,    TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_TTL_DEC | TPM_IPV4_UPDATE,                                                                      TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV4_MC,    TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE,                                                    TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV4_MC,    TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_TTL_DEC | TPM_IPV4_UPDATE,                                     TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV6_MC,    TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                                                  TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV6_MC,    TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                                   TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV6_MC,    TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                 TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV6_MC,    TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                  TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV6_MC,    TPM_MH_SET | TPM_MAC_SA_SET | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                                     TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV6_MC,    TPM_MH_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                                      TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV6_MC,    TPM_MH_SET | TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                                    TPM_INT_MC_MOD},
+    {TPM_CHAIN_TYPE_IPV6_MC,    TPM_MH_SET | TPM_MAC_DA_SET | TPM_MAC_SA_SET | TPM_VLAN_MOD | TPM_PPPOE_DEL | TPM_HOPLIM_DEC | TPM_IPV6_UPDATE,                     TPM_INT_MC_MOD},
+};
+
+#define TPM_CHAIN_MAP_SIZE    (sizeof(tpm_mod2_chain_map)/sizeof(tpm_chain_map_t))
+
+/*******************************************************************************
+                               Internal definitions
+*******************************************************************************/
+
+/*******************************************************************************
+                               Internal functions
+*******************************************************************************/
+
+uint16_t tpm_mod2_get_jump_to(tpm_mod2_entry_t *pattern)
+{
+    if (pattern == NULL)
+    {
+        return TPM_MOD2_NULL_ENT_IDX;
+    }
+
+    if ((pattern->opcode == TPM_MOD2_OPCODE_JUMP) ||
+        (pattern->opcode == TPM_MOD2_OPCODE_JUMP_SKIP2) ||
+        (pattern->opcode == TPM_MOD2_OPCODE_JUMP_SUBR))
+    {
+        return pattern->data;
+    }
+
+    return TPM_MOD2_NULL_ENT_IDX;
+}
+
+tpm_pattern_entry_t * tpm_mod2_get_chain_from_pattern_set(tpm_pattern_entry_t *pattern_set, tpm_chain_type_t chain_type, uint16_t chain_idx)
+{
+    uint8_t set_idx, fst_free = TPM_MOD2_MAX_PATTERN_SETS;
+
+    for (set_idx = 1; set_idx < TPM_MOD2_MAX_PATTERN_SETS; set_idx++)
+    {
+        if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+        {
+            if (pattern_set[set_idx].is_valid == 0)
+            {
+                fst_free = set_idx;
+                break;
+            }
+        }
+        else if (pattern_set[set_idx].is_valid)
+        {
+            if ((TPM_AREA_TYPE_CHAIN == pattern_set[set_idx].area_type) &&
+                (chain_type == pattern_set[set_idx].chain_type) &&
+                (chain_idx ==  pattern_set[set_idx].index))
+            {
+                return &pattern_set[set_idx];
+            }
+        }
+        else if (fst_free == TPM_MOD2_MAX_PATTERN_SETS)
+        {
+            fst_free = set_idx;
+        }
+    }
+
+    if (chain_idx != TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        return NULL;
+    }
+
+    if (fst_free != TPM_MOD2_MAX_PATTERN_SETS)
+    {
+        pattern_set[fst_free].is_valid   = 1;
+        pattern_set[fst_free].area_type  = TPM_AREA_TYPE_CHAIN;
+        pattern_set[fst_free].chain_type = chain_type;
+    }
+
+    return &pattern_set[fst_free];
+}
+
+/*******************************************************************************
+* tpm_mod2_parse_chain_type()
+*
+* DESCRIPTION: The API is mapping mod bitmap into chain type - BM vs chain_type
+*
+* INPUTS:   mod_bm      - set of flags described which fields in the packet
+*                         to be changed
+*
+* OUTPUTS:
+*
+* RETURNS:
+*           chain_type
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+tpm_chain_type_t tpm_mod2_parse_chain_type(tpm_pkt_mod_bm_t mod_bm, tpm_pkt_mod_int_bm_t int_mod_bm)
+{
+    uint32_t map_idx;
+
+    for (map_idx = 0; map_idx < TPM_CHAIN_MAP_SIZE; map_idx++) {
+        if (mod_bm == tpm_mod2_chain_map[map_idx].mod_bm) {
+        	if (tpm_mod2_chain_map[map_idx].int_mod_bm == TPM_MOD2_DONT_CARE_INT_BM ||
+				int_mod_bm == tpm_mod2_chain_map[map_idx].int_mod_bm) {
+	            return tpm_mod2_chain_map[map_idx].chain_type;
+        	}
+        }
+    }
+
+    return TPM_CHAIN_TYPE_NONE;
+}
+
+/*******************************************************************************
+* tpm_mod2_validate_logical_params()
+*
+* DESCRIPTION: The API is validating the params - BM vs mod_data
+*
+* INPUTS:   gmac_port   - GMAC port
+*           mod_bm      - set of flags described which fields in the packet
+*                         to be changed
+*           mod_data    - modification entry data
+*
+* OUTPUTS:
+*
+* RETURNS:
+*           TPM_OK, TPM_NOT_FOUND or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_validate_logical_params   (tpm_gmacs_enum_t   gmac_port,
+                                               tpm_pkt_mod_bm_t   mod_bm,
+                                               tpm_pkt_mod_int_bm_t int_mod_bm,
+                                               tpm_pkt_mod_t     *mod_data,
+                                               uint32_t          *mod_entry)
+{
+    tpm_chain_type_t chain_type;
+    tpm_mac_key_t   *mac_data = &mod_data->mac_mod;
+    tpm_pppoe_key_t *pppoe_data = &mod_data->pppoe_mod;
+    uint8_t          forbid_dbl_tag_oper = 0;
+
+    if (gmac_port >= TPM_MAX_NUM_GMACS)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: port %d \n", gmac_port);
+        return TPM_FAIL;
+    }
+
+    if (mod_data == NULL ||
+        mod_entry == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    if (mod_bm == 0)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL bitmap\n");
+        return TPM_FAIL;
+    }
+
+    chain_type = tpm_mod2_parse_chain_type(mod_bm, int_mod_bm);
+    if (chain_type == TPM_CHAIN_TYPE_NONE)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: unsupported bitmap 0x%05x\n", mod_bm);
+        return TPM_FAIL;
+    }
+
+    if (chain_type == TPM_CHAIN_TYPE_IPV4_NAPT ||
+        chain_type == TPM_CHAIN_TYPE_IPV4_MC   ||
+        chain_type == TPM_CHAIN_TYPE_ROUTE)
+    {
+        forbid_dbl_tag_oper = 1;
+    }
+
+    /* for every bit set in the BM - check that the mod_data has the values ok - not NULL pointers */
+    if (mod_bm & TPM_MH_SET)
+    {
+        if (!tpm_db_mod2_get_multicast_mh_state())
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: MH disabled\n");
+            return TPM_FAIL;
+        }
+        if (mod_data->mh_mod == 0)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: Zero MH_2B\n");
+            return TPM_FAIL;
+        }
+    }
+
+    if (mod_bm & TPM_MAC_DA_SET)
+    {
+        if (memcmp(mac_data->mac_da, null_mac_address, TPM_DA_LEN) == 0 ||
+            memcmp(mac_data->mac_da_mask, null_mac_address, TPM_DA_LEN) == 0)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL DST MAC\n");
+            return TPM_FAIL;
+        }
+    }
+
+    if (mod_bm & TPM_MAC_SA_SET)
+    {
+        if (memcmp(mac_data->mac_sa, null_mac_address, TPM_SA_LEN) == 0 ||
+            memcmp(mac_data->mac_sa_mask, null_mac_address, TPM_SA_LEN) == 0)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL SRC MAC\n");
+            return TPM_FAIL;
+        }
+    }
+
+    if (mod_bm & TPM_VLAN_MOD)
+    {
+        tpm_vlan_oper_t vlan_oper = mod_data->vlan_mod.vlan_op;
+        tpm_vlan_key_t *v1_out = &mod_data->vlan_mod.vlan1_out, *v2_out = &mod_data->vlan_mod.vlan2_out;
+#if 0
+        /* Currently VLAN modification request cannot include other modifications */
+        if (mod_bm != TPM_VLAN_MOD)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: VLAN modification BM (0x%x)\n", mod_bm);
+            return TPM_FAIL;
+        }
+#endif
+        if (vlan_oper >= VLANOP_ILLEGAL)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: VLAN op. %d \n", vlan_oper);
+            return TPM_FAIL;
+        }
+
+        if (!tpm_db_mod2_get_double_tag_state() || forbid_dbl_tag_oper)
+        {
+            if (vlan_oper == VLANOP_EXT_TAG_MOD_INS ||
+                vlan_oper == VLANOP_INS_2TAG ||
+                vlan_oper == VLANOP_MOD_2TAG ||
+                vlan_oper == VLANOP_SWAP_TAGS ||
+                vlan_oper == VLANOP_DEL_2TAG ||
+                vlan_oper == VLANOP_INT_TAG_MOD ||
+                vlan_oper == VLANOP_EXT_TAG_DEL_INT_MOD)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Unsupport double VLAN Operation: VLAN op. %d \n", vlan_oper);
+                return TPM_FAIL;
+            }
+        }
+
+		switch (vlan_oper) {
+
+		case VLANOP_INS_2TAG:
+			if ((v1_out->tpid == 0) || (v1_out->tpid_mask == 0)) {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: v2 TPID is NULL for add action\n");
+                return TPM_FAIL;
+			}
+		case VLANOP_EXT_TAG_INS:
+			if ((v1_out->tpid == 0) || (v1_out->tpid_mask == 0)) {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: v1 TPID is NULL for add action\n");
+                return TPM_FAIL;
+			}
+			break;
+
+		case VLANOP_EXT_TAG_MOD_INS:
+		case VLANOP_MOD_2TAG:
+		case VLANOP_SWAP_TAGS:
+			if ((v2_out->tpid == 0) && (v2_out->tpid_mask == 0xffff)) {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: v2 TPID is NULL for modify new action\n");
+                return TPM_FAIL;
+			}
+		case VLANOP_EXT_TAG_MOD:
+			if ((v1_out->tpid == 0) && (v1_out->tpid_mask == 0xffff)) {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: v1 TPID is NULL for modify new action\n");
+                return TPM_FAIL;
+			}
+			break;
+
+		case VLANOP_INT_TAG_MOD:
+		case VLANOP_EXT_TAG_DEL_INT_MOD:
+			if ((v2_out->tpid == 0) && (v2_out->tpid_mask == 0xffff)) {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: v2 TPID is NULL for modify new action\n");
+                return TPM_FAIL;
+			}
+			break;
+
+		default:
+			break;
+		}
+
+        if ( v1_out->vid_mask != TPM_MOD2_ORIGINAL_VID &&
+             v1_out->vid_mask != TPM_MOD2_NEW_VID )
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: VLAN1 mask - %x\n", v1_out->vid_mask);
+            return TPM_FAIL;
+        }
+
+        if ( v2_out->vid_mask != TPM_MOD2_ORIGINAL_VID &&
+             v2_out->vid_mask != TPM_MOD2_NEW_VID )
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: VLAN2 mask - %x\n", v2_out->vid_mask);
+            return TPM_FAIL;
+        }
+
+        if ( v1_out->cfi_mask != TPM_MOD2_ORIGINAL_CFI &&
+             v1_out->cfi_mask != TPM_MOD2_NEW_CFI )
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: VLAN1 CFI mask - %x\n", v1_out->cfi_mask);
+            return TPM_FAIL;
+        }
+
+        if ( v2_out->cfi_mask != TPM_MOD2_ORIGINAL_CFI &&
+             v2_out->cfi_mask != TPM_MOD2_NEW_CFI )
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: VLAN2 CFI mask - %x\n", v2_out->cfi_mask);
+            return TPM_FAIL;
+        }
+
+        if ( v1_out->pbit_mask != TPM_MOD2_ORIGINAL_PBIT &&
+             v1_out->pbit_mask != TPM_MOD2_NEW_PBIT )
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: VLAN1 PBIT mask - %x\n", v1_out->pbit_mask);
+            return TPM_FAIL;
+        }
+
+        if ( v2_out->pbit_mask != TPM_MOD2_ORIGINAL_PBIT &&
+             v2_out->pbit_mask != TPM_MOD2_NEW_PBIT )
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: VLAN2 PBIT mask - %x\n", v2_out->pbit_mask);
+            return TPM_FAIL;
+        }
+    }
+
+    if ((mod_bm & TPM_PPPOE_DEL || mod_bm & TPM_PPPOE_ADD) &&
+        !tpm_db_mod2_get_pppoe_add_mod_state())
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: PPPoE disabled\n");
+        return TPM_FAIL;
+    }
+
+    if (mod_bm & TPM_PPPOE_DEL &&
+        mod_bm & TPM_PPPOE_ADD)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: BM includes PPPoE add and del flags\n");
+        return TPM_FAIL;
+    }
+
+    if (mod_bm & TPM_PPPOE_ADD)
+    {
+        if (pppoe_data->ppp_proto == 0 ||
+            pppoe_data->ppp_session == 0)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL PPPoE data\n");
+            return TPM_FAIL;
+        }
+    }
+
+    if (mod_bm & TPM_IPV4_UPDATE)
+    {
+        tpm_ipv4_acl_key_t *ipv4_data = &(mod_data->l3.ipv4_mod);
+        if (mod_bm & TPM_IPV4_DST_SET)
+        {
+            if (memcmp(ipv4_data->ipv4_dst_ip_add, null_ipv4_address, TPM_IPV4_SIP_LEN) == 0 ||
+                memcmp(ipv4_data->ipv4_dst_ip_add_mask, null_ipv4_address, TPM_IPV4_SIP_LEN) == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL DST IPv4 data\n");
+                return TPM_FAIL;
+            }
+        }
+
+        if (mod_bm & TPM_IPV4_SRC_SET)
+        {
+            if (memcmp(ipv4_data->ipv4_src_ip_add, null_ipv4_address, TPM_IPV4_SIP_LEN) == 0 ||
+                memcmp(ipv4_data->ipv4_src_ip_add_mask, null_ipv4_address, TPM_IPV4_SIP_LEN) == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL SRC IPv4 data\n");
+                return TPM_FAIL;
+            }
+        }
+
+        if (mod_bm & TPM_DSCP_SET)
+        {
+            if (ipv4_data->ipv4_dscp == 0 ||
+                ipv4_data->ipv4_dscp_mask == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL IPv4 DSCP data\n");
+                return TPM_FAIL;
+            }
+        }
+
+        if (mod_bm & TPM_L4_DST_SET)
+        {
+            if (ipv4_data->l4_dst_port == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL L4 DST port\n");
+                return TPM_FAIL;
+            }
+        }
+
+        if (mod_bm & TPM_L4_SRC_SET)
+        {
+            if (ipv4_data->l4_src_port == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL L4 SRC port\n");
+                return TPM_FAIL;
+            }
+        }
+    }
+    else
+    {
+        if (mod_bm & TPM_IPV4_DST_SET ||
+            mod_bm & TPM_IPV4_SRC_SET ||
+            mod_bm & TPM_TTL_DEC)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid flags: TPM_IPV4_UPDATE should be set\n");
+            return TPM_FAIL;
+        }
+    }
+
+    if (mod_bm & TPM_IPV6_UPDATE)
+    {
+        tpm_ipv6_acl_key_t *ipv6_data = &mod_data->l3.ipv6_mod;
+        if (mod_bm & TPM_IPV6_DST_SET)
+        {
+            if (memcmp(ipv6_data->ipv6_dst_ip_add, null_ipv6_address, TPM_IPV6_ADDR_LEN) == 0 ||
+                memcmp(ipv6_data->ipv6_dst_ip_add_mask, null_ipv6_address, TPM_IPV6_ADDR_LEN) == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL DST IPv6 data\n");
+                return TPM_FAIL;
+            }
+        }
+
+        if (mod_bm & TPM_IPV6_SRC_SET)
+        {
+            if (memcmp(ipv6_data->ipv6_src_ip_add, null_ipv6_address, TPM_IPV6_ADDR_LEN) == 0 ||
+                memcmp(ipv6_data->ipv6_src_ip_add_mask, null_ipv6_address, TPM_IPV6_ADDR_LEN) == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL SRC IPv6 data\n");
+                return TPM_FAIL;
+            }
+        }
+
+        if (mod_bm & TPM_DSCP_SET)
+        {
+            if (ipv6_data->ipv6_dscp == 0 ||
+                ipv6_data->ipv6_dscp_mask == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL IPv6 DSCP data\n");
+                return TPM_FAIL;
+            }
+        }
+
+        if (mod_bm & TPM_L4_DST_SET)
+        {
+            if (ipv6_data->l4_dst_port == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL L6 DST port\n");
+                return TPM_FAIL;
+            }
+        }
+
+        if (mod_bm & TPM_L4_SRC_SET)
+        {
+            if (ipv6_data->l4_src_port == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL L6 SRC port\n");
+                return TPM_FAIL;
+            }
+        }
+    }
+    else
+    {
+        if (mod_bm & TPM_IPV6_DST_SET ||
+            mod_bm & TPM_IPV6_SRC_SET ||
+            mod_bm & TPM_HOPLIM_DEC)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid flags: TPM_IPV6_UPDATE should be set\n");
+            return TPM_FAIL;
+        }
+    }
+
+    if (mod_bm & TPM_DSCP_SET     &&
+        !(mod_bm & TPM_IPV6_UPDATE) &&
+        !(mod_bm & TPM_IPV4_UPDATE))
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid flags: TPM_IPV4_UPDATE or TPM_IPV6_UPDATE should be set\n");
+        return TPM_FAIL;
+    }
+
+    if (mod_bm & TPM_L4_SRC_SET   ||
+        mod_bm & TPM_L4_DST_SET   ||
+        mod_bm & TPM_IPV6_SRC_SET ||
+        mod_bm & TPM_IPV6_DST_SET ||
+        mod_bm & TPM_IPV4_SRC_SET ||
+        mod_bm & TPM_IPV4_DST_SET)
+    {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Internal BM verification (0x%x)\n", int_mod_bm);
+
+        if (int_mod_bm == 0)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL internal modification BM \n");
+            return TPM_FAIL;
+        }
+#if 0
+        else if (int_mod_bm & TPM_INT_2_VLANS)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: TPM_INT_2_VLANS should NOT be set \n");
+            return TPM_FAIL;
+        }
+#endif
+    }
+
+    if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) && (int_mod_bm & TPM_INT_SPLIT_MOD))
+    {
+        if (mod_bm == TPM_VLAN_MOD)
+        {
+            if ((mod_data->vlan_mod.vlan_op != VLANOP_EXT_TAG_MOD) &&
+                (mod_data->vlan_mod.vlan_op != VLANOP_EXT_TAG_INS) &&
+                (mod_data->vlan_mod.vlan_op != VLANOP_EXT_TAG_MOD_INS) &&
+                (mod_data->vlan_mod.vlan_op != VLANOP_NOOP))
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: vlan_op should be one of VLANOP_EXT_TAG_MOD, VLANOP_EXT_TAG_INS and VLANOP_EXT_TAG_MOD_INS. \n");
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: TPM_VLAN_MOD should be set. \n");
+            return TPM_FAIL;
+        }
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_single_command_add()
+*
+*******************************************************************************/
+static int32_t tpm_mod2_single_command_add(tpm_mod_flag_bm_entry_t *cmd_pattern,
+                                           uint16_t                data,
+                                           tpm_pattern_entry_t    *entry_p)
+{
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), &(cmd_pattern->entry), sizeof(tpm_mod2_entry_t));
+        entry_p->line[entry_p->line_num++].data = data;
+
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added command 0x%x (data=0x%x pattern_line=%d)\n",
+                    cmd_pattern->entry[0].opcode, data, entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_skip_command_add()
+*
+*******************************************************************************/
+static int32_t  tpm_mod2_skip_command_add (uint8_t *skip,
+                                           uint8_t              skip_before,
+                                           tpm_pattern_entry_t *entry_p)
+{
+    if (*skip || skip_before)
+    {
+        /* Add SKIP */
+        if (tpm_mod2_single_command_add(&tpm_mod2_skip_pattern, (*skip + skip_before), entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+
+        *skip = 0;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_skip_to_l3_off_command_add()
+*
+*******************************************************************************/
+static int32_t  tpm_mod2_skip_to_l3_offset_command_add (uint8_t *skip,
+                                           uint8_t              mod_data,
+                                           tpm_pattern_entry_t *entry_p)
+{
+    /* Add SKIP */
+    if (tpm_mod2_single_command_add(&tpm_mod2_skip_pattern,
+                                    ((0x2 << 12)/*add l3_offset*/ | (0x2 << 8)/*sub mod_data*/ | mod_data),
+                                    entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    *skip = 0;
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_fill_in_vlan_data()
+*
+*******************************************************************************/
+uint32_t tpm_mod2_fill_in_vlan_data (tpm_vlan_key_t      *vlan_data)
+{
+    uint32_t tpm_data = 0;
+
+    tpm_data  = (vlan_data->vid << TPM_MOD2_ENTRY_VID_OFFS) & TPM_MOD2_ENTRY_VID_MASK;
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "tpm_data 1: 0x%4.4x (vid 0x%x mask 0x%x)\n",
+                 tpm_data, vlan_data->vid, vlan_data->vid_mask);
+
+    tpm_data |= (vlan_data->cfi << TPM_MOD2_ENTRY_CFI_OFFS) & TPM_MOD2_ENTRY_CFI_MASK;
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "tpm_data 2: 0x%4.4x (cfi 0x%x mask 0x%x)\n",
+                 tpm_data, vlan_data->cfi, vlan_data->cfi_mask);
+
+    tpm_data |= (vlan_data->pbit << TPM_MOD2_ENTRY_PBIT_OFFS) & TPM_MOD2_ENTRY_PBIT_MASK;
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "tpm_data 3: 0x%4.4x (pbit 0x%x mask 0x%x)\n",
+                 tpm_data, vlan_data->pbit, vlan_data->pbit_mask);
+
+    return (tpm_data & TPM_MOD2_ENTRY_MOD_DATA_MASK);
+}
+
+/*******************************************************************************
+* tpm_mod2_process_mh_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_mh_set (tpm_gmacs_enum_t      gmac_port,
+                                 uint32_t                bm,
+                                 uint16_t                cmd_idx,
+                                 uint8_t                *skip,
+                                 tpm_pkt_mod_t          *mod_data,
+                                 tpm_mod_pattern_data_t *pattern_data,
+                                 tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+    tpm_mod2_entry_t    tmp_pattern[TPM_MOD2_MH_CMD_ENTRIES];
+    uint16_t            chain_idx = TPM_MOD2_INVALID_CHAIN_ID, main_chain_id = TPM_MOD2_INVALID_CHAIN_ID;
+    uint16_t            jump_to;
+
+    memset(tmp_pattern, 0, sizeof(tmp_pattern));
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    /* Build pattern entries */
+    memcpy(tmp_pattern, tpm_mod2_pattern_array[cmd_idx].entry, sizeof(tmp_pattern));
+    tmp_pattern[0].data = mod_data->mh_mod;
+    tmp_pattern[0].last = 1;
+
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    /* Scan mh db to check if the MH subchain exist or not. */
+    chain_idx = tpm_db_mod2_get_chain_entry(gmac_port, TPM_CHAIN_TYPE_MH, TPM_MOD2_MH_CMD_ENTRIES, tmp_pattern);
+    if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        if(is_tpm_check) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "TPM check sub chain-%d failed\n", TPM_CHAIN_TYPE_MH);
+            return TPM_FAIL;
+        }
+
+        if (pattern_data->main_chain_type == TPM_CHAIN_TYPE_MH)
+        {
+            chain_idx = pattern_data->main_chain_id;
+        }
+        else
+        {
+            /* Get next free chain index of MH subchain area */
+            chain_idx = tpm_db_mod2_get_next_free_chain_entry(gmac_port, TPM_CHAIN_TYPE_MH);
+            if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+            {
+                spin_unlock_bh(&tpmMod2ChainEntryLock);
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the mac subchain \n");
+                return TPM_FAIL;
+            }
+        }
+    }
+    else
+    {
+        if (pattern_data->main_chain_type == TPM_CHAIN_TYPE_MH)
+        {
+            main_chain_id = chain_idx;
+        }
+    }
+    /* Write to mh db */
+    if(!is_tpm_check) {
+        if (tpm_db_mod2_set_chain_entry(gmac_port, TPM_CHAIN_TYPE_MH, chain_idx,
+                                        TPM_MOD2_MH_CMD_ENTRIES, tmp_pattern) != TPM_OK) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set mh subr chain entry\n");
+            return TPM_FAIL;
+        }
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    /* Fill MH entries in local pattern set */
+    if (pattern_data->main_chain_type == TPM_CHAIN_TYPE_MH)
+    {
+        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+        if (main_chain_id != TPM_MOD2_INVALID_CHAIN_ID)
+        {
+            pattern_data->main_chain_id = main_chain_id;
+        }
+    }
+    else
+    {
+        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, TPM_CHAIN_TYPE_MH, TPM_MOD2_INVALID_CHAIN_ID);
+    }
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get free pattern set. \n");
+        return TPM_FAIL;
+    }
+    entry_p->index = chain_idx;
+
+    if ((entry_p->line_num + TPM_MOD2_MH_CMD_ENTRIES) <= TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tmp_pattern,
+               sizeof(tpm_mod2_entry_t)*TPM_MOD2_MH_CMD_ENTRIES);
+        entry_p->line_num += TPM_MOD2_MH_CMD_ENTRIES;
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d \n", entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    /* Update main chain */
+    if (pattern_data->main_chain_type != TPM_CHAIN_TYPE_MH)
+    {
+        /* Convert Chain Index to PMT Index */
+        jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(TPM_CHAIN_TYPE_MH, chain_idx);
+        if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+        {
+            TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+            return TPM_FAIL;
+        }
+        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+        if (entry_p == NULL)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+            return TPM_FAIL;
+        }
+        if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+        {
+            if (tpm_mod2_single_command_add(&tpm_mod2_jump_subr_pattern, jump_to, entry_p) != TPM_OK)
+            {
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+            return TPM_FAIL;
+        }
+    }
+
+    return TPM_OK;
+}
+
+
+/*******************************************************************************
+* tpm_mod2_process_da_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_da_set (tpm_gmacs_enum_t      gmac_port,
+                                 uint32_t                bm,
+                                 uint16_t                cmd_idx,
+                                 uint8_t                *skip,
+                                 tpm_pkt_mod_t          *mod_data,
+                                 tpm_mod_pattern_data_t *pattern_data,
+                                 tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+    tpm_mod2_entry_t    tmp_pattern[TPM_MOD2_MAC_CMD_ENTRIES];
+    uint16_t            chain_idx = TPM_MOD2_INVALID_CHAIN_ID;
+    uint16_t            jump_to;
+    uint8_t             *mac_array = NULL;
+
+    memset(tmp_pattern, 0, sizeof(tmp_pattern));
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    /* Skip to DA field */
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    /* Build pattern entries */
+    memcpy(tmp_pattern, tpm_mod2_pattern_array[cmd_idx].entry, sizeof(tmp_pattern));
+
+    mac_array = mod_data->mac_mod.mac_da;
+
+    tmp_pattern[0].data = (mac_array[0] << 8) | mac_array[1];
+    tmp_pattern[1].data = (mac_array[2] << 8) | mac_array[3];
+    tmp_pattern[2].data = (mac_array[4] << 8) | mac_array[5];
+    tmp_pattern[2].last = 1;
+
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    /* Scan mac db to check if the mac subchain exist or not. */
+    chain_idx = tpm_db_mod2_get_chain_entry(gmac_port, TPM_CHAIN_TYPE_MAC, TPM_MOD2_MAC_CMD_ENTRIES, tmp_pattern);
+    if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        if(is_tpm_check) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "TPM check sub chain-%d failed\n", TPM_CHAIN_TYPE_MAC);
+            return TPM_FAIL;
+        }
+        /* Get next free chain index of mac subchain area */
+        chain_idx = tpm_db_mod2_get_next_free_chain_entry(gmac_port, TPM_CHAIN_TYPE_MAC);
+        if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the mac subchain \n");
+            return TPM_FAIL;
+        }
+    }
+    /* Write to mac db */
+    if(!is_tpm_check) {
+        if (tpm_db_mod2_set_chain_entry(gmac_port, TPM_CHAIN_TYPE_MAC, chain_idx,
+	                                TPM_MOD2_MAC_CMD_ENTRIES, tmp_pattern) != TPM_OK) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set mac subr chain entry\n");
+            return TPM_FAIL;
+        }
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    /* Fill DA entries in local pattern set */
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, TPM_CHAIN_TYPE_MAC, TPM_MOD2_INVALID_CHAIN_ID);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get free pattern set. \n");
+        return TPM_FAIL;
+    }
+    entry_p->index = chain_idx;
+
+    if ((entry_p->line_num + TPM_MOD2_MAC_CMD_ENTRIES) <= TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tmp_pattern,
+               sizeof(tpm_mod2_entry_t)*TPM_MOD2_MAC_CMD_ENTRIES);
+        entry_p->line_num += TPM_MOD2_MAC_CMD_ENTRIES;
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d \n", entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the mac.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    /* Add jump/jump_subr command in main_chain */
+    /* Convert Chain Index to PMT Index */
+    jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(TPM_CHAIN_TYPE_MAC, chain_idx);
+    if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+    {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+        return TPM_FAIL;
+    }
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+    if (pattern_data->main_chain_type == TPM_CHAIN_TYPE_L2)
+    {
+        if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+        {
+            if (tpm_mod2_single_command_add(&tpm_mod2_jump_pattern, jump_to, entry_p) != TPM_OK)
+            {
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+            return TPM_FAIL;
+        }
+    }
+    else
+    {
+        if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+        {
+            if (tpm_mod2_single_command_add(&tpm_mod2_jump_subr_pattern, jump_to, entry_p) != TPM_OK)
+            {
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+            return TPM_FAIL;
+        }
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_sa_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_sa_set (tpm_gmacs_enum_t      gmac_port,
+                                 uint32_t                bm,
+                                 uint16_t                cmd_idx,
+                                 uint8_t                *skip,
+                                 tpm_pkt_mod_t          *mod_data,
+                                 tpm_mod_pattern_data_t *pattern_data,
+                                 tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+    tpm_mod2_entry_t    tmp_pattern[TPM_MOD2_MAC_CMD_ENTRIES];
+    uint16_t            chain_idx = TPM_MOD2_INVALID_CHAIN_ID;
+    uint16_t            jump_to;
+    uint8_t             *mac_array = NULL;
+
+
+    memset(tmp_pattern, 0, sizeof(tmp_pattern));
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    /* Skip to SA field */
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    /* Build pattern entries */
+    memcpy(tmp_pattern, tpm_mod2_pattern_array[cmd_idx].entry, sizeof(tmp_pattern));
+
+    mac_array = mod_data->mac_mod.mac_sa;
+
+    tmp_pattern[0].data = (mac_array[0] << 8) | mac_array[1];
+    tmp_pattern[1].data = (mac_array[2] << 8) | mac_array[3];
+    tmp_pattern[2].data = (mac_array[4] << 8) | mac_array[5];
+    tmp_pattern[2].last = 1;
+
+
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    /* Scan mac db to check if the mac subchain exist or not. */
+    chain_idx = tpm_db_mod2_get_chain_entry(gmac_port, TPM_CHAIN_TYPE_MAC, TPM_MOD2_MAC_CMD_ENTRIES, tmp_pattern);
+    if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        if(is_tpm_check) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "TPM check sub chain-%d failed\n", TPM_CHAIN_TYPE_MAC);
+            return TPM_FAIL;
+        }
+        /* Get next free chain index of mac subchain area */
+        chain_idx = tpm_db_mod2_get_next_free_chain_entry(gmac_port, TPM_CHAIN_TYPE_MAC);
+        if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the mac subchain \n");
+            return TPM_FAIL;
+        }
+    }
+    /* Write to mac db */
+    if(!is_tpm_check) {
+        if (tpm_db_mod2_set_chain_entry(gmac_port, TPM_CHAIN_TYPE_MAC, chain_idx,
+	                                TPM_MOD2_MAC_CMD_ENTRIES, tmp_pattern) != TPM_OK) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set mac subr chain entry\n");
+            return TPM_FAIL;
+        }
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    /* Fill SA entries in local pattern set */
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, TPM_CHAIN_TYPE_MAC, TPM_MOD2_INVALID_CHAIN_ID);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get free pattern set. \n");
+        return TPM_FAIL;
+    }
+    entry_p->index = chain_idx;
+
+    if ((entry_p->line_num + TPM_MOD2_MAC_CMD_ENTRIES) <= TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tmp_pattern,
+               sizeof(tpm_mod2_entry_t)*TPM_MOD2_MAC_CMD_ENTRIES);
+        entry_p->line_num += TPM_MOD2_MAC_CMD_ENTRIES;
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d \n", entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the mac.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    /* add jump/jump_subr command in main_chain */
+    /* Convert Chain Index to PMT Index */
+    jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(TPM_CHAIN_TYPE_MAC, chain_idx);
+    if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+    {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+        return TPM_FAIL;
+    }
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+    if (pattern_data->main_chain_type == TPM_CHAIN_TYPE_L2)
+    {
+        if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+        {
+            if (tpm_mod2_single_command_add(&tpm_mod2_jump_pattern, jump_to, entry_p) != TPM_OK)
+            {
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+            return TPM_FAIL;
+        }
+    }
+    else
+    {
+        if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+        {
+            if (tpm_mod2_single_command_add(&tpm_mod2_jump_subr_pattern, jump_to, entry_p) != TPM_OK)
+            {
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+            return TPM_FAIL;
+        }
+    }
+
+    return TPM_OK;
+}
+
+
+/*******************************************************************************
+* tpm_mod2_configured_vlan_oper_set()
+*
+*******************************************************************************/
+uint16_t tpm_mod2_configured_vlan_oper_set (tpm_gmacs_enum_t      gmac_port,
+                                           tpm_mod2_entry_t       *patt_entry,
+                                           tpm_vlan_key_t         *vlan_data,
+                                           uint16_t               *conf_data,
+                                           tpm_mod_pattern_data_t *pattern_data,
+                                           tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+    tpm_mod2_entry_t    tmp_pattern[TPM_MOD2_MAX_VLAN_ENTRIES];
+    uint16_t            chain_idx = TPM_MOD2_INVALID_CHAIN_ID;
+
+    memset(tmp_pattern, 0, sizeof(tmp_pattern));
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    /* Build pattern entries */
+    memcpy(tmp_pattern, patt_entry, sizeof(tmp_pattern));
+    if (conf_data)
+    {
+        tmp_pattern[0].data = *conf_data;
+    }
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d: 0x%4.4x, 0x%4.4x\n",
+                 1, tmp_pattern[0].opcode, tmp_pattern[0].data);
+    if (vlan_data)
+    {
+        tmp_pattern[1].data = tpm_mod2_fill_in_vlan_data(vlan_data);
+    }
+    if (conf_data == NULL || patt_entry->opcode == TPM_MOD2_OPCODE_SKIP)
+    {
+        tmp_pattern[0].last = 1;
+    }
+    else
+    {
+        tmp_pattern[1].last = 1;
+    }
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d: 0x%4.4x, 0x%4.4x\n",
+                 1, tmp_pattern[0].opcode, tmp_pattern[0].data);
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d: 0x%4.4x, 0x%4.4x\n",
+                 2, tmp_pattern[1].opcode, tmp_pattern[1].data);
+
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    /* Scan vlan db to check if the vlan subchain exist or not. */
+    chain_idx = tpm_db_mod2_get_chain_entry(gmac_port, TPM_CHAIN_TYPE_VLAN, TPM_MOD2_MAX_VLAN_ENTRIES, tmp_pattern);
+    if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        if(is_tpm_check) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "sub chain-%d check failed\n",TPM_CHAIN_TYPE_VLAN);
+            return TPM_MOD2_INVALID_CHAIN_ID;
+        }
+        /* Get next free chain index of vlan subchain area */
+        chain_idx = tpm_db_mod2_get_next_free_chain_entry(gmac_port, TPM_CHAIN_TYPE_VLAN);
+        if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the vlan subchain \n");
+            return TPM_MOD2_INVALID_CHAIN_ID;
+        }
+    }
+    /* Write to vlan db */
+    if(!is_tpm_check) {
+        if (tpm_db_mod2_set_chain_entry(gmac_port, TPM_CHAIN_TYPE_VLAN, chain_idx,
+	                                TPM_MOD2_MAX_VLAN_ENTRIES, tmp_pattern) != TPM_OK) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set vlan subr chain entry\n");
+            return TPM_FAIL;
+        }
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    /* Fill VLAN entries in local pattern set */
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, TPM_CHAIN_TYPE_VLAN, TPM_MOD2_INVALID_CHAIN_ID);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get free pattern set. \n");
+        return TPM_FAIL;
+    }
+    entry_p->index = chain_idx;
+
+    if ((entry_p->line_num + TPM_MOD2_MAX_VLAN_ENTRIES) <= TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tmp_pattern,
+               sizeof(tpm_mod2_entry_t)*TPM_MOD2_MAX_VLAN_ENTRIES);
+        entry_p->line_num += TPM_MOD2_MAX_VLAN_ENTRIES;
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d \n", entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the vlan.pattern (%d)\n", entry_p->line_num);
+        return TPM_MOD2_INVALID_CHAIN_ID;
+    }
+
+    return chain_idx;
+}
+
+/*******************************************************************************
+* tpm_mod2_config_vlan1_data_get()
+*
+*******************************************************************************/
+int32_t tpm_mod2_config_tpid (uint8_t is_vlan1, uint16_t tpid, uint16_t tpid_mask, uint16_t *conf_data)
+{
+	int32_t     rc;
+	uint32_t    eth_type_sel;
+
+	if (tpid_mask == TPM_MOD2_NEW_TPID) {
+		rc = tpm_mod2_tpid_get(tpid, &eth_type_sel);
+
+		if (rc != TPM_OK) {
+			TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get TPID selector (0x%x)\n", tpid);
+			return rc;
+		}
+	} else {
+		if (is_vlan1 != 0)
+			eth_type_sel = TPM_MOD2_TP_FROM_VLAN_1;
+		else
+			eth_type_sel = TPM_MOD2_TP_FROM_VLAN_2;
+	}
+	
+	*conf_data = eth_type_sel;
+	return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_config_vlan1_data_get()
+*
+*******************************************************************************/
+int32_t tpm_mod2_config_vlan1_data_get (tpm_vlan_key_t *vlan_data, uint16_t *cdata)
+{
+    uint16_t conf_data;
+    int32_t  rc;
+
+    *cdata = 0;
+
+    rc = tpm_mod2_config_tpid(1, vlan_data->tpid, vlan_data->tpid_mask, &conf_data);
+
+    if (rc != TPM_OK)
+        return rc;
+
+    if (vlan_data->vid_mask == TPM_MOD2_NEW_VID)
+        conf_data |= TPM_MOD2_VID_NEW;
+    else
+        conf_data |= TPM_MOD2_VID_FROM_VLAN_1;
+
+    if (vlan_data->cfi_mask == TPM_MOD2_NEW_CFI)
+        conf_data |= TPM_MOD2_CFI_NEW;
+    else
+        conf_data |= TPM_MOD2_CFI_FROM_VLAN_1;
+
+    if (vlan_data->pbit_mask == TPM_MOD2_NEW_PBIT)
+        conf_data |= TPM_MOD2_PBIT_NEW;
+    else
+        conf_data |= TPM_MOD2_PBIT_FROM_VLAN_1;
+
+    *cdata = conf_data;
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_config_vlan2_data_get()
+*
+*******************************************************************************/
+int32_t tpm_mod2_config_vlan2_data_get (tpm_vlan_key_t *vlan_data, uint16_t *cdata)
+{
+    uint16_t conf_data;
+    int32_t  rc;
+
+    *cdata = 0;
+
+    rc = tpm_mod2_config_tpid(0, vlan_data->tpid, vlan_data->tpid_mask, &conf_data);
+
+    if (rc != TPM_OK)
+        return rc;
+
+    if (vlan_data->vid_mask == TPM_MOD2_NEW_VID)
+        conf_data |= TPM_MOD2_VID_NEW;
+    else
+        conf_data |= TPM_MOD2_VID_FROM_VLAN_2;
+
+    if (vlan_data->cfi_mask == TPM_MOD2_NEW_CFI)
+        conf_data |= TPM_MOD2_CFI_NEW;
+    else
+        conf_data |= TPM_MOD2_CFI_FROM_VLAN_2;
+
+    if (vlan_data->pbit_mask == TPM_MOD2_NEW_PBIT)
+        conf_data |= TPM_MOD2_PBIT_NEW;
+    else
+        conf_data |= TPM_MOD2_PBIT_FROM_VLAN_2;
+
+    *cdata = conf_data;
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_vlan_mod()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_vlan_mod     (tpm_gmacs_enum_t      gmac_port,
+                                       uint32_t                bm,
+                                       uint16_t                cmd_idx,
+                                       uint8_t                *skip,
+                                       tpm_pkt_mod_t          *mod_data,
+                                       tpm_mod_pattern_data_t *pattern_data,
+                                       tpm_self_check_enable_t is_tpm_check)
+{
+    uint16_t    config_data;
+    uint16_t    v1_chain_id = TPM_MOD2_INVALID_CHAIN_ID;
+    uint16_t    v2_chain_id = TPM_MOD2_INVALID_CHAIN_ID;
+    uint16_t    jump_to;
+    tpm_pattern_entry_t *entry_p = NULL;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    /* Skip to VLAN field */
+    if (mod_data->vlan_mod.vlan_op != VLANOP_NOOP)
+    {
+        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+        if (entry_p == NULL)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+            return TPM_FAIL;
+        }
+        if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+        {
+            if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+            {
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+            return TPM_FAIL;
+        }
+    } else {
+    	return TPM_OK;
+    }
+
+    switch(mod_data->vlan_mod.vlan_op)
+    {
+    case VLANOP_EXT_TAG_MOD:
+    /***********************/
+        /* Add VLAN modification commands for VLAN1 */
+        if (tpm_mod2_config_vlan1_data_get(&(mod_data->vlan_mod.vlan1_out), &config_data) == TPM_OK)
+        {
+            v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                            tpm_mod2_vlan_pattern_array[VLANOP_EXT_TAG_MOD].vlan1,
+                                                            &(mod_data->vlan_mod.vlan1_out),
+                                                            &config_data, pattern_data, is_tpm_check);
+        }
+        break;
+
+    case VLANOP_EXT_TAG_DEL:
+    /***********************/
+        /* Add VLAN delete command for VLAN1 */
+        v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port, tpm_mod2_vlan_pattern_array[VLANOP_EXT_TAG_DEL].vlan1,
+                                                        NULL, NULL, pattern_data, is_tpm_check);
+        break;
+
+    case VLANOP_EXT_TAG_INS:
+    /***********************/
+        /* Add VLAN add commands for VLAN1 */
+        if (tpm_mod2_config_vlan1_data_get(&(mod_data->vlan_mod.vlan1_out), &config_data) == TPM_OK)
+        {
+            v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                            tpm_mod2_vlan_pattern_array[VLANOP_EXT_TAG_INS].vlan1,
+                                                           &(mod_data->vlan_mod.vlan1_out),
+                                                           &config_data, pattern_data, is_tpm_check);
+        }
+        break;
+
+    case VLANOP_EXT_TAG_MOD_INS:
+    /***********************/
+        /* Add VLAN add commands for VLAN1 */
+        if (tpm_mod2_config_vlan1_data_get(&(mod_data->vlan_mod.vlan1_out), &config_data) == TPM_OK)
+        {
+            v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                            tpm_mod2_vlan_pattern_array[VLANOP_EXT_TAG_MOD_INS].vlan1,
+                                                           &(mod_data->vlan_mod.vlan1_out),
+                                                           &config_data, pattern_data, is_tpm_check);
+
+            /* Add VLAN modification commands for VLAN2 */
+            if (tpm_mod2_config_vlan1_data_get(&(mod_data->vlan_mod.vlan2_out), &config_data) == TPM_OK)
+            {
+                v2_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                                tpm_mod2_vlan_pattern_array[VLANOP_EXT_TAG_MOD_INS].vlan2,
+                                                                &(mod_data->vlan_mod.vlan2_out),
+                                                                &config_data, pattern_data, is_tpm_check);
+            }
+            else
+            {
+                return TPM_FAIL;
+            }
+        }
+        break;
+
+    case VLANOP_INS_2TAG:
+    /***********************/
+        /* Add VLAN add commands for VLAN1 */
+        if (tpm_mod2_config_vlan1_data_get(&(mod_data->vlan_mod.vlan1_out), &config_data) == TPM_OK)
+        {
+            v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                            tpm_mod2_vlan_pattern_array[VLANOP_INS_2TAG].vlan1,
+                                                            &(mod_data->vlan_mod.vlan1_out),
+                                                            &config_data, pattern_data, is_tpm_check);
+
+            /* Add VLAN add commands for VLAN2 */
+            if (tpm_mod2_config_vlan2_data_get(&(mod_data->vlan_mod.vlan2_out), &config_data) == TPM_OK)
+            {
+                v2_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                                tpm_mod2_vlan_pattern_array[VLANOP_INS_2TAG].vlan2,
+                                                                &(mod_data->vlan_mod.vlan2_out),
+                                                                &config_data, pattern_data, is_tpm_check);
+            }
+            else
+            {
+                return TPM_FAIL;
+            }
+        }
+        break;
+
+    case VLANOP_MOD_2TAG:
+    /***********************/
+        /* Add VLAN modification commands for VLAN1 */
+        if (tpm_mod2_config_vlan1_data_get(&(mod_data->vlan_mod.vlan1_out), &config_data) == TPM_OK)
+        {
+            v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                            tpm_mod2_vlan_pattern_array[VLANOP_MOD_2TAG].vlan1,
+                                                            &(mod_data->vlan_mod.vlan1_out),
+                                                            &config_data, pattern_data, is_tpm_check);
+
+            /* Add VLAN modification commands for VLAN2 */
+            if (tpm_mod2_config_vlan2_data_get(&(mod_data->vlan_mod.vlan2_out), &config_data) == TPM_OK)
+            {
+                v2_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                                tpm_mod2_vlan_pattern_array[VLANOP_MOD_2TAG].vlan2,
+                                                                &(mod_data->vlan_mod.vlan2_out),
+                                                                &config_data, pattern_data, is_tpm_check);
+            }
+            else
+            {
+                return TPM_FAIL;
+            }
+        }
+        break;
+
+    case VLANOP_SWAP_TAGS:
+    /***********************/
+        /* Add VLAN modification commands for VLAN1 */
+        if (tpm_mod2_config_vlan2_data_get(&(mod_data->vlan_mod.vlan1_out), &config_data) == TPM_OK)
+        {
+        	if (mod_data->vlan_mod.vlan1_out.tpid_mask != TPM_MOD2_NEW_TPID)
+			{
+	        	config_data &= ~(0x7);
+				config_data |= TPM_MOD2_TP_FROM_VLAN_1;
+			}
+            v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                            tpm_mod2_vlan_pattern_array[VLANOP_SWAP_TAGS].vlan1,
+                                                            &(mod_data->vlan_mod.vlan1_out),
+                                                            &config_data, pattern_data, is_tpm_check);
+
+            /* Add VLAN modification commands for VLAN2 */
+            if (tpm_mod2_config_vlan1_data_get(&(mod_data->vlan_mod.vlan2_out), &config_data) == TPM_OK)
+            {
+	        	if (mod_data->vlan_mod.vlan2_out.tpid_mask != TPM_MOD2_NEW_TPID)
+				{
+		        	config_data &= ~(0x7);
+					config_data |= TPM_MOD2_TP_FROM_VLAN_2;
+				}
+                v2_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                                tpm_mod2_vlan_pattern_array[VLANOP_SWAP_TAGS].vlan2,
+                                                                &(mod_data->vlan_mod.vlan2_out),
+                                                                &config_data, pattern_data, is_tpm_check);
+            }
+            else
+            {
+                return TPM_FAIL;
+            }
+        }
+        break;
+
+    case VLANOP_DEL_2TAG:
+    /***********************/
+        v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port, tpm_mod2_vlan_pattern_array[VLANOP_DEL_2TAG].vlan1,
+                                                        NULL, NULL, pattern_data, is_tpm_check);
+        v2_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port, tpm_mod2_vlan_pattern_array[VLANOP_DEL_2TAG].vlan2,
+                                                        NULL, NULL, pattern_data, is_tpm_check);
+        break;
+
+    case VLANOP_INT_TAG_MOD:
+    /***********************/
+        /* SKIP to the inner VLAN tag */
+        if (*skip)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "skip is not zero (%d)\n", *skip);
+            return TPM_FAIL;
+        }
+
+        config_data = tpm_mod2_vlan_pattern_array[VLANOP_INT_TAG_MOD].vlan1[0].data;
+        v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port, tpm_mod2_vlan_pattern_array[VLANOP_INT_TAG_MOD].vlan1,
+                                                        NULL, &config_data, pattern_data, is_tpm_check);
+
+        /* Add VLAN modification commands for VLAN2 */
+        if (tpm_mod2_config_vlan2_data_get(&(mod_data->vlan_mod.vlan2_out), &config_data) == TPM_OK)
+        {
+            v2_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port,
+                                                            tpm_mod2_vlan_pattern_array[VLANOP_INT_TAG_MOD].vlan2,
+                                                           &(mod_data->vlan_mod.vlan2_out),
+                                                           &config_data, pattern_data, is_tpm_check);
+        }
+        break;
+
+    case VLANOP_EXT_TAG_DEL_INT_MOD:
+    /***********************/
+        /* Add VLAN delete command for VLAN1 */
+        v1_chain_id = tpm_mod2_configured_vlan_oper_set(gmac_port, &(tpm_mod2_vlan_pattern_array[VLANOP_EXT_TAG_DEL_INT_MOD].vlan1[0]),
+                                                        NULL, NULL, pattern_data, is_tpm_check);
+
+        /* Add VLAN modification commands for VLAN2 */
+        if (tpm_mod2_config_vlan2_data_get(&(mod_data->vlan_mod.vlan2_out), &config_data) == TPM_OK)
+        {
+            v2_chain_id = tpm_mod2_configured_vlan_oper_set (gmac_port,
+                                                            tpm_mod2_vlan_pattern_array[VLANOP_EXT_TAG_DEL_INT_MOD].vlan2,
+                                                            &(mod_data->vlan_mod.vlan2_out),
+                                                            &config_data, pattern_data, is_tpm_check);
+        }
+        break;
+
+    default:
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Do nothing for %d operation \n", mod_data->vlan_mod.vlan_op);
+        return TPM_OK;
+    }
+
+    if ((v1_chain_id == TPM_MOD2_INVALID_CHAIN_ID && v2_chain_id == TPM_MOD2_INVALID_CHAIN_ID) ||
+        v1_chain_id == TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No VLAN chain is added \n");
+        return TPM_FAIL;
+    }
+
+    /* Update main chain */
+    if (v1_chain_id != TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        /* Add jump/jump_subr command in main_chain */
+        /* Convert Chain Index to PMT Index */
+        jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(TPM_CHAIN_TYPE_VLAN, v1_chain_id);
+        if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+        {
+            TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+            return TPM_FAIL;
+        }
+        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+        if (entry_p == NULL)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+            return TPM_FAIL;
+        }
+        if (pattern_data->main_chain_type != TPM_CHAIN_TYPE_L2 || v2_chain_id != TPM_MOD2_INVALID_CHAIN_ID)
+        {
+            if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+            {
+                if (tpm_mod2_single_command_add(&tpm_mod2_jump_subr_pattern, jump_to, entry_p) != TPM_OK)
+                {
+                    return TPM_FAIL;
+                }
+            }
+            else
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+            {
+                if (tpm_mod2_single_command_add(&tpm_mod2_jump_pattern, jump_to, entry_p) != TPM_OK)
+                {
+                    return TPM_FAIL;
+                }
+            }
+            else
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+                return TPM_FAIL;
+            }
+        }
+    }
+
+    if (v2_chain_id != TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        //tpm_pattern_entry_t *v1_entry, *v2_entry;
+
+        //v1_entry = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, TPM_CHAIN_TYPE_VLAN, v1_chain_id);
+        //v2_entry = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, TPM_CHAIN_TYPE_VLAN, v2_chain_id);
+        //if (v1_entry == NULL || v2_entry == NULL)
+        //{
+        //    TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get v1 or v2 pattern set. \n");
+        //    return TPM_FAIL;
+        //}
+
+        //if (v1_entry->line_num == v2_entry->line_num &&
+        //    !memcmp(v1_entry->line, v2_entry->line,
+        //            v1_entry->line_num * sizeof(tpm_mod2_entry_t)))
+        //{
+        //    v2_entry->index = v1_chain_id;
+        //    jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(TPM_CHAIN_TYPE_VLAN, v1_chain_id);
+        //    if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+        //    {
+        //        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+        //        return TPM_FAIL;
+        //    }
+        //}
+        //else
+        //{
+            /* Convert Chain Index to PMT Index */
+            jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(TPM_CHAIN_TYPE_VLAN, v2_chain_id);
+            if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+            {
+                TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+                return TPM_FAIL;
+            }
+        //}
+
+        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+        if (entry_p == NULL)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+            return TPM_FAIL;
+        }
+        /* Add jump/jump_subr command in main_chain */
+        if (pattern_data->main_chain_type == TPM_CHAIN_TYPE_L2)
+        {
+            if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+            {
+                if (tpm_mod2_single_command_add(&tpm_mod2_jump_pattern, jump_to, entry_p) != TPM_OK)
+                {
+                    return TPM_FAIL;
+                }
+            }
+            else
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+                return TPM_FAIL;
+            }
+        }
+        else
+        {
+            if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+            {
+                if (tpm_mod2_single_command_add(&tpm_mod2_jump_subr_pattern, jump_to, entry_p) != TPM_OK)
+                {
+                    return TPM_FAIL;
+                }
+            }
+            else
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+                return TPM_FAIL;
+            }
+        }
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_pppoe_del()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_pppoe_del (tpm_gmacs_enum_t      gmac_port,
+                                    uint32_t                bm,
+                                    uint16_t                cmd_idx,
+                                    uint8_t                *skip,
+                                    tpm_pkt_mod_t          *mod_data,
+                                    tpm_mod_pattern_data_t *pattern_data,
+                                    tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+    tpm_mod2_entry_t     tmp_pattern[TPM_MOD2_PPPOE_DEL_CMD_ENTRIES];
+    uint16_t             chain_idx = TPM_MOD2_INVALID_CHAIN_ID;
+    uint16_t             jump_to;
+	tpm_chain_type_t     subr_chain = TPM_CHAIN_TYPE_PPPOE;
+
+    memset(tmp_pattern, 0, sizeof(tmp_pattern));
+
+	if (bm & TPM_IPV6_UPDATE)
+		subr_chain = TPM_CHAIN_TYPE_IPV6_PPPOE;
+
+    /* Build pattern entries */
+    memcpy(tmp_pattern, tpm_mod2_pattern_array[cmd_idx].entry,
+           sizeof(tpm_mod2_entry_t)*TPM_MOD2_PPPOE_DEL_CMD_ENTRIES);
+    tmp_pattern[TPM_MOD2_PPPOE_DEL_CMD_ENTRIES-1].last = 1;
+
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    /*update IPV6 in pattern*/
+    if (bm & TPM_IPV6_UPDATE)
+        tmp_pattern[0].data = 0x86dd;
+
+    /* Scan pppoe db to check if the pppoe subchain exist or not.  */
+    chain_idx = tpm_db_mod2_get_chain_entry(gmac_port, subr_chain, TPM_MOD2_PPPOE_DEL_CMD_ENTRIES, tmp_pattern);
+    if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+    {
+    	/*If it is tpm check, subchain check failed, return*/
+        if (is_tpm_check) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "TPM check sub chain-%d failed\n", subr_chain);
+            return TPM_FAIL;
+        }
+        /* Get next free chain index of pppoe subchain area */
+        chain_idx = tpm_db_mod2_get_next_free_chain_entry(gmac_port, subr_chain);
+        if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the pppoe subchain \n");
+            return TPM_FAIL;
+        }
+    }
+    /* Write to pppoe db */
+    if(!is_tpm_check) {
+        if (tpm_db_mod2_set_chain_entry(gmac_port, subr_chain, chain_idx,
+	                                TPM_MOD2_PPPOE_DEL_CMD_ENTRIES, tmp_pattern) != TPM_OK) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set pppoe subr chain entry\n");
+	        return TPM_FAIL;
+	    }
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    /* Fill PPPoE DEL entries in local pattern set */
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, subr_chain, TPM_MOD2_INVALID_CHAIN_ID);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get free pattern set. \n");
+        return TPM_FAIL;
+    }
+    entry_p->index = chain_idx;
+
+    if ((entry_p->line_num + TPM_MOD2_PPPOE_DEL_CMD_ENTRIES) <= TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tmp_pattern,
+               sizeof(tpm_mod2_entry_t)*TPM_MOD2_PPPOE_DEL_CMD_ENTRIES);
+        entry_p->line_num += TPM_MOD2_PPPOE_DEL_CMD_ENTRIES;
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d \n", entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the pppoe.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    /* Add jump/jump_subr command in main_chain */
+    /* Convert Chain Index to PMT Index */
+    jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(subr_chain, chain_idx);
+    if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+    {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+        return TPM_FAIL;
+    }
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        if (tpm_mod2_single_command_add(&tpm_mod2_jump_subr_pattern, jump_to, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_pppoe_add()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_pppoe_add (tpm_gmacs_enum_t      gmac_port,
+                                    uint32_t                bm,
+                                    uint16_t                cmd_idx,
+                                    uint8_t                *skip,
+                                    tpm_pkt_mod_t          *mod_data,
+                                    tpm_mod_pattern_data_t *pattern_data,
+                                    tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+    tpm_mod2_entry_t    ipv4_pattern[TPM_MOD2_PPPOE_ADD_CMD_ENTRIES];
+    tpm_mod2_entry_t    ipv6_pattern[TPM_MOD2_IPV6_PPPOE_ADD_CMD_ENTRIES];
+    uint16_t            chain_idx = TPM_MOD2_INVALID_CHAIN_ID;
+    uint16_t            jump_to;
+	tpm_chain_type_t    subr_chain = TPM_CHAIN_TYPE_PPPOE;
+    tpm_mod2_entry_t    *tmp_pattern = ipv4_pattern;
+	uint32_t            entry_num = TPM_MOD2_PPPOE_ADD_CMD_ENTRIES;
+	
+
+    memset(ipv4_pattern, 0, sizeof(ipv4_pattern));
+    memset(ipv6_pattern, 0, sizeof(ipv6_pattern));
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+	if (bm & TPM_IPV6_UPDATE) {
+		subr_chain = TPM_CHAIN_TYPE_IPV6_PPPOE;
+		tmp_pattern = ipv6_pattern;
+		entry_num = TPM_MOD2_IPV6_PPPOE_ADD_CMD_ENTRIES;
+	}
+	
+    /* Build pattern entries */
+	if (bm & TPM_IPV6_UPDATE) {
+	    memcpy(tmp_pattern, tpm_mod2_ipv6_pppoe_pattern.entry,
+	           entry_num * sizeof(tpm_mod2_entry_t));
+	    tmp_pattern[2].data = mod_data->pppoe_mod.ppp_session;
+	} else {
+	    memcpy(tmp_pattern, tpm_mod2_pattern_array[cmd_idx].entry,
+	           entry_num * sizeof(tpm_mod2_entry_t));
+	    tmp_pattern[0].data = mod_data->pppoe_mod.ppp_session;
+	}
+    tmp_pattern[entry_num - 1].last = 1;
+
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    /* Scan pppoe db to check if the pppoe subchain exist or not. */
+    chain_idx = tpm_db_mod2_get_chain_entry(gmac_port, subr_chain, entry_num, tmp_pattern);
+    if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+    {
+        if(is_tpm_check) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "TPM check sub chain-%d failed\n", subr_chain);
+            return TPM_FAIL;
+        }
+        /* Get next free chain index of pppoe subchain area */
+        chain_idx = tpm_db_mod2_get_next_free_chain_entry(gmac_port, subr_chain);
+        if (chain_idx == TPM_MOD2_INVALID_CHAIN_ID)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the pppoe subchain \n");
+            return TPM_FAIL;
+        }
+    }
+    /* Write to pppoe db */
+    if(!is_tpm_check) {
+        if (tpm_db_mod2_set_chain_entry(gmac_port, subr_chain, chain_idx,
+	                                entry_num, tmp_pattern) != TPM_OK) {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set pppoe subr chain entry\n");
+            return TPM_FAIL;
+        }
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    /* Fill PPPoE ADD entries in local pattern set */
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, subr_chain, TPM_MOD2_INVALID_CHAIN_ID);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get free pattern set. \n");
+        return TPM_FAIL;
+    }
+    entry_p->index = chain_idx;
+
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tmp_pattern,
+               entry_num * sizeof(tpm_mod2_entry_t));
+        entry_p->line_num += entry_num;
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d \n", entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the pppoe.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    /* Add jump/jump_subr command in main_chain */
+    /* Convert Chain Index to PMT Index */
+    jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(subr_chain, chain_idx);
+    if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+    {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+        return TPM_FAIL;
+    }
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        if (tpm_mod2_single_command_add(&tpm_mod2_jump_subr_pattern, jump_to, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_ipv4_update()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_ipv4_update (tpm_gmacs_enum_t      gmac_port,
+                                      uint32_t                bm,
+                                      uint16_t                cmd_idx,
+                                      uint8_t                *skip,
+                                      tpm_pkt_mod_t          *mod_data,
+                                      tpm_mod_pattern_data_t *pattern_data,
+                                      tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if ((bm & TPM_DSCP_SET)     ||
+        (bm & TPM_TTL_DEC)      ||
+        (bm & TPM_IPV4_SRC_SET) ||
+        (bm & TPM_IPV4_DST_SET))
+    {
+        if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+            return TPM_FAIL;
+
+        /* Copy IP checksum pattern */
+        if (tpm_mod2_single_command_add(&tpm_mod2_pattern_array[cmd_idx], 0, entry_p) != TPM_OK)
+            return TPM_FAIL;
+    }
+    else
+    {
+        *skip = tpm_mod2_pattern_array[cmd_idx].skip_no_parse;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_dscp_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_dscp_set (tpm_gmacs_enum_t      gmac_port,
+                                   uint32_t                bm,
+                                   uint16_t                cmd_idx,
+                                   uint8_t                *skip,
+                                   tpm_pkt_mod_t          *mod_data,
+                                   tpm_mod_pattern_data_t *pattern_data,
+                                   tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+    uint16_t    data = 0;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if (bm & TPM_IPV4_UPDATE)
+    {
+        if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+
+        /* Copy IPv4 DSCP pattern */
+        data = tpm_mod2_pattern_array[cmd_idx].entry[0].data |
+               ((mod_data->l3.ipv4_mod.ipv4_dscp << TPM_MOD2_DSCP_DATA_BIT) & TPM_MOD2_DSCP_DATA_MASK);
+
+        if (tpm_mod2_single_command_add(&tpm_mod2_pattern_array[cmd_idx], data, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+    }
+    else
+    {
+        if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+
+        /* Copy IPv6 TC pattern */
+        data = tpm_mod2_ipv6_tc_pattern.entry[0].data |
+               ((mod_data->l3.ipv6_mod.ipv6_dscp << TPM_MOD2_TC_DATA_BIT) & TPM_MOD2_TC_DATA_MASK);
+
+        if (tpm_mod2_single_command_add(&tpm_mod2_ipv6_tc_pattern, data, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_ttl_dec()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_ttl_dec (tpm_gmacs_enum_t      gmac_port,
+                                  uint32_t                bm,
+                                  uint16_t                cmd_idx,
+                                  uint8_t                *skip,
+                                  tpm_pkt_mod_t          *mod_data,
+                                  tpm_mod_pattern_data_t *pattern_data,
+                                  tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+    uint16_t extra_word_skip = 0;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    /* Save skip command by TTL DEC skip_before */
+    if (*skip % 2)
+    {
+        if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+    }
+    else
+    {
+        extra_word_skip = (*skip / 2) << 8;
+        *skip = 0;
+    }
+
+    /* Copy TTL DEC pattern w/o changing data*/
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tpm_mod2_pattern_array[cmd_idx].entry, sizeof(tpm_mod2_entry_t));
+        entry_p->line[entry_p->line_num].data += extra_word_skip;
+        entry_p->line_num++;
+
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added command 0x%x pattern_line=%d\n",
+                    tpm_mod2_pattern_array[cmd_idx].entry[0].opcode, entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_v4_sip_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_v4_sip_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    /* Copy IPv4 SIP pattern */
+    if ((entry_p->line_num + TPM_MOD2_IP_CMD_ENTRIES) <= TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tpm_mod2_pattern_array[cmd_idx].entry,
+               sizeof(tpm_mod2_entry_t)*TPM_MOD2_IP_CMD_ENTRIES);
+
+        entry_p->line[entry_p->line_num++].data = ((mod_data->l3.ipv4_mod.ipv4_src_ip_add[0] << 8) | mod_data->l3.ipv4_mod.ipv4_src_ip_add[1]);
+        entry_p->line[entry_p->line_num++].data = ((mod_data->l3.ipv4_mod.ipv4_src_ip_add[2] << 8) | mod_data->l3.ipv4_mod.ipv4_src_ip_add[3]);
+
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d \n", entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+
+/*******************************************************************************
+* tpm_mod2_process_v4_dip_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_v4_dip_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    /* Copy IPv4 DIP pattern */
+    if ((entry_p->line_num + TPM_MOD2_IP_CMD_ENTRIES) <= TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tpm_mod2_pattern_array[cmd_idx].entry,
+               sizeof(tpm_mod2_entry_t)*TPM_MOD2_IP_CMD_ENTRIES);
+
+        entry_p->line[entry_p->line_num++].data = ((mod_data->l3.ipv4_mod.ipv4_dst_ip_add[0] << 8) | mod_data->l3.ipv4_mod.ipv4_dst_ip_add[1]);
+        entry_p->line[entry_p->line_num++].data = ((mod_data->l3.ipv4_mod.ipv4_dst_ip_add[2] << 8) | mod_data->l3.ipv4_mod.ipv4_dst_ip_add[3]);
+
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "pattern_line=%d \n", entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_hoplim_dec()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_hoplim_dec (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    /* Copy Hop limit DEC pattern w/o changing data*/
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tpm_mod2_pattern_array[cmd_idx].entry, sizeof(tpm_mod2_entry_t));
+        entry_p->line_num++;
+
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added command 0x%x pattern_line=%d\n",
+                    tpm_mod2_pattern_array[cmd_idx].entry[0].opcode, entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_l4_src_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_l4_src_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    /* Copy L4 SRC pattern */
+    if (tpm_mod2_single_command_add(&tpm_mod2_pattern_array[cmd_idx],
+                                    mod_data->l3.ipv4_mod.l4_src_port, entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+
+/*******************************************************************************
+* tpm_mod2_process_l4_dst_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_l4_dst_set (tpm_gmacs_enum_t      gmac_port,
+                                     uint32_t                bm,
+                                     uint16_t                cmd_idx,
+                                     uint8_t                *skip,
+                                     tpm_pkt_mod_t          *mod_data,
+                                     tpm_mod_pattern_data_t *pattern_data,
+                                     tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if (tpm_mod2_skip_command_add(skip, tpm_mod2_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    /* Copy L4 DST pattern */
+    if (tpm_mod2_single_command_add(&tpm_mod2_pattern_array[cmd_idx],
+                                    mod_data->l3.ipv4_mod.l4_dst_port, entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_l4_checksum_set()
+*
+*******************************************************************************/
+int32_t tpm_mod2_process_l4_checksum_set(tpm_gmacs_enum_t      gmac_port,
+                                         uint32_t                bm,
+                                         uint16_t                cmd_idx,
+                                         uint8_t                *skip,
+                                         tpm_pkt_mod_t          *mod_data,
+                                         tpm_mod_pattern_data_t *pattern_data,
+                                         tpm_self_check_enable_t is_tpm_check)
+{
+    tpm_pattern_entry_t *entry_p = NULL;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "gmac(%d), bitmap(%x)\n",gmac_port, bm);
+
+    if (bm & TPM_INT_L4_UDP)
+    {
+        /* If udp_checksum_calc is taken from Init, take init value */
+        if (tpm_db_mod2_get_udp_checksum_init_bm_state())
+        {
+            if (!tpm_db_mod2_get_udp_checksum_state())
+                return TPM_OK;
+        }
+        else if ((bm & TPM_INT_UDP_CHECKSUM) == 0) /* else take from API flag */
+        {
+            return TPM_OK;
+        }
+    }
+
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, pattern_data->main_chain_type, pattern_data->main_chain_id);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+        return TPM_FAIL;
+    }
+
+    if (tpm_mod2_skip_command_add(skip, tpm_mod2_int_pattern_array[cmd_idx].skip_before, entry_p) != TPM_OK)
+    {
+        return TPM_FAIL;
+    }
+
+    /* Copy L4 checksum pattern w/o changing data*/
+    if (entry_p->line_num < TPM_MOD2_MAX_PATTERN_ENTRIES)
+    {
+        memcpy(&(entry_p->line[entry_p->line_num]), tpm_mod2_int_pattern_array[cmd_idx].entry, sizeof(tpm_mod2_entry_t));
+        entry_p->line_num++;
+
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added command 0x%x pattern_line=%d\n",
+                    tpm_mod2_pattern_array[cmd_idx].entry[0].opcode, entry_p->line_num);
+    }
+    else
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the tmp.pattern (%d)\n", entry_p->line_num);
+        return TPM_FAIL;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_process_l4_checksum_set()
+*
+*******************************************************************************/
+static uint8_t  tpm_mod2_skip_get (tpm_pkt_mod_bm_t mod_bm,
+                                   uint16_t         mod_flag_idx)
+{
+    uint8_t skip_val = 0;
+
+    switch(mod_flag_idx)
+    {
+    case TPM_MOD_MAC_DA_SET:     /* 0 - Update the MAC DA Address*/
+    case TPM_MOD_MAC_SA_SET:     /* 1 - Update the MAC SA Address*/
+    case TPM_MOD_VLAN_MOD:       /* 2 - Update the VLAN Tags (add/del/update)*/
+    case TPM_MOD_PPPOE_DEL:      /* 3 - Delete a PPPoE encapsulation*/
+    case TPM_MOD_PPPOE_ADD:      /* 4 - Add a PPPoE encapsulation*/
+        skip_val = tpm_mod2_pattern_array[mod_flag_idx].skip_no_parse;
+        break;
+
+    case TPM_MOD_DSCP_SET:       /* 5 - Set the DSCP value */
+        skip_val = tpm_mod2_pattern_array[mod_flag_idx].skip_no_parse;
+
+        break;
+
+    case TPM_MOD_TTL_DEC:        /* 6 - Decrease the TTL value */
+    case TPM_MOD_IPV4_SRC_SET:   /* 8 - Set the IPV4 Source Address */
+    case TPM_MOD_IPV4_DST_SET:   /* 9 - Set the IPV4 Destination Address */
+        if (mod_bm & TPM_IPV4_UPDATE)
+        {
+            skip_val = tpm_mod2_pattern_array[mod_flag_idx].skip_no_parse;
+        }
+        break;
+
+    case TPM_MOD_HOPLIM_DEC:     /* 11 - Decrease the Hop Limit value */
+    case TPM_MOD_IPV6_SRC_SET:   /* 12 - Set the IPV6 Source Address */
+    case TPM_MOD_IPV6_DST_SET:   /* 13 - Set the IPV6 Destination Address */
+        if (mod_bm & TPM_IPV6_UPDATE)
+        {
+            skip_val = tpm_mod2_pattern_array[mod_flag_idx].skip_no_parse;
+        }
+        break;
+
+    case TPM_MOD_L4_SRC_SET:     /* 14 - Set the L4 Source Port (UDP or TCP) */
+    case TPM_MOD_L4_DST_SET:     /* 15 - Set the L4 Destination Port (UDP or TCP) */
+        if ((mod_bm & TPM_IPV6_UPDATE) ||
+            (mod_bm & TPM_IPV4_UPDATE))
+        {
+            skip_val = tpm_mod2_pattern_array[mod_flag_idx].skip_no_parse;
+        }
+        break;
+
+    case TPM_MOD_IPV4_UPDATE:    /* 7 - Update the IPv4 Header*/
+    case TPM_MOD_IPV6_UPDATE:    /* 10 - Update the IPv6 Header */
+    default:
+        break;
+    }
+
+    return skip_val;
+}
+
+/*******************************************************************************
+* tpm_mod2_parse_get()
+*
+*******************************************************************************/
+static uint8_t  tpm_mod2_l2_parse_len_get (uint16_t         mod_flag_idx,
+                                           uint32_t         mh_en,
+                                           tpm_pkt_mod_t   *mod_data)
+{
+    uint8_t  parse_len = 0;
+
+    if (mod_flag_idx < TPM_MOD_PPPOE_DEL)
+    {
+        if (mod_flag_idx >= TPM_MOD_MH_SET && mh_en)
+        {
+            parse_len += 2; // add mh len
+        }
+
+        if (mod_flag_idx >= TPM_MOD_MAC_DA_SET)
+        {
+            parse_len += 6; // add da len
+        }
+
+        if (mod_flag_idx >= TPM_MOD_MAC_SA_SET)
+        {
+            parse_len += 6; // add sa len
+        }
+
+        if (mod_flag_idx == TPM_MOD_VLAN_MOD)
+        {
+            switch (mod_data->vlan_mod.vlan_op)
+            {
+            case VLANOP_EXT_TAG_MOD:
+            case VLANOP_EXT_TAG_DEL:
+            case VLANOP_EXT_TAG_MOD_INS:
+                parse_len += 4; // one tag is processed.
+                break;
+
+            case VLANOP_INS_2TAG:
+            case VLANOP_MOD_2TAG:
+            case VLANOP_SWAP_TAGS:
+            case VLANOP_DEL_2TAG:
+            case VLANOP_INT_TAG_MOD:
+            case VLANOP_EXT_TAG_DEL_INT_MOD:
+                parse_len += 8; // two tags are processed.
+                break;
+
+            case VLANOP_EXT_TAG_INS:
+            default:
+                break;
+            }
+        }
+    }
+
+    return parse_len;
+}
+
+/*******************************************************************************
+* tpm_mod2_fill_in_pattern()
+*
+* DESCRIPTION: The API sets the temporary pattern which will be written to HW.
+*
+* INPUTS:   mod_bm      - set of flags described which fields in the packet
+*                         to be changed
+*           int_mod_bm  - set of internal flags
+*           mod_data    - modification entry data
+*	    is_tpm_check -fill pattern for tpm check or not
+*
+* OUTPUTS:
+*           mod_entry   - start entry number which has been set for this
+*                         modification <j>
+*
+* RETURNS:
+*           TPM_OK, TPM_NOT_FOUND or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_fill_in_pattern   (tpm_gmacs_enum_t     gmac_port,
+                                       tpm_pkt_mod_bm_t        mod_bm,
+                                       tpm_pkt_mod_int_bm_t    int_mod_bm,
+                                       tpm_pkt_mod_t          *mod_data,
+                                       uint32_t               *mod_entry,
+                                       tpm_mod_pattern_data_t *pattern_data,
+                                       tpm_self_check_enable_t is_tpm_check)
+{
+    uint16_t    jump_idx, main_idx, flag_idx, jump_to;
+    uint16_t    last_mod_flag = TPM_MOD_MH_SET;
+    uint8_t     skip = 0;
+    uint8_t     minus_len = 0;
+    uint32_t    mh_en;
+    tpm_chain_type_t     main_chain_type, db_main_chain_type;
+    tpm_pattern_entry_t *entry_p = NULL;
+    uint32_t    i;
+    uint16_t    max_sz;
+    uint16_t    pmt_entry;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+    jump_idx = 0;
+
+    /* Init jump pattern entry */
+    entry_p = &pattern_data->pattern_set[0];
+    entry_p->is_valid   = 1;
+    entry_p->area_type  = TPM_AREA_TYPE_JUMP;
+    entry_p->chain_type = TPM_CHAIN_TYPE_NONE;
+
+    if (TPM_CHECK_DISABLE == is_tpm_check) {
+        /* Get next_free index => jump_idx */
+        spin_lock_bh(&tpmMod2JumpEntryLock);
+        if ((TPM_SPLIT_MOD_ENABLED == tpm_db_split_mod_get_enable()) && (int_mod_bm & TPM_INT_SPLIT_MOD))
+        {
+            TPM_OS_INFO(TPM_MODZ2_HM_MOD, "Need split_mod JUMP entry\n");
+            jump_idx = tpm_db_mod2_get_next_split_mod_free_jump_entry(gmac_port, mod_data);
+        }
+	else {
+            TPM_OS_INFO(TPM_MODZ2_HM_MOD, "Need common JUMP entry\n");
+            jump_idx = tpm_db_mod2_get_next_free_jump_entry(gmac_port);
+	}
+        spin_unlock_bh(&tpmMod2JumpEntryLock);
+        if (jump_idx == TPM_MOD2_NULL_ENT_IDX)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free JUMP entry\n");
+            return TPM_FAIL;
+        }
+
+        /* Ensure there is no write to index 0 in modification table */
+        if (jump_idx == 0)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Illegal write to index 0 in modification table: (jump_idx=%d)\n", jump_idx);
+            return TPM_FAIL;
+        }
+	entry_p->index = jump_idx;
+        /* Return mod_entry index */
+        *mod_entry = jump_idx;
+    } else {
+        entry_p->index = *mod_entry;
+        jump_idx = *mod_entry;
+        /*get main chain index*/
+        if (tpm_mod2_main_chain_index_get(gmac_port, jump_idx, &pmt_entry,is_tpm_check)) {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain index for tpm check\n");
+            return TPM_FAIL;
+        }
+        /*get chain ID by PMT entry index*/
+        if (tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port,pmt_entry,&db_main_chain_type,&main_idx)) {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Get main chain id failed for tpm check\n");
+            return TPM_FAIL;
+        }
+    }
+
+    /* Get main chain type from mod_bm */
+    main_chain_type = tpm_mod2_parse_chain_type(mod_bm, int_mod_bm);
+    if (TPM_CHECK_DISABLE == is_tpm_check) {
+        spin_lock_bh(&tpmMod2ChainEntryLock);
+        /* Get next_free index by chain_type => main_idx */
+        main_idx = tpm_db_mod2_get_next_free_chain_entry(gmac_port, main_chain_type);
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+        if (main_idx == TPM_MOD2_INVALID_CHAIN_ID) {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "No free space in the main area (chain_type=%d)\n", main_chain_type);
+            return TPM_FAIL;
+        }
+    }
+
+    /* Get port MH mode */
+    if (tpm_db_gmac_mh_en_conf_get(gmac_port, &mh_en)) {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get port MH mode\n");
+        return TPM_FAIL;
+    }
+
+    /* Set main chain for mod_rules */
+    pattern_data->main_chain_type = main_chain_type;
+    pattern_data->main_chain_id   = main_idx;
+
+    /* Get free pattern entry for main_chain */
+    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, main_chain_type, TPM_MOD2_INVALID_CHAIN_ID);
+    if (entry_p == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get free pattern set for main_chain\n");
+        return TPM_FAIL;
+    }
+    entry_p->index = pattern_data->main_chain_id;
+
+    for (flag_idx = 0; flag_idx < TPM_MAX_PKT_MOD_FLAGS; flag_idx++)
+    {
+        if (mod_bm & tpm_mod2_pattern_array[flag_idx].mask)
+        {
+            /* next pattern found */
+            if (tpm_mod2_pattern_array[flag_idx].process_pattern != NULL)
+            {
+                entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, main_chain_type, main_idx);
+                if (entry_p == NULL)
+                {
+                    TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set\n");
+                    return TPM_FAIL;
+                }
+
+                //if ((last_mod_flag < TPM_MOD_PPPOE_DEL && flag_idx == TPM_MOD_PPPOE_DEL) ||
+                //    (last_mod_flag < TPM_MOD_PPPOE_ADD && flag_idx == TPM_MOD_PPPOE_ADD))
+                //{
+                //    /* skip to L3_offset */
+                //    minus_len = tpm_mod2_l2_parse_len_get(last_mod_flag, mod_data);
+                //    if (tpm_mod2_skip_to_l3_offset_command_add(&skip, (minus_len + 2/*eth_type*/), entry_p) != TPM_OK)
+                //    {
+                //        return TPM_FAIL;
+                //    }
+                //    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added SKIP to ipv4 header\n");
+                //}
+
+                if (last_mod_flag < TPM_MOD_PPPOE_DEL && flag_idx == TPM_MOD_PPPOE_DEL)
+                {
+                    /* skip to L3_offset */
+                    minus_len = tpm_mod2_l2_parse_len_get(last_mod_flag, mh_en, mod_data);
+                    minus_len+= (2/*eth_type*/ + 8/*pppoe_hdr*/);
+                    if (tpm_mod2_skip_to_l3_offset_command_add(&skip, minus_len, entry_p) != TPM_OK)
+                    {
+                        return TPM_FAIL;
+                    }
+                    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added SKIP to ipv4 header\n");
+                }
+                else if (last_mod_flag < TPM_MOD_PPPOE_ADD && flag_idx == TPM_MOD_PPPOE_ADD)
+                {
+                    /* skip to L3_offset */
+                    minus_len = tpm_mod2_l2_parse_len_get(last_mod_flag, mh_en, mod_data);
+                    minus_len+= 2/*eth_type*/;
+                    if (tpm_mod2_skip_to_l3_offset_command_add(&skip, minus_len, entry_p) != TPM_OK)
+                    {
+                        return TPM_FAIL;
+                    }
+                    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added SKIP to ipv4 header\n");
+                }
+
+                if (tpm_mod2_pattern_array[flag_idx].process_pattern(gmac_port, mod_bm, flag_idx, &skip, mod_data, pattern_data, is_tpm_check) != TPM_OK)
+                {
+                    TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to add cmd pattern (%d)\n", flag_idx);
+                    return TPM_FAIL;
+                }
+                last_mod_flag = flag_idx;
+                TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added patterns for %d \n", flag_idx);
+            }
+            else
+            {
+                //if ((last_mod_flag < TPM_MOD_PPPOE_ADD && flag_idx == TPM_MOD_PPPOE_ADD) ||
+                //    (last_mod_flag < TPM_MOD_PPPOE_DEL && flag_idx == TPM_MOD_PPPOE_DEL))
+                if (last_mod_flag < TPM_MOD_PPPOE_DEL && flag_idx == TPM_MOD_PPPOE_ADD)
+                {
+                    /* Skip to L3 offset if L3_mod is requested */
+                    if (mod_bm & (TPM_MOD2_IPV4_MOD_MASK | TPM_MOD2_IPV6_MOD_MASK | TPM_MOD2_L4_MOD_MASK))
+                    {
+                        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, main_chain_type, main_idx);
+                        if (entry_p == NULL)
+                        {
+                            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+                            return TPM_FAIL;
+                        }
+
+                        /* Skip to L3_offset */
+                        minus_len = tpm_mod2_l2_parse_len_get(last_mod_flag, mh_en, mod_data);
+                        if (tpm_mod2_skip_to_l3_offset_command_add(&skip, minus_len, entry_p) != TPM_OK)
+                        {
+                            return TPM_FAIL;
+                        }
+                        last_mod_flag = TPM_MOD_PPPOE_ADD;
+                        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added SKIP to ipv4 header\n");
+                    }
+                    else
+                    {
+                        /* Finish parsing mod_flag */
+                        break;
+                    }
+                }
+                else
+                {
+                    skip += tpm_mod2_skip_get(mod_bm, flag_idx);
+                }
+            }
+        }
+        else
+        {
+            /* If not match any mod flag before L3 offset, skip the gap between VLAN Tag and L3 header. */
+            if (last_mod_flag < TPM_MOD_PPPOE_DEL && flag_idx == TPM_MOD_PPPOE_ADD)
+            {
+                if (mod_bm & (TPM_MOD2_IPV4_MOD_MASK | TPM_MOD2_IPV6_MOD_MASK | TPM_MOD2_L4_MOD_MASK))
+                {
+                    entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, main_chain_type, main_idx);
+                    if (entry_p == NULL)
+                    {
+                        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+                        return TPM_FAIL;
+                    }
+
+                    /* skip to L3_offset */
+                    minus_len = tpm_mod2_l2_parse_len_get(last_mod_flag, mh_en, mod_data);
+                    if (tpm_mod2_skip_to_l3_offset_command_add(&skip, minus_len, entry_p) != TPM_OK)
+                    {
+                        return TPM_FAIL;
+                    }
+                    last_mod_flag = TPM_MOD_PPPOE_ADD;
+                }
+                else
+                {
+                    /* Finish parsing mod_flag */
+                    break;
+                }
+            }
+            else
+            {
+                skip += tpm_mod2_skip_get(mod_bm, flag_idx);
+            }
+        }
+    }
+
+    if (mod_bm & TPM_L4_SRC_SET ||
+        mod_bm & TPM_L4_DST_SET ||
+        mod_bm & TPM_IPV6_SRC_SET ||
+        mod_bm & TPM_IPV6_DST_SET ||
+        mod_bm & TPM_IPV4_SRC_SET ||
+        mod_bm & TPM_IPV4_DST_SET)
+    {
+        /* Update L4 checksum */
+        for (flag_idx = 0; flag_idx < TPM_MAX_INT_MOD_FLAGS; flag_idx++)
+        {
+            if (int_mod_bm & tpm_mod2_int_pattern_array[flag_idx].mask)
+            {
+                if (tpm_mod2_int_pattern_array[flag_idx].process_pattern != NULL)
+                {
+                    if (tpm_mod2_int_pattern_array[flag_idx].process_pattern(gmac_port, int_mod_bm, flag_idx, &skip, mod_data, pattern_data, is_tpm_check) != TPM_OK)
+                    {
+                        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to add cmd pattern (%d)\n", flag_idx);
+                        return TPM_FAIL;
+                    }
+
+                    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added patterns for %d \n", flag_idx);
+                }
+            }
+        }
+    }
+
+    if (main_chain_type != TPM_CHAIN_TYPE_MH)
+    {
+        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, main_chain_type, main_idx);
+        if (entry_p == NULL)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+            return TPM_FAIL;
+        }
+        /* Set "last" bit to the last modification entry */
+        entry_p->line[entry_p->line_num-1].last = 1;
+        /* Last command should never be jump_subr, replace it with jump */
+        if (entry_p->line[entry_p->line_num-1].opcode == TPM_MOD2_OPCODE_JUMP_SUBR)
+        {
+            entry_p->line[entry_p->line_num-1].opcode = TPM_MOD2_OPCODE_JUMP;
+        }
+    }
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Set last bit to pattern_line=%d\n", entry_p->line_num-1);
+
+    /* Write jump entry to db */
+    jump_to = tpm_db_mod2_convert_chain_to_pmt_entry(main_chain_type, pattern_data->main_chain_id);
+    if (jump_to == TPM_MOD2_NULL_ENT_IDX)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+        return TPM_FAIL;
+    }
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "[GMAC-%d] Jump from 0x%04x to chain-%d[%d] 0x%04x\n",
+                 gmac_port, jump_idx, main_chain_type, pattern_data->main_chain_id, jump_to);
+
+    /* Verify whether the Marvell tag has been defined -
+       in this case the first command in the pattern should be JUMP_SKIP2 */
+    /* get the MH - if enabled or not */
+    entry_p = &pattern_data->pattern_set[0];
+    if (mh_en == TPM_FALSE || mod_bm & TPM_MH_SET)
+    {
+        if (tpm_mod2_single_command_add(&tpm_mod2_jump_pattern, jump_to, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added JUMP pattern\n");
+    }
+    else
+    {
+        if (tpm_mod2_single_command_add(&tpm_mod2_jump_skip2_pattern, jump_to, entry_p) != TPM_OK)
+        {
+            return TPM_FAIL;
+        }
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Added JUMP-SKIP2 pattern\n");
+    }
+
+    /*if function for tpm check, return from here*/
+    if (is_tpm_check)
+        return TPM_OK;
+
+    spin_lock_bh(&tpmMod2JumpEntryLock);
+    if (tpm_db_mod2_set_jump_entry(gmac_port, entry_p->index, entry_p->line) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2JumpEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set jump entry\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2JumpEntryLock);
+
+    if (main_chain_type != TPM_CHAIN_TYPE_MH)
+    {
+        /* Write main chain entry to db */
+        entry_p = tpm_mod2_get_chain_from_pattern_set(pattern_data->pattern_set, main_chain_type, main_idx);
+        if (entry_p == NULL)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Fail to get main pattern set. \n");
+            return TPM_FAIL;
+        }
+        spin_lock_bh(&tpmMod2ChainEntryLock);
+        if (tpm_db_mod2_set_chain_entry(gmac_port, main_chain_type, main_idx, entry_p->line_num, entry_p->line) != TPM_OK)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set main chain entry\n");
+            return TPM_FAIL;
+        }
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+    }
+
+    /* Check if number of chain PMT entry exceeds the maximum chain size */
+    for (i=1; i < TPM_MOD2_MAX_PATTERN_SETS; i++)
+    {
+        entry_p = &pattern_data->pattern_set[i];
+
+        if (entry_p->is_valid)
+        {
+            max_sz = tpm_db_mod2_get_chain_max_size(entry_p->chain_type);
+            if (entry_p->line_num > max_sz)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "chain(%d) PMT entry number(%d) exceeds the maximum chain size(%d)\n", 
+                             entry_p->chain_type, entry_p->line_num, max_sz);
+                return TPM_FAIL;
+            }
+        }
+    }
+
+    return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_mod2_hw_add_entry()
+*
+* DESCRIPTION: The API writes a complete Modification table entry to HW table
+*
+* INPUTS:   gmac_port   - GMAC port
+*           pattern_set - pattern array with data to be written
+*
+* OUTPUTS:
+*
+* RETURNS:
+*           TPM_OK, TPM_NOT_FOUND or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_hw_add_entry   (tpm_gmacs_enum_t       gmac_port,
+                                    tpm_mod_pattern_data_t *pattern_data)
+{
+    uint16_t    line_id, set_id, pmt_id, /*chain_id, */valid_set_num;
+    uint32_t    cfg_pnc_parse_flag = 0;
+    uint8_t     is_exist;
+    tpm_pattern_entry_t *entry_p = NULL;
+    tpm_mod2_entry_t    *line_p  = NULL;
+
+    MV_NETA_PMT entry;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "\n");
+
+	cfg_pnc_parse_flag = mv_eth_ctrl_pnc_get();
+
+    if (cfg_pnc_parse_flag == 1) {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, " TPM is NOT configuring the PNC / MOD - MV driver is responsible \n");
+        return (TPM_OK);
+    }
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, " TPM is configuring the PNC / MOD \n");
+
+    valid_set_num = 0;
+    /* Set sub chain and main chain first */
+    for (set_id = 1; set_id < TPM_MOD2_MAX_PATTERN_SETS; set_id++)
+    {
+        entry_p = &pattern_data->pattern_set[set_id];
+        if (entry_p->is_valid)
+        {
+            TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, " Write pattern set %d to HW: chain_type %d, chain_index %d, line_num %d\n",
+                         set_id, entry_p->chain_type, entry_p->index, entry_p->line_num);
+
+            /* Validate pattern data */
+            if (entry_p->line_num == 0)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Empty pattern\n");
+                return TPM_FAIL;
+            }
+
+            /* Convert chain index to PMT entry index */
+            pmt_id = tpm_db_mod2_convert_chain_to_pmt_entry(entry_p->chain_type, entry_p->index);
+            if (pmt_id == TPM_MOD2_NULL_ENT_IDX)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid pmt entry\n");
+                return TPM_FAIL;
+            }
+
+            valid_set_num++;
+
+            /* If chain_type is one of the subchains,
+               check if the entry has already existed in database. */
+            switch (entry_p->chain_type)
+            {
+            case TPM_CHAIN_TYPE_MH:
+            case TPM_CHAIN_TYPE_MAC:
+            case TPM_CHAIN_TYPE_PPPOE:
+			case TPM_CHAIN_TYPE_IPV6_PPPOE:
+            case TPM_CHAIN_TYPE_VLAN:
+                spin_lock_bh(&tpmMod2ChainEntryLock);
+                if (tpm_db_mod2_if_chain_pmt_entries_exist(gmac_port, entry_p->chain_type, entry_p->index, &is_exist) != TPM_OK)
+                {
+                    spin_unlock_bh(&tpmMod2ChainEntryLock);
+                    TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get hw entries status\n");
+                    return TPM_FAIL;
+                }
+                if (is_exist)
+                {
+                    spin_unlock_bh(&tpmMod2ChainEntryLock);
+                    continue;
+                }
+                if (tpm_db_mod2_activate_chain_pmt_entry(gmac_port, entry_p->chain_type, entry_p->index) != TPM_OK)
+                {
+                    spin_unlock_bh(&tpmMod2ChainEntryLock);
+                    TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to activate hw entries\n");
+                    return TPM_FAIL;
+                }
+                spin_unlock_bh(&tpmMod2ChainEntryLock);
+                break;
+            case TPM_CHAIN_TYPE_L2:
+            case TPM_CHAIN_TYPE_IPV4_NAPT:
+            case TPM_CHAIN_TYPE_IPV4_MC:
+            case TPM_CHAIN_TYPE_ROUTE:
+            case TPM_CHAIN_TYPE_IPV6_MC:
+                spin_lock_bh(&tpmMod2ChainEntryLock);
+                if (tpm_db_mod2_activate_chain_pmt_entry(gmac_port, entry_p->chain_type, entry_p->index) != TPM_OK)
+                {
+                    spin_unlock_bh(&tpmMod2ChainEntryLock);
+                    TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to activate hw entries\n");
+                    return TPM_FAIL;
+                }
+                spin_unlock_bh(&tpmMod2ChainEntryLock);
+                break;
+            default:
+                break;
+            }
+
+            for (line_id = 0; line_id < TPM_MOD2_MAX_PATTERN_ENTRIES && line_id < entry_p->line_num; line_id++)
+            {
+                line_p = &entry_p->line[line_id];
+                /* Fill in modData */
+                entry.word = line_p->data & MV_NETA_PMT_DATA_MASK;
+                /* Fill in opCode */
+                entry.word |= ((line_p->opcode << MV_NETA_PMT_CMD_OFFS) & MV_NETA_PMT_CMD_ALL_MASK);
+                /* Fill in L3 checksum flag */
+                entry.word |= ((line_p->updt_ipv4 << MV_NETA_PMT_IP4_CSUM_BIT) & MV_NETA_PMT_IP4_CSUM_MASK);
+                /* Fill in L4 checksum flag */
+                entry.word |= ((line_p->updt_tcp << MV_NETA_PMT_L4_CSUM_BIT) & MV_NETA_PMT_L4_CSUM_MASK);
+                /* Fill in last instruction flag */
+                entry.word |= ((line_p->last << MV_NETA_PMT_LAST_BIT) & MV_NETA_PMT_LAST_MASK);
+
+                spin_lock_bh(&tpmMod2PmtHwLock);
+                mvNetaPmtWrite(gmac_port, pmt_id++, &entry);
+                spin_unlock_bh(&tpmMod2PmtHwLock);
+            }
+        }
+    }
+
+    /* Set jump entry */
+    line_p = &pattern_data->pattern_set[0].line[0];
+    /* Fill in modData */
+    entry.word = line_p->data & MV_NETA_PMT_DATA_MASK;
+    /* Fill in opCode */
+    entry.word |= ((line_p->opcode << MV_NETA_PMT_CMD_OFFS) & MV_NETA_PMT_CMD_ALL_MASK);
+    /* Fill in L3 checksum flag */
+    entry.word |= ((line_p->updt_ipv4 << MV_NETA_PMT_IP4_CSUM_BIT) & MV_NETA_PMT_IP4_CSUM_MASK);
+    /* Fill in L4 checksum flag */
+    entry.word |= ((line_p->updt_tcp << MV_NETA_PMT_L4_CSUM_BIT) & MV_NETA_PMT_L4_CSUM_MASK);
+    /* Fill in last instruction flag */
+    entry.word |= ((line_p->last << MV_NETA_PMT_LAST_BIT) & MV_NETA_PMT_LAST_MASK);
+
+    spin_lock_bh(&tpmMod2PmtHwLock);
+    mvNetaPmtWrite(gmac_port, pattern_data->pattern_set[0].index, &entry);
+    spin_unlock_bh(&tpmMod2PmtHwLock);
+
+    return TPM_OK;
+}
+
+int32_t    tpm_mod2_flush_all   (tpm_gmacs_enum_t       gmac_port,
+                            tpm_mod_pattern_data_t *pattern_data,
+                            uint8_t                 updt_next_free,
+                            uint8_t                 on_failure)
+{
+    uint16_t set_id;
+    tpm_pattern_entry_t *pattern_set = NULL;
+    
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    pattern_set = pattern_data->pattern_set;
+
+	if (pattern_set[0].index != 0 && pattern_set[0].index != TPM_MOD2_NULL_ENT_IDX) {
+	    spin_lock_bh(&tpmMod2JumpEntryLock);
+	    if (tpm_db_mod2_flush_jump_area(gmac_port, pattern_set[0].index, updt_next_free, on_failure) != TPM_OK)
+	    {
+	        spin_unlock_bh(&tpmMod2JumpEntryLock);
+	        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to flush jump area\n");
+	        return TPM_FAIL;
+	    }
+	    spin_unlock_bh(&tpmMod2JumpEntryLock);
+	}
+	
+	if (pattern_data->main_chain_type != TPM_CHAIN_TYPE_NONE) {
+	    for (set_id = 1; set_id < TPM_MOD2_MAX_PATTERN_SETS; set_id++)
+	    {
+	        if (pattern_set[set_id].is_valid)
+	        {
+	            spin_lock_bh(&tpmMod2ChainEntryLock);
+	            if (tpm_db_mod2_flush_chain_entry(gmac_port, pattern_set[set_id].chain_type,
+	                                        pattern_set[set_id].index, updt_next_free, on_failure) != TPM_OK)
+	            {
+	                spin_unlock_bh(&tpmMod2ChainEntryLock);
+	                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to flush jump area\n");
+	                return TPM_FAIL;
+	            }
+	            spin_unlock_bh(&tpmMod2ChainEntryLock);
+	        }
+	    }
+	}
+	
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_hw_add_entry()
+*
+* DESCRIPTION: The API writes NOOP entry to HW Modification table
+*
+* INPUTS:   gmac_port   - GMAC port
+*           mod_entry   - modification entry number
+*
+* OUTPUTS:
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_hw_inv_entry   (tpm_gmacs_enum_t    gmac_port,
+                                    uint16_t            mod_entry)
+{
+    MV_NETA_PMT entry;
+    uint32_t    cfg_pnc_parse_flag = 0;
+
+	cfg_pnc_parse_flag = mv_eth_ctrl_pnc_get();
+
+    if (cfg_pnc_parse_flag == 1) {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, " TPM is NOT invalidating the MOD - MV driver is responsible \n");
+        return (TPM_OK);
+    }
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, " gmac_port = %d mod_entry = %d\n", gmac_port, mod_entry);
+
+    entry.word = 0;
+    /* Fill in opCode */
+    entry.word |= ((TPM_MOD2_OPCODE_NOOP << MV_NETA_PMT_CMD_OFFS) & MV_NETA_PMT_CMD_ALL_MASK);
+    /* Fill in last instruction flag */
+    entry.word |= ((1 << MV_NETA_PMT_LAST_BIT) & MV_NETA_PMT_LAST_MASK);
+
+    spin_lock_bh(&tpmMod2PmtHwLock);
+    mvNetaPmtWrite(gmac_port, mod_entry, &entry);
+    spin_unlock_bh(&tpmMod2PmtHwLock);
+
+    return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_mod2_sw_add_entry()
+*
+* DESCRIPTION: The API writes a complete Modification table entry to Shadow table
+*
+* INPUTS:   gmac_port   - GMAC port
+*
+* OUTPUTS:  None
+*
+* RETURNS:
+*           TPM_OK, TPM_NOT_FOUND or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_sw_add_entry   (tpm_mod_owner_t     owner,
+                                    tpm_gmacs_enum_t        gmac_port,
+                                    tpm_mod_pattern_data_t *pattern_data)
+{
+    uint16_t             set_id;
+    tpm_pattern_entry_t *entry_p;
+
+    if (pattern_data == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    for (set_id = 0; set_id < TPM_MOD2_MAX_PATTERN_SETS; set_id++)
+    {
+        entry_p = &pattern_data->pattern_set[set_id];
+        if (entry_p->is_valid)
+        {
+            if (entry_p->area_type == TPM_AREA_TYPE_JUMP)
+            {
+                spin_lock_bh(&tpmMod2JumpEntryLock);
+                if (tpm_db_mod2_activate_jump_entry(gmac_port, entry_p->index) != TPM_OK)
+                {
+                    spin_unlock_bh(&tpmMod2JumpEntryLock);
+                    TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set jump entry\n");
+                    return TPM_FAIL;
+                }
+                spin_unlock_bh(&tpmMod2JumpEntryLock);
+            }
+            else
+            {
+                spin_lock_bh(&tpmMod2ChainEntryLock);
+                if (tpm_db_mod2_activate_chain_entry(gmac_port, entry_p->chain_type, entry_p->index) != TPM_OK)
+                {
+                    spin_unlock_bh(&tpmMod2ChainEntryLock);
+                    TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to set chain-%d entry\n", entry_p->chain_type);
+                    return TPM_FAIL;
+                }
+                spin_unlock_bh(&tpmMod2ChainEntryLock);
+            }
+        }
+    }
+
+    return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_mod2_print_set_params()
+*
+* DESCRIPTION: Prints set parameters
+*
+* INPUTS:   gmac_port   - GMAC port
+*           mod_bm      - set of flags described which fields in the packet
+*                         to be changed
+*           mod_data    - modification entry data
+*
+* OUTPUTS:  None
+*
+* RETURNS:
+*           TPM_OK, TPM_NOT_FOUND or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+void    tpm_mod2_print_set_params   (tpm_gmacs_enum_t   gmac_port,
+                                     tpm_pkt_mod_bm_t   mod_bm,
+                                     tpm_pkt_mod_t      *mod_data)
+{
+    char    mac_str[DB_MAC_STR_LEN] = {'\0'};
+    char    mac_mask_str[DB_MAC_STR_LEN] = {'\0'};
+    char    ipv4_str[DB_IPV4_STR_LEN];
+    char    ipv4_mask_str[DB_IPV4_STR_LEN];
+    char    ipv6_str[DB_IPV6_STR_LEN];
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "port = %d, BM = 0x%x\n", gmac_port, mod_bm);
+    printk("VLAN data: op = %d\n", mod_data->vlan_mod.vlan_op);
+    printk("   VLAN1 tpid=0x%4.4x, vid=%d(%d), cfi=%d(%d), pbit=%d(%d)\n", mod_data->vlan_mod.vlan1_out.tpid,
+           mod_data->vlan_mod.vlan1_out.vid, mod_data->vlan_mod.vlan1_out.vid_mask,
+           mod_data->vlan_mod.vlan1_out.cfi, mod_data->vlan_mod.vlan1_out.cfi_mask,
+           mod_data->vlan_mod.vlan1_out.pbit, mod_data->vlan_mod.vlan1_out.pbit_mask);
+    printk("   VLAN2 tpid=0x%4.4x, vid=%d(%d), cfi=%d(%d), pbit=%d(%d)\n", mod_data->vlan_mod.vlan2_out.tpid,
+           mod_data->vlan_mod.vlan2_out.vid, mod_data->vlan_mod.vlan2_out.vid_mask,
+           mod_data->vlan_mod.vlan2_out.cfi, mod_data->vlan_mod.vlan2_out.cfi_mask,
+           mod_data->vlan_mod.vlan2_out.pbit, mod_data->vlan_mod.vlan2_out.pbit_mask);
+    printk("MH data:   0x%02x\n", mod_data->mh_mod);
+    printk("MAC data:  SRC %s  MASK %s\n",
+           db_mac_to_str(mod_data->mac_mod.mac_sa, mac_str),
+           db_mac_to_str(mod_data->mac_mod.mac_sa_mask, mac_mask_str));
+    printk("           DST %s  MASK %s\n",
+           db_mac_to_str(mod_data->mac_mod.mac_da, mac_str),
+           db_mac_to_str(mod_data->mac_mod.mac_da_mask, mac_mask_str));
+    printk("PPPoE data: session 0x%x  proto 0x%x\n",
+           mod_data->pppoe_mod.ppp_session, mod_data->pppoe_mod.ppp_proto);
+
+    if (mod_bm & TPM_IPV4_UPDATE)
+    {
+        printk("IPv4 data: proto = %d\n", mod_data->l3.ipv4_mod.ipv4_proto);
+        printk("           SRC %s  MASK %s\n",
+               db_ipv4_to_str(mod_data->l3.ipv4_mod.ipv4_src_ip_add, ipv4_str),
+               db_ipv4_to_str(mod_data->l3.ipv4_mod.ipv4_src_ip_add_mask, ipv4_mask_str));
+        printk("           DST %s  MASK %s\n",
+               db_ipv4_to_str(mod_data->l3.ipv4_mod.ipv4_dst_ip_add, ipv4_str),
+               db_ipv4_to_str(mod_data->l3.ipv4_mod.ipv4_dst_ip_add_mask, ipv4_mask_str));
+        printk("           DSCP %d  MASK 0x%x\n",
+               mod_data->l3.ipv4_mod.ipv4_dscp, mod_data->l3.ipv4_mod.ipv4_dscp_mask);
+        printk("L4 data:   SRC port = %d DST port = %d\n",
+               mod_data->l3.ipv4_mod.l4_src_port, mod_data->l3.ipv4_mod.l4_dst_port);
+    }
+
+    if (mod_bm & TPM_IPV6_UPDATE)
+    {
+        printk("IPv6 data: proto = %d\n", mod_data->l3.ipv6_mod.ipv6_next_header);
+        printk("           SRC %s \n",
+               db_ipv4_to_str(mod_data->l3.ipv6_mod.ipv6_src_ip_add, ipv6_str));
+        printk("           MASK %s\n",
+               db_ipv4_to_str(mod_data->l3.ipv6_mod.ipv6_src_ip_add_mask, ipv6_str));
+        printk("           DST %s\n",
+               db_ipv4_to_str(mod_data->l3.ipv6_mod.ipv6_dst_ip_add, ipv6_str));
+        printk("           MASK %s\n",
+               db_ipv4_to_str(mod_data->l3.ipv6_mod.ipv6_dst_ip_add_mask, ipv6_str));
+        printk("           DSCP %d  MASK 0x%x\n",
+               mod_data->l3.ipv6_mod.ipv6_dscp, mod_data->l3.ipv6_mod.ipv6_dscp_mask);
+        printk("L4 data:   SRC port = %d DST port = %d\n",
+               mod_data->l3.ipv6_mod.l4_src_port, mod_data->l3.ipv6_mod.l4_dst_port);
+    }
+}
+
+/*******************************************************************************
+                               Modification table APIs
+*******************************************************************************/
+
+int32_t    tpm_mod2_inlock_entry_set(tpm_mod_owner_t      owner,
+                                     tpm_gmacs_enum_t     gmac_port,
+                                     tpm_pkt_mod_bm_t     mod_bm,
+                                     tpm_pkt_mod_int_bm_t int_mod_bm,
+                                     tpm_pkt_mod_t        *mod_data,
+                                     uint32_t             *mod_entry)
+{
+    int32_t     rc;
+    tpm_mod_pattern_data_t pattern_data;
+
+    /* PH1 - clear the global pattern for reuse */
+    memset(&pattern_data, 0, sizeof(tpm_mod_pattern_data_t));
+
+    *mod_entry = TPM_MOD2_NULL_ENT_IDX;
+
+    /* validate logical parameters*/
+    rc = tpm_mod2_validate_logical_params(gmac_port, mod_bm, int_mod_bm, mod_data, mod_entry);
+
+    if (rc != TPM_OK) {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, " -- tpm_mod2_validate_logical_params FAILED. \n");
+        return (TPM_FAIL);
+    }
+
+    /* print debug - all function params */
+    TPM_OS_COND_DEBUG(TPM_MODZ2_HM_MOD)
+    {
+        tpm_mod2_print_set_params (gmac_port, mod_bm, mod_data);
+    }
+    /*if only VLAN mod, and op is NO OP, return from here*/
+    if ((mod_bm & TPM_VLAN_MOD) && ((mod_bm & ~TPM_VLAN_MOD) == 0)) {
+        if(mod_data->vlan_mod.vlan_op == VLANOP_NOOP) {
+            *mod_entry = 0;
+            return (TPM_OK);
+        }
+    }
+
+    /* update the pattern of new modification with real data */
+    rc = tpm_mod2_fill_in_pattern(gmac_port, mod_bm, int_mod_bm, mod_data, mod_entry, &pattern_data, TPM_CHECK_DISABLE);
+
+    if (rc != TPM_OK) {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, " -- tpm_mod2_fill_in_pattern FAILED. \n");
+        if (tpm_mod2_flush_all(gmac_port, &pattern_data, 0, 1) != TPM_OK)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to flush pmt entry status\n");
+            return TPM_FAIL;
+        }
+        return (TPM_FAIL);
+    }
+
+
+    TPM_OS_COND_DEBUG(TPM_MODZ2_HM_MOD)
+    {
+        tpm_mod2_print_tmp_pattern(&pattern_data);
+    }
+
+    if (*mod_entry != 0)
+    {
+        /* WR entries to the HW table */
+        rc = tpm_mod2_hw_add_entry(gmac_port, &pattern_data);
+
+        if (rc != TPM_OK) {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, " -- tpm_mod2_hw_add_entry FAILED. \n");
+            if (tpm_mod2_flush_all(gmac_port, &pattern_data, 0, 1) != TPM_OK)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to flush pmt entry status\n");
+                return TPM_FAIL;
+            }
+            return (TPM_FAIL);
+        }
+
+
+        /* WR entries to the SW table */
+        rc = tpm_mod2_sw_add_entry(owner, gmac_port, &pattern_data);
+
+        if (rc != TPM_OK) {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, " -- tpm_mod2_sw_add_entry FAILED. \n");
+            if (tpm_mod2_flush_all(gmac_port, &pattern_data, 0, 1) != TPM_OK)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to flush pmt entry status\n");
+                return TPM_FAIL;
+            }
+            return (TPM_FAIL);
+        }
+    }
+
+    if (tpm_mod2_flush_all(gmac_port, &pattern_data, 0, 0) != TPM_OK)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to flush pmt entry status\n");
+        return TPM_FAIL;
+    }
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Modification entry start index = %d\n", *mod_entry);
+
+    return (TPM_OK);
+}
+
+/*******************************************************************************
+* tpm_mod2_entry_set()
+*
+* DESCRIPTION: The API sets a complete Modification table entry
+*
+* INPUTS:   gmac_port   - GMAC port
+*           mod_bm      - set of flags described which fields in the packet
+*                         to be changed
+*           int_mod_bm  - set of internal flags
+*           mod_data    - modification entry data
+*
+* OUTPUTS:
+*           mod_entry   - start entry number which has been set for this
+*                         modification
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_entry_set   (tpm_mod_owner_t      owner,
+                                 tpm_gmacs_enum_t     gmac_port,
+                                 tpm_pkt_mod_bm_t     mod_bm,
+                                 tpm_pkt_mod_int_bm_t int_mod_bm,
+                                 tpm_pkt_mod_t        *mod_data,
+                                 uint32_t             *mod_entry)
+{
+    int32_t           rc;
+
+    rc = tpm_mod2_inlock_entry_set(owner, gmac_port, mod_bm, int_mod_bm, mod_data, mod_entry);
+
+    return(rc);
+}
+
+
+/*******************************************************************************
+* tpm_mod2_entry_get()
+*
+* DESCRIPTION: The API gets Modification table entry
+*
+* INPUTS:   gmac_port   - GMAC port
+*           mod_entry   - start entry number (in the "jump" area)
+*
+* OUTPUTS:
+*           valid_entries   - number of valid entries in the chunk
+*                             0 - there is no requested data
+*           pnc_ref         - Number of references from Pnc entries to this modification rule
+* RETURNS:
+*           pointer to the tpm_mod2_rule_entries[TPM_MOD2_MAIN_CHAIN_SIZE]
+*           included requested data or NULL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_entry_get   (tpm_gmacs_enum_t   gmac_port,
+                                        uint32_t           mod_entry,
+                                        uint16_t           *entries_num,
+                                        tpm_mod_rule_t     *pnc_entries)
+{
+    uint16_t pmt_entry, main_chain_id, subr_chain_id, entry_num, entry_id, subr_entry_num, subr_entry_id;
+    uint16_t main_entry, subr_entry;
+    uint16_t pattern_num = 0;
+    tpm_mod2_entry_t  pattern_data;
+    tpm_chain_type_t  main_chain_type, subr_chain_type;
+
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Get Mod. entry for port %d with start index = %d\n",
+                 gmac_port, mod_entry);
+
+    if (gmac_port >= TPM_MAX_NUM_GMACS)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: port %d\n", gmac_port);
+        return TPM_FAIL;
+    }
+
+    if (entries_num == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    if (pnc_entries == NULL)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: NULL pointer\n");
+        return TPM_FAIL;
+    }
+
+    *entries_num = 0;
+
+    /* Get jump entry pattern data */
+    spin_lock_bh(&tpmMod2JumpEntryLock);
+    if (tpm_db_mod2_get_jump_entry_pattern_data(gmac_port, mod_entry, &pattern_data) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2JumpEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to delete jump entry\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2JumpEntryLock);
+
+    if (pattern_num < TPM_MAX_MOD_RULE_NUM)
+    {
+        pnc_entries[pattern_num].entry_id = mod_entry;
+        memcpy(&(pnc_entries[pattern_num].entry_data), &pattern_data, sizeof(tpm_mod2_entry_t));
+        pattern_num++;
+    }
+
+
+    /* Get main chain PMT entry index */
+    pmt_entry = tpm_mod2_get_jump_to(&pattern_data);
+    if (pmt_entry == TPM_MOD2_NULL_ENT_IDX)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain entry\n");
+        return TPM_FAIL;
+    }
+
+    main_entry = pmt_entry;
+
+    /* Get main chain type and chain index */
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    if (tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port, pmt_entry, &main_chain_type, &main_chain_id) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain entry\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    if (tpm_db_mod2_get_chain_entry_num(gmac_port, main_chain_type, main_chain_id, &entry_num) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain size\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    for (entry_id = 0; entry_id < entry_num; entry_id++)
+    {
+        /* Get main chain entry pattern data */
+        spin_lock_bh(&tpmMod2ChainEntryLock);
+        if (tpm_db_mod2_get_chain_entry_pattern_data(gmac_port, main_chain_type, main_chain_id,
+                                                        entry_id, &pattern_data) != TPM_OK)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain data\n");
+        }
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+        if (pattern_num < TPM_MAX_MOD_RULE_NUM)
+        {
+            pnc_entries[pattern_num].entry_id = main_entry + entry_id;
+            memcpy(&(pnc_entries[pattern_num].entry_data), &pattern_data, sizeof(tpm_mod2_entry_t));
+            pattern_num++;
+        }
+
+        /* Check if calling a subr chain */
+        pmt_entry = tpm_mod2_get_jump_to(&pattern_data);
+        if (pmt_entry == TPM_MOD2_NULL_ENT_IDX)
+        {
+            continue;
+        }
+
+        subr_entry = pmt_entry;
+
+        /* Get subr chain type and chain index */
+        spin_lock_bh(&tpmMod2ChainEntryLock);
+        if (tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port, pmt_entry, &subr_chain_type, &subr_chain_id) != TPM_OK)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain entry\n");
+        }
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+        spin_lock_bh(&tpmMod2ChainEntryLock);
+        if (tpm_db_mod2_get_chain_entry_num(gmac_port, subr_chain_type, subr_chain_id, &subr_entry_num) != TPM_OK)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get subr chain size\n");
+            return TPM_FAIL;
+        }
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+        for (subr_entry_id = 0; subr_entry_id < subr_entry_num; subr_entry_id++)
+        {
+            /* Get subr chain entry pattern data */
+            spin_lock_bh(&tpmMod2ChainEntryLock);
+            if (tpm_db_mod2_get_chain_entry_pattern_data(gmac_port, subr_chain_type, subr_chain_id,
+                                                            subr_entry_id, &pattern_data) != TPM_OK)
+            {
+                spin_unlock_bh(&tpmMod2ChainEntryLock);
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get subr chain data\n");
+            }
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+            if (pattern_num < TPM_MAX_MOD_RULE_NUM)
+            {
+                pnc_entries[pattern_num].entry_id = subr_entry + subr_entry_id;
+                memcpy(&(pnc_entries[pattern_num].entry_data), &pattern_data, sizeof(tpm_mod2_entry_t));
+                pattern_num++;
+            }
+        }
+    }
+
+    *entries_num = pattern_num;
+
+    return TPM_OK;
+}
+
+
+/*******************************************************************************
+* tpm_mod2_entry_del()
+*
+* DESCRIPTION: The API invalidates a modification entry chunk - given by PNC.
+*
+* INPUTS:   gmac_port   - GMAC port
+*           mod_entry   - start entry number (in the "jump" area)
+*
+* OUTPUTS:
+*
+* RETURNS:
+*           TPM_OK, TPM_NOT_FOUND or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_mod2_inlock_entry_del(tpm_mod_owner_t      owner,
+                                  tpm_gmacs_enum_t     gmac_port,
+                                  uint32_t             mod_entry)
+{
+    uint16_t pmt_entry, main_chain_id, subr_chain_id, entry_num, entry_id;
+    tpm_mod2_entry_t  pattern_data;
+    tpm_chain_type_t  main_chain_type, subr_chain_type;
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "for gmac_port= (%d) mod_entry (%d)\n", gmac_port, mod_entry);
+    if (gmac_port >= TPM_MAX_NUM_GMACS)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: port %d\n", gmac_port);
+        return TPM_FAIL;
+    }
+
+    memset(&pattern_data, 0, sizeof(tpm_mod2_entry_t));
+
+    /* Invalidate HW entry */
+    tpm_mod2_hw_inv_entry(gmac_port, mod_entry);
+
+    /* Get jump entry pattern data */
+    spin_lock_bh(&tpmMod2JumpEntryLock);
+    if (tpm_db_mod2_get_jump_entry_pattern_data(gmac_port, mod_entry, &pattern_data) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2JumpEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to delete jump entry\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2JumpEntryLock);
+
+    /* Delete jump entry */
+    spin_lock_bh(&tpmMod2JumpEntryLock);
+    if (tpm_db_mod2_del_jump_entry(gmac_port, mod_entry) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2JumpEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to delete jump entry\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2JumpEntryLock);
+
+    /* Get main chain PMT entry index */
+    pmt_entry = tpm_mod2_get_jump_to(&pattern_data);
+    if (pmt_entry == TPM_MOD2_NULL_ENT_IDX)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain entry\n");
+        return TPM_FAIL;
+    }
+    /* Get main chain type and chain index */
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    if (tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port, pmt_entry, &main_chain_type, &main_chain_id) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain entry\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    if (tpm_db_mod2_get_chain_entry_num(gmac_port, main_chain_type, main_chain_id, &entry_num) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain size\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    for (entry_id = 0; entry_id < entry_num; entry_id++)
+    {
+        /* Get main chain entry pattern data */
+        spin_lock_bh(&tpmMod2ChainEntryLock);
+        if (tpm_db_mod2_get_chain_entry_pattern_data(gmac_port, main_chain_type, main_chain_id,
+                                                        entry_id, &pattern_data) != TPM_OK)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain size\n");
+        }
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+        /* Check if calling a subr chain */
+        pmt_entry = tpm_mod2_get_jump_to(&pattern_data);
+        if (pmt_entry == TPM_MOD2_NULL_ENT_IDX)
+        {
+            continue;
+        }
+
+        /* Get subr chain type and chain index */
+        spin_lock_bh(&tpmMod2ChainEntryLock);
+        if (tpm_db_mod2_get_chain_id_by_pmt_entry(gmac_port, pmt_entry, &subr_chain_type, &subr_chain_id) != TPM_OK)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get main chain entry\n");
+        }
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+        /* Delete subr chain */
+        spin_lock_bh(&tpmMod2ChainEntryLock);
+        if (tpm_db_mod2_del_chain_entry(gmac_port, subr_chain_type, subr_chain_id) != TPM_OK)
+        {
+            spin_unlock_bh(&tpmMod2ChainEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to delete chain entries\n");
+        }
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+    }
+
+    /* Delete main chain */
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    if (tpm_db_mod2_del_chain_entry(gmac_port, main_chain_type, main_chain_id) != TPM_OK)
+    {
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to delete chain entries\n");
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_entry_del()
+*
+* DESCRIPTION: The API invalidates a modification entry chunk - given by PNC.
+*
+* INPUTS:   gmac_port   - GMAC port
+*           mod_entry   - start entry number (in the "jump" area)
+*
+* OUTPUTS:
+*
+* RETURNS:
+*           TPM_OK, TPM_NOT_FOUND or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_mod2_entry_del(tpm_mod_owner_t      owner,
+                           tpm_gmacs_enum_t     gmac_port,
+                           uint32_t             mod_entry)
+{
+    int32_t            rc;
+
+    //if (in_interrupt())
+    //{
+    //    return ERR_IN_INTERRUPT;
+    //}
+
+    /* Lock the Mod */
+    //spin_lock(&tpmModLock);
+
+    rc = tpm_mod2_inlock_entry_del(owner, gmac_port, mod_entry);
+
+    /* Unlock Mod */
+    //spin_lock(&tpmModLock);
+    return (rc);
+}
+
+
+/*******************************************************************************
+* tpm_mod2_mac_inv()
+*
+* DESCRIPTION: The API resets Modification table for a specified port
+*
+* INPUTS:   gmac_port     - GMAC port
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_mac_inv  (tpm_gmacs_enum_t   gmac_port)
+{
+    uint32_t    cfg_pnc_parse_flag = 0;
+
+	cfg_pnc_parse_flag = mv_eth_ctrl_pnc_get();
+
+    if (cfg_pnc_parse_flag == 1) {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, " TPM is NOT invalidating the MOD - MV driver is responsible \n");
+        return (TPM_OK);
+    }
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, " gmac_port = %d \n", gmac_port);
+
+    if (gmac_port >= TPM_MAX_NUM_GMACS)
+    {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid parameter: port %d \n", gmac_port);
+        return TPM_FAIL;
+    }
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "gmac port = %d\n", gmac_port);
+
+    /* Invalidate PMT */
+    mvNetaPmtClear(gmac_port);
+
+    return TPM_OK;
+}
+
+
+
+/*******************************************************************************
+* tpm_mod2_registers_init()
+*
+* DESCRIPTION: The API sets init values to the HW registers used by modification
+*
+* INPUTS:   None
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_mod2_registers_init  (tpm_gmacs_enum_t   gmac_port, uint16_t  txp)
+{
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "\n");
+
+    /* Init PPPOE registers*/
+    MV_REG_WRITE (NETA_TX_PMT_PPPOE_TYPE_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_ETY);
+    MV_REG_WRITE (NETA_TX_PMT_PPPOE_DATA_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_DATA);
+    MV_REG_WRITE (NETA_TX_PMT_PPPOE_LEN_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_LEN);
+    MV_REG_WRITE (NETA_TX_PMT_PPPOE_PROTO_REG(gmac_port, txp), TPM_MOD2_DEFAULT_PPPOE_PROTO);
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_modz2_tpid_get()
+*
+* DESCRIPTION:     The function receives a tpid, and returns the selector that matches it.
+*                  - If the tpid has a match, it is returned.
+*                  - If there is no match, a new selector  is created in hardware and in DB.
+*                  - If there is no free selector,  an error is returned
+*
+* INPUTS:
+* tpid            - Requested Vlan tpid
+*
+* OUTPUTS:
+* eth_type_sel    - selector that matches the tpid
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_mod2_tpid_get(uint32_t tpid,
+                          uint32_t *eth_type_sel)
+{
+    uint32_t    ret_code;
+    uint32_t    l_etype_sel;
+    int         port, txp;
+
+    /* Check if vlan_ethertype exists */
+    ret_code = tpm_db_mod_etype_sel_get(tpid, &l_etype_sel);
+
+    /*Create new entry for ethertype */
+    if (ret_code != TPM_OK)
+    {
+        TPM_OS_DEBUG(TPM_MODZ2_HM_MOD,  "New tpid(0x%4x)", tpid);
+
+        /* Get free Etype Select */
+        ret_code = tpm_db_mod_etype_sel_free_get(&l_etype_sel);
+        if (ret_code != TPM_OK)
+        {
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Can't create additional Vlan Ethertype, tpid(0x%x)\n", tpid);
+            return(TPM_FAIL);
+        }
+        else
+        {
+            /* Create tpid in HW  */
+            for (port=TPM_ENUM_GMAC_0; port < TPM_MAX_NUM_GMACS; port++)
+            {
+                TPM_OS_DEBUG(TPM_MODZ2_HM_MOD,  " port(%d) sel(%d)\n", port, l_etype_sel);
+
+                if (port != TPM_ENUM_PMAC)
+                {
+                    mvNetaVlanEtySet(port, 0, l_etype_sel, tpid);
+                }
+                else
+                {
+                    for (txp=0; txp < TPM_MAX_NUM_TCONT; txp++)
+                    {
+                        mvNetaVlanEtySet(port, txp, l_etype_sel, tpid);
+                    }
+                }
+            }
+
+            /* Set tpid in db */
+            ret_code = tpm_db_mod_etype_sel_set(tpid, l_etype_sel);
+            if (ret_code != TPM_OK)
+            {
+                TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Can't create additional Vlan Ethertype, tpid(0x%x) l_etype_sel(%d)\n", tpid, l_etype_sel);
+                return(TPM_FAIL);
+            }
+        }
+    }
+
+    *eth_type_sel = l_etype_sel;
+
+    TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "etype_sel(%d)\n", l_etype_sel);
+    return(TPM_OK);
+}
+
+
+int32_t tpm_mod2_init(void)
+{
+    spin_lock_init(&tpmMod2JumpEntryLock);
+    spin_lock_init(&tpmMod2ChainEntryLock);
+    spin_lock_init(&tpmMod2PmtHwLock);
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_split_mod_create_l2_pmts()
+*
+* DESCRIPTION:     The function create split mod entries
+*                  - If the tpid has a match, it is returned.
+*                  - If there is no match, a new selector  is created in hardware and in DB.
+*                  - If there is no free selector,  an error is returned
+*
+* INPUTS:
+* port            - target gmac port
+* mod_data        - split mod entries info
+* init_flag       -flag indicate whether it invoked by init or not
+*
+* OUTPUTS:
+* None
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_mod2_split_mod_create_l2_pmts(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data, bool init_flag)
+{
+	uint32_t p_bits_nums;
+	uint32_t loop;
+	uint32_t mod_entry;
+	int32_t db_ret, tpm_ret;
+	uint32_t vlan_index;
+	tpm_vlan_key_t *vlan_out = NULL;
+	tpm_pkt_mod_t mod_data_tmp;
+
+	/*check param*/
+	if (mod_data == NULL) {
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid pointer\n");
+		return(TPM_FAIL);
+	}
+
+	if (TPM_SPLIT_MOD_DISABLED == tpm_db_split_mod_get_enable())
+	{
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "SPLIT_MOD_DISABLED\n");
+		return(TPM_RC_OK);
+	}
+
+	/* find vlan */
+	db_ret = tpm_db_mod2_split_mod_get_vlan_index(port, mod_data, &vlan_index);
+	if (TPM_DB_OK == db_ret)
+	{
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "this vlan already exists\n");
+		/* increase user number of this vlan */
+		tpm_db_mod2_split_mod_increase_vlan_user_num(port, mod_data);
+		return(TPM_OK);
+	}
+	
+	db_ret = tpm_db_mod2_split_mod_insert_vlan(port, mod_data);
+	if (TPM_DB_OK != db_ret)
+	{
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "insert_vlan failed\n");
+		return(ERR_GENERAL);
+	}
+
+	p_bits_nums = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
+
+	memcpy(&mod_data_tmp, mod_data, sizeof(tpm_pkt_mod_t));
+	/* VLANOP_EXT_TAG_MOD_INS mod insert VLAN p_bit*/
+	if (VLANOP_EXT_TAG_MOD_INS == mod_data->vlan_mod.vlan_op)
+		vlan_out = &mod_data_tmp.vlan_mod.vlan2_out;
+	else
+		vlan_out = &mod_data_tmp.vlan_mod.vlan1_out;
+
+	if (!init_flag) {
+		vlan_out->pbit_mask = 0;
+		/* add the first pmt to set p-bit AS-IS */
+		tpm_ret = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, port, TPM_VLAN_MOD, TPM_INT_SPLIT_MOD, &mod_data_tmp, &mod_entry);
+		if (TPM_OK != tpm_ret)
+		{
+			TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "set pbit init PMT failed: port %d\n", port);
+			return TPM_FAIL;
+		}
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "add the first pmt to set p-bit AS-IS, mod_entry: %d \n", mod_entry);
+	}
+
+	vlan_out->pbit_mask = 0xff;
+
+	/* build pmt entry for each pbit from 0 to 7 */
+	for (loop = 0; loop < p_bits_nums; loop++) {
+		vlan_out->pbit = loop;
+		tpm_ret = tpm_mod2_entry_set(TPM_MOD_OWNER_TPM, port, TPM_VLAN_MOD, TPM_INT_SPLIT_MOD, &mod_data_tmp, &mod_entry);
+		if (TPM_OK != tpm_ret) {
+			TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "set pbit init PMT failed: port %d, pbit %d \n", port, loop);
+			return TPM_FAIL;
+		}
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "add pmt for p-bit: %d, mod_entry: %d \n", loop, mod_entry);
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_mod2_split_mod_init(tpm_gmacs_enum_t port)
+{
+	int32_t	    tpm_ret;
+	tpm_pkt_mod_t mod_data;
+	
+	if (TPM_SPLIT_MOD_DISABLED == tpm_db_split_mod_get_enable())
+	{
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "SPLIT_MOD_DISABLED\n");
+		return(TPM_OK);
+	}
+
+	/* add default pmt from 1 to p_bits_nums */
+	memset(&mod_data, 0, sizeof(mod_data));
+	mod_data.vlan_mod.vlan_op = VLANOP_EXT_TAG_MOD;
+	mod_data.vlan_mod.vlan1_out.pbit_mask = 0xff;
+
+	tpm_ret = tpm_mod2_split_mod_create_l2_pmts(port, &mod_data, true);
+	if (TPM_RC_OK != tpm_ret)
+	{
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to add default pmt from 1 to p_bits_nums\n");
+		return(TPM_FAIL);
+	}
+
+	/* add default pmt from untag NOOP to p_bits_nums */
+	memset(&mod_data, 0, sizeof(mod_data));
+	mod_data.vlan_mod.vlan_op = VLANOP_NOOP;
+	//mod_data.vlan_mod.vlan1_out.pbit_mask = 0xff;
+
+	tpm_ret = tpm_mod2_split_mod_create_l2_pmts(port, &mod_data, true);
+	if (TPM_RC_OK != tpm_ret)
+	{
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to add default pmt from 1 to p_bits_nums\n");
+		return(TPM_FAIL);
+	}
+
+	return TPM_OK;
+}
+
+int32_t tpm_mod2_split_mod_try_pmt_entry_del(tpm_api_sections_t api_section, 
+                                  tpm_gmacs_enum_t     gmac_port,
+                                  uint32_t             mod_entry)
+{
+	uint32_t num_vlans;
+	uint32_t num_pbits;
+	uint32_t vlan_index;
+	uint32_t user_num = 0;
+	int32_t  tpm_ret;
+	uint32_t i = 0;
+
+	if (!mod_entry) {
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "mod_entry is zero, PMT do not need to be removed\n");
+		return(TPM_OK);
+	}
+
+	if (TPM_SPLIT_MOD_DISABLED == tpm_db_split_mod_get_enable()) {
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "SPLIT_MOD_DISABLED, PMT need to be removed\n");
+		return(TPM_FAIL);
+	}
+	
+	if (	(TPM_IPV4_ACL == api_section)
+		 && (mod_entry <= TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX)) {
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "IPv4 split mod, PMT do not need to be removed\n");
+		return(TPM_OK);
+	}
+	
+	if (TPM_L2_PRIM_ACL != api_section) {
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Not L2 ACL, PMT need to be removed\n");
+		return(TPM_FAIL);
+	}
+
+	if ((mod_entry % 16) > 8) {
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Not L2 split mod: %d, PMT need to be removed\n", mod_entry);
+		return(TPM_FAIL);
+	}
+
+	vlan_index = mod_entry / 16;
+	num_vlans = tpm_db_split_mod_get_num_vlans();
+	if (vlan_index > num_vlans) {
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "Not L2 split mod: %d, PMT need to be removed\n", mod_entry);
+		return(TPM_FAIL);
+	}
+
+	if (vlan_index <= 1) {
+		TPM_OS_DEBUG(TPM_MODZ2_HM_MOD, "mod entry: %d, PMT smaller than 32 is reserved, "
+			"can not be removed\n", mod_entry);
+		return(TPM_OK);
+	}
+
+	/* decrease user number of this vlan */
+	tpm_ret = tpm_db_mod2_split_mod_decrease_vlan_user_num(gmac_port, vlan_index, &user_num);
+	if (TPM_DB_OK != tpm_ret)
+	{
+		TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to decrease vlan user num, index: %d\n", vlan_index);
+		return(TPM_OK);
+	}
+
+	/* still other usr, do not remove */
+	if (user_num != 0)
+	{
+		TPM_OS_INFO(TPM_MODZ2_HM_MOD, "still other usr, do not remove, usr num: %d\n", user_num);
+		return(TPM_OK);
+	}
+	
+	/* remove all the PMT entry for this VLAN */
+	num_pbits = TPM_DB_SPLIT_MOD_P_BIT_NUM_MAX;
+	for(i = 0; i <= num_pbits; i++) {
+		tpm_ret = tpm_mod2_entry_del(TPM_MOD_OWNER_TPM, gmac_port, (vlan_index * 16 + i));
+		if (TPM_DB_OK != tpm_ret)
+		{
+			TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "failed to del split mod, index: %d\n", (vlan_index * 16 + i));
+			return(TPM_OK);
+		}
+	}
+    return TPM_OK;
+}
+
+
+/*******************************************************************************
+                          Modification table print functions
+*******************************************************************************/
+char *opCodeOperationStr[30] =
+{
+    "NOOP",
+    "ADD",
+    "CONF_VLAN",
+    "ADD_VLAN",
+    "CONF_DSA1",
+    "CONF_DSA2",
+    "ADD_DSA",
+    "DEL",
+    "REP2",
+    "REP_LSB",
+    "REP_MSB",
+    "REP_VLAN",
+    "DEC_TTL_LSB",
+    "DEC_TTL_MSB",
+    "ADD_CALC_LEN",
+    "REP_LEN",
+    "REP_IP_CHKSUM",
+    "REP_L4_CHKSUM",
+    "SKIP",
+    "JUMP",
+    "JUMP_SKIP2",
+    "JUMP_SUBR",
+    "PPPOE",
+    "STORE",
+    "ADD_IP_CHKSUM",
+    "RESERVED",
+    "RESERVED",
+    "RESERVED",
+    "RESERVED",
+    "RESERVED"
+};
+
+static void tpm_mod2_print_header (void)
+{
+    printk("==========================================================\n");
+    printk(" Index  OpCode    Operation      Data  Last  IPv4    L4   \n");
+    printk("                                            update update \n");
+    printk("==========================================================\n");
+}
+
+int32_t tpm_mod2_print_tmp_pattern (tpm_mod_pattern_data_t *pattern_data)
+{
+    uint32_t set_id, line_id;
+    tpm_pattern_entry_t *entry_p = NULL;
+    uint16_t pmt_entry;
+
+    if (NULL == pattern_data)
+    {
+        return TPM_FAIL;
+    }
+
+    tpm_mod2_print_header();
+
+    for (set_id = 0; set_id < TPM_MOD2_MAX_PATTERN_SETS; set_id++)
+    {
+        if (pattern_data->pattern_set[set_id].is_valid)
+        {
+            entry_p = &(pattern_data->pattern_set[set_id]);
+
+            if (set_id == 0)
+            {
+                pmt_entry = entry_p->index;
+            }
+            else
+            {
+                pmt_entry = tpm_db_mod2_convert_chain_to_pmt_entry(entry_p->chain_type, entry_p->index);
+            }
+
+            printk("[ set %d ] area_type %d, chain_type %d, chain_index %d (pmt_entry 0x%04x), line_num %d \r\n",
+                    set_id, entry_p->area_type, entry_p->chain_type, entry_p->index, pmt_entry, entry_p->line_num);
+            for (line_id = 0; line_id < TPM_MOD2_MAX_PATTERN_ENTRIES && line_id < entry_p->line_num; line_id++)
+            {
+                printk(" %03d      0x%2x  %15s  0x%4.4x  %1d     %1d      %1d\n",
+                       line_id,
+                       entry_p->line[line_id].opcode,
+                       opCodeOperationStr[entry_p->line[line_id].opcode],
+                       entry_p->line[line_id].data, entry_p->line[line_id].last,
+                       entry_p->line[line_id].updt_ipv4, entry_p->line[line_id].updt_tcp);
+            }
+        }
+    }
+    return TPM_OK;
+}
+
+int32_t tpm_mod2_print_rule (tpm_gmacs_enum_t   gmac_port,
+                             uint32_t           mod_entry)
+{
+    tpm_mod_rule_t mod_rule[TPM_MAX_MOD_RULE_NUM];
+    uint16_t       rule_num, rule_idx;
+
+    if (tpm_mod2_entry_get(gmac_port, mod_entry, &rule_num, mod_rule) != TPM_OK)
+    {
+        printk("Modification entry %d is not found\n", mod_entry);
+        return TPM_NOT_FOUND;
+    }
+
+    tpm_mod2_print_header();
+
+    for (rule_idx = 0; rule_idx < rule_num; rule_idx++)
+    {
+        printk(" %03d      0x%2x  %15s  0x%4.4x  %1d     %1d      %1d\n",
+               mod_rule[rule_idx].entry_id, mod_rule[rule_idx].entry_data.opcode,
+               opCodeOperationStr[mod_rule[rule_idx].entry_data.opcode],
+               mod_rule[rule_idx].entry_data.data, mod_rule[rule_idx].entry_data.last,
+               mod_rule[rule_idx].entry_data.updt_ipv4, mod_rule[rule_idx].entry_data.updt_tcp);
+    }
+
+
+    return TPM_OK;
+}
+
+int32_t tpm_mod2_print_jump_all (tpm_gmacs_enum_t   gmac_port)
+{
+    tpm_db_mod2_show_jump_pmt_entries(gmac_port);
+    return TPM_OK;
+}
+
+int32_t tpm_mod2_print_main_all (tpm_gmacs_enum_t   gmac_port)
+{
+    tpm_db_mod2_show_chain_pmt_entries(gmac_port, TPM_CHAIN_TYPE_NONE);
+    return TPM_OK;
+}
+
+int32_t tpm_mod2_print_config (tpm_gmacs_enum_t   gmac_port)
+{
+    uint32_t chain_type;
+
+    tpm_db_mod2_show_jump_cfg_data();
+    for (chain_type = TPM_CHAIN_TYPE_MH; chain_type < TPM_CHAIN_TYPE_MAX; chain_type++)
+    {
+        tpm_db_mod2_show_chain_cfg_data(chain_type);
+    }
+
+    return TPM_OK;
+}
+
+/*tpm check*/
+/*******************************************************************************
+* tpm_mod2_main_chain_index_get - Get main chain index from HW or DB
+*
+* INPUT:
+*       gmac_port - target gmac port
+*	jump_idx - jump entry index
+*	from - get main chain index from DB or HW
+*
+* OUTPUT:
+*	main_entry - main chain index
+*
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t	tpm_mod2_main_chain_index_get(tpm_gmacs_enum_t gmac_port, uint16_t jump_idx,
+				      uint16_t *main_entry, tpm_self_check_enable_t from)
+{
+    int err;
+    tpm_mod2_entry_t db_jump_pattern;
+    MV_NETA_PMT pEntry;
+
+    /*params check*/
+    if (main_entry == NULL) {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "NULL pointer\n");
+        return TPM_FAIL;
+    }
+    if (from != TPM_CHECK_MAIN_CHAIN_IDX_DB && from != TPM_CHECK_MAIN_CHAIN_IDX_HW) {
+        TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Invalid input\n");
+        return TPM_FAIL;
+    }
+
+    if (from == TPM_CHECK_MAIN_CHAIN_IDX_DB) {
+        /*get main chain index from DB*/
+        spin_lock_bh(&tpmMod2JumpEntryLock);
+        if (tpm_db_mod2_get_jump_entry_pattern_data(gmac_port, jump_idx, &db_jump_pattern) != TPM_OK) {
+            spin_unlock_bh(&tpmMod2JumpEntryLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get db jump entry pattern_data\n");
+            return TPM_FAIL;
+        }
+        spin_unlock_bh(&tpmMod2JumpEntryLock);
+        *main_entry = db_jump_pattern.data;
+    } else if (from == TPM_CHECK_MAIN_CHAIN_IDX_HW) {
+        /*get main chain index from HW*/
+        spin_lock_bh(&tpmMod2PmtHwLock);
+        err = mvNetaPmtRead(gmac_port, jump_idx, &pEntry);
+        if (err) {
+            spin_unlock_bh(&tpmMod2PmtHwLock);
+            TPM_OS_ERROR(TPM_MODZ2_HM_MOD, "Failed to get hw jump data\n");
+            return TPM_FAIL;
+        }
+        spin_unlock_bh(&tpmMod2PmtHwLock);
+        *main_entry = pEntry.word & 0xFFFF;
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_neta_pmt_get - read HW PMT entry from target port
+*
+* INPUT:
+*       gmac_port - target gmac port
+*	idx - entry index
+*
+* OUTPUT:
+*	pEntry - pmt entry wanted
+*
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_mod2_neta_pmt_get(tpm_gmacs_enum_t gmac_port, int idx, MV_NETA_PMT *pEntry)
+{
+    spin_lock_bh(&tpmMod2PmtHwLock);
+    if (mvNetaPmtRead(gmac_port, idx, pEntry)) {
+        spin_unlock_bh(&tpmMod2PmtHwLock);
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2PmtHwLock);
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_db_jump_pattern_data_get - read jump entry pattern data from tpm db
+*
+* INPUT:
+*       gmac_port - target gmac port
+*	entry_id - jump entry index
+*
+* OUTPUT:
+*	pattern - pattern data
+*
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_mod2_db_jump_pattern_data_get(tpm_gmacs_enum_t gmac_port, uint16_t entry_id, tpm_mod2_entry_t *pattern)
+{
+    spin_lock_bh(&tpmMod2JumpEntryLock);
+    if (tpm_db_mod2_get_jump_entry_pattern_data(gmac_port, entry_id, pattern) != TPM_OK) {
+        spin_unlock_bh(&tpmMod2JumpEntryLock);
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2JumpEntryLock);
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_mod2_db_jump_pattern_data_get - read chain entry pattern data from tpm db
+*
+* INPUT:
+*       gmac_port - target gmac port
+*	chain_type - chain type
+*	chain_id - chain index
+*	pattern_id - pattern index
+*
+* OUTPUT:
+*	pattern - pattern data
+*
+*RETURN:
+*
+*COMMENTS:
+*
+*******************************************************************************/
+int32_t tpm_mod2_db_chain_pattern_data_get(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+					   uint16_t chain_id, uint16_t pattern_id, tpm_mod2_entry_t *pattern)
+{
+    spin_lock_bh(&tpmMod2ChainEntryLock);
+    if (tpm_db_mod2_get_chain_entry_pattern_data(gmac_port, chain_type, chain_id, pattern_id, pattern)) {
+        spin_unlock_bh(&tpmMod2ChainEntryLock);
+        return TPM_FAIL;
+    }
+    spin_unlock_bh(&tpmMod2ChainEntryLock);
+
+    return TPM_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.h
new file mode 100755
index 0000000..60af2b1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_modz2_mgr.h
@@ -0,0 +1,318 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#ifndef __TPM_MODZ2_H__
+#define __TPM_MODZ2_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "tpm_common.h"
+#include "tpm_db.h"
+#include "tpm_self_check.h"
+
+/*************************************************************/
+/*               TEMP. DEFINITIONS                           */
+/*************************************************************/
+
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+#define TPM_MOD2_OPCODE_NOOP                0x0
+#define TPM_MOD2_OPCODE_ADD                 0x1
+#define TPM_MOD2_OPCODE_CONF_VLAN           0x2
+#define TPM_MOD2_OPCODE_ADD_VLAN            0x3
+#define TPM_MOD2_OPCODE_CONF_DSA1           0x4
+#define TPM_MOD2_OPCODE_CONF_DSA2           0x5
+#define TPM_MOD2_OPCODE_ADD_DSA             0x6
+#define TPM_MOD2_OPCODE_DEL                 0x7
+#define TPM_MOD2_OPCODE_REP2                0x8
+#define TPM_MOD2_OPCODE_REP_LSB             0x9
+#define TPM_MOD2_OPCODE_REP_MSB             0xA
+#define TPM_MOD2_OPCODE_REP_VLAN            0xB
+#define TPM_MOD2_OPCODE_DEC_TTL_LSB         0xC
+#define TPM_MOD2_OPCODE_DEC_TTL_MSB         0xD
+#define TPM_MOD2_OPCODE_ADD_CALC_LEN        0xE
+#define TPM_MOD2_OPCODE_REP_LEN             0xF
+#define TPM_MOD2_OPCODE_REP_IP_CHKSUM       0x10
+#define TPM_MOD2_OPCODE_ADD_IP_CHKSUM       0x18
+#define TPM_MOD2_OPCODE_REP_L4_CHKSUM       0x11
+#define TPM_MOD2_OPCODE_SKIP                0x12
+#define TPM_MOD2_OPCODE_JUMP                0x13
+#define TPM_MOD2_OPCODE_JUMP_SKIP2          0x14
+#define TPM_MOD2_OPCODE_JUMP_SUBR           0x15
+#define TPM_MOD2_OPCODE_PPPOE               0x16
+#define TPM_MOD2_OPCODE_STORE               0x17
+
+
+#define TPM_MOD2_DEFAULT_ETY                (0x8100)
+#define TPM_MOD2_DEFAULT_PPPOE_ETY          (0x8864)
+#define TPM_MOD2_DEFAULT_PPPOE_DATA         (0x1100)
+#define TPM_MOD2_DEFAULT_PPPOE_LEN          (0x7000)
+#define TPM_MOD2_DEFAULT_PPPOE_PROTO        (0x0021)
+
+/* Self-defined Ethernet type for CPU loopback frames*/
+#define TPM_MOD2_CPU_LOOPBACK_ETY           (0xAABB)
+
+/* Max number of modification entries per command */
+#define TPM_MOD2_MAX_CMD_ENTRIES            (5)
+
+#define TPM_MOD2_MH_CMD_ENTRIES             (1)
+#define TPM_MOD2_MAC_CMD_ENTRIES            (3)
+#define TPM_MOD2_IP_CMD_ENTRIES             (2)
+#define TPM_MOD2_PPPOE_DEL_CMD_ENTRIES      (2)
+#define TPM_MOD2_PPPOE_ADD_CMD_ENTRIES      (1)
+#define TPM_MOD2_IPV6_PPPOE_ADD_CMD_ENTRIES (5)
+
+#define TPM_MOD2_MAX_VLAN_ENTRIES           (2)
+#define TPM_MOD2_VLAN_ADD_ENTRIES           (2)
+#define TPM_MOD2_VLAN_DEL_ENTRIES           (1)
+#define TPM_MOD2_VLAN_MOD_ENTRIES           (2)
+#define TPM_MOD2_VLAN_SKIP_ENTRIES          (1)
+
+#define TPM_MOD2_NULL_PATTERN_IDX           (0xFF)
+
+#define TPM_MOD2_NEW_TPID                   (0xFFFF)
+#define TPM_MOD2_NEW_VID                    (0xFFFF)
+#define TPM_MOD2_NEW_CFI                    (0xFF)
+#define TPM_MOD2_NEW_PBIT                   (0xFF)
+
+#define TPM_MOD2_ORIGINAL_VID               (0x0)
+#define TPM_MOD2_ORIGINAL_CFI               (0x0)
+#define TPM_MOD2_ORIGINAL_PBIT              (0x0)
+
+#define TPM_MOD2_ENTRY_VID_OFFS             (0)
+#define TPM_MOD2_ENTRY_VID_BITS             (12)
+#define TPM_MOD2_ENTRY_VID_MASK             (((1 << TPM_MOD2_ENTRY_VID_BITS) - 1) << TPM_MOD2_ENTRY_VID_OFFS)
+
+#define TPM_MOD2_ENTRY_CFI_OFFS             (12)
+#define TPM_MOD2_ENTRY_CFI_BITS             (1)
+#define TPM_MOD2_ENTRY_CFI_MASK             (1 << TPM_MOD2_ENTRY_CFI_OFFS)
+
+#define TPM_MOD2_ENTRY_PBIT_OFFS            (13)
+#define TPM_MOD2_ENTRY_PBIT_BITS            (3)
+#define TPM_MOD2_ENTRY_PBIT_MASK            (((1 << TPM_MOD2_ENTRY_PBIT_BITS) - 1) << TPM_MOD2_ENTRY_PBIT_OFFS)
+
+#define TPM_MOD2_ENTRY_MOD_DATA_MASK        (0x0000FFFF)
+
+#define TPM_MOD2_TP_FROM_REG_0              (0x0000)
+#define TPM_MOD2_TP_FROM_REG_1              (0x0001)
+#define TPM_MOD2_TP_FROM_REG_2              (0x0002)
+#define TPM_MOD2_TP_FROM_REG_3              (0x0003)
+#define TPM_MOD2_TP_FROM_VLAN_1             (0x0004)
+#define TPM_MOD2_TP_FROM_VLAN_2             (0x0005)
+
+#define TPM_MOD2_VID_FROM_VLAN_1            (0x0000)
+#define TPM_MOD2_VID_FROM_VLAN_2            (0x0010)
+#define TPM_MOD2_VID_NEW                    (0x0020)
+
+#define TPM_MOD2_CFI_FROM_VLAN_1            (0x0000)
+#define TPM_MOD2_CFI_FROM_VLAN_2            (0x0040)
+#define TPM_MOD2_CFI_NEW                    (0x0080)
+
+#define TPM_MOD2_PBIT_FROM_VLAN_1           (0x0000)
+#define TPM_MOD2_PBIT_FROM_VLAN_2           (0x0100)
+#define TPM_MOD2_PBIT_NEW                   (0x0200)
+
+
+#define TPM_MOD2_INVALID_CHAIN_ID           (0xFFFF)
+
+#define TPM_MOD2_IPV4_MOD_MASK              (TPM_DSCP_SET | TPM_TTL_DEC | TPM_IPV4_UPDATE | TPM_IPV4_SRC_SET | TPM_IPV4_DST_SET)
+#define TPM_MOD2_IPV6_MOD_MASK              (TPM_IPV6_UPDATE | TPM_HOPLIM_DEC | TPM_IPV6_SRC_SET | TPM_IPV6_DST_SET)
+#define TPM_MOD2_L4_MOD_MASK                (TPM_L4_SRC_SET | TPM_L4_DST_SET)
+
+#define TPM_MOD2_DONT_CARE_INT_BM           (0xFFFFFFFF)
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+
+
+/*************************************************************/
+/*               STRUCTURES                                  */
+/*************************************************************/
+
+typedef struct
+{
+    tpm_area_type_t     area_type;
+    tpm_chain_type_t    chain_type;
+    uint16_t            index;
+    uint8_t             is_valid;
+    uint8_t             line_num;
+    tpm_mod2_entry_t    line[TPM_MOD2_MAX_PATTERN_ENTRIES];
+} tpm_pattern_entry_t;
+
+typedef struct
+{
+    tpm_chain_type_t    main_chain_type;
+    uint16_t            main_chain_id;
+    tpm_pattern_entry_t pattern_set[TPM_MOD2_MAX_PATTERN_SETS];
+} tpm_mod_pattern_data_t;
+
+typedef int32_t  (*pattern_f)(tpm_gmacs_enum_t      gmac_port,
+                              uint32_t                bm,
+                              uint16_t                cmd_idx,
+                              uint8_t                *skip,
+                              tpm_pkt_mod_t          *mod_data,
+                              tpm_mod_pattern_data_t *pattern_data,
+                              tpm_self_check_enable_t is_tpm_check);
+
+typedef struct
+{
+    uint8_t             skip_before;
+    uint8_t             skip_no_parse;
+    uint32_t            mask;
+    pattern_f           process_pattern;
+    tpm_mod2_entry_t    entry[TPM_MOD2_MAX_CMD_ENTRIES];
+
+} tpm_mod_flag_bm_entry_t;
+
+typedef struct
+{
+    tpm_mod2_entry_t    vlan1[TPM_MOD2_MAX_VLAN_ENTRIES];
+    tpm_mod2_entry_t    vlan2[TPM_MOD2_MAX_VLAN_ENTRIES];
+} tpm_mod_vlan_entry_t;
+
+typedef struct
+{
+    tpm_chain_type_t chain_type;
+    tpm_pkt_mod_bm_t mod_bm;
+	tpm_pkt_mod_int_bm_t int_mod_bm;
+} tpm_chain_map_t;
+
+/*************************************************************/
+/*               PROTOTYPES                                  */
+/*************************************************************/
+int32_t    tpm_mod2_entry_set   (tpm_mod_owner_t    owner,
+                                 tpm_gmacs_enum_t   gmac_port,
+                                 tpm_pkt_mod_bm_t   mod_bm,
+                                 tpm_pkt_mod_int_bm_t int_mod_bm,
+                                 tpm_pkt_mod_t      *mod_data,
+                                 uint32_t           *mod_entry);
+
+int32_t    tpm_mod2_entry_get   (tpm_gmacs_enum_t   gmac_port,
+                                        uint32_t           mod_entry,
+                                        uint16_t           *entries_num,
+                                        tpm_mod_rule_t     *pnc_entries);
+
+int32_t    tpm_mod2_entry_del   (tpm_mod_owner_t    owner,
+                                 tpm_gmacs_enum_t   gmac_port,
+                                 uint32_t           mod_entry);
+
+int32_t    tpm_mod2_hw_inv_entry(tpm_gmacs_enum_t    gmac_port,
+                                 uint16_t            mod_entry);
+
+int32_t    tpm_mod2_mac_inv (tpm_gmacs_enum_t   gmac_port);
+
+int32_t    tpm_mod2_registers_init (tpm_gmacs_enum_t   gmac_port, uint16_t txp);
+
+int32_t    tpm_mod2_tpid_get(uint32_t tpid,
+                             uint32_t *eth_type_sel);
+
+int32_t    tpm_mod2_print_tmp_pattern (tpm_mod_pattern_data_t *pattern_data);
+
+int32_t    tpm_mod2_print_rule (tpm_gmacs_enum_t   gmac_port,
+                                uint32_t           mod_entry);
+
+int32_t    tpm_mod2_print_jump_all (tpm_gmacs_enum_t   gmac_port);
+
+int32_t    tpm_mod2_print_main_all (tpm_gmacs_enum_t   gmac_port);
+
+int32_t    tpm_mod2_print_config (tpm_gmacs_enum_t   gmac_port);
+
+int32_t    tpm_mod2_init(void);
+int32_t tpm_mod2_split_mod_init(tpm_gmacs_enum_t port);
+int32_t tpm_mod2_split_mod_create_l2_pmts(tpm_gmacs_enum_t port, tpm_pkt_mod_t *mod_data, bool init_flag);
+int32_t tpm_mod2_split_mod_try_pmt_entry_del(tpm_api_sections_t api_section, 
+                                  tpm_gmacs_enum_t     gmac_port,
+                                  uint32_t             mod_entry);
+
+int32_t    tpm_mod2_fill_in_pattern   (tpm_gmacs_enum_t     gmac_port,
+                                       tpm_pkt_mod_bm_t        mod_bm,
+                                       tpm_pkt_mod_int_bm_t    int_mod_bm,
+                                       tpm_pkt_mod_t          *mod_data,
+                                       uint32_t               *mod_entry,
+                                       tpm_mod_pattern_data_t *pattern_data,
+                                       tpm_self_check_enable_t is_tpm_check);
+tpm_chain_type_t tpm_mod2_parse_chain_type(tpm_pkt_mod_bm_t mod_bm, tpm_pkt_mod_int_bm_t int_mod_bm);
+
+/*for TPM self check*/
+int32_t tpm_mod2_main_chain_index_get(tpm_gmacs_enum_t gmac_port,
+                                      uint16_t jump_idx,
+                                      uint16_t *main_entry,
+                                      tpm_self_check_enable_t from);
+int32_t tpm_mod2_neta_pmt_get(tpm_gmacs_enum_t gmac_port, int idx, MV_NETA_PMT *pEntry);
+int32_t tpm_mod2_db_jump_pattern_data_get(tpm_gmacs_enum_t gmac_port, uint16_t entry_id, tpm_mod2_entry_t *pattern);
+int32_t tpm_mod2_db_chain_pattern_data_get(tpm_gmacs_enum_t gmac_port, tpm_chain_type_t chain_type,
+					   uint16_t chain_id,
+					   uint16_t pattern_id,
+					   tpm_mod2_entry_t *pattern);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TPM_MODZ2_H__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_pnc_mgr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_pnc_mgr.c
new file mode 100755
index 0000000..555a39a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_pnc_mgr.c
@@ -0,0 +1,709 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+#define TPM_PNC_ERR_ON_OOR(cond) if (cond){TPM_OS_ERROR(TPM_PNC_HM_MOD, "%s(%d): out of range\n",__FUNCTION__,__LINE__); return TPM_FAIL;}
+#define TPM_PNC_ERR_ON_OOM(cond) if (cond){TPM_OS_ERROR(TPM_PNC_HM_MOD, "%s(%d): out of memory\n",__FUNCTION__,__LINE__);return TPM_FAIL;}
+#define DWORD_LEN       32
+
+
+/* Global  Variables */
+spinlock_t tpmPncLock;
+
+
+
+//static    unsigned long     flags;
+//static    unsigned long     r_jiffies, t_jiffies;
+
+
+/*******************************************************************************
+* tpm_pnc_fill_in_entry()
+*
+* DESCRIPTION:  This function moves HW PnC entry in the internal format
+*
+* INPUTS:
+*           tcam_entry  - HW PnC entry
+*
+* OUTPUTS:
+*           pnc_entry   - PnC entry
+*
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+void tpm_pnc_print_sw_entry (tpm_pnc_all_t   *pnc_entry)
+{
+    int     i;
+
+    printk("*****************************************************************************************\n");
+    printk("TCAM:  LU  Port Add info    Packet\n");
+    printk("=========================================================================================\n");
+    printk("       %2.2d   %2.2d   %2.2x         ",
+           pnc_entry->tcam_entry.lu_id,
+           pnc_entry->tcam_entry.port_ids,
+           pnc_entry->tcam_entry.add_info_data);
+
+    for (i=0; i < TPM_TCAM_PKT_WIDTH; i++) {
+        printk("%2.2x", pnc_entry->tcam_entry.pkt_data.pkt_byte[i]);
+    }
+    printk("\n                 %2.2x         ", pnc_entry->tcam_entry.add_info_mask);
+    for (i=0; i < TPM_TCAM_PKT_WIDTH; i++) {
+        printk("%2.2x", pnc_entry->tcam_entry.pkt_mask.pkt_byte[i]);
+    }
+
+    printk("\n");
+    printk("================================================================================\n");
+    printk("SRAM:  NLU  Add info  LU Done  NLU idx   Q      Shift(val)   RI         FL      \n");
+    printk("================================================================================\n");
+    printk("       %2.2d      %2.2x        %1.1x        %2.2x     %4.4x    %3.3x(%3.3x)    %2.2x%4.4x     %8.8x\n",
+           pnc_entry->sram_entry.next_lu_id,
+           pnc_entry->sram_entry.add_info_data,
+           pnc_entry->sram_entry.lookup_done,
+           pnc_entry->sram_entry.next_lu_off_reg,
+           pnc_entry->sram_entry.pnc_queue,
+           pnc_entry->sram_entry.shift_updt_reg,
+           pnc_entry->sram_entry.shift_updt_val,
+           pnc_entry->sram_entry.res_info_23_16_data,
+           pnc_entry->sram_entry.res_info_15_0_data,
+           pnc_entry->sram_entry.flowid_val);
+    printk("               %2.2x                                            %2.2x%4.4x     %8.8x\n",
+           pnc_entry->sram_entry.add_info_mask,
+           pnc_entry->sram_entry.res_info_23_16_mask,
+           pnc_entry->sram_entry.res_info_15_0_mask,
+           pnc_entry->sram_entry.flowid_updt_mask);
+    printk("*****************************************************************************************\n");
+}
+
+/*******************************************************************************
+* tpm_pnc_fill_in_entry()
+*
+* DESCRIPTION:  This function moves HW PnC entry in the internal format
+*
+* INPUTS:
+*           tcam_entry  - HW PnC entry
+*
+* OUTPUTS:
+*           pnc_entry   - PnC entry
+*
+* RETURNS:
+*           None
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+void tpm_pnc_fill_in_entry(struct tcam_entry  *tcamEntry, tpm_pnc_all_t *pnc_entry)
+{
+    int         i, word, shift;
+    uint32_t    val, mask;
+
+    /* Fill in TCAM data */
+    pnc_entry->tcam_entry.lu_id         = (tcamEntry->data.u.word[LU_WORD]   >> LU_OFFS) & LU_MASK;
+    pnc_entry->tcam_entry.port_ids      = (tcamEntry->data.u.word[PORT_WORD] >> PORT_OFFS) & PORT_MASK;
+    pnc_entry->tcam_entry.add_info_data = (tcamEntry->data.u.word[AI_WORD]   >> AI_OFFS) & AI_MASK;
+    pnc_entry->tcam_entry.add_info_mask = (tcamEntry->mask.u.word[AI_WORD]   >> AI_OFFS) & AI_MASK;
+
+    for (i = 0; i < TPM_TCAM_PKT_WIDTH; i++)
+    {
+        pnc_entry->tcam_entry.pkt_data.pkt_byte[i] = tcamEntry->data.u.byte[i];
+        pnc_entry->tcam_entry.pkt_mask.pkt_byte[i] = tcamEntry->mask.u.byte[i];
+    }
+
+    /* Fill in SRAM data */
+    word                                   = LU_ID_OFFS / DWORD_LEN;
+    shift                                  = LU_ID_OFFS % DWORD_LEN;
+    pnc_entry->sram_entry.next_lu_id       = (tcamEntry->sram.word[word] >> shift) & LU_MASK;
+
+    word                                   = LU_DONE_OFFS / DWORD_LEN;
+    shift                                  = LU_DONE_OFFS % DWORD_LEN;
+    pnc_entry->sram_entry.lookup_done      = (tcamEntry->sram.word[word] >> shift) & 0x1;
+
+    word                                   = RXQ_QUEUE_OFFS / DWORD_LEN;
+    shift                                  = RXQ_QUEUE_OFFS % DWORD_LEN;
+    pnc_entry->sram_entry.pnc_queue        = (tcamEntry->sram.word[word] >> shift) & RXQ_MASK;
+
+    word                                   = NEXT_LU_SHIFT_OFFS / DWORD_LEN;
+    shift                                  = NEXT_LU_SHIFT_OFFS % DWORD_LEN;
+    pnc_entry->sram_entry.next_lu_off_reg  = (tcamEntry->sram.word[word] >> shift) & SHIFT_IDX_MASK;
+
+    word                                   = SHIFT_IDX_OFFS / DWORD_LEN;
+    shift                                  = SHIFT_IDX_OFFS % DWORD_LEN;
+    pnc_entry->sram_entry.shift_updt_reg   = (tcamEntry->sram.word[word] >> shift) & SHIFT_IDX_MASK;
+
+    word                                   = SHIFT_VAL_OFFS/DWORD_LEN;
+    shift                                  = SHIFT_VAL_OFFS%DWORD_LEN;
+    pnc_entry->sram_entry.shift_updt_val   = (tcamEntry->sram.word[word] >> shift) & SHIFT_VAL_MASK;
+
+    word                                   = AI_VALUE_OFFS/DWORD_LEN;
+    shift                                  = AI_VALUE_OFFS%DWORD_LEN;
+    pnc_entry->sram_entry.add_info_data    = (tcamEntry->sram.word[word] >> shift) & AI_MASK;
+
+    word                                   = AI_MASK_OFFS/DWORD_LEN;
+    shift                                  = AI_MASK_OFFS%DWORD_LEN;
+    pnc_entry->sram_entry.add_info_mask    = (tcamEntry->sram.word[word] >> shift) & AI_MASK;
+
+    pnc_entry->sram_entry.flowid_updt_mask = 0;
+
+    if (tcamEntry->sram.word[1] & FLOW_ID_LSW_MASK)
+        pnc_entry->sram_entry.flowid_updt_mask |= FLOW_ID_LSW_MASK;
+
+    if (tcamEntry->sram.word[1] & FLOW_ID_MSW_MASK)
+        pnc_entry->sram_entry.flowid_updt_mask |= FLOW_ID_MSW_MASK;
+
+    pnc_entry->sram_entry.flowid_val = tcamEntry->sram.word[0];
+
+    word  = RI_VALUE_OFFS/DWORD_LEN;
+    shift = RI_VALUE_OFFS%DWORD_LEN;
+    val   = (tcamEntry->sram.word[word] >> shift) & RI_MASK;
+
+    /* RI mask : word 1 - 6 bits (25 - 31)
+                 word 2 - 18 bits (0 - 17) */
+    word  = RI_MASK_OFFS/DWORD_LEN;
+    shift = RI_MASK_OFFS%DWORD_LEN;
+    mask  = (tcamEntry->sram.word[word] >> shift) & RI_MASK;
+    word++;
+    mask |= (tcamEntry->sram.word[word] & 0x3FFFF) << 6;
+
+    pnc_entry->sram_entry.res_info_15_0_data  =  val  & RES_INFO_BITS_16_MASK;
+    pnc_entry->sram_entry.res_info_15_0_mask  =  mask & RES_INFO_BITS_16_MASK;
+    pnc_entry->sram_entry.res_info_23_16_data = (val  & RES_INFO_BITS_8_MASK) >> MAX_RES_INFO_BITS_16;
+    pnc_entry->sram_entry.res_info_23_16_mask = (mask & RES_INFO_BITS_8_MASK) >> MAX_RES_INFO_BITS_16;
+
+}
+
+
+/*******************************************************************************
+* tpm_pnc_hw_entry_inv()
+*
+* DESCRIPTION: This API invalidates a TCAM entry in a range.
+*              It does not change any other entry in the TCAM.
+*
+* INPUTS:   entry   - entry to be invalidated
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           TPM_OK or TPK_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+static inline void tpm_pnc_hw_entry_inv(uint32_t entry)
+{
+    unsigned long     flags;
+
+    /* Lock the PnC */
+    spin_lock_irqsave(&tpmPncLock, flags);
+
+    /* Invalidate entry */
+    tcam_hw_inv(entry);
+
+    /* Unlock PnC */
+    spin_unlock_irqrestore(&tpmPncLock, flags);
+
+    return;
+}
+
+static inline void tpm_pnc_hw_entry_read(struct tcam_entry *te, uint32_t entry)
+{
+    unsigned long     flags;
+
+    /* Lock the PnC */
+    spin_lock_irqsave(&tpmPncLock, flags);
+
+    /* Read entry */
+    tcam_hw_read(te, entry);
+
+    /* Unlock PnC */
+    spin_unlock_irqrestore(&tpmPncLock, flags);
+
+    return;
+}
+
+
+static inline void tpm_pnc_hw_entry_write(struct tcam_entry *te, uint32_t entry)
+{
+    unsigned long     flags;
+
+    /* Lock the PnC */
+    spin_lock_irqsave(&tpmPncLock, flags);
+
+    /* Write entry */
+    tcam_hw_write(te, entry);
+
+    /* Unlock PnC */
+    spin_unlock_irqrestore(&tpmPncLock, flags);
+
+    return;
+}
+
+/*******************************************************************************
+* tpm_pnc_set()
+*
+* DESCRIPTION:  This API provides a generic interface to set a complete PnC
+*               entry (TCAM + SRAM), or just update the SRAM.
+*               If (TCAM and SRAM) are updated, PnC entry is first invalidated
+*               and only then configured.
+*
+* INPUTS:
+*           entry       - entry to be set/updated
+*           sram_update - 0 - set a complete PnC entry
+*                         1 - just SRAM update
+*           pnc_entry   - pointer to the set/updated PnC entry
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t    tpm_pnc_set  (uint32_t      entry,
+                         uint32_t      sram_update,
+                         tpm_pnc_all_t *pnc_entry)
+{
+    struct tcam_entry tcamEntry;
+    uint32_t          sram_res_info_data = 0;
+    int               indx;
+    uint32_t          cfg_pnc_parse_flag = 0;
+
+
+	cfg_pnc_parse_flag = mv_eth_ctrl_pnc_get();
+
+    if (cfg_pnc_parse_flag == 1) {
+        TPM_OS_DEBUG(TPM_PNC_HM_MOD, " TPM is NOT configuring the PNC - MV driver is responsible \n");
+        return (TPM_OK);
+    }
+    TPM_OS_DEBUG( TPM_PNC_HM_MOD, "entry(%d) sram_update(%d)\n",entry, sram_update);
+    TPM_PNC_ERR_ON_OOR(entry >= TPM_PNC_SIZE);
+    TPM_PNC_ERR_ON_OOM(pnc_entry == NULL);
+
+    /* sram_update is equal to 0, therefore the PnC entry is set */
+    if (!sram_update)
+    {
+        /* Update TCAM */
+
+        /* Invalidate PnC entry */
+        tpm_pnc_hw_entry_inv(entry);
+
+        /* Clear SW TCAM entry */
+        tcam_sw_clear(&tcamEntry);
+
+        /* Set lookup */
+        if (pnc_entry->tcam_entry.lu_id != TPM_PNC_ANY_LUID)
+        {
+            tcam_sw_set_lookup(&tcamEntry, pnc_entry->tcam_entry.lu_id);
+        }
+
+        /* Set port */
+        tcam_sw_set_port(&tcamEntry, 0, PORT_MASK &(~(pnc_entry->tcam_entry.port_ids)));
+
+        /* Set TCAM add info */
+        tcam_sw_set_ainfo(&tcamEntry, MASK_AI(pnc_entry->tcam_entry.add_info_data),
+                                      MASK_AI(pnc_entry->tcam_entry.add_info_mask));
+
+        /* Set packet data */
+        for (indx = 0; indx < TPM_TCAM_PKT_WIDTH; indx++)
+        {
+            tcam_sw_set_byte(&tcamEntry, indx, pnc_entry->tcam_entry.pkt_data.pkt_byte[indx]);
+            tcam_sw_set_mask(&tcamEntry, indx, pnc_entry->tcam_entry.pkt_mask.pkt_byte[indx]);
+        }
+    }
+
+    /* sram_update is not equal to 0, therefore SRAM of the PnC entry is updated, read PnC entry */
+    else
+    {
+        /* Clear SW TCAM entry */
+        tcam_sw_clear(&tcamEntry);
+
+        /* Read the entry from HW */
+        tpm_pnc_hw_entry_read(&tcamEntry, entry);
+
+		/* Clear old sram entry */
+		sram_sw_clear(&tcamEntry.sram);
+    }
+
+    /* Update SRAM */
+
+    /* Set next lookup ID */
+    sram_sw_set_next_lookup(&tcamEntry, pnc_entry->sram_entry.next_lu_id);
+
+    /* Set add info update */
+    sram_sw_set_ainfo(&tcamEntry, MASK_AI(pnc_entry->sram_entry.add_info_data), MASK_AI(pnc_entry->sram_entry.add_info_mask));
+
+    /* Set lookup done */
+    sram_sw_set_lookup_done(&tcamEntry, pnc_entry->sram_entry.lookup_done);
+
+    /* Set Next lookup offset index */
+    sram_sw_set_next_lookup_shift(&tcamEntry, pnc_entry->sram_entry.next_lu_off_reg);
+
+    /* Set queue */
+    if (pnc_entry->sram_entry.pnc_queue != 0xFFFF)
+    {
+        sram_sw_set_rxq(&tcamEntry, pnc_entry->sram_entry.pnc_queue, 1);
+    }
+
+    /* Set shift update */
+    sram_sw_set_shift_update(&tcamEntry, pnc_entry->sram_entry.shift_updt_reg,
+                                         pnc_entry->sram_entry.shift_updt_val);
+
+    /* Set results info (RI) */
+    sram_res_info_data = ((pnc_entry->sram_entry.res_info_23_16_data << 16) |
+                           pnc_entry->sram_entry.res_info_15_0_data);
+    sram_sw_set_rinfo(&tcamEntry, sram_res_info_data, sram_res_info_data);
+    /* if need to set marvell header, update them all */
+    if (sram_res_info_data & TPM_MH_RI_BIT14 ||
+        sram_res_info_data & TPM_MH_RI_BIT15 ||
+        sram_res_info_data & TPM_MH_RI_BIT16 ||
+        sram_res_info_data & TPM_MH_RI_BIT17)
+        tcamEntry.sram.word[RI_MASK_OFFS / DWORD_LEN] |= (1 << ((TPM_PNC_RI_MH_BIT_14 + RI_MASK_OFFS) % DWORD_LEN)) |
+                                                         (1 << ((TPM_PNC_RI_MH_BIT_15 + RI_MASK_OFFS) % DWORD_LEN)) |
+                                                         (1 << ((TPM_PNC_RI_MH_BIT_16 + RI_MASK_OFFS) % DWORD_LEN)) |
+                                                         (1 << ((TPM_PNC_RI_MH_BIT_17 + RI_MASK_OFFS) % DWORD_LEN));
+
+    /* Set flow id */
+    sram_sw_set_flowid(&tcamEntry, pnc_entry->sram_entry.flowid_val, pnc_entry->sram_entry.flowid_updt_mask);
+
+    /* Write the current entry to HW */
+    tpm_pnc_hw_entry_write(&tcamEntry, entry);
+
+    return TPM_OK;
+}
+
+
+
+
+/*******************************************************************************
+* tpm_pnc_entry_inv()
+*
+* DESCRIPTION: This API invalidates a TCAM entry in a range.
+*              It does not change any other entry in the TCAM.
+*
+* INPUTS:   entry   - entry to be invalidated
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           TPM_OK or TPK_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_pnc_entry_inv(uint32_t entry)
+{
+    uint32_t          cfg_pnc_parse_flag = 0;
+
+	cfg_pnc_parse_flag = mv_eth_ctrl_pnc_get();
+
+    if (cfg_pnc_parse_flag == 1) {
+        TPM_OS_DEBUG(TPM_PNC_HM_MOD, " TPM is NOT invalidating the PNC - MV driver is responsible \n");
+        return (TPM_OK);
+    }
+
+    TPM_OS_DEBUG( TPM_PNC_HM_MOD, "entry(%d)\n",entry);
+    TPM_PNC_ERR_ON_OOR(entry >= TPM_PNC_SIZE);
+
+    /* Invalidate PnC entry */
+    tpm_pnc_hw_entry_inv(entry);
+
+    return TPM_OK;
+}
+
+
+void tpm_pnc_entry_copy(uint32_t read_entry, uint32_t write_entry)
+{
+    struct tcam_entry tcamEntry;
+    uint32_t pnc_cgrp, lu_mask;
+
+    /* Clear SW TCAM entry */
+    tcam_sw_clear(&tcamEntry);
+
+    /* Read entry from HW */
+    tpm_pnc_hw_entry_read(&tcamEntry, read_entry);
+
+    /* Read PNC counter to get group and LU kask*/
+    pnc_cgrp = tpm_tcam_get_cntr_group(read_entry);
+    lu_mask = tpm_tcam_get_lu_mask(read_entry);
+
+    /* Write entry to HW */
+    tpm_pnc_hw_entry_write(&tcamEntry, write_entry);
+
+    /* Write PNC reg for counter group and LU mask */
+    tpm_tcam_set_lu_mask(write_entry, (int32_t) lu_mask);
+    tpm_tcam_set_cntr_group(write_entry, (int32_t) pnc_cgrp);
+}
+
+
+
+/*******************************************************************************
+* tpm_pnc_entry_insert()
+*
+* DESCRIPTION: This API inserts an invalid empty PnC entry.
+*              It 'pushes down' a block of TCAM entries following the inserted entry.
+*
+* INPUTS:      entry        - entry to be inserted
+*              last_entry   - last entry to be moved
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_pnc_entry_insert(uint32_t entry,
+                             uint32_t last_entry)
+{
+    int indx;
+    int iterNum;
+    uint32_t   cfg_pnc_parse_flag = 0;
+
+	cfg_pnc_parse_flag = mv_eth_ctrl_pnc_get();
+
+    if (cfg_pnc_parse_flag == 1) {
+        TPM_OS_DEBUG(TPM_PNC_HM_MOD, " TPM is NOT configuring the PNC - MV driver is responsible \n");
+        return (TPM_OK);
+    }
+
+    TPM_PNC_ERR_ON_OOR(entry >= TPM_PNC_SIZE);
+    TPM_PNC_ERR_ON_OOR(last_entry+1 >= TPM_PNC_SIZE);
+    TPM_PNC_ERR_ON_OOR(entry > last_entry);
+
+    iterNum = last_entry - entry + 1;
+
+    for (indx = 0; indx < iterNum; indx++)
+    {
+        tpm_pnc_entry_copy(last_entry-indx, last_entry-indx+1);
+    }
+
+    /* Invalidate inserted entry */
+    tpm_pnc_entry_inv(entry);
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_pnc_entry_delete()
+*
+* DESCRIPTION: This API deletes a TCAM entry in a range.
+*              It closes the gap, and pushes up subsequent TCAM entries in the range.
+*
+* INPUTS:      entry        - entry to be deleted
+*              last_entry   - last entry to be moved
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_pnc_entry_delete(uint32_t entry,
+                             uint32_t last_entry)
+{
+    int indx;
+    int iterNum;
+    uint32_t  cfg_pnc_parse_flag = 0;
+
+	cfg_pnc_parse_flag = mv_eth_ctrl_pnc_get();
+
+    if (cfg_pnc_parse_flag == 1) {
+        TPM_OS_DEBUG(TPM_PNC_HM_MOD, " TPM is NOT configuring the PNC - MV driver is responsible \n");
+        return (TPM_OK);
+    }
+    TPM_PNC_ERR_ON_OOR(entry >= TPM_PNC_SIZE);
+    TPM_PNC_ERR_ON_OOR(last_entry >= TPM_PNC_SIZE);
+    TPM_PNC_ERR_ON_OOR(entry > last_entry);
+
+    iterNum = last_entry - entry;
+
+    /* Invalidate deleted entry */
+    tpm_pnc_entry_inv(entry);
+
+    for (indx = 0; indx < iterNum; indx++)
+    {
+        tpm_pnc_entry_copy(entry+indx+1, entry+indx);
+    }
+
+    /* Invalidate last moved entry */
+    tpm_pnc_entry_inv(last_entry);
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_pnc_range_inv()
+*
+* DESCRIPTION: This API resets a range
+*
+* INPUTS:      entry        - start entry to be deleted
+*              last_entry   - last entry to be deleted
+*
+* OUTPUTS:
+*           None
+*
+* RETURNS:
+*           TPM_OK or TPM_FAIL
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_pnc_range_inv(uint32_t entry,
+                          uint32_t last_entry)
+{
+    int indx;
+    uint32_t          cfg_pnc_parse_flag = 0;
+
+	cfg_pnc_parse_flag = mv_eth_ctrl_pnc_get();
+
+    if (cfg_pnc_parse_flag == 1) {
+        TPM_OS_DEBUG(TPM_PNC_HM_MOD, " TPM is NOT configuring the PNC - MV driver is responsible \n");
+        return (TPM_OK);
+    }
+
+    TPM_OS_DEBUG( TPM_PNC_HM_MOD, "entry(%d) last_entry(%d)\n",entry, last_entry);
+    TPM_PNC_ERR_ON_OOR(entry >= TPM_PNC_SIZE);
+    TPM_PNC_ERR_ON_OOR(last_entry >= TPM_PNC_SIZE);
+    TPM_PNC_ERR_ON_OOR(entry > last_entry);
+
+    for (indx = entry; indx <= last_entry; indx++)
+    {
+        /* Invalidate entry */
+        tpm_pnc_entry_inv(indx);
+    }
+
+    return TPM_OK;
+}
+
+/*******************************************************************************
+* tpm_pnc_get_next_valid()
+*
+* DESCRIPTION: The API returns the next valid PnC entry
+*
+* INPUTS:   cur_entry   - start valid entry index
+*
+* OUTPUTS:  next_entry  - next valid entry index
+*           pnc_entry   - next valid entry
+*
+* RETURNS:
+*           TPM_OK, TPM_FAIL or TPM_NOT_FOUND
+*
+* COMMENTS:
+*           None
+*
+*******************************************************************************/
+int32_t tpm_pnc_get_next_valid(uint32_t       cur_entry,
+                               int32_t       *next_entry,
+                               tpm_pnc_all_t *pnc_entry)
+{
+    int               indx;
+    struct tcam_entry tcamEntry;
+    int32_t           rc = TPM_NOT_FOUND;
+
+    TPM_PNC_ERR_ON_OOR(cur_entry >= TPM_PNC_SIZE);
+    TPM_PNC_ERR_ON_OOM(next_entry == NULL);
+    TPM_PNC_ERR_ON_OOM(pnc_entry == NULL);
+
+    *next_entry = -1;
+
+    for (indx = (cur_entry + 1); indx < TPM_PNC_SIZE; indx++)
+    {
+        /* Clear SW TCAM entry */
+        tcam_sw_clear(&tcamEntry);
+
+        /* Read entry from HW */
+        tpm_pnc_hw_entry_read(&tcamEntry, indx);
+
+        if (tcamEntry.ctrl.flags & TCAM_F_INV)
+            continue;
+
+        rc = TPM_OK;
+        *next_entry = indx;
+        tpm_pnc_fill_in_entry(&tcamEntry, pnc_entry);
+        break;
+    }
+
+    return rc;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_pnc_mgr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_pnc_mgr.h
new file mode 100755
index 0000000..ead1acd
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_pnc_mgr.h
@@ -0,0 +1,124 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#ifndef __TPM_PNCM_H__
+#define __TPM_PNCM_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+/*               TEMP. DEFINITIONS                           */
+/*************************************************************/
+
+/*************************************************************/
+/*               DEFINITIONS                                 */
+/*************************************************************/
+#define MAX_PORT_NUMBER         0x1F
+#define MAX_ADD_INFO_BITS       7  /* Add info field size = 7 bits */
+
+/* Result info field size = 24 bits */
+#define MAX_RES_INFO_BITS_16    16
+#define MAX_RES_INFO_BITS_8     8
+#define RES_INFO_BITS_16_MASK   0x0000FFFF
+#define RES_INFO_BITS_8_MASK    0x00FF0000
+
+
+/* Flow ID */
+#define FLOW_ID_LSW_MASK        0x00000001
+#define FLOW_ID_MSW_MASK        0x00000002
+#define FLOW_ID_MSW_SHIFT       16
+
+/*************************************************************/
+/*               ENUMERATIONS                                */
+/*************************************************************/
+
+/*************************************************************/
+/*               STRUCTURES                                  */
+/*************************************************************/
+
+/*************************************************************/
+/*               PROTOTYPES for internal using               */
+/*************************************************************/
+void tpm_pnc_fill_in_entry(struct tcam_entry *tcamEntry, tpm_pnc_all_t *pnc_entry);
+void tpm_pnc_print_sw_entry(tpm_pnc_all_t *pnc_entry);
+
+/*************************************************************/
+/*               PROTOTYPES                                  */
+/*************************************************************/
+int32_t tpm_pnc_set            (uint32_t entry, uint32_t sram_update, tpm_pnc_all_t *pnc_entry);
+int32_t tpm_pnc_get_next_valid (uint32_t cur_entry, int32_t *next_entry, tpm_pnc_all_t  *pnc_entry);
+int32_t tpm_pnc_entry_insert   (uint32_t entry, uint32_t last_entry);
+int32_t tpm_pnc_entry_delete   (uint32_t entry, uint32_t last_entry);
+int32_t tpm_pnc_entry_inv      (uint32_t entry);
+int32_t tpm_pnc_range_inv      (uint32_t entry, uint32_t last_entry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TPM_PNCM_H__*/
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_rtos.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_rtos.h
new file mode 100755
index 0000000..6b72fa6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_rtos.h
@@ -0,0 +1,131 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+**  FILE        : tpm_rtos.h                                                 **
+**                                                                           **
+**  DESCRIPTION : This file contains ONU GPON Linux OS resources             **
+*******************************************************************************
+*                                                                             *
+*  MODIFICATION HISTORY:                                                      *
+*                                                                             *
+*   10Aug10  Oren Ben Hayun   created                                         *
+* =========================================================================== *
+******************************************************************************/
+#ifndef _TPM_RTOS_H_
+#define _TPM_RTOS_H_
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/byteorder/generic.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#include <linux/in.h>
+#include <linux/capability.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include "mvTypes.h"
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+/* Definitions
+------------------------------------------------------------------------------*/
+
+/* Enums
+------------------------------------------------------------------------------*/
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* Macros
+------------------------------------------------------------------------------*/
+
+#endif /* _TPM_RTOS_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.c
new file mode 100755
index 0000000..ede6176
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.c
@@ -0,0 +1,6427 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* mv_tpm_sw_config.c
+*
+*
+*  MODULE : TPM Switch
+*
+*  DESCRIPTION : This file config tpm switch
+*
+*  MODIFICATION HISTORY:
+*           28Apr2010   DimaM  - initial version created.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1.47 $
+*******************************************************************************/
+
+#include "tpm_common.h"
+#include "tpm_header.h"
+
+uint32_t trace_sw_dbg_flag = 0;
+
+#define IF_ERROR(ret)\
+    if (ret != TPM_DB_OK) {\
+        printk(KERN_ERR "ERROR: (%s) call not allowed, switch not initialized\n", __FUNCTION__);\
+        return(ret);\
+    }
+
+#define SWITCH_INIT_CHECK()\
+    int32_t ret_init_check;\
+    ret_init_check = tpm_sw_init_check();\
+    IF_ERROR(ret_init_check);
+
+/*******************************************************************************
+* tpm_sw_init_check
+*
+* DESCRIPTION:
+*       This function is to check switch is allowed to init or not
+*
+* INPUTS:
+*       NONE
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_init_check(void)
+{
+    uint32_t switch_init;
+    int32_t ret;
+
+    ret = tpm_db_switch_init_get(&switch_init);
+    IF_ERROR(ret);
+    if (!switch_init)
+        return ERR_SW_NOT_INIT;
+
+    return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_sw_set_debug_trace_flag
+*
+* DESCRIPTION:
+*       This function sets TPM trace flag.
+*
+* INPUTS:
+*       enDis    - enable or disable
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_debug_trace_flag
+(
+     uint32_t enDis
+)
+{
+    trace_sw_dbg_flag = enDis;
+    return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_sw_add_static_mac
+*
+* DESCRIPTION:
+*       This function creates a static MAC entry in the MAC address table for a
+*       specific UNI port in the integrated switch
+*
+* INPUTS:
+*       owner_id    - APP owner id, should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       static_mac  - 6 byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_add_static_mac
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             static_mac[6]
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r \
+               static_mac[%02x:%02x:%02x:%02x:%02x:%02x]\n\r",
+              __FUNCTION__,owner_id,src_port, static_mac[0],static_mac[1],static_mac[2],static_mac[3],static_mac[4],static_mac[5]);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_add_static_mac(lPort, &(static_mac[0]));
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_del_static_mac
+*
+* DESCRIPTION:
+*       This function removes an existing static MAC entry from the MAC address
+*       table  in the integrated switch.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       static_mac  - 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_del_static_mac
+(
+    uint32_t owner_id,
+    uint8_t  static_mac[6]
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                 "==ENTER==%s: owner_id[%d]\n\r, \
+                 static_mac[%02x:%02x:%02x:%02x:%02x:%02x]\n\r",
+                 __FUNCTION__,owner_id,static_mac[0],static_mac[1],static_mac[2],static_mac[3],static_mac[4],static_mac[5]);
+    }
+
+    retVal = mv_switch_del_static_mac(&(static_mac[0]));
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_static_mac_w_ports_mask
+*
+* DESCRIPTION:
+*       This function creates or destory a static MAC entry in the MAC address
+*       table for several specific ports in the integrated switch
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       ports_mask  - Ports mask.
+*       static_mac  - 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_static_mac_w_ports_mask
+(
+    uint32_t owner_id,
+    uint32_t ports_mask,
+    uint8_t  static_mac[6]
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],ports_mask[0x%x]\n\r"\
+               "static_mac[%02x:%02x:%02x:%02x:%02x:%02x]\n\r",
+               __FUNCTION__,owner_id,
+               ports_mask,
+               static_mac[0],
+               static_mac[1],
+               static_mac[2],
+               static_mac[3],
+               static_mac[4],
+               static_mac[5]);
+    }
+
+    retVal = mv_switch_mac_addr_set(&(static_mac[0]), 0, ports_mask, 1);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_clear_dynamic_mac
+*
+* DESCRIPTION:
+*       Clear all dynamic MAC.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_clear_dynamic_mac(    uint32_t owner_id)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d]\n\r", __FUNCTION__, owner_id);
+    }
+
+    retVal = mv_switch_clear_dynamic_mac();
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_mirror
+*
+* DESCRIPTION:
+*       Set port mirror.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*       sport      - Source port.
+*       dport      - Destination port.
+*       mode       - mirror mode.
+*       enable     - enable/disable mirror.
+*
+* OUTPUTS:
+*       None
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_mirror
+(
+    uint32_t             owner_id,
+    uint32_t             sport,
+    uint32_t             dport,
+    tpm_sw_mirror_type_t mode,
+    bool                 enable
+)
+{
+    tpm_error_code_t retVal;
+    GT_BOOL  state;
+    uint32_t  sw_sport;
+    uint32_t  sw_dport; 
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] sport[%d] dport[%d] mode[%d] enable[%d]\n\r",
+               __FUNCTION__, owner_id, tpm_db_eth_port_switch_port_get(sport),
+               tpm_db_eth_port_switch_port_get(dport), mode, enable);
+    }
+
+    if(enable == true)
+        state = GT_TRUE;
+    else
+        state = GT_FALSE;
+
+    sw_sport = tpm_db_eth_port_switch_port_get(sport);
+    sw_dport = tpm_db_eth_port_switch_port_get(dport); 
+
+    if (TPM_DB_ERR_PORT_NUM == sw_sport || TPM_DB_ERR_PORT_NUM == sw_dport){
+            TPM_OS_ERROR(TPM_INIT_MOD, "invalid port (sw_sport %d, sw_dport %d)\n", sw_sport, sw_dport);
+	     return GT_FAIL;
+    }
+
+    retVal = mv_switch_set_mirror(sw_sport, sw_dport, (GT_MIRROR_MODE)mode, state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_mirror
+*
+* DESCRIPTION:
+*       Get port mirror status.
+*
+* INPUTS:
+*       owner_id    - APP owner id , should be used for all API calls.
+*       sport       - Source port.
+*       dport       - Destination port.
+*       mode        - mirror mode.
+*
+* OUTPUTS:
+*       enable      - enable/disable mirror.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_mirror
+(
+    uint32_t             owner_id,
+    uint32_t             sport,
+    uint32_t             dport,
+    tpm_sw_mirror_type_t mode,
+    bool                *enable
+)
+{
+    tpm_error_code_t retVal;
+    GT_BOOL  state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] sport[%d] dport[%d] mode[%d] \n\r",
+               __FUNCTION__, owner_id, tpm_db_eth_port_switch_port_get(sport),
+               tpm_db_eth_port_switch_port_get(dport), mode);
+    }
+
+    retVal = mv_switch_get_mirror(tpm_db_eth_port_switch_port_get(sport),
+                                  tpm_db_eth_port_switch_port_get(dport),
+                                  (GT_MIRROR_MODE)mode, &state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(state == GT_FALSE)
+        *enable = false;
+    else
+        *enable = true;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: enable[%d]\n\r",__FUNCTION__, *enable);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_isolate_eth_port_vector()
+*
+* DESCRIPTION:      Isolate port vector.
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       port_vector - port vector.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_isolate_eth_port_vector
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t            port_vector
+)
+{
+#define MEM_PORTS_NR  7
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    uint32_t memPorts[MEM_PORTS_NR] = {1};
+    uint32_t i = 0;
+    uint8_t  memPortsLen = MEM_PORTS_NR;
+    uint32_t sw_port_num;
+
+    SWITCH_INIT_CHECK();
+
+    memset(memPorts, 1, sizeof(memPorts));
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] src_port[%d] port_vector[%d]\n\r",
+               __FUNCTION__, owner_id, src_port, port_vector);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    /*Init port list*/
+    for(i=0; i<MEM_PORTS_NR; i++)
+    {
+        memPorts[i] = i;
+    }
+
+    for (i=TPM_SRC_PORT_UNI_0; i<TPM_MAX_NUM_UNI_PORTS; i++)
+    {
+	sw_port_num = tpm_db_eth_port_switch_port_get(i);
+
+	if (TPM_DB_ERR_PORT_NUM == sw_port_num)
+		continue;
+
+	if (sw_port_num >= MEM_PORTS_NR) {
+		TPM_OS_ERROR(TPM_INIT_MOD, "sw_port_num too big! (%d >= MEM_PORTS_NR) \n", sw_port_num);
+		return ERR_SRC_PORT_INVALID;
+	}
+
+        if(port_vector & (1 << i))
+        {
+            memPorts[sw_port_num] = sw_port_num;
+            printk(KERN_INFO
+               "==ENTER==%s: 1  i[%d] sw_port_num[%d]\n\r",
+               __FUNCTION__,  i, sw_port_num);
+        }
+        else
+        {
+            memPorts[sw_port_num] = 0x80;
+            printk(KERN_INFO
+               "==ENTER==%s: 2  i[%d] sw_port_num[%d]\n\r",
+               __FUNCTION__,  i, sw_port_num);
+        }
+    }
+
+    /*set VLAN member*/
+    retVal = mv_switch_set_port_vlan_ports(lPort, memPorts, memPortsLen);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+     if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s \n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_isolate_eth_port_vector()
+*
+* DESCRIPTION:      Isolate port vector.
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       port_vector - port vector.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_isolate_eth_port_vector
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t            *port_vector
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    uint32_t memPorts[7] = {0x80};
+    uint32_t i = 0;
+    uint8_t  memPortsLen = 7;
+    uint32_t sw_port_num;
+    uint32_t vector = 0;
+
+    SWITCH_INIT_CHECK();
+
+    memset(memPorts, 1, sizeof(memPorts));
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] src_port[%d] \n\r",
+               __FUNCTION__, owner_id, src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    /*get VLAN member*/
+    retVal = mv_switch_get_port_vlan_ports(lPort, memPorts, &memPortsLen);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    for(i=TPM_SRC_PORT_UNI_0; i<TPM_MAX_NUM_ETH_PORTS; i++)
+    {
+        sw_port_num = tpm_db_eth_port_switch_port_get(i);
+	 if (TPM_DB_ERR_PORT_NUM == sw_port_num)
+            continue;
+
+        if(memPorts[sw_port_num] == sw_port_num)
+        {
+            vector |= (1 << (i-1));
+        }
+    }
+
+    *port_vector = vector & 0x0000000F;
+
+     if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: port_vector[%d]\n\r",__FUNCTION__, *port_vector);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_set_mtu_size
+*
+* DESCRIPTION:
+*       Set switch MTU size.
+*
+* INPUTS:
+*       owner_id  - APP owner id , should be used for all API calls.
+*       type      - MRU type:GMAC0, GMAC1, PONMAC, switch
+*       mtu       - MTU size.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_set_mtu_size
+(
+    uint32_t       owner_id,
+    tpm_mru_type_t type,
+    uint32_t       mtu
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],type[%d],mtu[%d]\r\n",
+               __FUNCTION__, owner_id, type, mtu);
+
+    }
+
+    switch(type)
+    {
+        case TPM_NETA_MTU_GMAC0:
+              /*GMAC0 port number: 0*/
+            retVal = mv_eth_set_mtu(0, mtu);
+            break;
+        case TPM_NETA_MTU_GMAC1:
+            /*GMAC1 port number: 1*/
+            retVal = mv_eth_set_mtu(1, mtu);
+            break;
+        case TPM_NETA_MTU_PONMAC:
+            /*PON GMAC port number: 2*/
+            retVal = mv_eth_set_mtu(2, mtu);
+            break;
+        case TPM_NETA_MTU_SWITCH:
+            /*Set switch MTU*/
+            retVal = mv_switch_set_mtu(mtu);
+            break;
+        default:
+            break;
+    }
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_get_mtu_size
+*
+* DESCRIPTION:
+*       Get switch MTU size.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*       type       - MRU type:GMAC0, GMAC1, PONMAC, switch
+*
+* OUTPUTS:
+*       mtu        - MTU size.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+tpm_error_code_t tpm_get_mtu_size
+(
+    uint32_t        owner_id,
+    tpm_mru_type_t  type,
+    uint32_t       *mtu
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+              "==ENTER==%s: owner_id[%d],type[%d],",
+              __FUNCTION__,owner_id, type);
+
+    }
+
+    switch(type)
+    {
+        case TPM_NETA_MTU_GMAC0:
+              /*GMAC0 port number: 0*/
+            retVal = mv_eth_get_mtu(0, mtu);
+            break;
+        case TPM_NETA_MTU_GMAC1:
+            /*GMAC1 port number: 1*/
+            retVal = mv_eth_get_mtu(1, mtu);
+            break;
+        case TPM_NETA_MTU_PONMAC:
+            /*PON GMAC port number: 2*/
+            retVal = mv_eth_get_mtu(2, mtu);
+            break;
+        case TPM_NETA_MTU_SWITCH:
+            /*Get switch MTU*/
+            retVal = mv_switch_get_mtu(mtu);
+            break;
+        default:
+            break;
+    }
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:mtu[%d]\n\r",__FUNCTION__, *mtu);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_max_macs
+*
+* DESCRIPTION:
+*       This function limits the number of MAC addresses per src_port.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mac_per_port - maximum number of MAC addresses per port (1-255).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       The following care is needed when enabling this feature:
+*            1) disable learning on the ports
+*            2) flush all non-static addresses in the ATU
+*            3) define the desired limit for the ports
+*            4) re-enable learing on the ports
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_max_macs
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             mac_per_port
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],mac_per_port[%d]\r\n",
+                __FUNCTION__, owner_id, src_port, mac_per_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_port_max_macs(lPort, mac_per_port);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_max_macs
+*
+* DESCRIPTION:
+*        Port's auto learning limit. When the limit is non-zero value, the number
+*        of MAC addresses that can be learned on this UNI port are limited to the value
+*        specified in this API. When the learn limit has been reached any frame
+*        that ingresses this UNI port with a source MAC address not already in the
+*        address database that is associated with this UNI port will be discarded.
+*        Normal auto-learning will resume on the UNI port as soon as the number of
+*        active unicast MAC addresses associated to this UNI port is less than the
+*        learn limit.
+*        CPU directed ATU Load, Purge, or Move will not have any effect on the
+*        learn limit.
+*        This feature is disabled when the limit is zero.
+*        The following care is needed when enabling this feature:
+*            1) dsable learning on the ports
+*            2) flush all non-static addresses in the ATU
+*            3) define the desired limit for the ports
+*            4) re-enable learing on the ports
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       limit      - maximum number of MAC addresses per UNI port (1-255).
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_max_macs
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t           *limit
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_max_macs(lPort, limit);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: limit[%d]\n\r",
+                __FUNCTION__,*limit);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_tagged
+*
+* DESCRIPTION:
+*       The API allows or drops tagged packets on a per UNI port basis.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       allow_tagged - set to 1 = discard tagged packets per UNI port
+*                      set to 0 = allow tagged packets per UNI port.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success   - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_tagged
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             allow_tagged
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          mode;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+              "==ENTER==%s: owner_id[%d],src_port[%d],allow_tagged[%d]\r\n",
+              __FUNCTION__,owner_id,src_port,allow_tagged);
+
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    if (allow_tagged == 1)
+    {
+        mode = 1/*GT_TRUE*/;
+    }
+    else
+    {
+        mode = MV_FALSE;
+    }
+
+    retVal = mv_switch_set_port_tagged(lPort, mode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_tagged
+*
+* DESCRIPTION:
+*       This routine gets DiscardTagged bit for the given UNI port.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       mode       - MV_TRUE if DiscardTagged bit is set, MV_FALSE otherwise
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_tagged
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t            *mode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_tagged(lPort, mode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:mode[%d]\n\r",__FUNCTION__,*mode);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_untagged
+*
+* DESCRIPTION:
+*       The API allows or drops untagged packets on a per UNI port basis.
+*
+* INPUTS:
+*       owner_id       - APP owner id - should be used for all API calls.
+*       src_port       - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       allow_untagged - set to 1 = discard untagged packets per UNI port
+*                        set to 0 = alow untagged packets per UNI port.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success     - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_untagged
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             allow_untagged
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          mode;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],allow_untagged[%d]\r\n",
+                __FUNCTION__,owner_id,src_port,allow_untagged);
+    }
+
+    if (allow_untagged == 1)
+    {
+        mode = 1/*GT_TRUE*/;
+    }
+    else
+    {
+        mode = MV_FALSE;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_port_untagged(lPort, mode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_untagged
+*
+* DESCRIPTION:
+*       This routine gets DiscardUntagged bit for the given UNI port.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       mode        - MV_TRUE if DiscardUntagged bit is set, MV_FALSE otherwise
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_untagged
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t            *mode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_untagged(lPort, mode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:mode[%d]\n\r",
+                __FUNCTION__,*mode);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_def_vlan
+*
+* DESCRIPTION:
+*       The API sets port default vlan id.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - the port vlan id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_def_vlan
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint16_t            vid
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],vid[%d]\r\n",
+                __FUNCTION__,owner_id,src_port,vid);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    if (vid > 4095)
+    {
+        printk(KERN_ERR
+            "%s:illegal VID[%d]\r\n", __FUNCTION__, vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    retVal = mv_switch_set_port_def_vlan(lPort, vid);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_def_vlan
+*
+* DESCRIPTION:
+*       The API gets port default vlan id.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       vid        - the port vlan id
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_def_vlan
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint16_t            *vid
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_def_vlan(lPort, vid);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:vid[%d]\n\r",
+                __FUNCTION__,*vid);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_def_pri
+*
+* DESCRIPTION:
+*       The API sets port default priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       pri        - the port priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_def_pri
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             pri
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],pri[%d]\r\n",
+                __FUNCTION__,owner_id,src_port,pri);
+    }
+
+    if (pri>7)
+    {
+        printk(KERN_ERR
+           "%s:illegal pri[%d]\r\n", __FUNCTION__, pri);
+        return ERR_GENERAL;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_port_def_pri(lPort, pri);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_def_pri
+*
+* DESCRIPTION:
+*       The API gets port default priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       pri        - the port priority.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_def_pri
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t            *pri
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_def_pri(lPort, pri);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:pri[%d]\n\r",
+                __FUNCTION__,*pri);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_port_add_vid
+*
+* DESCRIPTION:
+*       The API adds a VID to the list of the allowed VIDs per UNI port.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid      - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       see the example sample802_1qSetup().
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_add_vid
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint16_t            vid
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],vid[%d]\n",
+                __FUNCTION__,owner_id,src_port,vid);
+    }
+
+    if (vid >= TPM_MAX_VID)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== invalid VID[%d]\r\n", __FUNCTION__,__LINE__,vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_port_add_vid(lPort, vid, TPM_GMAC0_AMBER_PORT_NUM);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_clear_vid_per_port
+*
+* DESCRIPTION:
+*       The API delete all VID from the list of VIDs allowed per UNI port.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_clear_vid_per_port
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    uint16_t         vid;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    for(vid=1; vid < TPM_MAX_VID-1; vid++)
+    {
+        retVal = mv_switch_del_vid_per_port(lPort, vid);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_add_all_vid_per_port
+*
+* DESCRIPTION:
+*       The API adds all allowed VIDs from 1 to 4095 per UNI port.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_add_all_vid_per_port
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    uint16_t         vid;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    for(vid=1; vid < TPM_MAX_VID-1; vid++)
+    {
+        retVal = mv_switch_port_add_vid(lPort, vid, TPM_GMAC0_AMBER_PORT_NUM);
+        if (retVal != TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        }
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_port_del_vid
+*
+* DESCRIPTION:
+*       The API delete and existing VID from the list of VIDs allowed per UNI port.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - VLAN id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_del_vid
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint16_t            vid
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],vid[%d]\r\n",
+                __FUNCTION__, owner_id, src_port, vid);
+    }
+
+    if (vid >= TPM_MAX_VID)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== invalid VID[%d]\r\n", __FUNCTION__,__LINE__,vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_del_vid_per_port(lPort, vid);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_vid_egress_mode
+*
+* DESCRIPTION:
+*       The API sets the egress mode for a member port of a vlan.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid        - vlan id
+*       eMode      - egress mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       MEMBER_EGRESS_UNMODIFIED - 0
+*       NOT_A_MEMBER             - 1
+*       MEMBER_EGRESS_UNTAGGED   - 2
+*       MEMBER_EGRESS_TAGGED     - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_vid_egress_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint16_t            vid,
+    uint8_t             eMode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],vid[%d],eMode[%d]\r\n",
+                __FUNCTION__,owner_id,src_port,vid,eMode);
+    }
+
+    if (vid >= TPM_MAX_VID)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== invalid VID[%d]\r\n", __FUNCTION__,__LINE__,vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_port_vid_egress_mode(lPort, vid, eMode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_port_get_vid
+*
+* DESCRIPTION:
+*       The API return VID to the list of the allowed VIDs per UNI port.
+*
+* INPUTS:
+*       owner_id   - APP owner id should be used for all API calls.
+*       vid        -  searching VID.
+*
+* OUTPUTS:
+*       found      - MV_TRUE, if the appropriate entry exists.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_get_vid
+(
+    uint32_t  owner_id,
+    uint32_t  vid,
+    uint32_t *found
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],vid[%d]\r\n",
+                __FUNCTION__,owner_id,vid);
+    }
+
+    if (vid >= TPM_MAX_VID)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== invalid VID[%d]\r\n", __FUNCTION__,__LINE__,vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    retVal = mv_switch_port_print_vid(vid, found);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: found[%d]\n\r",__FUNCTION__,*found);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_port_add_vid_group()
+*
+* DESCRIPTION:      Add a group of VID to the list of the allowed VIDs per port,
+*                    and set the egress mode correspondingly.
+*
+* INPUTS:
+*       owner_id - APP owner id  should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode     - VLAN egress mode.
+*       min_vid  - min VLAN ID.
+*       max_vid  - max VLAN ID.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_add_vid_group
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             mode,
+    uint16_t            min_vid,
+    uint16_t            max_vid
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    uint16_t         vid;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d], src_port[%d], mode[%d], min_vid[%d] max_vid[%d]\r\n",
+                __FUNCTION__,owner_id, src_port, mode, min_vid, max_vid);
+    }
+
+    /*check VID*/
+    if (max_vid >= TPM_MAX_VID)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== invalid max_vid[%d]\r\n", __FUNCTION__,__LINE__,max_vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    if(min_vid > max_vid)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR==  param error: min_vid[%d] > max_vid[%d] \r\n", __FUNCTION__,__LINE__, min_vid, max_vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    for(vid=min_vid; vid<=max_vid; vid++)
+    {
+        /*set the VID*/
+        retVal = tpm_sw_port_add_vid(owner_id, src_port, vid);
+        if(retVal !=TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+            break;
+        }
+
+        /*set VLAN egress mode*/
+        retVal = tpm_sw_set_port_vid_egress_mode(owner_id, src_port, vid, mode);
+        if(retVal !=TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+            break;
+        }
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_port_del_vid_group()
+*
+* DESCRIPTION:      Delete a group of VID to the list of the allowed VIDs per port,
+*                    and set the egress mode correspondingly.
+*
+* INPUTS:
+*       owner_id - APP owner id  should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       min_vid  - min VLAN ID.
+*       max_vid  - max VLAN ID.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_del_vid_group
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint16_t            min_vid,
+    uint16_t            max_vid
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    uint16_t         vid;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d], src_port[%d], min_vid[%d] max_vid[%d]\r\n",
+                __FUNCTION__,owner_id, src_port, min_vid, max_vid);
+    }
+
+    /*check VID*/
+    if (max_vid >= TPM_MAX_VID)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== invalid max_vid[%d]\r\n", __FUNCTION__,__LINE__,max_vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    if(min_vid > max_vid)
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR==  param error: min_vid[%d] > max_vid[%d] \r\n", __FUNCTION__,__LINE__, min_vid, max_vid);
+        return ERR_SW_VID_INVALID;
+    }
+
+    for(vid=min_vid; vid<=max_vid; vid++)
+    {
+        /*Delete the VID*/
+        retVal = tpm_sw_port_del_vid(owner_id, src_port, vid);
+        if(retVal !=TPM_RC_OK)
+        {
+            printk(KERN_ERR
+                   "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+            break;
+        }
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_prv_set_secure_mode
+*
+* DESCRIPTION:
+*       Change a port mode in the SW data base and remove it from all VLANs
+*
+* INPUTS:
+*       owner_id   -  APP owner id - should be used for all API calls.
+*       port       -  secure port number
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_prv_set_secure_mode
+(
+    uint32_t owner_id,
+    uint32_t port
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    retVal = mv_switch_prv_set_secure_mode(port);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+              "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_prv_set_fallback_mode
+*
+* DESCRIPTION:
+*       Change a port mode in the SW data base and add it to all VLANs
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       port       - secure port number
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_prv_set_fallback_mode
+(
+    uint32_t owner_id,
+    uint32_t port
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    retVal = mv_switch_prv_set_fallback_mode(port);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+              "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_port_set_vid_filter
+*
+* DESCRIPTION:
+*       The API sets the filtering mode of a certain UNI port.
+*       If the UNI port is in filtering mode, only the VIDs added by the
+*       tpm_sw_port_add_vid API will be allowed to ingress and egress the UNI port.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       vid_filter - set to 1 - means the UNI port will DROP all packets which are NOT in
+*                    the allowed VID list (built using API tpm_sw_port_add_vid).
+*                    set to 0 - means that the list of VIDs allowed
+*                    per UNI port has no significance (the list is not deleted).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_set_vid_filter
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             vid_filter
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                 "==ENTER==%s: owner_id[%d],src_port[%d],vid_filter[%d]\r\n",
+                 __FUNCTION__,owner_id,src_port, vid_filter);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_vid_filter_per_port(lPort, vid_filter);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+              "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_vid_filter_per_port
+*
+* DESCRIPTION:
+*        This routine gets protected mode of a UNI port port.
+*        When this mode is set to GT_TRUE, frames are allowed to egress UNI port
+*        defined by the 802.1Q VLAN membership for the frame's VID 'AND'
+*        by the UNI port's VLANTable if 802.1Q is enabled on the UNI port. Both must
+*        allow the frame to Egress.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*         mode - GT_TRUE: header mode enabled
+*                   GT_FALSE otherwise
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_vid_filter_per_port
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t           *mode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    uint8_t          vid_filter;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                 "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                 __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_vid_filter_per_port(lPort, &vid_filter);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    *mode = (uint32_t)vid_filter;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: mode[%d] \n\r",__FUNCTION__, *mode);
+    }
+
+    return TPM_RC_OK;
+}
+
+/*******************************************************************************
+* tpm_sw_set_uni_sched()
+*
+* DESCRIPTION:      Configures the scheduling mode per Ethernet port.
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       sched_mode  - scheduler mode per port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*DDD
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_sched
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_sw_sched_type_t sched_mode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    uint32_t         mode;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],sched_mode[%d]\n\r",
+               __FUNCTION__,owner_id,src_port,sched_mode);
+    }
+
+    switch(sched_mode)
+    {
+        case  TPM_PP_SCHED_STRICT:
+            mode = PORT_SCHED_MODE_SPRI;
+            break;
+
+        case TPM_PP_SCHED_WRR:
+            mode = PORT_SCHED_MODE_WRRB;
+            break;
+
+       default:
+            printk(KERN_INFO "==Error== %s: sched_mode[1 or 2]\n\r",__FUNCTION__);
+            return ERR_GENERAL;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_port_sched_mode(lPort, mode);
+    if (retVal != GT_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_uni_q_weight
+*
+* DESCRIPTION:
+*       The API configures the weight of a queues for all
+*       Ethernet UNI ports in the integrated switch.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       weight   - weight value per queue (1-8).queue (value 1-3).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.  DDD
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_q_weight
+(
+    uint32_t owner_id,
+    uint8_t  queue_id,
+    uint8_t  weight
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],queue_id[%d] weight[%d]\n\r",
+                __FUNCTION__,owner_id,queue_id,weight);
+    }
+
+    if ((queue_id == 0) ||
+        (queue_id > SW_QOS_NUM_OF_QUEUES))
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== invalid queue[%d]\r\n", __FUNCTION__,__LINE__,queue_id);
+        return ERR_SW_TM_QUEUE_INVALID;
+    }
+
+    retVal = mv_switch_set_uni_q_weight(queue_id, weight);
+    if (retVal != GT_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures an ingress policing function for an Ethernet UNI port.
+*
+* INPUTS:
+*       owner_id   - APP owner id, should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       count_mode - count mode:
+*                               TPM_SW_LIMIT_FRAME
+*                               TPM_SW_LIMIT_LAYER1
+*                               TPM_SW_LIMIT_LAYER2
+*                               TPM_SW_LIMIT_LAYER3
+*       cir        - comited info rate.
+*       cbs        - Committed Burst Size limit (expected to be 2kBytes)
+*       ebs        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_ingr_police_rate
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_limit_mode_t    count_mode,
+    uint32_t            cir,
+    uint32_t            cbs,
+    uint32_t            ebs
+)
+{
+    tpm_error_code_t    retVal = TPM_RC_OK;
+    int32_t             lPort  = 0;
+    GT_PIRL2_COUNT_MODE mode;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],count_mode[%d], cir[%d], cbs[%d], ebs[%d]\r\n",
+                __FUNCTION__,owner_id,src_port,count_mode, cir, cbs,ebs);
+    }
+
+    mode = (GT_PIRL2_COUNT_MODE)count_mode;
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_uni_ingr_police_rate(lPort, (GT_PIRL2_COUNT_MODE)mode, cir, cbs, ebs);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s \n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_uni_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API gets an ingress policing function for an Ethernet UNI port.
+*
+* INPUTS:
+*       owner_id - APP owner id, should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       count_mode - count mode:
+*                               TPM_SW_LIMIT_FRAME
+*                               TPM_SW_LIMIT_LAYER1
+*                               TPM_SW_LIMIT_LAYER2
+*                               TPM_SW_LIMIT_LAYER3
+*       cir       - comited info rate.
+*       cbs       - Committed Burst Size limit (expected to be 2kBytes)
+*       ebs       - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_uni_ingr_police_rate
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    tpm_limit_mode_t    *count_mode,
+    uint32_t            *cir,
+    uint32_t            *cbs,
+    uint32_t            *ebs
+)
+{
+    tpm_error_code_t    retVal = TPM_RC_OK;
+    int32_t             lPort  = 0;
+    GT_PIRL2_COUNT_MODE mode;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_uni_ingr_police_rate(lPort, &mode, cir, cbs, ebs);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    *count_mode = (tpm_limit_mode_t)mode;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:,count_mode[%d], cir[%d], cbs[%d], ebs[%d]\n\r",
+                __FUNCTION__, *count_mode, *cir, *cbs, *ebs);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       The API Configures a policer function for a traffic class for an Ethernet UNI port.
+*       There are 4 globally defined traffic classes in the integrated switch.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       tc       - traffic class ( a combination of p-bits and DSCP values).
+*       cir      - comited info rate.
+*       cbs      - comited burst rate.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_tc_ingr_police_rate
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t             tc,
+    uint32_t             cir,
+    uint32_t             cbs
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],tc[%d],cir[%d],cbs[%d]\r\n",
+                __FUNCTION__,owner_id,src_port,tc, cir, cbs);
+    }
+
+    if ((tc == 0) || (tc > SW_QOS_NUM_OF_QUEUES))
+    {
+        printk(KERN_INFO
+               "%s:%d:==ERROR== invalid tc[%d]\r\n", __FUNCTION__,__LINE__,tc);
+        return ERR_SW_TM_QUEUE_INVALID;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_uni_tc_ingr_police_rate(lPort, tc, cir, cbs);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       This routine gets the UNI port's ingress data limit for priority 0 or 1 or 2 or 3 frames.
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       src_port - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*
+*       tc       - traffic class ( a combination of p-bits and DSCP values).
+*       cir      - comited info rate.
+*       cbs      - comited burst rate
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_uni_tc_ingr_police_rate
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t            *tc,
+    uint32_t            *cir,
+    uint32_t            *cbs
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_uni_tc_ingr_police_rate(lPort, tc, cir, cbs);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:tc[0x%x] cir[%d]\n\r",
+               __FUNCTION__,*tc,*cir);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API Configures the egress frame rate limit of an Ethernet UNI port
+* INPUTS:
+*       owner_id             - APP owner id - should be used for all API calls.
+*       src_port             - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode                 - frame/rate limit mode
+*       frame_rate_limit_val - egress rate limit value.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       GT_ERATE_TYPE used kbRate - frame rate valid values are:
+*                                    7600,..., 9600,
+*                                    10000, 20000, 30000, 40000, ..., 100000,
+*                                    110000, 120000, 130000, ..., 1000000.
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_uni_egr_rate_limit
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    tpm_limit_mode_t     mode,
+    uint32_t             frame_rate_limit_val
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d],mode[%d],frame_rate_limit_val[%d]\r\n",
+                __FUNCTION__,owner_id,src_port,mode,frame_rate_limit_val);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_uni_egr_rate_limit(lPort, (GT_PIRL_ELIMIT_MODE)mode, frame_rate_limit_val);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API return the egress frame rate limit of an Ethernet UNI port
+* INPUTS:
+*       owner_id        - APP owner id - should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       mode            - frame/rate limit mode
+*       rate_limit_val  - egress rate limit value..
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       GT_ERATE_TYPE used kbRate - frame rate valid values are:
+*                                    7600,..., 9600,
+*                                    10000, 20000, 30000, 40000, ..., 100000,
+*                                    110000, 120000, 130000, ..., 1000000.
+
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_uni_egr_rate_limit
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    tpm_limit_mode_t    *mode,
+    uint32_t            *frame_rate_limit_val
+)
+{
+    tpm_error_code_t    retVal = TPM_RC_OK;
+    int32_t             lPort  = 0;
+    GT_PIRL_ELIMIT_MODE limit_mode;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d],src_port[%d]\r\n",
+                __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_uni_egr_rate_limit(lPort, &limit_mode, frame_rate_limit_val);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+    *mode = (tpm_limit_mode_t)limit_mode;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: mode[%d], frame_rate_limit_val[%d]\n\r",
+                __FUNCTION__, *mode, *frame_rate_limit_val);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_atu_size
+*
+* DESCRIPTION:
+*       This function Sets the Mac address table size.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       size        - Table size
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        The device GT_88E6351 have fixed ATU size 8192.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_atu_size
+(
+    uint32_t owner_id,
+    uint32_t size
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    uint32_t         atu_size;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],size[%d]\n\r",
+               __FUNCTION__,owner_id,size);
+    }
+
+    switch(size)
+    {
+        case 0: atu_size = 0; /*ATU_SIZE_256*/  break;
+        case 1: atu_size = 1; /*ATU_SIZE_512*/  break;
+        case 2: atu_size = 2; /*ATU_SIZE_1024*/ break;
+        case 3: atu_size = 3; /*ATU_SIZE_2048*/ break;
+        case 4: atu_size = 4; /*ATU_SIZE_4096*/ break;
+        case 5:
+            printk(KERN_INFO "8192 entries not supported by driver\n");break;
+
+        default:
+            printk(KERN_INFO "==Error== %s: size[0-4]\n\r",__FUNCTION__);
+            return ERR_GENERAL;
+    }
+
+    /* The driver support only 8192 entry as constant value */
+    printk(" The device GT_88E6351 have fixed ATU size 8192\r\n");
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_mac_age_time
+*
+* DESCRIPTION:
+*       This function Sets the Mac address table size.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       time_out   - Aging Time value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_mac_age_time
+(
+    uint32_t owner_id,
+    uint32_t time_out
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],time_out[%d]\n\r",
+               __FUNCTION__,owner_id,time_out);
+    }
+
+    retVal = mv_switch_set_age_time(time_out);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_mac_age_time
+*
+* DESCRIPTION:
+*       This function Sets the Mac address table size.
+*
+* INPUTS:
+*       owner_id   - APP owner id , should be used for all API calls.
+*
+* OUTPUTS:
+*       time_out   - time out value.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_mac_age_time
+(
+     uint32_t  owner_id,
+     uint32_t *time_out
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d]\n\r",
+               __FUNCTION__,owner_id);
+    }
+
+    retVal = mv_switch_get_age_time(time_out);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:,time_out[%d]\n\r",__FUNCTION__,*time_out);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+*  tpm_sw_set_mac_learn
+*
+* DESCRIPTION:
+*       Enable/disable automatic learning of new source MAC addresses on port
+*       ingress.
+*
+* INPUTS:
+*       owner_id  - APP owner id , should be used for all API calls.
+*       src_port  - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       enable    - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+tpm_error_code_t  tpm_sw_set_mac_learn
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    bool                enable
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d], src_port[%d] enable[%d]\n\r",
+               __FUNCTION__,owner_id, src_port, enable);
+    }
+
+    if(enable == true)
+        state = GT_TRUE;
+    else
+        state = GT_FALSE;
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_mac_learn(lPort, state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+*  tpm_sw_get_mac_learn
+*
+* DESCRIPTION:
+*       Enable/disable automatic learning of new source MAC addresses on port
+*       ingress.
+*
+* INPUTS:
+*       owner_id  - APP owner id , should be used for all API calls.
+*       src_port  - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       enable    - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+tpm_error_code_t  tpm_sw_get_mac_learn
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    bool               *enable
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d], src_port[%d] \n\r",
+               __FUNCTION__,owner_id, src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_mac_learn(lPort, &state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(state == GT_TRUE)
+        *enable = true;
+    else
+        *enable = false;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:enable[%d]\n\r",__FUNCTION__, *enable);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_vlan_ports
+*
+* DESCRIPTION:
+*       This routine sets the port VLAN group port membership list.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_vlan_ports
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t            memPorts[],
+    uint8_t             memPortsLen
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d] memPorts[%02d %02d %02d %02d %02d %02d] \
+               memPortsLen[%d]\n\r",
+               __FUNCTION__,
+              owner_id,
+              src_port,
+              memPorts[0],
+              memPorts[1],
+              memPorts[2],
+              memPorts[3],
+              memPorts[4],
+              memPorts[5],
+              memPortsLen);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_port_vlan_ports(lPort, memPorts, memPortsLen);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_vlan_ports
+*
+* DESCRIPTION:
+*       This routine gets the port VLAN group port membership list.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_vlan_ports
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t             memPorts[],
+    uint8_t             *memPortsLen
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_vlan_ports(lPort, memPorts, memPortsLen);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT==%s: memPorts[%02d %02d %02d %02d %02d %02d] memPortsLen[%d]\n\r",
+               __FUNCTION__,
+               memPorts[0],
+               memPorts[1],
+               memPorts[2],
+               memPorts[3],
+               memPorts[4],
+               memPorts[5],
+               *memPortsLen);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_ingress_limit_mode
+*
+* DESCRIPTION:
+*       This routine sets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode       - rate control ingress limit mode.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*    GT_LIMT_ALL = 0,        limit and count all frames
+*    GT_LIMIT_FLOOD,         limit and count Broadcast, Multicast and flooded unicast frames
+*    GT_LIMIT_BRDCST_MLTCST, limit and count Broadcast and Multicast frames
+*    GT_LIMIT_BRDCST         limit and count Broadcast frames
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_ingress_limit_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t            mode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],mode[%d]\n\r",
+               __FUNCTION__,owner_id,src_port,mode);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_ingress_limit_mode(lPort, mode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_ingress_limit_mode
+*
+* DESCRIPTION:
+*       This routine gets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*        mode        - rate control ingress limit mode.
+*
+* RETURNS:
+*       On success   -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*    GT_LIMT_ALL = 0,        limit and count all frames
+*    GT_LIMIT_FLOOD,         limit and count Broadcast, Multicast and flooded unicast frames
+*    GT_LIMIT_BRDCST_MLTCST, limit and count Broadcast and Multicast frames
+*    GT_LIMIT_BRDCST         limit and count Broadcast frames
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_ingress_limit_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t           *mode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_ingress_limit_mode(lPort, mode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: mode[%d]\n\r",__FUNCTION__,*mode);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_priority_selection
+*
+* DESCRIPTION:
+*       This function sets initial QPri and FPri selection.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_priority_selection
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             init_pri,
+    bool                tag_if_both
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          lTag;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] src_port[%d] init_pri[%d]\n\r",
+               __FUNCTION__,owner_id,src_port,init_pri);
+    }
+
+    if (init_pri >= PRI_SEL_TYPE_MAX)
+    {
+        printk(KERN_INFO
+               "%s:%d: invalid initial priority\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    if(true == tag_if_both)
+        lTag = GT_TRUE;
+    else
+        lTag = GT_FALSE;
+
+    retVal = mv_switch_set_priority_selection(lPort,init_pri,lTag);
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_priority_selection
+*
+* DESCRIPTION:
+*       This function gets initial QPri and FPri selection.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_priority_selection
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint8_t             *init_pri,
+    bool                *tag_if_both
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          lTag;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    if (NULL == init_pri)
+    {
+        printk(KERN_INFO
+               "%s:%d: null pointer\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_priority_selection(lPort,init_pri,&lTag);
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if(GT_TRUE == lTag)
+       *tag_if_both = true;
+    else
+       *tag_if_both = false;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s: init_pri[%d]\n\r",__FUNCTION__,*init_pri);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This function maps a tag priority to a queue priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       tag_pri    - Source tag priority number.
+*       q_pri      - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_tag_pri_mapping
+(
+     uint32_t owner_id,
+     uint8_t  tag_pri,
+     uint8_t  q_pri
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] tag_pri[%d] q_pri[%d]\n\r",
+               __FUNCTION__,owner_id,tag_pri,q_pri);
+    }
+
+    if (tag_pri > SW_QOS_NUM_OF_TAG_PRI)
+    {
+        printk(KERN_INFO
+               "%s:%d: invalid tag priority\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    if (q_pri > SW_QOS_NUM_OF_QUEUES)
+    {
+        printk(KERN_INFO
+               "%s:%d: invalid queue priority\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    retVal = mv_switch_set_tag_pri_mapping(tag_pri,q_pri);
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This function gets the queue priority for a tag priority mapping to.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       tag_pri    - Source tag priority number.
+*
+* OUTPUTS:
+*       q_pri      - Target queue priority number.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_tag_pri_mapping
+(
+     uint32_t owner_id,
+     uint8_t  tag_pri,
+     uint8_t *q_pri
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] tag_pri[%d]\n\r",
+               __FUNCTION__,owner_id,tag_pri);
+    }
+
+    if (NULL == q_pri)
+    {
+        printk(KERN_INFO
+               "%s:%d: null pointer\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    if (tag_pri > SW_QOS_NUM_OF_TAG_PRI)
+    {
+        printk(KERN_INFO
+               "%s:%d: invalid tag priority\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    retVal = mv_switch_get_tag_pri_mapping(tag_pri,q_pri);
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s: q_pri[%d]\n\r",__FUNCTION__,*q_pri);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This function maps a dscp value to a queue priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       dscp       - Source dscp value.
+*       q_pri      - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_ip_pri_mapping
+(
+     uint32_t owner_id,
+     uint8_t  dscp,
+     uint8_t  q_pri
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] dscp[0x%x] q_pri[%d]\n\r",
+               __FUNCTION__,owner_id,dscp,q_pri);
+    }
+
+    if (dscp > SW_QOS_DSCP_MAX)
+    {
+        printk(KERN_INFO
+               "%s:%d: invalid dscp number\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    if (q_pri > SW_QOS_NUM_OF_QUEUES)
+    {
+        printk(KERN_INFO
+               "%s:%d: invalid queue priority\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    retVal = mv_switch_set_ip_pri_mapping(dscp,q_pri);
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This function gets the queue priority for a dscp value mapping to.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       dscp       - Source dscp value.
+*
+* OUTPUTS:
+*       q_pri      - Target queue priority number.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_ip_pri_mapping
+(
+     uint32_t owner_id,
+     uint8_t  dscp,
+     uint8_t *q_pri
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] dscp[%d]\n\r",
+               __FUNCTION__,owner_id,dscp);
+    }
+
+    if (NULL == q_pri)
+    {
+        printk(KERN_INFO
+               "%s:%d: null pointer\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    if (dscp > SW_QOS_DSCP_MAX)
+    {
+        printk(KERN_INFO
+               "%s:%d: invalid tag priority\r\n", __FUNCTION__,__LINE__);
+        return ERR_GENERAL;
+    }
+
+    retVal = mv_switch_get_ip_pri_mapping(dscp,q_pri);
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s: q_pri[%d]\n\r",__FUNCTION__,*q_pri);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_broadcast_flood
+*
+* DESCRIPTION:
+*       This function decides whether the switch always floods the broadcast
+*       frames to all portsr or uses the multicast egress mode (per port).
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       always_on  - always floods the broadcast regardless the multicast egress mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_broadcast_flood
+(
+     uint32_t owner_id,
+     bool     always_on
+)
+{
+    tpm_error_code_t retVal;
+    GT_BOOL          lFloodOn;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] always_on[%d]\n\r",
+               __FUNCTION__,owner_id,always_on);
+    }
+
+    if(true == always_on)
+        lFloodOn = GT_TRUE;
+    else
+        lFloodOn = GT_FALSE;
+
+    retVal = mv_switch_set_broadcast_flood(lFloodOn);
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* tpm_sw_get_broadcast_flood
+*
+* DESCRIPTION:
+*       This function gets the global mode of broadcast flood.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       always_on  - always floods the broadcast regardless the multicast egress mode.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_broadcast_flood
+(
+    uint32_t owner_id,
+    bool    *always_on
+)
+{
+    tpm_error_code_t retVal;
+    GT_BOOL          lFloodOn;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d]\n\r",
+               __FUNCTION__,owner_id);
+    }
+
+    retVal = mv_switch_get_broadcast_flood(&lFloodOn);
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if(GT_TRUE == lFloodOn)
+        *always_on = true;
+    else
+        *always_on = false;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s: always_on[%d]\n\r",__FUNCTION__,*always_on);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_flooding()
+*
+* DESCRIPTION:      permit or not the flooding per port
+*
+* INPUTS:
+*   owner_id    - APP owner id  should be used for all API calls.
+*   src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*   flood_mode  - flooding mode.
+*   allow_flood - set to 1 = permit flooding of unknown DA.
+*
+* OUTPUTS:
+*   None.
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_flooding
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_flood_type_t    flood_mode,
+    uint8_t             allow_flood
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          enable;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] src_port[%d] flood_mode[%d], allow_flood[%d]\n\r",
+               __FUNCTION__, owner_id, src_port, flood_mode, allow_flood);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    if(allow_flood == 1)
+    {
+        enable = GT_TRUE;
+    }
+    else
+    {
+        enable = GT_FALSE;
+    }
+
+    switch(flood_mode)
+    {
+        case TPM_FLOOD_UNKNOWN_UNICAST:
+            retVal = mv_switch_set_unknown_unicast_flood(lPort, enable);
+            break;
+        case TPM_FLOOD_UNKNOWN_MULTI_BROAD_CAST:
+            retVal = mv_switch_set_unknown_multicast_flood(lPort, enable);
+            break;
+        default:
+            break;
+    }
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_flooding()
+*
+* DESCRIPTION:      permit or not the flooding per port
+*
+* INPUTS:
+*   owner_id    - APP owner id  should be used for all API calls.
+*   src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*   flood_mode  - flooding mode
+*
+* OUTPUTS:
+*   allow_flood - set to 1 = permit flooding .
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_flooding
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_flood_type_t    flood_mode,
+    uint8_t            *allow_flood
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          enable;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] src_port[%d] flood_mode[%d]\n\r",
+               __FUNCTION__, owner_id, src_port, flood_mode);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    switch(flood_mode)
+    {
+        case TPM_FLOOD_UNKNOWN_UNICAST:
+            retVal = mv_switch_get_unknown_unicast_flood(lPort, &enable);
+            break;
+        case TPM_FLOOD_UNKNOWN_MULTI_BROAD_CAST:
+            retVal = mv_switch_get_unknown_multicast_flood(lPort, &enable);
+            break;
+        default:
+            break;
+    }
+
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n",__FUNCTION__,__LINE__);
+    }
+
+    if(enable == GT_TRUE)
+    {
+        *allow_flood = 1;
+    }
+    else
+    {
+        *allow_flood = 0;
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s: allow_flood[%d]\n\r",__FUNCTION__, *allow_flood);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_convert_port_index()
+*
+* DESCRIPTION: convert switch port index to external port index.
+*
+* INPUTS:
+* owner_id       - APP owner id  should be used for all API calls.
+* switch_port    - switch port index
+*
+* OUTPUTS:
+* extern_port    - external port index
+*
+* RETURNS:
+* On success, the function returns TPM_RC_OK. On error different types are returned
+* according to the case - see tpm_error_code_t.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_convert_port_index (uint32_t             owner_id,
+                                             uint32_t             switch_port,
+                                             tpm_src_port_type_t *extern_port)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] switch_port[%d]\n\r",
+               __FUNCTION__, owner_id, switch_port);
+    }
+
+    *extern_port = tpm_db_phy_convert_port_index(switch_port);
+    if (*extern_port == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) switch_port(%d) is invalid\n", __FUNCTION__, __LINE__, switch_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s: extern_port[%d]\n\r",__FUNCTION__, *extern_port);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_set_port_autoneg_mode
+*
+* DESCRIPTION:
+*       The API Configures the auto negotiation state of an Ethernet UNI port.
+* INPUTS:
+*       owner_id       - APP owner id  should be used for all API calls.
+*       src_port       - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       autoneg_state  - autonegotiation state, enabled or disabled.
+*       autoneg_mode   - enum:
+*                        TPM_SPEED_AUTO_DUPLEX_AUTO: Auto for both speed and duplex
+*                        TPM_SPEED_1000_DUPLEX_AUTO: 1000Mbps and auto duplex
+*                        TPM_SPEED_100_DUPLEX_AUTO:  100Mbps and auto duplex
+*                        TPM_SPEED_10_DUPLEX_AUTO:   10Mbps and auto duplex
+*                        TPM_SPEED_AUTO_DUPLEX_FULL: Auto for speed only and Full duplex
+*                        TPM_SPEED_AUTO_DUPLEX_HALF: Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                        TPM_SPEED_1000_DUPLEX_FULL: 1000Mbps Full duplex.
+*                        TPM_SPEED_1000_DUPLEX_HALF: 1000Mbps half duplex.
+*                        TPM_SPEED_100_DUPLEX_FULL:  100Mbps Full duplex.
+*                        TPM_SPEED_100_DUPLEX_HALF:  100Mbps half duplex.
+*                        TPM_SPEED_10_DUPLEX_FULL:   10Mbps Full duplex.
+*                        TPM_SPEED_10_DUPLEX_HALF:   10Mbps half duplex.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_autoneg_mode
+(
+    uint32_t              owner_id,
+    tpm_src_port_type_t   src_port,
+    bool                  autoneg_state,
+    tpm_autoneg_mode_t    autoneg_mode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL  state, prev_state;
+    GT_PHY_AUTO_MODE prev_mode;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+              "==ENTER==%s: owner_id[%d],src_port[%d],autoneg_state[%d],autoneg_mode[%d]\n\r",
+              __FUNCTION__, owner_id, src_port, autoneg_state, autoneg_mode);
+    }
+
+    if(true == autoneg_state)
+        state = GT_TRUE;
+    else
+        state = GT_FALSE;
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    if (TPM_RC_OK == (retVal = mv_switch_get_port_autoneg_mode(lPort, &prev_state, &prev_mode)))
+    {
+        if (prev_state != state || prev_mode != (GT_PHY_AUTO_MODE)autoneg_mode)
+        {
+            retVal = mv_switch_set_port_autoneg_mode(lPort, state, (GT_PHY_AUTO_MODE)autoneg_mode);
+            if (retVal != TPM_RC_OK)
+            {
+                printk(KERN_ERR
+                       "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+            }
+        }
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_autoneg_mode
+*
+* DESCRIPTION:
+*       The API return the the auto negotiation state of an Ethernet  UNI port.
+* INPUTS:
+*       owner_id       - APP owner id  should be used for all API calls.
+*       src_port       - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       autoneg_state  - autonegotiation state, enabled or disabled.
+*       autoneg_mode   - enum:
+*                        TPM_SPEED_AUTO_DUPLEX_AUTO: Auto for both speed and duplex
+*                        TPM_SPEED_1000_DUPLEX_AUTO: 1000Mbps and auto duplex
+*                        TPM_SPEED_100_DUPLEX_AUTO:  100Mbps and auto duplex
+*                        TPM_SPEED_10_DUPLEX_AUTO:   10Mbps and auto duplex
+*                        TPM_SPEED_AUTO_DUPLEX_FULL: Auto for speed only and Full duplex
+*                        TPM_SPEED_AUTO_DUPLEX_HALF: Auto for speed only and Half duplex. (1000Mbps is not supported)
+*                        TPM_SPEED_1000_DUPLEX_FULL: 1000Mbps Full duplex.
+*                        TPM_SPEED_1000_DUPLEX_HALF: 1000Mbps half duplex.
+*                        TPM_SPEED_100_DUPLEX_FULL:  100Mbps Full duplex.
+*                        TPM_SPEED_100_DUPLEX_HALF:  100Mbps half duplex.
+*                        TPM_SPEED_10_DUPLEX_FULL:   10Mbps Full duplex.
+*                        TPM_SPEED_10_DUPLEX_HALF:   10Mbps half duplex.
+
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_autoneg_mode
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    bool                *autoneg_state,
+    tpm_autoneg_mode_t  *autoneg_mode
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+    GT_PHY_AUTO_MODE mode;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_autoneg_mode(lPort, &state, &mode);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(GT_TRUE == state)
+        *autoneg_state = true;
+    else
+        *autoneg_state = false;
+
+    *autoneg_mode = (tpm_autoneg_mode_t)mode;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s: autoneg_state[%d], autoneg_mode[%d]\n\r", __FUNCTION__, *autoneg_state, *autoneg_mode);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_restart_port_autoneg
+*
+* DESCRIPTION:
+*       The API restart the auto negotiation of an Ethernet  UNI port.
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*        NONE.
+*                                .
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_restart_port_autoneg
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_restart_port_autoneg(lPort);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_set_port_admin_state
+*
+* DESCRIPTION:
+*       The API Configures the PHY port  state of an Ethernet  UNI port.
+* INPUTS:
+*       owner_id        - APP owner id  should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       phy_port_state  - PHY port  state to set.
+*                         0:normal state
+*                         1:power down
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success      -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_admin_state
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    bool                phy_port_state
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL  state, prev_state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],phy_port_state[%d]\n\r",
+               __FUNCTION__,owner_id,src_port,phy_port_state);
+    }
+
+    if(phy_port_state == true)
+        state = GT_TRUE;
+    else
+        state = GT_FALSE;
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    if (TPM_RC_OK == (retVal = mv_switch_get_phy_port_state(lPort, &prev_state)))
+    {
+        if (prev_state != state)
+        {
+            retVal = mv_switch_set_phy_port_state(lPort, state);
+            if (retVal != TPM_RC_OK)
+            {
+                printk(KERN_ERR
+                       "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+            }
+        }
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_admin_state
+*
+* DESCRIPTION:
+*       The API return the PHY port  state of an Ethernet  UNI port.
+* INPUTS:
+*       owner_id         - APP owner id  should be used for all API calls.
+*       src_port         - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       phy_port_state   -  0:normal state
+*                           1:power down                                    .
+*
+* RETURNS:
+*       On success       -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_admin_state
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    bool               *phy_port_state
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_phy_port_state(lPort, &state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(state == GT_TRUE)
+        *phy_port_state = true;
+    else
+        *phy_port_state = false;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: phy_port_state[%d]\n\r",__FUNCTION__,*phy_port_state);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_link_status
+*
+* DESCRIPTION:
+*       The API return realtime port link status of an Ethernet  UNI port.
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       port_link_status  -  0:port link is ON
+*                            1:port link is DOWN                                    .
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_link_status
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    bool                *port_link_status
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_link_status(lPort, &state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(state == GT_TRUE)
+        *port_link_status = true;
+    else
+        *port_link_status = false;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+               "==EXIT== %s: port_link_status[%d]\n\r",__FUNCTION__,*port_link_status);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_duplex_status
+*
+* DESCRIPTION:
+*       The API return realtime port duplex status of an Ethernet  UNI port.
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       port_duplex_status  -  0:half deplex mode
+*                              1:full deplex mode                    .
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_duplex_status
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    bool                *port_duplex_status
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_duplex_status(lPort, &state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(state == GT_TRUE)
+        *port_duplex_status = true;
+    else
+        *port_duplex_status = false;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: port_duplex_status[%d]\n\r",__FUNCTION__,*port_duplex_status);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_speed_mode
+*
+* DESCRIPTION:
+*       The API return realtime port speed mode of an Ethernet  UNI port.
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       port_duplex_status  -  0:10M
+*                              1:100M
+*                              2:1000M
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_speed_mode
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t            *speed
+)
+{
+    tpm_error_code_t   retVal = TPM_RC_OK;
+    int32_t            lPort  = 0;
+    GT_PORT_SPEED_MODE tmpSpeed;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_speed_mode(lPort, &tmpSpeed);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    *speed = (uint32_t)tmpSpeed;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: speed[%d]\n\r",__FUNCTION__,*speed);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_set_port_flow_control_support
+*
+* DESCRIPTION:
+*       This routine will set the pause bit in Autonegotiation Advertisement
+*        Register. And restart the autonegotiation.
+*
+* INPUTS:
+*       owner_id   - APP owner id  should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       state      - false:port pause is off.
+*                    true:port pause is on.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+tpm_error_code_t tpm_phy_set_port_flow_control_support
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    bool                state
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_PHY_PAUSE_MODE pause_state, prev_state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],state[%d]\n\r",
+               __FUNCTION__,owner_id,src_port,state);
+    }
+
+    if(state == true)
+        pause_state = GT_PHY_PAUSE;
+    else
+        pause_state = GT_PHY_NO_PAUSE;
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    if (TPM_RC_OK == (retVal = mv_switch_get_port_pause(lPort, &prev_state)))
+    {
+        if (prev_state != pause_state)
+        {
+            retVal = mv_switch_set_port_pause(lPort, pause_state);
+            if (retVal != TPM_RC_OK)
+            {
+                printk(KERN_ERR
+                       "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+            }
+        }
+    }
+
+    //retVal = mv_switch_restart_port_autoneg(port);
+    // if (retVal != TPM_RC_OK)
+    // {
+    //     printk(KERN_ERR
+    //            "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    // }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_flow_control_support
+* DESCRIPTION:
+*       This routine will get the pause bit in Autonegotiation Advertisement
+*        Register.
+*
+* INPUTS:
+*       owner_id   - APP owner id  should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS
+*       state      -  false:port pause is off.
+*                      true:port pause is on.
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+tpm_error_code_t tpm_phy_get_port_flow_control_support
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    bool               *state
+)
+{
+    tpm_error_code_t  retVal = TPM_RC_OK;
+    int32_t           lPort  = 0;
+    GT_PHY_PAUSE_MODE pause_state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_pause(lPort, &pause_state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(pause_state == GT_PHY_NO_PAUSE)
+        *state = false;
+    else
+        *state = true;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: flow_control[%d]\n\r",__FUNCTION__,*state);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_flow_control_state
+*
+* DESCRIPTION:
+*     This routine will get the current pause state.
+*        Register.
+*
+* INPUTS:
+*       owner_id   - APP owner id  should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*        state     -
+*                   false: MAC Pause not implemented in the link partner or in MyPause
+*                   true:  MAC Pause is implemented in the link partner and in MyPause
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case, see tpm_error_code_t.
+* COMMENTS:
+*       None.
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_flow_control_state
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    bool               *state
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          fc_state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_pause_state(lPort, &fc_state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(fc_state == GT_FALSE)
+        *state = false;
+    else
+        *state = true;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: flow_control_state[%d]\n\r",__FUNCTION__,*state);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_set_port_loopback
+*
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode        - Internal or external loopback
+*       enable      - If GT_TRUE, enable loopback mode
+*                     If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_loopback
+(
+    uint32_t                owner_id,
+    tpm_src_port_type_t     src_port,
+    tpm_phy_loopback_mode_t mode,
+    bool                    enable
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state, link_forced;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],mode[%d], enable[%d]\n\r",
+               __FUNCTION__,owner_id, src_port, mode, (uint32_t)enable);
+    }
+
+    if(enable == true)
+    {
+        state = GT_TRUE;
+    }
+    else
+    {
+        state = GT_FALSE;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    switch((GT_PHY_LOOPBACK_MODE)mode)
+    {
+        case PHY_INTERNAL_LOOPBACK:
+            if (lPort == INT_GE_PHY_SWITCH_PORT)
+            {
+                retVal = mv_switch_get_port_forced_link(lPort, &link_forced);
+                if (retVal != TPM_RC_OK)
+                {
+                    printk(KERN_ERR
+                           "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                    break;
+                }
+                if (((state == GT_TRUE) && (link_forced == GT_FALSE)) ||
+                    ((state == GT_FALSE)&& (link_forced == GT_TRUE)))
+                {
+                    retVal = mv_switch_set_port_forced_link(lPort, state);
+                    if (retVal != TPM_RC_OK)
+                    {
+                        printk(KERN_ERR
+                               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                        break;
+                    }
+                    retVal = mv_switch_set_port_link_value(lPort, state);
+                    if (retVal != TPM_RC_OK)
+                    {
+                        printk(KERN_ERR
+                               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+                        break;
+                    }
+                }
+            }
+            retVal = mv_switch_set_port_loopback(lPort, state);
+            break;
+        case PHY_EXTERNAL_LOOPBACK:
+            retVal = mv_switch_set_port_line_loopback(lPort, state);
+            break;
+        default:
+            break;
+
+    }
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_loopback
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode        - Internal or external loopback
+*
+* OUTPUTS:
+*       enable      - If GT_TRUE,  loopback mode is enabled
+*                     If GT_FALSE,  loopback mode is disabled
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_loopback
+(
+    uint32_t                owner_id,
+    tpm_src_port_type_t     src_port,
+    tpm_phy_loopback_mode_t mode,
+    bool                   *enable
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d], mode[%d]\n\r",
+               __FUNCTION__,owner_id,src_port, mode);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    switch((GT_PHY_LOOPBACK_MODE)mode)
+    {
+        case PHY_INTERNAL_LOOPBACK:
+           retVal = mv_switch_get_port_loopback(lPort, &state);
+            break;
+        case PHY_EXTERNAL_LOOPBACK:
+            retVal = mv_switch_get_port_line_loopback(lPort, &state);
+            break;
+        default:
+            break;
+    }
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if(state == GT_TRUE)
+    {
+        *enable = true;
+    }
+    else
+    {
+        *enable = false;
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: enable[%d]\n\r",__FUNCTION__,(uint32_t)*enable);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_set_port_duplex_mode
+*
+* DESCRIPTION:
+*        Sets duplex mode for a specific logical port. This function will keep
+*        the speed and loopback mode to the previous value, but disable others,
+*        such as Autonegotiation.
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       enable      - Enable/Disable dulpex mode
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*         data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_set_port_duplex_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    bool                enable
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],enable[%d]\n\r",
+               __FUNCTION__,owner_id,src_port,(uint32_t)enable);
+    }
+
+    if(enable == true)
+    {
+        state = GT_TRUE;
+    }
+    else
+    {
+        state = GT_FALSE;
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_port_duplex_mode(lPort, state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_duplex_mode
+*
+* DESCRIPTION:
+*         Gets duplex mode for a specific logical port.
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+
+*
+* OUTPUTS:
+*       enable      - Enable/Disable dulpex mode
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*         data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_duplex_mode
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    bool                *enable
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_BOOL          state;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_duplex_mode(lPort, &state);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:enable[%d]\n\r",__FUNCTION__,  *enable);
+    }
+
+
+    if(state == GT_TRUE)
+    {
+        *enable = true;
+    }
+    else
+    {
+        *enable = false;
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_set_port_speed
+*
+* DESCRIPTION:
+*       This routine will disable auto-negotiation and set the PHY port speed .
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       speed       -    PHY_SPEED_10_MBPS   - 10Mbps
+*                        PHY_SPEED_100_MBPS  - 100Mbps
+*                        PHY_SPEED_1000_MBPS - 1000Mbps.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+
+tpm_error_code_t tpm_phy_set_port_speed
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_phy_speed_t     speed
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d],speed[%d]\n\r",
+               __FUNCTION__,owner_id,src_port, (uint32_t)speed);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_set_port_speed(lPort, (GT_PHY_SPEED)speed);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_phy_get_port_speed
+*
+* DESCRIPTION:
+*       This routine will get current PHY port speed .
+*
+* INPUTS:
+*       owner_id    - APP owner id  should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+
+*
+*
+* OUTPUTS:
+*        speed      -    PHY_SPEED_10_MBPS   -10Mbps
+*                        PHY_SPEED_100_MBPS  -100Mbps
+*                        PHY_SPEED_1000_MBPS -1000Mbps.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_phy_get_port_speed
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_phy_speed_t    *speed
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_PHY_SPEED     lSpeed;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id,src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_speed(lPort, &lSpeed);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    *speed = (tpm_phy_speed_t)lSpeed;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s: speed[%d]\n\r",__FUNCTION__,(uint32_t)*speed);
+    }
+
+    return retVal;
+}
+
+/*------------------------------------------------------------------------------
+                            Debug functions
+------------------------------------------------------------------------------*/
+
+
+/*******************************************************************************
+* tpm_sw_prv_clear_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_prv_clear_port_counters
+(
+    void
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s:\n\r",__FUNCTION__);
+    }
+
+    retVal = mv_switch_clear_port_counters();
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_global_reg
+*
+* DESCRIPTION:
+*       This function sets value to the global register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_global_reg
+(
+    uint32_t owner_id,
+    uint8_t  regAddr,
+    uint16_t data
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] regAddr[0x%x] data[0x%x]\n\r",
+               __FUNCTION__,owner_id, regAddr, data);
+    }
+
+    retVal = mv_switch_set_global_reg (regAddr, data);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_global_reg
+*
+* DESCRIPTION:
+*       This function gets value from the global register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_global_reg
+(
+     uint32_t owner_id,
+     uint8_t  regAddr,
+    uint16_t *data
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d] regAddr[0x%x]\n\r",
+               __FUNCTION__,owner_id, regAddr);
+    }
+
+    retVal = mv_switch_get_global_reg (regAddr, data);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:,data[0x%x]\n\r",__FUNCTION__,*data);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_set_port_reg
+*
+* DESCRIPTION:
+*       This function sets value to the port register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_reg
+(
+     uint32_t owner_id,
+     uint8_t  lport,
+     uint8_t  regAddr,
+     uint16_t data
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d] lport[%d] regAddr[0x%x] data[0x%x]\n\r",
+                __FUNCTION__,lport, owner_id, regAddr, data);
+    }
+
+    retVal = mv_switch_set_port_reg (lport, regAddr, data);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_get_port_reg
+*
+* DESCRIPTION:
+*       This function gets value from the port register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+*       data        - The data to be written.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_reg
+(
+     uint32_t  owner_id,
+     uint8_t   lport,
+     uint8_t   regAddr,
+     uint16_t *data
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d] lport[%d] regAddr[0x%x]\n\r",
+                __FUNCTION__,owner_id,lport, regAddr);
+    }
+
+    retVal = mv_switch_get_port_reg (lport, regAddr, data);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:,data[0x%x]\n\r",__FUNCTION__,*data);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_print_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        Clear on read.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_print_port_counters
+(
+     uint32_t owner_id,
+     uint8_t  lport
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d] lport[%d]\n\r",
+                __FUNCTION__,owner_id,lport);
+    }
+
+    retVal = mv_switch_print_port_counters(lport);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+        return retVal;
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_clear_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id    - APP owner id , should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_clear_port_counters
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s:\n\r",__FUNCTION__);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_clean_port_counters(lPort);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_pm_1_read
+*
+*
+* INPUTS:
+*       wner_id         - APP owner id  should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       tpm_swport_pm_3 - Holds PM data
+*
+* OUTPUTS:
+*       PM data is supplied structure.
+*
+* RETURNS:
+* TPM_RC_OK - on success, else error code
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_1_read
+(
+     uint32_t             owner_id,
+     tpm_src_port_type_t  src_port,
+     tpm_swport_pm_1_t   *tpm_swport_pm_1
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_STATS_COUNTER_SET3 statsCounterSet;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id, src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_counters(lPort, &statsCounterSet);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    tpm_swport_pm_1->fcsErrors                       = statsCounterSet.InFCSErr;
+    tpm_swport_pm_1->excessiveCollisionCounter       = statsCounterSet.Excessive;
+    tpm_swport_pm_1->lateCollisionCounter            = statsCounterSet.Late;
+    tpm_swport_pm_1->frameTooLongs                   = statsCounterSet.Oversize;
+    tpm_swport_pm_1->bufferOverflowsOnReceive        = 0;
+    tpm_swport_pm_1->bufferOverflowsOnTransmit       = 0;
+    tpm_swport_pm_1->singleCollisionFrameCounter     = statsCounterSet.Single;
+    tpm_swport_pm_1->multipleCollisionsFrameCounter  = statsCounterSet.Multiple;
+    tpm_swport_pm_1->sqeCounter                      = 0;
+    tpm_swport_pm_1->deferredTransmissionCounter     = statsCounterSet.Deferred;
+    tpm_swport_pm_1->internalMacTransmitErrorCounter = 0;
+    tpm_swport_pm_1->carrierSenseErrorCounter        = 0;
+    tpm_swport_pm_1->alignmentErrorCounter           = 0;
+    tpm_swport_pm_1->internalMacReceiveErrorCounter  = statsCounterSet.InMACRcvErr;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_pm_3_read
+*
+*
+* INPUTS:
+*       owner_id        - APP owner id  should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       tpm_swport_pm_3 - Holds PM data
+*
+* OUTPUTS:
+*       PM data is supplied structure.
+*
+* RETURNS:
+* TPM_RC_OK - on success, else error code
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_3_read
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_swport_pm_3_t  *tpm_swport_pm_3
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+    GT_STATS_COUNTER_SET3 statsCounterSet;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id, src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_get_port_counters(lPort, &statsCounterSet);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    tpm_swport_pm_3->dropEvents              = 0;
+    tpm_swport_pm_3->octets                  = statsCounterSet.InGoodOctetsLo;
+    tpm_swport_pm_3->packets                 = statsCounterSet.InUnicasts;
+    tpm_swport_pm_3->broadcastPackets        = statsCounterSet.InBroadcasts;
+    tpm_swport_pm_3->multicastPackets        = statsCounterSet.InMulticasts;
+    tpm_swport_pm_3->undersizePackets        = 0;
+    tpm_swport_pm_3->fragments               = statsCounterSet.Fragments;
+    tpm_swport_pm_3->jabbers                 = statsCounterSet.Jabber;
+    tpm_swport_pm_3->packets_64Octets        = statsCounterSet.Octets64;
+    tpm_swport_pm_3->packets_65_127Octets    = statsCounterSet.Octets127;
+    tpm_swport_pm_3->packets_128_255Octets   = statsCounterSet.Octets255;
+    tpm_swport_pm_3->packets_256_511Octets   = statsCounterSet.Octets511;
+    tpm_swport_pm_3->packets_512_1023Octets  = statsCounterSet.Octets1023;
+    tpm_swport_pm_3->packets_1024_1518Octets = statsCounterSet.OctetsMax;
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_clear_port_counter
+*
+* DESCRIPTION:
+*       The API clear port pm counter.
+*
+* INPUTS:
+*       owner_id    - APP owner id should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       none.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case  see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+
+tpm_error_code_t tpm_sw_clear_port_counter
+(
+     uint32_t            owner_id,
+     tpm_src_port_type_t src_port
+)
+{
+    tpm_error_code_t retVal = TPM_RC_OK;
+    int32_t          lPort  = 0;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s: owner_id[%d],src_port[%d]\n\r",
+               __FUNCTION__,owner_id, src_port);
+    }
+
+    lPort = tpm_db_eth_port_switch_port_get(src_port);
+    if (lPort == TPM_DB_ERR_PORT_NUM)
+    {
+        printk(KERN_ERR "ERROR: (%s:%d) source port(%d) is invalid\n", __FUNCTION__, __LINE__, src_port);
+        return ERR_SRC_PORT_INVALID;
+    }
+
+    retVal = mv_switch_clean_port_counters(lPort);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+/*******************************************************************************
+* tpm_sw_get_fdb
+*
+* DESCRIPTION:
+*       This function gets all FDB table.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       db_num      - ATU MAC Address Database number. If multiple address
+*                     databases are not being used, DBNum should be zero.
+*                     If multiple address databases are being used, this value
+*                     should be set to the desired address database number.
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_fdb
+(
+     uint32_t owner_id,
+     uint16_t db_num
+)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==ENTER==%s: owner_id[%d] db_num[%d]\n\r",
+                __FUNCTION__,owner_id,db_num);
+    }
+
+    retVal =  mv_switch_print_fdb(db_num);
+    if ((retVal != TPM_RC_OK) && (retVal != GT_NO_SUCH))
+    {
+        printk(KERN_INFO
+               "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s:\n\r",__FUNCTION__);
+    }
+
+    return retVal;
+}
+/*******************************************************************************
+* tpm_sw_flush_vtu
+*
+* DESCRIPTION:
+*       Flush VTU on the Switch
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_flush_vtu(uint32_t owner_id)
+{
+    tpm_error_code_t retVal;
+
+    SWITCH_INIT_CHECK();
+
+    retVal = mv_switch_flush_vtu();
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+              "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    return retVal;
+}
+/*******************************************************************************
+* tpm_sw_flush_atu
+*
+* DESCRIPTION:
+*       Flush ATU on the Switch
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       flush_type  - FLUSH all or FLUSH all dynamic
+*       db_num      - ATU DB Num, only 0 should be used, since there is only one ATU DB right now.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_flush_atu(uint32_t owner_id, tpm_flush_atu_type_t flush_type, uint16_t db_num)
+{
+    tpm_error_code_t retVal;
+    GT_FLUSH_CMD flush_cmd;
+
+    SWITCH_INIT_CHECK();
+
+    if (TPM_FLUSH_ATU_ALL == flush_type)
+        flush_cmd = GT_FLUSH_ALL;
+    else
+        flush_cmd = GT_FLUSH_ALL_UNLOCKED;
+
+    if (0 != db_num)
+    {
+        printk(KERN_ERR
+              "%s:%d: function failed, db_num should be 0\r\n", __FUNCTION__,__LINE__);
+    }
+
+    retVal = mv_switch_flush_atu(flush_cmd, db_num);
+    if (retVal != TPM_RC_OK)
+    {
+        printk(KERN_ERR
+              "%s:%d: function failed\r\n", __FUNCTION__,__LINE__);
+    }
+
+    return retVal;
+}
+
+/*******************************************************************************
+* tpm_sw_init
+*
+* DESCRIPTION:
+*       This function init all parameters
+*
+* INPUTS:
+*       NONE.
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       NONE
+*
+* COMMENTS:
+*        There is a temprorary function.
+*
+*******************************************************************************/
+void tpm_sw_init
+(
+    void
+)
+{
+    int32_t int_ret;
+    uint32_t switch_init;
+
+    int_ret = tpm_db_switch_init_get(&switch_init);
+    if (int_ret)
+        printk(KERN_INFO "tpm_db_switch_init_get failed\n");
+    if (!switch_init) {
+        printk(KERN_INFO "switch is not allowed to init\n");
+        return;
+    }
+
+    if (trace_sw_dbg_flag)
+    {
+       printk(KERN_INFO
+               "==ENTER==%s:\n\r",__FUNCTION__);
+    }
+
+    mv_switch_drv_init();
+
+    if (trace_sw_dbg_flag)
+    {
+        printk(KERN_INFO
+                "==EXIT== %s\n\r",__FUNCTION__);
+    }
+}
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.h
new file mode 100755
index 0000000..2026e27
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tpm/plat/tpm_switch_mgr.h
@@ -0,0 +1,1065 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/******************************************************************************
+* mv_tpm_sw_config.h
+*
+*
+*  MODULE : TPM Switch
+*
+*  DESCRIPTION : This file config tpm switch
+*
+*  MODIFICATION HISTORY:
+*           28Apr2010   DimaM  - initial version created.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1.27 $
+*******************************************************************************/
+
+#ifndef __INC_TPM_SW_CONFIG
+#define __INC_TPM_SW_CONFIG
+
+#define PORT_SCHED_MODE_WRRB     (0)
+#define PORT_SCHED_MODE_SPRI     (1)
+#define PORT_SCHED_MODE_SPRI3    (2)
+#define PORT_SCHED_MODE_SPRI2_3  (3)
+
+#define SW_QOS_NUM_OF_QUEUES     (4)
+
+#define INT_GE_PHY_SWITCH_PORT   (0)
+
+/*******************************************************************************
+* tpm_sw_set_static_mac_w_ports_mask
+*
+* DESCRIPTION:
+*       This function creates or destory a static MAC entry in the MAC address
+*       table for several specific ports in the integrated switch
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       ports_mask  - Ports mask.
+*       static_mac  - 6byte network order MAC source address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_static_mac_w_ports_mask
+(
+    uint32_t    owner_id,
+    uint32_t    ports_mask,
+    uint8_t     static_mac[6]
+);
+
+/*******************************************************************************
+* tpm_sw_get_port_max_macs
+*
+* DESCRIPTION:
+*        Port's auto learning limit. When the limit is non-zero value, the number
+*        of MAC addresses that can be learned on this lport are limited to the value
+*        specified in this API. When the learn limit has been reached any frame
+*        that ingresses this lport with a source MAC address not already in the
+*        address database that is associated with this lport will be discarded.
+*        Normal auto-learning will resume on the lport as soon as the number of
+*        active unicast MAC addresses associated to this lport is less than the
+*        learn limit.
+*        CPU directed ATU Load, Purge, or Move will not have any effect on the
+*        learn limit.
+*        This feature is disabled when the limit is zero.
+*        The following care is needed when enabling this feature:
+*            1) dsable learning on the ports
+*            2) flush all non-static addresses in the ATU
+*            3) define the desired limit for the ports
+*            4) re-enable learing on the ports
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       limit       - maximum number of MAC addresses per lport (1-255).
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_max_macs
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t           *limit
+);
+
+
+/*******************************************************************************
+* tpm_sw_port_get_vid
+*
+* DESCRIPTION:
+*       The API return VID to the list of the allowed VIDs per lport.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       vid        -  searching VID.
+*
+* OUTPUTS:
+*       found      - GT_TRUE, if the appropriate entry exists.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_port_get_vid
+(
+    uint32_t  owner_id,
+    uint32_t  vid,
+    uint32_t *found
+);
+
+
+/*******************************************************************************
+* tpm_sw_get_vid_filter_per_port
+*
+* DESCRIPTION:
+*        This routine gets protected mode of a switch lport.
+*        When this mode is set to GT_TRUE, frames are allowed to egress lport
+*        defined by the 802.1Q VLAN membership for the frame's VID 'AND'
+*        by the lport's VLANTable if 802.1Q is enabled on the lport. Both must
+*        allow the frame to Egress.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       mode       - GT_TRUE: header mode enabled
+*                    GT_FALSE otherwise
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_vid_filter_per_port
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t           *mode
+);
+
+/*******************************************************************************
+* tpm_sw_get_uni_tc_ingr_police_rate
+*
+* DESCRIPTION:
+*       This routine gets the lport's ingress data limit for priority 0 or 1 or 2 or 3 frames.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       src_port   - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*
+*       tc         - traffic class ( a combination of p-bits and DSCP values).
+*       cir        - comited info rate.
+*       cbs        - comited burst rate
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_uni_tc_ingr_police_rate
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t            *tc,
+    uint32_t            *cir,
+    uint32_t            *cbs
+);
+
+/*******************************************************************************
+* tpm_sw_get_uni_egr_rate_limit
+*
+* DESCRIPTION:
+*       The API return the egress frame rate limit of an Ethernet UNI lport
+* INPUTS:
+*       owner_id        - APP owner id - should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       mode            - frame/rate limit mode
+*       rate_limit_val  - egress rate limit value..
+*
+* RETURNS:
+*       On success      - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       GT_ERATE_TYPE used kbRate - frame rate valid values are:
+*                                    7600,..., 9600,
+*                                    10000, 20000, 30000, 40000, ..., 100000,
+*                                    110000, 120000, 130000, ..., 1000000.
+
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_uni_egr_rate_limit
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    tpm_limit_mode_t    *mode,
+    uint32_t            *frame_rate_limit_val
+);
+
+/*******************************************************************************
+* tpm_sw_set_atu_size
+*
+* DESCRIPTION:
+*       This function Sets the Mac address table size.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       size        - Table size
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        size 0(256) - 5(8192)
+*                256 entries Mac address table.
+*                512 entries Mac address table.
+*                1024 entries Mac address table.
+*                2048 entries Mac address table.
+*                4096 entries Mac address table.
+*                8192 entries Mac address table.
+*******************************************************************************/
+
+tpm_error_code_t tpm_sw_set_atu_size
+(
+    uint32_t    owner_id,
+    uint32_t    size
+);
+
+/*******************************************************************************
+* tpm_sw_set_port_vlan_ports
+*
+* DESCRIPTION:
+*       This routine sets the port VLAN group port membership list.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_vlan_ports
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t            memPorts[],
+    uint8_t             memPortsLen
+);
+
+/*******************************************************************************
+* tpm_sw_get_port_vlan_ports
+*
+* DESCRIPTION:
+*       This routine gets the port VLAN group port membership list.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+* RETURNS:
+*       On success  - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_vlan_ports
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint32_t             memPorts[],
+    uint8_t             *memPortsLen
+);
+
+/*******************************************************************************
+* tpm_sw_set_ingress_limit_mode
+*
+* DESCRIPTION:
+*       This routine sets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       mode         - rate control ingress limit mode.
+*
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success   - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*    GT_LIMT_ALL = 0,        limit and count all frames
+*    GT_LIMIT_FLOOD,         limit and count Broadcast, Multicast and flooded unicast frames
+*    GT_LIMIT_BRDCST_MLTCST, limit and count Broadcast and Multicast frames
+*    GT_LIMIT_BRDCST         limit and count Broadcast frames
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_ingress_limit_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t            mode
+);
+
+/*******************************************************************************
+* tpm_sw_get_ingress_limit_mode
+*
+* DESCRIPTION:
+*       This routine gets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       owner_id     - APP owner id - should be used for all API calls.
+*       src_port     - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+*
+* OUTPUTS:
+*        mode        - rate control ingress limit mode.
+*
+* RETURNS:
+*       On success   -  TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*    GT_LIMT_ALL = 0,        limit and count all frames
+*    GT_LIMIT_FLOOD,         limit and count Broadcast, Multicast and flooded unicast frames
+*    GT_LIMIT_BRDCST_MLTCST, limit and count Broadcast and Multicast frames
+*    GT_LIMIT_BRDCST         limit and count Broadcast frames
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_ingress_limit_mode
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint32_t           *mode
+);
+
+/*******************************************************************************
+* tpm_sw_set_priority_selection
+*
+* DESCRIPTION:
+*       This function sets initial QPri and FPri selection.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_priority_selection
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    uint8_t             init_pri,
+    bool                tag_if_both
+);
+
+/*******************************************************************************
+* tpm_sw_get_priority_selection
+*
+* DESCRIPTION:
+*       This function gets initial QPri and FPri selection.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       init_pri    - Initial QPri and FPri selection type.
+*       tag_if_both - Use Tag information for the initial QPri assignment if the frame is both
+*                     tagged and its also IPv4 or IPv6 and if InitialPri uses Tag & IP priority.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       PRI_SEL_USE_PORTS_DEF  - 0
+*       PRI_SEL_TAG_PRI_ONLY   - 1
+*       PRI_SEL_IP_PRI_ONLY    - 2
+*       PRI_SEL_TAG_AND_IP_PRI - 3
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_priority_selection
+(
+    uint32_t             owner_id,
+    tpm_src_port_type_t  src_port,
+    uint8_t             *init_pri,
+    bool                *tag_if_both
+);
+
+/*******************************************************************************
+* tpm_sw_set_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This function maps a tag priority to a queue priority.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       tag_pri     - Source tag priority number.
+*       q_pri       - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_tag_pri_mapping
+(
+     uint32_t owner_id,
+     uint8_t  tag_pri,
+     uint8_t  q_pri
+);
+
+/*******************************************************************************
+* tpm_sw_get_tag_pri_mapping
+*
+* DESCRIPTION:
+*       This function gets the queue priority for a tag priority mapping to.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       tag_pri    - Source tag priority number.
+*
+* OUTPUTS:
+*       q_pri      - Target queue priority number.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       tag_pri 0-7.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_tag_pri_mapping
+(
+    uint32_t owner_id,
+    uint8_t  tag_pri,
+    uint8_t *q_pri
+);
+
+/*******************************************************************************
+* tpm_sw_set_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This function maps a dscp value to a queue priority.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       dscp       - Source dscp value.
+*       q_pri      - Target queue priority number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_ip_pri_mapping
+(
+     uint32_t owner_id,
+     uint8_t  dscp,
+     uint8_t  q_pri
+);
+
+/*******************************************************************************
+* tpm_sw_get_ip_pri_mapping
+*
+* DESCRIPTION:
+*       This function gets the queue priority for a dscp value mapping to.
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*       dscp       - Source dscp value.
+*
+* OUTPUTS:
+*       q_pri      - Target queue priority number.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       dscp    0-63.
+*       q_pri   0-3.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_ip_pri_mapping
+(
+    uint32_t owner_id,
+    uint8_t  dscp,
+    uint8_t *q_pri
+);
+
+/*******************************************************************************
+* tpm_sw_set_broadcast_flood
+*
+* DESCRIPTION:
+*       This function decides whether the switch always floods the broadcast
+*       frames to all portsr or uses the multicast egress mode (per port).
+*
+* INPUTS:
+*       owner_id - APP owner id - should be used for all API calls.
+*       always_on - always floods the broadcast regardless the multicast egress mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_broadcast_flood
+(
+     uint32_t owner_id,
+     bool     always_on
+);
+
+/*******************************************************************************
+* tpm_sw_get_broadcast_flood
+*
+* DESCRIPTION:
+*       This function gets the global mode of broadcast flood.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       always_on - always floods the broadcast regardless the multicast egress mode.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_broadcast_flood
+(
+     uint32_t owner_id,
+     bool    *always_on
+);
+
+/*------------------------------------------------------------------------------
+                            Debug functions
+------------------------------------------------------------------------------*/
+
+/*******************************************************************************
+* tpm_sw_set_global_reg
+*
+* DESCRIPTION:
+*       This function sets value to the global register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_global_reg
+(
+    uint32_t             owner_id,
+    uint8_t              regAddr,
+    uint16_t             data
+);
+
+/*******************************************************************************
+* tpm_sw_get_global_reg
+*
+* DESCRIPTION:
+*       This function gets value from the global register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_global_reg
+(
+     uint32_t             owner_id,
+     uint8_t              regAddr,
+    uint16_t             *data
+);
+
+/*******************************************************************************
+* tpm_sw_set_port_reg
+*
+* DESCRIPTION:
+*       This function sets value to the port register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*       data        - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_port_reg
+(
+     uint32_t            owner_id,
+     uint8_t             lport,
+     uint8_t             regAddr,
+     uint16_t            data
+);
+
+/*******************************************************************************
+* tpm_sw_get_port_reg
+*
+* DESCRIPTION:
+*       This function gets value from the port register.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*       regAddr     - The register's address.
+*
+* OUTPUTS:
+*       data        - The data to be written.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_port_reg
+(
+     uint32_t            owner_id,
+     uint8_t             lport,
+     uint8_t             regAddr,
+    uint16_t            *data
+);
+
+/*******************************************************************************
+* tpm_sw_get_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_print_port_counters
+(
+     uint32_t            owner_id,
+     uint8_t             lport
+);
+
+/*******************************************************************************
+* tpm_sw_clear_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id    - APP owner id , should be used for all API calls.
+*       src_port    - Source port in UNI port index, UNI0, UNI1...UNI4.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_clear_port_counters
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port
+);
+
+/*******************************************************************************
+* tpm_sw_pm_1_read
+*
+*
+* INPUTS:
+*       wner_id         - APP owner id should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       tpm_swport_pm_3 - Holds PM data
+*
+* OUTPUTS:
+*       PM data is supplied structure.
+*
+* RETURNS:
+* TPM_RC_OK - on success, else error code
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_1_read
+(
+     uint32_t             owner_id,
+     tpm_src_port_type_t  src_port,
+     tpm_swport_pm_1_t   *tpm_swport_pm_1
+);
+
+/*******************************************************************************
+* tpm_sw_pm_3_read
+*
+*
+* INPUTS:
+*       owner_id        - APP owner id should be used for all API calls.
+*       src_port        - Source port in UNI port index, UNI0, UNI1...UNI4.
+*       tpm_swport_pm_3 - Holds PM data
+*
+* OUTPUTS:
+*       PM data is supplied structure.
+*
+* RETURNS:
+* TPM_RC_OK - on success, else error code
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_pm_3_read
+(
+    uint32_t            owner_id,
+    tpm_src_port_type_t src_port,
+    tpm_swport_pm_3_t  *tpm_swport_pm_3
+);
+
+/*******************************************************************************
+* tpm_sw_prv_clear_port_counters
+*
+* DESCRIPTION:
+*       This function gets all counters of the given port
+*
+* INPUTS:
+*       owner_id    - APP owner id , should be used for all API calls.
+*       lport       - Port number to write the register for.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case , see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_prv_clear_port_counters
+(
+    void
+);
+
+/*******************************************************************************
+* tpm_sw_get_fdb
+*
+* DESCRIPTION:
+*       This function gets all FDB table.
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       db_num      - ATU MAC Address Database number. If multiple address
+*                     databases are not being used, DBNum should be zero.
+*                     If multiple address databases are being used, this value
+*                     should be set to the desired address database number.
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_get_fdb
+(
+     uint32_t            owner_id,
+     uint16_t            db_num
+);
+/*******************************************************************************
+* tpm_sw_flush_vtu
+*
+* DESCRIPTION:
+*       Flush VTU on the Switch
+*
+* INPUTS:
+*       owner_id   - APP owner id - should be used for all API calls.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_flush_vtu(uint32_t owner_id);
+
+/*******************************************************************************
+* tpm_sw_flush_atu
+*
+* DESCRIPTION:
+*       Flush ATU on the Switch
+*
+* INPUTS:
+*       owner_id    - APP owner id - should be used for all API calls.
+*       flush_type  - FLUSH all or FLUSH all dynamic
+*       db_num      - ATU DB Num, only 0 should be used, since there is only one ATU DB right now.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_flush_atu(uint32_t owner_id, tpm_flush_atu_type_t flush_type, uint16_t db_num);
+
+/*******************************************************************************
+* tpm_sw_init
+*
+* DESCRIPTION:
+*       This function init all parameters
+*
+* INPUTS:
+*       NONE.
+*
+* OUTPUTS:
+*       NONE.
+*
+* RETURNS:
+*       NONE
+*
+* COMMENTS:
+*        There is a temprorary function.
+*
+*******************************************************************************/
+void tpm_sw_init
+(
+    void
+);
+
+/*******************************************************************************
+* tpm_sw_set_debug_trace_flag
+*
+* DESCRIPTION:
+*       This function sets TPM trace flag.
+*
+* INPUTS:
+*       enDis    - enable or disable
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       On success - TPM_RC_OK.
+*       On error different types are returned according to the case - see tpm_error_code_t.
+*
+* COMMENTS:
+*        NONE.
+*
+*******************************************************************************/
+tpm_error_code_t tpm_sw_set_debug_trace_flag
+(
+     uint32_t            enDis
+);
+
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/Makefile
new file mode 100755
index 0000000..0264247
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the Marvell XOR/DMA Driver
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+ifeq ($(CONFIG_ARCH_ARMADA_XP),y)
+	include $(srctree)/arch/arm/mach-armadaxp/config/mvRules.mk
+endif
+
+obj-$(CONFIG_MV_DBG_TRACE) += dbg-trace.o
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/dbg-trace.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/dbg-trace.c
new file mode 100755
index 0000000..b4c847b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/dbg-trace.c
@@ -0,0 +1,337 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/capability.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/platform_device.h>
+#include "mvCommon.h"
+#include "dbg-trace.h"
+
+#define TRACE_ARR_LEN   800
+#define STR_LEN         128
+
+static inline int mv_trace_next_idx(int idx)
+{
+	idx++;
+	if (idx == TRACE_ARR_LEN)
+		idx = 0;
+
+	return idx;
+}
+
+static inline int mv_trace_prev_idx(int idx)
+{
+	if (idx == 0)
+		idx = TRACE_ARR_LEN;
+
+	idx--;
+	return idx;
+}
+
+struct trace {
+	struct timeval tv;
+	char str[STR_LEN];
+	char valid;
+};
+
+struct trace *trc_arr[CONFIG_NR_CPUS];
+static int trc_index[CONFIG_NR_CPUS];
+static int trc_active;
+static int trc_mode;
+
+void TRC_START(void)
+{
+	trc_active = 1;
+}
+
+void TRC_STOP(void)
+{
+	trc_active = 0;
+}
+
+void TRC_MODE(int mode)
+{
+	trc_mode = mode;
+}
+
+int TRC_INIT(void)
+{
+	struct trace *trc;
+	int cpu;
+
+	printk(KERN_INFO "Marvell debug tracing is supported\n");
+
+	for_each_possible_cpu(cpu) {
+
+		trc = kmalloc(TRACE_ARR_LEN * sizeof(struct trace), GFP_KERNEL);
+		if (trc == NULL) {
+			printk(KERN_ERR "Can't allocate Debug Trace buffer\n");
+			return 1;
+		}
+		memset(trc, 0, TRACE_ARR_LEN * sizeof(struct trace));
+		trc_arr[cpu] = trc;
+		trc_index[cpu] = 0;
+		trc_active = 0;
+		trc_mode = 0;
+	}
+	return 0;
+}
+
+void TRC_REC(char *fmt, ...)
+{
+	va_list args;
+	int idx = trc_index[smp_processor_id()];
+	struct trace *trc = &trc_arr[smp_processor_id()][idx];
+
+	if (trc_active == 0)
+		return;
+
+	if (trc_mode == 1) {
+		/* Stop when trace buffer is full */
+		if (trc->valid) {
+			printk(KERN_ERR "Trace stopped - buffer is full\n");
+			TRC_STOP();
+			return;
+		}
+	}
+	do_gettimeofday(&trc->tv);
+	va_start(args, fmt);
+	vsprintf(trc->str, fmt, args);
+	va_end(args);
+	trc->valid = 1;
+
+	trc_index[smp_processor_id()] = mv_trace_next_idx(idx);
+}
+
+/* cpu_mask:  0 - from running CPU only, -1 from all CPUs, 1..(1 << CONFIG_NR_CPUS) - 1 */
+/* time_mode: 0 - time stamp normalized to oldest message, 1 - difference from previous message */
+void TRC_OUTPUT(int cpu_mask, int time_mode)
+{
+	int i, last, next, cpu, active;
+	struct trace *p;
+	struct timeval *tv_base;
+
+	active = trc_active;
+	trc_active = 0;
+	if (cpu_mask == 0)
+		cpu = smp_processor_id();
+	else {
+		for_each_possible_cpu(cpu) {
+			if (MV_BIT_CHECK(cpu_mask, cpu))
+				break;
+		}
+	}
+
+	next = trc_index[cpu];
+	last = mv_trace_prev_idx(next);
+	p = &trc_arr[cpu][last];
+	if (p->valid == 0) {
+		printk(KERN_INFO "\nTrace: cpu=%d - No valid entries\n", cpu);
+		return;
+	}
+
+	/* Find first valid entry */
+	i = next;
+	while (i != last) {
+		p = &trc_arr[cpu][i];
+		if (p->valid)
+			break;
+		i = mv_trace_next_idx(i);
+	}
+
+	tv_base = &trc_arr[cpu][i].tv;
+
+	printk(KERN_INFO "\nTrace: cpu=%d, first=%d, last=%d, base time: %lu sec, %lu usec\n",
+				cpu, i, last, tv_base->tv_sec, tv_base->tv_usec);
+	printk(KERN_INFO "\n No CPU [s : ms : us]  message\n");
+	do {
+		unsigned int sec, msec, usec;
+
+		p = &trc_arr[cpu][i];
+		sec = p->tv.tv_sec - tv_base->tv_sec;
+		if (p->tv.tv_usec >= tv_base->tv_usec)
+			usec = (p->tv.tv_usec - tv_base->tv_usec);
+		else {
+			sec--;
+			usec = 1000000 - (tv_base->tv_usec - p->tv.tv_usec);
+		}
+		msec = usec / 1000;
+		usec = usec % 1000;
+		printk(KERN_INFO "%03d: %d: [%02u:%03u:%03u]: ", i, cpu, sec, msec, usec);
+		printk(KERN_INFO "%s", p->str);
+		i = mv_trace_next_idx(i);
+		if (time_mode == 1)
+			tv_base = &p->tv;
+	} while (i != next);
+
+	memset(trc_arr[cpu], 0, TRACE_ARR_LEN * sizeof(struct trace));
+	trc_index[cpu] = 0;
+	trc_active = active;
+
+}
+
+void TRC_RELEASE(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+
+		kfree(trc_arr[smp_processor_id()]);
+		trc_index[smp_processor_id()] = 0;
+	}
+}
+
+void mv_trace_status(void)
+{
+	int cpu;
+
+	printk(KERN_INFO "TRACE: strlen=%d, entries=%d, mode=%d, active=%d\n",
+			STR_LEN, TRACE_ARR_LEN, trc_mode, trc_active);
+	for_each_possible_cpu(cpu) {
+		printk(KERN_INFO "cpu=%d, trc_index=%4d, trc_buffer=%p\n", cpu, trc_index[cpu], trc_arr[cpu]);
+	}
+}
+
+static ssize_t mv_trace_help(char *buf)
+{
+	int off = 0;
+
+	off += sprintf(buf+off, "cat           help   	- show this help\n");
+	off += sprintf(buf+off, "cat           status 	- show trace buffer status\n");
+	off += sprintf(buf+off, "echo [0|1]  > start	- stop/start trace record\n");
+	off += sprintf(buf+off, "echo m      > mode     - set record mode: 0-overwrite, 1-stop on full \n");
+	off += sprintf(buf+off, "echo c t    > dump     - dump trace buffer: <c>-cpu_mask, <t>-time mode\n");
+
+	return off;
+}
+
+static ssize_t mv_trace_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	const char      *name = attr->attr.name;
+	int             off = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (!strcmp(name, "status"))
+		mv_trace_status();
+	else
+		off = mv_trace_help(buf);
+
+	return off;
+}
+
+static ssize_t mv_trace_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
+{
+	const char      *name = attr->attr.name;
+	int             err = 0;
+	unsigned int    a, b;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Read arguments */
+	sscanf(buf, "%x %x", &a, &b);
+
+	if (!strcmp(name, "start")) {
+		if (a)
+			TRC_START();
+		else
+			TRC_STOP();
+	} else if (!strcmp(name, "mode"))
+			TRC_MODE(a);
+	else if (!strcmp(name, "dump"))
+		TRC_OUTPUT(a, b);
+	else {
+		printk(KERN_ERR "%s: illegal operation <%s>\n", __func__, attr->attr.name);
+		err = -EINVAL;
+	}
+	return err ? -EINVAL : len;
+}
+
+static DEVICE_ATTR(help,        S_IRUSR, mv_trace_show, NULL);
+static DEVICE_ATTR(status,      S_IRUSR, mv_trace_show, NULL);
+static DEVICE_ATTR(start,       S_IWUSR, mv_trace_show, mv_trace_store);
+static DEVICE_ATTR(mode,        S_IWUSR, mv_trace_show, mv_trace_store);
+static DEVICE_ATTR(dump,        S_IWUSR, mv_trace_show, mv_trace_store);
+
+static struct attribute *mv_trace_attrs[] = {
+
+	&dev_attr_help.attr,
+	&dev_attr_status.attr,
+	&dev_attr_start.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_dump.attr,
+	NULL
+};
+
+static struct attribute_group mv_trace_group = {
+	.name = "trace",
+	.attrs = mv_trace_attrs,
+};
+
+int __devinit mv_trace_init(void)
+{
+	int err;
+	struct device *pd;
+
+	err = TRC_INIT();
+	if (err) {
+		printk(KERN_INFO "sysfs group failed %d\n", err);
+		goto out;
+	}
+
+	pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	if (!pd) {
+		platform_device_register_simple("neta", -1, NULL, 0);
+		pd = bus_find_device_by_name(&platform_bus_type, NULL, "neta");
+	}
+
+	if (!pd) {
+		printk(KERN_ERR"%s: cannot find neta device\n", __func__);
+		pd = &platform_bus;
+	}
+
+	err = sysfs_create_group(&pd->kobj, &mv_trace_group);
+	if (err) {
+		printk(KERN_INFO "sysfs group failed %d\n", err);
+		goto out;
+	}
+out:
+
+	return err;
+}
+
+module_init(mv_trace_init);
+
+MODULE_AUTHOR("Dima Epshtein");
+MODULE_DESCRIPTION("Trace message support");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/dbg-trace.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/dbg-trace.h
new file mode 100755
index 0000000..a411195
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_trace/dbg-trace.h
@@ -0,0 +1,53 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+#ifndef _MV_DBG_TRCE_H_
+#define _MV_DBG_TRCE_H_
+
+#ifdef CONFIG_MV_DBG_TRACE
+
+int  TRC_INIT(void);
+void TRC_REC(char *fmt, ...);
+void TRC_OUTPUT(int cpu_mask, int time_mode);
+void TRC_RELEASE(void);
+void TRC_START(void);
+void TRC_STOP(void);
+void TRC_MODE(int mode);
+
+#else
+
+#define TRC_INIT(mode)
+#define TRC_REC(X...)
+#define TRC_OUTPUT(cpu_mask, time_mode)
+#define TRC_RELEASE()
+#define TRC_START()
+#define TRC_STOP()
+#define TRC_MODE(mode)
+
+#endif /* CONFIG_MV_DBG_TRACE */
+
+#endif /* _MV_DBG_TRCE_H_ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/Kconfig
new file mode 100755
index 0000000..1656f68
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/Kconfig
@@ -0,0 +1,63 @@
+menu "TSU options"
+	depends on MV_INCLUDE_TS
+
+config  MV_TSU
+	bool "Support for Marvell Transport Stream Interface"
+#	depends on MV_INCLUDE_TS
+	default n
+choice
+	prompt "TSU interface type"
+	depends on MV_TSU
+	default TSU_PARALLEL_IF
+
+config TSU_SERIAL_IF
+	bool "Serial Interface"
+	---help---
+	The TSU will work in serial mode (2 ports).
+
+config TSU_PARALLEL_IF
+	bool "Parallel Interface"
+	---help---
+	The TSU will work in parallel mode (1 port).
+endchoice
+
+
+choice
+	prompt "TSU Core-Clock"
+	depends on MV_TSU
+	default TSU_CORE_CLK_83MHZ
+
+config TSU_CORE_CLK_71MHZ
+	bool "71 MHz TSU Core Clock"
+
+config TSU_CORE_CLK_83MHZ
+	bool "83 MHz TSU Core Clock"
+
+config TSU_CORE_CLK_91MHZ
+	bool "91 MHz TSU Core Clock"
+config TSU_CORE_CLK_100MHZ
+	bool "100 MHz TSU Core Clock"
+
+endchoice
+
+config  MV_TSU_PKT_SIZE
+        int "TSU packet size"
+        depends on MV_TSU
+	default 188
+	range 188, 256
+        ---help---
+          Define the TS packet size to be used (Same for both ports)
+	  Must be >= 188 and <= 256.
+
+config  MV_TSU_PROC
+	bool "Support for TSU proc interface"
+	depends on MV_TSU
+	default y
+        ---help---
+          Support Proc-fs interface to configuring the TS control driver.
+
+endmenu
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/Makefile
new file mode 100755
index 0000000..811d010
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Marvell Transport Stream Unit driver
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+obj-$(CONFIG_MV_TSU)	+= mv_tsu.o
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu.c
new file mode 100755
index 0000000..8f5babb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu.c
@@ -0,0 +1,1552 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/cdev.h>
+#include <linux/version.h>
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ts/mvTsu.h"
+#include "ts/mvTsuRegs.h"
+#include "mvSysTsApi.h"
+#include "mv_tsu_ioctl.h"
+#include "mv_tsu.h"
+
+/*
+ * Local Macros and Definiions.
+ */
+#undef TSU_DEBUG
+//#define TSU_DEBUG
+#define TSU_DBG_OFF     0x00
+#define TSU_DBG_INIT    0x01
+#define TSU_DBG_OPEN    0x02
+#define TSU_DBG_RELEASE 0x04
+#define TSU_DBG_READ 	0x08
+#define TSU_DBG_WRITE 	0x10
+#define TSU_DBG_IOCTL 	0x20
+#define TSU_DBG_PROC    0x40
+#define TSU_DBG_INT     0x80
+#define TSU_DBG_ALL     0xFFFFFFFF
+
+#ifdef TSU_DEBUG
+static u32 mvtsu_dbg = TSU_DBG_READ;
+#define TSU_DPRINT(f, x) if((mvtsu_dbg & (f)) == (f)) printk x
+#else
+#define TSU_DPRINT(f, x)
+#endif
+#define TSU_ENTER(f, fname)	TSU_DPRINT(f, ("Entering " fname "()\n"))
+#define TSU_LEAVE(f, fname)	TSU_DPRINT(f, ("Leaving " fname "()\n"))
+
+#undef TSU_UNCACHED_DATA_BUFFERS
+
+#define TSU_DATA_BUFF_HW_2_SW(buf)      (((MV_U32)(buf)) & ~(TSU_DMA_ALIGN - 1))
+
+#define TSU_IS_DEC_DIGIT(c)	(((c) >= '0') && ((c) <= '9'))
+
+#define TSU_DEV_NAME "tsu"
+#define TSU_NUM_DEVICES	2
+#ifdef CONFIG_TSU_SERIAL_IF
+#define DEF_TSU_MODE TSU_MODE_SERIAL
+#else
+#define DEF_TSU_MODE TSU_MODE_PARALLEL
+#endif
+
+#if defined(CONFIG_TSU_CORE_CLK_71MHZ)
+#define DEF_TSU_CORE_CLOCK TSU_CORE_CLK_71_MHZ
+#elif defined(CONFIG_TSU_CORE_CLK_83MHZ)
+#define DEF_TSU_CORE_CLOCK TSU_CORE_CLK_83_MHZ
+#elif defined(CONFIG_TSU_CORE_CLK_91MHZ)
+#define DEF_TSU_CORE_CLOCK TSU_CORE_CLK_91_MHZ
+#elif defined(CONFIG_TSU_CORE_CLK_100MHZ)
+#define DEF_TSU_CORE_CLOCK TSU_CORE_CLK_100_MHZ
+#endif
+
+#define TSU_MIN_READ_SIZE	8
+
+/*
+ * Local data-structures.
+ */
+struct mvtsu_dev {
+	u8 port;
+	struct cdev cdev;
+	MV_TSU_BUFF_INFO buff_info;
+	MV_TSU_SIGNAL_CONFIG signal_cfg;
+	MV_U32 serial_sig_flags;
+	MV_U8 sync_loss;
+	MV_U8 sync_detect;
+	MV_TSU_PORT_DIRECTION port_dir;
+	u32 valid_data_size;	/* Size of data in HW buffers.		*/
+	u32 rd_rw_data_size;	/* Size of buffer for read / write.	*/
+	u8 *data_buff;
+	u32 *stat_buff;
+	u32 stat_buff_size;
+	u32 data_offs;
+	u32 buff_handle;
+	u8 read_all_at_once;
+	u32 clockrate;
+	u32 rd_wr_timeout;
+	u32 tx_tms_gap;
+	u32 tx_tms_val;
+	u8 auto_tms_mode;
+	spinlock_t lock;
+	struct tsu_stat int_stat;
+};
+
+
+/*
+ * Local control variables.
+ */
+static MV_TSU_PORTS_MODE cfg_tsu_mode;
+static MV_TSU_CORE_CLOCK cfg_core_clk;
+static int cfg_pkt_size;
+static struct mvtsu_dev mvtsu_devs[TSU_NUM_DEVICES];
+static dev_t mvtsu_device;
+char *mvtsu_cmdline;
+
+int mvtsu_cmdline_config(char *s);
+static int mvtsu_parse_cmdline(void);
+__setup("mv_tsu_config=", mvtsu_cmdline_config);
+
+#ifdef CONFIG_MV_TSU_PROC
+static struct proc_dir_entry *mvtsu_proc_entry;
+
+static int mvtsu_proc_init(void);
+#endif /* CONFIG_MV_TSU_PROC */
+
+#ifdef TSU_DEBUG
+static void mvtsu_dump_regs(int port)
+{
+	int i;
+
+	for(i = 0x0; i <= 0x68; i+=4) {
+		printk("Reg 0x%08x --> 0x%08x.\n",TSU_REG_BASE(port) + i,
+		       MV_REG_READ(TSU_REG_BASE(port) + i));
+	}
+	return;
+}
+#endif /* TSU_DEBUG */
+
+/*
+ * Calculate the timestamp gap between two packets.
+ */
+static void mvtsu_tx_timestamp_calc(struct mvtsu_dev *dev)
+{
+	u32 base_clock = 4166660;
+
+	dev->tx_tms_gap = (base_clock * cfg_pkt_size) / (dev->clockrate / 10);
+	dev->tx_tms_val = 0;
+	return;
+}
+
+
+/*
+ * Calculate the timeout needed between packets.
+ */
+static void mvtsu_rd_wr_timeout_calc(struct mvtsu_dev *dev)
+{
+        dev->rd_wr_timeout = 0;
+        if(dev->clockrate >= 1000) {
+		/* How much time (in milisec) is needed for a single 	*/
+		/* block of data.					*/
+		dev->rd_wr_timeout = ((dev->valid_data_size * 8) /
+				      (dev->clockrate / 1000));
+	}
+	/* Double the timeout to be on the safe side.	*/
+	dev->rd_wr_timeout *= 2;
+	if(dev->rd_wr_timeout < 50)
+		dev->rd_wr_timeout = 50;
+	return;
+}
+
+
+static void mvtsu_set_defaults(struct mvtsu_dev *dev)
+{
+	TSU_ENTER(TSU_DBG_INIT, "mvtsu_set_defaults");
+
+	/* Set buffer parameters.	*/
+	dev->buff_info.aggrMode = TSU_DFLT_AGGR_MODE;
+	dev->buff_info.aggrMode2TmstmpOff = TSU_DFLT_TMSTMP_OFFS;
+	dev->buff_info.aggrNumPackets = TSU_DFLT_AGGR_PCKT_NUM;
+	dev->buff_info.numTsDesc = TSU_DFLT_TS_DESC_NUM;
+	dev->buff_info.numDoneQEntry = TSU_DFLT_TS_DONEQ_NUM;
+	dev->buff_info.tsDataBuff = NULL;
+	dev->buff_info.tsDoneBuff = NULL;
+	dev->buff_info.dataBlockSize = 0;
+
+	/* Set signal config.		*/
+	dev->signal_cfg.tsDataEdge = TSU_SIGNAL_EDGE_KEEP_DEF;
+	dev->signal_cfg.tsError = TSU_SIGNAL_KEEP_DEF;
+	dev->signal_cfg.tsSync = TSU_SIGNAL_KEEP_DEF;
+	dev->signal_cfg.tsValid = TSU_SIGNAL_KEEP_DEF;
+	dev->serial_sig_flags = 0;
+
+	/* TS Sync detection parameters.	*/
+	mvTsuRxSyncDetectionGet(dev->port,&dev->sync_detect, &dev->sync_loss);
+
+	dev->read_all_at_once = TSU_DFLT_DATA_READ_AT_ONCE;
+	dev->clockrate = TSU_DFLT_CLOCK_RATE;
+
+	TSU_LEAVE(TSU_DBG_INIT, "mvtsu_set_defaults");
+	return;
+}
+
+static irqreturn_t mvtsu_interrupt_handler(int irq , void *arg)
+{
+	struct mvtsu_dev* dev = (struct mvtsu_dev*)arg;
+	u32 cause;
+
+	TSU_ENTER(TSU_DBG_INT, "mvtsu_interrupt_handler");
+
+	cause = MV_REG_READ(MV_TSU_INTERRUPT_SRC_REG(dev->port));
+	TSU_DPRINT(TSU_DBG_INT, ("\tPort %d, Cause = 0x%08x.\n",dev->port,cause));
+
+	if(cause & TSU_INT_TS_IF_ERROR)
+		dev->int_stat.ts_if_err++;
+	if(cause & TSU_INT_FIFO_OVFL_ERROR)
+		dev->int_stat.fifo_ovfl++;
+	if(cause & TSU_INT_TS_CONN_ERROR)
+		dev->int_stat.ts_conn_err++;
+	if(cause & TSU_INT_CLOCK_SYNC_EXP)
+		dev->int_stat.clk_sync_exp++;
+
+	TSU_LEAVE(TSU_DBG_INT, "mvtsu_interrupt_handler");
+	return IRQ_HANDLED;
+}
+
+int mvtsu_open (struct inode *inode, struct file *filp)
+{
+	struct mvtsu_dev *dev;
+	MV_TSU_PORT_CONFIG port_cfg;
+	MV_TSU_BUFF_INFO *binfo = NULL;
+	MV_STATUS status;
+	int result = 0;
+	int stat_size = 0;
+	int data_size = 0;
+	int data_buff_offs;
+
+	TSU_ENTER(TSU_DBG_OPEN, "mvtsu_open");
+
+	if(MV_FALSE == mvCtrlPwrClckGet(TS_UNIT_ID, 0)) {
+		printk("Transport Stream interface is powered off.\n");
+		return 0;
+	}
+
+	/*  Find the device structure.	*/
+	dev = container_of(inode->i_cdev, struct mvtsu_dev, cdev);
+
+    	/* Determine the port direction according to the read / write flag.*/
+	if ((filp->f_mode & (FMODE_WRITE | FMODE_READ)) == FMODE_WRITE) {
+		port_cfg.portDir = TSU_PORT_OUTPUT;
+	} else if ((filp->f_mode & (FMODE_WRITE | FMODE_READ)) == FMODE_READ) {
+		port_cfg.portDir = TSU_PORT_INPUT;
+	} else {
+		result = -EINVAL;
+		goto fail_init;
+	}
+
+	/* Reset the port.		*/
+	mvTsuPortReset(dev->port);
+
+	/* Initialize the port.		*/
+	port_cfg.pktSize = cfg_pkt_size;
+       	status = mvTsuPortInit(dev->port,&port_cfg);
+	if(status != MV_OK) {
+		result = -EINVAL;
+		goto fail_init;
+	}
+
+	TSU_DPRINT(TSU_DBG_OPEN, ("\tTSU unit initialized successfully.\n"));
+
+	/* Initialize the port buffers.	*/
+	binfo = &dev->buff_info;
+	switch(binfo->aggrMode)
+	{
+	case (MV_TSU_AGGR_MODE_DISABLED):
+		binfo->dataBlockSize = port_cfg.pktSize;
+		dev->valid_data_size = port_cfg.pktSize;
+		dev->rd_rw_data_size = binfo->dataBlockSize + TSU_DONE_STATUS_ENTRY_SIZE;
+		binfo->aggrNumPackets = 1;
+		break;
+	case (MV_TSU_AGGR_MODE_1):
+		binfo->dataBlockSize = port_cfg.pktSize * binfo->aggrNumPackets;
+		if(port_cfg.portDir == TSU_PORT_OUTPUT) {
+			binfo->dataBlockSize += MV_MAX(TSU_DMA_ALIGN,TSU_MODE1_OUT_TMS_SIZE);
+			dev->rd_rw_data_size = binfo->dataBlockSize;
+		}
+		else {
+			dev->rd_rw_data_size = binfo->dataBlockSize +
+				(binfo->aggrNumPackets * TSU_DONE_STATUS_ENTRY_SIZE);
+		}
+		dev->valid_data_size = port_cfg.pktSize * binfo->aggrNumPackets;
+		break;
+	case (MV_TSU_AGGR_MODE_2):
+		binfo->aggrMode2TmstmpOff = TSU_DMA_ALIGN -
+			(port_cfg.pktSize & (TSU_DMA_ALIGN - 1));
+		binfo->dataBlockSize =
+			(binfo->aggrNumPackets *
+			 (port_cfg.pktSize + binfo->aggrMode2TmstmpOff) +
+			 TSU_DMA_ALIGN);
+		dev->valid_data_size = (binfo->aggrNumPackets *
+					(port_cfg.pktSize + binfo->aggrMode2TmstmpOff));
+		dev->rd_rw_data_size = dev->valid_data_size;
+	default:
+		break;
+	}
+
+	dev->port_dir = port_cfg.portDir;
+
+	/* Align the data block size to a cache line.	*/
+	binfo->dataBlockSize = MV_ALIGN_UP(binfo->dataBlockSize,32);
+	data_size = binfo->dataBlockSize * binfo->numTsDesc;
+#ifdef TSU_UNCACHED_DATA_BUFFERS
+	binfo->tsDataBuff =
+		mvOsIoUncachedMalloc(NULL,data_size,(MV_ULONG*)(&binfo->tsDataBuffPhys),
+				     NULL);
+#else
+	binfo->tsDataBuff =
+		mvOsIoCachedMalloc(NULL,data_size,(MV_ULONG*)(&binfo->tsDataBuffPhys),
+				   NULL);
+#endif /* TSU_UNCACHED_DATA_BUFFERS */
+	if(binfo->tsDataBuff == NULL) {
+		result = -ENOMEM;
+		goto fail_init;
+	}
+//	memset(binfo->tsDataBuff,0x88,data_size);
+#ifndef TSU_UNCACHED_DATA_BUFFERS
+	mvOsCacheClear(NULL,(MV_U32*)TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuff),
+		       data_size);
+#endif /* TSU_UNCACHED_DATA_BUFFERS */
+
+	/* Align tsDataBuff according to the HW limitation.	*/
+	if(binfo->aggrMode == MV_TSU_AGGR_MODE_2) {
+		data_buff_offs = port_cfg.pktSize & (TSU_DMA_ALIGN - 1);
+	}
+	else if((binfo->aggrMode == MV_TSU_AGGR_MODE_1) &&
+		(port_cfg.portDir == TSU_PORT_OUTPUT)) {
+        	data_buff_offs = TSU_DMA_ALIGN - TSU_MODE1_OUT_TMS_SIZE;
+	}
+	else {
+		data_buff_offs = 0;
+	}
+
+	binfo->tsDataBuff = (MV_U32*)((MV_U32)binfo->tsDataBuff + data_buff_offs);
+	binfo->tsDataBuffPhys += data_buff_offs;
+
+	TSU_DPRINT(TSU_DBG_OPEN, ("\tTSU Data buffer allocated successfully "
+				  "(%p, %d).\n",binfo->tsDataBuff, data_size));
+	/* Allocate memory for done queue.	*/
+	stat_size = TSU_DONE_STATUS_ENTRY_SIZE * binfo->numDoneQEntry;
+	dev->stat_buff_size = stat_size;
+	binfo->tsDoneBuff =
+		mvOsIoUncachedMalloc(NULL,stat_size,
+				     (MV_ULONG*)(&binfo->tsDoneBuffPhys),NULL);
+	if(binfo->tsDoneBuff == NULL) {
+		result = -ENOMEM;
+		goto fail_init;
+	}
+
+	TSU_DPRINT(TSU_DBG_OPEN, ("\tTSU Done buffer allocated successfully"
+				  "(%p, %d).\n",binfo->tsDoneBuff, stat_size));
+
+	status = mvTsuBuffersInit(dev->port,&dev->buff_info);
+	if(status != MV_OK) {
+		TSU_DPRINT(TSU_DBG_OPEN, ("\tmvTsuBuffersInit() Failed (%d).",
+					  status));
+		result = -EINVAL;
+		goto fail_init;
+	}
+	TSU_DPRINT(TSU_DBG_OPEN, ("\tHAL Buffers initialized successfully.\n"));
+
+	status = mvTsuPortSignalCfgSet(dev->port,&(dev->signal_cfg),dev->serial_sig_flags);
+	if(status != MV_OK) {
+		TSU_DPRINT(TSU_DBG_OPEN, ("\tmvTsuPortSignalCfgSet() Failed (%d).",
+					status));
+		result = -EINVAL;
+		goto fail_init;
+	}
+	TSU_DPRINT(TSU_DBG_OPEN, ("\tPort signal parameters set successfully.\n"));
+
+	status = mvTsuRxSyncDetectionSet(dev->port,dev->sync_detect,dev->sync_loss);
+	if(status != MV_OK) {
+		TSU_DPRINT(TSU_DBG_OPEN, ("\tmvTsuRxSyncDetectionSet() Failed (%d).",
+					status));
+		result = -EINVAL;
+		goto fail_init;
+	}
+	TSU_DPRINT(TSU_DBG_OPEN, ("\tRx sync parameters set successfully.\n"));
+
+	mvtsu_rd_wr_timeout_calc(dev);
+
+	if(dev->port_dir == TSU_PORT_OUTPUT) {
+		mvtsu_tx_timestamp_calc(dev);
+	}
+
+	/* Register IRQ.	*/
+	MV_REG_WRITE(MV_TSU_INTERRUPT_MASK_REG(dev->port),TSU_DFLT_INT_MASK);
+	if(request_irq(IRQ_TS_INT(dev->port),mvtsu_interrupt_handler,
+		       IRQF_DISABLED | IRQF_SAMPLE_RANDOM,"tsu",dev)) {
+		printk(KERN_ERR "Cannot assign irq%d to TSU port%d\n",
+		       IRQ_TS_INT(dev->port), dev->port);
+		goto fail_init;
+	}
+	TSU_DPRINT(TSU_DBG_OPEN, ("\tTSU interrupt registered at IRQ %d.\n",
+				  IRQ_TS_INT(dev->port)));
+
+	if(port_cfg.portDir == TSU_PORT_INPUT) {
+		/* Enable Rx timestamp.	*/
+		mvTsuRxTimestampCntEn(dev->port,MV_TRUE);
+		mvTsuDmaWatermarkSet(dev->port,0x8);
+	}
+
+	/* Make the private_data hold the pointer to the device data.	*/
+	filp->private_data = dev;
+
+	TSU_LEAVE(TSU_DBG_OPEN, "mvtsu_open");
+	return 0;
+
+fail_init:
+	if(binfo != NULL) {
+		if(binfo->tsDataBuff != NULL)
+#ifdef TSU_UNCACHED_DATA_BUFFERS
+			mvOsIoUncachedFree(
+				NULL,data_size,
+				TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuffPhys),
+				(MV_U32*)TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuff),0);
+#else
+		mvOsIoCachedFree(
+			NULL,data_size,
+			TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuffPhys),
+			(MV_U32*)TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuff),0);
+#endif /* TSU_UNCACHED_DATA_BUFFERS */
+		if(binfo->tsDoneBuff != NULL)
+			mvOsIoUncachedFree(NULL,stat_size,binfo->tsDoneBuffPhys,
+					   binfo->tsDoneBuff,0);
+		binfo->tsDataBuff = NULL;
+		binfo->tsDoneBuff = NULL;
+	}
+	TSU_LEAVE(TSU_DBG_OPEN, "mvtsu_open");
+	return result;
+}
+
+
+int mvtsu_release (struct inode *inode, struct file *filp)
+{
+	struct mvtsu_dev *dev = (struct mvtsu_dev*)filp->private_data;
+	MV_TSU_BUFF_INFO *binfo;
+	int size;
+
+	TSU_ENTER(TSU_DBG_RELEASE, "mvtsu_release");
+
+	free_irq(IRQ_TS_INT(dev->port),dev);
+
+	if(dev->port_dir == TSU_PORT_INPUT) {
+		/* Stop Rx timestamp.	*/
+		mvTsuRxTimestampCntEn(dev->port,MV_FALSE);
+	}
+
+	/* Shutdown the port.		*/
+	mvTsuPortShutdown(dev->port);
+
+	/* Clear interrupt mask.	*/
+	MV_REG_WRITE(MV_TSU_INTERRUPT_MASK_REG(dev->port),0);
+
+	/* Free previously allocated buffers.	*/
+	binfo = &dev->buff_info;
+	if(binfo->tsDataBuff != NULL) {
+		size = binfo->dataBlockSize * binfo->numTsDesc;
+#ifdef TSU_UNCACHED_DATA_BUFFERS
+		mvOsIoUncachedFree(NULL,size,
+				   TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuffPhys),
+				   (MV_U32*)TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuff),0);
+#else
+		mvOsIoCachedFree(NULL,size,
+				 TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuffPhys),
+				 (MV_U32*)TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuff),0);
+#endif /* TSU_UNCACHED_DATA_BUFFERS */
+	}
+	if(binfo->tsDoneBuff != NULL) {
+		mvOsIoUncachedFree(NULL,dev->stat_buff_size,binfo->tsDoneBuffPhys,
+				   binfo->tsDoneBuff,0);
+	}
+	binfo->tsDataBuff = NULL;
+	binfo->tsDoneBuff = NULL;
+
+	mvtsu_set_defaults(dev);
+
+	TSU_LEAVE(TSU_DBG_RELEASE, "mvtsu_release");
+	return 0;
+}
+
+
+/*
+ * Helper function for retrying read buffer requests.
+ * Assume that the device spinlock is held.
+ */
+static int mvtsu_next_rx_buff_get(struct file *filp, u32 **data_buff,
+				  u32 **stat_buff, u32 *buff_handle,
+				  unsigned long *flags)
+{
+	struct mvtsu_dev *dev = (struct mvtsu_dev*)filp->private_data;
+	int timeout = 0;
+	int cnt = 0;
+	MV_STATUS status;
+
+//	timeout = (dev->rd_wr_timeout == 0) ? 2000 : (dev->rd_wr_timeout + 100);
+	timeout = dev->rd_wr_timeout;
+
+	while(cnt < timeout) {
+		status = mvTsuRxNextBuffGet(dev->port,data_buff,stat_buff,
+					    buff_handle);
+		if(status != MV_OK) {
+			if(status != MV_NO_MORE)
+				return -EIO;
+		}
+		else {
+#if !defined(TSU_UNCACHED_DATA_BUFFERS) && defined(CONFIG_MV_SP_I_FTCH_DB_INV)
+			dma_unmap_single(NULL, mvOsIoVirtToPhy(NULL, *data_buff) ,
+					dev->buff_info.dataBlockSize, DMA_FROM_DEVICE);
+#endif
+			break;
+		}
+		if (filp->f_flags & O_NONBLOCK)
+			break;
+
+		spin_unlock_irqrestore(&(dev->lock), *flags);
+		if(dev->rd_wr_timeout)
+			msleep_interruptible(1);
+		else
+			udelay(1000);
+
+		cnt += 1;
+		spin_lock_irqsave(&(dev->lock), *flags);
+	}
+	if(cnt >= timeout) {
+		printk(KERN_INFO "TSU: Read timeout.\n");
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+
+/*
+ * Helper function for copying timestamp info to user buffer.
+ */
+inline static void mvtsu_rx_tmsstmp_copy(struct mvtsu_dev *dev, u32 *stat_buff,
+					 char *out_buff, int *buf_offs,
+					 int *buf_size)
+{
+	MV_U32 size;
+	MV_U32 all;
+	MV_U32 avail;
+
+	all = TSU_DONE_STATUS_ENTRY_SIZE * dev->buff_info.aggrNumPackets;
+	/* Calculate avilable data at end of buffer.	*/
+	avail = dev->stat_buff_size -
+		((MV_U32)stat_buff - (MV_U32)dev->buff_info.tsDoneBuff);
+	if(avail < all)
+		size = avail;
+	else
+		size = all;
+
+	if(copy_to_user(out_buff,stat_buff,size))
+		panic("TSU: copy_to_user failed.");
+	avail = all - size;
+	if(avail != 0) {
+		if(copy_to_user(out_buff + size,dev->buff_info.tsDoneBuff,avail))
+			panic("TSU: copy_to_user failed.");
+	}
+
+	*buf_offs += all;
+	*buf_size -= all;
+        return;
+}
+
+/*
+ * TSU data read
+ */
+ssize_t mvtsu_read(struct file *filp, char __user *buf, size_t count,
+		   loff_t *f_pos)
+{
+	struct mvtsu_dev *dev = filp->private_data;
+	MV_U8 port = dev->port;
+	MV_U8 *data_buff;
+	MV_U32 size;
+	int status;
+	int buf_offs = 0;
+	unsigned long flags;
+
+	TSU_ENTER(TSU_DBG_READ, "mvtsu_read");
+	spin_lock_irqsave(&(dev->lock), flags);
+
+	if((dev->buff_info.aggrMode != MV_TSU_AGGR_MODE_2) &&
+	   (count < (TSU_DONE_STATUS_ENTRY_SIZE * dev->buff_info.aggrNumPackets))) {
+		printk(KERN_ERR "TSU: Read operations must be at least of size "
+				"%d",
+		       TSU_DONE_STATUS_ENTRY_SIZE * dev->buff_info.aggrNumPackets);
+		status = -EINVAL;
+		goto no_data;
+	}
+
+	if(dev->data_buff == NULL) {
+		TSU_DPRINT(TSU_DBG_READ, ("\tGet new data buffer..."));
+		status = mvtsu_next_rx_buff_get(filp,(MV_U32**)(&dev->data_buff),
+						&dev->stat_buff,
+						&dev->buff_handle,&flags);
+		if(status) {
+			TSU_DPRINT(TSU_DBG_READ, ("FAILED.\n"));
+			goto no_data;
+		}
+
+		TSU_DPRINT(TSU_DBG_READ, ("OK.\n"));
+		if(dev->buff_info.aggrMode != MV_TSU_AGGR_MODE_2)
+			/* Copy the timestamp before the packet's data.	*/
+			mvtsu_rx_tmsstmp_copy(dev,dev->stat_buff,buf,&buf_offs,
+					      &count);
+		dev->data_offs = 0;
+	}
+	data_buff = dev->data_buff;
+	size = dev->rd_rw_data_size - dev->data_offs;
+
+	if(dev->read_all_at_once && (size > count)) {
+		status = -EINVAL;
+		printk(KERN_INFO "TSU: Read buffer too small, "
+				 "(Read All At Once mode)");
+		goto no_data;
+	}
+
+        /* Valid data in data_buff.	*/
+	if(size < count)
+		count = size;
+	TSU_DPRINT(TSU_DBG_READ, ("\tCopy %d Bytes (%d, %p, %d).\n", count,
+				  buf_offs,data_buff,dev->data_offs));
+	if(copy_to_user(buf + buf_offs,data_buff + dev->data_offs,count))
+		panic("TSU: copy_to_user failed.");
+
+	dev->data_offs += count;
+	*f_pos += (count + buf_offs);
+
+	if(dev->data_offs == dev->valid_data_size) {
+		TSU_DPRINT(TSU_DBG_READ, ("\tFree RX buffer.\n"));
+//		memset(dev->data_buff,0x88,dev->buff_info.dataBlockSize);
+#ifndef TSU_UNCACHED_DATA_BUFFERS
+		mvOsCacheClear(NULL,
+			       (MV_U32*)TSU_DATA_BUFF_HW_2_SW(dev->data_buff),
+			       dev->buff_info.dataBlockSize);
+#endif /* TSU_UNCACHED_DATA_BUFFERS */
+		status = mvTsuRxBuffFree(port,(MV_U32*)dev->data_buff,
+					 dev->stat_buff,dev->buff_handle);
+		if(status != MV_OK) {
+			panic("TSU: Error in state machine, mvTsuRxBuffFree() "
+			      "Failed.");
+		}
+		dev->data_buff = NULL;
+		dev->stat_buff = NULL;
+	}
+
+	spin_unlock_irqrestore(&(dev->lock), flags);
+        TSU_LEAVE(TSU_DBG_READ, "mvtsu_read");
+	return count + buf_offs;
+
+no_data:
+	spin_unlock_irqrestore(&(dev->lock), flags);
+	printk(KERN_DEBUG "TSU: Failed to read.\n");
+        TSU_LEAVE(TSU_DBG_READ, "mvtsu_read");
+	return status;
+}
+
+
+/*
+ * Helper function for retrying write buffer requests.
+  * Assume that the device spinlock is held.
+ */
+static int mvtsu_next_tx_buff_get(struct file *filp, u32 **data_buff,
+				  u32 *buff_handle, unsigned long *flags)
+{
+	struct mvtsu_dev *dev = (struct mvtsu_dev*)filp->private_data;
+	int timeout = 0;
+	int cnt = 0;
+	MV_STATUS status;
+
+//	timeout = (dev->rd_wr_timeout == 0) ? 2000000 : (dev->rd_wr_timeout + 100);
+	timeout = dev->rd_wr_timeout;
+
+	while(cnt < timeout) {
+		status = mvTsuTxNextBuffGet(dev->port,data_buff,buff_handle);
+		if(status != MV_OK) {
+			if(status != MV_NO_MORE)
+				return -EIO;
+		}
+		else {
+			break;
+		}
+
+		if (filp->f_flags & O_NONBLOCK)
+			break;
+		spin_unlock_irqrestore(&(dev->lock), *flags);
+		if(dev->rd_wr_timeout)
+			msleep_interruptible(10);
+		else
+			udelay(1000);
+
+		cnt += 10;
+		spin_lock_irqsave(&(dev->lock), *flags);
+	}
+	if(cnt >= timeout) {
+		printk(KERN_INFO "TSU: Write timeout.\n");
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+
+/*
+ * TSU data write
+ */
+ssize_t mvtsu_write (struct file *filp, const char __user *buf, size_t count,
+		     loff_t *f_pos)
+{
+	struct mvtsu_dev *dev = filp->private_data;
+	MV_U8 port = dev->port;
+	int status;
+	int buf_offs = 0;
+	MV_BOOL tsErr = MV_FALSE;
+	MV_U32 tms = 0;
+	MV_U32 data;
+	unsigned long flags;
+	size_t orig_cnt = count;
+
+	TSU_ENTER(TSU_DBG_WRITE, "mvtsu_write");
+	spin_lock_irqsave(&(dev->lock), flags);
+
+	if(count < dev->rd_rw_data_size) {
+		printk(KERN_ERR "TSU: Write operations must hold at least a "
+				"single data block of data(%d , %d)",
+		       dev->rd_rw_data_size, count);
+		status = -EINVAL;
+		goto no_tx;
+	}
+
+	TSU_DPRINT(TSU_DBG_WRITE, ("\tGet new data buffer..."));
+	status = mvtsu_next_tx_buff_get(filp,(MV_U32**)(&dev->data_buff),
+					&dev->buff_handle,&flags);
+	if(status) {
+		TSU_DPRINT(TSU_DBG_WRITE, ("FAILED.\n"));
+		goto no_tx;
+	}
+
+	TSU_DPRINT(TSU_DBG_WRITE, ("OK.\n"));
+
+	if(dev->buff_info.aggrMode == MV_TSU_AGGR_MODE_DISABLED) {
+		if(dev->auto_tms_mode) {
+			tms = dev->tx_tms_val;
+			dev->tx_tms_val += dev->tx_tms_gap;
+		} else {
+			TSU_DPRINT(TSU_DBG_WRITE, ("\tGet timestamp info.\n"));
+			/* Copy the timestamp from the beginning of data buffer. */
+			if(copy_from_user(&data,buf,TSU_DONE_STATUS_ENTRY_SIZE))
+				panic("TSU: copy_to_user failed.");
+
+			tsErr = TSU_STATUS_ERROR_GET(data);
+			tms = TSU_STATUS_TMSSTMP_GET(data);
+			TSU_DPRINT(TSU_DBG_WRITE, ("\tTimestamp = %d.\n",tms));
+		}
+		buf_offs = TSU_DONE_STATUS_ENTRY_SIZE;
+		count -= TSU_DONE_STATUS_ENTRY_SIZE;
+	}
+
+	/* Valid data in data_buff.	*/
+	if(dev->valid_data_size < count)
+		count = dev->valid_data_size;
+
+	TSU_DPRINT(TSU_DBG_WRITE, ("\tCopy %d Bytes.\n", count));
+	if(copy_from_user(dev->data_buff, buf + buf_offs, count))
+		panic("TSU Write: copy_to_user failed.");
+	*f_pos += orig_cnt;
+
+	TSU_DPRINT(TSU_DBG_WRITE, ("\tFree TX buffer.\n"));
+#ifndef TSU_UNCACHED_DATA_BUFFERS
+	mvOsCacheFlush(NULL,(MV_U32*)TSU_DATA_BUFF_HW_2_SW(dev->data_buff),
+		       dev->buff_info.dataBlockSize);
+#endif /* TSU_UNCACHED_DATA_BUFFERS */
+
+	status = mvTsuTxBuffPut(port,(MV_U32*)dev->data_buff,tms,tsErr,
+				dev->buff_handle);
+	if(status != MV_OK)
+		panic("TSU: Error in state machine, mvTsuTxBuffPut() Failed.");
+
+	spin_unlock_irqrestore(&(dev->lock), flags);
+	TSU_LEAVE(TSU_DBG_WRITE, "mvtsu_write");
+	return orig_cnt;
+
+no_tx:
+	spin_unlock_irqrestore(&(dev->lock), flags);
+	printk(KERN_DEBUG "TSU: Failed to write.\n");
+	TSU_LEAVE(TSU_DBG_WRITE, "mvtsu_write");
+	return status;
+}
+
+/*
+ * TSU ioctl()
+ */
+int mvtsu_ioctl (struct inode *inode, struct file *filp, unsigned int cmd,
+		 unsigned long arg)
+{
+	struct mvtsu_dev *dev = filp->private_data;
+	int ret = 0;
+	u32 val;
+	unsigned long flags;
+	MV_STATUS status = MV_OK;
+	struct tsu_tmstmp_info tms_info;
+	struct tsu_buff_info buf_info;
+
+	TSU_ENTER(TSU_DBG_IOCTL, "mvtsu_ioctl");
+	TSU_DPRINT(TSU_DBG_IOCTL, ("\targ = 0x%08x.\n",(unsigned int)arg));
+
+	spin_lock_irqsave(&(dev->lock), flags);
+
+	switch(cmd) {
+	case MVTSU_IOCFREQSET:
+		get_user(val,(u32 __user *)arg);
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tFrequency set to %d.\n",val));
+		if(dev->port_dir == TSU_PORT_OUTPUT)
+			status = mvTsuTxClockFreqSet(dev->port,val,MV_FALSE);
+		if(status == MV_OK) {
+			dev->clockrate = val;
+			mvtsu_rd_wr_timeout_calc(dev);
+			mvtsu_tx_timestamp_calc(dev);
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+	case MVTSU_IOCTXTMSSET:
+		if(copy_from_user(&tms_info,(struct tsu_tmstmp_info*)arg,
+				  sizeof(tms_info)))
+			panic("TSU IOCTL: copy_from_user failed.\n");
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tTx timestamp set to (%d,%d).\n",
+					   tms_info.timestamp,
+					   tms_info.enable_tms));
+		status = mvTsuTxInitTimeStampSet(
+			dev->port, (tms_info.enable_tms ? MV_TRUE : MV_FALSE),
+			tms_info.timestamp);
+		if(status != MV_OK)
+			ret = -EINVAL;
+		break;
+	case MVTSU_IOCTXDONE:
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tTx Done.\n"));
+		if(mvTsuTxDone(dev->port) != MV_OK)
+			ret = -EINVAL;
+		break;
+	case MVTSU_IOCRDPKTATONCE:
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tRx Read Packet At Once.\n"));
+		get_user(val,(u32 __user *)arg);
+                dev->read_all_at_once = val;
+		break;
+	case MVTSU_IOCBUFFPARAMGET:
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tGet Buffer Params.\n"));
+		switch(dev->buff_info.aggrMode) {
+		case MV_TSU_AGGR_MODE_DISABLED:
+			buf_info.aggr_mode = aggrModeDisabled;
+			break;
+		case MV_TSU_AGGR_MODE_1:
+			buf_info.aggr_mode = aggrMode1;
+			break;
+		case MV_TSU_AGGR_MODE_2:
+			buf_info.aggr_mode = aggrMode2;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		buf_info.aggr_mode2_tmstmp_off =
+			dev->buff_info.aggrMode2TmstmpOff;
+		buf_info.aggr_num_packets =
+			dev->buff_info.aggrNumPackets;
+		buf_info.num_done_q_entries =
+			dev->buff_info.numDoneQEntry;
+		buf_info.num_ts_desc =
+			dev->buff_info.numTsDesc;
+		buf_info.pkt_size = cfg_pkt_size;
+
+		if(copy_to_user((struct tsu_buff_info*)arg,&buf_info,
+				sizeof(buf_info)))
+			panic("TSU IOCTL: copy_to_user failed.\n");
+		break;
+	case MVTSU_IOCGETSTAT:
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tGet Statistics.\n"));
+		if(copy_to_user((struct tsu_stat*)arg,&dev->int_stat,
+				sizeof(struct tsu_stat)))
+			panic("TSU IOCTL: copy_to_user failed.\n");
+		break;
+	case MVTSU_IOCCLEARSTAT:
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tClear Statistics.\n"));
+		memset(&(dev->int_stat),0,sizeof(dev->int_stat));
+		break;
+	case MVTSU_IOCAUTOTMS:
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tAuto timestamp mode.\n"));
+		get_user(val,(u32 __user *)arg);
+		dev->auto_tms_mode = val;
+		break;
+	default:
+		TSU_DPRINT(TSU_DBG_IOCTL, ("\tInvalid request.\n"));
+		ret = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&(dev->lock), flags);
+
+	TSU_LEAVE(TSU_DBG_IOCTL, "mvtsu_ioctl");
+	return ret;
+}
+
+
+#ifdef CONFIG_MV_TSU_PROC
+
+/*
+	Parameter		Port	Value		Possible Values
+
+	sync_detect		x	x		int
+	sync_loss		x	x		int
+	aggr_mode		x	x		(mode1 / mode2 / dis)
+	aggr_mode2_off		x	x		int
+	aggr_num_pckts		x	x		int
+	num_desc		x	x		int
+	num_done_queue		x	x		int
+	sync_sig		x	x		(dis / high / low)
+	valid_sig		x	x		(dis / high / low)
+	error_sig		x	x		(dis / high / low)
+	data_edge		x	x		(fall / rise)
+	data_order		x	x		(msb / lsb)
+	sync_act		x	x		(1 / 8)
+	clk_mode		x	x		(cont / gap)
+*/
+
+#define TSU_AGGR_MODE_2_STR(mode)					\
+	((mode == MV_TSU_AGGR_MODE_DISABLED) ? "dis" : 			\
+	 ((mode == MV_TSU_AGGR_MODE_1) ? "mode1" : "mode2"))
+
+#define TSU_SIGNAL_MODE_2_STR(mode)					\
+	((mode == TSU_SIGNAL_DIS) ? "dis" : 				\
+	 ((mode == TSU_SIGNAL_EN_ACT_LOW) ? "low" : "high"))
+
+#define TSU_STR_2_SIGNAL_MODE(mode,str)					\
+	{								\
+		if(!strncmp((str),"dis",3))				\
+			mode = TSU_SIGNAL_DIS;				\
+		else if(!strncmp((str),"low",3))			\
+			mode = TSU_SIGNAL_EN_ACT_LOW;			\
+		else if(!strncmp((str),"high",4))			\
+			mode = TSU_SIGNAL_EN_ACT_HIGH;			\
+		else							\
+			mode = TSU_SIGNAL_KEEP_DEF;			\
+	}
+
+
+
+int mvtsu_proc_write(struct file *file, const char *buffer,unsigned long count,
+		     void *data)
+{
+	MV_TSU_SIGNAL_CONFIG	signal_cfg;
+	MV_U32 flags;
+	MV_U8 sync_detect;
+	MV_U8 sync_loss;
+	MV_BOOL write_signal = MV_FALSE;
+        MV_BOOL write_sync = MV_FALSE;
+	MV_U8 port;
+	int len = 0;
+	int tmp;
+	char *str;
+	struct mvtsu_dev *dev;
+
+	TSU_ENTER(TSU_DBG_PROC, "mvtsu_proc_write");
+
+	len = sscanf(buffer,"%d ",&tmp);
+
+	if(tmp >= MV_TSU_NUM_PORTS)
+		return count;
+	port = (MV_U8)tmp;
+        len++; /* Skip over the space.	*/
+
+	signal_cfg.tsDataEdge = TSU_SIGNAL_EDGE_FALL;
+	signal_cfg.tsError = TSU_SIGNAL_KEEP_DEF;
+	signal_cfg.tsSync = TSU_SIGNAL_KEEP_DEF;
+	signal_cfg.tsValid = TSU_SIGNAL_KEEP_DEF;
+	flags = 0;
+
+	if(mvTsuRxSyncDetectionGet(port,&sync_detect,&sync_loss) != MV_OK)
+		return count;
+	dev = &mvtsu_devs[port];
+
+	TSU_DPRINT(TSU_DBG_PROC, ("\tbuffer = %s.\n",buffer+len));
+	str = "sync_detect ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		len += sscanf(buffer+len,"%d",&tmp);
+		sync_detect = (MV_U8)tmp;
+		TSU_DPRINT(TSU_DBG_PROC, ("\tsync_detect = %d.\n",sync_detect));
+		write_sync = MV_TRUE;
+		goto done;
+	}
+	str = "sync_loss ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		len += sscanf(buffer+len,"%d",&tmp);
+		sync_loss = (MV_U8)tmp;
+		TSU_DPRINT(TSU_DBG_PROC, ("\tsync_loss = %d.\n",sync_loss));
+		write_sync = MV_TRUE;
+		goto done;
+	}
+
+	str = "aggr_mode ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		str = "dis";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			dev->buff_info.aggrMode = MV_TSU_AGGR_MODE_DISABLED;
+			goto done;
+		}
+		str = "mode1";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			dev->buff_info.aggrMode = MV_TSU_AGGR_MODE_1;
+			goto done;
+		}
+		str = "mode2";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			dev->buff_info.aggrMode = MV_TSU_AGGR_MODE_2;
+			goto done;
+		}
+		goto done;
+	}
+
+        str = "aggr_mode2_off ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		len += sscanf(buffer+len,"%d",&tmp);
+		dev->buff_info.aggrMode2TmstmpOff = tmp;
+		goto done;
+	}
+
+	str = "aggr_num_pckts ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		len += sscanf(buffer+len,"%d",&tmp);
+		dev->buff_info.aggrNumPackets = tmp;
+		goto done;
+	}
+
+	str = "num_desc ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		len += sscanf(buffer+len,"%d",&tmp);
+		dev->buff_info.numTsDesc = tmp;
+		goto done;
+	}
+
+	str = "num_done_queue ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		len += sscanf(buffer+len,"%d",&tmp);
+		dev->buff_info.numDoneQEntry = tmp;
+		goto done;
+	}
+
+	str = "sync_sig ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		TSU_STR_2_SIGNAL_MODE(signal_cfg.tsSync,buffer+len);
+                write_signal = MV_TRUE;
+		goto done;
+	}
+
+	str = "valid_sig ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		TSU_STR_2_SIGNAL_MODE(signal_cfg.tsValid,buffer+len);
+		write_signal = MV_TRUE;
+		goto done;
+	}
+
+	str = "error_sig ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		TSU_STR_2_SIGNAL_MODE(signal_cfg.tsError,buffer+len);
+		write_signal = MV_TRUE;
+		goto done;
+	}
+
+	str = "data_edge ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		str = "fall";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			signal_cfg.tsDataEdge = TSU_SIGNAL_EDGE_FALL;
+			write_signal = MV_TRUE;
+			goto done;
+		}
+		str = "rise";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			signal_cfg.tsDataEdge = TSU_SIGNAL_EDGE_RISE;
+			write_signal = MV_TRUE;
+			goto done;
+		}
+		goto done;
+	}
+
+	str = "data_order ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		str = "msb";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			flags |= MV_TSU_SER_DATA_ORDER_MSB;
+			write_signal = MV_TRUE;
+			goto done;
+		}
+		str = "lsb";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			flags |= MV_TSU_SER_DATA_ORDER_LSB;
+			write_signal = MV_TRUE;
+			goto done;
+		}
+		goto done;
+	}
+
+	str = "sync_act ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		len += sscanf(buffer+len,"%d",&tmp);
+		write_signal = MV_TRUE;
+		if(tmp == 1)
+			flags |= MV_TSU_SER_SYNC_ACT_1_BIT;
+		else if(tmp == 8)
+			flags |= MV_TSU_SER_SYNC_ACT_8_BIT;
+		else
+			write_signal = MV_FALSE;
+		goto done;
+	}
+
+	str = "clk_mode ";
+	if(!strncmp(buffer+len, str,strlen(str))) {
+		len += strlen(str);
+		str = "cont";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			flags |= MV_TSU_SER_TX_CLK_MODE_CONT;
+			write_signal = MV_TRUE;
+			goto done;
+		}
+		str = "gap";
+		if(!strncmp(buffer+len, str,strlen(str))) {
+			len += strlen(str);
+			flags |= MV_TSU_SER_TX_CLK_MODE_GAPPED;
+			write_signal = MV_TRUE;
+			goto done;
+		}
+		goto done;
+	}
+
+done:
+	if(write_signal == MV_TRUE){
+		mvTsuPortSignalCfgSet(port,&signal_cfg,flags);
+		dev->serial_sig_flags = flags;
+		dev->signal_cfg = signal_cfg;
+	}
+	if(write_sync == MV_TRUE){
+		mvTsuRxSyncDetectionSet(port,sync_detect,sync_loss);
+		dev->sync_loss = sync_loss;
+		dev->sync_detect = sync_detect;
+	}
+
+	TSU_LEAVE(TSU_DBG_PROC, "mvtsu_proc_write");
+	return count;
+}
+
+
+int mvtsu_proc_read_port(int port, char *buf)
+{
+	MV_U8	sync_detect, sync_loss;
+	MV_TSU_SIGNAL_CONFIG signal_cfg;
+	MV_U32 flags;
+	int len=0;
+
+	if(mvTsuRxSyncDetectionGet(port,&sync_detect,&sync_loss) != MV_OK)
+		return -1;
+	len += sprintf(buf,"\tsync_detect\t\t%d\t%d\tint\n",port,sync_detect);
+	len += sprintf(buf+len,"\tsync_loss\t\t%d\t%d\tint\n",port,sync_loss);
+
+	len += sprintf(buf+len,"\taggr_mode\t\t%d\t%s\t(mode1 / mode2 / dis)\n",
+		       port,
+		       TSU_AGGR_MODE_2_STR(mvtsu_devs[port].buff_info.aggrMode));
+	len += sprintf(buf+len,"\taggr_mode2_off\t\t%d\t%d\tint\n",
+		       port,mvtsu_devs[port].buff_info.aggrMode2TmstmpOff);
+	len += sprintf(buf+len,"\taggr_num_pckts\t\t%d\t%d\tint\n",
+		       port,mvtsu_devs[port].buff_info.aggrNumPackets);
+	len += sprintf(buf+len,"\tnum_desc\t\t%d\t%d\tint\n",
+		       port,mvtsu_devs[port].buff_info.numTsDesc);
+	len += sprintf(buf+len,"\tnum_done_queue\t\t%d\t%d\tint\n",
+		       port,mvtsu_devs[port].buff_info.numDoneQEntry);
+
+	if(mvTsuPortSignalCfgGet(port,&signal_cfg,&flags) != MV_OK)
+		return -1;
+	len += sprintf(buf+len,"\tsync_sig\t\t%d\t%s\t(dis / high / low)\n",
+		       port,TSU_SIGNAL_MODE_2_STR(signal_cfg.tsSync));
+	len += sprintf(buf+len,"\tvalid_sig\t\t%d\t%s\t(dis / high / low)\n",
+		       port,TSU_SIGNAL_MODE_2_STR(signal_cfg.tsValid));
+	len += sprintf(buf+len,"\terror_sig\t\t%d\t%s\t(dis / high / low)\n",
+		       port,TSU_SIGNAL_MODE_2_STR(signal_cfg.tsError));
+	len += sprintf(buf+len,"\tdata_edge\t\t%d\t%s\t(fall / rise)\n",
+		       port,(signal_cfg.tsDataEdge == TSU_SIGNAL_EDGE_FALL) ?
+		       "fall" : "rise");
+
+	if(cfg_tsu_mode == TSU_MODE_SERIAL) {
+		len += sprintf(buf+len,"\tdata_order\t\t%d\t%s\t(msb / lsb)\n",
+			       port,(flags & MV_TSU_SER_DATA_ORDER_MSB) ? "msb" : "lsb");
+		len += sprintf(buf+len,"\tsync_act\t\t%d\t%d\t(1 / 8)\n",
+			       port,(flags & MV_TSU_SER_SYNC_ACT_1_BIT) ? 1 : 8);
+		len += sprintf(buf+len,"\tclk_mode\t\t%d\t%s\t(cont / gap)\n",
+			       port,
+			       (flags & MV_TSU_SER_TX_CLK_MODE_CONT) ? "cont" : "gap");
+	}
+	return len;
+}
+
+
+int mvtsu_proc_read(char* page, char** start, off_t off, int count,int* eof,
+		    void* data)
+{
+	int len = 0;
+	int i;
+	int res;
+
+	if(off > 0)
+		return 0;
+	len += sprintf(page,"\tParameter\t\tPort\tValue\tPossible Values\n\n");
+
+	for(i = 0; i < MV_TSU_NUM_PORTS; i++) {
+                res = mvtsu_proc_read_port(i,page+len);
+		if(res < 0) {
+			len = -1;
+			break;
+		}
+		len += res;
+	}
+	if(len != -1)
+		len += sprintf(page+len,"\nConfig String: <port> <attr> <val>\n");
+
+	return len;
+}
+
+
+/*
+ * Create TSU proc entry.
+ */
+static int mvtsu_proc_init(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+	mvtsu_proc_entry = create_proc_entry("tsu", 0666, &proc_root);
+	mvtsu_proc_entry->owner = THIS_MODULE;
+#else
+	mvtsu_proc_entry = create_proc_entry("tsu", 0666, NULL);
+#endif
+	mvtsu_proc_entry->read_proc = mvtsu_proc_read;
+	mvtsu_proc_entry->write_proc = mvtsu_proc_write;
+	return 0;
+}
+
+#endif /* CONFIG_MV_TSU_PROC */
+
+
+/*
+ * Parse the TSU command line.
+ * The command line looks as follows:
+ * mv_tsu_config=<interface mode>,<packet size>,<core clock in MHz>
+ * e.g. serial,188,73
+ */
+int mvtsu_cmdline_config(char *s)
+{
+    mvtsu_cmdline = s;
+    return 1;
+}
+
+static int mvtsu_parse_core_clk(char **cmdline)
+{
+	char *str = *cmdline;
+	int num = 0;
+
+	while(*str != '\0') {
+		if(!TSU_IS_DEC_DIGIT(*str))
+			return -1;
+		num = (num * 10) + (*str - '0');
+		str++;
+	}
+
+	switch (num) {
+	case(71):
+		cfg_core_clk = TSU_CORE_CLK_71_MHZ;
+                break;
+	case(83):
+		cfg_core_clk = TSU_CORE_CLK_83_MHZ;
+		break;
+	case(91):
+		cfg_core_clk = TSU_CORE_CLK_91_MHZ;
+		break;
+	case(100):
+		cfg_core_clk = TSU_CORE_CLK_100_MHZ;
+		break;
+	default:
+		return -1;
+	}
+
+	*cmdline = str;
+	return 0;
+}
+
+
+static int mvtsu_parse_pkt_size(char **cmdline)
+{
+	char *str = *cmdline;
+	int num = 0;
+
+	while((*str != '\0') && (*str != ',')) {
+		if(!TSU_IS_DEC_DIGIT(*str))
+			return -1;
+		num = (num * 10) + (*str - '0');
+		str++;
+	}
+	if((*str == ',') && (num != 0)) {
+		cfg_pkt_size = num;
+		*cmdline = str;
+		return 0;
+	}
+	return -1;
+}
+
+
+static int mvtsu_parse_mode(char **cmdline)
+{
+	char *str;
+
+	str = "serial";
+	if(!strncmp(*cmdline,str,strlen(str))) {
+		cfg_tsu_mode = TSU_MODE_SERIAL;
+		*cmdline += strlen(str);
+	} else {
+                str = "parallel";
+		if(!strncmp(*cmdline,str,strlen(str))) {
+			cfg_tsu_mode = TSU_MODE_PARALLEL;
+			*cmdline += strlen(str);
+			return 0;
+		}
+	}
+	return 0;
+}
+
+
+static int mvtsu_parse_cmdline(void)
+{
+	char *cmdline;
+
+	if(mvtsu_cmdline) {
+		TSU_DPRINT(TSU_DBG_INIT, ("TSU command line: %s.\n",mvtsu_cmdline));
+		cmdline = mvtsu_cmdline;
+		if(mvtsu_parse_mode(&cmdline) != 0) {
+			printk(KERN_ERR "TSU: Bad interface mode option in command line, using default.\n");
+			goto set_default;
+		}
+                if(cmdline[0] != ',') {
+			printk(KERN_ERR "TSU: Bad command line format (Expected ',' found %c).\n",
+			       cmdline[0]);
+		}
+		cmdline++;
+		if(mvtsu_parse_pkt_size(&cmdline) != 0) {
+			printk(KERN_ERR "TSU: Bad packet size option in command line, using default.\n");
+			goto set_default;
+		}
+		if(cmdline[0] != ',') {
+			printk(KERN_ERR "TSU: Bad command line format (Expected ',' found %c).\n",
+			       cmdline[0]);
+		}
+		cmdline++;
+		if(mvtsu_parse_core_clk(&cmdline) != 0) {
+			printk(KERN_ERR "TSU: Bad core-clock option in command line "
+					"(Expected 71 / 83 / 91 / 100), using default.\n");
+			goto set_default;
+		}
+		goto success;
+	} else {
+		printk(KERN_INFO "TSU: No command line parameters, using default.\n");
+	}
+
+set_default:
+	cfg_tsu_mode = DEF_TSU_MODE;
+	cfg_core_clk = DEF_TSU_CORE_CLOCK;
+	cfg_pkt_size = CONFIG_MV_TSU_PKT_SIZE;
+success:
+	return 0;
+}
+
+
+struct file_operations mvtsu_fops = {
+	.owner =     THIS_MODULE,
+	.read =	     mvtsu_read,
+	.write =     mvtsu_write,
+	.ioctl =     mvtsu_ioctl,
+	.open =	     mvtsu_open,
+	.release =   mvtsu_release,
+};
+
+/*
+ * Initialize the TSU driver
+ */
+int mvtsu_init(void)
+{
+	int result, i;
+	dev_t dev;
+
+        TSU_ENTER(TSU_DBG_INIT, "mvtsu_init");
+
+	/* Check unit power mode.		*/
+	if(mvCtrlPwrClckGet(TS_UNIT_ID,0) == MV_FALSE) {
+		printk("Warning: TS unit is powered off.\n");
+		TSU_LEAVE(TSU_DBG_INIT, "mvtsu_init");
+		return 0;
+	}
+
+	/* Parse command line parameters.	*/
+	mvtsu_parse_cmdline();
+
+	dev = MKDEV(MV_TSU_MAJOR, 0);
+	result = register_chrdev_region(dev, TSU_NUM_DEVICES, TSU_DEV_NAME);
+
+	if (result < 0) {
+		printk("Failed to register char device (%d,%d)\n",result, TSU_NUM_DEVICES);
+		TSU_LEAVE(TSU_DBG_INIT, "mvtsu_init");
+		return result;
+	}
+
+	/* Perform unit initialization.	*/
+	result = mvSysTsuInit(cfg_core_clk, cfg_tsu_mode ,NULL);
+	if(result != MV_OK) {
+		goto fail_init;
+		result = -EINVAL;
+	}
+	TSU_DPRINT(TSU_DBG_INIT, ("\tTSU unit initialized successfully.\n"));
+
+	/* Create the char device.	*/
+	for (i = 0; i < TSU_NUM_DEVICES; i++) {
+		mvtsu_devs[i].port = i;
+		mvtsu_set_defaults(&mvtsu_devs[i]);
+		cdev_init(&mvtsu_devs[i].cdev, &mvtsu_fops);
+		mvtsu_devs[i].cdev.owner = THIS_MODULE;
+		mvtsu_devs[i].cdev.ops = &mvtsu_fops;
+		dev = MKDEV(MV_TSU_MAJOR, i);
+		result = cdev_add (&mvtsu_devs[i].cdev, dev, 1);
+		if (result) {
+			printk(KERN_ERR "Error %d adding tsu%d", result, i);
+			goto fail_add;
+		}
+		spin_lock_init(&mvtsu_devs[i].lock);
+		TSU_DPRINT(TSU_DBG_INIT, ("\tChar device %d initialized.\n",i));
+	}
+
+#ifdef CONFIG_MV_TSU_PROC
+	TSU_DPRINT(TSU_DBG_INIT, ("\tCreating Proc entry.\n"));
+	mvtsu_proc_init();
+#endif /* CONFIG_MV_TSU_PROC */
+
+	printk("Transport Stream interface registered.\n");
+	printk("  o %s Mode.\n",
+	       (cfg_tsu_mode == TSU_MODE_PARALLEL) ? "Parallel" : "Serial");
+	printk("  o Core-Clock - ");
+	switch (cfg_core_clk) {
+	case (TSU_CORE_CLK_83_MHZ):
+		printk("83");
+		break;
+	case (TSU_CORE_CLK_71_MHZ):
+		printk("71");
+		break;
+	case (TSU_CORE_CLK_91_MHZ):
+		printk("91");
+		break;
+	case (TSU_CORE_CLK_100_MHZ):
+		printk("100");
+		break;
+	}
+	printk(" MHz.\n");
+	printk("  o Packet Size - %d Bytes.\n",cfg_pkt_size);
+	TSU_LEAVE(TSU_DBG_INIT, "mvtsu_init");
+	return 0;
+
+fail_add:
+	while(i > 0) {
+		cdev_del(&mvtsu_devs[i-1].cdev);
+		i--;
+	}
+
+fail_init:
+	dev = MKDEV(MV_TSU_MAJOR, 0);
+	unregister_chrdev_region(dev, TSU_NUM_DEVICES);
+
+	TSU_LEAVE(TSU_DBG_INIT, "mvtsu_init");
+	return result;
+}
+
+
+/*
+ * Cleanup the TSU driver.
+ */
+void mvtsu_cleanup(void)
+{
+	int i;
+
+	TSU_ENTER(TSU_DBG_INIT, "mvtsu_cleanup");
+	for(i = 0; i < TSU_NUM_DEVICES; i++) {
+		cdev_del(&mvtsu_devs[i].cdev);
+	}
+
+	unregister_chrdev_region(mvtsu_device, TSU_NUM_DEVICES);
+
+	mvTsuShutdown();
+
+	TSU_LEAVE(TSU_DBG_INIT, "mvtsu_cleanup");
+}
+
+module_init(mvtsu_init);
+module_exit(mvtsu_cleanup);
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu.h
new file mode 100755
index 0000000..9845a8c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu.h
@@ -0,0 +1,49 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#ifndef __MV_TSU_H__
+#define __MV_TSU_H__
+
+
+#define MV_TSU_MAJOR		MV_TS_MAJOR
+
+#define TSU_DFLT_AGGR_MODE 	MV_TSU_AGGR_MODE_DISABLED
+#define TSU_DFLT_TMSTMP_OFFS	4
+#define TSU_DFLT_AGGR_PCKT_NUM	1
+#define TSU_DFLT_TS_DESC_NUM	512 //Rx: 512 // Tx: 256
+#define TSU_DFLT_TS_DONEQ_NUM	TSU_DFLT_TS_DESC_NUM * TSU_DFLT_AGGR_PCKT_NUM
+#define TSU_DFLT_DATA_READ_AT_ONCE	0
+#define TSU_DFLT_CLOCK_RATE	20000000
+
+
+#define TSU_DFLT_INT_MASK	(TSU_INT_TS_IF_ERROR |		\
+                                 TSU_INT_FIFO_OVFL_ERROR |	\
+                                 TSU_INT_TS_CONN_ERROR |	\
+                                 TSU_INT_CLOCK_SYNC_EXP | 0x7F)
+
+#endif /* __MV_TSU_H__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu_ioctl.h b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu_ioctl.h
new file mode 100755
index 0000000..2a5d954
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/mv_tsu_ioctl.h
@@ -0,0 +1,79 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#ifndef __MV_TSU_IOCTL_H__
+#define __MV_TSU_IOCTL_H__
+
+#define TSU_STATUS_ERROR_GET(status)		((status >> 28) & 0x1)
+#define TSU_STATUS_ERROR_SET(status)		(status = status | (0x1 << 28))
+#define TSU_STATUS_TMSSTMP_GET(status)		(status & 0xFFFFFFF)
+#define TSU_STATUS_TMSSTMP_SET(status,tms)	(status = status | (tms & 0xFFFFFFF))
+
+struct tsu_tmstmp_info {
+	unsigned int timestamp;
+	unsigned char enable_tms;
+};
+
+
+enum tsu_aggr_mode {
+	aggrModeDisabled,
+	aggrMode1,
+	aggrMode2
+};
+
+struct tsu_buff_info {
+	enum tsu_aggr_mode aggr_mode;
+	unsigned char aggr_mode2_tmstmp_off;
+	unsigned char aggr_num_packets;
+
+	unsigned int num_ts_desc;
+	unsigned int num_done_q_entries;
+	int pkt_size;
+};
+
+
+struct tsu_stat {
+	unsigned int ts_if_err;
+	unsigned int fifo_ovfl;
+	unsigned int ts_conn_err;
+	unsigned int clk_sync_exp;
+};
+
+
+#define MVTSU_IOC_MAGIC  'T'
+
+#define MVTSU_IOCFREQSET	_IOW(MVTSU_IOC_MAGIC,1, unsigned int)
+#define MVTSU_IOCTXTMSSET	_IOW(MVTSU_IOC_MAGIC,2, struct tsu_tmstmp_info)
+#define MVTSU_IOCTXDONE		_IO(MVTSU_IOC_MAGIC,3)
+#define MVTSU_IOCRDPKTATONCE	_IOW(MVTSU_IOC_MAGIC,4, unsigned int)
+#define MVTSU_IOCBUFFPARAMGET	_IOR(MVTSU_IOC_MAGIC,5, struct tsu_buff_info)
+#define MVTSU_IOCGETSTAT	_IOR(MVTSU_IOC_MAGIC,6, struct tsu_stat)
+#define MVTSU_IOCCLEARSTAT	_IO(MVTSU_IOC_MAGIC,7)
+#define MVTSU_IOCAUTOTMS	_IOW(MVTSU_IOC_MAGIC,8, unsigned int)
+
+#endif /* __MV_TSU_IOCTL_H__ */
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/Makefile
new file mode 100755
index 0000000..bcf7f40
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the Marvell USB device controller
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+USB_DIR := ../mv_hal/usb/
+USB_PATH := $(srctree)/arch/arm/plat-feroceon/mv_hal/usb
+
+USB_DEV_DIR := $(USB_DIR)/device
+
+EXTRA_CFLAGS += -I$(USB_PATH)/api -I$(USB_PATH)/common -I$(USB_PATH)/device
+
+OBJS        := mv_udc_main.o ../$(USB_DEV_DIR)/mvUsbDevCh9.o ../$(USB_DEV_DIR)/mvUsbDevMain.o 	\
+               ../$(USB_DEV_DIR)/mvUsbDevRecv.o ../$(USB_DEV_DIR)/mvUsbDevSend.o ../$(USB_DEV_DIR)/mvUsbDevUtl.o 	\
+	       ../$(USB_DEV_DIR)/mvUsbHsDevUtl.o  ../$(USB_DEV_DIR)/mvUsbHsDevMain.o ../$(USB_DEV_DIR)/mvUsbHsDevCncl.o
+
+mv_udc-objs := $(OBJS)
+obj-m := mv_udc.o
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/README b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/README
new file mode 100755
index 0000000..9b7fbaa
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/README
@@ -0,0 +1,86 @@
+
+Introduction:
++++++++++++++
+This is a USB gadget driver for Marvell SoC:
+There are two Linux Gadget examples are working above the gadget driver
+mv_usb_gadget.ko  - an USB device Gadget driver module.
+g_file_storage.ko - a Kernel USB file storage gadget module.
+g_ether.ko        - a Kernel USB Ethernet gadget module
+
+In order to use this module make sure that one of USB Controllers on the board 
+is configured as a USB device. It means that the UBoot environment variable usb0Mode 
+(or usb1Mode if exist) is set to "device".
+
+Compile:
+++++++++
+
+To compile mv_usb_gadget.ko:
+1. Go to linux Kernel directory
+...
+To compile g_file_storage.ko and g_ether.ko:
+1. Choose in the config option 'Support for USB Gadgets' to be module 'M' 
+   and choose 'USB Peripheral Controller' to be 'Dummy HCD'
+2. => M=arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc
+3. Copy g_file_storage.ko and g_ether.ko from drivers/usb/gadget/
+
+
+Run g_file_storage.ko example:
+++++
+Under the ARM FS:
+    On the first time we need to create a file which will be use as the gadget file storage:
+    'dd bs=1M count=64 if=/dev/zero of=/root/diskFile'   # 64M file storage initialized with zeros 
+
+    Load modules:
+    'insmod mv_udc.ko'
+    With NFS:
+    --------
+    'insmod g_file_storage.ko file=/root/diskFile use_directio=0'
+
+    With HD:
+    --------
+    'insmod g_file_storage.ko file=/root/diskFile'	
+
+Connect a USB cable from the device connector to a Host computer.
+
+On the first connection we need to initialize the disk:
+----------------------
+ on windows :
+	    choose my computer + right_click -> manage:
+	    choose Disk management:	
+	    initialize the new Disk and create a partition on it.
+ on Linux :
+  X - storage id (a,b,c ..)  Y - partition id (1,2,..) DIR - directory name.
+  --create partition table:
+        'fdisk /dev/sdX' (check help for more info, p - display all partition
+                                                n - create a new partition (use primary)
+                                                d - delete a partition
+                                                w - write changes made to the HD)
+  --create a new FS on one of the partitions:
+        'mkfs.ext3 /dev/sdXY'
+
+  --mount one of the partitions:
+        'mkdir /root/mnt/DIR'
+        'mount /dev/sdXY /root/mnt/DIR'
+
+
+Run g_ether.ko example:
+++++
+Under the ARM FS:
+-----------------
+    Load modules:
+    'insmod mv_usb_gadget.ko'
+    'insmod g_ether.ko'
+
+    Configure USB interface:
+    'ifconfig usb0 11.4.0.1'
+
+Connect a USB cable from the device connector to a Host computer.
+
+On Host computer:
+-----------------
+on windows :
+    choose My Network Places + right_click -> Properties
+    choose Linux USB Ethernet/RNDIS Gadget connection + right_click -> Properties
+    Configure specific IP address for this interface (e.g. 11.4.0.100)
+
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/mv_udc_main.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/mv_udc_main.c
new file mode 100755
index 0000000..ba1031e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/mv_udc_main.c
@@ -0,0 +1,2022 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+        this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+ 
+#include "mvOs.h"
+#include "config/mvSysHwConfig.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "usb/api/mvUsbDevApi.h"
+#include "usb/api/mvUsbCh9.h"
+#include "usb/mvUsb.h"
+#include "usb/mvUsbRegs.h"
+
+#include <linux/module.h> 
+#include <linux/moduleparam.h>
+#include <linux/wait.h>
+#include <linux/usb/ch9.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+#include <linux/usb_gadget.h>
+#else
+#include <linux/usb/gadget.h>
+#endif
+#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+
+#ifdef MV_USB_VOLTAGE_FIX
+
+#define MV_USB_CONNECTED	1
+#define MV_USB_DISCONNECTED	2
+
+static int mv_usb_initialize_kobject (void);
+
+#endif /* MV_USB_VOLTAGE_FIX */
+
+#if defined(CONFIG_MV645xx) || defined(CONFIG_MV646xx)
+#   include "marvell_pic.h"
+#endif /* CONFIG_MV645xx */
+
+#ifdef CONFIG_SMP
+#define MV_SPIN_LOCK_IRQSAVE(spinlock,flags) \
+if(!in_interrupt())  \
+spin_lock_irqsave(spinlock, flags)
+
+#define MV_SPIN_UNLOCK_IRQRESTORE(spinlock,flags) \
+if(!in_interrupt())  \
+spin_unlock_irqrestore(spinlock, flags)
+
+#else /* CONFIG_SMP */
+
+#define MV_SPIN_LOCK_IRQSAVE(spinlock,flags) spin_lock_irqsave(spinlock, flags)
+#define MV_SPIN_UNLOCK_IRQRESTORE(spinlock,flags) spin_unlock_irqrestore(spinlock, flags)
+
+#endif /* CONFIG_SMP */
+
+
+/*  
+ *  Enable/Disable Streaming mode for USB Core
+ */
+/*#if (defined(CONFIG_MV88F6082) || defined(CONFIG_MV645xx) || defined(USB_UNDERRUN_WA))*/
+#if (MV_USB_VERSION >= 1) || defined(USB_UNDERRUN_WA)
+static int streaming = 1;  
+#else
+static int streaming = 0;  
+#endif
+module_param_named(streaming, streaming, int, S_IRUGO);
+MODULE_PARM_DESC(streaming, "0 - Streaming Disable, 1 - Streaming Enable");
+
+static int epin_first = 1;  
+module_param_named(epin_first, epin_first, int, S_IRUGO);
+MODULE_PARM_DESC(epin_first, "First choose of IN endpoint number");
+
+static int epout_first = 1;  
+module_param_named(epout_first, epout_first, int, S_IRUGO);
+MODULE_PARM_DESC(epout_first, "First choose of OUT endpoint number");
+
+#if defined(USB_UNDERRUN_WA)
+#include "mvIdma.h" 
+
+extern int              mv_idma_usage_get(int* free_map);
+extern unsigned char*   mv_sram_usage_get(int* sram_size_ptr);
+
+
+#define USB_IDMA_CTRL_LOW_VALUE       ICCLR_DST_BURST_LIM_128BYTE   \
+                                    | ICCLR_SRC_BURST_LIM_128BYTE   \
+                                    | ICCLR_BLOCK_MODE              \
+                                    | ICCLR_DESC_MODE_16M
+
+/*  
+ *  0..3   - use specifed IDMA engine. If the engine is busy - find free one.
+ *  Other  - don't use IDMA (use memcpy instead)
+ */
+static int idma = 1;  
+module_param_named(idma, idma, int, S_IRUGO);
+MODULE_PARM_DESC(idma, "IDMA engine used for copy from DRAM to SRAM [0..3]");
+
+/*  
+ */
+static int wa_sram_parts  = 2;  
+module_param_named(wa_sram_parts, wa_sram_parts, int, S_IRUGO);
+MODULE_PARM_DESC(wa_sram_parts, "");
+
+static int wa_sram_descr  = 1;  
+module_param_named(wa_sram_descr, wa_sram_descr, int, S_IRUGO);
+MODULE_PARM_DESC(wa_sram_descr, "");
+
+/*  
+ */
+static int wa_threshold = 64;  
+module_param_named(wa_threshold, wa_threshold, int, S_IRUGO);
+MODULE_PARM_DESC(wa_threshold, "");
+
+
+static char*    sramBase = (char*)NULL;
+static int      sramSize = 0;
+
+u32     mvUsbSramGet(u32* pSize)
+{
+    char*   pBuf;
+
+    /* Align address to 64 bytes */
+    pBuf = (char*)MV_ALIGN_UP((u32)sramBase, 64);
+
+    if(pSize != NULL)
+    {
+        *pSize = sramSize - (pBuf - sramBase);
+    }
+/*
+    mvOsPrintf("mvUsbSramGet: Base=%p (%p), Size=%d (%d)\n", 
+                sramBase, pBuf, sramSize, *pSize);
+*/
+    return (u32)pBuf;
+}
+
+void        mvUsbIdmaToSramCopy(void* sram_buf, void* src_buf, unsigned int size)
+{
+    unsigned long phys_addr;
+
+/*
+    mvOsPrintf("IdmaToSramCopy: idma=%d, sram=%p, src=%p (0x%x)\n", 
+                    usbWaIdma, sram_buf, src_buf, phys_addr);
+*/
+    if( (idma >= 0) && (idma < MV_IDMA_MAX_CHAN) )
+    {
+        phys_addr = pci_map_single(NULL, src_buf, size, PCI_DMA_TODEVICE );
+
+        /* !!!! SRAM Uncached */
+        /*mvOsCacheInvalidate(NULL, sram_buf, size);*/
+
+        mvDmaTransfer(idma, (MV_U32)phys_addr, 
+                      (MV_U32)sram_buf, size, 0);
+
+        /* Wait until copy is finished */
+        while( mvDmaStateGet(idma) != MV_IDLE );
+    }
+    else
+    {
+        /* mvOsPrintf("usbWA: copy to SRAM %d bytes: \n", size); */
+        memcpy(sram_buf, src_buf, size);
+        /* !!!! SRAM Uncached */
+        /*mvOsCacheFlush(NULL, sram_buf, size);*/
+    }
+}
+
+USB_WA_FUNCS    usbWaFuncs = 
+{
+    mvUsbSramGet,
+    mvUsbIdmaToSramCopy
+};
+
+int mv_usb_find_idma_engine(int idma_no)
+{
+    int idma, free = 0;
+    int free_map[MV_IDMA_MAX_CHAN];
+
+    if( (idma_no < 0) || (idma_no >= MV_IDMA_MAX_CHAN) )
+    {
+        mvOsPrintf("Wrong IDMA number (%d): Valid range [0..%d]\n", 
+                    idma_no, (MV_IDMA_MAX_CHAN-1) );
+        return -1;
+    }
+    free = mv_idma_usage_get(free_map);
+    if(free == 0)
+    {
+        mvOsPrintf("No free IDMAs for USB Underrun WA: use memcpy\n");
+        return -1;
+    }
+    /* First of all check user idma_no */
+    if(free_map[idma_no] != 0)
+        return idma_no;
+
+    /* User idma_no is Busy. Look for free IDMA engine */
+    for(idma=0; idma<MV_IDMA_MAX_CHAN; idma++)
+    {
+        if(free_map[idma] != 0)
+            break;
+    }
+    mvOsPrintf("IDMA engine #%d is Busy. Use IDMA engine #%d instead\n", idma_no, idma);
+    return idma;
+}
+#endif /* USB_UNDERRUN_WA */
+
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBGMSG(fmt,args...)    \
+             mvOsPrintf(fmt , ## args)
+#else
+#   define DBGMSG(fmt,args...)
+#endif /* DEBUG */
+
+#define DRIVER_VERSION  "05-July-2006"
+#define DRIVER_DESC "Marvell Gadget USB Peripheral Controller"
+
+struct mv_usb_dev;
+
+struct mv_usb_ep 
+{
+    struct usb_ep       ep;
+    struct mv_usb_dev*  usb_dev;
+    struct list_head    req_list;
+    unsigned            num : 8,
+                        is_enabled : 1,
+                        is_in : 1;
+};
+
+struct mv_usb_dev 
+{
+    /* each pci device provides one gadget, several endpoints */
+    struct usb_gadget           gadget;
+    spinlock_t                  lock;
+    struct usb_gadget_driver    *driver;
+    struct mv_usb_ep            ep[2*ARC_USB_MAX_ENDPOINTS];
+    unsigned                    enabled : 1,
+                                protocol_stall : 1,
+                                got_irq : 1;
+    u16                         chiprev;
+    struct device               *dev; 
+    void*                       mv_usb_handle;
+    int                         dev_no;
+    MV_U8                       vbus_gpp_no;
+};
+
+void    mv_usb_show(struct mv_usb_dev* mv_dev, unsigned int mode);
+
+extern void   _usb_dci_vusb20_isr(pointer);
+
+static void* mvUsbMalloc(unsigned int size)
+{
+    return kmalloc(size,GFP_ATOMIC);
+}
+
+static void mvUsbFree(void* buf)
+{
+    return kfree(buf);
+}
+
+static void* mvUsbIoUncachedMalloc( void* pDev, MV_U32 size, MV_U32 alignment, 
+                                    MV_ULONG* pPhyAddr )
+{
+#if defined(USB_UNDERRUN_WA)
+    if(wa_sram_descr != 0)
+    {
+        char*   pBuf;
+
+        pBuf = (char*)MV_ALIGN_UP((MV_U32)sramBase, alignment);
+        size += (pBuf - sramBase);
+        if( (sramSize < size) )
+        {
+            mvOsPrintf("SRAM malloc failed: Required %d bytes - Free %d bytes\n", 
+                        size, sramSize);
+            return NULL;
+        }
+        if(pPhyAddr != NULL)
+            *pPhyAddr = (MV_ULONG)sramBase;
+/*
+        mvOsPrintf("usbUncachedMalloc: , pBuf=%p (%p), size=%d, align=%d\n", 
+                sramBase, pBuf, size, alignment);
+*/
+        pBuf = sramBase;
+
+        sramSize -= size;
+        sramBase += size;
+
+        return pBuf;
+    }
+#endif 
+    return pci_alloc_consistent( pDev, size+alignment, (dma_addr_t *)pPhyAddr );
+}
+
+static void mvUsbIoUncachedFree( void* pDev, MV_U32 size, MV_ULONG phyAddr, void* pVirtAddr )
+{
+#if defined(USB_UNDERRUN_WA)
+    if(wa_sram_descr != 0)
+    {
+        return;
+    }
+#endif 
+    return pci_free_consistent( pDev, size, pVirtAddr, (dma_addr_t)phyAddr );
+} 
+
+static MV_ULONG mvUsbCacheInvalidate( void* pDev, void* p, int size )
+{
+#if defined(USB_UNDERRUN_WA)
+    if( ((char*)p >= sramBase) && 
+        ((char*)p < (sramBase + sramSize)) )
+        return (unsigned long)p;
+#endif
+
+    return pci_map_single( pDev, p, size, PCI_DMA_FROMDEVICE );
+}
+
+static MV_ULONG mvUsbCacheFlush( void* pDev, void* p, int size )
+{
+#if defined(USB_UNDERRUN_WA)
+    if( ((char*)p >= sramBase) && 
+        ((char*)p < (sramBase + sramSize)) )
+        return (unsigned long)p;
+#endif
+
+    return pci_map_single( pDev, p, size, PCI_DMA_TODEVICE );
+}
+
+static unsigned long mvUsbVirtToPhys(void* pDev, void* pVirtAddr)
+{
+#if defined(USB_UNDERRUN_WA)
+    if( ((char*)pVirtAddr >= sramBase) && 
+        ((char*)pVirtAddr < (sramBase + sramSize)) )
+        return (unsigned long)pVirtAddr;
+#endif 
+
+    return virt_to_phys(pVirtAddr);
+}
+
+static void   usbDevResetComplete(int devNo)
+{
+    MV_U32  regVal; 
+
+    regVal = MV_USB_CORE_MODE_DEVICE | MV_USB_CORE_SETUP_LOCK_DISABLE_MASK;
+    if(streaming == 0)    
+        regVal |= MV_USB_CORE_STREAM_DISABLE_MASK; 
+
+    /* Set USB_MODE register */
+    MV_REG_WRITE(MV_USB_CORE_MODE_REG(devNo), regVal); 
+}
+
+extern MV_U32   mvUsbGetCapRegAddr(int devNo);
+
+
+USB_IMPORT_FUNCS    usbImportFuncs =
+{
+    mvOsPrintf,
+    mvOsSPrintf,
+    mvUsbIoUncachedMalloc,
+    mvUsbIoUncachedFree,
+    mvUsbMalloc,
+    mvUsbFree,
+    memset,
+    memcpy,
+    mvUsbCacheFlush,
+    mvUsbCacheInvalidate,
+    mvUsbVirtToPhys,
+    NULL,
+    NULL,
+    mvUsbGetCapRegAddr,
+    usbDevResetComplete
+};
+
+
+static struct mv_usb_dev*   the_controllers[MV_USB_MAX_PORTS] = {NULL};
+
+static const char driver_name [] = "mv_udc";
+static const char driver_desc [] = DRIVER_DESC;
+
+static char ep_names [2*ARC_USB_MAX_ENDPOINTS][10] = 
+{
+    "ep0out", "ep0in", 
+};
+ 
+
+ 
+
+static struct usb_ep_ops mv_usb_ep_ops;
+
+static void mv_usb_ep_cancel_all_req(struct mv_usb_ep *mv_ep)
+{
+    struct mv_usb_dev*      mv_dev = mv_ep->usb_dev;
+    struct usb_request*     usb_req;
+    int                     req_cntr, tr_cntr;
+
+    req_cntr = tr_cntr = 0;
+
+    /* Cancel all transfers */
+    while(_usb_device_get_transfer_status(mv_dev->mv_usb_handle, mv_ep->num, 
+           mv_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV) != ARC_USB_STATUS_IDLE)
+   {
+        tr_cntr++;
+       _usb_device_cancel_transfer(mv_dev->mv_usb_handle, mv_ep->num, 
+                           mv_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV);
+    }
+/*
+    if(tr_cntr > 0)
+    {
+        mvOsPrintf("Cancel ALL transfers: ep=%d-%s, %d transfers\n", 
+                        mv_ep->num, mv_ep->is_in ? "in" : "out", tr_cntr);
+    }
+*/
+    while (!list_empty (&mv_ep->req_list)) 
+    {
+        usb_req = list_entry (mv_ep->req_list.next, struct usb_request, list);
+
+        /* Dequeue request and call complete function */
+        list_del_init (&usb_req->list);
+
+        if (usb_req->status == -EINPROGRESS)
+            usb_req->status = -ESHUTDOWN;
+
+        usb_req->complete (&mv_ep->ep, usb_req);
+        req_cntr++;
+        if(req_cntr >= MAX_XDS_FOR_TR_CALLS)
+            break;
+    }
+/*
+    if(req_cntr > 0)
+    {
+        mvOsPrintf("Cancel ALL Requests: ep=%d-%s, %d requests\n", 
+                        mv_ep->num, mv_ep->is_in ? "in" : "out", req_cntr);
+        _usb_stats(mv_dev->mv_usb_handle);
+    }
+*/
+}
+
+static uint_8 mv_usb_start_ep0(struct mv_usb_dev *mv_dev)
+{
+    DBGMSG("%s: mv_dev=%p, mv_usb_handle=%p, mv_ep=%p, usb_ep=%p\n", 
+           __FUNCTION__, mv_dev, mv_dev->mv_usb_handle, &mv_dev->ep[0], &mv_dev->ep[0].ep);
+
+    /* Init ep0 IN and OUT */
+    mv_dev->ep[0].is_enabled = 1;
+
+    _usb_device_init_endpoint(mv_dev->mv_usb_handle, 0, mv_dev->ep[0].ep.maxpacket, 
+                                ARC_USB_SEND,  ARC_USB_CONTROL_ENDPOINT, 0);
+
+    _usb_device_init_endpoint(mv_dev->mv_usb_handle, 0, mv_dev->ep[0].ep.maxpacket, 
+                                ARC_USB_RECV, ARC_USB_CONTROL_ENDPOINT, 0);
+
+    return USB_OK;
+}
+
+static void   mv_usb_ep_init(struct mv_usb_ep *ep, int num, int is_in)
+{
+    sprintf(&ep_names[num*2+is_in][0], "ep%d%s", num, is_in ? "in" : "out");
+    ep->ep.name = &ep_names[num*2+is_in][0];
+
+    ep->num = num;
+    ep->is_in = is_in;
+    ep->is_enabled = 0;
+
+    INIT_LIST_HEAD (&ep->req_list);
+    
+    ep->ep.maxpacket = ~0;
+    ep->ep.ops = &mv_usb_ep_ops;
+}
+
+static uint_8 mv_usb_reinit (struct mv_usb_dev *usb_dev)
+{
+    int                 i, ep_num;
+    struct mv_usb_ep    *ep;
+
+    DBGMSG("%s: mv_dev=%p, mv_usb_handle=%p\n", 
+           __FUNCTION__, usb_dev, usb_dev->mv_usb_handle);
+
+    INIT_LIST_HEAD (&usb_dev->gadget.ep_list);
+
+    /* Enumerate IN endpoints */
+    ep_num = epin_first;
+    for(i=0; i<_usb_device_get_max_endpoint(usb_dev->mv_usb_handle); i++)
+    {
+        ep = &usb_dev->ep[ep_num*2+1];
+        if (ep_num != 0)
+        {
+            INIT_LIST_HEAD(&ep->ep.ep_list);
+            list_add_tail (&ep->ep.ep_list, &usb_dev->gadget.ep_list);
+        }
+        mv_usb_ep_init(ep, ep_num, 1);
+        ep->usb_dev = usb_dev;
+
+        ep_num++;
+        if(ep_num == _usb_device_get_max_endpoint(usb_dev->mv_usb_handle))
+            ep_num = 0;
+    }
+
+    /* Enumerate OUT endpoints */
+    ep_num = epout_first;
+    for(i=0; i<_usb_device_get_max_endpoint(usb_dev->mv_usb_handle); i++)
+    {
+        ep = &usb_dev->ep[ep_num*2];
+        if (ep_num != 0)
+        {
+            INIT_LIST_HEAD(&ep->ep.ep_list);
+            list_add_tail (&ep->ep.ep_list, &usb_dev->gadget.ep_list);
+        }
+        mv_usb_ep_init(ep, ep_num, 0);
+        ep->usb_dev = usb_dev;
+
+        ep_num++;
+        if(ep_num == _usb_device_get_max_endpoint(usb_dev->mv_usb_handle))
+            ep_num = 0;
+    }
+    usb_dev->ep[0].ep.maxpacket = 64;
+    usb_dev->gadget.ep0 = &usb_dev->ep[0].ep;
+    INIT_LIST_HEAD (&usb_dev->gadget.ep0->ep_list);
+    return USB_OK;
+}
+
+void mv_usb_bus_reset_service(void*      handle, 
+                               uint_8     type, 
+                               boolean    setup,
+                               uint_8     direction, 
+                               uint_8_ptr buffer,
+                               uint_32    length, 
+                               uint_8     error)
+{
+    int                     i, dev_no = _usb_device_get_dev_num(handle);
+    struct mv_usb_dev       *mv_dev = the_controllers[dev_no];
+    struct mv_usb_ep        *mv_ep;
+
+    if(setup == 0)
+    {
+        /* mv_usb_show(mv_dev, 0x3ff); */
+
+        /* Stop Hardware and cancel all pending requests */
+        for (i=0; i<2*_usb_device_get_max_endpoint(handle); i++)
+        {
+            mv_ep = &mv_dev->ep[i];
+
+            if(mv_ep->is_enabled == 0)
+                continue;
+
+            mv_usb_ep_cancel_all_req(mv_ep);
+        }
+        /* If connected call Function disconnect callback */
+        if( (mv_dev->gadget.speed != USB_SPEED_UNKNOWN) && 
+            (mv_dev->driver != NULL) &&
+            (mv_dev->driver->disconnect != NULL) )
+
+        {
+/*
+            USB_printf("USB gadget device disconnect or port reset: frindex=0x%x\n",
+                    MV_REG_READ(MV_USB_CORE_FRAME_INDEX_REG(dev_no)) );    
+*/
+            mv_dev->driver->disconnect (&mv_dev->gadget);
+        }
+        mv_dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+        /* Reinit all endpoints */
+        mv_usb_reinit(mv_dev);
+    }
+    else
+    {
+        _usb_device_start(mv_dev->mv_usb_handle);
+        /* Restart Control Endpoint #0 */
+        mv_usb_start_ep0(mv_dev);
+    }
+}
+
+
+void mv_usb_speed_service(void*      handle, 
+                           uint_8     type, 
+                           boolean    setup,
+                           uint_8     direction, 
+                           uint_8_ptr buffer,
+                           uint_32    length, 
+                           uint_8     error)
+{
+    int                     dev_no = _usb_device_get_dev_num(handle);
+    struct mv_usb_dev       *mv_dev = the_controllers[dev_no];
+
+    DBGMSG("Speed = %s\n", (length == ARC_USB_SPEED_HIGH) ? "High" : "Full");
+
+    if(length == ARC_USB_SPEED_HIGH)
+        mv_dev->gadget.speed = USB_SPEED_HIGH;
+    else
+        mv_dev->gadget.speed = USB_SPEED_FULL;
+
+    return;
+}
+
+void mv_usb_suspend_service(void*      handle, 
+                            uint_8     type, 
+                            boolean    setup,
+                            uint_8     direction, 
+                            uint_8_ptr buffer,
+                            uint_32    length, 
+                            uint_8     error)
+{
+    int                     dev_no = _usb_device_get_dev_num(handle);
+    struct mv_usb_dev       *mv_dev = the_controllers[dev_no];
+
+    DBGMSG("%s\n", __FUNCTION__);
+
+    if( (mv_dev->driver != NULL) &&
+        (mv_dev->driver->suspend != NULL) )
+        mv_dev->driver->suspend (&mv_dev->gadget);
+}
+
+void mv_usb_resume_service(void*      handle, 
+                            uint_8     type, 
+                            boolean    setup,
+                            uint_8     direction, 
+                            uint_8_ptr buffer,
+                            uint_32    length, 
+                            uint_8     error)
+{
+    int                     dev_no = _usb_device_get_dev_num(handle);
+    struct mv_usb_dev       *mv_dev = the_controllers[dev_no];
+
+    DBGMSG("%s\n", __FUNCTION__);
+
+    if( (mv_dev->driver != NULL) &&
+        (mv_dev->driver->resume != NULL) )
+        mv_dev->driver->resume (&mv_dev->gadget);
+}
+
+void mv_usb_tr_complete_service(void*      handle, 
+                                 uint_8     type, 
+                                 boolean    setup,
+                                 uint_8     direction, 
+                                 uint_8_ptr buffer,
+                                 uint_32    length, 
+                                 uint_8     error)
+{
+    int                     dev_no = _usb_device_get_dev_num(handle);
+    struct mv_usb_dev       *mv_dev = the_controllers[dev_no];
+    struct mv_usb_ep       *mv_ep;
+    struct usb_request      *usb_req;
+    int                     ep_num = (type*2) + direction;
+
+    DBGMSG("%s: ep_num=%d, setup=%s, direction=%s, pBuf=0x%x, length=%d, error=0x%x\n", 
+             __FUNCTION__, type, setup ? "YES" : "NO", 
+             (direction == ARC_USB_RECV) ? "RECV" : "SEND", 
+             (unsigned)buffer, (int)length, error);
+
+    mv_ep = &mv_dev->ep[ep_num];
+    if( !list_empty(&mv_ep->req_list) )
+    {
+        usb_req = list_entry (mv_ep->req_list.next, struct usb_request, list);
+        if(usb_req->buf != buffer)
+        {
+                mvOsPrintf("ep=%d-%s: req=%p, Unexpected buffer pointer: %p, len=%d, expected=%p\n", 
+                    ep_num, (direction == ARC_USB_RECV) ? "out" : "in",
+                    usb_req, buffer, length, usb_req->buf);
+                return;       
+        }
+        /* Dequeue request and call complete function */
+        list_del_init (&usb_req->list);
+
+        usb_req->actual += length;
+        usb_req->status = error;
+
+        usb_req->complete (&mv_ep->ep, usb_req);
+
+        if(error != 0)
+        {
+            _usb_device_stall_endpoint(mv_ep->usb_dev->mv_usb_handle, mv_ep->num,
+                mv_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV);
+        }
+    }
+    else
+        mvOsPrintf("ep=%p, epName=%s, epNum=%d - reqList EMPTY\n", 
+                mv_ep, mv_ep->ep.name, mv_ep->num);
+}
+
+void mv_usb_ep0_complete_service(void*      handle, 
+                                 uint_8     type, 
+                                 boolean    setup,
+                                 uint_8     direction, 
+                                 uint_8_ptr buffer,
+                                 uint_32    length, 
+                                 uint_8     error)
+{ /* Body */
+    int                     dev_no = _usb_device_get_dev_num(handle);
+    struct mv_usb_dev       *mv_dev = the_controllers[dev_no];
+    struct mv_usb_ep       *mv_ep;
+    struct usb_request*     usb_req;
+    int                     rc;
+    boolean                 is_delegate = FALSE;
+    SETUP_STRUCT            ctrl_req_org;
+    static SETUP_STRUCT     mv_ctrl_req;
+   
+    DBGMSG("%s: EP0(%d), setup=%s, direction=%s, pBuf=0x%x, length=%d, error=0x%x\n", 
+                __FUNCTION__, type, setup ? "YES" : "NO", 
+                (direction == ARC_USB_RECV) ? "RECV" : "SEND", 
+                (unsigned)buffer, (int)length, error);
+
+    mv_ep = &mv_dev->ep[type];
+
+    if (setup) 
+    {
+        _usb_device_read_setup_data(handle, type, (u8 *)&ctrl_req_org);
+        mv_ctrl_req.REQUESTTYPE = ctrl_req_org.REQUESTTYPE;
+        mv_ctrl_req.REQUEST = ctrl_req_org.REQUEST;
+        mv_ctrl_req.VALUE = le16_to_cpu (ctrl_req_org.VALUE);
+        mv_ctrl_req.INDEX = le16_to_cpu (ctrl_req_org.INDEX);
+        mv_ctrl_req.LENGTH = le16_to_cpu (ctrl_req_org.LENGTH);
+
+        while(_usb_device_get_transfer_status(handle, mv_ep->num, 
+                ARC_USB_SEND) != ARC_USB_STATUS_IDLE)
+        {
+            _usb_device_cancel_transfer(mv_dev->mv_usb_handle, mv_ep->num, 
+                           ARC_USB_SEND);
+        }
+        while(_usb_device_get_transfer_status(handle, mv_ep->num, 
+                ARC_USB_RECV) != ARC_USB_STATUS_IDLE)
+        {
+            _usb_device_cancel_transfer(mv_dev->mv_usb_handle, mv_ep->num, 
+                           ARC_USB_RECV);
+        }
+        /* make sure any leftover request state is cleared */
+        while (!list_empty (&mv_ep->req_list)) 
+        {
+            usb_req = list_entry (mv_ep->req_list.next, struct usb_request, list);
+
+            /* Dequeue request and call complete function */
+            list_del_init (&usb_req->list);
+
+            if (usb_req->status == -EINPROGRESS)
+                usb_req->status = -EPROTO;
+
+            usb_req->complete (&mv_ep->ep, usb_req);
+        }
+    }
+    /* Setup request direction */
+    mv_ep->is_in = (mv_ctrl_req.REQUESTTYPE & REQ_DIR_IN) != 0;     
+
+    if(setup)
+        DBGMSG("Setup: dir=%s, reqType=0x%x, req=0x%x, value=0x%02x, index=0x%02x, length=0x%02x\n", 
+                (direction == ARC_USB_SEND) ? "In" : "Out",
+                mv_ctrl_req.REQUESTTYPE, mv_ctrl_req.REQUEST, mv_ctrl_req.VALUE,
+                mv_ctrl_req.INDEX, mv_ctrl_req.LENGTH); 
+
+    /* Handle most lowlevel requests;
+     * everything else goes uplevel to the gadget code.
+     */
+    if( (mv_ctrl_req.REQUESTTYPE & REQ_TYPE_MASK) == REQ_TYPE_STANDARD)
+    {
+        switch (mv_ctrl_req.REQUEST) 
+        {
+            case REQ_GET_STATUS: 
+                mvUsbCh9GetStatus(handle, setup, &mv_ctrl_req);
+                break;
+
+            case REQ_CLEAR_FEATURE:
+                mvUsbCh9ClearFeature(handle, setup, &mv_ctrl_req);
+                break;
+
+            case REQ_SET_FEATURE:
+                mvUsbCh9SetFeature(handle, setup, &mv_ctrl_req);
+                break;
+
+            case REQ_SET_ADDRESS:
+                mvUsbCh9SetAddress(handle, setup, &mv_ctrl_req);
+                break;
+
+            default:
+                /* All others delegate call up-layer gadget code */
+                is_delegate = TRUE;
+        }
+    }
+    else
+        is_delegate = TRUE;
+
+    /* delegate call up-layer gadget code */
+    if(is_delegate)
+    {
+        if(setup)
+        {
+            rc = mv_dev->driver->setup (&mv_dev->gadget, (struct usb_ctrlrequest*)&ctrl_req_org);
+            if(rc < 0)
+            {
+                mvOsPrintf("Setup is failed: rc=%d, req=0x%02x, reqType=0x%x, value=0x%04x, index=0x%04x\n", 
+                    rc, ctrl_req_org.REQUEST, ctrl_req_org.REQUESTTYPE, 
+                    ctrl_req_org.VALUE, ctrl_req_org.INDEX);
+                _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+                return;
+            }
+            /* Acknowledge  */
+            if( mv_ep->is_in ) {
+                _usb_device_recv_data(handle, 0, NULL, 0);
+            } 
+            else if( mv_ctrl_req.LENGTH ) {
+                _usb_device_send_data(handle, 0, NULL, 0);
+            }
+        }
+    }
+
+    if(!setup)
+    {
+        if( !list_empty(&mv_ep->req_list) )
+        {
+            usb_req = list_entry (mv_ep->req_list.next, struct usb_request, list);
+
+            /* Dequeue request and call complete function */
+            list_del_init (&usb_req->list);
+
+            usb_req->actual = length;
+            usb_req->status = error;
+            usb_req->complete (&mv_ep->ep, usb_req);
+        }
+        DBGMSG("Setup complete: dir=%s, is_in=%d, length=%d\n", 
+                (direction == ARC_USB_SEND) ? "In" : "Out",
+                mv_ep->is_in, length);
+    }
+}
+
+#ifdef MV_USB_VOLTAGE_FIX
+
+/* usb_state - state of usb:connected(1)/disconnected(2) */
+static int usb_state = MV_USB_DISCONNECTED;
+
+/* usb_device-device structure for kobject functionality */
+static struct device mv_usb_device;
+
+/* mv_usb_work_struct - workqueue structure using for creating and run work tasks */
+static struct work_struct mv_usb_work_struct;
+
+/* mv_bustype for inizialization usb_device structure */
+static struct bus_type mv_usb_bustype = {
+		.name		= "mv_udc",
+};
+
+/*******************************************************************************
+* mv_usb_work_struct_routine
+* DESCRIPTION: 	notify userspace by ending an uevent
+* INPUTS:       *ignored - structure work_struct - N/A
+* OUTPUTS:      N/A
+* RETURNS:      N/A
+*******************************************************************************/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+static int mv_usb_work_struct_routine(struct work_struct *ignored)
+#else
+static void mv_usb_work_struct_routine(struct work_struct *ignored)
+#endif
+{
+	int retval=1;
+
+	/* Usb device connected */
+	if(usb_state == MV_USB_CONNECTED)
+	{
+		retval = kobject_uevent(&mv_usb_device.kobj, KOBJ_ADD);
+		mvOsPrintf("Usb device connected\n");
+	}
+	/* Usb device disconnected */
+	else
+	{
+		retval = kobject_uevent(&mv_usb_device.kobj, KOBJ_REMOVE);
+		mvOsPrintf("Usb device disconnected\n");
+	}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+	/* on error */
+	if(retval != 0)
+	{
+		mvOsPrintf("ERROR: %d, kobject_uevent() failed\n",retval);
+	}
+	return retval;
+#endif
+}
+
+/* initialize a work-struct with work task -mv_usb_work_struct_routine */
+static DECLARE_WORK(mv_usb_work_struct, mv_usb_work_struct_routine);
+
+static irqreturn_t mv_usb_vbus_irq (int irq, void *_dev)
+{
+    struct mv_usb_dev       *mv_dev = _dev;
+    int                     vbus_change, retval=0;
+
+    vbus_change = mvUsbBackVoltageUpdate(mv_dev->dev_no, (int)mv_dev->vbus_gpp_no);
+    if(vbus_change == 2)
+    {
+        if( (mv_dev->gadget.speed != USB_SPEED_UNKNOWN) &&
+            (mv_dev->driver != NULL)                    &&
+            (mv_dev->driver->disconnect != NULL) )
+            mv_dev->driver->disconnect (&mv_dev->gadget);
+    }
+    /*
+    printk("%s: vbus_change = %d, usb_state=%d\n", 
+            __FUNCTION__, vbus_change, usb_state);
+    */
+
+	/* 
+	   set state of usb device (1-connected;2-disconnected) and
+	   schedule mv_usb_work_struct_routine in workqueue 
+	   if mv_usb_work_struct entry is empty 
+	*/
+	usb_state=(vbus_change==2) ? MV_USB_DISCONNECTED : MV_USB_CONNECTED;

+	if(list_empty(&mv_usb_work_struct.entry))
+	{
+		retval = schedule_work(&mv_usb_work_struct);
+ 		if(retval == 0)
+		{
+			mvOsPrintf("ERROR: %d, schedule_work() failed\n",retval);
+		}
+	}

+    return IRQ_HANDLED;
+}
+#endif /* MV_USB_VOLTAGE_FIX */
+
+static irqreturn_t mv_usb_dev_irq (int irq, void *_dev)
+{
+    struct mv_usb_dev       *mv_dev = _dev;
+
+    spin_lock (&mv_dev->lock);
+
+    /* handle ARC USB Device interrupts */
+    _usb_dci_vusb20_isr(mv_dev->mv_usb_handle);
+
+    spin_unlock (&mv_dev->lock);
+
+    return IRQ_HANDLED;
+}
+
+#ifdef MV_USB_VOLTAGE_FIX
+
+/*******************************************************************************
+* mv_usb_initialize_kobject
+* DESCRIPTION: 	init device,set bus type, create and add kobject
+* INPUTS:       *dev - pointer for device structure
+* OUTPUTS:      N/A
+* RETURNS:      status USB_OK on success
+*******************************************************************************/
+static int mv_usb_initialize_kobject (void)
+{
+	int retval = 1;
+
+	/* init device */
+	device_initialize(&mv_usb_device);
+
+	/* set bus_type for device */
+	mv_usb_device.bus = &mv_usb_bustype;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+	/* init kobject */
+	retval = kobject_set_name(&mv_usb_device.kobj, "mv_udc_d");
+	if(retval != USB_OK)
+	{
+		mvOsPrintf("ERROR: %d, kobject_set_name() failed\n",retval);
+		return retval;
+	}
+	retval = kobject_add(&mv_usb_device.kobj);
+#else
+	retval = kobject_add(&mv_usb_device.kobj, NULL, "mv_udc_d");
+
+#endif
+
+	/* add kobject */
+	if(retval != USB_OK)
+	{
+		mvOsPrintf("ERROR: %d, kobject_add() failed\n",retval);
+		return retval;
+	}
+	return USB_OK;
+}
+#endif /* MV_USB_VOLTAGE_FIX */
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+{
+    int                 retval, dev_no;
+    struct mv_usb_dev   *mv_dev = NULL;
+    uint_8              error;
+
+/*    mvOsPrintf("ENTER usb_gadget_register_driver: \n");*/
+
+    /* Find USB Gadget device controller */
+    for(dev_no=0; dev_no<mvCtrlUsbMaxGet(); dev_no++)
+    {
+        mv_dev = the_controllers[dev_no];
+        if(mv_dev != NULL)
+            break;
+    }
+
+    if ( (driver == NULL)
+            || (driver->speed != USB_SPEED_HIGH)
+            || !driver->bind
+            || !driver->unbind
+            || !driver->setup)
+    {
+        mvOsPrintf("ERROR: speed=%d, bind=%p,  unbind=%p, setup=%p\n",
+                    driver->speed, driver->bind, driver->unbind, driver->setup);
+        return -EINVAL;
+    }
+
+    if (!mv_dev)
+    {
+        mvOsPrintf("ERROR: max_dev=%d, mv_dev=%p\n", mvCtrlUsbMaxGet(), mv_dev);
+        return -ENODEV;
+    }
+    if (mv_dev->driver)
+    {
+        mvOsPrintf("ERROR: driver=%p is busy\n", mv_dev->driver);
+        return -EBUSY;
+    }
+/*
+    mvOsPrintf("usb_gadget_register_driver: dev=%d, mv_dev=%p, pDriver=%p\n", 
+                dev_no, mv_dev, driver);
+*/
+    /* first hook up the driver ... */
+    mv_dev->driver = driver;
+    mv_dev->gadget.dev.driver = &driver->driver;
+    retval = driver->bind (&mv_dev->gadget);
+    if (retval) {
+        mvOsPrintf("bind to driver %s --> %d\n",
+                driver->driver.name, retval);
+        mv_dev->driver = 0;
+        mv_dev->gadget.dev.driver = 0;
+        return retval;
+    }
+
+    /* request_irq */
+    if (request_irq (IRQ_USB_CTRL(dev_no), mv_usb_dev_irq, IRQF_DISABLED, 
+                     driver_name, mv_dev) != 0) 
+    {
+        mvOsPrintf("%s register: request interrupt %d failed\n", 
+                driver->driver.name, IRQ_USB_CTRL(dev_no));
+        return -EBUSY;
+    }
+
+    _usb_device_start(mv_dev->mv_usb_handle);
+    error = mv_usb_start_ep0(mv_dev);
+
+    mvOsPrintf("registered Marvell USB-%d gadget driver %s\n", dev_no, driver->driver.name);
+    return error;
+}
+EXPORT_SYMBOL (usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+{
+    int                 i, dev_no;
+    struct mv_usb_ep    *mv_ep;
+    struct mv_usb_dev   *mv_dev = NULL;
+    unsigned long       flags = 0;
+
+    /* Find USB Gadget device controller */
+    for(dev_no=0; dev_no<mvCtrlUsbMaxGet(); dev_no++)
+    {
+        if( (the_controllers[dev_no] != NULL) && (the_controllers[dev_no]->driver == driver) )
+        {
+            mv_dev = the_controllers[dev_no];
+            break;
+        }
+    }
+    
+    if (!mv_dev)
+    {
+        mvOsPrintf("usb_gadget_unregister_driver FAILED: no such device\n");
+        return -ENODEV;
+    }
+    if (!driver || (driver != mv_dev->driver) )
+    {
+        mvOsPrintf("usb_gadget_unregister_driver FAILED: no such driver, dev_no=%d\n", dev_no);
+        return -EINVAL;
+    }
+
+    /* Stop and Disable ARC USB device */
+    MV_SPIN_LOCK_IRQSAVE(&mv_dev->lock, flags);
+
+    /* Stop Endpoints */
+    for (i=0; i<2*_usb_device_get_max_endpoint(mv_dev->mv_usb_handle); i++)
+    {
+        mv_ep = &mv_dev->ep[i];
+        if(mv_ep->is_enabled == 0)
+            continue;
+
+        mv_ep->is_enabled = 0;
+        mv_usb_ep_cancel_all_req(mv_ep);
+
+        _usb_device_deinit_endpoint(mv_dev->mv_usb_handle, mv_ep->num, 
+                                mv_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV);
+    }
+    _usb_device_stop(mv_dev->mv_usb_handle);
+
+    MV_SPIN_UNLOCK_IRQRESTORE(&mv_dev->lock, flags);
+
+    if (mv_dev->gadget.speed != USB_SPEED_UNKNOWN)
+        mv_dev->driver->disconnect (&mv_dev->gadget);
+
+    driver->unbind (&mv_dev->gadget);
+
+    /* free_irq */
+    free_irq (IRQ_USB_CTRL(dev_no), mv_dev);
+
+    mv_dev->gadget.dev.driver = 0;
+    mv_dev->driver = 0;
+
+    mv_dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+    /* Reinit all endpoints */
+    mv_usb_reinit(mv_dev);
+
+    /*device_remove_file(dev->dev, &dev_attr_function); ?????*/
+    mvOsPrintf("unregistered Marvell USB %d gadget driver %s\n", dev_no, driver->driver.name);
+
+    return 0;
+}
+EXPORT_SYMBOL (usb_gadget_unregister_driver);
+
+void    mv_usb_show(struct mv_usb_dev* mv_dev, unsigned int mode)
+{
+    int     i;
+
+    mvOsPrintf("\n-------------------------------------------------------------\n");
+
+    if( MV_BIT_CHECK(mode, 0) )
+        _usb_regs(mv_dev->mv_usb_handle);
+
+    if( MV_BIT_CHECK(mode, 1) )
+        _usb_status(mv_dev->mv_usb_handle);
+
+    if( MV_BIT_CHECK(mode, 2) )
+        _usb_stats(mv_dev->mv_usb_handle);
+
+    if( MV_BIT_CHECK(mode, 3) )
+        _usb_debug_print_trace_log();
+
+    for(i=0; i<_usb_device_get_max_endpoint(mv_dev->mv_usb_handle); i++)
+    {
+        if( MV_BIT_CHECK(mode, (8+i)) )
+        {
+            _usb_ep_status(mv_dev->mv_usb_handle, i, ARC_USB_RECV);
+            _usb_ep_status(mv_dev->mv_usb_handle, i, ARC_USB_SEND);
+        }
+    }
+    mvOsPrintf("-------------------------------------------------------------\n\n");
+}
+EXPORT_SYMBOL (mv_usb_show);
+
+static int  mv_usb_ep_enable(struct usb_ep *_ep, 
+                              const struct usb_endpoint_descriptor *desc)
+{
+    struct mv_usb_dev* usb_dev;
+    struct mv_usb_ep*  usb_ep;
+    uint_16             maxSize;
+    uint_8              epType; 
+    unsigned long       flags = 0;
+
+    usb_ep = container_of (_ep, struct mv_usb_ep, ep);
+    if( (_ep == NULL) || (desc == NULL) )
+        return -EINVAL;
+    
+    usb_dev = usb_ep->usb_dev;
+
+    if(usb_ep->is_enabled)
+    {
+        mvOsPrintf("mv_usb: %d%s Endpoint (%s) is already in use\n", 
+                    usb_ep->num, usb_ep->is_in ? "In" : "Out", usb_ep->ep.name);
+        return -EINVAL;
+    }
+/*
+    mvOsPrintf("USB Enable %s: type=%d, maxPktSize=%d\n",
+                _ep->name, desc->bmAttributes & 0x3, desc->wMaxPacketSize);
+*/
+    if(usb_ep->num == 0)
+    {
+        mvOsPrintf("mv_usb: ep0 is reserved\n");
+        return -EINVAL;
+    }
+
+    if(desc->bDescriptorType != USB_DT_ENDPOINT)
+    {
+        mvOsPrintf("mv_usb: wrong descriptor type %d\n", desc->bDescriptorType);
+        return -EINVAL;
+    }
+
+    MV_SPIN_LOCK_IRQSAVE(&usb_dev->lock, flags);
+
+    usb_dev = usb_ep->usb_dev;
+    if( (usb_dev->driver == NULL) || 
+        (usb_dev->gadget.speed == USB_SPEED_UNKNOWN) )
+    {
+        MV_SPIN_UNLOCK_IRQRESTORE(&usb_dev->lock, flags);
+        return -ESHUTDOWN;
+    }
+    /* Max packet size */
+    maxSize = le16_to_cpu (desc->wMaxPacketSize);
+
+    /* Endpoint type */
+    if( (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL)
+        epType = ARC_USB_CONTROL_ENDPOINT;
+    else if( (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC) 
+        epType = ARC_USB_ISOCHRONOUS_ENDPOINT;
+    else if( (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) 
+        epType = ARC_USB_BULK_ENDPOINT;
+    else
+        epType = ARC_USB_INTERRUPT_ENDPOINT;
+
+    _ep->maxpacket = maxSize & 0x7ff;
+    usb_ep->is_enabled = 1;
+
+    _usb_device_init_endpoint(usb_dev->mv_usb_handle, usb_ep->num, maxSize, 
+            usb_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV, epType,
+            (epType == ARC_USB_BULK_ENDPOINT) ? ARC_USB_DEVICE_DONT_ZERO_TERMINATE : 0);
+
+    MV_SPIN_UNLOCK_IRQRESTORE(&usb_dev->lock, flags);
+    return 0;
+}
+
+static int  mv_usb_ep_disable (struct usb_ep *_ep)
+{
+    struct mv_usb_dev*  mv_dev;
+    struct mv_usb_ep*   mv_ep;
+    unsigned long       flags = 0;
+    uint_8              direction;
+
+    mv_ep = container_of (_ep, struct mv_usb_ep, ep);
+    if( (_ep == NULL) || (mv_ep->is_enabled == 0) || (mv_ep->num == 0))
+        return -EINVAL;
+
+    mv_dev = mv_ep->usb_dev;
+/*
+    mvOsPrintf("mv_usb_ep_disable: mv_dev=%p, ep=0x%x (%d-%s), name=%s\n", 
+                mv_dev, (unsigned)_ep, mv_ep->num, mv_ep->is_in ? "in" : "out", 
+                _ep->name);
+*/    
+    MV_SPIN_LOCK_IRQSAVE(&mv_dev->lock, flags);
+
+    direction = mv_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV;
+
+    mv_ep->is_enabled = 0;
+
+    /* Cancell all requests */
+    mv_usb_ep_cancel_all_req(mv_ep);
+
+    /* Disable endpoint */
+    _usb_device_deinit_endpoint(mv_dev->mv_usb_handle, mv_ep->num, direction);
+
+    MV_SPIN_UNLOCK_IRQRESTORE(&mv_dev->lock, flags);
+    return 0;
+}
+
+
+static struct usb_request* mv_usb_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+    struct usb_request* req;
+
+    if (!_ep)
+        return NULL;
+
+    req = kmalloc (sizeof *req, gfp_flags);
+    if (!req)
+        return NULL;
+
+    memset (req, 0, sizeof *req);
+    INIT_LIST_HEAD (&req->list);
+
+    return req;
+}
+
+static void     mv_usb_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+
+    if (!_ep || !_req)
+    {
+        mvOsPrintf("ep_free_request Error: _ep=%p, _req=%p\n", _ep, _req);
+        return;
+    }
+    kfree (_req);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+static void *mv_usb_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
+		dma_addr_t *dma, gfp_t gfp_flags)
+{
+	struct mv_usb_ep *ep;
+
+	if (!_ep)
+		return NULL;
+
+	ep = container_of(_ep, struct mv_usb_ep, ep);
+
+	return dma_alloc_coherent(ep->usb_dev->gadget.dev.parent,
+			bytes, dma, gfp_flags);
+}
+
+/*------------------------------------------------------------------
+ * frees an i/o buffer
+*---------------------------------------------------------------------*/
+static void mv_usb_ep_free_buffer(struct usb_ep *_ep, void *buf,
+		dma_addr_t dma, unsigned bytes)
+{
+	struct mv_usb_ep *ep;
+
+	if (!_ep)
+		return;
+
+	ep = container_of(_ep, struct mv_usb_ep, ep);
+
+	dma_free_coherent(ep->usb_dev->gadget.dev.parent, bytes, buf, dma);
+}
+#endif
+
+static int      mv_usb_ep_queue (struct usb_ep *_ep, struct usb_request *_req, 
+                                 gfp_t gfp_flags)
+{
+    struct mv_usb_dev* usb_dev;
+    struct mv_usb_ep*  usb_ep;
+    unsigned long       flags = 0;
+    uint_8              error;
+
+    usb_ep = container_of (_ep, struct mv_usb_ep, ep);
+    /* check parameters */
+    if( (_ep == NULL) || (_req == NULL) )
+    {
+        mvOsPrintf("ep_queue Failed: _ep=%p, _req=%p\n", _ep, _req);
+        return -EINVAL;
+    }
+    usb_dev = usb_ep->usb_dev;
+
+    if ( (usb_dev->driver == NULL) || (usb_dev->gadget.speed == USB_SPEED_UNKNOWN) )
+        return -ESHUTDOWN;
+
+    if(usb_ep->is_enabled == 0)
+    {
+        mvOsPrintf("ep_queue Failed - %s is disabled: usb_ep=%p\n", _ep->name, usb_ep);
+        return -EINVAL;
+    }
+
+    DBGMSG("%s: num=%d-%s, name=%s, _req=%p, buf=%p, length=%d\n", 
+                __FUNCTION__, usb_ep->num, usb_ep->is_in ? "in" : "out", 
+                _ep->name, _req, _req->buf, _req->length);
+
+    MV_SPIN_LOCK_IRQSAVE(&usb_dev->lock, flags);
+                
+    _req->status = -EINPROGRESS;
+    _req->actual = 0;
+
+    /* Add request to list */
+    if( ((usb_ep->num == 0) && (_req->length == 0)) || (usb_ep->is_in) )
+    {
+        int     send_size, size;
+        uint_8  *send_ptr, *buf_ptr;
+
+        send_ptr = buf_ptr = _req->buf;
+        send_size = size = _req->length;
+        list_add_tail(&_req->list, &usb_ep->req_list);
+
+        error = _usb_device_send_data(usb_dev->mv_usb_handle, usb_ep->num, send_ptr, send_size);
+        if(error != USB_OK)
+        {
+            mvOsPrintf("ep_queue: Can't SEND data (err=%d): ep_num=%d, pBuf=0x%x, send_size=%d\n",
+                    error, usb_ep->num, (unsigned)_req->buf, _req->length);
+            list_del_init (&_req->list);
+        }
+
+        size -= send_size;
+        buf_ptr += send_size;
+    }
+    else
+    {
+        error = _usb_device_recv_data(usb_dev->mv_usb_handle, usb_ep->num, _req->buf, _req->length);
+        if(error != USB_OK)
+        {
+            mvOsPrintf("mv_usb_ep_queue: Can't RCV data (err=%d): ep_num=%d, pBuf=0x%x, size=%d\n",
+                        error, usb_ep->num, (unsigned)_req->buf, _req->length);
+        }
+        else
+            list_add_tail(&_req->list, &usb_ep->req_list);
+    }
+
+    MV_SPIN_UNLOCK_IRQRESTORE(&usb_dev->lock, flags);
+
+    return (int)error;
+}
+
+/* Cancell request */
+static int      mv_usb_ep_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+{
+    struct mv_usb_dev* usb_dev;
+    struct usb_request *usb_req;
+    struct mv_usb_ep*  usb_ep;
+    unsigned long       flags = 0;
+    int                 status = 0;
+
+    usb_ep = container_of (_ep, struct mv_usb_ep, ep);
+    /* check parameters */
+    if( (_ep == NULL) || (_req == NULL) || (usb_ep->is_enabled == 0) )
+        return -EINVAL;
+
+    usb_dev = usb_ep->usb_dev;
+        
+    if ( (usb_dev->driver == NULL) || (usb_dev->gadget.speed == USB_SPEED_UNKNOWN) )
+    {
+        mvOsPrintf("mv_usb_ep_dequeue: ep=0x%x, num=%d-%s, name=%s, driver=0x%x, speed=%d\n", 
+                (unsigned)_ep, usb_ep->num, usb_ep->is_in ? "in" : "out", 
+                _ep->name, (unsigned)usb_dev->driver, usb_dev->gadget.speed);
+
+        return -ESHUTDOWN;
+    }
+
+    MV_SPIN_LOCK_IRQSAVE(&usb_dev->lock, flags);
+
+    /* ????? Currently supported only dequeue request from the HEAD of List */
+    if( !list_empty(&usb_ep->req_list) )
+    {
+        usb_req = list_entry (usb_ep->req_list.next, struct usb_request, list);
+
+        if(usb_req == _req)
+        {
+            /* Cancel transfer */
+            _usb_device_cancel_transfer(usb_dev->mv_usb_handle, usb_ep->num, 
+                            usb_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV);
+            /* Dequeue request and call complete function */
+            list_del_init (&_req->list);
+
+            if (_req->status == -EINPROGRESS)
+                _req->status = -ECONNRESET;
+
+            /* ????? what about enable interrupts */
+            _req->complete (&usb_ep->ep, _req);
+        }
+        else
+        {
+            mvOsPrintf("Cancel request failed: ep=%p, usb_req=%p, req=%p\n", 
+                        _ep, usb_req, _req);
+            status = EINVAL;
+        }
+    }
+    /*
+    else
+        mvOsPrintf("%s: ep=%p, epName=%s, epNum=%d - reqList EMPTY\n", 
+                    __FUNCTION__, usb_ep, usb_ep->ep.name, usb_ep->num);
+    */
+    MV_SPIN_UNLOCK_IRQRESTORE(&usb_dev->lock, flags);
+
+    return status;
+}
+
+static int      mv_usb_ep_set_halt (struct usb_ep *_ep, int value)
+{
+    struct mv_usb_ep*   mv_ep;
+    unsigned long       flags = 0;
+    int                 retval = 0;
+
+    mv_ep = container_of (_ep, struct mv_usb_ep, ep);
+    if (_ep == NULL)
+        return -EINVAL;
+    if( (mv_ep->usb_dev->driver == NULL) || 
+        (mv_ep->usb_dev->gadget.speed == USB_SPEED_UNKNOWN) )
+        return -ESHUTDOWN;
+
+/*
+    mvOsPrintf("%s - %s \n", 
+                _ep->name, value ? "Stalled" : "Unstalled");
+*/
+    MV_SPIN_LOCK_IRQSAVE(&mv_ep->usb_dev->lock, flags);
+    if (!list_empty (&mv_ep->req_list))
+        retval = -EAGAIN;
+    else 
+    {
+        /* set/clear, then synch memory views with the device */
+        if (value) 
+        {
+            if (mv_ep->num == 0)
+                mv_ep->usb_dev->protocol_stall = 1;
+            else
+                _usb_device_stall_endpoint(mv_ep->usb_dev->mv_usb_handle, mv_ep->num,
+                mv_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV);
+        } 
+        else
+        {
+            _usb_device_unstall_endpoint(mv_ep->usb_dev->mv_usb_handle, mv_ep->num, 
+                                    mv_ep->is_in ? ARC_USB_SEND : ARC_USB_RECV);
+        }
+    }
+    MV_SPIN_UNLOCK_IRQRESTORE(&mv_ep->usb_dev->lock, flags);
+
+    return retval;
+}
+
+
+static void     mv_usb_ep_fifo_flush (struct usb_ep *_ep)
+{
+    DBGMSG("%s: ep=%p, ep_name=%s - NOT supported\n", __FUNCTION__, _ep, _ep->name);
+}
+
+
+static struct usb_ep_ops mv_usb_ep_ops = 
+{
+    .enable         = mv_usb_ep_enable,
+    .disable        = mv_usb_ep_disable,
+
+    .alloc_request  = mv_usb_ep_alloc_request,
+    .free_request   = mv_usb_ep_free_request,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+    .alloc_buffer  = mv_usb_ep_alloc_buffer,
+    .free_buffer   = mv_usb_ep_free_buffer,
+#endif
+    .queue          = mv_usb_ep_queue,
+    .dequeue        = mv_usb_ep_dequeue,
+
+    .set_halt       = mv_usb_ep_set_halt,
+    .fifo_flush     = mv_usb_ep_fifo_flush,
+    /*.fifo_status    =  Not supported */
+};
+
+static int mv_usb_get_frame (struct usb_gadget *_gadget)
+{
+    DBGMSG("Call mv_usb_get_frame - NOT supported\n");
+    return 0;
+}
+
+static int mv_usb_wakeup(struct usb_gadget *_gadget)
+{
+    DBGMSG("Call mv_usb_wakeup - NOT supported\n");
+    return 0;
+}
+
+static int mv_usb_set_selfpowered (struct usb_gadget *_gadget, int value)
+{
+    DBGMSG("Call mv_usb_set_selfpowered - NOT supported\n");
+    return 0;
+}
+
+static const struct usb_gadget_ops mv_usb_ops = 
+{
+    .get_frame       = mv_usb_get_frame,
+    .wakeup          = mv_usb_wakeup,
+    .set_selfpowered = mv_usb_set_selfpowered,
+    .ioctl           = NULL,
+};
+
+static void mv_usb_gadget_release (struct device *_dev)
+{
+    struct mv_usb_dev   *usb_dev = dev_get_drvdata (_dev);
+
+    /*mvOsPrintf("Call mv_usb_gadget_release \n");*/
+    mvOsFree(usb_dev);
+}
+
+
+static int __init mv_usb_gadget_probe(struct platform_device *pDev) 
+{
+    struct device	        *_dev = &pDev->dev; 
+    struct mv_usb_dev       *mv_dev;
+    int                     dev_no, retval, i;
+    uint_8                  error;
+
+    /*mvOsPrintf("Call mv_usb_gadget_probe: _dev=%p, pDev=%p\n", _dev, pDev);*/
+
+    for(dev_no=0; dev_no<mvCtrlUsbMaxGet(); dev_no++)
+    {
+        if( (pDev->resource[1].flags == IORESOURCE_IRQ) &&
+            (pDev->resource[1].start == IRQ_USB_CTRL(dev_no)) )
+        {
+            break;
+        }
+    }
+    if(dev_no >= mvCtrlUsbMaxGet())
+    {
+        mvOsPrintf("mv_udc_probe: device is not found\n");
+        return -EINVAL;
+    }
+    mvOsPrintf("USB-%d Gadget driver probed\n", dev_no);
+
+    if (the_controllers[dev_no]) 
+    {
+        mvOsPrintf("mv_dev_load: USB-%d controller is BUSY\n", dev_no);
+        return -EBUSY;
+    }
+
+    /* alloc, and start init */
+    mv_dev = mvOsMalloc (sizeof(struct mv_usb_dev));
+    if (mv_dev == NULL)
+    {
+        mvOsPrintf("mv_dev_load: malloc failed\n");
+        return -ENOMEM;
+    }
+
+    memset (mv_dev, 0, sizeof *mv_dev);
+    spin_lock_init (&mv_dev->lock);
+    mv_dev->dev = _dev; 
+    mv_dev->gadget.ops = &mv_usb_ops;
+    mv_dev->gadget.is_dualspeed = 1;
+
+    /* the "gadget" abstracts/virtualizes the controller */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+    strcpy (mv_dev->gadget.dev.bus_id, "gadget");
+#else
+    dev_set_name(&mv_dev->gadget.dev, "gadget");
+#endif
+    mv_dev->gadget.dev.parent = _dev;
+    mv_dev->gadget.dev.dma_mask = _dev->dma_mask; /* ?????? */
+    mv_dev->gadget.dev.release = mv_usb_gadget_release;
+    mv_dev->gadget.name = driver_name;
+    mv_dev->mv_usb_handle = NULL;
+    mv_dev->dev_no = dev_no;
+
+    dev_set_drvdata(_dev, mv_dev);
+    the_controllers[dev_no] = mv_dev;
+
+#ifdef MV_USB_VOLTAGE_FIX
+
+    mv_dev->vbus_gpp_no = mvUsbGppInit(dev_no);
+    mvOsPrintf("USB gadget device #%d: vbus_gpp_no = %d\n", 
+                    dev_no, mv_dev->vbus_gpp_no);
+
+    if(mv_dev->vbus_gpp_no != (MV_U8)N_A)
+    {
+        if (request_irq (IRQ_GPP_START + mv_dev->vbus_gpp_no, mv_usb_vbus_irq, IRQF_DISABLED, 
+                     driver_name, mv_dev) != 0) 
+        {
+            mvOsPrintf("%s probe: request interrupt %d failed\n", 
+                    driver_name, IRQ_GPP_START + mv_dev->vbus_gpp_no);
+            return -EBUSY;
+        }
+    }
+
+#endif /* MV_USB_VOLTAGE_FIX */
+
+    /* Reset ARC USB device ????? */
+    /* Reinit ARC USB device ????? */
+
+    /* First of all. */
+    _usb_device_set_bsp_funcs(&usbImportFuncs);
+
+#if defined(USB_UNDERRUN_WA)
+
+    if(wa_sram_parts > USB_SRAM_MAX_PARTS)
+    {
+        mvOsPrintf("Wrong <wa_sram_parts> param (%d): Valid range [1 .. %d]\n",
+                wa_sram_parts, USB_SRAM_MAX_PARTS);
+        return -EINVAL;
+    }
+
+    global_wa_funcs = &usbWaFuncs;
+    global_wa_threshold = wa_threshold;
+    global_wa_sram_parts = wa_sram_parts;
+
+    sramBase = mv_sram_usage_get(&sramSize);
+    if(sramBase == NULL)
+    {
+        mvOsPrintf("USB Underrun WA: No free SRAM space\n");
+        return -ENOMEM;
+    }
+    memset(sramBase, 0, sramSize);
+    
+    idma = mv_usb_find_idma_engine(idma);
+    if(idma != -1)
+    {
+        MV_REG_WRITE(IDMA_BYTE_COUNT_REG(idma), 0);
+        MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(idma), 0);
+        MV_REG_WRITE(IDMA_CTRL_HIGH_REG(idma), ICCHR_ENDIAN_LITTLE 
+#ifdef MV_CPU_LE
+					 | ICCHR_DESC_BYTE_SWAP_EN
+#endif
+					 );
+        MV_REG_WRITE(IDMA_CTRL_LOW_REG(idma), USB_IDMA_CTRL_LOW_VALUE);
+    }
+    mvOsPrintf("USB underrun WA: idma=%d, streaming=%d, threshold=%d, SRAM: base=%p, size=%d, parts=%d\n", 
+                idma, streaming, global_wa_threshold, sramBase, sramSize, global_wa_sram_parts);
+#endif /* USB_UNDERRUN_WA */
+
+    /*_usb_debug_set_flags(MV_USB_GADGET_DEBUG_FLAGS);*/
+
+    /* Enable ARC USB device */
+    retval = (int)_usb_device_init(dev_no, &mv_dev->mv_usb_handle);
+    if (retval != USB_OK) 
+    {
+        mvOsPrintf("\nUSB Initialization failed. Error: %x", retval);
+        return -EINVAL;
+    } /* Endif */
+
+    if( (epin_first < 1) || (epin_first >= _usb_device_get_max_endpoint(mv_dev->mv_usb_handle)) )
+    {
+        mvOsPrintf("\nUSB_%d: epin_first=%d is out of range 1..%d. Use default epin_first=1\n", 
+                    dev_no, epin_first, _usb_device_get_max_endpoint(mv_dev->mv_usb_handle) );
+        epin_first = 1;
+    }
+
+    if( (epout_first < 1) || (epout_first >= _usb_device_get_max_endpoint(mv_dev->mv_usb_handle)) )
+    {
+        mvOsPrintf("\nUSB_%d: epout_first=%d is out of range 1..%d. Use default epout_first=1\n", 
+                    dev_no, epout_first, _usb_device_get_max_endpoint(mv_dev->mv_usb_handle) );
+        epout_first = 1;
+    }
+
+    /* Self Power, Remote wakeup disable */
+    _usb_device_set_status(mv_dev->mv_usb_handle, ARC_USB_STATUS_DEVICE, (1 << DEVICE_SELF_POWERED));
+
+    /* Register all ARC Services */  
+    error = _usb_device_register_service(mv_dev->mv_usb_handle, 
+                                ARC_USB_SERVICE_BUS_RESET, mv_usb_bus_reset_service);
+    if (error != USB_OK) 
+    {
+        mvOsPrintf("\nUSB BUS_RESET Service Registration failed. Error: 0x%x", error);
+        return -EINVAL;
+    } /* Endif */
+   
+    error = _usb_device_register_service(mv_dev->mv_usb_handle, 
+                        ARC_USB_SERVICE_SPEED_DETECTION, mv_usb_speed_service);
+    if (error != USB_OK) 
+    {
+        mvOsPrintf("\nUSB SPEED_DETECTION Service Registration failed. Error: 0x%x", 
+                        error);
+        return -EINVAL;
+    } /* Endif */
+         
+    error = _usb_device_register_service(mv_dev->mv_usb_handle, 
+                                ARC_USB_SERVICE_SUSPEND, mv_usb_suspend_service);
+    if (error != USB_OK) 
+    {
+        mvOsPrintf("\nUSB SUSPEND Service Registration failed. Error: 0x%x", error);
+        return -EINVAL;
+    } /* Endif */
+
+    error = _usb_device_register_service(mv_dev->mv_usb_handle, 
+                                ARC_USB_SERVICE_SLEEP, mv_usb_suspend_service);
+    if (error != USB_OK) 
+    {
+        mvOsPrintf("\nUSB SUSPEND Service Registration failed. Error: 0x%x", error);
+        return -EINVAL;
+    } /* Endif */    
+
+    error = _usb_device_register_service(mv_dev->mv_usb_handle, 
+                                ARC_USB_SERVICE_RESUME, mv_usb_resume_service);
+    if (error != USB_OK) 
+    {
+        mvOsPrintf("\nUSB RESUME Service Registration failed. Error: 0x%x", error);
+        return -EINVAL;
+    } /* Endif */
+
+    error = _usb_device_register_service(mv_dev->mv_usb_handle, 0, 
+                                            mv_usb_ep0_complete_service);   
+    if (error != USB_OK) 
+    {
+        mvOsPrintf("\nUSB ep0 TR_COMPLETE Service Registration failed. Error: 0x%x", error);
+        return error;
+    } /* Endif */
+
+    for (i=1; i<_usb_device_get_max_endpoint(mv_dev->mv_usb_handle); i++)
+    {
+        error = _usb_device_register_service(mv_dev->mv_usb_handle, i, 
+                                                    mv_usb_tr_complete_service);   
+        if (error != USB_OK) 
+        {
+            mvOsPrintf("\nUSB ep0 TR_COMPLETE Service Registration failed. Error: 0x%x", error);
+            return error;
+        } /* Endif */
+    }
+    mv_dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+    if( mv_usb_reinit (mv_dev) != USB_OK)
+        return -EINVAL;
+
+    retval = device_register (&mv_dev->gadget.dev);
+
+#ifdef MV_USB_VOLTAGE_FIX
+
+	if(retval!= USB_OK)
+	{
+		mvOsPrintf("ERROR: %d, device_register() failed\n", retval);
+		return retval;
+	}
+
+	/* create and init kobject */

+ 	retval = mv_usb_initialize_kobject();
+	if(retval != USB_OK)
+	{
+		mvOsPrintf("ERROR: %d, kobject_init() failed\n", retval);
+		return retval;
+	}
+
+#endif /* MV_USB_VOLTAGE_FIX */
+
+    return retval; 
+}
+
+static int __exit mv_usb_gadget_remove(struct platform_device *pDev)
+{
+    int                 i;
+    struct device	    *_dev = &pDev->dev; 
+    struct mv_usb_dev   *mv_dev = dev_get_drvdata(_dev); 
+
+    mvOsPrintf("mv_usb_gadget_remove: mv_dev=%p, driver=%p\n", 
+                mv_dev, mv_dev->driver);
+    /* start with the driver above us */
+    if (mv_dev->driver) 
+    {
+        /* should have been done already by driver model core */
+        mvOsPrintf("pci remove, driver '%s' is still registered\n",
+                    mv_dev->driver->driver.name);

+
+        usb_gadget_unregister_driver (mv_dev->driver);
+    }
+
+    spin_lock (&mv_dev->lock);
+
+    for (i=0; i<_usb_device_get_max_endpoint(mv_dev->mv_usb_handle); i++)
+        _usb_device_unregister_service(mv_dev->mv_usb_handle, i);   
+
+    /* Deregister all other services */
+    _usb_device_unregister_service(mv_dev->mv_usb_handle, ARC_USB_SERVICE_BUS_RESET);   
+    _usb_device_unregister_service(mv_dev->mv_usb_handle, ARC_USB_SERVICE_SPEED_DETECTION);
+
+    _usb_device_unregister_service(mv_dev->mv_usb_handle, ARC_USB_SERVICE_SUSPEND);
+
+    _usb_device_unregister_service(mv_dev->mv_usb_handle, ARC_USB_SERVICE_RESUME);
+
+    _usb_device_shutdown(mv_dev->mv_usb_handle);
+
+    spin_unlock (&mv_dev->lock);
+
+#ifdef MV_USB_VOLTAGE_FIX
+
+    if(mv_dev->vbus_gpp_no != (MV_U8)N_A)
+    {
+        free_irq (IRQ_GPP_START + mv_dev->vbus_gpp_no, mv_dev); 
+    }
+    /* delete kobject */

+	kobject_del(&mv_usb_device.kobj);

+
+#endif /* MV_USB_VOLTAGE_FIX */
+
+    the_controllers[mv_dev->dev_no] = 0;
+    device_unregister (&mv_dev->gadget.dev);
+
+    kfree(mv_dev);
+
+    dev_set_drvdata(_dev, 0);
+    return 0;
+}
+ 
+
+/* global variables from 'regdump' */
+static struct proc_dir_entry *usb_resource_dump;
+static u32  usb_resource_dump_result;
+
+int usb_resource_dump_write (struct file *file, const char *buffer,
+                      unsigned long count, void *data) 
+{
+    return 0;
+}
+
+int usb_resource_dump_read (char *buffer, char **buffer_location, off_t offset,
+                            int buffer_length, int *zero, void *ptr) 
+{
+    int                 i, dev;
+    static int          count = 0;
+    struct mv_usb_dev*  mv_dev;
+
+    printk("usb_resource_dump_read_%-3d\n",  count);
+    if(offset > 0)
+        return 0;
+
+    count++;
+    usb_resource_dump_result = count;
+
+    for(dev=0; dev<mvCtrlUsbMaxGet(); dev++)
+    {
+        mv_dev = the_controllers[dev];
+
+        if(mv_dev != NULL)
+        {
+            mv_usb_show(mv_dev, 0xff);
+
+            _usb_ep_status(mv_dev->mv_usb_handle, 0, ARC_USB_RECV);
+            _usb_ep_status(mv_dev->mv_usb_handle, 0, ARC_USB_SEND);
+
+            for(i=1; i<_usb_device_get_max_endpoint(mv_dev->mv_usb_handle); i++)
+            {
+                struct mv_usb_ep    *ep;
+
+                /* OUT endpoint (RECV) */ 
+                ep = &mv_dev->ep[i*2];
+                if(ep->is_enabled)
+                    _usb_ep_status(mv_dev->mv_usb_handle, i, ARC_USB_RECV);
+
+                /* IN endpoint (SEND) */
+                ep = &mv_dev->ep[i*2+1];
+                if(ep->is_enabled)
+                    _usb_ep_status(mv_dev->mv_usb_handle, i, ARC_USB_SEND);
+            }
+        }
+    }
+    return sprintf(buffer, "%x\n", usb_resource_dump_result);
+}
+
+int usb_start_resource_dump(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+  usb_resource_dump = create_proc_entry ("usb_dump" , 0666 , &proc_root);
+#else
+  usb_resource_dump = create_proc_entry ("usb_dump" , 0666, 0);
+#endif
+  usb_resource_dump->read_proc = usb_resource_dump_read;
+  usb_resource_dump->write_proc = usb_resource_dump_write;
+  usb_resource_dump->nlink = 1;
+  return 0;
+}
+/*
+static struct device_driver mv_usb_gadget_driver = 
+{
+    .name       = (char *) driver_name,
+    .id_table   = NULL,
+    .bus        = &platform_bus_type,
+    .probe      = mv_usb_gadget_probe,
+    .remove     = __exit_p(mv_usb_gadget_remove), 
+};
+*/
+
+static struct platform_driver mv_usb_gadget_driver = {
+        .probe          = mv_usb_gadget_probe,
+        .remove         = __exit_p(mv_usb_gadget_remove),
+        .id_table       = NULL,
+        .driver = {
+                .name = driver_name,
+                .bus = &platform_bus_type
+        }
+};
+
+MODULE_VERSION (DRIVER_VERSION);
+MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_AUTHOR ("Dima Epshtein");
+MODULE_LICENSE ("GPL");
+
+static int __init init (void)
+{
+    int dev_no;
+
+    mvOsPrintf("%s: version %s loaded\n", driver_name, DRIVER_VERSION);
+    for(dev_no=0; dev_no<mvCtrlUsbMaxGet(); dev_no++)
+    {
+	    the_controllers[dev_no] = NULL;
+    }
+    usb_start_resource_dump();
+    return platform_driver_register(&mv_usb_gadget_driver); 
+}
+module_init (init);
+
+static void __exit cleanup (void)
+{
+    mvOsPrintf("%s: version %s unloaded\n", driver_name, DRIVER_VERSION);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+    remove_proc_entry("usb_dump" , &proc_root);
+#else
+    remove_proc_entry("usb_dump", NULL);
+#endif
+    platform_driver_unregister(&mv_usb_gadget_driver);
+}
+module_exit (cleanup);
+
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/Kconfig b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/Kconfig
new file mode 100755
index 0000000..956ce1d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/Kconfig
@@ -0,0 +1,87 @@
+config MV_XOR_NET_DMA
+        bool "Use the XOR engine as NET DMA"
+        depends on NET_DMA && NOT_SUPPORTED
+        default n
+        help
+          Invokes XOR as NET DMA engine
+
+config MV_USE_XOR_ENGINE
+        bool "Use the XOR engines to offload CPU tasks"   
+        depends on (MV_INCLUDE_XOR) && EXPERIMENTAL
+        default n
+        help
+            Say Y of you want to use the XOR engine to offload some of the 
+            CPU tasks.
+
+config MV_XOR_MEMCOPY
+        bool "Use the XOR engine to accelerate memcpy()"
+        depends on MV_USE_XOR_ENGINE && NOT_SUPPORTED
+        default n
+        help
+          Say Y here if you want to use the XOR engine to perform
+          the memcpy and memmove.
+
+config MV_XOR_MEMCOPY_THRESHOLD
+        int "Minimum number of bytes to use XOR acceleration for memcpy()"
+        depends on MV_XOR_MEMCOPY
+        default "128"
+        help
+          This is the minimum buffer size needed in order to operate the XOR engine
+          for accelerating the memcpy() operations
+
+config MV_XOR_MEMXOR
+        bool "Use the XOR engine to perform xor bitmap calculations"
+        depends on MV_USE_XOR_ENGINE
+        default n
+        help
+          Say Y to accelerate the RAID4/5 xor bitmap calculations.
+
+config MV_XOR_MEMXOR_THRESHOLD
+        int "Minimum number of bytes to perform xor bitmap calculations"
+        depends on MV_XOR_MEMXOR
+        default "4096"
+        help
+          This is the minimum buffer size to operate the XOR engine
+          for xor bitmap operations
+
+config MV_XOR_COPY_TO_USER
+	bool "Use XOR hardware to accelerate copy_to_user function"
+	depends on MV_USE_XOR_ENGINE && NOT_SUPPORTED
+	default n
+	help
+	  Say Y here to accelerate the copy_to_user function
+
+config MV_XOR_COPY_TO_USER_THRESHOLD
+        int "A threshold to employ XOR hardware for copy_to_user()"
+        depends on MV_XOR_COPY_TO_USER
+        default "1260"
+        help
+          This is the minimum buffer size required to operate XOR engine
+          to accelerate the copy_to_user() operation.
+
+config MV_XOR_COPY_FROM_USER
+	bool "Use XOR hardware to accelerate copy_from_user function"
+	depends on MV_USE_XOR_ENGINE && NOT_SUPPORTED
+	default n
+	help
+	  Say Y here to accelerate the copy_from_user function
+
+config MV_XOR_COPY_FROM_USER_THRESHOLD
+        int "A threshold to employ XOR hardware for copy_from_user()"
+        depends on MV_XOR_COPY_FROM_USER
+        default "1260"
+        help
+          This is the minimum buffer size required to operate XOR engine
+          to accelerate the copy_from_user() operation.
+
+config MV_XOR_CHANNELS
+        int "Number of XOR channels"
+        depends on MV_USE_XOR_ENGINE
+        range 1 4
+        default 2
+	help
+	  Select the number of XOR channels to be used for kernel functions
+	  accelerations.
+#endmenu
+
+##source	"drivers/dma/Kconfig"
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/Makefile b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/Makefile
new file mode 100755
index 0000000..b3fbdfc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Marvell XOR/DMA Driver
+#
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
+
+obj-$(CONFIG_MV_USE_XOR_ENGINE) += mv_netdma.o
diff --git a/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/mv_netdma.c b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/mv_netdma.c
new file mode 100755
index 0000000..372d626
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_drivers_lsp/mv_xor/mv_netdma.c
@@ -0,0 +1,1610 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+*******************************************************************************/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/dmaengine.h>
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "xor/mvXor.h"
+#include "xor/mvXorRegs.h"
+#include "mvSysXorApi.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#define DUBUG
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK(s, args...)  printk("xor: " s, ## args)
+#else
+#define DPRINTK(s, args...)
+#endif
+
+/* 
+ * Perform integrity test.
+ * Upon completion of xor dma operation, 
+ * each descriptor will be checked to success bit.
+ */
+#define XOR_INTEGRITY
+#undef XOR_INTEGRITY
+
+/* 
+ * Double invalidate WA
+ */
+#ifdef CONFIG_MV_SP_I_FTCH_DB_INV
+#define XOR_UNMAP
+#endif
+
+/* 
+ * Perform benchmark
+ */
+#define XOR_BENCH
+#undef XOR_BENCH
+
+
+#define XOR_STATS
+//#undef XOR_STATS
+#ifdef XOR_STATS
+#define STAT_INC(s) 	xor_stats->s++
+#define STAT_ADD(s,n) 	xor_stats->s[((n)>>STAT_SHIFT)&(STAT_BYTES-1)]++
+#define STAT_SHIFT	7
+#define STAT_BYTES	(1 << 9)
+#else
+#define STAT_INC(s)
+#define STAT_ADD(s,n)
+#endif
+#if defined (CONFIG_MV_XOR_MEMCOPY) || defined (CONFIG_MV_IDMA_MEMCOPY)
+#define memcpy asm_memcpy
+#endif
+
+#define XOR_BUG(c) if (c) {xor_dump(); BUG();}
+
+#define CHANNELS    		CONFIG_MV_XOR_CHANNELS
+#define ENGINES    			(CHANNELS >> 1)
+#define XOR_TIMEOUT 		0x8000000
+#define XOR_MIN_COPY_CHUNK 	16		/* A0 specification */
+#define NET_DESC 			128		/* NET DMA descriptors */
+#define DMA_DESC 			2		/* memcpy descriptors */
+
+#define to_dma_channel(dch) container_of(dch, struct xor_dma_channel, common)
+
+enum {
+	CHAIN_NETDMA = CHANNELS,
+#ifdef CONFIG_MV_XOR_MEMCOPY
+	CHAIN_MEMCPY,
+#endif
+#ifdef CONFIG_MV_XOR_MEMXOR
+	CHAIN_MEMXOR,
+#endif
+#ifdef CONFIG_MV_XOR_COPY_TO_USER
+	CHAIN_TO_USR,
+#endif
+#ifdef CONFIG_MV_XOR_COPY_FROM_USER
+	CHAIN_FROM_USR,
+#endif
+	CHAINS,
+};
+
+typedef MV_XOR_DESC xor_desc_t;
+
+struct xor_chain {
+	unsigned int 		idx;
+	unsigned int		pending;
+	xor_desc_t*    		desc;			/* N descriptors 	*/
+	dma_addr_t     	 	base;			/* phy address  	*/
+	struct xor_channel*	owner;			/* owned by channel	*/
+	unsigned int		busy;			/* busy by cpu		*/
+	unsigned int		cookie_used;	/* last used 		*/
+	unsigned int		cookie_done;	/* last completed 	*/
+};
+
+struct xor_channel {
+	unsigned int 		idx;
+	unsigned int		busy;
+	struct xor_chain* 	chain;			/* busy on chain	*/
+	unsigned int		pad;
+};
+
+#ifdef CONFIG_MV_XOR_NET_DMA
+struct xor_dma_device {
+	struct dma_device common;
+};
+
+struct xor_dma_channel {
+	struct dma_chan		common;
+	struct xor_chain* 	chain;
+	spinlock_t 			lock;
+};
+#endif
+
+struct xor_net_stats
+{
+#ifdef XOR_STATS
+	unsigned int err_chann_busy;
+	unsigned int err_chain_busy;
+	unsigned int err_addr;
+	unsigned int err_dma;
+
+#ifdef CONFIG_MV_XOR_NET_DMA
+	unsigned int netdma_b2p;
+	unsigned int netdma_p2p;
+	unsigned int netdma_b2b;
+	unsigned int netdma_cpu;
+	unsigned int netdma_dma;
+	unsigned int netdma_complete;
+	unsigned int netdma_pending;
+	unsigned int netdma_bytes[STAT_BYTES];
+#endif
+#ifdef CONFIG_MV_XOR_MEMCOPY
+	unsigned int memcp;
+	unsigned int memcp_dma;
+	unsigned int memcp_bytes[STAT_BYTES];
+#endif
+#ifdef CONFIG_MV_XOR_MEMXOR
+	unsigned int memxor;
+	unsigned int memxor_dma;
+	unsigned int memxor_bytes[STAT_BYTES];
+#endif
+#ifdef CONFIG_MV_XOR_COPY_TO_USER
+	unsigned int to_usr;
+	unsigned int to_usr_dma;
+	unsigned int to_usr_bytes[STAT_BYTES];		
+#endif
+#ifdef CONFIG_MV_XOR_COPY_FROM_USER
+	unsigned int from_usr;
+	unsigned int from_usr_dma;
+	unsigned int from_usr_bytes[STAT_BYTES];		
+#endif
+#endif
+};
+
+#ifdef CONFIG_MV_XOR_NET_DMA
+static struct xor_dma_device xor_dma_dev;
+static struct xor_dma_channel xor_dma_chn[1];
+#endif
+
+struct xor_channel* xor_channels;
+struct xor_chain* xor_chains;
+struct xor_net_stats* xor_stats;
+
+static unsigned int xor_enabled __read_mostly;
+
+
+
+/*
+ * channel busy test
+ */
+static inline unsigned int xor_is_active(unsigned int i)
+{
+	return MV_REG_READ(XOR_ACTIVATION_REG(XOR_UNIT(i),XOR_CHAN(i))) 
+			/* & XEXACTR_XESTATUS_MASK */;
+}
+
+/*
+ * set dma operation mode for channel i
+ */
+static inline void xor_mode_dma(unsigned int i)
+{
+	unsigned int mode = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(i),XOR_CHAN(i)));
+	mode &= ~XEXCR_OPERATION_MODE_MASK;
+	mode |= XEXCR_OPERATION_MODE_DMA;
+	MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(i), XOR_CHAN(i)), mode);
+}
+
+/*
+ * set xor operation mode for channel i
+ */
+static inline void xor_mode_xor(unsigned int i)
+{
+	unsigned int mode = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(i),XOR_CHAN(i)));
+	mode &= ~XEXCR_OPERATION_MODE_MASK;
+	mode |= XEXCR_OPERATION_MODE_XOR;
+	MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(i), XOR_CHAN(i)), mode);
+}
+
+/*
+ * run dma operation on channel
+ */
+static inline void xor_dma(unsigned int i, unsigned int base)
+{
+#ifdef MV_BRIDGE_SYNC_REORDER
+	mvOsBridgeReorderWA();
+#endif
+	MV_REG_WRITE(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(i), XOR_CHAN(i)), base);                    
+	MV_REG_WRITE(XOR_ACTIVATION_REG(XOR_UNIT(i), XOR_CHAN(i)), XEXACTR_XESTART_MASK);
+}
+
+/*
+ * xor engine busy wait
+ */
+static void xor_dump(void);
+#define XOR_CAUSE_DONE_MASK(chan) ((BIT0|BIT1) << (chan * 16))
+void xor_wait(unsigned int chan)
+{
+    unsigned int timeout;
+	unsigned int addr = XOR_CAUSE_REG(XOR_UNIT(chan));
+	unsigned int mask = XOR_CAUSE_DONE_MASK(XOR_CHAN(chan));
+
+	timeout = XOR_TIMEOUT;
+    while(!(MV_REG_READ(addr) & mask))
+		XOR_BUG(!timeout--);			
+
+	MV_REG_WRITE(addr, ~mask);
+
+    timeout = XOR_TIMEOUT;
+	while(xor_is_active(chan))
+		XOR_BUG(!timeout--);
+}
+
+/*
+ * Second L2 invalidate (WA)
+ */
+#ifdef XOR_UNMAP
+static void xor_chain_unmap(struct xor_chain* chain)
+{
+	u32 va;
+	u32 i = chain->pending;
+	xor_desc_t* desc = chain->desc;
+	unsigned long flags;
+
+	raw_local_irq_save(flags);
+
+	while(i--) {
+		va = __phys_to_virt(desc->phyDestAdd);
+		/* invalidate l2 */
+		__asm__ __volatile__ ("mcr p15, 1, %0, c15, c11, 4" : : "r" (va));
+		__asm__ __volatile__ ("mcr p15, 1, %0, c15, c11, 5" : : "r" (va+desc->byteCnt-1));
+		desc++;
+	}
+
+	raw_local_irq_restore(flags);
+}
+#endif
+/*
+ * Chain integrity test
+ */
+#ifdef XOR_INTEGRITY
+static void xor_integrity(struct xor_chain* chain)
+{
+	unsigned int i;
+
+	for (i=0; i<chain->pending; i++) {
+		mvOsCacheLineInv(0, chain->desc + i);
+		if (chain->desc[i].status != 0x40000000) {
+			printk("XOR: violation chain[%d] desc=%d status=%x active=%d %x<-%x %d bytes\n", 
+				   chain->idx, i, 
+				   chain->desc[i].status,
+				   xor_is_active(chain->idx),
+				   chain->desc[i].phyDestAdd, chain->desc[i].srcAdd0, chain->desc[i].byteCnt);
+		}
+	}
+}
+#endif
+
+static void xor_dump(void)
+{
+	unsigned int i;
+
+	for (i=0; i<CHANNELS; i++) {
+		printk(" CHANNEL_ARBITER_REG %08x\n", MV_REG_READ(XOR_CHANNEL_ARBITER_REG(XOR_UNIT(i))));
+		printk(" CONFIG_REG          %08x\n", MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(i),XOR_CHAN(i))));
+		printk(" ACTIVATION_REG      %08x\n", MV_REG_READ(XOR_ACTIVATION_REG(XOR_UNIT(i), XOR_CHAN(i))));
+		printk(" CAUSE_REG           %08x\n", MV_REG_READ(XOR_CAUSE_REG(XOR_UNIT(i))));
+		printk(" MASK_REG            %08x\n", MV_REG_READ(XOR_MASK_REG(XOR_UNIT(i))));
+		printk(" ERROR_CAUSE_REG     %08x\n", MV_REG_READ(XOR_ERROR_CAUSE_REG(XOR_UNIT(i))));
+		printk(" ERROR_ADDR_REG      %08x\n", MV_REG_READ(XOR_ERROR_ADDR_REG(XOR_UNIT(i))));
+		printk(" NEXT_DESC_PTR_REG   %08x\n", MV_REG_READ(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(i),XOR_CHAN(i))));
+		printk(" CURR_DESC_PTR_REG   %08x\n", MV_REG_READ(XOR_CURR_DESC_PTR_REG(XOR_UNIT(i),XOR_CHAN(i))));
+		printk(" BYTE_COUNT_REG      %08x\n\n", MV_REG_READ(XOR_BYTE_COUNT_REG(XOR_UNIT(i),XOR_CHAN(i))));
+	}
+
+	for (i=0; i<CHANNELS; i++) {
+		printk("channel[%d] active=0x%x busy=%d chain=%x\n", 
+						xor_channels[i].idx,
+						xor_is_active(i), 
+						xor_channels[i].busy, 
+						xor_channels[i].chain ? xor_channels[i].chain->idx : ~0);
+	}
+
+	for (i=0; i<CHAINS; i++) {		
+		printk("chain[%d] on channel=%8x desc=%x cookies(%x,%x) pending=%d\n", i,
+						xor_chains[i].owner ? xor_chains[i].owner->idx : ~0,
+						xor_chains[i].base, 
+						xor_chains[i].cookie_done,
+						xor_chains[i].cookie_used,
+						xor_chains[i].pending);
+	}
+}
+
+static void xor_stat(void)
+{	
+#ifdef XOR_STATS
+		int i;
+
+		printk("XOR errors...........%10u\n", xor_stats->err_dma);
+		printk("XOR busy channel.....%10u\n", xor_stats->err_chann_busy); 
+		printk("XOR busy chain.......%10u\n", xor_stats->err_chain_busy);
+		printk("XOR invalid address..%10u\n", xor_stats->err_addr);
+#ifdef CONFIG_MV_XOR_NET_DMA
+		printk("\n");
+		printk("NETDMA b2p...........%10u\n", xor_stats->netdma_b2p);
+		printk("NETDMA p2p...........%10u\n", xor_stats->netdma_p2p);
+		printk("NETDMA b2b...........%10u\n", xor_stats->netdma_b2b);
+		printk("NETDMA by cpu........%10u\n", xor_stats->netdma_cpu);
+		printk("NETDMA by hw.........%10u\n", xor_stats->netdma_dma);
+		printk("NETDMA pending.......%10u\n", xor_stats->netdma_pending);
+		printk("NETDMA complete......%10u\n", xor_stats->netdma_complete);
+#endif
+#ifdef CONFIG_MV_XOR_MEMCOPY
+		printk("\n");
+		printk("MEMCPY total.........%10u\n", xor_stats->memcp);
+		printk("MEMCPY by hw.........%10u\n", xor_stats->memcp_dma);
+#endif
+#ifdef CONFIG_MV_XOR_MEMXOR
+		printk("\n");
+		printk("MEMXOR total.........%10u\n", xor_stats->memxor);
+		printk("MEMXOR by hw.........%10u\n", xor_stats->memxor_dma);
+#endif
+#ifdef CONFIG_MV_XOR_COPY_TO_USER
+		printk("\n");
+		printk("TO_USER total.........%10u\n", xor_stats->to_usr);
+		printk("TO_USER by hw.........%10u\n", xor_stats->to_usr_dma);
+#endif
+#ifdef CONFIG_MV_XOR_COPY_FROM_USER
+		printk("\n");
+		printk("FROM_USER total.........%10u\n", xor_stats->from_usr);
+		printk("FROM_USER by hw.........%10u\n", xor_stats->from_usr_dma);
+#endif
+
+		printk("BYTES  NETDMA   MEMCPY   MEMXOR   TO_USER  FROM_USER\n");
+		for (i=0; i<STAT_BYTES; i++) {
+			u32 a=0, b=0, c=0, d=0, e=0;
+#ifdef CONFIG_MV_XOR_NET_DMA
+			a = xor_stats->netdma_bytes[i];
+#endif
+#ifdef CONFIG_MV_XOR_MEMCOPY
+			b = xor_stats->memcp_bytes[i];
+#endif
+#ifdef CONFIG_MV_XOR_MEMXOR
+			c = xor_stats->memxor_bytes[i];
+#endif
+#ifdef CONFIG_MV_XOR_COPY_TO_USER
+			d = xor_stats->to_usr_bytes[i];
+#endif
+#ifdef CONFIG_MV_XOR_COPY_FROM_USER
+			e = xor_stats->from_usr_bytes[i];
+#endif
+			if (a || b || c || d || e)
+				printk("%5d%8u %8u %8u %8u %8u\n", i<<STAT_SHIFT, a, b, c, d, e);
+		}
+
+		memset(xor_stats, 0, sizeof(struct xor_net_stats));
+#endif       
+}
+
+/*
+ * Allocate chain
+ */
+static inline unsigned int xor_try_chain(struct xor_chain* chain)
+{
+	unsigned long flags=0;
+	local_irq_save(flags);	
+	if (chain->busy) {
+		local_irq_restore(flags);
+		STAT_INC(err_chain_busy);
+		return 1;
+	}
+	chain->busy = 1;
+	local_irq_restore(flags);
+	return 0;
+}
+
+/*
+ * Connect channel to chain
+ */
+static inline void xor_attach(struct xor_chain* chain, struct xor_channel* xch)
+{
+	xch->chain = chain;
+	chain->owner = xch;
+}
+
+/*
+ * Disconnect channel and chain
+ */
+static inline void xor_detach(struct xor_chain* chain, struct xor_channel* xch)
+{
+#ifdef XOR_INTEGRITY
+	xor_integrity(chain);
+#endif	
+#ifdef XOR_UNMAP
+	if (chain->pending) 
+		xor_chain_unmap(chain);
+#endif
+	chain->cookie_done = chain->cookie_used;
+	chain->pending = 0;
+	chain->owner = NULL;
+	chain->busy = 0;
+	xch->chain = NULL;
+}
+
+/*
+ * Allocate channel
+ */
+static struct xor_channel* xor_get(void)
+{
+    static int rr=0;
+	int retry=CHANNELS;
+	struct xor_channel* xch = NULL;	
+	unsigned long flags=0;
+
+	local_irq_save(flags);
+
+	rr += ENGINES;
+
+	while(retry--) { 
+		rr &= (CHANNELS-1);
+
+		if (xor_channels[rr].busy || xor_is_active(rr)) {
+			rr++;
+			continue;
+		}
+	
+		xch = &xor_channels[rr];
+		xch->busy = 1;
+
+		if (xch->chain)
+			xor_detach(xch->chain, xch);
+
+		break;
+	}
+
+	local_irq_restore(flags);
+
+	if (!xch) 
+		STAT_INC(err_chann_busy);
+
+	return xch;
+}
+
+static inline void xor_put(struct xor_channel* xch)
+{
+	xch->busy = 0;
+}
+
+/*
+ * Fast clean, dsb() required
+ * The call is intended for multiple calls and when dsb() on commit endpoint
+ */
+static inline void dmac_clean_dcache_line(void* addr)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 1" : : "r" (addr));
+	__asm__ __volatile__ ("mcr p15, 1, %0, c15, c9, 1" : : "r" (addr));
+
+#else
+	dma_cache_maint(addr, 32, DMA_TO_DEVICE);
+#endif
+}
+
+#ifdef CONFIG_MV_XOR_NET_DMA
+static int xor_alloc_chan_resources(struct dma_chan *dch)
+{
+	return 1;
+}
+
+static void xor_free_chan_resources(struct dma_chan *dch)
+{
+	printk("xor: free netdma chain[%d] resources\n", dch->chan_id);
+}
+
+/*
+ *  Start xmit of chain 
+ */
+static struct xor_chain* xor_xmit(struct xor_chain* chain)
+{
+	struct xor_channel* xch;
+	int i;
+
+	xch = xor_get();
+	if (!xch) 
+		goto out;
+
+	xor_attach(chain, xch);
+
+	i = chain->pending;
+	while(i--)
+		dmac_clean_dcache_line(chain->desc + i);
+	dsb();
+
+	STAT_INC(netdma_dma);
+	xor_dma(xch->idx, chain->base);
+	xor_put(xch);
+
+	/*
+	 * find free chain,
+	 * always succedded since chains >> channels
+	 */
+	i = CHAIN_NETDMA;
+	while(i--) {	
+		if (likely(chain->idx < CHAIN_NETDMA))
+			chain++;
+		else
+			chain = xor_chains;
+
+		if (chain->owner)
+			continue;
+			
+		if (chain->busy)
+			continue;
+
+        chain->busy = 1;
+		break;
+	}
+
+out:
+	return chain;	
+}
+
+static dma_cookie_t xor_memcpy_buf_to_pg(struct dma_chan *chan,
+										 struct page *page, unsigned int offset, void *_from, size_t n)
+{
+	u32 to, from=(u32)_from;
+	xor_desc_t* desc;
+	struct xor_dma_channel* dch = to_dma_channel(chan);
+	struct xor_chain* chain;
+	int irq = in_interrupt();
+	u32 c;
+
+	STAT_INC(netdma_b2p);
+	STAT_ADD(netdma_bytes, n);
+
+	to = (u32)page_address(page) + offset;
+
+	DPRINTK("%s: %p<-%p %d bytes\n", __FUNCTION__, to, from, n);
+
+	if (!virt_addr_valid(to) || !virt_addr_valid(from)) {
+		STAT_INC(err_addr);
+		goto out;
+	}
+
+	/* at least two cache lines or XOR minimum */
+	if (n < 96)
+		goto out;
+
+	if (to & 31) {
+		c = 32 - (to & 31);
+		memcpy((void*)to, (void*)from, c);
+		to += c;
+		from += c;
+		n -= c;
+	}
+
+	c = (to+n) & 31;
+	if (c) {
+		n -= c;
+		memcpy((void*)to+n, (void*)from+n, c);
+	}
+
+	if (n < 32) 
+		goto out;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	dmac_clean_range((void*)from, (void*)from + n);
+	dmac_inv_range((void*)to, (void*)to + n);
+#else
+	dma_cache_maint((void*)from, n, DMA_TO_DEVICE);
+	dma_cache_maint((void*)to, n, DMA_FROM_DEVICE);
+#endif
+
+	if (!irq)
+		spin_lock_bh(&dch->lock);
+
+	chain = dch->chain; 
+
+	XOR_BUG(chain->owner || chain->pending>=NET_DESC);
+
+	desc = chain->desc + chain->pending++;
+	desc->srcAdd0 = __pa((void*)from);
+	desc->phyDestAdd = __pa((void*)to);	
+	desc->byteCnt = n;
+	desc->status = BIT31;
+
+	if (chain->pending == 1)
+		chain->cookie_done = chan->cookie;
+
+	if (++chan->cookie < 0)
+		chan->cookie = 1;
+
+	chain->cookie_used = chan->cookie;
+
+    if (chain->pending > 1)
+		dch->chain = xor_xmit(chain);
+
+	if (!irq)
+		spin_unlock_bh(&dch->lock);
+
+	return chan->cookie;
+
+out:
+	STAT_INC(netdma_cpu);
+	memcpy((void*)to, (void*)from, n);
+	return chan->cookie;
+}
+
+static dma_cookie_t xor_memcpy_pg_to_pg(struct dma_chan *chan,
+									struct page *dest_pg, unsigned int dest_off,
+									struct page *src_pg, unsigned int src_off, size_t n)
+{
+	STAT_INC(netdma_p2p);
+	return xor_memcpy_buf_to_pg(chan,
+								dest_pg, 
+								dest_off, 
+								(void*)((u32)page_address(src_pg) + src_off), n);
+}
+
+static dma_cookie_t xor_memcpy_buf_to_buf(struct dma_chan *chan,void *dest, void *src, size_t n)
+{
+	/* kernel copies (e.g. smbfs) 
+	 * not really tested
+	 */
+	STAT_INC(netdma_b2b);
+	return xor_memcpy_buf_to_pg(chan,
+								page_address(dest),
+								page_offset(dest),
+								src, n);
+}
+
+/*
+ * cookies compare
+ */
+static inline int before(__s32 c1, __s32 c2)
+{
+	/*
+	 * Cookies are continuous. 
+	 * The distance between cookies should not exceed FFFF,
+	 * otherwise is considered as overflow.
+	 */
+	if (c1 <= c2) 
+		return (c2 - c1) <= 0xFFFF;
+    else 
+		return (c1 - c2) > 0xFFFF;
+}
+
+/*
+ * Find completed cookie across all chains. 
+ * Each one has [done,used] section. If for sections done=used, report max,
+ * otherwise, the minimum 'done' is returned.
+ */
+static /*inline*/ dma_cookie_t xor_get_completed(void)
+{
+	dma_cookie_t min_cookie = 0;
+	dma_cookie_t max_cookie = 0;
+	dma_cookie_t c_used, c_done;
+
+	struct xor_chain* chain = xor_chains;
+	int i = CHAIN_NETDMA;
+
+	do {
+			c_used = chain->cookie_used;
+			c_done = chain->cookie_done;
+
+			if (c_used != c_done) {
+				if (chain->owner && !xor_is_active(chain->owner->idx)) {
+					c_used = c_done = chain->cookie_used;
+				}
+			}
+
+			if (c_used != c_done) {
+			/*
+			 * at least one chain is incomplete. 
+			 * find minimal cookie which is done across all chains
+			 */		
+				if (!min_cookie || before(c_done, min_cookie))
+					min_cookie = c_done;
+			}
+
+			/*
+			 * in the case whether all chains are completed, 
+			 * find their max cookie
+			 */		
+			else if (!c_done)  {
+				;
+			}
+			else if (!max_cookie || before(max_cookie, c_done))
+					max_cookie = c_done;
+
+			chain++;
+
+	} while(i--);
+
+	return min_cookie ? min_cookie: max_cookie;
+}
+#ifdef XOR_UNMAP
+static void xor_memcpy_cleanup(struct dma_chan *chan, dma_cookie_t cookie)
+{
+	struct xor_chain* chain = xor_chains;
+	struct xor_dma_channel* dch = to_dma_channel(chan);
+	int i = CHAIN_NETDMA;
+
+	spin_lock_bh(&dch->lock);
+
+	do {
+		if (chain->owner && 
+			chain->pending && !xor_is_active(chain->owner->idx)) {
+				xor_detach(chain, chain->owner);
+		}
+
+		chain++;
+
+	} while(i--);
+
+	spin_unlock_bh(&dch->lock);
+}
+#endif
+
+static enum dma_status xor_memcpy_complete(struct dma_chan *chan,
+										dma_cookie_t cookie, 
+										dma_cookie_t *pdone,
+										dma_cookie_t *pused)
+{
+	dma_cookie_t done;
+	dma_cookie_t used;
+	enum dma_status ret;
+
+	STAT_INC(netdma_complete);
+
+	done = xor_get_completed();
+	used = chan->cookie;
+	
+	if (pdone)
+		*pdone = done;
+	if (pused)
+		*pused = used;
+
+	ret = dma_async_is_complete(cookie, done, used);
+#ifdef XOR_UNMAP
+	if (ret == DMA_SUCCESS)
+		xor_memcpy_cleanup(chan, cookie);
+#endif
+
+	return ret;
+}
+
+static void xor_memcpy_issue_pending(struct dma_chan *chan)
+{
+	struct xor_dma_channel* dch = to_dma_channel(chan);
+	struct xor_chain* chain;
+	unsigned int irq = in_interrupt();
+
+	STAT_INC(netdma_pending);
+
+	chain = dch->chain;
+	if (chain->owner)
+		return;
+
+	if (!irq)
+		spin_lock_bh(&dch->lock);
+
+	chain = dch->chain;
+
+	if (!chain->owner && chain->pending) {
+		do {
+			dch->chain = xor_xmit(chain);
+		} while (dch->chain == chain);
+	}
+ 
+	if (!irq)
+		spin_unlock_bh(&dch->lock);
+}
+#endif /* CONFIG_MV_XOR_NET_DMA */
+
+static int xor_proc_write(struct file *file, const char __user *buffer,
+			   unsigned long count, void *data)
+{
+#ifdef XOR_BENCH
+	xor_bench(NULL,NULL,0);
+#endif
+	return count;
+}
+
+static int xor_proc_read(char *page, char **start, off_t off, 
+						 int count, int *eof, void *data)
+{
+	xor_dump();
+	xor_stat();
+	return 0;
+}
+
+int __init mv_xor_init(void)
+{
+		unsigned int i;
+		struct proc_dir_entry *proc_e;
+		struct xor_chain* chain;
+		u32 va;	
+
+		if ((MV_FALSE == mvCtrlPwrClckGet(XOR_UNIT_ID, 0)) || 
+		    (MV_FALSE == mvCtrlPwrClckGet(XOR_UNIT_ID, 1)))
+		{
+			printk("\nWarning at least one XOR port is Powered Off\n");
+			return 0;
+			
+		}
+	
+
+#if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
+		if (MV_FALSE == mvSocUnitIsMappedToThisCpu(XOR)) {
+			printk(KERN_INFO"XOR engine is not mapped to this CPU\n");
+			return -ENODEV;
+		}	
+#endif
+
+		mvSysXorInit();
+
+		/* stats */
+		va = (u32)kmalloc(32 + (sizeof(struct xor_net_stats)), GFP_KERNEL);
+		va += 32 - (va & 31);
+		xor_stats = (struct xor_net_stats*)va;
+		memset(xor_stats, 0, sizeof(struct xor_net_stats));
+
+		/* channels */
+		va = (u32)kmalloc(32 + (sizeof(struct xor_channel) * CHANNELS), GFP_KERNEL);
+		va += 32 - (va & 31);
+		xor_channels = (struct xor_channel*)va;
+		memset(xor_channels, 0, sizeof(struct xor_channel) * CHANNELS);
+
+		/* chains */
+		va = (u32)kmalloc(32 + (sizeof(struct xor_chain) * CHAINS), GFP_KERNEL);
+		va += 32 - (va & 31);
+		xor_chains = (struct xor_chain*)va;
+		memset(xor_chains, 0, sizeof(struct xor_chain) * CHAINS);
+
+		/*
+		 * init channels
+		 */
+		for(i=0; i<CHANNELS; i++) {
+			xor_channels[i].idx = i;
+			xor_channels[i].busy = 0;
+			xor_channels[i].chain = NULL;
+
+			xor_mode_dma(i);
+		}
+
+		/*
+		 * init chains
+         */                                 
+        i = CHAINS;
+		while(i--) {
+			u32 sz, va=0;	
+
+			chain = &xor_chains[i];
+			
+			chain->idx = i;			
+
+			if (i <= CHAIN_NETDMA)
+				sz = sizeof(xor_desc_t) * NET_DESC;
+			else
+				sz = sizeof(xor_desc_t) * DMA_DESC;
+
+			va = (u32)kmalloc(sz+64, GFP_KERNEL);
+			va += 64 - (va & 63);
+			chain->desc = (void*)va;
+			chain->base = __pa(va);
+
+			memset(chain->desc, 0, sz);	
+			BUG_ON(63 & (u32)chain->desc);
+
+			/*
+			 * Init next pointer
+             */
+			if (i <= CHAIN_NETDMA) {
+				int d = NET_DESC - 1;
+				while(d--)
+					chain->desc[d].phyNextDescPtr = 
+						chain->base + (sizeof(xor_desc_t) * (d+1));
+			}
+
+		}
+    
+
+#ifdef CONFIG_PROC_FS
+		/* FIXME: /proc/sys/dev/ */
+		proc_e = create_proc_entry("mvxor", 0666, 0);
+        proc_e->read_proc = xor_proc_read;
+        proc_e->write_proc = xor_proc_write;
+		proc_e->nlink = 1;
+#endif
+
+#ifdef CONFIG_MV_XOR_NET_DMA
+		memset(&xor_dma_dev, 0, sizeof(struct xor_dma_device));
+		memset(xor_dma_chn, 0, sizeof(struct xor_dma_channel));
+		INIT_LIST_HEAD(&xor_dma_dev.common.channels);
+
+		xor_dma_dev.common.chancnt = 1;
+		xor_dma_chn[0].common.device = &xor_dma_dev.common;
+		xor_dma_chn[0].chain = &xor_chains[0];
+		xor_dma_chn[0].chain->busy = 1;
+
+		spin_lock_init(&xor_dma_chn[0].lock);
+		list_add_tail(&xor_dma_chn[0].common.device_node, 
+						  &xor_dma_dev.common.channels);
+
+		xor_dma_dev.common.device_alloc_chan_resources = xor_alloc_chan_resources;
+		xor_dma_dev.common.device_free_chan_resources = xor_free_chan_resources;
+		xor_dma_dev.common.device_memcpy_buf_to_buf = xor_memcpy_buf_to_buf;
+		xor_dma_dev.common.device_memcpy_buf_to_pg = xor_memcpy_buf_to_pg;
+		xor_dma_dev.common.device_memcpy_pg_to_pg = xor_memcpy_pg_to_pg;
+		xor_dma_dev.common.device_memcpy_complete = xor_memcpy_complete;
+		xor_dma_dev.common.device_memcpy_issue_pending = xor_memcpy_issue_pending;
+
+		if (dma_async_device_register(&xor_dma_dev.common)) {
+			printk(KERN_ERR" XOR engine cannot be registered as async NET_DMA\n");    
+			return -ENODEV;
+		}
+
+		printk(KERN_INFO "XOR registered %d NET_DMA over %d channels\n", 
+			   xor_dma_dev.common.chancnt, CHANNELS);
+
+#else
+		printk(KERN_INFO "XOR registered %d channels\n", CHANNELS);
+
+#endif
+
+#ifdef XOR_UNMAP
+		printk(KERN_INFO "XOR 2nd invalidate WA enabled\n");
+#endif
+		xor_enabled = 1;
+		return 0;
+}
+
+void __exit mv_xor_exit(void)
+{
+    return;
+}
+
+module_init(mv_xor_init);
+module_exit(mv_xor_exit);
+MODULE_LICENSE(GPL);
+
+
+/* = ====================================================================== */
+#ifdef CONFIG_MV_XOR_MEMCOPY
+void* xor_memcpy(void *_to, const void* _from, __kernel_size_t n)
+{
+	u32 to = (u32)_to;
+	u32 from = (u32)_from;
+	u32 sa, da;
+
+	struct xor_chain* chain;
+	struct xor_channel *xch;
+
+	if (!xor_enabled)			
+		return asm_memcpy((void*)to, (void*)from, n);
+
+	STAT_INC(memcp);
+	STAT_ADD(memcp_bytes,n);
+
+	DPRINTK("%s:%x<-%x %d bytes\n", __FUNCTION__, to, from, n);
+
+	if (n < 128)
+		goto out;
+
+	if (!virt_addr_valid(to) || !virt_addr_valid(from)) {
+		STAT_INC(err_addr);
+		goto out;
+	}
+
+	da = __pa((void*)to);	
+	sa = __pa((void*)from);
+
+	if (((da < sa) && (sa < da+n)) || 
+		((sa < da) && (da < sa+n))) 
+		return memmove((void*)to, (void*)from, n);
+	
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	dmac_clean_range((void*)from, (void*)from + n);
+	dmac_inv_range((void*)to, (void*)to + n);
+#else
+	dma_cache_maint((void*)from, n, DMA_TO_DEVICE);
+	dma_cache_maint((void*)to, n, DMA_FROM_DEVICE);
+#endif
+
+	da = virt_to_phys((void*)to);	
+	sa = virt_to_phys((void*)from);
+
+	if (unlikely(!sa || !da)) {
+		STAT_INC(err_addr);
+		goto out;
+	}
+
+	chain = &xor_chains[CHAIN_MEMCPY];
+	if (xor_try_chain(chain)) 
+		goto out;
+
+	DPRINTK("%s: %x<-%x %d bytes\n", __FUNCTION__, da, sa, n);
+	chain->pending = 1;
+	chain->desc->srcAdd0 = sa;
+	chain->desc->phyDestAdd = da;
+	chain->desc->byteCnt = n;
+	chain->desc->phyNextDescPtr = 0;
+	chain->desc->status = BIT31;
+
+	dmac_clean_dcache_line(chain->desc);
+	dsb();
+
+	xch = xor_get();
+	if (!xch) 
+		goto out2;
+
+	STAT_INC(memcp_dma);
+	xor_attach(chain, xch);
+	xor_dma(xch->idx, chain->base);
+
+	{
+		u32 c;
+
+		da = to & 31;
+		sa = from & 31;		
+		if (sa || da) {
+			c = (sa > da) ? 32 - da : 32 - sa;
+			memmove((void*)to, (void*)from, c);
+		}
+
+		da = (to+n) & 31;
+		sa = (from+n) & 31;
+		if (sa || da) {
+			c = (da > sa) ? da : sa;
+			memmove((void*)(to+n-c), (void*)(from+n-c), c);
+		}
+	}
+
+	xor_wait(xch->idx);
+	xor_detach(chain, xch);
+	xor_put(xch);
+
+	return (void*)to;
+
+out2:
+	chain->busy = 0;
+out:
+	return asm_memcpy((void*)to, (void*)from, n);
+}
+EXPORT_SYMBOL(xor_memcpy);
+#endif /* CONFIG_MV_XOR_MEMCOPY */
+
+#ifdef CONFIG_MV_XOR_MEMXOR
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+int xor_memxor(unsigned int count, unsigned int n, void **va)
+{
+	struct xor_chain* chain;
+	struct xor_channel *xch;
+	u32* p;
+
+	if (!xor_enabled)
+		goto out;
+
+	BUG_ON(count <= 1);
+
+	DPRINTK("%s: %d sources %d bytes\n", __FUNCTION__, count, n);
+
+	chain = &xor_chains[CHAIN_MEMXOR];
+	if (xor_try_chain(chain)) 
+		goto out;
+
+	chain->pending = 1;
+	chain->desc->phyDestAdd = __pa(va[0]);
+	chain->desc->byteCnt = n;
+	chain->desc->phyNextDescPtr = 0;
+	chain->desc->descCommand = (1 << count) - 1;
+	chain->desc->status = BIT31;
+
+	p = &chain->desc->srcAdd0;
+
+#ifdef MV_CPU_BE
+	p = &chain->desc->srcAdd1;
+	if (count & 1) 
+		p[count] = __pa(va[count-1]);
+#endif
+
+	while(count--) {
+		dmac_clean_range(va[count], (void*)va[count] + n);
+		p[count] = __pa(va[count]);
+	}
+
+	dmac_clean_dcache_line(chain->desc);
+	dmac_clean_dcache_line(chain->desc+32);
+	dsb();
+
+	xch = xor_get();
+	if (!xch) 
+		goto out2;
+
+	STAT_ADD(memxor_bytes, n);
+	STAT_INC(memxor_dma);
+
+	xor_attach(chain, xch);
+	xor_mode_xor(xch->idx);
+	xor_dma(xch->idx, chain->base);
+
+	/* could be useful before busywait, because we already have it clean */
+	dmac_inv_range(va[0], (void*)va[0] + n);
+	xor_wait(xch->idx);
+
+	xor_mode_dma(xch->idx);
+	xor_detach(chain, xch);
+	wmb();
+	xor_put(xch);
+
+	return 0;
+
+out2:
+	chain->busy = 0;
+out:
+	return 1;
+}
+#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26) */
+int xor_memxor(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
+{
+	struct xor_chain* chain;
+	struct xor_channel *xch;
+	u32* p;
+
+	if (!xor_enabled)
+		goto out;
+
+	BUG_ON(src_count < 1);
+
+	DPRINTK("%s: %d sources %d bytes\n", __FUNCTION__, src_count, bytes);
+
+	chain = &xor_chains[CHAIN_MEMXOR];
+	if (xor_try_chain(chain)) 
+		goto out;
+
+	chain->pending = 1;
+	chain->desc->phyDestAdd = __pa(dest);
+	chain->desc->byteCnt = bytes;
+	chain->desc->phyNextDescPtr = 0;
+	chain->desc->descCommand = (1 << (src_count+1)) - 1; /* add dest to the count */
+	chain->desc->status = BIT31;
+
+#ifdef MV_CPU_BE
+    /* set the first (srcAdd1) desc to be the dest */
+	chain->desc->srcAdd1 = chain->desc->phyDestAdd;
+	p = &chain->desc->srcAdd0;
+	if ((src_count+1) & 1)
+		p[src_count] = __pa(srcs[src_count-1]);
+#else
+	/* set the first desc (srcAdd0) to be the dest */
+	chain->desc->srcAdd0 = chain->desc->phyDestAdd;
+	p = &chain->desc->srcAdd1;
+#endif
+
+	dma_cache_maint(dest, bytes, DMA_TO_DEVICE);
+    
+	while(src_count--) {
+		dma_cache_maint((void*)srcs[src_count], bytes, DMA_TO_DEVICE);
+		p[src_count] = __pa(srcs[src_count]);
+	}
+
+	dmac_clean_dcache_line(chain->desc);
+	dmac_clean_dcache_line(chain->desc+32);
+	dsb();
+
+	xch = xor_get();
+	if (!xch) 
+		goto out2;
+
+	STAT_ADD(memxor_bytes, bytes);
+	STAT_INC(memxor_dma);
+
+	xor_attach(chain, xch);
+	xor_mode_xor(xch->idx);
+	xor_dma(xch->idx, chain->base);
+
+	/* could be useful before busywait, because we already have it clean */
+	dma_cache_maint(dest, bytes, DMA_FROM_DEVICE);
+	xor_wait(xch->idx);
+
+	xor_mode_dma(xch->idx);
+	xor_detach(chain, xch);
+	wmb();
+	xor_put(xch);
+
+	return 0;
+
+out2:
+	chain->busy = 0;
+out:
+	return 1;
+}
+
+#endif
+EXPORT_SYMBOL(xor_memxor);
+#endif /* CONFIG_MV_XOR_MEMXOR */
+
+
+#if defined(CONFIG_MV_XOR_COPY_TO_USER) || defined(CONFIG_MV_XOR_COPY_FROM_USER)
+/*
+ * Obtain pa address from user va
+ */
+static inline u32 __pa_user(u32 va, int write)
+{
+    struct page *page;
+    struct vm_area_struct *vm;
+    struct mm_struct * mm = (va >= TASK_SIZE)? &init_mm : current->mm;
+    unsigned int flags;
+
+    if (virt_addr_valid(va)) 
+        return __pa(va);
+
+    if (va >= (u32)high_memory)
+	    return 0;
+    
+    flags  = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+
+    vm = find_extend_vma(mm, va);
+    if (!vm || (vm->vm_flags & (VM_IO|VM_PFNMAP)) || !(flags & vm->vm_flags))
+		return 0;
+
+    flags = FOLL_PTE_EXIST | FOLL_TOUCH;
+    flags |= (write) ? FOLL_WRITE : 0;
+		 
+    page = follow_page(vm, va, flags);
+    
+    if (pfn_valid(page_to_pfn(page))) 
+        return ((page_to_pfn(page) << PAGE_SHIFT) | (va & (PAGE_SIZE - 1)));
+
+	return 0;
+}
+#endif /* COPY_XX_USER */
+
+#ifdef CONFIG_MV_XOR_COPY_TO_USER
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+unsigned long xor_copy_to_user(unsigned long to, unsigned long from, unsigned long n)
+{
+	u32 sa, da, copy;
+	struct xor_chain* chain;
+	struct xor_channel* xch;
+	unsigned int i = 0;
+	unsigned long rc;
+	unsigned long flags=0;
+
+	if (unlikely(!xor_enabled))
+		goto out;
+
+	STAT_INC(to_usr);
+	STAT_ADD(to_usr_bytes, n);
+
+	DPRINTK("%s: %p<-%p %d bytes\n", __FUNCTION__, to, from, n);
+
+	if (!virt_addr_valid(from)) {
+		STAT_INC(err_addr);
+		goto out;
+	}
+
+	if (to & 31) 
+		mvOsCacheLineFlushInv(0, to);
+
+	if ((to+n) & 31) 
+		mvOsCacheLineFlushInv(0, to+n);
+
+	dmac_clean_range((void*)from, (void*)from + n);
+	
+	chain = &xor_chains[CHAIN_TO_USR];
+	if (xor_try_chain(chain)) 
+		goto out;
+
+	local_irq_save(flags);	
+
+	while(n) {
+		copy = PAGE_SIZE - (to & ~PAGE_MASK);
+		if (copy > n)
+			copy = n;
+
+		if (!copy) 
+			break;
+
+		if (copy < XOR_MIN_COPY_CHUNK) {
+			rc= __arch_copy_to_user((void*)to, (void*)from, copy);
+			if (rc)
+				goto out2;
+		}
+		else {
+
+			sa = __pa(from);
+			da = __pa_user(to, 1);
+	
+			if (unlikely(!sa || !da)) {
+				STAT_INC(err_addr);
+				goto out2;
+			}
+
+            DPRINTK("%s: desc[%d] %x<-%x %d bytes\n", __FUNCTION__, i, da, sa, copy);
+
+			dmac_inv_range((void*)to, (void*)to + copy);
+
+			chain->desc[i].srcAdd0 = sa;
+			chain->desc[i].phyDestAdd = da;
+			chain->desc[i].byteCnt = copy;
+			chain->desc[i].phyNextDescPtr = 0;
+			chain->desc[i].status = BIT31;
+			if (i) 
+				chain->desc[i-1].phyNextDescPtr = 
+						chain->base + (sizeof(xor_desc_t) * i);
+			
+			i++;
+		}
+
+		from += copy;
+		to += copy;
+		n -= copy;
+	}
+
+	if (i) {       
+
+		while(i--)
+			dmac_clean_dcache_line(chain->desc + i);
+		dsb();
+
+		xch = xor_get();		
+		if (!xch) 
+			goto out2;
+
+		xor_attach(chain, xch);
+
+		DPRINTK("%s: ch[%d] chain=%d\n", __FUNCTION__, xch->idx, chain->idx);
+
+		STAT_INC(to_usr_dma);
+		xor_dma(xch->idx, chain->base);
+		xor_wait(xch->idx);
+
+		xor_detach(chain, xch);
+		xor_put(xch);
+	}
+
+	local_irq_restore(flags);
+
+	return 0;
+
+out2:
+	chain->busy=0;
+	local_irq_restore(flags);
+out:
+	return __arch_copy_to_user((void*)to, (void*)from, n);
+}
+EXPORT_SYMBOL(xor_copy_to_user);
+#else
+#error "Kernel version >= 2,6,26 does not support XOR copy_to_user"
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) */
+#endif /* CONFIG_MV_XOR_COPY_TO_USER */
+
+#ifdef CONFIG_MV_XOR_COPY_FROM_USER
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+unsigned long xor_copy_from_user(unsigned long to, unsigned long from, unsigned long n)
+{
+	u32 sa, da, copy;
+	struct xor_chain* chain;
+	struct xor_channel* xch;
+	unsigned int i = 0;
+	unsigned long flags=0;
+	unsigned long rc;
+
+	if (unlikely(!xor_enabled))
+		goto out;
+
+	STAT_INC(from_usr);
+	STAT_ADD(from_usr_bytes, n);
+
+	DPRINTK("%s: %p<-%p %d bytes\n", __FUNCTION__, to, from, n);
+
+	if (!virt_addr_valid(to)) {
+		STAT_INC(err_addr);
+		goto out;
+	}
+
+	if (to & 31) 
+		mvOsCacheLineFlushInv(0, to);
+
+	if ((to+n) & 31) 
+		mvOsCacheLineFlushInv(0, to+n);
+
+	dmac_inv_range((void*)to, (void*)to + n);
+	
+	chain = &xor_chains[CHAIN_FROM_USR];
+	if (xor_try_chain(chain)) 
+		goto out;
+
+	local_irq_save(flags);	
+
+	while(n) {
+		copy = PAGE_SIZE - (from & ~PAGE_MASK);
+		if (copy > n)
+			copy = n;
+
+		if (!copy) 
+			break;
+
+		if (copy < XOR_MIN_COPY_CHUNK) {
+			rc = __arch_copy_from_user((void*)to, (void*)from, copy);
+			if (rc)
+				goto out2;
+		}
+		else {
+
+			sa = __pa_user(from, 0);
+			da = __pa(to);
+
+			if (unlikely(!sa || !da)) {
+				STAT_INC(err_addr);
+				goto out2;
+			}
+            
+			DPRINTK("%s: desc[%d] %x<-%x %d bytes\n", __FUNCTION__, i, da, sa, copy);
+
+			dmac_clean_range((void*)from, (void*)from + copy);
+
+			chain->desc[i].srcAdd0 = sa;
+			chain->desc[i].phyDestAdd = da;
+			chain->desc[i].byteCnt = copy;
+			chain->desc[i].phyNextDescPtr = 0;
+			chain->desc[i].status = BIT31;
+			if (i) 
+				chain->desc[i-1].phyNextDescPtr = 
+						chain->base + (sizeof(xor_desc_t) * i);
+			
+			i++;
+		}
+
+		from += copy;
+		to += copy;
+		n -= copy;
+	}
+
+	if (i) {       
+
+		while(i--)
+			dmac_clean_dcache_line(chain->desc + i);
+		dsb();
+
+		xch = xor_get();		
+		if (!xch) 
+			goto out2;
+
+		xor_attach(chain, xch);
+
+		DPRINTK("%s: ch[%d] chain=%d\n", __FUNCTION__, xch->idx, chain->idx);
+
+		STAT_INC(from_usr_dma);
+		xor_dma(xch->idx, chain->base);
+		xor_wait(xch->idx);
+
+		xor_detach(chain, xch);
+		xor_put(xch);
+	}
+
+	local_irq_restore(flags);
+
+	return 0;
+
+out2:
+	chain->busy=0;
+	local_irq_restore(flags);
+out:
+	return __arch_copy_from_user((void*)to, (void*)from, n);
+}
+EXPORT_SYMBOL(xor_copy_from_user);
+#else
+#error "Kernel version >= 2,6,26 does not support XOR copy_from_user"
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) */
+#endif /* CONFIG_MV_XOR_COPY_FROM_USER */
+
+
+#ifdef XOR_BENCH
+void xor_bench(void *to, void *from, unsigned long n)
+{
+		unsigned long time;
+		u32 i;
+		u32 t;
+		 //	
+		 // functions under benchmark, use / to skip.
+         //
+		char* fn[] = {"/", "asm_memzero", "/", 
+						"/xor_memcpy", "/memcpy", 
+						"/xor_memxor", "/xor_block", NULL};
+		void* va[3];
+
+		for (n=128; n<=0x100000; n*=2) {
+
+			va[0] =  kmalloc(n, GFP_KERNEL);;
+			va[1] = kmalloc(n, GFP_KERNEL);;
+			va[2] = kmalloc(n, GFP_KERNEL);;
+
+			if (!va[1] || !va[0]) {
+				printk("%s: kmalloc failed on %luB\n", __FUNCTION__, n);
+				return;
+			}
+
+			for (t=0; fn[t]; t++) {
+				if (fn[t][0] == '/') 
+					continue;
+
+				cond_resched();
+				i = 0;
+				time = jiffies + msecs_to_jiffies(1000);
+	
+				while (jiffies <= time) {
+					switch (t) {
+						case 1: 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+								dmac_inv_range((void*)va[0], (void*)va[0] + n);
+#else
+								dma_cache_maint((void*)va[0], n, DMA_FROM_DEVICE);
+#endif
+								memzero(va[0], n); 
+						break;
+#ifdef CONFIG_MV_XOR_MEMCOPY
+						case 3: xor_memcpy(va[0], va[1], n); 
+							break;
+						case 4: asm_memcpy(va[0], va[1], n); 
+							break;
+#else
+						case 4: memcpy(va[0], va[1], n); 
+							break;
+#endif
+#ifdef CONFIG_MV_XOR_MEMXOR
+						case 5: xor_memxor(3, n ,va); 
+							break;
+#endif
+						case 6: xor_block(3, n ,va); 
+							break;
+						default:
+							printk("%s skipped\n", fn[t]);
+							time = 0;
+					}
+					
+					i++;
+				}
+
+				printk("%s: %lu8B %8luMBs %s()\n", __FUNCTION__, 
+					   n, (i * n) >> 20, fn[t]);
+
+			}
+
+			kfree(va[2]);
+			kfree(va[1]);
+			kfree(va[0]);
+		}
+}
+#endif
+
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodec.c b/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodec.c
new file mode 100755
index 0000000..293c917
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodec.c
@@ -0,0 +1,484 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvCLAudioCodec.h"
+#include "mvCLAudioCodecRegs.h"
+#include "mvSysAudioDac.h"
+
+/*******************************************************************************
+* mvCLAudioCodecInit - Initizlize the Cirrus Logic device
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+* OUTPUT:
+*		None
+* RETURN:
+*       MV_TRUE or MV_FALSE.
+*
+*******************************************************************************/
+MV_BOOL mvCLAudioCodecInit(MV_AUDIO_CODEC_DEV *pCodecDev)
+{
+	MV_U8 nData;
+
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return MV_FALSE;
+	}
+
+	/* Verify chip ID and revision */
+	nData = mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_ID_REG);
+	if ((MV_CL_AUDIO_CODEC_CHIP_ID != (nData >> 3)) || (MV_CL_AUDIO_CODEC_REV_ID != (nData & 0x7))) {
+		mvOsPrintf("%s: Error - Invalid Cirrus Logic chip/rev ID!\n", __func__);
+		return MV_FALSE;
+	}
+
+	/* Set the digital Interface format */
+	nData = mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_IF_CTRL_REG);
+	nData &= ~(0x7 << 3);
+	nData |= (pCodecDev->DACDigitalIFFormat << 3);
+	mvCLAudioCodecRegSet(pCodecDev, CL_AUDIO_CODEC_IF_CTRL_REG, nData);
+
+	/* Set the ADC Mode */
+	if (MV_LEFT_JUSTIFIED_MODE == pCodecDev->ADCMode)
+		mvCLAudioCodecRegBitsReset(pCodecDev, CL_AUDIO_CODEC_IF_CTRL_REG, BIT2);
+	else
+		mvCLAudioCodecRegBitsSet(pCodecDev, CL_AUDIO_CODEC_IF_CTRL_REG, BIT2);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvCLAudioCodecOutputVolumeSet - Set the Cirrus Logic output volume of OUTA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       nVolume  : Volume level.
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecOutputVolumeSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nVolume)
+{
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+	mvCLAudioCodecRegSet(pCodecDev, CL_AUDIO_CODEC_VOL_OUTA_CTRL_REG, nVolume);
+}
+
+/*******************************************************************************
+* mvCLAudioCodecOutputVolumeGet - Get the Cirrus Logic output volume of OUTA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+* OUTPUT:
+*       None
+* RETURN:
+*		Volume level.
+*
+*******************************************************************************/
+MV_U8 mvCLAudioCodecOutputVolumeGet(MV_AUDIO_CODEC_DEV *pCodecDev)
+{
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return 0;
+	}
+	return mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_VOL_OUTA_CTRL_REG);
+}
+
+/*******************************************************************************
+* mvCLAudioCodecOutputVolumeMute - Mute the Cirrus Logic output volume of OUTA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       bMute    : MV_TRUE for mute, MV_FALSE to un-mute
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecOutputVolumeMute(MV_AUDIO_CODEC_DEV *pCodecDev, MV_BOOL bMute)
+{
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+	if (MV_TRUE == bMute)
+		mvCLAudioCodecRegBitsSet(pCodecDev, CL_AUDIO_CODEC_DAC_OUTPUT_CTRL_REG, BIT0);
+	else
+		mvCLAudioCodecRegBitsReset(pCodecDev, CL_AUDIO_CODEC_DAC_OUTPUT_CTRL_REG, BIT0);
+}
+
+/*******************************************************************************
+* mvCLAudioCodecInputVolumeSet - Set the Cirrus Logic input volume of INA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       nVolume  : Volume level.
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecInputVolumeSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nVolume)
+{
+	MV_U8 nData;
+
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+	nData = mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_PGAA_VOL_CTRL_REG);
+	nData &= ~0x1f;
+	nData |= (0x1f & nVolume);
+	mvCLAudioCodecRegSet(pCodecDev, CL_AUDIO_CODEC_PGAA_VOL_CTRL_REG, nData);
+}
+
+/*******************************************************************************
+* mvCLAudioCodecInputVolumeGet - Get the Cirrus Logic input volume of INA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+* OUTPUT:
+*		None
+* RETURN:
+*       Volume level.
+*
+*******************************************************************************/
+MV_U8 mvCLAudioCodecInputVolumeGet(MV_AUDIO_CODEC_DEV *pCodecDev)
+{
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return 0;
+	}
+	return mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_PGAA_VOL_CTRL_REG) & 0x1f;
+}
+
+/*******************************************************************************
+* mvCLAudioCodecInputVolumeMute - Mute the Cirrus Logic input volume of INA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       bMute    : MV_TRUE for mute, MV_FALSE to un-mute
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecInputVolumeMute(MV_AUDIO_CODEC_DEV *pCodecDev, MV_BOOL bMute)
+{
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+	if (MV_TRUE == bMute)
+		mvCLAudioCodecRegBitsSet(pCodecDev, CL_AUDIO_CODEC_ADC_INPUT_INV_MUTE_REG, BIT0);
+	else
+		mvCLAudioCodecRegBitsReset(pCodecDev, CL_AUDIO_CODEC_ADC_INPUT_INV_MUTE_REG, BIT0);
+}
+
+/*******************************************************************************
+* mvCLAudioCodecTrebleSet - Set the Cirrus Logic output treble of INA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       nTreble  : treble value.
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecTrebleSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nTreble)
+{
+	MV_U8 nData;
+
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+	nData = mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_TONE_CTRL_REG);
+	nData &= 0xF;
+	nData |= (nTreble << 4);
+	mvCLAudioCodecRegSet(pCodecDev, CL_AUDIO_CODEC_TONE_CTRL_REG, nData);
+}
+
+/*******************************************************************************
+* mvCLAudioCodecTrebleGet - Get the Cirrus Logic output treble of INA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+* OUTPUT:
+*		None
+* RETURN:
+*       treble value
+*
+*******************************************************************************/
+MV_U8 mvCLAudioCodecTrebleGet(MV_AUDIO_CODEC_DEV *pCodecDev)
+{
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return 0;
+	}
+	return mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_TONE_CTRL_REG) >> 4;
+}
+
+/*******************************************************************************
+* mvCLAudioCodecBassSet - Set the Cirrus Logic output bass of INA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       nBass    : Bass level.
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecBassSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nBass)
+{
+	MV_U8 nData;
+
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+	nData = mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_TONE_CTRL_REG);
+	nData &= 0xf0;
+	nData |= nBass;
+	mvCLAudioCodecRegSet(pCodecDev, CL_AUDIO_CODEC_TONE_CTRL_REG, nData);
+}
+
+/*******************************************************************************
+* mvCLAudioCodecBassGet - Get the Cirrus Logic output bass of INA
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+* OUTPUT:
+*		None
+* RETURN:
+*       Bass level
+*
+*******************************************************************************/
+MV_U8 mvCLAudioCodecBassGet(MV_AUDIO_CODEC_DEV *pCodecDev)
+{
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return 0;
+	}
+	return mvCLAudioCodecRegGet(pCodecDev, CL_AUDIO_CODEC_TONE_CTRL_REG) & 0xF;
+}
+
+/*******************************************************************************
+* mvCLAudioCodecRegSet - Set Cirrus Logic register value
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       nOffset  : register offset
+*       nData    : register data
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecRegSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nData)
+{
+	MV_U32 offset, data;
+
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+
+	offset = nOffset;
+	data = nData;
+	if (mvSysAudioCodecRegWrite(pCodecDev->codecHandle, offset, data) != MV_OK) {
+		mvOsPrintf("%s: Error while writing register!\n", __func__);
+		return;
+	}
+
+}
+
+/*******************************************************************************
+* mvCLAudioCodecRegGet - Set Cirrus Logic register value
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       nOffset  : register offset
+* OUTPUT:
+*		None
+* RETURN:
+*       register data
+*
+*******************************************************************************/
+MV_U8 mvCLAudioCodecRegGet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset)
+{
+	MV_U32 offset, data;
+
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return 0;
+	}
+
+	offset = nOffset;
+	if (mvSysAudioCodecRegRead(pCodecDev->codecHandle, offset, &data) != MV_OK) {
+		mvOsPrintf("%s: Error while reading register!\n", __func__);
+		return 0;
+	}
+
+	return (MV_U8) data;
+}
+
+/*******************************************************************************
+* mvCLAudioCodecRegBitsSet - Set Cirrus Logic register bits value
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       nOffset  : register offset
+*       nBits    : register bits
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecRegBitsSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nBits)
+{
+	MV_U8 nData;
+
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+
+	nData = mvCLAudioCodecRegGet(pCodecDev, nOffset);
+	nData |= nBits;
+	mvCLAudioCodecRegSet(pCodecDev, nOffset, nData);
+
+}
+
+/*******************************************************************************
+* mvCLAudioCodecRegGet - Reset Cirrus Logic register bits value
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure.
+*       nOffset  : register offset
+*       nBits    : register bits
+* OUTPUT:
+*		None
+* RETURN:
+*       register data
+*
+*******************************************************************************/
+MV_VOID mvCLAudioCodecRegBitsReset(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nBits)
+{
+	MV_U8 nData;
+
+	if (NULL == pCodecDev) {
+		mvOsPrintf("%s: Error - pCodecDev = NULL!\n", __func__);
+		return;
+	}
+
+	nData = mvCLAudioCodecRegGet(pCodecDev, nOffset);
+	nData &= ~nBits;
+	mvCLAudioCodecRegSet(pCodecDev, nOffset, nData);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodec.h b/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodec.h
new file mode 100755
index 0000000..ef4e151
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodec.h
@@ -0,0 +1,135 @@
+
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCLAudioCodech
+#define __INCmvCLAudioCodech
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define  MV_CL_AUDIO_CODEC_CHIP_ID   0x1B
+#define  MV_CL_AUDIO_CODEC_REV_ID    0x1
+
+/* Selects the digital interface format used for the data in on SDIN. */
+	typedef enum _mvDACDigitalIFFormat {
+		MV_L_JUSTIFIED_UP_TO_24_BIT,
+		MV_I2S_UP_TO_24_BIT,
+		MV_R_JUSTIFIED_UP_TO_24_BIT,
+		MV_R_JUSTIFIED_20_BIT,
+		MV_R_JUSTIFIED_18_BIT,
+		MV_R_JUSTIFIED_16_BIT
+	} MV_DAC_DIGITAL_IF_FORMAT;
+
+/* Selects either the I2S or Left-Justified digital interface format for the
+   data on SDOUT. */
+	typedef enum _mvADCMode {
+		MV_LEFT_JUSTIFIED_MODE,
+		MV_I2S_MODE
+	} MV_ADC_MODE;
+
+/* Cirrus Logic device structure */
+	typedef struct _mvAudioCodecDev {
+		/* MUST be set by user!!!   */
+		MV_VOID *codecHandle;
+		MV_U8 chanNum;
+		MV_DAC_DIGITAL_IF_FORMAT DACDigitalIFFormat;
+		MV_ADC_MODE ADCMode;
+
+		/* Set by driver */
+		MV_U8 nChipID;
+		MV_U8 nRevID;
+
+	} MV_AUDIO_CODEC_DEV;
+
+/* Initialize the Cirrus Logic device */
+	MV_BOOL mvCLAudioCodecInit(MV_AUDIO_CODEC_DEV *pCodecDev);
+
+/* Function to control output volume (playback) */
+	MV_VOID mvCLAudioCodecOutputVolumeSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nVolume);
+	MV_U8 mvCLAudioCodecOutputVolumeGet(MV_AUDIO_CODEC_DEV *pCodecDev);
+	MV_VOID mvCLAudioCodecOutputVolumeMute(MV_AUDIO_CODEC_DEV *pCodecDev, MV_BOOL bMute);
+
+/* Function to control input volume (record) */
+	MV_VOID mvCLAudioCodecInputVolumeSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nVolume);
+	MV_U8 mvCLAudioCodecInputVolumeGet(MV_AUDIO_CODEC_DEV *pCodecDev);
+	MV_VOID mvCLAudioCodecInputVolumeMute(MV_AUDIO_CODEC_DEV *pCodecDev, MV_BOOL bMute);
+
+/* Function to control output tone */
+	MV_VOID mvCLAudioCodecTrebleSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nTreble);
+	MV_U8 mvCLAudioCodecTrebleGet(MV_AUDIO_CODEC_DEV *pCodecDev);
+	MV_VOID mvCLAudioCodecBassSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nBass);
+	MV_U8 mvCLAudioCodecBassGet(MV_AUDIO_CODEC_DEV *pCodecDev);
+
+/* Function to access the Cirrus Logic CODEC registers */
+	MV_VOID mvCLAudioCodecRegSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nData);
+	MV_U8 mvCLAudioCodecRegGet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset);
+	MV_VOID mvCLAudioCodecRegBitsSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nBits);
+	MV_VOID mvCLAudioCodecRegBitsReset(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nBits);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __INCmvCLAudioCodech */
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodecRegs.h b/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodecRegs.h
new file mode 100755
index 0000000..0f9d8a9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/dac/mvCLAudioCodecRegs.h
@@ -0,0 +1,85 @@
+
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCLAudioCodecRegsh
+#define __INCmvCLAudioCodecRegsh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define   CL_AUDIO_CODEC_ID_REG                    0x1
+#define   CL_AUDIO_CODEC_IF_CTRL_REG               0x4
+#define   CL_AUDIO_CODEC_ADC_INPUT_INV_MUTE_REG    0x7
+#define   CL_AUDIO_CODEC_DAC_OUTPUT_CTRL_REG       0x8
+#define   CL_AUDIO_CODEC_DAC_CTRL_REG              0x9
+#define   CL_AUDIO_CODEC_PGAA_VOL_CTRL_REG         0xa
+#define   CL_AUDIO_CODEC_TONE_CTRL_REG             0x15
+#define   CL_AUDIO_CODEC_VOL_OUTA_CTRL_REG         0x16
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __INCmvCLAudioCodecRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/dac/mvSysAudioDac.h b/arch/arm/plat-feroceon/mv_hal/audio/dac/mvSysAudioDac.h
new file mode 100755
index 0000000..bbfe19b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/dac/mvSysAudioDac.h
@@ -0,0 +1,118 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_SYS_AUDIO_DAC_H__
+#define __MV_SYS_AUDIO_DAC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+* mvSysAudioCodecRegRead
+*
+* DESCRIPTION:
+*	System interface for reading an Audio codec register.
+*
+* INPUT:
+*       codecHandle: Handle passed by OS glue by which an audio codec is
+*		     identified.
+*       regOffset:   Offset of codec register to be read.
+*
+* OUTPUT:
+*       regData:     Register data
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+	MV_STATUS mvSysAudioCodecRegRead(MV_VOID *codecHandle, MV_U32 regOffset, MV_U32 *regData);
+
+/*******************************************************************************
+* mvSysAudioCodecRegWrite
+*
+* DESCRIPTION:
+*	System interface for writing an Audio codec register.
+*
+* INPUT:
+*       codecHandle: Handle passed by OS glue by which an audio codec is
+*		     identified.
+*       regOffset:   Offset of codec register to be written.
+*       regData:     Register data to write.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+	MV_STATUS mvSysAudioCodecRegWrite(MV_VOID *codecHandle, MV_U32 regOffset, MV_U32 regData);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/mvAudio.c b/arch/arm/plat-feroceon/mv_hal/audio/mvAudio.c
new file mode 100755
index 0000000..acdc9a9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/mvAudio.c
@@ -0,0 +1,944 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysAudioConfig.h"
+#include "mvAudioRegs.h"
+#include "mvAudio.h"
+
+/* #define MV_AUDIO_SKIP_WIN_DECODING */
+
+static MV_U32 audioBurstBytesNumGet(MV_AUDIO_BURST_SIZE burst);
+
+static MV_AUDIO_HAL_DATA audioHalData[MV_AUDIO_MAX_UNITS];
+#ifndef MV_AUDIO_SKIP_WIN_DECODING
+static MV_UNIT_WIN_INFO audioAddrDecWinMap[MAX_TARGETS + 1];
+static MV_STATUS mvAudioReplaceAddrWin(MV_U32 unit, MV_U32 winId, MV_U32 buffPhysAddr, MV_U32 buffSize);
+#endif
+
+/*******************************************************************************
+* mvAudioHalInit - Initialize the Audio subsystem
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvAudioHalInit(MV_U8 unit, MV_AUDIO_HAL_DATA *halData)
+{
+	int timeout;
+
+	MV_REG_BIT_RESET(MV_AUDIO_PLL_CTRL1_REG(unit), 0x333FF8);
+	MV_REG_BIT_SET(MV_AUDIO_PLL_CTRL1_REG(unit), 0x111D18);
+
+	/*MV_REG_BIT_RESET(0x10074,0xC018000);
+	   MV_REG_BIT_SET(0x10074,0x4008000); */
+
+	timeout = 10000000;
+	while (timeout--)
+		continue;
+
+	MV_REG_BIT_RESET(MV_AUDIO_PLL_CTRL1_REG(unit), 0x333FF8);
+	MV_REG_BIT_SET(MV_AUDIO_PLL_CTRL1_REG(unit), 0x111D18);
+
+	mvOsMemcpy(&audioHalData[unit], halData, sizeof(MV_AUDIO_HAL_DATA));
+	/*MV_REG_BIT_RESET(0x10074,0xC018000);
+	   MV_REG_BIT_SET(0x10074,0x4008000); */
+
+}
+
+/* Clocks Control and Status related*/
+/*******************************************************************************
+* mvAudioDCOCtrlSet - Set DCO control register
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       dcoCtrl: pointer to MV_AUDIO_FREQ_DATA structure
+* OUTPUT:
+*		None
+* RETURN:
+*       None
+*
+*******************************************************************************/
+
+MV_STATUS mvAudioDCOCtrlSet(int unit, MV_AUDIO_FREQ_DATA *dcoCtrl)
+{
+	MV_U32 reg;
+	/* Check parameters */
+	if (dcoCtrl->baseFreq > AUDIO_FREQ_96KH) {
+		mvOsPrintf("mvAudioDCOCtrlSet: dcoCtrl->baseFreq value (0x%x) invalid\n", dcoCtrl->baseFreq);
+		return MV_BAD_PARAM;
+
+	}
+	if ((dcoCtrl->offset > 0xFD0) || (dcoCtrl->offset < 0x20)) {
+		mvOsPrintf("mvAudioDCOCtrlSet: dcoCtrl->offset value (0x%x) invalid\n", dcoCtrl->baseFreq);
+		return MV_BAD_PARAM;
+	}
+	reg = MV_REG_READ(MV_AUDIO_DCO_CTRL_REG(unit));
+
+	reg &= ~(ADCR_DCO_CTRL_FS_MASK | ADCR_DCO_CTRL_OFFSET_MASK);
+	reg |= ((dcoCtrl->baseFreq << ADCR_DCO_CTRL_FS_OFFS) | (dcoCtrl->offset << ADCR_DCO_CTRL_OFFSET_OFFS));
+	MV_REG_WRITE(MV_AUDIO_DCO_CTRL_REG(unit), reg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAudioDCOCtrlGet - Set DCO control register
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       dcoCtrl: pointer to MV_AUDIO_FREQ_DATA structure
+* OUTPUT:
+*		dcoCtrl: pointer to MV_AUDIO_FREQ_DATA structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+
+MV_VOID mvAudioDCOCtrlGet(int unit, MV_AUDIO_FREQ_DATA *dcoCtrl)
+{
+	MV_U32 reg = MV_REG_READ(MV_AUDIO_DCO_CTRL_REG(unit));
+
+	dcoCtrl->baseFreq = (reg & ADCR_DCO_CTRL_FS_MASK) >> ADCR_DCO_CTRL_FS_OFFS;
+	dcoCtrl->offset = (reg & ADCR_DCO_CTRL_OFFSET_MASK) >> ADCR_DCO_CTRL_OFFSET_OFFS;
+}
+
+/*******************************************************************************
+* mvAudioSpcrCtrlGet - Set SPCR control register
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       spcrCtrl: pointer to MV_AUDIO_FREQ_DATA structure
+* OUTPUT:
+*		spcrCtrl: pointer to MV_AUDIO_FREQ_DATA structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+
+MV_VOID mvAudioSpcrCtrlGet(int unit, MV_AUDIO_FREQ_DATA *spcrCtrl)
+{
+	MV_U32 reg = MV_REG_READ(MV_AUDIO_SPCR_DCO_STATUS_REG(unit));
+
+	spcrCtrl->baseFreq = (reg & ASDSR_SPCR_CTRLFS_MASK) >> ASDSR_SPCR_CTRLFS_OFFS;
+	spcrCtrl->offset = (reg & ASDSR_SPCR_CTRLOFFSET_MASK) >> ASDSR_SPCR_CTRLOFFSET_OFFS;
+}
+
+/* Audio PlayBack related*/
+/*******************************************************************************
+* mvAudioPlaybackControlSet - Set Playback general parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_AUDIO_PLAYBACK_CTRL structure
+* OUTPUT:
+*		None
+* RETURN:
+*       MV_OK on success , MV_FAIL on fail
+*
+*******************************************************************************/
+MV_STATUS mvAudioPlaybackControlSet(int unit, MV_AUDIO_PLAYBACK_CTRL *ctrl)
+{
+	MV_U32 reg;
+
+	if (ctrl->monoMode >= AUDIO_PLAY_OTHER_MONO) {
+		mvOsPrintf("mvAudioPlaybackControlSet: Error ,illegal monoMode %x\n", ctrl->monoMode);
+
+		return MV_FAIL;
+
+	}
+
+	if ((ctrl->burst != AUDIO_32BYTE_BURST) && (ctrl->burst != AUDIO_128BYTE_BURST)) {
+		mvOsPrintf("mvAudioPlaybackControlSet: Error ,illegal burst %x\n", ctrl->burst);
+
+		return MV_FAIL;
+
+	}
+
+	if (ctrl->bufferPhyBase & (MV_AUDIO_BUFFER_MIN_ALIGN - 1)) {
+		mvOsPrintf("mvAudioPlaybackControlSet: Error ,bufferPhyBase is not"
+			   "\n aligned to 0x%x bytes\n", MV_AUDIO_BUFFER_MIN_ALIGN);
+
+		return MV_FAIL;
+	}
+
+	if ((ctrl->bufferSize <= audioBurstBytesNumGet(ctrl->burst)) ||
+	    (ctrl->bufferSize & (audioBurstBytesNumGet(ctrl->burst) - 1)) ||
+	    (ctrl->bufferSize > AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX))
+	    ) {
+		mvOsPrintf("mvAudioPlaybackControlSet: Error, bufferSize smaller"
+			   "\nthan or not multiple of 0x%x bytes or larger than"
+			   "\n 0x%x", audioBurstBytesNumGet(ctrl->burst), AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
+
+		return MV_FAIL;
+	}
+
+	reg = MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG(unit));
+	reg &= ~(APCR_PLAY_BURST_SIZE_MASK | APCR_LOOPBACK_MASK | APCR_PLAY_MONO_MASK | APCR_PLAY_SAMPLE_SIZE_MASK);
+	reg |= ctrl->burst << APCR_PLAY_BURST_SIZE_OFFS;
+	reg |= ctrl->loopBack << APCR_LOOPBACK_OFFS;
+	reg |= ctrl->monoMode << APCR_PLAY_MONO_OFFS;
+	reg |= ctrl->sampleSize << APCR_PLAY_SAMPLE_SIZE_OFFS;
+	MV_REG_WRITE(MV_AUDIO_PLAYBACK_CTRL_REG(unit), reg);
+
+#ifndef MV_AUDIO_SKIP_WIN_DECODING
+	if (mvAudioReplaceAddrWin(unit, MV_AUDIO_PLAYBACK_WIN_NUM, ctrl->bufferPhyBase, ctrl->bufferSize) != MV_OK) {
+		mvOsPrintf("mvAudioRecordControlSet: Failed to replace address decoding window.\n");
+		return MV_FAIL;
+	}
+#endif
+
+	/* Set the interrupt byte count.                            */
+	reg = ctrl->intByteCount & APBCI_BYTE_COUNT_MASK;
+	MV_REG_WRITE(MV_AUDIO_PLAYBACK_BYTE_CNTR_INT_REG(unit), reg);
+
+	MV_REG_WRITE(MV_AUDIO_PLAYBACK_BUFF_START_REG(unit), ctrl->bufferPhyBase);
+	MV_REG_WRITE(MV_AUDIO_PLAYBACK_BUFF_SIZE_REG(unit), AUDIO_SIZE_TO_REG(ctrl->bufferSize));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAudioPlaybackControlGet - Get Playback general parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_AUDIO_PLAYBACK_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_AUDIO_PLAYBACK_CTRL structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvAudioPlaybackControlGet(int unit, MV_AUDIO_PLAYBACK_CTRL *ctrl)
+{
+	MV_U32 reg = MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG(unit));
+
+	ctrl->burst = (reg & APCR_PLAY_BURST_SIZE_MASK) >> APCR_PLAY_BURST_SIZE_OFFS;
+	ctrl->loopBack = (reg & APCR_LOOPBACK_MASK) >> APCR_LOOPBACK_OFFS;
+	ctrl->monoMode = (reg & APCR_PLAY_MONO_MASK) >> APCR_PLAY_MONO_OFFS;
+
+	ctrl->bufferPhyBase = MV_REG_READ(MV_AUDIO_PLAYBACK_BUFF_START_REG(unit));
+	reg = MV_REG_READ(MV_AUDIO_PLAYBACK_BUFF_SIZE_REG(unit));
+	ctrl->bufferSize = AUDIO_REG_TO_SIZE(reg);
+
+	ctrl->intByteCount = MV_REG_READ(MV_AUDIO_PLAYBACK_BYTE_CNTR_INT_REG(unit));
+}
+
+/*******************************************************************************
+* mvAudioPlaybackStatusGet - Get Playback status parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_AUDIO_PLAYBACK_STATUS structure
+* OUTPUT:
+*		ctrl: pointer to MV_AUDIO_PLAYBACK_STATUS structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvAudioPlaybackStatusGet(int unit, MV_AUDIO_PLAYBACK_STATUS *status)
+{
+	status->muteI2S = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG(unit)) & APCR_PLAY_I2S_MUTE_MASK) ?
+			   MV_TRUE : MV_FALSE);
+	status->enableI2S = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG(unit)) & APCR_PLAY_I2S_ENABLE_MASK) ?
+			     MV_TRUE : MV_FALSE);
+	status->muteSPDIF = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG(unit)) & APCR_PLAY_SPDIF_MUTE_MASK) ?
+			     MV_TRUE : MV_FALSE);
+	status->enableSPDIF = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG(unit)) & APCR_PLAY_SPDIF_ENABLE_MASK) ?
+			       MV_TRUE : MV_FALSE);
+	status->pause = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG(unit)) & APCR_PLAY_PAUSE_MASK) ? MV_TRUE : MV_FALSE);
+
+}
+
+/*******************************************************************************
+* mvSPDIFPlaybackCtrlGet - Set SPDIF Playback control parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_SPDIF_PLAYBACK_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_SPDIF_PLAYBACK_CTRL structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+/* Audio SPDIF PlayBack related*/
+MV_VOID mvSPDIFPlaybackCtrlSet(int unit, MV_SPDIF_PLAYBACK_CTRL *ctrl)
+{
+	if (ctrl->blockStartInternally)
+		MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_BLOCK_START_MASK);
+	else
+		MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_BLOCK_START_MASK);
+
+	if (ctrl->validityFromMemory)
+		MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK);
+	else
+		MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK);
+
+	if (ctrl->userBitsFromMemory)
+		MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_PB_MEM_USR_EN_MASK);
+	else
+		MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_PB_MEM_USR_EN_MASK);
+
+	if (ctrl->underrunData)
+		MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_UNDERRUN_DATA_MASK);
+	else
+		MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_UNDERRUN_DATA_MASK);
+
+	if (ctrl->validity)
+		MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_PB_REG_VALIDITY_MASK);
+	else
+		MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_PB_REG_VALIDITY_MASK);
+
+	if (ctrl->nonPcm)
+		MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_PB_NONPCM_MASK);
+	else
+		MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit), ASPCR_SPDIF_PB_NONPCM_MASK);
+}
+
+/*******************************************************************************
+* mvSPDIFPlaybackCtrlGet - Get SPDIF Playback control parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_SPDIF_PLAYBACK_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_SPDIF_PLAYBACK_CTRL structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvSPDIFPlaybackCtrlGet(int unit, MV_SPDIF_PLAYBACK_CTRL *ctrl)
+{
+	ctrl->blockStartInternally =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit)) & ASPCR_SPDIF_BLOCK_START_MASK) ? MV_TRUE : MV_FALSE);
+	ctrl->nonPcm =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit)) & ASPCR_SPDIF_PB_NONPCM_MASK) ? MV_TRUE : MV_FALSE);
+	ctrl->underrunData =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit)) & ASPCR_SPDIF_UNDERRUN_DATA_MASK) ? MV_TRUE : MV_FALSE);
+	ctrl->userBitsFromMemory =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit)) & ASPCR_SPDIF_PB_MEM_USR_EN_MASK) ? MV_TRUE : MV_FALSE);
+	ctrl->validity =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit)) & ASPCR_SPDIF_PB_REG_VALIDITY_MASK) ? MV_TRUE : MV_FALSE);
+	ctrl->validityFromMemory =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit)) & ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK) ?
+	     MV_TRUE : MV_FALSE);
+
+}
+
+/*******************************************************************************
+* mvI2SPlaybackCtrlSet - Set I2S Playback control parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_I2S_PLAYBACK_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_I2S_PLAYBACK_CTRL structure
+* RETURN:
+*       MV_OK on success, and MV_FAIL on fail.
+*
+*******************************************************************************/
+
+/* Audio I2S PlayBack related*/
+MV_STATUS mvI2SPlaybackCtrlSet(int unit, MV_I2S_PLAYBACK_CTRL *ctrl)
+{
+	MV_U32 reg = MV_REG_READ(MV_AUDIO_I2S_PLAY_CTRL_REG(unit)) &
+	    ~(AIPCR_I2S_PB_JUSTF_MASK | AIPCR_I2S_PB_SAMPLE_SIZE_MASK);
+
+	if (ctrl->sampleSize > SAMPLE_16BIT) {
+		mvOsPrintf("mvI2SPlaybackCtrlSet: illigal sample size\n");
+		return MV_FAIL;
+	}
+
+	reg |= ctrl->sampleSize << AIPCR_I2S_PB_SAMPLE_SIZE_OFFS;
+
+	if (ctrl->sendLastFrame)
+		MV_REG_BIT_SET(MV_AUDIO_I2S_PLAY_CTRL_REG(unit), AIPCR_I2S_SEND_LAST_FRM_MASK);
+	else
+		MV_REG_BIT_RESET(MV_AUDIO_I2S_PLAY_CTRL_REG(unit), AIPCR_I2S_SEND_LAST_FRM_MASK);
+
+	switch (ctrl->justification) {
+	case I2S_JUSTIFIED:
+	case LEFT_JUSTIFIED:
+	case RIGHT_JUSTIFIED:
+		reg |= ctrl->justification << AIPCR_I2S_PB_JUSTF_OFFS;
+		break;
+	default:
+		mvOsPrintf("mvI2SPlaybackCtrlSet: illigal Justification value\n");
+		return MV_FAIL;
+
+	}
+
+	MV_REG_WRITE(MV_AUDIO_I2S_PLAY_CTRL_REG(unit), reg);
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvI2SPlaybackCtrlGet - Get I2S Playback control parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_I2S_PLAYBACK_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_I2S_PLAYBACK_CTRL structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvI2SPlaybackCtrlGet(int unit, MV_I2S_PLAYBACK_CTRL *ctrl)
+{
+	ctrl->sendLastFrame =
+	    ((MV_REG_READ(MV_AUDIO_I2S_PLAY_CTRL_REG(unit)) & AIPCR_I2S_SEND_LAST_FRM_MASK) ? MV_TRUE : MV_FALSE);
+
+	ctrl->justification =
+	    ((MV_REG_READ(MV_AUDIO_I2S_PLAY_CTRL_REG(unit)) & AIPCR_I2S_PB_JUSTF_MASK) >> AIPCR_I2S_PB_JUSTF_OFFS);
+
+	ctrl->sampleSize =
+	    ((MV_REG_READ(MV_AUDIO_I2S_PLAY_CTRL_REG(unit)) & AIPCR_I2S_PB_SAMPLE_SIZE_MASK) >>
+	     AIPCR_I2S_PB_SAMPLE_SIZE_OFFS);
+
+}
+
+/*******************************************************************************
+* mvAudioRecordControlGet - Get Recording control parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_AUDIO_RECORD_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_AUDIO_RECORD_CTRL structure
+* RETURN:
+*       MV_OK on success , MV_FAIL on fail.
+*
+*******************************************************************************/
+/* Audio Recording*/
+MV_STATUS mvAudioRecordControlSet(int unit, MV_AUDIO_RECORD_CTRL *ctrl)
+{
+	MV_U32 reg;
+
+	if (ctrl->monoChannel > AUDIO_REC_RIGHT_MONO) {
+		mvOsPrintf("mvAudioRecordControlSet: Error ,illegal monoChannel %x\n", ctrl->monoChannel);
+
+		return MV_FAIL;
+	}
+
+	if ((ctrl->burst != AUDIO_32BYTE_BURST) && (ctrl->burst != AUDIO_128BYTE_BURST)) {
+		mvOsPrintf("mvAudioRecordControlSet: Error ,illegal burst %x\n", ctrl->burst);
+
+		return MV_FAIL;
+
+	}
+
+	if (ctrl->bufferPhyBase & (MV_AUDIO_BUFFER_MIN_ALIGN - 1)) {
+		mvOsPrintf("mvAudioRecordControlSet: Error ,bufferPhyBase is not"
+			   "\n aligned to 0x%x bytes\n", MV_AUDIO_BUFFER_MIN_ALIGN);
+
+		return MV_FAIL;
+	}
+
+	if ((ctrl->bufferSize <= audioBurstBytesNumGet(ctrl->burst)) ||
+	    (ctrl->bufferSize & (audioBurstBytesNumGet(ctrl->burst) - 1)) ||
+	    (ctrl->bufferSize > AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX))
+	    ) {
+		mvOsPrintf("mvAudioRecordControlSet: Error, bufferSize smaller"
+			   "\nthan or not multiple of 0x%x bytes or larger than"
+			   "\n 0x%x", audioBurstBytesNumGet(ctrl->burst), AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
+
+		return MV_FAIL;
+	}
+
+	reg = MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit));
+	reg &= ~(ARCR_RECORD_BURST_SIZE_MASK | ARCR_RECORDED_MONO_CHNL_MASK | ARCR_RECORD_SAMPLE_SIZE_MASK);
+	switch (ctrl->sampleSize) {
+	case SAMPLE_16BIT:
+	case SAMPLE_16BIT_NON_COMPACT:
+	case SAMPLE_20BIT:
+	case SAMPLE_24BIT:
+	case SAMPLE_32BIT:
+		reg |= ctrl->sampleSize << ARCR_RECORD_SAMPLE_SIZE_OFFS;
+		break;
+	default:
+		mvOsPrintf("mvAudioRecordControlSet: Error ,illegal sampleSize %x\n", ctrl->sampleSize);
+
+		return MV_FAIL;
+	}
+
+	reg |= ctrl->burst << ARCR_RECORD_BURST_SIZE_OFFS;
+	reg |= ctrl->monoChannel << ARCR_RECORDED_MONO_CHNL_OFFS;
+	MV_REG_WRITE(MV_AUDIO_RECORD_CTRL_REG(unit), reg);
+
+	if (ctrl->mono)
+		MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG(unit), ARCR_RECORD_MONO_MASK);
+	else
+		MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG(unit), ARCR_RECORD_MONO_MASK);
+
+#ifndef MV_AUDIO_SKIP_WIN_DECODING
+	if (mvAudioReplaceAddrWin(unit, MV_AUDIO_RECORD_WIN_NUM, ctrl->bufferPhyBase, ctrl->bufferSize) != MV_OK) {
+		mvOsPrintf("mvAudioRecordControlSet: Failed to replace address decoding window.\n");
+		return MV_FAIL;
+	}
+#endif
+
+	/* Set the interrupt byte count.                            */
+	reg = ctrl->intByteCount & ARBCI_BYTE_COUNT_MASK;
+	MV_REG_WRITE(MV_AUDIO_RECORD_BYTE_CNTR_INT_REG(unit), reg);
+
+	MV_REG_WRITE(MV_AUDIO_RECORD_START_ADDR_REG(unit), ctrl->bufferPhyBase);
+	MV_REG_WRITE(MV_AUDIO_RECORD_BUFF_SIZE_REG(unit), AUDIO_SIZE_TO_REG(ctrl->bufferSize));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAudioRecordControlGet - Get Recording control parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_AUDIO_RECORD_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_AUDIO_RECORD_CTRL structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvAudioRecordControlGet(int unit, MV_AUDIO_RECORD_CTRL *ctrl)
+{
+	MV_U32 reg;
+
+	ctrl->mono = ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit)) & ARCR_RECORD_MONO_MASK) ? MV_TRUE : MV_FALSE);
+
+	ctrl->burst =
+	    ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit)) & ARCR_RECORD_BURST_SIZE_MASK) >>
+	     ARCR_RECORD_BURST_SIZE_OFFS);
+
+	ctrl->monoChannel =
+	    ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit)) & ARCR_RECORDED_MONO_CHNL_MASK) >>
+	     ARCR_RECORDED_MONO_CHNL_OFFS);
+
+	ctrl->sampleSize =
+	    ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit)) & ARCR_RECORD_SAMPLE_SIZE_MASK) >>
+	     ARCR_RECORD_SAMPLE_SIZE_OFFS);
+
+	ctrl->bufferPhyBase = MV_REG_READ(MV_AUDIO_RECORD_START_ADDR_REG(unit));
+	reg = MV_REG_READ(MV_AUDIO_RECORD_BUFF_SIZE_REG(unit));
+	ctrl->bufferSize = AUDIO_REG_TO_SIZE(reg);
+
+	ctrl->intByteCount = MV_REG_READ(MV_AUDIO_RECORD_BYTE_CNTR_INT_REG(unit));
+
+}
+
+/*******************************************************************************
+* mvAudioRecordControlGet - Get Recording status parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       status: pointer to MV_AUDIO_RECORD_STATUS structure
+* OUTPUT:
+*		status: pointer to MV_AUDIO_RECORD_STATUS structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvAudioRecordStatusGet(int unit, MV_AUDIO_RECORD_STATUS *status)
+{
+	status->I2SEnable =
+	    ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit)) & ARCR_RECORD_I2S_EN_MASK) ? MV_TRUE : MV_FALSE);
+
+	status->mute = ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit)) & ARCR_RECORD_MUTE_MASK) ? MV_TRUE : MV_FALSE);
+
+	status->pause = ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit)) & ARCR_RECORD_PAUSE_MASK) ? MV_TRUE : MV_FALSE);
+
+	status->spdifEnable =
+	    ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG(unit)) & ARCR_RECORD_SPDIF_EN_MASK) ? MV_TRUE : MV_FALSE);
+
+}
+
+/*******************************************************************************
+* mvSPDIFRecordTclockSet - Set T-clock for SPDIF
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       none
+* OUTPUT:
+*		none
+* RETURN:
+*       MV_OK on success , MV_NOT_SUPPORTED on non supported T-clock
+*
+*******************************************************************************/
+
+/* SPDIF Recording Related*/
+MV_STATUS mvSPDIFRecordTclockSet(int unit)
+{
+	MV_U32 tclock = audioHalData[unit].tclk;
+	MV_U32 reg = MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG(unit));
+
+	reg &= ~ASRGR_CORE_CLK_FREQ_MASK;
+	switch (tclock) {
+	case MV_BOARD_TCLK_133MHZ:
+		reg |= ASRGR_CORE_CLK_FREQ_133MHZ;
+		break;
+	case MV_BOARD_TCLK_150MHZ:
+		reg |= ASRGR_CORE_CLK_FREQ_150MHZ;
+		break;
+	case MV_BOARD_TCLK_166MHZ:
+		reg |= ASRGR_CORE_CLK_FREQ_166MHZ;
+		break;
+	case MV_BOARD_TCLK_200MHZ:
+		reg |= ASRGR_CORE_CLK_FREQ_200MHZ;
+		break;
+	default:
+		mvOsPrintf("mvSPDIFRecordTclockSet: Not supported core clock %d\n", tclock);
+		return MV_NOT_SUPPORTED;
+	}
+
+	MV_REG_WRITE(MV_AUDIO_SPDIF_REC_GEN_REG(unit), reg);
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvSPDIFRecordTclockGet - Get T-clock for SPDIF
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       none
+* OUTPUT:
+*		none
+* RETURN:
+*       T-clock configured in the SPDIF.
+*
+*******************************************************************************/
+MV_U32 mvSPDIFRecordTclockGet(int unit)
+{
+	MV_U32 reg = (MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG(unit)) & ASRGR_CORE_CLK_FREQ_MASK);
+
+	switch (reg) {
+	case ASRGR_CORE_CLK_FREQ_133MHZ:
+		return MV_BOARD_TCLK_133MHZ;
+	case ASRGR_CORE_CLK_FREQ_150MHZ:
+		return MV_BOARD_TCLK_150MHZ;
+	case ASRGR_CORE_CLK_FREQ_166MHZ:
+		return MV_BOARD_TCLK_166MHZ;
+	case ASRGR_CORE_CLK_FREQ_200MHZ:
+		return MV_BOARD_TCLK_200MHZ;
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+* mvAudioRecordControlGet - Get SPDIF Recording status parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       status: pointer to MV_SPDIF_RECORD_STATUS structure
+* OUTPUT:
+*		status: pointer to MV_SPDIF_RECORD_STATUS structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvSPDIFRecordStatusGet(int unit, MV_SPDIF_RECORD_STATUS *status)
+{
+	status->freq =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG(unit)) & ASRGR_CORE_CLK_FREQ_MASK) >> ASRGR_CORE_CLK_FREQ_OFFS);
+
+	status->nonLinearPcm =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG(unit)) & ASRGR_NON_PCM_MASK) ? MV_TRUE : MV_FALSE);
+
+	status->validPcm =
+	    ((MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG(unit)) & ASRGR_VALID_PCM_INFO_MASK) ? MV_TRUE : MV_FALSE);
+
+}
+
+/* I2S Recording Related*/
+/*******************************************************************************
+* mvI2SRecordCntrlSet - Get I2S Recording status parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_I2S_RECORD_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_I2S_RECORD_CTRL structure
+* RETURN:
+*       MV_OK on success , MV_FAIL on fail.
+*
+*******************************************************************************/
+MV_STATUS mvI2SRecordCntrlSet(int unit, MV_I2S_RECORD_CTRL *ctrl)
+{
+	MV_U32 reg;
+
+#if 0
+	if (ctrl->sample > SAMPLE_16BIT) {
+		mvOsPrintf("mvI2SRecordCntrlSet: Error , Illigal sample size %d\n", ctrl->sample);
+		return MV_FAIL;
+	}
+#endif
+
+	reg = MV_REG_READ(MV_AUDIO_I2S_REC_CTRL_REG(unit));
+	reg &= ~(AIRCR_I2S_RECORD_JUSTF_MASK | AIRCR_I2S_SAMPLE_SIZE_MASK);
+
+	switch (ctrl->justf) {
+	case I2S_JUSTIFIED:
+	case LEFT_JUSTIFIED:
+	case RIGHT_JUSTIFIED:
+	case RISE_BIT_CLCK_JUSTIFIED:
+		reg |= ctrl->justf << AIRCR_I2S_RECORD_JUSTF_OFFS;
+		break;
+	default:
+		return MV_FAIL;
+	}
+
+	reg |= ctrl->sample << AIRCR_I2S_SAMPLE_SIZE_OFFS;
+
+	MV_REG_WRITE(MV_AUDIO_I2S_REC_CTRL_REG(unit), reg);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAudioRecordControlGet - Get I2S Recording status parameters
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       ctrl: pointer to MV_I2S_RECORD_CTRL structure
+* OUTPUT:
+*		ctrl: pointer to MV_I2S_RECORD_CTRL structure
+* RETURN:
+*       None
+*
+*******************************************************************************/
+MV_VOID mvI2SRecordCntrlGet(int unit, MV_I2S_RECORD_CTRL *ctrl)
+{
+	ctrl->sample =
+	    ((MV_REG_READ(MV_AUDIO_I2S_REC_CTRL_REG(unit)) & AIRCR_I2S_SAMPLE_SIZE_MASK) >> AIRCR_I2S_SAMPLE_SIZE_OFFS);
+
+	ctrl->justf =
+	    ((MV_REG_READ(MV_AUDIO_I2S_REC_CTRL_REG(unit)) & AIRCR_I2S_RECORD_JUSTF_MASK) >>
+	     AIRCR_I2S_RECORD_JUSTF_OFFS);
+}
+
+/*******************************************************************************
+* audioBurstBytesNumGet - Convert Burst enum to bytes number
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       burst:  MV_AUDIO_BURST_SIZE  enum
+* OUTPUT:
+*		none
+* RETURN:
+*       number of burst bytes
+*
+*******************************************************************************/
+static MV_U32 audioBurstBytesNumGet(MV_AUDIO_BURST_SIZE burst)
+{
+	switch (burst) {
+	case AUDIO_32BYTE_BURST:
+		return 32;
+	case AUDIO_128BYTE_BURST:
+		return 128;
+	default:
+		return 0xffffffff;
+	}
+}
+
+#ifndef MV_AUDIO_SKIP_WIN_DECODING
+/*******************************************************************************
+* mvAudioReplaceAddrWin
+*
+* DESCRIPTION:
+*	This function is used to replace the address decoding windows of the
+*	recording / playback engines, in case the address given by the user is
+*	not within the configured window.
+*
+* INPUT:
+*       unit:  Audio unit ID.
+*	winId: Playback or Recording window.
+*	buffPhysAddr: The physical address of the buffer to be configured.
+*	buffSize: Size of buffPhysAddr.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+static MV_STATUS mvAudioReplaceAddrWin(MV_U32 unit, MV_U32 winId, MV_U32 buffPhysAddr, MV_U32 buffSize)
+{
+	MV_UNIT_WIN_INFO audioWin;
+	MV_UNIT_WIN_INFO *winInfo;
+	MV_ADDR_WIN bufAddrWin;
+	MV_U32 target, i;
+
+	/* Get the details of the Record address window */
+	if (mvAudioWinRead(unit, winId, &audioWin) != MV_OK) {
+		mvOsPrintf("mvAudioRecordControlSet: Error calling mvAudioWinGet on win %d\n", unit);
+		return MV_FAIL;
+	}
+
+	bufAddrWin.baseHigh = 0;
+	bufAddrWin.baseLow = buffPhysAddr;
+	bufAddrWin.size = buffSize;
+
+	/* If Record window is not enabled or buffer address is not within window boundries
+	   then try to set a new value to the Record window by
+	   Geting the target of where the buffer exist, if the buffer is within the window
+	   of the new target then set the Record window to that target
+	   else return Fail
+	 */
+	if ((audioWin.enable != MV_TRUE) || (MV_TRUE != mvWinWithinWinTest(&bufAddrWin, &audioWin.addrWin))) {
+		/* Look for the target containing the phyBaseAddr */
+		for (i = 0; i < MAX_TARGETS; i++) {
+			winInfo = &audioAddrDecWinMap[i];
+
+			if ((buffPhysAddr >= winInfo->addrWin.baseLow) &&
+			    (buffPhysAddr < winInfo->addrWin.baseLow + winInfo->addrWin.size))
+				break;
+		}
+
+		/* Get the target of the buffer that user require */
+		target = i;
+		if (MAX_TARGETS == target) {
+			mvOsPrintf("mvAudioReplaceAddrWin: Address not found in any of the targets 0x%x\n",
+				   buffPhysAddr);
+			return MV_FAIL;
+		}
+
+		/* if the address window of the target is enabled and the user buffer is within
+		   that target address window then set the palyback\recording window to the
+		   target window
+		 */
+		if ((winInfo->enable == MV_TRUE) && (MV_TRUE == mvWinWithinWinTest(&bufAddrWin, &winInfo->addrWin))) {
+			if (mvAudioWinWrite(unit, winId, winInfo) != MV_OK) {
+				mvOsPrintf("mvAudioReplaceAddrWin: Error calling mvAudioWinWrite on win %d\n", winId);
+				return MV_FAIL;
+			}
+
+		} else {
+			mvOsPrintf("mvAudioReplaceAddrWin: Error buffer is not within a valid target\n");
+			return MV_FAIL;
+
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAudioSetAddDecMap
+*
+* DESCRIPTION:
+*	This function is called by the audio address decoding configuration
+*	function to initialize the address decoding map of the audio HAL.
+*	This info will be used by the mvAudioReplaceAddrWin() function.
+*
+* INPUT:
+*	pAddrDecWinMap: System's address deocding map.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvAudioSetAddDecMap(MV_UNIT_WIN_INFO *pAddrDecWinMap)
+{
+	mvOsMemcpy(audioAddrDecWinMap, pAddrDecWinMap, sizeof(audioAddrDecWinMap));
+	return MV_OK;
+}
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/mvAudio.h b/arch/arm/plat-feroceon/mv_hal/audio/mvAudio.h
new file mode 100755
index 0000000..1912676
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/mvAudio.h
@@ -0,0 +1,398 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCMVAudioH
+#define __INCMVAudioH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysAudioConfig.h"
+
+/*********************************/
+/* General enums and structures */
+/*********************************/
+
+	typedef struct {
+		MV_U32 tclk;
+	} MV_AUDIO_HAL_DATA;
+
+/* Audio source Clocks enum*/
+	typedef enum _mvAudioClock {
+		AUDIO_DCO_CLK = 0,
+		AUDIO_SPCR_CLK = 2,
+		AUDIO_EXT_CLK = 3
+	} MV_AUDIO_CLOCK;
+
+	typedef enum _mvAudioFreq {
+		AUDIO_FREQ_44_1KH = 0,	/* 11.2896Mhz */
+		AUDIO_FREQ_48KH = 1,	/* 12.288Mhz */
+		AUDIO_FREQ_96KH = 2,	/* 24.576Mhz */
+		AUDIO_FREQ_LOWER_44_1KH = 3,	/*Lower than 11.2896MHz */
+		AUDIO_FREQ_HIGHER_96KH = 4,	/*Higher than 24.576MHz */
+		AUDIO_FREQ_OTHER = 7,	/*Other frequency */
+	} MV_AUDIO_FREQ;
+
+	typedef enum _mvAudioSampleFreq {
+		SMAPLE_8KHZ = 0,
+		SMAPLE_16KHZ,
+		SMAPLE_22_05KHZ,
+		SMAPLE_24KHZ,
+		SMAPLE_32KHZ,
+		SMAPLE_44_1KHZ,
+		SMAPLE_48KHZ,
+		SMAPLE_64KHZ,
+		SMAPLE_88KHZ,
+		SMAPLE_96KHZ,
+		SMAPLE_176KHZ,
+		SMAPLE_192KHZ
+	} MV_AUDIO_SAMPLE_FREQ;
+
+	typedef enum _mvAudioBurstSize {
+		AUDIO_32BYTE_BURST = 1,
+		AUDIO_128BYTE_BURST = 2,
+
+	} MV_AUDIO_BURST_SIZE;
+
+	typedef enum _mvAudioPlaybackMono {
+		AUDIO_PLAY_MONO_OFF = 0,
+		AUDIO_PLAY_LEFT_MONO = 1,
+		AUDIO_PLAY_RIGHT_MONO = 2,
+		AUDIO_PLAY_BOTH_MONO = 3,
+		AUDIO_PLAY_OTHER_MONO = 4
+	} MV_AUDIO_PLAYBACK_MONO;
+
+	typedef enum _mvAudioRecordMono {
+		AUDIO_REC_LEFT_MONO = 0,
+		AUDIO_REC_RIGHT_MONO = 1,
+
+	} MV_AUDIO_RECORD_MONO;
+
+	typedef enum _mvAudioSampleSize {
+		SAMPLE_32BIT = 0,
+		SAMPLE_24BIT = 1,
+		SAMPLE_20BIT = 2,
+		SAMPLE_16BIT = 3,
+		SAMPLE_16BIT_NON_COMPACT = 7
+	} MV_AUDIO_SAMPLE_SIZE;
+
+	typedef enum _mvAudioI2SJustification {
+		LEFT_JUSTIFIED = 0,
+		I2S_JUSTIFIED = 5,
+		RISE_BIT_CLCK_JUSTIFIED = 7,
+		RIGHT_JUSTIFIED = 8,
+
+	} MV_AUDIO_I2S_JUSTIFICATION;
+
+/* Type of Audio operations*/
+	typedef enum _mvAudioOperation {
+		AUDIO_PLAYBACK = 0,
+		AUDIO_RECORD = 1
+	} MV_AUDIO_OP;
+
+	typedef struct _mvAudioFreqData {
+		MV_AUDIO_FREQ baseFreq;	/* Control FS, selects the base frequency of the DCO */
+		MV_U32 offset;	/* Offset control in which each step equals to 0.9536 ppm */
+
+	} MV_AUDIO_FREQ_DATA;
+
+/*********************************/
+/* Play Back related structures */
+/*********************************/
+
+	typedef struct _mvAudioPlaybackCtrl {
+		MV_AUDIO_BURST_SIZE burst;	/* Specifies the Burst Size of the DMA */
+		MV_BOOL loopBack;	/* When Loopback is enabled, playback
+					   data is looped back to be recorded */
+		MV_AUDIO_PLAYBACK_MONO monoMode;	/* Mono Mode is used */
+		MV_U32 bufferPhyBase;	/* Physical Address of DMA buffer */
+		MV_U32 bufferSize;	/* Size of DMA buffer */
+		MV_U32 intByteCount;	/* Number of bytes after which an
+					   interrupt will be issued. */
+		MV_AUDIO_SAMPLE_SIZE sampleSize;	/* Playback Sample Size */
+	} MV_AUDIO_PLAYBACK_CTRL;
+
+	typedef struct _mvAudioPlaypackStatus {
+		MV_BOOL muteI2S;
+		MV_BOOL enableI2S;
+		MV_BOOL muteSPDIF;
+		MV_BOOL enableSPDIF;
+		MV_BOOL pause;
+
+	} MV_AUDIO_PLAYBACK_STATUS;
+
+	typedef struct _mvSpdifPlaybackCtrl {
+		MV_BOOL nonPcm;	/* PCM or non-PCM mode */
+		MV_BOOL validity;	/* Validity bit value when using
+					   registers (userBitsFromMemory=0) */
+		MV_BOOL underrunData;	/* If true send last frame on mute/pause/underrun
+					   otherwise send 24 binary */
+		MV_BOOL userBitsFromMemory;	/* otherwise from intenal registers */
+		MV_BOOL validityFromMemory;	/* otherwise from internal registers */
+		MV_BOOL blockStartInternally;	/* When user and valid bits are form registers
+						   then this bit should be zero */
+	} MV_SPDIF_PLAYBACK_CTRL;
+
+	typedef struct _mvI2SPlaybackCtrl {
+		MV_AUDIO_SAMPLE_SIZE sampleSize;
+		MV_AUDIO_I2S_JUSTIFICATION justification;
+		MV_BOOL sendLastFrame;	/* If true send last frame on mute/pause/underrun
+					   otherwise send 64 binary */
+	} MV_I2S_PLAYBACK_CTRL;
+
+/*********************************/
+/* Recording  related structures */
+/*********************************/
+
+	typedef struct _mvAudioRecordCtrl {
+		MV_AUDIO_BURST_SIZE burst;	/* Recording DMA Burst Size */
+		MV_AUDIO_SAMPLE_SIZE sampleSize;	/*Recording Sample Size */
+		MV_BOOL mono;	/* If true then recording mono else recording stereo */
+		MV_AUDIO_RECORD_MONO monoChannel;	/* Left or right moono */
+		MV_U32 bufferPhyBase;	/* Physical Address of DMA buffer */
+		MV_U32 bufferSize;	/* Size of DMA buffer */
+
+		MV_U32 intByteCount;	/* Number of bytes after which an
+					   interrupt will be issued. */
+
+	} MV_AUDIO_RECORD_CTRL;
+
+	typedef struct _mvAudioRecordStatus {
+		MV_BOOL mute;
+		MV_BOOL pause;
+		MV_BOOL spdifEnable;
+		MV_BOOL I2SEnable;
+
+	} MV_AUDIO_RECORD_STATUS;
+
+	typedef struct _mvSPDIFRecordStatus {
+		MV_BOOL nonLinearPcm;	/* pcm non-pcm */
+		MV_BOOL validPcm;	/* valid non-valid pcm */
+		MV_AUDIO_SAMPLE_FREQ freq;	/* sampled frequency */
+
+	} MV_SPDIF_RECORD_STATUS;
+
+	typedef struct _mvI2SRecordCntrl {
+		MV_AUDIO_SAMPLE_SIZE sample;	/* I2S Recording Sample Size */
+		MV_AUDIO_I2S_JUSTIFICATION justf;
+	} MV_I2S_RECORD_CTRL;
+
+/*********************************/
+/* Usefull Macros 				*/
+/*
+ -- Clocks Control and Status related --
+mvAudioIsDcoLocked()
+mvAudioIsSpcrLocked()
+mvAudioIsPllLocked()
+mvAudioAllCountersClear()
+mvAudioPlayCounterClear()
+mvAudioRecCounterClear()
+mvAudioAllCountersStart()
+mvAudioPlayCounterStart()
+mvAudioRecCounterStart()
+mvAudioAllCountersStop()
+mvAudioPlayCounterStop()
+mvAudioRecCounterStop()
+
+ -- PlayBack related --
+mvAudioIsPlaybackBusy()
+mvAudioI2SPlaybackMute(mute)
+mvAudioI2SPlaybackEnable(enable)
+mvAudioSPDIFPlaybackMute(mute)
+mvAudioSPDIFPlaybackEnable(enable)
+mvAudioPlaybackPause(pause)
+
+---- Recording ---
+mvAudioSPDIFRecordingEnable(enable)
+mvAudioI2SRecordingEnable(enable)
+mvAudioRecordMute(mute)
+mvAudioRecordPause(pause)
+
+********************************/
+
+/* Clocks Control and Status related*/
+#define mvAudioIsDcoLocked()	\
+	(ASDSR_DCO_LOCK_MASK & MV_REG_READ(MV_AUDIO_SPCR_DCO_STATUS_REG))
+#define	mvAudioIsSpcrLocked()	\
+	(ASDSR_SPCR_LOCK_MASK & MV_REG_READ(AUDIO_SPCR_DCO_STATUS_REG))
+#define	mvAudioIsPllLocked()	\
+	(ASDSR_PLL_LOCK_MASK & MV_REG_READ(AUDIO_SPCR_DCO_STATUS_REG))
+
+#define mvAudioAllCountersClear()	\
+	(MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_CLR_REC_CNTR_MASK|ASCCR_CLR_PLAY_CNTR_MASK)))
+#define mvAudioPlayCounterClear()	\
+	(MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_CLR_PLAY_CNTR_MASK)))
+#define mvAudioRecCounterClear()	\
+	(MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_CLR_REC_CNTR_MASK)))
+
+#define	mvAudioAllCountersStart()	\
+	(MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_ACTIVE_PLAY_CNTR_MASK|ASCCR_ACTIVE_REC_CNTR_MASK)))
+#define mvAudioPlayCounterStart()	\
+	(MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_ACTIVE_PLAY_CNTR_MASK)))
+#define mvAudioRecCounterStart()	\
+	(MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_ACTIVE_REC_CNTR_MASK)))
+
+#define	mvAudioAllCountersStop()	\
+	(MV_REG_BIT_RESET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_ACTIVE_PLAY_CNTR_MASK|ASCCR_ACTIVE_REC_CNTR_MASK)))
+#define mvAudioPlayCounterStop()	\
+	(MV_REG_BIT_RESET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_ACTIVE_PLAY_CNTR_MASK)))
+#define mvAudioRecCounterStop()	\
+	(MV_REG_BIT_RESET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG(0), (ASCCR_ACTIVE_REC_CNTR_MASK)))
+
+/* Audio PlayBack related*/
+#define	mvAudioIsPlaybackBusy()	\
+	(APCR_PLAY_BUSY_MASK & MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG(0)))
+
+#define	mvAudioI2SPlaybackMute(mute)	\
+	(void)((mute) ? (MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_I2S_MUTE_MASK)) : 	\
+			 MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_I2S_MUTE_MASK))
+#define	mvAudioI2SPlaybackEnable(enable)	\
+	 (void)((enable) ? (MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_I2S_ENABLE_MASK)) : 	\
+			  MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_I2S_ENABLE_MASK))
+
+#define	mvAudioSPDIFPlaybackMute(mute)	\
+	(void)((mute) ? (MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_SPDIF_MUTE_MASK)) : 	\
+			 MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_SPDIF_MUTE_MASK))
+#define	mvAudioSPDIFPlaybackEnable(enable)	\
+	 (void)((enable) ? (MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_SPDIF_ENABLE_MASK)) : 	\
+			  MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_SPDIF_ENABLE_MASK))
+
+#define	mvAudioAllIfPlaybackEnable(enable)	\
+	 (void)((enable) ?     \
+			(MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG(0),     \
+			(APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))) : 	\
+			MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG(0),  \
+			(APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK)))
+
+#define	mvAudioPlaybackPause(pause)	\
+	 (void)((pause) ? (MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_PAUSE_MASK)) : 	\
+			  MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_PLAY_PAUSE_MASK))
+
+#define	mvAudioPlaybackLoopbackEnable(enable)	\
+	 (void)((enable) ? (MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_LOOPBACK_MASK)) : 	\
+			  MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG(0), APCR_LOOPBACK_MASK))
+
+/* Audio Recording*/
+#define	mvAudioSPDIFRecordingEnable(enable)	\
+	 (void)((enable) ? (MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG(0), ARCR_RECORD_SPDIF_EN_MASK)) : 	\
+			  MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG(0), ARCR_RECORD_SPDIF_EN_MASK))
+
+#define	mvAudioI2SRecordingEnable(enable)	\
+	 (void)((enable) ? (MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG(0), ARCR_RECORD_I2S_EN_MASK)) : 	\
+			  MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG(0), ARCR_RECORD_I2S_EN_MASK))
+
+#define mvAudioRecordMute(mute)	\
+	 (void)((mute) ? (MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG(0), ARCR_RECORD_MUTE_MASK)) : 	\
+			  MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG(0), ARCR_RECORD_MUTE_MASK))
+
+#define mvAudioRecordPause(pause)	\
+	 (void)((pause) ? (MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG(0), ARCR_RECORD_PAUSE_MASK)) : 	\
+			  MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG(0), ARCR_RECORD_PAUSE_MASK))
+
+/*********************************/
+/* Functions API 				*/
+/*********************************/
+
+	MV_VOID mvAudioHalInit(MV_U8 unit, MV_AUDIO_HAL_DATA *halData);
+	MV_STATUS mvAudioWinInit(MV_U32 unit, MV_UNIT_WIN_INFO *addrWinMap);
+	MV_STATUS mvAudioWinRead(MV_U32 unit, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+	MV_STATUS mvAudioWinWrite(MV_U32 unit, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+
+/* Clocks Control and Status related*/
+	MV_STATUS mvAudioDCOCtrlSet(int unit, MV_AUDIO_FREQ_DATA *dcoCtrl);
+	MV_VOID mvAudioDCOCtrlGet(int unit, MV_AUDIO_FREQ_DATA *dcoCtrl);
+	MV_VOID mvAudioSpcrCtrlGet(int unit, MV_AUDIO_FREQ_DATA *spcrCtrl);
+
+/* Audio PlayBack related*/
+	MV_STATUS mvAudioPlaybackControlSet(int unit, MV_AUDIO_PLAYBACK_CTRL *ctrl);
+	MV_VOID mvAudioPlaybackControlGet(int unit, MV_AUDIO_PLAYBACK_CTRL *ctrl);
+	MV_VOID mvAudioPlaybackStatusGet(int unit, MV_AUDIO_PLAYBACK_STATUS *status);
+
+/* Audio SPDIF PlayBack related*/
+	MV_VOID mvSPDIFPlaybackCtrlSet(int unit, MV_SPDIF_PLAYBACK_CTRL *ctrl);
+	MV_VOID mvSPDIFPlaybackCtrlGet(int unit, MV_SPDIF_PLAYBACK_CTRL *ctrl);
+
+/* Audio I2S PlayBack related*/
+	MV_STATUS mvI2SPlaybackCtrlSet(int unit, MV_I2S_PLAYBACK_CTRL *ctrl);
+	MV_VOID mvI2SPlaybackCtrlGet(int unit, MV_I2S_PLAYBACK_CTRL *ctrl);
+
+/* Audio Recording*/
+	MV_STATUS mvAudioRecordControlSet(int unit, MV_AUDIO_RECORD_CTRL *ctrl);
+	MV_VOID mvAudioRecordControlGet(int unit, MV_AUDIO_RECORD_CTRL *ctrl);
+	MV_VOID mvAudioRecordStatusGet(int unit, MV_AUDIO_RECORD_STATUS *status);
+
+/* SPDIF Recording Related*/
+	MV_STATUS mvSPDIFRecordTclockSet(int unit);
+	MV_U32 mvSPDIFRecordTclockGet(int unit);
+	MV_VOID mvSPDIFRecordStatusGet(int unit, MV_SPDIF_RECORD_STATUS *status);
+
+/* I2S Recording Related*/
+	MV_STATUS mvI2SRecordCntrlSet(int unit, MV_I2S_RECORD_CTRL *ctrl);
+	MV_VOID mvI2SRecordCntrlGet(int unit, MV_I2S_RECORD_CTRL *ctrl);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/mvAudioAddrDec.c b/arch/arm/plat-feroceon/mv_hal/audio/mvAudioAddrDec.c
new file mode 100755
index 0000000..46a62b5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/mvAudioAddrDec.c
@@ -0,0 +1,251 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvAudioRegs.h"
+
+#ifndef MV_AUDIO_SKIP_WIN_DECODING
+extern MV_STATUS mvAudioSetAddDecMap(MV_UNIT_WIN_INFO *pAddrDecWinMap);
+#endif
+
+/*******************************************************************************
+* mvAudioWinWrite
+*
+* DESCRIPTION:
+*	This function writes the address decoding registers according to the
+*	given window configuration.
+*
+* INPUT:
+*       unit	    - The Audio unit number to configure.
+*       winNum	    - AUDIO target address decode window number.
+*       pAddrDecWin - AUDIO target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*   MV_OK on success,
+*	MV_BAD_PARAM if winNum is invalid.
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvAudioWinWrite(MV_U32 unit, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 baseReg;
+	MV_U32 sizeReg;
+	MV_U32 size;
+	MV_U32 alignment;
+
+	/* Parameter checking   */
+	if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN) {
+		mvOsPrintf("%s: ERR. Invalid win num %d\n", __func__, winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) {
+		mvOsPrintf("mvAudioWinWrite:Error setting AUDIO window %d to "
+			   "Address 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	size = pAddrDecWin->addrWin.size;
+	if (!MV_IS_POWER_OF_2(size)) {
+		mvOsPrintf("mvAudioWinWrite: Error setting AUDIO window %d. "
+			   "Window size is not a power to 2.", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	alignment = 1 << MV_AUDIO_WIN_SIZE_OFFSET;
+
+	sizeReg = (size / alignment - 1) << MV_AUDIO_WIN_SIZE_OFFSET;
+
+	/* BaseLow[31:16] => base register [31:16]          */
+	baseReg = pAddrDecWin->addrWin.baseLow & MV_AUDIO_WIN_BASE_MASK;
+
+	/* set attributes */
+	sizeReg &= ~MV_AUDIO_WIN_ATTR_MASK;
+	sizeReg |= (pAddrDecWin->attrib << MV_AUDIO_WIN_ATTR_OFFSET);
+
+	/* set target ID */
+	sizeReg &= ~MV_AUDIO_WIN_TARGET_MASK;
+	sizeReg |= (pAddrDecWin->targetId << MV_AUDIO_WIN_TARGET_OFFSET);
+
+	if (pAddrDecWin->enable == MV_TRUE)
+		sizeReg |= MV_AUDIO_WIN_ENABLE_MASK;
+	else
+		sizeReg &= ~MV_AUDIO_WIN_ENABLE_MASK;
+
+	MV_REG_WRITE(MV_AUDIO_WIN_CTRL_REG(unit, winNum), sizeReg);
+	MV_REG_WRITE(MV_AUDIO_WIN_BASE_REG(unit, winNum), baseReg);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAudioWinRead
+*
+* DESCRIPTION:
+*       Read AUDIO peripheral target address window.
+*
+* INPUT:
+*       winNum - AUDIO target address decode window number.
+*
+* OUTPUT:
+*       pAddrDecWin - AUDIO target window data structure.
+*
+* RETURN:
+*	MV_BAD_PARAM if winNum is invalid.
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvAudioWinRead(MV_U32 unit, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 baseReg, sizeReg;
+	MV_U32 sizeRegVal;
+	MV_U32 alignment;
+
+	if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN) {
+		mvOsPrintf("%s : ERR. Invalid winNum %d\n", __func__, winNum);
+		return MV_BAD_PARAM;
+	}
+
+	baseReg = MV_REG_READ(MV_AUDIO_WIN_BASE_REG(unit, winNum));
+	sizeReg = MV_REG_READ(MV_AUDIO_WIN_CTRL_REG(unit, winNum));
+
+	alignment = 1 << MV_AUDIO_WIN_SIZE_OFFSET;
+	sizeRegVal = (sizeReg & MV_AUDIO_WIN_SIZE_MASK) >> MV_AUDIO_WIN_SIZE_OFFSET;
+
+	pAddrDecWin->addrWin.size = (sizeRegVal + 1) * alignment;
+
+	/* Extract base address                                             */
+	/* Base register [31:16] ==> baseLow[31:16]                 */
+	pAddrDecWin->addrWin.baseLow = baseReg & MV_AUDIO_WIN_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh = 0;
+
+	/* attrib and targetId */
+	pAddrDecWin->attrib = (sizeReg & MV_AUDIO_WIN_ATTR_MASK) >> MV_AUDIO_WIN_ATTR_OFFSET;
+	pAddrDecWin->targetId = (sizeReg & MV_AUDIO_WIN_TARGET_MASK) >> MV_AUDIO_WIN_TARGET_OFFSET;
+
+	/* Check if window is enabled   */
+	if (sizeReg & MV_AUDIO_WIN_ENABLE_MASK)
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvAudioWinInit
+*
+* DESCRIPTION:
+*       Initialize the AUDIO peripheral target address window.
+*
+* INPUT:
+*	unit	 : The unit number to initialize the address decoding for.
+*	addWinMap: An array holding the address decoding information for the
+*		    system.
+*
+* OUTPUT:
+*     None.
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvAudioWinInit(MV_U32 unit, MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_32 winNum;
+	MV_UNIT_WIN_INFO *cpuAddrDecWin;
+
+	/* Initiate Audio address decode */
+
+	/* First disable all address decode windows */
+	for (winNum = 0; winNum < MV_AUDIO_MAX_ADDR_DECODE_WIN; winNum++) {
+		MV_U32 regVal = MV_REG_READ(MV_AUDIO_WIN_CTRL_REG(unit, winNum));
+		regVal &= ~MV_AUDIO_WIN_ENABLE_MASK;
+		MV_REG_WRITE(MV_AUDIO_WIN_CTRL_REG(unit, winNum), regVal);
+	}
+
+	for (winNum = 0; winNum < MV_AUDIO_MAX_ADDR_DECODE_WIN; winNum++) {
+		/* We will set the Window to DRAM_CS0 in default */
+		/* first get attributes from CPU If */
+		cpuAddrDecWin = &addrWinMap[SDRAM_CS0];
+
+		if (cpuAddrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvAudioWinWrite(unit, winNum, cpuAddrDecWin))
+				return MV_ERROR;
+		}
+	}
+
+#ifndef MV_AUDIO_SKIP_WIN_DECODING
+	/* Initialize the address decoding map in the audio driver */
+	mvAudioSetAddDecMap(addrWinMap);
+#endif
+
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/mvAudioRegs.h b/arch/arm/plat-feroceon/mv_hal/audio/mvAudioRegs.h
new file mode 100755
index 0000000..42f4f95
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/mvAudioRegs.h
@@ -0,0 +1,356 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCMVAudioRegsH
+#define __INCMVAudioRegsH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvSysAudioConfig.h"
+
+#define APBBCR_SIZE_MAX						0x3FFFFF
+#define APBBCR_SIZE_SHIFT					0x2
+
+#define AUDIO_REG_TO_SIZE(reg)		(((reg) + 1) << APBBCR_SIZE_SHIFT)
+#define AUDIO_SIZE_TO_REG(size)		(((size) >> APBBCR_SIZE_SHIFT) - 1)
+
+#define MV_AUDIO_BUFFER_MIN_ALIGN	0x8
+
+/********************/
+/* Clocking Control*/
+/*******************/
+#define MV_AUDIO_PLL_CTRL1_REG(unit)			(MV_AUDIO_REGS_BASE(unit) + 0x1200)
+#define MV_AUDIO_DCO_CTRL_REG(unit)			(MV_AUDIO_REGS_BASE(unit) + 0x1204)
+#define MV_AUDIO_SPCR_DCO_STATUS_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x120c)
+#define MV_AUDIO_SAMPLE_CNTR_CTRL_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1220)
+#define MV_AUDIO_PLAYBACK_SAMPLE_CNTR_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1224)
+#define MV_AUDIO_RECORD_SAMPLE_CNTR_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1228)
+#define MV_AUDIO_CLOCK_CTRL_REG(unit)			(MV_AUDIO_REGS_BASE(unit) + 0x1230)
+
+/* MV_AUDIO_DCO_CTRL_REG */
+#define ADCR_DCO_CTRL_FS_OFFS		0
+#define ADCR_DCO_CTRL_FS_MASK		(0x3 << ADCR_DCO_CTRL_FS_OFFS)
+#define ADCR_DCO_CTRL_FS_44_1KHZ	(0x0 << ADCR_DCO_CTRL_FS_OFFS)
+#define ADCR_DCO_CTRL_FS_48KHZ		(0x1 << ADCR_DCO_CTRL_FS_OFFS)
+#define ADCR_DCO_CTRL_FS_96KHZ		(0x2 << ADCR_DCO_CTRL_FS_OFFS)
+
+#define ADCR_DCO_CTRL_OFFSET_OFFS	2
+#define ADCR_DCO_CTRL_OFFSET_MASK	(0xfff << ADCR_DCO_CTRL_OFFSET_OFFS)
+
+/* MV_AUDIO_SPCR_DCO_STATUS_REG */
+#define ASDSR_SPCR_CTRLFS_OFFS		0
+#define ASDSR_SPCR_CTRLFS_MASK		(0x7 << ASDSR_SPCR_CTRLFS_OFFS)
+#define ASDSR_SPCR_CTRLFS_44_1KHZ	(0x0 << ASDSR_SPCR_CTRLFS_OFFS)
+#define ASDSR_SPCR_CTRLFS_48KHZ		(0x1 << ASDSR_SPCR_CTRLFS_OFFS)
+#define ASDSR_SPCR_CTRLFS_96KHZ		(0x2 << ASDSR_SPCR_CTRLFS_OFFS)
+#define ASDSR_SPCR_CTRLFS_44_1KHZ_LESS	(0x3 << ASDSR_SPCR_CTRLFS_OFFS)
+#define ASDSR_SPCR_CTRLFS_96KHZ_MORE	(0x4 << ASDSR_SPCR_CTRLFS_OFFS)
+#define ASDSR_SPCR_CTRLFS_OTHER		(0x7 << ASDSR_SPCR_CTRLFS_OFFS)
+
+#define ASDSR_SPCR_CTRLOFFSET_OFFS	3
+#define ASDSR_SPCR_CTRLOFFSET_MASK	(0xfff << ASDSR_SPCR_CTRLOFFSET_OFFS)
+
+#define ASDSR_SPCR_LOCK_OFFS		15
+#define ASDSR_SPCR_LOCK_MASK		(0x1 << ASDSR_SPCR_LOCK_OFFS)
+
+#define ASDSR_DCO_LOCK_OFFS		16
+#define ASDSR_DCO_LOCK_MASK		(0x1 << ASDSR_DCO_LOCK_OFFS)
+
+#define ASDSR_PLL_LOCK_OFFS		17
+#define ASDSR_PLL_LOCK_MASK		(0x1 << ASDSR_PLL_LOCK_OFFS)
+
+/*MV_AUDIO_SAMPLE_CNTR_CTRL_REG */
+
+#define ASCCR_CLR_PLAY_CNTR_OFFS	9
+#define ASCCR_CLR_PLAY_CNTR_MASK	(0x1 << ASCCR_CLR_PLAY_CNTR_OFFS)
+
+#define ASCCR_CLR_REC_CNTR_OFFS		8
+#define ASCCR_CLR_REC_CNTR_MASK		(0x1 << ASCCR_CLR_REC_CNTR_OFFS)
+
+#define ASCCR_ACTIVE_PLAY_CNTR_OFFS	1
+#define ASCCR_ACTIVE_PLAY_CNTR_MASK	(0x1 << ASCCR_ACTIVE_PLAY_CNTR_OFFS)
+
+#define ASCCR_ACTIVE_REC_CNTR_OFFS	0
+#define ASCCR_ACTIVE_REC_CNTR_MASK	(0x1 << ASCCR_ACTIVE_REC_CNTR_OFFS)
+
+/* MV_AUDIO_CLOCK_CTRL_REG */
+#define ACCR_MCLK_SOURCE_OFFS		0
+#define ACCR_MCLK_SOURCE_MASK		(0x3 << ACCR_MCLK_SOURCE_OFFS)
+#define ACCR_MCLK_SOURCE_DCO		(0x0 << ACCR_MCLK_SOURCE_OFFS)
+#define ACCR_MCLK_SOURCE_SPCR		(0x2 << ACCR_MCLK_SOURCE_OFFS)
+#define ACCR_MCLK_SOURCE_EXT		(0x3 << ACCR_MCLK_SOURCE_OFFS)
+
+/********************/
+/* Interrupts		*/
+/*******************/
+#define MV_AUDIO_ERROR_CAUSE_REG(unit)			(MV_AUDIO_REGS_BASE(unit) + 0x1300)
+#define MV_AUDIO_ERROR_MASK_REG(unit)			(MV_AUDIO_REGS_BASE(unit) + 0x1304)
+#define MV_AUDIO_INT_CAUSE_REG(unit)			(MV_AUDIO_REGS_BASE(unit) + 0x1308)
+#define MV_AUDIO_INT_MASK_REG(unit)			(MV_AUDIO_REGS_BASE(unit) + 0x130C)
+#define MV_AUDIO_RECORD_BYTE_CNTR_INT_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1310)
+#define MV_AUDIO_PLAYBACK_BYTE_CNTR_INT_REG(unit)	(MV_AUDIO_REGS_BASE(unit) + 0x1314)
+
+/* MV_AUDIO_INT_CAUSE_REG*/
+#define AICR_RECORD_BYTES_INT			(0x1 << 13)
+#define AICR_PLAY_BYTES_INT			(0x1 << 14)
+
+#define ARBCI_BYTE_COUNT_MASK                   0xFFFFFF
+#define APBCI_BYTE_COUNT_MASK                   0xFFFFFF
+
+/********************/
+/* Audio Playback	*/
+/*******************/
+/* General */
+#define MV_AUDIO_PLAYBACK_CTRL_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1100)
+#define MV_AUDIO_PLAYBACK_BUFF_START_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1104)
+#define MV_AUDIO_PLAYBACK_BUFF_SIZE_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1108)
+#define MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG(unit)	(MV_AUDIO_REGS_BASE(unit) + 0x110c)
+
+/* SPDIF */
+#define MV_AUDIO_SPDIF_PLAY_CTRL_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x2204)
+#define MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(unit, ind)	        \
+					(MV_AUDIO_REGS_BASE(unit) + 0x2280 + (ind << 2))
+#define MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(unit, ind)	    \
+					(MV_AUDIO_REGS_BASE(unit) + 0x22a0 + (ind << 2))
+#define MV_AUDIO_SPDIF_PLAY_USR_BITS_LEFT_REG(unit, ind)          \
+					(MV_AUDIO_REGS_BASE(unit) + 0x22c0 + (ind << 2))
+#define MV_AUDIO_SPDIF_PLAY_USR_BITS_RIGHT_REG(unit, ind)              \
+					(MV_AUDIO_REGS_BASE(unit) + 0x22e0 + (ind << 2))
+/*I2S*/
+#define MV_AUDIO_I2S_PLAY_CTRL_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x2508)
+
+/* MV_AUDIO_PLAYBACK_CTRL_REG */
+#define APCR_PLAY_SAMPLE_SIZE_OFFS			0
+#define APCR_PLAY_SAMPLE_SIZE_MASK			(0x7 << APCR_PLAY_SAMPLE_SIZE_OFFS)
+
+#define APCR_PLAY_I2S_ENABLE_OFFS			3
+#define APCR_PLAY_I2S_ENABLE_MASK			(0x1 << APCR_PLAY_I2S_ENABLE_OFFS)
+
+#define APCR_PLAY_SPDIF_ENABLE_OFFS			4
+#define APCR_PLAY_SPDIF_ENABLE_MASK			(0x1 << APCR_PLAY_SPDIF_ENABLE_OFFS)
+
+#define APCR_PLAY_MONO_OFFS				5
+#define APCR_PLAY_MONO_MASK				(0x3 << APCR_PLAY_MONO_OFFS)
+
+#define APCR_PLAY_I2S_MUTE_OFFS				7
+#define APCR_PLAY_I2S_MUTE_MASK				(0x1 << APCR_PLAY_I2S_MUTE_OFFS)
+
+#define APCR_PLAY_SPDIF_MUTE_OFFS			8
+#define APCR_PLAY_SPDIF_MUTE_MASK			(0x1 << APCR_PLAY_SPDIF_MUTE_OFFS)
+
+#define APCR_PLAY_PAUSE_OFFS				9
+#define APCR_PLAY_PAUSE_MASK				(0x1 << APCR_PLAY_PAUSE_OFFS)
+
+#define APCR_LOOPBACK_OFFS				10
+#define APCR_LOOPBACK_MASK				(0x1 << APCR_LOOPBACK_OFFS)
+
+#define APCR_PLAY_BURST_SIZE_OFFS			11
+#define APCR_PLAY_BURST_SIZE_MASK			(0x3 << APCR_PLAY_BURST_SIZE_OFFS)
+
+#define APCR_PLAY_BUSY_OFFS				16
+#define APCR_PLAY_BUSY_MASK				(0x1 << APCR_PLAY_BUSY_OFFS)
+
+/* MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG */
+#define APBBCR_SIZE_MAX					0x3FFFFF
+#define APBBCR_SIZE_SHIFT				0x2
+
+/* MV_AUDIO_SPDIF_PLAY_CTRL_REG */
+#define ASPCR_SPDIF_BLOCK_START_OFFS		0x0
+#define ASPCR_SPDIF_BLOCK_START_MASK		(0x1 << ASPCR_SPDIF_BLOCK_START_OFFS)
+
+#define ASPCR_SPDIF_PB_EN_MEM_VALIDITY_OFFS	0x1
+#define ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK	(0x1 << ASPCR_SPDIF_PB_EN_MEM_VALIDITY_OFFS)
+
+#define ASPCR_SPDIF_PB_MEM_USR_EN_OFFS		0x2
+#define ASPCR_SPDIF_PB_MEM_USR_EN_MASK		(0x1 << ASPCR_SPDIF_PB_MEM_USR_EN_OFFS)
+
+#define ASPCR_SPDIF_UNDERRUN_DATA_OFFS		0x5
+#define ASPCR_SPDIF_UNDERRUN_DATA_MASK		(0x1 << ASPCR_SPDIF_UNDERRUN_DATA_OFFS)
+
+#define ASPCR_SPDIF_PB_REG_VALIDITY_OFFS	16
+#define ASPCR_SPDIF_PB_REG_VALIDITY_MASK	(0x1 << ASPCR_SPDIF_PB_REG_VALIDITY_OFFS)
+
+#define ASPCR_SPDIF_PB_NONPCM_OFFS		17
+#define ASPCR_SPDIF_PB_NONPCM_MASK		(0x1 << ASPCR_SPDIF_PB_NONPCM_OFFS)
+
+/* MV_AUDIO_I2S_PLAY_CTRL_REG */
+#define AIPCR_I2S_SEND_LAST_FRM_OFFS		23
+#define AIPCR_I2S_SEND_LAST_FRM_MASK		(1 << AIPCR_I2S_SEND_LAST_FRM_OFFS)
+
+#define AIPCR_I2S_PB_JUSTF_OFFS			26
+#define AIPCR_I2S_PB_JUSTF_MASK			(0xf << AIPCR_I2S_PB_JUSTF_OFFS)
+
+#define AIPCR_I2S_PB_SAMPLE_SIZE_OFFS		30
+#define AIPCR_I2S_PB_SAMPLE_SIZE_MASK		(0x3 << AIPCR_I2S_PB_SAMPLE_SIZE_OFFS)
+
+/********************/
+/* Audio Recordnig	*/
+/*******************/
+/* General */
+#define MV_AUDIO_RECORD_CTRL_REG(unit)			(MV_AUDIO_REGS_BASE(unit) + 0x1000)
+#define MV_AUDIO_RECORD_START_ADDR_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1004)
+#define MV_AUDIO_RECORD_BUFF_SIZE_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x1008)
+#define MV_AUDIO_RECORD_BUF_BYTE_CNTR_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x100C)
+
+/*SPDIF */
+#define MV_AUDIO_SPDIF_REC_GEN_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x2004)
+#define MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG(unit)	(MV_AUDIO_REGS_BASE(unit) + 0x2008)
+#define MV_AUDIO_SPDIF_REC_CH_STATUS_LEFT_REG(unit, ind)                  \
+						(MV_AUDIO_REGS_BASE(unit) + 0x2180 + ((ind) << 2))
+#define MV_AUDIO_SPDIF_REC_CH_STATUS_RIGHT_REG(unit, ind)                 \
+						(MV_AUDIO_REGS_BASE(unit) + 0x21a0 + ((ind) << 2))
+#define MV_AUDIO_SPDIF_REC_USR_BITS_LEFT_REG(unit, ind)                   \
+						(MV_AUDIO_REGS_BASE(unit) + 0x21c0 + ((ind) << 2))
+#define MV_AUDIO_SPDIF_REC_USR_BITS_RIGHT_REG(unit, ind)                  \
+						(MV_AUDIO_REGS_BASE(unit) + 0x21e0 + ((ind) << 2))
+
+/*I2S*/
+#define MV_AUDIO_I2S_REC_CTRL_REG(unit)		(MV_AUDIO_REGS_BASE(unit) + 0x2408)
+
+/* MV_AUDIO_RECORD_CTRL_REG*/
+#define ARCR_RECORD_SAMPLE_SIZE_OFFS   	  	0
+#define ARCR_RECORD_SAMPLE_SIZE_MASK   	  	(0x7 << ARCR_RECORD_SAMPLE_SIZE_OFFS)
+
+#define ARCR_RECORDED_MONO_CHNL_OFFS   	  	3
+#define ARCR_RECORDED_MONO_CHNL_MASK   	  	(0x1 << ARCR_RECORDED_MONO_CHNL_OFFS)
+
+#define ARCR_RECORD_MONO_OFFS		   	4
+#define ARCR_RECORD_MONO_MASK		   	(0x1 << ARCR_RECORD_MONO_OFFS)
+
+#define ARCR_RECORD_BURST_SIZE_OFFS	   	5
+#define ARCR_RECORD_BURST_SIZE_MASK	   	(0x3 << ARCR_RECORD_BURST_SIZE_OFFS)
+
+#define ARCR_RECORD_MUTE_OFFS		   	8
+#define ARCR_RECORD_MUTE_MASK		   	(0x1 << ARCR_RECORD_MUTE_OFFS)
+
+#define ARCR_RECORD_PAUSE_OFFS		   	9
+#define ARCR_RECORD_PAUSE_MASK		   	(0x1 << ARCR_RECORD_PAUSE_OFFS)
+
+#define ARCR_RECORD_I2S_EN_OFFS		   	10
+#define ARCR_RECORD_I2S_EN_MASK		   	(0x1 << ARCR_RECORD_I2S_EN_OFFS)
+
+#define ARCR_RECORD_SPDIF_EN_OFFS	   	11
+#define ARCR_RECORD_SPDIF_EN_MASK	   	(0x1 << ARCR_RECORD_SPDIF_EN_OFFS)
+
+/* MV_AUDIO_SPDIF_REC_GEN_REG*/
+#define ASRGR_CORE_CLK_FREQ_OFFS		1
+#define ASRGR_CORE_CLK_FREQ_MASK		(0x3 << ASRGR_CORE_CLK_FREQ_OFFS)
+#define ASRGR_CORE_CLK_FREQ_133MHZ		(0x0 << ASRGR_CORE_CLK_FREQ_OFFS)
+#define ASRGR_CORE_CLK_FREQ_150MHZ		(0x1 << ASRGR_CORE_CLK_FREQ_OFFS)
+#define ASRGR_CORE_CLK_FREQ_166MHZ		(0x2 << ASRGR_CORE_CLK_FREQ_OFFS)
+#define ASRGR_CORE_CLK_FREQ_200MHZ		(0x3 << ASRGR_CORE_CLK_FREQ_OFFS)
+
+#define ASRGR_VALID_PCM_INFO_OFFS		7
+#define ASRGR_VALID_PCM_INFO_MASK		(0x1 << ASRGR_VALID_PCM_INFO_OFFS)
+
+#define ASRGR_SAMPLE_FREQ_OFFS			8
+#define ASRGR_SAMPLE_FREQ_MASK			(0xf << ASRGR_SAMPLE_FREQ_OFFS)
+
+#define ASRGR_NON_PCM_OFFS			14
+#define ASRGR_NON_PCM_MASK			(1 << ASRGR_NON_PCM_OFFS)
+
+/* MV_AUDIO_I2S_REC_CTRL_REG*/
+#define AIRCR_I2S_RECORD_JUSTF_OFFS		26
+#define AIRCR_I2S_RECORD_JUSTF_MASK		(0xf << AIRCR_I2S_RECORD_JUSTF_OFFS)
+
+#define AIRCR_I2S_SAMPLE_SIZE_OFFS		30
+#define AIRCR_I2S_SAMPLE_SIZE_MASK		(0x3 << AIRCR_I2S_SAMPLE_SIZE_OFFS)
+
+/*
+** Address decoding related.
+*/
+
+#define MV_AUDIO_MAX_ADDR_DECODE_WIN 		2
+#define MV_AUDIO_RECORD_WIN_NUM			0
+#define MV_AUDIO_PLAYBACK_WIN_NUM		1
+
+#define MV_AUDIO_WIN_CTRL_REG(unit, win)	(MV_AUDIO_REGS_BASE(unit) + 0xA04 + ((win)<<3))
+#define MV_AUDIO_WIN_BASE_REG(unit, win)	(MV_AUDIO_REGS_BASE(unit) + 0xA00 + ((win)<<3))
+
+#define MV_AUDIO_RECORD_WIN_CTRL_REG(unit)	MV_AUDIO_WIN_CTRL_REG(unit, MV_AUDIO_RECORD_WIN_NUM)
+#define MV_AUDIO_RECORD_WIN_BASE_REG(unit)	MV_AUDIO_WIN_BASE_REG(unit, MV_AUDIO_RECORD_WIN_NUM)
+#define MV_AUDIO_PLAYBACK_WIN_CTRL_REG(unit)	MV_AUDIO_WIN_CTRL_REG(unit, MV_AUDIO_PLAYBACK_WIN_NUM)
+#define MV_AUDIO_PLAYBACK_WIN_BASE_REG(unit)	MV_AUDIO_WIN_BASE_REG(unit, MV_AUDIO_PLAYBACK_WIN_NUM)
+
+/* BITs in Windows 0-3 Control and Base Registers */
+#define MV_AUDIO_WIN_ENABLE_BIT               0
+#define MV_AUDIO_WIN_ENABLE_MASK              (1<<MV_AUDIO_WIN_ENABLE_BIT)
+
+#define MV_AUDIO_WIN_TARGET_OFFSET            4
+#define MV_AUDIO_WIN_TARGET_MASK              (0xF<<MV_AUDIO_WIN_TARGET_OFFSET)
+
+#define MV_AUDIO_WIN_ATTR_OFFSET              8
+#define MV_AUDIO_WIN_ATTR_MASK                (0xFF<<MV_AUDIO_WIN_ATTR_OFFSET)
+
+#define MV_AUDIO_WIN_SIZE_OFFSET              16
+#define MV_AUDIO_WIN_SIZE_MASK                (0xFFFF<<MV_AUDIO_WIN_SIZE_OFFSET)
+
+#define MV_AUDIO_WIN_BASE_OFFSET              16
+#define MV_AUDIO_WIN_BASE_MASK                (0xFFFF<<MV_AUDIO_WIN_BASE_OFFSET)
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __INCMVAudioRegsH */
diff --git a/arch/arm/plat-feroceon/mv_hal/audio/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/audio/mvCompVer.txt
new file mode 100755
index 0000000..3afa556
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/audio/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.3
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAes.h b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAes.h
new file mode 100755
index 0000000..f41acb0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAes.h
@@ -0,0 +1,70 @@
+/* mvAes.h   v2.0   August '99
+* Reference ANSI C code
+*/
+
+/*  AES Cipher header file for ANSI C Submissions
+      Lawrence E. Bassham III
+      Computer Security Division
+      National Institute of Standards and Technology
+
+    April 15, 1998
+
+    This sample is to assist implementers developing to the Cryptographic
+	API Profile for AES Candidate Algorithm Submissions.  Please consult this
+	document as a cross-reference.
+
+    ANY CHANGES, WHERE APPROPRIATE, TO INFORMATION PROVIDED IN THIS FILE
+	MUST BE DOCUMENTED.  CHANGES ARE ONLY APPROPRIATE WHERE SPECIFIED WITH
+	THE STRING "CHANGE POSSIBLE".  FUNCTION CALLS AND THEIR PARAMETERS CANNOT
+	BE CHANGED.  STRUCTURES CAN BE ALTERED TO ALLOW IMPLEMENTERS TO INCLUDE
+	IMPLEMENTATION SPECIFIC INFORMATION.
+*/
+
+/*  Includes:
+	Standard include files
+*/
+
+#ifndef __mvAes_h__
+#define __mvAes_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvOs.h"
+
+/*  Error Codes - CHANGE POSSIBLE: inclusion of additional error codes  */
+
+/*  Key direction is invalid, e.g., unknown value */
+#define     AES_BAD_KEY_DIR        -1
+
+/*  Key material not of correct length */
+#define     AES_BAD_KEY_MAT        -2
+
+/*  Key passed is not valid  */
+#define     AES_BAD_KEY_INSTANCE   -3
+
+/*  Params struct passed to cipherInit invalid */
+#define     AES_BAD_CIPHER_MODE    -4
+
+/*  Cipher in wrong state (e.g., not initialized) */
+#define     AES_BAD_CIPHER_STATE   -5
+
+#define     AES_BAD_CIPHER_INSTANCE   -7
+
+/*  Function protoypes  */
+/*  CHANGED: makeKey(): parameter blockLen added
+	this parameter is absolutely necessary if you want to
+	setup the round keys in a variable block length setting
+	cipherInit(): parameter blockLen added (for obvious reasons)
+ */
+	int aesMakeKey(MV_U8 *expandedKey, MV_U8 *keyMaterial, int keyLen, int blockLen);
+	int aesBlockEncrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen,
+			       MV_U32 *plain, int numBlocks, MV_U32 *cipher);
+	int aesBlockDecrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen,
+			       MV_U32 *plain, int numBlocks, MV_U32 *cipher);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesAlg.c b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesAlg.c
new file mode 100755
index 0000000..de62cc3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesAlg.c
@@ -0,0 +1,341 @@
+/* rijndael-alg-ref.c   v2.0   August '99
+ * Reference ANSI C code
+ * authors: Paulo Barreto
+ *          Vincent Rijmen, K.U.Leuven
+ *
+ * This code is placed in the public domain.
+ */
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvAesAlg.h"
+#include "mvAesBoxes.dat"
+
+MV_U8 mul1(MV_U8 aa, MV_U8 bb);
+void KeyAddition(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC], MV_U8 BC);
+void ShiftRow128Enc(MV_U8 a[4][MAXBC]);
+void ShiftRow128Dec(MV_U8 a[4][MAXBC]);
+void Substitution(MV_U8 a[4][MAXBC], MV_U8 box[256]);
+void MixColumn(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC]);
+void InvMixColumn(MV_U8 a[4][MAXBC]);
+
+#define mul(aa, bb) (mask[bb] & Alogtable[aa + Logtable[bb]])
+
+MV_U8 mul1(MV_U8 aa, MV_U8 bb)
+{
+	return mask[bb] & Alogtable[aa + Logtable[bb]];
+}
+
+void KeyAddition(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC], MV_U8 BC)
+{
+	/* Exor corresponding text input and round key input bytes
+	 */
+	((MV_U32 *) (&(a[0][0])))[0] ^= ((MV_U32 *) (&(rk[0][0])))[0];
+	((MV_U32 *) (&(a[1][0])))[0] ^= ((MV_U32 *) (&(rk[1][0])))[0];
+	((MV_U32 *) (&(a[2][0])))[0] ^= ((MV_U32 *) (&(rk[2][0])))[0];
+	((MV_U32 *) (&(a[3][0])))[0] ^= ((MV_U32 *) (&(rk[3][0])))[0];
+
+}
+
+void ShiftRow128Enc(MV_U8 a[4][MAXBC])
+{
+	/* Row 0 remains unchanged
+	 * The other three rows are shifted a variable amount
+	 */
+	MV_U8 tmp[MAXBC];
+
+	tmp[0] = a[1][1];
+	tmp[1] = a[1][2];
+	tmp[2] = a[1][3];
+	tmp[3] = a[1][0];
+
+	((MV_U32 *) (&(a[1][0])))[0] = ((MV_U32 *) (&(tmp[0])))[0];
+	/*
+	   a[1][0] = tmp[0];
+	   a[1][1] = tmp[1];
+	   a[1][2] = tmp[2];
+	   a[1][3] = tmp[3];
+	 */
+	tmp[0] = a[2][2];
+	tmp[1] = a[2][3];
+	tmp[2] = a[2][0];
+	tmp[3] = a[2][1];
+
+	((MV_U32 *) (&(a[2][0])))[0] = ((MV_U32 *) (&(tmp[0])))[0];
+	/*
+	   a[2][0] = tmp[0];
+	   a[2][1] = tmp[1];
+	   a[2][2] = tmp[2];
+	   a[2][3] = tmp[3];
+	 */
+	tmp[0] = a[3][3];
+	tmp[1] = a[3][0];
+	tmp[2] = a[3][1];
+	tmp[3] = a[3][2];
+
+	((MV_U32 *) (&(a[3][0])))[0] = ((MV_U32 *) (&(tmp[0])))[0];
+	/*
+	   a[3][0] = tmp[0];
+	   a[3][1] = tmp[1];
+	   a[3][2] = tmp[2];
+	   a[3][3] = tmp[3];
+	 */
+}
+
+void ShiftRow128Dec(MV_U8 a[4][MAXBC])
+{
+	/* Row 0 remains unchanged
+	 * The other three rows are shifted a variable amount
+	 */
+	MV_U8 tmp[MAXBC];
+
+	tmp[0] = a[1][3];
+	tmp[1] = a[1][0];
+	tmp[2] = a[1][1];
+	tmp[3] = a[1][2];
+
+	((MV_U32 *) (&(a[1][0])))[0] = ((MV_U32 *) (&(tmp[0])))[0];
+	/*
+	   a[1][0] = tmp[0];
+	   a[1][1] = tmp[1];
+	   a[1][2] = tmp[2];
+	   a[1][3] = tmp[3];
+	 */
+
+	tmp[0] = a[2][2];
+	tmp[1] = a[2][3];
+	tmp[2] = a[2][0];
+	tmp[3] = a[2][1];
+
+	((MV_U32 *) (&(a[2][0])))[0] = ((MV_U32 *) (&(tmp[0])))[0];
+	/*
+	   a[2][0] = tmp[0];
+	   a[2][1] = tmp[1];
+	   a[2][2] = tmp[2];
+	   a[2][3] = tmp[3];
+	 */
+
+	tmp[0] = a[3][1];
+	tmp[1] = a[3][2];
+	tmp[2] = a[3][3];
+	tmp[3] = a[3][0];
+
+	((MV_U32 *) (&(a[3][0])))[0] = ((MV_U32 *) (&(tmp[0])))[0];
+	/*
+	   a[3][0] = tmp[0];
+	   a[3][1] = tmp[1];
+	   a[3][2] = tmp[2];
+	   a[3][3] = tmp[3];
+	 */
+}
+
+void Substitution(MV_U8 a[4][MAXBC], MV_U8 box[256])
+{
+	/* Replace every byte of the input by the byte at that place
+	 * in the nonlinear S-box
+	 */
+	int i, j;
+
+	for (i = 0; i < 4; i++)
+		for (j = 0; j < 4; j++)
+			a[i][j] = box[a[i][j]];
+}
+
+void MixColumn(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC])
+{
+	/* Mix the four bytes of every column in a linear way
+	 */
+	MV_U8 b[4][MAXBC];
+	int i, j;
+
+	for (j = 0; j < 4; j++) {
+		b[0][j] = mul(25, a[0][j]) ^ mul(1, a[1][j]) ^ a[2][j] ^ a[3][j];
+		b[1][j] = mul(25, a[1][j]) ^ mul(1, a[2][j]) ^ a[3][j] ^ a[0][j];
+		b[2][j] = mul(25, a[2][j]) ^ mul(1, a[3][j]) ^ a[0][j] ^ a[1][j];
+		b[3][j] = mul(25, a[3][j]) ^ mul(1, a[0][j]) ^ a[1][j] ^ a[2][j];
+	}
+	for (i = 0; i < 4; i++)
+		/*for(j = 0; j < BC; j++) a[i][j] = b[i][j]; */
+		((MV_U32 *)(&(a[i][0])))[0] = ((MV_U32*)(&(b[i][0])))[0] ^ ((MV_U32*)(&(rk[i][0])))[0];;
+}
+
+void InvMixColumn(MV_U8 a[4][MAXBC])
+{
+	/* Mix the four bytes of every column in a linear way
+	 * This is the opposite operation of Mixcolumn
+	 */
+	MV_U8 b[4][MAXBC];
+	int i, j;
+
+	for (j = 0; j < 4; j++) {
+		b[0][j] = mul(223, a[0][j]) ^ mul(104, a[1][j]) ^ mul(238, a[2][j]) ^ mul(199, a[3][j]);
+		b[1][j] = mul(223, a[1][j]) ^ mul(104, a[2][j]) ^ mul(238, a[3][j]) ^ mul(199, a[0][j]);
+		b[2][j] = mul(223, a[2][j]) ^ mul(104, a[3][j]) ^ mul(238, a[0][j]) ^ mul(199, a[1][j]);
+		b[3][j] = mul(223, a[3][j]) ^ mul(104, a[0][j]) ^ mul(238, a[1][j]) ^ mul(199, a[2][j]);
+	}
+	for (i = 0; i < 4; i++)
+		/*for(j = 0; j < BC; j++) a[i][j] = b[i][j]; */
+		((MV_U32 *) (&(a[i][0])))[0] = ((MV_U32 *) (&(b[i][0])))[0];
+}
+
+int rijndaelKeySched(MV_U8 k[4][MAXKC], int keyBits, int blockBits, MV_U8 W[MAXROUNDS + 1][4][MAXBC])
+{
+	/* Calculate the necessary round keys
+	 * The number of calculations depends on keyBits and blockBits
+	 */
+	int KC, BC, ROUNDS;
+	int i, j, t, rconpointer = 0;
+	MV_U8 tk[4][MAXKC];
+
+	switch (keyBits) {
+	case 128:
+		KC = 4;
+		break;
+	case 192:
+		KC = 6;
+		break;
+	case 256:
+		KC = 8;
+		break;
+	default:
+		return (-1);
+	}
+
+	switch (blockBits) {
+	case 128:
+		BC = 4;
+		break;
+	case 192:
+		BC = 6;
+		break;
+	case 256:
+		BC = 8;
+		break;
+	default:
+		return (-2);
+	}
+
+	switch (keyBits >= blockBits ? keyBits : blockBits) {
+	case 128:
+		ROUNDS = 10;
+		break;
+	case 192:
+		ROUNDS = 12;
+		break;
+	case 256:
+		ROUNDS = 14;
+		break;
+	default:
+		return (-3);	/* this cannot happen */
+	}
+
+	for (j = 0; j < KC; j++)
+		for (i = 0; i < 4; i++)
+			tk[i][j] = k[i][j];
+	t = 0;
+	/* copy values into round key array */
+	for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++)
+		for (i = 0; i < 4; i++)
+			W[t / BC][i][t % BC] = tk[i][j];
+
+	while (t < (ROUNDS + 1) * BC) {	/* while not enough round key material calculated */
+		/* calculate new values */
+		for (i = 0; i < 4; i++)
+			tk[i][0] ^= S[tk[(i + 1) % 4][KC - 1]];
+		tk[0][0] ^= rcon[rconpointer++];
+
+		if (KC != 8)
+			for (j = 1; j < KC; j++)
+				for (i = 0; i < 4; i++)
+					tk[i][j] ^= tk[i][j - 1];
+		else {
+			for (j = 1; j < KC / 2; j++)
+				for (i = 0; i < 4; i++)
+					tk[i][j] ^= tk[i][j - 1];
+			for (i = 0; i < 4; i++)
+				tk[i][KC / 2] ^= S[tk[i][KC / 2 - 1]];
+			for (j = KC / 2 + 1; j < KC; j++)
+				for (i = 0; i < 4; i++)
+					tk[i][j] ^= tk[i][j - 1];
+		}
+		/* copy values into round key array */
+		for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++)
+			for (i = 0; i < 4; i++)
+				W[t / BC][i][t % BC] = tk[i][j];
+	}
+
+	return 0;
+}
+
+int rijndaelEncrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS + 1][4][MAXBC], int rounds)
+{
+	/* Encryption of one block.
+	 */
+	int r, BC, ROUNDS;
+
+	BC = 4;
+	ROUNDS = rounds;
+
+	/* begin with a key addition
+	 */
+
+	KeyAddition(a, rk[0], BC);
+
+	/* ROUNDS-1 ordinary rounds
+	 */
+	for (r = 1; r < ROUNDS; r++) {
+		Substitution(a, S);
+		ShiftRow128Enc(a);
+		MixColumn(a, rk[r]);
+		/*KeyAddition(a,rk[r],BC); */
+	}
+
+	/* Last round is special: there is no MixColumn
+	 */
+	Substitution(a, S);
+	ShiftRow128Enc(a);
+	KeyAddition(a, rk[ROUNDS], BC);
+
+	return 0;
+}
+
+int rijndaelDecrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS + 1][4][MAXBC], int rounds)
+{
+	int r, BC, ROUNDS;
+
+	BC = 4;
+	ROUNDS = rounds;
+
+	/* To decrypt: apply the inverse operations of the encrypt routine,
+	 *             in opposite order
+	 *
+	 * (KeyAddition is an involution: it 's equal to its inverse)
+	 * (the inverse of Substitution with table S is Substitution with the inverse table of S)
+	 * (the inverse of Shiftrow is Shiftrow over a suitable distance)
+	 */
+
+	/* First the special round:
+	 *   without InvMixColumn
+	 *   with extra KeyAddition
+	 */
+	KeyAddition(a, rk[ROUNDS], BC);
+	ShiftRow128Dec(a);
+	Substitution(a, Si);
+
+	/* ROUNDS-1 ordinary rounds
+	 */
+	for (r = ROUNDS - 1; r > 0; r--) {
+		KeyAddition(a, rk[r], BC);
+		InvMixColumn(a);
+		ShiftRow128Dec(a);
+		Substitution(a, Si);
+
+	}
+
+	/* End with the extra key addition
+	 */
+
+	KeyAddition(a, rk[0], BC);
+
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesAlg.h b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesAlg.h
new file mode 100755
index 0000000..864cfc4
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesAlg.h
@@ -0,0 +1,24 @@
+/* rijndael-alg-ref.h   v2.0   August '99
+ * Reference ANSI C code
+ * authors: Paulo Barreto
+ *          Vincent Rijmen, K.U.Leuven
+ */
+#ifndef __RIJNDAEL_ALG_H
+#define __RIJNDAEL_ALG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAXBC				(128/32)
+#define MAXKC				(256/32)
+#define MAXROUNDS			14
+
+	int rijndaelKeySched(MV_U8 k[4][MAXKC], int keyBits, int blockBits, MV_U8 rk[MAXROUNDS + 1][4][MAXBC]);
+	int rijndaelEncrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS + 1][4][MAXBC], int rounds);
+	int rijndaelDecrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS + 1][4][MAXBC], int rounds);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __RIJNDAEL_ALG_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesApi.c b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesApi.c
new file mode 100755
index 0000000..c5915d9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesApi.c
@@ -0,0 +1,270 @@
+/* rijndael-api-ref.c   v2.1   April 2000
+ * Reference ANSI C code
+ * authors: v2.0 Paulo Barreto
+ *               Vincent Rijmen, K.U.Leuven
+ *          v2.1 Vincent Rijmen, K.U.Leuven
+ *
+ * This code is placed in the public domain.
+ */
+
+#include "mvCommon.h"
+#include "mvOs.h"
+
+#include "mvAes.h"
+#include "mvAesAlg.h"
+
+/*  Defines:
+	Add any additional defines you need
+*/
+
+#define     MODE_ECB        1	/*  Are we ciphering in ECB mode?   */
+#define     MODE_CBC        2	/*  Are we ciphering in CBC mode?   */
+#define     MODE_CFB1       3	/*  Are we ciphering in 1-bit CFB mode? */
+
+int aesMakeKey(MV_U8 *expandedKey, MV_U8 *keyMaterial, int keyLen, int blockLen)
+{
+	MV_U8 W[MAXROUNDS + 1][4][MAXBC];
+	MV_U8 k[4][MAXKC];
+	MV_U8 j;
+	int i, rounds, KC;
+
+	if (expandedKey == NULL)
+		return AES_BAD_KEY_INSTANCE;
+
+	if (!((keyLen == 128) || (keyLen == 192) || (keyLen == 256)))
+		return AES_BAD_KEY_MAT;
+
+	if (keyMaterial == NULL)
+		return AES_BAD_KEY_MAT;
+
+	/* initialize key schedule: */
+	for (i = 0; i < keyLen / 8; i++) {
+		j = keyMaterial[i];
+		k[i % 4][i / 4] = j;
+	}
+
+	rijndaelKeySched(k, keyLen, blockLen, W);
+#ifdef MV_AES_DEBUG
+	{
+		MV_U8 *pW = &W[0][0][0];
+		int x;
+
+		mvOsPrintf("Expended Key: size = %d\n", sizeof(W));
+		for (i = 0; i < sizeof(W); i++)
+			mvOsPrintf("%02x ", pW[i]);
+
+		for (i = 0; i < MAXROUNDS + 1; i++) {
+			mvOsPrintf("\n Round #%02d: ", i);
+			for (x = 0; x < MAXBC; x++)
+				mvOsPrintf("%02x%02x%02x%02x ", W[i][0][x], W[i][1][x], W[i][2][x], W[i][3][x]);
+			mvOsPrintf("\n");
+		}
+	}
+#endif /* MV_AES_DEBUG */
+	switch (keyLen) {
+	case 128:
+		rounds = 10;
+		KC = 4;
+		break;
+	case 192:
+		rounds = 12;
+		KC = 6;
+		break;
+	case 256:
+		rounds = 14;
+		KC = 8;
+		break;
+	default:
+		return (-1);
+	}
+
+	for (i = 0; i < MAXBC; i++)
+		for (j = 0; j < 4; j++)
+			expandedKey[i * 4 + j] = W[rounds][j][i];
+
+	for (; i < KC; i++)
+		for (j = 0; j < 4; j++)
+			expandedKey[i * 4 + j] = W[rounds - 1][j][i + MAXBC - KC];
+
+	return 0;
+}
+
+int aesBlockEncrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen,
+		       MV_U32 *plain, int numBlocks, MV_U32 *cipher)
+{
+	int i, j, t;
+	MV_U8 block[4][MAXBC];
+	int rounds;
+	char *input, *outBuffer;
+
+	input = (char *)plain;
+	outBuffer = (char *)cipher;
+
+	/* check parameter consistency: */
+	if ((expandedKey == NULL) || ((keyLen != 128) && (keyLen != 192) && (keyLen != 256)))
+		return AES_BAD_KEY_MAT;
+
+	if ((mode != MODE_ECB && mode != MODE_CBC))
+		return AES_BAD_CIPHER_STATE;
+
+	switch (keyLen) {
+	case 128:
+		rounds = 10;
+		break;
+	case 192:
+		rounds = 12;
+		break;
+	case 256:
+		rounds = 14;
+		break;
+	default:
+		return (-3);	/* this cannot happen */
+	}
+
+	switch (mode) {
+	case MODE_ECB:
+		for (i = 0; i < numBlocks; i++) {
+			for (j = 0; j < 4; j++) {
+				for (t = 0; t < 4; t++)
+					/* parse input stream into rectangular array */
+					block[t][j] = input[16 * i + 4 * j + t] & 0xFF;
+			}
+			rijndaelEncrypt128(block, (MV_U8(*)[4][MAXBC]) expandedKey, rounds);
+			for (j = 0; j < 4; j++) {
+				/* parse rectangular array into output ciphertext bytes */
+				for (t = 0; t < 4; t++)
+					outBuffer[16 * i + 4 * j + t] = (MV_U8) block[t][j];
+			}
+		}
+		break;
+
+	case MODE_CBC:
+		for (j = 0; j < 4; j++) {
+			for (t = 0; t < 4; t++)
+				/* parse initial value into rectangular array */
+				block[t][j] = IV[t + 4 * j] & 0xFF;
+		}
+		for (i = 0; i < numBlocks; i++) {
+			for (j = 0; j < 4; j++) {
+				for (t = 0; t < 4; t++)
+					/* parse input stream into rectangular array and exor with
+					   IV or the previous ciphertext */
+					block[t][j] ^= input[16 * i + 4 * j + t] & 0xFF;
+			}
+			rijndaelEncrypt128(block, (MV_U8(*)[4][MAXBC]) expandedKey, rounds);
+			for (j = 0; j < 4; j++) {
+				/* parse rectangular array into output ciphertext bytes */
+				for (t = 0; t < 4; t++)
+					outBuffer[16 * i + 4 * j + t] = (MV_U8) block[t][j];
+			}
+		}
+		break;
+
+	default:
+		return AES_BAD_CIPHER_STATE;
+	}
+
+	return 0;
+}
+
+int aesBlockDecrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen,
+		       MV_U32 *srcData, int numBlocks, MV_U32 *dstData)
+{
+	int i, j, t;
+	MV_U8 block[4][MAXBC];
+	MV_U8 iv[4][MAXBC];
+	int rounds;
+	char *input, *outBuffer;
+
+	input = (char *)srcData;
+	outBuffer = (char *)dstData;
+
+	if (expandedKey == NULL)
+		return AES_BAD_KEY_MAT;
+
+	/* check parameter consistency: */
+	if (keyLen != 128 && keyLen != 192 && keyLen != 256)
+		return AES_BAD_KEY_MAT;
+
+	if ((mode != MODE_ECB && mode != MODE_CBC))
+		return AES_BAD_CIPHER_STATE;
+
+	switch (keyLen) {
+	case 128:
+		rounds = 10;
+		break;
+	case 192:
+		rounds = 12;
+		break;
+	case 256:
+		rounds = 14;
+		break;
+	default:
+		return (-3);	/* this cannot happen */
+	}
+
+	switch (mode) {
+	case MODE_ECB:
+		for (i = 0; i < numBlocks; i++) {
+			for (j = 0; j < 4; j++) {
+				for (t = 0; t < 4; t++) {
+					/* parse input stream into rectangular array */
+					block[t][j] = input[16 * i + 4 * j + t] & 0xFF;
+				}
+			}
+			rijndaelDecrypt128(block, (MV_U8(*)[4][MAXBC]) expandedKey, rounds);
+			for (j = 0; j < 4; j++) {
+				/* parse rectangular array into output ciphertext bytes */
+				for (t = 0; t < 4; t++)
+					outBuffer[16 * i + 4 * j + t] = (MV_U8) block[t][j];
+			}
+		}
+		break;
+
+	case MODE_CBC:
+		/* first block */
+		for (j = 0; j < 4; j++) {
+			for (t = 0; t < 4; t++) {
+				/* parse input stream into rectangular array */
+				block[t][j] = input[4 * j + t] & 0xFF;
+				iv[t][j] = block[t][j];
+			}
+		}
+		rijndaelDecrypt128(block, (MV_U8(*)[4][MAXBC]) expandedKey, rounds);
+
+		for (j = 0; j < 4; j++) {
+			/* exor the IV and parse rectangular array into output ciphertext bytes */
+			for (t = 0; t < 4; t++) {
+				outBuffer[4 * j + t] = (MV_U8) (block[t][j] ^ IV[t + 4 * j]);
+				IV[t + 4 * j] = iv[t][j];
+			}
+		}
+
+		/* next blocks */
+		for (i = 1; i < numBlocks; i++) {
+			for (j = 0; j < 4; j++) {
+				for (t = 0; t < 4; t++) {
+					/* parse input stream into rectangular array */
+					iv[t][j] = input[16 * i + 4 * j + t] & 0xFF;
+					block[t][j] = iv[t][j];
+				}
+			}
+			rijndaelDecrypt128(block, (MV_U8(*)[4][MAXBC]) expandedKey, rounds);
+
+			for (j = 0; j < 4; j++) {
+				/* exor previous ciphertext block and parse rectangular array
+				   into output ciphertext bytes */
+				for (t = 0; t < 4; t++) {
+					outBuffer[16 * i + 4 * j + t] = (MV_U8) (block[t][j] ^ IV[t + 4 * j]);
+					IV[t + 4 * j] = iv[t][j];
+				}
+			}
+		}
+		break;
+
+	default:
+		return AES_BAD_CIPHER_STATE;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesBoxes.dat b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesBoxes.dat
new file mode 100755
index 0000000..f1cbab7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/AES/mvAesBoxes.dat
@@ -0,0 +1,125 @@
+static MV_U8 mask[256] = {
+	0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static MV_U8 Logtable[256] = {
+	0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
+	100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
+	125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
+	101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
+	150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
+	102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
+	126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
+	43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
+	175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
+	44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
+	127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
+	204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
+	151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
+	83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
+	68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
+	103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7,
+};
+
+static MV_U8 Alogtable[512] = {
+	1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+	95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+	229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+	83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+	76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+	131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+	181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+	254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+	251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+	195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+	159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+	155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+	252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+	69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+	18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+	57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1,
+
+	3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+	95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+	229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+	83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+	76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+	131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+	181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+	254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+	251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+	195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+	159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+	155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+	252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+	69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+	18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+	57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1,
+
+};
+
+static MV_U8 S[256] = {
+	99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+	202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+	183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+	4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+	9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+	83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+	208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+	81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+	205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+	96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+	224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+	231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+	186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+	112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+	225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+	140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22,
+};
+
+static MV_U8 Si[256] = {
+	82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
+	124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
+	84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
+	8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
+	114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
+	108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
+	144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
+	208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
+	58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+	150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
+	71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
+	252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
+	31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
+	96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
+	160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+	23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125,
+};
+
+/*
+static MV_U8 iG[4][4] = {
+{0x0e, 0x09, 0x0d, 0x0b},
+{0x0b, 0x0e, 0x09, 0x0d},
+{0x0d, 0x0b, 0x0e, 0x09},
+{0x09, 0x0d, 0x0b, 0x0e},
+};
+*/
+static MV_U32 rcon[30] = {
+	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
+	    0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91,
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCesa.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesa.c
new file mode 100755
index 0000000..dc021bb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesa.c
@@ -0,0 +1,3024 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysCesaConfig.h"
+#include "mvCesaRegs.h"
+#include "mvCesa.h"
+#include "AES/mvAes.h"
+#include "mvMD5.h"
+#include "mvSHA1.h"
+#include "mvSHA256.h"
+
+#undef CESA_DEBUG
+
+/********** Global variables **********/
+
+/*  If request size is more than MV_CESA_MAX_BUF_SIZE the
+ *  request is processed as fragmented request.
+ */
+
+MV_CESA_STATS cesaStats;
+MV_16 cesaLastSid[MV_CESA_CHANNELS];
+MV_CESA_SA **pCesaSAD = NULL;
+MV_U32 cesaMaxSA = 0;
+MV_CESA_REQ *pCesaReqFirst[MV_CESA_CHANNELS];
+MV_CESA_REQ *pCesaReqLast[MV_CESA_CHANNELS];
+MV_CESA_REQ *pCesaReqEmpty[MV_CESA_CHANNELS];
+MV_CESA_REQ *pCesaReqProcess[MV_CESA_CHANNELS];
+int cesaQueueDepth[MV_CESA_CHANNELS];
+int cesaReqResources[MV_CESA_CHANNELS];
+
+MV_CESA_SRAM_MAP *cesaSramVirtPtr[MV_CESA_CHANNELS];
+void *cesaOsHandle = NULL;
+MV_U16 ctrlModel;
+MV_U8 ctrlRev;
+MV_U32 sha2CmdVal;
+
+#ifdef MV_CESA_CHAIN_MODE
+
+MV_U32 cesaChainLength[MV_CESA_CHANNELS];
+int chainReqNum[MV_CESA_CHANNELS];
+MV_U32 chainIndex[MV_CESA_CHANNELS];
+MV_CESA_REQ *pNextActiveChain[MV_CESA_CHANNELS];
+MV_CESA_REQ *pEndCurrChain[MV_CESA_CHANNELS];
+MV_BOOL isFirstReq[MV_CESA_CHANNELS];
+
+#endif /* MV_CESA_CHAIN_MODE */
+
+static MV_CESA_HAL_DATA cesaHalData;
+
+static INLINE MV_U8 *mvCesaSramAddrGet(MV_U8 chan)
+{
+	return (MV_U8 *) cesaHalData.sramPhysBase[chan];
+}
+
+static INLINE MV_ULONG mvCesaSramVirtToPhys(MV_U8 chan, void *pDev, MV_U8 *pSramVirt)
+{
+	return (MV_ULONG) (pSramVirt - cesaHalData.sramVirtBase[chan]) + cesaHalData.sramPhysBase[chan];
+}
+
+/* Internal Function prototypes */
+
+static INLINE void mvCesaSramDescrBuild(MV_U8 chan, MV_U32 config, int frag,
+					int cryptoOffset, int ivOffset, int cryptoLength,
+					int macOffset, int digestOffset, int macLength, int macTotalLen,
+					MV_CESA_REQ *pCesaReq, MV_DMA_DESC *pDmaDesc);
+
+static INLINE void mvCesaSramSaUpdate(MV_U8 chan, short sid, MV_DMA_DESC *pDmaDesc);
+
+static INLINE int mvCesaDmaCopyPrepare(MV_U8 chan, MV_CESA_MBUF *pMbuf, MV_U8 *pSramBuf,
+				       MV_DMA_DESC *pDmaDesc, MV_BOOL isToMbuf,
+				       int offset, int copySize, MV_BOOL skipFlush);
+
+static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
+			    unsigned char innerIV[], unsigned char outerIV[]);
+
+static MV_STATUS mvCesaFragAuthComplete(MV_U8 chan, MV_CESA_REQ *pReq, MV_CESA_SA *pSA, int macDataSize);
+
+static MV_CESA_COMMAND *mvCesaCtrModeInit(void);
+
+static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd);
+static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd);
+static void mvCesaCtrModeFinish(MV_CESA_COMMAND *pCmd);
+
+static INLINE MV_STATUS mvCesaReqProcess(MV_U8 chan, MV_CESA_REQ *pReq);
+static MV_STATUS mvCesaFragReqProcess(MV_U8 chan, MV_CESA_REQ *pReq, MV_U8 frag);
+
+static INLINE MV_STATUS mvCesaParamCheck(MV_CESA_SA *pSA, MV_CESA_COMMAND *pCmd, MV_U8 *pFixOffset);
+static INLINE MV_STATUS mvCesaFragParamCheck(MV_U8 chan, MV_CESA_SA *pSA, MV_CESA_COMMAND *pCmd);
+
+static INLINE void mvCesaFragSizeFind(MV_CESA_SA *pSA, MV_CESA_REQ *pReq,
+				      int cryptoOffset, int macOffset,
+				      int *pCopySize, int *pCryptoDataSize, int *pMacDataSize);
+static MV_STATUS mvCesaMbufCacheUnmap(MV_CESA_MBUF *pMbuf, int offset, int size);
+static MV_STATUS mvCesaUpdateSADSize(MV_U32 size);
+
+/* Go to the next request in the request queue */
+static INLINE MV_CESA_REQ *MV_CESA_REQ_NEXT_PTR(MV_U8 chan, MV_CESA_REQ *pReq)
+{
+	if (pReq == pCesaReqLast[chan])
+		return pCesaReqFirst[chan];
+
+	return (pReq + 1);
+}
+
+/* Go to the previous request in the request queue */
+static INLINE MV_CESA_REQ *MV_CESA_REQ_PREV_PTR(MV_U8 chan, MV_CESA_REQ *pReq)
+{
+	if (pReq == pCesaReqFirst[chan])
+		return pCesaReqLast[chan];
+
+	return (pReq - 1);
+}
+
+static INLINE void mvCesaReqProcessStart(MV_U8 chan, MV_CESA_REQ *pReq)
+{
+	MV_32 frag;
+
+#ifdef MV_CESA_CHAIN_MODE
+	pReq->state = MV_CESA_CHAIN;
+#else
+	pReq->state = MV_CESA_PROCESS;
+#endif
+
+	cesaStats.startCount++;
+
+	if (pReq->fragMode == MV_CESA_FRAG_NONE) {
+		frag = 0;
+	} else {
+		frag = pReq->frags.nextFrag;
+		pReq->frags.nextFrag++;
+	}
+
+	/* Enable TDMA engine */
+	MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG(chan), 0);
+	MV_REG_WRITE(MV_CESA_TDMA_NEXT_DESC_PTR_REG(chan),
+		     (MV_U32) mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
+
+#if defined(MV_BRIDGE_SYNC_REORDER)
+	mvOsBridgeReorderWA();
+#endif
+
+	/* Start Accelerator */
+	/* For KW2/Z2, DSMP/Z1: Enable also bit[31] for SHA-2 support */
+	MV_REG_BIT_SET(MV_CESA_CMD_REG(chan), (MV_CESA_CMD_CHAN_ENABLE_MASK | sha2CmdVal));
+}
+
+/*******************************************************************************
+* mvCesaHalInit - Initialize the CESA driver
+*
+* DESCRIPTION:
+*       This function initialize the CESA driver.
+*       1) Session database
+*       2) Request queue
+*       4) DMA descriptor lists - one list per request. Each list
+*           has MV_CESA_MAX_DMA_DESC descriptors.
+*
+* INPUT:
+*       numOfSession    - maximum number of supported sessions
+*       queueDepth      - number of elements in the request queue.
+*	    osHandle	    - A handle used by the OS to allocate memory for the
+*			            module (Passed to the OS Services layer)
+*
+* RETURN:
+*       MV_OK           - Success
+*       MV_NO_RESOURCE  - Fail, can't allocate resources:
+*                         Session database, request queue,
+*                         DMA descriptors list, LRU cache database.
+*       MV_NOT_ALIGNED  - Sram base address is not 8 byte aligned.
+*
+*******************************************************************************/
+MV_STATUS mvCesaHalInit(int numOfSession, int queueDepth, void *osHandle, MV_CESA_HAL_DATA *halData)
+{
+	int i, req;
+	MV_U32 descOffsetReg, configReg;
+	MV_U8 chan;
+
+	cesaOsHandle = osHandle;
+	sha2CmdVal = 0;
+
+	mvOsPrintf("mvCesaInit: channels=%d, session=%d, queue=%d\n", MV_CESA_CHANNELS, numOfSession, queueDepth);
+
+	/* Create initial Session database */
+	pCesaSAD = mvOsMalloc(sizeof(MV_CESA_SA *) * numOfSession);
+	if (pCesaSAD == NULL) {
+		mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d SAs\n",
+			   sizeof(MV_CESA_SA *) * numOfSession, numOfSession);
+		mvCesaFinish();
+		return MV_NO_RESOURCE;
+	}
+	memset(pCesaSAD, 0, sizeof(MV_CESA_SA *) * numOfSession);
+	cesaMaxSA = numOfSession;
+
+	ctrlModel = halData->ctrlModel;
+	ctrlRev = halData->ctrlRev;
+
+	/* Initiliaze per channel resources */
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+
+		cesaSramVirtPtr[chan] = (MV_CESA_SRAM_MAP *) (halData->sramVirtBase[chan] + halData->sramOffset[chan]);
+
+		/* Create request queue */
+		pCesaReqFirst[chan] = mvOsMalloc(sizeof(MV_CESA_REQ) * queueDepth);
+		if (pCesaReqFirst[chan] == NULL) {
+			mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d requests\n",
+				   sizeof(MV_CESA_REQ) * queueDepth, queueDepth);
+			mvCesaFinish();
+			return MV_NO_RESOURCE;
+		}
+		memset(pCesaReqFirst[chan], 0, sizeof(MV_CESA_REQ) * queueDepth);
+		pCesaReqEmpty[chan] = pCesaReqFirst[chan];
+		pCesaReqLast[chan] = pCesaReqFirst[chan] + (queueDepth - 1);
+		pCesaReqProcess[chan] = pCesaReqEmpty[chan];
+		cesaQueueDepth[chan] = queueDepth;
+		cesaReqResources[chan] = queueDepth;
+		cesaLastSid[chan] = -1;
+#ifdef MV_CESA_CHAIN_MODE
+		cesaChainLength[chan] = MAX_CESA_CHAIN_LENGTH;
+		chainReqNum[chan] = 0;
+		chainIndex[chan] = 0;
+		pNextActiveChain[chan] = NULL;
+		pEndCurrChain[chan] = NULL;
+		isFirstReq[chan] = MV_TRUE;
+#endif
+
+		/* pSramBase must be 8 byte aligned */
+		if (MV_IS_NOT_ALIGN((MV_ULONG) cesaSramVirtPtr[chan], 8)) {
+			mvOsPrintf("mvCesaInit: pSramBase (%p) must be 8 byte aligned\n", cesaSramVirtPtr[chan]);
+			mvCesaFinish();
+			return MV_NOT_ALIGNED;
+		}
+
+		/* Clear registers */
+		MV_REG_WRITE(MV_CESA_CFG_REG(chan), 0);
+		MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+		MV_REG_WRITE(MV_CESA_ISR_MASK_REG(chan), 0);
+
+		/* Initialize DMA descriptor lists for all requests in Request queue */
+		descOffsetReg = configReg = 0;
+		for (req = 0; req < queueDepth; req++) {
+			int frag;
+			MV_CESA_REQ *pReq;
+			MV_DMA_DESC *pDmaDesc;
+
+			pReq = &pCesaReqFirst[chan][req];
+
+			pReq->cesaDescBuf.bufSize = sizeof(MV_CESA_DESC) * MV_CESA_MAX_REQ_FRAGS + CPU_D_CACHE_LINE_SIZE;
+
+			pReq->cesaDescBuf.bufVirtPtr = mvOsIoCachedMalloc(osHandle, pReq->cesaDescBuf.bufSize,
+							&pReq->cesaDescBuf.bufPhysAddr,
+							&pReq->cesaDescBuf.memHandle);
+			if (pReq->cesaDescBuf.bufVirtPtr == NULL) {
+				mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for CESA descriptors\n",
+						req, pReq->cesaDescBuf.bufSize);
+				mvCesaFinish();
+				return MV_NO_RESOURCE;
+			}
+			memset(pReq->cesaDescBuf.bufVirtPtr, 0, pReq->cesaDescBuf.bufSize);
+			pReq->pCesaDesc = (MV_CESA_DESC *) MV_ALIGN_UP((MV_ULONG) pReq->cesaDescBuf.bufVirtPtr,
+							CPU_D_CACHE_LINE_SIZE);
+
+			pReq->dmaDescBuf.bufSize = sizeof(MV_DMA_DESC) * MV_CESA_MAX_DMA_DESC * MV_CESA_MAX_REQ_FRAGS +
+							CPU_D_CACHE_LINE_SIZE;
+
+			pReq->dmaDescBuf.bufVirtPtr = mvOsIoCachedMalloc(osHandle, pReq->dmaDescBuf.bufSize,
+							&pReq->dmaDescBuf.bufPhysAddr, &pReq->dmaDescBuf.memHandle);
+
+			if (pReq->dmaDescBuf.bufVirtPtr == NULL) {
+				mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for DMA descriptor list\n",
+					req, pReq->dmaDescBuf.bufSize);
+				mvCesaFinish();
+				return MV_NO_RESOURCE;
+			}
+			memset(pReq->dmaDescBuf.bufVirtPtr, 0, pReq->dmaDescBuf.bufSize);
+			pDmaDesc = (MV_DMA_DESC *) MV_ALIGN_UP((MV_ULONG) pReq->dmaDescBuf.bufVirtPtr,
+						CPU_D_CACHE_LINE_SIZE);
+
+			for (frag = 0; frag < MV_CESA_MAX_REQ_FRAGS; frag++) {
+				MV_CESA_DMA *pDma = &pReq->dma[frag];
+
+				pDma->pDmaFirst = pDmaDesc;
+				pDma->pDmaLast = NULL;
+
+				for (i = 0; i < MV_CESA_MAX_DMA_DESC - 1; i++) {
+					/* link all DMA descriptors together */
+					pDma->pDmaFirst[i].phyNextDescPtr =
+						MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pDmaDesc[i + 1]));
+				}
+				pDma->pDmaFirst[i].phyNextDescPtr = 0;
+				mvOsCacheFlush(NULL, &pDma->pDmaFirst[0], MV_CESA_MAX_DMA_DESC * sizeof(MV_DMA_DESC));
+
+				pDmaDesc += MV_CESA_MAX_DMA_DESC;
+			}
+		}
+
+		/*mvCesaCryptoIvSet(NULL, MV_CESA_MAX_IV_LENGTH); */
+		descOffsetReg = (MV_U16)((MV_U8 *)&cesaSramVirtPtr[chan]->desc - mvCesaSramAddrGet(chan));
+		MV_REG_WRITE(MV_CESA_CHAN_DESC_OFFSET_REG(chan), descOffsetReg);
+
+		configReg |= (MV_CESA_CFG_WAIT_DMA_MASK | MV_CESA_CFG_ACT_DMA_MASK);
+
+#ifdef MV_CESA_CHAIN_MODE
+		configReg |= MV_CESA_CFG_CHAIN_MODE_MASK;
+#endif
+
+		/* Initialize TDMA engine */
+		MV_REG_WRITE(MV_CESA_TDMA_CTRL_REG(chan), MV_CESA_TDMA_CTRL_VALUE);
+		MV_REG_WRITE(MV_CESA_TDMA_BYTE_COUNT_REG(chan), 0);
+		MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG(chan), 0);
+
+#ifdef AURORA_IO_CACHE_COHERENCY
+		/* No support for outstanding read with i/o cache coherency on DiscoSMP/Z1 */
+		if (((ctrlModel & 0xff00) == 0x7800) && (ctrlRev < 1))
+			MV_REG_BIT_RESET(MV_CESA_TDMA_CTRL_REG(chan), MV_CESA_TDMA_OUTSTAND_READ_EN_MASK);
+#endif
+
+		switch ((MV_U16)(ctrlModel & 0xff00)) {
+		case 0x6500:
+			if (ctrlRev < 2) {
+				/* Parallel mode should be disabled('1') for chip rev. < A0 */
+				configReg |= MV_CESA_CFG_ENC_AUTH_PARALLEL_MODE_MASK;
+				sha2CmdVal = BIT31;
+			}
+			break;
+		case 0x6700:
+		case 0x7800:
+			if (ctrlRev < 1) {
+				/* Parallel mode should be disabled('1') for chip rev. < A0 */
+				configReg |= MV_CESA_CFG_ENC_AUTH_PARALLEL_MODE_MASK;
+				sha2CmdVal = BIT31;
+			}
+			break;
+		default:
+			mvOsPrintf("Error, chip revision(%d) no supported\n", halData->ctrlRev);
+			break;
+		}
+
+		/* Set CESA configuration registers */
+		MV_REG_WRITE(MV_CESA_CFG_REG(chan), configReg);
+	}
+
+	mvCesaDebugStatsClear();
+	mvOsMemcpy(&cesaHalData, halData, sizeof(MV_CESA_HAL_DATA));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaFinish - Shutdown the CESA driver
+*
+* DESCRIPTION:
+*       This function shutdown the CESA driver and free all allocted resources.
+*
+* INPUT:    None
+*
+* RETURN:
+*       MV_OK   - Success
+*       Other   - Fail
+*
+*******************************************************************************/
+MV_STATUS mvCesaFinish(void)
+{
+	int req, sid;
+	MV_CESA_REQ *pReq;
+	MV_U8 chan;
+
+	mvOsPrintf("mvCesaFinish: \n");
+
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+
+		cesaSramVirtPtr[chan] = NULL;
+
+		MV_REG_WRITE(MV_CESA_CFG_REG(chan), 0);
+		MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+		MV_REG_WRITE(MV_CESA_ISR_MASK_REG(chan), 0);
+
+
+		/* Free all resources: DMA list, etc. */
+		for (req = 0; req < cesaQueueDepth[chan]; req++) {
+			pReq = &pCesaReqFirst[chan][req];
+			if (pReq->dmaDescBuf.bufVirtPtr != NULL) {
+				mvOsIoCachedFree(cesaOsHandle, pReq->dmaDescBuf.bufSize,
+					pReq->dmaDescBuf.bufPhysAddr,
+					pReq->dmaDescBuf.bufVirtPtr, pReq->dmaDescBuf.memHandle);
+			}
+			if (pReq->cesaDescBuf.bufVirtPtr != NULL) {
+				mvOsIoCachedFree(cesaOsHandle, pReq->cesaDescBuf.bufSize,
+					pReq->cesaDescBuf.bufPhysAddr,
+					pReq->cesaDescBuf.bufVirtPtr, pReq->cesaDescBuf.memHandle);
+			}
+
+			/* Free request queue */
+			if (pCesaReqFirst[chan] != NULL) {
+				mvOsFree(pCesaReqFirst[chan]);
+				pCesaReqFirst[chan] = pCesaReqLast[chan] = NULL;
+				pCesaReqEmpty[chan] = pCesaReqProcess[chan] = NULL;
+				cesaQueueDepth[chan] = cesaReqResources[chan] = 0;
+			}
+		}
+	}
+
+	/* Free SA database */
+	if (pCesaSAD != NULL) {
+		for (sid = 0; sid < cesaMaxSA; sid++) {
+			/* Free SRAM SA structure */
+			mvOsIoCachedFree(cesaOsHandle, pCesaSAD[sid]->sramSABuffSize,
+					 pCesaSAD[sid]->sramSAPhysAddr,
+					 pCesaSAD[sid]->sramSABuff, pCesaSAD[sid]->memHandle);
+			/* Free SA structure */
+			mvOsFree(pCesaSAD[sid]);
+			pCesaSAD[sid] = NULL;
+		}
+
+		cesaMaxSA = 0;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaCryptoIvSet - Set IV value for Crypto algorithm working in CBC mode
+*
+* DESCRIPTION:
+*    This function set IV value using by Crypto algorithms in CBC mode.
+*   Each channel has its own IV value.
+*   This function gets IV value from the caller. If no IV value passed from
+*   the caller or only part of IV passed, the function will init the rest part
+*   of IV value (or the whole IV) by random value.
+*
+* INPUT:
+*       MV_U8*  pIV     - Pointer to IV value supplied by user. If pIV==NULL
+*                       the function will generate random IV value.
+*       int     ivSize  - size (in bytes) of IV provided by user. If ivSize is
+*                       smaller than maximum IV size, the function will complete
+*                       IV by random value.
+*
+* RETURN:
+*       MV_OK   - Success
+*       Other   - Fail
+*
+*******************************************************************************/
+MV_STATUS mvCesaCryptoIvSet(MV_U8 chan, MV_U8 *pIV, int ivSize)
+{
+	MV_U8 *pSramIV;
+
+	pSramIV = cesaSramVirtPtr[chan]->cryptoIV;
+	if (ivSize > MV_CESA_MAX_IV_LENGTH) {
+		mvOsPrintf("mvCesaCryptoIvSet: ivSize (%d) is too large\n", ivSize);
+		ivSize = MV_CESA_MAX_IV_LENGTH;
+	}
+	if (pIV != NULL) {
+		memcpy(pSramIV, pIV, ivSize);
+		ivSize = MV_CESA_MAX_IV_LENGTH - ivSize;
+		pSramIV += ivSize;
+	}
+
+	while (ivSize > 0) {
+		int size, mv_random = mvOsRand();
+
+		size = MV_MIN(ivSize, sizeof(mv_random));
+		memcpy(pSramIV, (void *)&mv_random, size);
+
+		pSramIV += size;
+		ivSize -= size;
+	}
+/*
+    mvOsCacheFlush(NULL, cesaSramVirtPtr[chan]->cryptoIV, MV_CESA_MAX_IV_LENGTH);
+    mvOsCacheInvalidate(NULL, cesaSramVirtPtr[chan]->cryptoIV, MV_CESA_MAX_IV_LENGTH);
+*/
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaSessionOpen - Open new uni-directional crypto session
+*
+* DESCRIPTION:
+*       This function open new session.
+*
+* INPUT:
+*       MV_CESA_OPEN_SESSION *pSession - pointer to new session input parameters
+*
+* OUTPUT:
+*       short           *pSid  - session ID, should be used for all future
+*                                   requests over this session.
+*
+* RETURN:
+*       MV_OK           - Session opend successfully.
+*       MV_FULL         - All sessions are in use, no free place in
+*                       SA database.
+*       MV_BAD_PARAM    - One of session input parameters is invalid.
+*
+*******************************************************************************/
+MV_STATUS mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short *pSid)
+{
+	short sid;
+	MV_U32 config = 0;
+	int digestSize;
+	MV_BUF_INFO cesaSramSaBuf;
+
+	cesaStats.openedCount++;
+
+	/* Find free entry in SAD */
+	for (sid = 0; sid < cesaMaxSA; sid++)
+		if (pCesaSAD[sid] == NULL)
+			break;
+
+	/* No more sessions left ? */
+	if (sid == cesaMaxSA) {
+		if (MV_FAIL == mvCesaUpdateSADSize(cesaMaxSA * 2)) {
+			mvOsPrintf("mvCesaSessionOpen: SA Database is FULL\n");
+			return MV_FULL;
+		}
+	}
+
+	/* Allocate SA entry */
+	pCesaSAD[sid] = mvOsMalloc(sizeof(MV_CESA_SA));
+	if (pCesaSAD[sid] == NULL) {
+		mvOsPrintf("mvCesaSessionOpen: Can't allocate %d bytes for SA structures\n", sizeof(MV_CESA_SA));
+		return MV_FULL;
+	}
+	memset(pCesaSAD[sid], 0, sizeof(MV_CESA_SA));
+
+	/* Allocate image of sramSA in DRAM */
+	cesaSramSaBuf.bufSize = sizeof(MV_CESA_SRAM_SA) + CPU_D_CACHE_LINE_SIZE;
+
+	cesaSramSaBuf.bufVirtPtr = mvOsIoCachedMalloc(cesaOsHandle, cesaSramSaBuf.bufSize,
+						      &cesaSramSaBuf.bufPhysAddr, &cesaSramSaBuf.memHandle);
+
+	if (cesaSramSaBuf.bufVirtPtr == NULL) {
+		mvOsPrintf("mvCesaSessionOpen: Can't allocate %d bytes for sramSA structures\n", cesaSramSaBuf.bufSize);
+		return MV_FULL;
+	}
+	memset(cesaSramSaBuf.bufVirtPtr, 0, cesaSramSaBuf.bufSize);
+
+	/* Save allocation parameters */
+	pCesaSAD[sid]->sramSABuff = cesaSramSaBuf.bufVirtPtr;
+	pCesaSAD[sid]->sramSABuffSize = cesaSramSaBuf.bufSize;
+	pCesaSAD[sid]->memHandle = cesaSramSaBuf.memHandle;
+	pCesaSAD[sid]->pSramSA = (MV_CESA_SRAM_SA *) MV_ALIGN_UP((MV_ULONG) cesaSramSaBuf.bufVirtPtr,
+								 CPU_D_CACHE_LINE_SIZE);
+
+	/* Align physical address to the beginning of SRAM SA */
+	pCesaSAD[sid]->sramSAPhysAddr = MV_32BIT_LE(mvCesaVirtToPhys(&cesaSramSaBuf, pCesaSAD[sid]->pSramSA));
+
+	/* Check Input parameters for Open session */
+	if (pSession->operation >= MV_CESA_MAX_OPERATION) {
+		mvOsPrintf("mvCesaSessionOpen: Unexpected operation %d\n", pSession->operation);
+		return MV_BAD_PARAM;
+	}
+	config |= (pSession->operation << MV_CESA_OPERATION_OFFSET);
+
+	if ((pSession->direction != MV_CESA_DIR_ENCODE) && (pSession->direction != MV_CESA_DIR_DECODE)) {
+		mvOsPrintf("mvCesaSessionOpen: Unexpected direction %d\n", pSession->direction);
+		return MV_BAD_PARAM;
+	}
+	config |= (pSession->direction << MV_CESA_DIRECTION_BIT);
+	/* Clear SA entry */
+	/* memset(&pCesaSAD[sid], 0, sizeof(pCesaSAD[sid])); */
+
+	/* Check AUTH parameters and update SA entry */
+	if (pSession->operation != MV_CESA_CRYPTO_ONLY) {
+		/* For HMAC (MD5/SHA1/SHA2) - Maximum Key size is 64 bytes */
+		if ((pSession->macMode == MV_CESA_MAC_HMAC_MD5) || (pSession->macMode == MV_CESA_MAC_HMAC_SHA1) ||
+					(pSession->macMode == MV_CESA_MAC_HMAC_SHA2)) {
+			if (pSession->macKeyLength > MV_CESA_MAX_MAC_KEY_LENGTH) {
+				mvOsPrintf("mvCesaSessionOpen: macKeyLength %d is too large\n", pSession->macKeyLength);
+				return MV_BAD_PARAM;
+			}
+			mvCesaHmacIvGet(pSession->macMode, pSession->macKey, pSession->macKeyLength,
+					pCesaSAD[sid]->pSramSA->macInnerIV, pCesaSAD[sid]->pSramSA->macOuterIV);
+			pCesaSAD[sid]->macKeyLength = pSession->macKeyLength;
+		}
+		switch (pSession->macMode) {
+		case MV_CESA_MAC_MD5:
+		case MV_CESA_MAC_HMAC_MD5:
+			digestSize = MV_CESA_MD5_DIGEST_SIZE;
+			break;
+
+		case MV_CESA_MAC_SHA1:
+		case MV_CESA_MAC_HMAC_SHA1:
+			digestSize = MV_CESA_SHA1_DIGEST_SIZE;
+			break;
+
+		case MV_CESA_MAC_SHA2:
+		case MV_CESA_MAC_HMAC_SHA2:
+			digestSize = MV_CESA_SHA2_DIGEST_SIZE;
+			break;
+
+		default:
+			mvOsPrintf("mvCesaSessionOpen: Unexpected macMode %d\n", pSession->macMode);
+			return MV_BAD_PARAM;
+		}
+		config |= (pSession->macMode << MV_CESA_MAC_MODE_OFFSET);
+
+		/* Supported digest sizes:     */
+		/* MD5 - 16 bytes (128 bits),  */
+		/* SHA1 - 20 bytes (160 bits), */
+		/* SHA2 - 32 bytes (256 bits) or 12 bytes (96 bits) for all */
+		if ((pSession->digestSize != digestSize) && (pSession->digestSize != 12)) {
+			mvOsPrintf("mvCesaSessionOpen: Unexpected digest size %d\n", pSession->digestSize);
+			mvOsPrintf("\t Valid values [bytes]: MD5-16, SHA1-20, SHA2-32, All-12\n");
+			return MV_BAD_PARAM;
+		}
+		pCesaSAD[sid]->digestSize = pSession->digestSize;
+
+		if (pCesaSAD[sid]->digestSize == 12) {
+			/* Set MV_CESA_MAC_DIGEST_SIZE_BIT if digest size is 96 bits */
+			config |= (MV_CESA_MAC_DIGEST_96B << MV_CESA_MAC_DIGEST_SIZE_BIT);
+		}
+	}
+
+	/* Check CRYPTO parameters and update SA entry */
+	if (pSession->operation != MV_CESA_MAC_ONLY) {
+		switch (pSession->cryptoAlgorithm) {
+		case MV_CESA_CRYPTO_DES:
+			pCesaSAD[sid]->cryptoKeyLength = MV_CESA_DES_KEY_LENGTH;
+			pCesaSAD[sid]->cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE;
+			break;
+
+		case MV_CESA_CRYPTO_3DES:
+			pCesaSAD[sid]->cryptoKeyLength = MV_CESA_3DES_KEY_LENGTH;
+			pCesaSAD[sid]->cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE;
+			/* Only EDE mode is supported */
+			config |= (MV_CESA_CRYPTO_3DES_EDE << MV_CESA_CRYPTO_3DES_MODE_BIT);
+			break;
+
+		case MV_CESA_CRYPTO_AES:
+			switch (pSession->cryptoKeyLength) {
+			case 16:
+				pCesaSAD[sid]->cryptoKeyLength = MV_CESA_AES_128_KEY_LENGTH;
+				config |= (MV_CESA_CRYPTO_AES_KEY_128 << MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
+				break;
+
+			case 24:
+				pCesaSAD[sid]->cryptoKeyLength = MV_CESA_AES_192_KEY_LENGTH;
+				config |= (MV_CESA_CRYPTO_AES_KEY_192 << MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
+				break;
+
+			case 32:
+			default:
+				pCesaSAD[sid]->cryptoKeyLength = MV_CESA_AES_256_KEY_LENGTH;
+				config |= (MV_CESA_CRYPTO_AES_KEY_256 << MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
+				break;
+			}
+			pCesaSAD[sid]->cryptoBlockSize = MV_CESA_AES_BLOCK_SIZE;
+			break;
+
+		default:
+			mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoAlgorithm %d\n", pSession->cryptoAlgorithm);
+			return MV_BAD_PARAM;
+		}
+		config |= (pSession->cryptoAlgorithm << MV_CESA_CRYPTO_ALG_OFFSET);
+
+		if (pSession->cryptoKeyLength != pCesaSAD[sid]->cryptoKeyLength) {
+			mvOsPrintf("cesaSessionOpen: Wrong CryptoKeySize %d != %d\n",
+				   pSession->cryptoKeyLength, pCesaSAD[sid]->cryptoKeyLength);
+			return MV_BAD_PARAM;
+		}
+
+		/* Copy Crypto key */
+		if ((pSession->cryptoAlgorithm == MV_CESA_CRYPTO_AES) && (pSession->direction == MV_CESA_DIR_DECODE)) {
+			/* Crypto Key for AES decode is computed from original key material */
+			/* and depend on cryptoKeyLength (128/192/256 bits) */
+			aesMakeKey(pCesaSAD[sid]->pSramSA->cryptoKey, pSession->cryptoKey,
+				   pSession->cryptoKeyLength * 8, MV_CESA_AES_BLOCK_SIZE * 8);
+		} else {
+			/*panic("mvCesaSessionOpen2"); */
+			memcpy(pCesaSAD[sid]->pSramSA->cryptoKey, pSession->cryptoKey, pCesaSAD[sid]->cryptoKeyLength);
+
+		}
+
+		switch (pSession->cryptoMode) {
+		case MV_CESA_CRYPTO_ECB:
+			pCesaSAD[sid]->cryptoIvSize = 0;
+			break;
+
+		case MV_CESA_CRYPTO_CBC:
+			pCesaSAD[sid]->cryptoIvSize = pCesaSAD[sid]->cryptoBlockSize;
+			break;
+
+		case MV_CESA_CRYPTO_CTR:
+			/* Supported only for AES algorithm */
+			if (pSession->cryptoAlgorithm != MV_CESA_CRYPTO_AES) {
+				mvOsPrintf("mvCesaSessionOpen: CRYPTO CTR mode supported for AES only\n");
+				return MV_BAD_PARAM;
+			}
+			pCesaSAD[sid]->cryptoIvSize = 0;
+			pCesaSAD[sid]->ctrMode = 1;
+			/* Replace to ECB mode for HW */
+			pSession->cryptoMode = MV_CESA_CRYPTO_ECB;
+			break;
+
+		default:
+			mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoMode %d\n", pSession->cryptoMode);
+			return MV_BAD_PARAM;
+		}
+
+		config |= (pSession->cryptoMode << MV_CESA_CRYPTO_MODE_BIT);
+	}
+	pCesaSAD[sid]->config = config;
+
+	mvOsCacheFlush(NULL, pCesaSAD[sid]->pSramSA, sizeof(MV_CESA_SRAM_SA));
+	if (pSid != NULL)
+		*pSid = sid;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaSessionClose - Close active crypto session
+*
+* DESCRIPTION:
+*       This function closes existing session
+*
+* INPUT:
+*       short sid   - Unique identifier of the session to be closed
+*
+* RETURN:
+*       MV_OK        - Session closed successfully.
+*       MV_BAD_PARAM - Session identifier is out of valid range.
+*       MV_NOT_FOUND - There is no active session with such ID.
+*
+*******************************************************************************/
+MV_STATUS mvCesaSessionClose(short sid)
+{
+	MV_U8 chan;
+
+	cesaStats.closedCount++;
+
+	if (sid >= cesaMaxSA) {
+		mvOsPrintf("CESA Error: sid (%d) is too big\n", sid);
+		return MV_BAD_PARAM;
+	}
+
+	if (pCesaSAD[sid] == NULL) {
+		mvOsPrintf("CESA Warning: Session (sid=%d) is invalid\n", sid);
+		return MV_NOT_FOUND;
+	}
+
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+		if (cesaLastSid[chan] == sid)
+			cesaLastSid[chan] = -1;
+	}
+
+	/* Free SA structures */
+	mvOsIoCachedFree(cesaOsHandle, pCesaSAD[sid]->sramSABuffSize,
+			 pCesaSAD[sid]->sramSAPhysAddr, pCesaSAD[sid]->sramSABuff, pCesaSAD[sid]->memHandle);
+	mvOsFree(pCesaSAD[sid]);
+
+	pCesaSAD[sid] = NULL;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaAction - Perform crypto operation
+*
+* DESCRIPTION:
+*       This function set new CESA request FIFO queue for further HW processing.
+*       The function checks request parameters before set new request to the queue.
+*       If one of the CESA channels is ready for processing the request will be
+*       passed to HW. When request processing is finished the CESA interrupt will
+*       be generated by HW. The caller should call mvCesaReadyGet() function to
+*       complete request processing and get result.
+*
+* INPUT:
+* 	MV_U8 chan		- channel ID.
+*       MV_CESA_COMMAND *pCmd   - pointer to new CESA request.
+*                               It includes pointers to Source and Destination
+*                               buffers, session identifier get from
+*                               mvCesaSessionOpen() function, pointer to caller
+*                               private data and all needed crypto parameters.
+*
+* RETURN:
+*       MV_OK             - request successfully added to request queue
+*                         and will be processed.
+*       MV_NO_MORE        - request successfully added to request queue and will
+*                         be processed, but request queue became Full and next
+*                         request will not be accepted.
+*       MV_NO_RESOURCE    - request queue is FULL and the request can not
+*                         be processed.
+*       MV_OUT_OF_CPU_MEM - memory allocation needed for request processing is
+*                         failed. Request can not be processed.
+*       MV_NOT_ALLOWED    - This mixed request (CRYPTO+MAC) can not be processed
+*                         as one request and should be splitted for two requests:
+*                         CRYPTO_ONLY and MAC_ONLY.
+*       MV_BAD_PARAM      - One of the request parameters is out of valid range.
+*                         The request can not be processed.
+*
+*******************************************************************************/
+MV_STATUS mvCesaAction(MV_U8 chan, MV_CESA_COMMAND *pCmd)
+{
+	MV_STATUS status;
+	MV_CESA_REQ *pReq = pCesaReqEmpty[chan];
+	int sid = pCmd->sessionId;
+	MV_CESA_SA *pSA = pCesaSAD[sid];
+#ifdef MV_CESA_CHAIN_MODE
+	MV_CESA_REQ *pFromReq;
+	MV_CESA_REQ *pToReq;
+#endif
+	cesaStats.reqCount++;
+
+	/* Check that the request queue is not FULL */
+	if (cesaReqResources[chan] == 0)
+		return MV_NO_RESOURCE;
+
+	if ((sid >= cesaMaxSA) || (pSA == NULL)) {
+		mvOsPrintf("CESA Action Error: Session sid=%d is INVALID\n", sid);
+		return MV_BAD_PARAM;
+	}
+	pSA->count++;
+
+	if (pSA->ctrMode) {
+		/* AES in CTR mode can't be mixed with Authentication */
+		if ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) {
+			mvOsPrintf("mvCesaAction : CRYPTO CTR mode can't be mixed with AUTH\n");
+			return MV_NOT_ALLOWED;
+		}
+		/* All other request parameters should not be checked because key stream */
+		/* (not user data) processed by AES HW engine */
+		pReq->pOrgCmd = pCmd;
+		/* Allocate temporary pCmd structure for Key stream */
+		pCmd = mvCesaCtrModeInit();
+		if (pCmd == NULL)
+			return MV_OUT_OF_CPU_MEM;
+
+		/* Prepare Key stream */
+		mvCesaCtrModePrepare(pCmd, pReq->pOrgCmd);
+		pReq->fixOffset = 0;
+	} else {
+		/* Check request parameters and calculae fixOffset */
+		status = mvCesaParamCheck(pSA, pCmd, &pReq->fixOffset);
+		if (status != MV_OK)
+			return status;
+	}
+	pReq->pCmd = pCmd;
+
+	/* Check if the packet need fragmentation */
+	if (pCmd->pSrc->mbufSize <= sizeof(cesaSramVirtPtr[chan]->buf)) {
+		/* request size is smaller than single buffer size */
+		pReq->fragMode = MV_CESA_FRAG_NONE;
+
+		/* Prepare NOT fragmented packets */
+		status = mvCesaReqProcess(chan, pReq);
+		if (status != MV_OK)
+			mvOsPrintf("CesaReady: ReqProcess error: pReq=%p, status=0x%x\n", pReq, status);
+#ifdef MV_CESA_CHAIN_MODE
+		pReq->frags.numFrag = 1;
+#endif
+	} else {
+		MV_U8 frag = 0;
+
+		/* request size is larger than buffer size - needs fragmentation */
+
+		/* Check restrictions for processing fragmented packets */
+		status = mvCesaFragParamCheck(chan, pSA, pCmd);
+		if (status != MV_OK)
+			return status;
+
+		pReq->fragMode = MV_CESA_FRAG_FIRST;
+		pReq->frags.nextFrag = 0;
+
+		/* Prepare Process Fragmented packets */
+		while (pReq->fragMode != MV_CESA_FRAG_LAST) {
+			if (frag >= MV_CESA_MAX_REQ_FRAGS) {
+				mvOsPrintf("mvCesaAction Error: Too large request frag=%d\n", frag);
+				return MV_OUT_OF_CPU_MEM;
+			}
+			status = mvCesaFragReqProcess(chan, pReq, frag);
+			if (status == MV_OK) {
+#ifdef MV_CESA_CHAIN_MODE
+				if (frag) {
+					pReq->dma[frag - 1].pDmaLast->phyNextDescPtr =
+					    MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
+					mvOsCacheFlush(NULL, pReq->dma[frag - 1].pDmaLast, sizeof(MV_DMA_DESC));
+				}
+#endif /* MV_CESA_CHAIN_MODE */
+				frag++;
+			}
+		}
+		pReq->frags.numFrag = frag;
+
+#ifdef MV_CESA_CHAIN_MODE
+		if (chainReqNum[chan]) {
+			chainReqNum[chan] += pReq->frags.numFrag;
+			if (chainReqNum[chan] >= MAX_CESA_CHAIN_LENGTH)
+				chainReqNum[chan] = MAX_CESA_CHAIN_LENGTH;
+		}
+#endif /* MV_CESA_CHAIN_MODE */
+	}
+
+	pReq->state = MV_CESA_PENDING;
+
+	pCesaReqEmpty[chan] = MV_CESA_REQ_NEXT_PTR(chan, pCesaReqEmpty[chan]);
+	cesaReqResources[chan] -= 1;
+
+/* #ifdef CESA_DEBUG */
+	if ((cesaQueueDepth[chan] - cesaReqResources[chan]) > cesaStats.maxReqCount)
+		cesaStats.maxReqCount = (cesaQueueDepth[chan] - cesaReqResources[chan]);
+/* #endif CESA_DEBUG */
+
+	cesaLastSid[chan] = sid;
+
+#ifdef MV_CESA_CHAIN_MODE
+	/* Are we within chain bounderies and follows the first request ? */
+	if ((chainReqNum[chan] > 0) && (chainReqNum[chan] < MAX_CESA_CHAIN_LENGTH)) {
+		if (chainIndex[chan]) {
+			pFromReq = MV_CESA_REQ_PREV_PTR(chan, pReq);
+			pToReq = pReq;
+			pReq->state = MV_CESA_CHAIN;
+			/* assume concatenating is possible */
+			pFromReq->dma[pFromReq->frags.numFrag - 1].pDmaLast->phyNextDescPtr =
+			    MV_32BIT_LE(mvCesaVirtToPhys(&pToReq->dmaDescBuf, pToReq->dma[0].pDmaFirst));
+			mvOsCacheFlush(NULL, pFromReq->dma[pFromReq->frags.numFrag - 1].pDmaLast, sizeof(MV_DMA_DESC));
+
+			/* align active & next pointers */
+			if (pNextActiveChain[chan]->state != MV_CESA_PENDING)
+				pEndCurrChain[chan] = pNextActiveChain[chan] = MV_CESA_REQ_NEXT_PTR(chan, pReq);
+		} else {	/* we have only one chain, start new one */
+			chainReqNum[chan] = 0;
+			chainIndex[chan]++;
+			/* align active & next pointers  */
+			if (pNextActiveChain[chan]->state != MV_CESA_PENDING)
+				pEndCurrChain[chan] = pNextActiveChain[chan] = pReq;
+		}
+	} else {
+		/* In case we concatenate full chain */
+		if (chainReqNum[chan] == MAX_CESA_CHAIN_LENGTH) {
+			chainIndex[chan]++;
+			if (pNextActiveChain[chan]->state != MV_CESA_PENDING)
+				pEndCurrChain[chan] = pNextActiveChain[chan] = pReq;
+			chainReqNum[chan] = 0;
+		}
+
+		pReq = pCesaReqProcess[chan];
+		if (pReq->state == MV_CESA_PENDING) {
+			pNextActiveChain[chan] = pReq;
+			pEndCurrChain[chan] = MV_CESA_REQ_NEXT_PTR(chan, pReq);
+			/* Start Process new request */
+			mvCesaReqProcessStart(chan, pReq);
+		}
+	}
+
+	chainReqNum[chan]++;
+
+	if ((chainIndex[chan] < MAX_CESA_CHAIN_LENGTH) && (chainReqNum[chan] > cesaStats.maxChainUsage))
+		cesaStats.maxChainUsage = chainReqNum[chan];
+
+#else
+
+	/* Check status of CESA channels and process requests if possible */
+	pReq = pCesaReqProcess[chan];
+	if (pReq->state == MV_CESA_PENDING) {
+		/* Start Process new request */
+		mvCesaReqProcessStart(chan, pReq);
+	}
+#endif /* MV_CESA_CHAIN_MODE */
+
+	/* If request queue became FULL - return MV_NO_MORE */
+	if (cesaReqResources[chan] == 0)
+		return MV_NO_MORE;
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvCesaReadyGet - Get crypto request that processing is finished
+*
+* DESCRIPTION:
+*       This function complete request processing and return ready request to
+*       caller. To don't miss interrupts the caller must call this function
+*       while MV_OK or MV_TERMINATE values returned.
+*
+* INPUT:
+*   MV_U32          chanMap  - map of CESA channels finished thier job
+*                              accordingly with CESA Cause register.
+*   MV_CESA_RESULT* pResult  - pointer to structure contains information
+*                            about ready request. It includes pointer to
+*                            user private structure "pReqPrv", session identifier
+*                            for this request "sessionId" and return code.
+*                            Return code set to MV_FAIL if calculated digest value
+*                            on decode direction is different than digest value
+*                            in the packet.
+*
+* RETURN:
+*       MV_OK           - Success, ready request is returned.
+*       MV_NOT_READY    - Next request is not ready yet. New interrupt will
+*                       be generated for futher request processing.
+*       MV_EMPTY        - There is no more request for processing.
+*       MV_BUSY         - Fragmented request is not ready yet.
+*       MV_TERMINATE    - Call this function once more to complete processing
+*                       of fragmented request.
+*
+*******************************************************************************/
+MV_STATUS mvCesaReadyGet(MV_U8 chan, MV_CESA_RESULT *pResult)
+{
+	MV_STATUS status, readyStatus = MV_NOT_READY;
+	MV_U32 statusReg;
+	MV_CESA_REQ *pReq;
+	MV_CESA_SA *pSA;
+
+#ifdef MV_CESA_CHAIN_MODE
+	if (isFirstReq[chan] == MV_TRUE) {
+
+		if (chainIndex[chan] == 0)
+			chainReqNum[chan] = 0;
+
+		isFirstReq[chan] = MV_FALSE;
+
+		if (pNextActiveChain[chan]->state == MV_CESA_PENDING) {
+
+			/* Start request Process */
+			mvCesaReqProcessStart(chan, pNextActiveChain[chan]);
+			pEndCurrChain[chan] = pNextActiveChain[chan];
+			if (chainIndex[chan] > 0)
+				chainIndex[chan]--;
+			/* Update pNextActiveChain to next chain head */
+			while (pNextActiveChain[chan]->state == MV_CESA_CHAIN)
+				pNextActiveChain[chan] = MV_CESA_REQ_NEXT_PTR(chan, pNextActiveChain[chan]);
+		}
+
+	}
+
+	/* Check if there are more processed requests - can we remove pEndCurrChain ??? */
+	if (pCesaReqProcess[chan] == pEndCurrChain[chan]) {
+
+		isFirstReq[chan] = MV_TRUE;
+		pEndCurrChain[chan] = pNextActiveChain[chan];
+#else
+	if (pCesaReqProcess[chan]->state != MV_CESA_PROCESS) {
+#endif /* MV_CESA_CHAIN_MODE */
+
+		return MV_EMPTY;
+	}
+#ifdef CESA_DEBUG
+	statusReg = MV_REG_READ(MV_CESA_STATUS_REG(chan));
+	if (statusReg & MV_CESA_STATUS_ACTIVE_MASK) {
+		mvOsPrintf("mvCesaReadyGet: Not Ready, Status = 0x%x\n", statusReg);
+		cesaStats.notReadyCount++;
+		return MV_NOT_READY;
+	}
+#endif /* CESA_DEBUG */
+
+	cesaStats.readyCount++;
+
+	pReq = pCesaReqProcess[chan];
+	pSA = pCesaSAD[pReq->pCmd->sessionId];
+
+	pResult->retCode = MV_OK;
+	if (pReq->fragMode != MV_CESA_FRAG_NONE) {
+		MV_U8 *pNewDigest;
+		int frag;
+
+#ifdef MV_CESA_CHAIN_MODE
+		pReq->frags.nextFrag = 1;
+		while (pReq->frags.nextFrag <= pReq->frags.numFrag) {
+#endif /* MV_CESA_CHAIN_MODE */
+
+			frag = (pReq->frags.nextFrag - 1);
+
+			/* Restore DMA descriptor list */
+			pReq->dma[frag].pDmaLast->phyNextDescPtr =
+			    MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[frag].pDmaLast[1]));
+			pReq->dma[frag].pDmaLast = NULL;
+
+			/* Special processing for finished fragmented request */
+			if (pReq->frags.nextFrag >= pReq->frags.numFrag) {
+				mvCesaMbufCacheUnmap(pReq->pCmd->pDst, 0, pReq->pCmd->pDst->mbufSize);
+
+				/* Fragmented packet is ready */
+				if ((pSA->config & MV_CESA_OPERATION_MASK) !=
+				    (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) {
+					int macDataSize = pReq->pCmd->macLength - pReq->frags.macSize;
+
+					if (macDataSize != 0) {
+						/* Calculate all other blocks by SW */
+						mvCesaFragAuthComplete(chan, pReq, pSA, macDataSize);
+					}
+
+					/* Copy new digest from SRAM to the Destination buffer */
+					pNewDigest = cesaSramVirtPtr[chan]->buf + pReq->frags.newDigestOffset;
+					status = mvCesaCopyToMbuf(pNewDigest, pReq->pCmd->pDst,
+								  pReq->pCmd->digestOffset, pSA->digestSize);
+
+					/* For decryption: Compare new digest value with original one */
+					if ((pSA->config & MV_CESA_DIRECTION_MASK) ==
+					    (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) {
+						if (memcmp(pNewDigest, pReq->frags.orgDigest, pSA->digestSize) != 0) {
+/*
+						mvOsPrintf("Digest error: chan=%d, newDigest=%p, orgDigest=%p, status = 0x%x\n",
+							chan, pNewDigest, pReq->frags.orgDigest, MV_REG_READ(MV_CESA_STATUS_REG));
+*/
+							/* Signiture verification is failed */
+							pResult->retCode = MV_FAIL;
+						}
+					}
+				}
+				readyStatus = MV_OK;
+			}
+#ifdef MV_CESA_CHAIN_MODE
+			pReq->frags.nextFrag++;
+		}
+#endif
+	} else {
+		mvCesaMbufCacheUnmap(pReq->pCmd->pDst, 0, pReq->pCmd->pDst->mbufSize);
+
+		/* Restore DMA descriptor list */
+		pReq->dma[0].pDmaLast->phyNextDescPtr =
+		    MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[0].pDmaLast[1]));
+		pReq->dma[0].pDmaLast = NULL;
+		if (((pSA->config & MV_CESA_OPERATION_MASK) !=
+		     (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) &&
+		    ((pSA->config & MV_CESA_DIRECTION_MASK) == (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))) {
+			/* For AUTH on decode : Check Digest result in Status register */
+			statusReg = MV_REG_READ(MV_CESA_STATUS_REG(chan));
+			if (statusReg & MV_CESA_STATUS_DIGEST_ERR_MASK) {
+/*
+				mvOsPrintf("Digest error: chan=%d, status = 0x%x\n",
+						chan, statusReg);
+*/
+				/* Signiture verification is failed */
+				pResult->retCode = MV_FAIL;
+			}
+		}
+		readyStatus = MV_OK;
+	}
+
+	if (readyStatus == MV_OK) {
+		/* If Request is ready - Prepare pResult structure */
+		pResult->pReqPrv = pReq->pCmd->pReqPrv;
+		pResult->sessionId = pReq->pCmd->sessionId;
+		pResult->mbufSize = pReq->pCmd->pSrc->mbufSize;
+		pResult->reqId = pReq->pCmd->reqId;
+		pReq->state = MV_CESA_IDLE;
+		pCesaReqProcess[chan] = MV_CESA_REQ_NEXT_PTR(chan, pCesaReqProcess[chan]);
+		cesaReqResources[chan]++;
+
+		if (pSA->ctrMode) {
+			/* For AES CTR mode - complete processing and free allocated resources */
+			mvCesaCtrModeComplete(pReq->pOrgCmd, pReq->pCmd);
+			mvCesaCtrModeFinish(pReq->pCmd);
+			pReq->pOrgCmd = NULL;
+		}
+	}
+#ifndef MV_CESA_CHAIN_MODE
+	if (pCesaReqProcess[chan]->state == MV_CESA_PROCESS) {
+		/* Start request Process */
+		mvCesaReqProcessStart(chan, pCesaReqProcess[chan]);
+		if (readyStatus == MV_NOT_READY)
+			readyStatus = MV_BUSY;
+	} else if (pCesaReqProcess[chan] != pCesaReqEmpty[chan]) {
+		/* Start process new request from the queue */
+		mvCesaReqProcessStart(chan, pCesaReqProcess[chan]);
+	}
+#endif /* !MV_CESA_CHAIN_MODE */
+	return readyStatus;
+}
+
+/***************** Functions to work with CESA_MBUF structure ******************/
+
+/*******************************************************************************
+* mvCesaMbufOffset - Locate offset in the Mbuf structure
+*
+* DESCRIPTION:
+*       This function locates offset inside Multi-Bufeer structure.
+*       It get fragment number and place in the fragment where the offset
+*       is located.
+*
+*
+* INPUT:
+*   MV_CESA_MBUF* pMbuf  - Pointer to multi-buffer structure
+*   int           offset - Offset from the beginning of the data presented by
+*                        the Mbuf structure.
+*
+* OUTPUT:
+*   int*        pBufOffset  - Offset from the beginning of the fragment where
+*                           the offset is located.
+*
+* RETURN:
+*       int - Number of fragment, where the offset is located\
+*
+*******************************************************************************/
+int mvCesaMbufOffset(MV_CESA_MBUF *pMbuf, int offset, int *pBufOffset)
+{
+	int frag = 0;
+
+	while (offset > 0) {
+		if (frag >= pMbuf->numFrags) {
+			mvOsPrintf("mvCesaMbufOffset: Error: frag (%d) > numFrags (%d)\n", frag, pMbuf->numFrags);
+			return MV_INVALID;
+		}
+		if (offset < pMbuf->pFrags[frag].bufSize)
+			break;
+
+		offset -= pMbuf->pFrags[frag].bufSize;
+		frag++;
+	}
+	if (pBufOffset != NULL)
+		*pBufOffset = offset;
+
+	return frag;
+}
+
+/*******************************************************************************
+* mvCesaCopyFromMbuf - Copy data from the Mbuf structure to continuous buffer
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*   MV_U8*          pDstBuf  - Pointer to continuous buffer, where data is
+*                              copied to.
+*   MV_CESA_MBUF*   pSrcMbuf - Pointer to multi-buffer structure where data is
+*                              copied from.
+*   int             offset   - Offset in the Mbuf structure where located first
+*                            byte of data should be copied.
+*   int             size     - Size of data should be copied
+*
+* RETURN:
+*       MV_OK           - Success, all data is copied successfully.
+*       MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range.
+*                         No data is copied.
+*       MV_EMPTY        - Multi-buffer structure has not enough data to copy
+*                       Data from the offset to end of Mbuf data is copied.
+*
+*******************************************************************************/
+MV_STATUS mvCesaCopyFromMbuf(MV_U8 *pDstBuf, MV_CESA_MBUF *pSrcMbuf, int offset, int size)
+{
+	int frag, fragOffset, bufSize;
+	MV_U8 *pBuf;
+
+	if (size == 0)
+		return MV_OK;
+
+	frag = mvCesaMbufOffset(pSrcMbuf, offset, &fragOffset);
+	if (frag == MV_INVALID) {
+		mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+		return MV_OUT_OF_RANGE;
+	}
+
+	bufSize = pSrcMbuf->pFrags[frag].bufSize - fragOffset;
+	pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+	while (MV_TRUE) {
+		if (size <= bufSize) {
+			memcpy(pDstBuf, pBuf, size);
+			return MV_OK;
+		}
+		memcpy(pDstBuf, pBuf, bufSize);
+		size -= bufSize;
+		frag++;
+		pDstBuf += bufSize;
+		if (frag >= pSrcMbuf->numFrags)
+			break;
+
+		bufSize = pSrcMbuf->pFrags[frag].bufSize;
+		pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr;
+	}
+	mvOsPrintf("mvCesaCopyFromMbuf: Mbuf is EMPTY - %d bytes isn't copied\n", size);
+	return MV_EMPTY;
+}
+
+/*******************************************************************************
+* mvCesaCopyToMbuf - Copy data from continuous buffer to the Mbuf structure
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*   MV_U8*          pSrcBuf  - Pointer to continuous buffer, where data is
+*                              copied from.
+*   MV_CESA_MBUF*   pDstMbuf - Pointer to multi-buffer structure where data is
+*                              copied to.
+*   int             offset   - Offset in the Mbuf structure where located first
+*                            byte of data should be copied.
+*   int             size     - Size of data should be copied
+*
+* RETURN:
+*       MV_OK           - Success, all data is copied successfully.
+*       MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range.
+*                         No data is copied.
+*       MV_FULL         - Multi-buffer structure has not enough place to copy
+*                       all data. Data from the offset to end of Mbuf data
+*                       is copied.
+*
+*******************************************************************************/
+MV_STATUS mvCesaCopyToMbuf(MV_U8 *pSrcBuf, MV_CESA_MBUF *pDstMbuf, int offset, int size)
+{
+	int frag, fragOffset, bufSize;
+	MV_U8 *pBuf;
+
+	if (size == 0)
+		return MV_OK;
+
+	frag = mvCesaMbufOffset(pDstMbuf, offset, &fragOffset);
+	if (frag == MV_INVALID) {
+		mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+		return MV_OUT_OF_RANGE;
+	}
+
+	bufSize = pDstMbuf->pFrags[frag].bufSize - fragOffset;
+	pBuf = pDstMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+	while (MV_TRUE) {
+		if (size <= bufSize) {
+			memcpy(pBuf, pSrcBuf, size);
+			return MV_OK;
+		}
+		memcpy(pBuf, pSrcBuf, bufSize);
+		size -= bufSize;
+		frag++;
+		pSrcBuf += bufSize;
+		if (frag >= pDstMbuf->numFrags)
+			break;
+
+		bufSize = pDstMbuf->pFrags[frag].bufSize;
+		pBuf = pDstMbuf->pFrags[frag].bufVirtPtr;
+	}
+	mvOsPrintf("mvCesaCopyToMbuf: Mbuf is FULL - %d bytes isn't copied\n", size);
+	return MV_FULL;
+}
+
+/*******************************************************************************
+* mvCesaMbufCopy - Copy data from one Mbuf structure to the other Mbuf structure
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*
+*   MV_CESA_MBUF*   pDstMbuf - Pointer to multi-buffer structure where data is
+*                              copied to.
+*   int      dstMbufOffset   - Offset in the dstMbuf structure where first byte
+*                            of data should be copied to.
+*   MV_CESA_MBUF*   pSrcMbuf - Pointer to multi-buffer structure where data is
+*                              copied from.
+*   int      srcMbufOffset   - Offset in the srcMbuf structure where first byte
+*                            of data should be copied from.
+*   int             size     - Size of data should be copied
+*
+* RETURN:
+*       MV_OK           - Success, all data is copied successfully.
+*       MV_OUT_OF_RANGE - Failed, srcMbufOffset or dstMbufOffset is out of
+*                       srcMbuf or dstMbuf structure correspondently.
+*                       No data is copied.
+*       MV_BAD_SIZE     - srcMbuf or dstMbuf structure is too small to copy
+*                       all data. Partial data is copied
+*
+*******************************************************************************/
+MV_STATUS mvCesaMbufCopy(MV_CESA_MBUF *pMbufDst, int dstMbufOffset,
+			 MV_CESA_MBUF *pMbufSrc, int srcMbufOffset, int size)
+{
+	int srcFrag, dstFrag, srcSize, dstSize, srcOffset, dstOffset;
+	int copySize;
+	MV_U8 *pSrc, *pDst;
+
+	if (size == 0)
+		return MV_OK;
+
+	srcFrag = mvCesaMbufOffset(pMbufSrc, srcMbufOffset, &srcOffset);
+	if (srcFrag == MV_INVALID) {
+		mvOsPrintf("CESA srcMbuf Error: offset (%d) out of range\n", srcMbufOffset);
+		return MV_OUT_OF_RANGE;
+	}
+	pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr + srcOffset;
+	srcSize = pMbufSrc->pFrags[srcFrag].bufSize - srcOffset;
+
+	dstFrag = mvCesaMbufOffset(pMbufDst, dstMbufOffset, &dstOffset);
+	if (dstFrag == MV_INVALID) {
+		mvOsPrintf("CESA dstMbuf Error: offset (%d) out of range\n", dstMbufOffset);
+		return MV_OUT_OF_RANGE;
+	}
+	pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr + dstOffset;
+	dstSize = pMbufDst->pFrags[dstFrag].bufSize - dstOffset;
+
+	while (size > 0) {
+		copySize = MV_MIN(srcSize, dstSize);
+		if (size <= copySize) {
+			memcpy(pDst, pSrc, size);
+			return MV_OK;
+		}
+		memcpy(pDst, pSrc, copySize);
+		size -= copySize;
+		srcSize -= copySize;
+		dstSize -= copySize;
+
+		if (srcSize == 0) {
+			srcFrag++;
+			if (srcFrag >= pMbufSrc->numFrags)
+				break;
+
+			pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr;
+			srcSize = pMbufSrc->pFrags[srcFrag].bufSize;
+		}
+
+		if (dstSize == 0) {
+			dstFrag++;
+			if (dstFrag >= pMbufDst->numFrags)
+				break;
+
+			pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr;
+			dstSize = pMbufDst->pFrags[dstFrag].bufSize;
+		}
+	}
+	mvOsPrintf("mvCesaMbufCopy: BAD size - %d bytes isn't copied\n", size);
+
+	return MV_BAD_SIZE;
+}
+
+MV_STATUS mvCesaUpdateSADSize(MV_U32 size)
+{
+	MV_CESA_SA **pNewCesaSAD = NULL;
+
+	/*mvOsPrintf("mvCesaUpdateSADSize: Increasing SA Database to %d sessions\n",size); */
+
+	/* Allocate new buffer to hold larger SAD */
+	pNewCesaSAD = mvOsMalloc(sizeof(MV_CESA_SA *) * size);
+	if (pNewCesaSAD == NULL) {
+		mvOsPrintf("mvCesaUpdateSADSize: Can't allocate %d bytes for new SAD buffer\n", size);
+		return MV_FAIL;
+	}
+	memset(pNewCesaSAD, 0, (sizeof(MV_CESA_SA *) * size));
+	mvOsMemcpy(pNewCesaSAD, pCesaSAD, (sizeof(MV_CESA_SA *) * cesaMaxSA));
+	mvOsFree(pCesaSAD);
+	pCesaSAD = pNewCesaSAD;
+	cesaMaxSA = size;
+
+	return MV_OK;
+}
+
+static MV_STATUS mvCesaMbufCacheUnmap(MV_CESA_MBUF *pMbuf, int offset, int size)
+{
+	int frag, fragOffset, bufSize;
+	MV_U8 *pBuf;
+
+	if (size == 0)
+		return MV_OK;
+
+	frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
+	if (frag == MV_INVALID) {
+		mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+		return MV_OUT_OF_RANGE;
+	}
+
+	bufSize = pMbuf->pFrags[frag].bufSize - fragOffset;
+	pBuf = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+	while (MV_TRUE) {
+		if (size <= bufSize) {
+			mvOsCacheUnmap(NULL, mvOsIoVirtToPhy(NULL, pBuf), size);
+			return MV_OK;
+		}
+
+		mvOsCacheUnmap(NULL, mvOsIoVirtToPhy(NULL, pBuf), bufSize);
+		size -= bufSize;
+		frag++;
+		if (frag >= pMbuf->numFrags)
+			break;
+
+		bufSize = pMbuf->pFrags[frag].bufSize;
+		pBuf = pMbuf->pFrags[frag].bufVirtPtr;
+	}
+	mvOsPrintf("%s: Mbuf is FULL - %d bytes isn't Unmapped\n", __func__, size);
+	return MV_FULL;
+}
+
+/*************************************** Local Functions ******************************/
+
+/*******************************************************************************
+* mvCesaFragReqProcess - Process fragmented request
+*
+* DESCRIPTION:
+*       This function processes a fragment of fragmented request (First, Middle or Last)
+*
+*
+* INPUT:
+*       MV_CESA_REQ* pReq   - Pointer to the request in the request queue.
+*
+* RETURN:
+*       MV_OK        - The fragment is successfully passed to HW for processing.
+*       MV_TERMINATE - Means, that HW finished its work on this packet and no more
+*                    interrupts will be generated for this request.
+*                    Function mvCesaReadyGet() must be called to complete request
+*                    processing and get request result.
+*
+*******************************************************************************/
+static MV_STATUS mvCesaFragReqProcess(MV_U8 chan, MV_CESA_REQ *pReq, MV_U8 frag)
+{
+	int i, copySize, cryptoDataSize, macDataSize, sid;
+	int cryptoIvOffset, digestOffset;
+	MV_U32 config;
+	MV_CESA_COMMAND *pCmd = pReq->pCmd;
+	MV_CESA_SA *pSA;
+	MV_CESA_MBUF *pMbuf;
+	MV_DMA_DESC *pDmaDesc = pReq->dma[frag].pDmaFirst;
+	MV_U8 *pSramBuf = cesaSramVirtPtr[chan]->buf;
+	int macTotalLen = 0;
+	int fixOffset, cryptoOffset, macOffset;
+
+	cesaStats.fragCount++;
+
+	sid = pReq->pCmd->sessionId;
+
+	pSA = pCesaSAD[sid];
+
+	cryptoIvOffset = digestOffset = 0;
+	i = macDataSize = 0;
+	cryptoDataSize = 0;
+
+	/* First fragment processing */
+	if (pReq->fragMode == MV_CESA_FRAG_FIRST) {
+		/* pReq->frags monitors processing of fragmented request between fragments */
+		pReq->frags.bufOffset = 0;
+		pReq->frags.cryptoSize = 0;
+		pReq->frags.macSize = 0;
+
+		config = pSA->config | (MV_CESA_FRAG_FIRST << MV_CESA_FRAG_MODE_OFFSET);
+
+		/* fixOffset can be not equal to zero only for FIRST fragment */
+		fixOffset = pReq->fixOffset;
+		/* For FIRST fragment crypto and mac offsets are taken from pCmd */
+		cryptoOffset = pCmd->cryptoOffset;
+		macOffset = pCmd->macOffset;
+
+		copySize = sizeof(cesaSramVirtPtr[chan]->buf) - pReq->fixOffset;
+
+		/* Find fragment size: Must meet all requirements for CRYPTO and MAC
+		 * cryptoDataSize   - size of data will be encrypted/decrypted in this fragment
+		 * macDataSize      - size of data will be signed/verified in this fragment
+		 * copySize         - size of data will be copied from srcMbuf to SRAM and
+		 *                  back to dstMbuf for this fragment
+		 */
+		mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset, &copySize, &cryptoDataSize, &macDataSize);
+
+		if ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) {
+			/* CryptoIV special processing */
+			if ((pSA->config & MV_CESA_CRYPTO_MODE_MASK) == (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT)) {
+				/* In CBC mode for encode direction when IV from user */
+				if ((pCmd->ivFromUser) &&
+				    ((pSA->config & MV_CESA_DIRECTION_MASK) ==
+				     (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT))) {
+
+					/* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer,
+					 * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place
+					 * in the buffer to SRAM IVPointer
+					 */
+					i += mvCesaDmaCopyPrepare(chan, pCmd->pSrc, cesaSramVirtPtr[chan]->cryptoIV,
+									&pDmaDesc[i], MV_FALSE, pCmd->ivOffset,
+									pSA->cryptoIvSize, pCmd->skipFlush);
+				}
+
+				/* Special processing when IV is not located in the first fragment */
+				if (pCmd->ivOffset > (copySize - pSA->cryptoIvSize)) {
+					/* Prepare dummy place for cryptoIV in SRAM */
+					cryptoIvOffset = cesaSramVirtPtr[chan]->tempCryptoIV - mvCesaSramAddrGet(chan);
+
+					/* For Decryption: Copy IV value from pCmd->ivOffset to Special SRAM place */
+					if ((pSA->config & MV_CESA_DIRECTION_MASK) ==
+					    (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) {
+						i += mvCesaDmaCopyPrepare(chan, pCmd->pSrc,
+										cesaSramVirtPtr[chan]->tempCryptoIV,
+										&pDmaDesc[i], MV_FALSE, pCmd->ivOffset,
+										pSA->cryptoIvSize, pCmd->skipFlush);
+					} else {
+						/* For Encryption when IV is NOT from User: */
+						/* Copy IV from SRAM to buffer (pCmd->ivOffset) */
+						if (pCmd->ivFromUser == 0) {
+							/* copy IV value from cryptoIV to Buffer (pCmd->ivOffset) */
+							i += mvCesaDmaCopyPrepare(chan, pCmd->pSrc,
+								cesaSramVirtPtr[chan]->cryptoIV, &pDmaDesc[i],
+								MV_TRUE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
+						}
+					}
+				} else {
+					cryptoIvOffset = pCmd->ivOffset;
+				}
+			}
+		}
+
+		if ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) {
+			/* MAC digest special processing on Decode direction */
+			if ((pSA->config & MV_CESA_DIRECTION_MASK) == (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) {
+				/* Save digest from pCmd->digestOffset */
+				mvCesaCopyFromMbuf(pReq->frags.orgDigest,
+						   pCmd->pSrc, pCmd->digestOffset, pSA->digestSize);
+
+				/* If pCmd->digestOffset is not located on the first */
+				if (pCmd->digestOffset > (copySize - pSA->digestSize)) {
+					MV_U8 digestZero[MV_CESA_MAX_DIGEST_SIZE];
+
+					/* Set zeros to pCmd->digestOffset (DRAM) */
+					memset(digestZero, 0, MV_CESA_MAX_DIGEST_SIZE);
+					mvCesaCopyToMbuf(digestZero, pCmd->pSrc, pCmd->digestOffset, pSA->digestSize);
+
+					/* Prepare dummy place for digest in SRAM */
+					digestOffset = cesaSramVirtPtr[chan]->tempDigest - mvCesaSramAddrGet(chan);
+				} else {
+					digestOffset = pCmd->digestOffset;
+				}
+			}
+		}
+		/* Update SA in SRAM */
+		if (cesaLastSid[chan] != sid) {
+			mvCesaSramSaUpdate(chan, sid, &pDmaDesc[i]);
+			i++;
+		}
+
+		pReq->fragMode = MV_CESA_FRAG_MIDDLE;
+	} else {
+		/* Continue fragment */
+		fixOffset = 0;
+		cryptoOffset = 0;
+		macOffset = 0;
+		if ((pCmd->pSrc->mbufSize - pReq->frags.bufOffset) <= sizeof(cesaSramVirtPtr[chan]->buf)) {
+			/* Last fragment */
+			config = pSA->config | (MV_CESA_FRAG_LAST << MV_CESA_FRAG_MODE_OFFSET);
+			pReq->fragMode = MV_CESA_FRAG_LAST;
+			copySize = pCmd->pSrc->mbufSize - pReq->frags.bufOffset;
+
+			if ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) {
+				macDataSize = pCmd->macLength - pReq->frags.macSize;
+
+				/* If pCmd->digestOffset is not located on last fragment */
+				if (pCmd->digestOffset < pReq->frags.bufOffset) {
+					/* Prepare dummy place for digest in SRAM */
+					digestOffset = cesaSramVirtPtr[chan]->tempDigest - mvCesaSramAddrGet(chan);
+				} else {
+					digestOffset = pCmd->digestOffset - pReq->frags.bufOffset;
+				}
+				pReq->frags.newDigestOffset = digestOffset;
+				macTotalLen = pCmd->macLength;
+			}
+
+			if ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET))
+				cryptoDataSize = pCmd->cryptoLength - pReq->frags.cryptoSize;
+
+			/* cryptoIvOffset - don't care */
+		} else {
+			/* Middle fragment */
+			config = pSA->config | (MV_CESA_FRAG_MIDDLE << MV_CESA_FRAG_MODE_OFFSET);
+			copySize = sizeof(cesaSramVirtPtr[chan]->buf);
+			/* digestOffset and cryptoIvOffset - don't care */
+
+			/* Find fragment size */
+			mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset,
+					   &copySize, &cryptoDataSize, &macDataSize);
+		}
+	}
+
+	/********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
+	pMbuf = pCmd->pSrc;
+	i += mvCesaDmaCopyPrepare(chan, pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
+				  MV_FALSE, pReq->frags.bufOffset, copySize, pCmd->skipFlush);
+
+	/* Prepare CESA descriptor to copy from DRAM to SRAM by DMA */
+	mvCesaSramDescrBuild(chan, config, frag,
+			     cryptoOffset + fixOffset, cryptoIvOffset + fixOffset,
+			     cryptoDataSize, macOffset + fixOffset,
+			     digestOffset + fixOffset, macDataSize, macTotalLen, pReq, &pDmaDesc[i]);
+	i++;
+
+	/* Add special descriptor Ownership for CPU */
+	pDmaDesc[i].byteCnt = 0;
+	pDmaDesc[i].phySrcAdd = 0;
+	pDmaDesc[i].phyDestAdd = 0;
+	i++;
+
+	/********* Prepare DMA descriptors to copy from SRAM to pDst *********/
+	pMbuf = pCmd->pDst;
+	i += mvCesaDmaCopyPrepare(chan, pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
+				  MV_TRUE, pReq->frags.bufOffset, copySize, pCmd->skipFlush);
+
+	/* Next field of Last DMA descriptor must be NULL */
+	pDmaDesc[i - 1].phyNextDescPtr = 0;
+	pReq->dma[frag].pDmaLast = &pDmaDesc[i - 1];
+	mvOsCacheFlush(NULL, pReq->dma[frag].pDmaFirst, i * sizeof(MV_DMA_DESC));
+
+	/*mvCesaDebugDescriptor(&cesaSramVirtPtr[chan]->desc[frag]); */
+
+	pReq->frags.bufOffset += copySize;
+	pReq->frags.cryptoSize += cryptoDataSize;
+	pReq->frags.macSize += macDataSize;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaReqProcess - Process regular (Non-fragmented) request
+*
+* DESCRIPTION:
+*       This function processes the whole (not fragmented) request
+*
+* INPUT:
+*       MV_CESA_REQ* pReq   - Pointer to the request in the request queue.
+*
+* RETURN:
+*       MV_OK   - The request is successfully passed to HW for processing.
+*       Other   - Failure. The request will not be processed
+*
+*******************************************************************************/
+static MV_STATUS mvCesaReqProcess(MV_U8 chan, MV_CESA_REQ *pReq)
+{
+	MV_CESA_MBUF *pMbuf;
+	MV_DMA_DESC *pDmaDesc;
+	MV_U8 *pSramBuf;
+	int sid, i, fixOffset;
+	MV_CESA_SA *pSA;
+	MV_CESA_COMMAND *pCmd = pReq->pCmd;
+
+	cesaStats.procCount++;
+
+	sid = pCmd->sessionId;
+	pSA = pCesaSAD[sid];
+	pDmaDesc = pReq->dma[0].pDmaFirst;
+	pSramBuf = cesaSramVirtPtr[chan]->buf;
+	fixOffset = pReq->fixOffset;
+
+/*
+    mvOsPrintf("mvCesaReqProcess: sid=%d, pSA=%p, pDmaDesc=%p, pSramBuf=%p\n",
+			sid, pSA, pDmaDesc, pSramBuf);
+*/
+	i = 0;
+
+	/* Crypto IV Special processing in CBC mode for Encryption direction */
+	if (((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) &&
+	    ((pSA->config & MV_CESA_CRYPTO_MODE_MASK) == (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT)) &&
+	    ((pSA->config & MV_CESA_DIRECTION_MASK) == (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) &&
+	    (pCmd->ivFromUser)) {
+		/* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer,
+		 * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place
+		 * in the buffer to SRAM IVPointer
+		 */
+		i += mvCesaDmaCopyPrepare(chan, pCmd->pSrc, cesaSramVirtPtr[chan]->cryptoIV, &pDmaDesc[i],
+					  MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
+	}
+
+	/* Update SA in SRAM */
+	if (cesaLastSid[chan] != sid) {
+		mvCesaSramSaUpdate(chan, sid, &pDmaDesc[i]);
+		i++;
+	}
+
+	/********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
+	pMbuf = pCmd->pSrc;
+	i += mvCesaDmaCopyPrepare(chan, pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
+				  MV_FALSE, 0, pMbuf->mbufSize, pCmd->skipFlush);
+
+	/* Prepare Security Accelerator descriptor to SRAM words 0 - 7 */
+	mvCesaSramDescrBuild(chan, pSA->config, 0, pCmd->cryptoOffset + fixOffset,
+			     pCmd->ivOffset + fixOffset, pCmd->cryptoLength,
+			     pCmd->macOffset + fixOffset, pCmd->digestOffset + fixOffset,
+			     pCmd->macLength, pCmd->macLength, pReq, &pDmaDesc[i]);
+	i++;
+
+	/* Add special descriptor Ownership for CPU */
+	pDmaDesc[i].byteCnt = 0;
+	pDmaDesc[i].phySrcAdd = 0;
+	pDmaDesc[i].phyDestAdd = 0;
+	i++;
+
+	/********* Prepare DMA descriptors to copy from SRAM to pDst *********/
+	pMbuf = pCmd->pDst;
+	i += mvCesaDmaCopyPrepare(chan, pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
+				  MV_TRUE, 0, pMbuf->mbufSize, pCmd->skipFlush);
+
+	/* Next field of Last DMA descriptor must be NULL */
+	pDmaDesc[i - 1].phyNextDescPtr = 0;
+	pReq->dma[0].pDmaLast = &pDmaDesc[i - 1];
+	mvOsCacheFlush(NULL, pReq->dma[0].pDmaFirst, i * sizeof(MV_DMA_DESC));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaSramDescrBuild - Set CESA descriptor in SRAM
+*
+* DESCRIPTION:
+*       This function builds CESA descriptor in SRAM from all Command parameters
+*
+*
+* INPUT:
+*       int     chan            - CESA channel uses the descriptor
+*       MV_U32  config          - 32 bits of WORD_0 in CESA descriptor structure
+*       int     cryptoOffset    - Offset from the beginning of SRAM buffer where
+*                               data for encryption/decription is started.
+*       int     ivOffset        - Offset of crypto IV from the SRAM base. Valid only
+*                               for first fragment.
+*       int     cryptoLength    - Size (in bytes) of data for encryption/descryption
+*                               operation on this fragment.
+*       int     macOffset       - Offset from the beginning of SRAM buffer where
+*                               data for Authentication is started
+*       int     digestOffset    - Offset from the beginning of SRAM buffer where
+*                               digest is located. Valid for first and last fragments.
+*       int     macLength       - Size (in bytes) of data for Authentication
+*                               operation on this fragment.
+*       int     macTotalLen     - Toatl size (in bytes) of data for Authentication
+*                               operation on the whole request (packet). Valid for
+*                               last fragment only.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+static void mvCesaSramDescrBuild(MV_U8 chan, MV_U32 config, int frag,
+				 int cryptoOffset, int ivOffset, int cryptoLength,
+				 int macOffset, int digestOffset, int macLength,
+				 int macTotalLen, MV_CESA_REQ *pReq, MV_DMA_DESC *pDmaDesc)
+{
+	MV_CESA_DESC *pCesaDesc = &pReq->pCesaDesc[frag];
+	MV_CESA_DESC *pSramDesc = &cesaSramVirtPtr[chan]->desc;
+	MV_U16 sramBufOffset = (MV_U16)((MV_U8 *)cesaSramVirtPtr[chan]->buf - mvCesaSramAddrGet(chan));
+
+	pCesaDesc->config = MV_32BIT_LE(config);
+
+	if ((config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) {
+		/* word 1 */
+		pCesaDesc->cryptoSrcOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset);
+		pCesaDesc->cryptoDstOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset);
+		/* word 2 */
+		pCesaDesc->cryptoDataLen = MV_16BIT_LE(cryptoLength);
+		/* word 3 */
+		pCesaDesc->cryptoKeyOffset = MV_16BIT_LE((MV_U16) (cesaSramVirtPtr[chan]->sramSA.cryptoKey -
+								   mvCesaSramAddrGet(chan)));
+		/* word 4 */
+		pCesaDesc->cryptoIvOffset = MV_16BIT_LE((MV_U16) (cesaSramVirtPtr[chan]->cryptoIV - mvCesaSramAddrGet(chan)));
+		pCesaDesc->cryptoIvBufOffset = MV_16BIT_LE(sramBufOffset + ivOffset);
+	}
+
+	if ((config & MV_CESA_OPERATION_MASK) != (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) {
+		/* word 5 */
+		pCesaDesc->macSrcOffset = MV_16BIT_LE(sramBufOffset + macOffset);
+		pCesaDesc->macTotalLen = MV_16BIT_LE(macTotalLen);
+
+		/* word 6 */
+		pCesaDesc->macDigestOffset = MV_16BIT_LE(sramBufOffset + digestOffset);
+		pCesaDesc->macDataLen = MV_16BIT_LE(macLength);
+
+		/* word 7 */
+		pCesaDesc->macInnerIvOffset = MV_16BIT_LE((MV_U16) (cesaSramVirtPtr[chan]->sramSA.macInnerIV -
+								    mvCesaSramAddrGet(chan)));
+		pCesaDesc->macOuterIvOffset = MV_16BIT_LE((MV_U16) (cesaSramVirtPtr[chan]->sramSA.macOuterIV -
+								    mvCesaSramAddrGet(chan)));
+	}
+	/* Prepare DMA descriptor to CESA descriptor from DRAM to SRAM */
+	pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&pReq->cesaDescBuf, pCesaDesc));
+	pDmaDesc->phyDestAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(chan, NULL, (MV_U8 *) pSramDesc));
+	pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_DESC) | BIT31);
+
+	/* flush Source buffer */
+	mvOsCacheFlush(NULL, pCesaDesc, sizeof(MV_CESA_DESC));
+}
+
+/*******************************************************************************
+* mvCesaSramSaUpdate - Move required SA information to SRAM if needed.
+*
+* DESCRIPTION:
+*   Copy to SRAM values of the required SA.
+*
+*
+* INPUT:
+*       short       sid          - Session ID needs SRAM Cache update
+*       MV_DMA_DESC *pDmaDesc   - Pointer to DMA descriptor used to
+*                                copy SA values from DRAM to SRAM.
+*
+* RETURN:
+*       MV_OK           - Cache entry for this SA copied to SRAM.
+*       MV_NO_CHANGE    - Cache entry for this SA already exist in SRAM
+*
+*******************************************************************************/
+static INLINE void mvCesaSramSaUpdate(MV_U8 chan, short sid, MV_DMA_DESC *pDmaDesc)
+{
+	MV_CESA_SA *pSA = pCesaSAD[sid];
+
+	/* Prepare DMA descriptor to Copy CACHE_SA from SA database in DRAM to SRAM */
+	pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_SRAM_SA) | BIT31);
+	pDmaDesc->phySrcAdd = pSA->sramSAPhysAddr;
+	pDmaDesc->phyDestAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(chan, NULL, (MV_U8 *)&cesaSramVirtPtr[chan]->sramSA));
+
+	/* Source buffer is already flushed during OpenSession */
+	/*mvOsCacheFlush(NULL, &pSA->sramSA, sizeof(MV_CESA_SRAM_SA)); */
+}
+
+/*******************************************************************************
+* mvCesaDmaCopyPrepare - prepare DMA descriptor list to copy data presented by
+*                       Mbuf structure from DRAM to SRAM
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_MBUF*   pMbuf       - pointer to Mbuf structure contains request
+*                                   data in DRAM
+*       MV_U8*          pSramBuf    - pointer to buffer in SRAM where data should
+*                                   be copied to.
+*       MV_DMA_DESC*    pDmaDesc   - pointer to first DMA descriptor for this copy.
+*                                   The function set number of DMA descriptors needed
+*                                   to copy the copySize bytes from Mbuf.
+*       MV_BOOL         isToMbuf    - Copy direction.
+*                                   MV_TRUE means copy from SRAM buffer to Mbuf in DRAM.
+*                                   MV_FALSE means copy from Mbuf in DRAM to SRAM buffer.
+*       int             offset      - Offset in the Mbuf structure that copy should be
+*                                   started from.
+*       int             copySize    - Size of data should be copied.
+*
+* RETURN:
+*       int  - number of DMA descriptors used for the copy.
+*
+*******************************************************************************/
+#ifndef MV_NETBSD
+static INLINE int mvCesaDmaCopyPrepare(MV_U8 chan, MV_CESA_MBUF *pMbuf, MV_U8 *pSramBuf,
+				       MV_DMA_DESC *pDmaDesc, MV_BOOL isToMbuf,
+				       int offset, int copySize, MV_BOOL skipFlush)
+{
+	int bufOffset, bufSize, size, frag, i;
+	MV_U8 *pBuf;
+
+	i = 0;
+
+	/* Calculate start place for copy: fragment number and offset in the fragment */
+	frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset);
+	bufSize = pMbuf->pFrags[frag].bufSize - bufOffset;
+	pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset;
+
+	/* Size accumulate total copy size */
+	size = 0;
+
+	/* Create DMA lists to copy mBuf from pSrc to SRAM */
+	while (size < copySize) {
+		/* Find copy size for each DMA descriptor */
+		bufSize = MV_MIN(bufSize, (copySize - size));
+		pDmaDesc[i].byteCnt = MV_32BIT_LE(bufSize | BIT31);
+		if (isToMbuf) {
+			pDmaDesc[i].phyDestAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
+			pDmaDesc[i].phySrcAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(chan, NULL, (pSramBuf + size)));
+			/* invalidate the buffer */
+			if (skipFlush == MV_FALSE)
+				mvOsCacheInvalidate(NULL, pBuf, bufSize);
+		} else {
+			pDmaDesc[i].phySrcAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
+			pDmaDesc[i].phyDestAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(chan, NULL, (pSramBuf + size)));
+			/* flush the buffer */
+			if (skipFlush == MV_FALSE)
+				mvOsCacheFlush(NULL, pBuf, bufSize);
+		}
+
+		/* Count number of used DMA descriptors */
+		i++;
+		size += bufSize;
+
+		/* go to next fragment in the Mbuf */
+		frag++;
+		pBuf = pMbuf->pFrags[frag].bufVirtPtr;
+		bufSize = pMbuf->pFrags[frag].bufSize;
+	}
+	return i;
+}
+#else /* MV_NETBSD */
+static int mvCesaDmaCopyPrepare(MV_U8 chan, MV_CESA_MBUF *pMbuf, MV_U8 *pSramBuf,
+				MV_DMA_DESC *pDmaDesc, MV_BOOL isToMbuf, int offset, int copySize, MV_BOOL skipFlush)
+{
+	int bufOffset, bufSize, thisSize, size, frag, i;
+	MV_ULONG bufPhys, sramPhys;
+	MV_U8 *pBuf;
+
+	/*
+	 * Calculate start place for copy: fragment number and offset in
+	 * the fragment
+	 */
+	frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset);
+
+	/*
+	 * Get SRAM physical address only once. We can update it in-place
+	 * as we build the descriptor chain.
+	 */
+	sramPhys = mvCesaSramVirtToPhys(chan, NULL, pSramBuf);
+
+	/*
+	 * 'size' accumulates total copy size, 'i' counts desccriptors.
+	 */
+	size = i = 0;
+
+	/* Create DMA lists to copy mBuf from pSrc to SRAM */
+	while (size < copySize) {
+		/*
+		 * Calculate # of bytes to copy from the current fragment,
+		 * and the pointer to the start of data
+		 */
+		bufSize = pMbuf->pFrags[frag].bufSize - bufOffset;
+		pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset;
+		bufOffset = 0;	/* First frag may be non-zero */
+		frag++;
+
+		/*
+		 * As long as there is data in the current fragment...
+		 */
+		while (bufSize > 0) {
+			/*
+			 * Ensure we don't cross an MMU page boundary.
+			 * XXX: This is NetBSD-specific, but it is a
+			 * quick and dirty way to fix the problem.
+			 * A true HAL would rely on the OS-specific
+			 * driver to do this...
+			 */
+			thisSize = PAGE_SIZE - (((MV_ULONG) pBuf) & (PAGE_SIZE - 1));
+			thisSize = MV_MIN(bufSize, thisSize);
+			/*
+			 * Make sure we don't copy more than requested
+			 */
+			if (thisSize > (copySize - size)) {
+				thisSize = copySize - size;
+				bufSize = 0;
+			}
+
+			/*
+			 * Physicall address of this fragment
+			 */
+			bufPhys = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
+
+			/*
+			 * Set up the descriptor
+			 */
+			pDmaDesc[i].byteCnt = MV_32BIT_LE(thisSize | BIT31);
+			if (isToMbuf) {
+				pDmaDesc[i].phyDestAdd = bufPhys;
+				pDmaDesc[i].phySrcAdd = MV_32BIT_LE(sramPhys);
+				/* invalidate the buffer */
+				if (skipFlush == MV_FALSE)
+					mvOsCacheInvalidate(NULL, pBuf, thisSize);
+			} else {
+				pDmaDesc[i].phySrcAdd = bufPhys;
+				pDmaDesc[i].phyDestAdd = MV_32BIT_LE(sramPhys);
+				/* flush the buffer */
+				if (skipFlush == MV_FALSE)
+					mvOsCacheFlush(NULL, pBuf, thisSize);
+			}
+
+			pDmaDesc[i].phyNextDescPtr = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, (&pDmaDesc[i + 1])));
+
+			/* flush the DMA desc */
+			mvOsCacheFlush(NULL, &pDmaDesc[i], sizeof(MV_DMA_DESC));
+
+			/* Update state */
+			bufSize -= thisSize;
+			sramPhys += thisSize;
+			pBuf += thisSize;
+			size += thisSize;
+			i++;
+		}
+	}
+
+	return i;
+}
+#endif /* MV_NETBSD */
+/*******************************************************************************
+* mvCesaHmacIvGet - Calculate Inner and Outter values from HMAC key
+*
+* DESCRIPTION:
+*       This function calculate Inner and Outer values used for HMAC algorithm.
+*       This operation allows improve performance fro the whole HMAC processing.
+*
+* INPUT:
+*       MV_CESA_MAC_MODE    macMode     - Authentication mode: HMAC_MD5, HMAC_SHA1 or HMAC_SHA2.
+*       unsigned char       key[]       - Pointer to HMAC key.
+*       int                 keyLength   - Size of HMAC key (maximum 64 bytes)
+*
+* OUTPUT:
+*       unsigned char       innerIV[]   - HASH(key^inner)
+*       unsigned char       outerIV[]   - HASH(key^outter)
+*
+* RETURN:   None
+*
+*******************************************************************************/
+static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
+			    unsigned char innerIV[], unsigned char outerIV[])
+{
+	unsigned char inner[MV_CESA_MAX_MAC_KEY_LENGTH];
+	unsigned char outer[MV_CESA_MAX_MAC_KEY_LENGTH];
+	int i, digestSize = 0;
+#if defined(MV_CPU_LE) || defined(MV_PPC)
+	MV_U32 swapped32, val32, *pVal32;
+#endif
+	for (i = 0; i < keyLength; i++) {
+		inner[i] = 0x36 ^ key[i];
+		outer[i] = 0x5c ^ key[i];
+	}
+
+	for (i = keyLength; i < MV_CESA_MAX_MAC_KEY_LENGTH; i++) {
+		inner[i] = 0x36;
+		outer[i] = 0x5c;
+	}
+	if (macMode == MV_CESA_MAC_HMAC_MD5) {
+		MV_MD5_CONTEXT ctx;
+
+		mvMD5Init(&ctx);
+		mvMD5Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
+
+		memcpy(innerIV, ctx.buf, MV_CESA_MD5_DIGEST_SIZE);
+		memset(&ctx, 0, sizeof(ctx));
+
+		mvMD5Init(&ctx);
+		mvMD5Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
+		memcpy(outerIV, ctx.buf, MV_CESA_MD5_DIGEST_SIZE);
+		memset(&ctx, 0, sizeof(ctx));
+		digestSize = MV_CESA_MD5_DIGEST_SIZE;
+	} else if (macMode == MV_CESA_MAC_HMAC_SHA1) {
+		MV_SHA1_CTX ctx;
+
+		mvSHA1Init(&ctx);
+		mvSHA1Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
+		memcpy(innerIV, ctx.state, MV_CESA_SHA1_DIGEST_SIZE);
+		memset(&ctx, 0, sizeof(ctx));
+
+		mvSHA1Init(&ctx);
+		mvSHA1Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
+		memcpy(outerIV, ctx.state, MV_CESA_SHA1_DIGEST_SIZE);
+		memset(&ctx, 0, sizeof(ctx));
+		digestSize = MV_CESA_SHA1_DIGEST_SIZE;
+	} else if (macMode == MV_CESA_MAC_HMAC_SHA2) {
+		sha256_context ctx;
+
+		mvSHA256Init(&ctx);
+		mvSHA256Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
+		memcpy(innerIV, ctx.state, MV_CESA_SHA2_DIGEST_SIZE);
+		memset(&ctx, 0, sizeof(ctx));
+
+		mvSHA256Init(&ctx);
+		mvSHA256Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
+		memcpy(outerIV, ctx.state, MV_CESA_SHA2_DIGEST_SIZE);
+		memset(&ctx, 0, sizeof(ctx));
+		digestSize = MV_CESA_SHA2_DIGEST_SIZE;
+	} else {
+		mvOsPrintf("hmacGetIV: Unexpected macMode %d\n", macMode);
+	}
+#if defined(MV_CPU_LE) || defined(MV_PPC)
+	/* 32 bits Swap of Inner and Outer values */
+	pVal32 = (MV_U32 *) innerIV;
+	for (i = 0; i < digestSize / 4; i++) {
+		val32 = *pVal32;
+		swapped32 = MV_BYTE_SWAP_32BIT(val32);
+		*pVal32 = swapped32;
+		pVal32++;
+	}
+	pVal32 = (MV_U32 *) outerIV;
+	for (i = 0; i < digestSize / 4; i++) {
+		val32 = *pVal32;
+		swapped32 = MV_BYTE_SWAP_32BIT(val32);
+		*pVal32 = swapped32;
+		pVal32++;
+	}
+#endif /* defined(MV_CPU_LE) || defined(MV_PPC) */
+}
+
+/*******************************************************************************
+* mvCesaFragSha1Complete - Complete SHA1 authentication started by HW using SW
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_MBUF*   pMbuf           - Pointer to Mbuf structure where data
+*                                       for SHA1 is placed.
+*       int             offset          - Offset in the Mbuf structure where
+*                                       unprocessed data for SHA1 is started.
+*       MV_U8*          pOuterIV        - Pointer to OUTER for this session.
+*                                       If pOuterIV==NULL - MAC mode is HASH_SHA1
+*                                       If pOuterIV!=NULL - MAC mode is HMAC_SHA1
+*       int             macLeftSize     - Size of unprocessed data for SHA1.
+*       int             macTotalSize    - Total size of data for SHA1 in the
+*                                       request (processed + unprocessed)
+*
+* OUTPUT:
+*       MV_U8*     pDigest  - Pointer to place where calculated Digest will
+*                           be stored.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+static void mvCesaFragSha1Complete(MV_U8 chan, MV_CESA_MBUF *pMbuf, int offset,
+				   MV_U8 *pOuterIV, int macLeftSize, int macTotalSize, MV_U8 *pDigest)
+{
+	MV_SHA1_CTX ctx;
+	MV_U8 *pData;
+	int i, frag, fragOffset, size;
+
+	/* Read temporary Digest from HW */
+	for (i = 0; i < MV_CESA_SHA1_DIGEST_SIZE / 4; i++)
+		ctx.state[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(chan, i));
+
+	/* Initialize MV_SHA1_CTX structure */
+	memset(ctx.buffer, 0, 64);
+	/* Set count[0] in bits. 32 bits is enough for 512 MBytes */
+	/* so count[1] is always 0 */
+	ctx.count[0] = ((macTotalSize - macLeftSize) * 8);
+	ctx.count[1] = 0;
+
+	/* If HMAC - add size of Inner block (64 bytes) ro count[0] */
+	if (pOuterIV != NULL)
+		ctx.count[0] += (64 * 8);
+
+	/* Get place of unprocessed data in the Mbuf structure */
+	frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
+	if (frag == MV_INVALID) {
+		mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+		return;
+	}
+
+	pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+	size = pMbuf->pFrags[frag].bufSize - fragOffset;
+
+	/* Complete Inner part */
+	while (macLeftSize > 0) {
+		if (macLeftSize <= size) {
+			mvSHA1Update(&ctx, pData, macLeftSize);
+			break;
+		}
+		mvSHA1Update(&ctx, pData, size);
+		macLeftSize -= size;
+		frag++;
+		pData = pMbuf->pFrags[frag].bufVirtPtr;
+		size = pMbuf->pFrags[frag].bufSize;
+	}
+	mvSHA1Final(pDigest, &ctx);
+/*
+    mvOsPrintf("mvCesaFragSha1Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
+			pOuterIV, macLeftSize, macTotalSize);
+	mvDebugMemDump(pDigest, MV_CESA_SHA1_DIGEST_SIZE, 1);
+*/
+
+	if (pOuterIV != NULL) {
+		/* If HMAC - Complete Outer part */
+		for (i = 0; i < MV_CESA_SHA1_DIGEST_SIZE / 4; i++) {
+#if defined(MV_CPU_LE) || defined(MV_ARM)
+			ctx.state[i] = MV_BYTE_SWAP_32BIT(((MV_U32 *) pOuterIV)[i]);
+#else
+			ctx.state[i] = ((MV_U32 *) pOuterIV)[i];
+#endif
+		}
+		memset(ctx.buffer, 0, 64);
+
+		ctx.count[0] = 64 * 8;
+		ctx.count[1] = 0;
+		mvSHA1Update(&ctx, pDigest, MV_CESA_SHA1_DIGEST_SIZE);
+		mvSHA1Final(pDigest, &ctx);
+	}
+}
+
+/*******************************************************************************
+* mvCesaFragMd5Complete - Complete MD5 authentication started by HW using SW
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_MBUF*   pMbuf           - Pointer to Mbuf structure where data
+*                                       for SHA1 is placed.
+*       int             offset          - Offset in the Mbuf structure where
+*                                       unprocessed data for MD5 is started.
+*       MV_U8*          pOuterIV        - Pointer to OUTER for this session.
+*                                       If pOuterIV==NULL - MAC mode is HASH_MD5
+*                                       If pOuterIV!=NULL - MAC mode is HMAC_MD5
+*       int             macLeftSize     - Size of unprocessed data for MD5.
+*       int             macTotalSize    - Total size of data for MD5 in the
+*                                       request (processed + unprocessed)
+*
+* OUTPUT:
+*       MV_U8*     pDigest  - Pointer to place where calculated Digest will
+*                           be stored.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+static void mvCesaFragMd5Complete(MV_U8 chan, MV_CESA_MBUF *pMbuf, int offset,
+				  MV_U8 *pOuterIV, int macLeftSize, int macTotalSize, MV_U8 *pDigest)
+{
+	MV_MD5_CONTEXT ctx;
+	MV_U8 *pData;
+	int i, frag, fragOffset, size;
+
+	/* Read temporary Digest from HW */
+	for (i = 0; i < MV_CESA_MD5_DIGEST_SIZE / 4; i++)
+		ctx.buf[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(chan, i));
+
+	memset(ctx.in, 0, 64);
+
+	/* Set count[0] in bits. 32 bits is enough for 512 MBytes */
+	/* so count[1] is always 0 */
+	ctx.bits[0] = ((macTotalSize - macLeftSize) * 8);
+	ctx.bits[1] = 0;
+
+	/* If HMAC - add size of Inner block (64 bytes) ro count[0] */
+	if (pOuterIV != NULL)
+		ctx.bits[0] += (64 * 8);
+
+	frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
+	if (frag == MV_INVALID) {
+		mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+		return;
+	}
+
+	pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+	size = pMbuf->pFrags[frag].bufSize - fragOffset;
+
+	/* Complete Inner part */
+	while (macLeftSize > 0) {
+		if (macLeftSize <= size) {
+			mvMD5Update(&ctx, pData, macLeftSize);
+			break;
+		}
+		mvMD5Update(&ctx, pData, size);
+		macLeftSize -= size;
+		frag++;
+		pData = pMbuf->pFrags[frag].bufVirtPtr;
+		size = pMbuf->pFrags[frag].bufSize;
+	}
+	mvMD5Final(pDigest, &ctx);
+
+/*
+    mvOsPrintf("mvCesaFragMd5Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
+				pOuterIV, macLeftSize, macTotalSize);
+    mvDebugMemDump(pDigest, MV_CESA_MD5_DIGEST_SIZE, 1);
+*/
+	if (pOuterIV != NULL) {
+		/* Complete Outer part */
+		for (i = 0; i < MV_CESA_MD5_DIGEST_SIZE / 4; i++) {
+#if defined(MV_CPU_LE) || defined(MV_ARM)
+			ctx.buf[i] = MV_BYTE_SWAP_32BIT(((MV_U32 *) pOuterIV)[i]);
+#else
+			ctx.buf[i] = ((MV_U32 *) pOuterIV)[i];
+#endif
+		}
+		memset(ctx.in, 0, 64);
+
+		ctx.bits[0] = 64 * 8;
+		ctx.bits[1] = 0;
+		mvMD5Update(&ctx, pDigest, MV_CESA_MD5_DIGEST_SIZE);
+		mvMD5Final(pDigest, &ctx);
+	}
+}
+
+/*******************************************************************************
+* mvCesaFragSha2Complete - Complete SHA2 authentication started by HW using SW
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_MBUF*   pMbuf           - Pointer to Mbuf structure where data
+*                                       for SHA2 is placed.
+*       int             offset          - Offset in the Mbuf structure where
+*                                       unprocessed data for SHA2 is started.
+*       MV_U8*          pOuterIV        - Pointer to OUTER for this session.
+*                                       If pOuterIV==NULL - MAC mode is HASH_SHA2
+*                                       If pOuterIV!=NULL - MAC mode is HMAC_SHA2
+*       int             macLeftSize     - Size of unprocessed data for SHA2.
+*       int             macTotalSize    - Total size of data for SHA2 in the
+*                                       request (processed + unprocessed)
+*
+* OUTPUT:
+*       MV_U8*     pDigest  - Pointer to place where calculated Digest will
+*                           be stored.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+static void mvCesaFragSha2Complete(MV_U8 chan, MV_CESA_MBUF *pMbuf, int offset,
+				   MV_U8 *pOuterIV, int macLeftSize, int macTotalSize, MV_U8 *pDigest)
+{
+	sha256_context ctx;
+	MV_U8 *pData;
+	int i, frag, fragOffset, size;
+
+	/* Read temporary Digest from HW */
+	for (i = 0; i < MV_CESA_SHA2_DIGEST_SIZE / 4; i++)
+		ctx.state[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(chan, i));
+
+	/* Initialize sha256_context structure */
+	memset(ctx.buffer, 0, 64);
+	/* Set total[0] in bits. 32 bits is enough for 512 MBytes */
+	/* so total[1] is always 0 */
+	ctx.total[0] = ((macTotalSize - macLeftSize) * 8);
+	ctx.total[1] = 0;
+
+	/* If HMAC - add size of Inner block (64 bytes) ro count[0] */
+	if (pOuterIV != NULL)
+		ctx.total[0] += (64 * 8);
+
+	/* Get place of unprocessed data in the Mbuf structure */
+	frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
+	if (frag == MV_INVALID) {
+		mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+		return;
+	}
+
+	pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+	size = pMbuf->pFrags[frag].bufSize - fragOffset;
+
+	/* Complete Inner part */
+	while (macLeftSize > 0) {
+		if (macLeftSize <= size) {
+			mvSHA256Update(&ctx, pData, macLeftSize);
+			break;
+		}
+		mvSHA256Update(&ctx, pData, size);
+		macLeftSize -= size;
+		frag++;
+		pData = pMbuf->pFrags[frag].bufVirtPtr;
+		size = pMbuf->pFrags[frag].bufSize;
+	}
+	mvSHA256Finish(&ctx, pDigest);
+/*
+    mvOsPrintf("mvCesaFragSha2Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
+			pOuterIV, macLeftSize, macTotalSize);
+	mvDebugMemDump(pDigest, MV_CESA_SHA2_DIGEST_SIZE, 1);
+*/
+
+	if (pOuterIV != NULL) {
+		/* If HMAC - Complete Outer part */
+		for (i = 0; i < MV_CESA_SHA2_DIGEST_SIZE / 4; i++) {
+#if defined(MV_CPU_LE) || defined(MV_ARM)
+			ctx.state[i] = MV_BYTE_SWAP_32BIT(((MV_U32 *) pOuterIV)[i]);
+#else
+			ctx.state[i] = ((MV_U32 *) pOuterIV)[i];
+#endif
+		}
+		memset(ctx.buffer, 0, 64);
+
+		ctx.total[0] = 64 * 8;
+		ctx.total[1] = 0;
+		mvSHA256Update(&ctx, pDigest, MV_CESA_SHA2_DIGEST_SIZE);
+		mvSHA256Finish(&ctx, pDigest);
+	}
+}
+
+
+/*******************************************************************************
+* mvCesaFragAuthComplete -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* 	MB_U8		chan,
+*       MV_CESA_REQ*    pReq,
+*       MV_CESA_SA*     pSA,
+*       int             macDataSize
+*
+* RETURN:
+*       MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaFragAuthComplete(MV_U8 chan, MV_CESA_REQ *pReq, MV_CESA_SA *pSA, int macDataSize)
+{
+	MV_CESA_COMMAND *pCmd = pReq->pCmd;
+	MV_U8 *pDigest;
+	MV_CESA_MAC_MODE macMode;
+	MV_U8 *pOuterIV = NULL;
+
+	/* Copy data from Source fragment to Destination */
+	if (pCmd->pSrc != pCmd->pDst)
+		mvCesaMbufCopy(pCmd->pDst, pReq->frags.bufOffset, pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
+
+/*
+    mvCesaCopyFromMbuf(cesaSramVirtPtr[chan]->buf[0], pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
+    mvCesaCopyToMbuf(cesaSramVirtPtr[chan]->buf[0], pCmd->pDst, pReq->frags.bufOffset, macDataSize);
+*/
+	pDigest = (mvCesaSramAddrGet(chan) + pReq->frags.newDigestOffset);
+
+	macMode = (pSA->config & MV_CESA_MAC_MODE_MASK) >> MV_CESA_MAC_MODE_OFFSET;
+/*
+    mvOsPrintf("macDataSize=%d, macLength=%d, digestOffset=%d, macMode=%d\n",
+		macDataSize, pCmd->macLength, pCmd->digestOffset, macMode);
+*/
+	switch (macMode) {
+	case MV_CESA_MAC_HMAC_MD5:
+		pOuterIV = pSA->pSramSA->macOuterIV;
+		/* fallthrough */
+
+	case MV_CESA_MAC_MD5:
+		mvCesaFragMd5Complete(chan, pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
+				      macDataSize, pCmd->macLength, pDigest);
+		break;
+
+	case MV_CESA_MAC_HMAC_SHA1:
+		pOuterIV = pSA->pSramSA->macOuterIV;
+		/* fallthrough */
+
+	case MV_CESA_MAC_SHA1:
+		mvCesaFragSha1Complete(chan, pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
+				       macDataSize, pCmd->macLength, pDigest);
+		break;
+
+	case MV_CESA_MAC_HMAC_SHA2:
+		pOuterIV = pSA->pSramSA->macOuterIV;
+		/* fallthrough */
+
+	case MV_CESA_MAC_SHA2:
+		mvCesaFragSha2Complete(chan, pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
+				       macDataSize, pCmd->macLength, pDigest);
+		break;
+
+	default:
+		mvOsPrintf("mvCesaFragAuthComplete: Unexpected macMode %d\n", macMode);
+		return MV_BAD_PARAM;
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaCtrModeInit -
+*
+* DESCRIPTION:
+*
+*
+* INPUT: NONE
+*
+*
+* RETURN:
+*       MV_CESA_COMMAND*
+*
+*******************************************************************************/
+static MV_CESA_COMMAND *mvCesaCtrModeInit(void)
+{
+	MV_CESA_MBUF *pMbuf;
+	MV_U8 *pBuf;
+	MV_CESA_COMMAND *pCmd;
+
+	pBuf = mvOsMalloc(sizeof(MV_CESA_COMMAND) + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) + 100);
+	if (pBuf == NULL) {
+		mvOsPrintf("mvCesaCtrModeInit: Can't allocate %u bytes for CTR Mode\n",
+			   sizeof(MV_CESA_COMMAND) + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO));
+		return NULL;
+	}
+	pCmd = (MV_CESA_COMMAND *)pBuf;
+	pBuf += sizeof(MV_CESA_COMMAND);
+
+	pMbuf = (MV_CESA_MBUF *)pBuf;
+	pBuf += sizeof(MV_CESA_MBUF);
+
+	pMbuf->pFrags = (MV_BUF_INFO *)pBuf;
+
+	pMbuf->numFrags = 1;
+	pCmd->pSrc = pMbuf;
+	pCmd->pDst = pMbuf;
+/*
+    mvOsPrintf("CtrModeInit: pCmd=%p, pSrc=%p, pDst=%p, pFrags=%p\n", pCmd, pCmd->pSrc, pCmd->pDst,
+			pMbuf->pFrags);
+*/
+	return pCmd;
+}
+
+/*******************************************************************************
+* mvCesaCtrModePrepare -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd
+*
+* RETURN:
+*       MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd)
+{
+	MV_CESA_MBUF *pMbuf;
+	MV_U8 *pBuf, *pIV;
+	MV_U32 counter, *pCounter;
+	int cryptoSize = MV_ALIGN_UP(pCmd->cryptoLength, MV_CESA_AES_BLOCK_SIZE);
+/*
+    mvOsPrintf("CtrModePrepare: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n",
+			pCmd, pCmd->pSrc, pCmd->pDst,
+			pCtrModeCmd, pCtrModeCmd->pSrc, pCtrModeCmd->pDst);
+*/
+	pMbuf = pCtrModeCmd->pSrc;
+
+	/* Allocate buffer for Key stream */
+	pBuf = mvOsIoCachedMalloc(cesaOsHandle, cryptoSize, &pMbuf->pFrags[0].bufPhysAddr, &pMbuf->pFrags[0].memHandle);
+	if (pBuf == NULL) {
+		mvOsPrintf("mvCesaCtrModePrepare: Can't allocate %d bytes\n", cryptoSize);
+		return MV_OUT_OF_CPU_MEM;
+	}
+	memset(pBuf, 0, cryptoSize);
+	mvOsCacheFlush(NULL, pBuf, cryptoSize);
+
+	pMbuf->pFrags[0].bufVirtPtr = pBuf;
+	pMbuf->mbufSize = cryptoSize;
+	pMbuf->pFrags[0].bufSize = cryptoSize;
+
+	pCtrModeCmd->pReqPrv = pCmd->pReqPrv;
+	pCtrModeCmd->sessionId = pCmd->sessionId;
+
+	/* ivFromUser and ivOffset are don't care */
+	pCtrModeCmd->cryptoOffset = 0;
+	pCtrModeCmd->cryptoLength = cryptoSize;
+
+	/* digestOffset, macOffset and macLength are don't care */
+
+	mvCesaCopyFromMbuf(pBuf, pCmd->pSrc, pCmd->ivOffset, MV_CESA_AES_BLOCK_SIZE);
+	pCounter = (MV_U32 *)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter)));
+	counter = *pCounter;
+	counter = MV_32BIT_BE(counter);
+	pIV = pBuf;
+	cryptoSize -= MV_CESA_AES_BLOCK_SIZE;
+
+	/* fill key stream */
+	while (cryptoSize > 0) {
+		pBuf += MV_CESA_AES_BLOCK_SIZE;
+		memcpy(pBuf, pIV, MV_CESA_AES_BLOCK_SIZE - sizeof(counter));
+		pCounter = (MV_U32 *)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter)));
+		counter++;
+		*pCounter = MV_32BIT_BE(counter);
+		cryptoSize -= MV_CESA_AES_BLOCK_SIZE;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaCtrModeComplete -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd
+*
+* RETURN:
+*       MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd)
+{
+	int srcFrag, dstFrag, srcOffset, dstOffset, keyOffset, srcSize, dstSize;
+	int cryptoSize = pCmd->cryptoLength;
+	MV_U8 *pSrc, *pDst, *pKey;
+	MV_STATUS status = MV_OK;
+/*
+    mvOsPrintf("CtrModeComplete: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n",
+			pCmd, pCmd->pSrc, pCmd->pDst,
+			pOrgCmd, pOrgCmd->pSrc, pOrgCmd->pDst);
+*/
+	/* XOR source data with key stream to destination data */
+	pKey = pCmd->pDst->pFrags[0].bufVirtPtr;
+	keyOffset = 0;
+
+	if ((pOrgCmd->pSrc != pOrgCmd->pDst) && (pOrgCmd->cryptoOffset > 0)) {
+		/* Copy Prefix from source buffer to destination buffer */
+
+		status = mvCesaMbufCopy(pOrgCmd->pDst, 0, pOrgCmd->pSrc, 0, pOrgCmd->cryptoOffset);
+/*
+		status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc, 0, pOrgCmd->cryptoOffset);
+		status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst, 0, pOrgCmd->cryptoOffset);
+*/
+	}
+
+	srcFrag = mvCesaMbufOffset(pOrgCmd->pSrc, pOrgCmd->cryptoOffset, &srcOffset);
+	pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr;
+	srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize;
+
+	dstFrag = mvCesaMbufOffset(pOrgCmd->pDst, pOrgCmd->cryptoOffset, &dstOffset);
+	pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr;
+	dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize;
+
+	while (cryptoSize > 0) {
+		pDst[dstOffset] = (pSrc[srcOffset] ^ pKey[keyOffset]);
+
+		cryptoSize--;
+		dstOffset++;
+		srcOffset++;
+		keyOffset++;
+
+		if (srcOffset >= srcSize) {
+			srcFrag++;
+			srcOffset = 0;
+			pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr;
+			srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize;
+		}
+
+		if (dstOffset >= dstSize) {
+			dstFrag++;
+			dstOffset = 0;
+			pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr;
+			dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize;
+		}
+	}
+
+	if (pOrgCmd->pSrc != pOrgCmd->pDst) {
+		/* Copy Suffix from source buffer to destination buffer */
+		srcOffset = pOrgCmd->cryptoOffset + pOrgCmd->cryptoLength;
+
+		if ((pOrgCmd->pDst->mbufSize - srcOffset) > 0) {
+			status = mvCesaMbufCopy(pOrgCmd->pDst, srcOffset,
+						pOrgCmd->pSrc, srcOffset, pOrgCmd->pDst->mbufSize - srcOffset);
+		}
+
+/*
+		status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc, srcOffset, pOrgCmd->pSrc->mbufSize - srcOffset);
+		status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst, srcOffset, pOrgCmd->pDst->mbufSize - srcOffset);
+*/
+	}
+
+	/* Free buffer used for Key stream */
+	mvOsIoCachedFree(cesaOsHandle, pCmd->pDst->pFrags[0].bufSize,
+			 pCmd->pDst->pFrags[0].bufPhysAddr,
+			 pCmd->pDst->pFrags[0].bufVirtPtr, pCmd->pDst->pFrags[0].memHandle);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaCtrModeFinish -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_COMMAND* pCmd
+*
+* RETURN:
+*       MV_STATUS
+*
+*******************************************************************************/
+static void mvCesaCtrModeFinish(MV_CESA_COMMAND *pCmd)
+{
+	mvOsFree(pCmd);
+}
+
+/*******************************************************************************
+* mvCesaParamCheck -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset
+*
+* RETURN:
+*       MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaParamCheck(MV_CESA_SA *pSA, MV_CESA_COMMAND *pCmd, MV_U8 *pFixOffset)
+{
+	MV_U8 fixOffset = 0xFF;
+
+/*
+	mvOsPrintf("mvCesaParamCheck:macOffset=%d digestOffset=%d cryptoOffset=%d ivOffset=%d"
+		"cryptoLength=%d cryptoBlockSize=%d mbufSize=%d\n",
+		pCmd->macOffset, pCmd->digestOffset, pCmd->cryptoOffset, pCmd->ivOffset,
+		pCmd->cryptoLength, pSA->cryptoBlockSize, pCmd->pSrc->mbufSize);
+*/
+
+	/* Check AUTH operation parameters */
+	if (((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET))) {
+		/* MAC offset should be at least 4 byte aligned */
+		if (MV_IS_NOT_ALIGN(pCmd->macOffset, 4)) {
+			mvOsPrintf("mvCesaAction: macOffset %d must be 4 byte aligned\n", pCmd->macOffset);
+			return MV_BAD_PARAM;
+		}
+		/* Digest offset must be 4 byte aligned */
+		if (MV_IS_NOT_ALIGN(pCmd->digestOffset, 4)) {
+			mvOsPrintf("mvCesaAction: digestOffset %d must be 4 byte aligned\n", pCmd->digestOffset);
+			return MV_BAD_PARAM;
+		}
+		/* In addition all offsets should be the same alignment: 8 or 4 */
+		if (fixOffset == 0xFF) {
+			fixOffset = (pCmd->macOffset % 8);
+		} else {
+			if ((pCmd->macOffset % 8) != fixOffset) {
+				mvOsPrintf("mvCesaAction: macOffset %d mod 8 must be equal %d\n",
+					   pCmd->macOffset, fixOffset);
+				return MV_BAD_PARAM;
+			}
+		}
+		if ((pCmd->digestOffset % 8) != fixOffset) {
+			mvOsPrintf("mvCesaAction: digestOffset %d mod 8 must be equal %d\n",
+				   pCmd->digestOffset, fixOffset);
+			return MV_BAD_PARAM;
+		}
+	}
+	/* Check CRYPTO operation parameters */
+	if (((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET))) {
+		/* CryptoOffset should be at least 4 byte aligned */
+		if (MV_IS_NOT_ALIGN(pCmd->cryptoOffset, 4)) {
+			mvOsPrintf("CesaAction: cryptoOffset=%d must be 4 byte aligned\n", pCmd->cryptoOffset);
+			return MV_BAD_PARAM;
+		}
+		/* cryptoLength should be the whole number of blocks */
+		if (MV_IS_NOT_ALIGN(pCmd->cryptoLength, pSA->cryptoBlockSize)) {
+			mvOsPrintf("mvCesaAction: cryptoLength=%d must be %d byte aligned\n",
+				   pCmd->cryptoLength, pSA->cryptoBlockSize);
+			return MV_BAD_PARAM;
+		}
+		if (fixOffset == 0xFF) {
+			fixOffset = (pCmd->cryptoOffset % 8);
+		} else {
+			/* In addition all offsets should be the same alignment: 8 or 4 */
+			if ((pCmd->cryptoOffset % 8) != fixOffset) {
+				mvOsPrintf("mvCesaAction: cryptoOffset %d mod 8 must be equal %d \n",
+					   pCmd->cryptoOffset, fixOffset);
+				return MV_BAD_PARAM;
+			}
+		}
+
+		/* check for CBC mode */
+		if (pSA->cryptoIvSize > 0) {
+			/* cryptoIV must not be part of CryptoLength */
+			if (((pCmd->ivOffset + pSA->cryptoIvSize) > pCmd->cryptoOffset) &&
+			    (pCmd->ivOffset < (pCmd->cryptoOffset + pCmd->cryptoLength))) {
+				mvOsPrintf
+				    ("mvCesaFragParamCheck: cryptoIvOffset (%d) is part of cryptoLength (%d+%d)\n",
+				     pCmd->ivOffset, pCmd->macOffset, pCmd->macLength);
+				return MV_BAD_PARAM;
+			}
+
+			/* ivOffset must be 4 byte aligned */
+			if (MV_IS_NOT_ALIGN(pCmd->ivOffset, 4)) {
+				mvOsPrintf("CesaAction: ivOffset=%d must be 4 byte aligned\n", pCmd->ivOffset);
+				return MV_BAD_PARAM;
+			}
+			/* In addition all offsets should be the same alignment: 8 or 4 */
+			if ((pCmd->ivOffset % 8) != fixOffset) {
+				mvOsPrintf("mvCesaAction: ivOffset %d mod 8 must be %d\n", pCmd->ivOffset, fixOffset);
+				return MV_BAD_PARAM;
+			}
+		}
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaFragParamCheck -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_U8 chan, MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd
+*
+* RETURN:
+*       MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaFragParamCheck(MV_U8 chan, MV_CESA_SA *pSA, MV_CESA_COMMAND *pCmd)
+{
+	int offset;
+
+	if (((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET))) {
+		/* macOffset must be less that SRAM buffer size */
+		if (pCmd->macOffset > (sizeof(cesaSramVirtPtr[chan]->buf) - MV_CESA_AUTH_BLOCK_SIZE)) {
+			mvOsPrintf("mvCesaFragParamCheck: macOffset is too large (%d)\n", pCmd->macOffset);
+			return MV_BAD_PARAM;
+		}
+		/* macOffset+macSize must be more than mbufSize - SRAM buffer size */
+		if (((pCmd->macOffset + pCmd->macLength) > pCmd->pSrc->mbufSize) ||
+		    ((pCmd->pSrc->mbufSize - (pCmd->macOffset + pCmd->macLength)) >= sizeof(cesaSramVirtPtr[chan]->buf))) {
+			mvOsPrintf("mvCesaFragParamCheck: macLength is too large (%d), mbufSize=%d\n",
+				   pCmd->macLength, pCmd->pSrc->mbufSize);
+			return MV_BAD_PARAM;
+		}
+	}
+
+	if (((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET))) {
+		/* cryptoOffset must be less that SRAM buffer size */
+		/* 4 for possible fixOffset */
+		if ((pCmd->cryptoOffset + 4) > (sizeof(cesaSramVirtPtr[chan]->buf) - pSA->cryptoBlockSize)) {
+			mvOsPrintf("mvCesaFragParamCheck: cryptoOffset is too large (%d)\n", pCmd->cryptoOffset);
+			return MV_BAD_PARAM;
+		}
+
+		/* cryptoOffset+cryptoSize must be more than mbufSize - SRAM buffer size */
+		if (((pCmd->cryptoOffset + pCmd->cryptoLength) > pCmd->pSrc->mbufSize) ||
+		    ((pCmd->pSrc->mbufSize - (pCmd->cryptoOffset + pCmd->cryptoLength)) >=
+		     (sizeof(cesaSramVirtPtr[chan]->buf) - pSA->cryptoBlockSize))) {
+			mvOsPrintf("mvCesaFragParamCheck: cryptoLength is too large (%d), mbufSize=%d\n",
+				   pCmd->cryptoLength, pCmd->pSrc->mbufSize);
+			return MV_BAD_PARAM;
+		}
+	}
+
+	/* When MAC_THEN_CRYPTO or CRYPTO_THEN_MAC */
+	if (((pSA->config & MV_CESA_OPERATION_MASK) ==
+	     (MV_CESA_MAC_THEN_CRYPTO << MV_CESA_OPERATION_OFFSET)) ||
+	    ((pSA->config & MV_CESA_OPERATION_MASK) == (MV_CESA_CRYPTO_THEN_MAC << MV_CESA_OPERATION_OFFSET))) {
+
+		/* abs(cryptoOffset-macOffset) must be aligned cryptoBlockSize */
+		if (pCmd->cryptoOffset > pCmd->macOffset)
+			offset = pCmd->cryptoOffset - pCmd->macOffset;
+		else
+			offset = pCmd->macOffset - pCmd->cryptoOffset;
+
+		if (MV_IS_NOT_ALIGN(offset, pSA->cryptoBlockSize)) {
+/*
+		mvOsPrintf("mvCesaFragParamCheck: (cryptoOffset - macOffset) must be %d byte aligned\n",
+				pSA->cryptoBlockSize);
+*/
+			return MV_NOT_ALLOWED;
+		}
+		/* Digest must not be part of CryptoLength */
+		if (((pCmd->digestOffset + pSA->digestSize) > pCmd->cryptoOffset) &&
+		    (pCmd->digestOffset < (pCmd->cryptoOffset + pCmd->cryptoLength))) {
+/*
+		mvOsPrintf("mvCesaFragParamCheck: digestOffset (%d) is part of cryptoLength (%d+%d)\n",
+					pCmd->digestOffset, pCmd->cryptoOffset, pCmd->cryptoLength);
+*/
+			return MV_NOT_ALLOWED;
+		}
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaFragSizeFind -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd,
+*       int cryptoOffset, int macOffset,
+*
+* OUTPUT:
+*       int* pCopySize, int* pCryptoDataSize, int* pMacDataSize
+*
+* RETURN:
+*       MV_STATUS
+*
+*******************************************************************************/
+static void mvCesaFragSizeFind(MV_CESA_SA *pSA, MV_CESA_REQ *pReq,
+			       int cryptoOffset, int macOffset, int *pCopySize, int *pCryptoDataSize, int *pMacDataSize)
+{
+	MV_CESA_COMMAND *pCmd = pReq->pCmd;
+	int cryptoDataSize, macDataSize, copySize;
+
+	cryptoDataSize = macDataSize = 0;
+	copySize = *pCopySize;
+
+	if ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) {
+		cryptoDataSize = MV_MIN((copySize - cryptoOffset), (pCmd->cryptoLength - (pReq->frags.cryptoSize + 1)));
+
+		/* cryptoSize for each fragment must be the whole number of blocksSize */
+		if (MV_IS_NOT_ALIGN(cryptoDataSize, pSA->cryptoBlockSize)) {
+			cryptoDataSize = MV_ALIGN_DOWN(cryptoDataSize, pSA->cryptoBlockSize);
+			copySize = cryptoOffset + cryptoDataSize;
+		}
+	}
+	if ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) {
+		macDataSize = MV_MIN((copySize - macOffset), (pCmd->macLength - (pReq->frags.macSize + 1)));
+
+		/* macSize for each fragment (except last) must be the whole number of blocksSize */
+		if (MV_IS_NOT_ALIGN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE)) {
+			macDataSize = MV_ALIGN_DOWN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE);
+			copySize = macOffset + macDataSize;
+		}
+		cryptoDataSize = copySize - cryptoOffset;
+	}
+	*pCopySize = copySize;
+
+	if (pCryptoDataSize != NULL)
+		*pCryptoDataSize = cryptoDataSize;
+
+	if (pMacDataSize != NULL)
+		*pMacDataSize = macDataSize;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCesa.h b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesa.h
new file mode 100755
index 0000000..6fded48
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesa.h
@@ -0,0 +1,360 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvCesa.h - Header File for Cryptographic Engines and Security Accelerator
+*
+* DESCRIPTION:
+*       This header file contains macros typedefs and function declaration for
+*       the Marvell Cryptographic Engines and Security Accelerator.
+*
+*******************************************************************************/
+
+#ifndef __mvCesa_h__
+#define __mvCesa_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysCesaConfig.h"
+#include "mvCesaRegs.h"
+
+typedef enum {
+	MV_CESA_SPLIT_NONE = 0,
+	MV_CESA_SPLIT_FIRST = 1,
+	MV_CESA_SPLIT_SECOND = 2
+} MV_CESA_SPLIT;
+
+typedef struct {
+	MV_ULONG sramPhysBase[MV_CESA_CHANNELS];
+	MV_U8 *sramVirtBase[MV_CESA_CHANNELS];
+	MV_U16 sramOffset[MV_CESA_CHANNELS];
+	MV_U16 ctrlModel;	/* Controller Model     */
+	MV_U8 ctrlRev;		/* Controller Revision  */
+} MV_CESA_HAL_DATA;
+
+/* Redefine MV_DMA_DESC structure */
+typedef struct _mvDmaDesc {
+	MV_U32 byteCnt;	/* The total number of bytes to transfer        */
+	MV_U32 phySrcAdd;	/* The physical source address                  */
+	MV_U32 phyDestAdd;	/* The physical destination address             */
+	MV_U32 phyNextDescPtr;	/* If we are using chain mode DMA transfer,     */
+	/* then this pointer should point to the        */
+	/* physical address of the next descriptor,     */
+	/* otherwise it should be NULL.                 */
+} MV_DMA_DESC;
+
+#define MV_CESA_AUTH_BLOCK_SIZE         64	/* bytes */
+
+#define MV_CESA_MD5_DIGEST_SIZE         16	/* bytes */
+#define MV_CESA_SHA1_DIGEST_SIZE        20	/* bytes */
+#define MV_CESA_SHA2_DIGEST_SIZE	32	/* bytes */
+
+#define MV_CESA_MAX_DIGEST_SIZE         MV_CESA_SHA2_DIGEST_SIZE
+
+#define MV_CESA_DES_KEY_LENGTH          8	/* bytes = 64 bits */
+#define MV_CESA_3DES_KEY_LENGTH         24	/* bytes = 192 bits */
+#define MV_CESA_AES_128_KEY_LENGTH      16	/* bytes = 128 bits */
+#define MV_CESA_AES_192_KEY_LENGTH      24	/* bytes = 192 bits */
+#define MV_CESA_AES_256_KEY_LENGTH      32	/* bytes = 256 bits */
+
+#define MV_CESA_MAX_CRYPTO_KEY_LENGTH   MV_CESA_AES_256_KEY_LENGTH
+
+#define MV_CESA_DES_BLOCK_SIZE          8	/* bytes = 64 bits */
+#define MV_CESA_3DES_BLOCK_SIZE         8	/* bytes = 64 bits */
+
+#define MV_CESA_AES_BLOCK_SIZE          16	/* bytes = 128 bits */
+
+#define MV_CESA_MAX_IV_LENGTH           MV_CESA_AES_BLOCK_SIZE
+
+#define MV_CESA_MAX_MAC_KEY_LENGTH      64	/* bytes */
+
+typedef struct {
+	MV_U8 cryptoKey[MV_CESA_MAX_CRYPTO_KEY_LENGTH];
+	MV_U8 macKey[MV_CESA_MAX_MAC_KEY_LENGTH];
+	MV_CESA_OPERATION operation;
+	MV_CESA_DIRECTION direction;
+	MV_CESA_CRYPTO_ALG cryptoAlgorithm;
+	MV_CESA_CRYPTO_MODE cryptoMode;
+	MV_U8 cryptoKeyLength;
+	MV_CESA_MAC_MODE macMode;
+	MV_U8 macKeyLength;
+	MV_U8 digestSize;
+} MV_CESA_OPEN_SESSION;
+
+typedef struct {
+	MV_BUF_INFO *pFrags;
+	MV_U16 numFrags;
+	MV_U16 mbufSize;
+} MV_CESA_MBUF;
+
+typedef struct {
+	void *pReqPrv;	/* instead of reqId */
+	MV_U32 retCode;
+	MV_16 sessionId;
+	MV_U16 mbufSize;
+	MV_U32 reqId;	/* Driver internal */
+} MV_CESA_RESULT;
+
+typedef void (*MV_CESA_CALLBACK) (MV_CESA_RESULT *pResult);
+
+typedef struct {
+	void *pReqPrv;	/* instead of reqId */
+	MV_CESA_MBUF *pSrc;
+	MV_CESA_MBUF *pDst;
+	MV_CESA_CALLBACK *pFuncCB;
+	MV_16 sessionId;
+	MV_U16 ivFromUser;
+	MV_U16 ivOffset;
+	MV_U16 cryptoOffset;
+	MV_U16 cryptoLength;
+	MV_U16 digestOffset;
+	MV_U16 macOffset;
+	MV_U16 macLength;
+	MV_BOOL skipFlush;
+	MV_CESA_SPLIT split;
+	MV_U32 reqId;	/* Driver internal */
+} MV_CESA_COMMAND;
+
+MV_STATUS mvCesaHalInit(int numOfSession, int queueDepth, void *osHandle, MV_CESA_HAL_DATA *halData);
+MV_STATUS mvCesaTdmaWinInit(MV_U8 chan, MV_UNIT_WIN_INFO *addrWinMap);
+MV_STATUS mvCesaFinish(void);
+MV_STATUS mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short *pSid);
+MV_STATUS mvCesaSessionClose(short sid);
+MV_STATUS mvCesaCryptoIvSet(MV_U8 chan, MV_U8 *pIV, int ivSize);
+MV_STATUS mvCesaAction(MV_U8 chan, MV_CESA_COMMAND *pCmd);
+MV_STATUS mvCesaReadyGet(MV_U8 chan, MV_CESA_RESULT *pResult);
+int mvCesaMbufOffset(MV_CESA_MBUF *pMbuf, int offset, int *pBufOffset);
+MV_STATUS mvCesaCopyFromMbuf(MV_U8 *pDst, MV_CESA_MBUF *pSrcMbuf, int offset, int size);
+MV_STATUS mvCesaCopyToMbuf(MV_U8 *pSrc, MV_CESA_MBUF *pDstMbuf, int offset, int size);
+MV_STATUS mvCesaMbufCopy(MV_CESA_MBUF *pMbufDst, int dstMbufOffset,
+			MV_CESA_MBUF *pMbufSrc, int srcMbufOffset, int size);
+
+/********** Debug functions ********/
+void mvCesaDebugMbuf(const char *str, MV_CESA_MBUF *pMbuf, int offset, int size);
+void mvCesaDebugSA(short sid, int mode);
+void mvCesaDebugStats(void);
+void mvCesaDebugStatsClear(void);
+void mvCesaDebugRegs(void);
+void mvCesaDebugStatus(void);
+void mvCesaDebugQueue(int mode);
+void mvCesaDebugSram(int mode);
+void mvCesaDebugSAD(int mode);
+
+/********  CESA Private definitions ********/
+#define MV_CESA_TDMA_CTRL_VALUE       (MV_CESA_TDMA_DST_BURST_MASK(MV_CESA_TDMA_BURST_128B) 		\
+						| MV_CESA_TDMA_SRC_BURST_MASK(MV_CESA_TDMA_BURST_128B)  \
+						| MV_CESA_TDMA_OUTSTAND_READ_EN_MASK                    \
+						| MV_CESA_TDMA_NO_BYTE_SWAP_MASK			\
+						| MV_CESA_TDMA_ENABLE_MASK)
+
+#define MV_CESA_MAX_PKT_SIZE        (64 * 1024)
+#define MV_CESA_MAX_MBUF_FRAGS      20
+
+#define MV_CESA_MAX_REQ_FRAGS       ((MV_CESA_MAX_PKT_SIZE / MV_CESA_MAX_BUF_SIZE) + 1)
+
+#define MV_CESA_MAX_DMA_DESC    (MV_CESA_MAX_MBUF_FRAGS*2 + 5)
+
+#define MAX_CESA_CHAIN_LENGTH	20
+
+typedef enum {
+	MV_CESA_IDLE = 0,
+	MV_CESA_PENDING,
+	MV_CESA_PROCESS,
+	MV_CESA_READY,
+	MV_CESA_CHAIN,
+} MV_CESA_STATE;
+
+/* Session database */
+
+/* Map of Key materials of the session in SRAM.
+ * Each field must be 8 byte aligned
+ * Total size: 32 + 24 + 24 = 80 bytes
+ */
+typedef struct {
+	MV_U8 cryptoKey[MV_CESA_MAX_CRYPTO_KEY_LENGTH];
+	MV_U8 macInnerIV[MV_CESA_MAX_DIGEST_SIZE];
+	MV_U8 reservedInner[4];
+	MV_U8 macOuterIV[MV_CESA_MAX_DIGEST_SIZE];
+	MV_U8 reservedOuter[4];
+} MV_CESA_SRAM_SA;
+
+typedef struct {
+	MV_CESA_SRAM_SA *pSramSA;
+	MV_U8 *sramSABuff;	/* holds initial allocation virtual address */
+	MV_U32 sramSABuffSize;
+	MV_ULONG sramSAPhysAddr;	/* holds initial allocation physical address  */
+	MV_U32 memHandle;
+	MV_U32 config;
+	MV_U8 cryptoKeyLength;
+	MV_U8 cryptoIvSize;
+	MV_U8 cryptoBlockSize;
+	MV_U8 digestSize;
+	MV_U8 macKeyLength;
+	MV_U8 ctrMode;
+	MV_U32 count;
+} MV_CESA_SA;
+
+/* DMA list management */
+typedef struct {
+	MV_DMA_DESC *pDmaFirst;
+	MV_DMA_DESC *pDmaLast;
+} MV_CESA_DMA;
+
+typedef struct {
+	MV_U8 numFrag;
+	MV_U8 nextFrag;
+	int bufOffset;
+	int cryptoSize;
+	int macSize;
+	int newDigestOffset;
+	MV_U8 orgDigest[MV_CESA_MAX_DIGEST_SIZE];
+} MV_CESA_FRAGS;
+
+/* Request queue */
+typedef struct {
+	MV_U8 state;
+	MV_U8 fragMode;
+	MV_U8 fixOffset;
+	MV_CESA_COMMAND *pCmd;
+	MV_CESA_COMMAND *pOrgCmd;
+	MV_BUF_INFO dmaDescBuf;
+	MV_CESA_DMA dma[MV_CESA_MAX_REQ_FRAGS];
+	MV_BUF_INFO cesaDescBuf;
+	MV_CESA_DESC *pCesaDesc;
+	MV_CESA_FRAGS frags;
+} MV_CESA_REQ;
+
+/* SRAM map */
+/* Total SRAM size calculation */
+/*  SRAM size =
+ *              MV_CESA_MAX_BUF_SIZE  +
+ *              sizeof(MV_CESA_DESC)  +
+ *              MV_CESA_MAX_IV_LENGTH +
+ *              MV_CESA_MAX_IV_LENGTH +
+ *              MV_CESA_MAX_DIGEST_SIZE +
+ *              sizeof(MV_CESA_SRAM_SA)
+ *            = 1600 + 32 + 16 + 16 + 24 + 80 + 280 (reserved) = 2048 bytes
+ *            = 3200 + 32 + 16 + 16 + 24 + 80 + 728 (reserved) = 4096 bytes
+ */
+typedef struct {
+	MV_U8 buf[MV_CESA_MAX_BUF_SIZE];
+	MV_CESA_DESC desc;
+	MV_U8 cryptoIV[MV_CESA_MAX_IV_LENGTH];
+	MV_U8 tempCryptoIV[MV_CESA_MAX_IV_LENGTH];
+	MV_U8 tempDigest[MV_CESA_MAX_DIGEST_SIZE + 4];
+	MV_CESA_SRAM_SA sramSA;
+} MV_CESA_SRAM_MAP;
+
+typedef struct {
+	MV_U32 openedCount;
+	MV_U32 closedCount;
+	MV_U32 fragCount;
+	MV_U32 reqCount;
+	MV_U32 maxReqCount;
+	MV_U32 procCount;
+	MV_U32 readyCount;
+	MV_U32 notReadyCount;
+	MV_U32 startCount;
+#ifdef MV_CESA_CHAIN_MODE
+	MV_U32 maxChainUsage;
+#endif			/* MV_CESA_CHAIN_MODE */
+} MV_CESA_STATS;
+
+/* External variables */
+
+extern MV_CESA_STATS cesaStats;
+extern MV_CESA_FRAGS cesaFrags;
+extern MV_CESA_SA **pCesaSAD;
+extern MV_U32 cesaMaxSA;
+extern MV_CESA_REQ *pCesaReqFirst[MV_CESA_CHANNELS];
+extern MV_CESA_REQ *pCesaReqLast[MV_CESA_CHANNELS];
+extern MV_CESA_REQ *pCesaReqEmpty[MV_CESA_CHANNELS];
+extern MV_CESA_REQ *pCesaReqProcess[MV_CESA_CHANNELS];
+extern int cesaQueueDepth[MV_CESA_CHANNELS];
+extern int cesaReqResources[MV_CESA_CHANNELS];
+
+#ifdef MV_CESA_CHAIN_MODE
+	extern MV_U32 cesaChainLength[MV_CESA_CHANNELS];
+#endif				/* MV_CESA_CHAIN_MODE */
+
+extern MV_CESA_SRAM_MAP *cesaSramVirtPtr[MV_CESA_CHANNELS];
+
+static INLINE MV_ULONG mvCesaVirtToPhys(MV_BUF_INFO *pBufInfo, void *pVirt)
+{
+	return (pBufInfo->bufPhysAddr + ((MV_U8 *)pVirt - pBufInfo->bufVirtPtr));
+}
+
+/* Additional DEBUG functions */
+void mvCesaDebugSramSA(MV_CESA_SRAM_SA *pSramSA, int mode);
+void mvCesaDebugCmd(MV_CESA_COMMAND *pCmd, int mode);
+void mvCesaDebugDescriptor(MV_CESA_DESC *pDesc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __mvCesa_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaAddrDec.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaAddrDec.c
new file mode 100755
index 0000000..555b1bc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaAddrDec.c
@@ -0,0 +1,289 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvCesa.h"
+#include "mvCesaRegs.h"
+
+MV_TARGET tdmaAddrDecPrioTable[] = {
+#if defined(MV_INCLUDE_SDRAM_CS0)
+	SDRAM_CS0,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS1)
+	SDRAM_CS1,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS2)
+	SDRAM_CS2,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS3)
+	SDRAM_CS3,
+#endif
+	TBL_TERM
+};
+
+static MV_STATUS cesaWinOverlapDetect(MV_U8 chan, MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
+static MV_STATUS mvCesaTdmaWinRead(MV_U8 chan, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin);
+static MV_STATUS mvCesaTdmaWinWrite(MV_U8 chan, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin);
+
+/*******************************************************************************
+* mvCesaTdmaWinRead.
+*
+* DESCRIPTION:
+*       Read TDMA target address window.
+*
+* INPUT:
+*	chan - Channel ID.
+*       winNum - TDMA target address decode window number.
+*
+* OUTPUT:
+*       pDecWin - TDMA target window data structure.
+*
+* RETURN:
+*	MV_BAD_PARAM if winNum is invalid.
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+static MV_STATUS mvCesaTdmaWinRead(MV_U8 chan, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+	MV_U32 size;
+
+	/* Parameter checking   */
+	if (winNum >= MV_CESA_TDMA_ADDR_DEC_WIN) {
+		mvOsPrintf("%s : ERR. Invalid winNum %d\n", __func__, winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	baseReg = MV_REG_READ(MV_CESA_TDMA_BASE_ADDR_REG(chan, winNum));
+	sizeReg = MV_REG_READ(MV_CESA_TDMA_WIN_CTRL_REG(chan, winNum));
+
+	/* Check if window is enabled   */
+	if (sizeReg & MV_CESA_TDMA_WIN_ENABLE_MASK) {
+		pDecWin->enable = MV_TRUE;
+
+		/* Extract window parameters from registers */
+		pDecWin->targetId = (sizeReg & MV_CESA_TDMA_WIN_TARGET_MASK) >> MV_CESA_TDMA_WIN_TARGET_OFFSET;
+		pDecWin->attrib = (sizeReg & MV_CESA_TDMA_WIN_ATTR_MASK) >> MV_CESA_TDMA_WIN_ATTR_OFFSET;
+
+		size = (sizeReg & MV_CESA_TDMA_WIN_SIZE_MASK) >> MV_CESA_TDMA_WIN_SIZE_OFFSET;
+		pDecWin->addrWin.size = (size + 1) * (1 << MV_CESA_TDMA_WIN_SIZE_OFFSET);
+		pDecWin->addrWin.baseLow = (baseReg & MV_CESA_TDMA_WIN_BASE_MASK);
+		pDecWin->addrWin.baseHigh = 0;
+	} else {
+		pDecWin->enable = MV_FALSE;
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaTdmaWinWrite
+*
+* DESCRIPTION:
+*	This function writes the address decoding registers according to the
+*	given window configuration.
+*
+* INPUT:
+*	chan - Channel ID.
+*       pAddrDecWin - CESA TDMA target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_BAD_PARAM if winNum is invalid or size is not a power of 2.
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+static MV_STATUS mvCesaTdmaWinWrite(MV_U8 chan, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+	MV_U32 size;
+
+	/* Parameter checking   */
+	if (winNum >= MV_CESA_TDMA_ADDR_DEC_WIN) {
+		mvOsPrintf("mvCesaTdmaWinSet: ERR. Invalid win num %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlapps with current windows     */
+	if (MV_TRUE == cesaWinOverlapDetect(chan, winNum, &pDecWin->addrWin)) {
+		mvOsPrintf("%s: ERR. Window %d overlap\n", __func__, winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) {
+		mvOsPrintf("mvCesaTdmaWinSet: Error setting CESA TDMA window %d.\n"
+			   "Address 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pDecWin->addrWin.baseLow, pDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	if (!MV_IS_POWER_OF_2(pDecWin->addrWin.size)) {
+		mvOsPrintf("mvCesaTdmaWinWrite: Error setting CESA window %d. "
+			   "Window size is not a power to 2.", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	size = (pDecWin->addrWin.size / (1 << MV_CESA_TDMA_WIN_SIZE_OFFSET)) - 1;
+
+	/* set Size, Attributes and TargetID */
+	sizeReg = (((pDecWin->targetId << MV_CESA_TDMA_WIN_TARGET_OFFSET) & MV_CESA_TDMA_WIN_TARGET_MASK) |
+		   ((pDecWin->attrib << MV_CESA_TDMA_WIN_ATTR_OFFSET) & MV_CESA_TDMA_WIN_ATTR_MASK) |
+		   ((size << MV_CESA_TDMA_WIN_SIZE_OFFSET) & MV_CESA_TDMA_WIN_SIZE_MASK));
+
+	if (pDecWin->enable == MV_TRUE)
+		sizeReg |= MV_CESA_TDMA_WIN_ENABLE_MASK;
+	else
+		sizeReg &= ~MV_CESA_TDMA_WIN_ENABLE_MASK;
+
+	/* Update Base value  */
+	baseReg = (pDecWin->addrWin.baseLow & MV_CESA_TDMA_WIN_BASE_MASK);
+
+	MV_REG_WRITE(MV_CESA_TDMA_WIN_CTRL_REG(chan, winNum), sizeReg);
+	MV_REG_WRITE(MV_CESA_TDMA_BASE_ADDR_REG(chan, winNum), baseReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* cesaWinOverlapDetect - Detect CESA TDMA address windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviur is expected in case TDMA address decode
+*       windows overlapps.
+*       This function detects TDMA address decode windows overlapping of a
+*       specified window. The function does not check the window itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+* 	chan	    - Channel ID
+*       winNum      - address decode window number.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE     - if the given address window overlap current address
+*                   decode map,
+*       MV_FALSE    - otherwise, MV_ERROR if reading invalid data
+*                   from registers.
+*
+*******************************************************************************/
+static MV_STATUS cesaWinOverlapDetect(MV_U8 chan, MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 winNumIndex;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	for (winNumIndex = 0; winNumIndex < MV_CESA_TDMA_ADDR_DEC_WIN; winNumIndex++) {
+		/* Do not check window itself       */
+		if (winNumIndex == winNum)
+			continue;
+
+		/* Get window parameters    */
+		if (MV_OK != mvCesaTdmaWinRead(chan, winNumIndex, &addrDecWin)) {
+			mvOsPrintf("%s: ERR. TargetWinGet failed\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled windows    */
+		if (addrDecWin.enable == MV_FALSE)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+			return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+MV_STATUS mvCesaTdmaWinInit(MV_U8 chan, MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 winNum;
+	MV_UNIT_WIN_INFO *addrDecWin;
+	MV_U32 winPrioIndex = 0;
+
+	/* First disable all address decode windows */
+	for (winNum = 0; winNum < MV_CESA_TDMA_ADDR_DEC_WIN; winNum++)
+		MV_REG_BIT_RESET(MV_CESA_TDMA_WIN_CTRL_REG(chan, winNum), MV_CESA_TDMA_WIN_ENABLE_MASK);
+
+	/* Go through all windows in user table until table terminator      */
+	winNum = 0;
+	while ((tdmaAddrDecPrioTable[winPrioIndex] != TBL_TERM) && (winNum < MV_CESA_TDMA_ADDR_DEC_WIN)) {
+
+		addrDecWin = &addrWinMap[tdmaAddrDecPrioTable[winPrioIndex]];
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvCesaTdmaWinWrite(chan, winNum, addrDecWin)) {
+				mvOsPrintf("mvCesaTdmaWinSet FAILED: winNum=%d\n", winNum);
+				return MV_ERROR;
+			}
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaDebug.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaDebug.c
new file mode 100755
index 0000000..1ac973c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaDebug.c
@@ -0,0 +1,461 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvDebug.h"
+
+#include "cesa/mvMD5.h"
+#include "cesa/mvSHA1.h"
+#include "cesa/mvSHA256.h"
+#include "cesa/mvCesaRegs.h"
+#include "cesa/mvCesa.h"
+#include "cesa/AES/mvAes.h"
+
+static const char *mvCesaDebugStateStr(MV_CESA_STATE state)
+{
+	switch (state) {
+	case MV_CESA_IDLE:
+		return "Idle";
+
+	case MV_CESA_PENDING:
+		return "Pend";
+
+	case MV_CESA_PROCESS:
+		return "Proc";
+
+	case MV_CESA_READY:
+		return "Ready";
+
+	default:
+		break;
+	}
+	return "Unknown";
+}
+
+static const char *mvCesaDebugOperStr(MV_CESA_OPERATION oper)
+{
+	switch (oper) {
+	case MV_CESA_MAC_ONLY:
+		return "MacOnly";
+
+	case MV_CESA_CRYPTO_ONLY:
+		return "CryptoOnly";
+
+	case MV_CESA_MAC_THEN_CRYPTO:
+		return "MacCrypto";
+
+	case MV_CESA_CRYPTO_THEN_MAC:
+		return "CryptoMac";
+
+	default:
+		break;
+	}
+	return "Null";
+}
+
+static const char *mvCesaDebugCryptoAlgStr(MV_CESA_CRYPTO_ALG cryptoAlg)
+{
+	switch (cryptoAlg) {
+	case MV_CESA_CRYPTO_DES:
+		return "DES";
+
+	case MV_CESA_CRYPTO_3DES:
+		return "3DES";
+
+	case MV_CESA_CRYPTO_AES:
+		return "AES";
+
+	default:
+		break;
+	}
+	return "Null";
+}
+
+static const char *mvCesaDebugMacModeStr(MV_CESA_MAC_MODE macMode)
+{
+	switch (macMode) {
+	case MV_CESA_MAC_MD5:
+		return "MD5";
+
+	case MV_CESA_MAC_SHA1:
+		return "SHA1";
+
+	case MV_CESA_MAC_SHA2:
+		return "SHA2";
+
+	case MV_CESA_MAC_HMAC_MD5:
+		return "HMAC-MD5";
+
+	case MV_CESA_MAC_HMAC_SHA1:
+		return "HMAC_SHA1";
+
+	case MV_CESA_MAC_HMAC_SHA2:
+		return "HMAC_SHA2";
+
+	default:
+		break;
+	}
+	return "Null";
+}
+
+void mvCesaDebugCmd(MV_CESA_COMMAND *pCmd, int mode)
+{
+	mvOsPrintf("pCmd=%p, pReqPrv=%p, pSrc=%p, pDst=%p, pCB=%p, sid=%d\n",
+		   pCmd, pCmd->pReqPrv, pCmd->pSrc, pCmd->pDst, pCmd->pFuncCB, pCmd->sessionId);
+	mvOsPrintf("isUser=%d, ivOffs=%d, crOffs=%d, crLen=%d, digest=%d, macOffs=%d, macLen=%d\n",
+		   pCmd->ivFromUser, pCmd->ivOffset, pCmd->cryptoOffset, pCmd->cryptoLength,
+		   pCmd->digestOffset, pCmd->macOffset, pCmd->macLength);
+}
+
+/* no need to use in tool */
+void mvCesaDebugMbuf(const char *str, MV_CESA_MBUF *pMbuf, int offset, int size)
+{
+	int frag, len, fragOffset;
+
+	if (str != NULL)
+		mvOsPrintf("%s: pMbuf=%p, numFrags=%d, mbufSize=%d\n", str, pMbuf, pMbuf->numFrags, pMbuf->mbufSize);
+
+	frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
+	if (frag == MV_INVALID) {
+		mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+		return;
+	}
+
+	for (; frag < pMbuf->numFrags; frag++) {
+		mvOsPrintf("#%2d. bufVirt=%p, bufSize=%d\n",
+			   frag, pMbuf->pFrags[frag].bufVirtPtr, pMbuf->pFrags[frag].bufSize);
+		if (size > 0) {
+			len = MV_MIN(pMbuf->pFrags[frag].bufSize, size);
+			mvDebugMemDump(pMbuf->pFrags[frag].bufVirtPtr + fragOffset, len, 1);
+			size -= len;
+			fragOffset = 0;
+		}
+	}
+}
+
+void mvCesaDebugRegs(void)
+{
+	MV_U8 chan = 0;
+
+	mvOsPrintf("\t CESA Registers:\n");
+
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+		mvOsPrintf("\n\nChannel %d:\n", chan);
+		mvOsPrintf("===========\n");
+		mvOsPrintf("MV_CESA_CMD_REG                     : 0x%X = 0x%08x\n",
+			MV_CESA_CMD_REG(chan), MV_REG_READ(MV_CESA_CMD_REG(chan)));
+
+		mvOsPrintf("MV_CESA_CHAN_DESC_OFFSET_REG        : 0x%X = 0x%08x\n",
+			MV_CESA_CHAN_DESC_OFFSET_REG(chan), MV_REG_READ(MV_CESA_CHAN_DESC_OFFSET_REG(chan)));
+
+		mvOsPrintf("MV_CESA_CFG_REG                     : 0x%X = 0x%08x\n",
+			MV_CESA_CFG_REG(chan), MV_REG_READ(MV_CESA_CFG_REG(chan)));
+
+		mvOsPrintf("MV_CESA_STATUS_REG                  : 0x%X = 0x%08x\n",
+			MV_CESA_STATUS_REG(chan), MV_REG_READ(MV_CESA_STATUS_REG(chan)));
+
+		mvOsPrintf("MV_CESA_ISR_CAUSE_REG               : 0x%X = 0x%08x\n",
+			MV_CESA_ISR_CAUSE_REG(chan), MV_REG_READ(MV_CESA_ISR_CAUSE_REG(chan)));
+
+		mvOsPrintf("MV_CESA_ISR_MASK_REG                : 0x%X = 0x%08x\n",
+			MV_CESA_ISR_MASK_REG(chan), MV_REG_READ(MV_CESA_ISR_MASK_REG(chan)));
+#if (MV_CESA_VERSION >= 2)
+		mvOsPrintf("MV_CESA_TDMA_CTRL_REG               : 0x%X = 0x%08x\n",
+			MV_CESA_TDMA_CTRL_REG(chan), MV_REG_READ(MV_CESA_TDMA_CTRL_REG(chan)));
+
+		mvOsPrintf("MV_CESA_TDMA_BYTE_COUNT_REG         : 0x%X = 0x%08x\n",
+			MV_CESA_TDMA_BYTE_COUNT_REG(chan), MV_REG_READ(MV_CESA_TDMA_BYTE_COUNT_REG(chan)));
+
+		mvOsPrintf("MV_CESA_TDMA_SRC_ADDR_REG           : 0x%X = 0x%08x\n",
+			MV_CESA_TDMA_SRC_ADDR_REG(chan), MV_REG_READ(MV_CESA_TDMA_SRC_ADDR_REG(chan)));
+
+		mvOsPrintf("MV_CESA_TDMA_DST_ADDR_REG           : 0x%X = 0x%08x\n",
+			MV_CESA_TDMA_DST_ADDR_REG(chan), MV_REG_READ(MV_CESA_TDMA_DST_ADDR_REG(chan)));
+
+		mvOsPrintf("MV_CESA_TDMA_NEXT_DESC_PTR_REG      : 0x%X = 0x%08x\n",
+			MV_CESA_TDMA_NEXT_DESC_PTR_REG(chan), MV_REG_READ(MV_CESA_TDMA_NEXT_DESC_PTR_REG(chan)));
+
+		mvOsPrintf("MV_CESA_TDMA_CURR_DESC_PTR_REG      : 0x%X = 0x%08x\n",
+			MV_CESA_TDMA_CURR_DESC_PTR_REG(chan), MV_REG_READ(MV_CESA_TDMA_CURR_DESC_PTR_REG(chan)));
+
+		mvOsPrintf("MV_CESA_TDMA_ERROR_CAUSE_REG        : 0x%X = 0x%08x\n",
+			MV_CESA_TDMA_ERROR_CAUSE_REG(chan), MV_REG_READ(MV_CESA_TDMA_ERROR_CAUSE_REG(chan)));
+
+		mvOsPrintf("MV_CESA_TDMA_ERROR_MASK_REG         : 0x%X = 0x%08x\n",
+			MV_CESA_TDMA_ERROR_MASK_REG(chan), MV_REG_READ(MV_CESA_TDMA_ERROR_CAUSE_REG(chan)));
+
+#endif
+	}
+}
+
+void mvCesaDebugStatus(void)
+{
+	MV_U8 chan = 0;
+	mvOsPrintf("\n\t CESA Status\n\n");
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+
+		mvOsPrintf("Channel %d: pReqQ=%p, qDepth=%d, reqSize=%d bytes, qRes=%d",
+			chan, pCesaReqFirst[chan], cesaQueueDepth[chan], (int)sizeof(MV_CESA_REQ), cesaReqResources[chan]);
+
+#ifdef MV_CESA_CHAIN_MODE
+		mvOsPrintf(", chainLength=%u", cesaChainLength[chan]);
+#endif
+
+		mvOsPrintf("\n");
+	}
+	mvOsPrintf("pSAD=%p, maxSA=%d, sizeSA=%d bytes\n", pCesaSAD, cesaMaxSA, (int)sizeof(MV_CESA_SA));
+
+	mvOsPrintf("\n");
+
+	mvCesaDebugRegs();
+	mvCesaDebugStats();
+	mvCesaDebugStatsClear();
+}
+
+void mvCesaDebugDescriptor(MV_CESA_DESC *pDesc)
+{
+	mvOsPrintf("config=0x%08x, crSrcOffs=0x%04x, crDstOffs=0x%04x\n",
+		pDesc->config, pDesc->cryptoSrcOffset, pDesc->cryptoDstOffset);
+
+	mvOsPrintf("crLen=0x%04x, crKeyOffs=0x%04x, ivOffs=0x%04x, ivBufOffs=0x%04x\n",
+		pDesc->cryptoDataLen, pDesc->cryptoKeyOffset, pDesc->cryptoIvOffset, pDesc->cryptoIvBufOffset);
+
+	mvOsPrintf("macSrc=0x%04x, digest=0x%04x, macLen=0x%04x, inIv=0x%04x, outIv=0x%04x\n",
+			pDesc->macSrcOffset, pDesc->macDigestOffset, pDesc->macDataLen,
+			pDesc->macInnerIvOffset, pDesc->macOuterIvOffset);
+}
+
+void mvCesaDebugQueue(int mode)
+{
+	MV_U8 chan = 0;
+
+	mvOsPrintf("\n\t CESA Request Queue:\n\n");
+
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+		mvOsPrintf("\n\nChannel %d:\n", chan);
+		mvOsPrintf("===========\n");
+
+		mvOsPrintf("pFirstReq=%p, pLastReq=%p, qDepth=%d, reqSize=%d bytes\n",
+			pCesaReqFirst[chan], pCesaReqLast[chan], cesaQueueDepth[chan], (int)sizeof(MV_CESA_REQ));
+
+		mvOsPrintf("pEmpty=%p, pProcess=%p, qResources=%d\n", pCesaReqEmpty[chan],
+					pCesaReqProcess[chan], cesaReqResources[chan]);
+
+		if (mode != 0) {
+			int count = 0;
+			MV_CESA_REQ *pReq = pCesaReqFirst[chan];
+
+			for (count = 0; count < cesaQueueDepth[chan]; count++) {
+				/* Print out requsts */
+				mvOsPrintf("%02d. pReq=%p, state=%s, frag=0x%x, pCmd=%p, pDma=%p, pDesc=%p\n",
+					count, pReq, mvCesaDebugStateStr(pReq->state),
+					pReq->fragMode, pReq->pCmd, pReq->dma[0].pDmaFirst, &pReq->pCesaDesc[0]);
+				if (pReq->fragMode != MV_CESA_FRAG_NONE) {
+					int frag;
+
+					mvOsPrintf("pFrags=%p, num=%d, next=%d, bufOffset=%d, cryptoSize=%d, macSize=%d\n",
+						&pReq->frags, pReq->frags.numFrag, pReq->frags.nextFrag,
+						pReq->frags.bufOffset, pReq->frags.cryptoSize, pReq->frags.macSize);
+					for (frag = 0; frag < pReq->frags.numFrag; frag++) {
+						mvOsPrintf("#%d: pDmaFirst=%p, pDesc=%p\n", frag,
+							pReq->dma[frag].pDmaFirst, &pReq->pCesaDesc[frag]);
+					}
+				}
+				if (mode > 1) {
+					/* Print out Command */
+					mvCesaDebugCmd(pReq->pCmd, mode);
+
+					/* Print out Descriptor */
+					mvCesaDebugDescriptor(&pReq->pCesaDesc[0]);
+				}
+				pReq++;
+			}
+		}
+	}
+}
+
+void mvCesaDebugSramSA(MV_CESA_SRAM_SA *pSramSA, int mode)
+{
+	if (pSramSA == NULL) {
+		mvOsPrintf("cesaSramSA: Unexpected pSramSA=%p\n", pSramSA);
+		return;
+	}
+	mvOsPrintf("pSramSA=%p, sizeSramSA=%d bytes\n", pSramSA, (int)sizeof(MV_CESA_SRAM_SA));
+
+	if (mode != 0) {
+		mvOsPrintf("cryptoKey=%p, maxCryptoKey=%d bytes\n", pSramSA->cryptoKey, MV_CESA_MAX_CRYPTO_KEY_LENGTH);
+		mvDebugMemDump(pSramSA->cryptoKey, MV_CESA_MAX_CRYPTO_KEY_LENGTH, 1);
+
+		mvOsPrintf("macInnerIV=%p, maxInnerIV=%d bytes\n", pSramSA->macInnerIV, MV_CESA_MAX_DIGEST_SIZE);
+		mvDebugMemDump(pSramSA->macInnerIV, MV_CESA_MAX_DIGEST_SIZE, 1);
+
+		mvOsPrintf("macOuterIV=%p, maxOuterIV=%d bytes\n", pSramSA->macOuterIV, MV_CESA_MAX_DIGEST_SIZE);
+		mvDebugMemDump(pSramSA->macOuterIV, MV_CESA_MAX_DIGEST_SIZE, 1);
+	}
+}
+
+void mvCesaDebugSA(short sid, int mode)
+{
+	MV_CESA_OPERATION oper;
+	MV_CESA_DIRECTION dir;
+	MV_CESA_CRYPTO_ALG cryptoAlg;
+	MV_CESA_CRYPTO_MODE cryptoMode;
+	MV_CESA_MAC_MODE macMode;
+	MV_CESA_SA *pSA = pCesaSAD[sid];
+
+	if (pSA != NULL) {
+		/*if(((pSA->count != 0) && (mode > 0)) || (mode >= 2))
+		   { */
+		mvOsPrintf("\n\nCESA SA Entry #%d (%p) - %s (count=%d)\n",
+			   sid, pSA, (pSA != NULL) ? "Valid" : "Invalid", pSA->count);
+
+		oper = (pSA->config & MV_CESA_OPERATION_MASK) >> MV_CESA_OPERATION_OFFSET;
+		dir = (pSA->config & MV_CESA_DIRECTION_MASK) >> MV_CESA_DIRECTION_BIT;
+		mvOsPrintf("%s - %s ", mvCesaDebugOperStr(oper), (dir == MV_CESA_DIR_ENCODE) ? "Encode" : "Decode");
+		if (oper != MV_CESA_MAC_ONLY) {
+			cryptoAlg = (pSA->config & MV_CESA_CRYPTO_ALG_MASK) >> MV_CESA_CRYPTO_ALG_OFFSET;
+			cryptoMode = (pSA->config & MV_CESA_CRYPTO_MODE_MASK) >> MV_CESA_CRYPTO_MODE_BIT;
+			mvOsPrintf("- %s - %s ", mvCesaDebugCryptoAlgStr(cryptoAlg),
+				   (cryptoMode == MV_CESA_CRYPTO_ECB) ? "ECB" : "CBC");
+		}
+		if (oper != MV_CESA_CRYPTO_ONLY) {
+			macMode = (pSA->config & MV_CESA_MAC_MODE_MASK) >> MV_CESA_MAC_MODE_OFFSET;
+			mvOsPrintf("- %s ", mvCesaDebugMacModeStr(macMode));
+		}
+		mvOsPrintf("\n");
+
+		if (mode > 0) {
+			mvOsPrintf("config=0x%08x, cryptoKeySize=%d, digestSize=%d\n",
+				   pCesaSAD[sid]->config, pCesaSAD[sid]->cryptoKeyLength, pCesaSAD[sid]->digestSize);
+
+			mvCesaDebugSramSA(pCesaSAD[sid]->pSramSA, mode);
+		}
+		/*} */
+	}
+}
+
+ /**/ void mvCesaDebugSram(int mode)
+{
+	MV_U8 chan = 0;
+
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+		mvOsPrintf("\n\nChannel %d:\n", chan);
+		mvOsPrintf("===========\n");
+
+		mvOsPrintf("\n\t SRAM contents: size=%d, pVirt=%p\n\n", (int)sizeof(MV_CESA_SRAM_MAP),
+						cesaSramVirtPtr[chan]);
+
+		mvOsPrintf("\n\t Sram buffer: size=%d, pVirt=%p\n", MV_CESA_MAX_BUF_SIZE, cesaSramVirtPtr[chan]->buf);
+		if (mode != 0)
+			mvDebugMemDump(cesaSramVirtPtr[chan]->buf, 64, 1);
+
+		mvOsPrintf("\n");
+		mvOsPrintf("\n\t Sram descriptor: size=%d, pVirt=%p\n", (int)sizeof(MV_CESA_DESC),
+						&cesaSramVirtPtr[chan]->desc);
+		if (mode != 0) {
+			mvOsPrintf("\n");
+			mvCesaDebugDescriptor(&cesaSramVirtPtr[chan]->desc);
+		}
+		mvOsPrintf("\n\t Sram IV: size=%d, pVirt=%p\n", MV_CESA_MAX_IV_LENGTH, &cesaSramVirtPtr[chan]->cryptoIV);
+		if (mode != 0) {
+			mvOsPrintf("\n");
+			mvDebugMemDump(cesaSramVirtPtr[chan]->cryptoIV, MV_CESA_MAX_IV_LENGTH, 1);
+		}
+		mvOsPrintf("\n");
+		mvCesaDebugSramSA(&cesaSramVirtPtr[chan]->sramSA, 0);
+	}
+}
+
+void mvCesaDebugSAD(int mode)
+{
+	int sid;
+
+	mvOsPrintf("\n\t Cesa SAD status: pSAD=%p, maxSA=%d\n", pCesaSAD, cesaMaxSA);
+
+	for (sid = 0; sid < cesaMaxSA; sid++)
+		mvCesaDebugSA(sid, mode);
+}
+
+void mvCesaDebugStats(void)
+{
+	mvOsPrintf("\n\t Cesa Statistics\n");
+
+	mvOsPrintf("Opened=%u, Closed=%u\n", cesaStats.openedCount, cesaStats.closedCount);
+	mvOsPrintf("Req=%u, maxReq=%u, frags=%u, start=%u\n",
+		   cesaStats.reqCount, cesaStats.maxReqCount, cesaStats.fragCount, cesaStats.startCount);
+
+#ifdef MV_CESA_CHAIN_MODE
+	mvOsPrintf("maxChainUsage=%u\n", cesaStats.maxChainUsage);
+#endif
+
+	mvOsPrintf("\n");
+	mvOsPrintf("proc=%u, ready=%u, notReady=%u\n",
+		   cesaStats.procCount, cesaStats.readyCount, cesaStats.notReadyCount);
+}
+
+void mvCesaDebugStatsClear(void)
+{
+	memset(&cesaStats, 0, sizeof(cesaStats));
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaIf.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaIf.c
new file mode 100755
index 0000000..af8878c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaIf.c
@@ -0,0 +1,307 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvCesaIf.h"
+
+#define MV_CESA_IF_MAX_WEIGHT	0xFFFFFFFF
+
+/* Globals */
+MV_CESA_FLOW_TYPE chanFlowType[MV_CESA_CHANNELS];
+MV_U32 chanWeight[MV_CESA_CHANNELS];
+MV_STATUS readyStatus[MV_CESA_CHANNELS];
+MV_CESA_RESULT **pResQueue;
+MV_CESA_RESULT *resQueue;
+MV_CESA_RESULT *pResEmpty;
+MV_CESA_RESULT *pCurrResult;
+MV_CESA_POLICY currCesaPolicy;
+MV_U8 splitChanId;
+MV_U32 resQueueDepth;
+MV_U32 gReqId;
+MV_U32 currResId;
+
+MV_STATUS mvCesaIfHalInit(int numOfSession, int queueDepth, void *osHandle, MV_CESA_HAL_DATA *halData)
+{
+	/* Initialize globals */
+	currCesaPolicy = CESA_NULL_POLICY;
+	splitChanId = 0;
+	gReqId = 0;
+	currResId = 0;
+	pCurrResult = NULL;
+	resQueueDepth = queueDepth;
+
+	/* Allocate reordered results queue */
+	resQueue = (MV_CESA_RESULT *)mvOsMalloc(resQueueDepth * sizeof(MV_CESA_RESULT));
+	if (resQueue == NULL) {
+		mvOsPrintf("%s: Error, resQueue malloc failed\n", __func__);
+		return MV_ERROR;
+	}
+
+	/* Allocate pointers queue to reordered results queue */
+	pResQueue = (MV_CESA_RESULT **)mvOsMalloc(resQueueDepth * sizeof(MV_CESA_RESULT*));
+	if (pResQueue == NULL) {
+		mvOsPrintf("%s: Error, pResQueue malloc failed\n", __func__);
+		return MV_ERROR;
+	}
+
+	pResEmpty = &resQueue[0];
+	memset(chanWeight, 0, (MV_CESA_CHANNELS * sizeof(MV_U32)));
+	memset(chanFlowType, 0, (MV_CESA_CHANNELS * sizeof(MV_CESA_FLOW_TYPE)));
+	memset(pResQueue, 0, (resQueueDepth * sizeof(MV_CESA_RESULT *)));
+	memset(resQueue, 0, (resQueueDepth * sizeof(MV_CESA_RESULT)));
+	memset(readyStatus, MV_TRUE, (MV_CESA_CHANNELS * sizeof(MV_STATUS)));
+
+	return mvCesaHalInit(numOfSession, queueDepth, osHandle, halData);
+}
+
+MV_STATUS mvCesaIfTdmaWinInit(MV_U8 chan, MV_UNIT_WIN_INFO *addrWinMap)
+{
+	return mvCesaTdmaWinInit(chan, addrWinMap);
+}
+
+MV_STATUS mvCesaIfFinish(void)
+{
+	/* Free resources */
+	mvOsFree(pResQueue);
+	mvOsFree(resQueue);
+
+	return mvCesaFinish();
+}
+
+MV_STATUS mvCesaIfSessionOpen(MV_CESA_OPEN_SESSION *pSession, short *pSid)
+{
+	return mvCesaSessionOpen(pSession, pSid);
+}
+
+MV_STATUS mvCesaIfSessionClose(short sid)
+{
+	return mvCesaSessionClose(sid);
+}
+
+MV_STATUS mvCesaIfAction(MV_CESA_COMMAND *pCmd)
+{
+	MV_U8 chan = 0, chanId = 0;
+	MV_U32 min = MV_CESA_IF_MAX_WEIGHT; /* max possible value */
+	MV_U32 freeReqCount = 0;
+	MV_STATUS status;
+
+	/* Any room for the request ? */
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++)
+		freeReqCount += cesaReqResources[chan];
+
+	if (freeReqCount == 0)
+		return MV_NO_RESOURCE;
+
+	switch (currCesaPolicy) {
+	case CESA_WEIGHTED_CHAN_POLICY:
+	case CESA_NULL_POLICY:
+		for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+			if ((cesaReqResources[chan] > 0) && (chanWeight[chan] < min)) {
+				min = chanWeight[chan];
+				chanId = chan;
+			}
+		}
+		chanWeight[chanId] += pCmd->pSrc->mbufSize;
+		break;
+
+	case CESA_FLOW_ASSOC_CHAN_POLICY:
+		/* TBD - handle policy */
+		break;
+
+	case CESA_SINGLE_CHAN_POLICY:
+		break;
+
+	default:
+		mvOsPrintf("%s: Error, policy not supported\n", __func__);
+		return MV_ERROR;
+	}
+
+	/* Check if we need to handle SPLIT case */
+	if (pCmd->split != MV_CESA_SPLIT_NONE) {
+		if (pCmd->split == MV_CESA_SPLIT_FIRST)
+			splitChanId = chanId;
+		else	/* MV_CESA_SPLIT_SECOND */
+			chanId = splitChanId;
+	}
+
+	pCmd->reqId = gReqId;
+
+	status = mvCesaAction(chanId, pCmd);
+	if ((status == MV_OK) || (status == MV_NO_MORE))
+		gReqId = ((gReqId + 1) % resQueueDepth);
+
+	return status;
+}
+
+MV_STATUS mvCesaIfReadyGet(MV_U8 chan, MV_CESA_RESULT *pResult)
+{
+	MV_STATUS status;
+
+	while (MV_TRUE) {
+
+		if (readyStatus[chan] == MV_FALSE)
+			break;
+
+		/* Get next result */
+		status = mvCesaReadyGet(chan, pResEmpty);
+		if (status != MV_OK)
+			break;
+
+		switch (currCesaPolicy) {
+		case CESA_WEIGHTED_CHAN_POLICY:
+		case CESA_NULL_POLICY:
+			chanWeight[chan] -= pResEmpty->mbufSize;
+			break;
+
+		case CESA_FLOW_ASSOC_CHAN_POLICY:
+			/* TBD - handle policy */
+			break;
+
+		case CESA_SINGLE_CHAN_POLICY:
+			break;
+
+		default:
+			mvOsPrintf("%s: Error, policy not supported\n", __func__);
+			return MV_ERROR;
+		}
+
+		if (pResQueue[pResEmpty->reqId] != NULL)
+			mvOsPrintf("%s: Warning, result entry was overrided(reqId=%d)\n", __func__, pResEmpty->reqId);
+
+		pResQueue[pResEmpty->reqId] = pResEmpty;
+		pResEmpty = ((pResEmpty != &resQueue[resQueueDepth-1]) ? (pResEmpty + 1) : &resQueue[0]);
+#ifndef MV_CESA_CHAIN_MODE
+		break;
+#endif
+	}
+
+	pCurrResult = pResQueue[currResId];
+
+	if (pCurrResult == NULL) {
+		readyStatus[chan] = MV_TRUE;
+		return MV_NOT_READY;
+	} else {
+		/* Release results in order */
+		readyStatus[chan] = MV_FALSE;
+		/* Fill result data */
+		pResult->retCode = pCurrResult->retCode;
+		pResult->pReqPrv = pCurrResult->pReqPrv;
+		pResult->sessionId = pCurrResult->sessionId;
+		pResult->mbufSize = pCurrResult->mbufSize;
+		pResult->reqId = pCurrResult->reqId;
+		pResQueue[currResId] = NULL;
+		currResId = ((currResId + 1) % resQueueDepth);
+		return MV_OK;
+	}
+}
+
+MV_STATUS mvCesaIfPolicySet(MV_CESA_POLICY cesaPolicy, MV_CESA_FLOW_TYPE flowType)
+{
+	MV_U8 chan = 0;
+
+	if (currCesaPolicy == CESA_NULL_POLICY) {
+		currCesaPolicy = cesaPolicy;
+	} else {
+		/* Check if more than 1 policy was assigned */
+		if (currCesaPolicy != cesaPolicy) {
+			mvOsPrintf("%s: Error, can not support multiple policies\n", __func__);
+			return MV_ERROR;
+		}
+	}
+
+	if (cesaPolicy == CESA_FLOW_ASSOC_CHAN_POLICY) {
+
+		if (flowType == CESA_NULL_FLOW_TYPE) {
+			mvOsPrintf("%s: Error, bad policy configuration\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Find next empty entry */
+		for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+			if (chanFlowType[chan] == CESA_NULL_FLOW_TYPE)
+				chanFlowType[chan] = flowType;
+		}
+
+		if (chan == MV_CESA_CHANNELS) {
+			mvOsPrintf("%s: Error, no empty entry is available\n", __func__);
+			return MV_ERROR;
+		}
+
+	}
+
+	return MV_OK;
+}
+
+MV_STATUS mvCesaIfPolicyGet(MV_CESA_POLICY *pCesaPolicy)
+{
+	*pCesaPolicy = currCesaPolicy;
+
+	return MV_OK;
+}
+
+MV_VOID mvCesaIfDebugMbuf(const char *str, MV_CESA_MBUF *pMbuf, int offset, int size)
+{
+	return mvCesaDebugMbuf(str, pMbuf, offset, size);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaIf.h b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaIf.h
new file mode 100755
index 0000000..a2eda95
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaIf.h
@@ -0,0 +1,116 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvCesa.h - Header File for Cryptographic Engines and Security Accelerator
+*
+* DESCRIPTION:
+*       This header file contains macros typedefs and function declaration for
+*       the Marvell Cryptographic Engines and Security Accelerator.
+*
+*******************************************************************************/
+
+#ifndef __mvCesaIf_h__
+#define __mvCesaIf_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysCesaConfig.h"
+#include "mvCesa.h"
+#include "mvCesaRegs.h"
+
+typedef enum {
+	CESA_NULL_POLICY = 0,
+	CESA_SINGLE_CHAN_POLICY,
+	CESA_WEIGHTED_CHAN_POLICY,
+	CESA_FLOW_ASSOC_CHAN_POLICY
+} MV_CESA_POLICY;
+
+typedef enum {
+	CESA_NULL_FLOW_TYPE = 0,
+	CESA_IPSEC_FLOW_TYPE,
+	CESA_SSL_FLOW_TYPE,
+	CESA_DISK_FLOW_TYPE,
+	CESA_NFPSEC_FLOW_TYPE
+} MV_CESA_FLOW_TYPE;
+
+	MV_STATUS mvCesaIfHalInit(int numOfSession, int queueDepth, void *osHandle, MV_CESA_HAL_DATA *halData);
+	MV_STATUS mvCesaIfTdmaWinInit(MV_U8 chan, MV_UNIT_WIN_INFO *addrWinMap);
+	MV_STATUS mvCesaIfFinish(void);
+	MV_STATUS mvCesaIfSessionOpen(MV_CESA_OPEN_SESSION *pSession, short *pSid);
+	MV_STATUS mvCesaIfSessionClose(short sid);
+	MV_STATUS mvCesaIfAction(MV_CESA_COMMAND *pCmd);
+	MV_STATUS mvCesaIfReadyGet(MV_U8 chan, MV_CESA_RESULT *pResult);
+	MV_STATUS mvCesaIfPolicySet(MV_CESA_POLICY cesaPolicy, MV_CESA_FLOW_TYPE flowType);
+	MV_STATUS mvCesaIfPolicyGet(MV_CESA_POLICY *pCesaPolicy);
+	MV_VOID mvCesaIfDebugMbuf(const char *str, MV_CESA_MBUF *pMbuf, int offset, int size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __mvCesaIf_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaRegs.h b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaRegs.h
new file mode 100755
index 0000000..090dee9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaRegs.h
@@ -0,0 +1,361 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __mvCesaRegs_h__
+#define __mvCesaRegs_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvSysCesaConfig.h"
+
+	typedef struct {
+		/* word 0 */
+		MV_U32 config;
+		/* word 1 */
+		MV_U16 cryptoSrcOffset;
+		MV_U16 cryptoDstOffset;
+		/* word 2 */
+		MV_U16 cryptoDataLen;
+		MV_U16 reserved1;
+		/* word 3 */
+		MV_U16 cryptoKeyOffset;
+		MV_U16 reserved2;
+		/* word 4 */
+		MV_U16 cryptoIvOffset;
+		MV_U16 cryptoIvBufOffset;
+		/* word 5 */
+		MV_U16 macSrcOffset;
+		MV_U16 macTotalLen;
+		/* word 6 */
+		MV_U16 macDigestOffset;
+		MV_U16 macDataLen;
+		/* word 7 */
+		MV_U16 macInnerIvOffset;
+		MV_U16 macOuterIvOffset;
+	} MV_CESA_DESC;
+
+/* operation */
+	typedef enum {
+		MV_CESA_MAC_ONLY = 0,
+		MV_CESA_CRYPTO_ONLY = 1,
+		MV_CESA_MAC_THEN_CRYPTO = 2,
+		MV_CESA_CRYPTO_THEN_MAC = 3,
+		MV_CESA_MAX_OPERATION
+	} MV_CESA_OPERATION;
+
+#define MV_CESA_OPERATION_OFFSET        		0
+#define MV_CESA_OPERATION_MASK          		(0x3 << MV_CESA_OPERATION_OFFSET)
+
+/* mac algorithm */
+	typedef enum {
+		MV_CESA_MAC_NULL = 0,
+		MV_CESA_MAC_SHA2 = 1,
+		MV_CESA_MAC_HMAC_SHA2 = 3,
+		MV_CESA_MAC_MD5 = 4,
+		MV_CESA_MAC_SHA1 = 5,
+		MV_CESA_MAC_HMAC_MD5 = 6,
+		MV_CESA_MAC_HMAC_SHA1 = 7,
+	} MV_CESA_MAC_MODE;
+
+#define MV_CESA_MAC_MODE_OFFSET         		4
+#define MV_CESA_MAC_MODE_MASK           		(0x7 << MV_CESA_MAC_MODE_OFFSET)
+
+	typedef enum {
+		MV_CESA_MAC_DIGEST_FULL = 0,
+		MV_CESA_MAC_DIGEST_96B = 1,
+	} MV_CESA_MAC_DIGEST_SIZE;
+
+#define MV_CESA_MAC_DIGEST_SIZE_BIT     		7
+#define MV_CESA_MAC_DIGEST_SIZE_MASK    		(1 << MV_CESA_MAC_DIGEST_SIZE_BIT)
+
+	typedef enum {
+		MV_CESA_CRYPTO_NULL = 0,
+		MV_CESA_CRYPTO_DES = 1,
+		MV_CESA_CRYPTO_3DES = 2,
+		MV_CESA_CRYPTO_AES = 3,
+	} MV_CESA_CRYPTO_ALG;
+
+#define MV_CESA_CRYPTO_ALG_OFFSET       		8
+#define MV_CESA_CRYPTO_ALG_MASK         		(0x3 << MV_CESA_CRYPTO_ALG_OFFSET)
+
+/* direction */
+	typedef enum {
+		MV_CESA_DIR_ENCODE = 0,
+		MV_CESA_DIR_DECODE = 1,
+	} MV_CESA_DIRECTION;
+
+#define MV_CESA_DIRECTION_BIT           		12
+#define MV_CESA_DIRECTION_MASK          		(1 << MV_CESA_DIRECTION_BIT)
+
+/* crypto IV mode */
+	typedef enum {
+		MV_CESA_CRYPTO_ECB = 0,
+		MV_CESA_CRYPTO_CBC = 1,
+		/* NO HW Support */
+		MV_CESA_CRYPTO_CTR = 10,
+	} MV_CESA_CRYPTO_MODE;
+
+#define MV_CESA_CRYPTO_MODE_BIT         		16
+#define MV_CESA_CRYPTO_MODE_MASK        		(1 << MV_CESA_CRYPTO_MODE_BIT)
+
+/* 3DES mode */
+	typedef enum {
+		MV_CESA_CRYPTO_3DES_EEE = 0,
+		MV_CESA_CRYPTO_3DES_EDE = 1,
+	} MV_CESA_CRYPTO_3DES_MODE;
+
+#define MV_CESA_CRYPTO_3DES_MODE_BIT    		20
+#define MV_CESA_CRYPTO_3DES_MODE_MASK   		(1 << MV_CESA_CRYPTO_3DES_MODE_BIT)
+
+/* AES Key Length */
+	typedef enum {
+		MV_CESA_CRYPTO_AES_KEY_128 = 0,
+		MV_CESA_CRYPTO_AES_KEY_192 = 1,
+		MV_CESA_CRYPTO_AES_KEY_256 = 2,
+	} MV_CESA_CRYPTO_AES_KEY_LEN;
+
+#define MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET   		24
+#define MV_CESA_CRYPTO_AES_KEY_LEN_MASK     		(0x3 << MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET)
+
+/* Fragmentation mode */
+	typedef enum {
+		MV_CESA_FRAG_NONE = 0,
+		MV_CESA_FRAG_FIRST = 1,
+		MV_CESA_FRAG_LAST = 2,
+		MV_CESA_FRAG_MIDDLE = 3,
+	} MV_CESA_FRAG_MODE;
+
+#define MV_CESA_FRAG_MODE_OFFSET            		30
+#define MV_CESA_FRAG_MODE_MASK              		(0x3 << MV_CESA_FRAG_MODE_OFFSET)
+/*---------------------------------------------------------------------------*/
+
+/********** Security Accelerator Command Register **************/
+#define MV_CESA_CMD_REG(chan)               		(MV_CESA_REGS_BASE(chan) + 0xE00)
+
+#define MV_CESA_CMD_CHAN_ENABLE_BIT         		0
+#define MV_CESA_CMD_CHAN_ENABLE_MASK        		(1 << MV_CESA_CMD_CHAN_ENABLE_BIT)
+
+#define MV_CESA_CMD_CHAN_DISABLE_BIT        		2
+#define MV_CESA_CMD_CHAN_DISABLE_MASK       		(1 << MV_CESA_CMD_CHAN_DISABLE_BIT)
+
+/********** Security Accelerator Descriptor Pointers Register **********/
+#define MV_CESA_CHAN_DESC_OFFSET_REG(chan)  		(MV_CESA_REGS_BASE(chan) + 0xE04)
+
+/********** Security Accelerator Configuration Register **********/
+#define MV_CESA_CFG_REG(chan)                     	(MV_CESA_REGS_BASE(chan) + 0xE08)
+
+#define MV_CESA_CFG_STOP_DIGEST_ERR_BIT     		0
+#define MV_CESA_CFG_STOP_DIGEST_ERR_MASK    		(1 << MV_CESA_CFG_STOP_DIGEST_ERR_BIT)
+
+#define MV_CESA_CFG_WAIT_DMA_BIT            		7
+#define MV_CESA_CFG_WAIT_DMA_MASK           		(1 << MV_CESA_CFG_WAIT_DMA_BIT)
+
+#define MV_CESA_CFG_ACT_DMA_BIT             		9
+#define MV_CESA_CFG_ACT_DMA_MASK            		(1 << MV_CESA_CFG_ACT_DMA_BIT)
+
+#define MV_CESA_CFG_CHAIN_MODE_BIT          		11
+#define MV_CESA_CFG_CHAIN_MODE_MASK         		(1 << MV_CESA_CFG_CHAIN_MODE_BIT)
+
+#define MV_CESA_CFG_ENC_AUTH_PARALLEL_MODE_BIT		13
+#define MV_CESA_CFG_ENC_AUTH_PARALLEL_MODE_MASK		(1 << MV_CESA_CFG_ENC_AUTH_PARALLEL_MODE_BIT)
+
+/********** Security Accelerator Status Register ***********/
+#define MV_CESA_STATUS_REG(chan)            		(MV_CESA_REGS_BASE(chan) + 0xE0C)
+
+#define MV_CESA_STATUS_ACTIVE_BIT           		0
+#define MV_CESA_STATUS_ACTIVE_MASK          		(1 << MV_CESA_STATUS_ACTIVE_BIT)
+
+#define MV_CESA_STATUS_DIGEST_ERR_BIT       		8
+#define MV_CESA_STATUS_DIGEST_ERR_MASK      		(1 << MV_CESA_STATUS_DIGEST_ERR_BIT)
+
+/* Cryptographic Engines and Security Accelerator Interrupt Cause Register */
+#define MV_CESA_ISR_CAUSE_REG(chan)         		(MV_CESA_REGS_BASE(chan) + 0xE20)
+
+/* Cryptographic Engines and Security Accelerator Interrupt Mask Register */
+#define MV_CESA_ISR_MASK_REG(chan)          		(MV_CESA_REGS_BASE(chan) + 0xE24)
+
+#define MV_CESA_CAUSE_AUTH_MASK             		(1 << 0)
+#define MV_CESA_CAUSE_DES_MASK              		(1 << 1)
+#define MV_CESA_CAUSE_AES_ENCR_MASK         		(1 << 2)
+#define MV_CESA_CAUSE_AES_DECR_MASK         		(1 << 3)
+#define MV_CESA_CAUSE_DES_ALL_MASK          		(1 << 4)
+
+#define MV_CESA_CAUSE_ACC_BIT              	 	5
+#define MV_CESA_CAUSE_ACC_MASK              		(1 << MV_CESA_CAUSE_ACC_BIT)
+
+#define MV_CESA_CAUSE_ACC_DMA_BIT           		7
+#define MV_CESA_CAUSE_ACC_DMA_MASK          		(1 << MV_CESA_CAUSE_ACC_DMA_BIT)
+#define MV_CESA_CAUSE_ACC_DMA_ALL_MASK      		(3 << MV_CESA_CAUSE_ACC_DMA_BIT)
+
+#define MV_CESA_CAUSE_DMA_COMPL_BIT         		9
+#define MV_CESA_CAUSE_DMA_COMPL_MASK        		(1 << MV_CESA_CAUSE_DMA_COMPL_BIT)
+
+#define MV_CESA_CAUSE_DMA_OWN_ERR_BIT       		10
+#define MV_CESA_CAUSE_DMA_OWN_ERR_MASK      		(1 < MV_CESA_CAUSE_DMA_OWN_ERR_BIT)
+
+#define MV_CESA_CAUSE_DMA_CHAIN_PKT_BIT     		11
+#define MV_CESA_CAUSE_DMA_CHAIN_PKT_MASK    		(1 < MV_CESA_CAUSE_DMA_CHAIN_PKT_BIT)
+
+#define MV_CESA_AUTH_DATA_IN_REG(chan)      		(MV_CESA_REGS_BASE(chan) + 0xd38)
+#define MV_CESA_AUTH_BIT_COUNT_LOW_REG(chan)      	(MV_CESA_REGS_BASE(chan) + 0xd20)
+#define MV_CESA_AUTH_BIT_COUNT_HIGH_REG(chan)     	(MV_CESA_REGS_BASE(chan) + 0xd24)
+
+#define MV_CESA_AUTH_INIT_VAL_DIGEST_REG(chan, i)	(MV_CESA_REGS_BASE(chan) + 0xd00 + (i<<2))
+
+#define MV_CESA_AUTH_INIT_VAL_DIGEST_A_REG(chan)  	(MV_CESA_REGS_BASE(chan) + 0xd00)
+#define MV_CESA_AUTH_INIT_VAL_DIGEST_B_REG(chan)  	(MV_CESA_REGS_BASE(chan) + 0xd04)
+#define MV_CESA_AUTH_INIT_VAL_DIGEST_C_REG(chan)  	(MV_CESA_REGS_BASE(chan) + 0xd08)
+#define MV_CESA_AUTH_INIT_VAL_DIGEST_D_REG(chan)  	(MV_CESA_REGS_BASE(chan) + 0xd0c)
+#define MV_CESA_AUTH_INIT_VAL_DIGEST_E_REG(chan)  	(MV_CESA_REGS_BASE(chan) + 0xd10)
+#define MV_CESA_AUTH_COMMAND_REG(chan)            	(MV_CESA_REGS_BASE(chan) + 0xd18)
+
+#define MV_CESA_AUTH_ALGORITHM_BIT          		0
+#define MV_CESA_AUTH_ALGORITHM_MD5          		(0<<AUTH_ALGORITHM_BIT)
+#define MV_CESA_AUTH_ALGORITHM_SHA1         		(1<<AUTH_ALGORITHM_BIT)
+
+#define MV_CESA_AUTH_IV_MODE_BIT            		1
+#define MV_CESA_AUTH_IV_MODE_INIT           		(0<<AUTH_IV_MODE_BIT)
+#define MV_CESA_AUTH_IV_MODE_CONTINUE       		(1<<AUTH_IV_MODE_BIT)
+
+#define MV_CESA_AUTH_DATA_BYTE_SWAP_BIT     		2
+#define MV_CESA_AUTH_DATA_BYTE_SWAP_MASK    		(1<<AUTH_DATA_BYTE_SWAP_BIT)
+
+#define MV_CESA_AUTH_IV_BYTE_SWAP_BIT       		4
+#define MV_CESA_AUTH_IV_BYTE_SWAP_MASK      		(1<<AUTH_IV_BYTE_SWAP_BIT)
+
+#define MV_CESA_AUTH_TERMINATION_BIT        		31
+#define MV_CESA_AUTH_TERMINATION_MASK       		(1<<AUTH_TERMINATION_BIT)
+
+/*************** TDMA Control Register ************************************************/
+#define MV_CESA_TDMA_CTRL_REG(chan)               	(MV_CESA_TDMA_REGS_BASE(chan) + 0x840)
+
+#define MV_CESA_TDMA_BURST_32B              		3
+#define MV_CESA_TDMA_BURST_128B             		4
+
+#define MV_CESA_TDMA_DST_BURST_OFFSET       		0
+#define MV_CESA_TDMA_DST_BURST_ALL_MASK     		(0x7<<MV_CESA_TDMA_DST_BURST_OFFSET)
+#define MV_CESA_TDMA_DST_BURST_MASK(burst)  		((burst)<<MV_CESA_TDMA_DST_BURST_OFFSET)
+
+#define MV_CESA_TDMA_OUTSTAND_READ_EN_BIT   		4
+#define MV_CESA_TDMA_OUTSTAND_READ_EN_MASK  		(1<<MV_CESA_TDMA_OUTSTAND_READ_EN_BIT)
+
+#define MV_CESA_TDMA_SRC_BURST_OFFSET       		6
+#define MV_CESA_TDMA_SRC_BURST_ALL_MASK     		(0x7<<MV_CESA_TDMA_SRC_BURST_OFFSET)
+#define MV_CESA_TDMA_SRC_BURST_MASK(burst)  		((burst)<<MV_CESA_TDMA_SRC_BURST_OFFSET)
+
+#define MV_CESA_TDMA_CHAIN_MODE_BIT         		9
+#define MV_CESA_TDMA_NON_CHAIN_MODE_MASK    		(1<<MV_CESA_TDMA_CHAIN_MODE_BIT)
+
+#define MV_CESA_TDMA_BYTE_SWAP_BIT	    		11
+#define MV_CESA_TDMA_BYTE_SWAP_MASK	    		(0 << MV_CESA_TDMA_BYTE_SWAP_BIT)
+#define MV_CESA_TDMA_NO_BYTE_SWAP_MASK	    		(1 << MV_CESA_TDMA_BYTE_SWAP_BIT)
+
+#define MV_CESA_TDMA_ENABLE_BIT		    		12
+#define MV_CESA_TDMA_ENABLE_MASK            		(1<<MV_CESA_TDMA_ENABLE_BIT)
+
+#define MV_CESA_TDMA_FETCH_NEXT_DESC_BIT    		13
+#define MV_CESA_TDMA_FETCH_NEXT_DESC_MASK   		(1<<MV_CESA_TDMA_FETCH_NEXT_DESC_BIT)
+
+#define MV_CESA_TDMA_CHAN_ACTIVE_BIT	    		14
+#define MV_CESA_TDMA_CHAN_ACTIVE_MASK       		(1<<MV_CESA_TDMA_CHAN_ACTIVE_BIT)
+/*------------------------------------------------------------------------------------*/
+
+#define MV_CESA_TDMA_BYTE_COUNT_REG(chan)         	(MV_CESA_TDMA_REGS_BASE(chan) + 0x800)
+#define MV_CESA_TDMA_SRC_ADDR_REG(chan)           	(MV_CESA_TDMA_REGS_BASE(chan) + 0x810)
+#define MV_CESA_TDMA_DST_ADDR_REG(chan)           	(MV_CESA_TDMA_REGS_BASE(chan) + 0x820)
+#define MV_CESA_TDMA_NEXT_DESC_PTR_REG(chan)      	(MV_CESA_TDMA_REGS_BASE(chan) + 0x830)
+#define MV_CESA_TDMA_CURR_DESC_PTR_REG(chan)      	(MV_CESA_TDMA_REGS_BASE(chan) + 0x870)
+
+#define MV_CESA_TDMA_ERROR_CAUSE_REG(chan)        	(MV_CESA_TDMA_REGS_BASE(chan) + 0x8C8)
+#define MV_CESA_TDMA_ERROR_MASK_REG(chan)         	(MV_CESA_TDMA_REGS_BASE(chan) + 0x8CC)
+
+/*************** Address Decode Register ********************************************/
+
+#define MV_CESA_TDMA_ADDR_DEC_WIN           		4
+
+#define MV_CESA_TDMA_BASE_ADDR_REG(chan, win)     	(MV_CESA_TDMA_REGS_BASE(chan) + 0xa00 + (win<<3))
+
+#define MV_CESA_TDMA_WIN_CTRL_REG(chan, win)      	(MV_CESA_TDMA_REGS_BASE(chan) + 0xa04 + (win<<3))
+
+#define MV_CESA_TDMA_WIN_ENABLE_BIT         		0
+#define MV_CESA_TDMA_WIN_ENABLE_MASK        		(1 << MV_CESA_TDMA_WIN_ENABLE_BIT)
+
+#define MV_CESA_TDMA_WIN_TARGET_OFFSET      		4
+#define MV_CESA_TDMA_WIN_TARGET_MASK        		(0xf << MV_CESA_TDMA_WIN_TARGET_OFFSET)
+
+#define MV_CESA_TDMA_WIN_ATTR_OFFSET        		8
+#define MV_CESA_TDMA_WIN_ATTR_MASK          		(0xff << MV_CESA_TDMA_WIN_ATTR_OFFSET)
+
+#define MV_CESA_TDMA_WIN_SIZE_OFFSET        		16
+#define MV_CESA_TDMA_WIN_SIZE_MASK          		(0xFFFF << MV_CESA_TDMA_WIN_SIZE_OFFSET)
+
+#define MV_CESA_TDMA_WIN_BASE_OFFSET        		16
+#define MV_CESA_TDMA_WIN_BASE_MASK          		(0xFFFF << MV_CESA_TDMA_WIN_BASE_OFFSET)
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __mvCesaRegs_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaTest.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaTest.c
new file mode 100755
index 0000000..824d60b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCesaTest.c
@@ -0,0 +1,3026 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvOs.h"
+
+#if defined(MV_VXWORKS)
+
+#include "sysLib.h"
+#include "logLib.h"
+#include "tickLib.h"
+#include "intLib.h"
+#include "config.h"
+
+SEM_ID cesaSemId = NULL;
+SEM_ID cesaWaitSemId = NULL;
+
+#define CESA_TEST_LOCK(flags)       flags = intLock()
+#define CESA_TEST_UNLOCK(flags)     intUnlock(flags)
+
+#define CESA_TEST_WAIT_INIT()       cesaWaitSemId = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY)
+#define CESA_TEST_WAKE_UP()         semGive(cesaWaitSemId)
+#define CESA_TEST_WAIT(cond, ms)    semTake(cesaWaitSemId, (sysClkRateGet()*ms)/1000)
+
+#define CESA_TEST_TICK_GET()        tickGet()
+#define CESA_TEST_TICK_TO_MS(tick)  (((tick)*1000)/sysClkRateGet())
+
+#elif defined(MV_LINUX)
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+wait_queue_head_t cesaTest_waitq;
+spinlock_t cesaLock;
+static struct timeval tv;
+
+#define CESA_TEST_LOCK(flags)       spin_lock_irqsave(&cesaLock, flags)
+#define CESA_TEST_UNLOCK(flags)     spin_unlock_irqrestore(&cesaLock, flags);
+
+#define CESA_TEST_WAIT_INIT()       init_waitqueue_head(&cesaTest_waitq)
+#define CESA_TEST_WAKE_UP()         wake_up(&cesaTest_waitq)
+#define CESA_TEST_WAIT(cond, ms)    wait_event_timeout(cesaTest_waitq, (cond), msecs_to_jiffies(ms))
+
+#elif defined(MV_NETBSD)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+static int cesaLock;
+
+#define	CESA_TEST_LOCK(flags)		flags = splnet()
+#define	CESA_TEST_UNLOCK(flags)		splx(flags)
+
+#define	CESA_TEST_WAIT_INIT()	/* nothing */
+#define	CESA_TEST_WAKE_UP()		wakeup(&cesaLock)
+#define	CESA_TEST_WAIT(cond, ms)	\
+do {					\
+	while (!(cond))			\
+		tsleep(&cesaLock, PWAIT, "cesatest", mstohz(ms)); \
+} while (/*CONSTCOND*/0)
+
+#define	CESA_TEST_TICK_GET()		hardclock_ticks
+#define	CESA_TEST_TICK_TO_MS(tick)	((1000/hz)*(tick))
+
+#define	request_irq(i, h, t, n, a)	\
+	(!mv_intr_establish((i), IPL_NET, (int(*)(void *))(h), (a)))
+
+#else
+#error "Only Linux, VxWorks, or NetBSD OS are supported"
+#endif
+
+#include "mvDebug.h"
+
+#include "mvSysCesaConfig.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ctrlEnv/sys/mvCpuIf.h"
+#include "cntmr/mvCntmr.h"
+#include "cesa/mvCesaIf.h"
+#include "cesa/mvMD5.h"
+#include "cesa/mvSHA1.h"
+#include "cesa/mvSHA256.h"
+
+#if defined(CONFIG_MV646xx)
+#include "marvell_pic.h"
+#endif
+
+#define MV_CESA_USE_TIMER_ID    0
+#define CESA_DEF_BUF_SIZE       1500
+#define CESA_DEF_BUF_NUM        1
+#define CESA_DEF_SESSION_NUM    32
+
+#define CESA_DEF_ITER_NUM       100
+
+#define CESA_DEF_REQ_SIZE       256
+
+/* CESA Tests Debug */
+#undef CESA_TEST_DEBUG
+
+#ifdef CESA_TEST_DEBUG
+
+#   define CESA_TEST_DEBUG_PRINT(msg)   mvOsPrintf msg
+#   define CESA_TEST_DEBUG_CODE(code)   code
+
+typedef struct {
+	int type;		/* 0 - isrEmpty, 1 - cesaReadyGet, 2 - cesaAction */
+	MV_U32 timeStamp;
+	MV_U32 cause;
+	MV_U32 realCause;
+	MV_U32 dmaErrCause;
+	int resources;
+	MV_CESA_REQ *pReqReady;
+	MV_CESA_REQ *pReqEmpty;
+	MV_CESA_REQ *pReqProcess;
+} MV_CESA_TEST_TRACE;
+
+#define MV_CESA_TEST_TRACE_SIZE      25
+
+static int cesaTestTraceIdx;
+static MV_CESA_TEST_TRACE cesaTestTrace[MV_CESA_TEST_TRACE_SIZE];
+
+#if 0
+static void cesaTestTraceAdd(int type, MV_U32 cause)
+{
+	cesaTestTrace[cesaTestTraceIdx].type = type;
+	cesaTestTrace[cesaTestTraceIdx].cause = cause;
+	cesaTestTrace[cesaTestTraceIdx].realCause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
+	cesaTestTrace[cesaTestTraceIdx].dmaErrCause = MV_REG_READ(MV_CESA_TDMA_ERROR_CAUSE_REG);
+	cesaTestTrace[cesaTestTraceIdx].resources = cesaReqResources;
+	cesaTestTrace[cesaTestTraceIdx].pReqReady = pCesaReqReady;
+	cesaTestTrace[cesaTestTraceIdx].pReqEmpty = pCesaReqEmpty;
+	cesaTestTrace[cesaTestTraceIdx].pReqProcess = pCesaReqProcess;
+	cesaTestTrace[cesaTestTraceIdx].timeStamp = mvCntmrRead(MV_CESA_USE_TIMER_ID);
+	cesaTestTraceIdx++;
+	if (cesaTestTraceIdx == MV_CESA_TEST_TRACE_SIZE)
+		cesaTestTraceIdx = 0;
+}
+#endif
+#else
+
+#   define CESA_TEST_DEBUG_PRINT(msg)
+#   define CESA_TEST_DEBUG_CODE(code)
+
+#endif /* CESA_TEST_DEBUG */
+
+int cesaExpReqId = 0;
+int cesaCbIter = 0;
+
+int cesaIdx;
+int cesaIteration;
+int cesaRateSize;
+int cesaReqSize;
+unsigned long cesaTaskId;
+int cesaBufNum;
+int cesaBufSize;
+int cesaCheckOffset;
+int cesaCheckSize;
+int cesaCheckMode;
+int cesaTestIdx;
+int cesaCaseIdx;
+
+MV_U32 cesaTestIsrCount = 0;
+MV_U32 cesaTestIsrMissCount = 0;
+
+MV_U32 cesaCryptoError = 0;
+MV_U32 cesaReqIdError = 0;
+MV_U32 cesaError = 0;
+
+char *cesaHexBuffer = NULL;
+
+char *cesaBinBuffer = NULL;
+char *cesaExpBinBuffer = NULL;
+
+char *cesaInputHexStr = NULL;
+char *cesaOutputHexStr = NULL;
+
+MV_BUF_INFO cesaReqBufs[CESA_DEF_REQ_SIZE];
+
+MV_CESA_COMMAND *cesaCmdRing;
+MV_CESA_RESULT cesaResult;
+
+int cesaTestFull = 0;
+
+MV_BOOL cesaIsReady = MV_FALSE;
+MV_U32 cesaCycles = 0;
+MV_U32 cesaBeginTicks = 0;
+MV_U32 cesaEndTicks = 0;
+MV_U32 cesaRate = 0;
+MV_U32 cesaRateAfterDot = 0;
+
+void *cesaTestOSHandle = NULL;
+
+enum {
+	CESA_FAST_CHECK_MODE = 0,
+	CESA_FULL_CHECK_MODE,
+	CESA_NULL_CHECK_MODE,
+	CESA_SHOW_CHECK_MODE,
+	CESA_SW_SHOW_CHECK_MODE,
+	CESA_SW_NULL_CHECK_MODE,
+
+	CESA_MAX_CHECK_MODE
+};
+
+enum {
+	DES_TEST_TYPE = 0,
+	TRIPLE_DES_TEST_TYPE = 1,
+	AES_TEST_TYPE = 2,
+	MD5_TEST_TYPE = 3,
+	SHA1_TEST_TYPE = 4,
+	SHA2_TEST_TYPE = 5,
+	COMBINED_TEST_TYPE = 6,
+	MAX_TEST_TYPE
+};
+
+/* Tests data base */
+typedef struct {
+	short sid;
+	char cryptoAlgorithm;	/* DES/3DES/AES */
+	char cryptoMode;	/* ECB or CBC */
+	char macAlgorithm;	/* MD5 / SHA1 / SHA2 */
+	char operation;		/* CRYPTO/HMAC/CRYPTO+HMAC/HMAC+CRYPTO */
+	char direction;		/* ENCODE(SIGN)/DECODE(VERIFY) */
+	unsigned char *pCryptoKey;
+	int cryptoKeySize;
+	unsigned char *pMacKey;
+	int macKeySize;
+	const char *name;
+} MV_CESA_TEST_SESSION;
+
+typedef struct {
+	MV_CESA_TEST_SESSION *pSessions;
+	int numSessions;
+} MV_CESA_TEST_DB_ENTRY;
+
+typedef struct {
+	char *plainHexStr;
+	char *cipherHexStr;
+	unsigned char *pCryptoIV;
+	int cryptoLength;
+	int macLength;
+	int digestOffset;
+} MV_CESA_TEST_CASE;
+
+typedef struct {
+	int size;
+	const char *outputHexStr;
+} MV_CESA_SIZE_TEST;
+
+static unsigned char cryptoKey1[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
+};
+
+static unsigned char cryptoKey7[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+static unsigned char iv1[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef };
+
+static unsigned char cryptoKey2[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static unsigned char cryptoKey3[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
+};
+
+static unsigned char cryptoKey4[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+static unsigned char cryptoKey5[] = { 0x56, 0xe4, 0x7a, 0x38, 0xc5, 0x59, 0x89, 0x74,
+	0xbc, 0x46, 0x90, 0x3d, 0xba, 0x29, 0x03, 0x49
+};
+
+static unsigned char key3des1[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+	0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+	0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+/*  Input ASCII string: The quick brown fox jump  */
+static char plain3des1[] = "54686520717566636B2062726F776E20666F78206A756D70";
+static char cipher3des1[] = "A826FD8CE53B855FCCE21C8112256FE668D5C05DD9B6B900";
+
+static unsigned char key3des2[] = { 0x62, 0x7f, 0x46, 0x0e, 0x08, 0x10, 0x4a, 0x10,
+	0x43, 0xcd, 0x26, 0x5d, 0x58, 0x40, 0xea, 0xf1,
+	0x31, 0x3e, 0xdf, 0x97, 0xdf, 0x2a, 0x8a, 0x8c
+};
+
+static unsigned char iv3des2[] = { 0x8e, 0x29, 0xf7, 0x5e, 0xa7, 0x7e, 0x54, 0x75 };
+
+static char plain3des2[] = "326a494cd33fe756";
+
+static char cipher3desCbc2[] = "8e29f75ea77e5475" "b22b8d66de970692";
+
+static unsigned char key3des3[] = { 0x37, 0xae, 0x5e, 0xbf, 0x46, 0xdf, 0xf2, 0xdc,
+	0x07, 0x54, 0xb9, 0x4f, 0x31, 0xcb, 0xb3, 0x85,
+	0x5e, 0x7f, 0xd3, 0x6d, 0xc8, 0x70, 0xbf, 0xae
+};
+
+static unsigned char iv3des3[] = { 0x3d, 0x1d, 0xe3, 0xcc, 0x13, 0x2e, 0x3b, 0x65 };
+
+static char plain3des3[] = "84401f78fe6c10876d8ea23094ea5309";
+
+static char cipher3desCbc3[] = "3d1de3cc132e3b65" "7b1f7c7e3b1c948ebd04a75ffba7d2f5";
+
+static unsigned char iv5[] = { 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c,
+	0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9
+};
+
+static unsigned char aesCtrKey[] = { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+	0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC
+};
+
+static unsigned char mdKey1[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
+};
+
+static unsigned char mdKey2[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+};
+
+static unsigned char shaKey1[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	0x0b, 0x0b, 0x0b, 0x0b
+};
+
+static unsigned char shaKey2[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	0xaa, 0xaa, 0xaa, 0xaa
+};
+
+static unsigned char mdKey4[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+};
+
+static unsigned char shaKey4[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+	0x11, 0x12, 0x13, 0x14
+};
+
+static unsigned char sha2Key1[] = { 0x0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
+	0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+
+static MV_CESA_TEST_SESSION desTestSessions[] = {
+/*000*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey7, sizeof(cryptoKey7) / sizeof(cryptoKey7[0]),
+	 NULL, 0,
+	 "DES ECB encode",
+	 }
+	,
+/*001*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey7, sizeof(cryptoKey7) / sizeof(cryptoKey7[0]),
+	 NULL, 0,
+	 "DES ECB decode",
+	 }
+	,
+/*002*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey7, sizeof(cryptoKey7) / sizeof(cryptoKey7[0]),
+	 NULL, 0,
+	 "DES CBC encode"}
+	,
+/*003*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey7, sizeof(cryptoKey7) / sizeof(cryptoKey7[0]),
+	 NULL, 0,
+	 "DES CBC decode"}
+	,
+/*004*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0, NULL, 0,
+	 "NULL Crypto Algorithm encode"}
+	,
+};
+
+static MV_CESA_TEST_SESSION tripleDesTestSessions[] = {
+/*100*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 NULL, 0,
+	 "3DES ECB encode",
+	 }
+	,
+/*101*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 NULL, 0,
+	 "3DES ECB decode",
+	 }
+	,
+/*102*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 NULL, 0,
+	 "3DES CBC encode"}
+	,
+/*103*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 NULL, 0,
+	 "3DES CBC decode"}
+	,
+/*104*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 key3des1, sizeof(key3des1),
+	 NULL, 0,
+	 "3DES ECB encode"}
+	,
+/*105*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 key3des2, sizeof(key3des2),
+	 NULL, 0,
+	 "3DES ECB encode"}
+	,
+/*106*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 key3des3, sizeof(key3des3),
+	 NULL, 0,
+	 "3DES ECB encode"}
+	,
+};
+
+static MV_CESA_TEST_SESSION aesTestSessions[] = {
+/*200*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey2, sizeof(cryptoKey2) / sizeof(cryptoKey2[0]),
+	 NULL, 0,
+	 "AES-128 ECB encode"}
+	,
+/*201*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey2, sizeof(cryptoKey2) / sizeof(cryptoKey2[0]),
+	 NULL, 0,
+	 "AES-128 ECB decode"}
+	,
+/*202*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey5, sizeof(cryptoKey5) / sizeof(cryptoKey5[0]),
+	 NULL, 0,
+	 "AES-128 CBC encode"}
+	,
+/*203*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey5, sizeof(cryptoKey5) / sizeof(cryptoKey5[0]),
+	 NULL, 0,
+	 "AES-128 CBC decode"}
+	,
+/*204*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey3, sizeof(cryptoKey3) / sizeof(cryptoKey3[0]),
+	 NULL, 0,
+	 "AES-192 ECB encode"}
+	,
+/*205*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey3, sizeof(cryptoKey3) / sizeof(cryptoKey3[0]),
+	 NULL, 0,
+	 "AES-192 ECB decode"}
+	,
+/*206*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey4, sizeof(cryptoKey4) / sizeof(cryptoKey4[0]),
+	 NULL, 0,
+	 "AES-256 ECB encode"}
+	,
+/*207*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey4, sizeof(cryptoKey4) / sizeof(cryptoKey4[0]),
+	 NULL, 0,
+	 "AES-256 ECB decode"}
+	,
+/*208*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CTR,
+	 MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 aesCtrKey, sizeof(aesCtrKey) / sizeof(aesCtrKey[0]),
+	 NULL, 0,
+	 "AES-128 CTR encode"}
+	,
+};
+
+static MV_CESA_TEST_SESSION md5TestSessions[] = {
+/*300*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 mdKey1, sizeof(mdKey1),
+	 "HMAC-MD5 Generate Signature"}
+	,
+/*301*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 NULL, 0,
+	 mdKey1, sizeof(mdKey1),
+	 "HMAC-MD5 Verify Signature"}
+	,
+/*302*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 mdKey2, sizeof(mdKey2),
+	 "HMAC-MD5 Generate Signature"}
+	,
+/*303*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 NULL, 0,
+	 mdKey2, sizeof(mdKey2),
+	 "HMAC-MD5 Verify Signature"}
+	,
+/*304*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 mdKey4, sizeof(mdKey4),
+	 "HMAC-MD5 Generate Signature"}
+	,
+/*305*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_MD5, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 NULL, 0,
+	 "HASH-MD5 Generate Signature"}
+	,
+};
+
+static MV_CESA_TEST_SESSION sha1TestSessions[] = {
+/*400*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 shaKey1, sizeof(shaKey1),
+	 "HMAC-SHA1 Generate Signature"}
+	,
+/*401*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 NULL, 0,
+	 shaKey1, sizeof(shaKey1),
+	 "HMAC-SHA1 Verify Signature"}
+	,
+/*402*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 shaKey2, sizeof(shaKey2),
+	 "HMAC-SHA1 Generate Signature"}
+	,
+/*403*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 NULL, 0,
+	 shaKey2, sizeof(shaKey2),
+	 "HMAC-SHA1 Verify Signature"}
+	,
+/*404*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 shaKey4, sizeof(shaKey4),
+	 "HMAC-SHA1 Generate Signature"}
+	,
+/*405*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_SHA1, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 NULL, 0,
+	 "HASH-SHA1 Generate Signature"}
+	,
+};
+
+static MV_CESA_TEST_SESSION sha2TestSessions[] = {
+/*500*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA2, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 sha2Key1, sizeof(sha2Key1),
+	 "HMAC-SHA2 Generate Signature"}
+	,
+/*501*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA2, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 NULL, 0,
+	 sha2Key1, sizeof(sha2Key1),
+	 "HMAC-SHA2 Verify Signature"}
+	,
+/*502*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_SHA2, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_ENCODE,
+	 NULL, 0,
+	 NULL, 0,
+	 "HASH-SHA2 Generate Signature"}
+	,
+/*503*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_SHA2, MV_CESA_MAC_ONLY,
+	 MV_CESA_DIR_DECODE,
+	 NULL, 0,
+	 NULL, 0,
+	 "HASH-SHA2 Verify Signature"}
+	,
+};
+
+static MV_CESA_TEST_SESSION combinedTestSessions[] = {
+/*600*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey1, MV_CESA_DES_KEY_LENGTH,
+	 mdKey4, sizeof(mdKey4),
+	 "DES + MD5 encode"}
+	,
+/*601*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey1, MV_CESA_DES_KEY_LENGTH,
+	 shaKey4, sizeof(shaKey4),
+	 "DES + SHA1 encode"}
+	,
+/*602*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 mdKey4, sizeof(mdKey4),
+	 "3DES + MD5 encode"}
+	,
+/*603*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 shaKey4, sizeof(shaKey4),
+	 "3DES + SHA1 encode"}
+	,
+/*604*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 mdKey4, sizeof(mdKey4),
+	 "3DES CBC + MD5 encode"}
+	,
+/*605*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 shaKey4, sizeof(shaKey4),
+	 "3DES CBC + SHA1 encode"}
+	,
+/*606*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey5, sizeof(cryptoKey5) / sizeof(cryptoKey5[0]),
+	 mdKey4, sizeof(mdKey4),
+	 "AES-128 CBC + MD5 encode"}
+	,
+/*607*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CBC,
+	 MV_CESA_MAC_HMAC_SHA1, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey5, sizeof(cryptoKey5) / sizeof(cryptoKey5[0]),
+	 shaKey4, sizeof(shaKey4),
+	 "AES-128 CBC + SHA1 encode"}
+	,
+/*608*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_THEN_CRYPTO,
+	 MV_CESA_DIR_DECODE,
+	 cryptoKey1, sizeof(cryptoKey1) / sizeof(cryptoKey1[0]),
+	 mdKey4, sizeof(mdKey4),
+	 "HMAC-MD5 + 3DES decode"}
+	,
+/*609*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB,
+	 MV_CESA_MAC_HMAC_SHA2, MV_CESA_CRYPTO_THEN_MAC,
+	 MV_CESA_DIR_ENCODE,
+	 cryptoKey2, sizeof(cryptoKey2) / sizeof(cryptoKey2[0]),
+	 sha2Key1, sizeof(sha2Key1),
+	 "AES-128 CBC + SHA2 encode"}
+	,
+};
+
+static MV_CESA_TEST_DB_ENTRY cesaTestsDB[MAX_TEST_TYPE + 1] = {
+	{desTestSessions, sizeof(desTestSessions) / sizeof(desTestSessions[0])}
+	,
+	{tripleDesTestSessions, sizeof(tripleDesTestSessions) / sizeof(tripleDesTestSessions[0])}
+	,
+	{aesTestSessions, sizeof(aesTestSessions) / sizeof(aesTestSessions[0])}
+	,
+	{md5TestSessions, sizeof(md5TestSessions) / sizeof(md5TestSessions[0])}
+	,
+	{sha1TestSessions, sizeof(sha1TestSessions) / sizeof(sha1TestSessions[0])}
+	,
+	{sha2TestSessions, sizeof(sha2TestSessions) / sizeof(sha2TestSessions[0])}
+	,
+	{combinedTestSessions, sizeof(combinedTestSessions) / sizeof(combinedTestSessions[0])}
+	,
+	{NULL, 0}
+};
+
+char cesaNullPlainHexText[] = "000000000000000000000000000000000000000000000000";
+
+char cesaPlainAsciiText[] = "Now is the time for all ";
+char cesaPlainHexEbc[] = "4e6f77206973207468652074696d6520666f7220616c6c20";
+char cesaCipherHexEcb[] = "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53";
+char cesaPlainHexCbc[] = "1234567890abcdef4e6f77206973207468652074696d6520666f7220616c6c20";
+char cesaCipherHexCbc[] = "1234567890abcdefe5c7cdde872bf27c43e934008c389c0f683788499a7c05f6";
+
+char cesaAesPlainHexEcb[] = "000102030405060708090a0b0c0d0e0f";
+char cesaAes128cipherHexEcb[] = "0a940bb5416ef045f1c39458c653ea5a";
+char cesaAes192cipherHexEcb[] = "0060bffe46834bb8da5cf9a61ff220ae";
+char cesaAes256cipherHexEcb[] = "5a6e045708fb7196f02e553d02c3a692";
+
+char cesaAsciiStr1[] = "Hi There";
+char cesaDataHexStr1[] = "4869205468657265";
+char cesaHmacMd5digestHex1[] = "9294727a3638bb1c13f48ef8158bfc9d";
+char cesaHmacSha1digestHex1[] = "b617318655057264e28bc0b6fb378c8ef146be00";
+char cesaHmacSha2digestHex1[] = "a28cf43130ee696a98f14a37678b56bcfcbdd9e5cf69717fecf5480f0ebdf790";
+char cesaDataAndMd5digest1[] = "48692054686572659294727a3638bb1c13f48ef8158bfc9d";
+char cesaDataAndSha1digest1[] = "4869205468657265b617318655057264e28bc0b6fb378c8ef146be00";
+char cesaDataAndSha2digest1[] = "53616D706C65206D65737361676520666F72206B65796C656E3C626C6F636B6C656E"
+				"000000000000" "a28cf43130ee696a98f14a37678b56bcfcbdd9e5cf69717fecf5480f0ebdf790";
+
+char cesaAesPlainText[] = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+    "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
+
+char cesaAes128CipherCbc[] = "c30e32ffedc0774e6aff6af0869f71aa"
+    "0f3af07a9a31a9c684db207eb0ef8e4e" "35907aa632c3ffdf868bb7b29d3d46ad" "83ce9f9a102ee99d49a53e87f4c3da55";
+
+char cesaAesIvPlainText[] = "8ce82eefbea0da3c44699ed7db51b7d9"
+    "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+    "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
+
+char cesaAes128IvCipherCbc[] = "8ce82eefbea0da3c44699ed7db51b7d9"
+    "c30e32ffedc0774e6aff6af0869f71aa"
+    "0f3af07a9a31a9c684db207eb0ef8e4e" "35907aa632c3ffdf868bb7b29d3d46ad" "83ce9f9a102ee99d49a53e87f4c3da55";
+
+char cesaAesCtrPlain[] = "00E0017B27777F3F4A1786F000000001"
+    "000102030405060708090A0B0C0D0E0F" "101112131415161718191A1B1C1D1E1F" "20212223";
+
+char cesaAesCtrCipher[] = "00E0017B27777F3F4A1786F000000001"
+    "C1CF48A89F2FFDD9CF4652E9EFDB72D7" "4540A42BDE6D7836D59A5CEAAEF31053" "25B2072F";
+
+/* Input cesaHmacHex3 is '0xdd' repeated 50 times */
+char cesaHmacMd5digestHex3[] = "56be34521d144c88dbb8c733f0e8b3f6";
+char cesaHmacSha1digestHex3[] = "125d7342b9ac11cd91a39af48aa17b4f63f175d3";
+char cesaDataHexStr3[50 * 2 + 1] = "";
+char cesaDataAndMd5digest3[sizeof(cesaDataHexStr3) + sizeof(cesaHmacMd5digestHex3) + 8 * 2 + 1] = "";
+char cesaDataAndSha1digest3[sizeof(cesaDataHexStr3) + sizeof(cesaHmacSha1digestHex3) + 8 * 2 + 1] = "";
+char cesaDataAndSha2digest3[] = "6162630000000000"
+				"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
+
+/* Ascii string is "abc" */
+char hashHexStr3[] = "616263";
+char hashMd5digest3[] = "900150983cd24fb0d6963f7d28e17f72";
+char hashSha1digest3[] = "a9993e364706816aba3e25717850c26c9cd0d89d";
+char hashSha2digest3[] = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
+
+char hashHexStr80[] = "31323334353637383930"
+    "31323334353637383930"
+    "31323334353637383930"
+    "31323334353637383930" "31323334353637383930" "31323334353637383930" "31323334353637383930" "31323334353637383930";
+
+char hashMd5digest80[] = "57edf4a22be3c955ac49da2e2107b67a";
+
+char tripleDesThenMd5digest80[] = "b7726a03aad490bd6c5a452a89a1b271";
+char tripleDesThenSha1digest80[] = "b2ddeaca91030eab5b95a234ef2c0f6e738ff883";
+
+char cbc3desThenMd5digest80[] = "6f463057e1a90e0e91ae505b527bcec0";
+char cbc3desThenSha1digest80[] = "1b002ed050be743aa98860cf35659646bb8efcc0";
+
+char cbcAes128ThenMd5digest80[] = "6b6e863ac5a71d15e3e9b1c86c9ba05f";
+char cbcAes128ThenSha1digest80[] = "13558472d1fc1c90dffec6e5136c7203452d509b";
+
+char cesaDataHexStr4[] = "53616D706C65206D65737361676520666F72206B65796C656E3C626C6F636B6C656E";
+char aes128EcbThenHmacSha2[] = "631cb14ab7f43a46c7517a32f793d64c8a7814ebfb32294b9d20f2f79eb6baba";
+
+static MV_CESA_TEST_CASE cesaTestCases[] = {
+/*     plainHexStr          cipherHexStr               IV    crypto  mac     digest */
+/*                                                           Length  Length  Offset */
+/*0 */ {NULL, NULL, NULL, 0, 0, -1},
+/*1 */ {cesaPlainHexEbc, cesaCipherHexEcb, NULL, 24, 0, -1},
+/*2 */ {cesaPlainHexCbc, cesaCipherHexCbc, NULL, 24, 0, -1},
+/*3 */ {cesaAesPlainHexEcb, cesaAes128cipherHexEcb, NULL, 16, 0, -1},
+/*4 */ {cesaAesPlainHexEcb, cesaAes192cipherHexEcb, NULL, 16, 0, -1},
+/*5 */ {cesaAesPlainHexEcb, cesaAes256cipherHexEcb, NULL, 16, 0, -1},
+/*6 */ {cesaDataHexStr1, cesaHmacMd5digestHex1, NULL, 0, 8, -1},
+/*7 */ {NULL, cesaDataAndMd5digest1, NULL, 0, 8, -1},
+/*8 */ {cesaDataHexStr3, cesaHmacMd5digestHex3, NULL, 0, 50, -1},
+/*9 */ {NULL, cesaDataAndMd5digest3, NULL, 0, 50, -1},
+/*10*/ {cesaAesPlainText, cesaAes128IvCipherCbc, iv5, 64, 0, -1},
+/*11*/ {cesaDataHexStr1, cesaHmacSha1digestHex1, NULL, 0, 8, -1},
+/*12*/ {NULL, cesaDataAndSha1digest1, NULL, 0, 8, -1},
+/*13*/ {cesaDataHexStr3, cesaHmacSha1digestHex3, NULL, 0, 50, -1},
+/*14*/ {NULL, cesaDataAndSha1digest3, NULL, 0, 50, -1},
+/*15*/ {hashHexStr3, hashMd5digest3, NULL, 0, 3, -1},
+/*16*/ {hashHexStr3, hashSha1digest3, NULL, 0, 3, -1},
+/*17*/ {hashHexStr80, tripleDesThenMd5digest80, NULL, 80, 80, -1},
+/*18*/ {hashHexStr80, tripleDesThenSha1digest80, NULL, 80, 80, -1},
+/*19*/ {hashHexStr80, cbc3desThenMd5digest80, iv1, 80, 80, -1},
+/*20*/ {hashHexStr80, cbc3desThenSha1digest80, iv1, 80, 80, -1},
+/*21*/ {hashHexStr80, cbcAes128ThenMd5digest80, iv5, 80, 80, -1},
+/*22*/ {hashHexStr80, cbcAes128ThenSha1digest80, iv5, 80, 80, -1},
+/*23*/ {cesaAesCtrPlain, cesaAesCtrCipher, NULL, 36, 0, -1},
+/*24*/ {cesaAesIvPlainText, cesaAes128IvCipherCbc, NULL, 64, 0, -1},
+/*25*/ {plain3des1, cipher3des1, NULL, 0, 0, -1},
+/*26*/ {plain3des2, cipher3desCbc2, iv3des2, 0, 0, -1},
+/*27*/ {plain3des3, cipher3desCbc3, iv3des3, 0, 0, -1},
+/*28*/ {cesaDataHexStr4, cesaHmacSha2digestHex1, NULL, 0, 34, -1},
+/*29*/ {NULL, cesaDataAndSha2digest1, NULL, 0, 34, -1},
+/*30*/ {hashHexStr3, hashSha2digest3, NULL, 0, 3, -1},
+/*31*/ {NULL, cesaDataAndSha2digest3, NULL, 0, 3, -1},
+/*32*/ {cesaAesPlainHexEcb, aes128EcbThenHmacSha2, NULL, 16, 16, -1},
+};
+
+/* Key         = 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ *               0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+ * Input 0xdd repeated "size" times
+ */
+static MV_CESA_SIZE_TEST mdMultiSizeTest302[] = {
+	{80, "7a031a640c14a4872814930b1ef3a5b2"},
+	{512, "5488e6c5a14dc72a79f28312ca5b939b"},
+	{1000, "d00814f586a8b78a05724239d2531821"},
+	{1001, "bf07df7b7f49d3f5b5ecacd4e9e63281"},
+	{1002, "1ed4a1a802e87817a819d4e37bb4d0f7"},
+	{1003, "5972ab64a4f265ee371dac2f2f137f90"},
+	{1004, "71f95e7ec3aa7df2548e90898abdb28e"},
+	{1005, "e082790b4857fcfc266e92e59e608814"},
+	{1006, "9500f02fd8ac7fde8b10e4fece9a920d"},
+	{1336, "e42edcce57d0b75b01aa09d71427948b"},
+	{1344, "bb5454ada0deb49ba0a97ffd60f57071"},
+	{1399, "0f44d793e744b24d53f44f295082ee8c"},
+	{1400, "359de8a03a9b707928c6c60e0e8d79f1"},
+	{1401, "e913858b484cbe2b384099ea88d8855b"},
+	{1402, "d9848a164af53620e0540c1d7d87629e"},
+	{1403, "0c9ee1c2c9ef45e9b625c26cbaf3e822"},
+	{1404, "12edd4f609416e3c936170360561b064"},
+	{1405, "7fc912718a05446395345009132bf562"},
+	{1406, "882f17425e579ff0d85a91a59f308aa0"},
+	{1407, "005cae408630a2fb5db82ad9db7e59da"},
+	{1408, "64655f8b404b3fea7a3e3e609bc5088f"},
+	{1409, "4a145284a7f74e01b6bb1a0ec6a0dd80"},
+	{2048, "67caf64475650732def374ebb8bde3fd"},
+	{2049, "6c84f11f472825f7e6cd125c2981884b"},
+	{2050, "8999586754a73a99efbe4dbad2816d41"},
+	{2051, "ba6946b610e098d286bc81091659dfff"},
+	{2052, "d0afa01c92d4d13def2b024f36faed83"},
+	{3072, "61d8beac61806afa2585d74a9a0e6974"},
+	{3074, "f6501a28dcc24d1e4770505c51a87ed3"},
+	{3075, "ea4a6929be67e33e61ff475369248b73"},
+	{4048, "aa8c4d68f282a07e7385acdfa69f4bed"},
+	{4052, "afb5ed2c0e1d430ea59e59ed5ed6b18a"},
+	{4058, "9e8553f9bdd43aebe0bd729f0e600c99"},
+	{6144, "f628f3e5d183fe5cdd3a5abee39cf872"},
+	{6150, "89a3efcea9a2f25f919168ad4a1fd292"},
+	{6400, "cdd176b7fb747873efa4da5e32bdf88f"},
+	{6528, "b1d707b027354aca152c45ee559ccd3f"},
+	{8192, "c600ea4429ac47f9941f09182166e51a"},
+	{16384, "16e8754bfbeb4c649218422792267a37"},
+	{18432, "0fd0607521b0aa8b52219cfbe215f63e"},
+	{0, NULL},
+};
+
+/* Key         = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ *               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ */
+static MV_CESA_SIZE_TEST mdMultiSizeTest304[] = {
+	{80, "a456c4723fee6068530af5a2afa71627"},
+	{512, "f85c2a2344f5de68b432208ad13e5794"},
+	{1000, "35464d6821fd4a293a41eb84e274c8c5"},
+	{1001, "c08eedbdce60cceb54bc2d732bb32c8b"},
+	{1002, "5664f71800c011cc311cb6943339c1b8"},
+	{1003, "779c723b044c585dc7802b13e8501bdc"},
+	{1004, "55e500766a2c307bc5c5fdd15e4cacd4"},
+	{1005, "d5f978954f5c38529d1679d2b714f068"},
+	{1006, "cd3efc827ce628b7281b72172693abf9"},
+	{1336, "6f04479910785878ae6335b8d1e87edf"},
+	{1344, "b6d27b50c2bce1ba2a8e1b5cc4324368"},
+	{1399, "65f70a1d4c86e5eaeb0704c8a7816795"},
+	{1400, "3394b5adc4cb3ff98843ca260a44a88a"},
+	{1401, "3a06f3582033a66a4e57e0603ce94e74"},
+	{1402, "e4d97f5ed51edc48abfa46eeb5c31752"},
+	{1403, "3d05e40b080ee3bedf293cb87b7140e7"},
+	{1404, "8cf294fc3cd153ab18dccb2a52cbf244"},
+	{1405, "d1487bd42f6edd9b4dab316631159221"},
+	{1406, "0527123b6bf6936cf5d369dc18c6c70f"},
+	{1407, "3224a06639db70212a0cd1ae1fcc570a"},
+	{1408, "a9e13335612c0356f5e2c27086e86c43"},
+	{1409, "a86d1f37d1ed8a3552e9a4f04dceea98"},
+	{2048, "396905c9b961cd0f6152abfb69c4449c"},
+	{2049, "49f39bff85d9dcf059fadb89efc4a70f"},
+	{2050, "3a2b4823bc4d0415656550226a63e34a"},
+	{2051, "dec60580d406c782540f398ad0bcc7e0"},
+	{2052, "32f76610a14310309eb748fe025081bf"},
+	{3072, "45edc1a42bf9d708a621076b63b774da"},
+	{3074, "9be1b333fe7c0c9f835fb369dc45f778"},
+	{3075, "8c06fcac7bd0e7b7a17fd6508c09a549"},
+	{4048, "0ddaef848184bf0ad98507a10f1e90e4"},
+	{4052, "81976bcaeb274223983996c137875cb8"},
+	{4058, "0b0a7a1c82bc7cbc64d8b7cd2dc2bb22"},
+	{6144, "1c24056f52725ede2dff0d7f9fc9855f"},
+	{6150, "b7f4b65681c4e43ee68ca466ca9ca4ec"},
+	{6400, "443bbaab9f7331ddd4bf11b659cd43c8"},
+	{6528, "216f44f23047cfee03a7a64f88f9a995"},
+	{8192, "ac7a993b2cad54879dba1bde63e39097"},
+	{8320, "55ed7be9682d6c0025b3221a62088d08"},
+	{16384, "c6c722087653b62007aea668277175e5"},
+	{18432, "f1faca8e907872c809e14ffbd85792d6"},
+	{0, NULL},
+};
+
+/* HASH-MD5
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ *               repeated "size" times
+ */
+static MV_CESA_SIZE_TEST mdMultiSizeTest305[] = {
+	{80, "57edf4a22be3c955ac49da2e2107b67a"},
+	{512, "c729ae8f0736cc377a9767a660eaa04e"},
+	{1000, "f1257a8659eb92d36fe14c6bf3852a6a"},
+	{1001, "f8a46fe8ea04fdc8c7de0e84042d3878"},
+	{1002, "da188dd67bff87d58aa3c02af2d0cc0f"},
+	{1003, "961753017feee04c9b93a8e51658a829"},
+	{1004, "dd68c4338608dcc87807a711636bf2af"},
+	{1005, "e338d567d3ce66bf69ada29658a8759b"},
+	{1006, "443c9811e8b92599b0b149e8d7ec700a"},
+	{1336, "89a98511706008ba4cbd0b4a24fa5646"},
+	{1344, "335a919805f370b9e402a62c6fe01739"},
+	{1399, "5d18d0eddcd84212fe28d812b5e80e3b"},
+	{1400, "6b695c240d2dffd0dffc99459ca76db6"},
+	{1401, "49590f61298a76719bc93a57a30136f5"},
+	{1402, "94c2999fa3ef1910a683d69b2b8476f2"},
+	{1403, "37073a02ab00ecba2645c57c228860db"},
+	{1404, "1bcd06994fce28b624f0c5fdc2dcdd2b"},
+	{1405, "11b93671a64c95079e8cf9e7cddc8b3d"},
+	{1406, "4b6695772a4c66313fa4871017d05f36"},
+	{1407, "d1539b97fbfda1c075624e958de19c5b"},
+	{1408, "b801b9b69920907cd018e8063092ede9"},
+	{1409, "b765f1406cfe78e238273ed01bbcaf7e"},
+	{2048, "1d7e2c64ac29e2b3fb4c272844ed31f5"},
+	{2049, "71d38fac49c6b1f4478d8d88447bcdd0"},
+	{2050, "141c34a5592b1bebfa731e0b23d0cdba"},
+	{2051, "c5e1853f21c59f5d6039bd13d4b380d8"},
+	{2052, "dd44a0d128b63d4b5cccd967906472d7"},
+	{3072, "37d158e33b21390822739d13db7b87fe"},
+	{3074, "aef3b209d01d39d0597fe03634bbf441"},
+	{3075, "335ffb428eabf210bada96d74d5a4012"},
+	{4048, "2434c2b43d798d2819487a886261fc64"},
+	{4052, "ac2fa84a8a33065b2e92e36432e861f8"},
+	{4058, "856781f85616c341c3533d090c1e1e84"},
+	{6144, "e5d134c652c18bf19833e115f7a82e9b"},
+	{6150, "a09a353be7795fac2401dac5601872e6"},
+	{6400, "08b9033ac6a1821398f50af75a2dbc83"},
+	{6528, "3d47aa193a8540c091e7e02f779e6751"},
+	{8192, "d3164e710c0626f6f395b38f20141cb7"},
+	{8320, "b727589d9183ff4e8491dd24466974a3"},
+	{16384, "3f54d970793d2274d5b20d10a69938ac"},
+	{18432, "f558511dcf81985b7a1bb57fad970531"},
+	{0, NULL},
+};
+
+/* Key         = 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ *               0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+ *               0xaa, 0xaa, 0xaa, 0xaa
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ */
+static MV_CESA_SIZE_TEST sha1MultiSizeTest402[] = {
+	{80, "e812f370e659705a1649940d1f78cd7af18affd3"},
+	{512, "e547f886b2c15d995ed76a8a924cb408c8080f66"},
+	{1000, "239443194409f1a5342ecde1a092c8f3a3ed790a"},
+	{1001, "f278ab9a102850a9f48dc4e9e6822afe2d0c52b5"},
+	{1002, "8bcc667df5ab6ece988b3af361d09747c77f4e72"},
+	{1003, "0fae6046c7dc1d3e356b25af836f6077a363f338"},
+	{1004, "0ea48401cc92ae6bc92ae76685269cb0167fbe1a"},
+	{1005, "ecbcd7c879b295bafcd8766cbeac58cc371e31d1"},
+	{1006, "eb4a4a3d07d1e9a15e6f1ab8a9c47f243e27324c"},
+	{1336, "f5950ee1d77c10e9011d2149699c9366fe52529c"},
+	{1344, "b04263604a63c351b0b3b9cf1785b4bdba6c8838"},
+	{1399, "8cb1cff61d5b784045974a2fc69386e3b8d24218"},
+	{1400, "9bb2f3fcbeddb2b90f0be797cd647334a2816d51"},
+	{1401, "23ae462a7a0cb440f7445791079a5d75a535dd33"},
+	{1402, "832974b524a4d3f9cc2f45a3cabf5ccef65cd2aa"},
+	{1403, "d1c683742fe404c3c20d5704a5430e7832a7ec95"},
+	{1404, "867c79042e64f310628e219d8b85594cd0c7adc3"},
+	{1405, "c9d81d49d13d94358f56ccfd61af02b36c69f7c3"},
+	{1406, "0df43daab2786172f9b8d07d61f14a070cf1287a"},
+	{1407, "0fd8f3ad7f169534b274d4c66bbddd89f759e391"},
+	{1408, "3987511182b18473a564436003139b808fa46343"},
+	{1409, "ef667e063c9e9f539a8987a8d0bd3066ee85d901"},
+	{2048, "921109c99f3fedaca21727156d5f2b4460175327"},
+	{2049, "47188600dd165eb45f27c27196d3c46f4f042c1b"},
+	{2050, "8831939904009338de10e7fa670847041387807d"},
+	{2051, "2f8ebb5db2997d614e767be1050366f3641e7520"},
+	{2052, "669e51cd730dae158d3bef8adba075bd95a0d011"},
+	{3072, "cfee66cfd83abc8451af3c96c6b35a41cc6c55f5"},
+	{3074, "216ea26f02976a261b7d21a4dd3085157bedfabd"},
+	{3075, "bd612ebba021fd8e012b14c3bd60c8c5161fabc0"},
+	{4048, "c2564c1fdf2d5e9d7dde7aace2643428e90662e8"},
+	{4052, "91ce61fe924b445dfe7b5a1dcd10a27caec16df6"},
+	{4058, "db2a9be5ee8124f091c7ebd699266c5de223c164"},
+	{6144, "855109903feae2ba3a7a05a326b8a171116eb368"},
+	{6150, "37520bb3a668294d9c7b073e7e3daf8fee248a78"},
+	{6400, "60a353c841b6d2b1a05890349dad2fa33c7536b7"},
+	{6528, "9e53a43a69bb42d7c8522ca8bd632e421d5edb36"},
+	{8192, "a918cb0da862eaea0a33ee0efea50243e6b4927c"},
+	{8320, "29a5dcf55d1db29cd113fcf0572ae414f1c71329"},
+	{16384, "6fb27966138e0c8d5a0d65ace817ebd53633cee1"},
+	{18432, "ca09900d891c7c9ae2a559b10f63a217003341c1"},
+	{0, NULL},
+};
+
+/* Key         = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ *               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+ *               0x11, 0x12, 0x13, 0x14
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ */
+static MV_CESA_SIZE_TEST sha1MultiSizeTest404[] = {
+	{80, "beaf20a34b06a87558d156c0949bc3957d40222e"},
+	{512, "3353955358d886bc2940a3c7f337ff7dafb59c7b"},
+	{1000, "8737a542c5e9b2b6244b757ebb69d5bd602a829f"},
+	{1001, "fd9e7582d8a5d3c9fe3b923e4e6a41b07a1eb4d4"},
+	{1002, "a146d14a6fc3c274ff600568f4d75b977989e00d"},
+	{1003, "be22601bbc027ddef2dec97d30b3dc424fd803c5"},
+	{1004, "3e71fe99b2fe2b7bfdf4dbf0c7f3da25d7ea35e7"},
+	{1005, "2c422735d7295408fddd76f5e8a83a2a8da13df3"},
+	{1006, "6d875319049314b61855101a647b9ba3313428e6"},
+	{1336, "c1631ea80bad9dc43a180712461b65a0598c711c"},
+	{1344, "816069bf91d34581005746e2e0283d0f9c7b7605"},
+	{1399, "4e139866dc61cfcb8b67ca2ebd637b3a538593af"},
+	{1400, "ff2a0f8dd2b02c5417910f6f55d33a78e081a723"},
+	{1401, "ab00c12be62336964cbce31ae97fe2a0002984d5"},
+	{1402, "61349e7f999f3a1acc56c3e9a5060a9c4a7b05b6"},
+	{1403, "3edbc0f61e435bc1317fa27d840076093fb79353"},
+	{1404, "d052c6dfdbe63d45dab23ef9893e2aa4636aca1e"},
+	{1405, "0cc16b7388d67bf0add15a31e6e6c753cfae4987"},
+	{1406, "c96ba7eaad74253c38c22101b558d2850b1d1b90"},
+	{1407, "3445428a40d2c6556e7c55797ad8d323b61a48d9"},
+	{1408, "8d6444f937a09317c89834187b8ea9b8d3a8c56b"},
+	{1409, "c700acd3ecd19014ea2bdb4d42510c467e088475"},
+	{2048, "ee27d2a0cb77470c2f496212dfd68b5bb7b04e4b"},
+	{2049, "683762d7a02983b26a6d046e6451d9cd82c25932"},
+	{2050, "0fd20f1d55a9ee18363c2a6fd54aa13aee69992f"},
+	{2051, "86c267d8cc4bc8d59090e4f8b303da960fd228b7"},
+	{2052, "452395ae05b3ec503eea34f86fc0832485ad97c1"},
+	{3072, "75198e3cfd0b9bcff2dabdf8e38e6fdaa33ca49a"},
+	{3074, "4e24785ef080141ce4aab4675986d9acea624d7c"},
+	{3075, "3a20c5978dd637ec0e809bf84f0d9ccf30bc65bf"},
+	{4048, "3c32da256be7a7554922bf5fed51b0d2d09e59ad"},
+	{4052, "fff898426ea16e54325ae391a32c6c9bce4c23c0"},
+	{4058, "c800b9e562e1c91e1310116341a3c91d37f848ec"},
+	{6144, "d91d509d0cc4376c2d05bf9a5097717a373530e6"},
+	{6150, "d957030e0f13c5df07d9eec298542d8f94a07f12"},
+	{6400, "bb745313c3d7dc17b3f955e5534ad500a1082613"},
+	{6528, "77905f80d9ca82080bbb3e5654896dabfcfd1bdb"},
+	{8192, "5237fd9a81830c974396f99f32047586612ff3c0"},
+	{8320, "57668e28d5f2dba0839518a11db0f6af3d7e08bf"},
+	{16384, "62e093fde467f0748087beea32e9af97d5c61241"},
+	{18432, "845fb33130c7d6ea554fd5aacb9c50cf7ccb5929"},
+	{0, NULL},
+};
+
+/* HASH-SHA1
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ *               repeated "size" times
+ */
+static MV_CESA_SIZE_TEST sha1MultiSizeTest405[] = {
+	{80, "50abf5706a150990a08b2c5ea40fa0e585554732"},
+	{512, "f14516a08948fa27917a974d219741a697ba0087"},
+	{1000, "0bd18c378d5788817eb4f1e5dc07d867efa5cbf4"},
+	{1001, "ca29b85c35db1b8aef83c977893a11159d1b7aa2"},
+	{1002, "d83bc973eaaedb8a31437994dabbb3304b0be086"},
+	{1003, "2cf7bbef0acd6c00536b5c58ca470df9a3a90b6c"},
+	{1004, "e4375d09b1223385a8a393066f8209acfd936a80"},
+	{1005, "1029b38043e027745d019ce1d2d68e3d8b9d8f99"},
+	{1006, "deea16dcebbd8ac137e2b984deb639b9fb5e9680"},
+	{1336, "ea031b065fff63dcfb6a41956e4777520cdbc55d"},
+	{1344, "b52096c6445e6c0a8355995c70dc36ae186c863c"},
+	{1399, "cde2f6f8379870db4b32cf17471dc828a8dbff2b"},
+	{1400, "e53ff664064bc09fe5054c650806bd42d8179518"},
+	{1401, "d1156db5ddafcace64cdb510ff0d4af9b9a8ad64"},
+	{1402, "34ede0e9a909dd84a2ae291539105c0507b958e1"},
+	{1403, "a772ca3536da77e6ad3251e4f9e1234a4d7b87c0"},
+	{1404, "29740fd2b04e7a8bfd32242db6233156ad699948"},
+	{1405, "65b17397495b70ce4865dad93bf991b74c97cce1"},
+	{1406, "a7ee89cd0754061fdb91af7ea6abad2c69d542e3"},
+	{1407, "3eebf82f7420188e23d328b7ce93580b279a5715"},
+	{1408, "e08d3363a8b9a490dfb3a4c453452b8f114deeec"},
+	{1409, "95d74df739181a4ff30b8c39e28793a36598e924"},
+	{2048, "aa40262509c2abf84aab0197f83187fc90056d91"},
+	{2049, "7dec28ef105bc313bade8d9a7cdeac58b99de5ea"},
+	{2050, "d2e30f77ec81197de20f56588a156094ecb88450"},
+	{2051, "6b22ccc874833e96551a39da0c0edcaa0d969d92"},
+	{2052, "f843141e57875cd669af58744bc60aa9ea59549c"},
+	{3072, "09c5fedeaa62c132e673cc3c608a00142273d086"},
+	{3074, "b09e95eea9c7b1b007a58accec488301901a7f3d"},
+	{3075, "e6226b77b4ada287a8c9bbcf4ed71eec5ce632dc"},
+	{4048, "e99394894f855821951ddddf5bfc628547435f5c"},
+	{4052, "32d2f1af38be9cfba6cd03d55a254d0b3e1eb382"},
+	{4058, "d906552a4f2aca3a22e1fecccbcd183d7289d0ef"},
+	{6144, "2e7f62d35a860988e1224dc0543204af19316041"},
+	{6150, "d6b89698ee133df46fec9d552fadc328aa5a1b51"},
+	{6400, "dff50e90c46853988fa3a4b4ce5dda6945aae976"},
+	{6528, "9e63ec0430b96db02d38bc78357a2f63de2ab7f8"},
+	{8192, "971eb71ed60394d5ab5abb12e88420bdd41b5992"},
+	{8320, "91606a31b46afeaac965cecf87297e791b211013"},
+	{16384, "547f830a5ec1f5f170ce818f156b1002cabc7569"},
+	{18432, "f16f272787f3b8d539652e4dc315af6ab4fda0ef"},
+	{0, NULL},
+};
+
+/* CryptoKey   = 0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef;
+ * MacKey      = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ *               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ * Note: only sizes aligned to 3DES block size (8 bytes) allowed
+ */
+static MV_CESA_SIZE_TEST tripleDesMdMultiSizeTest602[] = {
+	{64, "9586962a2aaaef28803dec2e17807a7f"},
+	{80, "b7726a03aad490bd6c5a452a89a1b271"},
+	{352, "f1ed9563aecc3c0d2766eb2bed3b4e4c"},
+	{512, "0f9decb11ab40fe86f4d4d9397bc020e"},
+	{1000, "3ba69deac12cab8ff9dff7dbd9669927"},
+	{1336, "6cf47bf1e80e03e2c1d0945bc50d37d2"},
+	{1344, "4be388dab21ceb3fa1b8d302e9b821f7"},
+	{1400, "a58b79fb21dd9bfc6ec93e3b99fb0ef1"},
+	{1408, "8bc97379fc2ac3237effcdd4f7a86528"},
+	{2048, "1339f03ab3076f25a20bc4cba16eb5bf"},
+	{3072, "731204d2d90c4b36ae41f5e1fb874288"},
+	{4048, "c028d998cfda5642547b7e1ed5ea16e4"},
+	{6144, "b1b19cd910cc51bd22992f1e59f1e068"},
+	{6400, "44e4613496ba622deb0e7cb768135a2f"},
+	{6528, "3b06b0a86f8db9cd67f9448dfcf10549"},
+	{8192, "d581780b7163138a0f412be681457d82"},
+	{16384, "03b8ac05527faaf1bed03df149c65ccf"},
+	{18432, "677c8a86a41dab6c5d81b85b8fb10ff6"},
+	{0, NULL},
+};
+
+/* CryptoKey   = 0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef;
+ * MacKey      = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ *               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+ *               0x11, 0x12, 0x13, 0x14
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ * Note: only sizes aligned to 3DES block size (8 bytes) allowed
+ */
+static MV_CESA_SIZE_TEST tripleDesShaMultiSizeTest603[] = {
+	{64, "44a1e9bcbfc1429630d9ea68b7a48b0427a684f2"},
+	{80, "b2ddeaca91030eab5b95a234ef2c0f6e738ff883"},
+	{352, "4b91864c7ff629bdff75d9726421f76705452aaf"},
+	{512, "6dd37faceeb2aa98ba74f4242ed6734a4d546af5"},
+	{1000, "463661c30300be512a9df40904f0757cde5f1141"},
+	{1336, "b931f831d9034fe59c65176400b039fe9c1f44a5"},
+	{1344, "af8866b1cd4a4887d6185bfe72470ffdfb3648e1"},
+	{1400, "49c6caf07296d5e31d2504d088bc5b20c3ee7cdb"},
+	{1408, "fcae8deedbc6ebf0763575dc7e9de075b448a0f4"},
+	{2048, "edece5012146c1faa0dd10f50b183ba5d2af58ac"},
+	{3072, "5b83625adb43a488b8d64fecf39bb766818547b7"},
+	{4048, "d2c533678d26c970293af60f14c8279dc708bfc9"},
+	{6144, "b8f67af4f991b08b725f969b049ebf813bfacc5c"},
+	{6400, "d9a6c7f746ac7a60ef2edbed2841cf851c25cfb0"},
+	{6528, "376792b8c8d18161d15579fb7829e6e3a27e9946"},
+	{8192, "d890eabdca195b34ef8724b28360cffa92ae5655"},
+	{16384, "a167ee52639ec7bf19aee9c6e8f76667c14134b9"},
+	{18432, "e4396ab56f67296b220985a12078f4a0e365d2cc"},
+	{0, NULL},
+};
+
+/* CryptoKey   = 0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef
+ * IV          = 0x12345678, 0x90abcdef
+ * MacKey      = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ *               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ * Note: only sizes aligned to 3DES block size (8 bytes) allowed
+ */
+static MV_CESA_SIZE_TEST cbc3desMdMultiSizeTest604[] = {
+	{64, "8d10e00802460ede0058c139ba48bd2d"},
+	{80, "6f463057e1a90e0e91ae505b527bcec0"},
+	{352, "4938d48bdf86aece2c6851e7c6079788"},
+	{512, "516705d59f3cf810ebf2a13a23a7d42e"},
+	{1000, "a5a000ee5c830e67ddc6a2d2e5644b31"},
+	{1336, "44af60087b74ed07950088efbe3b126a"},
+	{1344, "1f5b39e0577920af731dabbfcf6dfc2a"},
+	{1400, "6804ea640e29b9cd39e08bc37dbce734"},
+	{1408, "4fb436624b02516fc9d1535466574bf9"},
+	{2048, "c909b0985c423d8d86719f701e9e83db"},
+	{3072, "cfe0bc34ef97213ee3d3f8b10122db21"},
+	{4048, "03ea10b5ae4ddeb20aed6af373082ed1"},
+	{6144, "b9a0ff4f87fc14b3c2dc6f0ed0998fdf"},
+	{6400, "6995f85d9d4985dd99e974ec7dda9dd6"},
+	{6528, "bbbb548ce2fa3d58467f6a6a5168a0e6"},
+	{8192, "afe101fbe745bb449ae4f50d10801456"},
+	{16384, "9741706d0b1c923340c4660ff97cacdf"},
+	{18432, "b0217becb73cb8f61fd79c7ce9d023fb"},
+	{0, NULL},
+};
+
+/* CryptoKey   = 0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef;
+ * IV          = 0x12345678, 0x90abcdef
+ * MacKey      = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ *               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+ *               0x11, 0x12, 0x13, 0x14
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ * Note: only sizes aligned to 3DES block size (8 bytes) allowed
+ */
+static MV_CESA_SIZE_TEST cbc3desShaMultiSizeTest605[] = {
+	{64, "409187e5bdb0be4a7754ca3747f7433dc4f01b98"},
+	{80, "1b002ed050be743aa98860cf35659646bb8efcc0"},
+	{352, "6cbf7ebe50fa4fa6eecc19eca23f9eae553ccfff"},
+	{512, "cfb5253fb4bf72b743320c30c7e48c54965853b0"},
+	{1000, "95e04e1ca2937e7c5a9aba9e42d2bcdb8a7af21f"},
+	{1336, "3b5c1f5eee5837ebf67b83ae01405542d77a6627"},
+	{1344, "2b3d42ab25615437f98a1ee310b81d07a02badc2"},
+	{1400, "7f8687df7c1af44e4baf3c934b6cca5ab6bc993e"},
+	{1408, "473a581c5f04f7527d50793c845471ac87e86430"},
+	{2048, "e41d20cae7ebe34e6e828ed62b1e5734019037bb"},
+	{3072, "275664afd7a561d804e6b0d204e53939cde653ae"},
+	{4048, "0d220cc5b34aeeb46bbbd637dde6290b5a8285a3"},
+	{6144, "cb393ddcc8b1c206060625b7d822ef9839e67bc5"},
+	{6400, "dd3317e2a627fc04800f74a4b05bfda00fab0347"},
+	{6528, "8a74c3b2441ab3f5a7e08895cc432566219a7c41"},
+	{8192, "b8e6ef3a549ed0e005bd5b8b1a5fe6689e9711a7"},
+	{16384, "55f59404008276cdac0e2ba0d193af2d40eac5ce"},
+	{18432, "86ae6c4fc72369a54cce39938e2d0296cd9c6ec5"},
+	{0, NULL},
+};
+
+/* CryptoKey   = 0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef
+ * IV          = 0x12345678, 0x90abcdef
+ * MacKey      = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ *               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ * Note: only sizes aligned to AES block size (16 bytes) allowed
+ */
+static MV_CESA_SIZE_TEST cbcAes128md5multiSizeTest606[] = {
+	{16, "7ca4c2ba866751598720c5c4aa0d6786"},
+	{64, "7dba7fb988e80da609b1fea7254bced8"},
+	{80, "6b6e863ac5a71d15e3e9b1c86c9ba05f"},
+	{352, "a1ceb9c2e3021002400d525187a9f38c"},
+	{512, "596c055c1c55db748379223164075641"},
+	{1008, "f920989c02f3b3603f53c99d89492377"},
+	{1344, "2e496b73759d77ed32ea222dbd2e7b41"},
+	{1408, "7178c046b3a8d772efdb6a71c4991ea4"},
+	{2048, "a917f0099c69eb94079a8421714b6aad"},
+	{3072, "693cd5033d7f5391d3c958519fa9e934"},
+	{4048, "139dca91bcff65b3c40771749052906b"},
+	{6144, "428d9cef6df4fb70a6e9b6bbe4819e55"},
+	{6400, "9c0b909e76daa811e12b1fc17000a0c4"},
+	{6528, "ad876f6297186a7be1f1b907ed860eda"},
+	{8192, "479cbbaca37dd3191ea1f3e8134a0ef4"},
+	{16384, "60fda559c74f91df538100c9842f2f15"},
+	{18432, "4a3eb1cba1fa45f3981270953f720c42"},
+	{0, NULL},
+};
+
+/* CryptoKey   = 0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef,
+ *               0x01234567, 0x89abcdef;
+ * IV          = 0x12345678, 0x90abcdef
+ * MacKey      = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ *               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+ *               0x11, 0x12, 0x13, 0x14
+ * InputHexStr = "31323334353637383930" (ASCII = "1234567890")
+ * Note: only sizes aligned to AES block size (16 bytes) allowed
+ */
+static MV_CESA_SIZE_TEST cbcAes128sha1multiSizeTest607[] = {
+	{16, "9aa8dc1c45f0946daf78057fa978759c625c1fee"},
+	{64, "9f588fc1ede851e5f8b20256abc9979465ae2189"},
+	{80, "13558472d1fc1c90dffec6e5136c7203452d509b"},
+	{352, "6b93518e006cfaa1f7adb24615e7291fb0a27e06"},
+	{512, "096874951a77fbbf333e49d80c096ee2016e09bd"},
+	{1008, "696fc203c2e4b5ae0ec5d1db3f623c490bc6dbac"},
+	{1344, "79bf77509935ccd3528caaac6a5eb6481f74029b"},
+	{1408, "627f9462b95fc188e8cfa7eec15119bdc5d4fcf1"},
+	{2048, "3d50d0c005feba92fe41502d609fced9c882b4d1"},
+	{3072, "758807e5b983e3a91c06fb218fe0f73f77111e94"},
+	{4048, "ca90e85242e33f005da3504416a52098d0d31fb2"},
+	{6144, "8044c1d4fd06642dfc46990b4f18b61ef1e972cf"},
+	{6400, "166f1f4ea57409f04feba9fb1e39af0e00bd6f43"},
+	{6528, "0389016a39485d6e330f8b4215ddf718b404f7e9"},
+	{8192, "6df7ee2a8b61d6f7f860ce8dbf778f0c2a5b508b"},
+	{16384, "a70a6d8dfa1f91ded621c3dbaed34162bc48783f"},
+	{18432, "8dfad627922ce15df1eed10bdbed49244efa57db"},
+	{0, NULL},
+};
+
+void cesaTestPrintStatus(void);
+
+/*------------------------- LOCAL FUNCTIONs ---------------------------------*/
+MV_STATUS testCmd(int sid, int iter, MV_CESA_COMMAND *pCmd,
+		  MV_CESA_TEST_SESSION *pTestSession, MV_U8 *pIV, int ivSize);
+MV_STATUS testClose(int idx);
+MV_STATUS testOpen(int idx);
+void close_session(int sid);
+void cesaTestCheckReady(const MV_CESA_RESULT *r);
+void cesaCheckReady(MV_CESA_RESULT *r);
+void printTestResults(int idx, MV_STATUS status, int checkMode);
+void cesaLastResult(void);
+void cesaTestPrintReq(int req, int offset, int size);
+
+void cesaTestPrintStatus(void);
+void cesaTestPrintSession(int idx);
+void sizeTest(int testIdx, int iter, int checkMode);
+void multiTest(int iter, int reqSize, int checkMode);
+void oneTest(int testIdx, int caseIdx, int iter, int reqSize, int checkMode);
+void multiSizeTest(int idx, int iter, int checkMode, char *inputData);
+void cesaTest(int iter, int reqSize, int checkMode);
+void cesaOneTest(int testIdx, int caseIdx, int iter, int reqSize, int checkMode);
+void combiTest(int iter, int reqSize, int checkMode);
+void sha1Test(int iter, int reqSize, int checkMode);
+void sha2Test(int iter, int reqSize, int checkMode);
+void mdTest(int iter, int reqSize, int checkMode);
+void aesTest(int iter, int reqSize, int checkMode);
+void tripleDesTest(int iter, int reqSize, int checkMode);
+void desTest(int iter, int reqSize, int checkMode);
+void cesaTestStop(void);
+MV_STATUS testRun(int idx, int caseIdx, int iter, int reqSize, int checkMode);
+void cesaTestStart(int bufNum, int bufSize);
+
+static MV_U32 getRate(MV_U32 *remainder)
+{
+	MV_U32 rate;
+#ifdef MV_LINUX
+	rate = ((cesaIteration * cesaRateSize * 8) / (cesaEndTicks - cesaBeginTicks));
+	*remainder = 0;
+#else
+	MV_U32 kBits, milliSec;
+
+	milliSec = 0;
+	if ((cesaEndTicks - cesaBeginTicks) > 0)
+		milliSec = CESA_TEST_TICK_TO_MS(cesaEndTicks - cesaBeginTicks);
+
+	if (milliSec == 0) {
+		if (remainder != NULL)
+			*remainder = 0;
+		return 0;
+	}
+
+	kBits = (cesaIteration * cesaRateSize * 8) / 1000;
+	rate = kBits / milliSec;
+	if (remainder != NULL)
+		*remainder = ((kBits % milliSec) * 10) / milliSec;
+#endif
+	return rate;
+}
+
+static char *extractMbuf(MV_CESA_MBUF *pMbuf, int offset, int size, char *hexStr)
+{
+	mvCesaCopyFromMbuf((MV_U8 *)cesaBinBuffer, pMbuf, offset, size);
+	mvBinToHex((const MV_U8 *)cesaBinBuffer, hexStr, size);
+
+	return hexStr;
+}
+
+static MV_BOOL cesaCheckMbuf(MV_CESA_MBUF *pMbuf, const char *hexString, int offset, int checkSize)
+{
+	MV_BOOL isFailed = MV_FALSE;
+	MV_STATUS status;
+	int size = strlen(hexString) / 2;
+	int checkedSize = 0;
+/*
+	mvOsPrintf("cesaCheckMbuf: pMbuf=%p, offset=%d, checkSize=%d, mBufSize=%d\n",
+			pMbuf, offset, checkSize, pMbuf->mbufSize);
+*/
+	if (pMbuf->mbufSize < (checkSize + offset)) {
+		mvOsPrintf("checkSize (%d) is too large: offset=%d, mbufSize=%d\n", checkSize, offset, pMbuf->mbufSize);
+		return MV_TRUE;
+	}
+	status = mvCesaCopyFromMbuf((MV_U8 *)cesaBinBuffer, pMbuf, offset, checkSize);
+	if (status != MV_OK) {
+		mvOsPrintf("CesaTest: Can't copy %d bytes from Mbuf=%p to checkBuf=%p\n",
+			   checkSize, pMbuf, cesaBinBuffer);
+		return MV_TRUE;
+	}
+/*
+    mvDebugMemDump(cesaBinBuffer, size, 1);
+*/
+	mvHexToBin(hexString, (MV_U8 *)cesaExpBinBuffer, size);
+
+	/* Compare buffers */
+	while (checkSize > checkedSize) {
+		size = MV_MIN(size, (checkSize - checkedSize));
+		if (memcmp(cesaExpBinBuffer, &cesaBinBuffer[checkedSize], size) != 0) {
+			mvOsPrintf("CheckMbuf failed: checkSize=%d, size=%d, checkedSize=%d\n",
+				   checkSize, size, checkedSize);
+			mvDebugMemDump(&cesaBinBuffer[checkedSize], size, 1);
+			mvDebugMemDump(cesaExpBinBuffer, size, 1);
+
+			isFailed = MV_TRUE;
+			break;
+		}
+		checkedSize += size;
+	}
+
+	return isFailed;
+}
+
+static MV_STATUS cesaSetMbuf(MV_CESA_MBUF *pMbuf, const char *hexString, int offset, int reqSize)
+{
+	MV_STATUS status = MV_OK;
+	int copySize, size = strlen(hexString) / 2;
+
+	mvHexToBin(hexString, (MV_U8 *)cesaBinBuffer, size);
+
+	copySize = 0;
+	while (reqSize > copySize) {
+		size = MV_MIN(size, (reqSize - copySize));
+
+		status = mvCesaCopyToMbuf((MV_U8 *)cesaBinBuffer, pMbuf, offset + copySize, size);
+		if (status != MV_OK) {
+			mvOsPrintf("cesaSetMbuf Error: Copy %d of %d bytes to MBuf\n", copySize, reqSize);
+			break;
+		}
+		copySize += size;
+	}
+	pMbuf->mbufSize = offset + copySize;
+	return status;
+}
+
+static MV_CESA_TEST_SESSION *getTestSessionDb(int idx, int *pTestIdx)
+{
+	int testIdx, dbIdx = idx / 100;
+
+	if (dbIdx > MAX_TEST_TYPE) {
+		mvOsPrintf("Wrong index %d - No such test type\n", idx);
+		return NULL;
+	}
+	testIdx = idx % 100;
+
+	if (testIdx >= cesaTestsDB[dbIdx].numSessions) {
+		mvOsPrintf("Wrong index %d - No such test\n", idx);
+		return NULL;
+	}
+	if (pTestIdx != NULL)
+		*pTestIdx = testIdx;
+
+	return cesaTestsDB[dbIdx].pSessions;
+}
+
+/* Debug */
+void cesaTestPrintReq(int req, int offset, int size)
+{
+	MV_CESA_MBUF *pMbuf;
+
+	mvOsPrintf("cesaTestPrintReq: req=%d, offset=%d, size=%d\n", req, offset, size);
+	mvDebugMemDump(cesaCmdRing, 128, 4);
+
+	pMbuf = cesaCmdRing[req].pSrc;
+	mvCesaIfDebugMbuf("src", pMbuf, offset, size);
+	pMbuf = cesaCmdRing[req].pDst;
+	mvCesaIfDebugMbuf("dst", pMbuf, offset, size);
+
+	cesaTestPrintStatus();
+}
+
+void cesaLastResult(void)
+{
+	mvOsPrintf("Last Result: ReqId = %d, SessionId = %d, rc = (%d)\n",
+		   (MV_U32) cesaResult.pReqPrv, cesaResult.sessionId, cesaResult.retCode);
+}
+
+void printTestResults(int idx, MV_STATUS status, int checkMode)
+{
+	int testIdx;
+	MV_CESA_TEST_SESSION *pTestSessions = getTestSessionDb(idx, &testIdx);
+
+	if (pTestSessions == NULL)
+		return;
+
+	mvOsPrintf("%-35s %4dx%-4d : ", pTestSessions[testIdx].name, cesaIteration, cesaReqSize);
+	if ((status == MV_OK) && (cesaCryptoError == 0) && (cesaError == 0) && (cesaReqIdError == 0)) {
+		mvOsPrintf("Passed, Rate=%3u.%u Mbps (%5u cpp)\n",
+			   cesaRate, cesaRateAfterDot, cesaEndTicks - cesaBeginTicks);
+	} else {
+		mvOsPrintf("Failed, Status = 0x%x\n", status);
+		if (cesaCryptoError > 0)
+			mvOsPrintf("cryptoError : %d\n", cesaCryptoError);
+		if (cesaReqIdError > 0)
+			mvOsPrintf("reqIdError  : %d\n", cesaReqIdError);
+		if (cesaError > 0)
+			mvOsPrintf("cesaError  : %d\n", cesaError);
+	}
+	if (cesaTestIsrMissCount > 0)
+		mvOsPrintf("cesaIsrMissed  : %d\n", cesaTestIsrMissCount);
+}
+
+void cesaCheckReady(MV_CESA_RESULT *r)
+{
+	int reqId;
+	MV_CESA_MBUF *pMbuf;
+	MV_BOOL isFailed;
+
+	cesaResult = *r;
+	reqId = (int)cesaResult.pReqPrv;
+	pMbuf = cesaCmdRing[reqId].pDst;
+
+/*
+	mvOsPrintf("cesaCheckReady: reqId=%d, checkOffset=%d, checkSize=%d\n",
+			reqId, cesaCheckOffset, cesaCheckSize);
+*/
+	/* Check expected reqId */
+	if (reqId != cesaExpReqId) {
+		cesaReqIdError++;
+
+	mvOsPrintf("CESA reqId Error: cbIter=%d (%d), reqId=%d, expReqId=%d\n",
+				cesaCbIter, cesaIteration, reqId, cesaExpReqId);
+
+	} else {
+		if ((cesaCheckMode == CESA_FULL_CHECK_MODE) || (cesaCheckMode == CESA_FAST_CHECK_MODE)) {
+			if (cesaResult.retCode != MV_OK) {
+				cesaError++;
+
+				mvOsPrintf("CESA Error: cbIter=%d (%d), reqId=%d, rc=%d\n",
+					   cesaCbIter, cesaIteration, reqId, cesaResult.retCode);
+			} else {
+				if ((cesaCheckSize > 0) && (cesaOutputHexStr != NULL)) {
+					/* Check expected output */
+
+					isFailed =
+					    cesaCheckMbuf(pMbuf, cesaOutputHexStr, cesaCheckOffset, cesaCheckSize);
+					if (isFailed) {
+						mvOsPrintf("CESA Crypto Error: cbIter=%d (%d), reqId=%d\n",
+							   cesaCbIter, cesaIteration, reqId);
+
+						CESA_TEST_DEBUG_PRINT(("Error: reqId=%d, reqSize=%d, checkOffset=%d, checkSize=%d\n",
+											   reqId, cesaReqSize, cesaCheckOffset, cesaCheckSize));
+
+						CESA_TEST_DEBUG_PRINT(("Output str: %s\n", cesaOutputHexStr));
+
+						CESA_TEST_DEBUG_CODE(mvCesaIfDebugMbuf
+								     ("error", pMbuf, 0,
+								      cesaCheckOffset + cesaCheckSize));
+
+						cesaCryptoError++;
+					}
+				}
+			}
+		}
+	}
+	if (cesaCheckMode == CESA_SHOW_CHECK_MODE) {
+		extractMbuf(pMbuf, cesaCheckOffset, cesaCheckSize, cesaHexBuffer);
+		mvOsPrintf("%4d, %s\n", cesaCheckOffset, cesaHexBuffer);
+	}
+
+	cesaCbIter++;
+	if (cesaCbIter >= cesaIteration) {
+		cesaCbIter = 0;
+		cesaExpReqId = 0;
+		cesaIsReady = MV_TRUE;
+#ifdef MV_LINUX
+		do_gettimeofday(&tv);
+		cesaEndTicks = ((tv.tv_sec * 1000000) + tv.tv_usec);
+#else
+		cesaEndTicks = CESA_TEST_TICK_GET();
+#endif
+		cesaRate = getRate(&cesaRateAfterDot);
+	} else {
+		cesaExpReqId = reqId + 1;
+		if (cesaExpReqId == CESA_DEF_REQ_SIZE)
+			cesaExpReqId = 0;
+	}
+}
+
+#ifdef MV_NETBSD
+static int cesaTestReadyIsr(void *arg)
+#else
+#ifdef __KERNEL__
+static irqreturn_t cesaTestReadyIsr(int irq, void *dev_id)
+#endif
+#ifdef MV_VXWORKS
+void cesaTestReadyIsr(void)
+#endif
+#endif
+{
+	MV_U32 cause;
+	MV_STATUS status;
+	MV_CESA_RESULT result;
+	MV_U8 chan = 0;
+
+	cesaTestIsrCount++;
+
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+
+		cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG(chan));
+
+		if ((cause & MV_CESA_CAUSE_ACC_DMA_ALL_MASK) != 0) {
+			MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+			while (MV_TRUE) {
+				/* Get Ready requests */
+				status = mvCesaIfReadyGet(chan, &result);
+				if (status == MV_OK)
+					cesaCheckReady(&result);
+				else
+					break;
+			}
+
+			if ((cesaTestFull == 1) && (status != MV_BUSY)) {
+				cesaTestFull = 0;
+				CESA_TEST_WAKE_UP();
+			}
+		}
+	}
+
+#ifdef MV_NETBSD
+		return 0;
+#else
+#ifdef __KERNEL__
+		return 1;
+#else
+		return;
+#endif
+#endif
+
+}
+
+void cesaTestCheckReady(const MV_CESA_RESULT *r)
+{
+	MV_CESA_RESULT result = *r;
+
+	cesaCheckReady(&result);
+
+	if (cesaTestFull == 1) {
+		cesaTestFull = 0;
+		CESA_TEST_WAKE_UP();
+	}
+}
+
+static INLINE int open_session(MV_CESA_OPEN_SESSION *pOs)
+{
+	MV_U16 sid;
+	MV_STATUS status;
+
+	status = mvCesaIfSessionOpen(pOs, (short *)&sid);
+	if (status != MV_OK) {
+		mvOsPrintf("CesaTest: Can't open new session - status = 0x%x\n", status);
+		return -1;
+	}
+
+	return (int)sid;
+}
+
+void close_session(int sid)
+{
+	MV_STATUS status;
+
+	status = mvCesaIfSessionClose(sid);
+	if (status != MV_OK)
+		mvOsPrintf("CesaTest: Can't close session %d - status = 0x%x\n", sid, status);
+
+}
+
+MV_STATUS testOpen(int idx)
+{
+	MV_CESA_OPEN_SESSION os;
+	int sid, i, testIdx;
+	MV_CESA_TEST_SESSION *pTestSession;
+	MV_U16 digestSize = 0;
+
+	pTestSession = getTestSessionDb(idx, &testIdx);
+	if (pTestSession == NULL) {
+		mvOsPrintf("Test %d is not exist\n", idx);
+		return MV_BAD_PARAM;
+	}
+	pTestSession = &pTestSession[testIdx];
+
+	if (pTestSession->sid != -1) {
+		mvOsPrintf("Session for test %d already created: sid=%d\n", idx, pTestSession->sid);
+		return MV_OK;
+	}
+
+	os.cryptoAlgorithm = pTestSession->cryptoAlgorithm;
+	os.macMode = pTestSession->macAlgorithm;
+	switch (os.macMode) {
+	case MV_CESA_MAC_MD5:
+	case MV_CESA_MAC_HMAC_MD5:
+		digestSize = MV_CESA_MD5_DIGEST_SIZE;
+		break;
+
+	case MV_CESA_MAC_SHA1:
+	case MV_CESA_MAC_HMAC_SHA1:
+		digestSize = MV_CESA_SHA1_DIGEST_SIZE;
+		break;
+
+	case MV_CESA_MAC_SHA2:
+	case MV_CESA_MAC_HMAC_SHA2:
+		digestSize = MV_CESA_SHA2_DIGEST_SIZE;
+		break;
+
+	case MV_CESA_MAC_NULL:
+		digestSize = 0;
+	}
+	os.cryptoMode = pTestSession->cryptoMode;
+	os.direction = pTestSession->direction;
+	os.operation = pTestSession->operation;
+
+	for (i = 0; i < pTestSession->cryptoKeySize; i++)
+		os.cryptoKey[i] = pTestSession->pCryptoKey[i];
+
+	os.cryptoKeyLength = pTestSession->cryptoKeySize;
+
+	for (i = 0; i < pTestSession->macKeySize; i++)
+		os.macKey[i] = pTestSession->pMacKey[i];
+
+	os.macKeyLength = pTestSession->macKeySize;
+	os.digestSize = digestSize;
+
+	sid = open_session(&os);
+	if (sid == -1) {
+		mvOsPrintf("Can't open session for test %d: rc=0x%x\n", idx, cesaResult.retCode);
+		return cesaResult.retCode;
+	}
+	CESA_TEST_DEBUG_PRINT(("Opened session: sid = %d\n", sid));
+	pTestSession->sid = sid;
+	return MV_OK;
+}
+
+MV_STATUS testClose(int idx)
+{
+	int testIdx;
+	MV_CESA_TEST_SESSION *pTestSession;
+
+	pTestSession = getTestSessionDb(idx, &testIdx);
+	if (pTestSession == NULL) {
+		mvOsPrintf("Test %d is not exist\n", idx);
+		return MV_BAD_PARAM;
+	}
+	pTestSession = &pTestSession[testIdx];
+
+	if (pTestSession->sid == -1) {
+		mvOsPrintf("Test session %d is not opened\n", idx);
+		return MV_NO_SUCH;
+	}
+
+	close_session(pTestSession->sid);
+	pTestSession->sid = -1;
+
+	return MV_OK;
+}
+
+MV_STATUS testCmd(int sid, int iter, MV_CESA_COMMAND *pCmd,
+		  MV_CESA_TEST_SESSION *pTestSession, MV_U8 *pIV, int ivSize)
+{
+	int cmdReqId = 0;
+	int i;
+	MV_STATUS rc = MV_OK;
+	char ivZeroHex[] = "0000";
+	MV_U8 chan = 0;
+
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	if (pCmd == NULL) {
+		mvOsPrintf("testCmd failed: pCmd=NULL\n");
+		return MV_BAD_PARAM;
+	}
+	pCmd->sessionId = sid;
+
+	cesaCryptoError = 0;
+	cesaReqIdError = 0;
+	cesaError = 0;
+	cesaTestIsrMissCount = 0;
+	cesaIsReady = MV_FALSE;
+	cesaIteration = iter;
+
+	if (cesaInputHexStr == NULL)
+		cesaInputHexStr = cesaPlainHexEbc;
+
+	for (i = 0; i < CESA_DEF_REQ_SIZE; i++) {
+		pCmd->pSrc = (MV_CESA_MBUF *) (cesaCmdRing[i].pSrc);
+		if (pIV != NULL) {
+			/* If IV from SA - set IV in Source buffer to zeros */
+			cesaSetMbuf(pCmd->pSrc, ivZeroHex, 0, pCmd->cryptoOffset);
+			cesaSetMbuf(pCmd->pSrc, cesaInputHexStr, pCmd->cryptoOffset,
+				    (cesaReqSize - pCmd->cryptoOffset));
+		} else {
+			cesaSetMbuf(pCmd->pSrc, cesaInputHexStr, 0, cesaReqSize);
+		}
+		pCmd->pDst = (MV_CESA_MBUF *) (cesaCmdRing[i].pDst);
+		cesaSetMbuf(pCmd->pDst, cesaNullPlainHexText, 0, cesaReqSize);
+
+		memcpy(&cesaCmdRing[i], pCmd, sizeof(*pCmd));
+	}
+
+	if (cesaCheckMode == CESA_SW_SHOW_CHECK_MODE) {
+		MV_U8 pDigest[MV_CESA_MAX_DIGEST_SIZE];
+
+		if (pTestSession->macAlgorithm == MV_CESA_MAC_MD5) {
+			mvMD5(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, pDigest);
+			mvOsPrintf("SW HASH_MD5: reqSize=%d, macLength=%d\n", cesaReqSize, pCmd->macLength);
+			mvDebugMemDump(pDigest, MV_CESA_MD5_DIGEST_SIZE, 1);
+			return MV_OK;
+		}
+		if (pTestSession->macAlgorithm == MV_CESA_MAC_SHA1) {
+			mvSHA1(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, pDigest);
+			mvOsPrintf("SW HASH_SHA1: reqSize=%d, macLength=%d\n", cesaReqSize, pCmd->macLength);
+			mvDebugMemDump(pDigest, MV_CESA_SHA1_DIGEST_SIZE, 1);
+			return MV_OK;
+		}
+		if (pTestSession->macAlgorithm == MV_CESA_MAC_SHA2) {
+			mvSHA256(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, pDigest);
+			mvOsPrintf("SW HASH_SHA2: reqSize=%d, macLength=%d\n", cesaReqSize, pCmd->macLength);
+			mvDebugMemDump(pDigest, MV_CESA_SHA2_DIGEST_SIZE, 1);
+			return MV_OK;
+		}
+	}
+#ifdef MV_LINUX
+	do_gettimeofday(&tv);
+	cesaBeginTicks = ((tv.tv_sec * 1000000) + tv.tv_usec);
+#else
+	cesaBeginTicks = CESA_TEST_TICK_GET();
+#endif
+	CESA_TEST_DEBUG_CODE(memset(cesaTestTrace, 0, sizeof(cesaTestTrace)); cesaTestTraceIdx = 0;);
+
+	if (cesaCheckMode == CESA_SW_NULL_CHECK_MODE) {
+		MV_U8 pDigest[MV_CESA_MAX_DIGEST_SIZE];
+
+		for (i = 0; i < iter; i++) {
+
+			if (pTestSession->macAlgorithm == MV_CESA_MAC_MD5)
+				mvMD5(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, (unsigned char *)pDigest);
+
+			if (pTestSession->macAlgorithm == MV_CESA_MAC_SHA1)
+				mvSHA1(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, (MV_U8 *) pDigest);
+
+			if (pTestSession->macAlgorithm == MV_CESA_MAC_SHA2)
+				mvSHA256(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, (MV_U8 *) pDigest);
+		}
+#ifdef MV_LINUX
+		do_gettimeofday(&tv);
+		cesaEndTicks = ((tv.tv_sec * 1000000) + tv.tv_usec);
+#else
+		cesaEndTicks = CESA_TEST_TICK_GET();
+#endif
+		cesaRate = getRate(&cesaRateAfterDot);
+		cesaIsReady = MV_TRUE;
+
+		return MV_OK;
+	}
+
+	/*cesaTestIsrCount = 0; */
+	/*mvCesaDebugStatsClear(); */
+
+#ifndef MV_NETBSD
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++)
+		MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+#endif
+
+	for (i = 0; i < iter; i++) {
+		unsigned long flags;
+
+		pCmd = &cesaCmdRing[cmdReqId];
+		pCmd->pReqPrv = (void *)cmdReqId;
+
+		CESA_TEST_LOCK(flags);
+
+		pCmd->split = MV_CESA_SPLIT_NONE;
+
+		rc = mvCesaIfAction(pCmd);
+		if (rc == MV_NO_RESOURCE)
+			cesaTestFull = 1;
+
+		CESA_TEST_UNLOCK(flags);
+
+		if (rc == MV_NO_RESOURCE) {
+			CESA_TEST_LOCK(flags);
+			CESA_TEST_WAIT((cesaTestFull == 0), 100);
+			CESA_TEST_UNLOCK(flags);
+			if (cesaTestFull == 1) {
+				mvOsPrintf("CESA Test timeout: i=%d, iter=%d, cesaTestFull=%d\n",
+					   i, iter, cesaTestFull);
+				cesaTestFull = 0;
+				return MV_TIMEOUT;
+			}
+
+			CESA_TEST_LOCK(flags);
+
+			rc = mvCesaIfAction(pCmd);
+
+			CESA_TEST_UNLOCK(flags);
+		}
+		if ((rc != MV_OK) && (rc != MV_NO_MORE)) {
+			mvOsPrintf("mvCesaIfAction failed: rc=%d\n", rc);
+			return rc;
+		}
+
+		cmdReqId++;
+		if (cmdReqId >= CESA_DEF_REQ_SIZE)
+			cmdReqId = 0;
+
+#ifdef MV_LINUX
+		/* Reschedule each 16 requests */
+		if ((i & 0xF) == 0)
+			schedule();
+#endif
+	}
+	return MV_OK;
+}
+
+extern MV_STATUS mvSysCesaInit(int numOfSession, int queueDepth, void *osHandle);
+
+void cesaTestStart(int bufNum, int bufSize)
+{
+	int i, j, idx;
+	MV_CESA_MBUF *pMbufSrc, *pMbufDst;
+	MV_BUF_INFO *pFragsSrc, *pFragsDst;
+	char *pBuf;
+#ifndef MV_NETBSD
+	int numOfSessions, queueDepth;
+	MV_STATUS status;
+#endif
+	MV_U8 chan = 0;
+	char irqStr[12];
+
+	cesaCmdRing = mvOsMalloc(sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE);
+	if (cesaCmdRing == NULL) {
+		mvOsPrintf("testStart: Can't allocate %d bytes of memory\n",
+			   (int)(sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE));
+		return;
+	}
+	memset(cesaCmdRing, 0, sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE);
+
+	if (bufNum == 0)
+		bufNum = CESA_DEF_BUF_NUM;
+
+	if (bufSize == 0)
+		bufSize = CESA_DEF_BUF_SIZE;
+
+	cesaBufNum = bufNum;
+	cesaBufSize = bufSize;
+	mvOsPrintf("CESA test started: bufNum = %d, bufSize = %d\n", bufNum, bufSize);
+
+	cesaHexBuffer = mvOsMalloc(2 * bufNum * bufSize);
+	if (cesaHexBuffer == NULL) {
+		mvOsPrintf("testStart: Can't malloc %d bytes for cesaHexBuffer.\n", 2 * bufNum * bufSize);
+		return;
+	}
+	memset(cesaHexBuffer, 0, (2 * bufNum * bufSize));
+
+	cesaBinBuffer = mvOsMalloc(bufNum * bufSize);
+	if (cesaBinBuffer == NULL) {
+		mvOsPrintf("testStart: Can't malloc %d bytes for cesaBinBuffer\n", bufNum * bufSize);
+		return;
+	}
+	memset(cesaBinBuffer, 0, (bufNum * bufSize));
+
+	cesaExpBinBuffer = mvOsMalloc(bufNum * bufSize);
+	if (cesaExpBinBuffer == NULL) {
+		mvOsPrintf("testStart: Can't malloc %d bytes for cesaExpBinBuffer\n", bufNum * bufSize);
+		return;
+	}
+	memset(cesaExpBinBuffer, 0, (bufNum * bufSize));
+
+	CESA_TEST_WAIT_INIT();
+
+	pMbufSrc = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	pFragsSrc = mvOsMalloc(sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	pMbufDst = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	pFragsDst = mvOsMalloc(sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	if ((pMbufSrc == NULL) || (pFragsSrc == NULL) || (pMbufDst == NULL) || (pFragsDst == NULL)) {
+		mvOsPrintf("testStart: Can't malloc Src and Dst pMbuf and pFrags structures.\n");
+		/* !!!! Dima cesaTestCleanup(); */
+		return;
+	}
+
+	memset(pMbufSrc, 0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	memset(pFragsSrc, 0, sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	memset(pMbufDst, 0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE);
+	memset(pFragsDst, 0, sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE);
+
+	mvOsPrintf("Cesa Test Start: pMbufSrc=%p, pFragsSrc=%p, pMbufDst=%p, pFragsDst=%p\n",
+		   pMbufSrc, pFragsSrc, pMbufDst, pFragsDst);
+
+	idx = 0;
+	for (i = 0; i < CESA_DEF_REQ_SIZE; i++) {
+		pBuf = mvOsIoCachedMalloc(cesaTestOSHandle, bufSize * bufNum * 2,
+					  &cesaReqBufs[i].bufPhysAddr, &cesaReqBufs[i].memHandle);
+		if (pBuf == NULL) {
+			mvOsPrintf("testStart: Can't malloc %d bytes for pBuf\n", bufSize * bufNum * 2);
+			return;
+		}
+
+		memset(pBuf, 0, bufSize * bufNum * 2);
+		mvOsCacheFlush(cesaTestOSHandle, pBuf, bufSize * bufNum * 2);
+		if (pBuf == NULL) {
+			mvOsPrintf("cesaTestStart: Can't allocate %d bytes for req_%d buffers\n",
+				   bufSize * bufNum * 2, i);
+			return;
+		}
+
+		cesaReqBufs[i].bufVirtPtr = (MV_U8 *) pBuf;
+		cesaReqBufs[i].bufSize = bufSize * bufNum * 2;
+
+		cesaCmdRing[i].pSrc = &pMbufSrc[i];
+		cesaCmdRing[i].pSrc->pFrags = &pFragsSrc[idx];
+		cesaCmdRing[i].pSrc->numFrags = bufNum;
+		cesaCmdRing[i].pSrc->mbufSize = 0;
+
+		cesaCmdRing[i].pDst = &pMbufDst[i];
+		cesaCmdRing[i].pDst->pFrags = &pFragsDst[idx];
+		cesaCmdRing[i].pDst->numFrags = bufNum;
+		cesaCmdRing[i].pDst->mbufSize = 0;
+
+		for (j = 0; j < bufNum; j++) {
+			cesaCmdRing[i].pSrc->pFrags[j].bufVirtPtr = (MV_U8 *) pBuf;
+			cesaCmdRing[i].pSrc->pFrags[j].bufSize = bufSize;
+			pBuf += bufSize;
+			cesaCmdRing[i].pDst->pFrags[j].bufVirtPtr = (MV_U8 *) pBuf;
+			cesaCmdRing[i].pDst->pFrags[j].bufSize = bufSize;
+			pBuf += bufSize;
+		}
+		idx += bufNum;
+	}
+
+#ifndef MV_NETBSD
+	numOfSessions = CESA_DEF_SESSION_NUM;
+	queueDepth = CESA_DEF_REQ_SIZE;
+
+	status = mvSysCesaInit(numOfSessions, queueDepth, NULL);
+	if (status != MV_OK) {
+		mvOsPrintf("mvCesaInit is Failed: status = 0x%x\n", status);
+		/* !!!! Dima cesaTestCleanup(); */
+		return;
+	}
+#endif /* !MV_NETBSD */
+
+	/* Prepare data for tests */
+	for (i = 0; i < 50; i++)
+		strcat((char *)cesaDataHexStr3, "dd");
+
+	strcpy((char *)cesaDataAndMd5digest3, cesaDataHexStr3);
+	strcpy((char *)cesaDataAndSha1digest3, cesaDataHexStr3);
+
+	/* Digest must be 8 byte aligned */
+	for (; i < 56; i++) {
+		strcat((char *)cesaDataAndMd5digest3, "00");
+		strcat((char *)cesaDataAndSha1digest3, "00");
+	}
+	strcat((char *)cesaDataAndMd5digest3, cesaHmacMd5digestHex3);
+	strcat((char *)cesaDataAndSha1digest3, cesaHmacSha1digestHex3);
+
+	for (chan = 0; chan < MV_CESA_CHANNELS; chan++) {
+#ifndef MV_NETBSD
+		MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG(chan), 0);
+		MV_REG_WRITE(MV_CESA_ISR_MASK_REG(chan), MV_CESA_CAUSE_ACC_DMA_MASK);
+#endif
+
+#ifdef MV_VXWORKS
+	{
+		MV_STATUS status;
+
+		status = intConnect((VOIDFUNCPTR *) INT_LVL_CESA, cesaTestReadyIsr, (int)NULL);
+		if (status != OK) {
+			mvOsPrintf("CESA: Can't connect CESA (%d) interrupt, status=0x%x \n", INT_LVL_CESA, status);
+			/* !!!! Dima cesaTestCleanup(); */
+			return;
+		}
+		cesaSemId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
+		if (cesaSemId == NULL) {
+			mvOsPrintf("cesaTestStart: Can't create semaphore\n");
+			return;
+		}
+		intEnable(INT_LVL_CESA);
+	}
+#endif /* MV_VXWORKS */
+
+#if !defined(MV_NETBSD) && defined(__KERNEL__)
+		memset(irqStr, '\0', sizeof(irqStr));
+		sprintf(irqStr, "cesa_test%d", chan);
+		if (request_irq(CESA_IRQ(chan), cesaTestReadyIsr, (IRQF_DISABLED), "cesa_test", NULL)) {
+			mvOsPrintf("cannot assign irq\n");
+			/* !!!! Dima cesaTestCleanup(); */
+			return;
+		}
+	}
+	spin_lock_init(&cesaLock);
+#endif
+}
+
+MV_STATUS testRun(int idx, int caseIdx, int iter, int reqSize, int checkMode)
+{
+	int testIdx, count, sid, digestSize;
+	int blockSize;
+	MV_CESA_TEST_SESSION *pTestSession;
+	MV_CESA_COMMAND cmd;
+	MV_STATUS status;
+	MV_U8 chan;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	pTestSession = getTestSessionDb(idx, &testIdx);
+	if (pTestSession == NULL) {
+		mvOsPrintf("Test %d is not exist\n", idx);
+		return MV_BAD_PARAM;
+	}
+	pTestSession = &pTestSession[testIdx];
+
+	sid = pTestSession->sid;
+	if (sid == -1) {
+		mvOsPrintf("Test %d is not opened\n", idx);
+		return MV_BAD_STATE;
+	}
+	switch (pTestSession->cryptoAlgorithm) {
+	case MV_CESA_CRYPTO_DES:
+	case MV_CESA_CRYPTO_3DES:
+		blockSize = MV_CESA_DES_BLOCK_SIZE;
+		break;
+
+	case MV_CESA_CRYPTO_AES:
+		blockSize = MV_CESA_AES_BLOCK_SIZE;
+		break;
+
+	case MV_CESA_CRYPTO_NULL:
+		blockSize = 0;
+		break;
+
+	default:
+		mvOsPrintf("cesaTestRun: Bad CryptoAlgorithm=%d\n", pTestSession->cryptoAlgorithm);
+		return MV_BAD_PARAM;
+	}
+	switch (pTestSession->macAlgorithm) {
+	case MV_CESA_MAC_MD5:
+	case MV_CESA_MAC_HMAC_MD5:
+		digestSize = MV_CESA_MD5_DIGEST_SIZE;
+		break;
+
+	case MV_CESA_MAC_SHA1:
+	case MV_CESA_MAC_HMAC_SHA1:
+		digestSize = MV_CESA_SHA1_DIGEST_SIZE;
+		break;
+
+	case MV_CESA_MAC_SHA2:
+	case MV_CESA_MAC_HMAC_SHA2:
+		digestSize = MV_CESA_SHA2_DIGEST_SIZE;
+		break;
+
+	default:
+		digestSize = 0;
+	}
+
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	if (pTestSession->direction == MV_CESA_DIR_ENCODE) {
+		cesaOutputHexStr = cesaTestCases[caseIdx].cipherHexStr;
+		cesaInputHexStr = cesaTestCases[caseIdx].plainHexStr;
+	} else {
+		cesaOutputHexStr = cesaTestCases[caseIdx].plainHexStr;
+		cesaInputHexStr = cesaTestCases[caseIdx].cipherHexStr;
+	}
+
+	cmd.sessionId = sid;
+	if (checkMode == CESA_FAST_CHECK_MODE) {
+		cmd.cryptoLength = cesaTestCases[caseIdx].cryptoLength;
+		cmd.macLength = cesaTestCases[caseIdx].macLength;
+	} else {
+		cmd.cryptoLength = reqSize;
+		cmd.macLength = reqSize;
+	}
+	cesaRateSize = cmd.cryptoLength;
+	cesaReqSize = cmd.cryptoLength;
+	cmd.cryptoOffset = 0;
+	if (pTestSession->operation != MV_CESA_MAC_ONLY) {
+		if ((pTestSession->cryptoMode == MV_CESA_CRYPTO_CBC) ||
+		    (pTestSession->cryptoMode == MV_CESA_CRYPTO_CTR)) {
+			cmd.ivOffset = 0;
+			cmd.cryptoOffset = blockSize;
+			if (cesaTestCases[caseIdx].pCryptoIV == NULL) {
+				cmd.ivFromUser = 1;
+			} else {
+				cmd.ivFromUser = 0;
+				for (chan = 0; chan < MV_CESA_CHANNELS; chan++)
+					mvCesaCryptoIvSet(chan, cesaTestCases[caseIdx].pCryptoIV, blockSize);
+			}
+			cesaReqSize = cmd.cryptoOffset + cmd.cryptoLength;
+		}
+	}
+
+/*
+	mvOsPrintf("ivFromUser=%d, cryptoLength=%d, cesaReqSize=%d, cryptoOffset=%d\n",
+				cmd.ivFromUser, cmd.cryptoLength, cesaReqSize, cmd.cryptoOffset);
+*/
+	if (pTestSession->operation != MV_CESA_CRYPTO_ONLY) {
+		cmd.macOffset = cmd.cryptoOffset;
+
+		if (cesaTestCases[caseIdx].digestOffset == -1) {
+			cmd.digestOffset = cmd.macOffset + cmd.macLength;
+			cmd.digestOffset = MV_ALIGN_UP(cmd.digestOffset, 8);
+		} else {
+			cmd.digestOffset = cesaTestCases[caseIdx].digestOffset;
+		}
+		if ((cmd.digestOffset + digestSize) > cesaReqSize)
+			cesaReqSize = cmd.digestOffset + digestSize;
+	}
+
+	cesaCheckMode = checkMode;
+
+	if (checkMode == CESA_NULL_CHECK_MODE) {
+		cesaCheckSize = 0;
+		cesaCheckOffset = 0;
+	} else {
+		if (pTestSession->operation == MV_CESA_CRYPTO_ONLY) {
+			cesaCheckOffset = 0;
+			cesaCheckSize = cmd.cryptoLength;
+		} else {
+			cesaCheckSize = digestSize;
+			cesaCheckOffset = cmd.digestOffset;
+		}
+	}
+/*
+	mvOsPrintf("reqSize=%d, checkSize=%d, checkOffset=%d, checkMode=%d\n",
+			cesaReqSize, cesaCheckSize, cesaCheckOffset, cesaCheckMode);
+
+	mvOsPrintf("blockSize=%d, ivOffset=%d, ivFromUser=%d, crOffset=%d, crLength=%d\n",
+			blockSize, cmd.ivOffset, cmd.ivFromUser,
+			cmd.cryptoOffset, cmd.cryptoLength);
+
+	mvOsPrintf("macOffset=%d, digestOffset=%d, macLength=%d\n",
+			cmd.macOffset, cmd.digestOffset, cmd.macLength);
+*/
+	status = testCmd(sid, iter, &cmd, pTestSession, cesaTestCases[caseIdx].pCryptoIV, blockSize);
+
+	if (status != MV_OK)
+		return status;
+
+	/* Wait when all callbacks is received */
+	count = 0;
+	while (cesaIsReady == MV_FALSE) {
+		mvOsSleep(10);
+		count++;
+		if (count > 100) {
+			mvOsPrintf("testRun: Timeout occured\n");
+			return MV_TIMEOUT;
+		}
+	}
+
+	return MV_OK;
+}
+
+void cesaTestStop(void)
+{
+	MV_CESA_MBUF *pMbufSrc, *pMbufDst;
+	MV_BUF_INFO *pFragsSrc, *pFragsDst;
+	int i;
+
+	/* Release all allocated memories */
+	pMbufSrc = (MV_CESA_MBUF *) (cesaCmdRing[0].pSrc);
+	pFragsSrc = cesaCmdRing[0].pSrc->pFrags;
+
+	pMbufDst = (MV_CESA_MBUF *) (cesaCmdRing[0].pDst);
+	pFragsDst = cesaCmdRing[0].pDst->pFrags;
+
+	mvOsFree(pMbufSrc);
+	mvOsFree(pMbufDst);
+	mvOsFree(pFragsSrc);
+	mvOsFree(pFragsDst);
+
+	for (i = 0; i < CESA_DEF_REQ_SIZE; i++) {
+		mvOsIoCachedFree(cesaTestOSHandle, cesaReqBufs[i].bufSize,
+				 cesaReqBufs[i].bufPhysAddr, cesaReqBufs[i].bufVirtPtr, cesaReqBufs[i].memHandle);
+	}
+	cesaDataHexStr3[0] = '\0';
+
+	/* Free CESA HAL resources */
+	mvCesaIfFinish();
+}
+
+void desTest(int iter, int reqSize, int checkMode)
+{
+	int mode, i;
+	MV_STATUS status;
+
+	mode = checkMode;
+	if (checkMode == CESA_FULL_CHECK_MODE)
+		mode = CESA_FAST_CHECK_MODE;
+	i = iter;
+	if (mode != CESA_NULL_CHECK_MODE)
+		i = 1;
+
+	testOpen(0);
+	testOpen(1);
+	testOpen(2);
+	testOpen(3);
+
+/* DES / ECB mode / Encrypt only */
+	status = testRun(0, 1, iter, reqSize, checkMode);
+	printTestResults(0, status, checkMode);
+
+/* DES / ECB mode / Decrypt only */
+	status = testRun(1, 1, iter, reqSize, checkMode);
+	printTestResults(1, status, checkMode);
+
+/* DES / CBC mode / Encrypt only */
+	status = testRun(2, 2, i, reqSize, mode);
+	printTestResults(2, status, mode);
+
+/* DES / CBC mode / Decrypt only */
+	status = testRun(3, 2, iter, reqSize, mode);
+	printTestResults(3, status, mode);
+
+	testClose(0);
+	testClose(1);
+	testClose(2);
+	testClose(3);
+}
+
+void tripleDesTest(int iter, int reqSize, int checkMode)
+{
+	int mode, i;
+	MV_STATUS status;
+
+	mode = checkMode;
+	if (checkMode == CESA_FULL_CHECK_MODE)
+		mode = CESA_FAST_CHECK_MODE;
+	i = iter;
+	if (mode != CESA_NULL_CHECK_MODE)
+		i = 1;
+
+	testOpen(100);
+	testOpen(101);
+	testOpen(102);
+	testOpen(103);
+
+/* 3DES / ECB mode / Encrypt only */
+	status = testRun(100, 1, iter, reqSize, checkMode);
+	printTestResults(100, status, checkMode);
+
+/* 3DES / ECB mode / Decrypt only */
+	status = testRun(101, 1, iter, reqSize, checkMode);
+	printTestResults(101, status, checkMode);
+
+/* 3DES / CBC mode / Encrypt only */
+	status = testRun(102, 2, i, reqSize, mode);
+	printTestResults(102, status, mode);
+
+/* 3DES / CBC mode / Decrypt only */
+	status = testRun(103, 2, iter, reqSize, mode);
+	printTestResults(103, status, mode);
+
+	testClose(100);
+	testClose(101);
+	testClose(102);
+	testClose(103);
+}
+
+void aesTest(int iter, int reqSize, int checkMode)
+{
+	MV_STATUS status;
+	int mode, i;
+
+	mode = checkMode;
+	if (checkMode == CESA_FULL_CHECK_MODE)
+		mode = CESA_FAST_CHECK_MODE;
+
+	i = iter;
+	if (mode != CESA_NULL_CHECK_MODE)
+		i = 1;
+
+	testOpen(200);
+	testOpen(201);
+	testOpen(202);
+	testOpen(203);
+	testOpen(204);
+	testOpen(205);
+	testOpen(206);
+	testOpen(207);
+	testOpen(208);
+
+/* AES-128 Encode ECB mode */
+	status = testRun(200, 3, iter, reqSize, checkMode);
+	printTestResults(200, status, checkMode);
+
+/* AES-128 Decode ECB mode */
+	status = testRun(201, 3, iter, reqSize, checkMode);
+	printTestResults(201, status, checkMode);
+
+/* AES-128 Encode CBC mode (IV from SA) */
+	status = testRun(202, 10, i, reqSize, mode);
+	printTestResults(202, status, mode);
+
+/* AES-128 Encode CBC mode (IV from User) */
+	status = testRun(202, 24, i, reqSize, mode);
+	printTestResults(202, status, mode);
+
+/* AES-128 Decode CBC mode */
+	status = testRun(203, 24, iter, reqSize, mode);
+	printTestResults(203, status, checkMode);
+
+/* AES-192 Encode ECB mode */
+	status = testRun(204, 4, iter, reqSize, checkMode);
+	printTestResults(204, status, checkMode);
+
+/* AES-192 Decode ECB mode */
+	status = testRun(205, 4, iter, reqSize, checkMode);
+	printTestResults(205, status, checkMode);
+
+/* AES-256 Encode ECB mode */
+	status = testRun(206, 5, iter, reqSize, checkMode);
+	printTestResults(206, status, checkMode);
+
+/* AES-256 Decode ECB mode */
+	status = testRun(207, 5, iter, reqSize, checkMode);
+	printTestResults(207, status, checkMode);
+
+#if 0
+/* AES-128 Encode CTR mode */
+	status = testRun(208, 23, iter, reqSize, mode);
+	printTestResults(208, status, checkMode);
+#endif
+
+	testClose(200);
+	testClose(201);
+	testClose(202);
+	testClose(203);
+	testClose(204);
+	testClose(205);
+	testClose(206);
+	testClose(207);
+	testClose(208);
+}
+
+void mdTest(int iter, int reqSize, int checkMode)
+{
+	int mode;
+	MV_STATUS status;
+
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	mode = checkMode;
+	if (checkMode == CESA_FULL_CHECK_MODE)
+		mode = CESA_FAST_CHECK_MODE;
+
+	testOpen(300);
+	testOpen(301);
+	testOpen(302);
+	testOpen(303);
+	testOpen(305);
+
+/* HMAC-MD5 Generate signature test */
+	status = testRun(300, 6, iter, reqSize, mode);
+	printTestResults(300, status, checkMode);
+
+/* HMAC-MD5 Verify Signature test */
+	status = testRun(301, 7, iter, reqSize, mode);
+	printTestResults(301, status, checkMode);
+
+/* HMAC-MD5 Generate signature test */
+	status = testRun(302, 8, iter, reqSize, mode);
+	printTestResults(302, status, checkMode);
+
+/* HMAC-MD5 Verify Signature test */
+	status = testRun(303, 9, iter, reqSize, mode);
+	printTestResults(303, status, checkMode);
+
+/* HASH-MD5 Generate signature test */
+	status = testRun(305, 15, iter, reqSize, mode);
+	printTestResults(305, status, checkMode);
+
+	testClose(300);
+	testClose(301);
+	testClose(302);
+	testClose(303);
+	testClose(305);
+}
+
+void sha1Test(int iter, int reqSize, int checkMode)
+{
+	int mode;
+	MV_STATUS status;
+
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	mode = checkMode;
+	if (checkMode == CESA_FULL_CHECK_MODE)
+		mode = CESA_FAST_CHECK_MODE;
+
+	testOpen(400);
+	testOpen(401);
+	testOpen(402);
+	testOpen(403);
+	testOpen(405);
+
+/* HMAC-SHA1 Generate signature test */
+	status = testRun(400, 11, iter, reqSize, mode);
+	printTestResults(400, status, checkMode);
+
+/* HMAC-SHA1 Verify Signature test */
+	status = testRun(401, 12, iter, reqSize, mode);
+	printTestResults(401, status, checkMode);
+
+/* HMAC-SHA1 Generate signature test */
+	status = testRun(402, 13, iter, reqSize, mode);
+	printTestResults(402, status, checkMode);
+
+/* HMAC-SHA1 Verify Signature test */
+	status = testRun(403, 14, iter, reqSize, mode);
+	printTestResults(403, status, checkMode);
+
+/* HMAC-SHA1 Generate signature test */
+	status = testRun(405, 16, iter, reqSize, mode);
+	printTestResults(405, status, checkMode);
+
+	testClose(400);
+	testClose(401);
+	testClose(402);
+	testClose(403);
+	testClose(405);
+}
+
+void sha2Test(int iter, int reqSize, int checkMode)
+{
+	int mode;
+	MV_STATUS status;
+
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	mode = checkMode;
+	if (checkMode == CESA_FULL_CHECK_MODE)
+		mode = CESA_FAST_CHECK_MODE;
+
+	testOpen(500);
+	testOpen(501);
+	testOpen(502);
+	testOpen(503);
+
+/* HMAC-SHA2 Generate signature test */
+	status = testRun(500, 28, iter, reqSize, mode);
+	printTestResults(500, status, checkMode);
+/* HMAC-SHA2 Verify signature test */
+	status = testRun(501, 29, iter, reqSize, mode);
+	printTestResults(501, status, checkMode);
+/* HMAC-SHA2 Generate signature test */
+	status = testRun(502, 30, iter, reqSize, mode);
+	printTestResults(502, status, checkMode);
+/* HMAC-SHA2 Verify signature test */
+	status = testRun(503, 31, iter, reqSize, mode);
+	printTestResults(503, status, checkMode);
+
+	testClose(500);
+	testClose(501);
+	testClose(502);
+	testClose(503);
+}
+
+void combiTest(int iter, int reqSize, int checkMode)
+{
+	MV_STATUS status;
+	int mode, i;
+
+	mode = checkMode;
+	if (checkMode == CESA_FULL_CHECK_MODE)
+		mode = CESA_FAST_CHECK_MODE;
+
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	i = iter;
+	if (mode != CESA_NULL_CHECK_MODE)
+		i = 1;
+
+	testOpen(600);
+	testOpen(601);
+	testOpen(602);
+	testOpen(603);
+	testOpen(604);
+	testOpen(605);
+	testOpen(606);
+	testOpen(607);
+	testOpen(609);
+
+/* DES ECB + MD5 encode test */
+	status = testRun(600, 17, iter, reqSize, mode);
+	printTestResults(600, status, mode);
+
+/* DES ECB + SHA1 encode test */
+	status = testRun(601, 18, iter, reqSize, mode);
+	printTestResults(601, status, mode);
+
+/* 3DES ECB + MD5 encode test */
+	status = testRun(602, 17, iter, reqSize, mode);
+	printTestResults(602, status, mode);
+
+/* 3DES ECB + SHA1 encode test */
+	status = testRun(603, 18, iter, reqSize, mode);
+	printTestResults(603, status, mode);
+
+/* 3DES CBC + MD5 encode test */
+	status = testRun(604, 19, i, reqSize, mode);
+	printTestResults(604, status, mode);
+
+/* 3DES CBC + SHA1 encode test */
+	status = testRun(605, 20, i, reqSize, mode);
+	printTestResults(605, status, mode);
+
+/* AES-128 CBC + MD5 encode test */
+	status = testRun(606, 21, i, reqSize, mode);
+	printTestResults(606, status, mode);
+
+/* AES-128 CBC + SHA1 encode test */
+	status = testRun(607, 22, i, reqSize, mode);
+	printTestResults(607, status, mode);
+
+/* AES-128 CBC + SHA2 encode test */
+	status = testRun(609, 32, i, reqSize, mode);
+	printTestResults(609, status, mode);
+
+	testClose(600);
+	testClose(601);
+	testClose(602);
+	testClose(603);
+	testClose(604);
+	testClose(605);
+	testClose(606);
+	testClose(607);
+	testClose(609);
+}
+
+void cesaOneTest(int testIdx, int caseIdx, int iter, int reqSize, int checkMode)
+{
+	MV_STATUS status;
+
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	mvOsPrintf("test=%d, case=%d, size=%d, iter=%d\n", testIdx, caseIdx, reqSize, iter);
+
+	status = testOpen(testIdx);
+
+	status = testRun(testIdx, caseIdx, iter, reqSize, checkMode);
+	printTestResults(testIdx, status, checkMode);
+	status = testClose(testIdx);
+
+}
+
+void cesaTest(int iter, int reqSize, int checkMode)
+{
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	mvOsPrintf("%d iteration\n", iter);
+	mvOsPrintf("%d size\n\n", reqSize);
+
+/* DES tests */
+	desTest(iter, reqSize, checkMode);
+
+/* 3DES tests */
+	tripleDesTest(iter, reqSize, checkMode);
+
+/* AES tests */
+	aesTest(iter, reqSize, checkMode);
+
+/* MD5 tests */
+	mdTest(iter, reqSize, checkMode);
+
+/* SHA-1 tests */
+	sha1Test(iter, reqSize, checkMode);
+
+/* SHA-2 tests */
+	sha2Test(iter, reqSize, checkMode);
+}
+
+void multiSizeTest(int idx, int iter, int checkMode, char *inputData)
+{
+	MV_STATUS status;
+	int i;
+	MV_CESA_SIZE_TEST *pMultiTest;
+
+	if (testOpen(idx) != MV_OK)
+		return;
+
+	if (iter == 0)
+		iter = CESA_DEF_ITER_NUM;
+
+	if (checkMode == CESA_SHOW_CHECK_MODE)
+		iter = 1;
+	else
+		checkMode = CESA_FULL_CHECK_MODE;
+
+	cesaTestCases[0].plainHexStr = inputData;
+	cesaTestCases[0].pCryptoIV = NULL;
+
+	switch (idx) {
+	case 302:
+		pMultiTest = mdMultiSizeTest302;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = cesaDataHexStr3;
+		break;
+
+	case 304:
+		pMultiTest = mdMultiSizeTest304;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 305:
+		pMultiTest = mdMultiSizeTest305;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 402:
+		pMultiTest = sha1MultiSizeTest402;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 404:
+		pMultiTest = sha1MultiSizeTest404;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 405:
+		pMultiTest = sha1MultiSizeTest405;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 602:
+		pMultiTest = tripleDesMdMultiSizeTest602;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 603:
+		pMultiTest = tripleDesShaMultiSizeTest603;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 604:
+		iter = 1;
+		pMultiTest = cbc3desMdMultiSizeTest604;
+		cesaTestCases[0].pCryptoIV = iv1;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 605:
+		iter = 1;
+		pMultiTest = cbc3desShaMultiSizeTest605;
+		cesaTestCases[0].pCryptoIV = iv1;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 606:
+		iter = 1;
+		pMultiTest = cbcAes128md5multiSizeTest606;
+		cesaTestCases[0].pCryptoIV = iv5;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	case 607:
+		iter = 1;
+		pMultiTest = cbcAes128sha1multiSizeTest607;
+		cesaTestCases[0].pCryptoIV = iv5;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+		break;
+
+	default:
+		iter = 1;
+		checkMode = CESA_SHOW_CHECK_MODE;
+		pMultiTest = mdMultiSizeTest302;
+		if (inputData == NULL)
+			cesaTestCases[0].plainHexStr = hashHexStr80;
+	}
+	i = 0;
+	while (pMultiTest[i].outputHexStr != NULL) {
+		cesaTestCases[0].cipherHexStr = (char *)pMultiTest[i].outputHexStr;
+		status = testRun(idx, 0, iter, pMultiTest[i].size, checkMode);
+		if (checkMode != CESA_SHOW_CHECK_MODE) {
+			cesaReqSize = pMultiTest[i].size;
+			printTestResults(idx, status, checkMode);
+		}
+		if (status != MV_OK)
+			break;
+		i++;
+	}
+	testClose(idx);
+/*
+    mvCesaDebugStatus();
+    cesaTestPrintStatus();
+*/
+}
+
+void open_session_test(int idx, int caseIdx, int iter)
+{
+	int reqIdError, cryptoError, openErrors, i;
+	int openErrDisp[100];
+	MV_STATUS status;
+
+	memset(openErrDisp, 0, sizeof(openErrDisp));
+	openErrors = 0;
+	reqIdError = 0;
+	cryptoError = 0;
+	for (i = 0; i < iter; i++) {
+		status = testOpen(idx);
+		if (status != MV_OK) {
+			openErrors++;
+			openErrDisp[status]++;
+		} else {
+			testRun(idx, caseIdx, 1, 0, CESA_FAST_CHECK_MODE);
+			if (cesaCryptoError > 0)
+				cryptoError++;
+			if (cesaReqIdError > 0)
+				reqIdError++;
+
+			testClose(idx);
+		}
+	}
+	if (cryptoError > 0)
+		mvOsPrintf("cryptoError : %d\n", cryptoError);
+	if (reqIdError > 0)
+		mvOsPrintf("reqIdError  : %d\n", reqIdError);
+
+	if (openErrors > 0) {
+		mvOsPrintf("Open Errors = %d\n", openErrors);
+		for (i = 0; i < 100; i++) {
+			if (openErrDisp[i] != 0)
+				mvOsPrintf("Error %d - occurs %d times\n", i, openErrDisp[i]);
+		}
+	}
+}
+
+void loopback_test(int idx, int iter, int size, char *pPlainData)
+{
+}
+
+#if defined(MV_VXWORKS)
+int testMode = 0;
+unsigned __TASKCONV cesaTask(void *args)
+{
+	int reqSize = cesaReqSize;
+
+	if (testMode == 0) {
+		cesaOneTest(cesaTestIdx, cesaCaseIdx, cesaIteration, reqSize, cesaCheckMode);
+	} else {
+		if (testMode == 1) {
+			cesaTest(cesaIteration, reqSize, cesaCheckMode);
+			combiTest(cesaIteration, reqSize, cesaCheckMode);
+		} else {
+			multiSizeTest(cesaIdx, cesaIteration, cesaCheckMode, NULL);
+		}
+	}
+	return 0;
+}
+
+void oneTest(int testIdx, int caseIdx, int iter, int reqSize, int checkMode)
+{
+	long rc;
+
+	cesaIteration = iter;
+	cesaReqSize = cesaRateSize = reqSize;
+	cesaCheckMode = checkMode;
+	testMode = 0;
+	cesaTestIdx = testIdx;
+	cesaCaseIdx = caseIdx;
+	rc = mvOsTaskCreate("CESA_T", 100, 4 * 1024, cesaTask, NULL, &cesaTaskId);
+	if (rc != MV_OK)
+		mvOsPrintf("hMW: Can't create CESA multiCmd test task, rc = %d\n", (int)rc);
+}
+
+void multiTest(int iter, int reqSize, int checkMode)
+{
+	long rc;
+
+	cesaIteration = iter;
+	cesaCheckMode = checkMode;
+	cesaReqSize = reqSize;
+	testMode = 1;
+	rc = mvOsTaskCreate("CESA_T", 100, 4 * 1024, cesaTask, NULL, &cesaTaskId);
+	if (rc != MV_OK)
+		mvOsPrintf("hMW: Can't create CESA multiCmd test task, rc = %d\n", (int)rc);
+}
+
+void sizeTest(int testIdx, int iter, int checkMode)
+{
+	long rc;
+
+	cesaIteration = iter;
+	cesaCheckMode = checkMode;
+	testMode = 2;
+	cesaIdx = testIdx;
+	rc = mvOsTaskCreate("CESA_T", 100, 4 * 1024, cesaTask, NULL, &cesaTaskId);
+	if (rc != MV_OK)
+		mvOsPrintf("hMW: Can't create CESA test task, rc = %d\n", (int)rc);
+}
+
+#endif /* MV_VXWORKS */
+
+extern void mvCesaDebugSA(short sid, int mode);
+void cesaTestPrintSession(int idx)
+{
+	int testIdx;
+	MV_CESA_TEST_SESSION *pTestSession;
+
+	pTestSession = getTestSessionDb(idx, &testIdx);
+	if (pTestSession == NULL) {
+		mvOsPrintf("Test %d is not exist\n", idx);
+		return;
+	}
+	pTestSession = &pTestSession[testIdx];
+
+	if (pTestSession->sid == -1) {
+		mvOsPrintf("Test session %d is not opened\n", idx);
+		return;
+	}
+
+	mvCesaDebugSA(pTestSession->sid, 1);
+}
+
+void cesaTestPrintStatus(void)
+{
+	mvOsPrintf("\n\t Cesa Test Status\n\n");
+
+	mvOsPrintf("isrCount=%d\n", cesaTestIsrCount);
+
+#ifdef CESA_TEST_DEBUG
+	{
+		int i, j;
+		j = cesaTestTraceIdx;
+		mvOsPrintf("No  Type  Cause   rCause   errCause   Res     Time     pReady    pProc    pEmpty\n");
+		for (i = 0; i < MV_CESA_TEST_TRACE_SIZE; i++) {
+			mvOsPrintf
+			    ("%02d.  %d   0x%04x  0x%04x   0x%04x   0x%02x   0x%02x   %02d   0x%06x  %p  %p  %p\n", j,
+			     cesaTestTrace[j].type, cesaTestTrace[j].cause, cesaTestTrace[j].realCause,
+			     cesaTestTrace[j].dmaErrCause, cesaTestTrace[j].resources, cesaTestTrace[j].timeStamp,
+			     cesaTestTrace[j].pReqReady, cesaTestTrace[j].pReqProcess, cesaTestTrace[j].pReqEmpty);
+			j++;
+			if (j == MV_CESA_TEST_TRACE_SIZE)
+				j = 0;
+		}
+	}
+#endif /* CESA_TEST_DEBUG */
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/cesa/mvCompVer.txt
new file mode 100755
index 0000000..5f39390
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.4
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvLru.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvLru.c
new file mode 100755
index 0000000..fe97761
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvLru.c
@@ -0,0 +1,150 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvLru.h"
+/* LRU Cache support */
+
+/* Init LRU cache database */
+MV_LRU_CACHE *mvLruCacheInit(int numOfEntries)
+{
+	int i;
+	MV_LRU_CACHE *pLruCache;
+
+	pLruCache = mvOsMalloc(sizeof(MV_LRU_CACHE));
+
+	if (pLruCache == NULL)
+		return NULL;
+
+	memset(pLruCache, 0, sizeof(MV_LRU_CACHE));
+
+	pLruCache->table = mvOsMalloc(numOfEntries * sizeof(MV_LRU_ENTRY));
+	if (pLruCache->table == NULL) {
+		mvOsFree(pLruCache);
+		return NULL;
+	}
+	memset(pLruCache->table, 0, numOfEntries * sizeof(MV_LRU_ENTRY));
+	pLruCache->tableSize = numOfEntries;
+
+	for (i = 0; i < numOfEntries; i++) {
+		pLruCache->table[i].next = i + 1;
+		pLruCache->table[i].prev = i - 1;
+	}
+	pLruCache->least = 0;
+	pLruCache->most = numOfEntries - 1;
+
+	return pLruCache;
+}
+
+void mvLruCacheFinish(MV_LRU_CACHE *pLruCache)
+{
+	mvOsFree(pLruCache->table);
+	mvOsFree(pLruCache);
+}
+
+/* Update LRU cache database after using cache Index */
+void mvLruCacheIdxUpdate(MV_LRU_CACHE *pLruHndl, int cacheIdx)
+{
+	int prev, next;
+
+	if (cacheIdx == pLruHndl->most)
+		return;
+
+	next = pLruHndl->table[cacheIdx].next;
+	if (cacheIdx == pLruHndl->least) {
+		pLruHndl->least = next;
+	} else {
+		prev = pLruHndl->table[cacheIdx].prev;
+
+		pLruHndl->table[next].prev = prev;
+		pLruHndl->table[prev].next = next;
+	}
+
+	pLruHndl->table[pLruHndl->most].next = cacheIdx;
+	pLruHndl->table[cacheIdx].prev = pLruHndl->most;
+	pLruHndl->most = cacheIdx;
+}
+
+/* Delete LRU cache entry */
+void mvLruCacheIdxDelete(MV_LRU_CACHE *pLruHndl, int cacheIdx)
+{
+	int prev, next;
+
+	if (cacheIdx == pLruHndl->least)
+		return;
+
+	prev = pLruHndl->table[cacheIdx].prev;
+	if (cacheIdx == pLruHndl->most) {
+		pLruHndl->most = prev;
+	} else {
+		next = pLruHndl->table[cacheIdx].next;
+
+		pLruHndl->table[next].prev = prev;
+		pLruHndl->table[prev].next = next;
+	}
+	pLruHndl->table[pLruHndl->least].prev = cacheIdx;
+	pLruHndl->table[cacheIdx].next = pLruHndl->least;
+	pLruHndl->least = cacheIdx;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvLru.h b/arch/arm/plat-feroceon/mv_hal/cesa/mvLru.h
new file mode 100755
index 0000000..15097d8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvLru.h
@@ -0,0 +1,113 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvLru.h - Header File for Least Recently Used Cache algorithm
+*
+* DESCRIPTION:
+*       This header file contains macros typedefs and function declaration for
+*       the Least Recently Used Cache algorithm.
+*
+*******************************************************************************/
+
+#ifndef __mvLru_h__
+#define __mvLru_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+	int next;
+	int prev;
+} MV_LRU_ENTRY;
+
+typedef struct {
+	int least;
+	int most;
+	MV_LRU_ENTRY *table;
+	int tableSize;
+} MV_LRU_CACHE;
+
+/* Find Cache index for replacement LRU */
+static INLINE int mvLruCacheIdxFind(MV_LRU_CACHE *pLruHndl)
+{
+	return pLruHndl->least;
+}
+/* Init LRU cache module */
+MV_LRU_CACHE *mvLruCacheInit(int numOfEntries);
+
+/* Finish LRU cache module */
+void mvLruCacheFinish(MV_LRU_CACHE *pLruHndl);
+
+/* Update LRU cache database after using cache Index */
+void mvLruCacheIdxUpdate(MV_LRU_CACHE *pLruHndl, int cacheIdx);
+
+/* Delete LRU cache entry */
+void mvLruCacheIdxDelete(MV_LRU_CACHE *pLruHndl, int cacheIdx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __mvLru_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvMD5.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvMD5.c
new file mode 100755
index 0000000..550a51b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvMD5.c
@@ -0,0 +1,339 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvMD5.h"
+
+static void mvMD5Transform(MV_U32 buf[4], MV_U32 const in[MV_MD5_MAC_LEN]);
+
+#ifdef MV_CPU_LE
+#define mvByteReverse(buf, len)	/* Nothing */
+#else
+static void mvByteReverse(unsigned char *buf, unsigned longs);
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void mvByteReverse(unsigned char *buf, unsigned longs)
+{
+	MV_U32 t;
+
+	do {
+		t = (MV_U32) ((unsigned)buf[3] << 8 | buf[2]) << 16 | ((unsigned)buf[1] << 8 | buf[0]);
+		*(MV_U32 *)buf = t;
+		buf += 4;
+	} while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void mvMD5Init(MV_MD5_CONTEXT *ctx)
+{
+	ctx->buf[0] = 0x67452301;
+	ctx->buf[1] = 0xefcdab89;
+	ctx->buf[2] = 0x98badcfe;
+	ctx->buf[3] = 0x10325476;
+
+	ctx->bits[0] = 0;
+	ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void mvMD5Update(MV_MD5_CONTEXT *ctx, unsigned char const *buf, unsigned len)
+{
+	MV_U32 t;
+
+	/* Update bitcount */
+
+	t = ctx->bits[0];
+	ctx->bits[0] = t + ((MV_U32)len << 3);
+	if (ctx->bits[0] < t)
+		ctx->bits[1]++;	/* Carry from low to high */
+	ctx->bits[1] += len >> 29;
+
+	t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+	/* Handle any leading odd-sized chunks */
+
+	if (t) {
+		unsigned char *p = (unsigned char *)ctx->in + t;
+
+		t = 64 - t;
+		if (len < t) {
+			memcpy(p, buf, len);
+			return;
+		}
+		memcpy(p, buf, t);
+		mvByteReverse(ctx->in, MV_MD5_MAC_LEN);
+		mvMD5Transform(ctx->buf, (MV_U32 *)ctx->in);
+		buf += t;
+		len -= t;
+	}
+	/* Process data in 64-byte chunks */
+
+	while (len >= 64) {
+		memcpy(ctx->in, buf, 64);
+		mvByteReverse(ctx->in, MV_MD5_MAC_LEN);
+		mvMD5Transform(ctx->buf, (MV_U32 *)ctx->in);
+		buf += 64;
+		len -= 64;
+	}
+
+	/* Handle any remaining bytes of data. */
+
+	memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void mvMD5Final(unsigned char digest[MV_MD5_MAC_LEN], MV_MD5_CONTEXT *ctx)
+{
+	unsigned count;
+	unsigned char *p;
+
+	/* Compute number of bytes mod 64 */
+	count = (ctx->bits[0] >> 3) & 0x3F;
+
+	/* Set the first char of padding to 0x80.  This is safe since there is
+	   always at least one byte free */
+	p = ctx->in + count;
+	*p++ = 0x80;
+
+	/* Bytes of padding needed to make 64 bytes */
+	count = 64 - 1 - count;
+
+	/* Pad out to 56 mod 64 */
+	if (count < 8) {
+		/* Two lots of padding:  Pad the first block to 64 bytes */
+		memset(p, 0, count);
+		mvByteReverse(ctx->in, MV_MD5_MAC_LEN);
+		mvMD5Transform(ctx->buf, (MV_U32 *)ctx->in);
+
+		/* Now fill the next block with 56 bytes */
+		memset(ctx->in, 0, 56);
+	} else {
+		/* Pad block to 56 bytes */
+		memset(p, 0, count - 8);
+	}
+	mvByteReverse(ctx->in, 14);
+
+	/* Append length in bits and transform */
+	((MV_U32 *) ctx->in)[14] = ctx->bits[0];
+	((MV_U32 *) ctx->in)[15] = ctx->bits[1];
+
+	mvMD5Transform(ctx->buf, (MV_U32 *)ctx->in);
+	mvByteReverse((unsigned char *)ctx->buf, 4);
+	memcpy(digest, ctx->buf, MV_MD5_MAC_LEN);
+	memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	(w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x)
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void mvMD5Transform(MV_U32 buf[4], MV_U32 const in[MV_MD5_MAC_LEN])
+{
+	register MV_U32 a, b, c, d;
+
+	a = buf[0];
+	b = buf[1];
+	c = buf[2];
+	d = buf[3];
+
+	MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+	MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+	MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+	MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+	MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+	MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+	MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+	MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+	MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+	MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+	MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+	MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+	MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+	MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+	MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+	MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+	MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+	MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+	MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+	MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+	MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+	MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+	MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+	MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+	MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+	MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+	MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+	MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+	MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+	MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+	MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+	MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+	MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+	MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+	MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+	MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+	MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+	MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+	MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+	MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+	buf[0] += a;
+	buf[1] += b;
+	buf[2] += c;
+	buf[3] += d;
+}
+
+void mvMD5(unsigned char const *buf, unsigned len, unsigned char *digest)
+{
+	MV_MD5_CONTEXT ctx;
+
+	mvMD5Init(&ctx);
+	mvMD5Update(&ctx, buf, len);
+	mvMD5Final(digest, &ctx);
+}
+
+void mvHmacMd5(unsigned char const *text, int text_len, unsigned char const *key, int key_len, unsigned char *digest)
+{
+	int i;
+	MV_MD5_CONTEXT ctx;
+	unsigned char k_ipad[64 + 1];	/* inner padding - key XORd with ipad */
+	unsigned char k_opad[64 + 1];	/* outer padding - key XORd with opad */
+
+	/* start out by storing key in pads */
+	memset(k_ipad, 0, 64);
+	memcpy(k_ipad, key, key_len);
+	memset(k_opad, 0, 64);
+	memcpy(k_opad, key, key_len);
+
+	/* XOR key with ipad and opad values */
+	for (i = 0; i < 64; i++) {
+		k_ipad[i] ^= 0x36;
+		k_opad[i] ^= 0x5c;
+	}
+
+	/* perform inner MD5 */
+	mvMD5Init(&ctx);	/* init ctx for 1st pass */
+	mvMD5Update(&ctx, k_ipad, 64);	/* start with inner pad */
+	mvMD5Update(&ctx, text, text_len);	/* then text of datagram */
+	mvMD5Final(digest, &ctx);	/* finish up 1st pass */
+
+	/* perform outer MD5 */
+	mvMD5Init(&ctx);	/* init ctx for 2nd pass */
+	mvMD5Update(&ctx, k_opad, 64);	/* start with outer pad */
+	mvMD5Update(&ctx, digest, 16);	/* then results of 1st hash */
+	mvMD5Final(digest, &ctx);	/* finish up 2nd pass */
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvMD5.h b/arch/arm/plat-feroceon/mv_hal/cesa/mvMD5.h
new file mode 100755
index 0000000..051fb57
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvMD5.h
@@ -0,0 +1,92 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __mvMD5_h__
+#define __mvMD5_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MV_MD5_MAC_LEN 16
+
+	typedef struct {
+		MV_U32 buf[4];
+		MV_U32 bits[2];
+		MV_U8 in[64];
+	} MV_MD5_CONTEXT;
+
+	void mvMD5Init(MV_MD5_CONTEXT *context);
+	void mvMD5Update(MV_MD5_CONTEXT *context, unsigned char const *buf, unsigned len);
+	void mvMD5Final(unsigned char digest[16], MV_MD5_CONTEXT *context);
+
+	void mvMD5(unsigned char const *buf, unsigned len, unsigned char *digest);
+
+	void mvHmacMd5(unsigned char const *text, int text_len,
+		       unsigned char const *key, int key_len, unsigned char *digest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __mvMD5_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA1.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA1.c
new file mode 100755
index 0000000..ca3861e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA1.c
@@ -0,0 +1,288 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvSHA1.h"
+
+#define SHA1HANDSOFF
+
+typedef union {
+	MV_U8 c[64];
+	MV_U32 l[16];
+
+} CHAR64LONG16;
+
+static void mvSHA1Transform(MV_U32 state[5], const MV_U8 *buffer);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+#ifdef MV_CPU_LE
+#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
+		(rol(block->l[i], 8) & 0x00FF00FF))
+#else
+#define blk0(i) (block->l[i])
+#endif
+#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
+		block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v, w, x, y, z, i) \
+		z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+		w = rol(w, 30);
+#define R1(v, w, x, y, z, i) \
+		z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+		w = rol(w, 30);
+#define R2(v, w, x, y, z, i) \
+		z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
+#define R3(v, w, x, y, z, i) \
+		z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+		w = rol(w, 30);
+#define R4(v, w, x, y, z, i) \
+		z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+		w = rol(w, 30);
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+static void mvSHA1Transform(MV_U32 state[5], const MV_U8 *buffer)
+{
+	MV_U32 a, b, c, d, e;
+	CHAR64LONG16 *block;
+
+#ifdef SHA1HANDSOFF
+	static MV_U32 workspace[16];
+
+	block = (CHAR64LONG16 *) workspace;
+	memcpy(block, buffer, 64);
+#else
+	block = (CHAR64LONG16 *) buffer;
+#endif
+	/* Copy context->state[] to working vars */
+	a = state[0];
+	b = state[1];
+	c = state[2];
+	d = state[3];
+	e = state[4];
+	/* 4 rounds of 20 operations each. Loop unrolled. */
+	R0(a, b, c, d, e, 0);
+	R0(e, a, b, c, d, 1);
+	R0(d, e, a, b, c, 2);
+	R0(c, d, e, a, b, 3);
+	R0(b, c, d, e, a, 4);
+	R0(a, b, c, d, e, 5);
+	R0(e, a, b, c, d, 6);
+	R0(d, e, a, b, c, 7);
+	R0(c, d, e, a, b, 8);
+	R0(b, c, d, e, a, 9);
+	R0(a, b, c, d, e, 10);
+	R0(e, a, b, c, d, 11);
+	R0(d, e, a, b, c, 12);
+	R0(c, d, e, a, b, 13);
+	R0(b, c, d, e, a, 14);
+	R0(a, b, c, d, e, 15);
+	R1(e, a, b, c, d, 16);
+	R1(d, e, a, b, c, 17);
+	R1(c, d, e, a, b, 18);
+	R1(b, c, d, e, a, 19);
+	R2(a, b, c, d, e, 20);
+	R2(e, a, b, c, d, 21);
+	R2(d, e, a, b, c, 22);
+	R2(c, d, e, a, b, 23);
+	R2(b, c, d, e, a, 24);
+	R2(a, b, c, d, e, 25);
+	R2(e, a, b, c, d, 26);
+	R2(d, e, a, b, c, 27);
+	R2(c, d, e, a, b, 28);
+	R2(b, c, d, e, a, 29);
+	R2(a, b, c, d, e, 30);
+	R2(e, a, b, c, d, 31);
+	R2(d, e, a, b, c, 32);
+	R2(c, d, e, a, b, 33);
+	R2(b, c, d, e, a, 34);
+	R2(a, b, c, d, e, 35);
+	R2(e, a, b, c, d, 36);
+	R2(d, e, a, b, c, 37);
+	R2(c, d, e, a, b, 38);
+	R2(b, c, d, e, a, 39);
+	R3(a, b, c, d, e, 40);
+	R3(e, a, b, c, d, 41);
+	R3(d, e, a, b, c, 42);
+	R3(c, d, e, a, b, 43);
+	R3(b, c, d, e, a, 44);
+	R3(a, b, c, d, e, 45);
+	R3(e, a, b, c, d, 46);
+	R3(d, e, a, b, c, 47);
+	R3(c, d, e, a, b, 48);
+	R3(b, c, d, e, a, 49);
+	R3(a, b, c, d, e, 50);
+	R3(e, a, b, c, d, 51);
+	R3(d, e, a, b, c, 52);
+	R3(c, d, e, a, b, 53);
+	R3(b, c, d, e, a, 54);
+	R3(a, b, c, d, e, 55);
+	R3(e, a, b, c, d, 56);
+	R3(d, e, a, b, c, 57);
+	R3(c, d, e, a, b, 58);
+	R3(b, c, d, e, a, 59);
+	R4(a, b, c, d, e, 60);
+	R4(e, a, b, c, d, 61);
+	R4(d, e, a, b, c, 62);
+	R4(c, d, e, a, b, 63);
+	R4(b, c, d, e, a, 64);
+	R4(a, b, c, d, e, 65);
+	R4(e, a, b, c, d, 66);
+	R4(d, e, a, b, c, 67);
+	R4(c, d, e, a, b, 68);
+	R4(b, c, d, e, a, 69);
+	R4(a, b, c, d, e, 70);
+	R4(e, a, b, c, d, 71);
+	R4(d, e, a, b, c, 72);
+	R4(c, d, e, a, b, 73);
+	R4(b, c, d, e, a, 74);
+	R4(a, b, c, d, e, 75);
+	R4(e, a, b, c, d, 76);
+	R4(d, e, a, b, c, 77);
+	R4(c, d, e, a, b, 78);
+	R4(b, c, d, e, a, 79);
+	/* Add the working vars back into context.state[] */
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+	state[4] += e;
+	/* Wipe variables */
+	a = b = c = d = e = 0;
+}
+
+void mvSHA1Init(MV_SHA1_CTX *context)
+{
+	/* SHA1 initialization constants */
+	context->state[0] = 0x67452301;
+	context->state[1] = 0xEFCDAB89;
+	context->state[2] = 0x98BADCFE;
+	context->state[3] = 0x10325476;
+	context->state[4] = 0xC3D2E1F0;
+	context->count[0] = context->count[1] = 0;
+}
+
+/* Run your data through this. */
+void mvSHA1Update(MV_SHA1_CTX *context, MV_U8 const *data, unsigned int len)
+{
+	MV_U32 i, j;
+
+	j = (context->count[0] >> 3) & 63;
+	context->count[0] += len << 3;
+	if (context->count[0] < (len << 3))
+		context->count[1]++;
+	context->count[1] += (len >> 29);
+	if ((j + len) > 63) {
+		memcpy(&context->buffer[j], data, (i = 64 - j));
+		mvSHA1Transform(context->state, context->buffer);
+		for (; i + 63 < len; i += 64)
+			mvSHA1Transform(context->state, &data[i]);
+		j = 0;
+	} else {
+		i = 0;
+	}
+	memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+void mvSHA1Final(MV_U8 *digest, MV_SHA1_CTX *context)
+{
+	MV_U32 i;
+	MV_U8 finalcount[8];
+
+	for (i = 0; i < 8; i++)
+		finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255);
+	/* Endian independent */
+
+	mvSHA1Update(context, (const unsigned char *)"\200", 1);
+	while ((context->count[0] & 504) != 448)
+		mvSHA1Update(context, (const unsigned char *)"\0", 1);
+
+	mvSHA1Update(context, finalcount, 8);	/* Should cause a mvSHA1Transform()
+						 */
+	for (i = 0; i < 20; i++) {
+		digest[i] = (unsigned char)
+		    ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
+	}
+	/* Wipe variables */
+	i = 0;
+	memset(context->buffer, 0, 64);
+	memset(context->state, 0, 20);
+	memset(context->count, 0, 8);
+	memset(finalcount, 0, 8);
+
+#ifdef SHA1HANDSOFF		/* make SHA1Transform overwrite it's own static vars */
+	mvSHA1Transform(context->state, context->buffer);
+#endif
+}
+
+void mvSHA1(MV_U8 const *buf, unsigned int len, MV_U8 *digest)
+{
+	MV_SHA1_CTX ctx;
+
+	mvSHA1Init(&ctx);
+	mvSHA1Update(&ctx, buf, len);
+	mvSHA1Final(digest, &ctx);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA1.h b/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA1.h
new file mode 100755
index 0000000..1890c9b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA1.h
@@ -0,0 +1,89 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __mvSHA1_h__
+#define __mvSHA1_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MV_SHA1_MAC_LEN 20
+
+	typedef struct {
+		MV_U32 state[5];
+		MV_U32 count[2];
+		MV_U8 buffer[64];
+	} MV_SHA1_CTX;
+
+	void mvSHA1Init(MV_SHA1_CTX *context);
+	void mvSHA1Update(MV_SHA1_CTX *context, MV_U8 const *buf, unsigned int len);
+	void mvSHA1Final(MV_U8 *digest, MV_SHA1_CTX *context);
+
+	void mvSHA1(MV_U8 const *buf, unsigned int len, MV_U8 *digest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __mvSHA1_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA256.c b/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA256.c
new file mode 100755
index 0000000..a47dcb8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA256.c
@@ -0,0 +1,308 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvSHA256.h"
+
+#define GET_UINT32(n, b, i)			\
+{						\
+    (n) = ((MV_U32) (b)[(i)] << 24)		\
+	| ((MV_U32) (b)[(i) + 1] << 16)		\
+	| ((MV_U32) (b)[(i) + 2] <<  8)		\
+	| ((MV_U32) (b)[(i) + 3]);		\
+}
+
+#define PUT_UINT32(n, b, i)			\
+{						\
+    (b)[(i)] = (MV_U8) ((n) >> 24);		\
+    (b)[(i) + 1] = (MV_U8) ((n) >> 16);		\
+    (b)[(i) + 2] = (MV_U8) ((n) >>  8);		\
+    (b)[(i) + 3] = (MV_U8) (n);			\
+}
+
+MV_VOID mvSHA256Init(sha256_context *ctx)
+{
+	ctx->total[0] = 0;
+	ctx->total[1] = 0;
+
+	ctx->state[0] = 0x6A09E667;
+	ctx->state[1] = 0xBB67AE85;
+	ctx->state[2] = 0x3C6EF372;
+	ctx->state[3] = 0xA54FF53A;
+	ctx->state[4] = 0x510E527F;
+	ctx->state[5] = 0x9B05688C;
+	ctx->state[6] = 0x1F83D9AB;
+	ctx->state[7] = 0x5BE0CD19;
+}
+
+MV_VOID sha256_process(sha256_context *ctx, MV_U8 data[64])
+{
+	MV_U32 temp1, temp2, W[64];
+	MV_U32 A, B, C, D, E, F, G, H;
+
+	GET_UINT32(W[0], data, 0);
+	GET_UINT32(W[1], data, 4);
+	GET_UINT32(W[2], data, 8);
+	GET_UINT32(W[3], data, 12);
+	GET_UINT32(W[4], data, 16);
+	GET_UINT32(W[5], data, 20);
+	GET_UINT32(W[6], data, 24);
+	GET_UINT32(W[7], data, 28);
+	GET_UINT32(W[8], data, 32);
+	GET_UINT32(W[9], data, 36);
+	GET_UINT32(W[10], data, 40);
+	GET_UINT32(W[11], data, 44);
+	GET_UINT32(W[12], data, 48);
+	GET_UINT32(W[13], data, 52);
+	GET_UINT32(W[14], data, 56);
+	GET_UINT32(W[15], data, 60);
+
+#define  SHR(x, n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x, n) (SHR(x, n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^  SHR(x, 3))
+#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^  SHR(x, 10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+
+#define F0(x, y, z) ((x & y) | (z & (x | y)))
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+
+#define R(t)						\
+(							\
+    W[t] = S1(W[t -  2]) + W[t -  7] +			\
+	S0(W[t - 15]) + W[t - 16]			\
+)
+
+#define P(a, b, c, d, e, f, g, h, x, K)                  \
+{                                               	 \
+    temp1 = h + S3(e) + F1(e, f, g) + K + x;      	 \
+    temp2 = S2(a) + F0(a, b, c);                  	 \
+    d += temp1; h = temp1 + temp2;              	 \
+}
+
+	A = ctx->state[0];
+	B = ctx->state[1];
+	C = ctx->state[2];
+	D = ctx->state[3];
+	E = ctx->state[4];
+	F = ctx->state[5];
+	G = ctx->state[6];
+	H = ctx->state[7];
+
+	P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98);
+	P(H, A, B, C, D, E, F, G, W[1], 0x71374491);
+	P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF);
+	P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5);
+	P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B);
+	P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1);
+	P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4);
+	P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5);
+	P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98);
+	P(H, A, B, C, D, E, F, G, W[9], 0x12835B01);
+	P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
+	P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
+	P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
+	P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
+	P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
+	P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
+	P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
+	P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
+	P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
+	P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
+	P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
+	P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
+	P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
+	P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
+	P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
+	P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
+	P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
+	P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
+	P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
+	P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
+	P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
+	P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
+	P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
+	P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
+	P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
+	P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
+	P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
+	P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
+	P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
+	P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
+	P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
+	P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
+	P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
+	P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
+	P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
+	P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
+	P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
+	P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
+	P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
+	P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
+	P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
+	P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
+	P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
+	P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
+	P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
+	P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
+	P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
+	P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
+	P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
+	P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
+	P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
+	P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
+	P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
+	P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
+
+	ctx->state[0] += A;
+	ctx->state[1] += B;
+	ctx->state[2] += C;
+	ctx->state[3] += D;
+	ctx->state[4] += E;
+	ctx->state[5] += F;
+	ctx->state[6] += G;
+	ctx->state[7] += H;
+}
+
+MV_VOID mvSHA256Update(sha256_context *ctx, MV_U8 *input, MV_U32 length)
+{
+	MV_U32 left, fill;
+
+	if (!length)
+		return;
+
+	left = ctx->total[0] & 0x3F;
+	fill = 64 - left;
+
+	ctx->total[0] += length;
+	ctx->total[0] &= 0xFFFFFFFF;
+
+	if (ctx->total[0] < length)
+		ctx->total[1]++;
+
+	if (left && length >= fill) {
+		memcpy((MV_VOID *) (ctx->buffer + left), (MV_VOID *) input, fill);
+		sha256_process(ctx, ctx->buffer);
+		length -= fill;
+		input += fill;
+		left = 0;
+	}
+
+	while (length >= 64) {
+		sha256_process(ctx, input);
+		length -= 64;
+		input += 64;
+	}
+
+	if (length)
+		memcpy((MV_VOID *) (ctx->buffer + left), (MV_VOID *) input, length);
+}
+
+static MV_U8 sha256_padding[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+MV_VOID mvSHA256Finish(sha256_context *ctx, MV_U8 *digest)
+{
+	MV_U32 last, padn;
+	MV_U32 high, low;
+	MV_U8 msglen[8];
+
+	high = (ctx->total[0] >> 29)
+	    | (ctx->total[1] << 3);
+	low = (ctx->total[0] << 3);
+
+	PUT_UINT32(high, msglen, 0);
+	PUT_UINT32(low, msglen, 4);
+
+	last = ctx->total[0] & 0x3F;
+	padn = (last < 56) ? (56 - last) : (120 - last);
+
+	mvSHA256Update(ctx, sha256_padding, padn);
+	mvSHA256Update(ctx, msglen, 8);
+
+	PUT_UINT32(ctx->state[0], digest, 0);
+	PUT_UINT32(ctx->state[1], digest, 4);
+	PUT_UINT32(ctx->state[2], digest, 8);
+	PUT_UINT32(ctx->state[3], digest, 12);
+	PUT_UINT32(ctx->state[4], digest, 16);
+	PUT_UINT32(ctx->state[5], digest, 20);
+	PUT_UINT32(ctx->state[6], digest, 24);
+	PUT_UINT32(ctx->state[7], digest, 28);
+}
+
+MV_VOID mvSHA256(MV_U8 const *buf, MV_U32 len, MV_U8 * digest)
+{
+	sha256_context ctx;
+
+	mvSHA256Init(&ctx);
+	mvSHA256Update(&ctx, buf, len);
+	mvSHA256Finish(&ctx, digest);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA256.h b/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA256.h
new file mode 100755
index 0000000..489e0e7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cesa/mvSHA256.h
@@ -0,0 +1,87 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _mvSHA256_H
+#define _mvSHA256_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    MV_U32 total[2];
+    MV_U32 state[8];
+    MV_U8 buffer[64];
+}
+sha256_context;
+
+MV_VOID mvSHA256Init(sha256_context *ctx);
+MV_VOID mvSHA256Update(sha256_context *ctx, MV_U8 *input, MV_U32 length);
+MV_VOID mvSHA256Finish(sha256_context *ctx, MV_U8 *digest);
+MV_VOID mvSHA256(MV_U8 const *buf, MV_U32 len, MV_U8 *digest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __mvSHA256_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmr.c b/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmr.c
new file mode 100755
index 0000000..6a90a42
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmr.c
@@ -0,0 +1,356 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysCntmrConfig.h"
+#include "mvCntmrRegs.h"
+#include "mvCntmr.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/*******************************************************************************
+* mvCntmrLoad -
+*
+* DESCRIPTION:
+*       Load an init Value to a given counter/timer
+*
+* INPUT:
+*       countNum - counter number
+*       value - value to be loaded
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess
+*******************************************************************************/
+MV_STATUS mvCntmrLoad(MV_U32 countNum, MV_U32 value)
+{
+	if (countNum >= MV_CNTMR_MAX_COUNTER) {
+
+		mvOsPrintf(("mvCntmrLoad: Err. illegal counter number \n"));
+		return MV_BAD_PARAM;;
+
+	}
+
+	MV_REG_WRITE(CNTMR_RELOAD_REG(countNum), value);
+	MV_REG_WRITE(CNTMR_VAL_REG(countNum), value);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCntmrRead -
+*
+* DESCRIPTION:
+*  	Returns the value of the given Counter/Timer
+*
+* INPUT:
+*       countNum - counter number
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_U32 counter value
+*******************************************************************************/
+MV_U32 mvCntmrRead(MV_U32 countNum)
+{
+	return MV_REG_READ(CNTMR_VAL_REG(countNum));
+}
+
+/*******************************************************************************
+* mvCntmrWrite -
+*
+* DESCRIPTION:
+*  	Returns the value of the given Counter/Timer
+*
+* INPUT:
+*       countNum - counter number
+*		countVal - value to write
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None
+*******************************************************************************/
+void mvCntmrWrite(MV_U32 countNum, MV_U32 countVal)
+{
+	MV_REG_WRITE(CNTMR_VAL_REG(countNum), countVal);
+}
+
+/*******************************************************************************
+* mvCntmrCtrlSet -
+*
+* DESCRIPTION:
+*  	Set the Control to a given counter/timer
+*
+* INPUT:
+*       countNum - counter number
+*		pCtrl - pointer to MV_CNTMR_CTRL structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess
+*******************************************************************************/
+MV_STATUS mvCntmrCtrlSet(MV_U32 countNum, MV_CNTMR_CTRL *pCtrl)
+{
+	MV_U32 cntmrCtrl;
+
+	if (countNum >= MV_CNTMR_MAX_COUNTER) {
+
+		DB(mvOsPrintf(("mvCntmrCtrlSet: Err. illegal counter number \n")));
+		return MV_BAD_PARAM;;
+
+	}
+
+	/* read control register */
+	cntmrCtrl = MV_REG_READ(CNTMR_CTRL_REG);
+
+	if (pCtrl->enable) {	/* enable counter\timer */
+		cntmrCtrl |= CTCR_ARM_TIMER_EN(countNum);
+	} else {		/* disable counter\timer */
+
+		cntmrCtrl &= ~CTCR_ARM_TIMER_EN(countNum);
+	}
+
+	if (pCtrl->autoEnable) {	/* Auto mode */
+		cntmrCtrl |= CTCR_ARM_TIMER_AUTO_EN(countNum);
+
+	} else {		/* no auto mode */
+
+		cntmrCtrl &= ~CTCR_ARM_TIMER_AUTO_EN(countNum);
+	}
+
+	MV_REG_WRITE(CNTMR_CTRL_REG, cntmrCtrl);
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvCntmrCtrlGet -
+*
+* DESCRIPTION:
+*  	Get the Control value of a given counter/timer
+*
+* INPUT:
+*       countNum - counter number
+*		pCtrl - pointer to MV_CNTMR_CTRL structure
+*
+* OUTPUT:
+*       Counter\Timer control value
+*
+* RETURN:
+*       MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess
+*******************************************************************************/
+MV_STATUS mvCntmrCtrlGet(MV_U32 countNum, MV_CNTMR_CTRL *pCtrl)
+{
+	MV_U32 cntmrCtrl;
+
+	if (countNum >= MV_CNTMR_MAX_COUNTER) {
+		DB(mvOsPrintf(("mvCntmrCtrlGet: Err. illegal counter number \n")));
+		return MV_BAD_PARAM;;
+	}
+
+	/* read control register */
+	cntmrCtrl = MV_REG_READ(CNTMR_CTRL_REG);
+
+	/* enable counter\timer */
+	if (cntmrCtrl & CTCR_ARM_TIMER_EN(countNum))
+		pCtrl->enable = MV_TRUE;
+	else
+		pCtrl->enable = MV_FALSE;
+
+	/* counter mode */
+	if (cntmrCtrl & CTCR_ARM_TIMER_AUTO_EN(countNum))
+		pCtrl->autoEnable = MV_TRUE;
+	else
+		pCtrl->autoEnable = MV_FALSE;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCntmrEnable -
+*
+* DESCRIPTION:
+*  	Set the Enable-Bit to logic '1' ==> starting the counter
+*
+* INPUT:
+*       countNum - counter number
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess
+*******************************************************************************/
+MV_STATUS mvCntmrEnable(MV_U32 countNum)
+{
+	MV_U32 cntmrCtrl;
+
+	if (countNum >= MV_CNTMR_MAX_COUNTER) {
+
+		DB(mvOsPrintf(("mvCntmrEnable: Err. illegal counter number \n")));
+		return MV_BAD_PARAM;;
+
+	}
+
+	/* read control register */
+	cntmrCtrl = MV_REG_READ(CNTMR_CTRL_REG);
+
+	/* enable counter\timer */
+	cntmrCtrl |= CTCR_ARM_TIMER_EN(countNum);
+
+	MV_REG_WRITE(CNTMR_CTRL_REG, cntmrCtrl);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCntmrDisable -
+*
+* DESCRIPTION:
+*  	Stop the counter/timer running, and returns its Value
+*
+* INPUT:
+*       countNum - counter number
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_U32 counter\timer value
+*******************************************************************************/
+MV_STATUS mvCntmrDisable(MV_U32 countNum)
+{
+	MV_U32 cntmrCtrl;
+
+	if (countNum >= MV_CNTMR_MAX_COUNTER) {
+
+		DB(mvOsPrintf(("mvCntmrDisable: Err. illegal counter number \n")));
+		return MV_BAD_PARAM;;
+
+	}
+
+	/* read control register */
+	cntmrCtrl = MV_REG_READ(CNTMR_CTRL_REG);
+
+	/* disable counter\timer */
+	cntmrCtrl &= ~CTCR_ARM_TIMER_EN(countNum);
+
+	MV_REG_WRITE(CNTMR_CTRL_REG, cntmrCtrl);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCntmrStart -
+*
+* DESCRIPTION:
+*  	Combined all the sub-operations above to one function: Load,setMode,Enable
+*
+* INPUT:
+*       countNum - counter number
+*		value - value of the counter\timer to be set
+*		pCtrl - pointer to MV_CNTMR_CTRL structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess
+*******************************************************************************/
+MV_STATUS mvCntmrStart(MV_U32 countNum, MV_U32 value, MV_CNTMR_CTRL *pCtrl)
+{
+
+	if (countNum >= MV_CNTMR_MAX_COUNTER) {
+
+		mvOsPrintf(("mvCntmrDisable: Err. illegal counter number \n"));
+		return MV_BAD_PARAM;;
+
+	}
+
+	/* load value onto counter\timer */
+	mvCntmrLoad(countNum, value);
+
+	/* set the counter to load in the first time */
+	mvCntmrWrite(countNum, value);
+
+	/* set control for timer \ cunter and enable */
+	mvCntmrCtrlSet(countNum, pCtrl);
+
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmr.h b/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmr.h
new file mode 100755
index 0000000..e7d75dc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmr.h
@@ -0,0 +1,120 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvTmrWtdgh
+#define __INCmvTmrWtdgh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes */
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysCntmrConfig.h"
+
+/* This enumerator describe counters\watchdog numbers       */
+	typedef enum _mvCntmrID {
+		TIMER0 = 0,
+		TIMER1,
+		WATCHDOG,
+		TIMER2,
+		TIMER3,
+	} MV_CNTMR_ID;
+
+/* Counter / Timer control structure */
+	typedef struct _mvCntmrCtrl {
+		MV_BOOL enable;	/* enable */
+		MV_BOOL autoEnable;	/* counter/Timer                    */
+	} MV_CNTMR_CTRL;
+
+/* Functions */
+
+/* Load an init Value to a given counter/timer */
+	MV_STATUS mvCntmrLoad(MV_U32 countNum, MV_U32 value);
+
+/* Returns the value of the given Counter/Timer */
+	MV_U32 mvCntmrRead(MV_U32 countNum);
+
+/* Write a value of the given Counter/Timer */
+	void mvCntmrWrite(MV_U32 countNum, MV_U32 countVal);
+
+/* Set the Control to a given counter/timer */
+	MV_STATUS mvCntmrCtrlSet(MV_U32 countNum, MV_CNTMR_CTRL *pCtrl);
+
+/* Get the value of a given counter/timer */
+	MV_STATUS mvCntmrCtrlGet(MV_U32 countNum, MV_CNTMR_CTRL *pCtrl);
+
+/* Set the Enable-Bit to logic '1' ==> starting the counter. */
+	MV_STATUS mvCntmrEnable(MV_U32 countNum);
+
+/* Stop the counter/timer running, and returns its Value. */
+	MV_STATUS mvCntmrDisable(MV_U32 countNum);
+
+/* Combined all the sub-operations above to one function: Load,setMode,Enable */
+	MV_STATUS mvCntmrStart(MV_U32 countNum, MV_U32 value, MV_CNTMR_CTRL *pCtrl);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __INCmvTmrWtdgh */
diff --git a/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmrRegs.h b/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmrRegs.h
new file mode 100755
index 0000000..d2e1383
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cntmr/mvCntmrRegs.h
@@ -0,0 +1,130 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvTmrwtdgRegsh
+#define __INCmvTmrwtdgRegsh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvSysCntmrConfig.h"
+
+/*******************************************/
+/* ARM Timers Registers Map                */
+/*******************************************/
+
+#define CNTMR_RELOAD_REG(tmrNum)	(MV_CNTMR_REGS_BASE + 0x10 + (tmrNum)*8 + \
+						(((tmrNum) < 3) ? 0 : 8))
+#define CNTMR_VAL_REG(tmrNum)		(MV_CNTMR_REGS_BASE + 0x14 + (tmrNum)*8 + \
+						(((tmrNum) < 3) ? 0 : 8))
+#define CNTMR_CTRL_REG			(MV_CNTMR_REGS_BASE)
+
+/*For MV78XX0*/
+#define CNTMR_CAUSE_REG(cpuId)		(CPU_AHB_MBUS_CAUSE_INT_REG(cpuId))
+#define CNTMR_MASK_REG(cpuId)		(CPU_AHB_MBUS_MASK_INT_REG(cpuId))
+
+/* ARM Timers Registers Map                */
+/*******************************************/
+
+
+/* ARM Timers Control Register */
+/* CPU_TIMERS_CTRL_REG (CTCR) */
+
+#define TIMER0_NUM				0
+#define TIMER1_NUM				1
+#define WATCHDOG_NUM			2
+#define TIMER2_NUM				3
+#define TIMER3_NUM				4
+
+#define CTCR_ARM_TIMER_EN_OFFS(cntr)	(cntr * 2)
+#define CTCR_ARM_TIMER_EN_MASK(cntr)	(1 << CTCR_ARM_TIMER_EN_OFFS)
+#define CTCR_ARM_TIMER_EN(cntr)			(1 << CTCR_ARM_TIMER_EN_OFFS(cntr))
+#define CTCR_ARM_TIMER_DIS(cntr)		(0 << CTCR_ARM_TIMER_EN_OFFS(cntr))
+
+#define CTCR_ARM_TIMER_AUTO_OFFS(cntr)	((cntr * 2) + 1)
+#define CTCR_ARM_TIMER_AUTO_MASK(cntr)	BIT1
+#define CTCR_ARM_TIMER_AUTO_EN(cntr)	(1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
+#define CTCR_ARM_TIMER_AUTO_DIS(cntr)	(0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
+
+
+/* ARM Timer\Watchdog Reload Register */
+/* CNTMR_RELOAD_REG (TRR) */
+
+#define TRG_ARM_TIMER_REL_OFFS			0
+#define TRG_ARM_TIMER_REL_MASK			0xffffffff
+
+/* ARM Timer\Watchdog Register */
+/* CNTMR_VAL_REG (TVRG) */
+
+#define TVR_ARM_TIMER_OFFS			0
+#define TVR_ARM_TIMER_MASK			0xffffffff
+#define TVR_ARM_TIMER_MAX			0xffffffff
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __INCmvTmrwtdgRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/cntmr/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/cntmr/mvCompVer.txt
new file mode 100755
index 0000000..3afa556
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cntmr/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.3
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/cpu/feroceon/mvFeroceonCntrs.c b/arch/arm/plat-feroceon/mv_hal/cpu/feroceon/mvFeroceonCntrs.c
new file mode 100755
index 0000000..5b9a091
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cpu/feroceon/mvFeroceonCntrs.c
@@ -0,0 +1,122 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mvOs.h"
+#include "../mvCpuCntrs.h"
+
+const static MV_CPU_CNTRS_OPS mvCpuCntrsOpsTbl[MV_FEROCEON_CNTRS_NUM][MV_FEROCEON_CNTRS_OPS_NUM] = {
+	/*0 */
+	{
+	 /*0x2 *//*0x4 *//*0x8 */
+	 MV_CPU_CNTRS_CYCLES, MV_CPU_CNTRS_DCACHE_READ_HIT, MV_CPU_CNTRS_DCACHE_READ_MISS,
+	 /*0x10 *//*0x20 *//*0x40 */
+	 MV_CPU_CNTRS_DCACHE_WRITE_HIT, MV_CPU_CNTRS_DCACHE_WRITE_MISS, MV_CPU_CNTRS_INSTRUCTIONS,
+	 /*0x80 *//*0x100 *//*0x200 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x400 *//*0x800 *//*0x1000 */
+	 MV_CPU_CNTRS_MMU_READ_LATENCY, MV_CPU_CNTRS_ICACHE_READ_LATENCY, MV_CPU_CNTRS_WB_WRITE_LATENCY,
+	 /*0x2000 *//*0x4000 *//*0x8000 */
+	 MV_CPU_CNTRS_LDM_STM_HOLD, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x10000 *//*0x20000 *//*0x40000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_DATA_WRITE_ACCESS,
+	 /*0x80000 *//*0x100000 *//*0x200000 */
+	 MV_CPU_CNTRS_DATA_READ_ACCESS, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x400000 *//*0x800000 *//*0x1000000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x2000000 *//*0x4000000 *//*0x8000000 */
+	 MV_CPU_CNTRS_BRANCH_PREDICT_HIT, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 },
+	/*1 */
+	{
+	 /*0x2 *//*0x4 *//*0x8 */
+	 MV_CPU_CNTRS_CYCLES, MV_CPU_CNTRS_ICACHE_READ_MISS, MV_CPU_CNTRS_DCACHE_READ_MISS,
+	 /*0x10 *//*0x20 *//*0x40 */
+	 MV_CPU_CNTRS_DCACHE_WRITE_MISS, MV_CPU_CNTRS_ITLB_MISS, MV_CPU_CNTRS_SINGLE_ISSUE,
+	 /*0x80 *//*0x100 *//*0x200 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_BRANCH_RETIRED, MV_CPU_CNTRS_INVALID,
+	 /*0x400 *//*0x800 *//*0x1000 */
+	 MV_CPU_CNTRS_MMU_READ_BEAT, MV_CPU_CNTRS_ICACHE_READ_LATENCY, MV_CPU_CNTRS_WB_WRITE_BEAT,
+	 /*0x2000 *//*0x4000 *//*0x8000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_IS_HOLD,
+	 /*0x10000 *//*0x20000 *//*0x40000 */
+	 MV_CPU_CNTRS_DATA_READ_ACCESS, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x80000 *//*0x100000 *//*0x200000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x400000 *//*0x800000 *//*0x1000000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x2000000 *//*0x4000000 *//*0x8000000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 },
+	/*2 */
+	{
+	 /*0x2 *//*0x4 *//*0x8 */
+	 MV_CPU_CNTRS_CYCLES, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_DCACHE_ACCESS,
+	 /*0x10 *//*0x20 *//*0x40 */
+	 MV_CPU_CNTRS_DTLB_MISS, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x80 *//*0x100 *//*0x200 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_BRANCH_PREDICT_MISS, MV_CPU_CNTRS_WB_WRITE_BEAT,
+	 /*0x400 *//*0x800 *//*0x1000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_DCACHE_READ_LATENCY, MV_CPU_CNTRS_DCACHE_WRITE_LATENCY,
+	 /*0x2000 *//*0x4000 *//*0x8000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x10000 *//*0x20000 *//*0x40000 */
+	 MV_CPU_CNTRS_BIU_SIMULT_ACCESS, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x80000 *//*0x100000 *//*0x200000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x400000 *//*0x800000 *//*0x1000000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x2000000 *//*0x4000000 *//*0x8000000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 },
+	/*3 */
+	{
+	 /*0x2 *//*0x4 *//*0x8 */
+	 MV_CPU_CNTRS_CYCLES, MV_CPU_CNTRS_DCACHE_READ_MISS, MV_CPU_CNTRS_DCACHE_WRITE_MISS,
+	 /*0x10 *//*0x20 *//*0x40 */
+	 MV_CPU_CNTRS_TLB_MISS, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x80 *//*0x100 *//*0x200 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_BRANCH_TAKEN, MV_CPU_CNTRS_WB_FULL_CYCLES,
+	 /*0x400 *//*0x800 *//*0x1000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_DCACHE_READ_BEAT, MV_CPU_CNTRS_DCACHE_WRITE_BEAT,
+	 /*0x2000 *//*0x4000 *//*0x8000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x10000 *//*0x20000 *//*0x40000 */
+	 MV_CPU_CNTRS_BIU_ANY_ACCESS, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_DATA_WRITE_ACCESS,
+	 /*0x80000 *//*0x100000 *//*0x200000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x400000 *//*0x800000 *//*0x1000000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 /*0x2000000 *//*0x4000000 *//*0x8000000 */
+	 MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID, MV_CPU_CNTRS_INVALID,
+	 }
+};
+
+int		mvCpuCntrsMap(int counter, MV_CPU_CNTRS_OPS op)
+{
+	int	i;
+
+	for (i = 0; i < MV_FEROCEON_CNTRS_OPS_NUM; i++) {
+		if (mvCpuCntrsOpsTbl[counter][i] == op)
+			return (i + 1);
+	}
+	mvOsPrintf("invalid CPU counters event %d for counter %d\n", op, counter);
+	return -1;
+}
+
+void mvCpuCntrsInit(void)
+{
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/cpu/feroceon/mvFeroceonCntrs.h b/arch/arm/plat-feroceon/mv_hal/cpu/feroceon/mvFeroceonCntrs.h
new file mode 100755
index 0000000..e7ebceb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cpu/feroceon/mvFeroceonCntrs.h
@@ -0,0 +1,179 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __mvFeroceonCntrs_h__
+#define __mvFeroceonCntrs_h__
+
+#include "mvTypes.h"
+#include "mvOs.h"
+
+#define MV_FEROCEON_CNTRS_NUM       4
+#define MV_FEROCEON_CNTRS_OPS_NUM   32
+
+#define MV_CPU_CNTR_SIZE			64 /* bits */
+
+
+/* internal */
+static INLINE int mvCpuCntrsStart(int counter, int op)
+{
+	MV_U32 reg = (1 << op) | 0x1;	/*enable */
+
+	switch (counter) {
+	case 0:
+__asm__ __volatile__("mcr p15, 0, %0, c15, c12, 0" : : "r"(reg));
+		return 0;
+
+	case 1:
+__asm__ __volatile__("mcr p15, 0, %0, c15, c12, 1" : : "r"(reg));
+		return 0;
+
+	case 2:
+__asm__ __volatile__("mcr p15, 0, %0, c15, c12, 2" : : "r"(reg));
+		return 0;
+
+	case 3:
+__asm__ __volatile__("mcr p15, 0, %0, c15, c12, 3" : : "r"(reg));
+		return 0;
+
+	default:
+		mvOsPrintf("error in program_counter: bad counter number (%d)\n", counter);
+	}
+	return 1;
+}
+
+static INLINE void mvCpuCntrsStop(const int counter)
+{
+	MV_U32 ll = 0;
+
+	switch (counter) {
+	case 0:
+MV_ASM("mcr p15, 0, %0, c15, c12, 0" : : "r"(ll));
+		break;
+
+	case 1:
+MV_ASM("mcr p15, 0, %0, c15, c12, 1" : : "r"(ll));
+		break;
+
+	case 2:
+MV_ASM("mcr p15, 0, %0, c15, c12, 2" : : "r"(ll));
+		break;
+
+	case 3:
+MV_ASM("mcr p15, 0, %0, c15, c12, 3" : : "r"(ll));
+		break;
+
+	default:
+		mvOsPrintf("mv_cpu_cntrs_read: bad counter number (%d)\n", counter);
+	}
+}
+
+static INLINE MV_U64 mvCpuCntrsRead(const int counter)
+{
+	MV_U32 low = 0, high = 0;
+
+	switch (counter) {
+	case 0:
+MV_ASM("mrc p15, 0, %0, c15, c13, 0" : "=r"(low));
+MV_ASM("mrc p15, 0, %0, c15, c13, 1" : "=r"(high));
+		break;
+
+	case 1:
+MV_ASM("mrc p15, 0, %0, c15, c13, 2" : "=r"(low));
+MV_ASM("mrc p15, 0, %0, c15, c13, 3" : "=r"(high));
+		break;
+
+	case 2:
+MV_ASM("mrc p15, 0, %0, c15, c13, 4" : "=r"(low));
+MV_ASM("mrc p15, 0, %0, c15, c13, 5" : "=r"(high));
+		break;
+
+	case 3:
+MV_ASM("mrc p15, 0, %0, c15, c13, 6" : "=r"(low));
+MV_ASM("mrc p15, 0, %0, c15, c13, 7" : "=r"(high));
+		break;
+
+	default:
+		mvOsPrintf("mv_cpu_cntrs_read: bad counter number (%d)\n", counter);
+	}
+	return (((MV_U64) high << 32) | low);
+}
+
+static INLINE void mvCpuCntrsReset(void)
+{
+	MV_U32 reg = 0;
+
+MV_ASM("mcr p15, 0, %0, c15, c13, 0" : : "r"(reg));
+MV_ASM("mcr p15, 0, %0, c15, c13, 1" : : "r"(reg));
+MV_ASM("mcr p15, 0, %0, c15, c13, 2" : : "r"(reg));
+MV_ASM("mcr p15, 0, %0, c15, c13, 3" : : "r"(reg));
+MV_ASM("mcr p15, 0, %0, c15, c13, 4" : : "r"(reg));
+MV_ASM("mcr p15, 0, %0, c15, c13, 5" : : "r"(reg));
+MV_ASM("mcr p15, 0, %0, c15, c13, 6" : : "r"(reg));
+MV_ASM("mcr p15, 0, %0, c15, c13, 7" : : "r"(reg));
+}
+
+
+void mvCpuCntrsInit(void);
+
+#endif /* __mvFeroceonCntrs_h__ */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuCntrs.c b/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuCntrs.c
new file mode 100755
index 0000000..61f5d7b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuCntrs.c
@@ -0,0 +1,141 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mvOs.h"
+#include "mvCpuCntrs.h"
+
+MV_CPU_CNTRS_ENTRY mvCpuCntrsTbl[MV_CPU_CNTRS_NUM];
+
+void mvCpuCntrsEventClear(MV_CPU_CNTRS_EVENT *pEvent)
+{
+	int i;
+
+	for (i = 0; i < MV_CPU_CNTRS_NUM; i++)
+		pEvent->counters_sum[i] = 0;
+	pEvent->num_of_measurements = 0;
+}
+
+MV_CPU_CNTRS_EVENT *mvCpuCntrsEventCreate(char *name, MV_U32 print_threshold)
+{
+	int i;
+	MV_CPU_CNTRS_EVENT *event = mvOsMalloc(sizeof(MV_CPU_CNTRS_EVENT));
+
+	if (event) {
+		strncpy(event->name, name, sizeof(event->name));
+		event->num_of_measurements = 0;
+		event->avg_sample_count = print_threshold;
+		for (i = 0; i < MV_CPU_CNTRS_NUM; i++) {
+			event->counters_before[i] = 0;
+			event->counters_after[i] = 0;
+			event->counters_sum[i] = 0;
+		}
+	}
+	return event;
+}
+
+void mvCpuCntrsEventDelete(MV_CPU_CNTRS_EVENT *event)
+{
+	if (event != NULL)
+		mvOsFree(event);
+}
+
+MV_STATUS mvCpuCntrsProgram(int counter, MV_CPU_CNTRS_OPS op, char *name, MV_U32 overhead)
+{
+	int	opIdx;
+
+	strncpy(mvCpuCntrsTbl[counter].name, name, sizeof(mvCpuCntrsTbl[counter].name));
+	mvCpuCntrsTbl[counter].operation = op;
+	mvCpuCntrsTbl[counter].overhead = overhead;
+	mvCpuCntrsTbl[counter].max_value = ~0 >> (64 - MV_CPU_CNTR_SIZE);
+
+	opIdx = mvCpuCntrsMap(counter, op);
+	if (opIdx == -1) {
+		mvOsPrintf("%s: Can't map CPU counter %d, to %d event\n", __func__, counter, op);
+		return MV_FAIL;
+	}
+
+	if (mvCpuCntrsStart(counter, opIdx)) {
+		mvOsPrintf("%s: Can't start CPU counter %d, op=%d, opIdx=%d\n", __func__, counter, op, opIdx);
+		return MV_FAIL;
+	}
+
+	mvOsPrintf("%s: Counter=%d, opIdx=%d, overhead=%d, max=0x%llx\n",
+		   mvCpuCntrsTbl[counter].name, counter, opIdx, mvCpuCntrsTbl[counter].overhead,
+		   mvCpuCntrsTbl[counter].max_value);
+
+	return MV_OK;
+}
+
+void mvCpuCntrsShow(MV_CPU_CNTRS_EVENT *pEvent)
+{
+	int			i;
+	MV_U64		counters_avg;
+	static int	title = 0;
+
+	if ((title % 64) == 0) {
+
+		mvOsPrintf("\n%16s  ", " ");
+		for (i = 0; i < MV_CPU_CNTRS_NUM; i++) {
+
+			if (mvCpuCntrsTbl[i].operation == MV_CPU_CNTRS_INVALID)
+				continue;
+
+			mvOsPrintf(" %8s, ", mvCpuCntrsTbl[i].name);
+		}
+		mvOsPrintf("\n");
+	}
+
+	mvOsPrintf("%16s: ", pEvent->name);
+	for (i = 0; i < MV_CPU_CNTRS_NUM; i++) {
+
+		if (mvCpuCntrsTbl[i].operation == MV_CPU_CNTRS_INVALID)
+			continue;
+
+
+		counters_avg = mvOsDivMod64(pEvent->counters_sum[i], pEvent->num_of_measurements, NULL);
+/*		counters_avg = pEvent->counters_sum[i] / pEvent->num_of_measurements;*/
+		if (counters_avg >= mvCpuCntrsTbl[i].overhead)
+			counters_avg -= mvCpuCntrsTbl[i].overhead;
+		else
+			counters_avg = 0;
+		mvOsPrintf(" %8llu, ", counters_avg);
+
+/*
+		mvOsPrintf("%s = %5llu / %u, ",
+				mvCpuCntrsTbl[i].name, pEvent->counters_sum[i], pEvent->num_of_measurements);
+*/
+	}
+	mvOsPrintf("\n");
+	mvCpuCntrsEventClear(pEvent);
+	mvCpuCntrsReset();
+
+	title++;
+}
+
+void mvCpuCntrsStatus(void)
+{
+	int i;
+
+	for (i = 0; i < MV_CPU_CNTRS_NUM; i++)
+		mvOsPrintf("#%d: %s, overhead=%d\n", i, mvCpuCntrsTbl[i].name, mvCpuCntrsTbl[i].overhead);
+}
+
+void mvCpuCntrsInitialize(void)
+{
+	memset(mvCpuCntrsTbl, 0, sizeof(mvCpuCntrsTbl));
+	mvCpuCntrsInit();
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuCntrs.h b/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuCntrs.h
new file mode 100755
index 0000000..a75f365
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuCntrs.h
@@ -0,0 +1,241 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __mvCpuCntrs_h__
+#define __mvCpuCntrs_h__
+
+#include "mvTypes.h"
+#include "mvOs.h"
+
+#ifdef CONFIG_PLAT_ARMADA
+#include "pj4/mvPJ4Cntrs.h"
+
+#define MV_CPU_CNTRS_NUM            MRVL_PJ4B_MAX_COUNTERS
+#define MV_CPU_CNTRS_OPS_NUM        MRVL_PJ4B_EVT_UNUSED
+
+#else /**/
+
+#include "feroceon/mvFeroceonCntrs.h"
+
+#define MV_CPU_CNTRS_NUM            MV_FEROCEON_CNTRS_NUM
+#define MV_CPU_CNTRS_OPS_NUM        MV_FEROCEON_CNTRS_OPS_NUM
+
+#endif /* CONFIG_PLAT_ARMADA */
+
+typedef enum {
+	MV_CPU_CNTRS_INVALID = 0,
+	MV_CPU_CNTRS_CYCLES,
+	MV_CPU_CNTRS_ICACHE_READ_MISS,
+	MV_CPU_CNTRS_DCACHE_ACCESS,
+	MV_CPU_CNTRS_DCACHE_READ_MISS,
+	MV_CPU_CNTRS_DCACHE_READ_HIT,
+	MV_CPU_CNTRS_DCACHE_WRITE_MISS,
+	MV_CPU_CNTRS_DCACHE_WRITE_HIT,
+	MV_CPU_CNTRS_DTLB_MISS,
+	MV_CPU_CNTRS_TLB_MISS,
+	MV_CPU_CNTRS_ITLB_MISS,
+	MV_CPU_CNTRS_INSTRUCTIONS,
+	MV_CPU_CNTRS_SINGLE_ISSUE,
+	MV_CPU_CNTRS_MMU_READ_LATENCY,
+	MV_CPU_CNTRS_MMU_READ_BEAT,
+	MV_CPU_CNTRS_BRANCH_RETIRED,
+	MV_CPU_CNTRS_BRANCH_TAKEN,
+	MV_CPU_CNTRS_BRANCH_PREDICT_MISS,
+	MV_CPU_CNTRS_BRANCH_PREDICT_HIT,
+	MV_CPU_CNTRS_WB_FULL_CYCLES,
+	MV_CPU_CNTRS_WB_WRITE_LATENCY,
+	MV_CPU_CNTRS_WB_WRITE_BEAT,
+	MV_CPU_CNTRS_ICACHE_READ_LATENCY,
+	MV_CPU_CNTRS_ICACHE_READ_BEAT,
+	MV_CPU_CNTRS_DCACHE_READ_LATENCY,
+	MV_CPU_CNTRS_DCACHE_READ_BEAT,
+	MV_CPU_CNTRS_DCACHE_WRITE_LATENCY,
+	MV_CPU_CNTRS_DCACHE_WRITE_BEAT,
+	MV_CPU_CNTRS_LDM_STM_HOLD,
+	MV_CPU_CNTRS_IS_HOLD,
+	MV_CPU_CNTRS_DATA_WRITE_ACCESS,
+	MV_CPU_CNTRS_DATA_READ_ACCESS,
+	MV_CPU_CNTRS_BIU_SIMULT_ACCESS,
+	MV_CPU_CNTRS_BIU_ANY_ACCESS,
+
+} MV_CPU_CNTRS_OPS;
+
+typedef struct {
+	char				name[16];
+	MV_CPU_CNTRS_OPS	operation;
+	int					opIdx;
+	MV_U32				overhead;
+	MV_U64				max_value;
+
+} MV_CPU_CNTRS_ENTRY;
+
+typedef struct {
+	char	name[16];
+	MV_U32	num_of_measurements;
+	MV_U32	avg_sample_count;
+	MV_U64	counters_before[MV_CPU_CNTRS_NUM];
+	MV_U64	counters_after[MV_CPU_CNTRS_NUM];
+	MV_U64	counters_sum[MV_CPU_CNTRS_NUM];
+
+} MV_CPU_CNTRS_EVENT;
+
+
+extern MV_CPU_CNTRS_ENTRY mvCpuCntrsTbl[];
+
+static INLINE void mvCpuCntrsReadBefore(MV_CPU_CNTRS_EVENT *pEvent)
+{
+	/* order is important - we want to measure the cycle count last here! */
+#ifdef CONFIG_PLAT_ARMADA
+	pEvent->counters_before[6] = mvCpuPmCntrRead(5);
+	pEvent->counters_before[5] = mvCpuPmCntrRead(4);
+	pEvent->counters_before[4] = mvCpuPmCntrRead(3);
+	pEvent->counters_before[3] = mvCpuPmCntrRead(2);
+	pEvent->counters_before[2] = mvCpuPmCntrRead(1);
+	pEvent->counters_before[1] = mvCpuPmCntrRead(0);
+	/* 0 - cycles counter */
+	pEvent->counters_before[0] = mvCpuCyclesCntrRead();
+#else
+	pEvent->counters_before[1] = mvCpuCntrsRead(1);
+	pEvent->counters_before[3] = mvCpuCntrsRead(3);
+	pEvent->counters_before[0] = mvCpuCntrsRead(0);
+	pEvent->counters_before[2] = mvCpuCntrsRead(2);
+#endif /* CONFIG_PLAT_ARMADA */
+}
+
+static INLINE void mvCpuCntrsReadAfter(MV_CPU_CNTRS_EVENT *pEvent)
+{
+	int i;
+
+	/* order is important - we want to measure the cycle count first here! */
+#ifdef CONFIG_PLAT_ARMADA
+	/* 0 - cycles counter */
+	pEvent->counters_after[0] = mvCpuCyclesCntrRead();
+	pEvent->counters_after[1] = mvCpuPmCntrRead(0);
+	pEvent->counters_after[2] = mvCpuPmCntrRead(1);
+	pEvent->counters_after[3] = mvCpuPmCntrRead(2);
+	pEvent->counters_after[4] = mvCpuPmCntrRead(3);
+	pEvent->counters_after[5] = mvCpuPmCntrRead(4);
+	pEvent->counters_after[6] = mvCpuPmCntrRead(5);
+#else /**/
+	pEvent->counters_after[2] = mvCpuCntrsRead(2);
+	pEvent->counters_after[0] = mvCpuCntrsRead(0);
+	pEvent->counters_after[3] = mvCpuCntrsRead(3);
+	pEvent->counters_after[1] = mvCpuCntrsRead(1);
+#endif /* CONFIG_PLAT_ARMADA */
+
+	/* now update summary */
+	for (i = 0; i < MV_CPU_CNTRS_NUM; i++) {
+
+		if (mvCpuCntrsTbl[i].operation == MV_CPU_CNTRS_INVALID)
+			continue;
+
+		if (pEvent->counters_after[i] >= pEvent->counters_before[i])
+			pEvent->counters_sum[i] += (pEvent->counters_after[i] - pEvent->counters_before[i]);
+		else {
+			pEvent->counters_sum[i] += ((mvCpuCntrsTbl[i].max_value - pEvent->counters_before[i]) +
+										pEvent->counters_after[i]);
+		}
+	}
+	pEvent->num_of_measurements++;
+/*
+	mvOsPrintf("CCNT_%u: before=%llu, after=%llu, sum=%llu\n",
+				pEvent->num_of_measurements, pEvent->counters_before[0],
+				pEvent->counters_after[0], pEvent->counters_sum[0]);
+*/
+}
+
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+
+#define MV_CPU_CNTRS_READ(counter)	mvCpuCntrsRead(counter)
+
+#define MV_CPU_CNTRS_START(event)	mvCpuCntrsReadBefore(event)
+
+#define MV_CPU_CNTRS_STOP(event)	mvCpuCntrsReadAfter(event)
+
+#define MV_CPU_CNTRS_SHOW(event)	                                      \
+		if (event->num_of_measurements >= event->avg_sample_count)     \
+			mvCpuCntrsShow(event);
+
+#else
+
+#define MV_CPU_CNTRS_READ(counter)
+#define MV_CPU_CNTRS_START(event)
+#define MV_CPU_CNTRS_STOP(event)
+#define MV_CPU_CNTRS_SHOW(event)
+
+#endif /* CONFIG_MV_CPU_PERF_CNTRS */
+
+/* Functions should be implemented for each CPU */
+int					mvCpuCntrsMap(int counter, MV_CPU_CNTRS_OPS op);
+void				mvCpuCntrsInit(void);
+int					mvCpuCntrsStart(int idx, int event);
+
+void				mvCpuCntrsInitialize(void);
+MV_STATUS			mvCpuCntrsProgram(int counter, MV_CPU_CNTRS_OPS op, char *name, MV_U32 overhead);
+MV_CPU_CNTRS_EVENT	*mvCpuCntrsEventCreate(char *name, MV_U32 print_threshold);
+void				mvCpuCntrsEventDelete(MV_CPU_CNTRS_EVENT *event);
+void				mvCpuCntrsShow(MV_CPU_CNTRS_EVENT *pEvent);
+void				mvCpuCntrsEventClear(MV_CPU_CNTRS_EVENT *pEvent);
+
+
+#endif /* __mvCpuCntrs_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuL2Cntrs.c b/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuL2Cntrs.c
new file mode 100755
index 0000000..18120be
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuL2Cntrs.c
@@ -0,0 +1,128 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mvOs.h"
+#include "mvCpuL2Cntrs.h"
+
+MV_CPU_L2_CNTRS_ENTRY mvCpuL2CntrsTbl[MV_CPU_L2_CNTRS_NUM];
+
+MV_CPU_L2_CNTRS_EVENT *mvCpuL2CntrsEventTbl[128];
+
+void mvCpuL2CntrsReset(void)
+{
+	MV_U32 reg = 0;
+
+MV_ASM("mcr p15, 6, %0, c15, c13, 0" : : "r"(reg));
+MV_ASM("mcr p15, 6, %0, c15, c13, 1" : : "r"(reg));
+MV_ASM("mcr p15, 6, %0, c15, c13, 2" : : "r"(reg));
+MV_ASM("mcr p15, 6, %0, c15, c13, 3" : : "r"(reg));
+}
+
+static void mvCpuL2CntrConfig(int counter, int op)
+{
+	MV_U32 reg = (1 << op) | 0x1;	/*enable */
+
+	switch (counter) {
+	case 0:
+MV_ASM("mcr p15, 6, %0, c15, c12, 0" : : "r"(reg));
+		return;
+
+	case 1:
+MV_ASM("mcr p15, 6, %0, c15, c12, 1" : : "r"(reg));
+		return;
+
+	default:
+		mvOsPrintf("mvCpuL2CntrConfig: bad counter number (%d)\n", counter);
+	}
+	return;
+}
+
+void mvCpuL2CntrsEventClear(MV_CPU_L2_CNTRS_EVENT *pEvent)
+{
+	int i;
+
+	for (i = 0; i < MV_CPU_L2_CNTRS_NUM; i++)
+		pEvent->counters_sum[i] = 0;
+	pEvent->num_of_measurements = 0;
+}
+
+MV_CPU_L2_CNTRS_EVENT *mvCpuL2CntrsEventCreate(char *name, MV_U32 print_threshold)
+{
+	int i;
+	MV_CPU_L2_CNTRS_EVENT *event = mvOsMalloc(sizeof(MV_CPU_L2_CNTRS_EVENT));
+
+	if (event) {
+		strncpy(event->name, name, sizeof(event->name));
+		event->num_of_measurements = 0;
+		event->avg_sample_count = print_threshold;
+		for (i = 0; i < MV_CPU_L2_CNTRS_NUM; i++) {
+			event->counters_before[i] = 0;
+			event->counters_after[i] = 0;
+			event->counters_sum[i] = 0;
+		}
+	}
+	return event;
+}
+
+void mvCpuL2CntrsEventDelete(MV_CPU_L2_CNTRS_EVENT *event)
+{
+	if (event != NULL)
+		mvOsFree(event);
+}
+
+MV_STATUS mvCpuL2CntrsProgram(int counter, MV_CPU_L2_CNTRS_OPS op, char *name, MV_U32 overhead)
+{
+	strncpy(mvCpuL2CntrsTbl[counter].name, name, sizeof(mvCpuL2CntrsTbl[counter].name));
+	mvCpuL2CntrsTbl[counter].operation = op;
+	mvCpuL2CntrsTbl[counter].opIdx = op;
+	mvCpuL2CntrsTbl[counter].overhead = overhead;
+	mvCpuL2CntrConfig(counter, op);
+	mvOsPrintf("CPU L2 Counter %d: operation=%d, overhead=%d\n", counter, op, overhead);
+	return MV_OK;
+}
+
+void mvCpuL2CntrsShow(MV_CPU_L2_CNTRS_EVENT *pEvent)
+{
+	int i;
+	MV_U64 counters_avg;
+
+	if (pEvent->num_of_measurements < pEvent->avg_sample_count)
+		return;
+
+	mvOsPrintf("%16s: ", pEvent->name);
+	for (i = 0; i < MV_CPU_L2_CNTRS_NUM; i++) {
+		counters_avg = mvOsDivMod64(pEvent->counters_sum[i], pEvent->num_of_measurements, NULL);
+
+		if (counters_avg >= mvCpuL2CntrsTbl[i].overhead)
+			counters_avg -= mvCpuL2CntrsTbl[i].overhead;
+		else
+			counters_avg = 0;
+
+		mvOsPrintf("%s=%5llu, ", mvCpuL2CntrsTbl[i].name, counters_avg);
+	}
+	mvOsPrintf("\n");
+	mvCpuL2CntrsEventClear(pEvent);
+	mvCpuL2CntrsReset();
+}
+
+void mvCpuL2CntrsStatus(void)
+{
+	int i;
+
+	for (i = 0; i < MV_CPU_L2_CNTRS_NUM; i++)
+		mvOsPrintf("#%d: %s, overhead=%d\n", i, mvCpuL2CntrsTbl[i].name, mvCpuL2CntrsTbl[i].overhead);
+
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuL2Cntrs.h b/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuL2Cntrs.h
new file mode 100755
index 0000000..71b50b8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cpu/mvCpuL2Cntrs.h
@@ -0,0 +1,175 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __mvCpuL2Cntrs_h__
+#define __mvCpuL2Cntrs_h__
+
+#include "mvTypes.h"
+#include "mvOs.h"
+
+#define MV_CPU_L2_CNTRS_NUM         2
+
+typedef enum {
+	MV_CPU_L2_CNTRS_ENABLE = 0,
+	MV_CPU_L2_CNTRS_DATA_REQ,
+	MV_CPU_L2_CNTRS_DATA_MISS_REQ,
+	MV_CPU_L2_CNTRS_INST_REQ,
+	MV_CPU_L2_CNTRS_INST_MISS_REQ,
+	MV_CPU_L2_CNTRS_DATA_READ_REQ,
+	MV_CPU_L2_CNTRS_DATA_READ_MISS_REQ,
+	MV_CPU_L2_CNTRS_DATA_WRITE_REQ,
+	MV_CPU_L2_CNTRS_DATA_WRITE_MISS_REQ,
+	MV_CPU_L2_CNTRS_RESERVED,
+	MV_CPU_L2_CNTRS_DIRTY_EVICT_REQ,
+	MV_CPU_L2_CNTRS_EVICT_BUFF_STALL,
+	MV_CPU_L2_CNTRS_ACTIVE_CYCLES,
+
+} MV_CPU_L2_CNTRS_OPS;
+
+typedef struct {
+	char name[16];
+	MV_CPU_L2_CNTRS_OPS operation;
+	int opIdx;
+	MV_U32 overhead;
+
+} MV_CPU_L2_CNTRS_ENTRY;
+
+typedef struct {
+	char name[16];
+	MV_U32 num_of_measurements;
+	MV_U32 avg_sample_count;
+	MV_U64 counters_before[MV_CPU_L2_CNTRS_NUM];
+	MV_U64 counters_after[MV_CPU_L2_CNTRS_NUM];
+	MV_U64 counters_sum[MV_CPU_L2_CNTRS_NUM];
+
+} MV_CPU_L2_CNTRS_EVENT;
+
+MV_STATUS mvCpuL2CntrsProgram(int counter, MV_CPU_L2_CNTRS_OPS op, char *name, MV_U32 overhead);
+void mvCpuL2CntrsInit(void);
+MV_CPU_L2_CNTRS_EVENT *mvCpuL2CntrsEventCreate(char *name, MV_U32 print_threshold);
+void mvCpuL2CntrsEventDelete(MV_CPU_L2_CNTRS_EVENT *event);
+void mvCpuL2CntrsReset(void);
+void mvCpuL2CntrsShow(MV_CPU_L2_CNTRS_EVENT *pEvent);
+void mvCpuL2CntrsEventClear(MV_CPU_L2_CNTRS_EVENT *pEvent);
+
+static INLINE MV_U64 mvCpuL2CntrsRead(const int counter)
+{
+	MV_U32 low = 0, high = 0;
+
+	switch (counter) {
+	case 0:
+MV_ASM("mrc p15, 6, %0, c15, c13, 0" : "=r"(low));
+MV_ASM("mrc p15, 6, %0, c15, c13, 1" : "=r"(high));
+		break;
+
+	case 1:
+MV_ASM("mrc p15, 6, %0, c15, c13, 2" : "=r"(low));
+MV_ASM("mrc p15, 6, %0, c15, c13, 3" : "=r"(high));
+		break;
+
+	default:
+		mvOsPrintf("mvCpuL2CntrsRead: bad counter number (%d)\n", counter);
+	}
+	return (((MV_U64) high << 32) | low);
+
+}
+
+static INLINE void mvCpuL2CntrsReadBefore(MV_CPU_L2_CNTRS_EVENT *pEvent)
+{
+	int i;
+
+	for (i = 0; i < MV_CPU_L2_CNTRS_NUM; i++)
+		pEvent->counters_before[i] = mvCpuL2CntrsRead(i);
+}
+
+static INLINE void mvCpuL2CntrsReadAfter(MV_CPU_L2_CNTRS_EVENT *pEvent)
+{
+	int i;
+
+	for (i = 0; i < MV_CPU_L2_CNTRS_NUM; i++) {
+		pEvent->counters_after[i] = mvCpuL2CntrsRead(i);
+		pEvent->counters_sum[i] += (pEvent->counters_after[i] - pEvent->counters_before[i]);
+	}
+	pEvent->num_of_measurements++;
+}
+
+#ifdef CONFIG_MV_CPU_L2_PERF_CNTRS
+
+#define MV_CPU_L2_CNTRS_READ(counter)   mvCpuL2CntrsRead(counter)
+
+#define MV_CPU_L2_CNTRS_START(event)	mvCpuL2CntrsReadBefore(event)
+
+#define MV_CPU_L2_CNTRS_STOP(event)	    mvCpuL2CntrsReadAfter(event)
+
+#define MV_CPU_L2_CNTRS_SHOW(event)	    mvCpuL2CntrsShow(event)
+
+#else
+
+#define MV_CPU_L2_CNTRS_READ(counter)
+#define MV_CPU_L2_CNTRS_START(event)
+#define MV_CPU_L2_CNTRS_STOP(event)
+#define MV_CPU_L2_CNTRS_SHOW(event)
+
+#endif /* CONFIG_MV_CPU_L2_PERF_CNTRS */
+
+#endif /* __mvCpuL2Cntrs_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/cpu/pj4/mvPJ4Cntrs.c b/arch/arm/plat-feroceon/mv_hal/cpu/pj4/mvPJ4Cntrs.c
new file mode 100755
index 0000000..d0c4f39
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cpu/pj4/mvPJ4Cntrs.c
@@ -0,0 +1,94 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mvOs.h"
+#include "mvCpuCntrs.h"
+
+int		mvCpuCntrsMap(int counter, MV_CPU_CNTRS_OPS op)
+{
+	int	event;
+
+	switch (op) {
+	case MV_CPU_CNTRS_CYCLES:
+		event = MRVL_PJ4B_CYCLE_COUNT;
+		break;
+
+	case MV_CPU_CNTRS_INSTRUCTIONS:
+		event = MRVL_PJ4B_INSN_EXECUTED;
+		break;
+
+	case MV_CPU_CNTRS_ICACHE_READ_MISS:
+		event = MRVL_PJ4B_ICACHE_READ_MISS;
+		break;
+
+	case MV_CPU_CNTRS_DCACHE_READ_MISS:
+		event = MRVL_PJ4B_DCACHE_READ_MISS;
+		break;
+
+	case MV_CPU_CNTRS_DCACHE_WRITE_MISS:
+		event = MRVL_PJ4B_DCACHE_WRITE_MISS;
+		break;
+
+	case MV_CPU_CNTRS_DTLB_MISS:
+		event = MRVL_PJ4B_DTLB_MISS;
+		break;
+
+	default:
+		mvOsPrintf("invalid CPU counters event %d\n", op);
+			return -1;
+	}
+	return event;
+}
+
+
+int	mvCpuCntrsStart(int idx, int event)
+{
+	u32 enable;
+
+	if (idx == MRVL_PJ4B_CCNT) {
+		enable = (1 << MRVL_PJ4B_CCNT_BIT_OFFSET);
+	} else if (idx < MRVL_PJ4B_MAX_COUNTERS) {
+		enable = (1 << (idx - MRVL_PJ4B_PMN0));
+	} else {
+		mvOsPrintf("invalid counter number (%d)\n", idx);
+		return 1;
+	}
+	mrvl_pj4b_pmu_cntr_disable(enable);
+	if (idx != MRVL_PJ4B_CCNT) {
+		/* select event */
+		if (evt >= MRVL_PJ4B_EVT_UNUSED)
+			return 1;
+
+		mrvl_pj4b_pmu_select_event((idx - MRVL_PJ4B_PMN0), evt);
+	}
+	mrvl_pj4b_pmu_cntr_enable(enable);
+	return 0;
+}
+
+void	mvCpuCntrsInit(void)
+{
+	MV_U32	pmnc;
+
+	mvCpuCntrsReset();
+
+	pmnc = mrvl_pj4b_read_pmnc();
+
+	pmnc &= ~MRVL_PJ4B_PMU_RESET;
+	pmnc |= MRVL_PJ4B_PMU_ENABLE;
+
+	mrvl_pj4b_write_pmnc(pmnc);
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/cpu/pj4/mvPJ4Cntrs.h b/arch/arm/plat-feroceon/mv_hal/cpu/pj4/mvPJ4Cntrs.h
new file mode 100755
index 0000000..dd49baa
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/cpu/pj4/mvPJ4Cntrs.h
@@ -0,0 +1,300 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __mvPJ4Cntrs_h__
+#define __mvPJ4Cntrs_h__
+
+#define MV_CPU_CNTR_SIZE			32 /* bits */
+
+#define MRVL_PJ4B_CCNT_BIT_OFFSET 	31
+
+#define	MRVL_PJ4B_PMU_ENABLE	0x001	/* Enable counters */
+#define MRVL_PJ4B_PMN_RESET		0x002	/* Reset event counters */
+#define	MRVL_PJ4B_CCNT_RESET	0x004	/* Reset cycles counter */
+#define	MRVL_PJ4B_PMU_RESET		(MRVL_PJ4B_CCNT_RESET | MRVL_PJ4B_PMN_RESET)
+#define MRVL_PJ4B_PMU_CNT64		0x008	/* Make CCNT count every 64th cycle */
+
+/*
+* Different types of events that can be counted by the Marvell PJ4 Performance Monitor
+*
+*/
+enum mrvl_pj4b_perf_types  {
+	MRVL_PJ4B_SOFTWARE_INCR = 0x00,	/* software increment */
+	MRVL_PJ4B_IFU_IFETCH_REFILL = 0x01, 	/* instruction fetch that cause a refill */
+						/* at the lowest level of instruction or unified cache */
+	MRVL_PJ4B_IF_TLB_REFILL = 0x02,		/* instruction fetch that cause a TLB refill at the lowest level of TLB */
+	MRVL_PJ4B_DATA_RW_CACHE_REFILL = 0x03,	/* data read or write operation that causes a refill of */
+						/* at the lowest level of data or unified cache */
+	MRVL_PJ4B_DATA_RW_CACHE_ACCESS = 0x04,	/* data read or write operation that causes a cache access */
+						/* at the lowest level of data or unified cache */
+	MRVL_PJ4B_DATA_RW_TLB_REFILL = 0x05,	/* data read or write operation that causes a TLB refill */
+						/* at the lowest level of TLB */
+	MRVL_PJ4B_DATA_READ_INST_EXEC = 0x06,	/* data read architecturally executed */
+	MRVL_PJ4B_DATA_WRIT_INST_EXEC = 0x07,	/* data write architecturally executed */
+	MRVL_PJ4B_INSN_EXECUTED = 0x08,		/* instruction architecturally executed */
+	MRVL_PJ4B_EXCEPTION_TAKEN = 0x09,	/* exception taken */
+	MRVL_PJ4B_EXCEPTION_RETURN = 0x0a,	/* exception return architecturally executed */
+	MRVL_PJ4B_INSN_WR_CONTEXTIDR = 0x0b,	/* instruction that writes to the Context ID Register */
+						/* architecturally executed */
+	MRVL_PJ4B_SW_CHANGE_PC = 0x0c,		/* software change of PC, except by an exception, architecturally executed */
+	MRVL_PJ4B_BR_EXECUTED = 0x0d,		/* immediate branch architecturally executed, taken or not taken */
+	MRVL_PJ4B_PROCEDURE_RETURN = 0x0e,	/* procedure return architecturally executed */
+	MRVL_PJ4B_UNALIGNED_ACCESS = 0x0f,	/* unaligned access architecturally executed */
+	MRVL_PJ4B_BR_INST_MISS_PRED = 0x10,	/* branch mispredicted or not predicted */
+	MRVL_PJ4B_CYCLE_COUNT = 0x11,		/* cycle count */
+	MRVL_PJ4B_BR_PRED_TAKEN = 0x12,		/* branches or other change in the program flow */
+						/* that could have been predicted */
+						/* by the branch prediction resources of the processor */
+	MRVL_PJ4B_DCACHE_READ_HIT = 0x40,	/* counts the number of Data Cache read hits */
+	MRVL_PJ4B_DCACHE_READ_MISS = 0x41,	/* connts the number of Data Cache read misses */
+	MRVL_PJ4B_DCACHE_WRITE_HIT = 0x42,	/* counts the number of Data Cache write hits */
+	MRVL_PJ4B_DCACHE_WRITE_MISS = 0x43,	/* counts the number of Data Cache write misses */
+	MRVL_PJ4B_MMU_BUS_REQUEST = 0x44,	/* counts the number of cycles of request to the MMU Bus */
+	MRVL_PJ4B_ICACHE_BUS_REQUEST = 0x45,	/* counts the number of cycles the Instruction Cache requests the bus */
+						/* until the data return */
+	MRVL_PJ4B_WB_WRITE_LATENCY = 0x46,	/* counts the number of cycles the Write Buffer requests the bus */
+	MRVL_PJ4B_HOLD_LDM_STM = 0x47,		/* counts the number of cycles the pipeline is held */
+						/* because of a load/store multiple instruction */
+	MRVL_PJ4B_NO_DUAL_CFLAG = 0x48,		/* counts the number of cycles the processor cannot dual issue */
+						/* because of a Carry flag dependency */
+	MRVL_PJ4B_NO_DUAL_REGISTER_PLUS = 0x49,	/* counts the number of cycles the processor cannot dual issue because */
+						/* the register file does not have enough read ports and at least one other reason */
+	MRVL_PJ4B_LDST_ROB0_ON_HOLD = 0x4a,	/* counts the number of cycles a load or store instruction waits */
+						/* to retire from ROB0 */
+	MRVL_PJ4B_LDST_ROB1_ON_HOLD = 0x4b,	/* counts the number of cycles a load or store instruction waits */
+						/* to retire from ROB0=1 */
+	MRVL_PJ4B_DATA_WRITE_ACCESS_COUNT = 0x4c, 	/* counts the number of any Data write access */
+	MRVL_PJ4B_DATA_READ_ACCESS_COUNT = 0x4d, 	/* counts the number of any Data read access */
+	MRVL_PJ4B_A2_STALL = 0x4e, 		/* counts the number of cycles ALU A2 is stalled */
+	/*TODO: implement with fabric counters*/
+	MRVL_PJ4B_L2C_WRITE_HIT = 0x4f, 	/* counts the number of write accesses to addresses already in the L2C */
+	MRVL_PJ4B_L2C_WRITE_MISS = 0x50,	/* counts the number of write accesses to addresses not in the L2C */
+	MRVL_PJ4B_L2C_READ_COUNT = 0x51,	/* counts the number of L2C cache-to-bus external read request */
+	/*TODO: end*/
+	MRVL_PJ4B_ICACHE_READ_MISS = 0x60, 	/* counts the number of Instruction Cache read misses */
+	MRVL_PJ4B_ITLB_MISS = 0x61, 		/* counts the number of instruction TLB miss */
+	MRVL_PJ4B_SINGLE_ISSUE = 0x62, 		/* counts the number of cycles the processor single issues */
+	MRVL_PJ4B_BR_RETIRED = 0x63, 		/* counts the number of times one branch retires */
+	MRVL_PJ4B_ROB_FULL = 0x64, 		/* counts the number of cycles the Re-order Buffer (ROB) is full */
+	MRVL_PJ4B_MMU_READ_BEAT = 0x65, 	/* counts the number of times the bus returns RDY to the MMU */
+	MRVL_PJ4B_WB_WRITE_BEAT = 0x66, 	/* counts the number times the bus returns ready to the Write Buffer */
+	MRVL_PJ4B_DUAL_ISSUE = 0x67, 		/* counts the number of cycles the processor dual issues */
+	MRVL_PJ4B_NO_DUAL_RAW = 0x68, 		/* counts the number of cycles the processor cannot dual issue */
+						/* because of a Read after Write hazard */
+	MRVL_PJ4B_HOLD_IS = 0x69, 		/* counts the number of cycles the issue is held */
+	/*TODO: implement with fabric counters*/
+	MRVL_PJ4B_L2C_LATENCY = 0x6a, 		/* counts the latency for the most recent L2C read */
+						/* from the external bus Counts cycles */
+	/*TODO: end*/
+	MRVL_PJ4B_DCACHE_ACCESS = 0x70, 	/* counts the number of times the Data cache is accessed */
+	MRVL_PJ4B_DTLB_MISS = 0x71, 		/* counts the number of data TLB misses */
+	MRVL_PJ4B_BR_PRED_MISS = 0x72, 		/* counts the number of mispredicted branches */
+	MRVL_PJ4B_A1_STALL = 0x74, 		/* counts the number of cycles ALU A1 is stalled */
+	MRVL_PJ4B_DCACHE_READ_LATENCY = 0x75, 	/* counts the number of cycles the Data cache requests the bus for a read */
+	MRVL_PJ4B_DCACHE_WRITE_LATENCY = 0x76, 	/* counts the number of cycles the Data cache requests the bus */
+						/* for a write */
+	MRVL_PJ4B_NO_DUAL_REGISTER_FILE = 0x77, /* counts the number of cycles the processor cannot dual issue */
+						/* because the register file doesn't have enough read ports */
+	MRVL_PJ4B_BIU_SIMULTANEOUS_ACCESS = 0x78, 	/* BIU Simultaneous Access */
+	MRVL_PJ4B_L2C_READ_HIT = 0x79, 		/* counts the number of L2C cache-to-bus external read requests */
+	MRVL_PJ4B_L2C_READ_MISS = 0x7a, 	/* counts the number of L2C read accesses that resulted */
+						/* in an external read request */
+	MRVL_PJ4B_L2C_EVICTION = 0x7b, 		/* counts the number of evictions (CastOUT) of a line from the L2 cache */
+	MRVL_PJ4B_TLB_MISS = 0x80, 		/* counts the number of instruction and data TLB misses */
+	MRVL_PJ4B_BR_TAKEN = 0x81, 		/* counts the number of taken branches */
+	MRVL_PJ4B_WB_FULL = 0x82, 		/* counts the number of cycles WB is full */
+	MRVL_PJ4B_DCACHE_READ_BEAT = 0x83, 	/* counts the number of times the bus returns Data to */
+						/* the Data cache during read request */
+	MRVL_PJ4B_DCACHE_WRITE_BEAT = 0x84, 	/* counts the number of times the bus returns ready to */
+						/* the Data cache during write request */
+	MRVL_PJ4B_NO_DUAL_HW = 0x85, 		/* counts the number of cycles the processor cannot dual issue */
+						/* because of hardware conflict */
+	MRVL_PJ4B_NO_DUAL_MULTIPLE = 0x86, 	/* counts the number of cycles the processor cannot dual issue */
+						/* because of multiple reasons */
+	MRVL_PJ4B_BIU_ANY_ACCESS = 0x87, 	/* counts the number of cycles the BIU is accessed by any unit */
+	MRVL_PJ4B_MAIN_TLB_REFILL_BY_ICACHE = 0x88, 	/* counts the number of instruction fetch operations */
+							/* that causes a Main TLB walk */
+	MRVL_PJ4B_MAIN_TLB_REFILL_BY_DCACHE = 0x89, 	/* counts the number of Data read or write operations */
+							/* that causes a Main TLB walk */
+	MRVL_PJ4B_ICACHE_READ_BEAT = 0x8a, 	/* counts the number of times the bus returns RDY to the instruction cache */
+	MRVL_PJ4B_PMUEXT_IN0 = 0x90, 		/* counts any event from external input source PMUEXTIN[0] */
+	MRVL_PJ4B_PMUEXT_IN1 = 0x91, 		/* counts any event from external input source PMUEXTIN[1] */
+	MRVL_PJ4B_PMUEXT_IN0_IN1 = 0x92, 	/* counts any event from both external input sources PMUEXTIN[0] */
+						/* and PMUEXTIN[1] */
+	MRVL_PJ4B_WMMX2_STORE_FIFO_FULL = 0xc0, /* counts the number of cycles when the WMMX2 store FIFO is full */
+	MRVL_PJ4B_WMMX2_FINISH_FIFO_FULL = 0xc1,/* counts the number of cycles when the WMMX2 finish FIFO is full */
+	MRVL_PJ4B_WMMX2_INST_FIFO_FULL = 0xc2, 	/* counts the number of cycles when the WMMX2 instruction FIFO is full */
+	MRVL_PJ4B_WMMX2_INST_RETIRED = 0xc3, 	/* counts the number of retired WMMX2 instructions */
+	MRVL_PJ4B_WMMX2_BUSY = 0xc4, 		/* counts the number of cycles when the WMMX2 is busy */
+	MRVL_PJ4B_WMMX2_HOLD_MI = 0xc5, 	/* counts the number of cycles when WMMX2 holds the issue stage */
+	MRVL_PJ4B_WMMX2_HOLD_MW = 0xc6, 	/* counts the number of cycles when WMMX2 holds the write back stage */
+	/* EVT_CCNT is not hardware defined */
+	MRVL_PJ4B_EVT_CCNT = 0xFE,		/* CPU_CYCLE */
+	MRVL_PJ4B_EVT_UNUSED = 0xFF,
+};
+
+enum  pj4b_pmu_counters {
+	MRVL_PJ4B_CCNT = 0,
+	MRVL_PJ4B_PMN0,
+	MRVL_PJ4B_PMN1,
+	MRVL_PJ4B_PMN2,
+	MRVL_PJ4B_PMN3,
+	MRVL_PJ4B_PMN4,
+	MRVL_PJ4B_PMN5,
+	MRVL_PJ4B_MAX_COUNTERS
+};
+
+
+static inline void mrvl_pj4b_pmu_intr_disable(u32 val)
+{
+	asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r"(val));
+}
+
+static inline void mrvl_pj4b_pmu_cntr_disable(u32 val)
+{
+	asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(val));
+}
+
+static inline void mrvl_pj4b_pmu_intr_enable(u32 val)
+{
+	asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r"(val));
+}
+
+static inline void mrvl_pj4b_pmu_cntr_enable(u32 val)
+{
+	asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(val));
+}
+
+static inline void mrvl_pj4b_pmu_select_event(u32 cntr, u32 evt)
+{
+	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(cntr));
+	asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r"(evt));
+}
+
+
+static inline void mrvl_pj4b_write_pmnc(u32 val)
+{
+	asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
+}
+
+static inline u32 mrvl_pj4b_read_pmnc(void)
+{
+	u32 val;
+
+	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
+
+	return val;
+}
+
+static INLINE MV_U64 mvCpuPmCntrRead(const int counter)
+{
+	MV_U32 val;
+
+	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(counter));
+	asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r"(val));
+
+	return (MV_U64)val;
+}
+
+static INLINE MV_U64 mvCpuCyclesCntrRead(void)
+{
+	MV_U32 val;
+
+	asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
+
+	return (MV_U64)val;
+}
+
+/* Read counter register */
+static INLINE MV_U64 mvCpuCntrsRead(const int counter)
+{
+	MV_U64 val = 0;
+
+	switch (counter) {
+	case MRVL_PJ4B_CCNT:
+		val = mvCpuCyclesCntrRead();
+		break;
+
+	case MRVL_PJ4B_PMN0:
+	case MRVL_PJ4B_PMN1:
+	case MRVL_PJ4B_PMN2:
+	case MRVL_PJ4B_PMN3:
+	case MRVL_PJ4B_PMN4:
+	case MRVL_PJ4B_PMN5:
+		val = mvCpuPmCntrRead(counter - MRVL_PJ4B_PMN0);
+		break;
+	}
+	return (MV_U64)val;
+}
+
+static INLINE void mvCpuCntrsReset(void)
+{
+	MV_U32	reg;
+
+	reg = mrvl_pj4b_read_pmnc();
+	reg |= MRVL_PJ4B_PMU_RESET;
+	mrvl_pj4b_write_pmnc(reg);
+}
+
+
+#endif /* __mvPJ4Cntrs_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/ddr2/mvCompVer.txt
new file mode 100755
index 0000000..5f39390
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.4
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramCounters.h b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramCounters.h
new file mode 100755
index 0000000..933ee67
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramCounters.h
@@ -0,0 +1,268 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvDramCountersh
+#define __INCmvDramCountersh
+
+/* includes */
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysDdrConfig.h"
+#include "mvDramIfRegs.h"
+
+#define SDRAM_STAT_CNTRS_CTRL  			(MV_DDR_REGS_BASE + 0x1590)
+#define SDRAM_STAT_CNTR_SELECT_OFFSET(c)	((c == 0) ? 0 : 8)
+#define SDRAM_STAT_CNTR_SELECT_MASK(c)		(0x1F << SDRAM_STAT_CNTR_SELECT_OFFSET(c))
+#define SDRAM_STAT_CNTR_RESET_OFFSET		16
+#define SDRAM_STAT_CNTR_RESET_MASK		(0x1 << SDRAM_STAT_CNTR_RESET_OFFSET)
+#define SDRAM_STAT_CNTR_START_OFFSET		17
+#define SDRAM_STAT_CNTR_START_MASK		(0x1 << SDRAM_STAT_CNTR_START_OFFSET)
+
+#define SDRAM_STAT_CNTRS_VAL(set, idx)		(MV_DDR_REGS_BASE + 0x1594 + (set << 3) + (idx << 2))
+#define SDRAM_STAT_HCLK_VAL(idx)		(MV_DDR_REGS_BASE + 0x15A4 + (idx << 2))
+
+typedef enum {
+	MBUSL_CACHE_READ = 0,
+	MBUSL_BURST_READ,
+	MBUSL_PAR_READ,
+	MBUSL_CACHE_WRITE,
+	MBUSL_BURST_WRITE,
+	MBUSL_UNSPEC_WRITE,
+	MBUSL_FULL_PAR_WRITE,
+	MBUSL_SEMI_PAR_WRITE,
+	MBUSL_TOTAL_READS,
+	MBUSL_TOTAL_WRITES,
+	MBUSL_TOTAL_TRANS,
+	MBUSL0_TOTAL_TRANS,
+	MBUSL1_TOTAL_TRANS,
+	MBUSL_LOOKUP_HIT,
+	MBUS_CACHE_READ,
+	MBUS_BURST_READ,
+	MBUS_PAR_READ,
+	MBUS_CACHE_WRITE,
+	MBUS_CACHE_WRITE_RMW,
+	MBUS_BURST_WRITE,
+	MBUS_BURST_WRITE_RMW,
+	MBUS_PAR_WRITE,
+	MBUS_PAR_WRITE_RMW,
+	MBUS_TOTAL_READS,
+	MBUS_TOTAL_WRITES,
+	MBUS_TOTAL_TRANS,
+	MBUS0_TOTAL_TRANS,
+	MBUS1_TOTAL_TRANS,
+	MBUS_BURST_CHOP,
+	NUM_BURSTS_128BIT,
+	DRAM_ACTIVE,
+	DRAM_PRECHARGE
+} MV_DRAM_STAT_MODE;
+
+/*******************************************************************************
+* mvDramStatStart
+*
+* DESCRIPTION:
+*       Start DRAM statistics counters.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static inline void mvDramStatStart(void)
+{
+	MV_REG_BIT_SET(SDRAM_STAT_CNTRS_CTRL, SDRAM_STAT_CNTR_START_MASK);
+}
+
+/*******************************************************************************
+* mvDramStatStop
+*
+* DESCRIPTION:
+*       Stop DRAM statistics counters.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static inline void mvDramStatStop(void)
+{
+	MV_REG_BIT_RESET(SDRAM_STAT_CNTRS_CTRL, SDRAM_STAT_CNTR_START_MASK);
+}
+
+/*******************************************************************************
+* mvDramStatClear
+*
+* DESCRIPTION:
+*       Clear the DRAM statistics counters.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static inline void mvDramStatClear(void)
+{
+	MV_U32 reg;
+
+	MV_REG_BIT_SET(SDRAM_STAT_CNTRS_CTRL, SDRAM_STAT_CNTR_RESET_MASK);
+	do {
+		reg = MV_REG_READ(SDRAM_STAT_CNTRS_CTRL);
+	} while (reg & SDRAM_STAT_CNTR_RESET_MASK);
+
+	return;
+}
+
+/*******************************************************************************
+* mvDramStatConfig
+*
+* DESCRIPTION:
+*       Configure the DRAM statistics counters.
+*
+* INPUT:
+*       cntIdx	- The counter index to configure.
+*	mode	- The mode to configure the counter.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+static inline MV_STATUS mvDramStatConfig(MV_U8 cntIdx, MV_DRAM_STAT_MODE mode)
+{
+	MV_U32 reg;
+
+	reg = MV_REG_READ(SDRAM_STAT_CNTRS_CTRL);
+	reg &= ~SDRAM_STAT_CNTR_SELECT_MASK(cntIdx);
+	reg |= (mode << SDRAM_STAT_CNTR_SELECT_OFFSET(cntIdx));
+	MV_REG_WRITE(SDRAM_STAT_CNTRS_CTRL, reg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDramStatRead
+*
+* DESCRIPTION:
+*       Read the current DRAM statistics value.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*       counter0 - Value of DRAM statistics counter #0.
+*       counter1 - Value of DRAM statistics counter #1.
+*	hclk	 - Value of HCLK counter.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+static inline MV_STATUS mvDramStatRead(MV_U64 *counter0, MV_U64 *counter1, MV_U64 *hclk)
+{
+	MV_U32 val;
+
+	if (counter0 != NULL) {
+		val = MV_REG_READ(SDRAM_STAT_CNTRS_VAL(0, 0));
+		*counter0 = val;
+		val = MV_REG_READ(SDRAM_STAT_CNTRS_VAL(0, 1));
+		*counter0 |= ((MV_U64) val << 32);
+	}
+
+	if (counter1 != NULL) {
+		val = MV_REG_READ(SDRAM_STAT_CNTRS_VAL(1, 0));
+		*counter1 = val;
+		val = MV_REG_READ(SDRAM_STAT_CNTRS_VAL(1, 1));
+		*counter1 |= ((MV_U64) val << 32);
+	}
+
+	if (hclk != NULL) {
+		val = MV_REG_READ(SDRAM_STAT_HCLK_VAL(0));
+		*hclk = val;
+		val = MV_REG_READ(SDRAM_STAT_HCLK_VAL(1));
+		*hclk |= ((MV_U64) val << 32);
+	}
+
+	return MV_OK;
+}
+
+#endif /* __INCmvDramCountersh */
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIf.c b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIf.c
new file mode 100755
index 0000000..889a695
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIf.c
@@ -0,0 +1,1993 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* includes */
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysDdrConfig.h"
+#include "ddr2/mvDramIf.h"
+#include "mvDramIfRegs.h"
+/* #include "ctrlEnv/sys/mvCpuIf.h" */
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ddr2/mvDramIfStaticInit.h"
+#include "spd/mvSpd.h"
+
+/* #define MV_DEBUG */
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+/* DRAM bank presence encoding */
+#define BANK_PRESENT_CS0			    0x1
+#define BANK_PRESENT_CS0_CS1			0x3
+#define BANK_PRESENT_CS0_CS2			0x5
+#define BANK_PRESENT_CS0_CS1_CS2		0x7
+#define BANK_PRESENT_CS0_CS2_CS3		0xd
+#define BANK_PRESENT_CS0_CS2_CS3_CS4	0xf
+
+/* locals   */
+#ifndef MV_STATIC_DRAM_ON_BOARD
+static void sdramDDr2OdtConfig(MV_DRAM_BANK_INFO *pBankInfo);
+static MV_U32 dunitCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas, MV_U32 busClk, MV_STATUS TTmode);
+static MV_U32 dunitCtrlHighRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk);
+static MV_U32 sdramModeRegCalc(MV_U32 minCas);
+static MV_U32 sdramExtModeRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk);
+static MV_U32 sdramAddrCtrlRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_DRAM_BANK_INFO *pBankInfoDIMM1);
+static MV_U32 sdramConfigRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_DRAM_BANK_INFO *pBankInfo2, MV_U32 busClk);
+static MV_U32 minCasCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_DRAM_BANK_INFO *pBankInfo2, MV_U32 busClk, MV_U32 forcedCl);
+static MV_U32 sdramTimeCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas, MV_U32 busClk);
+static MV_U32 sdramTimeCtrlHighRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk);
+static MV_U32 sdramDdr2TimeLoRegCalc(MV_U32 minCas);
+static MV_U32 sdramDdr2TimeHiRegCalc(MV_U32 minCas);
+#endif
+MV_32 DRAM_CS_Order[MV_DRAM_MAX_CS] = { N_A
+#ifdef MV_INCLUDE_SDRAM_CS1
+	    , N_A
+#endif
+#ifdef MV_INCLUDE_SDRAM_CS2
+	    , N_A
+#endif
+#ifdef MV_INCLUDE_SDRAM_CS3
+	    , N_A
+#endif
+};
+
+/* Get DRAM size of CS num */
+MV_U32 mvDramCsSizeGet(MV_U32 csNum)
+{
+	MV_DRAM_BANK_INFO bankInfo;
+	MV_U32 size, deviceW, dimmW;
+#ifdef MV78XX0
+	MV_U32 temp;
+#endif
+
+	if (MV_OK == mvDramBankInfoGet(csNum, &bankInfo)) {
+		if (0 == bankInfo.size)
+			return 0;
+
+		/* Note that the Dimm width might be different then the device DRAM width */
+#ifdef MV78XX0
+		temp = MV_REG_READ(SDRAM_CONFIG_REG);
+		deviceW = ((temp & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_32BIT) ? 32 : 64;
+#else
+		deviceW = 16 /* KW family */ ;
+#endif
+		dimmW = bankInfo.dataWidth - (bankInfo.dataWidth % 16);
+		size = ((bankInfo.size << 20) / (dimmW / deviceW));
+		return size;
+	} else
+		return 0;
+}
+
+/*******************************************************************************
+* mvDramIfDetect - Prepare DRAM interface configuration values.
+*
+* DESCRIPTION:
+*       This function implements the full DRAM detection and timing
+*       configuration for best system performance.
+*       Since this routine runs from a ROM device (Boot Flash), its stack
+*       resides on RAM, that might be the system DRAM. Changing DRAM
+*       configuration values while keeping vital data in DRAM is risky. That
+*       is why the function does not preform the configuration setting but
+*       prepare those in predefined 32bit registers (in this case IDMA
+*       registers are used) for other routine to perform the settings.
+*       The function will call for board DRAM SPD information for each DRAM
+*       chip select. The function will then analyze those SPD parameters of
+*       all DRAM banks in order to decide on DRAM configuration compatible
+*       for all DRAM banks.
+*       The function will set the CPU DRAM address decode registers.
+*       Note: This routine prepares values that will overide configuration of
+*       mvDramBasicAsmInit().
+*
+* INPUT:
+*       forcedCl - Forced CAL Latency. If equal to zero, do not force.
+*       eccDisable - Force down the ECC.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_STATUS mvDramIfDetect(MV_U32 forcedCl, MV_BOOL eccDisable, MV_U32 sysClk)
+{
+#ifndef MV_STATIC_DRAM_ON_BOARD
+	MV_32 MV_DRAM_CS_order[MV_DRAM_MAX_CS] = {
+		SDRAM_CS0
+#ifdef MV_INCLUDE_SDRAM_CS1
+		    , SDRAM_CS1
+#endif
+#ifdef MV_INCLUDE_SDRAM_CS2
+		    , SDRAM_CS2
+#endif
+#ifdef MV_INCLUDE_SDRAM_CS3
+		    , SDRAM_CS3
+#endif
+	};
+#endif
+	MV_U32 busClk;
+#ifndef MV_STATIC_DRAM_ON_BOARD
+	MV_U32 deviceW, dimmW;
+	MV_U32 numOfAllDevices = 0;
+	MV_STATUS TTMode;
+	MV_DRAM_BANK_INFO bankInfo[MV_DRAM_MAX_CS];
+	MV_U32 size, base = 0, i, j, temp, busClkPs;
+	MV_U8 minCas;
+	MV_DRAM_DEC_WIN dramDecWin;
+	dramDecWin.addrWin.baseHigh = 0;
+#endif
+
+	busClk = sysClk;
+
+	if (0 == busClk) {
+		mvOsPrintf("Dram: ERR. Can't detect system clock! \n");
+		return MV_ERROR;
+	}
+#ifndef MV_STATIC_DRAM_ON_BOARD
+
+	busClkPs = 1000000000 / (busClk / 1000);	/* in ps units */
+	/* we will use bank 0 as the representative of the all the DRAM banks,  */
+	/* since bank 0 must exist.                                             */
+	for (i = 0; i < MV_DRAM_MAX_CS; i++) {
+		/* if Bank exist */
+		if (MV_OK == mvDramBankInfoGet(i, &bankInfo[i])) {
+			DB(mvOsPrintf("Dram: Find bank %d\n", i));
+			/* check it isn't SDRAM */
+			if (bankInfo[i].memoryType != MEM_TYPE_DDR2) {
+				mvOsOutput("Dram: ERR. SDRAM type not supported !!!\n");
+				return MV_ERROR;
+			}
+
+			/* All banks must support the Mclk freqency */
+			if (bankInfo[i].minCycleTimeAtMaxCasLatPs > busClkPs) {
+				mvOsOutput("Dram: ERR. Bank %d doesn't support memory clock!!!\n", i);
+				return MV_ERROR;
+			}
+
+			/* All banks must support registry in order to activate it */
+			if (bankInfo[i].registeredAddrAndControlInputs != bankInfo[0].registeredAddrAndControlInputs) {
+				mvOsOutput("Dram: ERR. different Registered settings !!!\n");
+				return MV_ERROR;
+			}
+
+			/* All banks must support same ECC mode */
+			if (bankInfo[i].errorCheckType != bankInfo[0].errorCheckType) {
+				mvOsOutput("Dram: ERR. different ECC settings !!!\n");
+				return MV_ERROR;
+			}
+		} else {
+			/* bank 0 doesn't exist */
+			if (i == 0) {
+				mvOsOutput("Dram: ERR. Fail to detect bank 0 !!!\n");
+				return MV_ERROR;
+			} else {
+				DB(mvOsPrintf("Dram: Could not find bank %d\n", i));
+				bankInfo[i].size = 0;	/* Mark this bank as non exist */
+			}
+		}
+	}
+
+#ifdef MV_INCLUDE_SDRAM_CS2
+	if (bankInfo[SDRAM_CS0].size < bankInfo[SDRAM_CS2].size) {
+		MV_DRAM_CS_order[0] = SDRAM_CS2;
+		MV_DRAM_CS_order[1] = SDRAM_CS3;
+		MV_DRAM_CS_order[2] = SDRAM_CS0;
+		MV_DRAM_CS_order[3] = SDRAM_CS1;
+		DRAM_CS_Order[0] = SDRAM_CS2;
+		DRAM_CS_Order[1] = SDRAM_CS3;
+		DRAM_CS_Order[2] = SDRAM_CS0;
+		DRAM_CS_Order[3] = SDRAM_CS1;
+	} else
+#endif
+	{
+		MV_DRAM_CS_order[0] = SDRAM_CS0;
+		MV_DRAM_CS_order[1] = SDRAM_CS1;
+		DRAM_CS_Order[0] = SDRAM_CS0;
+		DRAM_CS_Order[1] = SDRAM_CS1;
+#ifdef MV_INCLUDE_SDRAM_CS2
+		MV_DRAM_CS_order[2] = SDRAM_CS2;
+		MV_DRAM_CS_order[3] = SDRAM_CS3;
+		DRAM_CS_Order[2] = SDRAM_CS2;
+		DRAM_CS_Order[3] = SDRAM_CS3;
+#endif
+	}
+
+	for (j = 0; j < MV_DRAM_MAX_CS; j++) {
+		i = MV_DRAM_CS_order[j];
+
+		if (0 == bankInfo[i].size)
+			continue;
+
+		/* Init the CPU window decode */
+		/* Note that the Dimm width might be different then the device DRAM width */
+#ifdef MV78XX0
+		temp = MV_REG_READ(SDRAM_CONFIG_REG);
+		deviceW = ((temp & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_32BIT) ? 32 : 64;
+#else
+		deviceW = 16 /* KW family */ ;
+#endif
+		dimmW = bankInfo[0].dataWidth - (bankInfo[0].dataWidth % 16);
+		size = ((bankInfo[i].size << 20) / (dimmW / deviceW));
+
+		/* We can not change DRAM window settings while excecuting      */
+		/* code from it. That is why we skip the DRAM CS[0], saving     */
+		/* it to the ROM configuration routine                          */
+
+		numOfAllDevices += bankInfo[i].numberOfDevices;
+		if (i == MV_DRAM_CS_order[0]) {
+			MV_U32 sizeToReg;
+			/* Translate the given window size to register format           */
+			sizeToReg = ctrlSizeToReg(size, SCSR_SIZE_ALIGNMENT);
+			/* Size parameter validity check.                           */
+			if (-1 == sizeToReg) {
+				mvOsOutput("DRAM: ctrlSizeToReg: ERR. Win %d size invalid.\n", i);
+				return MV_BAD_PARAM;
+			}
+
+			DB(mvOsPrintf("Dram: Bank 0 Size - %x\n", sizeToReg);
+			    )
+			    sizeToReg = (sizeToReg << SCSR_SIZE_OFFS);
+			sizeToReg |= SCSR_WIN_EN;
+			MV_REG_WRITE(DRAM_BUF_REG0, sizeToReg);
+		} else {
+			dramDecWin.addrWin.baseLow = base;
+			dramDecWin.addrWin.size = size;
+			dramDecWin.enable = MV_TRUE;
+			DB(mvOsPrintf("Dram: Enable window %d base 0x%x, size=0x%x\n", i, base, size));
+
+			/* Check if the DRAM size is more then 3GByte */
+			if (base < 0xC0000000) {
+				DB(mvOsPrintf("Dram: Enable window %d base 0x%x, size=0x%x\n", i, base, size));
+				if (MV_OK != mvDramIfWinSet(i, &dramDecWin)) {
+					mvOsPrintf("Dram: ERR. Fail to set bank %d!!!\n", SDRAM_CS0 + i);
+					return MV_ERROR;
+				}
+			}
+		}
+
+		base += size;
+
+		/* update the suportedCasLatencies mask */
+		bankInfo[0].suportedCasLatencies &= bankInfo[i].suportedCasLatencies;
+	}
+
+	/* calculate minimum CAS */
+	minCas = minCasCalc(&bankInfo[0], &bankInfo[2], busClk, forcedCl);
+	if (0 == minCas) {
+		mvOsOutput("Dram: Warn: Could not find CAS compatible to SysClk %dMhz\n", (busClk / 1000000));
+
+		minCas = DDR2_CL_4;	/* Continue with this CAS */
+		mvOsOutput("Set default CAS latency 4\n");
+	}
+
+	/* calc SDRAM_CONFIG_REG  and save it to temp register */
+	temp = sdramConfigRegCalc(&bankInfo[0], &bankInfo[2], busClk);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. sdramConfigRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+
+	/* check if ECC is enabled by the user */
+	if (eccDisable) {
+		/* turn off ECC */
+		temp &= ~BIT18;
+	}
+	DB(mvOsPrintf("Dram: sdramConfigRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG1, temp);
+
+	/* calc SDRAM_MODE_REG  and save it to temp register */
+	temp = sdramModeRegCalc(minCas);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. sdramModeRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: sdramModeRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG2, temp);
+
+	/* calc SDRAM_EXTENDED_MODE_REG  and save it to temp register */
+	temp = sdramExtModeRegCalc(&bankInfo[0], busClk);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. sdramExtModeRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: sdramExtModeRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG10, temp);
+
+	/* calc D_UNIT_CONTROL_LOW  and save it to temp register */
+	TTMode = MV_FALSE;
+	DB(mvOsPrintf("Dram: numOfAllDevices = %x\n", numOfAllDevices);
+	    )
+	    if ((numOfAllDevices > 9) && (bankInfo[0].registeredAddrAndControlInputs == MV_FALSE)) {
+		if (((numOfAllDevices > 9) && (busClk > MV_BOARD_SYSCLK_200MHZ)) || (numOfAllDevices > 18)) {
+			mvOsOutput("Enable 2T ");
+			TTMode = MV_TRUE;
+		}
+	}
+
+	temp = dunitCtrlLowRegCalc(&bankInfo[0], minCas, busClk, TTMode);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. dunitCtrlLowRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: dunitCtrlLowRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG3, temp);
+
+	/* calc D_UNIT_CONTROL_HIGH  and save it to temp register */
+	temp = dunitCtrlHighRegCalc(&bankInfo[0], busClk);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. dunitCtrlHighRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: dunitCtrlHighRegCalc - %x\n", temp);
+	    )
+	    /* check if ECC is enabled by the user */
+	    if (eccDisable) {
+		/* turn off sample stage if no ecc */
+		temp &= ~SDRAM__D2P_EN;;
+	}
+	MV_REG_WRITE(DRAM_BUF_REG13, temp);
+
+	/* calc SDRAM_ADDR_CTRL_REG  and save it to temp register */
+	temp = sdramAddrCtrlRegCalc(&bankInfo[0], &bankInfo[2]);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. sdramAddrCtrlRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: sdramAddrCtrlRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG4, temp);
+
+	/* calc SDRAM_TIMING_CTRL_LOW_REG  and save it to temp register */
+	temp = sdramTimeCtrlLowRegCalc(&bankInfo[0], minCas, busClk);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. sdramTimeCtrlLowRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: sdramTimeCtrlLowRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG5, temp);
+
+	/* calc SDRAM_TIMING_CTRL_HIGH_REG  and save it to temp register */
+	temp = sdramTimeCtrlHighRegCalc(&bankInfo[0], busClk);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. sdramTimeCtrlHighRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: sdramTimeCtrlHighRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG6, temp);
+
+	sdramDDr2OdtConfig(bankInfo);
+
+	/* calc DDR2_SDRAM_TIMING_LOW_REG  and save it to temp register */
+	temp = sdramDdr2TimeLoRegCalc(minCas);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. sdramDdr2TimeLoRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: sdramDdr2TimeLoRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG11, temp);
+
+	/* calc DDR2_SDRAM_TIMING_HIGH_REG  and save it to temp register */
+	temp = sdramDdr2TimeHiRegCalc(minCas);
+	if (-1 == temp) {
+		mvOsOutput("Dram: ERR. sdramDdr2TimeHiRegCalc failed !!!\n");
+		return MV_ERROR;
+	}
+	DB(mvOsPrintf("Dram: sdramDdr2TimeHiRegCalc - %x\n", temp);
+	    )
+	    MV_REG_WRITE(DRAM_BUF_REG12, temp);
+#endif
+
+	/* Note that DDR SDRAM Address/Control and Data pad calibration     */
+	/* settings is done in mvSdramIfConfig.s                            */
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDramIfBankBaseGet - Get DRAM interface bank base.
+*
+* DESCRIPTION:
+*       This function returns the 32 bit base address of a given DRAM bank.
+*
+* INPUT:
+*       bankNum - Bank number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       DRAM bank size. If bank is disabled or paramter is invalid, the
+*		function returns -1.
+*
+*******************************************************************************/
+MV_U32 mvDramIfBankBaseGet(MV_U32 bankNum)
+{
+	MV_DRAM_DEC_WIN addrDecWin;
+	MV_U32 result = 0xFFFFFFFF;
+
+	if (mvDramIfWinGet(SDRAM_CS0 + bankNum, &addrDecWin) == MV_OK) {
+		if (addrDecWin.enable == MV_TRUE)
+			result = addrDecWin.addrWin.baseLow;
+	}
+
+	DB(mvOsPrintf("Dram: mvDramIfBankBaseGet Bank %d base addr is %x \n", bankNum, result));
+	return result;
+}
+
+/*******************************************************************************
+* mvDramIfBankSizeGet - Get DRAM interface bank size.
+*
+* DESCRIPTION:
+*       This function returns the size of a given DRAM bank.
+*
+* INPUT:
+*       bankNum - Bank number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       DRAM bank size. If bank is disabled the function return '0'. In case
+*		or paramter is invalid, the function returns -1.
+*
+*******************************************************************************/
+MV_U32 mvDramIfBankSizeGet(MV_U32 bankNum)
+{
+	MV_DRAM_DEC_WIN addrDecWin;
+	MV_U32 result = 0;
+
+	if (mvDramIfWinGet(SDRAM_CS0 + bankNum, &addrDecWin) == MV_OK) {
+		if (addrDecWin.enable == MV_TRUE)
+			result = addrDecWin.addrWin.size;
+	}
+
+	DB(mvOsPrintf("Dram: mvDramIfBankSizeGet Bank %d size is %x \n", bankNum, result));
+	return result;
+}
+
+/*******************************************************************************
+* mvDramIfSizeGet - Get DRAM interface total size.
+*
+* DESCRIPTION:
+*       This function get the DRAM total size.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       DRAM total size. In case or paramter is invalid, the function
+*		returns -1.
+*
+*******************************************************************************/
+MV_U32 mvDramIfSizeGet(MV_VOID)
+{
+	MV_U32 size = 0, i;
+
+	for (i = 0; i < MV_DRAM_MAX_CS; i++)
+		size += mvDramIfBankSizeGet(i);
+
+	DB(mvOsPrintf("Dram: mvDramIfSizeGet size is %x \n", size));
+	return size;
+}
+
+/*******************************************************************************
+* mvDramIfSingleBitErrThresholdSet - Set single bit ECC threshold.
+*
+* DESCRIPTION:
+*       The ECC single bit error threshold is the number of single bit
+*       errors to happen before the Dunit generates an interrupt.
+*       This function set single bit ECC threshold.
+*
+* INPUT:
+*       threshold - threshold.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if threshold is to big, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvDramIfSingleBitErrThresholdSet(MV_U32 threshold)
+{
+	MV_U32 regVal;
+
+	if (threshold > SECR_THRECC_MAX)
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(SDRAM_ECC_CONTROL_REG);
+	regVal &= ~SECR_THRECC_MASK;
+	regVal |= ((SECR_THRECC(threshold) & SECR_THRECC_MASK));
+	MV_REG_WRITE(SDRAM_ECC_CONTROL_REG, regVal);
+
+	return MV_OK;
+}
+
+#ifndef MV_STATIC_DRAM_ON_BOARD
+/*******************************************************************************
+* minCasCalc - Calculate the Minimum CAS latency which can be used.
+*
+* DESCRIPTION:
+*	Calculate the minimum CAS latency that can be used, base on the DRAM
+*	parameters and the SDRAM bus Clock freq.
+*
+* INPUT:
+*	busClk    - the DRAM bus Clock.
+*	pBankInfo - bank info parameters.
+*	forcedCl - Forced CAS Latency multiplied by 10. If equal to zero, do not force.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       The minimum CAS Latency. The function returns 0 if max CAS latency
+*		supported by banks is incompatible with system bus clock frequancy.
+*
+*******************************************************************************/
+
+static MV_U32 minCasCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_DRAM_BANK_INFO *pBankInfo2, MV_U32 busClk, MV_U32 forcedCl)
+{
+	MV_U32 count = 1, j;
+	MV_U32 busClkPs = 1000000000 / (busClk / 1000);	/* in ps units */
+	MV_U32 startBit, stopBit;
+	MV_U32 minCas0 = 0, minCas2 = 0;
+
+	/*     DDR 2:
+	 *******-******-******-******-******-******-******-*******
+	 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+	 *******-******-******-******-******-******-******-*******
+	 CAS    =       * TBD  | TBD  |  5   |  4   |  3   |  2   | TBD  | TBD  *
+	 Disco VI=      * TBD  | TBD  |  5   |  4   |  3   |  TBD   | TBD | TBD *
+	 Disco Duo=     * TBD  |   6  |  5   |  4   |  3   |  TBD   | TBD | TBD *
+	 *********************************************************/
+
+	/* If we are asked to use the forced CAL  we change the suported CAL to be forcedCl only */
+	if (forcedCl) {
+		mvOsOutput("DRAM: Using forced CL %d.%d\n", (forcedCl / 10), (forcedCl % 10));
+
+		if (forcedCl == 30)
+			pBankInfo->suportedCasLatencies = 0x08;
+		else if (forcedCl == 40)
+			pBankInfo->suportedCasLatencies = 0x10;
+		else if (forcedCl == 50)
+			pBankInfo->suportedCasLatencies = 0x20;
+		else if (forcedCl == 60)
+			pBankInfo->suportedCasLatencies = 0x40;
+		else {
+			mvOsPrintf("Forced CL %d.%d not supported. Set default CL 4\n",
+				   (forcedCl / 10), (forcedCl % 10));
+			pBankInfo->suportedCasLatencies = 0x10;
+		}
+
+		return pBankInfo->suportedCasLatencies;
+	}
+
+	/* go over the supported cas mask from Max Cas down and check if the    */
+	/* SysClk stands in its time requirments.                               */
+
+	DB(mvOsPrintf("Dram: minCasCalc supported mask = %x busClkPs = %x \n",
+		      pBankInfo->suportedCasLatencies, busClkPs));
+	count = 1;
+	for (j = 7; j > 0; j--) {
+		if ((pBankInfo->suportedCasLatencies >> j) & BIT0) {
+			/* Reset the bits for CL incompatible for the sysClk */
+			switch (count) {
+			case 1:
+				if (pBankInfo->minCycleTimeAtMaxCasLatPs > busClkPs)
+					pBankInfo->suportedCasLatencies &= ~(BIT0 << j);
+				count++;
+				break;
+			case 2:
+				if (pBankInfo->minCycleTimeAtMaxCasLatMinus1Ps > busClkPs)
+					pBankInfo->suportedCasLatencies &= ~(BIT0 << j);
+				count++;
+				break;
+			case 3:
+				if (pBankInfo->minCycleTimeAtMaxCasLatMinus2Ps > busClkPs)
+					pBankInfo->suportedCasLatencies &= ~(BIT0 << j);
+				count++;
+				break;
+			default:
+				pBankInfo->suportedCasLatencies &= ~(BIT0 << j);
+				break;
+			}
+		}
+	}
+
+	DB(mvOsPrintf("Dram: minCasCalc support = %x (after SysCC calc)\n", pBankInfo->suportedCasLatencies));
+
+	count = 1;
+	DB(mvOsPrintf("Dram2: minCasCalc supported mask = %x busClkPs = %x \n",
+		      pBankInfo2->suportedCasLatencies, busClkPs));
+	for (j = 7; j > 0; j--) {
+		if ((pBankInfo2->suportedCasLatencies >> j) & BIT0) {
+			/* Reset the bits for CL incompatible for the sysClk */
+			switch (count) {
+			case 1:
+				if (pBankInfo2->minCycleTimeAtMaxCasLatPs > busClkPs)
+					pBankInfo2->suportedCasLatencies &= ~(BIT0 << j);
+				count++;
+				break;
+			case 2:
+				if (pBankInfo2->minCycleTimeAtMaxCasLatMinus1Ps > busClkPs)
+					pBankInfo2->suportedCasLatencies &= ~(BIT0 << j);
+				count++;
+				break;
+			case 3:
+				if (pBankInfo2->minCycleTimeAtMaxCasLatMinus2Ps > busClkPs)
+					pBankInfo2->suportedCasLatencies &= ~(BIT0 << j);
+				count++;
+				break;
+			default:
+				pBankInfo2->suportedCasLatencies &= ~(BIT0 << j);
+				break;
+			}
+		}
+	}
+
+	DB(mvOsPrintf("Dram2: minCasCalc support = %x (after SysCC calc)\n", pBankInfo2->suportedCasLatencies));
+
+	startBit = 3;		/* DDR2 support CL start with CL3 (bit 3) */
+	stopBit = 6;		/* DDR2 support CL stops with CL6 (bit 6) */
+
+	for (j = startBit; j <= stopBit; j++) {
+		if ((pBankInfo->suportedCasLatencies >> j) & BIT0) {
+			DB(mvOsPrintf("Dram: minCasCalc choose CAS %x \n", (BIT0 << j)));
+			minCas0 = (BIT0 << j);
+			break;
+		}
+	}
+
+	for (j = startBit; j <= stopBit; j++) {
+		if ((pBankInfo2->suportedCasLatencies >> j) & BIT0) {
+			DB(mvOsPrintf("Dram: minCasCalc choose CAS %x \n", (BIT0 << j)));
+			minCas2 = (BIT0 << j);
+			break;
+		}
+	}
+
+	if (minCas2 > minCas0)
+		return minCas2;
+	else
+		return minCas0;
+
+	return 0;
+}
+
+/*******************************************************************************
+* sdramConfigRegCalc - Calculate sdram config register
+*
+* DESCRIPTION: Calculate sdram config register optimized value based
+*			on the bank info parameters.
+*
+* INPUT:
+*	busClk    - the DRAM bus Clock.
+*	pBankInfo - sdram bank parameters
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       sdram config reg value.
+*
+*******************************************************************************/
+static MV_U32 sdramConfigRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_DRAM_BANK_INFO *pBankInfo2, MV_U32 busClk)
+{
+	MV_U32 sdramConfig = 0;
+	MV_U32 refreshPeriod;
+
+	busClk /= 1000000;	/* we work with busClk in MHz */
+
+	sdramConfig = MV_REG_READ(SDRAM_CONFIG_REG);
+
+	/* figure out the memory refresh internal */
+	switch (pBankInfo->refreshInterval & 0xf) {
+	case 0x0:		/* refresh period is 15.625 usec */
+		refreshPeriod = 15625;
+		break;
+	case 0x1:		/* refresh period is 3.9 usec         */
+		refreshPeriod = 3900;
+		break;
+	case 0x2:		/* refresh period is 7.8 usec         */
+		refreshPeriod = 7800;
+		break;
+	case 0x3:		/* refresh period is 31.3 usec        */
+		refreshPeriod = 31300;
+		break;
+	case 0x4:		/* refresh period is 62.5 usec        */
+		refreshPeriod = 62500;
+		break;
+	case 0x5:		/* refresh period is 125 usec         */
+		refreshPeriod = 125000;
+		break;
+	default:		/* refresh period undefined                                   */
+		mvOsPrintf("Dram: ERR. DRAM refresh period is unknown!\n");
+		return -1;
+	}
+
+	/* Now the refreshPeriod is in register format value */
+	refreshPeriod = (busClk * refreshPeriod) / 1000;
+
+	DB(mvOsPrintf("Dram: sdramConfigRegCalc calculated refresh interval %0x\n", refreshPeriod));
+
+	/* make sure the refresh value is only 14 bits */
+	if (refreshPeriod > SDRAM_REFRESH_MAX) {
+		refreshPeriod = SDRAM_REFRESH_MAX;
+		DB(mvOsPrintf("Dram: sdramConfigRegCalc adjusted refresh interval %0x\n", refreshPeriod));
+	}
+
+	/* Clear the refresh field */
+	sdramConfig &= ~SDRAM_REFRESH_MASK;
+
+	/* Set new value to refresh field */
+	sdramConfig |= (refreshPeriod & SDRAM_REFRESH_MASK);
+
+	/*  registered DRAM ? */
+	if (pBankInfo->registeredAddrAndControlInputs) {
+		/* it's registered DRAM, so set the reg. DRAM bit */
+		sdramConfig |= SDRAM_REGISTERED;
+		DB(mvOsPrintf("DRAM Attribute: Registered address and control inputs.\n");
+		    )
+	}
+
+	/* ECC and IERR support */
+	sdramConfig &= ~SDRAM_ECC_MASK;	/* Clear ECC field */
+	sdramConfig &= ~SDRAM_IERR_MASK;	/* Clear IErr field */
+
+	if (pBankInfo->errorCheckType) {
+		sdramConfig |= SDRAM_ECC_EN;
+		sdramConfig |= SDRAM_IERR_REPORTE;
+		DB(mvOsPrintf("Dram: mvDramIfDetect Enabling ECC\n"));
+	} else {
+		sdramConfig |= SDRAM_ECC_DIS;
+		sdramConfig |= SDRAM_IERR_IGNORE;
+		DB(mvOsPrintf("Dram: mvDramIfDetect Disabling ECC!\n"));
+	}
+	/* Set static default settings */
+	sdramConfig |= SDRAM_CONFIG_DV;
+
+	DB(mvOsPrintf("Dram: sdramConfigRegCalc set sdramConfig to 0x%x\n", sdramConfig));
+
+	return sdramConfig;
+}
+
+/*******************************************************************************
+* sdramModeRegCalc - Calculate sdram mode register
+*
+* DESCRIPTION: Calculate sdram mode register optimized value based
+*			on the bank info parameters and the minCas.
+*
+* INPUT:
+*	minCas	  - minimum CAS supported.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       sdram mode reg value.
+*
+*******************************************************************************/
+static MV_U32 sdramModeRegCalc(MV_U32 minCas)
+{
+	MV_U32 sdramMode;
+
+	sdramMode = MV_REG_READ(SDRAM_MODE_REG);
+
+	/* Clear CAS Latency field */
+	sdramMode &= ~SDRAM_CL_MASK;
+
+	DB(mvOsPrintf("DRAM CAS Latency ");)
+
+	switch (minCas) {
+	case DDR2_CL_3:
+		sdramMode |= SDRAM_DDR2_CL_3;
+		DB(mvOsPrintf("3.\n");)
+		break;
+	case DDR2_CL_4:
+		sdramMode |= SDRAM_DDR2_CL_4;
+		DB(mvOsPrintf("4.\n");)
+	    break;
+	case DDR2_CL_5:
+		sdramMode |= SDRAM_DDR2_CL_5;
+		DB(mvOsPrintf("5.\n");)
+	    break;
+	case DDR2_CL_6:
+		sdramMode |= SDRAM_DDR2_CL_6;
+		DB(mvOsPrintf("6.\n");)
+	    break;
+	default:
+		mvOsOutput("\nsdramModeRegCalc ERROR: Max. CL out of range\n");
+		return -1;
+	}
+
+	DB(mvOsPrintf("\nsdramModeRegCalc register 0x%x\n", sdramMode));
+
+	return sdramMode;
+}
+
+/*******************************************************************************
+* sdramExtModeRegCalc - Calculate sdram Extended mode register
+*
+* DESCRIPTION:
+*		Return sdram Extended mode register value based
+*		on the bank info parameters and bank presence.
+*
+* INPUT:
+*	pBankInfo - sdram bank parameters
+*	busClk - DRAM frequency
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       sdram Extended mode reg value.
+*
+*******************************************************************************/
+static MV_U32 sdramExtModeRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk)
+{
+	MV_U32 populateBanks = 0;
+	int bankNum;
+
+	/* Represent the populate banks in binary form */
+	for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) {
+		if (0 != pBankInfo[bankNum].size)
+			populateBanks |= (1 << bankNum);
+	}
+
+	switch (populateBanks) {
+	case (BANK_PRESENT_CS0):
+	case (BANK_PRESENT_CS0_CS1):
+		return DDR_SDRAM_EXT_MODE_CS0_CS1_DV;
+
+	case (BANK_PRESENT_CS0_CS2):
+	case (BANK_PRESENT_CS0_CS1_CS2):
+	case (BANK_PRESENT_CS0_CS2_CS3):
+	case (BANK_PRESENT_CS0_CS2_CS3_CS4):
+		if (busClk >= MV_BOARD_SYSCLK_267MHZ)
+			return DDR_SDRAM_EXT_MODE_FAST_CS0_CS1_CS2_CS3_DV;
+		else
+			return DDR_SDRAM_EXT_MODE_CS0_CS1_CS2_CS3_DV;
+
+	default:
+		mvOsOutput("sdramExtModeRegCalc: Invalid DRAM bank presence\n");
+		return -1;
+	}
+	return 0;
+}
+
+/*******************************************************************************
+* dunitCtrlLowRegCalc - Calculate sdram dunit control low register
+*
+* DESCRIPTION: Calculate sdram dunit control low register optimized value based
+*			on the bank info parameters and the minCas.
+*
+* INPUT:
+*	pBankInfo - sdram bank parameters
+*	minCas	  - minimum CAS supported.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       sdram dunit control low reg value.
+*
+*******************************************************************************/
+static MV_U32 dunitCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas, MV_U32 busClk, MV_STATUS TTMode)
+{
+	MV_U32 dunitCtrlLow, cl;
+	MV_U32 sbOutR[4] = { 3, 5, 7, 9 };
+	MV_U32 sbOutU[4] = { 1, 3, 5, 7 };
+
+	dunitCtrlLow = MV_REG_READ(SDRAM_DUNIT_CTRL_REG);
+
+	DB(mvOsPrintf("Dram: dunitCtrlLowRegCalc\n"));
+
+	/* Clear StBurstOutDel field */
+	dunitCtrlLow &= ~SDRAM_SB_OUT_MASK;
+
+	/* Clear StBurstInDel field */
+	dunitCtrlLow &= ~SDRAM_SB_IN_MASK;
+
+	/* Clear CtrlPos field */
+	dunitCtrlLow &= ~SDRAM_CTRL_POS_MASK;
+
+	/* Clear 2T field */
+	dunitCtrlLow &= ~SDRAM_2T_MASK;
+	if (TTMode == MV_TRUE)
+		dunitCtrlLow |= SDRAM_2T_MODE;
+
+	/* For proper sample of read data set the Dunit Control register's      */
+	/* stBurstInDel bits [27:24]                                            */
+	/*              200MHz - 267MHz None reg  = CL + 1                      */
+	/*              200MHz - 267MHz reg       = CL + 2                      */
+	/*              > 267MHz None reg  = CL + 2                     */
+	/*              > 267MHz reg      = CL + 3                      */
+
+	/* For proper sample of read data set the Dunit Control register's      */
+	/* stBurstOutDel bits [23:20]                                           */
+			/********-********-********-********-
+			*  CL=3  |  CL=4  |  CL=5  |  CL=6  |
+			*********-********-********-********-
+	Not Reg.	*  0001  |  0011  |  0101  |  0111  |
+			*********-********-********-********-
+	Registered	*  0011  |  0101  |  0111  |  1001  |
+			*********-********-********-********/
+
+	/* Set Dunit Control low default value */
+	dunitCtrlLow |= SDRAM_DUNIT_CTRL_LOW_DDR2_DV;
+
+	switch (minCas) {
+	case DDR2_CL_3:
+		cl = 3;
+		break;
+	case DDR2_CL_4:
+		cl = 4;
+		break;
+	case DDR2_CL_5:
+		cl = 5;
+		break;
+	case DDR2_CL_6:
+		cl = 6;
+		break;
+	default:
+		mvOsOutput("Dram: dunitCtrlLowRegCalc Max. CL out of range %d\n", minCas);
+		return -1;
+	}
+
+	/* registerd DDR SDRAM? */
+	if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
+		dunitCtrlLow |= (sbOutR[cl - 3]) << SDRAM_SB_OUT_DEL_OFFS;
+	else
+		dunitCtrlLow |= (sbOutU[cl - 3]) << SDRAM_SB_OUT_DEL_OFFS;
+
+	DB(mvOsPrintf("\n\ndunitCtrlLowRegCalc: CL = %d, frequencies=%d\n", cl, busClk));
+
+	if (busClk <= MV_BOARD_SYSCLK_267MHZ) {
+		if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
+			cl = cl + 2;
+		else
+			cl = cl + 1;
+	} else {
+		if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
+			cl = cl + 3;
+		else
+			cl = cl + 2;
+	}
+
+	DB(mvOsPrintf("dunitCtrlLowRegCalc: SDRAM_SB_IN_DEL_OFFS = %d \n", cl));
+	dunitCtrlLow |= cl << SDRAM_SB_IN_DEL_OFFS;
+
+	DB(mvOsPrintf("Dram: Reg dunit control low = %x\n", dunitCtrlLow));
+
+	return dunitCtrlLow;
+}
+
+/*******************************************************************************
+* dunitCtrlHighRegCalc - Calculate sdram dunit control high register
+*
+* DESCRIPTION: Calculate sdram dunit control high register optimized value based
+*			on the bus clock.
+*
+* INPUT:
+*	busClk	  - DRAM frequency.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       sdram dunit control high reg value.
+*
+*******************************************************************************/
+static MV_U32 dunitCtrlHighRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk)
+{
+	MV_U32 dunitCtrlHigh;
+	dunitCtrlHigh = MV_REG_READ(SDRAM_DUNIT_CTRL_HI_REG);
+	if (busClk > MV_BOARD_SYSCLK_300MHZ)
+		dunitCtrlHigh |= SDRAM__P2D_EN;
+	else
+		dunitCtrlHigh &= ~SDRAM__P2D_EN;
+
+	if (busClk > MV_BOARD_SYSCLK_267MHZ)
+		dunitCtrlHigh |= (SDRAM__WR_MESH_DELAY_EN | SDRAM__PUP_ZERO_SKEW_EN | SDRAM__ADD_HALF_FCC_EN);
+
+	/* If ECC support we turn on D2P sample */
+	dunitCtrlHigh &= ~SDRAM__D2P_EN;	/* Clear D2P bit */
+	if ((pBankInfo->errorCheckType) && (busClk > MV_BOARD_SYSCLK_267MHZ))
+		dunitCtrlHigh |= SDRAM__D2P_EN;
+
+	return dunitCtrlHigh;
+}
+
+/*******************************************************************************
+* sdramAddrCtrlRegCalc - Calculate sdram address control register
+*
+* DESCRIPTION: Calculate sdram address control register optimized value based
+*			on the bank info parameters and the minCas.
+*
+* INPUT:
+*	pBankInfo - sdram bank parameters
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       sdram address control reg value.
+*
+*******************************************************************************/
+static MV_U32 sdramAddrCtrlRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_DRAM_BANK_INFO *pBankInfoDIMM1)
+{
+	MV_U32 addrCtrl = 0;
+
+	if (pBankInfoDIMM1->size) {
+		switch (pBankInfoDIMM1->sdramWidth) {
+		case 4:	/* memory is x4 */
+			mvOsOutput("sdramAddrCtrlRegCalc: Error - x4 not supported!\n");
+			return -1;
+			break;
+		case 8:	/* memory is x8 */
+			addrCtrl |= SDRAM_ADDRSEL_X8(2) | SDRAM_ADDRSEL_X8(3);
+			DB(mvOsPrintf("sdramAddrCtrlRegCalc: sdramAddrCtrlRegCalc SDRAM device DIMM2 width x8\n"));
+			break;
+		case 16:
+			addrCtrl |= SDRAM_ADDRSEL_X16(2) | SDRAM_ADDRSEL_X16(3);
+			DB(mvOsPrintf("sdramAddrCtrlRegCalc: sdramAddrCtrlRegCalc SDRAM device DIMM2 width x16\n"));
+			break;
+		default:	/* memory width unsupported */
+			mvOsOutput("sdramAddrCtrlRegCalc: ERR. DRAM chip width is unknown!\n");
+			return -1;
+		}
+	}
+
+	switch (pBankInfo->sdramWidth) {
+	case 4:		/* memory is x4 */
+		mvOsOutput("sdramAddrCtrlRegCalc: Error - x4 not supported!\n");
+		return -1;
+		break;
+	case 8:		/* memory is x8 */
+		addrCtrl |= SDRAM_ADDRSEL_X8(0) | SDRAM_ADDRSEL_X8(1);
+		DB(mvOsPrintf("sdramAddrCtrlRegCalc: sdramAddrCtrlRegCalc SDRAM device width x8\n"));
+		break;
+	case 16:
+		addrCtrl |= SDRAM_ADDRSEL_X16(0) | SDRAM_ADDRSEL_X16(1);
+		DB(mvOsPrintf("sdramAddrCtrlRegCalc: sdramAddrCtrlRegCalc SDRAM device width x16\n"));
+		break;
+	default:		/* memory width unsupported */
+		mvOsOutput("sdramAddrCtrlRegCalc: ERR. DRAM chip width is unknown!\n");
+		return -1;
+	}
+
+	/* Note that density is in MB units */
+	switch (pBankInfo->deviceDensity) {
+	case 256:		/* 256 Mbit */
+		DB(mvOsPrintf("DRAM Device Density 256Mbit\n"));
+		addrCtrl |= SDRAM_DSIZE_256Mb(0) | SDRAM_DSIZE_256Mb(1);
+		break;
+	case 512:		/* 512 Mbit */
+		DB(mvOsPrintf("DRAM Device Density 512Mbit\n"));
+		addrCtrl |= SDRAM_DSIZE_512Mb(0) | SDRAM_DSIZE_512Mb(1);
+		break;
+	case 1024:		/* 1 Gbit */
+		DB(mvOsPrintf("DRAM Device Density 1Gbit\n"));
+		addrCtrl |= SDRAM_DSIZE_1Gb(0) | SDRAM_DSIZE_1Gb(1);
+		break;
+	case 2048:		/* 2 Gbit */
+		DB(mvOsPrintf("DRAM Device Density 2Gbit\n"));
+		addrCtrl |= SDRAM_DSIZE_2Gb(0) | SDRAM_DSIZE_2Gb(1);
+		break;
+	default:
+		mvOsOutput("Dram: sdramAddrCtrl unsupported RAM-Device size %d\n", pBankInfo->deviceDensity);
+		return -1;
+	}
+
+	if (pBankInfoDIMM1->size) {
+		switch (pBankInfoDIMM1->deviceDensity) {
+		case 256:	/* 256 Mbit */
+			DB(mvOsPrintf("DIMM2: DRAM Device Density 256Mbit\n"));
+			addrCtrl |= SDRAM_DSIZE_256Mb(2) | SDRAM_DSIZE_256Mb(3);
+			break;
+		case 512:	/* 512 Mbit */
+			DB(mvOsPrintf("DIMM2: DRAM Device Density 512Mbit\n"));
+			addrCtrl |= SDRAM_DSIZE_512Mb(2) | SDRAM_DSIZE_512Mb(3);
+			break;
+		case 1024:	/* 1 Gbit */
+			DB(mvOsPrintf("DIMM2: DRAM Device Density 1Gbit\n"));
+			addrCtrl |= SDRAM_DSIZE_1Gb(2) | SDRAM_DSIZE_1Gb(3);
+			break;
+		case 2048:	/* 2 Gbit */
+			DB(mvOsPrintf("DIMM2: DRAM Device Density 2Gbit\n"));
+			addrCtrl |= SDRAM_DSIZE_2Gb(2) | SDRAM_DSIZE_2Gb(3);
+			break;
+		default:
+			mvOsOutput("DIMM2: Dram: sdramAddrCtrl unsupported RAM-Device size %d\n",
+				   pBankInfoDIMM1->deviceDensity);
+			return -1;
+		}
+	}
+	/* SDRAM address control */
+	DB(mvOsPrintf("Dram: setting sdram address control with: %x \n", addrCtrl));
+
+	return addrCtrl;
+}
+
+/*******************************************************************************
+* sdramTimeCtrlLowRegCalc - Calculate sdram timing control low register
+*
+* DESCRIPTION:
+*       This function calculates sdram timing control low register
+*       optimized value based on the bank info parameters and the minCas.
+*
+* INPUT:
+*	    pBankInfo - sdram bank parameters
+*	minCas	  - minimum CAS supported.
+*       busClk    - Bus clock
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       sdram timing control low reg value.
+*
+*******************************************************************************/
+static MV_U32 sdramTimeCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas, MV_U32 busClk)
+{
+	MV_U32 tRp = 0;
+	MV_U32 tRrd = 0;
+	MV_U32 tRcd = 0;
+	MV_U32 tRas = 0;
+	MV_U32 tWr = 0;
+	MV_U32 tWtr = 0;
+	MV_U32 tRtp = 0;
+	MV_U32 timeCtrlLow = 0;
+
+	MV_U32 bankNum;
+
+	busClk = busClk / 1000000;	/* In MHz */
+
+	/* Scan all DRAM banks to find maximum timing values */
+	for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) {
+		tRp = MV_MAX(tRp, pBankInfo[bankNum].minRowPrechargeTime);
+		tRrd = MV_MAX(tRrd, pBankInfo[bankNum].minRowActiveToRowActive);
+		tRcd = MV_MAX(tRcd, pBankInfo[bankNum].minRasToCasDelay);
+		tRas = MV_MAX(tRas, pBankInfo[bankNum].minRasPulseWidth);
+	}
+
+	/* Extract timing (in ns) from SPD value. We ignore the tenth ns part.  */
+	/* by shifting the data two bits right.                                 */
+	tRp = tRp >> 2;		/* For example 0x50 -> 20ns                        */
+	tRrd = tRrd >> 2;
+	tRcd = tRcd >> 2;
+
+	/* Extract clock cycles from time parameter. We need to round up        */
+	tRp = ((busClk * tRp) / 1000) + (((busClk * tRp) % 1000) ? 1 : 0);
+	DB(mvOsPrintf("Dram  Timing Low: tRp = %d ", tRp));
+	tRrd = ((busClk * tRrd) / 1000) + (((busClk * tRrd) % 1000) ? 1 : 0);
+	/* JEDEC min reqeirments tRrd = 2 */
+	if (tRrd < 2)
+		tRrd = 2;
+	DB(mvOsPrintf("tRrd = %d ", tRrd));
+	tRcd = ((busClk * tRcd) / 1000) + (((busClk * tRcd) % 1000) ? 1 : 0);
+	DB(mvOsPrintf("tRcd = %d ", tRcd));
+	tRas = ((busClk * tRas) / 1000) + (((busClk * tRas) % 1000) ? 1 : 0);
+	DB(mvOsPrintf("tRas = %d ", tRas));
+
+	/* tWr and tWtr is different for DDR1 and DDR2. tRtp is only for DDR2   */
+	/* Scan all DRAM banks to find maximum timing values */
+	for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) {
+		tWr = MV_MAX(tWr, pBankInfo[bankNum].minWriteRecoveryTime);
+		tWtr = MV_MAX(tWtr, pBankInfo[bankNum].minWriteToReadCmdDelay);
+		tRtp = MV_MAX(tRtp, pBankInfo[bankNum].minReadToPrechCmdDelay);
+	}
+
+	/* Extract timing (in ns) from SPD value. We ignore the tenth ns    */
+	/* part by shifting the data two bits right.                        */
+	tWr = tWr >> 2;		/* For example 0x50 -> 20ns                    */
+	tWtr = tWtr >> 2;
+	tRtp = tRtp >> 2;
+	/* Extract clock cycles from time parameter. We need to round up    */
+	tWr = ((busClk * tWr) / 1000) + (((busClk * tWr) % 1000) ? 1 : 0);
+	DB(mvOsPrintf("tWr = %d ", tWr));
+	tWtr = ((busClk * tWtr) / 1000) + (((busClk * tWtr) % 1000) ? 1 : 0);
+	/* JEDEC min reqeirments tWtr = 2 */
+	if (tWtr < 2)
+		tWtr = 2;
+	DB(mvOsPrintf("tWtr = %d ", tWtr));
+	tRtp = ((busClk * tRtp) / 1000) + (((busClk * tRtp) % 1000) ? 1 : 0);
+	/* JEDEC min reqeirments tRtp = 2 */
+	if (tRtp < 2)
+		tRtp = 2;
+	DB(mvOsPrintf("tRtp = %d ", tRtp));
+
+	/* Note: value of 0 in register means one cycle, 1 means two and so on  */
+	timeCtrlLow = (((tRp - 1) << SDRAM_TRP_OFFS) |
+		       ((tRrd - 1) << SDRAM_TRRD_OFFS) |
+		       ((tRcd - 1) << SDRAM_TRCD_OFFS) |
+		       (((tRas - 1) << SDRAM_TRAS_OFFS) & SDRAM_TRAS_MASK) |
+		       ((tWr - 1) << SDRAM_TWR_OFFS) |
+		       ((tWtr - 1) << SDRAM_TWTR_OFFS) | ((tRtp - 1) << SDRAM_TRTP_OFFS));
+
+	/* Check extended tRas bit */
+	if ((tRas - 1) & BIT4)
+		timeCtrlLow |= (1 << SDRAM_EXT_TRAS_OFFS);
+
+	return timeCtrlLow;
+}
+
+/*******************************************************************************
+* sdramTimeCtrlHighRegCalc - Calculate sdram timing control high register
+*
+* DESCRIPTION:
+*       This function calculates sdram timing control high register
+*       optimized value based on the bank info parameters and the bus clock.
+*
+* INPUT:
+*	    pBankInfo - sdram bank parameters
+*       busClk    - Bus clock
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       sdram timing control high reg value.
+*
+*******************************************************************************/
+static MV_U32 sdramTimeCtrlHighRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk)
+{
+	MV_U32 tRfc;
+	MV_U32 timingHigh;
+	MV_U32 timeNs = 0;
+	MV_U32 bankNum;
+
+	busClk = busClk / 1000000;	/* In MHz */
+
+	/* Set DDR timing high register static configuration bits */
+	timingHigh = MV_REG_READ(SDRAM_TIMING_CTRL_HIGH_REG);
+
+	/* Set DDR timing high register default value */
+	timingHigh |= SDRAM_TIMING_CTRL_HIGH_REG_DV;
+
+	/* Clear tRfc field */
+	timingHigh &= ~SDRAM_TRFC_MASK;
+
+	/* Scan all DRAM banks to find maximum timing values */
+	for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) {
+		timeNs = MV_MAX(timeNs, pBankInfo[bankNum].minRefreshToActiveCmd);
+		DB(mvOsPrintf("Dram:  Timing High: minRefreshToActiveCmd = %d\n",
+			      pBankInfo[bankNum].minRefreshToActiveCmd));
+	}
+	if (busClk >= 333 && mvCtrlModelGet() == MV_78XX0_A1_REV)
+		timingHigh |= 0x1 << SDRAM_TR2W_W2R_OFFS;
+
+	tRfc = ((busClk * timeNs) / 1000) + (((busClk * timeNs) % 1000) ? 1 : 0);
+	/* Note: value of 0 in register means one cycle, 1 means two and so on  */
+	DB(mvOsPrintf("Dram:  Timing High: tRfc = %d\n", tRfc));
+	timingHigh |= (((tRfc - 1) & SDRAM_TRFC_MASK) << SDRAM_TRFC_OFFS);
+	DB(mvOsPrintf("Dram:  Timing High: tRfc = %d\n", tRfc));
+
+	/* SDRAM timing high */
+	DB(mvOsPrintf("Dram: setting timing high with: %x \n", timingHigh));
+
+	return timingHigh;
+}
+
+/*******************************************************************************
+* sdramDDr2OdtConfig - Set DRAM DDR2 On Die Termination registers.
+*
+* DESCRIPTION:
+*       This function config DDR2 On Die Termination (ODT) registers.
+*
+* INPUT:
+*		pBankInfo - bank info parameters.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       None
+*******************************************************************************/
+static void sdramDDr2OdtConfig(MV_DRAM_BANK_INFO *pBankInfo)
+{
+	MV_U32 populateBanks = 0;
+	MV_U32 odtCtrlLow, odtCtrlHigh, dunitOdtCtrl;
+	int bankNum;
+
+	/* Represent the populate banks in binary form */
+	for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) {
+		if (0 != pBankInfo[bankNum].size)
+			populateBanks |= (1 << bankNum);
+	}
+
+	switch (populateBanks) {
+	case (BANK_PRESENT_CS0):
+	case (BANK_PRESENT_CS0_CS1):
+		odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_CS1_DV;
+		odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_CS1_DV;
+		dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS1_DV;
+		break;
+	case (BANK_PRESENT_CS0_CS2):
+	case (BANK_PRESENT_CS0_CS1_CS2):
+	case (BANK_PRESENT_CS0_CS2_CS3):
+	case (BANK_PRESENT_CS0_CS2_CS3_CS4):
+		odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_CS1_CS2_CS3_DV;
+		odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_CS1_CS2_CS3_DV;
+		dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS1_CS2_CS3_DV;
+		break;
+	default:
+		DB(mvOsPrintf("sdramDDr2OdtConfig: Invalid DRAM bank presence\n"));
+		return;
+	}
+	/* DDR2 SDRAM ODT ctrl low  */
+	DB(mvOsPrintf("Dram: DDR2 setting ODT ctrl low with: %x \n", odtCtrlLow));
+	MV_REG_WRITE(DRAM_BUF_REG7, odtCtrlLow);
+
+	/* DDR2 SDRAM ODT ctrl high  */
+	DB(mvOsPrintf("Dram: DDR2 setting ODT ctrl high with: %x \n", odtCtrlHigh));
+	MV_REG_WRITE(DRAM_BUF_REG8, odtCtrlHigh);
+
+	/* DDR2 DUNIT ODT ctrl  */
+	if (((mvCtrlModelGet() == MV_78XX0_DEV_ID) && (mvCtrlRevGet() == MV_78XX0_Y0_REV)) ||
+	    (mvCtrlModelGet() == MV_76100_DEV_ID) ||
+	    (mvCtrlModelGet() == MV_78100_DEV_ID) || (mvCtrlModelGet() == MV_78200_DEV_ID))
+		dunitOdtCtrl &= ~(BIT9 | BIT8);	/* Clear ODT always on */
+
+	DB(mvOsPrintf("DUNIT: DDR2 setting ODT ctrl with: %x \n", dunitOdtCtrl));
+	MV_REG_WRITE(DRAM_BUF_REG9, dunitOdtCtrl);
+	return;
+}
+
+/*******************************************************************************
+* sdramDdr2TimeLoRegCalc - Set DDR2 DRAM Timing Low registers.
+*
+* DESCRIPTION:
+*       This function config DDR2 DRAM Timing low registers.
+*
+* INPUT:
+*	minCas	  - minimum CAS supported.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       DDR2 sdram timing low reg value.
+*******************************************************************************/
+static MV_U32 sdramDdr2TimeLoRegCalc(MV_U32 minCas)
+{
+	MV_U8 cl = -1;
+	MV_U32 ddr2TimeLoReg;
+
+	/* read and clear the feilds we are going to set */
+	ddr2TimeLoReg = MV_REG_READ(SDRAM_DDR2_TIMING_LO_REG);
+	ddr2TimeLoReg &= ~(SD2TLR_TODT_ON_RD_MASK |
+			   SD2TLR_TODT_OFF_RD_MASK | SD2TLR_TODT_ON_CTRL_RD_MASK | SD2TLR_TODT_OFF_CTRL_RD_MASK);
+
+	if (minCas == DDR2_CL_3) {
+		cl = 3;
+	} else if (minCas == DDR2_CL_4) {
+		cl = 4;
+	} else if (minCas == DDR2_CL_5) {
+		cl = 5;
+	} else if (minCas == DDR2_CL_6) {
+		cl = 6;
+	} else {
+		DB(mvOsPrintf("sdramDdr2TimeLoRegCalc: CAS latency %d unsupported. using CAS latency 4\n", minCas));
+		cl = 4;
+	}
+
+	ddr2TimeLoReg |= ((cl - 3) << SD2TLR_TODT_ON_RD_OFFS);
+	ddr2TimeLoReg |= (cl << SD2TLR_TODT_OFF_RD_OFFS);
+	ddr2TimeLoReg |= (cl << SD2TLR_TODT_ON_CTRL_RD_OFFS);
+	ddr2TimeLoReg |= ((cl + 3) << SD2TLR_TODT_OFF_CTRL_RD_OFFS);
+
+	/* DDR2 SDRAM timing low */
+	DB(mvOsPrintf("Dram: DDR2 setting timing low with: %x \n", ddr2TimeLoReg));
+
+	return ddr2TimeLoReg;
+}
+
+/*******************************************************************************
+* sdramDdr2TimeHiRegCalc - Set DDR2 DRAM Timing High registers.
+*
+* DESCRIPTION:
+*       This function config DDR2 DRAM Timing high registers.
+*
+* INPUT:
+*	minCas	  - minimum CAS supported.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       DDR2 sdram timing high reg value.
+*******************************************************************************/
+static MV_U32 sdramDdr2TimeHiRegCalc(MV_U32 minCas)
+{
+	MV_U8 cl = -1;
+	MV_U32 ddr2TimeHiReg;
+
+	/* read and clear the feilds we are going to set */
+	ddr2TimeHiReg = MV_REG_READ(SDRAM_DDR2_TIMING_HI_REG);
+	ddr2TimeHiReg &= ~(SD2THR_TODT_ON_WR_MASK |
+			   SD2THR_TODT_OFF_WR_MASK | SD2THR_TODT_ON_CTRL_WR_MASK | SD2THR_TODT_OFF_CTRL_WR_MASK);
+
+	if (minCas == DDR2_CL_3) {
+		cl = 3;
+	} else if (minCas == DDR2_CL_4) {
+		cl = 4;
+	} else if (minCas == DDR2_CL_5) {
+		cl = 5;
+	} else if (minCas == DDR2_CL_6) {
+		cl = 6;
+	} else {
+		mvOsOutput("sdramDdr2TimeHiRegCalc: CAS latency %d unsupported. using CAS latency 4\n", minCas);
+		cl = 4;
+	}
+
+	ddr2TimeHiReg |= ((cl - 3) << SD2THR_TODT_ON_WR_OFFS);
+	ddr2TimeHiReg |= (cl << SD2THR_TODT_OFF_WR_OFFS);
+	ddr2TimeHiReg |= (cl << SD2THR_TODT_ON_CTRL_WR_OFFS);
+	ddr2TimeHiReg |= ((cl + 3) << SD2THR_TODT_OFF_CTRL_WR_OFFS);
+
+	/* DDR2 SDRAM timin high  */
+	DB(mvOsPrintf("Dram: DDR2 setting timing high with: %x \n", ddr2TimeHiReg));
+
+	return ddr2TimeHiReg;
+}
+#endif
+
+/*******************************************************************************
+* mvDramIfCalGet - Get CAS Latency
+*
+* DESCRIPTION:
+*       This function get the CAS Latency.
+*
+* INPUT:
+*       None
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       CAS latency times 10 (to avoid using floating point).
+*
+*******************************************************************************/
+MV_U32 mvDramIfCalGet(void)
+{
+	MV_U32 sdramCasLat, casLatMask;
+
+	casLatMask = (MV_REG_READ(SDRAM_MODE_REG) & SDRAM_CL_MASK);
+
+	switch (casLatMask) {
+	case SDRAM_DDR2_CL_3:
+		sdramCasLat = 30;
+		break;
+	case SDRAM_DDR2_CL_4:
+		sdramCasLat = 40;
+		break;
+	case SDRAM_DDR2_CL_5:
+		sdramCasLat = 50;
+		break;
+	case SDRAM_DDR2_CL_6:
+		sdramCasLat = 60;
+		break;
+	default:
+		mvOsOutput("mvDramIfCalGet: Err, unknown DDR2 CAL\n");
+		return -1;
+	}
+
+	return sdramCasLat;
+}
+
+/*******************************************************************************
+* mvDramIfSelfRefreshSet - Put the dram in self refresh mode -
+*
+* DESCRIPTION:
+*               add support in power management.
+*
+*
+* INPUT:
+*       None
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       None
+*
+*******************************************************************************/
+
+MV_VOID mvDramIfSelfRefreshSet()
+{
+	MV_U32 operReg;
+
+	operReg = MV_REG_READ(SDRAM_OPERATION_REG);
+	MV_REG_WRITE(SDRAM_OPERATION_REG, operReg | SDRAM_CMD_SLF_RFRSH);
+	/* Read until register is reset to 0 */
+	while (MV_REG_READ(SDRAM_OPERATION_REG))
+		;
+}
+
+/*******************************************************************************
+* mvDramIfDimGetSPDversion - return DIMM SPD version.
+*
+* DESCRIPTION:
+*		This function prints the DRAM controller information.
+*
+* INPUT:
+*		None.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*		None.
+*
+*******************************************************************************/
+static void mvDramIfDimGetSPDversion(MV_U32 *pMajor, MV_U32 *pMinor, MV_U32 bankNum)
+{
+	MV_DIMM_INFO dimmInfo;
+	if (bankNum >= MV_DRAM_MAX_CS) {
+		DB(mvOsPrintf("Dram: mvDramIfDimGetSPDversion bad params \n"));
+		return;
+	}
+	memset(&dimmInfo, 0, sizeof(dimmInfo));
+	if (MV_OK != dimmSpdGet((MV_U32) (bankNum / 2), &dimmInfo)) {
+		DB(mvOsPrintf("Dram: ERR dimmSpdGet failed to get dimm info \n"));
+		return;
+	}
+	*pMajor = dimmInfo.spdRawData[DIMM_SPD_VERSION] / 10;
+	*pMinor = dimmInfo.spdRawData[DIMM_SPD_VERSION] % 10;
+}
+
+/*******************************************************************************
+* mvDramIfShow - Show DRAM controller information.
+*
+* DESCRIPTION:
+*		This function prints the DRAM controller information.
+*
+* INPUT:
+*		None.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*		None.
+*
+*******************************************************************************/
+void mvDramIfShow(void)
+{
+	int i, sdramCasLat, sdramCsSize;
+	MV_U32 Major = 0, Minor = 0;
+
+	mvOsOutput("DRAM Controller info:\n");
+
+	mvOsOutput("Total DRAM ");
+	mvSizePrint(mvDramIfSizeGet());
+	mvOsOutput("\n");
+
+	for (i = 0; i < MV_DRAM_MAX_CS; i++) {
+		sdramCsSize = mvDramIfBankSizeGet(i);
+		if (sdramCsSize) {
+			if (0 == (i & 1)) {
+				mvDramIfDimGetSPDversion(&Major, &Minor, i);
+				mvOsOutput("DIMM %d version %d.%d\n", i / 2, Major, Minor);
+			}
+			mvOsOutput("\tDRAM CS[%d] ", i);
+			mvSizePrint(sdramCsSize);
+			mvOsOutput("\n");
+		}
+	}
+	sdramCasLat = mvDramIfCalGet();
+
+	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_ECC_EN)
+		mvOsOutput("ECC enabled, ");
+	else
+		mvOsOutput("ECC Disabled, ");
+
+	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_REGISTERED)
+		mvOsOutput("Registered DIMM\n");
+	else
+		mvOsOutput("Non registered DIMM\n");
+
+	mvOsOutput("Configured CAS Latency %d.%d\n", sdramCasLat / 10, sdramCasLat % 10);
+}
+
+/*******************************************************************************
+* mvDramIfGetFirstCS - find the  DRAM bank on the lower address
+*
+*
+* DESCRIPTION:
+*       This function return the fisrt CS on address 0
+*
+* INPUT:
+*		None.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       SDRAM_CS0 or SDRAM_CS2
+*
+*******************************************************************************/
+MV_U32 mvDramIfGetFirstCS(void)
+{
+	MV_DRAM_BANK_INFO bankInfo[MV_DRAM_MAX_CS];
+
+	if (DRAM_CS_Order[0] == N_A) {
+		mvDramBankInfoGet(SDRAM_CS0, &bankInfo[SDRAM_CS0]);
+#ifdef MV_INCLUDE_SDRAM_CS2
+		mvDramBankInfoGet(SDRAM_CS2, &bankInfo[SDRAM_CS2]);
+#endif
+
+#ifdef MV_INCLUDE_SDRAM_CS2
+		if (bankInfo[SDRAM_CS0].size < bankInfo[SDRAM_CS2].size) {
+			DRAM_CS_Order[0] = SDRAM_CS2;
+			DRAM_CS_Order[1] = SDRAM_CS3;
+			DRAM_CS_Order[2] = SDRAM_CS0;
+			DRAM_CS_Order[3] = SDRAM_CS1;
+
+			return SDRAM_CS2;
+		}
+#endif
+		DRAM_CS_Order[0] = SDRAM_CS0;
+		DRAM_CS_Order[1] = SDRAM_CS1;
+#ifdef MV_INCLUDE_SDRAM_CS2
+		DRAM_CS_Order[2] = SDRAM_CS2;
+		DRAM_CS_Order[3] = SDRAM_CS3;
+#endif
+		return SDRAM_CS0;
+	}
+	return DRAM_CS_Order[0];
+}
+
+/*******************************************************************************
+* mvDramIfGetCSorder -
+*
+*
+* DESCRIPTION:
+*       This function return the fisrt CS on address 0
+*
+* INPUT:
+*		CS number.
+*
+* OUTPUT:
+*		CS order.
+*
+* RETURN:
+*       SDRAM_CS0 or SDRAM_CS2
+*
+* NOTE: mvDramIfGetFirstCS must be caled before this subroutine
+*******************************************************************************/
+MV_U32 mvDramIfGetCSorder(MV_U32 csOrder)
+{
+	return DRAM_CS_Order[csOrder];
+}
+
+/*******************************************************************************
+* sdramIfWinOverlap - Check if an address window overlap an SDRAM address window
+*
+* DESCRIPTION:
+*		This function scan each SDRAM address decode window to test if it
+*		overlapps the given address windoow
+*
+* INPUT:
+*       target      - SDRAM target where the function skips checking.
+*       pAddrDecWin - The tested address window for overlapping with
+*					  SDRAM windows.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlaps any enabled address
+*       decode map, MV_FALSE otherwise.
+*
+*******************************************************************************/
+static MV_BOOL sdramIfWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin)
+{
+	MV_TARGET targetNum;
+	MV_DRAM_DEC_WIN addrDecWin;
+
+	for (targetNum = SDRAM_CS0; targetNum < MV_DRAM_MAX_CS; targetNum++) {
+		/* don't check our winNum or illegal targets */
+		if (targetNum == target)
+			continue;
+
+		/* Get window parameters        */
+		if (MV_OK != mvDramIfWinGet(targetNum, &addrDecWin)) {
+			mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n");
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled windows        */
+		if (MV_FALSE == addrDecWin.enable)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) {
+			mvOsPrintf("sdramIfWinOverlap: Required target %d overlap winNum %d\n", target, targetNum);
+			return MV_TRUE;
+		}
+	}
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvDramIfWinSet - Set DRAM interface address decode window
+*
+* DESCRIPTION:
+*       This function sets DRAM interface address decode window.
+*
+* INPUT:
+*	    target      - System target. Use only SDRAM targets.
+*       pAddrDecWin - SDRAM address window structure.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK
+*       otherwise.
+*******************************************************************************/
+MV_STATUS mvDramIfWinSet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin)
+{
+	MV_U32 baseReg = 0, sizeReg = 0;
+	MV_U32 sizeToReg = 0;
+
+	/* Check if the requested window overlaps with current enabled windows  */
+	if (MV_TRUE == sdramIfWinOverlap(target, &pAddrDecWin->addrWin)) {
+		mvOsPrintf("mvDramIfWinSet: ERR. Target %d overlaps\n", target);
+		return MV_BAD_PARAM;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) {
+		mvOsPrintf("mvDramIfWinSet:Error setting DRAM interface window %d."
+			   "\nAddress 0x%08x is unaligned to size 0x%x.\n",
+			   target, pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	/* read base register */
+	baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(0, target));
+
+	/* read size register */
+	sizeReg = MV_REG_READ(SDRAM_SIZE_REG(0, target));
+
+	/* Write to address decode Base Address Register                  */
+	baseReg &= ~SCBAR_BASE_MASK;
+	baseReg |= (pAddrDecWin->addrWin.baseLow & SCBAR_BASE_MASK);
+
+	/* Translate the given window size to register format                   */
+	sizeToReg = (pAddrDecWin->addrWin.size / SCSR_SIZE_ALIGNMENT) - 1;
+
+	/* set size */
+	sizeReg &= ~SCSR_SIZE_MASK;
+	/* Size is located at upper 16 bits */
+	sizeReg |= (sizeToReg << SCSR_SIZE_OFFS);
+
+	/* enable/Disable */
+	if (MV_TRUE == pAddrDecWin->enable)
+		sizeReg |= SCSR_WIN_EN;
+	else
+		sizeReg &= ~SCSR_WIN_EN;
+
+	/* 3) Write to address decode Base Address Register.            */
+	MV_REG_WRITE(SDRAM_BASE_ADDR_REG(0, target), baseReg);
+
+	/* Write to address decode Size Register.                       */
+	MV_REG_WRITE(SDRAM_SIZE_REG(0, target), sizeReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDramIfWinGet - Get DRAM interface address decode window
+*
+* DESCRIPTION:
+*       This function gets DRAM interface address decode window.
+*
+* INPUT:
+*	    target - System target. Use only SDRAM targets.
+*
+* OUTPUT:
+*       pAddrDecWin - SDRAM address window structure.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK
+*       otherwise.
+*******************************************************************************/
+MV_STATUS mvDramIfWinGet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin)
+{
+	MV_U32 baseReg, sizeReg;
+	MV_U32 sizeRegVal;
+
+	/* Read base and size registers */
+	sizeReg = MV_REG_READ(SDRAM_SIZE_REG(0, target));
+	baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(0, target));
+
+	sizeRegVal = (sizeReg & SCSR_SIZE_MASK) >> SCSR_SIZE_OFFS;
+
+	pAddrDecWin->addrWin.size = (sizeRegVal + 1) * SCSR_SIZE_ALIGNMENT;
+
+	/* Check if ctrlRegToSize returned OK */
+	if (-1 == pAddrDecWin->addrWin.size) {
+		mvOsPrintf("mvDramIfWinGet: size of target %d is Illigal\n", target);
+		return MV_ERROR;
+	}
+
+	/* Extract base address                                         */
+	/* Base register [31:16] ==> baseLow[31:16]             */
+	pAddrDecWin->addrWin.baseLow = baseReg & SCBAR_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh = 0;
+
+	if (sizeReg & SCSR_WIN_EN)
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDramIfWinEnable - Enable/Disable SDRAM address decode window
+*
+* DESCRIPTION:
+*		This function enable/Disable SDRAM address decode window.
+*
+* INPUT:
+*	    target - System target. Use only SDRAM targets.
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*		MV_ERROR in case function parameter are invalid, MV_OK otherewise.
+*
+*******************************************************************************/
+MV_STATUS mvDramIfWinEnable(MV_TARGET target, MV_BOOL enable)
+{
+	MV_DRAM_DEC_WIN addrDecWin;
+
+	if (enable == MV_TRUE) {
+		/* First check for overlap with other enabled windows                           */
+		if (MV_OK != mvDramIfWinGet(target, &addrDecWin)) {
+			mvOsPrintf("mvDramIfWinEnable:ERR. Getting target %d failed.\n", target);
+			return MV_ERROR;
+		}
+		/* Check for overlapping */
+		if (MV_FALSE == sdramIfWinOverlap(target, &(addrDecWin.addrWin))) {
+			/* No Overlap. Enable address decode winNum window              */
+			MV_REG_BIT_SET(SDRAM_SIZE_REG(0, target), SCSR_WIN_EN);
+		} else {	/* Overlap detected */
+			mvOsPrintf("mvDramIfWinEnable: ERR. Target %d overlap detect\n", target);
+			return MV_ERROR;
+		}
+	} else {		/* Disable address decode winNum window                             */
+		MV_REG_BIT_RESET(SDRAM_SIZE_REG(0, target), SCSR_WIN_EN);
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDramIfIsTypeDdr3
+*
+* DESCRIPTION:
+*	This function checks if DRAM controller is configured for DDR3 mode.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_TRUE if controller is configured for DDR3,
+*	MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_BOOL mvDramIfIsTypeDdr3(void)
+{
+	MV_U32 reg;
+	reg = MV_REG_READ(SDRAM_CONFIG_REG);
+
+	if ((reg & SDRAM_DTYPE_MASK) == SDRAM_DTYPE_DDR3)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIf.h b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIf.h
new file mode 100755
index 0000000..1d6af9c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIf.h
@@ -0,0 +1,178 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvDramIfh
+#define __INCmvDramIfh
+
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+/* includes */
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ddr2/mvDramIfRegs.h"
+#include "ddr2/mvDramIfConfig.h"
+#include "mvSysDdrConfig.h"
+
+/* defines  */
+/* DRAM Timing parameters */
+#define SDRAM_TWR                    15	/* ns tWr */
+#define SDRAM_TRFC_64_512M_AT_200MHZ 70	/* ns tRfc for dens 64-512 @ 200MHz */
+#define SDRAM_TRFC_64_512M           75	/* ns tRfc for dens 64-512          */
+#define SDRAM_TRFC_1G                120	/* ns tRfc for dens 1GB             */
+#define SDRAM_TR2R_CYC               1	/* cycle for tR2r                   */
+
+#define CAL_AUTO_DETECT     0	/* Do not force CAS latancy (mvDramIfDetect) */
+#define ECC_DISABLE         1	/* Force ECC to Disable                      */
+#define ECC_ENABLE          0	/* Force ECC to ENABLE                       */
+
+/* typedefs */
+/* enumeration for memory types */
+typedef enum _mvMemoryType {
+	MEM_TYPE_SDRAM,
+	MEM_TYPE_DDR1,
+	MEM_TYPE_DDR2
+} MV_MEMORY_TYPE;
+
+/* enumeration for DDR2 supported CAS Latencies */
+typedef enum _mvDimmDdr2Cas {
+	DDR2_CL_3 = 0x08,
+	DDR2_CL_4 = 0x10,
+	DDR2_CL_5 = 0x20,
+	DDR2_CL_6 = 0x40,
+	DDR2_CL_FAULT
+} MV_DIMM_DDR2_CAS;
+
+typedef struct _mvDramBankInfo {
+	MV_MEMORY_TYPE memoryType;	/* DDR1, DDR2 or SDRAM */
+
+	/* DIMM dimensions */
+	MV_U32 numOfRowAddr;
+	MV_U32 numOfColAddr;
+	MV_U32 dataWidth;
+	MV_U32 errorCheckType;	/* ECC , PARITY.. */
+	MV_U32 sdramWidth;	/* 4,8,16 or 32 */
+	MV_U32 errorCheckDataWidth;	/* 0 - no, 1 - Yes */
+	MV_U32 burstLengthSupported;
+	MV_U32 numOfBanksOnEachDevice;
+	MV_U32 suportedCasLatencies;
+	MV_U32 refreshInterval;
+
+	/* DIMM timing parameters */
+	MV_U32 minCycleTimeAtMaxCasLatPs;
+	MV_U32 minCycleTimeAtMaxCasLatMinus1Ps;
+	MV_U32 minCycleTimeAtMaxCasLatMinus2Ps;
+	MV_U32 minRowPrechargeTime;
+	MV_U32 minRowActiveToRowActive;
+	MV_U32 minRasToCasDelay;
+	MV_U32 minRasPulseWidth;
+	MV_U32 minWriteRecoveryTime;	/* DDR2 only */
+	MV_U32 minWriteToReadCmdDelay;	/* DDR2 only */
+	MV_U32 minReadToPrechCmdDelay;	/* DDR2 only */
+	MV_U32 minRefreshToActiveCmd;	/* DDR2 only */
+
+	/* Parameters calculated from the extracted DIMM information */
+	MV_U32 size;
+	MV_U32 deviceDensity;	/* 16,64,128,256 or 512 Mbit */
+	MV_U32 numberOfDevices;
+
+	/* DIMM attributes (MV_TRUE for yes) */
+	MV_BOOL registeredAddrAndControlInputs;
+	MV_BOOL registeredDQMBinputs;
+
+} MV_DRAM_BANK_INFO;
+
+typedef struct _mvDramIfDecWin {
+	MV_ADDR_WIN addrWin;	/* An address window */
+	MV_BOOL enable;	/* Address decode window is enabled/disabled    */
+} MV_DRAM_DEC_WIN;
+
+#include "ddr2/spd/mvSpd.h"
+
+/* mvDramIf.h API list */
+MV_STATUS mvDramIfWinSet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin);
+MV_STATUS mvDramIfWinGet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin);
+MV_STATUS mvDramIfWinEnable(MV_TARGET target, MV_BOOL enable);
+MV_BOOL mvDramIfIsTypeDdr3(void);
+MV_VOID mvDramIfBasicAsmInit(MV_VOID);
+MV_STATUS mvDramIfDetect(MV_U32 forcedCl, MV_BOOL eccDisable, MV_U32 sysClk);
+MV_VOID _mvDramIfConfig(int entryNum);
+
+MV_U32 mvDramIfBankSizeGet(MV_U32 bankNum);
+MV_U32 mvDramIfBankBaseGet(MV_U32 bankNum);
+MV_U32 mvDramIfSizeGet(MV_VOID);
+MV_U32 mvDramIfCalGet(void);
+MV_STATUS mvDramIfSingleBitErrThresholdSet(MV_U32 threshold);
+MV_VOID mvDramIfSelfRefreshSet(void);
+void mvDramIfShow(void);
+MV_U32 mvDramIfGetFirstCS(void);
+MV_U32 mvDramIfGetCSorder(MV_U32 csOrder);
+MV_U32 mvDramCsSizeGet(MV_U32 csNum);
+
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+#endif				/* __INCmvDramIfh */
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfBasicInit.S b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfBasicInit.S
new file mode 100755
index 0000000..c276f52
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfBasicInit.S
@@ -0,0 +1,1027 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#define	_ASMLANGUAGE
+#define MV_ASMLANGUAGE
+#include "mvSysHwConfig.h"
+#include "mvOsAsm.h"
+#include "boardEnv/mvBoardEnvSpec.h"
+#include "ctrlEnv/sys/mvCpuIfRegs.h"
+#include "mvDramIfConfig.h"
+#include "mvDramIfRegs.h"
+#include "pex/mvPexRegs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ctrlEnv/mvCtrlEnvAsm.h"
+#include "mvCommon.h"
+
+/* defines */
+#if defined(MV_STATIC_DRAM_ON_BOARD)
+/******************************************************************************
+* static definitions for several dimms
+*******************************************************************************/
+#if defined(DB_MV78XX0) || defined(DB_MV88F632X)
+#if defined(MV78100)
+/* DDR2 boards 512MB 333MHz */
+#define STATIC_SDRAM0_BANK0_SIZE		0x1ffffff1 /*	0x1504	*/
+#define STATIC_SDRAM_CONFIG	     		0x43048C30 /*	0x1400  */
+#define STATIC_DUNIT_CTRL_LOW			0x38543000 /*   0x1404  */
+#define STATIC_SDRAM_TIME_CTRL_LOW		0x22125441 /*   0x1408  */
+#define STATIC_SDRAM_TIME_CTRL_HI		0x00000A29 /*   0x140c  */
+#define STATIC_SDRAM_ADDR_CTRL			0x00000088 /*   0x1410  */
+#define STATIC_SDRAM_MODE	     		0x00000652 /*	0x141c  */
+#define STATIC_SDRAM_EXT_MODE          	0x00000040 /*   0x1420  */
+#define STATIC_DUNIT_CTRL_HI			0x0000FFFF /*   0x1424  */
+#define STATIC_SDRAM_DDR2_TIMING_LO		0x00085520 /*   0x1428  */
+#define STATIC_SDRAM_ODT_CTRL_LOW	    0x84210000 /*   0x1494  */
+#define STATIC_SDRAM_ODT_CTRL_HI	    0x00000000 /*   0x1498  */
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    	0x0000E80F /*   0x149c  */
+#define STATIC_SDRAM_DDR2_TIMING_HI		0x00008552 /*   0x147C  */
+
+#elif defined(MV78200)
+/*  512MB per CD,  800Mhz cl5  */
+#define	STATIC_DRAM_BANK_CS0
+#define	STATIC_DRAM_BANK_CS2
+
+#define STATIC_SDRAM0_BANK0_SIZE		0x1ffffff1 /*	0x1504	*/
+#define STATIC_SDRAM1_BANK0_SIZE		0x1ffffff9  /*  0x1514  */
+#define STATIC_SDRAM1_BANK0_BASE		0x20000000 /*   0x1510  */
+
+
+#define STATIC_SDRAM_CONFIG	     		0x43008C30 /*	0x1400  */
+#define STATIC_DUNIT_CTRL_LOW			0x37543010 /*   0x1404  */
+#define STATIC_SDRAM_TIME_CTRL_LOW		0x22125441 /*   0x1408  */
+#define STATIC_SDRAM_TIME_CTRL_HI		0x00000A29 /*   0x140c  */
+
+#define STATIC_SDRAM_ADDR_CTRL			0x00008888 /*   0x1410  */
+#define STATIC_SDRAM_MODE	     		0x00000652 /*	0x141c  */
+
+#define STATIC_SDRAM_EXT_MODE          	0x00000044 /*   0x1420  */
+#define STATIC_DUNIT_CTRL_HI			0x0000FF7F /*   0x1424  */
+#define STATIC_SDRAM_DDR2_TIMING_LO		0x00085520 /*   0x1428  */
+
+#define STATIC_SDRAM_DDR2_TIMING_HI		0x00008552 /*   0x147C  */
+
+#define STATIC_SDRAM_ODT_CTRL_LOW	    0x030C030C /*   0x1494  */
+#define STATIC_SDRAM_ODT_CTRL_HI	    0x00000000 /*   0x1498  */
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    	0x0000F40F /*   0x149c  */
+
+#endif
+
+#elif defined(RD_MV78XX0_AMC)
+/* On board DDR2 512MB 400MHz CL5 */
+#define STATIC_SDRAM0_BANK0_SIZE		0x1ffffff1 /*	0x1504	*/
+#define STATIC_SDRAM_CONFIG	     		0x43008C30 /*	0x1400  */
+#define STATIC_SDRAM_MODE	     		0x00000652 /*	0x141c  */
+#define STATIC_DUNIT_CTRL_LOW			0x38543000 /*   0x1404  */
+#define STATIC_DUNIT_CTRL_HI			0x0000F07F /*   0x1424  */
+#define STATIC_SDRAM_ADDR_CTRL			0x000000DD /*   0x1410  */
+#define STATIC_SDRAM_TIME_CTRL_LOW		0x23135441 /*   0x1408  */
+#define STATIC_SDRAM_TIME_CTRL_HI		0x00000A32 /*   0x140c  */
+#define STATIC_SDRAM_ODT_CTRL_LOW	     	0x84210000 /*   0x1494  */
+#define STATIC_SDRAM_ODT_CTRL_HI	     	0x00000000 /*   0x1498  */
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    		0x0000EB0F /*   0x149c  */
+#define STATIC_SDRAM_EXT_MODE          		0x00000040 /*   0x1420  */
+#define STATIC_SDRAM_DDR2_TIMING_LO		0x00085520 /*   0x1428  */
+#define STATIC_SDRAM_DDR2_TIMING_HI		0x00008552 /*   0x147C  */
+
+#define STATIC_SDRAM1_BANK0_SIZE       0x0FFFFFF1 /*  0x1514  */
+#define STATIC_SDRAM1_BANK0_BASE       0x10000000 /*   0x1510  */
+
+#elif defined(RD_MV78XX0_H3C)
+/* DDR2 boards 512MB 333MHz */
+#define STATIC_SDRAM0_BANK0_SIZE		0x1ffffff1 /*	0x1504	*/
+
+#define STATIC_SDRAM_CONFIG	     		0x43048a25 /*	0x1400  */
+#define STATIC_SDRAM_MODE	     		0x00000652 /*	0x141c  */
+#define STATIC_DUNIT_CTRL_LOW			0x38543000 /*   0x1404  */
+#define STATIC_DUNIT_CTRL_HI			0x0000F07F /*   0x1424  */
+#define STATIC_SDRAM_ADDR_CTRL			0x00000088 /*   0x1410  */
+#define STATIC_SDRAM_TIME_CTRL_LOW		0x2202444e /*   0x1408  */
+#define STATIC_SDRAM_TIME_CTRL_HI		0x00000A22 /*   0x140c  */
+#define STATIC_SDRAM_ODT_CTRL_LOW	     	0x84210000 /*   0x1494  */
+#define STATIC_SDRAM_ODT_CTRL_HI	     	0x00000000 /*   0x1498  */
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    		0x0000EB0F /*   0x149c  */
+#define STATIC_SDRAM_EXT_MODE          		0x00000040 /*   0x1420  */
+#define STATIC_SDRAM_DDR2_TIMING_LO		0x00085520 /*   0x1428  */
+#define STATIC_SDRAM_DDR2_TIMING_HI		0x00008552 /*   0x147C  */
+
+#elif defined(RD_MV78XX0_PCAC)
+/* DDR2 boards 256MB 200MHz */
+#define STATIC_SDRAM0_BANK0_SIZE		0x0ffffff1 /*	0x1504	*/
+#define STATIC_SDRAM_CONFIG	     		0x43000a25 /*	0x1400  */
+#define STATIC_SDRAM_MODE	     		0x00000652 /*	0x141c  */
+#define STATIC_DUNIT_CTRL_LOW			0x38543000 /*   0x1404  */
+#define STATIC_DUNIT_CTRL_HI			0x0000F07F /*   0x1424  */
+#define STATIC_SDRAM_ADDR_CTRL			0x000000DD /*   0x1410  */
+#define STATIC_SDRAM_TIME_CTRL_LOW		0x2202444e /*   0x1408  */
+#define STATIC_SDRAM_TIME_CTRL_HI		0x00000822 /*   0x140c  */
+#define STATIC_SDRAM_ODT_CTRL_LOW	     	0x84210000 /*   0x1494  */
+#define STATIC_SDRAM_ODT_CTRL_HI	     	0x00000000 /*   0x1498  */
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    		0x0000EB0F /*   0x149c  */
+#define STATIC_SDRAM_EXT_MODE          		0x00000040 /*   0x1420  */
+#define STATIC_SDRAM_DDR2_TIMING_LO		0x00085520 /*   0x1428  */
+#define STATIC_SDRAM_DDR2_TIMING_HI		0x00008552 /*   0x147C  */
+
+#else
+/* DDR2 MV88F6281 boards 256MB 400MHz */
+#define STATIC_SDRAM0_BANK0_SIZE		0x0FFFFFF1 /*	0x1504	*/
+#define STATIC_SDRAM_CONFIG	     		0x43000c30 /*	0x1400  */
+#define STATIC_SDRAM_MODE	     		0x00000C52 /*	0x141c  */
+#define STATIC_DUNIT_CTRL_LOW			0x39543000 /*   0x1404  */
+#define STATIC_DUNIT_CTRL_HI			0x0000F1FF /*   0x1424  */
+#define STATIC_SDRAM_ADDR_CTRL			0x000000cc /*   0x1410  */
+#define STATIC_SDRAM_TIME_CTRL_LOW		0x22125451 /*   0x1408  */
+#define STATIC_SDRAM_TIME_CTRL_HI		0x00000A33 /*   0x140c  */
+#define STATIC_SDRAM_ODT_CTRL_LOW	     	0x003C0000 /*   0x1494  */
+#define STATIC_SDRAM_ODT_CTRL_HI	     	0x00000000 /*   0x1498  */
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    		0x0000F80F /*   0x149c  */
+#define STATIC_SDRAM_EXT_MODE          		0x00000042 /*   0x1420  */
+#define STATIC_SDRAM_DDR2_TIMING_LO		0x00085520 /*   0x1428  */
+#define STATIC_SDRAM_DDR2_TIMING_HI		0x00008552 /*   0x147C  */
+#endif /* MV78XX0 */
+
+#endif /* MV_STATIC_DRAM_ON_BOARD */
+
+.globl dramBoot1
+dramBoot1:
+        .word   0
+/*************************************************************
+* basic timing init
+**************************************************************/
+	.globl _mvDramInitTiming
+_mvDramInitTiming:
+	/* Set Dunit high control register	      */
+        MV_REG_READ_ASM (r6, r5, SDRAM_DUNIT_CTRL_HI_REG)
+		orr		r6, r6, #BIT7 /* SDRAM__D2P_EN */
+		orr		r6, r6, #BIT8 /* SDRAM__P2D_EN */
+#ifdef MV78XX0
+		orr		r6, r6, #BIT9 /* SDRAM__ADD_HALF_FCC_EN */
+		orr		r6, r6, #BIT10 /* SDRAM__PUP_ZERO_SKEW_EN */
+		orr		r6, r6, #BIT11 /* SDRAM__WR_MASH_DELAY_EN */
+#endif
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_DUNIT_CTRL_HI_REG)
+
+#ifdef MV78XX0
+        MV_REG_READ_ASM (r6, r5, SDRAM_DUNIT_CTRL_REG)
+		orr		r6, r6, #BIT4	/* Enable 2T mode */
+		bic		r6, r6, #BIT6	/* clear ctrlPos */
+		MV_REG_WRITE_ASM (r6, r5, SDRAM_DUNIT_CTRL_REG)
+#endif
+
+
+     	/*DDR SDRAM Initialization Control */
+		ldr	r6, =DSICR_INIT_EN
+		MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG)
+2:		MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG)
+		and    	r6, r6, #DSICR_INIT_EN
+		cmp    	r6, #0
+		bne 	2b
+		mov		pc, lr
+
+
+#if defined(MV_STATIC_DRAM_ON_BOARD)
+/*************************************************************
+* basic init for static DRAM (on board dram no SPD)
+**************************************************************/
+
+	.globl _mvDramIfStaticInit
+_mvDramIfStaticInit:
+
+		mov     r11, LR     		/* Save link register */
+		mov		r10, r2
+		bl	    _mvDramInitTiming
+
+        /* If we boot from NAND jump to DRAM address */
+        mov     r5, #1
+        ldr     r6, =dramBoot1
+        str     r5, [r6]                /* We started executing from DRAM */
+
+        ldr     r6, dramBoot1
+        cmp     r6, #0
+        bne     1f
+
+	/* set all dram windows to 0 */
+		mov		r6, #0
+		MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,0))
+		MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,1))
+		MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,2))
+		MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,3))
+		ldr		r6, = STATIC_SDRAM0_BANK0_SIZE
+		MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,0))
+
+#ifdef STATIC_DRAM_BANK_CS2
+		ldr 	r6, = STATIC_SDRAM1_BANK0_SIZE
+		MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,2))
+		ldr		r6, = STATIC_SDRAM1_BANK0_BASE
+		MV_REG_WRITE_ASM(r6, r5, SDRAM_BASE_ADDR_REG (0,2))
+#endif
+
+
+	/* set all dram configuration in temp registers */
+		ldr		r6, = STATIC_SDRAM0_BANK0_SIZE
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG0)
+		ldr		r6, = STATIC_SDRAM_CONFIG
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG1)
+		ldr		r6, = STATIC_SDRAM_MODE
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG2)
+		ldr		r6, = STATIC_DUNIT_CTRL_LOW
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG3)
+		ldr		r6, = STATIC_SDRAM_ADDR_CTRL
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG4)
+		ldr		r6, = STATIC_SDRAM_TIME_CTRL_LOW
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG5)
+		ldr		r6, = STATIC_SDRAM_TIME_CTRL_HI
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG6)
+		ldr		r6, = STATIC_SDRAM_ODT_CTRL_LOW
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG7)
+		ldr		r6, = STATIC_SDRAM_ODT_CTRL_HI
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG8)
+		ldr		r6, = STATIC_SDRAM_DUNIT_ODT_CTRL
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG9)
+		ldr		r6, = STATIC_SDRAM_EXT_MODE
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG10)
+		ldr		r6, = STATIC_SDRAM_DDR2_TIMING_LO
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG11)
+		ldr		r6, = STATIC_SDRAM_DDR2_TIMING_HI
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG12)
+#ifndef MTD_NAND_LNC_BOOT
+		ldr		r6, = STATIC_DUNIT_CTRL_HI
+		MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG13)
+#endif
+
+		ldr		sp,=0
+		bl		_mvDramIfConfig
+		ldr		r0, =0
+#ifdef MV78XX0
+		bl	_mvDramIfEccMemInit
+#ifdef STATIC_DRAM_BANK_CS2
+		ldr 	r0, =2
+		bl 		_mvDramIfEccMemInit
+#endif
+		ldr 	r0, =0
+#endif
+1:
+		mov 	r2, r10
+		mov     PC, r11         	/* r11 is saved link register */
+
+#else  /* #if defined(MV_STATIC_DRAM_ON_BOARD) */
+
+/*******************************************************************************
+* mvDramIfBasicInit - Basic initialization of DRAM interface
+*
+* DESCRIPTION:
+*       The function will initialize the DRAM for basic usage. The function
+*       will use the TWSI assembly API to extract DIMM parameters according
+*       to which DRAM interface will be initialized.
+*       The function referes to the following DRAM parameters:
+*       1) DIMM is registered or not.
+*       2) DIMM width detection.
+*       3) DIMM density.
+*
+* INPUT:
+*       r3 - required size for initial DRAM.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*       Note:
+*       r4 holds I2C EEPROM address
+*       r5 holds SDRAM register base address
+*	r7 holds returned values
+*       r8 holds SDRAM various configuration registers value.
+*       r11 holds return function address.
+*******************************************************************************/
+/* Setting the offsets of the I2C registers */
+#define DIMM_TYPE_OFFSET	      2
+#define NUM_OF_ROWS_OFFSET            3
+#define NUM_OF_COLS_OFFSET            4
+#define NUM_OF_RANKS		      5
+#define DIMM_CONFIG_TYPE             11
+#define SDRAM_WIDTH_OFFSET           13
+#define NUM_OF_BANKS_OFFSET          17
+#define SUPPORTED_CL_OFFSET          18
+#define DIMM_TYPE_INFO_OFFSET        20         /* DDR2 only    */
+#define SDRAM_MODULES_ATTR_OFFSET    21
+#define RANK_SIZE_OFFSET             31
+
+#define DRAM_DEV_DENSITY_128M         128
+#define DRAM_DEV_DENSITY_256M         256
+#define DRAM_DEV_DENSITY_512M         512
+#define DRAM_DEV_DENSITY_1G          1024
+#define DRAM_DEV_DENSITY_2G          2048
+
+#define DRAM_RANK_DENSITY_128M       0x20
+#define DRAM_RANK_DENSITY_256M       0x40
+#define DRAM_RANK_DENSITY_512M       0x80
+#define DRAM_RANK_DENSITY_1G	     0x1
+#define DRAM_RANK_DENSITY_2G	     0x2
+
+       .globl _mvDramIfBasicInit
+       .extern _i2cInit
+_mvDramIfBasicInit:
+
+        mov     r11, LR     		/* Save link register */
+
+		bl	    _mvDramInitTiming
+
+        mov     r5, #1
+        ldr     r8, =dramBoot1
+        str     r5, [r8]                /* We started executing from DRAM */
+
+        /* If we boot from NAND jump to DRAM address */
+        ldr     r8, dramBoot1
+        cmp     r8, #0
+        movne   pc, r11
+
+        bl      _i2cInit                /* Initialize TWSI master             */
+
+        /* Check if we have more then 1 dimm */
+		ldr		r6, =0
+		MV_REG_WRITE_ASM (r6, r1, DRAM_BUF_REG14)
+#ifdef MV78XX0
+		bl		_is_Second_Dimm_Exist
+		beq 	single_dimm
+		ldr		r6, =1
+		MV_REG_WRITE_ASM (r6, r1, DRAM_BUF_REG14)
+single_dimm:
+        bl      _i2cInit                /* Initialize TWSI master             */
+#endif
+
+        /* Get default SDRAM Config values */
+        MV_REG_READ_ASM (r8, r5, SDRAM_CONFIG_REG)
+
+        /* Get registered/non registered info from DIMM */
+		bl  	_is_Registered
+        beq     nonRegistered
+
+setRegistered:
+        orr     r8, r8, #SDRAM_REGISTERED   /* Set registered bit(17)         */
+nonRegistered:
+#if defined(MV78XX0) && !defined(MV632X)
+        /* Get ECC/non ECC info from DIMM */
+		bl  	_is_Ecc
+        beq     setConfigReg
+
+setEcc:
+        orr     r8, r8, #SDRAM_ECC_EN   /* Set ecc bit(18)         */
+#endif
+setConfigReg:
+        MV_REG_WRITE_ASM (r8, r5, DRAM_BUF_REG1)
+
+        /* Set maximum CL supported by DIMM */
+		bl	_get_CAL
+
+        /* r7 is DIMM supported CAS (e.g: 3 --> 0x1C)                         */
+        clz     r6, r7
+        rsb     r6, r6, #31     /* r6 = the bit number of MAX CAS supported   */
+
+casDdr2:
+		ldr     r7, =0x41        /* stBurstInDel|stBurstOutDel field value     */
+		ldr     r3, =0x53       /* stBurstInDel|stBurstOutDel registered value*/
+		ldr     r8, =0x32      /* Assuming MAX CL = 3           */
+        cmp     r6, #3          /* If CL = 3 break              */
+        beq     casDdr2Cont
+
+		ldr     r7, =0x53        /* stBurstInDel|stBurstOutDel field value     */
+		ldr     r3, =0x65       /* stBurstInDel|stBurstOutDel registered value*/
+		ldr     r8, =0x42      /* Assuming MAX CL = 4           */
+        cmp     r6, #4          /* If CL = 4 break              */
+        beq     casDdr2Cont
+
+		ldr     r7, =0x65        /* stBurstInDel|stBurstOutDel field value     */
+		ldr     r3, =0x77       /* stBurstInDel|stBurstOutDel registered value*/
+		ldr     r8, =0x52      /* Assuming MAX CL = 5           */
+        cmp     r6, #5          /* If CL = 5 break              */
+        beq     casDdr2Cont
+
+		ldr     r7, =0x77        /* stBurstInDel|stBurstOutDel field value     */
+		ldr     r3, =0x89       /* stBurstInDel|stBurstOutDel registered value*/
+		ldr     r8, =0x62      /* Assuming MAX CL = 6           */
+        cmp     r6, #6          /* If CL = 5 break              */
+        beq     casDdr2Cont
+
+        /* This is an error. return */
+        b       exit_ddrAutoConfig      /* This is an error !!  */
+casDdr2Cont:
+
+        /* Get default SDRAM Mode values */
+        MV_REG_READ_ASM (r6, r5, SDRAM_MODE_REG)
+        bic     r6, r6, #(BIT6 | BIT5 | BIT4) /* Clear CL filed */
+		orr		r6, r6, r8
+        MV_REG_WRITE_ASM (r6, r5, DRAM_BUF_REG2)
+
+	/* Set Dunit control register according to max CL detected	      */
+        MV_REG_READ_ASM (r6, r5, DRAM_BUF_REG1)
+		tst		r6, #SDRAM_REGISTERED
+		beq		setDunitReg
+		mov		r7, r3
+
+setDunitReg:
+#ifdef MV78XX0
+        /* Set SDRAM Extended Mode register for double DIMM */
+	/* Check DRAM frequency for more then 267MHz set ODT Rtt to 50ohm */
+
+        MV_REG_READ_ASM (r4, r5, CPU_RESET_SAMPLE_L_REG)
+		ldr		r5, =MSAR_SYSCLCK_MASK
+		and		r4, r4, r5
+		ldr		r5, =MSAR_SYSCLCK_333
+		cmp		r4, r5
+		ble		Clock333
+		add 	r7, r7, #0x10
+Clock333:
+#endif
+
+        MV_REG_READ_ASM (r6, r5, SDRAM_DUNIT_CTRL_REG)
+		bic		r6, r6, #(0xff << 20) /* Clear SBout and SBin */
+		orr		r6, r6, #BIT4	/* Enable 2T mode */
+		bic		r6, r6, #BIT6	/* clear ctrlPos */
+		orr		r6, r6, r7, LSL #20
+        MV_REG_WRITE_ASM (r6, r5, DRAM_BUF_REG3)
+
+	/* Set Dunit high control register	      */
+        MV_REG_READ_ASM (r6, r5, SDRAM_DUNIT_CTRL_HI_REG)
+		orr		r6, r6, #BIT7 /* SDRAM__D2P_EN */
+		orr		r6, r6, #BIT8 /* SDRAM__P2D_EN */
+#ifdef MV78XX0
+		orr		r6, r6, #BIT9 /* SDRAM__ADD_HALF_FCC_EN */
+		orr		r6, r6, #BIT10 /* SDRAM__PUP_ZERO_SKEW_EN */
+		orr		r6, r6, #BIT11 /* SDRAM__WR_MASH_DELAY_EN */
+#endif
+        MV_REG_WRITE_ASM (r6, r5, DRAM_BUF_REG13)
+
+        /* DIMM density configuration*/
+        /* Density = (1 << (rowNum + colNum)) * dramWidth * dramBankNum       */
+Density:
+	/* Get bank 0 and 1 density */
+		ldr		r6, =0
+		bl 		_getDensity
+
+		mov 	r8, r7
+        mov     r8, r8, LSR #20 /* Move density 20 bits to the right  */
+                                /* For example 0x10000000 --> 0x1000 */
+
+        mov     r3, #(SDRAM_DSIZE_256Mb(0) | SDRAM_DSIZE_256Mb(1))
+        cmp     r8, #DRAM_DEV_DENSITY_256M
+        beq     get_bank_2_density
+
+        mov     r3, #(SDRAM_DSIZE_512Mb(0) | SDRAM_DSIZE_512Mb(1))
+        cmp     r8, #DRAM_DEV_DENSITY_512M
+        beq     get_bank_2_density
+
+        mov     r3, #(SDRAM_DSIZE_1Gb(0) | SDRAM_DSIZE_1Gb(1))
+        cmp     r8, #DRAM_DEV_DENSITY_1G
+        beq     get_bank_2_density
+
+        mov     r3, #(SDRAM_DSIZE_2Gb(0) | SDRAM_DSIZE_2Gb(1))
+        cmp     r8, #DRAM_DEV_DENSITY_2G
+        beq     get_bank_2_density
+
+        /* This is an error. return */
+        b       exit_ddrAutoConfig
+
+get_bank_2_density:
+	/* Check for second dimm */
+	MV_REG_READ_ASM (r6, r1, DRAM_BUF_REG14)
+		cmp		r6, #1
+		bne 	get_width
+
+	/* Get bank 2 and 3 density */
+		ldr		r6, =2
+		bl 		_getDensity
+
+		mov 	r8, r7
+        mov     r8, r8, LSR #20 /* Move density 20 bits to the right  */
+                                /* For example 0x10000000 --> 0x1000 */
+
+        orr     r3, r3, #(SDRAM_DSIZE_256Mb(2) | SDRAM_DSIZE_256Mb(3))
+        cmp     r8, #DRAM_DEV_DENSITY_256M
+        beq     get_width
+
+        and     r3, r3, #~(SDRAM_DSIZE_MASK(2) | SDRAM_DSIZE_MASK(3))
+        orr     r3, r3, #(SDRAM_DSIZE_512Mb(2) | SDRAM_DSIZE_512Mb(3))
+        cmp     r8, #DRAM_DEV_DENSITY_512M
+        beq     get_width
+
+        and     r3, r3, #~(SDRAM_DSIZE_MASK(2) | SDRAM_DSIZE_MASK(3))
+        orr     r3, r3, #(SDRAM_DSIZE_1Gb(2) | SDRAM_DSIZE_1Gb(3))
+        cmp     r8, #DRAM_DEV_DENSITY_1G
+        beq     get_width
+
+        and     r3, r3, #~(SDRAM_DSIZE_MASK(2) | SDRAM_DSIZE_MASK(3))
+        orr     r3, r3, #(SDRAM_DSIZE_2Gb(2) | SDRAM_DSIZE_2Gb(3))
+        cmp     r8, #DRAM_DEV_DENSITY_2G
+        beq     get_width
+
+        /* This is an error. return */
+        b       exit_ddrAutoConfig
+
+	/* Get SDRAM width */
+get_width:
+	/* Get bank 0 and 1 width */
+		ldr		r6, =0
+		bl 		_get_width
+
+        cmp     r7, #8           /* x8 devices   */
+        beq     get_bank_2_width
+
+        orr     r3, r3, #(SDRAM_ADDRSEL_X16(0) | SDRAM_ADDRSEL_X16(1)) /* x16 devices  */
+        cmp     r7, #16
+        beq     get_bank_2_width
+
+        /* This is an error. return */
+        b       exit_ddrAutoConfig
+
+get_bank_2_width:
+	/* Check for second dimm */
+	MV_REG_READ_ASM (r6, r1, DRAM_BUF_REG14)
+		cmp		r6, #1
+		bne 	densCont
+
+	/* Get bank 2 and 3 width */
+		ldr		r6, =2
+		bl 		_get_width
+
+        cmp     r7, #8           /* x8 devices   */
+        beq     densCont
+
+        orr     r3, r3, #(SDRAM_ADDRSEL_X16(2) | SDRAM_ADDRSEL_X16(3)) /* x16 devices  */
+        cmp     r7, #16
+        beq     densCont
+
+        /* This is an error. return */
+        b       exit_ddrAutoConfig
+
+densCont:
+        MV_REG_WRITE_ASM (r3, r5, DRAM_BUF_REG4)
+
+        /* Set SDRAM timing control low register */
+		ldr		r4, =SDRAM_TIMING_CTRL_LOW_REG_DEFAULT
+        /* MV_REG_READ_ASM (r4, r5, SDRAM_TIMING_CTRL_LOW_REG) */
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG5)
+
+        /* Set SDRAM timing control high register */
+		ldr		r6, =SDRAM_TIMING_CTRL_HIGH_REG_DEFAULT
+
+		MV_REG_READ_ASM (r4, r5, CPU_RESET_SAMPLE_L_REG)
+		ldr		r5, =MSAR_SYSCLCK_MASK
+		and		r4, r4, r5
+		ldr		r5, =MSAR_SYSCLCK_333
+		cmp		r4, r5
+		blt		timingHighClock333
+		orr 	r6, r6, #BIT9
+
+timingHighClock333:
+    /* MV_REG_READ_ASM (r6, r5, SDRAM_TIMING_CTRL_HIGH_REG) */
+    MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG6)
+
+	/* Check for second dimm */
+	MV_REG_READ_ASM (r6, r1, DRAM_BUF_REG14)
+		cmp		r6, #1
+		bne 	single_dimm_odt
+
+        /* Set SDRAM ODT control low register for double DIMM*/
+        ldr		r4, =DDR2_ODT_CTRL_LOW_CS0_CS1_CS2_CS3_DV
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG7)
+
+        /* Set DUNIT ODT control register for double DIMM */
+        ldr		r4, =DDR2_DUNIT_ODT_CTRL_CS0_CS1_CS2_CS3_DV
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG9)
+
+#ifdef MV78XX0
+        /* Set SDRAM Extended Mode register for double DIMM */
+	/* Check DRAM frequency for more then 267MHz set ODT Rtt to 50ohm */
+
+        MV_REG_READ_ASM (r4, r5, CPU_RESET_SAMPLE_L_REG)
+		ldr		r5, =MSAR_SYSCLCK_MASK
+		and		r4, r4, r5
+		ldr		r5, =MSAR_SYSCLCK_267
+		cmp		r4, r5
+		beq		slow_dram_clock_rtt
+		ldr		r5, =MSAR_SYSCLCK_300
+		cmp		r4, r5
+		beq		slow_dram_clock_rtt
+		ldr		r5, =MSAR_SYSCLCK_333
+		cmp		r4, r5
+		beq		fast_dram_clock_rtt
+		ldr		r5, =MSAR_SYSCLCK_400
+		cmp		r4, r5
+		beq		fast_dram_clock_rtt
+
+		b		slow_dram_clock_rtt
+
+fast_dram_clock_rtt:
+        ldr		r4, =DDR_SDRAM_EXT_MODE_FAST_CS0_CS1_CS2_CS3_DV
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG10)
+		b 		odt_config_end
+#endif
+slow_dram_clock_rtt:
+        ldr	r4, =DDR_SDRAM_EXT_MODE_CS0_CS1_CS2_CS3_DV
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG10)
+		b 		odt_config_end
+
+single_dimm_odt:
+        /* Set SDRAM ODT control low register */
+        ldr		r4, =DDR2_ODT_CTRL_LOW_CS0_CS1_DV
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG7)
+
+        /* Set DUNIT ODT control register */
+        ldr		r4, =DDR2_DUNIT_ODT_CTRL_CS0_CS1_DV
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG9)
+
+        /* Set SDRAM Extended Mode register */
+        ldr		r4, =DDR_SDRAM_EXT_MODE_CS0_CS1_DV
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG10)
+
+odt_config_end:
+        /* SDRAM ODT control high register is left as default */
+        MV_REG_READ_ASM (r4, r5, DDR2_SDRAM_ODT_CTRL_HIGH_REG)
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG8)
+
+        /*Read CL and set the DDR2 registers accordingly */
+        MV_REG_READ_ASM (r6, r5, DRAM_BUF_REG2)
+        and 	r6, r6, #SDRAM_CL_MASK
+        mov 	r4, r6
+        orr 	r4, r4, r6, LSL #4
+        orr 	r4, r4, r6, LSL #8
+        orr 	r4, r4, r6, LSL #12
+        mov 	r5, #0x30000
+        add 	r4, r4, r5
+        sub 	r4, r4, #0x30
+        /* Set SDRAM Ddr2 Timing Low register */
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG11)
+
+        /* Set SDRAM Ddr2 Timing High register */
+        mov 	r4, r4, LSR #4
+        MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG12)
+
+timeParamDone:
+	/* Close all windows */
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,0))
+        and		r6, r6,#~SCSR_SIZE_MASK
+        and		r6, r6,#~1
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,0))
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,1))
+        and		r6, r6,#~SCSR_SIZE_MASK
+        and		r6, r6,#~1
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,1))
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,2))
+        and		r6, r6,#~SCSR_SIZE_MASK
+        and		r6, r6,#~1
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,2))
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,3))
+        and		r6, r6,#~SCSR_SIZE_MASK
+        and		r6, r6,#~1
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,3))
+
+        /* Set sdram bank 0 size and enable it */
+		ldr		r6, =0
+		bl 		_mvDramIfGetDimmSizeFromSpd
+#ifdef MV78XX0
+	/* Check DRAM width */
+        MV_REG_READ_ASM (r4, r5, SDRAM_CONFIG_REG)
+		ldr		r5, =SDRAM_DWIDTH_MASK
+		and		r4, r4, r5
+		ldr		r5, =SDRAM_DWIDTH_64BIT
+		cmp		r4, r5
+		beq		dram_64bit_width
+		/* Utilize only 32bit width */
+		mov		r8, r8, LSR #1
+#else
+	/* Utilize only 16bit width */
+	mov	r8, r8, LSR #2
+#endif
+dram_64bit_width:
+	/* Update first dimm size return value R8 */
+        MV_REG_READ_ASM (r5, r6, SDRAM_SIZE_REG(0,0))
+        ldr		r6, =~SCSR_SIZE_MASK
+		and		r5, r5, r6
+		orr		r5, r5, r8
+        MV_REG_WRITE_ASM(r5, r8, SDRAM_SIZE_REG(0,0))
+
+	/* Clear bank 2 size */
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,2))
+        and		r6, r6,#~SCSR_SIZE_MASK
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,2))
+
+	/* Check for second dimm */
+	MV_REG_READ_ASM (r6, r1, DRAM_BUF_REG14)
+		cmp		r6, #1
+		bne 	defualt_order
+
+        /* Set sdram bank 2 size */
+	ldr	r6, =2
+	bl _mvDramIfGetDimmSizeFromSpd
+#ifdef MV78XX0
+	/* Check DRAM width */
+        MV_REG_READ_ASM (r4, r5, SDRAM_CONFIG_REG)
+		ldr		r5, =SDRAM_DWIDTH_MASK
+		and		r4, r4, r5
+		ldr		r5, =SDRAM_DWIDTH_64BIT
+		cmp		r4, r5
+		beq		dram_64bit_width2
+	/* Utilize only 32bit width */
+		mov		r8, r8, LSR #1
+#else
+	/* Utilize only 16bit width */
+		mov		r8, r8, LSR #2
+#endif
+dram_64bit_width2:
+	/* Update first dimm size return value R8 */
+        MV_REG_READ_ASM (r5, r6, SDRAM_SIZE_REG(0,2))
+        ldr		r6, =~SCSR_SIZE_MASK
+		and		r5, r5, r6
+		orr		r5, r5, r8
+        MV_REG_WRITE_ASM(r5, r8, SDRAM_SIZE_REG(0,2))
+
+	/* Close windows 1 and 3 */
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,1))
+        and		r6, r6,#~1
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,1))
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,3))
+        and		r6, r6,#~1
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,3))
+
+	/* Check dimm size for setting dram bank order */
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,0))
+        MV_REG_READ_ASM (r4, r5, SDRAM_SIZE_REG(0,2))
+        and		r6, r6,#SCSR_SIZE_MASK
+        and		r4, r4,#SCSR_SIZE_MASK
+		cmp		r6, r4
+		bge		defualt_order
+
+	/* Bank 2 is biger then bank 0 */
+		ldr		r6,=0
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_BASE_ADDR_REG(0,2))
+
+	/* Open win 2 */
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,2))
+        orr		r6, r6,#1
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,2))
+
+		ldr		sp,=0
+		bl		_mvDramIfConfig
+#ifdef MV78XX0
+	/* Init ECC on CS 2 */
+		ldr		r0, =2
+		bl		_mvDramIfEccMemInit
+#endif
+        mov     PC, r11         /* r11 is saved link register */
+
+defualt_order:
+
+	/* Open win 0 */
+        MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,0))
+        orr		r6, r6,#1
+        MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,0))
+
+		ldr		sp,=0
+		bl		_mvDramIfConfig
+#ifdef MV78XX0
+	/* Init ECC on CS 0 */
+		ldr		r0, =0
+		bl		_mvDramIfEccMemInit
+#endif
+exit_ddrAutoConfig:
+        mov     PC, r11         /* r11 is saved link register */
+
+
+/***************************************************************************************/
+/*       r4 holds I2C EEPROM address
+ *       r7 holds I2C EEPROM offset parameter for i2cRead and its --> returned value
+ *       r8 holds SDRAM various configuration registers value.
+ *	r13 holds Link register
+ */
+/**************************/
+_getDensity:
+		mov     r13, LR                            /* Save link register */
+
+	/* Read SPD rank size from DIMM0 */
+        mov     r4, #MV_BOARD_DIMM0_I2C_ADDR       /* reading from DIMM0      */
+
+		cmp		r6, #0
+		beq		1f
+
+	/* Read SPD rank size from DIMM1 */
+        mov     r4, #MV_BOARD_DIMM1_I2C_ADDR /* reading from DIMM1            */
+
+1:
+        mov     r7, #NUM_OF_ROWS_OFFSET            /* offset  3               */
+        bl      _i2cRead
+        mov     r8, r7                             /* r8 save number of rows  */
+
+        mov     r7, #NUM_OF_COLS_OFFSET            /* offset  4               */
+        bl      _i2cRead
+        add     r8, r8, r7                         /* r8 = number of rows + number of col */
+
+        mov     r7, #0x1
+        mov     r8, r7, LSL r8                     /* r8 = (1 << r8)          */
+
+        mov     r7, #SDRAM_WIDTH_OFFSET            /* offset 13 */
+        bl      _i2cRead
+        mul     r8, r7, r8
+
+        mov     r7, #NUM_OF_BANKS_OFFSET           /* offset 17               */
+        bl      _i2cRead
+        mul     r7, r8, r7
+
+		mov     PC, r13
+
+/**************************/
+_get_width:
+		mov     r13, LR                 /* Save link register */
+
+	/* Read SPD rank size from DIMM0 */
+        mov     r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0            */
+
+		cmp		r6, #0
+		beq		1f
+
+	/* Read SPD rank size from DIMM1 */
+        mov     r4, #MV_BOARD_DIMM1_I2C_ADDR /* reading from DIMM1            */
+
+1:
+        /* Get SDRAM width (SPD offset 13) */
+        mov     r7, #SDRAM_WIDTH_OFFSET
+        bl      _i2cRead                /* result in r7                       */
+
+		mov     PC, r13
+
+/**************************/
+_get_CAL:
+		mov     r13, LR                 /* Save link register */
+
+        /* Set maximum CL supported by DIMM */
+        mov     r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0            */
+        mov     r7, #SUPPORTED_CL_OFFSET     /* offset  18 */
+        bl      _i2cRead
+
+		mov     PC, r13
+
+/**************************/
+/* R8 - sdram configuration register.
+ * Return value in flag if no-registered then Z-flag is set
+ */
+_is_Registered:
+		mov     r13, LR                 /* Save link register */
+#if defined(MV645xx)
+        /* Get registered/non registered info from DIMM */
+        tst     r8, #SDRAM_DTYPE_DDR2
+        bne     regDdr2
+
+regDdr1:
+        mov     r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0            */
+        mov     r7, #SDRAM_MODULES_ATTR_OFFSET
+        bl      _i2cRead                /* result in r7                       */
+
+        tst     r7, #0x2
+		b	exit
+#endif
+regDdr2:
+        mov     r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0            */
+        mov     r7, #DIMM_TYPE_INFO_OFFSET
+        bl      _i2cRead                /* result in r7                       */
+
+        tst     r7, #0x11               /* DIMM type = regular RDIMM (0x01)   */
+                                        /* or Mini-RDIMM (0x10)               */
+exit:
+        mov     PC, r13
+
+
+/**************************/
+/* Return value in flag if no-Ecc then Z-flag is set */
+_is_Ecc:
+		mov     r13, LR                 /* Save link register */
+
+        mov     r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0            */
+        mov     r7, #DIMM_CONFIG_TYPE
+        bl      _i2cRead                /* result in r7                       */
+
+        tst     r7, #0x2               /* bit 1 -> Data ECC */
+        mov     PC, r13
+
+/**************************/
+/* Return value in flag if no second DIMM then Z-flag is set */
+_is_Second_Dimm_Exist:
+		mov     r13, LR                 /* Save link register */
+
+        mov     r4, #MV_BOARD_DIMM1_I2C_ADDR /* reading from DIMM0            */
+        mov     r7, #DIMM_TYPE_OFFSET
+        bl      _i2cRead                /* result in r7                       */
+
+     	tst     r7, #0x8               /* bit3 is '1' -> DDR 2 */
+        mov     PC, r13
+
+/*******************************************************************************
+* _mvDramIfGetDimmSizeFromSpd  - read bank 0 dram's size
+*
+* DESCRIPTION:
+*       The function will read the bank 0 dram size(SPD version 1.0 and above )
+*
+* INPUT:
+*       r6 - dram bank number.
+*
+* OUTPUT:
+*	none
+*/
+_mvDramIfGetDimmSizeFromSpd:
+
+	mov     r13, LR                 /* Save link register */
+
+	/* Read SPD rank size from DIMM0 */
+        mov     r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0            */
+
+		cmp		r6, #0
+		beq		1f
+
+	/* Read SPD rank size from DIMM1 */
+        mov     r4, #MV_BOARD_DIMM1_I2C_ADDR /* reading from DIMM1            */
+
+1:
+        mov     r7, #RANK_SIZE_OFFSET	/* offset  31 */
+        bl      _i2cRead
+
+pass_read:
+      	ldr     r8, =(0x7 << SCSR_SIZE_OFFS)
+        cmp		r7, #DRAM_RANK_DENSITY_128M
+        beq     endDimmSize
+
+      	ldr     r8, =(0xf << SCSR_SIZE_OFFS)
+        cmp		r7, #DRAM_RANK_DENSITY_256M
+        beq     endDimmSize
+
+        ldr     r8, =(0x1f << SCSR_SIZE_OFFS)
+        cmp		r7, #DRAM_RANK_DENSITY_512M
+        beq     endDimmSize
+
+        ldr     r8, =(0x3f << SCSR_SIZE_OFFS)
+        cmp		r7, #DRAM_RANK_DENSITY_1G
+        beq     endDimmSize
+
+        ldr     r8, =(0x7f  << SCSR_SIZE_OFFS)     /* DRAM_RANK_DENSITY_2G */
+endDimmSize:
+        mov     PC, r13
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfConfig.S b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfConfig.S
new file mode 100755
index 0000000..ca47448
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfConfig.S
@@ -0,0 +1,528 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvDramIfBasicAsm.s
+*
+* DESCRIPTION:
+*       Memory full detection and best timing configuration is done in
+*       C code. C runtime environment requires a stack. This module API
+*       initialize DRAM interface chip select 0 for basic functionality for
+*       the use of stack.
+*       The module API assumes DRAM information is stored in I2C EEPROM reside
+*       in a given I2C address MV_BOARD_DIMM0_I2C_ADDR. The I2C EEPROM
+*       internal data structure is assumed to be orgenzied in common DRAM
+*       vendor SPD structure.
+*       NOTE: DFCDL values are assumed to be already initialized prior to
+*       this module API activity.
+*
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+/* includes */
+#define	_ASMLANGUAGE
+#define MV_ASMLANGUAGE
+#include "mvOsAsm.h"
+#include "mvSysHwConfig.h"
+#include "mvDramIfRegs.h"
+#include "mvDramIfConfig.h"
+#include "mvCpuIfRegs.h"
+#include "pex/mvPexRegs.h"
+#include "mvCtrlEnvSpec.h"
+#include "mvCommon.h"
+#include "mvSysXorConfig.h"
+
+/* defines  */
+
+/* locals   */
+.data
+.globl _mvDramIfConfig
+.text
+.globl _mvDramIfMemInit
+
+/*******************************************************************************
+* _mvDramIfConfig - Basic DRAM interface initialization.
+*
+* DESCRIPTION:
+*       The function will initialize the following DRAM parameters using the
+*       values prepared by mvDramIfDetect routine. Values are located
+*       in predefined registers.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+
+_mvDramIfConfig:
+
+        /* Save register on stack */
+	cmp	sp, #0
+	beq	no_stack_s
+save_on_stack:
+        stmdb	sp!, {r1, r2, r3, r4}
+no_stack_s:
+
+	/* Dunit FTDLL Configuration Register */
+	/* 0) Write to SDRAM FTDLL coniguration register */
+        ldr     r4, = SDRAM_FTDLL_REG_DEFAULT_LEFT;
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_FTDLL_CONFIG_LEFT_REG)
+        str     r4, [r1]
+        ldr     r4, = SDRAM_FTDLL_REG_DEFAULT_RIGHT;
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_FTDLL_CONFIG_RIGHT_REG)
+        str     r4, [r1]
+        ldr     r4, = SDRAM_FTDLL_REG_DEFAULT_UP;
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_FTDLL_CONFIG_UP_REG)
+        str     r4, [r1]
+
+	/* 1) Write to SDRAM coniguration register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG1)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_CONFIG_REG)
+        str     r4, [r1]
+
+	/* 2) Write Dunit control low register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG3)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_DUNIT_CTRL_REG)
+        str     r4, [r1]
+
+	/* 2) Write Dunit control high register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG13)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_DUNIT_CTRL_HI_REG)
+        str     r4, [r1]
+
+        /* 3) Write SDRAM address control register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG4)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_ADDR_CTRL_REG)
+        str     r4, [r1]
+#if defined(MV_STATIC_DRAM_ON_BOARD)
+        /* 4) Write SDRAM bank 0 size register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG0)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_SIZE_REG(0,0))
+        str     r4, [r1]
+#endif
+
+        /* 5) Write SDRAM open pages control register */
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_OPEN_PAGE_CTRL_REG)
+        ldr     r4, =SDRAM_OPEN_PAGES_CTRL_REG_DV
+        str     r4, [r1]
+
+        /* 6) Write SDRAM timing Low register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG5)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_TIMING_CTRL_LOW_REG)
+        str     r4, [r1]
+
+        /* 7) Write SDRAM timing High register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG6)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_TIMING_CTRL_HIGH_REG)
+        str     r4, [r1]
+
+        /* Config DDR2 On Die Termination (ODT) registers */
+        /* Write SDRAM DDR2 ODT control low register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG7)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + DDR2_SDRAM_ODT_CTRL_LOW_REG)
+        str     r4, [r1]
+
+        /* Write SDRAM DDR2 ODT control high register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG8)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + DDR2_SDRAM_ODT_CTRL_HIGH_REG)
+        str     r4, [r1]
+
+        /* Write SDRAM DDR2 Dunit ODT control register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG9)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + DDR2_DUNIT_ODT_CONTROL_REG)
+        str     r4, [r1]
+
+        /* Write DDR2 SDRAM timing Low register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG11)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_DDR2_TIMING_LO_REG)
+        str     r4, [r1]
+
+        /* Write DDR2 SDRAM timing High register */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG12)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_DDR2_TIMING_HI_REG)
+        str     r4, [r1]
+
+        /* 8) Write SDRAM mode register */
+        /* The CPU must not attempt to change the SDRAM Mode register setting */
+        /* prior to DRAM controller completion of the DRAM initialization     */
+        /* sequence. To guarantee this restriction, it is recommended that    */
+        /* the CPU sets the SDRAM Operation register to NOP command, performs */
+        /* read polling until the register is back in Normal operation value, */
+        /* and then sets SDRAM Mode register to its new value.               */
+
+	/* 8.1 write 'nop' to SDRAM operation */
+        mov     r4, #0x5                 /* 'NOP' command              */
+        MV_REG_WRITE_ASM(r4, r1, SDRAM_OPERATION_REG)
+
+        /* 8.2 poll SDRAM operation. Make sure its back to normal operation   */
+_sdramOpPoll1:
+        ldr     r4, [r1]
+        cmp     r4, #0                          /* '0' = Normal SDRAM Mode    */
+        bne     _sdramOpPoll1
+
+        /* 8.3 Now its safe to write new value to SDRAM Mode register         */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG2)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_MODE_REG)
+        str     r4, [r1]
+
+        /* 8.4 Make the Dunit write the DRAM its new mode                     */
+        mov     r4, #0x3                 /* Mode Register Set command  */
+        MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG)
+
+        /* 8.5 poll SDRAM operation. Make sure its back to normal operation   */
+_sdramOpPoll2:
+        ldr     r4, [r1]
+        cmp     r4, #0                          /* '0' = Normal SDRAM Mode    */
+        bne     _sdramOpPoll2
+
+        /* Now its safe to write new value to SDRAM Extended Mode regist */
+        ldr     r1, =(INTER_REGS_BASE + DRAM_BUF_REG10)
+        ldr     r4, [r1]
+        ldr     r1, =(INTER_REGS_BASE + SDRAM_EXTENDED_MODE_REG)
+        str     r4, [r1]
+
+        /* 9) Write SDRAM Extended mode register This operation should be     */
+        /*    done for each memory bank                                       */
+        /* write 'nop' to SDRAM operation */
+        mov     r4, #0x5                 /* 'NOP' command              */
+        MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG)
+
+        /* poll SDRAM operation. Make sure its back to normal operation   */
+_sdramOpPoll3:
+        ldr     r4, [r1]
+        cmp     r4, #0                          /* '0' = Normal SDRAM Mode    */
+        bne     _sdramOpPoll3
+        /* Go over each of the Banks */
+        ldr     r3, =0          /* r3 = DRAM bank Num */
+
+extModeLoop:
+        /* Set the SDRAM Operation Control to each of the DRAM banks          */
+        mov     r4, r3   /* Do not swap the bank counter value */
+        MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_CTRL_REG)
+
+        /* Make the Dunit write the DRAM its new mode                     */
+        mov     r4, #0x4        /* Extended Mode Register Set command  */
+        MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG)
+
+        /* poll SDRAM operation. Make sure its back to normal operation   */
+_sdramOpPoll4:
+        ldr     r4, [r1]
+        cmp     r4, #0                          /* '0' = Normal SDRAM Mode    */
+        bne     _sdramOpPoll4
+
+        add     r3, r3, #1
+        cmp     r3, #4         /* 4 = Number of banks */
+        bne     extModeLoop
+
+extModeEnd:
+cmp	sp, #0
+	beq	no_stack_l
+	mov     r1, LR                        	/* Save link register */
+#if defined(MV78XX0)
+	bl   	_mvDramIfMemInit
+#endif
+	mov	LR,r1				/* restore link register */
+load_from_stack:
+	/* Restore registers */
+        ldmia	sp!, {r1, r2, r3, r4}
+no_stack_l:
+
+        mov     pc, lr
+
+
+/*******************************************************************************
+* _mvDramIfEccMemInit - Basic DRAM ECC initialization.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+#define XOR_CHAN0         0   /* XOR channel 0 used for memory initialization */
+#define XOR_UNIT0         0   /* XOR unit 0 used for memory initialization */
+#define XOR_ADDR_DEC_WIN0 0   /* Enable DRAM access using XOR decode window 0 */
+/* XOR engine register offsets macros */
+#define XOR_CONFIG_REG(chan)                (MV_XOR_REGS_BASE(0) + 0x10 + ((chan)    * 4))
+#define XOR_ACTIVATION_REG(chan)            (MV_XOR_REGS_BASE(0) + 0x20 + ((chan)    * 4))
+#define XOR_CAUSE_REG			    (MV_XOR_REGS_BASE(0) + 0x30)
+#define XOR_ERROR_CAUSE_REG                 (MV_XOR_REGS_BASE(0) + 0x50)
+#define XOR_ERROR_ADDR_REG                  (MV_XOR_REGS_BASE(0) + 0x60)
+#define XOR_WINDOW_CTRL_REG(chan)           (MV_XOR_REGS_BASE(0) + 0x240 + ((chan)    * 4))
+#define XOR_BASE_ADDR_REG(winNum)     	    (MV_XOR_REGS_BASE(0) + 0x250 + ((winNum)  * 4))
+#define XOR_SIZE_MASK_REG(winNum)           (MV_XOR_REGS_BASE(0) + 0x270 + ((winNum)  * 4))
+#define XOR_INIT_VAL_LOW_REG                (MV_XOR_REGS_BASE(0) + 0x2E0)
+#define XOR_INIT_VAL_HIGH_REG               (MV_XOR_REGS_BASE(0) + 0x2E4)
+#define XOR_DST_PTR_REG(chan)               (MV_XOR_REGS_BASE(0) + 0x2B0 + ((chan)    * 4))
+#define XOR_BLOCK_SIZE_REG(chan)            (MV_XOR_REGS_BASE(0) + 0x2C0 + ((chan)    * 4))
+
+.globl _mvDramIfEccMemInit
+/*******************************************************************************
+* _mvDramIfEccMemInit  - mem init for dram cs
+*
+* DESCRIPTION:
+*       This function will clean the cs by ussing the XOR mem init.
+*
+* INPUT:
+*       r0 - dram bank number.
+*
+* OUTPUT:
+*	none
+*/
+_mvDramIfEccMemInit:
+
+        /* Save register on stack */
+	cmp	sp, #0
+	beq	no_stack_s1
+save_on_stack1:
+        stmdb	sp!, {r0,r1, r2, r3, r4, r5, r6}
+no_stack_s1:
+
+	ldr	r1, = 0
+
+        /* Disable all XOR address decode windows to avoid possible overlap */
+        MV_REG_WRITE_ASM (r1, r5, (XOR_WINDOW_CTRL_REG(XOR_CHAN0)))
+
+        /* Init r5 to first XOR_SIZE_MASK_REG */
+		mov		r5, r0, LSL #3
+        add     r5, r5,#0x1500
+        add     r5, r5,#0x04
+        add     r5, r5,#(INTER_REGS_BASE)
+        ldr     r6, [r5]
+        HTOLL(r6,r5)
+        MV_REG_WRITE_ASM (r6, r5, XOR_SIZE_MASK_REG(XOR_ADDR_DEC_WIN0))
+
+	mov		r5, r0, LSL #3
+        add     r5, r5,#0x1500
+        add     r5, r5,#(INTER_REGS_BASE)
+        ldr     r6, [r5]
+        HTOLL(r6,r5)
+        /* Update destination & size */
+        MV_REG_WRITE_ASM(r6, r5, XOR_DST_PTR_REG(XOR_CHAN0))
+        HTOLL(r6,r5)
+        /* Init r6 to first XOR_BASE_ADDR_REG */
+	ldr	r4, = 0xf
+	ldr	r5, = 0x1
+	mov	r5, r5, LSL r0
+	bic	r4, r4, r5
+	mov 	r4, r4, LSL #8
+
+        orr	r6, r6, r4
+        MV_REG_WRITE_ASM (r6, r5, XOR_BASE_ADDR_REG(XOR_ADDR_DEC_WIN0))
+
+	ldr	r6, = 0xff0001
+        MV_REG_WRITE_ASM (r6, r5, XOR_WINDOW_CTRL_REG(XOR_CHAN0))
+
+        /* Configure XOR engine for memory init function.           */
+        MV_REG_READ_ASM (r6, r5, XOR_CONFIG_REG(XOR_CHAN0))
+        and	r6, r6, #~0x7        	/* Clear operation mode field      */
+        orr     r6, r6, #0x4             /* Set operation to memory init    */
+        MV_REG_WRITE_ASM(r6, r5, XOR_CONFIG_REG(XOR_CHAN0))
+
+        /* Set initVal in the XOR Engine Initial Value Registers       */
+	ldr	r6, = 0xfeedfeed
+        MV_REG_WRITE_ASM(r6, r5, XOR_INIT_VAL_LOW_REG)
+	ldr	r6, = 0xfeedfeed
+        MV_REG_WRITE_ASM(r6, r5, XOR_INIT_VAL_HIGH_REG)
+
+        /* Set block size using DRAM bank size  */
+
+	mov	r5, r0, LSL #3
+        add     r5, r5,#0x1500
+        add     r5, r5,#0x04
+        add     r5, r5,#(INTER_REGS_BASE)
+
+        ldr     r6, [r5]
+        HTOLL(r6,r5)
+	and	r6, r6, #SCSR_SIZE_MASK
+	mov	r5, r6, LSR #SCSR_SIZE_OFFS
+        add	r5, r5, #1
+	mov	r6, r5, LSL #SCSR_SIZE_OFFS
+        MV_REG_WRITE_ASM(r6, r5, XOR_BLOCK_SIZE_REG(XOR_CHAN0))
+
+        /* Clean interrupt cause*/
+        MV_REG_WRITE_ASM(r1, r5, XOR_CAUSE_REG)
+
+        /* Clean error interrupt cause*/
+        MV_REG_READ_ASM(r6, r5, XOR_ERROR_CAUSE_REG)
+        MV_REG_READ_ASM(r6, r5, XOR_ERROR_ADDR_REG)
+
+        /* Start transfer */
+        MV_REG_READ_ASM (r6, r5, XOR_ACTIVATION_REG(XOR_CHAN0))
+        orr     r6, r6, #0x1 /* Preform start command      */
+        MV_REG_WRITE_ASM(r6, r5, XOR_ACTIVATION_REG(XOR_CHAN0))
+
+        /* Wait for engine to finish */
+waitForComplete:
+        MV_REG_READ_ASM(r6, r5, XOR_CAUSE_REG)
+        and   	r6, r6, #2
+	cmp	r6, #0
+        beq     waitForComplete
+
+        /* Clear all error report registers */
+        MV_REG_WRITE_ASM(r1, r5, SDRAM_SINGLE_BIT_ERR_CNTR_REG)
+        MV_REG_WRITE_ASM(r1, r5, SDRAM_DOUBLE_BIT_ERR_CNTR_REG)
+
+        MV_REG_WRITE_ASM(r1, r5, SDRAM_ERROR_CAUSE_REG)
+
+	cmp	sp, #0
+	beq	no_stack_l1
+load_from_stack1:
+        ldmia	sp!, {r0, r1, r2, r3, r4, r5, r6}
+no_stack_l1:
+        mov     pc, lr
+
+
+/*******************************************************************************
+* mvDramIfMemInit - Use XOR to clear all memory.
+*
+* DESCRIPTION:
+*       Use assembler function _mvDramIfEccMemInit to fill all memory with FEADFEAD pattern.
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+#if defined(MV78XX0)
+
+_mvDramIfMemInit:
+        stmdb	sp!, {r0,r1, r2, r3, r4, r5, r6}
+	mov     r6, LR                 /* Save link register */
+    	/* Check if dram bank 0 has to be init for ECC */
+	MV_REG_READ_ASM (r0, r5, SDRAM_SIZE_REG(0,0))
+	and 	r3, r0, #SCSR_WIN_EN
+        cmp     r3, #0
+	beq   	no_bank_0
+	MV_REG_READ_ASM(r0, r5,  SDRAM_BASE_ADDR_REG(0,0))
+        cmp     r0, #0
+	beq   	no_bank_0
+	mov	r0,#0
+	bl	_mvDramIfEccMemInit
+
+no_bank_0:
+    	/* Check if dram bank 1 has to be init for ECC */
+        MV_REG_READ_ASM (r0, r5, SDRAM_SIZE_REG(0,1))
+	and 	r0, r0, #SCSR_WIN_EN
+        cmp     r0, #0
+	beq   	no_bank_1
+	mov	r0,#1
+	bl	_mvDramIfEccMemInit
+no_bank_1:
+    	/* Check if dram bank 2 has to be init for ECC */
+    	MV_REG_READ_ASM (r0, r5, SDRAM_SIZE_REG(0,2))
+	and 	r0, r0, #SCSR_WIN_EN
+        cmp     r0, #0
+	beq   	no_bank_2
+	MV_REG_READ_ASM(r0, r5,  SDRAM_BASE_ADDR_REG(0,2))
+        cmp     r0, #0
+	beq   	no_bank_2
+	mov	r0,#2
+	bl	_mvDramIfEccMemInit
+
+no_bank_2:
+    	/* Check if dram bank 3 has to be init for ECC */
+	MV_REG_READ_ASM (r0, r5, SDRAM_SIZE_REG(0,3))
+	and 	r0, r0, #SCSR_WIN_EN
+	cmp     r0, #0
+	beq   	no_bank_3
+	mov	r0,#3
+	bl	_mvDramIfEccMemInit
+no_bank_3:
+	mov     LR ,r6                /* restore link register */
+	ldmia	sp!, {r0, r1, r2, r3, r4, r5, r6}
+	mov     pc, lr
+#endif
+
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfConfig.h b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfConfig.h
new file mode 100755
index 0000000..b0faf20
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfConfig.h
@@ -0,0 +1,155 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvDramIfConfigh
+#define __INCmvDramIfConfigh
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+/* includes */
+
+/* defines  */
+
+/* registers defaults values */
+
+#define SDRAM_CONFIG_DV 	(SDRAM_SRMODE_DRAM | BIT25 | BIT30)
+
+#define SDRAM_DUNIT_CTRL_LOW_DDR2_DV			\
+		(SDRAM_SRCLK_KEPT		|	\
+		 SDRAM_CLK1DRV_NORMAL		|	\
+		 (BIT28 | BIT29))
+
+#define SDRAM_ADDR_CTRL_DV	    2
+
+#define SDRAM_TIMING_CTRL_LOW_REG_DV 	\
+		((0x2 << SDRAM_TRCD_OFFS) | 	\
+		 (0x2 << SDRAM_TRP_OFFS)  | 	\
+		 (0x1 << SDRAM_TWR_OFFS)  | 	\
+		 (0x0 << SDRAM_TWTR_OFFS) | 	\
+		 (0x5 << SDRAM_TRAS_OFFS) | 	\
+		 (0x1 << SDRAM_TRRD_OFFS))
+
+/* Note: value of 0 in register means one cycle, 1 means two and so on  */
+#define SDRAM_TIMING_CTRL_HIGH_REG_DV 	\
+		((0x0 << SDRAM_TR2R_OFFS)	|	\
+		 (0x0 << SDRAM_TR2W_W2R_OFFS)	|	\
+		 (0x1 << SDRAM_TW2W_OFFS))
+
+#define SDRAM_OPEN_PAGES_CTRL_REG_DV 	SDRAM_OPEN_PAGE_EN
+
+/* Presence	     Ctrl Low    Ctrl High  Dunit Ctrl   Ext Mode     */
+/* CS0              0x84210000  0x00000000  0x0000780F  0x00000440    */
+/* CS0+CS1          0x84210000  0x00000000  0x0000780F  0x00000440    */
+/* CS0+CS2          0x030C030C  0x00000000  0x0000740F  0x00000404    */
+/* CS0+CS1+CS2      0x030C030C  0x00000000  0x0000740F  0x00000404    */
+/* CS0+CS2+CS3      0x030C030C  0x00000000  0x0000740F  0x00000404    */
+/* CS0+CS1+CS2+CS3  0x030C030C  0x00000000  0x0000740F  0x00000404    */
+
+#define DDR2_ODT_CTRL_LOW_CS0_CS1_DV		0x84210000
+#define DDR2_ODT_CTRL_HIGH_CS0_CS1_DV		0x00000000
+#define DDR2_DUNIT_ODT_CTRL_CS0_CS1_DV		0x0000E80F
+#ifdef MV78XX0
+#define DDR_SDRAM_EXT_MODE_CS0_CS1_DV		0x00000040
+#else
+#define DDR_SDRAM_EXT_MODE_CS0_CS1_DV		0x00000440
+#endif
+
+#define DDR2_ODT_CTRL_LOW_CS0_CS1_CS2_CS3_DV	0x030C030C
+#define DDR2_ODT_CTRL_HIGH_CS0_CS1_CS2_CS3_DV	0x00000000
+#define DDR2_DUNIT_ODT_CTRL_CS0_CS1_CS2_CS3_DV	0x0000F40F
+#ifdef MV78XX0
+#define DDR_SDRAM_EXT_MODE_CS0_CS1_CS2_CS3_DV	0x00000004
+#define DDR_SDRAM_EXT_MODE_FAST_CS0_CS1_CS2_CS3_DV	0x00000044
+#else
+#define DDR_SDRAM_EXT_MODE_CS0_CS1_CS2_CS3_DV	0x00000404
+#define DDR_SDRAM_EXT_MODE_FAST_CS0_CS1_CS2_CS3_DV	0x00000444
+#endif
+
+/* DDR SDRAM Adderss/Control and Data Pads Calibration default values */
+#define DDR2_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV	\
+		(3 << SDRAM_PRE_DRIVER_STRENGTH_OFFS)
+
+#define DDR2_DATA_PAD_STRENGTH_TYPICAL_DV		\
+		(3 << SDRAM_PRE_DRIVER_STRENGTH_OFFS)
+
+/* DDR SDRAM Mode Register default value */
+#define DDR2_MODE_REG_DV		(SDRAM_BURST_LEN_4 | SDRAM_WR_3_CYC)
+/* DDR SDRAM Timing parameter default values */
+#define SDRAM_TIMING_CTRL_LOW_REG_DEFAULT  	0x33136552
+#define SDRAM_TRFC_DEFAULT_VALUE		0x34
+#define SDRAM_TRFC_DEFAULT		SDRAM_TRFC_DEFAULT_VALUE
+#define SDRAM_TW2W_DEFALT		(0x1 << SDRAM_TW2W_OFFS)
+
+#define SDRAM_TIMING_CTRL_HIGH_REG_DEFAULT  (SDRAM_TRFC_DEFAULT | SDRAM_TW2W_DEFALT)
+
+#define SDRAM_FTDLL_REG_DEFAULT_LEFT  		0x88C800
+#define SDRAM_FTDLL_REG_DEFAULT_RIGHT  		0x88C800
+#define SDRAM_FTDLL_REG_DEFAULT_UP  		0x88C800
+
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+#endif				/* __INCmvDramIfh */
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfRegs.h b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfRegs.h
new file mode 100755
index 0000000..8e71189
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfRegs.h
@@ -0,0 +1,428 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvDramIfRegsh
+#define __INCmvDramIfRegsh
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysDdrConfig.h"
+
+/* DDR SDRAM Controller Address Decode Registers */
+	/* SDRAM CSn Base Address Register (SCBAR) */
+#define SDRAM_BASE_ADDR_REG(cpu, csNum)	(0x1500 + ((csNum) * 8) + ((cpu) * 0x70))
+#define SCBAR_BASE_OFFS			16
+#define SCBAR_BASE_MASK			(0xffff << SCBAR_BASE_OFFS)
+#define SCBAR_BASE_ALIGNMENT		0x10000
+
+/* SDRAM CSn Size Register (SCSR) */
+#define SDRAM_SIZE_REG(cpu, csNum)	(0x1504 + ((csNum) * 8) + ((cpu) * 0x70))
+#define SCSR_SIZE_OFFS			24
+#define SCSR_SIZE_MASK			(0xff << SCSR_SIZE_OFFS)
+#define SCSR_SIZE_ALIGNMENT		0x1000000
+#define SCSR_WIN_EN			BIT0
+
+/* configuration register */
+#define SDRAM_CONFIG_REG   		(MV_DDR_REGS_BASE + 0x1400)
+#define SDRAM_REFRESH_OFFS 		0
+#define SDRAM_REFRESH_MAX  		0x3FFF
+#define SDRAM_REFRESH_MASK 		(SDRAM_REFRESH_MAX << SDRAM_REFRESH_OFFS)
+#define SDRAM_DTYPE_OFFS		14
+#define SDRAM_DTYPE_MASK		(1 << SDRAM_DTYPE_OFFS)
+#define SDRAM_DTYPE_DDR2		(0 << SDRAM_DTYPE_OFFS)
+#define SDRAM_DTYPE_DDR3		(1 << SDRAM_DTYPE_OFFS)
+#define SDRAM_DWIDTH_OFFS       	15
+#define SDRAM_DWIDTH_MASK       	(1 << SDRAM_DWIDTH_OFFS)
+#define SDRAM_DWIDTH_32BIT      	(0 << SDRAM_DWIDTH_OFFS)
+#define SDRAM_DWIDTH_64BIT      	(1 << SDRAM_DWIDTH_OFFS)
+#define SDRAM_REGISTERED   		(1 << 17)
+#define SDRAM_ECC_OFFS    		18
+#define SDRAM_ECC_MASK    		(1 << SDRAM_ECC_OFFS)
+#define SDRAM_ECC_DIS     		(0 << SDRAM_ECC_OFFS)
+#define SDRAM_ECC_EN        		(1 << SDRAM_ECC_OFFS)
+#define SDRAM_IERR_OFFS    		19
+#define SDRAM_IERR_MASK    		(1 << SDRAM_IERR_OFFS)
+#define SDRAM_IERR_REPORTE     		(0 << SDRAM_IERR_OFFS)
+#define SDRAM_IERR_IGNORE      		(1 << SDRAM_IERR_OFFS)
+#define SDRAM_SRMODE_OFFS       	24
+#define SDRAM_SRMODE_MASK       	(1 << SDRAM_SRMODE_OFFS)
+#define SDRAM_SRMODE_POWER      	(0 << SDRAM_SRMODE_OFFS)
+#define SDRAM_SRMODE_DRAM       	(1 << SDRAM_SRMODE_OFFS)
+
+/* dunit control low register */
+#define SDRAM_DUNIT_CTRL_REG  		(MV_DDR_REGS_BASE + 0x1404)
+#define SDRAM_2T_OFFS			4
+#define SDRAM_2T_MASK			(1 << SDRAM_2T_OFFS)
+#define SDRAM_2T_MODE			(1 << SDRAM_2T_OFFS)
+
+#define SDRAM_SRCLK_OFFS		5
+#define SDRAM_SRCLK_MASK		(1 << SDRAM_SRCLK_OFFS)
+#define SDRAM_SRCLK_KEPT		(0 << SDRAM_SRCLK_OFFS)
+#define SDRAM_SRCLK_GATED		(1 << SDRAM_SRCLK_OFFS)
+#define SDRAM_CTRL_POS_OFFS	   	6
+#define SDRAM_CTRL_POS_MASK		(1 << SDRAM_CTRL_POS_OFFS)
+#define SDRAM_CTRL_POS_FALL	   	(0 << SDRAM_CTRL_POS_OFFS)
+#define SDRAM_CTRL_POS_RISE	   	(1 << SDRAM_CTRL_POS_OFFS)
+#define SDRAM_CLK1DRV_OFFS      	12
+#define SDRAM_CLK1DRV_MASK      	(1 << SDRAM_CLK1DRV_OFFS)
+#define SDRAM_CLK1DRV_HIGH_Z    	(0 << SDRAM_CLK1DRV_OFFS)
+#define SDRAM_CLK1DRV_NORMAL    	(1 << SDRAM_CLK1DRV_OFFS)
+#define SDRAM_CLK2DRV_OFFS      	13
+#define SDRAM_CLK2DRV_MASK      	(1 << SDRAM_CLK2DRV_OFFS)
+#define SDRAM_CLK2DRV_HIGH_Z    	(0 << SDRAM_CLK2DRV_OFFS)
+#define SDRAM_CLK2DRV_NORMAL    	(1 << SDRAM_CLK2DRV_OFFS)
+#define SDRAM_SB_OUT_DEL_OFFS 		20
+#define SDRAM_SB_OUT_DEL_MAX 		0xf
+#define SDRAM_SB_OUT_MASK 		(SDRAM_SB_OUT_DEL_MAX<<SDRAM_SB_OUT_DEL_OFFS)
+#define SDRAM_SB_IN_DEL_OFFS 		24
+#define SDRAM_SB_IN_DEL_MAX 		0xf
+#define SDRAM_SB_IN_MASK 		(SDRAM_SB_IN_DEL_MAX<<SDRAM_SB_IN_DEL_OFFS)
+
+/* dunit control hight register */
+#define SDRAM_DUNIT_CTRL_HI_REG  	(MV_DDR_REGS_BASE + 0x1424)
+#define SDRAM__D2P_OFFS			7
+#define SDRAM__D2P_EN			(1 << SDRAM__D2P_OFFS)
+#define SDRAM__P2D_OFFS			8
+#define SDRAM__P2D_EN			(1 << SDRAM__P2D_OFFS)
+#define SDRAM__ADD_HALF_FCC_OFFS	9
+#define SDRAM__ADD_HALF_FCC_EN		(1 << SDRAM__ADD_HALF_FCC_OFFS)
+#define SDRAM__PUP_ZERO_SKEW_OFFS	10
+#define SDRAM__PUP_ZERO_SKEW_EN		(1 << SDRAM__PUP_ZERO_SKEW_OFFS)
+#define SDRAM__WR_MESH_DELAY_OFFS	11
+#define SDRAM__WR_MESH_DELAY_EN		(1 << SDRAM__WR_MESH_DELAY_OFFS)
+
+/* sdram timing control low register */
+#define SDRAM_TIMING_CTRL_LOW_REG	(MV_DDR_REGS_BASE + 0x1408)
+#define SDRAM_TRCD_OFFS 		4
+#define SDRAM_TRCD_MASK 		(0xF << SDRAM_TRCD_OFFS)
+#define SDRAM_TRP_OFFS 			8
+#define SDRAM_TRP_MASK 			(0xF << SDRAM_TRP_OFFS)
+#define SDRAM_TWR_OFFS 			12
+#define SDRAM_TWR_MASK 			(0xF << SDRAM_TWR_OFFS)
+#define SDRAM_TWTR_OFFS 		16
+#define SDRAM_TWTR_MASK 		(0xF << SDRAM_TWTR_OFFS)
+#define SDRAM_TRAS_OFFS 		0
+#define SDRAM_TRAS_MASK 		(0xF << SDRAM_TRAS_OFFS)
+#define SDRAM_EXT_TRAS_OFFS 		20
+#define SDRAM_EXT_TRAS_MASK 		(0x1 << SDRAM_EXT_TRAS_OFFS)
+#define SDRAM_TRRD_OFFS 		24
+#define SDRAM_TRRD_MASK 		(0xF << SDRAM_TRRD_OFFS)
+#define SDRAM_TRTP_OFFS			28
+#define SDRAM_TRTP_MASK			(0xF << SDRAM_TRTP_OFFS)
+#define SDRAM_TRTP_DDR1 		(0x1 << SDRAM_TRTP_OFFS)
+
+/* sdram timing control high register */
+#define SDRAM_TIMING_CTRL_HIGH_REG	(MV_DDR_REGS_BASE + 0x140c)
+#define SDRAM_TRFC_OFFS 		0
+#define SDRAM_TRFC_MASK 		(0x3F << SDRAM_TRFC_OFFS)
+#define SDRAM_TR2R_OFFS 		7
+#define SDRAM_TR2R_MASK 		(0x3 << SDRAM_TR2R_OFFS)
+#define SDRAM_TR2W_W2R_OFFS		9
+#define SDRAM_TR2W_W2R_MASK		(0x3 << SDRAM_TR2W_W2R_OFFS)
+#define SDRAM_TW2W_OFFS			11
+#define SDRAM_TW2W_MASK			(0x3 << SDRAM_TW2W_OFFS)
+
+/* sdram DDR2 timing low register (SD2TLR) */
+#define SDRAM_DDR2_TIMING_LO_REG	(MV_DDR_REGS_BASE + 0x1428)
+#define SD2TLR_TODT_ON_RD_OFFS		4
+#define SD2TLR_TODT_ON_RD_MASK		(0xF << SD2TLR_TODT_ON_RD_OFFS)
+#define SD2TLR_TODT_OFF_RD_OFFS		8
+#define SD2TLR_TODT_OFF_RD_MASK		(0xF << SD2TLR_TODT_OFF_RD_OFFS)
+#define SD2TLR_TODT_ON_CTRL_RD_OFFS	12
+#define SD2TLR_TODT_ON_CTRL_RD_MASK	(0xF << SD2TLR_TODT_ON_CTRL_RD_OFFS)
+#define SD2TLR_TODT_OFF_CTRL_RD_OFFS	16
+#define SD2TLR_TODT_OFF_CTRL_RD_MASK	(0xF << SD2TLR_TODT_OFF_CTRL_RD_OFFS)
+
+/* sdram DDR2 timing high register (SD2TLR) */
+#define SDRAM_DDR2_TIMING_HI_REG	(MV_DDR_REGS_BASE + 0x147C)
+#define SD2THR_TODT_ON_WR_OFFS		0
+#define SD2THR_TODT_ON_WR_MASK		(0xF << SD2THR_TODT_ON_WR_OFFS)
+#define SD2THR_TODT_OFF_WR_OFFS		4
+#define SD2THR_TODT_OFF_WR_MASK		(0xF << SD2THR_TODT_OFF_WR_OFFS)
+#define SD2THR_TODT_ON_CTRL_WR_OFFS	8
+#define SD2THR_TODT_ON_CTRL_WR_MASK	(0xF << SD2THR_TODT_ON_CTRL_WR_OFFS)
+#define SD2THR_TODT_OFF_CTRL_WR_OFFS	12
+#define SD2THR_TODT_OFF_CTRL_WR_MASK	(0xF << SD2THR_TODT_OFF_CTRL_WR_OFFS)
+
+/* address control register */
+#define SDRAM_ADDR_CTRL_REG		(MV_DDR_REGS_BASE + 0x1410)
+#define SDRAM_ADDRSEL_OFFS(cs)		(4 * (cs))
+#define SDRAM_ADDRSEL_MASK(cs)		(0x3 << SDRAM_ADDRSEL_OFFS(cs))
+#define SDRAM_ADDRSEL_X8(cs)		(0x0 << SDRAM_ADDRSEL_OFFS(cs))
+#define SDRAM_ADDRSEL_X16(cs)		(0x1 << SDRAM_ADDRSEL_OFFS(cs))
+#define SDRAM_DSIZE_OFFS(cs)   	    	(2 + 4 * (cs))
+#define SDRAM_DSIZE_MASK(cs)   	    	(0x3 << SDRAM_DSIZE_OFFS(cs))
+#define SDRAM_DSIZE_256Mb(cs) 	    	(0x1 << SDRAM_DSIZE_OFFS(cs))
+#define SDRAM_DSIZE_512Mb(cs)  	    	(0x2 << SDRAM_DSIZE_OFFS(cs))
+#define SDRAM_DSIZE_1Gb(cs)  	    	(0x3 << SDRAM_DSIZE_OFFS(cs))
+#define SDRAM_DSIZE_2Gb(cs)  	    	(0x0 << SDRAM_DSIZE_OFFS(cs))
+
+/* SDRAM Open Pages Control registers */
+#define SDRAM_OPEN_PAGE_CTRL_REG	(MV_DDR_REGS_BASE + 0x1414)
+#define SDRAM_OPEN_PAGE_EN			(0 << 0)
+#define SDRAM_OPEN_PAGE_DIS			(1 << 0)
+
+/* sdram opertion register */
+#define SDRAM_OPERATION_REG 		(MV_DDR_REGS_BASE + 0x1418)
+#define SDRAM_CMD_OFFS  			0
+#define SDRAM_CMD_MASK   			(0xF << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_NORMAL 			(0x0 << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_PRECHARGE_ALL 	(0x1 << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_REFRESH_ALL 		(0x2 << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_REG_SET_CMD 		(0x3 << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_EXT_MODE_SET 		(0x4 << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_NOP 				(0x5 << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_SLF_RFRSH 		(0x7 << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_EMRS2_CMD  		(0x8 << SDRAM_CMD_OFFS)
+#define SDRAM_CMD_EMRS3_CMD  		(0x9 << SDRAM_CMD_OFFS)
+
+/* sdram mode register */
+#define SDRAM_MODE_REG 				(MV_DDR_REGS_BASE + 0x141c)
+#define SDRAM_BURST_LEN_OFFS 		0
+#define SDRAM_BURST_LEN_MASK 		(0x7 << SDRAM_BURST_LEN_OFFS)
+#define SDRAM_BURST_LEN_4    		(0x2 << SDRAM_BURST_LEN_OFFS)
+#define SDRAM_CL_OFFS   			4
+#define SDRAM_CL_MASK   			(0x7 << SDRAM_CL_OFFS)
+#define SDRAM_DDR2_CL_3      		(0x3 << SDRAM_CL_OFFS)
+#define SDRAM_DDR2_CL_4      		(0x4 << SDRAM_CL_OFFS)
+#define SDRAM_DDR2_CL_5    		    (0x5 << SDRAM_CL_OFFS)
+#define SDRAM_DDR2_CL_6    		    (0x6 << SDRAM_CL_OFFS)
+
+#define SDRAM_TM_OFFS           	7
+#define SDRAM_TM_MASK           	(1 << SDRAM_TM_OFFS)
+#define SDRAM_TM_NORMAL         	(0 << SDRAM_TM_OFFS)
+#define SDRAM_TM_TEST_MODE      	(1 << SDRAM_TM_OFFS)
+#define SDRAM_DLL_OFFS         		8
+#define SDRAM_DLL_MASK          	(1 << SDRAM_DLL_OFFS)
+#define SDRAM_DLL_NORMAL        	(0 << SDRAM_DLL_OFFS)
+#define SDRAM_DLL_RESET 			(1 << SDRAM_DLL_OFFS)
+#define SDRAM_WR_OFFS				9
+#define SDRAM_WR_MAX				7
+#define SDRAM_WR_MASK				(SDRAM_WR_MAX << SDRAM_WR_OFFS)
+#define SDRAM_WR_2_CYC				(1 << SDRAM_WR_OFFS)
+#define SDRAM_WR_3_CYC				(2 << SDRAM_WR_OFFS)
+#define SDRAM_WR_4_CYC				(3 << SDRAM_WR_OFFS)
+#define SDRAM_WR_5_CYC				(4 << SDRAM_WR_OFFS)
+#define SDRAM_WR_6_CYC				(5 << SDRAM_WR_OFFS)
+#define SDRAM_PD_OFFS				12
+#define SDRAM_PD_MASK				(1 << SDRAM_PD_OFFS)
+#define SDRAM_PD_FAST_EXIT			(0 << SDRAM_PD_OFFS)
+#define SDRAM_PD_SLOW_EXIT			(1 << SDRAM_PD_OFFS)
+
+/* DDR SDRAM Extended Mode register (DSEMR) */
+#define SDRAM_EXTENDED_MODE_REG		(MV_DDR_REGS_BASE + 0x1420)
+#define DSEMR_DLL_ENABLE			0
+#define DSEMR_DLL_DISABLE			1
+#define DSEMR_DS_OFFS				1
+#define DSEMR_DS_MASK				(1 << DSEMR_DS_OFFS)
+#define DSEMR_DS_NORMAL				(0 << DSEMR_DS_OFFS)
+#define DSEMR_DS_REDUCED			(1 << DSEMR_DS_OFFS)
+#define DSEMR_QOFF_OUTPUT_BUFF_EN	(0 << 12)
+#define DSEMR_RTT0_OFFS				2
+#define DSEMR_RTT1_OFFS				6
+#define DSEMR_RTT_ODT_DISABLE		((0 << DSEMR_RTT0_OFFS) || (0 << DSEMR_RTT1_OFFS))
+#define DSEMR_RTT_ODT_75_OHM		((1 << DSEMR_RTT0_OFFS) || (0 << DSEMR_RTT1_OFFS))
+#define DSEMR_RTT_ODT_150_OHM		((0 << DSEMR_RTT0_OFFS) || (1 << DSEMR_RTT1_OFFS))
+#define DSEMR_RTT_ODT_50_OHM		((1 << DSEMR_RTT0_OFFS) || (1 << DSEMR_RTT1_OFFS))
+#define DSEMR_DQS_OFFS				10
+#define DSEMR_DQS_MASK				(1 << DSEMR_DQS_OFFS)
+#define DSEMR_DQS_DIFFERENTIAL		(0 << DSEMR_DQS_OFFS)
+#define DSEMR_DQS_SINGLE_ENDED		(1 << DSEMR_DQS_OFFS)
+#define DSEMR_RDQS_ENABLE			(1 << 11)
+#define DSEMR_QOFF_OUTPUT_BUFF_EN	(0 << 12)
+#define DSEMR_QOFF_OUTPUT_BUFF_DIS	(1 << 12)
+
+/* DDR SDRAM Operation Control Register */
+#define SDRAM_OPERATION_CTRL_REG	(MV_DDR_REGS_BASE + 0x142c)
+
+/* Dunit FTDLL Configuration Register */
+#define SDRAM_FTDLL_CONFIG_LEFT_REG		(MV_DDR_REGS_BASE + 0x1484)
+#define SDRAM_FTDLL_CONFIG_RIGHT_REG		(MV_DDR_REGS_BASE + 0x161C)
+#define SDRAM_FTDLL_CONFIG_UP_REG		(MV_DDR_REGS_BASE + 0x1620)
+
+/* Pads Calibration register */
+#define SDRAM_ADDR_CTRL_PADS_CAL_REG	(MV_DDR_REGS_BASE + 0x14c0)
+#define SDRAM_DATA_PADS_CAL_REG		    (MV_DDR_REGS_BASE + 0x14c4)
+#define SDRAM_DRVN_OFFS 			0
+#define SDRAM_DRVN_MASK 			(0x3F << SDRAM_DRVN_OFFS)
+#define SDRAM_DRVP_OFFS 			6
+#define SDRAM_DRVP_MASK 			(0x3F << SDRAM_DRVP_OFFS)
+#define SDRAM_PRE_DRIVER_STRENGTH_OFFS		12
+#define SDRAM_PRE_DRIVER_STRENGTH_MASK		(3 << SDRAM_PRE_DRIVER_STRENGTH_OFFS)
+#define SDRAM_TUNE_EN   		BIT16
+#define SDRAM_LOCKN_OFFS 			17
+#define SDRAM_LOCKN_MAKS 			(0x3F << SDRAM_LOCKN_OFFS)
+#define SDRAM_LOCKP_OFFS 			23
+#define SDRAM_LOCKP_MAKS 			(0x3F << SDRAM_LOCKP_OFFS)
+#define SDRAM_WR_EN     			(1 << 31)
+
+/* DDR2 SDRAM ODT Control (Low) Register (DSOCLR) */
+#define DDR2_SDRAM_ODT_CTRL_LOW_REG (MV_DDR_REGS_BASE + 0x1494)
+#define DSOCLR_ODT_RD_OFFS(odtNum)  (odtNum * 4)
+#define DSOCLR_ODT_RD_MASK(odtNum)  (0xf << DSOCLR_ODT_RD_OFFS(odtNum))
+#define DSOCLR_ODT_RD(odtNum, bank) ((1 << bank) << DSOCLR_ODT_RD_OFFS(odtNum))
+#define DSOCLR_ODT_WR_OFFS(odtNum)  (16 + (odtNum * 4))
+#define DSOCLR_ODT_WR_MASK(odtNum)  (0xf << DSOCLR_ODT_WR_OFFS(odtNum))
+#define DSOCLR_ODT_WR(odtNum, bank) ((1 << bank) << DSOCLR_ODT_WR_OFFS(odtNum))
+
+/* DDR2 SDRAM ODT Control (High) Register (DSOCHR) */
+#define DDR2_SDRAM_ODT_CTRL_HIGH_REG    	(MV_DDR_REGS_BASE + 0x1498)
+/* Optional control values to DSOCHR_ODT_EN macro */
+#define DDR2_ODT_CTRL_DUNIT         0
+#define DDR2_ODT_CTRL_NEVER         1
+#define DDR2_ODT_CTRL_ALWAYS        3
+#define DSOCHR_ODT_EN_OFFS(odtNum)  (odtNum * 2)
+#define DSOCHR_ODT_EN_MASK(odtNum)  (0x3 << DSOCHR_ODT_EN_OFFS(odtNum))
+#define DSOCHR_ODT_EN(odtNum, ctrl) (ctrl << DSOCHR_ODT_EN_OFFS(odtNum))
+
+/* DDR2 Dunit ODT Control Register (DDOCR)*/
+#define DDR2_DUNIT_ODT_CONTROL_REG  (MV_DDR_REGS_BASE + 0x149c)
+#define DDOCR_ODT_RD_OFFS          	0
+#define DDOCR_ODT_RD_MASK           (0xf << DDOCR_ODT_RD_OFFS)
+#define DDOCR_ODT_RD(bank)          ((1 << bank) << DDOCR_ODT_RD_OFFS)
+#define DDOCR_ODT_WR_OFFS           4
+#define DDOCR_ODT_WR_MASK           (0xf << DDOCR_ODT_WR_OFFS)
+#define DDOCR_ODT_WR(bank)          ((1 << bank) << DDOCR_ODT_WR_OFFS)
+#define DSOCR_ODT_EN_OFFS           8
+#define DSOCR_ODT_EN_MASK           (0x3 << DSOCR_ODT_EN_OFFS)
+/* For ctrl parameters see DDR2 SDRAM ODT Control (High) Register (0x1498) above. */
+#define DSOCR_ODT_EN(ctrl)         	(ctrl << DSOCR_ODT_EN_OFFS)
+#define DSOCR_ODT_SEL_DISABLE	    0
+#define DSOCR_ODT_SEL_75_OHM	    2
+#define DSOCR_ODT_SEL_150_OHM	    1
+#define DSOCR_ODT_SEL_50_OHM        3
+#define DSOCR_DQ_ODT_SEL_OFFS       10
+#define DSOCR_DQ_ODT_SEL_MASK       (0x3 << DSOCR_DQ_ODT_SEL_OFFS)
+#define DSOCR_DQ_ODT_SEL(odtSel)    (odtSel << DSOCR_DQ_ODT_SEL_OFFS)
+#define DSOCR_ST_ODT_SEL_OFFS       12
+#define DSOCR_ST_ODT_SEL_MASK       (0x3 << DSOCR_ST_ODT_SEL_OFFS)
+#define DSOCR_ST_ODT_SEL(odtSel)    (odtSel << DSOCR_ST_ODT_SEL_OFFS)
+#define DSOCR_ST_ODT_EN             (1 << 14)
+
+/* DDR SDRAM Initialization Control Register (DSICR) */
+#define DDR_SDRAM_INIT_CTRL_REG	    (MV_DDR_REGS_BASE + 0x1480)
+#define DSICR_INIT_EN		    	(1 << 0)
+#define DSICR_T200_SET		    	(1 << 8)
+
+/* sdram extended mode2 register (SEM2R) */
+#define SDRAM_EXTENDED_MODE2_REG	(MV_DDR_REGS_BASE + 0x148C)
+#define SEM2R_EMRS2_DDR2_OFFS		0
+#define SEM2R_EMRS2_DDR2_MASK		(0x7FFF << SEM2R_EMRS2_DDR2_OFFS)
+
+/* sdram extended mode3 register (SEM3R) */
+#define SDRAM_EXTENDED_MODE3_REG	(MV_DDR_REGS_BASE + 0x1490)
+#define SEM3R_EMRS3_DDR2_OFFS		0
+#define SEM3R_EMRS3_DDR2_MASK		(0x7FFF << SEM3R_EMRS3_DDR2_OFFS)
+
+/* sdram error registers */
+#define SDRAM_ERROR_CAUSE_REG               	(MV_DDR_REGS_BASE + 0x14d0)
+#define SDRAM_ERROR_MASK_REG                	(MV_DDR_REGS_BASE + 0x14d4)
+#define SDRAM_ERROR_DATA_LOW_REG            	(MV_DDR_REGS_BASE + 0x1444)
+#define SDRAM_ERROR_DATA_HIGH_REG           	(MV_DDR_REGS_BASE + 0x1440)
+#define SDRAM_ERROR_ADDR_REG                	(MV_DDR_REGS_BASE + 0x1450)
+#define SDRAM_ERROR_ECC_REG                 	(MV_DDR_REGS_BASE + 0x1448)
+#define SDRAM_CALC_ECC_REG                  	(MV_DDR_REGS_BASE + 0x144c)
+#define SDRAM_ECC_CONTROL_REG               	(MV_DDR_REGS_BASE + 0x1454)
+#define SDRAM_SINGLE_BIT_ERR_CNTR_REG 		(MV_DDR_REGS_BASE + 0x1458)
+#define SDRAM_DOUBLE_BIT_ERR_CNTR_REG 		(MV_DDR_REGS_BASE + 0x145c)
+
+/* SDRAM Error Cause Register (SECR) */
+#define SECR_SINGLE_BIT_ERR			BIT0
+#define SECR_DOUBLE_BIT_ERR			BIT1
+#define SECR_DATA_PATH_PARITY_ERR	BIT2
+/* SDRAM Error Address Register (SEAR) */
+#define SEAR_ERR_TYPE_OFFS			0
+#define SEAR_ERR_TYPE_MASK      	(1 << SEAR_ERR_TYPE_OFFS)
+#define SEAR_ERR_TYPE_SINGLE    	0
+#define SEAR_ERR_TYPE_DOUBLE    	(1 << SEAR_ERR_TYPE_OFFS)
+#define SEAR_ERR_CS_OFFS			1
+#define SEAR_ERR_CS_MASK			(3 << SEAR_ERR_CS_OFFS)
+#define SEAR_ERR_CS(csNum)			(csNum << SEAR_ERR_CS_OFFS)
+#define SEAR_ERR_ADDR_OFFS      	3
+#define SEAR_ERR_ADDR_MASK      	(0x1FFFFFFF << SEAR_ERR_ADDR_OFFS)
+
+/* SDRAM ECC Control Register (SECR) */
+#define SECR_FORCEECC_OFFS          0
+#define SECR_FORCEECC_MASK          (0xFF << SECR_FORCEECC_OFFS)
+#define SECR_FORCEEN_OFFS           8
+#define SECR_FORCEEN_MASK           (1 << SECR_FORCEEN_OFFS)
+#define SECR_ECC_CALC_MASK          (0 << SECR_FORCEEN_OFFS)
+#define SECR_ECC_USER_MASK          (1 << SECR_FORCEEN_OFFS)
+#define SECR_PERRPROP_EN            BIT9
+#define SECR_CNTMODE_OFFS           10
+#define SECR_CNTMODE_MASK           (1 << SECR_CNTMODE_OFFS)
+#define SECR_ALL_IN_CS0             (0 << SECR_CNTMODE_OFFS)
+#define SECR_NORMAL_COUNTER         (1 << SECR_CNTMODE_OFFS)
+#define SECR_THRECC_OFFS            16
+#define SECR_THRECC_MAX             0xFF
+#define SECR_THRECC_MASK            (SECR_THRECC_MAX << SECR_THRECC_OFFS)
+#define SECR_THRECC(threshold)      (threshold << SECR_THRECC_OFFS)
+
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+#endif				/* __INCmvDramIfRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfStaticInit.h b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfStaticInit.h
new file mode 100755
index 0000000..933346f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvDramIfStaticInit.h
@@ -0,0 +1,181 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvDramIfStaticInith
+#define __INCmvDramIfStaticInith
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef MV_STATIC_DRAM_ON_BOARD
+#define STATIC_DRAM_BANK_1
+#undef	STATIC_DRAM_BANK_2
+#undef	STATIC_DRAM_BANK_3
+#undef 	STATIC_DRAM_BANK_4
+
+#ifdef MV_DIMM_TS256MLQ72V5U
+#define	STATIC_DRAM_BANK_2
+#define	STATIC_DRAM_BANK_3
+#undef 	STATIC_DRAM_BANK_4
+
+#define STATIC_SDRAM_CONFIG_REG		    0x4724481A	/* offset 0x1400 - DMA reg-0xf1000814 */
+#define STATIC_SDRAM_DUNIT_CTRL_REG         0x37707450	/* offset 0x1404 - DMA reg-0xf100081c */
+#define STATIC_SDRAM_TIMING_CTRL_LOW_REG    0x11A13330	/* offset 0x1408 - DMA reg-0xf1000824 */
+#define STATIC_SDRAM_TIMING_CTRL_HIGH_REG   0x00000601	/* offset 0x140c - DMA reg-0xf1000828 */
+#define STATIC_SDRAM_ADDR_CTRL_REG          0x00001CB2	/* offset 0x1410 - DMA reg-0xf1000820 */
+#define STATIC_SDRAM_MODE_REG               0x00000642	/* offset 0x141c - DMA reg-0xf1000818 */
+#define STATIC_SDRAM_ODT_CTRL_LOW	    0x030C030C	/*   0x1494  */
+#define STATIC_SDRAM_ODT_CTRL_HI	    0x00000000	/*   0x1498  */
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    	    0x0000740F	/*   0x149c  */
+#define STATIC_SDRAM_EXT_MODE          	    0x00000404	/*   0x1420  */
+#define STATIC_SDRAM_DDR2_TIMING_LO         0x00074410	/*   0x1428  */
+#define STATIC_SDRAM_DDR2_TIMING_HI         0x00007441	/*   0x147C  */
+
+#define STATIC_SDRAM_RANK0_SIZE_DIMM0       0x3FFF	/* size bank0 dimm0   - DMA reg-0xf1000810 */
+#define STATIC_SDRAM_RANK1_SIZE_DIMM0       0x3FFF	/* size bank1 dimm0   */
+#define STATIC_SDRAM_RANK0_SIZE_DIMM1       0x3FFF	/* size bank0 dimm1   */
+#define STATIC_SDRAM_RANK1_SIZE_DIMM1       0x0	/* size bank1 dimm1   */
+
+#endif				/* TS256MLQ72V5U */
+
+#ifdef MV_MT9VDDT3272AG
+/* one DIMM 256M  */
+#define STATIC_SDRAM_CONFIG_REG		    0x5820040d	/* offset 0x1400 - DMA reg-0xf1000814 */
+#define STATIC_SDRAM_DUNIT_CTRL_REG         0xC4000540	/* offset 0x1404 - DMA reg-0xf100081c */
+#define STATIC_SDRAM_TIMING_CTRL_LOW_REG    0x01602220	/* offset 0x1408 - DMA reg-0xf1000824 */
+#define STATIC_SDRAM_TIMING_CTRL_HIGH_REG   0x0000000b	/* offset 0x140c - DMA reg-0xf1000828 */
+#define STATIC_SDRAM_ADDR_CTRL_REG          0x00000012	/* offset 0x1410 - DMA reg-0xf1000820 */
+#define STATIC_SDRAM_MODE_REG               0x00000062	/* offset 0x141c - DMA reg-0xf1000818 */
+#define STATIC_SDRAM_RANK0_SIZE_DIMM0       0x0fff	/* size bank0 dimm0   - DMA reg-0xf1000810 */
+#define STATIC_SDRAM_RANK0_SIZE_DIMM1       0x0	/* size bank0 dimm1   */
+
+#endif				/* MV_MT9VDDT3272AG */
+
+#ifdef MV_D27RB12P
+/*
+Two DIMM 512M + ECC enabled, Registered DIMM  CAS Latency 2.5
+*/
+
+#define STATIC_SDRAM_CONFIG_REG		    0x6826081E	/* offset 0x1400 - DMA reg-0xf1000814 */
+#define STATIC_SDRAM_DUNIT_CTRL_REG         0xC5000540	/* offset 0x1404 - DMA reg-0xf100081c */
+#define STATIC_SDRAM_TIMING_CTRL_LOW_REG    0x01501220	/* offset 0x1408 - DMA reg-0xf1000824 */
+#define STATIC_SDRAM_TIMING_CTRL_HIGH_REG   0x00000009	/* offset 0x140c - DMA reg-0xf1000828 */
+#define STATIC_SDRAM_ADDR_CTRL_REG          0x00000012	/* offset 0x1410 - DMA reg-0xf1000820 */
+#define STATIC_SDRAM_MODE_REG               0x00000062	/* offset 0x141c - DMA reg-0xf1000818 */
+#define STATIC_SDRAM_RANK0_SIZE_DIMM0       0x0FFF	/* size bank0 dimm0   - DMA reg-0xf1000810 */
+#define STATIC_SDRAM_RANK0_SIZE_DIMM1       0x0FFF	/* size bank0 dimm1   */
+
+#define STATIC_DRAM_BANK_2
+
+#define STATIC_DRAM_BANK_3
+#define STATIC_DRAM_BANK_4
+
+#endif				/*  mv_D27RB12P  */
+
+#ifdef RD_MV645XX
+
+#define STATIC_MEM_TYPE				MEM_TYPE_DDR2
+#define STATIC_DIMM_INFO_BANK0_SIZE		256
+/* DDR2 boards 256 MB*/
+
+#define STATIC_SDRAM_RANK0_SIZE_DIMM0       	0x00000fff	/* size bank0 dimm0   - DMA reg-0xf1000810 */
+#define STATIC_SDRAM_CONFIG_REG	     		0x07190618
+#define STATIC_SDRAM_MODE_REG	     		0x00000432
+#define STATIC_SDRAM_DUNIT_CTRL_REG     	0xf4a03440
+#define STATIC_SDRAM_ADDR_CTRL_REG	     	0x00000022
+#define STATIC_SDRAM_TIMING_CTRL_LOW_REG    	0x11712220
+#define STATIC_SDRAM_TIMING_CTRL_HIGH_REG	0x00000504
+#define STATIC_SDRAM_ODT_CTRL_LOW	     	0x84210000
+#define STATIC_SDRAM_ODT_CTRL_HI	     	0x00000000
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    		0x0000780f
+#define STATIC_SDRAM_EXT_MODE          		0x00000440
+#define STATIC_SDRAM_DDR2_TIMING_LO         	0x00063300
+#define STATIC_SDRAM_DDR2_TIMING_HI         	0x00006330
+#endif				/* RD_MV645XX */
+
+#ifdef MV_DIMM_M3783354CZ3_CE6
+
+#define STATIC_SDRAM_RANK0_SIZE_DIMM0		0x00000FFF	/* 0x2010 size bank0 dimm0   - DMA reg-0xf1000810 */
+#define STATIC_SDRAM_CONFIG_REG	     		0x07190618	/*   0x1400  */
+#define STATIC_SDRAM_MODE_REG	     		0x00000432	/*   0x141c  */
+#define STATIC_SDRAM_DUNIT_CTRL_REG     	0xf4a03440	/*   0x1404  */
+#define STATIC_SDRAM_ADDR_CTRL_REG	     	0x00000022	/*   0x1410  */
+#define STATIC_SDRAM_TIMING_CTRL_LOW_REG	0x11712220	/*   0x1408  */
+#define STATIC_SDRAM_TIMING_CTRL_HIGH_REG	0x00000504	/*   0x140c  */
+#define STATIC_SDRAM_ODT_CTRL_LOW	     	0x84210000	/*   0x1494  */
+#define STATIC_SDRAM_ODT_CTRL_HI	     	0x00000000	/*   0x1498  */
+#define STATIC_SDRAM_DUNIT_ODT_CTRL    		0x0000780f	/*   0x149c  */
+#define STATIC_SDRAM_EXT_MODE          		0x00000440	/*   0x1420  */
+#define STATIC_SDRAM_DDR2_TIMING_LO		0x00063300	/*   0x1428  */
+#define STATIC_SDRAM_DDR2_TIMING_HI		0x00006330	/*   0x147C  */
+
+#endif				/* MV_DIMM_M3783354CZ3_CE6 */
+
+#endif				/* MV_STATIC_DRAM_ON_BOARD */
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __INCmvDramIfStaticInith */
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/mvSysDdr.h b/arch/arm/plat-feroceon/mv_hal/ddr2/mvSysDdr.h
new file mode 100755
index 0000000..652d40b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/mvSysDdr.h
@@ -0,0 +1,115 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __mvSysDdr_h__
+#define __mvSysDdr_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+* mvSysDdrSpdRead
+*
+* DESCRIPTION:
+*	System interface for reading DDR SPD contents.
+*
+* INPUT:
+*       data:	Buffer to read data into.
+*       size:	Number of bytes to read.
+*
+* OUTPUT:
+*       data:	SPD data.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysDdrSpdRead(MV_U8 *data, MV_U32 size);
+
+/*******************************************************************************
+* mvSysDdrSpdWrite
+*
+* DESCRIPTION:
+*	System interface for writing DDR SPD contents.
+*
+* INPUT:
+*       data:	Buffer holding the data to be written.
+*       size:	Number of bytes to write.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysDdrSpdWrite(MV_U8 *data, MV_U32 size);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/spd/mvSpd.c b/arch/arm/plat-feroceon/mv_hal/ddr2/spd/mvSpd.c
new file mode 100755
index 0000000..d5a5aa6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/spd/mvSpd.c
@@ -0,0 +1,1284 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysRtcConfig.h"
+#include "ddr2/mvDramIf.h"
+#include "ddr2/spd/mvSpd.h"
+#include "boardEnv/mvBoardEnvLib.h"
+#include "ddr2/mvSysDdr.h"
+
+/* #define MV_DEBUG */
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+static MV_VOID cpyDimm2BankInfo(MV_DIMM_INFO *pDimmInfo, MV_DRAM_BANK_INFO *pBankInfo);
+static MV_U32 cas2ps(MV_U8 spd_byte);
+/*******************************************************************************
+* mvDramBankGet - Get the DRAM bank paramters.
+*
+* DESCRIPTION:
+*       This function retrieves DRAM bank parameters as described in
+*       DRAM_BANK_INFO struct to the controller DRAM unit. In case the board
+*       has its DRAM on DIMMs it will use its EEPROM to extract SPD data
+*       from it. Otherwise, if the DRAM is soldered on board, the function
+*       should insert its bank information into MV_DRAM_BANK_INFO struct.
+*
+* INPUT:
+*       bankNum  - Board DRAM bank number.
+*
+* OUTPUT:
+*       pBankInfo  - DRAM bank information struct.
+*
+* RETURN:
+*       MV_FAIL - Bank parameters could not be read.
+*
+*******************************************************************************/
+MV_STATUS mvDramBankInfoGet(MV_U32 bankNum, MV_DRAM_BANK_INFO *pBankInfo)
+{
+	MV_DIMM_INFO dimmInfo;
+
+	DB(mvOsPrintf("Dram: mvDramBankInfoGet bank %d\n", bankNum));
+	/* zero pBankInfo structure */
+
+	if ((NULL == pBankInfo) || (bankNum >= MV_DRAM_MAX_CS)) {
+		DB(mvOsPrintf("Dram: mvDramBankInfoGet bad params \n"));
+		return MV_BAD_PARAM;
+	}
+	memset(pBankInfo, 0, sizeof(*pBankInfo));
+
+	if (MV_OK != dimmSpdGet((MV_U32) (bankNum / 2), &dimmInfo)) {
+		DB(mvOsPrintf("Dram: ERR dimmSpdGet failed to get dimm info \n"));
+		return MV_FAIL;
+	}
+	if ((dimmInfo.numOfModuleBanks == 1) && ((bankNum % 2) == 1)) {
+		DB(mvOsPrintf("Dram: ERR dimmSpdGet. Can't find DIMM bank 2 \n"));
+		return MV_FAIL;
+	}
+	/* convert Dimm info to Bank info */
+	cpyDimm2BankInfo(&dimmInfo, pBankInfo);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* cpyDimm2BankInfo - Convert a Dimm info struct into a bank info struct.
+*
+* DESCRIPTION:
+*       Convert a Dimm info struct into a bank info struct.
+*
+* INPUT:
+*       pDimmInfo - DIMM information structure.
+*
+* OUTPUT:
+*       pBankInfo  - DRAM bank information struct.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID cpyDimm2BankInfo(MV_DIMM_INFO *pDimmInfo, MV_DRAM_BANK_INFO *pBankInfo)
+{
+	pBankInfo->memoryType = pDimmInfo->memoryType;
+
+	/* DIMM dimensions */
+	pBankInfo->numOfRowAddr = pDimmInfo->numOfRowAddr;
+	pBankInfo->numOfColAddr = pDimmInfo->numOfColAddr;
+	pBankInfo->dataWidth = pDimmInfo->dataWidth;
+	pBankInfo->errorCheckType = pDimmInfo->errorCheckType;
+	pBankInfo->sdramWidth = pDimmInfo->sdramWidth;
+	pBankInfo->errorCheckDataWidth = pDimmInfo->errorCheckDataWidth;
+	pBankInfo->numOfBanksOnEachDevice = pDimmInfo->numOfBanksOnEachDevice;
+	pBankInfo->suportedCasLatencies = pDimmInfo->suportedCasLatencies;
+	pBankInfo->refreshInterval = pDimmInfo->refreshInterval;
+
+	/* DIMM timing parameters */
+	pBankInfo->minCycleTimeAtMaxCasLatPs = pDimmInfo->minCycleTimeAtMaxCasLatPs;
+	pBankInfo->minCycleTimeAtMaxCasLatMinus1Ps = pDimmInfo->minCycleTimeAtMaxCasLatMinus1Ps;
+	pBankInfo->minCycleTimeAtMaxCasLatMinus2Ps = pDimmInfo->minCycleTimeAtMaxCasLatMinus2Ps;
+
+	pBankInfo->minRowPrechargeTime = pDimmInfo->minRowPrechargeTime;
+	pBankInfo->minRowActiveToRowActive = pDimmInfo->minRowActiveToRowActive;
+	pBankInfo->minRasToCasDelay = pDimmInfo->minRasToCasDelay;
+	pBankInfo->minRasPulseWidth = pDimmInfo->minRasPulseWidth;
+	pBankInfo->minWriteRecoveryTime = pDimmInfo->minWriteRecoveryTime;
+	pBankInfo->minWriteToReadCmdDelay = pDimmInfo->minWriteToReadCmdDelay;
+	pBankInfo->minReadToPrechCmdDelay = pDimmInfo->minReadToPrechCmdDelay;
+	pBankInfo->minRefreshToActiveCmd = pDimmInfo->minRefreshToActiveCmd;
+
+	/* Parameters calculated from the extracted DIMM information */
+	pBankInfo->size = pDimmInfo->size / pDimmInfo->numOfModuleBanks;
+	pBankInfo->deviceDensity = pDimmInfo->deviceDensity;
+	pBankInfo->numberOfDevices = pDimmInfo->numberOfDevices / pDimmInfo->numOfModuleBanks;
+
+	/* DIMM attributes (MV_TRUE for yes) */
+
+	if ((pDimmInfo->memoryType == MEM_TYPE_SDRAM) || (pDimmInfo->memoryType == MEM_TYPE_DDR1)) {
+		if (pDimmInfo->dimmAttributes & BIT1)
+			pBankInfo->registeredAddrAndControlInputs = MV_TRUE;
+		else
+			pBankInfo->registeredAddrAndControlInputs = MV_FALSE;
+	} else {		/* pDimmInfo->memoryType == MEM_TYPE_DDR2 */
+
+		if (pDimmInfo->dimmTypeInfo & (BIT0 | BIT4))
+			pBankInfo->registeredAddrAndControlInputs = MV_TRUE;
+		else
+			pBankInfo->registeredAddrAndControlInputs = MV_FALSE;
+	}
+
+	return;
+}
+
+/*******************************************************************************
+* dimmSpdCpy - Cpy SPD parameters from dimm 0 to dimm 1.
+*
+* DESCRIPTION:
+*       Read the DIMM SPD parameters from dimm 0 into dimm 1 SPD.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if function could read DIMM parameters, MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_STATUS dimmSpdCpy(MV_VOID)
+{
+	MV_U32 i;
+	MV_U32 spdChecksum;
+
+	MV_U8 data[SPD_SIZE];
+
+	/* zero dimmInfo structure */
+	memset(data, 0, SPD_SIZE);
+
+	/* read the dimm eeprom */
+	DB(mvOsPrintf("DRAM: Read Dimm eeprom\n"));
+
+	if (MV_OK != mvSysDdrSpdRead(data, SPD_SIZE)) {
+		DB(mvOsPrintf("DRAM: ERR. no DIMM in dimmNum 0\n"));
+		return MV_FAIL;
+	}
+
+	DB(puts("DRAM: Reading dimm info succeded.\n"));
+
+	/* calculate SPD checksum */
+	spdChecksum = 0;
+
+	for (i = 0; i <= 62; i++)
+		spdChecksum += data[i];
+
+	if ((spdChecksum & 0xff) != data[63]) {
+		DB(mvOsPrintf("DRAM: Warning. Wrong SPD Checksum %2x, expValue=%2x\n",
+			      (MV_U32) (spdChecksum & 0xff), data[63]));
+	} else {
+		DB(mvOsPrintf("DRAM: SPD Checksum ok!\n"));
+	}
+
+	/* copy the SPD content 1:1 into the DIMM 1 SPD */
+	for (i = 0; i < SPD_SIZE; i++) {
+		if (MV_OK != mvSysDdrSpdWrite(&data[i], 1)) {
+			mvOsPrintf("DRAM: ERR. no DIMM in dimmNum 1 byte %d \n", i);
+			return MV_FAIL;
+		}
+		mvOsDelay(5);
+	}
+
+	DB(puts("DRAM: Reading dimm info succeded.\n"));
+	return MV_OK;
+}
+
+/*******************************************************************************
+* dimmSpdGet - Get the SPD parameters.
+*
+* DESCRIPTION:
+*       Read the DIMM SPD parameters into given struct parameter.
+*
+* INPUT:
+*       dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator.
+*
+* OUTPUT:
+*       pDimmInfo - DIMM information structure.
+*
+* RETURN:
+*       MV_TRUE if function could read DIMM parameters, MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_STATUS dimmSpdGet(MV_U32 dimmNum, MV_DIMM_INFO *pDimmInfo)
+{
+	MV_U32 i;
+	MV_U32 density = 1;
+	MV_U32 spdChecksum;
+
+	MV_U8 data[SPD_SIZE];
+
+	if ((NULL == pDimmInfo) || (dimmNum >= MAX_DIMM_NUM)) {
+		DB(mvOsPrintf("Dram: mvDramBankInfoGet bad params \n"));
+		return MV_BAD_PARAM;
+	}
+
+	/* zero dimmInfo structure */
+	memset(data, 0, SPD_SIZE);
+
+	/* read the dimm eeprom */
+	DB(mvOsPrintf("DRAM: Read Dimm eeprom\n"));
+	if (MV_OK != mvSysDdrSpdRead(data, SPD_SIZE)) {
+		DB(mvOsPrintf("DRAM: ERR. no DIMM in dimmNum %d \n", dimmNum));
+		return MV_FAIL;
+	}
+	DB(puts("DRAM: Reading dimm info succeded.\n"));
+
+	/* calculate SPD checksum */
+	spdChecksum = 0;
+
+	for (i = 0; i <= 62; i++)
+		spdChecksum += data[i];
+
+	if ((spdChecksum & 0xff) != data[63]) {
+		DB(mvOsPrintf("DRAM: Warning. Wrong SPD Checksum %2x, expValue=%2x\n",
+			      (MV_U32) (spdChecksum & 0xff), data[63]));
+	} else {
+		DB(mvOsPrintf("DRAM: SPD Checksum ok!\n"));
+	}
+
+	/* copy the SPD content 1:1 into the dimmInfo structure */
+	for (i = 0; i < SPD_SIZE; i++) {
+		pDimmInfo->spdRawData[i] = data[i];
+		DB(mvOsPrintf("SPD-EEPROM Byte %3d = %3x (%3d)\n", i, data[i], data[i]));
+	}
+
+	DB(mvOsPrintf("DRAM SPD Information:\n"));
+
+	/* Memory type (DDR / SDRAM) */
+	switch (data[DIMM_MEM_TYPE]) {
+	case (DIMM_MEM_TYPE_SDRAM):
+		pDimmInfo->memoryType = MEM_TYPE_SDRAM;
+		DB(mvOsPrintf("DRAM Memeory type SDRAM\n"));
+		break;
+	case (DIMM_MEM_TYPE_DDR1):
+		pDimmInfo->memoryType = MEM_TYPE_DDR1;
+		DB(mvOsPrintf("DRAM Memeory type DDR1\n"));
+		break;
+	case (DIMM_MEM_TYPE_DDR2):
+		pDimmInfo->memoryType = MEM_TYPE_DDR2;
+		DB(mvOsPrintf("DRAM Memeory type DDR2\n"));
+		break;
+	default:
+		mvOsPrintf("ERROR: Undefined memory type!\n");
+		return MV_ERROR;
+	}
+
+	/* Number Of Row Addresses */
+	pDimmInfo->numOfRowAddr = data[DIMM_ROW_NUM];
+	DB(mvOsPrintf("DRAM numOfRowAddr[3]         %d\n", pDimmInfo->numOfRowAddr));
+
+	/* Number Of Column Addresses */
+	pDimmInfo->numOfColAddr = data[DIMM_COL_NUM];
+	DB(mvOsPrintf("DRAM numOfColAddr[4]         %d\n", pDimmInfo->numOfColAddr));
+
+	/* Number Of Module Banks */
+	pDimmInfo->numOfModuleBanks = data[DIMM_MODULE_BANK_NUM];
+	DB(mvOsPrintf("DRAM numOfModuleBanks[5]     0x%x\n", pDimmInfo->numOfModuleBanks));
+
+	/* Number of module banks encoded differently for DDR2 */
+	if (pDimmInfo->memoryType == MEM_TYPE_DDR2)
+		pDimmInfo->numOfModuleBanks = (pDimmInfo->numOfModuleBanks & 0x7) + 1;
+
+	/* Data Width */
+	pDimmInfo->dataWidth = data[DIMM_DATA_WIDTH];
+	DB(mvOsPrintf("DRAM dataWidth[6]            0x%x\n", pDimmInfo->dataWidth));
+
+	/* Minimum Cycle Time At Max CasLatancy */
+	pDimmInfo->minCycleTimeAtMaxCasLatPs = cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS]);
+
+	/* Error Check Type */
+	pDimmInfo->errorCheckType = data[DIMM_ERR_CHECK_TYPE];
+	DB(mvOsPrintf("DRAM errorCheckType[11]      0x%x\n", pDimmInfo->errorCheckType));
+
+	/* Refresh Interval */
+	pDimmInfo->refreshInterval = data[DIMM_REFRESH_INTERVAL];
+	DB(mvOsPrintf("DRAM refreshInterval[12]     0x%x\n", pDimmInfo->refreshInterval));
+
+	/* Sdram Width */
+	pDimmInfo->sdramWidth = data[DIMM_SDRAM_WIDTH];
+	DB(mvOsPrintf("DRAM sdramWidth[13]          0x%x\n", pDimmInfo->sdramWidth));
+
+	/* Error Check Data Width */
+	pDimmInfo->errorCheckDataWidth = data[DIMM_ERR_CHECK_DATA_WIDTH];
+	DB(mvOsPrintf("DRAM errorCheckDataWidth[14] 0x%x\n", pDimmInfo->errorCheckDataWidth));
+
+	/* Burst Length Supported */
+	/*     SDRAM/DDR1:
+	 *******-******-******-******-******-******-******-*******
+	 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+	 *******-******-******-******-******-******-******-*******
+	 burst length =  * Page | TBD  | TBD  | TBD  |  8   |  4   |  2   |   1  *
+	 *********************************************************/
+	/*     DDR2:
+	 *******-******-******-******-******-******-******-*******
+	 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+	 *******-******-******-******-******-******-******-*******
+	 burst length =  * Page | TBD  | TBD  | TBD  |  8   |  4   | TBD  | TBD  *
+	 *********************************************************/
+
+	pDimmInfo->burstLengthSupported = data[DIMM_BURST_LEN_SUP];
+	DB(mvOsPrintf("DRAM burstLengthSupported[16] 0x%x\n", pDimmInfo->burstLengthSupported));
+
+	/* Number Of Banks On Each Device */
+	pDimmInfo->numOfBanksOnEachDevice = data[DIMM_DEV_BANK_NUM];
+	DB(mvOsPrintf("DRAM numOfBanksOnEachDevice[17] 0x%x\n", pDimmInfo->numOfBanksOnEachDevice));
+
+	/* Suported Cas Latencies */
+
+	/*      SDRAM:
+	 *******-******-******-******-******-******-******-*******
+	 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+	 *******-******-******-******-******-******-******-*******
+	 CAS =   * TBD  |  7   |  6   |  5   |  4   |  3   |   2  |   1  *
+	 ********************************************************/
+
+	/*     DDR 1:
+	 *******-******-******-******-******-******-******-*******
+	 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+	 *******-******-******-******-******-******-******-*******
+	 CAS =   * TBD  |  4   | 3.5  |   3  | 2.5  |  2   | 1.5  |   1  *
+	 *********************************************************/
+
+	/*     DDR 2:
+	 *******-******-******-******-******-******-******-*******
+	 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+	 *******-******-******-******-******-******-******-*******
+	 CAS =   * TBD  | TBD  |  5   |  4   |  3   |  2   | TBD  | TBD  *
+	 *********************************************************/
+
+	pDimmInfo->suportedCasLatencies = data[DIMM_SUP_CAL];
+	DB(mvOsPrintf("DRAM suportedCasLatencies[18]    0x%x\n", pDimmInfo->suportedCasLatencies));
+
+	/* For DDR2 only, get the DIMM type information */
+	if (pDimmInfo->memoryType == MEM_TYPE_DDR2) {
+		pDimmInfo->dimmTypeInfo = data[DIMM_DDR2_TYPE_INFORMATION];
+		DB(mvOsPrintf("DRAM dimmTypeInfo[20] (DDR2) 0x%x\n", pDimmInfo->dimmTypeInfo));
+	}
+
+	/* SDRAM Modules Attributes */
+	pDimmInfo->dimmAttributes = data[DIMM_BUF_ADDR_CONT_IN];
+	DB(mvOsPrintf("DRAM dimmAttributes[21]          0x%x\n", pDimmInfo->dimmAttributes));
+
+	/* Minimum Cycle Time At Max CasLatancy Minus 1 */
+	pDimmInfo->minCycleTimeAtMaxCasLatMinus1Ps = cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS_MINUS1]);
+
+	/* Minimum Cycle Time At Max CasLatancy Minus 2 */
+	pDimmInfo->minCycleTimeAtMaxCasLatMinus2Ps = cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS_MINUS2]);
+
+	pDimmInfo->minRowPrechargeTime = data[DIMM_MIN_ROW_PRECHARGE_TIME];
+	DB(mvOsPrintf("DRAM minRowPrechargeTime[27]     0x%x\n", pDimmInfo->minRowPrechargeTime));
+	pDimmInfo->minRowActiveToRowActive = data[DIMM_MIN_ROW_ACTIVE_TO_ROW_ACTIVE];
+	DB(mvOsPrintf("DRAM minRowActiveToRowActive[28] 0x%x\n", pDimmInfo->minRowActiveToRowActive));
+	pDimmInfo->minRasToCasDelay = data[DIMM_MIN_RAS_TO_CAS_DELAY];
+	DB(mvOsPrintf("DRAM minRasToCasDelay[29]        0x%x\n", pDimmInfo->minRasToCasDelay));
+	pDimmInfo->minRasPulseWidth = data[DIMM_MIN_RAS_PULSE_WIDTH];
+	DB(mvOsPrintf("DRAM minRasPulseWidth[30]        0x%x\n", pDimmInfo->minRasPulseWidth));
+
+	/* DIMM Bank Density */
+	pDimmInfo->dimmBankDensity = data[DIMM_BANK_DENSITY];
+	DB(mvOsPrintf("DRAM dimmBankDensity[31]         0x%x\n", pDimmInfo->dimmBankDensity));
+
+	/* Only DDR2 includes Write Recovery Time field. Other SDRAM ignore     */
+	pDimmInfo->minWriteRecoveryTime = data[DIMM_MIN_WRITE_RECOVERY_TIME];
+	DB(mvOsPrintf("DRAM minWriteRecoveryTime[36]    0x%x\n", pDimmInfo->minWriteRecoveryTime));
+
+	/* Only DDR2 includes Internal Write To Read Command Delay field.       */
+	pDimmInfo->minWriteToReadCmdDelay = data[DIMM_MIN_WRITE_TO_READ_CMD_DELAY];
+	DB(mvOsPrintf("DRAM minWriteToReadCmdDelay[37]  0x%x\n", pDimmInfo->minWriteToReadCmdDelay));
+
+	/* Only DDR2 includes Internal Read To Precharge Command Delay field.   */
+	pDimmInfo->minReadToPrechCmdDelay = data[DIMM_MIN_READ_TO_PRECH_CMD_DELAY];
+	DB(mvOsPrintf("DRAM minReadToPrechCmdDelay[38]  0x%x\n", pDimmInfo->minReadToPrechCmdDelay));
+
+	/* Only DDR2 includes Minimum Refresh to Activate/Refresh Command field */
+	pDimmInfo->minRefreshToActiveCmd = data[DIMM_MIN_REFRESH_TO_ACTIVATE_CMD];
+	DB(mvOsPrintf("DRAM minRefreshToActiveCmd[42]   0x%x\n", pDimmInfo->minRefreshToActiveCmd));
+
+	/* calculating the sdram density. Representing device density from      */
+	/* bit 20 to allow representation of 4GB and above.                     */
+	/* For example, if density is 512Mbit 0x20000000, will be represent in  */
+	/* deviceDensity by 0x20000000 >> 16 --> 0x00000200. Another example    */
+	/* is density 8GB 0x200000000 >> 16 --> 0x00002000.                     */
+	density = (1 << ((pDimmInfo->numOfRowAddr + pDimmInfo->numOfColAddr) - 20));
+	pDimmInfo->deviceDensity = density * pDimmInfo->numOfBanksOnEachDevice * pDimmInfo->sdramWidth;
+	DB(mvOsPrintf("DRAM deviceDensity           %d\n", pDimmInfo->deviceDensity));
+
+	/* Number of devices includeing Error correction */
+	pDimmInfo->numberOfDevices = (pDimmInfo->dataWidth / pDimmInfo->sdramWidth) * pDimmInfo->numOfModuleBanks;
+	DB(mvOsPrintf("DRAM numberOfDevices         %d\n", pDimmInfo->numberOfDevices));
+
+	pDimmInfo->size = 0;
+
+	/* Note that pDimmInfo->size is in MB units */
+	if (pDimmInfo->memoryType == MEM_TYPE_SDRAM) {
+		if (pDimmInfo->dimmBankDensity & BIT0)
+			pDimmInfo->size += 1024;	/* Equal to 1GB     */
+		else if (pDimmInfo->dimmBankDensity & BIT1)
+			pDimmInfo->size += 8;	/* Equal to 8MB     */
+		else if (pDimmInfo->dimmBankDensity & BIT2)
+			pDimmInfo->size += 16;	/* Equal to 16MB    */
+		else if (pDimmInfo->dimmBankDensity & BIT3)
+			pDimmInfo->size += 32;	/* Equal to 32MB    */
+		else if (pDimmInfo->dimmBankDensity & BIT4)
+			pDimmInfo->size += 64;	/* Equal to 64MB    */
+		else if (pDimmInfo->dimmBankDensity & BIT5)
+			pDimmInfo->size += 128;	/* Equal to 128MB   */
+		else if (pDimmInfo->dimmBankDensity & BIT6)
+			pDimmInfo->size += 256;	/* Equal to 256MB   */
+		else if (pDimmInfo->dimmBankDensity & BIT7)
+			pDimmInfo->size += 512;	/* Equal to 512MB   */
+	} else if (pDimmInfo->memoryType == MEM_TYPE_DDR1) {
+		if (pDimmInfo->dimmBankDensity & BIT0)
+			pDimmInfo->size += 1024;	/* Equal to 1GB     */
+		else if (pDimmInfo->dimmBankDensity & BIT1)
+			pDimmInfo->size += 2048;	/* Equal to 2GB     */
+		else if (pDimmInfo->dimmBankDensity & BIT2)
+			pDimmInfo->size += 16;	/* Equal to 16MB    */
+		else if (pDimmInfo->dimmBankDensity & BIT3)
+			pDimmInfo->size += 32;	/* Equal to 32MB    */
+		else if (pDimmInfo->dimmBankDensity & BIT4)
+			pDimmInfo->size += 64;	/* Equal to 64MB    */
+		else if (pDimmInfo->dimmBankDensity & BIT5)
+			pDimmInfo->size += 128;	/* Equal to 128MB   */
+		else if (pDimmInfo->dimmBankDensity & BIT6)
+			pDimmInfo->size += 256;	/* Equal to 256MB   */
+		else if (pDimmInfo->dimmBankDensity & BIT7)
+			pDimmInfo->size += 512;	/* Equal to 512MB   */
+	} else {		/* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */
+
+		if (pDimmInfo->dimmBankDensity & BIT0)
+			pDimmInfo->size += 1024;	/* Equal to 1GB     */
+		else if (pDimmInfo->dimmBankDensity & BIT1)
+			pDimmInfo->size += 2048;	/* Equal to 2GB     */
+		else if (pDimmInfo->dimmBankDensity & BIT2)
+			pDimmInfo->size += 4096;	/* Equal to 4GB     */
+		else if (pDimmInfo->dimmBankDensity & BIT3)
+			pDimmInfo->size += 8192;	/* Equal to 8GB     */
+		else if (pDimmInfo->dimmBankDensity & BIT4)
+			pDimmInfo->size += 16384;	/* Equal to 16GB    */
+		else if (pDimmInfo->dimmBankDensity & BIT5)
+			pDimmInfo->size += 128;	/* Equal to 128MB   */
+		else if (pDimmInfo->dimmBankDensity & BIT6)
+			pDimmInfo->size += 256;	/* Equal to 256MB   */
+		else if (pDimmInfo->dimmBankDensity & BIT7)
+			pDimmInfo->size += 512;	/* Equal to 512MB   */
+	}
+
+	pDimmInfo->size *= pDimmInfo->numOfModuleBanks;
+
+	DB(mvOsPrintf("Dram: dimm size    %dMB \n", pDimmInfo->size));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* dimmSpdPrint - Print the SPD parameters.
+*
+* DESCRIPTION:
+*       Print the Dimm SPD parameters.
+*
+* INPUT:
+*       pDimmInfo - DIMM information structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID dimmSpdPrint(MV_U32 dimmNum, MV_U32 sysClock)
+{
+	MV_DIMM_INFO dimmInfo;
+	MV_U32 i, temp = 0;
+	MV_U32 k, maskLeftOfPoint = 0, maskRightOfPoint = 0;
+	MV_U32 rightOfPoint = 0, leftOfPoint = 0, div, time_tmp, shift;
+	MV_U32 busClkPs;
+	MV_U8 trp_clocks = 0, trcd_clocks, tras_clocks, trrd_clocks, temp_buf[40], *spdRawData;
+
+	busClkPs = 1000000000 / (sysClock / 100);	/* in 10 ps units */
+
+	spdRawData = dimmInfo.spdRawData;
+
+	if (MV_OK != dimmSpdGet(dimmNum, &dimmInfo)) {
+		mvOsOutput("ERROR: Could not read SPD information!\n");
+		return;
+	}
+
+	/* find Manufactura of Dimm Module */
+	mvOsOutput("\nManufacturer's JEDEC ID Code:   ");
+	for (i = 0; i < DIMM_MODULE_MANU_SIZE; i++)
+		mvOsOutput("%x", spdRawData[DIMM_MODULE_MANU_OFFS + i]);
+
+	mvOsOutput("\n");
+
+	/* Manufacturer's Specific Data */
+	for (i = 0; i < DIMM_MODULE_ID_SIZE; i++)
+		temp_buf[i] = spdRawData[DIMM_MODULE_ID_OFFS + i];
+
+	mvOsOutput("Manufacturer's Specific Data:   %s\n", temp_buf);
+
+	/* Module Part Number */
+	for (i = 0; i < DIMM_MODULE_VEN_SIZE; i++)
+		temp_buf[i] = spdRawData[DIMM_MODULE_VEN_OFFS + i];
+
+	mvOsOutput("Module Part Number:             %s\n", temp_buf);
+
+	/* Module Serial Number */
+	for (i = 0; i < sizeof(MV_U32); i++)
+		temp |= spdRawData[95 + i] << 8 * i;
+
+	mvOsOutput("DIMM Serial No.                 %ld (%lx)\n", (long)temp, (long)temp);
+
+	/* find Manufac-Data of Dimm Module */
+	mvOsOutput("Manufactoring Date:             Year 20%d%d/ ww %d%d\n",
+		   ((spdRawData[93] & 0xf0) >> 4), (spdRawData[93] & 0xf),
+		   ((spdRawData[94] & 0xf0) >> 4), (spdRawData[94] & 0xf));
+	/* find modul_revision of Dimm Module */
+	mvOsOutput("Module Revision:                %d.%d\n", spdRawData[62] / 10, spdRawData[62] % 10);
+
+	/* find manufac_place of Dimm Module */
+	mvOsOutput("manufac_place:                  %d\n", spdRawData[72]);
+
+	/* go over the first 35 I2C data bytes */
+	for (i = 2; i <= 35; i++)
+		switch (i) {
+		case 2:	/* Memory type (DDR1/2 / SDRAM) */
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM)
+				mvOsOutput("Dram Type is:                   SDRAM\n");
+			else if (dimmInfo.memoryType == MEM_TYPE_DDR1)
+				mvOsOutput("Dram Type is:                   SDRAM DDR1\n");
+			else if (dimmInfo.memoryType == MEM_TYPE_DDR2)
+				mvOsOutput("Dram Type is:                   SDRAM DDR2\n");
+			else
+				mvOsOutput("Dram Type unknown\n");
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 3:	/* Number Of Row Addresses */
+			mvOsOutput("Module Number of row addresses: %d\n", dimmInfo.numOfRowAddr);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 4:	/* Number Of Column Addresses */
+			mvOsOutput("Module Number of col addresses: %d\n", dimmInfo.numOfColAddr);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 5:	/* Number Of Module Banks */
+			mvOsOutput("Number of Banks on Mod.:        %d\n", dimmInfo.numOfModuleBanks);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 6:	/* Data Width */
+			mvOsOutput("Module Data Width:              %d bit\n", dimmInfo.dataWidth);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 8:	/* Voltage Interface */
+			switch (spdRawData[i]) {
+			case 0x0:
+				mvOsOutput("Module is               TTL_5V_TOLERANT\n");
+				break;
+			case 0x1:
+				mvOsOutput("Module is               LVTTL\n");
+				break;
+			case 0x2:
+				mvOsOutput("Module is               HSTL_1_5V\n");
+				break;
+			case 0x3:
+				mvOsOutput("Module is               SSTL_3_3V\n");
+				break;
+			case 0x4:
+				mvOsOutput("Module is               SSTL_2_5V\n");
+				break;
+			case 0x5:
+				if (dimmInfo.memoryType != MEM_TYPE_SDRAM) {
+					mvOsOutput("Module is                 SSTL_1_8V\n");
+					break;
+				}
+			default:
+				mvOsOutput("Module is               VOLTAGE_UNKNOWN\n");
+				break;
+			}
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 9:	/* Minimum Cycle Time At Max CasLatancy */
+			leftOfPoint = (spdRawData[i] & 0xf0) >> 4;
+			rightOfPoint = (spdRawData[i] & 0x0f) * 10;
+
+			/* DDR2 addition of right of point */
+			if ((spdRawData[i] & 0x0f) == 0xA)
+				rightOfPoint = 25;
+			if ((spdRawData[i] & 0x0f) == 0xB)
+				rightOfPoint = 33;
+			if ((spdRawData[i] & 0x0f) == 0xC)
+				rightOfPoint = 66;
+			if ((spdRawData[i] & 0x0f) == 0xD)
+				rightOfPoint = 75;
+			mvOsOutput("Minimum Cycle Time At Max CL:   %d.%d [ns]\n", leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 10:	/* Clock To Data Out */
+			div = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 10 : 100;
+			time_tmp = (((spdRawData[i] & 0xf0) >> 4) * 10) + ((spdRawData[i] & 0x0f));
+			leftOfPoint = time_tmp / div;
+			rightOfPoint = time_tmp % div;
+			mvOsOutput("Clock To Data Out:              %d.%d [ns]\n", leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 11:	/* Error Check Type */
+			mvOsOutput("Error Check Type (0=NONE):      %d\n", dimmInfo.errorCheckType);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 12:	/* Refresh Interval */
+			mvOsOutput("Refresh Rate:                   %x\n", dimmInfo.refreshInterval);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 13:	/* Sdram Width */
+			mvOsOutput("Sdram Width:                    %d bits\n", dimmInfo.sdramWidth);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 14:	/* Error Check Data Width */
+			mvOsOutput("Error Check Data Width:         %d bits\n", dimmInfo.errorCheckDataWidth);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 15:	/* Minimum Clock Delay is unsupported */
+			if ((dimmInfo.memoryType == MEM_TYPE_SDRAM) || (dimmInfo.memoryType == MEM_TYPE_DDR1))
+				mvOsOutput("Minimum Clk Delay back to back: %d\n", spdRawData[i]);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 16:	/* Burst Length Supported */
+			/*     SDRAM/DDR1:
+			 *******-******-******-******-******-******-******-*******
+			 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+			 *******-******-******-******-******-******-******-*******
+			 burst length =  * Page | TBD  | TBD  | TBD  |  8   |  4   |  2   |   1  *
+			 *********************************************************/
+			/*     DDR2:
+			 *******-******-******-******-******-******-******-*******
+			 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+			 *******-******-******-******-******-******-******-*******
+			 burst length =  * Page | TBD  | TBD  | TBD  |  8   |  4   | TBD  | TBD  *
+			 *********************************************************/
+			mvOsOutput("Burst Length Supported: ");
+			if ((dimmInfo.memoryType == MEM_TYPE_SDRAM) || (dimmInfo.memoryType == MEM_TYPE_DDR1)) {
+				if (dimmInfo.burstLengthSupported & BIT0)
+					mvOsOutput("1, ");
+				if (dimmInfo.burstLengthSupported & BIT1)
+					mvOsOutput("2, ");
+			}
+			if (dimmInfo.burstLengthSupported & BIT2)
+				mvOsOutput("4, ");
+			if (dimmInfo.burstLengthSupported & BIT3)
+				mvOsOutput("8, ");
+
+			mvOsOutput(" Bit \n");
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 17:	/* Number Of Banks On Each Device */
+			mvOsOutput("Number Of Banks On Each Chip:   %d\n", dimmInfo.numOfBanksOnEachDevice);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 18:	/* Suported Cas Latencies */
+
+			/*      SDRAM:
+			 *******-******-******-******-******-******-******-*******
+			 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+			 *******-******-******-******-******-******-******-*******
+			 CAS =   * TBD  |  7   |  6   |  5   |  4   |  3   |   2  |   1  *
+			 ********************************************************/
+
+			/*     DDR 1:
+			 *******-******-******-******-******-******-******-*******
+			 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+			 *******-******-******-******-******-******-******-*******
+			 CAS =   * TBD  |  4   | 3.5  |   3  | 2.5  |  2   | 1.5  |   1  *
+			 *********************************************************/
+
+			/*     DDR 2:
+			 *******-******-******-******-******-******-******-*******
+			 * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+			 *******-******-******-******-******-******-******-*******
+			 CAS =   * TBD  | TBD  |  5   |  4   |  3   |  2   | TBD  | TBD  *
+			 *********************************************************/
+
+			mvOsOutput("Suported Cas Latencies: (CL) 			");
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				for (k = 0; k <= 7; k++) {
+					if (dimmInfo.suportedCasLatencies & (1 << k))
+						mvOsOutput("%d,             ", k + 1);
+				}
+			} else if (dimmInfo.memoryType == MEM_TYPE_DDR1) {
+				if (dimmInfo.suportedCasLatencies & BIT0)
+					mvOsOutput("1, ");
+				if (dimmInfo.suportedCasLatencies & BIT1)
+					mvOsOutput("1.5, ");
+				if (dimmInfo.suportedCasLatencies & BIT2)
+					mvOsOutput("2, ");
+				if (dimmInfo.suportedCasLatencies & BIT3)
+					mvOsOutput("2.5, ");
+				if (dimmInfo.suportedCasLatencies & BIT4)
+					mvOsOutput("3, ");
+				if (dimmInfo.suportedCasLatencies & BIT5)
+					mvOsOutput("3.5, ");
+			} else if (dimmInfo.memoryType == MEM_TYPE_DDR2) {
+				if (dimmInfo.suportedCasLatencies & BIT2)
+					mvOsOutput("2, ");
+				if (dimmInfo.suportedCasLatencies & BIT3)
+					mvOsOutput("3, ");
+				if (dimmInfo.suportedCasLatencies & BIT4)
+					mvOsOutput("4, ");
+				if (dimmInfo.suportedCasLatencies & BIT5)
+					mvOsOutput("5, ");
+			} else
+				mvOsOutput("?.?, ");
+			mvOsOutput("\n");
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 20:	/* DDR2 DIMM type info */
+			if (dimmInfo.memoryType == MEM_TYPE_DDR2) {
+				if (dimmInfo.dimmTypeInfo & (BIT0 | BIT4))
+					mvOsOutput("Registered DIMM (RDIMM)\n");
+				else if (dimmInfo.dimmTypeInfo & (BIT1 | BIT5))
+					mvOsOutput("Unbuffered DIMM (UDIMM)\n");
+				else
+					mvOsOutput("Unknown DIMM type.\n");
+			}
+
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 21:	/* SDRAM Modules Attributes */
+			mvOsOutput("\nModule Attributes (SPD Byte 21): \n");
+
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				if (dimmInfo.dimmAttributes & BIT0)
+					mvOsOutput(" Buffered Addr/Control Input:   Yes\n");
+				else
+					mvOsOutput(" Buffered Addr/Control Input:   No\n");
+
+				if (dimmInfo.dimmAttributes & BIT1)
+					mvOsOutput(" Registered Addr/Control Input: Yes\n");
+				else
+					mvOsOutput(" Registered Addr/Control Input: No\n");
+
+				if (dimmInfo.dimmAttributes & BIT2)
+					mvOsOutput(" On-Card PLL (clock):           Yes \n");
+				else
+					mvOsOutput(" On-Card PLL (clock):           No \n");
+
+				if (dimmInfo.dimmAttributes & BIT3)
+					mvOsOutput(" Bufferd DQMB Input:            Yes \n");
+				else
+					mvOsOutput(" Bufferd DQMB Inputs:           No \n");
+
+				if (dimmInfo.dimmAttributes & BIT4)
+					mvOsOutput(" Registered DQMB Inputs:        Yes \n");
+				else
+					mvOsOutput(" Registered DQMB Inputs:        No \n");
+
+				if (dimmInfo.dimmAttributes & BIT5)
+					mvOsOutput(" Differential Clock Input:      Yes \n");
+				else
+					mvOsOutput(" Differential Clock Input:      No \n");
+
+				if (dimmInfo.dimmAttributes & BIT6)
+					mvOsOutput(" redundant Row Addressing:      Yes \n");
+				else
+					mvOsOutput(" redundant Row Addressing:      No \n");
+			} else if (dimmInfo.memoryType == MEM_TYPE_DDR1) {
+				if (dimmInfo.dimmAttributes & BIT0)
+					mvOsOutput(" Buffered Addr/Control Input:   Yes\n");
+				else
+					mvOsOutput(" Buffered Addr/Control Input:   No\n");
+
+				if (dimmInfo.dimmAttributes & BIT1)
+					mvOsOutput(" Registered Addr/Control Input: Yes\n");
+				else
+					mvOsOutput(" Registered Addr/Control Input: No\n");
+
+				if (dimmInfo.dimmAttributes & BIT2)
+					mvOsOutput(" On-Card PLL (clock):           Yes \n");
+				else
+					mvOsOutput(" On-Card PLL (clock):           No \n");
+
+				if (dimmInfo.dimmAttributes & BIT3)
+					mvOsOutput(" FET Switch On-Card Enabled:    Yes \n");
+				else
+					mvOsOutput(" FET Switch On-Card Enabled:    No \n");
+
+				if (dimmInfo.dimmAttributes & BIT4)
+					mvOsOutput(" FET Switch External Enabled:   Yes \n");
+				else
+					mvOsOutput(" FET Switch External Enabled:   No \n");
+
+				if (dimmInfo.dimmAttributes & BIT5)
+					mvOsOutput(" Differential Clock Input:      Yes \n");
+				else
+					mvOsOutput(" Differential Clock Input:      No \n");
+			} else {	/* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */
+
+				mvOsOutput(" Number of Active Registers on the DIMM: %d\n",
+					   (dimmInfo.dimmAttributes & 0x3) + 1);
+
+				mvOsOutput(" Number of PLLs on the DIMM: %d\n", ((dimmInfo.dimmAttributes) >> 2) & 0x3);
+
+				if (dimmInfo.dimmAttributes & BIT4)
+					mvOsOutput(" FET Switch External Enabled:   Yes \n");
+				else
+					mvOsOutput(" FET Switch External Enabled:   No \n");
+
+				if (dimmInfo.dimmAttributes & BIT6)
+					mvOsOutput(" Analysis probe installed:      Yes \n");
+				else
+					mvOsOutput(" Analysis probe installed:      No \n");
+			}
+
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 22:	/* Suported AutoPreCharge */
+			mvOsOutput("\nModul Attributes (SPD Byte 22): \n");
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				if (spdRawData[i] & BIT0)
+					mvOsOutput(" Early Ras Precharge:           Yes \n");
+				else
+					mvOsOutput(" Early Ras Precharge:           No \n");
+
+				if (spdRawData[i] & BIT1)
+					mvOsOutput(" AutoPreCharge:                 Yes \n");
+				else
+					mvOsOutput(" AutoPreCharge:                 No \n");
+
+				if (spdRawData[i] & BIT2)
+					mvOsOutput(" Precharge All:                 Yes \n");
+				else
+					mvOsOutput(" Precharge All:                 No \n");
+
+				if (spdRawData[i] & BIT3)
+					mvOsOutput(" Write 1/ReadBurst:             Yes \n");
+				else
+					mvOsOutput(" Write 1/ReadBurst:             No \n");
+
+				if (spdRawData[i] & BIT4)
+					mvOsOutput(" lower VCC tolerance:           5%%\n");
+				else
+					mvOsOutput(" lower VCC tolerance:           10%%\n");
+
+				if (spdRawData[i] & BIT5)
+					mvOsOutput(" upper VCC tolerance:           5%%\n");
+				else
+					mvOsOutput(" upper VCC tolerance:           10%%\n");
+			} else if (dimmInfo.memoryType == MEM_TYPE_DDR1) {
+				if (spdRawData[i] & BIT0)
+					mvOsOutput(" Supports Weak Driver:          Yes \n");
+				else
+					mvOsOutput(" Supports Weak Driver:          No \n");
+
+				if (!(spdRawData[i] & BIT4))
+					mvOsOutput(" lower VCC tolerance:           0.2V\n");
+
+				if (!(spdRawData[i] & BIT5))
+					mvOsOutput(" upper VCC tolerance:           0.2V\n");
+
+				if (spdRawData[i] & BIT6)
+					mvOsOutput(" Concurrent Auto Preharge:      Yes \n");
+				else
+					mvOsOutput(" Concurrent Auto Preharge:      No \n");
+
+				if (spdRawData[i] & BIT7)
+					mvOsOutput(" Supports Fast AP:              Yes \n");
+				else
+					mvOsOutput(" Supports Fast AP:              No \n");
+			} else if (dimmInfo.memoryType == MEM_TYPE_DDR2) {
+				if (spdRawData[i] & BIT0)
+					mvOsOutput(" Supports Weak Driver:          Yes \n");
+				else
+					mvOsOutput(" Supports Weak Driver:          No \n");
+			}
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 23:
+			/* Minimum Cycle Time At Maximum Cas Latancy Minus 1 (2nd highest CL) */
+			leftOfPoint = (spdRawData[i] & 0xf0) >> 4;
+			rightOfPoint = (spdRawData[i] & 0x0f) * 10;
+
+			/* DDR2 addition of right of point */
+			if ((spdRawData[i] & 0x0f) == 0xA)
+				rightOfPoint = 25;
+			if ((spdRawData[i] & 0x0f) == 0xB)
+				rightOfPoint = 33;
+			if ((spdRawData[i] & 0x0f) == 0xC)
+				rightOfPoint = 66;
+			if ((spdRawData[i] & 0x0f) == 0xD)
+				rightOfPoint = 75;
+
+			mvOsOutput("Minimum Cycle Time At 2nd highest CasLatancy"
+				   "(0 = Not supported): %d.%d [ns]\n", leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 24:	/* Clock To Data Out 2nd highest Cas Latency Value */
+			div = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 10 : 100;
+			time_tmp = (((spdRawData[i] & 0xf0) >> 4) * 10) + ((spdRawData[i] & 0x0f));
+			leftOfPoint = time_tmp / div;
+			rightOfPoint = time_tmp % div;
+			mvOsOutput("Clock To Data Out (2nd CL value): 		%d.%d [ns]\n",
+				   leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 25:
+			/* Minimum Cycle Time At Maximum Cas Latancy Minus 2 (3rd highest CL) */
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				leftOfPoint = (spdRawData[i] & 0xfc) >> 2;
+				rightOfPoint = (spdRawData[i] & 0x3) * 25;
+			} else {	/* DDR1 or DDR2 */
+
+				leftOfPoint = (spdRawData[i] & 0xf0) >> 4;
+				rightOfPoint = (spdRawData[i] & 0x0f) * 10;
+
+				/* DDR2 addition of right of point */
+				if ((spdRawData[i] & 0x0f) == 0xA)
+					rightOfPoint = 25;
+				if ((spdRawData[i] & 0x0f) == 0xB)
+					rightOfPoint = 33;
+				if ((spdRawData[i] & 0x0f) == 0xC)
+					rightOfPoint = 66;
+				if ((spdRawData[i] & 0x0f) == 0xD)
+					rightOfPoint = 75;
+			}
+			mvOsOutput("Minimum Cycle Time At 3rd highest CasLatancy"
+				   "(0 = Not supported): %d.%d [ns]\n", leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 26:	/* Clock To Data Out 3rd highest Cas Latency Value */
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				leftOfPoint = (spdRawData[i] & 0xfc) >> 2;
+				rightOfPoint = (spdRawData[i] & 0x3) * 25;
+			} else {	/* DDR1 or DDR2 */
+
+				time_tmp = (((spdRawData[i] & 0xf0) >> 4) * 10) + ((spdRawData[i] & 0x0f));
+				leftOfPoint = 0;
+				rightOfPoint = time_tmp;
+			}
+			mvOsOutput("Clock To Data Out (3rd CL value): 		%d.%2d[ns]\n",
+				   leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 27:	/* Minimum Row Precharge Time */
+			shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0 : 2;
+			maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0xff : 0xfc;
+			maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0x00 : 0x03;
+			leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift);
+			rightOfPoint = (spdRawData[i] & maskRightOfPoint) * 25;
+			temp = ((leftOfPoint * 100) + rightOfPoint);	/* in 10ps Intervals */
+			trp_clocks = (temp + (busClkPs - 1)) / busClkPs;
+			mvOsOutput("Minimum Row Precharge Time [ns]: 		%d.%d = "
+				   "in Clk cycles %d\n", leftOfPoint, rightOfPoint, trp_clocks);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 28:	/* Minimum Row Active to Row Active Time */
+			shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0 : 2;
+			maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0xff : 0xfc;
+			maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0x00 : 0x03;
+			leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift);
+			rightOfPoint = (spdRawData[i] & maskRightOfPoint) * 25;
+			temp = ((leftOfPoint * 100) + rightOfPoint);	/* in 100ns Interval */
+			trrd_clocks = (temp + (busClkPs - 1)) / busClkPs;
+			mvOsOutput("Minimum Row Active -To- Row Active Delay [ns]: "
+				   "%d.%d = in Clk cycles %d\n", leftOfPoint, rightOfPoint, trp_clocks);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 29:	/* Minimum Ras-To-Cas Delay */
+			shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0 : 2;
+			maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0xff : 0xfc;
+			maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 0x00 : 0x03;
+			leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift);
+			rightOfPoint = (spdRawData[i] & maskRightOfPoint) * 25;
+			temp = ((leftOfPoint * 100) + rightOfPoint);	/* in 100ns Interval */
+			trcd_clocks = (temp + (busClkPs - 1)) / busClkPs;
+			mvOsOutput("Minimum Ras-To-Cas Delay [ns]: 			%d.%d = "
+				   "in Clk cycles %d\n", leftOfPoint, rightOfPoint, trp_clocks);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 30:	/* Minimum Ras Pulse Width */
+			tras_clocks = (cas2ps(spdRawData[i]) + (busClkPs - 1)) / busClkPs;
+			mvOsOutput("Minimum Ras Pulse Width [ns]: 			%d = "
+				   "in Clk cycles %d\n", spdRawData[i], tras_clocks);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 31:	/* Module Bank Density */
+			mvOsOutput("Module Bank Density (more than 1= Multisize-Module):");
+
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				if (dimmInfo.dimmBankDensity & BIT0)
+					mvOsOutput("1GB, ");
+				if (dimmInfo.dimmBankDensity & BIT1)
+					mvOsOutput("8MB, ");
+				if (dimmInfo.dimmBankDensity & BIT2)
+					mvOsOutput("16MB, ");
+				if (dimmInfo.dimmBankDensity & BIT3)
+					mvOsOutput("32MB, ");
+				if (dimmInfo.dimmBankDensity & BIT4)
+					mvOsOutput("64MB, ");
+				if (dimmInfo.dimmBankDensity & BIT5)
+					mvOsOutput("128MB, ");
+				if (dimmInfo.dimmBankDensity & BIT6)
+					mvOsOutput("256MB, ");
+				if (dimmInfo.dimmBankDensity & BIT7)
+					mvOsOutput("512MB, ");
+			} else if (dimmInfo.memoryType == MEM_TYPE_DDR1) {
+				if (dimmInfo.dimmBankDensity & BIT0)
+					mvOsOutput("1GB, ");
+				if (dimmInfo.dimmBankDensity & BIT1)
+					mvOsOutput("2GB, ");
+				if (dimmInfo.dimmBankDensity & BIT2)
+					mvOsOutput("16MB, ");
+				if (dimmInfo.dimmBankDensity & BIT3)
+					mvOsOutput("32MB, ");
+				if (dimmInfo.dimmBankDensity & BIT4)
+					mvOsOutput("64MB, ");
+				if (dimmInfo.dimmBankDensity & BIT5)
+					mvOsOutput("128MB, ");
+				if (dimmInfo.dimmBankDensity & BIT6)
+					mvOsOutput("256MB, ");
+				if (dimmInfo.dimmBankDensity & BIT7)
+					mvOsOutput("512MB, ");
+			} else {	/* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */
+
+				if (dimmInfo.dimmBankDensity & BIT0)
+					mvOsOutput("1GB, ");
+				if (dimmInfo.dimmBankDensity & BIT1)
+					mvOsOutput("2GB, ");
+				if (dimmInfo.dimmBankDensity & BIT2)
+					mvOsOutput("4GB, ");
+				if (dimmInfo.dimmBankDensity & BIT3)
+					mvOsOutput("8GB, ");
+				if (dimmInfo.dimmBankDensity & BIT4)
+					mvOsOutput("16GB, ");
+				if (dimmInfo.dimmBankDensity & BIT5)
+					mvOsOutput("128MB, ");
+				if (dimmInfo.dimmBankDensity & BIT6)
+					mvOsOutput("256MB, ");
+				if (dimmInfo.dimmBankDensity & BIT7)
+					mvOsOutput("512MB, ");
+			}
+			mvOsOutput("\n");
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 32:	/* Address And Command Setup Time (measured in ns/1000) */
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				rightOfPoint = (spdRawData[i] & 0x0f);
+				leftOfPoint = (spdRawData[i] & 0xf0) >> 4;
+				if (leftOfPoint > 7)
+					leftOfPoint *= -1;
+			} else {	/* DDR1 or DDR2 */
+
+				time_tmp = (((spdRawData[i] & 0xf0) >> 4) * 10) + ((spdRawData[i] & 0x0f));
+				leftOfPoint = time_tmp / 100;
+				rightOfPoint = time_tmp % 100;
+			}
+			mvOsOutput("Address And Command Setup Time [ns]: 		%d.%d\n",
+				   leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 33:	/* Address And Command Hold Time */
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				rightOfPoint = (spdRawData[i] & 0x0f);
+				leftOfPoint = (spdRawData[i] & 0xf0) >> 4;
+				if (leftOfPoint > 7)
+					leftOfPoint *= -1;
+			} else {	/* DDR1 or DDR2 */
+
+				time_tmp = (((spdRawData[i] & 0xf0) >> 4) * 10) + ((spdRawData[i] & 0x0f));
+				leftOfPoint = time_tmp / 100;
+				rightOfPoint = time_tmp % 100;
+			}
+			mvOsOutput("Address And Command Hold Time [ns]: 		%d.%d\n",
+				   leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 34:	/* Data Input Setup Time */
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				rightOfPoint = (spdRawData[i] & 0x0f);
+				leftOfPoint = (spdRawData[i] & 0xf0) >> 4;
+				if (leftOfPoint > 7)
+					leftOfPoint *= -1;
+			} else {	/* DDR1 or DDR2 */
+
+				time_tmp = (((spdRawData[i] & 0xf0) >> 4) * 10) + ((spdRawData[i] & 0x0f));
+				leftOfPoint = time_tmp / 100;
+				rightOfPoint = time_tmp % 100;
+			}
+			mvOsOutput("Data Input Setup Time [ns]: 			%d.%d\n",
+				   leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 35:	/* Data Input Hold Time */
+			if (dimmInfo.memoryType == MEM_TYPE_SDRAM) {
+				rightOfPoint = (spdRawData[i] & 0x0f);
+				leftOfPoint = (spdRawData[i] & 0xf0) >> 4;
+				if (leftOfPoint > 7)
+					leftOfPoint *= -1;
+			} else {	/* DDR1 or DDR2 */
+
+				time_tmp = (((spdRawData[i] & 0xf0) >> 4) * 10) + ((spdRawData[i] & 0x0f));
+				leftOfPoint = time_tmp / 100;
+				rightOfPoint = time_tmp % 100;
+			}
+			mvOsOutput("Data Input Hold Time [ns]: 			%d.%d\n\n", leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+
+		case 36:	/* Relevant for DDR2 only: Write Recovery Time */
+			leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> 2);
+			rightOfPoint = (spdRawData[i] & maskRightOfPoint) * 25;
+			mvOsOutput("Write Recovery Time [ns]: 			%d.%d\n", leftOfPoint, rightOfPoint);
+			break;
+/*----------------------------------------------------------------------------*/
+		}
+
+}
+
+/*
+ * translate ns.ns/10 coding of SPD timing values
+ * into ps unit values
+ */
+/*******************************************************************************
+*  cas2ps - Translate x.y ns parameter to pico-seconds values
+*
+* DESCRIPTION:
+*       This function translates x.y nano seconds to its value in pico seconds.
+*       For example 3.75ns will return 3750.
+*
+* INPUT:
+*       spd_byte - DIMM SPD byte.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       value in pico seconds.
+*
+*******************************************************************************/
+static MV_U32 cas2ps(MV_U8 spd_byte)
+{
+	MV_U32 ns, ns10;
+
+	/* isolate upper nibble */
+	ns = (spd_byte >> 4) & 0x0F;
+	/* isolate lower nibble */
+	ns10 = (spd_byte & 0x0F);
+
+	if (ns10 < 10)
+		ns10 *= 10;
+	else if (ns10 == 10)
+		ns10 = 25;
+	else if (ns10 == 11)
+		ns10 = 33;
+	else if (ns10 == 12)
+		ns10 = 66;
+	else if (ns10 == 13)
+		ns10 = 75;
+	else
+		mvOsOutput("cas2ps Err. unsupported cycle time.\n");
+
+	return (ns * 1000 + ns10 * 10);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/ddr2/spd/mvSpd.h b/arch/arm/plat-feroceon/mv_hal/ddr2/spd/mvSpd.h
new file mode 100755
index 0000000..59cb482
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ddr2/spd/mvSpd.h
@@ -0,0 +1,192 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvDram
+#define __INCmvDram
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ddr2/mvDramIf.h"
+
+#define MAX_DIMM_NUM 			2
+#define SPD_SIZE			128
+
+/* Dimm spd offsets */
+#define DIMM_MEM_TYPE 					2
+#define DIMM_ROW_NUM 					3
+#define DIMM_COL_NUM 					4
+#define DIMM_MODULE_BANK_NUM 				5
+#define DIMM_DATA_WIDTH 				6
+#define DIMM_VOLT_IF 					8
+#define DIMM_MIN_CC_AT_MAX_CAS 				9
+#define DIMM_ERR_CHECK_TYPE 				11
+#define DIMM_REFRESH_INTERVAL 				12
+#define DIMM_SDRAM_WIDTH 				13
+#define DIMM_ERR_CHECK_DATA_WIDTH 			14
+#define DIMM_MIN_CLK_DEL 				15
+#define DIMM_BURST_LEN_SUP 				16
+#define DIMM_DEV_BANK_NUM 				17
+#define DIMM_SUP_CAL 					18
+#define DIMM_DDR2_TYPE_INFORMATION          		20	/* DDR2 only */
+#define DIMM_BUF_ADDR_CONT_IN 				21
+#define DIMM_MIN_CC_AT_MAX_CAS_MINUS1			23
+#define DIMM_MIN_CC_AT_MAX_CAS_MINUS2			25
+#define DIMM_MIN_ROW_PRECHARGE_TIME			27
+#define DIMM_MIN_ROW_ACTIVE_TO_ROW_ACTIVE		28
+#define DIMM_MIN_RAS_TO_CAS_DELAY			29
+#define DIMM_MIN_RAS_PULSE_WIDTH			30
+#define DIMM_BANK_DENSITY				31
+#define DIMM_MIN_WRITE_RECOVERY_TIME        		36
+#define DIMM_MIN_WRITE_TO_READ_CMD_DELAY    		37
+#define DIMM_MIN_READ_TO_PRECH_CMD_DELAY    		38
+#define DIMM_MIN_REFRESH_TO_ACTIVATE_CMD    		42
+#define DIMM_SPD_VERSION    				62
+
+/* Dimm Memory Type values */
+#define DIMM_MEM_TYPE_SDRAM					0x4
+#define DIMM_MEM_TYPE_DDR1 					0x7
+#define DIMM_MEM_TYPE_DDR2 					0x8
+
+#define DIMM_MODULE_MANU_OFFS 		64
+#define DIMM_MODULE_MANU_SIZE 		8
+#define DIMM_MODULE_VEN_OFFS 		73
+#define DIMM_MODULE_VEN_SIZE 		25
+#define DIMM_MODULE_ID_OFFS 		99
+#define DIMM_MODULE_ID_SIZE 		18
+
+/* enumeration for voltage levels. */
+typedef enum _mvDimmVoltageIf {
+	TTL_5V_TOLERANT,
+	LVTTL,
+	HSTL_1_5V,
+	SSTL_3_3V,
+	SSTL_2_5V,
+	VOLTAGE_UNKNOWN,
+} MV_DIMM_VOLTAGE_IF;
+
+/* enumaration for SDRAM CAS Latencies. */
+typedef enum _mvDimmSdramCas {
+	SD_CL_1 = 1,
+	SD_CL_2,
+	SD_CL_3,
+	SD_CL_4,
+	SD_CL_5,
+	SD_CL_6,
+	SD_CL_7,
+	SD_FAULT
+} MV_DIMM_SDRAM_CAS;
+
+/* DIMM information structure */
+typedef struct _mvDimmInfo {
+	MV_MEMORY_TYPE memoryType;	/* DDR or SDRAM */
+
+	MV_U8 spdRawData[SPD_SIZE];	/* Content of SPD-EEPROM copied 1:1  */
+
+	/* DIMM dimensions */
+	MV_U32 numOfRowAddr;
+	MV_U32 numOfColAddr;
+	MV_U32 numOfModuleBanks;
+	MV_U32 dataWidth;
+	MV_U32 errorCheckType;	/* ECC , PARITY.. */
+	MV_U32 sdramWidth;	/* 4,8,16 or 32 */
+	MV_U32 errorCheckDataWidth;	/* 0 - no, 1 - Yes */
+	MV_U32 burstLengthSupported;
+	MV_U32 numOfBanksOnEachDevice;
+	MV_U32 suportedCasLatencies;
+	MV_U32 refreshInterval;
+	MV_U32 dimmBankDensity;
+	MV_U32 dimmTypeInfo;	/* DDR2 only */
+	MV_U32 dimmAttributes;
+
+	/* DIMM timing parameters */
+	MV_U32 minCycleTimeAtMaxCasLatPs;
+	MV_U32 minCycleTimeAtMaxCasLatMinus1Ps;
+	MV_U32 minCycleTimeAtMaxCasLatMinus2Ps;
+	MV_U32 minRowPrechargeTime;
+	MV_U32 minRowActiveToRowActive;
+	MV_U32 minRasToCasDelay;
+	MV_U32 minRasPulseWidth;
+	MV_U32 minWriteRecoveryTime;	/* DDR2 only */
+	MV_U32 minWriteToReadCmdDelay;	/* DDR2 only */
+	MV_U32 minReadToPrechCmdDelay;	/* DDR2 only */
+	MV_U32 minRefreshToActiveCmd;	/* DDR2 only */
+
+	/* Parameters calculated from the extracted DIMM information */
+	MV_U32 size;	/* 16,64,128,256 or 512 MByte in MB units */
+	MV_U32 deviceDensity;	/* 16,64,128,256 or 512 Mbit in MB units  */
+	MV_U32 numberOfDevices;
+
+} MV_DIMM_INFO;
+
+MV_STATUS mvDramBankInfoGet(MV_U32 bankNum, MV_DRAM_BANK_INFO *pBankInfo);
+MV_STATUS dimmSpdGet(MV_U32 dimmNum, MV_DIMM_INFO *pDimmInfo);
+MV_VOID dimmSpdPrint(MV_U32 dimmNum, MV_U32 sysClock);
+MV_STATUS dimmSpdCpy(MV_VOID);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __INCmvDram */
diff --git a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvCompVer.txt
new file mode 100755
index 0000000..38a9264
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.4

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.c b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.c
new file mode 100755
index 0000000..52c5a33
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.c
@@ -0,0 +1,2048 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mvSysEthPhyConfig.h"
+#include "mvEthPhyRegs.h"
+#include "mvEthPhy.h"
+
+static 	MV_VOID	mvEthPhyPower(MV_U32 ethPortNum, MV_BOOL enable);
+
+static MV_ETHPHY_HAL_DATA ethphyHalData;
+
+
+/*******************************************************************************
+* mvEthPhyRegWriteExtSmi -
+* mvEthPhyRegReadExtSmi -
+*
+* DESCRIPTION:
+*       Wrapper functions for accessing PHY registers internally, in case the
+*	external PHY access functions are not provided (In HAL Data).
+*	This is used for initializing the Quad PHY through a switch SMI bus
+*	and not the MAC SMI.
+*
+* INPUT:
+*	phyAddr		- The PHY address to be accessed.
+*	regAddr		- The register address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success, MV_ERROR otherwise.
+*
+*******************************************************************************/
+static MV_STATUS mvEthPhyRegWriteExtSmi(MV_U32 phyAddr, MV_U32 regAddr, MV_U16 val)
+{
+	if (ethphyHalData.mvExtPhyWriteFunc != NULL)
+		return ethphyHalData.mvExtPhyWriteFunc(phyAddr, regAddr, val);
+	else
+		return mvEthPhyRegWrite(phyAddr, regAddr, val);
+}
+
+static MV_STATUS mvEthPhyRegReadExtSmi(MV_U32 phyAddr, MV_U32 regAddr, MV_U16 *data)
+{
+	if (ethphyHalData.mvExtPhyReadFunc != NULL)
+		return ethphyHalData.mvExtPhyReadFunc(phyAddr, regAddr, data);
+	else
+		return mvEthPhyRegRead(phyAddr, regAddr, data);
+}
+
+
+/*******************************************************************************
+* mvEthPhyHalInit -
+*
+* DESCRIPTION:
+*       Initialize the ethernet phy unit HAL.
+*
+* INPUT:
+*       halData	- Ethernet PHY HAL data.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success, MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyHalInit(MV_ETHPHY_HAL_DATA *halData)
+{
+	mvOsMemcpy(&ethphyHalData, halData, sizeof(MV_ETHPHY_HAL_DATA));
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvEthPhygetId -
+*
+* DESCRIPTION:
+*       Get Phy ID.
+*
+* INPUT:
+*       ethPortNum - The port number to get the PHY ID for.
+*
+* OUTPUT:
+*       devId - The PHY ID.
+*
+* RETURN:
+*       MV_OK on success, MV_ERROR otherwise.
+*
+*******************************************************************************/
+static MV_STATUS mvEthPhyGetId(MV_U32 ethPortNum, MV_U16 *devId)
+{
+	MV_U32     phyAddr;
+	MV_U16     id1, id2;
+
+	if (ethPortNum != ((MV_U32) -1)) {
+		phyAddr = ethphyHalData.phyAddr[ethPortNum];
+		/* Set page as 0 */
+		if (mvEthPhyRegWrite(phyAddr, 22, 0) != MV_OK)
+			return MV_ERROR;
+
+		/* Reads ID1 */
+		if (mvEthPhyRegRead(phyAddr, 2, &id1) != MV_OK)
+			return MV_ERROR;
+
+		/* Reads ID2 */
+		if (mvEthPhyRegRead(phyAddr, 3, &id2) != MV_OK)
+			return MV_ERROR;
+	} else {
+		phyAddr = ethphyHalData.quadPhyStartAddr;
+		/* Set page as 0 */
+		if (mvEthPhyRegWriteExtSmi(phyAddr, 22, 0) != MV_OK)
+			return MV_ERROR;
+
+		/* Reads ID1 */
+		if (mvEthPhyRegReadExtSmi(phyAddr, 2, &id1) != MV_OK)
+			return MV_ERROR;
+
+		/* Reads ID2 */
+		if (mvEthPhyRegReadExtSmi(phyAddr, 3, &id2) != MV_OK)
+			return MV_ERROR;
+	}
+
+	if (!MV_IS_MARVELL_OUI(id1, id2)) {
+		mvOsPrintf("Cannot find Marvell Device id1 %x id2 %x\n", id1, id2);
+		return MV_ERROR;
+	}
+
+	*devId = (id2 & 0x3F0) >> 4;
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyInit -
+*
+* DESCRIPTION:
+*       Initialize the ethernet phy unit.
+*
+* INPUT:
+*       ethPortNum - The port number on which to initialize the PHY.
+*	eeeEnable  - Whether to enable EEE or not.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success, MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyInit(MV_U32 ethPortNum, MV_BOOL eeeEnable)
+{
+	MV_U32     phyAddr;
+	MV_U16     deviceId;
+
+	if (mvEthPhyGetId(ethPortNum, &deviceId) != MV_OK) {
+		mvOsPrintf("Cannot Get Marvell PHY Device ID.\n");
+		return MV_ERROR;
+	}
+
+	if (ethPortNum != ((MV_U32) -1))
+		phyAddr = ethphyHalData.phyAddr[ethPortNum];
+	else
+		phyAddr = ethphyHalData.quadPhyStartAddr;
+
+	switch (deviceId) {
+	case MV_PHY_88E1116:
+	case MV_PHY_88E1116R:
+		mvEthE1116PhyBasicInit(phyAddr);
+		break;
+	case MV_PHY_88E3061:
+		mvEthE3016PhyBasicInit(phyAddr);
+		break;
+	case MV_PHY_88E1111:
+		mvEthE1111PhyBasicInit(phyAddr);
+		break;
+	case MV_PHY_88E1112:
+		mvEthE1112PhyBasicInit(phyAddr);
+		break;
+	case MV_PHY_88E1011:
+		mvEthE1011PhyBasicInit(phyAddr);
+		break;
+	case MV_PHY_88E1121:
+		mvEth1121PhyBasicInit(phyAddr);
+		break;
+	case MV_PHY_88E114X:
+		mvEth1145PhyBasicInit(phyAddr);
+		break;
+	case MV_PHY_88F6601_INTERNAL:
+	case MV_PHY_88E154X:
+	case MV_PHY_88E154X_Z1:
+		/* case MV_PHY_KW2_INTERNAL_GE: */
+		if (ethPortNum != ((MV_U32) -1))
+			mvEthInternalGEPhyBasicInit(phyAddr, eeeEnable);
+		else
+			mvEth1540PhyBasicInit(eeeEnable);
+		break;
+	case MV_PHY_88E1340S:
+	case MV_PHY_88E1340:
+	case MV_PHY_88E1340M:
+		mvEth1340PhyBasicInit();
+		break;
+	case MV_PHY_88E1310:
+		mvEth131xPhyBasicInit(phyAddr);
+		break;
+	case MV_PHY_88E1512:
+		mvEthE1512PhyBasicInit(ethPortNum, eeeEnable);
+		break;
+
+	case MV_PHY_88E104X:
+	case MV_PHY_88E10X0:
+	case MV_PHY_88E10X0S:
+	case MV_PHY_88E3082:
+	case MV_PHY_88E1149:
+	case MV_PHY_88E1181:
+	case MV_PHY_88E3016_88E3019:
+	case MV_PHY_88E1240:
+	case MV_PHY_88E1149R:
+	case MV_PHY_88E1119R:
+	default:
+			mvOsPrintf("Unknown Device(%#x). Initialization failed\n", deviceId);
+			return MV_ERROR;
+	}
+	return MV_OK;
+}
+
+void    rdPhy(MV_U32 phyAddr, MV_U32 regOffs)
+{
+	MV_U16      data;
+	MV_STATUS   status;
+
+	status = mvEthPhyRegRead(phyAddr, regOffs, &data);
+	if (status == MV_OK)
+		mvOsPrintf("reg=%d: 0x%04x\n", regOffs, data);
+	else
+		mvOsPrintf("Read failed\n");
+}
+
+
+/*******************************************************************************
+* mvEthPhyRegRead - Read from ethernet phy register.
+*
+* DESCRIPTION:
+*       This function reads ethernet phy register.
+*
+* INPUT:
+*       phyAddr - Phy address.
+*       regOffs - Phy register offset.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       16bit phy register value, or 0xffff on error
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyRegRead(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 *data)
+{
+	MV_U32 			smiReg;
+	volatile MV_U32 timeout;
+
+	/* check parameters */
+	if ((phyAddr << ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) {
+		mvOsPrintf("mvEthPhyRegRead: Err. Illegal PHY device address %d\n",
+				phyAddr);
+		return MV_FAIL;
+	}
+	if ((regOffs <<  ETH_PHY_SMI_REG_ADDR_OFFS) & ~ETH_PHY_SMI_REG_ADDR_MASK) {
+		mvOsPrintf("mvEthPhyRegRead: Err. Illegal PHY register offset %d\n",
+				regOffs);
+		return MV_FAIL;
+	}
+
+	timeout = ETH_PHY_TIMEOUT;
+	/* wait till the SMI is not busy*/
+	do {
+		/* read smi register */
+		smiReg = MV_REG_READ(ethphyHalData.ethPhySmiReg);
+		if (timeout-- == 0) {
+			mvOsPrintf("mvEthPhyRegRead: SMI busy timeout\n");
+			return MV_FAIL;
+		}
+	} while (smiReg & ETH_PHY_SMI_BUSY_MASK);
+
+	/* fill the phy address and regiser offset and read opcode */
+	smiReg = (phyAddr <<  ETH_PHY_SMI_DEV_ADDR_OFFS) | (regOffs << ETH_PHY_SMI_REG_ADDR_OFFS)|
+			   ETH_PHY_SMI_OPCODE_READ;
+
+	/* write the smi register */
+	MV_REG_WRITE(ethphyHalData.ethPhySmiReg, smiReg);
+
+	timeout = ETH_PHY_TIMEOUT;
+
+	/* wait till readed value is ready */
+	do {
+		/* read smi register */
+		smiReg = MV_REG_READ(ethphyHalData.ethPhySmiReg);
+
+		if (timeout-- == 0) {
+			mvOsPrintf("mvEthPhyRegRead: SMI read-valid timeout\n");
+			return MV_FAIL;
+		}
+	} while (!(smiReg & ETH_PHY_SMI_READ_VALID_MASK));
+
+	/* Wait for the data to update in the SMI register */
+	for (timeout = 0; timeout < ETH_PHY_TIMEOUT; timeout++)
+		;
+
+	*data = (MV_U16)(MV_REG_READ(ethphyHalData.ethPhySmiReg) & ETH_PHY_SMI_DATA_MASK);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyRegWrite - Write to ethernet phy register.
+*
+* DESCRIPTION:
+*       This function write to ethernet phy register.
+*
+* INPUT:
+*       phyAddr - Phy address.
+*       regOffs - Phy register offset.
+*       data    - 16bit data.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK if write succeed, MV_BAD_PARAM on bad parameters , MV_ERROR on error .
+*		MV_TIMEOUT on timeout
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyRegWrite(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 data)
+{
+	MV_U32 			smiReg;
+	volatile MV_U32 timeout;
+
+	/* check parameters */
+	if ((phyAddr <<  ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) {
+		mvOsPrintf("mvEthPhyRegWrite: Err. Illegal phy address \n");
+		return MV_BAD_PARAM;
+	}
+	if ((regOffs <<  ETH_PHY_SMI_REG_ADDR_OFFS) & ~ETH_PHY_SMI_REG_ADDR_MASK) {
+		mvOsPrintf("mvEthPhyRegWrite: Err. Illegal register offset \n");
+		return MV_BAD_PARAM;
+	}
+
+	timeout = ETH_PHY_TIMEOUT;
+
+	/* wait till the SMI is not busy*/
+	do {
+		/* read smi register */
+		smiReg = MV_REG_READ(ethphyHalData.ethPhySmiReg);
+		if (timeout-- == 0) {
+			mvOsPrintf("mvEthPhyRegWrite: SMI busy timeout\n");
+		return MV_TIMEOUT;
+		}
+	} while (smiReg & ETH_PHY_SMI_BUSY_MASK);
+
+	/* fill the phy address and regiser offset and write opcode and data*/
+	smiReg = (data << ETH_PHY_SMI_DATA_OFFS);
+	smiReg |= (phyAddr <<  ETH_PHY_SMI_DEV_ADDR_OFFS) | (regOffs << ETH_PHY_SMI_REG_ADDR_OFFS);
+	smiReg &= ~ETH_PHY_SMI_OPCODE_READ;
+
+	/* write the smi register */
+	MV_REG_WRITE(ethphyHalData.ethPhySmiReg, smiReg);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvEthPhyReset - Reset ethernet Phy.
+*
+* DESCRIPTION:
+*       This function resets a given ethernet Phy.
+*
+* INPUT:
+*       phyAddr - Phy address.
+*       timeout - in millisec
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK       - Success
+*           MV_TIMEOUT  - Timeout
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyReset(MV_U32 phyAddr, int timeout)
+{
+	MV_U16  phyRegData;
+
+	/* Reset the PHY */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+
+	/* Set bit 15 to reset the PHY */
+	phyRegData |= ETH_PHY_CTRL_RESET_MASK;
+	mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData);
+
+	/* Wait untill Reset completed */
+	while (timeout > 0) {
+		mvOsSleep(100);
+		timeout -= 100;
+
+		if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+			return MV_FAIL;
+
+		if ((phyRegData & ETH_PHY_CTRL_RESET_MASK) == 0)
+			return MV_OK;
+	}
+	return MV_TIMEOUT;
+}
+
+
+/*******************************************************************************
+* mvEthPhyRestartAN - Restart ethernet Phy Auto-Negotiation.
+*
+* DESCRIPTION:
+*       This function resets a given ethernet Phy.
+*
+* INPUT:
+*       phyAddr - Phy address.
+*       timeout - in millisec; 0 - no timeout (don't wait)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK       - Success
+*           MV_TIMEOUT  - Timeout
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyRestartAN(MV_U32 phyAddr, int timeout)
+{
+	MV_U16  phyRegData;
+
+	/* Reset the PHY */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+
+	/* Set bit 12 to Enable autonegotiation of the PHY */
+	phyRegData |= ETH_PHY_CTRL_AN_ENABLE_MASK;
+
+	/* Set bit 9 to Restart autonegotiation of the PHY */
+	phyRegData |= ETH_PHY_CTRL_AN_RESTART_MASK;
+	mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData);
+
+	if (timeout == 0)
+		return MV_OK;
+
+	/* Wait untill Auotonegotiation completed */
+	while (timeout > 0) {
+		mvOsSleep(100);
+		timeout -= 100;
+
+		if (mvEthPhyRegRead(phyAddr, ETH_PHY_STATUS_REG, &phyRegData) != MV_OK)
+			return MV_FAIL;
+
+		if (phyRegData & ETH_PHY_STATUS_AN_DONE_MASK)
+			return MV_OK;
+	}
+	return MV_TIMEOUT;
+}
+
+
+/*******************************************************************************
+* mvEthPhyDisableAN - Disable Phy Auto-Negotiation and set forced Speed and Duplex
+*
+* DESCRIPTION:
+*       This function disable AN and set duplex and speed.
+*
+* INPUT:
+*       phyAddr - Phy address.
+*       speed   - port speed. 0 - 10 Mbps, 1-100 Mbps, 2 - 1000 Mbps
+*       duplex  - port duplex. 0 - Half duplex, 1 - Full duplex
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_OK   - Success
+*           MV_FAIL - Failure
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyDisableAN(MV_U32 phyAddr, int speed, int duplex)
+{
+	MV_U16  phyRegData;
+
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
+		return MV_FAIL;
+
+	switch (speed) {
+	case 0: /* 10 Mbps */
+			phyRegData &= ~ETH_PHY_CTRL_SPEED_LSB_MASK;
+			phyRegData &= ~ETH_PHY_CTRL_SPEED_MSB_MASK;
+			break;
+
+	case 1: /* 100 Mbps */
+			phyRegData |= ETH_PHY_CTRL_SPEED_LSB_MASK;
+			phyRegData &= ~ETH_PHY_CTRL_SPEED_MSB_MASK;
+			break;
+
+	case 2: /* 1000 Mbps */
+			phyRegData &= ~ETH_PHY_CTRL_SPEED_LSB_MASK;
+			phyRegData |= ETH_PHY_CTRL_SPEED_MSB_MASK;
+			break;
+
+	default:
+			mvOsOutput("Unexpected speed = %d\n", speed);
+			return MV_FAIL;
+	}
+
+	switch (duplex) {
+	case 0: /* half duplex */
+			phyRegData &= ~ETH_PHY_CTRL_DUPLEX_MASK;
+			break;
+
+	case 1: /* full duplex */
+			phyRegData |= ETH_PHY_CTRL_DUPLEX_MASK;
+			break;
+
+	default:
+			mvOsOutput("Unexpected duplex = %d\n", duplex);
+	}
+	/* Clear bit 12 to Disable autonegotiation of the PHY */
+	phyRegData &= ~ETH_PHY_CTRL_AN_ENABLE_MASK;
+
+	/* Clear bit 9 to DISABLE, Restart autonegotiation of the PHY */
+	phyRegData &= ~ETH_PHY_CTRL_AN_RESTART_MASK;
+	mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData);
+	return MV_OK;
+}
+
+MV_STATUS   mvEthPhyLoopback(MV_U32 phyAddr, MV_BOOL isEnable)
+{
+	MV_U16      regVal, ctrlVal;
+	MV_STATUS   status;
+
+	/* Set loopback speed and duplex accordingly with current */
+	/* Bits: 6, 8, 13 */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &ctrlVal) != MV_OK)
+		return MV_FAIL;
+
+	if (isEnable) {
+		/* Select page 2 */
+		mvEthPhyRegWrite(phyAddr, 22, 2);
+
+		mvEthPhyRegRead(phyAddr, 21, &regVal);
+		regVal &= ~(ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_SPEED_LSB_MASK |
+				ETH_PHY_CTRL_SPEED_MSB_MASK | ETH_PHY_CTRL_AN_ENABLE_MASK);
+		regVal |= (ctrlVal & (ETH_PHY_CTRL_DUPLEX_MASK | ETH_PHY_CTRL_SPEED_LSB_MASK |
+					ETH_PHY_CTRL_SPEED_MSB_MASK | ETH_PHY_CTRL_AN_ENABLE_MASK));
+		mvEthPhyRegWrite(phyAddr, 21, regVal);
+
+		/* Select page 0 */
+		mvEthPhyRegWrite(phyAddr, 22, 0);
+
+		/* Disable Energy detection   R16[9:8] = 00 */
+		/* Disable MDI/MDIX crossover R16[6:5] = 00 */
+		mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_CTRL_REG, &regVal);
+		regVal &= ~(BIT5 | BIT6 | BIT8 | BIT9);
+		mvEthPhyRegWrite(phyAddr, ETH_PHY_SPEC_CTRL_REG, regVal);
+
+		status = mvEthPhyReset(phyAddr, 1000);
+		if (status != MV_OK) {
+			mvOsPrintf("mvEthPhyReset failed: status=0x%x\n", status);
+			return status;
+		}
+
+		/* Set loopback */
+		ctrlVal |= ETH_PHY_CTRL_LOOPBACK_MASK;
+		mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, ctrlVal);
+	} else {
+		/* Cancel Loopback */
+		ctrlVal &= ~ETH_PHY_CTRL_LOOPBACK_MASK;
+		mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, ctrlVal);
+
+		status = mvEthPhyReset(phyAddr, 1000);
+		if (status != MV_OK) {
+			mvOsPrintf("mvEthPhyReset failed: status=0x%x\n", status);
+			return status;
+		}
+
+		/* Enable Energy detection   R16[9:8] = 11 */
+		/* Enable MDI/MDIX crossover R16[6:5] = 11 */
+		mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_CTRL_REG, &regVal);
+		regVal |= (BIT5 | BIT6 | BIT8 | BIT9);
+		mvEthPhyRegWrite(phyAddr, ETH_PHY_SPEC_CTRL_REG, regVal);
+
+		status = mvEthPhyReset(phyAddr, 1000);
+		if (status != MV_OK) {
+			mvOsPrintf("mvEthPhyReset failed: status=0x%x\n", status);
+			return status;
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyCheckLink -
+*
+* DESCRIPTION:
+*	check link in phy port
+*
+* INPUT:
+*       phyAddr - Phy address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   MV_TRUE if link is up, MV_FALSE if down
+*
+*******************************************************************************/
+MV_BOOL mvEthPhyCheckLink(MV_U32 phyAddr)
+{
+	MV_U16 val_st, val_ctrl, val_spec_st;
+
+	/* read status reg */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_STATUS_REG, &val_st) != MV_OK)
+		return MV_FALSE;
+
+	/* read control reg */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &val_ctrl) != MV_OK)
+		return MV_FALSE;
+
+	/* read special status reg */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_STATUS_REG, &val_spec_st) != MV_OK)
+		return MV_FALSE;
+
+	/* Check for PHY exist */
+	if ((val_ctrl == ETH_PHY_SMI_DATA_MASK) && (val_st & ETH_PHY_SMI_DATA_MASK))
+		return MV_FALSE;
+
+
+	if (val_ctrl & ETH_PHY_CTRL_AN_ENABLE_MASK) {
+		if (val_st & ETH_PHY_STATUS_AN_DONE_MASK)
+			return MV_TRUE;
+		else
+			return MV_FALSE;
+	} else {
+		if (val_spec_st & ETH_PHY_SPEC_STATUS_LINK_MASK)
+			return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvEthPhyPrintStatus -
+*
+* DESCRIPTION:
+*	print port Speed, Duplex, Auto-negotiation, Link.
+*
+* INPUT:
+*       phyAddr - Phy address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   16bit phy register value, or 0xffff on error
+*
+*******************************************************************************/
+MV_STATUS	mvEthPhyPrintStatus(MV_U32 phyAddr)
+{
+	MV_U16 val;
+
+	/* read control reg */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &val) != MV_OK)
+		return MV_ERROR;
+
+	if (val & ETH_PHY_CTRL_AN_ENABLE_MASK)
+		mvOsOutput("Auto negotiation: Enabled\n");
+	else
+		mvOsOutput("Auto negotiation: Disabled\n");
+
+
+	/* read specific status reg */
+	if (mvEthPhyRegRead(phyAddr, ETH_PHY_SPEC_STATUS_REG, &val) != MV_OK)
+		return MV_ERROR;
+
+	switch (val & ETH_PHY_SPEC_STATUS_SPEED_MASK) {
+	case ETH_PHY_SPEC_STATUS_SPEED_1000MBPS:
+			mvOsOutput("Speed: 1000 Mbps\n");
+			break;
+	case ETH_PHY_SPEC_STATUS_SPEED_100MBPS:
+			mvOsOutput("Speed: 100 Mbps\n");
+			break;
+	case ETH_PHY_SPEC_STATUS_SPEED_10MBPS:
+			mvOsOutput("Speed: 10 Mbps\n");
+	default:
+			mvOsOutput("Speed: Uknown\n");
+			break;
+
+	}
+
+	if (val & ETH_PHY_SPEC_STATUS_DUPLEX_MASK)
+		mvOsOutput("Duplex: Full\n");
+	else
+		mvOsOutput("Duplex: Half\n");
+
+
+	if (val & ETH_PHY_SPEC_STATUS_LINK_MASK)
+		mvOsOutput("Link: up\n");
+	else
+		mvOsOutput("Link: down\n");
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyAdvertiseSet -
+*
+* DESCRIPTION:
+*	Set advertisement mode
+*
+* INPUT:
+*       phyAddr - Phy address.
+*	advertise - 	0x1: 10 half
+*			0x2: 10 full
+*			0x4: 100 half
+*			0x8: 100 full
+*			0x10: 1000 half
+*			0x20: 1000 full
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyAdvertiseSet(MV_U32 phyAddr, MV_U16 advertise)
+{
+	MV_U16 regVal, tmp;
+	/* 10 - 100 */
+	mvEthPhyRegRead(phyAddr, ETH_PHY_AUTONEGO_AD_REG, &regVal);
+
+	regVal = regVal & (~ETH_PHY_10_100_BASE_ADVERTISE_MASK);
+	tmp = (advertise & 0xf);
+	regVal = regVal | (tmp << ETH_PHY_10_100_BASE_ADVERTISE_OFFSET);
+	mvEthPhyRegWrite(phyAddr, ETH_PHY_AUTONEGO_AD_REG, regVal);
+	/* 1000 */
+	mvEthPhyRegRead(phyAddr, ETH_PHY_1000BASE_T_CTRL_REG, &regVal);
+	/* keep only bits 4-5 + shift to the right */
+	tmp = ((advertise >> 4) & 0x3);
+	regVal = regVal & (~ETH_PHY_1000BASE_ADVERTISE_MASK);
+	regVal = regVal | (tmp << ETH_PHY_1000BASE_ADVERTISE_OFFSET);
+	mvEthPhyRegWrite(phyAddr, ETH_PHY_1000BASE_T_CTRL_REG, regVal);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPhyAdvertiseGet -
+*
+* DESCRIPTION:
+*	Get advertisement mode
+*
+* INPUT:
+*       phyAddr - Phy address.
+*
+* OUTPUT:
+*       advertise - 	0x1: 10 half
+*			0x2: 10 full
+*			0x4: 100 half
+*			0x8: 100 full
+*			0x10: 1000 half
+*			0x20: 1000 full
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_STATUS mvEthPhyAdvertiseGet(MV_U32 phyAddr, MV_U16 *advertise)
+{
+	MV_U16 regVal, tmp;
+	if (advertise == NULL)
+		return MV_BAD_PARAM;
+
+	/* 10 - 100 */
+	mvEthPhyRegRead(phyAddr, ETH_PHY_AUTONEGO_AD_REG, &regVal);
+	tmp = ((regVal & ETH_PHY_10_100_BASE_ADVERTISE_MASK) >> ETH_PHY_10_100_BASE_ADVERTISE_OFFSET);
+	/* 1000 */
+	mvEthPhyRegRead(phyAddr, ETH_PHY_1000BASE_T_CTRL_REG, &regVal);
+	tmp |= (((regVal & ETH_PHY_1000BASE_ADVERTISE_MASK) >> ETH_PHY_1000BASE_ADVERTISE_OFFSET) << 4);
+	*advertise = tmp;
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvEthE1111PhyBasicInit -
+*
+* DESCRIPTION:
+*	Do a basic Init to the Phy , including reset
+*
+* INPUT:
+*       phyAddr - PHY address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+MV_VOID		mvEthE1111PhyBasicInit(MV_U32 phyAddr)
+{
+	MV_U16 reg;
+
+	/* Phy recv and tx delay */
+	mvEthPhyRegRead(phyAddr, 20, &reg);
+	reg |= BIT1 | BIT7;
+	mvEthPhyRegWrite(phyAddr, 20, reg);
+
+	/* Leds link and activity*/
+	mvEthPhyRegWrite(phyAddr, 24, 0x4111);
+
+	/* reset the phy */
+	mvEthPhyRegRead(phyAddr, 0, &reg);
+	reg |= BIT15;
+	mvEthPhyRegWrite(phyAddr, 0, reg);
+
+	if (ethphyHalData.boardSpecInit == MV_TRUE)
+		mvEthPhyRegWrite(phyAddr,
+				ethphyHalData.specRegOff , ethphyHalData.specData);
+
+}
+
+/*******************************************************************************
+* mvEthE1112PhyBasicInit -
+*
+* DESCRIPTION:
+*	Do a basic Init to the Phy , including reset
+*
+* INPUT:
+*	phyAddr - PHY address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+MV_VOID		mvEthE1112PhyBasicInit(MV_U32 phyAddr)
+{
+	MV_U16 reg;
+
+	/* Set phy address */
+	/*MV_REG_WRITE(ETH_PHY_ADDR_REG(ethPortNum), mvBoardPhyAddrGet(ethPortNum));*/
+
+	/* Implement PHY errata */
+	mvEthPhyRegWrite(phyAddr, 22, 2);
+	mvEthPhyRegWrite(phyAddr, 0, 0x140);
+	mvEthPhyRegWrite(phyAddr, 0, 0x8140);
+	mvEthPhyRegWrite(phyAddr, 22, 0);
+
+	mvEthPhyRegWrite(phyAddr, 22, 3);
+	mvEthPhyRegWrite(phyAddr, 16, 0x103);
+	mvEthPhyRegWrite(phyAddr, 22, 0);
+
+	/* reset the phy */
+	mvEthPhyRegRead(phyAddr, 0, &reg);
+	reg |= BIT15;
+	mvEthPhyRegWrite(phyAddr, 0, reg);
+
+}
+
+/*******************************************************************************
+* mvEthE1116PhyBasicInit -
+*
+* DESCRIPTION:
+*	Do a basic Init to the Phy , including reset
+*
+* INPUT:
+*       phyAddr - PHY address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+MV_VOID		mvEthE1116PhyBasicInit(MV_U32 phyAddr)
+{
+	MV_U16 reg;
+
+	/* Leds link and activity*/
+	mvEthPhyRegWrite(phyAddr, 22, 0x3);
+	mvEthPhyRegRead(phyAddr, 16, &reg);
+	reg &= ~0xf;
+	reg	|= 0x1;
+	mvEthPhyRegWrite(phyAddr, 16, reg);
+	mvEthPhyRegWrite(phyAddr, 22, 0x0);
+
+	/* Set RGMII delay */
+	mvEthPhyRegWrite(phyAddr, 22, 2);
+	mvEthPhyRegRead(phyAddr, 21, &reg);
+	reg	|= (BIT5 | BIT4);
+	mvEthPhyRegWrite(phyAddr, 21, reg);
+	mvEthPhyRegWrite(phyAddr, 22, 0);
+
+	/* reset the phy */
+	mvEthPhyRegRead(phyAddr, 0, &reg);
+	reg |= BIT15;
+	mvEthPhyRegWrite(phyAddr, 0, reg);
+}
+
+
+/*******************************************************************************
+* mvEthE3016PhyBasicInit -
+*
+* DESCRIPTION:
+*	Do a basic Init to the Phy , including reset
+*
+* INPUT:
+*       phyAddr - PHY address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+MV_VOID		mvEthE3016PhyBasicInit(MV_U32 phyAddr)
+{
+	MV_U16 reg;
+
+	/* Leds link and activity*/
+	mvEthPhyRegRead(phyAddr, 22, &reg);
+	reg &= ~0xf;
+	reg	|= 0xa;
+	mvEthPhyRegWrite(phyAddr, 22, reg);
+
+	/* Set RGMII (RX) delay and copper mode */
+	mvEthPhyRegRead(phyAddr, 28, &reg);
+	reg &= ~(BIT3 | BIT10 | BIT11);
+	reg	|= (BIT10);
+	mvEthPhyRegWrite(phyAddr, 28, reg);
+
+	/* reset the phy */
+	mvEthPhyRegRead(phyAddr, 0, &reg);
+	reg |= BIT15;
+	mvEthPhyRegWrite(phyAddr, 0, reg);
+}
+
+
+/*******************************************************************************
+* mvEthE1011PhyBasicInit -
+*
+* DESCRIPTION:
+*	Do a basic Init to the Phy , including reset
+*
+* INPUT:
+*       phyAddr - PHY address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+MV_VOID		mvEthE1011PhyBasicInit(MV_U32 phyAddr)
+{
+	MV_U16 reg;
+
+	/* Phy recv and tx delay */
+	mvEthPhyRegRead(phyAddr, 20, &reg);
+	reg &= ~(BIT1 | BIT7);
+	mvEthPhyRegWrite(phyAddr, 20, reg);
+
+	/* Leds link and activity*/
+	mvEthPhyRegWrite(phyAddr, 24, 0x4111);
+
+	/* reset the phy */
+	mvEthPhyRegRead(phyAddr, 0, &reg);
+	reg |= BIT15;
+	mvEthPhyRegWrite(phyAddr, 0, reg);
+
+}
+
+/*******************************************************************************
+* mvEthE1112PhyPowerDown -
+*
+* DESCRIPTION:
+*	Power down the Phy , including reset
+*
+* INPUT:
+*       ethPortNum - Ethernet port number
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+MV_VOID	mvEthE1112PhyPowerDown(MV_U32 ethPortNum)
+{
+	mvEthPhyPower(ethPortNum, MV_FALSE);
+}
+
+/*******************************************************************************
+* mvEthE1112PhyPowerUp -
+*
+* DESCRIPTION:
+*	Power up the Phy , including reset
+*
+* INPUT:
+*       ethPortNum - Ethernet port number
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+MV_VOID	mvEthE1112PhyPowerUp(MV_U32 ethPortNum)
+{
+	mvEthPhyPower(ethPortNum, MV_TRUE);
+}
+
+/*******************************************************************************
+* mvEthPhyPower -
+*
+* DESCRIPTION:
+*	Do a basic power down/up to the Phy , including reset
+*
+* INPUT:
+*       ethPortNum - Ethernet port number
+*	enable - MV_TRUE - power up
+*		 MV_FALSE - power down
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+static MV_VOID	mvEthPhyPower(MV_U32 ethPortNum, MV_BOOL enable)
+{
+	MV_U16 reg;
+	if (enable == MV_FALSE) {
+	/* Power down command */
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 22, 2); 		/* select page 2 */
+		mvEthPhyRegRead(ethphyHalData.phyAddr[ethPortNum], 16, &reg);
+		reg |= BIT3;
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 16, reg);		/* select to disable the SERDES */
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 22, 0); 		/* select page 0 */
+
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 22, 3);		/* Power off LED's */
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 16, 0x88);
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 22, 0);
+
+		mvEthPhyRegRead(ethphyHalData.phyAddr[ethPortNum], ETH_PHY_CTRL_REG, &reg);
+		reg |= ETH_PHY_CTRL_RESET_MASK;
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], ETH_PHY_CTRL_REG, reg);	/* software reset */
+		mvEthPhyRegRead(ethphyHalData.phyAddr[ethPortNum], ETH_PHY_CTRL_REG, &reg);
+		reg |= ETH_PHY_CTRL_POWER_DOWN_MASK;
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], ETH_PHY_CTRL_REG, reg);	/* power down the PHY */
+	} else {
+	/* Power up command */
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 22, 2); 		/* select page 2 */
+		mvEthPhyRegRead(ethphyHalData.phyAddr[ethPortNum], 16, &reg);
+		reg &= ~BIT3;
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 16, reg);		/* select to enable the SERDES */
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 22, 0); 		/* select page 0 */
+
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 22, 3);		/* Power on LED's */
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 16, 0x03);
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], 22, 0);
+
+		mvEthPhyRegRead(ethphyHalData.phyAddr[ethPortNum], ETH_PHY_CTRL_REG, &reg);
+		reg |= ETH_PHY_CTRL_RESET_MASK;
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], ETH_PHY_CTRL_REG, reg);	/* software reset */
+		mvEthPhyRegRead(ethphyHalData.phyAddr[ethPortNum], ETH_PHY_CTRL_REG, &reg);
+		reg &= ~ETH_PHY_CTRL_POWER_DOWN_MASK;
+		mvEthPhyRegWrite(ethphyHalData.phyAddr[ethPortNum], ETH_PHY_CTRL_REG, reg);	/* power up the PHY */
+	}
+}
+
+
+/*******************************************************************************
+* mvEth1145PhyInit - Initialize MARVELL 1145 Phy
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       phyAddr - Phy address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvEth1145PhyBasicInit(MV_U32 phyAddr)
+{
+	MV_U16 value;
+
+	/* Set Link1000 output pin to be link indication, set Tx output pin to be activity */
+	mvEthPhyRegWrite(phyAddr, 0x18, ETH_PHY_LED_ACT_LNK_DV);
+	mvOsDelay(10);
+
+	/* Add delay to RGMII Tx and Rx */
+	mvEthPhyRegRead(phyAddr, 0x14, &value);
+	mvEthPhyRegWrite(phyAddr, 0x14, (value | BIT1 | BIT7));
+	mvOsDelay(10);
+
+	/* Set Phy TPVL to 0 */
+	mvEthPhyRegWrite(phyAddr, 0x10, 0x60);
+	mvOsDelay(10);
+
+	/* Reset Phy */
+	mvEthPhyRegRead(phyAddr, 0x00, &value);
+	mvEthPhyRegWrite(phyAddr, 0x00, (value | BIT15));
+	mvOsDelay(10);
+
+	return;
+}
+
+
+/*******************************************************************************
+* mvEthSgmiiToCopperPhyInit - Initialize Test board 1112 Phy
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       phyAddr - Phy address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvEthSgmiiToCopperPhyBasicInit(MV_U32 port)
+{
+    MV_U16 value;
+    MV_U16 phyAddr = 0xC;
+
+   /* Port 0 phyAdd c */
+   /* Port 1 phyAdd d */
+    mvEthPhyRegWrite(phyAddr + port, 22, 3);
+    mvEthPhyRegWrite(phyAddr + port, 16, 0x103);
+    mvEthPhyRegWrite(phyAddr + port, 22, 0);
+
+		/* reset the phy */
+    mvEthPhyRegRead(phyAddr + port, 0, &value);
+    value |= BIT15;
+    mvEthPhyRegWrite(phyAddr + port, 0, value);
+}
+
+
+MV_VOID mvEth1121PhyBasicInit(MV_U32 phyAddr)
+{
+	MV_U16 value;
+
+	/* Change page select to 2 */
+	value = 2;
+	mvEthPhyRegWrite(phyAddr, 22, value);
+	mvOsDelay(10);
+
+	/* Set RGMII rx delay */
+	mvEthPhyRegRead(phyAddr, 21, &value);
+	value |= BIT5;
+	mvEthPhyRegWrite(phyAddr, 21, value);
+	mvOsDelay(10);
+
+	/* Change page select to 0 */
+	value = 0;
+	mvEthPhyRegWrite(phyAddr, 22, value);
+	mvOsDelay(10);
+
+	/* reset the phy */
+	mvEthPhyRegRead(phyAddr, 0, &value);
+	value |= BIT15;
+	mvEthPhyRegWrite(phyAddr, 0, value);
+	mvOsDelay(10);
+}
+MV_VOID mvEthInternalGEPhyBasicInit(MV_U32 phyAddr, MV_BOOL eeeEnable)
+{
+	MV_U16 value;
+
+	if ((MV_6601_DEV_ID != mvCtrlModelGet()) && 
+	    (ethphyHalData.ctrlRevId < 2)) {
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x00FF);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0x0FD0);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x214C);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0x0000);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x2000);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0x0F16);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x2146);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x0);
+	}
+
+	/* reset the phy */
+	mvEthPhyRegRead(phyAddr, 0, &value);
+	value |= BIT15;
+	mvEthPhyRegWrite(phyAddr, 0, value);
+	mvOsDelay(10);
+
+	/* EEE support on Avanta-MC internel GbE PHY */
+	if ((MV_6601_DEV_ID == mvCtrlModelGet()) && (eeeEnable == MV_TRUE)) {
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x00FF);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0x214B);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x2144);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0x0C28);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x2146);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0xB233);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x214D);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0xCC0C);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x2159);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x00FB);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0xC00D);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x0000);
+		mvEthPhyRegWrite(phyAddr, 0xD, 0x0007);
+		mvEthPhyRegWrite(phyAddr, 0xE, 0x003C);
+		mvEthPhyRegWrite(phyAddr, 0xD, 0x4007);
+		mvEthPhyRegWrite(phyAddr, 0xE, 0x0006);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x0012);
+		mvEthPhyRegWrite(phyAddr, 0x0, 0x0C00);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x0000);
+		mvEthPhyRegWrite(phyAddr, 0x0, 0x9140);
+		mvOsDelay(10);
+	}
+
+	return;
+}
+
+MV_VOID mvEth1540Y0PhyBasicInit(MV_BOOL eeeEnable)
+{
+	int i;
+	MV_U16 reg;
+	int startAddr, endAddr;
+
+	startAddr = ethphyHalData.quadPhyStartAddr;
+	endAddr = startAddr + 4;
+
+	for (i = startAddr; i < endAddr; i++) {
+		/* Enable QSGMII AN */
+		/* Set page to 4. */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 4);
+		/* Enable AN */
+		mvEthPhyRegWriteExtSmi(i, 0x0, 0x1140);
+		/* Set page to 0. */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0);
+
+		/* Power up the phy */
+		mvEthPhyRegReadExtSmi(i, ETH_PHY_CTRL_REG, &reg);
+		reg &= ~(ETH_PHY_CTRL_POWER_DOWN_MASK);
+		mvEthPhyRegWriteExtSmi(i, ETH_PHY_CTRL_REG, reg);
+		mvOsDelay(100);
+		if (eeeEnable) {
+			/* set ELU#0 default match */
+			/* RW U1 P0 R22 H0010 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x10);
+			/* RW U1 P0 R1 H0104 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x0104);
+			/* RW U1 P0 R2 h0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x0000);
+			/* RW U1 P0 R3 H4000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x4000);
+			/* RW U1 P0 R1 H0904 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x0904);
+			/* RW U1 P0 R2 h0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x0000);
+			/* RW U1 P0 R3 H4000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x4000);
+			/* RW U1 P0 R1 H1104 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x1104);
+			/* RW U1 P0 R2 h0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x0000);
+			/* RW U1 P0 R3 H4000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x4000);
+			/* RW U1 P0 R1 H1904 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x1904);
+			/* RW U1 P0 R2 h0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x0000);
+			/* RW U1 P0 R3 H4000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x4000);
+			/* RW U1 P0 R22 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+			/* set ILU#0 default match */
+			/* RW U1 P0 R22 H0010 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+			/* RW U1 P0 R1 H0207 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x0207);
+			/* RW U1 P0 R2 h4000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x4000);
+			/* RW U1 P0 R3 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0000);
+			/* RW U1 P0 R1 H0A07 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x0a07);
+			/* RW U1 P0 R2 h4000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x4000);
+			/* RW U1 P0 R3 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0000);
+			/* RW U1 P0 R1 H1207 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x1207);
+			/* RW U1 P0 R2 h4000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x4000);
+			/* RW U1 P0 R3 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0000);
+			/* RW U1 P0 R1 H1A07 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x1a07);
+			/* RW U1 P0 R2 h4000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x4000);
+			/* RW U1 P0 R3 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0000);
+			/* RW U1 P0 R22 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+			/* change the wiremac ipg from 12 to 11 */
+			/* RW U1 P0 R22 H0010 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+			/* RW U1 P0 R1 H0041 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x0041);
+			/* RW U1 P0 R2 h00b1 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x00b1);
+			/* RW U1 P0 R3 H0002 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0002);
+			/* RW U1 P0 R1 H0841 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x0841);
+			/* RW U1 P0 R2 h00b1 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x00b1);
+			/* RW U1 P0 R3 H0002 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0002);
+			/* RW U1 P0 R1 H1041 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x1041);
+			/* RW U1 P0 R2 h00b1 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x00b1);
+			/* RW U1 P0 R3 H0002 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0002);
+			/* RW U1 P0 R1 H1841 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x1841);
+			/* RW U1 P0 R2 h00b1 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x00b1);
+			/* RW U1 P0 R3 H0002 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0002);
+			/* RW U1 P0 R22 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+
+			/* change the setting to not drop badtag */
+			/* RW U1 P0 R22 H0010 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+			/* RW U1 P0 R1 H000b */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x000b);
+			/* RW U1 P0 R2 h0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x0000);
+			/* RW U1 P0 R3 H0fb4 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0fb4);
+			/* RW U1 P0 R1 H080b */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x080b);
+			/* RW U1 P0 R2 h0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x0000);
+			/* RW U1 P0 R3 H0fb4 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0fb4);
+			/* RW U1 P0 R1 H100b */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x100b);
+			/* RW U1 P0 R2 h0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x0000);
+			/* RW U1 P0 R3 H0fb4 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0fb4);
+			/* RW U1 P0 R1 H180b */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x180b);
+			/* RW U1 P0 R2 h0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x0000);
+			/* RW U1 P0 R3 H0fb4 */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x0fb4);
+			/* RW U1 P0 R22 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+			/* set MACSec EEE Entry/Exit Timer */
+			/* RW U1 P0 R22 H0010 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+			/* RW U1 P0 R1 H03C0 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x03c0);
+			/* RW U1 P0 R2 H111E */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x111e);
+			/* RW U1 P0 R3 H111E */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x111e);
+			/* RW U1 P0 R1 H0BC0 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x0bc0);
+			/* RW U1 P0 R2 H111E */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x111e);
+			/* RW U1 P0 R3 H111E */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x111e);
+			/* RW U1 P0 R1 H13C0 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x13c0);
+			/* RW U1 P0 R2 H111E */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x111e);
+			/* RW U1 P0 R3 H111E */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x111e);
+			/* RW U1 P0 R1 H1BC0 */
+			mvEthPhyRegWriteExtSmi(i, 0x1, 0x1bc0);
+			/* RW U1 P0 R2 H111E */
+			mvEthPhyRegWriteExtSmi(i, 0x2, 0x111e);
+			/* RW U1 P0 R3 H111E */
+			mvEthPhyRegWriteExtSmi(i, 0x3, 0x111e);
+			/* RW U1 P0 R22 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+			/* Start of EEE Workaround */
+			/* RW U1 P0-3 R22 H00FB */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x00FB);
+			/* RW U1 P0-3 R11 H1120 */
+			mvEthPhyRegWriteExtSmi(i, 0xB , 0x1120);
+			/* RW U1 P0-3 R8  H3666 */
+			mvEthPhyRegWriteExtSmi(i, 0x8 , 0x3666);
+			/* RW U1 P0-3 R22 H00FF */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x00FF);
+			/* RW U1 P0-3 R17 H0F0C */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x0F0C);
+			/* RW U1 P0-3 R16 H2146 */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x2146);
+			/* RW U1 P0-3 R17 Hc090 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0xC090);
+			/* RW U1 P0-3 R16 H2147 */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x2147);
+			/* RW U1 P0-3 R17 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x0000);
+			/* RW U1 P0-3 R16 H2000 */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x2000);
+			/* RW U1 P0-3 R17 H6000 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x6000);
+			/* RW U1 P0-3 R16 H2143 */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x2143);
+			/* RW U1 P0-3 R17 HC004 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0xC004);
+			/* RW U1 P0-3 R16 H2100 */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x2100);
+			/* RW U1 P0-3 R17 H49E8 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x49E8);
+			/* RW U1 P0-3 R16 H2144 */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x2144);
+			/* RW U1 P0-3 R17 H3180 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x3180);
+			/* RW U1 P0-3 R16 H2148 */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x2148);
+			/* RW U1 P0-3 R17 HFC44 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0xFC44);
+			/* RW U1 P0-3 R16 H214B */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x214B);
+			/* RW U1 P0-3 R17 H7FD2 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x7FD2);
+			/* RW U1 P0-3 R16 H214C */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x214C);
+			/* RW U1 P0-3 R17 H2240 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x2240);
+			/* RW U1 P0-3 R16 H214D */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x214D);
+			/* RW U1 P0-3 R17 H3008 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x3008);
+			/* RW U1 P0-3 R16 H214E */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x214E);
+			/* RW U1 P0-3 R17 H3DF0 */
+			mvEthPhyRegWriteExtSmi(i, 0x11, 0x3DF0);
+			/* RW U1 P0-3 R16 H214F */
+			mvEthPhyRegWriteExtSmi(i, 0x10, 0x214F);
+			/* RW U1 P0-3 R22 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0);
+
+			/* Enable EEE Auto-neg advertisement on P0-P7 ports */
+			/* RW U1 P0-3 R13 H0007 */
+			mvEthPhyRegWriteExtSmi(i, 0xD , 0x0007);
+			/* RW U1 P0-3 R14 H003C */
+			mvEthPhyRegWriteExtSmi(i, 0xE , 0x003C);
+			/* RW U1 P0-3 R13 H4007 */
+			mvEthPhyRegWriteExtSmi(i, 0xD , 0x4007);
+			/* RW U1 P0-3 R14 H0006 */
+			mvEthPhyRegWriteExtSmi(i, 0xE , 0x0006);
+
+			/* Soft-Reset on P0-P7 ports */
+			/* RW U1 P0-3 R22 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0);
+			/* RW U1 P0-3 R0  H9140 */
+			mvEthPhyRegWriteExtSmi(i, 0x0 , 0x9140);
+
+			/* Enable MACsec EEE Master Mode on P0-3 ports */
+			/* RW U1 P0 R22 H0010 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+			/* RW U1 P0 R1  H03C1 */
+			mvEthPhyRegWriteExtSmi(i, 0x1 , 0x03C1);
+			/* RW U1 P0 R2  H0001 */
+			mvEthPhyRegWriteExtSmi(i, 0x2 , 0x0001);
+			/* RW U1 P0 R3  H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3 , 0x0000);
+			/* RW U1 P0 R1  H0BC1 */
+			mvEthPhyRegWriteExtSmi(i, 0x1 , 0x0BC1);
+			/* RW U1 P0 R2  H0001 */
+			mvEthPhyRegWriteExtSmi(i, 0x2 , 0x0001);
+			/* RW U1 P0 R3  H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3 , 0x0000);
+			/* RW U1 P0 R1  H13C1 */
+			mvEthPhyRegWriteExtSmi(i, 0x1 , 0x13C1);
+			/* RW U1 P0 R2  H0001 */
+			mvEthPhyRegWriteExtSmi(i, 0x2 , 0x0001);
+			/* RW U1 P0 R3  H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3 , 0x0000);
+			/* RW U1 P0 R1  H1BC1 */
+			mvEthPhyRegWriteExtSmi(i, 0x1 , 0x1BC1);
+			/* RW U1 P0 R2  H0001 */
+			mvEthPhyRegWriteExtSmi(i, 0x2 , 0x0001);
+			/* RW U1 P0 R3  H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x3 , 0x0000);
+			/* RW U1 P0 R22 H0000 */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+		}
+		/*  set ELU#0 default match   */
+		/*  RW U1 P0 R22 H0010  */
+		/*  RW U1 P0 R1 H0104 */
+		/*  RW U1 P0 R2 h0000 */
+		/*  RW U1 P0 R3 H4000 */
+		/*  RW U1 P0 R1 H0904 */
+		/*  RW U1 P0 R2 h0000 */
+		/*  RW U1 P0 R3 H4000 */
+		/*  RW U1 P0 R1 H1104 */
+		/*  RW U1 P0 R2 h0000 */
+		/*  RW U1 P0 R3 H4000 */
+		/*  RW U1 P0 R1 H1904 */
+		/*  RW U1 P0 R2 h0000 */
+		/*  RW U1 P0 R3 H4000 */
+		/*  RW U1 P0 R22 H0000 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+		/*  set ILU#0 default match  */
+		/*  RW U1 P0 R22 H0010 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+		/*  RW U1 P0 R1 H0207 */
+		/*  RW U1 P0 R2 h4000 */
+		/*  RW U1 P0 R3 H0000 */
+		/*  RW U1 P0 R1 H0A07 */
+		/*  RW U1 P0 R2 h4000 */
+		/*  RW U1 P0 R3 H0000 */
+		/*  RW U1 P0 R1 H1207 */
+		/*  RW U1 P0 R2 h4000 */
+		/*  RW U1 P0 R3 H0000 */
+		/*  RW U1 P0 R1 H1A07 */
+		/*  RW U1 P0 R2 h4000 */
+		/*  RW U1 P0 R3 H0000 */
+		/*  RW U1 P0 R22 H0000 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+		/*  change the wiremac ipg from 12 to 11   */
+		/*  RW U1 P0 R22 H0010 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+		/*  RW U1 P0 R1 H0041 */
+		/*  RW U1 P0 R2 h00b1 */
+		/*  RW U1 P0 R3 H0002 */
+		/*  RW U1 P0 R1 H0841 */
+		/*  RW U1 P0 R2 h00b1 */
+		/*  RW U1 P0 R3 H0002 */
+		/*  RW U1 P0 R1 H1041 */
+		/*  RW U1 P0 R2 h00b1 */
+		/*  RW U1 P0 R3 H0002 */
+		/*  RW U1 P0 R1 H1841 */
+		/*  RW U1 P0 R2 h00b1 */
+		/*  RW U1 P0 R3 H0002 */
+		/*  RW U1 P0 R22 H0000 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+
+		/*  change the setting to not drop badtag   */
+		/*  RW U1 P0 R22 H0010 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+		/*  RW U1 P0 R1 H000b */
+		/*  RW U1 P0 R2 h0000 */
+		/*  RW U1 P0 R3 H0fb4 */
+		/*  RW U1 P0 R1 H080b */
+		/*  RW U1 P0 R2 h0000 */
+		/*  RW U1 P0 R3 H0fb4 */
+		/*  RW U1 P0 R1 H100b */
+		/*  RW U1 P0 R2 h0000 */
+		/*  RW U1 P0 R3 H0fb4 */
+		/*  RW U1 P0 R1 H180b */
+		/*  RW U1 P0 R2 h0000 */
+		/*  RW U1 P0 R3 H0fb4 */
+		/*  RW U1 P0 R22 H0000 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+		/*  set MACSec EEE Entry/Exit Timer  */
+		/*  RW U1 P0 R22 H0010 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0010);
+		/*  RW U1 P0 R1 H03C0 */
+		/*  RW U1 P0 R2 H111E */
+		/*  RW U1 P0 R3 H111E */
+		/*  RW U1 P0 R1 H0BC0 */
+		/*  RW U1 P0 R2 H111E */
+		/*  RW U1 P0 R3 H111E */
+		/*  RW U1 P0 R1 H13C0 */
+		/*  RW U1 P0 R2 H111E */
+		/*  RW U1 P0 R3 H111E */
+		/*  RW U1 P0 R1 H1BC0 */
+		/*  RW U1 P0 R2 H111E */
+		/*  RW U1 P0 R3 H111E */
+		/*  RW U1 P0 R22 H0000 */
+		/*  RW U1 P0-3 R22 H00FB */
+		/*  RW U1 P0-3 R11 H1120 */
+		/*  RW U1 P0-3 R8  H3666 */
+		/*  RW U1 P0-3 R22 H00FF */
+		/*  RW U1 P0-3 R17 H0F0C */
+		/*  RW U1 P0-3 R16 H2146 */
+		/*  RW U1 P0-3 R17 Hc090 */
+		/*  RW U1 P0-3 R16 H2147 */
+		/*  RW U1 P0-3 R17 H0000 */
+		/*  RW U1 P0-3 R16 H2000 */
+		/*  RW U1 P0-3 R17 H6000 */
+		/*  RW U1 P0-3 R16 H2143 */
+		/*  RW U1 P0-3 R17 HC004 */
+		/*  RW U1 P0-3 R16 H2100 */
+		/*  RW U1 P0-3 R17 H49E8 */
+		/*  RW U1 P0-3 R16 H2144 */
+		/*  RW U1 P0-3 R17 H3180 */
+		/*  RW U1 P0-3 R16 H2148 */
+		/*  RW U1 P0-3 R17 HFC44 */
+		/*  RW U1 P0-3 R16 H214B */
+		/*  RW U1 P0-3 R17 H7FD2 */
+		/*  RW U1 P0-3 R16 H214C */
+		/*  RW U1 P0-3 R17 H2240 */
+		/*  RW U1 P0-3 R16 H214D */
+		/*  RW U1 P0-3 R17 H3008 */
+		/*  RW U1 P0-3 R16 H214E */
+		/*  RW U1 P0-3 R17 H3DF0 */
+		/*  RW U1 P0-3 R16 H214F */
+		/*  RW U1 P0-3 R22 H0000 */
+		/*  RW U1 P0-3 R13 H0007 */
+		/*  RW U1 P0-3 R14 H003C */
+		/*  RW U1 P0-3 R13 H4007 */
+		/*  RW U1 P0-3 R14 H0006 */
+		/*  RW U1 P0-3 R22 H0000 */
+		/*  RW U1 P0-3 R0  H9140 */
+		/*  RW U1 P0 R22 H0010 */
+		/*  RW U1 P0 R1  H03C1 */
+		/*  RW U1 P0 R2  H0001 */
+		/*  RW U1 P0 R3  H0000 */
+		/*  RW U1 P0 R1  H0BC1 */
+		/*  RW U1 P0 R2  H0001 */
+		/*  RW U1 P0 R3  H0000 */
+		/*  RW U1 P0 R1  H13C1 */
+		/*  RW U1 P0 R2  H0001 */
+		/*  RW U1 P0 R3  H0000 */
+		/*  RW U1 P0 R1  H1BC1 */
+		/*  RW U1 P0 R2  H0001 */
+		/*  RW U1 P0 R3  H0000 */
+		/*  RW U1 P0 R22 H0000 */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+
+		if (eeeEnable == MV_FALSE) {
+			/* Disable MACSec */
+			mvEthPhyRegWriteExtSmi(i, 0x16, 0x12);
+			mvEthPhyRegReadExtSmi(i, 27, &reg);
+			reg &= ~(1 << 13);
+			mvEthPhyRegWriteExtSmi(i, 27, reg);
+		}
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+	}
+	/*  Sleep 3000 */
+	mvOsDelay(300);
+
+}
+
+MV_VOID mvEth1540A0PhyBasicInit(MV_BOOL eeeEnable)
+{
+	int i;
+	MV_U16 reg;
+	int startAddr, endAddr;
+
+	startAddr = ethphyHalData.quadPhyStartAddr;
+	endAddr = startAddr + 4;
+
+	for (i = startAddr; i < endAddr; i++) {
+		/* Enable QSGMII AN */
+		/* Set page to 4. */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 4);
+		/* Enable AN */
+		mvEthPhyRegWriteExtSmi(i, 0x0, 0x1140);
+		/* Set page to 0. */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0);
+
+		/* Power up the phy */
+		mvEthPhyRegReadExtSmi(i, ETH_PHY_CTRL_REG, &reg);
+		reg &= ~(ETH_PHY_CTRL_POWER_DOWN_MASK);
+		mvEthPhyRegWriteExtSmi(i, ETH_PHY_CTRL_REG, reg);
+
+		/* Disable Drop BadTag */
+		mvEthPhyRegWriteExtSmi(i, 22, 0x0010);
+		mvEthPhyRegWriteExtSmi(i, 1, 0x000B);
+		mvEthPhyRegWriteExtSmi(i, 2, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 3, 0x0FB4);
+		mvEthPhyRegWriteExtSmi(i, 1, 0x080B);
+		mvEthPhyRegWriteExtSmi(i, 2, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 3, 0x0FB4);
+		mvEthPhyRegWriteExtSmi(i, 1, 0x100B);
+		mvEthPhyRegWriteExtSmi(i, 2, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 3, 0x0FB4);
+		mvEthPhyRegWriteExtSmi(i, 1, 0x180B);
+		mvEthPhyRegWriteExtSmi(i, 2, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 3, 0x0FB4);
+		mvEthPhyRegWriteExtSmi(i, 22, 0x0000);
+
+		mvEthPhyRegWriteExtSmi(i, 22, 0x00FA);
+		mvEthPhyRegWriteExtSmi(i, 8, 0x0010);
+
+		mvEthPhyRegWriteExtSmi(i, 22, 0x00FB);
+		mvEthPhyRegWriteExtSmi(i, 1, 0x4099);
+		mvEthPhyRegWriteExtSmi(i, 3, 0x1120);
+		mvEthPhyRegWriteExtSmi(i, 11, 0x113C);
+		mvEthPhyRegWriteExtSmi(i, 14, 0x8100);
+		mvEthPhyRegWriteExtSmi(i, 15, 0x112A);
+
+		mvEthPhyRegWriteExtSmi(i, 22, 0x00FC);
+		mvEthPhyRegWriteExtSmi(i, 1, 0x20B0);
+
+		mvEthPhyRegWriteExtSmi(i, 22, 0x00FF);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2000);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x4444);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2140);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x8064);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2141);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x0108);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2144);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x0F16);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2146);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x8C44);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x214B);
+
+		mvEthPhyRegWriteExtSmi(i, 17, 0x0F90);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x214C);
+		mvEthPhyRegWriteExtSmi(i, 17, 0xBA33);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x214D);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x39AA);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x214F);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x8433);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2151);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x2010);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2152);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x99EB);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2153);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x2F3B);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2154);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x584E);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2156);
+		mvEthPhyRegWriteExtSmi(i, 17, 0x1223);
+		mvEthPhyRegWriteExtSmi(i, 16, 0x2158);
+		mvEthPhyRegWriteExtSmi(i, 22, 0x0000);
+
+		/* Enable EEE_Auto-neg for 1000BASE-T and 100BASE-TX */
+		mvEthPhyRegWriteExtSmi(i, 22, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 13, 0x0007);
+		mvEthPhyRegWriteExtSmi(i, 14, 0x003C);
+		mvEthPhyRegWriteExtSmi(i, 13, 0x4007);
+		mvEthPhyRegWriteExtSmi(i, 14, 0x0006);
+
+		/* Enable MACSec (Reg 27_2.13 = '1') */
+		mvEthPhyRegWriteExtSmi(i, 22, 0x0012);
+		mvEthPhyRegReadExtSmi(i, 27, &reg);
+		reg |= (1 << 13);
+		mvEthPhyRegWriteExtSmi(i, 27, reg);
+
+		if (eeeEnable == MV_TRUE) {
+			/* Enable EEE Master (Legacy) Mode */
+			mvEthPhyRegWriteExtSmi(i, 22, 0x0010);
+			mvEthPhyRegWriteExtSmi(i, 1, 0x03c1);
+			mvEthPhyRegWriteExtSmi(i, 2, 0x0001);
+			mvEthPhyRegWriteExtSmi(i, 3, 0x0000);
+			mvEthPhyRegWriteExtSmi(i, 1, 0x0bc1);
+			mvEthPhyRegWriteExtSmi(i, 2, 0x0001);
+			mvEthPhyRegWriteExtSmi(i, 3, 0x0000);
+			mvEthPhyRegWriteExtSmi(i, 1, 0x13c1);
+			mvEthPhyRegWriteExtSmi(i, 2, 0x0001);
+			mvEthPhyRegWriteExtSmi(i, 3, 0x0000);
+			mvEthPhyRegWriteExtSmi(i, 1, 0x1bc1);
+			mvEthPhyRegWriteExtSmi(i, 2, 0x0001);
+			mvEthPhyRegWriteExtSmi(i, 3, 0x0000);
+			mvEthPhyRegWriteExtSmi(i, 22, 0x0000);
+		}
+
+		mvEthPhyRegWriteExtSmi(i, 22, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 0, 0x9140);
+
+		mvOsDelay(100);
+	}
+	/*  Sleep 3000 */
+	/* mvOsDelay(300); */
+
+}
+
+MV_VOID mvEth1540Z1PhyBasicInit(MV_BOOL eeeEnable)
+{
+	MV_U32 i;
+	MV_U32 startAddr, endAddr;
+
+	startAddr = ethphyHalData.quadPhyStartAddr;
+	endAddr = startAddr + 4;
+
+	for (i = startAddr; i < endAddr; i++) {
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0002);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x6008);
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0012);
+		mvEthPhyRegWriteExtSmi(i, 0x1, 0x111E);
+		mvEthPhyRegWriteExtSmi(i, 0x2, 0x111E);
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x00FA);
+		mvEthPhyRegWriteExtSmi(i, 0x8, 0x0010);
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x00FB);
+		mvEthPhyRegWriteExtSmi(i, 0x1, 0x4099);
+		mvEthPhyRegWriteExtSmi(i, 0x3, 0x1120);
+		mvEthPhyRegWriteExtSmi(i, 0xb, 0x113C);
+		mvEthPhyRegWriteExtSmi(i, 0xe, 0x8100);
+		mvEthPhyRegWriteExtSmi(i, 0xf, 0x112A);
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x00FC);
+		mvEthPhyRegWriteExtSmi(i, 0x1, 0x20B0);
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x00FF);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2000);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x4444);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2140);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x8064);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2141);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x0108);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2144);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x0F16);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2146);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x8C44);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x214B);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x0F90);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x214C);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0xBA33);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x214D);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x39AA);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x214F);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x8433);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2151);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x2010);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2152);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x99EB);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2153);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x2F3B);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2154);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x584E);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2156);
+		mvEthPhyRegWriteExtSmi(i, 0x11, 0x1223);
+		mvEthPhyRegWriteExtSmi(i, 0x10, 0x2158);
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0x0000);
+		mvEthPhyRegWriteExtSmi(i, 0x0 , 0x9140);
+	}
+}
+
+
+MV_VOID mvEth1540PhyBasicInit(MV_BOOL eeeEnable)
+{
+	MV_U16 reg;
+	int startAddr;
+
+	startAddr = ethphyHalData.quadPhyStartAddr;
+
+	/* Reads ID2 */
+	if (mvEthPhyRegReadExtSmi(startAddr, 3, &reg) != MV_OK)
+		return;
+
+	/* Check if this is 1545-Z1 */
+	if (((reg & 0x3F0) >> 4) == MV_PHY_88E154X_Z1) {
+		mvEth1540Z1PhyBasicInit(eeeEnable);
+		return;
+	}
+
+	/* Identify PHY Revision. */
+	mvEthPhyRegWriteExtSmi(startAddr, 0x16, 0xFB);
+	mvEthPhyRegReadExtSmi(startAddr, 0x1F, &reg);
+	mvEthPhyRegWriteExtSmi(startAddr, 0x16, 0x0);
+
+	if (reg == 0x100)
+		mvEth1540Y0PhyBasicInit(eeeEnable);
+	else
+		mvEth1540A0PhyBasicInit(eeeEnable);
+
+	return;
+}
+
+MV_VOID mvEth1340PhyBasicInit(void)
+{
+	int i;
+	MV_U16 reg;
+	int startAddr, endAddr;
+
+	startAddr = ethphyHalData.quadPhyStartAddr;
+	endAddr = startAddr + 4;
+
+	for (i = startAddr; i < endAddr; i++) {
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0);
+		mvEthPhyRegWriteExtSmi(i, 0x1d, 3);
+		mvEthPhyRegWriteExtSmi(i, 0x1e, 2);
+		mvEthPhyRegWriteExtSmi(i, 0x1d, 0);
+
+		/* Power up the phy */
+		/* mvEthPhyRegReadExtSmi(i,ETH_PHY_CTRL_REG, &reg); */
+		/* reg |= ETH_PHY_CTRL_RESET_MASK; */
+		/* mvEthPhyRegWriteExtSmi(i,ETH_PHY_CTRL_REG, reg);   software reset */
+
+		/* Enable QSGMII AN */
+		/* Set page to 4. */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 4);
+		/* Enable AN */
+		mvEthPhyRegWriteExtSmi(i, 0x0, 0x1140);
+		/* Set page to 0. */
+		mvEthPhyRegWriteExtSmi(i, 0x16, 0);
+
+		mvEthPhyRegReadExtSmi(i, ETH_PHY_CTRL_REG, &reg);
+		reg &= ~(ETH_PHY_CTRL_POWER_DOWN_MASK);
+		mvEthPhyRegWriteExtSmi(i, ETH_PHY_CTRL_REG, reg);
+	}
+}
+
+MV_VOID mvEth131xPhyBasicInit(MV_U32 phyAddr)
+{
+	MV_U16	val;
+
+	mvEthPhyRegWrite(phyAddr, 0x16, 0x2);
+	mvEthPhyRegRead(phyAddr, 0x18, &val);
+	/* Force PMOS, NMOS values. */
+	val |= (1 << 6);
+	/* Set NMOS value. */
+	val &= ~0x7;
+	val |= 0x1;
+
+	/* Set PMOS value. */
+	val &= ~(0x7 << 8);
+	val |= (1 << 8);
+	mvEthPhyRegWrite(phyAddr, 0x18, val);
+	mvEthPhyRegWrite(phyAddr, 0x16, 0x0);
+
+	return;
+}
+/*******************************************************************************
+* mvEthE1512PhyBasicInit -
+*
+* DESCRIPTION:
+*	Do a basic Init to the Phy , including reset
+*
+* INPUT:
+*       ethPortNum - Ethernet port number
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:   None
+*
+*******************************************************************************/
+MV_VOID mvEthE1512PhyBasicInit(MV_U32 ethPortNum, MV_BOOL eeeEnable)
+{
+	MV_U32 phyAddr;
+
+	phyAddr = ethphyHalData.phyAddr[ethPortNum];
+
+	mvEthPhyRegWrite(phyAddr, 0x16, 0x12);
+	mvEthPhyRegWrite(phyAddr, 0x14, 0x201);
+	mvEthPhyRegWrite(phyAddr, 0x14, 0x8201);
+	mvEthPhyRegWrite(phyAddr, 0x16, 0);
+
+	/* EEE support on Avanta-MC 1512 PHY(on-board) */
+	if ((MV_6601_DEV_ID == mvCtrlModelGet()) && (eeeEnable == MV_TRUE)) {
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x00FF);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0x214B);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x2144);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0x0C28);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x2146);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0xB233);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x214D);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0xCC0C);
+		mvEthPhyRegWrite(phyAddr, 0x10, 0x2159);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x00FB);
+		mvEthPhyRegWrite(phyAddr, 0x11, 0xC00D);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x0000);
+		mvEthPhyRegWrite(phyAddr, 0xD, 0x0007);
+		mvEthPhyRegWrite(phyAddr, 0xE, 0x003C);
+		mvEthPhyRegWrite(phyAddr, 0xD, 0x4007);
+		mvEthPhyRegWrite(phyAddr, 0xE, 0x0006);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x0012);
+		mvEthPhyRegWrite(phyAddr, 0x0, 0x0C00);
+		mvEthPhyRegWrite(phyAddr, 0x16, 0x0000);
+		mvEthPhyRegWrite(phyAddr, 0x0, 0x9140);
+		mvOsDelay(10);
+	}
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.h b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.h
new file mode 100755
index 0000000..d621d81
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhy.h
@@ -0,0 +1,157 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCETHPHYH
+#define __INCETHPHYH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysEthPhyConfig.h"
+#define MV_PHY_88F6601_INTERNAL 0x0
+#define MV_PHY_88E3061  0x1      /* E3061, E3081 */
+#define MV_PHY_88E104X  0x2      /* E1040, E1041, E1042 */
+#define MV_PHY_88E10X0  0x4      /* E1000, E1010, E1020 */
+#define MV_PHY_88E10X0S 0x5      /* E1000S, E1010S, E1020S */
+#define MV_PHY_88E1011  0x6      /* E1011, E1011S */
+#define MV_PHY_88E3082  0x8
+#define MV_PHY_88E1112  0x9
+#define MV_PHY_88E1149  0xA
+#define MV_PHY_88E1121  0xB
+#define MV_PHY_88E1111  0xC      /* E1111, E1115 */
+#define MV_PHY_88E114X  0xD
+#define MV_PHY_88E1181  0xE
+#define MV_PHY_88E1340S 0x1C    /* 88E1340S */
+#define MV_PHY_88E1512  0x1D
+#define MV_PHY_88E1340  0x1E    /* 88E1340/x0a */
+#define MV_PHY_88E154X  0x2B     /* 88E1545M */
+#define MV_PHY_88E154X_Z1 0x2A   /* 88E1545M-Z1 */
+#define MV_PHY_88E1340M 0x1F    /* 88E1340M/x0a */
+#define MV_PHY_88E1116R 0x24
+#define MV_PHY_88E1116  0x21     /* E1116, E1116R */
+#define MV_PHY_88E3016_88E3019  0x22     /* E3015, E3016, E3018, 88E3019 */
+#define MV_PHY_88E1240  0x23
+#define MV_PHY_88E1149R 0x25
+#define MV_PHY_88E1119R 0x28    /* 88E1119R */
+#define MV_PHY_88E1310  0x29    /* 88E1310 */
+#define MV_PHY_KW2_INTERNAL_GE  0x2b
+#define MV_PHY_KW2_INTERNAL_3FE 0x26
+
+#define MV_IS_MARVELL_OUI(_reg2, _reg3)		\
+	(((_reg2) == 0x0141) && (((_reg3)&0xFC00) == 0x0C00))
+
+typedef struct {
+	MV_U8		ctrlRevId;
+	MV_U32		phyAddr[MV_ETH_MAX_PORTS];
+	MV_U32		quadPhyStartAddr;
+	MV_BOOL		boardSpecInit;		/* Special board phy init */
+	MV_U32		specRegOff;		/* Board specific register offset, Valid if boardSpecInit == TRUE */
+	MV_U32		specData;  		/* Board specific data to write, Valid if boardSpecInit == TRUE */
+	MV_U32		ethPhySmiReg;		/* Ethernet unit PHY SMI register offset */
+	/* Below functions are needed for initializing Quad PHYs through an
+	** external switch SMI bus.
+	** These are optional parameters.
+	*/
+	MV_STATUS	(*mvExtPhyWriteFunc)(MV_U32 phyAddr, MV_U32 regAddr, MV_U16 val);
+	MV_STATUS	(*mvExtPhyReadFunc)(MV_U32 phyAddr, MV_U32 regAddr, MV_U16 *data);
+} MV_ETHPHY_HAL_DATA;
+
+MV_STATUS 	mvEthPhyHalInit(MV_ETHPHY_HAL_DATA *halData);
+MV_STATUS	mvEthPhyInit(MV_U32 ethPortNum, MV_BOOL eeeEnable);
+MV_STATUS	mvEthPhyRegRead(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 *data);
+MV_STATUS 	mvEthPhyRegWrite(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 data);
+MV_STATUS 	mvEthPhyReset(MV_U32 phyAddr, int timeout);
+MV_STATUS 	mvEthPhyRestartAN(MV_U32 phyAddr, int timeout);
+MV_STATUS 	mvEthPhyDisableAN(MV_U32 phyAddr, int speed, int duplex);
+MV_STATUS   	mvEthPhyLoopback(MV_U32 phyAddr, MV_BOOL isEnable);
+MV_BOOL     	mvEthPhyCheckLink(MV_U32 phyAddr);
+MV_STATUS	mvEthPhyPrintStatus(MV_U32 phyAddr);
+MV_STATUS	mvEthPhyAdvertiseSet(MV_U32 phyAddr, MV_U16 advertise);
+MV_STATUS	mvEthPhyAdvertiseGet(MV_U32 phyAddr, MV_U16 *advertise);
+
+MV_VOID		mvEthE1111PhyBasicInit(MV_U32 phyAddr);
+MV_VOID		mvEthE1112PhyBasicInit(MV_U32 phyAddr);
+MV_VOID		mvEthE1112PhyPowerDown(MV_U32 phyAddr);
+MV_VOID		mvEthE1112PhyPowerUp(MV_U32 phyAddr);
+MV_VOID		mvEthE1116PhyPower(MV_U32 phyAddr, MV_BOOL enable);
+MV_VOID		mvEthE1116PhyBasicInit(MV_U32 phyAddr);
+MV_VOID		mvEthE3016PhyBasicInit(MV_U32 phyAddr);
+MV_VOID		mvEthE1011PhyBasicInit(MV_U32 phyAddr);
+MV_VOID 	mvEthSgmiiToCopperPhyBasicInit(MV_U32 phyAddr);
+MV_VOID		mvEth1145PhyBasicInit(MV_U32 phyAddr);
+MV_VOID		mvEth1121PhyBasicInit(MV_U32 phyAddr);
+MV_VOID		mvEthInternalGEPhyBasicInit(MV_U32 phyAddr, MV_BOOL eeeEnable);
+MV_VOID		mvEth1540PhyBasicInit(MV_BOOL eeeEnable);
+MV_VOID		mvEth1340PhyBasicInit(void);
+MV_VOID		mvEth131xPhyBasicInit(MV_U32 phyAddr);
+MV_VOID 	mvEthE1512PhyBasicInit(MV_U32 ethPortNum, MV_BOOL eeeEnable);
+/* MV_VOID		mvEthInternal3FEPhyBasicInit(MV_U32 port); */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef __INCETHPHYH */
diff --git a/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhyRegs.h b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhyRegs.h
new file mode 100755
index 0000000..c91984d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth-phy/mvEthPhyRegs.h
@@ -0,0 +1,173 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	 specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCethphyregsh
+#define __INCethphyregsh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvSysEthConfig.h"
+
+/* defines */
+#define ETH_PHY_TIMEOUT		    10000
+
+/* SMI register fields (ETH_PHY_SMI_REG) */
+
+#define ETH_PHY_SMI_DATA_OFFS	        0 /* Data */
+#define ETH_PHY_SMI_DATA_MASK	        (0xffff << ETH_PHY_SMI_DATA_OFFS)
+
+#define ETH_PHY_SMI_DEV_ADDR_OFFS	    16 /* PHY device address */
+#define ETH_PHY_SMI_DEV_ADDR_MASK       (0x1f << ETH_PHY_SMI_DEV_ADDR_OFFS)
+
+#define ETH_PHY_SMI_REG_ADDR_OFFS	    21 /* PHY device register address */
+#define ETH_PHY_SMI_REG_ADDR_MASK	    (0x1f << ETH_PHY_SMI_REG_ADDR_OFFS)
+
+#define ETH_PHY_SMI_OPCODE_OFFS	        26	/* Write/Read opcode */
+#define ETH_PHY_SMI_OPCODE_MASK	        (3 << ETH_PHY_SMI_OPCODE_OFFS)
+#define ETH_PHY_SMI_OPCODE_WRITE        (0 << ETH_PHY_SMI_OPCODE_OFFS)
+#define ETH_PHY_SMI_OPCODE_READ         (1 << ETH_PHY_SMI_OPCODE_OFFS)
+
+#define ETH_PHY_SMI_READ_VALID_BIT	    27	/* Read Valid  */
+#define ETH_PHY_SMI_READ_VALID_MASK	    (1 << ETH_PHY_SMI_READ_VALID_BIT)
+
+#define ETH_PHY_SMI_BUSY_BIT		    28  /* Busy */
+#define ETH_PHY_SMI_BUSY_MASK		    (1 << ETH_PHY_SMI_BUSY_BIT)
+
+/* PHY registers and bits */
+#define ETH_PHY_CTRL_REG                0
+#define ETH_PHY_STATUS_REG              1
+#define ETH_PHY_AUTONEGO_AD_REG		    4
+#define ETH_PHY_1000BASE_T_CTRL_REG	    9
+#define ETH_PHY_SPEC_CTRL_REG           16
+#define ETH_PHY_SPEC_STATUS_REG         17
+
+/* ETH_PHY_CTRL_REG bits */
+#define ETH_PHY_CTRL_SPEED_MSB_BIT      6
+#define ETH_PHY_CTRL_SPEED_MSB_MASK     (1 << ETH_PHY_CTRL_SPEED_MSB_BIT)
+
+#define ETH_PHY_CTRL_COLISION_TEST_BIT  7
+#define ETH_PHY_CTRL_COLISION_TEST_MASK (1 << ETH_PHY_CTRL_COLISION_TEST_BIT)
+
+#define ETH_PHY_CTRL_DUPLEX_BIT         8
+#define ETH_PHY_CTRL_DUPLEX_MASK        (1 << ETH_PHY_CTRL_DUPLEX_BIT)
+
+#define ETH_PHY_CTRL_AN_RESTART_BIT     9
+#define ETH_PHY_CTRL_AN_RESTART_MASK    (1 << ETH_PHY_CTRL_AN_RESTART_BIT)
+
+#define ETH_PHY_CTRL_ISOLATE_BIT        10
+#define ETH_PHY_CTRL_ISOLATE_MASK       (1 << ETH_PHY_CTRL_ISOLATE_BIT)
+
+#define ETH_PHY_CTRL_POWER_DOWN_BIT     11
+#define ETH_PHY_CTRL_POWER_DOWN_MASK    (1 << ETH_PHY_CTRL_POWER_DOWN_BIT)
+
+#define ETH_PHY_CTRL_AN_ENABLE_BIT      12
+#define ETH_PHY_CTRL_AN_ENABLE_MASK     (1 << ETH_PHY_CTRL_AN_ENABLE_BIT)
+
+#define ETH_PHY_CTRL_SPEED_LSB_BIT	    13
+#define ETH_PHY_CTRL_SPEED_LSB_MASK	    (1 << ETH_PHY_CTRL_SPEED_LSB_BIT)
+
+#define ETH_PHY_CTRL_LOOPBACK_BIT	    14
+#define ETH_PHY_CTRL_LOOPBACK_MASK	    (1 << ETH_PHY_CTRL_LOOPBACK_BIT)
+
+#define ETH_PHY_CTRL_RESET_BIT          15
+#define ETH_PHY_CTRL_RESET_MASK         (1 << ETH_PHY_CTRL_RESET_BIT)
+
+/* ETH_PHY_STATUS_REG bits */
+#define ETH_PHY_STATUS_AN_DONE_BIT      5
+#define ETH_PHY_STATUS_AN_DONE_MASK     (1 << ETH_PHY_STATUS_AN_DONE_BIT)
+
+/* ETH_PHY_AUTONEGO_AD_REG bits */
+#define ETH_PHY_10_100_BASE_ADVERTISE_OFFSET	5
+#define ETH_PHY_10_100_BASE_ADVERTISE_MASK	(0xf << ETH_PHY_10_100_BASE_ADVERTISE_OFFSET)
+
+/* ETH_PHY_1000BASE_T_CTRL_REG bits */
+#define ETH_PHY_1000BASE_ADVERTISE_OFFSET	8
+#define ETH_PHY_1000BASE_ADVERTISE_MASK		(0x3 << ETH_PHY_1000BASE_ADVERTISE_OFFSET)
+
+/* ETH_PHY_SPEC_STATUS_REG bits */
+#define ETH_PHY_SPEC_STATUS_SPEED_OFFS		14
+#define ETH_PHY_SPEC_STATUS_SPEED_MASK		(0x3 << ETH_PHY_SPEC_STATUS_SPEED_OFFS)
+
+#define ETH_PHY_SPEC_STATUS_SPEED_10MBPS	(0x0 << ETH_PHY_SPEC_STATUS_SPEED_OFFS)
+#define ETH_PHY_SPEC_STATUS_SPEED_100MBPS	(0x1 << ETH_PHY_SPEC_STATUS_SPEED_OFFS)
+#define ETH_PHY_SPEC_STATUS_SPEED_1000MBPS	(0x2 << ETH_PHY_SPEC_STATUS_SPEED_OFFS)
+
+
+#define ETH_PHY_SPEC_STATUS_DUPLEX_BIT		13
+#define ETH_PHY_SPEC_STATUS_DUPLEX_MASK		(0x1 << ETH_PHY_SPEC_STATUS_DUPLEX_BIT)
+
+#define ETH_PHY_SPEC_STATUS_LINK_BIT		10
+#define ETH_PHY_SPEC_STATUS_LINK_MASK		(0x1 << ETH_PHY_SPEC_STATUS_LINK_BIT)
+
+/* ETH_PHY_SPEC_STATUS_REG bits */
+#define ETH_PHY_LED_ACT_LNK_DV              0x4109
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __INCethphyregsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEth.c b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEth.c
new file mode 100755
index 0000000..21540f8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEth.c
@@ -0,0 +1,2592 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvEth.c - Marvell's Gigabit Ethernet controller low level driver
+*
+* DESCRIPTION:
+*       This file introduce OS independent APIs to Marvell's Gigabit Ethernet
+*       controller. This Gigabit Ethernet Controller driver API controls
+*       1) Operations (i.e. port Init, Finish, Up, Down, PhyReset etc').
+*       2) Data flow (i.e. port Send, Receive etc').
+*       3) MAC Filtering functions (ethSetMcastAddr, ethSetRxFilterMode, etc.)
+*       4) MIB counters support (ethReadMibCounter)
+*       5) Debug functions (ethPortRegs, ethPortCounters, ethPortQueues, etc.)
+*       Each Gigabit Ethernet port is controlled via ETH_PORT_CTRL struct.
+*       This struct includes configuration information as well as driver
+*       internal data needed for its operations.
+*
+*       Supported Features:
+*       - OS independent. All required OS services are implemented via external
+*       OS dependent components (like osLayer or ethOsg)
+*       - The user is free from Rx/Tx queue managing.
+*       - Simple Gigabit Ethernet port operation API.
+*       - Simple Gigabit Ethernet port data flow API.
+*       - Data flow and operation API support per queue functionality.
+*       - Support cached descriptors for better performance.
+*       - PHY access and control API.
+*       - Port Configuration API.
+*       - Full control over Special and Other Multicast MAC tables.
+*
+*******************************************************************************/
+/* includes */
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysEthConfig.h"
+#include "mvEthRegs.h"
+#include "eth/mvEth.h"
+#include "mvEthGbe.h"
+
+#ifdef MV_RT_DEBUG
+#   define ETH_DEBUG
+#endif
+
+/* locals */
+MV_BOOL ethDescInSram;
+MV_BOOL ethDescSwCoher;
+MV_ETH_HAL_DATA ethHalData;
+
+/* This array holds the control structure of each port */
+ETH_PORT_CTRL *ethPortCtrl[MV_ETH_MAX_PORTS];
+
+/* Ethernet Port Local routines */
+
+static void ethInitRxDescRing(ETH_PORT_CTRL *pPortCtrl, int queue);
+
+static void ethInitTxDescRing(ETH_PORT_CTRL *pPortCtrl, int queue);
+
+static void ethSetUcastTable(int portNo, int queue);
+
+static MV_BOOL ethSetUcastAddr(int ethPortNum, MV_U8 lastNibble, int queue);
+static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue);
+static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue);
+
+static void ethFreeDescrMemory(ETH_PORT_CTRL *pEthPortCtrl, MV_BUF_INFO *pDescBuf);
+static MV_U8 *ethAllocDescrMemory(ETH_PORT_CTRL *pEthPortCtrl, int size, MV_ULONG * pPhysAddr, MV_U32 *memHandle);
+
+static void mvEthPortSgmiiConfig(int port);
+
+/******************************************************************************/
+/*                      EthDrv Initialization functions                       */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvEthHalInit - Initialize the Giga Ethernet unit
+*
+* DESCRIPTION:
+*       This function initialize the Giga Ethernet unit.
+*       1) Configure Address decode windows of the unit
+*	2) Set registers to HW default values.
+*       3) Clear and Disable interrupts
+*
+* INPUT:  NONE
+*
+* RETURN: NONE
+*
+* NOTE: this function is called once in the boot process.
+*******************************************************************************/
+void mvEthHalInit(MV_ETH_HAL_DATA *halData)
+{
+	int port;
+
+	mvOsMemcpy(&ethHalData, halData, sizeof(MV_ETH_HAL_DATA));
+
+	/* Init static data structures */
+	for (port = 0; port < MV_ETH_MAX_PORTS; port++)
+		ethPortCtrl[port] = NULL;
+	/* Power down all existing ports */
+	for (port = 0; port < ethHalData.maxPortNum; port++) {
+		if (ethHalData.portData[port].powerOn == MV_FALSE)
+			continue;
+#if defined(MV78200)
+		/* Skip ports mapped to another CPU */
+		if (MV_FALSE == mvSocUnitIsMappedToThisCpu(GIGA0 + port))
+			continue;
+#endif
+
+		/* Disable Giga Ethernet Unit interrupts */
+		MV_REG_WRITE(ETH_UNIT_INTR_MASK_REG(port), 0);
+
+		/* Clear ETH_UNIT_INTR_CAUSE_REG register */
+		MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port), 0);
+
+	}
+
+	mvEthMemAttrGet(&ethDescInSram, &ethDescSwCoher);
+
+#if defined(ETH_DESCR_IN_SRAM)
+	if (ethDescInSram == MV_FALSE)
+		mvOsPrintf("ethDrv: WARNING! Descriptors will be allocated in DRAM instead of SRAM.\n");
+#endif /* ETH_DESCR_IN_SRAM */
+}
+
+/*******************************************************************************
+* mvEthMemAttrGet - Define properties (SRAM/DRAM, SW_COHER / HW_COHER / UNCACHED)
+*                       of of memory location for RX and TX descriptors.
+*
+* DESCRIPTION:
+*       This function allocates memory for RX and TX descriptors.
+*       - If ETH_DESCR_IN_SRAM defined, allocate from SRAM memory.
+*       - If ETH_DESCR_IN_SDRAM defined, allocate from SDRAM memory.
+*
+* INPUT:
+*	MV_BOOL* pIsSram - place of descriptors:
+*                      MV_TRUE  - in SRAM
+*                      MV_FALSE - in DRAM
+*   MV_BOOL* pIsSwCoher - cache coherency of descriptors:
+*                      MV_TRUE  - driver is responsible for cache coherency
+*                      MV_FALSE - driver is not responsible for cache coherency
+*
+* RETURN:
+*
+*******************************************************************************/
+void mvEthMemAttrGet(MV_BOOL *pIsSram, MV_BOOL *pIsSwCoher)
+{
+	MV_BOOL isSram, isSwCoher;
+
+	isSram = MV_FALSE;
+
+#ifdef CONFIG_HW_CACHE_COHERENCY
+	isSwCoher = MV_FALSE;
+#else
+	isSwCoher = MV_TRUE;
+#endif
+
+#if defined(ETH_DESCR_IN_SRAM)
+	if (ethHalData.sramSize > 0) {
+		isSram = MV_TRUE;
+#if (INTEG_SRAM_COHER == MV_CACHE_COHER_SW)
+		isSwCoher = MV_TRUE;
+#else
+		isSwCoher = MV_FALSE;
+#endif
+	}
+#endif /* ETH_DESCR_IN_SRAM */
+
+	if (pIsSram != NULL)
+		*pIsSram = isSram;
+
+	if (pIsSwCoher != NULL)
+		*pIsSwCoher = isSwCoher;
+}
+
+/******************************************************************************/
+/*                      Port Initialization functions                         */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvEthPortInit - Initialize the Ethernet port driver
+*
+* DESCRIPTION:
+*       This function initialize the ethernet port.
+*       1) Allocate and initialize internal port Control structure.
+*       2) Create RX and TX descriptor rings for default RX and TX queues
+*	3) Disable RX and TX operations, clear cause registers and
+*          mask all interrupts.
+*	4) Set all registers to default values and clean all MAC tables.
+*
+* INPUT:
+*       int             portNo          - Ethernet port number
+*       ETH_PORT_INIT   *pEthPortInit   - Ethernet port init structure
+*
+* RETURN:
+*       void* - ethernet port handler, that should be passed to the most other
+*               functions dealing with this port.
+*
+* NOTE: This function is called once per port when loading the eth module.
+*******************************************************************************/
+void *mvEthPortInit(int portNo, MV_ETH_PORT_INIT * pEthPortInit)
+{
+	int queue, descSize;
+	ETH_PORT_CTRL *pPortCtrl;
+
+	/* Check validity of parameters */
+	if ((portNo >= (int)ethHalData.maxPortNum) || (pEthPortInit->rxDefQ >= MV_ETH_RX_Q_NUM)) {
+		mvOsPrintf("EthPort #%d: Bad initialization parameters\n", portNo);
+		return NULL;
+	}
+	if ((pEthPortInit->rxDescrNum[pEthPortInit->rxDefQ]) == 0) {
+		mvOsPrintf("EthPort #%d: rxDefQ (%d) must be created\n", portNo, pEthPortInit->rxDefQ);
+		return NULL;
+	}
+
+	pPortCtrl = (ETH_PORT_CTRL *) mvOsMalloc(sizeof(ETH_PORT_CTRL));
+	if (pPortCtrl == NULL) {
+		mvOsPrintf("EthDrv: Can't allocate %dB for port #%d control structure!\n",
+			   (int)sizeof(ETH_PORT_CTRL), portNo);
+		return NULL;
+	}
+
+	memset(pPortCtrl, 0, sizeof(ETH_PORT_CTRL));
+	ethPortCtrl[portNo] = pPortCtrl;
+
+	pPortCtrl->portState = MV_UNDEFINED_STATE;
+
+	pPortCtrl->portNo = portNo;
+
+	pPortCtrl->osHandle = pEthPortInit->osHandle;
+
+	/* Copy Configuration parameters */
+	pPortCtrl->portConfig.rxDefQ = pEthPortInit->rxDefQ;
+	pPortCtrl->portConfig.ejpMode = 0;
+
+	for (queue = 0; queue < MV_ETH_RX_Q_NUM; queue++)
+		pPortCtrl->rxQueueConfig[queue].descrNum = pEthPortInit->rxDescrNum[queue];
+	for (queue = 0; queue < MV_ETH_TX_Q_NUM; queue++)
+		pPortCtrl->txQueueConfig[queue].descrNum = pEthPortInit->txDescrNum[queue];
+
+	mvEthPortDisable(pPortCtrl);
+
+	/* Set the board information regarding PHY address */
+	mvEthPhyAddrSet(pPortCtrl, ethHalData.portData[portNo].phyAddr);
+
+	/* Create all requested RX queues */
+	for (queue = 0; queue < MV_ETH_RX_Q_NUM; queue++) {
+		if (pPortCtrl->rxQueueConfig[queue].descrNum == 0)
+			continue;
+
+		/* Allocate memory for RX descriptors */
+		descSize = ((pPortCtrl->rxQueueConfig[queue].descrNum * ETH_RX_DESC_ALIGNED_SIZE) +
+			    CPU_D_CACHE_LINE_SIZE);
+
+		pPortCtrl->rxQueue[queue].descBuf.bufVirtPtr =
+		    ethAllocDescrMemory(pPortCtrl, descSize,
+					&pPortCtrl->rxQueue[queue].descBuf.bufPhysAddr,
+					&pPortCtrl->rxQueue[queue].descBuf.memHandle);
+		pPortCtrl->rxQueue[queue].descBuf.bufSize = descSize;
+		if (pPortCtrl->rxQueue[queue].descBuf.bufVirtPtr == NULL) {
+			mvOsPrintf("EthPort #%d, rxQ=%d: Can't allocate %d bytes in %s for %d RX descr\n",
+				   pPortCtrl->portNo, queue, descSize,
+				   ethDescInSram ? "SRAM" : "DRAM", pPortCtrl->rxQueueConfig[queue].descrNum);
+			return NULL;
+		}
+
+		ethInitRxDescRing(pPortCtrl, queue);
+	}
+	/* Create TX queues */
+	for (queue = 0; queue < MV_ETH_TX_Q_NUM; queue++) {
+		if (pPortCtrl->txQueueConfig[queue].descrNum == 0)
+			continue;
+
+		/* Allocate memory for TX descriptors */
+		descSize = ((pPortCtrl->txQueueConfig[queue].descrNum * ETH_TX_DESC_ALIGNED_SIZE) +
+			    CPU_D_CACHE_LINE_SIZE);
+
+		pPortCtrl->txQueue[queue].descBuf.bufVirtPtr =
+		    ethAllocDescrMemory(pPortCtrl, descSize,
+					&pPortCtrl->txQueue[queue].descBuf.bufPhysAddr,
+					&pPortCtrl->txQueue[queue].descBuf.memHandle);
+		pPortCtrl->txQueue[queue].descBuf.bufSize = descSize;
+		if (pPortCtrl->txQueue[queue].descBuf.bufVirtPtr == NULL) {
+			mvOsPrintf("EthPort #%d, txQ=%d: Can't allocate %d bytes in %s for %d TX descr\n",
+				   pPortCtrl->portNo, queue, descSize, ethDescInSram ? "SRAM" : "DRAM",
+				   pPortCtrl->txQueueConfig[queue].descrNum);
+			return NULL;
+		}
+
+		ethInitTxDescRing(pPortCtrl, queue);
+	}
+	mvEthDefaultsSet(pPortCtrl);
+
+	pPortCtrl->portState = MV_IDLE;
+	return pPortCtrl;
+}
+
+/*******************************************************************************
+* ethPortFinish - Finish the Ethernet port driver
+*
+* DESCRIPTION:
+*       This function finish the ethernet port.
+*       1) Down ethernet port if needed.
+*       2) Delete RX and TX descriptor rings for all created RX and TX queues
+*       3) Free internal port Control structure.
+*
+* INPUT:
+*       void*   pEthPortHndl  - Ethernet port handler
+*
+* RETURN:   NONE.
+*
+*******************************************************************************/
+void mvEthPortFinish(void *pPortHndl)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	int queue, portNo = pPortCtrl->portNo;
+
+	if (pPortCtrl->portState == MV_ACTIVE) {
+		mvOsPrintf("ethPort #%d: Warning !!! Finish port in Active state\n", portNo);
+		mvEthPortDisable(pPortHndl);
+	}
+
+	/* Free all allocated RX queues */
+	for (queue = 0; queue < MV_ETH_RX_Q_NUM; queue++)
+		ethFreeDescrMemory(pPortCtrl, &pPortCtrl->rxQueue[queue].descBuf);
+	/* Free all allocated TX queues */
+	for (queue = 0; queue < MV_ETH_TX_Q_NUM; queue++)
+		ethFreeDescrMemory(pPortCtrl, &pPortCtrl->txQueue[queue].descBuf);
+
+	/* Free port control structure */
+	mvOsFree(pPortCtrl);
+
+	ethPortCtrl[portNo] = NULL;
+}
+
+/*******************************************************************************
+* mvEthDefaultsSet - Set defaults to the ethernet port
+*
+* DESCRIPTION:
+*       This function set default values to the ethernet port.
+*       1) Clear Cause registers and Mask all interrupts
+*       2) Clear all MAC tables
+*       3) Set defaults to all registers
+*       4) Reset all created RX and TX descriptors ring
+*       5) Reset PHY
+*
+* INPUT:
+*       void*   pEthPortHndl  - Ethernet port handler
+*
+* RETURN:	MV_STATUS
+*               MV_OK - Success, Others - Failure
+* NOTE:
+*   This function update all the port configuration except those set
+*   Initialy by the OsGlue by MV_ETH_PORT_INIT.
+*   This function can be called after portDown to return the port setting
+*   to defaults.
+*******************************************************************************/
+MV_STATUS mvEthDefaultsSet(void *pPortHndl)
+{
+	int ethPortNo, queue;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	MV_U32 txPrio;
+	MV_U32 portCfgReg, portCfgExtReg, portSdmaCfgReg;
+
+	ethPortNo = pPortCtrl->portNo;
+
+	/* Clear Cause registers */
+	MV_REG_WRITE(ETH_INTR_CAUSE_REG(ethPortNo), 0);
+	MV_REG_WRITE(ETH_INTR_CAUSE_EXT_REG(ethPortNo), 0);
+
+	/* Mask all interrupts */
+	MV_REG_WRITE(ETH_INTR_MASK_REG(ethPortNo), 0);
+	MV_REG_WRITE(ETH_INTR_MASK_EXT_REG(ethPortNo), 0);
+
+	portCfgReg = PORT_CONFIG_VALUE;
+	portCfgExtReg = PORT_CONFIG_EXTEND_VALUE;
+
+	/* build PORT_SDMA_CONFIG_REG */
+	portSdmaCfgReg = ETH_TX_INTR_COAL_MASK(0);
+	portSdmaCfgReg |= ETH_TX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE);
+
+#ifdef CONFIG_HW_CACHE_COHERENCY
+	/* some devices have restricted RX burst size when using HW coherency */
+	portSdmaCfgReg |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_4_64BIT_VALUE);
+#else
+	portSdmaCfgReg |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE);
+#endif
+
+#if defined(MV_CPU_BE)
+	/* big endian */
+# if defined(MV_ARM)
+	portSdmaCfgReg |= (ETH_RX_NO_DATA_SWAP_MASK | ETH_TX_NO_DATA_SWAP_MASK |
+#if defined(MV_CPU_BE) && defined(MV_KW2_BE_ETH_WA)
+			   ETH_NO_DESC_SWAP_MASK);
+#else
+			   ETH_DESC_SWAP_MASK);
+#endif
+# elif defined(MV_PPC)
+	portSdmaCfgReg |= (ETH_RX_DATA_SWAP_MASK | ETH_TX_DATA_SWAP_MASK | ETH_NO_DESC_SWAP_MASK);
+# else
+# error "Giga Ethernet Swap policy is not defined for the CPU_ARCH"
+# endif	/* MV_ARM / MV_PPC */
+
+#else /* MV_CPU_LE */
+	/* little endian */
+	portSdmaCfgReg |= (ETH_RX_NO_DATA_SWAP_MASK | ETH_TX_NO_DATA_SWAP_MASK | 	ETH_NO_DESC_SWAP_MASK);
+#endif /* MV_CPU_BE / MV_CPU_LE */
+
+	pPortCtrl->portRxQueueCmdReg = 0;
+	pPortCtrl->portTxQueueCmdReg = 0;
+
+#if (MV_ETH_VERSION >= 4)
+	if (pPortCtrl->portConfig.ejpMode == MV_TRUE)
+		MV_REG_WRITE(ETH_TXQ_CMD_1_REG(ethPortNo), ETH_TX_EJP_ENABLE_MASK);
+	else
+		MV_REG_WRITE(ETH_TXQ_CMD_1_REG(ethPortNo), 0);
+#endif /* (MV_ETH_VERSION >= 4) */
+
+	ethSetUcastTable(ethPortNo, -1);
+	mvEthSetSpecialMcastTable(ethPortNo, -1);
+	mvEthSetOtherMcastTable(ethPortNo, -1);
+
+	/* Update value of PortConfig register accordingly with all RxQueue types */
+	pPortCtrl->portConfig.rxArpQ = pPortCtrl->portConfig.rxDefQ;
+	pPortCtrl->portConfig.rxBpduQ = pPortCtrl->portConfig.rxDefQ;
+	pPortCtrl->portConfig.rxTcpQ = pPortCtrl->portConfig.rxDefQ;
+	pPortCtrl->portConfig.rxUdpQ = pPortCtrl->portConfig.rxDefQ;
+
+	portCfgReg &= ~ETH_DEF_RX_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_QUEUE_MASK(pPortCtrl->portConfig.rxDefQ);
+
+	portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl->portConfig.rxArpQ);
+
+	portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl->portConfig.rxBpduQ);
+
+	portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl->portConfig.rxTcpQ);
+
+	portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl->portConfig.rxUdpQ);
+
+	/* Assignment of Tx CTRP of given queue */
+	txPrio = 0;
+
+	for (queue = 0; queue < MV_ETH_TX_Q_NUM; queue++) {
+		pQueueCtrl = &pPortCtrl->txQueue[queue];
+
+		if (pQueueCtrl->pFirstDescr != NULL) {
+			ethResetTxDescRing(pPortCtrl, queue);
+
+			MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo, queue), 0x3fffffff);
+			MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo, queue), 0x03ffffff);
+		} else {
+			MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo, queue), 0x0);
+			MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo, queue), 0x0);
+		}
+	}
+
+	/* Assignment of Rx CRDP of given queue */
+	for (queue = 0; queue < MV_ETH_RX_Q_NUM; queue++)
+		ethResetRxDescRing(pPortCtrl, queue);
+
+	/* Assign port configuration and command. */
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(ethPortNo), portCfgReg);
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(ethPortNo), portCfgExtReg);
+
+	/* Assign port SDMA configuration */
+	MV_REG_WRITE(ETH_SDMA_CONFIG_REG(ethPortNo), portSdmaCfgReg);
+
+	/* Turn off the port/queue bandwidth limitation */
+	MV_REG_WRITE(ETH_MAX_TRANSMIT_UNIT_REG(ethPortNo), 0x0);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* ethPortUp - Start the Ethernet port RX and TX activity.
+*
+* DESCRIPTION:
+*       This routine start Rx and Tx activity:
+*
+*       Note: Each Rx and Tx queue descriptor's list must be initialized prior
+*       to calling this function (use etherInitTxDescRing for Tx queues and
+*       etherInitRxDescRing for Rx queues).
+*
+* INPUT:
+*       void*   pEthPortHndl  - Ethernet port handler
+*
+* RETURN:   MV_STATUS
+*           MV_OK - Success, Others - Failure.
+*
+* NOTE : used for port link up.
+*******************************************************************************/
+MV_STATUS mvEthPortUp(void *pEthPortHndl)
+{
+	int ethPortNo;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+
+	ethPortNo = pPortCtrl->portNo;
+/*
+	if ((pPortCtrl->portState != MV_ACTIVE) && (pPortCtrl->portState != MV_PAUSED)) {
+		mvOsPrintf("ethDrv port%d: Unexpected port state %d\n", ethPortNo, pPortCtrl->portState);
+		return MV_BAD_STATE;
+	}
+*/
+	ethPortNo = pPortCtrl->portNo;
+
+	/* WA for incompatability of NETA unit in legacy mode */
+	{
+		int queue;
+		ETH_QUEUE_CTRL *pQueueCtrl;
+
+		for (queue = 0; queue < MV_ETH_RX_Q_NUM; queue++) {
+			pQueueCtrl = &pPortCtrl->rxQueue[queue];
+
+			if (pQueueCtrl->pFirstDescr != NULL) {
+				MV_REG_WRITE(ETH_RX_CUR_DESC_PTR_REG(ethPortNo, queue),
+					     (MV_U32) ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr));
+			}
+		}
+	}
+
+	/* Enable port RX. */
+	MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNo), pPortCtrl->portRxQueueCmdReg);
+
+	/* Enable port TX. */
+/*     MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(ethPortNo)) = pPortCtrl->portTxQueueCmdReg; */
+
+	pPortCtrl->portState = MV_ACTIVE;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* ethPortDown - Stop the Ethernet port activity.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       void*   pEthPortHndl  - Ethernet port handler
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure.
+*
+* NOTE : used for port link down.
+*******************************************************************************/
+MV_STATUS mvEthPortDown(void *pEthPortHndl)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	int ethPortNum = pPortCtrl->portNo;
+	unsigned int regData;
+	volatile int uDelay, mDelay;
+
+	/* Stop Rx port activity. Check port Rx activity. */
+	regData = (MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum))) & ETH_RXQ_ENABLE_MASK;
+	if (regData != 0) {
+		/* Issue stop command for active channels only */
+		MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNum), (regData << ETH_RXQ_DISABLE_OFFSET));
+	}
+
+	/* Stop Tx port activity. Check port Tx activity. */
+	regData = (MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum))) & ETH_TXQ_ENABLE_MASK;
+	if (regData != 0) {
+		/* Issue stop command for active channels only */
+		MV_REG_WRITE(ETH_TX_QUEUE_COMMAND_REG(ethPortNum), (regData << ETH_TXQ_DISABLE_OFFSET));
+	}
+
+	/* Wait for all Rx activity to terminate. */
+	mDelay = 0;
+	do {
+		if (mDelay >= RX_DISABLE_TIMEOUT_MSEC) {
+			mvOsPrintf("ethPort_%d: TIMEOUT for RX stopped !!! rxQueueCmd - 0x08%x\n", ethPortNum, regData);
+			break;
+		}
+		mvOsDelay(1);
+		mDelay++;
+
+		/* Check port RX Command register that all Rx queues are stopped */
+		regData = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum));
+	} while (regData & 0xFF);
+
+	/* Wait for all Tx activity to terminate. */
+	mDelay = 0;
+	do {
+		if (mDelay >= TX_DISABLE_TIMEOUT_MSEC) {
+			mvOsPrintf("ethPort_%d: TIMEOUT for TX stoped !!! txQueueCmd - 0x08%x\n", ethPortNum, regData);
+			break;
+		}
+		mvOsDelay(1);
+		mDelay++;
+
+		/* Check port TX Command register that all Tx queues are stopped */
+		regData = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum));
+	} while (regData & 0xFF);
+
+	/* Double check to Verify that TX FIFO is Empty */
+	mDelay = 0;
+	while (MV_TRUE) {
+		do {
+			if (mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC) {
+				mvOsPrintf("\n ethPort_%d: TIMEOUT for TX FIFO empty !!! portStatus - 0x08%x\n",
+					   ethPortNum, regData);
+				break;
+			}
+			mvOsDelay(1);
+			mDelay++;
+
+			regData = MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum));
+		} while (((regData & ETH_TX_FIFO_EMPTY_MASK(0)) == 0) || ((regData & ETH_TX_IN_PROGRESS_MASK(0)) != 0));
+
+		if (mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC)
+			break;
+
+		/* Double check */
+		regData = MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum));
+		if (((regData & ETH_TX_FIFO_EMPTY_MASK(0)) != 0) && ((regData & ETH_TX_IN_PROGRESS_MASK(0)) == 0)) {
+			break;
+		} else
+			mvOsPrintf("ethPort_%d: TX FIFO Empty double check failed. %d msec, portStatus=0x%x\n",
+				   ethPortNum, mDelay, regData);
+	}
+
+	/* Do NOT force link down */
+/*
+	regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum));
+	regData |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK);
+	MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData);
+*/
+	/* Wait about 2500 tclk cycles */
+	uDelay = (PORT_DISABLE_WAIT_TCLOCKS / (ethHalData.tclk / 1000000));
+	mvOsUDelay(uDelay);
+
+	pPortCtrl->portState = MV_PAUSED;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* ethPortEnable - Enable the Ethernet port and Start RX and TX.
+*
+* DESCRIPTION:
+*       This routine enable the Ethernet port and Rx and Tx activity:
+*
+*       Note: Each Rx and Tx queue descriptor's list must be initialized prior
+*       to calling this function (use etherInitTxDescRing for Tx queues and
+*       etherInitRxDescRing for Rx queues).
+*
+* INPUT:
+*       void*   pEthPortHndl  - Ethernet port handler
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure.
+*
+* NOTE: main usage is to enable the port after ifconfig up.
+*******************************************************************************/
+MV_STATUS mvEthPortEnable(void *pEthPortHndl)
+{
+	int 		port;
+	ETH_PORT_CTRL 	*pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	MV_U32 		regVal;
+
+	port = pPortCtrl->portNo;
+
+	/* Enable port */
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_0_REG(port));
+	regVal |= NETA_GMAC_PORT_EN_MASK;
+
+	MV_REG_WRITE(NETA_GMAC_CTRL_0_REG(port), regVal);
+
+	mvEthMibCountersClear(pEthPortHndl);
+
+	pPortCtrl->portState = MV_PAUSED;
+
+	/* If Link is UP, Start RX and TX traffic */
+	if (MV_REG_READ(NETA_GMAC_STATUS_REG(port)) & NETA_GMAC_LINK_UP_MASK)
+		return (mvEthPortUp(pEthPortHndl));
+
+	return MV_NOT_READY;
+}
+
+/*******************************************************************************
+* mvEthPortDisable - Stop RX and TX activities and Disable the Ethernet port.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       void*   pEthPortHndl  - Ethernet port handler
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure.
+*
+* NOTE: main usage is to disable the port after ifconfig down.
+*******************************************************************************/
+MV_STATUS mvEthPortDisable(void *pEthPortHndl)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	int 		port = pPortCtrl->portNo;
+	unsigned int regData;
+	volatile int mvDelay;
+
+	if (pPortCtrl->portState == MV_ACTIVE) {
+		/* Stop RX and TX activities */
+		mvEthPortDown(pEthPortHndl);
+	}
+
+	/* Reset the Enable bit in the Serial Control Register */
+    regData = MV_REG_READ(NETA_GMAC_CTRL_0_REG(port));
+    regData &= ~(NETA_GMAC_PORT_EN_MASK);
+    MV_REG_WRITE(NETA_GMAC_CTRL_0_REG(port), regData);
+
+	/* Wait about 2500 tclk cycles */
+	mvDelay = (PORT_DISABLE_WAIT_TCLOCKS * (ethHalData.cpuPclk / ethHalData.tclk));
+	for (mvDelay; mvDelay > 0; mvDelay--)
+		continue;
+
+	pPortCtrl->portState = MV_IDLE;
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPortForceTxDone - Get next buffer from TX queue in spite of buffer ownership.
+*
+* DESCRIPTION:
+*       This routine used to free buffers attached to the Tx ring and should
+*       be called only when Giga Ethernet port is Down
+*
+* INPUT:
+*       void*       pEthPortHndl    - Ethernet Port handler.
+*       int         txQueue         - Number of TX queue.
+*
+* OUTPUT:
+*       MV_PKT_INFO *pPktInfo       - Pointer to packet was sent.
+*
+* RETURN:
+*       MV_EMPTY    - There is no more buffers in this queue.
+*       MV_OK       - Buffer detached from the queue and pPktInfo structure
+*                   filled with relevant information.
+*
+*******************************************************************************/
+MV_PKT_INFO *mvEthPortForceTxDone(void *pEthPortHndl, int txQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	MV_PKT_INFO *pPktInfo;
+	ETH_TX_DESC *pTxDesc;
+	int port = pPortCtrl->portNo;
+
+	pQueueCtrl = &pPortCtrl->txQueue[txQueue];
+
+	while ((pQueueCtrl->pUsedDescr != pQueueCtrl->pCurrentDescr) || (pQueueCtrl->resource == 0)) {
+		/* Free next descriptor */
+		pQueueCtrl->resource++;
+		pTxDesc = (ETH_TX_DESC *) pQueueCtrl->pUsedDescr;
+
+		/* pPktInfo is available only in descriptors which are last descriptors */
+		pPktInfo = (MV_PKT_INFO *) ETH_GET_32B_DESCR_VAL(pTxDesc->returnInfo);
+		if (pPktInfo)
+			pPktInfo->status = ETH_GET_32B_DESCR_VAL(pTxDesc->cmdSts);
+
+		ETH_SET_32B_DESCR_VAL(pTxDesc->cmdSts, 0x0);
+		ETH_SET_32B_DESCR_VAL(pTxDesc->returnInfo, 0x0);
+		ETH_DESCR_FLUSH_INV(pPortCtrl, pTxDesc);
+
+		pQueueCtrl->pUsedDescr = TX_NEXT_DESC_PTR(pTxDesc, pQueueCtrl);
+
+		if (pPktInfo)
+			if (pPktInfo->status & ETH_TX_LAST_DESC_MASK)
+				return pPktInfo;
+	}
+	MV_REG_WRITE(ETH_TX_CUR_DESC_PTR_REG(port, txQueue),
+		     (MV_U32) ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr));
+	return NULL;
+}
+
+/*******************************************************************************
+* mvEthPortForceRx - Get next buffer from RX queue in spite of buffer ownership.
+*
+* DESCRIPTION:
+*       This routine used to free buffers attached to the Rx ring and should
+*       be called only when Giga Ethernet port is Down
+*
+* INPUT:
+*       void*       pEthPortHndl    - Ethernet Port handler.
+*       int         rxQueue         - Number of Rx queue.
+*
+* OUTPUT:
+*       MV_PKT_INFO *pPktInfo       - Pointer to received packet.
+*
+* RETURN:
+*       MV_EMPTY    - There is no more buffers in this queue.
+*       MV_OK       - Buffer detached from the queue and pBufInfo structure
+*                   filled with relevant information.
+*
+*******************************************************************************/
+MV_PKT_INFO *mvEthPortForceRx(void *pEthPortHndl, int rxQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	ETH_RX_DESC *pRxDesc;
+	MV_PKT_INFO *pPktInfo;
+	int port = pPortCtrl->portNo;
+
+	pQueueCtrl = &pPortCtrl->rxQueue[rxQueue];
+
+	if (pQueueCtrl->resource == 0) {
+		MV_REG_WRITE(ETH_RX_CUR_DESC_PTR_REG(port, rxQueue),
+			     (MV_U32) ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr));
+
+		return NULL;
+	}
+	/* Free next descriptor */
+	pQueueCtrl->resource--;
+	pRxDesc = (ETH_RX_DESC *) pQueueCtrl->pCurrentDescr;
+	pPktInfo = (MV_PKT_INFO *) ETH_GET_32B_DESCR_VAL(pRxDesc->returnInfo);
+
+	pPktInfo->status = ETH_GET_32B_DESCR_VAL(pRxDesc->cmdSts);
+	ETH_SET_32B_DESCR_VAL(pRxDesc->cmdSts, 0x0);
+	ETH_SET_32B_DESCR_VAL(pRxDesc->returnInfo, 0x0);
+	ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc);
+
+	pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl);
+	return pPktInfo;
+}
+
+/******************************************************************************/
+/*                          Port Configuration functions                      */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvEthRxCoalSet  - Sets coalescing interrupt mechanism on RX path
+*
+* DESCRIPTION:
+*       This routine sets the RX coalescing interrupt mechanism parameter.
+*       This parameter is a timeout counter, that counts in 64 tClk
+*       chunks, that when timeout event occurs a maskable interrupt occurs.
+*       The parameter is calculated using the tCLK frequency of the
+*       MV-64xxx chip, and the required number is in micro seconds.
+*
+* INPUT:
+*       void*           pPortHndl   - Ethernet Port handler.
+*       MV_U32          uSec        - Number of micro seconds between
+*                                   RX interrupts
+*
+* RETURN:
+*       None.
+*
+* COMMENT:
+*   1 sec           - TCLK_RATE clocks
+*   1 uSec          - TCLK_RATE / 1,000,000 clocks
+*
+*   Register Value for N micro seconds -  ((N * ( (TCLK_RATE / 1,000,000)) / 64)
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_U32 mvEthRxCoalSet(void *pPortHndl, MV_U32 uSec)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	MV_U32 coal = ((uSec * (ethHalData.tclk / 1000000)) / 64);
+	MV_U32 portSdmaCfgReg;
+
+	portSdmaCfgReg = MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo));
+	portSdmaCfgReg &= ~ETH_RX_INTR_COAL_ALL_MASK;
+
+	portSdmaCfgReg |= ETH_RX_INTR_COAL_MASK(coal);
+
+#if (MV_ETH_VERSION >= 2)
+	/* Set additional bit if needed ETH_RX_INTR_COAL_MSB_BIT (25) */
+	if (ETH_RX_INTR_COAL_MASK(coal) > ETH_RX_INTR_COAL_ALL_MASK)
+		portSdmaCfgReg |= ETH_RX_INTR_COAL_MSB_MASK;
+#endif /* MV_ETH_VERSION >= 2 */
+
+	MV_REG_WRITE(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo), portSdmaCfgReg);
+	return coal;
+}
+
+/*******************************************************************************
+* mvEthTxCoalSet - Sets coalescing interrupt mechanism on TX path
+*
+* DESCRIPTION:
+*       This routine sets the TX coalescing interrupt mechanism parameter.
+*       This parameter is a timeout counter, that counts in 64 tClk
+*       chunks, that when timeout event occurs a maskable interrupt
+*       occurs.
+*       The parameter is calculated using the tCLK frequency of the
+*       MV-64xxx chip, and the required number is in micro seconds.
+*
+* INPUT:
+*       void*           pPortHndl    - Ethernet Port handler.
+*       MV_U32          uSec        - Number of micro seconds between
+*                                   RX interrupts
+*
+* RETURN:
+*       None.
+*
+* COMMENT:
+*   1 sec           - TCLK_RATE clocks
+*   1 uSec          - TCLK_RATE / 1,000,000 clocks
+*
+*   Register Value for N micro seconds -  ((N * ( (TCLK_RATE / 1,000,000)) / 64)
+*
+*******************************************************************************/
+MV_U32 mvEthTxCoalSet(void *pPortHndl, MV_U32 uSec)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	MV_U32 coal = ((uSec * (ethHalData.tclk / 1000000)) / 64);
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo));
+	regVal &= ~ETH_TX_INTR_COAL_ALL_MASK;
+	regVal |= ETH_TX_INTR_COAL_MASK(coal);
+
+	/* Set TX Coalescing mechanism */
+	MV_REG_WRITE(ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo), regVal);
+	return coal;
+}
+
+/*******************************************************************************
+* mvEthCoalGet - Gets RX and TX coalescing values in micro seconds
+*
+* DESCRIPTION:
+*       This routine gets the RX and TX coalescing interrupt values.
+*       The parameter is calculated using the tCLK frequency of the
+*       MV-64xxx chip, and the returned numbers are in micro seconds.
+*
+* INPUTs:
+*       void*   pPortHndl   - Ethernet Port handler.
+*
+* OUTPUTs:
+*       MV_U32* pRxCoal     - Number of micro seconds between RX interrupts
+*       MV_U32* pTxCoal     - Number of micro seconds between TX interrupts
+*
+* RETURN:
+*       MV_STATUS   MV_OK  - success
+*                   Others - failure.
+*
+* COMMENT:
+*   1 sec           - TCLK_RATE clocks
+*   1 uSec          - TCLK_RATE / 1,000,000 clocks
+*
+*   Register Value for N micro seconds -  ((N * ( (TCLK_RATE / 1,000,000)) / 64)
+*
+*******************************************************************************/
+MV_STATUS mvEthCoalGet(void *pPortHndl, MV_U32 * pRxCoal, MV_U32 * pTxCoal)
+{
+	MV_U32 regVal, coal, usec;
+
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+
+	/* get TX Coalescing */
+	regVal = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo));
+	coal = ((regVal & ETH_TX_INTR_COAL_ALL_MASK) >> ETH_TX_INTR_COAL_OFFSET);
+
+	usec = (coal * 64) / (ethHalData.tclk / 1000000);
+	if (pTxCoal != NULL)
+		*pTxCoal = usec;
+
+	/* Get RX Coalescing */
+	regVal = MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo));
+	coal = ((regVal & ETH_RX_INTR_COAL_ALL_MASK) >> ETH_RX_INTR_COAL_OFFSET);
+
+#if (MV_ETH_VERSION >= 2)
+	if (regVal & ETH_RX_INTR_COAL_MSB_MASK) {
+		/* Add MSB */
+		coal |= (ETH_RX_INTR_COAL_ALL_MASK + 1);
+	}
+#endif /* MV_ETH_VERSION >= 2 */
+
+	usec = (coal * 64) / (ethHalData.tclk / 1000000);
+	if (pRxCoal != NULL)
+		*pRxCoal = usec;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthMaxRxSizeSet -
+*
+* DESCRIPTION:
+*       Change maximum receive size of the port. This configuration will take place
+*       after next call of ethPortSetDefaults() function.
+*
+* INPUT:
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvEthMaxRxSizeSet(void *pPortHndl, int maxRxSize)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	int 		portNo = pPortCtrl->portNo;
+	MV_U32		regVal;
+
+	regVal =  MV_REG_READ(NETA_GMAC_CTRL_0_REG(portNo));
+	regVal &= ~NETA_GMAC_MAX_RX_SIZE_MASK;
+	regVal |= (maxRxSize << NETA_GMAC_MAX_RX_SIZE_OFFS);
+	MV_REG_WRITE(NETA_GMAC_CTRL_0_REG(portNo), regVal);
+
+	return MV_OK;
+}
+
+/******************************************************************************/
+/*                      MAC Filtering functions                               */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvEthRxFilterModeSet - Configure Fitering mode of Ethernet port
+*
+* DESCRIPTION:
+*       This routine used to free buffers attached to the Rx ring and should
+*       be called only when Giga Ethernet port is Down
+*
+* INPUT:
+*       void*       pEthPortHndl    - Ethernet Port handler.
+*       MV_BOOL     isPromisc       - Promiscous mode
+*                                   MV_TRUE  - accept all Broadcast, Multicast
+*                                              and Unicast packets
+*                                   MV_FALSE - accept all Broadcast,
+*                                              specially added Multicast and
+*                                              single Unicast packets
+*
+* RETURN:   MV_STATUS   MV_OK - Success, Other - Failure
+*
+*******************************************************************************/
+MV_STATUS mvEthRxFilterModeSet(void *pEthPortHndl, MV_BOOL isPromisc)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	int queue;
+	MV_U32 portCfgReg;
+
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
+	/* Set / Clear UPM bit in port configuration register */
+	if (isPromisc) {
+		/* Accept all multicast packets to RX default queue */
+		queue = pPortCtrl->portConfig.rxDefQ;
+		portCfgReg |= ETH_UNICAST_PROMISCUOUS_MODE_MASK;
+		memset(pPortCtrl->mcastCount, 1, sizeof(pPortCtrl->mcastCount));
+		MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl->portNo), 0xFFFF);
+		MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl->portNo), 0xFFFFFFFF);
+	} else {
+		/* Reject all Multicast addresses */
+		queue = -1;
+		portCfgReg &= ~ETH_UNICAST_PROMISCUOUS_MODE_MASK;
+		/* Clear all mcastCount */
+		memset(pPortCtrl->mcastCount, 0, sizeof(pPortCtrl->mcastCount));
+	}
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
+
+	/* Set Special Multicast and Other Multicast tables */
+	mvEthSetSpecialMcastTable(pPortCtrl->portNo, queue);
+	mvEthSetOtherMcastTable(pPortCtrl->portNo, queue);
+	ethSetUcastTable(pPortCtrl->portNo, queue);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthMacAddrSet - This function Set the port Unicast address.
+*
+* DESCRIPTION:
+*       This function Set the port Ethernet MAC address. This address
+*       will be used to send Pause frames if enabled. Packets with this
+*       address will be accepted and dispatched to default RX queue
+*
+* INPUT:
+*       void*   pEthPortHndl    - Ethernet port handler.
+*       char*   pAddr           - Address to be set
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success,  Other - Faulure
+*
+*******************************************************************************/
+MV_STATUS mvEthMacAddrSet(void *pPortHndl, unsigned char *pAddr, int queue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	unsigned int macH;
+	unsigned int macL;
+
+	if (queue >= MV_ETH_RX_Q_NUM) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", queue);
+		return MV_BAD_PARAM;
+	}
+
+	if (queue != -1) {
+		macL = (pAddr[4] << 8) | (pAddr[5]);
+		macH = (pAddr[0] << 24) | (pAddr[1] << 16) | (pAddr[2] << 8) | (pAddr[3] << 0);
+
+		MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl->portNo), macL);
+		MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl->portNo), macH);
+	}
+
+	/* Accept frames of this address */
+	ethSetUcastAddr(pPortCtrl->portNo, pAddr[5], queue);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthMacAddrGet - This function returns the port Unicast address.
+*
+* DESCRIPTION:
+*       This function returns the port Ethernet MAC address.
+*
+* INPUT:
+*       int     portNo          - Ethernet port number.
+*       char*   pAddr           - Pointer where address will be written to
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success,  Other - Faulure
+*
+*******************************************************************************/
+MV_STATUS mvEthMacAddrGet(int portNo, unsigned char *pAddr)
+{
+	unsigned int macH;
+	unsigned int macL;
+
+	if (pAddr == NULL) {
+		mvOsPrintf("mvEthMacAddrGet: NULL pointer.\n");
+		return MV_BAD_PARAM;
+	}
+
+	macH = MV_REG_READ(ETH_MAC_ADDR_HIGH_REG(portNo));
+	macL = MV_REG_READ(ETH_MAC_ADDR_LOW_REG(portNo));
+	pAddr[0] = (macH >> 24) & 0xff;
+	pAddr[1] = (macH >> 16) & 0xff;
+	pAddr[2] = (macH >> 8) & 0xff;
+	pAddr[3] = macH & 0xff;
+	pAddr[4] = (macL >> 8) & 0xff;
+	pAddr[5] = macL & 0xff;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthMcastCrc8Get - Calculate CRC8 of MAC address.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       MV_U8*  pAddr           - Address to calculate CRC-8
+*
+* RETURN: MV_U8 - CRC-8 of this MAC address
+*
+*******************************************************************************/
+MV_U8 mvEthMcastCrc8Get(MV_U8 *pAddr)
+{
+	unsigned int macH;
+	unsigned int macL;
+	int macArray[48];
+	int crc[8];
+	int i;
+	unsigned char crcResult = 0;
+
+	/* Calculate CRC-8 out of the given address */
+	macH = (pAddr[0] << 8) | (pAddr[1]);
+	macL = (pAddr[2] << 24) | (pAddr[3] << 16) | (pAddr[4] << 8) | (pAddr[5] << 0);
+
+	for (i = 0; i < 32; i++)
+		macArray[i] = (macL >> i) & 0x1;
+
+	for (i = 32; i < 48; i++)
+		macArray[i] = (macH >> (i - 32)) & 0x1;
+
+	crc[0] = macArray[45] ^ macArray[43] ^ macArray[40] ^ macArray[39] ^
+	    macArray[35] ^ macArray[34] ^ macArray[31] ^ macArray[30] ^
+	    macArray[28] ^ macArray[23] ^ macArray[21] ^ macArray[19] ^
+	    macArray[18] ^ macArray[16] ^ macArray[14] ^ macArray[12] ^
+	    macArray[8] ^ macArray[7] ^ macArray[6] ^ macArray[0];
+
+	crc[1] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^
+	    macArray[41] ^ macArray[39] ^ macArray[36] ^ macArray[34] ^
+	    macArray[32] ^ macArray[30] ^ macArray[29] ^ macArray[28] ^
+	    macArray[24] ^ macArray[23] ^ macArray[22] ^ macArray[21] ^
+	    macArray[20] ^ macArray[18] ^ macArray[17] ^ macArray[16] ^
+	    macArray[15] ^ macArray[14] ^ macArray[13] ^ macArray[12] ^
+	    macArray[9] ^ macArray[6] ^ macArray[1] ^ macArray[0];
+
+	crc[2] = macArray[47] ^ macArray[46] ^ macArray[44] ^ macArray[43] ^
+	    macArray[42] ^ macArray[39] ^ macArray[37] ^ macArray[34] ^
+	    macArray[33] ^ macArray[29] ^ macArray[28] ^ macArray[25] ^
+	    macArray[24] ^ macArray[22] ^ macArray[17] ^ macArray[15] ^
+	    macArray[13] ^ macArray[12] ^ macArray[10] ^ macArray[8] ^
+	    macArray[6] ^ macArray[2] ^ macArray[1] ^ macArray[0];
+
+	crc[3] = macArray[47] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^
+	    macArray[40] ^ macArray[38] ^ macArray[35] ^ macArray[34] ^
+	    macArray[30] ^ macArray[29] ^ macArray[26] ^ macArray[25] ^
+	    macArray[23] ^ macArray[18] ^ macArray[16] ^ macArray[14] ^
+	    macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[7] ^ macArray[3] ^ macArray[2] ^ macArray[1];
+
+	crc[4] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[41] ^
+	    macArray[39] ^ macArray[36] ^ macArray[35] ^ macArray[31] ^
+	    macArray[30] ^ macArray[27] ^ macArray[26] ^ macArray[24] ^
+	    macArray[19] ^ macArray[17] ^ macArray[15] ^ macArray[14] ^
+	    macArray[12] ^ macArray[10] ^ macArray[8] ^ macArray[4] ^ macArray[3] ^ macArray[2];
+
+	crc[5] = macArray[47] ^ macArray[46] ^ macArray[45] ^ macArray[42] ^
+	    macArray[40] ^ macArray[37] ^ macArray[36] ^ macArray[32] ^
+	    macArray[31] ^ macArray[28] ^ macArray[27] ^ macArray[25] ^
+	    macArray[20] ^ macArray[18] ^ macArray[16] ^ macArray[15] ^
+	    macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[5] ^ macArray[4] ^ macArray[3];
+
+	crc[6] = macArray[47] ^ macArray[46] ^ macArray[43] ^ macArray[41] ^
+	    macArray[38] ^ macArray[37] ^ macArray[33] ^ macArray[32] ^
+	    macArray[29] ^ macArray[28] ^ macArray[26] ^ macArray[21] ^
+	    macArray[19] ^ macArray[17] ^ macArray[16] ^ macArray[14] ^
+	    macArray[12] ^ macArray[10] ^ macArray[6] ^ macArray[5] ^ macArray[4];
+
+	crc[7] = macArray[47] ^ macArray[44] ^ macArray[42] ^ macArray[39] ^
+	    macArray[38] ^ macArray[34] ^ macArray[33] ^ macArray[30] ^
+	    macArray[29] ^ macArray[27] ^ macArray[22] ^ macArray[20] ^
+	    macArray[18] ^ macArray[17] ^ macArray[15] ^ macArray[13] ^
+	    macArray[11] ^ macArray[7] ^ macArray[6] ^ macArray[5];
+
+	for (i = 0; i < 8; i++)
+		crcResult = crcResult | (crc[i] << i);
+
+	return crcResult;
+}
+
+/*******************************************************************************
+* mvEthMcastAddrSet - Multicast address settings.
+*
+* DESCRIPTION:
+*       This API controls the MV device MAC multicast support.
+*       The MV device supports multicast using two tables:
+*       1) Special Multicast Table for MAC addresses of the form
+*          0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF).
+*          The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+*          Table entries in the DA-Filter table.
+*          In this case, the function calls ethPortSmcAddr() routine to set the
+*          Special Multicast Table.
+*       2) Other Multicast Table for multicast of another type. A CRC-8bit
+*          is used as an index to the Other Multicast Table entries in the
+*          DA-Filter table.
+*          In this case, the function calculates the CRC-8bit value and calls
+*          ethPortOmcAddr() routine to set the Other Multicast Table.
+*
+* INPUT:
+*       void*   pEthPortHndl    - Ethernet port handler.
+*       MV_U8*  pAddr           - Address to be set
+*       int     queue           - RX queue to capture all packets with this
+*                               Multicast MAC address.
+*                               -1 means delete this Multicast address.
+*
+* RETURN: MV_STATUS
+*       MV_TRUE - Success, Other - Failure
+*
+*******************************************************************************/
+MV_STATUS mvEthMcastAddrSet(void *pPortHndl, MV_U8 * pAddr, int queue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	unsigned char crcResult = 0;
+
+	if (queue >= MV_ETH_RX_Q_NUM) {
+		mvOsPrintf("ethPort %d: RX queue #%d is out of range\n", pPortCtrl->portNo, queue);
+		return MV_BAD_PARAM;
+	}
+
+	if ((pAddr[0] == 0x01) && (pAddr[1] == 0x00) && (pAddr[2] == 0x5E) && (pAddr[3] == 0x00) && (pAddr[4] == 0x00)) {
+		ethSetSpecialMcastAddr(pPortCtrl->portNo, pAddr[5], queue);
+	} else {
+		crcResult = mvEthMcastCrc8Get(pAddr);
+
+		/* Check Add counter for this CRC value */
+		if (queue == -1) {
+			if (pPortCtrl->mcastCount[crcResult] == 0) {
+				mvOsPrintf("ethPort #%d: No valid Mcast for crc8=0x%02x\n",
+					   pPortCtrl->portNo, (unsigned)crcResult);
+				return MV_NO_SUCH;
+			}
+
+			pPortCtrl->mcastCount[crcResult]--;
+			if (pPortCtrl->mcastCount[crcResult] != 0) {
+				mvOsPrintf("ethPort #%d: After delete there are %d valid Mcast for crc8=0x%02x\n",
+					   pPortCtrl->portNo, pPortCtrl->mcastCount[crcResult], (unsigned)crcResult);
+				return MV_NO_CHANGE;
+			}
+		} else {
+			pPortCtrl->mcastCount[crcResult]++;
+			if (pPortCtrl->mcastCount[crcResult] > 1) {
+				mvOsPrintf("ethPort #%d: Valid Mcast for crc8=0x%02x already exists\n",
+					   pPortCtrl->portNo, (unsigned)crcResult);
+				return MV_NO_CHANGE;
+			}
+		}
+		ethSetOtherMcastAddr(pPortCtrl->portNo, crcResult, queue);
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* ethSetUcastTable - Unicast address settings.
+*
+* DESCRIPTION:
+*      Set all entries in the Unicast MAC Table queue==-1 means reject all
+* INPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+static void ethSetUcastTable(int portNo, int queue)
+{
+	int offset;
+	MV_U32 regValue;
+
+	if (queue == -1) {
+		regValue = 0;
+	} else {
+		regValue = (((0x01 | (queue << 1)) << 0) |
+			    ((0x01 | (queue << 1)) << 8) |
+			    ((0x01 | (queue << 1)) << 16) | ((0x01 | (queue << 1)) << 24));
+	}
+
+	for (offset = 0; offset <= 0xC; offset += 4)
+		MV_REG_WRITE((ETH_DA_FILTER_UCAST_BASE(portNo) + offset), regValue);
+}
+
+/*******************************************************************************
+* mvEthSetSpecialMcastTable - Special Multicast address settings.
+*
+* DESCRIPTION:
+*   Set all entries to the Special Multicast MAC Table. queue==-1 means reject all
+* INPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_VOID mvEthSetSpecialMcastTable(int portNo, int queue)
+{
+	int offset;
+	MV_U32 regValue;
+
+	if (queue == -1) {
+		regValue = 0;
+	} else {
+		regValue = (((0x01 | (queue << 1)) << 0) |
+			    ((0x01 | (queue << 1)) << 8) |
+			    ((0x01 | (queue << 1)) << 16) | ((0x01 | (queue << 1)) << 24));
+	}
+
+	for (offset = 0; offset <= 0xFC; offset += 4)
+		MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(portNo) + offset), regValue);
+
+}
+
+/*******************************************************************************
+* mvEthSetOtherMcastTable - Other Multicast address settings.
+*
+* DESCRIPTION:
+*   Set all entries to the Other Multicast MAC Table. queue==-1 means reject all
+* INPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_VOID mvEthSetOtherMcastTable(int portNo, int queue)
+{
+	int offset;
+	MV_U32 regValue;
+
+	if (queue == -1) {
+		regValue = 0;
+	} else {
+		regValue = (((0x01 | (queue << 1)) << 0) |
+			    ((0x01 | (queue << 1)) << 8) |
+			    ((0x01 | (queue << 1)) << 16) | ((0x01 | (queue << 1)) << 24));
+	}
+
+	for (offset = 0; offset <= 0xFC; offset += 4)
+		MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(portNo) + offset), regValue);
+}
+
+/*******************************************************************************
+* ethSetUcastAddr - This function Set the port unicast address table
+*
+* DESCRIPTION:
+*       This function locates the proper entry in the Unicast table for the
+*       specified MAC nibble and sets its properties according to function
+*       parameters.
+*
+* INPUT:
+*       int     ethPortNum  - Port number.
+*       MV_U8   lastNibble  - Unicast MAC Address last nibble.
+*       int     queue       - Rx queue number for this MAC address.
+*                           value "-1" means remove address
+*
+* OUTPUT:
+*       This function add/removes MAC addresses from the port unicast address
+*       table.
+*
+* RETURN:
+*       MV_TRUE is output succeeded.
+*       MV_FALSE if option parameter is invalid.
+*
+*******************************************************************************/
+static MV_BOOL ethSetUcastAddr(int portNo, MV_U8 lastNibble, int queue)
+{
+	unsigned int unicastReg;
+	unsigned int tblOffset;
+	unsigned int regOffset;
+
+	/* Locate the Unicast table entry */
+	lastNibble = (0xf & lastNibble);
+	tblOffset = (lastNibble / 4) * 4;	/* Register offset from unicast table base */
+	regOffset = lastNibble % 4;	/* Entry offset within the above register */
+
+	unicastReg = MV_REG_READ((ETH_DA_FILTER_UCAST_BASE(portNo) + tblOffset));
+
+	if (queue == -1) {
+		/* Clear accepts frame bit at specified unicast DA table entry */
+		unicastReg &= ~(0xFF << (8 * regOffset));
+	} else {
+		unicastReg &= ~(0xFF << (8 * regOffset));
+		unicastReg |= ((0x01 | (queue << 1)) << (8 * regOffset));
+	}
+	MV_REG_WRITE((ETH_DA_FILTER_UCAST_BASE(portNo) + tblOffset), unicastReg);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* ethSetSpecialMcastAddr - Special Multicast address settings.
+*
+* DESCRIPTION:
+*       This routine controls the MV device special MAC multicast support.
+*       The Special Multicast Table for MAC addresses supports MAC of the form
+*       0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF).
+*       The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+*       Table entries in the DA-Filter table.
+*       This function set the Special Multicast Table appropriate entry
+*       according to the argument given.
+*
+* INPUT:
+*       int     ethPortNum      Port number.
+*       unsigned char   mcByte      Multicast addr last byte (MAC DA[7:0] bits).
+*       int          queue      Rx queue number for this MAC address.
+*       int             option      0 = Add, 1 = remove address.
+*
+* OUTPUT:
+*       See description.
+*
+* RETURN:
+*       MV_TRUE is output succeeded.
+*       MV_FALSE if option parameter is invalid.
+*
+*******************************************************************************/
+static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue)
+{
+	unsigned int smcTableReg;
+	unsigned int tblOffset;
+	unsigned int regOffset;
+
+	/* Locate the SMC table entry */
+	tblOffset = (lastByte / 4);	/* Register offset from SMC table base    */
+	regOffset = lastByte % 4;	/* Entry offset within the above register */
+
+	smcTableReg = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum) + tblOffset * 4));
+
+	if (queue == -1) {
+		/* Clear accepts frame bit at specified Special DA table entry */
+		smcTableReg &= ~(0xFF << (8 * regOffset));
+	} else {
+		smcTableReg &= ~(0xFF << (8 * regOffset));
+		smcTableReg |= ((0x01 | (queue << 1)) << (8 * regOffset));
+	}
+	MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum) + tblOffset * 4), smcTableReg);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* ethSetOtherMcastAddr - Multicast address settings.
+*
+* DESCRIPTION:
+*       This routine controls the MV device Other MAC multicast support.
+*       The Other Multicast Table is used for multicast of another type.
+*       A CRC-8bit is used as an index to the Other Multicast Table entries
+*       in the DA-Filter table.
+*       The function gets the CRC-8bit value from the calling routine and
+*       set the Other Multicast Table appropriate entry according to the
+*       CRC-8 argument given.
+*
+* INPUT:
+*       int     ethPortNum  Port number.
+*       MV_U8   crc8        A CRC-8bit (Polynomial: x^8+x^2+x^1+1).
+*       int     queue       Rx queue number for this MAC address.
+*
+* OUTPUT:
+*       See description.
+*
+* RETURN:
+*       MV_TRUE is output succeeded.
+*       MV_FALSE if option parameter is invalid.
+*
+*******************************************************************************/
+static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue)
+{
+	unsigned int omcTableReg;
+	unsigned int tblOffset;
+	unsigned int regOffset;
+
+	/* Locate the OMC table entry */
+	tblOffset = (crc8 / 4) * 4;	/* Register offset from OMC table base    */
+	regOffset = crc8 % 4;	/* Entry offset within the above register */
+
+	omcTableReg = MV_REG_READ((ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum) + tblOffset));
+
+	if (queue == -1) {
+		/* Clear accepts frame bit at specified Other DA table entry */
+		omcTableReg &= ~(0xFF << (8 * regOffset));
+	} else {
+		omcTableReg &= ~(0xFF << (8 * regOffset));
+		omcTableReg |= ((0x01 | (queue << 1)) << (8 * regOffset));
+	}
+
+	MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum) + tblOffset), omcTableReg);
+
+	return MV_TRUE;
+}
+
+/******************************************************************************/
+/*                      MIB Counters functions                                */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvEthMibCounterRead - Read a MIB counter
+*
+* DESCRIPTION:
+*       This function reads a MIB counter of a specific ethernet port.
+*       NOTE - Read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW or
+*              ETH_MIB_GOOD_OCTETS_SENT_LOW counters will return 64 bits value,
+*              so pHigh32 pointer should not be NULL in this case.
+*
+* INPUT:
+*       int           ethPortNum  - Ethernet Port number.
+*       unsigned int  mibOffset   - MIB counter offset.
+*
+* OUTPUT:
+*       MV_U32*       pHigh32 - pointer to place where 32 most significant bits
+*                             of the counter will be stored.
+*
+* RETURN:
+*       32 low sgnificant bits of MIB counter value.
+*
+*******************************************************************************/
+MV_U32 mvEthMibCounterRead(void *pPortHandle, unsigned int mibOffset, MV_U32 * pHigh32)
+{
+	int portNo;
+	MV_U32 valLow32, valHigh32;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+
+	portNo = pPortCtrl->portNo;
+
+	valLow32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo) + mibOffset);
+
+	/* Implement FEr ETH. Erroneous Value when Reading the Upper 32-bits    */
+	/* of a 64-bit MIB Counter.                                             */
+	if ((mibOffset == ETH_MIB_GOOD_OCTETS_RECEIVED_LOW) || (mibOffset == ETH_MIB_GOOD_OCTETS_SENT_LOW)) {
+		valHigh32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo) + mibOffset + 4);
+		if (pHigh32 != NULL)
+			*pHigh32 = valHigh32;
+	}
+	return valLow32;
+}
+
+/*******************************************************************************
+* mvEthMibCountersClear - Clear all MIB counters
+*
+* DESCRIPTION:
+*       This function clears all MIB counters
+*
+* INPUT:
+*       int           ethPortNum  - Ethernet Port number.
+*
+*
+* RETURN:   void
+*
+*******************************************************************************/
+void mvEthMibCountersClear(void *pPortHandle)
+{
+	int i, portNo;
+	unsigned int dummy;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+
+	portNo = pPortCtrl->portNo;
+
+	/* Perform dummy reads from MIB counters */
+	for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; i += 4)
+		dummy = MV_REG_READ((ETH_MIB_COUNTERS_BASE(portNo) + i));
+}
+
+/******************************************************************************/
+/*                        RX Dispatching configuration routines               */
+/******************************************************************************/
+
+int mvEthTosToRxqGet(void *pPortHandle, int tos)
+{
+	MV_U32 regValue;
+	int regIdx, regOffs, rxq;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+
+	if (tos > 0xFF) {
+		mvOsPrintf("eth_%d: tos=0x%x is out of range\n", pPortCtrl->portNo, tos);
+		return -1;
+	}
+	regIdx = mvOsDivide(tos >> 2, 10);
+	regOffs = mvOsReminder(tos >> 2, 10);
+
+	regValue = MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx));
+	rxq = (regValue >> (regOffs * 3));
+	rxq &= 0x7;
+
+	return rxq;
+}
+
+/*******************************************************************************
+* mvEthTosToRxqSet - Map packets with special TOS value to special RX queue
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       void*   pPortHandle - Pointer to port specific handler;
+*       int     tos         - TOS value in the IP header of the packet
+*       int     rxq         - RX Queue for packets with the configured TOS value
+*                           Negative value (-1) means no special processing for these packets,
+*                           so they will be processed as regular packets.
+*
+* RETURN:   MV_STATUS
+*******************************************************************************/
+MV_STATUS mvEthTosToRxqSet(void *pPortHandle, int tos, int rxq)
+{
+	MV_U32 regValue;
+	int regIdx, regOffs;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+
+	if ((rxq < 0) || (rxq >= MV_ETH_RX_Q_NUM)) {
+		mvOsPrintf("eth_%d: RX queue #%d is out of range\n", pPortCtrl->portNo, rxq);
+		return MV_BAD_PARAM;
+	}
+	if (tos > 0xFF) {
+		mvOsPrintf("eth_%d: tos=0x%x is out of range\n", pPortCtrl->portNo, tos);
+		return MV_BAD_PARAM;
+	}
+	regIdx = mvOsDivide(tos >> 2, 10);
+	regOffs = mvOsReminder(tos >> 2, 10);
+
+	regValue = MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx));
+	regValue &= ~(0x7 << (regOffs * 3));
+	regValue |= (rxq << (regOffs * 3));
+
+	MV_REG_WRITE(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx), regValue);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthVlanPrioRxQueue - Configure RX queue to capture VLAN tagged packets with
+*                        special priority bits [0-2]
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       void*   pPortHandle - Pointer to port specific handler;
+*       int     bpduQueue   - Special queue to capture VLAN tagged packets with special
+*                           priority.
+*                           Negative value (-1) means no special processing for these packets,
+*                           so they will be processed as regular packets.
+*
+* RETURN:   MV_STATUS
+*       MV_OK       - Success
+*       MV_FAIL     - Failed.
+*
+*******************************************************************************/
+MV_STATUS mvEthVlanPrioRxQueue(void *pPortHandle, int vlanPrio, int vlanPrioQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	MV_U32 vlanPrioReg;
+
+	if (vlanPrioQueue >= MV_ETH_RX_Q_NUM) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", vlanPrioQueue);
+		return MV_BAD_PARAM;
+	}
+	if (vlanPrio >= 8) {
+		mvOsPrintf("ethDrv: vlanPrio=%d is out of range\n", vlanPrio);
+		return MV_BAD_PARAM;
+	}
+
+	vlanPrioReg = MV_REG_READ(ETH_VLAN_TAG_TO_PRIO_REG(pPortCtrl->portNo));
+	vlanPrioReg &= ~(0x7 << (vlanPrio * 3));
+	vlanPrioReg |= (vlanPrioQueue << (vlanPrio * 3));
+	MV_REG_WRITE(ETH_VLAN_TAG_TO_PRIO_REG(pPortCtrl->portNo), vlanPrioReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthBpduRxQueue - Configure RX queue to capture BPDU packets.
+*
+* DESCRIPTION:
+*       This function defines processing of BPDU packets.
+*   BPDU packets can be accepted and captured to one of RX queues
+*   or can be processing as regular Multicast packets.
+*
+* INPUT:
+*       void*   pPortHandle - Pointer to port specific handler;
+*       int     bpduQueue   - Special queue to capture BPDU packets (DA is equal to
+*                           01-80-C2-00-00-00 through 01-80-C2-00-00-FF,
+*                           except for the Flow-Control Pause packets).
+*                           Negative value (-1) means no special processing for BPDU,
+*                           packets so they will be processed as regular Multicast packets.
+*
+* RETURN:   MV_STATUS
+*       MV_OK       - Success
+*       MV_FAIL     - Failed.
+*
+*******************************************************************************/
+MV_STATUS mvEthBpduRxQueue(void *pPortHandle, int bpduQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	MV_U32 portCfgReg;
+	MV_U32 portCfgExtReg;
+
+	if (bpduQueue >= MV_ETH_RX_Q_NUM) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", bpduQueue);
+		return MV_BAD_PARAM;
+	}
+
+	portCfgExtReg = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl->portNo));
+
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
+	if (bpduQueue >= 0) {
+		pPortCtrl->portConfig.rxBpduQ = bpduQueue;
+
+		portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK;
+		portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl->portConfig.rxBpduQ);
+
+		MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
+
+		portCfgExtReg |= ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK;
+	} else {
+		pPortCtrl->portConfig.rxBpduQ = -1;
+		/* no special processing for BPDU packets */
+		portCfgExtReg &= (~ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK);
+	}
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl->portNo), portCfgExtReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthArpRxQueue - Configure RX queue to capture ARP packets.
+*
+* DESCRIPTION:
+*       This function defines processing of ARP (type=0x0806) packets.
+*   ARP packets can be accepted and captured to one of RX queues
+*   or can be processed as other Broadcast packets.
+*
+* INPUT:
+*       void*   pPortHandle - Pointer to port specific handler;
+*       int     arpQueue    - Special queue to capture ARP packets (type=0x806).
+*                           Negative value (-1) means discard ARP packets
+*
+* RETURN:   MV_STATUS
+*       MV_OK       - Success
+*       MV_FAIL     - Failed.
+*
+*******************************************************************************/
+MV_STATUS mvEthArpRxQueue(void *pPortHandle, int arpQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	MV_U32 portCfgReg;
+
+	if (arpQueue >= MV_ETH_RX_Q_NUM) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", arpQueue);
+		return MV_BAD_PARAM;
+	}
+
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
+
+	if (arpQueue >= 0) {
+		pPortCtrl->portConfig.rxArpQ = arpQueue;
+		portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK;
+		portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl->portConfig.rxArpQ);
+
+		portCfgReg &= (~ETH_REJECT_ARP_BCAST_MASK);
+	} else {
+		pPortCtrl->portConfig.rxArpQ = -1;
+		portCfgReg |= ETH_REJECT_ARP_BCAST_MASK;
+	}
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthTcpRxQueue - Configure RX queue to capture TCP packets.
+*
+* DESCRIPTION:
+*       This function defines processing of TCP packets.
+*   TCP packets can be accepted and captured to one of RX queues
+*   or can be processed as regular Unicast packets.
+*
+* INPUT:
+*       void*   pPortHandle - Pointer to port specific handler;
+*       int     tcpQueue    - Special queue to capture TCP packets. Value "-1"
+*                           means no special processing for TCP packets,
+*                           so they will be processed as regular
+*
+* RETURN:   MV_STATUS
+*       MV_OK       - Success
+*       MV_FAIL     - Failed.
+*
+*******************************************************************************/
+MV_STATUS mvEthTcpRxQueue(void *pPortHandle, int tcpQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	MV_U32 portCfgReg;
+
+	if (tcpQueue >= MV_ETH_RX_Q_NUM) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", tcpQueue);
+		return MV_BAD_PARAM;
+	}
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
+
+	if (tcpQueue >= 0) {
+		pPortCtrl->portConfig.rxTcpQ = tcpQueue;
+		portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK;
+		portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl->portConfig.rxTcpQ);
+
+		portCfgReg |= ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK;
+	} else {
+		pPortCtrl->portConfig.rxTcpQ = -1;
+		portCfgReg &= (~ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK);
+	}
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthUdpRxQueue - Configure RX queue to capture UDP packets.
+*
+* DESCRIPTION:
+*       This function defines processing of UDP packets.
+*   TCP packets can be accepted and captured to one of RX queues
+*   or can be processed as regular Unicast packets.
+*
+* INPUT:
+*       void*   pPortHandle - Pointer to port specific handler;
+*       int     udpQueue    - Special queue to capture UDP packets. Value "-1"
+*                           means no special processing for UDP packets,
+*                           so they will be processed as regular
+*
+* RETURN:   MV_STATUS
+*       MV_OK       - Success
+*       MV_FAIL     - Failed.
+*
+*******************************************************************************/
+MV_STATUS mvEthUdpRxQueue(void *pPortHandle, int udpQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	MV_U32 portCfgReg;
+
+	if (udpQueue >= MV_ETH_RX_Q_NUM) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", udpQueue);
+		return MV_BAD_PARAM;
+	}
+
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo));
+
+	if (udpQueue >= 0) {
+		pPortCtrl->portConfig.rxUdpQ = udpQueue;
+		portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK;
+		portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl->portConfig.rxUdpQ);
+
+		portCfgReg |= ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK;
+	} else {
+		pPortCtrl->portConfig.rxUdpQ = -1;
+		portCfgReg &= ~ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK;
+	}
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg);
+
+	return MV_OK;
+}
+
+/******************************************************************************/
+/*                          Speed, Duplex, FlowControl routines               */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvEthSpeedDuplexSet - Set Speed and Duplex of the port.
+*
+* DESCRIPTION:
+*       This function configure the port to work with desirable Duplex and Speed.
+*       Changing of these parameters are allowed only when port is disabled.
+*       This function disable the port if was enabled, change duplex and speed
+*       and, enable the port back if needed.
+*
+* INPUT:
+*       void*           pPortHandle - Pointer to port specific handler;
+*       ETH_PORT_SPEED  speed       - Speed of the port.
+*       ETH_PORT_SPEED  duplex      - Duplex of the port.
+*
+* RETURN:   MV_STATUS
+*       MV_OK           - Success
+*       MV_OUT_OF_RANGE - Failed. Port is out of valid range
+*       MV_NOT_FOUND    - Failed. Port is not initialized.
+*       MV_BAD_PARAM    - Input parameters (speed/duplex) in conflict.
+*       MV_BAD_VALUE    - Value of one of input parameters (speed, duplex)
+*                       is not valid
+*
+*******************************************************************************/
+MV_STATUS mvEthSpeedDuplexSet(void *pPortHandle, MV_ETH_PORT_SPEED speed, MV_ETH_PORT_DUPLEX duplex)
+{
+	/* FIXME */
+	mvOsPrintf("WARNING: %s for GMAC temporary not supported\n", __func__);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthFlowCtrlSet - Set Flow Control of the port.
+*
+* DESCRIPTION:
+*       This function configure the port to work with desirable Duplex and
+*       Speed. Changing of these parameters are allowed only when port is
+*       disabled. This function disable the port if was enabled, change
+*       duplex and speed and, enable the port back if needed.
+*
+* INPUT:
+*       void*           pPortHandle - Pointer to port specific handler;
+*       MV_ETH_PORT_FC  flowControl - Flow control of the port.
+*
+* RETURN:   MV_STATUS
+*       MV_OK           - Success
+*       MV_OUT_OF_RANGE - Failed. Port is out of valid range
+*       MV_NOT_FOUND    - Failed. Port is not initialized.
+*       MV_BAD_VALUE    - Value flowControl parameters is not valid
+*
+*******************************************************************************/
+MV_STATUS mvEthFlowCtrlSet(void *pPortHandle, MV_ETH_PORT_FC flowControl)
+{
+	/* FIXME */
+	mvOsPrintf("WARNING: %s for GMAC temporary not supported\n", __func__);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthHeaderModeSet - Set port header mode.
+*
+* DESCRIPTION:
+*       This function configures the port to work in Marvell-Header mode.
+*
+* INPUT:
+*       void*           pPortHandle - Pointer to port specific handler;
+*       MV_ETH_HEADER_MODE headerMode - The header mode to set the port in.
+*
+* RETURN:   MV_STATUS
+*       MV_OK           - Success
+*       MV_NOT_SUPPORTED- Feature not supported.
+*       MV_OUT_OF_RANGE - Failed. Port is out of valid range
+*       MV_NOT_FOUND    - Failed. Port is not initialized.
+*       MV_BAD_VALUE    - Value of headerMode or numRxQueue parameter is not valid.
+*
+*******************************************************************************/
+MV_STATUS mvEthHeaderModeSet(void *pPortHandle, MV_ETH_HEADER_MODE headerMode)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	int port = pPortCtrl->portNo;
+	MV_U32 mvHeaderReg;
+	MV_U32 numRxQ = MV_ETH_RX_Q_NUM;
+
+	if ((port < 0) || (port >= ethHalData.maxPortNum))
+		return MV_OUT_OF_RANGE;
+
+	pPortCtrl = ethPortCtrl[port];
+	if (pPortCtrl == NULL)
+		return MV_NOT_FOUND;
+
+	mvHeaderReg = MV_REG_READ(ETH_PORT_MARVELL_HEADER_REG(port));
+	/* Disable header mode.             */
+	mvHeaderReg &= ~ETH_MVHDR_EN_MASK;
+
+	if (headerMode != MV_ETH_DISABLE_HEADER_MODE) {
+		/* Enable Header mode.              */
+		mvHeaderReg |= ETH_MVHDR_EN_MASK;
+
+		/* Clear DA-Prefix  & MHMask fields. */
+		mvHeaderReg &= ~(ETH_MVHDR_DAPREFIX_MASK | ETH_MVHDR_MHMASK_MASK);
+
+		if (numRxQ > 1) {
+			switch (headerMode) {
+			case (MV_ETH_ENABLE_HEADER_MODE_PRI_2_1):
+				mvHeaderReg |= ETH_MVHDR_DAPREFIX_PRI_1_2;
+				break;
+			case (MV_ETH_ENABLE_HEADER_MODE_PRI_DBNUM):
+				mvHeaderReg |= ETH_MVHDR_DAPREFIX_DBNUM_PRI;
+				break;
+			case (MV_ETH_ENABLE_HEADER_MODE_PRI_SPID):
+				mvHeaderReg |= ETH_MVHDR_DAPREFIX_SPID_PRI;
+				break;
+			default:
+				break;
+			}
+
+			switch (numRxQ) {
+			case (4):
+				mvHeaderReg |= ETH_MVHDR_MHMASK_4_QUEUE;
+				break;
+			case (8):
+				mvHeaderReg |= ETH_MVHDR_MHMASK_8_QUEUE;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	MV_REG_WRITE(ETH_PORT_MARVELL_HEADER_REG(port), mvHeaderReg);
+
+	return MV_OK;
+}
+
+#if (MV_ETH_VERSION >= 4)
+/*******************************************************************************
+* mvEthEjpModeSet - Enable / Disable EJP policy for TX.
+*
+* DESCRIPTION:
+*       This function
+*
+* INPUT:
+*       void*           pPortHandle - Pointer to port specific handler;
+*       MV_BOOL         TRUE - enable EJP mode
+*                       FALSE - disable EJP mode
+*
+* OUTPUT:   MV_STATUS
+*       MV_OK           - Success
+*       Other           - Failure
+*
+* RETURN:   None.
+*
+*******************************************************************************/
+MV_STATUS mvEthEjpModeSet(void *pPortHandle, int mode)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	int port = pPortCtrl->portNo;
+
+	if ((port < 0) || (port >= ethHalData.maxPortNum))
+		return MV_OUT_OF_RANGE;
+
+	pPortCtrl = ethPortCtrl[port];
+	if (pPortCtrl == NULL)
+		return MV_NOT_FOUND;
+
+	pPortCtrl->portConfig.ejpMode = mode;
+	if (mode) {
+		/* EJP enabled */
+		MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port), ETH_TX_EJP_ENABLE_MASK);
+	} else {
+		/* EJP disabled */
+		MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port), 0);
+	}
+	mvOsPrintf("eth_%d: EJP %s - ETH_TXQ_CMD_1_REG: 0x%x = 0x%08x\n",
+		   port, mode ? "Enabled" : "Disabled", ETH_TXQ_CMD_1_REG(port), MV_REG_READ(ETH_TXQ_CMD_1_REG(port)));
+
+	return MV_OK;
+}
+#endif /* MV_ETH_VERSION >= 4 */
+
+/*******************************************************************************
+* mvEthStatusGet - Get major properties of the port .
+*
+* DESCRIPTION:
+*       This function get major properties of the port (link, speed, duplex,
+*       flowControl, etc) and return them using the single structure.
+*
+* INPUT:
+*       void*           pPortHandle - Pointer to port specific handler;
+*
+* OUTPUT:
+*       MV_ETH_PORT_STATUS* pStatus - Pointer to structure, were port status
+*                                   will be placed.
+*
+* RETURN:   None.
+*
+*******************************************************************************/
+void mvEthStatusGet(void *pPortHandle, MV_ETH_PORT_STATUS * pStatus)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	int port = pPortCtrl->portNo;
+	MV_U32 		regVal;
+
+	regVal = MV_REG_READ(NETA_GMAC_STATUS_REG(port));
+
+	if (regVal & NETA_GMAC_SPEED_1000_MASK)
+		pStatus->speed = MV_ETH_SPEED_1000;
+	else if (regVal & NETA_GMAC_SPEED_100_MASK)
+		pStatus->speed = MV_ETH_SPEED_100;
+	else
+		pStatus->speed = MV_ETH_SPEED_10;
+
+	if (regVal & NETA_GMAC_LINK_UP_MASK)
+		pStatus->isLinkUp = MV_TRUE;
+	else
+		pStatus->isLinkUp = MV_FALSE;
+
+	if (regVal & NETA_GMAC_FULL_DUPLEX_MASK)
+		pStatus->duplex = MV_ETH_DUPLEX_FULL;
+	else
+		pStatus->duplex = MV_ETH_DUPLEX_HALF;
+
+	/* FIXME */
+	pStatus->flowControl = MV_ETH_FC_DISABLE;
+}
+
+/******************************************************************************/
+/*                         PHY Control Functions                              */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvEthPhyAddrSet - Set the ethernet port PHY address.
+*
+* DESCRIPTION:
+*       This routine set the ethernet port PHY address according to given
+*       parameter.
+*
+* INPUT:
+*       void*   pPortHandle     - Pointer to port specific handler;
+*       int     phyAddr         - PHY address
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+void mvEthPhyAddrSet(void *pPortHandle, int phyAddr)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	int port = pPortCtrl->portNo;
+	unsigned int regData;
+
+	regData = MV_REG_READ(ETH_PHY_ADDR_REG(port));
+
+	regData &= ~ETH_PHY_ADDR_MASK;
+	regData |= phyAddr;
+
+	MV_REG_WRITE(ETH_PHY_ADDR_REG(port), regData);
+
+	return;
+}
+
+/*******************************************************************************
+* mvEthPhyAddrGet - Get the ethernet port PHY address.
+*
+* DESCRIPTION:
+*       This routine returns the given ethernet port PHY address.
+*
+* INPUT:
+*       void*   pPortHandle - Pointer to port specific handler;
+*
+*
+* RETURN: int - PHY address.
+*
+*******************************************************************************/
+int mvEthPhyAddrGet(void *pPortHandle)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHandle;
+	int port = pPortCtrl->portNo;
+	unsigned int regData;
+
+	regData = MV_REG_READ(ETH_PHY_ADDR_REG(port));
+
+	return ((regData >> (5 * port)) & 0x1f);
+}
+
+/******************************************************************************/
+/*                Descriptor handling Functions                               */
+/******************************************************************************/
+
+/*******************************************************************************
+* etherInitRxDescRing - Curve a Rx chain desc list and buffer in memory.
+*
+* DESCRIPTION:
+*       This function prepares a Rx chained list of descriptors and packet
+*       buffers in a form of a ring. The routine must be called after port
+*       initialization routine and before port start routine.
+*       The Ethernet SDMA engine uses CPU bus addresses to access the various
+*       devices in the system (i.e. DRAM). This function uses the ethernet
+*       struct 'virtual to physical' routine (set by the user) to set the ring
+*       with physical addresses.
+*
+* INPUT:
+*       ETH_QUEUE_CTRL  *pEthPortCtrl   Ethernet Port Control srtuct.
+*       int             rxQueue         Number of Rx queue.
+*       int             rxDescNum       Number of Rx descriptors
+*       MV_U8*          rxDescBaseAddr  Rx descriptors memory area base addr.
+*
+* OUTPUT:
+*       The routine updates the Ethernet port control struct with information
+*       regarding the Rx descriptors and buffers.
+*
+* RETURN: None
+*
+*******************************************************************************/
+static void ethInitRxDescRing(ETH_PORT_CTRL *pPortCtrl, int queue)
+{
+	ETH_RX_DESC *pRxDescBase, *pRxDesc, *pRxPrevDesc;
+	int ix, rxDescNum = pPortCtrl->rxQueueConfig[queue].descrNum;
+	ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->rxQueue[queue];
+
+	/* Make sure descriptor address is cache line size aligned  */
+	pRxDescBase = (ETH_RX_DESC *) MV_ALIGN_UP((MV_ULONG) pQueueCtrl->descBuf.bufVirtPtr, CPU_D_CACHE_LINE_SIZE);
+
+	pRxDesc = (ETH_RX_DESC *) pRxDescBase;
+	pRxPrevDesc = pRxDesc;
+
+	/* initialize the Rx descriptors ring */
+	for (ix = 0; ix < rxDescNum; ix++) {
+		ETH_SET_16B_DESCR_VAL(pRxDesc->bufSize, 0x0);
+		ETH_SET_16B_DESCR_VAL(pRxDesc->byteCnt, 0x0);
+		ETH_SET_32B_DESCR_VAL(pRxDesc->cmdSts, ETH_BUFFER_OWNED_BY_HOST);
+		ETH_SET_32B_DESCR_VAL(pRxDesc->bufPtr, 0x0);
+		ETH_SET_32B_DESCR_VAL(pRxDesc->returnInfo, 0x0);
+		pRxPrevDesc = pRxDesc;
+		if (ix == (rxDescNum - 1)) {
+			/* Closing Rx descriptors ring */
+			ETH_SET_32B_DESCR_VAL(pRxPrevDesc->nextDescPtr,
+					      (MV_U32) ethDescVirtToPhy(pQueueCtrl, (void *)pRxDescBase));
+		} else {
+			pRxDesc = (ETH_RX_DESC *) ((MV_ULONG) pRxDesc + ETH_RX_DESC_ALIGNED_SIZE);
+			ETH_SET_32B_DESCR_VAL(pRxPrevDesc->nextDescPtr,
+					      (MV_U32) ethDescVirtToPhy(pQueueCtrl, (void *)pRxDesc));
+		}
+		ETH_DESCR_FLUSH_INV(pPortCtrl, pRxPrevDesc);
+	}
+
+	pQueueCtrl->pCurrentDescr = pRxDescBase;
+	pQueueCtrl->pUsedDescr = pRxDescBase;
+
+	pQueueCtrl->pFirstDescr = pRxDescBase;
+	pQueueCtrl->pLastDescr = pRxDesc;
+	pQueueCtrl->resource = 0;
+}
+
+void ethResetRxDescRing(void *pPortHndl, int queue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->rxQueue[queue];
+	ETH_RX_DESC *pRxDesc = (ETH_RX_DESC *) pQueueCtrl->pFirstDescr;
+
+	pQueueCtrl->resource = 0;
+	if (pQueueCtrl->pFirstDescr != NULL) {
+		while (MV_TRUE) {
+			ETH_SET_16B_DESCR_VAL(pRxDesc->bufSize, 0x0);
+			ETH_SET_16B_DESCR_VAL(pRxDesc->byteCnt, 0x0);
+			ETH_SET_32B_DESCR_VAL(pRxDesc->cmdSts, ETH_BUFFER_OWNED_BY_HOST);
+			ETH_SET_32B_DESCR_VAL(pRxDesc->bufPtr, 0x0);
+			ETH_SET_32B_DESCR_VAL(pRxDesc->returnInfo, 0x0);
+			ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc);
+			if ((void *)pRxDesc == pQueueCtrl->pLastDescr)
+				break;
+			pRxDesc = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl);
+		}
+		pQueueCtrl->pCurrentDescr = pQueueCtrl->pFirstDescr;
+		pQueueCtrl->pUsedDescr = pQueueCtrl->pFirstDescr;
+
+		/* Update RX Command register */
+		pPortCtrl->portRxQueueCmdReg |= (1 << queue);
+
+		/* update HW */
+		MV_REG_WRITE(ETH_RX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue),
+			     (MV_U32) ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr));
+	} else {
+		/* Update RX Command register */
+		pPortCtrl->portRxQueueCmdReg &= ~(1 << queue);
+
+		/* update HW */
+		MV_REG_WRITE(ETH_RX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), 0);
+	}
+}
+
+/*******************************************************************************
+* etherInitTxDescRing - Curve a Tx chain desc list and buffer in memory.
+*
+* DESCRIPTION:
+*       This function prepares a Tx chained list of descriptors and packet
+*       buffers in a form of a ring. The routine must be called after port
+*       initialization routine and before port start routine.
+*       The Ethernet SDMA engine uses CPU bus addresses to access the various
+*       devices in the system (i.e. DRAM). This function uses the ethernet
+*       struct 'virtual to physical' routine (set by the user) to set the ring
+*       with physical addresses.
+*
+* INPUT:
+*       ETH_PORT_CTRL   *pEthPortCtrl   Ethernet Port Control srtuct.
+*       int             txQueue         Number of Tx queue.
+*       int             txDescNum       Number of Tx descriptors
+*       int             txBuffSize      Size of Tx buffer
+*       MV_U8*          pTxDescBase     Tx descriptors memory area base addr.
+*
+* OUTPUT:
+*       The routine updates the Ethernet port control struct with information
+*       regarding the Tx descriptors and buffers.
+*
+* RETURN:   None.
+*
+*******************************************************************************/
+static void ethInitTxDescRing(ETH_PORT_CTRL *pPortCtrl, int queue)
+{
+	ETH_TX_DESC *pTxDescBase, *pTxDesc, *pTxPrevDesc;
+	int ix, txDescNum = pPortCtrl->txQueueConfig[queue].descrNum;
+	ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->txQueue[queue];
+
+	/* Make sure descriptor address is cache line size aligned  */
+	pTxDescBase = (ETH_TX_DESC *) MV_ALIGN_UP((MV_ULONG) pQueueCtrl->descBuf.bufVirtPtr, CPU_D_CACHE_LINE_SIZE);
+
+	pTxDesc = (ETH_TX_DESC *) pTxDescBase;
+	pTxPrevDesc = pTxDesc;
+
+	/* initialize the Tx descriptors ring */
+	for (ix = 0; ix < txDescNum; ix++) {
+		ETH_SET_16B_DESCR_VAL(pTxDesc->byteCnt, 0x0000);
+		ETH_SET_16B_DESCR_VAL(pTxDesc->L4iChk, 0x0000);
+		ETH_SET_32B_DESCR_VAL(pTxDesc->cmdSts, ETH_BUFFER_OWNED_BY_HOST);
+		ETH_SET_32B_DESCR_VAL(pTxDesc->bufPtr, 0x0);
+		ETH_SET_32B_DESCR_VAL(pTxDesc->returnInfo, 0x0);
+
+		pTxPrevDesc = pTxDesc;
+
+		if (ix == (txDescNum - 1)) {
+#ifdef MV_LEGACY_ETH_WA
+			/* Closing Tx descriptors ring */
+			ETH_SET_32B_DESCR_VAL(pTxPrevDesc->nextDescPtr, 0x0);
+#else
+			ETH_SET_32B_DESCR_VAL(pTxPrevDesc->nextDescPtr,
+					      (MV_U32) ethDescVirtToPhy(pQueueCtrl, (void *)pTxDescBase));
+#endif
+		} else {
+			pTxDesc = (ETH_TX_DESC *) ((MV_ULONG) pTxDesc + ETH_TX_DESC_ALIGNED_SIZE);
+#ifdef MV_LEGACY_ETH_WA
+			ETH_SET_32B_DESCR_VAL(pTxPrevDesc->nextDescPtr, 0x0);
+#else
+			ETH_SET_32B_DESCR_VAL(pTxPrevDesc->nextDescPtr,
+				(MV_U32) ethDescVirtToPhy(pQueueCtrl,
+					(void *)pTxDesc));
+#endif
+		}
+		ETH_DESCR_FLUSH_INV(pPortCtrl, pTxPrevDesc);
+	}
+
+	pQueueCtrl->pCurrentDescr = pTxDescBase;
+	pQueueCtrl->pUsedDescr = pTxDescBase;
+
+	pQueueCtrl->pFirstDescr = pTxDescBase;
+	pQueueCtrl->pLastDescr = pTxDesc;
+	/* Leave one TX descriptor out of use */
+	pQueueCtrl->resource = txDescNum - 1;
+}
+
+void ethResetTxDescRing(void *pPortHndl, int queue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->txQueue[queue];
+	ETH_TX_DESC *pTxDesc = (ETH_TX_DESC *) pQueueCtrl->pFirstDescr;
+
+	pQueueCtrl->resource = 0;
+	if (pQueueCtrl->pFirstDescr != NULL) {
+		while (MV_TRUE) {
+			ETH_SET_16B_DESCR_VAL(pTxDesc->byteCnt, 0x0000);
+			ETH_SET_16B_DESCR_VAL(pTxDesc->L4iChk, 0x0000);
+			ETH_SET_32B_DESCR_VAL(pTxDesc->cmdSts, ETH_BUFFER_OWNED_BY_HOST);
+			ETH_SET_32B_DESCR_VAL(pTxDesc->bufPtr, 0x0);
+			ETH_SET_32B_DESCR_VAL(pTxDesc->returnInfo, 0x0);
+			ETH_DESCR_FLUSH_INV(pPortCtrl, pTxDesc);
+			pQueueCtrl->resource++;
+			if ((void *)pTxDesc == pQueueCtrl->pLastDescr)
+				break;
+			pTxDesc = TX_NEXT_DESC_PTR(pTxDesc, pQueueCtrl);
+		}
+		/* Leave one TX descriptor out of use */
+		pQueueCtrl->resource--;
+		pQueueCtrl->pCurrentDescr = pQueueCtrl->pFirstDescr;
+		pQueueCtrl->pUsedDescr = pQueueCtrl->pFirstDescr;
+		/* Update TX Command register */
+		pPortCtrl->portTxQueueCmdReg |= MV_32BIT_LE_FAST(1 << queue);
+		/* update HW */
+		MV_REG_WRITE(ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue),
+				(MV_U32) ethDescVirtToPhy(pQueueCtrl,
+					pQueueCtrl->pCurrentDescr));
+	} else {
+		/* Update TX Command register */
+		pPortCtrl->portTxQueueCmdReg &= MV_32BIT_LE_FAST(~(1 << queue));
+		/* update HW */
+		MV_REG_WRITE(ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), 0);
+	}
+}
+
+/*******************************************************************************
+* ethAllocDescrMemory - Free memory allocated for RX and TX descriptors.
+*
+* DESCRIPTION:
+*       This function allocates memory for RX and TX descriptors.
+*       - If ETH_DESCR_IN_SRAM defined, allocate memory from SRAM.
+*       - If ETH_DESCR_IN_SDRAM defined, allocate memory in SDRAM.
+*
+* INPUT:
+*       int size - size of memory should be allocated.
+*
+* RETURN: None
+*
+*******************************************************************************/
+static MV_U8 *ethAllocDescrMemory(ETH_PORT_CTRL * pPortCtrl, int descSize, MV_ULONG * pPhysAddr, MV_U32 * memHandle)
+{
+	MV_U8 *pVirt;
+#if defined(ETH_DESCR_IN_SRAM)
+	if (ethDescInSram == MV_TRUE)
+		pVirt = (MV_U8 *) mvSramMalloc(descSize, pPhysAddr);
+	else
+#endif /* ETH_DESCR_IN_SRAM */
+	{
+#ifdef ETH_DESCR_UNCACHED
+		pVirt = (MV_U8 *) mvOsIoUncachedMalloc(pPortCtrl->osHandle, descSize, pPhysAddr, memHandle);
+#else
+		pVirt = (MV_U8 *) mvOsIoCachedMalloc(pPortCtrl->osHandle, descSize, pPhysAddr, memHandle);
+#endif /* ETH_DESCR_UNCACHED */
+	}
+	memset(pVirt, 0, descSize);
+
+	return pVirt;
+}
+
+/*******************************************************************************
+* ethFreeDescrMemory - Free memory allocated for RX and TX descriptors.
+*
+* DESCRIPTION:
+*       This function frees memory allocated for RX and TX descriptors.
+*       - If ETH_DESCR_IN_SRAM defined, free memory using gtSramFree() function.
+*       - If ETH_DESCR_IN_SDRAM defined, free memory using mvOsFree() function.
+*
+* INPUT:
+*       void* pVirtAddr - virtual pointer to memory allocated for RX and TX
+*                       desriptors.
+*
+* RETURN: None
+*
+*******************************************************************************/
+void ethFreeDescrMemory(ETH_PORT_CTRL *pPortCtrl, MV_BUF_INFO *pDescBuf)
+{
+	if ((pDescBuf == NULL) || (pDescBuf->bufVirtPtr == NULL))
+		return;
+
+#if defined(ETH_DESCR_IN_SRAM)
+	if (ethDescInSram) {
+		mvSramFree(pDescBuf->bufSize, pDescBuf->bufPhysAddr, pDescBuf->bufVirtPtr);
+		return;
+	}
+#endif /* ETH_DESCR_IN_SRAM */
+
+#ifdef ETH_DESCR_UNCACHED
+	mvOsIoUncachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr,
+			   pDescBuf->bufVirtPtr, pDescBuf->memHandle);
+#else
+	mvOsIoCachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr,
+			 pDescBuf->bufVirtPtr, pDescBuf->memHandle);
+#endif /* ETH_DESCR_UNCACHED */
+}
+
+/******************************************************************************/
+/*                Other Functions                                         */
+/******************************************************************************/
+
+void mvEthPortPowerUp(int port)
+{
+	MV_U32 regVal;
+
+	/* MAC Cause register should be cleared */
+	MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port), 0);
+
+	if (ethHalData.portData[port].isSgmii)
+		mvEthPortSgmiiConfig(port);
+
+	/* Cancel Port Reset */
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_2_REG(port));
+	regVal &= (~NETA_GMAC_PORT_RESET_MASK);
+	MV_REG_WRITE(NETA_GMAC_CTRL_2_REG(port), regVal);
+	while ((MV_REG_READ(NETA_GMAC_CTRL_2_REG(port)) & NETA_GMAC_PORT_RESET_MASK) != 0)
+		continue;
+
+}
+
+void mvEthPortPowerDown(int port)
+{
+	MV_U32 regVal;
+
+	/* Port must be DISABLED */
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_0_REG(port));
+	if ((regVal & NETA_GMAC_PORT_EN_MASK) != 0) {
+		mvOsPrintf("ethPort #%d: PowerDown - port must be Disabled (PSC=0x%x)\n", port, regVal);
+		return;
+	}
+
+	/* Port Reset (Read after write the register as a precaution) */
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_2_REG(port));
+	regVal |= NETA_GMAC_PORT_RESET_MASK;
+	MV_REG_WRITE(NETA_GMAC_CTRL_2_REG(port), regVal);
+	while ((MV_REG_READ(NETA_GMAC_CTRL_2_REG(port)) & NETA_GMAC_PORT_RESET_MASK) == 0)
+		continue;
+}
+
+MV_STATUS	mvEthGmacRgmiiSet(int port, int enable)
+{
+	MV_U32	regVal;
+
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_2_REG(port));
+	if (enable)
+		regVal |= NETA_GMAC_PORT_RGMII_MASK;
+	else
+		regVal &= ~NETA_GMAC_PORT_RGMII_MASK;
+
+	MV_REG_WRITE(NETA_GMAC_CTRL_2_REG(port), regVal);
+
+	return MV_OK;
+}
+
+static void mvEthPortSgmiiConfig(int port)
+{
+	mvOsPrintf("WARNING: %s for GMAC temporary not supported\n", __func__);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthAddrDec.c b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthAddrDec.c
new file mode 100755
index 0000000..92dd3d5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthAddrDec.c
@@ -0,0 +1,449 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "../mvEth.h"
+#include "mvEthRegs.h"
+
+MV_TARGET ethAddrDecPrioTab[] = {
+#if defined(MV_INCLUDE_SDRAM_CS0)
+	SDRAM_CS0,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS1)
+	SDRAM_CS1,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS2)
+	SDRAM_CS2,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS3)
+	SDRAM_CS3,
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS0)
+	DEVICE_CS0,
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS1)
+	DEVICE_CS1,
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS2)
+	DEVICE_CS2,
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS3)
+	DEVICE_CS3,
+#endif
+#if defined(MV_INCLUDE_PEX)
+#ifdef MV_INCLUDE_PEX0
+	PEX0_IO,
+#endif
+#ifdef MV_INCLUDE_PEX1
+	PEX1_IO,
+#endif
+#endif
+	TBL_TERM
+};
+
+static MV_STATUS ethWinOverlapDetect(MV_U32 port, MV_U32 winNum,
+					MV_ADDR_WIN *pAddrWin);
+
+/*******************************************************************************
+* mvEthWinInit
+*
+* DESCRIPTION:
+*	This function initialize ETH window decode unit. It set the default
+*	address decode windows of the unit.
+*
+* INPUT:
+*	port	 : The port number to initialize the address decoding for.
+*	addWinMap: An array holding the address decoding information for the
+*		    system.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if setting fail.
+*******************************************************************************/
+MV_STATUS mvEthWinInit(MV_U32 port, MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 winNum, winPrioIndex = 0, i, regVal = 0;
+	MV_UNIT_WIN_INFO *addrDecWin;
+	static MV_U32 accessProtReg;
+
+#if (MV_ETH_VERSION <= 1)
+	static MV_BOOL isFirst = MV_TRUE;
+
+	if (isFirst == MV_FALSE) {
+		MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(port), accessProtReg);
+		return MV_OK;
+	}
+	isFirst = MV_FALSE;
+#endif /* MV_GIGA_ETH_VERSION */
+
+	/* Initiate Ethernet address decode */
+	/* First disable all address decode windows */
+	for (winNum = 0; winNum < ETH_MAX_DECODE_WIN; winNum++)
+		regVal |= MV_BIT_MASK(winNum);
+
+	MV_REG_WRITE(ETH_BASE_ADDR_ENABLE_REG(port), regVal);
+
+	/* Go through all windows in user table until table terminator      */
+	for (winNum = 0; ((ethAddrDecPrioTab[winPrioIndex] != TBL_TERM) && (winNum < ETH_MAX_DECODE_WIN));) {
+		addrDecWin = &addrWinMap[ethAddrDecPrioTab[winPrioIndex]];
+
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvEthWinWrite(port, winNum, addrDecWin)) {
+				mvOsPrintf("mvEthWinInit: ERR. mvEthWinWrite failed winNum=%d (%d, %d)\n",
+					   winNum, winPrioIndex, ethAddrDecPrioTab[winPrioIndex]);
+				return MV_ERROR;
+			}
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+
+	/* set full access to all windows. */
+	for (i = 0; i < winNum; i++)
+		accessProtReg |= (FULL_ACCESS << (i * 2));
+
+	MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(port), accessProtReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthWinWrite
+*
+* DESCRIPTION:
+*	This function writes the address decoding registers according to the
+*	given window configuration.
+*
+* INPUT:
+*	unit	    - The Ethernet unit number to configure.
+*       winNum	    - ETH target address decode window number.
+*       pAddrDecWin - ETH target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_BAD_PARAM if winNum is invalid.
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvEthWinWrite(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 size, alignment;
+	MV_U32 baseReg, sizeReg;
+
+	/* Parameter checking   */
+	if (winNum >= ETH_MAX_DECODE_WIN) {
+		mvOsPrintf("mvEthWinSet: ERR. Invalid win num %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlapps with current windows     */
+	if (MV_TRUE == ethWinOverlapDetect(port, winNum, &pAddrDecWin->addrWin)) {
+		mvOsPrintf("mvEthWinWrite: ERR. Window %d overlap\n", winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) {
+		mvOsPrintf("mvEthWinSet: Error setting Ethernet window %d.\n"
+			   "Address 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	size = pAddrDecWin->addrWin.size;
+	if (!MV_IS_POWER_OF_2(size)) {
+		mvOsPrintf("mvEthWinWrite: Error setting AUDIO window %d. " "Window size is not a power to 2.", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	baseReg = (pAddrDecWin->addrWin.baseLow & ETH_WIN_BASE_MASK);
+	sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum));
+
+	/* set size */
+	alignment = 1 << ETH_WIN_SIZE_OFFS;
+	sizeReg &= ~ETH_WIN_SIZE_MASK;
+	sizeReg |= (((size / alignment) - 1) << ETH_WIN_SIZE_OFFS);
+
+	/* set attributes */
+	baseReg &= ~ETH_WIN_ATTR_MASK;
+	baseReg |= pAddrDecWin->attrib << ETH_WIN_ATTR_OFFS;
+
+	/* set target ID */
+	baseReg &= ~ETH_WIN_TARGET_MASK;
+	baseReg |= pAddrDecWin->targetId << ETH_WIN_TARGET_OFFS;
+
+	/* for the safe side we disable the window before writing the new
+	   values */
+	mvEthWinEnable(port, winNum, MV_FALSE);
+	MV_REG_WRITE(ETH_WIN_BASE_REG(port, winNum), baseReg);
+
+	/* Write to address decode Size Register                            */
+	MV_REG_WRITE(ETH_WIN_SIZE_REG(port, winNum), sizeReg);
+
+	/* Enable address decode target window                              */
+	if (pAddrDecWin->enable == MV_TRUE)
+		mvEthWinEnable(port, winNum, MV_TRUE);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* ethWinOverlapDetect - Detect ETH address windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviur is expected in case ETH address decode
+*       windows overlapps.
+*       This function detects ETH address decode windows overlapping of a
+*       specified window. The function does not check the window itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS ethWinOverlapDetect(MV_U32 port, MV_U32 winNum,
+					MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 baseAddrEnableReg;
+	MV_U32 winNumIndex;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	/* Read base address enable register. Do not check disabled windows     */
+	baseAddrEnableReg = MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port));
+
+	for (winNumIndex = 0; winNumIndex < ETH_MAX_DECODE_WIN; winNumIndex++) {
+		/* Do not check window itself           */
+		if (winNumIndex == winNum)
+			continue;
+
+		/* Do not check disabled windows        */
+		if (baseAddrEnableReg & (1 << winNumIndex))
+			continue;
+
+		/* Get window parameters        */
+		if (MV_OK != mvEthWinRead(port, winNumIndex, &addrDecWin)) {
+			mvOsPrintf("ethWinOverlapDetect: ERR. TargetWinGet failed\n");
+			return MV_ERROR;
+		}
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+			return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvEthWinRead
+*
+* DESCRIPTION:
+*       Read Ethernet peripheral target address window.
+*
+* INPUT:
+*       winNum - ETH to target address decode window number.
+*
+* OUTPUT:
+*       pAddrDecWin - ETH target window data structure.
+*
+* RETURN:
+*	MV_BAD_PARAM if winNum is invalid.
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvEthWinRead(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 baseReg, sizeReg;
+	MV_U32 alignment, size;
+
+	/* Parameter checking   */
+	if (winNum >= ETH_MAX_DECODE_WIN) {
+		mvOsPrintf("mvEthWinGet: ERR. Invalid winNum %d\n", winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum));
+	sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum));
+
+	alignment = 1 << ETH_WIN_SIZE_OFFS;
+	size = (sizeReg & ETH_WIN_SIZE_MASK) >> ETH_WIN_SIZE_OFFS;
+	pAddrDecWin->addrWin.size = (size + 1) * alignment;
+
+	/* Extract base address                                     */
+	pAddrDecWin->addrWin.baseLow = baseReg & ETH_WIN_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh = 0;
+
+	/* attrib and targetId */
+	pAddrDecWin->attrib = (baseReg & ETH_WIN_ATTR_MASK) >> ETH_WIN_ATTR_OFFS;
+	pAddrDecWin->targetId = (baseReg & ETH_WIN_TARGET_MASK) >> ETH_WIN_TARGET_OFFS;
+
+	/* Check if window is enabled   */
+	if (~(MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port))) & (1 << winNum))
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthWinEnable - Enable/disable a ETH to target address window
+*
+* DESCRIPTION:
+*       This function enable/disable a ETH to target address window.
+*       According to parameter 'enable' the routine will enable the
+*       window, thus enabling ETH accesses (before enabling the window it is
+*       tested for overlapping). Otherwise, the window will be disabled.
+*
+* INPUT:
+*       winNum - ETH to target address decode window number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_ERROR if decode window number was wrong or enabled window overlapps.
+*
+*******************************************************************************/
+MV_STATUS mvEthWinEnable(MV_U32 port, MV_U32 winNum, MV_BOOL enable)
+{
+	/* Parameter checking   */
+	if (winNum >= ETH_MAX_DECODE_WIN) {
+		mvOsPrintf("mvEthTargetWinEnable:ERR. Invalid winNum%d\n", winNum);
+		return MV_ERROR;
+	}
+
+	if (enable == MV_TRUE) {
+		MV_REG_BIT_RESET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum));
+	} else {
+		/* Disable address decode target window                             */
+		MV_REG_BIT_SET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum));
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthProtWinSet - Set access protection of Ethernet to target window.
+*
+* DESCRIPTION:
+*       Each Ethernet port can be configured with access attributes for each
+*       of the Ethenret to target windows (address decode windows). This
+*       function sets access attributes to a given window for the given channel.
+*
+* INPUTS:
+*       ethPort   - ETH channel number. See MV_ETH_CHANNEL enumerator.
+*       winNum - IETH to target address decode window number.
+*       access - IETH access rights. See MV_ACCESS_RIGHTS enumerator.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR in case window number is invalid or access right reserved.
+*
+*******************************************************************************/
+MV_STATUS mvEthProtWinSet(MV_U32 portNo, MV_U32 winNum, MV_ACCESS_RIGHTS access)
+{
+	MV_U32 protReg;
+
+	/* Parameter checking   */
+	if (portNo >= MV_ETH_MAX_PORTS) {
+		mvOsPrintf("mvEthProtWinSet:ERR. Invalid port number %d\n", portNo);
+		return MV_ERROR;
+	}
+
+	if (winNum >= ETH_MAX_DECODE_WIN) {
+		mvOsPrintf("mvEthProtWinSet:ERR. Invalid winNum%d\n", winNum);
+		return MV_ERROR;
+	}
+
+	if ((access == ACC_RESERVED) || (access >= MAX_ACC_RIGHTS)) {
+		mvOsPrintf("mvEthProtWinSet:ERR. Inv access param %d\n", access);
+		return MV_ERROR;
+	}
+	/* Read current protection register */
+	protReg = MV_REG_READ(ETH_ACCESS_PROTECT_REG(portNo));
+
+	/* Clear protection window field */
+	protReg &= ~(ETH_PROT_WIN_MASK(winNum));
+
+	/* Set new protection field value */
+	protReg |= (access << (ETH_PROT_WIN_OFFS(winNum)));
+
+	/* Write protection register back   */
+	MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(portNo), protReg);
+
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthDebug.c b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthDebug.c
new file mode 100755
index 0000000..7ad7024
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthDebug.c
@@ -0,0 +1,696 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvEthDebug.c - Source file for user friendly debug functions
+*
+* DESCRIPTION:
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#define MV_RT_DEBUG
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysEthConfig.h"
+#include "mvEthRegs.h"
+#include "eth/mvEth.h"
+#include "mvEthDebug.h"
+#include "mvEthGbe.h"
+
+/* #define mvOsPrintf printf */
+void mvEthPortShow(void *pHndl);
+void mvEthQueuesShow(void *pHndl, int rxQueue, int txQueue, int mode);
+
+static void mvEthRegPrint(MV_U32 reg_addr, MV_U8 *reg_name)
+{
+	mvOsPrintf("  %-32s: 0x%x = 0x%08x\n", reg_name, reg_addr, MV_REG_READ(reg_addr));
+}
+
+#if 0
+static void mvEthRegPrint0(MV_U32 reg_addr, MV_U8 *reg_name)
+{
+	mvOsPrintf("  %-32s: %u\n", reg_name, MV_REG_READ(reg_addr));
+}
+
+static void mvEthRegPrint2(MV_U32 reg_addr, MV_U8 *reg_name, MV_U32 index)
+{
+	char buf[64];
+
+	mvOsSPrintf(buf, "%s[%d]", reg_name, index);
+	mvOsPrintf("  %-32s: 0x%x = 0x%08x\n", buf, reg_addr, MV_REG_READ(reg_addr));
+}
+#endif
+
+/******************************************************************************/
+/*                          Debug functions                                   */
+/******************************************************************************/
+void ethRxCoal(int port, int usec)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthRxCoalSet(pHndl, usec);
+}
+
+void ethTxCoal(int port, int usec)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthTxCoalSet(pHndl, usec);
+}
+
+#if (MV_ETH_VERSION >= 4)
+void ethEjpModeSet(int port, int mode)
+{
+	void *pHndl;
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthEjpModeSet(pHndl, mode);
+}
+#endif /* (MV_ETH_VERSION >= 4) */
+
+void ethBpduRxQ(int port, int bpduQueue)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthBpduRxQueue(pHndl, bpduQueue);
+}
+
+void ethArpRxQ(int port, int arpQueue)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthArpRxQueue(pHndl, arpQueue);
+}
+
+void ethTcpRxQ(int port, int tcpQueue)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthTcpRxQueue(pHndl, tcpQueue);
+}
+
+void ethUdpRxQ(int port, int udpQueue)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthUdpRxQueue(pHndl, udpQueue);
+}
+
+void ethTxPolicyRegs(int port)
+{
+	int queue;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) mvEthPortHndlGet(port);
+
+	if (pPortCtrl == NULL)
+		return;
+
+	mvOsPrintf("Port #%d TX Policy: EJP=%d, TXQs: ", port, pPortCtrl->portConfig.ejpMode);
+	for (queue = 0; queue < MV_ETH_TX_Q_NUM; queue++) {
+		if (pPortCtrl->txQueueConfig[queue].descrNum > 0)
+			mvOsPrintf("%d, ", queue);
+	}
+	mvOsPrintf("\n");
+
+	mvOsPrintf("\n\t TX policy Port #%d configuration registers\n", port);
+
+	mvOsPrintf("ETH_TX_QUEUE_COMMAND_REG            : 0x%X = 0x%08x\n",
+		   ETH_TX_QUEUE_COMMAND_REG(port), MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(port)));
+
+	mvOsPrintf("ETH_TX_FIXED_PRIO_CFG_REG           : 0x%X = 0x%08x\n",
+		   ETH_TX_FIXED_PRIO_CFG_REG(port), MV_REG_READ(ETH_TX_FIXED_PRIO_CFG_REG(port)));
+
+	mvOsPrintf("ETH_TX_TOKEN_RATE_CFG_REG           : 0x%X = 0x%08x\n",
+		   ETH_TX_TOKEN_RATE_CFG_REG(port), MV_REG_READ(ETH_TX_TOKEN_RATE_CFG_REG(port)));
+
+	mvOsPrintf("ETH_MAX_TRANSMIT_UNIT_REG           : 0x%X = 0x%08x\n",
+		   ETH_MAX_TRANSMIT_UNIT_REG(port), MV_REG_READ(ETH_MAX_TRANSMIT_UNIT_REG(port)));
+
+	mvOsPrintf("ETH_TX_TOKEN_BUCKET_SIZE_REG        : 0x%X = 0x%08x\n",
+		   ETH_TX_TOKEN_BUCKET_SIZE_REG(port), MV_REG_READ(ETH_TX_TOKEN_BUCKET_SIZE_REG(port)));
+
+	mvOsPrintf("ETH_TX_TOKEN_BUCKET_COUNT_REG       : 0x%X = 0x%08x\n",
+		   ETH_TX_TOKEN_BUCKET_COUNT_REG(port), MV_REG_READ(ETH_TX_TOKEN_BUCKET_COUNT_REG(port)));
+
+	for (queue = 0; queue < MV_ETH_MAX_TXQ; queue++) {
+		mvOsPrintf("\n\t TX policy Port #%d, Queue #%d configuration registers\n", port, queue);
+
+		mvOsPrintf("ETH_TXQ_TOKEN_COUNT_REG             : 0x%X = 0x%08x\n",
+			   ETH_TXQ_TOKEN_COUNT_REG(port, queue), MV_REG_READ(ETH_TXQ_TOKEN_COUNT_REG(port, queue)));
+
+		mvOsPrintf("ETH_TXQ_TOKEN_CFG_REG               : 0x%X = 0x%08x\n",
+			   ETH_TXQ_TOKEN_CFG_REG(port, queue), MV_REG_READ(ETH_TXQ_TOKEN_CFG_REG(port, queue)));
+
+		mvOsPrintf("ETH_TXQ_ARBITER_CFG_REG             : 0x%X = 0x%08x\n",
+			   ETH_TXQ_ARBITER_CFG_REG(port, queue), MV_REG_READ(ETH_TXQ_ARBITER_CFG_REG(port, queue)));
+	}
+	mvOsPrintf("\n");
+}
+
+/* Print important registers of Ethernet port */
+void ethPortRegs(int port)
+{
+	mvOsPrintf("\n\t ethGiga #%d port Registers:\n", port);
+
+	mvOsPrintf("ETH_PORT_STATUS_REG                 : 0x%X = 0x%08x\n",
+		   ETH_PORT_STATUS_REG(port), MV_REG_READ(ETH_PORT_STATUS_REG(port)));
+
+	mvOsPrintf("ETH_PORT_SERIAL_CTRL_REG            : 0x%X = 0x%08x\n",
+		   ETH_PORT_SERIAL_CTRL_REG(port), MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port)));
+
+	mvOsPrintf("ETH_PORT_CONFIG_REG                 : 0x%X = 0x%08x\n",
+		   ETH_PORT_CONFIG_REG(port), MV_REG_READ(ETH_PORT_CONFIG_REG(port)));
+
+	mvOsPrintf("ETH_PORT_CONFIG_EXTEND_REG          : 0x%X = 0x%08x\n",
+		   ETH_PORT_CONFIG_EXTEND_REG(port), MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(port)));
+
+	mvOsPrintf("ETH_SDMA_CONFIG_REG                 : 0x%X = 0x%08x\n",
+		   ETH_SDMA_CONFIG_REG(port), MV_REG_READ(ETH_SDMA_CONFIG_REG(port)));
+
+	mvOsPrintf("ETH_TX_FIFO_URGENT_THRESH_REG       : 0x%X = 0x%08x\n",
+		   ETH_TX_FIFO_URGENT_THRESH_REG(port), MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(port)));
+
+	mvOsPrintf("ETH_RX_QUEUE_COMMAND_REG            : 0x%X = 0x%08x\n",
+		   ETH_RX_QUEUE_COMMAND_REG(port), MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(port)));
+
+	mvOsPrintf("ETH_TX_QUEUE_COMMAND_REG            : 0x%X = 0x%08x\n",
+		   ETH_TX_QUEUE_COMMAND_REG(port), MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(port)));
+
+	mvOsPrintf("ETH_INTR_CAUSE_REG                  : 0x%X = 0x%08x\n",
+		   ETH_INTR_CAUSE_REG(port), MV_REG_READ(ETH_INTR_CAUSE_REG(port)));
+
+	mvOsPrintf("ETH_INTR_EXTEND_CAUSE_REG           : 0x%X = 0x%08x\n",
+		   ETH_INTR_CAUSE_EXT_REG(port), MV_REG_READ(ETH_INTR_CAUSE_EXT_REG(port)));
+
+	mvOsPrintf("ETH_INTR_MASK_REG                   : 0x%X = 0x%08x\n",
+		   ETH_INTR_MASK_REG(port), MV_REG_READ(ETH_INTR_MASK_REG(port)));
+
+	mvOsPrintf("ETH_INTR_EXTEND_MASK_REG            : 0x%X = 0x%08x\n",
+		   ETH_INTR_MASK_EXT_REG(port), MV_REG_READ(ETH_INTR_MASK_EXT_REG(port)));
+
+	mvOsPrintf("ETH_RX_DESCR_STAT_CMD_REG           : 0x%X = 0x%08x\n",
+		   ETH_RX_DESCR_STAT_CMD_REG(port, 0), MV_REG_READ(ETH_RX_DESCR_STAT_CMD_REG(port, 0)));
+
+	mvOsPrintf("ETH_RX_BYTE_COUNT_REG               : 0x%X = 0x%08x\n",
+		   ETH_RX_BYTE_COUNT_REG(port, 0), MV_REG_READ(ETH_RX_BYTE_COUNT_REG(port, 0)));
+
+	mvOsPrintf("ETH_RX_BUF_PTR_REG                  : 0x%X = 0x%08x\n",
+		   ETH_RX_BUF_PTR_REG(port, 0), MV_REG_READ(ETH_RX_BUF_PTR_REG(port, 0)));
+
+	mvOsPrintf("ETH_RX_CUR_DESC_PTR_REG             : 0x%X = 0x%08x\n",
+		   ETH_RX_CUR_DESC_PTR_REG(port, 0), MV_REG_READ(ETH_RX_CUR_DESC_PTR_REG(port, 0)));
+}
+
+/* Print Giga Ethernet UNIT registers */
+void ethRegs(int port)
+{
+	mvOsPrintf("ETH_PHY_ADDR_REG               : 0x%X = 0x%08x\n",
+		   ETH_PHY_ADDR_REG(port), MV_REG_READ(ETH_PHY_ADDR_REG(port)));
+
+	mvOsPrintf("ETH_UNIT_INTR_CAUSE_REG        : 0x%X = 0x%08x\n",
+		   ETH_UNIT_INTR_CAUSE_REG(port), MV_REG_READ(ETH_UNIT_INTR_CAUSE_REG(port)));
+
+	mvOsPrintf("ETH_UNIT_INTR_MASK_REG         : 0x%X = 0x%08x\n",
+		   ETH_UNIT_INTR_MASK_REG(port), MV_REG_READ(ETH_UNIT_INTR_MASK_REG(port)));
+
+	mvOsPrintf("ETH_UNIT_ERROR_ADDR_REG        : 0x%X = 0x%08x\n",
+		   ETH_UNIT_ERROR_ADDR_REG(port), MV_REG_READ(ETH_UNIT_ERROR_ADDR_REG(port)));
+
+	mvOsPrintf("ETH_UNIT_INT_ADDR_ERROR_REG    : 0x%X = 0x%08x\n",
+		   ETH_UNIT_INT_ADDR_ERROR_REG(port), MV_REG_READ(ETH_UNIT_INT_ADDR_ERROR_REG(port)));
+
+}
+
+/******************************************************************************/
+/*                      MIB Counters functions                                */
+/******************************************************************************/
+
+/*******************************************************************************
+* ethClearMibCounters - Clear all MIB counters
+*
+* DESCRIPTION:
+*       This function clears all MIB counters of a specific ethernet port.
+*       A read from the MIB counter will reset the counter.
+*
+* INPUT:
+*       int    port -  Ethernet Port number.
+*
+* RETURN: None
+*
+*******************************************************************************/
+void ethClearCounters(int port)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthMibCountersClear(pHndl);
+
+	return;
+}
+
+/* Print counters of the Ethernet port */
+void ethPortCounters(int port)
+{
+	MV_U32 regValue, regValHigh;
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl == NULL)
+		return;
+
+	mvOsPrintf("\n\t Port #%d MIB Counters\n\n", port);
+
+	mvOsPrintf("GoodFramesReceived          = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_FRAMES_RECEIVED, NULL));
+	mvOsPrintf("BadFramesReceived           = %u\n", mvEthMibCounterRead(pHndl, ETH_MIB_BAD_FRAMES_RECEIVED, NULL));
+	mvOsPrintf("BroadcastFramesReceived     = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_BROADCAST_FRAMES_RECEIVED, NULL));
+	mvOsPrintf("MulticastFramesReceived     = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_MULTICAST_FRAMES_RECEIVED, NULL));
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, &regValHigh);
+	mvOsPrintf("GoodOctetsReceived          = 0x%08x%08x\n", regValHigh, regValue);
+
+	mvOsPrintf("\n");
+	mvOsPrintf("GoodFramesSent              = %u\n", mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_FRAMES_SENT, NULL));
+	mvOsPrintf("BroadcastFramesSent         = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_BROADCAST_FRAMES_SENT, NULL));
+	mvOsPrintf("MulticastFramesSent         = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_MULTICAST_FRAMES_SENT, NULL));
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_OCTETS_SENT_LOW, &regValHigh);
+	mvOsPrintf("GoodOctetsSent              = 0x%08x%08x\n", regValHigh, regValue);
+
+	mvOsPrintf("\n\t FC Control Counters\n");
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_UNREC_MAC_CONTROL_RECEIVED, NULL);
+	mvOsPrintf("UnrecogMacControlReceived   = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_FC_RECEIVED, NULL);
+	mvOsPrintf("GoodFCFramesReceived        = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_BAD_FC_RECEIVED, NULL);
+	mvOsPrintf("BadFCFramesReceived         = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_FC_SENT, NULL);
+	mvOsPrintf("FCFramesSent                = %u\n", regValue);
+
+	mvOsPrintf("\n\t RX Errors\n");
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_BAD_OCTETS_RECEIVED, NULL);
+	mvOsPrintf("BadOctetsReceived           = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_UNDERSIZE_RECEIVED, NULL);
+	mvOsPrintf("UndersizeFramesReceived     = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_FRAGMENTS_RECEIVED, NULL);
+	mvOsPrintf("FragmentsReceived           = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_OVERSIZE_RECEIVED, NULL);
+	mvOsPrintf("OversizeFramesReceived      = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_JABBER_RECEIVED, NULL);
+	mvOsPrintf("JabbersReceived             = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_MAC_RECEIVE_ERROR, NULL);
+	mvOsPrintf("MacReceiveErrors            = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_BAD_CRC_EVENT, NULL);
+	mvOsPrintf("BadCrcReceived              = %u\n", regValue);
+
+	mvOsPrintf("\n\t TX Errors\n");
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR, NULL);
+	mvOsPrintf("TxMacErrors                 = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_EXCESSIVE_COLLISION, NULL);
+	mvOsPrintf("TxExcessiveCollisions       = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_COLLISION, NULL);
+	mvOsPrintf("TxCollisions                = %u\n", regValue);
+
+	regValue = mvEthMibCounterRead(pHndl, ETH_MIB_LATE_COLLISION, NULL);
+	mvOsPrintf("TxLateCollisions            = %u\n", regValue);
+
+	mvOsPrintf("\n");
+	regValue = MV_REG_READ(ETH_RX_DISCARD_PKTS_CNTR_REG(port));
+	mvOsPrintf("Rx Discard packets counter  = %u\n", regValue);
+
+	regValue = MV_REG_READ(ETH_RX_OVERRUN_PKTS_CNTR_REG(port));
+	mvOsPrintf("Rx Overrun packets counter  = %u\n", regValue);
+}
+
+/* Print RMON counters of the Ethernet port */
+void ethPortRmonCounters(int port)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl == NULL)
+		return;
+
+	mvOsPrintf("\n\t Port #%d RMON MIB Counters\n\n", port);
+
+	mvOsPrintf("64 ByteFramesReceived           = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_64_OCTETS, NULL));
+	mvOsPrintf("65...127 ByteFramesReceived     = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_65_TO_127_OCTETS, NULL));
+	mvOsPrintf("128...255 ByteFramesReceived    = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_128_TO_255_OCTETS, NULL));
+	mvOsPrintf("256...511 ByteFramesReceived    = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_256_TO_511_OCTETS, NULL));
+	mvOsPrintf("512...1023 ByteFramesReceived   = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_512_TO_1023_OCTETS, NULL));
+	mvOsPrintf("1024...Max ByteFramesReceived   = %u\n",
+		   mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_1024_TO_MAX_OCTETS, NULL));
+}
+
+/* Print port information */
+void ethPortStatus(int port)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthPortShow(pHndl);
+}
+
+
+void    mvNetaGmacRegs(int port)
+{
+	mvOsPrintf("\nPort #%d GMAC registers:\n", port);
+
+	mvEthRegPrint(ETH_PORT_STATUS_REG(port),        (MV_U8 *)"ETH_PORT_STATUS_REG");
+	mvEthRegPrint(ETH_PORT_SERIAL_CTRL_REG(port),   (MV_U8 *)"ETH_PORT_SERIAL_CTRL_REG");
+	mvEthRegPrint(NETA_GMAC_CTRL_0_REG(port),       (MV_U8 *)"NETA_GMAC_CTRL_0_REG");
+	mvEthRegPrint(NETA_GMAC_CTRL_1_REG(port),       (MV_U8 *)"NETA_GMAC_CTRL_1_REG");
+	mvEthRegPrint(NETA_GMAC_CTRL_2_REG(port),       (MV_U8 *)"NETA_GMAC_CTRL_2_REG");
+	mvEthRegPrint(NETA_GMAC_AN_CTRL_REG(port),      (MV_U8 *)"NETA_GMAC_AN_CTRL_REG");
+	mvEthRegPrint(NETA_GMAC_STATUS_REG(port),       (MV_U8 *)"NETA_GMAC_STATUS_REG");
+	mvEthRegPrint(NETA_GMAC_SERIAL_REG(port),       (MV_U8 *)"NETA_GMAC_SERIAL_REG");
+	mvEthRegPrint(NETA_GMAC_FIFO_PARAM_0_REG(port), (MV_U8 *)"NETA_GMAC_FIFO_PARAM_0_REG");
+	mvEthRegPrint(NETA_GMAC_FIFO_PARAM_1_REG(port), (MV_U8 *)"NETA_GMAC_FIFO_PARAM_1_REG");
+	mvEthRegPrint(NETA_GMAC_CAUSE_REG(port),        (MV_U8 *)"NETA_GMAC_CAUSE_REG");
+	mvEthRegPrint(NETA_GMAC_MASK_REG(port),         (MV_U8 *)"NETA_GMAC_MASK_REG");
+	mvEthRegPrint(NETA_GMAC_MIB_CTRL_REG(port),     (MV_U8 *)"NETA_GMAC_MIB_CTRL_REG");
+}
+
+/* Print port queues information */
+void ethPortQueues(int port, int rxQueue, int txQueue, int mode)
+{
+	void *pHndl;
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL)
+		mvEthQueuesShow(pHndl, rxQueue, txQueue, mode);
+}
+
+void ethUcastSet(int port, char *macStr, int queue)
+{
+	void *pHndl;
+	MV_U8 macAddr[MV_MAC_ADDR_SIZE];
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL) {
+		mvMacStrToHex(macStr, macAddr);
+		mvEthMacAddrSet(pHndl, macAddr, queue);
+	}
+}
+
+void ethPortUcastShow(int port)
+{
+	MV_U32 unicastReg, macL, macH;
+	int i, j;
+
+	macL = MV_REG_READ(ETH_MAC_ADDR_LOW_REG(port));
+	macH = MV_REG_READ(ETH_MAC_ADDR_HIGH_REG(port));
+
+	mvOsPrintf("\n\t Port #%d Unicast MAC table: %02x:%02x:%02x:%02x:%02x:%02x\n\n",
+		   port, ((macH >> 24) & 0xff), ((macH >> 16) & 0xff),
+		   ((macH >> 8) & 0xff), (macH & 0xff), ((macL >> 8) & 0xff), (macL & 0xff));
+
+	for (i = 0; i < 4; i++) {
+		unicastReg = MV_REG_READ((ETH_DA_FILTER_UCAST_BASE(port) + i * 4));
+		for (j = 0; j < 4; j++) {
+			MV_U8 macEntry = (unicastReg >> (8 * j)) & 0xFF;
+			mvOsPrintf("%X: %8s, Q = %d\n", i * 4 + j,
+				   (macEntry & BIT0) ? "Accept" : "Reject", (macEntry >> 1) & 0x7);
+		}
+	}
+}
+
+void ethMcastAdd(int port, char *macStr, int queue)
+{
+	void *pHndl;
+	MV_U8 macAddr[MV_MAC_ADDR_SIZE];
+
+	pHndl = mvEthPortHndlGet(port);
+	if (pHndl != NULL) {
+		mvMacStrToHex(macStr, macAddr);
+		mvEthMcastAddrSet(pHndl, macAddr, queue);
+	}
+}
+
+void ethPortMcast(int port)
+{
+	int tblIdx, regIdx;
+	MV_U32 regVal;
+
+	mvOsPrintf("\n\t Port #%d Special (IP) Multicast table: 01:00:5E:00:00:XX\n\n", port);
+
+	for (tblIdx = 0; tblIdx < (256 / 4); tblIdx++) {
+		regVal = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(port) + tblIdx * 4));
+		for (regIdx = 0; regIdx < 4; regIdx++) {
+			if ((regVal & (0x01 << (regIdx * 8))) != 0) {
+				mvOsPrintf("0x%02X: Accepted, rxQ = %d\n",
+					   tblIdx * 4 + regIdx, ((regVal >> (regIdx * 8 + 1)) & 0x07));
+			}
+		}
+	}
+	mvOsPrintf("\n\t Port #%d Other Multicast table\n\n", port);
+	for (tblIdx = 0; tblIdx < (256 / 4); tblIdx++) {
+		regVal = MV_REG_READ((ETH_DA_FILTER_OTH_MCAST_BASE(port) + tblIdx * 4));
+		for (regIdx = 0; regIdx < 4; regIdx++) {
+			if ((regVal & (0x01 << (regIdx * 8))) != 0) {
+				mvOsPrintf("Crc8=0x%02X: Accepted, rxQ = %d\n",
+					   tblIdx * 4 + regIdx, ((regVal >> (regIdx * 8 + 1)) & 0x07));
+			}
+		}
+	}
+}
+
+/* Print status of Ethernet port */
+void mvEthPortShow(void *pHndl)
+{
+	MV_U32 regValue, rxCoal, txCoal;
+	int speed, queue, port;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pHndl;
+
+	port = pPortCtrl->portNo;
+
+    regValue = MV_REG_READ(NETA_GMAC_STATUS_REG(port));
+
+	mvOsPrintf("\n\t ethGiga #%d port Status: 0x%04x = 0x%08x\n\n", port, ETH_PORT_STATUS_REG(port), regValue);
+
+	mvOsPrintf("descInSram=%d, descSwCoher=%d\n", ethDescInSram, ethDescSwCoher);
+    if (regValue & NETA_GMAC_SPEED_1000_MASK)
+		speed = 1000;
+    else if (regValue & NETA_GMAC_SPEED_100_MASK)
+		speed = 100;
+	else
+		speed = 10;
+
+	mvEthCoalGet(pPortCtrl, &rxCoal, &txCoal);
+
+	/* Link, Speed, Duplex, FlowControl */
+	mvOsPrintf("Link=%s, Speed=%d, Duplex=%s, RxFlowControl=%s",
+		(regValue & NETA_GMAC_LINK_UP_MASK) ? "up" : "down", speed,
+		(regValue & NETA_GMAC_FULL_DUPLEX_MASK) ? "full" : "half",
+		(regValue & 0) ? "enable" : "disable");
+
+	mvOsPrintf("\n");
+
+	mvOsPrintf("RxCoal = %d usec, TxCoal = %d usec\n", rxCoal, txCoal);
+
+	mvOsPrintf("rxDefQ=%d, arpQ=%d, bpduQ=%d, tcpQ=%d, udpQ=%d\n\n",
+		   pPortCtrl->portConfig.rxDefQ, pPortCtrl->portConfig.rxArpQ,
+		   pPortCtrl->portConfig.rxBpduQ, pPortCtrl->portConfig.rxTcpQ, pPortCtrl->portConfig.rxUdpQ);
+
+	/* Print all RX and TX queues */
+	for (queue = 0; queue < MV_ETH_RX_Q_NUM; queue++) {
+		mvOsPrintf("RX Queue #%d: base=0x%lx, free=%d\n",
+			   queue, (MV_ULONG) pPortCtrl->rxQueue[queue].pFirstDescr,
+			   mvEthRxResourceGet(pPortCtrl, queue));
+	}
+	mvOsPrintf("\n");
+	for (queue = 0; queue < MV_ETH_TX_Q_NUM; queue++) {
+		mvOsPrintf("TX Queue #%d: base=0x%lx, free=%d\n",
+			   queue, (MV_ULONG) pPortCtrl->txQueue[queue].pFirstDescr,
+			   mvEthTxResourceGet(pPortCtrl, queue));
+	}
+}
+
+/* Print RX and TX queue of the Ethernet port */
+void mvEthQueuesShow(void *pHndl, int rxQueue, int txQueue, int mode)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	MV_U32 regValue;
+	ETH_RX_DESC *pRxDescr;
+	ETH_TX_DESC *pTxDescr;
+	int i, port = pPortCtrl->portNo;
+
+	if ((rxQueue >= 0) && (rxQueue < MV_ETH_RX_Q_NUM)) {
+		pQueueCtrl = &(pPortCtrl->rxQueue[rxQueue]);
+		mvOsPrintf("Port #%d, RX Queue #%d\n\n", port, rxQueue);
+
+		mvOsPrintf("CURR_RX_DESC_PTR        : 0x%X = 0x%08x\n",
+			   ETH_RX_CUR_DESC_PTR_REG(port, rxQueue), MV_REG_READ(ETH_RX_CUR_DESC_PTR_REG(port, rxQueue)));
+
+		if (pQueueCtrl->pFirstDescr != NULL) {
+			mvOsPrintf("pFirstDescr=0x%lx, pLastDescr=0x%lx, numOfResources=%d\n",
+				   (MV_ULONG) pQueueCtrl->pFirstDescr, (MV_ULONG) pQueueCtrl->pLastDescr,
+				   pQueueCtrl->resource);
+			mvOsPrintf("pCurrDescr: 0x%lx, pUsedDescr: 0x%lx\n",
+				   (MV_ULONG) pQueueCtrl->pCurrentDescr, (MV_ULONG) pQueueCtrl->pUsedDescr);
+
+			if (mode == 1) {
+				pRxDescr = (ETH_RX_DESC *) pQueueCtrl->pFirstDescr;
+				i = 0;
+				do {
+					mvOsPrintf
+					    ("%3d. desc=%08x (%08x), cmd=%08x, data=%4d, buf=%4d, buf=%08x, pkt=%lx, os=%lx\n",
+					     i, (MV_U32) pRxDescr, (MV_U32) ethDescVirtToPhy(pQueueCtrl,
+											     (MV_U8 *) pRxDescr),
+					     ETH_GET_32B_DESCR_VAL(pRxDescr->cmdSts),
+					     ETH_GET_16B_DESCR_VAL(pRxDescr->byteCnt),
+					     (MV_U32) ETH_GET_16B_DESCR_VAL(pRxDescr->bufSize),
+					     (unsigned int)ETH_GET_32B_DESCR_VAL(pRxDescr->bufPtr),
+					     (MV_ULONG) ETH_GET_32B_DESCR_VAL(pRxDescr->returnInfo),
+					     (((MV_PKT_INFO *) (ETH_GET_32B_DESCR_VAL(pRxDescr->returnInfo)))->osInfo));
+
+					ETH_DESCR_INV(pPortCtrl, pRxDescr);
+					pRxDescr = RX_NEXT_DESC_PTR(pRxDescr, pQueueCtrl);
+					i++;
+				} while (pRxDescr != pQueueCtrl->pFirstDescr);
+			}
+		} else
+			mvOsPrintf("RX Queue #%d is NOT CREATED\n", rxQueue);
+	}
+
+	if ((txQueue >= 0) && (txQueue < MV_ETH_TX_Q_NUM)) {
+		pQueueCtrl = &(pPortCtrl->txQueue[txQueue]);
+		mvOsPrintf("Port #%d, TX Queue #%d\n\n", port, txQueue);
+
+		regValue = MV_REG_READ(ETH_TX_CUR_DESC_PTR_REG(port, txQueue));
+		mvOsPrintf("CURR_TX_DESC_PTR        : 0x%X = 0x%08x\n",
+			   ETH_TX_CUR_DESC_PTR_REG(port, txQueue), regValue);
+
+		if (pQueueCtrl->pFirstDescr != NULL) {
+			mvOsPrintf("pFirstDescr=0x%lx, pLastDescr=0x%lx, numOfResources=%d\n",
+				   (MV_ULONG) pQueueCtrl->pFirstDescr,
+				   (MV_ULONG) pQueueCtrl->pLastDescr, pQueueCtrl->resource);
+			mvOsPrintf("pCurrDescr: 0x%lx, pUsedDescr: 0x%lx\n",
+				   (MV_ULONG) pQueueCtrl->pCurrentDescr, (MV_ULONG) pQueueCtrl->pUsedDescr);
+
+			if (mode == 1) {
+				pTxDescr = (ETH_TX_DESC *) pQueueCtrl->pFirstDescr;
+				i = 0;
+				do {
+					mvOsPrintf
+					    ("%3d. desc=%08x (%08x), cmd=%08x, data=%4d, buf=%08x, pkt=%lx, os=%lx\n",
+					     i, (MV_U32) pTxDescr, (MV_U32) ethDescVirtToPhy(pQueueCtrl,
+											     (MV_U8 *) pTxDescr),
+					     ETH_GET_32B_DESCR_VAL(pTxDescr->cmdSts),
+					     ETH_GET_16B_DESCR_VAL(pTxDescr->byteCnt),
+					     (MV_U32) ETH_GET_32B_DESCR_VAL(pTxDescr->bufPtr),
+					     (MV_ULONG) ETH_GET_32B_DESCR_VAL(pTxDescr->returnInfo),
+					     pTxDescr->
+					     returnInfo
+					     ? (((MV_PKT_INFO *) ETH_GET_32B_DESCR_VAL(pTxDescr->returnInfo))->
+						osInfo) : 0x0);
+
+					ETH_DESCR_INV(pPortCtrl, pTxDescr);
+					pTxDescr = TX_NEXT_DESC_PTR(pTxDescr, pQueueCtrl);
+					i++;
+				} while (pTxDescr != pQueueCtrl->pFirstDescr);
+			}
+		} else
+			mvOsPrintf("TX Queue #%d is NOT CREATED\n", txQueue);
+	}
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthDebug.h b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthDebug.h
new file mode 100755
index 0000000..2e7e3b1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthDebug.h
@@ -0,0 +1,152 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_ETH_DEBUG_H__
+#define __MV_ETH_DEBUG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 0
+/*
+ ** Externs
+ */
+void     ethBpduRxQ(int port, int bpduQueue);
+void     ethArpRxQ(int port, int bpduQueue);
+void     ethTcpRxQ(int port, int bpduQueue);
+void     ethUdpRxQ(int port, int bpduQueue);
+void     ethMcastAdd(int port, char *macStr, int queue);
+
+#ifdef INCLUDE_MULTI_QUEUE
+void   	ethRxPolicy(int port);
+void   	ethTxPolicy(int port);
+void   	ethTxPolDA(int port, char *macStr, int txQ, char *headerHexStr);
+void   	ethRxPolMode(int port, MV_ETH_PRIO_MODE prioMode);
+void    ethRxPolQ(int port, int rxQueue, int rxQuota);
+#endif /* INCLUDE_MULTI_QUEUE */
+
+void    print_egiga_stat(void *sc, unsigned int port);
+void    ethPortStatus(int port);
+void    ethPortQueues(int port, int rxQueue, int txQueue, int mode);
+void    ethPortMcast(int port);
+void    ethPortRegs(int port);
+void    ethPortCounters(int port);
+void 	ethPortRmonCounters(int port);
+void    ethRxCoal(int port, int usec);
+void    ethTxCoal(int port, int usec);
+
+void    ethRegs(int port);
+void	ethClearCounters(int port);
+void    ethUcastSet(int port, char *macStr, int queue);
+void    ethPortUcastShow(int port);
+
+#ifdef CONFIG_MV_ETH_HEADER
+void	run_com_header(const char *buffer);
+#endif
+
+#ifdef INCLUDE_MULTI_QUEUE
+void    ethRxPolMode(int port, MV_ETH_PRIO_MODE prioMode);
+void    ethRxPolQ(int port, int queue, int quota);
+void    ethRxPolicy(int port);
+void    ethTxPolDef(int port, int txQ, char *headerHexStr);
+void    ethTxPolDA(int port, char *macStr, int txQ, char *headerHexStr);
+void    ethTxPolicy(int port);
+#endif /* INCLUDE_MULTI_QUEUE */
+
+#if (MV_ETH_VERSION >= 4)
+void     ethEjpModeSet(int port, int mode)
+#endif
+#endif /* 0 */
+
+
+
+
+void    ethRxCoal(int port, int usec);
+void    ethTxCoal(int port, int usec);
+#if (MV_ETH_VERSION >= 4)
+void     ethEjpModeSet(int port, int mode);
+#endif /* (MV_ETH_VERSION >= 4) */
+
+void    ethBpduRxQ(int port, int bpduQueue);
+void    ethArpRxQ(int port, int arpQueue);
+void    ethTcpRxQ(int port, int tcpQueue);
+void    ethUdpRxQ(int port, int udpQueue);
+void    ethTxPolicyRegs(int port);
+void    ethPortRegs(int port);
+void    ethRegs(int port);
+void ethClearCounters(int port);
+void    ethPortCounters(int port);
+void    ethPortRmonCounters(int port);
+void    ethPortStatus(int port);
+void    ethPortQueues(int port, int rxQueue, int txQueue, int mode);
+void    ethUcastSet(int port, char *macStr, int queue);
+void    ethPortUcastShow(int port);
+void    ethMcastAdd(int port, char *macStr, int queue);
+void    ethPortMcast(int port);
+void    mvEthPortShow(void *pHndl);
+void    mvEthQueuesShow(void *pHndl, int rxQueue, int txQueue, int mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthGbe.h b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthGbe.h
new file mode 100755
index 0000000..5352444
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthGbe.h
@@ -0,0 +1,746 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvEth.h - Header File for : Marvell Gigabit Ethernet Controller
+*
+* DESCRIPTION:
+*	This header file contains macros typedefs and function declaration specific to
+*	the Marvell Gigabit Ethernet Controller.
+*
+* DEPENDENCIES:
+*	None.
+*
+*******************************************************************************/
+
+#ifndef __mvEthGbe_h__
+#define __mvEthGbe_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "eth/mvEth.h"
+
+extern MV_BOOL ethDescInSram;
+extern MV_BOOL ethDescSwCoher;
+extern ETH_PORT_CTRL *ethPortCtrl[];
+
+static INLINE MV_ULONG ethDescVirtToPhy(ETH_QUEUE_CTRL *pQueueCtrl, MV_U8 *pDesc)
+{
+#if defined(ETH_DESCR_IN_SRAM)
+	if (ethDescInSram)
+		return mvSramVirtToPhy(pDesc);
+	else
+#endif	/* ETH_DESCR_IN_SRAM */
+		return (pQueueCtrl->descBuf.bufPhysAddr + (pDesc - pQueueCtrl->descBuf.bufVirtPtr));
+}
+
+/* Return port handler */
+#define mvEthPortHndlGet(port)  ethPortCtrl[port]
+/* Used as WA for HW/SW race on TX */
+static INLINE int mvEthPortTxEnable(void *pPortHndl, int queue, int max_deep)
+{
+	int deep = 0;
+	MV_U32 txCurrReg, txEnReg;
+	ETH_TX_DESC *pTxLastDesc;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+
+	txEnReg = MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo));
+	if ((txEnReg & MV_32BIT_LE_FAST(ETH_TXQ_ENABLE_MASK)) == 0) {
+		MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) = pPortCtrl->portTxQueueCmdReg;
+		return 0;
+	}
+	pQueueCtrl = &pPortCtrl->txQueue[queue];
+	pTxLastDesc = pQueueCtrl->pCurrentDescr;
+	txCurrReg = MV_REG_READ(ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue));
+	if (ethDescVirtToPhy(pQueueCtrl, (MV_U8 *) pTxLastDesc) == txCurrReg) {
+		/* All descriptors are processed, no chance for race */
+		return 0;
+	}
+
+	/* Check distance betwee HW and SW location: */
+	/* If distance between HW and SW pointers is less than max_deep descriptors */
+	/* Race condition is possible, so wait end of TX and restart TXQ */
+	while (deep < max_deep) {
+		pTxLastDesc = TX_PREV_DESC_PTR(pTxLastDesc, pQueueCtrl);
+		if (ethDescVirtToPhy(pQueueCtrl, (MV_U8 *) pTxLastDesc) == txCurrReg) {
+			int count = 0;
+			while ((txEnReg & MV_32BIT_LE_FAST(ETH_TXQ_ENABLE_MASK)) != 0) {
+				count++;
+				if (count > 10000) {
+					mvOsPrintf("mvEthPortTxEnable: timeout - TXQ_CMD=0x%08x\n",
+						   MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)));
+					break;
+				}
+				txEnReg = MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo));
+			}
+			MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) =
+				pPortCtrl->portTxQueueCmdReg;
+			return count;
+		}
+		deep++;
+	}
+	/* Distance between HW and SW pointers is more than max_deep descriptors, */
+	/* So NO race condition - do nothing */
+	return -1;
+}
+
+/* defines  */
+#define ETH_CSUM_MIN_BYTE_COUNT     72
+
+/* Tailgate and Kirwood have only 2K TX FIFO */
+#if (MV_ETH_VERSION == 2) || (MV_ETH_VERSION == 4)
+#define ETH_CSUM_MAX_BYTE_COUNT     1600
+#else
+#define ETH_CSUM_MAX_BYTE_COUNT     (9*1024)
+#endif /* MV_ETH_VERSION */
+
+#define ETH_MV_HEADER_SIZE	    2
+#define ETH_MV_TX_EN
+
+/* An offest in Tx descriptors to store data for buffers less than 8 Bytes */
+#define MIN_TX_BUFF_LOAD            8
+#define TX_BUF_OFFSET_IN_DESC       (ETH_TX_DESC_ALIGNED_SIZE - MIN_TX_BUFF_LOAD)
+
+/* Default port configuration value */
+#define PORT_CONFIG_VALUE                       \
+	(ETH_DEF_RX_QUEUE_MASK(0)       |   \
+	ETH_DEF_RX_ARP_QUEUE_MASK(0)   |   \
+	ETH_DEF_RX_TCP_QUEUE_MASK(0)   |   \
+	ETH_DEF_RX_UDP_QUEUE_MASK(0)   |   \
+	ETH_DEF_RX_BPDU_QUEUE_MASK(0)  |   \
+	ETH_RX_CHECKSUM_WITH_PSEUDO_HDR)
+
+/* Default port extend configuration value */
+#define PORT_CONFIG_EXTEND_VALUE            0
+
+#define PORT_SERIAL_CONTROL_VALUE                           \
+	(ETH_DISABLE_FC_AUTO_NEG_MASK                |   \
+	BIT9                                        |   \
+	ETH_DO_NOT_FORCE_LINK_FAIL_MASK             |   \
+	ETH_MAX_RX_PACKET_1552BYTE                  |   \
+	ETH_SET_FULL_DUPLEX_MASK)
+
+#define PORT_SERIAL_CONTROL_100MB_FORCE_VALUE               \
+	(ETH_FORCE_LINK_PASS_MASK                    |   \
+	ETH_DISABLE_DUPLEX_AUTO_NEG_MASK            |   \
+	ETH_DISABLE_FC_AUTO_NEG_MASK                |   \
+	BIT9                                        |   \
+	ETH_DO_NOT_FORCE_LINK_FAIL_MASK             |   \
+	ETH_DISABLE_SPEED_AUTO_NEG_MASK             |   \
+	ETH_SET_FULL_DUPLEX_MASK                    |   \
+	ETH_SET_MII_SPEED_100_MASK                  |   \
+	ETH_MAX_RX_PACKET_1552BYTE)
+
+#define PORT_SERIAL_CONTROL_1000MB_FORCE_VALUE              \
+	(ETH_FORCE_LINK_PASS_MASK                    |   \
+	ETH_DISABLE_DUPLEX_AUTO_NEG_MASK            |   \
+	ETH_DISABLE_FC_AUTO_NEG_MASK                |   \
+	BIT9                                        |   \
+	ETH_DO_NOT_FORCE_LINK_FAIL_MASK             |   \
+	ETH_DISABLE_SPEED_AUTO_NEG_MASK             |   \
+	ETH_SET_FULL_DUPLEX_MASK                    |   \
+	ETH_SET_GMII_SPEED_1000_MASK                |   \
+	ETH_MAX_RX_PACKET_1552BYTE)
+
+#define PORT_SERIAL_CONTROL_SGMII_IBAN_VALUE                \
+	(ETH_DISABLE_FC_AUTO_NEG_MASK                |   \
+	BIT9                                        |   \
+	ETH_IN_BAND_AN_EN_MASK                      |   \
+	ETH_DO_NOT_FORCE_LINK_FAIL_MASK             |   \
+	ETH_MAX_RX_PACKET_1552BYTE)
+
+/* Function headers: */
+MV_VOID mvEthSetSpecialMcastTable(int portNo, int queue);
+MV_STATUS mvEthArpRxQueue(void *pPortHandle, int arpQueue);
+MV_STATUS mvEthUdpRxQueue(void *pPortHandle, int udpQueue);
+MV_STATUS mvEthTcpRxQueue(void *pPortHandle, int tcpQueue);
+MV_STATUS mvEthMacAddrGet(int portNo, unsigned char *pAddr);
+MV_VOID mvEthSetOtherMcastTable(int portNo, int queue);
+MV_STATUS mvEthHeaderModeSet(void *pPortHandle, MV_ETH_HEADER_MODE headerMode);
+/* Interrupt Coalesting functions */
+MV_U32 mvEthRxCoalSet(void *pPortHndl, MV_U32 uSec);
+MV_U32 mvEthTxCoalSet(void *pPortHndl, MV_U32 uSec);
+MV_STATUS mvEthCoalGet(void *pPortHndl, MV_U32 *pRxCoal, MV_U32 *pTxCoal);
+
+/******************************************************************************/
+/*                          Data Flow functions                               */
+/******************************************************************************/
+static INLINE void mvEthPortTxRestart(void *pPortHndl)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) = pPortCtrl->portTxQueueCmdReg;
+}
+
+/* Get number of Free resources in specific TX queue */
+static INLINE int mvEthTxResourceGet(void *pPortHndl, int txQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	return (pPortCtrl->txQueue[txQueue].resource);
+}
+
+/* Get number of Free resources in specific RX queue */
+static INLINE int mvEthRxResourceGet(void *pPortHndl, int rxQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	return (pPortCtrl->rxQueue[rxQueue].resource);
+}
+
+static INLINE int mvEthTxQueueIsFull(void *pPortHndl, int txQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+
+	if (pPortCtrl->txQueue[txQueue].resource == 0)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+/* Get number of Free resources in specific RX queue */
+static INLINE int mvEthRxQueueIsFull(void *pPortHndl, int rxQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->rxQueue[rxQueue];
+
+	if ((pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && (pQueueCtrl->resource != 0))
+		return MV_TRUE;
+	return MV_FALSE;
+}
+
+static INLINE int mvEthTxQueueIsEmpty(void *pPortHndl, int txQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->txQueue[txQueue];
+	if ((pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && (pQueueCtrl->resource != 0))
+		return MV_TRUE;
+	return MV_FALSE;
+}
+
+/* Get number of Free resources in specific RX queue */
+static INLINE int mvEthRxQueueIsEmpty(void *pPortHndl, int rxQueue)
+{
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pPortHndl;
+
+	if (pPortCtrl->rxQueue[rxQueue].resource == 0)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvEthPortTx - Send an Ethernet packet
+*
+* DESCRIPTION:
+*	This routine send a given packet described by pPktInfo parameter.
+*	Single buffer only.
+*
+* INPUT:
+*       void*       pEthPortHndl  - Ethernet Port handler.
+*       int         txQueue       - Number of Tx queue.
+*       MV_PKT_INFO *pPktInfo     - User packet to send.
+*
+* RETURN:
+*       MV_NO_RESOURCE  - No enough resources to send this packet.
+*       MV_ERROR        - Unexpected Fatal error.
+*       MV_OK           - Packet send successfully.
+*
+*******************************************************************************/
+static INLINE MV_STATUS mvEthPortTx(void *pEthPortHndl, int txQueue, MV_PKT_INFO *pPktInfo)
+{
+	ETH_TX_DESC *pTxCurrDesc;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	int portNo;
+	MV_BUF_INFO *pBufInfo = pPktInfo->pFrags;
+
+#ifdef ETH_DEBUG
+	if (pPortCtrl->portState != MV_ACTIVE)
+		return MV_BAD_STATE;
+#endif /* ETH_DEBUG */
+
+	portNo = pPortCtrl->portNo;
+	pQueueCtrl = &pPortCtrl->txQueue[txQueue];
+
+	/* Get the Tx Desc ring indexes */
+	pTxCurrDesc = pQueueCtrl->pCurrentDescr;
+
+	/* Check if there is enough resources to send the packet */
+	if (pQueueCtrl->resource == 0)
+		return MV_NO_RESOURCE;
+
+#ifdef MV_LEGACY_ETH_WA
+	while (MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(portNo)) & (1 << txQueue))
+		continue;
+	MV_REG_WRITE(ETH_TX_CUR_DESC_PTR_REG(portNo, txQueue),
+			(MV_U32) ethDescVirtToPhy(pQueueCtrl, (MV_U8 *)pTxCurrDesc));
+#endif
+
+	ETH_SET_16B_DESCR_VAL(pTxCurrDesc->byteCnt, pBufInfo->dataSize);
+
+	/* Flash Buffer */
+	if (pPktInfo->pktSize != 0) {
+#ifdef MV_NETBSD
+		ETH_SET_32B_DESCR_VAL(pTxCurrDesc->bufPtr, pBufInfo->bufPhysAddr);
+		ETH_PACKET_CACHE_FLUSH(pBufInfo->bufVirtPtr, pPktInfo->pktSize);
+#else /* MV_NETBSD */
+		ETH_SET_32B_DESCR_VAL(pTxCurrDesc->bufPtr,
+				      ETH_PACKET_CACHE_FLUSH(pBufInfo->bufVirtPtr, pPktInfo->pktSize));
+#endif /* MV_NETBSD */
+		pPktInfo->pktSize = 0;
+	} else
+		ETH_SET_32B_DESCR_VAL(pTxCurrDesc->bufPtr, pBufInfo->bufPhysAddr);
+
+	ETH_SET_32B_DESCR_VAL(pTxCurrDesc->returnInfo, (MV_ULONG) pPktInfo);
+
+	/* There is only one buffer in the packet */
+	/* The OSG might set some bits for checksum offload, so add them to first descriptor */
+	ETH_SET_32B_DESCR_VAL(pTxCurrDesc->cmdSts,
+			      pPktInfo->status |
+			      ETH_BUFFER_OWNED_BY_DMA |
+			      ETH_TX_GENERATE_CRC_MASK |
+			      ETH_TX_ENABLE_INTERRUPT_MASK |
+			      ETH_TX_ZERO_PADDING_MASK | ETH_TX_FIRST_DESC_MASK | ETH_TX_LAST_DESC_MASK);
+
+	ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc);
+
+	pQueueCtrl->resource--;
+	pQueueCtrl->pCurrentDescr = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl);
+
+	/* Apply send command */
+	MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(portNo)) = pPortCtrl->portTxQueueCmdReg;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPortSgTx - Send an Ethernet packet
+*
+* DESCRIPTION:
+*       This routine send a given packet described by pBufInfo parameter. It
+*       supports transmitting of a packet spaned over multiple buffers.
+*
+* INPUT:
+*       void*       pEthPortHndl  - Ethernet Port handler.
+*       int         txQueue       - Number of Tx queue.
+*       MV_PKT_INFO *pPktInfo     - User packet to send.
+*
+* RETURN:
+*       MV_NO_RESOURCE  - No enough resources to send this packet.
+*       MV_ERROR        - Unexpected Fatal error.
+*       MV_OK           - Packet send successfully.
+*
+*******************************************************************************/
+static INLINE MV_STATUS mvEthPortSgTx(void *pEthPortHndl, int txQueue, MV_PKT_INFO *pPktInfo)
+{
+	ETH_TX_DESC *pTxFirstDesc;
+	ETH_TX_DESC *pTxCurrDesc;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	int portNo, bufCount;
+	MV_BUF_INFO *pBufInfo = pPktInfo->pFrags;
+	MV_U8 *pTxBuf;
+
+#ifdef ETH_DEBUG
+	if (pPortCtrl->portState != MV_ACTIVE)
+		return MV_BAD_STATE;
+#endif /* ETH_DEBUG */
+
+	portNo = pPortCtrl->portNo;
+	pQueueCtrl = &pPortCtrl->txQueue[txQueue];
+
+	/* Get the Tx Desc ring indexes */
+	pTxCurrDesc = pQueueCtrl->pCurrentDescr;
+
+	/* Check if there is enough resources to send the packet */
+	if (pQueueCtrl->resource < pPktInfo->numFrags)
+		return MV_NO_RESOURCE;
+
+	/* Remember first desc */
+	pTxFirstDesc = pTxCurrDesc;
+
+	bufCount = 0;
+	while (MV_TRUE) {
+		if (pBufInfo[bufCount].dataSize <= MIN_TX_BUFF_LOAD) {
+			/* Buffers with a payload smaller than MIN_TX_BUFF_LOAD (8 bytes) must be aligned    */
+			/* to 64-bit boundary. Two options here:                                             */
+			/* 1) Usually, copy the payload to the reserved 8 bytes inside descriptor.           */
+			/* 2) In the Half duplex workaround, the reserved 8 bytes inside descriptor are used */
+			/*    as a pointer to the aligned buffer, copy the small payload to this buffer.     */
+			pTxBuf = ((MV_U8 *) pTxCurrDesc) + TX_BUF_OFFSET_IN_DESC;
+			mvOsBCopy(pBufInfo[bufCount].bufVirtPtr, pTxBuf, pBufInfo[bufCount].dataSize);
+			ETH_SET_32B_DESCR_VAL(pTxCurrDesc->bufPtr, ethDescVirtToPhy(pQueueCtrl, pTxBuf));
+		} else {
+			/* Flash Buffer */
+#ifdef MV_NETBSD
+			ETH_SET_32B_DESCR_VAL(pTxCurrDesc->bufPtr, pBufInfo[bufCount].bufPhysAddr);
+			ETH_PACKET_CACHE_FLUSH(pBufInfo[bufCount].bufVirtPtr, pBufInfo[bufCount].dataSize);
+#else
+			ETH_SET_32B_DESCR_VAL(pTxCurrDesc->bufPtr,
+					      ETH_PACKET_CACHE_FLUSH(pBufInfo[bufCount].bufVirtPtr,
+								     pBufInfo[bufCount].dataSize));
+#endif
+		}
+
+		ETH_SET_16B_DESCR_VAL(pTxCurrDesc->byteCnt, pBufInfo[bufCount].dataSize);
+		bufCount++;
+
+		if (bufCount >= pPktInfo->numFrags)
+			break;
+
+		if (bufCount > 1) {
+			/* There is middle buffer of the packet Not First and Not Last */
+			ETH_SET_32B_DESCR_VAL(pTxCurrDesc->cmdSts, ETH_BUFFER_OWNED_BY_DMA);
+			ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc);
+		}
+		/* Go to next descriptor and next buffer */
+		pTxCurrDesc = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl);
+	}		/* while not last */
+
+	/* Set last desc with DMA ownership and interrupt enable. */
+	ETH_SET_32B_DESCR_VAL(pTxCurrDesc->returnInfo, (MV_ULONG) pPktInfo);
+	if (bufCount == 1) {
+		/* There is only one buffer in the packet */
+		/* The OSG might set some bits for checksum offload, so add them to first descriptor */
+		ETH_SET_32B_DESCR_VAL(pTxCurrDesc->cmdSts,
+				      pPktInfo->status |
+				      ETH_BUFFER_OWNED_BY_DMA |
+				      ETH_TX_GENERATE_CRC_MASK |
+				      ETH_TX_ENABLE_INTERRUPT_MASK |
+				      ETH_TX_ZERO_PADDING_MASK | ETH_TX_FIRST_DESC_MASK |
+				      ETH_TX_LAST_DESC_MASK);
+	} else {
+		/* Last but not First */
+		ETH_SET_32B_DESCR_VAL(pTxCurrDesc->cmdSts,
+				      ETH_BUFFER_OWNED_BY_DMA |
+				      ETH_TX_ENABLE_INTERRUPT_MASK | ETH_TX_ZERO_PADDING_MASK |
+				      ETH_TX_LAST_DESC_MASK);
+
+		/* Update First when more than one buffer in the packet */
+		/* The OSG might set some bits for checksum offload, so add them to first descriptor */
+		ETH_SET_32B_DESCR_VAL(pTxFirstDesc->cmdSts,
+				      pPktInfo->status |
+				      ETH_BUFFER_OWNED_BY_DMA | ETH_TX_GENERATE_CRC_MASK |
+				      ETH_TX_FIRST_DESC_MASK);
+
+		ETH_DESCR_FLUSH_INV(pPortCtrl, pTxFirstDesc);
+	}
+
+	ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc);
+
+	/* Update txQueue state */
+	pQueueCtrl->resource -= bufCount;
+	pQueueCtrl->pCurrentDescr = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl);
+
+	/* Apply send command */
+	MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(portNo)) = pPortCtrl->portTxQueueCmdReg;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvEthPortTxDone - Free all used Tx descriptors and mBlks.
+*
+* DESCRIPTION:
+*       This routine returns the transmitted packet information to the caller.
+*
+* INPUT:
+*       void*       pEthPortHndl    - Ethernet Port handler.
+*       int         txQueue         - Number of Tx queue.
+*
+* OUTPUT:
+*       MV_PKT_INFO *pPktInfo       - Pointer to packet was sent.
+*
+* RETURN:
+*       MV_NOT_FOUND    - No transmitted packets to return. Transmit in progress.
+*       MV_EMPTY        - No transmitted packets to return. TX Queue is empty.
+*       MV_ERROR        - Unexpected Fatal error.
+*       MV_OK           - There is transmitted packet in the queue,
+*                       'pPktInfo' filled with relevant information.
+*
+*******************************************************************************/
+static INLINE MV_PKT_INFO *mvEthPortTxDone(void *pEthPortHndl, int txQueue)
+{
+	ETH_TX_DESC *pTxCurrDesc;
+	ETH_TX_DESC *pTxUsedDesc;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	MV_PKT_INFO *pPktInfo;
+	MV_U32 commandStatus;
+
+	pQueueCtrl = &pPortCtrl->txQueue[txQueue];
+
+	pTxUsedDesc = pQueueCtrl->pUsedDescr;
+	pTxCurrDesc = pQueueCtrl->pCurrentDescr;
+
+	while (MV_TRUE) {
+		/* No more used descriptors */
+		commandStatus = ETH_GET_32B_DESCR_VAL(pTxUsedDesc->cmdSts);
+		if (commandStatus & (ETH_BUFFER_OWNED_BY_DMA)) {
+			ETH_DESCR_INV(pPortCtrl, pTxUsedDesc);
+			return NULL;
+		}
+		if ((pTxUsedDesc == pTxCurrDesc) && (pQueueCtrl->resource != 0))
+			return NULL;
+
+		pQueueCtrl->resource++;
+		pQueueCtrl->pUsedDescr = TX_NEXT_DESC_PTR(pTxUsedDesc, pQueueCtrl);
+		if (commandStatus & (ETH_TX_LAST_DESC_MASK)) {
+			pPktInfo = (MV_PKT_INFO *) ETH_GET_32B_DESCR_VAL(pTxUsedDesc->returnInfo);
+			pPktInfo->status = commandStatus;
+			return pPktInfo;
+		}
+		pTxUsedDesc = pQueueCtrl->pUsedDescr;
+	}
+}
+
+/*******************************************************************************
+* mvEthPortRx - Get new received packets from Rx queue.
+*
+* DESCRIPTION:
+*       This routine returns the received data to the caller. There is no
+*       data copying during routine operation. All information is returned
+*       using pointer to packet information struct passed from the caller.
+*
+* INPUT:
+*       void*       pEthPortHndl    - Ethernet Port handler.
+*       int         rxQueue         - Number of Rx queue.
+*
+* OUTPUT:
+*       MV_PKT_INFO *pPktInfo       - Pointer to received packet.
+*
+* RETURN:
+*       MV_NO_RESOURCE  - No free resources in RX queue.
+*       MV_ERROR        - Unexpected Fatal error.
+*       MV_OK           - New packet received and 'pBufInfo' structure filled
+*                       with relevant information.
+*
+*******************************************************************************/
+static INLINE MV_PKT_INFO *mvEthPortRx(void *pEthPortHndl, int rxQueue)
+{
+	ETH_RX_DESC *pRxCurrDesc;
+	MV_U32 commandStatus;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	MV_PKT_INFO *pPktInfo;
+
+	pQueueCtrl = &(pPortCtrl->rxQueue[rxQueue]);
+
+	/* Check resources */
+	if (pQueueCtrl->resource == 0) {
+		mvOsPrintf("ethPortRx: no more resources\n");
+		return NULL;
+	}
+	while (MV_TRUE) {
+		/* Get the Rx Desc ring 'curr and 'used' indexes */
+		pRxCurrDesc = pQueueCtrl->pCurrentDescr;
+
+		commandStatus = ETH_GET_32B_DESCR_VAL(pRxCurrDesc->cmdSts);
+		if (commandStatus & (ETH_BUFFER_OWNED_BY_DMA)) {
+			/* Nothing to receive... */
+			ETH_DESCR_INV(pPortCtrl, pRxCurrDesc);
+			return NULL;
+		}
+
+		/* Valid RX only if FIRST and LAST bits are set */
+		if ((commandStatus & (ETH_RX_LAST_DESC_MASK | ETH_RX_FIRST_DESC_MASK)) ==
+		    (ETH_RX_LAST_DESC_MASK | ETH_RX_FIRST_DESC_MASK)) {
+			pPktInfo = (MV_PKT_INFO *) ETH_GET_32B_DESCR_VAL(pRxCurrDesc->returnInfo);
+			pPktInfo->pFrags->dataSize = ETH_GET_16B_DESCR_VAL(pRxCurrDesc->byteCnt) - 4;
+			pPktInfo->status = commandStatus;
+			pPktInfo->fragIP =
+			    ETH_GET_16B_DESCR_VAL(pRxCurrDesc->bufSize) & ETH_RX_IP_FRAGMENTED_FRAME_MASK;
+
+			pQueueCtrl->resource--;
+			/* Update 'curr' in data structure */
+				pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxCurrDesc, pQueueCtrl);
+
+#ifdef INCLUDE_SYNC_BARR
+			mvCpuIfSyncBarr(DRAM_TARGET);
+#endif
+			return pPktInfo;
+		} else {
+			ETH_RX_DESC *pRxUsedDesc = pQueueCtrl->pUsedDescr;
+
+#ifdef ETH_DEBUG
+			mvOsPrintf("ethDrv: Unexpected Jumbo frame: "
+				   "status=0x%08x, byteCnt=%d, pData=0x%x\n",
+				   commandStatus, ETH_GET_16B_DESCR_VAL(pRxCurrDesc->byteCnt),
+				   ETH_GET_32B_DESCR_VAL(pRxCurrDesc->bufPtr));
+#endif /* ETH_DEBUG */
+
+			/* move buffer from pCurrentDescr position to pUsedDescr position */
+			pRxUsedDesc->bufPtr = pRxCurrDesc->bufPtr;
+			pRxUsedDesc->returnInfo = pRxCurrDesc->returnInfo;
+			pRxUsedDesc->bufSize = pRxCurrDesc->bufSize & ETH_RX_BUFFER_MASK;
+
+			/* Return the descriptor to DMA ownership */
+			ETH_SET_32B_DESCR_VAL(pRxUsedDesc->cmdSts,
+					      ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT_MASK);
+
+			/* Flush descriptor and CPU pipe */
+			ETH_DESCR_FLUSH_INV(pPortCtrl, pRxUsedDesc);
+
+			/* Move the used descriptor pointer to the next descriptor */
+			pQueueCtrl->pUsedDescr = RX_NEXT_DESC_PTR(pRxUsedDesc, pQueueCtrl);
+			pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxCurrDesc, pQueueCtrl);
+		}
+	}
+}
+
+/*******************************************************************************
+* mvEthPortRxDoneTest - Returns a Rx buffer back to the Rx ring.
+*
+* DESCRIPTION:
+*       This routine performs a diagnostic for Rx buffer
+*
+*******************************************************************************/
+static INLINE void mvEthRxDoneTest(MV_BUF_INFO *pBuf, MV_U32 alignment)
+{
+	MV_U32 va = (MV_U32) pBuf->bufVirtPtr;
+	MV_U32 pa = (MV_U32) pBuf->bufPhysAddr;
+
+	/*
+	 * Check the manipulation of pBuf is properly done prior to RxDone
+	 */
+	if (((va & 0xFF) != alignment) || ((pa & 0xFF) != alignment) || pBuf->bufAddrShift) {
+		mvOsPrintf("mvRxDoneTest: pBuf=%p va=%x pa=%x shift=%d\n", pBuf, va, pa, pBuf->bufAddrShift);
+		/* dump_stack() */
+	}
+}
+
+/*******************************************************************************
+* mvEthPortRxDone - Returns a Rx buffer back to the Rx ring.
+*
+* DESCRIPTION:
+*       This routine returns a Rx buffer back to the Rx ring.
+*
+* INPUT:
+*       void*       pEthPortHndl    - Ethernet Port handler.
+*       int         rxQueue         - Number of Rx queue.
+*       MV_PKT_INFO *pPktInfo       - Pointer to received packet.
+*
+* RETURN:
+*       MV_ERROR        - Unexpected Fatal error.
+*       MV_OUT_OF_RANGE - RX queue is already FULL, so this buffer can't be
+*                       returned to this queue.
+*       MV_FULL         - Buffer returned successfully and RX queue became full.
+*                       More buffers should not be returned at the time.
+*       MV_OK           - Buffer returned successfully and there are more free
+*                       places in the queue.
+*
+*******************************************************************************/
+static INLINE MV_STATUS mvEthPortRxDone(void *pEthPortHndl, int rxQueue, MV_PKT_INFO *pPktInfo)
+{
+	ETH_RX_DESC *pRxUsedDesc;
+	ETH_QUEUE_CTRL *pQueueCtrl;
+	ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL *) pEthPortHndl;
+
+/*
+	for debug:
+	mvEthRxDoneTest(pPktInfo->pFrags, CONFIG_NET_SKB_HEADROOM);
+*/
+	pQueueCtrl = &pPortCtrl->rxQueue[rxQueue];
+
+	/* Get 'used' Rx descriptor */
+	pRxUsedDesc = pQueueCtrl->pUsedDescr;
+
+	/* Check that ring is not FULL */
+	if ((pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && (pQueueCtrl->resource != 0)) {
+		mvOsPrintf("%s %d: out of range Error resource=%d, curr=%p, used=%p\n",
+			   __func__, pPortCtrl->portNo, pQueueCtrl->resource,
+			   pQueueCtrl->pCurrentDescr, pQueueCtrl->pUsedDescr);
+		return MV_OUT_OF_RANGE;
+	}
+
+	ETH_SET_32B_DESCR_VAL(pRxUsedDesc->bufPtr, pPktInfo->pFrags->bufPhysAddr);
+	ETH_SET_32B_DESCR_VAL(pRxUsedDesc->returnInfo, (MV_ULONG) pPktInfo);
+	ETH_SET_16B_DESCR_VAL(pRxUsedDesc->bufSize, pPktInfo->pFrags->bufSize & ETH_RX_BUFFER_MASK);
+
+	/* Invalidate data buffer accordingly with pktSize */
+	if (pPktInfo->pktSize != 0) {
+		ETH_PACKET_CACHE_INVALIDATE(pPktInfo->pFrags->bufVirtPtr, pPktInfo->pktSize);
+		pPktInfo->pktSize = 0;
+	}
+
+	/* Return the descriptor to DMA ownership */
+	ETH_SET_32B_DESCR_VAL(pRxUsedDesc->cmdSts, ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT_MASK);
+
+	/* Flush descriptor and CPU pipe */
+	ETH_DESCR_FLUSH_INV(pPortCtrl, pRxUsedDesc);
+
+	pQueueCtrl->resource++;
+
+	/* Move the used descriptor pointer to the next descriptor */
+	pQueueCtrl->pUsedDescr = RX_NEXT_DESC_PTR(pRxUsedDesc, pQueueCtrl);
+
+	/* If ring became Full return MV_FULL */
+	if (pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr)
+		return MV_FULL;
+
+	return MV_OK;
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __mvEthGbe_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthRegs.h b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthRegs.h
new file mode 100755
index 0000000..63a8f1f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/gbe/mvEthRegs.h
@@ -0,0 +1,811 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __INCmvEthRegsh
+#define __INCmvEthRegsh
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "mvSysEthConfig.h"
+
+#define ETH_MAX_DECODE_WIN              6
+#define ETH_MAX_HIGH_ADDR_REMAP_WIN     4
+
+/****************************************/
+/*        Ethernet Unit Registers       */
+/****************************************/
+#define ETH_PHY_ADDR_REG(port)              (MV_ETH_REGS_BASE(port) + 0x000)
+#define ETH_SMI_REG(port)                   (MV_ETH_REGS_BASE(port) + 0x004)
+#define ETH_UNIT_DEF_ADDR_REG(port)         (MV_ETH_REGS_BASE(port) + 0x008)
+#define ETH_UNIT_DEF_ID_REG(port)           (MV_ETH_REGS_BASE(port) + 0x00c)
+#define ETH_UNIT_RESERVED(port)             (MV_ETH_REGS_BASE(port) + 0x014)
+#define ETH_UNIT_INTR_CAUSE_REG(port)       (MV_ETH_REGS_BASE(port) + 0x080)
+#define ETH_UNIT_INTR_MASK_REG(port)        (MV_ETH_REGS_BASE(port) + 0x084)
+
+
+#define ETH_UNIT_ERROR_ADDR_REG(port)       (MV_ETH_REGS_BASE(port) + 0x094)
+#define ETH_UNIT_INT_ADDR_ERROR_REG(port)   (MV_ETH_REGS_BASE(port) + 0x098)
+
+/* Ethernet Unit Control (EUC) register */
+#define ETH_UNIT_CONTROL_REG(port)          (MV_ETH_REGS_BASE(port) + 0x0B0)
+
+#define ETH_PHY_POLLING_ENABLE_BIT	        1
+#define ETH_PHY_POLLING_ENABLE_MASK	        (1 << ETH_PHY_POLLING_ENABLE_BIT)
+
+#define ETH_PORT_RESET_BIT                  24
+#define ETH_PORT_RESET_MASK                 (1 << ETH_PORT_RESET_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+/**** Address decode registers ****/
+
+#define ETH_WIN_BASE_REG(port, win)         (MV_ETH_REGS_BASE(port) + 0x200 + ((win)<<3))
+#define ETH_WIN_SIZE_REG(port, win)         (MV_ETH_REGS_BASE(port) + 0x204 + ((win)<<3))
+#define ETH_WIN_REMAP_REG(port, win)        (MV_ETH_REGS_BASE(port) + 0x280 + ((win)<<2))
+#define ETH_BASE_ADDR_ENABLE_REG(port)      (MV_ETH_REGS_BASE(port) + 0x290)
+#define ETH_ACCESS_PROTECT_REG(port)        (MV_ETH_REGS_BASE(port) + 0x294)
+
+/* The target associated with this window	    */
+#define ETH_WIN_TARGET_OFFS             0
+#define ETH_WIN_TARGET_MASK             (0xf << ETH_WIN_TARGET_OFFS)
+/* The target attributes associated with window */
+#define ETH_WIN_ATTR_OFFS               8
+#define ETH_WIN_ATTR_MASK               (0xff << ETH_WIN_ATTR_OFFS)
+
+/* The Base address associated with window */
+#define ETH_WIN_BASE_OFFS		            16
+#define ETH_WIN_BASE_MASK		            (0xFFFF << ETH_WIN_BASE_OFFS)
+
+#define ETH_WIN_SIZE_OFFS		            16
+#define ETH_WIN_SIZE_MASK		            (0xFFFF << ETH_WIN_SIZE_OFFS)
+/* Ethernet Port Access Protect Register (EPAPR)    */
+#define ETH_PROT_NO_ACCESS                  0
+#define ETH_PROT_READ_ONLY                  1
+#define ETH_PROT_FULL_ACCESS                3
+#define ETH_PROT_WIN_OFFS(winNum)           (2 * (winNum))
+#define ETH_PROT_WIN_MASK(winNum)           (0x3 << ETH_PROT_WIN_OFFS(winNum))
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_PORT_CONFIG_REG(port)           (MV_ETH_REGS_BASE(port) + 0x400)
+#define ETH_PORT_CONFIG_EXTEND_REG(port)    (MV_ETH_REGS_BASE(port) + 0x404)
+
+#define ETH_VLAN_ETHER_TYPE_REG(port)       (MV_ETH_REGS_BASE(port) + 0x410)
+#define ETH_MAC_ADDR_LOW_REG(port)          (MV_ETH_REGS_BASE(port) + 0x414)
+#define ETH_MAC_ADDR_HIGH_REG(port)         (MV_ETH_REGS_BASE(port) + 0x418)
+#define ETH_SDMA_CONFIG_REG(port)           (MV_ETH_REGS_BASE(port) + 0x41c)
+#define ETH_DIFF_SERV_PRIO_REG(port, code)  (MV_ETH_REGS_BASE(port) + 0x420  + ((code)<<2))
+
+/* Port Serial Control0 register (PSC0) */
+#define ETH_PORT_SERIAL_CTRL_REG(port)      (MV_ETH_REGS_BASE(port) + 0x43c)
+
+#define ETH_TX_FC_MODE_OFFSET               5
+#define ETH_TX_FC_MODE_MASK                 (3 << ETH_TX_FC_MODE_OFFSET)
+#define ETH_TX_FC_NO_PAUSE                  (0 << ETH_TX_FC_MODE_OFFSET)
+#define ETH_TX_FC_SEND_PAUSE                (1 << ETH_TX_FC_MODE_OFFSET)
+
+#define ETH_TX_BP_MODE_OFFSET               7
+#define ETH_TX_BP_MODE_MASK                 (3 << ETH_TX_BP_MODE_OFFSET)
+#define ETH_TX_BP_NO_JAM                    (0 << ETH_TX_BP_MODE_OFFSET)
+#define ETH_TX_BP_SEND_JAM                  (1 << ETH_TX_BP_MODE_OFFSET)
+
+#define ETH_RETRANSMIT_FOREVER_BIT          11
+#define ETH_RETRANSMIT_FOREVER_MASK         (1 << ETH_RETRANSMIT_FOREVER_BIT)
+
+#define ETH_DTE_ADVERT_BIT                  14
+#define ETH_DTE_ADVERT_MASK                 (1 << ETH_DTE_ADVERT_BIT)
+
+#define ETH_IGNORE_RX_ERR_BIT               28
+#define ETH_IGNORE_RX_ERR_MASK              (1 << ETH_IGNORE_RX_ERR_BIT)
+
+#define ETH_IGNORE_COL_BIT                  29
+#define ETH_IGNORE_COL_MASK                 (1 << ETH_IGNORE_COL_BIT)
+
+#define ETH_IGNORE_CARRIER_SENSE_BIT        30
+#define ETH_IGNORE_CARRIER_SENSE_MASK       (1 << ETH_IGNORE_CARRIER_SENSE_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_VLAN_TAG_TO_PRIO_REG(port)      (MV_ETH_REGS_BASE(port) + 0x440)
+
+/***** Ethernet Port Status reg (PSR) *****/
+#define ETH_PORT_STATUS_REG(port)           (MV_ETH_REGS_BASE(port) + 0x444)
+
+#define ETH_TX_IN_PROGRESS_OFFS             0
+#define ETH_TX_IN_PROGRESS_MASK(txp)        (1 << ((txp) + ETH_TX_IN_PROGRESS_OFFS))
+#define ETH_TX_IN_PROGRESS_ALL_MASK         (0xFF << ETH_TX_IN_PROGRESS_OFFS)
+
+#define ETH_TX_FIFO_EMPTY_OFFS              8
+#define ETH_TX_FIFO_EMPTY_MASK(txp)         (1 << ((txp) + ETH_TX_FIFO_EMPTY_OFFS))
+#define ETH_TX_FIFO_EMPTY_ALL_MASK          (0xFF << ETH_TX_FIFO_EMPTY_OFFS)
+
+#define ETH_RX_FIFO_EMPTY_BIT               16
+#define ETH_RX_FIFO_EMPTY_MASK              (1 << ETH_RX_FIFO_EMPTY_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+
+/***** Transmit Queue Command (TxQC) register *****/
+#define ETH_TX_QUEUE_COMMAND_REG(port)      (MV_ETH_REGS_BASE(port) + 0x448)
+
+#define ETH_TXQ_ENABLE_OFFSET               0
+#define ETH_TXQ_ENABLE_MASK                 (0x000000FF << ETH_TXQ_ENABLE_OFFSET)
+
+#define ETH_TXQ_DISABLE_OFFSET              8
+#define ETH_TXQ_DISABLE_MASK                (0x000000FF << ETH_TXQ_DISABLE_OFFSET)
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_PORT_MARVELL_HEADER_REG(port)   (MV_ETH_REGS_BASE(port) + 0x454)
+#define ETH_MAX_TOKEN_BUCKET_SIZE_REG(port) (MV_ETH_REGS_BASE(port) + 0x45c)
+#define ETH_INTR_CAUSE_REG(port)            (MV_ETH_REGS_BASE(port) + 0x460)
+#define ETH_INTR_CAUSE_EXT_REG(port)        (MV_ETH_REGS_BASE(port) + 0x464)
+#define ETH_INTR_MASK_REG(port)             (MV_ETH_REGS_BASE(port) + 0x468)
+#define ETH_INTR_MASK_EXT_REG(port)         (MV_ETH_REGS_BASE(port) + 0x46c)
+#define ETH_TX_FIFO_URGENT_THRESH_REG(port) (MV_ETH_REGS_BASE(port) + 0x474)
+#define ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (MV_ETH_REGS_BASE(port) + 0x47c)
+#define ETH_RX_DISCARD_PKTS_CNTR_REG(port)  (MV_ETH_REGS_BASE(port) + 0x484)
+#define ETH_RX_OVERRUN_PKTS_CNTR_REG(port)  (MV_ETH_REGS_BASE(port) + 0x488)
+#define ETH_INTERNAL_ADDR_ERROR_REG(port)   (MV_ETH_REGS_BASE(port) + 0x494)
+#define ETH_TX_FIXED_PRIO_CFG_REG(port)     (MV_ETH_REGS_BASE(port) + 0x4dc)
+#define ETH_TX_TOKEN_RATE_CFG_REG(port)     (MV_ETH_REGS_BASE(port) + 0x4e0)
+#define ETH_TX_QUEUE_COMMAND1_REG(port)     (MV_ETH_REGS_BASE(port) + 0x4e4)
+#define ETH_MAX_TRANSMIT_UNIT_REG(port)     (MV_ETH_REGS_BASE(port) + 0x4e8)
+#define ETH_TX_TOKEN_BUCKET_SIZE_REG(port)  (MV_ETH_REGS_BASE(port) + 0x4ec)
+#define ETH_TX_TOKEN_BUCKET_COUNT_REG(port) (MV_ETH_REGS_BASE(port) + 0x780)
+#define ETH_RX_DESCR_STAT_CMD_REG(port, q)  (MV_ETH_REGS_BASE(port) + 0x600 + ((q)<<4))
+#define ETH_RX_BYTE_COUNT_REG(port, q)      (MV_ETH_REGS_BASE(port) + 0x604 + ((q)<<4))
+#define ETH_RX_BUF_PTR_REG(port, q)         (MV_ETH_REGS_BASE(port) + 0x608 + ((q)<<4))
+#define ETH_RX_CUR_DESC_PTR_REG(port, q)    (MV_ETH_REGS_BASE(port) + 0x60c + ((q)<<4))
+
+/***** Receive Queue Command (RxQC) register *****/
+#define ETH_RX_QUEUE_COMMAND_REG(port)      (MV_ETH_REGS_BASE(port) + 0x680)
+
+#define ETH_RXQ_ENABLE_OFFSET               0
+#define ETH_RXQ_ENABLE_MASK                 (0x000000FF << ETH_RXQ_ENABLE_OFFSET)
+
+#define ETH_RXQ_DISABLE_OFFSET              8
+#define ETH_RXQ_DISABLE_MASK                (0x000000FF << ETH_RXQ_DISABLE_OFFSET)
+/*-----------------------------------------------------------------------------------------------*/
+#define ETH_TX_CUR_DESC_PTR_REG(port, q)    (MV_ETH_REGS_BASE(port) + 0x6c0 + ((q)<<2))
+
+#define ETH_TXQ_TOKEN_COUNT_REG(port, q)    (MV_ETH_REGS_BASE(port) + 0x700 + ((q)<<4))
+#define ETH_TXQ_TOKEN_CFG_REG(port, q)      (MV_ETH_REGS_BASE(port) + 0x704 + ((q)<<4))
+#define ETH_TXQ_ARBITER_CFG_REG(port, q)    (MV_ETH_REGS_BASE(port) + 0x708 + ((q)<<4))
+
+#if (MV_ETH_VERSION >= 4)
+#define ETH_TXQ_CMD_1_REG(port)             (MV_ETH_REGS_BASE(port) + 0x4E4)
+#define ETH_EJP_TX_HI_IPG_REG(port)         (MV_ETH_REGS_BASE(port) + 0x7A8)
+#define ETH_EJP_TX_LO_IPG_REG(port)         (MV_ETH_REGS_BASE(port) + 0x7B8)
+#define ETH_EJP_HI_TKN_LO_PKT_REG(port)     (MV_ETH_REGS_BASE(port) + 0x7C0)
+#define ETH_EJP_HI_TKN_ASYNC_PKT_REG(port)  (MV_ETH_REGS_BASE(port) + 0x7C4)
+#define ETH_EJP_LO_TKN_ASYNC_PKT_REG(port)  (MV_ETH_REGS_BASE(port) + 0x7C8)
+#define ETH_EJP_TX_SPEED_REG(port)          (MV_ETH_REGS_BASE(port) + 0x7D0)
+#endif /* MV_ETH_VERSION >= 4 */
+
+
+/******* GigE MAC registers *******/
+#define NETA_REG_BASE(port) 				(MV_ETH_REGS_BASE(port) & ~0x2000)
+
+#define NETA_GMAC_CTRL_0_REG(p)             (NETA_REG_BASE(p) + 0x2C00)
+
+#define NETA_GMAC_PORT_EN_BIT               0
+#define NETA_GMAC_PORT_EN_MASK              (1 << NETA_GMAC_PORT_EN_BIT)
+
+#define NETA_GMAC_PORT_TYPE_BIT             1
+#define NETA_GMAC_PORT_TYPE_MASK            (1 << NETA_GMAC_PORT_TYPE_BIT)
+#define NETA_GMAC_PORT_TYPE_SGMII           (0 << NETA_GMAC_PORT_TYPE_BIT)
+#define NETA_GMAC_PORT_TYPE_1000X           (1 << NETA_GMAC_PORT_TYPE_BIT)
+
+#define NETA_GMAC_MAX_RX_SIZE_OFFS          2
+#define NETA_GMAC_MAX_RX_SIZE_MASK          (0x1FFF << NETA_GMAC_MAX_RX_SIZE_OFFS)
+
+#define NETA_GMAC_MIB_CNTR_EN_BIT           15
+#define NETA_GMAC_MIB_CNTR_EN_MASK          (1 << NETA_GMAC_MIB_CNTR_EN_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_GMAC_CTRL_1_REG(p)             (NETA_REG_BASE(p) + 0x2C04)
+
+#define NETA_GMAC_CTRL_2_REG(p)             (NETA_REG_BASE(p) + 0x2C08)
+
+#define NETA_GMAC_PORT_RGMII_BIT	    4
+#define NETA_GMAC_PORT_RGMII_MASK           (1 << NETA_GMAC_PORT_RGMII_BIT)
+
+#define NETA_GMAC_PORT_RESET_BIT            6
+#define NETA_GMAC_PORT_RESET_MASK           (1 << NETA_GMAC_PORT_RESET_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_GMAC_AN_CTRL_REG(p)                (NETA_REG_BASE(p) + 0x2C0C)
+
+#define NETA_FORCE_LINK_FAIL_BIT                0
+#define NETA_FORCE_LINK_FAIL_MASK               (1 << NETA_FORCE_LINK_FAIL_BIT)
+
+#define NETA_FORCE_LINK_PASS_BIT                1
+#define NETA_FORCE_LINK_PASS_MASK               (1 << NETA_FORCE_LINK_PASS_BIT)
+
+#define NETA_SET_MII_SPEED_100_BIT              5
+#define NETA_SET_MII_SPEED_100_MASK             (1 << NETA_SET_MII_SPEED_100_BIT)
+
+#define NETA_SET_GMII_SPEED_1000_BIT            6
+#define NETA_SET_GMII_SPEED_1000_MASK           (1 << NETA_SET_GMII_SPEED_1000_BIT)
+
+#define NETA_ENABLE_SPEED_AUTO_NEG_BIT          7
+#define NETA_ENABLE_SPEED_AUTO_NEG_MASK         (1 << NETA_ENABLE_SPEED_AUTO_NEG_BIT)
+
+#define NETA_SET_FLOW_CONTROL_BIT               8
+#define NETA_SET_FLOW_CONTROL_MASK              (1 << NETA_SET_FLOW_CONTROL_BIT)
+
+#define NETA_FLOW_CONTROL_ADVERTISE_BIT         9
+#define NETA_FLOW_CONTROL_ADVERTISE_MASK        (1 << NETA_FLOW_CONTROL_ADVERTISE_BIT)
+
+#define NETA_FLOW_CONTROL_ASYMETRIC_BIT         10
+#define NETA_FLOW_CONTROL_ASYMETRIC_MASK        (1 << NETA_FLOW_CONTROL_ASYMETRIC_BIT)
+
+#define NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_BIT   11
+#define NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK  (1 << NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_BIT)
+
+#define NETA_SET_FULL_DUPLEX_BIT                12
+#define NETA_SET_FULL_DUPLEX_MASK               (1 << NETA_SET_FULL_DUPLEX_BIT)
+
+#define NETA_ENABLE_DUPLEX_AUTO_NEG_BIT         13
+#define NETA_ENABLE_DUPLEX_AUTO_NEG_MASK        (1 << NETA_ENABLE_DUPLEX_AUTO_NEG_BIT)
+
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_GMAC_STATUS_REG(p)                 (NETA_REG_BASE(p) + 0x2C10)
+
+#define NETA_GMAC_LINK_UP_BIT               0
+#define NETA_GMAC_LINK_UP_MASK              (1 << NETA_GMAC_LINK_UP_BIT)
+
+#define NETA_GMAC_SPEED_1000_BIT            1
+#define NETA_GMAC_SPEED_1000_MASK           (1 << NETA_GMAC_SPEED_1000_BIT)
+
+#define NETA_GMAC_SPEED_100_BIT             2
+#define NETA_GMAC_SPEED_100_MASK            (1 << NETA_GMAC_SPEED_100_BIT)
+
+#define NETA_GMAC_FULL_DUPLEX_BIT           3
+#define NETA_GMAC_FULL_DUPLEX_MASK          (1 << NETA_GMAC_FULL_DUPLEX_BIT)
+
+#define NETA_RX_FLOW_CTRL_ENABLE_BIT        4
+#define NETA_RX_FLOW_CTRL_ENABLE_MASK       (1 << NETA_RX_FLOW_CTRL_ENABLE_BIT)
+
+#define NETA_TX_FLOW_CTRL_ENABLE_BIT        5
+#define NETA_TX_FLOW_CTRL_ENABLE_MASK       (1 << NETA_TX_FLOW_CTRL_ENABLE_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_GMAC_SERIAL_REG(p)             (NETA_REG_BASE(p) + 0x2C14)
+
+#define NETA_GMAC_FIFO_PARAM_0_REG(p)       (NETA_REG_BASE(p) + 0x2C18)
+#define NETA_GMAC_FIFO_PARAM_1_REG(p)       (NETA_REG_BASE(p) + 0x2C1C)
+
+#define NETA_GMAC_CAUSE_REG(p)              (NETA_REG_BASE(p) + 0x2C20)
+#define NETA_GMAC_MASK_REG(p)               (NETA_REG_BASE(p) + 0x2C24)
+
+#define NETA_GMAC_SERDES_CFG_0_REG(p)       (NETA_REG_BASE(p) + 0x2C28)
+#define NETA_GMAC_SERDES_CFG_1_REG(p)       (NETA_REG_BASE(p) + 0x2C2C)
+#define NETA_GMAC_SERDES_CFG_2_REG(p)       (NETA_REG_BASE(p) + 0x2C30)
+#define NETA_GMAC_SERDES_CFG_3_REG(p)       (NETA_REG_BASE(p) + 0x2C34)
+
+#define NETA_GMAC_PRBS_STATUS_REG(p)        (NETA_REG_BASE(p) + 0x2C38)
+#define NETA_GMAC_PRBS_ERR_CNTR_REG(p)      (NETA_REG_BASE(p) + 0x2C3C)
+
+#define NETA_GMAC_STATUS_1_REG(p)           (NETA_REG_BASE(p) + 0x2C40)
+
+#define NETA_GMAC_MIB_CTRL_REG(p)           (NETA_REG_BASE(p) + 0x2C44)
+#define NETA_GMAC_CTRL_3_REG(p)             (NETA_REG_BASE(p) + 0x2C48)
+
+#define NETA_GMAC_QSGMII_REG(p)             (NETA_REG_BASE(p) + 0x2C4C)
+#define NETA_GMAC_QSGMII_STATUS_REG(p)      (NETA_REG_BASE(p) + 0x2C50)
+#define NETA_GMAC_QSGMII_ERR_CNTR_REG(p)    (NETA_REG_BASE(p) + 0x2C54)
+
+/* 8 FC Timer registers: 0x2c58 .. 0x2c74 */
+#define NETA_GMAC_FC_TIMER_REG(p, r)        (NETA_REG_BASE(p) + 0x2C58 + ((r) << 2))
+
+/* 4 DSA Tag registers: 0x2c78 .. 0x2c84 */
+#define NETA_GMAC_DSA_TAG_REG(p, r)         (NETA_REG_BASE(p) + 0x2C78 + ((r) << 2))
+
+#define NETA_GMAC_FC_WIN_0_REG(p)           (NETA_REG_BASE(p) + 0x2C88)
+#define NETA_GMAC_FC_WIN_1_REG(p)           (NETA_REG_BASE(p) + 0x2C8C)
+
+#define NETA_GMAC_CTRL_4_REG(p)             (NETA_REG_BASE(p) + 0x2C90)
+
+#define NETA_GMAC_SERIAL_1_REG(p)           (NETA_REG_BASE(p) + 0x2C94)
+
+#define NETA_LOW_POWER_CTRL_0_REG(p)        (NETA_REG_BASE(p) + 0x2CC0)
+
+/* Low Power Idle Control #1 register */
+#define NETA_LOW_POWER_CTRL_1_REG(p)        (NETA_REG_BASE(p) + 0x2CC4)
+
+#define NETA_LPI_REQUEST_EN_BIT             0
+#define NETA_LPI_REQUEST_EN_MASK            (1 << NETA_LPI_REQUEST_EN_BIT)
+
+#define NETA_LPI_REQUEST_FORCE_BIT          1
+#define NETA_LPI_REQUEST_FORCE_MASK         (1 << NETA_LPI_REQUEST_FORCE_BIT)
+
+#define NETA_LPI_MANUAL_MODE_BIT            2
+#define NETA_LPI_MANUAL_MODE_MASK           (1 << NETA_LPI_MANUAL_MODE_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_LOW_POWER_CTRL_2_REG(p)        (NETA_REG_BASE(p) + 0x2CC8)
+#define NETA_LOW_POWER_STATUS_REG(p)        (NETA_REG_BASE(p) + 0x2CCC)
+#define NETA_LOW_POWER_CNTR_REG(p)          (NETA_REG_BASE(p) + 0x2CD0)
+
+
+#define ETH_MIB_COUNTERS_BASE(port)         (MV_ETH_REGS_BASE(port) + 0x1000)
+#define ETH_DA_FILTER_SPEC_MCAST_BASE(port) (MV_ETH_REGS_BASE(port) + 0x1400)
+#define ETH_DA_FILTER_OTH_MCAST_BASE(port)  (MV_ETH_REGS_BASE(port) + 0x1500)
+#define ETH_DA_FILTER_UCAST_BASE(port)      (MV_ETH_REGS_BASE(port) + 0x1600)
+
+/* Phy address register definitions */
+#define ETH_PHY_ADDR_OFFS          0
+#define ETH_PHY_ADDR_MASK          (0x1f << ETH_PHY_ADDR_OFFS)
+
+/* MIB Counters register definitions */
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW    0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH   0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED         0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR   0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED        0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED         0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED   0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED   0x1c
+#define ETH_MIB_FRAMES_64_OCTETS            0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS     0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS    0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS    0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS   0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS   0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW        0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH       0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT            0x40
+#define ETH_MIB_EXCESSIVE_COLLISION         0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT       0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT       0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED  0x50
+#define ETH_MIB_FC_SENT                     0x54
+#define ETH_MIB_GOOD_FC_RECEIVED            0x58
+#define ETH_MIB_BAD_FC_RECEIVED             0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED          0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED          0x64
+#define ETH_MIB_OVERSIZE_RECEIVED           0x68
+#define ETH_MIB_JABBER_RECEIVED             0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR           0x70
+#define ETH_MIB_BAD_CRC_EVENT               0x74
+#define ETH_MIB_COLLISION                   0x78
+#define ETH_MIB_LATE_COLLISION              0x7c
+
+
+/****************************************/
+/*        Ethernet Unit Register BITs   */
+/****************************************/
+#if (MV_ETH_VERSION >= 4)
+#define ETH_TX_EJP_RESET_BIT                0
+#define ETH_TX_EJP_RESET_MASK               (1 << ETH_TX_EJP_RESET_BIT)
+
+#define ETH_TX_EJP_ENABLE_BIT               2
+#define ETH_TX_EJP_ENABLE_MASK              (1 << ETH_TX_EJP_ENABLE_BIT)
+
+#define ETH_TX_LEGACY_WRR_BIT               3
+#define ETH_TX_LEGACY_WRR_MASK              (1 << ETH_TX_LEGACY_WRR_BIT)
+#endif /* (MV_ETH_VERSION >= 4) */
+
+
+/***** BITs of Port Configuration reg (PxCR) *****/
+#define ETH_UNICAST_PROMISCUOUS_MODE_BIT    0
+#define ETH_UNICAST_PROMISCUOUS_MODE_MASK   (1<<ETH_UNICAST_PROMISCUOUS_MODE_BIT)
+
+#define ETH_DEF_RX_QUEUE_OFFSET             1
+#define ETH_DEF_RX_QUEUE_ALL_MASK           (0x7<<ETH_DEF_RX_QUEUE_OFFSET)
+#define ETH_DEF_RX_QUEUE_MASK(queue)        ((queue)<<ETH_DEF_RX_QUEUE_OFFSET)
+
+#define ETH_DEF_RX_ARP_QUEUE_OFFSET         4
+#define ETH_DEF_RX_ARP_QUEUE_ALL_MASK       (0x7<<ETH_DEF_RX_ARP_QUEUE_OFFSET)
+#define ETH_DEF_RX_ARP_QUEUE_MASK(queue)    ((queue)<<ETH_DEF_RX_ARP_QUEUE_OFFSET)
+
+#define ETH_REJECT_NOT_IP_ARP_BCAST_BIT     7
+#define ETH_REJECT_NOT_IP_ARP_BCAST_MASK    (1<<ETH_REJECT_NOT_IP_ARP_BCAST_BIT)
+
+#define ETH_REJECT_IP_BCAST_BIT             8
+#define ETH_REJECT_IP_BCAST_MASK            (1<<ETH_REJECT_IP_BCAST_BIT)
+
+#define ETH_REJECT_ARP_BCAST_BIT            9
+#define ETH_REJECT_ARP_BCAST_MASK           (1<<ETH_REJECT_ARP_BCAST_BIT)
+
+#define ETH_TX_NO_SET_ERROR_SUMMARY_BIT     12
+#define ETH_TX_NO_SET_ERROR_SUMMARY_MASK    (1<<ETH_TX_NO_SET_ERROR_SUMMARY_BIT)
+
+#define ETH_CAPTURE_TCP_FRAMES_ENABLE_BIT   14
+#define ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK  (1<<ETH_CAPTURE_TCP_FRAMES_ENABLE_BIT)
+
+#define ETH_CAPTURE_UDP_FRAMES_ENABLE_BIT   15
+#define ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK  (1<<ETH_CAPTURE_UDP_FRAMES_ENABLE_BIT)
+
+#define ETH_DEF_RX_TCP_QUEUE_OFFSET         16
+#define ETH_DEF_RX_TCP_QUEUE_ALL_MASK       (0x7<<ETH_DEF_RX_TCP_QUEUE_OFFSET)
+#define ETH_DEF_RX_TCP_QUEUE_MASK(queue)    ((queue)<<ETH_DEF_RX_TCP_QUEUE_OFFSET)
+
+#define ETH_DEF_RX_UDP_QUEUE_OFFSET         19
+#define ETH_DEF_RX_UDP_QUEUE_ALL_MASK       (0x7<<ETH_DEF_RX_UDP_QUEUE_OFFSET)
+#define ETH_DEF_RX_UDP_QUEUE_MASK(queue)    ((queue)<<ETH_DEF_RX_UDP_QUEUE_OFFSET)
+
+#define ETH_DEF_RX_BPDU_QUEUE_OFFSET        22
+#define ETH_DEF_RX_BPDU_QUEUE_ALL_MASK      (0x7<<ETH_DEF_RX_BPDU_QUEUE_OFFSET)
+#define ETH_DEF_RX_BPDU_QUEUE_MASK(queue)   ((queue)<<ETH_DEF_RX_BPDU_QUEUE_OFFSET)
+
+#define ETH_RX_CHECKSUM_MODE_OFFSET         25
+#define ETH_RX_CHECKSUM_NO_PSEUDO_HDR       (0<<ETH_RX_CHECKSUM_MODE_OFFSET)
+#define ETH_RX_CHECKSUM_WITH_PSEUDO_HDR     (1<<ETH_RX_CHECKSUM_MODE_OFFSET)
+
+/***** BITs of Port Configuration Extend reg (PxCXR) *****/
+#define ETH_CAPTURE_SPAN_BPDU_ENABLE_BIT    1
+#define ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK   (1<<ETH_CAPTURE_SPAN_BPDU_ENABLE_BIT)
+
+#define ETH_TX_DISABLE_GEN_CRC_BIT          3
+#define ETH_TX_DISABLE_GEN_CRC_MASK         (1<<ETH_TX_DISABLE_GEN_CRC_BIT)
+
+
+/***** BITs of Port Sdma Configuration reg (SDCR) *****/
+#define ETH_RX_FRAME_INTERRUPT_BIT          0
+#define ETH_RX_FRAME_INTERRUPT_MASK         (1<<ETH_RX_FRAME_INTERRUPT_BIT)
+
+#define ETH_BURST_SIZE_1_64BIT_VALUE        0
+#define ETH_BURST_SIZE_2_64BIT_VALUE        1
+#define ETH_BURST_SIZE_4_64BIT_VALUE        2
+#define ETH_BURST_SIZE_8_64BIT_VALUE        3
+#define ETH_BURST_SIZE_16_64BIT_VALUE       4
+
+#define ETH_RX_BURST_SIZE_OFFSET            1
+#define ETH_RX_BURST_SIZE_ALL_MASK          (0x7<<ETH_RX_BURST_SIZE_OFFSET)
+#define ETH_RX_BURST_SIZE_MASK(burst)       ((burst)<<ETH_RX_BURST_SIZE_OFFSET)
+
+#define ETH_RX_NO_DATA_SWAP_BIT             4
+#define ETH_RX_NO_DATA_SWAP_MASK            (1<<ETH_RX_NO_DATA_SWAP_BIT)
+#define ETH_RX_DATA_SWAP_MASK               (0<<ETH_RX_NO_DATA_SWAP_BIT)
+
+#define ETH_TX_NO_DATA_SWAP_BIT             5
+#define ETH_TX_NO_DATA_SWAP_MASK            (1<<ETH_TX_NO_DATA_SWAP_BIT)
+#define ETH_TX_DATA_SWAP_MASK               (0<<ETH_TX_NO_DATA_SWAP_BIT)
+
+#define ETH_DESC_SWAP_BIT                   6
+#define ETH_DESC_SWAP_MASK                  (1<<ETH_DESC_SWAP_BIT)
+#define ETH_NO_DESC_SWAP_MASK               (0<<ETH_DESC_SWAP_BIT)
+
+#define ETH_RX_INTR_COAL_OFFSET             7
+#define ETH_RX_INTR_COAL_ALL_MASK           (0x3fff<<ETH_RX_INTR_COAL_OFFSET)
+#define ETH_RX_INTR_COAL_MASK(value)        (((value)<<ETH_RX_INTR_COAL_OFFSET)  \
+	& ETH_RX_INTR_COAL_ALL_MASK)
+
+#define ETH_TX_BURST_SIZE_OFFSET            22
+#define ETH_TX_BURST_SIZE_ALL_MASK          (0x7<<ETH_TX_BURST_SIZE_OFFSET)
+#define ETH_TX_BURST_SIZE_MASK(burst)       ((burst)<<ETH_TX_BURST_SIZE_OFFSET)
+
+#define ETH_RX_INTR_COAL_MSB_BIT            25
+#define ETH_RX_INTR_COAL_MSB_MASK           (1<<ETH_RX_INTR_COAL_MSB_BIT)
+
+/* BITs Port #x Tx FIFO Urgent Threshold (PxTFUT) */
+#define ETH_TX_INTR_COAL_OFFSET             4
+#define ETH_TX_INTR_COAL_ALL_MASK           (0x3fff << ETH_TX_INTR_COAL_OFFSET)
+#define ETH_TX_INTR_COAL_MASK(value)        (((value) << ETH_TX_INTR_COAL_OFFSET)  \
+	& ETH_TX_INTR_COAL_ALL_MASK)
+
+
+/* BITs of SDMA Descriptor Command/Status field */
+#if defined(MV_CPU_BE) && !defined(MV_KW2_BE_ETH_WA)
+
+#define ETH_GET_32B_DESCR_VAL(val)	(val)
+#define ETH_GET_16B_DESCR_VAL(val)	(val)
+#define ETH_SET_32B_DESCR_VAL(var, val)	((var) = (val))
+#define ETH_SET_16B_DESCR_VAL(var, val)	((var) = (val))
+
+typedef struct _ethRxDesc {
+	MV_U16 byteCnt;	/* Descriptor buffer byte count     */
+	MV_U16 bufSize;	/* Buffer size                      */
+	MV_U32 cmdSts;	/* Descriptor command status        */
+	MV_U32 nextDescPtr;	/* Next descriptor pointer          */
+	MV_U32 bufPtr;	/* Descriptor buffer pointer        */
+	MV_ULONG returnInfo;	/* User resource return information */
+} ETH_RX_DESC;
+
+typedef struct _ethTxDesc {
+	MV_U16 byteCnt;	/* Descriptor buffer byte count     */
+	MV_U16 L4iChk;	/* CPU provided TCP Checksum        */
+	MV_U32 cmdSts;	/* Descriptor command status        */
+	MV_U32 nextDescPtr;	/* Next descriptor pointer          */
+	MV_U32 bufPtr;	/* Descriptor buffer pointer        */
+	MV_ULONG returnInfo;	/* User resource return information */
+	MV_U8 *alignBufPtr;	/* Pointer to 8 byte aligned buffer */
+} ETH_TX_DESC;
+
+#elif defined(MV_CPU_LE) || defined(MV_KW2_BE_ETH_WA)
+
+#ifdef MV_KW2_BE_ETH_WA
+#define ETH_GET_32B_DESCR_VAL(val)	MV_BYTE_SWAP_32BIT(val)
+#define ETH_GET_16B_DESCR_VAL(val)	MV_BYTE_SWAP_16BIT(val)
+#define ETH_SET_32B_DESCR_VAL(var, val) \
+				(var = MV_BYTE_SWAP_32BIT(val))
+#define ETH_SET_16B_DESCR_VAL(var, val) \
+				(var = MV_BYTE_SWAP_16BIT(val))
+#else
+#define ETH_GET_32B_DESCR_VAL(val)	(val)
+#define ETH_GET_16B_DESCR_VAL(val)	(val)
+#define ETH_SET_32B_DESCR_VAL(var, val)	((var) = (val))
+#define ETH_SET_16B_DESCR_VAL(var, val)	((var) = (val))
+#endif
+
+typedef struct _ethRxDesc {
+	MV_U32 cmdSts;	/* Descriptor command status        */
+	MV_U16 bufSize;	/* Buffer size                      */
+	MV_U16 byteCnt;	/* Descriptor buffer byte count     */
+	MV_U32 bufPtr;	/* Descriptor buffer pointer        */
+	MV_U32 nextDescPtr;	/* Next descriptor pointer          */
+	MV_ULONG returnInfo;	/* User resource return information */
+} ETH_RX_DESC;
+
+typedef struct _ethTxDesc {
+	MV_U32 cmdSts;	/* Descriptor command status        */
+	MV_U16 L4iChk;	/* CPU provided TCP Checksum        */
+	MV_U16 byteCnt;	/* Descriptor buffer byte count     */
+	MV_U32 bufPtr;	/* Descriptor buffer pointer        */
+	MV_U32 nextDescPtr;	/* Next descriptor pointer          */
+	MV_ULONG returnInfo;	/* User resource return information */
+	MV_U8 *alignBufPtr;	/* Pointer to 32 byte aligned buffer */
+} ETH_TX_DESC;
+
+#else
+#error "MV_CPU_BE or MV_CPU_LE must be defined"
+#endif				/* MV_CPU_BE || MV_CPU_LE */
+
+/* Buffer offset from buffer pointer */
+#define ETH_RX_BUF_OFFSET               0x2
+
+
+/* Tx & Rx descriptor bits */
+#define ETH_ERROR_SUMMARY_BIT               0
+#define ETH_ERROR_SUMMARY_MASK              (1<<ETH_ERROR_SUMMARY_BIT)
+
+#define ETH_BUFFER_OWNER_BIT                31
+#define ETH_BUFFER_OWNED_BY_DMA             (1<<ETH_BUFFER_OWNER_BIT)
+#define ETH_BUFFER_OWNED_BY_HOST            (0<<ETH_BUFFER_OWNER_BIT)
+
+/* Tx descriptor bits */
+#define ETH_TX_ERROR_CODE_OFFSET            1
+#define ETH_TX_ERROR_CODE_MASK              (3<<ETH_TX_ERROR_CODE_OFFSET)
+#define ETH_TX_LATE_COLLISION_ERROR         (0<<ETH_TX_ERROR_CODE_OFFSET)
+#define ETH_TX_UNDERRUN_ERROR               (1<<ETH_TX_ERROR_CODE_OFFSET)
+#define ETH_TX_EXCESSIVE_COLLISION_ERROR    (2<<ETH_TX_ERROR_CODE_OFFSET)
+
+#define ETH_TX_LLC_SNAP_FORMAT_BIT          9
+#define ETH_TX_LLC_SNAP_FORMAT_MASK         (1<<ETH_TX_LLC_SNAP_FORMAT_BIT)
+
+#define ETH_TX_IP_FRAG_BIT                  10
+#define ETH_TX_IP_FRAG_MASK                 (1<<ETH_TX_IP_FRAG_BIT)
+#define ETH_TX_IP_FRAG                      (0<<ETH_TX_IP_FRAG_BIT)
+#define ETH_TX_IP_NO_FRAG                   (1<<ETH_TX_IP_FRAG_BIT)
+
+#define ETH_TX_IP_HEADER_LEN_OFFSET         11
+#define ETH_TX_IP_HEADER_LEN_ALL_MASK       (0xF<<ETH_TX_IP_HEADER_LEN_OFFSET)
+#define ETH_TX_IP_HEADER_LEN_MASK(len)      ((len)<<ETH_TX_IP_HEADER_LEN_OFFSET)
+
+#define ETH_TX_VLAN_TAGGED_FRAME_BIT        15
+#define ETH_TX_VLAN_TAGGED_FRAME_MASK       (1<<ETH_TX_VLAN_TAGGED_FRAME_BIT)
+
+#define ETH_TX_L4_TYPE_BIT                  16
+#define ETH_TX_L4_TCP_TYPE                  (0<<ETH_TX_L4_TYPE_BIT)
+#define ETH_TX_L4_UDP_TYPE                  (1<<ETH_TX_L4_TYPE_BIT)
+
+#define ETH_TX_GENERATE_L4_CHKSUM_BIT       17
+#define ETH_TX_GENERATE_L4_CHKSUM_MASK      (1<<ETH_TX_GENERATE_L4_CHKSUM_BIT)
+
+#define ETH_TX_GENERATE_IP_CHKSUM_BIT       18
+#define ETH_TX_GENERATE_IP_CHKSUM_MASK      (1<<ETH_TX_GENERATE_IP_CHKSUM_BIT)
+
+#define ETH_TX_ZERO_PADDING_BIT             19
+#define ETH_TX_ZERO_PADDING_MASK            (1<<ETH_TX_ZERO_PADDING_BIT)
+
+#define ETH_TX_LAST_DESC_BIT                20
+#define ETH_TX_LAST_DESC_MASK               (1<<ETH_TX_LAST_DESC_BIT)
+
+#define ETH_TX_FIRST_DESC_BIT               21
+#define ETH_TX_FIRST_DESC_MASK              (1<<ETH_TX_FIRST_DESC_BIT)
+
+#define ETH_TX_GENERATE_CRC_BIT             22
+#define ETH_TX_GENERATE_CRC_MASK            (1<<ETH_TX_GENERATE_CRC_BIT)
+
+#define ETH_TX_ENABLE_INTERRUPT_BIT         23
+#define ETH_TX_ENABLE_INTERRUPT_MASK        (1<<ETH_TX_ENABLE_INTERRUPT_BIT)
+
+#define ETH_TX_AUTO_MODE_BIT                30
+#define ETH_TX_AUTO_MODE_MASK               (1<<ETH_TX_AUTO_MODE_BIT)
+
+
+/* Rx descriptor bits */
+#define ETH_RX_ERROR_CODE_OFFSET            1
+#define ETH_RX_ERROR_CODE_MASK              (3<<ETH_RX_ERROR_CODE_OFFSET)
+#define ETH_RX_CRC_ERROR                    (0<<ETH_RX_ERROR_CODE_OFFSET)
+#define ETH_RX_OVERRUN_ERROR                (1<<ETH_RX_ERROR_CODE_OFFSET)
+#define ETH_RX_MAX_FRAME_LEN_ERROR          (2<<ETH_RX_ERROR_CODE_OFFSET)
+#define ETH_RX_RESOURCE_ERROR               (3<<ETH_RX_ERROR_CODE_OFFSET)
+
+#define ETH_RX_L4_CHECKSUM_OFFSET           3
+#define ETH_RX_L4_CHECKSUM_MASK             (0xffff<<ETH_RX_L4_CHECKSUM_OFFSET)
+
+#define ETH_RX_VLAN_TAGGED_FRAME_BIT        19
+#define ETH_RX_VLAN_TAGGED_FRAME_MASK       (1<<ETH_RX_VLAN_TAGGED_FRAME_BIT)
+
+#define ETH_RX_BPDU_FRAME_BIT               20
+#define ETH_RX_BPDU_FRAME_MASK              (1<<ETH_RX_BPDU_FRAME_BIT)
+
+#define ETH_RX_L4_TYPE_OFFSET               21
+#define ETH_RX_L4_TYPE_MASK                 (3<<ETH_RX_L4_TYPE_OFFSET)
+#define ETH_RX_L4_TCP_TYPE                  (0<<ETH_RX_L4_TYPE_OFFSET)
+#define ETH_RX_L4_UDP_TYPE                  (1<<ETH_RX_L4_TYPE_OFFSET)
+#define ETH_RX_L4_OTHER_TYPE                (2<<ETH_RX_L4_TYPE_OFFSET)
+
+#define ETH_RX_NOT_LLC_SNAP_FORMAT_BIT      23
+#define ETH_RX_NOT_LLC_SNAP_FORMAT_MASK     (1<<ETH_RX_NOT_LLC_SNAP_FORMAT_BIT)
+
+#define ETH_RX_IP_FRAME_TYPE_BIT            24
+#define ETH_RX_IP_FRAME_TYPE_MASK           (1<<ETH_RX_IP_FRAME_TYPE_BIT)
+
+#define ETH_RX_IP_HEADER_OK_BIT             25
+#define ETH_RX_IP_HEADER_OK_MASK            (1<<ETH_RX_IP_HEADER_OK_BIT)
+
+#define ETH_RX_LAST_DESC_BIT                26
+#define ETH_RX_LAST_DESC_MASK               (1<<ETH_RX_LAST_DESC_BIT)
+
+#define ETH_RX_FIRST_DESC_BIT               27
+#define ETH_RX_FIRST_DESC_MASK              (1<<ETH_RX_FIRST_DESC_BIT)
+
+#define ETH_RX_UNKNOWN_DA_BIT               28
+#define ETH_RX_UNKNOWN_DA_MASK              (1<<ETH_RX_UNKNOWN_DA_BIT)
+
+#define ETH_RX_ENABLE_INTERRUPT_BIT         29
+#define ETH_RX_ENABLE_INTERRUPT_MASK        (1<<ETH_RX_ENABLE_INTERRUPT_BIT)
+
+#define ETH_RX_L4_CHECKSUM_OK_BIT           30
+#define ETH_RX_L4_CHECKSUM_OK_MASK          (1<<ETH_RX_L4_CHECKSUM_OK_BIT)
+
+/* Rx descriptor bufSize field */
+#define ETH_RX_IP_FRAGMENTED_FRAME_BIT      2
+#define ETH_RX_IP_FRAGMENTED_FRAME_MASK     (1<<ETH_RX_IP_FRAGMENTED_FRAME_BIT)
+
+#define ETH_RX_BUFFER_MASK                  0xFFF8
+
+
+/* Ethernet Cause Register BITs */
+#define ETH_CAUSE_RX_READY_SUM_BIT          0
+#define ETH_CAUSE_EXTEND_BIT                1
+
+#define ETH_CAUSE_RX_READY_OFFSET           2
+#define ETH_CAUSE_RX_READY_BIT(queue)       (ETH_CAUSE_RX_READY_OFFSET + (queue))
+#define ETH_CAUSE_RX_READY_MASK(queue)      (1 << (ETH_CAUSE_RX_READY_BIT(queue)))
+
+#define ETH_CAUSE_RX_ERROR_SUM_BIT          10
+#define ETH_CAUSE_RX_ERROR_OFFSET           11
+#define ETH_CAUSE_RX_ERROR_BIT(queue)       (ETH_CAUSE_RX_ERROR_OFFSET + (queue))
+#define ETH_CAUSE_RX_ERROR_MASK(queue)      (1 << (ETH_CAUSE_RX_ERROR_BIT(queue)))
+
+#define ETH_CAUSE_TX_END_BIT                19
+#define ETH_CAUSE_SUM_BIT                   31
+
+/* Ethernet Cause Extended Register BITs */
+#define ETH_CAUSE_TX_BUF_OFFSET             0
+#define ETH_CAUSE_TX_BUF_BIT(queue)         (ETH_CAUSE_TX_BUF_OFFSET + (queue))
+#define ETH_CAUSE_TX_BUF_MASK(queue)        (1 << (ETH_CAUSE_TX_BUF_BIT(queue)))
+
+#define ETH_CAUSE_TX_ERROR_OFFSET           8
+#define ETH_CAUSE_TX_ERROR_BIT(queue)       (ETH_CAUSE_TX_ERROR_OFFSET + (queue))
+#define ETH_CAUSE_TX_ERROR_MASK(queue)      (1 << (ETH_CAUSE_TX_ERROR_BIT(queue)))
+
+#define ETH_CAUSE_PHY_STATUS_CHANGE_BIT     16
+#define ETH_CAUSE_RX_OVERRUN_BIT            18
+#define ETH_CAUSE_TX_UNDERRUN_BIT           19
+#define ETH_CAUSE_LINK_STATE_CHANGE_BIT     20
+#define ETH_CAUSE_INTERNAL_ADDR_ERR_BIT     23
+#define ETH_CAUSE_EXTEND_SUM_BIT            31
+
+/* Marvell Header Register */
+/* Marvell Header register bits */
+#define ETH_MVHDR_EN_BIT                    0
+#define ETH_MVHDR_EN_MASK                   (1 << ETH_MVHDR_EN_BIT)
+
+#define ETH_MVHDR_DAPREFIX_BIT              1
+#define ETH_MVHDR_DAPREFIX_MASK             (0x3 << ETH_MVHDR_DAPREFIX_BIT)
+#define ETH_MVHDR_DAPREFIX_PRI_1_2          (0x1 << ETH_MVHDR_DAPREFIX_BIT)
+#define ETH_MVHDR_DAPREFIX_DBNUM_PRI        (0x2 << ETH_MVHDR_DAPREFIX_BIT)
+#define ETH_MVHDR_DAPREFIX_SPID_PRI         (0x3 << ETH_MVHDR_DAPREFIX_BIT)
+
+#define ETH_MVHDR_MHMASK_BIT                8
+#define ETH_MVHDR_MHMASK_MASK               (0x3 << ETH_MVHDR_MHMASK_BIT)
+#define ETH_MVHDR_MHMASK_8_QUEUE            (0x0 << ETH_MVHDR_MHMASK_BIT)
+#define ETH_MVHDR_MHMASK_4_QUEUE            (0x1 << ETH_MVHDR_MHMASK_BIT)
+#define ETH_MVHDR_MHMASK_2_QUEUE            (0x3 << ETH_MVHDR_MHMASK_BIT)
+
+
+/* Relevant for 6183 ONLY */
+#define ETH_UNIT_PORTS_PADS_CALIB_0_REG     (MV_ETH_REGS_BASE(0) + 0x0A0)
+#define ETH_UNIT_PORTS_PADS_CALIB_1_REG     (MV_ETH_REGS_BASE(0) + 0x0A4)
+#define ETH_UNIT_PORTS_PADS_CALIB_2_REG     (MV_ETH_REGS_BASE(0) + 0x0A8)
+/* Ethernet Unit Ports Pads Calibration_REG (ETH_UNIT_PORTS_PADS_CALIB_x_REG)  */
+#define ETH_ETHERNET_PAD_CLIB_DRVN_OFFS		0
+#define ETH_ETHERNET_PAD_CLIB_DRVN_MASK		(0x1F << ETH_ETHERNET_PAD_CLIB_DRVN_OFFS)
+
+#define ETH_ETHERNET_PAD_CLIB_DRVP_OFFS         5
+#define ETH_ETHERNET_PAD_CLIB_DRVP_MASK         (0x1F << ETH_ETHERNET_PAD_CLIB_DRVP_OFFS)
+
+#define ETH_ETHERNET_PAD_CLIB_TUNEEN_OFFS       16
+#define ETH_ETHERNET_PAD_CLIB_TUNEEN_MASK       (0x1 << ETH_ETHERNET_PAD_CLIB_TUNEEN_OFFS)
+
+#define ETH_ETHERNET_PAD_CLIB_LOCKN_OFFS        17
+#define ETH_ETHERNET_PAD_CLIB_LOCKN_MASK        (0x1F << ETH_ETHERNET_PAD_CLIB_LOCKN_OFFS)
+
+#define ETH_ETHERNET_PAD_CLIB_OFFST_OFFS        24
+#define ETH_ETHERNET_PAD_CLIB_OFFST_MASK        (0x1F << ETH_ETHERNET_PAD_CLIB_OFFST_OFFS)
+
+#define ETH_ETHERNET_PAD_CLIB_WR_EN_OFFS        31
+#define ETH_ETHERNET_PAD_CLIB_WR_EN_MASK        (0x1  << ETH_ETHERNET_PAD_CLIB_WR_EN_OFFS)
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INCmvEthRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/eth/mvCompVer.txt
new file mode 100755
index 0000000..38a9264
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.4

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/eth/mvEth.h b/arch/arm/plat-feroceon/mv_hal/eth/mvEth.h
new file mode 100755
index 0000000..f73f3f5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/mvEth.h
@@ -0,0 +1,357 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvEth.h - Header File for : Ethernet Controller
+*
+* DESCRIPTION:
+*       This header file contains macros typedefs and function declaration for
+*       Marvell Gigabit Ethernet Controllers.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __mvEth_h__
+#define __mvEth_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes */
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "gbe/mvEthRegs.h"
+#include "mvSysEthConfig.h"
+
+/* defines  */
+
+#define MV_ETH_EXTRA_FRAGS_NUM      2
+
+	typedef struct {
+		MV_U32 maxPortNum;
+		MV_U32 cpuPclk;
+		MV_U32 tclk;
+#ifdef ETH_DESCR_IN_SRAM
+		MV_U32 sramSize;
+#endif
+
+		struct {
+			MV_BOOL powerOn;
+			MV_32 phyAddr;
+			MV_BOOL isSgmii;
+			MV_ETH_MAC_SPEED macSpeed;
+		} portData[MV_ETH_MAX_PORTS];
+	} MV_ETH_HAL_DATA;
+
+	typedef enum {
+		MV_ETH_SPEED_AN,
+		MV_ETH_SPEED_10,
+		MV_ETH_SPEED_100,
+		MV_ETH_SPEED_1000
+	} MV_ETH_PORT_SPEED;
+
+	typedef enum {
+		MV_ETH_DUPLEX_AN,
+		MV_ETH_DUPLEX_HALF,
+		MV_ETH_DUPLEX_FULL
+	} MV_ETH_PORT_DUPLEX;
+
+	typedef enum {
+		MV_ETH_FC_AN_ADV_DIS,
+		MV_ETH_FC_AN_ADV_SYM,
+		MV_ETH_FC_DISABLE,
+		MV_ETH_FC_ENABLE
+	} MV_ETH_PORT_FC;
+
+	typedef enum {
+		MV_ETH_PRIO_FIXED = 0,	/* Fixed priority mode */
+		MV_ETH_PRIO_WRR = 1	/* Weighted round robin priority mode */
+	} MV_ETH_PRIO_MODE;
+
+/* Ethernet port specific infomation */
+	typedef struct {
+		int maxRxPktSize;
+		int rxDefQ;
+		int rxBpduQ;
+		int rxArpQ;
+		int rxTcpQ;
+		int rxUdpQ;
+		int ejpMode;
+	} MV_ETH_PORT_CFG;
+
+	typedef struct {
+		int descrNum;
+	} MV_ETH_RX_Q_CFG;
+
+	typedef struct {
+		int descrNum;
+		MV_ETH_PRIO_MODE prioMode;
+		int quota;
+	} MV_ETH_TX_Q_CFG;
+
+	typedef struct {
+		int rxDefQ;
+		int txDescrNum[MV_ETH_TX_Q_NUM];
+		int rxDescrNum[MV_ETH_RX_Q_NUM];
+		void *osHandle;
+	} MV_ETH_PORT_INIT;
+
+	typedef struct {
+		MV_BOOL isLinkUp;
+		MV_ETH_PORT_SPEED speed;
+		MV_ETH_PORT_DUPLEX duplex;
+		MV_ETH_PORT_FC flowControl;
+
+	} MV_ETH_PORT_STATUS;
+
+	typedef enum {
+		MV_ETH_DISABLE_HEADER_MODE = 0,
+		MV_ETH_ENABLE_HEADER_MODE_PRI_2_1 = 1,
+		MV_ETH_ENABLE_HEADER_MODE_PRI_DBNUM = 2,
+		MV_ETH_ENABLE_HEADER_MODE_PRI_SPID = 3
+	} MV_ETH_HEADER_MODE;
+
+/* ethernet.h API list */
+	void mvEthHalInit(MV_ETH_HAL_DATA *halData);
+	void mvEthMemAttrGet(MV_BOOL *pIsSram, MV_BOOL *pIsSwCoher);
+
+/* Port Initalization routines */
+	void *mvEthPortInit(int port, MV_ETH_PORT_INIT *pPortInit);
+	void ethResetTxDescRing(void *pPortHndl, int queue);
+	void ethResetRxDescRing(void *pPortHndl, int queue);
+
+	void *mvEthPortHndlGet(int port);
+
+	void mvEthPortFinish(void *pEthPortHndl);
+	MV_STATUS mvEthPortDown(void *pEthPortHndl);
+	MV_STATUS mvEthPortDisable(void *pEthPortHndl);
+	MV_STATUS mvEthPortUp(void *pEthPortHndl);
+	MV_STATUS mvEthPortEnable(void *pEthPortHndl);
+
+/* Port data flow routines */
+	MV_PKT_INFO *mvEthPortForceTxDone(void *pEthPortHndl, int txQueue);
+	MV_PKT_INFO *mvEthPortForceRx(void *pEthPortHndl, int rxQueue);
+
+/* Port Configuration routines */
+	MV_STATUS mvEthDefaultsSet(void *pEthPortHndl);
+	MV_STATUS mvEthMaxRxSizeSet(void *pPortHndl, int maxRxSize);
+
+/* Port RX MAC Filtering control routines */
+	MV_U8 mvEthMcastCrc8Get(MV_U8 *pAddr);
+	MV_STATUS mvEthRxFilterModeSet(void *pPortHndl, MV_BOOL isPromisc);
+	MV_STATUS mvEthMacAddrSet(void *pPortHandle, MV_U8 * pMacAddr, int queue);
+	MV_STATUS mvEthMcastAddrSet(void *pPortHandle, MV_U8 * pAddr, int queue);
+
+/* MIB Counters APIs */
+	MV_U32 mvEthMibCounterRead(void *pPortHndl, unsigned int mibOffset, MV_U32 * pHigh32);
+	void mvEthMibCountersClear(void *pPortHandle);
+
+/* TX Scheduling configuration routines */
+	MV_STATUS mvEthTxQueueConfig(void *pPortHandle, int txQueue, MV_ETH_PRIO_MODE txPrioMode, int txQuota);
+
+/* RX Dispatching configuration routines */
+MV_STATUS mvEthBpduRxQueue(void *pPortHandle, int bpduQueue);
+MV_STATUS mvEthVlanPrioRxQueue(void *pPortHandle, int vlanPrio, int vlanPrioQueue);
+MV_STATUS mvEthTosToRxqSet(void *pPortHandle, int tos, int rxq);
+int mvEthTosToRxqGet(void *pPortHandle, int tos);
+
+/* Speed, Duplex, FlowControl routines */
+MV_STATUS mvEthSpeedDuplexSet(void *pPortHandle, MV_ETH_PORT_SPEED speed, MV_ETH_PORT_DUPLEX duplex);
+MV_STATUS mvEthFlowCtrlSet(void *pPortHandle, MV_ETH_PORT_FC flowControl);
+
+/* MAC special functions: implemented accordignly with MAC version */
+MV_STATUS mvEthGmacRgmiiSet(int port, int enable);
+
+#if (MV_ETH_VERSION >= 4)
+	MV_STATUS mvEthEjpModeSet(void *pPortHandle, int mode);
+#endif				/* (MV_ETH_VERSION >= 4) */
+
+	void mvEthStatusGet(void *pPortHandle, MV_ETH_PORT_STATUS *pStatus);
+
+/* Marvell Header control               */
+	MV_STATUS mvEthHeaderModeSet(void *pPortHandle, MV_ETH_HEADER_MODE headerMode);
+
+/* PHY routines */
+	void mvEthPhyAddrSet(void *pPortHandle, int phyAddr);
+	int mvEthPhyAddrGet(void *pPortHandle);
+
+/* Power management routines */
+	void mvEthPortPowerDown(int port);
+	void mvEthPortPowerUp(int port);
+
+	MV_STATUS mvEthWinInit(MV_U32 port, MV_UNIT_WIN_INFO *addrWinMap);
+	MV_STATUS mvEthWinWrite(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+	MV_STATUS mvEthWinRead(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+	MV_STATUS mvEthWinEnable(MV_U32 port, MV_U32 winNum, MV_BOOL enable);
+
+/******************** ETH PRIVATE ************************/
+
+/*#define UNCACHED_TX_BUFFERS*/
+/*#define UNCACHED_RX_BUFFERS*/
+
+/* Port attributes */
+/* Size of a Tx/Rx descriptor used in chain list data structure */
+#define ETH_RX_DESC_ALIGNED_SIZE        32
+#define ETH_TX_DESC_ALIGNED_SIZE        32
+
+#define TX_DISABLE_TIMEOUT_MSEC     1000
+#define RX_DISABLE_TIMEOUT_MSEC     1000
+#define TX_FIFO_EMPTY_TIMEOUT_MSEC  10000
+#define PORT_DISABLE_WAIT_TCLOCKS   5000
+
+/* Macros that save access to desc in order to find next desc pointer  */
+#define RX_NEXT_DESC_PTR(pRxDescr, pQueueCtrl)                              \
+	((pRxDescr) == (pQueueCtrl)->pLastDescr) ?                          \
+		(ETH_RX_DESC *)((pQueueCtrl)->pFirstDescr) :                  \
+		(ETH_RX_DESC *)(((MV_ULONG)(pRxDescr)) + ETH_RX_DESC_ALIGNED_SIZE)
+
+#define TX_NEXT_DESC_PTR(pTxDescr, pQueueCtrl)                              \
+	((pTxDescr) == (pQueueCtrl)->pLastDescr) ?                          \
+		(ETH_TX_DESC *)((pQueueCtrl)->pFirstDescr) :                  \
+		(ETH_TX_DESC *)(((MV_ULONG)(pTxDescr)) + ETH_TX_DESC_ALIGNED_SIZE)
+
+#define RX_PREV_DESC_PTR(pRxDescr, pQueueCtrl)                              \
+	((pRxDescr) == (pQueueCtrl)->pFirstDescr) ?                          \
+		(ETH_RX_DESC *)((pQueueCtrl)->pLastDescr) :                  \
+		(ETH_RX_DESC *)(((MV_ULONG)(pRxDescr)) - ETH_RX_DESC_ALIGNED_SIZE)
+
+#define TX_PREV_DESC_PTR(pTxDescr, pQueueCtrl)                              \
+	((pTxDescr) == (pQueueCtrl)->pFirstDescr) ?                          \
+		(ETH_TX_DESC *)((pQueueCtrl)->pLastDescr) :                  \
+		(ETH_TX_DESC *)(((MV_ULONG)(pTxDescr)) - ETH_TX_DESC_ALIGNED_SIZE)
+
+/* Queue specific information */
+	typedef struct {
+		void *pFirstDescr;
+		void *pLastDescr;
+		void *pCurrentDescr;
+		void *pUsedDescr;
+		int resource;
+		MV_BUF_INFO descBuf;
+	} ETH_QUEUE_CTRL;
+
+/* Ethernet port specific infomation */
+	typedef struct _ethPortCtrl {
+		int portNo;
+		ETH_QUEUE_CTRL rxQueue[MV_ETH_RX_Q_NUM];	/* Rx ring resource  */
+		ETH_QUEUE_CTRL txQueue[MV_ETH_TX_Q_NUM];	/* Tx ring resource  */
+
+		MV_ETH_PORT_CFG portConfig;
+		MV_ETH_RX_Q_CFG rxQueueConfig[MV_ETH_RX_Q_NUM];
+		MV_ETH_TX_Q_CFG txQueueConfig[MV_ETH_TX_Q_NUM];
+
+		/* Register images - For DP */
+		MV_U32 portTxQueueCmdReg;	/* Port active Tx queues summary    */
+		MV_U32 portRxQueueCmdReg;	/* Port active Rx queues summary    */
+
+		MV_STATE portState;
+
+		MV_U8 mcastCount[256];
+		MV_U32 *hashPtr;
+		void *osHandle;
+	} ETH_PORT_CTRL;
+
+/************** MACROs ****************/
+
+/* MACROs to Flush / Invalidate TX / RX Buffers */
+#if (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) && !defined(UNCACHED_TX_BUFFERS)
+#   define ETH_PACKET_CACHE_FLUSH(pAddr, size)                                  \
+	mvOsCacheClear(NULL, (pAddr), (size))                                   \
+				/*CPU_PIPE_FLUSH; */
+#else
+#   define ETH_PACKET_CACHE_FLUSH(pAddr, size)                                  \
+	mvOsIoVirtToPhy(NULL, (pAddr))
+#endif				/* ETHER_DRAM_COHER == MV_CACHE_COHER_SW */
+
+#if ((ETHER_DRAM_COHER == MV_CACHE_COHER_SW) && !defined(UNCACHED_RX_BUFFERS))
+#   define ETH_PACKET_CACHE_INVALIDATE(pAddr, size)                             \
+	mvOsCacheInvalidate(NULL, (pAddr), (size))                             \
+				/*CPU_PIPE_FLUSH; */
+#else
+#   define ETH_PACKET_CACHE_INVALIDATE(pAddr, size)
+#endif				/* ETHER_DRAM_COHER == MV_CACHE_COHER_SW && !UNCACHED_RX_BUFFERS */
+
+#ifdef ETH_DESCR_UNCACHED
+
+#define ETH_DESCR_FLUSH_INV(pPortCtrl, pDescr)
+#define ETH_DESCR_INV(pPortCtrl, pDescr)
+
+#else
+
+#define ETH_DESCR_FLUSH_INV(pPortCtrl, pDescr)      \
+	mvOsCacheLineFlushInv(pPortCtrl->osHandle, (MV_ULONG)(pDescr))
+
+#define ETH_DESCR_INV(pPortCtrl, pDescr)            \
+	mvOsCacheLineInv(pPortCtrl->osHandle, (MV_ULONG)(pDescr))
+
+#endif				/* ETH_DESCR_UNCACHED */
+
+/* #include "eth/gbe/mvEthGbe.h" */
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __mvEth_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfp.c b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfp.c
new file mode 100755
index 0000000..9e825c0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfp.c
@@ -0,0 +1,987 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvNfp.c - Marvell Network Fast Processing (Routing and NAT)
+*
+* DESCRIPTION:
+*
+*       Supported Features:
+*       - OS independent.
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvOs.h"
+#include "mvDebug.h"
+#include "eth/nfp/mvNfp.h"
+#include "eth/nfp/mvNfpSec.h"
+#include "eth/mvEth.h"
+
+static struct ruleHashBucket *ruleDb;
+static MV_U32 ruleDbSize;
+
+static MV_U32 nfpHashMaxDepth;
+static MV_U32 nfpRuleSetCount;
+static MV_U32 nfpRuleUpdateCount;
+static MV_U32 nfpRuleDeleteCount;
+
+MV_U32 fp_ip_jhash_iv = 0;
+
+MV_STATUS mvFpInit(void)
+{
+	fp_ip_jhash_iv = mvOsRand();
+
+	return MV_OK;
+}
+
+/* Initialize NFP Rule Database (Routing + ARP information table) */
+MV_STATUS mvFpRuleDbInit(MV_U32 dbSize)
+{
+	ruleDb = (struct ruleHashBucket *)mvOsMalloc(sizeof(struct ruleHashBucket) * dbSize);
+	if (ruleDb == NULL) {
+		mvOsPrintf("NFP Rule DB: Not Enough Memory\n");
+		return MV_NO_RESOURCE;
+	}
+	ruleDbSize = dbSize;
+	memset(ruleDb, 0, sizeof(struct ruleHashBucket) * ruleDbSize);
+	nfpRuleSetCount = nfpRuleUpdateCount = nfpRuleDeleteCount = 0;
+
+	mvOsPrintf("mvFpRuleDb (%p): %d entries, %d bytes\n",
+		   ruleDb, ruleDbSize, sizeof(struct ruleHashBucket) * ruleDbSize);
+
+	return MV_OK;
+}
+
+/* Clear NFP Rule Database (Routing + ARP information table) */
+MV_STATUS mvFpRuleDbClear(void)
+{
+	MV_U32 i = 0;
+	MV_FP_RULE *currRule;
+	MV_FP_RULE *tmpRule;
+
+	if (ruleDb == NULL)
+		return MV_NOT_INITIALIZED;
+
+	for (i = 0; i < ruleDbSize; i++) {
+		currRule = ruleDb[i].ruleChain;
+		while (currRule != NULL) {
+			tmpRule = currRule;
+			currRule = currRule->next;
+			mvOsFree(tmpRule);
+		}
+		ruleDb[i].ruleChain = NULL;
+	}
+	return MV_OK;
+}
+
+/* Free Rule Database memory */
+void mvFpRuleDbDestroy(void)
+{
+	if (ruleDb != NULL)
+		mvOsFree(ruleDb);
+}
+
+/* Print rule action type. Assume rule is not NULL. */
+static void mvFpActionTypePrint(const MV_FP_RULE *rule)
+{
+	switch (rule->mgmtInfo.actionType) {
+	case MV_FP_ROUTE_CMD:
+		mvOsPrintf("A=Route, ");
+		break;
+	case MV_FP_DROP_CMD:
+		mvOsPrintf("A=Drop, ");
+		break;
+	case MV_FP_TO_STACK_CMD:
+		mvOsPrintf("A=Stack, ");
+		break;
+	default:
+		mvOsPrintf("A=Unknown (%d), ", rule->mgmtInfo.actionType);
+		break;
+	}
+}
+
+/* Print rule type (static or dynamic). Assume rule is not NULL. */
+static void mvFpRuleTypePrint(const MV_FP_RULE *rule)
+{
+	switch (rule->mgmtInfo.ruleType) {
+	case MV_FP_STATIC_RULE:
+		mvOsPrintf("T=Static");
+		break;
+	case MV_FP_DYNAMIC_RULE:
+		mvOsPrintf("T=Dynamic");
+		break;
+	default:
+		mvOsPrintf("T=Unknown");
+		break;
+	}
+}
+
+/* Print a NFP Rule */
+void mvFpRulePrint(const MV_FP_RULE *rule)
+{
+	mvFpActionTypePrint(rule);
+	mvFpRuleTypePrint(rule);
+	mvOsPrintf(", SIP=");
+	mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.srcIp));
+	mvOsPrintf(", DIP=");
+	mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.dstIp));
+	mvOsPrintf(", GTW=");
+	mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.defGtwIp));
+	mvOsPrintf(", DA=");
+	mvDebugPrintMacAddr(rule->routingInfo.dstMac);
+	mvOsPrintf(", SA=");
+	mvDebugPrintMacAddr(rule->routingInfo.srcMac);
+	mvOsPrintf(", inIf=%d", rule->routingInfo.inIfIndex);
+	mvOsPrintf(", outIf=%d", rule->routingInfo.outIfIndex);
+	mvOsPrintf(", ToS=0x%x", rule->routingInfo.dscp);
+	mvOsPrintf(", TxQ=%d", rule->routingInfo.txq);
+
+	mvOsPrintf(", count=%d, aware_flags=0x%X", rule->mgmtInfo.new_count, rule->routingInfo.aware_flags);
+	mvOsPrintf("\n");
+}
+
+/* Print NFP Rule Database (Routing + ARP information table) */
+MV_STATUS mvFpRuleDbPrint(void)
+{
+	MV_U32 count, i;
+	MV_FP_RULE *currRule;
+
+	mvOsPrintf("\nPrinting NFP Rule Database\n");
+	count = 0;
+
+	for (i = 0; i < ruleDbSize; i++) {
+		currRule = ruleDb[i].ruleChain;
+
+		if (currRule != NULL)
+			mvOsPrintf("\n%03u: FP DB hash=0x%x", count, i);
+
+		while (currRule != NULL) {
+			mvOsPrintf("\n%03u: Rule=%p: ", count, currRule);
+			mvFpRulePrint(currRule);
+			currRule = currRule->next;
+			count++;
+		}
+	}
+	return MV_OK;
+}
+
+/* Copy all the information from src_rule to new_rule */
+/* Warning - doesn't perform any checks on memory, just copies */
+/* count is set to zero in new_rule */
+/* Note: the next pointer is not updated . */
+void mvFpRuleCopy(MV_FP_RULE *dstRule, const MV_FP_RULE *srcRule)
+{
+	dstRule->mgmtInfo.actionType = srcRule->mgmtInfo.actionType;
+	dstRule->mgmtInfo.new_count = srcRule->mgmtInfo.new_count;
+	dstRule->mgmtInfo.old_count = srcRule->mgmtInfo.old_count;
+	dstRule->mgmtInfo.ruleType = srcRule->mgmtInfo.ruleType;
+	dstRule->mgmtInfo.snat_aware_refcnt = srcRule->mgmtInfo.snat_aware_refcnt;
+	dstRule->mgmtInfo.dnat_aware_refcnt = srcRule->mgmtInfo.dnat_aware_refcnt;
+
+	dstRule->routingInfo.aware_flags = srcRule->routingInfo.aware_flags;
+	dstRule->routingInfo.srcIp = srcRule->routingInfo.srcIp;
+	dstRule->routingInfo.dstIp = srcRule->routingInfo.dstIp;
+	dstRule->routingInfo.defGtwIp = srcRule->routingInfo.defGtwIp;
+	memcpy(dstRule->routingInfo.srcMac, srcRule->routingInfo.srcMac, MV_MAC_ADDR_SIZE);
+	memcpy(dstRule->routingInfo.dstMac, srcRule->routingInfo.dstMac, MV_MAC_ADDR_SIZE);
+	dstRule->routingInfo.inIfIndex = srcRule->routingInfo.inIfIndex;
+	dstRule->routingInfo.outIfIndex = srcRule->routingInfo.outIfIndex;
+	dstRule->routingInfo.txq = srcRule->routingInfo.txq;
+	dstRule->routingInfo.dscp = srcRule->routingInfo.dscp;
+}
+
+/* Get the count value for a rule that matches the given SIP, DIP */
+MV_U32 mvFpRouteCountGet(MV_U32 srcIp, MV_U32 dstIp)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_RULE *pRule;
+
+	hash = mv_jhash_3words(dstIp, srcIp, (MV_U32) 0, fp_ip_jhash_iv);
+	hash_tr = hash & (ruleDbSize - 1);
+
+	pRule = ruleDb[hash_tr].ruleChain;
+	while (pRule) {
+		/* look for a matching rule */
+		if ((pRule->routingInfo.dstIp == dstIp) && (pRule->routingInfo.srcIp == srcIp))
+			return pRule->mgmtInfo.new_count;
+
+		pRule = pRule->next;
+	}
+	return 0;
+}
+
+MV_STATUS mvFpRuleAwareSet(MV_FP_RULE *pSetRule)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_RULE *pRule;
+
+	hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, (MV_U32) 0, fp_ip_jhash_iv);
+	hash_tr = hash & (ruleDbSize - 1);
+
+	pRule = ruleDb[hash_tr].ruleChain;
+	while (pRule) {
+		if ((pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp) &&
+		    (pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp)) {
+
+			pRule->routingInfo.aware_flags = pSetRule->routingInfo.aware_flags;
+#ifdef MV_FP_DEBUG
+			mvOsPrintf("Update FP aware: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash0x%x, flags=0x%x\n",
+				   MV_IP_QUAD(pSetRule->routingInfo.dstIp),
+				   MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr, pSetRule->routingInfo.aware_flags);
+#endif
+			return MV_OK;
+		}
+		pRule = pRule->next;
+	}
+#ifdef MV_FP_DEBUG
+	mvOsPrintf("FP aware NOT found: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%x, flags=0x%x\n",
+		   MV_IP_QUAD(pSetRule->routingInfo.dstIp),
+		   MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr, pSetRule->routingInfo.aware_flags);
+#endif
+	return MV_NOT_FOUND;
+}
+
+/* Set a Routing ToS Rule: update an existing rule  */
+#ifdef CONFIG_MV_ETH_NFP_TOS
+MV_STATUS mvFpToSSet(MV_FP_RULE *pSetRule)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_RULE *pRule;
+
+	hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, (MV_U32) 0, fp_ip_jhash_iv);
+	hash_tr = hash & (ruleDbSize - 1);
+
+	pRule = ruleDb[hash_tr].ruleChain;
+	while (pRule) {
+		if ((pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp &&
+		     pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp)) {
+			pRule->routingInfo.txq = pSetRule->routingInfo.txq;
+			pRule->routingInfo.dscp = pSetRule->routingInfo.dscp;
+			nfpRuleUpdateCount++;
+#ifdef MV_FP_DEBUG
+			mvOsPrintf("ToSNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x TOS=0x%x TxQ=%d\n",
+				   nfpRuleUpdateCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp),
+				   MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr,
+				   pRule->routingInfo.dscp, pRule->routingInfo.txq);
+#endif
+			return MV_OK;
+		}
+		pRule = pRule->next;
+	}
+	return MV_NOT_FOUND;
+}
+#endif
+/* Set a Routing Rule: create a new rule or update an existing rule  */
+/* in the Routing + ARP information table */
+MV_STATUS mvFpRuleSet(MV_FP_RULE *pSetRule)
+{
+	MV_U32 hash, hash_tr;
+	int depth = 0;
+	MV_FP_RULE *pRule, *pNewRule;
+
+	hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, (MV_U32) 0, fp_ip_jhash_iv);
+	hash_tr = hash & (ruleDbSize - 1);
+
+	pRule = ruleDb[hash_tr].ruleChain;
+	while (pRule) {
+		if ((pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp &&
+		     pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp)) {
+
+			mvFpRuleCopy(pRule, pSetRule);
+			nfpRuleUpdateCount++;
+
+#ifdef MV_FP_DEBUG
+			mvOsPrintf("UpdNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x TOS=0x%x TxQ=%d\n",
+				   nfpRuleUpdateCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp),
+				   MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr,
+				   pRule->routingInfo.dscp, pRule->routingInfo.txq);
+#endif
+			return MV_OK;
+		}
+		pRule = pRule->next;
+	}
+
+	/* Allocate new entry */
+	pNewRule = mvOsMalloc(sizeof(MV_FP_RULE));
+	if (pNewRule == NULL) {
+		mvOsPrintf("mvFpRuleSet: Can't allocate new rule\n");
+		return MV_FAIL;
+	}
+	mvFpRuleCopy(pNewRule, pSetRule);
+	pNewRule->next = NULL;
+
+	if (ruleDb[hash_tr].ruleChain == NULL)
+		ruleDb[hash_tr].ruleChain = pNewRule;
+	else {
+		pRule = ruleDb[hash_tr].ruleChain;
+		while (pRule->next != NULL) {
+			depth++;
+			pRule = pRule->next;
+		}
+		pRule->next = pNewRule;
+	}
+	if (depth > nfpHashMaxDepth)
+		nfpHashMaxDepth = depth;
+	nfpRuleSetCount++;
+
+#ifdef MV_FP_DEBUG
+	mvOsPrintf("SetNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x, aware=0x%02x\n",
+		   nfpRuleSetCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp),
+		   MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr, pSetRule->routingInfo.aware_flags);
+#endif
+	return MV_OK;
+}
+
+/* Delete a specified rule from the Routing + ARP information table */
+MV_STATUS mvFpRuleDelete(MV_FP_RULE *rule)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_RULE *currRule, *prevRule;
+
+	nfpRuleDeleteCount++;
+	hash = mv_jhash_3words(rule->routingInfo.dstIp, rule->routingInfo.srcIp, (MV_U32) 0, fp_ip_jhash_iv);
+	hash_tr = hash & (ruleDbSize - 1);
+
+	prevRule = NULL;
+	for (currRule = ruleDb[hash_tr].ruleChain; currRule != NULL; prevRule = currRule, currRule = currRule->next) {
+		if ((currRule->routingInfo.srcIp == rule->routingInfo.srcIp) &&
+		    (currRule->routingInfo.dstIp == rule->routingInfo.dstIp)) {
+			if (prevRule == NULL)
+				ruleDb[hash_tr].ruleChain = currRule->next;
+			else
+				prevRule->next = currRule->next;
+#ifdef MV_FP_DEBUG
+			mvOsPrintf("DelNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x\n",
+				   nfpRuleDeleteCount, MV_IP_QUAD(currRule->routingInfo.dstIp),
+				   MV_IP_QUAD(currRule->routingInfo.srcIp), hash_tr);
+#endif
+			mvOsFree(currRule);
+			return MV_OK;
+		}
+	}
+	return MV_NOT_FOUND;
+}
+
+/* Find and return the first matching rule in the Routing + ARP information table */
+static INLINE MV_FP_RULE *mvFpRuleFind(MV_U32 dstIp, MV_U32 srcIp)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_RULE *pRule;
+	int count = 0;
+
+	hash = mv_jhash_3words(dstIp, srcIp, (MV_U32) 0, fp_ip_jhash_iv);
+	hash_tr = hash & (ruleDbSize - 1);
+
+	pRule = ruleDb[hash_tr].ruleChain;
+
+	while (pRule) {
+		/* look for a matching rule */
+		if ((pRule->routingInfo.dstIp == dstIp) && (pRule->routingInfo.srcIp == srcIp)) {
+			pRule->mgmtInfo.new_count++;
+			return pRule;
+		}
+		pRule = pRule->next;
+		count++;
+	}
+	return NULL;
+}
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+static INLINE MV_U32 mvFpFdbMember(MV_U32 ifIndex)
+{
+	return (ifIndex < ETH_FP_IFINDEX_MAX) ? fdbMember[ifIndex] : 0;
+}
+
+static MV_FP_FDB_RULE *mvFpFdbLookup(MV_U32 ifIndex, MV_U8 * pDA)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_FDB_RULE *pRule;
+	MV_U32 bridgeId;
+	int count = 0;
+
+	if (ifIndex >= ETH_FP_IFINDEX_MAX)
+		return NULL;
+	bridgeId = fdbMember[ifIndex];
+	if (!(bridgeId))
+		return NULL;
+
+	hash = mv_jhash_3words(bridgeId, 0, *(MV_U32 *) (pDA + 2), fp_ip_jhash_iv);
+	hash_tr = hash & (fdbRuleDbSize - 1);
+
+	pRule = fdbRuleDb[hash_tr].ruleChain;
+
+	while (pRule) {
+/*
+		MV_NFP_DBG("%s: looking %d %02x:%02x:%02x:%02x:%02x:%02x\n",
+			   __FUNCTION__, bridgeId,
+				   pRule->fdbInfo.mac[0],
+				   pRule->fdbInfo.mac[1],
+				   pRule->fdbInfo.mac[2],
+				   pRule->fdbInfo.mac[3],
+				   pRule->fdbInfo.mac[4],
+				   pRule->fdbInfo.mac[5]);
+*/
+		if ((bridgeId == pRule->fdbInfo.bridge) &&
+		    (*((MV_U16 *) (pDA + 0)) == *(MV_U16 *) (&pRule->fdbInfo.mac[0])) &&
+		    (*((MV_U16 *) (pDA + 2)) == *(MV_U16 *) (&pRule->fdbInfo.mac[2])) &&
+		    (*((MV_U16 *) (pDA + 4)) == *(MV_U16 *) (&pRule->fdbInfo.mac[4]))) {
+			pRule->mgmtInfo.new_count++;
+			break;
+		}
+		pRule = pRule->next;
+		count++;
+	}
+/*
+	if (pRule)
+		MV_NFP_DBG("%s: lookup bridge=%d %02x:%02x:%02x:%02x:%02x:%02x => if=%d flags=%x\n",
+				__FUNCTION__, bridgeId, pDA[0],pDA[1],pDA[2],pDA[3],pDA[4],pDA[5],
+				pRule->fdbInfo.ifIndex, pRule->fdbInfo.flags);
+	else
+		MV_NFP_DBG("%s: lookup bridge=%d %02x:%02x:%02x:%02x:%02x:%02x => unknown\n",
+				__FUNCTION__, bridgeId, pDA[0],pDA[1],pDA[2],pDA[3],pDA[4],pDA[5]);
+
+*/
+	return pRule;
+}
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+
+/*
+ * PPPoE Support
+ */
+#ifdef CONFIG_MV_ETH_NFP_PPP
+static INLINE void mvFpDecTTL(MV_IP_HEADER *pIpHdr)
+{
+	MV_U32 check = (MV_U32) pIpHdr->checksum;
+	check += (MV_U32) htons(0x0100);
+	pIpHdr->checksum = (MV_U16) (check + (check >= 0xFFFF));
+	pIpHdr->ttl--;
+}
+static INLINE __wsum csum_unfold(__sum16 n)
+{
+	return (__force __wsum) n;
+}
+
+static INLINE __sum16 csum_fold(__wsum sum)
+{
+      __asm__("add    %0, %1, %1, ror #16     @ csum_fold" : "=r"(sum)
+      :	"r"(sum)
+      :	"cc");
+	return (__force __sum16) (~(__force u32) sum >> 16);
+}
+
+__u32 csum_partial(const char *src, int len, __u32 sum);
+
+static INLINE void mvFpCSumInc(MV_IP_HEADER *pIpHdr, MV_U32 srcIp, MV_U32 newIp)
+{
+	MV_TCP_HEADER *pTcpHdr;
+	MV_UDP_HEADER *pUdpHdr;
+	__be32 diff[] = { ~srcIp, newIp };
+
+	pIpHdr->checksum = csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum_unfold(pIpHdr->checksum)));
+
+	switch (pIpHdr->protocol) {
+	case MV_IP_PROTO_TCP:
+		pTcpHdr = (MV_TCP_HEADER *) ((unsigned)pIpHdr + sizeof(MV_IP_HEADER));
+		pTcpHdr->chksum = csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum_unfold(pTcpHdr->chksum)));
+		break;
+	case MV_IP_PROTO_UDP:
+		pUdpHdr = (MV_UDP_HEADER *) ((unsigned)pIpHdr + sizeof(MV_IP_HEADER));
+		pUdpHdr->check = csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum_unfold(pUdpHdr->check)));
+		break;
+	}
+}
+
+static INLINE MV_U32 mvFpPppLookup(MV_U32 ifIndex)
+{
+	return pppOpen[ifIndex].pppInfo.if_ppp;
+}
+#endif /* CONFIG_MV_ETH_NFP_PPP */
+
+/* Check that protocol supported for FP NAT and extract srcPort and dstPort
+ *  (or their equivalents)  from the packet.
+ */
+MV_U8 mvFpPortsGet(MV_IP_HEADER *pIpHdr, MV_U16 *pDstPort, MV_U16 *pSrcPort)
+{
+	MV_U8 proto = pIpHdr->protocol;
+	MV_UDP_HEADER *pUdpHdr;
+	MV_TCP_HEADER *pTcpHdr;
+
+	switch (proto) {
+	case MV_IP_PROTO_TCP:
+		pTcpHdr = (MV_TCP_HEADER *) ((unsigned)pIpHdr + sizeof(MV_IP_HEADER));
+		*pDstPort = pTcpHdr->dest;
+		*pSrcPort = pTcpHdr->source;
+		break;
+
+	case MV_IP_PROTO_UDP:
+		pUdpHdr = (MV_UDP_HEADER *) ((unsigned)pIpHdr + sizeof(MV_IP_HEADER));
+		*pDstPort = pUdpHdr->dest;
+		*pSrcPort = pUdpHdr->source;
+		break;
+
+		/* Other protocols supporting NAT only without ports
+		 * case ???????:
+		 * case ???????:
+		 *     *pDstPort = 0;
+		 *     *pSrcPort = 0;
+		 *     break
+		 *
+		 */
+
+	default:
+		/* Skip NAT processing at all */
+		proto = MV_IP_PROTO_NULL;
+	}
+	return proto;
+}
+
+int mvFpProcess(MV_U32 ifIndex, MV_PKT_INFO *pPkt, MV_IP_HEADER *pIpHdr, MV_FP_STATS *pFpStats)
+{
+	MV_FP_RULE *pRt;
+	MV_U32 dip, sip;
+	MV_U8 proto;
+	MV_U16 srcPort, dstPort;
+	MV_STATUS status;
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	MV_FP_NAT_RULE *pDnatRule, *pSnatRule;
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+#ifdef CONFIG_MV_ETH_NFP_FDB
+	MV_FP_FDB_RULE *pFdb;
+#endif
+	MV_U8 *pEth = pPkt->pFrags->bufVirtPtr;
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	MV_BUF_INFO *pBuf = pPkt->pFrags;
+#endif
+#ifdef CONFIG_MV_ETH_NFP_SEC
+	MV_NFP_SEC_SPD_RULE *pSpd;
+	MV_NFP_SEC_SA_ENTRY *pSAEntry;
+	MV_ESP_HEADER *pEspHdr;
+#endif
+
+	MV_NFP_STAT(pFpStats->process++);
+
+	/* Check MAC address:
+	 *   WAN - non-promiscous mode.
+	 *       Unicast packets - NFP,
+	 *       Multicast, Broadcast - Linux
+	 *   LAN - Promiscous mode.
+	 *       LAN Unicast MAC - NFP,
+	 *       Multicast, Broadcast, Unknown Unicast - Linux
+	 */
+	if (pEth[ETH_MV_HEADER_SIZE] == 0x01) {
+		MV_NFP_STAT(pFpStats->multicast++);
+		return -1;
+	}
+#ifdef CONFIG_MV_ETH_NFP_FDB
+	if (mvFpFdbMember(ifIndex)) {
+		pFdb = mvFpFdbLookup(ifIndex, pEth + ETH_MV_HEADER_SIZE);
+		if (!pFdb) {
+			MV_NFP_STAT(pFpStats->fdb_rx_unknown++);
+			return -1;
+		}
+		if (pFdb->fdbInfo.flags & MV_FP_FDB_IS_LOCAL) {
+			/* DA is local, continue with routing */
+			MV_NFP_STAT(pFpStats->fdb_rx_local++);
+		} else {
+			/* perform bridging */
+			MV_NFP_STAT(pFpStats->fdb_bridged++);
+			return pFdb->fdbInfo.ifIndex;
+		}
+	}
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	/* Decapsulate PPPoE */
+	if (!pIpHdr) {
+		MV_PPPoE_HEADER *pPPP = (MV_PPPoE_HEADER *) pEth;
+		if ((pPPP->ethertype == 0x6488) && (pPPP->proto == 0x2100)) {
+			pIpHdr = (MV_IP_HEADER *) (pEth + ETH_MV_HEADER_SIZE +
+						   sizeof(MV_802_3_HEADER) + ETH_FP_PPPOE_HDR);
+
+			/* do not process fragments */
+			if (pIpHdr->fragmentCtrl & 0xFF3F) {
+				MV_NFP_STAT(pFpStats->ppp_rx_frag++);
+				goto out;
+			}
+
+			pBuf->bufAddrShift -= ETH_FP_PPPOE_HDR;
+			pBuf->bufPhysAddr += ETH_FP_PPPOE_HDR;
+			pBuf->bufVirtPtr += ETH_FP_PPPOE_HDR;
+			pBuf->dataSize -= ETH_FP_PPPOE_HDR;
+			pEth += ETH_FP_PPPOE_HDR;
+
+			pPkt->status = ETH_TX_IP_NO_FRAG | ETH_TX_GENERATE_IP_CHKSUM_MASK |
+			    (0x5 << ETH_TX_IP_HEADER_LEN_OFFSET);
+
+			switch (pIpHdr->protocol) {
+			case MV_IP_PROTO_TCP:
+				pPkt->status |= ETH_TX_L4_TCP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK;
+				break;
+			case MV_IP_PROTO_UDP:
+				pPkt->status |= ETH_TX_L4_UDP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK;
+				break;
+			}
+
+			MV_NFP_STAT(pFpStats->ppp_rx++);
+			MV_NFP_STAT(pFpStats->ethertype_unknown--);
+		}
+	}
+
+	if (!pIpHdr)
+		goto out;
+#endif /* CONFIG_MV_ETH_NFP_PPP */
+
+	proto = mvFpPortsGet(pIpHdr, &dstPort, &srcPort);
+
+	/* Check TTL value */
+	if (pIpHdr->ttl <= 1) {
+		/* TTL expired */
+		MV_NFP_STAT(pFpStats->ip_ttl_expired++);
+		goto out;
+	}
+
+	dip = pIpHdr->dstIP;
+	sip = pIpHdr->srcIP;
+
+#ifdef CONFIG_MV_ETH_NFP_SEC
+	/* TBD - Add statistics counters */
+	/* inbound ipsec traffic */
+	if (pIpHdr->protocol == MV_IP_PROTO_ESP) {
+
+		/* extract esp header */
+		pEspHdr = (MV_ESP_HEADER *) ((MV_U8 *) pIpHdr + sizeof(MV_IP_HEADER));
+
+		/* extract SA according to packet spi */
+		pSAEntry = mvNfpSecSARuleFind(pEspHdr->spi);
+		if (pSAEntry != NULL) {
+			if (MV_OK == mvNfpSecIncoming(pPkt, pSAEntry)) {
+				MV_NFP_STAT(pFpStats->sec_in++);
+				return MV_NFP_STOLEN;
+			} else {
+				/* TDB- handle pkt gracefully */
+				MV_NFP_STAT(pFpStats->sec_in_drop++);
+				return MV_NFP_DROP;
+
+			}
+		}
+		mvOsPrintf("mvFpProcess: no SA found for ESP packet(spi=0x%x)\n", pEspHdr->spi);
+	} else {
+		/* outbound */
+		pSpd = mvNfpSecSPDRuleFind(dip, sip, proto, dstPort, srcPort, MV_NFP_SEC_RULE_DB_OUT);
+		if (pSpd != NULL) {
+			switch (pSpd->actionType) {
+			case (MV_NFP_SEC_FWD):
+				break;
+			case (MV_NFP_SEC_SECURE):
+				status = mvNfpSecOutgoing(pPkt, pSpd->pSAEntry);
+				if (status == MV_OK) {
+					/* handled by cesa */
+					MV_NFP_STAT(pFpStats->sec_out++);
+					return MV_NFP_STOLEN;
+				} else if (status == MV_OUT_OF_RANGE) {
+					/* slow path */
+					MV_NFP_STAT(pFpStats->sec_out_slow++);
+					return MV_NFP_NONE;
+				} else {
+					/* drop packet */
+					MV_NFP_STAT(pFpStats->sec_out_drop++);
+					return MV_NFP_DROP;
+				}
+				break;
+			case (MV_NFP_SEC_DROP):
+				MV_NFP_STAT(pFpStats->sec_out_drop++);
+				return MV_NFP_DROP;
+				break;
+			}
+		}
+	}
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	proto = mvFpPortsGet(pIpHdr, &dstPort, &srcPort);
+	if (proto == MV_IP_PROTO_NULL) {
+		/* NAT not supported for this protocol */
+		MV_NFP_STAT(pFpStats->nat_bad_proto++);
+		pDnatRule = NULL;
+	} else {
+		/* Lookup NAT database accordingly with 5 tuple key */
+		pDnatRule = mvFpNatRuleFind(dip, sip, proto, dstPort, srcPort);
+	}
+	if (pDnatRule != NULL) {
+		if (pDnatRule->flags & MV_FP_DIP_CMD_MAP)
+			dip = pDnatRule->newIp;
+		if (pDnatRule->flags & MV_FP_DPORT_CMD_MAP)
+			dstPort = pDnatRule->newPort;
+	} else {
+		MV_NFP_STAT(pFpStats->dnat_not_found++);
+	}
+
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+	pRt = mvFpRuleFind(dip, sip);
+	if (pRt == NULL) {
+		/* IP Routing rule is not found: go to Linux IP stack */
+		MV_NFP_STAT(pFpStats->route_miss++);
+		goto out;
+	}
+
+	MV_NFP_STAT(pFpStats->route_hit++);
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	if ((pDnatRule != NULL) && (pDnatRule->flags & MV_FP_DNAT_CMD_MAP)) {
+		MV_NFP_STAT(pFpStats->dnat_found++);
+		pSnatRule = mvFpNatRuleFind(dip, sip, proto, dstPort, srcPort);
+	} else {
+		pSnatRule = pDnatRule;
+	}
+
+	if ((pSnatRule != NULL) && (pSnatRule->flags & MV_FP_SNAT_CMD_MAP))
+		MV_NFP_STAT(pFpStats->snat_found++);
+	else
+		MV_NFP_STAT(pFpStats->snat_not_found++);
+
+	/* Check IP awareness */
+	if ((pRt->routingInfo.aware_flags & MV_FP_DIP_CMD_MAP) && (pDnatRule == NULL)) {
+		MV_NFP_STAT(pFpStats->dnat_aware++);
+		goto out;
+	}
+
+	if ((pRt->routingInfo.aware_flags & MV_FP_SIP_CMD_MAP) && (pSnatRule == NULL)) {
+		MV_NFP_STAT(pFpStats->snat_aware++);
+		goto out;
+	}
+
+	/* Update packet accordingly with NAT rules */
+	if ((pDnatRule != NULL) || (pSnatRule != NULL))
+		mvFpNatPktUpdate(pIpHdr, pDnatRule, pSnatRule);
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+	ifIndex = pRt->routingInfo.outIfIndex;
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	/* Encapsulate PPPoE on Tx */
+	if (mvFpPppLookup(ifIndex)) {
+		if (pBuf->dataSize > 1514 + ETH_MV_HEADER_SIZE - ETH_FP_PPPOE_HDR) {
+			MV_NFP_STAT(pFpStats->ppp_tx_slow++);
+			goto out;
+		}
+
+		MV_NFP_STAT(pFpStats->ppp_tx++);
+
+		/* FIXME: pktSize is left unchanged */
+		pBuf->bufAddrShift += ETH_FP_PPPOE_HDR;
+		pBuf->bufPhysAddr -= ETH_FP_PPPOE_HDR;
+		pBuf->bufVirtPtr -= ETH_FP_PPPOE_HDR;
+		pBuf->dataSize += ETH_FP_PPPOE_HDR;
+		pEth -= ETH_FP_PPPOE_HDR;
+
+		/* -6B aligment from 32B boundary */
+		{
+			MV_U32 *d = (MV_U32 *) pEth;
+			MV_U32 *s = pppOpen[ifIndex].pppInfo.u.u32;
+
+			*(d++) = *(s++);
+			*(d++) = *(s++);
+			*(d++) = *(s++);
+			*(d++) = *(s++);
+			*(d++) = *(s++);
+			*(d++) = *(s++);
+		}
+
+		/* update payload len */
+		*(MV_U16 *) (pEth + 20) = htons(pBuf->dataSize - 14 - ETH_FP_PPPOE_HDR);
+
+		mvFpDecTTL(pIpHdr);
+#ifdef CONFIG_MV_ETH_NFP_NAT
+		if (pSnatRule)
+			mvFpCSumInc(pIpHdr, pSnatRule->srcIp, pSnatRule->newIp);
+#endif
+		pPkt->status = 0;
+		ifIndex = pppOpen[ifIndex].pppInfo.if_eth;
+
+		/* Flush and Invalidate 3rd cacheline */
+		pEth = (MV_U32) pEth & ~(CPU_D_CACHE_LINE_SIZE - 1);
+		pEth += CPU_D_CACHE_LINE_SIZE * 2;
+		mvOsCacheLineFlushInv(NULL, pEth);
+		goto end;
+	}
+#endif /* CONFIG_MV_ETH_NFP_PPP */
+
+	*(MV_U16 *) (pEth + 2) = *(MV_U16 *) (&pRt->routingInfo.dstMac[0]);
+	*(MV_U32 *) (pEth + 4) = *(MV_U32 *) (&pRt->routingInfo.dstMac[2]);
+	*(MV_U32 *) (pEth + 8) = *(MV_U32 *) (&pRt->routingInfo.srcMac[0]);
+	*(MV_U16 *) (pEth + 12) = *(MV_U16 *) (&pRt->routingInfo.srcMac[4]);
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	*(MV_U16 *) (pEth + 14) = 0x0008;
+#endif
+
+	pIpHdr->ttl--;
+
+#ifdef CONFIG_MV_ETH_NFP_TOS
+	pIpHdr->tos = pRt->routingInfo.dscp;
+	pPkt->txq = pRt->routingInfo.txq;
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+	/* find actual port inside bridge, otherwise br->xmit is called */
+	if (mvFpFdbMember(ifIndex)) {
+		pFdb = mvFpFdbLookup(ifIndex, pEth + ETH_MV_HEADER_SIZE);
+		if (pFdb) {
+			MV_NFP_STAT(pFpStats->fdb_tx_found++);
+			return pFdb->fdbInfo.ifIndex;
+		}
+	}
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+
+end:
+	return ifIndex;
+out:
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	/* restore original packet */
+	if (pBuf->bufAddrShift) {
+		pBuf->bufPhysAddr += pBuf->bufAddrShift;
+		pBuf->bufVirtPtr += pBuf->bufAddrShift;
+		pBuf->dataSize -= pBuf->bufAddrShift;
+		pBuf->bufAddrShift = 0;
+		MV_NFP_STAT(pFpStats->ppp_rx_slow++);
+	}
+#endif
+	MV_NFP_STAT(pFpStats->slowpath++);
+	return -1;
+}
+
+void mvFpStatsPrint(MV_FP_STATS *pFpStats)
+{
+#ifdef MV_FP_STATISTICS
+	mvOsPrintf("\n====================================================\n");
+	mvOsPrintf(" NFP statistics");
+	mvOsPrintf("\n-------------------------------\n");
+
+	mvOsPrintf("nfp_parsing....................%10u\n", pFpStats->parsing);
+	mvOsPrintf("nfp_process....................%10u\n", pFpStats->process);
+	mvOsPrintf("nfp_route_hit..................%10u\n", pFpStats->route_hit);
+	mvOsPrintf("nfp_route_miss.................%10u\n", pFpStats->route_miss);
+	mvOsPrintf("nfp_ethertype_unknown..........%10u\n", pFpStats->ethertype_unknown);
+	mvOsPrintf("nfp_ip_frag....................%10u\n", pFpStats->ip_frag);
+	mvOsPrintf("nfp_slowpath...................%10u\n", pFpStats->slowpath);
+	mvOsPrintf("nfp_multicast..................%10u\n", pFpStats->multicast);
+	mvOsPrintf("nfp_vlan_tagged................%10u\n", pFpStats->vlan_tagged);
+	mvOsPrintf("nfp_ttl_expired................%10u\n", pFpStats->ip_ttl_expired);
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	mvOsPrintf("nfp_nat_bad_proto..............%10u\n", pFpStats->nat_bad_proto);
+	mvOsPrintf("nfp_nat_dnat_found.............%10u\n", pFpStats->dnat_found);
+	mvOsPrintf("nfp_nat_snat_found.............%10u\n", pFpStats->snat_found);
+	mvOsPrintf("nfp_nat_dnat_not_found.........%10u\n", pFpStats->dnat_not_found);
+	mvOsPrintf("nfp_nat_snat_not_found.........%10u\n", pFpStats->snat_not_found);
+	mvOsPrintf("nfp_nat_dnat_aware.............%10u\n", pFpStats->dnat_aware);
+	mvOsPrintf("nfp_nat_snat_aware.............%10u\n", pFpStats->snat_aware);
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+	mvOsPrintf("nfp_fdb_rx_local...............%10u\n", pFpStats->fdb_rx_local);
+	mvOsPrintf("nfp_fdb_rx_unknown.............%10u\n", pFpStats->fdb_rx_unknown);
+	mvOsPrintf("nfp_fdb_tx_found...............%10u\n", pFpStats->fdb_tx_found);
+	mvOsPrintf("nfp_fdb_bridged................%10u\n", pFpStats->fdb_bridged);
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	mvOsPrintf("nfp_ppp_rx.....................%10u\n", pFpStats->ppp_rx);
+	mvOsPrintf("nfp_ppp_tx.....................%10u\n", pFpStats->ppp_tx);
+	mvOsPrintf("nfp_ppp_err....................%10u\n", pFpStats->ppp_err);
+	mvOsPrintf("nfp_ppp_rx_slow................%10u\n", pFpStats->ppp_rx_slow);
+	mvOsPrintf("nfp_ppp_tx_slow................%10u\n", pFpStats->ppp_tx_slow);
+	mvOsPrintf("nfp_ppp_rx_frag................%10u\n", pFpStats->ppp_rx_frag);
+	mvOsPrintf("nfp_ppp_tx_esp.................%10u\n", pFpStats->ppp_tx_esp);
+
+#endif /* CONFIG_MV_ETH_NFP_PPP */
+
+#ifdef CONFIG_MV_ETH_NFP_SEC
+	mvOsPrintf("nfp_sec_in.....................%10u\n", pFpStats->sec_in);
+	mvOsPrintf("nfp_sec_in_drop................%10u\n", pFpStats->sec_in_drop);
+	mvOsPrintf("nfp_sec_out....................%10u\n", pFpStats->sec_out);
+	mvOsPrintf("nfp_sec_out_drop...............%10u\n", pFpStats->sec_out_drop);
+	mvOsPrintf("nfp_sec_out_slow...............%10u\n", pFpStats->sec_out_slow);
+#endif /* CONFIG_MV_ETH_NFP_SEC */
+
+	memset(pFpStats, 0, sizeof(MV_FP_STATS));
+#endif /* MV_FP_STATISTICS */
+
+	mvOsPrintf("\n");
+	mvOsPrintf("Routing rules: Set=%u, Update=%u, Delete=%u, maxDepth=%u\n",
+		   nfpRuleSetCount, nfpRuleUpdateCount, nfpRuleDeleteCount, nfpHashMaxDepth);
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	mvOsPrintf("\n");
+	mvOsPrintf("NAT rules:     Set=%u, Update=%u, Delete=%u, maxDepth=%u\n",
+		   natRuleSetCount, natRuleUpdateCount, natRuleDeleteCount, natHashMaxDepth);
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+	mvOsPrintf("\n");
+	mvOsPrintf("FDB rules:     Set=%u, Update=%u, Delete=%u, maxDepth=%u\n",
+		   fdbRuleSetCount, fdbRuleUpdateCount, fdbRuleDeleteCount, fdbHashMaxDepth);
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfp.h b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfp.h
new file mode 100755
index 0000000..c7337da
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfp.h
@@ -0,0 +1,577 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvNfp.h - Header File for Marvell NFP (Routing and NAT)
+*
+* DESCRIPTION:
+*       This header file contains macros, typedefs and function declarations
+* 	specific to the Marvell Network Fast Processing (Routing and NAT).
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __mvNfp_h__
+#define __mvNfp_h__
+
+/* includes */
+#include "mvTypes.h"
+#include "mvCommon.h"
+#include "mvStack.h"
+#include "mv802_3.h"
+#include "eth/mvEth.h"
+#include "eth/gbe/mvEthGbe.h"
+#include "mvSysHwConfig.h"
+
+/* defines */
+#define ETH_FP_IFINDEX_MAX     	128
+#define ETH_FP_PPPOE_HDR        8	/* PPP header is 6, PPPoE header is 2 */
+#define ETH_FP_MTU 		(1518 + ETH_MV_HEADER_SIZE)	/* maximum frame size incluing MH */
+#define ETH_FP_PPPOE_MTU 		(ETH_FP_MTU - ETH_FP_PPPOE_HDR)	/* maximum frame size for PPPoE */
+
+/* uncomment to open some debug prints on adding and updating NFP rules */
+#define MV_FP_DEBUG
+#undef MV_FP_DEBUG
+
+#ifdef MV_FP_DEBUG
+#   define MV_NFP_DBG(fmt, arg...) printk(KERN_INFO fmt, ##arg)
+#else
+#   define MV_NFP_DBG(fmt, arg...)
+#endif
+
+#ifdef MV_FP_STATISTICS
+# define MV_NFP_STAT(CODE) CODE;
+#else
+# define MV_NFP_STAT(CODE)
+#endif
+
+/* enumerations */
+typedef enum {
+	MV_FP_ROUTE_CMD,	/* perform NFP routing */
+	MV_FP_DROP_CMD,		/* drop packet */
+	MV_FP_TO_STACK_CMD,	/* pass packet to linux stack */
+	MV_FP_DIP_CMD,		/* replace DIP */
+	MV_FP_SIP_CMD,		/* replace SIP */
+	MV_FP_DPORT_CMD,	/* replace DPORT */
+	MV_FP_SPORT_CMD,	/* replace SPORT */
+	MV_FP_BRIDGE_CMD,	/* perform fast path bridging */
+	MV_FP_PPP_CMD,		/* perform fast path pppoe */
+} MV_FP_CMD_TYPE;
+
+typedef enum {
+	MV_NFP_DROP = -3,
+	MV_NFP_STOLEN = -2,
+	MV_NFP_NONE = -1,
+	/* positive values are valid */
+} MV_NFP_IF_INDEX;
+
+#define MV_FP_NULL_BINDING  0
+#define MV_FP_NULL_BINDING_SET	(1 << MV_FP_ROUTE_CMD)
+
+#define MV_FP_DIP_CMD_MAP   (1 << MV_FP_DIP_CMD)
+#define MV_FP_DPORT_CMD_MAP (1 << MV_FP_DPORT_CMD)
+#define MV_FP_DNAT_CMD_MAP  (MV_FP_DIP_CMD_MAP | MV_FP_DPORT_CMD_MAP)
+
+#define MV_FP_SIP_CMD_MAP   (1 << MV_FP_SIP_CMD)
+#define MV_FP_SPORT_CMD_MAP (1 << MV_FP_SPORT_CMD)
+#define MV_FP_SNAT_CMD_MAP  (MV_FP_SIP_CMD_MAP | MV_FP_SPORT_CMD_MAP)
+
+typedef enum {
+	MV_FP_STATIC_RULE,	/* a static rule created by the user */
+	MV_FP_DYNAMIC_RULE	/* a dynamic rule */
+} MV_FP_RULE_TYPE;
+
+/* structure definitions (used by the NFP Manager and the NFP Database)*/
+typedef struct {
+	MV_FP_CMD_TYPE actionType;
+	MV_U32 old_count;
+	int new_count;
+	MV_FP_RULE_TYPE ruleType;
+	int dnat_aware_refcnt;
+	int snat_aware_refcnt;
+
+} MV_FP_RULE_MGMT_INFO;
+
+typedef struct {
+	MV_U32 dstIp;
+	MV_U32 srcIp;
+	MV_U32 defGtwIp;
+	MV_U8 dscp;
+	MV_U8 txq;
+	MV_U16 reserved1;
+	MV_U8 reserved2;
+	MV_U8 aware_flags;
+	/* dstMac should be 2 byte aligned */
+	MV_U8 dstMac[MV_MAC_ADDR_SIZE];
+	MV_U8 srcMac[MV_MAC_ADDR_SIZE];
+	MV_U8 inIfIndex;	/* Linux interface index */
+	MV_U8 outIfIndex;	/* Linux interface index */
+} MV_FP_RULE_ROUTING_INFO;
+
+typedef struct _mv_fp_rule {
+	struct _mv_fp_rule *next;
+
+	MV_FP_RULE_MGMT_INFO mgmtInfo;
+	MV_FP_RULE_ROUTING_INFO routingInfo;
+
+} MV_FP_RULE;
+
+struct ruleHashBucket {
+	MV_FP_RULE *ruleChain;	/* This is an entry in the rule hash table. */
+
+	/* Add additional fields (such as a lock) here if required */
+};
+
+#define MV_JHASH_MIX(a, b, c)        \
+{                                   \
+    a -= b; a -= c; a ^= (c>>13);   \
+    b -= c; b -= a; b ^= (a<<8);    \
+    c -= a; c -= b; c ^= (b>>13);   \
+    a -= b; a -= c; a ^= (c>>12);   \
+    b -= c; b -= a; b ^= (a<<16);   \
+    c -= a; c -= b; c ^= (b>>5);    \
+    a -= b; a -= c; a ^= (c>>3);    \
+    b -= c; b -= a; b ^= (a<<10);   \
+    c -= a; c -= b; c ^= (b>>15);   \
+}
+
+/* The golden ration: an arbitrary value */
+#define MV_JHASH_GOLDEN_RATIO           0x9e3779b9
+
+extern MV_U32 fp_ip_jhash_iv;
+
+static INLINE MV_U32 mv_jhash_3words(MV_U32 a, MV_U32 b, MV_U32 c, MV_U32 initval)
+{
+	a += MV_JHASH_GOLDEN_RATIO;
+	b += MV_JHASH_GOLDEN_RATIO;
+	c += initval;
+	MV_JHASH_MIX(a, b, c);
+
+	return c;
+}
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+
+typedef struct _mv_fp_nat_rule {
+	struct _mv_fp_nat_rule *next;
+	MV_U32 old_count;
+	MV_U32 new_count;
+
+	/* Original packet information */
+	/* Fields will contain invalid values if they are irrelevant */
+	MV_U32 srcIp;
+	MV_U32 dstIp;
+	MV_U16 srcPort;
+	MV_U16 dstPort;
+	MV_U8 proto;
+
+	/* NAT information */
+	MV_U8 flags;
+	MV_U32 newIp;
+	MV_U16 newPort;
+
+} MV_FP_NAT_RULE;
+
+struct natRuleHashBucket {
+	MV_FP_NAT_RULE *natRuleChain;	/* This is an entry in the NAT rule hash table. */
+
+	/* Add additional fields (such as a lock) here if required */
+};
+
+extern struct natRuleHashBucket *natRuleDb;
+extern MV_U32 natRuleDbSize;
+extern MV_U32 natRuleUpdateCount, natRuleSetCount, natRuleDeleteCount;
+extern MV_U32 natHashMaxDepth;
+
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+/*
+ * PPPoE Support
+ */
+#ifdef CONFIG_MV_ETH_NFP_PPP
+
+typedef struct {
+	MV_U16 tag;
+	MV_U8 da[MV_MAC_ADDR_SIZE];
+	MV_U8 sa[MV_MAC_ADDR_SIZE];
+	MV_U16 ethertype;
+	MV_U8 version;
+	MV_U8 code;
+	MV_U16 session;
+	MV_U16 len;
+	MV_U16 proto;
+} __attribute__ ((packed)) MV_PPPoE_HEADER;
+
+typedef struct {
+	union {
+		MV_PPPoE_HEADER ppp;
+		MV_U32 u32[6];
+	} u;
+	MV_U32 if_ppp;		/* e.g. ppp0 */
+	MV_U32 if_eth;		/* e.g. eth0 */
+	MV_U32 channel;
+} MV_FP_RULE_PPP_INFO;
+
+typedef struct _mv_fp_ppp_rule {
+	struct _mv_fp_ppp_rule *next;
+
+	MV_FP_RULE_MGMT_INFO mgmtInfo;
+	MV_FP_RULE_PPP_INFO pppInfo;
+
+} MV_FP_PPP_RULE;
+
+extern MV_FP_PPP_RULE pppOpen[];
+
+#endif /* CONFIG_MV_ETH_NFP_PPP */
+
+/*
+ * 802.1D Support
+ */
+#ifdef CONFIG_MV_ETH_NFP_FDB
+
+#define MV_FP_FDB_IS_LOCAL 1
+
+typedef struct {
+	MV_U16 flags;
+	MV_U8 mac[6];
+	MV_U32 ifIndex;
+	MV_U32 bridge;
+} MV_FP_RULE_FDB_INFO;
+
+typedef struct _mv_fp_fdb_rule {
+	struct _mv_fp_fdb_rule *next;
+
+	MV_FP_RULE_MGMT_INFO mgmtInfo;
+	MV_FP_RULE_FDB_INFO fdbInfo;
+
+} MV_FP_FDB_RULE;
+
+struct fdbRuleHashBucket {
+	MV_FP_FDB_RULE *ruleChain;
+};
+
+extern struct fdbRuleHashBucket *fdbRuleDb;
+extern MV_U32 fdbRuleDbSize;
+extern MV_U32 fdbMember[];
+extern MV_U32 fdbRuleUpdateCount, fdbRuleSetCount, fdbRuleDeleteCount;
+extern MV_U32 fdbHashMaxDepth;
+
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+
+typedef struct {
+	MV_U32 parsing;
+	MV_U32 process;
+	MV_U32 route_miss;
+	MV_U32 route_hit;
+	MV_U32 ip_ttl_expired;
+	MV_U32 slowpath;
+	MV_U32 multicast;
+	MV_U32 ethertype_unknown;
+	MV_U32 ip_frag;
+	MV_U32 vlan_tagged;
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+	MV_U32 nat_bad_proto;
+	MV_U32 dnat_aware;
+	MV_U32 snat_aware;
+	MV_U32 dnat_found;
+	MV_U32 snat_found;
+	MV_U32 dnat_not_found;
+	MV_U32 snat_not_found;
+#endif				/* CONFIG_MV_ETH_NFP_NAT */
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+	MV_U32 fdb_rx_local;
+	MV_U32 fdb_rx_unknown;
+	MV_U32 fdb_tx_found;
+	MV_U32 fdb_bridged;
+#endif				/* CONFIG_MV_ETH_NFP_FDB */
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	MV_U32 ppp_rx;
+	MV_U32 ppp_rx_slow;
+	MV_U32 ppp_rx_frag;
+	MV_U32 ppp_tx;
+	MV_U32 ppp_tx_slow;
+	MV_U32 ppp_tx_esp;
+	MV_U32 ppp_err;
+#endif				/* CONFIG_MV_ETH_NFP_PPP */
+
+#ifdef CONFIG_MV_ETH_NFP_SEC
+	MV_U32 sec_in;
+	MV_U32 sec_in_drop;
+	MV_U32 sec_out;
+	MV_U32 sec_out_drop;
+	MV_U32 sec_out_slow;
+#endif				/* CONFIG_MV_ETH_NFP_SEC */
+
+} MV_FP_STATS;
+
+static INLINE MV_IP_HEADER *mvFpParsing(MV_PKT_INFO *pPktInfo, MV_FP_STATS *pFpStats)
+{
+	MV_U8 *pData;
+	MV_IP_HEADER *pIpHdr;
+	MV_U32 tx_status;
+
+	pData = (MV_U8 *) pPktInfo->pFrags[0].bufVirtPtr + ETH_MV_HEADER_SIZE;
+
+	MV_NFP_STAT(pFpStats->parsing++);
+
+	/* Check LLC/SNAP and IP header */
+	if (((pPktInfo->status & ETH_RX_NOT_LLC_SNAP_FORMAT_MASK) == 0) ||
+	    ((pPktInfo->status & ETH_RX_IP_HEADER_OK_MASK) == 0)) {
+		/* Non IP packet: go to Linux IP stack */
+		MV_NFP_STAT(pFpStats->ethertype_unknown++);
+		return NULL;
+	}
+
+	if (pPktInfo->fragIP) {
+		MV_NFP_STAT(pFpStats->ip_frag++);
+		return NULL;
+	}
+
+	tx_status = (ETH_TX_GENERATE_IP_CHKSUM_MASK | ETH_TX_IP_NO_FRAG | (5 << ETH_TX_IP_HEADER_LEN_OFFSET));
+
+	/* Calculate start of IP header */
+	if ((pPktInfo->status & ETH_RX_VLAN_TAGGED_FRAME_MASK)) {
+		MV_NFP_STAT(pFpStats->vlan_tagged++);
+		pIpHdr = (MV_IP_HEADER *) (pData + sizeof(MV_802_3_HEADER) + MV_VLAN_HLEN);
+		tx_status |= ETH_TX_VLAN_TAGGED_FRAME_MASK;
+	} else {
+		pIpHdr = (MV_IP_HEADER *) (pData + sizeof(MV_802_3_HEADER));
+	}
+
+	if ((pPktInfo->status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_TCP_TYPE)
+		tx_status |= (ETH_TX_L4_TCP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK);
+	else if ((pPktInfo->status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_UDP_TYPE)
+		tx_status |= (ETH_TX_L4_UDP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK);
+
+	pPktInfo->status = tx_status;
+
+	return pIpHdr;
+}
+
+/* Initialize NFP Rule Database (Routing + ARP information table) */
+MV_STATUS mvFpRuleDbInit(MV_U32 dbSize);
+/* Clear NFP Rule Database (Routing + ARP information table) */
+MV_STATUS mvFpRuleDbClear(void);
+/* Free Rule Database memory */
+void mvFpRuleDbDestroy(void);
+/* Print NFP Rule Database (Routing + ARP information table) */
+MV_STATUS mvFpRuleDbPrint(void);
+/* Copy all the information from src_rule to new_rule */
+/* Warning - doesn't perform any checks on memory, just copies */
+/* count is set to zero in new_rule */
+/* Note: the next pointer is not updated . */
+void mvFpRuleCopy(MV_FP_RULE *newRule, const MV_FP_RULE *srcRule);
+/* Get the maximum count value for a rule with srcIp == given ip */
+MV_U32 mvFpMaxArpCountGet(MV_U32 ip);
+/* Get the count value for a rule that matches the given SIP, DIP */
+MV_U32 mvFpRouteCountGet(MV_U32 srcIp, MV_U32 dstIp);
+/* Set a Routing Rule: create a new rule or update an existing rule  */
+/* in the Routing + ARP information table */
+MV_STATUS mvFpRuleSet(MV_FP_RULE *rule);
+/* Delete a specified rule from the Routing + ARP information table */
+MV_STATUS mvFpRuleDelete(MV_FP_RULE *rule);
+/* Set a Routing ToS Rule */
+MV_STATUS mvFpToSSet(MV_FP_RULE *rule);
+/* Print a Rule */
+void mvFpRulePrint(const MV_FP_RULE *rule);
+/* Enable NFP */
+void mvFpEnable(void);
+/* Give all packets to Linux IP stack */
+void mvFpDisable(void);
+MV_STATUS mvFpInit(void);
+int mvFpProcess(MV_U32 ifIndex, MV_PKT_INFO *pPkt, MV_IP_HEADER *pIpHdr, MV_FP_STATS *pFpStats);
+void mvFpStatsPrint(MV_FP_STATS *pFpStats);
+
+/* NAT SUPPORT Functions */
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+/* Find and return the first matching rule */
+static INLINE MV_FP_NAT_RULE *mvFpNatRuleFind(MV_U32 dstIp, MV_U32 srcIp, MV_U8 proto, MV_U16 dport, MV_U16 sport)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_NAT_RULE *pNatRule;
+	int count = 0;
+
+	hash = mv_jhash_3words(dstIp, srcIp, (MV_U32) ((dport << 16) | sport),
+			       (MV_U32) ((fp_ip_jhash_iv << 8) | proto));
+	hash_tr = hash & (natRuleDbSize - 1);
+/*
+    mvOsPrintf("mvFpNatRuleFind: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%08x (0x%x)\n",
+		dstIp, srcIp, proto, dport, sport, hash, hash_tr);
+*/
+	pNatRule = natRuleDb[hash_tr].natRuleChain;
+
+	while (pNatRule) {
+		/* look for a matching rule */
+		if ((pNatRule->dstIp == dstIp) &&
+		    (pNatRule->srcIp == srcIp) &&
+		    (pNatRule->proto == proto) && (pNatRule->dstPort == dport) && (pNatRule->srcPort == sport)) {
+			pNatRule->new_count++;
+			return pNatRule;
+		}
+		pNatRule = pNatRule->next;
+		count++;
+	}
+	return NULL;
+}
+
+/* Initialize NFP NAT Rule Database (SNAT + DNAT table) */
+MV_STATUS mvFpNatDbInit(MV_U32 dbSize);
+
+/* Clear NFP NAT Rule Database (SNAT + DNAT table) */
+MV_STATUS mvFpNatDbClear(void);
+
+/* Free NAT Database memory */
+void mvFpNatDbDestroy(void);
+
+/* Set a NAT rule: create a new rule or update an existing rule in the SNAT + DNAT table */
+MV_STATUS mvFpNatRuleSet(MV_FP_NAT_RULE *natRule);
+
+MV_STATUS mvFpRuleAwareSet(MV_FP_RULE *pSetRule);
+
+/* Delete a specified NAT rule from the SNAT + DNAT table */
+MV_STATUS mvFpNatRuleDelete(MV_FP_NAT_RULE *natRule);
+
+/* Get the count value for a NAT rule */
+MV_U32 mvFpNatCountGet(MV_U32 srcIp, MV_U32 dstIp, MV_U16 srcPort, MV_U16 dstPort, MV_U8 proto);
+
+/* Print NFP NAT Rule Database (SNAT + DNAT table) */
+MV_STATUS mvFpNatDbPrint(void);
+
+/* Print a NAT Rule */
+void mvFpNatRulePrint(const MV_FP_NAT_RULE *rule);
+
+/* Extract dstPort and srcPort values from the packet */
+MV_U8 mvFpNatPortsGet(MV_IP_HEADER *pIpHdr, MV_U16 *pDstPort, MV_U16 *pSrcPort);
+
+int mvFpNatPktUpdate(MV_IP_HEADER *pIpHdr, MV_FP_NAT_RULE *pDnatRule, MV_FP_NAT_RULE *pSnatRule);
+
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+
+#ifdef CONFIG_MV_ETH_NFP_FDB
+
+/* Init NFP Bridge Rule Database */
+MV_STATUS mvFpFdbInit(MV_U32 dbSize);
+
+/* Clear NFP Bridge Rule Database */
+MV_STATUS mvFpFdbClear(void);
+
+/* Destroy NFP Bridge Rule Database */
+void mvFpFdbDestroy(void);
+
+/* Add NFP Bridge Rule */
+MV_STATUS mvFpFdbRuleSet(MV_FP_FDB_RULE *rule);
+
+/* Delete NFP Bridge Rule Database */
+MV_STATUS mvFpFdbRuleDel(MV_FP_FDB_RULE *rule);
+
+/* Aging NFP Bridge Rule Database */
+MV_U32 mvFpFdbRuleAge(MV_FP_FDB_RULE *rule);
+
+/* Print NFP Bridge Rule Database */
+MV_STATUS mvFpFdbPrint(void);
+
+#endif /* CONFIG_MV_ETH_NFP_FDB */
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+
+/* Init NFP PPPoE Rule Database */
+MV_STATUS mvFpPppInit(void);
+
+/* Clear NFP PPPoE Rule Database */
+MV_STATUS mvFpPppClear(void);
+
+/* Destroy NFP PPPoE Rule Database */
+void mvFpPppDestroy(void);
+
+/* Add NFP PPPoE Rule */
+MV_STATUS mvFpPppRuleSet(MV_FP_PPP_RULE *rule);
+
+/* Delete NFP PPPoE Rule Database */
+MV_STATUS mvFpPppRuleDel(MV_FP_PPP_RULE *rule);
+
+/* Aging NFP PPPoE Rule Database */
+MV_U32 mvFpPppRuleAge(MV_FP_PPP_RULE *rule);
+
+/* Print NFP PPPoE Rule Database */
+MV_STATUS mvFpPppPrint(void);
+
+/* Add PPPoE header */
+int mvFpPPPoE(MV_U32 ifIndex, MV_PKT_INFO *pPkt, MV_FP_STATS *pFpStats);
+
+/* Get physical interface the PPP runs over */
+MV_U32 mvFpPppPhyIf(MV_U32 ifIndex);
+
+#endif /* CONFIG_MV_ETH_NFP_PPP */
+
+#ifdef CONFIG_MV_ETH_NFP_SEC
+MV_VOID mvNfpSecDbPrint(MV_VOID);
+#endif /* CONFIG_MV_ETH_NFP_SEC */
+
+#endif /* __mvNfp_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpFdb.c b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpFdb.c
new file mode 100755
index 0000000..93f83dd
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpFdb.c
@@ -0,0 +1,309 @@
+/*******************************************************************************
+Copyright (C) Marvell Interfdbional Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+Interfdbional Ltd. and/or its affiliates ("Marvell") under the following
+alterfdbive licensing terms.  Once you have made an election to distribute the
+File under one of the following license alterfdbives, please (i) delete this
+introductory statement regarding license alterfdbives, (ii) delete the two
+license alterfdbives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvFastPath.c - Marvell Fast Route Routing and Bridge
+*
+* DESCRIPTION:
+*
+*       Supported Features:
+*       - OS independent.
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvOs.h"
+#include "mvDebug.h"
+#include "eth/nfp/mvNfp.h"
+#include "eth/mvEth.h"
+
+struct fdbRuleHashBucket *fdbRuleDb;
+MV_U32 fdbRuleDbSize;
+MV_U32 fdbMember[ETH_FP_IFINDEX_MAX];
+MV_U32 fdbRuleUpdateCount = 0;
+MV_U32 fdbRuleSetCount = 0;
+MV_U32 fdbRuleDeleteCount = 0;
+MV_U32 fdbHashMaxDepth;
+
+MV_STATUS mvFpFdbInit(MV_U32 dbSize)
+{
+	fdbRuleDb = (struct fdbRuleHashBucket *)mvOsMalloc(sizeof(struct fdbRuleHashBucket) * dbSize);
+	if (fdbRuleDb == NULL) {
+		mvOsPrintf("NFP (fdb): not enough memory\n");
+		return MV_NO_RESOURCE;
+	}
+	fdbRuleDbSize = dbSize;
+	memset(fdbRuleDb, 0, sizeof(struct fdbRuleHashBucket) * fdbRuleDbSize);
+	memset(fdbMember, 0, sizeof(fdbMember));
+
+	mvOsPrintf("NFP (fdb) init %d entries, %d bytes\n",
+		   fdbRuleDbSize, sizeof(struct fdbRuleHashBucket) * fdbRuleDbSize);
+	return MV_OK;
+}
+
+/* Clear Fast Route Bridge Rule Database (SNAT + DNAT table) */
+MV_STATUS mvFpFdbClear(void)
+{
+	MV_U32 i = fdbRuleDbSize;
+	MV_FP_FDB_RULE *rule, *tmp;
+
+	if (fdbRuleDb != NULL)
+		return MV_NOT_INITIALIZED;
+
+	while (i--) {
+		rule = fdbRuleDb[i].ruleChain;
+		while (rule) {
+			tmp = rule;
+			rule = rule->next;
+			mvOsFree(tmp);
+		}
+		fdbRuleDb[i].ruleChain = NULL;
+	}
+	return MV_OK;
+}
+
+void mvFpFdbDestroy(void)
+{
+	if (fdbRuleDb != NULL)
+		mvOsFree(fdbRuleDb);
+}
+
+static INLINE int mvFpFdbRuleCmp(MV_FP_RULE_FDB_INFO *rule1, MV_FP_RULE_FDB_INFO *rule2)
+{
+	return !((rule1->bridge == rule2->bridge) &&
+		 (rule1->ifIndex == rule2->ifIndex) && !memcmp(rule1->mac, rule2->mac, 6));
+}
+
+static INLINE MV_U32 mvFpFdbRuleHash(MV_FP_FDB_RULE *rule)
+{
+	return mv_jhash_3words(rule->fdbInfo.bridge, 0, *(MV_U32 *) (rule->fdbInfo.mac + 2), fp_ip_jhash_iv);
+}
+
+MV_STATUS mvFpFdbRuleSet(MV_FP_FDB_RULE *newrule)
+{
+	int depth = 0;
+	MV_U32 hash;
+	MV_FP_FDB_RULE *rule;
+
+	/* ignore foreign ifindex */
+	if (newrule->fdbInfo.ifIndex >= ETH_FP_IFINDEX_MAX)
+		return MV_OUT_OF_RANGE;
+
+	hash = mvFpFdbRuleHash(newrule);
+	hash &= (fdbRuleDbSize - 1);
+
+	rule = fdbRuleDb[hash].ruleChain;
+	while (rule) {
+		if (!mvFpFdbRuleCmp(&rule->fdbInfo, &newrule->fdbInfo)) {
+			fdbRuleUpdateCount++;
+			goto out;
+		}
+		depth++;
+		rule = rule->next;
+	}
+	fdbRuleSetCount++;
+	if (depth > fdbHashMaxDepth)
+		fdbHashMaxDepth = depth;
+
+	rule = mvOsMalloc(sizeof(MV_FP_FDB_RULE));
+
+	if (!rule) {
+		mvOsPrintf("NFP (fdb): can't allocate new rule\n");
+		return MV_FAIL;
+	}
+
+	/* FIXME: No spinlocks */
+	rule->next = fdbRuleDb[hash].ruleChain;
+	fdbRuleDb[hash].ruleChain = rule;
+out:
+	mvOsMemcpy(rule, newrule, sizeof(MV_FP_FDB_RULE));
+
+	if (rule->fdbInfo.flags & MV_FP_FDB_IS_LOCAL) {
+		fdbMember[rule->fdbInfo.ifIndex] = rule->fdbInfo.bridge;
+		fdbMember[rule->fdbInfo.bridge] = rule->fdbInfo.bridge;
+	}
+
+	MV_NFP_DBG("NFP (fdb): new bridge=%d ifIndex=%d %02X:%02X:%02X:%02X:%02X:%02X flags=%x\n",
+		   rule->fdbInfo.bridge, rule->fdbInfo.ifIndex,
+		   rule->fdbInfo.mac[0], rule->fdbInfo.mac[1], rule->fdbInfo.mac[2],
+		   rule->fdbInfo.mac[3], rule->fdbInfo.mac[4], rule->fdbInfo.mac[5], rule->fdbInfo.flags);
+
+	return MV_OK;
+}
+
+MV_STATUS mvFpFdbRuleDel(MV_FP_FDB_RULE *oldrule)
+{
+	MV_U32 hash;
+	MV_FP_FDB_RULE *rule, *prev;
+
+	/* ignore foreign ifindex */
+	if (oldrule->fdbInfo.ifIndex >= ETH_FP_IFINDEX_MAX)
+		return MV_OUT_OF_RANGE;
+
+	if (oldrule->fdbInfo.flags & MV_FP_FDB_IS_LOCAL) {
+		fdbMember[oldrule->fdbInfo.ifIndex] = 0;
+		fdbMember[oldrule->fdbInfo.bridge] = 0;
+		MV_NFP_DBG("NFP (fdb): del member bridge=%d ifIndex=%d\n",
+			   oldrule->fdbInfo.bridge, oldrule->fdbInfo.ifIndex);
+	}
+
+	hash = mvFpFdbRuleHash(oldrule);
+	hash &= (fdbRuleDbSize - 1);
+
+	rule = fdbRuleDb[hash].ruleChain;
+	prev = NULL;
+
+	while (rule) {
+		if (!mvFpFdbRuleCmp(&rule->fdbInfo, &oldrule->fdbInfo)) {
+
+			if (prev)
+				prev->next = rule->next;
+			else
+				fdbRuleDb[hash].ruleChain = rule->next;
+
+			fdbRuleDeleteCount++;
+			MV_NFP_DBG
+			    ("NFP (fdb): del bridge=%d ifIndex=%d %02X:%02X:%02X:%02X:%02X:%02X flags=%x count=%d\n",
+			     rule->fdbInfo.bridge, rule->fdbInfo.ifIndex, rule->fdbInfo.mac[0], rule->fdbInfo.mac[1],
+			     rule->fdbInfo.mac[2], rule->fdbInfo.mac[3], rule->fdbInfo.mac[4], rule->fdbInfo.mac[5],
+			     rule->fdbInfo.flags, rule->mgmtInfo.new_count);
+
+			mvOsFree(rule);
+			return MV_OK;
+		}
+
+		prev = rule;
+		rule = rule->next;
+	}
+
+	return MV_NOT_FOUND;
+}
+
+MV_U32 mvFpFdbRuleAge(MV_FP_FDB_RULE *oldrule)
+{
+	MV_U32 hash, age;
+	MV_FP_FDB_RULE *rule, *prev;
+
+	/* ignore foreign ifindex */
+	if (oldrule->fdbInfo.ifIndex >= ETH_FP_IFINDEX_MAX)
+		return 0;
+
+	hash = mvFpFdbRuleHash(oldrule);
+	hash &= (fdbRuleDbSize - 1);
+
+	rule = fdbRuleDb[hash].ruleChain;
+	prev = NULL;
+
+	while (rule) {
+		if (!mvFpFdbRuleCmp(&rule->fdbInfo, &oldrule->fdbInfo)) {
+
+			MV_NFP_DBG
+			    ("NFP (fdb): age bridge=%d ifIndex=%d %02X:%02X:%02X:%02X:%02X:%02X flags=%x age=%d\n",
+			     rule->fdbInfo.bridge, rule->fdbInfo.ifIndex, rule->fdbInfo.mac[0], rule->fdbInfo.mac[1],
+			     rule->fdbInfo.mac[2], rule->fdbInfo.mac[3], rule->fdbInfo.mac[4], rule->fdbInfo.mac[5],
+			     rule->fdbInfo.flags, rule->mgmtInfo.new_count);
+
+			age = rule->mgmtInfo.new_count;
+			rule->mgmtInfo.new_count = 0;
+			return age;
+
+		}
+
+		prev = rule;
+		rule = rule->next;
+	}
+
+	return 0;
+}
+
+static void mvFpFdbRulePrint(MV_FP_FDB_RULE *rule, MV_U32 hash)
+{
+	mvOsPrintf("NFP (fdb): 0x%x bridge=%d ifIndex=%d %02X:%02X:%02X:%02X:%02X:%02X flags=%x count=%d\n",
+		   mvFpFdbRuleHash((MV_FP_FDB_RULE *) rule),
+		   rule->fdbInfo.bridge, rule->fdbInfo.ifIndex,
+		   rule->fdbInfo.mac[0], rule->fdbInfo.mac[1], rule->fdbInfo.mac[2],
+		   rule->fdbInfo.mac[3], rule->fdbInfo.mac[4], rule->fdbInfo.mac[5],
+		   rule->fdbInfo.flags, rule->mgmtInfo.new_count);
+}
+
+MV_STATUS mvFpFdbPrint(void)
+{
+	MV_U32 i = fdbRuleDbSize;
+	MV_FP_FDB_RULE *rule;
+
+	for (i = 0; i < ETH_FP_IFINDEX_MAX; i++) {
+		if (fdbMember[i])
+			mvOsPrintf("NFP (fdb): bridge=%d ifIndex=%d\n", fdbMember[i], i);
+	}
+
+	for (i = 0; i < fdbRuleDbSize; i++) {
+		rule = fdbRuleDb[i].ruleChain;
+
+		while (rule) {
+			mvFpFdbRulePrint(rule, i);
+			rule = rule->next;
+		}
+	}
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpNat.c b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpNat.c
new file mode 100755
index 0000000..f191ad7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpNat.c
@@ -0,0 +1,365 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* includes */
+#include "mvTypes.h"
+#include "mvOs.h"
+#include "mvStack.h"
+#include "mvDebug.h"
+#include "eth/nfp/mvNfp.h"
+#include "eth/mvEth.h"
+
+struct natRuleHashBucket *natRuleDb;
+MV_U32 natRuleDbSize;
+
+MV_U32 natRuleUpdateCount = 0;
+MV_U32 natRuleSetCount = 0;
+MV_U32 natRuleDeleteCount = 0;
+MV_U32 natHashMaxDepth = 0;
+
+/* Initialize NFP NAT Rule Database (SNAT + DNAT table) */
+MV_STATUS mvFpNatDbInit(MV_U32 dbSize)
+{
+	natRuleDb = (struct natRuleHashBucket *)mvOsMalloc(sizeof(struct natRuleHashBucket) * dbSize);
+	if (natRuleDb == NULL) {
+		mvOsPrintf("NFP NAT Rule DB: Not Enough Memory\n");
+		return MV_NO_RESOURCE;
+	}
+	natRuleDbSize = dbSize;
+	memset(natRuleDb, 0, sizeof(struct natRuleHashBucket) * natRuleDbSize);
+
+	natRuleSetCount = natRuleDeleteCount = natRuleUpdateCount = 0;
+
+	mvOsPrintf("mvFpNatDb (%p): %d entries, %d bytes\n",
+		   natRuleDb, natRuleDbSize, sizeof(struct natRuleHashBucket) * natRuleDbSize);
+
+	return MV_OK;
+}
+
+/* Clear NFP NAT Rule Database (SNAT + DNAT table) */
+MV_STATUS mvFpNatDbClear(void)
+{
+	MV_U32 i = 0;
+	MV_FP_NAT_RULE *currRule;
+	MV_FP_NAT_RULE *tmpRule;
+
+	if (natRuleDb == NULL)
+		return MV_NOT_INITIALIZED;
+
+	for (i = 0; i < natRuleDbSize; i++) {
+		currRule = natRuleDb[i].natRuleChain;
+		while (currRule != NULL) {
+			tmpRule = currRule;
+			currRule = currRule->next;
+			mvOsFree(tmpRule);
+		}
+		natRuleDb[i].natRuleChain = NULL;
+	}
+	return MV_OK;
+}
+
+/* Free NAT Database memory */
+void mvFpNatDbDestroy(void)
+{
+	if (natRuleDb != NULL)
+		mvOsFree(natRuleDb);
+}
+
+static void mvFpNatRuleUpdate(MV_FP_NAT_RULE *dstRule, const MV_FP_NAT_RULE *srcRule)
+{
+	dstRule->flags = srcRule->flags;
+	dstRule->newIp = srcRule->newIp;
+	dstRule->newPort = srcRule->newPort;
+	dstRule->new_count = srcRule->new_count;
+	dstRule->old_count = srcRule->old_count;
+}
+
+/* Set a NAT rule: create a new rule or update an existing rule in the SNAT + DNAT table */
+MV_STATUS mvFpNatRuleSet(MV_FP_NAT_RULE *pSetRule)
+{
+	int depth = 0;
+	MV_U32 hash, hash_tr;
+	MV_FP_NAT_RULE *pNatRule, *pNewRule;
+
+	hash = mv_jhash_3words(pSetRule->dstIp, pSetRule->srcIp,
+			       (MV_U32) ((pSetRule->dstPort << 16) | pSetRule->srcPort),
+			       (MV_U32) ((fp_ip_jhash_iv << 8) | pSetRule->proto));
+	hash_tr = hash & (natRuleDbSize - 1);
+	pNatRule = natRuleDb[hash_tr].natRuleChain;
+
+	while (pNatRule) {
+		/* look for a matching rule */
+		if ((pNatRule->dstIp == pSetRule->dstIp) &&
+		    (pNatRule->srcIp == pSetRule->srcIp) &&
+		    (pNatRule->proto == pSetRule->proto) &&
+		    (pNatRule->dstPort == pSetRule->dstPort) && (pNatRule->srcPort == pSetRule->srcPort)) {
+			/* update rule */
+			mvFpNatRuleUpdate(pNatRule, pSetRule);
+			natRuleUpdateCount++;
+
+#ifdef MV_FP_DEBUG
+			mvOsPrintf
+			    ("UpdNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x, flags=0x%02x\n",
+			     natRuleUpdateCount, pNatRule->dstIp, pNatRule->srcIp, pNatRule->proto,
+			     MV_16BIT_BE(pNatRule->dstPort), MV_16BIT_BE(pNatRule->srcPort), hash_tr, pNatRule->flags);
+#endif
+			return MV_OK;
+		}
+		pNatRule = pNatRule->next;
+	}
+	/* Allocate new entry */
+	pNewRule = mvOsMalloc(sizeof(MV_FP_NAT_RULE));
+	if (pNewRule == NULL) {
+		mvOsPrintf("mvFpNatRuleSet: Can't allocate new rule\n");
+		return MV_FAIL;
+	}
+
+	memcpy(pNewRule, pSetRule, sizeof(*pNewRule));
+	pNewRule->next = NULL;
+
+	if (natRuleDb[hash_tr].natRuleChain == NULL) {
+		natRuleDb[hash_tr].natRuleChain = pNewRule;
+	} else {
+		pNatRule = natRuleDb[hash_tr].natRuleChain;
+
+		while (pNatRule->next != NULL) {
+			depth++;
+			pNatRule = pNatRule->next;
+		}
+
+		pNatRule->next = pNewRule;
+	}
+	if (depth > natHashMaxDepth)
+		natHashMaxDepth = depth;
+
+	natRuleSetCount++;
+
+#ifdef MV_FP_DEBUG
+	mvOsPrintf("SetNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x, flags=0x%02x\n",
+		   natRuleSetCount, pNewRule->dstIp, pNewRule->srcIp, pNewRule->proto,
+		   MV_16BIT_BE(pNewRule->dstPort), MV_16BIT_BE(pNewRule->srcPort), hash_tr, pNewRule->flags);
+#endif
+	return MV_OK;
+}
+
+/* Delete a specified NAT rule from the SNAT + DNAT table */
+MV_STATUS mvFpNatRuleDelete(MV_FP_NAT_RULE *natRule)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_NAT_RULE *currRule, *prevRule;
+
+	natRuleDeleteCount++;
+
+	hash = mv_jhash_3words(natRule->dstIp, natRule->srcIp,
+			       (MV_U32) ((natRule->dstPort << 16) | natRule->srcPort),
+			       (MV_U32) ((fp_ip_jhash_iv << 8) | natRule->proto));
+	hash_tr = hash & (natRuleDbSize - 1);
+
+	prevRule = NULL;
+	for (currRule = natRuleDb[hash_tr].natRuleChain;
+	     currRule != NULL; prevRule = currRule, currRule = currRule->next) {
+		if (currRule->srcIp == natRule->srcIp &&
+		    currRule->dstIp == natRule->dstIp &&
+		    currRule->srcPort == natRule->srcPort &&
+		    currRule->dstPort == natRule->dstPort && currRule->proto == natRule->proto) {
+			if (prevRule == NULL)
+				natRuleDb[hash_tr].natRuleChain = currRule->next;
+			else
+				prevRule->next = currRule->next;
+
+#ifdef MV_FP_DEBUG
+			mvOsPrintf("DelNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x\n",
+				   natRuleDeleteCount, currRule->dstIp, currRule->srcIp, currRule->proto,
+				   MV_16BIT_BE(currRule->dstPort), MV_16BIT_BE(currRule->srcPort), hash_tr);
+#endif
+			mvOsFree(currRule);
+			return MV_OK;
+		}
+	}
+	return MV_NOT_FOUND;
+}
+
+int mvFpNatPktUpdate(MV_IP_HEADER *pIpHdr, MV_FP_NAT_RULE *pDnatRule, MV_FP_NAT_RULE *pSnatRule)
+{
+	MV_UDP_HEADER *pUdpHdr;
+	MV_TCP_HEADER *pTcpHdr;
+	MV_ICMP_ECHO_HEADER *pIcmpHdr;
+	int hdr_size = 0;
+	MV_U16 *pDstPort = NULL, *pSrcPort = NULL;
+
+	switch (pIpHdr->protocol) {
+	case MV_IP_PROTO_TCP:
+		pTcpHdr = (MV_TCP_HEADER *) ((unsigned)pIpHdr + sizeof(MV_IP_HEADER));
+		pDstPort = &pTcpHdr->dest;
+		pSrcPort = &pTcpHdr->source;
+		hdr_size = sizeof(MV_TCP_HEADER);
+		break;
+
+	case MV_IP_PROTO_UDP:
+		pUdpHdr = (MV_UDP_HEADER *) ((unsigned)pIpHdr + sizeof(MV_IP_HEADER));
+		pDstPort = &pUdpHdr->dest;
+		pSrcPort = &pUdpHdr->source;
+		hdr_size = sizeof(MV_UDP_HEADER);
+		break;
+
+	case MV_IP_PROTO_ICMP:
+		pIcmpHdr = (MV_ICMP_ECHO_HEADER *) ((unsigned)pIpHdr + sizeof(MV_IP_HEADER));
+		if ((pIcmpHdr->type == MV_ICMP_ECHO) || (pIcmpHdr->type == MV_ICMP_ECHOREPLY)) {
+			pDstPort = &pIcmpHdr->id;
+			pSrcPort = &pIcmpHdr->id;
+			hdr_size = sizeof(MV_ICMP_ECHO_HEADER);
+		} else {
+			mvOsPrintf("Wrong ICMP type: 0x%x\n", pIcmpHdr->type & 0xFF);
+		}
+		break;
+
+	case MV_IP_PROTO_ZERO_HOP:
+		/* Do nothing - only IP addresses are updated for this protocol */
+		break;
+
+	default:
+		mvOsPrintf("Unexpected IP protocol: 0x%x\n", pIpHdr->protocol);
+	}
+	if (pDnatRule != NULL) {
+		if (pDnatRule->flags & MV_FP_DIP_CMD_MAP)
+			pIpHdr->dstIP = pDnatRule->newIp;
+		if ((pDnatRule->flags & MV_FP_DPORT_CMD_MAP) && (pDstPort != NULL))
+			*pDstPort = pDnatRule->newPort;
+	}
+
+	if (pSnatRule != NULL) {
+		if (pSnatRule->flags & MV_FP_SIP_CMD_MAP)
+			pIpHdr->srcIP = pSnatRule->newIp;
+
+		if ((pSnatRule->flags & MV_FP_SPORT_CMD_MAP) && (pSrcPort != NULL))
+			*pSrcPort = pSnatRule->newPort;
+	}
+	return hdr_size;
+}
+
+/* Print a NFP NAT Rule */
+void mvFpNatRulePrint(const MV_FP_NAT_RULE *rule)
+{
+	/* Note: some of the fields in the NAT rule may contain invalid values */
+	mvOsPrintf("Original packet: ");
+	mvOsPrintf("SIP=");
+	mvDebugPrintIpAddr(MV_32BIT_BE(rule->srcIp)), mvOsPrintf(", DIP=");
+	mvDebugPrintIpAddr(MV_32BIT_BE(rule->dstIp)), mvOsPrintf(", SPort=%d", MV_16BIT_BE(rule->srcPort));
+	mvOsPrintf(", DPort=%d", MV_16BIT_BE(rule->dstPort));
+	mvOsPrintf("\nNAT Info: ");
+	mvOsPrintf("count=%u, flags=0x%x", rule->new_count, rule->flags);
+	mvOsPrintf(", newIP=");
+	mvDebugPrintIpAddr(MV_32BIT_BE(rule->newIp));
+	mvOsPrintf(", newPort=%d", MV_16BIT_BE(rule->newPort));
+	mvOsPrintf("\n");
+}
+
+/* Print NFP NAT Rule Database (SNAT + DNAT table) */
+MV_STATUS mvFpNatDbPrint(void)
+{
+	MV_U32 count, i = 0;
+	MV_FP_NAT_RULE *currRule;
+
+	mvOsPrintf("\nPrinting NFP NAT Rule Database: \n");
+	count = 0;
+	for (i = 0; i < natRuleDbSize; i++) {
+		currRule = natRuleDb[i].natRuleChain;
+
+		if (currRule != NULL)
+			mvOsPrintf("\n%03u: NAT DB hash=0x%x\n", count, i);
+
+		while (currRule != NULL) {
+			if ((currRule->flags != MV_FP_NULL_BINDING) || (currRule->new_count > 0)) {
+				mvOsPrintf("%03u: Rule=%p, Next=%p\n", count, currRule, currRule->next);
+				mvFpNatRulePrint(currRule);
+			}
+			currRule = currRule->next;
+			count++;
+		}
+	}
+	return MV_OK;
+}
+
+/* Get the count value for a NAT rule */
+MV_U32 mvFpNatCountGet(MV_U32 srcIp, MV_U32 dstIp, MV_U16 srcPort, MV_U16 dstPort, MV_U8 proto)
+{
+	MV_U32 hash, hash_tr;
+	MV_FP_NAT_RULE *pNatRule;
+
+	hash = mv_jhash_3words(dstIp, srcIp, (MV_U32) ((dstPort << 16) | srcPort),
+			       (MV_U32) ((fp_ip_jhash_iv << 8) | proto));
+	hash_tr = hash & (natRuleDbSize - 1);
+	pNatRule = natRuleDb[hash_tr].natRuleChain;
+
+	while (pNatRule) {
+		/* look for a matching rule */
+		if ((pNatRule->dstIp == dstIp) &&
+		    (pNatRule->srcIp == srcIp) &&
+		    (pNatRule->proto == proto) && (pNatRule->dstPort == dstPort) && (pNatRule->srcPort == srcPort)) {
+			return pNatRule->new_count;
+		}
+		pNatRule = pNatRule->next;
+	}
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpPpp.c b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpPpp.c
new file mode 100755
index 0000000..f823f03
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpPpp.c
@@ -0,0 +1,317 @@
+/*******************************************************************************
+Copyright (C) Marvell Interpppional Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+Interpppional Ltd. and/or its affiliates ("Marvell") under the following
+alterpppive licensing terms.  Once you have made an election to distribute the
+File under one of the following license alterpppives, please (i) delete this
+introductory statement regarding license alterpppives, (ii) delete the two
+license alterpppives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvPPP.c - Marvell Fast Route PPP Processing
+*
+* DESCRIPTION:
+*
+*       Supported Features:
+*       - OS independent.
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvTypes.h"
+#include "mvOs.h"
+#include "mvStack.h"
+#include "mvDebug.h"
+#include "eth/nfp/mvNfp.h"
+#include "eth/mvEth.h"
+
+#define MACFMT    "%02X:%02X:%02X:%02X:%02X:%02X"
+#define MACSTR(m) m[0], m[1], m[2], m[3], m[4], m[5]
+
+MV_FP_PPP_RULE pppOpen[ETH_FP_IFINDEX_MAX];	/* connected pppoe sessions */
+MV_FP_PPP_RULE pppHalf[ETH_FP_IFINDEX_MAX];	/* half-open pppoe connections */
+
+MV_STATUS mvFpPppInit(void)
+{
+	memset(pppOpen, 0, sizeof(MV_FP_PPP_RULE) * ETH_FP_IFINDEX_MAX);
+	memset(pppHalf, 0, sizeof(MV_FP_PPP_RULE) * ETH_FP_IFINDEX_MAX);
+
+	mvOsPrintf("NFP (pppoe) init %d entries, %d bytes\n", ETH_FP_IFINDEX_MAX,
+		   2 * sizeof(MV_FP_PPP_RULE) * ETH_FP_IFINDEX_MAX);
+	return MV_OK;
+}
+
+/* Clear Fast Route Bridge Rule Database (SNAT + DNAT table) */
+MV_STATUS mvFpPppClear(void)
+{
+	memset(pppOpen, 0, sizeof(MV_FP_PPP_RULE) * ETH_FP_IFINDEX_MAX);
+	return MV_OK;
+}
+
+void mvFpPppDestroy(void)
+{
+	mvFpPppClear();
+}
+
+void mvFpPppRulePrint(char *text, MV_FP_PPP_RULE * rule)
+{
+	mvOsPrintf("NFP (pppoe): ppp %s (%s) if_ppp=%u if_eth=%u session=%u DA=" MACFMT " SA=" MACFMT " %x\n",
+		   text, rule->pppInfo.if_ppp ? "open" : "half",
+		   rule->pppInfo.if_ppp,
+		   rule->pppInfo.if_eth,
+		   rule->pppInfo.u.ppp.session,
+		   MACSTR(rule->pppInfo.u.ppp.da), MACSTR(rule->pppInfo.u.ppp.sa), rule->pppInfo.channel);
+}
+
+MV_STATUS mvFpPppRuleSet(MV_FP_PPP_RULE *rule)
+{
+	int if_ppp = rule->pppInfo.if_ppp;
+	int i = ETH_FP_IFINDEX_MAX;
+
+#ifdef MV_FP_DEBUG
+	mvFpPppRulePrint("new", rule);
+#endif
+
+	/* half open */
+	if (!if_ppp) {
+		memcpy(&pppHalf[rule->pppInfo.if_eth], rule, sizeof(MV_FP_PPP_RULE));
+	} else
+		while (i--) {
+			/* look for channel id match */
+			if (pppHalf[i].pppInfo.channel == rule->pppInfo.channel) {
+				memcpy(&pppOpen[if_ppp], &pppHalf[i], sizeof(MV_FP_PPP_RULE));
+				memset(&pppHalf[i], 0, sizeof(MV_FP_PPP_RULE));
+				pppOpen[if_ppp].pppInfo.if_ppp = if_ppp;
+				break;
+			}
+		}
+
+	return MV_OK;
+}
+
+MV_STATUS mvFpPppRuleDel(MV_FP_PPP_RULE *rule)
+{
+	int i = ETH_FP_IFINDEX_MAX;
+
+#ifdef MV_FP_DEBUG
+	mvOsPrintf("NFP (pppoe): del ppp channel %x\n", rule->pppInfo.channel);
+#endif
+
+	while (i--) {
+		if (pppOpen[i].pppInfo.channel == rule->pppInfo.channel) {
+			mvFpPppRulePrint("del", &pppOpen[i]);
+			pppOpen[i].pppInfo.if_ppp = 0;
+			memset(&pppOpen[i], 0, sizeof(MV_FP_PPP_RULE));
+			break;
+		}
+	}
+
+	return MV_OK;
+}
+
+MV_U32 mvFpPppRuleAge(MV_FP_PPP_RULE *rule)
+{
+	return MV_OK;
+}
+
+MV_STATUS mvFpPppPrint(void)
+{
+	int i = ETH_FP_IFINDEX_MAX;
+
+	while (i--) {
+		if (pppOpen[i].pppInfo.if_eth)
+			mvFpPppRulePrint("", &pppOpen[i]);
+
+		if (pppHalf[i].pppInfo.if_eth)
+			mvFpPppRulePrint("", &pppHalf[i]);
+
+	}
+
+	return MV_OK;
+}
+
+MV_U32 mvFpPppPhyIf(MV_U32 ifIndex)
+{
+	if (pppOpen[ifIndex].pppInfo.if_ppp)
+		return pppOpen[ifIndex].pppInfo.if_eth;
+	return ETH_FP_IFINDEX_MAX;
+}
+
+/* IP header csum calculation */
+static inline unsigned short from32to16(unsigned long x)
+{
+	/* add up 16-bit and 16-bit for 16+c bit */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up carry.. */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+static unsigned long do_csum(char *buff, int len)
+{
+	int odd, count;
+	unsigned long result = 0;
+
+	if (len <= 0)
+		goto out;
+	odd = 1 & (unsigned long)buff;
+	if (odd) {
+		result = *buff;
+		len--;
+		buff++;
+	}
+	count = len >> 1;	/* nr of 16-bit words.. */
+	if (count) {
+		if (2 & (unsigned long)buff) {
+			result += *(unsigned short *)buff;
+			count--;
+			len -= 2;
+			buff += 2;
+		}
+		count >>= 1;	/* nr of 32-bit words.. */
+		if (count) {
+			unsigned long carry = 0;
+			do {
+				unsigned long w = *(unsigned long *)buff;
+				count--;
+				buff += 4;
+				result += carry;
+				result += w;
+				carry = (w > result);
+			} while (count);
+			result += carry;
+			result = (result & 0xffff) + (result >> 16);
+		}
+		if (len & 2) {
+			result += *(unsigned short *)buff;
+			buff += 2;
+		}
+	}
+	if (len & 1)
+		result += (*buff << 8);
+	result = from32to16(result);
+	if (odd)
+		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+	return result;
+}
+
+static INLINE void mvFpCSumIP(MV_IP_HEADER *pIpHdr)
+{
+	pIpHdr->checksum = 0;
+	pIpHdr->checksum = ~do_csum((char *)pIpHdr, 20 /*iph->ihl */);
+}
+
+static INLINE MV_U32 mvFpPppLookup(MV_U32 ifIndex)
+{
+	return pppOpen[ifIndex].pppInfo.if_ppp;
+}
+
+/* NFP bottom half */
+int mvFpPPPoE(MV_U32 ifIndex, MV_PKT_INFO *pPkt, MV_FP_STATS *pFpStats)
+{
+	MV_U8 *pEth = pPkt->pFrags->bufVirtPtr;
+	MV_BUF_INFO *pBuf = pPkt->pFrags;
+
+	MV_NFP_STAT(pFpStats->ppp_tx_esp++);
+
+	/* Encapsulate PPPoE on Tx */
+	if (!mvFpPppLookup(ifIndex)) {
+		MV_NFP_STAT(pFpStats->ppp_err++);
+		return MV_FAIL;
+	}
+
+	if (pBuf->dataSize > ETH_FP_PPPOE_MTU) {
+		/* Bad, we check size in the mvNfpSecOutgoing() --BK */
+		mvOsPrintf("PPPoE oversize %d > %d\n", pBuf->dataSize, ETH_FP_PPPOE_MTU);
+		MV_NFP_STAT(pFpStats->ppp_err++);
+		return MV_FAIL;
+	}
+
+	pBuf->bufAddrShift += ETH_FP_PPPOE_HDR;
+	pBuf->bufPhysAddr -= ETH_FP_PPPOE_HDR;
+	pBuf->bufVirtPtr -= ETH_FP_PPPOE_HDR;
+	pBuf->dataSize += ETH_FP_PPPOE_HDR;
+	pEth -= ETH_FP_PPPOE_HDR;
+
+	/* -6B aligment from 32B boundary */
+	{
+		MV_U32 *d = (MV_U32 *) pEth;
+		MV_U32 *s = pppOpen[ifIndex].pppInfo.u.u32;
+
+		*(d++) = *(s++);
+		*(d++) = *(s++);
+		*(d++) = *(s++);
+		*(d++) = *(s++);
+		*(d++) = *(s++);
+		*(d++) = *(s++);
+	}
+
+	/* update payload len */
+	*(MV_U16 *) (pEth + 20) = htons(pBuf->dataSize - 14 - ETH_FP_PPPOE_HDR);
+
+	/* recalculate IP csum in sw */
+	mvFpCSumIP((MV_IP_HEADER *) (pEth + 24));
+	pPkt->status = 0;
+
+	/* flush two cachelines */
+	mvOsCacheLineFlushInv(NULL, pEth);
+	mvOsCacheLineFlushInv(NULL, pEth + 32);
+
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpSec.c b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpSec.c
new file mode 100755
index 0000000..0519252
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpSec.c
@@ -0,0 +1,581 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvNfpSec.c - Marvell Network Fast Processing with IPSec(Routing only)
+*
+* DESCRIPTION:
+*
+*       Supported Features:
+*       - OS independent.
+*
+*******************************************************************************/
+
+/* includes */
+#include "mvOs.h"
+#include "mvDebug.h"
+#include "eth/nfp/mvNfp.h"
+#include "eth/mvEth.h"
+#include "eth/nfp/mvNfpSec.h"
+#include "cesa/mvCesa.h"
+
+/* IPSec SA & SPD DBs */
+MV_NFP_SEC_SPD_RULE *spdInDb;
+MV_NFP_SEC_SPD_RULE *spdOutDb;
+MV_NFP_SEC_SA_ENTRY *saInDb;
+MV_NFP_SEC_SA_ENTRY *saOutDb;
+
+static MV_CESA_MBUF cesaMbufArray[MV_NFP_SEC_Q_SIZE];
+static MV_CESA_COMMAND cesaCmdArray[MV_NFP_SEC_Q_SIZE];
+static MV_NFP_SEC_CESA_PRIV cesaPrivArray[MV_NFP_SEC_Q_SIZE + MV_NFP_SEC_REQ_Q_SIZE];
+static int cesaCmdIndx; /* static variable initialized automatically to 0 */
+static int cesaPrivIndx; /* static variable initialized automatically to 0 */
+
+static MV_U32 spdInRuleCount;
+static MV_U32 spdOutRuleCount;
+static MV_U32 saInEntryCount;
+static MV_U32 saOutEntryCount;
+static MV_U32 secDbSize;
+
+extern int cesaReqResources;
+
+MV_STATUS mvNfpSecInit(MV_U32 dbSize)
+{
+	if (dbSize == 0)
+		return MV_BAD_PARAM;
+
+	spdInDb = (struct _mv_nfp_sec_spd_rule *)mvOsMalloc(dbSize * (sizeof(struct _mv_nfp_sec_spd_rule)));
+	spdOutDb = (struct _mv_nfp_sec_spd_rule *)mvOsMalloc(dbSize * (sizeof(struct _mv_nfp_sec_spd_rule)));
+	saInDb = (struct _mv_nfp_sec_sa_entry *)mvOsMalloc(dbSize * (sizeof(struct _mv_nfp_sec_sa_entry)));
+	saOutDb = (struct _mv_nfp_sec_sa_entry *)mvOsMalloc(dbSize * (sizeof(struct _mv_nfp_sec_sa_entry)));
+
+	if ((spdInDb == NULL) || (spdOutDb == NULL) || (saInDb == NULL) || (saOutDb == NULL)) {
+		mvOsPrintf("NFP-IPSec Rules DB: Not Enough Memory\n");
+		return MV_NO_RESOURCE;
+	}
+
+	secDbSize = dbSize;
+	spdInRuleCount = spdOutRuleCount = saInEntryCount = saOutEntryCount = 0;
+
+	memset(spdInDb, 0, (dbSize * sizeof(struct _mv_nfp_sec_spd_rule)));
+	memset(spdOutDb, 0, (dbSize * sizeof(struct _mv_nfp_sec_spd_rule)));
+	memset(saInDb, 0, (dbSize * sizeof(struct _mv_nfp_sec_sa_entry)));
+	memset(saOutDb, 0, (dbSize * sizeof(struct _mv_nfp_sec_sa_entry)));
+
+	return MV_OK;
+
+}
+
+MV_STATUS mvNfpSecDbClear(MV_VOID)
+{
+	MV_U32 i;
+	MV_NFP_SEC_SPD_RULE *pCurrSpdInRule, *pCurrSpdOutRule;
+	MV_NFP_SEC_SA_ENTRY *pCurrSAInEntery, *pCurrSAOutEntery;
+
+	if ((spdInDb == NULL) && (spdOutDb == NULL) && (saInDb == NULL) && (saOutDb == NULL))
+		return MV_NOT_INITIALIZED;
+
+	/* assume all 4 DBs are initialized */
+	for (i = 0; i < secDbSize; i++) {
+		pCurrSpdInRule = (spdInDb + i);
+		pCurrSpdOutRule = (spdOutDb + i);
+		pCurrSAInEntery = (saInDb + i);
+		pCurrSAOutEntery = (saOutDb + i);
+		mvOsFree(pCurrSpdInRule);
+		mvOsFree(pCurrSpdOutRule);
+		mvOsFree(pCurrSAInEntery);
+		mvOsFree(pCurrSAOutEntery);
+	}
+
+	spdInDb = spdOutDb = NULL;
+	saInDb = saOutDb = NULL;
+
+	return MV_OK;
+}
+
+static INLINE MV_VOID mvNfpSecClearRange(MV_U8 *addr, MV_U32 size)
+{
+	MV_U32 i;
+	MV_U8 *align;
+
+	align = (MV_U8 *) ((MV_U32) addr & ~0x1f);
+
+	for (i = 0; align <= (addr + size); align += CPU_D_CACHE_LINE_SIZE)
+		mvOsCacheLineFlushInv(NULL, align);
+}
+
+static INLINE MV_VOID mvNfpSecInvRange(MV_U8 *addr, MV_U32 size)
+{
+	MV_U32 i;
+	MV_U8 *align;
+
+	align = (MV_U8 *) ((MV_U32) addr & ~0x1f);
+
+	for (i = 0; align <= (addr + size); align += CPU_D_CACHE_LINE_SIZE)
+		mvOsCacheLineInv(NULL, align);
+}
+
+/****************************************************/
+/* warning: need to replace DB list with hash table */
+/****************************************************/
+MV_NFP_SEC_SPD_RULE *mvNfpSecSPDRuleSet(MV_NFP_SEC_SPD_RULE *pSpdRule, MV_NFP_SEC_RULE_DB_DIR inOut)
+{
+	MV_NFP_SEC_SPD_RULE *pCurrSpdRule;
+	MV_U32 currRuleIndex = 0, spdRuleCount;
+
+	pCurrSpdRule = (inOut ? spdOutDb : spdInDb);
+	spdRuleCount = (inOut ? spdOutRuleCount : spdInRuleCount);
+
+	if (spdRuleCount >= secDbSize)
+		return NULL;
+
+	/* search if rule already exists */
+	while (currRuleIndex < spdRuleCount) {
+		if ((pCurrSpdRule->sIp == pSpdRule->sIp) && (pCurrSpdRule->dIp == pSpdRule->dIp)
+#ifdef	MV_NFP_SEC_5TUPLE_KEY_SUPPORT
+		    && (pCurrSpdRule->proto == pSpdRule->proto) &&
+		    (pCurrSpdRule->srcPort == pSpdRule->srcPort) && (pCurrSpdRule->dstPort == pSpdRule->dstPort)
+#endif
+		    ) {
+			/* rule exists - return */
+			return pCurrSpdRule;
+		}
+		currRuleIndex++;
+		pCurrSpdRule++;
+	}
+
+	pCurrSpdRule = (inOut ? (spdOutDb + spdRuleCount) : (spdInDb + spdRuleCount));;
+	memcpy(pCurrSpdRule, pSpdRule, sizeof(struct _mv_nfp_sec_spd_rule));
+	inOut ? spdOutRuleCount++ : spdInRuleCount++;
+
+	return pCurrSpdRule;
+
+}
+
+MV_NFP_SEC_SA_ENTRY *mvNfpSecSAEntrySet(MV_NFP_SEC_SA_ENTRY *pSAEntry, MV_NFP_SEC_RULE_DB_DIR inOut)
+{
+
+	MV_NFP_SEC_SA_ENTRY *pCurrSAEntery;
+	MV_U32 currEntryIndex = 0, saEntryCount;
+
+	pCurrSAEntery = (inOut ? saOutDb : saInDb);
+	saEntryCount = (inOut ? saOutEntryCount : saInEntryCount);
+
+	if (saEntryCount >= secDbSize)
+		return NULL;
+
+	/* search if rule already exists */
+	while (currEntryIndex < saEntryCount) {
+		if (pCurrSAEntery->spi == pSAEntry->spi) {
+			/* rule exists - return */
+			return pCurrSAEntery;
+		}
+		currEntryIndex++;
+		pCurrSAEntery++;
+	}
+
+	pCurrSAEntery = (inOut ? (saOutDb + saEntryCount) : (saInDb + saEntryCount));
+	memcpy(pCurrSAEntery, pSAEntry, sizeof(struct _mv_nfp_sec_sa_entry));
+	inOut ? saOutEntryCount++ : saInEntryCount++;
+
+	return pCurrSAEntery;
+
+}
+
+MV_STATUS mvNfpSecOutCheck(MV_PKT_INFO *pPktInfo)
+{
+	if (pPktInfo->pFrags->dataSize > MV_NFP_SEC_MAX_PACKET)
+		return MV_OUT_OF_RANGE;
+	return MV_OK;
+}
+
+INLINE MV_STATUS mvNfpSecInCheck(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	/* TBD - sequence number */
+	return MV_OK;
+}
+
+MV_NFP_SEC_SPD_RULE *mvNfpSecSPDRuleFind(MV_U32 dstIp, MV_U32 srcIp,
+					 MV_U8 proto, MV_U16 dport, MV_U16 sport, MV_NFP_SEC_RULE_DB_DIR inOut)
+{
+	MV_NFP_SEC_SPD_RULE *pCurrSpdRule;
+	MV_U32 currRuleIndex = 0, spdRuleCount;
+
+	pCurrSpdRule = (inOut ? spdOutDb : spdInDb);
+	spdRuleCount = (inOut ? spdOutRuleCount : spdInRuleCount);
+
+	/* SPD DB is empty */
+	if (!spdRuleCount)
+		return NULL;
+
+	/* scan IN/OUT SPD database for matching rule */
+	while (currRuleIndex < spdRuleCount) {
+		if ((pCurrSpdRule->sIp == srcIp) && (pCurrSpdRule->dIp == dstIp)
+#ifdef	MV_NFP_SEC_5TUPLE_KEY_SUPPORT
+		    && (pCurrSpdRule->proto == proto)
+		    (pCurrSpdRule->srcPort == sport) && (pCurrSpdRule->dstPort == dport)
+#endif
+		    ) {
+			/* rule found - return */
+			return pCurrSpdRule;
+		}
+		currRuleIndex++;
+		pCurrSpdRule++;
+	}
+
+	return NULL;
+
+}
+
+INLINE MV_VOID mvNfpSecBuildMac(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	MV_802_3_HEADER *pMacHdr;
+
+	pMacHdr = (MV_802_3_HEADER *) ((MV_U8 *) (pPktInfo->pFrags[0].bufVirtPtr));
+	memcpy(pMacHdr, &pSAEntry->tunnelHdr.dstMac, 12);
+	pMacHdr->typeOrLen = 0x08;	/* stands for IP protocol code 16bit swapped */
+	return;
+}
+
+INLINE MV_VOID mvNfpSecBuildIPTunnel(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	MV_IP_HEADER *pIpHdr, *pIntIpHdr;
+	MV_U16 newIpTotalLength;
+
+	newIpTotalLength = pPktInfo->pFrags[0].dataSize - sizeof(MV_802_3_HEADER);
+
+	pIpHdr = (MV_IP_HEADER *) (pPktInfo->pFrags[0].bufVirtPtr + sizeof(MV_802_3_HEADER));
+	pIntIpHdr = (MV_IP_HEADER *) ((MV_U8 *) (pIpHdr) + sizeof(MV_IP_HEADER) + sizeof(MV_ESP_HEADER) +
+				      pSAEntry->ivSize);
+
+	/* TBD - review below settings in RFC */
+	pIpHdr->version = 0x45;
+	pIpHdr->tos = 0;
+	pIpHdr->checksum = 0;
+	pIpHdr->totalLength = MV_16BIT_BE(newIpTotalLength);
+	pIpHdr->identifier = 0;
+	pIpHdr->fragmentCtrl = 0;
+	pIpHdr->ttl = pIntIpHdr->ttl - 1;
+	pIpHdr->protocol = MV_IP_PROTO_ESP;
+	pIpHdr->srcIP = pSAEntry->tunnelHdr.sIp;
+	pIpHdr->dstIP = pSAEntry->tunnelHdr.dIp;
+
+	pPktInfo->status = ETH_TX_IP_NO_FRAG | ETH_TX_GENERATE_IP_CHKSUM_MASK | (0x5 << ETH_TX_IP_HEADER_LEN_OFFSET);
+
+	return;
+}
+
+/* Append sequence number and spi, save some space for IV */
+INLINE MV_VOID mvNfpSecBuildEspHdr(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	MV_ESP_HEADER *pEspHdr;
+
+	pEspHdr = (MV_ESP_HEADER *) (pPktInfo->pFrags[0].bufVirtPtr + sizeof(MV_802_3_HEADER) + sizeof(MV_IP_HEADER));
+	pEspHdr->spi = pSAEntry->spi;
+	pSAEntry->seqNum = (pSAEntry->seqNum++);
+	pEspHdr->seqNum = MV_32BIT_BE(pSAEntry->seqNum);
+}
+
+MV_STATUS mvNfpSecEspProcess(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	MV_CESA_COMMAND *pCesaCmd;
+	MV_CESA_MBUF *pCesaMbuf;
+	MV_NFP_SEC_CESA_PRIV *pCesaPriv;
+	MV_STATUS status;
+	MV_IP_HEADER *pIpHdr;
+	MV_BUF_INFO *pBuf;
+
+	pCesaCmd = &cesaCmdArray[cesaCmdIndx];
+	pCesaMbuf = &cesaMbufArray[cesaCmdIndx];
+	cesaCmdIndx++;
+	cesaCmdIndx %= MV_NFP_SEC_Q_SIZE;
+	pCesaPriv = &cesaPrivArray[cesaPrivIndx++];
+	cesaPrivIndx = cesaPrivIndx % (MV_NFP_SEC_Q_SIZE + MV_NFP_SEC_REQ_Q_SIZE);
+
+	pCesaPriv->pPktInfo = pPktInfo;
+	pCesaPriv->pSaEntry = pSAEntry;
+	pCesaPriv->pCesaCmd = pCesaCmd;
+
+	/*
+	 *  Fix, encrypt/decrypt the IP payload only, --BK 20091027
+	 */
+	pBuf = pPktInfo->pFrags;
+	pIpHdr = (MV_IP_HEADER *) (pBuf->bufVirtPtr + sizeof(MV_802_3_HEADER));
+	pBuf->dataSize = MV_16BIT_BE(pIpHdr->totalLength) + sizeof(MV_802_3_HEADER);
+
+	pBuf->bufVirtPtr += MV_NFP_SEC_ESP_OFFSET;
+	pBuf->bufPhysAddr += MV_NFP_SEC_ESP_OFFSET;
+	pBuf->dataSize -= MV_NFP_SEC_ESP_OFFSET;
+	pBuf->bufAddrShift -= MV_NFP_SEC_ESP_OFFSET;
+
+	pCesaMbuf->pFrags = pPktInfo->pFrags;
+	pCesaMbuf->numFrags = 1;
+	pCesaMbuf->mbufSize = pBuf->dataSize;
+
+	pCesaCmd->pReqPrv = (MV_VOID *) pCesaPriv;
+	pCesaCmd->sessionId = pSAEntry->sid;
+	pCesaCmd->pSrc = pCesaMbuf;
+	pCesaCmd->pDst = pCesaMbuf;
+	pCesaCmd->skipFlush = MV_TRUE;
+
+	/* Assume ESP */
+	pCesaCmd->cryptoOffset = sizeof(MV_ESP_HEADER) + pSAEntry->ivSize;
+	pCesaCmd->cryptoLength = pBuf->dataSize - (sizeof(MV_ESP_HEADER)
+						   + pSAEntry->ivSize + pSAEntry->digestSize);
+	pCesaCmd->ivFromUser = 0;	/* relevant for encode only */
+	pCesaCmd->ivOffset = sizeof(MV_ESP_HEADER);
+	pCesaCmd->macOffset = 0;
+	pCesaCmd->macLength = pBuf->dataSize - pSAEntry->digestSize;
+	pCesaCmd->digestOffset = pBuf->dataSize - pSAEntry->digestSize;
+
+	/* save original digest in case of decrypt+auth */
+	if (pSAEntry->secOp == MV_NFP_SEC_DECRYPT) {
+		memcpy(pCesaPriv->orgDigest, (pBuf->bufVirtPtr + pCesaCmd->digestOffset), pSAEntry->digestSize);
+		mvNfpSecInvRange((pBuf->bufVirtPtr + pCesaCmd->digestOffset), pSAEntry->digestSize);
+	}
+
+	pSAEntry->stats.bytes += pBuf->dataSize;
+	if (pSAEntry->secOp == MV_NFP_SEC_DECRYPT)
+		pSAEntry->stats.decrypt++;
+	else
+		pSAEntry->stats.encrypt++;
+
+	disable_irq(CESA_IRQ);
+	status = mvCesaAction(pCesaCmd);
+	enable_irq(CESA_IRQ);
+	if (status != MV_OK) {
+		pSAEntry->stats.rejected++;
+		mvOsPrintf("%s: mvCesaAction failed %d\n", __func__, status);
+	}
+
+	return status;
+}
+
+MV_STATUS mvNfpSecOutgoing(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	MV_U8 *pTmp;
+	MV_U32 cryptoSize, encBlockMod, dSize;
+	MV_BUF_INFO *pBuf = pPktInfo->pFrags;
+
+	/* CESA Q is full drop. */
+	if (cesaReqResources <= 1) {
+		pSAEntry->stats.rejected++;
+		return MV_NO_RESOURCE;
+	}
+
+	/* encrypt payload */
+	cryptoSize = pBuf->dataSize - sizeof(MV_802_3_HEADER) - ETH_MV_HEADER_SIZE;
+
+	/* ignore Marvell header */
+	pBuf->dataSize -= ETH_MV_HEADER_SIZE;
+	pBuf->bufVirtPtr += ETH_MV_HEADER_SIZE;
+	pBuf->bufPhysAddr += ETH_MV_HEADER_SIZE;
+	pBuf->bufAddrShift -= ETH_MV_HEADER_SIZE;
+
+	/* Align buffer address to beginning of new packet - TBD handle VLAN tag, LLC */
+	dSize = pSAEntry->ivSize + sizeof(MV_ESP_HEADER) + sizeof(MV_IP_HEADER);
+	pBuf->bufVirtPtr -= dSize;
+	pBuf->bufPhysAddr -= dSize;
+	pBuf->dataSize += dSize;
+	pBuf->bufAddrShift += dSize;
+
+	encBlockMod = (cryptoSize % MV_NFP_SEC_ENC_BLOCK_SIZE);
+	/* leave space for padLen + Protocol */
+	if (encBlockMod > 14) {
+		encBlockMod = MV_NFP_SEC_ENC_BLOCK_SIZE - encBlockMod;
+		encBlockMod += MV_NFP_SEC_ENC_BLOCK_SIZE;
+	} else
+		encBlockMod = MV_NFP_SEC_ENC_BLOCK_SIZE - encBlockMod;
+
+	/* expected frame size */
+	dSize = pBuf->dataSize + encBlockMod + pSAEntry->digestSize;
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+	/* keep enough room for PPPoE header */
+	if (ETH_FP_IFINDEX_MAX != mvFpPppPhyIf(pSAEntry->tunnelHdr.outIfIndex))
+		dSize += ETH_FP_PPPOE_HDR;
+#endif
+
+	if (dSize > ETH_FP_MTU - ETH_MV_HEADER_SIZE)
+		goto rollback;
+
+	pBuf->dataSize += encBlockMod;
+	pTmp = pBuf->bufVirtPtr + pBuf->dataSize;
+	memset(pTmp - encBlockMod, 0, encBlockMod - 2);
+	*((MV_U8 *) (pTmp - 2)) = (MV_U8) (encBlockMod - 2);
+	*((MV_U8 *) (pTmp - 1)) = (MV_U8) 4;
+	mvNfpSecClearRange(pTmp - encBlockMod, encBlockMod);
+
+	pBuf->dataSize += pSAEntry->digestSize;
+	mvNfpSecBuildEspHdr(pPktInfo, pSAEntry);
+	mvNfpSecBuildIPTunnel(pPktInfo, pSAEntry);
+	mvNfpSecBuildMac(pPktInfo, pSAEntry);
+
+	/* flush & invalidate new MAC, IP, & ESP headers + old ip */
+	dSize = pBuf->bufAddrShift + sizeof(MV_IP_HEADER) + sizeof(MV_802_3_HEADER);
+	mvNfpSecClearRange(pBuf->bufVirtPtr, dSize);
+
+	return mvNfpSecEspProcess(pPktInfo, pSAEntry);
+
+rollback:
+	/* slow path */
+	pBuf->bufPhysAddr += pBuf->bufAddrShift;
+	pBuf->bufVirtPtr += pBuf->bufAddrShift;
+	pBuf->dataSize -= pBuf->bufAddrShift;
+	pBuf->bufAddrShift = 0;
+
+	pSAEntry->stats.rejected++;
+	return MV_OUT_OF_RANGE;
+}
+
+MV_STATUS mvNfpSecIncoming(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+
+	MV_BUF_INFO *pBuf = pPktInfo->pFrags;
+	MV_U32 invSize;
+
+	/* CESA Q is full drop. */
+	if (cesaReqResources <= 1) {
+		pSAEntry->stats.rejected++;
+		return MV_NO_RESOURCE;
+	}
+
+	/* TBD - duplicate invalidatation */
+	if (MV_OK != mvNfpSecInCheck(pPktInfo, pSAEntry)) {
+		pSAEntry->stats.rejected++;
+		return MV_ERROR;
+	}
+
+	/* ignore Marvell header */
+	pBuf->dataSize -= ETH_MV_HEADER_SIZE;
+	pBuf->bufVirtPtr += ETH_MV_HEADER_SIZE;
+	pBuf->bufPhysAddr += ETH_MV_HEADER_SIZE;
+	pBuf->bufAddrShift -= ETH_MV_HEADER_SIZE;
+
+	/* update buffer address shift value */
+	/* tracked by bufAddrShift, --BK 091022 */
+	/* pBuf->bufAddrShift -= (pSAEntry->ivSize + sizeof(MV_ESP_HEADER) + sizeof(MV_IP_HEADER)); */
+
+	/* invalidate MAC, IP & ESP  headers */
+	invSize = sizeof(MV_802_3_HEADER) + sizeof(MV_IP_HEADER) + sizeof(MV_ESP_HEADER);
+	mvNfpSecInvRange(pBuf->bufVirtPtr, invSize);
+
+	return mvNfpSecEspProcess(pPktInfo, pSAEntry);
+}
+
+MV_NFP_SEC_SA_ENTRY *mvNfpSecSARuleFind(MV_U32 spiPkt)
+{
+	MV_NFP_SEC_SA_ENTRY *pCurrSAEntery = saInDb;
+	MV_U32 currEntryIndex = 0;
+
+	while (currEntryIndex < saInEntryCount) {
+		if (pCurrSAEntery->spi == spiPkt)
+			return pCurrSAEntery;
+		currEntryIndex++;
+		pCurrSAEntery++;
+	}
+
+	return NULL;
+
+}
+
+MV_VOID mvNfpSecSaPrint(MV_NFP_SEC_SA_ENTRY *pSAEntry)
+{
+	mvDebugPrintIpAddr(MV_32BIT_BE(pSAEntry->tunnelHdr.sIp));
+	mvOsPrintf("->");
+	mvDebugPrintIpAddr(MV_32BIT_BE(pSAEntry->tunnelHdr.dIp));
+	mvOsPrintf(" out_if=%d da=", pSAEntry->tunnelHdr.outIfIndex);
+	mvDebugPrintMacAddr(pSAEntry->tunnelHdr.dstMac);
+	mvOsPrintf(" spi=0x%x", MV_32BIT_BE(pSAEntry->spi));
+
+	if (pSAEntry)
+		mvOsPrintf("\tstats: encrypt:%d decrypt:%d reject:%d drop:%d bytes:%d",
+			   pSAEntry->stats.encrypt, pSAEntry->stats.decrypt,
+			   pSAEntry->stats.rejected, pSAEntry->stats.dropped, pSAEntry->stats.bytes);
+	mvOsPrintf("\n");
+}
+
+MV_VOID mvNfpSecDbPrint(MV_VOID)
+{
+	MV_U32 i;
+
+	mvOsPrintf("NFP IPSec:\n");
+
+	for (i = 0; i < spdInRuleCount; i++) {
+		mvOsPrintf("inbound[%d] ", i);
+		mvDebugPrintIpAddr(MV_32BIT_BE(spdInDb[i].sIp));
+		mvOsPrintf("->");
+		mvDebugPrintIpAddr(MV_32BIT_BE(spdInDb[i].dIp));
+		mvOsPrintf(" ");
+		mvNfpSecSaPrint(spdInDb[i].pSAEntry);
+	}
+	for (i = 0; i < spdOutRuleCount; i++) {
+		mvOsPrintf("outbound[%d] ", i);
+		mvDebugPrintIpAddr(MV_32BIT_BE(spdOutDb[i].sIp));
+		mvOsPrintf("->");
+		mvDebugPrintIpAddr(MV_32BIT_BE(spdOutDb[i].dIp));
+		mvOsPrintf(" ");
+		mvNfpSecSaPrint(spdOutDb[i].pSAEntry);
+	}
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpSec.h b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpSec.h
new file mode 100755
index 0000000..5d9dde6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/eth/nfp/mvNfpSec.h
@@ -0,0 +1,191 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvNfpSec.h - Header File for Marvell NFP IPSec (Routing only)
+*
+* DESCRIPTION:
+*       This header file contains macros, typedefs and function declarations
+* 	specific to the Marvell Network Fast Processing with IPSec(Routing only).
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __mvNfpSec_h__
+#define __mvNfpSec_h__
+
+#ifdef CONFIG_MV_ETH_NFP_SEC
+
+#include "mvCommon.h"
+#include "cesa/mvCesa.h"
+
+/* IPSec defines */
+#define MV_NFP_SEC_MAX_PACKET		1540
+#define MV_NFP_SEC_ENC_BLOCK_SIZE	16
+
+#define MV_NFP_SEC_ESP_OFFSET		34
+
+/* IPSec Enumerators */
+typedef enum {
+	MV_NFP_SEC_TUNNEL = 0,
+	MV_NFP_SEC_TRANSPORT,
+} MV_NFP_SEC_PROT;
+
+typedef enum {
+	MV_NFP_SEC_ESP = 0,
+	MV_NFP_SEC_AH,
+} MV_NFP_SEC_ENCAP;
+
+typedef enum {
+	MV_NFP_SEC_RULE_DB_IN = 0,
+	MV_NFP_SEC_RULE_DB_OUT,
+} MV_NFP_SEC_RULE_DB_DIR;
+
+typedef enum {
+	MV_NFP_SEC_DROP = 0,
+	MV_NFP_SEC_FWD,
+	MV_NFP_SEC_SECURE
+} MV_NFP_SEC_ACTION;
+
+typedef enum {
+	MV_NFP_SEC_ENCRYPT = 0,
+	MV_NFP_SEC_DECRYPT,
+} MV_NFP_SEC_OP;
+
+typedef struct _mv_nfp_sa_stats {
+	MV_U32 encrypt;
+	MV_U32 decrypt;
+	MV_U32 rejected;	/* slow path */
+	MV_U32 dropped;		/* packet drop */
+	MV_U32 bytes;
+} MV_NFP_SA_STATS;
+
+/* IPSec Structures */
+typedef struct _mv_nfp_sec_tunnel_hdr {
+	MV_U32 sIp;		/*  BE */
+	MV_U32 dIp;		/* BE */
+	/* dstMac should be 2 byte aligned */
+	MV_U8 dstMac[MV_MAC_ADDR_SIZE];	/* BE */
+	MV_U8 srcMac[MV_MAC_ADDR_SIZE];	/* BE */
+	MV_U8 outIfIndex;
+} MV_NFP_SEC_TUNNEL_HDR;
+
+typedef struct _mv_nfp_sec_sa_entry {
+	MV_U32 spi;		/* BE */
+	MV_NFP_SEC_PROT tunProt;
+	MV_NFP_SEC_ENCAP encap;
+	MV_U16 sid;
+	MV_U32 seqNum;		/* LE  */
+	MV_NFP_SEC_TUNNEL_HDR tunnelHdr;
+	MV_U32 lifeTime;
+	MV_U8 ivSize;
+	MV_U8 cipherBlockSize;
+	MV_U8 digestSize;
+	MV_NFP_SEC_OP secOp;
+	MV_NFP_SA_STATS stats;
+} MV_NFP_SEC_SA_ENTRY;
+
+typedef struct _mv_nfp_sec_spd_rule {
+	MV_U32 sIp;		/* BE */
+	MV_U32 dIp;		/* BE */
+	MV_U8 proto;
+	MV_U16 dstPort;		/* BE */
+	MV_U16 srcPort;		/* BE */
+	MV_NFP_SEC_ACTION actionType;
+	MV_NFP_SEC_SA_ENTRY *pSAEntry;
+} MV_NFP_SEC_SPD_RULE;
+
+typedef struct _mv_nfp_sec_cesa_priv {
+	MV_NFP_SEC_SA_ENTRY *pSaEntry;
+	MV_PKT_INFO *pPktInfo;
+	MV_U8 orgDigest[MV_CESA_MAX_DIGEST_SIZE];
+	MV_CESA_COMMAND *pCesaCmd;
+} MV_NFP_SEC_CESA_PRIV;
+
+MV_NFP_SEC_SPD_RULE *mvNfpSecSPDRuleFind(MV_U32 dstIp, MV_U32 srcIp,
+					 MV_U8 proto, MV_U16 dport, MV_U16 sport, MV_NFP_SEC_RULE_DB_DIR inOut);
+
+MV_STATUS mvNfpSecOutCheck(MV_PKT_INFO *pPktInfo);
+
+MV_STATUS mvNfpSecOutgoing(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry);
+
+MV_STATUS mvNfpSecEspProcess(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry);
+
+MV_NFP_SEC_SA_ENTRY *mvNfpSecSARuleFind(MV_U32 spiPkt);
+
+MV_STATUS mvNfpSecIncoming(MV_PKT_INFO *pPktInfo, MV_NFP_SEC_SA_ENTRY *pSAEntry);
+
+MV_NFP_SEC_SPD_RULE *mvNfpSecSPDRuleSet(MV_NFP_SEC_SPD_RULE *pSpdRule, MV_NFP_SEC_RULE_DB_DIR inOut);
+
+MV_NFP_SEC_SA_ENTRY *mvNfpSecSAEntrySet(MV_NFP_SEC_SA_ENTRY *pSAEntry, MV_NFP_SEC_RULE_DB_DIR inOut);
+
+MV_STATUS mvNfpSecInit(MV_U32 dbSize);	/*  global init */
+
+MV_VOID mvNfpSecDbPrint(MV_VOID);
+
+#endif /* CONFIG_MV_ETH_NFP_SEC */
+
+#endif /* __mvNfpSec_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/gpp/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/gpp/mvCompVer.txt
new file mode 100755
index 0000000..5f39390
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/gpp/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.4
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/gpp/mvGpp.c b/arch/arm/plat-feroceon/mv_hal/gpp/mvGpp.c
new file mode 100755
index 0000000..bb991f0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/gpp/mvGpp.c
@@ -0,0 +1,447 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysGppConfig.h"
+#include "mvGppRegs.h"
+#include "mvGpp.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+static MV_VOID gppRegSet(MV_U32 group, MV_U32 regOffs, MV_U32 mask, MV_U32 value);
+
+static MV_GPP_HAL_DATA gppHalData;
+
+/*******************************************************************************
+* mvGppInit - Init GPP HAL
+*
+* DESCRIPTION:
+*
+* INPUT:
+*	halData - GPP HAL data.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvGppInit(MV_GPP_HAL_DATA *halData)
+{
+	mvOsMemcpy(&gppHalData, halData, sizeof(MV_GPP_HAL_DATA));
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvGppTypeSet - Enable a GPP (OUT) pin
+*
+* DESCRIPTION:
+*
+* INPUT:
+*	group		- GPP group number
+*	mask		- 32bit mask value. Each set bit in the mask means that the type
+*			  of corresponding GPP will be set. Other GPPs are ignored.
+*	value		- 32bit value that describes GPP type per pin.
+*
+* OUTPUT:
+*	None.
+*
+* EXAMPLE:
+*	Set GPP8 to input and GPP15 to output.
+*	mvGppTypeSet(0, (GPP8 | GPP15),
+*		     ((MV_GPP_IN & GPP8) | (MV_GPP_OUT & GPP15)) );
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_STATUS mvGppTypeSet(MV_U32 group, MV_U32 mask, MV_U32 value)
+{
+	if (group >= MV_GPP_MAX_GROUP) {
+		DB(mvOsPrintf("mvGppTypeSet: ERR. invalid group number \n"));
+		return MV_BAD_PARAM;
+	}
+
+	gppRegSet(group, GPP_DATA_OUT_EN_REG(group), mask, value);
+
+	/* Workaround for Erratum FE-MISC-70 */
+	if (gppHalData.ctrlRev == MV_88F6XXX_A0_REV && (group == 1)) {
+		mask &= 0x2;
+		gppRegSet(0, GPP_DATA_OUT_EN_REG(0), mask, value);
+	}
+	/*End of WA */
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvGppBlinkEn - Set a GPP (IN) Pin list to blink every ~100ms
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       group - GPP group number
+*       mask  - 32bit mask value. Each set bit in the mask means that the type
+*               of corresponding GPP will be set. Other GPPs are ignored.
+*       value - 32bit value that describes GPP blink per pin.
+*
+* OUTPUT:
+*       None.
+*
+* EXAMPLE:
+*       Set GPP8 to be static and GPP15 to be blinking.
+*       mvGppBlinkEn(0, (GPP8 | GPP15),
+*                    ((MV_GPP_OUT_STATIC & GPP8) | (MV_GPP_OUT_BLINK & GPP15)) );
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_STATUS mvGppBlinkEn(MV_U32 group, MV_U32 mask, MV_U32 value)
+{
+	if (group >= MV_GPP_MAX_GROUP) {
+		DB(mvOsPrintf("mvGppBlinkEn: ERR. invalid group number \n"));
+		return MV_BAD_PARAM;
+	}
+
+	gppRegSet(group, GPP_BLINK_EN_REG(group), mask, value);
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvGppPolaritySet - Set a GPP (IN) Pin list Polarity mode
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       group - GPP group number
+*       mask  - 32bit mask value. Each set bit in the mask means that the type
+*               of corresponding GPP will be set. Other GPPs are ignored.
+*       value - 32bit value that describes GPP polarity per pin.
+*
+* OUTPUT:
+*       None.
+*
+* EXAMPLE:
+*       Set GPP8 to the actual pin value and GPP15 to be inverted.
+*       mvGppPolaritySet(0, (GPP8 | GPP15),
+*                    ((MV_GPP_IN_ORIGIN & GPP8) | (MV_GPP_IN_INVERT & GPP15)) );
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_STATUS mvGppPolaritySet(MV_U32 group, MV_U32 mask, MV_U32 value)
+{
+	if (group >= MV_GPP_MAX_GROUP) {
+		DB(mvOsPrintf("mvGppPolaritySet: ERR. invalid group number \n"));
+		return MV_BAD_PARAM;
+	}
+
+	gppRegSet(group, GPP_DATA_IN_POL_REG(group), mask, value);
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvGppPolarityGet - Get a value of relevant bits from GPP Polarity register.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       group - GPP group number
+*       mask  - 32bit mask value. Each set bit in the mask means that the
+*               returned value is valid for it.
+*
+* OUTPUT:
+*       None.
+*
+* EXAMPLE:
+*       Get GPP8 and GPP15 value.
+*       mvGppPolarityGet(0, (GPP8 | GPP15));
+*
+* RETURN:
+*       32bit value that describes GPP polatity mode per pin.
+*
+*******************************************************************************/
+MV_U32 mvGppPolarityGet(MV_U32 group, MV_U32 mask)
+{
+	MV_U32 regVal;
+
+	if (group >= MV_GPP_MAX_GROUP) {
+		DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n"));
+		return MV_ERROR;
+	}
+	regVal = MV_REG_READ(GPP_DATA_IN_POL_REG(group));
+
+	return (regVal & mask);
+}
+
+/*******************************************************************************
+* mvGppValueGet - Get a GPP Pin list value.
+*
+* DESCRIPTION:
+*       This function get GPP value.
+*
+* INPUT:
+*       group - GPP group number
+*       mask  - 32bit mask value. Each set bit in the mask means that the
+*               returned value is valid for it.
+*
+* OUTPUT:
+*       None.
+*
+* EXAMPLE:
+*       Get GPP8 and GPP15 value.
+*       mvGppValueGet(0, (GPP8 | GPP15));
+*
+* RETURN:
+*       32bit value that describes GPP activity mode per pin.
+*
+*******************************************************************************/
+MV_U32 mvGppValueGet(MV_U32 group, MV_U32 mask)
+{
+	MV_U32 gppData;
+
+	gppData = MV_REG_READ(GPP_DATA_IN_REG(group));
+
+	gppData &= mask;
+
+	return gppData;
+
+}
+
+/*******************************************************************************
+* mvGppValueSet - Set a GPP Pin list value.
+*
+* DESCRIPTION:
+*       This function set value for given GPP pin list.
+*
+* INPUT:
+*       group - GPP group number
+*       mask  - 32bit mask value. Each set bit in the mask means that the
+*               value of corresponding GPP will be set accordingly. Other GPP
+*               are not affected.
+*       value - 32bit value that describes GPP value per pin.
+*
+* OUTPUT:
+*       None.
+*
+* EXAMPLE:
+*       Set GPP8 value of '0' and GPP15 value of '1'.
+*       mvGppActiveSet(0, (GPP8 | GPP15), ((0 & GPP8) | (GPP15)) );
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_STATUS mvGppValueSet(MV_U32 group, MV_U32 mask, MV_U32 value)
+{
+	MV_U32 outEnable, tmp;
+	MV_U32 i;
+
+	if (group >= MV_GPP_MAX_GROUP) {
+		DB(mvOsPrintf("mvGppValueSet: Error invalid group number \n"));
+		return MV_BAD_PARAM;
+	}
+
+	/* verify that the gpp pin is configured as output              */
+	/* Note that in the register out enabled -> bit = '0'.  */
+	outEnable = ~MV_REG_READ(GPP_DATA_OUT_EN_REG(group));
+
+	/* Workaround for Erratum FE-MISC-70 */
+	if (gppHalData.ctrlRev == MV_88F6XXX_A0_REV && (group == 1)) {
+		tmp = ~MV_REG_READ(GPP_DATA_OUT_EN_REG(0));
+		outEnable &= 0xfffffffd;
+		outEnable |= (tmp & 0x2);
+	}
+	/*End of WA */
+	for (i = 0; i < 32; i++) {
+		if (((mask & (1 << i)) & (outEnable & (1 << i))) != (mask & (1 << i))) {
+			mvOsPrintf("mvGppValueSet: Err. An attempt to set output "
+				   "value to GPP %d in input mode.\n", i);
+			return MV_ERROR;
+		}
+	}
+
+	gppRegSet(group, GPP_DATA_OUT_REG(group), mask, value);
+
+	return MV_OK;
+
+}
+
+
+/*******************************************************************************
+* mvGppBlinkCntrSet
+*
+* DESCRIPTION:
+*       Set blink counter on / off duration.
+*
+* INPUT:
+*       blnkCntr - The blink counter to set (A or B).
+*	onDuration - Blink-on duration in ticks.
+*	offDuration - Blink-off duration in ticks.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvGppBlinkCntrSet(MV_GPP_BLINK_CNTR blnkCntr, MV_U32 onDuration, MV_U32 offDuration)
+{
+	MV_REG_WRITE(GPP_BLINK_CNTR_ON(blnkCntr), onDuration);
+	MV_REG_WRITE(GPP_BLINK_CNTR_OFF(blnkCntr), offDuration);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvGppBlinkCntrSelect
+*
+* DESCRIPTION:
+*       Select the blink counter according to a given gpio will blink.
+*
+* INPUT:
+*	gppIdx	- The GPP index.
+*	blnkCntr- The blink counter to associate the GPP to.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvGppBlinkCntrSelect(MV_U32 gppIdx, MV_GPP_BLINK_CNTR blnkCntr)
+{
+	MV_U32 group = gppIdx >> 5;
+	MV_U32 idx = gppIdx & 0x1F;
+
+	if (group >= MV_GPP_MAX_GROUP) {
+		DB(mvOsPrintf("mvGppBlinkCntrSelect: Error invalid group number \n"));
+		return MV_BAD_PARAM;
+	}
+
+	if (blnkCntr == MV_GPP_BLINK_CNTR_A)
+		MV_REG_BIT_RESET(GPP_BLINK_CNTR_SELECT(group), (1 << idx));
+	else
+		MV_REG_BIT_SET(GPP_BLINK_CNTR_SELECT(group), (1 << idx));
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* gppRegSet - Set a specific GPP pin on a specific GPP register
+*
+* DESCRIPTION:
+*       This function set a specific GPP pin on a specific GPP register
+*
+* INPUT:
+*		regOffs - GPP Register offset
+*       group - GPP group number
+*       mask  - 32bit mask value. Each set bit in the mask means that the
+*               value of corresponding GPP will be set accordingly. Other GPP
+*               are not affected.
+*       value - 32bit value that describes GPP value per pin.
+*
+* OUTPUT:
+*       None.
+*
+* EXAMPLE:
+*       Set GPP8 value of '0' and GPP15 value of '1'.
+*       mvGppActiveSet(0, (GPP8 | GPP15), ((0 & GPP8) | (1 & GPP15)) );
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID gppRegSet(MV_U32 group, MV_U32 regOffs, MV_U32 mask, MV_U32 value)
+{
+	MV_U32 gppData;
+
+	gppData = MV_REG_READ(regOffs);
+
+	gppData &= ~mask;
+
+	gppData |= (value & mask);
+
+	MV_REG_WRITE(regOffs, gppData);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/gpp/mvGpp.h b/arch/arm/plat-feroceon/mv_hal/gpp/mvGpp.h
new file mode 100755
index 0000000..ff04860
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/gpp/mvGpp.h
@@ -0,0 +1,138 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvGppH
+#define __INCmvGppH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "mvSysGppConfig.h"
+
+typedef struct {
+	MV_U8 ctrlRev;
+} MV_GPP_HAL_DATA;
+
+typedef enum {
+	MV_GPP_BLINK_CNTR_A = 0,
+	MV_GPP_BLINK_CNTR_B
+} MV_GPP_BLINK_CNTR;
+
+/* These macros describes the GPP type. Each of the GPPs pins can */
+/* be assigned to act as a general purpose input or output pin. */
+#define	MV_GPP_IN	0xFFFFFFFF	/* GPP input */
+#define MV_GPP_OUT	0		/* GPP output */
+
+/* These macros describes the GPP Out Enable. */
+#define	MV_GPP_OUT_DIS	0xFFFFFFFF	/* Out pin disabled */
+#define MV_GPP_OUT_EN		0	/* Out pin enabled */
+
+/* These macros describes the GPP Out Blinking. */
+/* When set and the corresponding bit in GPIO Data Out Enable Control */
+/* Register is enabled, the GPIO pin blinks every ~100 ms (a period of */
+/* 2^24 TCLK clocks). */
+#define	MV_GPP_OUT_BLINK	0xFFFFFFFF	/* Out pin blinking */
+#define MV_GPP_OUT_STATIC	0	/* Out pin static */
+
+/* These macros describes the GPP Polarity. */
+/* When set to 1 GPIO Data In Register reflects the inverted value of the */
+/* corresponding pin. */
+
+#define	MV_GPP_IN_INVERT	0xFFFFFFFF	/* Inverted value is got */
+#define MV_GPP_IN_ORIGIN	0	/* original value is got */
+
+/* mvGppInit - Initialize GPP HAL */
+MV_STATUS mvGppInit(MV_GPP_HAL_DATA *halData);
+
+/* mvGppTypeSet - Set PP pin mode (IN or OUT) */
+MV_STATUS mvGppTypeSet(MV_U32 group, MV_U32 mask, MV_U32 value);
+
+/* mvGppBlinkEn - Set a GPP (IN) Pin list to blink every ~100ms */
+MV_STATUS mvGppBlinkEn(MV_U32 group, MV_U32 mask, MV_U32 value);
+
+/* mvGppPolaritySet - Set a GPP (IN) Pin list Polarity mode. */
+MV_STATUS mvGppPolaritySet(MV_U32 group, MV_U32 mask, MV_U32 value);
+
+/* mvGppPolarityGet - Get the Polarity of a GPP Pin */
+MV_U32 mvGppPolarityGet(MV_U32 group, MV_U32 mask);
+
+/* mvGppValueGet - Get a GPP Pin list value. */
+MV_U32 mvGppValueGet(MV_U32 group, MV_U32 mask);
+
+/* mvGppValueSet - Set a GPP Pin list value. */
+MV_STATUS mvGppValueSet(MV_U32 group, MV_U32 mask, MV_U32 value);
+
+/* mvGppBlinkCounterSet - Set a Blink counter on / off values. */
+MV_STATUS mvGppBlinkCntrSet(MV_GPP_BLINK_CNTR blnkCntr, MV_U32 onDuration, MV_U32 offDuration);
+
+/* mvGppBlinkCntrSelect - Associate a given gpp to a blink counter. */
+MV_STATUS mvGppBlinkCntrSelect(MV_U32 gppIdx, MV_GPP_BLINK_CNTR blnkCntr);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* #ifndef __INCmvGppH */
diff --git a/arch/arm/plat-feroceon/mv_hal/gpp/mvGppRegs.h b/arch/arm/plat-feroceon/mv_hal/gpp/mvGppRegs.h
new file mode 100755
index 0000000..d7ae553
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/gpp/mvGppRegs.h
@@ -0,0 +1,132 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvGppRegsH
+#define __INCmvGppRegsH
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+#include "mvSysGppConfig.h"
+
+#define    MV_GPP0  BIT0
+#define    MV_GPP1  BIT1
+#define    MV_GPP2  BIT2
+#define    MV_GPP3  BIT3
+#define    MV_GPP4  BIT4
+#define    MV_GPP5  BIT5
+#define    MV_GPP6  BIT6
+#define    MV_GPP7  BIT7
+#define    MV_GPP8  BIT8
+#define    MV_GPP9  BIT9
+#define    MV_GPP10 BIT10
+#define    MV_GPP11 BIT11
+#define    MV_GPP12 BIT12
+#define    MV_GPP13 BIT13
+#define    MV_GPP14 BIT14
+#define    MV_GPP15 BIT15
+#define    MV_GPP16 BIT16
+#define    MV_GPP17 BIT17
+#define    MV_GPP18 BIT18
+#define    MV_GPP19 BIT19
+#define    MV_GPP20 BIT20
+#define    MV_GPP21 BIT21
+#define    MV_GPP22 BIT22
+#define    MV_GPP23 BIT23
+#define    MV_GPP24 BIT24
+#define    MV_GPP25 BIT25
+#define    MV_GPP26 BIT26
+#define    MV_GPP27 BIT27
+#define    MV_GPP28 BIT28
+#define    MV_GPP29 BIT29
+#define    MV_GPP30 BIT30
+#define    MV_GPP31 BIT31
+
+/* registers offsets */
+
+#define GPP_DATA_OUT_REG(grp)			(MV_GPP_REGS_BASE(grp) + 0x00)
+#define GPP_DATA_OUT_REG_0			(MV_GPP_REGS_BASE_0 + 0x00)	/* Used in .S files */
+#define GPP_DATA_OUT_EN_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x04)
+#define GPP_BLINK_EN_REG(grp)			(MV_GPP_REGS_BASE(grp) + 0x08)
+#define GPP_DATA_IN_POL_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x0C)
+#define GPP_DATA_IN_REG(grp)			(MV_GPP_REGS_BASE(grp) + 0x10)
+#define GPP_INT_CAUSE_REG(grp)			(MV_GPP_REGS_BASE(grp) + 0x14)
+#define GPP_INT_MASK_REG(grp)			(MV_GPP_REGS_BASE(grp) + 0x18)
+#define GPP_INT_LVL_REG(grp)			(MV_GPP_REGS_BASE(grp) + 0x1C)
+
+#define GPP_BLINK_CNTR_ON(idx)			(MV_GPP_REGS_BASE(0) + 0xC0 + (idx) * 8)
+#define GPP_BLINK_CNTR_OFF(idx)			(MV_GPP_REGS_BASE(0) + 0xC4 + (idx) * 8)
+#define GPP_BLINK_CNTR_SELECT(grp)		(MV_GPP_REGS_BASE(grp) + 0x20)
+
+#define GPP_FUNC_SELECT_REG			(MV_GPP_REGS_BASE(0) + 0x40)
+
+/* Relevant for MV78XX0 */
+#define GPP_DATA_OUT_SET_REG			(MV_GPP_REGS_BASE(0) + 0x20)
+#define GPP_DATA_OUT_CLEAR_REG			(MV_GPP_REGS_BASE(0) + 0x24)
+
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+#endif				/* #ifndef __INCmvGppRegsH */
diff --git a/arch/arm/plat-feroceon/mv_hal/idma/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/idma/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/idma/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/idma/mvIdma.c b/arch/arm/plat-feroceon/mv_hal/idma/mvIdma.c
new file mode 100755
index 0000000..cbae167
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/idma/mvIdma.c
@@ -0,0 +1,427 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvIdma.c - Implementation file for IDMA HW library
+*
+* DESCRIPTION:
+*       This file contains Marvell Controller IDMA HW library API
+*       implementation.
+*       NOTE:
+*       1) This HW library API assumes IDMA source, destination and
+*          descriptors are cache coherent.
+*       2) In order to gain high performance, the API does not parform
+*          API parameter checking.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "idma/mvIdma.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)   x
+#else
+#define DB(x)
+#endif
+
+/*******************************************************************************
+* mvDmaInit - Initialize IDMA engine
+*
+* DESCRIPTION:
+*               This function initialize IDMA unit.
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if setting fail.
+*******************************************************************************/
+MV_VOID mvDmaHalInit(MV_U32 dmaChanNum)
+{
+	MV_U32 i;
+
+	/* Abort any DMA activity */
+	for (i = 0; i < dmaChanNum; i++) {
+		mvDmaCommandSet(i, MV_STOP);
+
+#if defined(MV_CPU_LE) || defined(MV78XX0)
+		/* The following must be set */
+		mvDmaCtrlHighSet(i, (ICCHR_ENDIAN_LITTLE
+#if defined(MV_CPU_LE)
+				     | ICCHR_DESC_BYTE_SWAP_EN
+#endif /* MV_CPU_LE */
+				 ));
+#endif /* MV_CPU_LE || MV78XX0 */
+	}
+	MV_REG_WRITE(IDMA_CAUSE_REG, 0);
+}
+
+/*******************************************************************************
+* mvDmaCtrlLowSet - Set IDMA channel control low register
+*
+* DESCRIPTION:
+*       Each IDMA Channel has its own unique control registers (high and low)
+*       where certain IDMA modes are programmed.
+*       This function writes 32bit word to IDMA control low register.
+*
+*						!!!!!! WARNING !!!!!!
+*		If system uses the IDMA DRAM HW cache coherency the source and
+* 		destination maximum DTL size must be cache line size.
+*
+* INPUT:
+*       chan     - DMA channel number. See MV_DMA_CHANNEL enumerator.
+*       ctrlWord - Channel control word for low register.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK
+*
+* NOTE: This function can modified the Override attribute that mvDmaOverrideSet
+*       configured.
+*******************************************************************************/
+MV_STATUS mvDmaCtrlLowSet(MV_U32 chan, MV_U32 ctrlWord)
+{
+	MV_REG_WRITE(IDMA_CTRL_LOW_REG(chan), ctrlWord);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDmaCtrlHighSet - Set IDMA channel control high register
+*
+* DESCRIPTION:
+*       Each IDMA Channel has its own unique control registers (high and low)
+*       where certain IDMA modes are programmed.
+*       This function writes 32bit word to IDMA control high register.
+*
+* INPUT:
+*       chan     - DMA channel number. See MV_DMA_CHANNEL enumerator.
+*       ctrlWord - Channel control word for high register.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK.
+*
+*******************************************************************************/
+MV_STATUS mvDmaCtrlHighSet(MV_U32 chan, MV_U32 ctrlWord)
+{
+	MV_REG_WRITE(IDMA_CTRL_HIGH_REG(chan), ctrlWord);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDmaTransfer - Transfer data from source to destination
+*
+* DESCRIPTION:
+*       This function initiates IDMA channel, according to function parameters,
+*       in order to perform DMA transaction.
+*       This routine supports both chain and none chained DMA modes.
+*       To use the function in chain mode just set phyNextDesc parameter with
+*       chain second descriptor address (the first one is given in other
+*       function paarameters). Otherwise (none chain mode) set it to NULL.
+*       To gain maximum performance the user is asked to keep the following
+*       restrictions:
+*       1) Selected engine is available (not busy).
+*       1) This module does not take into consideration CPU MMU issues.
+*          In order for the IDMA engine to access the appropreate source
+*          and destination, address parameters must be given in system
+*          physical mode.
+*       2) This API does not take care of cache coherency issues. The source,
+*          destination and in case of chain the descriptor list are assumed
+*          to be cache coherent.
+*       3) In case of chain mode, the API does not align the user descriptor
+*          chain. Instead, the user must make sure the descriptor chain is
+*          aligned according to IDMA rquirements.
+*       4) Parameters validity. For example, does size parameter exceeds
+*          maximum byte count of descriptor mode (16M or 64K).
+*
+* INPUT:
+*       chan          - DMA channel number. See MV_DMA_CHANNEL enumerator.
+*       phySrc        - Physical source address.
+*       phyDst        - Physical destination address.
+*       size          - The total number of bytes to transfer.
+*       *pPhyNextDesc - Physical address pointer to 2nd descriptor in chain.
+*                       In case of none chain mode set it to NULL.
+*
+* OUTPUT:
+*       None.
+*
+* RETURS:
+*       MV_OK.
+*
+*******************************************************************************/
+MV_STATUS mvDmaTransfer(MV_U32 chan, MV_U32 phySrc, MV_U32 phyDst, MV_U32 size, MV_U32 phyNextDescPtr)
+{
+	/* Set byte count register                      */
+	MV_REG_WRITE(IDMA_BYTE_COUNT_REG(chan), size);
+	/* Set source address register          */
+	MV_REG_WRITE(IDMA_SRC_ADDR_REG(chan), phySrc);
+	/* Set destination address register     */
+	MV_REG_WRITE(IDMA_DST_ADDR_REG(chan), phyDst);
+	/* UnLock the Source address in dma operation */
+	MV_REG_BIT_RESET(IDMA_CTRL_LOW_REG(chan), ICCLR_SRC_HOLD);
+
+	if (0 != phyNextDescPtr) {	/* Chain mode. Set next descriptor register     */
+		MV_REG_WRITE(IDMA_NEXT_DESC_PTR_REG(chan), phyNextDescPtr);
+	}
+
+	/* Start DMA    */
+	MV_REG_BIT_SET(IDMA_CTRL_LOW_REG(chan), ICCLR_CHAN_ENABLE);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDmaMemInit - Initialize a memory buffer with a given 64bit value pattern
+*
+* DESCRIPTION:
+*       This function initiates IDMA channel, according to function parameters,
+*       in order to perform DMA transaction for the purpose of initializing a
+*       memory buffer with a user supplied pattern.
+*       This routine supports both chain and none chained DMA modes.
+*       To use the function in chain mode just set phyNextDesc parameter with
+*       chain second descriptor address (the first one is given in other
+*       function paarameters). Otherwise (none chain mode) set it to NULL.
+*       To gain maximum performance the user is asked to keep the following
+*       restrictions:
+*       1) Selected engine is available (not busy).
+*       1) This module does not take into consideration CPU MMU issues.
+*          In order for the IDMA engine to access the appropreate source
+*          and destination, address parameters must be given in system
+*          physical mode.
+*       2) This API does not take care of cache coherency issues. The source,
+*          destination and in case of chain the descriptor list are assumed
+*          to be cache coherent.
+*       3) No chain mode support.
+*       4) Parameters validity. For example, does size parameter exceeds
+*          maximum byte count of descriptor mode (16M or 64K).
+*
+* INPUT:
+*       chan          - DMA channel number. See MV_DMA_CHANNEL enumerator.
+*       ptrnPtr       - Physical source address of the 64bit pattern
+*       startPtr      - Physical destinaation address to start with
+*       size          - The total number of bytes to transfer.
+*
+* OUTPUT:
+*       None.
+*
+* RETURS:
+*       MV_OK.
+*
+*******************************************************************************/
+MV_STATUS mvDmaMemInit(MV_U32 chan, MV_U32 ptrnPtr, MV_U32 startPtr, MV_U32 size)
+{
+	/* Set byte count register                      */
+	MV_REG_WRITE(IDMA_BYTE_COUNT_REG(chan), size);
+	/* Set source address register          */
+	MV_REG_WRITE(IDMA_SRC_ADDR_REG(chan), ptrnPtr);
+	/* Set destination address register     */
+	MV_REG_WRITE(IDMA_DST_ADDR_REG(chan), startPtr);
+	/* Lock the Source address in dma operation */
+	MV_REG_BIT_SET(IDMA_CTRL_LOW_REG(chan), ICCLR_SRC_HOLD);
+
+	/* Start DMA    */
+	MV_REG_BIT_SET(IDMA_CTRL_LOW_REG(chan), ICCLR_CHAN_ENABLE);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDmaStateGet - Get IDMA channel status.
+*
+* DESCRIPTION:
+*       DMA channel status can be active, stopped, paused.
+*       This function retrunes the channel status.
+*
+* INPUT:
+*       chan - IDMA channel number. See MV_DMA_CHANNEL enumerator.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       One of MV_STATE enumerator values.
+*
+*******************************************************************************/
+MV_STATE mvDmaStateGet(MV_U32 chan)
+{
+	MV_U32 ctrlLow;
+
+	/* Read control low register    */
+	ctrlLow = MV_REG_READ(IDMA_CTRL_LOW_REG(chan));
+
+	/* Leave only enable/active bits    */
+	ctrlLow &= (ICCLR_CHAN_ENABLE | ICCLR_CHAN_ACTIVE);
+
+	/* If channel is enabled and active then its running        */
+	if (ctrlLow == (ICCLR_CHAN_ENABLE | ICCLR_CHAN_ACTIVE))
+		return MV_ACTIVE;
+
+	/* If channel is disabled but active then its paused        */
+	else if (ctrlLow == ICCLR_CHAN_ACTIVE)
+		return MV_PAUSED;
+	else
+		return MV_IDLE;
+}
+
+/*******************************************************************************
+* mvDmaCommandSet - Set command to DMA channel
+*
+* DESCRIPTION:
+*       DMA channel can be started, idel, paused and restarted.
+*       Paused can be set only if channel is active.
+*       Start can be set only if channel is idle.
+*       Restart can be set only if channel is paused.
+*       Stop activate the channel abort which cause the DMA to aborts in the
+*       middle of a transaction.
+*
+* INPUT:
+*       chan    - IDMA channel number. See MV_DMA_CHANNEL enumerator.
+*       command - Requested command. See MV_COMMAND enumerator.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if requested command can not be set.
+*
+*******************************************************************************/
+MV_STATUS mvDmaCommandSet(MV_U32 chan, MV_COMMAND command)
+{
+	MV_U32 ctrlLow;
+	MV_U32 dmaStatus;
+
+	/* Read control low register    */
+	ctrlLow = MV_REG_READ(IDMA_CTRL_LOW_REG(chan));
+
+	/* Get current DMA status       */
+	dmaStatus = mvDmaStateGet(chan);
+
+	if ((command == MV_START) && (dmaStatus == MV_IDLE)) {
+		/* To start, set DMA channel enable bit                             */
+		ctrlLow |= ICCLR_CHAN_ENABLE;
+	} else if ((command == MV_PAUSE) && (dmaStatus == MV_ACTIVE)) {
+		/* To pause, reset DMA channel enable bit                           */
+		ctrlLow &= ~ICCLR_CHAN_ENABLE;
+	} else if ((command == MV_RESTART) && (dmaStatus == MV_PAUSED)) {
+		/* To restart, set DMA channel enable bit                           */
+		ctrlLow |= ICCLR_CHAN_ENABLE;
+	} else if (command == MV_STOP) {
+		/* To stop, set DMA channel abort bit                               */
+		ctrlLow |= ICCLR_CHANNEL_ABORT;
+	} else {
+		DB(mvOsPrintf("mvDmaCommandSet: ERR. Can not set command %d in \
+					   status %d\n", command, dmaStatus));
+		return MV_ERROR;
+	}
+
+	/* Write control word to register   */
+	MV_REG_WRITE(IDMA_CTRL_LOW_REG(chan), ctrlLow);
+
+	/* If comman is stop, ensure channel is stopped                         */
+	if (command == MV_STOP) {
+		while (MV_IDLE != mvDmaStateGet(chan))
+			continue;
+	}
+
+	return MV_OK;
+}
+
+/************ DEBUG ***********/
+MV_VOID mvIdmaRegs(MV_U32 chan)
+{
+	mvOsPrintf("\t IDMA #%d Registers:\n", chan);
+
+	mvOsPrintf("IDMA_BYTE_COUNT_REG             : 0x%X = 0x%08x\n",
+		   IDMA_BYTE_COUNT_REG(chan), MV_REG_READ(IDMA_BYTE_COUNT_REG(chan)));
+
+	mvOsPrintf("IDMA_SRC_ADDR_REG               : 0x%X = 0x%08x\n",
+		   IDMA_SRC_ADDR_REG(chan), MV_REG_READ(IDMA_SRC_ADDR_REG(chan)));
+
+	mvOsPrintf("IDMA_DST_ADDR_REG               : 0x%X = 0x%08x\n",
+		   IDMA_DST_ADDR_REG(chan), MV_REG_READ(IDMA_DST_ADDR_REG(chan)));
+
+	mvOsPrintf("IDMA_NEXT_DESC_PTR_REG          : 0x%X = 0x%08x\n",
+		   IDMA_NEXT_DESC_PTR_REG(chan), MV_REG_READ(IDMA_NEXT_DESC_PTR_REG(chan)));
+
+	mvOsPrintf("IDMA_CURR_DESC_PTR_REG          : 0x%X = 0x%08x\n",
+		   IDMA_CURR_DESC_PTR_REG(chan), MV_REG_READ(IDMA_CURR_DESC_PTR_REG(chan)));
+
+	mvOsPrintf("IDMA_CTRL_LOW_REG               : 0x%X = 0x%08x\n",
+		   IDMA_CTRL_LOW_REG(chan), MV_REG_READ(IDMA_CTRL_LOW_REG(chan)));
+
+	mvOsPrintf("IDMA_CTRL_HIGH_REG              : 0x%X = 0x%08x\n",
+		   IDMA_CTRL_HIGH_REG(chan), MV_REG_READ(IDMA_CTRL_HIGH_REG(chan)));
+
+	mvOsPrintf("IDMA_CAUSE_REG                  : 0x%X = 0x%08x\n", IDMA_CAUSE_REG, MV_REG_READ(IDMA_CAUSE_REG));
+
+	mvOsPrintf("IDMA_MASK_REG                   : 0x%X = 0x%08x\n", IDMA_MASK_REG, MV_REG_READ(IDMA_MASK_REG));
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/idma/mvIdma.h b/arch/arm/plat-feroceon/mv_hal/idma/mvIdma.h
new file mode 100755
index 0000000..69beb04
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/idma/mvIdma.h
@@ -0,0 +1,118 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvIdma.h - Header File for :
+*
+* DESCRIPTION:
+*       This file contains Marvell Controller IDMA HW library API.
+*       NOTE: This HW library API assumes IDMA source, destination and
+*       descriptors are cache coherent.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+
+#ifndef __INCmvIdmah
+#define __INCmvIdmah
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "idma/mvIdmaRegs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+/* defines  */
+#define MV_IDMA_DESC_ALIGNMENT  0x10  /* 16bytes aligment restriction       */
+
+/* typedefs */
+
+
+/* This struct describes IDMA descriptor structure                          */
+typedef struct _mvDmaDesc {
+	MV_U32 	byteCnt;	/* The total number of bytes to transfer        */
+	MV_U32 	phySrcAdd;	/* The physical source address                  */
+	MV_U32 	phyDestAdd;	/* The physical destination address             */
+	MV_U32	phyNextDescPtr;	/* If we are using chain mode DMA transfer,     */
+				/* then this pointer should point to the        */
+				/* physical address of the next descriptor,     */
+				/* otherwise it should be NULL.                 */
+} MV_DMA_DESC;
+
+
+/* mvIdma.h API list */
+MV_VOID mvDmaHalInit(MV_U32);
+MV_STATUS mvDmaCtrlLowSet(MV_U32 chan, MV_U32 ctrlWord);
+MV_STATUS mvDmaCtrlHighSet(MV_U32 chan, MV_U32 ctrlWord);
+MV_STATUS mvDmaTransfer(MV_U32 chan, MV_U32 phySrc, MV_U32 phyDst, MV_U32 size, MV_U32 phyNextDescPtr);
+MV_STATUS mvDmaMemInit(MV_U32 chan, MV_U32 ptrnPtr, MV_U32 startPtr, MV_U32 size);
+MV_STATE  mvDmaStateGet(MV_U32 chan);
+MV_STATUS mvDmaCommandSet(MV_U32 chan, MV_COMMAND command);
+
+MV_VOID mvIdmaRegs(MV_U32 chan);
+
+#endif /* __INCmvIdmah */
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/idma/mvIdmaRegs.h b/arch/arm/plat-feroceon/mv_hal/idma/mvIdmaRegs.h
new file mode 100755
index 0000000..8dc6488
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/idma/mvIdmaRegs.h
@@ -0,0 +1,210 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvIdmaRegsh
+#define __INCmvIdmaRegsh
+
+
+/* defines */
+
+
+/* IDMA channel rgisters       												*/
+#define IDMA_BYTE_COUNT_REG(chan)          	(IDMA_UNIT_BASE + 0x0 + ((chan) * 4))
+#define IDMA_SRC_ADDR_REG(chan)            	(IDMA_UNIT_BASE + 0x10 + ((chan) * 4))
+#define IDMA_DST_ADDR_REG(chan)            	(IDMA_UNIT_BASE + 0x20 + ((chan) * 4))
+#define IDMA_NEXT_DESC_PTR_REG(chan)       	(IDMA_UNIT_BASE + 0x30 + ((chan) * 4))
+#define IDMA_CURR_DESC_PTR_REG(chan)	   	(IDMA_UNIT_BASE + 0x70 + ((chan) * 4))
+
+/* IDMA Channel Control														*/
+#define IDMA_CTRL_LOW_REG(chan)			(IDMA_UNIT_BASE + 0x40 + ((chan) * 4))
+#define IDMA_CTRL_HIGH_REG(chan)		(IDMA_UNIT_BASE + 0x80 + ((chan) * 4))
+
+ /*  IDMA Interrupt Register  */
+#define IDMA_CAUSE_REG            		(IDMA_UNIT_BASE + 0xc0)
+#define IDMA_MASK_REG           		(IDMA_UNIT_BASE + 0xc4)
+#define IDMA_ERROR_ADDR_REG             (IDMA_UNIT_BASE + 0xc8)
+#define IDMA_ERROR_SELECT_REG           (IDMA_UNIT_BASE + 0xcc)
+
+
+/* DMA register fileds */
+
+
+/* IDMA Channel Byte Count Register (ICBCR) */
+#define ICBCR_BYTECNT_OFFS			0		/* Byte count field offset		*/
+#define ICBCR_BYTECNT_MASK_64K  	0xFFFF	/* Maximum Byte count for 64K 	*/
+#define ICBCR_BYTECNT_MASK_16M  	0xFFFFFF/* Maximum Byte count for 16M	*/
+#define ICBCR_BYTECNT_LEFT_OFFS		30		/* Applicable for 16M mode		*/
+#define ICBCR_BYTECNT_LEFT			(1 << ICBCR_BYTECNT_LEFT_OFFS)
+#define ICBCR_DESC_OWNER_OFFS		31		/* Descriptor owned by DMA/CPU	*/
+#define ICBCR_DESC_OWNER_MASK		(1 << ICBCR_DESC_OWNER_OFFS)
+#define ICBCR_DESC_OWNER_BY_DMA		(0 << ICBCR_DESC_OWNER_OFFS)
+#define ICBCR_DESC_OWNED_BY_CPU		(1 << ICBCR_DESC_OWNER_OFFS)
+
+
+/* IDMA Channel Control Low Register (ICCLR)								*/
+/* Data Transfer Limit Note: If an IDMA accesses a cache coherent DRAM 		*/
+/* region, the burst limit must not exceed 32 bytes.						*/
+#define B_8BYTE		0
+#define B_16BYTE	1
+#define B_32BYTE	3
+#define B_64BYTE	7
+#define B_128BYTE	4
+
+#define ICCLR_DST_BURST_LIM_OFFS	0
+#define ICCLR_DST_BURST_LIM_MASK	(0x7 << ICCLR_DST_BURST_LIM_OFFS)
+#define ICCLR_DST_BURST_LIM_8BYTE	(B_8BYTE   << ICCLR_DST_BURST_LIM_OFFS)
+#define ICCLR_DST_BURST_LIM_16BYTE	(B_16BYTE  << ICCLR_DST_BURST_LIM_OFFS)
+#define ICCLR_DST_BURST_LIM_32BYTE	(B_32BYTE  << ICCLR_DST_BURST_LIM_OFFS)
+#define ICCLR_DST_BURST_LIM_64BYTE	(B_64BYTE  << ICCLR_DST_BURST_LIM_OFFS)
+#define ICCLR_DST_BURST_LIM_128BYTE	(B_128BYTE << ICCLR_DST_BURST_LIM_OFFS)
+#define ICCLR_SRC_HOLD_OFFS		3   	/* Hold/increment source address*/
+#define ICCLR_SRC_HOLD_MASK		(1 << ICCLR_SRC_HOLD_OFFS)
+#define ICCLR_SRC_INC		   	(0 << ICCLR_SRC_HOLD_OFFS)
+#define ICCLR_SRC_HOLD		   	(1 << ICCLR_SRC_HOLD_OFFS)
+#define ICCLR_ACK_WIDTH_OFFS		4 	/* Asserted for one/two TCLK cycle	*/
+#define ICCLR_ACK_WIDTH_MASK		(1 << ICCLR_ACK_WIDTH_OFFS)
+#define ICCLR_ACK_WIDTH_ONE_TCLK	(0 << ICCLR_ACK_WIDTH_OFFS)
+#define ICCLR_ACK_WIDTH_TWO_TCLK	(1 << ICCLR_ACK_WIDTH_OFFS)
+#define ICCLR_DST_HOLD_OFFS		5   	/* Hold/increment source address*/
+#define ICCLR_DST_HOLD_MASK		(1 << ICCLR_DST_HOLD_OFFS)
+#define ICCLR_DST_INC		   	(0 << ICCLR_DST_HOLD_OFFS)
+#define ICCLR_DST_HOLD		   	(1 << ICCLR_DST_HOLD_OFFS)
+#define ICCLR_SRC_BURST_LIM_OFFS	6
+#define ICCLR_SRC_BURST_LIM_MASK	(0x7 << ICCLR_SRC_BURST_LIM_OFFS)
+#define ICCLR_SRC_BURST_LIM_8BYTE	(B_8BYTE   << ICCLR_SRC_BURST_LIM_OFFS)
+#define ICCLR_SRC_BURST_LIM_16BYTE	(B_16BYTE  << ICCLR_SRC_BURST_LIM_OFFS)
+#define ICCLR_SRC_BURST_LIM_32BYTE	(B_32BYTE  << ICCLR_SRC_BURST_LIM_OFFS)
+#define ICCLR_SRC_BURST_LIM_64BYTE	(B_64BYTE  << ICCLR_SRC_BURST_LIM_OFFS)
+#define ICCLR_SRC_BURST_LIM_128BYTE	(B_128BYTE << ICCLR_SRC_BURST_LIM_OFFS)
+#define ICCLR_CHAIN_MODE_OFFS	   	9
+#define ICCLR_NON_CHAIN_MODE  	   	(1 << ICCLR_CHAIN_MODE_OFFS)
+#define ICCLR_INT_MODE_OFFS		10  	/* Interrupt mode               */
+#define ICCLR_INT_MODE_MASK		(1 << ICCLR_INT_MODE_OFFS)
+#define ICCLR_INT_BYTE_CNT_ZERO		(0 << ICCLR_INT_MODE_OFFS)
+#define ICCLR_INT_EVERY_NULL_PTR	(1 << ICCLR_INT_MODE_OFFS)
+#define ICCLR_DEMAND_MODE_OFFS		11  	/* Demand/Block transfer mode	*/
+#define ICCLR_DEMAND_MODE_MASK		(1 << ICCLR_DEMAND_MODE_OFFS)
+#define ICCLR_DEMAND_MODE		(0 << ICCLR_DEMAND_MODE_OFFS)
+#define ICCLR_BLOCK_MODE		(1 << ICCLR_DEMAND_MODE_OFFS)
+#define ICCLR_CHAN_ENABLE		BIT12	/* Channel enable				*/
+#define ICCLR_FETCH_NEXT_DESC	   	BIT13	/* Fetch next descriptor		*/
+#define ICCLR_CHAN_ACTIVE	        BIT14  	/* Channel active				*/
+#define ICCLR_REQ_DIR_OFFS		15		/* Request generated by src/dst	*/
+#define ICCLR_REQ_DIR_MASK		(1 << ICCLR_REQ_DIR_OFFS)
+#define ICCLR_REQ_DIR_SRC		(0 << ICCLR_REQ_DIR_OFFS)
+#define ICCLR_REQ_DIR_DST		(1 << ICCLR_REQ_DIR_OFFS)
+#define ICCLR_REQ_MODE_OFFS		16		/* DMAReqn is level/edge input	*/
+#define ICCLR_REQ_MODE_MASK		(1 << ICCLR_REQ_MODE_OFFS)
+#define ICCLR_REQ_MODE_LEVEL		(0 << ICCLR_REQ_MODE_OFFS)
+#define ICCLR_REQ_MODE_EDGE		(1 << ICCLR_REQ_MODE_OFFS)
+#define ICCLR_CLOSE_DESC_ENABLE	   	BIT17  	/* Close descriptor enable      */
+#define ICCLR_EOT_ENABLE		BIT18  	/* End Of Tarnsfer (EOT) enable */
+#define ICCLR_EOT_AFFECT_OFFS		19 /* EOT -> Fetch next descriptor/halt */
+#define ICCLR_EOT_AFFECT_MASK		(1 << ICCLR_EOT_AFFECT_OFFS)
+#define ICCLR_EOT_FETCH_NEXT		(0 << ICCLR_EOT_AFFECT_OFFS)
+#define ICCLR_EOT_FETCH_HALT		(1 << ICCLR_EOT_AFFECT_OFFS)
+#define ICCLR_CHANNEL_ABORT		BIT20  	/* Abort DMA transfer           */
+
+#define ICCLR_OVRRD_SRC_OFFS		21
+#define ICCLR_OVRRD_SRC_MASK		(0x3 << ICCLR_OVRRD_SRC_OFFS)
+#define ICCLR_OVRRD_SRC_BAR(barNo)	((barNo) << ICCLR_OVRRD_SRC_OFFS)
+
+#define ICCLR_OVRRD_DST_OFFS		23
+#define ICCLR_OVRRD_DST_MASK		(0x3 << ICCLR_OVRRD_DST_OFFS)
+#define ICCLR_OVRRD_DST_BAR(barNo)	((barNo) << ICCLR_OVRRD_DST_OFFS)
+
+#define ICCLR_OVRRD_NDSC_OFFS		25
+#define ICCLR_OVRRD_NDSC_MASK		(0x3 << ICCLR_OVRRD_NDSC_OFFS)
+#define ICCLR_OVRRD_NDSC_BAR(barNo)	((barNo) << ICCLR_OVRRD_NDSC_OFFS)
+
+#define ICCLR_DESC_MODE_OFFS		31	/* Descriptor mode 64KB/16M    	*/
+#define ICCLR_DESC_MODE_MASK		(1 << ICCLR_DESC_MODE_OFFS)
+#define ICCLR_DESC_MODE_64K		(0 << ICCLR_DESC_MODE_OFFS)
+#define ICCLR_DESC_MODE_16M		(1 << ICCLR_DESC_MODE_OFFS)
+
+/* IDMA Channel Control High Register (ICCHR)								*/
+#define ICCHR_ENDIANESS_OFFS		0
+#define ICCHR_ENDIANESS_MASK		(1 << ICCHR_ENDIANESS_OFFS)
+#define ICCHR_ENDIAN_BIG		(0 << ICCHR_ENDIANESS_OFFS)
+#define ICCHR_ENDIAN_LITTLE		(1 << ICCHR_ENDIANESS_OFFS)
+#define ICCHR_DESC_BYTE_SWAP_EN		BIT1	/* swap the bytes of 64-bit 	*/
+											/* dword during descriptor fetch*/
+#define ICCHR_DESC_DEMAND_ENABLE	BIT2	/* Descriptor Demand Mode en	*/
+
+/* IDMA Channel Interrupt Cause Register (ICICR) */
+#define ICICR_CHAN_OFFS			8
+#define ICICR_CAUSE_OFFS(chan)   	(chan * ICICR_CHAN_OFFS)
+#define ICICR_CAUSE_MASK_ALL(chan)      (0xFF << ICICR_CAUSE_OFFS(chan))
+#define ICICR_CAUSE_MASK(chan, cause)   (1 << (cause + ICICR_CAUSE_OFFS(chan)))
+#define ICICR_COMP_MASK			0x01010101
+#define ICICR_ERR_MASK			0x3e3e3e3e
+
+/* IDMA Error Select Register (IESR)	*/
+#define IESR_ERR_TYPE_OFFS		0
+#define IESR_ERR_TYPE_MASK		(0x1f << IESR_ERR_TYPE_OFFS)
+
+
+
+#endif	/* __INCmvIdmaRegsh */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/mflash/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlash.c b/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlash.c
new file mode 100755
index 0000000..266dc37
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlash.c
@@ -0,0 +1,1320 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+ 
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include "mflash/mvMFlash.h"
+#include "mflash/mvPMFlash.h"
+#include "mflash/mvSMFlash.h" 
+#include "mflash/mvMFlashSpec.h"
+#include "mflash/mvPMFlashSpec.h"
+#include "mflash/mvSMFlashSpec.h"
+
+/*#define MV_DEBUG*/
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+/* Static Functions */
+static MV_STATUS mvMFlashBlockByRegionWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, \
+                                         MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify, \
+                                         MV_BOOL main);
+static MV_STATUS mvMFlash64bInfWr       (MV_MFLASH_INFO *pFlash, MV_U32 offset, \
+                                         MV_U8 *pBuff, MV_BOOL verify);
+static MV_STATUS mvMFlash64bWr          (MV_MFLASH_INFO *pFlash, MV_U32 offset, \
+                                         MV_U8 *pBuff, MV_BOOL verify);
+
+/*******************************************************************************
+* mvMFlashInit - Initialize a Marvell Flash device
+*
+* DESCRIPTION:
+*       This function performs the necessary initialization for a Marvell 
+*       Sunol flash.
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*           pFlash->baseAddr: flash base address.
+*           pFlash->ifMode: The mode used SPI or Parallel.
+*       
+* OUTPUT:
+*       pFlash: pointer to the tructure with Marvell Flash information detected
+*           pFlash->flashModel: flash model deteced
+*           pFlash->sectorSize: Size of each sector (unified sector size)
+*           pFlash->sectorNumber: Number of sectors in the flash
+*           pFlash->infoSize: Size of the Information region.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashInit (MV_MFLASH_INFO *pFlash)
+{
+    MV_U32  manufId;
+    MV_U16  devId;
+    MV_U8  reg;
+    MV_STATUS ret;
+
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+    {
+        /* perform the basic initialization */
+        if ((ret = mvPMFlashInit(pFlash)) != MV_OK)
+            return ret;
+
+        /* Try to read the device ID and decide the device model */
+        if ((ret = mvPMFlashIdGet(pFlash, &manufId, &devId)) != MV_OK)
+            return ret;
+
+        /* Get the Serial interface configuration register to check sector size */
+        if ((ret = mvPMFlashReadConfig4(pFlash, &reg)) != MV_OK)
+            return ret;
+    }
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+    {   
+        /* perform the basic initialization */
+        if ((ret = mvSMFlashInit(pFlash)) != MV_OK)
+            return ret;
+
+        /* Try to read the device ID and decide the device model */
+        if ((ret = mvSMFlashIdGet(pFlash, &manufId, &devId)) != MV_OK)
+            return ret;
+
+        /* Get the Serial interface configuration register to check sector size */
+        if ((ret = mvSMFlashReadConfig4(pFlash, &reg)) != MV_OK)
+            return ret;
+    }
+    else
+    {
+        mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    /* check the manufacturer Id to be the same as MARVELL */
+    if (manufId != MV_MFLASH_MANUFACTURER_ID)
+    {
+        mvOsPrintf("%s ERROR: Flash unknown manufacturer ID!\n", __FUNCTION__);
+        return MV_NOT_SUPPORTED;
+    }
+
+    /* based on device ID and the PAGE4K bit fill model, sector size and number */
+    switch (devId & MV_MFLASH_DEVICE_ID_MASK)
+    {
+        case MV_MFLASH_DEVICE_ID_SUNOL_1:
+            pFlash->flashModel = MV_MFLASH_SUNOL_1;
+            pFlash->infoSize = MV_MFLASH_INF_MEM_SZ_SUNOL_1;
+            if (reg & MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK)  /* 1 - page is 4K */
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL;
+                pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_1;
+            }
+            else    /* 0 - page is 32K */
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG;
+                pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_1;
+            }
+            break;
+
+        case MV_MFLASH_DEVICE_ID_SUNOL_2:
+            pFlash->flashModel = MV_MFLASH_SUNOL_2;
+            pFlash->infoSize = MV_MFLASH_INF_MEM_SZ_SUNOL_2_3;
+            if (reg & MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK)  /* 1 - page is 4K */
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL;
+                pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_2;
+            }
+            else    /* 0 - page is 32K */
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG;
+                pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_2;
+            }
+            break;
+
+        case MV_MFLASH_DEVICE_ID_SUNOL_3:
+            pFlash->flashModel = MV_MFLASH_SUNOL_3;
+            pFlash->infoSize = MV_MFLASH_INF_MEM_SZ_SUNOL_2_3;
+            if (reg & MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK)  /* 1 - page is 4K */
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL;
+                pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_3;
+            }
+            else    /* 0 - page is 32K */
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG;
+                pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_3;
+            }
+            break;
+
+        default:
+            mvOsPrintf("%s ERROR: Unknown Flash Device ID!\n", __FUNCTION__);
+            pFlash->flashModel = MV_MFLASH_MODEL_UNKNOWN;
+            return MV_NOT_SUPPORTED;
+    }
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvMFlashChipErase - Erase the whole flash
+*
+* DESCRIPTION:
+*       Erase the whole flash (both the Main and Information region)
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashChipErase (MV_MFLASH_INFO *pFlash)
+{
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashChipErase(pFlash);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashChipErase(pFlash);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}   
+
+/*******************************************************************************
+* mvMFlashMainErase - Erase the main flash region only
+*
+* DESCRIPTION:
+*       Erase the Main flash region
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashMainErase (MV_MFLASH_INFO *pFlash)
+{
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashMainErase(pFlash);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashMainErase(pFlash);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlashInfErase - Erase the information flash region only
+*
+* DESCRIPTION:
+*       Erase the information flash region
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashInfErase (MV_MFLASH_INFO *pFlash)
+{
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashInfErase(pFlash);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashInfErase(pFlash);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+
+/*******************************************************************************
+* mvMFlashSecErase - Erase the single sector of the main flash region 
+*
+* DESCRIPTION:
+*       Erase one sector of the main flash region
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		secOffset: sector offset within the MFlash
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashSecErase (MV_MFLASH_INFO *pFlash, MV_U32 secNumber)
+{
+    MV_U32 i;
+    MV_U32 * pW = (MV_U32*) ((secNumber * pFlash->sectorSize) + pFlash->baseAddr);
+    MV_U32 erasedWord = 0xFFFFFFFF;
+    MV_U32 wordsPerSector = (pFlash->sectorSize / sizeof(MV_U32));
+    MV_BOOL eraseNeeded = MV_FALSE;
+
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    /* First compare to FF and check if erase is needed */
+    for (i=0; i<wordsPerSector; i++)
+    {
+        if (memcmp(pW, &erasedWord, sizeof(MV_U32)) != 0)
+        {
+            eraseNeeded = MV_TRUE;
+            break;
+        }
+
+        ++pW;
+    }
+
+    if (!eraseNeeded)
+        return MV_OK;
+
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashSecErase(pFlash, secNumber);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashSecErase(pFlash, secNumber);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlash64bWr - Perform the alligned write according to the SPI mode and verify
+*                 type.
+*
+* DESCRIPTION:
+*       Select the appropriate write api according to the SPI mode and the 
+*       verify flag.
+*
+*******************************************************************************/
+static MV_STATUS mvMFlash64bWr (MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+                                          MV_U8 *pBuff, MV_BOOL verify)
+{
+    MV_STATUS ret; 
+
+    /* check for NULL pointer */
+#ifndef CONFIG_MARVELL
+    if(NULL == pBuff)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+#endif
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    /* call the api based on the SPI mode and the verify option */
+    if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+    {        
+	    if (verify)
+	    {          
+		    if ((ret = mvPMFlash64bWrVerify(pFlash, offset, pBuff)) != MV_OK)
+			    return ret;
+	    }
+	    else
+	    {
+		    if ((ret = mvPMFlash64bWr(pFlash, offset, pBuff)) != MV_OK)
+			    return ret;
+	    }
+    }      
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+    {
+        if (verify)
+	    {
+		    if ((ret = mvSMFlash64bWrVerify(pFlash, offset, pBuff)) != MV_OK)
+			    return ret;
+	    }
+	    else
+	    {
+		    if ((ret = mvSMFlash64bWr(pFlash, offset, pBuff)) != MV_OK)
+			    return ret;
+	    }
+    }
+    else
+    {
+        mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvMFlash64bInfWr - Perform the alligned write to the information region based 
+*                    on the SPI mode and verify type.
+*
+* DESCRIPTION:
+*       Select the appropriate write api according to the SPI mode and the 
+*       verify flag.
+*
+*******************************************************************************/
+static MV_STATUS mvMFlash64bInfWr (MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+                                           MV_U8 *pBuff, MV_BOOL verify)
+{
+    MV_STATUS ret; 
+
+    /* check for NULL pointer */
+#ifndef CONFIG_MARVELL
+    if(NULL == pBuff)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+#endif
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    /* call the api based on the SPI mode and the verify option */
+    if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+    {
+	    if (verify)
+	    {          
+		    if ((ret = mvPMFlash64bInfWrVerify(pFlash, offset, pBuff)) != MV_OK)
+			    return ret;
+	    }
+	    else
+	    {
+		    if ((ret = mvPMFlash64bInfWr(pFlash, offset, pBuff)) != MV_OK)
+			    return ret;
+	    }
+    }      
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+    {
+        if (verify)
+	    {
+		    if ((ret = mvSMFlash64bInfWrVerify(pFlash, offset, pBuff)) != MV_OK)
+			    return ret;
+	 
+	    }
+	    else
+	    {
+		    if ((ret = mvSMFlash64bInfWr(pFlash, offset, pBuff)) != MV_OK)
+			    return ret;
+	    }
+    }
+    else
+    {
+        mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    return MV_OK;
+}
+
+
+
+/*******************************************************************************
+* mvMFlashBlockByRegionWr - Write a buffer with a custom length and allignment
+*                           based on the region (main or information)
+*
+* DESCRIPTION:
+*       Program a varient sized block in the selected region of the MFlash
+*       and perform the verify based on flag.
+*
+*******************************************************************************/
+static MV_STATUS mvMFlashBlockByRegionWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+                          MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify, MV_BOOL main)
+{
+    MV_U8 tempBuff[MV_MFLASH_PROG_CHUNK_SIZE];
+	MV_U32 data2write	= blockSize;
+	MV_U32 preAllOfst	= (offset & MV_MFLASH_PROG_ALIGN_MASK);
+    MV_U32 preAllSz		= (preAllOfst ? (MV_MFLASH_PROG_CHUNK_SIZE - preAllOfst) : 0);	
+	MV_U32 writeOffset	= (offset & ~MV_MFLASH_PROG_ALIGN_MASK);
+    MV_STATUS ret;
+
+    /* check for NULL pointer */
+#ifndef CONFIG_MARVELL
+    if(NULL == pBlock)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+#endif
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* verify that the write commands does not exceed the size */
+    if ((offset + blockSize) >  (pFlash->sectorNumber * pFlash->sectorSize))
+    {
+        DB(mvOsPrintf("%s WARNING: Exceeded flash size!!\n", __FUNCTION__);)
+		return MV_BAD_PARAM;
+    }
+	
+	/* check if the total block size is less than the first chunk remainder */
+	if (data2write < preAllSz)
+		preAllSz = data2write;
+
+	/* check if programing does not start at a 64byte alligned offset */
+	if (preAllSz)
+	{
+        /* first copy the original data */
+        if (main)
+        {
+            if ((ret = mvMFlashBlockRd(pFlash, writeOffset, MV_MFLASH_PROG_CHUNK_SIZE, tempBuff)) != MV_OK)
+                return ret;
+        }
+        else
+        {
+            if ((ret = mvMFlashBlockInfRd(pFlash, writeOffset, MV_MFLASH_PROG_CHUNK_SIZE, tempBuff)) != MV_OK)
+                return ret;
+        }
+
+		/* overwrite the data to be changed */
+		mvOsMemcpy((MV_VOID*)&tempBuff[preAllOfst], pBlock, preAllSz);
+
+        /* Perform the 64 bytes write based on the mode and verify type */
+        if (main)
+        {
+            if ((ret = mvMFlash64bWr(pFlash, writeOffset, tempBuff, verify)) != MV_OK)
+                return ret;
+        }
+        else
+        {
+            if ((ret = mvMFlash64bInfWr(pFlash, writeOffset, tempBuff, verify)) != MV_OK)
+                return ret;
+        }
+		
+		/* increment pointers and counters */
+		writeOffset += MV_MFLASH_PROG_CHUNK_SIZE;
+		data2write -= preAllSz;
+		pBlock += preAllSz;
+	}
+
+	/* program the data that fits in complete 64bytes chunks */
+	while (data2write >= MV_MFLASH_PROG_CHUNK_SIZE)
+	{
+        /* Perform the 64 bytes write based on the mode and verify type */
+        if (main)
+        {
+            if ((ret = mvMFlash64bWr(pFlash, writeOffset, pBlock, verify)) != MV_OK)
+                return ret;
+        }
+        else
+        {
+            if ((ret = mvMFlash64bInfWr(pFlash, writeOffset, pBlock, verify)) != MV_OK)
+                return ret;
+        }
+
+		/* increment pointers and counters */
+		writeOffset += MV_MFLASH_PROG_CHUNK_SIZE;
+		data2write -= MV_MFLASH_PROG_CHUNK_SIZE;
+		pBlock += MV_MFLASH_PROG_CHUNK_SIZE;
+	}
+
+	/* program the last partial chunk */
+	if (data2write)
+	{
+		/* first copy the original data */
+        if (main)
+        {
+            if ((ret = mvMFlashBlockRd(pFlash, writeOffset, MV_MFLASH_PROG_CHUNK_SIZE, tempBuff)) != MV_OK)
+                return ret;
+        }
+        else
+        {
+            if ((ret = mvMFlashBlockInfRd(pFlash, writeOffset, MV_MFLASH_PROG_CHUNK_SIZE, tempBuff)) != MV_OK)
+                return ret;
+        }
+
+		/* overwrite the data to be changed */
+		mvOsMemcpy(tempBuff, pBlock, data2write);
+
+        /* Perform the 64 bytes write based on the mode and verify type */
+        if (main)
+        {
+            if ((ret = mvMFlash64bWr(pFlash, writeOffset, tempBuff, verify)) != MV_OK)
+                return ret;
+        }
+        else
+        {
+            if ((ret = mvMFlash64bInfWr(pFlash, writeOffset, tempBuff, verify)) != MV_OK)
+                return ret;
+        }
+	}
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvMFlashBlockWr - Write a buffer with a custom length and allignment
+*
+* DESCRIPTION:
+*       Program a varient sized block in the Main region of the MFlash.
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		offset: offset within the Information region (limited to 1024)
+*		blockSize: size in bytes of the buffer to be programmed.
+*		pBlock: pointer to the 64 bytes buffer to be programed
+*		verify: bollean flag controlling the compare after program feature
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashBlockWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+                          MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify)
+{
+    /* check for NULL pointers */
+#ifndef CONFIG_MARVELL
+    if(NULL == pBlock)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+#endif
+
+    if (NULL == pFlash)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    return mvMFlashBlockByRegionWr(pFlash, offset, blockSize, pBlock, verify, MV_TRUE /* main region */);
+}
+
+
+/*******************************************************************************
+* mvMFlashInfBlockWr - Write a buffer with a custom length and allignment to 
+*                      the information region of the flash
+*
+* DESCRIPTION:
+*       Program a varient sized block in the Information region of the MFlash.
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		offset: offset within the Information region (limited to 1024)
+*		blockSize: size in bytes of the buffer to be programmed.
+*		pBlock: pointer to the 64 bytes buffer to be programed
+*		verify: bollean flag controlling the compare after program feature
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashInfBlockWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+                             MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify)
+{
+    /* check for NULL pointers */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    return mvMFlashBlockByRegionWr(pFlash, offset, blockSize, pBlock, verify, MV_FALSE /* info region */);
+}
+
+/*******************************************************************************
+* mvMFlashBlockRd - Read a block of Memory from the Main Flash 
+*
+* DESCRIPTION:
+*       Read a block of Memory from the Main Flash region
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		offset: offset to read from the main region of the MFlash
+*		blockSize: number of bytes to read from the offset
+*		pBlock: pointer of the buffer to fill
+*
+* OUTPUT:
+*		pBlock: pointer of the buffer holding the data read from flash.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashBlockRd (MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+                           MV_U32 blockSize, MV_U8 *pBlock)
+{
+    /* check for NULL pointers */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashBlockRd(pFlash, offset, blockSize, pBlock);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashBlockRd(pFlash, offset, blockSize, pBlock);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlashSecErase - Erase the single sector of the main flash region 
+*
+* DESCRIPTION:
+*       Erase one sector of the main flash region
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		secOffset: sector offset within the MFlash
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashBlockInfRd (MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+                              MV_U32 blockSize, MV_U8 *pBlock)
+{
+    /* check for NULL pointers */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashBlockInfRd(pFlash, offset, blockSize, pBlock);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashBlockInfRd(pFlash, offset, blockSize, pBlock);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlashReadConfig - Read the Configuration register
+*
+* DESCRIPTION:
+*       Perform the Read CONFIGx register RAB
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*       regNum: register number to read (1-4 in parallel and 3-4 in spi)
+*		pConfigReg: pointer to read in the configuration register
+*
+* OUTPUT:
+*		pConfigReg: pointer with the data read from the configuration register
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashReadConfig (MV_MFLASH_INFO *pFlash, MV_U32 regNum, MV_U8 * pConfigReg)
+{
+    /* check for NULL pointer */
+    if ((pFlash == NULL) || (pConfigReg == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+    {
+        switch (regNum)
+        {
+            case 1:
+                return mvPMFlashReadConfig1(pFlash, pConfigReg);
+
+            case 2:
+                return mvPMFlashReadConfig2(pFlash, pConfigReg);
+
+            case 3:
+                return mvPMFlashReadConfig3(pFlash, pConfigReg);
+
+            case 4:
+                return mvPMFlashReadConfig4(pFlash, pConfigReg);
+
+            default:
+                DB(mvOsPrintf("%s WARNING: Not supported in parallel mode!!\n", __FUNCTION__);)
+                return MV_NOT_SUPPORTED;
+        }
+    }
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+    {
+        switch (regNum)
+        {
+            case 3:
+                return mvSMFlashReadConfig3(pFlash, pConfigReg);
+
+            case 4:
+                return mvSMFlashReadConfig4(pFlash, pConfigReg);
+
+            default:
+                DB(mvOsPrintf("%s WARNING: Not supported in SPI mode!!\n", __FUNCTION__);)
+                return MV_NOT_SUPPORTED;
+        }
+    }
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlashSetConfig - Write to the Configuration register
+*
+* DESCRIPTION:
+*       Perform the write CONFIGx register RAB
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*       regNum: register number to write (1-4 in parallel and 3-4 in spi)
+*		configReg: Data to write in the configuration register
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashSetConfig	(MV_MFLASH_INFO *pFlash, MV_U32 regNum, MV_U8 configReg)
+{
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+    {
+        switch (regNum)
+        {
+            case 1:
+                return mvPMFlashSetConfig1(pFlash, configReg);
+
+            case 2:
+                return mvPMFlashSetConfig2(pFlash, configReg);
+
+            case 3:
+                return mvPMFlashSetConfig3(pFlash, configReg);
+
+            case 4:
+                return mvPMFlashSetConfig4(pFlash, configReg);
+
+            default:
+                DB(mvOsPrintf("%s WARNING: Not supported in parallel mode!!\n", __FUNCTION__);)
+                return MV_NOT_SUPPORTED;
+        }
+    }
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+    {
+        switch (regNum)
+        {
+            case 3:
+                return mvSMFlashSetConfig3(pFlash, configReg);
+
+            case 4:
+                return mvSMFlashSetConfig4(pFlash, configReg);
+
+            default:
+                DB(mvOsPrintf("%s WARNING: Not supported in SPI mode!!\n", __FUNCTION__);)
+                return MV_NOT_SUPPORTED;
+        }
+    }
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlashSetSlewRate - Set the slew rate for parallel interface
+*
+* DESCRIPTION:
+*       Perform the set slew rate register RAB
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		configReg: Data to write in the slew rate register
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashSetSlewRate (MV_MFLASH_INFO *pFlash, MV_U8 configReg)
+{
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashSetSlewRate(pFlash, configReg);
+
+    DB(mvOsPrintf("%s WARNING: Invalid interface mode!\n", __FUNCTION__);)
+    return MV_BAD_PARAM;
+}   
+
+/*******************************************************************************
+* mvMFlashWriteProtectSet - Set the write protection feature status
+*
+* DESCRIPTION:
+*       Enable or disable the write protection
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		wp: write protection status (enable = MV_TRUE, disable = MVFALSE)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashWriteProtectSet (MV_MFLASH_INFO *pFlash, MV_BOOL wp)
+{
+    MV_U32 reg;
+
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+    
+    /* read, modify then write the register */
+    reg = MV_REG_READ(MV_PMFLASH_IF_CFG_REG);
+    if (wp) /* active low */
+        reg &= ~MV_PMFLASH_WP_PROTECT_MASK;
+    else
+        reg |= MV_PMFLASH_WP_PROTECT_MASK;
+
+    MV_REG_WRITE(MV_PMFLASH_IF_CFG_REG, reg);
+
+    return MV_OK;
+
+#if 0
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashWriteProtectSet(pFlash, wp);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashWriteProtectSet(pFlash, wp);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+#endif
+}
+
+/*******************************************************************************
+* mvMFlashWriteProtectGet - Get the write protection feature status
+*
+* DESCRIPTION:
+*       Retreive the write protection status from the hardware (from the MFlash
+*               controller and not from the flash device configuration register)
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		wp: pointer to the variable to retreive the write protection status in
+*
+* OUTPUT:
+*       None.
+*		wp: pointer to the variable holding the write protection status 
+*           (enable = MV_TRUE, disable = MVFALSE)
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashWriteProtectGet(MV_MFLASH_INFO *pFlash, MV_BOOL * pWp)
+{
+    MV_U32 reg;
+
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+    
+    /* read the register and check the bit status */
+    reg = MV_REG_READ(MV_PMFLASH_IF_CFG_REG);
+    if (reg & MV_PMFLASH_WP_PROTECT_MASK)
+        *pWp = MV_FALSE;
+    else
+        *pWp = MV_TRUE;
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvMFlashSectorSizeSet - Set the sector size
+*
+* DESCRIPTION:
+*       Set the sector size of the MFLASH main region
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		secSize: size of sector in bytes (either 4K or 32K)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashSectorSizeSet (MV_MFLASH_INFO *pFlash, MV_U32 secSize)
+{
+	MV_STATUS ret;
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        ret = mvPMFlashSectorSizeSet(pFlash, secSize);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        ret = mvSMFlashSectorSizeSet(pFlash, secSize);
+    else
+    {
+	    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    	return MV_BAD_PARAM;
+    }
+    
+    if (ret != MV_OK)
+    	return ret;
+    	
+    /* update the sector size and number in the structure */
+    switch (pFlash->flashModel)
+    {
+        case MV_MFLASH_SUNOL_1:
+            if (secSize ==  MV_MFLASH_SECTOR_SIZE_SMALL) 
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL;
+                pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_1;
+            }
+            else 
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG;
+                pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_1;
+            }
+            break;
+
+        case MV_MFLASH_SUNOL_2:
+            if (secSize ==  MV_MFLASH_SECTOR_SIZE_SMALL) 
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL;
+                pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_2;
+            }
+            else 
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG;
+                pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_2;
+            }
+            break;
+
+        case MV_MFLASH_SUNOL_3:
+            if (secSize ==  MV_MFLASH_SECTOR_SIZE_SMALL) 
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL;
+                pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_3;
+            }
+            else 
+            {
+                pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG;
+                pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_3;
+            }
+            break;
+
+        default:
+            mvOsPrintf("%s ERROR: Unknown Flash Type!\n", __FUNCTION__);
+            return MV_NOT_SUPPORTED;
+    }
+    
+    return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvMFlashPrefetchSet - Set the Prefetch mode enable/disable
+*
+* DESCRIPTION:
+*       Enable (MV_TRUE) or Disable (MV_FALSE) the prefetch mode
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*		prefetch: enable/disable (MV_TRUE/MV_FALSE)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashPrefetchSet (MV_MFLASH_INFO *pFlash, MV_BOOL prefetch)
+{
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashPrefetchSet(pFlash, prefetch);
+
+    DB(mvOsPrintf("%s WARNING: Invalid interface mode!\n", __FUNCTION__);)
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlashShutdownSet - Shutdown the voltage regulator in the flash device
+*
+* DESCRIPTION:
+*       Causes the device to enter in a power save mode untill the next access 
+*		to the flash.
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashShutdownSet(MV_MFLASH_INFO *pFlash)
+{
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashShutdownSet(pFlash);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashShutdownSet(pFlash);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlashIdGet - Retreive the MFlash's manufacturer and device IDs
+*
+* DESCRIPTION:
+*       Read from the flash the 32bit manufacturer Id and the 16bit device ID
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*       pManfId: pointer to the 32bit variable to read the manufacturer ID in
+*       pDevId: pointer to the 16bit variable to read the device ID in
+*
+* OUTPUT:
+*       pManfId: pointer to the 32bit variable holding the manufacturer ID
+*       pDevId: pointer to the 16bit variable holding the device ID
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashIdGet (MV_MFLASH_INFO *pFlash, MV_U32 * pManfId, MV_U16 * pDevId)
+{
+    /* check for NULL pointer */
+    if ((pFlash == NULL) || (pManfId == NULL) || (pDevId == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	if (pFlash->ifMode == MV_MFLASH_PARALLEL)
+        return mvPMFlashIdGet(pFlash, pManfId, pDevId);
+    else if (pFlash->ifMode == MV_MFLASH_SPI)
+        return mvSMFlashIdGet(pFlash, pManfId, pDevId);
+
+    mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__);
+    return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvMFlashReset - Reset the flash device and the MFlash glue logic
+*
+* DESCRIPTION:
+*       Perfom a hard reset for the Marvell Flash and the controller interface
+*
+* INPUT:
+*       pFlash: pointer to the MFlash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvMFlashReset(MV_MFLASH_INFO *pFlash)
+{
+	MV_U32 reg;
+
+    /* check for NULL pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* set both bits 4 and 5 */
+	reg = MV_REG_READ(MV_PMFLASH_IF_CFG_REG);
+	reg |= (MV_PMFLASH_RESET_MASK | MV_PMFLASH_IF_RESET_MASK);
+	MV_REG_WRITE(MV_PMFLASH_IF_CFG_REG, reg);
+
+	/* Insert a short delay */
+	mvOsDelay(1);   /* 1ms */
+
+	/* reset both bits 4 and 5 */
+	reg = MV_REG_READ(MV_PMFLASH_IF_CFG_REG);
+	reg &= ~(MV_PMFLASH_RESET_MASK | MV_PMFLASH_IF_RESET_MASK);
+	MV_REG_WRITE(MV_PMFLASH_IF_CFG_REG, reg);
+
+	return MV_OK;
+}
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlash.h b/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlash.h
new file mode 100755
index 0000000..3fdc265
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlash.h
@@ -0,0 +1,141 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvMFlashH
+#define __INCmvMFlashH
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+/* enumerations */
+typedef enum
+{
+    MV_MFLASH_MODEL_UNKNOWN = 0,
+	MV_MFLASH_SUNOL_1 = 1,
+	MV_MFLASH_SUNOL_2 = 2,
+	MV_MFLASH_SUNOL_3 = 3
+} MV_MFLASH_MODEL;
+
+typedef enum
+{
+    MV_MFLASH_SPI,
+    MV_MFLASH_PARALLEL
+} MV_MFLASH_MODE;
+
+/* Type Definitions */
+typedef struct 
+{
+    MV_MFLASH_MODE          ifMode;         /* Interface mode to the MFlash chip */
+    MV_U32					baseAddr;       /* Flash Base Address */
+	MV_MFLASH_MODEL  		flashModel;		/* Marvell flash model enumeration */
+    MV_U32                  sectorSize;     /* Size of each sector in the main region */
+    MV_U32                  sectorNumber;   /* Number of sectors in Main region */
+    MV_U32                  infoSize;       /* Size of the Information region */
+} MV_MFLASH_INFO;
+
+/* Function Prototypes */
+
+/* Init */
+MV_STATUS	mvMFlashInit			(MV_MFLASH_INFO *pFlash);
+
+/* Erase */
+MV_STATUS 	mvMFlashChipErase  	    (MV_MFLASH_INFO *pFlash); /* Erase the whole chip */
+MV_STATUS 	mvMFlashMainErase	  	(MV_MFLASH_INFO *pFlash); /* Erase the whole main region */
+MV_STATUS 	mvMFlashInfErase	  	(MV_MFLASH_INFO *pFlash); /* Erase the whole information region */
+MV_STATUS 	mvMFlashSecErase 		(MV_MFLASH_INFO *pFlash, MV_U32 secNumber); /* Single Main sector erase */
+
+/* write to main and information regions regardless of allignment */
+MV_STATUS	mvMFlashBlockWr 		(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify);
+MV_STATUS	mvMFlashInfBlockWr 	    (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify);
+
+/* read from main and information regions */
+MV_STATUS	mvMFlashBlockRd 		(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock);
+MV_STATUS	mvMFlashBlockInfRd 	    (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock);
+
+/* Configuration registers Read/Write */
+MV_STATUS	mvMFlashReadConfig	    (MV_MFLASH_INFO *pFlash, MV_U32 regNum, MV_U8 * pConfigReg);
+MV_STATUS	mvMFlashSetConfig		(MV_MFLASH_INFO *pFlash, MV_U32 regNum, MV_U8 configReg);
+MV_STATUS	mvMFlashSetSlewRate	    (MV_MFLASH_INFO *pFlash, MV_U8 configReg);
+
+/* write protection */
+MV_STATUS 	mvMFlashWriteProtectSet (MV_MFLASH_INFO *pFlash, MV_BOOL wp);
+MV_STATUS 	mvMFlashWriteProtectGet (MV_MFLASH_INFO *pFlash, MV_BOOL * pWp);
+
+/* Set the Sector Size option */
+MV_STATUS 	mvMFlashSectorSizeSet	(MV_MFLASH_INFO *pFlash, MV_U32 secSize);
+
+/* Prefetch Operation Set */
+MV_STATUS	mvMFlashPrefetchSet     (MV_MFLASH_INFO *pFlash, MV_BOOL prefetch);
+
+/* Shutdown/operate (true/false) the device */
+MV_STATUS 	mvMFlashShutdownSet     (MV_MFLASH_INFO *pFlash);
+
+/* Retreive the Flash ID */
+MV_STATUS	mvMFlashIdGet			(MV_MFLASH_INFO *pFlash, MV_U32 * pManfId, MV_U16 * pDevId);
+
+/* Peform a hard reset to the MFlash and Interface glue */
+MV_STATUS	mvMFlashReset			(MV_MFLASH_INFO *pFlash);
+
+#endif /* __INCmvPMFlashH */
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlashSpec.h b/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlashSpec.h
new file mode 100755
index 0000000..de4ea9c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvMFlashSpec.h
@@ -0,0 +1,103 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvMFlashSpecH
+#define __INCmvMFlashSpecH
+
+/* Information and Main region sizes per sunol model */
+#define		MV_MFLASH_INF_MEM_SZ_SUNOL_1	    0x400		/* 1Kbyte */
+#define		MV_MFLASH_INF_MEM_SZ_SUNOL_2_3		0x800		/* 2Kbyte */
+#define		MV_MFLASH_MAIN_MEM_SZ_SUNOL_1		0x30000	    /* 192 Kbyte */
+#define		MV_MFLASH_MAIN_MEM_SZ_SUNOL_2		0x40000	    /* 256 KByte */
+#define		MV_MFLASH_MAIN_MEM_SZ_SUNOL_3		0x60000	    /* 384 KByte */
+
+/* maunfacturer and Device IDs */
+#define     MV_MFLASH_MANUFACTURER_ID           0x7F7F7FE9  /* Marvell Semiconductors Manufacturer ID */
+#define     MV_MFLASH_DEVICE_ID_SUNOL_1         0x0290      /* LS nibble is the revision */
+#define     MV_MFLASH_DEVICE_ID_SUNOL_2         0x02A0      /* LS nibble is the revision */
+#define     MV_MFLASH_DEVICE_ID_SUNOL_3         0x02D0      /* LS nibble is the revision */
+#define     MV_MFLASH_DEVICE_ID_MASK            0xFFF0      /* mask for the device ID */
+#define     MV_MFLASH_DEVICE_ID_REV_MASK        0x000F      /* revision part of the device ID */
+
+/* SUNOL sector Sizes */
+#define     MV_MFLASH_SECTOR_SIZE_SMALL         0x1000		/* 4KByte */
+#define     MV_MFLASH_SECTOR_SIZE_BIG	        0x8000		/* 32KByte */
+
+/* SUNOL sectors number */
+#define     MV_MFLASH_SMALL_SEC_NUM_SUNOL_1     (MV_MFLASH_MAIN_MEM_SZ_SUNOL_1 / MV_MFLASH_SECTOR_SIZE_SMALL) /* 48 */
+#define     MV_MFLASH_SMALL_SEC_NUM_SUNOL_2     (MV_MFLASH_MAIN_MEM_SZ_SUNOL_2 / MV_MFLASH_SECTOR_SIZE_SMALL) /* 64 */
+#define     MV_MFLASH_SMALL_SEC_NUM_SUNOL_3     (MV_MFLASH_MAIN_MEM_SZ_SUNOL_3 / MV_MFLASH_SECTOR_SIZE_SMALL) /* 96 */
+#define     MV_MFLASH_BIG_SEC_NUM_SUNOL_1       (MV_MFLASH_MAIN_MEM_SZ_SUNOL_1 / MV_MFLASH_SECTOR_SIZE_BIG) /* 6 */
+#define     MV_MFLASH_BIG_SEC_NUM_SUNOL_2       (MV_MFLASH_MAIN_MEM_SZ_SUNOL_2 / MV_MFLASH_SECTOR_SIZE_BIG) /* 8 */
+#define     MV_MFLASH_BIG_SEC_NUM_SUNOL_3       (MV_MFLASH_MAIN_MEM_SZ_SUNOL_3 / MV_MFLASH_SECTOR_SIZE_BIG) /* 12 */
+
+/* Loops Timeouts */
+#define		MV_MFLASH_MAX_CMD_DONE_LOOP	        1000000 /* max poll times to wait for the comamnd done */
+#define		MV_MFLASH_MAX_PRG_LOOP				1000000 /* max poll times to wait for programming to be completed */
+
+/* Page allignment and Mask */
+#define		MV_MFLASH_PROG_ALIGN_MASK			0x3f	/* PROG should be alligned to 64 bytes */
+#define		MV_MFLASH_PROG_CHUNK_SIZE			(MV_MFLASH_PROG_ALIGN_MASK + 1)
+
+#endif /* __INCmvMFlashSpecH */
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlash.c b/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlash.c
new file mode 100755
index 0000000..c795161
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlash.c
@@ -0,0 +1,1426 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+ 
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include "mflash/mvMFlash.h"
+#include "mflash/mvMFlashSpec.h"
+#include "mflash/mvPMFlash.h"
+#include "mflash/mvPMFlashSpec.h"
+#include "ctrlEnv/mvCtrlEnvLib.h" 
+
+/*#define MV_DEBUG*/
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+/* MACROS */
+
+/* Static Functions */
+static MV_STATUS waitOnCmdDone              (MV_VOID);
+static MV_STATUS waitOnEraseBitClear        (MV_VOID);
+static MV_STATUS waitOnInfReadBitClear      (MV_VOID);
+static MV_STATUS mvPMFlashReadSR            (MV_U8 * pStatusReg);
+static MV_STATUS mvPMFlashReadRegSeq        (MV_U32 prgCmnd, MV_U8 * pStatusReg);
+static MV_STATUS mvPMFlashWriteRegSeq       (MV_U32 prgCmnd, MV_U32 reg);
+static MV_STATUS mvPMFlashProgSeq           (MV_MFLASH_INFO *pFlash, MV_U32 prgCmnd, MV_U32 offset, MV_U8 *pBlock);
+static MV_STATUS mvPMFlashEraseSeq          (MV_MFLASH_INFO *pFlash, MV_U32 eraseCmnd);
+static MV_STATUS mvPMFlashIndirectReadSeq   (MV_MFLASH_INFO *pFlash, MV_U32 readCmnd, MV_U8* p8Bytes);
+
+/*******************************************************************************
+* waitOnCmdDone - Wait for command done bit
+*
+* DESCRIPTION:
+*       Block waiting for command done. Returns Error Status
+*
+********************************************************************************/
+static MV_STATUS waitOnCmdDone(MV_VOID)
+{
+	MV_U32 i;
+	/* loop over waiting for the command done bit to be set */
+	for (i=0; i<MV_MFLASH_MAX_CMD_DONE_LOOP; i++)
+		if (MV_REG_READ(MV_PMFLASH_IF_STATUS_REG) & MV_PMFLASH_CMD_DONE_MASK)
+			return MV_OK;
+
+    DB(mvOsPrintf("%s WARNING: Command Timeout!\n", __FUNCTION__);)
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* waitOnEraseBitClear - Wait for erase bit to be cleared by H/W
+*
+* DESCRIPTION:
+*       Block waiting for erase bit (bit13 in Flash command opcode register)
+*		to be cleared by hardware as an indication that the command was accepted.
+*
+********************************************************************************/
+static MV_STATUS waitOnEraseBitClear(MV_VOID)
+{
+	MV_U32 i;
+	/* loop over waiting for the command done bit to be set */
+	for (i=0; i<MV_MFLASH_MAX_CMD_DONE_LOOP; i++)
+		if ((MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG) & MV_PMFLASH_ERASE_STRT_MASK) == 0)
+			return MV_OK;
+
+    DB(mvOsPrintf("%s WARNING: Command Timeout!\n", __FUNCTION__);)
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* waitOnRdStatusBitClear - Wait for Read status bit to be cleared by H/W
+*
+* DESCRIPTION:
+*       Block waiting for Read bit (bit14 in Flash command opcode register)
+*		to be cleared by hardware as an indication that the command was executed.
+*
+********************************************************************************/
+static MV_STATUS waitOnRdStatusBitClear(MV_VOID)
+{
+	MV_U32 i;
+	/* loop over waiting for the command done bit to be set */
+	for (i=0; i<MV_MFLASH_MAX_CMD_DONE_LOOP; i++)
+		if ((MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG) & MV_PMFLASH_RDSR_SET_MASK) == 0)
+			return MV_OK;
+
+    DB(mvOsPrintf("%s WARNING: Command Timeout!\n", __FUNCTION__);)
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* waitOnInfReadBitClear - Wait for Information Read bit to be cleared by H/W
+*
+* DESCRIPTION:
+*       Block waiting for IREAD (bit15 in Flash command opcode register)
+*		to be cleared by hardware as an indication that the requested 8bytes
+*		are ready to be ready by s/w.
+*
+********************************************************************************/
+static MV_STATUS waitOnInfReadBitClear(MV_VOID)
+{
+	MV_U32 i;
+	/* loop over waiting for the command done bit to be set */
+	for (i=0; i<MV_MFLASH_MAX_CMD_DONE_LOOP; i++)
+		if ((MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG) & MV_PMFLASH_INF_READ_STRT_MASK) == 0)
+			return MV_OK;
+
+    DB(mvOsPrintf("%s WARNING: Command Timeout!\n", __FUNCTION__);)
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* mvPMFlashReadRegSeq - Read internal register of the MFLASH
+*
+* DESCRIPTION:
+*       Perform the Read internal register RAB
+*
+********************************************************************************/
+static MV_STATUS mvPMFlashReadRegSeq(MV_U32 prgCmnd, MV_U8 * pStatusReg)
+{	
+	MV_U32 temp;
+    MV_STATUS ret;
+
+	/* set commnand opcode = RDSR */
+	temp = MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG);
+	temp = ((temp & ~MV_PMFLASH_CMD_OPCD_MASK) | prgCmnd | MV_PMFLASH_EAD9_8_MASK);
+	MV_REG_WRITE(MV_PMFLASH_CMD_OPCODE_REG, temp);
+
+	/* trigger the operation */
+	MV_REG_BIT_SET(MV_PMFLASH_CMD_OPCODE_REG, MV_PMFLASH_RDSR_SET_MASK);	
+
+	/* wait on the read status bit to be cleared */
+	if ((ret = waitOnRdStatusBitClear()) != MV_OK)
+		return ret;
+
+	/* wait for command done bit - this is supposed to be immediate */
+	if ((ret = waitOnCmdDone()) != MV_OK)
+		return ret;
+
+	/* read the satus register */
+	*pStatusReg = (MV_REG_READ(MV_PMFLASH_STATUS_REG) & MV_PMFLASH_STATUS_MASK);
+	
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlashWriteRegSeq - Write internal register of the MFLASH
+*
+* DESCRIPTION:
+*       Perform the write internal register RAB
+*
+********************************************************************************/
+static MV_STATUS mvPMFlashWriteRegSeq(MV_U32 prgCmnd, MV_U32 reg)
+{	
+    MV_STATUS ret;
+	MV_U32 temp;
+
+	/* set data to be written in the address low register */
+	MV_REG_WRITE(MV_PMFLASH_ADDR_LOW_REG, (reg & 0xFFFF));
+
+	/* set commnand opcode = prgCmnd */
+	temp = MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG);
+	temp = ((temp & ~MV_PMFLASH_CMD_OPCD_MASK) | prgCmnd | MV_PMFLASH_EAD9_8_MASK);
+	MV_REG_WRITE(MV_PMFLASH_CMD_OPCODE_REG, temp);
+
+	/* trigger the operation */
+	MV_REG_BIT_SET(MV_PMFLASH_CMD_OPCODE_REG, MV_PMFLASH_ERASE_STRT_MASK);	
+
+	/* wait for erase bit to be cleared */
+	if ((ret = waitOnEraseBitClear()) != MV_OK)
+		return ret;
+	
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlashReadSR - Read the Status register
+*
+* DESCRIPTION:
+*       Perform the Read status register RAB
+*
+********************************************************************************/
+static MV_STATUS mvPMFlashReadSR(MV_U8 * pStatusReg)
+{	
+	return mvPMFlashReadRegSeq(MV_PMFLASH_OPCD_RDSR, pStatusReg);
+}
+
+/*******************************************************************************
+* mvPMFlashProgSeq - Perform the program sequence for the MFLASH
+*
+* DESCRIPTION:
+*       program a 64 byte block (with or without compare after program) on 
+*		both the main and information regions of the flash.
+*
+********************************************************************************/
+static MV_STATUS mvPMFlashProgSeq(MV_MFLASH_INFO *pFlash, MV_U32 prgCmnd, MV_U32 offset, 
+                                  MV_U8 *pBlock)
+{
+	MV_U32 i;
+	MV_U16 * pBuff;
+	MV_U8 status;
+	MV_U32 temp;
+    MV_STATUS ret;
+
+	/* check that the programming offset is alligned according to requirement */
+	if (offset & MV_MFLASH_PROG_ALIGN_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Programming allignment problem!\n", __FUNCTION__);)
+		return MV_NOT_ALIGNED;
+    }
+
+	/* Set the flash address low */
+	MV_REG_WRITE(MV_PMFLASH_ADDR_LOW_REG, (offset & 0xFFFF));
+
+	/* set the flash address high */
+	MV_REG_WRITE(MV_PMFLASH_ADDR_HI_REG, ((offset >> 16) & 0xFFFF));
+
+	/* set commnand opcode = prgCmnd */
+	temp = MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG);
+	temp = ((temp & ~MV_PMFLASH_CMD_OPCD_MASK) | prgCmnd | MV_PMFLASH_EAD9_8_MASK);
+	MV_REG_WRITE(MV_PMFLASH_CMD_OPCODE_REG, temp);
+
+	/* start the programming operation - set bit 12 to 1 */
+	MV_REG_BIT_SET(MV_PMFLASH_CMD_OPCODE_REG, MV_PMFLASH_WR_OPER_STRT_MASK);	
+
+	/* serialize the whole 64 byte buffer */
+	pBuff = (MV_U16*)pBlock;
+	for (i=0; i<MV_PMFLASH_PROG_WORDS_PER_CHUNK; i++)
+	{
+		MV_REG_WRITE(MV_PMFLASH_DATA_REG, MV_16BIT_LE(*pBuff));
+		pBuff++;
+	}
+
+	/* stop the programming operation - set bit 12 to 0 */
+	MV_REG_BIT_RESET(MV_PMFLASH_CMD_OPCODE_REG, MV_PMFLASH_WR_OPER_STRT_MASK);	
+
+	for (i=0; i<MV_MFLASH_MAX_PRG_LOOP; i++)
+	{
+		if ((ret = mvPMFlashReadSR(&status)) != MV_OK)
+			return ret;
+
+		/* check the WIP bit if cleared (indicating end of programming) */
+		if ((status & MV_PMFLASH_STAT_WIP_MASK) == 0)
+			return MV_OK;
+	}
+
+    DB(mvOsPrintf("%s WARNING: Command Timeout!\n", __FUNCTION__);)
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* mvPMFlashEraseSeq - Perform the erase sequence for the MFLASH
+*
+* DESCRIPTION:
+*       Erase a complete region in the MFlash (Main, Information or the 
+*		whole flash).
+*
+********************************************************************************/
+static MV_STATUS mvPMFlashEraseSeq(MV_MFLASH_INFO *pFlash, MV_U32 eraseCmnd)
+{
+	MV_U32 i;
+	MV_U8 status;
+	MV_U32 temp;
+    MV_STATUS ret;
+
+	/* set commnand opcode = prgCmnd */
+	temp = MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG);
+	temp = ((temp & ~MV_PMFLASH_CMD_OPCD_MASK) | eraseCmnd | MV_PMFLASH_EAD9_8_MASK);
+	MV_REG_WRITE(MV_PMFLASH_CMD_OPCODE_REG, temp);
+
+	/* Trigger the erase operation - set bit 13 to 1 */
+	MV_REG_BIT_SET(MV_PMFLASH_CMD_OPCODE_REG, MV_PMFLASH_ERASE_STRT_MASK);	
+
+	/* wait for the command to be sent to the device */
+	if ((ret = waitOnEraseBitClear()) != MV_OK)
+		return ret;
+
+	/* wait for the erase command to be completed */
+	for (i=0; i<MV_MFLASH_MAX_PRG_LOOP; i++)
+	{
+		/* read the Status register */
+		if ((ret = mvPMFlashReadSR(&status)) != MV_OK)
+			return ret;
+
+		/* check the WIP bit if cleared (indicating end of programming) */
+		if ((status & MV_PMFLASH_STAT_WIP_MASK) == 0)
+			return MV_OK;
+	}
+
+    DB(mvOsPrintf("%s WARNING: Command Timeout!\n", __FUNCTION__);)
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* mvPMFlashIndirectReadSeq - Perform the Information READ sequence
+*
+* DESCRIPTION:
+*       Read indirectly from the FLASH information region
+*
+********************************************************************************/
+static MV_STATUS mvPMFlashIndirectReadSeq(MV_MFLASH_INFO *pFlash, MV_U32 readCmnd, MV_U8* p8Bytes)
+{
+	MV_U32 i;
+	MV_U16 * dataPrt = (MV_U16*)p8Bytes;
+	MV_U32 temp;
+    MV_STATUS ret;
+
+	/* set commnand opcode = prgCmnd */
+	temp = MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG);
+	temp = ((temp & ~MV_PMFLASH_CMD_OPCD_MASK) | readCmnd | MV_PMFLASH_EAD9_8_MASK);
+	MV_REG_WRITE(MV_PMFLASH_CMD_OPCODE_REG, temp);
+
+	/* Trigger the erase operation - set bit 13 to 1 */
+	MV_REG_BIT_SET(MV_PMFLASH_CMD_OPCODE_REG, MV_PMFLASH_INF_READ_STRT_MASK);
+	
+	/* block waiting for bit to be cleared by hardware */
+	if ((ret = waitOnInfReadBitClear()) != MV_OK)
+		return ret;
+
+	/* read the 8bytes from the Data register into the buffer in 4 iterations */
+	for (i=0; i<4; i++)
+	{
+		*dataPrt = MV_REG_READ(MV_PMFLASH_DATA_REG);
+		dataPrt++;
+	}
+
+	return MV_OK;
+}
+
+/*
+#####################################################################################
+#####################################################################################
+*/
+
+/*******************************************************************************
+* mvPMFlashInit - Perform basic initialize for the MFlash device in paralle mode
+*
+* DESCRIPTION:
+*       This function performs the necessary initialization for a Marvell 
+*       Sunol flash.
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashInit (MV_MFLASH_INFO *pFlash)
+{
+    MV_STATUS ret;
+
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* set the static timing parameters */
+	if ((ret = mvPMFlashSetConfig1(pFlash, ((MV_PMFLASH_T2 << 4) | MV_PMFLASH_T1))) != MV_OK)
+        return ret;
+
+	if ((ret = mvPMFlashSetConfig3(pFlash, MV_PMFLASH_T7)) != MV_OK)
+        return ret;
+
+	if ((ret = mvPMFlashSetSlewRate(pFlash, ((MV_PMFLASH_PCLK_OUT << 4) | 
+		                         (MV_PMFLASH_SLEW_2_3 << 2) | 
+						          MV_PMFLASH_SLEW_0_1))) != MV_OK)
+        return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlash64bWr - Program (no Verify) main flash data
+*
+* DESCRIPTION:
+*       Program an alligned 64byte block in the main flash region of the MFlash
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		offset: offset within the Information region (limited to 1024)
+*		pBlock: pointer to the 64 bytes buffer to be programed
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlash64bWr (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock)
+{
+    /* Check for null pointer */
+#ifndef CONFIG_MARVELL
+    if(NULL == pBlock)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+#endif
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashProgSeq(pFlash, MV_PMFLASH_OPCD_PROGRAM, offset, pBlock);
+}
+
+/*******************************************************************************
+* mvPMFlash64bWrVerify - Program and Verify Main flash data
+*
+* DESCRIPTION:
+*       Program and Verify a 64byte alligned block in the main region of the 
+*       MFlash
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		offset: offset within the main region
+*		pBlock: pointer to the 64 bytes buffer to be programed
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlash64bWrVerify (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock)
+{
+    MV_STATUS ret;
+    MV_U8 status;
+
+    /* Check for null pointer */
+#ifndef CONFIG_MARVELL
+    if(NULL == pBlock)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+#endif
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    /* Perform the program sequence */
+	if ((ret = mvPMFlashProgSeq(pFlash, MV_PMFLASH_OPCD_PRG_CMP, offset, pBlock)) != MV_OK)
+        return ret;
+
+    /* Read the status register */
+	if ((ret = mvPMFlashReadSR(&status)) != MV_OK)
+		return ret;
+
+	/* check the result of the compare operartion */
+	if (status & MV_PMFLASH_STAT_CMP_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Compare after write Failed!\n", __FUNCTION__);)
+		return MV_FAIL;
+    }
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlash64bInfWr - Program (no Verify) Information data
+*
+* DESCRIPTION:
+*       Program a 64byte alligned block in the information region of the 
+*       MFlash - Offset is limited to 1024
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		offset: offset within the Information region (limited to 1024)
+*		pBlock: pointer to the 64 bytes buffer to be programed
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlash64bInfWr (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock)
+{
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashProgSeq(pFlash, MV_PMFLASH_OPCD_IPROGRAM, offset, pBlock);
+}
+
+/*******************************************************************************
+* mvPMFlash64bInfWrVerify - Program and Verify Information data
+*
+* DESCRIPTION:
+*       Program and Verify a 64byte alligned block in the information region 
+*       of the MFlash - Offset is limited to 1024
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		offset: offset within the Information region (limited to 1024)
+*		pBlock: pointer to the 64 bytes buffer to be programed
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlash64bInfWrVerify (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock)
+{
+	MV_STATUS ret;
+    MV_U8 status;
+
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+    /* Perform the program sequence */
+	if ((ret = mvPMFlashProgSeq(pFlash, MV_PMFLASH_OPCD_IPRG_CMP, offset, pBlock)) != MV_OK)
+        return ret;
+
+    /* Read the status register */
+	if ((ret = mvPMFlashReadSR(&status)) != MV_OK)
+		return ret;
+
+	/* check the result of the compare operartion */
+	if (status & MV_PMFLASH_STAT_CMP_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Compare after write Failed!\n", __FUNCTION__);)
+		return MV_FAIL;
+    }
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlashChipErase - Erase the whole flash
+*
+* DESCRIPTION:
+*       Erase the whole flash (both the Main and Information region).
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashChipErase (MV_MFLASH_INFO *pFlash)
+{
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashEraseSeq(pFlash, MV_PMFLASH_OPCD_CHIP_ERASE);
+}
+
+/*******************************************************************************
+* mvPMFlashMainErase - Erase the main flash region only
+*
+* DESCRIPTION:
+*       Erase the Main flash region only. The information region will not be
+*       affected.
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashMainErase (MV_MFLASH_INFO *pFlash)
+{
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashEraseSeq(pFlash, MV_PMFLASH_OPCD_MAIN_ERASE);
+}
+
+/*******************************************************************************
+* mvPMFlashInfErase - Erase the information flash region only
+*
+* DESCRIPTION:
+*       Erase the information flash region. The main flash region will not be
+*       affected.
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashInfErase (MV_MFLASH_INFO *pFlash)
+{
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashEraseSeq(pFlash, MV_PMFLASH_OPCD_IPAGE_ERASE);
+}
+
+
+/*******************************************************************************
+* mvPMFlashSecErase - Erase the single sector of the main flash region 
+*
+* DESCRIPTION:
+*       Erase one sector of the main flash region
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		secNumber: sector number to erase
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashSecErase (MV_MFLASH_INFO *pFlash, MV_U32 secNumber)
+{
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* set the sector address in the flash address low */
+	MV_REG_WRITE(MV_PMFLASH_ADDR_LOW_REG, (secNumber & 0xFFFF));
+
+	/* Perform the erase sequence*/
+	return mvPMFlashEraseSeq(pFlash, MV_PMFLASH_OPCD_PAGE_ERASE);
+}
+
+
+/*******************************************************************************
+* mvPMFlashBlockRd - Read a block of Memory from the Main Flash 
+*
+* DESCRIPTION:
+*       Read a block of Memory from the Main Flash 
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		offset: offset to read from the main region of the MFlash
+*		blockSize: number of bytes to read from the offset
+*
+* OUTPUT:
+*		pBlock: pointer of the buffer to fill
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashBlockRd (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, 
+                            MV_U8 *pBlock)
+{
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* check that requested data is in the region */
+    if ((offset + blockSize) > (pFlash->sectorNumber * pFlash->sectorSize))
+    {
+        DB(mvOsPrintf("%s WARNING: Read allignment problem!\n", __FUNCTION__);)
+        return MV_BAD_PARAM;
+    }
+	
+    /* Read using direct access */
+	mvOsMemcpy(pBlock, (MV_VOID*)(pFlash->baseAddr + offset), blockSize);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlashBlockInfRd - Read a block of Memory from the Information region 
+*
+* DESCRIPTION:
+*       Read a block of Memory from the information region
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		offset: offset to read from the main region of the MFlash
+*		blockSize: number of bytes to read from the offset
+*
+* OUTPUT:
+*		pBlock: pointer of the buffer to fill
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashBlockInfRd (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, 
+                               MV_U8 *pBlock)
+{
+    MV_STATUS ret;
+	MV_U8 tempBuff[MV_PMFLASH_IREAD_CHUNK_SIZE];
+	MV_U32 data2read	= blockSize;
+	MV_U32 preAllOfst	= (offset & MV_PMFLASH_IREAD_ALIGN_MASK);
+    MV_U32 preAllSz		= (preAllOfst ? (MV_PMFLASH_IREAD_CHUNK_SIZE - preAllOfst) : 0);	
+	MV_U32 readOffset	= (offset & ~MV_PMFLASH_IREAD_ALIGN_MASK);
+
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* sanity check on sizes and offsets based on chip model */
+    if ((offset + blockSize) > pFlash->infoSize)
+    {
+        DB(mvOsPrintf("%s WARNING: Read exceeds flash size!\n", __FUNCTION__);)
+        return MV_BAD_PARAM;
+    }
+
+	/* set the ADDDRESS HI to zero - since only the low address is needed */
+	MV_REG_WRITE(MV_PMFLASH_ADDR_HI_REG, 0); /* only low address is needed */
+
+	/* check if the total block size is less than the first chunk remainder */
+	if (data2read < preAllSz)
+		preAllSz = data2read;
+
+	/* Check if read offset is not alligned to 8bytes; then perform a read alligned 
+	   to 8 bytes and copy only the necessary data */
+	if (preAllOfst)
+	{
+		/* set the read offset address in the flash address Low */
+		MV_REG_WRITE(MV_PMFLASH_ADDR_LOW_REG, readOffset);
+		if ((ret = mvPMFlashIndirectReadSeq(pFlash, MV_PMFLASH_OPCD_IREAD, tempBuff)) != MV_OK)
+			return ret;
+
+		/* copy to the buffer only the needed data */
+		mvOsMemcpy (pBlock, &tempBuff[preAllOfst], preAllSz);
+
+		/* increment the pointers and offsets */
+		data2read -= preAllSz;
+		readOffset += MV_PMFLASH_IREAD_CHUNK_SIZE;
+		pBlock += preAllSz;
+	}
+
+	/* perform all reads that are alligned to 8bytes and full 8bytes */
+	while (data2read >= MV_PMFLASH_IREAD_CHUNK_SIZE)
+	{
+		/* set the read offset address in the flash address Low */
+		MV_REG_WRITE(MV_PMFLASH_ADDR_LOW_REG, readOffset);
+		if ((ret = mvPMFlashIndirectReadSeq(pFlash, MV_PMFLASH_OPCD_IREAD, pBlock)) != MV_OK)
+			return ret;
+
+		/* increment the pointers and offsets */
+		data2read -= MV_PMFLASH_IREAD_CHUNK_SIZE;
+		readOffset += MV_PMFLASH_IREAD_CHUNK_SIZE;
+		pBlock += MV_PMFLASH_IREAD_CHUNK_SIZE;
+	}
+	
+	/* check if we need to perform a partial read at the end */
+	if (data2read)
+	{
+		/* set the read offset address in the flash address Low */
+		MV_REG_WRITE(MV_PMFLASH_ADDR_LOW_REG, readOffset);
+		if ((ret = mvPMFlashIndirectReadSeq(pFlash, MV_PMFLASH_OPCD_IREAD, tempBuff)) != MV_OK)
+			return ret;
+		
+		/* copy to the buffer only the needed data */
+		mvOsMemcpy (pBlock, tempBuff, data2read);
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlashReadConfig1 - Read the Configuration register
+*
+* DESCRIPTION:
+*       Perform the Read CONFIG1 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		pConfigReg: pointer to the variable to fill
+*
+* OUTPUT:
+*       pConfigReg: pointer to the variable holding the register value
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashReadConfig1(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg)
+{	
+    if ((pFlash == NULL) || (pConfigReg == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashReadRegSeq(MV_PMFLASH_OPCD_READ_CFG1, pConfigReg);
+}
+
+/*******************************************************************************
+* mvPMFlashReadConfig2 - Read the Configuration register
+*
+* DESCRIPTION:
+*       Perform the Read CONFIG2 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		pConfigReg: pointer to the variable to fill
+*
+* OUTPUT:
+*       pConfigReg: pointer to the variable holding the register value
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashReadConfig2(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg)
+{	
+	if ((pFlash == NULL) || (pConfigReg == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashReadRegSeq(MV_PMFLASH_OPCD_READ_CFG2, pConfigReg);
+}
+
+/*******************************************************************************
+* mvPMFlashReadConfig3 - Read the Configuration register
+*
+* DESCRIPTION:
+*       Perform the Read CONFIG3 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		pConfigReg: pointer to the variable to fill
+*
+* OUTPUT:
+*       pConfigReg: pointer to the variable holding the register value
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashReadConfig3(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg)
+{	
+	if ((pFlash == NULL) || (pConfigReg == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashReadRegSeq(MV_PMFLASH_OPCD_READ_CFG3, pConfigReg);
+}
+
+/*******************************************************************************
+* mvPMFlashReadConfig4 - Read the Configuration register
+*
+* DESCRIPTION:
+*       Perform the Read CONFIG4 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		pConfigReg: pointer to the variable to fill
+*
+* OUTPUT:
+*       pConfigReg: pointer to the variable holding the register value
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashReadConfig4(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg)
+{	
+	if ((pFlash == NULL) || (pConfigReg == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashReadRegSeq(MV_PMFLASH_OPCD_READ_CFG4, pConfigReg);
+}
+
+/*******************************************************************************
+* mvPMFlashSetConfig1 - Write the Configuration register
+*
+* DESCRIPTION:
+*       Perform the SET CONFIG1 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		configReg: value to set in the configuration register
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashSetConfig1(MV_MFLASH_INFO *pFlash, MV_U8 configReg)
+{	
+	if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashWriteRegSeq(MV_PMFLASH_OPCD_SET_CFG1, configReg);
+}
+
+/*******************************************************************************
+* mvPMFlashSetConfig2 - Write the Configuration register
+*
+* DESCRIPTION:
+*       Perform the SET CONFIG2 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		configReg: value to set in the configuration register
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashSetConfig2(MV_MFLASH_INFO *pFlash, MV_U8 configReg)
+{	
+	if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashWriteRegSeq(MV_PMFLASH_OPCD_SET_CFG2, configReg);
+}
+
+/*******************************************************************************
+* mvPMFlashSetConfig3 - Write the Configuration register
+*
+* DESCRIPTION:
+*       Perform the SET CONFIG3 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		configReg: value to set in the configuration register
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashSetConfig3(MV_MFLASH_INFO *pFlash, MV_U8 configReg)
+{	
+	if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashWriteRegSeq(MV_PMFLASH_OPCD_SET_CFG3, configReg);
+}
+
+/*******************************************************************************
+* mvPMFlashSetConfig4 - Write the Configuration register
+*
+* DESCRIPTION:
+*       Perform the SET CONFIG4 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		configReg: value to set in the configuration register
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashSetConfig4(MV_MFLASH_INFO *pFlash, MV_U8 configReg)
+{	
+	if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashWriteRegSeq(MV_PMFLASH_OPCD_SET_CFG4, configReg);
+}
+/*******************************************************************************
+* mvPMFlashSetConfig4 - Write the Configuration register
+*
+* DESCRIPTION:
+*       Perform the SET CONFIG4 register RAB
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		configReg: value to set in the configuration register
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+********************************************************************************/
+MV_STATUS mvPMFlashSetSlewRate (MV_MFLASH_INFO *pFlash, MV_U8 configReg)
+{
+	if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashWriteRegSeq(MV_PMFLASH_OPCD_SET_SLEW, configReg);
+}
+
+/*******************************************************************************
+* mvPMFlashWriteProtectSet - Set the write protection feature status
+*
+* DESCRIPTION:
+*       Enable or disable the write protection
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		wp: write protection status (enable = MV_TRUE, disable = MVFALSE)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashWriteProtectSet (MV_MFLASH_INFO *pFlash, MV_BOOL wp)
+{
+    MV_STATUS ret;
+	MV_U8 tempReg;
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;	
+    }
+
+	/* Read the original value */
+	if ((ret = mvPMFlashReadConfig4(pFlash, &tempReg)) != MV_OK)
+    {
+        DB(mvOsPrintf("%s WARNING: Failed to read Config register!\n", __FUNCTION__);)
+		return ret;
+    }
+
+	/* set the WP bit */
+	if (wp) /* write protect active hi */
+		tempReg |= MV_PMFLASH_CFG4_WP_MASK;
+	else
+		tempReg &= ~MV_PMFLASH_CFG4_WP_MASK;
+
+	/* write the new register value */
+	if ((ret = mvPMFlashSetConfig4(pFlash, tempReg)) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlashWriteProtectGet - Get the write protection feature status
+*
+* DESCRIPTION:
+*       Read from the h/w the write protection status
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		pWp: pointer to the variable to read in the write protection status
+*
+* OUTPUT:
+*		pWp: pointer to the variable holding the write protection status
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashWriteProtectGet(MV_MFLASH_INFO *pFlash, MV_BOOL * pWp)
+{
+    MV_STATUS ret;
+	MV_U8 tempReg;
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;	
+    }
+
+	/* Read the original value */
+	if ((ret = mvPMFlashReadConfig4(pFlash, &tempReg)) != MV_OK)
+    {
+        DB(mvOsPrintf("%s WARNING: Failed to read Config register!\n", __FUNCTION__);)
+		return ret;
+    }
+
+	/* Read the WP bit */
+	if (tempReg &= ~MV_PMFLASH_CFG4_WP_MASK)
+        *pWp = MV_TRUE;
+    else
+        *pWp = MV_FALSE;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlashSectorSizeSet - Set the sector size (4K or 32K)
+*
+* DESCRIPTION:
+*       Set the sector size of the MFLASH main region
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		secSize: size of sector in bytes (either 4K or 32K)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashSectorSizeSet (MV_MFLASH_INFO *pFlash, MV_U32 secSize)
+{
+    MV_STATUS ret;
+	MV_U8 tempReg;
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;	
+    }
+
+	/* Read the original value */
+	if ((ret = mvPMFlashReadConfig4(pFlash, &tempReg)) != MV_OK)
+		return ret;
+
+	/* set the sector size bit */
+	switch (secSize)
+	{
+		case MV_MFLASH_SECTOR_SIZE_SMALL:
+			tempReg |= MV_PMFLASH_CFG4_PG_SZ_MASK;		/* 1 - 4K */
+			break;
+
+		case MV_MFLASH_SECTOR_SIZE_BIG:
+			tempReg &= ~MV_PMFLASH_CFG4_PG_SZ_MASK;		/* 0 - 32K */
+			break;
+
+		default:
+            DB(mvOsPrintf("%s WARNING: Invalid parameter sector size!\n", __FUNCTION__);)
+			return MV_BAD_PARAM;
+	}
+
+	/* write the new register value */
+	if ((ret = mvPMFlashSetConfig4(pFlash, tempReg)) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvPMFlashPrefetchSet - Set the Prefetch mode enable/disable
+*
+* DESCRIPTION:
+*       Enable (MV_TRUE) or Disable (MV_FALSE) the prefetch mode
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*		prefetch: enable/disable (true/false)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashPrefetchSet (MV_MFLASH_INFO *pFlash, MV_BOOL prefetch)
+{
+    MV_STATUS ret;
+	MV_U8 tempReg;
+
+	if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* Read the original value */
+	if ((ret = mvPMFlashReadConfig2(pFlash, &tempReg)) != MV_OK)
+		return ret;
+
+	/* set the prefetch enable bit */
+	if (prefetch) 
+		tempReg |= MV_PMFLASH_CFG2_PRFTCH_MASK;		/* prefetch mode active HI */
+	else
+		tempReg &= ~MV_PMFLASH_CFG2_PRFTCH_MASK;
+
+	/* write the new register value */
+	if ((ret = mvPMFlashSetConfig2(pFlash, tempReg)) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPMFlashShutdownSet - Shutdown the voltage regulator in the flash device
+*
+* DESCRIPTION:
+*       Causes the device to enter in a power save mode untill the next access 
+*		to the flash.
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashShutdownSet(MV_MFLASH_INFO *pFlash)
+{
+	if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvPMFlashEraseSeq(pFlash, MV_PMFLASH_OPCD_SHUTDOWN);	
+}
+
+/*******************************************************************************
+* mvPMFlashIdGet - Retreive the MFlash manufacturer and device IDs
+*
+* DESCRIPTION:
+*       Read from the Mflash the 32bit manufacturer ID and the 16bit devide Id.
+*
+* INPUT:
+*       pFlash: Structure with Marvell Flash information
+*       pManfCode: pointer to the 32bit to fill the manufacturer Id
+*       pDevCode: pointer to the 16bit to fill the device Id
+*
+* OUTPUT:
+*       pManfCode: pointer to the 32bit holding the manufacturer Id
+*       pDevCode: pointer to the 16bit holding the device Id
+*
+* RETURN:
+*       Success or Error code.
+*       
+*
+*******************************************************************************/
+MV_STATUS mvPMFlashIdGet (MV_MFLASH_INFO *pFlash, MV_U32 * pManfCode, MV_U16 * pDevCode)
+{
+	MV_U32 temp;	
+    MV_STATUS ret;
+
+	if ((pFlash == NULL) || (pManfCode == NULL) || (pDevCode == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* first confiure the Inf Read Data length = 3 (i.e 3*16bit = 6bytes)
+	  This is because we need to read 6 bytes (4bytes Manuf. ID and 2 bytes Dev ID) */
+	MV_REG_WRITE(MV_PMFLASH_IF_CTRL_REG, MV_PMFLASH_READ_ID_16BIT_COUNT);
+
+	/* set commnand opcode = prgCmnd */
+	temp = MV_REG_READ(MV_PMFLASH_CMD_OPCODE_REG);
+	temp = ((temp & ~MV_PMFLASH_CMD_OPCD_MASK) | MV_PMFLASH_OPCD_READ_ID | MV_PMFLASH_EAD9_8_MASK);
+	MV_REG_WRITE(MV_PMFLASH_CMD_OPCODE_REG, temp);
+
+	/* Trigger the erase operation - set bit 13 to 1 */
+	MV_REG_BIT_SET(MV_PMFLASH_CMD_OPCODE_REG, MV_PMFLASH_INF_READ_STRT_MASK);
+	
+	/* block waiting for bit to be cleared by hardware */
+	if ((ret = waitOnInfReadBitClear()) != MV_OK)
+		return ret;
+
+	/* read the 6bytes from the Data register into the buffer in 3 iterations */
+	/* First re-organize the Manufacturer ID */
+	*pManfCode = 0;
+	temp = MV_REG_READ(MV_PMFLASH_DATA_REG);		/* First 16bit */
+	*pManfCode |= ((temp << 24) & 0xFF000000);
+	*pManfCode |= ((temp << 8)  & 0x00FF0000);
+	temp = MV_REG_READ(MV_PMFLASH_DATA_REG);		/* Second 16bit */
+	*pManfCode |= ((temp << 8) & 0x0000FF00);
+	*pManfCode |= ((temp >> 8) & 0x000000FF);
+
+	/* Then re-organize the Device ID */
+	*pDevCode = 0;
+	temp = MV_REG_READ(MV_PMFLASH_DATA_REG);		/* Third 16bit */
+	*pDevCode |= ((temp << 8) & 0x0000FF00);
+	*pDevCode |= ((temp >> 8) & 0x000000FF);
+
+	/* Set the word count back to the defualt for IREAD commands = 4*16bit */
+	MV_REG_WRITE(MV_PMFLASH_IF_CTRL_REG, MV_PMFLASH_IREAD_16BIT_COUNT);
+
+	return MV_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlash.h b/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlash.h
new file mode 100755
index 0000000..33d0aec
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlash.h
@@ -0,0 +1,120 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvPMFlashH
+#define __INCmvPMFlashH
+
+#include "mvMFlash.h"
+
+/* Parallel mode function prototypes */
+
+/* Init */
+MV_STATUS	mvPMFlashInit			(MV_MFLASH_INFO *pFlash);
+
+/* Erase */
+MV_STATUS 	mvPMFlashChipErase  	(MV_MFLASH_INFO *pFlash); /* Erase the whole chip */
+MV_STATUS 	mvPMFlashMainErase	  	(MV_MFLASH_INFO *pFlash); /* Erase the whole main region */
+MV_STATUS 	mvPMFlashInfErase	  	(MV_MFLASH_INFO *pFlash); /* Erase the whole information region */
+MV_STATUS 	mvPMFlashSecErase 		(MV_MFLASH_INFO *pFlash, MV_U32 secNumber); /* Single Main sector erase */
+
+/* write */
+MV_STATUS   mvPMFlash64bWr          (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock);
+MV_STATUS   mvPMFlash64bWrVerify    (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock);
+MV_STATUS   mvPMFlash64bInfWr       (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock);
+MV_STATUS   mvPMFlash64bInfWrVerify (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock);
+
+/* Read */
+MV_STATUS   mvPMFlashBlockRd        (MV_MFLASH_INFO *pFlash, MV_U32 offset, \
+                                     MV_U32 blockSize, MV_U8 *pBlock);
+MV_STATUS   mvPMFlashBlockInfRd     (MV_MFLASH_INFO *pFlash, MV_U32 offset, \
+                                     MV_U32 blockSize, MV_U8 *pBlock);
+
+/* Configuration registers Read/Write */
+MV_STATUS	mvPMFlashReadConfig1	(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg);
+MV_STATUS	mvPMFlashReadConfig2	(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg);
+MV_STATUS	mvPMFlashReadConfig3 	(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg);
+MV_STATUS	mvPMFlashReadConfig4	(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg);
+MV_STATUS	mvPMFlashSetConfig1		(MV_MFLASH_INFO *pFlash, MV_U8 configReg);
+MV_STATUS	mvPMFlashSetConfig2		(MV_MFLASH_INFO *pFlash, MV_U8 configReg);
+MV_STATUS	mvPMFlashSetConfig3		(MV_MFLASH_INFO *pFlash, MV_U8 configReg);
+MV_STATUS	mvPMFlashSetConfig4		(MV_MFLASH_INFO *pFlash, MV_U8 configReg);
+MV_STATUS	mvPMFlashSetSlewRate	(MV_MFLASH_INFO *pFlash, MV_U8 configReg);
+
+/* write protection */
+MV_STATUS 	mvPMFlashWriteProtectSet(MV_MFLASH_INFO *pFlash, MV_BOOL wp);
+MV_STATUS 	mvPMFlashWriteProtectGet(MV_MFLASH_INFO *pFlash, MV_BOOL * pWp);
+
+/* Set the Sector Size option */
+MV_STATUS 	mvPMFlashSectorSizeSet	(MV_MFLASH_INFO *pFlash, MV_U32 secSize);
+
+/* Prefetch Operation Set */
+MV_STATUS	mvPMFlashPrefetchSet    (MV_MFLASH_INFO *pFlash, MV_BOOL prefetch);
+
+/* Shutdown/operate (true/false) the device */
+MV_STATUS 	mvPMFlashShutdownSet    (MV_MFLASH_INFO *pFlash);
+
+/* Retreive the Flash ID */
+MV_STATUS	mvPMFlashIdGet			(MV_MFLASH_INFO *pFlash, MV_U32 * pManfCode, MV_U16 * pDevCode);
+
+#endif /* __INCmvPMFlashH */
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlashSpec.h b/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlashSpec.h
new file mode 100755
index 0000000..5bdb145
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvPMFlashSpec.h
@@ -0,0 +1,178 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvPMFlashSpecH
+#define __INCmvPMFlashSpecH
+
+#include "mvMFlashSpec.h"
+
+/* default values for the timing registers */
+#define		MV_PMFLASH_T1                       0x7     /* Read Access Time T1 – sunol2 default */
+#define		MV_PMFLASH_T2                       0x7     /* Read Access Time T2 – sunol2 default */
+#define		MV_PMFLASH_T7                       0x29    /* Divider Number for T7 – sunol2 default */
+#define		MV_PMFLASH_PCLK_OUT                 0x0     /* Hold Time between reference clock and PCLK */
+#define		MV_PMFLASH_SLEW_0_1                 0x2     /* slew rate for PCLK_OUT bits 0-1 */
+#define		MV_PMFLASH_SLEW_2_3                 0x3     /* slew rate for PCLK_OUT bits 2-3 */
+
+/* Programming allignment mask */
+#define		MV_PMFLASH_PROG_WORDS_PER_CHUNK		(MV_MFLASH_PROG_CHUNK_SIZE / 2)
+
+/* IRead Allignmet definitions */
+#define		MV_PMFLASH_IREAD_ALIGN_MASK			0x0007  /* IREAD should be alligned to 8bytes */
+#define		MV_PMFLASH_IREAD_CHUNK_SIZE			(MV_PMFLASH_IREAD_ALIGN_MASK + 1)
+
+/* wrod count for the Indirect read commands (IREAD and READ ID) */
+#define		MV_PMFLASH_IREAD_16BIT_COUNT		0x4			/* 8 bytes per IREAD command */
+#define		MV_PMFLASH_READ_ID_16BIT_COUNT		0x3			/* 6 bytes = 4 manf ID + 2 Dev ID */
+
+/* MFlash command opcodes */
+#define		MV_PMFLASH_OPCD_PROGRAM				0x02
+#define		MV_PMFLASH_OPCD_PRG_CMP				0x07
+#define		MV_PMFLASH_OPCD_IPROGRAM			0x82
+#define		MV_PMFLASH_OPCD_IPRG_CMP			0x87
+#define		MV_PMFLASH_OPCD_PAGE_ERASE			0x52
+#define		MV_PMFLASH_OPCD_IPAGE_ERASE			0xD2
+#define		MV_PMFLASH_OPCD_CHIP_ERASE			0xE2
+#define		MV_PMFLASH_OPCD_MAIN_ERASE			0x62
+#define		MV_PMFLASH_OPCD_RDSR				0x05
+#define		MV_PMFLASH_OPCD_IREAD				0x83
+#define		MV_PMFLASH_OPCD_SET_CFG1			0xB0
+#define		MV_PMFLASH_OPCD_SET_CFG2			0xB1
+#define		MV_PMFLASH_OPCD_SET_CFG3			0xB2
+#define		MV_PMFLASH_OPCD_SET_CFG4			0xB3
+#define		MV_PMFLASH_OPCD_READ_CFG1			0xB4
+#define		MV_PMFLASH_OPCD_READ_CFG2			0xB5
+#define		MV_PMFLASH_OPCD_READ_CFG3			0xB6
+#define		MV_PMFLASH_OPCD_READ_CFG4			0xB7
+#define		MV_PMFLASH_OPCD_SHUTDOWN			0xA4
+#define		MV_PMFLASH_OPCD_SET_SLEW			0xA5
+#define		MV_PMFLASH_OPCD_READ_ID				0x15
+
+/* Marvell Flash Device Controller Registers */
+#define		MV_PMFLASH_CTRLR_OFST				0x10500
+#define		MV_PMFLASH_IF_CTRL_REG				(MV_PMFLASH_CTRLR_OFST + 0x00)
+#define		MV_PMFLASH_IF_CFG_REG				(MV_PMFLASH_CTRLR_OFST + 0x04)
+#define		MV_PMFLASH_ADDR_LOW_REG				(MV_PMFLASH_CTRLR_OFST + 0x08)
+#define		MV_PMFLASH_ADDR_HI_REG				(MV_PMFLASH_CTRLR_OFST + 0x0c)
+#define		MV_PMFLASH_CMD_OPCODE_REG			(MV_PMFLASH_CTRLR_OFST + 0x10)
+#define		MV_PMFLASH_IF_STATUS_REG			(MV_PMFLASH_CTRLR_OFST + 0x14)
+#define		MV_PMFLASH_STATUS_REG				(MV_PMFLASH_CTRLR_OFST + 0x18)
+#define		MV_PMFLASH_DATA_REG					(MV_PMFLASH_CTRLR_OFST + 0x20)
+
+/* Flash Interface configuration */
+#define		MV_PMFLASH_SERIAL_MODE_OFFSET		0		/* bit 0 */
+#define		MV_PMFLASH_RESET_OFFSET				4		/* bit 4 */
+#define		MV_PMFLASH_IF_RESET_OFFSET			5		/* bit 5 */
+#define		MV_PMFLASH_WP_PROTECT_OFFSET		6		/* bit 6 */
+#define		MV_PMFLASH_EXT_FLASH_OFFSET			12	    /* bit 12 */
+#define		MV_PMFLASH_EXT_PROGRAMMER_OFFSET	13	    /* bit 13 */
+#define		MV_PMFLASH_SERIAL_MODE_MASK			(0x1  << MV_PMFLASH_SERIAL_MODE_OFFSET)
+#define		MV_PMFLASH_RESET_MASK				(0x1  << MV_PMFLASH_RESET_OFFSET)
+#define		MV_PMFLASH_IF_RESET_MASK			(0x1  << MV_PMFLASH_IF_RESET_OFFSET)
+#define		MV_PMFLASH_WP_PROTECT_MASK			(0x1  << MV_PMFLASH_WP_PROTECT_OFFSET)
+#define		MV_PMFLASH_EXT_FLASH_MASK			(0x1  << MV_PMFLASH_EXT_FLASH_OFFSET)
+#define		MV_PMFLASH_EXT_PROGRAMMER_MASK		(0x1  << MV_PMFLASH_EXT_PROGRAMMER_OFFSET)
+
+#define     MV_PMFLASH_SPI_BUS_MODE_MASK        (MV_PMFLASH_SERIAL_MODE_MASK | MV_PMFLASH_EXT_FLASH_MASK | MV_PMFLASH_EXT_PROGRAMMER_MASK)
+#define     MV_PMFLASH_SPI_BUS_TO_MFLASH        0x1001
+#define     MV_PMFLASH_SPI_BUS_TO_EXT_SFLASH    0x0000
+#define     MV_PMFLASH_SPI_BUS_EXT_PROGRAMER    0x2001
+
+/* Command Opcode Register Masks */
+#define		MV_PMFLASH_CMD_OPCD_OFFSET			0		/* bits 0-7 */
+#define     MV_PMFLASH_EAD9_8_OFFSET            8       /* bit 8 */
+#define		MV_PMFLASH_WR_OPER_STRT_OFFSET		12  	/* bit 12 */
+#define		MV_PMFLASH_ERASE_STRT_OFFSET		13	    /* bit 13 */
+#define		MV_PMFLASH_RDSR_SET_OFFSET			14	    /* bit 14 */
+#define		MV_PMFLASH_INF_READ_STRT_OFFSET		15	    /* bit 15 */
+#define     MV_PMFLASH_EAD9_8_MASK              (0x3  << MV_PMFLASH_EAD9_8_OFFSET)
+#define		MV_PMFLASH_CMD_OPCD_MASK			(0xFF << MV_PMFLASH_CMD_OPCD_OFFSET)
+#define		MV_PMFLASH_WR_OPER_STRT_MASK		(0x1  << MV_PMFLASH_WR_OPER_STRT_OFFSET)
+#define		MV_PMFLASH_ERASE_STRT_MASK			(0x1  << MV_PMFLASH_ERASE_STRT_OFFSET)
+#define		MV_PMFLASH_RDSR_SET_MASK			(0x1  << MV_PMFLASH_RDSR_SET_OFFSET)
+#define		MV_PMFLASH_INF_READ_STRT_MASK		(0x1  << MV_PMFLASH_INF_READ_STRT_OFFSET)
+
+/* Flash Interface Status Register Masks */
+#define     MV_PMFLASH_CMD_DONE_OFFSET			0		/* bit 0 */
+#define     MV_PMFLASH_CMD_DONE_MASK			(0x1  << MV_PMFLASH_CMD_DONE_OFFSET)
+
+/* Flash Status Register Masks */
+#define		MV_PMFLASH_STATUS_OFFSET			0		/* bits 0-7 */
+#define		MV_PMFLASH_STAT_WIP_OFFSET			0		/* bit 0 */
+#define     MV_PMFLASH_STAT_CMP_OFFSET          6       /* bit 6 */
+#define		MV_PMFLASH_STATUS_MASK				(0xFF << MV_PMFLASH_STATUS_OFFSET)
+#define		MV_PMFLASH_STAT_WIP_MASK			(0x1  << MV_PMFLASH_STAT_WIP_OFFSET)
+#define		MV_PMFLASH_STAT_CMP_MASK			(0x1  << MV_PMFLASH_STAT_CMP_OFFSET)
+
+/* MFlash CONFIG4 register bit Masks */
+#define		MV_PMFLASH_CFG4_PG_SZ_OFFSET		0		/* bit 0 */
+#define		MV_PMFLASH_CFG4_WP_OFFSET			7		/* bit 7 */
+#define		MV_PMFLASH_CFG4_PG_SZ_MASK			(0x1  << MV_PMFLASH_CFG4_PG_SZ_OFFSET)
+#define		MV_PMFLASH_CFG4_WP_MASK				(0x1  << MV_PMFLASH_CFG4_WP_OFFSET)
+
+/* MFlash CONFIG2 register bit Masks */
+#define		MV_PMFLASH_CFG2_PRFTCH_OFFSET		7	    /* bit 7 */
+#define		MV_PMFLASH_CFG2_PRFTCH_MASK			(0x1  << MV_PMFLASH_CFG2_PRFTCH_OFFSET)
+
+#endif /* __INCmvPMFlashSpecH */
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlash.c b/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlash.c
new file mode 100755
index 0000000..9ac4eea
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlash.c
@@ -0,0 +1,1076 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include "mflash/mvSMFlash.h"
+#include "mflash/mvSMFlashSpec.h"
+#include "mflash/mvMFlash.h"
+#include "mflash/mvMFlashSpec.h"
+#include "spi/mvSpi.h"
+#include "spi/mvSpiCmnd.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+/*#define MV_DEBUG*/
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+/* Static Functions */
+static MV_STATUS mvSingleByteCmnd     (MV_U8 opcode);
+static MV_STATUS mvSingleByteRead     (MV_U8 opcode, MV_U8* pData);
+static MV_STATUS mvSingleByteWrite    (MV_U8 opcode, MV_U8 data);
+static MV_STATUS mvWriteEnable        (MV_VOID);
+static MV_STATUS mvStatusRegGet       (MV_U8* pStatus);
+static MV_STATUS mvWaitOnWipClear     (MV_VOID);
+
+/*******************************************************************************
+* mvSingleByteCmnd - Issue an 8bit commmand
+*
+* DESCRIPTION:
+*       serialize an 8bit command without any data
+*
+********************************************************************************/
+static MV_STATUS mvSingleByteCmnd(MV_U8 opcode)
+{
+	MV_U8 cmd[1];
+	cmd[0] = opcode;
+	return mvSpiWriteThenRead(cmd, 1, NULL, 0,0);
+}
+
+/*******************************************************************************
+* mvSingleByteCmnd - Issue an 8bit Read
+*
+* DESCRIPTION:
+*       serialize an 8bit command and read 8bits of data
+*
+********************************************************************************/
+static MV_STATUS mvSingleByteRead(MV_U8 opcode, MV_U8* pData)
+{
+	MV_U8 cmd[1];
+	cmd[0] = opcode;
+	return mvSpiWriteThenRead(cmd, 1, pData, 1,0);
+}
+
+/*******************************************************************************
+* mvSingleByteWrite - Issue an 8bit Write
+*
+* DESCRIPTION:
+*       serialize an 8bit command and 8bits of data
+*
+********************************************************************************/
+static MV_STATUS mvSingleByteWrite(MV_U8 opcode, MV_U8 data)
+{
+	return mvSpiWriteThenWrite(&opcode, 1, &data, 1);
+}
+
+/*******************************************************************************
+* mvWriteEnable - Perform the write enable sequence
+*
+* DESCRIPTION:
+*       Writa enable sequence needed before program and erase commands
+*
+********************************************************************************/
+static MV_STATUS mvWriteEnable(MV_VOID)
+{
+	return mvSingleByteCmnd(MV_SMFLASH_WREN_CMND_OPCD);
+}
+
+/*******************************************************************************
+* mvStatusRegGet - Retreiv the value of the status register
+*
+* DESCRIPTION:
+*       perform the RDSR sequence to get the 8bit status register
+*
+********************************************************************************/
+static MV_STATUS mvStatusRegGet(MV_U8* pStatus)
+{
+	return mvSingleByteRead(MV_SMFLASH_RDSR_CMND_OPCD, pStatus);
+}
+
+/*******************************************************************************
+* mvWaitOnWipClear - Block waiting for the WIP (write in progress) to be cleared
+*
+* DESCRIPTION:
+*       Block waiting for the WIP (write in progress) to be cleared
+*
+********************************************************************************/
+static MV_STATUS mvWaitOnWipClear(MV_VOID)
+{
+    MV_STATUS ret;
+	MV_U32 i;
+	MV_U8 status;
+
+	for (i=0; i<MV_MFLASH_MAX_PRG_LOOP; i++)
+	{
+		/* Read the status register */
+		if ((ret = mvStatusRegGet(&status)) != MV_OK)
+			return ret;
+
+		/* check if write in progress bit was cleared by h/w */
+		if ((status & MV_SMFLASH_STATUS_REG_WIP_MASK) == 0)
+			return MV_OK;
+	}
+
+    DB(mvOsPrintf("%s WARNING: Wait Timeout!\n", __FUNCTION__);)
+	return MV_TIMEOUT;
+}
+
+/*
+#####################################################################################
+#####################################################################################
+*/
+
+/*******************************************************************************
+* mvSMFlashInit - Initialize the Marvell serial flash device
+*
+* DESCRIPTION:
+*       Perform the neccessary initialization and configuration
+*
+* INPUT:
+*       flinfo: Flash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashInit (MV_MFLASH_INFO *pFlash)
+{
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSMFlashChipErase - Erase the whole chip
+*
+* DESCRIPTION:
+*       Perform the chip erase sequence. To set both the Main and information
+*		regions to logic ones.
+*
+* INPUT:
+*       pFlash: Flash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashChipErase (MV_MFLASH_INFO *pFlash)
+{
+	MV_STATUS ret = MV_OK;
+
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	if ((ret = mvSingleByteCmnd(MV_SMFLASH_CHIP_ERASE_CMND_OPCD)) != MV_OK)
+		return ret;
+
+	/* wait for the write in progress bit to be cleared in the status register */
+	if ((ret = mvWaitOnWipClear()) != MV_OK)
+		return ret;
+
+	return ret;
+}
+
+/*******************************************************************************
+* mvSMFlashMainErase - Erase the Main flash region only
+*
+* DESCRIPTION:
+*       Erase the main flash region to ones. Information region will not be
+*		affected.
+*
+* INPUT:
+*       pFlash: Flash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashMainErase (MV_MFLASH_INFO *pFlash)
+{
+	MV_STATUS ret = MV_OK;
+
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	if ((ret = mvSingleByteCmnd(MV_SMFLASH_MAIN_ERASE_CMND_OPCD)) != MV_OK)
+		return ret;
+
+	/* wait for the write in progress bit to be cleared in the status register */
+	if ((ret = mvWaitOnWipClear()) != MV_OK)
+		return ret;
+
+	return ret;
+}
+
+/*******************************************************************************
+* mvSMFlashInfErase - Erase the whole information region only
+*
+* DESCRIPTION:
+*       Erase the whole information region without affecting the Main region.
+*
+* INPUT:
+*       pFlash: Flash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashInfErase (MV_MFLASH_INFO *pFlash)
+{
+	MV_STATUS ret = MV_OK;
+
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	if ((ret = mvSingleByteCmnd(MV_SMFLASH_IPG_ERASE_CMND_OPCD)) != MV_OK)
+		return ret;
+
+	/* wait for the write in progress bit to be cleared in the status register */
+	if ((ret = mvWaitOnWipClear()) != MV_OK)
+		return ret;
+
+	return ret;
+}
+
+/*******************************************************************************
+* mvSMFlashSecErase - Erase a single sector of the Main region
+*
+* DESCRIPTION:
+*       Perform the sequence to erase a Main region sector
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		secNumber: sector number to erase.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashSecErase (MV_MFLASH_INFO *pFlash, MV_U32 secAddr)
+{
+	MV_STATUS ret;
+	MV_U8 cmd[MV_SMFLASH_PAGE_ERASE_CMND_LEN];
+
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	cmd[0] = MV_SMFLASH_PAGE_ERASE_CMND_OPCD;
+	cmd[1] = ((secAddr >> 16) & 0xFF);		/* address bits 16 - 23 */
+	cmd[2] = ((secAddr >> 8) & 0xFF);		/* address bits 8 - 15 */
+	cmd[3] = (secAddr & 0xFF);				/* address bits 0 - 7 */
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	if ((ret = mvSpiWriteThenRead(cmd, MV_SMFLASH_PAGE_ERASE_CMND_LEN, NULL, 0, 0)) != MV_OK)
+		return ret;
+
+	/* wait for the write in progress bit to be cleared in the status register */
+	if ((ret = mvWaitOnWipClear()) != MV_OK)
+		return ret;
+
+	return ret;
+}
+
+
+
+/*******************************************************************************
+* mvSMFlash64bWr - Program 64 bytes of Data alligned to 64 boundaries
+*
+* DESCRIPTION:
+*       Program to main region 64 bytes of Data alligned to 64 boundaries
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		offset: address to start the programming from (alligned to 64 bytes)
+*		pBlock: pointer to the 64 bytes to program
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlash64bWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock)
+{
+	MV_STATUS ret;
+	MV_U8 cmd[MV_SMFLASH_PRGRM_CMND_LEN];
+
+    /* Check for null pointer */
+#ifndef CONFIG_MARVELL
+    if(NULL == pBlock)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+#endif
+
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* check allignment */
+	if (offset & MV_SMFLASH_PAGE_ALLIGN_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Allignment error!\n", __FUNCTION__);)
+		return MV_BAD_PARAM;
+    }
+
+	/* encode the command to send */
+	cmd[0] = MV_SMFLASH_PRGRM_CMND_OPCD;
+	cmd[1] = ((offset >> 16) & 0xFF);
+	cmd[2] = ((offset >> 8) & 0xFF);
+	cmd[3] = (offset & 0xFF);
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	/* serialize the command and then followed by the data to program */
+	if ((ret = mvSpiWriteThenWrite(cmd, MV_SMFLASH_PRGRM_CMND_LEN, pBlock, MV_SMFLASH_PAGE_SIZE)) != MV_OK)
+		return ret;
+
+	/* wait for the write in progress bit to be cleared in the status register */
+	if ((ret = mvWaitOnWipClear()) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSMFlash64bWrVerify - Program and verify 64 bytes of Data alligned to
+*						 64 bytes boundaries
+*
+* DESCRIPTION:
+*       Program and verifyto main region 64 bytes of Data alligned to 64
+*		bytes boundaries
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		offset: address to start the programming from (alligned to 64 bytes)
+*		pBlock: pointer to the 64 bytes to program
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlash64bWrVerify(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock)
+{
+	MV_STATUS ret;
+	MV_U8 cmd[MV_SMFLASH_PRGRM_CMP_CMND_LEN];
+    MV_U8 status;
+
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* check allignment */
+	if (offset & MV_SMFLASH_PAGE_ALLIGN_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Allignment error!\n", __FUNCTION__);)
+		return MV_BAD_PARAM;
+    }
+
+	/* encode the command to send */
+	cmd[0] = MV_SMFLASH_PRGRM_CMP_CMND_OPCD;
+	cmd[1] = ((offset >> 16) & 0xFF);
+	cmd[2] = ((offset >> 8) & 0xFF);
+	cmd[3] = (offset & 0xFF);
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	/* serialize the command and then followed by the data to program */
+	if ((ret = mvSpiWriteThenWrite(cmd, MV_SMFLASH_PRGRM_CMP_CMND_LEN, pBlock, MV_SMFLASH_PAGE_SIZE)) != MV_OK)
+		return ret;
+
+	/* wait for the write in progress bit to be cleared in the status register */
+	if ((ret = mvWaitOnWipClear()) != MV_OK)
+		return ret;
+
+	/* Read the status register */
+	if ((ret = mvStatusRegGet(&status)) != MV_OK)
+		return ret;
+
+	/* check if result of the compare operartion */
+	if (status & MV_SMFLASH_STATUS_REG_CMP_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Compare after write error!\n", __FUNCTION__);)
+		return MV_FAIL;
+    }
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSMFlash64bInfWr - Information region program 64 bytes of Data alligned
+*					  to 64 bytes boundaries
+*
+* DESCRIPTION:
+*       Program to information region 64 bytes of Data alligned to 64 boundaries
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		offset: address to start the programming from (alligned to 64 bytes)
+*		pBlock: pointer to the 64 bytes to program
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlash64bInfWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock)
+{
+	MV_STATUS ret;
+	MV_U8 cmd[MV_SMFLASH_IPRGRM_CMND_LEN];
+
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* check allignment */
+	if (offset & MV_SMFLASH_PAGE_ALLIGN_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Allignment error!\n", __FUNCTION__);)
+		return MV_BAD_PARAM;
+    }
+
+	/* encode the command to send */
+	cmd[0] = MV_SMFLASH_IPRGRM_CMND_OPCD;
+	cmd[1] = ((offset >> 16) & 0xFF);
+	cmd[2] = ((offset >> 8) & 0xFF);
+	cmd[3] = (offset & 0xFF);
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	/* serialize the command and then followed by the data to program */
+	if ((ret = mvSpiWriteThenWrite(cmd, MV_SMFLASH_IPRGRM_CMND_LEN, pBlock, MV_SMFLASH_PAGE_SIZE)) != MV_OK)
+		return ret;
+
+	/* wait for the write in progress bit to be cleared in the status register */
+	if ((ret = mvWaitOnWipClear()) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSMFlash64bInfWrVerify - Program and verify 64 bytes of Data ti the
+*							information region alligned to 64 boundaries
+*
+* DESCRIPTION:
+*       Program and then verify to the information region 64 bytes of Data
+*		alligned to 64 boundaries
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		offset: address to start the programming from (alligned to 64 bytes)
+*		pBlock: pointer to the 64 bytes to program
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlash64bInfWrVerify(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock)
+{
+	MV_STATUS ret;
+	MV_U8 cmd[MV_SMFLASH_IPRGRM_CMP_CMND_LEN];
+    MV_U8 status;
+
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* check allignment */
+	if (offset & MV_SMFLASH_PAGE_ALLIGN_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Allignment error!\n", __FUNCTION__);)
+		return MV_BAD_PARAM;
+    }
+
+	/* encode the command to send */
+	cmd[0] = MV_SMFLASH_IPRGRM_CMP_CMND_OPCD;
+	cmd[1] = ((offset >> 16) & 0xFF);
+	cmd[2] = ((offset >> 8) & 0xFF);
+	cmd[3] = (offset & 0xFF);
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	/* serialize the command and then followed by the data to program */
+	if ((ret = mvSpiWriteThenWrite(cmd, MV_SMFLASH_IPRGRM_CMP_CMND_LEN, pBlock, MV_SMFLASH_PAGE_SIZE)) != MV_OK)
+		return ret;
+
+	/* wait for the write in progress bit to be cleared in the status register */
+	if ((ret = mvWaitOnWipClear()) != MV_OK)
+		return ret;
+
+    /* Read the status register */
+	if ((ret = mvStatusRegGet(&status)) != MV_OK)
+		return ret;
+
+	/* check if result of the compare operartion */
+	if (status & MV_SMFLASH_STATUS_REG_CMP_MASK)
+    {
+        DB(mvOsPrintf("%s WARNING: Compare after information region write error!\n", __FUNCTION__);)
+		return MV_FAIL;
+    }
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSMFlashBlockRd - Read from the main region into a buffer
+*
+* DESCRIPTION:
+*       Issue the main region read sequence. Size and offset are not limited
+*		except to the size of the flash.
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		offset: address in the main region to start the reading from.
+*		blockSize: size of the buffer to be read
+*		pBlock: pointer to the buffer to hold the data read from the flash
+*
+* OUTPUT:
+*		pBlock: pointer to the buffer holding the data from the flash
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashBlockRd(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize,
+						   MV_U8 *pBlock)
+{
+	MV_STATUS ret;
+	MV_U8 cmd[MV_SMFLASH_READ_CMND_LEN];
+
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* check that requested data is in the region */
+    if ((offset + blockSize) > (pFlash->sectorNumber * pFlash->sectorSize))
+    {
+        DB(mvOsPrintf("%s WARNING: Read exceeds flash size!\n", __FUNCTION__);)
+        return MV_BAD_PARAM;
+    }
+
+	/* encode the command to send */
+	cmd[0] = MV_SMFLASH_READ_CMND_OPCD;
+	cmd[1] = ((offset >> 16) & 0xFF);
+	cmd[2] = ((offset >> 8) & 0xFF);
+	cmd[3] = (offset & 0xFF);
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	/* serialize the command and then followed by the data to program */
+	if ((ret = mvSpiWriteThenRead(cmd, MV_SMFLASH_READ_CMND_LEN, pBlock, blockSize, 0)) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSMFlashBlockInfRd - Read from the information region into a buffer
+*
+* DESCRIPTION:
+*       Issue the information region read sequence. Size and offset are not
+*		limited except to the size of the information region.
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		offset: address in the information region to start the reading from.
+*		blockSize: size of the buffer to be read
+*		pBlock: pointer to the buffer to hold the data read from the flash
+*
+* OUTPUT:
+*		pBlock: pointer to the buffer holding the data from the flash
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashBlockInfRd(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize,
+							  MV_U8 *pBlock)
+{
+	MV_STATUS ret;
+	MV_U8 cmd[MV_SMFLASH_IREAD_CMND_LEN];
+
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pBlock == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* check that requested data is in the region */
+    if ((offset + blockSize) > pFlash->infoSize)
+    {
+        DB(mvOsPrintf("%s WARNING: Read exceeds information region size!\n", __FUNCTION__);)
+		return MV_BAD_PARAM;
+    }
+
+	/* encode the command to send */
+	cmd[0] = MV_SMFLASH_IREAD_CMND_OPCD;
+	cmd[1] = ((offset >> 16) & 0xFF);
+	cmd[2] = ((offset >> 8) & 0xFF);
+	cmd[3] = (offset & 0xFF);
+
+	/* Perform the write enable sequence */
+	if ((ret = mvWriteEnable()) != MV_OK)
+		return ret;
+
+	/* serialize the command and then followed by the data to program */
+	if ((ret = mvSpiWriteThenRead(cmd, MV_SMFLASH_IREAD_CMND_LEN, pBlock, blockSize, 0)) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSMFlashReadConfig3 - Read the value of the configuration register
+*
+* DESCRIPTION:
+*       Read the value of the configuration register #3
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		configReg: pointer to the 8bit variable to read in the config register
+*
+* OUTPUT:
+*		configReg: pointer to the 8bit varable holding the config register
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashReadConfig3(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg)
+{
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pConfigReg == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvSingleByteRead(MV_SMFLASH_READ_CFG_3_CMND_OPCD, pConfigReg);
+}
+
+/*******************************************************************************
+* mvSMFlashReadConfig4 - Read the value of the configuration register
+*
+* DESCRIPTION:
+*       Read the value of the configuration register #4
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		configReg: pointer to the 8bit variable to read in the config register
+*
+* OUTPUT:
+*		configReg: pointer to the 8bit varable holding the config register
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashReadConfig4(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg)
+{
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pConfigReg == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvSingleByteRead(MV_SMFLASH_READ_CFG_4_CMND_OPCD, pConfigReg);
+}
+
+/*******************************************************************************
+* mvSMFlashSetConfig3 - Set the value of the configuration register
+*
+* DESCRIPTION:
+*       Set the value of the configuration register #3
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		configReg: 8bit variable to be written to the config register
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashSetConfig3(MV_MFLASH_INFO *pFlash, MV_U8 configReg)
+{
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvSingleByteWrite(MV_SMFLASH_SET_CFG_3_CMND_OPCD, configReg);
+}
+
+/*******************************************************************************
+* mvSMFlashSetConfig4 - Set the value of the configuration register
+*
+* DESCRIPTION:
+*       Set the value of the configuration register #4
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		configReg: 8bit variable to be written to the config register
+*
+* OUTPUT:
+*		None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashSetConfig4(MV_MFLASH_INFO *pFlash, MV_U8 configReg)
+{
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvSingleByteWrite(MV_SMFLASH_SET_CFG_4_CMND_OPCD, configReg);
+}
+
+/*******************************************************************************
+* mvSMFlashWriteProtectSet - Write protect the whole flash device
+*
+* DESCRIPTION:
+*       Enable/Disable the write protection on the whole flash device.
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		wp: enable/disable (MV_TRUE/MV_FALSE) write protection
+*
+* OUTPUT:
+*		None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashWriteProtectSet(MV_MFLASH_INFO *pFlash, MV_BOOL wp)
+{
+    MV_STATUS ret;
+	MV_U8 reg;
+
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* Read the serial configuration register #4 */
+	if ((ret = mvSMFlashReadConfig4(pFlash, &reg)) != MV_OK)
+		return ret;
+
+	/* set the WP bit according to the wp input */
+	if (wp)
+		reg &= ~MV_SMFLASH_SRL_CFG4_WP_MASK;
+	else
+		reg |= MV_SMFLASH_SRL_CFG4_WP_MASK;
+
+	/* write back the serial configuration register #4 */
+	if ((ret = mvSMFlashSetConfig4(pFlash, reg)) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvSMFlashSectorSizeSet - Set the sector size
+*
+* DESCRIPTION:
+*       Set the sector size (4K or 32K)
+*
+* INPUT:
+*       pFlash: Flash information structure
+*		secSize: requested sector size
+*
+* OUTPUT:
+*		None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashSectorSizeSet(MV_MFLASH_INFO *pFlash, MV_U32 secSize)
+{
+    MV_STATUS ret;
+	MV_U8 reg;
+
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	/* Read the serial configuration register #4 */
+	if ((ret = mvSMFlashReadConfig4(pFlash, &reg)) != MV_OK)
+		return ret;
+
+	/* set the PAGE4K bit according to the secSize input */
+	switch (secSize)
+	{
+		case MV_MFLASH_SECTOR_SIZE_BIG:
+			reg &= ~MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK;	/* 32K sectors */
+			break;
+
+		case MV_MFLASH_SECTOR_SIZE_SMALL:
+			reg |= MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK;		/* 4K sectors */
+			break;
+
+		default:
+            DB(mvOsPrintf("%s WARNING: Invalid parameter sector size!\n", __FUNCTION__);)
+			return MV_BAD_PARAM;
+	}
+
+	/* write back the serial configuration register #4 */
+	if ((ret = mvSMFlashSetConfig4(pFlash, reg)) != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSMFlashShutdownSet - Put the flash device in power save mode
+*
+* DESCRIPTION:
+*       Put the flash device in power save mode
+*
+* INPUT:
+*       pFlash: Flash information structure
+*
+* OUTPUT:
+*		None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashShutdownSet(MV_MFLASH_INFO *pFlash)
+{
+    /* Check for null pointer */
+    if (pFlash == NULL)
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	return mvSingleByteCmnd(MV_SMFLASH_SHUTDOWN_CMND_OPCD);
+}
+
+/*******************************************************************************
+* mvSMFlashIdGet - Retreive the Manufacturer ID and Device ID
+*
+* DESCRIPTION:
+*       Read from the flash device the
+*
+* INPUT:
+*       pFlash: Flash information structure
+*
+* OUTPUT:
+*		None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSMFlashIdGet(MV_MFLASH_INFO *pFlash, MV_U32 * pManfCode, MV_U16 * pDevCode)
+{
+	MV_STATUS ret = MV_OK;
+	MV_U8 cmd[MV_SMFLASH_RDID_CMND_LEN];
+	MV_U8 id[MV_SMFLASH_RDID_RPLY_LEN];
+
+    /* Check for null pointer */
+    if ((pFlash == NULL) || (pManfCode == NULL) || (pDevCode == NULL))
+    {
+        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
+        return MV_BAD_PARAM;
+    }
+
+	cmd[0] = MV_SMFLASH_RDID_CMND_OPCD;
+
+	if ((ret = mvSpiWriteThenRead(cmd, MV_SMFLASH_RDID_CMND_LEN, id, MV_SMFLASH_RDID_RPLY_LEN, 0)) != MV_OK)
+		return ret;
+
+	*pManfCode = ((id[0] << 24) | (id[1] << 16) | (id[2] << 8) | (id[3]));
+	*pDevCode = ((id[4] << 8) | (id[5]));
+
+	return ret;
+}
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlash.h b/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlash.h
new file mode 100755
index 0000000..a5be79c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlash.h
@@ -0,0 +1,111 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSMFlashH
+#define __INCmvSMFlashH
+
+#include "mvMFlash.h"
+
+/* Function Prototypes */
+
+/* Init */
+MV_STATUS	mvSMFlashInit			(MV_MFLASH_INFO *pFlash);
+
+/* Erase */
+MV_STATUS 	mvSMFlashChipErase  	(MV_MFLASH_INFO *pFlash); /* Erase the whole chip */
+MV_STATUS 	mvSMFlashMainErase	  	(MV_MFLASH_INFO *pFlash); /* Erase the whole main region */
+MV_STATUS 	mvSMFlashInfErase	  	(MV_MFLASH_INFO *pFlash); /* Erase the whole information region */
+MV_STATUS 	mvSMFlashSecErase 		(MV_MFLASH_INFO *pFlash, MV_U32 secAddr); /* Single Main sector erase */
+
+/* Read */
+MV_STATUS   mvSMFlashBlockRd        (MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+						             MV_U32 blockSize, MV_U8 *pBlock);
+MV_STATUS   mvSMFlashBlockInfRd     (MV_MFLASH_INFO *pFlash, MV_U32 offset, 
+                                     MV_U32 blockSize, MV_U8 *pBlock);
+
+/* write - 64 bytes aliigned to 64 edges */
+MV_STATUS   mvSMFlash64bWr          (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock);
+MV_STATUS   mvSMFlash64bWrVerify    (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock);
+MV_STATUS   mvSMFlash64bInfWr       (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock);
+MV_STATUS   mvSMFlash64bInfWrVerify (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBlock);
+
+/* Configuration registers Read/Write */
+MV_STATUS	mvSMFlashReadConfig3 	(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg);
+MV_STATUS	mvSMFlashReadConfig4	(MV_MFLASH_INFO *pFlash, MV_U8 * pConfigReg);
+MV_STATUS	mvSMFlashSetConfig3		(MV_MFLASH_INFO *pFlash, MV_U8 configReg);
+MV_STATUS	mvSMFlashSetConfig4		(MV_MFLASH_INFO *pFlash, MV_U8 configReg);
+
+/* write protection */
+MV_STATUS 	mvSMFlashWriteProtectSet(MV_MFLASH_INFO *pFlash, MV_BOOL wp);
+
+/* Set the Sector Size option */
+MV_STATUS 	mvSMFlashSectorSizeSet	(MV_MFLASH_INFO *pFlash, MV_U32 secSize);
+
+/* Shutdown/operate (true/false) the device */
+MV_STATUS 	mvSMFlashShutdownSet    (MV_MFLASH_INFO *pFlash);
+
+/* Retreive the Flash ID */
+MV_STATUS	mvSMFlashIdGet			(MV_MFLASH_INFO *pFlash, MV_U32 * pManfCode, MV_U16 * pDevCode);
+
+#endif /* __INCmvSMFlashH */
diff --git a/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlashSpec.h b/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlashSpec.h
new file mode 100755
index 0000000..680c1bc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/mflash/mvSMFlashSpec.h
@@ -0,0 +1,119 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSMFlashSpecH
+#define __INCmvSMFlashSpecH
+
+/* Constants */
+#define		MV_SMFLASH_PAGE_ALLIGN_MASK		    0x3F
+#define		MV_SMFLASH_PAGE_SIZE			    (MV_SMFLASH_PAGE_ALLIGN_MASK+1) /* 64 byte */
+
+#define		MV_SMFLASH_WREN_CMND_OPCD		    0x06	/* Write Enable */
+#define		MV_SMFLASH_WRDI_CMND_OPCD		    0x04	/* Write Disable */
+#define		MV_SMFLASH_RDSR_CMND_OPCD		    0x05	/* Read Status Register */
+#define		MV_SMFLASH_READ_CMND_OPCD		    0x03	/* Sequential Read */
+#define		MV_SMFLASH_PRGRM_CMND_OPCD		    0x02	/* Page Program */
+#define		MV_SMFLASH_PRGRM_CMP_CMND_OPCD	    0x07	/* Page Program and compare */
+#define		MV_SMFLASH_PAGE_ERASE_CMND_OPCD	    0x42	/* Sector Erase */
+#define		MV_SMFLASH_MAIN_ERASE_CMND_OPCD	    0x62	/* Main region Erase */
+#define		MV_SMFLASH_RDID_CMND_OPCD		    0x15	/* Read ID */
+#define		MV_SMFLASH_IREAD_CMND_OPCD		    0x83	/* Read from Information region */
+#define		MV_SMFLASH_IPRGRM_CMND_OPCD		    0x82	/* Program the information region */
+#define		MV_SMFLASH_IPRGRM_CMP_CMND_OPCD	    0x87	/* Program and compare information region */
+#define		MV_SMFLASH_SET_CFG_3_CMND_OPCD	    0xB2	/* Set configuration register 3 */
+#define		MV_SMFLASH_SET_CFG_4_CMND_OPCD	    0xB3	/* Set configuration register 4 */
+#define		MV_SMFLASH_READ_CFG_3_CMND_OPCD	    0xB6	/* Read configuration register 3 */
+#define		MV_SMFLASH_READ_CFG_4_CMND_OPCD	    0xB7	/* Read configuration register 4 */
+#define		MV_SMFLASH_IPG_ERASE_CMND_OPCD	    0xC2	/* Erase the information page */
+#define		MV_SMFLASH_CHIP_ERASE_CMND_OPCD	    0xE2	/* Chip erase (main + information) */
+#define		MV_SMFLASH_SHUTDOWN_CMND_OPCD	    0xF0	/* Set flash in power down mode */
+
+#define		MV_SMFLASH_PAGE_ERASE_CMND_LEN	    4		/* 1B opcode + 3B address */
+#define		MV_SMFLASH_PRGRM_CMND_LEN   		4		/* 1B opcode + 3B address */
+#define		MV_SMFLASH_PRGRM_CMP_CMND_LEN	    4		/* 1B opcode + 3B address */
+#define		MV_SMFLASH_IPRGRM_CMND_LEN		    4		/* 1B opcode + 3B address */
+#define		MV_SMFLASH_IPRGRM_CMP_CMND_LEN  	4		/* 1B opcode + 3B address */
+#define		MV_SMFLASH_READ_CMND_LEN		    4		/* 1B opcode + 3B address */
+#define		MV_SMFLASH_IREAD_CMND_LEN		    4		/* 1B opcode + 3B address */
+#define		MV_SMFLASH_RDID_CMND_LEN		    1		/* 1B opcode */
+#define		MV_SMFLASH_RDID_RPLY_LEN		    6		/* 4B manuf ID + 2B device ID */
+
+/* Status Register Bit Masks */
+#define		MV_SMFLASH_STATUS_REG_WIP_OFFSET    0	    /* bit 0 - Write in Progress */
+#define		MV_SMFLASH_STATUS_REG_WEL_OFFSET    1	    /* bit 1 - Write enable Latch */
+#define		MV_SMFLASH_STATUS_REG_CMP_OFFSET    6	    /* bit 6 - Compare status */
+#define		MV_SMFLASH_STATUS_REG_WP_OFFSET	    7	    /* bit 7 - Write protect status */
+#define		MV_SMFLASH_STATUS_REG_WIP_MASK	    (0x1 << MV_SMFLASH_STATUS_REG_WIP_OFFSET)
+#define		MV_SMFLASH_STATUS_REG_WEL_MASK	    (0x1 << MV_SMFLASH_STATUS_REG_WEL_OFFSET)
+#define		MV_SMFLASH_STATUS_REG_CMP_MASK	    (0x1 << MV_SMFLASH_STATUS_REG_CMP_OFFSET)
+#define		MV_SMFLASH_STATUS_REG_WP_MASK	    (0x1 << MV_SMFLASH_STATUS_REG_WP_OFFSET)
+
+/* Serial Interface Configuration 4 Masks */
+#define		MV_SMFLASH_SRL_CFG4_PG_SIZE_OFFSET  0       /* bit 0 - Page size */
+#define		MV_SMFLASH_SRL_CFG4_WP_OFFSET		7       /* bit 7 - Write protection */
+#define		MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK    (0x1 << MV_SMFLASH_SRL_CFG4_PG_SIZE_OFFSET)
+#define		MV_SMFLASH_SRL_CFG4_WP_MASK		    (0x1 << MV_SMFLASH_SRL_CFG4_WP_OFFSET)
+
+#endif /* __INCmvSMFlashSpecH */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBm.c b/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBm.c
new file mode 100755
index 0000000..d7168bf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBm.c
@@ -0,0 +1,462 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"		/* Should be included before mvSysHwConfig */
+#include "mvTypes.h"
+#include "mv802_3.h"
+#include "mvDebug.h"
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvSysEthConfig.h"
+
+#include "mvBm.h"
+
+MV_U8 *mvBmVirtBase = 0;
+static MV_BM_POOL	mvBmPools[MV_BM_POOLS];
+
+/* Initialize Hardware Buffer management unit */
+MV_STATUS mvBmInit(MV_U8 *virtBase)
+{
+	MV_U32 regVal;
+
+	mvBmVirtBase = virtBase;
+
+	/* Mask BM all interrupts */
+	MV_REG_WRITE(MV_BM_INTR_MASK_REG, 0);
+
+	/* Clear BM cause register */
+	MV_REG_WRITE(MV_BM_INTR_CAUSE_REG, 0);
+
+	/* Set BM configuration register */
+	regVal = MV_REG_READ(MV_BM_CONFIG_REG);
+
+	/* Reduce MaxInBurstSize from 32 BPs to 16 BPs */
+	regVal &= ~MV_BM_MAX_IN_BURST_SIZE_MASK;
+	regVal |= MV_BM_MAX_IN_BURST_SIZE_16BP;
+	MV_REG_WRITE(MV_BM_CONFIG_REG, regVal);
+
+	memset(mvBmPools, 0, sizeof(mvBmPools));
+
+	return MV_OK;
+}
+
+MV_STATUS mvBmControl(MV_COMMAND cmd)
+{
+	MV_U32 regVal = 0;
+
+	switch (cmd) {
+	case MV_START:
+		regVal = MV_BM_START_MASK;
+		break;
+
+	case MV_STOP:
+		regVal = MV_BM_STOP_MASK;
+		break;
+
+	case MV_PAUSE:
+		regVal = MV_BM_PAUSE_MASK;
+		break;
+
+	default:
+		mvOsPrintf("bmControl: Unknown command %d\n", cmd);
+		return MV_FAIL;
+	}
+	MV_REG_WRITE(MV_BM_COMMAND_REG, regVal);
+	return MV_OK;
+}
+
+MV_STATE mvBmStateGet(void)
+{
+	MV_U32 regVal;
+	MV_STATE state;
+
+	regVal = MV_REG_READ(MV_BM_COMMAND_REG);
+
+	switch ((regVal >> MV_BM_STATUS_OFFS) & MV_BM_STATUS_ALL_MASK) {
+	case MV_BM_STATUS_ACTIVE:
+		state = MV_ACTIVE;
+		break;
+
+	case MV_BM_STATUS_NOT_ACTIVE:
+		state = MV_IDLE;
+		break;
+
+	case MV_BM_STATUS_PAUSED:
+		state = MV_PAUSED;
+		break;
+
+	default:
+		mvOsPrintf("bmStateGet: Unexpected state 0x%x\n", regVal);
+		state = MV_UNDEFINED_STATE;
+	}
+	return state;
+}
+
+void      mvBmConfigSet(MV_U32 mask)
+{
+	MV_U32	regVal;
+
+	regVal = MV_REG_READ(MV_BM_CONFIG_REG);
+	regVal |= mask;
+	MV_REG_WRITE(MV_BM_CONFIG_REG, regVal);
+}
+
+void      mvBmConfigClear(MV_U32 mask)
+{
+	MV_U32	regVal;
+
+	regVal = MV_REG_READ(MV_BM_CONFIG_REG);
+	regVal &= ~mask;
+	MV_REG_WRITE(MV_BM_CONFIG_REG, regVal);
+}
+
+void mvBmPoolTargetSet(int pool, MV_U8 targetId, MV_U8 attr)
+{
+	MV_U32 regVal;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return;
+	}
+	/* Read modify write */
+	regVal = MV_REG_READ(MV_BM_XBAR_POOL_REG(pool));
+
+	regVal &= ~MV_BM_TARGET_ID_MASK(pool);
+	regVal &= ~MV_BM_XBAR_ATTR_MASK(pool);
+	regVal |= MV_BM_TARGET_ID_VAL(pool, targetId);
+	regVal |= MV_BM_XBAR_ATTR_VAL(pool, attr);
+
+	MV_REG_WRITE(MV_BM_XBAR_POOL_REG(pool), regVal);
+}
+
+void mvBmPoolEnable(int pool)
+{
+	MV_U32 regVal;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return;
+	}
+	regVal = MV_REG_READ(MV_BM_POOL_BASE_REG(pool));
+	regVal |= MV_BM_POOL_ENABLE_MASK;
+	MV_REG_WRITE(MV_BM_POOL_BASE_REG(pool), regVal);
+
+	/* Clear BM cause register */
+	MV_REG_WRITE(MV_BM_INTR_CAUSE_REG, 0);
+
+}
+
+void mvBmPoolDisable(int pool)
+{
+	MV_U32 regVal;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return;
+	}
+	regVal = MV_REG_READ(MV_BM_POOL_BASE_REG(pool));
+	regVal &= ~MV_BM_POOL_ENABLE_MASK;
+	MV_REG_WRITE(MV_BM_POOL_BASE_REG(pool), regVal);
+}
+
+MV_BOOL mvBmPoolIsEnabled(int pool)
+{
+	MV_U32 regVal;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return MV_FALSE;
+	}
+	regVal = MV_REG_READ(MV_BM_POOL_BASE_REG(pool));
+	return (regVal & MV_BM_POOL_ENABLE_MASK);
+}
+
+/* Configure BM specific pool of "capacity" size. */
+MV_STATUS mvBmPoolInit(int pool, void *virtPoolBase, MV_ULONG physPoolBase, int capacity)
+{
+	MV_BM_POOL	*pBmPool;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return MV_BAD_PARAM;
+	}
+	/* poolBase must be 4 byte aligned */
+	if (MV_IS_NOT_ALIGN(physPoolBase, MV_BM_POOL_PTR_ALIGN)) {
+		mvOsPrintf("bmPoolBase = 0x%lx is not aligned 4 bytes\n", physPoolBase);
+		return MV_NOT_ALIGNED;
+	}
+	/* Minimum pool capacity is 128 entries */
+	if (capacity < MV_BM_POOL_CAP_MIN) {
+		mvOsPrintf("bmPool capacity = %d is smaller than minimum (%d)\n", capacity, MV_BM_POOL_CAP_MIN);
+		return MV_BAD_SIZE;
+	}
+	/* Update data structure */
+	pBmPool = &mvBmPools[pool];
+	if (pBmPool->pVirt != NULL) {
+		mvOsPrintf("bmPool = %d is already busy\n", pool);
+		return MV_BUSY;
+	}
+
+	pBmPool->pool = pool;
+	pBmPool->capacity = capacity;
+	pBmPool->pVirt = virtPoolBase;
+	pBmPool->physAddr = physPoolBase;
+
+	/* Maximum pool capacity is 16K entries (2^14) */
+	if (capacity > MV_BM_POOL_CAP_MAX) {
+		mvOsPrintf("bmPool capacity = %d is larger than maximum (%d)\n", capacity, MV_BM_POOL_CAP_MAX);
+		return MV_BAD_SIZE;
+	}
+
+	/* Set poolBase address */
+	MV_REG_WRITE(MV_BM_POOL_BASE_REG(pool), physPoolBase);
+
+	/* Set Read pointer to 0 */
+	MV_REG_WRITE(MV_BM_POOL_READ_PTR_REG(pool), 0);
+
+	/* Set Read pointer to 0 */
+	MV_REG_WRITE(MV_BM_POOL_WRITE_PTR_REG(pool), 0);
+
+	/* Set Pool size */
+	MV_REG_WRITE(MV_BM_POOL_SIZE_REG(pool), MV_BM_POOL_SIZE_VAL(capacity));
+
+	return MV_OK;
+}
+
+MV_STATUS mvBmPoolBufSizeSet(int pool, int buf_size)
+{
+	MV_BM_POOL *pBmPool;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return MV_BAD_PARAM;
+	}
+	pBmPool = &mvBmPools[pool];
+
+	pBmPool->bufSize = buf_size;
+
+	return MV_OK;
+}
+
+MV_STATUS mvBmPoolBufNumUpdate(int pool, int buf_num)
+{
+	MV_BM_POOL *pBmPool;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return MV_BAD_PARAM;
+	}
+
+	pBmPool = &mvBmPools[pool];
+	if (pBmPool->bufSize == 0) {
+		mvOsPrintf("bmPoolId = %d has unknown buf_size  \n", pool);
+		return MV_BAD_PARAM;
+	}
+	pBmPool->bufNum += buf_num;
+	return MV_OK;
+}
+
+void mvBmPoolPrint(int pool)
+{
+	MV_BM_POOL *pBmPool;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return;
+	}
+
+	pBmPool = &mvBmPools[pool];
+	if (pBmPool->pVirt == NULL) {
+		mvOsPrintf("bmPool = %d is not created yet\n", pool);
+		return;
+	}
+
+	mvOsPrintf("  %2d:     %4d       %4d       %4d      %p      0x%08x\n",
+						pBmPool->pool, pBmPool->capacity, pBmPool->bufSize, pBmPool->bufNum,
+						pBmPool->pVirt, (unsigned)pBmPool->physAddr);
+}
+
+void mvBmStatus(void)
+{
+	int i;
+
+	mvOsPrintf("BM Pools status\n");
+	mvOsPrintf("pool:    capacity    bufSize    bufNum      virtPtr       physAddr\n");
+	for (i = 0; i < MV_BM_POOLS; i++)
+		mvBmPoolPrint(i);
+}
+
+void mvBmPoolDump(int pool, int mode)
+{
+	MV_U32     regVal;
+	MV_ULONG   *pBufAddr;
+	MV_BM_POOL *pBmPool;
+	int setReadIdx, getReadIdx, setWriteIdx, getWriteIdx, freeBuffs, i;
+
+	/* validate poolId */
+	if ((pool < 0) || (pool >= MV_BM_POOLS)) {
+		mvOsPrintf("bmPoolId = %d is invalid \n", pool);
+		return;
+	}
+
+	pBmPool = &mvBmPools[pool];
+	if (pBmPool->pVirt == NULL) {
+		mvOsPrintf("bmPool = %d is not created yet\n", pool);
+		return;
+	}
+
+	mvOsPrintf("\n[NETA BM: pool=%d, mode=%d]\n", pool, mode);
+
+	mvOsPrintf("poolBase=%p (0x%x), capacity=%d, buf_num=%d, buf_size=%d\n",
+		   pBmPool->pVirt, (unsigned)pBmPool->physAddr, pBmPool->capacity, pBmPool->bufNum, pBmPool->bufSize);
+
+	regVal = MV_REG_READ(MV_BM_POOL_READ_PTR_REG(pool));
+	setReadIdx = ((regVal & MV_BM_POOL_SET_READ_PTR_MASK) >> MV_BM_POOL_SET_READ_PTR_OFFS) / 4;
+	getReadIdx = ((regVal & MV_BM_POOL_GET_READ_PTR_MASK) >> MV_BM_POOL_GET_READ_PTR_OFFS) / 4;
+
+	regVal = MV_REG_READ(MV_BM_POOL_WRITE_PTR_REG(pool));
+	setWriteIdx = ((regVal & MV_BM_POOL_SET_WRITE_PTR_MASK) >> MV_BM_POOL_SET_WRITE_PTR_OFFS) / 4;
+	getWriteIdx = ((regVal & MV_BM_POOL_GET_WRITE_PTR_MASK) >> MV_BM_POOL_GET_WRITE_PTR_OFFS) / 4;
+	if (getWriteIdx >= getReadIdx)
+		freeBuffs = getWriteIdx - getReadIdx;
+	else
+		freeBuffs = (pBmPool->capacity - getReadIdx) + getWriteIdx;
+
+	mvOsPrintf("nextToRead: set=%d, get=%d, nextToWrite: set=%d, get=%d, freeBuffs=%d\n",
+		setReadIdx, getReadIdx, setWriteIdx, getWriteIdx, freeBuffs);
+
+	if (mode > 0) {
+		/* Print the content of BM pool */
+		i = getReadIdx;
+		while (i != getWriteIdx) {
+			pBufAddr = (MV_ULONG *)pBmPool->pVirt + i;
+			mvOsPrintf("%3d. pBufAddr=%p, bufAddr=%08x\n",
+				   i, pBufAddr, (MV_U32)(*pBufAddr));
+			i++;
+			if (i == pBmPool->capacity)
+				i = 0;
+		}
+	}
+}
+
+void mvBmRegs(void)
+{
+	int pool;
+
+	mvOsPrintf("\n\t Hardware Buffer Management Registers:\n");
+
+	mvOsPrintf("MV_BM_CONFIG_REG                : 0x%X = 0x%08x\n",
+		   MV_BM_CONFIG_REG, MV_REG_READ(MV_BM_CONFIG_REG));
+
+	mvOsPrintf("MV_BM_COMMAND_REG               : 0x%X = 0x%08x\n",
+		   MV_BM_COMMAND_REG, MV_REG_READ(MV_BM_COMMAND_REG));
+
+	mvOsPrintf("MV_BM_INTR_CAUSE_REG            : 0x%X = 0x%08x\n",
+		   MV_BM_INTR_CAUSE_REG, MV_REG_READ(MV_BM_INTR_CAUSE_REG));
+
+	mvOsPrintf("MV_BM_INTR_MASK_REG             : 0x%X = 0x%08x\n",
+		   MV_BM_INTR_MASK_REG, MV_REG_READ(MV_BM_INTR_MASK_REG));
+
+	mvOsPrintf("MV_BM_XBAR_01_REG               : 0x%X = 0x%08x\n",
+		   MV_BM_XBAR_01_REG, MV_REG_READ(MV_BM_XBAR_01_REG));
+
+	mvOsPrintf("MV_BM_XBAR_23_REG               : 0x%X = 0x%08x\n",
+		   MV_BM_XBAR_23_REG, MV_REG_READ(MV_BM_XBAR_23_REG));
+
+	for (pool = 0; pool < MV_BM_POOLS; pool++) {
+		mvOsPrintf("\n\t BM Pool #%d registers:\n", pool);
+
+		mvOsPrintf("MV_BM_POOL_BASE_REG             : 0x%X = 0x%08x\n",
+			MV_BM_POOL_BASE_REG(pool), MV_REG_READ(MV_BM_POOL_BASE_REG(pool)));
+
+		mvOsPrintf("MV_BM_POOL_READ_PTR_REG         : 0x%X = 0x%08x\n",
+			MV_BM_POOL_READ_PTR_REG(pool), MV_REG_READ(MV_BM_POOL_READ_PTR_REG(pool)));
+
+		mvOsPrintf("MV_BM_POOL_WRITE_PTR_REG        : 0x%X = 0x%08x\n",
+			MV_BM_POOL_WRITE_PTR_REG(pool), MV_REG_READ(MV_BM_POOL_WRITE_PTR_REG(pool)));
+
+		mvOsPrintf("MV_BM_POOL_SIZE_REG             : 0x%X = 0x%08x\n",
+			MV_BM_POOL_SIZE_REG(pool), MV_REG_READ(MV_BM_POOL_SIZE_REG(pool)));
+	}
+	mvOsPrintf("\n");
+
+	mvOsPrintf("MV_BM_DEBUG_REG                 : 0x%X = 0x%08x\n", MV_BM_DEBUG_REG, MV_REG_READ(MV_BM_DEBUG_REG));
+
+	mvOsPrintf("MV_BM_READ_PTR_REG              : 0x%X = 0x%08x\n",
+		   MV_BM_READ_PTR_REG, MV_REG_READ(MV_BM_READ_PTR_REG));
+
+	mvOsPrintf("MV_BM_WRITE_PTR_REG             : 0x%X = 0x%08x\n",
+		   MV_BM_WRITE_PTR_REG, MV_REG_READ(MV_BM_WRITE_PTR_REG));
+
+	mvOsPrintf("\n");
+
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBm.h b/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBm.h
new file mode 100755
index 0000000..fddc413
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBm.h
@@ -0,0 +1,131 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __mvBm_h__
+#define __mvBm_h__
+
+/* includes */
+#include "mvTypes.h"
+#include "mvCommon.h"
+#include "mvStack.h"
+#include "mv802_3.h"
+
+#include "mvBmRegs.h"
+
+typedef struct {
+	int valid;
+	int longPool;
+	int shortPool;
+	int longBufNum;
+	int shortBufNum;
+
+} MV_BM_CONFIG;
+
+typedef struct {
+	int         pool;
+	int         capacity;
+	int         bufNum;
+	int         bufSize;
+	MV_U32      *pVirt;
+	MV_ULONG    physAddr;
+} MV_BM_POOL;
+
+extern MV_U8 *mvBmVirtBase;
+/* defines */
+
+/* bits[8-9] of address define pool 0-3 */
+#define BM_POOL_ACCESS_OFFS     8
+
+/* INLINE functions */
+static INLINE void mvBmPoolPut(int poolId, MV_ULONG bufPhysAddr)
+{
+	*((MV_ULONG *)((unsigned)mvBmVirtBase | (poolId << BM_POOL_ACCESS_OFFS))) = (MV_ULONG)(MV_32BIT_LE(bufPhysAddr));
+}
+
+static INLINE MV_ULONG mvBmPoolGet(int poolId)
+{
+	MV_U32	bufPhysAddr = *(MV_U32 *)((unsigned)mvBmVirtBase | (poolId << 8));
+
+	return (MV_ULONG)(MV_32BIT_LE(bufPhysAddr));
+}
+
+/* prototypes */
+MV_STATUS mvBmInit(MV_U8 *virtBase);
+void      mvBmConfigSet(MV_U32 mask);
+void      mvBmConfigClear(MV_U32 mask);
+MV_STATUS mvBmControl(MV_COMMAND cmd);
+MV_STATE  mvBmStateGet(void);
+void      mvBmPoolTargetSet(int pool, MV_U8 targetId, MV_U8 attr);
+void      mvBmPoolEnable(int pool);
+void      mvBmPoolDisable(int pool);
+MV_BOOL   mvBmPoolIsEnabled(int pool);
+MV_STATUS mvBmPoolInit(int pool, void *virtPoolBase, MV_ULONG physPoolBase, int capacity);
+MV_STATUS mvBmPoolBufNumUpdate(int pool, int buf_num);
+MV_STATUS mvBmPoolBufSizeSet(int pool, int buf_size);
+void      mvBmRegs(void);
+void      mvBmStatus(void);
+void      mvBmPoolDump(int pool, int mode);
+void      mvBmPoolPrint(int pool);
+
+#endif /* __mvBm_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBmRegs.h b/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBmRegs.h
new file mode 100755
index 0000000..38499db
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/bm/mvBmRegs.h
@@ -0,0 +1,231 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __mvBmRegs_h__
+#define __mvBmRegs_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define MV_BM_POOLS                 4
+#define MV_BM_POOL_CAP_MAX          (16*1024 - MV_BM_POOL_PTR_ALIGN/4)
+#define MV_BM_POOL_CAP_MIN          128
+#define MV_BM_POOL_PTR_ALIGN        128
+
+/* BM Configuration Register */
+#define MV_BM_CONFIG_REG                (MV_BM_REG_BASE + 0x0)
+
+#define MV_BM_SRC_BURST_SIZE_OFFS       0
+#define MV_BM_SRC_BURST_SIZE_MASK       (3 << MV_BM_SRC_BURST_SIZE_OFFS)
+#define MV_BM_SRC_BURST_SIZE_128B       (0 << MV_BM_SRC_BURST_SIZE_OFFS)
+#define MV_BM_SRC_BURST_SIZE_32B        (1 << MV_BM_SRC_BURST_SIZE_OFFS)
+
+#define MV_BM_DST_BURST_SIZE_OFFS       2
+#define MV_BM_DST_BURST_SIZE_MASK       (3 << MV_BM_DST_BURST_SIZE_OFFS)
+#define MV_BM_DST_BURST_SIZE_128B       (0 << MV_BM_DST_BURST_SIZE_OFFS)
+#define MV_BM_DST_BURST_SIZE_32B        (1 << MV_BM_DST_BURST_SIZE_OFFS)
+
+#define MV_BM_DST_SWAP_BIT              4
+#define MV_BM_DST_SWAP_MASK             (1 << MV_BM_DST_SWAP_BIT)
+
+#define MV_BM_SRC_SWAP_BIT              5
+#define MV_BM_SRC_SWAP_MASK             (1 << MV_BM_SRC_SWAP_BIT)
+
+#define MV_BM_LOW_THRESH_OFFS           8
+#define MV_BM_LOW_THRESH_MASK           (0xF << MV_BM_LOW_THRESH_OFFS)
+#define MV_BM_LOW_THRESH_VALUE(val)     ((val) << MV_BM_LOW_THRESH_OFFS)
+
+#define MV_BM_HIGH_THRESH_OFFS          12
+#define MV_BM_HIGH_THRESH_MASK          (0xF << MV_BM_HIGH_THRESH_OFFS)
+#define MV_BM_HIGH_THRESH_VALUE(val)    ((val) << MV_BM_HIGH_THRESH_OFFS)
+
+#define MV_BM_MAX_IN_BURST_SIZE_OFFS    17
+#define MV_BM_MAX_IN_BURST_SIZE_MASK    (3 << MV_BM_MAX_IN_BURST_SIZE_OFFS)
+#define MV_BM_MAX_IN_BURST_SIZE_32BP    (0 << MV_BM_MAX_IN_BURST_SIZE_OFFS)
+#define MV_BM_MAX_IN_BURST_SIZE_24BP    (1 << MV_BM_MAX_IN_BURST_SIZE_OFFS)
+#define MV_BM_MAX_IN_BURST_SIZE_16BP    (2 << MV_BM_MAX_IN_BURST_SIZE_OFFS)
+#define MV_BM_MAX_IN_BURST_SIZE_8BP     (3 << MV_BM_MAX_IN_BURST_SIZE_OFFS)
+
+#define MV_BM_EMPTY_LIMIT_BIT			19
+#define MV_BM_EMPTY_LIMIT_MASK			(1 << MV_BM_EMPTY_LIMIT_BIT)
+
+
+/* BM Activation Register */
+#define MV_BM_COMMAND_REG               (MV_BM_REG_BASE + 0x4)
+
+#define MV_BM_START_BIT                 0
+#define MV_BM_START_MASK                (1 << MV_BM_START_BIT)
+
+#define MV_BM_STOP_BIT                  1
+#define MV_BM_STOP_MASK                 (1 << MV_BM_STOP_BIT)
+
+#define MV_BM_PAUSE_BIT                 2
+#define MV_BM_PAUSE_MASK                (1 << MV_BM_PAUSE_BIT)
+
+#define MV_BM_STATUS_OFFS               4
+#define MV_BM_STATUS_ALL_MASK           (0x3)
+#define MV_BM_STATUS_NOT_ACTIVE         (0x0)
+#define MV_BM_STATUS_ACTIVE             (0x1)
+#define MV_BM_STATUS_PAUSED             (0x2)
+#define MV_BM_STATUS_MASK(status)       ((status) << MV_BM_STATUS_OFFS)
+
+/* BM Xbar interface Register */
+#define MV_BM_XBAR_01_REG               (MV_BM_REG_BASE + 0x8)
+#define MV_BM_XBAR_23_REG               (MV_BM_REG_BASE + 0xC)
+
+#define MV_BM_XBAR_POOL_REG(pool)       (((pool) < 2) ? MV_BM_XBAR_01_REG : MV_BM_XBAR_23_REG)
+
+#define MV_BM_TARGET_ID_OFFS(pool)      (((pool) & 1) ? 16 : 0)
+#define MV_BM_TARGET_ID_MASK(pool)      (0xF << MV_BM_TARGET_ID_OFFS(pool))
+#define MV_BM_TARGET_ID_VAL(pool, id)   ((id) << MV_BM_TARGET_ID_OFFS(pool))
+
+#define MV_BM_XBAR_ATTR_OFFS(pool)      (((pool) & 1) ? 20 : 4)
+#define MV_BM_XBAR_ATTR_MASK(pool)      (0xFF << MV_BM_XBAR_ATTR_OFFS(pool))
+#define MV_BM_XBAR_ATTR_VAL(pool, attr) ((attr) << MV_BM_XBAR_ATTR_OFFS(pool))
+
+/* Address of External Buffer Pointers Pool Register */
+#define MV_BM_POOL_BASE_REG(pool)       (MV_BM_REG_BASE + 0x10 + ((pool) << 4))
+
+#define MV_BM_POOL_ENABLE_BIT           0
+#define MV_BM_POOL_ENABLE_MASK          (1 << MV_BM_POOL_ENABLE_BIT)
+
+#define MV_BM_POOL_BASE_ADDR_OFFS       2
+#define MV_BM_POOL_BASE_ADDR_MASK       (0x3FFFFFFF << MV_BM_POOL_BASE_ADDR_OFFS)
+
+/* External Buffer Pointers Pool RD pointer Register */
+#define MV_BM_POOL_READ_PTR_REG(pool)   (MV_BM_REG_BASE + 0x14 + ((pool) << 4))
+
+#define MV_BM_POOL_SET_READ_PTR_OFFS    0
+#define MV_BM_POOL_SET_READ_PTR_MASK    (0xFFFC << MV_BM_POOL_SET_READ_PTR_OFFS)
+#define MV_BM_POOL_SET_READ_PTR(val)    ((val) << MV_BM_POOL_SET_READ_PTR_OFFS)
+
+#define MV_BM_POOL_GET_READ_PTR_OFFS    16
+#define MV_BM_POOL_GET_READ_PTR_MASK    (0xFFFC << MV_BM_POOL_GET_READ_PTR_OFFS)
+
+
+/* External Buffer Pointers Pool WR pointer */
+#define MV_BM_POOL_WRITE_PTR_REG(pool)  (MV_BM_REG_BASE + 0x18 + ((pool) << 4))
+
+#define MV_BM_POOL_SET_WRITE_PTR_OFFS   0
+#define MV_BM_POOL_SET_WRITE_PTR_MASK   (0xFFFC << MV_BM_POOL_SET_WRITE_PTR_OFFS)
+#define MV_BM_POOL_SET_WRITE_PTR(val)   ((val) << MV_BM_POOL_SET_WRITE_PTR_OFFS)
+
+#define MV_BM_POOL_GET_WRITE_PTR_OFFS   16
+#define MV_BM_POOL_GET_WRITE_PTR_MASK   (0xFFFC << MV_BM_POOL_GET_WRITE_PTR_OFFS)
+
+/* External Buffer Pointers Pool Size Register */
+#define MV_BM_POOL_SIZE_REG(pool)       (MV_BM_REG_BASE + 0x1C + ((pool) << 4))
+
+#define MV_BM_POOL_SIZE_OFFS            0
+#define MV_BM_POOL_SIZE_MASK            (0x3FFF << MV_BM_POOL_SIZE_OFFS)
+#define MV_BM_POOL_SIZE_VAL(size)       ((size) << MV_BM_POOL_SIZE_OFFS)
+
+
+/* BM Interrupt Cause Register */
+#define MV_BM_INTR_CAUSE_REG            (MV_BM_REG_BASE + 0x50)
+
+#define MV_BM_CAUSE_FREE_FAIL_BIT(p)    (0 + ((p) * 6))
+#define MV_BM_CAUSE_FREE_FAIL_MASK(p)   (1 << MV_BM_CAUSE_FREE_FAIL_BIT(p))
+
+#define MV_BM_CAUSE_ALLOC_FAIL_BIT(p)   (1 + ((p) * 6))
+#define MV_BM_CAUSE_ALLOC_FAIL_MASK(p)  (1 << MV_BM_CAUSE_ALLOC_FAIL_BIT(p))
+
+#define MV_BM_CAUSE_POOL_EMPTY_BIT(p)   (2 + ((p) * 6))
+#define MV_BM_CAUSE_POOL_EMPTY_MASK(p)  (1 << MV_BM_CAUSE_POOL_EMPTY_BIT(p))
+
+#define MV_BM_CAUSE_POOL_FULL_BIT(p)    (3 + ((p) * 6))
+#define MV_BM_CAUSE_POOL_FULL_MASK(p)   (1 << MV_BM_CAUSE_POOL_FULL_BIT(p))
+
+#define MV_BM_CAUSE_INT_PAR_ERR_BIT     27
+#define MV_BM_CAUSE_INT_PAR_ERR_MASK    (1 << MV_BM_CAUSE_INT_PAR_ERR_MASK)
+
+#define MV_BM_CAUSE_XBAR_PAR_ERR_BIT    28
+#define MV_BM_CAUSE_XBAR_PAR_ERR_MASK   (1 << MV_BM_CAUSE_XBAR_PAR_ERR_MASK)
+
+#define MV_BM_CAUSE_STOPPED_BIT         29
+#define MV_BM_CAUSE_STOPPED_MASK        (1 << MV_BM_CAUSE_STOPPED_MASK)
+
+#define MV_BM_CAUSE_PAUSED_BIT          30
+#define MV_BM_CAUSE_PAUSED_MASK         (1 << MV_BM_CAUSE_PAUSED_MASK)
+
+#define MV_BM_CAUSE_SUMMARY_BIT         31
+#define MV_BM_CAUSE_SUMMARY_MASK        (1 << MV_BM_CAUSE_SUMMARY_MASK)
+
+/* BM interrupt Mask Register */
+#define MV_BM_INTR_MASK_REG             (MV_BM_REG_BASE + 0x54)
+
+#define MV_BM_DEBUG_REG                 (MV_BM_REG_BASE + 0x60)
+#define MV_BM_READ_PTR_REG              (MV_BM_REG_BASE + 0x64)
+#define MV_BM_WRITE_PTR_REG             (MV_BM_REG_BASE + 0x68)
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __mvBmRegs_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvEthRegs.h b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvEthRegs.h
new file mode 100755
index 0000000..dd2100b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvEthRegs.h
@@ -0,0 +1,644 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __INCmvEthRegsh
+#define __INCmvEthRegsh
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "mvNetaRegs.h"
+
+#define MV_ETH_MH_SIZE					2
+#define MV_ETH_CRC_SIZE                 4
+
+#define ETH_MAX_DECODE_WIN              6
+#define ETH_MAX_HIGH_ADDR_REMAP_WIN     4
+
+/****************************************/
+/*        Ethernet Unit Registers       */
+/****************************************/
+#define ETH_REG_BASE(port)                  MV_ETH_REGS_BASE(port)
+
+#define ETH_PHY_ADDR_REG(port)              (ETH_REG_BASE(port) + 0x2000)
+#define ETH_SMI_REG(port)                   (ETH_REG_BASE(port) + 0x2004)
+#define ETH_UNIT_DEF_ADDR_REG(port)         (ETH_REG_BASE(port) + 0x2008)
+#define ETH_UNIT_DEF_ID_REG(port)           (ETH_REG_BASE(port) + 0x200c)
+#define ETH_UNIT_RESERVED(port)             (ETH_REG_BASE(port) + 0x2014)
+#define ETH_UNIT_INTR_CAUSE_REG(port)       (ETH_REG_BASE(port) + 0x2080)
+#define ETH_UNIT_INTR_MASK_REG(port)        (ETH_REG_BASE(port) + 0x2084)
+
+#define ETH_UNIT_ERROR_ADDR_REG(port)       (ETH_REG_BASE(port) + 0x2094)
+#define ETH_UNIT_INT_ADDR_ERROR_REG(port)   (ETH_REG_BASE(port) + 0x2098)
+
+/* Ethernet Unit Control (EUC) register */
+#define ETH_UNIT_CONTROL_REG(port)          (ETH_REG_BASE(port) + 0x20B0)
+
+#define ETH_PHY_POLLING_ENABLE_BIT          1
+#define ETH_PHY_POLLING_ENABLE_MASK        (1 << ETH_PHY_POLLING_ENABLE_BIT)
+
+#define ETH_UNIT_PORT_RESET_BIT             24
+#define ETH_UNIT_PORT_RESET_MASK            (1 << ETH_UNIT_PORT_RESET_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+/**** Address decode registers ****/
+
+#define ETH_WIN_BASE_REG(port, win)         (ETH_REG_BASE(port) + 0x2200 + ((win) << 3))
+#define ETH_WIN_SIZE_REG(port, win)         (ETH_REG_BASE(port) + 0x2204 + ((win) << 3))
+#define ETH_WIN_REMAP_REG(port, win)        (ETH_REG_BASE(port) + 0x2280 + ((win) << 2))
+#define ETH_BASE_ADDR_ENABLE_REG(port)      (ETH_REG_BASE(port) + 0x2290)
+#define ETH_ACCESS_PROTECT_REG(port)        (ETH_REG_BASE(port) + 0x2294)
+
+/* The target associated with this window*/
+#define ETH_WIN_TARGET_OFFS                 0
+#define ETH_WIN_TARGET_MASK                 (0xf << ETH_WIN_TARGET_OFFS)
+/* The target attributes associated with window */
+#define ETH_WIN_ATTR_OFFS                   8
+#define ETH_WIN_ATTR_MASK                   (0xff << ETH_WIN_ATTR_OFFS)
+
+/* The Base address associated with window */
+#define ETH_WIN_BASE_OFFS		            16
+#define ETH_WIN_BASE_MASK		            (0xFFFF << ETH_WIN_BASE_OFFS)
+
+#define ETH_WIN_SIZE_OFFS		            16
+#define ETH_WIN_SIZE_MASK		            (0xFFFF << ETH_WIN_SIZE_OFFS)
+
+ /* Ethernet Port Access Protect Register (EPAPR) */
+#define ETH_PROT_NO_ACCESS                  0
+#define ETH_PROT_READ_ONLY                  1
+#define ETH_PROT_FULL_ACCESS                3
+#define ETH_PROT_WIN_OFFS(winNum)           (2 * (winNum))
+#define ETH_PROT_WIN_MASK(winNum)           (0x3 << ETH_PROT_WIN_OFFS(winNum))
+/*-----------------------------------------------------------------------------------------------*/
+
+
+/***** Port Configuration reg (PxCR) *****/
+#define ETH_PORT_CONFIG_REG(port)           (ETH_REG_BASE(port) + 0x2400)
+
+#define ETH_UNICAST_PROMISCUOUS_MODE_BIT    0
+#define ETH_UNICAST_PROMISCUOUS_MODE_MASK   (1 << ETH_UNICAST_PROMISCUOUS_MODE_BIT)
+
+#define ETH_DEF_RX_QUEUE_OFFSET             1
+#define ETH_DEF_RX_QUEUE_ALL_MASK           (0x7 << ETH_DEF_RX_QUEUE_OFFSET)
+#define ETH_DEF_RX_QUEUE_MASK(queue)        ((queue) << ETH_DEF_RX_QUEUE_OFFSET)
+
+#define ETH_DEF_RX_ARP_QUEUE_OFFSET         4
+#define ETH_DEF_RX_ARP_QUEUE_ALL_MASK       (0x7 << ETH_DEF_RX_ARP_QUEUE_OFFSET)
+#define ETH_DEF_RX_ARP_QUEUE_MASK(queue)    ((queue) << ETH_DEF_RX_ARP_QUEUE_OFFSET)
+
+#define ETH_REJECT_NOT_IP_ARP_BCAST_BIT     7
+#define ETH_REJECT_NOT_IP_ARP_BCAST_MASK    (1 << ETH_REJECT_NOT_IP_ARP_BCAST_BIT)
+
+#define ETH_REJECT_IP_BCAST_BIT             8
+#define ETH_REJECT_IP_BCAST_MASK            (1 << ETH_REJECT_IP_BCAST_BIT)
+
+#define ETH_REJECT_ARP_BCAST_BIT            9
+#define ETH_REJECT_ARP_BCAST_MASK           (1 << ETH_REJECT_ARP_BCAST_BIT)
+
+#define ETH_TX_NO_SET_ERROR_SUMMARY_BIT     12
+#define ETH_TX_NO_SET_ERROR_SUMMARY_MASK    (1 << ETH_TX_NO_SET_ERROR_SUMMARY_BIT)
+
+#define ETH_CAPTURE_TCP_FRAMES_ENABLE_BIT   14
+#define ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK  (1 << ETH_CAPTURE_TCP_FRAMES_ENABLE_BIT)
+
+#define ETH_CAPTURE_UDP_FRAMES_ENABLE_BIT   15
+#define ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK  (1 << ETH_CAPTURE_UDP_FRAMES_ENABLE_BIT)
+
+#define ETH_DEF_RX_TCP_QUEUE_OFFSET         16
+#define ETH_DEF_RX_TCP_QUEUE_ALL_MASK       (0x7 << ETH_DEF_RX_TCP_QUEUE_OFFSET)
+#define ETH_DEF_RX_TCP_QUEUE_MASK(queue)    ((queue) << ETH_DEF_RX_TCP_QUEUE_OFFSET)
+
+#define ETH_DEF_RX_UDP_QUEUE_OFFSET         19
+#define ETH_DEF_RX_UDP_QUEUE_ALL_MASK       (0x7 << ETH_DEF_RX_UDP_QUEUE_OFFSET)
+#define ETH_DEF_RX_UDP_QUEUE_MASK(queue)    ((queue) << ETH_DEF_RX_UDP_QUEUE_OFFSET)
+
+#define ETH_DEF_RX_BPDU_QUEUE_OFFSET        22
+#define ETH_DEF_RX_BPDU_QUEUE_ALL_MASK      (0x7 << ETH_DEF_RX_BPDU_QUEUE_OFFSET)
+#define ETH_DEF_RX_BPDU_QUEUE_MASK(queue)   ((queue) << ETH_DEF_RX_BPDU_QUEUE_OFFSET)
+
+#define ETH_RX_CHECKSUM_MODE_OFFSET         25
+#define ETH_RX_CHECKSUM_NO_PSEUDO_HDR       (0 << ETH_RX_CHECKSUM_MODE_OFFSET)
+#define ETH_RX_CHECKSUM_WITH_PSEUDO_HDR     (1 << ETH_RX_CHECKSUM_MODE_OFFSET)
+/*-----------------------------------------------------------------------------------------------*/
+
+/***** Port Configuration Extend reg (PxCXR) *****/
+#define ETH_PORT_CONFIG_EXTEND_REG(port)    (ETH_REG_BASE(port) + 0x2404)
+
+#define ETH_CAPTURE_SPAN_BPDU_ENABLE_BIT    1
+#define ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK   (1 << ETH_CAPTURE_SPAN_BPDU_ENABLE_BIT)
+
+#define ETH_TX_DISABLE_GEN_CRC_BIT          3
+#define ETH_TX_DISABLE_GEN_CRC_MASK         (1 << ETH_TX_DISABLE_GEN_CRC_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_VLAN_ETHER_TYPE_REG(port)       (ETH_REG_BASE(port) + 0x2410)
+#define ETH_MAC_ADDR_LOW_REG(port)          (ETH_REG_BASE(port) + 0x2414)
+#define ETH_MAC_ADDR_HIGH_REG(port)         (ETH_REG_BASE(port) + 0x2418)
+
+
+/***** Port Sdma Configuration reg (SDCR) *****/
+#define ETH_SDMA_CONFIG_REG(port)           (ETH_REG_BASE(port) + 0x241c)
+
+#define ETH_RX_FRAME_INTERRUPT_BIT          0
+#define ETH_RX_FRAME_INTERRUPT_MASK         (1 << ETH_RX_FRAME_INTERRUPT_BIT)
+
+#define ETH_BURST_SIZE_1_64BIT_VALUE        0
+#define ETH_BURST_SIZE_2_64BIT_VALUE        1
+#define ETH_BURST_SIZE_4_64BIT_VALUE        2
+#define ETH_BURST_SIZE_8_64BIT_VALUE        3
+#define ETH_BURST_SIZE_16_64BIT_VALUE       4
+
+#define ETH_RX_BURST_SIZE_OFFSET            1
+#define ETH_RX_BURST_SIZE_ALL_MASK          (0x7 << ETH_RX_BURST_SIZE_OFFSET)
+#define ETH_RX_BURST_SIZE_MASK(burst)       ((burst) << ETH_RX_BURST_SIZE_OFFSET)
+
+#define ETH_RX_NO_DATA_SWAP_BIT             4
+#define ETH_RX_NO_DATA_SWAP_MASK            (1 << ETH_RX_NO_DATA_SWAP_BIT)
+#define ETH_RX_DATA_SWAP_MASK               (0 << ETH_RX_NO_DATA_SWAP_BIT)
+
+#define ETH_TX_NO_DATA_SWAP_BIT             5
+#define ETH_TX_NO_DATA_SWAP_MASK            (1 << ETH_TX_NO_DATA_SWAP_BIT)
+#define ETH_TX_DATA_SWAP_MASK               (0 << ETH_TX_NO_DATA_SWAP_BIT)
+
+#define ETH_DESC_SWAP_BIT                   6
+#define ETH_DESC_SWAP_MASK                  (1 << ETH_DESC_SWAP_BIT)
+#define ETH_NO_DESC_SWAP_MASK               (0 << ETH_DESC_SWAP_BIT)
+
+#define ETH_TX_BURST_SIZE_OFFSET            22
+#define ETH_TX_BURST_SIZE_ALL_MASK          (0x7 << ETH_TX_BURST_SIZE_OFFSET)
+#define ETH_TX_BURST_SIZE_MASK(burst)       ((burst) << ETH_TX_BURST_SIZE_OFFSET)
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_DIFF_SERV_PRIO_REG(port, code)  (ETH_REG_BASE(port) + 0x2420  + ((code) << 2))
+
+/* Port Serial Control0 register (PSC0) */
+#define ETH_PORT_SERIAL_CTRL_REG(port)      (ETH_REG_BASE(port) + 0x243c)
+
+#define ETH_TX_FC_MODE_OFFSET               5
+#define ETH_TX_FC_MODE_MASK                 (3 << ETH_TX_FC_MODE_OFFSET)
+#define ETH_TX_FC_NO_PAUSE                  (0 << ETH_TX_FC_MODE_OFFSET)
+#define ETH_TX_FC_SEND_PAUSE                (1 << ETH_TX_FC_MODE_OFFSET)
+
+#define ETH_TX_BP_MODE_OFFSET               7
+#define ETH_TX_BP_MODE_MASK                 (3 << ETH_TX_BP_MODE_OFFSET)
+#define ETH_TX_BP_NO_JAM                    (0 << ETH_TX_BP_MODE_OFFSET)
+#define ETH_TX_BP_SEND_JAM                  (1 << ETH_TX_BP_MODE_OFFSET)
+
+#define ETH_RETRANSMIT_FOREVER_BIT          11
+#define ETH_RETRANSMIT_FOREVER_MASK         (1 << ETH_RETRANSMIT_FOREVER_BIT)
+
+#define ETH_DTE_ADVERT_BIT                  14
+#define ETH_DTE_ADVERT_MASK                 (1 << ETH_DTE_ADVERT_BIT)
+
+/* Other bits are different for new GMAC and old GMAC modules */
+#ifdef MV_ETH_GMAC_NEW
+
+#define ETH_IGNORE_RX_ERR_BIT               28
+#define ETH_IGNORE_RX_ERR_MASK              (1 << ETH_IGNORE_RX_ERR_BIT)
+
+#define ETH_IGNORE_COL_BIT                  29
+#define ETH_IGNORE_COL_MASK                 (1 << ETH_IGNORE_COL_BIT)
+
+#define ETH_IGNORE_CARRIER_SENSE_BIT        30
+#define ETH_IGNORE_CARRIER_SENSE_MASK       (1 << ETH_IGNORE_CARRIER_SENSE_BIT)
+
+#else /* Old GMAC */
+
+#define ETH_PORT_ENABLE_BIT                 0
+#define ETH_PORT_ENABLE_MASK                (1 << ETH_PORT_ENABLE_BIT)
+
+#define ETH_FORCE_LINK_PASS_BIT             1
+#define ETH_FORCE_LINK_PASS_MASK            (1 << ETH_FORCE_LINK_PASS_BIT)
+
+#define ETH_DISABLE_DUPLEX_AUTO_NEG_BIT     2
+#define ETH_DISABLE_DUPLEX_AUTO_NEG_MASK    (1 << ETH_DISABLE_DUPLEX_AUTO_NEG_BIT)
+
+#define ETH_DISABLE_FC_AUTO_NEG_BIT         3
+#define ETH_DISABLE_FC_AUTO_NEG_MASK        (1 << ETH_DISABLE_FC_AUTO_NEG_BIT)
+
+#define ETH_ADVERTISE_SYM_FC_BIT            4
+#define ETH_ADVERTISE_SYM_FC_MASK           (1 << ETH_ADVERTISE_SYM_FC_BIT)
+
+#define ETH_DO_NOT_FORCE_LINK_FAIL_BIT      10
+#define ETH_DO_NOT_FORCE_LINK_FAIL_MASK     (1 << ETH_DO_NOT_FORCE_LINK_FAIL_BIT)
+
+#define ETH_DISABLE_SPEED_AUTO_NEG_BIT      13
+#define ETH_DISABLE_SPEED_AUTO_NEG_MASK     (1 << ETH_DISABLE_SPEED_AUTO_NEG_BIT)
+
+#define ETH_MAX_RX_PACKET_SIZE_OFFSET       17
+#define ETH_MAX_RX_PACKET_SIZE_MASK         (7 << ETH_MAX_RX_PACKET_SIZE_OFFSET)
+#define ETH_MAX_RX_PACKET_1518BYTE          (0 << ETH_MAX_RX_PACKET_SIZE_OFFSET)
+#define ETH_MAX_RX_PACKET_1522BYTE          (1 << ETH_MAX_RX_PACKET_SIZE_OFFSET)
+#define ETH_MAX_RX_PACKET_1552BYTE          (2 << ETH_MAX_RX_PACKET_SIZE_OFFSET)
+#define ETH_MAX_RX_PACKET_9022BYTE          (3 << ETH_MAX_RX_PACKET_SIZE_OFFSET)
+#define ETH_MAX_RX_PACKET_9192BYTE          (4 << ETH_MAX_RX_PACKET_SIZE_OFFSET)
+#define ETH_MAX_RX_PACKET_9700BYTE          (5 << ETH_MAX_RX_PACKET_SIZE_OFFSET)
+
+#define ETH_SET_FULL_DUPLEX_BIT             21
+#define ETH_SET_FULL_DUPLEX_MASK            (1 << ETH_SET_FULL_DUPLEX_BIT)
+
+#define ETH_SET_FLOW_CTRL_BIT               22
+#define ETH_SET_FLOW_CTRL_MASK              (1 << ETH_SET_FLOW_CTRL_BIT)
+
+#define ETH_SET_GMII_SPEED_1000_BIT         23
+#define ETH_SET_GMII_SPEED_1000_MASK        (1 << ETH_SET_GMII_SPEED_1000_BIT)
+
+#define ETH_SET_MII_SPEED_100_BIT           24
+#define ETH_SET_MII_SPEED_100_MASK          (1 << ETH_SET_MII_SPEED_100_BIT)
+
+#endif /* MV_ETH_GMAC_NEW */
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_VLAN_TAG_TO_PRIO_REG(port)      (ETH_REG_BASE(port) + 0x2440)
+
+/* Ethernet Type Priority register */
+#define ETH_TYPE_PRIO_REG(port)             (ETH_REG_BASE(port) + 0x24BC)
+
+#define ETH_TYPE_PRIO_ENABLE_BIT            0
+#define ETH_TYPE_PRIO_FORCE_BIT             1
+
+#define ETH_TYPE_PRIO_RXQ_OFFS              2
+#define ETH_TYPE_PRIO_RXQ_ALL_MASK          (0x7 << ETH_TYPE_PRIO_RXQ_OFFS)
+#define ETH_TYPE_PRIO_RXQ_MASK(rxq)         ((rxq) << ETH_TYPE_PRIO_RXQ_OFFS)
+
+#define ETH_TYPE_PRIO_VALUE_OFFS            5
+#define ETH_TYPE_PRIO_VALUE_ALL_MASK        (0xFFFF << ETH_TYPE_PRIO_VALUE_OFFS)
+#define ETH_TYPE_PRIO_VALUE_MASK(type)      (type << ETH_TYPE_PRIO_VALUE_OFFS)
+
+#define ETH_FORCE_UNICAST_BIT               21
+#define ETH_FORCE_UNICAST_MASK              (1 << ETH_FORCE_UNICAST_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+/***** Ethernet Port Status reg (PSR) *****/
+#define ETH_PORT_STATUS_REG(port)           (ETH_REG_BASE(port) + 0x2444)
+
+/* Other bits are different for new GMAC and old GMAC modules */
+#ifdef MV_ETH_GMAC_NEW
+
+#define ETH_TX_IN_PROGRESS_OFFS             0
+#define ETH_TX_IN_PROGRESS_MASK(txp)        (1 << ((txp) + ETH_TX_IN_PROGRESS_OFFS))
+#define ETH_TX_IN_PROGRESS_ALL_MASK         (0xFF << ETH_TX_IN_PROGRESS_OFFS)
+
+#define ETH_TX_FIFO_EMPTY_OFFS              8
+#define ETH_TX_FIFO_EMPTY_MASK(txp)         (1 << ((txp) + ETH_TX_FIFO_EMPTY_OFFS))
+#define ETH_TX_FIFO_EMPTY_ALL_MASK          (0xFF << ETH_TX_FIFO_EMPTY_OFFS)
+
+#define ETH_RX_FIFO_EMPTY_BIT               16
+#define ETH_RX_FIFO_EMPTY_MASK              (1 << ETH_RX_FIFO_EMPTY_BIT)
+
+#else /* Old GMAC */
+
+#define ETH_LINK_UP_BIT                     1
+#define ETH_LINK_UP_MASK                    (1 << ETH_LINK_UP_BIT)
+
+#define ETH_FULL_DUPLEX_BIT                 2
+#define ETH_FULL_DUPLEX_MASK                (1 << ETH_FULL_DUPLEX_BIT)
+
+#define ETH_FLOW_CTRL_ENABLED_BIT        	3
+#define ETH_FLOW_CTRL_ENABLED_MASK       	(1 << ETH_FLOW_CTRL_ENABLED_BIT)
+
+#define ETH_GMII_SPEED_1000_BIT             4
+#define ETH_GMII_SPEED_1000_MASK            (1 << ETH_GMII_SPEED_1000_BIT)
+
+#define ETH_MII_SPEED_100_BIT               5
+#define ETH_MII_SPEED_100_MASK              (1 << ETH_MII_SPEED_100_BIT)
+
+#define ETH_TX_IN_PROGRESS_BIT              7
+#define ETH_TX_IN_PROGRESS_MASK             (1 << ETH_TX_IN_PROGRESS_BIT)
+
+#define ETH_TX_FIFO_EMPTY_BIT               10
+#define ETH_TX_FIFO_EMPTY_MASK              (1 << ETH_TX_FIFO_EMPTY_BIT)
+
+#define ETH_RX_FIFO_EMPTY_BIT               12
+#define ETH_RX_FIFO_EMPTY_MASK              (1 << ETH_RX_FIFO_EMPTY_BIT)
+
+#define PON_TX_IN_PROGRESS_OFFS             0
+#define PON_TX_IN_PROGRESS_MASK(txp)        (1 << ((txp) + PON_TX_IN_PROGRESS_OFFS))
+#define PON_TX_IN_PROGRESS_ALL_MASK         (0xFF << PON_TX_IN_PROGRESS_OFFS)
+
+#define PON_TX_FIFO_EMPTY_OFFS              8
+#define PON_TX_FIFO_EMPTY_MASK(txp)         (1 << ((txp) + PON_TX_FIFO_EMPTY_OFFS))
+#define PON_TX_FIFO_EMPTY_ALL_MASK          (0xFF << PON_TX_FIFO_EMPTY_OFFS)
+
+#endif /* MV_ETH_GMAC_NEW */
+/*-----------------------------------------------------------------------------------------------*/
+
+
+/***** Transmit Queue Command (TxQC) register *****/
+#define ETH_TX_QUEUE_COMMAND_REG(p, txp)    (NETA_TX_REG_BASE((p), (txp)) + 0x0048)
+
+#define ETH_TXQ_ENABLE_OFFSET               0
+#define ETH_TXQ_ENABLE_MASK                 (0x000000FF << ETH_TXQ_ENABLE_OFFSET)
+
+#define ETH_TXQ_DISABLE_OFFSET              8
+#define ETH_TXQ_DISABLE_MASK                (0x000000FF << ETH_TXQ_DISABLE_OFFSET)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Marvell Header Register */
+#define ETH_PORT_MARVELL_HEADER_REG(port)   (ETH_REG_BASE(port) + 0x2454)
+
+#define ETH_MH_EN_BIT                       0
+#define ETH_MH_EN_MASK                      (1 << ETH_MH_EN_BIT)
+
+#define ETH_DSA_EN_OFFS                     10
+#define ETH_DSA_EN_MASK                     (3 << ETH_DSA_EN_OFFS)
+#define ETH_DSA_MASK                        (1 << ETH_DSA_EN_OFFS)
+#define ETH_DSA_EXT_MASK                    (2 << ETH_DSA_EN_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Ethernet Cause Register */
+#define ETH_INTR_CAUSE_REG(port)            (ETH_REG_BASE(port) + 0x2460)
+
+#define ETH_CAUSE_RX_READY_SUM_BIT          0
+#define ETH_CAUSE_EXTEND_BIT                1
+
+#define ETH_CAUSE_RX_READY_OFFSET           2
+#define ETH_CAUSE_RX_READY_BIT(queue)       (ETH_CAUSE_RX_READY_OFFSET + (queue))
+#define ETH_CAUSE_RX_READY_MASK(queue)      (1 << (ETH_CAUSE_RX_READY_BIT(queue)))
+
+#define ETH_CAUSE_RX_ERROR_SUM_BIT          10
+#define ETH_CAUSE_RX_ERROR_OFFSET           11
+#define ETH_CAUSE_RX_ERROR_BIT(queue)       (ETH_CAUSE_RX_ERROR_OFFSET + (queue))
+#define ETH_CAUSE_RX_ERROR_MASK(queue)      (1 << (ETH_CAUSE_RX_ERROR_BIT(queue)))
+
+#define ETH_CAUSE_TX_END_BIT                19
+#define ETH_CAUSE_SUM_BIT                   31
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Ethernet Cause Extended Register */
+#define ETH_INTR_CAUSE_EXT_REG(port)        (ETH_REG_BASE(port) + 0x2464)
+
+#define ETH_CAUSE_TX_BUF_OFFSET             0
+#define ETH_CAUSE_TX_BUF_BIT(queue)         (ETH_CAUSE_TX_BUF_OFFSET + (queue))
+#define ETH_CAUSE_TX_BUF_MASK(queue)        (1 << (ETH_CAUSE_TX_BUF_BIT(queue)))
+
+#define ETH_CAUSE_TX_ERROR_OFFSET           8
+#define ETH_CAUSE_TX_ERROR_BIT(queue)       (ETH_CAUSE_TX_ERROR_OFFSET + (queue))
+#define ETH_CAUSE_TX_ERROR_MASK(queue)      (1 << (ETH_CAUSE_TX_ERROR_BIT(queue)))
+
+#define ETH_CAUSE_PHY_STATUS_CHANGE_BIT     16
+#define ETH_CAUSE_RX_OVERRUN_BIT            18
+#define ETH_CAUSE_TX_UNDERRUN_BIT           19
+#define ETH_CAUSE_LINK_STATE_CHANGE_BIT     20
+#define ETH_CAUSE_INTERNAL_ADDR_ERR_BIT     23
+#define ETH_CAUSE_EXTEND_SUM_BIT            31
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_INTR_MASK_REG(port)             (ETH_REG_BASE(port) + 0x2468)
+#define ETH_INTR_MASK_EXT_REG(port)         (ETH_REG_BASE(port) + 0x246c)
+#define ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (ETH_REG_BASE(port) + 0x247c)
+#define ETH_RX_DISCARD_PKTS_CNTR_REG(port)  (ETH_REG_BASE(port) + 0x2484)
+#define ETH_RX_OVERRUN_PKTS_CNTR_REG(port)  (ETH_REG_BASE(port) + 0x2488)
+#define ETH_INTERNAL_ADDR_ERROR_REG(port)   (ETH_REG_BASE(port) + 0x2494)
+
+/***** Receive Queue Command (RxQC) register *****/
+#define ETH_RX_QUEUE_COMMAND_REG(port)      (ETH_REG_BASE(port) + 0x2680)
+
+#define ETH_RXQ_ENABLE_OFFSET               0
+#define ETH_RXQ_ENABLE_MASK                 (0x000000FF << ETH_RXQ_ENABLE_OFFSET)
+
+#define ETH_RXQ_DISABLE_OFFSET              8
+#define ETH_RXQ_DISABLE_MASK                (0x000000FF << ETH_RXQ_DISABLE_OFFSET)
+/*-----------------------------------------------------------------------------------------------*/
+
+/******************************** WRR Legacy rigisters ********************************************/
+
+#ifndef MV_ETH_WRR_NEW
+
+/* Transmit Queue Fixed Priority Configuration (TQFPC) */
+#define ETH_TX_FIXED_PRIO_CFG_REG(p, txp)   (NETA_TX_REG_BASE((p), (txp)) + 0x00dc)
+
+#define ETH_TX_FIXED_PRIO_OFFS              0
+#define ETH_TX_FIXED_PRIO_MASK              (0xFF << ETH_TX_FIXED_PRIO_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Port Transmit Token-Bucket Rate Configuration (PTTBRC) */
+#define ETH_TXP_TOKEN_RATE_CFG_REG(p, txp)  (NETA_TX_REG_BASE((p), (txp)) + 0x00e0)
+
+#define ETH_TXP_TOKEN_RATE_OFFS             0
+#define ETH_TXP_TOKEN_RATE_MAX              0x7FFF
+#define ETH_TXP_TOKEN_RATE_ALL_MASK         (ETH_TXP_TOKEN_RATE_MAX << ETH_TXP_TOKEN_RATE_OFFS)
+#define ETH_TXP_TOKEN_RATE_MASK(rate)       ((rate) << ETH_TXP_TOKEN_RATE_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Transmit Queue Command1 (TQC1) - reserved */
+#define ETH_TXQ_CMD_1_REG(p, txp)           (NETA_TX_REG_BASE((p), (txp)) + 0x00e4)
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_MAX_TRANSMIT_UNIT_REG(p, txp)   (NETA_TX_REG_BASE((p), (txp)) + 0x00e8)
+
+#define ETH_TX_MTU_OFFS                     0
+#define ETH_TX_MTU_MAX                      0x3F
+#define ETH_TX_MTU_ALL_MASK                 (ETH_TX_MTU_MAX << ETH_TX_MTU_OFFS)
+#define ETH_TX_MTU_MASK(mtu)                ((mtu) << ETH_TX_MTU_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Port Maximum Token Bucket Size (PMTBS) */
+#define ETH_TXP_TOKEN_SIZE_REG(p, txp)      (NETA_TX_REG_BASE((p), (txp)) + 0x00ec)
+
+#define ETH_TXP_TOKEN_SIZE_OFFS             0
+#define ETH_TXP_TOKEN_SIZE_MAX              0xFFFF
+#define ETH_TXP_TOKEN_SIZE_ALL_MASK         (ETH_TXP_TOKEN_SIZE_MAX << ETH_TXP_TOKEN_SIZE_OFFS)
+#define ETH_TXP_TOKEN_SIZE_MASK(size)       ((size) << ETH_TXP_TOKEN_SIZE_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_TXQ_TOKEN_COUNT_REG(p, txp, q)  (NETA_TX_REG_BASE((p), (txp)) + 0x0300 + ((q) << 4))
+
+#define ETH_TXQ_TOKEN_COUNT_OFFS            0
+#define ETH_TXQ_TOKEN_COUNT_MASK            (0x3FFFFFFF << ETH_TXQ_TOKEN_COUNT_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Transmit Queue Token Bucket Configuration (TQxTBC) */
+#define ETH_TXQ_TOKEN_CFG_REG(p, txp, q)    (NETA_TX_REG_BASE((p), (txp)) + 0x0304 + ((q) << 4))
+
+#define ETH_TXQ_TOKEN_RATE_OFFS             0
+#define ETH_TXQ_TOKEN_RATE_MAX              0x7FFF
+#define ETH_TXQ_TOKEN_RATE_ALL_MASK         (ETH_TXQ_TOKEN_RATE_MAX << ETH_TXQ_TOKEN_RATE_OFFS)
+#define ETH_TXQ_TOKEN_RATE_MASK(size)       ((size) << ETH_TXQ_TOKEN_RATE_OFFS)
+
+#define ETH_TXQ_TOKEN_SIZE_OFFS             16
+#define ETH_TXQ_TOKEN_SIZE_MAX              0xFFFF
+#define ETH_TXQ_TOKEN_SIZE_ALL_MASK         (ETH_TXQ_TOKEN_SIZE_MAX << ETH_TXQ_TOKEN_SIZE_OFFS)
+#define ETH_TXQ_TOKEN_SIZE_MASK(size)       ((size) << ETH_TXQ_TOKEN_SIZE_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Transmit Queue Arbiter Configuration (TQxAC) register */
+#define ETH_TXQ_ARBITER_CFG_REG(p, txp, q)  (NETA_TX_REG_BASE((p), (txp)) + 0x0308 + ((q) << 4))
+
+#define ETH_TXQ_WRR_WEIGHT_OFFS             0
+#define ETH_TXQ_WRR_WEIGHT_MAX              0xFF
+#define ETH_TXQ_WRR_WEIGHT_ALL_MASK         (ETH_TXQ_WRR_WEIGHT_MAX << ETH_TXQ_WRR_WEIGHT_OFFS)
+#define ETH_TXQ_WRR_WEIGHT_MASK(weigth)     ((weigth) << ETH_TXQ_WRR_WEIGHT_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Port Transmit Token-Bucket Counter (PTTBC) */
+#define ETH_TXP_TOKEN_COUNT_REG(p, txp)     (NETA_TX_REG_BASE((p), (txp)) + 0x0380)
+#define ETH_TXP_TOKEN_COUNT_OFFS            0
+#define ETH_TXP_TOKEN_COUNT_MASK            (0x3FFFFFFF << ETH_TXP_TOKEN_COUNT_OFFS)
+
+#endif /* MV_ETH_WRR_NEW */
+/**************************************************************************************************/
+
+
+#define ETH_MIB_COUNTERS_BASE(port, txp)    (ETH_REG_BASE(port) + 0x3000 + ((txp) * 0x80))
+#define ETH_DA_FILTER_SPEC_MCAST_BASE(port) (ETH_REG_BASE(port) + 0x3400)
+#define ETH_DA_FILTER_OTH_MCAST_BASE(port)  (ETH_REG_BASE(port) + 0x3500)
+#define ETH_DA_FILTER_UCAST_BASE(port)      (ETH_REG_BASE(port) + 0x3600)
+
+/* Phy address register definitions */
+#define ETH_PHY_ADDR_OFFS          0
+#define ETH_PHY_ADDR_MASK          (0x1f << ETH_PHY_ADDR_OFFS)
+
+/* MIB Counters register definitions */
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW    0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH   0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED         0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR   0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED        0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED         0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED   0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED   0x1c
+#define ETH_MIB_FRAMES_64_OCTETS            0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS     0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS    0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS    0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS   0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS   0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW        0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH       0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT            0x40
+#define ETH_MIB_EXCESSIVE_COLLISION         0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT       0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT       0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED  0x50
+#define ETH_MIB_FC_SENT                     0x54
+#define ETH_MIB_GOOD_FC_RECEIVED            0x58
+#define ETH_MIB_BAD_FC_RECEIVED             0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED          0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED          0x64
+#define ETH_MIB_OVERSIZE_RECEIVED           0x68
+#define ETH_MIB_JABBER_RECEIVED             0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR           0x70
+#define ETH_MIB_BAD_CRC_EVENT               0x74
+#define ETH_MIB_COLLISION                   0x78
+#define ETH_MIB_LATE_COLLISION              0x7c
+
+
+#ifndef MV_ETH_GMAC_NEW
+/*****************************************************/
+/*        Registers are not exist in new GMAC    */
+/*****************************************************/
+#define ETH_MII_SERIAL_PARAM_REG(port)      (ETH_REG_BASE(port) + 0x2408)
+#define ETH_GMII_SERIAL_PARAM_REG(port)     (ETH_REG_BASE(port) + 0x240c)
+
+/* Port Serial Control1 (PSC1) */
+#define ETH_PORT_SERIAL_CTRL_1_REG(port)    (ETH_REG_BASE(port) + 0x244c)
+#define ETH_PSC_ENABLE_BIT                  2
+#define ETH_PSC_ENABLE_MASK                 (1 << ETH_PSC_ENABLE_BIT)
+
+#define ETH_RGMII_ENABLE_BIT                3
+#define ETH_RGMII_ENABLE_MASK               (1 << ETH_RGMII_ENABLE_BIT)
+
+#define ETH_PORT_RESET_BIT                  4
+#define ETH_PORT_RESET_MASK                 (1 << ETH_PORT_RESET_BIT)
+
+#define ETH_INBAND_AUTO_NEG_ENABLE_BIT      6
+#define ETH_INBAND_AUTO_NEG_ENABLE_MASK     (1 << ETH_INBAND_AUTO_NEG_ENABLE_BIT)
+
+#define ETH_INBAND_AUTO_NEG_BYPASS_BIT      7
+#define ETH_INBAND_AUTO_NEG_BYPASS_MASK     (1 << ETH_INBAND_AUTO_NEG_BYPASS_BIT)
+
+#define ETH_INBAND_AUTO_NEG_START_BIT       8
+#define ETH_INBAND_AUTO_NEG_START_MASK      (1 << ETH_INBAND_AUTO_NEG_START_BIT)
+
+#define ETH_PORT_TYPE_BIT                   11
+#define ETH_PORT_TYPE_1000BasedX_MASK       (1 << ETH_PORT_TYPE_BIT)
+
+#define ETH_SGMII_MODE_BIT                  12
+#define ETH_1000BaseX_MODE_MASK             (0 << ETH_SGMII_MODE_BIT)
+#define ETH_SGMII_MODE_MASK                 (1 << ETH_SGMII_MODE_BIT)
+
+#define ETH_MGMII_MODE_BIT                  13
+
+#define ETH_EN_MII_ODD_PRE_BIT		        22
+#define ETH_EN_MII_ODD_PRE_MASK		        (1 << ETH_EN_MII_ODD_PRE_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Ethernet Port Status1 (PS1) */
+#define ETH_PORT_STATUS_1_REG(port)         (ETH_REG_BASE(port) + 0x2450)
+#define ETH_AUTO_NEG_DONE_BIT               4
+#define ETH_AUTO_NEG_DONE_MASK              (1 << ETH_AUTO_NEG_DONE_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+#define ETH_PORT_FIFO_PARAMS_REG(port)      (ETH_REG_BASE(port) + 0x2458)
+
+#endif /* MV_ETH_GMAC_NEW */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INCmvEthRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvHwf.c b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvHwf.c
new file mode 100755
index 0000000..e57702c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvHwf.c
@@ -0,0 +1,371 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"		/* Should be included before mvSysHwConfig */
+#include "mvTypes.h"
+#include "mvDebug.h"
+#include "mvOs.h"
+#include "mvNeta.h"
+#include "bm/mvBm.h"
+
+/*#define HWF_DBG mvOsPrintf*/
+#define HWF_DBG(X...)
+
+/*******************************************************************************
+* mvNetaHwfInit - Init HWF registers of the port
+* DESCRIPTION:
+*
+* INPUT:
+*       int			port - NETA port number
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure
+*
+* NOTE:
+*******************************************************************************/
+MV_STATUS mvNetaHwfInit(int port)
+{
+	int					p, txp;
+	MV_U32				regVal;
+	MV_NETA_PORT_CTRL	*pPortCtrl;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort)) {
+		mvOsPrintf("%s: port %d is out of range\n", __func__, port);
+		return MV_OUT_OF_RANGE;
+	}
+
+	pPortCtrl = mvNetaPortHndlGet(port);
+	if (pPortCtrl == NULL) {
+		mvOsPrintf("%s: port %d is not initialized\n", __func__, port);
+		return MV_FAIL;
+	}
+
+	/* Set TX Port base addresses */
+	for (p = 0; p < mvNetaHalData.maxPort; p++) {
+		pPortCtrl = mvNetaPortHndlGet(p);
+		if (pPortCtrl == NULL)
+			continue;
+
+		for (txp = 0; txp < pPortCtrl->txpNum; txp++) {
+			regVal = MV_REG_READ(NETA_HWF_TXP_CFG_REG(port, (p + txp)));
+			regVal &= ~NETA_TXP_BASE_ADDR_MASK(p + txp);
+			regVal |= ((NETA_TX_REG_BASE(p, txp) >> 10) << NETA_TXP_BASE_ADDR_OFFS(p + txp));
+			MV_REG_WRITE(NETA_HWF_TXP_CFG_REG(port, (p + txp)), regVal);
+		}
+	}
+	/* Init HWF RX Control register */
+	regVal = NETA_GEM_PID_SRC_FLOW_ID;
+	MV_REG_WRITE(NETA_HWF_RX_CTRL_REG(port), regVal);
+
+	/* Set Small TX Gap */
+	MV_REG_WRITE(NETA_HWF_TX_GAP_REG(port), NETA_HWF_SMALL_TX_GAP_MASK);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+ * mvNetaHwfBmPoolsSet - Set short and long pools to be used by HWF of the port
+ *
+ * INPUT:
+ *       int        port	- port number
+ *       int        short_pool	- BM pool for short buffers
+ *       int        long_pool	- BM pool for long buffers
+ *
+ * RETURN:   MV_STATUS
+ *               MV_OK - Success, Others - Failure
+ *
+ *******************************************************************************/
+MV_STATUS mvNetaHwfBmPoolsSet(int port, int short_pool, int long_pool)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_HWF_RX_CTRL_REG(port));
+
+	regVal &= ~NETA_HWF_LONG_POOL_MASK;
+	regVal |= NETA_HWF_LONG_POOL_ID(long_pool);
+
+	regVal &= ~NETA_HWF_SHORT_POOL_MASK;
+	regVal |= NETA_HWF_SHORT_POOL_ID(short_pool);
+
+	MV_REG_WRITE(NETA_HWF_RX_CTRL_REG(port), regVal);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+ * mvNetaHwfEnable - Enable / Disable HWF of the port
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *       int        port   - port number
+ *       int        enable - 0 - disable, 1 - enable
+ *
+ * RETURN:   MV_STATUS
+ *               MV_OK - Success, Others - Failure
+ *
+ * NOTE:
+ *******************************************************************************/
+MV_STATUS mvNetaHwfEnable(int port, int enable)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_HWF_RX_CTRL_REG(port));
+	if (enable)
+		regVal |= NETA_HWF_ENABLE_MASK;
+	else
+		regVal &= ~NETA_HWF_ENABLE_MASK;
+
+	MV_REG_WRITE(NETA_HWF_RX_CTRL_REG(port), regVal);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+ * mvNetaHwfTxqInit - Set TXQ base address and size, set default Drop configuration
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *       int        rx_port:            RX port number
+ *       int        tx_port, txp, txq:  port, TCONT and TXQ numbers
+ *
+ * RETURN:   MV_STATUS
+ *               MV_OK - Success, Others - Failure
+ *
+ * NOTE:
+ *******************************************************************************/
+MV_STATUS mvNetaHwfTxqInit(int tx_port, int txp, int txq)
+{
+	MV_U32				regVal;
+	MV_NETA_PORT_CTRL	*pPortCtrl;
+	MV_NETA_QUEUE_CTRL	*pQueueCtrl;
+	int					port, dropThresh;
+
+	pPortCtrl = mvNetaPortHndlGet(tx_port);
+	if (pPortCtrl == NULL) {
+		mvOsPrintf("%s: port %d is not initialized\n", __func__, tx_port);
+		return MV_NOT_INITIALIZED;
+	}
+
+	pQueueCtrl = &pPortCtrl->pTxQueue[txp * CONFIG_MV_ETH_TXQ + txq].queueCtrl;
+
+	if (pQueueCtrl->pFirst == NULL) {
+		mvOsPrintf("%s: tx_port=%d, txp=%d, txq=%d is not initialized\n",
+					__func__, tx_port, txp, txq);
+		return MV_NOT_INITIALIZED;
+	}
+
+	for (port = 0; port < mvNetaHalData.maxPort; port++) {
+
+		pPortCtrl = mvNetaPortHndlGet(port);
+		if (pPortCtrl == NULL)
+			continue;
+
+		regVal = NETA_HWF_TX_PORT_MASK(tx_port + txp) | NETA_HWF_TXQ_MASK(txq);
+		MV_REG_WRITE(NETA_HWF_TX_PTR_REG(port), regVal);
+		MV_REG_WRITE(NETA_HWF_TXQ_BASE_REG(port), pQueueCtrl->descBuf.bufPhysAddr);
+		MV_REG_WRITE(NETA_HWF_TXQ_SIZE_REG(port), pQueueCtrl->lastDesc + 1);
+
+		dropThresh = (CONFIG_MV_ETH_HWF_TXQ_DROP * (pQueueCtrl->lastDesc + 1)) / 100;
+		regVal = (dropThresh << NETA_YELLOW_DROP_THRESH_OFFS) |
+			    (CONFIG_MV_ETH_HWF_TXQ_DROP_RND << NETA_YELLOW_DROP_RND_GEN_OFFS);
+
+		MV_REG_WRITE(NETA_HWF_DROP_TH_REG(port), regVal);
+	}
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+ * mvNetaHwfTxqEnable - Enable / Disable HWF from the rx_port to tx_port/txp/txq
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *       int        rx_port:            RX port number
+ *       int        tx_port, txp, txq:  port, TCONT and TXQ numbers
+ *       int        enable:             0 - disable, 1 - enable
+ *
+ * RETURN:   MV_STATUS
+ *               MV_OK - Success, Others - Failure
+ *
+ * NOTE:
+ *******************************************************************************/
+MV_STATUS mvNetaHwfTxqEnable(int port, int tx_port, int txp, int txq, int enable)
+{
+	MV_U32 regVal;
+
+	/* Enable HWF for each TXQ */
+	regVal = NETA_HWF_TX_PORT_MASK(tx_port + txp) | NETA_HWF_TXQ_MASK(txq);
+	MV_REG_WRITE(NETA_HWF_TX_PTR_REG(port), regVal);
+
+	MV_REG_WRITE(NETA_HWF_TXQ_ENABLE_REG(port), enable << NETA_HWF_TXQ_ENABLE_BIT);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+ * mvNetaHwfTxqDropSet - Set HWF drop threshold
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *       int        rx_port:            RX port number
+ *       int        tx_port, txp, txq:  port, TCONT and TXQ numbers
+ *       int        thresh, bits		drop configuration
+ *
+ * RETURN:   MV_STATUS
+ *               MV_OK - Success, Others - Failure
+ *
+ * NOTE:
+ *******************************************************************************/
+MV_STATUS mvNetaHwfTxqDropSet(int port, int tx_port, int txp, int txq, int thresh, int bits)
+{
+	MV_U32 regVal, dropThresh;
+	MV_NETA_PORT_CTRL *pPortCtrl;
+	MV_NETA_QUEUE_CTRL *pQueueCtrl;
+
+	pPortCtrl = mvNetaPortHndlGet(tx_port);
+	if (pPortCtrl == NULL)
+		return MV_FAIL;
+
+	pQueueCtrl = &pPortCtrl->pTxQueue[txp * CONFIG_MV_ETH_TXQ + txq].queueCtrl;
+	if (pQueueCtrl->pFirst == NULL)
+		return MV_FAIL;
+
+	/* Set HWF Drop parameters for specific TXQ */
+	regVal = NETA_HWF_TX_PORT_MASK(tx_port + txp) | NETA_HWF_TXQ_MASK(txq);
+	MV_REG_WRITE(NETA_HWF_TX_PTR_REG(port), regVal);
+
+	dropThresh = (thresh * (pQueueCtrl->lastDesc + 1)) / 100;
+	regVal = (dropThresh << NETA_YELLOW_DROP_THRESH_OFFS) | (bits << NETA_YELLOW_DROP_RND_GEN_OFFS);
+
+	MV_REG_WRITE(NETA_HWF_DROP_TH_REG(port), regVal);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+ * mvNetaHwfMhSrcSet - Select MH source on TX during HWF (PNC or field in
+ * 			HWF RX control register.
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *       int        port;	port number
+ *       int        mh_src; 0 - register field, 1 - PNC result info bits
+ *
+ * RETURN:   MV_STATUS
+ *               MV_OK - Success, Others - Failure
+ *
+ * NOTE:
+ *******************************************************************************/
+MV_STATUS mvNetaHwfMhSrcSet(int port, MV_NETA_HWF_MH_SRC mh_src)
+{
+	MV_U32	regVal;
+
+	regVal = MV_REG_READ(NETA_HWF_RX_CTRL_REG(port));
+
+	switch (mh_src) {
+
+	case MV_NETA_HWF_MH_REG:
+		regVal &= ~NETA_MH_SRC_PNC_MASK;
+		break;
+
+	case MV_NETA_HWF_MH_PNC:
+		regVal |= NETA_MH_SRC_PNC_MASK;
+		break;
+
+	default:
+		mvOsPrintf("port=%d: Unexpected HWF MH source = %d value\n", port, mh_src);
+		return MV_BAD_PARAM;
+	}
+	MV_REG_WRITE(NETA_HWF_RX_CTRL_REG(port), regVal);
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+ * mvNetaHwfMhSelSet - Set MH value on TX during HWF.
+ *
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *       int        port;		port number
+ *       int        mh_sel_mask;	use the following values as mask
+ *					NETA_MH_DONT_CHANGE
+ *					NETA_MH_REPLACE_GPON_HDR
+ *					NETA_MH_REPLACE_MH_REG(r)
+ * RETURN:   MV_STATUS
+ *               MV_OK - Success, Others - Failure
+ *
+ * NOTE:
+ *******************************************************************************/
+MV_STATUS mvNetaHwfMhSelSet(int port, MV_U8 mh_sel_mask)
+{
+	MV_U32	regVal;
+
+	regVal = MV_REG_READ(NETA_HWF_RX_CTRL_REG(port));
+	regVal &= ~NETA_MH_SEL_MASK;
+	regVal |= ((mh_sel_mask<<NETA_MH_SEL_OFFS) & NETA_MH_SEL_MASK);
+
+	MV_REG_WRITE(NETA_HWF_RX_CTRL_REG(port), regVal);
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.c b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.c
new file mode 100755
index 0000000..c822d2a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.c
@@ -0,0 +1,3554 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"		/* Should be included before mvSysHwConfig */
+#include "mvTypes.h"
+#include "mv802_3.h"
+#include "mvDebug.h"
+#include "mvOs.h"
+
+#include "mvNeta.h"
+#include "pnc/mvPnc.h"
+#include "bm/mvBm.h"
+
+/* This array holds the control structure of each port */
+MV_NETA_PORT_CTRL **mvNetaPortCtrl = NULL;
+MV_NETA_HAL_DATA mvNetaHalData;
+
+/* Function prototypes */
+#ifdef CONFIG_MV_ETH_LEGACY_PARSER
+static MV_BOOL netaSetUcastAddr(int port, MV_U8 lastNibble, int queue);
+static MV_BOOL netaSetSpecialMcastAddr(int port, MV_U8 lastByte, int queue);
+static MV_BOOL netaSetOtherMcastAddr(int port, MV_U8 crc8, int queue);
+#endif /* CONFIG_MV_ETH_LEGACY_PARSER */
+
+static void mvNetaPortSgmiiConfig(int port);
+static MV_U8 *mvNetaDescrMemoryAlloc(MV_NETA_PORT_CTRL * pPortCtrl, int descSize,
+				   MV_ULONG *pPhysAddr, MV_U32 *memHandle);
+static void mvNetaDescrMemoryFree(MV_NETA_PORT_CTRL *pPortCtrl, MV_BUF_INFO *pDescBuf);
+static void mvNetaDescRingReset(MV_NETA_QUEUE_CTRL *pQueueHndl);
+
+#define TX_DISABLE_TIMEOUT_MSEC     1000
+#define RX_DISABLE_TIMEOUT_MSEC     1000
+#define TX_FIFO_EMPTY_TIMEOUT_MSEC  10000
+#define PORT_DISABLE_WAIT_TCLOCKS   5000
+
+int mvNetaPortCheck(int port)
+{
+	if ((port < 0) || (port >= mvNetaHalData.maxPort)) {
+		mvOsPrintf("port %d is out of range\n", port);
+		return 1;
+	}
+	if (!(MV_BIT_CHECK(mvNetaHalData.portMask, port))) {
+		mvOsPrintf("port %d is not in portMask (%x)\n", port,  	mvNetaHalData.portMask);
+		return 1;
+	}
+
+	return 0;
+}
+
+int mvNetaTxpCheck(int port, int txp)
+{
+	int txpNum;
+
+	if (mvNetaPortCheck(port))
+		return 1;
+
+	txpNum = 1;
+
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(port))
+		txpNum = MV_ETH_MAX_TCONT();
+#endif /* CONFIG_MV_PON */
+
+	if ((txp < 0) || (txp >= txpNum)) {
+		mvOsPrintf("txp %d is out of range\n", txp);
+		return 1;
+	}
+	return 0;
+}
+
+int mvNetaMaxCheck(int num, int limit)
+{
+	if ((num < 0) || (num >= limit)) {
+		mvOsPrintf("%d is out of range %d\n", num, limit);
+		return 1;
+	}
+
+	return 0;
+}
+
+/******************************************************************************/
+/*                      Port Initialization functions                         */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvNetaPortInit - Initialize the NETA port
+*
+* DESCRIPTION:
+*       This function initializes the NETA port.
+*       1) Allocates and initializes internal port control structure.
+*       2) Creates RX and TX descriptor rings.
+*       3) Disables RX and TX operations, clears cause registers and
+*	   masks all interrupts.
+*       4) Sets all registers to default values and cleans all MAC tables.
+*
+* INPUT:
+*       int			portNo          - NETA port number
+*
+* RETURN:
+*       void* - NETA port handler that should be passed to most other
+*               functions dealing with this port.
+*
+* NOTE: This function is called once per port when loading the NETA module.
+*******************************************************************************/
+void *mvNetaPortInit(int portNo, void *osHandle)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl;
+
+	/* Check validity of parameters */
+	if ((portNo < 0) || (portNo >= mvNetaHalData.maxPort)) {
+		mvOsPrintf("EthPort #%d: Bad initialization parameters\n", portNo);
+		return NULL;
+	}
+
+	pPortCtrl = (MV_NETA_PORT_CTRL *)mvOsMalloc(sizeof(MV_NETA_PORT_CTRL));
+	if (pPortCtrl == NULL) {
+		mvOsPrintf("EthDrv: Can't allocate %dB for port #%d control structure!\n",
+			   (int)sizeof(MV_NETA_PORT_CTRL), portNo);
+		return NULL;
+	}
+
+	memset(pPortCtrl, 0, sizeof(MV_NETA_PORT_CTRL));
+	mvNetaPortCtrl[portNo] = pPortCtrl;
+
+	pPortCtrl->portNo = portNo;
+	pPortCtrl->osHandle = osHandle;
+
+	pPortCtrl->txpNum = 1;
+
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(portNo))
+		pPortCtrl->txpNum = MV_ETH_MAX_TCONT();
+#endif /* CONFIG_MV_PON */
+
+	pPortCtrl->rxqNum = CONFIG_MV_ETH_RXQ;
+	pPortCtrl->txqNum = CONFIG_MV_ETH_TXQ;
+
+	/* Allocate RXQ and TXQ structures */
+	pPortCtrl->pRxQueue = mvOsMalloc(pPortCtrl->rxqNum * sizeof(MV_NETA_RXQ_CTRL));
+	if (pPortCtrl->pRxQueue == NULL) {
+		mvOsPrintf("mvNeta port%d: Can't allocate %d Bytes for %d RXQs controls\n",
+			   portNo, (int)pPortCtrl->rxqNum * sizeof(MV_NETA_RXQ_CTRL), pPortCtrl->rxqNum);
+		return NULL;
+	}
+	memset(pPortCtrl->pRxQueue, 0, pPortCtrl->rxqNum * sizeof(MV_NETA_RXQ_CTRL));
+
+	pPortCtrl->pTxQueue = mvOsMalloc(pPortCtrl->txpNum * pPortCtrl->txqNum * sizeof(MV_NETA_TXQ_CTRL));
+	if (pPortCtrl->pTxQueue == NULL) {
+		mvOsPrintf("mvNeta port%d: Can't allocate %d Bytes for %d TXQs controls\n",
+			   portNo, (int)pPortCtrl->txqNum * pPortCtrl->txpNum * sizeof(MV_NETA_TXQ_CTRL),
+			   pPortCtrl->txqNum * pPortCtrl->txpNum);
+		return NULL;
+	}
+	memset(pPortCtrl->pTxQueue, 0, pPortCtrl->txpNum * pPortCtrl->txqNum * sizeof(MV_NETA_TXQ_CTRL));
+
+	/* Disable port */
+	mvNetaPortDisable(portNo);
+	mvNetaDefaultsSet(portNo);
+
+	return pPortCtrl;
+}
+
+/*******************************************************************************
+* mvNetaPortDestroy - Free the memory allocated for a NETA port
+*
+* DESCRIPTION:
+*       This function frees the memory allocated for the NETA port in mvNetaPortInit().
+*
+* INPUT:
+*       int			portNo          - NETA port number
+*
+*******************************************************************************/
+void mvNetaPortDestroy(int portNo)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(portNo);
+
+	if (pPortCtrl->pTxQueue)
+		mvOsFree(pPortCtrl->pTxQueue);
+
+	if (pPortCtrl->pRxQueue)
+		mvOsFree(pPortCtrl->pRxQueue);
+
+	if (pPortCtrl)
+		mvOsFree(pPortCtrl);
+
+	mvNetaPortCtrl[portNo] = NULL;
+}
+
+
+/*******************************************************************************
+* mvNetaAccMode - Get NETA Acceleration mode
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* RETURN:
+*       int - NETA Acceleration mode
+*
+* NOTE: This function is called once on loading the NETA module.
+*******************************************************************************/
+int mvNetaAccMode(void)
+{
+	int mode;
+
+#if defined(CONFIG_MV_ETH_BM) && defined(CONFIG_MV_ETH_PNC)
+	mode = NETA_ACC_MODE_MASK(NETA_ACC_MODE_EXT_PNC_BMU);
+#elif defined(CONFIG_MV_ETH_BM)
+	mode = NETA_ACC_MODE_MASK(NETA_ACC_MODE_EXT_BMU);
+#elif defined(CONFIG_MV_ETH_PNC)
+	mode = NETA_ACC_MODE_MASK(NETA_ACC_MODE_EXT_PNC);
+#else
+	mode = NETA_ACC_MODE_MASK(NETA_ACC_MODE_EXT);
+#endif
+
+	return mode;
+}
+
+/*******************************************************************************
+* mvNetaDefaultsSet - Set defaults to the NETA port
+*
+* DESCRIPTION:
+*       This function sets default values to the NETA port.
+*       1) Clears interrupt Cause and Mask registers.
+*       2) Clears all MAC tables.
+*       3) Sets defaults to all registers.
+*       4) Resets RX and TX descriptor rings.
+*       5) Resets PHY.
+*
+* INPUT:
+*   int     portNo		- Port number.
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure
+* NOTE:
+*   This function updates all the port configurations except those set
+*   initialy by the OsGlue by MV_NETA_PORT_INIT.
+*   This function can be called after portDown to return the port settings
+*   to defaults.
+*******************************************************************************/
+MV_STATUS mvNetaDefaultsSet(int port)
+{
+	int cpu;
+	int queue, txp;
+	MV_U32 regVal;
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(port);
+
+	/* Clear all Cause registers */
+	MV_REG_WRITE(NETA_INTR_NEW_CAUSE_REG(port), 0);
+	MV_REG_WRITE(NETA_INTR_OLD_CAUSE_REG(port), 0);
+	MV_REG_WRITE(NETA_INTR_MISC_CAUSE_REG(port), 0);
+
+	/* Mask all interrupts */
+	MV_REG_WRITE(NETA_INTR_NEW_MASK_REG(port), 0);
+	MV_REG_WRITE(NETA_INTR_OLD_MASK_REG(port), 0);
+	MV_REG_WRITE(NETA_INTR_MISC_MASK_REG(port), 0);
+
+	MV_REG_WRITE(NETA_INTR_ENABLE_REG(port), 0);
+
+	/* Enable MBUS Retry bit16 */
+	MV_REG_WRITE(NETA_MBUS_RETRY_REG(port), NETA_MBUS_RETRY_CYCLES(0x20));
+
+	/* Set CPU queue access map - all CPUs have access to all RX queues and to all TX queues */
+
+	for (cpu = 0; cpu < mvNetaHalData.maxCPUs; cpu++)
+		if (MV_BIT_CHECK(mvNetaHalData.cpuMask, cpu))
+			MV_REG_WRITE(NETA_CPU_MAP_REG(port, cpu), (NETA_CPU_RXQ_ACCESS_ALL_MASK | NETA_CPU_TXQ_ACCESS_ALL_MASK));
+
+	/* Reset RX and TX DMAs */
+	MV_REG_WRITE(NETA_PORT_RX_RESET_REG(port), NETA_PORT_RX_DMA_RESET_MASK);
+
+	for (txp = 0; txp < pPortCtrl->txpNum; txp++) {
+		MV_REG_WRITE(NETA_PORT_TX_RESET_REG(port, txp), NETA_PORT_TX_DMA_RESET_MASK);
+
+#ifdef CONFIG_MV_PON
+		if ((txp * MV_ETH_MAX_TXQ % 32) == 0) {
+			MV_REG_WRITE(GPON_TXQ_INTR_NEW_CAUSE_REG(txp * MV_ETH_MAX_TXQ), 0);
+			MV_REG_WRITE(GPON_TXQ_INTR_NEW_MASK_REG(txp * MV_ETH_MAX_TXQ), 0);
+			MV_REG_WRITE(GPON_TXQ_INTR_OLD_CAUSE_REG(txp * MV_ETH_MAX_TXQ), 0);
+			MV_REG_WRITE(GPON_TXQ_INTR_OLD_MASK_REG(txp * MV_ETH_MAX_TXQ), 0);
+			MV_REG_WRITE(GPON_TXQ_INTR_ERR_CAUSE_REG(txp * MV_ETH_MAX_TXQ), 0);
+			MV_REG_WRITE(GPON_TXQ_INTR_ERR_MASK_REG(txp * MV_ETH_MAX_TXQ), 0);
+
+			MV_REG_WRITE(GPON_TXQ_INTR_ENABLE_REG(txp * MV_ETH_MAX_TXQ), 0xFFFFFFFF);
+		}
+#endif /* CONFIG_MV_PON */
+
+		/* Disable Legacy WRR, Disable EJP, Release from reset */
+#ifdef MV_ETH_WRR_NEW
+		MV_REG_WRITE(NETA_TX_CMD_1_REG(port, txp), 0);
+		/* Close bandwidth for all queues */
+		for (queue = 0; queue < MV_ETH_MAX_TXQ; queue++)
+			MV_REG_WRITE(NETA_TXQ_TOKEN_CNTR_REG(port, txp, queue),  0);
+
+		/* Set basic period to  1 usec */
+		MV_REG_WRITE(NETA_TX_REFILL_PERIOD_REG(port, txp),  mvNetaHalData.tClk / 1000000);
+#else
+		MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port, txp), 0);
+		for (queue = 0; queue < MV_ETH_MAX_TXQ; queue++) {
+			MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(port, txp, queue), 0);
+			MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(port, txp, queue), 0);
+		}
+#endif /* MV_ETH_WRR_NEW */
+
+		MV_REG_WRITE(NETA_PORT_TX_RESET_REG(port, txp), 0);
+	}
+
+	MV_REG_WRITE(NETA_PORT_RX_RESET_REG(port), 0);
+
+	/* Set Port Acceleration Mode */
+	regVal = mvNetaAccMode();
+	MV_REG_WRITE(NETA_ACC_MODE_REG(port), regVal);
+
+#ifdef CONFIG_MV_ETH_BM
+	/* Set address of Buffer Management Unit */
+	MV_REG_WRITE(NETA_BM_ADDR_REG(port), mvNetaHalData.bmPhysBase);
+#endif /* CONFIG_MV_ETH_BM */
+
+	/* Update value of portCfg register accordingly with all RxQueue types */
+	regVal = PORT_CONFIG_VALUE(CONFIG_MV_ETH_RXQ_DEF);
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(port), regVal);
+
+	regVal = PORT_CONFIG_EXTEND_VALUE;
+	MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(port), regVal);
+
+	if (MV_PON_PORT(port))
+		MV_REG_WRITE(ETH_RX_MINIMAL_FRAME_SIZE_REG(port), 40);
+	else
+		MV_REG_WRITE(ETH_RX_MINIMAL_FRAME_SIZE_REG(port), 64);
+
+#ifndef MV_ETH_GMAC_NEW
+	if (!MV_PON_PORT(port)) {
+		regVal = PORT_SERIAL_CONTROL_VALUE;
+
+		regVal &= ~ETH_MAX_RX_PACKET_SIZE_MASK;
+		regVal |= ETH_MAX_RX_PACKET_1522BYTE;
+
+		MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), regVal);
+
+		/* Allow receiving packes with odd number of preamble nibbles */
+		regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port));
+		regVal |= ETH_EN_MII_ODD_PRE_MASK;
+		MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal);
+	}
+#endif /* !MV_ETH_GMAC_NEW */
+
+	/* build PORT_SDMA_CONFIG_REG */
+	regVal = 0;
+
+#ifdef CONFIG_MV_ETH_REDUCE_BURST_SIZE_WA
+	/* This is a WA for the IOCC HW BUG involve in using 128B burst size */
+	regVal |= ETH_TX_BURST_SIZE_MASK(ETH_BURST_SIZE_2_64BIT_VALUE);
+	regVal |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_2_64BIT_VALUE);
+#else
+	/* Default burst size */
+	regVal |= ETH_TX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE);
+	regVal |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE);
+#endif /* CONFIG_MV_ETH_REDUCE_BURST_SIZE_WA */
+
+#if defined(MV_CPU_BE) && !defined(CONFIG_MV_ETH_BE_WA)
+    /* big endian */
+    regVal |= (ETH_RX_NO_DATA_SWAP_MASK | ETH_TX_NO_DATA_SWAP_MASK | ETH_DESC_SWAP_MASK);
+#else /* MV_CPU_LE */
+    /* little endian */
+	regVal |= (ETH_RX_NO_DATA_SWAP_MASK | ETH_TX_NO_DATA_SWAP_MASK | ETH_NO_DESC_SWAP_MASK);
+#endif /* MV_CPU_BE && !CONFIG_MV_ETH_BE_WA */
+
+	/* Assign port SDMA configuration */
+	MV_REG_WRITE(ETH_SDMA_CONFIG_REG(port), regVal);
+
+	mvNetaSetUcastTable(port, -1);
+	mvNetaSetSpecialMcastTable(port, -1);
+	mvNetaSetOtherMcastTable(port, -1);
+
+#if defined(CONFIG_MV_PON) && defined(MV_PON_MIB_SUPPORT)
+	if (MV_PON_PORT(port))
+		/* Set default MibNo = 0 for PON RX counters */
+		mvNetaPonRxMibDefault(0);
+#endif /* CONFIG_MV_PON && MV_PON_MIB_SUPPORT */
+
+	/* Set port interrupt enable register - default enable all */
+	MV_REG_WRITE(NETA_INTR_ENABLE_REG(port),
+		     (NETA_RXQ_PKT_INTR_ENABLE_ALL_MASK | NETA_TXQ_PKT_INTR_ENABLE_ALL_MASK));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaHalInit - Initialize the HAL and the NETA unit
+*
+* DESCRIPTION:
+*       This function:
+*	1) Initializes HAL global data structures.
+*       2) Clears and disables NETA unit interrupts.
+*
+* INPUT:  NONE
+*
+* RETURN: NONE
+*
+* NOTE: this function is called once in the boot process.
+*******************************************************************************/
+MV_STATUS mvNetaHalInit(MV_NETA_HAL_DATA *halData)
+{
+	int port;
+
+	mvNetaHalData = *halData;
+
+	/* Allocate port data structures */
+	mvNetaPortCtrl = mvOsMalloc(mvNetaHalData.maxPort * sizeof(MV_NETA_PORT_CTRL *));
+	if (mvNetaPortCtrl == NULL) {
+		mvOsPrintf("%s: Can't allocate %d bytes for %d ports\n", __func__,
+			   mvNetaHalData.maxPort * sizeof(MV_NETA_PORT_CTRL), mvNetaHalData.maxPort);
+		return MV_FAIL;
+	}
+	for (port = 0; port < mvNetaHalData.maxPort; port++)
+		mvNetaPortCtrl[port] = NULL;
+
+#ifdef CONFIG_MV_ETH_BM
+	mvBmInit(mvNetaHalData.bmVirtBase);
+#endif /* CONFIG_MV_ETH_BM */
+
+#ifdef CONFIG_MV_ETH_PNC
+	mvPncInit(mvNetaHalData.pncVirtBase);
+#endif /* CONFIG_MV_ETH_PNC */
+
+	return MV_OK;
+}
+
+/* Update CPUs that can process packets incoming to specific RXQ */
+MV_STATUS	mvNetaRxqCpuMaskSet(int port, int rxq, int cpu_mask)
+{
+	int		cpu;
+	MV_U32	regVal;
+
+	for (cpu = 0; cpu < mvNetaHalData.maxCPUs; cpu++) {
+		if (!(MV_BIT_CHECK(mvNetaHalData.cpuMask, cpu)))
+			continue;
+		regVal = MV_REG_READ(NETA_CPU_MAP_REG(port, cpu));
+
+		if (cpu_mask & MV_BIT_MASK(cpu))
+			regVal |= NETA_CPU_RXQ_ACCESS_MASK(rxq);
+		else
+			regVal &= ~NETA_CPU_RXQ_ACCESS_MASK(rxq);
+
+		MV_REG_WRITE(NETA_CPU_MAP_REG(port, cpu), regVal);
+	}
+	return MV_OK;
+}
+
+/*****************************************************************/
+/* Functions below are different for old and new version of GMAC */
+/*****************************************************************/
+
+#ifdef MV_ETH_GMAC_NEW
+
+MV_STATUS       mvEthGmacRgmiiSet(int port, int enable)
+{
+	MV_U32  regVal;
+
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_2_REG(port));
+	if (enable)
+		regVal |= NETA_GMAC_PORT_RGMII_MASK;
+	else
+		regVal &= ~NETA_GMAC_PORT_RGMII_MASK;
+
+	MV_REG_WRITE(NETA_GMAC_CTRL_2_REG(port), regVal);
+
+	return MV_OK;
+}
+
+static void mvNetaPortSgmiiConfig(int port)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_2_REG(port));
+	regVal |= (NETA_GMAC_PSC_ENABLE_MASK);
+	MV_REG_WRITE(NETA_GMAC_CTRL_2_REG(port), regVal);
+}
+
+
+void mvNetaPortPowerUp(int port, MV_BOOL isSgmii, MV_BOOL isRgmii)
+{
+	MV_U32 regVal;
+
+	/* MAC Cause register should be cleared */
+	MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port), 0);
+
+	if (isSgmii)
+		mvNetaPortSgmiiConfig(port);
+
+	mvEthGmacRgmiiSet(port, isRgmii);
+
+	/* Cancel Port Reset */
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_2_REG(port));
+	regVal &= (~NETA_GMAC_PORT_RESET_MASK);
+	MV_REG_WRITE(NETA_GMAC_CTRL_2_REG(port), regVal);
+	while ((MV_REG_READ(NETA_GMAC_CTRL_2_REG(port)) & NETA_GMAC_PORT_RESET_MASK) != 0)
+		continue;
+}
+
+void mvNetaPortPowerDown(int port)
+{
+}
+
+/******************************************************************************/
+/*                          Port Configuration functions                      */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvNetaMaxRxSizeSet -
+*
+* DESCRIPTION:
+*       Change maximum receive size of the port. This configuration will take place
+*       imidiately.
+*
+* INPUT:
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvNetaMaxRxSizeSet(int portNo, int maxRxSize)
+{
+    MV_U32		regVal;
+
+	if (!MV_PON_PORT(portNo)) {
+
+	    regVal =  MV_REG_READ(NETA_GMAC_CTRL_0_REG(portNo));
+		regVal &= ~NETA_GMAC_MAX_RX_SIZE_MASK;
+		regVal |= (((maxRxSize - MV_ETH_MH_SIZE) / 2) << NETA_GMAC_MAX_RX_SIZE_OFFS);
+		MV_REG_WRITE(NETA_GMAC_CTRL_0_REG(portNo), regVal);
+/*
+		mvOsPrintf("%s: port=%d, maxRxSize=%d, regAddr=0x%x, regVal=0x%x\n",
+			__func__, portNo, maxRxSize, NETA_GMAC_CTRL_0_REG(portNo), regVal);
+*/
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaForceLinkModeSet -
+*
+* DESCRIPTION:
+*       Sets "Force Link Pass" and "Do Not Force Link Fail" bits.
+* 	Note: This function should only be called when the port is disabled.
+*
+* INPUT:
+* 	int		portNo			- port number
+* 	MV_BOOL force_link_pass	- Force Link Pass
+* 	MV_BOOL force_link_fail - Force Link Failure
+*		0, 0 - normal state: detect link via PHY and connector
+*		1, 1 - prohibited state.
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvNetaForceLinkModeSet(int portNo, MV_BOOL force_link_up, MV_BOOL force_link_down)
+{
+	MV_U32	regVal;
+
+	if ((portNo < 0) || (portNo >= mvNetaHalData.maxPort))
+		return MV_BAD_PARAM;
+
+	/* Can't force link pass and link fail at the same time */
+	if ((force_link_up) && (force_link_down))
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(portNo));
+
+	if (force_link_up)
+		regVal |= NETA_FORCE_LINK_PASS_MASK;
+	else
+		regVal &= ~NETA_FORCE_LINK_PASS_MASK;
+
+	if (force_link_down)
+		regVal |= NETA_FORCE_LINK_FAIL_MASK;
+	else
+		regVal &= ~NETA_FORCE_LINK_FAIL_MASK;
+
+	MV_REG_WRITE(NETA_GMAC_AN_CTRL_REG(portNo), regVal);
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaSpeedDuplexSet -
+*
+* DESCRIPTION:
+*       Sets port speed to Auto Negotiation / 1000 / 100 / 10 Mbps.
+*	Sets port duplex to Auto Negotiation / Full / Half Duplex.
+*
+* INPUT:
+* 	int portNo - port number
+* 	MV_ETH_PORT_SPEED speed - port speed
+*	MV_ETH_PORT_DUPLEX duplex - port duplex mode
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvNetaSpeedDuplexSet(int portNo, MV_ETH_PORT_SPEED speed, MV_ETH_PORT_DUPLEX duplex)
+{
+	MV_U32 regVal;
+
+	if ((portNo < 0) || (portNo >= mvNetaHalData.maxPort))
+		return MV_BAD_PARAM;
+
+	/* Check validity */
+	if ((speed == MV_ETH_SPEED_1000) && (duplex == MV_ETH_DUPLEX_HALF))
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(portNo));
+
+	switch (speed) {
+	case MV_ETH_SPEED_AN:
+		regVal |= NETA_ENABLE_SPEED_AUTO_NEG_MASK;
+		/* the other bits don't matter in this case */
+		break;
+	case MV_ETH_SPEED_1000:
+		regVal &= ~NETA_ENABLE_SPEED_AUTO_NEG_MASK;
+		regVal |= NETA_SET_GMII_SPEED_1000_MASK;
+		regVal &= ~NETA_SET_MII_SPEED_100_MASK;
+		/* the 100/10 bit doesn't matter in this case */
+		break;
+	case MV_ETH_SPEED_100:
+		regVal &= ~NETA_ENABLE_SPEED_AUTO_NEG_MASK;
+		regVal &= ~NETA_SET_GMII_SPEED_1000_MASK;
+		regVal |= NETA_SET_MII_SPEED_100_MASK;
+		break;
+	case MV_ETH_SPEED_10:
+		regVal &= ~NETA_ENABLE_SPEED_AUTO_NEG_MASK;
+		regVal &= ~NETA_SET_GMII_SPEED_1000_MASK;
+		regVal &= ~NETA_SET_MII_SPEED_100_MASK;
+		break;
+	default:
+		mvOsPrintf("Unexpected Speed value %d\n", speed);
+		return MV_BAD_PARAM;
+	}
+
+	switch (duplex) {
+	case MV_ETH_DUPLEX_AN:
+		regVal  |= NETA_ENABLE_DUPLEX_AUTO_NEG_MASK;
+		/* the other bits don't matter in this case */
+		break;
+	case MV_ETH_DUPLEX_HALF:
+		regVal &= ~NETA_ENABLE_DUPLEX_AUTO_NEG_MASK;
+		regVal &= ~NETA_SET_FULL_DUPLEX_MASK;
+		break;
+	case MV_ETH_DUPLEX_FULL:
+		regVal &= ~NETA_ENABLE_DUPLEX_AUTO_NEG_MASK;
+		regVal |= NETA_SET_FULL_DUPLEX_MASK;
+		break;
+	default:
+		mvOsPrintf("Unexpected Duplex value %d\n", duplex);
+		return MV_BAD_PARAM;
+	}
+
+	MV_REG_WRITE(NETA_GMAC_AN_CTRL_REG(portNo), regVal);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaSpeedDuplexGet -
+*
+* DESCRIPTION:
+*       Gets port speed
+*	Gets port duplex
+*
+* INPUT:
+* 	int portNo - port number
+* OUTPUT:
+* 	MV_ETH_PORT_SPEED *speed - port speed
+*	MV_ETH_PORT_DUPLEX *duplex - port duplex mode
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvNetaSpeedDuplexGet(int portNo, MV_ETH_PORT_SPEED *speed, MV_ETH_PORT_DUPLEX *duplex)
+{
+	MV_U32 regVal;
+	if ((portNo < 0) || (portNo >= mvNetaHalData.maxPort))
+		return MV_BAD_PARAM;
+
+	/* Check validity */
+	if (!speed || !duplex)
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(portNo));
+	if (regVal & NETA_ENABLE_SPEED_AUTO_NEG_MASK)
+		*speed = MV_ETH_SPEED_AN;
+	else if (regVal & NETA_SET_GMII_SPEED_1000_MASK)
+		*speed = MV_ETH_SPEED_1000;
+	else if (regVal & NETA_SET_MII_SPEED_100_MASK)
+		*speed = MV_ETH_SPEED_100;
+	else
+		*speed = MV_ETH_SPEED_10;
+
+	if (regVal & NETA_ENABLE_DUPLEX_AUTO_NEG_MASK)
+		*duplex = MV_ETH_DUPLEX_AN;
+	else if (regVal & NETA_SET_FULL_DUPLEX_MASK)
+		*duplex = MV_ETH_DUPLEX_FULL;
+	else
+		*duplex = MV_ETH_DUPLEX_HALF;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaFlowCtrlSet - Set Flow Control of the port.
+*
+* DESCRIPTION:
+*       This function configures the port's Flow Control properties.
+*
+* INPUT:
+*       int				port		- Port number
+*       MV_ETH_PORT_FC  flowControl - Flow control of the port.
+*
+* RETURN:   MV_STATUS
+*       MV_OK           - Success
+*       MV_OUT_OF_RANGE - Failed. Port is out of valid range
+*       MV_BAD_VALUE    - Value flowControl parameters is not valid
+*
+*******************************************************************************/
+MV_STATUS mvNetaFlowCtrlSet(int port, MV_ETH_PORT_FC flowControl)
+{
+	MV_U32 regVal;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort))
+		return MV_OUT_OF_RANGE;
+
+	regVal = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(port));
+
+	switch (flowControl) {
+	case MV_ETH_FC_AN_NO:
+		regVal |= NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
+		regVal &= ~NETA_FLOW_CONTROL_ADVERTISE_MASK;
+		regVal &= ~NETA_FLOW_CONTROL_ASYMETRIC_MASK;
+		break;
+
+	case MV_ETH_FC_AN_SYM:
+		regVal |= NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
+		regVal |= NETA_FLOW_CONTROL_ADVERTISE_MASK;
+		regVal &= ~NETA_FLOW_CONTROL_ASYMETRIC_MASK;
+		break;
+
+	case MV_ETH_FC_AN_ASYM:
+		regVal |= NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
+		regVal |= NETA_FLOW_CONTROL_ADVERTISE_MASK;
+		regVal |= NETA_FLOW_CONTROL_ASYMETRIC_MASK;
+		break;
+
+	case MV_ETH_FC_DISABLE:
+		regVal &= ~NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
+		regVal &= ~NETA_SET_FLOW_CONTROL_MASK;
+		break;
+
+	case MV_ETH_FC_ENABLE:
+		regVal &= ~NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
+		regVal |= NETA_SET_FLOW_CONTROL_MASK;
+		break;
+
+	default:
+		mvOsPrintf("ethDrv: Unexpected FlowControl value %d\n", flowControl);
+		return MV_BAD_VALUE;
+	}
+
+	MV_REG_WRITE(NETA_GMAC_AN_CTRL_REG(port), regVal);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaFlowCtrlGet - Get Flow Control configuration of the port.
+*
+* DESCRIPTION:
+*       This function returns the port's Flow Control properties.
+*
+* INPUT:
+*       int				port		- Port number
+*
+* OUTPUT:
+*       MV_ETH_PORT_FC  *flowCntrl	- Flow control of the port.
+*
+* RETURN:   MV_STATUS
+*       MV_OK           - Success
+*       MV_OUT_OF_RANGE - Failed. Port is out of valid range
+*
+*******************************************************************************/
+MV_STATUS mvNetaFlowCtrlGet(int port, MV_ETH_PORT_FC *pFlowCntrl)
+{
+	MV_U32 regVal;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort))
+		return MV_OUT_OF_RANGE;
+
+	regVal = MV_REG_READ(NETA_GMAC_AN_CTRL_REG(port));
+
+	if (regVal & NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK) {
+		/* Auto negotiation is enabled */
+		if (regVal & NETA_FLOW_CONTROL_ADVERTISE_MASK) {
+			if (regVal & NETA_FLOW_CONTROL_ASYMETRIC_MASK)
+				*pFlowCntrl = MV_ETH_FC_AN_ASYM;
+			else
+				*pFlowCntrl = MV_ETH_FC_AN_SYM;
+		} else
+			*pFlowCntrl = MV_ETH_FC_AN_NO;
+	} else {
+		/* Auto negotiation is disabled */
+		if (regVal & NETA_SET_FLOW_CONTROL_MASK)
+			*pFlowCntrl = MV_ETH_FC_ENABLE;
+		else
+			*pFlowCntrl = MV_ETH_FC_DISABLE;
+	}
+	return MV_OK;
+}
+
+MV_STATUS mvNetaPortEnable(int port)
+{
+	if (!MV_PON_PORT(port)) {
+		MV_U32 regVal;
+
+		/* Enable port */
+		regVal = MV_REG_READ(NETA_GMAC_CTRL_0_REG(port));
+		regVal |= NETA_GMAC_PORT_EN_MASK;
+
+		MV_REG_WRITE(NETA_GMAC_CTRL_0_REG(port), regVal);
+
+		/* If Link is UP, Start RX and TX traffic */
+		if (MV_REG_READ(NETA_GMAC_STATUS_REG(port)) & NETA_GMAC_LINK_UP_MASK)
+			return mvNetaPortUp(port);
+	}
+	return MV_NOT_READY;
+}
+
+MV_STATUS mvNetaPortDisable(int port)
+{
+	MV_U32 regData;
+
+	mvNetaPortDown(port);
+
+	if (!MV_PON_PORT(port)) {
+		/* Reset the Enable bit in the Serial Control Register */
+		regData = MV_REG_READ(NETA_GMAC_CTRL_0_REG(port));
+		regData &= ~(NETA_GMAC_PORT_EN_MASK);
+		MV_REG_WRITE(NETA_GMAC_CTRL_0_REG(port), regData);
+	}
+	/* Wait about 200 usec */
+	mvOsUDelay(200);
+
+	return MV_OK;
+}
+
+MV_BOOL		mvNetaLinkIsUp(port)
+{
+	MV_U32	regVal;
+
+	if (MV_PON_PORT(port))
+		return MV_TRUE;
+
+	regVal = MV_REG_READ(NETA_GMAC_STATUS_REG(port));
+	if (regVal & NETA_GMAC_LINK_UP_MASK)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+MV_STATUS	mvNetaLinkStatus(int port, MV_ETH_PORT_STATUS *pStatus)
+{
+	MV_U32 regVal;
+
+	if (MV_PON_PORT(port)) {
+		/* FIXME: --BK */
+		pStatus->linkup = MV_TRUE;
+		pStatus->speed = MV_ETH_SPEED_1000;
+		pStatus->duplex = MV_ETH_DUPLEX_FULL;
+		pStatus->rxFc = MV_ETH_FC_DISABLE;
+		pStatus->txFc = MV_ETH_FC_DISABLE;
+		return MV_OK;
+	}
+
+	regVal = MV_REG_READ(NETA_GMAC_STATUS_REG(port));
+
+	if (regVal & NETA_GMAC_SPEED_1000_MASK)
+		pStatus->speed = MV_ETH_SPEED_1000;
+	else if (regVal & NETA_GMAC_SPEED_100_MASK)
+		pStatus->speed = MV_ETH_SPEED_100;
+	else
+		pStatus->speed = MV_ETH_SPEED_10;
+
+	if (regVal & NETA_GMAC_LINK_UP_MASK)
+		pStatus->linkup = MV_TRUE;
+	else
+		pStatus->linkup = MV_FALSE;
+
+	if (regVal & NETA_GMAC_FULL_DUPLEX_MASK)
+		pStatus->duplex = MV_ETH_DUPLEX_FULL;
+	else
+		pStatus->duplex = MV_ETH_DUPLEX_HALF;
+
+	if (regVal & NETA_TX_FLOW_CTRL_ACTIVE_MASK)
+		pStatus->txFc = MV_ETH_FC_ACTIVE;
+	else if (regVal & NETA_TX_FLOW_CTRL_ENABLE_MASK)
+		pStatus->txFc = MV_ETH_FC_ENABLE;
+	else
+		pStatus->txFc = MV_ETH_FC_DISABLE;
+
+	if (regVal & NETA_RX_FLOW_CTRL_ACTIVE_MASK)
+		pStatus->rxFc = MV_ETH_FC_ACTIVE;
+	else if (regVal & NETA_RX_FLOW_CTRL_ENABLE_MASK)
+		pStatus->rxFc = MV_ETH_FC_ENABLE;
+	else
+		pStatus->rxFc = MV_ETH_FC_DISABLE;
+
+	return MV_OK;
+}
+
+/* Set Low Power Idle mode for GMAC port */
+MV_STATUS           mvNetaGmacLpiSet(int port, int mode)
+{
+	if (!MV_PON_PORT(port))	{
+		MV_U32  regVal;
+
+		regVal = MV_REG_READ(NETA_LOW_POWER_CTRL_1_REG(port));
+		if (mode)
+			regVal |= NETA_LPI_REQUEST_EN_MASK;
+		else
+			regVal &= ~NETA_LPI_REQUEST_EN_MASK;
+
+		MV_REG_WRITE(NETA_LOW_POWER_CTRL_1_REG(port), regVal);
+
+		return MV_OK;
+	}
+	return MV_FAIL;
+}
+
+#else	/* Old GMAC functions */
+
+static void mvNetaPortSgmiiConfig(int port)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port));
+	regVal |= (/*ETH_SGMII_MODE_MASK |*/ ETH_PSC_ENABLE_MASK /*| ETH_INBAND_AUTO_NEG_ENABLE_MASK */);
+	/* regVal &= (~ETH_INBAND_AUTO_NEG_BYPASS_MASK); */
+	MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal);
+}
+
+void mvNetaPortPowerUp(int port, MV_BOOL isSgmii, MV_BOOL isRgmii)
+{
+	MV_U32 regVal;
+
+	/* MAC Cause register should be cleared */
+	MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port), 0);
+
+
+	if (isSgmii)
+		mvNetaPortSgmiiConfig(port);
+
+	/* Cancel Port Reset */
+	regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port));
+	regVal &= (~ETH_PORT_RESET_MASK);
+
+	if (isRgmii)
+		regVal |= ETH_RGMII_ENABLE_MASK;
+	else
+		regVal &= (~ETH_RGMII_ENABLE_MASK);
+
+	MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal);
+	while ((MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)) & ETH_PORT_RESET_MASK) != 0)
+		continue;
+}
+
+void mvNetaPortPowerDown(int port)
+{
+}
+
+/******************************************************************************/
+/*                          Port Configuration functions                      */
+/******************************************************************************/
+
+/*******************************************************************************
+* netaMruGet - Get MRU configuration for Max Rx packet size.
+*
+* INPUT:
+*           MV_U32 maxRxPktSize - max  packet size.
+*
+* RETURN:   MV_U32 - MRU configuration.
+*
+*******************************************************************************/
+static MV_U32 netaMruGet(MV_U32 maxRxPktSize)
+{
+	MV_U32 portSerialCtrlReg = 0;
+
+	if (maxRxPktSize > 9192)
+		portSerialCtrlReg |= ETH_MAX_RX_PACKET_9700BYTE;
+	else if (maxRxPktSize > 9022)
+		portSerialCtrlReg |= ETH_MAX_RX_PACKET_9192BYTE;
+	else if (maxRxPktSize > 1552)
+		portSerialCtrlReg |= ETH_MAX_RX_PACKET_9022BYTE;
+	else if (maxRxPktSize > 1522)
+		portSerialCtrlReg |= ETH_MAX_RX_PACKET_1552BYTE;
+	else if (maxRxPktSize > 1518)
+		portSerialCtrlReg |= ETH_MAX_RX_PACKET_1522BYTE;
+	else
+		portSerialCtrlReg |= ETH_MAX_RX_PACKET_1518BYTE;
+
+	return portSerialCtrlReg;
+}
+
+/*******************************************************************************
+* mvNetaMaxRxSizeSet -
+*
+* DESCRIPTION:
+*       Change maximum receive size of the port. This configuration will take place
+*       imidiately.
+*
+* INPUT:
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvNetaMaxRxSizeSet(int portNo, int maxRxSize)
+{
+	MV_U32 portSerialCtrlReg;
+
+	portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(portNo));
+	portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK;
+	portSerialCtrlReg |= netaMruGet(maxRxSize);
+	MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(portNo), portSerialCtrlReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaForceLinkModeSet -
+*
+* DESCRIPTION:
+*       Sets "Force Link Pass" and "Do Not Force Link Fail" bits.
+* 	Note: This function should only be called when the port is disabled.
+*
+* INPUT:
+* 	int portNo - port number
+* 	MV_BOOL force_link_pass - value for Force Link Pass bit (bit 1): 0 or 1
+* 	MV_BOOL do_not_force_link_fail - value for Do Not Force Link Fail bit (bit 10): 0 or 1
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvNetaForceLinkModeSet(int portNo, MV_BOOL force_link_up, MV_BOOL force_link_down)
+{
+	MV_U32 portSerialCtrlReg;
+
+	if ((portNo < 0) || (portNo >= mvNetaHalData.maxPort))
+		return MV_BAD_PARAM;
+
+	/* Can't force link pass and link fail at the same time */
+	if ((force_link_up) && (force_link_down))
+		return MV_BAD_PARAM;
+
+	portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(portNo));
+
+	if (force_link_up)
+		portSerialCtrlReg |= ETH_FORCE_LINK_PASS_MASK | ETH_DO_NOT_FORCE_LINK_FAIL_MASK;
+	else if (force_link_down)
+		portSerialCtrlReg &= ~(ETH_FORCE_LINK_PASS_MASK | ETH_DO_NOT_FORCE_LINK_FAIL_MASK);
+
+	MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(portNo), portSerialCtrlReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaSpeedDuplexSet -
+*
+* DESCRIPTION:
+*       Sets port speed to Auto Negotiation / 1000 / 100 / 10 Mbps.
+*	Sets port duplex to Auto Negotiation / Full / Half Duplex.
+*
+* INPUT:
+* 	int portNo - port number
+* 	MV_ETH_PORT_SPEED speed - port speed
+*	MV_ETH_PORT_DUPLEX duplex - port duplex mode
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvNetaSpeedDuplexSet(int portNo, MV_ETH_PORT_SPEED speed, MV_ETH_PORT_DUPLEX duplex)
+{
+	MV_U32 portSerialCtrlReg;
+
+	if ((portNo < 0) || (portNo >= mvNetaHalData.maxPort))
+		return MV_BAD_PARAM;
+
+	/* Check validity */
+	if ((speed == MV_ETH_SPEED_1000) && (duplex == MV_ETH_DUPLEX_HALF))
+		return MV_BAD_PARAM;
+
+	portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(portNo));
+
+	switch (speed) {
+	case MV_ETH_SPEED_AN:
+		portSerialCtrlReg &= ~ETH_DISABLE_SPEED_AUTO_NEG_MASK;
+		/* the other bits don't matter in this case */
+		break;
+	case MV_ETH_SPEED_1000:
+		portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK;
+		portSerialCtrlReg |= ETH_SET_GMII_SPEED_1000_MASK;
+		/* the 100/10 bit doesn't matter in this case */
+		break;
+	case MV_ETH_SPEED_100:
+		portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK;
+		portSerialCtrlReg &= ~ETH_SET_GMII_SPEED_1000_MASK;
+		portSerialCtrlReg |= ETH_SET_MII_SPEED_100_MASK;
+		break;
+	case MV_ETH_SPEED_10:
+		portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK;
+		portSerialCtrlReg &= ~ETH_SET_GMII_SPEED_1000_MASK;
+		portSerialCtrlReg &= ~ETH_SET_MII_SPEED_100_MASK;
+		break;
+	default:
+		mvOsPrintf("Unexpected Speed value %d\n", speed);
+		return MV_BAD_PARAM;
+	}
+
+	switch (duplex) {
+	case MV_ETH_DUPLEX_AN:
+		portSerialCtrlReg &= ~ETH_DISABLE_DUPLEX_AUTO_NEG_MASK;
+		/* the other bits don't matter in this case */
+		break;
+	case MV_ETH_DUPLEX_HALF:
+		portSerialCtrlReg |= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK;
+		portSerialCtrlReg &= ~ETH_SET_FULL_DUPLEX_MASK;
+		break;
+	case MV_ETH_DUPLEX_FULL:
+		portSerialCtrlReg |= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK;
+		portSerialCtrlReg |= ETH_SET_FULL_DUPLEX_MASK;
+		break;
+	default:
+		mvOsPrintf("Unexpected Duplex value %d\n", duplex);
+		return MV_BAD_PARAM;
+	}
+
+	MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(portNo), portSerialCtrlReg);
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvNetaSpeedDuplexGet -
+*
+* DESCRIPTION:
+*       Gets port speed
+*	Gets port duplex
+*
+* INPUT:
+* 	int portNo - port number
+* OUTPUT:
+* 	MV_ETH_PORT_SPEED *speed - port speed
+*	MV_ETH_PORT_DUPLEX *duplex - port duplex mode
+*
+* RETURN:
+*******************************************************************************/
+MV_STATUS mvNetaSpeedDuplexGet(int portNo, MV_ETH_PORT_SPEED *speed, MV_ETH_PORT_DUPLEX *duplex)
+{
+	MV_U32 regVal;
+	if ((portNo < 0) || (portNo >= mvNetaHalData.maxPort))
+		return MV_BAD_PARAM;
+
+	/* Check validity */
+	if (!speed || !duplex)
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(portNo));
+	if (!(regVal & ETH_DISABLE_SPEED_AUTO_NEG_MASK))
+		*speed = MV_ETH_SPEED_AN;
+	else if (regVal & ETH_SET_GMII_SPEED_1000_MASK)
+		*speed = MV_ETH_SPEED_1000;
+	else if (regVal & ETH_SET_MII_SPEED_100_MASK)
+		*speed = MV_ETH_SPEED_100;
+	else
+		*speed = MV_ETH_SPEED_10;
+
+	if (!(regVal & ETH_DISABLE_DUPLEX_AUTO_NEG_MASK))
+		*duplex = MV_ETH_DUPLEX_AN;
+	else if (regVal & ETH_SET_FULL_DUPLEX_MASK)
+		*duplex = MV_ETH_DUPLEX_FULL;
+	else
+		*duplex = MV_ETH_DUPLEX_HALF;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaFlowCtrlSet - Set Flow Control of the port.
+*
+* DESCRIPTION:
+*       This function configures the port's Flow Control properties.
+*
+* INPUT:
+*       int				port		- Port number
+*       MV_ETH_PORT_FC  flowControl - Flow control of the port.
+*
+* RETURN:   MV_STATUS
+*       MV_OK           - Success
+*       MV_OUT_OF_RANGE - Failed. Port is out of valid range
+*       MV_BAD_VALUE    - Value flowControl parameters is not valid
+*
+*******************************************************************************/
+MV_STATUS mvNetaFlowCtrlSet(int port, MV_ETH_PORT_FC flowControl)
+{
+	MV_U32 regVal;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort))
+		return MV_OUT_OF_RANGE;
+
+	regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
+
+	switch (flowControl) {
+	case MV_ETH_FC_AN_NO:
+		regVal &= ~ETH_DISABLE_FC_AUTO_NEG_MASK;
+		regVal &= ~ETH_ADVERTISE_SYM_FC_MASK;
+		break;
+
+	case MV_ETH_FC_AN_SYM:
+		regVal &= ~ETH_DISABLE_FC_AUTO_NEG_MASK;
+		regVal |= ETH_ADVERTISE_SYM_FC_MASK;
+		break;
+
+	case MV_ETH_FC_DISABLE:
+		regVal |= ETH_DISABLE_FC_AUTO_NEG_MASK;
+		regVal &= ~ETH_SET_FLOW_CTRL_MASK;
+		break;
+
+	case MV_ETH_FC_ENABLE:
+		regVal |= ETH_DISABLE_FC_AUTO_NEG_MASK;
+		regVal |= ETH_SET_FLOW_CTRL_MASK;
+		break;
+
+	default:
+		mvOsPrintf("ethDrv: Unexpected FlowControl value %d\n", flowControl);
+		return MV_BAD_VALUE;
+	}
+
+	MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), regVal);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaFlowCtrlGet - Get Flow Control configuration of the port.
+*
+* DESCRIPTION:
+*       This function returns the port's Flow Control properties.
+*
+* INPUT:
+*       int				port		- Port number
+*
+* OUTPUT:
+*       MV_ETH_PORT_FC  *flowCntrl	- Flow control of the port.
+*
+* RETURN:   MV_STATUS
+*       MV_OK           - Success
+*       MV_OUT_OF_RANGE - Failed. Port is out of valid range
+*
+*******************************************************************************/
+MV_STATUS mvNetaFlowCtrlGet(int port, MV_ETH_PORT_FC *pFlowCntrl)
+{
+	MV_U32 regVal;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort))
+		return MV_OUT_OF_RANGE;
+
+	regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
+
+	if (regVal & ETH_DISABLE_FC_AUTO_NEG_MASK) {
+		/* Auto negotiation is disabled */
+		if (regVal & ETH_SET_FLOW_CTRL_MASK)
+			*pFlowCntrl = MV_ETH_FC_ENABLE;
+		else
+			*pFlowCntrl = MV_ETH_FC_DISABLE;
+	} else {
+		/* Auto negotiation is enabled */
+		if (regVal & ETH_ADVERTISE_SYM_FC_MASK)
+			*pFlowCntrl = MV_ETH_FC_AN_SYM;
+		else
+			*pFlowCntrl = MV_ETH_FC_AN_NO;
+	}
+	return MV_OK;
+}
+
+MV_STATUS mvNetaPortEnable(int port)
+{
+	if (!MV_PON_PORT(port)) {
+		MV_U32 regVal;
+
+		/* Enable port */
+		regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
+		regVal |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK | ETH_PORT_ENABLE_MASK);
+
+		MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), regVal);
+
+		/* If Link is UP, Start RX and TX traffic */
+		if (MV_REG_READ(ETH_PORT_STATUS_REG(port)) & ETH_LINK_UP_MASK)
+			return mvNetaPortUp(port);
+	}
+	return MV_NOT_READY;
+}
+
+MV_STATUS mvNetaPortDisable(int port)
+{
+	MV_U32 regData;
+
+	mvNetaPortDown(port);
+
+	if (!MV_PON_PORT(port)) {
+		/* Reset the Enable bit in the Serial Control Register */
+		regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
+		regData &= ~(ETH_PORT_ENABLE_MASK);
+		MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), regData);
+	}
+	/* Wait about 200 usec */
+	mvOsUDelay(200);
+
+	return MV_OK;
+}
+
+MV_BOOL		mvNetaLinkIsUp(port)
+{
+	MV_U32	regVal;
+
+	if (MV_PON_PORT(port))
+		return MV_TRUE;
+
+	regVal = MV_REG_READ(ETH_PORT_STATUS_REG(port));
+	if (regVal & ETH_LINK_UP_MASK)
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+MV_STATUS mvNetaLinkStatus(int port, MV_ETH_PORT_STATUS *pStatus)
+{
+	MV_U32 regVal;
+
+	if (MV_PON_PORT(port)) {
+		/* FIXME: --BK */
+		pStatus->linkup = MV_TRUE;
+		pStatus->speed = MV_ETH_SPEED_1000;
+		pStatus->duplex = MV_ETH_DUPLEX_FULL;
+		pStatus->rxFc = MV_ETH_FC_DISABLE;
+		pStatus->txFc = MV_ETH_FC_DISABLE;
+		return MV_OK;
+	}
+
+	regVal = MV_REG_READ(ETH_PORT_STATUS_REG(port));
+
+	if (regVal & ETH_GMII_SPEED_1000_MASK)
+		pStatus->speed = MV_ETH_SPEED_1000;
+	else if (regVal & ETH_MII_SPEED_100_MASK)
+		pStatus->speed = MV_ETH_SPEED_100;
+	else
+		pStatus->speed = MV_ETH_SPEED_10;
+
+	if (regVal & ETH_LINK_UP_MASK)
+		pStatus->linkup = MV_TRUE;
+	else
+		pStatus->linkup = MV_FALSE;
+
+	if (regVal & ETH_FULL_DUPLEX_MASK)
+		pStatus->duplex = MV_ETH_DUPLEX_FULL;
+	else
+		pStatus->duplex = MV_ETH_DUPLEX_HALF;
+
+	pStatus->txFc = MV_ETH_FC_DISABLE;
+	if (regVal & ETH_FLOW_CTRL_ENABLED_MASK)
+		pStatus->rxFc = MV_ETH_FC_ENABLE;
+	else
+		pStatus->rxFc = MV_ETH_FC_DISABLE;
+
+	return MV_OK;
+}
+
+#endif /* MV_ETH_GMAC_NEW */
+
+/******************************************************************************/
+/*                      MAC Filtering functions                               */
+/******************************************************************************/
+
+#ifdef CONFIG_MV_ETH_LEGACY_PARSER
+/*******************************************************************************
+* mvNetaRxUnicastPromiscSet - Configure Fitering mode of Ethernet port
+*
+* DESCRIPTION:
+*       This routine used to free buffers attached to the Rx ring and should
+*       be called only when Giga Ethernet port is Down
+*
+* INPUT:
+*		int			portNo			- Port number.
+*       MV_BOOL     isPromisc       - Promiscous mode
+*                                   MV_TRUE  - accept all Broadcast, Multicast
+*                                              and Unicast packets
+*                                   MV_FALSE - accept all Broadcast,
+*                                              specially added Multicast and
+*                                              single Unicast packets
+*
+* RETURN:   MV_STATUS   MV_OK - Success, Other - Failure
+*
+*******************************************************************************/
+MV_STATUS mvNetaRxUnicastPromiscSet(int port, MV_BOOL isPromisc)
+{
+	MV_U32 portCfgReg, regVal;
+
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(port));
+	regVal = MV_REG_READ(ETH_TYPE_PRIO_REG(port));
+
+	/* Set / Clear UPM bit in port configuration register */
+	if (isPromisc == MV_TRUE) {
+		/* Accept all Unicast addresses */
+		portCfgReg |= ETH_UNICAST_PROMISCUOUS_MODE_MASK;
+		regVal |= ETH_FORCE_UNICAST_MASK;
+		MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(port), 0xFFFF);
+		MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(port), 0xFFFFFFFF);
+	} else {
+		/* Reject all Unicast addresses */
+		portCfgReg &= ~ETH_UNICAST_PROMISCUOUS_MODE_MASK;
+		regVal &= ~ETH_FORCE_UNICAST_MASK;
+	}
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(port), portCfgReg);
+	MV_REG_WRITE(ETH_TYPE_PRIO_REG(port), regVal);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaMacAddrSet - This function Set the port Unicast address.
+*
+* DESCRIPTION:
+*       This function Set the port Ethernet MAC address. This address
+*       will be used to send Pause frames if enabled. Packets with this
+*       address will be accepted and dispatched to default RX queue
+*
+* INPUT:
+*       int*    port    - Ethernet port.
+*       char*   pAddr   - Address to be set
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success,  Other - Faulure
+*
+*******************************************************************************/
+MV_STATUS mvNetaMacAddrSet(int portNo, unsigned char *pAddr, int queue)
+{
+	unsigned int macH;
+	unsigned int macL;
+
+	if (queue >= CONFIG_MV_ETH_RXQ) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", queue);
+		return MV_BAD_PARAM;
+	}
+
+	if (queue != -1) {
+		macL = (pAddr[4] << 8) | (pAddr[5]);
+		macH = (pAddr[0] << 24) | (pAddr[1] << 16) | (pAddr[2] << 8) | (pAddr[3] << 0);
+
+		MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(portNo), macL);
+		MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(portNo), macH);
+	}
+
+	/* Accept frames of this address */
+	netaSetUcastAddr(portNo, pAddr[5], queue);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaMacAddrGet - This function returns the port Unicast address.
+*
+* DESCRIPTION:
+*       This function returns the port Ethernet MAC address.
+*
+* INPUT:
+*       int     portNo          - Ethernet port number.
+*       char*   pAddr           - Pointer where address will be written to
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success,  Other - Faulure
+*
+*******************************************************************************/
+MV_STATUS mvNetaMacAddrGet(int portNo, unsigned char *pAddr)
+{
+	unsigned int macH;
+	unsigned int macL;
+
+	if (pAddr == NULL) {
+		mvOsPrintf("mvNetaMacAddrGet: NULL pointer.\n");
+		return MV_BAD_PARAM;
+	}
+
+	macH = MV_REG_READ(ETH_MAC_ADDR_HIGH_REG(portNo));
+	macL = MV_REG_READ(ETH_MAC_ADDR_LOW_REG(portNo));
+	pAddr[0] = (macH >> 24) & 0xff;
+	pAddr[1] = (macH >> 16) & 0xff;
+	pAddr[2] = (macH >> 8) & 0xff;
+	pAddr[3] = macH & 0xff;
+	pAddr[4] = (macL >> 8) & 0xff;
+	pAddr[5] = macL & 0xff;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaMcastCrc8Get - Calculate CRC8 of MAC address.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       MV_U8*  pAddr           - Address to calculate CRC-8
+*
+* RETURN: MV_U8 - CRC-8 of this MAC address
+*
+*******************************************************************************/
+static MV_U8 mvNetaMcastCrc8Get(MV_U8 *pAddr)
+{
+	unsigned int macH;
+	unsigned int macL;
+	int macArray[48];
+	int crc[8];
+	int i;
+	unsigned char crcResult = 0;
+
+	/* Calculate CRC-8 out of the given address */
+	macH = (pAddr[0] << 8) | (pAddr[1]);
+	macL = (pAddr[2] << 24) | (pAddr[3] << 16) | (pAddr[4] << 8) | (pAddr[5] << 0);
+
+	for (i = 0; i < 32; i++)
+		macArray[i] = (macL >> i) & 0x1;
+
+	for (i = 32; i < 48; i++)
+		macArray[i] = (macH >> (i - 32)) & 0x1;
+
+	crc[0] = macArray[45] ^ macArray[43] ^ macArray[40] ^ macArray[39] ^
+	    macArray[35] ^ macArray[34] ^ macArray[31] ^ macArray[30] ^
+	    macArray[28] ^ macArray[23] ^ macArray[21] ^ macArray[19] ^
+	    macArray[18] ^ macArray[16] ^ macArray[14] ^ macArray[12] ^
+	    macArray[8] ^ macArray[7] ^ macArray[6] ^ macArray[0];
+
+	crc[1] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^
+	    macArray[41] ^ macArray[39] ^ macArray[36] ^ macArray[34] ^
+	    macArray[32] ^ macArray[30] ^ macArray[29] ^ macArray[28] ^
+	    macArray[24] ^ macArray[23] ^ macArray[22] ^ macArray[21] ^
+	    macArray[20] ^ macArray[18] ^ macArray[17] ^ macArray[16] ^
+	    macArray[15] ^ macArray[14] ^ macArray[13] ^ macArray[12] ^
+	    macArray[9] ^ macArray[6] ^ macArray[1] ^ macArray[0];
+
+	crc[2] = macArray[47] ^ macArray[46] ^ macArray[44] ^ macArray[43] ^
+	    macArray[42] ^ macArray[39] ^ macArray[37] ^ macArray[34] ^
+	    macArray[33] ^ macArray[29] ^ macArray[28] ^ macArray[25] ^
+	    macArray[24] ^ macArray[22] ^ macArray[17] ^ macArray[15] ^
+	    macArray[13] ^ macArray[12] ^ macArray[10] ^ macArray[8] ^
+	    macArray[6] ^ macArray[2] ^ macArray[1] ^ macArray[0];
+
+	crc[3] = macArray[47] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^
+	    macArray[40] ^ macArray[38] ^ macArray[35] ^ macArray[34] ^
+	    macArray[30] ^ macArray[29] ^ macArray[26] ^ macArray[25] ^
+	    macArray[23] ^ macArray[18] ^ macArray[16] ^ macArray[14] ^
+	    macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[7] ^ macArray[3] ^ macArray[2] ^ macArray[1];
+
+	crc[4] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[41] ^
+	    macArray[39] ^ macArray[36] ^ macArray[35] ^ macArray[31] ^
+	    macArray[30] ^ macArray[27] ^ macArray[26] ^ macArray[24] ^
+	    macArray[19] ^ macArray[17] ^ macArray[15] ^ macArray[14] ^
+	    macArray[12] ^ macArray[10] ^ macArray[8] ^ macArray[4] ^ macArray[3] ^ macArray[2];
+
+	crc[5] = macArray[47] ^ macArray[46] ^ macArray[45] ^ macArray[42] ^
+	    macArray[40] ^ macArray[37] ^ macArray[36] ^ macArray[32] ^
+	    macArray[31] ^ macArray[28] ^ macArray[27] ^ macArray[25] ^
+	    macArray[20] ^ macArray[18] ^ macArray[16] ^ macArray[15] ^
+	    macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[5] ^ macArray[4] ^ macArray[3];
+
+	crc[6] = macArray[47] ^ macArray[46] ^ macArray[43] ^ macArray[41] ^
+	    macArray[38] ^ macArray[37] ^ macArray[33] ^ macArray[32] ^
+	    macArray[29] ^ macArray[28] ^ macArray[26] ^ macArray[21] ^
+	    macArray[19] ^ macArray[17] ^ macArray[16] ^ macArray[14] ^
+	    macArray[12] ^ macArray[10] ^ macArray[6] ^ macArray[5] ^ macArray[4];
+
+	crc[7] = macArray[47] ^ macArray[44] ^ macArray[42] ^ macArray[39] ^
+	    macArray[38] ^ macArray[34] ^ macArray[33] ^ macArray[30] ^
+	    macArray[29] ^ macArray[27] ^ macArray[22] ^ macArray[20] ^
+	    macArray[18] ^ macArray[17] ^ macArray[15] ^ macArray[13] ^
+	    macArray[11] ^ macArray[7] ^ macArray[6] ^ macArray[5];
+
+	for (i = 0; i < 8; i++)
+		crcResult = crcResult | (crc[i] << i);
+
+	return crcResult;
+}
+
+/*******************************************************************************
+* mvNetaMcastAddrSet - Multicast address settings.
+*
+* DESCRIPTION:
+*       This API controls the MV device MAC multicast support.
+*       The MV device supports multicast using two tables:
+*       1) Special Multicast Table for MAC addresses of the form
+*          0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF).
+*          The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+*          Table entries in the DA-Filter table.
+*          In this case, the function calls netaPortSmcAddr() routine to set the
+*          Special Multicast Table.
+*       2) Other Multicast Table for multicast of another type. A CRC-8bit
+*          is used as an index to the Other Multicast Table entries in the
+*          DA-Filter table.
+*          In this case, the function calculates the CRC-8bit value and calls
+*          netaPortOmcAddr() routine to set the Other Multicast Table.
+*
+* INPUT:
+*       void*   port            - Ethernet port.
+*       MV_U8*  pAddr           - Address to be set
+*       int     queue           - RX queue to capture all packets with this
+*                               Multicast MAC address.
+*                               -1 means delete this Multicast address.
+*
+* RETURN: MV_STATUS
+*       MV_TRUE - Success, Other - Failure
+*
+*******************************************************************************/
+MV_STATUS mvNetaMcastAddrSet(int port, MV_U8 *pAddr, int queue)
+{
+	if (queue >= CONFIG_MV_ETH_RXQ) {
+		mvOsPrintf("ethPort %d: RX queue #%d is out of range\n", port, queue);
+		return MV_BAD_PARAM;
+	}
+
+	if ((pAddr[0] == 0x01) && (pAddr[1] == 0x00) && (pAddr[2] == 0x5E) && (pAddr[3] == 0x00) && (pAddr[4] == 0x00)) {
+		netaSetSpecialMcastAddr(port, pAddr[5], queue);
+	} else {
+		unsigned char crcResult = 0;
+		MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(port);
+
+		crcResult = mvNetaMcastCrc8Get(pAddr);
+
+		/* Check Add counter for this CRC value */
+		if (queue == -1) {
+			if (pPortCtrl->mcastCount[crcResult] == 0) {
+				mvOsPrintf("ethPort #%d: No valid Mcast for crc8=0x%02x\n", port, (unsigned)crcResult);
+				return MV_NO_SUCH;
+			}
+
+			pPortCtrl->mcastCount[crcResult]--;
+			if (pPortCtrl->mcastCount[crcResult] != 0) {
+				mvOsPrintf("ethPort #%d: After delete there are %d valid Mcast for crc8=0x%02x\n",
+					   pPortCtrl->portNo, pPortCtrl->mcastCount[crcResult], (unsigned)crcResult);
+				return MV_NO_CHANGE;
+			}
+		} else {
+			pPortCtrl->mcastCount[crcResult]++;
+			if (pPortCtrl->mcastCount[crcResult] > 1) {
+				mvOsPrintf("ethPort #%d: Valid Mcast for crc8=0x%02x already exists\n",
+					   port, (unsigned)crcResult);
+				return MV_NO_CHANGE;
+			}
+		}
+		netaSetOtherMcastAddr(port, crcResult, queue);
+	}
+	return MV_OK;
+}
+#endif /* CONFIG_MV_ETH_LEGACY_PARSER */
+
+/*******************************************************************************
+* mvNetaSetUcastTable - Unicast address settings.
+*
+* DESCRIPTION:
+*      Set all entries in the Unicast MAC Table queue==-1 means reject all
+* INPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+void mvNetaSetUcastTable(int port, int queue)
+{
+	int offset;
+	MV_U32 regValue;
+
+	if (queue == -1) {
+		regValue = 0;
+	} else {
+		regValue = (((0x01 | (queue << 1)) << 0) |
+			    ((0x01 | (queue << 1)) << 8) |
+			    ((0x01 | (queue << 1)) << 16) | ((0x01 | (queue << 1)) << 24));
+	}
+
+	for (offset = 0; offset <= 0xC; offset += 4)
+		MV_REG_WRITE((ETH_DA_FILTER_UCAST_BASE(port) + offset), regValue);
+}
+
+/*******************************************************************************
+* mvNetaSetSpecialMcastTable - Special Multicast address settings.
+*
+* DESCRIPTION:
+*   Set all entries to the Special Multicast MAC Table. queue==-1 means reject all
+* INPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_VOID mvNetaSetSpecialMcastTable(int portNo, int queue)
+{
+	int offset;
+	MV_U32 regValue;
+
+	if (queue == -1) {
+		regValue = 0;
+	} else {
+		regValue = (((0x01 | (queue << 1)) << 0) |
+			    ((0x01 | (queue << 1)) << 8) |
+			    ((0x01 | (queue << 1)) << 16) | ((0x01 | (queue << 1)) << 24));
+	}
+
+	for (offset = 0; offset <= 0xFC; offset += 4)
+		MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(portNo) + offset), regValue);
+}
+
+/*******************************************************************************
+* mvNetaSetOtherMcastTable - Other Multicast address settings.
+*
+* DESCRIPTION:
+*   Set all entries to the Other Multicast MAC Table. queue==-1 means reject all
+* INPUT:
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_VOID mvNetaSetOtherMcastTable(int portNo, int queue)
+{
+	int offset;
+	MV_U32 regValue;
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(portNo);
+
+	if (queue == -1) {
+		memset(pPortCtrl->mcastCount, 0, sizeof(pPortCtrl->mcastCount));
+		regValue = 0;
+	} else {
+		memset(pPortCtrl->mcastCount, 1, sizeof(pPortCtrl->mcastCount));
+		regValue = (((0x01 | (queue << 1)) << 0) |
+			    ((0x01 | (queue << 1)) << 8) |
+			    ((0x01 | (queue << 1)) << 16) | ((0x01 | (queue << 1)) << 24));
+	}
+
+	for (offset = 0; offset <= 0xFC; offset += 4)
+		MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(portNo) + offset), regValue);
+}
+
+#ifdef CONFIG_MV_ETH_LEGACY_PARSER
+/*******************************************************************************
+* netaSetUcastAddr - This function Set the port unicast address table
+*
+* DESCRIPTION:
+*       This function locates the proper entry in the Unicast table for the
+*       specified MAC nibble and sets its properties according to function
+*       parameters.
+*
+* INPUT:
+*       int     portNo		- Port number.
+*       MV_U8   lastNibble	- Unicast MAC Address last nibble.
+*       int     queue		- Rx queue number for this MAC address.
+*                           		value "-1" means remove address.
+*
+* OUTPUT:
+*       This function add/removes MAC addresses from the port unicast address
+*       table.
+*
+* RETURN:
+*       MV_TRUE is output succeeded.
+*       MV_FALSE if option parameter is invalid.
+*
+*******************************************************************************/
+static MV_BOOL netaSetUcastAddr(int portNo, MV_U8 lastNibble, int queue)
+{
+	unsigned int unicastReg;
+	unsigned int tblOffset;
+	unsigned int regOffset;
+
+	/* Locate the Unicast table entry */
+	lastNibble = (0xf & lastNibble);
+	tblOffset = (lastNibble / 4) * 4;	/* Register offset from unicast table base */
+	regOffset = lastNibble % 4;	/* Entry offset within the above register */
+
+	unicastReg = MV_REG_READ((ETH_DA_FILTER_UCAST_BASE(portNo) + tblOffset));
+
+	if (queue == -1) {
+		/* Clear accepts frame bit at specified unicast DA table entry */
+		unicastReg &= ~(0xFF << (8 * regOffset));
+	} else {
+		unicastReg &= ~(0xFF << (8 * regOffset));
+		unicastReg |= ((0x01 | (queue << 1)) << (8 * regOffset));
+	}
+	MV_REG_WRITE((ETH_DA_FILTER_UCAST_BASE(portNo) + tblOffset), unicastReg);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* netaSetSpecialMcastAddr - Special Multicast address settings.
+*
+* DESCRIPTION:
+*       This routine controls the MV device special MAC multicast support.
+*       The Special Multicast Table for MAC addresses supports MAC of the form
+*       0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF).
+*       The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+*       Table entries in the DA-Filter table.
+*       This function set the Special Multicast Table appropriate entry
+*       according to the argument given.
+*
+* INPUT:
+*       int     port      Port number.
+*       unsigned char   mcByte      Multicast addr last byte (MAC DA[7:0] bits).
+*       int          queue      Rx queue number for this MAC address.
+*       int             option      0 = Add, 1 = remove address.
+*
+* OUTPUT:
+*       See description.
+*
+* RETURN:
+*       MV_TRUE is output succeeded.
+*       MV_FALSE if option parameter is invalid.
+*
+*******************************************************************************/
+static MV_BOOL netaSetSpecialMcastAddr(int port, MV_U8 lastByte, int queue)
+{
+	unsigned int smcTableReg;
+	unsigned int tblOffset;
+	unsigned int regOffset;
+
+	/* Locate the SMC table entry */
+	tblOffset = (lastByte / 4);	/* Register offset from SMC table base    */
+	regOffset = lastByte % 4;	/* Entry offset within the above register */
+
+	smcTableReg = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(port) + tblOffset * 4));
+
+	if (queue == -1) {
+		/* Clear accepts frame bit at specified Special DA table entry */
+		smcTableReg &= ~(0xFF << (8 * regOffset));
+	} else {
+		smcTableReg &= ~(0xFF << (8 * regOffset));
+		smcTableReg |= ((0x01 | (queue << 1)) << (8 * regOffset));
+	}
+	MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(port) + tblOffset * 4), smcTableReg);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* netaSetOtherMcastAddr - Multicast address settings.
+*
+* DESCRIPTION:
+*       This routine controls the MV device Other MAC multicast support.
+*       The Other Multicast Table is used for multicast of another type.
+*       A CRC-8bit is used as an index to the Other Multicast Table entries
+*       in the DA-Filter table.
+*       The function gets the CRC-8bit value from the calling routine and
+*       set the Other Multicast Table appropriate entry according to the
+*       CRC-8 argument given.
+*
+* INPUT:
+*       int     port        Port number.
+*       MV_U8   crc8        A CRC-8bit (Polynomial: x^8+x^2+x^1+1).
+*       int     queue       Rx queue number for this MAC address.
+*
+* OUTPUT:
+*       See description.
+*
+* RETURN:
+*       MV_TRUE is output succeeded.
+*       MV_FALSE if option parameter is invalid.
+*
+*******************************************************************************/
+static MV_BOOL netaSetOtherMcastAddr(int port, MV_U8 crc8, int queue)
+{
+	unsigned int omcTableReg;
+	unsigned int tblOffset;
+	unsigned int regOffset;
+
+	/* Locate the OMC table entry */
+	tblOffset = (crc8 / 4) * 4;	/* Register offset from OMC table base    */
+	regOffset = crc8 % 4;	/* Entry offset within the above register */
+
+	omcTableReg = MV_REG_READ((ETH_DA_FILTER_OTH_MCAST_BASE(port) + tblOffset));
+
+	if (queue == -1) {
+		/* Clear accepts frame bit at specified Other DA table entry */
+		omcTableReg &= ~(0xFF << (8 * regOffset));
+	} else {
+		omcTableReg &= ~(0xFF << (8 * regOffset));
+		omcTableReg |= ((0x01 | (queue << 1)) << (8 * regOffset));
+	}
+
+	MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(port) + tblOffset), omcTableReg);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvNetaTosToRxqSet - Map packets with special TOS value to special RX queue
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		int     portNo		- Port number.
+*       int     tos         - TOS value in the IP header of the packet
+*       int     rxq         - RX Queue for packets with the configured TOS value
+*                           Negative value (-1) means no special processing for these packets,
+*                           so they will be processed as regular packets.
+*
+* RETURN:   MV_STATUS
+*******************************************************************************/
+MV_STATUS   mvNetaTosToRxqSet(int port, int tos, int rxq)
+{
+	MV_U32          regValue;
+	int             regIdx, regOffs;
+
+	if ((rxq < 0) || (rxq >= MV_ETH_MAX_RXQ)) {
+		mvOsPrintf("eth_%d: RX queue #%d is out of range\n", port, rxq);
+		return MV_BAD_PARAM;
+	}
+	if (tos > 0xFF) {
+		mvOsPrintf("eth_%d: tos=0x%x is out of range\n", port, tos);
+		return MV_BAD_PARAM;
+	}
+	regIdx  = mvOsDivide(tos >> 2, 10);
+	regOffs = mvOsReminder(tos >> 2, 10);
+
+	regValue = MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(port, regIdx));
+	regValue &= ~(0x7 << (regOffs*3));
+	regValue |= (rxq << (regOffs*3));
+
+	MV_REG_WRITE(ETH_DIFF_SERV_PRIO_REG(port, regIdx), regValue);
+	return MV_OK;
+}
+
+int     mvNetaTosToRxqGet(int port, int tos)
+{
+	MV_U32          regValue;
+	int             regIdx, regOffs, rxq;
+
+	if (tos > 0xFF) {
+		mvOsPrintf("eth_%d: tos=0x%x is out of range\n", port, tos);
+		return -1;
+	}
+	regIdx  = mvOsDivide(tos >> 2, 10);
+	regOffs = mvOsReminder(tos >> 2, 10);
+
+	regValue = MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(port, regIdx));
+	rxq = (regValue >> (regOffs * 3));
+	rxq &= 0x7;
+
+	return rxq;
+}
+
+/*******************************************************************************
+* mvNetaVprioToRxqSet - Map packets with special VLAN priority to special RX queue
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       int     portNo  - Port number.
+*       int     vprio   - Vlan Priority value in packet header
+*       int     rxq     - RX Queue for packets with the configured TOS value
+*                         Negative value (-1) means no special processing for these packets,
+*                         so they will be processed as regular packets.
+*
+* RETURN:   MV_STATUS
+*******************************************************************************/
+MV_STATUS   mvNetaVprioToRxqSet(int port, int vprio, int rxq)
+{
+	MV_U32          regValue;
+
+	if ((rxq < 0) || (rxq >= MV_ETH_MAX_RXQ)) {
+		mvOsPrintf("eth_%d: RX queue #%d is out of range\n", port, rxq);
+		return MV_BAD_PARAM;
+	}
+	if (vprio > 0x7) {
+		mvOsPrintf("eth_%d: vprio=0x%x is out of range\n", port, vprio);
+		return MV_BAD_PARAM;
+	}
+
+	regValue = MV_REG_READ(ETH_VLAN_TAG_TO_PRIO_REG(port));
+	regValue &= ~(0x7 << (vprio * 3));
+	regValue |= (rxq << (vprio * 3));
+
+	MV_REG_WRITE(ETH_VLAN_TAG_TO_PRIO_REG(port), regValue);
+	return MV_OK;
+}
+
+int     mvNetaVprioToRxqGet(int port, int vprio)
+{
+	MV_U32          regValue;
+	int             rxq;
+
+	if (vprio > 0x7) {
+		mvOsPrintf("eth_%d: vprio=0x%x is out of range\n", port, vprio);
+		return -1;
+	}
+
+	regValue = MV_REG_READ(ETH_VLAN_TAG_TO_PRIO_REG(port));
+	rxq = (regValue >> (vprio * 3));
+	rxq &= 0x7;
+
+	return rxq;
+}
+#endif /* CONFIG_MV_ETH_LEGACY_PARSER */
+
+/******************************************************************************/
+/*                         PHY Control Functions                              */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvNetaPhyAddrSet - Set the ethernet port PHY address.
+*
+* DESCRIPTION:
+*       This routine set the ethernet port PHY address according to given
+*       parameter.
+*
+* INPUT:
+*       int     portNo		- Port number.
+*       int     phyAddr     - PHY address
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+void mvNetaPhyAddrSet(int port, int phyAddr)
+{
+	unsigned int regData;
+
+	regData = MV_REG_READ(ETH_PHY_ADDR_REG(port));
+
+	regData &= ~ETH_PHY_ADDR_MASK;
+	regData |= phyAddr;
+
+	MV_REG_WRITE(ETH_PHY_ADDR_REG(port), regData);
+
+    /* Enable PHY polling */
+    regData = MV_REG_READ(ETH_UNIT_CONTROL_REG(port));
+    regData |= ETH_PHY_POLLING_ENABLE_MASK;
+    MV_REG_WRITE(ETH_UNIT_CONTROL_REG(port), regData);
+
+	return;
+}
+
+/*******************************************************************************
+* mvNetaPhyAddrGet - Get the ethernet port PHY address.
+*
+* DESCRIPTION:
+*       This routine returns the given ethernet port PHY address.
+*
+* INPUT:
+*   int     portNo		- Port number.
+*
+*
+* RETURN: int - PHY address.
+*
+*******************************************************************************/
+int mvNetaPhyAddrGet(int port)
+{
+	unsigned int 	regData;
+	int		phy;
+
+	regData = MV_REG_READ(ETH_PHY_ADDR_REG(port));
+
+	phy = (regData >> (5 * port));
+	phy &= 0x1F;
+	return phy;
+}
+
+/******************************************************************************/
+/*                Descriptor handling Functions                               */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvNetaDescRingReset -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       MV_NETA_PORT_CTRL	*pPortCtrl	NETA Port Control srtucture.
+*       int			queue		Number of Rx queue.
+*
+* OUTPUT:
+*
+* RETURN: None
+*
+*******************************************************************************/
+static void mvNetaDescRingReset(MV_NETA_QUEUE_CTRL *pQueueCtrl)
+{
+	int		descrNum = (pQueueCtrl->lastDesc + 1);
+	char	*pDesc = pQueueCtrl->pFirst;
+
+	if (pDesc == NULL)
+		return;
+
+	/* reset ring of descriptors */
+	memset(pDesc, 0, (descrNum * NETA_DESC_ALIGNED_SIZE));
+	mvOsCacheFlush(NULL, pDesc, (descrNum * NETA_DESC_ALIGNED_SIZE));
+	pQueueCtrl->nextToProc = 0;
+}
+
+/* Reset all RXQs */
+void mvNetaRxReset(int port)
+{
+	int rxq;
+	MV_NETA_RXQ_CTRL *pRxqCtrl;
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortCtrl[port];
+
+	MV_REG_WRITE(NETA_PORT_RX_RESET_REG(port), NETA_PORT_RX_DMA_RESET_MASK);
+	for (rxq = 0; rxq < pPortCtrl->rxqNum ; rxq++) {
+		pRxqCtrl = mvNetaRxqHndlGet(port, rxq);
+		mvNetaDescRingReset(&pRxqCtrl->queueCtrl);
+	}
+	MV_REG_WRITE(NETA_PORT_RX_RESET_REG(port), 0);
+}
+
+/* Reset all TXQs */
+void mvNetaTxpReset(int port, int txp)
+{
+	int txq;
+	MV_NETA_TXQ_CTRL *pTxqCtrl;
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortCtrl[port];
+
+	MV_REG_WRITE(NETA_PORT_TX_RESET_REG(port, txp), NETA_PORT_TX_DMA_RESET_MASK);
+	for (txq = 0; txq < pPortCtrl->txqNum; txq++) {
+		pTxqCtrl = mvNetaTxqHndlGet(port, txp, txq);
+		mvNetaDescRingReset(&pTxqCtrl->queueCtrl);
+	}
+	MV_REG_WRITE(NETA_PORT_TX_RESET_REG(port, txp), 0);
+}
+
+/*******************************************************************************
+* mvNetaRxqInit -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*   int     portNo		- Port number.
+*   int		queue		- Number of Rx queue.
+*	int		descrNum	- Number of descriptors
+*
+* OUTPUT:
+*
+* RETURN: None
+*
+*******************************************************************************/
+MV_NETA_RXQ_CTRL *mvNetaRxqInit(int port, int queue, int descrNum)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortCtrl[port];
+	MV_NETA_RXQ_CTRL *pRxqCtrl = &pPortCtrl->pRxQueue[queue];
+	MV_NETA_QUEUE_CTRL *pQueueCtrl = &pRxqCtrl->queueCtrl;
+	int descSize;
+
+	/* Allocate memory for RX descriptors */
+	descSize = ((descrNum * NETA_DESC_ALIGNED_SIZE) + CPU_D_CACHE_LINE_SIZE);
+	pQueueCtrl->descBuf.bufVirtPtr =
+	    mvNetaDescrMemoryAlloc(pPortCtrl, descSize, &pQueueCtrl->descBuf.bufPhysAddr, &pQueueCtrl->descBuf.memHandle);
+
+	pQueueCtrl->descBuf.bufSize = descSize;
+
+	if (pQueueCtrl->descBuf.bufVirtPtr == NULL) {
+		mvOsPrintf("EthPort #%d, rxQ=%d: Can't allocate %d bytes for %d RX descr\n",
+			   pPortCtrl->portNo, queue, descSize, descrNum);
+		return NULL;
+	}
+
+	/* Make sure descriptor address is cache line size aligned  */
+	pQueueCtrl->pFirst = (char *)MV_ALIGN_UP((MV_ULONG) pQueueCtrl->descBuf.bufVirtPtr, CPU_D_CACHE_LINE_SIZE);
+
+	pQueueCtrl->lastDesc = (descrNum - 1);
+
+	mvNetaDescRingReset(pQueueCtrl);
+
+	/* Set Rx descriptors queue starting address */
+	MV_REG_WRITE(NETA_RXQ_BASE_ADDR_REG(pPortCtrl->portNo, queue),
+		     netaDescVirtToPhys(pQueueCtrl, (MV_U8 *)pQueueCtrl->pFirst));
+	MV_REG_WRITE(NETA_RXQ_SIZE_REG(pPortCtrl->portNo, queue), descrNum);
+
+	return pRxqCtrl;
+}
+
+/*******************************************************************************
+* mvNetaTxqInit - Allocate required memory and initialize TXQ descriptor ring.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		int     portNo		- Port number.
+*		int		txp			- Number of T-CONT instance.
+*		int		queue		- Number of Tx queue.
+*		int		descrNum	- Number of descriptors
+*
+* OUTPUT:
+*
+* RETURN: None
+*
+*******************************************************************************/
+MV_NETA_TXQ_CTRL *mvNetaTxqInit(int port, int txp, int queue, int descrNum)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortCtrl[port];
+	MV_NETA_TXQ_CTRL *pTxqCtrl;
+	MV_NETA_QUEUE_CTRL *pQueueCtrl;
+	int descSize;
+
+	pTxqCtrl = mvNetaTxqHndlGet(port, txp, queue);
+	pQueueCtrl = &pTxqCtrl->queueCtrl;
+
+	/* Allocate memory for TX descriptors */
+	descSize = ((descrNum * NETA_DESC_ALIGNED_SIZE) + CPU_D_CACHE_LINE_SIZE);
+	pQueueCtrl->descBuf.bufVirtPtr =
+	    mvNetaDescrMemoryAlloc(pPortCtrl, descSize, &pQueueCtrl->descBuf.bufPhysAddr, &pQueueCtrl->descBuf.memHandle);
+
+	pQueueCtrl->descBuf.bufSize = descSize;
+
+	if (pQueueCtrl->descBuf.bufVirtPtr == NULL) {
+		mvOsPrintf("EthPort #%d, txQ=%d: Can't allocate %d bytes for %d TX descr\n",
+			   pPortCtrl->portNo, queue, descSize, descrNum);
+		return NULL;
+	}
+
+	/* Make sure descriptor address is cache line size aligned  */
+	pQueueCtrl->pFirst = (char *)MV_ALIGN_UP((MV_ULONG) pQueueCtrl->descBuf.bufVirtPtr, CPU_D_CACHE_LINE_SIZE);
+
+	pQueueCtrl->lastDesc = (descrNum - 1);
+
+	mvNetaDescRingReset(pQueueCtrl);
+
+    /* Set maximum bandwidth for enabled TXQs */
+#ifdef MV_ETH_WRR_NEW
+    MV_REG_WRITE(NETA_TXQ_TOKEN_CNTR_REG(port, txp, queue), NETA_TXQ_TOKEN_CNTR_MAX);
+#else
+	MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(port, txp, queue), 0x03ffffff);
+	MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(port, txp, queue), 0x3fffffff);
+#endif /* MV_ETH_WRR_NEW */
+
+	/* Set Tx descriptors queue starting address */
+	MV_REG_WRITE(NETA_TXQ_BASE_ADDR_REG(port, txp, queue), netaDescVirtToPhys(pQueueCtrl, (MV_U8 *)pQueueCtrl->pFirst));
+
+	MV_REG_WRITE(NETA_TXQ_SIZE_REG(port, txp, queue), NETA_TXQ_DESC_NUM_MASK(descrNum));
+
+	return pTxqCtrl;
+}
+
+/*******************************************************************************
+* mvNetaRxqDelete - Delete RXQ and free memory allocated for descriptors ring.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		int     port		- Port number.
+*		int		queue		- Number of RX queue.
+*
+* OUTPUT:
+*
+* RETURN: None
+*
+*******************************************************************************/
+void mvNetaRxqDelete(int port, int queue)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl =  mvNetaPortCtrl[port];
+	MV_NETA_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->pRxQueue[queue].queueCtrl;
+
+	mvNetaDescrMemoryFree(pPortCtrl, &pQueueCtrl->descBuf);
+
+	memset(pQueueCtrl, 0, sizeof(*pQueueCtrl));
+
+	/* Clear Rx descriptors queue starting address and size */
+	MV_REG_WRITE(NETA_RXQ_BASE_ADDR_REG(port, queue), 0);
+	MV_REG_WRITE(NETA_RXQ_SIZE_REG(port, queue), 0);
+}
+
+/*******************************************************************************
+* mvNetaTxqDelete - Delete TXQ and free memory allocated for descriptors ring.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		int     port		- Port number.
+*		int		txp			- Number of T-CONT instance.
+*		int		queue		- Number of Tx queue.
+*
+* OUTPUT:
+*
+* RETURN: None
+*
+*******************************************************************************/
+void mvNetaTxqDelete(int port, int txp, int queue)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl =  mvNetaPortCtrl[port];
+	MV_NETA_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->pTxQueue[queue].queueCtrl;
+
+	mvNetaDescrMemoryFree(pPortCtrl, &pQueueCtrl->descBuf);
+
+	memset(pQueueCtrl, 0, sizeof(*pQueueCtrl));
+
+    /* Set minimum bandwidth for disabled TXQs */
+#ifdef MV_ETH_WRR_NEW
+	MV_REG_WRITE(NETA_TXQ_TOKEN_CNTR_REG(port, txp, queue), 0);
+#else
+	MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(port, txp, queue), 0);
+	MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(port, txp, queue), 0);
+#endif /* MV_ETH_WRR_NEW */
+
+	/* Set Tx descriptors queue starting address and size */
+	MV_REG_WRITE(NETA_TXQ_BASE_ADDR_REG(port, txp, queue), 0);
+	MV_REG_WRITE(NETA_TXQ_SIZE_REG(port, txp, queue), 0);
+}
+
+
+/*******************************************************************************
+* mvNetaDescrMemoryFree - Free memory allocated for RX and TX descriptors.
+*
+* DESCRIPTION:
+*       This function frees memory allocated for RX and TX descriptors.
+*
+* INPUT:
+*
+* RETURN: None
+*
+*******************************************************************************/
+static void mvNetaDescrMemoryFree(MV_NETA_PORT_CTRL *pPortCtrl, MV_BUF_INFO *pDescBuf)
+{
+	if ((pDescBuf == NULL) || (pDescBuf->bufVirtPtr == NULL))
+		return;
+
+#ifdef ETH_DESCR_UNCACHED
+	mvOsIoUncachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr,
+			   pDescBuf->bufVirtPtr, pDescBuf->memHandle);
+#else
+	mvOsIoCachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr,
+			 pDescBuf->bufVirtPtr, pDescBuf->memHandle);
+#endif /* ETH_DESCR_UNCACHED */
+}
+
+/*******************************************************************************
+* mvNetaDescrMemoryAlloc - Allocate memory for RX and TX descriptors.
+*
+* DESCRIPTION:
+*       This function allocates memory for RX and TX descriptors.
+*
+* INPUT:
+*
+* RETURN: None
+*
+*******************************************************************************/
+static MV_U8 *mvNetaDescrMemoryAlloc(MV_NETA_PORT_CTRL *pPortCtrl, int descSize,
+				   MV_ULONG *pPhysAddr, MV_U32 *memHandle)
+{
+	MV_U8 *pVirt;
+
+#ifdef ETH_DESCR_UNCACHED
+	pVirt = (MV_U8 *)mvOsIoUncachedMalloc(pPortCtrl->osHandle, descSize, pPhysAddr, memHandle);
+#else
+	pVirt = (MV_U8 *)mvOsIoCachedMalloc(pPortCtrl->osHandle, descSize, pPhysAddr, memHandle);
+#endif /* ETH_DESCR_UNCACHED */
+
+	if (pVirt)
+		memset(pVirt, 0, descSize);
+
+	return pVirt;
+}
+
+/***************** Configuration functions ************************/
+
+MV_STATUS mvNetaMhSet(int port, MV_NETA_MH_MODE mh)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(ETH_PORT_MARVELL_HEADER_REG(port));
+	/* Clear relevant fields */
+	regVal &= ~(ETH_DSA_EN_MASK | ETH_MH_EN_MASK);
+	switch (mh) {
+	case MV_NETA_MH_NONE:
+		break;
+
+	case MV_NETA_MH:
+		regVal |= ETH_MH_EN_MASK;
+		break;
+
+	case MV_NETA_DSA:
+		regVal |= ETH_DSA_MASK;
+		break;
+
+	case MV_NETA_DSA_EXT:
+		regVal |= ETH_DSA_EXT_MASK;
+
+	default:
+		mvOsPrintf("port=%d: Unexpected MH = %d value\n", port, mh);
+		return MV_BAD_PARAM;
+	}
+	MV_REG_WRITE(ETH_PORT_MARVELL_HEADER_REG(port), regVal);
+	return MV_OK;
+}
+
+/* Set one of NETA_TX_MAX_MH_REGS registers */
+MV_STATUS mvNetaTxMhRegSet(int port, int txp, int reg, MV_U16 mh)
+{
+	/* Check params */
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (reg >= NETA_TX_MAX_MH_REGS)
+		return MV_BAD_PARAM;
+
+	/* Write register */
+	MV_REG_WRITE(NETA_TX_MH_REG(port, txp, reg), (MV_U32)mh);
+		return MV_OK;
+}
+
+
+MV_STATUS mvNetaRxqBufSizeSet(int port, int rxq, int bufSize)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_RXQ_SIZE_REG(port, rxq));
+
+	regVal &= ~NETA_RXQ_BUF_SIZE_MASK;
+	regVal |= ((bufSize >> 3) << NETA_RXQ_BUF_SIZE_OFFS);
+
+	MV_REG_WRITE(NETA_RXQ_SIZE_REG(port, rxq), regVal);
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaRxqTimeCoalSet(int port, int rxq, MV_U32 uSec)
+{
+	MV_U32 regVal;
+
+	regVal = (mvNetaHalData.tClk / 1000000) * uSec;
+
+	MV_REG_WRITE(NETA_RXQ_INTR_TIME_COAL_REG(port, rxq), regVal);
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaRxqPktsCoalSet(int port, int rxq, MV_U32 pkts)
+{
+	MV_REG_WRITE(NETA_RXQ_THRESHOLD_REG(port, rxq),
+		     (NETA_RXQ_OCCUPIED_DESC_MASK(pkts) | NETA_RXQ_NON_OCCUPIED_DESC_MASK(0)));
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaTxDonePktsCoalSet(int port, int txp, int txq, MV_U32 pkts)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_TXQ_SIZE_REG(port, txp, txq));
+
+	regVal &= ~NETA_TXQ_SENT_DESC_TRESH_ALL_MASK;
+	regVal |= NETA_TXQ_SENT_DESC_TRESH_MASK(pkts);
+
+	MV_REG_WRITE(NETA_TXQ_SIZE_REG(port, txp, txq), regVal);
+
+	return MV_OK;
+}
+
+MV_U32 mvNetaRxqTimeCoalGet(int port, int rxq)
+{
+	MV_U32 regVal, uSec;
+
+	regVal = MV_REG_READ(NETA_RXQ_INTR_TIME_COAL_REG(port, rxq));
+
+	uSec = regVal / (mvNetaHalData.tClk / 1000000);
+
+	return uSec;
+}
+
+MV_U32 mvNetaRxqPktsCoalGet(int port, int rxq)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_RXQ_THRESHOLD_REG(port, rxq));
+
+	return ((regVal & NETA_RXQ_OCCUPIED_DESC_ALL_MASK) >> NETA_RXQ_OCCUPIED_DESC_OFFS);
+}
+
+MV_U32 mvNetaTxDonePktsCoalGet(int port, int txp, int txq)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_TXQ_SIZE_REG(port, txp, txq));
+
+	return ((regVal & NETA_TXQ_SENT_DESC_TRESH_ALL_MASK) >> NETA_TXQ_SENT_DESC_TRESH_OFFS);
+}
+
+/*******************************************************************************
+* mvNetaPortUp - Start the Ethernet port RX and TX activity.
+*
+* DESCRIPTION:
+*       This routine start Rx and Tx activity:
+*
+*       Note: Each Rx and Tx queue descriptor's list must be initialized prior
+*       to calling this function (use etherInitTxDescRing for Tx queues and
+*       etherInitRxDescRing for Rx queues).
+*
+* INPUT:
+*		int     portNo		- Port number.
+*
+* RETURN:   MV_STATUS
+*           MV_OK - Success, Others - Failure.
+*
+*******************************************************************************/
+MV_STATUS mvNetaPortUp(int port)
+{
+	int queue, txp;
+	MV_U32 qMap;
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(port);
+	MV_NETA_QUEUE_CTRL *pQueueCtrl;
+
+	/* Enable all initialized TXs. */
+	for (txp = 0; txp < pPortCtrl->txpNum; txp++) {
+		mvNetaMibCountersClear(port, txp);
+
+		qMap = 0;
+		for (queue = 0; queue < CONFIG_MV_ETH_TXQ; queue++) {
+			pQueueCtrl = &pPortCtrl->pTxQueue[txp * CONFIG_MV_ETH_TXQ + queue].queueCtrl;
+
+			if (pQueueCtrl->pFirst != NULL)
+				qMap |= (1 << queue);
+		}
+		MV_REG_WRITE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo, txp), qMap);
+	}
+	/* Enable all initialized RXQs. */
+	qMap = 0;
+	for (queue = 0; queue < CONFIG_MV_ETH_RXQ; queue++) {
+		pQueueCtrl = &pPortCtrl->pRxQueue[queue].queueCtrl;
+
+		if (pQueueCtrl->pFirst != NULL)
+			qMap |= (1 << queue);
+	}
+	MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(pPortCtrl->portNo), qMap);
+
+/*
+	mvOsPrintf("Start TX port activity: regData=0x%x (0x%x)\n",
+		pPortCtrl->txqMap, MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)));
+*/
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaPortDown - Stop the Ethernet port activity.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*		int     portNo		- Port number.
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure.
+*
+* NOTE : used for port link down.
+*******************************************************************************/
+MV_STATUS mvNetaPortDown(int port)
+{
+	int	          txp;
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(port);
+	MV_U32 		  regData, txFifoEmptyMask = 0, txInProgMask = 0;
+	int 		  mDelay;
+
+	/* Stop Rx port activity. Check port Rx activity. */
+	regData = (MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(port))) & ETH_RXQ_ENABLE_MASK;
+	if (regData != 0) {
+		/* Issue stop command for active channels only */
+		MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(port), (regData << ETH_RXQ_DISABLE_OFFSET));
+	}
+
+	if (!MV_PON_PORT(port)) {
+		/* Wait for all Rx activity to terminate. */
+		mDelay = 0;
+		do {
+			if (mDelay >= RX_DISABLE_TIMEOUT_MSEC) {
+				mvOsPrintf("ethPort_%d: TIMEOUT for RX stopped !!! rxQueueCmd - 0x08%x\n", port, regData);
+				break;
+			}
+			mvOsDelay(1);
+			mDelay++;
+
+			/* Check port RX Command register that all Rx queues are stopped */
+			regData = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(port));
+		} while (regData & 0xFF);
+	}
+
+	if (!MV_PON_PORT(port)) {
+		/* Stop Tx port activity. Check port Tx activity. */
+		for (txp = 0; txp < pPortCtrl->txpNum; txp++) {
+			/* Issue stop command for active channels only */
+			regData = (MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(port, txp))) & ETH_TXQ_ENABLE_MASK;
+			if (regData != 0)
+				MV_REG_WRITE(ETH_TX_QUEUE_COMMAND_REG(port, txp), (regData << ETH_TXQ_DISABLE_OFFSET));
+
+			/* Wait for all Tx activity to terminate. */
+			mDelay = 0;
+			do {
+				if (mDelay >= TX_DISABLE_TIMEOUT_MSEC) {
+					mvOsPrintf("port=%d, txp=%d: TIMEOUT for TX stopped !!! txQueueCmd - 0x%08x\n",
+						   port, txp, regData);
+					break;
+				}
+				mvOsDelay(1);
+				mDelay++;
+
+				/* Check port TX Command register that all Tx queues are stopped */
+				regData = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(port, txp));
+			} while (regData & 0xFF);
+#ifdef MV_ETH_GMAC_NEW
+			txFifoEmptyMask |= ETH_TX_FIFO_EMPTY_MASK(txp);
+			txInProgMask    |= ETH_TX_IN_PROGRESS_MASK(txp);
+#else
+			if (MV_PON_PORT(port)) {
+				txFifoEmptyMask |= PON_TX_FIFO_EMPTY_MASK(txp);
+				txInProgMask |= PON_TX_IN_PROGRESS_MASK(txp);
+			} else {
+				txFifoEmptyMask = ETH_TX_FIFO_EMPTY_MASK;
+				txInProgMask = ETH_TX_IN_PROGRESS_MASK;
+			}
+#endif /* MV_ETH_GMAC_NEW */
+		}
+
+		/* Double check to Verify that TX FIFO is Empty */
+		mDelay = 0;
+		while (MV_TRUE) {
+			do {
+				if (mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC) {
+					mvOsPrintf("\n port=%d, TX FIFO empty timeout. status=0x08%x, empty=0x%x, inProg=0x%x\n",
+						port, regData, txFifoEmptyMask, txInProgMask);
+					break;
+				}
+				mvOsDelay(1);
+				mDelay++;
+
+				regData = MV_REG_READ(ETH_PORT_STATUS_REG(port));
+			} while (((regData & txFifoEmptyMask) != txFifoEmptyMask) || ((regData & txInProgMask) != 0));
+
+			if (mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC)
+				break;
+
+			/* Double check */
+			regData = MV_REG_READ(ETH_PORT_STATUS_REG(port));
+			if (((regData & txFifoEmptyMask) == txFifoEmptyMask) && ((regData & txInProgMask) == 0)) {
+				break;
+			} else
+				mvOsPrintf("port=%d: TX FIFO Empty double check failed. %d msec, status=0x%x, empty=0x%x, inProg=0x%x\n",
+					 port, mDelay, regData, txFifoEmptyMask, txInProgMask);
+		}
+	}
+	/* Wait about 200 usec */
+	mvOsUDelay(200);
+
+	return MV_OK;
+}
+
+
+MV_STATUS mvNetaRxqOffsetSet(int port, int rxq, int offset)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_RXQ_CONFIG_REG(port, rxq));
+	regVal &= ~NETA_RXQ_PACKET_OFFSET_ALL_MASK;
+
+	/* Offset is in */
+	regVal |= NETA_RXQ_PACKET_OFFSET_MASK(offset >> 3);
+
+	MV_REG_WRITE(NETA_RXQ_CONFIG_REG(port, rxq), regVal);
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaBmPoolBufSizeSet(int port, int pool, int bufsize)
+{
+	MV_U32 regVal;
+
+	regVal = MV_ALIGN_UP(bufsize, NETA_POOL_BUF_SIZE_ALIGN);
+	MV_REG_WRITE(NETA_POOL_BUF_SIZE_REG(port, pool), regVal);
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaRxqBmEnable(int port, int rxq, int shortPool, int longPool)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_RXQ_CONFIG_REG(port, rxq));
+
+	regVal &= ~(NETA_RXQ_SHORT_POOL_ID_MASK | NETA_RXQ_LONG_POOL_ID_MASK);
+	regVal |= (shortPool << NETA_RXQ_SHORT_POOL_ID_OFFS);
+	regVal |= (longPool << NETA_RXQ_LONG_POOL_ID_OFFS);
+	regVal |= NETA_RXQ_HW_BUF_ALLOC_MASK;
+
+	MV_REG_WRITE(NETA_RXQ_CONFIG_REG(port, rxq), regVal);
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaRxqBmDisable(int port, int rxq)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_RXQ_CONFIG_REG(port, rxq));
+
+	regVal &= ~NETA_RXQ_HW_BUF_ALLOC_MASK;
+
+	MV_REG_WRITE(NETA_RXQ_CONFIG_REG(port, rxq), regVal);
+
+	return MV_OK;
+}
+
+/******************************************************************************/
+/*                        WRR / EJP configuration routines                    */
+/******************************************************************************/
+
+/* Set maximum burst rate (using IPG configuration) */
+MV_STATUS mvNetaTxpEjpBurstRateSet(int port, int txp, int txq, int rate)
+{
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	/* Only TXQs 2 and 3 are valid */
+	if ((txq != 2) && (txq != 3)) {
+		mvOsPrintf("%s: txq=%d is INVALID. Only TXQs 2 and 3 are supported\n", __func__, txq);
+		return MV_BAD_PARAM;
+	}
+
+	mvOsPrintf("Not supported\n");
+
+	return MV_OK;
+}
+
+/* Set maximum packet size for each one of EJP priorities (IsoLo, Async) */
+MV_STATUS mvNetaTxpEjpMaxPktSizeSet(int port, int txp, int type, int size)
+{
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	mvOsPrintf("Not supported\n");
+
+	/* TBD */
+	return MV_OK;
+}
+
+/* TBD - Set Transmit speed for EJP calculations */
+MV_STATUS mvNetaTxpEjpTxSpeedSet(int port, int txp, int type, int speed)
+{
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	/* TBD */
+	mvOsPrintf("Not supported\n");
+
+	return MV_OK;
+}
+
+#ifdef MV_ETH_WRR_NEW
+/* Calculate period and tokens accordingly with required rate and accuracy */
+MV_STATUS mvNetaRateCalc(int rate, unsigned int accuracy, unsigned int *pPeriod, unsigned int *pTokens)
+{
+	/* Calculate refill tokens and period - rate [Kbps] = tokens [bits] * 1000 / period [usec] */
+	/* Assume:  Tclock [MHz] / BasicRefillNoOfClocks = 1 */
+	unsigned int period, tokens, calc;
+
+	if (rate == 0) {
+		/* Disable traffic from the port: tokens = 0 */
+		if (pPeriod != NULL)
+			*pPeriod = 1000;
+
+		if (pTokens != NULL)
+			*pTokens = 0;
+
+		return MV_OK;
+	}
+
+	/* Find values of "period" and "tokens" match "rate" and "accuracy" when period is minimal */
+	for (period = 1; period <= 1000; period++) {
+		tokens = 1;
+		while (MV_TRUE)	{
+			calc = (tokens * 1000) / period;
+			if (((MV_ABS(calc - rate) * 100) / rate) <= accuracy) {
+				if (pPeriod != NULL)
+					*pPeriod = period;
+
+				if (pTokens != NULL)
+					*pTokens = tokens;
+
+				return MV_OK;
+			}
+			if (calc > rate)
+				break;
+
+			tokens++;
+		}
+	}
+	return MV_FAIL;
+}
+
+/* Enable / Disable EJP mode */
+MV_STATUS mvNetaTxpEjpSet(int port, int txp, int enable)
+{
+	MV_U32  regVal;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (enable)
+		regVal = NETA_TX_EJP_ENABLE_MASK;
+	else
+		regVal = 0;
+
+	MV_REG_WRITE(NETA_TX_CMD_1_REG(port, txp), 0);
+
+	return MV_OK;
+}
+
+
+
+/* Set TXQ to work in FIX priority mode */
+MV_STATUS mvNetaTxqFixPrioSet(int port, int txp, int txq)
+{
+	MV_U32 regVal;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(NETA_TX_FIXED_PRIO_CFG_REG(port, txp));
+	regVal |= (1 << txq);
+	MV_REG_WRITE(NETA_TX_FIXED_PRIO_CFG_REG(port, txp), regVal);
+
+	return MV_OK;
+}
+
+/* Set TXQ to work in WRR mode and set relative weight. */
+/*   Weight range [1..N] */
+MV_STATUS mvNetaTxqWrrPrioSet(int port, int txp, int txq, int weight)
+{
+	MV_U32 regVal, mtu;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return MV_BAD_PARAM;
+
+	/* Weight * 256 bytes * 8 bits must be larger then MTU [bits] */
+	mtu = MV_REG_READ(NETA_TXP_MTU_REG(port, txp));
+	/* MTU [bits] -> MTU [256 bytes] */
+	mtu = ((mtu / 8) / 256) + 1;
+/*
+	mvOsPrintf("%s: port=%d, txp=%d, txq=%d, weight=%d, mtu=%d\n",
+			__func__, port, txp, txq, weight, mtu);
+*/
+	if ((weight < mtu) || (weight > NETA_TXQ_WRR_WEIGHT_MAX)) {
+		mvOsPrintf("%s Error: weight=%d is out of range %d...%d\n",
+				__func__, weight, mtu, NETA_TXQ_WRR_WEIGHT_MAX);
+		return MV_FAIL;
+	}
+
+	regVal = MV_REG_READ(NETA_TXQ_WRR_ARBITER_REG(port, txp, txq));
+
+	regVal &= ~NETA_TXQ_WRR_WEIGHT_ALL_MASK;
+	regVal |= NETA_TXQ_WRR_WEIGHT_MASK(weight);
+	MV_REG_WRITE(NETA_TXQ_WRR_ARBITER_REG(port, txp, txq), regVal);
+
+	regVal = MV_REG_READ(NETA_TX_FIXED_PRIO_CFG_REG(port, txp));
+	regVal &= ~(1 << txq);
+	MV_REG_WRITE(NETA_TX_FIXED_PRIO_CFG_REG(port, txp), regVal);
+
+	return MV_OK;
+}
+
+/* Set minimum number of tockens to start transmit for TX port
+ *   maxTxSize [bytes]    - maximum packet size can be sent via this TX port
+ */
+MV_STATUS   mvNetaTxpMaxTxSizeSet(int port, int txp, int maxTxSize)
+{
+	MV_U32	regVal, size, mtu;
+	int		txq;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	mtu = maxTxSize * 8;
+	if (mtu > NETA_TXP_MTU_MAX)
+		mtu = NETA_TXP_MTU_MAX;
+
+	/* set MTU */
+	regVal = MV_REG_READ(NETA_TXP_MTU_REG(port, txp));
+	regVal &= ~NETA_TXP_MTU_ALL_MASK;
+	regVal |= NETA_TXP_MTU_MASK(mtu);
+
+	MV_REG_WRITE(NETA_TXP_MTU_REG(port, txp), regVal);
+
+	/* TXP token size and all TXQs token size must be larger that MTU */
+	regVal = MV_REG_READ(NETA_TXP_TOKEN_SIZE_REG(port, txp));
+	size = regVal & NETA_TXP_TOKEN_SIZE_MAX;
+	if (size < mtu) {
+		size = mtu;
+		regVal &= ~NETA_TXP_TOKEN_SIZE_MAX;
+		regVal |= size;
+		MV_REG_WRITE(NETA_TXP_TOKEN_SIZE_REG(port, txp), regVal);
+	}
+	for (txq = 0; txq < CONFIG_MV_ETH_TXQ; txq++) {
+		regVal = MV_REG_READ(NETA_TXQ_TOKEN_SIZE_REG(port, txp, txq));
+		size = regVal & NETA_TXQ_TOKEN_SIZE_MAX;
+		if (size < mtu) {
+			size = mtu;
+			regVal &= ~NETA_TXQ_TOKEN_SIZE_MAX;
+			regVal |= size;
+			MV_REG_WRITE(NETA_TXQ_TOKEN_SIZE_REG(port, txp, txq), regVal);
+		}
+	}
+	return MV_OK;
+}
+
+/* Set bandwidth limitation for TX port
+ *   rate [Kbps]    - steady state TX bandwidth limitation
+ */
+MV_STATUS   mvNetaTxpRateSet(int port, int txp, int rate)
+{
+	MV_U32		regVal;
+	unsigned int	tokens, period, accuracy = 0;
+	MV_STATUS	status;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(NETA_TX_REFILL_PERIOD_REG(port, txp));
+
+	status = mvNetaRateCalc(rate, accuracy, &period, &tokens);
+	if (status != MV_OK) {
+		mvOsPrintf("%s: Can't provide rate of %d [Kbps] with accuracy of %d [%%]\n",
+				__func__, rate, accuracy);
+		return status;
+	}
+	if (tokens > NETA_TXP_REFILL_TOKENS_MAX)
+		tokens = NETA_TXP_REFILL_TOKENS_MAX;
+
+	if (period > NETA_TXP_REFILL_PERIOD_MAX)
+		period = NETA_TXP_REFILL_PERIOD_MAX;
+
+	regVal = MV_REG_READ(NETA_TXP_REFILL_REG(port, txp));
+
+	regVal &= ~NETA_TXP_REFILL_TOKENS_ALL_MASK;
+	regVal |= NETA_TXP_REFILL_TOKENS_MASK(tokens);
+
+	regVal &= ~NETA_TXP_REFILL_PERIOD_ALL_MASK;
+	regVal |= NETA_TXP_REFILL_PERIOD_MASK(period);
+
+	MV_REG_WRITE(NETA_TXP_REFILL_REG(port, txp), regVal);
+
+	return MV_OK;
+}
+
+/* Set maximum burst size for TX port
+ *   burst [bytes] - number of bytes to be sent with maximum possible TX rate,
+ *                    before TX rate limitation will take place.
+ */
+MV_STATUS mvNetaTxpBurstSet(int port, int txp, int burst)
+{
+	MV_U32  size, mtu;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	/* Calulate Token Bucket Size */
+	size = 8 * burst;
+
+	if (size > NETA_TXP_TOKEN_SIZE_MAX)
+		size = NETA_TXP_TOKEN_SIZE_MAX;
+
+	/* Token bucket size must be larger then MTU */
+	mtu = MV_REG_READ(NETA_TXP_MTU_REG(port, txp));
+	if (mtu > size) {
+		mvOsPrintf("%s Error: Bucket size (%d bytes) < MTU (%d bytes)\n",
+					__func__, (size / 8), (mtu / 8));
+		return MV_BAD_PARAM;
+	}
+	MV_REG_WRITE(NETA_TXP_TOKEN_SIZE_REG(port, txp), size);
+
+	return MV_OK;
+}
+
+/* Set bandwidth limitation for TXQ
+ *   rate  [Kbps]  - steady state TX rate limitation
+ */
+MV_STATUS   mvNetaTxqRateSet(int port, int txp, int txq, int rate)
+{
+	MV_U32		regVal;
+	unsigned int	period, tokens, accuracy = 0;
+	MV_STATUS	status;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return MV_BAD_PARAM;
+
+	status = mvNetaRateCalc(rate, accuracy, &period, &tokens);
+	if (status != MV_OK) {
+		mvOsPrintf("%s: Can't provide rate of %d [Kbps] with accuracy of %d [%%]\n",
+				__func__, rate, accuracy);
+		return status;
+	}
+
+	if (tokens > NETA_TXQ_REFILL_TOKENS_MAX)
+		tokens = NETA_TXQ_REFILL_TOKENS_MAX;
+
+	if (period > NETA_TXQ_REFILL_PERIOD_MAX)
+		period = NETA_TXQ_REFILL_PERIOD_MAX;
+
+	regVal = MV_REG_READ(NETA_TXQ_REFILL_REG(port, txp, txq));
+
+	regVal &= ~NETA_TXQ_REFILL_TOKENS_ALL_MASK;
+	regVal |= NETA_TXQ_REFILL_TOKENS_MASK(tokens);
+
+	regVal &= ~NETA_TXQ_REFILL_PERIOD_ALL_MASK;
+	regVal |= NETA_TXQ_REFILL_PERIOD_MASK(period);
+
+	MV_REG_WRITE(NETA_TXQ_REFILL_REG(port, txp, txq), regVal);
+
+	return MV_OK;
+}
+
+/* Set maximum burst size for TX port
+ *   burst [bytes] - number of bytes to be sent with maximum possible TX rate,
+ *                    before TX bandwidth limitation will take place.
+ */
+MV_STATUS mvNetaTxqBurstSet(int port, int txp, int txq, int burst)
+{
+	MV_U32  size, mtu;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return MV_BAD_PARAM;
+
+	/* Calulate Tocket Bucket Size */
+	size = 8 * burst;
+
+	if (size > NETA_TXQ_TOKEN_SIZE_MAX)
+		size = NETA_TXQ_TOKEN_SIZE_MAX;
+
+	/* Tocken bucket size must be larger then MTU */
+	mtu = MV_REG_READ(NETA_TXP_MTU_REG(port, txp));
+	if (mtu > size) {
+		mvOsPrintf("%s Error: Bucket size (%d bytes) < MTU (%d bytes)\n",
+					__func__, (size / 8), (mtu / 8));
+		return MV_BAD_PARAM;
+	}
+
+	MV_REG_WRITE(NETA_TXQ_TOKEN_SIZE_REG(port, txp, txq), size);
+
+	return MV_OK;
+}
+
+#else /* Old WRR/EJP module */
+
+MV_STATUS mvNetaTxpEjpSet(int port, int txp, int enable)
+{
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	mvOsPrintf("Not supported\n");
+
+	return MV_OK;
+}
+
+
+/* Set TXQ to work in FIX priority mode */
+MV_STATUS mvNetaTxqFixPrioSet(int port, int txp, int txq)
+{
+	MV_U32 regVal;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(ETH_TX_FIXED_PRIO_CFG_REG(port, txp));
+	regVal |= (1 << txq);
+	MV_REG_WRITE(ETH_TX_FIXED_PRIO_CFG_REG(port, txp), regVal);
+
+	return MV_OK;
+}
+
+/* Set TXQ to work in WRR mode and set relative weight. */
+/*   Weight range [1..N] */
+MV_STATUS mvNetaTxqWrrPrioSet(int port, int txp, int txq, int weight)
+{
+	MV_U32 regVal;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(ETH_TXQ_ARBITER_CFG_REG(port, txp, txq));
+	if (weight > ETH_TXQ_WRR_WEIGHT_MAX)
+		weight = ETH_TXQ_WRR_WEIGHT_MAX;
+
+	regVal &= ~ETH_TXQ_WRR_WEIGHT_ALL_MASK;
+	regVal |= ETH_TXQ_WRR_WEIGHT_MASK(weight);
+	MV_REG_WRITE(ETH_TXQ_ARBITER_CFG_REG(port, txp, txq), regVal);
+
+	regVal = MV_REG_READ(ETH_TX_FIXED_PRIO_CFG_REG(port, txp));
+	regVal &= ~(1 << txq);
+	MV_REG_WRITE(ETH_TX_FIXED_PRIO_CFG_REG(port, txp), regVal);
+
+	return MV_OK;
+}
+
+MV_STATUS   mvNetaTxpMaxTxSizeSet(int port, int txp, int maxTxSize)
+{
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	/* TBD */
+	return MV_OK;
+}
+
+/* Set bandwidth limitation for TX port
+ *   bw [kbps]    - steady state TX bandwidth limitation
+ */
+MV_STATUS mvNetaTxpRateSet(int port, int txp, int bw)
+{
+	MV_U32 regVal, rate;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	/* TokenRate[1/64 bit/cycle] = BW[kb/sec]*64/TCLK[MHz]. */
+	rate = (((bw * 64) / 1000) / (mvNetaHalData.tClk / 1000000));
+	if (rate > ETH_TXP_TOKEN_RATE_MAX)
+		rate = ETH_TXP_TOKEN_RATE_MAX;
+
+	regVal = MV_REG_READ(ETH_TXP_TOKEN_RATE_CFG_REG(port, txp));
+	regVal &= ~ETH_TXP_TOKEN_RATE_ALL_MASK;
+	regVal |= ETH_TXP_TOKEN_RATE_MASK(rate);
+
+	MV_REG_WRITE(ETH_TXP_TOKEN_RATE_CFG_REG(port, txp), regVal);
+
+	return MV_OK;
+}
+
+/* Set maximum burst size for TX port
+ *   burst [bytes] - number of bytes to be sent with maximum possible TX rate,
+ *                    before TX rate limitation will take place.
+ */
+MV_STATUS mvNetaTxpBurstSet(int port, int txp, int burst)
+{
+	MV_U32 regVal, size;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	/* Token Bucket Size */
+	size = (burst / 256);
+	if (size > ETH_TXP_TOKEN_SIZE_MAX)
+		size = ETH_TXP_TOKEN_SIZE_MAX;
+
+	regVal = MV_REG_READ(ETH_TXP_TOKEN_SIZE_REG(port, txp));
+	regVal &= ~ETH_TXP_TOKEN_SIZE_ALL_MASK;
+	regVal |= ETH_TXP_TOKEN_SIZE_MASK(size);
+
+	MV_REG_WRITE(ETH_TXP_TOKEN_SIZE_REG(port, txp), regVal);
+
+	return MV_OK;
+}
+
+/* Set bandwidth limitation for TXQ
+ *   rate  [kbps]  - steady state TX rate limitation
+ */
+MV_STATUS mvNetaTxqRateSet(int port, int txp, int txq, int bw)
+{
+	MV_U32 regVal;
+	MV_U32 rate;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return MV_BAD_PARAM;
+
+	regVal = MV_REG_READ(ETH_TXQ_TOKEN_CFG_REG(port, txp, txq));
+
+	/* TokenRate[1/64 bit/cycle] = BW[Mb/sec]*64/TCLK[MHz]. */
+	rate = (((bw * 64) / 1000) / (mvNetaHalData.tClk / 1000000));
+	if (rate > ETH_TXQ_TOKEN_RATE_MAX)
+		rate = ETH_TXQ_TOKEN_RATE_MAX;
+
+	regVal &= ~ETH_TXQ_TOKEN_RATE_ALL_MASK;
+	regVal |= ETH_TXQ_TOKEN_RATE_MASK(rate);
+
+	MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(port, txp, txq), regVal);
+
+	return MV_OK;
+}
+
+/* Set maximum burst size for TX port
+ *   burst [bytes] - number of bytes to be sent with maximum possible TX rate,
+ *                    before TX bandwidth limitation will take place.
+ */
+MV_STATUS mvNetaTxqBurstSet(int port, int txp, int txq, int burst)
+{
+	MV_U32 regVal, size;
+
+	if (mvNetaTxpCheck(port, txp))
+		return MV_BAD_PARAM;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return MV_BAD_PARAM;
+
+	/* Token Bucket Size */
+	size = (burst / 256);
+	if (size > ETH_TXQ_TOKEN_SIZE_MAX)
+		size = ETH_TXQ_TOKEN_SIZE_MAX;
+
+	regVal = MV_REG_READ(ETH_TXQ_TOKEN_CFG_REG(port, txp, txq));
+
+	regVal &= ~ETH_TXQ_TOKEN_SIZE_ALL_MASK;
+	regVal |= ETH_TXQ_TOKEN_SIZE_MASK(size);
+
+	MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(port, txp, txq), regVal);
+
+	return MV_OK;
+}
+#endif /* MV_ETH_WRR_NEW */
+
+#ifdef CONFIG_MV_ETH_LEGACY_PARSER
+/******************************************************************************/
+/*                        RX Dispatching configuration routines               */
+/******************************************************************************/
+
+MV_STATUS mvNetaTcpRxq(int port, int rxq)
+{
+	MV_U32 portCfgReg;
+
+	if ((rxq < 0) || (rxq >= MV_ETH_MAX_RXQ)) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", rxq);
+		return MV_BAD_PARAM;
+	}
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(port));
+
+	portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(rxq);
+	portCfgReg |= ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK;
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(port), portCfgReg);
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaUdpRxq(int port, int rxq)
+{
+	MV_U32 portCfgReg;
+
+	if ((rxq < 0) || (rxq >= MV_ETH_MAX_RXQ)) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", rxq);
+		return MV_BAD_PARAM;
+	}
+
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(port));
+
+	portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(rxq);
+	portCfgReg |= ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK;
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(port), portCfgReg);
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaArpRxq(int port, int rxq)
+{
+	MV_U32 portCfgReg;
+
+	if ((rxq < 0) || (rxq >= MV_ETH_MAX_RXQ)) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", rxq);
+		return MV_BAD_PARAM;
+	}
+
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(port));
+
+	portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(rxq);
+	portCfgReg &= (~ETH_REJECT_ARP_BCAST_MASK);
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(port), portCfgReg);
+
+	return MV_OK;
+}
+
+MV_STATUS mvNetaBpduRxq(int port, int rxq)
+{
+	MV_U32 portCfgReg;
+	MV_U32 portCfgExtReg;
+
+	if ((rxq < 0) || (rxq >= MV_ETH_MAX_RXQ)) {
+		mvOsPrintf("ethDrv: RX queue #%d is out of range\n", rxq);
+		return MV_BAD_PARAM;
+	}
+
+	portCfgExtReg = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(port));
+	portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(port));
+
+	portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK;
+	portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(rxq);
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_REG(port), portCfgReg);
+
+	portCfgExtReg |= ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK;
+
+	MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(port), portCfgExtReg);
+
+	return MV_OK;
+}
+#endif /* CONFIG_MV_ETH_LEGACY_PARSER */
+
+
+/******************************************************************************/
+/*                      MIB Counters functions                                */
+/******************************************************************************/
+
+/*******************************************************************************
+* mvNetaMibCounterRead - Read a MIB counter
+*
+* DESCRIPTION:
+*       This function reads a MIB counter of a specific ethernet port.
+*       NOTE - Read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW or
+*              ETH_MIB_GOOD_OCTETS_SENT_LOW counters will return 64 bits value,
+*              so pHigh32 pointer should not be NULL in this case.
+*
+* INPUT:
+*       port        - Ethernet Port number.
+*       mib         - MIB number
+*       mibOffset   - MIB counter offset.
+*
+* OUTPUT:
+*       MV_U32*       pHigh32 - pointer to place where 32 most significant bits
+*                             of the counter will be stored.
+*
+* RETURN:
+*       32 low sgnificant bits of MIB counter value.
+*
+*******************************************************************************/
+MV_U32 mvNetaMibCounterRead(int port, int mib, unsigned int mibOffset, MV_U32 *pHigh32)
+{
+	MV_U32 valLow32, valHigh32;
+
+	valLow32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(port, mib) + mibOffset);
+
+	/* Implement FEr ETH. Erroneous Value when Reading the Upper 32-bits    */
+	/* of a 64-bit MIB Counter.                                             */
+	if ((mibOffset == ETH_MIB_GOOD_OCTETS_RECEIVED_LOW) || (mibOffset == ETH_MIB_GOOD_OCTETS_SENT_LOW)) {
+		valHigh32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(port, mib) + mibOffset + 4);
+		if (pHigh32 != NULL)
+			*pHigh32 = valHigh32;
+	}
+	return valLow32;
+}
+
+/*******************************************************************************
+* mvNetaMibCountersClear - Clear all MIB counters
+*
+* DESCRIPTION:
+*       This function clears all MIB counters
+*
+* INPUT:
+*       port      - Ethernet Port number.
+*       mib       - MIB number
+*
+*
+* RETURN:   void
+*
+*******************************************************************************/
+void mvNetaMibCountersClear(int port, int mib)
+{
+	int i;
+	MV_U32 dummy;
+
+#if defined(CONFIG_MV_PON) && !defined(MV_PON_MIB_SUPPORT)
+	if (MV_PON_PORT(port))
+		return;
+#endif /* CONFIG_MV_PON && !MV_PON_MIB_SUPPORT */
+
+	/* Perform dummy reads from MIB counters */
+	for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; i += 4)
+		dummy = MV_REG_READ((ETH_MIB_COUNTERS_BASE(port, mib) + i));
+}
+
+#if defined(CONFIG_MV_PON) && defined(MV_PON_MIB_SUPPORT)
+
+/* Set default MIB counters set for RX packets. mib==-1 means don't count */
+MV_STATUS   mvNetaPonRxMibDefault(int mib)
+{
+	MV_U32  regVal = 0;
+
+	regVal = MV_REG_READ(NETA_PON_MIB_RX_DEF_REG);
+	if (mib == -1) {
+		/* Don't count default packets that not match Gem portID */
+		regVal &= ~NETA_PON_MIB_RX_VALID_MASK;
+	} else {
+		if (mvNetaMaxCheck(mib, MV_ETH_MAX_TCONT()))
+			return MV_BAD_PARAM;
+
+		regVal &= ~NETA_PON_MIB_RX_MIB_NO_MASK;
+		regVal |= NETA_PON_MIB_RX_VALID_MASK | NETA_PON_MIB_RX_MIB_NO(mib);
+	}
+	MV_REG_WRITE(NETA_PON_MIB_RX_DEF_REG, regVal);
+
+	return MV_OK;
+}
+
+/* Set MIB counters set used for RX packets with special gemPid. mib==-1 means delete entry */
+MV_STATUS   mvNetaPonRxMibGemPid(int mib, MV_U16 gemPid)
+{
+	MV_U32	regVal;
+	int	i, free = -1;
+
+	if ((mib != -1) && mvNetaMaxCheck(mib, MV_ETH_MAX_TCONT()))
+		return MV_BAD_PARAM;
+
+	/* look for gemPid if exist of first free entry */
+	for (i = 0; i < NETA_PON_MIB_MAX_GEM_PID; i++) {
+		regVal = MV_REG_READ(NETA_PON_MIB_RX_CTRL_REG(i));
+		if ((regVal & NETA_PON_MIB_RX_VALID_MASK) &&
+		    ((regVal & NETA_PON_MIB_RX_GEM_PID_ALL_MASK) ==
+			NETA_PON_MIB_RX_GEM_PID_MASK(gemPid))) {
+			/* Entry for this gemPid exist */
+			if (mib == -1) {
+				/* Delete entry */
+				regVal &= ~NETA_PON_MIB_RX_VALID_MASK;
+			} else {
+				/* update mibNo */
+				regVal &= ~NETA_PON_MIB_RX_MIB_NO_MASK;
+				regVal |= NETA_PON_MIB_RX_MIB_NO(mib);
+			}
+			MV_REG_WRITE(NETA_PON_MIB_RX_CTRL_REG(i), regVal);
+
+			return MV_OK;
+		}
+		if ((free == -1) && ((regVal & NETA_PON_MIB_RX_VALID_MASK) == 0)) {
+			/* remember first invalid entry */
+			free = i;
+		}
+	}
+	if (mib == -1)	{
+		mvOsPrintf("%s: Can't delete entry for gemPid=0x%x - NOT found\n",
+					__func__, gemPid);
+		return MV_NOT_FOUND;
+	}
+	if (free == -1)	{
+		mvOsPrintf("%s: No free entry for gemPid=0x%x, rxMib=%d\n",
+					__func__, gemPid, mib);
+		return MV_FULL;
+	}
+	regVal = NETA_PON_MIB_RX_VALID_MASK | NETA_PON_MIB_RX_MIB_NO(mib) | NETA_PON_MIB_RX_GEM_PID_MASK(gemPid);
+	MV_REG_WRITE(NETA_PON_MIB_RX_CTRL_REG(free), regVal);
+
+    return MV_OK;
+}
+#endif /* CONFIG_MV_PON && MV_PON_MIB_SUPPORT */
+
+#ifdef CONFIG_MV_INCLUDE_TPM
+void mvNetaVlanEtySet(int port, int txp, int reg_num, MV_U32 regVal)
+{
+    MV_REG_WRITE(NETA_TX_PMT_ETHER_TYPE_REG(port, txp, reg_num), regVal);
+}
+
+MV_STATUS mvNetaPortIpgSet(int port, MV_U16 ipg)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_3_REG(port));
+	regVal &= ~NETA_GMAC_IPG_SIZE_ALL_MASK;
+	regVal |= NETA_GMAC_IPG_SIZE_MASK(ipg);
+
+	MV_REG_WRITE(NETA_GMAC_CTRL_3_REG(port), regVal);
+
+	return MV_OK;
+}
+
+MV_U16 mvNetaPortIpgGet(int port)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_GMAC_CTRL_3_REG(port));
+
+	return ((regVal & NETA_GMAC_IPG_SIZE_ALL_MASK) >> NETA_GMAC_IPG_SIZE_OFFS);
+}
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.h b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.h
new file mode 100755
index 0000000..ad3679c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNeta.h
@@ -0,0 +1,775 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __mvNeta_h__
+#define __mvNeta_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#include "mvTypes.h"
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysEthConfig.h"
+#include "mvNetaRegs.h"
+#include "mvEthRegs.h"
+
+#ifdef CONFIG_MV_ETH_PNC
+# include "pnc/mvPnc.h"
+#endif /* CONFIG_MV_ETH_PNC */
+
+#define NETA_RX_IP_IS_FRAG(status)     ((status) & NETA_RX_IP4_FRAG_MASK)
+#define NETA_RX_IP_SET_FRAG(rxd)       ((rxd)->status |= NETA_RX_IP4_FRAG_MASK)
+
+#define NETA_RX_L4_CSUM_IS_OK(status)  ((status) & NETA_RX_L4_CSUM_OK_MASK)
+#define	NETA_RX_L4_CSUM_SET_OK(rxd)    ((rxd)->status |= NETA_RX_L4_CSUM_OK_MASK)
+
+#define NETA_RX_IS_PPPOE(rxd)          ((rxd)->pncInfo & NETA_PNC_PPPOE)
+#define NETA_RX_SET_PPPOE(rxd)         ((rxd)->pncInfo |= NETA_PNC_PPPOE)
+
+#define NETA_RX_GET_IPHDR_OFFSET(rxd)       (((rxd)->status & NETA_RX_L3_OFFSET_MASK) >> NETA_RX_L3_OFFSET_OFFS)
+#define NETA_RX_SET_IPHDR_OFFSET(rxd, offs) ((rxd)->status |= ((offs) << NETA_RX_L3_OFFSET_OFFS) & NETA_RX_L3_OFFSET_MASK)
+
+#define NETA_RX_GET_IPHDR_HDRLEN(rxd)       (((rxd)->status & NETA_RX_IP_HLEN_MASK) >> NETA_RX_IP_HLEN_OFFS)
+#define NETA_RX_SET_IPHDR_HDRLEN(rxd, hlen) ((rxd)->status |= ((hlen) << NETA_RX_IP_HLEN_OFFS) & NETA_RX_IP_HLEN_MASK)
+
+#ifdef CONFIG_MV_ETH_PNC
+
+#define NETA_RX_IS_VLAN(rxd)           ((rxd)->pncInfo & NETA_PNC_VLAN)
+#define NETA_RX_SET_VLAN(rxd)          ((rxd)->pncInfo |= NETA_PNC_VLAN)
+
+#define NETA_RX_L3_IS_IP4(status)      (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP4)
+#define NETA_RX_L3_SET_IP4(rxd)        ((rxd)->status |= NETA_RX_L3_IP4)
+
+#define NETA_RX_L3_IS_IP4_ERR(status)  (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP4_ERR)
+#define NETA_RX_L3_SET_IP4_ERR(rxd)    ((rxd)->status |= NETA_RX_L3_IP4_ERR)
+
+#define NETA_RX_L3_IS_IP6(status)      (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP6)
+#define NETA_RX_L3_SET_IP6(rxd)        ((rxd)->status |= NETA_RX_L3_IP6)
+
+#define NETA_RX_L3_IS_UN(status)       (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_UN)
+#define NETA_RX_L3_SET_UN(rxd)         ((rxd)->status |= NETA_RX_L3_UN)
+
+#define NETA_RX_L4_IS_TCP(status)      (((status) & NETA_RX_L4_MASK) == NETA_RX_L4_TCP)
+#define NETA_RX_L4_SET_TCP(rxd)        ((rxd)->status |= NETA_RX_L4_TCP)
+
+#define NETA_RX_L4_IS_UDP(status)      (((status) & NETA_RX_L4_MASK) == NETA_RX_L4_UDP)
+#define NETA_RX_L4_SET_UDP(rxd)        ((rxd)->status |= NETA_RX_L4_UDP)
+
+#define NETA_RX_L4_IS_OTHER(status)    (((status) & NETA_RX_L4_MASK) == NETA_RX_L4_OTHER)
+#define NETA_RX_L4_SET_OTHER(rxd)      ((rxd)->status |= NETA_RX_L4_OTHER)
+
+#else /* LEGACY parser */
+
+#define NETA_RX_IS_VLAN(rxd)           ((rxd)->status & ETH_RX_VLAN_TAGGED_FRAME_MASK)
+#define NETA_RX_SET_VLAN(rxd)          ((rxd)->status |= ETH_RX_VLAN_TAGGED_FRAME_MASK)
+
+#ifdef MV_ETH_LEGACY_PARSER_IPV6
+
+#define NETA_RX_L3_IS_IP4(status)      (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP4)
+#define NETA_RX_L3_SET_IP4(rxd)        ((rxd)->status |= NETA_RX_L3_IP4)
+
+#define NETA_RX_L3_IS_IP4_ERR(status)  (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP4_ERR)
+#define NETA_RX_L3_SET_IP4_ERR(rxd)    ((rxd)->status |= NETA_RX_L3_IP4_ERR)
+
+#define NETA_RX_L3_IS_IP6(status)      (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_IP6)
+#define NETA_RX_L3_SET_IP6(rxd)        ((rxd)->status |= NETA_RX_L3_IP6)
+
+#define NETA_RX_L3_IS_UN(status)       (((status) & NETA_RX_L3_MASK) == NETA_RX_L3_UN)
+#define NETA_RX_L3_SET_UN(rxd)         ((rxd)->status |= NETA_RX_L3_UN)
+
+#else
+
+#define NETA_RX_L3_IS_IP4(status)      ((status) & ETH_RX_IP_HEADER_OK_MASK)
+#define NETA_RX_L3_SET_IP4(rxd)        ((rxd)->status |= (ETH_RX_IP_HEADER_OK_MASK | ETH_RX_IP_FRAME_TYPE_MASK))
+
+#define NETA_RX_L3_IS_IP4_ERR(status)  (((status) & ETH_RX_IP_FRAME_TYPE_MASK) &&	\
+					!((status) & ETH_RX_IP_HEADER_OK_MASK))
+
+#define NETA_RX_L3_SET_IP4_ERR(rxd)													\
+					((rxd)->status |= ETH_RX_IP_FRAME_TYPE_MASK);					\
+					((rxd)->status &= ~ETH_RX_IP_HEADER_OK_MASK);
+
+#define NETA_RX_L3_IS_IP6(status)      (MV_FALSE)
+#define NETA_RX_L3_SET_IP6(rxd)        NETA_RX_L3_SET_UN(rxd)
+
+#define NETA_RX_L3_IS_UN(status)       (((status) & ETH_RX_IP_FRAME_TYPE_MASK) == 0)
+#define NETA_RX_L3_SET_UN(rxd)         ((rxd)->status &= ~ETH_RX_IP_FRAME_TYPE_MASK)
+
+#endif /* MV_ETH_LEGACY_PARSER_IPV6 */
+
+#define NETA_RX_L4_IS_TCP(status)      (((status) & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_TCP_TYPE)
+#define NETA_RX_L4_SET_TCP(rxd)        ((rxd)->status |= ETH_RX_L4_TCP_TYPE)
+
+#define NETA_RX_L4_IS_UDP(status)      (((status) & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_UDP_TYPE)
+#define NETA_RX_L4_SET_UDP(rxd)        ((rxd)->status |= ETH_RX_L4_UDP_TYPE)
+
+#define NETA_RX_L4_IS_OTHER(status)    (((status) & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_OTHER_TYPE)
+#define NETA_RX_L4_SET_OTHER(rxd)      ((rxd)->status |= ETH_RX_L4_OTHER_TYPE)
+
+#endif	/* CONFIG_MV_ETH_PNC */
+
+/* Default port configuration value */
+#define PORT_CONFIG_VALUE(rxQ)			\
+	(					\
+	ETH_DEF_RX_QUEUE_MASK(rxQ) |		\
+	ETH_DEF_RX_ARP_QUEUE_MASK(rxQ) |	\
+	ETH_DEF_RX_TCP_QUEUE_MASK(rxQ) |	\
+	ETH_DEF_RX_UDP_QUEUE_MASK(rxQ) |	\
+	ETH_DEF_RX_BPDU_QUEUE_MASK(rxQ) |	\
+	ETH_TX_NO_SET_ERROR_SUMMARY_MASK |	\
+	ETH_RX_CHECKSUM_WITH_PSEUDO_HDR		\
+	)
+
+/* Default port extend configuration value */
+#define PORT_CONFIG_EXTEND_VALUE            0
+
+#ifdef MV_ETH_GMAC_NEW
+#define PORT_SERIAL_CONTROL_VALUE				0
+#else
+#define PORT_SERIAL_CONTROL_VALUE		\
+	(					\
+	ETH_DISABLE_FC_AUTO_NEG_MASK |		\
+	BIT9 |					\
+	ETH_DO_NOT_FORCE_LINK_FAIL_MASK |	\
+	ETH_SET_FULL_DUPLEX_MASK		\
+	)
+#endif /* MV_ETH_GMAC_NEW */
+
+typedef enum {
+	MV_ETH_SPEED_AN,
+	MV_ETH_SPEED_10,
+	MV_ETH_SPEED_100,
+	MV_ETH_SPEED_1000
+} MV_ETH_PORT_SPEED;
+
+typedef enum {
+	MV_ETH_DUPLEX_AN,
+	MV_ETH_DUPLEX_HALF,
+	MV_ETH_DUPLEX_FULL
+} MV_ETH_PORT_DUPLEX;
+
+typedef enum {
+	MV_ETH_FC_AN_NO,
+	MV_ETH_FC_AN_SYM,
+	MV_ETH_FC_AN_ASYM,
+	MV_ETH_FC_DISABLE,
+	MV_ETH_FC_ENABLE,
+	MV_ETH_FC_ACTIVE
+
+} MV_ETH_PORT_FC;
+
+
+typedef enum {
+	MV_ETH_PRIO_FIXED = 0,	/* Fixed priority mode */
+	MV_ETH_PRIO_WRR = 1	/* Weighted round robin priority mode */
+} MV_ETH_PRIO_MODE;
+
+/* Ethernet port specific infomation */
+typedef struct eth_link_status {
+	MV_BOOL				linkup;
+	MV_ETH_PORT_SPEED	speed;
+	MV_ETH_PORT_DUPLEX	duplex;
+	MV_ETH_PORT_FC		rxFc;
+	MV_ETH_PORT_FC		txFc;
+
+} MV_ETH_PORT_STATUS;
+
+typedef enum {
+	MV_NETA_MH_NONE = 0,
+	MV_NETA_MH = 1,
+	MV_NETA_DSA = 2,
+	MV_NETA_DSA_EXT = 3
+} MV_NETA_MH_MODE;
+
+typedef struct {
+	MV_U32 maxPort;
+	MV_U32 pClk;
+	MV_U32 tClk;
+	int	maxCPUs;
+	MV_BOOL	iocc;
+	MV_U16 ctrlModel;       /* Controller Model     */
+	MV_U8  ctrlRev;         /* Controller Revision  */
+
+#ifdef CONFIG_MV_ETH_BM
+	MV_ULONG bmPhysBase;
+	MV_U8 *bmVirtBase;
+#endif				/* CONFIG_MV_ETH_BM */
+
+#ifdef CONFIG_MV_ETH_PNC
+	MV_ULONG pncPhysBase;
+	MV_U8 *pncVirtBase;
+#endif				/* CONFIG_MV_ETH_PNC */
+	MV_U32 portMask;
+	MV_U32 cpuMask;
+} MV_NETA_HAL_DATA;
+
+typedef struct eth_pbuf {
+	void *osInfo;
+	MV_ULONG physAddr;
+	MV_U8 *pBuf;
+	MV_U16 bytes;
+	MV_U16 offset;
+	MV_U8  pool;
+	MV_U8  reserved;
+	MV_U16 vlanId;
+} MV_ETH_PKT;
+
+typedef struct {
+	char *pFirst;
+	int lastDesc;
+	int nextToProc;
+	int descSize;
+	MV_BUF_INFO descBuf;
+
+} MV_NETA_QUEUE_CTRL;
+
+#define MV_NETA_QUEUE_DESC_PTR(pQueueCtrl, descIdx)                 \
+    ((pQueueCtrl)->pFirst + ((descIdx) * NETA_DESC_ALIGNED_SIZE))
+
+#define MV_NETA_QUEUE_NEXT_DESC(pQueueCtrl, descIdx)  \
+    (((descIdx) < (pQueueCtrl)->lastDesc) ? ((descIdx) + 1) : 0)
+
+#define MV_NETA_QUEUE_PREV_DESC(pQueueCtrl, descIdx)  \
+    (((descIdx) > 0) ? ((descIdx) - 1) : (pQueueCtrl)->lastDesc)
+
+typedef struct {
+	MV_NETA_QUEUE_CTRL queueCtrl;
+
+} MV_NETA_RXQ_CTRL;
+
+typedef struct {
+	MV_NETA_QUEUE_CTRL queueCtrl;
+
+} MV_NETA_TXQ_CTRL;
+
+typedef struct {
+	int portNo;
+	MV_NETA_RXQ_CTRL *pRxQueue;
+	MV_NETA_TXQ_CTRL *pTxQueue;
+	int rxqNum;
+	int txpNum;
+	int txqNum;
+	MV_U8 mcastCount[256];
+	void *osHandle;
+} MV_NETA_PORT_CTRL;
+
+extern MV_NETA_PORT_CTRL **mvNetaPortCtrl;
+extern MV_NETA_HAL_DATA mvNetaHalData;
+
+#ifdef CONFIG_MV_PON
+#define MV_ETH_MAX_TCONT() 	CONFIG_MV_PON_TCONTS
+#endif /* CONFIG_MV_PON */
+
+/* Get Giga port handler */
+static INLINE MV_NETA_PORT_CTRL *mvNetaPortHndlGet(int port)
+{
+	return mvNetaPortCtrl[port];
+}
+
+/* Get RX queue handler */
+static INLINE MV_NETA_RXQ_CTRL *mvNetaRxqHndlGet(int port, int rxq)
+{
+	return &mvNetaPortCtrl[port]->pRxQueue[rxq];
+}
+
+/* Get TX queue handler */
+static INLINE MV_NETA_TXQ_CTRL *mvNetaTxqHndlGet(int port, int txp, int txq)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortCtrl[port];
+
+	return &pPortCtrl->pTxQueue[txp * pPortCtrl->txqNum + txq];
+}
+
+#if defined(MV_CPU_BE) && defined(CONFIG_MV_ETH_BE_WA)
+/* Swap RX descriptor to be BE */
+static INLINE void mvNetaRxqDescSwap(NETA_RX_DESC *pRxDesc)
+{
+	pRxDesc->status = MV_BYTE_SWAP_32BIT(pRxDesc->status);
+	pRxDesc->pncInfo = MV_BYTE_SWAP_16BIT(pRxDesc->pncInfo);
+	pRxDesc->dataSize =  MV_BYTE_SWAP_16BIT(pRxDesc->dataSize);
+	pRxDesc->bufPhysAddr = MV_BYTE_SWAP_32BIT(pRxDesc->bufPhysAddr);
+	pRxDesc->pncFlowId = MV_BYTE_SWAP_32BIT(pRxDesc->pncFlowId);
+	/* pRxDesc->bufCookie = MV_BYTE_SWAP_32BIT(pRxDesc->bufCookie); */
+	pRxDesc->prefetchCmd = MV_BYTE_SWAP_16BIT(pRxDesc->prefetchCmd);
+	pRxDesc->csumL4 = MV_BYTE_SWAP_16BIT(pRxDesc->csumL4);
+	pRxDesc->pncExtra = MV_BYTE_SWAP_32BIT(pRxDesc->pncExtra);
+	pRxDesc->hw_cmd = MV_BYTE_SWAP_32BIT(pRxDesc->hw_cmd);
+}
+
+/* Swap TX descriptor to be BE */
+static INLINE void mvNetaTxqDescSwap(NETA_TX_DESC *pTxDesc)
+{
+	pTxDesc->command = MV_BYTE_SWAP_32BIT(pTxDesc->command);
+    pTxDesc->csumL4 = MV_BYTE_SWAP_16BIT(pTxDesc->csumL4);
+    pTxDesc->dataSize = MV_BYTE_SWAP_16BIT(pTxDesc->dataSize);
+    pTxDesc->bufPhysAddr = MV_BYTE_SWAP_32BIT(pTxDesc->bufPhysAddr);
+    pTxDesc->hw_cmd = MV_BYTE_SWAP_32BIT(pTxDesc->hw_cmd);
+}
+#else
+static INLINE void mvNetaRxqDescSwap(NETA_RX_DESC *pRxDesc)
+{
+}
+static INLINE void mvNetaTxqDescSwap(NETA_TX_DESC *pTxDesc)
+{
+}
+#endif /* MV_CPU_BE &&  CONFIG_MV_ETH_BE_WA */
+
+/* Get number of RX descriptors occupied by received packets */
+static INLINE int mvNetaRxqBusyDescNumGet(int port, int rxq)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_RXQ_STATUS_REG(port, rxq));
+
+	return (regVal & NETA_RXQ_OCCUPIED_DESC_ALL_MASK) >> NETA_RXQ_OCCUPIED_DESC_OFFS;
+}
+
+/* Get number of free RX descriptors ready to received new packets */
+static INLINE int mvNetaRxqFreeDescNumGet(int port, int rxq)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_RXQ_STATUS_REG(port, rxq));
+
+	return (regVal & NETA_RXQ_NON_OCCUPIED_DESC_ALL_MASK) >> NETA_RXQ_NON_OCCUPIED_DESC_OFFS;
+}
+
+/* Update HW with number of RX descriptors processed by SW:
+ *    - decrement number of occupied descriptors
+ *    - increment number of Non-occupied descriptors
+ */
+static INLINE void mvNetaRxqDescNumUpdate(int port, int rxq, int rx_done, int rx_filled)
+{
+	MV_U32 regVal;
+
+	if ((rx_done <= 0xFF) && (rx_filled <= 0xFF)) {
+		regVal = (rx_done << NETA_RXQ_DEC_OCCUPIED_OFFS) | (rx_filled << NETA_RXQ_ADD_NON_OCCUPIED_OFFS);
+		MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal);
+		return;
+	}
+
+	/* Only 255 descriptors can be added at once */
+	while ((rx_done > 0) || (rx_filled > 0)) {
+		if (rx_done <= 0xFF) {
+			regVal = (rx_done << NETA_RXQ_DEC_OCCUPIED_OFFS);
+			rx_done = 0;
+		} else {
+			regVal = (0xFF << NETA_RXQ_DEC_OCCUPIED_OFFS);
+			rx_done -= 0xFF;
+		}
+		if (rx_filled <= 0xFF) {
+			regVal |= (rx_filled << NETA_RXQ_ADD_NON_OCCUPIED_OFFS);
+			rx_filled = 0;
+		} else {
+			regVal |= (0xFF << NETA_RXQ_ADD_NON_OCCUPIED_OFFS);
+			rx_filled -= 0xFF;
+		}
+		MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal);
+	}
+}
+
+/* Add number of descriptors are ready to receive new packets */
+static INLINE void mvNetaRxqNonOccupDescAdd(int port, int rxq, int rx_desc)
+{
+	MV_U32	regVal;
+
+	/* Only 255 descriptors can be added at once */
+	while (rx_desc > 0xFF) {
+		regVal = (0xFF << NETA_RXQ_ADD_NON_OCCUPIED_OFFS);
+		MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal);
+		rx_desc = rx_desc - 0xFF;
+	}
+	regVal = (rx_desc << NETA_RXQ_ADD_NON_OCCUPIED_OFFS);
+	MV_REG_WRITE(NETA_RXQ_STATUS_UPDATE_REG(port, rxq), regVal);
+}
+
+
+/* Decrement sent descriptors counter */
+static INLINE void mvNetaTxqSentDescDec(int port, int txp, int txq, int sent_desc)
+{
+	MV_U32 regVal;
+
+	/* Only 255 TX descriptors can be updated at once */
+	while (sent_desc > 0xFF) {
+		regVal = (0xFF << NETA_TXQ_DEC_SENT_OFFS);
+		MV_REG_WRITE(NETA_TXQ_UPDATE_REG(port, txp, txq), regVal);
+		sent_desc = sent_desc - 0xFF;
+	}
+	regVal = (sent_desc << NETA_TXQ_DEC_SENT_OFFS);
+	MV_REG_WRITE(NETA_TXQ_UPDATE_REG(port, txp, txq), regVal);
+}
+
+/* Get number of TX descriptors already sent by HW */
+static INLINE int mvNetaTxqSentDescNumGet(int port, int txp, int txq)
+{
+	MV_U32  regVal;
+	int     sent_desc;
+
+	regVal = MV_REG_READ(NETA_TXQ_STATUS_REG(port, txp, txq));
+	sent_desc = (regVal & NETA_TXQ_SENT_DESC_MASK) >> NETA_TXQ_SENT_DESC_OFFS;
+
+	return sent_desc;
+}
+
+/* Get number of TX descriptors didn't send by HW yet and waiting for TX */
+static INLINE int mvNetaTxqPendDescNumGet(int port, int txp, int txq)
+{
+	MV_U32 regVal;
+
+	regVal = MV_REG_READ(NETA_TXQ_STATUS_REG(port, txp, txq));
+
+	return (regVal & NETA_TXQ_PENDING_DESC_MASK) >> NETA_TXQ_PENDING_DESC_OFFS;
+}
+
+/* Update HW with number of TX descriptors to be sent */
+static INLINE void mvNetaTxqPendDescAdd(int port, int txp, int txq, int pend_desc)
+{
+	MV_U32 regVal;
+
+	/* Only 255 descriptors can be added at once - we don't check it for performance */
+	/* Assume caller process TX desriptors in quanta less than 256 */
+	regVal = (pend_desc << NETA_TXQ_ADD_PENDING_OFFS);
+	MV_REG_WRITE(NETA_TXQ_UPDATE_REG(port, txp, txq), regVal);
+}
+
+/* Get number of sent descriptors and descrement counter. Number of sent descriptors is returned. */
+static INLINE int mvNetaTxqSentDescProc(int port, int txp, int txq)
+{
+	int sent_desc;
+
+	/* Get number of sent descriptors */
+	sent_desc = mvNetaTxqSentDescNumGet(port, txp, txq);
+	/* Decrement sent descriptors counter */
+	if (sent_desc)
+		mvNetaTxqSentDescDec(port, txp, txq, sent_desc);
+
+	return sent_desc;
+}
+
+/* Get pointer to next RX descriptor to be processed by SW */
+static INLINE NETA_RX_DESC *mvNetaRxqNextDescGet(MV_NETA_RXQ_CTRL *pRxq)
+{
+	NETA_RX_DESC	*pRxDesc;
+	int				rxDesc = pRxq->queueCtrl.nextToProc;
+
+	pRxq->queueCtrl.nextToProc = MV_NETA_QUEUE_NEXT_DESC(&(pRxq->queueCtrl), rxDesc);
+
+	pRxDesc = ((NETA_RX_DESC *)pRxq->queueCtrl.pFirst) + rxDesc;
+
+	return pRxDesc;
+}
+
+static INLINE NETA_RX_DESC *mvNetaRxqDescGet(MV_NETA_RXQ_CTRL *pRxq)
+{
+	NETA_RX_DESC	*pRxDesc;
+
+	pRxDesc = ((NETA_RX_DESC *)pRxq->queueCtrl.pFirst) + pRxq->queueCtrl.nextToProc;
+
+	return pRxDesc;
+}
+
+/* Refill RX descriptor (when BM is not supported) */
+static INLINE void mvNetaRxDescFill(NETA_RX_DESC *pRxDesc, MV_U32 physAddr, MV_U32 cookie)
+{
+	pRxDesc->bufCookie = (MV_U32)cookie;
+
+#if defined(CONFIG_MV_ETH_BE_WA)
+	pRxDesc->bufPhysAddr = MV_32BIT_LE(physAddr);
+#else
+	pRxDesc->bufPhysAddr = physAddr;
+#endif /* CONFIG_MV_ETH_BE_WA */
+
+	mvOsCacheLineFlush(NULL, pRxDesc);
+}
+
+/* Get pointer to next TX descriptor to be processed (send) by HW */
+static INLINE NETA_TX_DESC *mvNetaTxqNextDescGet(MV_NETA_TXQ_CTRL *pTxq)
+{
+	int txDesc = pTxq->queueCtrl.nextToProc;
+
+	pTxq->queueCtrl.nextToProc = MV_NETA_QUEUE_NEXT_DESC(&(pTxq->queueCtrl), txDesc);
+
+	return ((NETA_TX_DESC *) pTxq->queueCtrl.pFirst) + txDesc;
+}
+
+/* Get pointer to previous TX descriptor in the ring for rollback when needed */
+static INLINE NETA_TX_DESC *mvNetaTxqPrevDescGet(MV_NETA_TXQ_CTRL *pTxq)
+{
+	int txDesc = pTxq->queueCtrl.nextToProc;
+
+	pTxq->queueCtrl.nextToProc = MV_NETA_QUEUE_PREV_DESC(&(pTxq->queueCtrl), txDesc);
+
+	return ((NETA_TX_DESC *) pTxq->queueCtrl.pFirst) + txDesc;
+}
+
+/* Set TXQ descriptors fields relevant for CSUM calculation */
+static INLINE MV_U32 mvNetaTxqDescCsum(int l3_offs, int l3_proto, int ip_hdr_len, int l4_proto)
+{
+	MV_U32 command;
+
+	/* fields: L3_offset, IP_hdrlen, L3_type, G_IPv4_chk, G_L4_chk, L4_type */
+	/* required only for checksum calculation */
+	command = (l3_offs << NETA_TX_L3_OFFSET_OFFS);
+	command |= (ip_hdr_len << NETA_TX_IP_HLEN_OFFS);
+
+	if (l3_proto == MV_16BIT_BE(MV_IP_TYPE))
+		command |= (NETA_TX_L3_IP4 | NETA_TX_IP_CSUM_MASK);
+	else
+		command |= NETA_TX_L3_IP6;
+
+	if (l4_proto == MV_IP_PROTO_TCP)
+		command |= (NETA_TX_L4_TCP | NETA_TX_L4_CSUM_FULL);
+	else if (l4_proto == MV_IP_PROTO_UDP)
+		command |= (NETA_TX_L4_UDP | NETA_TX_L4_CSUM_FULL);
+	else
+		command |= NETA_TX_L4_CSUM_NOT;
+
+	return command;
+}
+
+static INLINE MV_ULONG netaDescVirtToPhys(MV_NETA_QUEUE_CTRL *pQueueCtrl, MV_U8 *pDesc)
+{
+	return (pQueueCtrl->descBuf.bufPhysAddr + (pDesc - pQueueCtrl->descBuf.bufVirtPtr));
+}
+
+
+#ifdef CONFIG_MV_PON
+static INLINE void mvNetaPonTxqBytesAdd(int port, int txp, int txq, int bytes)
+{
+	MV_U32	regVal;
+
+	regVal = (NETA_TX_NEW_BYTES_MASK(bytes) | NETA_TX_NEW_BYTES_TXQ_MASK(txq) | NETA_TX_NEW_BYTES_COLOR_GREEN);
+
+	MV_REG_WRITE(NETA_TX_ADD_BYTES_REG(port, txp), regVal);
+}
+#endif /* CONFIG_MV_PON */
+
+/* Function prototypes */
+MV_STATUS 	mvNetaHalInit(MV_NETA_HAL_DATA *halData);
+
+MV_STATUS 	mvNetaWinInit(MV_U32 port, MV_UNIT_WIN_INFO *addrWinMap);
+MV_STATUS 	mvNetaWinWrite(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+MV_STATUS 	mvNetaWinRead(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+MV_STATUS 	mvNetaWinEnable(MV_U32 port, MV_U32 winNum, MV_BOOL enable);
+
+int 		mvNetaAccMode(void);
+MV_STATUS 	mvNetaMemMapGet(MV_ULONG physAddr, MV_U8 *pTarget, MV_U8 *pAttr);
+
+void		*mvNetaPortInit(int port, void *osHandle);
+void		mvNetaPortDestroy(int portNo);
+MV_NETA_TXQ_CTRL 	*mvNetaTxqInit(int port, int txp, int queue, int descrNum);
+MV_NETA_RXQ_CTRL 	*mvNetaRxqInit(int port, int queue, int descrNum);
+void		mvNetaTxqDelete(int port, int txp, int queue);
+void		mvNetaRxqDelete(int port, int queue);
+
+void mvNetaRxReset(int port);
+void mvNetaTxpReset(int port, int txp);
+
+MV_STATUS	mvNetaPortDisable(int port);
+MV_STATUS	mvNetaPortEnable(int port);
+MV_STATUS	mvNetaPortUp(int port);
+MV_STATUS	mvNetaPortDown(int port);
+
+MV_BOOL		mvNetaLinkIsUp(int port);
+MV_STATUS	mvNetaLinkStatus(int port, MV_ETH_PORT_STATUS *pStatus);
+MV_STATUS	mvNetaDefaultsSet(int port);
+MV_STATUS	mvNetaForceLinkModeSet(int portNo, MV_BOOL force_link_pass, MV_BOOL force_link_fail);
+MV_STATUS	mvNetaSpeedDuplexSet(int portNo, MV_ETH_PORT_SPEED speed, MV_ETH_PORT_DUPLEX duplex);
+MV_STATUS 	mvNetaSpeedDuplexGet(int portNo, MV_ETH_PORT_SPEED *speed, MV_ETH_PORT_DUPLEX *duplex);
+
+MV_STATUS	mvNetaRxqCpuMaskSet(int port, int rxq, int cpu_mask);
+void		mvNetaRxqCpuDump(int port, int cpu);
+
+void		mvNetaSetOtherMcastTable(int portNo, int queue);
+void		mvNetaSetUcastTable(int port, int queue);
+void		mvNetaSetSpecialMcastTable(int portNo, int queue);
+
+#ifdef CONFIG_MV_ETH_LEGACY_PARSER
+MV_STATUS	mvNetaRxUnicastPromiscSet(int port, MV_BOOL isPromisc);
+
+MV_STATUS	mvNetaMcastAddrSet(int port, MV_U8 *pAddr, int queue);
+MV_STATUS	mvNetaMacAddrGet(int portNo, unsigned char *pAddr);
+
+MV_STATUS	mvNetaTosToRxqSet(int port, int rxq, int tos);
+int			mvNetaTosToRxqGet(int port, int tos);
+
+MV_STATUS   mvNetaVprioToRxqSet(int port, int vprio, int rxq);
+int	    	mvNetaVprioToRxqGet(int port, int vprio);
+
+MV_STATUS	mvNetaTcpRxq(int port, int rxq);
+MV_STATUS	mvNetaUdpRxq(int port, int rxq);
+MV_STATUS	mvNetaArpRxq(int port, int rxq);
+MV_STATUS	mvNetaBpduRxq(int port, int rxq);
+#endif /* CONFIG_MV_ETH_LEGACY_PARSER */
+
+void 		mvNetaPhyAddrSet(int port, int phyAddr);
+int 		mvNetaPhyAddrGet(int port);
+
+void 		mvNetaPortPowerDown(int port);
+void 		mvNetaPortPowerUp(int port, MV_BOOL isSgmii, MV_BOOL isRgmii);
+
+/* Interrupt Coalesting functions */
+MV_STATUS mvNetaRxqTimeCoalSet(int port, int rxq, MV_U32 uSec);
+MV_STATUS mvNetaRxqPktsCoalSet(int port, int rxq, MV_U32 pkts);
+MV_STATUS mvNetaTxDonePktsCoalSet(int port, int txp, int txq, MV_U32 pkts);
+MV_U32 mvNetaRxqTimeCoalGet(int port, int rxq);
+MV_U32 mvNetaRxqPktsCoalGet(int port, int rxq);
+MV_U32 mvNetaTxDonePktsCoalGet(int port, int txp, int txq);
+
+MV_STATUS mvNetaRxqBufSizeSet(int port, int rxq, int bufSize);
+MV_STATUS mvNetaMhSet(int port, MV_NETA_MH_MODE mh);
+MV_STATUS mvNetaTxMhRegSet(int port, int txp, int reg, MV_U16 mh);
+MV_STATUS mvNetaMaxRxSizeSet(int port, int maxRxSize);
+MV_STATUS mvNetaMacAddrSet(int port, unsigned char *pAddr, int queue);
+
+MV_STATUS mvNetaRxqOffsetSet(int port, int rxq, int offset);
+MV_STATUS mvNetaBmPoolBufSizeSet(int port, int pool, int bufsize);
+MV_STATUS mvNetaRxqBmEnable(int port, int rxq, int smallPool, int largePool);
+MV_STATUS mvNetaRxqBmDisable(int port, int rxq);
+
+MV_STATUS mvNetaTxpEjpSet(int port, int txp, int enable);
+MV_STATUS mvNetaTxqFixPrioSet(int port, int txp, int txq);
+MV_STATUS mvNetaTxqWrrPrioSet(int port, int txp, int txq, int weight);
+MV_STATUS mvNetaTxpMaxTxSizeSet(int port, int txp, int maxTxSize);
+MV_STATUS mvNetaTxpRateSet(int port, int txp, int bw);
+MV_STATUS mvNetaTxqRateSet(int port, int txp, int txq, int bw);
+MV_STATUS mvNetaTxpBurstSet(int port, int txp, int burst);
+MV_STATUS mvNetaTxqBurstSet(int port, int txp, int txq, int burst);
+MV_STATUS mvNetaTxpEjpBurstRateSet(int port, int txp, int txq, int rate);
+MV_STATUS mvNetaTxpEjpMaxPktSizeSet(int port, int txp, int type, int size);
+MV_STATUS mvNetaTxpEjpTxSpeedSet(int port, int txp, int type, int speed);
+
+int mvNetaPortCheck(int port);
+int mvNetaTxpCheck(int port, int txp);
+int mvNetaMaxCheck(int num, int limit);
+
+void mvNetaMibCountersClear(int port, int txp);
+MV_U32 mvNetaMibCounterRead(int port, int txp, unsigned int mibOffset, MV_U32 *pHigh32);
+
+void mvEthPortRegs(int port);
+void mvEthPortUcastShow(int port);
+void mvEthPortMcastShow(int port);
+void mvNetaPortRegs(int port);
+void mvNetaPncRegs(void);
+void mvNetaTxpRegs(int port, int txp);
+void mvNetaRxqRegs(int port, int rxq);
+void mvNetaTxqRegs(int port, int txp, int txq);
+void mvNetaPortStatus(int port);
+void mvNetaRxqShow(int port, int rxq, int mode);
+void mvNetaTxqShow(int port, int txp, int txq, int mode);
+
+void mvEthTxpWrrRegs(int port, int txp);
+void mvEthRegs(int port);
+void mvEthPortCounters(int port, int mib);
+void mvEthPortRmonCounters(int port, int mib);
+
+MV_STATUS mvNetaFlowCtrlSet(int port, MV_ETH_PORT_FC flowControl);
+MV_STATUS mvNetaFlowCtrlGet(int port, MV_ETH_PORT_FC *flowControl);
+
+#ifdef MV_ETH_GMAC_NEW
+MV_STATUS   mvEthGmacRgmiiSet(int port, int enable);
+MV_STATUS	mvNetaGmacLpiSet(int port, int mode);
+void	    mvNetaGmacRegs(int port);
+#endif /* MV_ETH_GMAC_NEW */
+
+#ifdef CONFIG_MV_PON
+void        mvNetaPonTxpRegs(int port, int txp);
+MV_STATUS   mvNetaPonRxMibDefault(int mib);
+MV_STATUS   mvNetaPonRxMibGemPid(int mib, MV_U16 gemPid);
+#endif /* CONFIG_MV_PON */
+
+#ifdef CONFIG_MV_ETH_HWF
+typedef enum {
+    MV_NETA_HWF_MH_REG = 0,
+    MV_NETA_HWF_MH_PNC = 1
+} MV_NETA_HWF_MH_SRC;
+
+MV_STATUS mvNetaHwfInit(int port);
+MV_STATUS mvNetaHwfEnable(int port, int enable);
+MV_STATUS mvNetaHwfBmPoolsSet(int port, int short_pool, int long_pool);
+MV_STATUS mvNetaHwfTxqInit(int p, int txp, int txq);
+MV_STATUS mvNetaHwfTxqEnable(int port, int p, int txp, int txq, int enable);
+MV_STATUS mvNetaHwfTxqDropSet(int port, int p, int txp, int txq, int thresh, int bits);
+MV_STATUS mvNetaHwfMhSrcSet(int port, MV_NETA_HWF_MH_SRC src);
+MV_STATUS mvNetaHwfMhSelSet(int port, MV_U8 mhSel);
+
+void mvNetaHwfRxpRegs(int port);
+void mvNetaHwfTxpRegs(int port, int p, int txp);
+void mvNetaHwfTxpCntrs(int port, int p, int txp);
+#endif /* CONFIG_MV_ETH_HWF */
+
+#ifdef CONFIG_MV_INCLUDE_TPM
+void mvNetaVlanEtySet(int port, int txp, int reg_num, MV_U32 regVal);
+MV_STATUS mvNetaPortIpgSet(int port, MV_U16 ipg);
+MV_U16 mvNetaPortIpgGet(int port);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __mvNeta_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaAddrDec.c b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaAddrDec.c
new file mode 100755
index 0000000..ebd8fe1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaAddrDec.c
@@ -0,0 +1,424 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvSysEthConfig.h"
+
+#include "mvNeta.h"
+
+MV_TARGET ethAddrDecPrioTab[] = {
+#if defined(MV_INCLUDE_SDRAM_CS0)
+	SDRAM_CS0,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS1)
+	SDRAM_CS1,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS2)
+	SDRAM_CS2,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS3)
+	SDRAM_CS3,
+#endif
+#if defined(CONFIG_MV_ETH_BM)
+	PNC_BM,
+#endif
+	TBL_TERM
+};
+
+static MV_STATUS ethWinOverlapDetect(MV_U32 port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
+
+/*******************************************************************************
+* mvNetaWinInit
+*
+* DESCRIPTION:
+*	This function initialize ETH window decode unit. It set the default
+*	address decode windows of the unit.
+*
+* INPUT:
+*	port	 : The port number to initialize the address decoding for.
+*	addWinMap: An array holding the address decoding information for the
+*		    system.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if setting fail.
+*******************************************************************************/
+MV_STATUS mvNetaWinInit(MV_U32 port, MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 winNum, winPrioIndex = 0, i, regVal = 0;
+	MV_UNIT_WIN_INFO *addrDecWin;
+	MV_U32 accessProtReg = 0;
+
+	/* Initiate Ethernet address decode */
+	/* First disable all address decode windows */
+	for (winNum = 0; winNum < ETH_MAX_DECODE_WIN; winNum++)
+		regVal |= MV_BIT_MASK(winNum);
+
+	MV_REG_WRITE(ETH_BASE_ADDR_ENABLE_REG(port), regVal);
+
+	/* Go through all windows in user table until table terminator      */
+	for (winNum = 0; ((ethAddrDecPrioTab[winPrioIndex] != TBL_TERM) && (winNum < ETH_MAX_DECODE_WIN));) {
+		addrDecWin = &addrWinMap[ethAddrDecPrioTab[winPrioIndex]];
+
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvNetaWinWrite(port, winNum, addrDecWin)) {
+				mvOsPrintf("mvNetaWinInit failed: winNum=%d (%d, %d)\n",
+					   winNum, winPrioIndex, ethAddrDecPrioTab[winPrioIndex]);
+				return MV_ERROR;
+			}
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+
+	/* set full access to all windows. */
+	for (i = 0; i < winNum; i++)
+		accessProtReg |= (FULL_ACCESS << (i * 2));
+
+	MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(port), accessProtReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaWinWrite
+*
+* DESCRIPTION:
+*	This function writes the address decoding registers according to the
+*	given window configuration.
+*
+* INPUT:
+*	unit	    - The Ethernet unit number to configure.
+*       winNum	    - ETH target address decode window number.
+*       pAddrDecWin - ETH target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success,
+*	MV_BAD_PARAM if winNum is invalid.
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvNetaWinWrite(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 size, alignment;
+	MV_U32 baseReg, sizeReg;
+
+	/* Parameter checking   */
+	if (winNum >= ETH_MAX_DECODE_WIN) {
+		mvOsPrintf("mvNetaWinSet: ERR. Invalid win num %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlapps with current windows     */
+	if (MV_TRUE == ethWinOverlapDetect(port, winNum, &pAddrDecWin->addrWin)) {
+		mvOsPrintf("mvNetaWinWrite: ERR. Window %d overlap\n", winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) {
+		mvOsPrintf("mvNetaWinSet: Error setting Ethernet window %d.\n"
+			   "Address 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	size = pAddrDecWin->addrWin.size;
+	if (!MV_IS_POWER_OF_2(size)) {
+		mvOsPrintf("mvNetaWinWrite: Error setting AUDIO window %d. "
+			   "Window size is not a power to 2.", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	baseReg = (pAddrDecWin->addrWin.baseLow & ETH_WIN_BASE_MASK);
+	sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum));
+
+	/* set size */
+	alignment = 1 << ETH_WIN_SIZE_OFFS;
+	sizeReg &= ~ETH_WIN_SIZE_MASK;
+	sizeReg |= (((size / alignment) - 1) << ETH_WIN_SIZE_OFFS);
+
+	/* set attributes */
+	baseReg &= ~ETH_WIN_ATTR_MASK;
+	baseReg |= pAddrDecWin->attrib << ETH_WIN_ATTR_OFFS;
+
+	/* set target ID */
+	baseReg &= ~ETH_WIN_TARGET_MASK;
+	baseReg |= pAddrDecWin->targetId << ETH_WIN_TARGET_OFFS;
+
+	/* for the safe side we disable the window before writing the new
+	   values */
+	mvNetaWinEnable(port, winNum, MV_FALSE);
+	MV_REG_WRITE(ETH_WIN_BASE_REG(port, winNum), baseReg);
+
+	/* Write to address decode Size Register                            */
+	MV_REG_WRITE(ETH_WIN_SIZE_REG(port, winNum), sizeReg);
+
+	/* Enable address decode target window                              */
+	if (pAddrDecWin->enable == MV_TRUE)
+		mvNetaWinEnable(port, winNum, MV_TRUE);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* ethWinOverlapDetect - Detect ETH address windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviur is expected in case ETH address decode
+*       windows overlapps.
+*       This function detects ETH address decode windows overlapping of a
+*       specified window. The function does not check the window itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS ethWinOverlapDetect(MV_U32 port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 baseAddrEnableReg;
+	MV_U32 winNumIndex;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	/* Read base address enable register. Do not check disabled windows     */
+	baseAddrEnableReg = MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port));
+
+	for (winNumIndex = 0; winNumIndex < ETH_MAX_DECODE_WIN; winNumIndex++) {
+		/* Do not check window itself           */
+		if (winNumIndex == winNum)
+			continue;
+
+		/* Do not check disabled windows        */
+		if (baseAddrEnableReg & (1 << winNumIndex))
+			continue;
+
+		/* Get window parameters        */
+		if (MV_OK != mvNetaWinRead(port, winNumIndex, &addrDecWin)) {
+			mvOsPrintf("ethWinOverlapDetect: ERR. TargetWinGet failed\n");
+			return MV_ERROR;
+		}
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+			return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvNetaWinRead
+*
+* DESCRIPTION:
+*       Read Ethernet peripheral target address window.
+*
+* INPUT:
+*       winNum - ETH to target address decode window number.
+*
+* OUTPUT:
+*       pAddrDecWin - ETH target window data structure.
+*
+* RETURN:
+*	MV_BAD_PARAM if winNum is invalid.
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvNetaWinRead(MV_U32 port, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 baseReg, sizeReg;
+	MV_U32 alignment, size;
+
+	/* Parameter checking   */
+	if (winNum >= ETH_MAX_DECODE_WIN) {
+		mvOsPrintf("mvNetaWinGet: ERR. Invalid winNum %d\n", winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum));
+	sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum));
+
+	alignment = 1 << ETH_WIN_SIZE_OFFS;
+	size = (sizeReg & ETH_WIN_SIZE_MASK) >> ETH_WIN_SIZE_OFFS;
+	pAddrDecWin->addrWin.size = (size + 1) * alignment;
+
+	/* Extract base address                                     */
+	pAddrDecWin->addrWin.baseLow = baseReg & ETH_WIN_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh = 0;
+
+	/* attrib and targetId */
+	pAddrDecWin->attrib = (baseReg & ETH_WIN_ATTR_MASK) >> ETH_WIN_ATTR_OFFS;
+	pAddrDecWin->targetId = (baseReg & ETH_WIN_TARGET_MASK) >> ETH_WIN_TARGET_OFFS;
+
+	/* Check if window is enabled   */
+	if (~(MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port))) & (1 << winNum))
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaWinEnable - Enable/disable a ETH to target address window
+*
+* DESCRIPTION:
+*       This function enable/disable a ETH to target address window.
+*       According to parameter 'enable' the routine will enable the
+*       window, thus enabling ETH accesses (before enabling the window it is
+*       tested for overlapping). Otherwise, the window will be disabled.
+*
+* INPUT:
+*       winNum - ETH to target address decode window number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_ERROR if decode window number was wrong or enabled window overlapps.
+*
+*******************************************************************************/
+MV_STATUS mvNetaWinEnable(MV_U32 port, MV_U32 winNum, MV_BOOL enable)
+{
+	/* Parameter checking   */
+	if (winNum >= ETH_MAX_DECODE_WIN) {
+		mvOsPrintf("mvNetaTargetWinEnable:ERR. Invalid winNum%d\n", winNum);
+		return MV_ERROR;
+	}
+
+	if (enable == MV_TRUE)
+		MV_REG_BIT_RESET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum));
+	else
+		/* Disable address decode target window                             */
+		MV_REG_BIT_SET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaProtWinSet - Set access protection of Ethernet to target window.
+*
+* DESCRIPTION:
+*       Each Ethernet port can be configured with access attributes for each
+*       of the Ethenret to target windows (address decode windows). This
+*       function sets access attributes to a given window for the given channel.
+*
+* INPUTS:
+*       ethPort   - ETH channel number. See MV_ETH_CHANNEL enumerator.
+*       winNum - IETH to target address decode window number.
+*       access - IETH access rights. See MV_ACCESS_RIGHTS enumerator.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR in case window number is invalid or access right reserved.
+*
+*******************************************************************************/
+MV_STATUS mvNetaProtWinSet(MV_U32 portNo, MV_U32 winNum, MV_ACCESS_RIGHTS access)
+{
+	MV_U32 protReg;
+
+	/* Parameter checking   */
+	if (portNo >= MV_ETH_MAX_PORTS) {
+		mvOsPrintf("mvNetaProtWinSet:ERR. Invalid port number %d\n", portNo);
+		return MV_ERROR;
+	}
+
+	if (winNum >= ETH_MAX_DECODE_WIN) {
+		mvOsPrintf("mvNetaProtWinSet:ERR. Invalid winNum%d\n", winNum);
+		return MV_ERROR;
+	}
+
+	if ((access == ACC_RESERVED) || (access >= MAX_ACC_RIGHTS)) {
+		mvOsPrintf("mvNetaProtWinSet:ERR. Inv access param %d\n", access);
+		return MV_ERROR;
+	}
+	/* Read current protection register */
+	protReg = MV_REG_READ(ETH_ACCESS_PROTECT_REG(portNo));
+
+	/* Clear protection window field */
+	protReg &= ~(ETH_PROT_WIN_MASK(winNum));
+
+	/* Set new protection field value */
+	protReg |= (access << (ETH_PROT_WIN_OFFS(winNum)));
+
+	/* Write protection register back   */
+	MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(portNo), protReg);
+
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaDebug.c b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaDebug.c
new file mode 100755
index 0000000..2a487d0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaDebug.c
@@ -0,0 +1,794 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvNetaDebug.c - Source file for user friendly debug functions
+*
+* DESCRIPTION:
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#include "mvOs.h"
+#include "mvCommon.h"
+#include "mvTypes.h"
+#include "mv802_3.h"
+#include "mvDebug.h"
+
+#include "mvNeta.h"
+#include "bm/mvBm.h"
+#include "pnc/mvTcam.h"
+
+static void mvEthRegPrint(MV_U32 reg_addr, char *reg_name)
+{
+	mvOsPrintf("  %-32s: 0x%x = 0x%08x\n", reg_name, reg_addr, MV_REG_READ(reg_addr));
+}
+
+static void mvEthRegPrint0(MV_U32 reg_addr, char *reg_name)
+{
+	mvOsPrintf("  %-32s: %u\n", reg_name, MV_REG_READ(reg_addr));
+}
+
+static void mvEthRegPrint2(MV_U32 reg_addr, char *reg_name, MV_U32 index)
+{
+	char buf[64];
+
+	mvOsSPrintf(buf, "%s[%d]", reg_name, index);
+	mvOsPrintf("  %-32s: 0x%x = 0x%08x\n", buf, reg_addr, MV_REG_READ(reg_addr));
+}
+
+static void mvEthMibPrint(int port, int mib, MV_U32 offset, char *mib_name)
+{
+	MV_U32 regVaLo, regValHi = 0;
+
+	regVaLo = mvNetaMibCounterRead(port, mib, offset, &regValHi);
+
+	if (!regValHi)
+		mvOsPrintf("  %-32s: %u\n", mib_name, regVaLo);
+	else
+		mvOsPrintf("  t%-32s: 0x%08x%08x\n", mib_name, regValHi, regVaLo);
+}
+
+void mvEthTxpWrrRegs(int port, int txp)
+{
+	int queue;
+
+	if (mvNetaTxpCheck(port, txp))
+		return;
+
+	mvOsPrintf("\n[TXP WRR/EJP registers: port=%d, txp=%d]\n", port, txp);
+	mvEthRegPrint(ETH_TX_QUEUE_COMMAND_REG(port, txp), "ETH_TX_QUEUE_COMMAND_REG");
+
+#ifdef MV_ETH_WRR_NEW
+	mvEthRegPrint(NETA_TX_CMD_1_REG(port, txp),          "NETA_TX_CMD_1_REG");
+	mvEthRegPrint(NETA_TX_FIXED_PRIO_CFG_REG(port, txp), "NETA_TX_FIXED_PRIO_CFG_REG");
+	mvEthRegPrint(NETA_TX_REFILL_PERIOD_REG(port, txp),  "NETA_TX_REFILL_PERIOD_REG");
+	mvEthRegPrint(NETA_TXP_MTU_REG(port, txp),           "NETA_TXP_MTU_REG");
+	mvEthRegPrint(NETA_TXP_REFILL_REG(port, txp),        "NETA_TXP_REFILL_REG");
+	mvEthRegPrint(NETA_TXP_TOKEN_SIZE_REG(port, txp),    "NETA_TXP_TOKEN_SIZE_REG");
+	mvEthRegPrint(NETA_TXP_TOKEN_CNTR_REG(port, txp),    "NETA_TXP_TOKEN_CNTR_REG");
+	mvEthRegPrint(NETA_TXP_EJP_HI_LO_REG(port, txp),     "NETA_TXP_EJP_HI_LO_REG");
+	mvEthRegPrint(NETA_TXP_EJP_HI_ASYNC_REG(port, txp),  "NETA_TXP_EJP_HI_ASYNC_REG");
+	mvEthRegPrint(NETA_TXP_EJP_LO_ASYNC_REG(port, txp),  "NETA_TXP_EJP_LO_ASYNC_REG");
+	mvEthRegPrint(NETA_TXP_EJP_SPEED_REG(port, txp),     "NETA_TXP_EJP_SPEED_REG");
+
+	for (queue = 0; queue < MV_ETH_MAX_TXQ; queue++) {
+		mvOsPrintf("\n[TXQ WRR/EJP registers: port=%d, txp=%d, txq=%d]\n", port, txp, queue);
+		mvEthRegPrint(NETA_TXQ_REFILL_REG(port, txp, queue), "NETA_TXQ_REFILL_REG");
+		mvEthRegPrint(NETA_TXQ_TOKEN_SIZE_REG(port, txp, queue), "NETA_TXQ_TOKEN_SIZE_REG");
+		mvEthRegPrint(NETA_TXQ_TOKEN_CNTR_REG(port, txp, queue), "NETA_TXQ_TOKEN_CNTR_REG");
+		mvEthRegPrint(NETA_TXQ_WRR_ARBITER_REG(port, txp, queue), "NETA_TXQ_WRR_ARBITER_REG");
+		if ((queue == 2) || (queue == 3))
+			mvEthRegPrint(NETA_TXQ_EJP_IPG_REG(port, txp, queue), "NETA_TXQ_EJP_IPG_REG");
+	}
+#else
+	mvEthRegPrint(ETH_TXQ_CMD_1_REG(port, txp), "ETH_TXQ_CMD_1_REG");
+	mvEthRegPrint(ETH_TX_FIXED_PRIO_CFG_REG(port, txp), "ETH_TX_FIXED_PRIO_CFG_REG");
+	mvEthRegPrint(ETH_TXP_TOKEN_RATE_CFG_REG(port, txp), "ETH_TXP_TOKEN_RATE_CFG_REG");
+	mvEthRegPrint(ETH_MAX_TRANSMIT_UNIT_REG(port, txp), "ETH_MAX_TRANSMIT_UNIT_REG");
+	mvEthRegPrint(ETH_TXP_TOKEN_SIZE_REG(port, txp), "ETH_TXP_TOKEN_BUCKET_SIZE_REG");
+	mvEthRegPrint(ETH_TXP_TOKEN_COUNT_REG(port, txp), "ETH_TXP_TOKEN_BUCKET_COUNT_REG");
+
+	for (queue = 0; queue < MV_ETH_MAX_TXQ; queue++) {
+		mvOsPrintf("\n[TxQ policy: port=%d, txp=%d, txq=%d]\n", port, txp, queue);
+		mvEthRegPrint(ETH_TXQ_TOKEN_COUNT_REG(port, txp, queue), "ETH_TXQ_TOKEN_COUNT_REG");
+		mvEthRegPrint(ETH_TXQ_TOKEN_CFG_REG(port, txp, queue), "ETH_TXQ_TOKEN_CFG_REG");
+		mvEthRegPrint(ETH_TXQ_ARBITER_CFG_REG(port, txp, queue), "ETH_TXQ_ARBITER_CFG_REG");
+	}
+#endif /* MV_ETH_WRR_NEW */
+}
+
+/* Print important registers of Ethernet port */
+void mvEthPortRegs(int port)
+{
+	int txp;
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(port);
+
+	if (mvNetaPortCheck(port))
+		return;
+
+	mvEthRegPrint(ETH_PORT_STATUS_REG(port), "ETH_PORT_STATUS_REG");
+	mvEthRegPrint(ETH_PORT_SERIAL_CTRL_REG(port), "ETH_PORT_SERIAL_CTRL_REG");
+	mvEthRegPrint(ETH_PORT_CONFIG_REG(port), "ETH_PORT_CONFIG_REG");
+	mvEthRegPrint(ETH_PORT_CONFIG_EXTEND_REG(port), "ETH_PORT_CONFIG_EXTEND_REG");
+	mvEthRegPrint(ETH_SDMA_CONFIG_REG(port), "ETH_SDMA_CONFIG_REG");
+	mvEthRegPrint(ETH_RX_MINIMAL_FRAME_SIZE_REG(port), "ETH_RX_MINIMAL_FRAME_SIZE_REG");
+	mvEthRegPrint(ETH_INTR_CAUSE_REG(port), "ETH_INTR_CAUSE_REG");
+	mvEthRegPrint(ETH_INTR_CAUSE_EXT_REG(port), "ETH_INTR_CAUSE_EXT_REG");
+	mvEthRegPrint(ETH_INTR_MASK_REG(port), "ETH_INTR_MASK_REG");
+	mvEthRegPrint(ETH_INTR_MASK_EXT_REG(port), "ETH_INTR_MASK_EXT_REG");
+
+	mvEthRegPrint(ETH_RX_QUEUE_COMMAND_REG(port), "ETH_RX_QUEUE_COMMAND_REG");
+	for (txp = 0; txp < pPortCtrl->txpNum; txp++)
+		mvEthRegPrint(ETH_TX_QUEUE_COMMAND_REG(port, txp), "ETH_TX_QUEUE_COMMAND_REG");
+}
+
+/* Print Giga Ethernet UNIT registers */
+void mvEthRegs(int port)
+{
+	int win;
+	MV_U32	regValue;
+
+	if (mvNetaPortCheck(port))
+		return;
+
+	mvEthRegPrint(ETH_PHY_ADDR_REG(port), "ETH_PHY_ADDR_REG");
+	mvEthRegPrint(ETH_UNIT_INTR_CAUSE_REG(port), "ETH_UNIT_INTR_CAUSE_REG");
+	mvEthRegPrint(ETH_UNIT_INTR_MASK_REG(port), "ETH_UNIT_INTR_MASK_REG");
+	mvEthRegPrint(ETH_UNIT_ERROR_ADDR_REG(port), "ETH_UNIT_ERROR_ADDR_REG");
+	mvEthRegPrint(ETH_UNIT_INT_ADDR_ERROR_REG(port), "ETH_UNIT_INT_ADDR_ERROR_REG");
+	mvEthRegPrint(ETH_BASE_ADDR_ENABLE_REG(port), "ETH_BASE_ADDR_ENABLE_REG");
+	mvEthRegPrint(ETH_ACCESS_PROTECT_REG(port), "ETH_ACCESS_PROTECT_REG");
+
+	regValue = MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port));
+	for (win = 0; win < ETH_MAX_DECODE_WIN; win++) {
+		if (regValue & (1 << win))
+			continue; /* window is disable */
+		mvOsPrintf("win[%d]\n", win);
+		mvEthRegPrint(ETH_WIN_BASE_REG(port, win), "ETH_WIN_BASE_REG");
+		mvEthRegPrint(ETH_WIN_SIZE_REG(port, win), "ETH_WIN_SIZE_REG");
+	}
+}
+
+#ifdef MV_ETH_GMAC_NEW
+void    mvNetaGmacRegs(int port)
+{
+	if (mvNetaPortCheck(port))
+		return;
+
+	if (MV_PON_PORT(port)) {
+		mvOsPrintf("Not supported for PON port #%d \n", port);
+		return;
+	}
+	mvEthRegPrint(ETH_PORT_STATUS_REG(port),        "ETH_PORT_STATUS_REG");
+	mvEthRegPrint(ETH_PORT_SERIAL_CTRL_REG(port),   "ETH_PORT_SERIAL_CTRL_REG");
+	mvEthRegPrint(NETA_GMAC_CTRL_0_REG(port),       "NETA_GMAC_CTRL_0_REG");
+	mvEthRegPrint(NETA_GMAC_CTRL_1_REG(port),       "NETA_GMAC_CTRL_1_REG");
+	mvEthRegPrint(NETA_GMAC_CTRL_2_REG(port),       "NETA_GMAC_CTRL_2_REG");
+	mvEthRegPrint(NETA_GMAC_AN_CTRL_REG(port),      "NETA_GMAC_AN_CTRL_REG");
+	mvEthRegPrint(NETA_GMAC_STATUS_REG(port),       "NETA_GMAC_STATUS_REG");
+	mvEthRegPrint(NETA_GMAC_SERIAL_REG(port),       "NETA_GMAC_SERIAL_REG");
+	mvEthRegPrint(NETA_GMAC_FIFO_PARAM_0_REG(port), "NETA_GMAC_FIFO_PARAM_0_REG");
+	mvEthRegPrint(NETA_GMAC_FIFO_PARAM_1_REG(port), "NETA_GMAC_FIFO_PARAM_1_REG");
+	mvEthRegPrint(NETA_GMAC_CAUSE_REG(port),        "NETA_GMAC_CAUSE_REG");
+	mvEthRegPrint(NETA_GMAC_MASK_REG(port),         "NETA_GMAC_MASK_REG");
+	mvEthRegPrint(NETA_GMAC_MIB_CTRL_REG(port),     "NETA_GMAC_MIB_CTRL_REG");
+}
+#endif /* MV_ETH_GMAC_NEW */
+
+void mvNetaRxqRegs(int port, int rxq)
+{
+	if (mvNetaPortCheck(port))
+		return;
+
+	if (mvNetaMaxCheck(rxq, MV_ETH_MAX_RXQ))
+		return;
+
+	mvOsPrintf("\n[NetA Rx: port=%d, rxq=%d]\n", port, rxq);
+	mvEthRegPrint(ETH_RX_QUEUE_COMMAND_REG(port), "ETH_RX_QUEUE_COMMAND_REG");
+	mvEthRegPrint(NETA_RXQ_CONFIG_REG(port, rxq), "NETA_RXQ_CONFIG_REG");
+	mvEthRegPrint(NETA_RXQ_INTR_TIME_COAL_REG(port, rxq), "NETA_RXQ_INTR_TIME_COAL_REG");
+	mvEthRegPrint(NETA_RXQ_BASE_ADDR_REG(port, rxq), "NETA_RXQ_BASE_ADDR_REG");
+	mvEthRegPrint(NETA_RXQ_SIZE_REG(port, rxq), "NETA_RXQ_SIZE_REG");
+	mvEthRegPrint(NETA_RXQ_THRESHOLD_REG(port, rxq), "NETA_RXQ_THRESHOLD_REG");
+	mvEthRegPrint(NETA_RXQ_STATUS_REG(port, rxq), "NETA_RXQ_STATUS_REG");
+	mvEthRegPrint(NETA_RXQ_INDEX_REG(port, rxq), "NETA_RXQ_INDEX_REG");
+}
+
+void mvNetaTxqRegs(int port, int txp, int txq)
+{
+	if (mvNetaTxpCheck(port, txp))
+		return;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return;
+
+	mvOsPrintf("\n[NetA Tx: port=%d, txp=%d, txq=%d]\n", port, txp, txq);
+	mvEthRegPrint(NETA_TXQ_BASE_ADDR_REG(port, txp, txq), "NETA_TXQ_BASE_ADDR_REG");
+	mvEthRegPrint(NETA_TXQ_SIZE_REG(port, txp, txq), "NETA_TXQ_SIZE_REG");
+	mvEthRegPrint(NETA_TXQ_STATUS_REG(port, txp, txq), "NETA_TXQ_STATUS_REG");
+	mvEthRegPrint(NETA_TXQ_INDEX_REG(port, txp, txq), "NETA_TXQ_INDEX_REG");
+	mvEthRegPrint(NETA_TXQ_SENT_DESC_REG(port, txp, txq), "NETA_TXQ_SENT_DESC_REG");
+}
+
+void mvNetaTxpRegs(int port, int txp)
+{
+	int queue;
+
+	if (mvNetaTxpCheck(port, txp))
+		return;
+
+	mvOsPrintf("\n[NetA Tx: port=%d, txp=%d]\n", port, txp);
+	mvEthRegPrint(ETH_TX_QUEUE_COMMAND_REG(port, txp), "ETH_TX_QUEUE_COMMAND_REG");
+	for (queue = 0; queue < CONFIG_MV_ETH_TXQ; queue++)
+		mvNetaTxqRegs(port, txp, queue);
+}
+
+#ifdef CONFIG_MV_ETH_PNC
+void mvNetaPncRegs(void)
+{
+	mvEthRegPrint(MV_PNC_LOOP_CTRL_REG, "PNC_LOOP_CTRL_REG");
+	mvEthRegPrint(MV_PNC_TCAM_CTRL_REG, "PNC_TCAM_CTRL_REG");
+	mvEthRegPrint(MV_PNC_INIT_OFFS_REG, "PNC_INIT_OFFS_REG");
+	mvEthRegPrint(MV_PNC_INIT_LOOKUP_REG, "PNC_INIT_LOOKUP_REG");
+	mvEthRegPrint(MV_PNC_CAUSE_REG, "PNC_CAUSE_REG");
+	mvEthRegPrint(MV_PNC_MASK_REG, "PNC_MASK_REG");
+	mvEthRegPrint(MV_PNC_HIT_SEQ0_REG, "PNC_HIT_SEQ0_REG");
+	mvEthRegPrint(MV_PNC_HIT_SEQ1_REG, "PNC_HIT_SEQ1_REG");
+	mvEthRegPrint(MV_PNC_HIT_SEQ2_REG, "PNC_HIT_SEQ2_REG");
+	mvEthRegPrint(MV_PNC_XBAR_RET_REG, "PNC_XBAR_RET_REG");
+
+#ifdef MV_ETH_PNC_AGING
+	{
+		int     i;
+
+		mvEthRegPrint(MV_PNC_AGING_CTRL_REG,  "PNC_AGING_CTRL_REG");
+		mvEthRegPrint(MV_PNC_AGING_HI_THRESH_REG,  "PNC_AGING_HI_THRESH_REG");
+		mvOsPrintf("\n");
+		for (i = 0; i < MV_PNC_AGING_MAX_GROUP; i++)
+			mvEthRegPrint2(MV_PNC_AGING_LO_THRESH_REG(i), "PNC_AGING_LO_THRESH_REG", i);
+	}
+#endif /* MV_ETH_PNC_AGING */
+
+#ifdef MV_ETH_PNC_LB
+	mvEthRegPrint(MV_PNC_LB_CRC_INIT_REG, "PNC_LB_CRC_INIT_REG");
+#endif /* MV_ETH_PNC_LB */
+}
+#endif /* CONFIG_MV_ETH_PNC */
+
+#ifdef CONFIG_MV_ETH_PMT
+void mvNetaPmtRegs(int port, int txp)
+{
+	int i;
+
+	if (mvNetaTxpCheck(port, txp))
+		return;
+
+	mvOsPrintf("\n[NetA PMT registers: port=%d, txp=%d]\n", port, txp);
+
+#ifdef MV_ETH_PMT_NEW
+	mvEthRegPrint(NETA_TX_PMT_ACCESS_REG(port), "NETA_TX_PMT_ACCESS_REG");
+	mvEthRegPrint(NETA_TX_PMT_FIFO_THRESH_REG(port), "NETA_TX_PMT_FIFO_THRESH_REG");
+	mvEthRegPrint(NETA_TX_PMT_MTU_REG(port), "NETA_TX_PMT_MTU_REG");
+
+	mvOsPrintf("\n");
+	for (i = 0; i < NETA_TX_PMT_MAX_ETHER_TYPES; i++)
+		mvEthRegPrint2(NETA_TX_PMT_ETHER_TYPE_REG(port, txp, i), "NETA_TX_PMT_ETHER_TYPE_REG", i);
+
+	mvOsPrintf("\n");
+	mvEthRegPrint(NETA_TX_PMT_DEF_VLAN_CFG_REG(port), "NETA_TX_PMT_DEF_VLAN_CFG_REG");
+	mvEthRegPrint(NETA_TX_PMT_DEF_DSA_1_CFG_REG(port), "NETA_TX_PMT_DEF_DSA_1_CFG_REG");
+	mvEthRegPrint(NETA_TX_PMT_DEF_DSA_2_CFG_REG(port), "NETA_TX_PMT_DEF_DSA_2_CFG_REG");
+	mvEthRegPrint(NETA_TX_PMT_DEF_DSA_SRC_DEV_REG(port), "NETA_TX_PMT_DEF_DSA_SRC_DEV_REG");
+
+	mvEthRegPrint(NETA_TX_PMT_TTL_ZERO_CNTR_REG(port), "NETA_TX_PMT_TTL_ZERO_CNTR_REG");
+	mvEthRegPrint(NETA_TX_PMT_TTL_ZERO_CNTR_REG(port), "NETA_TX_PMT_TTL_ZERO_CNTR_REG");
+
+	mvOsPrintf("\n");
+	mvEthRegPrint(NETA_TX_PMT_PPPOE_TYPE_REG(port, txp), "NETA_TX_PMT_PPPOE_TYPE_REG");
+	mvEthRegPrint(NETA_TX_PMT_PPPOE_DATA_REG(port, txp), "NETA_TX_PMT_PPPOE_DATA_REG");
+	mvEthRegPrint(NETA_TX_PMT_PPPOE_LEN_REG(port, txp), "NETA_TX_PMT_PPPOE_LEN_REG");
+	mvEthRegPrint(NETA_TX_PMT_PPPOE_PROTO_REG(port, txp), "NETA_TX_PMT_PPPOE_PROTO_REG");
+	mvOsPrintf("\n");
+
+	mvEthRegPrint(NETA_TX_PMT_CONFIG_REG(port), "NETA_TX_PMT_CONFIG_REG");
+	mvEthRegPrint(NETA_TX_PMT_STATUS_1_REG(port), "NETA_TX_PMT_STATUS_1_REG");
+	mvEthRegPrint(NETA_TX_PMT_STATUS_2_REG(port), "NETA_TX_PMT_STATUS_2_REG");
+#else
+	for (i = 0; i < NETA_TX_MAX_MH_REGS; i++)
+		mvEthRegPrint2(NETA_TX_MH_REG(port, txp, i), "NETA_TX_MH_REG", i);
+
+	mvEthRegPrint(NETA_TX_DSA_SRC_DEV_REG(port, txp), "NETA_TX_DSA_SRC_DEV_REG");
+
+	for (i = 0; i < NETA_TX_MAX_ETH_TYPE_REGS; i++)
+		mvEthRegPrint2(NETA_TX_ETH_TYPE_REG(port, txp, i), "NETA_TX_ETH_TYPE_REG", i);
+#endif /* MV_ETH_PMT_NEW */
+}
+#endif /* CONFIG_MV_ETH_PMT */
+
+void mvNetaPortRegs(int port)
+{
+	int i;
+	MV_NETA_PORT_CTRL *pPortCtrl = mvNetaPortHndlGet(port);
+
+	if (mvNetaPortCheck(port))
+		return;
+
+	/* Per CPU register */
+	for (i = 0; i < mvNetaHalData.maxCPUs; i++)
+		mvEthRegPrint2(NETA_CPU_MAP_REG(port, i), "NETA_CPU_MAP_REG", i);
+
+	/* Per BM pool registers */
+	for (i = 0; i < MV_BM_POOLS; i++)
+		mvEthRegPrint2(NETA_POOL_BUF_SIZE_REG(port, i), "NETA_POOL_BUF_SIZE_REG", i);
+
+	/* Per port registers */
+	mvEthRegPrint(NETA_VERSION_REG(port), "NETA_VERSION_REG");
+	mvEthRegPrint(NETA_PORT_RX_RESET_REG(port), "NETA_PORT_RX_RESET_REG");
+	for (i = 0; i < pPortCtrl->txpNum; i++)
+		mvEthRegPrint(NETA_PORT_TX_RESET_REG(port, i), "NETA_PORT_TX_RESET_REG");
+	mvEthRegPrint(NETA_BM_ADDR_REG(port), "NETA_BM_ADDR_REG");
+	mvEthRegPrint(NETA_ACC_MODE_REG(port), "NETA_ACC_MODE_REG");
+	mvEthRegPrint(NETA_INTR_NEW_CAUSE_REG(port), "NETA_INTR_NEW_CAUSE_REG");
+	mvEthRegPrint(NETA_INTR_NEW_MASK_REG(port), "NETA_INTR_NEW_MASK_REG");
+	mvEthRegPrint(NETA_INTR_MISC_CAUSE_REG(port), "NETA_INTR_MISC_CAUSE_REG");
+	mvEthRegPrint(NETA_INTR_MISC_MASK_REG(port), "NETA_INTR_MISC_MASK_REG");
+	mvEthRegPrint(NETA_INTR_ENABLE_REG(port), "NETA_INTR_ENABLE_REG");
+	mvEthRegPrint(NETA_LEGACY_DBA_REG(port), "NETA_LEGACY_DBA_REG");
+}
+
+/* Print status of Ethernet port */
+void mvNetaPortStatus(int port)
+{
+	MV_ETH_PORT_STATUS	link;
+	MV_NETA_PORT_CTRL 	*pPortCtrl;
+
+	if (mvNetaPortCheck(port))
+		return;
+
+	pPortCtrl = mvNetaPortHndlGet(port);
+	mvOsPrintf("\n[Link: port=%d, ctrl=%p]\n", port, pPortCtrl);
+	if (!pPortCtrl)
+		return;
+
+	if (MV_PON_PORT(port)) {
+		mvOsPrintf("GPON port %d link is up\n", port);
+	} else {
+
+		mvNetaLinkStatus(port, &link);
+
+		if (link.linkup) {
+			mvOsPrintf("link up");
+			mvOsPrintf(", %s duplex", (link.duplex == MV_ETH_DUPLEX_FULL) ? "full" : "half");
+			mvOsPrintf(", speed ");
+
+			if (link.speed == MV_ETH_SPEED_1000)
+				mvOsPrintf("1 Gbps\n");
+			else if (link.speed == MV_ETH_SPEED_100)
+				mvOsPrintf("100 Mbps\n");
+			else
+				mvOsPrintf("10 Mbps\n");
+
+			mvOsPrintf("rxFC - %s, txFC - %s\n",
+				(link.rxFc == MV_ETH_FC_DISABLE) ? "disabled" : "enabled",
+				(link.txFc == MV_ETH_FC_DISABLE) ? "disabled" : "enabled");
+		} else
+			mvOsPrintf("link down\n");
+	}
+#ifndef CONFIG_MV_ETH_PNC
+	{
+		MV_U32	regValue = MV_REG_READ(ETH_PORT_CONFIG_REG(port));
+
+		mvOsPrintf("default queue: rx=%d, arp=%d, bpdu=%d, tcp=%d, udp=%d\n",
+		   (regValue & ETH_DEF_RX_QUEUE_ALL_MASK) >> ETH_DEF_RX_QUEUE_OFFSET,
+		   (regValue & ETH_DEF_RX_ARP_QUEUE_ALL_MASK) >> ETH_DEF_RX_ARP_QUEUE_OFFSET,
+		   (regValue & ETH_DEF_RX_BPDU_QUEUE_ALL_MASK) >> ETH_DEF_RX_BPDU_QUEUE_OFFSET,
+		   (regValue & ETH_DEF_RX_TCP_QUEUE_ALL_MASK) >> ETH_DEF_RX_TCP_QUEUE_OFFSET,
+		   (regValue & ETH_DEF_RX_UDP_QUEUE_ALL_MASK) >> ETH_DEF_RX_UDP_QUEUE_OFFSET);
+	}
+#endif /* CONFIG_MV_ETH_PNC */
+}
+
+void mvNetaRxqShow(int port, int rxq, int mode)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl;
+	MV_NETA_QUEUE_CTRL *pQueueCtrl;
+
+	if (mvNetaPortCheck(port))
+		return;
+
+	if (mvNetaMaxCheck(rxq, MV_ETH_MAX_RXQ))
+		return;
+
+	pPortCtrl = mvNetaPortHndlGet(port);
+	if (!pPortCtrl)
+		return;
+
+	pQueueCtrl = &pPortCtrl->pRxQueue[rxq].queueCtrl;
+	mvOsPrintf("\n[NetA RxQ: port=%d, rxq=%d]\n", port, rxq);
+
+	if (!pQueueCtrl->pFirst) {
+		mvOsPrintf("rx queue %d wasn't created\n", rxq);
+		return;
+	}
+
+	mvOsPrintf("intr_coal: %d [pkts] or %d [usec]\n",
+		mvNetaRxqPktsCoalGet(port, rxq), mvNetaRxqTimeCoalGet(port, rxq));
+
+	mvOsPrintf("pFirst=%p (0x%x), numOfDescr=%d\n",
+		   pQueueCtrl->pFirst,
+		   (MV_U32) netaDescVirtToPhys(pQueueCtrl, (MV_U8 *) pQueueCtrl->pFirst), pQueueCtrl->lastDesc + 1);
+
+	mvOsPrintf("nextToProc=%d (%p), rxqOccupied=%d, rxqNonOccupied=%d\n",
+		   pQueueCtrl->nextToProc,
+		   MV_NETA_QUEUE_DESC_PTR(pQueueCtrl, pQueueCtrl->nextToProc),
+		   mvNetaRxqBusyDescNumGet(port, rxq), mvNetaRxqFreeDescNumGet(port, rxq));
+
+	if (mode > 0) {
+		int i;
+		NETA_RX_DESC *pRxDesc;
+
+		for (i = 0; i <= pQueueCtrl->lastDesc; i++) {
+			pRxDesc = (NETA_RX_DESC *) MV_NETA_QUEUE_DESC_PTR(pQueueCtrl, i);
+
+			mvOsPrintf("%3d. desc=%p, status=%08x, data=%4d, bufAddr=%08x, bufCookie=%08x\n",
+				   i, pRxDesc, pRxDesc->status,
+				   pRxDesc->dataSize, (MV_U32) pRxDesc->bufPhysAddr, (MV_U32) pRxDesc->bufCookie);
+
+			mvOsCacheLineInv(NULL, pRxDesc);
+		}
+	}
+}
+
+void mvNetaTxqShow(int port, int txp, int txq, int mode)
+{
+	MV_NETA_PORT_CTRL *pPortCtrl;
+	MV_NETA_TXQ_CTRL *pTxqCtrl;
+	MV_NETA_QUEUE_CTRL *pQueueCtrl;
+
+	if (mvNetaTxpCheck(port, txp))
+		return;
+
+	pPortCtrl = mvNetaPortHndlGet(port);
+	if (!pPortCtrl)
+		return;
+
+	if (mvNetaMaxCheck(txq, MV_ETH_MAX_TXQ))
+		return;
+
+	mvOsPrintf("\n[NetA TxQ: port=%d, txp=%d, txq=%d]\n", port, txp, txq);
+
+	pTxqCtrl = mvNetaTxqHndlGet(port, txp, txq);
+	pQueueCtrl = &pTxqCtrl->queueCtrl;
+
+	if (!pQueueCtrl->pFirst) {
+		mvOsPrintf("tx queue %d wasn't created\n", txq);
+		return;
+	}
+
+	mvOsPrintf("pFirst=%p (0x%x), numOfDescr=%d\n",
+		   pQueueCtrl->pFirst,
+		   (MV_U32) netaDescVirtToPhys(pQueueCtrl, (MV_U8 *) pQueueCtrl->pFirst), pQueueCtrl->lastDesc + 1);
+
+	mvOsPrintf("nextToProc=%d (%p), txqSent=%d, txqPending=%d\n",
+		   pQueueCtrl->nextToProc,
+		   MV_NETA_QUEUE_DESC_PTR(pQueueCtrl, pQueueCtrl->nextToProc),
+		   mvNetaTxqSentDescNumGet(port, txp, txq), mvNetaTxqPendDescNumGet(port, txp, txq));
+
+	if (mode > 0) {
+		int i;
+		NETA_TX_DESC *pTxDesc;
+
+		for (i = 0; i <= pQueueCtrl->lastDesc; i++) {
+			pTxDesc = (NETA_TX_DESC *) MV_NETA_QUEUE_DESC_PTR(pQueueCtrl, i);
+
+			mvOsPrintf("%3d. pTxDesc=%p, cmd=%08x, data=%4d, bufAddr=%08x, gponinfo=%x\n",
+				   i, pTxDesc, pTxDesc->command, pTxDesc->dataSize,
+				   (MV_U32) pTxDesc->bufPhysAddr, pTxDesc->hw_cmd);
+
+			mvOsCacheLineInv(NULL, pTxDesc);
+		}
+	}
+}
+
+/* Print counters of the Ethernet port */
+void mvEthPortCounters(int port, int mib)
+{
+#ifndef MV_PON_MIB_SUPPORT
+	if (MV_PON_PORT(port)) {
+		mvOsPrintf("%s: not supported for PON port\n", __func__);
+		return;
+	}
+#endif /* !MV_PON_MIB_SUPPORT */
+
+	if (mvNetaTxpCheck(port, mib))
+		return;
+
+	if (!mvNetaPortHndlGet(port))
+		return;
+
+	mvOsPrintf("\nMIBs: port=%d, mib=%d\n", port, mib);
+
+#ifdef CONFIG_MV_PON
+	if (MV_PON_PORT(port)) {
+		int	i;
+
+		for (i = 0; i < NETA_PON_MIB_MAX_GEM_PID; i++)
+			mvEthRegPrint2(NETA_PON_MIB_RX_CTRL_REG(i), "NETA_PON_MIB_RX_CTRL_REG", i);
+
+		mvEthRegPrint(NETA_PON_MIB_RX_DEF_REG, "NETA_PON_MIB_RX_DEF_REG");
+	}
+#endif /* CONFIG_MV_PON */
+
+	mvOsPrintf("\n[Rx]\n");
+	mvEthMibPrint(port, mib, ETH_MIB_GOOD_FRAMES_RECEIVED, "GOOD_FRAMES_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_BAD_FRAMES_RECEIVED, "BAD_FRAMES_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_BROADCAST_FRAMES_RECEIVED, "BROADCAST_FRAMES_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_MULTICAST_FRAMES_RECEIVED, "MULTICAST_FRAMES_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, "GOOD_OCTETS_RECEIVED");
+	mvOsPrintf("\n[Rx Errors]\n");
+	mvEthMibPrint(port, mib, ETH_MIB_BAD_OCTETS_RECEIVED, "BAD_OCTETS_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_UNDERSIZE_RECEIVED, "UNDERSIZE_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_FRAGMENTS_RECEIVED, "FRAGMENTS_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_OVERSIZE_RECEIVED, "OVERSIZE_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_JABBER_RECEIVED, "JABBER_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_MAC_RECEIVE_ERROR, "MAC_RECEIVE_ERROR");
+	mvEthMibPrint(port, mib, ETH_MIB_BAD_CRC_EVENT, "BAD_CRC_EVENT");
+	mvEthRegPrint0(ETH_RX_DISCARD_PKTS_CNTR_REG(port), "RX_DISCARD_PKTS_CNTR_REG");
+	mvEthRegPrint0(ETH_RX_OVERRUN_PKTS_CNTR_REG(port), "RX_OVERRUN_PKTS_CNTR_REG");
+	mvOsPrintf("\n[Tx]\n");
+	mvEthMibPrint(port, mib, ETH_MIB_GOOD_FRAMES_SENT, "GOOD_FRAMES_SENT");
+	mvEthMibPrint(port, mib, ETH_MIB_BROADCAST_FRAMES_SENT, "BROADCAST_FRAMES_SENT");
+	mvEthMibPrint(port, mib, ETH_MIB_MULTICAST_FRAMES_SENT, "MULTICAST_FRAMES_SENT");
+	mvEthMibPrint(port, mib, ETH_MIB_GOOD_OCTETS_SENT_LOW, "GOOD_OCTETS_SENT");
+	mvOsPrintf("\n[Tx Errors]\n");
+	mvEthMibPrint(port, mib, ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR, "INTERNAL_MAC_TRANSMIT_ERR");
+	mvEthMibPrint(port, mib, ETH_MIB_EXCESSIVE_COLLISION, "EXCESSIVE_COLLISION");
+	mvEthMibPrint(port, mib, ETH_MIB_COLLISION, "COLLISION");
+	mvEthMibPrint(port, mib, ETH_MIB_LATE_COLLISION, "LATE_COLLISION");
+
+	mvOsPrintf("\n[FC control]\n");
+	mvEthMibPrint(port, mib, ETH_MIB_UNREC_MAC_CONTROL_RECEIVED, "UNREC_MAC_CONTROL_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_GOOD_FC_RECEIVED, "GOOD_FC_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_BAD_FC_RECEIVED, "BAD_FC_RECEIVED");
+	mvEthMibPrint(port, mib, ETH_MIB_FC_SENT, "FC_SENT");
+	mvOsPrintf("\n");
+}
+
+/* Print RMON counters of the Ethernet port */
+void mvEthPortRmonCounters(int port, int mib)
+{
+	void	*pHndl;
+
+	if (mvNetaTxpCheck(port, mib))
+		return;
+
+	pHndl = mvNetaPortHndlGet(port);
+	if (!pHndl)
+		return;
+
+	mvOsPrintf("\n[RMON]: port=%d, mib=%d\n", port, mib);
+
+	mvEthMibPrint(port, mib, ETH_MIB_FRAMES_64_OCTETS, "0...64");
+	mvEthMibPrint(port, mib, ETH_MIB_FRAMES_65_TO_127_OCTETS, "65...127");
+	mvEthMibPrint(port, mib, ETH_MIB_FRAMES_128_TO_255_OCTETS, "128...255");
+	mvEthMibPrint(port, mib, ETH_MIB_FRAMES_256_TO_511_OCTETS, "256...511");
+	mvEthMibPrint(port, mib, ETH_MIB_FRAMES_512_TO_1023_OCTETS, "512...1023");
+	mvEthMibPrint(port, mib, ETH_MIB_FRAMES_1024_TO_MAX_OCTETS, "1024...Max");
+}
+
+void mvEthPortUcastShow(int port)
+{
+	MV_U32 unicastReg, macL, macH;
+	int i, j;
+
+	macL = MV_REG_READ(ETH_MAC_ADDR_LOW_REG(port));
+	macH = MV_REG_READ(ETH_MAC_ADDR_HIGH_REG(port));
+
+	mvOsPrintf("Unicast MAC Table: port=%d %02x:%02x:%02x:%02x:%02x:%02x\n",
+		   port, ((macH >> 24) & 0xff), ((macH >> 16) & 0xff),
+		   ((macH >> 8) & 0xff), (macH & 0xff), ((macL >> 8) & 0xff), (macL & 0xff));
+
+	for (i = 0; i < 4; i++) {
+		unicastReg = MV_REG_READ((ETH_DA_FILTER_UCAST_BASE(port) + i * 4));
+		for (j = 0; j < 4; j++) {
+			MV_U8 macEntry = (unicastReg >> (8 * j)) & 0xFF;
+			mvOsPrintf("%X: %8s, Q = %d\n", i * 4 + j,
+				   (macEntry & BIT0) ? "accept" : "reject", (macEntry >> 1) & 0x7);
+		}
+	}
+}
+
+void mvEthPortMcastShow(int port)
+{
+	int tblIdx, regIdx;
+	MV_U32 regVal;
+
+	mvOsPrintf("Special (IP) Multicast Table port=%d: 01:00:5E:00:00:XX\n", port);
+
+	for (tblIdx = 0; tblIdx < (256 / 4); tblIdx++) {
+		regVal = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(port) + tblIdx * 4));
+		for (regIdx = 0; regIdx < 4; regIdx++) {
+			if ((regVal & (0x01 << (regIdx * 8))) != 0) {
+				mvOsPrintf("0x%02X: accepted, rxQ = %d\n",
+					   tblIdx * 4 + regIdx, ((regVal >> (regIdx * 8 + 1)) & 0x07));
+			}
+		}
+	}
+
+	mvOsPrintf("Other Multicast Table: port=%d\n", port);
+	for (tblIdx = 0; tblIdx < (256 / 4); tblIdx++) {
+		regVal = MV_REG_READ((ETH_DA_FILTER_OTH_MCAST_BASE(port) + tblIdx * 4));
+		for (regIdx = 0; regIdx < 4; regIdx++) {
+			if ((regVal & (0x01 << (regIdx * 8))) != 0) {
+				mvOsPrintf("crc8=0x%02X: accepted, rxq = %d\n",
+					   tblIdx * 4 + regIdx, ((regVal >> (regIdx * 8 + 1)) & 0x07));
+			}
+		}
+	}
+}
+
+#ifdef CONFIG_MV_ETH_HWF
+void mvNetaHwfTxpCntrs(int port, int p, int txp)
+{
+	int txq;
+	MV_U32 regVal;
+
+	if (mvNetaPortCheck(port) || mvNetaPortCheck(p))
+		return;
+
+	if (mvNetaTxpCheck(p, txp))
+		return;
+
+	mvOsPrintf("\n[HWF Counters: port=%d]\n", port);
+
+	for (txq = 0; txq < CONFIG_MV_ETH_TXQ; txq++) {
+		mvOsPrintf("\n[HWF: hwf_txp=%d, txq=%d]\n", p + txp, txq);
+
+		regVal = NETA_HWF_TX_PORT_MASK(p + txp) | NETA_HWF_TXQ_MASK(txq);
+		MV_REG_WRITE(NETA_HWF_TX_PTR_REG(port), regVal);
+
+		mvEthRegPrint(NETA_HWF_ACCEPTED_CNTR(port), "NETA_HWF_ACCEPTED_CNTR");
+		mvEthRegPrint(NETA_HWF_YELLOW_DROP_CNTR(port), "NETA_HWF_YELLOW_DROP_CNTR");
+		mvEthRegPrint(NETA_HWF_GREEN_DROP_CNTR(port), "NETA_HWF_GREEN_DROP_CNTR");
+		mvEthRegPrint(NETA_HWF_THRESH_DROP_CNTR(port), "NETA_HWF_THRESH_DROP_CNTR");
+	}
+}
+
+void mvNetaHwfRxpRegs(int port)
+{
+	int txpNum, txp;
+
+	if (mvNetaPortCheck(port))
+		return;
+
+	mvOsPrintf("\n[HWF Config: port=%d]\n", port);
+	mvEthRegPrint(NETA_HWF_RX_CTRL_REG(port), "NETA_HWF_RX_CTRL_REG");
+	mvEthRegPrint(NETA_HWF_RX_THRESH_REG(port), "NETA_HWF_RX_THRESH_REG");
+
+	/* Calculate total number of txp */
+	txpNum = 2;
+
+#ifdef CONFIG_MV_PON
+	txpNum += MV_ETH_MAX_TCONT();
+#endif /* CONFIG_MV_PON */
+
+	for (txp = 0; txp < txpNum; txp += 2)
+		mvEthRegPrint2(NETA_HWF_TXP_CFG_REG(port, txp), "NETA_HWF_TXP_CFG_REG", txp);
+}
+
+void mvNetaHwfTxpRegs(int port, int p, int txp)
+{
+	int txq;
+	MV_U32 regVal;
+
+	if (mvNetaPortCheck(port) || mvNetaPortCheck(p))
+		return;
+
+	if (mvNetaTxpCheck(p, txp))
+		return;
+
+	for (txq = 0; txq < CONFIG_MV_ETH_TXQ; txq++) {
+		mvOsPrintf("\n[HWF: hwf_txp=%d, txq=%d]\n", p + txp, txq);
+		regVal = NETA_HWF_TX_PORT_MASK(p + txp) | NETA_HWF_TXQ_MASK(txq);
+		MV_REG_WRITE(NETA_HWF_TX_PTR_REG(port), regVal);
+
+		mvEthRegPrint(NETA_HWF_DROP_TH_REG(port), "NETA_HWF_DROP_TH_REG");
+		mvEthRegPrint(NETA_HWF_TXQ_BASE_REG(port), "NETA_HWF_TXQ_BASE_REG");
+		mvEthRegPrint(NETA_HWF_TXQ_SIZE_REG(port), "NETA_HWF_TXQ_SIZE_REG");
+		mvEthRegPrint(NETA_HWF_TXQ_ENABLE_REG(port), "NETA_HWF_TXQ_ENABLE_REG");
+	}
+}
+#endif /* CONFIG_MV_ETH_HWF */
+
+void mvNetaRxqCpuDump(int port, int cpu)
+{
+	MV_U32 regVal = MV_REG_READ(NETA_CPU_MAP_REG(port, cpu));
+	int j;
+	for (j = 0; j < CONFIG_MV_ETH_RXQ; j++) {
+		if (regVal & 1)
+			mvOsPrintf("RXQ-%d ", j);
+		else
+			mvOsPrintf("       ");
+	regVal >>= 1;
+	}
+	mvOsPrintf("\n");
+}
+
+#ifdef CONFIG_MV_PON
+void mvNetaPonTxpRegs(int port, int txp)
+{
+	int txq;
+
+	if (mvNetaTxpCheck(port, txp))
+		return;
+
+	mvOsPrintf("\n[NetA PON TXQ Bytes registers: port=%d, txp=%d]\n", port, txp);
+	for (txq = 0; txq < MV_ETH_MAX_TXQ; txq++)
+		mvEthRegPrint2(NETA_TXQ_NEW_BYTES_REG(port, txp, txq), "NETA_TXQ_NEW_BYTES_REG", txq);
+}
+#endif /* CONFIG_MV_PON */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaRegs.h b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaRegs.h
new file mode 100755
index 0000000..7b0d73b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/gbe/mvNetaRegs.h
@@ -0,0 +1,1234 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __mvNetaRegs_h__
+#define __mvNetaRegs_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "mvSysEthConfig.h"
+
+#define NETA_REG_BASE(port) 				MV_ETH_REGS_BASE(port)
+
+
+/************************** NETA TX Registers ******************************/
+
+#ifdef CONFIG_MV_PON
+#define NETA_TX_REG_BASE(p, txp)  	(MV_PON_PORT(p) ? \
+					(MV_PON_REG_BASE + 0x4000 + ((txp) >> 1) * 0x2000 + ((txp) & 0x1) * 0x400) :  \
+					(NETA_REG_BASE(p) + 0x2400))
+#else
+#define NETA_TX_REG_BASE(p, txp)   	(NETA_REG_BASE(p) + 0x2400)
+#endif /* CONFIG_MV_PON */
+
+/************************** NETA RX Registers ******************************/
+
+/* PxRXyC: Port RX queues Configuration Register */
+#define NETA_RXQ_CONFIG_REG(p, q)        	(NETA_REG_BASE(p) + 0x1400 + ((q) << 2))
+
+#define NETA_RXQ_HW_BUF_ALLOC_BIT           0
+#define NETA_RXQ_HW_BUF_ALLOC_MASK          (1 << NETA_RXQ_HW_BUF_ALLOC_BIT)
+
+#define NETA_RXQ_SHORT_POOL_ID_OFFS         4
+#define NETA_RXQ_SHORT_POOL_ID_MASK         (0x3 << NETA_RXQ_SHORT_POOL_ID_OFFS)
+
+#define NETA_RXQ_LONG_POOL_ID_OFFS          6
+#define NETA_RXQ_LONG_POOL_ID_MASK          (0x3 << NETA_RXQ_LONG_POOL_ID_OFFS)
+
+#define NETA_RXQ_PACKET_OFFSET_OFFS         8
+#define NETA_RXQ_PACKET_OFFSET_ALL_MASK     (0xF << NETA_RXQ_PACKET_OFFSET_OFFS)
+#define NETA_RXQ_PACKET_OFFSET_MASK(offs)   ((offs) << NETA_RXQ_PACKET_OFFSET_OFFS)
+
+
+#define NETA_RXQ_INTR_ENABLE_BIT            15
+#define NETA_RXQ_INTR_ENABLE_MASK           (0x1 << NETA_RXQ_INTR_ENABLE_BIT)
+
+/* ????? What about PREFETCH commands 1, 2, 3 */
+#define NETA_RXQ_PREFETCH_MODE_BIT          16
+#define NETA_RXQ_PREFETCH_PNC               (0 << NETA_RXQ_PREFETCH_MODE_BIT)
+#define NETA_RXQ_PREFETCH_CMD_0             (1 << NETA_RXQ_PREFETCH_MODE_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_RXQ_SNOOP_REG(p, q)            (NETA_REG_BASE(p) + 0x1420 + ((q) << 2))
+
+#define NETA_RXQ_SNOOP_BYTES_OFFS           0
+#define NETA_RXQ_SNOOP_BYTES_MASK           (0x3FFF << NETA_RXQ_SNOOP_BYTES_OFFS)
+
+#define NETA_RXQ_L2_DEPOSIT_BYTES_OFFS      16
+#define NETA_RXQ_L2_DEPOSIT_BYTES_MASK      (0x3FFF << NETA_RXQ_L2_DEPOSIT_BYTES_OFFS)
+
+
+#define NETA_RXQ_PREFETCH_01_REG(p, q)      (NETA_REG_BASE(p) + 0x1440 + ((q) << 2))
+#define NETA_RXQ_PREFETCH_23_REG(p, q)      (NETA_REG_BASE(p) + 0x1460 + ((q) << 2))
+
+#define NETA_RXQ_PREFETCH_CMD_OFFS(cmd)     (((cmd) & 1) ? 16 : 0)
+#define NETA_RXQ_PREFETCH_CMD_MASK(cmd)     (0xFFFF << NETA_RXQ_PREFETCH_CMD_OFFS(cmd))
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_RXQ_BASE_ADDR_REG(p, q)        (NETA_REG_BASE(p) + 0x1480 + ((q) << 2))
+#define NETA_RXQ_SIZE_REG(p, q)             (NETA_REG_BASE(p) + 0x14A0 + ((q) << 2))
+
+#define NETA_RXQ_DESC_NUM_OFFS              0
+#define NETA_RXQ_DESC_NUM_MASK              (0x3FFF << NETA_RXQ_DESC_NUM_OFFS)
+
+#define NETA_RXQ_BUF_SIZE_OFFS              19
+#define NETA_RXQ_BUF_SIZE_MASK              (0x1FFF << NETA_RXQ_BUF_SIZE_OFFS)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_RXQ_THRESHOLD_REG(p, q)        (NETA_REG_BASE(p) + 0x14C0 + ((q) << 2))
+#define NETA_RXQ_STATUS_REG(p, q)           (NETA_REG_BASE(p) + 0x14E0 + ((q) << 2))
+
+#define NETA_RXQ_OCCUPIED_DESC_OFFS         0
+#define NETA_RXQ_OCCUPIED_DESC_ALL_MASK     (0x3FFF << NETA_RXQ_OCCUPIED_DESC_OFFS)
+#define NETA_RXQ_OCCUPIED_DESC_MASK(val)    ((val) << NETA_RXQ_OCCUPIED_DESC_OFFS)
+
+#define NETA_RXQ_NON_OCCUPIED_DESC_OFFS     16
+#define NETA_RXQ_NON_OCCUPIED_DESC_ALL_MASK (0x3FFF << NETA_RXQ_NON_OCCUPIED_DESC_OFFS)
+#define NETA_RXQ_NON_OCCUPIED_DESC_MASK(v)  ((v) << NETA_RXQ_NON_OCCUPIED_DESC_OFFS)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_RXQ_STATUS_UPDATE_REG(p, q)    (NETA_REG_BASE(p) + 0x1500 + ((q) << 2))
+
+/* Decrement OCCUPIED Descriptors counter */
+#define NETA_RXQ_DEC_OCCUPIED_OFFS          0
+#define NETA_RXQ_DEC_OCCUPIED_MASK          (0xFF << NETA_RXQ_DEC_OCCUPIED_OFFS)
+
+/* Increment NON_OCCUPIED Descriptors counter */
+#define NETA_RXQ_ADD_NON_OCCUPIED_OFFS      16
+#define NETA_RXQ_ADD_NON_OCCUPIED_MASK      (0xFF << NETA_RXQ_ADD_NON_OCCUPIED_OFFS)
+/*-------------------------------------------------------------------------------*/
+
+/* Port RX queues Descriptors Index Register (a register per RX Queue) */
+#define NETA_RXQ_INDEX_REG(p, q)            (NETA_REG_BASE(p) + 0x1520 + ((q) << 2))
+
+#define NETA_RXQ_NEXT_DESC_INDEX_OFFS       0
+#define NETA_RXQ_NEXT_DESC_INDEX_MASK       (0x3FFF << NETA_RXQ_NEXT_DESC_INDEX_OFFS)
+/*-------------------------------------------------------------------------------*/
+
+/* Port Pool-N Buffer Size Register - 8 bytes alignment */
+#define NETA_POOL_BUF_SIZE_REG(p, pool)     (NETA_REG_BASE(p) + 0x1700 + ((pool) << 2))
+#define NETA_POOL_BUF_SIZE_ALIGN            8
+#define NETA_POOL_BUF_SIZE_OFFS             3
+#define NETA_POOL_BUF_SIZE_MASK             (0x1FFF << NETA_POOL_BUF_SIZE_OFFS)
+/*-------------------------------------------------------------------------------*/
+
+/* Port RX Flow Control register */
+#define NETA_FLOW_CONTROL_REG(p)            (NETA_REG_BASE(p) + 0x1710)
+
+#define NETA_PRIO_PAUSE_PKT_GEN_BIT         0
+#define NETA_PRIO_PAUSE_PKT_GEN_GIGA        (0 << NETA_PRIO_PAUSE_PKT_GEN_BIT)
+#define NETA_PRIO_PAUSE_PKT_GEN_CPU         (1 << NETA_PRIO_PAUSE_PKT_GEN_BIT)
+
+#define NETA_PRIO_TX_PAUSE_BIT              1
+#define NETA_PRIO_TX_PAUSE_GIGA             (0 << NETA_PRIO_TX_PAUSE_BIT)
+#define NETA_PRIO_TX_PAUSE_CPU              (1 << NETA_PRIO_TX_PAUSE_BIT)
+/*-------------------------------------------------------------------------------*/
+
+/* Port TX pause control register */
+#define NETA_TX_PAUSE_REG(p)                (NETA_REG_BASE(p) + 0x1714)
+
+/* ????? One register for all TXQs - problem for multi-core */
+#define NETA_TXQ_PAUSE_ENABLE_OFFS          0
+#define NETA_TXQ_PAUSE_ENABLE_ALL_MASK      (0xFF << NETA_TXQ_PAUSE_ENABLE_OFFS)
+#define NETA_TXQ_PAUSE_ENABLE_MASK(q)       ((1 << q) << NETA_TXQ_PAUSE_ENABLE_OFFS)
+/*-------------------------------------------------------------------------------*/
+
+/* Port Flow Control generation control register */
+#define NETA_FC_GEN_REG(p)                  (NETA_REG_BASE(p) + 0x1718)
+
+#define NETA_PAUSE_PKT_GEN_DATA_BIT         0
+#define NETA_PAUSE_PKT_GEN_DATA_OFF         (0 << NETA_PAUSE_PKT_GEN_DATA_BIT)
+#define NETA_PAUSE_PKT_GEN_DATA_ON          (1 << NETA_PAUSE_PKT_GEN_DATA_BIT)
+
+#define NETA_TXQ_PAUSE_PKT_GEN_OFFS         4
+#define NETA_TXQ_PAUSE_PKT_GEN_ALL_MASK     (0x7 << NETA_TXQ_PAUSE_PKT_GEN_OFFS)
+#define NETA_TXQ_PAUSE_PKT_GEN_MASK(q)      ((1 << q) << NETA_TXQ_PAUSE_PKT_GEN_OFFS)
+
+#define NETA_RX_DEBUG_REG(p)                (NETA_REG_BASE(p) + 0x17f0)
+/* RXQ memory dump: offset = 1c00 - 1cbc */
+
+/* PxRXINIT: Port RX Initialization Register */
+#define NETA_PORT_RX_RESET_REG(p)           (NETA_REG_BASE(p) + 0x1cc0)
+
+#define NETA_PORT_RX_DMA_RESET_BIT          0
+#define NETA_PORT_RX_DMA_RESET_MASK         (1 << NETA_PORT_RX_DMA_RESET_BIT)
+/*-------------------------------------------------------------------------------*/
+
+
+#define NETA_HWF_RX_CTRL_REG(p)             (NETA_REG_BASE(p) + 0x1d00)
+
+#define NETA_COLOR_SRC_SEL_BIT				0
+#define NETA_COLOR_SRC_SEL_MASK				(1 << NETA_COLOR_SRC_SEL_BIT)
+
+#define NETA_GEM_PID_SRC_SEL_OFFS           4
+#define NETA_GEM_PID_SRC_SEL_MASK           (7 << NETA_GEM_PID_SRC_SEL_OFFS)
+#define NETA_GEM_PID_SRC_GPON_HDR           (0 << NETA_GEM_PID_SRC_SEL_OFFS)
+#define NETA_GEM_PID_SRC_EXT_DSA_TAG        (1 << NETA_GEM_PID_SRC_SEL_OFFS)
+#define NETA_GEM_PID_SRC_FLOW_ID            (2 << NETA_GEM_PID_SRC_SEL_OFFS)
+#define NETA_GEM_PID_SRC_DSA_TAG            (3 << NETA_GEM_PID_SRC_SEL_OFFS)
+#define NETA_GEM_PID_SRC_ZERO               (4 << NETA_GEM_PID_SRC_SEL_OFFS)
+
+#define NETA_TXQ_SRC_SEL_BIT                8
+#define NETA_TXQ_SRC_SEL_MASK               (1 << NETA_TXQ_SRC_SEL_BIT)
+#define NETA_TXQ_SRC_FLOW_ID                (0 << NETA_TXQ_SRC_SEL_BIT)
+#define NETA_TXQ_SRC_RES_INFO               (1 << NETA_TXQ_SRC_SEL_BIT)
+
+#ifdef MV_ETH_PMT_NEW
+
+#define NETA_MH_SEL_OFFS                    12
+#define NETA_MH_SEL_MASK                    (0xF << NETA_MH_SEL_OFFS)
+#define NETA_MH_DONT_CHANGE                 (0)
+#define NETA_MH_REPLACE_GPON_HDR            (1)
+#define NETA_MH_REPLACE_MH_REG(r)           (r + 1)
+
+#define NETA_MH_SRC_PNC_BIT                 16
+#define NETA_MH_SRC_PNC_MASK                (1 << NETA_MH_SRC_PNC_BIT)
+
+#define NETA_HWF_ENABLE_BIT                 17
+#define NETA_HWF_ENABLE_MASK                (1 << NETA_HWF_ENABLE_BIT)
+
+#else
+
+#define NETA_MH_SEL_OFFS                    12
+#define NETA_MH_SEL_MASK                    (0x7 << NETA_MH_SEL_OFFS)
+#define NETA_MH_DONT_CHANGE                 (0)
+#define NETA_MH_REPLACE_GPON_HDR            (1)
+#define NETA_MH_REPLACE_MH_REG(r)           (r + 1)
+
+#define NETA_MH_SRC_PNC_BIT                 15
+#define NETA_MH_SRC_PNC_MASK                (1 << NETA_MH_SRC_PNC_BIT)
+
+#define NETA_HWF_ENABLE_BIT                 16
+#define NETA_HWF_ENABLE_MASK                (1 << NETA_HWF_ENABLE_BIT)
+
+#endif /* MV_ETH_PMT_NEW */
+
+#define NETA_HWF_SHORT_POOL_OFFS            20
+#define NETA_HWF_SHORT_POOL_MASK            (3 << NETA_HWF_SHORT_POOL_OFFS)
+#define NETA_HWF_SHORT_POOL_ID(pool)        ((pool) << NETA_HWF_SHORT_POOL_OFFS)
+
+#define NETA_HWF_LONG_POOL_OFFS             22
+#define NETA_HWF_LONG_POOL_MASK             (3 << NETA_HWF_LONG_POOL_OFFS)
+#define NETA_HWF_LONG_POOL_ID(pool)         ((pool) << NETA_HWF_LONG_POOL_OFFS)
+/*-----------------------------------------------------------------------------------*/
+
+#define NETA_HWF_RX_THRESH_REG(p)           (NETA_REG_BASE(p) + 0x1d04)
+
+#ifdef MV_ETH_PMT_NEW
+
+#define NETA_HWF_RX_FIFO_WORDS_OFFS         0
+#define NETA_HWF_RX_FIFO_WORDS_MASK         (0x3FF << NETA_HWF_RX_FIFO_WORDS_OFFS)
+
+#define NETA_HWF_RX_FIFO_PKTS_OFFS          16
+#define NETA_HWF_RX_FIFO_PKTS_MASK          (0x7F << NETA_HWF_RX_FIFO_PKTS_OFFS)
+
+#else
+
+#define NETA_HWF_RX_FIFO_WORDS_OFFS         0
+#define NETA_HWF_RX_FIFO_WORDS_MASK         (0xFF << NETA_HWF_RX_FIFO_WORDS_OFFS)
+
+#define NETA_HWF_RX_FIFO_PKTS_OFFS          8
+#define NETA_HWF_RX_FIFO_PKTS_MASK          (0x1F << NETA_HWF_RX_FIFO_PKTS_OFFS)
+
+#endif /* MV_ETH_PMT_NEW */
+/*-----------------------------------------------------------------------------------*/
+
+
+#define NETA_HWF_TXP_CFG_REG(p, txp)        (NETA_REG_BASE(p) + 0x1d10 + ((txp) >> 1) * 4)
+
+#define NETA_TXP_BASE_ADDR_OFFS(txp)        (((txp) & 0x1) ? 18 : 2)
+#define NETA_TXP_BASE_ADDR_MASK(txp)        (0xFFFF << NETA_TXP_BASE_ADDR_OFFS(txp))
+/*-----------------------------------------------------------------------------------*/
+
+#define NETA_HWF_TX_PTR_REG(p)              (NETA_REG_BASE(p) + 0x1d30)
+
+#define NETA_HWF_TX_PORT_OFFS               11
+#define NETA_HWF_TX_PORT_ALL_MASK           (0xF << NETA_HWF_TX_PORT_OFFS)
+#define NETA_HWF_TX_PORT_MASK(txp)          ((txp) << NETA_HWF_TX_PORT_OFFS)
+
+#define NETA_HWF_TXQ_OFFS                   8
+#define NETA_HWF_TXQ_ALL_MASK               (0x7 << NETA_HWF_TXQ_OFFS)
+#define NETA_HWF_TXQ_MASK(txq)              ((txq) << NETA_HWF_TXQ_OFFS)
+/*-----------------------------------------------------------------------------------*/
+
+#define NETA_HWF_DROP_TH_REG(p)             (NETA_REG_BASE(p) + 0x1d40)
+
+#define NETA_YELLOW_DROP_THRESH_OFFS        0
+#define NETA_YELLOW_DROP_THRESH_MASK        (0x3fff << NETA_YELLOW_DROP_THRESH_OFFS)
+
+#define NETA_YELLOW_DROP_RND_GEN_OFFS       16
+#define NETA_YELLOW_DROP_RND_GEN_MASK       (0xf << NETA_YELLOW_DROP_RND_GEN_OFFS)
+/*-----------------------------------------------------------------------------------*/
+
+#define NETA_HWF_TXQ_BASE_REG(p)            (NETA_REG_BASE(p) + 0x1d44)
+/*-----------------------------------------------------------------------------------*/
+
+#define NETA_HWF_TXQ_SIZE_REG(p)            (NETA_REG_BASE(p) + 0x1d48)
+
+#define NETA_HWF_TXQ_SIZE_OFFS              0
+#define NETA_HWF_TXQ_SIZE_MASK              (0x3fff << NETA_HWF_TXQ_SIZE_OFFS)
+/*-----------------------------------------------------------------------------------*/
+
+#define NETA_HWF_TXQ_ENABLE_REG(p)          (NETA_REG_BASE(p) + 0x1d4c)
+
+#define NETA_HWF_TXQ_ENABLE_BIT             0
+#define NETA_HWF_TXQ_ENABLE_MASK            (1 << NETA_HWF_TXQ_ENABLE_BIT)
+/*-----------------------------------------------------------------------------------*/
+
+#define NETA_HWF_ACCEPTED_CNTR(p)           (NETA_REG_BASE(p) + 0x1d50)
+#define NETA_HWF_YELLOW_DROP_CNTR(p)        (NETA_REG_BASE(p) + 0x1d54)
+#define NETA_HWF_GREEN_DROP_CNTR(p)         (NETA_REG_BASE(p) + 0x1d58)
+#define NETA_HWF_THRESH_DROP_CNTR(p)        (NETA_REG_BASE(p) + 0x1d5c)
+
+#define NETA_HWF_MEMORY_REG(p)				(NETA_REG_BASE(p) + 0x1d60)
+
+/* Hardware Forwarding TX access gap register */
+#define NETA_HWF_TX_GAP_REG(p)				(NETA_REG_BASE(p) + 0x1d6C)
+
+#define NETA_HWF_SMALL_TX_GAP_BIT			0
+#define NETA_HWF_SMALL_TX_GAP_MASK			(1 << NETA_HWF_SMALL_TX_GAP_BIT)
+/*-----------------------------------------------------------------------------------*/
+
+
+
+/**************************** NETA General Registers ***********************/
+
+/* Cross Bar registers per Giga Unit */
+#define NETA_MBUS_RETRY_REG(p)              (NETA_REG_BASE((p) & ~0x1) + 0x2010)
+
+#define NETA_MBUS_RETRY_DISABLE_BIT			16
+#define NETA_MBUS_RETRY_DISABLE_MASK		(1 << NETA_MBUS_RETRY_DISABLE_BIT)
+
+#define NETA_MBUS_RETRY_CYCLES_OFFS			0
+#define NETA_MBUS_RETRY_CYCLES_MASK			(0xFF << NETA_MBUS_RETRY_CYCLES_OFFS)
+#define NETA_MBUS_RETRY_CYCLES(val)			((val) << NETA_MBUS_RETRY_CYCLES_OFFS)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_MBUS_ARBITER_REG(p)            (NETA_REG_BASE((p) & ~0x1) + 0x20C0)
+/*-------------------------------------------------------------------------------*/
+
+/* PACC - Port Acceleration Register */
+#define NETA_ACC_MODE_REG(p)                (NETA_REG_BASE(p) + 0x2500)
+
+#define NETA_ACC_MODE_OFFS                  0
+#define NETA_ACC_MODE_ALL_MASK              (7 << NETA_ACC_MODE_OFFS)
+#define NETA_ACC_MODE_MASK(mode)            ((mode) << NETA_ACC_MODE_OFFS)
+#define NETA_ACC_MODE_LEGACY                0
+#define NETA_ACC_MODE_EXT                   1
+#define NETA_ACC_MODE_EXT_BMU               2
+#define NETA_ACC_MODE_EXT_PNC               3
+#define NETA_ACC_MODE_EXT_PNC_BMU           4
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_BM_ADDR_REG(p)                 (NETA_REG_BASE(p) + 0x2504)
+
+#define NETA_CPU_MAP_REG(p, cpu)            (NETA_REG_BASE(p) + 0x2540 + ((cpu) << 2))
+
+#define NETA_CPU_RXQ_ACCESS_OFFS            0
+#define NETA_CPU_RXQ_ACCESS_ALL_MASK        (0xFF << NETA_CPU_RXQ_ACCESS_OFFS)
+#define NETA_CPU_RXQ_ACCESS_MASK(q)         (1 << (NETA_CPU_RXQ_ACCESS_OFFS + (q)))
+
+#define NETA_CPU_TXQ_ACCESS_OFFS            8
+#define NETA_CPU_TXQ_ACCESS_ALL_MASK        (0xFF << NETA_CPU_TXQ_ACCESS_OFFS)
+#define NETA_CPU_TXQ_ACCESS_MASK(q)         (1 << (NETA_CPU_TXQ_ACCESS_OFFS + (q)))
+
+/* Interrupt coalescing mechanism */
+#define NETA_RXQ_INTR_TIME_COAL_REG(p, q)   (NETA_REG_BASE(p) + 0x2580 + ((q) << 2))
+
+/* Exception Interrupt Port/Queue Cause register */
+#define NETA_INTR_NEW_CAUSE_REG(p)          (NETA_REG_BASE(p) + 0x25A0)
+#define NETA_INTR_NEW_MASK_REG(p)           (NETA_REG_BASE(p) + 0x25A4)
+
+#ifdef CONFIG_MV_PON
+#   define GPON_CAUSE_TXQ_SENT_SUM_OFFS     0
+#   define GPON_CAUSE_TXQ_SENT_SUM_MASK     (3 << GPON_CAUSE_TXQ_SENT_SUM_OFFS)
+#endif /* CONFIG_MV_PON */
+
+#define NETA_CAUSE_TXQ_SENT_DESC_OFFS       0
+#define NETA_CAUSE_TXQ_SENT_DESC_BIT(q)     (NETA_CAUSE_TXQ_SENT_DESC_OFFS + (q))
+#define NETA_CAUSE_TXQ_SENT_DESC_ALL_MASK   (0xFF << NETA_CAUSE_TXQ_SENT_DESC_OFFS)
+#define NETA_CAUSE_TXQ_SENT_DESC_MASK(q)    (1 << (NETA_CAUSE_TXQ_SENT_DESC_BIT(q)))
+
+#define NETA_CAUSE_RXQ_OCCUP_DESC_OFFS      8
+#define NETA_CAUSE_RXQ_OCCUP_DESC_BIT(q)    (NETA_CAUSE_RXQ_OCCUP_DESC_OFFS + (q))
+#define NETA_CAUSE_RXQ_OCCUP_DESC_ALL_MASK  (0xFF << NETA_CAUSE_RXQ_OCCUP_DESC_OFFS)
+#define NETA_CAUSE_RXQ_OCCUP_DESC_MASK(q)   (1 << (NETA_CAUSE_RXQ_OCCUP_DESC_BIT(q)))
+
+#define NETA_CAUSE_RXQ_FREE_DESC_OFFS       16
+#define NETA_CAUSE_RXQ_FREE_DESC_BIT(q)     (NETA_CAUSE_RXQ_FREE_DESC_OFFS + (q))
+#define NETA_CAUSE_RXQ_FREE_DESC_MASK(q)    (1 << (NETA_CAUSE_RXQ_FREE_DESC_BIT(q)))
+
+#define NETA_CAUSE_OLD_REG_SUM_BIT          29
+#define NETA_CAUSE_OLD_REG_SUM_MASK         (1 << NETA_CAUSE_OLD_REG_SUM_BIT)
+
+#define NETA_CAUSE_TX_ERR_SUM_BIT           30
+#define NETA_CAUSE_TX_ERR_SUM_MASK          (1 << NETA_CAUSE_TX_ERR_SUM_BIT)
+
+#define NETA_CAUSE_MISC_SUM_BIT             31
+#define NETA_CAUSE_MISC_SUM_MASK            (1 << NETA_CAUSE_MISC_SUM_BIT)
+
+#define NETA_CAUSE_TXQ_SENT_DESC_TXP_SUM    4 /* How many Tx ports are summarized by each bit */
+/*-------------------------------------------------------------------------------*/
+
+/* Data Path Port/Queue Cause Register */
+#define NETA_INTR_OLD_CAUSE_REG(p)          (NETA_REG_BASE(p) + 0x25A8)
+#define NETA_INTR_OLD_MASK_REG(p)           (NETA_REG_BASE(p) + 0x25AC)
+
+#ifdef CONFIG_MV_PON
+#   define GPON_CAUSE_TXQ_BUF_OFFS          0
+#   define GPON_CAUSE_TXQ_BUF_MASK          (3 << GPON_CAUSE_TXQ_BUF_OFFS)
+#endif /* CONFIG_MV_PON */
+
+#define NETA_CAUSE_TXQ_BUF_OFFS             0
+#define NETA_CAUSE_TXQ_BUF_BIT(q)           (NETA_CAUSE_TXQ_BUF_OFFS + (q))
+#define NETA_CAUSE_TXQ_BUF_ALL_MASK         (0xFF << NETA_CAUSE_TXQ_BUF_OFFS)
+#define NETA_CAUSE_TXQ_BUF_MASK(q)          (1 << (NETA_CAUSE_TXQ_BUF_BIT(q)))
+
+#define NETA_CAUSE_RXQ_PKT_OFFS             8
+#define NETA_CAUSE_RXQ_PKT_BIT(q)           (NETA_CAUSE_RXQ_PKT_OFFS + (q))
+#define NETA_CAUSE_RXQ_PKT_ALL_MASK         (0xFF << NETA_CAUSE_RXQ_PKT_OFFS)
+#define NETA_CAUSE_RXQ_PKT_MASK(q)          (1 << (NETA_CAUSE_RXQ_PKT_BIT(q)))
+
+#define NETA_CAUSE_RXQ_ERROR_OFFS           16
+#define NETA_CAUSE_RXQ_ERROR_BIT(q)         (NETA_CAUSE_RXQ_ERROR_OFFS + (q))
+#define NETA_CAUSE_RXQ_ERROR_ALL_MASK       (0xFF << NETA_CAUSE_RXQ_ERROR_OFFS)
+#define NETA_CAUSE_RXQ_ERROR_MASK(q)        (1 << (NETA_CAUSE_RXQ_ERROR_BIT(q)))
+
+#define NETA_CAUSE_NEW_REG_SUM_BIT          29
+#define NETA_CAUSE_NEW_REG_SUM_MASK         (1 << NETA_CAUSE_NEW_REG_SUM_BIT)
+/*-------------------------------------------------------------------------------*/
+
+/* Misc Port Cause Register */
+#define NETA_INTR_MISC_CAUSE_REG(p)         (NETA_REG_BASE(p) + 0x25B0)
+#define NETA_INTR_MISC_MASK_REG(p)          (NETA_REG_BASE(p) + 0x25B4)
+
+#define NETA_CAUSE_PHY_STATUS_CHANGE_BIT    0
+#define NETA_CAUSE_PHY_STATUS_CHANGE_MASK   (1 << NETA_CAUSE_PHY_STATUS_CHANGE_BIT)
+
+#define NETA_CAUSE_LINK_CHANGE_BIT          1
+#define NETA_CAUSE_LINK_CHANGE_MASK         (1 << NETA_CAUSE_LINK_CHANGE_BIT)
+
+#define NETA_CAUSE_PTP_BIT                  4
+
+#define NETA_CAUSE_INTERNAL_ADDR_ERR_BIT    7
+#define NETA_CAUSE_RX_OVERRUN_BIT           8
+#define NETA_CAUSE_RX_CRC_ERROR_BIT         9
+#define NETA_CAUSE_RX_LARGE_PKT_BIT         10
+#define NETA_CAUSE_TX_UNDERUN_BIT           11
+#define NETA_CAUSE_PRBS_ERR_BIT             12
+#define NETA_CAUSE_PSC_SYNC_CHANGE_BIT      13
+#define NETA_CAUSE_SERDES_SYNC_ERR_BIT      14
+
+#define NETA_CAUSE_BMU_ALLOC_ERR_OFFS       16
+#define NETA_CAUSE_BMU_ALLOC_ERR_ALL_MASK   (0xF << NETA_CAUSE_BMU_ALLOC_ERR_OFFS)
+#define NETA_CAUSE_BMU_ALLOC_ERR_MASK(pool) (1 << (NETA_CAUSE_BMU_ALLOC_ERR_OFFS + (pool)))
+
+#define NETA_CAUSE_TXQ_ERROR_OFFS           24
+#define NETA_CAUSE_TXQ_ERROR_BIT(q)         (NETA_CAUSE_TXQ_ERROR_OFFS + (q))
+#define NETA_CAUSE_TXQ_ERROR_ALL_MASK       (0xFF << NETA_CAUSE_TXQ_ERROR_OFFS)
+#define NETA_CAUSE_TXQ_ERROR_MASK(q)        (1 << (NETA_CAUSE_TXQ_ERROR_BIT(q)))
+
+#ifdef CONFIG_MV_PON
+#   define GPON_CAUSE_TXQ_ERROR_OFFS        24
+#   define GPON_CAUSE_TXQ_ERROR_MASK        (0x3 << GPON_CAUSE_TXQ_ERROR_OFFS)
+#endif /* CONFIG_MV_PON */
+/*-------------------------------------------------------------------------------*/
+
+/* one register for all queues - problem for Multi-Core */
+#define NETA_INTR_ENABLE_REG(p)             (NETA_REG_BASE(p) + 0x25B8)
+
+#define NETA_RXQ_PKT_INTR_ENABLE_OFFS       0
+#define NETA_RXQ_PKT_INTR_ENABLE_ALL_MASK   (0xFF << NETA_RXQ_PKT_INTR_ENABLE_OFFS)
+#define NETA_RXQ_PKT_INTR_ENABLE_MASK(q)    ((1 << NETA_RXQ_PKT_INTR_ENABLE_OFFS + (q))
+
+#define NETA_TXQ_PKT_INTR_ENABLE_OFFS       8
+#define NETA_TXQ_PKT_INTR_ENABLE_ALL_MASK   (0xFF << NETA_TXQ_PKT_INTR_ENABLE_OFFS)
+#define NETA_TXQ_PKT_INTR_ENABLE_MASK(q)    ((1 << NETA_TXQ_PKT_INTR_ENABLE_OFFS + (q))
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_VERSION_REG(p)                 (NETA_REG_BASE(p) + 0x25BC)
+
+#define NETA_VERSION_OFFS                   0
+#define NETA_VERSION_MASK                   (0xFF << NETA_VERSION_OFFS)
+
+#define NETA_LEGACY_DBA_REG(p)              (NETA_REG_BASE(p) + 0x25F0)
+
+#define NETA_LEGACY_DBA_OFFS                0
+#define NETA_LEGACY_DBA_MASK                (0x1 << NETA_LEGACY_DBA_OFFS)
+
+/* Serdes registres: 0x72E00-0x72FFC */
+
+#ifdef CONFIG_MV_PON
+/* Extra registers for GPON port only */
+#   define GPON_TXQ_INTR_ENABLE_REG(txq)    (MV_PON_REG_BASE + 0x0480 +  (txq / 32) * 4)
+#   define GPON_TXQ_INTR_NEW_CAUSE_REG(txq) (MV_PON_REG_BASE + 0x0500 +  (txq / 32) * 8)
+#   define GPON_TXQ_INTR_NEW_MASK_REG(txq)  (MV_PON_REG_BASE + 0x0504 +  (txq / 32) * 8)
+#   define GPON_TXQ_INTR_OLD_CAUSE_REG(txq) (MV_PON_REG_BASE + 0x0540 +  (txq / 32) * 8)
+#   define GPON_TXQ_INTR_OLD_MASK_REG(txq)  (MV_PON_REG_BASE + 0x0544 +  (txq / 32) * 8)
+#   define GPON_TXQ_INTR_ERR_CAUSE_REG(txq) (MV_PON_REG_BASE + 0x0580 +  (txq / 32) * 8)
+#   define GPON_TXQ_INTR_ERR_MASK_REG(txq)  (MV_PON_REG_BASE + 0x0584 +  (txq / 32) * 8)
+#endif /* CONFIG_MV_PON */
+/*-------------------------------------------------------------------------------*/
+
+#ifdef MV_ETH_GMAC_NEW
+
+/******* New GigE MAC registers *******/
+#define NETA_GMAC_CTRL_0_REG(p)             (NETA_REG_BASE(p) + 0x2C00)
+
+#define NETA_GMAC_PORT_EN_BIT               0
+#define NETA_GMAC_PORT_EN_MASK              (1 << NETA_GMAC_PORT_EN_BIT)
+
+#define NETA_GMAC_PORT_TYPE_BIT             1
+#define NETA_GMAC_PORT_TYPE_MASK            (1 << NETA_GMAC_PORT_TYPE_BIT)
+#define NETA_GMAC_PORT_TYPE_SGMII           (0 << NETA_GMAC_PORT_TYPE_BIT)
+#define NETA_GMAC_PORT_TYPE_1000X           (1 << NETA_GMAC_PORT_TYPE_BIT)
+
+#define NETA_GMAC_MAX_RX_SIZE_OFFS          2
+#define NETA_GMAC_MAX_RX_SIZE_MASK          (0x1FFF << NETA_GMAC_MAX_RX_SIZE_OFFS)
+
+#define NETA_GMAC_MIB_CNTR_EN_BIT           15
+#define NETA_GMAC_MIB_CNTR_EN_MASK          (1 << NETA_GMAC_MIB_CNTR_EN_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_GMAC_CTRL_1_REG(p)             (NETA_REG_BASE(p) + 0x2C04)
+
+#define NETA_GMAC_CTRL_2_REG(p)             (NETA_REG_BASE(p) + 0x2C08)
+
+#define NETA_GMAC_PSC_ENABLE_BIT            3
+#define NETA_GMAC_PSC_ENABLE_MASK           (1 << NETA_GMAC_PSC_ENABLE_BIT)
+
+#define NETA_GMAC_PORT_RGMII_BIT            4
+#define NETA_GMAC_PORT_RGMII_MASK           (1 << NETA_GMAC_PORT_RGMII_BIT)
+
+#define NETA_GMAC_PORT_RESET_BIT            6
+#define NETA_GMAC_PORT_RESET_MASK           (1 << NETA_GMAC_PORT_RESET_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_GMAC_AN_CTRL_REG(p)                (NETA_REG_BASE(p) + 0x2C0C)
+
+#define NETA_FORCE_LINK_FAIL_BIT                0
+#define NETA_FORCE_LINK_FAIL_MASK               (1 << NETA_FORCE_LINK_FAIL_BIT)
+
+#define NETA_FORCE_LINK_PASS_BIT                1
+#define NETA_FORCE_LINK_PASS_MASK               (1 << NETA_FORCE_LINK_PASS_BIT)
+
+#define NETA_SET_MII_SPEED_100_BIT              5
+#define NETA_SET_MII_SPEED_100_MASK             (1 << NETA_SET_MII_SPEED_100_BIT)
+
+#define NETA_SET_GMII_SPEED_1000_BIT            6
+#define NETA_SET_GMII_SPEED_1000_MASK           (1 << NETA_SET_GMII_SPEED_1000_BIT)
+
+#define NETA_ENABLE_SPEED_AUTO_NEG_BIT          7
+#define NETA_ENABLE_SPEED_AUTO_NEG_MASK         (1 << NETA_ENABLE_SPEED_AUTO_NEG_BIT)
+
+#define NETA_SET_FLOW_CONTROL_BIT               8
+#define NETA_SET_FLOW_CONTROL_MASK              (1 << NETA_SET_FLOW_CONTROL_BIT)
+
+#define NETA_FLOW_CONTROL_ADVERTISE_BIT         9
+#define NETA_FLOW_CONTROL_ADVERTISE_MASK        (1 << NETA_FLOW_CONTROL_ADVERTISE_BIT)
+
+#define NETA_FLOW_CONTROL_ASYMETRIC_BIT         10
+#define NETA_FLOW_CONTROL_ASYMETRIC_MASK        (1 << NETA_FLOW_CONTROL_ASYMETRIC_BIT)
+
+#define NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_BIT   11
+#define NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK  (1 << NETA_ENABLE_FLOW_CONTROL_AUTO_NEG_BIT)
+
+#define NETA_SET_FULL_DUPLEX_BIT                12
+#define NETA_SET_FULL_DUPLEX_MASK               (1 << NETA_SET_FULL_DUPLEX_BIT)
+
+#define NETA_ENABLE_DUPLEX_AUTO_NEG_BIT         13
+#define NETA_ENABLE_DUPLEX_AUTO_NEG_MASK        (1 << NETA_ENABLE_DUPLEX_AUTO_NEG_BIT)
+
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_GMAC_STATUS_REG(p)                 (NETA_REG_BASE(p) + 0x2C10)
+
+#define NETA_GMAC_LINK_UP_BIT               0
+#define NETA_GMAC_LINK_UP_MASK              (1 << NETA_GMAC_LINK_UP_BIT)
+
+#define NETA_GMAC_SPEED_1000_BIT            1
+#define NETA_GMAC_SPEED_1000_MASK           (1 << NETA_GMAC_SPEED_1000_BIT)
+
+#define NETA_GMAC_SPEED_100_BIT             2
+#define NETA_GMAC_SPEED_100_MASK            (1 << NETA_GMAC_SPEED_100_BIT)
+
+#define NETA_GMAC_FULL_DUPLEX_BIT           3
+#define NETA_GMAC_FULL_DUPLEX_MASK          (1 << NETA_GMAC_FULL_DUPLEX_BIT)
+
+#define NETA_RX_FLOW_CTRL_ENABLE_BIT        4
+#define NETA_RX_FLOW_CTRL_ENABLE_MASK       (1 << NETA_RX_FLOW_CTRL_ENABLE_BIT)
+
+#define NETA_TX_FLOW_CTRL_ENABLE_BIT        5
+#define NETA_TX_FLOW_CTRL_ENABLE_MASK       (1 << NETA_TX_FLOW_CTRL_ENABLE_BIT)
+
+#define NETA_RX_FLOW_CTRL_ACTIVE_BIT        6
+#define NETA_RX_FLOW_CTRL_ACTIVE_MASK       (1 << NETA_RX_FLOW_CTRL_ACTIVE_BIT)
+
+#define NETA_TX_FLOW_CTRL_ACTIVE_BIT        7
+#define NETA_TX_FLOW_CTRL_ACTIVE_MASK       (1 << NETA_TX_FLOW_CTRL_ACTIVE_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_GMAC_SERIAL_REG(p)             (NETA_REG_BASE(p) + 0x2C14)
+
+#define NETA_GMAC_FIFO_PARAM_0_REG(p)       (NETA_REG_BASE(p) + 0x2C18)
+#define NETA_GMAC_FIFO_PARAM_1_REG(p)       (NETA_REG_BASE(p) + 0x2C1C)
+
+#define NETA_GMAC_CAUSE_REG(p)              (NETA_REG_BASE(p) + 0x2C20)
+#define NETA_GMAC_MASK_REG(p)               (NETA_REG_BASE(p) + 0x2C24)
+
+#define NETA_GMAC_SERDES_CFG_0_REG(p)       (NETA_REG_BASE(p) + 0x2C28)
+#define NETA_GMAC_SERDES_CFG_1_REG(p)       (NETA_REG_BASE(p) + 0x2C2C)
+#define NETA_GMAC_SERDES_CFG_2_REG(p)       (NETA_REG_BASE(p) + 0x2C30)
+#define NETA_GMAC_SERDES_CFG_3_REG(p)       (NETA_REG_BASE(p) + 0x2C34)
+
+#define NETA_GMAC_PRBS_STATUS_REG(p)        (NETA_REG_BASE(p) + 0x2C38)
+#define NETA_GMAC_PRBS_ERR_CNTR_REG(p)      (NETA_REG_BASE(p) + 0x2C3C)
+
+#define NETA_GMAC_STATUS_1_REG(p)           (NETA_REG_BASE(p) + 0x2C40)
+
+#define NETA_GMAC_MIB_CTRL_REG(p)           (NETA_REG_BASE(p) + 0x2C44)
+#define NETA_GMAC_CTRL_3_REG(p)             (NETA_REG_BASE(p) + 0x2C48)
+
+#define NETA_GMAC_IPG_SIZE_OFFS             6
+#define NETA_GMAC_IPG_SIZE_ALL_MASK         (0x1FF << NETA_GMAC_IPG_SIZE_OFFS)
+#define NETA_GMAC_IPG_SIZE_MASK(size)       ((size) << NETA_GMAC_IPG_SIZE_OFFS)
+
+#define NETA_GMAC_QSGMII_REG(p)             (NETA_REG_BASE(p) + 0x2C4C)
+#define NETA_GMAC_QSGMII_STATUS_REG(p)      (NETA_REG_BASE(p) + 0x2C50)
+#define NETA_GMAC_QSGMII_ERR_CNTR_REG(p)    (NETA_REG_BASE(p) + 0x2C54)
+
+/* 8 FC Timer registers: 0x2c58 .. 0x2c74 */
+#define NETA_GMAC_FC_TIMER_REG(p, r)        (NETA_REG_BASE(p) + 0x2C58 + ((r) << 2))
+
+/* 4 DSA Tag registers: 0x2c78 .. 0x2c84 */
+#define NETA_GMAC_DSA_TAG_REG(p, r)         (NETA_REG_BASE(p) + 0x2C78 + ((r) << 2))
+
+#define NETA_GMAC_FC_WIN_0_REG(p)           (NETA_REG_BASE(p) + 0x2C88)
+#define NETA_GMAC_FC_WIN_1_REG(p)           (NETA_REG_BASE(p) + 0x2C8C)
+
+#define NETA_GMAC_CTRL_4_REG(p)             (NETA_REG_BASE(p) + 0x2C90)
+
+#define NETA_GMAC_SERIAL_1_REG(p)           (NETA_REG_BASE(p) + 0x2C94)
+
+#define NETA_LOW_POWER_CTRL_0_REG(p)        (NETA_REG_BASE(p) + 0x2CC0)
+
+/* Low Power Idle Control #1 register */
+#define NETA_LOW_POWER_CTRL_1_REG(p)        (NETA_REG_BASE(p) + 0x2CC4)
+
+#define NETA_LPI_REQUEST_EN_BIT             0
+#define NETA_LPI_REQUEST_EN_MASK            (1 << NETA_LPI_REQUEST_EN_BIT)
+
+#define NETA_LPI_REQUEST_FORCE_BIT          1
+#define NETA_LPI_REQUEST_FORCE_MASK         (1 << NETA_LPI_REQUEST_FORCE_BIT)
+
+#define NETA_LPI_MANUAL_MODE_BIT            2
+#define NETA_LPI_MANUAL_MODE_MASK           (1 << NETA_LPI_MANUAL_MODE_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_LOW_POWER_CTRL_2_REG(p)        (NETA_REG_BASE(p) + 0x2CC8)
+#define NETA_LOW_POWER_STATUS_REG(p)        (NETA_REG_BASE(p) + 0x2CCC)
+#define NETA_LOW_POWER_CNTR_REG(p)          (NETA_REG_BASE(p) + 0x2CD0)
+
+#endif /* MV_ETH_GMAC_NEW */
+
+
+#ifdef MV_PON_MIB_SUPPORT
+/* Special registers for PON MIB support */
+#define NETA_PON_MIB_MAX_GEM_PID            32
+#define NETA_PON_MIB_RX_CTRL_REG(idx)       (MV_PON_REG_BASE + 0x3800 + ((idx) << 2))
+#define NETA_PON_MIB_RX_DEF_REG             (MV_PON_REG_BASE + 0x3880)
+
+#define NETA_PON_MIB_RX_GEM_PID_OFFS        0
+#define NETA_PON_MIB_RX_GEM_PID_ALL_MASK    (0xFFF << NETA_PON_MIB_RX_GEM_PID_OFFS)
+#define NETA_PON_MIB_RX_GEM_PID_MASK(pid)   ((pid) << NETA_PON_MIB_RX_GEM_PID_OFFS)
+
+#define NETA_PON_MIB_RX_MIB_NO_OFFS         12
+#define NETA_PON_MIB_RX_MIB_NO_MASK         (0x7 << NETA_PON_MIB_RX_MIB_NO_OFFS)
+#define NETA_PON_MIB_RX_MIB_NO(mib)         ((mib) << NETA_PON_MIB_RX_MIB_NO_OFFS)
+
+#define NETA_PON_MIB_RX_VALID_BIT           15
+#define NETA_PON_MIB_RX_VALID_MASK          (1 << NETA_PON_MIB_RX_VALID_BIT)
+
+#endif /* MV_PON_MIB_SUPPORT */
+
+/******************************** NETA TX Registers *****************************/
+
+#define NETA_TXQ_BASE_ADDR_REG(p, txp, q)   (NETA_TX_REG_BASE((p), (txp)) + 0x1800 + ((q) << 2))
+
+#define NETA_TXQ_SIZE_REG(p, txp, q)        (NETA_TX_REG_BASE((p), (txp)) + 0x1820 + ((q) << 2))
+
+#define NETA_TXQ_DESC_NUM_OFFS              0
+#define NETA_TXQ_DESC_NUM_ALL_MASK          (0x3FFF << NETA_TXQ_DESC_NUM_OFFS)
+#define NETA_TXQ_DESC_NUM_MASK(size)        ((size) << NETA_TXQ_DESC_NUM_OFFS)
+
+#define NETA_TXQ_SENT_DESC_TRESH_OFFS       16
+#define NETA_TXQ_SENT_DESC_TRESH_ALL_MASK   (0x3FFF << NETA_TXQ_SENT_DESC_TRESH_OFFS)
+#define NETA_TXQ_SENT_DESC_TRESH_MASK(coal) ((coal) << NETA_TXQ_SENT_DESC_TRESH_OFFS)
+
+#define NETA_TXQ_STATUS_REG(p, txp, q)      (NETA_TX_REG_BASE((p), (txp)) + 0x1840 + ((q) << 2))
+
+#define NETA_TXQ_PENDING_DESC_OFFS          0
+#define NETA_TXQ_PENDING_DESC_MASK          (0x3FFF << NETA_TXQ_PENDING_DESC_OFFS)
+
+#define NETA_TXQ_SENT_DESC_OFFS             16
+#define NETA_TXQ_SENT_DESC_MASK             (0x3FFF << NETA_TXQ_SENT_DESC_OFFS)
+
+#define NETA_TXQ_UPDATE_REG(p, txp, q)      (NETA_TX_REG_BASE((p), (txp)) + 0x1860 + ((q) << 2))
+
+#define NETA_TXQ_ADD_PENDING_OFFS           0
+#define NETA_TXQ_ADD_PENDING_MASK           (0xFF << NETA_TXQ_ADD_PENDING_OFFS)
+
+#define NETA_TXQ_DEC_SENT_OFFS              16
+#define NETA_TXQ_DEC_SENT_MASK              (0xFF << NETA_TXQ_DEC_SENT_OFFS)
+
+#define NETA_TXQ_INDEX_REG(p, txp, q)       (NETA_TX_REG_BASE((p), (txp)) + 0x1880 + ((q) << 2))
+
+#define NETA_TXQ_NEXT_DESC_INDEX_OFFS       0
+#define NETA_TXQ_NEXT_DESC_INDEX_MASK       (0x3FFF << NETA_TXQ_NEXT_DESC_INDEX_OFFS)
+
+#define NETA_TXQ_SENT_DESC_REG(p, txp, q)   (NETA_TX_REG_BASE((p), (txp)) + 0x18A0 + ((q) << 2))
+/* Use NETA_TXQ_SENT_DESC_OFFS and NETA_TXQ_SENT_DESC_MASK */
+
+#ifdef MV_ETH_PMT_NEW
+#define NETA_TX_BAD_FCS_CNTR_REG(p, txp)    (NETA_TX_REG_BASE((p), (txp)) + 0x18C0)
+#define NETA_TX_DROP_CNTR_REG(p, txp)       (NETA_TX_REG_BASE((p), (txp)) + 0x18C4)
+#endif /* MV_ETH_PMT_NEW */
+
+#define NETA_PORT_TX_RESET_REG(p, txp)      (NETA_TX_REG_BASE((p), (txp)) + 0x18F0)
+
+#define NETA_PORT_TX_DMA_RESET_BIT          0
+#define NETA_PORT_TX_DMA_RESET_MASK         (1 << NETA_PORT_TX_DMA_RESET_BIT)
+
+#ifdef MV_ETH_PMT_NEW
+
+#define NETA_TX_ADD_BYTES_REG(p, txp)       (NETA_TX_REG_BASE((p), (txp)) + 0x18FC)
+
+#define NETA_TX_NEW_BYTES_OFFS              0
+#define NETA_TX_NEW_BYTES_ALL_MASK          (0xFFFF << NETA_TX_NEW_BYTES_OFFS)
+#define NETA_TX_NEW_BYTES_MASK(bytes)       ((bytes) << NETA_TX_NEW_BYTES_OFFS)
+
+#define NETA_TX_NEW_BYTES_TXQ_OFFS          28
+#define NETA_TX_NEW_BYTES_TXQ_MASK(txq)     ((txq) << NETA_TX_NEW_BYTES_TXQ_OFFS)
+
+#define NETA_TX_NEW_BYTES_COLOR_BIT         31
+#define NETA_TX_NEW_BYTES_COLOR_GREEN       (0 << NETA_TX_NEW_BYTES_COLOR_BIT)
+#define NETA_TX_NEW_BYTES_COLOR_YELLOW      (1 << NETA_TX_NEW_BYTES_COLOR_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define NETA_TXQ_NEW_BYTES_REG(p, txp, txq) (NETA_TX_REG_BASE((p), (txp)) + 0x1900 + ((txq) << 2))
+
+#define NETA_TX_MAX_MH_REGS                 15
+#define NETA_TX_MH_REG(p, txp, idx)         (NETA_TX_REG_BASE((p), (txp)) + 0x1944 + ((idx) << 2))
+
+/*************** Packet Modification Registers *******************/
+#define NETA_TX_PMT_ACCESS_REG(p)           (NETA_TX_REG_BASE((p), 0) + 0x1980)
+#define NETA_TX_PMT_FIFO_THRESH_REG(p)      (NETA_TX_REG_BASE((p), 0) + 0x1984)
+#define NETA_TX_PMT_MTU_REG(p)              (NETA_TX_REG_BASE((p), 0) + 0x1988)
+
+#define NETA_TX_PMT_MAX_ETHER_TYPES         4
+#define NETA_TX_PMT_ETHER_TYPE_REG(p, txp, i) (NETA_TX_REG_BASE((p), (txp)) + 0x1990 + ((i) << 2))
+
+#define NETA_TX_PMT_DEF_VLAN_CFG_REG(p)     (NETA_TX_REG_BASE((p), 0) + 0x19a0)
+#define NETA_TX_PMT_DEF_DSA_1_CFG_REG(p)    (NETA_TX_REG_BASE((p), 0) + 0x19a4)
+#define NETA_TX_PMT_DEF_DSA_2_CFG_REG(p)    (NETA_TX_REG_BASE((p), 0) + 0x19a8)
+#define NETA_TX_PMT_DEF_DSA_SRC_DEV_REG(p)  (NETA_TX_REG_BASE((p), 0) + 0x19ac)
+
+#define NETA_TX_PMT_TTL_ZERO_FRWD_REG(p)    (NETA_TX_REG_BASE((p), 0) + 0x19b0)
+#define NETA_TX_PMT_TTL_ZERO_CNTR_REG(p)    (NETA_TX_REG_BASE((p), 0) + 0x19b4)
+
+#define NETA_TX_PMT_PPPOE_TYPE_REG(p, txp)  (NETA_TX_REG_BASE((p), (txp)) + 0x19c0)
+#define NETA_TX_PMT_PPPOE_DATA_REG(p, txp)  (NETA_TX_REG_BASE((p), (txp)) + 0x19c4)
+#define NETA_TX_PMT_PPPOE_LEN_REG(p, txp)   (NETA_TX_REG_BASE((p), (txp)) + 0x19c8)
+#define NETA_TX_PMT_PPPOE_PROTO_REG(p, txp) (NETA_TX_REG_BASE((p), (txp)) + 0x19cc)
+
+#define NETA_TX_PMT_CONFIG_REG(p)           (NETA_TX_REG_BASE((p), 0) + 0x19d0)
+#define NETA_TX_PMT_STATUS_1_REG(p)         (NETA_TX_REG_BASE((p), 0) + 0x19d4)
+#define NETA_TX_PMT_STATUS_2_REG(p)         (NETA_TX_REG_BASE((p), 0) + 0x19d8)
+
+#else
+
+#define NETA_TX_COLOR_ADD_BYTES_REG(p, txp) (NETA_TX_REG_BASE((p), (txp)) + 0x1900)
+#define NETA_TX_GREEN_BYTES_REG(p, txp)     (NETA_TX_REG_BASE((p), (txp)) + 0x1908)
+#define NETA_TX_YELLOW_BYTES_REG(p, txp)    (NETA_TX_REG_BASE((p), (txp)) + 0x190c)
+
+#define NETA_TX_MAX_MH_REGS                 6
+#define NETA_TX_MH_REG(p, txp, idx)         (NETA_TX_REG_BASE((p), (txp)) + 0x1910 + ((idx) << 2))
+
+#define NETA_TX_DSA_SRC_DEV_REG(p, txp)     (NETA_TX_REG_BASE((p), (txp)) + 0x192C)
+
+#define NETA_TX_MAX_ETH_TYPE_REGS           4
+#define NETA_TX_ETH_TYPE_REG(p, txp, idx)   (NETA_TX_REG_BASE((p), (txp)) + 0x1930 + ((idx) << 2))
+
+#define NETA_TX_PMT_SIZE		256
+#define NETA_TX_PMT_W0_MASK		0xFFFF
+#define NETA_TX_PMT_W1_MASK		0xFFFFFFFF
+#define NETA_TX_PMT_W2_MASK		0x7FFFFFF
+#define NETA_TX_PMT_REG(p)		(NETA_TX_REG_BASE(p, 0) + 0x1940)
+#define NETA_TX_PMT_W0_REG(p)		(NETA_TX_REG_BASE(p, 0) + 0x1944)
+#define NETA_TX_PMT_W1_REG(p)		(NETA_TX_REG_BASE(p, 0) + 0x1948)
+#define NETA_TX_PMT_W2_REG(p)		(NETA_TX_REG_BASE(p, 0) + 0x194c)
+
+#endif /* MV_ETH_PMT_NEW */
+
+#ifdef MV_ETH_WRR_NEW
+/*********************** New TX WRR EJP Registers ********************************/
+
+#define NETA_TX_CMD_1_REG(p, txp)           (NETA_TX_REG_BASE((p), (txp)) + 0x1a00)
+
+#define NETA_TX_EJP_RESET_BIT               0
+#define NETA_TX_EJP_RESET_MASK              (1 << NETA_TX_EJP_RESET_BIT)
+
+#define NETA_TX_PTP_SYNC_BIT                1
+#define NETA_TX_PTP_SYNC_MASK               (1 << NETA_TX_EJP_RESET_BIT)
+
+#define NETA_TX_EJP_ENABLE_BIT              2
+#define NETA_TX_EJP_ENABLE_MASK             (1 << NETA_TX_EJP_ENABLE_BIT)
+
+#define NETA_TX_LEGACY_WRR_BIT              3
+#define NETA_TX_LEGACY_WRR_MASK             (1 << NETA_TX_LEGACY_WRR_BIT)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Transmit Queue Fixed Priority Configuration (TQFPC) */
+#define NETA_TX_FIXED_PRIO_CFG_REG(p, txp)  (NETA_TX_REG_BASE((p), (txp)) + 0x1a04)
+
+#define NETA_TX_FIXED_PRIO_OFFS             0
+#define NETA_TX_FIXED_PRIO_MASK             (0xFF << NETA_TX_FIXED_PRIO_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Basic Refill No of Clocks (BRC) */
+#define NETA_TX_REFILL_PERIOD_REG(p, txp)   (NETA_TX_REG_BASE((p), (txp)) + 0x1a08)
+
+#define NETA_TX_REFILL_CLOCKS_OFFS          0
+#define NETA_TX_REFILL_CLOCKS_MIN           16
+#define NETA_TX_REFILL_CLOCKS_MASK          (0xFFFF << NETA_TX_REFILL_RATE_CLOCKS_MASK)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Port Maximum Transmit Unit (PMTU) */
+#define NETA_TXP_MTU_REG(p, txp)            (NETA_TX_REG_BASE((p), (txp)) + 0x1a0c)
+
+#define NETA_TXP_MTU_OFFS                   0
+#define NETA_TXP_MTU_MAX                    0x3FFFF
+#define NETA_TXP_MTU_ALL_MASK               (NETA_TXP_MTU_MAX << NETA_TXP_MTU_OFFS)
+#define NETA_TXP_MTU_MASK(mtu)              ((mtu) << NETA_TXP_MTU_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Port Bucket Refill (PRefill) */
+#define NETA_TXP_REFILL_REG(p, txp)         (NETA_TX_REG_BASE((p), (txp)) + 0x1a10)
+
+#define NETA_TXP_REFILL_TOKENS_OFFS         0
+#define NETA_TXP_REFILL_TOKENS_MAX          0x7FFFF
+#define NETA_TXP_REFILL_TOKENS_ALL_MASK     (NETA_TXP_REFILL_TOKENS_MAX << NETA_TXP_REFILL_TOKENS_OFFS)
+#define NETA_TXP_REFILL_TOKENS_MASK(val)    ((val) << NETA_TXP_REFILL_TOKENS_OFFS)
+
+#define NETA_TXP_REFILL_PERIOD_OFFS         20
+#define NETA_TXP_REFILL_PERIOD_MAX          0x3FF
+#define NETA_TXP_REFILL_PERIOD_ALL_MASK     (NETA_TXP_REFILL_PERIOD_MAX << NETA_TXP_REFILL_PERIOD_OFFS)
+#define NETA_TXP_REFILL_PERIOD_MASK(val)    ((val) << NETA_TXP_REFILL_PERIOD_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Port Maximum Token Bucket Size (PMTBS) */
+#define NETA_TXP_TOKEN_SIZE_REG(p, txp)     (NETA_TX_REG_BASE((p), (txp)) + 0x1a14)
+#define NETA_TXP_TOKEN_SIZE_MAX             0xFFFFFFFF
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Port Token Bucket Counter (PMTBS) */
+#define NETA_TXP_TOKEN_CNTR_REG(p, txp)     (NETA_TX_REG_BASE((p), (txp)) + 0x1a18)
+#define NETA_TXP_TOKEN_CNTR_MAX             0xFFFFFFFF
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Queue Bucket Refill (QRefill) */
+#define NETA_TXQ_REFILL_REG(p, txp, q)      (NETA_TX_REG_BASE((p), (txp)) + 0x1a20 + ((q) << 2))
+
+#define NETA_TXQ_REFILL_TOKENS_OFFS         0
+#define NETA_TXQ_REFILL_TOKENS_MAX          0x7FFFF
+#define NETA_TXQ_REFILL_TOKENS_ALL_MASK     (NETA_TXQ_REFILL_TOKENS_MAX << NETA_TXQ_REFILL_TOKENS_OFFS)
+#define NETA_TXQ_REFILL_TOKENS_MASK(val)    ((val) << NETA_TXQ_REFILL_TOKENS_OFFS)
+
+#define NETA_TXQ_REFILL_PERIOD_OFFS         20
+#define NETA_TXQ_REFILL_PERIOD_MAX          0x3FF
+#define NETA_TXQ_REFILL_PERIOD_ALL_MASK     (NETA_TXQ_REFILL_PERIOD_MAX << NETA_TXQ_REFILL_PERIOD_OFFS)
+#define NETA_TXQ_REFILL_PERIOD_MASK(val)    ((val) << NETA_TXQ_REFILL_PERIOD_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Queue Maximum Token Bucket Size (QMTBS) */
+#define NETA_TXQ_TOKEN_SIZE_REG(p, txp, q)  (NETA_TX_REG_BASE((p), (txp)) + 0x1a40 + ((q) << 2))
+#define NETA_TXQ_TOKEN_SIZE_MAX             0x7FFFFFFF
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Queue Token Bucket Counter (PMTBS) */
+#define NETA_TXQ_TOKEN_CNTR_REG(p, txp, q)  (NETA_TX_REG_BASE((p), (txp)) + 0x1a60 + ((q) << 2))
+#define NETA_TXQ_TOKEN_CNTR_MAX             0xFFFFFFFF
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Transmit Queue Arbiter Configuration (TQxAC) */
+#define NETA_TXQ_WRR_ARBITER_REG(p, txp, q) (NETA_TX_REG_BASE((p), (txp)) + 0x1a80 + ((q) << 2))
+
+#define NETA_TXQ_WRR_WEIGHT_OFFS            0
+#define NETA_TXQ_WRR_WEIGHT_MAX             0xFF
+#define NETA_TXQ_WRR_WEIGHT_ALL_MASK        (NETA_TXQ_WRR_WEIGHT_MAX << NETA_TXQ_WRR_WEIGHT_OFFS)
+#define NETA_TXQ_WRR_WEIGHT_MASK(weigth)    ((weigth) << NETA_TXQ_WRR_WEIGHT_OFFS)
+
+#define NETA_TXQ_WRR_BYTE_COUNT_OFFS        8
+#define NETA_TXQ_WRR_BYTE_COUNT_MASK        (0x3FFFF << NETA_TXQ_WRR_BYTE_COUNT_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+/* Transmission Queue IPG (TQxIPG) */
+#define NETA_TXQ_EJP_IPG_REG(p, txp, q)     (NETA_TX_REG_BASE((p), (txp)) + 0x1aa0 + ((q) << 2))
+
+#define NETA_TXQ_EJP_IPG_OFFS               0
+#define NETA_TXQ_EJP_IPG_MASK               (0x3FFF << NETA_TXQ_EJP_IPG_OFFS)
+/*-----------------------------------------------------------------------------------------------*/
+
+#define NETA_TXP_EJP_HI_LO_REG(p, txp)      (NETA_TX_REG_BASE((p), (txp)) + 0x1ab0)
+#define NETA_TXP_EJP_HI_ASYNC_REG(p, txp)   (NETA_TX_REG_BASE((p), (txp)) + 0x1ab4)
+#define NETA_TXP_EJP_LO_ASYNC_REG(p, txp)   (NETA_TX_REG_BASE((p), (txp)) + 0x1ab8)
+#define NETA_TXP_EJP_SPEED_REG(p, txp)      (NETA_TX_REG_BASE((p), (txp)) + 0x1abc)
+/*-----------------------------------------------------------------------------------------------*/
+#endif /* MV_ETH_WRR_NEW */
+
+/******************** NETA RX EXTENDED DESCRIPTOR ********************************/
+
+#define NETA_DESC_ALIGNED_SIZE	            32
+
+#if defined(MV_CPU_BE) && !defined(CONFIG_MV_ETH_BE_WA)
+
+typedef struct neta_rx_desc {
+	MV_U16  dataSize;
+	MV_U16  pncInfo;
+	MV_U32  status;
+	MV_U32  pncFlowId;
+	MV_U32  bufPhysAddr;
+	MV_U16  csumL4;
+	MV_U16  prefetchCmd;
+	MV_U32  bufCookie;
+	MV_U32  hw_cmd;
+	MV_U32  pncExtra;
+} NETA_RX_DESC;
+
+#else
+
+typedef struct neta_rx_desc {
+	MV_U32  status;
+	MV_U16  pncInfo;
+	MV_U16  dataSize;
+	MV_U32  bufPhysAddr;
+	MV_U32  pncFlowId;
+	MV_U32  bufCookie;
+	MV_U16  prefetchCmd;
+	MV_U16  csumL4;
+	MV_U32  pncExtra;
+	MV_U32  hw_cmd;
+} NETA_RX_DESC;
+
+#endif /* MV_CPU_BE && !CONFIG_MV_ETH_BE_WA */
+
+/* "status" word fileds definition */
+#define NETA_RX_L3_OFFSET_OFFS              0
+#define NETA_RX_L3_OFFSET_MASK              (0x7F << NETA_RX_L3_OFFSET_OFFS)
+
+#define NETA_RX_IP_HLEN_OFFS                8
+#define NETA_RX_IP_HLEN_MASK                (0x1F << NETA_RX_IP_HLEN_OFFS)
+
+#define NETA_RX_BM_POOL_ID_OFFS             13
+#define NETA_RX_BM_POOL_ALL_MASK            (0x3 << NETA_RX_BM_POOL_ID_OFFS)
+#define NETA_RX_BM_POOL_ID_MASK(pool)       ((pool) << NETA_RX_BM_POOL_ID_OFFS)
+
+#define NETA_RX_ES_BIT                      16
+#define NETA_RX_ES_MASK                     (1 << NETA_RX_ES_BIT)
+
+#define NETA_RX_ERR_CODE_OFFS               17
+#define NETA_RX_ERR_CODE_MASK               (3 << NETA_RX_ERR_CODE_OFFS)
+#define NETA_RX_ERR_CRC                     (0 << NETA_RX_ERR_CODE_OFFS)
+#define NETA_RX_ERR_OVERRUN                 (1 << NETA_RX_ERR_CODE_OFFS)
+#define NETA_RX_ERR_LEN                     (2 << NETA_RX_ERR_CODE_OFFS)
+#define NETA_RX_ERR_RESOURCE                (3 << NETA_RX_ERR_CODE_OFFS)
+
+#define NETA_RX_F_DESC_BIT                  26
+#define NETA_RX_F_DESC_MASK                 (1 << NETA_RX_F_DESC_BIT)
+
+#define NETA_RX_L_DESC_BIT                  27
+#define NETA_RX_L_DESC_MASK                 (1 << NETA_RX_L_DESC_BIT)
+
+#define NETA_RX_L4_CSUM_OK_BIT              30
+#define NETA_RX_L4_CSUM_OK_MASK             (1 << NETA_RX_L4_CSUM_OK_BIT)
+
+#define NETA_RX_IP4_FRAG_BIT                31
+#define NETA_RX_IP4_FRAG_MASK               (1 << NETA_RX_IP4_FRAG_BIT)
+
+#ifdef CONFIG_MV_ETH_PNC
+
+#define NETA_RX_L3_OFFS                     24
+#define NETA_RX_L3_MASK                     (3 << NETA_RX_L3_OFFS)
+#define NETA_RX_L3_UN                       (0 << NETA_RX_L3_OFFS)
+#define NETA_RX_L3_IP6                      (1 << NETA_RX_L3_OFFS)
+#define NETA_RX_L3_IP4           	        (2 << NETA_RX_L3_OFFS)
+#define NETA_RX_L3_IP4_ERR            		(3 << NETA_RX_L3_OFFS)
+
+#define NETA_RX_L4_OFFS                     28
+#define NETA_RX_L4_MASK                     (3 << NETA_RX_L4_OFFS)
+#define NETA_RX_L4_TCP                      (0 << NETA_RX_L4_OFFS)
+#define NETA_RX_L4_UDP                      (1 << NETA_RX_L4_OFFS)
+#define NETA_RX_L4_OTHER                    (2 << NETA_RX_L4_OFFS)
+
+/* Bits of "pncExtra" field */
+#define NETA_RX_PNC_ENABLED_BIT             0
+#define NETA_RX_PNC_ENABLED_MASK            (1 << NETA_RX_PNC_ENABLED_BIT)
+
+#define NETA_RX_PNC_LOOPS_OFFS              1
+#define NETA_RX_PNC_LOOPS_MASK              (0xF << NETA_RX_PNC_LOOPS_OFFS)
+
+#define NETA_PNC_STATUS_OFFS                5
+#define NETA_PNC_STATUS_MASK                (3 << NETA_PNC_STATUS_OFFS)
+
+#define NETA_PNC_RI_EXTRA_OFFS              16
+#define NETA_PNC_RI_EXTRA_MASK              (0xFFF << NETA_PNC_RI_EXTRA_OFFS)
+/*---------------------------------------------------------------------------*/
+
+#else
+
+#define ETH_RX_VLAN_TAGGED_FRAME_BIT        19
+#define ETH_RX_VLAN_TAGGED_FRAME_MASK       (1 << ETH_RX_VLAN_TAGGED_FRAME_BIT)
+
+#define ETH_RX_BPDU_FRAME_BIT               20
+#define ETH_RX_BPDU_FRAME_MASK              (1 << ETH_RX_BPDU_FRAME_BIT)
+
+#define ETH_RX_L4_TYPE_OFFSET               21
+#define ETH_RX_L4_TYPE_MASK                 (3 << ETH_RX_L4_TYPE_OFFSET)
+#define ETH_RX_L4_TCP_TYPE                  (0 << ETH_RX_L4_TYPE_OFFSET)
+#define ETH_RX_L4_UDP_TYPE                  (1 << ETH_RX_L4_TYPE_OFFSET)
+#define ETH_RX_L4_OTHER_TYPE                (2 << ETH_RX_L4_TYPE_OFFSET)
+
+#define ETH_RX_NOT_LLC_SNAP_FORMAT_BIT      23
+#define ETH_RX_NOT_LLC_SNAP_FORMAT_MASK     (1 << ETH_RX_NOT_LLC_SNAP_FORMAT_BIT)
+
+#ifdef MV_ETH_LEGACY_PARSER_IPV6
+
+#define NETA_RX_L3_OFFS                     24
+#define NETA_RX_L3_MASK                     (3 << NETA_RX_L3_OFFS)
+#define NETA_RX_L3_UN                       (0 << NETA_RX_L3_OFFS)
+#define NETA_RX_L3_IP6                      (2 << NETA_RX_L3_OFFS)
+#define NETA_RX_L3_IP4           	        (3 << NETA_RX_L3_OFFS)
+#define NETA_RX_L3_IP4_ERR            		(1 << NETA_RX_L3_OFFS)
+
+#else
+
+#define ETH_RX_IP_FRAME_TYPE_BIT            24
+#define ETH_RX_IP_FRAME_TYPE_MASK           (1 << ETH_RX_IP_FRAME_TYPE_BIT)
+
+#define ETH_RX_IP_HEADER_OK_BIT             25
+#define ETH_RX_IP_HEADER_OK_MASK            (1 << ETH_RX_IP_HEADER_OK_BIT)
+
+#endif /* MV_ETH_LEGACY_PARSER_IPV6 */
+
+#define ETH_RX_UNKNOWN_DA_BIT               28
+#define ETH_RX_UNKNOWN_DA_MASK              (1 << ETH_RX_UNKNOWN_DA_BIT)
+
+#endif /* CONFIG_MV_ETH_PNC */
+/*---------------------------------------------------------------------------*/
+
+
+/* Bit map of "hw_cmd" field */
+#define NETA_RX_COLOR_BIT                   3
+#define NETA_RX_COLOR_MASK				    (1 << NETA_RX_COLOR_BIT)
+#define NETA_RX_COLOR_GREEN                 (0 << NETA_RX_COLOR_BIT)
+#define NETA_RX_COLOR_YELLOW                (1 << NETA_RX_COLOR_BIT)
+
+#define NETA_RX_DSA_OFFS           		    4
+#define NETA_RX_DSA_MASK           		    (3 << NETA_RX_DSA_OFFS)
+#define NETA_RX_DSA_NONE                    (0 << NETA_RX_DSA_OFFS)
+#define NETA_RX_DSA                         (1 << NETA_RX_DSA_OFFS)
+#define NETA_RX_DSA_E                       (2 << NETA_RX_DSA_OFFS)
+
+#define NETA_RX_GEM_PID_OFFS                8
+#define NETA_RX_GEM_PID_MASK                (0xFFF << NETA_RX_GEM_PID_OFFS)
+/*---------------------------------------------------------------------------*/
+
+
+/******************** NETA TX EXTENDED DESCRIPTOR ********************************/
+
+#if defined(MV_CPU_BE) && !defined(CONFIG_MV_ETH_BE_WA)
+
+typedef struct neta_tx_desc {
+	MV_U16  dataSize;
+	MV_U16  csumL4;
+	MV_U32  command;
+	MV_U32  hw_cmd;
+	MV_U32  bufPhysAddr;
+	MV_U32  reserved[4];
+} NETA_TX_DESC;
+
+#else
+
+typedef struct neta_tx_desc {
+	MV_U32  command;
+	MV_U16  csumL4;
+	MV_U16  dataSize;
+	MV_U32  bufPhysAddr;
+	MV_U32  hw_cmd;
+	MV_U32  reserved[4];
+} NETA_TX_DESC;
+
+#endif /* MV_CPU_BE && !CONFIG_MV_ETH_BE_WA */
+
+/* "command" word fileds definition */
+#define NETA_TX_L3_OFFSET_OFFS              0
+#define NETA_TX_L3_OFFSET_MASK              (0x7F << NETA_TX_L3_OFFSET_OFFS)
+
+#define NETA_TX_GEM_OEM_BIT                 7
+#define NETA_TX_GEM_OEM_MASK                (1 << NETA_TX_GEM_OEM_BIT)
+
+#define NETA_TX_IP_HLEN_OFFS                8
+#define NETA_TX_IP_HLEN_MASK                (0x1F << NETA_TX_IP_HLEN_OFFS)
+
+#define NETA_TX_BM_POOL_ID_OFFS             13
+#define NETA_TX_BM_POOL_ID_ALL_MASK         (0x3 << NETA_TX_BM_POOL_ID_OFFS)
+#define NETA_TX_BM_POOL_ID_MASK(pool)       ((pool) << NETA_TX_BM_POOL_ID_OFFS)
+
+#define NETA_TX_HWF_BIT                     15
+#define NETA_TX_HWF_MASK                    (1 << NETA_TX_HWF_BIT)
+
+#define NETA_TX_L4_BIT                      16
+#define NETA_TX_L4_TCP                      (0 << NETA_TX_L4_BIT)
+#define NETA_TX_L4_UDP                      (1 << NETA_TX_L4_BIT)
+
+#define NETA_TX_L3_BIT                      17
+#define NETA_TX_L3_IP4                      (0 << NETA_TX_L3_BIT)
+#define NETA_TX_L3_IP6                      (1 << NETA_TX_L3_BIT)
+
+#define NETA_TX_IP_CSUM_BIT                 18
+#define NETA_TX_IP_CSUM_MASK                (1 << NETA_TX_IP_CSUM_BIT)
+
+#define NETA_TX_Z_PAD_BIT                   19
+#define NETA_TX_Z_PAD_MASK                  (1 << NETA_TX_Z_PAD_BIT)
+
+#define NETA_TX_L_DESC_BIT                  20
+#define NETA_TX_L_DESC_MASK                 (1 << NETA_TX_L_DESC_BIT)
+
+#define NETA_TX_F_DESC_BIT                  21
+#define NETA_TX_F_DESC_MASK                 (1 << NETA_TX_F_DESC_BIT)
+
+#define NETA_TX_BM_ENABLE_BIT               22
+#define NETA_TX_BM_ENABLE_MASK              (1 << NETA_TX_BM_ENABLE_BIT)
+
+
+#define NETA_TX_PKT_OFFSET_OFFS             23
+#define NETA_TX_PKT_OFFSET_MAX				0x7F
+#define NETA_TX_PKT_OFFSET_ALL_MASK         (NETA_TX_PKT_OFFSET_MAX << NETA_TX_PKT_OFFSET_OFFS)
+#define NETA_TX_PKT_OFFSET_MASK(offset)     (((offset) << NETA_TX_PKT_OFFSET_OFFS) & NETA_TX_PKT_OFFSET_ALL_MASK)
+
+#define NETA_TX_L4_CSUM_BIT                 30
+#define NETA_TX_L4_CSUM_MASK                (3 << NETA_TX_L4_CSUM_BIT)
+#define NETA_TX_L4_CSUM_PART                (0 << NETA_TX_L4_CSUM_BIT)
+#define NETA_TX_L4_CSUM_FULL                (1 << NETA_TX_L4_CSUM_BIT)
+#define NETA_TX_L4_CSUM_NOT                 (2 << NETA_TX_L4_CSUM_BIT)
+
+#define NETA_TX_FLZ_DESC_MASK               (NETA_TX_F_DESC_MASK | NETA_TX_L_DESC_MASK | NETA_TX_Z_PAD_MASK)
+/*-------------------------------------------------------------------------------*/
+
+/* "hw_cmd" field definition */
+#define NETA_TX_ES_BIT                      0
+#define NETA_TX_ES_MASK                     (1 << NETA_TX_ES_BIT)
+
+#define NETA_TX_ERR_CODE_OFFS               1
+#define NETA_TX_ERR_CODE_MASK               (3 << NETA_TX_ERR_CODE_OFFS)
+#define NETA_TX_ERR_LATE_COLLISION          (0 << NETA_TX_ERR_CODE_OFFS)
+#define NETA_TX_ERR_UNDERRUN                (1 << NETA_TX_ERR_CODE_OFFS)
+#define NETA_TX_ERR_EXCE_COLLISION          (2 << NETA_RX_ERR_CODE_OFFS)
+
+#define NETA_TX_COLOR_BIT                   3
+#define NETA_TX_COLOR_GREEN                 (0 << NETA_TX_COLOR_BIT)
+#define NETA_TX_COLOR_YELLOW                (1 << NETA_TX_COLOR_BIT)
+
+#define NETA_TX_MH_SEL_OFFS                 4
+
+#ifdef MV_ETH_PMT_NEW
+#define NETA_TX_MH_SEL_MASK                 (0xF << NETA_TX_MH_SEL_OFFS)
+#else
+#define NETA_TX_MH_SEL_MASK                 (0x7 << NETA_TX_MH_SEL_OFFS)
+#endif /* MV_ETH_PMT_NEW */
+
+#define NETA_TX_MH_UNCHANGE                 (0 << NETA_TX_MH_SEL_OFFS)
+
+#define NETA_TX_GEM_PID_OFFS                8
+#define NETA_TX_GEM_PID_MASK                (0xFFF << NETA_TX_GEM_PID_OFFS)
+
+#define NETA_TX_MOD_CMD_OFFS                20
+#define NETA_TX_MOD_CMD_MASK                (0x3FF << NETA_TX_MOD_CMD_OFFS)
+
+#define NETA_TX_DSA_OFFS                    30
+#define NETA_TX_DSA_MASK                    (3 << NETA_TX_DSA_OFFS)
+#define NETA_TX_DSA_NONE                    (0 << NETA_TX_DSA_OFFS)
+#define NETA_TX_DSA                         (1 << NETA_TX_DSA_OFFS) /* normal dsa */
+#define NETA_TX_DSA_E                       (2 << NETA_TX_DSA_OFFS) /* extended dsa */
+/*-------------------------------------------------------------------------------*/
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __mvNetaRegs_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/nfp/mvNfpDefs.h b/arch/arm/plat-feroceon/mv_hal/neta/nfp/mvNfpDefs.h
new file mode 100755
index 0000000..7dd7d13
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/nfp/mvNfpDefs.h
@@ -0,0 +1,224 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvNfpDefs.h - Header File for Marvell NFP Configuration definitions
+*
+* DESCRIPTION:
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __mvNfpDefs_h__
+#define __mvNfpDefs_h__
+
+#include "mv802_3.h"
+#include "gbe/mvNetaRegs.h"
+#include "gbe/mvNeta.h"
+
+#ifdef CONFIG_MV_ETH_NFP_MODULE
+# define CONFIG_MV_ETH_NFP
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP
+
+#define ETH_NFP
+
+#ifdef CONFIG_MV_ETH_NFP_EXT
+# define NFP_EXT
+# define NFP_EXT_NUM 	CONFIG_MV_ETH_NFP_EXT_NUM
+#else
+# define NFP_EXT_NUM 	0
+#endif
+
+#define NFP_MAX_PORTS   (MV_ETH_MAX_PORTS + NFP_EXT_NUM)
+
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN) || defined(CONFIG_MV_ETH_NFP_VLAN_LEARN) ||    \
+	defined(CONFIG_MV_ETH_NFP_FDB_LEARN) || defined(CONFIG_MV_ETH_NFP_PPP_LEARN) || \
+	defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+#define NFP_LEARN
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_FIB
+#define NFP_FIB
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_FIB_LEARN
+#define NFP_FIB_LEARN
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_VLAN
+#define NFP_VLAN
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_VLAN_LEARN
+#define NFP_VLAN_LEARN
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_PPP
+#define NFP_PPP
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_PPP_LEARN
+#define NFP_PPP_LEARN
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_CT
+#define NFP_CT
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_CT_LEARN
+#define NFP_CT_LEARN
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+#define NFP_NAT
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_LIMIT
+#define NFP_LIMIT
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_CLASSIFY
+#define NFP_CLASSIFY
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_STATS
+#define NFP_STAT
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_BRIDGE
+#define NFP_BRIDGE
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_FDB_MODE
+#define NFP_FDB_MODE
+#endif
+
+#ifdef CONFIG_MV_ETH_NFP_FDB_LEARN
+#define NFP_FDB_LEARN
+#endif
+
+#ifdef CONFIG_MV_ETH_SWITCH
+# define NFP_MAX_SWITCH_GROUPS  CONFIG_MV_ETH_SWITCH_NETDEV_NUM
+#else
+# define NFP_MAX_SWITCH_GROUPS  1
+#endif /* CONFIG_MV_ETH_SWITCH */
+
+typedef struct {
+	MV_U16 flags;
+
+	MV_U8  txp;
+	MV_U8  txq;
+
+	MV_U8 pkt_ecn;
+	MV_U8 pkt_dscp;
+	int   ct_dscp;
+
+	int pkt_vlan_prio;
+	int bridge_vlan_prio;
+	int ct_vlan_prio;
+
+	MV_U16 mh;
+
+	int iif_prio;
+	int iif_vlan_prio;
+	int iif_dscp_prio;
+
+	int prio_dscp;
+	int prio_vprio;
+	MV_U8 prio_txp;
+	MV_U8 prio_txq;
+	MV_U16 prio_mh;
+
+} NFP_CLASSIFY_INFO;
+
+typedef struct {
+	void   *dev;
+	MV_U32 tx_cmd;
+	MV_U32 diffL4[2];
+	MV_U8  *pWrite;
+	MV_U16 flags;
+	MV_U16 mtu;
+	short  shift;
+	MV_U8  txp;
+	MV_U8  txq;
+	MV_IP_HEADER_INFO ipInfo;
+	void   *privateData;
+} MV_NFP_RESULT;
+
+#define MV_NFP_RES_TXP_VALID       0x0001
+#define MV_NFP_RES_TXQ_VALID       0x0002
+#define MV_NFP_RES_IP_INFO_VALID   0x0004
+#define MV_NFP_RES_NETDEV_EXT      0x0010
+#define MV_NFP_RES_L4_CSUM_NEEDED  0x0020
+
+MV_STATUS mvNfpIfMapPortGet(int ifIdx, int *port);
+MV_STATUS mvNfpRx(MV_U32 inPort, NETA_RX_DESC *pRxDesc, MV_ETH_PKT *pPkt, MV_NFP_RESULT* pRes);
+
+#endif /* CONFIG_MV_ETH_NFP */
+
+#endif /* __mvNfp_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pmt/mvPmt.c b/arch/arm/plat-feroceon/mv_hal/neta/pmt/mvPmt.c
new file mode 100755
index 0000000..dce977a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pmt/mvPmt.c
@@ -0,0 +1,639 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"  /* Should be included before mvSysHwConfig */
+#include "mvTypes.h"
+#include "mvDebug.h"
+#include "mvOs.h"
+
+#include "gbe/mvNeta.h"
+
+#include "mvPmt.h"
+
+MV_NETA_PMT	**mvPmtBase = NULL;
+
+/* #define PMT_DBG mvOsPrintf */
+#define PMT_DBG(X...)
+
+static char mvPmtCmdNames[MV_ETH_PMT_SIZE][PMT_TEXT] = {
+
+	[MV_NETA_CMD_NONE]          = "NO_MOD",
+	[MV_NETA_CMD_ADD_2B]        = "ADD_2B",
+	[MV_NETA_CMD_CFG_VLAN]      = "CFG_VLAN",
+	[MV_NETA_CMD_ADD_VLAN]      = "ADD_VLAN",
+	[MV_NETA_CMD_CFG_DSA_1]     = "CFG_DSA_1",
+	[MV_NETA_CMD_CFG_DSA_2]     = "CFG_DSA_2",
+	[MV_NETA_CMD_ADD_DSA]       = "ADD_DSA",
+	[MV_NETA_CMD_DEL_BYTES]     = "DEL_BYTES",
+	[MV_NETA_CMD_REPLACE_2B]    = "REPLACE_2B",
+	[MV_NETA_CMD_REPLACE_LSB]   = "REPLACE_LSB",
+	[MV_NETA_CMD_REPLACE_MSB]   = "REPLACE_MSB",
+	[MV_NETA_CMD_REPLACE_VLAN]  = "REPLACE_VLAN",
+	[MV_NETA_CMD_DEC_LSB]       = "DEC_LSB",
+	[MV_NETA_CMD_DEC_MSB]       = "DEC_MSB",
+	[MV_NETA_CMD_ADD_CALC_LEN]  = "ADD_CALC_LEN",
+	[MV_NETA_CMD_REPLACE_LEN]   = "REPLACE_LEN",
+	[MV_NETA_CMD_IPV4_CSUM]     = "IPV4_CSUM",
+	[MV_NETA_CMD_L4_CSUM]       = "L4_CSUM",
+	[MV_NETA_CMD_SKIP]          = "SKIP",
+	[MV_NETA_CMD_JUMP]          = "JUMP",
+	[MV_NETA_CMD_JUMP_SKIP]     = "JUMP_SKIP",
+	[MV_NETA_CMD_JUMP_SUB]      = "JUMP_SUB",
+	[MV_NETA_CMD_PPPOE]         = "PPPOE",
+	[MV_NETA_CMD_STORE]         = "STORE",
+};
+
+/*******************************************************************************
+* mvNetaPmtWrite - Add entry to Packet Modification Table
+*
+* INPUT:
+*       int			port    - NETA port number
+*       int			idx     - PMT entry index to write to
+*       MV_NETA_PMT	pEntry  - PMT entry
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure
+*******************************************************************************/
+MV_STATUS   mvNetaPmtWrite(int port, int idx, MV_NETA_PMT *pEntry)
+{
+	MV_NETA_PMT	*pBase;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort)) {
+		mvOsPrintf("%s: port %d is out of range\n", __func__, port);
+		return MV_OUT_OF_RANGE;
+	}
+
+	if ((idx < 0) || (idx >= MV_ETH_PMT_SIZE)) {
+		mvOsPrintf("%s: entry %d is out of range\n", __func__, idx);
+		return MV_OUT_OF_RANGE;
+	}
+	if ((mvPmtBase == NULL) || (mvPmtBase[port] == NULL)) {
+		mvOsPrintf("%s: PMT for port #%d is not initialized\n", __func__, port);
+		return MV_INIT_ERROR;
+	}
+	pBase = mvPmtBase[port];
+	pBase[idx].word = pEntry->word;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaPmtRead - Read entry from Packet Modification Table
+*
+* INPUT:
+*       int			port - NETA port number
+*       int			idx  - PMT entry index to read from
+* OUTPUT:
+*       MV_NETA_PMT	pEntry - PMT entry
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure
+*******************************************************************************/
+MV_STATUS mvNetaPmtRead(int port, int idx, MV_NETA_PMT *pEntry)
+{
+	MV_NETA_PMT	*pBase;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort)) {
+		mvOsPrintf("%s: port %d is out of range\n", __func__, port);
+		return MV_OUT_OF_RANGE;
+	}
+
+	if ((idx < 0) || (idx >= MV_ETH_PMT_SIZE)) {
+		mvOsPrintf("%s: entry %d is out of range\n", __func__, idx);
+		return MV_OUT_OF_RANGE;
+	}
+	if ((mvPmtBase == NULL) || (mvPmtBase[port] == NULL)) {
+		mvOsPrintf("%s: PMT for port #%d is not initialized\n", __func__, port);
+		return MV_INIT_ERROR;
+	}
+	pBase = mvPmtBase[port];
+	pEntry->word = pBase[idx].word;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaPmtClear - Clear Packet Modification Table
+*
+* INPUT:
+*       int			port - NETA port number
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure
+*******************************************************************************/
+MV_STATUS   mvNetaPmtClear(int port)
+{
+	int         idx;
+	MV_NETA_PMT entry;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort)) {
+		mvOsPrintf("%s: port %d is out of range\n", __func__, port);
+		return MV_OUT_OF_RANGE;
+	}
+
+	MV_NETA_PMT_INVALID_SET(&entry);
+	for (idx = 0; idx < MV_ETH_PMT_SIZE; idx++)
+		mvNetaPmtWrite(port, idx, &entry);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaPmtInit - Init Packet Modification Table driver
+*
+* INPUT:
+*       int			port - NETA port number
+*
+* RETURN:   MV_STATUS
+*               MV_OK - Success, Others - Failure
+*******************************************************************************/
+MV_STATUS   mvNetaPmtInit(int port, MV_NETA_PMT *pBase)
+{
+	if ((port < 0) || (port >= mvNetaHalData.maxPort)) {
+		mvOsPrintf("%s: port %d is out of range\n", __func__, port);
+		return MV_OUT_OF_RANGE;
+	}
+
+	if (mvPmtBase == NULL) {
+		mvPmtBase = mvOsMalloc(mvNetaHalData.maxPort * sizeof(MV_NETA_PMT *));
+		if (mvPmtBase == NULL) {
+			mvOsPrintf("%s: Allocation failed\n", __func__);
+			return MV_OUT_OF_CPU_MEM;
+		}
+		memset(mvPmtBase, 0, mvNetaHalData.maxPort * sizeof(MV_NETA_PMT *));
+	}
+	mvPmtBase[port] = pBase;
+
+	mvNetaPmtClear(port);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNetaPmtDestroy - Free PMT Base memory
+*
+* INPUT:
+*
+* RETURN:   void
+*******************************************************************************/
+MV_VOID   mvNetaPmtDestroy(MV_VOID)
+{
+	if (mvPmtBase)
+		mvOsFree(mvPmtBase);
+}
+
+/*******************************************************************************
+* mvNetaPmtEntryPrint - Print PMT entry
+*
+* INPUT:
+*       MV_NETA_PMT*    pEntry - PMT entry to be printed
+*
+* RETURN:   void
+*******************************************************************************/
+void    mvNetaPmtEntryPrint(MV_NETA_PMT *pEntry)
+{
+	mvOsPrintf("%04x %04x: %s",
+		MV_NETA_PMT_CTRL_GET(pEntry), MV_NETA_PMT_DATA_GET(pEntry),
+		mvPmtCmdNames[MV_NETA_PMT_CMD_GET(pEntry)]);
+
+	if (pEntry->word & MV_NETA_PMT_IP4_CSUM_MASK)
+		mvOsPrintf(", IPv4 csum");
+
+	if (pEntry->word & MV_NETA_PMT_L4_CSUM_MASK)
+		mvOsPrintf(", L4 csum");
+
+	if (pEntry->word & MV_NETA_PMT_LAST_MASK)
+		mvOsPrintf(", Last");
+
+	mvOsPrintf("\n");
+}
+
+/*******************************************************************************
+* mvNetaPmtDump - Dump Packet Modification Table
+*
+* INPUT:
+*       int			port    - NETA port number
+*       int         flags   -
+*
+* RETURN:   void
+*******************************************************************************/
+void   mvNetaPmtDump(int port, int flags)
+{
+	int             idx, count = 0;
+	MV_NETA_PMT 	entry;
+	MV_STATUS       status;
+
+	if ((port < 0) || (port >= mvNetaHalData.maxPort)) {
+		mvOsPrintf("%s: port %d is out of range\n", __func__, port);
+		return;
+	}
+
+	for (idx = 0; idx < MV_ETH_PMT_SIZE; idx++) {
+		status = mvNetaPmtRead(port, idx, &entry);
+		if (status != MV_OK) {
+			mvOsPrintf("%s failed: port=%d, idx=%d, status=%d\n",
+					__func__, port, idx, status);
+			return;
+		}
+		if ((flags & PMT_PRINT_VALID_FLAG) && !MV_NETA_PMT_IS_VALID(&entry))
+			continue;
+
+		count++;
+		mvOsPrintf("[%3d]: ", idx);
+		mvNetaPmtEntryPrint(&entry);
+	}
+
+	if (!count)
+		mvOsPrintf("PMT is empty, %d entries\n", MV_ETH_PMT_SIZE);
+}
+
+/*******************************************************************************
+* mvNetaPmtAdd2Bytes - Set PMT entry with "add 2 bytes" command
+*
+* INPUT:
+*       MV_U16 data         - 2 bytes of data to be added
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void    mvNetaPmtAdd2Bytes(MV_NETA_PMT *pEntry, MV_U16 data)
+{
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_ADD_2B);
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/*******************************************************************************
+* mvNetaPmtReplace2Bytes - Set PMT entry with "Replace 2 bytes" command
+*
+* INPUT:
+*       MV_U16 data         - 2 bytes of data to be replaced
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void    mvNetaPmtReplace2Bytes(MV_NETA_PMT *pEntry, MV_U16 data)
+{
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_REPLACE_2B);
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/*******************************************************************************
+* mvNetaPmtDelShorts - Set PMT entry with "Delete" command
+*
+* INPUT:
+*       MV_U8   toDelete    - number of shorts to be deleted
+*       MV_U8   skipBefore  - number of shorts to be skipped before delete
+*       MV_U8   skipAfter   - number of shorts to be skipped after delete
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void    mvNetaPmtDelShorts(MV_NETA_PMT *pEntry, MV_U8 toDelete,
+				MV_U8 skipBefore, MV_U8 skipAfter)
+{
+	MV_U16  data;
+
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_DEL_BYTES);
+
+	data = MV_NETA_PMT_DEL_SHORTS(toDelete) |
+		MV_NETA_PMT_DEL_SKIP_B(skipBefore) |
+		MV_NETA_PMT_DEL_SKIP_A(skipAfter);
+
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/* Set update checksum flags to PMT entry */
+void    mvNetaPmtFlags(MV_NETA_PMT *pEntry, int last, int ipv4, int l4)
+{
+	if (last)
+		pEntry->word |= MV_NETA_PMT_LAST_MASK;
+
+	if (ipv4)
+		pEntry->word |= MV_NETA_PMT_IP4_CSUM_MASK;
+
+	if (l4)
+		pEntry->word |= MV_NETA_PMT_L4_CSUM_MASK;
+}
+
+/* Set Last flag to PMT entry */
+void    mvNetaPmtLastFlag(MV_NETA_PMT *pEntry, int last)
+{
+	if (last)
+		pEntry->word |= MV_NETA_PMT_LAST_MASK;
+	else
+		pEntry->word &= ~MV_NETA_PMT_LAST_MASK;
+}
+
+/*******************************************************************************
+* mvNetaPmtReplaceLSB - Set PMT entry with "Replace LSB" command
+*
+* INPUT:
+*       MV_U8 value    - value to be placed
+*       MV_U8 mask     - mask defines which bits to be replaced
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void    mvNetaPmtReplaceLSB(MV_NETA_PMT *pEntry, MV_U8 value, MV_U8 mask)
+{
+	MV_U16  data;
+
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_REPLACE_LSB);
+
+	data = (value << 0) | (mask << 8);
+
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/*******************************************************************************
+* mvNetaPmtReplaceMSB - Set PMT entry with "Replace MSB" command
+*
+* INPUT:
+*       MV_U8 value    - value to be placed
+*       MV_U8 mask     - mask defines which bits to be replaced
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void    mvNetaPmtReplaceMSB(MV_NETA_PMT *pEntry, MV_U8 value, MV_U8 mask)
+{
+	MV_U16  data;
+
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_REPLACE_MSB);
+
+	data = (value << 0) | (mask << 8);
+
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/*******************************************************************************
+* mvNetaPmtSkip - Set PMT entry with "Skip" command
+*
+* INPUT:
+*       MV_U16 shorts   - number of shorts to be skipped
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void    mvNetaPmtSkip(MV_NETA_PMT *pEntry, MV_U16 shorts)
+{
+	MV_U16  data;
+
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_SKIP);
+
+	data = MV_NETA_PMT_CALC_LEN_DATA(shorts * 2);
+	data |= MV_NETA_PMT_CALC_LEN_0_ZERO;
+	data |= MV_NETA_PMT_CALC_LEN_1(MV_NETA_PMT_ZERO_ADD);
+	data |= MV_NETA_PMT_CALC_LEN_2(MV_NETA_PMT_ZERO_ADD);
+	data |= MV_NETA_PMT_CALC_LEN_3_ADD_MASK;
+
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/*******************************************************************************
+* mvNetaPmtJump - Set PMT entry with "Jump" command
+*
+* INPUT:
+*       MV_U16 target   - PMT entry to jump to
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void    mvNetaPmtJump(MV_NETA_PMT *pEntry, MV_U16 target, int type, int cond)
+{
+	MV_U16  data;
+
+	if (type == 0) {
+		MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_JUMP);
+	} else if (type == 1) {
+		MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_JUMP_SKIP);
+	} else if (type == 2) {
+		MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_JUMP_SUB);
+	} else {
+		mvOsPrintf("%s - Unexpected type = %d\n", __func__, type);
+		return;
+	}
+
+	data = target;
+	if (cond == 1)
+		data |= MV_NETA_PMT_IP4_CSUM_MASK;
+	else if (cond == 2)
+		data |= MV_NETA_PMT_L4_CSUM_MASK;
+
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+
+/*******************************************************************************
+* mvNetaPmtDecLSB - Set PMT entry with "Decrement LSB" command
+*
+* INPUT:
+*       MV_U8   skipBefore  - number of shorts to be skipped before delete
+*       MV_U8   skipAfter   - number of shorts to be skipped after delete
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void        mvNetaPmtDecLSB(MV_NETA_PMT *pEntry, MV_U8 skipBefore, MV_U8 skipAfter)
+{
+	MV_U16  data;
+
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_DEC_LSB);
+
+	data =  MV_NETA_PMT_DEL_SKIP_B(skipBefore) |
+		MV_NETA_PMT_DEL_SKIP_A(skipAfter);
+
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/*******************************************************************************
+* mvNetaPmtDecMSB - Set PMT entry with "Decrement MSB" command
+*
+* INPUT:
+*       MV_U8   skipBefore  - number of shorts to be skipped before delete
+*       MV_U8   skipAfter   - number of shorts to be skipped after delete
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void        mvNetaPmtDecMSB(MV_NETA_PMT *pEntry, MV_U8 skipBefore, MV_U8 skipAfter)
+{
+	MV_U16  data;
+
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_DEC_MSB);
+
+	data =  MV_NETA_PMT_DEL_SKIP_B(skipBefore) |
+		MV_NETA_PMT_DEL_SKIP_A(skipAfter);
+
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/*******************************************************************************
+* mvNetaPmtReplaceIPv4csum - Set PMT entry with "Replace IP checksum" command
+*
+* INPUT:
+*       MV_U16   data
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void        mvNetaPmtReplaceIPv4csum(MV_NETA_PMT *pEntry, MV_U16 data)
+{
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_IPV4_CSUM);
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/*******************************************************************************
+* mvNetaPmtReplaceL4csum - Set PMT entry with "Replace TCP/UDP checksum" command
+*
+* INPUT:
+*       MV_U16   data
+*
+* OUTPUT:
+*       MV_NETA_PMT* pEntry - PMT entry to be set
+*
+* RETURN:   void
+*******************************************************************************/
+void        mvNetaPmtReplaceL4csum(MV_NETA_PMT *pEntry, MV_U16 data)
+{
+	MV_NETA_PMT_CMD_SET(pEntry, MV_NETA_CMD_L4_CSUM);
+	MV_NETA_PMT_DATA_SET(pEntry, data);
+}
+
+/**************************************************************/
+/* High level PMT configuration functions - multiple commands */
+/**************************************************************/
+
+/* Configure PMT to decrement TTL in IPv4 header - 2 entries */
+int     mvNetaPmtTtlDec(int port, int idx, int ip_offs, int isLast)
+{
+	MV_NETA_PMT     pmtEntry;
+
+	/* Skip to TTL and Decrement - Set flag for IP csum */
+	MV_NETA_PMT_CLEAR(&pmtEntry);
+	mvNetaPmtDecMSB(&pmtEntry, (ip_offs + 8)/2, 0);
+	mvNetaPmtFlags(&pmtEntry, 0, 1, 0);
+	mvNetaPmtWrite(port, idx, &pmtEntry);
+	idx++;
+
+	/* Update IP checksum */
+	MV_NETA_PMT_CLEAR(&pmtEntry);
+	mvNetaPmtReplaceIPv4csum(&pmtEntry, 0);
+	if (isLast)
+		mvNetaPmtLastFlag(&pmtEntry, 1);
+
+	mvNetaPmtWrite(port, idx, &pmtEntry);
+
+	return idx;
+}
+
+/* Configure PMT to replace bytes in the packet: minimum 2 bytes - 1 entry for each 2 bytes */
+int     mvNetaPmtDataReplace(int port, int idx, int offset,
+				 MV_U8 *data, int bytes, int isLast)
+{
+	int             i;
+	MV_U16          u16;
+	MV_NETA_PMT     pmtEntry;
+
+	if (offset > 0) {
+		/* Skip command first */
+		MV_NETA_PMT_CLEAR(&pmtEntry);
+		mvNetaPmtSkip(&pmtEntry, offset/2);
+		mvNetaPmtWrite(port, idx, &pmtEntry);
+		idx++;
+	}
+	for (i = 0; i < bytes; i += 2) {
+		/* Replace */
+		MV_NETA_PMT_CLEAR(&pmtEntry);
+		u16 = ((data[i] << 8) | data[i+1]);
+		mvNetaPmtReplace2Bytes(&pmtEntry, u16);
+		if (isLast && (i == bytes))
+			mvNetaPmtLastFlag(&pmtEntry, 1);
+
+		mvNetaPmtWrite(port, idx, &pmtEntry);
+		idx++;
+	}
+
+	return idx;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pmt/mvPmt.h b/arch/arm/plat-feroceon/mv_hal/neta/pmt/mvPmt.h
new file mode 100755
index 0000000..201cc23
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pmt/mvPmt.h
@@ -0,0 +1,262 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __mvPmt_h__
+#define __mvPmt_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "mvTypes.h"
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+#define PMT_TEXT    16
+
+#define PMT_PRINT_VALID_FLAG    0x01
+
+
+typedef union mv_neta_pmt_t {
+	MV_U32	word;
+
+} MV_NETA_PMT;
+
+#define MV_NETA_PMT_DATA_OFFS       0
+#define MV_NETA_PMT_DATA_BITS       16
+#define MV_NETA_PMT_DATA_MASK       (((1 << MV_NETA_PMT_DATA_BITS) - 1) << MV_NETA_PMT_DATA_OFFS)
+
+#define MV_NETA_PMT_CTRL_OFFS       16
+#define MV_NETA_PMT_CTRL_BITS       16
+#define MV_NETA_PMT_CTRL_MASK       (((1 << MV_NETA_PMT_CTRL_BITS) - 1) << MV_NETA_PMT_CTRL_OFFS)
+
+#define MV_NETA_PMT_CMD_OFFS        16
+#define MV_NETA_PMT_CMD_BITS        5
+#define MV_NETA_PMT_CMD_ALL_MASK    (((1 << MV_NETA_PMT_CMD_BITS) - 1) << MV_NETA_PMT_CMD_OFFS)
+#define MV_NETA_PMT_CMD_MASK(cmd)   ((cmd) << MV_NETA_PMT_CMD_OFFS)
+
+enum {
+    MV_NETA_CMD_NONE        = 0,
+    MV_NETA_CMD_ADD_2B,
+    MV_NETA_CMD_CFG_VLAN,
+    MV_NETA_CMD_ADD_VLAN,
+    MV_NETA_CMD_CFG_DSA_1,
+    MV_NETA_CMD_CFG_DSA_2,
+    MV_NETA_CMD_ADD_DSA,
+    MV_NETA_CMD_DEL_BYTES,
+    MV_NETA_CMD_REPLACE_2B,
+    MV_NETA_CMD_REPLACE_LSB,
+    MV_NETA_CMD_REPLACE_MSB,
+    MV_NETA_CMD_REPLACE_VLAN,
+    MV_NETA_CMD_DEC_LSB,
+    MV_NETA_CMD_DEC_MSB,
+    MV_NETA_CMD_ADD_CALC_LEN,
+    MV_NETA_CMD_REPLACE_LEN,
+    MV_NETA_CMD_IPV4_CSUM,
+    MV_NETA_CMD_L4_CSUM,
+    MV_NETA_CMD_SKIP,
+    MV_NETA_CMD_JUMP,
+    MV_NETA_CMD_JUMP_SKIP,
+    MV_NETA_CMD_JUMP_SUB,
+    MV_NETA_CMD_PPPOE,
+    MV_NETA_CMD_STORE,
+};
+
+#define MV_NETA_PMT_IP4_CSUM_BIT    21
+#define MV_NETA_PMT_IP4_CSUM_MASK   (1 << MV_NETA_PMT_IP4_CSUM_BIT)
+
+#define MV_NETA_PMT_L4_CSUM_BIT     22
+#define MV_NETA_PMT_L4_CSUM_MASK    (1 << MV_NETA_PMT_L4_CSUM_BIT)
+
+#define MV_NETA_PMT_LAST_BIT        23
+#define MV_NETA_PMT_LAST_MASK       (1 << MV_NETA_PMT_LAST_BIT)
+
+
+/*********** Command special defines ************/
+
+/* Bits for MV_NETA_CMD_DEL_BYTES command */
+/* [7:0] - number of words (2 bytes) to delete */
+#define MV_NETA_PMT_DEL_SHORTS_OFFS         0
+#define MV_NETA_PMT_DEL_SHORTS_MASK         (0xFF << MV_NETA_PMT_DEL_SHORTS_OFFS)
+#define MV_NETA_PMT_DEL_SHORTS(size)        (((size) << MV_NETA_PMT_DEL_SHORTS_OFFS) & MV_NETA_PMT_DEL_SHORTS_MASK)
+
+/* [11:8] - number of words (2 bytes) to skip before the delete command */
+#define MV_NETA_PMT_DEL_SKIP_B_OFFS         8
+#define MV_NETA_PMT_DEL_SKIP_B_MASK         (0xF << MV_NETA_PMT_DEL_SKIP_B_OFFS)
+#define MV_NETA_PMT_DEL_SKIP_B(size)        (((size) << MV_NETA_PMT_DEL_SKIP_B_OFFS) & MV_NETA_PMT_DEL_SKIP_B_MASK)
+
+/* [15:12] - number of words (2 bytes) to skip after the delete command */
+#define MV_NETA_PMT_DEL_SKIP_A_OFFS         12
+#define MV_NETA_PMT_DEL_SKIP_A_MASK         (0xF << MV_NETA_PMT_DEL_SKIP_A_OFFS)
+#define MV_NETA_PMT_DEL_SKIP_A(size)        (((size) << MV_NETA_PMT_DEL_SKIP_A_OFFS) & MV_NETA_PMT_DEL_SKIP_A_MASK)
+/*-----------------------------------------------------------------------------------------------------------------*/
+
+/* Bits for Add Calculated length operation */
+/* Used for commands: Add Calculated length, Replace length, Skip, */
+#define MV_NETA_PMT_ZERO_ADD                0
+#define MV_NETA_PMT_DATA_ADD                2
+#define MV_NETA_PMT_DATA_SUB                3
+
+#define MV_NETA_PMT_CALC_LEN_0_OFFS         14
+#define MV_NETA_PMT_CALC_LEN_0_MASK         (3 << MV_NETA_PMT_CALC_LEN_0_OFFS)
+#define MV_NETA_PMT_CALC_LEN_0_ZERO         (0 << MV_NETA_PMT_CALC_LEN_0_OFFS)
+#define MV_NETA_PMT_CALC_LEN_0_TX_DESC      (1 << MV_NETA_PMT_CALC_LEN_0_OFFS)
+#define MV_NETA_PMT_CALC_LEN_0_TX_PKT       (2 << MV_NETA_PMT_CALC_LEN_0_OFFS)
+#define MV_NETA_PMT_CALC_LEN_0_STORE        (3 << MV_NETA_PMT_CALC_LEN_0_OFFS)
+
+#define MV_NETA_PMT_CALC_LEN_1_OFFS         12
+#define MV_NETA_PMT_CALC_LEN_1_MASK         (3 << MV_NETA_PMT_CALC_LEN_1_OFFS)
+#define MV_NETA_PMT_CALC_LEN_1(op)          ((op) << MV_NETA_PMT_CALC_LEN_1_OFFS)
+
+#define MV_NETA_PMT_CALC_LEN_2_OFFS         10
+#define MV_NETA_PMT_CALC_LEN_2_MASK         (3 << MV_NETA_PMT_CALC_LEN_2_OFFS)
+#define MV_NETA_PMT_CALC_LEN_2(op)          ((op) << MV_NETA_PMT_CALC_LEN_2_OFFS)
+
+#define MV_NETA_PMT_CALC_LEN_3_BIT          9
+#define MV_NETA_PMT_CALC_LEN_3_ADD_MASK     (0 << MV_NETA_PMT_CALC_LEN_3_BIT)
+#define MV_NETA_PMT_CALC_LEN_3_SUB_MASK     (1 << MV_NETA_PMT_CALC_LEN_3_BIT)
+
+#define MV_NETA_PMT_CALC_LEN_DATA_OFFS      0
+#define MV_NETA_PMT_CALC_LEN_DATA_MASK      (0x1FF << MV_NETA_PMT_CALC_LEN_DATA_OFFS)
+#define MV_NETA_PMT_CALC_LEN_DATA(data)     ((data) << MV_NETA_PMT_CALC_LEN_DATA_OFFS)
+/*-----------------------------------------------------------------------------------------------------------------*/
+
+/* Bits for MV_NETA_CMD_DEC_LSB and MV_NETA_CMD_DEC_MSB commands */
+#define MV_NETA_PMT_DEC_SKIP_A_OFFS         0
+#define MV_NETA_PMT_DEC_SKIP_A_MASK         (0xFF << MV_NETA_PMT_DEC_SKIP_A_OFFS)
+#define MV_NETA_PMT_DEC_SKIP_A(size)        (((size) << MV_NETA_PMT_DEC_SKIP_A_OFFS) & MV_NETA_PMT_DEC_SKIP_A_MASK)
+
+#define MV_NETA_PMT_DEC_SKIP_B_OFFS         8
+#define MV_NETA_PMT_DEC_SKIP_B_MASK         (0xFF << MV_NETA_PMT_DEC_SKIP_B_OFFS)
+#define MV_NETA_PMT_DEC_SKIP_B(size)        (((size) << MV_NETA_PMT_DEC_SKIP_B_OFFS) & MV_NETA_PMT_DEC_SKIP_B_MASK)
+/*-----------------------------------------------------------------------------------------------------------------*/
+
+#define MV_NETA_PMT_CLEAR(pmt)          \
+		(pmt)->word = 0;
+
+#define MV_NETA_PMT_IS_VALID(pmt)        \
+		((((pmt)->word & MV_NETA_PMT_CMD_ALL_MASK) >> MV_NETA_PMT_CMD_OFFS) != MV_NETA_CMD_NONE)
+
+#define MV_NETA_PMT_INVALID_SET(pmt)        \
+		((pmt)->word = MV_NETA_PMT_CMD_MASK(MV_NETA_CMD_NONE) | MV_NETA_PMT_LAST_MASK);
+
+#define MV_NETA_PMT_CTRL_GET(pmt)           \
+		(MV_U16)(((pmt)->word & MV_NETA_PMT_CTRL_MASK) >> MV_NETA_PMT_CTRL_OFFS)
+
+#define MV_NETA_PMT_CMD_GET(pmt)           \
+		(((pmt)->word & MV_NETA_PMT_CMD_ALL_MASK) >> MV_NETA_PMT_CMD_OFFS)
+
+#define MV_NETA_PMT_DATA_GET(pmt)           \
+		(MV_U16)(((pmt)->word & MV_NETA_PMT_DATA_MASK) >> MV_NETA_PMT_DATA_OFFS)
+
+#define MV_NETA_PMT_CMD_SET(pmt, cmd)                       \
+		(pmt)->word &= ~MV_NETA_PMT_CMD_ALL_MASK;       \
+		(pmt)->word |= MV_NETA_PMT_CMD_MASK(cmd);
+
+#define MV_NETA_PMT_DATA_SET(pmt, data)                         \
+		(pmt)->word &= ~MV_NETA_PMT_DATA_MASK;              \
+		(pmt)->word |= ((data) << MV_NETA_PMT_DATA_OFFS);
+
+
+MV_STATUS   mvNetaPmtWrite(int port, int idx, MV_NETA_PMT *pEntry);
+MV_STATUS   mvNetaPmtRead(int port, int idx, MV_NETA_PMT *pEntry);
+MV_STATUS   mvNetaPmtClear(int port);
+MV_STATUS   mvNetaPmtInit(int port, MV_NETA_PMT *pBase);
+MV_VOID	    mvNetaPmtDestroy(MV_VOID);
+MV_VOID	    mvNetaPmtDump(int port, int flags);
+MV_VOID        mvNetaPmtRegs(int port, int txp);
+
+MV_VOID        mvNetaPmtEntryPrint(MV_NETA_PMT *pEntry);
+
+MV_VOID        mvNetaPmtAdd2Bytes(MV_NETA_PMT *pEntry, MV_U16 data);
+MV_VOID        mvNetaPmtReplace2Bytes(MV_NETA_PMT *pEntry, MV_U16 data);
+MV_VOID        mvNetaPmtDelShorts(MV_NETA_PMT *pEntry, MV_U8 bDelete,
+				MV_U8 skipBefore, MV_U8 skipAfter);
+MV_VOID        mvNetaPmtReplaceLSB(MV_NETA_PMT *pEntry, MV_U8 value, MV_U8 mask);
+MV_VOID        mvNetaPmtReplaceMSB(MV_NETA_PMT *pEntry, MV_U8 value, MV_U8 mask);
+
+MV_VOID        mvNetaPmtDecLSB(MV_NETA_PMT *pEntry, MV_U8 skipBefore, MV_U8 skipAfter);
+MV_VOID        mvNetaPmtDecMSB(MV_NETA_PMT *pEntry, MV_U8 skipBefore, MV_U8 skipAfter);
+
+MV_VOID        mvNetaPmtLastFlag(MV_NETA_PMT *pEntry, int last);
+MV_VOID        mvNetaPmtFlags(MV_NETA_PMT *pEntry, int last, int ipv4, int l4);
+MV_VOID        mvNetaPmtSkip(MV_NETA_PMT *pEntry, MV_U16 shorts);
+MV_VOID        mvNetaPmtReplaceIPv4csum(MV_NETA_PMT *pEntry, MV_U16 data);
+MV_VOID        mvNetaPmtReplaceL4csum(MV_NETA_PMT *pEntry, MV_U16 data);
+MV_VOID        mvNetaPmtJump(MV_NETA_PMT *pEntry, MV_U16 target, int type, int cond);
+
+/* High level PMT configurations */
+int         mvNetaPmtTtlDec(int port, int idx, int ip_offs, int isLast);
+int         mvNetaPmtDataReplace(int port, int idx, int offset,
+				 MV_U8 *data, int bytes, int isLast);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __mvPmt_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPnc.c b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPnc.c
new file mode 100755
index 0000000..cd6dbe3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPnc.c
@@ -0,0 +1,1559 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvOs.h"
+#include "mvCommon.h"
+#include "mv802_3.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#include "gbe/mvNetaRegs.h"
+#include "gbe/mvEthRegs.h"
+
+#include "mvPnc.h"
+#include "mvTcam.h"
+
+/*
+ * PNC debug
+ */
+/*#define PNC_DBG mvOsPrintf*/
+#define PNC_DBG(X...)
+
+/*
+ * PNC errors
+ */
+#define PNC_ERR mvOsPrintf
+/*#define PNC_ERR(X...)*/
+
+/*
+ * Local variables
+ */
+static int   pnc_inited = 0;
+static int rxq_mac_bc = CONFIG_MV_ETH_RXQ_DEF;
+static int rxq_mac_mc = CONFIG_MV_ETH_RXQ_DEF;
+static int rxq_vlan = CONFIG_MV_ETH_RXQ_DEF;
+static int rxq_ip6 = CONFIG_MV_ETH_RXQ_DEF;
+static int rxq_ip4 = CONFIG_MV_ETH_RXQ_DEF;
+static int rxq_ip4_tcp = CONFIG_MV_ETH_RXQ_DEF;
+static int rxq_ip4_udp = CONFIG_MV_ETH_RXQ_DEF;
+static int rxq_arp 		= CONFIG_MV_ETH_RXQ_DEF;
+
+
+#ifdef CONFIG_ARCH_FEROCEON_KW2
+int pnc_port_map(int pnc_port)
+{
+	switch (pnc_port) {
+	case 2:
+		return 0;
+
+	case 4:
+		return 1;
+
+	case 0:
+		return 2;
+
+	default:
+		mvOsPrintf("%s: pnc_port=%d is out of range\n", __func__, pnc_port);
+		return -1;
+	}
+}
+
+int pnc_eth_port_map(int eth_port)
+{
+	switch (eth_port) {
+	case 0:
+		return 2;
+
+	case 1:
+		return 4;
+
+	case 2:
+		return 0;
+
+	default:
+		mvOsPrintf("%s: eth_port=%d is out of range\n", __func__, eth_port);
+		return -1;
+	}
+}
+#else /* CONFIG_ARCH_ARMADA_XP */
+int pnc_port_map(int pnc_port)
+{
+	switch (pnc_port) {
+	case 0:
+	case 1:
+		return 0;
+
+	case 4:
+		return 1;
+
+	case 2:
+		return 2;
+
+	case 3:
+		return 3;
+
+	default:
+		mvOsPrintf("%s: pnc_port=%d is out of range\n", __func__, pnc_port);
+		return -1;
+	}
+}
+
+int pnc_eth_port_map(int eth_port)
+{
+	switch (eth_port) {
+	case 0:
+		return 0;
+
+	case 1:
+		return 4;
+
+	case 2:
+		return 2;
+
+	case 3:
+		return 3;
+
+	default:
+		mvOsPrintf("%s: eth_port=%d is out of range\n", __func__, eth_port);
+		return -1;
+	}
+}
+#endif /* MV_ETH_PNC_NEW */
+
+int pnc_te_del(unsigned int tid)
+{
+	PNC_DBG("%s [%d]\n", __func__, tid);
+
+	tcam_hw_inv(tid);
+
+	return 0;
+}
+
+/* pnc port setting: data: 0 for all bits, mask: 0 - for accepted ports, 1 - for rejected ports */
+int pnc_port_mask_check(unsigned int mask, int eth_port)
+{
+	int pnc_port = pnc_eth_port_map(eth_port);
+
+	if (pnc_port < 0)
+		return 0;
+
+	if (mask & (1 << pnc_port))
+		return 0;
+
+	return 1;
+}
+
+unsigned int pnc_port_mask_update(unsigned int mask, int eth_port, int add)
+{
+	int pnc_port = pnc_eth_port_map(eth_port);
+
+	if (pnc_port < 0)
+		return mask;
+
+	if (add)
+		mask &= ~(1 << pnc_port);
+	else
+		mask |= (1 << pnc_port);
+
+	return mask;
+}
+
+unsigned int pnc_port_mask(int eth_port)
+{
+	unsigned int mask;
+	int pnc_port = pnc_eth_port_map(eth_port);
+
+	if (pnc_port < 0)
+		return 0;
+
+	mask = (~(1 << pnc_port)) & PORT_MASK;
+	return mask;
+}
+
+/* Get TCAM entry if valid, NULL if invalid */
+struct tcam_entry *pnc_tcam_entry_get(int tid)
+{
+	struct tcam_entry *te;
+
+	te = tcam_sw_alloc(0);
+
+	tcam_hw_read(te, tid);
+
+	if (te->ctrl.flags & TCAM_F_INV) {
+		tcam_sw_free(te);
+		return NULL;
+	}
+	return te;
+}
+
+int pnc_tcam_port_update(int tid, int eth_port, int add)
+{
+	struct tcam_entry *te;
+	unsigned int data, mask;
+
+	te = pnc_tcam_entry_get(tid);
+	if (te == NULL) {
+		mvOsPrintf("%s: TCAM entry #%d is invalid\n", __func__, tid);
+		return -1;
+	}
+	tcam_sw_get_port(te, &data, &mask);
+	mask = pnc_port_mask_update(mask, eth_port, add);
+	tcam_sw_set_port(te, data, mask);
+	tcam_hw_write(te, tid);
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * MAC Address Section
+ *
+ ******************************************************************************
+ */
+
+/*
+ * pnc_mac_fc_drop - Add Flow Control MAC address match rule to the MAC section
+ * to drop PAUSE frames arriving without Marvell Header on all ports
+ */
+static void pnc_mac_fc_drop(void)
+{
+	struct tcam_entry *te = NULL;
+	unsigned char da[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x01 };
+	unsigned int len = MV_MAC_ADDR_SIZE;
+
+	te = tcam_sw_alloc(TCAM_LU_MAC);
+
+	/* set match on DA */
+	while (len--)
+		tcam_sw_set_byte(te, len, da[len]);
+
+	/* port id match */
+	tcam_sw_set_port(te, 0, 0);	/* all ports */
+
+	/* result info bit */
+	sram_sw_set_rinfo(te, RI_DROP, RI_DROP);
+
+	tcam_sw_text(te, "flow control");
+	sram_sw_set_lookup_done(te, 1);
+
+	tcam_hw_write(te, TE_MAC_FLOW_CTRL);
+	tcam_sw_free(te);
+}
+
+/*
+ * pnc_mac_da - Add DA MAC address match rule to the MAC section
+ * @da: destination MAC address
+ * @len: destination MAC address length to match on: 0..6
+ * @port_mask: source port id: 0..1F or ANY
+ * @rxq: rx queue
+ * @rinfo: result info bits to set
+ */
+static struct tcam_entry *pnc_mac_da(unsigned char *da, unsigned int len,
+				     unsigned int port_mask, int rxq, unsigned int rinfo)
+{
+	struct tcam_entry *te = NULL;
+
+	if (len > MV_MAC_ADDR_SIZE)
+		goto out;
+
+	if (rinfo >= BIT24)
+		goto out;
+
+	te = tcam_sw_alloc(TCAM_LU_MAC);
+
+	/* set match on DA */
+	while (len--)
+		tcam_sw_set_byte(te, MV_ETH_MH_SIZE + len, da[len]);
+
+	/* port id match */
+	tcam_sw_set_port(te, 0, port_mask);
+
+	/* result info bit */
+	sram_sw_set_rinfo(te, rinfo, rinfo);
+
+	/* set rx queue */
+	sram_sw_set_rxq(te, rxq, 0);
+
+	/* shift to ethertype */
+	sram_sw_set_shift_update(te, 0, MV_ETH_MH_SIZE + 2 * MV_MAC_ADDR_SIZE);
+	sram_sw_set_next_lookup(te, TCAM_LU_L2);
+out:
+	return te;
+}
+
+/*
+ * pnc_mac_me - Add DA MAC address of port
+ * @mac: destination MAC address or NULL for promiscuous
+ * @port: ingress giga port number
+ */
+int pnc_mac_me(unsigned int port, unsigned char *mac, int rxq)
+{
+	struct tcam_entry *te;
+	int len = MV_MAC_ADDR_SIZE;
+	char text[TCAM_TEXT];
+	unsigned int port_mask = pnc_port_mask(port);
+
+	if (port_mask < 0)
+		return 1;
+
+	if (!mac)
+		len = 0;
+
+	te = pnc_mac_da(mac, len, port_mask, rxq, RI_DA_ME);
+	sprintf(text, "%s%d", "ucast_me", port);
+	tcam_sw_text(te, text);
+
+	tcam_hw_write(te, TE_MAC_ME + port);
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+/*
+ * pnc_mcast_all - Accept all MAC multicast of port
+ * @port: ingress giga port number.
+ * @en: 1 - Accept ALL MCAST, 0 - Discard ALL MCAST
+ */
+int pnc_mcast_all(unsigned int port, int en)
+{
+	struct tcam_entry *te;
+	unsigned int data, mask;
+
+	te = pnc_tcam_entry_get(TE_MAC_MC_ALL);
+	if (te == NULL) {
+		mvOsPrintf("%s: MC_ALL entry (tid=%d) is invalid\n", __func__, TE_MAC_MC_ALL);
+		return 1;
+	}
+
+	/* Update port mask */
+	tcam_sw_get_port(te, &data, &mask);
+	mask = pnc_port_mask_update(mask, port, en);
+
+	tcam_sw_set_port(te, data, mask);
+	tcam_sw_text(te, "mcast_all");
+
+	tcam_hw_write(te, TE_MAC_MC_ALL);
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+/*
+ * pnc_mcast_me - Add DA MAC address of port
+ * @mac: Multicast MAC DA or NULL to delete all Multicast DAs for this port
+ * @port: ingress giga port number
+ */
+int pnc_mcast_me(unsigned int port, unsigned char *mac)
+{
+	struct tcam_entry *te;
+	int tid, empty = -1;
+	unsigned int data, mask;
+
+	if (mac == NULL) {
+		/* Delete all Multicast addresses for this port */
+		for (tid = (TE_MAC_MC_ALL + 1); tid <= TE_MAC_MC_L; tid++) {
+			/* Check TCAM entry */
+			te = pnc_tcam_entry_get(tid);
+			if (te != NULL) {
+				/* delete entry if belong specific port */
+				tcam_sw_get_port(te, &data, &mask);
+				mask = pnc_port_mask_update(mask, port, 0);
+				if (mask == PORT_MASK) {	/* No valid ports */
+					tcam_hw_inv(tid);
+				} else {
+					tcam_sw_set_port(te, data, mask);
+					tcam_hw_write(te, tid);
+				}
+				tcam_sw_free(te);
+			}
+		}
+		return 0;
+	}
+
+	/* Add new Multicast DA for this port */
+	for (tid = (TE_MAC_MC_ALL + 1); tid <= TE_MAC_MC_L; tid++) {
+		te = pnc_tcam_entry_get(tid);
+
+		/* Remember first Empty entry */
+		if (te == NULL) {
+			if (empty == -1)
+				empty = tid;
+
+			continue;
+		}
+
+		/* Find existing TCAM entry with this DA */
+		if (tcam_sw_cmp_bytes(te, MV_ETH_MH_SIZE, MV_MAC_ADDR_SIZE, mac) == 0) {
+			/* check and update port mask */
+			tcam_sw_get_port(te, &data, &mask);
+			mask = pnc_port_mask_update(mask, port, 1);
+			tcam_sw_set_port(te, data, mask);
+
+			tcam_hw_write(te, tid);
+			tcam_sw_free(te);
+			return 0;
+		}
+		tcam_sw_free(te);
+	}
+
+	/* Not found existing entry and no free TCAM entry - Failed */
+	if (empty == -1)
+		return 1;
+
+	/* Not found existing entry - add to free TCAM entry */
+	te = pnc_mac_da(mac, MV_MAC_ADDR_SIZE, pnc_port_mask(port), rxq_mac_mc, RI_DA_MC);
+	tcam_sw_text(te, "mcast_me");
+
+	tcam_hw_write(te, empty);
+	tcam_sw_free(te);
+	return 0;
+}
+
+/*
+ * pnc_mac_init - GE init phase configuration
+ */
+static int pnc_mac_init(void)
+{
+	struct tcam_entry *te;
+	unsigned char da_mc[6] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	unsigned char da_bc[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	PNC_DBG("%s\n", __func__);
+
+	/* broadcast - for all ports */
+	te = pnc_mac_da(da_bc, 6, 0, rxq_mac_bc, RI_DA_BC);
+	tcam_sw_text(te, "bcast");
+
+	tcam_hw_write(te, TE_MAC_BC);
+	tcam_sw_free(te);
+
+	/* flow control PAUSE frames - discard for all ports by default */
+	pnc_mac_fc_drop();
+
+	/* All Multicast - no ports by default */
+	te = pnc_mac_da(da_mc, 1, PORT_MASK, rxq_mac_mc, RI_DA_MC);
+	tcam_sw_text(te, "mcast_all");
+
+	tcam_hw_write(te, TE_MAC_MC_ALL);
+	tcam_sw_free(te);
+
+	/* end of section */
+	te = tcam_sw_alloc(TCAM_LU_MAC);
+	sram_sw_set_flowid(te, FLOWID_EOF_LU_MAC, FLOWID_CTRL_LOW_HALF_MASK);
+
+	/* Non-promiscous mode - DROP unknown packets */
+	sram_sw_set_rinfo(te, RI_DROP, RI_DROP);
+	sram_sw_set_lookup_done(te, 1);
+	tcam_sw_text(te, "mac_eof");
+
+	tcam_hw_write(te, TE_MAC_EOF);
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * L2 Section
+ *
+ ******************************************************************************
+ */
+
+/*
+ * Helper: match ethertype
+ */
+static void pnc_match_etype(struct tcam_entry *te, unsigned short ethertype)
+{
+	tcam_sw_set_byte(te, 0, ethertype >> 8);
+	tcam_sw_set_byte(te, 1, ethertype & 0xFF);
+}
+
+/* Set VLAN priority entry */
+int pnc_vlan_prio_set(int port, int prio, int rxq)
+{
+#if (CONFIG_MV_ETH_PNC_VLAN_PRIO > 0)
+	struct tcam_entry *te;
+	unsigned int pdata, pmask;
+	int q, tid, empty = -1;
+
+	PNC_DBG("%s\n", __func__);
+
+	/* check validity */
+	if ((prio < 0) || (prio > 7))
+		return 1;
+
+	if ((rxq < -1) || (rxq > CONFIG_MV_ETH_RXQ))
+		return 1;
+
+	/* Find match TCAM entry */
+	for (tid = TE_VLAN_PRIO; tid <= TE_VLAN_PRIO_END; tid++) {
+		te = pnc_tcam_entry_get(tid);
+		/* Remember first Empty entry */
+		if (te == NULL) {
+			if (empty == -1)
+				empty = tid;
+			continue;
+		}
+		/* find VLAN entry with the same priority */
+		if (tcam_sw_cmp_byte(te, 2, ((unsigned char)prio << 5)) == 0) {
+			tcam_sw_get_port(te, &pdata, &pmask);
+			if (rxq == -1) {
+				if (!pnc_port_mask_check(pmask, port)) {
+					tcam_sw_free(te);
+					continue;
+				}
+				pmask = pnc_port_mask_update(pmask, port, 0);
+				if (pmask == PORT_MASK) {	/* No valid ports */
+					tcam_hw_inv(tid);
+				} else {
+					tcam_sw_set_port(te, pdata, pmask);
+					tcam_hw_write(te, tid);
+				}
+			} else {
+				q = sram_sw_get_rxq(te, NULL);
+				if (rxq == q) {
+					/* Add port to this entry */
+					pmask = pnc_port_mask_update(pmask, port, 1);
+					tcam_sw_set_port(te, pdata, pmask);
+					tcam_hw_write(te, tid);
+				} else {
+					/* Update RXQ */
+					pmask = pnc_port_mask_update(pmask, port, 0);
+					if (pmask == PORT_MASK) {
+						/* No valid ports - use the same entry */
+						pmask = pnc_port_mask_update(pmask, port, 1);
+						tcam_sw_set_port(te, pdata, pmask);
+						sram_sw_set_rxq(te, rxq, 0);
+						tcam_hw_write(te, tid);
+						tcam_sw_free(te);
+					} else {
+						tcam_sw_free(te);
+						continue;
+					}
+				}
+			}
+			tcam_sw_free(te);
+			return 0;
+		}
+		tcam_sw_free(te);
+	}
+	if (rxq == -1) {
+		mvOsPrintf("%s: Entry not found - vprio=%d, rxq=%d\n",
+					__func__, prio, rxq);
+		return 1;
+	}
+
+	/* Not found existing entry and no free TCAM entry - Failed */
+	if (empty == -1) {
+		mvOsPrintf("%s: No free place - vprio=%d, rxq=%d\n",
+					__func__, prio, rxq);
+		return 1;
+	}
+
+	/* Not found existing entry - add to free TCAM entry */
+	te = tcam_sw_alloc(TCAM_LU_L2);
+	pnc_match_etype(te, MV_VLAN_TYPE);
+	tcam_sw_set_byte(te, 2, prio << 5);
+	tcam_sw_set_mask(te, 2, 7 << 5);
+	tcam_sw_text(te, "vlan_prio");
+
+	sram_sw_set_rinfo(te, RI_VLAN, RI_VLAN);
+	sram_sw_set_next_lookup(te, TCAM_LU_L2);
+	sram_sw_set_shift_update(te, 0, MV_VLAN_HLEN);
+	sram_sw_set_rxq(te, rxq, 0);
+
+	/* single port mask */
+	pmask = pnc_port_mask(port);
+	tcam_sw_set_port(te, 0, pmask);
+
+	tcam_sw_text(te, "vlan_prio");
+
+	tcam_hw_write(te, empty);
+	tcam_sw_free(te);
+
+	return 0;
+#else
+	return -1;
+#endif /* CONFIG_MV_ETH_PNC_VLAN_PRIO > 0 */
+}
+
+int pnc_vlan_init(void)
+{
+	struct tcam_entry *te;
+	int tid;
+
+	PNC_DBG("%s\n", __func__);
+
+	/* Set default VLAN entry */
+	tid = TE_VLAN_EOF;
+	te = tcam_sw_alloc(TCAM_LU_L2);
+	pnc_match_etype(te, MV_VLAN_TYPE);
+	tcam_sw_set_mask(te, 2, 0);
+	tcam_sw_text(te, "vlan_def");
+
+	sram_sw_set_rxq(te, rxq_vlan, 0);
+
+	sram_sw_set_rinfo(te, RI_VLAN, RI_VLAN);
+	sram_sw_set_next_lookup(te, TCAM_LU_L2);
+	sram_sw_set_shift_update(te, 0, MV_VLAN_HLEN);
+
+	tcam_hw_write(te, tid);
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * Ethertype Section
+ *
+ ******************************************************************************
+ */
+/* match arp */
+void pnc_etype_arp(int rxq)
+{
+	struct tcam_entry *te;
+
+	rxq_arp = rxq;
+	te = tcam_sw_alloc(TCAM_LU_L2);
+	pnc_match_etype(te, MV_IP_ARP_TYPE);
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_rxq(te, rxq_arp, 0);
+	tcam_sw_text(te, "etype_arp");
+
+	tcam_hw_write(te, TE_ETYPE_ARP);
+	tcam_sw_free(te);
+}
+
+/* match ip4 */
+static void pnc_etype_ip4(void)
+{
+	struct tcam_entry *te;
+
+	te = tcam_sw_alloc(TCAM_LU_L2);
+	pnc_match_etype(te, MV_IP_TYPE);
+	sram_sw_set_shift_update(te, 0, MV_ETH_TYPE_LEN);
+	sram_sw_set_next_lookup(te, TCAM_LU_IP4);
+	tcam_sw_text(te, "etype_ipv4");
+
+	tcam_hw_write(te, TE_ETYPE_IP4);
+	tcam_sw_free(te);
+}
+
+/* match ip6 */
+static void pnc_etype_ip6(void)
+{
+	struct tcam_entry *te;
+
+	te = tcam_sw_alloc(TCAM_LU_L2);
+	pnc_match_etype(te, MV_IP6_TYPE);
+	sram_sw_set_shift_update(te, 0, MV_ETH_TYPE_LEN);
+	sram_sw_set_next_lookup(te, TCAM_LU_IP6);
+	tcam_sw_text(te, "etype_ipv6");
+
+	tcam_hw_write(te, TE_ETYPE_IP6);
+	tcam_sw_free(te);
+}
+
+/* match pppoe */
+static void pnc_etype_pppoe(void)
+{
+	struct tcam_entry *te;
+
+	/* IPv4 over PPPoE */
+	te = tcam_sw_alloc(TCAM_LU_L2);
+	pnc_match_etype(te, MV_PPPOE_TYPE);
+	tcam_sw_set_byte(te, MV_PPPOE_HDR_SIZE, 0x00);
+	tcam_sw_set_byte(te, MV_PPPOE_HDR_SIZE + 1, 0x21);
+
+	sram_sw_set_shift_update(te, 0, MV_ETH_TYPE_LEN + MV_PPPOE_HDR_SIZE);
+	sram_sw_set_next_lookup(te, TCAM_LU_IP4);
+	sram_sw_set_rinfo(te, RI_PPPOE, RI_PPPOE);
+	tcam_sw_text(te, "pppoe_ip4");
+
+	tcam_hw_write(te, TE_PPPOE_IP4);
+	tcam_sw_free(te);
+
+	/* IPv6 over PPPoE */
+	te = tcam_sw_alloc(TCAM_LU_L2);
+	pnc_match_etype(te, MV_PPPOE_TYPE);
+
+	tcam_sw_set_byte(te, MV_PPPOE_HDR_SIZE, 0x00);
+	tcam_sw_set_byte(te, MV_PPPOE_HDR_SIZE + 1, 0x57);
+
+	sram_sw_set_shift_update(te, 0, MV_ETH_TYPE_LEN + MV_PPPOE_HDR_SIZE);
+	sram_sw_set_next_lookup(te, TCAM_LU_IP6);
+	sram_sw_set_rinfo(te, RI_PPPOE, RI_PPPOE);
+	tcam_sw_text(te, "pppoe_ip6");
+
+	tcam_hw_write(te, TE_PPPOE_IP6);
+	tcam_sw_free(te);
+}
+
+/*
+ * pnc_etype_init - match basic ethertypes
+ */
+static int pnc_etype_init(void)
+{
+	struct tcam_entry *te;
+	int tid;
+
+	PNC_DBG("%s\n", __func__);
+
+	pnc_etype_arp(CONFIG_MV_ETH_RXQ_DEF);
+	pnc_etype_ip4();
+	pnc_etype_ip6();
+	pnc_etype_pppoe();
+
+	/* add custom ethertypes here */
+	tid = TE_ETYPE;
+
+	ERR_ON_OOR(--tid >= TE_ETYPE_EOF);
+
+	/* end of section */
+	te = tcam_sw_alloc(TCAM_LU_L2);
+	sram_sw_set_flowid(te, FLOWID_EOF_LU_L2, FLOWID_CTRL_LOW_HALF_MASK);
+	sram_sw_set_rxq(te, CONFIG_MV_ETH_RXQ_DEF, 0);
+	sram_sw_set_lookup_done(te, 1);
+	tcam_sw_text(te, "etype_eof");
+
+	tcam_hw_write(te, TE_ETYPE_EOF);
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * IPv4 Section
+ *
+ ******************************************************************************
+ */
+
+static void pnc_ip4_flow_next_lookup_set(struct tcam_entry *te)
+{
+#ifdef CONFIG_MV_ETH_PNC_L3_FLOW
+	sram_sw_set_next_lookup(te, TCAM_LU_FLOW_IP4);
+#else
+	sram_sw_set_next_lookup(te, TCAM_LU_L4);
+#endif /* CONFIG_MV_ETH_PNC_L3_FLOW */
+}
+
+/*
+ * pnc_ip4_tos - Add TOS prioroty rules
+ */
+int pnc_ip4_dscp(int port, unsigned char dscp, unsigned char mask, int rxq)
+{
+#if (CONFIG_MV_ETH_PNC_DSCP_PRIO > 0)
+	struct tcam_entry *te;
+	unsigned int pdata, pmask;
+	int tid, q, empty = -1;
+
+	if ((rxq < -1) || (rxq > CONFIG_MV_ETH_RXQ))
+		return 1;
+
+	for (tid = TE_IP4_DSCP; tid <= TE_IP4_DSCP_END; tid++) {
+		PNC_DBG("%s: tid=%d, dscp=0x%02x, mask=0x%02x, rxq=%d\n", __func__, tid, dscp, mask, rxq);
+
+		te = pnc_tcam_entry_get(tid);
+		/* Remember first Empty entry */
+		if (te == NULL) {
+			if (empty == -1)
+				empty = tid;
+			continue;
+		}
+		/* Find existing entry for this TOS */
+		if (tcam_sw_cmp_bytes(te, 1, 1, &dscp) == 0) {
+			tcam_sw_get_port(te, &pdata, &pmask);
+			if (rxq == -1) {
+				if (!pnc_port_mask_check(pmask, port)) {
+					tcam_sw_free(te);
+					continue;
+				}
+				pmask = pnc_port_mask_update(pmask, port, 0);
+				if (pmask == PORT_MASK) {	/* No valid ports */
+					tcam_hw_inv(tid);
+				} else {
+					tcam_sw_set_port(te, pdata, pmask);
+					tcam_hw_write(te, tid);
+				}
+			} else {
+				q = sram_sw_get_rxq(te, NULL);
+				if (rxq == q) {
+					/* Add port to this entry */
+					pmask = pnc_port_mask_update(pmask, port, 1);
+					tcam_sw_set_port(te, pdata, pmask);
+					tcam_hw_write(te, tid);
+				} else {
+					/* Update RXQ */
+					pmask = pnc_port_mask_update(pmask, port, 0);
+					if (pmask == PORT_MASK) {
+						/* No valid ports - use the same entry */
+						pmask = pnc_port_mask_update(pmask, port, 1);
+						tcam_sw_set_port(te, pdata, pmask);
+						sram_sw_set_rxq(te, rxq, 0);
+						tcam_hw_write(te, tid);
+					} else {
+						tcam_sw_free(te);
+						continue;
+					}
+				}
+			}
+			tcam_sw_free(te);
+			return 0;
+		}
+		tcam_sw_free(te);
+	}
+
+	if (rxq == -1) {
+		mvOsPrintf("%s: Entry not found - tos=0x%x, rxq=%d\n",
+					__func__, dscp, rxq);
+		return 1;
+	}
+
+	/* Not found existing entry and no free TCAM entry - Failed */
+	if (empty == -1) {
+		mvOsPrintf("%s: No free place - tos=0x%x, rxq=%d\n",
+					__func__, dscp, rxq);
+		return 1;
+	}
+
+	/* Not found existing entry - add to free TCAM entry */
+	te = tcam_sw_alloc(TCAM_LU_IP4);
+	tcam_sw_set_byte(te, 1, (MV_U8) dscp);
+	tcam_sw_set_mask(te, 1, (MV_U8) mask);
+	sram_sw_set_rxq(te, rxq, 0);
+	pmask = pnc_port_mask(port);
+	tcam_sw_set_port(te, 0, pmask);
+	sram_sw_set_next_lookup(te, TCAM_LU_IP4);
+	tcam_sw_set_ainfo(te, 0, AI_DONE_MASK);
+	sram_sw_set_ainfo(te, AI_DONE_MASK, AI_DONE_MASK);
+
+	tcam_sw_text(te, "ipv4_tos");
+
+	tcam_hw_write(te, empty);
+	tcam_sw_free(te);
+	return 0;
+#else
+	return -1;
+#endif /* (CONFIG_MV_ETH_PNC_DSCP_PRIO > 0) */
+}
+
+
+/* IPv4/TCP header parsing for fragmentation and L4 offset.  */
+void pnc_ip4_tcp(int rxq)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s\n", __func__);
+	rxq_ip4_tcp = rxq;
+
+	/* TCP, FRAG=0 normal */
+	te = tcam_sw_alloc(TCAM_LU_IP4);
+	tcam_sw_set_byte(te, 9, MV_IP_PROTO_TCP);
+	tcam_sw_set_byte(te, 6, 0x00);
+	tcam_sw_set_mask(te, 6, 0x3F);
+	tcam_sw_set_byte(te, 7, 0x00);
+	tcam_sw_set_mask(te, 7, 0xFF);
+	sram_sw_set_shift_update(te, 1, SHIFT_IP4_HLEN);
+	sram_sw_set_rinfo(te, (RI_L3_IP4 | RI_L4_TCP), (RI_L3_IP4 | RI_L4_TCP));
+	sram_sw_set_rxq(te, rxq_ip4_tcp, 0);
+	sram_sw_set_ainfo(te, 0, AI_DONE_MASK);
+	pnc_ip4_flow_next_lookup_set(te);
+
+	tcam_sw_text(te, "ipv4_tcp");
+
+	tcam_hw_write(te, TE_IP4_TCP);
+	tcam_sw_free(te);
+
+	/* TCP, FRAG=1 any */
+	te = tcam_sw_alloc(TCAM_LU_IP4);
+	tcam_sw_set_byte(te, 9, MV_IP_PROTO_TCP);
+	sram_sw_set_shift_update(te, 1, SHIFT_IP4_HLEN);
+	sram_sw_set_rinfo(te, (RI_L3_IP4_FRAG | RI_L4_TCP), (RI_L3_IP4_FRAG | RI_L4_TCP));
+	sram_sw_set_rxq(te, rxq_ip4_tcp, 0);
+	sram_sw_set_ainfo(te, 0, AI_DONE_MASK);
+	pnc_ip4_flow_next_lookup_set(te);
+	tcam_sw_text(te, "ipv4_tcp_fr");
+
+	tcam_hw_write(te, TE_IP4_TCP_FRAG);
+	tcam_sw_free(te);
+}
+
+/* IPv4/UDP header parsing for fragmentation and L4 offset. */
+void pnc_ip4_udp(int rxq)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s\n", __func__);
+	rxq_ip4_udp = rxq;
+
+	/* UDP, FRAG=0 normal */
+	te = tcam_sw_alloc(TCAM_LU_IP4);
+	tcam_sw_set_byte(te, 9, MV_IP_PROTO_UDP);
+	tcam_sw_set_byte(te, 6, 0x00);
+	tcam_sw_set_mask(te, 6, 0x3F);
+	tcam_sw_set_byte(te, 7, 0x00);
+	tcam_sw_set_mask(te, 7, 0xFF);
+	sram_sw_set_shift_update(te, 1, SHIFT_IP4_HLEN);
+	sram_sw_set_rinfo(te, (RI_L3_IP4 | RI_L4_UDP), (RI_L3_IP4 | RI_L4_UDP));
+	sram_sw_set_rxq(te, rxq_ip4_udp, 0);
+	sram_sw_set_ainfo(te, 0, AI_DONE_MASK);
+	pnc_ip4_flow_next_lookup_set(te);
+	tcam_sw_text(te, "ipv4_udp");
+
+	tcam_hw_write(te, TE_IP4_UDP);
+	tcam_sw_free(te);
+
+	/* UDP, FRAG=1 any */
+	te = tcam_sw_alloc(TCAM_LU_IP4);
+	tcam_sw_set_byte(te, 9, MV_IP_PROTO_UDP);
+	sram_sw_set_shift_update(te, 1, SHIFT_IP4_HLEN);
+	sram_sw_set_rinfo(te, (RI_L3_IP4_FRAG | RI_L4_UDP), (RI_L3_IP4_FRAG | RI_L4_UDP));
+	sram_sw_set_rxq(te, rxq_ip4_udp, 0);
+	sram_sw_set_ainfo(te, 0, AI_DONE_MASK);
+	pnc_ip4_flow_next_lookup_set(te);
+	tcam_sw_text(te, "ipv4_udp_fr");
+
+	tcam_hw_write(te, TE_IP4_UDP_FRAG);
+	tcam_sw_free(te);
+}
+
+/* IPv4 - end of section  */
+static void pnc_ip4_end(void)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s\n", __func__);
+
+	te = tcam_sw_alloc(TCAM_LU_IP4);
+	sram_sw_set_rinfo(te, (RI_L3_IP4 | RI_L4_UN), (RI_L3_IP4 | RI_L4_UN));
+	sram_sw_set_rxq(te, rxq_ip4, 0);
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, FLOWID_EOF_LU_IP4, FLOWID_CTRL_LOW_HALF_MASK);
+
+	tcam_sw_text(te, "ipv4_eof");
+
+	tcam_hw_write(te, TE_IP4_EOF);
+	tcam_sw_free(te);
+}
+
+int pnc_ip4_init(void)
+{
+	PNC_DBG("%s\n", __func__);
+
+	pnc_ip4_tcp(CONFIG_MV_ETH_RXQ_DEF);
+	pnc_ip4_udp(CONFIG_MV_ETH_RXQ_DEF);
+	/*pnc_ip4_esp();*/
+	pnc_ip4_end();
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * IPv6 Section
+ *
+ *******************************************************************************
+ */
+
+static void pnc_ip6_flow_next_lookup_set(struct tcam_entry *te)
+{
+#ifdef CONFIG_MV_ETH_PNC_L3_FLOW
+	sram_sw_set_next_lookup(te, TCAM_LU_FLOW_IP6_A);
+#else
+	sram_sw_set_next_lookup(te, TCAM_LU_L4);
+#endif /* CONFIG_MV_ETH_PNC_L3_FLOW */
+}
+
+/* IPv6 - detect TCP */
+static void pnc_ip6_tcp(void)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s\n", __func__);
+
+	/* TCP without extension headers */
+	te = tcam_sw_alloc(TCAM_LU_IP6);
+	tcam_sw_set_byte(te, 6, MV_IP_PROTO_TCP);
+	sram_sw_set_shift_update(te, 1, sizeof(MV_IP6_HEADER));
+	pnc_ip6_flow_next_lookup_set(te);
+	sram_sw_set_rinfo(te, (RI_L3_IP6 | RI_L4_TCP), (RI_L3_IP6 | RI_L4_TCP));
+	sram_sw_set_rxq(te, rxq_ip6, 0);
+	tcam_sw_text(te, "ipv6_tcp");
+
+	tcam_hw_write(te, TE_IP6_TCP);
+	tcam_sw_free(te);
+}
+
+/* IPv6 - detect UDP */
+static void pnc_ip6_udp(void)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s\n", __func__);
+
+	/* UDP without extension headers */
+	te = tcam_sw_alloc(TCAM_LU_IP6);
+	tcam_sw_set_byte(te, 6, MV_IP_PROTO_UDP);
+	sram_sw_set_shift_update(te, 1, sizeof(MV_IP6_HEADER));
+	pnc_ip6_flow_next_lookup_set(te);
+
+	sram_sw_set_rinfo(te, (RI_L3_IP6 | RI_L4_UDP), (RI_L3_IP6 | RI_L4_UDP));
+	sram_sw_set_rxq(te, rxq_ip6, 0);
+	tcam_sw_text(te, "ipv6_udp");
+
+	tcam_hw_write(te, TE_IP6_UDP);
+	tcam_sw_free(te);
+}
+
+/* IPv6 - end of section  */
+static void pnc_ip6_end(void)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s\n", __func__);
+
+	te = tcam_sw_alloc(TCAM_LU_IP6);
+	sram_sw_set_shift_update(te, 1, sizeof(MV_IP6_HEADER));
+	sram_sw_set_rinfo(te, (RI_L3_IP6 | RI_L4_UN), (RI_L3_IP6 | RI_L4_UN));
+	sram_sw_set_rxq(te, rxq_ip6, 0);
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, FLOWID_EOF_LU_IP6, FLOWID_CTRL_LOW_HALF_MASK);
+	tcam_sw_text(te, "ipv6_eof");
+
+	tcam_hw_write(te, TE_IP6_EOF);
+	tcam_sw_free(te);
+}
+
+int pnc_ip6_init(void)
+{
+	PNC_DBG("%s\n", __func__);
+
+	pnc_ip6_tcp();
+	pnc_ip6_udp();
+
+	pnc_ip6_end();
+
+	return 0;
+}
+
+#ifdef CONFIG_MV_ETH_PNC_L3_FLOW
+/******************************************************************************
+ *
+ * L3 Flows Section
+ *
+ ******************************************************************************
+ */
+static int pnc_flow_init(void)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s\n", __func__);
+
+	/* end of section for IPv4 */
+	te = tcam_sw_alloc(TCAM_LU_FLOW_IP4);
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, FLOWID_EOF_LU_FLOW_IP4, FLOWID_CTRL_LOW_HALF_MASK);
+	tcam_sw_text(te, "flow_ip4_eof");
+
+	tcam_hw_write(te, TE_FLOW_IP4_EOF);
+	tcam_sw_free(te);
+
+	/* end of section for IPv6_A */
+	te = tcam_sw_alloc(TCAM_LU_FLOW_IP6_A);
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, FLOWID_EOF_LU_FLOW_IP6_A, FLOWID_CTRL_LOW_HALF_MASK);
+	tcam_sw_text(te, "flow_ip6_A_eof");
+
+	tcam_hw_write(te, TE_FLOW_IP6_A_EOF);
+	tcam_sw_free(te);
+
+	/* end of section for IPv6_B */
+	te = tcam_sw_alloc(TCAM_LU_FLOW_IP6_B);
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, FLOWID_EOF_LU_FLOW_IP6_B, FLOWID_CTRL_LOW_HALF_MASK);
+	tcam_sw_text(te, "flow_ip6_B_eof");
+
+	tcam_hw_write(te, TE_FLOW_IP6_B_EOF);
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+/* require 2 TCAM entries for macth */
+int pnc_ipv6_2_tuples_add(unsigned int tid1, unsigned int tid2, unsigned int flow_id,
+					      MV_U8 unique, MV_U8 *sip, MV_U8 *dip, unsigned int rxq)
+{
+	struct tcam_entry   *te;
+	int                 i;
+
+	if ((tid1 < TE_FLOW_L3) || (tid1 > TE_FLOW_L3_END))
+		ERR_ON_OOR(1);
+
+	if ((tid2 < TE_FLOW_L3) || (tid2 > TE_FLOW_L3_END))
+		ERR_ON_OOR(2);
+
+	te = tcam_sw_alloc(TCAM_LU_FLOW_IP6_A);
+	for (i = 0; i < 16; i++)
+		tcam_sw_set_byte(te, 8+i, sip[i]);
+
+	sram_sw_set_shift_update(te, 2, 24);
+
+	sram_sw_set_next_lookup_shift(te, 2);
+
+	sram_sw_set_next_lookup(te, TCAM_LU_FLOW_IP6_B);
+
+	sram_sw_set_ainfo(te, unique, AI_MASK);
+	tcam_sw_text(te, "ipv6_2t_A");
+
+	tcam_hw_write(te, tid1);
+	tcam_sw_free(te);
+
+	te = tcam_sw_alloc(TCAM_LU_FLOW_IP6_B);
+	for (i = 0; i < 16; i++)
+		tcam_sw_set_byte(te, i, dip[i]);
+
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, flow_id, FLOWID_CTRL_FULL_MASK);
+
+	if (PNC_FLOWID_IS_HWF(flow_id))	{
+		/* Overwrite RXQ - FIXME */
+		sram_sw_set_rxq(te, rxq, 1);
+	} else {
+		sram_sw_set_rxq(te, rxq, 0);
+	}
+
+	sram_sw_set_rinfo(te, RI_L3_FLOW, RI_L3_FLOW);
+
+	tcam_sw_set_ainfo(te, unique, AI_MASK);
+	tcam_sw_text(te, "ipv6_2t_B");
+
+	tcam_hw_write(te, tid2);
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+int pnc_ipv4_2_tuples_add(unsigned int tid, unsigned int flow_id, unsigned int sip, unsigned int dip, unsigned int rxq)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s [%d] flow=%d " MV_IPQUAD_FMT "->" MV_IPQUAD_FMT "\n",
+		__func__, tid, flow_id, MV_IPQUAD(((MV_U8 *)&sip)), MV_IPQUAD(((MV_U8 *)&dip)));
+
+	if (tid < TE_FLOW_L3)
+		ERR_ON_OOR(1);
+
+	if (tid > TE_FLOW_L3_END)
+		ERR_ON_OOR(1);
+
+	te = tcam_sw_alloc(TCAM_LU_FLOW_IP4);
+
+	tcam_sw_set_byte(te, 12, (sip >> 0) & 0xFF);
+	tcam_sw_set_byte(te, 13, (sip >> 8) & 0xFF);
+	tcam_sw_set_byte(te, 14, (sip >> 16) & 0xFF);
+	tcam_sw_set_byte(te, 15, (sip >> 24) & 0xFF);
+
+	tcam_sw_set_byte(te, 16, (dip >> 0) & 0xFF);
+	tcam_sw_set_byte(te, 17, (dip >> 8) & 0xFF);
+	tcam_sw_set_byte(te, 18, (dip >> 16) & 0xFF);
+	tcam_sw_set_byte(te, 19, (dip >> 24) & 0xFF);
+
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, flow_id, FLOWID_CTRL_FULL_MASK);
+	sram_sw_set_rxq(te, rxq, 0);
+	sram_sw_set_rinfo(te, RI_L3_FLOW, RI_L3_FLOW);
+	tcam_sw_text(te, "ipv4_2t");
+
+	tcam_hw_write(te, tid);
+	tcam_sw_free(te);
+
+#ifdef MV_ETH_PNC_AGING
+	mvPncAgingCntrGroupSet(tid, 3);
+#endif
+
+	return 0;
+}
+
+int pnc_ipv4_5_tuples_add(unsigned int tid, unsigned int flow_id,
+			  unsigned int sip, unsigned int dip, unsigned int proto, unsigned int ports, unsigned int rxq)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s [%d] flow=%d " MV_IPQUAD_FMT "->" MV_IPQUAD_FMT ", ports=0x%x, proto=%d\n",
+		__func__, tid, flow_id, MV_IPQUAD(((MV_U8 *)&sip)), MV_IPQUAD(((MV_U8 *)&dip)), ports, proto);
+
+	if (tid < TE_FLOW_L3)
+		ERR_ON_OOR(1);
+
+	if (tid > TE_FLOW_L3_END)
+		ERR_ON_OOR(1);
+
+	/* sanity check */
+
+	te = tcam_sw_alloc(TCAM_LU_FLOW_IP4);
+
+	tcam_sw_set_byte(te, 9, proto);
+
+	tcam_sw_set_byte(te, 12, (sip >> 0) & 0xFF);
+	tcam_sw_set_byte(te, 13, (sip >> 8) & 0xFF);
+	tcam_sw_set_byte(te, 14, (sip >> 16) & 0xFF);
+	tcam_sw_set_byte(te, 15, (sip >> 24) & 0xFF);
+
+	tcam_sw_set_byte(te, 16, (dip >> 0) & 0xFF);
+	tcam_sw_set_byte(te, 17, (dip >> 8) & 0xFF);
+	tcam_sw_set_byte(te, 18, (dip >> 16) & 0xFF);
+	tcam_sw_set_byte(te, 19, (dip >> 24) & 0xFF);
+
+	tcam_sw_set_byte(te, 20, (ports >> 0) & 0xFF);
+	tcam_sw_set_byte(te, 21, (ports >> 8) & 0xFF);
+	tcam_sw_set_byte(te, 22, (ports >> 16) & 0xFF);
+	tcam_sw_set_byte(te, 23, (ports >> 24) & 0xFF);
+
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, flow_id, FLOWID_CTRL_FULL_MASK);
+	sram_sw_set_rxq(te, rxq, 0);
+	sram_sw_set_rinfo(te, RI_L3_FLOW, RI_L3_FLOW);
+	tcam_sw_text(te, "ipv4_5t");
+
+	tcam_hw_write(te, tid);
+	tcam_sw_free(te);
+
+#ifdef MV_ETH_PNC_AGING
+	mvPncAgingCntrGroupSet(tid, 2);
+#endif
+
+	return 0;
+}
+#else
+int pnc_l4_end(void)
+{
+	struct tcam_entry *te;
+
+	PNC_DBG("%s\n", __func__);
+
+	te = tcam_sw_alloc(TCAM_LU_L4);
+	sram_sw_set_lookup_done(te, 1);
+	sram_sw_set_flowid(te, FLOWID_EOF_LU_L4, FLOWID_CTRL_LOW_HALF_MASK);
+
+	tcam_sw_text(te, "l4_eof");
+
+	tcam_hw_write(te, TE_L4_EOF);
+	tcam_sw_free(te);
+	return 0;
+}
+#endif /* CONFIG_MV_ETH_PNC_L3_FLOW */
+
+/******************************************************************************
+ *
+ * PnC Init
+ *
+ ******************************************************************************
+ */
+
+
+int pnc_def_entry_init(unsigned int tid, unsigned int rxq)
+{
+	struct tcam_entry  te;
+
+    tcam_sw_clear(&te);
+
+	PNC_DBG("%s [%d]\n", __func__, tid);
+
+    tcam_sw_set_lookup(&te, 0);
+    sram_sw_set_lookup_done(&te, 1);
+    sram_sw_set_rxq(&te, rxq, 0);
+
+    tcam_hw_write(&te, tid);
+
+	return 0;
+}
+
+int pnc_default_init(void)
+{
+	int     rc, port;
+	MV_U32	regVal = 0;
+
+	PNC_DBG("%s\n", __func__);
+
+	rc = tcam_hw_init();
+	if (rc)
+		goto out;
+
+	/* Mask all interrupts */
+	MV_REG_WRITE(MV_PNC_MASK_REG, 0xffffffff);
+
+	/* Clear all interrupts */
+	MV_REG_WRITE(MV_PNC_CAUSE_REG, 0x0);
+
+	/* Always start from lookup = 0 */
+	for (port = 0; port < PORT_BITS; port++)
+		regVal |= MV_PNC_PORT_LU_INIT_VAL(port, TCAM_LU_MAC);
+
+	MV_REG_WRITE(MV_PNC_INIT_LOOKUP_REG, regVal);
+
+	rc = pnc_mac_init();
+	if (rc)
+		goto out;
+
+	rc = pnc_vlan_init();
+	if (rc)
+		goto out;
+
+	rc = pnc_etype_init();
+	if (rc)
+		goto out;
+
+	rc = pnc_ip4_init();
+	if (rc)
+		goto out;
+
+	rc = pnc_ip6_init();
+	if (rc)
+		goto out;
+
+#ifdef CONFIG_MV_ETH_PNC_L3_FLOW
+	rc = pnc_flow_init();
+	if (rc)
+		goto out;
+#else
+	rc = pnc_l4_end();
+	if (rc)
+		goto out;
+#endif /* CONFIG_MV_ETH_PNC_L3_FLOW */
+
+#ifdef CONFIG_MV_ETH_PNC_WOL
+	mv_pnc_wol_init();
+#endif /* CONFIG_MV_ETH_PNC_WOL */
+
+	pnc_inited = 1;
+out:
+	return rc;
+}
+
+static void pnc_port_sprintf(struct tcam_entry *te, char *buf)
+{
+	int p, offs;
+	unsigned int data, mask;
+
+	tcam_sw_get_port(te, &data, &mask);
+	if (mask == PORT_MASK)
+		mvOsSPrintf(buf, "None");
+	else if (mask == 0)
+		mvOsSPrintf(buf, "All");
+	else {
+		offs = 0;
+		for (p = 0; p < PORT_BITS; p++) {
+			if ((mask & (1 << p)) == 0)
+				offs += mvOsSPrintf(buf + offs, " %d,", pnc_port_map(p));
+		}
+	}
+}
+
+void pnc_vlan_prio_show(int port)
+{
+#if (CONFIG_MV_ETH_PNC_VLAN_PRIO > 0)
+	struct tcam_entry *te;
+	int tid;
+	unsigned char prio;
+	char buf[16];
+
+	mvOsPrintf("Prio   Mask       Ports     RXQ    Name\n");
+	for (tid = TE_VLAN_PRIO; tid <= TE_VLAN_PRIO_END; tid++) {
+		te = pnc_tcam_entry_get(tid);
+		if (te) {
+			prio = *(te->data.u.byte + 2);
+			mvOsPrintf("0x%02x", prio >> 5);
+			prio = *(te->mask.u.byte + 2);
+			mvOsPrintf("   0x%02x", prio >> 5);
+			pnc_port_sprintf(te, buf);
+			mvOsPrintf(" %12s", buf);
+			mvOsPrintf("     %d", sram_sw_get_rxq(te, NULL));
+			mvOsPrintf("     %s\n", te->ctrl.text);
+			tcam_sw_free(te);
+		}
+	}
+#endif /* (CONFIG_MV_ETH_PNC_VLAN_PRIO > 0) */
+	return;
+}
+void pnc_ipv4_dscp_show(int port)
+{
+#if (CONFIG_MV_ETH_PNC_DSCP_PRIO > 0)
+	struct tcam_entry *te;
+	int tid;
+	unsigned char tos;
+	char buf[16];
+
+	mvOsPrintf("TOS    Mask       Ports   RXQ    Name\n");
+	for (tid = TE_IP4_DSCP; tid <= TE_IP4_DSCP_END; tid++) {
+		te = pnc_tcam_entry_get(tid);
+		if (te) {
+			tos = *(te->data.u.byte + 1);
+			mvOsPrintf("0x%02x", tos);
+			tos = *(te->mask.u.byte + 1);
+			mvOsPrintf("   0x%02x", tos);
+			pnc_port_sprintf(te, buf);
+			mvOsPrintf(" %10s", buf);
+			mvOsPrintf("     %d", sram_sw_get_rxq(te, NULL));
+			mvOsPrintf("     %s\n", te->ctrl.text);
+			tcam_sw_free(te);
+		}
+	}
+#endif /* CONFIG_MV_ETH_PNC_DSCP_PRIO > 0 */
+	return;
+}
+
+void pnc_mac_show(void)
+{
+	int tid;
+	struct tcam_entry *te;
+	char *mac;
+	char buf[16];
+
+	mvOsPrintf("     Addr                   Mask         Ports    RXQ   Name\n");
+	for (tid = TE_MAC_BC; tid < TE_MAC_EOF; tid++) {
+		te = pnc_tcam_entry_get(tid);
+		if (te) {
+			mac = te->data.u.byte + MV_ETH_MH_SIZE;
+			mvOsPrintf(MV_MACQUAD_FMT, MV_MACQUAD(mac));
+			mac = te->mask.u.byte + MV_ETH_MH_SIZE;
+			mvOsPrintf("   " MV_MACQUAD_FMT, MV_MACQUAD(mac));
+
+			pnc_port_sprintf(te, buf);
+			mvOsPrintf(" %10s", buf);
+			mvOsPrintf("     %d", sram_sw_get_rxq(te, NULL));
+			mvOsPrintf("     %s\n", te->ctrl.text);
+			tcam_sw_free(te);
+		}
+	}
+}
+
+int pnc_mh_omci(unsigned short data, unsigned short mask, unsigned int rxq)
+{
+	struct tcam_entry *te = NULL;
+
+	PNC_DBG("%s\n", __func__);
+
+	te = tcam_sw_alloc(TCAM_LU_MAC);
+
+	sram_sw_set_rinfo(te, RI_RX_SPECIAL, RI_RX_SPECIAL);
+	sram_sw_set_lookup_done(te, 1);
+	tcam_sw_set_port(te, 0, pnc_port_mask(MV_PON_PORT_ID));
+
+	tcam_sw_set_byte(te, 0, data >> 8);
+	tcam_sw_set_mask(te, 0, mask >> 8);
+
+	tcam_sw_set_byte(te, 1, data & 0xFF);
+	tcam_sw_set_mask(te, 1, mask & 0xFF);
+
+    if (rxq < CONFIG_MV_ETH_RXQ) {
+        sram_sw_set_rxq(te, rxq, 0);
+    }
+    else
+		mvOsPrintf("%s: rxq=%d is out of range\n", __func__, rxq);
+
+	tcam_sw_text(te, "mh_omci");
+
+	tcam_hw_write(te, 0 /*TE_MH_OMCI*/);
+
+	tcam_sw_free(te);
+
+	return 0;
+}
+
+
+int pnc_eoam(unsigned int rxq)
+{
+	struct tcam_entry *te = NULL;
+
+	PNC_DBG("%s\n", __func__);
+
+	te = tcam_sw_alloc(TCAM_LU_MAC);
+
+	sram_sw_set_rinfo(te, RI_RX_SPECIAL, RI_RX_SPECIAL);
+	sram_sw_set_lookup_done(te, 1);
+	tcam_sw_set_port(te, 0, pnc_port_mask(MV_PON_PORT_ID));
+
+	tcam_sw_set_byte(te, 0xe, 0x88);
+	tcam_sw_set_mask(te, 0xe, 0xFF);
+
+	tcam_sw_set_byte(te, 0xf, 0x09);
+	tcam_sw_set_mask(te, 0xf, 0xFF);
+
+	tcam_sw_text(te, "etype_eoam");
+
+    if (rxq < CONFIG_MV_ETH_RXQ) {
+        sram_sw_set_rxq(te, rxq, 0);
+    }
+    else
+		mvOsPrintf("%s: rxq=%d is out of range\n", __func__, rxq);
+
+	tcam_hw_write(te, 0 /*TE_MH_OMCI*/);
+
+	tcam_sw_free(te);
+
+	return 0;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPnc.h b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPnc.h
new file mode 100755
index 0000000..e2e2ef7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPnc.h
@@ -0,0 +1,374 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_PNC_H__
+#define __MV_PNC_H__
+
+
+#include "mvTcam.h"
+
+/*
+ * Errors
+ */
+#define ERR_ON_OOR(cond) if (cond) { mvOsPrintf("%s: out of range\n", __func__);  return PNC_ERR_OOR; }
+#define WARN_ON_OOR(cond) if (cond) { mvOsPrintf("%s: out of range\n", __func__);  return; }
+#define WARN_ON_OOM(cond) if (cond) { mvOsPrintf("%s: out of memory\n", __func__); return NULL; }
+
+ /*
+ * Errors assigment
+ */
+#define PNC_ERR_OOR			1			/* out of range error */
+#define PNC_ERR_INV			1			/* invalid parameter */
+
+ /* Result info bits assigment */
+#define RI_DROP	            (BIT0)		/* drop */
+
+#define RI_L4_OFFS     	    1
+#define RI_L4_MASK     	    (3 << RI_L4_OFFS)
+#define RI_L4_TCP           (0 << RI_L4_OFFS)
+#define RI_L4_UDP           (1 << RI_L4_OFFS)
+#define RI_L4_UN            (2 << RI_L4_OFFS)
+
+#define RI_L3_OFFS     	    3
+#define RI_L3_MASK     	    (7 << RI_L3_OFFS)
+#define RI_L3_UN            (0 << RI_L3_OFFS)
+#define RI_L3_IP6           (1 << RI_L3_OFFS)
+#define RI_L3_IP4_FRAG      (2 << RI_L3_OFFS)
+#define RI_L3_IP4           (3 << RI_L3_OFFS)
+#define RI_L3_IP4_FRAG_F    (6 << RI_L3_OFFS)
+
+#define RI_MCAST_OFFS       6
+#define RI_MCAST_MASK       (3 << RI_MCAST_OFFS)
+#define RI_MCAST_SPEC       (0 << RI_MCAST_OFFS)
+#define RI_MCAST_PNC_SPEC   (1 << RI_MCAST_OFFS)
+#define RI_MCAST_OTHER      (2 << RI_MCAST_OFFS)
+#define RI_MCAST_PNC_OTHER  (3 << RI_MCAST_OFFS)
+#define RI_MCAST_PNC_ONLY   (4 << RI_MCAST_OFFS)
+
+#define RI_MAC_LEARN        (BIT9)	/*media convert MAC learning*/
+#define RI_DA_MC            (BIT10)	/* multicast */
+#define RI_DA_BC            (BIT11)	/* broadcast */
+#define RI_DA_ME            (BIT12)	/* unicast */
+#define RI_PPPOE            (BIT13)	/* PPPoE */
+/* BITS 14-17 are reserved for setting MH field in HWF packets (TXz_MH_reg_1-15) */
+#define RI_L3_FLOW          (BIT18)     /* L3 flow is found */
+#define RI_VLAN             (BIT19)     /* VLAN */
+#define RI_RX_SPECIAL       (BIT20)     /* Packet for special RX processing */
+
+ /* Additional info bits assigment */
+#define AI_DONE_BIT         0
+#define AI_DONE_MASK        (1 << AI_DONE_BIT)
+
+/* PnC result info */
+#define NETA_PNC_VLAN       (RI_VLAN  >> 9)
+#define NETA_PNC_DA_MC      (RI_DA_MC >> 9)
+#define NETA_PNC_DA_BC      (RI_DA_BC >> 9)
+#define NETA_PNC_DA_UC      (RI_DA_ME >> 9)
+#define NETA_PNC_PPPOE      (RI_PPPOE >> 9)
+#define NETA_PNC_RX_SPECIAL (RI_RX_SPECIAL >> 9)
+#define NETA_PNC_MAC_LEARN  (RI_MAC_LEARN >> 9) /*Just for Media convert MAC learn through PNC*/
+/*---------------------------------------------------------------------------*/
+
+MV_STATUS   mvPncInit(MV_U8 *pncVirtBase);
+
+#ifdef CONFIG_MV_ETH_PNC
+/*
+ * TCAM topology definition.
+ * The TCAM is divided into sections per protocol encapsulation.
+ * Usually each section is designed to be to a lookup.
+ * Change sizes of sections according to the target product.
+ */
+enum {
+	/* MAC Lookup including Marvell/PON header */
+	TE_MH,         		/* Match marvell header */
+	TE_MAC_BC,	        /* broadcast */
+	TE_MAC_FLOW_CTRL,   /* Flow Control PAUSE frames */
+	TE_MAC_MC_ALL,      /* first multicast entry (always reserved for all MCASTs) */
+	TE_MAC_MC_L = TE_MAC_MC_ALL + CONFIG_MV_ETH_PNC_MCAST_NUM,    /* last multicast entry */
+	TE_MAC_ME,	        /* mac to me per port */
+	TE_MAC_ME_END = TE_MAC_ME + CONFIG_MV_ETH_PORTS_NUM - 1,
+	TE_MAC_EOF,
+
+    /* VLAN Lookup */
+#if (CONFIG_MV_ETH_PNC_VLAN_PRIO > 0)
+	TE_VLAN_PRIO,
+	TE_VLAN_PRIO_END = TE_VLAN_PRIO + CONFIG_MV_ETH_PNC_VLAN_PRIO,
+#endif /* (CONFIG_MV_ETH_PNC_VLAN_PRIO > 0) */
+	TE_VLAN_EOF,
+
+    /* Ethertype Lookup */
+	TE_ETYPE_ARP,
+	TE_ETYPE_IP4,
+	TE_ETYPE_IP6,
+	TE_PPPOE_IP4,
+	TE_PPPOE_IP6,
+	TE_ETYPE,	/* custom ethertype */
+	TE_ETYPE_EOF = TE_ETYPE + CONFIG_MV_ETH_PNC_ETYPE,
+
+	/* IP4 Lookup */
+#if (CONFIG_MV_ETH_PNC_DSCP_PRIO > 0)
+	TE_IP4_DSCP,
+	TE_IP4_DSCP_END = TE_IP4_DSCP + CONFIG_MV_ETH_PNC_DSCP_PRIO - 1,
+#endif /* CONFIG_MV_ETH_PNC_DSCP_PRIO > 0 */
+
+	TE_IP4_TCP,
+	TE_IP4_TCP_FRAG,
+	TE_IP4_UDP,
+	TE_IP4_UDP_FRAG,
+	TE_IP4_IGMP,
+	TE_IP4_ESP,
+	TE_IP4_EOF,
+
+	/* IP6 Lookup */
+	TE_IP6_TCP,
+	TE_IP6_UDP,
+	TE_IP6_EOF,
+
+#ifdef CONFIG_MV_ETH_PNC_L3_FLOW
+	/* Session Lookup for IPv4 and IPv6 */
+	TE_FLOW_L3,
+	TE_FLOW_L3_END = TE_FLOW_L3 + CONFIG_MV_PNC_L3_FLOW_LINES - 1,
+	TE_FLOW_IP4_EOF,
+	TE_FLOW_IP6_A_EOF,
+	TE_FLOW_IP6_B_EOF,
+#else
+	TE_L4_EOF,
+#endif /* CONFIG_MV_ETH_PNC_L3_FLOW */
+
+#ifdef CONFIG_MV_ETH_PNC_WOL
+	TE_WOL,
+	TE_WOL_EOF = CONFIG_MV_PNC_TCAM_LINES - 1,
+#endif /* CONFIG_MV_ETH_PNC_WOL */
+};
+
+
+enum {
+	TCAM_LU_MAC,
+	TCAM_LU_L2,
+	TCAM_LU_IP4,
+	TCAM_LU_IP6,
+#ifdef CONFIG_MV_ETH_PNC_L3_FLOW
+	TCAM_LU_FLOW_IP4,
+	TCAM_LU_FLOW_IP6_A,
+	TCAM_LU_FLOW_IP6_B,
+#else
+	TCAM_LU_L4,
+#endif /* CONFIG_MV_ETH_PNC_L3_FLOW */
+
+#ifdef CONFIG_MV_ETH_PNC_WOL
+	TCAM_LU_WOL,
+#endif /* CONFIG_MV_ETH_PNC_WOL */
+};
+
+/*
+ * Pre-defined FlowId assigment
+ */
+#define FLOWID_EOF_LU_MAC 			0xFFF0
+#define FLOWID_EOF_LU_L2			0xFFF2
+#define FLOWID_EOF_LU_IP4			0xFFF4
+#define FLOWID_EOF_LU_IP6			0xFFF6
+#define FLOWID_EOF_LU_L4			0xFFF7
+#define FLOWID_EOF_LU_FLOW_IP4		0xFFF8
+#define FLOWID_EOF_LU_FLOW_IP6_A	0xFFFA
+#define FLOWID_EOF_LU_FLOW_IP6_B	0xFFFB
+
+#define FLOWID_CTRL_FULL_MASK       FLOW_CTRL_MASK
+#define FLOWID_CTRL_LOW_HALF_MASK   FLOW_CTRL_HALF_MASK
+#define FLOWID_CTRL_HIGH_HALF_MASK  (FLOW_CTRL_MASK & ~FLOW_CTRL_HALF_MASK)
+
+/************ FlowID field detalization for HWF support ***********************/
+
+/* TXP for HWF: 0 - no HWF, 1 - Giga0, 2 - Giga1, 3..10 PON - TCONTs 0..7 */
+#define PNC_FLOWID_HWF_TXP_OFFS    24
+#define PNC_FLOWID_HWF_TXP_MASK    (0xF << PNC_FLOWID_HWF_TXP_OFFS)
+
+#define PNC_FLOWID_HWF_GEM_OFFS    12
+#define PNC_FLOWID_HWF_GEM_MASK    (0xFFF << PNC_FLOWID_HWF_GEM_OFFS)
+
+#define PNC_FLOWID_HWF_MOD_OFFS    0
+#define PNC_FLOWID_HWF_MOD_MASK    (0x3FF << PNC_FLOWID_HWF_MOD_OFFS)
+
+#define PNC_FLOWID_IS_HWF(flowid)	(((flowid) & PNC_FLOWID_HWF_TXP_MASK) != 0)
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Export API
+ */
+
+int pnc_default_init(void);
+
+int pnc_te_del(unsigned int tid);
+
+struct tcam_entry *pnc_tcam_entry_get(int tid);
+
+int          pnc_eth_port_map(int eth_port);
+int          pnc_port_map(int pnc_port);
+
+unsigned int pnc_port_mask_update(unsigned int mask, int eth_port, int add);
+unsigned int pnc_port_mask(int eth_port);
+int          pnc_tcam_port_update(int tid, int eth_port, int add);
+
+
+/* Set number of Rx queues */
+void pnc_rxq_max(int rxq_max);
+
+/* Assign Rx queue to a protocol */
+int pnc_rxq_proto(unsigned int proto, unsigned int rxq);
+
+/* Get availible range on section */
+int pnc_rule_range(int sec, int *first, int *last);
+
+/* Get section for specific rule */
+int pnc_rule_sec(int tid);
+
+/* Delete rule */
+int pnc_rule_del(int tid);
+
+/* Set MAC address of a port, or NULL for promiscuous */
+int pnc_mac_me(unsigned int port, unsigned char *mac, int rxq);
+
+/* Set Multicast MAC address to be accepted on the port */
+int pnc_mcast_me(unsigned int port, unsigned char *mac);
+
+/* Set VLAN priority entry */
+int pnc_vlan_prio_set(int port, int prio, int rxq);
+void pnc_vlan_prio_show(int port);
+
+/* match arp */
+void pnc_etype_arp(int rxq);
+
+/* TCP/IP header parsing for fragmentation and L4 offset.  */
+void pnc_ip4_tcp(int rxq);
+
+/* IPv4/UDP header parsing for fragmentation and L4 offset. */
+void pnc_ip4_udp(int rxq);
+
+/* Enable / Disable accept ALL Multicast */
+int pnc_mcast_all(unsigned int port, int en);
+
+void    pnc_mac_show(void);
+
+/* Add TOS priority rule */
+int     pnc_ip4_dscp(int port, unsigned char dscp, unsigned char mask, int rxq);
+void    pnc_ipv4_dscp_show(int port);
+
+
+/* 2 tuple match */
+int pnc_ipv4_2_tuples_add(unsigned int tid, unsigned int flow_hi,
+			      unsigned int sip, unsigned int dip, unsigned int rxq);
+
+int pnc_ipv6_2_tuples_add(unsigned int tid1, unsigned int tid2, unsigned int flow_id,
+					      MV_U8 unique, MV_U8 *sip, MV_U8 *dip, unsigned int rxq);
+
+/* 5 tuple match */
+int pnc_ipv4_5_tuples_add(unsigned int tid, unsigned int flow_hi,
+				unsigned int sip, unsigned int dip,
+				unsigned int proto, unsigned int ports, unsigned int rxq);
+
+#ifdef CONFIG_MV_ETH_PNC_WOL
+void mv_pnc_wol_init(void);
+int  mv_pnc_wol_rule_set(int port, char *data, char *mask, int size);
+int  mv_pnc_wol_rule_del(int idx);
+int  mv_pnc_wol_rule_del_all(int port);
+
+int  mv_pnc_wol_pkt_match(int port, char *data, int size, int *ruleId);
+void mv_pnc_wol_sleep(int port);
+void mv_pnc_wol_wakeup(int port);
+int  mv_pnc_wol_rule_dump(int idx);
+void mv_pnc_wol_dump(void);
+#endif /* CONFIG_MV_ETH_PNC_WOL */
+
+#ifdef MV_ETH_PNC_AGING
+MV_U32  mvPncAgingCntrRead(int tid);
+void    mvPncAgingCntrWrite(int tid, MV_U32 w32);
+void    mvPncAgingDump(int all);
+void    mvPncAgingReset(void);
+void    mvPncAgingScannerDump(void);
+void    mvPncAgingCntrClear(int tid);
+void    mvPncAgingCntrGroupSet(int tid, int gr);
+void    mvPncAgingCounterClear(int tid, int gr);
+void    mvPncAgingGroupCntrClear(int group);
+MV_U32  mvPncAgingLogEntryRead(int group, int mostly);
+void    mvPncAgingCntrLuMaskSet(int tid, int mask);
+void    mvPncAgingLuThreshSet(int group, unsigned int thesh);
+void    mvPncAgingLuReadClear(int tid);
+void    mvPncAgingTrigerSet(void);
+void    mvPncAgingCouterClear(int tid);
+#endif /* MV_ETH_PNC_AGING */
+
+
+int     pnc_mh_omci(unsigned short data, unsigned short mask, unsigned int rxq);
+int     pnc_eoam(unsigned int rxq);
+int     pnc_default_init(void);
+int     pnc_def_entry_init(unsigned int tid, unsigned int rxq);
+
+#ifdef MV_ETH_PNC_LB
+void    mvPncLbDump(void);
+int     mvPncLbRxqSet(int hash, int rxq);
+int		mvPncLbModeIp4(int mode);
+int		mvPncLbModeIp6(int mode);
+int		mvPncLbModeL4(int mode);
+#endif /* MV_ETH_PNC_LB */
+#endif /* CONFIG_MV_ETH_PNC */
+#endif /*__MV_PNC_H__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncAging.c b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncAging.c
new file mode 100755
index 0000000..ae7cea9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncAging.c
@@ -0,0 +1,316 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include "mvOs.h"
+#include "mvCommon.h"
+
+#include "gbe/mvNetaRegs.h"
+
+#include "mvPnc.h"
+#include "mvTcam.h"
+
+#ifdef MV_ETH_PNC_AGING
+
+extern char tcam_text[CONFIG_MV_PNC_TCAM_LINES][TCAM_TEXT];
+extern MV_U8 *mvPncVirtBase;
+
+void    mvPncAgingCntrWrite(int tid, MV_U32 w32)
+{
+	MV_U32  va;
+
+	WARN_ON_OOR(tid >= CONFIG_MV_PNC_TCAM_LINES);
+
+	va = (MV_U32)mvPncVirtBase;
+	va |= PNC_AGING_ACCESS_MASK;
+	va |= PNC_AGING_CNTRS_ADDR_MASK;
+	va |= (tid << PNC_AGING_CNTR_IDX_ADDR_OFFS);
+/*
+	mvOsPrintf("%s: tid=%d, va=0x%x, w32=0x%08x\n",
+		__func__, tid, va, w32);
+*/
+	MV_MEMIO32_WRITE(va, w32);
+}
+
+
+MV_U32  mvPncAgingCntrRead(int tid)
+{
+	MV_U32  va, w32;
+
+	ERR_ON_OOR(tid >= CONFIG_MV_PNC_TCAM_LINES);
+
+	va = (MV_U32)mvPncVirtBase;
+	va |= PNC_AGING_ACCESS_MASK;
+	va |= PNC_AGING_CNTRS_ADDR_MASK;
+	va |= (tid << PNC_AGING_CNTR_IDX_ADDR_OFFS);
+
+	w32 = MV_MEMIO32_READ(va);
+/*
+	mvOsPrintf("%s: tid=%d, va=0x%x, w32=0x%08x\n",
+		__func__, tid, va, w32);
+*/
+	return w32;
+}
+
+MV_U32  mvPncAgingGroupCntrRead(int group)
+{
+	MV_U32  va, w32;
+
+	ERR_ON_OOR(group >= MV_PNC_AGING_MAX_GROUP);
+
+	va = (MV_U32)mvPncVirtBase;
+	va |= PNC_AGING_ACCESS_MASK;
+	va |= PNC_AGING_GROUPS_ADDR_MASK;
+	va |= (group << PNC_AGING_GROUP_ADDR_OFFS);
+
+	w32 = MV_MEMIO32_READ(va);
+
+	return w32;
+}
+
+void    mvPncAgingGroupCntrClear(int group)
+{
+	MV_U32  w32;
+
+	WARN_ON_OOR(group >= MV_PNC_AGING_MAX_GROUP);
+
+	w32 = MV_REG_READ(MV_PNC_AGING_CTRL_REG);
+	w32 |= MV_PNC_AGING_GROUP_RESET(group);
+	MV_REG_WRITE(MV_PNC_AGING_CTRL_REG, w32);
+}
+
+MV_U32  mvPncAgingLogEntryRead(int group, int mostly)
+{
+	MV_U32  va, w32;
+
+	ERR_ON_OOR(group >= MV_PNC_AGING_MAX_GROUP);
+
+	va = (MV_U32)mvPncVirtBase;
+	va |= PNC_AGING_ACCESS_MASK;
+	va |= PNC_AGING_SCANNER_ADDR_MASK;
+	va |= ((MV_PNC_AGING_MAX_GROUP * mostly + group) << PNC_AGING_LOG_ADDR_OFFS);
+
+	w32 = MV_MEMIO32_READ(va);
+
+	return w32;
+}
+
+void    mvPncAgingCntrShow(int tid, MV_32 w32)
+{
+	mvOsPrintf("[%3d] (%-12s): gr=%d - %10u", tid, tcam_text[tid],
+		((w32 & PNC_AGING_GROUP_ALL_MASK) >> PNC_AGING_GROUP_OFFS),
+		((w32 & PNC_AGING_CNTR_MASK) >> PNC_AGING_CNTR_OFFS));
+
+	if (w32 & PNC_AGING_READ_LU_LOG_MASK)
+		mvOsPrintf(", LU_READ");
+
+	if (w32 & PNC_AGING_READ_MU_LOG_MASK)
+		mvOsPrintf(", MU_READ");
+
+	if (w32 & PNC_AGING_SKIP_LU_SCAN_MASK)
+		mvOsPrintf(", LU_SKIP");
+
+	if (w32 & PNC_AGING_SKIP_MU_SCAN_MASK)
+		mvOsPrintf(", MU_SKIP");
+
+	mvOsPrintf("\n");
+}
+
+void    mvPncAgingDump(int all)
+{
+	int     tid, gr;
+	MV_U32  cntrVal;
+
+	mvOsPrintf("TCAM entries Aging counters: %s\n", all ? "ALL" : "Non ZERO");
+	for (tid = 0; tid < CONFIG_MV_PNC_TCAM_LINES; tid++) {
+		cntrVal = mvPncAgingCntrRead(tid);
+
+		if (all || (cntrVal & PNC_AGING_CNTR_MASK))
+			mvPncAgingCntrShow(tid, cntrVal);
+	}
+	mvOsPrintf("Aging Counters Summary per group: \n");
+	for (gr = 0; gr < MV_PNC_AGING_MAX_GROUP; gr++)
+		mvOsPrintf("group #%d: %10u\n", gr, mvPncAgingGroupCntrRead(gr));
+}
+
+static MV_U32  mvPncScannerLog[CONFIG_MV_PNC_TCAM_LINES];
+static MV_U32  mvPncAgingCntrs[CONFIG_MV_PNC_TCAM_LINES];
+
+void    mvPncAgingScannerDump(void)
+{
+	int     i, j, gr;
+	MV_U32  w32;
+
+	mvOsPrintf("Scanner LU Log entries for aging counters:\n");
+	for (gr = 0; gr < MV_PNC_AGING_MAX_GROUP; gr++) {
+		i = 0;
+		mvOsPrintf("LU group #%d:\n", gr);
+		while (i < CONFIG_MV_PNC_TCAM_LINES) {
+			w32 = mvPncAgingLogEntryRead(gr, 0);
+			if ((w32 & PNC_AGING_LOG_VALID_MASK) == 0)
+				break;
+
+			mvOsDelay(20);
+			mvPncAgingCntrs[i] = mvPncAgingCntrRead(w32 & PNC_AGING_LOG_CNTR_IDX_MASK);
+			mvPncScannerLog[i] = w32;
+			i++;
+
+            if(!(i%8))
+            {
+                mvPncAgingTrigerSet();
+            }
+		}
+		for (j = 0; j < i; j++) {
+			mvOsPrintf("%d: 0x%08x - tid=%u, 0x%08x - cntr=%u\n",
+				j, mvPncScannerLog[j], mvPncScannerLog[j] & PNC_AGING_LOG_CNTR_IDX_MASK,
+				mvPncAgingCntrs[j],
+				(mvPncAgingCntrs[j] & PNC_AGING_CNTR_MASK) >> PNC_AGING_CNTR_OFFS);
+		}
+	}
+
+	mvOsPrintf("\n");
+	mvOsPrintf("Scanner MU Log entries for aging counters:\n");
+	for (gr = 0; gr < MV_PNC_AGING_MAX_GROUP; gr++) {
+		i = 0;
+		mvOsPrintf("MU group #%d:\n", gr);
+		while (i < CONFIG_MV_PNC_TCAM_LINES) {
+			w32 = mvPncAgingLogEntryRead(gr, 1);
+			/*mvOsDelay(1);*/
+			if ((w32 & PNC_AGING_LOG_VALID_MASK) == 0)
+				break;
+
+			mvOsDelay(20);
+			mvPncAgingCntrs[i] = mvPncAgingCntrRead(w32 & PNC_AGING_LOG_CNTR_IDX_MASK);
+			mvPncScannerLog[i] = w32;
+			i++;
+		}
+		for (j = 0; j < i; j++) {
+			mvOsPrintf("%d: 0x%08x - tid=%u, 0x%08x - cntr=%u\n",
+				j, mvPncScannerLog[j], mvPncScannerLog[j] & PNC_AGING_LOG_CNTR_IDX_MASK,
+				mvPncAgingCntrs[j],
+				(mvPncAgingCntrs[j] & PNC_AGING_CNTR_MASK) >> PNC_AGING_CNTR_OFFS);
+		}
+	}
+}
+
+void    mvPncAgingCntrClear(int tid)
+{
+	MV_U32  w32;
+
+	w32 = mvPncAgingCntrRead(tid);
+
+	w32 &= ~PNC_AGING_CNTR_MASK;
+	w32 &= ~(PNC_AGING_READ_LU_LOG_MASK | PNC_AGING_READ_MU_LOG_MASK);
+
+	mvPncAgingCntrWrite(tid, w32);
+}
+
+void    mvPncAgingCntrGroupSet(int tid, int gr)
+{
+	MV_U32  w32;
+
+    w32 = mvPncAgingCntrRead(tid);
+
+    w32 = (w32 & ~PNC_AGING_GROUP_ALL_MASK) | PNC_AGING_GROUP_MASK(gr);
+
+	/*mvOsPrintf("%s: tid=%d, gr=%d, w32=0x%x\n", __FUNCTION__, tid, gr, w32);*/
+	mvPncAgingCntrWrite(tid, w32);
+}
+
+void    mvPncAgingCntrLuMaskSet(int tid, int mask)
+{
+    MV_U32  w32;
+
+    w32 = mvPncAgingCntrRead(tid);
+
+    if(mask != 0)
+    {
+        w32 |= PNC_AGING_SKIP_LU_SCAN_MASK;
+    }
+    else
+    {
+        w32 &= ~PNC_AGING_SKIP_LU_SCAN_MASK;
+    }
+
+    mvPncAgingCntrWrite(tid, w32);
+}
+
+void    mvPncAgingLuThreshSet(int group, unsigned int thesh)
+{
+    MV_U32  w32;
+
+    WARN_ON_OOR(group >= MV_PNC_AGING_MAX_GROUP);
+
+    w32 = thesh & PNC_AGING_CNTR_MAX;
+    MV_REG_WRITE(MV_PNC_AGING_LO_THRESH_REG(group), w32);
+}
+
+void    mvPncAgingTrigerSet(void)
+{
+    MV_U32  w32;
+    w32 = MV_REG_READ(MV_PNC_AGING_CTRL_REG);
+    
+    w32 |= BIT6;
+    
+    MV_REG_WRITE(MV_PNC_AGING_CTRL_REG, w32);
+}
+
+void    mvPncAgingLuReadClear(int tid)
+{
+    MV_U32  w32;
+
+    w32 = mvPncAgingCntrRead(tid);
+
+    w32 &= ~(PNC_AGING_READ_LU_LOG_MASK);
+
+    mvPncAgingCntrWrite(tid, w32);
+}
+
+void    mvPncAgingCouterClear(int tid)
+{
+    MV_U32  w32;
+
+    w32 = mvPncAgingCntrRead(tid);
+    
+    w32 &= ~PNC_AGING_CNTR_MASK;
+
+    mvPncAgingCntrWrite(tid, w32);
+}
+
+/* Reset all Aging counters */
+void    mvPncAgingReset(void)
+{
+	int tid, gr;
+
+	for (tid = 0; tid < CONFIG_MV_PNC_TCAM_LINES; tid++)
+		mvPncAgingCntrClear(tid);
+
+	for (gr = 0; gr < MV_PNC_AGING_MAX_GROUP; gr++)
+		mvPncAgingGroupCntrClear(gr);
+}
+#endif /* MV_ETH_PNC_AGING */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncLb.c b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncLb.c
new file mode 100755
index 0000000..01ed15c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncLb.c
@@ -0,0 +1,159 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+*******************************************************************************/
+
+#include "mvOs.h"
+#include "mvCommon.h"
+
+#include "gbe/mvNetaRegs.h"
+
+#include "mvPnc.h"
+#include "mvTcam.h"
+
+#ifdef MV_ETH_PNC_LB
+
+void    mvPncLbDump(void)
+{
+	MV_U32	regVal;
+	int i, j, rxq;
+
+	MV_REG_WRITE(MV_PNC_LB_TBL_ACCESS_REG, 0);
+	mvOsPrintf("Hash:    rxq    rxq    rxq    rxq\n");
+	for (i = 0; i <= MV_PNC_LB_TBL_ADDR_MASK; i++) {
+		/* Each read returns 4 hash entries */
+		regVal = MV_REG_READ(MV_PNC_LB_TBL_ACCESS_REG);
+		/* Extract data */
+		regVal = (regVal & MV_PNC_LB_TBL_DATA_MASK) >> MV_PNC_LB_TBL_DATA_OFFS;
+		mvOsPrintf("%4d:    ", (i * 4));
+		for (j = 0; j < 4; j++) {
+			rxq = regVal & 7;
+			mvOsPrintf("%3d   ", rxq);
+			regVal = regVal >> 3;
+		}
+		mvOsPrintf("\n");
+	}
+}
+
+int    mvPncLbRxqSet(int hash, int rxq)
+{
+	MV_U32 regVal, entry, index;
+
+	entry = (hash / 4) & MV_PNC_LB_TBL_ADDR_MASK;
+	index = (hash & 3);
+
+	MV_REG_WRITE(MV_PNC_LB_TBL_ACCESS_REG, entry);
+	regVal = MV_REG_READ(MV_PNC_LB_TBL_ACCESS_REG);
+
+	regVal &= ~MV_PNC_LB_TBL_ADDR_MASK;
+	regVal |= entry;
+	regVal &= ~((7 << (index * 3)) << MV_PNC_LB_TBL_DATA_OFFS);
+	regVal |= ((rxq << (index * 3)) << MV_PNC_LB_TBL_DATA_OFFS);
+	regVal |= MV_PNC_LB_TBL_WRITE_TRIG_MASK;
+	MV_REG_WRITE(MV_PNC_LB_TBL_ACCESS_REG, regVal);
+
+	return 0;
+}
+
+int		mvPncLbModeIp4(int mode)
+{
+	int lb;
+	struct tcam_entry te;
+
+	switch (mode) {
+	case 0:
+		lb = LB_DISABLE_VALUE;
+		break;
+	case 1:
+		lb = LB_2_TUPLE_VALUE;
+		break;
+	case 2:
+	default:
+		mvOsPrintf("%s: %d - unexpected mode value\n", __func__, mode);
+		return 1;
+	}
+	tcam_hw_read(&te, TE_IP4_EOF);
+	sram_sw_set_load_balance(&te, lb);
+	tcam_hw_write(&te, TE_IP4_EOF);
+
+	return 0;
+}
+
+int	mvPncLbModeIp6(int mode)
+{
+	int lb;
+	struct tcam_entry te;
+
+	switch (mode) {
+	case 0:
+		lb = LB_DISABLE_VALUE;
+		break;
+	case 1:
+		lb = LB_2_TUPLE_VALUE;
+		break;
+	case 2:
+	default:
+		mvOsPrintf("%s: %d - unexpected mode value\n", __func__, mode);
+		return 1;
+	}
+	tcam_hw_read(&te, TE_IP6_EOF);
+	sram_sw_set_load_balance(&te, lb);
+	tcam_hw_write(&te, TE_IP6_EOF);
+
+	return 0;
+}
+
+int	mvPncLbModeL4(int mode)
+{
+	int lb;
+	struct tcam_entry te;
+
+	switch (mode) {
+	case 0:
+		lb = LB_DISABLE_VALUE;
+		break;
+	case 1:
+		lb = LB_2_TUPLE_VALUE;
+		break;
+	case 2:
+		lb = LB_4_TUPLE_VALUE;
+		break;
+	default:
+		mvOsPrintf("%s: %d - unexpected mode value\n", __func__, mode);
+		return 1;
+	}
+
+#ifdef CONFIG_MV_ETH_PNC_L3_FLOW
+	mvOsPrintf("%s: Not supported\n", __func__);
+	return 1;
+#else
+	tcam_hw_read(&te, TE_L4_EOF);
+	sram_sw_set_load_balance(&te, lb);
+	tcam_hw_write(&te, TE_L4_EOF);
+	return 0;
+#endif /* CONFIG_MV_ETH_PNC_L3_FLOW */
+}
+#endif /* MV_ETH_PNC_LB */
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncWol.c b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncWol.c
new file mode 100755
index 0000000..815533e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvPncWol.c
@@ -0,0 +1,503 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvOs.h"
+#include "mvCommon.h"
+#include "mv802_3.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#include "gbe/mvNeta.h"
+
+#include "mvPnc.h"
+#include "mvTcam.h"
+
+/* PNC debug */
+/*#define PNC_DBG mvOsPrintf*/
+#define PNC_DBG(X...)
+
+/* PNC errors */
+#define PNC_ERR mvOsPrintf
+/*#define PNC_ERR(X...)*/
+
+#define MV_PNC_MAX_RULES			128
+
+/* up to 5 tids can be set for one rule */
+#define MV_PNC_LOOKUP_MAX				(MV_PNC_TOTAL_DATA_SIZE / MV_PNC_LOOKUP_DATA_SIZE)
+
+typedef struct {
+
+	int		id;
+	int		port_mask;
+	char	data[MV_PNC_TOTAL_DATA_SIZE];
+	char	mask[MV_PNC_TOTAL_DATA_SIZE];
+	int		size;
+	int		tids[MV_PNC_LOOKUP_MAX];
+} MV_PNC_WOL_RULE;
+
+/* Support up to 128 WoL rules */
+static MV_PNC_WOL_RULE	*mv_pnc_wol_tbl[MV_PNC_MAX_RULES];
+
+/* Return values:
+ * 0..4 - number of exactly match TCAM enries (24 bytes)
+ * 5    - totally the same rule,
+ * -1   - partial match (not supported)
+ */
+int mv_pnc_rule_cmp(MV_PNC_WOL_RULE *pNew, MV_PNC_WOL_RULE *pExist)
+{
+	int		offset, i, lookup, non_equal_byte, non_equal_lookup;
+	MV_U8	mask;
+
+	offset = 0;
+	lookup = 0;
+	non_equal_byte = -1;
+	non_equal_lookup = -1;
+	while (offset < pNew->size) {
+
+		for (i = 0; i < MV_PNC_LOOKUP_DATA_SIZE; i++) {
+
+			mask = pNew->mask[offset + i] & pExist->mask[offset + i];
+			if ((pNew->data[offset + i] & mask) != (pExist->data[offset + i] & mask)) {
+				/* Different */
+				mvOsPrintf("#%d different on lookup #%d byte #%d: new:%02x & %02x, exist:%02x & %02x\n",
+							pExist->id, lookup, offset + i, pNew->data[offset + i], pNew->mask[offset + i],
+							pExist->data[offset + i], pExist->mask[offset + i]);
+				return lookup;
+			}
+			if (non_equal_byte == -1) {
+				if ((pNew->mask[offset + i] != pExist->mask[offset + i]) ||
+					(pNew->data[offset + i] != pExist->data[offset + i])) {
+					/* Entries are different in this byte */
+
+					/* Remember lookup where rules are different */
+					if (non_equal_lookup == -1)
+						non_equal_lookup = lookup;
+
+					if ((pNew->mask[offset + i] != pExist->mask[offset + i]) && (pNew->mask[offset + i] != 0xFF)) {
+						/* New rule is superset of the existing rule for this byte */
+						non_equal_byte = offset + i;
+					}
+				}
+			}
+		}
+		offset += MV_PNC_LOOKUP_DATA_SIZE;
+		lookup++;
+	}
+	if (non_equal_byte != -1) {
+		mvOsPrintf("#%d non equal on lookup=%d, byte=%d: new %02x & %02x, exist %02x & %02x\n",
+				pExist->id, non_equal_lookup, non_equal_byte, pNew->data[non_equal_byte], pNew->mask[non_equal_byte],
+				pExist->data[non_equal_byte], pExist->mask[non_equal_byte]);
+
+		if (non_equal_lookup < (lookup - 1)) {
+			/* Rejected */
+			mvOsPrintf("rejected: non_equal_lookup #%d < last_lookup #%d\n", non_equal_lookup, lookup - 1);
+			return -1;
+		} else {
+			mvOsPrintf("pass: non_equal_lookup #%d == last_lookup #%d\n", non_equal_lookup, lookup - 1);
+			return non_equal_lookup;
+		}
+	}
+	if (non_equal_lookup == -1) {
+		/* rules are the equal */
+		mvOsPrintf("#%d equal - number of lookups=%d\n", pExist->id, lookup);
+		return MV_PNC_LOOKUP_MAX;
+	} else {
+		/* New rule is superset of existing rule */
+		mvOsPrintf("#%d is superset on lookup #%d\n", pExist->id, non_equal_lookup);
+		return lookup;
+	}
+}
+
+void mv_pnc_wol_init(void)
+{
+	struct tcam_entry *te;
+
+	memset(mv_pnc_wol_tbl, 0, sizeof(mv_pnc_wol_tbl));
+
+	/* Set default entires for each one of LU used for WoL */
+	te = tcam_sw_alloc(TCAM_LU_WOL);
+	tcam_sw_set_lookup_all(te);
+	sram_sw_set_rinfo(te, RI_DROP, RI_DROP);
+	sram_sw_set_lookup_done(te, 1);
+	tcam_sw_text(te, "wol_eof");
+
+	tcam_hw_write(te, TE_WOL_EOF);
+	tcam_sw_free(te);
+}
+
+/* Add WoL rule to TCAM */
+int mv_pnc_wol_rule_set(int port, char *data, char *mask, int size)
+{
+	int               tid, i, free, lookup, match_lu, offset;
+	MV_PNC_WOL_RULE   *pWolRule, *pNewRule, *pMatchRule;
+
+	/* Check parameters validity */
+	if (mvNetaPortCheck(port))
+		return -1;
+
+	if (mvNetaMaxCheck(size, (MV_PNC_TOTAL_DATA_SIZE + 1)))
+		return -1;
+
+	/* Save WoL rule in mv_pnc_wol_tbl */
+	pNewRule = mvOsMalloc(sizeof(MV_PNC_WOL_RULE));
+	if (pNewRule == NULL) {
+		mvOsPrintf("%s: port=%d, size=%d - Can't allocate %d bytes\n",
+				__func__, port, size, sizeof(sizeof(MV_PNC_WOL_RULE)));
+		return -2;
+	}
+	memset(pNewRule, 0, sizeof(MV_PNC_WOL_RULE));
+	pNewRule->port_mask = (1 << port);
+	memcpy(pNewRule->data, data, size);
+	memcpy(pNewRule->mask, mask, size);
+
+	/* complete with don't care */
+	memset(&pNewRule->mask[size], 0, MV_PNC_TOTAL_DATA_SIZE - size);
+
+	/* remember last byte that mask != 0 */
+	pNewRule->size = 0;
+	for (i = 0; i < MV_PNC_TOTAL_DATA_SIZE; i++) {
+		if (pNewRule->mask[i] != 0)
+			pNewRule->size = i + 1;
+	}
+
+	/* Check if such rule already exist */
+	free = -1;
+	pMatchRule = NULL;
+	match_lu = 0;
+	for (i = 0; i < MV_PNC_MAX_RULES; i++) {
+
+		pWolRule = mv_pnc_wol_tbl[i];
+		if (pWolRule == NULL) {
+			/* Rememeber first free place */
+			if (free == -1)
+				free = i;
+
+			continue;
+		}
+		lookup = mv_pnc_rule_cmp(pNewRule, pWolRule);
+		if (lookup < 0) {
+			/* Rules are partilly different - not supported */
+			mvOsPrintf("%s: port=%d, size=%d - WoL rule partial match other rule\n",
+						__func__, port, size);
+			mvOsFree(pNewRule);
+			return -3;
+		}
+
+		if (lookup == MV_PNC_LOOKUP_MAX) {
+			/* The same rule exist - update port mask for all TCAM entries of the rule */
+			pWolRule->port_mask |= (1 << port);
+			for (lookup = 0; lookup < MV_PNC_LOOKUP_MAX; lookup++) {
+				if (pWolRule->tids[lookup] != 0)
+					pnc_tcam_port_update(pWolRule->tids[lookup], port, 1);
+			}
+			mvOsPrintf("%s: port=%d, size=%d - WoL rule already exist\n", __func__, port, size);
+			mvOsFree(pNewRule);
+			return i;
+		}
+		/* remember maximum match lookup and matched rule */
+		if (lookup > match_lu) {
+			match_lu = lookup;
+			pMatchRule = pWolRule;
+		}
+	}
+	if (free == -1) {
+		mvOsPrintf("%s: port=%d, size=%d - No free place\n", __func__, port, size);
+		mvOsFree(pNewRule);
+		return -MV_FULL;
+	}
+
+	/* Set WoL rule to TCAM */
+	pNewRule->id = free;
+	tid = TE_WOL;
+
+	offset = 0;
+	for (lookup = 0; lookup < MV_PNC_LOOKUP_MAX; lookup++) {
+		char              name[TCAM_TEXT];
+		struct tcam_entry *te;
+		unsigned int mask;
+
+		if (lookup < match_lu) {
+			pNewRule->tids[lookup] = pMatchRule->tids[lookup];
+			offset += MV_PNC_LOOKUP_DATA_SIZE;
+
+			/* Update port mask */
+			pnc_tcam_port_update(pNewRule->tids[lookup], port, 1);
+			continue;
+		}
+
+		if (offset >= pNewRule->size)
+			break;
+
+		/* Set free TCAM entry */
+		for (; tid < TE_WOL_EOF; tid++) {
+
+			te = pnc_tcam_entry_get(tid);
+			if (te != NULL) {
+				tcam_sw_free(te);
+				continue;
+			}
+
+			te = tcam_sw_alloc(TCAM_LU_WOL + lookup);
+
+			for (i = 0; i < MV_PNC_LOOKUP_DATA_SIZE; i++) {
+				tcam_sw_set_byte(te, i, pNewRule->data[offset + i]);
+				tcam_sw_set_mask(te, i, pNewRule->mask[offset + i]);
+			}
+
+			/* Set AI */
+			if (lookup == 0)
+				sram_sw_set_ainfo(te, pNewRule->id, AI_MASK);
+			else if (lookup > match_lu)
+				tcam_sw_set_ainfo(te, pNewRule->id, AI_MASK);
+			else {
+				tcam_sw_set_ainfo(te, pMatchRule->id, AI_MASK);
+				sram_sw_set_ainfo(te, pNewRule->id, AI_MASK);
+			}
+			/* set port mask */
+			mask = pnc_port_mask(port);
+			tcam_sw_set_port(te, 0, mask);
+
+			sprintf(name, "wol_%d", pNewRule->id);
+			tcam_sw_text(te, name);
+
+			if ((offset + i) >= pNewRule->size) {
+				/* Last TCAM entry */
+				sram_sw_set_lookup_done(te, 1);
+			} else {
+				sram_sw_set_shift_update(te, 0, MV_PNC_LOOKUP_DATA_SIZE);
+				sram_sw_set_next_lookup(te, TCAM_LU_WOL + lookup + 1);
+			}
+			offset += MV_PNC_LOOKUP_DATA_SIZE;
+
+			pNewRule->tids[lookup] = tid;
+			tcam_hw_write(te, tid);
+			tcam_sw_free(te);
+			break;
+		}
+	}
+
+	mv_pnc_wol_tbl[pNewRule->id] = pNewRule;
+	mvOsPrintf("%s: port=%d, size=%d - New rule added [%d] = %p, \n",
+				__func__, port, size, pNewRule->id, pNewRule);
+	return pNewRule->id;
+}
+
+/* Delete specific WoL rule (maybe more than one TCAM entry) */
+int mv_pnc_wol_rule_del(int idx)
+{
+#if 0
+	int lookup, tid;
+	MV_PNC_WOL_RULE *pWolRule;
+
+	pWolRule = mv_pnc_wol_tbl[idx];
+	if (pWolRule == NULL)
+		return 1;
+
+	/* Invalidate TCAM entries */
+	for (lookup = 0; lookup < pWolRule->maxLookup; lookup++) {
+		tid = pNewRule->tids[lookup];
+
+		/* FIXME: Decrement reference count of TID, if last invalidate - TCAM entry */
+		pnc_te_del(tid);
+	}
+#endif
+	mvOsPrintf("Not supported\n");
+	return 0;
+}
+
+int mv_pnc_wol_rule_del_all(int port)
+{
+	int i;
+	MV_PNC_WOL_RULE *pWolRule;
+
+	if (mvNetaPortCheck(port))
+		return -1;
+
+	for (i = 0; i < MV_PNC_MAX_RULES; i++) {
+		pWolRule = mv_pnc_wol_tbl[i];
+		if (pWolRule != NULL) {
+			mvOsFree(pWolRule);
+			mv_pnc_wol_tbl[i] = NULL;
+		}
+	}
+	/* Set free TCAM entry */
+	for (i = TE_WOL; i < TE_WOL_EOF; i++)
+		pnc_te_del(i);
+
+	return 0;
+}
+
+void mv_pnc_wol_sleep(int port)
+{
+	MV_U32 regVal;
+	int    pnc_port = pnc_eth_port_map(port);
+
+	regVal = MV_REG_READ(MV_PNC_INIT_LOOKUP_REG);
+
+	regVal &= ~MV_PNC_PORT_LU_INIT_MASK(pnc_port);
+	regVal |= MV_PNC_PORT_LU_INIT_VAL(pnc_port, TCAM_LU_WOL);
+
+	MV_REG_WRITE(MV_PNC_INIT_LOOKUP_REG, regVal);
+}
+
+void mv_pnc_wol_wakeup(int port)
+{
+	MV_U32 regVal;
+	int    pnc_port = pnc_eth_port_map(port);
+
+	regVal = MV_REG_READ(MV_PNC_INIT_LOOKUP_REG);
+
+	regVal &= ~MV_PNC_PORT_LU_INIT_MASK(pnc_port);
+	regVal |= MV_PNC_PORT_LU_INIT_VAL(pnc_port, TCAM_LU_MAC);
+
+	MV_REG_WRITE(MV_PNC_INIT_LOOKUP_REG, regVal);
+}
+
+int mv_pnc_wol_rule_dump(int idx)
+{
+	int	i;
+	MV_PNC_WOL_RULE *pWolRule;
+
+	if (mvNetaMaxCheck(idx, MV_PNC_MAX_RULES))
+		return -1;
+
+	pWolRule = mv_pnc_wol_tbl[idx];
+	if (pWolRule == NULL)
+		return 1;
+
+	mvOsPrintf("[%3d]: id=%d, port_mask=0x%x, size=%d, tids=[",
+				idx, pWolRule->id, pWolRule->port_mask, pWolRule->size);
+	for (i = 0; i < MV_PNC_LOOKUP_MAX; i++) {
+		if (pWolRule->tids[i] == 0)
+			break;
+		mvOsPrintf(" %d", pWolRule->tids[i]);
+	}
+	mvOsPrintf("]\n");
+
+	mvOsPrintf(" offs: ");
+	for (i = 0;  i < MV_PNC_LOOKUP_DATA_SIZE; i++)
+		mvOsPrintf("%02d", i);
+	mvOsPrintf("\n");
+
+	mvOsPrintf(" data: ");
+	i = 0;
+	while (i < pWolRule->size) {
+		mvOsPrintf("%02x", pWolRule->data[i++]);
+		if ((i % MV_PNC_LOOKUP_DATA_SIZE) == 0)
+			mvOsPrintf("\n       ");
+	}
+	mvOsPrintf("\n");
+
+	mvOsPrintf(" mask: ");
+	i = 0;
+	while (i < pWolRule->size) {
+		mvOsPrintf("%02x", pWolRule->mask[i++]);
+		if ((i % MV_PNC_LOOKUP_DATA_SIZE) == 0)
+			mvOsPrintf("\n       ");
+	}
+	mvOsPrintf("\n\n");
+
+	return 0;
+}
+
+void mv_pnc_wol_dump(void)
+{
+	int				i;
+
+	mvOsPrintf("WoL rules table\n");
+
+	for (i = 0; i < MV_PNC_MAX_RULES; i++)
+		mv_pnc_wol_rule_dump(i);
+}
+
+
+int  mv_pnc_wol_pkt_match(int port, char *data, int size, int *ruleId)
+{
+	int               i, j;
+	MV_PNC_WOL_RULE   *pWolRule;
+
+	/* Check if data match one of existing rules */
+	for (i = 0; i < MV_PNC_MAX_RULES; i++) {
+
+		pWolRule = mv_pnc_wol_tbl[i];
+		if (pWolRule == NULL)
+			continue;
+
+		/* packet size must be more or equal than rule size */
+		if (size < pWolRule->size)
+			continue;
+
+		for (j = 0; j < pWolRule->size; j++) {
+			if ((data[j] & pWolRule->mask[j]) != (pWolRule->data[j] & pWolRule->mask[j]))
+				break;
+		}
+
+		if (j == pWolRule->size) {
+			/* rule matched */
+			if (ruleId != NULL)
+				*ruleId = i;
+			return 1;
+		}
+	}
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvTcam.c b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvTcam.c
new file mode 100755
index 0000000..6405ed2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvTcam.c
@@ -0,0 +1,939 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvOs.h"
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+
+#include "mvPnc.h"
+#include "mvTcam.h"
+#include "gbe/mvNetaRegs.h"
+
+#define DWORD_LEN       32
+
+#define TCAM_DBG(x...) if (tcam_ctl_flags & TCAM_F_DEBUG) mvOsPrintf(x)
+/*#define TCAM_DBG(x...)*/
+
+
+/*
+ * SW control flags
+ */
+static int tcam_ctl_flags;
+#define TCAM_F_DEBUG	0x1
+#define TCAM_F_WRITE	0x2
+
+/*
+ * Keep short text per entry
+ */
+char tcam_text[CONFIG_MV_PNC_TCAM_LINES][TCAM_TEXT];
+
+MV_U8 *mvPncVirtBase = NULL;
+
+MV_STATUS mvPncInit(MV_U8 *pncVirtBase)
+{
+	mvPncVirtBase = pncVirtBase;
+
+	mvOsPrintf("mvPncVirtBase = 0x%p\n", pncVirtBase);
+	return MV_OK;
+}
+
+/*
+ * Low-Level API: TCAM
+ */
+void tcam_sw_clear(struct tcam_entry *te)
+{
+	memset(te, 0, sizeof(struct tcam_entry));
+}
+
+/*
+ *@ainfo : match to `1` on additional info bits 6..0
+ */
+void tcam_sw_set_ainfo(struct tcam_entry *te, unsigned int bits, unsigned int mask)
+{
+	int i;
+	MV_U32 key = te->data.u.word[AI_WORD];
+	MV_U32 val;
+
+	WARN_ON_OOR(bits > AI_MASK);
+	WARN_ON_OOR(mask > AI_MASK);
+
+	for (i = 0; i < AI_BITS; i++) {
+		if (mask & (1 << i)) {
+
+			val = 1 << (i + AI_OFFS);
+
+			if (bits & (1 << i))
+				key |= val;
+			else
+				key &= ~val;
+		}
+	}
+	te->data.u.word[AI_WORD] = key;
+	te->mask.u.word[AI_WORD] |= mask << AI_OFFS;
+}
+
+void tcam_sw_get_ainfo(struct tcam_entry *te, int *data, int *mask)
+{
+	*mask = ((te->mask.u.word[AI_WORD] >> AI_OFFS) & AI_MASK);
+
+	*data = ((te->data.u.word[AI_WORD] >> AI_OFFS) & AI_MASK);
+}
+
+static int tcam_sw_dump_ainfo(struct tcam_entry *te, char *buf)
+{
+	int i, data, mask;
+	int off = 0;
+
+	mask = ((te->mask.u.word[AI_WORD] >> AI_OFFS) & AI_MASK);
+	if (mask == 0)
+		return off;
+
+	data = ((te->data.u.word[AI_WORD] >> AI_OFFS) & AI_MASK);
+	off += mvOsSPrintf(buf + off, " AI=");
+	for (i = 0; i < AI_BITS; i++)
+		if (mask & (1 << i))
+			off += mvOsSPrintf(buf + off, "%d",
+							((data & (1 << i)) != 0));
+		else
+			off += mvOsSPrintf(buf + off, "x");
+
+	return off;
+}
+
+/*
+ *@port : port
+ */
+void tcam_sw_set_port(struct tcam_entry *te, unsigned int port, unsigned int mask)
+{
+	WARN_ON_OOR(port > PORT_MASK);
+	WARN_ON_OOR(mask > PORT_MASK);
+
+	te->data.u.word[PORT_WORD] &= ~(PORT_MASK << PORT_OFFS);
+	te->mask.u.word[PORT_WORD] &= ~(PORT_MASK << PORT_OFFS);
+
+	te->data.u.word[PORT_WORD] |= port << PORT_OFFS;
+	te->mask.u.word[PORT_WORD] |= mask << PORT_OFFS;
+}
+
+void tcam_sw_get_port(struct tcam_entry *te, unsigned int *port, unsigned int *mask)
+{
+	*port = (te->data.u.word[PORT_WORD] >> PORT_OFFS) & PORT_MASK;
+	*mask = (te->mask.u.word[PORT_WORD] >> PORT_OFFS) & PORT_MASK;
+}
+
+void tcam_sw_set_lookup(struct tcam_entry *te, unsigned int lookup)
+{
+	WARN_ON_OOR(lookup > LU_MASK);
+	te->data.u.word[PORT_WORD] &= ~(LU_MASK << LU_OFFS);
+	te->data.u.word[PORT_WORD] |= lookup << LU_OFFS;
+	te->mask.u.word[PORT_WORD] |= LU_MASK << LU_OFFS;
+}
+
+void tcam_sw_set_lookup_all(struct tcam_entry *te)
+{
+	te->data.u.word[PORT_WORD] &= ~(LU_MASK << LU_OFFS);
+	te->mask.u.word[PORT_WORD] &= ~(LU_MASK << LU_OFFS);
+}
+
+void tcam_sw_get_lookup(struct tcam_entry *te, unsigned int *lookup, unsigned int *mask)
+{
+	*lookup = (te->data.u.word[PORT_WORD] >> LU_OFFS) & LU_MASK;
+	*mask = (te->mask.u.word[PORT_WORD] >> LU_OFFS) & LU_MASK;
+}
+
+/* offset:23..0 */
+void tcam_sw_set_byte(struct tcam_entry *te, unsigned int offset, unsigned char data)
+{
+	WARN_ON_OOR(offset >= ((TCAM_LEN - 1) * 4));
+
+	te->data.u.byte[offset] = data;
+	te->mask.u.byte[offset] = 0xFF;
+}
+
+void tcam_sw_set_mask(struct tcam_entry *te, unsigned int offset, unsigned char mask)
+{
+	WARN_ON_OOR(offset >= ((TCAM_LEN - 1) * 4));
+
+	te->mask.u.byte[offset] = mask;
+}
+
+int tcam_sw_cmp_byte(struct tcam_entry *te, unsigned int offset, unsigned char data)
+{
+	unsigned char mask;
+
+	ERR_ON_OOR(offset >= ((TCAM_LEN - 1) * 4));
+
+	mask = te->mask.u.byte[offset];
+
+	if ((te->data.u.byte[offset] & mask) == (data & mask))
+		return 0;
+
+	return 1;
+}
+
+int tcam_sw_cmp_bytes(struct tcam_entry *te, unsigned int offset, unsigned int size, unsigned char *data)
+{
+	int i;
+
+	ERR_ON_OOR((offset + size) >= ((TCAM_LEN - 1) * 4));
+
+	for (i = 0; i < size; i++) {
+		if (tcam_sw_cmp_byte(te, offset + i, data[i]))
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Low-Level API: SRAM
+ */
+void sram_sw_clear(struct sram_entry *se)
+{
+	memset(se, 0, sizeof(struct sram_entry));
+}
+
+void sram_sw_set_flowid(struct tcam_entry *te, unsigned int flowid,
+			unsigned int mask)
+{
+	unsigned int i;
+
+	WARN_ON_OOR(mask > FLOW_CTRL_MASK);
+
+	for (i = 0; i < FLOW_CTRL_BITS; i++) {
+		if (mask & (1 << i)) {
+			te->sram.word[0] &= ~(FLOW_PART_MASK << (i * FLOW_PART_BITS));
+			te->sram.word[0] |= flowid & (FLOW_PART_MASK << (i * FLOW_PART_BITS));
+			te->sram.word[1] |= 1 << i;
+		}
+	}
+}
+
+void sram_sw_set_flowid_partial(struct tcam_entry *te, unsigned int flowid,
+				unsigned int idx)
+{
+	WARN_ON_OOR(idx >= FLOW_CTRL_BITS);
+	WARN_ON_OOR(flowid > FLOW_PART_MASK);
+
+	te->sram.word[0] &= ~(FLOW_PART_MASK << (idx * FLOW_PART_BITS));
+	te->sram.word[0] |= (flowid << (idx * FLOW_PART_BITS));
+	te->sram.word[1] |= 1 << idx;
+}
+
+void sram_sw_set_rinfo(struct tcam_entry *te, unsigned int rinfo, unsigned int mask)
+{
+	unsigned int word;
+	unsigned int i;
+
+	WARN_ON_OOR(rinfo > RI_MASK);
+
+	for (i = 0; i < RI_BITS; i++) {
+		if (mask & (1 << i)) {
+
+			word = (RI_VALUE_OFFS + i) / DWORD_LEN;
+			if (rinfo & (1 << i))
+				te->sram.word[word] |= (1 << ((i + RI_VALUE_OFFS) % DWORD_LEN));
+			else
+				te->sram.word[word] &= ~(1 << ((i + RI_VALUE_OFFS) % DWORD_LEN));
+
+			word = (RI_MASK_OFFS + i) / DWORD_LEN;
+			te->sram.word[word] |= (1 << ((i + RI_MASK_OFFS) % DWORD_LEN));
+		}
+	}
+}
+
+#ifdef MV_ETH_PNC_NEW
+
+#ifdef MV_ETH_PNC_LB
+void sram_sw_set_load_balance(struct tcam_entry *te, unsigned int value)
+{
+	unsigned int word;
+
+	WARN_ON_OOR(value > LB_QUEUE_MASK);
+
+	word = LB_QUEUE_OFFS / DWORD_LEN;
+	te->sram.word[word] &= ~(LB_QUEUE_MASK << (LB_QUEUE_OFFS % DWORD_LEN));
+	te->sram.word[word] |= value << (LB_QUEUE_OFFS % DWORD_LEN);
+}
+
+static int sram_sw_dump_load_balance(struct tcam_entry *te, char *buf)
+{
+	unsigned int word, value;
+
+	word = LB_QUEUE_OFFS / DWORD_LEN;
+	value = te->sram.word[word] >> (LB_QUEUE_OFFS % DWORD_LEN);
+	value &= LB_QUEUE_MASK;
+
+	if (value)
+		return mvOsSPrintf(buf, " LB=%d", value);
+
+	return 0;
+}
+#endif /* MV_ETH_PNC_LB */
+
+void sram_sw_set_rinfo_extra(struct tcam_entry *te, unsigned int ri_extra)
+{
+	unsigned int word, value;
+	unsigned int i, c;
+
+	WARN_ON_OOR(ri_extra > RI_EXTRA_MASK);
+
+	for (c = i = 0; i < RI_EXTRA_BITS; i += 2, c++)	{
+		value = ((ri_extra >> i) & 3);
+		if (value) {
+			word = (RI_EXTRA_VALUE_OFFS + i) / DWORD_LEN;
+			te->sram.word[word] &= ~(3 << ((i + RI_EXTRA_VALUE_OFFS) % DWORD_LEN));
+			te->sram.word[word] |= value << ((i + RI_EXTRA_VALUE_OFFS) % DWORD_LEN);
+
+			word = (RI_EXTRA_CTRL_OFFS + c) / DWORD_LEN;
+			te->sram.word[word] |= 1 << ((c + RI_EXTRA_CTRL_OFFS) % DWORD_LEN);
+		}
+	}
+}
+#endif /* MV_ETH_PNC_NEW */
+
+static int sram_sw_dump_rinfo(struct tcam_entry *te, char *buf)
+{
+	unsigned int word, shift, rinfo;
+	int i, off = 0;
+
+	word = RI_VALUE_OFFS / DWORD_LEN;
+	shift = RI_VALUE_OFFS % DWORD_LEN;
+	rinfo = (te->sram.word[word] >> shift) & ((1 << RI_BITS) - 1);
+
+	for (i = 0; i < RI_BITS; i++)
+		if (rinfo & (1 << i))
+			off += mvOsSPrintf(buf + off, " R%d", i);
+
+	return off;
+}
+
+void sram_sw_set_shift_update(struct tcam_entry *te, unsigned int index, unsigned int value)
+{
+	unsigned int word;
+
+	WARN_ON_OOR(index > SHIFT_IDX_MASK);	/* 0x7  */
+	WARN_ON_OOR(value > SHIFT_VAL_MASK);	/* 0x7F */
+
+	/* Reset value prior to set new one */
+	word = SHIFT_IDX_OFFS / DWORD_LEN;
+	te->sram.word[word] &= ~(SHIFT_IDX_MASK << (SHIFT_IDX_OFFS % DWORD_LEN));
+	te->sram.word[word] |= index << (SHIFT_IDX_OFFS % DWORD_LEN);
+
+	word = SHIFT_VAL_OFFS / DWORD_LEN;
+	te->sram.word[word] &= ~(SHIFT_VAL_MASK << (SHIFT_VAL_OFFS % DWORD_LEN));
+	te->sram.word[word] |= value << (SHIFT_VAL_OFFS % DWORD_LEN);
+
+	TCAM_DBG("%s: w=%x i=0x%x v=0x%x\n", __func__, word, index, value);
+}
+
+static int sram_sw_dump_shift_update(struct tcam_entry *te, char *buf)
+{
+	unsigned int word;
+	unsigned int index;
+	unsigned int value;
+
+	word = SHIFT_VAL_OFFS / DWORD_LEN;
+	value = te->sram.word[word] >> (SHIFT_VAL_OFFS % DWORD_LEN);
+	value &= SHIFT_VAL_MASK;
+
+	word = SHIFT_IDX_OFFS / DWORD_LEN;
+	index = te->sram.word[word] >> (SHIFT_IDX_OFFS % DWORD_LEN);
+	index &= SHIFT_IDX_MASK;
+
+	if (value)
+		return mvOsSPrintf(buf, " [%d]=%d", index, value);
+
+	return 0;
+}
+
+/* rxq:95..93 info:92 */
+void sram_sw_set_rxq(struct tcam_entry *te, unsigned int rxq, unsigned int force)
+{
+	unsigned int word;
+
+	WARN_ON_OOR(rxq > RXQ_MASK);
+
+	if (force) {
+		word = RXQ_INFO_OFFS / DWORD_LEN;
+		te->sram.word[word] |= 1 << (RXQ_INFO_OFFS % DWORD_LEN);
+	}
+
+	word = RXQ_QUEUE_OFFS / DWORD_LEN;
+	te->sram.word[word] &= ~(RXQ_MASK << (RXQ_QUEUE_OFFS % DWORD_LEN));
+	te->sram.word[word] |= rxq << (RXQ_QUEUE_OFFS % DWORD_LEN);
+}
+
+unsigned int sram_sw_get_rxq(struct tcam_entry *te, unsigned int *force)
+{
+	unsigned int word;
+	unsigned int rxq;
+
+	word = RXQ_INFO_OFFS / DWORD_LEN;
+	if (force)
+		*force = te->sram.word[word] & (1 << (RXQ_INFO_OFFS % DWORD_LEN));
+
+	word = RXQ_QUEUE_OFFS / DWORD_LEN;
+	rxq = te->sram.word[word] >> (RXQ_QUEUE_OFFS % DWORD_LEN);
+	rxq &= RXQ_MASK;
+
+	return rxq;
+}
+
+static int sram_sw_dump_rxq(struct tcam_entry *te, char *buf)
+{
+	unsigned int rxq, force;
+
+	rxq = sram_sw_get_rxq(te, &force);
+	if (rxq)
+		return mvOsSPrintf(buf, " %sQ%d", force ? "f" : "", rxq);
+
+	return 0;
+}
+
+/* index */
+void sram_sw_set_next_lookup_shift(struct tcam_entry *te, unsigned int index)
+{
+	unsigned int word;
+
+	WARN_ON_OOR(index > SHIFT_IDX_MASK);
+
+	word = NEXT_LU_SHIFT_OFFS / DWORD_LEN;
+	te->sram.word[word] |= index << (NEXT_LU_SHIFT_OFFS % DWORD_LEN);
+}
+
+static int sram_sw_dump_next_lookup_shift(struct tcam_entry *te, char *buf)
+{
+	unsigned int word, value;
+
+	word = NEXT_LU_SHIFT_OFFS / DWORD_LEN;
+	value = te->sram.word[word] >> (NEXT_LU_SHIFT_OFFS % DWORD_LEN);
+	value &= SHIFT_IDX_MASK;
+
+	if (value)
+		return mvOsSPrintf(buf, " SH=%d", value);
+
+	return 0;
+}
+
+/* done */
+void sram_sw_set_lookup_done(struct tcam_entry *te, unsigned int value)
+{
+	unsigned int word;
+
+	word = LU_DONE_OFFS / DWORD_LEN;
+	if (value)
+		te->sram.word[word] |= 1 << (LU_DONE_OFFS % DWORD_LEN);
+	else
+		te->sram.word[word] &= ~(1 << (LU_DONE_OFFS % DWORD_LEN));
+}
+
+/* index:91..89 val:88..82 */
+void sram_sw_set_ainfo(struct tcam_entry *te, unsigned int bits, unsigned int mask)
+{
+	unsigned int word;
+	unsigned int i;
+
+	WARN_ON_OOR(bits > AI_MASK);
+	WARN_ON_OOR(mask > AI_MASK);
+
+	for (i = 0; i < AI_BITS; i++)
+		if (mask & (1 << i)) {
+			word = (AI_VALUE_OFFS + i) / DWORD_LEN;
+			if (bits & (1 << i))
+				te->sram.word[word] |= (1 << ((i + AI_VALUE_OFFS) % DWORD_LEN));
+			else
+				te->sram.word[word] &= ~(1 << ((i + AI_VALUE_OFFS) % DWORD_LEN));
+
+			word = (AI_MASK_OFFS + i) / DWORD_LEN;
+			te->sram.word[word] |= 1 << ((i + AI_MASK_OFFS) % DWORD_LEN);
+		}
+}
+
+static int sram_sw_dump_ainfo(struct tcam_entry *te, char *buf)
+{
+	unsigned int word, shift, data, mask;
+	int i, off = 0;
+
+	word = AI_VALUE_OFFS / DWORD_LEN;
+	shift = AI_VALUE_OFFS % DWORD_LEN;
+	data = ((te->sram.word[word] >> shift) & AI_MASK);
+	shift = AI_MASK_OFFS % DWORD_LEN;
+	mask = ((te->sram.word[word] >> shift) & AI_MASK);
+
+	if (mask) {
+		off += mvOsSPrintf(buf + off, " AI=");
+		for (i = 0; i < AI_BITS; i++) {
+			if (mask & (1 << i))
+				off += mvOsSPrintf(buf + off, "%d", ((data & (1 << i)) != 0));
+			else
+				off += mvOsSPrintf(buf + off, "x");
+		}
+	}
+	return off;
+}
+
+/* 121..118 */
+void sram_sw_set_next_lookup(struct tcam_entry *te, unsigned int lookup)
+{
+	unsigned int word;
+
+	WARN_ON_OOR(lookup > LU_MASK);
+
+	word = LU_ID_OFFS / DWORD_LEN;
+	te->sram.word[word] |= lookup << (LU_ID_OFFS % DWORD_LEN);
+}
+static int sram_sw_dump_next_lookup(struct tcam_entry *te, char *buf)
+{
+	unsigned int word;
+	unsigned int lookup;
+
+	word = LU_DONE_OFFS / DWORD_LEN;
+	lookup = te->sram.word[word] >> (LU_DONE_OFFS % DWORD_LEN);
+	lookup &= 0x1;
+
+	if (lookup)
+		return mvOsSPrintf(buf, " LU=D");
+
+	word = LU_ID_OFFS / DWORD_LEN;
+	lookup = te->sram.word[word] >> (LU_ID_OFFS % DWORD_LEN);
+	lookup &= LU_MASK;
+
+	if (lookup)
+		return mvOsSPrintf(buf, " LU=%d", lookup);
+
+	return 0;
+}
+
+/*
+ * tcam_sw_alloc - allocate new TCAM entry
+ * @lookup: lookup section
+ */
+struct tcam_entry *tcam_sw_alloc(unsigned int lookup)
+{
+	struct tcam_entry *te = mvOsMalloc(sizeof(struct tcam_entry));
+
+	WARN_ON_OOM(!te);
+
+	tcam_sw_clear(te);
+	tcam_sw_set_lookup(te, lookup);
+	sram_sw_set_shift_update(te, 7, 0);
+
+	return te;
+}
+
+void tcam_sw_free(struct tcam_entry *te)
+{
+	mvOsFree(te);
+}
+
+void tcam_sw_text(struct tcam_entry *te, char *text)
+{
+	strncpy(te->ctrl.text, text, TCAM_TEXT);
+	te->ctrl.text[TCAM_TEXT - 1] = 0;
+}
+
+int tcam_sw_dump(struct tcam_entry *te, char *buf)
+{
+	unsigned int *word;
+	unsigned int off = 0;
+	MV_U32       w32;
+	int			 i;
+
+	/* hw entry id */
+	off += mvOsSPrintf(buf + off, "[%4d] ", te->ctrl.index);
+
+	word = (unsigned int *)&te->data;
+	i = TCAM_LEN - 1;
+	off += mvOsSPrintf(buf+off, "%4.4x ", word[i--] & 0xFFFF);
+
+	while (i >= 0) {
+		w32 = word[i--];
+		off += mvOsSPrintf(buf+off, "%8.8x ", MV_32BIT_LE_FAST(w32));
+	}
+	off += mvOsSPrintf(buf+off, "| ");
+
+	word = (unsigned int *)&te->sram;
+	off += mvOsSPrintf(buf+off, SRAM_FMT, SRAM_VAL(word));
+
+	off += sram_sw_dump_next_lookup(te, buf + off);
+	off += sram_sw_dump_next_lookup_shift(te, buf + off);
+	off += sram_sw_dump_rinfo(te, buf + off);
+	off += sram_sw_dump_ainfo(te, buf + off);
+	off += sram_sw_dump_shift_update(te, buf + off);
+	off += sram_sw_dump_rxq(te, buf + off);
+
+#ifdef MV_ETH_PNC_LB
+	off += sram_sw_dump_load_balance(te, buf + off);
+#endif /* MV_ETH_PNC_LB */
+
+	off += (te->ctrl.flags & TCAM_F_INV) ? mvOsSPrintf(buf + off, " [inv]") : 0;
+	off += mvOsSPrintf(buf + off, "\n       ");
+
+	word = (unsigned int *)&te->mask;
+	i = TCAM_LEN - 1;
+	off += mvOsSPrintf(buf+off, "%4.4x ", word[i--] & 0xFFFF);
+
+	while (i >= 0) {
+		w32 = word[i--];
+		off += mvOsSPrintf(buf+off, "%8.8x ", MV_32BIT_LE_FAST(w32));
+	}
+
+	off += mvOsSPrintf(buf + off, "   (%s)", te->ctrl.text);
+	off += tcam_sw_dump_ainfo(te, buf + off);
+	off += mvOsSPrintf(buf + off, "\n");
+
+	return off;
+}
+
+/*
+ * tcam_hw_inv - invalidate TCAM entry on HW
+ * @tid: entry index
+ */
+void tcam_hw_inv(int tid)
+{
+	MV_U32 va;
+
+	WARN_ON_OOR(tid >= CONFIG_MV_PNC_TCAM_LINES);
+	va = (MV_U32) mvPncVirtBase;
+	va |= PNC_TCAM_ACCESS_MASK;
+	va |= (tid << TCAM_LINE_INDEX_OFFS);
+	va |= (0xd << TCAM_WORD_ENTRY_OFFS);
+
+	MV_MEMIO_LE32_WRITE(va, 1);
+	TCAM_DBG("%s: (inv) 0x%8x <-- 0x%x [%2x]\n", __func__, va, 1, tid);
+}
+
+void tcam_hw_inv_all(void)
+{
+	MV_U32 va;
+	int tid = CONFIG_MV_PNC_TCAM_LINES;
+
+	while (tid--) {
+		va = (MV_U32) mvPncVirtBase;
+		va |= PNC_TCAM_ACCESS_MASK;
+		va |= (tid << TCAM_LINE_INDEX_OFFS);
+		va |= (0xd << TCAM_WORD_ENTRY_OFFS);
+
+		MV_MEMIO_LE32_WRITE(va, 1);
+		TCAM_DBG("%s: (inv) 0x%8x <-- 0x%x [%2x]\n", __func__, va, 1, tid);
+	}
+}
+
+/*
+ * tcam_hw_write - install TCAM entry on HW
+ * @tid: entry index
+ */
+int tcam_hw_write(struct tcam_entry *te, int tid)
+{
+	MV_U32 i, va, w32;
+
+	TCAM_DBG("%s: tid=0x%x\n", __func__, tid);
+	ERR_ON_OOR(tid >= CONFIG_MV_PNC_TCAM_LINES);
+
+	/* sram */
+	for (i = 0; i < SRAM_LEN; i++) {
+		w32 = te->sram.word[i];
+		/* last word triggers hardware */
+		if (tcam_ctl_flags & TCAM_F_WRITE || w32 || (i == (SRAM_LEN - 1))) {
+			va = (MV_U32) mvPncVirtBase;
+			va |= PNC_SRAM_ACCESS_MASK;
+			va |= (tid << TCAM_LINE_INDEX_OFFS);
+			va |= (i << TCAM_WORD_ENTRY_OFFS);
+			MV_MEMIO_LE32_WRITE(va, w32);
+			TCAM_DBG("%s: (sram) 0x%8x <-- 0x%x\n", __func__, va, w32);
+		}
+	}
+
+	/* tcam */
+	for (i = 0; i < (TCAM_LEN - 1); i++) {
+		w32 = te->data.u.word[i];
+
+		if (tcam_ctl_flags & TCAM_F_WRITE || w32) {
+			va = (MV_U32) mvPncVirtBase;
+			va |= PNC_TCAM_ACCESS_MASK;
+			va |= (tid << TCAM_LINE_INDEX_OFFS);
+			va |= ((2 * i) << TCAM_WORD_ENTRY_OFFS);
+
+			MV_MEMIO32_WRITE(va, w32);
+			TCAM_DBG("%s: (tcam data) 0x%08x <-- 0x%08x\n", __func__, va, w32);
+		}
+	}
+
+	/* mask */
+	for (i = 0; i < (TCAM_LEN - 1); i++) {
+		w32 = te->mask.u.word[i];
+
+		if (tcam_ctl_flags & TCAM_F_WRITE || w32) {
+			va = (MV_U32) mvPncVirtBase;
+			va |= PNC_TCAM_ACCESS_MASK;
+			va |= (tid << TCAM_LINE_INDEX_OFFS);
+			va |= ((2 * i + 1) << TCAM_WORD_ENTRY_OFFS);
+
+			MV_MEMIO32_WRITE(va, w32);
+			TCAM_DBG("%s: (tcam mask) 0x%08x <-- 0x%08x\n", __func__, va, w32);
+		}
+	}
+
+	va = (MV_U32) mvPncVirtBase;
+	va |= PNC_TCAM_ACCESS_MASK;
+	va |= (tid << TCAM_LINE_INDEX_OFFS);
+	va |= (0xc << TCAM_WORD_ENTRY_OFFS);
+
+	w32 = te->data.u.word[TCAM_LEN - 1] & 0xFFFF;
+	w32 |= (te->mask.u.word[TCAM_LEN - 1] << 16);
+
+	MV_MEMIO_LE32_WRITE(va, w32);
+	TCAM_DBG("%s: (last) 0x%8x <-- 0x%x\n", __func__, va, w32);
+
+	/* FIXME: perf hit */
+	if (te->ctrl.text[0]) {
+		TCAM_DBG("%s: (text) <-- %s\n", __func__, te->ctrl.text);
+		strncpy(tcam_text[tid], te->ctrl.text, TCAM_TEXT);
+		tcam_text[tid][TCAM_TEXT - 1] = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * tcam_hw_read - load TCAM entry from HW
+ * @tid: entry index
+ */
+int tcam_hw_read(struct tcam_entry *te, int tid)
+{
+	MV_U32 i, va, w32;
+
+	TCAM_DBG("%s: tid=0x%x\n", __func__, tid);
+	ERR_ON_OOR(tid >= CONFIG_MV_PNC_TCAM_LINES);
+
+	te->ctrl.index = tid;
+
+	/* sram */
+	for (i = 0; i < SRAM_LEN; i++) {
+		va = (MV_U32) mvPncVirtBase;
+		va |= PNC_SRAM_ACCESS_MASK;
+		va |= (tid << TCAM_LINE_INDEX_OFFS);
+		va |= (i << TCAM_WORD_ENTRY_OFFS);
+
+		te->sram.word[i] = w32 = MV_MEMIO_LE32_READ(va);
+		TCAM_DBG("%s: (sram) 0x%8x --> 0x%x\n", __func__, va, w32);
+	}
+
+	/* tcam */
+	for (i = 0; i < (TCAM_LEN - 1); i++) {
+		va = (MV_U32) mvPncVirtBase;
+		va |= PNC_TCAM_ACCESS_MASK;
+		va |= (tid << TCAM_LINE_INDEX_OFFS);
+		va |= ((2 * i) << TCAM_WORD_ENTRY_OFFS);
+
+		te->data.u.word[i] = w32 = MV_MEMIO32_READ(va);
+		TCAM_DBG("%s: (tcam data) 0x%8x --> 0x%x\n", __func__, va, w32);
+	}
+
+	/* mask */
+	for (i = 0; i < (TCAM_LEN - 1); i++) {
+		va = (MV_U32) mvPncVirtBase;
+		va |= PNC_TCAM_ACCESS_MASK;
+		va |= (tid << TCAM_LINE_INDEX_OFFS);
+		va |= ((2 * i + 1) << TCAM_WORD_ENTRY_OFFS);
+
+		te->mask.u.word[i] = w32 = MV_MEMIO32_READ(va);
+		TCAM_DBG("%s: (tcam mask) 0x%8x --> 0x%x\n", __func__, va, w32);
+	}
+
+	va = (MV_U32) mvPncVirtBase;
+	va |= PNC_TCAM_ACCESS_MASK;
+	va |= (tid << TCAM_LINE_INDEX_OFFS);
+	va |= (0xc << TCAM_WORD_ENTRY_OFFS);
+
+	w32 = MV_MEMIO_LE32_READ(va);
+	te->data.u.word[TCAM_LEN - 1] = w32 & 0xFFFF;
+	te->mask.u.word[TCAM_LEN - 1] = w32 >> 16;
+	TCAM_DBG("%s: (last) 0x%8x --> 0x%x\n", __func__, va, w32);
+
+	va = (MV_U32) mvPncVirtBase;
+	va |= PNC_TCAM_ACCESS_MASK;
+	va |= (tid << TCAM_LINE_INDEX_OFFS);
+	va |= (0xd << TCAM_WORD_ENTRY_OFFS);
+
+	w32 = MV_MEMIO_LE32_READ(va);
+	te->ctrl.flags = w32 & TCAM_F_INV;
+	TCAM_DBG("%s: (inv) 0x%8x --> 0x%x\n", __func__, va, w32);
+
+	/* text */
+	TCAM_DBG("%s: (text) --> %s\n", __func__, tcam_text[tid]);
+	strncpy(te->ctrl.text, tcam_text[tid], TCAM_TEXT);
+	te->ctrl.text[TCAM_TEXT - 1] = 0;
+
+	return 0;
+}
+
+/*
+ * tcam_hw_record - record enable
+ */
+void tcam_hw_record(int port)
+{
+	TCAM_DBG("%s: port %d 0x%x <-- 1\n", __func__, port, MV_PNC_HIT_SEQ0_REG);
+	MV_REG_WRITE(MV_PNC_HIT_SEQ0_REG, (port << 1) | 1);
+}
+
+/*
+ * tcam_hw_hits - dump hit sequence
+ */
+int tcam_hw_hits(char *buf)
+{
+	MV_U32 i, off = 0;
+
+	off += mvOsSPrintf(buf + off, "seq hit\n");
+	off += mvOsSPrintf(buf + off, "--- ---\n");
+
+	i = MV_REG_READ(MV_PNC_HIT_SEQ0_REG);
+	off += mvOsSPrintf(buf + off, "0 - %d\n", (i >> 10) & 0x3FF);
+	off += mvOsSPrintf(buf + off, "1 - %d\n", (i >> 20) & 0x3FF);
+
+	i = MV_REG_READ(MV_PNC_HIT_SEQ1_REG);
+	off += mvOsSPrintf(buf + off, "2 - %d\n", (i >> 0) & 0x3FF);
+	off += mvOsSPrintf(buf + off, "3 - %d\n", (i >> 10) & 0x3FF);
+	off += mvOsSPrintf(buf + off, "4 - %d\n", (i >> 20) & 0x3FF);
+
+	i = MV_REG_READ(MV_PNC_HIT_SEQ2_REG);
+	off += mvOsSPrintf(buf + off, "5 - %d\n", (i >> 0) & 0x3FF);
+	off += mvOsSPrintf(buf + off, "6 - %d\n", (i >> 10) & 0x3FF);
+	off += mvOsSPrintf(buf + off, "7 - %d\n", (i >> 20) & 0x3FF);
+
+	return off;
+}
+
+void tcam_hw_debug(int en)
+{
+	tcam_ctl_flags = en;
+}
+
+/*
+ * tcam_hw_dump - print out TCAM registers
+ * @all - whether to dump all entries or valid only
+ */
+int tcam_hw_dump(int all)
+{
+	int i;
+	struct tcam_entry te;
+	char buff[1024];
+
+	for (i = 0; i < CONFIG_MV_PNC_TCAM_LINES; i++) {
+		tcam_sw_clear(&te);
+		tcam_hw_read(&te, i);
+		if (!all && (te.ctrl.flags & TCAM_F_INV))
+			continue;
+		tcam_sw_dump(&te, buff);
+		mvOsPrintf(buff);
+	}
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * HW Init
+ *
+ ******************************************************************************
+ */
+int tcam_hw_init(void)
+{
+	int i;
+	MV_U32	regVal;
+	struct tcam_entry te;
+
+#if (CONFIG_MV_PNC_TCAM_LINES > MV_PNC_TCAM_LINES)
+#error "CONFIG_MV_PNC_TCAM_LINES must be less or equal than MV_PNC_TCAM_LINES"
+#endif
+
+	/* Power on TCAM arrays accordingly with CONFIG_MV_PNC_TCAM_LINES */
+	regVal = MV_REG_READ(MV_PNC_TCAM_CTRL_REG);
+	for (i = 0; i < (MV_PNC_TCAM_LINES / MV_PNC_TCAM_ARRAY_SIZE); i++) {
+		if ((i * MV_PNC_TCAM_ARRAY_SIZE) < CONFIG_MV_PNC_TCAM_LINES)
+			regVal |= MV_PNC_TCAM_POWER_UP(i); /* Power ON */
+		else
+			regVal &= ~MV_PNC_TCAM_POWER_UP(i); /* Power OFF */
+	}
+	MV_REG_WRITE(MV_PNC_TCAM_CTRL_REG, regVal);
+
+	tcam_sw_clear(&te);
+	sram_sw_set_lookup_done(&te, 1);
+
+	/* Perform full write */
+	tcam_ctl_flags = TCAM_F_WRITE;
+
+	for (i = 0; i < CONFIG_MV_PNC_TCAM_LINES; i++) {
+		sram_sw_set_flowid(&te, i, FLOW_CTRL_MASK);
+		tcam_sw_text(&te, "empty");
+		tcam_hw_write(&te, i);
+		tcam_hw_inv(i);
+	}
+
+	/* Back to partial write */
+	tcam_ctl_flags = 0;
+
+	return 0;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvTcam.h b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvTcam.h
new file mode 100755
index 0000000..a23d195
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/neta/pnc/mvTcam.h
@@ -0,0 +1,418 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __MV_TCAM_H__
+#define __MV_TCAM_H__
+
+/************************** NETA PNC Registers ******************************/
+
+#define MV_PNC_LOOP_CTRL_REG 				(MV_PNC_REG_BASE + 0x00)
+
+#define MV_PNC_TCAM_CTRL_REG 				(MV_PNC_REG_BASE + 0x04)
+
+#define MV_PNC_TCAM_POWER_UP_OFFS			0
+#define MV_PNC_TCAM_POWER_UP(array)			(1 << ((array) + MV_PNC_TCAM_POWER_UP_OFFS))
+/*-------------------------------------------------------------------------------*/
+
+#define MV_PNC_INIT_OFFS_REG 				(MV_PNC_REG_BASE + 0x08)
+
+#define MV_PNC_PORT_BUF_INIT_BITS			6
+#define MV_PNC_PORT_BUF_INIT_MAX			((1 << MV_PNC_PORT_BUF_INIT_BITS) - 1)
+#define MV_PNC_PORT_BUF_INIT_MASK(port)		(MV_PNC_PORT_BUF_INIT_MAX << ((port) * MV_PNC_PORT_BUF_INIT_BITS))
+#define MV_PNC_PORT_BUF_INIT_VAL(port, val)	((val) << ((port) * MV_PNC_PORT_BUF_INIT_BITS))
+/*-------------------------------------------------------------------------------*/
+
+#define MV_PNC_INIT_LOOKUP_REG 				(MV_PNC_REG_BASE + 0x0C)
+
+#define MV_PNC_PORT_LU_INIT_BITS			4
+#define MV_PNC_PORT_LU_INIT_MAX				((1 << MV_PNC_PORT_LU_INIT_BITS) - 1)
+#define MV_PNC_PORT_LU_INIT_MASK(port)		(MV_PNC_PORT_BUF_INIT_MAX << ((port) * MV_PNC_PORT_LU_INIT_BITS))
+#define MV_PNC_PORT_LU_INIT_VAL(port, val)	((val) << ((port) * MV_PNC_PORT_LU_INIT_BITS))
+/*-------------------------------------------------------------------------------*/
+
+#define MV_PNC_CAUSE_REG 					(MV_PNC_REG_BASE + 0x10)
+#define MV_PNC_MASK_REG 					(MV_PNC_REG_BASE + 0x14)
+
+#define MV_PNC_HIT_SEQ0_REG					(MV_PNC_REG_BASE + 0x18)
+
+#define MV_PNC_HIT_ENABLE_BIT				0
+#define MV_PNC_HIT_ENABLE_MASK				(1 << MV_PNC_HIT_ENABLE_BIT)
+
+#define MV_PNC_HIT_PORT_OFFS				1
+#define MV_PNC_HIT_PORT_BITS				3
+#define MV_PNC_HIT_PORT_MAX					((1 << MV_PNC_HIT_PORT_BITS) - 1)
+#define MV_PNC_HIT_PORT_MASK				(MV_PNC_HIT_PORT_MAX << MV_PNC_HIT_PORT_OFFS)
+#define MV_PNC_HIT_PORT(port)				(port << MV_PNC_HIT_PORT_OFFS)
+/*-------------------------------------------------------------------------------*/
+
+#define MV_PNC_HIT_SEQ1_REG					(MV_PNC_REG_BASE + 0x1C)
+#define MV_PNC_HIT_SEQ2_REG					(MV_PNC_REG_BASE + 0x20)
+#define MV_PNC_XBAR_RET_REG					(MV_PNC_REG_BASE + 0x24)
+/*-------------------------------------------------------------------------------*/
+
+
+#ifdef MV_ETH_PNC_AGING
+#define PNC_AGING_CNTRS_ADDR_MASK       (0 << 12)
+#define PNC_AGING_GROUPS_ADDR_MASK      (1 << 12)
+#define PNC_AGING_SCANNER_ADDR_MASK     (2 << 12)
+
+#define PNC_AGING_CNTR_IDX_ADDR_OFFS    2
+#define PNC_AGING_GROUP_ADDR_OFFS       2
+#define PNC_AGING_LOG_ADDR_OFFS         5
+
+#define PNC_AGING_CNTR_OFFS             0
+#define PNC_AGING_CNTR_MAX              0x3ffffff
+#define PNC_AGING_CNTR_MASK             (PNC_AGING_CNTR_MAX << PNC_AGING_CNTR_OFFS)
+
+#define PNC_AGING_GROUP_OFFS            26
+#define PNC_AGING_GROUP_ALL_MASK        (0x3 << PNC_AGING_GROUP_OFFS)
+#define PNC_AGING_GROUP_MASK(gr)        ((gr) << PNC_AGING_GROUP_OFFS)
+
+#define PNC_AGING_READ_LU_LOG_BIT       28
+#define PNC_AGING_READ_LU_LOG_MASK      (1 << PNC_AGING_READ_LU_LOG_BIT)
+
+#define PNC_AGING_READ_MU_LOG_BIT       29
+#define PNC_AGING_READ_MU_LOG_MASK      (1 << PNC_AGING_READ_MU_LOG_BIT)
+
+#define PNC_AGING_SKIP_LU_SCAN_BIT      30
+#define PNC_AGING_SKIP_LU_SCAN_MASK     (1 << PNC_AGING_SKIP_LU_SCAN_BIT)
+
+#define PNC_AGING_SKIP_MU_SCAN_BIT      31
+#define PNC_AGING_SKIP_MU_SCAN_MASK     (1 << PNC_AGING_SKIP_MU_SCAN_BIT)
+
+#define PNC_AGING_LOG_CNTR_IDX_OFFS     0
+#define PNC_AGING_LOG_CNTR_IDX_MASK     (0x3FF << PNC_AGING_LOG_CNTR_IDX_OFFS)
+
+#define PNC_AGING_LOG_VALID_BIT         31
+#define PNC_AGING_LOG_VALID_MASK        (1 << PNC_AGING_LOG_VALID_BIT)
+
+#define MV_PNC_AGING_MAX_GROUP              4
+
+/* Aging Control register */
+#define MV_PNC_AGING_CTRL_REG               (MV_PNC_REG_BASE + 0x28)
+
+#define MV_PNC_AGING_RESET_ON_READ_BIT      0
+#define MV_PNC_AGING_RESET_ON_READ_MASK     (1 << MV_PNC_AGING_RESET_ON_READ_BIT)
+
+#define MV_PNC_AGING_SCAN_VALID_BIT         1
+#define MV_PNC_AGING_SCAN_VALID_MASK        (1 << MV_PNC_AGING_SCAN_VALID_BIT)
+
+#define MV_PNC_AGING_GROUP_RESET_OFFS       2
+#define MV_PNC_AGING_GROUP_RESET_MASK       (0xF << MV_PNC_AGING_GROUP_RESET_OFFS)
+#define MV_PNC_AGING_GROUP_RESET(gr)        (1 << (gr + MV_PNC_AGING_GROUP_RESET_OFFS))
+
+#define MV_PNC_AGING_SCAN_START_BIT         6
+#define MV_PNC_AGING_SCAN_START_MASK        (1 << MV_PNC_AGING_SCAN_START_BIT)
+
+#define MV_PNC_AGING_SCAN_DISABLE_BIT       7
+#define MV_PNC_AGING_SCAN_DISABLE_MASK      (1 << MV_PNC_AGING_SCAN_DISABLE_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define MV_PNC_AGING_LO_THRESH_REG(gr)      (MV_PNC_REG_BASE + 0x2C + ((gr) << 2))
+#define MV_PNC_AGING_HI_THRESH_REG          (MV_PNC_REG_BASE + 0x3C)
+/*-------------------------------------------------------------------------------*/
+#endif /* MV_ETH_PNC_AGING */
+
+#ifdef MV_ETH_PNC_LB
+
+#define MV_PNC_LB_TBL_ACCESS_REG            (MV_PNC_REG_BASE + 0x40)
+
+#define MV_PNC_LB_TBL_ADDR_OFFS             0
+#define MV_PNC_LB_TBL_ADDR_MASK             (0x3F << MV_PNC_LB_TBL_ADDR_OFFS)
+
+#define MV_PNC_LB_TBL_DATA_OFFS             6
+#define MV_PNC_LB_TBL_DATA_MASK             (0xFFF << MV_PNC_LB_TBL_DATA_OFFS)
+
+#define MV_PNC_LB_TBL_WRITE_TRIG_BIT        18
+#define MV_PNC_LB_TBL_WRITE_TRIG_MASK       (1 << MV_PNC_LB_TBL_WRITE_TRIG_BIT)
+/*-------------------------------------------------------------------------------*/
+
+#define MV_PNC_LB_CRC_INIT_REG              (MV_PNC_REG_BASE + 0x44)
+#endif /* MV_ETH_PNC_LB */
+
+
+#define MV_PNC_TCAM_ARRAY_SIZE		256
+#define MV_PNC_TOTAL_DATA_SIZE		120
+#define MV_PNC_LOOKUP_DATA_SIZE		24
+
+#ifdef MV_ETH_PNC_NEW
+#define PNC_TCAM_ACCESS_MASK        (BIT18)
+#define PNC_SRAM_ACCESS_MASK        (BIT18 | BIT16)
+#define PNC_AGING_ACCESS_MASK       (BIT18 | BIT17)
+#define SRAM_LEN                    5 /* SRAM in words */
+#define SRAM_FMT                    "%5.5x %8.8x %8.8x %8.8x %8.8x"
+#define SRAM_VAL(p)                 p[4] & 0xFFFFF, p[3], p[2], p[1], p[0]
+#else
+#define PNC_TCAM_ACCESS_MASK        (BIT17)
+#define PNC_SRAM_ACCESS_MASK        (BIT17 | BIT16)
+#define SRAM_LEN                    4 /* SRAM in words */
+#define SRAM_FMT                    "%8.8x %8.8x %8.8x %8.8x"
+#define SRAM_VAL(p)                 p[3], p[2], p[1], p[0]
+#endif /* MV_ETH_PNC_NEW */
+
+#define TCAM_LEN                    7 /* TCAM key/mask in words */
+
+#define TCAM_LINE_INDEX_OFFS	6
+#define TCAM_WORD_ENTRY_OFFS	2
+
+#define AI_WORD					6
+#define AI_OFFS					0
+#define AI_BITS  				7
+#define AI_MASK					((1 << AI_BITS) - 1)
+
+#define PORT_WORD				6
+#define PORT_OFFS				7
+#define PORT_BITS  				5
+#define PORT_MASK				((1 << PORT_BITS) - 1)
+
+#define LU_WORD					6
+#define LU_OFFS					12
+#define LU_BITS  				4
+#define LU_MASK					((1 << LU_BITS) - 1)
+
+#ifdef MV_ETH_PNC_NEW
+#define RI_EXTRA_BITS  		    12
+#define RI_EXTRA_MASK			((1 << RI_EXTRA_BITS) - 1)
+
+#define FLOW_CTRL_BITS          8
+#define FLOW_PART_BITS          4
+#else
+#define FLOW_CTRL_BITS          2
+#define FLOW_PART_BITS          16
+#endif /* MV_ETH_PNC_NEW */
+#define NEXT_LU_SHIFT_BITS	3
+#define NEXT_LU_SHIFT_MASK	((1 << NEXT_LU_SHIFT_BITS) - 1)
+
+#define LU_DONE_BITS		1
+#define LU_DONE_MASK		((1 << LU_DONE_BITS) - 1)
+
+#define FLOW_CTRL_MASK          ((1 << FLOW_CTRL_BITS) - 1)
+#define FLOW_CTRL_HALF_MASK     ((1 << (FLOW_CTRL_BITS / 2)) - 1)
+#define FLOW_PART_MASK          ((1 << FLOW_PART_BITS) - 1)
+#define FLOW_VALUE_MASK         0xFFFFFFFF
+
+
+#define RI_BITS  				24
+#define RI_MASK					((1 << RI_BITS) - 1)
+
+#define SHIFT_VAL_BITS			7
+#define SHIFT_VAL_MASK			((1 << SHIFT_VAL_BITS) - 1)
+#define SHIFT_IDX_BITS			3
+#define SHIFT_IDX_MASK			((1 << SHIFT_IDX_BITS) - 1)
+#define RXQ_BITS				3
+#define RXQ_MASK				((1 << RXQ_BITS) - 1)
+
+#define LB_QUEUE_BITS           2
+#define LB_QUEUE_MASK			((1 << LB_QUEUE_BITS) - 1)
+#define LB_DISABLE_VALUE		0
+#define LB_2_TUPLE_VALUE		1
+#define LB_4_TUPLE_VALUE		2
+
+#define FLOW_VALUE_OFFS 		0   /* 32 bits */
+#define FLOW_CTRL_OFFS			32  /* 8 bits */
+
+/* PNC SRAM Layout */
+#ifdef MV_ETH_PNC_NEW
+#define RI_VALUE_OFFS 			40  /* 24 bits */
+#define RI_MASK_OFFS  			64  /* 24 bits */
+#define RI_VALUE_15_0_MASK		0xFFFF
+#define RI_VALUE_23_16_MASK		0xFF
+
+#define RI_EXTRA_VALUE_OFFS 	88  /* 12 bits */
+#define RI_EXTRA_CTRL_OFFS  	100 /* 6 bits */
+
+#define SHIFT_VAL_OFFS 			106	/* 7 bits - shift update value offset */
+#define SHIFT_IDX_OFFS 			113	/* 3 bits - shift update index offset */
+#define RXQ_INFO_OFFS  			116 /* 1 bit */
+#define RXQ_QUEUE_OFFS 			117 /* 3 bits */
+#define LB_QUEUE_OFFS           120 /* 2 bits - load balancing queue info */
+#define NEXT_LU_SHIFT_OFFS  	122 /* 3 bits */
+#define LU_DONE_OFFS  			125 /* 1 bit */
+#define KEY_TYPE_OFFS           126 /* 4 bits */
+#define AI_VALUE_OFFS 			130 /* 7 bits */
+#define AI_MASK_OFFS  			137 /* 7 bits */
+#define LU_ID_OFFS  			144 /* 4 bits */
+#else /* Old PNC version (z1) */
+#define RI_VALUE_OFFS 			34
+#define RI_MASK_OFFS  			58
+#define SHIFT_VAL_OFFS 			82	/* shift update value offset */
+#define SHIFT_IDX_OFFS 			89	/* shift update index offset */
+#define RXQ_INFO_OFFS  			92
+#define RXQ_QUEUE_OFFS 			93
+#define NEXT_LU_SHIFT_OFFS  	96
+#define LU_DONE_OFFS  			99
+#define AI_VALUE_OFFS 			104
+#define AI_MASK_OFFS  			111
+#define LU_ID_OFFS  			118
+#endif /* MV_ETH_PNC_NEW */
+
+#define SHIFT_IP4_HLEN			126 /* IPv4 dynamic shift index */
+#define SHIFT_IP6_HLEN			127 /* IPv6 dynamic shift index */
+
+/*
+ * TCAM misc/control
+ */
+#define TCAM_F_INV 				1
+#define TCAM_TEXT				16
+
+/*
+ * TCAM control
+ */
+struct tcam_ctrl {
+	unsigned int index;
+	unsigned int flags;
+	unsigned char text[TCAM_TEXT];
+};
+
+/*
+ * TCAM key
+ */
+struct tcam_data {
+	union {
+		unsigned int word[TCAM_LEN];
+		unsigned char byte[TCAM_LEN*4];
+	} u;
+};
+
+/*
+ * TCAM mask
+ */
+struct tcam_mask {
+	union {
+		unsigned int word[TCAM_LEN];
+		unsigned char byte[TCAM_LEN*4];
+	} u;
+};
+
+/*
+ * SRAM entry
+ */
+struct sram_entry {
+	unsigned int word[SRAM_LEN];
+};
+
+/*
+ * TCAM entry
+ */
+struct tcam_entry {
+	struct tcam_data data;
+	struct tcam_mask mask;
+	struct sram_entry sram;
+	struct tcam_ctrl ctrl;
+}  __attribute__((packed));
+
+/*
+ * TCAM Low Level API
+ */
+#ifdef MV_ETH_PNC_NEW
+void sram_sw_set_rinfo_extra(struct tcam_entry *te, unsigned int ri_extra);
+void sram_sw_set_load_balance(struct tcam_entry *te, unsigned int value);
+#endif /* MV_ETH_PNC_NEW */
+
+struct tcam_entry *tcam_sw_alloc(unsigned int section);
+void tcam_sw_free(struct tcam_entry *te);
+int tcam_sw_dump(struct tcam_entry *te, char *buf);
+void tcam_sw_clear(struct tcam_entry *te);
+
+void tcam_sw_set_port(struct tcam_entry *te, unsigned int port, unsigned int mask);
+void tcam_sw_get_port(struct tcam_entry *te, unsigned int *port, unsigned int *mask);
+
+void tcam_sw_set_lookup_all(struct tcam_entry *te);
+void tcam_sw_set_lookup(struct tcam_entry *te, unsigned int lookup);
+void tcam_sw_get_lookup(struct tcam_entry *te, unsigned int *lookup, unsigned int *mask);
+void tcam_sw_set_ainfo(struct tcam_entry *te, unsigned int bits, unsigned int mask);
+void tcam_sw_get_ainfo(struct tcam_entry *te, int *data, int *mask);
+void tcam_sw_set_byte(struct tcam_entry *te, unsigned int offset, unsigned char data);
+
+int  tcam_sw_cmp_byte(struct tcam_entry *te, unsigned int offset, unsigned char data);
+int  tcam_sw_cmp_bytes(struct tcam_entry *te, unsigned int offset, unsigned int size, unsigned char *data);
+
+void tcam_sw_set_mask(struct tcam_entry *te, unsigned int offset, unsigned char mask);
+void sram_sw_clear(struct sram_entry *se);
+void sram_sw_set_rinfo(struct tcam_entry *te, unsigned int rinfo, unsigned int mask);
+void sram_sw_set_shift_update(struct tcam_entry *te, unsigned int index, unsigned int value);
+void sram_sw_set_rxq(struct tcam_entry *te, unsigned int rxq, unsigned int force);
+
+unsigned int sram_sw_get_rxq(struct tcam_entry *te, unsigned int *force);
+
+void sram_sw_set_next_lookup_shift(struct tcam_entry *te, unsigned int index);
+void sram_sw_set_lookup_done(struct tcam_entry *te, unsigned int value);
+void sram_sw_set_next_lookup_shift(struct tcam_entry *te, unsigned int value);
+void sram_sw_set_ainfo(struct tcam_entry *te, unsigned int bits, unsigned int mask);
+void sram_sw_set_next_lookup(struct tcam_entry *te, unsigned int lookup);
+void sram_sw_set_flowid(struct tcam_entry *te, unsigned int flowid, unsigned int mask);
+void sram_sw_set_flowid_partial(struct tcam_entry *te, unsigned int flowid, unsigned int idx);
+void tcam_sw_text(struct tcam_entry *te, char *text);
+int tcam_hw_write(struct tcam_entry *te, int tid);
+int tcam_hw_read(struct tcam_entry *te, int tid);
+void tcam_hw_inv(int tid);
+void tcam_hw_inv_all(void);
+void tcam_hw_debug(int);
+int tcam_hw_dump(int);
+int tcam_hw_hits(char *buf);
+void tcam_hw_record(int);
+int tcam_hw_init(void);
+
+#endif
+
diff --git a/arch/arm/plat-feroceon/mv_hal/nfc/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/nfc/mvCompVer.txt
new file mode 100755
index 0000000..eb63b59
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/nfc/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: DOVE_HAL_3_1_2

+Unit HAL Version: 1.0.2

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/nfc/mvNfc.c b/arch/arm/plat-feroceon/mv_hal/nfc/mvNfc.c
new file mode 100755
index 0000000..bcc41cb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/nfc/mvNfc.c
@@ -0,0 +1,2283 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysNfcConfig.h"
+#include "mvNfcRegs.h"
+#ifdef MV_INCLUDE_PDMA
+#include "pdma/mvPdma.h"
+#include "pdma/mvPdmaRegs.h"
+#endif
+#include "mvNfc.h"
+
+/*************/
+/* Constants */
+/*************/
+
+#define NFC_NATIVE_READ_ID_CMD		0x0090
+#define NFC_READ_ID_ADDR_LEN		1
+#define NFC_ERASE_ADDR_LEN		3
+#define NFC_SP_READ_ADDR_LEN		3
+#define NFC_SP_BIG_READ_ADDR_LEN	4
+#define NFC_LP_READ_ADDR_LEN		5
+#define NFC_BLOCK_ADDR_BITS		0xFFFFFF
+#define NFC_SP_COL_OFFS			0
+#define NFC_SP_COL_MASK			(0xFF << NFC_SP_COL_OFFS)
+#define NFC_LP_COL_OFFS			0
+#define NFC_LP_COL_MASK			(0xFFFF << NFC_SP_COL_OFFS)
+#define NFC_SP_PG_OFFS			8
+#define NFC_SP_PG_MASK			(0xFFFFFF << NFC_SP_PG_OFFS)
+#define NFC_LP_PG_OFFS			16
+#define NFC_LP_PG_MASK			(0xFFFF << NFC_LP_PG_OFFS)
+#define NFC_PG_CNT_OFFS			8
+#define NFC_PG_CNT_MASK			(0xFF << NFC_PG_CNT_OFFS)
+
+#define NFC_READ_ID_PDMA_DATA_LEN	32
+#define NFC_READ_STATUS_PDMA_DATA_LEN	32
+#define NFC_READ_ID_PIO_DATA_LEN	8
+#define NFC_READ_STATUS_PIO_DATA_LEN	8
+#define NFC_RW_SP_PDMA_DATA_LEN		544
+#define NFC_RW_SP_NO_ECC_DATA_LEN	528
+#define NFC_RW_SP_HMNG_ECC_DATA_LEN	520
+#define NFC_RW_SP_G_NO_ECC_DATA_LEN	528
+#define NFC_RW_SP_G_HMNG_ECC_DATA_LEN	526
+
+#define NFC_RW_LP_PDMA_DATA_LEN		2112
+
+#define NFC_RW_LP_NO_ECC_DATA_LEN	2112
+#define NFC_RW_LP_HMNG_ECC_DATA_LEN	2088
+#define NFC_RW_LP_BCH_ECC_DATA_LEN	2080
+
+#define NFC_RW_LP_G_NO_ECC_DATA_LEN	2112
+#define NFC_RW_LP_G_HMNG_ECC_DATA_LEN	2088
+#define NFC_RW_LP_G_BCH_ECC_DATA_LEN	2080
+
+#define NFC_RW_LP_BCH1K_ECC_DATA_LEN	1024
+#define NFC_RW_LP_BCH704B_ECC_DATA_LEN	704
+#define NFC_RW_LP_BCH512B_ECC_DATA_LEN	512
+
+#define NFC_CMD_STRUCT_SIZE		(sizeof(MV_NFC_CMD))
+#define NFC_CMD_BUFF_SIZE(cmdb_0)	((cmdb_0 & NFC_CB0_LEN_OVRD_MASK) ? 16 : 12)
+#define NFC_CMD_BUFF_ADDR		(NFC_COMMAND_BUFF_0_REG_4PDMA)
+#define NFC_DATA_BUFF_ADDR		(NFC_DATA_BUFF_REG_4PDMA)
+
+/**********/
+/* Macros */
+/**********/
+#define ns_clk(ns, ns2clk)	((ns % ns2clk) ? (MV_U32)((ns/ns2clk)+1) : (MV_U32)(ns/ns2clk))
+
+#define DBGPRINT(x) 	printk x
+#define DBGLVL	 	KERN_INFO
+
+/***********/
+/* Typedef */
+/***********/
+
+/* Flash Timing Parameters */
+typedef struct {
+	/* Flash Timing */
+	MV_U32 tADL;		/* Address to write data delay */
+	MV_U32 tCH;		/* Enable signal hold time */
+	MV_U32 tCS;		/* Enable signal setup time */
+	MV_U32 tWH;		/* ND_nWE high duration */
+	MV_U32 tWP;		/* ND_nWE pulse time */
+	MV_U32 tRH;		/* ND_nRE high duration */
+	MV_U32 tRP;		/* ND_nRE pulse width */
+	MV_U32 tR;		/* ND_nWE high to ND_nRE low for read */
+	MV_U32 tWHR;		/* ND_nWE high to ND_nRE low for status read */
+	MV_U32 tAR;		/* ND_ALE low to ND_nRE low delay */
+	MV_U32 tRHW;		/* ND_nRE high to ND_nWE low delay */
+	/* Physical Layout */
+	MV_U32 pgPrBlk;		/* Pages per block */
+	MV_U32 pgSz;		/* Page size */
+	MV_U32 oobSz;		/* Page size */
+	MV_U32 blkNum;		/* Number of blocks per device */
+	MV_U32 id;		/* Manufacturer and device IDs */
+	MV_U32 seqDis;		/* Enable/Disable sequential multipage read */
+	MV_8 *model;		/* Flash Model string */
+	MV_U32 bb_page;		/* Page containing bad block marking */
+} MV_NFC_FLASH_INFO;
+
+/* Flash command set */
+typedef struct {
+	MV_U16 read1;
+	MV_U16 exitCacheRead;
+	MV_U16 cacheReadRand;
+	MV_U16 cacheReadSeq;
+	MV_U16 read2;
+	MV_U16 program;
+	MV_U16 readStatus;
+	MV_U16 readId;
+	MV_U16 erase;
+	MV_U16 multiplaneErase;
+	MV_U16 reset;
+	MV_U16 lock;
+	MV_U16 unlock;
+	MV_U16 lockStatus;
+} MV_NFC_FLASH_CMD_SET;
+
+/********/
+/* Data */
+/********/
+
+/* Defined Flash Types */
+MV_NFC_FLASH_INFO flashDeviceInfo[] = {
+	{			/* ST 1Gb 3V */
+	 .tADL = 100,		/* tADL, Address to write data delay */
+	 .tCH = 5,		/* tCH, Enable signal hold time */
+	 .tCS = 20,		/* tCS, Enable signal setup time */
+	 .tWH = 10,		/* tWH, ND_nWE high duration */
+	 .tWP = 15,		/* tWP, ND_nWE pulse time */
+	 .tRH = 10,		/* tRH, ND_nRE high duration */
+	 .tRP = 15,		/* tRP, ND_nRE pulse width */
+	 .tR = 25121,		/* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read - 25000+20+100+1 */
+	 .tWHR = 60,		/* tWHR, ND_nWE high to ND_nRE low delay for status read */
+	 .tAR = 10,		/* tAR, ND_ALE low to ND_nRE low delay */
+	 .tRHW = 48,		/* tRHW, ND_nRE high to ND_nWE low delay */
+	 .pgPrBlk = 64,		/* Pages per block - detected */
+	 .pgSz = 2048,		/* Page size */
+	 .oobSz = 64,		/* Spare size */
+	 .blkNum = 1024,	/* Number of blocks/sectors in the flash */
+	 .id = 0xF120,		/* Device ID 0xDevice,Vendor */
+	 .model = "ST 1Gb 8bit",
+	 .bb_page = 0,		/* Manufacturer Bad block marking page in block */
+	 },
+	{			/* ST 4Gb */
+	 .tADL = 70,		/* tADL, Address to write data delay */
+	 .tCH = 5,		/* tCH, Enable signal hold time */
+	 .tCS = 20,		/* tCS, Enable signal setup time */
+	 .tWH = 10,		/* tWH, ND_nWE high duration */
+	 .tWP = 12,		/* tWP, ND_nWE pulse time */
+	 .tRH = 12,		/* tRH, ND_nRE high duration */
+	 .tRP = 12,		/* tRP, ND_nRE pulse width */
+	 .tR = 25121,		/* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read - 25000+20+100+1 */
+	 .tWHR = 60,		/* tWHR, ND_nWE high to ND_nRE low delay for status read */
+	 .tAR = 10,		/* tAR, ND_ALE low to ND_nRE low delay */
+	 .tRHW = 100,		/* tRHW, ND_nRE high to ND_nWE low delay */
+	 .pgPrBlk = 64,		/* Pages per block - detected */
+	 .pgSz = 2048,		/* Page size */
+	 .oobSz = 64,		/* Spare size */
+	 .blkNum = 2048,	/* Number of blocks/sectors in the flash */
+	 .id = 0xDC20,		/* Device ID 0xDevice,Vendor */
+	 .model = "NM 4Gb 8bit",
+	 .bb_page = 0,		/* Manufacturer Bad block marking page in block */
+	 },
+	{			/* ST 4Gb */
+	 .tADL = 70,		/* tADL, Address to write data delay */
+	 .tCH = 5,		/* tCH, Enable signal hold time */
+	 .tCS = 15,		/* tCS, Enable signal setup time */
+	 .tWH = 7,		/* tWH, ND_nWE high duration */
+	 .tWP = 10,		/* tWP, ND_nWE pulse time */
+	 .tRH = 7,		/* tRH, ND_nRE high duration */
+	 .tRP = 10,		/* tRP, ND_nRE pulse width */
+	 .tR = 26000,		/* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read */
+	 .tWHR = 60,		/* tWHR, ND_nWE high to ND_nRE low delay for status read */
+	 .tAR = 10,		/* tAR, ND_ALE low to ND_nRE low delay */
+	 .tRHW = 100,		/* tRHW, ND_nRE high to ND_nWE low delay */
+	 .pgPrBlk = 64,		/* Pages per block - detected */
+	 .pgSz = 2048,		/* Page size */
+	 .oobSz = 64,		/* Spare size */
+	 .blkNum = 4096,	/* Number of blocks/sectors in the flash */
+	 .id = 0xDC2C,		/* Device ID 0xDevice,Vendor */
+	 .model = "NM 4Gb 8bit",
+	 .bb_page = 0,		/* Manufacturer Bad block marking page in block */
+	 },
+	{			/* ST 8Gb */
+	 .tADL = 0,		/* tADL, Address to write data delay */
+	 .tCH = 5,		/* tCH, Enable signal hold time */
+	 .tCS = 20,		/* tCS, Enable signal setup time */
+	 .tWH = 12,		/* tWH, ND_nWE high duration */
+	 .tWP = 12,		/* tWP, ND_nWE pulse time */
+	 .tRH = 12,		/* tRH, ND_nRE high duration */
+	 .tRP = 12,		/* tRP, ND_nRE pulse width */
+	 .tR = 25121,		/* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read - 25000+20+100+1 */
+	 .tWHR = 60,		/* tWHR, ND_nWE high to ND_nRE low delay for status read */
+	 .tAR = 10,		/* tAR, ND_ALE low to ND_nRE low delay */
+	 .tRHW = 48,		/* tRHW, ND_nRE high to ND_nWE low delay */
+	 .pgPrBlk = 64,		/* Pages per block - detected */
+	 .pgSz = 2048,		/* Page size */
+	 .oobSz = 64,		/* Spare size */
+	 .blkNum = 2048,	/* Number of blocks/sectors in the flash */
+	 .id = 0xD320,		/* Device ID 0xDevice,Vendor */
+	 .model = "ST 8Gb 8bit",
+	 .bb_page = 63,		/* Manufacturer Bad block marking page in block */
+	 },
+	{			/* ST 32Gb */
+	 .tADL = 0,		/* tADL, Address to write data delay */
+	 .tCH = 5,		/* tCH, Enable signal hold time */
+	 .tCS = 20,		/* tCS, Enable signal setup time */
+	 .tWH = 10,		/* tWH, ND_nWE high duration */
+	 .tWP = 12,		/* tWP, ND_nWE pulse time */
+	 .tRH = 10,		/* tRH, ND_nRE high duration */
+	 .tRP = 12,		/* tRP, ND_nRE pulse width */
+	 .tR = 25121,		/* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read - 25000+20+100+1 */
+	 .tWHR = 80,		/* tWHR, ND_nWE high to ND_nRE low delay for status read */
+	 .tAR = 10,		/* tAR, ND_ALE low to ND_nRE low delay */
+	 .tRHW = 48,		/* tRHW, ND_nRE high to ND_nWE low delay */
+	 .pgPrBlk = 64,		/* Pages per block - detected */
+	 .pgSz = 4096,		/* Page size */
+	 .oobSz = 128,		/* Spare size */
+	 .blkNum = 16384,	/* Number of blocks/sectors in the flash */
+	 .id = 0xD520,		/* Device ID 0xVendor,device */
+	 .model = "ST 32Gb 8bit",
+	 .bb_page = 63,		/* Manufacturer Bad block marking page in block */
+	 },
+
+	{			/* Samsung 16Gb */
+	 .tADL = 90,		/* tADL, Address to write data delay */
+	 .tCH = 0,		/* tCH, Enable signal hold time */
+	 .tCS = 5,		/* tCS, Enable signal setup time */
+	 .tWH = 10,		/* tWH, ND_nWE high duration */
+	 .tWP = 12,		/* tWP, ND_nWE pulse time */
+	 .tRH = 12,		/* tRH, ND_nRE high duration */
+	 .tRP = 12,		/* tRP, ND_nRE pulse width */
+	 .tR = 49146,		/* tR = data transfer from cell to register, maximum 60,000ns */
+	 .tWHR = 66,		/* tWHR, ND_nWE high to ND_nRE low delay for status read */
+	 .tAR = 66,		/* tAR, ND_ALE low to ND_nRE low delay */
+	 .tRHW = 32,		/* tRHW, ND_nRE high to ND_nWE low delay 32 clocks */
+	 .pgPrBlk = 128,	/* Pages per block - detected */
+	 .pgSz = 2048,		/* Page size */
+	 .oobSz = 64,		/* Spare size */
+	 .blkNum = 8192,	/* Number of blocks/sectors in the flash */
+	 .id = 0xD5EC,		/* Device ID 0xDevice,Vendor */
+	 .model = "Samsung 16Gb 8bit",
+	 .bb_page = 127,	/* Manufacturer Bad block marking page in block */
+	 },
+
+	{			/* Samsung 32Gb */
+	 .tADL = 0,		/* tADL, Address to write data delay */
+	 .tCH = 5,		/* tCH, Enable signal hold time */
+	 .tCS = 20,		/* tCS, Enable signal setup time */
+	 .tWH = 10,		/* tWH, ND_nWE high duration */
+	 .tWP = 15,		/* tWP, ND_nWE pulse time */
+	 .tRH = 15,		/* tRH, ND_nRE high duration */
+	 .tRP = 15,		/* tRP, ND_nRE pulse width */
+	 .tR = 60000,		/* tR = data transfer from cell to register, maximum 60,000ns */
+	 .tWHR = 60,		/* tWHR, ND_nWE high to ND_nRE low delay for status read */
+	 .tAR = 10,		/* tAR, ND_ALE low to ND_nRE low delay */
+	 .tRHW = 48,		/* tRHW, ND_nRE high to ND_nWE low delay */
+	 .pgPrBlk = 128,	/* Pages per block - detected */
+	 .pgSz = 4096,		/* Page size */
+	 .oobSz = 128,		/* Spare size */
+	 .blkNum = 8192,	/* Number of blocks/sectors in the flash */
+	 .id = 0xD7EC,		/* Device ID 0xDevice,Vendor */
+	 .model = "Samsung 32Gb 8bit",
+	 .bb_page = 127,	/* Manufacturer Bad block marking page in block */
+	 },
+
+	{			/* Micron 64Gb */
+	 .tADL = 0,		/* tADL, Address to write data delay */
+	 .tCH = 20,		/* tCH, Enable signal hold time */
+	 .tCS = 20,		/* tCS, Enable signal setup time */
+	 .tWH = 45,		/* tWH, ND_nWE high duration */
+	 .tWP = 45,		/* tWP, ND_nWE pulse time */
+	 .tRH = 45,		/* tRH, ND_nRE high duration */
+	 .tRP = 45,		/* tRP, ND_nRE pulse width */
+	 .tR = 0,		/* tR = data transfer from cell to register */
+	 .tWHR = 90,		/* tWHR, ND_nWE high to ND_nRE low delay for status read */
+	 .tAR = 65,		/* tAR, ND_ALE low to ND_nRE low delay */
+	 .tRHW = 32,		/* tRHW, ND_nRE high to ND_nWE low delay */
+	 .pgPrBlk = 256,	/* Pages per block - detected */
+	 .pgSz = 8192,		/* Page size */
+	 .oobSz = 448,		/* Spare size */
+	 .blkNum = 4096,	/* Number of blocks/sectors in the flash */
+	 .id = 0x882C,		/* Device ID 0xDevice,Vendor */
+	 .model = "Micron 64Gb 8bit",
+	 .bb_page = 0,		/* Manufacturer Bad block marking page in block */
+	 }
+
+};
+
+/* Defined Command set */
+#define 	MV_NFC_FLASH_SP_CMD_SET_IDX		0
+#define		MV_NFC_FLASH_LP_CMD_SET_IDX		1
+static MV_NFC_FLASH_CMD_SET flashCmdSet[] = {
+	{
+	 .read1 = 0x0000,
+	 .read2 = 0x0050,
+	 .program = 0x1080,
+	 .readStatus = 0x0070,
+	 .readId = 0x0090,
+	 .erase = 0xD060,
+	 .multiplaneErase = 0xD160,
+	 .reset = 0x00FF,
+	 .lock = 0x002A,
+	 .unlock = 0x2423,
+	 .lockStatus = 0x007A,
+	 },
+	{
+	 .read1 = 0x3000,
+	 .exitCacheRead = 0x003f,
+	 .cacheReadRand = 0x3100,
+	 .cacheReadSeq = 0x0031,
+	 .read2 = 0x0050,
+	 .program = 0x1080,
+	 .readStatus = 0x0070,
+	 .readId = 0x0090,
+	 .erase = 0xD060,
+	 .multiplaneErase = 0xD160,
+	 .reset = 0x00FF,
+	 .lock = 0x002A,
+	 .unlock = 0x2423,
+	 .lockStatus = 0x007A,
+	 }
+};
+
+#undef MV_NFC_REG_DBG
+#ifdef MV_NFC_REG_DBG
+MV_U32 mvNfcDbgFlag = 1;
+
+MV_U32 nfc_dbg_read(MV_U32 addr)
+{
+	MV_U32 reg = MV_MEMIO_LE32_READ((addr));
+	if (mvNfcDbgFlag)
+		mvOsPrintf("NFC read  0x%08x = %08x\n", addr, reg);
+	return reg;
+}
+
+MV_VOID nfc_dbg_write(MV_U32 addr, MV_U32 val)
+{
+	MV_MEMIO_LE32_WRITE((addr), (val));
+
+	if (mvNfcDbgFlag)
+		mvOsPrintf("NFC write 0x%08x = %08x\n", addr, val);
+}
+
+#undef MV_REG_READ
+#undef MV_REG_WRITE
+#define MV_REG_READ(x)		nfc_dbg_read(x)
+#define MV_REG_WRITE(x, y)	nfc_dbg_write(x, y)
+#endif
+
+/**************/
+/* Prototypes */
+/**************/
+static MV_STATUS mvDfcWait4Complete(MV_U32 statMask, MV_U32 usec);
+static MV_STATUS mvNfcReadIdNative(MV_NFC_CHIP_SEL cs, MV_U16 *id);
+static MV_STATUS mvNfcTimingSet(MV_U32 tclk, MV_NFC_FLASH_INFO *flInfo);
+static MV_U32 mvNfcColBits(MV_U32 pg_size);
+#ifdef CONFIG_MTD_NAND_NFC_INIT_RESET
+static MV_STATUS mvNfcReset(void);
+#endif
+
+/*******************************************************************************
+* mvNfcInit
+*
+* DESCRIPTION:
+*       Initialize the NAND controller unit, and perform a detection of the
+*	attached NAND device.
+*
+* INPUT:
+*	nfcInfo  - Flash information parameters.
+*
+* OUTPUT:
+*	nfcCtrl  - Nand control and status information to be held by the user
+*		    and passed to all other APIs.
+*
+* RETURN:
+*       MV_OK		- On success,
+*	MV_BAD_PARAM 	- The required ECC mode not supported by flash.
+*	MV_NOT_SUPPORTED- The underlying flash device is not supported by HAL.
+*	MV_TIMEOUT 	- Error accessing the underlying flahs device.
+*	MV_FAIL		- On failure
+*******************************************************************************/
+MV_STATUS mvNfcInit(MV_NFC_INFO *nfcInfo, MV_NFC_CTRL *nfcCtrl)
+{
+	MV_U32 ctrl_reg;
+	MV_STATUS ret;
+	MV_U16 read_id = 0;
+	MV_U32 i;
+	/* Initial register values */
+	ctrl_reg = 0;
+
+	/* make sure ECC is disabled at this point - will be enabled only when issuing certain commands */
+	MV_REG_BIT_RESET(NFC_CONTROL_REG, NFC_CTRL_ECC_EN_MASK);
+	if (nfcInfo->eccMode != MV_NFC_ECC_HAMMING)
+		MV_REG_BIT_RESET(NFC_ECC_CONTROL_REG, NFC_ECC_BCH_EN_MASK);
+
+	if ((nfcInfo->eccMode == MV_NFC_ECC_BCH_1K) ||
+	    (nfcInfo->eccMode == MV_NFC_ECC_BCH_704B) || (nfcInfo->eccMode == MV_NFC_ECC_BCH_512B)) {
+		/* Disable spare */
+		ctrl_reg &= ~NFC_CTRL_SPARE_EN_MASK;
+	} else {
+		/* Enable spare */
+		ctrl_reg |= NFC_CTRL_SPARE_EN_MASK;
+	}
+
+	ctrl_reg &= ~NFC_CTRL_ECC_EN_MASK;
+
+	/* Configure flash interface */
+	if (nfcInfo->ifMode == MV_NFC_IF_1X16) {
+		nfcCtrl->flashWidth = 16;
+		nfcCtrl->dfcWidth = 16;
+		ctrl_reg |= (NFC_CTRL_DWIDTH_M_MASK | NFC_CTRL_DWIDTH_C_MASK);
+	} else if (nfcInfo->ifMode == MV_NFC_IF_2X8) {
+		nfcCtrl->flashWidth = 8;
+		nfcCtrl->dfcWidth = 16;
+		ctrl_reg |= NFC_CTRL_DWIDTH_C_MASK;
+	} else {
+		nfcCtrl->flashWidth = 8;
+		nfcCtrl->dfcWidth = 8;
+	}
+
+	/* Configure initial READ-ID byte count */
+	ctrl_reg |= (0x2 << NFC_CTRL_RD_ID_CNT_OFFS);
+
+	/* Configure the Arbiter */
+	ctrl_reg |= NFC_CTRL_ND_ARB_EN_MASK;
+
+	/* Write registers before device detection */
+	MV_REG_WRITE(NFC_CONTROL_REG, ctrl_reg);
+
+#ifdef CONFIG_MTD_NAND_NFC_INIT_RESET
+	/* reset the device */
+	ret = mvNfcReset();
+	if (ret != MV_OK)
+		return ret;
+#endif
+
+	/* Read the device ID */
+	ret = mvNfcReadIdNative(nfcCtrl->currCs, &read_id);
+	if (ret != MV_OK)
+		return ret;
+
+	/* Look for device ID in knwon device table */
+	for (i = 0; i < (sizeof(flashDeviceInfo) / sizeof(MV_NFC_FLASH_INFO)); i++) {
+		if (flashDeviceInfo[i].id == read_id)
+			break;
+	}
+	if (i == (sizeof(flashDeviceInfo) / sizeof(MV_NFC_FLASH_INFO)))
+		return MV_NOT_SUPPORTED;
+	else
+		nfcCtrl->flashIdx = i;
+
+	/* Configure the command set based on page size */
+	if (flashDeviceInfo[i].pgSz < MV_NFC_2KB_PAGE)
+		nfcCtrl->cmdsetIdx = MV_NFC_FLASH_SP_CMD_SET_IDX;
+	else
+		nfcCtrl->cmdsetIdx = MV_NFC_FLASH_LP_CMD_SET_IDX;
+
+	/* calculate Timing parameters */
+	ret = mvNfcTimingSet(nfcInfo->tclk, &flashDeviceInfo[i]);
+	if (ret != MV_OK)
+		return ret;
+
+	/* Configure the control register based on the device detected */
+	ctrl_reg = MV_REG_READ(NFC_CONTROL_REG);
+
+	/* Configure DMA */
+	if (nfcInfo->ioMode == MV_NFC_PDMA_ACCESS)
+		ctrl_reg |= NFC_CTRL_DMA_EN_MASK;
+	else
+		ctrl_reg &= ~NFC_CTRL_DMA_EN_MASK;
+
+	/* Configure Page size */
+	ctrl_reg &= ~NFC_CTRL_PAGE_SZ_MASK;
+	switch (flashDeviceInfo[i].pgSz) {
+	case MV_NFC_512B_PAGE:
+		ctrl_reg |= NFC_CTRL_PAGE_SZ_512B;
+		break;
+
+	case MV_NFC_2KB_PAGE:
+	case MV_NFC_4KB_PAGE:
+	case MV_NFC_8KB_PAGE:
+		ctrl_reg |= NFC_CTRL_PAGE_SZ_2KB;
+		break;
+
+	default:
+		return MV_BAD_PARAM;
+	}
+
+	/* Disable sequential read if indicated */
+	if (flashDeviceInfo[i].seqDis)
+		ctrl_reg |= NFC_CTRL_SEQ_DIS_MASK;
+	else
+		ctrl_reg &= ~NFC_CTRL_SEQ_DIS_MASK;
+
+	/* Configure the READ-ID count and row address start based on page size */
+	ctrl_reg &= ~(NFC_CTRL_RD_ID_CNT_MASK | NFC_CTRL_RA_START_MASK);
+	if (flashDeviceInfo[i].pgSz >= MV_NFC_2KB_PAGE) {
+		ctrl_reg |= NFC_CTRL_RD_ID_CNT_LP;
+		ctrl_reg |= NFC_CTRL_RA_START_MASK;
+	} else {
+		ctrl_reg |= NFC_CTRL_RD_ID_CNT_SP;
+	}
+
+	/* Confiugre pages per block */
+	ctrl_reg &= ~NFC_CTRL_PG_PER_BLK_MASK;
+	switch (flashDeviceInfo[i].pgPrBlk) {
+	case 32:
+		ctrl_reg |= NFC_CTRL_PG_PER_BLK_32;
+		break;
+
+	case 64:
+		ctrl_reg |= NFC_CTRL_PG_PER_BLK_64;
+		break;
+
+	case 128:
+		ctrl_reg |= NFC_CTRL_PG_PER_BLK_128;
+		break;
+
+	case 256:
+		ctrl_reg |= NFC_CTRL_PG_PER_BLK_256;
+		break;
+
+	default:
+		return MV_BAD_PARAM;
+	}
+
+	/* Write the updated control register */
+	MV_REG_WRITE(NFC_CONTROL_REG, ctrl_reg);
+
+#ifdef MV_INCLUDE_PDMA
+	/* DMA resource allocation */
+	if (nfcInfo->ioMode == MV_NFC_PDMA_ACCESS) {
+		/* Allocate command buffer */
+		nfcCtrl->cmdBuff.bufVirtPtr =
+			mvOsIoUncachedMalloc(nfcInfo->osHandle, (NFC_CMD_STRUCT_SIZE * MV_NFC_MAX_DESC_CHAIN),
+					&nfcCtrl->cmdBuff.bufPhysAddr, &nfcCtrl->cmdBuff.memHandle);
+		if (nfcCtrl->cmdBuff.bufVirtPtr == NULL)
+			return MV_OUT_OF_CPU_MEM;
+		nfcCtrl->cmdBuff.bufSize = (NFC_CMD_STRUCT_SIZE * MV_NFC_MAX_DESC_CHAIN);
+		nfcCtrl->cmdBuff.dataSize = (NFC_CMD_STRUCT_SIZE * MV_NFC_MAX_DESC_CHAIN);
+
+		/* Allocate command DMA descriptors */
+		nfcCtrl->cmdDescBuff.bufVirtPtr =
+			mvOsIoUncachedMalloc(nfcInfo->osHandle, (MV_PDMA_DESC_SIZE * (MV_NFC_MAX_DESC_CHAIN + 1)),
+					&nfcCtrl->cmdDescBuff.bufPhysAddr, &nfcCtrl->cmdDescBuff.memHandle);
+		if (nfcCtrl->cmdDescBuff.bufVirtPtr == NULL)
+			return MV_OUT_OF_CPU_MEM;
+		/* verify allignment to 128bits */
+		if ((MV_U32) nfcCtrl->cmdDescBuff.bufVirtPtr & 0xF) {
+			nfcCtrl->cmdDescBuff.bufVirtPtr =
+			    (MV_U8 *) (((MV_U32) nfcCtrl->cmdDescBuff.bufVirtPtr & ~0xF) + MV_PDMA_DESC_SIZE);
+			nfcCtrl->cmdDescBuff.bufPhysAddr =
+			    ((nfcCtrl->cmdDescBuff.bufPhysAddr & ~0xF) + MV_PDMA_DESC_SIZE);
+		}
+		nfcCtrl->cmdDescBuff.bufSize = (MV_PDMA_DESC_SIZE * MV_NFC_MAX_DESC_CHAIN);
+		nfcCtrl->cmdDescBuff.dataSize = (MV_PDMA_DESC_SIZE * MV_NFC_MAX_DESC_CHAIN);
+
+		/* Allocate data DMA descriptors */
+		nfcCtrl->dataDescBuff.bufVirtPtr =
+			mvOsIoUncachedMalloc(nfcInfo->osHandle, (MV_PDMA_DESC_SIZE * (MV_NFC_MAX_DESC_CHAIN + 1)),
+					&nfcCtrl->dataDescBuff.bufPhysAddr,
+					&nfcCtrl->dataDescBuff.memHandle);
+		if (nfcCtrl->dataDescBuff.bufVirtPtr == NULL)
+			return MV_OUT_OF_CPU_MEM;
+		/* verify allignment to 128bits */
+		if ((MV_U32) nfcCtrl->dataDescBuff.bufVirtPtr & 0xF) {
+			nfcCtrl->dataDescBuff.bufVirtPtr =
+			    (MV_U8 *) (((MV_U32) nfcCtrl->dataDescBuff.bufVirtPtr & ~0xF) + MV_PDMA_DESC_SIZE);
+			nfcCtrl->dataDescBuff.bufPhysAddr =
+			    ((nfcCtrl->dataDescBuff.bufPhysAddr & ~0xF) + MV_PDMA_DESC_SIZE);
+		}
+		nfcCtrl->dataDescBuff.bufSize = (MV_PDMA_DESC_SIZE * MV_NFC_MAX_DESC_CHAIN);
+		nfcCtrl->dataDescBuff.dataSize = (MV_PDMA_DESC_SIZE * MV_NFC_MAX_DESC_CHAIN);
+
+		/* Allocate Data DMA channel */
+		if (mvPdmaChanAlloc(MV_PDMA_NAND_DATA, nfcInfo->dataPdmaIntMask, &nfcCtrl->dataChanHndl) != MV_OK)
+			return MV_NO_RESOURCE;
+
+		/* Allocate Command DMA channel */
+		if (mvPdmaChanAlloc(MV_PDMA_NAND_COMMAND, nfcInfo->cmdPdmaIntMask, &nfcCtrl->cmdChanHndl) != MV_OK)
+			return MV_NO_RESOURCE;
+	}
+#endif
+
+	/* Initialize remaining fields in the CTRL structure */
+	nfcCtrl->autoStatusRead = nfcInfo->autoStatusRead;
+	nfcCtrl->readyBypass = nfcInfo->readyBypass;
+	nfcCtrl->ioMode = nfcInfo->ioMode;
+	nfcCtrl->eccMode = nfcInfo->eccMode;
+	nfcCtrl->ifMode = nfcInfo->ifMode;
+	nfcCtrl->currCs = MV_NFC_CS_NONE;
+	nfcCtrl->regsPhysAddr = nfcInfo->regsPhysAddr;
+#ifdef MV_INCLUDE_PDMA
+	nfcCtrl->dataPdmaIntMask = nfcInfo->dataPdmaIntMask;
+	nfcCtrl->cmdPdmaIntMask = nfcInfo->cmdPdmaIntMask;
+#endif
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcSelectChip
+*
+* DESCRIPTION:
+*       Set the currently active chip for next commands.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	chip	 - The chip number to operate on.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK	- On success,
+*	MV_FAIL	- On failure
+*******************************************************************************/
+MV_STATUS mvNfcSelectChip(MV_NFC_CTRL *nfcCtrl, MV_NFC_CHIP_SEL chip)
+{
+	nfcCtrl->currCs = chip;
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcDataLength
+*
+* DESCRIPTION:
+*       Get the length of data based on the NFC configuration
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	cmd	 - Command to be executed
+*
+* OUTPUT:
+*	data_len - length of data to be transfered
+*
+* RETURN:
+*       MV_OK	- On success,
+*	MV_FAIL	- On failure
+*******************************************************************************/
+MV_STATUS mvNfcDataLength(MV_NFC_CTRL *nfcCtrl, MV_NFC_CMD_TYPE cmd, MV_U32 *data_len)
+{
+	/* Decide read data size based on page size */
+	if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {	/* Small Page */
+		if (nfcCtrl->ifMode == MV_NFC_IF_2X8) {
+			if (nfcCtrl->eccMode == MV_NFC_ECC_HAMMING)
+				*data_len = NFC_RW_SP_G_HMNG_ECC_DATA_LEN;
+			else	/* No ECC */
+				*data_len = NFC_RW_SP_G_NO_ECC_DATA_LEN;
+		} else {
+			if (nfcCtrl->eccMode == MV_NFC_ECC_HAMMING)
+				*data_len = NFC_RW_SP_HMNG_ECC_DATA_LEN;
+			else	/* No ECC */
+				*data_len = NFC_RW_SP_NO_ECC_DATA_LEN;
+		}
+	} else {		/* Large Page */
+
+		if (nfcCtrl->ifMode == MV_NFC_IF_2X8) {
+			if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_2K)
+				*data_len = NFC_RW_LP_G_BCH_ECC_DATA_LEN;
+			else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_1K)
+				*data_len = NFC_RW_LP_BCH1K_ECC_DATA_LEN;
+			else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_704B)
+				*data_len = NFC_RW_LP_BCH704B_ECC_DATA_LEN;
+			else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_512B)
+				*data_len = NFC_RW_LP_BCH512B_ECC_DATA_LEN;
+			else if (nfcCtrl->eccMode == MV_NFC_ECC_HAMMING)
+				*data_len = NFC_RW_LP_G_HMNG_ECC_DATA_LEN;
+			else	/* No ECC */
+				*data_len = NFC_RW_LP_G_NO_ECC_DATA_LEN;
+		} else {
+			if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_2K)
+				*data_len = NFC_RW_LP_BCH_ECC_DATA_LEN;
+			else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_1K)
+				*data_len = NFC_RW_LP_BCH1K_ECC_DATA_LEN;
+			else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_704B)
+				*data_len = NFC_RW_LP_BCH704B_ECC_DATA_LEN;
+			else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_512B)
+				*data_len = NFC_RW_LP_BCH512B_ECC_DATA_LEN;
+			else if (nfcCtrl->eccMode == MV_NFC_ECC_HAMMING)
+				*data_len = NFC_RW_LP_HMNG_ECC_DATA_LEN;
+			else	/* No ECC */
+				*data_len = NFC_RW_LP_NO_ECC_DATA_LEN;
+		}
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcTransferDataLength
+*
+* DESCRIPTION:
+*       Get the length of data to be transfered based on the command type and
+*	NFC configuration
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	cmd	 - Command to be executed
+*
+* OUTPUT:
+*	data_len - length of data to be transfered
+*
+* RETURN:
+*       MV_OK	- On success,
+*	MV_FAIL	- On failure
+*******************************************************************************/
+MV_STATUS mvNfcTransferDataLength(MV_NFC_CTRL *nfcCtrl, MV_NFC_CMD_TYPE cmd, MV_U32 *data_len)
+{
+	switch (cmd) {
+	case MV_NFC_CMD_READ_ID:
+		if (nfcCtrl->ioMode == MV_NFC_PDMA_ACCESS)
+			*data_len = NFC_READ_ID_PDMA_DATA_LEN;
+		else
+			*data_len = NFC_READ_ID_PIO_DATA_LEN;
+		break;
+
+	case MV_NFC_CMD_READ_STATUS:
+		if (nfcCtrl->ioMode == MV_NFC_PDMA_ACCESS)
+			*data_len = NFC_READ_STATUS_PDMA_DATA_LEN;
+		else
+			*data_len = NFC_READ_STATUS_PIO_DATA_LEN;
+		break;
+
+	case MV_NFC_CMD_READ_MONOLITHIC:	/* Read a single 512B or 2KB page */
+	case MV_NFC_CMD_READ_MULTIPLE:
+	case MV_NFC_CMD_READ_NAKED:
+	case MV_NFC_CMD_READ_LAST_NAKED:
+	case MV_NFC_CMD_READ_DISPATCH:
+	case MV_NFC_CMD_WRITE_MONOLITHIC:	/* Program a single page of 512B or 2KB */
+	case MV_NFC_CMD_WRITE_MULTIPLE:
+	case MV_NFC_CMD_WRITE_NAKED:
+	case MV_NFC_CMD_WRITE_LAST_NAKED:
+	case MV_NFC_CMD_WRITE_DISPATCH:
+	case MV_NFC_CMD_EXIT_CACHE_READ:
+	case MV_NFC_CMD_CACHE_READ_SEQ:
+	case MV_NFC_CMD_CACHE_READ_START:
+		if (nfcCtrl->ioMode == MV_NFC_PDMA_ACCESS) {
+			/* Decide read data size based on page size */
+			if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {	/* Small Page */
+				*data_len = NFC_RW_SP_PDMA_DATA_LEN;
+			} else {	/* Large Page */
+
+				if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_2K)
+					*data_len = NFC_RW_LP_BCH_ECC_DATA_LEN;
+				else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_1K)
+					*data_len = NFC_RW_LP_BCH1K_ECC_DATA_LEN;
+				else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_704B)
+					*data_len = NFC_RW_LP_BCH704B_ECC_DATA_LEN;
+				else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_512B)
+					*data_len = NFC_RW_LP_BCH512B_ECC_DATA_LEN;
+				else	/* Hamming and No-Ecc */
+					*data_len = NFC_RW_LP_PDMA_DATA_LEN;
+			}
+		} else {	/* PIO mode */
+
+			/* Decide read data size based on page size */
+			if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {	/* Small Page */
+				if (nfcCtrl->ifMode == MV_NFC_IF_2X8) {
+					if (nfcCtrl->eccMode == MV_NFC_ECC_HAMMING)
+						*data_len = NFC_RW_SP_G_HMNG_ECC_DATA_LEN;
+					else	/* No ECC */
+						*data_len = NFC_RW_SP_G_NO_ECC_DATA_LEN;
+				} else {
+					if (nfcCtrl->eccMode == MV_NFC_ECC_HAMMING)
+						*data_len = NFC_RW_SP_HMNG_ECC_DATA_LEN;
+					else	/* No ECC */
+						*data_len = NFC_RW_SP_NO_ECC_DATA_LEN;
+				}
+			} else {	/* Large Page */
+
+				if (nfcCtrl->ifMode == MV_NFC_IF_2X8) {
+					if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_2K)
+						*data_len = NFC_RW_LP_G_BCH_ECC_DATA_LEN;
+					else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_1K)
+						*data_len = NFC_RW_LP_BCH1K_ECC_DATA_LEN;
+					else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_704B)
+						*data_len = NFC_RW_LP_BCH704B_ECC_DATA_LEN;
+					else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_512B)
+						*data_len = NFC_RW_LP_BCH512B_ECC_DATA_LEN;
+					else if (nfcCtrl->eccMode == MV_NFC_ECC_HAMMING)
+						*data_len = NFC_RW_LP_G_HMNG_ECC_DATA_LEN;
+					else	/* No ECC */
+						*data_len = NFC_RW_LP_G_NO_ECC_DATA_LEN;
+				} else {
+					if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_2K)
+						*data_len = NFC_RW_LP_BCH_ECC_DATA_LEN;
+					else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_1K)
+						*data_len = NFC_RW_LP_BCH1K_ECC_DATA_LEN;
+					else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_704B)
+						*data_len = NFC_RW_LP_BCH704B_ECC_DATA_LEN;
+					else if (nfcCtrl->eccMode == MV_NFC_ECC_BCH_512B)
+						*data_len = NFC_RW_LP_BCH512B_ECC_DATA_LEN;
+					else if (nfcCtrl->eccMode == MV_NFC_ECC_HAMMING)
+						*data_len = NFC_RW_LP_HMNG_ECC_DATA_LEN;
+					else	/* No ECC */
+						*data_len = NFC_RW_LP_NO_ECC_DATA_LEN;
+				}
+			}
+		}
+		break;
+
+	case MV_NFC_CMD_ERASE:
+	case MV_NFC_CMD_MULTIPLANE_ERASE:
+	case MV_NFC_CMD_RESET:
+	case MV_NFC_CMD_WRITE_DISPATCH_START:
+	case MV_NFC_CMD_WRITE_DISPATCH_END:
+		return MV_BAD_PARAM;
+
+	default:
+		return MV_BAD_PARAM;
+
+	};
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcBuildCommand
+*
+* DESCRIPTION:
+*	Build the command buffer
+*
+* INPUT:
+*	nfcCtrl	- Nand control structure.
+*	cmd	- Command to be executed
+*	cmdb	- Command buffer cmdb[0:3] to fill
+*
+* OUTPUT:
+*	cmdb	- Command buffer filled
+*
+* RETURN:
+*	None
+*******************************************************************************/
+static MV_STATUS mvNfcBuildCommand(MV_NFC_CTRL *nfcCtrl, MV_NFC_MULTI_CMD *descInfo, MV_U32 *cmdb)
+{
+	cmdb[0] = 0;
+	cmdb[1] = 0;
+	cmdb[2] = 0;
+	cmdb[3] = 0;
+	if (nfcCtrl->autoStatusRead)
+		cmdb[0] |= NFC_CB0_AUTO_RS_MASK;
+
+	if ((nfcCtrl->currCs == MV_NFC_CS_1) || (nfcCtrl->currCs == MV_NFC_CS_3))
+		cmdb[0] |= NFC_CB0_CSEL_MASK;
+
+	if ((nfcCtrl->currCs == MV_NFC_CS_2) || (nfcCtrl->currCs == MV_NFC_CS_3))
+		cmdb[2] |= NFC_CB2_CS_2_3_SELECT_MASK;
+
+	if (nfcCtrl->readyBypass)
+		cmdb[0] |= NFC_CB0_RDY_BYP_MASK;
+
+	switch (descInfo->cmd) {
+	case MV_NFC_CMD_READ_ID:
+		cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].readId & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		cmdb[0] |= ((NFC_READ_ID_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+		cmdb[0] |= NFC_CB0_CMD_TYPE_READ_ID;
+		break;
+
+	case MV_NFC_CMD_READ_STATUS:
+		cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].readStatus & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		cmdb[0] |= NFC_CB0_CMD_TYPE_STATUS;
+		break;
+
+	case MV_NFC_CMD_ERASE:
+	case MV_NFC_CMD_MULTIPLANE_ERASE:
+
+		if (descInfo->cmd == MV_NFC_CMD_ERASE)
+			cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].erase & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		if (descInfo->cmd == MV_NFC_CMD_MULTIPLANE_ERASE)
+			cmdb[0] |=
+			    (flashCmdSet[nfcCtrl->cmdsetIdx].multiplaneErase & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+
+		cmdb[0] |= ((NFC_ERASE_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+		cmdb[0] |= NFC_CB0_DBC_MASK;
+		cmdb[0] |= NFC_CB0_CMD_TYPE_ERASE;
+		cmdb[1] |= (descInfo->pageAddr & NFC_BLOCK_ADDR_BITS);
+		break;
+
+	case MV_NFC_CMD_RESET:
+		cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].reset & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		cmdb[0] |= NFC_CB0_CMD_TYPE_RESET;
+		break;
+
+	case MV_NFC_CMD_CACHE_READ_SEQ:
+		cmdb[0] = (flashCmdSet[nfcCtrl->cmdsetIdx].cacheReadSeq & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		break;
+
+	case MV_NFC_CMD_CACHE_READ_RAND:
+		cmdb[0] = (flashCmdSet[nfcCtrl->cmdsetIdx].cacheReadRand & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {
+			cmdb[1] |= ((descInfo->pageAddr << NFC_SP_PG_OFFS) & NFC_SP_PG_MASK);
+			if (descInfo->pageAddr & ~NFC_SP_PG_MASK)
+				cmdb[0] |=
+				    ((NFC_SP_BIG_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			else
+				cmdb[0] |= ((NFC_SP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+		} else {
+			cmdb[0] |= ((NFC_LP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			cmdb[0] |= NFC_CB0_DBC_MASK;
+			cmdb[1] |= ((descInfo->pageAddr << NFC_LP_PG_OFFS) & NFC_LP_PG_MASK);
+			cmdb[2] |= (descInfo->pageAddr >> (32 - NFC_LP_PG_OFFS));
+		}
+		cmdb[0] |= NFC_CB0_CMD_TYPE_READ;
+		break;
+
+	case MV_NFC_CMD_EXIT_CACHE_READ:
+		cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].exitCacheRead & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		break;
+
+	case MV_NFC_CMD_CACHE_READ_START:
+		cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].read1 & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {
+			cmdb[1] |= ((descInfo->pageAddr << NFC_SP_PG_OFFS) & NFC_SP_PG_MASK);
+			if (descInfo->pageAddr & ~NFC_SP_PG_MASK)
+				cmdb[0] |=
+				    ((NFC_SP_BIG_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			else
+				cmdb[0] |= ((NFC_SP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+		} else {
+			cmdb[0] |= ((NFC_LP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			cmdb[0] |= NFC_CB0_DBC_MASK;
+			cmdb[1] |= ((descInfo->pageAddr << NFC_LP_PG_OFFS) & NFC_LP_PG_MASK);
+			cmdb[2] |= (descInfo->pageAddr >> (32 - NFC_LP_PG_OFFS));
+		}
+		cmdb[0] |= NFC_CB0_CMD_TYPE_READ;
+		cmdb[0] |= NFC_CB0_LEN_OVRD_MASK;
+		break;
+
+	case MV_NFC_CMD_READ_MONOLITHIC:	/* Read a single 512B or 2KB page */
+	case MV_NFC_CMD_READ_MULTIPLE:
+	case MV_NFC_CMD_READ_NAKED:
+	case MV_NFC_CMD_READ_LAST_NAKED:
+	case MV_NFC_CMD_READ_DISPATCH:
+		cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].read1 & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {
+			cmdb[1] |= ((descInfo->pageAddr << NFC_SP_PG_OFFS) & NFC_SP_PG_MASK);
+			if (descInfo->pageAddr & ~NFC_SP_PG_MASK)
+				cmdb[0] |=
+				    ((NFC_SP_BIG_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			else
+				cmdb[0] |= ((NFC_SP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+		} else {
+			cmdb[0] |= ((NFC_LP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			cmdb[0] |= NFC_CB0_DBC_MASK;
+			cmdb[1] |= ((descInfo->pageAddr << NFC_LP_PG_OFFS) & NFC_LP_PG_MASK);
+			cmdb[2] |= (descInfo->pageAddr >> (32 - NFC_LP_PG_OFFS));
+		}
+		cmdb[0] |= NFC_CB0_CMD_TYPE_READ;
+
+		if (descInfo->length) {
+			cmdb[0] |= NFC_CB0_LEN_OVRD_MASK;
+			cmdb[3] |= (descInfo->length & 0xFFFF);
+		}
+
+		/* Check for extended command syntax */
+		switch (descInfo->cmd) {
+		case MV_NFC_CMD_READ_MULTIPLE:
+			cmdb[0] |= NFC_CB0_CMD_XTYPE_MULTIPLE;
+			break;
+		case MV_NFC_CMD_READ_NAKED:
+			cmdb[0] |= NFC_CB0_CMD_XTYPE_NAKED;
+			break;
+		case MV_NFC_CMD_READ_LAST_NAKED:
+			cmdb[0] |= NFC_CB0_CMD_XTYPE_LAST_NAKED;
+			break;
+		case MV_NFC_CMD_READ_DISPATCH:
+			cmdb[0] |= NFC_CB0_CMD_XTYPE_DISPATCH;
+			break;
+		default:
+			break;
+		};
+		break;
+
+	case MV_NFC_CMD_WRITE_MONOLITHIC:	/* Program a single page of 512B or 2KB */
+	case MV_NFC_CMD_WRITE_MULTIPLE:
+		/*case MV_NFC_CMD_WRITE_NAKED: */
+	case MV_NFC_CMD_WRITE_LAST_NAKED:
+	case MV_NFC_CMD_WRITE_DISPATCH:
+		cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].program & (NFC_CB0_CMD1_MASK | NFC_CB0_CMD2_MASK));
+		if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {
+			if (descInfo->pageAddr & ~NFC_SP_PG_MASK)
+				cmdb[0] |=
+				    ((NFC_SP_BIG_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			else
+				cmdb[0] |= ((NFC_SP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			cmdb[1] |= ((descInfo->pageAddr << NFC_SP_PG_OFFS) & NFC_SP_PG_MASK);
+		} else {
+			cmdb[0] |= ((NFC_LP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			cmdb[1] |= ((descInfo->pageAddr << NFC_LP_PG_OFFS) & NFC_LP_PG_MASK);
+			cmdb[2] |= (descInfo->pageAddr >> (32 - NFC_LP_PG_OFFS));
+		}
+		cmdb[0] |= NFC_CB0_DBC_MASK;
+		cmdb[0] |= NFC_CB0_CMD_TYPE_WRITE;
+
+		/* Check for extended syntax */
+		switch (descInfo->cmd) {
+		case MV_NFC_CMD_WRITE_MULTIPLE:
+			cmdb[0] |= NFC_CB0_CMD_XTYPE_MULTIPLE;
+			break;
+		case MV_NFC_CMD_WRITE_NAKED:
+			cmdb[0] |= NFC_CB0_CMD_XTYPE_NAKED;
+			break;
+		case MV_NFC_CMD_WRITE_LAST_NAKED:
+			cmdb[0] |= NFC_CB0_CMD_XTYPE_LAST_NAKED;
+			break;
+		case MV_NFC_CMD_WRITE_DISPATCH:
+			cmdb[0] |= NFC_CB0_CMD_XTYPE_DISPATCH;
+			break;
+		default:
+			break;
+		};
+		break;
+
+	case MV_NFC_CMD_WRITE_DISPATCH_START:
+		cmdb[0] |= (flashCmdSet[nfcCtrl->cmdsetIdx].program & NFC_CB0_CMD1_MASK);
+		if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {
+			if (descInfo->pageAddr & ~NFC_SP_PG_MASK)
+				cmdb[0] |=
+				    ((NFC_SP_BIG_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			else
+				cmdb[0] |= ((NFC_SP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			cmdb[1] |= ((descInfo->pageAddr << NFC_SP_PG_OFFS) & NFC_SP_PG_MASK);
+		} else {
+			cmdb[0] |= ((NFC_LP_READ_ADDR_LEN << NFC_CB0_ADDR_CYC_OFFS) & NFC_CB0_ADDR_CYC_MASK);
+			cmdb[1] |= ((descInfo->pageAddr << NFC_LP_PG_OFFS) & NFC_LP_PG_MASK);
+			cmdb[2] |= (descInfo->pageAddr >> (32 - NFC_LP_PG_OFFS));
+		}
+		cmdb[0] |= NFC_CB0_CMD_TYPE_WRITE;
+		cmdb[0] |= NFC_CB0_CMD_XTYPE_DISPATCH;
+		break;
+
+	case MV_NFC_CMD_WRITE_NAKED:
+		cmdb[0] |= NFC_CB0_CMD_TYPE_WRITE;
+		cmdb[0] |= NFC_CB0_CMD_XTYPE_NAKED;
+		if (descInfo->length) {
+			cmdb[0] |= NFC_CB0_LEN_OVRD_MASK;
+			cmdb[3] |= (descInfo->length & 0xFFFF);
+		}
+		break;
+
+	case MV_NFC_CMD_WRITE_DISPATCH_END:
+		cmdb[0] |= ((flashCmdSet[nfcCtrl->cmdsetIdx].program >> 8) & NFC_CB0_CMD1_MASK);
+		cmdb[0] |= NFC_CB0_CMD_TYPE_WRITE;
+		cmdb[0] |= NFC_CB0_CMD_XTYPE_DISPATCH;
+		break;
+
+	default:
+		return MV_BAD_PARAM;
+	}
+
+	/* update page count */
+	cmdb[2] |= (((descInfo->pageCount - 1) << NFC_PG_CNT_OFFS) & NFC_PG_CNT_MASK);
+
+	return MV_OK;
+}
+
+#ifdef MV_INCLUDE_PDMA
+/*******************************************************************************
+* mvNfcCommandMultiple
+*
+* DESCRIPTION:
+*       Issue a command to the NAND controller.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	cmd	 - The command to issue.
+*	pageAddr - The page number to perform the command on (If the command
+*		   requires a flash offset), block address in erase.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK	   - On success,
+*	MV_TIMEOUT - Timeout while waiting for command request.
+*	MV_FAIL	   - On failure
+*******************************************************************************/
+MV_STATUS mvNfcCommandMultiple(MV_NFC_CTRL *nfcCtrl, MV_NFC_MULTI_CMD *descInfo, MV_U32 descCnt)
+{
+	MV_U32 reg, i, buff;
+	MV_U32 errCode = MV_OK;
+	MV_U32 cmdb[4];
+	MV_NFC_CMD *cmdVirtPtr = (MV_NFC_CMD *) nfcCtrl->cmdBuff.bufVirtPtr;
+	MV_NFC_CMD *cmdPhysPtr = (MV_NFC_CMD *) nfcCtrl->cmdBuff.bufPhysAddr;
+	MV_PDMA_DESC *cmdDescVirtPtr = (MV_PDMA_DESC *) nfcCtrl->cmdDescBuff.bufVirtPtr;
+	MV_PDMA_DESC *cmdDescPhysPtr = (MV_PDMA_DESC *) nfcCtrl->cmdDescBuff.bufPhysAddr;
+	MV_PDMA_DESC *dataDescVirtPtr = (MV_PDMA_DESC *) nfcCtrl->dataDescBuff.bufVirtPtr;
+	MV_PDMA_DESC *dataDescPhysPtr = (MV_PDMA_DESC *) nfcCtrl->dataDescBuff.bufPhysAddr;
+	MV_U32 xferLen;
+	MV_U32 dataDescCount = 0;
+	MV_U32 nPage;
+	MV_U32 timeout = 10000;
+	MV_STATUS ret;
+
+	/* Check MAX descriptor count */
+	if (descCnt > MV_NFC_MAX_DESC_CHAIN)
+		return MV_BAD_PARAM;
+
+	/* If not in PDMA fail operation */
+	if (nfcCtrl->ioMode != MV_NFC_PDMA_ACCESS)
+		return MV_BAD_PARAM;
+
+	/* Check that a chip was selected */
+	if (nfcCtrl->currCs == MV_NFC_CS_NONE)
+		return MV_FAIL;
+
+	/* Start the whole command chain through setting the ND_RUN */
+	/* Setting ND_RUN bit to start the new transaction - verify that controller in idle state */
+	while (timeout > 0) {
+		reg = MV_REG_READ(NFC_CONTROL_REG);
+		if (!(reg & NFC_CTRL_ND_RUN_MASK))
+			break;
+		timeout--;
+	}
+	if (timeout == 0)
+		return MV_BAD_STATE;
+
+	for (i = 0; i < descCnt; i++) {
+		if ((descInfo[i].cmd != MV_NFC_CMD_ERASE) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_MULTIPLANE_ERASE) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_RESET) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_EXIT_CACHE_READ) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_CACHE_READ_START) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_READ_DISPATCH) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_WRITE_DISPATCH_START) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_WRITE_DISPATCH_END)) {
+			/* Get transfer data length for this command type */
+			errCode = mvNfcTransferDataLength(nfcCtrl, descInfo[i].cmd, &xferLen);
+			if (errCode != MV_OK)
+				return errCode;
+		}
+
+		if (nfcCtrl->eccMode != MV_NFC_ECC_DISABLE) {
+			if ((descInfo[i].cmd == MV_NFC_CMD_READ_ID) || (descInfo[i].cmd == MV_NFC_CMD_READ_STATUS) ||
+			    (descInfo[i].cmd == MV_NFC_CMD_ERASE) || (descInfo[i].cmd == MV_NFC_CMD_RESET)) {
+				/* disable ECC for these commands */
+				MV_REG_BIT_RESET(NFC_CONTROL_REG, NFC_CTRL_ECC_EN_MASK);
+				if (nfcCtrl->eccMode != MV_NFC_ECC_HAMMING)
+					MV_REG_BIT_RESET(NFC_ECC_CONTROL_REG, NFC_ECC_BCH_EN_MASK);
+			} else {
+				/* enable ECC for all other commands */
+				MV_REG_BIT_SET(NFC_CONTROL_REG, NFC_CTRL_ECC_EN_MASK);
+				if (nfcCtrl->eccMode != MV_NFC_ECC_HAMMING)
+					MV_REG_BIT_SET(NFC_ECC_CONTROL_REG, NFC_ECC_BCH_EN_MASK);
+			}
+		}
+
+		/* Build the command buffer */
+		ret = mvNfcBuildCommand(nfcCtrl, &descInfo[i], cmdb);
+		if (ret != MV_OK)
+			return ret;
+
+		/* Fill Command data */
+		cmdVirtPtr[i].cmdb0 = cmdb[0];
+		cmdVirtPtr[i].cmdb1 = cmdb[1];
+		cmdVirtPtr[i].cmdb2 = cmdb[2];
+		cmdVirtPtr[i].cmdb3 = cmdb[3];
+
+		/* Hook to the previous descriptor if exists */
+		if (i != 0) {
+			cmdDescVirtPtr[i - 1].physDescPtr = (MV_U32) &cmdDescPhysPtr[i];
+			cmdVirtPtr[i - 1].cmdb0 |= NFC_CB0_NEXT_CMD_MASK;
+		}
+
+		/* Fill Command Descriptor */
+		cmdDescVirtPtr[i].physDescPtr = 0x1;
+		cmdDescVirtPtr[i].physSrcAddr = (MV_U32) &cmdPhysPtr[i];
+		cmdDescVirtPtr[i].physDestAddr = nfcCtrl->regsPhysAddr + NFC_CMD_BUFF_ADDR;
+		cmdDescVirtPtr[i].commandValue = mvPdmaCommandRegCalc(&nfcCtrl->cmdChanHndl, MV_PDMA_MEM_TO_PERIPH,
+								      NFC_CMD_BUFF_SIZE(cmdb[0]));
+
+		/* Check if data dma need to be operated for this command */
+		if ((descInfo[i].cmd != MV_NFC_CMD_ERASE) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_MULTIPLANE_ERASE) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_RESET) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_EXIT_CACHE_READ) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_CACHE_READ_START) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_READ_DISPATCH) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_WRITE_DISPATCH_START) &&
+		    (descInfo[i].cmd != MV_NFC_CMD_WRITE_DISPATCH_END)) {
+			for (nPage = 0; nPage < descInfo[i].pageCount; nPage++) {
+				if (dataDescCount != 0)
+					dataDescVirtPtr[dataDescCount - 1].physDescPtr =
+					    (MV_U32) &dataDescPhysPtr[dataDescCount];
+				/* Fill Data Descriptor */
+				if ((descInfo[i].cmd == MV_NFC_CMD_READ_MONOLITHIC) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_READ_MULTIPLE) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_CACHE_READ_SEQ) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_EXIT_CACHE_READ) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_CACHE_READ_RAND) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_READ_NAKED) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_READ_LAST_NAKED) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_READ_DISPATCH) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_READ_ID) ||
+				    (descInfo[i].cmd == MV_NFC_CMD_READ_STATUS)) {
+					if (descInfo[i].numSgBuffs == 1) {
+						/* A single buffer, use physAddr */
+						dataDescVirtPtr[dataDescCount].physSrcAddr =
+						    nfcCtrl->regsPhysAddr + NFC_DATA_BUFF_ADDR;
+						dataDescVirtPtr[dataDescCount].physDestAddr =
+						    descInfo[i].physAddr + nPage * xferLen;
+						dataDescVirtPtr[dataDescCount].commandValue =
+						    mvPdmaCommandRegCalc(&nfcCtrl->dataChanHndl, MV_PDMA_PERIPH_TO_MEM,
+									 (descInfo[i].length ? descInfo[i].
+									  length : xferLen));
+					} else {
+						/* Scatter-gather operation, use sgBuffAdd */
+						for (buff = 0; buff < descInfo[i].numSgBuffs; buff++) {
+							if (buff != 0)
+								dataDescVirtPtr[dataDescCount - 1].physDescPtr =
+								    (MV_U32) &dataDescPhysPtr[dataDescCount];
+							dataDescVirtPtr[dataDescCount].physSrcAddr =
+							    nfcCtrl->regsPhysAddr + NFC_DATA_BUFF_ADDR;
+							dataDescVirtPtr[dataDescCount].physDestAddr =
+							    descInfo[i].sgBuffAddr[buff];
+							dataDescVirtPtr[dataDescCount].commandValue =
+							    mvPdmaCommandRegCalc(&nfcCtrl->dataChanHndl,
+										 MV_PDMA_PERIPH_TO_MEM,
+										 descInfo[i].sgBuffSize[buff]);
+							dataDescCount++;
+						}
+						dataDescCount--;
+					}
+				} else {	/* Write */
+
+					if (descInfo[i].numSgBuffs == 1) {
+						/* A single buffer, use physAddr */
+						dataDescVirtPtr[dataDescCount].physSrcAddr =
+						    descInfo[i].physAddr + nPage * xferLen;
+						dataDescVirtPtr[dataDescCount].physDestAddr =
+						    nfcCtrl->regsPhysAddr + NFC_DATA_BUFF_ADDR;
+						dataDescVirtPtr[dataDescCount].commandValue =
+						    mvPdmaCommandRegCalc(&nfcCtrl->dataChanHndl, MV_PDMA_MEM_TO_PERIPH,
+									 (descInfo[i].length ? descInfo[i].
+									  length : xferLen));
+					} else {
+						/* Scatter-gather operation, use sgBuffAdd */
+						for (buff = 0; buff < descInfo[i].numSgBuffs; buff++) {
+							if (buff != 0)
+								dataDescVirtPtr[dataDescCount - 1].physDescPtr =
+								    (MV_U32) &dataDescPhysPtr[dataDescCount];
+							dataDescVirtPtr[dataDescCount].physSrcAddr =
+							    descInfo[i].sgBuffAddr[buff];
+							dataDescVirtPtr[dataDescCount].physDestAddr =
+							    nfcCtrl->regsPhysAddr + NFC_DATA_BUFF_ADDR;
+							dataDescVirtPtr[dataDescCount].commandValue =
+							    mvPdmaCommandRegCalc(&nfcCtrl->dataChanHndl,
+										 MV_PDMA_MEM_TO_PERIPH,
+										 descInfo[i].sgBuffSize[buff]);
+							dataDescCount++;
+						}
+						dataDescCount--;
+					}
+				}
+
+				dataDescVirtPtr[dataDescCount].physDescPtr = 0x1;
+				dataDescCount++;
+
+				if (dataDescCount > MV_NFC_MAX_DESC_CHAIN)
+					return MV_OUT_OF_RANGE;
+			}
+		}
+	}
+
+#if 0
+	DBGPRINT((DBGLVL "\ncmdDescPhysPtr  = %08x, Count = %d\n", (MV_U32) cmdDescPhysPtr, descCnt));
+	for (nPage = 0; nPage < descCnt; nPage++) {
+		DBGPRINT((DBGLVL "    Command[%d] physDescPtr  = %08x\n", nPage, cmdDescVirtPtr[nPage].physDescPtr));
+		DBGPRINT((DBGLVL "    Command[%d] physSrcAddr  = %08x\n", nPage, cmdDescVirtPtr[nPage].physSrcAddr));
+		DBGPRINT((DBGLVL "    Command[%d] physDestAddr = %08x\n", nPage, cmdDescVirtPtr[nPage].physDestAddr));
+		DBGPRINT((DBGLVL "    Command[%d] commandValue = %08x\n", nPage, cmdDescVirtPtr[nPage].commandValue));
+		DBGPRINT((DBGLVL "      NDCB0 = %08x, NDCB1 = %08x, NDCB2 = %08x, NDCB3 = %08x\n",
+			  cmdVirtPtr[nPage].cmdb0, cmdVirtPtr[nPage].cmdb1, cmdVirtPtr[nPage].cmdb2,
+			  cmdVirtPtr[nPage].cmdb3));
+	}
+
+	DBGPRINT((DBGLVL "dataDescPhysPtr  = %08x, Count = %d\n", (MV_U32) dataDescPhysPtr, dataDescCount));
+	for (nPage = 0; nPage < dataDescCount; nPage++) {
+		DBGPRINT((DBGLVL "    Data[%d] physDescPtr  = %08x\n", nPage, dataDescVirtPtr[nPage].physDescPtr));
+		DBGPRINT((DBGLVL "    Data[%d] physSrcAddr  = %08x\n", nPage, dataDescVirtPtr[nPage].physSrcAddr));
+		DBGPRINT((DBGLVL "    Data[%d] physDestAddr = %08x\n", nPage, dataDescVirtPtr[nPage].physDestAddr));
+		DBGPRINT((DBGLVL "    Data[%d] commandValue = %08x\n", nPage, dataDescVirtPtr[nPage].commandValue));
+	}
+#endif
+	if (dataDescCount) {
+		/* enable interrupts in the last data descriptor. */
+		mvPdmaCommandIntrEnable(&nfcCtrl->dataChanHndl, &(dataDescVirtPtr[dataDescCount - 1].commandValue));
+		/* operate the data DMA */
+		if (mvPdmaChanTransfer(&nfcCtrl->dataChanHndl, MV_PDMA_PERIPH_TO_MEM,
+				       0, 0, 0, (MV_U32) dataDescPhysPtr) != MV_OK)
+			return MV_HW_ERROR;
+	}
+
+	/* operate the command DMA */
+	if (mvPdmaChanTransfer(&nfcCtrl->cmdChanHndl, MV_PDMA_MEM_TO_PERIPH, 0, 0, 0, (MV_U32) cmdDescPhysPtr) != MV_OK)
+		return MV_HW_ERROR;
+
+	/* Clear all old events on the status register */
+	reg = MV_REG_READ(NFC_STATUS_REG);
+	MV_REG_WRITE(NFC_STATUS_REG, reg);
+
+	/* Start the whole command chain through setting the ND_RUN */
+	/* Setting ND_RUN bit to start the new transaction - verify that controller in idle state */
+	while (timeout > 0) {
+		reg = MV_REG_READ(NFC_CONTROL_REG);
+		if (!(reg & NFC_CTRL_ND_RUN_MASK))
+			break;
+		timeout--;
+	}
+	if (timeout == 0)
+		return MV_BAD_STATE;
+
+	reg |= NFC_CTRL_ND_RUN_MASK;
+	MV_REG_WRITE(NFC_CONTROL_REG, reg);
+
+	return MV_OK;
+}
+#endif
+
+/*******************************************************************************
+* mvNfcCommandPio
+*
+* DESCRIPTION:
+*       Issue a command to the NAND controller.
+*
+* INPUT:
+*	nfcCtrl   - Nand control structure.
+*	cmd_descr - The command to issue, page address, page number, data length
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK	   - On success,
+*	MV_TIMEOUT - Timeout while waiting for command request.
+*	MV_FAIL	   - On failure
+*******************************************************************************/
+MV_STATUS mvNfcCommandPio(MV_NFC_CTRL *nfcCtrl, MV_NFC_MULTI_CMD *cmd_desc, MV_BOOL next)
+{
+	MV_U32 reg;
+	MV_U32 errCode = MV_OK;
+	MV_U32 cmdb_pio[4];
+	MV_U32 *cmdb;
+	MV_U32 timeout = 10000;
+	MV_STATUS ret;
+
+	/* Check that a chip was selected */
+	if (nfcCtrl->currCs == MV_NFC_CS_NONE)
+		return MV_FAIL;
+
+	/* Clear all old events on the status register */
+	reg = MV_REG_READ(NFC_STATUS_REG);
+	MV_REG_WRITE(NFC_STATUS_REG, reg);
+
+	/* Setting ND_RUN bit to start the new transaction - verify that controller in idle state */
+	while (timeout > 0) {
+		reg = MV_REG_READ(NFC_CONTROL_REG);
+		if (!(reg & NFC_CTRL_ND_RUN_MASK))
+			break;
+		timeout--;
+	}
+
+	if (timeout == 0)
+		return MV_BAD_STATE;
+
+	reg |= NFC_CTRL_ND_RUN_MASK;
+	MV_REG_WRITE(NFC_CONTROL_REG, reg);
+
+	/* Wait for Command WRITE request */
+	errCode = mvDfcWait4Complete(NFC_SR_WRCMDREQ_MASK, 1);
+	if (errCode != MV_OK)
+		return errCode;
+	/* Build 12 byte Command */
+	if (nfcCtrl->ioMode == MV_NFC_PDMA_ACCESS)
+		cmdb = (MV_U32 *) nfcCtrl->cmdBuff.bufVirtPtr;
+	else			/* PIO mode */
+		cmdb = cmdb_pio;
+
+	if (nfcCtrl->eccMode != MV_NFC_ECC_DISABLE) {
+		switch (cmd_desc->cmd) {
+		case MV_NFC_CMD_READ_MONOLITHIC:
+		case MV_NFC_CMD_READ_MULTIPLE:
+		case MV_NFC_CMD_READ_NAKED:
+		case MV_NFC_CMD_READ_LAST_NAKED:
+		case MV_NFC_CMD_WRITE_MONOLITHIC:
+		case MV_NFC_CMD_WRITE_MULTIPLE:
+		case MV_NFC_CMD_WRITE_NAKED:
+		case MV_NFC_CMD_WRITE_LAST_NAKED:
+			if (nfcCtrl->eccMode != MV_NFC_ECC_DISABLE) {
+				MV_REG_BIT_SET(NFC_CONTROL_REG, NFC_CTRL_ECC_EN_MASK);
+				if (nfcCtrl->eccMode != MV_NFC_ECC_HAMMING)
+					MV_REG_BIT_SET(NFC_ECC_CONTROL_REG, NFC_ECC_BCH_EN_MASK);
+			}
+			break;
+
+		default:
+			/* disable ECC for non-data commands */
+			MV_REG_BIT_RESET(NFC_CONTROL_REG, NFC_CTRL_ECC_EN_MASK);
+			MV_REG_BIT_RESET(NFC_ECC_CONTROL_REG, NFC_ECC_BCH_EN_MASK);
+			break;
+		};
+	}
+
+	/* Build the command buffer */
+	ret = mvNfcBuildCommand(nfcCtrl, cmd_desc, cmdb);
+	if (ret != MV_OK)
+		return ret;
+
+	/* If next command, link to it */
+	if (next)
+		cmdb[0] |= NFC_CB0_NEXT_CMD_MASK;
+
+	/* issue command */
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, cmdb[0]);
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, cmdb[1]);
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, cmdb[2]);
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, cmdb[3]);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcStatusGet
+*
+* DESCRIPTION:
+*       Retrieve the NAND controller status to monitor the NAND access sequence.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	cmd	 - The last issued command to get the status for.
+*
+* OUTPUT:
+*	value	- Relevant only if one of the MV_NFC_STATUS_BBD OR
+*		  MV_NFC_STATUS_COR_ERROR errors is turned on.
+*		  For MV_NFC_STATUS_COR_ERROR: Holds the errors count.
+*		  For MV_NFC_STATUS_BBD: Holds the bad block address.
+*		  If error value is not desired, pass NULL as input.
+*
+* RETURN:
+*	A bitmask of the MV_NFC_STATUS_XXX status bits.
+*******************************************************************************/
+MV_U32 mvNfcStatusGet(MV_NFC_CTRL *nfcCtrl, MV_NFC_CMD_TYPE cmd, MV_U32 *value)
+{
+	MV_U32 reg, ret;
+
+	reg = MV_REG_READ(NFC_STATUS_REG);
+	if (reg == 0)
+		return 0;
+
+	if (value)
+		*value = ((reg & NFC_SR_ERR_CNT_MASK) >> NFC_SR_ERR_CNT_OFFS);
+
+	if ((nfcCtrl->currCs == MV_NFC_CS_0) || (nfcCtrl->currCs == MV_NFC_CS_2)) {
+		/* Clear out all non related interrupts */
+		reg &= (NFC_SR_CS0_BBD_MASK | NFC_SR_CS0_CMDD_MASK | NFC_SR_CS0_PAGED_MASK |
+			NFC_SR_RDY0_MASK | NFC_SR_WRCMDREQ_MASK | NFC_SR_RDDREQ_MASK |
+			NFC_SR_WRDREQ_MASK | NFC_SR_CORERR_MASK | NFC_SR_UNCERR_MASK);
+
+		ret = (reg & (NFC_SR_WRCMDREQ_MASK | NFC_SR_RDDREQ_MASK |
+			      NFC_SR_WRDREQ_MASK | NFC_SR_CORERR_MASK | NFC_SR_UNCERR_MASK));
+
+		if (reg & NFC_SR_CS0_BBD_MASK)
+			ret |= MV_NFC_STATUS_BBD;
+		if (reg & NFC_SR_CS0_CMDD_MASK)
+			ret |= MV_NFC_STATUS_CMDD;
+		if (reg & NFC_SR_CS0_PAGED_MASK)
+			ret |= MV_NFC_STATUS_PAGED;
+		if (reg & NFC_SR_RDY0_MASK)
+			ret |= MV_NFC_STATUS_RDY;
+	} else if ((nfcCtrl->currCs == MV_NFC_CS_1) || (nfcCtrl->currCs == MV_NFC_CS_3)) {
+		reg &= (NFC_SR_CS1_BBD_MASK | NFC_SR_CS1_CMDD_MASK | NFC_SR_CS1_PAGED_MASK |
+			NFC_SR_RDY1_MASK | NFC_SR_WRCMDREQ_MASK | NFC_SR_RDDREQ_MASK |
+			NFC_SR_WRDREQ_MASK | NFC_SR_CORERR_MASK | NFC_SR_UNCERR_MASK);
+
+		ret = (reg & (NFC_SR_WRCMDREQ_MASK | NFC_SR_RDDREQ_MASK |
+			      NFC_SR_WRDREQ_MASK | NFC_SR_CORERR_MASK | NFC_SR_UNCERR_MASK));
+
+		if (reg & NFC_SR_CS1_BBD_MASK)
+			ret |= MV_NFC_STATUS_BBD;
+		if (reg & NFC_SR_CS1_CMDD_MASK)
+			ret |= MV_NFC_STATUS_CMDD;
+		if (reg & NFC_SR_CS1_PAGED_MASK)
+			ret |= MV_NFC_STATUS_PAGED;
+		if (reg & NFC_SR_RDY1_MASK)
+			ret |= MV_NFC_STATUS_RDY;
+	} else {
+		reg &= (NFC_SR_WRCMDREQ_MASK | NFC_SR_RDDREQ_MASK |
+			NFC_SR_WRDREQ_MASK | NFC_SR_CORERR_MASK | NFC_SR_UNCERR_MASK);
+
+		ret = reg;
+	}
+
+	/* Clear out all reported events */
+	MV_REG_WRITE(NFC_STATUS_REG, reg);
+
+	return ret;
+}
+
+/*******************************************************************************
+* mvNfcIntrSet
+*
+* DESCRIPTION:
+*       Enable / Disable a given set of the Nand controller interrupts.
+*
+* INPUT:
+*	inatMask - A bitmask of the interrupts to enable / disable.
+*	enable	 - MV_TRUE: Unmask the interrupts
+*		   MV_FALSE: Mask the interrupts.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK	- On success,
+*	MV_FAIL	- On failure
+*******************************************************************************/
+MV_STATUS mvNfcIntrSet(MV_NFC_CTRL *nfcCtrl, MV_U32 intMask, MV_BOOL enable)
+{
+	MV_U32 reg;
+	MV_U32 msk = (intMask & (NFC_SR_WRCMDREQ_MASK | NFC_SR_RDDREQ_MASK | NFC_SR_WRDREQ_MASK |
+				 NFC_SR_CORERR_MASK | NFC_SR_UNCERR_MASK));
+
+	if ((nfcCtrl->currCs == MV_NFC_CS_0) || (nfcCtrl->currCs == MV_NFC_CS_2)) {
+		if (intMask & MV_NFC_STATUS_BBD)
+			msk |= NFC_SR_CS0_BBD_MASK;
+		if (intMask & MV_NFC_STATUS_CMDD)
+			msk |= NFC_SR_CS0_CMDD_MASK;
+		if (intMask & MV_NFC_STATUS_PAGED)
+			msk |= NFC_SR_CS0_PAGED_MASK;
+		if (intMask & MV_NFC_STATUS_RDY)
+			msk |= NFC_SR_RDY0_MASK;
+	} else if ((nfcCtrl->currCs == MV_NFC_CS_1) || (nfcCtrl->currCs == MV_NFC_CS_3)) {
+		if (intMask & MV_NFC_STATUS_BBD)
+			msk |= NFC_SR_CS1_BBD_MASK;
+		if (intMask & MV_NFC_STATUS_CMDD)
+			msk |= NFC_SR_CS1_CMDD_MASK;
+		if (intMask & MV_NFC_STATUS_PAGED)
+			msk |= NFC_SR_CS1_PAGED_MASK;
+		if (intMask & MV_NFC_STATUS_RDY)
+			msk |= NFC_SR_RDY0_MASK;
+	}
+
+	reg = MV_REG_READ(NFC_CONTROL_REG);
+	if (enable)
+		reg &= ~msk;
+	else
+		reg |= msk;
+
+	MV_REG_WRITE(NFC_CONTROL_REG, reg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcReadWrite
+*
+* DESCRIPTION:
+*       Perform a read / write operation of a previously issued command.
+*	When working in PIO mode, this function will perform the read / write
+*	operation from / to the supplied buffer.
+*	when working in PDMA mode, this function will trigger the PDMA to start
+*	the data transfer.
+*	In all cases, the user is responsible to make sure that the data
+*	transfer operation was done successfully by polling the command done bit.
+*	Before calling this function, the Data-Read/Write request interrupts
+*	should be disabled (the one relevant to the command being processed).
+*
+* INPUT:
+*	nfcCtrl     - Nand control structure.
+*	cmd	    - The previously issued command.
+*	virtBufAddr - [Relevant only when working in PIO mode]
+*		      The virtual address of the buffer to read to / write from.
+*	physBufAddr - [Relevant only when working in PDMA mode]
+*		      The physical address of the buffer to read to / write from.
+*		      The buffer should be cache coherent for PDMA access.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK	- On success,
+*	MV_FAIL	- On failure
+*******************************************************************************/
+MV_STATUS mvNfcReadWrite(MV_NFC_CTRL *nfcCtrl, MV_NFC_CMD_TYPE cmd, MV_U32 *virtBufAddr, MV_U32 physBuffAddr)
+{
+	MV_U32 data_len = 0;
+	MV_U32 i;
+	MV_STATUS errCode;
+
+	errCode = mvNfcTransferDataLength(nfcCtrl, cmd, &data_len);
+	if (errCode != MV_OK)
+		return errCode;
+
+	switch (cmd) {
+	case MV_NFC_CMD_READ_ID:
+	case MV_NFC_CMD_READ_STATUS:
+	case MV_NFC_CMD_READ_MONOLITHIC:	/* Read a single 512B or 2KB page */
+	case MV_NFC_CMD_READ_MULTIPLE:
+	case MV_NFC_CMD_READ_NAKED:
+	case MV_NFC_CMD_READ_LAST_NAKED:
+	case MV_NFC_CMD_READ_DISPATCH:
+		/* Issue command based on IO mode */
+		if (nfcCtrl->ioMode == MV_NFC_PDMA_ACCESS) {
+#ifdef MV_INCLUDE_PDMA
+			/* operate the DMA */
+			if (mvPdmaChanTransfer(&nfcCtrl->dataChanHndl, MV_PDMA_PERIPH_TO_MEM,
+					       nfcCtrl->regsPhysAddr + NFC_DATA_BUFF_ADDR,
+					       physBuffAddr, data_len, 0) != MV_OK)
+				return MV_HW_ERROR;
+#else
+			return MV_NOT_SUPPORTED;
+#endif
+		} else {	/* PIO mode */
+
+			for (i = 0; i < data_len; i += 4) {
+				*virtBufAddr = MV_REG_READ(NFC_DATA_BUFF_REG);
+				virtBufAddr++;
+			}
+		}
+		break;
+
+	case MV_NFC_CMD_WRITE_MONOLITHIC:	/* Program a single page of 512B or 2KB */
+	case MV_NFC_CMD_WRITE_MULTIPLE:
+	case MV_NFC_CMD_WRITE_NAKED:
+	case MV_NFC_CMD_WRITE_LAST_NAKED:
+	case MV_NFC_CMD_WRITE_DISPATCH:
+		/* Issue command based on IO mode */
+		if (nfcCtrl->ioMode == MV_NFC_PDMA_ACCESS) {
+#ifdef MV_INCLUDE_PDMA
+			/* operate the DMA */
+			if (mvPdmaChanTransfer(&nfcCtrl->dataChanHndl, MV_PDMA_MEM_TO_PERIPH,
+					       physBuffAddr, nfcCtrl->regsPhysAddr + NFC_DATA_BUFF_ADDR,
+					       data_len, 0) != MV_OK)
+				return MV_HW_ERROR;
+#else
+			return MV_NOT_SUPPORTED;
+#endif
+		} else {	/* PIO mode */
+
+			for (i = 0; i < data_len; i += 4) {
+				MV_REG_WRITE(NFC_DATA_BUFF_REG, *virtBufAddr);
+				virtBufAddr++;
+			}
+		}
+		break;
+
+	default:
+		return MV_BAD_PARAM;
+	};
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcReadWritePio
+*
+* DESCRIPTION:
+*       Perform PIO read / write operation to the specified buffer.
+*
+* INPUT:
+*	nfcCtrl     - Nand control structure.
+*	buff        - The virtual address of the buffer to read to / write from.
+*	data_len    - Byte count to transfer
+*	mode        - Read / Write/ None
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	None.
+*******************************************************************************/
+MV_VOID mvNfcReadWritePio(MV_NFC_CTRL *nfcCtrl, MV_U32 *buff, MV_U32 data_len, MV_NFC_PIO_RW_MODE mode)
+{
+	MV_U32 i;
+
+	switch (mode) {
+	case MV_NFC_PIO_READ:
+		for (i = 0; i < data_len; i += 4) {
+			*buff = MV_REG_READ(NFC_DATA_BUFF_REG);
+			buff++;
+		}
+		break;
+
+	case MV_NFC_PIO_WRITE:	/* Program a single page of 512B or 2KB */
+		for (i = 0; i < data_len; i += 4) {
+			MV_REG_WRITE(NFC_DATA_BUFF_REG, *buff);
+			buff++;
+		}
+		break;
+
+	default:
+		/* nothing to do */
+		break;
+	};
+}
+
+/*******************************************************************************
+* mvNfcAddress2RowConvert
+*
+* DESCRIPTION:
+*       Convert an absolute flash address to row index.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	address	 - The absolute flash address.
+*
+* OUTPUT:
+*	row	 - The row number corresponding to the given address.
+*	colOffset- The column offset within the row.
+*
+* RETURN:
+*	None
+*******************************************************************************/
+MV_VOID mvNfcAddress2RowConvert(MV_NFC_CTRL *nfcCtrl, MV_U32 address, MV_U32 *row, MV_U32 *colOffset)
+{
+
+	if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz < MV_NFC_2KB_PAGE) {	/* Small Page */
+		*colOffset = (address & 0xFF);
+		*row = (address >> 9);
+	} else {		/* Large Page */
+
+		*colOffset = (address & (flashDeviceInfo[nfcCtrl->flashIdx].pgSz - 1));
+
+		/* Calculate the page bits */
+		*row = (address >> mvNfcColBits(flashDeviceInfo[nfcCtrl->flashIdx].pgSz));
+	}
+}
+
+/*******************************************************************************
+* mvNfcAddress2BlockConvert
+*
+* DESCRIPTION:
+*       Convert an absolute flash address to erasable block address
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	address	 - The absolute flash address.
+*
+* OUTPUT:
+*	blk - block address
+*
+* RETURN:
+*	None
+*******************************************************************************/
+MV_VOID mvNfcAddress2BlockConvert(MV_NFC_CTRL *nfcCtrl, MV_U32 address, MV_U32 *blk)
+{
+	*blk = (address / (flashDeviceInfo[nfcCtrl->flashIdx].pgSz * flashDeviceInfo[nfcCtrl->flashIdx].pgPrBlk));
+}
+
+/*******************************************************************************
+* mvNfcAddress2BlockConvert
+*
+* DESCRIPTION:
+*       Convert an absolute flash address to erasable block address
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	address	 - The absolute flash address.
+*
+* OUTPUT:
+*	blk - block address
+*
+* RETURN:
+*	None
+*******************************************************************************/
+MV_8 *mvNfcFlashModelGet(MV_NFC_CTRL *nfcCtrl)
+{
+	static MV_8 *unk_dev = "Unknown Flash Device";
+
+	if (nfcCtrl->flashIdx >= (sizeof(flashDeviceInfo) / sizeof(MV_NFC_FLASH_INFO)))
+		return unk_dev;
+
+	return flashDeviceInfo[nfcCtrl->flashIdx].model;
+}
+
+/*******************************************************************************
+* mvNfcFlashPageSizeGet
+*
+* DESCRIPTION:
+*       Retrieve the logical page size of a given flash.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*
+* OUTPUT:
+*	size - Flash page size in bytes.
+*	totalSize - Page size including spare area.
+*		    (Pass NULL if not needed).
+*
+* RETURN:
+*	MV_NOT_FOUND - Bad flash index.
+*******************************************************************************/
+MV_STATUS mvNfcFlashPageSizeGet(MV_NFC_CTRL *nfcCtrl, MV_U32 *size, MV_U32 *totalSize)
+{
+	if (nfcCtrl->flashIdx >= (sizeof(flashDeviceInfo) / sizeof(MV_NFC_FLASH_INFO)))
+		return MV_NOT_FOUND;
+	if (size == NULL)
+		return MV_BAD_PTR;
+
+	if (nfcCtrl->ifMode == MV_NFC_IF_2X8)
+		*size = flashDeviceInfo[nfcCtrl->flashIdx].pgSz << 1;
+	else
+		*size = flashDeviceInfo[nfcCtrl->flashIdx].pgSz;
+
+	if (totalSize) {
+		mvNfcTransferDataLength(nfcCtrl, MV_NFC_CMD_READ_MONOLITHIC, totalSize);
+		if (nfcCtrl->ifMode == MV_NFC_IF_2X8)
+			*totalSize = (*totalSize) << 1;
+		if (flashDeviceInfo[nfcCtrl->flashIdx].pgSz > MV_NFC_2KB_PAGE)
+			*totalSize = (*totalSize) << 1;
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcFlashBlockSizeGet
+*
+* DESCRIPTION:
+*       Retrieve the logical block size of a given flash.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*
+* OUTPUT:
+*	size - Flash size in bytes.
+*
+* RETURN:
+*	MV_NOT_FOUND - Bad flash index.
+*******************************************************************************/
+MV_STATUS mvNfcFlashBlockSizeGet(MV_NFC_CTRL *nfcCtrl, MV_U32 *size)
+{
+	if (nfcCtrl->flashIdx >= (sizeof(flashDeviceInfo) / sizeof(MV_NFC_FLASH_INFO)))
+		return MV_NOT_FOUND;
+	if (size == NULL)
+		return MV_BAD_PTR;
+
+	if (nfcCtrl->ifMode == MV_NFC_IF_2X8)
+		*size = ((flashDeviceInfo[nfcCtrl->flashIdx].pgSz << 1) * flashDeviceInfo[nfcCtrl->flashIdx].pgPrBlk);
+	else
+		*size = (flashDeviceInfo[nfcCtrl->flashIdx].pgSz * flashDeviceInfo[nfcCtrl->flashIdx].pgPrBlk);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcFlashBlockNumGet
+*
+* DESCRIPTION:
+*       Retrieve the number of logical blocks of a given flash.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*
+* OUTPUT:
+*	numBlocks - Flash number of blocks.
+*
+* RETURN:
+*	MV_NOT_FOUND - Bad flash index.
+*******************************************************************************/
+MV_STATUS mvNfcFlashBlockNumGet(MV_NFC_CTRL *nfcCtrl, MV_U32 *numBlocks)
+{
+	if (nfcCtrl->flashIdx >= (sizeof(flashDeviceInfo) / sizeof(MV_NFC_FLASH_INFO)))
+		return MV_NOT_FOUND;
+	if (numBlocks == NULL)
+		return MV_BAD_PTR;
+
+	*numBlocks = flashDeviceInfo[nfcCtrl->flashIdx].blkNum;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcFlashIdGet
+*
+* DESCRIPTION:
+*       Retrieve the flash device ID.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*
+* OUTPUT:
+*	flashId - Flash ID.
+*
+* RETURN:
+*	MV_NOT_FOUND - Bad flash index.
+*******************************************************************************/
+MV_STATUS mvNfcFlashIdGet(MV_NFC_CTRL *nfcCtrl, MV_U32 *flashId)
+{
+	if (nfcCtrl->flashIdx >= (sizeof(flashDeviceInfo) / sizeof(MV_NFC_FLASH_INFO)))
+		return MV_NOT_FOUND;
+
+	if (flashId == NULL)
+		return MV_BAD_PTR;
+
+	*flashId = flashDeviceInfo[nfcCtrl->flashIdx].id;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcUnitStateStore - Store the NFC Unit state.
+*
+* DESCRIPTION:
+*       This function stores the NFC unit registers before the unit is suspended.
+*	The stored registers are placed into the input buffer which will be used for
+*	the restore operation.
+*
+* INPUT:
+*       regsData	- Buffer to store the unit state registers (Must
+*			  include at least 64 entries)
+*	len		- Number of entries in regsData input buffer.
+*
+* OUTPUT:
+*       regsData	- Unit state registers. The registers are stored in
+*			  pairs of (reg, value).
+*       len		- Number of entries in regsData buffer (Must be even).
+*
+* RETURS:
+*       MV_ERROR on failure.
+*       MV_OK on success.
+*
+*******************************************************************************/
+MV_STATUS mvNfcUnitStateStore(MV_U32 *stateData, MV_U32 *len)
+{
+	MV_U32 i;
+
+	if ((stateData == NULL) || (len == NULL))
+		return MV_BAD_PARAM;
+
+	i = 0;
+
+	stateData[i++] = NFC_CONTROL_REG;
+	stateData[i++] = MV_REG_READ(NFC_CONTROL_REG);
+
+	stateData[i++] = NFC_TIMING_0_REG;
+	stateData[i++] = MV_REG_READ(NFC_TIMING_0_REG);
+
+	stateData[i++] = NFC_TIMING_1_REG;
+	stateData[i++] = MV_REG_READ(NFC_TIMING_1_REG);
+
+	stateData[i++] = NFC_ECC_CONTROL_REG;
+	stateData[i++] = MV_REG_READ(NFC_ECC_CONTROL_REG);
+	*len = i;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvDfcWait4Complete
+*
+* DESCRIPTION:
+*  	Wait for event or process to complete
+*
+* INPUT:
+*	statMask: bit to wait from in status register NDSR
+*	usec: Max uSec to wait for event
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK		- On success,
+*	MV_TIMEOUT 	- Error accessing the underlying flahs device.
+*******************************************************************************/
+static MV_STATUS mvDfcWait4Complete(MV_U32 statMask, MV_U32 usec)
+{
+	MV_U32 i, sts;
+
+	for (i = 0; i < usec; i++) {
+		sts = (MV_REG_READ(NFC_STATUS_REG) & statMask);
+		if (sts) {
+			MV_REG_WRITE(NFC_STATUS_REG, sts);
+			return MV_OK;
+		}
+		mvOsUDelay(1);
+	}
+
+	return MV_TIMEOUT;
+}
+
+#ifdef CONFIG_MTD_NAND_NFC_INIT_RESET
+static MV_STATUS mvNfcReset(void)
+{
+	MV_U32 reg;
+	MV_U32 errCode = MV_OK;
+
+	/* Clear all old events on the status register */
+	reg = MV_REG_READ(NFC_STATUS_REG);
+	MV_REG_WRITE(NFC_STATUS_REG, reg);
+
+	/* Setting ND_RUN bit to start the new transaction */
+	reg = MV_REG_READ(NFC_CONTROL_REG);
+	reg |= NFC_CTRL_ND_RUN_MASK;
+	MV_REG_WRITE(NFC_CONTROL_REG, reg);
+
+	/* Wait for Command WRITE request */
+	errCode = mvDfcWait4Complete(NFC_SR_WRCMDREQ_MASK, 1);
+	if (errCode != MV_OK)
+		goto Error;
+
+	/* Send Command */
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, 0x00A000FF);	/* DFC_NDCB0_RESET */
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, 0x0);
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, 0x0);
+
+	/* Wait for Command completion */
+	errCode = mvDfcWait4Complete((NFC_SR_CS0_CMDD_MASK | NFC_SR_RDY0_MASK), 10);
+	if (errCode != MV_OK)
+		goto Error;
+
+	/* Clear ND_RUN bit if not self cleared */
+	reg = MV_REG_READ(NFC_CONTROL_REG);
+	if (reg & NFC_CTRL_ND_RUN_MASK)
+		MV_REG_WRITE(NFC_CONTROL_REG, (reg & ~NFC_CTRL_ND_RUN_MASK));
+
+Error:
+	return errCode;
+}
+#endif
+/*******************************************************************************
+* mvNfcReadIdNative
+*
+* DESCRIPTION:
+*       Read the flash Manufacturer and device ID in PIO mode.
+*
+* INPUT:
+*	None.
+*
+* OUTPUT:
+*	id: Manufacturer and Device Id detected (valid only if return is MV_OK).
+*
+* RETURN:
+*       MV_OK		- On success,
+*	MV_TIMEOUT 	- Error accessing the underlying flahs device.
+*	MV_FAIL		- On failure
+*******************************************************************************/
+static MV_STATUS mvNfcReadIdNative(MV_NFC_CHIP_SEL cs, MV_U16 *id)
+{
+	MV_U32 reg, cmdb0 = 0, cmdb2 = 0;
+	MV_U32 errCode = MV_OK;
+
+	/* Clear all old events on the status register */
+	reg = MV_REG_READ(NFC_STATUS_REG);
+	MV_REG_WRITE(NFC_STATUS_REG, reg);
+
+	/* Setting ND_RUN bit to start the new transaction */
+	reg = MV_REG_READ(NFC_CONTROL_REG);
+	reg |= NFC_CTRL_ND_RUN_MASK;
+	MV_REG_WRITE(NFC_CONTROL_REG, reg);
+
+	/* Wait for Command WRITE request */
+	errCode = mvDfcWait4Complete(NFC_SR_WRCMDREQ_MASK, 1);
+	if (errCode != MV_OK)
+		return errCode;
+
+	/* Send Command */
+	reg = NFC_NATIVE_READ_ID_CMD;
+	reg |= (0x1 << NFC_CB0_ADDR_CYC_OFFS);
+	reg |= NFC_CB0_CMD_TYPE_READ_ID;
+	cmdb0 = reg;
+	if ((cs == MV_NFC_CS_1) || (cs == MV_NFC_CS_3))
+		cmdb0 |= NFC_CB0_CSEL_MASK;
+
+	if ((cs == MV_NFC_CS_2) || (cs == MV_NFC_CS_3))
+		cmdb2 |= NFC_CB2_CS_2_3_SELECT_MASK;
+
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, cmdb0);
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, 0x0);
+	MV_REG_WRITE(NFC_COMMAND_BUFF_0_REG, cmdb2);
+
+	/* Wait for Data READ request */
+	errCode = mvDfcWait4Complete(NFC_SR_RDDREQ_MASK, 10);
+	if (errCode != MV_OK)
+		return errCode;
+
+	/*  Read the read ID bytes. + read 4 bogus bytes */
+	*id = (MV_U16) (MV_REG_READ(NFC_DATA_BUFF_REG) & 0xFFFF);
+	reg = MV_REG_READ(NFC_DATA_BUFF_REG);	/* dummy read to complete 8 bytes */
+
+	reg = MV_REG_READ(NFC_CONTROL_REG);
+	if (reg & NFC_CTRL_ND_RUN_MASK) {
+		MV_REG_WRITE(NFC_CONTROL_REG, (reg & ~NFC_CTRL_ND_RUN_MASK));
+		return MV_BAD_STATE;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcTimingSet
+*
+* DESCRIPTION:
+*       Set all flash timing parameters for optimized operation
+*
+* INPUT:
+*	tclk: Tclk frequency,
+	flInfo: timing information
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_OK		- On success,
+*	MV_FAIL		- On failure
+*******************************************************************************/
+static MV_STATUS mvNfcTimingSet(MV_U32 tclk, MV_NFC_FLASH_INFO *flInfo)
+{
+	MV_U32 reg;
+	MV_U32 clk2ns;
+
+	switch (tclk) {
+	case 166666667:
+		clk2ns = 6;
+		break;
+	case 200000000:
+		clk2ns = 5;
+		break;
+	case 250000000:
+		clk2ns = 4;
+		break;
+	default:
+		return MV_FAIL;
+	};
+
+	/* Configure the Timing-0 register */
+	reg = 0;
+	reg |= NFC_TMNG0_SEL_CNTR_MASK;
+	reg |= ((ns_clk(flInfo->tADL, clk2ns) << NFC_TMNG0_TADL_OFFS) & NFC_TMNG0_TADL_MASK);
+	reg |= ((ns_clk(flInfo->tCH, clk2ns) << NFC_TMNG0_TCH_OFFS) & NFC_TMNG0_TCH_MASK);
+	reg |= ((ns_clk(flInfo->tCS, clk2ns) << NFC_TMNG0_TCS_OFFS) & NFC_TMNG0_TCS_MASK);
+	reg |= ((ns_clk(flInfo->tWH, clk2ns) << NFC_TMNG0_TWH_OFFS) & NFC_TMNG0_TWH_MASK);
+	reg |= ((ns_clk(flInfo->tWP, clk2ns) << NFC_TMNG0_TWP_OFFS) & NFC_TMNG0_TWP_MASK);
+	reg |= ((ns_clk(flInfo->tRH, clk2ns) << NFC_TMNG0_TRH_OFFS) & NFC_TMNG0_TRH_MASK);
+	reg |= ((ns_clk(flInfo->tRP, clk2ns) << NFC_TMNG0_TRP_OFFS) & NFC_TMNG0_TRP_MASK);
+	MV_REG_WRITE(NFC_TIMING_0_REG, reg);
+
+	/* Configure the Timing-1 register */
+	reg = 0;
+	reg |= ((ns_clk(flInfo->tR, clk2ns) << NFC_TMNG1_TR_OFFS) & NFC_TMNG1_TR_MASK);
+	reg |= ((ns_clk(flInfo->tWHR, clk2ns) << NFC_TMNG1_TWHR_OFFS) & NFC_TMNG1_TWHR_MASK);
+	reg |= ((ns_clk(flInfo->tAR, clk2ns) << NFC_TMNG1_TAR_OFFS) & NFC_TMNG1_TAR_MASK);
+	reg |= (((flInfo->tRHW / 16) << NFC_TMNG1_TRHW_OFFS) & NFC_TMNG1_TRHW_MASK);
+	reg |= NFC_TMNG1_WAIT_MODE_MASK;
+	MV_REG_WRITE(NFC_TIMING_1_REG, reg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvNfcColBits
+*
+* DESCRIPTION:
+*       Calculate number of bits representing column part of the address
+*
+* INPUT:
+	pg_size: page size
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	Number of bits representing a column
+*******************************************************************************/
+static MV_U32 mvNfcColBits(MV_U32 pg_size)
+{
+	MV_U32 shift = 0;
+	while (pg_size) {
+		++shift;
+		pg_size >>= 1;
+	};
+
+	return (shift - 1);
+}
+
+/*******************************************************************************
+* mvNfcEccModeSet
+*
+* DESCRIPTION:
+*       Set the ECC mode at runtime to BCH, Hamming or No Ecc.
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*	MV_NFC_ECC_MODE eccMode: ECC type (BCH, Hamming or No Ecc)
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	previous ECC mode.
+*******************************************************************************/
+MV_NFC_ECC_MODE mvNfcEccModeSet(MV_NFC_CTRL *nfcCtrl, MV_NFC_ECC_MODE eccMode)
+{
+	MV_NFC_ECC_MODE prevEccMode;
+
+	prevEccMode = nfcCtrl->eccMode;
+	nfcCtrl->eccMode = eccMode;
+	return prevEccMode;
+}
+
+/*******************************************************************************
+* mvNfcBadBlockPageNumber
+*
+* DESCRIPTION:
+*       Get the page number within the block holding the bad block indication
+*
+* INPUT:
+*	nfcCtrl  - Nand control structure.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*       page number having the bad block indicator
+*******************************************************************************/
+MV_U32 mvNfcBadBlockPageNumber(MV_NFC_CTRL *nfcCtrl)
+{
+	return flashDeviceInfo[nfcCtrl->flashIdx].bb_page;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/nfc/mvNfc.h b/arch/arm/plat-feroceon/mv_hal/nfc/mvNfc.h
new file mode 100755
index 0000000..d84195a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/nfc/mvNfc.h
@@ -0,0 +1,426 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCMVNFCH
+#define __INCMVNFCH
+
+/******************************************************************************
+ * Usage model:
+ *	The following describes the usage model for the below APIs.
+ *	the sequences below does not handle errors, and assume all stages pass
+ *	successfully.
+ *	Nand Read of 2 pages, PDMA mode:
+ *		- mvNfcInit(MV_NFC_PDMA_ACCESS)
+ *		- mvNfcSelectChip(...)
+ *		- [If interrupt mode]
+ *		  Enable RD_DATA_REQ & CMD_DONE interrupts.
+ *		- mvNfcCommandIssue(MV_NFC_CMD_READ)
+ *		- [In interrupt mode]
+ *		  Block till one of the above interrupts is triggered.
+ *		- [In polling mode]
+ *		  Poll on mvNfcStatusGet() till STATUS_RDD_REQ is returned.
+ *		- [In interrupt mode]
+ *		  Disable the RD_DATA_REQ interrupt.
+ *		- mvNfcReadWrite()
+ *		- Block till CMD_DONE interrupt is issued (Or Error).
+ *		  OR
+ *		  Poll on mvNfcStatusGet() till CMD_DONE is returned. (Or Error).
+ *		- Wait for PDMA done interrupt to signal data ready in buffer.
+ *		==> At this stage, data is ready in the read buffer.
+ *		- [If interrupt mode]
+ *		  Enable RD_DATA_REQ & CMD_DONE interrupts.
+ *		- mvNfcCommandIssue(MV_NFC_CMD_READ_LAST_NAKED)
+ *		- [In interrupt mode]
+ *		  Block till one of the above interrupts is triggered.
+ *		- [In polling mode]
+ *		  Poll on mvNfcStatusGet() till STATUS_RDD_REQ is returned.
+ *		- [In interrupt mode]
+ *		  Disable the RD_DATA_REQ interrupt.
+ *		- mvNfcReadWrite()
+ *		- Block till CMD_DONE interrupt is issued (Or Error).
+ *		  OR
+ *		  Poll on mvNfcStatusGet() till CMD_DONE is returned. (Or Error).
+ *		- Wait for PDMA done interrupt to signal data ready in buffer.
+ *		==> At this stage, second page data is ready in the read buffer.
+ *		- mvNfcSelectChip(MV_NFC_CS_NONE)
+ *
+ *	Nand Write of single page, PIO mode:
+ *		- mvNfcInit(MV_NFC_PIO_ACCESS)
+ *		- mvNfcSelectChip(...)
+ *		- [If interrupt mode]
+ *		  Enable WR_DATA_REQ & CMD_DONE interrupts.
+ *		- mvNfcCommandIssue(MV_NFC_CMD_WRITE_MONOLITHIC)
+ *		- [In interrupt mode]
+ *		  Block till one of the above interrupts is triggered.
+ *		- [In polling mode]
+ *		  Poll on mvNfcStatusGet() till STATUS_WRD_REQ is returned.
+ *		- [In interrupt mode]
+ *		  Disable the WR_DATA_REQ interrupt.
+ *		- mvNfcReadWrite()
+ *		- Block till CMD_DONE interrupt is issued (Or Error).
+ *		  OR
+ *		  Poll on mvNfcStatusGet() till CMD_DONE is returned. (Or Error).
+ *		==> At this stage, data was written to the flash device.
+ *		- mvNfcSelectChip(MV_NFC_CS_NONE)
+ *
+ *	Nand Erase of a single block:
+ *		- mvNfcInit(...)
+ *		- mvNfcSelectChip(...)
+ *		- [If interrupt mode]
+ *		  Enable CMD_DONE interrupts.
+ *		- mvNfcCommandIssue(MV_NFC_CMD_ERASE)
+ *		- [In interrupt mode]
+ *		  Block till the above interrupt is triggered.
+ *		- [In polling mode]
+ *		  Poll on mvNfcStatusGet() till STATUS_CMD_DONE is returned.
+ *		==> At this stage, flash block was erased from the flash device.
+ *		- mvNfcSelectChip(MV_NFC_CS_NONE)
+ *
+ ******************************************************************************/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysNfcConfig.h"
+
+/********************************/
+/* Enums and structures 	*/
+/********************************/
+
+/* Maximum Chain length */
+#define MV_NFC_MAX_DESC_CHAIN		0x800
+
+/* Supported page sizes */
+#define MV_NFC_512B_PAGE		512
+#define MV_NFC_2KB_PAGE			2048
+#define MV_NFC_4KB_PAGE			4096
+#define MV_NFC_8KB_PAGE			8192
+
+#define MV_NFC_MAX_CHUNK_SIZE		(2048)
+
+/* Nand controller status bits.		*/
+#define MV_NFC_STATUS_CMD_REQ 		0x1
+#define MV_NFC_STATUS_RDD_REQ 		0x2
+#define MV_NFC_STATUS_WRD_REQ 		0x4
+#define MV_NFC_STATUS_COR_ERROR 	0x8
+#define MV_NFC_STATUS_UNC_ERROR 	0x10
+#define MV_NFC_STATUS_BBD 		0x20	/* Bad Block Detected */
+#define MV_NFC_STATUS_CMDD 		0x80	/* Command Done */
+#define MV_NFC_STATUS_PAGED 		0x200	/* Page Done */
+#define MV_NFC_STATUS_RDY		0x800	/* Device Ready */
+
+/* Nand controller interrupt bits.	*/
+#define MV_NFC_WR_CMD_REQ_INT		0x1
+#define MV_NFC_RD_DATA_REQ_INT		0x2
+#define MV_NFC_WR_DATA_REQ_INT		0x4
+#define MV_NFC_CORR_ERR_INT		0x8
+#define MV_NFC_UNCORR_ERR_INT		0x10
+#define MV_NFC_CS1_BAD_BLK_DETECT_INT	0x20
+#define MV_NFC_CS0_BAD_BLK_DETECT_INT	0x40
+#define MV_NFC_CS1_CMD_DONE_INT		0x80
+#define MV_NFC_CS0_CMD_DONE_INT		0x100
+#define MV_NFC_DEVICE_READY_INT		0x800
+
+/* Max number of buffers chunks for as single read / write operation */
+#define MV_NFC_RW_MAX_BUFF_NUM		16
+
+/* ECC mode options.			*/
+typedef enum {
+	MV_NFC_ECC_HAMMING = 0, /* 1 bit */
+	MV_NFC_ECC_BCH_2K,		/* 4 bit */
+	MV_NFC_ECC_BCH_1K,		/* 8 bit */
+	MV_NFC_ECC_BCH_704B,	/* 12 bit */
+	MV_NFC_ECC_BCH_512B,	/* 16 bit */
+	MV_NFC_ECC_DISABLE,
+	MV_NFC_ECC_MAX_CNT
+} MV_NFC_ECC_MODE;
+
+
+typedef enum {
+	MV_NFC_PIO_ACCESS,
+	MV_NFC_PDMA_ACCESS
+} MV_NFC_IO_MODE;
+
+typedef enum {
+	MV_NFC_PIO_READ,
+	MV_NFC_PIO_WRITE,
+	MV_NFC_PIO_NONE
+} MV_NFC_PIO_RW_MODE;
+
+
+typedef enum {
+	MV_NFC_IF_1X8,
+	MV_NFC_IF_1X16,
+	MV_NFC_IF_2X8
+} MV_NFC_IF_MODE;
+
+
+/* Flash device CS.			*/
+typedef enum {
+	MV_NFC_CS_0,
+	MV_NFC_CS_1,
+	MV_NFC_CS_2,
+	MV_NFC_CS_3,
+	MV_NFC_CS_NONE
+} MV_NFC_CHIP_SEL;
+
+
+/*
+ * 	ioMode		The access mode by which the unit will operate (PDMA / PIO).
+ * 	eccMode		The ECC mode to configure the controller to.
+ * 	ifMode		The NAND chip connection mode, 8-bit / 16-bit / gang mode.
+ * 	autoStatusRead	Whether to automatically read the flash status after each
+ *			erase / write commands.
+ *	tclk		System TCLK.
+ * 	readyBypass	Whether to wait for the RnB sugnal to be deasserted after
+ *			waiting the tR or skip it and move directly to the next step.
+ * 	osHandle	OS specific handle used for allocating command buffer
+ *	regsPhysAddr	Physical address of internal registers (used in DMA
+ *			mode only)
+ *	dataPdmaIntMask Interrupt mask for PDMA data channel (used in DMA mode
+ *			only).
+ *	cmdPdmaIntMask	Interrupt mask for PDMA command channel (used in DMA
+ *			mode only).
+ */
+typedef struct {
+	MV_NFC_IO_MODE 		ioMode;
+	MV_NFC_ECC_MODE 	eccMode;
+	MV_NFC_IF_MODE 		ifMode;
+	MV_BOOL 		autoStatusRead;
+	MV_U32			tclk;
+	MV_BOOL			readyBypass;
+	MV_VOID			*osHandle;
+	MV_U32			regsPhysAddr;
+#ifdef MV_INCLUDE_PDMA
+	MV_U32			dataPdmaIntMask;
+	MV_U32			cmdPdmaIntMask;
+#endif
+} MV_NFC_INFO;
+
+
+typedef enum {
+	MV_NFC_CMD_READ_ID = 0,
+	MV_NFC_CMD_READ_STATUS,
+	MV_NFC_CMD_ERASE,
+	MV_NFC_CMD_MULTIPLANE_ERASE,
+	MV_NFC_CMD_RESET,
+
+	MV_NFC_CMD_CACHE_READ_SEQ,
+	MV_NFC_CMD_CACHE_READ_RAND,
+	MV_NFC_CMD_EXIT_CACHE_READ,
+	MV_NFC_CMD_CACHE_READ_START,
+	MV_NFC_CMD_READ_MONOLITHIC,
+	MV_NFC_CMD_READ_MULTIPLE,
+	MV_NFC_CMD_READ_NAKED,
+	MV_NFC_CMD_READ_LAST_NAKED,
+	MV_NFC_CMD_READ_DISPATCH,
+
+	MV_NFC_CMD_WRITE_MONOLITHIC,
+	MV_NFC_CMD_WRITE_MULTIPLE,
+	MV_NFC_CMD_WRITE_NAKED,
+	MV_NFC_CMD_WRITE_LAST_NAKED,
+	MV_NFC_CMD_WRITE_DISPATCH,
+	MV_NFC_CMD_WRITE_DISPATCH_START,
+	MV_NFC_CMD_WRITE_DISPATCH_END,
+
+	MV_NFC_CMD_COUNT	/* This should be the last enum */
+
+} MV_NFC_CMD_TYPE;
+
+
+/*
+ * Nand information structure.
+ * 	flashId 	The ID of the flash information structure representing the timing
+ *		    	and physical layout data of the flash device.
+ *	cmdsetId  	The ID of the command-set structure holding the access
+ *		   	commands for the flash device.
+ *      flashWidth 	Flash device interface width in bits.
+ * 	autoStatusRead	Whether to automatically read the flash status after each
+ *		    	erase / write commands.
+ * 	tclk		System TCLK.
+ * 	readyBypass	Whether to wait for the RnB signal to be deasserted after
+ * 			waiting the tR or skip it and move directly to the next step.
+ *      ioMode		Controller access mode (PDMA / PIO).
+ *      eccMode		Flash ECC mode (Hamming, BCH, None).
+ *      ifMode		Flash interface mode.
+ *      currC		The current flash CS currently being accessed.
+ *	dataChanHndl	Pointer to the data DMA channel
+ *	cmdChanHndl	Pointer to the command DMA Channel
+ *	cmdBuff		Command buffer information (used in DMA only)
+ *	regsPhysAddr	Physical address of internal registers (used in DMA
+ *			mode only)
+ *	dataPdmaIntMask Interrupt mask for PDMA data channel (used in DMA mode
+ *			only).
+ *	cmdPdmaIntMask	Interrupt mask for PDMA command channel (used in DMA
+ *			mode only).
+ */
+typedef struct {
+	MV_U32		flashIdx;
+	MV_U32		cmdsetIdx;
+	MV_U32 		flashWidth;
+	MV_U32 		dfcWidth;
+	MV_BOOL 	autoStatusRead;
+	MV_BOOL		readyBypass;
+	MV_NFC_IO_MODE 	ioMode;
+	MV_NFC_ECC_MODE eccMode;
+	MV_NFC_IF_MODE 	ifMode;
+	MV_NFC_CHIP_SEL currCs;
+#ifdef MV_INCLUDE_PDMA
+	MV_PDMA_CHANNEL dataChanHndl;
+	MV_PDMA_CHANNEL cmdChanHndl;
+#endif
+	MV_BUF_INFO	cmdBuff;
+	MV_BUF_INFO	cmdDescBuff;
+	MV_BUF_INFO	dataDescBuff;
+	MV_U32		regsPhysAddr;
+#ifdef MV_INCLUDE_PDMA
+	MV_U32		dataPdmaIntMask;
+	MV_U32		cmdPdmaIntMask;
+#endif
+} MV_NFC_CTRL;
+
+/*
+ * Nand multi command information structure.
+ *	cmd		The command to be issued.
+ *	pageAddr	The flash page address to operate on.
+ *	pageCount	Number of pages to read / write.
+ *	virtAddr	The virtual address of the buffer to copy data to /
+ *			from (For relevant commands).
+ *	physAddr	The physical address of the buffer to copy data to /
+ *			from (For relevant commands).
+ *	The following parameters might only be used when working in Gagned PDMA
+ *	and the pageCount must be set to 1.
+ *	For ganged mode, the use might need to split the NAND stack read /
+ *	write buffer into several buffers according to what the HW expects.
+ *	e.g. NAND stack expects data in the following format:
+ *	---------------------------
+ *	| Data (4K) | Spare | ECC |
+ *	---------------------------
+ *	While NAND controller expects data to be in the following format:
+ *	-----------------------------------------------------
+ *	| Data (2K) | Spare | ECC | Data (2K) | Spare | ECC |
+ *	-----------------------------------------------------
+ *	numSgBuffs	Number of buffers to split the HW buffer into
+ *			If 1, then buffOffset & buffSize are ignored.
+ *	sgBuffAddr	Array holding the address of the buffers into which the
+ *			HW data should be split (Or read into).
+ *	sgBuffSize	Array holding the size of each sub-buffer, entry "i"
+ *			represents the size in bytes of the buffer starting at
+ *			offset buffOffset[i].
+ */
+typedef struct {
+	MV_NFC_CMD_TYPE cmd;
+	MV_U32		pageAddr;
+	MV_U32		pageCount;
+	MV_U32 		*virtAddr;
+	MV_U32		physAddr;
+	MV_U32		numSgBuffs;
+	MV_U32		sgBuffAddr[MV_NFC_RW_MAX_BUFF_NUM];
+	MV_U32		*sgBuffAddrVirt[MV_NFC_RW_MAX_BUFF_NUM];
+	MV_U32		sgBuffSize[MV_NFC_RW_MAX_BUFF_NUM];
+	MV_U32		length;
+} MV_NFC_MULTI_CMD;
+
+typedef struct {
+	MV_U32		cmdb0;
+	MV_U32		cmdb1;
+	MV_U32		cmdb2;
+	MV_U32		cmdb3;
+} MV_NFC_CMD;
+
+
+/********************************/
+/* Functions API 		*/
+/********************************/
+
+MV_STATUS mvNfcInit(MV_NFC_INFO *nfcInfo, MV_NFC_CTRL *nfcCtrl);
+MV_STATUS mvNfcSelectChip(MV_NFC_CTRL *nfcCtrl, MV_NFC_CHIP_SEL chip);
+MV_STATUS mvNfcCommandPio(MV_NFC_CTRL *nfcCtrl, MV_NFC_MULTI_CMD * cmd_desc, MV_BOOL next);
+MV_STATUS mvNfcCommandMultiple(MV_NFC_CTRL *nfcCtrl, MV_NFC_MULTI_CMD *descInfo, MV_U32 descCnt);
+MV_U32 	  mvNfcStatusGet(MV_NFC_CTRL *nfcCtrl, MV_NFC_CMD_TYPE cmd, MV_U32 *value);
+MV_STATUS mvNfcIntrSet(MV_NFC_CTRL *nfcCtrl, MV_U32 intMask, MV_BOOL enable);
+MV_STATUS mvNfcReadWrite(MV_NFC_CTRL *nfcCtrl, MV_NFC_CMD_TYPE cmd, MV_U32 *virtBufAddr, MV_U32 physBuffAddr);
+MV_VOID   mvNfcReadWritePio(MV_NFC_CTRL *nfcCtrl, MV_U32 * buff, MV_U32 data_len, MV_NFC_PIO_RW_MODE mode);
+MV_VOID   mvNfcAddress2RowConvert(MV_NFC_CTRL *nfcCtrl, MV_U32 address, MV_U32 *row, MV_U32 *colOffset);
+MV_VOID   mvNfcAddress2BlockConvert(MV_NFC_CTRL *nfcCtrl, MV_U32 address, MV_U32 *blk);
+MV_8	 *mvNfcFlashModelGet(MV_NFC_CTRL *nfcCtrl);
+MV_STATUS mvNfcFlashPageSizeGet(MV_NFC_CTRL *nfcCtrl, MV_U32 *size, MV_U32 *totalSize);
+MV_STATUS mvNfcFlashBlockSizeGet(MV_NFC_CTRL *nfcCtrl, MV_U32 *size);
+MV_STATUS mvNfcFlashBlockNumGet(MV_NFC_CTRL *nfcCtrl, MV_U32 *numBlocks);
+MV_STATUS mvNfcDataLength(MV_NFC_CTRL *nfcCtrl, MV_NFC_CMD_TYPE cmd, MV_U32 *data_len);
+MV_STATUS mvNfcTransferDataLength(MV_NFC_CTRL *nfcCtrl, MV_NFC_CMD_TYPE cmd, MV_U32 * data_len);
+MV_STATUS mvNfcFlashIdGet(MV_NFC_CTRL *nfcCtrl, MV_U32 *flashId);
+MV_STATUS mvNfcUnitStateStore(MV_U32 *stateData, MV_U32 *len);
+MV_NFC_ECC_MODE mvNfcEccModeSet(MV_NFC_CTRL *nfcCtrl, MV_NFC_ECC_MODE eccMode);
+MV_U32 	  mvNfcBadBlockPageNumber(MV_NFC_CTRL *nfcCtrl);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __INCMVNFCH */
diff --git a/arch/arm/plat-feroceon/mv_hal/nfc/mvNfcRegs.h b/arch/arm/plat-feroceon/mv_hal/nfc/mvNfcRegs.h
new file mode 100755
index 0000000..0c39668
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/nfc/mvNfcRegs.h
@@ -0,0 +1,313 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCMVNFCREGSH
+#define __INCMVNFCREGSH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvSysNfcConfig.h"
+
+/* NAND Flash Control Register */
+#define	NFC_CONTROL_REG			(MV_NFC_REGS_BASE + 0x0)
+#define	NFC_CTRL_WRCMDREQ_MASK		(0x1 << 0)
+#define NFC_CTRL_RDDREQ_MASK		(0x1 << 1)
+#define NFC_CTRL_WRDREQ_MASK		(0x1 << 2)
+#define NFC_CTRL_CORRERR_MASK		(0x1 << 3)
+#define NFC_CTRL_UNCERR_MASK		(0x1 << 4)
+#define NFC_CTRL_CS1_BBD_MASK		(0x1 << 5)
+#define NFC_CTRL_CS0_BBD_MASK		(0x1 << 6)
+#define NFC_CTRL_CS1_CMDD_MASK		(0x1 << 7)
+#define NFC_CTRL_CS0_CMDD_MASK		(0x1 << 8)
+#define NFC_CTRL_CS1_PAGED_MASK		(0x1 << 9)
+#define NFC_CTRL_CS0_PAGED_MASK		(0x1 << 10)
+#define NFC_CTRL_RDY_MASK		(0x1 << 11)
+#define NFC_CTRL_ND_ARB_EN_MASK		(0x1 << 12)
+#define NFC_CTRL_PG_PER_BLK_OFFS	13
+#define NFC_CTRL_PG_PER_BLK_MASK	(0x3 << NFC_CTRL_PG_PER_BLK_OFFS)
+#define NFC_CTRL_PG_PER_BLK_32		(0x0 << NFC_CTRL_PG_PER_BLK_OFFS)
+#define NFC_CTRL_PG_PER_BLK_64		(0x2 << NFC_CTRL_PG_PER_BLK_OFFS)
+#define NFC_CTRL_PG_PER_BLK_128		(0x1 << NFC_CTRL_PG_PER_BLK_OFFS)
+#define NFC_CTRL_PG_PER_BLK_256		(0x3 << NFC_CTRL_PG_PER_BLK_OFFS)
+#define NFC_CTRL_RA_START_MASK		(0x1 << 15)
+#define NFC_CTRL_RD_ID_CNT_OFFS		16
+#define NFC_CTRL_RD_ID_CNT_MASK		(0x7 << NFC_CTRL_RD_ID_CNT_OFFS)
+#define NFC_CTRL_RD_ID_CNT_SP		(0x2 << NFC_CTRL_RD_ID_CNT_OFFS)
+#define NFC_CTRL_RD_ID_CNT_LP		(0x4 << NFC_CTRL_RD_ID_CNT_OFFS)
+#define NFC_CTRL_CLR_PG_CNT_MASK	(0x1 << 20)
+#define NFC_CTRL_FORCE_CSX_MASK		(0x1 << 21)
+#define NFC_CTRL_ND_STOP_MASK		(0x1 << 22)
+#define NFC_CTRL_SEQ_DIS_MASK		(0x1 << 23)
+#define NFC_CTRL_PAGE_SZ_OFFS		24
+#define NFC_CTRL_PAGE_SZ_MASK		(0x3 << NFC_CTRL_PAGE_SZ_OFFS)
+#define NFC_CTRL_PAGE_SZ_512B		(0x0 << NFC_CTRL_PAGE_SZ_OFFS)
+#define NFC_CTRL_PAGE_SZ_2KB		(0x1 << NFC_CTRL_PAGE_SZ_OFFS)
+#define NFC_CTRL_DWIDTH_M_MASK		(0x1 << 26)
+#define NFC_CTRL_DWIDTH_C_MASK		(0x1 << 27)
+#define NFC_CTRL_ND_RUN_MASK		(0x1 << 28)
+#define NFC_CTRL_DMA_EN_MASK		(0x1 << 29)
+#define NFC_CTRL_ECC_EN_MASK		(0x1 << 30)
+#define NFC_CTRL_SPARE_EN_MASK		(0x1 << 31)
+
+/* NAND Interface Timing Parameter 0 Register */
+#define NFC_TIMING_0_REG		(MV_NFC_REGS_BASE + 0x4)
+#define NFC_TMNG0_TRP_OFFS		0
+#define NFC_TMNG0_TRP_MASK		(0x7 << NFC_TMNG0_TRP_OFFS)
+#define NFC_TMNG0_TRH_OFFS		3
+#define NFC_TMNG0_TRH_MASK		(0x7 << NFC_TMNG0_TRH_OFFS)
+#define NFC_TMNG0_ETRP_MASK		(0x1 << 6)
+#define NFC_TMNG0_SEL_NRE_EDGE_MASK	(0x1 << 7)
+#define NFC_TMNG0_TWP_OFFS		8
+#define NFC_TMNG0_TWP_MASK		(0x7 << NFC_TMNG0_TWP_OFFS)
+#define NFC_TMNG0_TWH_OFFS		11
+#define NFC_TMNG0_TWH_MASK		(0x7 << NFC_TMNG0_TWH_OFFS)
+#define NFC_TMNG0_TCS_OFFS		16
+#define NFC_TMNG0_TCS_MASK		(0x7 << NFC_TMNG0_TCS_OFFS)
+#define NFC_TMNG0_TCH_OFFS		19
+#define NFC_TMNG0_TCH_MASK		(0x7 << NFC_TMNG0_TCH_OFFS)
+#define NFC_TMNG0_RD_CNT_DEL_OFFS	22
+#define NFC_TMNG0_RD_CNT_DEL_MASK	(0xF << NFC_TMNG0_RD_CNT_DEL_OFFS)
+#define NFC_TMNG0_SEL_CNTR_MASK		(0x1 << 26)
+#define NFC_TMNG0_TADL_OFFS		27
+#define NFC_TMNG0_TADL_MASK		(0x1F << NFC_TMNG0_TADL_OFFS)
+
+/* NAND Interface Timing Parameter 1 Register */
+#define NFC_TIMING_1_REG		(MV_NFC_REGS_BASE + 0xC)
+#define NFC_TMNG1_TAR_OFFS		0
+#define NFC_TMNG1_TAR_MASK		(0xF << NFC_TMNG1_TAR_OFFS)
+#define NFC_TMNG1_TWHR_OFFS		4
+#define NFC_TMNG1_TWHR_MASK		(0xF << NFC_TMNG1_TWHR_OFFS)
+#define NFC_TMNG1_TRHW_OFFS		8
+#define NFC_TMNG1_TRHW_MASK		(0x3 << NFC_TMNG1_TRHW_OFFS)
+#define NFC_TMNG1_PRESCALE_MASK		(0x1 << 14)
+#define NFC_TMNG1_WAIT_MODE_MASK	(0x1 << 15)
+#define NFC_TMNG1_TR_OFFS		16
+#define NFC_TMNG1_TR_MASK		(0xFFFF << NFC_TMNG1_TR_OFFS)
+
+/* NAND Controller Status Register - NDSR */
+#define NFC_STATUS_REG			(MV_NFC_REGS_BASE + 0x14)
+#define NFC_SR_WRCMDREQ_MASK		(0x1 << 0)
+#define NFC_SR_RDDREQ_MASK		(0x1 << 1)
+#define NFC_SR_WRDREQ_MASK		(0x1 << 2)
+#define NFC_SR_CORERR_MASK		(0x1 << 3)
+#define NFC_SR_UNCERR_MASK		(0x1 << 4)
+#define NFC_SR_CS1_BBD_MASK		(0x1 << 5)
+#define NFC_SR_CS0_BBD_MASK		(0x1 << 6)
+#define NFC_SR_CS1_CMDD_MASK		(0x1 << 7)
+#define NFC_SR_CS0_CMDD_MASK		(0x1 << 8)
+#define NFC_SR_CS1_PAGED_MASK		(0x1 << 9)
+#define NFC_SR_CS0_PAGED_MASK		(0x1 << 10)
+#define NFC_SR_RDY0_MASK		(0x1 << 11)
+#define NFC_SR_RDY1_MASK		(0x1 << 12)
+#define NFC_SR_ALLIRQ_MASK		(0x1FFF << 0)
+#define NFC_SR_TRUSTVIO_MASK		(0x1 << 15)
+#define NFC_SR_ERR_CNT_OFFS		16
+#define NFC_SR_ERR_CNT_MASK		(0x1F << NFC_SR_ERR_CNT_OFFS)
+
+/* NAND Controller Page Count Register */
+#define NFC_PAGE_COUNT_REG		(MV_NFC_REGS_BASE + 0x18)
+#define NFC_PCR_PG_CNT_0_OFFS		0
+#define NFC_PCR_PG_CNT_0_MASK		(0xFF << NFC_PCR_PG_CNT_0_OFFS)
+#define NFC_PCR_PG_CNT_1_OFFS		16
+#define NFC_PCR_PG_CNT_1_MASK		(0xFF << NFC_PCR_PG_CNT_1_OFFS)
+
+/* NAND Controller Bad Block 0 Register */
+#define NFC_BAD_BLOCK_0_REG		(MV_NFC_REGS_BASE + 0x1C)
+
+/* NAND Controller Bad Block 1 Register */
+#define NFC_BAD_BLOCK_1_REG		(MV_NFC_REGS_BASE + 0x20)
+
+/* NAND ECC Controle Register */
+#define NFC_ECC_CONTROL_REG		(MV_NFC_REGS_BASE + 0x28)
+#define NFC_ECC_BCH_EN_MASK		(0x1 << 0)
+#define NFC_ECC_THRESHOLD_OFFS		1
+#define NFC_ECC_THRESHOLF_MASK		(0x3F << NFC_ECC_THRESHOLD_OFFS)
+#define NFC_ECC_SPARE_OFFS		7
+#define NFC_ECC_SPARE_MASK		(0xFF << NFC_ECC_SPARE_OFFS)
+
+/* NAND Busy Length Count */
+#define NFC_BUSY_LEN_CNT_REG		(MV_NFC_REGS_BASE + 0x2C)
+#define NFC_BUSY_CNT_0_OFFS		0
+#define NFC_BUSY_CNT_0_MASK		(0xFFFF << NFC_BUSY_CNT_0_OFFS)
+#define NFC_BUSY_CNT_1_OFFS		16
+#define NFC_BUSY_CNT_1_MASK		(0xFFFF << NFC_BUSY_CNT_1_OFFS)
+
+/* NAND Mutex Lock */
+#define NFC_MUTEX_LOCK_REG		(MV_NFC_REGS_BASE + 0x30)
+#define NFC_MUTEX_LOCK_MASK		(0x1 << 0)
+
+/* NAND Partition Command Match */
+#define NFC_PART_CMD_MACTH_1_REG	(MV_NFC_REGS_BASE + 0x34)
+#define NFC_PART_CMD_MACTH_2_REG	(MV_NFC_REGS_BASE + 0x38)
+#define NFC_PART_CMD_MACTH_3_REG	(MV_NFC_REGS_BASE + 0x3C)
+#define NFC_CMDMAT_CMD1_MATCH_OFFS	0
+#define NFC_CMDMAT_CMD1_MATCH_MASK	(0xFF << NFC_CMDMAT_CMD1_MATCH_OFFS)
+#define NFC_CMDMAT_CMD1_ROWADD_MASK	(0x1 << 8)
+#define NFC_CMDMAT_CMD1_NKDDIS_MASK	(0x1 << 9)
+#define NFC_CMDMAT_CMD2_MATCH_OFFS	10
+#define NFC_CMDMAT_CMD2_MATCH_MASK	(0xFF << NFC_CMDMAT_CMD2_MATCH_OFFS)
+#define NFC_CMDMAT_CMD2_ROWADD_MASK	(0x1 << 18)
+#define NFC_CMDMAT_CMD2_NKDDIS_MASK	(0x1 << 19)
+#define NFC_CMDMAT_CMD3_MATCH_OFFS	20
+#define NFC_CMDMAT_CMD3_MATCH_MASK	(0xFF << NFC_CMDMAT_CMD3_MATCH_OFFS)
+#define NFC_CMDMAT_CMD3_ROWADD_MASK	(0x1 << 28)
+#define NFC_CMDMAT_CMD3_NKDDIS_MASK	(0x1 << 29)
+#define NFC_CMDMAT_VALID_CNT_OFFS	30
+#define NFC_CMDMAT_VALID_CNT_MASK	(0x3 << NFC_CMDMAT_VALID_CNT_OFFS)
+
+/* NAND Controller Data Buffer */
+#define NFC_DATA_BUFF_REG_4PDMA		(MV_NFC_REGS_OFFSET + 0x40)
+#define NFC_DATA_BUFF_REG		(MV_NFC_REGS_BASE + 0x40)
+
+/* NAND Controller Command Buffer 0 */
+#define NFC_COMMAND_BUFF_0_REG_4PDMA	(MV_NFC_REGS_OFFSET + 0x48)
+#define NFC_COMMAND_BUFF_0_REG		(MV_NFC_REGS_BASE + 0x48)
+#define NFC_CB0_CMD1_OFFS		0
+#define NFC_CB0_CMD1_MASK		(0xFF << NFC_CB0_CMD1_OFFS)
+#define NFC_CB0_CMD2_OFFS		8
+#define NFC_CB0_CMD2_MASK		(0xFF << NFC_CB0_CMD2_OFFS)
+#define NFC_CB0_ADDR_CYC_OFFS		16
+#define NFC_CB0_ADDR_CYC_MASK		(0x7 << NFC_CB0_ADDR_CYC_OFFS)
+#define NFC_CB0_DBC_MASK			(0x1 << 19)
+#define NFC_CB0_NEXT_CMD_MASK		(0x1 << 20)
+#define NFC_CB0_CMD_TYPE_OFFS		21
+#define NFC_CB0_CMD_TYPE_MASK		(0x7 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CMD_TYPE_READ		(0x0 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CMD_TYPE_WRITE		(0x1 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CMD_TYPE_ERASE		(0x2 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CMD_TYPE_READ_ID	(0x3 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CMD_TYPE_STATUS		(0x4 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CMD_TYPE_RESET		(0x5 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CMD_TYPE_NAKED_CMD	(0x6 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CMD_TYPE_NAKED_ADDR	(0x7 << NFC_CB0_CMD_TYPE_OFFS)
+#define NFC_CB0_CSEL_MASK		(0x1 << 24)
+#define NFC_CB0_AUTO_RS_MASK		(0x1 << 25)
+#define NFC_CB0_ST_ROW_EN_MASK		(0x1 << 26)
+#define NFC_CB0_RDY_BYP_MASK		(0x1 << 27)
+#define NFC_CB0_LEN_OVRD_MASK		(0x1 << 28)
+#define NFC_CB0_CMD_XTYPE_OFFS		29
+#define NFC_CB0_CMD_XTYPE_MASK		(0x7 << NFC_CB0_CMD_XTYPE_OFFS)
+#define NFC_CB0_CMD_XTYPE_MONOLITHIC	(0x0 << NFC_CB0_CMD_XTYPE_OFFS)
+#define NFC_CB0_CMD_XTYPE_LAST_NAKED	(0x1 << NFC_CB0_CMD_XTYPE_OFFS)
+#define NFC_CB0_CMD_XTYPE_MULTIPLE	(0x4 << NFC_CB0_CMD_XTYPE_OFFS)
+#define NFC_CB0_CMD_XTYPE_NAKED		(0x5 << NFC_CB0_CMD_XTYPE_OFFS)
+#define NFC_CB0_CMD_XTYPE_DISPATCH	(0x6 << NFC_CB0_CMD_XTYPE_OFFS)
+
+/* NAND Controller Command Buffer 1 */
+#define NFC_COMMAND_BUFF_1_REG		(MV_NFC_REGS_BASE + 0x4C)
+#define NFC_CB1_ADDR1_OFFS		0
+#define NFC_CB1_ADDR1_MASK		(0xFF << NFC_CB1_ADDR1_OFFS)
+#define NFC_CB1_ADDR2_OFFS		8
+#define NFC_CB1_ADDR2_MASK		(0xFF << NFC_CB1_ADDR2_OFFS)
+#define NFC_CB1_ADDR3_OFFS		16
+#define NFC_CB1_ADDR3_MASK		(0xFF << NFC_CB1_ADDR3_OFFS)
+#define NFC_CB1_ADDR4_OFFS		24
+#define NFC_CB1_ADDR4_MASK		(0xFF << NFC_CB1_ADDR4_OFFS)
+
+/* NAND Controller Command Buffer 2 */
+#define NFC_COMMAND_BUFF_2_REG		(MV_NFC_REGS_BASE + 0x50)
+#define NFC_CB2_ADDR5_OFFS		0
+#define NFC_CB2_ADDR5_MASK		(0xFF << NFC_CB2_ADDR5_OFFS)
+#define NFC_CB2_CS_2_3_SELECT_MASK	(0x80 << NFC_CB2_ADDR5_OFFS)
+#define NFC_CB2_PAGE_CNT_OFFS		8
+#define NFC_CB2_PAGE_CNT_MASK		(0xFF << NFC_CB2_PAGE_CNT_OFFS)
+#define NFC_CB2_ST_CMD_OFFS		16
+#define NFC_CB2_ST_CMD_MASK		(0xFF << NFC_CB2_ST_CMD_OFFS)
+#define NFC_CB2_ST_MASK_OFFS		24
+#define NFC_CB2_ST_MASK_MASK		(0xFF << NFC_CB2_ST_MASK_OFFS)
+
+/* NAND Controller Command Buffer 3 */
+#define NFC_COMMAND_BUFF_3_REG		(MV_NFC_REGS_BASE + 0x54)
+#define NFC_CB3_NDLENCNT_OFFS		0
+#define NFC_CB3_NDLENCNT_MASK		(0xFFFF << NFC_CB3_NDLENCNT_OFFS)
+#define NFC_CB3_ADDR6_OFFS		16
+#define NFC_CB3_ADDR6_MASK		(0xFF << NFC_CB3_ADDR6_OFFS)
+#define NFC_CB3_ADDR7_OFFS		24
+#define NFC_CB3_ADDR7_MASK		(0xFF << NFC_CB3_ADDR7_OFFS)
+
+/* NAND Arbitration Control */
+#define NFC_ARB_CONTROL_REG		(MV_NFC_REGS_BASE + 0x5C)
+#define NFC_ARB_CNT_OFFS		0
+#define NFC_ARB_CNT_MASK		(0xFFFF << NFC_ARB_CNT_OFFS)
+
+/* NAND Partition Table for Chip Select */
+#define NFC_PART_TBL_4CS_REG(x)		(MV_NFC_REGS_BASE + (x * 0x4))
+#define NFC_PT4CS_BLOCKADD_OFFS		0
+#define NFC_PT4CS_BLOCKADD_MASK		(0xFFFFFF << NFC_PT4CS_BLOCKADD_OFFS)
+#define NFC_PT4CS_TRUSTED_MASK		(0x1 << 29)
+#define NFC_PT4CS_LOCK_MASK		(0x1 << 30)
+#define NFC_PT4CS_VALID_MASK		(0x1 << 31)
+
+/* NAND XBAR2AXI Bridge Configuration Register */
+#define NFC_XBAR2AXI_BRDG_CFG_REG	(MV_NFC_REGS_BASE + 0x1022C)
+#define NFC_XBC_CS_EXPAND_EN_MASK	(0x1 << 2)
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __INCMVNFCREGSH */
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvAmdFlash.c b/arch/arm/plat-feroceon/mv_hal/norflash/mvAmdFlash.c
new file mode 100755
index 0000000..a355839
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvAmdFlash.c
@@ -0,0 +1,257 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvFlash.h"
+
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+static MV_BOOL amdFlashStsIsRdy(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 excepted);
+static MV_VOID amdFlashUnlock(MV_FLASH_INFO *pFlash);
+
+/*******************************************************************************
+* reset the flash
+*******************************************************************************/
+MV_VOID amdFlashReset(MV_FLASH_INFO *pFlash)
+{
+	flashCmdSet(pFlash, 0, 0, AMD_CHIP_CMD_RST);
+	return;
+}
+
+/*******************************************************************************
+* amdFlashSecErase - Erase a sector.
+*
+* DESCRIPTION:
+*       Erase a Flash sector.
+*
+* INPUT:
+*       secNum  - sector Number.
+*       pFlash  - flash information.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       MV_OK if program completed successfully,
+*       MV_TIMEOUT if timeout reached,
+*       MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS amdFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 secNum)
+{
+	MV_U32 i;
+
+	DB(mvOsPrintf("Flash: amdFlashSecErase\n"));
+
+	/* erase sequence */
+	amdFlashUnlock(pFlash);
+
+	switch (pFlash->flashSpec.flashVen) {
+	case AMD_MANUF:
+	case STM_MANUF:
+		flashCmdSet(pFlash, AMD_CHIP_ADDR_ERASE1, 0, AMD_CHIP_CMD_ERASE1);
+		flashCmdSet(pFlash, AMD_CHIP_ADDR_ERASE2, 0, AMD_CHIP_CMD_ERASE2);
+		flashCmdSet(pFlash, AMD_CHIP_ADDR_ERASE3, 0, AMD_CHIP_CMD_ERASE3);
+		flashCmdSet(pFlash, 0, secNum, AMD_CHIP_CMD_ERASE4);
+		break;
+	case SST_MANUF:
+		flashCmdSet(pFlash, SST_CHIP_ADDR_ERASE1, 0, AMD_CHIP_CMD_ERASE1);
+		flashCmdSet(pFlash, SST_CHIP_ADDR_ERASE2, 0, AMD_CHIP_CMD_ERASE2);
+		flashCmdSet(pFlash, SST_CHIP_ADDR_ERASE3, 0, AMD_CHIP_CMD_ERASE3);
+		flashCmdSet(pFlash, 0, secNum, AMD_CHIP_CMD_ERASE4);
+		break;
+
+	}
+
+	/* wait for erase to complete */
+	for (i = 0; i < AMD_EARASE_MILI_TIMEOUT; i++) {
+		mvOsDelay(1);
+		if (MV_TRUE == amdFlashStsIsRdy(pFlash, mvFlashSecOffsGet(pFlash, secNum)
+						+ mvFlashBaseAddrGet(pFlash), AMD_CHIP_STAT_DQ7_MASK)) {
+			DB(mvOsPrintf("Flash: amdFlashSecErase erase PASS !!\n"));
+			return MV_OK;
+		}
+	}
+	mvOsPrintf("Flash: ERROR amdFlashSecErase timeout \n");
+
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* amdFlashProg - Prog busWidth Bits into the address offest in the flash.
+*
+* DESCRIPTION:
+*       This function writes busWidth data to a given flash offset.
+*
+* INPUT:
+*       pFlash - Flash identifier structure (flash cockie).
+*       offset - Offset from flash base address.
+*       data   - 32bit data to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK if program completed successfully,
+*	MV_TIMEOUT otherwise.
+*
+*******************************************************************************/
+MV_STATUS amdFlashProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data)
+{
+	MV_U32 i;
+	MV_U32 statusExpectedData;
+
+	DB(mvOsPrintf("Flash: amdFlashProg offset %x data %x\n", offset, data));
+
+	/* write sequence */
+	amdFlashUnlock(pFlash);
+
+	switch (pFlash->flashSpec.flashVen) {
+	case AMD_MANUF:
+	case STM_MANUF:
+		flashCmdSet(pFlash, AMD_CHIP_ADDR_PROG, 0, AMD_CHIP_CMD_PROG);
+		break;
+	case SST_MANUF:
+		flashCmdSet(pFlash, SST_CHIP_ADDR_PROG, 0, AMD_CHIP_CMD_PROG);
+		break;
+
+	}
+	flashBusWidthDataWr(pFlash, offset + mvFlashBaseAddrGet(pFlash), data);
+
+	/* To check status we need to be sure that the data is in the same endianess
+	   of the status, the status is always little endian and the data is big endian
+	   , so we will convert the data to little endian before calling the amdFlashStsIsRdy
+	   function */
+
+	switch (pFlash->busWidth) {
+	case 1:
+		statusExpectedData = data;
+		break;
+	case 2:
+		statusExpectedData = MV_16BIT_LE(data);
+		break;
+	case 4:
+		statusExpectedData = MV_32BIT_LE(data);
+		break;
+	default:
+		mvOsPrintf("%s ERROR: Bus Width %d Bytes isn't supported.\n", __func__, pFlash->busWidth);
+		return MV_TIMEOUT;
+	}
+
+	/* wait for write to complete */
+	for (i = 0; i < AMD_PROG_TIMEOUT; i++) {
+		if (MV_TRUE == amdFlashStsIsRdy(pFlash, offset + mvFlashBaseAddrGet(pFlash), statusExpectedData)) {
+			DB(mvOsPrintf("Flash: amdFlashProg prog PASS !!\n"));
+			return MV_OK;
+		}
+	}
+
+	mvOsPrintf("Flash: ERROR amdFlashSecErase timeout \n");
+
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* There are few ways to check if the AMD flash is busy or not:
+* 1) by checking DQ7 [and 5 - optional ]
+* 2) by checking toggle bit DQ7 (linux implementation)
+* here we used the first option:
+* after write/erase the flash push not(DQ7) until the opertion is completed.
+*******************************************************************************/
+static MV_BOOL amdFlashStsIsRdy(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 expected)
+{
+	MV_U32 status;
+
+	status = flashBusWidthRd(pFlash, addr);
+	/* if DQ7 == Datum 7 */
+	if ((status & flashDataExt(pFlash, AMD_CHIP_STAT_DQ7_MASK)) ==
+	    (flashDataExt(pFlash, expected) & flashDataExt(pFlash, AMD_CHIP_STAT_DQ7_MASK))) {
+		DB(mvOsPrintf("Flash: amdFlashStatusChk value is ready \n"));
+		return MV_TRUE;
+	}
+	DB(mvOsPrintf("Flash: amdFlashStatusChk staus not ready \n"));
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* Sequence for Unlocking the flash before accessing the flash.
+*******************************************************************************/
+static MV_VOID amdFlashUnlock(MV_FLASH_INFO *pFlash)
+{
+	switch (pFlash->flashSpec.flashVen) {
+	case AMD_MANUF:
+	case STM_MANUF:
+		flashCmdSet(pFlash, AMD_CHIP_UNLOCK_ADDR1, 0, AMD_CHIP_UNLOCK_CMD1);
+		flashCmdSet(pFlash, AMD_CHIP_UNLOCK_ADDR2, 0, AMD_CHIP_UNLOCK_CMD2);
+		break;
+	case SST_MANUF:
+		flashCmdSet(pFlash, SST_CHIP_UNLOCK_ADDR1, 0, AMD_CHIP_UNLOCK_CMD1);
+		flashCmdSet(pFlash, SST_CHIP_UNLOCK_ADDR2, 0, AMD_CHIP_UNLOCK_CMD2);
+		break;
+	}
+	return;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvAmdFlash.h b/arch/arm/plat-feroceon/mv_hal/norflash/mvAmdFlash.h
new file mode 100755
index 0000000..77e2227
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvAmdFlash.h
@@ -0,0 +1,168 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvAmdFlashH
+#define __INCmvAmdFlashH
+
+#include "mvFlashCom.h"
+
+
+/* AMD Flash IDs */
+#define AMD_FID_LV040B		0x4F		/* 29LV040B ID				*/
+						/* 4 Mbit, 512K x 8,			*/
+						/* 8 64K x 8 uniform sectors		*/
+
+#define AMD_FID_F040B		0xA4		/* 29F040B ID				*/
+						/* 4 Mbit, 512K x 8,			*/
+						/* 8 64K x 8 uniform sectors		*/
+#define STM_FID_M29W040B 	0xE3		/* M29W040B ID				*/
+						/* 4 Mbit, 512K x 8,			*/
+						/* 8 64K x 8 uniform sectors		*/
+#define AMD_FID_F080B		0xD5		/* 29F080  ID  ( 1 M)			*/
+						/* 8 Mbit, 512K x 16,			*/
+						/* 8 64K x 16 uniform sectors		*/
+#define AMD_FID_F016D		0xAD	/* 29F016  ID  ( 2 M x 8)		*/
+#define AMD_FID_F032B		0x41	/* 29F032  ID  ( 4 M x 8)		*/
+#define AMD_FID_LV116DT		0xC7	/* 29LV116DT   ( 2 M x 8, top boot sect)*/
+#define AMD_FID_LV016B		0xc8	/* 29LV016 ID  ( 2 M x 8)		*/
+
+#define AMD_FID_LV400T		0x22B9	/* 29LV400T ID ( 4 M, top boot sector)	*/
+#define AMD_FID_LV400B		0x22BA	/* 29LV400B ID ( 4 M, bottom boot sect) */
+
+#define AMD_FID_LV033C		0xA3	/* 29LV033C ID ( 4 M x 8)		*/
+#define AMD_FID_LV065D		0x93	/* 29LV065D ID ( 8 M x 8)		*/
+
+#define AMD_FID_LV800T		0x22DA	/* 29LV800T ID ( 8 M, top boot sector)	*/
+#define AMD_FID_LV800B		0x225B	/* 29LV800B ID ( 8 M, bottom boot sect) */
+
+#define AMD_FID_LV160T		0x22C4	/* 29LV160T ID (16 M, top boot sector)	*/
+#define AMD_FID_LV160B		0x2249	/* 29LV160B ID (16 M, bottom boot sect) */
+
+#define AMD_FID_LV320T		0x22F6	/* 29LV320T ID (32 M, top boot sector)	*/
+#define AMD_FID_LV320B		0x22F9	/* 29LV320B ID (32 M, bottom boot sect) */
+
+#define AMD_FID_DL322T		0x2255	/* 29DL322T ID (32 M, top boot sector)	*/
+#define AMD_FID_DL322B		0x2256	/* 29DL322B ID (32 M, bottom boot sect) */
+#define AMD_FID_DL323T		0x2250	/* 29DL323T ID (32 M, top boot sector)	*/
+#define AMD_FID_DL323B		0x2253	/* 29DL323B ID (32 M, bottom boot sect) */
+#define AMD_FID_DL324T		0x225C	/* 29DL324T ID (32 M, top boot sector)	*/
+#define AMD_FID_DL324B		0x225F	/* 29DL324B ID (32 M, bottom boot sect) */
+
+#define AMD_S29GL128N		0x227E  /* S29GL128N spansion 128Mbit flash     */
+#define AMD_FID_DL640		0x227E	/* 29DL640D ID (64 M, dual boot sectors)*/
+#define AMD_FID_MIRROR		0x227E	/* 1st ID word for MirrorBit family 	*/
+#define AMD_FID_LV640U_2	0x220C	/* 2d ID word for AM29LV640M at 0x38	*/
+#define AMD_FID_LV640U_3	0x2201	/* 3d ID word for AM29LV640M at 0x3c 	*/
+#define AMD_FID_LV128U_2 	0x2212	/* 2d ID word for AM29LV128M at 0x38 	*/
+#define AMD_FID_LV128U_3 	0x2200	/* 3d ID word for AM29LV128M at 0x3c 	*/
+
+#define AMD_FID_LV640U	 	0x22D7	/* 29LV640U ID (64 M, uniform sectors)	*/
+
+#define STM_FID_29W040B  	0xE3	/* M29W040B ID (4M = 512K x 8)  */
+
+/* SST Flash IDs */
+#define SST_39VF_020 		0xD6	/* SST39VF020 (256KB = 4K * 64) */
+
+
+/* Amd Flash APIs */
+#define AMD_EARASE_MILI_TIMEOUT	8000		/* mili seconds 	*/
+#define AMD_PROG_TIMEOUT		0xA0000 	/* number of loops 	*/
+
+/* Commands */
+#define AMD_CHIP_CMD_RST		0xF0		/* reset flash 			*/
+#define AMD_CHIP_UNLOCK_CMD1	0xAA		/* 1st data for unlock 		*/
+#define AMD_CHIP_UNLOCK_ADDR1	0x555		/* 1st addr for unlock 		*/
+#define SST_CHIP_UNLOCK_ADDR1	0x5555		/* 1st addr for unlock 		*/
+#define AMD_CHIP_UNLOCK_CMD2	0x55		/* 2nd data for unlock 		*/
+#define AMD_CHIP_UNLOCK_ADDR2	0x2AA		/* 2nd addr for unlock 		*/
+#define SST_CHIP_UNLOCK_ADDR2	0x2AAA		/* 2nd addr for unlock 		*/
+#define AMD_CHIP_CMD_PROG		0xA0		/* 1st data for program command */
+#define AMD_CHIP_ADDR_PROG		0x555		/* 1st addr for program command */
+#define SST_CHIP_ADDR_PROG		0x5555		/* 1st addr for program command */
+#define AMD_CHIP_CMD_ERASE1		0x80		/* 1st data for erase command 	*/
+#define AMD_CHIP_ADDR_ERASE1	0x555		/* 1st addr for erase command 	*/
+#define SST_CHIP_ADDR_ERASE1	0x5555		/* 1st addr for erase command 	*/
+#define AMD_CHIP_CMD_ERASE2		0xAA		/* 2nd data for erase command 	*/
+#define AMD_CHIP_ADDR_ERASE2	0x555		/* 2nd addr for erase command 	*/
+#define SST_CHIP_ADDR_ERASE2	0x5555		/* 2nd addr for erase command 	*/
+#define AMD_CHIP_CMD_ERASE3		0x55		/* 3rd data for erase command 	*/
+#define AMD_CHIP_ADDR_ERASE3	0x2AA		/* 3rd addr for erase command 	*/
+#define SST_CHIP_ADDR_ERASE3	0x2AAA		/* 3rd addr for erase command 	*/
+#define AMD_CHIP_CMD_ERASE4		0x30		/* 4rd data for erase command 	*/
+
+/* there are few ways to check if the AMD flash is busy or not:				*/
+/* 1) by checking DQ7 [and 5 - optional ]						*/
+/* 2) by checking toggle bit DQ7 (linux)						*/
+/* here we used the first option.			 				*/
+/* status register bits */
+#define AMD_CHIP_STAT_DQ7_MASK	0x80		/* Device is ready 		*/
+
+/* ID and Lock Configuration */
+#define AMD_CHIP_RD_ID_MAN		0x01		/* Manufacturer code = 0x89 	*/
+
+MV_STATUS amdFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 secNum);
+MV_VOID amdFlashReset(MV_FLASH_INFO *pFlash);
+MV_STATUS amdFlashProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data);
+
+#endif /* __INCmvAmdFlashH */
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/norflash/mvCompVer.txt
new file mode 100755
index 0000000..3afa556
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.3
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvFlash.c b/arch/arm/plat-feroceon/mv_hal/norflash/mvFlash.c
new file mode 100755
index 0000000..cf89998
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvFlash.c
@@ -0,0 +1,1297 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvFlash.h"
+
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+#define LAST_FLASH 0xFFFFFFFF
+/* When inserting a bottom/top flash number of sectors should be the number */
+/* of all sector including the "fragmented" sectors.                        */
+/*                                                                          */
+/* Size of the flash must be as spesified in Spec, in case there are 2 dev  */
+/* in a row the driver will recognize it according to bus and dev width.    */
+/*                                                                          */
+/* In case of using Bottom flash it should look like this:                  */
+/* MV_U32 IntelSecFrag[]= {_8K, _8K, _8K, _8K, _8K, _8K, _8K, _8K};         */
+/* FLASH_STRUCT supFlashAry[]=                                              */
+/* {                                                                        */
+/*  {                                                                       */
+/*   INTEL_MANUF,           flash Vendor                                    */
+/*   INTEL_FID_28F640J3A,   flash ID                                        */
+/*   _4M,                   flash size                                      */
+/*   71,                    flash secotor number                            */
+/*   BOTTOM,                flash sector structure (top, bottom, regular)   */
+/*   8,                     Number of sector fragments                      */
+/*   IntelSecFrag,          pointer to sector size fragment list            */
+/*   MV_FALSE               Support of HW protection                        */
+/*  },                                                                      */
+/*   .......                                                                */
+/* }                                                                        */
+/*                                                                          */
+
+MV_U32 IntelSecFrag[] = { _32K, _32K, _32K, _32K };
+
+FLASH_STRUCT supFlashAry[] = {
+/*  flashVen       flashId         size  #sec  secType #Frag pFragList HWprot HwWrBuff */
+	{INTEL_MANUF, INTEL_FID_28F256P30B, _32M, 259, BOTTOM, 4, IntelSecFrag, MV_TRUE, 64}
+	,
+	{INTEL_MANUF, INTEL_FID_28F640J3A, _8M, 64, REGULAR, 0, NULL, MV_TRUE, 32}
+	,
+	{INTEL_MANUF, INTEL_FID_28F128J3A, _16M, 128, REGULAR, 0, NULL, MV_TRUE, 32}
+	,
+	{SST_MANUF, SST_39VF_020, _256K, 64, REGULAR, 0, NULL, MV_FALSE, 0}
+	,
+	{AMD_MANUF, AMD_FID_LV040B, _512K, 8, REGULAR, 0, NULL, MV_FALSE, 0}
+	,
+	{STM_MANUF, STM_FID_29W040B, _512K, 8, REGULAR, 0, NULL, MV_FALSE, 0}
+	,
+	{AMD_MANUF, AMD_S29GL128N, _16M, 128, REGULAR, 0, NULL, MV_FALSE}
+	,
+	{MX_MANUF, AMD_FID_MIRROR, _16M, 256, REGULAR, 0, NULL, MV_FALSE}
+	,
+	{STM_MANUF, AMD_FID_MIRROR, _16M, 256, REGULAR, 0, NULL, MV_FALSE}
+	,
+	{LAST_FLASH, LAST_FLASH, 0, 0, REGULAR, 0, NULL, MV_FALSE, 0}
+};
+
+static MV_STATUS flashReset(MV_FLASH_INFO *pFlash);
+static MV_STATUS flashStructGet(MV_FLASH_INFO *pFlash, MV_U32 manu, MV_U32 id);
+static MV_STATUS flashSecsInit(MV_FLASH_INFO *pFlash);
+static MV_BOOL flashSecLockGet(MV_FLASH_INFO *pBlock, MV_U32 secNum);
+static MV_STATUS mvFlashProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data);
+static MV_U32 flashGetHwBuffSize(MV_FLASH_INFO *pFlash);
+static MV_STATUS flashHwBufferProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 byteCount, MV_U8 *pData);
+
+/*******************************************************************************
+* mvFlashInit - Initialize a flash descriptor structure.
+*
+* DESCRIPTION:
+*       This function intialize flash info struct with specified flash
+*       parameters. This structure is used to identify the target flash the
+*       function refers to. This allow the use of the same API for multiple
+*       flash devices.
+*
+*
+* INPUT:
+*       pFlash->baseAddr - Flash base address.
+*       pFlash->busWidth - Flash bus width (8, 16, 32 bit).
+*       pFlash->devWidth - Flash device width (8 or 16 bit).
+*
+* OUTPUT:
+*       pFlash - Flash identifier structure.
+*
+* RETURN:
+*       32bit describing flash size.
+*       In case of any error, it returns 0.
+*
+*******************************************************************************/
+MV_U32 mvFlashInit(MV_FLASH_INFO *pFlash)
+{
+	MV_U32 manu = 0, id = 0;
+
+	if (NULL == pFlash)
+		return 0;
+
+	DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n",
+		      pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth));
+
+	/* must init first sector base, before calling flashCmdSet */
+	pFlash->sector[0].baseOffs = 0;
+	/* reset flash 0xf0(AMD) 0xff (Intel) */
+	flashCmdSet(pFlash, 0, 0, 0xf0);
+	flashCmdSet(pFlash, 0, 0, 0xff);
+
+	/* Write auto select command: read Manufacturer ID      */
+	/* AMD seq is: 0x555 0xAA -> 0x2AA 0x55 -> 0x555 0x90   */
+	/* INTEL seq is dc 0x90                                 */
+	flashCmdSet(pFlash, 0x555, 0, 0xAA);
+	flashCmdSet(pFlash, 0x2AA, 0, 0x55);
+	flashCmdSet(pFlash, 0x555, 0, 0x90);
+
+	/* Write auto select command: read Manufacturer ID      */
+	/* SST seq is: 0x5555 0xAA -> 0x2AAA 0x55 -> 0x5555 0x90        */
+	flashCmdSet(pFlash, 0x5555, 0, 0xAA);
+	flashCmdSet(pFlash, 0x2AAA, 0, 0x55);
+	flashCmdSet(pFlash, 0x5555, 0, 0x90);
+
+	DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n",
+		      pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth));
+
+	/* get flash Manufactor and Id */
+	manu = flashBusWidthRd(pFlash, mvFlashBaseAddrGet(pFlash));
+	DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n",
+		      pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth));
+
+	/* Some Micron flashes don't use A0 address for Identifier and
+	   Lock information, so in order to read Identifier and lock information
+	   properly we will do the following workarround:
+	   If our device width is 1 (x8) then if address 0 equal to address 1
+	   and address 2 equal to address 3 ,then we have this case (A0 is not used)
+	   and then we will issue the address without A0 to read the Identifier and
+	   lock information properly */
+	DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n",
+		      pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth));
+
+	if ((pFlash->devWidth == 1) &&
+	    ((flashBusWidthRd(pFlash, flashAddrExt(pFlash, 0, 0)) ==
+	      flashBusWidthRd(pFlash, flashAddrExt(pFlash, 1, 0))) &&
+	     (flashBusWidthRd(pFlash, flashAddrExt(pFlash, 2, 0)) ==
+	      flashBusWidthRd(pFlash, flashAddrExt(pFlash, 3, 0))))) {
+		id = flashBusWidthRd(pFlash, flashAddrExt(pFlash, 2, 0));
+
+	} else
+		id = flashBusWidthRd(pFlash, flashAddrExt(pFlash, 1, 0));
+
+	/* check if this flash is Supported, and Init the pFlash flash feild */
+	if (MV_OK != flashStructGet(pFlash, manu, id)) {
+		mvOsPrintf("%s: Flash ISN'T supported: manufactor-0x%x, id-0x%x\n", __func__, manu, id);
+		return 0;
+	}
+	DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n",
+		      pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth));
+
+	/* Init pFlash sectors */
+	if (MV_OK != flashSecsInit(pFlash)) {
+		mvOsPrintf("Flash: ERROR mvFlashInit flashSecsInit failed \n");
+		return 0;
+	}
+
+	DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n",
+		      pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth));
+
+	/* print all flash information */
+	DB(flashPrint(pFlash));
+
+	/* reset the Flash */
+	flashReset(pFlash);
+	DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n",
+		      pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth));
+
+	return mvFlashSizeGet(pFlash);
+}
+
+/* erase */
+/*******************************************************************************
+* mvFlashErase - Completly Erase a flash.
+*
+* DESCRIPTION:
+*       This function completly erase the given flash, by erasing all the
+*		flash sectors one by one (Currently there is no support for HW
+*		flash erase).
+*
+* INPUT:
+*       pFlash - Flash identifier structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	MV_BAD_PARAM if pFlash is NULL,
+*   MV_OK if erased completed successfully,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvFlashErase(MV_FLASH_INFO *pFlash)
+{
+	MV_U32 i;
+
+	if (NULL == pFlash)
+		return MV_BAD_PARAM;
+
+	DB(mvOsPrintf("Flash: mvFlashErase \n"));
+	/* erase all sectors in the flash one by one */
+	for (i = 0; i < mvFlashNumOfSecsGet(pFlash); i++) {
+		if (MV_OK != mvFlashSecErase(pFlash, i))
+			return MV_FAIL;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* flashIsSecErased - Check if a given Sector is erased.
+*
+* DESCRIPTION:
+*	Go over the sector and check if its entire data is 0xFF.
+* INPUT:
+*       secNum	- sector Number.
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_BAD_PARAM if one of the inputs values is illegal,
+*	MV_TRUE if sector is already erased,
+*	MV_FALSE otherwise.
+*
+*******************************************************************************/
+MV_BOOL flashIsSecErased(MV_FLASH_INFO *pFlash, MV_U32 secNum)
+{
+	MV_U32 i;
+
+	DB(mvOsPrintf("Flash: flashIsSecErased. \n"));
+	if ((NULL == pFlash) || (secNum >= mvFlashNumOfSecsGet(pFlash)))
+		return MV_BAD_PARAM;
+
+	/* reset the flash */
+	flashReset(pFlash);
+
+	/* go over the sector */
+	for (i = mvFlashSecOffsGet(pFlash, secNum);
+	     i < mvFlashSecOffsGet(pFlash, secNum) + mvFlashSecSizeGet(pFlash, secNum); i += 4) {
+		if (mvFlash32Rd(pFlash, i) != FLASH_WR_ERASED) {
+			DB(mvOsPrintf("Flash: Not erased addr %x is %x \n", i, mvFlash32Rd(pFlash, i)));
+			return MV_FALSE;
+		}
+	}
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvFlashSecErase - Erase a flash sector.
+*
+* DESCRIPTION:
+*       This function checks if the sector isn't protected and if the sector
+*		isn't already erased.
+*
+* INPUT:
+*       pFlash    - Flash identifier structure.
+*       sectorNum - secrot number to erase.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	MV_BAD_PARAM if one of the inputs values is illegal,
+*       MV_OK if erased completed successfully,
+*	MV_FAIL otherwise (e.g. sector protected).
+*
+*******************************************************************************/
+MV_STATUS mvFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 sectorNum)
+{
+	MV_U32 status;
+	DB(mvOsPrintf("Flash: mvFlashSecErase \n"));
+
+	/* check parametrs values */
+	if ((NULL == pFlash) || (sectorNum >= mvFlashNumOfSecsGet(pFlash)))
+		return MV_BAD_PARAM;
+
+	/* check if sector is locked */
+	if (MV_TRUE == mvFlashSecLockGet(pFlash, sectorNum)) {
+		mvOsPrintf("Flash: ERROR mvFlashSecErase protected sector.\n");
+		return MV_FAIL;
+	}
+	/* check if already erased */
+	if (MV_TRUE == flashIsSecErased(pFlash, sectorNum)) {
+		DB(mvOsPrintf("Flash: FlashSecErase sector already erased \n"));
+		return MV_OK;
+	}
+
+	/* erase sector using the Flash Ven Alg. */
+	switch (mvFlashVenIdGet(pFlash)) {
+	case INTEL_MANUF:	/* INTEL/MT */
+		status = intelFlashSecErase(pFlash, sectorNum);
+		break;
+	case AMD_MANUF:
+	case STM_MANUF:
+	case SST_MANUF:
+	case MX_MANUF:
+		status = amdFlashSecErase(pFlash, sectorNum);
+		break;
+	default:
+		mvOsPrintf("Flash: ERROR mvFlashErase. unsupported flash vendor\n");
+		return MV_FAIL;
+	}
+	/* reset the flash */
+	flashReset(pFlash);
+
+	return status;
+}
+
+/* write */
+/*******************************************************************************
+* mvFlash32Wr - Write 32bit (word) to flash.
+*
+* DESCRIPTION:
+*       This function writes 32bit data to a given flash offset.
+*
+* INPUT:
+*       pFlash - Flash identifier structure (flash cockie).
+*       offset - Offset from flash base address.
+*       data   - 32bit data to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	MV_BAD_PARAM if one of the inputs values is illegal,
+*       MV_OK if write completed successfully,
+*	MV_FAIL otherwise (e.g. sector protected).
+*
+*******************************************************************************/
+MV_STATUS mvFlash32Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data)
+{
+	MV_U32 i, status = MV_OK, temp, secNum;
+
+	DB(mvOsPrintf("Flash: mvFlash32Wr offset %x data %x \n", offset, data));
+
+	/* check that the offset is aligned to 32 bit */
+	if ((NULL == pFlash) || (offset % 4))
+		return MV_BAD_PARAM;
+
+	secNum = mvFlashInWhichSec(pFlash, offset);
+
+	DB(mvOsPrintf("Flash: mvFlashProg \n"));
+	/* check if offset is in flash range */
+	if (secNum >= mvFlashNumOfSecsGet(pFlash)) {
+		DB(mvOsPrintf("Flash: mvFlashProg offset out of flash range \n"));
+		return MV_BAD_PARAM;
+	}
+
+	/* check if sector is locked */
+	if (MV_TRUE == mvFlashSecLockGet(pFlash, secNum)) {
+		mvOsPrintf("Flash: ERROR mvFlashProg protected sector.\n");
+		return MV_FAIL;
+	}
+
+	/* check if offset is erased enough */
+	if ((mvFlash32Rd(pFlash, offset) & data) != data) {
+		mvOsPrintf("%s ERROR: offset 0x%x (sector %d) isn't erased !!!.\n", __func__, offset, secNum);
+		return MV_FAIL;
+	}
+
+	/* bus width is 32 bit */
+	if (mvFlashBusWidthGet(pFlash) == 4) {
+		data = MV_32BIT_BE(data);
+		status = mvFlashProg(pFlash, offset, data);
+		if (status != MV_OK)
+			mvOsPrintf("%s ERROR: mvFlashProg() status %x \n", __func__, status);
+	}
+
+	/* bus width is 16 bit */
+	else if (mvFlashBusWidthGet(pFlash) == 2) {
+		for (i = 0; i < 2; i++) {
+			/* 0x44556677 -> [44][55][66][77] */
+			temp = MV_16BIT_BE(((data >> (16 * (1 - i))) & FLASH_MASK_16BIT));
+			if (MV_OK != mvFlashProg(pFlash, offset + (i * 2), temp)) {
+				status = MV_FAIL;
+				break;
+			}
+		}
+	}
+	/* bus width is 8 bit */
+	else if (mvFlashBusWidthGet(pFlash) == 1) {
+		for (i = 0; i < 4; i++) {
+			/* 0x44556677 -> [44][55][66][77] */
+			temp = ((data >> (8 * (3 - i))) & FLASH_MASK_8BIT);
+			if (MV_OK != mvFlashProg(pFlash, offset + i, temp))
+				status = MV_FAIL;
+		}
+	}
+	/* bus width isn't 8/16/32 */
+	else {
+		DB(mvOsPrintf("Flash: mvFlashWordWr no support for for bus width %d \n", mvFlashBusWidthGet(pFlash)));
+		status = MV_FAIL;
+	}
+	/* reset the flash */
+	flashReset(pFlash);
+
+	if (status != MV_OK)
+		mvOsPrintf("mvFlash32Wr: ERROR #### status %x \n", status);
+
+	return status;
+}
+
+/*******************************************************************************
+* mvFlash16Wr - Write 16bit (short) to flash.
+*
+* DESCRIPTION:
+*       This function writes 16bit data to a given flash offset.
+*
+* INPUT:
+*       pFlash - Flash identifier structure (flash cockie).
+*       offset - Offset from flash base address.
+*       sdata  - 16bit data to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	MV_BAD_PARAM if one of the inputs values is illegal,
+*       MV_OK if write completed successfully,
+*	MV_FAIL otherwise (e.g. sector protected).
+*
+*******************************************************************************/
+MV_STATUS mvFlash16Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U16 sdata)
+{
+	MV_U32 temp, shiftSdata;
+
+	DB(mvOsPrintf("Flash: mvFlash16Wr\n"));
+
+	/* check that the offset is aligned to 16 bit */
+	if ((NULL == pFlash) || (offset % 2))
+		return MV_BAD_PARAM;
+
+	/* sdata shift in 32 bit aligned. i.e.                                                                  */
+	/* wr 0x9922 to 0xf4000002 -> 0xf4000000: qqqq9999                                              */
+	shiftSdata = (1 - ((offset & 0x2) >> 1)) * 16;
+	/* read 32 bit aligned */
+	temp = mvFlash32Rd(pFlash, MV_ALIGN_DOWN(offset, 4));	/* aligned to 32 bit */
+	/* write 16 bit sdata into 32 bit */
+	temp &= temp & ~(0xffff << shiftSdata);
+	temp |= sdata << shiftSdata;
+
+	/* write 32 bit */
+	return mvFlash32Wr(pFlash, MV_ALIGN_DOWN(offset, 4), temp);
+}
+
+/*******************************************************************************
+* mvFlash8Wr - Write 8bit (char) to flash.
+*
+* DESCRIPTION:
+*       This function writes 8bit data to a given flash offset.
+*
+* INPUT:
+*       pFlash - Flash identifier structure (flash cockie).
+*       offset - Offset from flash base address.
+*       cdata  - 8bit data to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	MV_BAD_PARAM if one of the inputs values is illegal,
+*       MV_OK if write completed successfully,
+*	MV_FAIL otherwise (e.g. sector protected).
+*
+*******************************************************************************/
+MV_STATUS mvFlash8Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U8 cdata)
+{
+	MV_U32 temp, shiftCdata;
+
+	DB(mvOsPrintf("Flash: mvFlash8Wr\n"));
+	/* check that the offset is aligned to 16 bit */
+	if (NULL == pFlash)
+		return MV_BAD_PARAM;
+
+	/* cdata shift in 32 bit aligned. i.e.                                                                  */
+	/* wr 0x99 to 0xf4000003 -> 0xf4000000: qqqqqq99                                                */
+	shiftCdata = (3 - (offset & 0x3)) * 8;
+	/* read 32 bit aligned */
+	temp = mvFlash32Rd(pFlash, MV_ALIGN_DOWN(offset, 4));	/* aligned to 32 bit */
+	/* write 16 bit sdata into 32 bit */
+	temp &= temp & ~(0xff << shiftCdata);
+	temp |= cdata << shiftCdata;
+	/* write 32 bit */
+	return mvFlash32Wr(pFlash, MV_ALIGN_DOWN(offset, 4), temp);
+}
+
+/*******************************************************************************
+* mvFlashBlockUnbufWr - Write a block to flash. Unbuffered
+*
+* DESCRIPTION:
+*       This function writes a block of data to a given flash offset.
+*
+* INPUT:
+*       pFlash    - Flash identifier structure (flash cockie).
+*       offset    - Offset from flash base address.
+*       blockSize - Size of block in bytes.
+*       pBlock    - Pointer to data block to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       The number of bytes written to flash.
+*
+*******************************************************************************/
+MV_U32 mvFlashBlockUnbufWr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock)
+{
+	MV_U32 i, j, temp = 0;
+
+	DB(mvOsPrintf("Flash: mvFlashBlockWr\n"));
+	if (NULL == pFlash)
+		return 0;
+
+#ifndef CONFIG_MARVELL
+	if (NULL == pBlock)
+		return 0;
+#endif
+
+	for (i = 0; i < blockSize;) {
+		if (((offset + i) % 4) || ((blockSize - i) < 4)) {	/* unaligned to 32 bit */
+			DB(mvOsPrintf("Flash: mvFlashBlockWr not aligned\n"));
+			if (MV_OK != mvFlash8Wr(pFlash, offset + i, pBlock[i])) {
+				DB(mvOsPrintf("Flash: mvFlashBlockWr failed in writing char\n"));
+				return i;
+			}
+			i++;
+		} else {	/* aligned to 32 bit */
+
+			temp = 0;
+			/* to make sure we don't write to un aligned address */
+			for (j = 0; j < 4; j++) {
+				/* [44][55][66][77] -> 0x44556677  */
+				temp |= (pBlock[i + j] & FLASH_MASK_8BIT) << (8 * (3 - j));
+			}
+			if (MV_OK != mvFlash32Wr(pFlash, offset + i, temp)) {
+				DB(mvOsPrintf("Flash: mvFlashBlockWr failed in writing word\n"));
+				return i;
+			}
+			i += 4;
+		}
+	}
+
+	return i;
+}
+
+/*******************************************************************************
+* mvFlashBlockWr - Write a block to flash.
+*
+* DESCRIPTION:
+*       This function writes a block of data to a given flash offset.
+*
+* INPUT:
+*       pFlash    - Flash identifier structure (flash cockie).
+*       offset    - Offset from flash base address.
+*       blockSize - Size of block in bytes.
+*       pBlock    - Pointer to data block to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       The number of bytes written to flash.
+*
+*******************************************************************************/
+MV_U32 mvFlashBlockWr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock)
+{
+	MV_U32 numOfBytesWritten = 0;
+	MV_U32 secNum;		/* lastOffset; */
+	MV_U32 i;
+	MV_U32 hwBuffSize, sizeToWrite;
+	MV_U32 unBufWritten = 0;
+	MV_U8 *pTmpBlock = NULL;
+
+	DB(mvOsPrintf("Flash: mvFlashBlockWr\n"));
+	if (NULL == pFlash)
+		return 0;
+
+#ifndef CONFIG_MARVELL
+	if (NULL == pBlock)
+		return 0;
+#endif
+
+	/* check if any of the dest sectors is protected  */
+	/*lastOffset = ((MV_U32)pBlock) + blockSize; */
+	secNum = mvFlashInWhichSec(pFlash, offset);
+	do {
+		if (MV_TRUE == mvFlashSecLockGet(pFlash, secNum)) {
+			mvOsPrintf("Flash: ERROR mvFlashProg protected sector.\n");
+			return 0;
+		}
+
+		/* next sec base offset */
+		i = mvFlashSecOffsGet(pFlash, secNum) + mvFlashSecSizeGet(pFlash, secNum);
+		secNum++;
+
+	} while (i < blockSize);
+
+	hwBuffSize = flashGetHwBuffSize(pFlash);
+
+	/* if no HW buffer support, then call unbuffer routine */
+	if (hwBuffSize == 0)
+		return mvFlashBlockUnbufWr(pFlash, offset, blockSize, pBlock);
+
+	flashReset(pFlash);
+
+	/* now write unbuffered the unaligned data */
+	while (((offset % hwBuffSize) || (blockSize < hwBuffSize)) && (blockSize)) {
+		DB(mvOsPrintf("if I: offset = 0x%x, blockSize= 0x%x\n", offset, blockSize));
+
+		if ((blockSize < hwBuffSize) ||
+		    ((offset + blockSize) < (offset + (2 * hwBuffSize + (offset / hwBuffSize))))) {
+			sizeToWrite = blockSize;
+		} else
+			sizeToWrite = hwBuffSize - (offset % hwBuffSize);
+
+		unBufWritten = mvFlashBlockUnbufWr(pFlash, offset, sizeToWrite, pBlock);
+
+		flashReset(pFlash);
+
+		blockSize -= unBufWritten;
+		offset += unBufWritten;
+		pBlock += unBufWritten;
+		numOfBytesWritten += unBufWritten;
+
+		if (unBufWritten != sizeToWrite)
+			return numOfBytesWritten;
+
+	}
+
+	if (blockSize) {
+		/* now write buffered the aligned data */
+		sizeToWrite = blockSize - (blockSize % hwBuffSize);
+
+		/* Check source addr, in case source is in the FLASH            */
+		/* First copy the data to a temporary container in the SDRAM    */
+		/* and only then copy the data from the SDRAM to the FLASH      */
+		if (((MV_U32) pBlock >= mvFlashBaseAddrGet(pFlash)) &&
+		    ((MV_U32) pBlock < (mvFlashBaseAddrGet(pFlash) + mvFlashSizeGet(pFlash)))) {
+			/* Malloc memory */
+			pTmpBlock = mvOsMalloc(sizeToWrite);
+			if (NULL == pTmpBlock) {
+				DB(mvOsPrintf("mvFlashBlockWr: Malloc temporary container failed\n"));
+				flashReset(pFlash);
+				return numOfBytesWritten;
+			}
+			/* Copy data to SDRAM */
+			memcpy(pTmpBlock, pBlock, sizeToWrite);
+			/* Change source pointer to SDRAM */
+		} else
+			/* Source address is not in flash */
+			pTmpBlock = pBlock;
+
+		/* Write data to flash */
+		if (MV_OK != flashHwBufferProg(pFlash, offset, sizeToWrite, pTmpBlock)) {
+			DB(mvOsPrintf("mvFlashBlockWr: flashHwBufferProg failed\n"));
+			flashReset(pFlash);
+			return numOfBytesWritten;
+		}
+		/* Free memory only if used SDRAM container */
+		if (pTmpBlock != pBlock)
+			mvOsFree(pTmpBlock);
+
+		flashReset(pFlash);
+
+		blockSize -= sizeToWrite;
+		offset += sizeToWrite;
+		pBlock += sizeToWrite;
+		numOfBytesWritten += sizeToWrite;
+
+	}
+
+	/* now write unbuffered the rest */
+	if (blockSize) {
+		unBufWritten = mvFlashBlockUnbufWr(pFlash, offset, blockSize, pBlock);
+
+		flashReset(pFlash);
+
+		blockSize -= unBufWritten;
+		offset += unBufWritten;
+		pBlock += unBufWritten;
+		numOfBytesWritten += unBufWritten;
+
+	}
+
+	return numOfBytesWritten;
+}
+
+/* read */
+/*******************************************************************************
+* mvFlash32Rd - Read a 32bit (word) from flash.
+*
+* DESCRIPTION:
+*       This function reads 32bit (word) data from a given flash offset.
+*
+* INPUT:
+*       pFlash   - Flash identifier structure (flash cockie).
+*       offset   - Offset from flash base address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit data read from flash.
+*
+*******************************************************************************/
+MV_U32 mvFlash32Rd(MV_FLASH_INFO *pFlash, MV_U32 offset)
+{
+	MV_U32 val;
+
+	DB(mvOsPrintf("Flash: mvFlashWordRd %x\n", offset));
+	if (NULL == pFlash)
+		return 0;
+
+	val = MV_FL_32_DATA_READ(offset + mvFlashBaseAddrGet(pFlash));
+
+	return MV_32BIT_BE(val);
+}
+
+/*******************************************************************************
+* mvFlash16Rd - Read a 16bit (short) from flash.
+*
+* DESCRIPTION:
+*       This function reads 16bit (short) data from a given flash offset.
+*
+* INPUT:
+*       pFlash   - Flash identifier structure (flash cockie).
+*       offset   - Offset from flash base address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       16bit data read from flash.
+*
+*******************************************************************************/
+MV_U16 mvFlash16Rd(MV_FLASH_INFO *pFlash, MV_U32 offset)
+{
+	MV_U32 val;
+
+	if (NULL == pFlash)
+		return 0;
+
+	val = MV_FL_16_DATA_READ(offset + mvFlashBaseAddrGet(pFlash));
+
+	return MV_16BIT_BE(val);
+}
+
+/*******************************************************************************
+* mvFlash8Rd - Read a 8bit (char) from flash.
+*
+* DESCRIPTION:
+*       This function reads 8bit (char) data from a given flash offset.
+*
+* INPUT:
+*       pFlash   - Flash identifier structure (flash cockie).
+*       offset   - Offset from flash base address.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       8bit data read from flash.
+*	0 if pflash is NULL.
+*
+*******************************************************************************/
+MV_U8 mvFlash8Rd(MV_FLASH_INFO *pFlash, MV_U32 offset)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return MV_FL_8_DATA_READ(offset + mvFlashBaseAddrGet(pFlash));
+}
+
+/*******************************************************************************
+* mvFlashBlockRd - Read a block of data from flash.
+*
+* DESCRIPTION:
+*       This function reads a block of data from given flash offset.
+*
+* INPUT:
+*       pFlash    - Flash identifier structure (flash cockie).
+*       offset    - Offset from flash base address.
+*       blockSize - Size of block in bytes.
+*
+* OUTPUT:
+*       pBlock   - Pointer to data block to be read from flash.
+*
+* RETURN:
+*       The number of bytes read from flash.
+*
+*******************************************************************************/
+MV_U32 mvFlashBlockRd(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock)
+{
+	MV_U32 i, j, temp;
+
+	if ((NULL == pFlash) || (NULL == pBlock))
+		return 0;
+
+	for (i = 0; i < blockSize;) {
+		if (((offset + i) % 4) || ((blockSize - i) < 4)) {	/* unaligned to 32 bit */
+			DB(mvOsPrintf("Flash: mvFlashBlockRd not aligned\n"));
+			pBlock[i] = mvFlash8Rd(pFlash, offset + i);
+			i++;
+		} else {	/* aligned to 32 bit */
+
+			temp = mvFlash32Rd(pFlash, offset + i);
+			/* to make sure we don't write to un aligned address */
+			for (j = 0; j < 4; j++) {
+				/* 0x44556677 -> [44][55][66][77] */
+				pBlock[i + j] = (MV_U8) ((temp >> (8 * (3 - j))) & FLASH_MASK_8BIT);
+			}
+			i += 4;
+		}
+	}
+
+	return i;
+}
+
+/*******************************************************************************
+* mvFlashSecLockSet - Lock/Unlock a Sector in the flash for Writing.
+*
+* DESCRIPTION:
+*       Lock/Unlock a Sector in the flash for Writing.
+*
+* INPUT:
+*       pFlash	- Flash identifier structure.
+*       secNum	- Sector Number.
+*       enable	- MV_TRUE for Lock MV_FALSE for un-lock.
+*
+* OUTPUT:
+*      None
+*
+* RETURN:
+*	MV_BAD_PARAM if pFlash is NULL,
+*       MV_OK if operation completed successfully,
+*	MV_FAIL otherwise
+*
+*******************************************************************************/
+MV_STATUS mvFlashSecLockSet(MV_FLASH_INFO *pFlash, MV_U32 secNum, MV_BOOL enable)
+{
+	MV_U32 status = MV_FAIL;
+
+	DB(mvOsPrintf("Flash: mvFlashSecLockSet\n"));
+	if ((NULL == pFlash) || (secNum > mvFlashNumOfSecsGet(pFlash)))
+		return MV_BAD_PARAM;
+
+	/* check if sector is locked */
+	if (enable == mvFlashSecLockGet(pFlash, secNum)) {
+		DB(mvOsPrintf("already un/locked\n"));
+		return MV_OK;
+	}
+
+	/* SW Lock */
+	if (mvFlashIsHwLock(pFlash) == MV_FALSE) {
+		pFlash->sector[secNum].protect = enable;
+		status = MV_OK;
+	} else {		/* HW Lock */
+
+		switch (mvFlashVenIdGet(pFlash)) {
+		case INTEL_MANUF:	/* INTEL / MT */
+			status = intelFlashSecLock(pFlash, secNum, enable);
+			break;
+		default:
+			mvOsPrintf("%s ERROR: No support for flash vendor id=0x%x\n",
+				   __func__, mvFlashVenIdGet(pFlash));
+			return MV_FAIL;
+		}
+		/* if completed successfully, updated SW structure */
+		if (MV_OK == status)
+			pFlash->sector[secNum].protect = enable;
+
+		/* reset the flash */
+		flashReset(pFlash);
+	}
+
+	return status;
+}
+
+/********************** statics APIs *******************************************/
+/*******************************************************************************
+* flashReset - Reset the Flash.
+* DESCRIPTION:
+*	Reset the flash (Inset it into read mode).
+*
+* INPUT:
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_FAIL - if flash Vendor isn't supported MV_OK otherwise.
+*
+*******************************************************************************/
+static MV_STATUS flashReset(MV_FLASH_INFO *pFlash)
+{
+	switch (mvFlashVenIdGet(pFlash)) {
+	case INTEL_MANUF:	/* INTEL/MT */
+		intelFlashReset(pFlash);
+		break;
+	case AMD_MANUF:
+	case STM_MANUF:
+	case SST_MANUF:
+		amdFlashReset(pFlash);
+		break;
+	default:
+		mvOsPrintf("Flash: ERROR mvFlashErase unsupported flash vendor\n");
+		return MV_FAIL;
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* flashStructGet - return flash structure information.
+*
+* DESCRIPTION:
+*       This function goes over the supported flash list and look for a flash
+*	with manufactor code = manu and id code = id if found it return the flash
+*	structure.
+*
+* INPUT:
+*       manu    - Flash Manufactor.
+*       id    	- Flash ID.
+*
+* OUTPUT:
+*       pFlash	- Flash structure.
+*
+* RETURN:
+*	MV_BAD_PARAM if pFlash is NULL,
+*       MV_OK if manufactor and id were found,
+*	MV_FAIL otherwise
+*
+*******************************************************************************/
+static MV_STATUS flashStructGet(MV_FLASH_INFO *pFlash, MV_U32 manu, MV_U32 id)
+{
+	MV_U32 i = 0;
+
+	if (NULL == pFlash)
+		return MV_BAD_PARAM;
+
+	DB(mvOsPrintf("Flash: flashStructGet manu 0x%x id 0x%x \n", manu, id));
+	/* while its not the last supported flash */
+	while ((supFlashAry[i].flashVen != LAST_FLASH) || (supFlashAry[i].flashId != LAST_FLASH)) {
+		/* if supported flash manufactor and Id equal to manu and id break */
+		if ((flashDataExt(pFlash, supFlashAry[i].flashVen) == manu) &&
+		    (flashDataExt(pFlash, supFlashAry[i].flashId) == id)) {
+			DB(mvOsPrintf("Flash: flashStructGet flash is supported.\n"));
+			pFlash->flashSpec = supFlashAry[i];
+			return MV_OK;
+		}
+		i++;
+	}
+
+	/* manu and id are not supported! */
+	DB(mvOsPrintf("Flash: flashStructGet flash is not supported.\n"));
+	return MV_FAIL;
+}
+
+/*******************************************************************************
+*  flashSecsInit - Init the flash sector array in pFlash.
+*
+* DESCRIPTION:
+*	Init the sector array based on the sector type.
+*
+* INPUT:
+*
+* OUTPUT:
+*       pFlash	- Flash sectors information.
+*
+* RETURN:
+*	MV_BAD_PARAM if pFlash or frag sector struct(if needed) are NULL,
+*	MV_OK otherwise
+*
+*******************************************************************************/
+static MV_STATUS flashSecsInit(MV_FLASH_INFO *pFlash)
+{
+	MV_U32 i, temp, base = 0;
+	MV_U32 restSecSize, initSize = 0;
+	MV_U32 *pSecFrag, numSecFrag, firstSec, lastSec, flashDevNum;
+
+	if (NULL == pFlash)
+		return MV_BAD_PARAM;
+
+	/* first Init the bottom or top sectors */
+	if (mvFlashSecTypeGet(pFlash) != REGULAR) {	/* BOTTOM or TOP */
+		/* init sectors fragments parameters */
+		numSecFrag = pFlash->flashSpec.secFragNum;
+		pSecFrag = pFlash->flashSpec.pSecSizeFragList;
+		if (NULL == pSecFrag) {
+			mvOsPrintf("Flash: flashSecsInit missing frag sector list.\n");
+			return MV_BAD_PARAM;
+		}
+
+		/* In case we got more then one flash in parallel then each             */
+		/* fragment size will be "duplicated"                                                           */
+		flashDevNum = mvFlashNumOfDevGet(pFlash);
+
+		/* caculate the size of each sector in the rest of the flash sector */
+		temp = 0;
+		for (i = 0; i < numSecFrag; i++)
+			temp += pSecFrag[i] * flashDevNum;
+		restSecSize = (mvFlashSizeGet(pFlash) - temp) / (mvFlashNumOfSecsGet(pFlash) - numSecFrag);
+
+		if (mvFlashSecTypeGet(pFlash) == TOP) {	/* TOP */
+			/* if TOP sec type the the last sector is fragmented */
+			DB(mvOsPrintf("FLASH: initFlashSecs TOP Sector Type \n"));
+			base = mvFlashSizeGet(pFlash) - restSecSize;
+			temp = mvFlashNumOfSecsGet(pFlash) - numSecFrag;
+
+			for (i = 0; i < numSecFrag; i++) {
+				pFlash->sector[temp + i].baseOffs = base;
+				pFlash->sector[temp + i].size = pSecFrag[(numSecFrag - 1) - i] * flashDevNum;
+				/* Init Protect feild */
+				if (pFlash->flashSpec.HwProtect == MV_FALSE) {	/* SW Protect */
+					pFlash->sector[i].protect = MV_FALSE;
+				} else {	/* HW protect */
+
+					pFlash->sector[i].protect = flashSecLockGet(pFlash, temp + i);
+				}
+				/*increment base and size of initialized sectors */
+				base += pSecFrag[(numSecFrag - 1) - i] * flashDevNum;
+				initSize += pSecFrag[(numSecFrag - 1) - i] * flashDevNum;
+			}
+			/* prepare for rest of sector init */
+			firstSec = 0;
+			lastSec = mvFlashNumOfSecsGet(pFlash) - numSecFrag;
+			base = 0;
+
+		} else if (mvFlashSecTypeGet(pFlash) == BOTTOM) {	/* BOTTOM */
+			/* if BOTTOM sec type the the first sector is fragmented */
+			DB(mvOsPrintf("FLASH: initFlashSecs BOTTOM Sector Type \n"));
+
+			for (i = 0; i < numSecFrag; i++) {
+				pFlash->sector[i].baseOffs = base;
+				pFlash->sector[i].size = pSecFrag[i] * flashDevNum;
+				/* Init Protect feild */
+				if (pFlash->flashSpec.HwProtect == MV_FALSE) {	/* SW Protect */
+					pFlash->sector[i].protect = MV_FALSE;
+				} else {	/* HW protect */
+
+					pFlash->sector[i].protect = flashSecLockGet(pFlash, i);
+				}
+				/*increment base and size of initialized sectors */
+				base += pSecFrag[i] * flashDevNum;
+				initSize += pSecFrag[i] * flashDevNum;
+			}
+			/* prepare for rest of sector init */
+			firstSec = numSecFrag;
+			lastSec = mvFlashNumOfSecsGet(pFlash);
+		} else {	/* unknown Type */
+
+			mvOsPrintf("FLASH: initFlashSecs Sector Type %d is unsupported\n.", pFlash->flashSpec.secType);
+			return MV_BAD_PARAM;
+		}
+
+	} else {		/* REGULAR */
+
+		DB(mvOsPrintf("FLASH: initFlashSecs REGULAR Sector Type \n"));
+		restSecSize = mvFlashSizeGet(pFlash) / mvFlashNumOfSecsGet(pFlash);
+		firstSec = 0;
+		lastSec = mvFlashNumOfSecsGet(pFlash);
+	}
+
+	/* init the rest of the sectors */
+	DB(mvOsPrintf("Flash: flashSecsInit main sector loop %d - %d \n", firstSec, lastSec));
+	for (i = firstSec; i < lastSec; i++) {
+		pFlash->sector[i].baseOffs = base;
+		pFlash->sector[i].size = restSecSize;
+		/* Init Protect feild */
+		if (pFlash->flashSpec.HwProtect == MV_FALSE) {	/* SW Protect */
+			pFlash->sector[i].protect = MV_FALSE;
+		} else {	/* HW protect */
+
+			pFlash->sector[i].protect = flashSecLockGet(pFlash, i);
+		}
+		/*increment base */
+		base += restSecSize;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* flashSecLockGet - Return a sector Lock Bit status.
+*
+* DESCRIPTION:
+*	Return a sector Lock Bit status.
+*
+*
+* INPUT:
+*       pFlash	- Flash structure.
+*       secNum 	- Sector Number.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_TRUE if lock is set
+*	MV_FALSE if lock isn't set
+*
+*******************************************************************************/
+static MV_BOOL flashSecLockGet(MV_FLASH_INFO *pFlash, MV_U32 secNum)
+{
+	MV_U32 status;
+
+	/* check if sector is locked */
+	if ((NULL == pFlash) || (secNum >= mvFlashNumOfSecsGet(pFlash)))
+		return MV_BAD_PARAM;
+
+	switch (mvFlashVenIdGet(pFlash)) {
+	case INTEL_MANUF:	/* INTEL / MT */
+		status = intelFlashSecLockGet(pFlash, secNum);
+		break;
+	default:
+		mvOsPrintf("Flash: ERROR flashSecLockGet unsupported vendor\n");
+		return MV_FAIL;
+	}
+	/* reset the flash */
+	flashReset(pFlash);
+
+	return status;
+
+}
+
+/*******************************************************************************
+* mvFlashProg - Prog busWidth Bits into the address offest in the flash.
+*
+* DESCRIPTION:
+*       This function writes busWidth data to a given flash offset.
+*
+* INPUT:
+*       pFlash - Flash identifier structure (flash cockie).
+*       offset - Offset from flash base address.
+*       data   - 32bit data to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	MV_BAD_PARAM if one of the inputs values is illegal,
+*       MV_OK if program completed successfully,
+*	MV_FAIL otherwise (e.g. sector protected).
+*
+*******************************************************************************/
+static MV_STATUS mvFlashProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data)
+{
+	MV_U32 status;
+
+	switch (mvFlashVenIdGet(pFlash)) {
+	case INTEL_MANUF:	/* INTEL / MT */
+		status = intelFlashProg(pFlash, offset, data);
+		break;
+	case AMD_MANUF:
+	case STM_MANUF:
+	case SST_MANUF:
+		status = amdFlashProg(pFlash, offset, data);
+		break;
+	default:
+		mvOsPrintf("Flash: ERROR mvFlashProg unsupported flash vendor\n");
+		return MV_FAIL;
+	}
+
+	return status;
+
+}
+
+/*******************************************************************************
+* flashHwBufferProg - Prog flash via hw flash hw buffer
+*
+* DESCRIPTION:
+*       This function writes to a given flash offset using flash hw buffer.
+*
+* INPUT:
+*       pFlash - Flash identifier structure (flash cockie).
+*       offset - Offset from flash base address.
+*       data   - 32bit data to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	MV_BAD_PARAM if one of the inputs values is illegal,
+*   MV_OK if program completed successfully,
+*	MV_FAIL otherwise (e.g. sector protected).
+*
+*******************************************************************************/
+static MV_STATUS flashHwBufferProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 byteCount, MV_U8 *pData)
+{
+	MV_U32 status;
+
+	switch (mvFlashVenIdGet(pFlash)) {
+	case INTEL_MANUF:	/* INTEL / MT */
+		status = intelFlashHwBufferProg(pFlash, offset, byteCount, pData);
+		break;
+	default:
+		mvOsPrintf("Flash: ERROR flashHwBufferProg unsupported flash vendor\n");
+		return MV_FAIL;
+	}
+
+	return status;
+}
+
+/*******************************************************************************
+* flashGetHwBuffSize - get supported flash write buffer size.
+* DESCRIPTION:
+*	Returns supported flash write buffer size.
+*
+* INPUT:
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_U32 - supported buffer size
+*
+*******************************************************************************/
+static MV_U32 flashGetHwBuffSize(MV_FLASH_INFO *pFlash)
+{
+
+	switch (mvFlashVenIdGet(pFlash)) {
+	case INTEL_MANUF:	/* INTEL / MT */
+		return intelFlashGetHwBuffSize(pFlash);
+		break;
+	default:
+		return 0;
+	}
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvFlash.h b/arch/arm/plat-feroceon/mv_hal/norflash/mvFlash.h
new file mode 100755
index 0000000..be29adb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvFlash.h
@@ -0,0 +1,96 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvFlashH
+#define __INCmvFlashH
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvFlashCom.h"
+#include "mvIntelFlash.h"
+#include "mvAmdFlash.h"
+
+/** APIs **/
+/* Init */
+MV_U32 mvFlashInit(MV_FLASH_INFO *pFlash);
+/* Erase */
+MV_STATUS mvFlashErase(MV_FLASH_INFO *pFlash);
+MV_BOOL flashIsSecErased(MV_FLASH_INFO *pFlash, MV_U32 secNum);
+MV_STATUS mvFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 sectorNum);
+/* write */
+MV_STATUS mvFlash32Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data);
+MV_STATUS mvFlash16Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U16 sdata);
+MV_STATUS mvFlash8Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U8 cdata);
+MV_U32 mvFlashBlockWr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock);
+MV_U32 mvFlashBlockUnbufWr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock);
+/* read */
+MV_U32 mvFlash32Rd(MV_FLASH_INFO *pFlash, MV_U32 offset);
+MV_U16 mvFlash16Rd(MV_FLASH_INFO *pFlash, MV_U32 offset);
+MV_U8 mvFlash8Rd(MV_FLASH_INFO *pFlash, MV_U32 offset);
+MV_U32 mvFlashBlockRd(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock);
+/* protection */
+MV_STATUS mvFlashSecLockSet(MV_FLASH_INFO *pFlash, MV_U32 secNum, MV_BOOL enable);
+
+#endif /* __INCmvFlashH */
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvFlashCom.c b/arch/arm/plat-feroceon/mv_hal/norflash/mvFlashCom.c
new file mode 100755
index 0000000..d36ae1c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvFlashCom.c
@@ -0,0 +1,649 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvFlashCom.h"
+#include "mvIntelFlash.h"
+#include "mvAmdFlash.h"
+
+#undef MV_DEBUG
+
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+static MV_VOID sizePrint(MV_U32 size, MV_U8 *s);
+
+/*******************************************************************************
+* mvFlashInWhichSec - Return which Sector rap the offset address.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pFlash	- Flash identifier structure.
+*       offset	- offset address.
+*
+* OUTPUT:
+*      None
+*
+* RETURN:
+*       MV_U32	- The Sector Number that the offset sits in.
+*	BAD_SEC_NUM if not found.
+*
+*******************************************************************************/
+MV_U32 mvFlashInWhichSec(MV_FLASH_INFO *pFlash, MV_U32 offset)
+{
+	MV_U32 secNum;
+	if (NULL == pFlash)
+		return 0;
+
+	for (secNum = 0; secNum < mvFlashNumOfSecsGet(pFlash); secNum++) {
+		if ((offset >= mvFlashSecOffsGet(pFlash, secNum)) &&
+		    (offset < mvFlashSecOffsGet(pFlash, secNum) + mvFlashSecSizeGet(pFlash, secNum))) {
+			return secNum;
+		}
+	}
+	/* return illegal sector Number */
+	return FLASH_BAD_SEC_NUM;
+}
+
+/**************************************************/
+/* get information from the MV_FLASH_INFO struct  */
+/**************************************************/
+/* get the Number of Device which sits in parallel on the bus */
+MV_U32 mvFlashNumOfDevGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+	if (mvFlashBusWidthGet(pFlash) >= mvFlashDevWidthGet(pFlash))
+		return mvFlashBusWidthGet(pFlash) / mvFlashDevWidthGet(pFlash);
+	return 1;
+}
+
+/* get the Flash Lock type HW/SW */
+MV_BOOL mvFlashIsHwLock(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return MV_FALSE;
+
+	return pFlash->flashSpec.HwProtect;
+}
+
+/* get the lock status of a sector in the flash */
+MV_BOOL mvFlashSecLockGet(MV_FLASH_INFO *pFlash, MV_U32 secNum)
+{
+	if ((NULL == pFlash) || (secNum > mvFlashNumOfSecsGet(pFlash)))
+		return MV_FALSE;
+
+	return pFlash->sector[secNum].protect;
+}
+
+/* get the size of a sector in the flash */
+MV_U32 mvFlashSecSizeGet(MV_FLASH_INFO *pFlash, MV_U32 secNum)
+{
+	if ((NULL == pFlash) || (secNum > mvFlashNumOfSecsGet(pFlash)))
+		return 0;
+
+	return pFlash->sector[secNum].size;
+}
+
+/* get the num of sectors in the flash */
+MV_U32 mvFlashNumOfSecsGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return pFlash->flashSpec.sectorNum;
+}
+
+/* get the flash size */
+MV_U32 mvFlashSizeGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return pFlash->flashSpec.size * mvFlashNumOfDevGet(pFlash);
+}
+
+/* get the sector offset */
+MV_U32 mvFlashSecOffsGet(MV_FLASH_INFO *pFlash, MV_U32 secNum)
+{
+	if ((NULL == pFlash) || (secNum > mvFlashNumOfSecsGet(pFlash)))
+		return 0;
+
+	return pFlash->sector[secNum].baseOffs;
+}
+
+/* get the sector types TOP/BOT/REG */
+FLASH_SEC_TYPE mvFlashSecTypeGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return pFlash->flashSpec.secType;
+}
+
+/* get the flash Vendor ID */
+MV_U32 mvFlashVenIdGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return pFlash->flashSpec.flashVen;
+}
+
+/* get the flash device id */
+MV_U32 mvFlashDevIdGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return pFlash->flashSpec.flashId;
+}
+
+/* get the flash base address */
+MV_U32 mvFlashBaseAddrGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return pFlash->baseAddr;
+}
+
+/* get the flash bus width */
+MV_U32 mvFlashBusWidthGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return pFlash->busWidth;
+}
+
+/* get the flash device width */
+MV_U32 mvFlashDevWidthGet(MV_FLASH_INFO *pFlash)
+{
+	if (NULL == pFlash)
+		return 0;
+
+	return pFlash->devWidth;
+}
+
+/*******************************************************************************
+* flashDataExt - Extend Data.
+* DESCRIPTION:
+*	Should be used only for FLASH CFI command sequence.
+*
+* 	Prepare the Data according to the Flash Width and Bus Width.
+* 	If flash width = 2 and bus width = 1 data = 0x55 -> data = 0x55
+* 	If flash width = 2 and bus width = 4 data = 0x55 -> data = 0x550055
+* 	If flash width = 1 and bus width = 4 data = 0x55 -> data = 0x55555555
+*
+* INPUT:
+*       data    - Data to be expended.
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_U32 	- Data after extension.
+*	OxFFFFFFFF if pFlash is Null
+*
+*******************************************************************************/
+MV_U32 flashDataExt(MV_FLASH_INFO *pFlash, MV_U32 data)
+{
+	MV_U32 i;
+	if (NULL == pFlash)
+		return 0xFFFFFFFF;
+
+	for (i = 0; i < pFlash->busWidth; i += pFlash->devWidth)
+		data |= data << 8 * i;
+	return data;
+}
+
+/******************************************************************************
+* flashAddrExt - Extend Addr.
+* DESCRIPTION:
+*	Should be used only for FLASH CFI command sequence.
+*
+* 	Prepare the Addr according to the Flash width and the bus width,
+* 	and add the sector offset.
+*	If flash width = 2 and bus width = 1 then it means we are using 16 Bit
+* 	flash in 8 Bit mode, we should make sure that we shift the addr in 1 bit
+* 	since in 16 Bit flash A0 isn't connected. and A1 of the MV dev address will
+* 	go to A1 of the Flash.
+* 	If flash width = 2 and bus width = 4 then it means we are using 2 16 Bit
+* 	flash, (for the 16 Bit flash A0 isn't connected) and since when we refer to
+* 	address 0x4 we actually want to refer to 0x2 of each device, then we will
+* 	connect A2 of the MV Dev addres to A1 of the flash.
+*
+* INPUT:
+*       addr    - Addr to be expended.
+*	pFlash	- flash information.
+*	secNum 	- Sector Number.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_U32 	- Data after extension.
+*	0 if pFlash is Null.
+*
+*******************************************************************************/
+MV_U32 flashAddrExt(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 secNum)
+{
+	MV_U32 shift;
+	if (NULL == pFlash)
+		return 0;
+
+	shift = (pFlash->busWidth > pFlash->devWidth) ? pFlash->busWidth : pFlash->devWidth;
+	addr = addr * shift;
+
+	/* Add flash sector Offset. */
+	addr += (mvFlashSecOffsGet(pFlash, secNum) + mvFlashBaseAddrGet(pFlash));
+
+	return addr;
+}
+
+/*******************************************************************************
+* flashCmdSet - Write converted data to the flash converted address+sector base.
+*
+* DESCRIPTION:
+*		Convert data based on the bus width and the flash device width
+*		and write it to secoffset + converted address.
+*		Should be used only for FLASH command sequence.
+*
+* INPUT:
+*       addr    - Address offset.
+*	secNum	- In which sector the address is sitting.
+*       data    - Data to be written.
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	None
+*
+*******************************************************************************/
+MV_VOID flashCmdSet(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 secNum, MV_U32 data)
+{
+	if (NULL == pFlash)
+		return;
+
+	/* prepare the Data according to the Flash Width and Bus Width.                 */
+	data = flashDataExt(pFlash, data);
+	addr = flashAddrExt(pFlash, addr, secNum);
+
+	flashBusWidthWr(pFlash, addr, data);
+
+	return;
+}
+
+/*******************************************************************************
+* flashBusWidthRd - read BusWidth Bits from address.
+*
+* DESCRIPTION:
+*		read BusWidth Bits from address. Note that access to Flash registers
+*		is always in LE	mode as the Flash registers are in LE mode.
+*
+* INPUT:
+*       addr    - Address offset.
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_U32 - contain the Bus Width Bits read from the address.
+*
+*******************************************************************************/
+MV_U32 flashBusWidthRd(MV_FLASH_INFO *pFlash, MV_U32 addr)
+{
+	MV_U32 val;
+
+	switch (pFlash->busWidth) {
+	case 1:
+		val = (MV_U32) MV_FL_8_READ(addr);
+		break;
+	case 2:
+		val = (MV_U32) MV_FL_16_READ(addr);
+		break;
+	case 4:
+		val = MV_FL_32_READ(addr);
+		break;
+	default:
+		mvOsPrintf("%s ERROR: Bus Width %d Bytes isn't supported.\n", __func__, pFlash->busWidth);
+		return 0;
+	}
+	/* mvOsPrintf("Addr = 0x%x, val = 0x%x, width %d\n", addr, val, pFlash->busWidth); */
+
+	return val;
+}
+
+/*******************************************************************************
+* flashBusWidthWr - write BusWidth Bits from address.
+*
+* DESCRIPTION:
+*		write BusWidth Bits to address. Note that access to Flash registers
+*		is always in LE	mode as the Flash registers are in LE mode.
+*
+* INPUT:
+*       addr    - Address offset.
+*	data	- data to be written.
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	None
+*
+*******************************************************************************/
+MV_VOID flashBusWidthWr(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 data)
+{
+	/* mvOsPrintf("Addr = 0x%x, data = 0x%x, width %d\n", addr, data, pFlash->busWidth); */
+	switch (pFlash->busWidth) {
+	case 1:
+		MV_FL_8_WRITE(addr, (MV_U8) data);
+		break;
+	case 2:
+		MV_FL_16_WRITE(addr, (MV_U16) data);
+		break;
+	case 4:
+		MV_FL_32_WRITE(addr, data);
+		break;
+	default:
+		mvOsPrintf("%s ERROR: Bus Width %d Bytes isn't supported.\n", __func__, pFlash->busWidth);
+		return;
+	}
+
+	return;
+}
+
+/*******************************************************************************
+* flashBusWidthDataWr - write BusWidth Bits of data from address.
+*
+* DESCRIPTION:
+*		This function is used to perform data write to Flash, not like
+*		flashBusWidthWr which is used for commands.
+*
+* INPUT:
+*   addr    - Address offset.
+*	data	- data to be written.
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	None
+*
+*******************************************************************************/
+MV_VOID flashBusWidthDataWr(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 data)
+{
+	/*mvOsPrintf("Addr = 0x%x, data = 0x%x, width %d\n", addr, data, pFlash->busWidth); */
+	switch (pFlash->busWidth) {
+	case 1:
+		MV_FL_8_DATA_WRITE(addr, (MV_U8) data);
+		break;
+	case 2:
+		MV_FL_16_DATA_WRITE(addr, (MV_U16) data);
+		break;
+	case 4:
+		MV_FL_32_DATA_WRITE(addr, data);
+		break;
+	default:
+		mvOsPrintf("%s ERROR: Bus Width %d Bytes isn't supported.\n", __func__, pFlash->busWidth);
+		return;
+	}
+
+	return;
+}
+
+/*******************************************************************************
+*  flashPrint - Print flash information structure.
+*
+* DESCRIPTION:
+*	Prints all the feilds in the flash info structure.
+*
+* INPUT:
+*       pFlash	- Flash information.
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*	None
+*
+*******************************************************************************/
+MV_VOID flashPrint(MV_FLASH_INFO *pFlash)
+{
+	MV_U32 i;
+
+	if ((NULL == pFlash) || (mvFlashVenIdGet(pFlash) == 0)) {
+		mvOsOutput("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (mvFlashVenIdGet(pFlash)) {
+	case STM_MANUF:
+		mvOsOutput("STM ");
+		break;
+	case AMD_MANUF:
+		mvOsOutput("AMD ");
+		break;
+	case FUJ_MANUF:
+		mvOsOutput("FUJITSU ");
+		break;
+	case INTEL_MANUF:
+		mvOsOutput("INTEL ");
+		break;
+	case SST_MANUF:
+		mvOsOutput("SST ");
+		break;
+	case MX_MANUF:
+		mvOsOutput("MX ");
+		break;
+	default:
+		mvOsOutput("Unknown Vendor 0x%x", mvFlashVenIdGet(pFlash));
+		break;
+	}
+
+	switch (mvFlashDevIdGet(pFlash)) {
+	case AMD_FID_LV040B:
+		mvOsOutput("AM29LV040B (4 Mbit, bottom boot sect)");
+		break;
+	case AMD_FID_LV400B:
+		mvOsOutput("AM29LV400B (4 Mbit, bottom boot sect)");
+		break;
+	case AMD_FID_LV400T:
+		mvOsOutput("AM29LV400T (4 Mbit, top boot sector)");
+		break;
+	case AMD_FID_LV800B:
+		mvOsOutput("AM29LV800B (8 Mbit, bottom boot sect)");
+		break;
+	case AMD_FID_LV800T:
+		mvOsOutput("AM29LV800T (8 Mbit, top boot sector)");
+		break;
+	case AMD_FID_LV160B:
+		mvOsOutput("AM29LV160B (16 Mbit, bottom boot sect)");
+		break;
+	case AMD_FID_LV160T:
+		mvOsOutput("AM29LV160T (16 Mbit, top boot sector)");
+		break;
+	case AMD_FID_LV320B:
+		mvOsOutput("AM29LV320B (32 Mbit, bottom boot sect)");
+		break;
+	case AMD_FID_LV320T:
+		mvOsOutput("AM29LV320T (32 Mbit, top boot sector)");
+		break;
+	case AMD_S29GL128N:
+		mvOsOutput("SPANSION S29GL128N (128 Mbit) - AMD MirrorBit-compat");
+		break;
+	case STM_FID_29W040B:
+		mvOsOutput("M29W040B (4Mbit = 512K x 8) ");
+		break;
+	case INTEL_FID_28F320J3A:
+		mvOsOutput("28F320J3A (32 Mbit)");
+		break;
+	case INTEL_FID_28F640J3A:
+		mvOsOutput("28F640J3A (64 Mbit)");
+		break;
+	case INTEL_FID_28F128J3A:
+		mvOsOutput("28F128J3A (128 Mbit)");
+		break;
+	case INTEL_FID_28F128P30T:
+		mvOsOutput("28F128P30 TOP (128 Mbit)");
+		break;
+	case INTEL_FID_28F128P30B:
+		mvOsOutput("28F128P30 BOTTOM (128 Mbit)");
+		break;
+	case INTEL_FID_28F256P30T:
+		mvOsOutput("28F256P30 TOP (256 Mbit)");
+		break;
+#if defined(DB_88F1281)
+	case INTEL_FID_28F256P30B:
+		mvOsOutput("28F256P30 BOTTOM (128 Mbit)");
+		break;
+#else
+	case INTEL_FID_28F256P30B:
+		mvOsOutput("28F256P30 BOTTOM (256 Mbit)");
+		break;
+#endif
+	case SST_39VF_020:
+		mvOsOutput("SST39VF020 (2 Mbit)");
+		break;
+	default:
+		mvOsOutput("Unknown Chip Type id 0x%x", mvFlashDevIdGet(pFlash));
+		break;
+	}
+	if (mvFlashNumOfDevGet(pFlash) > 1)
+		mvOsOutput(" X %d", mvFlashNumOfDevGet(pFlash));
+
+	mvOsOutput("\nSize: ");
+	sizePrint(mvFlashSizeGet(pFlash), (MV_U8 *) " in ");
+	mvOsOutput("%d Sectors\n", mvFlashNumOfSecsGet(pFlash));
+	mvOsOutput("Bus Width: %dbit, device Width: %dbit, type: ",
+		   (8 * mvFlashBusWidthGet(pFlash)), (8 * mvFlashDevWidthGet(pFlash)));
+
+	switch (mvFlashSecTypeGet(pFlash)) {
+	case TOP:
+		mvOsOutput("TOP");
+		break;
+	case BOTTOM:
+		mvOsOutput("BOTTOM");
+		break;
+	case REGULAR:
+		mvOsOutput("REGULAR");
+		break;
+	default:
+		mvOsOutput("Unknown Type");
+		break;
+	}
+	mvOsOutput(".\n");
+
+	mvOsOutput("  Sector Start Addresses:");
+	for (i = 0; i < mvFlashNumOfSecsGet(pFlash); ++i) {
+		if ((i % 5) == 0)
+			mvOsOutput("\n   ");
+		mvOsOutput(" %08lX%s",
+			   (mvFlashSecOffsGet(pFlash, i) + mvFlashBaseAddrGet(pFlash)),
+			   mvFlashSecLockGet(pFlash, i) ? " (RO)" : "     ");
+	}
+	mvOsOutput("\n");
+
+	return;
+}
+
+/***************************************************************************
+* print sizes as "xxx kB", "xxx.y kB", "xxx MB" or "xxx.y MB" as needed;
+* allow for optional trailing string (like "\n")
+***************************************************************************/
+static MV_VOID sizePrint(MV_U32 size, MV_U8 *s)
+{
+	MV_U32 m, n;
+	MV_U32 d = 1 << 20;	/* 1 MB */
+	MV_U8 c = 'M';
+
+	if (size < d) {		/* print in kB */
+		c = 'k';
+		d = 1 << 10;
+	}
+
+	n = size / d;
+
+	m = (10 * (size - (n * d)) + (d / 2)) / d;
+
+	if (m >= 10) {
+		m -= 10;
+		n += 1;
+	}
+
+	mvOsOutput("%2d", n);
+	if (m)
+		mvOsOutput(".%d", m);
+	mvOsOutput(" %cB%s", c, s);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvFlashCom.h b/arch/arm/plat-feroceon/mv_hal/norflash/mvFlashCom.h
new file mode 100755
index 0000000..42af6d8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvFlashCom.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvFlashComH
+#define __INCmvFlashComH
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+/* Vendor Ids */
+#define AMD_MANUF	0x01	/* AMD     manuf. ID in D23..D16, D7..D0 */
+#define FUJ_MANUF	0x04	/* FUJITSU manuf. ID in D23..D16, D7..D0 */
+#define ATM_MANUF	0x1F	/* ATMEL */
+#define STM_MANUF	0x20	/* STM (Thomson) manuf. ID in D23.. -"- */
+#define SST_MANUF	0xBF	/* SST     manuf. ID in D23..D16, D7..D0 */
+#define MT_MANUF	0x89	/* MT      manuf. ID in D23..D16, D7..D0 */
+#define INTEL_MANUF	0x89	/* INTEL   manuf. ID in D23..D16, D7..D0 */
+#define INTEL_ALT_MANUF	0xB0	/* alternate INTEL namufacturer ID      */
+#define MX_MANUF	0xC2	/* MXIC    manuf. ID in D23..D16, D7..D0 */
+#define TOSH_MANUF	0x98	/* TOSHIBA manuf. ID in D23..D16, D7..D0 */
+
+#define MAX_SECTOR_NUM  300
+
+#define FLASH_BAD_SEC_NUM 	0xFFFFFFFF
+#define FLASH_WR_ERASED 	0xFFFFFFFF
+#define FLASH_MASK_16BIT 	0xFFFF
+#define FLASH_MASK_8BIT 	0xFF
+/* typedefs */
+
+/* This structure describes a flash sector                  */
+typedef struct _mvFlashSector {
+	MV_U32 baseOffs;	/* Sector base offset related to flash base.    */
+	MV_U32 size;		/* sector size in bytes                         */
+	MV_BOOL protect;	/* Sector write protect indicator               */
+} MV_FLASH_SECTOR;
+
+/* This structures describes a flash Sectors structure type */
+typedef enum flashSecType {
+	REGULAR,
+	BOTTOM,
+	TOP
+} FLASH_SEC_TYPE;
+
+typedef struct flashStruct {
+	MV_U32 flashVen;	/* AMD/Intel/...    */
+	MV_U32 flashId;		/* Combined device & vendor ID                               */
+	MV_U32 size;		/* Total Flash size in bytes                             */
+	MV_U32 sectorNum;	/* Flash total sector number                             */
+	FLASH_SEC_TYPE secType;	/* Sector structure type                                 */
+	MV_U32 secFragNum;	/* In case B/T flash then this is the Number */
+	/* of Sector defined in the Frag list.               */
+	MV_U32 *pSecSizeFragList;	/* a list of the sectors' sizes in the */
+	/* B/T sector part.                                                  */
+	MV_BOOL HwProtect;	/* HW protection is supported                                */
+	MV_U32 HwBuffLen;	/* support for hw buffering (0 - not,        */
+	/* > 0 - hw buff length).                    */
+} FLASH_STRUCT;
+
+/* This struct describes a Flash device     */
+typedef struct _mvFlashInfo {
+	FLASH_STRUCT flashSpec;
+	MV_U32 baseAddr;	/* Flash base address           */
+	MV_FLASH_SECTOR sector[MAX_SECTOR_NUM];	/* Flash sector list            */
+	MV_U32 busWidth;	/* Width of the Flash bus       */
+	MV_U32 devWidth;	/* Width of single Flash device */
+
+} MV_FLASH_INFO;
+
+/* get info */
+MV_U32 mvFlashNumOfDevGet(MV_FLASH_INFO *pFlash);
+MV_BOOL mvFlashIsHwLock(MV_FLASH_INFO *pFlash);
+MV_BOOL mvFlashSecLockGet(MV_FLASH_INFO *pFlash, MV_U32 secNum);
+MV_U32 mvFlashInWhichSec(MV_FLASH_INFO *pFlash, MV_U32 offset);
+MV_U32 mvFlashSecSizeGet(MV_FLASH_INFO *pFlash, MV_U32 sectorNumber);
+MV_U32 mvFlashNumOfSecsGet(MV_FLASH_INFO *pFlash);
+MV_U32 mvFlashSizeGet(MV_FLASH_INFO *pFlash);
+MV_U32 mvFlashSecOffsGet(MV_FLASH_INFO *pFlash, MV_U32 sectorNum);
+MV_U32 mvFlashVenIdGet(MV_FLASH_INFO *pFlash);
+MV_U32 mvFlashDevIdGet(MV_FLASH_INFO *pFlash);
+MV_U32 mvFlashBaseAddrGet(MV_FLASH_INFO *pFlash);
+MV_U32 mvFlashBusWidthGet(MV_FLASH_INFO *pFlash);
+MV_U32 mvFlashDevWidthGet(MV_FLASH_INFO *pFlash);
+FLASH_SEC_TYPE mvFlashSecTypeGet(MV_FLASH_INFO *pFlash);
+
+/* flash Utils */
+MV_U32 flashDataExt(MV_FLASH_INFO *pFlash, MV_U32 data);
+MV_U32 flashAddrExt(MV_FLASH_INFO *pFlash, MV_U32 data, MV_U32 secNum);
+MV_VOID flashCmdSet(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 secNum, MV_U32 data);
+MV_VOID flashPrint(MV_FLASH_INFO *pFlash);
+MV_VOID flashBusWidthWr(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 data);
+MV_VOID flashBusWidthDataWr(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 data);
+MV_U32 flashBusWidthRd(MV_FLASH_INFO *pFlash, MV_U32 addr);
+
+#endif /* __INCmvFlashComH */
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvIntelFlash.c b/arch/arm/plat-feroceon/mv_hal/norflash/mvIntelFlash.c
new file mode 100755
index 0000000..b6ad432
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvIntelFlash.c
@@ -0,0 +1,476 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvFlash.h"
+
+#undef MV_DEBUG
+
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+static MV_STATUS intelFlashStsGet(MV_FLASH_INFO *pFlash, MV_U32 sec, MV_BOOL enableReadCommand, MV_U32 *flashStatus);
+static MV_VOID intelFlashStatusClr(MV_FLASH_INFO *pFlash);
+
+/*******************************************************************************
+* reset the flash
+*******************************************************************************/
+MV_VOID intelFlashReset(MV_FLASH_INFO *pFlash)
+{
+	flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_RST);
+	return;
+}
+
+/*******************************************************************************
+* intelFlashSecErase - Erase a sector.
+*
+* DESCRIPTION:
+*	Erase a Flash sector.
+*
+* INPUT:
+*       secNum	- sector Number.
+*	pFlash	- flash information.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*       MV_OK if program completed successfully,
+*	MV_TIMEOUT if timeout reached,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS intelFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 secNum)
+{
+	MV_U32 i, status, flashStatus;
+
+	DB(mvOsPrintf("Flash: intelFlashSecErase\n"));
+
+	/* clear status */
+	intelFlashStatusClr(pFlash);
+
+	/* erase sequence */
+	flashCmdSet(pFlash, 0, secNum, INTEL_CHIP_CMD_ERASE1);
+	flashCmdSet(pFlash, 0, secNum, INTEL_CHIP_CMD_ERASE2);
+
+	/* wait for erase to complete */
+	for (i = 0; i < INTEL_EARASE_MILI_TIMEOUT; i++) {
+		mvOsDelay(1);
+		status = intelFlashStsGet(pFlash, 0, MV_TRUE, &flashStatus);
+		if (MV_NOT_READY != status)
+			return status;
+	}
+	mvOsPrintf("Flash: ERROR intelFlashSecErase timeout \n");
+
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* intelFlashProg - Prog busWidth Bits into the address offest in the flash.
+*
+* DESCRIPTION:
+*       This function writes busWidth data to a given flash offset.
+*
+* INPUT:
+*       pFlash - Flash identifier structure (flash cockie).
+*       offset - Offset from flash base address.
+*       data   - 32bit data to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK if program completed successfully,
+*	MV_TIMEOUT if timeout reached,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS intelFlashProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data)
+{
+	MV_U32 i, status, flashStatus;
+
+	DB(mvOsPrintf("Flash: mvIntelFlashWr\n"));
+
+	/* clear status */
+	intelFlashStatusClr(pFlash);
+
+	/* write sequence */
+	flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_PROG);
+	flashBusWidthDataWr(pFlash, offset + mvFlashBaseAddrGet(pFlash), data);
+
+	/* wait for write to complete */
+	for (i = 0; i < INTEL_PROG_TIMEOUT; i++) {
+		status = intelFlashStsGet(pFlash, 0, MV_TRUE, &flashStatus);
+		if (MV_NOT_READY != status)
+			return status;
+	}
+	mvOsPrintf("Flash: ERROR intelFlashSecErase timeout \n");
+
+	return MV_TIMEOUT;
+}
+
+MV_U32 intelFlashGetHwBuffSize(MV_FLASH_INFO *pFlash)
+{
+	MV_U32 buffSize;
+
+	buffSize = mvFlashNumOfDevGet(pFlash) * pFlash->flashSpec.HwBuffLen;
+	return buffSize;
+}
+
+/*******************************************************************************
+* intelFlashBufferProg - Prog hw buff into the address offest in the flash.
+*
+* DESCRIPTION:
+*       This function writes busWidth data to a given flash offset.
+*
+* INPUT:
+*       pFlash - Flash identifier structure (flash cockie).
+*       offset - Offset from flash base address.
+*       pData  - buffer (32 byte) data to be written to flash.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*   MV_OK if program completed successfully,
+*   MV_BAD_PARAM illegal param
+*	MV_TIMEOUT if timeout reached,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS intelFlashHwBufferProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 byteCount, MV_U8 *pData)
+{
+	MV_U32 i, status, flashStatus;
+	MV_U32 buffSize, sec, wordCount, busWidth;
+	MV_U32 offInBuff, absOffInFlash;
+	MV_U32 data, j;
+
+	DB(mvOsPrintf("Flash: intelFlashBufferProg\n"));
+	buffSize = (intelFlashGetHwBuffSize(pFlash));
+	if (buffSize == 0)
+		return MV_BAD_PARAM;
+
+	if (0 != (byteCount % buffSize))
+		return MV_BAD_PARAM;
+
+	/* has to be aligned */
+	if ((offset % buffSize) != 0)
+		return MV_BAD_PARAM;
+#ifndef CONFIG_MARVELL
+	if (pData == NULL)
+		return MV_BAD_PARAM;
+#endif
+
+	busWidth = mvFlashBusWidthGet(pFlash);
+	wordCount = (pFlash->flashSpec.HwBuffLen / mvFlashDevWidthGet(pFlash));
+	absOffInFlash = mvFlashBaseAddrGet(pFlash) + offset;
+	offInBuff = 0;
+
+	/* clear status */
+	intelFlashStatusClr(pFlash);
+
+	do {
+
+		/* Start the 'write to buffer' sequence */
+		sec = mvFlashInWhichSec(pFlash, offset);
+
+		i = 0;
+		do {
+			flashCmdSet(pFlash, 0, sec, INTEL_CHIP_CMD_WR_BUF);
+
+			status = intelFlashStsGet(pFlash, sec, MV_FALSE, &flashStatus);
+
+			if ((i++ > INTEL_PROG_TIMEOUT) && (status != MV_OK)) {
+				DB(printf("intelFlashHwBufferProg1: Timeout:offset = 0x%x flashStatus =0x%x\n",
+					  offset, flashStatus));
+				return status;
+			}
+
+		} while (status != MV_OK);
+
+		/* write num of words to write minus 1 */
+		flashCmdSet(pFlash, 0, sec, wordCount - 1);
+
+		for (i = 0; i < wordCount * mvFlashNumOfDevGet(pFlash); i += mvFlashNumOfDevGet(pFlash)) {
+			data = 0;
+			switch (busWidth) {
+			case 4:
+				for (j = 0; j < 4; j++) {
+					/* [44][55][66][77] -> 0x44556677  */
+					data |= (pData[offInBuff + j] & FLASH_MASK_8BIT) << (8 * (3 - j));
+				}
+				data = MV_32BIT_BE(data);
+				break;
+			case 2:
+				for (j = 0; j < 2; j++) {
+					/* [44][55] -> 0x4455  */
+					data |= (pData[offInBuff + j] & FLASH_MASK_8BIT) << (8 * (1 - j));
+				}
+				data = MV_16BIT_BE(data);
+				break;
+			case 1:
+				data = *(MV_U8 *) (((MV_U32) pData) + offInBuff);
+				break;
+			}
+			flashBusWidthDataWr(pFlash, absOffInFlash, data);
+
+			offInBuff += busWidth;
+			absOffInFlash += busWidth;
+		}
+
+		flashCmdSet(pFlash, 0, sec, INTEL_CHIP_CMD_CONFIRM_BUF);
+
+		/* check status  */
+		for (i = 0; i < INTEL_PROG_TIMEOUT; i++) {
+			status = intelFlashStsGet(pFlash, sec, MV_FALSE, &flashStatus);
+			if (status == MV_OK)
+				break;
+		}
+
+		if (status != MV_OK)
+			break;
+
+		byteCount -= buffSize;
+	} while (byteCount);
+
+	if (status != MV_OK) {
+
+		DB(printf("intelFlashHwBufferProg2: Timeout:offset = 0x%x flashStatus =0x%x\n", offset, flashStatus));
+
+		return status;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* intelSecLockGet - Return a sector Lock Bit status.
+*
+* DESCRIPTION:
+*	Return a sector Lock Bit status.
+*
+*
+* INPUT:
+*       pFlash	- Flash structure.
+*       secNum 	- Sector Number.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       MV_TRUE if lock is set
+*	MV_FALSE if lock isn't set
+*
+*******************************************************************************/
+MV_BOOL intelFlashSecLockGet(MV_FLASH_INFO *pFlash, MV_U32 secNum)
+{
+	MV_U32 status;
+
+	DB(mvOsPrintf("Flash: intelSecLockGet sector %d\n", secNum));
+
+	/* clear status */
+	intelFlashStatusClr(pFlash);
+
+	/* Some Micron flashes don't use A0 address for Identifier and
+	   Lock information, so in order to read Identifier and lock information
+	   properly we will do the following workarround:
+	   If our device width is 1 (x8) then if address 0 equal to address 1
+	   and address 2 equal to address 3 ,then we have this case (A0 is not used)
+	   and then we will issue the address without A0 to read the Identifier and
+	   lock information properly */
+
+	/* read Query sequence */
+	flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_RD_QUERY);
+
+	if ((pFlash->devWidth == 1) &&
+	    ((flashBusWidthRd(pFlash, flashAddrExt(pFlash, 0, 0)) ==
+	      flashBusWidthRd(pFlash, flashAddrExt(pFlash, 1, 0))) &&
+	     (flashBusWidthRd(pFlash, flashAddrExt(pFlash, 2, 0)) ==
+	      flashBusWidthRd(pFlash, flashAddrExt(pFlash, 3, 0))))) {
+		status = flashBusWidthRd(pFlash, flashAddrExt(pFlash, 4, secNum));
+
+	} else
+		status = flashBusWidthRd(pFlash, flashAddrExt(pFlash, 2, secNum));
+
+	if ((status & flashDataExt(pFlash, INTEL_CHIP_RD_ID_LOCK)) != 0) {
+		DB(mvOsPrintf("Flash: intelSecLockGet sector %d is locked \n", secNum));
+		return MV_TRUE;
+	}
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* intelSecLock - Lock/Unlock a Sector in the flash for Writing.
+*
+* DESCRIPTION:
+*       Lock/Unlock a Sector in the flash for Writing.
+*
+* INPUT:
+*       pFlash	- Flash identifier structure.
+*       secNum	- Sector Number.
+*       enable	- MV_TRUE for Lock MV_FALSE for un-lock.
+*
+* OUTPUT:
+*      None
+*
+* RETURN:
+*       MV_OK if program completed successfully,
+*	MV_TIMEOUT if timeout reached,
+*	MV_FAIL otherwise.
+*
+*******************************************************************************/
+MV_STATUS intelFlashSecLock(MV_FLASH_INFO *pFlash, MV_U32 secNum, MV_BOOL enable)
+{
+	MV_U32 status, intelLockEna, i, flashStatus;
+
+	status = MV_ERROR;
+
+	DB(mvOsPrintf("Flash: intelSecLock"));
+
+	/* lock */
+	if (enable == MV_TRUE) {
+		DB(mvOsPrintf("Flash: intelSecLock Lock sector %d \n", secNum));
+		intelLockEna = INTEL_CHIP_CMD_SET_LOCK_BLK;
+	} else {		/* unlock */
+		DB(mvOsPrintf("Flash: intelSecLock Unlock sector %d \n", secNum));
+		intelLockEna = INTEL_CHIP_CMD_CLR_LOCK_BLK;
+	}
+
+	/* clear status */
+	intelFlashStatusClr(pFlash);
+
+	/* Un/lock sequence */
+	flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_LOCK);
+	flashCmdSet(pFlash, 0, secNum, intelLockEna);
+
+	/* wait for write to complete */
+	for (i = 0; i < INTEL_LOCK_MILI_TIMEOUT; i++) {
+		mvOsDelay(1);
+		status = intelFlashStsGet(pFlash, 0, MV_TRUE, &flashStatus);
+		if (status != MV_NOT_READY)
+			break;
+	}
+	/* if timeout */
+	if (i >= INTEL_LOCK_MILI_TIMEOUT) {
+		mvOsPrintf("Flash: ERROR intelSecLock timeout \n");
+		return MV_TIMEOUT;
+	}
+	/* if completed successfully */
+	if (MV_OK == status) {
+		/* Unprotect one sector, which means unprotect all flash
+		 * and reprotect the other protected sectors.
+		 */
+		if (enable == MV_FALSE) {
+			for (i = 0; i < mvFlashNumOfSecsGet(pFlash); i++)
+				if ((i != secNum) && (MV_TRUE == mvFlashSecLockGet(pFlash, i)))
+					if (MV_OK != intelFlashSecLock(pFlash, i, MV_TRUE))
+						return MV_FAIL;
+		}
+		return MV_OK;
+	}
+	/* otherwise FAIL */
+	return MV_FAIL;
+}
+
+/*******************************************************************************
+* Check the Flash Status and return:
+*	MV_OK if status is ready and there isn't any error.
+*	MV_FAIL if status is ready and there is an error.
+*	MV_NOT_READY if status isn't ready.
+*******************************************************************************/
+static MV_STATUS intelFlashStsGet(MV_FLASH_INFO *pFlash, MV_U32 sec, MV_BOOL enableReadCommand, MV_U32 *flashStatus)
+{
+	MV_U32 status;
+
+	if (enableReadCommand)
+		flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_RD_STAT);
+	status = flashBusWidthRd(pFlash, pFlash->baseAddr + mvFlashSecOffsGet(pFlash, sec));
+
+	*flashStatus = status;
+
+	if ((status & flashDataExt(pFlash, INTEL_CHIP_STAT_RDY)) == flashDataExt(pFlash, INTEL_CHIP_STAT_RDY)) {
+		DB(mvOsPrintf("Flash: intelFlashStatusChk value is ready \n"));
+		if ((status & flashDataExt(pFlash, INTEL_CHIP_STAT_ERR)) != 0) {
+			mvOsPrintf("Flash: intelFlashStatusChk value has ERROR %x \n", status);
+			return MV_FAIL;
+		}
+		return MV_OK;
+	}
+
+	DB(mvOsPrintf("Flash: intelFlashStatusChk staus is %x and should %x \n",
+		      status, flashDataExt(pFlash, INTEL_CHIP_STAT_RDY)));
+	return MV_NOT_READY;
+}
+
+/*******************************************************************************
+* Clear the Flash Status.
+*******************************************************************************/
+static MV_VOID intelFlashStatusClr(MV_FLASH_INFO *pFlash)
+{
+	flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_CLR_STAT);
+	return;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/norflash/mvIntelFlash.h b/arch/arm/plat-feroceon/mv_hal/norflash/mvIntelFlash.h
new file mode 100755
index 0000000..ad89a76
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/norflash/mvIntelFlash.h
@@ -0,0 +1,163 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvIntelFlashH
+#define __INCmvIntelFlashH
+
+#include "mvFlashCom.h"
+
+
+/* Mt Flash IDs */
+#define MT_FID_28F400_T	0x4470	/* 28F400B3 ID ( 4 M, top boot sector)		*/
+#define MT_FID_28F400_B	0x4471	/* 28F400B3 ID ( 4 M, bottom boot sect) 	*/
+
+
+/* Intel Flash IDs */
+#define INTEL_FID_28F016S    0x66a0	/* 28F016S[VS] ID (16M = 512k x 16)	*/
+#define INTEL_FID_28F800B3T  0x8892	/*  8M = 512K x 16 top boot sector	*/
+#define INTEL_FID_28F800B3B  0x8893	/*  8M = 512K x 16 bottom boot sector	*/
+#define INTEL_FID_28F160B3T  0x8890	/*  16M = 1M x 16 top boot sector	*/
+#define INTEL_FID_28F160B3B  0x8891	/*  16M = 1M x 16 bottom boot sector	*/
+#define INTEL_FID_28F320B3T  0x8896	/*  32M = 2M x 16 top boot sector	*/
+#define INTEL_FID_28F320B3B  0x8897	/*  32M = 2M x 16 bottom boot sector	*/
+#define INTEL_FID_28F640B3T  0x8898	/*  64M = 4M x 16 top boot sector	*/
+#define INTEL_FID_28F640B3B  0x8899	/*  64M = 4M x 16 bottom boot sector	*/
+#define INTEL_FID_28F160F3B  0x88F4	/*  16M = 1M x 16 bottom boot sector	*/
+
+#define INTEL_FID_28F800C3T  0x88C0	/*  8M = 512K x 16 top boot sector	*/
+#define INTEL_FID_28F800C3B  0x88C1	/*  8M = 512K x 16 bottom boot sector	*/
+#define INTEL_FID_28F160C3T  0x88C2	/*  16M = 1M x 16 top boot sector	*/
+#define INTEL_FID_28F160C3B  0x88C3	/*  16M = 1M x 16 bottom boot sector	*/
+#define INTEL_FID_28F320C3T  0x88C4	/*  32M = 2M x 16 top boot sector	*/
+#define INTEL_FID_28F320C3B  0x88C5	/*  32M = 2M x 16 bottom boot sector	*/
+#define INTEL_FID_28F640C3T  0x88CC	/*  64M = 4M x 16 top boot sector	*/
+#define INTEL_FID_28F640C3B  0x88CD	/*  64M = 4M x 16 bottom boot sector	*/
+
+#define INTEL_FID_28F128J3   0x8918	/*  16M = 8M x 16 x 128 		*/
+#define INTEL_FID_28F320J5   0x0014	/*  32M = 128K x  32			*/
+#define INTEL_FID_28F640J5   0x0015	/*  64M = 128K x  64			*/
+#define INTEL_FID_28F320J3A  0x0016	/*  32M = 128K x  32			*/
+#define INTEL_FID_28F640J3A  0x0017	/*  64M = 128K x  64			*/
+#define INTEL_FID_28F128J3A  0x0018	/* 128M = 128K x 128			*/
+#define INTEL_FID_28F256L18T 0x880D	/* 256M = 128K x 255 + 32k x 4 		*/
+
+#define INTEL_FID_28F160S3   0x00D0	/*  16M = 512K x  32 (64kB x 32)	*/
+#define INTEL_FID_28F320S3   0x00D4	/*  32M = 512K x  64 (64kB x 64)	*/
+#define INTEL_FID_28F128P30T 0x8818	/*  16M = 128K x  127 (32kB x 4) top boot sector */
+#define INTEL_FID_28F128P30B 0x881B	/*  16M = 128K x  127 (32kB x 4) bottom boot sector */
+#define INTEL_FID_28F256P30T 0x8919	/*  32M = 128K x  255 (32kB x 4) top boot sector */
+#if defined(DB_88F1281)
+#define INTEL_FID_28F256P30B 0x1C	/*  16M = 64K x  255 (16kB x 4) bottom boot sector */
+#else
+#define INTEL_FID_28F256P30B 0x891C	/*  32M = 128K x  255 (32kB x 4) bottom boot sector */
+#endif
+
+
+/* Intel Flash APIs timeouts*/
+#define INTEL_EARASE_MILI_TIMEOUT		(8000*10) 	/* mili Sec 		*/
+#define INTEL_PROG_TIMEOUT				(0xA0000*10)	/* number of loops 	*/
+#define INTEL_LOCK_MILI_TIMEOUT			(8000*10) 	/* mili Sec		*/
+
+/* Commands */
+#define INTEL_CHIP_CMD_RST			0xFF	/* reset flash 					*/
+#define INTEL_CHIP_CMD_RD_ID		0x90	/* read the id and lock bits 	*/
+#define INTEL_CHIP_CMD_RD_QUERY		0x98	/* read device capabilities 	*/
+#define INTEL_CHIP_CMD_RD_STAT		0x70	/* read the status register 	*/
+#define INTEL_CHIP_CMD_CLR_STAT		0x50	/* clear the staus register		*/
+#define INTEL_CHIP_CMD_WR_BUF		0xE8	/* write buffer command			*/
+#define INTEL_CHIP_CMD_CONFIRM_BUF	0xD0	/* write buffer command			*/
+#define INTEL_CHIP_CMD_PROG			0x40	/* program word command 		*/
+#define INTEL_CHIP_CMD_ERASE1		0x20	/* 1st word for block erase 	*/
+#define INTEL_CHIP_CMD_ERASE2		0xD0	/* 2nd word for block erase 	*/
+#define INTEL_CHIP_CMD_ERASE_SUSP	0xB0	/* suspend block erase 			*/
+#define INTEL_CHIP_CMD_LOCK			0x60	/* 1st word for all lock cmds 	*/
+#define INTEL_CHIP_CMD_SET_LOCK_BLK	 0x01	/* 2nd wrd set block lock bit 	*/
+#define INTEL_CHIP_CMD_SET_LOCK_MSTR 0xF1	/* 2nd wrd set master lck bit 	*/
+#define INTEL_CHIP_CMD_CLR_LOCK_BLK	0xD0	/* 2nd wrd clear blk lck bit 	*/
+
+
+
+/* status register bits */
+#define INTEL_CHIP_STAT_DPS		0x02		/* Device Protect Status 		*/
+#define INTEL_CHIP_STAT_VPPS	0x08		/* VPP Status 					*/
+#define INTEL_CHIP_STAT_PSLBS	0x10		/* Program+Set Lock Bit Stat 	*/
+#define INTEL_CHIP_STAT_ECLBS	0x20		/* Erase+Clr Lock Bit Stat 		*/
+#define INTEL_CHIP_STAT_ESS		0x40		/* Erase Suspend Status 		*/
+#define INTEL_CHIP_STAT_RDY		0x80		/* WSM Mach Status, 1=rdy 		*/
+
+#define INTEL_CHIP_STAT_ERR		(INTEL_CHIP_STAT_VPPS | INTEL_CHIP_STAT_DPS | \
+				    INTEL_CHIP_STAT_ECLBS | INTEL_CHIP_STAT_PSLBS)
+
+/* Lock Configuration */
+#define INTEL_CHIP_RD_ID_LOCK		0x01		/* Bit 0 of each byte 		*/
+
+MV_STATUS intelFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 secNum);
+MV_VOID   intelFlashReset(MV_FLASH_INFO *pFlash);
+MV_STATUS intelFlashProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data);
+MV_BOOL   intelFlashSecLockGet(MV_FLASH_INFO *pFlash, MV_U32 secNum);
+MV_STATUS intelFlashSecLock(MV_FLASH_INFO *pFlash, MV_U32 secNum, MV_BOOL enable);
+MV_U32 intelFlashGetHwBuffSize(MV_FLASH_INFO *pFlash);
+MV_STATUS intelFlashHwBufferProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 byteCount, MV_U8 *pData);
+
+#endif /* __INCmvIntelFlashH */
diff --git a/arch/arm/plat-feroceon/mv_hal/pci-if/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/pci-if/mvCompVer.txt
new file mode 100755
index 0000000..3afa556
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pci-if/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.3
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIf.c b/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIf.c
new file mode 100755
index 0000000..a14130d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIf.c
@@ -0,0 +1,543 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvPciIf.h"
+#include "mvSysPexApi.h"
+
+/* #if defined(MV_INCLUDE_PCI) */
+/* #include "ctrlEnv/sys/mvSysPci.h" */
+/* #endif */
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/*******************************************************************************
+* mvPciInit - Initialize PCI interfaces
+*
+* DESCRIPTION:
+*
+* INPUT:
+*	None
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM
+*
+*******************************************************************************/
+MV_STATUS mvPciIfInit(MV_U32 pciIf, PCI_IF_MODE pciIfmode)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+
+		MV_PCI_MOD pciMod;
+
+		if (PCI_IF_MODE_HOST == pciIfmode) {
+			pciMod = MV_PCI_MOD_HOST;
+		} else if (PCI_IF_MODE_DEVICE == pciIfmode) {
+			pciMod = MV_PCI_MOD_DEVICE;
+		} else {
+			mvOsPrintf("%s: ERROR!!! Bus %d mode %d neither host nor device!\n",
+				   __func__, pciIf, pciIfmode);
+			return MV_FAIL;
+		}
+
+		return mvPciInit(pciIf - MV_PCI_START_IF, pciMod);
+#else
+		return MV_OK;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+
+		MV_PEX_TYPE pexType;
+
+		if (PCI_IF_MODE_HOST == pciIfmode) {
+			pexType = MV_PEX_ROOT_COMPLEX;
+		} else if (PCI_IF_MODE_DEVICE == pciIfmode) {
+			pexType = MV_PEX_END_POINT;
+		} else {
+			mvOsPrintf("%s: ERROR!!! Bus %d type %d neither root complex nor"
+				   " end point\n", __func__, pciIf, pciIfmode);
+			return MV_FAIL;
+		}
+		return mvSysPexInit(pciIf - MV_PEX_START_IF, pexType);
+
+#else
+		return MV_OK;
+#endif
+
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return MV_FAIL;
+}
+
+/* PCI configuration space read write */
+/*******************************************************************************
+* mvPciConfigRead - Read from configuration space
+*
+* DESCRIPTION:
+*	This function performs a 32 bit read from PCI configuration space.
+*	It supports both type 0 and type 1 of Configuration Transactions
+*	(local and over bridge). In order to read from local bus segment, use
+*	bus number retrieved from mvPciLocalBusNumGet(). Other bus numbers
+*	will result configuration transaction of type 1 (over bridge).
+*
+* INPUT:
+*	pciIf		- PCI interface number.
+*	bus		- PCI segment bus number.
+*	dev		- PCI device number.
+*	func		- Function number.
+*	regOffs		- Register offset.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	32bit register data, 0xffffffff on error
+*
+*******************************************************************************/
+MV_U32 mvPciIfConfigRead(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+		return mvPciConfigRead(pciIf - MV_PCI_START_IF, bus, dev, func, regOff);
+#else
+		return 0xffffffff;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+		return mvPexConfigRead(pciIf - MV_PEX_START_IF, bus, dev, func, regOff);
+#else
+		return 0xffffffff;
+#endif
+
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+* mvPciConfigWrite - Write to configuration space
+*
+* DESCRIPTION:
+*	This function performs a 32 bit write to PCI configuration space.
+*	It supports both type 0 and type 1 of Configuration Transactions
+*	(local and over bridge). In order to write to local bus segment, use
+*	bus number retrieved from mvPciLocalBusNumGet(). Other bus numbers
+*	will result configuration transaction of type 1 (over bridge).
+*
+* INPUT:
+*	pciIf		- PCI interface number.
+*	bus		- PCI segment bus number.
+*	dev		- PCI device number.
+*	func		- Function number.
+*	regOffs		- Register offset.
+*	data		- 32bit data.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPciIfConfigWrite(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff, MV_U32 data)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+		return mvPciConfigWrite(pciIf - MV_PCI_START_IF, bus, dev, func, regOff, data);
+#else
+		return MV_OK;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+		return mvPexConfigWrite(pciIf - MV_PEX_START_IF, bus, dev, func, regOff, data);
+#else
+		return MV_OK;
+#endif
+
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return MV_FAIL;
+}
+
+/*******************************************************************************
+* mvPciMasterEnable - Enable/disale PCI interface master transactions.
+*
+* DESCRIPTION:
+*	This function performs read modified write to PCI command status
+*	(offset 0x4) to set/reset bit 2. After this bit is set, the PCI
+*	master is allowed to gain ownership on the bus, otherwise it is
+*	incapable to do so.
+*
+* INPUT:
+*	pciIf		- PCI interface number.
+*	enable		- Enable/disable parameter.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPciIfMasterEnable(MV_U32 pciIf, MV_BOOL enable)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+		return mvPciMasterEnable(pciIf - MV_PCI_START_IF, enable);
+#else
+		return MV_OK;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+		return mvPexMasterEnable(pciIf - MV_PEX_START_IF, enable);
+#else
+		return MV_OK;
+#endif
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return MV_FAIL;
+}
+
+/*******************************************************************************
+* mvPciSlaveEnable - Enable/disale PCI interface slave transactions.
+*
+* DESCRIPTION:
+*	This function performs read modified write to PCI command status
+*	(offset 0x4) to set/reset bit 0 and 1. After those bits are set,
+*	the PCI slave is allowed to respond to PCI IO space access (bit 0)
+*	and PCI memory space access (bit 1).
+*
+* INPUT:
+*	pciIf		- PCI interface number.
+*	dev		- PCI device number.
+*	enable		- Enable/disable parameter.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPciIfSlaveEnable(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_BOOL enable)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+		return mvPciSlaveEnable(pciIf - MV_PCI_START_IF, bus, dev, enable);
+#else
+		return MV_OK;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+		return mvPexSlaveEnable(pciIf - MV_PEX_START_IF, bus, dev, enable);
+#else
+		return MV_OK;
+#endif
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return MV_FAIL;
+}
+
+/*******************************************************************************
+* mvPciLocalBusNumSet - Set PCI interface local bus number.
+*
+* DESCRIPTION:
+*	This function sets given PCI interface its local bus number.
+*	Note: In case the PCI interface is PCI-X, the information is read-only.
+*
+* INPUT:
+*	pciIf		- PCI interface number.
+*	busNum		- Bus number.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_NOT_ALLOWED in case PCI interface is PCI-X.
+*	MV_BAD_PARAM on bad parameters, otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPciIfLocalBusNumSet(MV_U32 pciIf, MV_U32 busNum)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+		return mvPciLocalBusNumSet(pciIf - MV_PCI_START_IF, busNum);
+#else
+		return MV_OK;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+		return mvPexLocalBusNumSet(pciIf - MV_PEX_START_IF, busNum);
+#else
+		return MV_OK;
+#endif
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return MV_FAIL;
+}
+
+/*******************************************************************************
+* mvPciLocalBusNumGet - Get PCI interface local bus number.
+*
+* DESCRIPTION:
+*	This function gets the local bus number of a given PCI interface.
+*
+* INPUT:
+*	pciIf  - PCI interface number.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	Local bus number.0xffffffff on Error
+*
+*******************************************************************************/
+MV_U32 mvPciIfLocalBusNumGet(MV_U32 pciIf)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+		return mvPciLocalBusNumGet(pciIf - MV_PCI_START_IF);
+#else
+		return 0xFFFFFFFF;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+		return mvPexLocalBusNumGet(pciIf - MV_PEX_START_IF);
+#else
+		return 0xFFFFFFFF;
+#endif
+
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+* mvPciLocalDevNumSet - Set PCI interface local device number.
+*
+* DESCRIPTION:
+*	This function sets given PCI interface its local device number.
+*	Note: In case the PCI interface is PCI-X, the information is read-only.
+*
+* INPUT:
+*	pciIf		- PCI interface number.
+*	devNum		- Device number.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_NOT_ALLOWED in case PCI interface is PCI-X.
+*	MV_BAD_PARAM on bad parameters, otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPciIfLocalDevNumSet(MV_U32 pciIf, MV_U32 devNum)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+		return mvPciLocalDevNumSet(pciIf - MV_PCI_START_IF, devNum);
+#else
+		return MV_OK;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+		return mvPexLocalDevNumSet(pciIf - MV_PEX_START_IF, devNum);
+#else
+		return MV_OK;
+#endif
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return MV_FAIL;
+}
+
+/*******************************************************************************
+* mvPciLocalDevNumGet - Get PCI interface local device number.
+*
+* DESCRIPTION:
+*	This function gets the local device number of a given PCI interface.
+*
+* INPUT:
+*	pciIf  - PCI interface number.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	Local device number. 0xffffffff on Error
+*
+*******************************************************************************/
+MV_U32 mvPciIfLocalDevNumGet(MV_U32 pciIf)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) {
+#if defined(MV_INCLUDE_PCI)
+		return mvPciLocalDevNumGet(pciIf - MV_PCI_START_IF);
+#else
+		return 0xFFFFFFFF;
+#endif
+	} else if (PCI_IF_TYPE_PEX == pciIfType) {
+#if defined(MV_INCLUDE_PEX)
+		return mvPexLocalDevNumGet(pciIf - MV_PEX_START_IF);
+#else
+		return 0xFFFFFFFF;
+#endif
+
+	} else {
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+* mvPciIfTypeGet -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*
+*******************************************************************************/
+PCI_IF_TYPE mvPciIfTypeGet(MV_U32 pciIf)
+{
+	if ((pciIf >= MV_PCI_START_IF) && (pciIf < MV_PCI_MAX_IF + MV_PCI_START_IF))
+		return PCI_IF_TYPE_CONVEN_PCIX;
+	else if ((pciIf >= MV_PEX_START_IF) && (pciIf < MV_PEX_MAX_IF + MV_PEX_START_IF))
+		return PCI_IF_TYPE_PEX;
+	else
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+
+	return 0xffffffff;
+}
+
+/*******************************************************************************
+* mvPciIfTypeGet -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_U32 mvPciRealIfNumGet(MV_U32 pciIf)
+{
+	PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf);
+
+	if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType)
+		return (pciIf - MV_PCI_START_IF);
+	else if (PCI_IF_TYPE_PEX == pciIfType)
+		return (pciIf - MV_PEX_START_IF);
+	else
+		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __func__, pciIf);
+
+	return 0xffffffff;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIf.h b/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIf.h
new file mode 100755
index 0000000..12165ec
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIf.h
@@ -0,0 +1,134 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCPCIIFH
+#define __INCPCIIFH
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+#include "mvSysHwConfig.h"
+#include "pci-if/mvPciIfRegs.h"
+#if defined(MV_INCLUDE_PEX)
+#include "pex/mvPex.h"
+#endif
+#if defined(MV_INCLUDE_PCI)
+#include "pci/mvPci.h"
+#endif
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "ctrlEnv/mvCtrlEnvAddrDec.h"
+
+typedef enum _mvPCIIfType {
+	PCI_IF_TYPE_CONVEN_PCIX,
+	PCI_IF_TYPE_PEX
+} PCI_IF_TYPE;
+
+typedef enum _mvPCIIfMode {
+	PCI_IF_MODE_HOST,
+	PCI_IF_MODE_DEVICE
+} PCI_IF_MODE;
+
+/* Global Functions prototypes */
+
+/* mvPciIfInit - Initialize PCI interfaces*/
+MV_STATUS mvPciIfInit(MV_U32 pciIf, PCI_IF_MODE pciIfmode);
+
+/* mvPciIfConfigRead - Read from configuration space */
+MV_U32 mvPciIfConfigRead(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff);
+
+/* mvPciIfConfigWrite - Write to configuration space */
+MV_STATUS mvPciIfConfigWrite(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff, MV_U32 data);
+
+/* mvPciIfMasterEnable - Enable/disale PCI interface master transactions.*/
+MV_STATUS mvPciIfMasterEnable(MV_U32 pciIf, MV_BOOL enable);
+
+/* mvPciIfSlaveEnable - Enable/disale PCI interface slave transactions.*/
+MV_STATUS mvPciIfSlaveEnable(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_BOOL enable);
+
+/* mvPciIfLocalBusNumSet - Set PCI interface local bus number.*/
+MV_STATUS mvPciIfLocalBusNumSet(MV_U32 pciIf, MV_U32 busNum);
+
+/* mvPciIfLocalBusNumGet - Get PCI interface local bus number.*/
+MV_U32 mvPciIfLocalBusNumGet(MV_U32 pciIf);
+
+/* mvPciIfLocalDevNumSet - Set PCI interface local device number.*/
+MV_STATUS mvPciIfLocalDevNumSet(MV_U32 pciIf, MV_U32 devNum);
+
+/* mvPciIfLocalDevNumGet - Get PCI interface local device number.*/
+MV_U32 mvPciIfLocalDevNumGet(MV_U32 pciIf);
+
+/* mvPciIfTypeGet - Get PCI If type*/
+PCI_IF_TYPE mvPciIfTypeGet(MV_U32 pciIf);
+
+MV_U32 mvPciRealIfNumGet(MV_U32 pciIf);
+
+/* mvPciIfAddrDecShow - Display address decode windows attributes */
+MV_VOID mvPciIfAddrDecShow(MV_VOID);
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif /* #ifndef __INCPCIIFH */
diff --git a/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIfRegs.h b/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIfRegs.h
new file mode 100755
index 0000000..668d75b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pci-if/mvPciIfRegs.h
@@ -0,0 +1,235 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCPCIIFREGSH
+#define __INCPCIIFREGSH
+
+/* defines */
+#define MAX_PCI_DEVICES         32
+#define MAX_PCI_FUNCS           8
+#define MAX_PCI_BUSSES          128
+
+/***************************************/
+/* PCI Configuration registers */
+/***************************************/
+
+/*********************************************/
+/* PCI Configuration, Function 0, Registers  */
+/*********************************************/
+
+/* Standard registers */
+#define PCI_DEVICE_AND_VENDOR_ID					0x000
+#define PCI_STATUS_AND_COMMAND						0x004
+#define PCI_CLASS_CODE_AND_REVISION_ID			    0x008
+#define PCI_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE		0x00C
+#define PCI_MEMORY_BAR_BASE_ADDR(barNum)		 	(0x010 + ((barNum) << 2))
+#define PCI_SUBSYS_ID_AND_SUBSYS_VENDOR_ID		 	0x02C
+#define PCI_EXPANSION_ROM_BASE_ADDR_REG			    0x030
+#define PCI_CAPABILTY_LIST_POINTER			        0x034
+#define PCI_INTERRUPT_PIN_AND_LINE					0x03C
+
+/* PCI Device and Vendor ID Register (PDVIR) */
+#define PDVIR_VEN_ID_OFFS			0	/* Vendor ID */
+#define PDVIR_VEN_ID_MASK			(0xffff << PDVIR_VEN_ID_OFFS)
+
+#define PDVIR_DEV_ID_OFFS			16	/* Device ID */
+#define PDVIR_DEV_ID_MASK  			(0xffff << PDVIR_DEV_ID_OFFS)
+
+/* PCI Status and Command Register (PSCR) */
+#define PSCR_IO_EN			BIT0	/* IO Enable                                                      */
+#define PSCR_MEM_EN			BIT1	/* Memory Enable                                                  */
+#define PSCR_MASTER_EN		BIT2	/* Master Enable                                                  */
+#define PSCR_SPECIAL_EN		BIT3	/* Special Cycle Enable                                   */
+#define PSCR_MEM_WRI_INV	BIT4	/* Memory Write and Invalidate Enable     */
+#define PSCR_VGA			BIT5	/* VGA Palette Snoops                                     */
+#define PSCR_PERR_EN		BIT6	/* Parity Errors Respond Enable                   */
+#define PSCR_ADDR_STEP   	BIT7	/* Address Stepping Enable (Wait Cycle En) */
+#define PSCR_SERR_EN		BIT8	/* Ability to assert SERR# line                   */
+#define PSCR_FAST_BTB_EN	BIT9	/* generate fast back-to-back transactions */
+#define PSCR_CAP_LIST		BIT20	/* Capability List Support                                */
+#define PSCR_66MHZ_EN		BIT21	/* 66 MHz Capable                                                 */
+#define PSCR_UDF_EN			BIT22	/* User definable features                                */
+#define PSCR_TAR_FAST_BB 	BIT23	/* fast back-to-back transactions capable */
+#define PSCR_DATA_PERR		BIT24	/* Data Parity reported                                   */
+
+#define PSCR_DEVSEL_TIM_OFFS 	25	/* DEVSEL timing */
+#define PSCR_DEVSEL_TIM_MASK 	(0x3 << PSCR_DEVSEL_TIM_OFFS)
+#define PSCR_DEVSEL_TIM_FAST	(0x0 << PSCR_DEVSEL_TIM_OFFS)
+#define PSCR_DEVSEL_TIM_MED 	(0x1 << PSCR_DEVSEL_TIM_OFFS)
+#define PSCR_DEVSEL_TIM_SLOW 	(0x2 << PSCR_DEVSEL_TIM_OFFS)
+
+#define PSCR_SLAVE_TABORT	BIT27	/* Signalled Target Abort       */
+#define PSCR_MASTER_TABORT	BIT28	/* Recieved Target Abort        */
+#define PSCR_MABORT			BIT29	/* Recieved Master Abort        */
+#define PSCR_SYSERR			BIT30	/* Signalled system error       */
+#define PSCR_DET_PARERR		BIT31	/* Detect Parity Error          */
+
+/*	PCI configuration register offset=0x08 fields
+	(PCI_CLASS_CODE_AND_REVISION_ID)(PCCRI) */
+
+#define PCCRIR_REVID_OFFS		0	/* Revision ID */
+#define PCCRIR_REVID_MASK		(0xff << PCCRIR_REVID_OFFS)
+
+#define PCCRIR_FULL_CLASS_OFFS	8	/* Full Class Code */
+#define PCCRIR_FULL_CLASS_MASK	(0xffffff << PCCRIR_FULL_CLASS_OFFS)
+
+#define PCCRIR_PROGIF_OFFS		8	/* Prog .I/F */
+#define PCCRIR_PROGIF_MASK		(0xff << PCCRIR_PROGIF_OFFS)
+
+#define PCCRIR_SUB_CLASS_OFFS	16	/* Sub Class */
+#define PCCRIR_SUB_CLASS_MASK	(0xff << PCCRIR_SUB_CLASS_OFFS)
+
+#define PCCRIR_BASE_CLASS_OFFS	24	/* Base Class */
+#define PCCRIR_BASE_CLASS_MASK	(0xff << PCCRIR_BASE_CLASS_OFFS)
+
+/* 	PCI configuration register offset=0x0C fields
+	(PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE)(PBHTLTCL) */
+
+#define PBHTLTCLR_CACHELINE_OFFS		0	/* Specifies the cache line size */
+#define PBHTLTCLR_CACHELINE_MASK		(0xff << PBHTLTCLR_CACHELINE_OFFS)
+
+#define PBHTLTCLR_LATTIMER_OFFS			8	/* latency timer */
+#define PBHTLTCLR_LATTIMER_MASK			(0xff << PBHTLTCLR_LATTIMER_OFFS)
+
+#define PBHTLTCLR_HEADTYPE_FULL_OFFS	16	/* Full Header Type */
+#define PBHTLTCLR_HEADTYPE_FULL_MASK	(0xff << PBHTLTCLR_HEADTYPE_FULL_OFFS)
+
+#define PBHTLTCLR_MULTI_FUNC			BIT23	/* Multi/Single function */
+
+#define PBHTLTCLR_HEADER_OFFS			16	/* Header type */
+#define PBHTLTCLR_HEADER_MASK			(0x7f << PBHTLTCLR_HEADER_OFFS)
+#define PBHTLTCLR_HEADER_STANDARD		(0x0 << PBHTLTCLR_HEADER_OFFS)
+#define PBHTLTCLR_HEADER_PCI2PCI_BRIDGE	(0x1 << PBHTLTCLR_HEADER_OFFS)
+
+#define PBHTLTCLR_BISTCOMP_OFFS		24	/* BIST Completion Code */
+#define PBHTLTCLR_BISTCOMP_MASK		(0xf << PBHTLTCLR_BISTCOMP_OFFS)
+
+#define PBHTLTCLR_BISTACT			BIT30	/* BIST Activate bit */
+#define PBHTLTCLR_BISTCAP			BIT31	/* BIST Capable Bit */
+
+/* PCI Bar Base Low Register (PBBLR) */
+#define PBBLR_IOSPACE			BIT0	/* Memory Space Indicator */
+
+#define PBBLR_TYPE_OFFS			1	/* BAR Type/Init Val. */
+#define PBBLR_TYPE_MASK			(0x3 << PBBLR_TYPE_OFFS)
+#define PBBLR_TYPE_32BIT_ADDR	(0x0 << PBBLR_TYPE_OFFS)
+#define PBBLR_TYPE_64BIT_ADDR	(0x2 << PBBLR_TYPE_OFFS)
+
+#define PBBLR_PREFETCH_EN		BIT3	/* Prefetch Enable */
+
+#define PBBLR_MEM_BASE_OFFS		4	/* Memory Bar Base address. Corresponds to
+address bits [31:4] */
+#define PBBLR_MEM_BASE_MASK		(0xfffffff << PBBLR_MEM_BASE_OFFS)
+
+#define PBBLR_IO_BASE_OFFS		2	/* IO Bar Base address. Corresponds to
+address bits [31:2] */
+#define PBBLR_IO_BASE_MASK		(0x3fffffff << PBBLR_IO_BASE_OFFS)
+
+#define PBBLR_BASE_OFFS			12	/* Base address. Address bits [31:12] */
+#define PBBLR_BASE_MASK			(0xfffff << PBBLR_BASE_OFFS)
+#define PBBLR_BASE_ALIGNMET		(1 << PBBLR_BASE_OFFS)
+
+/* PCI Bar Base High Fegister (PBBHR) */
+#define PBBHR_BASE_OFFS			0	/* Base address. Address bits [31:12] */
+#define PBBHR_BASE_MASK			(0xffffffff << PBBHR_BASE_OFFS)
+
+/*	PCI configuration register offset=0x2C fields
+	(PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID)(PSISVI) */
+
+#define PSISVIR_VENID_OFFS	0	/* Subsystem Manufacturer Vendor ID Number */
+#define PSISVIR_VENID_MASK	(0xffff << PSISVIR_VENID_OFFS)
+
+#define PSISVIR_DEVID_OFFS	16	/* Subsystem Device ID Number */
+#define PSISVIR_DEVID_MASK	(0xffff << PSISVIR_DEVID_OFFS)
+
+/*	PCI configuration register offset=0x30 fields
+	(PCI_EXPANSION_ROM_BASE_ADDR_REG)(PERBA) */
+
+#define PERBAR_EXPROMEN		BIT0	/* Expansion ROM Enable */
+
+#define PERBAR_BASE_OFFS		12	/* Expansion ROM Base Address */
+#define PERBAR_BASE_MASK		(0xfffff << PERBAR_BASE_OFFS)
+
+/*	PCI configuration register offset=0x34 fields
+	(PCI_CAPABILTY_LIST_POINTER)(PCLP) */
+
+#define PCLPR_CAPPTR_OFFS	0	/* Capability List Pointer */
+#define PCLPR_CAPPTR_MASK	(0xff << PCLPR_CAPPTR_OFFS)
+
+/*	PCI configuration register offset=0x3C fields
+	(PCI_INTERRUPT_PIN_AND_LINE)(PIPL) */
+
+#define PIPLR_INTLINE_OFFS	0	/* Interrupt line (IRQ) */
+#define PIPLR_INTLINE_MASK	(0xff << PIPLR_INTLINE_OFFS)
+
+#define PIPLR_INTPIN_OFFS	8	/* interrupt pin (A, B, C, D) */
+#define PIPLR_INTPIN_MASK	(0xff << PIPLR_INTPIN_OFFS)
+
+#define PIPLR_MINGRANT_OFFS	16	/* Minimum Grant on 250 nano seconds units */
+#define PIPLR_MINGRANT_MASK	(0xff << PIPLR_MINGRANT_OFFS)
+
+#define PIPLR_MAXLATEN_OFFS	24	/* Maximum latency on 250 nano seconds units */
+#define PIPLR_MAXLATEN_MASK	(0xff << PIPLR_MAXLATEN_OFFS)
+
+#endif /* #ifndef __INCPCIIFREGSH */
diff --git a/arch/arm/plat-feroceon/mv_hal/pci-if/pci_util/mvPciUtils.c b/arch/arm/plat-feroceon/mv_hal/pci-if/pci_util/mvPciUtils.c
new file mode 100755
index 0000000..31463e7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pci-if/pci_util/mvPciUtils.c
@@ -0,0 +1,753 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* includes */
+#include "pci-if/pci_util/mvPciUtils.h"
+#include "pex/mvPex.h"
+#include "mvCtrlEnvLib.h"
+#include "pci-if/mvPciIf.h"
+
+/* #define MV_DEBUG */
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/*
+This module only support scanning of Header type 00h of pci devices
+There is no suppotr for Header type 01h of pci devices  ( PCI bridges )
+*/
+
+static MV_STATUS pciDetectDevice(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_PCI_DEVICE *pPciAgent);
+
+static MV_U32 pciDetectDeviceBars(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_PCI_DEVICE *pPciAgent);
+
+/*******************************************************************************
+* mvPciScan - Scan a PCI interface bus
+*
+* DESCRIPTION:
+* Performs a full scan on a PCI interface and returns all possible details
+* on the agents found on the bus.
+*
+* INPUT:
+*	pciIf			- PCI Interface
+*	pPciAgents		- Pointer to an Array of the pci agents to be detected
+*	pPciAgentsNum		- pPciAgents array maximum number of elements
+*
+* OUTPUT:
+*	pPciAgents		- Array of the pci agents detected on the bus
+*	pPciAgentsNum		- Number of pci agents detected on the bus
+*
+* RETURN:
+*	MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+
+MV_STATUS mvPciScan(MV_U32 pciIf, MV_PCI_DEVICE *pPciAgents, MV_U32 * pPciAgentsNum)
+{
+
+	MV_U32 devIndex, funcIndex = 0, busIndex = 0, detectedDevNum = 0;
+	MV_U32 localBus = mvPexLocalBusNumGet(pciIf);
+	MV_PCI_DEVICE *pPciDevice;
+	MV_PCI_DEVICE *pMainDevice;
+
+	DB(mvOsPrintf("mvPciScan: PCI interface num %d\n", pciIf));
+	/* Parameter checking   */
+	if (pciIf >= mvCtrlPciIfMaxIfGet()) {
+		DB(mvOsPrintf("mvPciScan: ERR. Invalid PCI interface num %d\n", pciIf));
+		return MV_BAD_PARAM;
+	}
+	if (NULL == pPciAgents) {
+		DB(mvOsPrintf("mvPciScan: ERR. pPciAgents=NULL \n"));
+		return MV_BAD_PARAM;
+	}
+	if (NULL == pPciAgentsNum) {
+		DB(mvOsPrintf("mvPciScan: ERR. pPciAgentsNum=NULL \n"));
+		return MV_BAD_PARAM;
+	}
+
+	DB(mvOsPrintf("mvPciScan: PCI interface num %d mvPciMasterEnable\n", pciIf));
+	/* Master enable the MV PCI master */
+	if (MV_OK != mvPciIfMasterEnable(pciIf, MV_TRUE)) {
+		DB(mvOsPrintf("mvPciScan: ERR. mvPciMasterEnable failed  \n"));
+		return MV_ERROR;
+
+	}
+
+	DB(mvOsPrintf("mvPciScan: PCI interface num scan%d\n", pciIf));
+
+	/* go through all busses */
+	for (busIndex = localBus; busIndex < MAX_PCI_BUSSES; busIndex++) {
+		/* go through all possible devices on the local bus */
+		for (devIndex = 0; devIndex < MAX_PCI_DEVICES; devIndex++) {
+			/* always start with function equal to zero */
+			funcIndex = 0;
+
+			pPciDevice = &pPciAgents[detectedDevNum];
+			DB(mvOsPrintf("mvPciScan: PCI interface num scan%d:%d\n", busIndex, devIndex));
+
+			if (MV_ERROR == pciDetectDevice(pciIf, busIndex, devIndex, funcIndex, pPciDevice)) {
+				/* no device detected , try the next address */
+				continue;
+			}
+
+			/* We are here ! means we have detected a device */
+			/* always we start with only one function per device */
+			pMainDevice = pPciDevice;
+			pPciDevice->funtionsNum = 1;
+
+			/* move on */
+			detectedDevNum++;
+
+			/* check if we have no more room for a new device */
+			if (detectedDevNum == *pPciAgentsNum) {
+				DB(mvOsPrintf("mvPciScan: ERR. array passed too small \n"));
+				return MV_ERROR;
+			}
+
+			/* check the detected device if it is a multi functional device then
+			   scan all device functions */
+			if (pPciDevice->isMultiFunction == MV_TRUE) {
+				/* start with function number 1 because we have already detected
+				   function 0 */
+				for (funcIndex = 1; funcIndex < MAX_PCI_FUNCS; funcIndex++) {
+					pPciDevice = &pPciAgents[detectedDevNum];
+
+					if (MV_ERROR == pciDetectDevice(pciIf,
+									busIndex,
+									devIndex, funcIndex, pPciDevice)) {
+						/* no device detected means no more functions ! */
+						continue;
+					}
+					/* We are here ! means we have detected a device */
+
+					/* move on */
+					pMainDevice->funtionsNum++;
+					detectedDevNum++;
+
+					/* check if we have no more room for a new device */
+					if (detectedDevNum == *pPciAgentsNum) {
+						DB(mvOsPrintf("mvPciScan: ERR. Array too small\n"));
+						return MV_ERROR;
+					}
+				}
+			}
+		}
+	}
+
+	/* return the number of devices actually detected on the bus ! */
+	*pPciAgentsNum = detectedDevNum;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* pciDetectDevice - Detect a pci device parameters
+*
+* DESCRIPTION:
+* This function detect if a pci agent exist on certain address !
+* and if exists then it fills all possible information on the
+* agent
+*
+* INPUT:
+*	pciIf		- PCI Interface
+*	bus		- Bus number
+*	dev		- Device number
+*	func		- Function number
+*
+* OUTPUT:
+*	pPciAgent	- pointer to the pci agent filled with its information
+*
+* RETURN:
+*	MV_ERROR if no device , MV_OK otherwise
+*
+*******************************************************************************/
+
+static MV_STATUS pciDetectDevice(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_PCI_DEVICE *pPciAgent)
+{
+	MV_U32 pciData;
+
+	/* no Parameters checking ! because it is static function and it is assumed
+	   that all parameters were checked in the calling function */
+
+	/* Try read the PCI Vendor ID and Device ID */
+
+	/*  We will scan only ourselves and the PCI slots that exist on the
+	   board, because we may have a case that we have one slot that has
+	   a Cardbus connector, and because CardBus answers all IDsels we want
+	   to scan only this slot and ourseleves.
+
+	 */
+#if defined(MV_INCLUDE_PCI)
+	if ((PCI_IF_TYPE_CONVEN_PCIX == mvPciIfTypeGet(pciIf)) &&
+			(DB_88F5181_DDR1_PRPMC != mvBoardIdGet()) &&
+			(DB_88F5181_DDR1_PEXPCI != mvBoardIdGet()) &&
+			(DB_88F5181_DDR1_MNG != mvBoardIdGet()) && (mvBoardIsOurPciSlot(bus, dev) == MV_FALSE))
+		return MV_ERROR;
+
+#endif /* defined(MV_INCLUDE_PCI) */
+
+	pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_DEVICE_AND_VENDOR_ID);
+
+	if (PCI_ERROR_CODE == pciData) {
+		/* no device exist */
+		return MV_ERROR;
+	}
+
+	/* we are here ! means a device is detected */
+
+	/* fill basic information */
+	pPciAgent->busNumber = bus;
+	pPciAgent->deviceNum = dev;
+	pPciAgent->function = func;
+
+	/* Fill the PCI Vendor ID and Device ID */
+
+	pPciAgent->venID = (pciData & PDVIR_VEN_ID_MASK) >> PDVIR_VEN_ID_OFFS;
+	pPciAgent->deviceID = (pciData & PDVIR_DEV_ID_MASK) >> PDVIR_DEV_ID_OFFS;
+
+	/* Read Status and command */
+	pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_STATUS_AND_COMMAND);
+
+	/* Fill related Status and Command information */
+
+	if (pciData & PSCR_TAR_FAST_BB)
+		pPciAgent->isFastB2BCapable = MV_TRUE;
+	else
+		pPciAgent->isFastB2BCapable = MV_FALSE;
+
+	if (pciData & PSCR_CAP_LIST)
+		pPciAgent->isCapListSupport = MV_TRUE;
+	else
+		pPciAgent->isCapListSupport = MV_FALSE;
+
+	if (pciData & PSCR_66MHZ_EN)
+		pPciAgent->is66MHZCapable = MV_TRUE;
+	else
+		pPciAgent->is66MHZCapable = MV_FALSE;
+
+	/* Read Class Code and Revision */
+	pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_CLASS_CODE_AND_REVISION_ID);
+
+	pPciAgent->baseClassCode = (pciData & PCCRIR_BASE_CLASS_MASK) >> PCCRIR_BASE_CLASS_OFFS;
+
+	pPciAgent->subClassCode = (pciData & PCCRIR_SUB_CLASS_MASK) >> PCCRIR_SUB_CLASS_OFFS;
+
+	pPciAgent->progIf = (pciData & PCCRIR_PROGIF_MASK) >> PCCRIR_PROGIF_OFFS;
+
+	pPciAgent->revisionID = (pciData & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS;
+
+	/* Read  PCI_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE */
+	pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE);
+
+	pPciAgent->pciCacheLine = (pciData & PBHTLTCLR_CACHELINE_MASK) >> PBHTLTCLR_CACHELINE_OFFS;
+	pPciAgent->pciLatencyTimer = (pciData & PBHTLTCLR_LATTIMER_MASK) >> PBHTLTCLR_LATTIMER_OFFS;
+
+	switch (pciData & PBHTLTCLR_HEADER_MASK) {
+	case PBHTLTCLR_HEADER_STANDARD:
+
+		pPciAgent->pciHeader = MV_PCI_STANDARD;
+		break;
+	case PBHTLTCLR_HEADER_PCI2PCI_BRIDGE:
+
+		pPciAgent->pciHeader = MV_PCI_PCI2PCI_BRIDGE;
+		break;
+	}
+
+	if (pciData & PBHTLTCLR_MULTI_FUNC)
+		pPciAgent->isMultiFunction = MV_TRUE;
+	else
+		pPciAgent->isMultiFunction = MV_FALSE;
+
+	if (pciData & PBHTLTCLR_BISTCAP)
+		pPciAgent->isBISTCapable = MV_TRUE;
+	else
+		pPciAgent->isBISTCapable = MV_FALSE;
+
+	/* read this device pci bars */
+
+	pciDetectDeviceBars(pciIf, bus, dev, func, pPciAgent);
+
+	/* check if we are bridge */
+	if ((pPciAgent->baseClassCode == PCI_BRIDGE_CLASS) && (pPciAgent->subClassCode == P2P_BRIDGE_SUB_CLASS_CODE)) {
+
+		/* Read  P2P_BUSSES_NUM */
+		pciData = mvPciIfConfigRead(pciIf, bus, dev, func, P2P_BUSSES_NUM);
+
+		pPciAgent->p2pPrimBusNum = (pciData & PBM_PRIME_BUS_NUM_MASK) >> PBM_PRIME_BUS_NUM_OFFS;
+
+		pPciAgent->p2pSecBusNum = (pciData & PBM_SEC_BUS_NUM_MASK) >> PBM_SEC_BUS_NUM_OFFS;
+
+		pPciAgent->p2pSubBusNum = (pciData & PBM_SUB_BUS_NUM_MASK) >> PBM_SUB_BUS_NUM_OFFS;
+
+		pPciAgent->p2pSecLatencyTimer = (pciData & PBM_SEC_LAT_TMR_MASK) >> PBM_SEC_LAT_TMR_OFFS;
+
+		/* Read  P2P_IO_BASE_LIMIT_SEC_STATUS */
+		pciData = mvPciIfConfigRead(pciIf, bus, dev, func, P2P_IO_BASE_LIMIT_SEC_STATUS);
+
+		pPciAgent->p2pSecStatus = (pciData & PIBLSS_SEC_STATUS_MASK) >> PIBLSS_SEC_STATUS_OFFS;
+
+		pPciAgent->p2pIObase = (pciData & PIBLSS_IO_BASE_MASK) << PIBLSS_IO_LIMIT_OFFS;
+
+		/* clear low address (should be zero) */
+		pPciAgent->p2pIObase &= PIBLSS_HIGH_ADDR_MASK;
+
+		pPciAgent->p2pIOLimit = (pciData & PIBLSS_IO_LIMIT_MASK);
+
+		/* fill low address with 0xfff */
+		pPciAgent->p2pIOLimit |= PIBLSS_LOW_ADDR_MASK;
+
+		switch ((pciData & PIBLSS_ADD_CAP_MASK) >> PIBLSS_ADD_CAP_OFFS) {
+		case PIBLSS_ADD_CAP_16BIT:
+
+			pPciAgent->bIO32 = MV_FALSE;
+
+			break;
+		case PIBLSS_ADD_CAP_32BIT:
+
+			pPciAgent->bIO32 = MV_TRUE;
+
+			/* Read  P2P_IO_BASE_LIMIT_UPPER_16 */
+			pciData = mvPciIfConfigRead(pciIf, bus, dev, func, P2P_IO_BASE_LIMIT_UPPER_16);
+
+			pPciAgent->p2pIObase |= (pciData & PRBU_IO_UPP_BASE_MASK) << PRBU_IO_UPP_LIMIT_OFFS;
+
+			pPciAgent->p2pIOLimit |= (pciData & PRBU_IO_UPP_LIMIT_MASK);
+
+			break;
+		}
+
+		/* Read  P2P_MEM_BASE_LIMIT */
+		pciData = mvPciIfConfigRead(pciIf, bus, dev, func, P2P_MEM_BASE_LIMIT);
+
+		pPciAgent->p2pMemBase = (pciData & PMBL_MEM_BASE_MASK) << PMBL_MEM_LIMIT_OFFS;
+
+		/* clear low address */
+		pPciAgent->p2pMemBase &= PMBL_HIGH_ADDR_MASK;
+
+		pPciAgent->p2pMemLimit = (pciData & PMBL_MEM_LIMIT_MASK);
+
+		/* add 0xfffff */
+		pPciAgent->p2pMemLimit |= PMBL_LOW_ADDR_MASK;
+
+		/* Read  P2P_PREF_MEM_BASE_LIMIT */
+		pciData = mvPciIfConfigRead(pciIf, bus, dev, func, P2P_PREF_MEM_BASE_LIMIT);
+
+		pPciAgent->p2pPrefMemBase = (pciData & PRMBL_PREF_MEM_BASE_MASK) << PRMBL_PREF_MEM_LIMIT_OFFS;
+
+		/* get high address only */
+		pPciAgent->p2pPrefMemBase &= PRMBL_HIGH_ADDR_MASK;
+
+		pPciAgent->p2pPrefMemLimit = (pciData & PRMBL_PREF_MEM_LIMIT_MASK);
+
+		/* add 0xfffff */
+		pPciAgent->p2pPrefMemLimit |= PRMBL_LOW_ADDR_MASK;
+
+		switch (pciData & PRMBL_ADD_CAP_MASK) {
+		case PRMBL_ADD_CAP_32BIT:
+
+			pPciAgent->bPrefMem64 = MV_FALSE;
+
+			/* Read  P2P_PREF_BASE_UPPER_32 */
+			pPciAgent->p2pPrefBaseUpper32Bits = 0;
+
+			/* Read  P2P_PREF_LIMIT_UPPER_32 */
+			pPciAgent->p2pPrefLimitUpper32Bits = 0;
+
+			break;
+		case PRMBL_ADD_CAP_64BIT:
+
+			pPciAgent->bPrefMem64 = MV_TRUE;
+
+			/* Read  P2P_PREF_BASE_UPPER_32 */
+			pPciAgent->p2pPrefBaseUpper32Bits = mvPciIfConfigRead(pciIf,
+							    bus, dev, func,
+							    P2P_PREF_BASE_UPPER_32);
+
+			/* Read  P2P_PREF_LIMIT_UPPER_32 */
+			pPciAgent->p2pPrefLimitUpper32Bits = mvPciIfConfigRead(pciIf,
+							     bus, dev, func,
+							     P2P_PREF_LIMIT_UPPER_32);
+
+			break;
+
+		}
+
+	} else {		/* no bridge */
+
+		/* Read  PCI_SUBSYS_ID_AND_SUBSYS_VENDOR_ID */
+		pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_SUBSYS_ID_AND_SUBSYS_VENDOR_ID);
+
+		pPciAgent->subSysVenID = (pciData & PSISVIR_VENID_MASK) >> PSISVIR_VENID_OFFS;
+		pPciAgent->subSysID = (pciData & PSISVIR_DEVID_MASK) >> PSISVIR_DEVID_OFFS;
+
+		/* Read  PCI_EXPANSION_ROM_BASE_ADDR_REG */
+		pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_EXPANSION_ROM_BASE_ADDR_REG);
+
+		if (pciData & PERBAR_EXPROMEN)
+			pPciAgent->isExpRom = MV_TRUE;
+		else
+			pPciAgent->isExpRom = MV_FALSE;
+
+		pPciAgent->expRomAddr = (pciData & PERBAR_BASE_MASK) >> PERBAR_BASE_OFFS;
+	}
+
+	if (MV_TRUE == pPciAgent->isCapListSupport) {
+		/* Read  PCI_CAPABILTY_LIST_POINTER */
+		pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_CAPABILTY_LIST_POINTER);
+
+		pPciAgent->capListPointer = (pciData & PCLPR_CAPPTR_MASK) >> PCLPR_CAPPTR_OFFS;
+	}
+
+	/* Read  PCI_INTERRUPT_PIN_AND_LINE */
+	pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_INTERRUPT_PIN_AND_LINE);
+
+	pPciAgent->irqLine = (pciData & PIPLR_INTLINE_MASK) >> PIPLR_INTLINE_OFFS;
+
+	pPciAgent->intPin = (MV_PCI_INT_PIN) (pciData & PIPLR_INTPIN_MASK) >> PIPLR_INTPIN_OFFS;
+
+	pPciAgent->minGrant = (pciData & PIPLR_MINGRANT_MASK) >> PIPLR_MINGRANT_OFFS;
+	pPciAgent->maxLatency = (pciData & PIPLR_MAXLATEN_MASK) >> PIPLR_MAXLATEN_OFFS;
+
+	mvPciClassNameGet(pPciAgent->baseClassCode, (MV_8 *) pPciAgent->type);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* pciDetectDeviceBars - Detect a pci device bars
+*
+* DESCRIPTION:
+*	This function detects all pci agent bars
+*
+* INPUT:
+*	pciIf		- PCI Interface
+*	bus		- Bus number
+*	dev		- Device number
+*	func		- Function number
+*
+* OUTPUT:
+*	pPciAgent	- pointer to the pci agent filled with its information
+*
+* RETURN:
+*	Detected bars number
+*
+*******************************************************************************/
+static MV_U32 pciDetectDeviceBars(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_PCI_DEVICE *pPciAgent)
+{
+	MV_U32 pciData, barIndex, detectedBar = 0;
+	MV_U32 tmpBaseHigh = 0, tmpBaseLow = 0;
+	MV_U32 pciMaxBars = 0;
+
+	pPciAgent->barsNum = 0;
+
+	/* check if we are bridge */
+	if ((pPciAgent->baseClassCode == PCI_BRIDGE_CLASS) && (pPciAgent->subClassCode == P2P_BRIDGE_SUB_CLASS_CODE))
+		pciMaxBars = 2;
+	else			/* no bridge */
+		pciMaxBars = 6;
+
+	/* read this device pci bars */
+	for (barIndex = 0; barIndex < pciMaxBars; barIndex++) {
+		/* Read  PCI_MEMORY_BAR_BASE_ADDR */
+		tmpBaseLow = pciData = mvPciIfConfigRead(pciIf, bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex));
+
+		pPciAgent->pciBar[detectedBar].barOffset = PCI_MEMORY_BAR_BASE_ADDR(barIndex);
+
+		/* check if the bar is 32bit or 64bit bar */
+		switch (pciData & PBBLR_TYPE_MASK) {
+		case PBBLR_TYPE_32BIT_ADDR:
+			pPciAgent->pciBar[detectedBar].barType = PCI_32BIT_BAR;
+			break;
+		case PBBLR_TYPE_64BIT_ADDR:
+			pPciAgent->pciBar[detectedBar].barType = PCI_64BIT_BAR;
+			break;
+		}
+
+		/* check if it is memory or IO bar */
+		if (pciData & PBBLR_IOSPACE)
+			pPciAgent->pciBar[detectedBar].barMapping = PCI_IO_BAR;
+		else
+			pPciAgent->pciBar[detectedBar].barMapping = PCI_MEMORY_BAR;
+
+		/* if it is memory bar then check if it is prefetchable */
+		if (PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping) {
+			if (pciData & PBBLR_PREFETCH_EN)
+				pPciAgent->pciBar[detectedBar].isPrefetchable = MV_TRUE;
+			else
+				pPciAgent->pciBar[detectedBar].isPrefetchable = MV_FALSE;
+
+			pPciAgent->pciBar[detectedBar].barBaseLow = pciData & PBBLR_MEM_BASE_MASK;
+		} else {	/* IO Bar */
+
+			pPciAgent->pciBar[detectedBar].barBaseLow = pciData & PBBLR_IO_BASE_MASK;
+		}
+
+		pPciAgent->pciBar[detectedBar].barBaseHigh = 0;
+
+		if (PCI_64BIT_BAR == pPciAgent->pciBar[detectedBar].barType) {
+			barIndex++;
+
+			tmpBaseHigh = pPciAgent->pciBar[detectedBar].barBaseHigh =
+					      mvPciIfConfigRead(pciIf, bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex));
+		}
+
+		/* calculating full base address (64bit) */
+		pPciAgent->pciBar[detectedBar].barBaseAddr = (MV_U64) pPciAgent->pciBar[detectedBar].barBaseHigh;
+
+		pPciAgent->pciBar[detectedBar].barBaseAddr <<= 32;
+
+		pPciAgent->pciBar[detectedBar].barBaseAddr |= (MV_U64) pPciAgent->pciBar[detectedBar].barBaseLow;
+
+		/* get the sizes of the the bar */
+
+		pPciAgent->pciBar[detectedBar].barSizeHigh = 0;
+
+		if ((PCI_64BIT_BAR == pPciAgent->pciBar[detectedBar].barType) &&
+				(PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping)) {
+			/* write oxffffffff to the bar to get the size */
+			/* start with sizelow ( original value was saved in tmpBaseLow ) */
+			mvPciIfConfigWrite(pciIf,
+					   bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex - 1), 0xffffffff);
+
+			/* read size */
+			pPciAgent->pciBar[detectedBar].barSizeLow =
+				mvPciIfConfigRead(pciIf, bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex - 1));
+
+			/* restore original value */
+			mvPciIfConfigWrite(pciIf,
+					   bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex - 1), tmpBaseLow);
+
+			/* now do the same for BaseHigh */
+
+			/* write oxffffffff to the bar to get the size */
+			mvPciIfConfigWrite(pciIf, bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex), 0xffffffff);
+
+			/* read size */
+			pPciAgent->pciBar[detectedBar].barSizeHigh =
+				mvPciIfConfigRead(pciIf, bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex));
+
+			/* restore original value */
+			mvPciIfConfigWrite(pciIf,
+					   bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex), tmpBaseHigh);
+
+			if ((0 == pPciAgent->pciBar[detectedBar].barSizeLow) &&
+					(0 == pPciAgent->pciBar[detectedBar].barSizeHigh)) {
+				/* this bar is not applicable for this device,
+				   ignore all previous settings and check the next bar */
+
+				/* we though this was a 64bit bar , and it seems this
+				   was wrong ! so decrement barIndex */
+				barIndex--;
+				continue;
+			}
+
+			/* calculate the full 64 bit size  */
+
+			if (0 != pPciAgent->pciBar[detectedBar].barSizeHigh) {
+				pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK;
+
+				pPciAgent->pciBar[detectedBar].barSizeLow =
+					~pPciAgent->pciBar[detectedBar].barSizeLow + 1;
+
+				pPciAgent->pciBar[detectedBar].barSizeHigh = 0;
+
+			} else {
+
+				pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK;
+
+				pPciAgent->pciBar[detectedBar].barSizeLow =
+					~pPciAgent->pciBar[detectedBar].barSizeLow + 1;
+
+				pPciAgent->pciBar[detectedBar].barSizeHigh = 0;
+
+			}
+
+		} else {	/* 32bit bar */
+
+			/* write oxffffffff to the bar to get the size */
+			mvPciIfConfigWrite(pciIf, bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex), 0xffffffff);
+
+			/* read size */
+			pPciAgent->pciBar[detectedBar].barSizeLow =
+				mvPciIfConfigRead(pciIf, bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex));
+
+			if (0 == pPciAgent->pciBar[detectedBar].barSizeLow) {
+				/* this bar is not applicable for this device,
+				   ignore all previous settings and check the next bar */
+				continue;
+			}
+
+			/* restore original value */
+			mvPciIfConfigWrite(pciIf, bus, dev, func, PCI_MEMORY_BAR_BASE_ADDR(barIndex), tmpBaseLow);
+
+			/* calculate size low */
+
+			if (PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping)
+				pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK;
+			else
+				pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_IO_BASE_MASK;
+
+			pPciAgent->pciBar[detectedBar].barSizeLow =
+				~pPciAgent->pciBar[detectedBar].barSizeLow + 1;
+
+			pPciAgent->pciBar[detectedBar].barSizeHigh = 0;
+			pPciAgent->pciBar[detectedBar].barSize =
+				(MV_U64) pPciAgent->pciBar[detectedBar].barSizeLow;
+
+		}
+
+		/* we are here ! this means we have already detected a bar for
+		   this device , now move on */
+
+		detectedBar++;
+		pPciAgent->barsNum++;
+	}
+
+	return detectedBar;
+}
+
+/*******************************************************************************
+* mvPciClassNameGet - get PCI  class name
+*
+* DESCRIPTION:
+*	This function returns the PCI class name
+*
+* INPUT:
+*	baseClassCode	- Base Class Code.
+*
+* OUTPUT:
+*	pType		- the class name
+*
+* RETURN:
+*	MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPciClassNameGet(MV_U32 baseClassCode, MV_8 *pType)
+{
+	switch (baseClassCode) {
+	case 0x0:
+		strcpy(pType, "Old generation device");
+		break;
+	case 0x1:
+		strcpy(pType, "Mass storage controller");
+		break;
+	case 0x2:
+		strcpy(pType, "Network controller");
+		break;
+	case 0x3:
+		strcpy(pType, "Display controller");
+		break;
+	case 0x4:
+		strcpy(pType, "Multimedia device");
+		break;
+	case 0x5:
+		strcpy(pType, "Memory controller");
+		break;
+	case 0x6:
+		strcpy(pType, "Bridge Device");
+		break;
+	case 0x7:
+		strcpy(pType, "Simple Communication controllers");
+		break;
+	case 0x8:
+		strcpy(pType, "Base system peripherals");
+		break;
+	case 0x9:
+		strcpy(pType, "Input Devices");
+		break;
+	case 0xa:
+		strcpy(pType, "Docking stations");
+		break;
+	case 0xb:
+		strcpy(pType, "Processors");
+		break;
+	case 0xc:
+		strcpy(pType, "Serial bus controllers");
+		break;
+	case 0xd:
+		strcpy(pType, "Wireless controllers");
+		break;
+	case 0xe:
+		strcpy(pType, "Intelligent I/O controllers");
+		break;
+	case 0xf:
+		strcpy(pType, "Satellite communication controllers");
+		break;
+	case 0x10:
+		strcpy(pType, "Encryption/Decryption controllers");
+		break;
+	case 0x11:
+		strcpy(pType, "Data acquisition and signal processing controllers");
+		break;
+	default:
+		strcpy(pType, "Unknown device");
+		break;
+	}
+
+	return MV_OK;
+
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/pci-if/pci_util/mvPciUtils.h b/arch/arm/plat-feroceon/mv_hal/pci-if/pci_util/mvPciUtils.h
new file mode 100755
index 0000000..472c616
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pci-if/pci_util/mvPciUtils.h
@@ -0,0 +1,303 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		Documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvPciUtilsh
+#define __INCmvPciUtilsh
+
+/*
+This module only support scanning of Header type 00h of pci devices
+There is no suppotr for Header type 01h of pci devices  ( PCI bridges )
+*/
+
+/* includes */
+#include "mvCommon.h"
+#include "mvSysHwConfig.h"
+
+#include "pci-if/mvPciIf.h"
+#include "pci-if/mvPciIfRegs.h"
+
+/* PCI base address low bar mask */
+#define PCI_ERROR_CODE                      0xffffffff
+
+#define PCI_BRIDGE_CLASS					0x6
+#define P2P_BRIDGE_SUB_CLASS_CODE			0x4
+
+#define P2P_BUSSES_NUM						0x18
+#define P2P_IO_BASE_LIMIT_SEC_STATUS		0x1C
+#define P2P_MEM_BASE_LIMIT					0x20
+#define P2P_PREF_MEM_BASE_LIMIT				0x24
+#define P2P_PREF_BASE_UPPER_32				0x28
+#define P2P_PREF_LIMIT_UPPER_32				0x2C
+#define P2P_IO_BASE_LIMIT_UPPER_16			0x30
+#define P2P_EXP_ROM							0x38
+
+/* P2P_BUSSES_NUM  (PBM) */
+
+#define PBM_PRIME_BUS_NUM_OFFS				0
+#define PBM_PRIME_BUS_NUM_MASK				(0xff << PBM_PRIME_BUS_NUM_OFFS)
+
+#define PBM_SEC_BUS_NUM_OFFS				8
+#define PBM_SEC_BUS_NUM_MASK				(0xff << PBM_SEC_BUS_NUM_OFFS)
+
+#define PBM_SUB_BUS_NUM_OFFS				16
+#define PBM_SUB_BUS_NUM_MASK				(0xff << PBM_SUB_BUS_NUM_OFFS)
+
+#define PBM_SEC_LAT_TMR_OFFS				24
+#define PBM_SEC_LAT_TMR_MASK				(0xff << PBM_SEC_LAT_TMR_OFFS)
+
+/* P2P_IO_BASE_LIMIT_SEC_STATUS (PIBLSS) */
+
+#define PIBLSS_IO_BASE_OFFS					0
+#define PIBLSS_IO_BASE_MASK					(0xff << PIBLSS_IO_BASE_OFFS)
+
+#define PIBLSS_ADD_CAP_OFFS					0
+#define PIBLSS_ADD_CAP_MASK 				(0x3 << PIBLSS_ADD_CAP_OFFS)
+#define PIBLSS_ADD_CAP_16BIT 				(0x0 << PIBLSS_ADD_CAP_OFFS)
+#define PIBLSS_ADD_CAP_32BIT 				(0x1 << PIBLSS_ADD_CAP_OFFS)
+
+#define PIBLSS_LOW_ADDR_OFFS				0
+#define PIBLSS_LOW_ADDR_MASK				(0xFFF << PIBLSS_LOW_ADDR_OFFS)
+
+#define PIBLSS_HIGH_ADDR_OFFS				12
+#define PIBLSS_HIGH_ADDR_MASK				(0xF << PIBLSS_HIGH_ADDR_OFFS)
+
+#define PIBLSS_IO_LIMIT_OFFS				8
+#define PIBLSS_IO_LIMIT_MASK				(0xff << PIBLSS_IO_LIMIT_OFFS)
+
+#define PIBLSS_SEC_STATUS_OFFS				16
+#define PIBLSS_SEC_STATUS_MASK				(0xffff << PIBLSS_SEC_STATUS_OFFS)
+
+/* P2P_MEM_BASE_LIMIT (PMBL)*/
+
+#define PMBL_MEM_BASE_OFFS					0
+#define PMBL_MEM_BASE_MASK					(0xffff << PMBL_MEM_BASE_OFFS)
+
+#define PMBL_MEM_LIMIT_OFFS					16
+#define PMBL_MEM_LIMIT_MASK					(0xffff << PMBL_MEM_LIMIT_OFFS)
+
+#define PMBL_LOW_ADDR_OFFS					0
+#define PMBL_LOW_ADDR_MASK					(0xFFFFF << PMBL_LOW_ADDR_OFFS)
+
+#define PMBL_HIGH_ADDR_OFFS					20
+#define PMBL_HIGH_ADDR_MASK					(0xFFF << PMBL_HIGH_ADDR_OFFS)
+
+/* P2P_PREF_MEM_BASE_LIMIT (PRMBL) */
+
+#define PRMBL_PREF_MEM_BASE_OFFS			0
+#define PRMBL_PREF_MEM_BASE_MASK			(0xffff << PRMBL_PREF_MEM_BASE_OFFS)
+
+#define PRMBL_PREF_MEM_LIMIT_OFFS			16
+#define PRMBL_PREF_MEM_LIMIT_MASK			(0xffff<<PRMBL_PREF_MEM_LIMIT_OFFS)
+
+#define PRMBL_LOW_ADDR_OFFS					0
+#define PRMBL_LOW_ADDR_MASK					(0xFFFFF << PRMBL_LOW_ADDR_OFFS)
+
+#define PRMBL_HIGH_ADDR_OFFS				20
+#define PRMBL_HIGH_ADDR_MASK				(0xFFF << PRMBL_HIGH_ADDR_OFFS)
+
+#define PRMBL_ADD_CAP_OFFS					0
+#define PRMBL_ADD_CAP_MASK					(0xf << PRMBL_ADD_CAP_OFFS)
+#define PRMBL_ADD_CAP_32BIT					(0x0 << PRMBL_ADD_CAP_OFFS)
+#define PRMBL_ADD_CAP_64BIT					(0x1 << PRMBL_ADD_CAP_OFFS)
+
+/* P2P_IO_BASE_LIMIT_UPPER_16 (PIBLU) */
+
+#define PRBU_IO_UPP_BASE_OFFS				0
+#define PRBU_IO_UPP_BASE_MASK				(0xffff << PRBU_IO_UPP_BASE_OFFS)
+
+#define PRBU_IO_UPP_LIMIT_OFFS				16
+#define PRBU_IO_UPP_LIMIT_MASK				(0xffff << PRBU_IO_UPP_LIMIT_OFFS)
+
+/* typedefs */
+
+typedef enum _mvPciBarMapping {
+	PCI_MEMORY_BAR,
+	PCI_IO_BAR,
+	PCI_NO_MAPPING
+} MV_PCI_BAR_MAPPING;
+
+typedef enum _mvPciBarType {
+	PCI_32BIT_BAR,
+	PCI_64BIT_BAR
+} MV_PCI_BAR_TYPE;
+
+typedef enum _mvPciIntPin {
+	MV_PCI_INTA = 1,
+	MV_PCI_INTB = 2,
+	MV_PCI_INTC = 3,
+	MV_PCI_INTD = 4
+} MV_PCI_INT_PIN;
+
+typedef enum _mvPciHeader {
+	MV_PCI_STANDARD,
+	MV_PCI_PCI2PCI_BRIDGE
+} MV_PCI_HEADER;
+
+/* BAR structure */
+typedef struct _pciBar {
+	MV_U32 barOffset;
+	MV_U32 barBaseLow;
+	MV_U32 barBaseHigh;
+	MV_U32 barSizeLow;
+	MV_U32 barSizeHigh;
+	/* The 'barBaseAddr' is a 64-bit variable
+	   that will contain the TOTAL base address
+	   value achived by combining both the 'barBaseLow'
+	   and the 'barBaseHigh' parameters as follows:
+
+	   BIT: 63          31         0
+	   |           |         |
+	   barBaseHigh barBaseLow */
+	MV_U64 barBaseAddr;
+	/* The 'barSize' is a 64-bit variable
+	   that will contain the TOTAL size achived
+	   by combining both the 'barSizeLow' and
+	   the 'barSizeHigh' parameters as follows:
+
+	   BIT: 63          31         0
+	   |           |         |
+	   barSizeHigh barSizeLow
+
+	   NOTE: The total size described above
+	   is AFTER the size calculation as
+	   described in PCI spec rev2.2 */
+	MV_U64 barSize;
+	MV_BOOL isPrefetchable;
+	MV_PCI_BAR_TYPE barType;
+	MV_PCI_BAR_MAPPING barMapping;
+
+} PCI_BAR;
+
+/* Device information structure */
+typedef struct _mvPciDevice {
+	/* Device specific information */
+	MV_U32 busNumber;	/* Pci agent bus number */
+	MV_U32 deviceNum;	/* Pci agent device number */
+	MV_U32 function;	/* Pci agent function number */
+
+	MV_U32 venID;		/* Pci agent Vendor ID */
+	MV_U32 deviceID;	/* Pci agent Device ID */
+
+	MV_BOOL isFastB2BCapable;	/* Capability of Fast Back to Back
+					   transactions */
+	MV_BOOL isCapListSupport;	/* Support of Capability list */
+	MV_BOOL is66MHZCapable;	/* 66MHZ support */
+
+	MV_U32 baseClassCode;	/* Pci agent base Class Code */
+	MV_U32 subClassCode;	/* Pci agent sub Class Code */
+	MV_U32 progIf;	/* Pci agent Programing interface */
+	MV_U32 revisionID;
+
+	PCI_BAR pciBar[6];	/* Pci agent bar list */
+
+	MV_U32 p2pPrimBusNum;	/* P2P Primary Bus number */
+	MV_U32 p2pSecBusNum;	/* P2P Secondary Bus Number */
+	MV_U32 p2pSubBusNum;	/* P2P Subordinate bus Number */
+	MV_U32 p2pSecLatencyTimer;	/* P2P Econdary Latency Timer */
+	MV_U32 p2pIObase;	/* P2P IO Base */
+	MV_U32 p2pIOLimit;	/* P2P IO Linit */
+	MV_BOOL bIO32;
+	MV_U32 p2pSecStatus;	/* P2P Secondary Status */
+	MV_U32 p2pMemBase;	/* P2P Memory Space */
+	MV_U32 p2pMemLimit;	/* P2P Memory Limit */
+	MV_U32 p2pPrefMemBase;	/* P2P Prefetchable Mem Base */
+	MV_U32 p2pPrefMemLimit;	/* P2P Prefetchable Memory Limit */
+	MV_BOOL bPrefMem64;
+	MV_U32 p2pPrefBaseUpper32Bits;	/* P2P Prefetchable upper 32 bits */
+	MV_U32 p2pPrefLimitUpper32Bits;	/* P2P prefetchable limit upper 32 */
+
+	MV_U32 pciCacheLine;	/* Pci agent cache line */
+	MV_U32 pciLatencyTimer;	/* Pci agent Latency timer  */
+	MV_PCI_HEADER pciHeader;	/* Pci agent header type */
+	MV_BOOL isMultiFunction;	/* Multi function support */
+	MV_BOOL isBISTCapable;	/* Self test capable */
+
+	MV_U32 subSysID;	/* Sub System ID */
+	MV_U32 subSysVenID;	/* Sub System Vendor ID */
+
+	MV_BOOL isExpRom;	/* Expantion Rom support */
+	MV_U32 expRomAddr;	/* Expantion Rom pointer */
+
+	MV_U32 capListPointer;	/* Capability list pointer */
+
+	MV_U32 irqLine;	/* IRQ line  */
+	MV_PCI_INT_PIN intPin;	/* Interrupt pin */
+	MV_U32 minGrant;	/* Minimum grant */
+	MV_U32 maxLatency;	/* Maximum latency */
+
+	MV_U32 funtionsNum;	/* pci agent total functions number */
+
+	MV_U32 barsNum;
+	MV_U8 type[60];	/* class name of the pci agent */
+
+} MV_PCI_DEVICE;
+
+/* PCI gloabl functions */
+MV_STATUS mvPciClassNameGet(MV_U32 classCode, MV_8 *pType);
+
+/* Performs a full scan on both PCIs and returns all possible details on the
+   agents found on the bus. */
+MV_STATUS mvPciScan(MV_U32 pciIf, MV_PCI_DEVICE *pPciAgents, MV_U32 *pPciAgentsNum);
+
+#endif /* #ifndef __INCmvPciUtilsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/pex/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/pex/mvCompVer.txt
new file mode 100755
index 0000000..38a9264
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pex/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.4

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/pex/mvPex.c b/arch/arm/plat-feroceon/mv_hal/pex/mvPex.c
new file mode 100755
index 0000000..d9233bb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pex/mvPex.c
@@ -0,0 +1,1094 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysPexConfig.h"
+#include "mvPexRegs.h"
+/* #include "pci-if/mvPciIf.h" */
+#include "mvPex.h"
+#include "mvSysPex.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+static MV_PEX_HAL_DATA pexHalData[MV_PEX_MAX_IF];
+
+MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType, MV_PEX_HAL_DATA *halData)
+{
+	MV_PEX_MODE pexMode;
+	MV_U32 regVal;
+	MV_U32 status;
+	MV_U16 ctrlModel, phyRegVal;
+
+	mvOsMemcpy(&pexHalData[pexIf], halData, sizeof(MV_PEX_HAL_DATA));
+
+	/* First implement Guideline (GL# PCI Express-2) Wrong Default Value    */
+	/* to Transmitter Output Current (TXAMP) Relevant for: 88F5181-A1/B0/B1 */
+	/* and 88F5281-B0 and above, 88F5182, 88F5082, 88F5181L, 88F6082/L      */
+	ctrlModel = pexHalData[pexIf].ctrlModel;
+	if ((ctrlModel != MV_1281_DEV_ID) &&
+			(ctrlModel != MV_6281_DEV_ID) &&
+			(ctrlModel != MV_6282_DEV_ID) &&
+			(ctrlModel != MV_6280_DEV_ID) &&
+			(ctrlModel != MV_6192_DEV_ID) &&
+			(ctrlModel != MV_6190_DEV_ID) &&
+			(ctrlModel != MV_6180_DEV_ID) &&
+			(ctrlModel != MV_6183_DEV_ID) &&
+			(ctrlModel != MV_6183L_DEV_ID) &&
+			(ctrlModel != MV_78100_DEV_ID) &&
+			(ctrlModel != MV_78200_DEV_ID) &&
+			(ctrlModel != MV_76100_DEV_ID) &&
+			(ctrlModel != MV_6323_DEV_ID) &&
+			(ctrlModel != MV_6322_DEV_ID) &&
+			(ctrlModel != MV_6321_DEV_ID) &&
+			(ctrlModel != MV_78XX0_DEV_ID) &&
+			(ctrlModel != MV_6510_DEV_ID) &&
+			(ctrlModel != MV_6530_DEV_ID) && (ctrlModel != MV_6550_DEV_ID) && (ctrlModel != MV_6560_DEV_ID)) {
+
+		/* Read current value of TXAMP */
+		MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), 0x80820000);	/* Write the read command   */
+
+		regVal = MV_REG_READ(PEX_PHY_ACCESS_REG(pexIf));	/* Extract the data         */
+
+		/* Prepare new data for write */
+		regVal &= ~0x7;	/* Clear bits [2:0]         */
+		regVal |= 0x4;	/* Set the new value        */
+		regVal &= ~0x80000000;	/* Set "write" command      */
+		MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), regVal);	/* Write the write command  */
+	} else {
+		/* Implement 1.0V termination GL for 88F1281 device only */
+		/* BIT0 - Common mode feedback */
+		/* BIT3 - TxBuf, extra drive for 1.0V termination */
+		if (ctrlModel == MV_1281_DEV_ID) {
+			MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), 0x80860000);	/* Write the read command   */
+			regVal = MV_REG_READ(0x41b00);	/* Extract the data         */
+			regVal |= (BIT0 | BIT3);
+			regVal &= ~0x80000000;	/* Set "write" command      */
+			MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), regVal);	/* Write the write command  */
+
+			MV_REG_WRITE(0x31b00, 0x80860000);	/* Write the read command   */
+			regVal = MV_REG_READ(0x31b00);	/* Extract the data         */
+			regVal |= (BIT0 | BIT3);
+			regVal &= ~0x80000000;	/* Set "write" command      */
+			MV_REG_WRITE(0x31b00, regVal);	/* Write the write command  */
+		}
+	}
+	if ((ctrlModel == MV_6281_DEV_ID) ||
+			(ctrlModel == MV_6282_DEV_ID) ||
+			(ctrlModel == MV_6280_DEV_ID) ||
+			(ctrlModel == MV_6192_DEV_ID) || (ctrlModel == MV_6190_DEV_ID) || (ctrlModel == MV_6180_DEV_ID)) {
+		regVal = MV_REG_READ(0x100e4);	/* This register currently doesn't appear in the FS */
+		regVal |= 0x3 << 25;
+		MV_REG_WRITE(0x100e4, regVal);
+	}
+
+	if (ctrlModel == MV_6282_DEV_ID) {
+		mvPexPhyRegRead(pexIf, 0x92, &phyRegVal);
+		phyRegVal &= ~(0x80F0);
+		phyRegVal |= 0x8080;
+		mvPexPhyRegWrite(pexIf, 0x92, phyRegVal);
+	} else if ((ctrlModel == MV_6510_DEV_ID) ||
+			(ctrlModel == MV_6530_DEV_ID) || (ctrlModel == MV_6550_DEV_ID) || (ctrlModel == MV_6560_DEV_ID)) {
+		mvPexPhyRegRead(pexIf, 0x92, &phyRegVal);
+		phyRegVal &= ~(0x80F0);
+		phyRegVal |= 0x8080;
+		mvPexPhyRegWrite(pexIf, 0x92, phyRegVal);
+	}
+
+	if (mvPexModeGet(pexIf, &pexMode) != MV_OK) {
+		mvOsPrintf("PEX init ERR. mvPexModeGet failed (pexType=%d)\n", pexMode.pexType);
+		return MV_ERROR;
+	}
+
+	/* Check that required PEX type is the one set in reset time */
+	if (pexType != pexMode.pexType) {
+		/* No Link. Shut down the Phy */
+		mvPexPhyPowerDown(pexIf);
+		mvOsPrintf("PEX init ERR. PEX type sampled mismatch (%d,%d)\n", pexType, pexMode.pexType);
+		return MV_ERROR;
+	}
+
+	if (MV_PEX_ROOT_COMPLEX == pexType) {
+		mvPexLocalBusNumSet(pexIf, PEX_HOST_BUS_NUM(pexIf));
+		mvPexLocalDevNumSet(pexIf, PEX_HOST_DEV_NUM(pexIf));
+
+		/* Local device master Enable */
+		mvPexMasterEnable(pexIf, MV_TRUE);
+
+		/* Local device slave Enable */
+		mvPexSlaveEnable(pexIf, mvPexLocalBusNumGet(pexIf), mvPexLocalDevNumGet(pexIf), MV_TRUE);
+		/* Interrupt disable */
+		status = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_STATUS_AND_COMMAND));
+		status |= PXSAC_INT_DIS;
+		MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_STATUS_AND_COMMAND), status);
+	} else {
+		MV_REG_WRITE(PEX_DBG_CTRL_REG(pexIf), 0xF63F0C0);
+	}
+
+	mvSysPexCpuIfEnable(pexIf);
+	/* now wait 1 ms to be sure the link is valid (spec compliant) */
+	mvOsDelay(1);
+	/* Check if we have link */
+	if (MV_REG_READ(PEX_STATUS_REG(pexIf)) & PXSR_DL_DOWN) {
+		mvOsPrintf("PEX%d interface detected no Link.\n", pexIf);
+		return MV_NO_SUCH;
+	}
+
+	if (MV_PEX_WITDH_X1 == pexMode.pexWidth)
+		mvOsPrintf("PEX%d interface detected Link X1\n", pexIf);
+	else
+		mvOsPrintf("PEX%d interface detected Link X4\n", pexIf);
+
+#ifdef PCIE_VIRTUAL_BRIDGE_SUPPORT
+	mvPexVrtBrgInit(pexIf);
+#endif
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexModeGet - Get Pex Mode
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pexIf   - PEX interface number.
+*
+* OUTPUT:
+*       pexMode - Pex mode structure
+*
+* RETURN:
+*       MV_OK on success , MV_ERROR otherwise
+*
+*******************************************************************************/
+MV_U32 mvPexModeGet(MV_U32 pexIf, MV_PEX_MODE *pexMode)
+{
+	MV_U32 pexData;
+
+	if (pexIf >= MV_PEX_MAX_IF)
+		return MV_BAD_PARAM;
+
+	/* Parameter checking   */
+#if 0
+	if (PEX_DEFAULT_IF != pexIf) {
+		if (pexIf >= pexHalData[pexIf].maxPexIf) {
+			mvOsPrintf("mvPexModeGet: ERR. Invalid PEX interface %d\n", pexIf);
+			return MV_ERROR;
+		}
+	}
+#endif
+	pexData = MV_REG_READ(PEX_CTRL_REG(pexIf));
+
+	switch (pexData & PXCR_DEV_TYPE_CTRL_MASK) {
+	case PXCR_DEV_TYPE_CTRL_CMPLX:
+		pexMode->pexType = MV_PEX_ROOT_COMPLEX;
+		break;
+	case PXCR_DEV_TYPE_CTRL_POINT:
+		pexMode->pexType = MV_PEX_END_POINT;
+		break;
+
+	}
+
+	/* Check if we have link */
+	if (MV_REG_READ(PEX_STATUS_REG(pexIf)) & PXSR_DL_DOWN) {
+		pexMode->pexLinkUp = MV_FALSE;
+
+		/* If there is no link, the auto negotiation data is worthless */
+		pexMode->pexWidth = MV_PEX_WITDH_INVALID;
+	} else {
+		pexMode->pexLinkUp = MV_TRUE;
+
+		/* We have link. The link width is now valid */
+		pexData = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG));
+		pexMode->pexWidth = ((pexData & PXLCSR_NEG_LNK_WDTH_MASK) >> PXLCSR_NEG_LNK_WDTH_OFFS);
+	}
+
+	return MV_OK;
+}
+
+/* PEX configuration space read write */
+
+/*******************************************************************************
+* mvPexConfigRead - Read from configuration space
+*
+* DESCRIPTION:
+*       This function performs a 32 bit read from PEX configuration space.
+*       It supports both type 0 and type 1 of Configuration Transactions
+*       (local and over bridge). In order to read from local bus segment, use
+*       bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers
+*       will result configuration transaction of type 1 (over bridge).
+*
+* INPUT:
+*       pexIf   - PEX interface number.
+*       bus     - PEX segment bus number.
+*       dev     - PEX device number.
+*       func    - Function number.
+*       regOffs - Register offset.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       32bit register data, 0xffffffff on error
+*
+*******************************************************************************/
+MV_U32 mvPexConfigRead(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff)
+{
+#if defined(PCIE_VIRTUAL_BRIDGE_SUPPORT)
+	return mvPexVrtBrgConfigRead(pexIf, bus, dev, func, regOff);
+}
+
+MV_U32 mvPexHwConfigRead(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff)
+{
+#endif
+	MV_U32 pexData = 0;
+	MV_U32 localDev, localBus;
+
+	if (pexIf >= MV_PEX_MAX_IF)
+		return 0xFFFFFFFF;
+
+	/* Parameter checking   */
+	if (PEX_DEFAULT_IF != pexIf) {
+		if (pexIf >= pexHalData[pexIf].maxPexIf) {
+			mvOsPrintf("mvPexConfigRead: ERR. Invalid PEX interface %d\n", pexIf);
+			return 0xFFFFFFFF;
+		}
+	}
+
+	if (dev >= MAX_PEX_DEVICES) {
+		DB(mvOsPrintf("mvPexConfigRead: ERR. device number illigal %d\n", dev));
+		return 0xFFFFFFFF;
+	}
+
+	if (func >= MAX_PEX_FUNCS) {
+		DB(mvOsPrintf("mvPexConfigRead: ERR. function num illigal %d\n", func));
+		return 0xFFFFFFFF;
+	}
+
+	if (bus >= MAX_PEX_BUSSES) {
+		DB(mvOsPrintf("mvPexConfigRead: ERR. bus number illigal %d\n", bus));
+		return MV_ERROR;
+	}
+
+	DB(mvOsPrintf("mvPexConfigRead: pexIf %d, bus %d, dev %d, func %d, regOff 0x%x\n",
+		      pexIf, bus, dev, func, regOff));
+
+	localDev = mvPexLocalDevNumGet(pexIf);
+	localBus = mvPexLocalBusNumGet(pexIf);
+
+	/* Speed up the process. In case on no link, return MV_ERROR */
+	if ((dev != localDev) || (bus != localBus)) {
+		pexData = MV_REG_READ(PEX_STATUS_REG(pexIf));
+
+		if ((pexData & PXSR_DL_DOWN))
+			return MV_ERROR;
+	}
+
+	/* in PCI Express we have only one device number */
+	/* and this number is the first number we encounter
+	   else that the localDev */
+	/* spec pex define return on config read/write on any device */
+	if (bus == localBus) {
+		if (localDev == 0) {
+			/* if local dev is 0 then the first number we encounter
+			   after 0 is 1 */
+			if ((dev != 1) && (dev != localDev))
+				return MV_ERROR;
+		} else {
+			/* if local dev is not 0 then the first number we encounter
+			   is 0 */
+
+			if ((dev != 0) && (dev != localDev))
+				return MV_ERROR;
+		}
+		if (func != 0)	/* i.e bridge */
+			return MV_ERROR;
+	}
+
+	/* Creating PEX address to be passed */
+	pexData = (bus << PXCAR_BUS_NUM_OFFS);
+	pexData |= (dev << PXCAR_DEVICE_NUM_OFFS);
+	pexData |= (func << PXCAR_FUNC_NUM_OFFS);
+	pexData |= (regOff & PXCAR_REG_NUM_MASK);	/* lgacy register space */
+	/* extended register space */
+	pexData |= (((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >>
+		     PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
+
+	pexData |= PXCAR_CONFIG_EN;
+
+	/* Write the address to the PEX configuration address register */
+	MV_REG_WRITE(PEX_CFG_ADDR_REG(pexIf), pexData);
+
+	DB(mvOsPrintf("mvPexConfigRead:address pexData=%x ", pexData));
+
+	/* In order to let the PEX controller absorbed the address of the read  */
+	/* transaction we perform a validity check that the address was written */
+	if (pexData != MV_REG_READ(PEX_CFG_ADDR_REG(pexIf)))
+		return MV_ERROR;
+
+	/* cleaning Master Abort */
+	MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_STATUS_AND_COMMAND), PXSAC_MABORT);
+#if 0
+	/* Guideline (GL# PCI Express-1) Erroneous Read Data on Configuration   */
+	/* This guideline is relevant for all devices except of the following devices:
+	   88F5281-BO and above, 88F5181L-A0 and above, 88F1281 A0 and above
+	   88F6183 A0 and above, 88F6183L  */
+	ctrlModel = pexHalData[pexIf].ctrlModel;
+	if (((dev != localDev) || (bus != localBus)) &&
+			(!(MV_5281_DEV_ID == ctrlModel) &&
+			 !((MV_5181_DEV_ID == ctrlModel) && (mvCtrlRevGet() >= MV_5181L_A0_REV)) &&
+			 !(MV_1281_DEV_ID == ctrlModel) &&
+			 !(MV_6183_DEV_ID == ctrlModel) &&
+			 !(MV_6183L_DEV_ID == ctrlModel) &&
+			 !(MV_6281_DEV_ID == ctrlModel) &&
+			 !(MV_6282_DEV_ID == ctrlModel) &&
+			 !(MV_6192_DEV_ID == ctrlModel) &&
+			 !(MV_6190_DEV_ID == ctrlModel) &&
+			 !(MV_6180_DEV_ID == ctrlModel) && !(MV_6280_DEV_ID == ctrlModel) && !(MV_78XX0_DEV_ID == ctrlModel)
+			)) {
+
+		/* PCI-Express configuration read work-around */
+
+		/* we will use one of the Punit (AHBToMbus) windows to access the xbar
+		   and read the data from there */
+		/*
+		   Need to configure the 2 free Punit (AHB to MBus bridge)
+		   address decoding windows:
+		   Configure the flash Window to handle Configuration space requests
+		   for PEX0/1:
+		   1.    write 0x7931/0x7941 to the flash window and the size,
+		   79-xbar attr (pci cfg), 3/4-xbar target (pex0/1), 1-WinEn
+		   2.    write base to flash window
+
+		   Configuration transactions from the CPU should write/read the data
+		   to/from address of the form:
+		   addr[31:28] = 0x5 (for PEX0) or 0x6 (for PEX1)
+		   addr[27:24] = extended register number
+		   addr[23:16] = bus number
+		   addr[15:11] = device number
+		   addr[10:8]   = function number
+		   addr[7:0]     = register number
+		 */
+
+#include "ctrlEnv/sys/mvAhbToMbus.h"
+		{
+			MV_U32 winNum;
+			MV_AHB_TO_MBUS_DEC_WIN originWin;
+			MV_U32 pciAddr = 0;
+			MV_U32 remapLow = 0, remapHigh = 0;
+
+			/*
+			   We will use DEV_CS2\Flash window for this workarround
+			 */
+
+			winNum = mvAhbToMbusWinTargetGet(PEX_CONFIG_RW_WA_TARGET);
+
+			/* save remap values if exist */
+			if ((1 == winNum) || (0 == winNum)) {
+				remapLow = MV_REG_READ(AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum));
+				remapHigh = MV_REG_READ(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum));
+
+			}
+
+			/* save the original window values */
+			mvAhbToMbusWinGet(winNum, &originWin);
+
+			if (PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES) {
+				/* set the window as xbar window */
+				if (pexIf) {
+					MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum),
+						     (0x7931 | (((originWin.addrWin.size >> 16) - 1)) << 16));
+				} else {
+					MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum),
+						     (0x7941 | (((originWin.addrWin.size >> 16) - 1)) << 16));
+				}
+
+				MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), originWin.addrWin.baseLow);
+
+				/*pciAddr = originWin.addrWin.baseLow; */
+				pciAddr = (MV_U32) CPU_MEMIO_UNCACHED_ADDR((MV_U32) originWin.addrWin.baseLow);
+
+			} else {
+				/* set the window as xbar window */
+				if (pexIf) {
+					MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum),
+						     (0x7931 | (((PEX_CONFIG_RW_WA_SIZE >> 16) - 1)) << 16));
+				} else {
+					MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum),
+						     (0x7941 | (((PEX_CONFIG_RW_WA_SIZE >> 16) - 1)) << 16));
+				}
+
+				MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), PEX_CONFIG_RW_WA_BASE);
+
+				pciAddr = (MV_U32) CPU_MEMIO_UNCACHED_ADDR(PEX_CONFIG_RW_WA_BASE);
+			}
+
+			/* remap should be as base */
+			if ((1 == winNum) || (0 == winNum)) {
+				MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum), pciAddr);
+				MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum), 0);
+
+			}
+
+			/* extended register space */
+			pciAddr |= (bus << 16);
+			pciAddr |= (dev << 11);
+			pciAddr |= (func << 8);
+			pciAddr |= (regOff & PXCAR_REG_NUM_MASK);	/* lgacy register space */
+
+			pexData = *(MV_U32 *) pciAddr;
+			pexData = MV_32BIT_LE(pexData);	/* Data always in LE */
+
+			/* restore the original window values */
+			mvAhbToMbusWinSet(winNum, &originWin);
+
+			/* restore original remap values */
+			if ((1 == winNum) || (0 == winNum)) {
+				MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum), remapLow);
+				MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum), remapHigh);
+
+			}
+		}
+	} else
+#endif
+	{
+		/* Read the Data returned in the PEX Data register */
+		pexData = MV_REG_READ(PEX_CFG_DATA_REG(pexIf));
+
+	}
+
+	DB(mvOsPrintf("mvPexConfigRead: got : %x \n", pexData));
+
+	return pexData;
+
+}
+
+/*******************************************************************************
+* mvPexConfigWrite - Write to configuration space
+*
+* DESCRIPTION:
+*       This function performs a 32 bit write to PEX configuration space.
+*       It supports both type 0 and type 1 of Configuration Transactions
+*       (local and over bridge). In order to write to local bus segment, use
+*       bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers
+*       will result configuration transaction of type 1 (over bridge).
+*
+* INPUT:
+*       pexIf   - PEX interface number.
+*       bus     - PEX segment bus number.
+*       dev     - PEX device number.
+*       func    - Function number.
+*       regOffs - Register offset.
+*       data    - 32bit data.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff, MV_U32 data)
+{
+#if defined(PCIE_VIRTUAL_BRIDGE_SUPPORT)
+	return mvPexVrtBrgConfigWrite(pexIf, bus, dev, func, regOff, data);
+}
+
+MV_STATUS mvPexHwConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff, MV_U32 data)
+{
+#endif
+	MV_U32 pexData = 0;
+	MV_U32 localDev, localBus;
+
+	if (pexIf >= MV_PEX_MAX_IF)
+		return MV_BAD_PARAM;
+
+	/* Parameter checking   */
+	if (PEX_DEFAULT_IF != pexIf) {
+		if (pexIf >= pexHalData[pexIf].maxPexIf) {
+			mvOsPrintf("mvPexConfigWrite: ERR. Invalid PEX interface %d\n", pexIf);
+			return MV_ERROR;
+		}
+	}
+
+	if (dev >= MAX_PEX_DEVICES) {
+		mvOsPrintf("mvPexConfigWrite: ERR. device number illigal %d\n", dev);
+		return MV_BAD_PARAM;
+	}
+
+	if (func >= MAX_PEX_FUNCS) {
+		mvOsPrintf("mvPexConfigWrite: ERR. function number illigal %d\n", func);
+		return MV_ERROR;
+	}
+
+	if (bus >= MAX_PEX_BUSSES) {
+		mvOsPrintf("mvPexConfigWrite: ERR. bus number illigal %d\n", bus);
+		return MV_ERROR;
+	}
+
+	localDev = mvPexLocalDevNumGet(pexIf);
+	localBus = mvPexLocalBusNumGet(pexIf);
+
+	/* in PCI Express we have only one device number other than ourselves */
+	/* and this number is the first number we encounter
+	   else than the localDev that can be any valid dev number */
+	/* pex spec define return on config read/write on any device */
+	if (bus == localBus) {
+		if (localDev == 0) {
+			/* if local dev is 0 then the first number we encounter
+			   after 0 is 1 */
+			if ((dev != 1) && (dev != localDev))
+				return MV_ERROR;
+		} else {
+			/* if local dev is not 0 then the first number we encounter
+			   is 0 */
+
+			if ((dev != 0) && (dev != localDev))
+				return MV_ERROR;
+		}
+
+	}
+
+	/* if we are not accessing ourselves , then check the link */
+	if ((dev != localDev) || (bus != localBus)) {
+		/* workarround */
+		/* when no link return MV_ERROR */
+
+		pexData = MV_REG_READ(PEX_STATUS_REG(pexIf));
+
+		if ((pexData & PXSR_DL_DOWN))
+			return MV_ERROR;
+	}
+
+	pexData = 0;
+
+	/* Creating PEX address to be passed */
+	pexData |= (bus << PXCAR_BUS_NUM_OFFS);
+	pexData |= (dev << PXCAR_DEVICE_NUM_OFFS);
+	pexData |= (func << PXCAR_FUNC_NUM_OFFS);
+	pexData |= (regOff & PXCAR_REG_NUM_MASK);	/* lgacy register space */
+	/* extended register space */
+	pexData |= (((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >>
+		     PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
+	pexData |= PXCAR_CONFIG_EN;
+
+	DB(mvOsPrintf("mvPexConfigWrite: If=%x bus=%x func=%x dev=%x regOff=%x data=%x \n",
+		      pexIf, bus, func, dev, regOff, data, pexData));
+
+	/* Write the address to the PEX configuration address register */
+	MV_REG_WRITE(PEX_CFG_ADDR_REG(pexIf), pexData);
+
+	/* Clear CPU pipe. Important where CPU can perform OOO execution */
+	CPU_PIPE_FLUSH;
+
+	/* In order to let the PEX controller absorbed the address of the read  */
+	/* transaction we perform a validity check that the address was written */
+	if (pexData != MV_REG_READ(PEX_CFG_ADDR_REG(pexIf)))
+		return MV_ERROR;
+
+	/* Write the Data passed to the PEX Data register */
+	MV_REG_WRITE(PEX_CFG_DATA_REG(pexIf), data);
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvPexMasterEnable - Enable/disale PEX interface master transactions.
+*
+* DESCRIPTION:
+*       This function performs read modified write to PEX command status
+*       (offset 0x4) to set/reset bit 2. After this bit is set, the PEX
+*       master is allowed to gain ownership on the bus, otherwise it is
+*       incapable to do so.
+*
+* INPUT:
+*       pexIf  - PEX interface number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexMasterEnable(MV_U32 pexIf, MV_BOOL enable)
+{
+	MV_U32 pexCommandStatus;
+	MV_U32 localBus;
+	MV_U32 localDev;
+
+	/* Parameter checking   */
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexMasterEnable: ERR. Invalid PEX interface %d\n", pexIf);
+		return MV_ERROR;
+	}
+
+	localBus = mvPexLocalBusNumGet(pexIf);
+	localDev = mvPexLocalDevNumGet(pexIf);
+
+	pexCommandStatus = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_STATUS_AND_COMMAND));
+
+	if (MV_TRUE == enable)
+		pexCommandStatus |= PXSAC_MASTER_EN;
+	else
+		pexCommandStatus &= ~PXSAC_MASTER_EN;
+
+	MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_STATUS_AND_COMMAND), pexCommandStatus);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexSlaveEnable - Enable/disale PEX interface slave transactions.
+*
+* DESCRIPTION:
+*       This function performs read modified write to PEX command status
+*       (offset 0x4) to set/reset bit 0 and 1. After those bits are set,
+*       the PEX slave is allowed to respond to PEX IO space access (bit 0)
+*       and PEX memory space access (bit 1).
+*
+* INPUT:
+*       pexIf  - PEX interface number.
+*       dev     - PEX device number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexSlaveEnable(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_BOOL enable)
+{
+	MV_U32 pexCommandStatus;
+	MV_U32 RegOffs;
+
+	/* Parameter checking   */
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexSlaveEnable: ERR. Invalid PEX interface %d\n", pexIf);
+		return MV_BAD_PARAM;
+	}
+	if (dev >= MAX_PEX_DEVICES) {
+		mvOsPrintf("mvPexLocalDevNumSet: ERR. device number illigal %d\n", dev);
+		return MV_BAD_PARAM;
+
+	}
+
+	RegOffs = PEX_STATUS_AND_COMMAND;
+
+	pexCommandStatus = mvPexConfigRead(pexIf, bus, dev, 0, RegOffs);
+
+	if (MV_TRUE == enable)
+		pexCommandStatus |= (PXSAC_IO_EN | PXSAC_MEM_EN);
+	else
+		pexCommandStatus &= ~(PXSAC_IO_EN | PXSAC_MEM_EN);
+
+	mvPexConfigWrite(pexIf, bus, dev, 0, RegOffs, pexCommandStatus);
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvPexLocalBusNumSet - Set PEX interface local bus number.
+*
+* DESCRIPTION:
+*       This function sets given PEX interface its local bus number.
+*       Note: In case the PEX interface is PEX-X, the information is read-only.
+*
+* INPUT:
+*       pexIf  - PEX interface number.
+*       busNum - Bus number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_NOT_ALLOWED in case PEX interface is PEX-X.
+*		MV_BAD_PARAM on bad parameters ,
+*       otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexLocalBusNumSet(MV_U32 pexIf, MV_U32 busNum)
+{
+	MV_U32 pexStatus;
+	MV_U32 localBus;
+	MV_U32 localDev;
+
+	/* Parameter checking   */
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexLocalBusNumSet: ERR. Invalid PEX interface %d\n", pexIf);
+		return MV_BAD_PARAM;
+	}
+	if (busNum >= MAX_PEX_BUSSES) {
+		mvOsPrintf("mvPexLocalBusNumSet: ERR. bus number illigal %d\n", busNum);
+		return MV_ERROR;
+	}
+
+	localBus = mvPexLocalBusNumGet(pexIf);
+	localDev = mvPexLocalDevNumGet(pexIf);
+
+	pexStatus = MV_REG_READ(PEX_STATUS_REG(pexIf));
+
+	pexStatus &= ~PXSR_PEX_BUS_NUM_MASK;
+
+	pexStatus |= (busNum << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
+
+	MV_REG_WRITE(PEX_STATUS_REG(pexIf), pexStatus);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexLocalBusNumGet - Get PEX interface local bus number.
+*
+* DESCRIPTION:
+*       This function gets the local bus number of a given PEX interface.
+*
+* INPUT:
+*       pexIf  - PEX interface number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Local bus number.0xffffffff on Error
+*
+*******************************************************************************/
+MV_U32 mvPexLocalBusNumGet(MV_U32 pexIf)
+{
+	MV_U32 pexStatus;
+
+	if (pexIf >= MV_PEX_MAX_IF)
+		return 0xFFFFFFFF;
+
+	/* Parameter checking   */
+	if (PEX_DEFAULT_IF != pexIf) {
+		if (pexIf >= pexHalData[pexIf].maxPexIf) {
+			mvOsPrintf("mvPexLocalBusNumGet: ERR. Invalid PEX interface %d\n", pexIf);
+			return 0xFFFFFFFF;
+		}
+	}
+
+	pexStatus = MV_REG_READ(PEX_STATUS_REG(pexIf));
+
+	pexStatus &= PXSR_PEX_BUS_NUM_MASK;
+
+	return (pexStatus >> PXSR_PEX_BUS_NUM_OFFS);
+}
+
+/*******************************************************************************
+* mvPexLocalDevNumSet - Set PEX interface local device number.
+*
+* DESCRIPTION:
+*       This function sets given PEX interface its local device number.
+*       Note: In case the PEX interface is PEX-X, the information is read-only.
+*
+* INPUT:
+*       pexIf  - PEX interface number.
+*       devNum - Device number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_NOT_ALLOWED in case PEX interface is PEX-X.
+*		MV_BAD_PARAM on bad parameters ,
+*       otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexLocalDevNumSet(MV_U32 pexIf, MV_U32 devNum)
+{
+	MV_U32 pexStatus;
+	MV_U32 localBus;
+	MV_U32 localDev;
+
+	if (pexIf >= MV_PEX_MAX_IF)
+		return MV_BAD_PARAM;
+
+	/* Parameter checking   */
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexLocalDevNumSet: ERR. Invalid PEX interface %d\n", pexIf);
+		return MV_BAD_PARAM;
+	}
+	if (devNum >= MAX_PEX_DEVICES) {
+		mvOsPrintf("mvPexLocalDevNumSet: ERR. device number illigal %d\n", devNum);
+		return MV_BAD_PARAM;
+	}
+
+	localBus = mvPexLocalBusNumGet(pexIf);
+	localDev = mvPexLocalDevNumGet(pexIf);
+
+	pexStatus = MV_REG_READ(PEX_STATUS_REG(pexIf));
+
+	pexStatus &= ~PXSR_PEX_DEV_NUM_MASK;
+
+	pexStatus |= (devNum << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
+
+	MV_REG_WRITE(PEX_STATUS_REG(pexIf), pexStatus);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexLocalDevNumGet - Get PEX interface local device number.
+*
+* DESCRIPTION:
+*       This function gets the local device number of a given PEX interface.
+*
+* INPUT:
+*       pexIf  - PEX interface number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Local device number. 0xffffffff on Error
+*
+*******************************************************************************/
+MV_U32 mvPexLocalDevNumGet(MV_U32 pexIf)
+{
+	MV_U32 pexStatus;
+
+	/* Parameter checking   */
+
+	if (PEX_DEFAULT_IF != pexIf) {
+		if (pexIf >= pexHalData[pexIf].maxPexIf) {
+			mvOsPrintf("mvPexLocalDevNumGet: ERR. Invalid PEX interface %d\n", pexIf);
+			return 0xFFFFFFFF;
+		}
+	}
+
+	pexStatus = MV_REG_READ(PEX_STATUS_REG(pexIf));
+
+	pexStatus &= PXSR_PEX_DEV_NUM_MASK;
+
+	return (pexStatus >> PXSR_PEX_DEV_NUM_OFFS);
+}
+
+MV_VOID mvPexPhyRegRead(MV_U32 pexIf, MV_U32 regOffset, MV_U16 *value)
+{
+
+	MV_U32 regAddr;
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexPhyRegRead: ERR. Invalid PEX interface %d\n", pexIf);
+		return;
+	}
+	regAddr = (BIT31 | ((regOffset & 0x3fff) << 16));
+	MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), regAddr);
+	*value = MV_REG_READ(PEX_PHY_ACCESS_REG(pexIf));
+}
+
+MV_VOID mvPexPhyRegWrite(MV_U32 pexIf, MV_U32 regOffset, MV_U16 value)
+{
+
+	MV_U32 regAddr;
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexPhyRegWrite: ERR. Invalid PEX interface %d\n", pexIf);
+		return;
+	}
+	regAddr = (((regOffset & 0x3fff) << 16) | value);
+	MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), regAddr);
+}
+
+/*******************************************************************************
+* mvPexActiveStateLinkPMEnable
+*
+* DESCRIPTION:
+*	Enable Active Link State Power Management
+*
+* INPUT:
+*	pexIf		- PEX interface number.
+*	enable		- MV_TRUE to enable ASPM, MV_FALSE to disable.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_OK on success , MV_ERROR otherwise
+*
+*******************************************************************************/
+MV_STATUS mvPexActiveStateLinkPMEnable(MV_U32 pexIf, MV_BOOL enable)
+{
+	MV_U32 reg;
+
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexActiveStateLinkPMEnable: ERR. Invalid PEX interface %d\n", pexIf);
+		return MV_ERROR;
+	}
+
+	reg = MV_REG_READ(PEX_PWR_MNG_EXT_REG(pexIf)) & ~PXPMER_L1_ASPM_EN_MASK;
+	if (enable == MV_TRUE)
+		reg |= PXPMER_L1_ASPM_EN_MASK;
+	MV_REG_WRITE(PEX_PWR_MNG_EXT_REG(pexIf), reg);
+
+	/* Enable / Disable L0/1 entry */
+	reg = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG))
+	      & ~PXLCSR_ASPM_CNT_MASK;
+	if (enable == MV_TRUE)
+		reg |= PXLCSR_ASPM_CNT_L0S_L1S_ENT_SUPP;
+	MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG), reg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexForceX1
+*
+* DESCRIPTION:
+*	shut down lanes 1-3 if recognize that attached to an x1 end-point
+* INPUT:
+*	pexIf		- PEX interface number.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*	MV_OK on success , MV_ERROR otherwise
+*
+*******************************************************************************/
+MV_U32 mvPexForceX1(MV_U32 pexIf)
+{
+	MV_U32 regData = 0;
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexForceX1: ERR. Invalid PEX interface %d\n", pexIf);
+		return MV_BAD_PARAM;
+	}
+
+	regData = MV_REG_READ(PEX_CTRL_REG(pexIf)) & ~(PXCR_CONF_LINK_MASK);
+	regData |= PXCR_CONF_LINK_X1;
+
+	MV_REG_WRITE(PEX_CTRL_REG(pexIf), regData);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexIfEnable
+*
+* DESCRIPTION:
+*	This function Enables PCI Express interface.
+*
+* INPUT:
+*	pexIf		-  PEX interface number.
+*	pexType		-  MV_PEX_ROOT_COMPLEX - root complex device
+*			   MV_PEX_END_POINT - end point device
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvPexIfEnable(MV_U32 pexIf, MV_PEX_TYPE pexType)
+{
+	/* Set pex mode incase S@R not exist */
+	if (pexType == MV_PEX_END_POINT) {
+		MV_REG_BIT_RESET(PEX_CTRL_REG(pexIf), PXCR_DEV_TYPE_CTRL_MASK);
+		/* Change pex mode in capability reg */
+		MV_REG_BIT_RESET(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_CAPABILITY_REG), BIT22);
+		MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_CAPABILITY_REG), BIT20);
+	} else {
+		MV_REG_BIT_SET(PEX_CTRL_REG(pexIf), PXCR_DEV_TYPE_CTRL_MASK);
+	}
+	return;
+}
+
+MV_VOID mvPexPhyPowerDown(MV_U32 pexIf)
+{
+	MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), 0x20800087);
+	return;
+}
+
+#if 0
+/*  These APIs will be removed, OS glue should call the mvCtrlPwerClkxxx() */
+/*  functions directly. */
+MV_BOOL mvPexIsPowerUp(MV_U32 pexIf)
+{
+	if (pexIf >= pexHalData[pexIf].maxPexIf) {
+		mvOsPrintf("mvPexIsPowerUp: ERR. Invalid PEX interface %d\n", pexIf);
+		return MV_FALSE;
+	}
+	return mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf);
+}
+
+MV_VOID mvPexPowerDown(MV_U32 pexIf)
+{
+	MV_U32 ctrlModel = pexHalData[pexIf].ctrlModel;
+
+	if ((ctrlModel == MV_78XX0_DEV_ID) ||
+			(ctrlModel == MV_76100_DEV_ID) || (ctrlModel == MV_78100_DEV_ID) || (ctrlModel == MV_78200_DEV_ID)) {
+		mvCtrlPwrClckSet(PEX_UNIT_ID, pexIf, MV_FALSE);
+	} else {
+		MV_REG_WRITE((0x41B00 - (pexIf) * 0x10000), 0x20800087);
+	}
+}
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/pex/mvPex.h b/arch/arm/plat-feroceon/mv_hal/pex/mvPex.h
new file mode 100755
index 0000000..5a20a29
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pex/mvPex.h
@@ -0,0 +1,216 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*		Redistributions of source code must retain the above copyright notice,
+			this list of conditions and the following disclaimer.
+
+	*		Redistributions in binary form must reproduce the above copyright
+			notice, this list of conditions and the following disclaimer in the
+			documentation and/or other materials provided with the distribution.
+
+	*		Neither the name of Marvell nor the names of its contributors may be
+			used to endorse or promote products derived from this software without
+			specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCPEXH
+#define __INCPEXH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+	/* NOTE: not supported in this driver */
+
+	/* defines */
+	/* The number of supported PEX interfaces depend on Marvell controller */
+	/* device number. This device number ID is located on the PEX unit*/
+	/* configuration header. This creates a loop where calling PEX */
+	/* configuration read/write     routine results a call to get PEX configuration */
+	/* information etc. This macro defines a default PEX interface. This PEX */
+	/* interface is sure to exist.*/
+#define PEX_DEFAULT_IF	0
+
+	/* typedefs */
+	/* The Marvell controller supports both root complex and end point devices */
+	/* This enumeration describes the PEX type.                                 */
+	typedef enum _mvPexType {
+		MV_PEX_ROOT_COMPLEX,	/* root complex device */
+		MV_PEX_END_POINT	/* end point device */
+	} MV_PEX_TYPE;
+
+	typedef enum _mvPexWidth {
+		MV_PEX_WITDH_X1 = 1,
+		MV_PEX_WITDH_X2,
+		MV_PEX_WITDH_X3,
+		MV_PEX_WITDH_X4,
+		MV_PEX_WITDH_INVALID
+	} MV_PEX_WIDTH;
+
+	/* PEX Bar attributes */
+	typedef struct _mvPexMode {
+		MV_PEX_TYPE pexType;
+		MV_PEX_WIDTH pexWidth;
+		MV_BOOL pexLinkUp;
+	} MV_PEX_MODE;
+
+	/* PEX Bar attributes */
+	typedef struct _mvPexBar {
+		MV_ADDR_WIN addrWin;	/* An address window */
+		MV_BOOL enable;	/* Address decode window is enabled/disabled    */
+	} MV_PEX_BAR;
+
+	/* PEX Remap Window attributes */
+	typedef struct _mvPexRemapWin {
+		MV_ADDR_WIN addrWin;	/* An address window */
+		MV_BOOL enable;	/* Address decode window is enabled/disabled    */
+
+	} MV_PEX_REMAP_WIN;
+
+	/* PEX Window attributes */
+	typedef struct _mvPexDecWin {
+		MV_TARGET target;	/* Target for addr decode window        */
+		MV_UNIT_WIN_INFO winInfo;
+		MV_U32 targetBar;
+		MV_BOOL slvWrSpltCnt;
+	} MV_PEX_DEC_WIN;
+
+	/* PEX Wins registers offsets are inconsecutive. This struct describes WIN      */
+	/* register offsets     and its function where its is located.                                  */
+	/* Also, PEX address remap registers offsets are inconsecutive. This struct     */
+	/* describes address remap register offsets                                                                     */
+	typedef struct _pexWinRegInfo {
+		MV_U32 baseLowRegOffs;
+		MV_U32 baseHighRegOffs;
+		MV_U32 sizeRegOffs;
+		MV_U32 remapLowRegOffs;
+		MV_U32 remapHighRegOffs;
+
+	} PEX_WIN_REG_INFO;
+
+	typedef struct {
+		MV_U16 ctrlModel;
+		MV_U16 maxPexIf;
+	} MV_PEX_HAL_DATA;
+
+	/* Global Functions prototypes */
+	/* mvPexInit - Initialize PEX interfaces */
+	MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType, MV_PEX_HAL_DATA *halData);
+
+	/* mvPexModeGet - Get Pex If mode */
+	MV_U32 mvPexModeGet(MV_U32 pexIf, MV_PEX_MODE *pexMode);
+
+	/* mvPexConfigRead - Read from configuration space */
+	MV_U32 mvPexConfigRead(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff);
+
+	/* mvPexConfigWrite - Write to configuration space */
+	MV_STATUS mvPexConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff, MV_U32 data);
+
+	/* mvPexMasterEnable - Enable/disale PEX interface master transactions. */
+	MV_STATUS mvPexMasterEnable(MV_U32 pexIf, MV_BOOL enable);
+
+	/* mvPexSlaveEnable - Enable/disale PEX interface slave transactions. */
+	MV_STATUS mvPexSlaveEnable(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_BOOL enable);
+
+	/* mvPexLocalBusNumSet - Set PEX interface local bus number. */
+	MV_STATUS mvPexLocalBusNumSet(MV_U32 pexIf, MV_U32 busNum);
+
+	/* mvPexLocalBusNumGet - Get PEX interface local bus number. */
+	MV_U32 mvPexLocalBusNumGet(MV_U32 pexIf);
+
+	/* mvPexLocalDevNumSet - Set PEX interface local device number. */
+	MV_STATUS mvPexLocalDevNumSet(MV_U32 pexIf, MV_U32 devNum);
+
+	/* mvPexLocalDevNumGet - Get PEX interface local device number. */
+	MV_U32 mvPexLocalDevNumGet(MV_U32 pexIf);
+	/* mvPexForceX1 - Force PEX interface to X1 mode. */
+	MV_U32 mvPexForceX1(MV_U32 pexIf);
+
+	/* mvPexIsPowerUp - Is PEX interface Power up? */
+	MV_BOOL mvPexIsPowerUp(MV_U32 pexIf);
+
+	/* mvPexPowerDown - Power Down */
+	MV_VOID mvPexPhyPowerDown(MV_U32 pexIf);
+
+	/* mvPexPhyRegRead - Pex phy read */
+	MV_VOID mvPexPhyRegRead(MV_U32 pexIf, MV_U32 regOffset, MV_U16 *value);
+
+	/* mvPexPhyRegWrite - Pex phy write */
+	MV_VOID mvPexPhyRegWrite(MV_U32 pexIf, MV_U32 regOffset, MV_U16 value);
+
+	MV_STATUS mvPexActiveStateLinkPMEnable(MV_U32 pexIf, MV_BOOL enable);
+	/* mvPexIfEnable - Enable Pex interface. */
+	MV_VOID mvPexIfEnable(MV_U32 pexIf, MV_PEX_TYPE pexType);
+
+	/* mvPexWinInit - Window init */
+	MV_STATUS mvPexWinInit(MV_U32 pexIf, MV_PEX_TYPE pexType, MV_UNIT_WIN_INFO *addrWinMap);
+	const MV_8 *pexBarNameGet(MV_U32 bar);
+
+	/* mvPexTargetWinWrite - Window set */
+	MV_STATUS mvPexTargetWinWrite(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pexWin);
+
+	/* mvPexTargetWinRead - Window get */
+	MV_STATUS mvPexTargetWinRead(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pexWin);
+
+	MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable);
+	MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf, MV_U32 winNum, MV_BOOL enable);
+	MV_STATUS mvPexBarSet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *pAddrWin);
+	MV_STATUS mvPexBarGet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *pAddrWin);
+	MV_STATUS pexWinRegInfoGet(MV_U32 pexIf, MV_U32 winNum, PEX_WIN_REG_INFO *pWinRegInfo);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* #ifndef __INCPEXH */
diff --git a/arch/arm/plat-feroceon/mv_hal/pex/mvPexAddrDec.c b/arch/arm/plat-feroceon/mv_hal/pex/mvPexAddrDec.c
new file mode 100755
index 0000000..a32829e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pex/mvPexAddrDec.c
@@ -0,0 +1,1247 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvPexRegs.h"
+#include "mvPex.h"
+
+/* this structure describes the mapping between a Pex Window and a CPU target*/
+typedef struct _pexWinToTarget {
+	MV_TARGET target;
+	MV_BOOL enable;
+
+} PEX_WIN_TO_TARGET;
+
+/* this array is a priority array that define How Pex windows should be
+configured , We have only 6 Pex Windows that can be configured , but we
+have maximum of 9 CPU target windows ! the following array is a priority
+array where the lowest index has the highest priotiy and the highest
+index has the lowest priority of being cnfigured */
+
+MV_U32 pexDevBarPrioTable[] = {
+#if defined(MV_INCLUDE_DEVICE_CS0)
+	DEVICE_CS0,
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS1)
+	DEVICE_CS1,
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS2)
+	DEVICE_CS2,
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS3)
+	DEVICE_CS3,
+#endif
+	/*
+	   #if defined(MV_INCLUDE_DEVICE_CS4)
+	   DEVICE_CS4,
+	   #endif
+	 */
+	TBL_TERM
+};
+
+static MV_STATUS pexWinOverlapDetect(MV_U32 pexIf, MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
+static MV_STATUS pexBarIsValid(MV_U32 baseLow, MV_U32 size);
+static MV_BOOL pexIsWinWithinBar(MV_U32 pexIf, MV_ADDR_WIN *pAddrWin);
+static MV_BOOL pexBarOverlapDetect(MV_U32 pexIf, MV_U32 barNum, MV_ADDR_WIN *pAddrWin);
+
+/*******************************************************************************
+* mvPexWinInit
+*
+* DESCRIPTION:
+*   This function is responsible for configuring the Pex Bars and Windows
+*   in the following manner:
+*
+*  Assumptions :
+*	Bar0 is always internal registers bar
+*       Bar1 is always the DRAM bar
+*	Bar2 is always the Device bar
+*
+*  1) Sets the Internal registers bar base by obtaining the base from
+*	  the CPU Interface
+*  2) Sets the DRAM bar base and size by getting the base and size from
+*     the CPU Interface when the size is the sum of all enabled DRAM
+*	  chip selects and the base is the base of CS0 .
+*  3) Sets the Device bar base and size by getting these values from the
+*     CPU Interface when the base is the base of the lowest base of the
+*     Device chip selects, and the
+*
+* INPUT:
+*       pexIf   -  PEX interface number.
+*	addWinMap: An array holding the address decoding information for the
+*		    system.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM
+*
+*******************************************************************************/
+MV_STATUS mvPexWinInit(MV_U32 pexIf, MV_PEX_TYPE pexType, MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 bar;
+	MV_U32 winNum;
+	MV_PEX_BAR pexBar;
+	MV_PEX_DEC_WIN pexWin;
+	MV_UNIT_WIN_INFO *addrDecWin;
+	MV_TARGET target;
+	MV_U32 pexCurrWin = 0;
+
+	/* default and exapntion rom are always configured */
+
+#ifndef MV_DISABLE_PEX_DEVICE_BAR
+	MV_U32 winIndex;
+	MV_U32 maxBase = 0, sizeOfMaxBase = 0;
+	MV_U32 pexStartWindow;
+#endif
+
+	/* Enabled PCI-Express */
+	mvPexIfEnable(pexIf, pexType);
+
+	/* Start with bars */
+	/* First disable all PEX bars */
+	for (bar = 0; bar < PEX_MAX_BARS; bar++) {
+		if (PEX_INTER_REGS_BAR != bar) {
+			if (MV_OK != mvPexBarEnable(pexIf, bar, MV_FALSE)) {
+				mvOsPrintf("mvPexInit:mvPexBarEnable bar =%d failed \n", bar);
+				return MV_ERROR;
+			}
+		}
+	}
+
+	/* and disable all PEX target windows  */
+	for (winNum = 0; winNum < PEX_MAX_TARGET_WIN - 2; winNum++) {
+		if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_FALSE)) {
+			mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", winNum);
+			return MV_ERROR;
+		}
+	}
+
+	/* Now, go through all bars */
+
+	/******************************************************************************/
+	/*                       Internal registers bar                               */
+	/******************************************************************************/
+	bar = PEX_INTER_REGS_BAR;
+	addrDecWin = &addrWinMap[INTER_REGS];
+	/* we only open the bar , no need to open windows for this bar */
+
+	pexBar.addrWin.baseHigh = addrDecWin->addrWin.baseHigh;
+	pexBar.addrWin.baseLow = addrDecWin->addrWin.baseLow;
+	pexBar.addrWin.size = addrDecWin->addrWin.size;
+	pexBar.enable = MV_TRUE;
+
+	if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) {
+		mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar);
+		return MV_ERROR;
+	}
+
+	/******************************************************************************/
+	/*                                DRAM bar                                    */
+	/******************************************************************************/
+
+	bar = PEX_DRAM_BAR;
+	pexBar.addrWin.size = 0;
+
+	for (target = SDRAM_CS0; target < MV_DRAM_MAX_CS; target++) {
+		addrDecWin = &addrWinMap[target];
+		if ((addrDecWin->enable == MV_FALSE) && (target != SDRAM_CS0))
+			continue;
+
+		if (addrDecWin->enable == MV_TRUE) {
+			/* the base is the base of DRAM CS0 always */
+			if (SDRAM_CS0 == target) {
+				pexBar.addrWin.baseHigh = addrDecWin->addrWin.baseHigh;
+				pexBar.addrWin.baseLow = addrDecWin->addrWin.baseLow;
+			}
+
+			/* increment the bar size to be the sum of the size of all
+			 ** DRAM chips selecs */
+			pexBar.addrWin.size += addrDecWin->addrWin.size;
+
+			/* set a Pex window for this target !
+			 ** DRAM CS always will have a Pex Window , and is not a
+			 ** part of the priority table */
+			mvOsMemcpy(&pexWin.winInfo, addrDecWin, sizeof(MV_UNIT_WIN_INFO));
+
+			/* we disable the windows at first because we are not
+			 ** sure that it is witihin bar boundries */
+			pexWin.winInfo.enable = MV_FALSE;
+			pexWin.target = target;
+			pexWin.targetBar = bar;
+
+			if (MV_OK != mvPexTargetWinWrite(pexIf, pexCurrWin++, &pexWin)) {
+				mvOsPrintf("mvPexInit: ERR. mvPexTargetWinSet failed\n");
+				return MV_ERROR;
+			}
+		}
+	}
+
+	/* check if the size of the bar is illeggal */
+	if (!MV_IS_POWER_OF_2(pexBar.addrWin.size)) {
+		/* try to get a good size */
+		pexBar.addrWin.size = 1 << (mvLog2(pexBar.addrWin.size) + 1);
+	}
+
+	/* check if the size and base are valid */
+	if (MV_TRUE == pexBarOverlapDetect(pexIf, bar, &pexBar.addrWin)) {
+		mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n", bar);
+		mvOsPrintf("it will be disabled\n");
+		mvOsPrintf("please check Pex and CPU windows configuration\n");
+	} else {
+		pexBar.enable = MV_TRUE;
+
+		/* configure the bar */
+		if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) {
+			mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar);
+			return MV_ERROR;
+		}
+
+		/* after the bar was configured then we enable the Pex windows */
+		for (winNum = 0; winNum < pexCurrWin; winNum++) {
+			if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) {
+				mvOsPrintf("mvPexInit: Can't enable window =%d\n", winNum);
+				return MV_ERROR;
+			}
+		}
+	}
+
+	/******************************************************************************/
+	/*                              DEVICE bar                                    */
+	/******************************************************************************/
+
+	/* Open the Device BAR for non linux only */
+#ifndef MV_DISABLE_PEX_DEVICE_BAR
+
+	/* then device  bar */
+	bar = PEX_DEVICE_BAR;
+
+	/* save the starting window */
+	pexStartWindow = pexCurrWin;
+	pexBar.addrWin.size = 0;
+	pexBar.addrWin.baseLow = 0xffffffff;
+	pexBar.addrWin.baseHigh = 0;
+	maxBase = 0;
+
+	for (target = DEV_TO_TARGET(START_DEV_CS); target < DEV_TO_TARGET(MV_DEV_MAX_CS); target++) {
+		addrDecWin = &addrWinMap[target];
+
+		if (addrDecWin->enable == MV_TRUE) {
+			/* get the minimum base */
+			if (addrDecWin->addrWin.baseLow < pexBar.addrWin.baseLow)
+				pexBar.addrWin.baseLow = addrDecWin->addrWin.baseLow;
+
+			/* get the maximum base */
+			if (addrDecWin->addrWin.baseLow > maxBase) {
+				maxBase = addrDecWin->addrWin.baseLow;
+				sizeOfMaxBase = addrDecWin->addrWin.size;
+			}
+
+			/* search in the priority table for this target */
+			for (winIndex = 0; pexDevBarPrioTable[winIndex] != TBL_TERM; winIndex++) {
+				if (pexDevBarPrioTable[winIndex] != target) {
+					continue;
+				} else if (pexDevBarPrioTable[winIndex] == target) {
+					/*found it */
+					/* if the index of this target in the prio table is valid
+					 ** then we set the Pex window for this target, a valid index is
+					 ** an index that is lower than the number of the windows that
+					 ** was not configured yet */
+
+					/* we subtract 2 always because the default and expantion
+					 ** rom windows are always configured */
+					if (pexCurrWin < PEX_MAX_TARGET_WIN - 2) {
+						/* set a Pex window for this target !  */
+						mvOsMemcpy(&pexWin.winInfo, addrDecWin,
+							   sizeof(MV_UNIT_WIN_INFO));
+
+						/* we disable the windows at first because we are not
+						 ** sure that it is witihin bar boundries */
+						pexWin.enable = MV_FALSE;
+						pexWin.target = target;
+						pexWin.targetBar = bar;
+
+						if (MV_OK !=
+								mvPexTargetWinWrite(pexIf, pexCurrWin++, &pexWin)) {
+							mvOsPrintf("mvPexInit: ERR. Window Set failed\n");
+							return MV_ERROR;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	pexBar.addrWin.size = maxBase - pexBar.addrWin.baseLow + sizeOfMaxBase;
+	pexBar.enable = MV_TRUE;
+
+	/* check if the size of the bar is illegal */
+	if (!MV_IS_POWER_OF_2(pexBar.addrWin.size)) {
+		/* try to get a good size */
+		pexBar.addrWin.size = 1 << (mvLog2(pexBar.addrWin.size) + 1);
+	}
+
+	/* check if the size and base are valid */
+	if (MV_TRUE == pexBarOverlapDetect(pexIf, bar, &pexBar.addrWin)) {
+		mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n", bar);
+		mvOsPrintf("it will be disabled\n");
+		mvOsPrintf("please check Pex and CPU windows configuration\n");
+	} else {
+		if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) {
+			mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar);
+			return MV_ERROR;
+		}
+
+		/* now enable the windows */
+		for (winNum = pexStartWindow; winNum < pexCurrWin; winNum++) {
+			if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) {
+				mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", winNum);
+				return MV_ERROR;
+			}
+		}
+	}
+
+#endif
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexTargetWinWrite
+*
+* DESCRIPTION:
+*	Set PEX to peripheral target address window BAR
+*
+* INPUT:
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_OK if PEX BAR target window was set correctly,
+*		MV_BAD_PARAM on bad params
+*       MV_ERROR otherwise
+*       (e.g. address window overlapps with other active PEX target window).
+*
+*******************************************************************************/
+MV_STATUS mvPexTargetWinWrite(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pexWin)
+{
+	MV_U32 baseReg, sizeReg;
+	PEX_WIN_REG_INFO winRegInfo;
+	MV_UNIT_WIN_INFO *pAddrDecWin = &pexWin->winInfo;
+
+	if (winNum >= PEX_MAX_TARGET_WIN) {
+		mvOsPrintf("mvPexTargetWinWrite: ERR. Invalid PEX winNum %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* get the pex Window registers offsets */
+	pexWinRegInfoGet(pexIf, winNum, &winRegInfo);
+
+	if (MV_TRUE == pAddrDecWin->enable) {
+		/* 1) Check if the requested window overlaps with current windows  */
+		if (MV_TRUE == pexWinOverlapDetect(pexIf, winNum, &pAddrDecWin->addrWin)) {
+			mvOsPrintf("mvPexTargetWinWrite: ERR. Target %d overlap\n", winNum);
+			return MV_BAD_PARAM;
+		}
+
+		/* 2) Check if the requested window overlaps with current windows  */
+		if (MV_FALSE == pexIsWinWithinBar(pexIf, &pAddrDecWin->addrWin)) {
+			mvOsPrintf("mvPexTargetWinWrite: Win %d should be in bar boundries\n", winNum);
+			return MV_BAD_PARAM;
+		}
+
+		/* 3) Check if size is a power of 2.                                */
+		if (!MV_IS_POWER_OF_2(pAddrDecWin->addrWin.size)) {
+			mvOsPrintf("mvPexTargetWinWrite: Size is not a power of 2.\n");
+			return MV_BAD_PARAM;
+		}
+	}
+
+	/* read base register */
+	if (winRegInfo.baseLowRegOffs)
+		baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs);
+	else
+		baseReg = 0;
+
+	if (winRegInfo.sizeRegOffs)
+		sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs);
+	else
+		sizeReg = 0;
+
+	sizeReg = (pAddrDecWin->addrWin.size / PXWCR_SIZE_ALIGNMENT - 1) << PXWCR_SIZE_OFFS;
+	baseReg = pAddrDecWin->addrWin.baseLow & PXWBR_BASE_MASK;
+
+	/* enable\disable */
+	if (MV_TRUE == pAddrDecWin->enable)
+		sizeReg |= PXWCR_WIN_EN;
+	else
+		sizeReg &= ~PXWCR_WIN_EN;
+
+	/* clear bit location */
+	sizeReg &= ~PXWCR_WIN_BAR_MAP_MASK;
+
+	/* set bar Mapping */
+	if (pexWin->targetBar == 1)
+		sizeReg |= PXWCR_WIN_BAR_MAP_BAR1;
+	else if (pexWin->targetBar == 2)
+		sizeReg |= PXWCR_WIN_BAR_MAP_BAR2;
+
+	/* set attributes */
+	sizeReg &= ~PXWCR_ATTRIB_MASK;
+	sizeReg |= pAddrDecWin->attrib << PXWCR_ATTRIB_OFFS;
+	/* set target ID */
+	sizeReg &= ~PXWCR_TARGET_MASK;
+	sizeReg |= pAddrDecWin->targetId << PXWCR_TARGET_OFFS;
+
+	/* 3) Write to address decode Base Address Register                   */
+	if (winRegInfo.baseLowRegOffs)
+		MV_REG_WRITE(winRegInfo.baseLowRegOffs, baseReg);
+
+	/* write size reg */
+	if (winRegInfo.sizeRegOffs) {
+		if ((MV_PEX_WIN_DEFAULT == winNum) || (MV_PEX_WIN_EXP_ROM == winNum)) {
+			/* clear size because there is no size field */
+			sizeReg &= ~PXWCR_SIZE_MASK;
+			/* clear enable because there is no enable field */
+			sizeReg &= ~PXWCR_WIN_EN;
+		}
+		MV_REG_WRITE(winRegInfo.sizeRegOffs, sizeReg);
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexTargetWinRead
+*
+* DESCRIPTION:
+*		Get the PEX to peripheral target address window BAR.
+*
+* INPUT:
+*       pexIf - PEX interface number.
+*       bar   - BAR to be accessed by slave.
+*
+* OUTPUT:
+*       pAddrBarWin - PEX target window information data structure.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexTargetWinRead(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pexWin)
+{
+	MV_U32 sizeReg, baseReg;
+	MV_U32 sizeRegVal;
+	PEX_WIN_REG_INFO winRegInfo;
+	MV_UNIT_WIN_INFO *pAddrDecWin = &pexWin->winInfo;
+
+	/* Parameter checking   */
+	if (winNum >= PEX_MAX_TARGET_WIN) {
+		mvOsPrintf("mvPexTargetWinRead: ERR. Invalid PEX winNum %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* get the pex Window registers offsets */
+	pexWinRegInfoGet(pexIf, winNum, &winRegInfo);
+
+	/* read base register */
+	if (winRegInfo.baseLowRegOffs)
+		baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs);
+	else
+		baseReg = 0;
+
+	/* read size reg */
+	if (winRegInfo.sizeRegOffs)
+		sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs);
+	else
+		sizeReg = 0;
+
+	/* Extract size         */
+	sizeRegVal = (sizeReg & PXWCR_SIZE_MASK) >> PXWCR_SIZE_OFFS;
+	pAddrDecWin->addrWin.size = (sizeRegVal + 1) * PXWCR_SIZE_ALIGNMENT;
+	/* Extract base address */
+	pAddrDecWin->addrWin.baseLow = baseReg & PXWBR_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh = 0;
+
+	if (sizeReg & PXWCR_WIN_EN)
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+
+#if 0
+	if (-1 == pAddrDecWin->addrWin.size)
+		return MV_ERROR;
+#endif
+
+	/* get target bar */
+	if ((sizeReg & PXWCR_WIN_BAR_MAP_MASK) == PXWCR_WIN_BAR_MAP_BAR1)
+		pexWin->targetBar = 1;
+	else if ((sizeReg & PXWCR_WIN_BAR_MAP_MASK) == PXWCR_WIN_BAR_MAP_BAR2)
+		pexWin->targetBar = 2;
+
+	/* attrib and targetId */
+	pAddrDecWin->attrib = (sizeReg & PXWCR_ATTRIB_MASK) >> PXWCR_ATTRIB_OFFS;
+	pAddrDecWin->targetId = (sizeReg & PXWCR_TARGET_MASK) >> PXWCR_TARGET_OFFS;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexTargetWinEnable - Enable/disable a PEX BAR window
+*
+* DESCRIPTION:
+*       This function enable/disable a PEX BAR window.
+*       if parameter 'enable' == MV_TRUE the routine will enable the
+*       window, thus enabling PEX accesses for that BAR (before enabling the
+*       window it is tested for overlapping). Otherwise, the window will
+*       be disabled.
+*
+* INPUT:
+*       pexIf  - PEX interface number.
+*       bar    - BAR to be accessed by slave.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf, MV_U32 winNum, MV_BOOL enable)
+{
+	MV_PEX_DEC_WIN pexWin;
+	PEX_WIN_REG_INFO winRegInfo;
+	MV_UNIT_WIN_INFO *addrDecWin = &pexWin.winInfo;
+
+	/* Parameter checking   */
+	if (winNum >= PEX_MAX_TARGET_WIN) {
+		mvOsPrintf("mvPexTargetWinEnable ERR. Invalid PEX winNum %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* get the pex Window registers offsets */
+	pexWinRegInfoGet(pexIf, winNum, &winRegInfo);
+
+	/* if the address windows is disabled , we only disable the appropriare
+	 ** pex window and ignore other settings */
+	if (MV_FALSE == enable) {
+		/* this is not relevant to default and expantion rom windows */
+		if (winRegInfo.sizeRegOffs) {
+			if ((MV_PEX_WIN_DEFAULT != winNum) && (MV_PEX_WIN_EXP_ROM != winNum))
+				MV_REG_BIT_RESET(winRegInfo.sizeRegOffs, PXWCR_WIN_EN);
+		}
+	} else {
+		if (MV_OK != mvPexTargetWinRead(pexIf, winNum, &pexWin)) {
+			mvOsPrintf("mvPexTargetWinEnable: mvPexTargetWinRead Failed\n");
+			return MV_ERROR;
+		}
+
+		/* Check if the requested window overlaps with current windows  */
+		if (MV_TRUE == pexWinOverlapDetect(pexIf, winNum, &addrDecWin->addrWin)) {
+			mvOsPrintf("mvPexTargetWinEnable: ERR. Target %d overlap\n", winNum);
+			return MV_BAD_PARAM;
+		}
+
+		if (MV_FALSE == pexIsWinWithinBar(pexIf, &addrDecWin->addrWin)) {
+			mvOsPrintf("mvPexTargetWinEnable: Win %d should be in bar boundries\n", winNum);
+			return MV_BAD_PARAM;
+		}
+
+		/* this is not relevant to default and expantion rom windows */
+		if (winRegInfo.sizeRegOffs) {
+			if ((MV_PEX_WIN_DEFAULT != winNum) && (MV_PEX_WIN_EXP_ROM != winNum))
+				MV_REG_BIT_SET(winRegInfo.sizeRegOffs, PXWCR_WIN_EN);
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexTargetWinRemap - Set PEX to target address window remap.
+*
+* DESCRIPTION:
+*       The PEX interface supports remap of the BAR original address window.
+*       For each BAR it is possible to define a remap address. For example
+*       an address 0x12345678 that hits BAR 0x10 (SDRAM CS[0]) will be modified
+*       according to remap register but will also be targeted to the
+*       SDRAM CS[0].
+*
+* INPUT:
+*       pexIf    - PEX interface number.
+*       bar      - Peripheral target enumerator accessed by slave.
+*       pAddrWin - Address window to be checked.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum, MV_PEX_REMAP_WIN *pAddrWin)
+{
+	PEX_WIN_REG_INFO winRegInfo;
+
+	if (MV_PEX_WIN_DEFAULT == winNum) {
+		mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX win num %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	if (MV_IS_NOT_ALIGN(pAddrWin->addrWin.baseLow, PXWRR_REMAP_ALIGNMENT)) {
+		mvOsPrintf("mvPexTargetWinRemap: Error remap PEX interface %d win %d."
+			   "\nAddress 0x%08x is unaligned to size 0x%x.\n",
+			   pexIf, winNum, pAddrWin->addrWin.baseLow, pAddrWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	pexWinRegInfoGet(pexIf, winNum, &winRegInfo);
+
+	/* Set remap low register value */
+	MV_REG_WRITE(winRegInfo.remapLowRegOffs, pAddrWin->addrWin.baseLow);
+
+	/* Skip base high settings if the BAR has only base low (32-bit)            */
+	if (0 != winRegInfo.remapHighRegOffs)
+		MV_REG_WRITE(winRegInfo.remapHighRegOffs, pAddrWin->addrWin.baseHigh);
+
+	if (pAddrWin->enable == MV_TRUE)
+		MV_REG_BIT_SET(winRegInfo.remapLowRegOffs, PXWRR_REMAP_EN);
+	else
+		MV_REG_BIT_RESET(winRegInfo.remapLowRegOffs, PXWRR_REMAP_EN);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvPexTargetWinRemapEnable -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum, MV_BOOL enable)
+{
+	PEX_WIN_REG_INFO winRegInfo;
+
+	if (MV_PEX_WIN_DEFAULT == winNum) {
+		mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX win num %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	pexWinRegInfoGet(pexIf, winNum, &winRegInfo);
+	if (enable == MV_TRUE)
+		MV_REG_BIT_SET(winRegInfo.remapLowRegOffs, PXWRR_REMAP_EN);
+	else
+		MV_REG_BIT_RESET(winRegInfo.remapLowRegOffs, PXWRR_REMAP_EN);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+*  mvPexBarSet - Set PEX bar address and size
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexBarSet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *pAddrWin)
+{
+	MV_U32 regBaseLow;
+	MV_U32 regSize, sizeToReg;
+
+	/* check parameters */
+	if (barNum >= PEX_MAX_BARS) {
+		mvOsPrintf("mvPexBarSet: ERR. Invalid bar number %d\n", barNum);
+		return MV_BAD_PARAM;
+	}
+
+	if (pAddrWin->addrWin.size == 0) {
+		mvOsPrintf("mvPexBarSet: Size zero is illegal\n");
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the window complies with PEX spec                       */
+	if (MV_TRUE != pexBarIsValid(pAddrWin->addrWin.baseLow, pAddrWin->addrWin.size)) {
+		mvOsPrintf("mvPexBarSet: ERR. Target %d window invalid\n", barNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* 2) Check if the requested bar overlaps with current bars         */
+	if (MV_TRUE == pexBarOverlapDetect(pexIf, barNum, &pAddrWin->addrWin)) {
+		mvOsPrintf("mvPexBarSet: ERR. Target %d overlap\n", barNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Get size register value according to window size         */
+	sizeToReg = (pAddrWin->addrWin.size / PXBCR_BAR_SIZE_ALIGNMENT) - 1;
+
+	/* Read bar size */
+	if (PEX_INTER_REGS_BAR != barNum) {	/* internal registers have no size */
+		regSize = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf, barNum));
+
+		/* Size parameter validity check.                                   */
+		if (-1 == sizeToReg) {
+			mvOsPrintf("mvPexBarSet: ERR. Target BAR %d size invalid.\n", barNum);
+			return MV_BAD_PARAM;
+		}
+
+		regSize &= ~PXBCR_BAR_SIZE_MASK;
+		regSize |= (sizeToReg << PXBCR_BAR_SIZE_OFFS);
+		MV_REG_WRITE(PEX_BAR_CTRL_REG(pexIf, barNum), regSize);
+	}
+
+	/* set size */
+	/* Read base address low */
+	regBaseLow = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_MV_BAR_BASE(barNum)));
+
+	/* clear current base */
+	if (PEX_INTER_REGS_BAR == barNum) {
+		regBaseLow &= ~PXBIR_BASE_MASK;
+		regBaseLow |= (pAddrWin->addrWin.baseLow & PXBIR_BASE_MASK);
+	} else {
+		regBaseLow &= ~PXBR_BASE_MASK;
+		regBaseLow |= (pAddrWin->addrWin.baseLow & PXBR_BASE_MASK);
+	}
+
+	/* if we had a previous value that contain the bar type (MeM\IO), we want to
+	 ** restore it */
+	regBaseLow |= PEX_BAR_DEFAULT_ATTRIB;
+
+	/* write base low */
+	MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_MV_BAR_BASE(barNum)), regBaseLow);
+
+	if (pAddrWin->addrWin.baseHigh != 0) {
+		/* Read base address high */
+		MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_MV_BAR_BASE_HIGH(barNum)),
+			     pAddrWin->addrWin.baseHigh);
+	}
+
+	/* lastly enable the Bar */
+	if (pAddrWin->enable == MV_TRUE) {
+		if (PEX_INTER_REGS_BAR != barNum) {	/* internal registers are enabled always */
+			MV_REG_BIT_SET(PEX_BAR_CTRL_REG(pexIf, barNum), PXBCR_BAR_EN);
+		}
+	} else if (MV_FALSE == pAddrWin->enable) {
+		if (PEX_INTER_REGS_BAR != barNum) {	/* internal registers are enabled always */
+			MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf, barNum), PXBCR_BAR_EN);
+		}
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+*  mvPexBarGet - Get PEX bar address and size
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexBarGet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *pAddrWin)
+{
+	if (barNum >= PEX_MAX_BARS) {
+		mvOsPrintf("mvPexBarGet: ERR. Invalid bar number %d\n", barNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* read base low */
+	pAddrWin->addrWin.baseLow = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_MV_BAR_BASE(barNum)));
+
+	if (PEX_INTER_REGS_BAR == barNum)
+		pAddrWin->addrWin.baseLow &= PXBIR_BASE_MASK;
+	else
+		pAddrWin->addrWin.baseLow &= PXBR_BASE_MASK;
+
+	/* read base high */
+	pAddrWin->addrWin.baseHigh = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_MV_BAR_BASE_HIGH(barNum)));
+
+	/* Read bar size */
+	if (PEX_INTER_REGS_BAR != barNum) {	/* internal registers have no size */
+		pAddrWin->addrWin.size = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf, barNum));
+		/* check if enable or not */
+		if (pAddrWin->addrWin.size & PXBCR_BAR_EN)
+			pAddrWin->enable = MV_TRUE;
+		else
+			pAddrWin->enable = MV_FALSE;
+
+		/* now get the size */
+		pAddrWin->addrWin.size &= PXBCR_BAR_SIZE_MASK;
+		pAddrWin->addrWin.size >>= PXBCR_BAR_SIZE_OFFS;
+		pAddrWin->addrWin.size = (pAddrWin->addrWin.size + 1) * PXBCR_BAR_SIZE_ALIGNMENT;
+	} else {		/* PEX_INTER_REGS_BAR */
+		pAddrWin->addrWin.size = INTER_REGS_SIZE;
+		pAddrWin->enable = MV_TRUE;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+*  mvPexBarEnable -
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
+*
+*******************************************************************************/
+MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable)
+{
+	MV_PEX_BAR pexBar;
+
+	if (barNum >= PEX_MAX_BARS) {
+		mvOsPrintf("mvPexBarEnable: ERR. Invalid bar number %d\n", barNum);
+		return MV_BAD_PARAM;
+	}
+
+	if (PEX_INTER_REGS_BAR == barNum) {
+		if (MV_TRUE == enable)
+			return MV_OK;
+		else
+			return MV_ERROR;
+	}
+
+	if (MV_FALSE == enable) {
+		/* disable bar and quit */
+		MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf, barNum), PXBCR_BAR_EN);
+		return MV_OK;
+	}
+
+	/* else */
+	if (mvPexBarGet(pexIf, barNum, &pexBar) != MV_OK) {
+		mvOsPrintf("mvPexBarEnable: mvPexBarGet Failed\n");
+		return MV_ERROR;
+	}
+
+	if (MV_TRUE == pexBar.enable) {
+		/* it is already enabled !!! */
+		return MV_OK;
+	}
+
+	/* else enable the bar */
+	pexBar.enable = MV_TRUE;
+	if (mvPexBarSet(pexIf, barNum, &pexBar) != MV_OK) {
+		mvOsPrintf("mvPexBarEnable: mvPexBarSet Failed\n");
+		return MV_ERROR;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* pexWinOverlapDetect - Detect address windows overlapping
+*
+* DESCRIPTION:
+*       This function detects address window overlapping of a given address
+*       window in PEX BARs.
+*
+* INPUT:
+*       pAddrWin - Address window to be checked.
+*       bar      - BAR to be accessed by slave.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise.
+*
+*******************************************************************************/
+static MV_BOOL pexWinOverlapDetect(MV_U32 pexIf, MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 win;
+	MV_PEX_DEC_WIN pexWin;
+
+	for (win = 0; win < PEX_MAX_TARGET_WIN - 2; win++) {
+		/* don't check our target or illegal targets */
+		if (winNum == win)
+			continue;
+
+		/* Get window parameters        */
+		if (MV_OK != mvPexTargetWinRead(pexIf, win, &pexWin)) {
+			mvOsPrintf("pexWinOverlapDetect: ERR. TargetWinGet failed win=%x\n", win);
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled windows        */
+		if (MV_FALSE == pexWin.winInfo.enable)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &pexWin.winInfo.addrWin)) {
+			mvOsPrintf("pexWinOverlapDetect: winNum %d overlap current %d\n", winNum, win);
+			return MV_TRUE;
+		}
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* pexIsWinWithinBar - Detect if address is within PEX bar boundries
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise.
+*
+*******************************************************************************/
+static MV_BOOL pexIsWinWithinBar(MV_U32 pexIf, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 bar;
+	MV_PEX_BAR addrDecWin;
+
+	for (bar = 0; bar < PEX_MAX_BARS; bar++) {
+		/* Get window parameters        */
+		if (MV_OK != mvPexBarGet(pexIf, bar, &addrDecWin)) {
+			mvOsPrintf("pexIsWinWithinBar: ERR. mvPexBarGet failed\n");
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled bars   */
+		if (MV_FALSE == addrDecWin.enable)
+			continue;
+
+		if (MV_TRUE == mvWinWithinWinTest(pAddrWin, &addrDecWin.addrWin))
+			return MV_TRUE;
+	}
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* pexBarOverlapDetect - Detect address windows overlapping
+*
+* DESCRIPTION:
+*       This function detects address window overlapping of a given address
+*       window in PEX BARs.
+*
+* INPUT:
+*       pAddrWin - Address window to be checked.
+*       bar      - BAR to be accessed by slave.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise.
+*
+*******************************************************************************/
+static MV_BOOL pexBarOverlapDetect(MV_U32 pexIf, MV_U32 barNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 bar;
+	MV_PEX_BAR barDecWin;
+
+	for (bar = 0; bar < PEX_MAX_BARS; bar++) {
+		/* don't check our target or illegal targets */
+		if (barNum == bar)
+			continue;
+
+		/* Get window parameters        */
+		if (MV_OK != mvPexBarGet(pexIf, bar, &barDecWin)) {
+			mvOsPrintf("pexBarOverlapDetect: ERR. TargetWinGet failed\n");
+			return MV_ERROR;
+		}
+
+		/* don't check disabled bars */
+		if (barDecWin.enable == MV_FALSE)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &barDecWin.addrWin)) {
+			mvOsPrintf("pexBarOverlapDetect: winNum %d overlap current %d\n", barNum, bar);
+			return MV_TRUE;
+		}
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* pexBarIsValid - Check if the given address window is valid
+*
+* DESCRIPTION:
+*		PEX spec restrict BAR base to be aligned to BAR size.
+*		This function checks if the given address window is valid.
+*
+* INPUT:
+*       baseLow - 32bit low base address.
+*       size    - Window size.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the address window is valid, MV_FALSE otherwise.
+*
+*******************************************************************************/
+static MV_STATUS pexBarIsValid(MV_U32 baseLow, MV_U32 size)
+{
+	/* PCI spec restrict BAR base to be aligned to BAR size         */
+	if (MV_IS_NOT_ALIGN(baseLow, size))
+		return MV_ERROR;
+	else
+		return MV_TRUE;
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* pexBarRegInfoGet - Get BAR register information
+*
+* DESCRIPTION:
+* 		PEX BARs registers offsets are inconsecutive.
+*		This function gets a PEX BAR register information like register offsets
+*		and function location of the BAR.
+*
+* INPUT:
+*       pexIf - PEX interface number.
+*		bar	  - The PEX BAR in question.
+*
+* OUTPUT:
+*       pBarRegInfo - BAR register info struct.
+*
+* RETURN:
+*		MV_BAD_PARAM when bad parameters ,MV_ERROR on error ,othewise MV_OK
+*
+*******************************************************************************/
+MV_STATUS pexWinRegInfoGet(MV_U32 pexIf, MV_U32 winNum, PEX_WIN_REG_INFO *pWinRegInfo)
+{
+	if ((winNum >= 0) && (winNum <= 3)) {
+		pWinRegInfo->baseLowRegOffs = PEX_WIN0_3_BASE_REG(pexIf, winNum);
+		pWinRegInfo->baseHighRegOffs = 0;
+		pWinRegInfo->sizeRegOffs = PEX_WIN0_3_CTRL_REG(pexIf, winNum);
+		pWinRegInfo->remapLowRegOffs = PEX_WIN0_3_REMAP_REG(pexIf, winNum);
+		pWinRegInfo->remapHighRegOffs = 0;
+	} else if ((winNum >= 4) && (winNum <= 5)) {
+		pWinRegInfo->baseLowRegOffs = PEX_WIN4_5_BASE_REG(pexIf, winNum);
+		pWinRegInfo->baseHighRegOffs = 0;
+		pWinRegInfo->sizeRegOffs = PEX_WIN4_5_CTRL_REG(pexIf, winNum);
+		pWinRegInfo->remapLowRegOffs = PEX_WIN4_5_REMAP_REG(pexIf, winNum);
+		pWinRegInfo->remapHighRegOffs = PEX_WIN4_5_REMAP_HIGH_REG(pexIf, winNum);
+	} else if (MV_PEX_WIN_DEFAULT == winNum) {
+		pWinRegInfo->baseLowRegOffs = 0;
+		pWinRegInfo->baseHighRegOffs = 0;
+		pWinRegInfo->sizeRegOffs = PEX_WIN_DEFAULT_CTRL_REG(pexIf);
+		pWinRegInfo->remapLowRegOffs = 0;
+		pWinRegInfo->remapHighRegOffs = 0;
+	} else if (MV_PEX_WIN_EXP_ROM == winNum) {
+		pWinRegInfo->baseLowRegOffs = 0;
+		pWinRegInfo->baseHighRegOffs = 0;
+		pWinRegInfo->sizeRegOffs = PEX_WIN_EXP_ROM_CTRL_REG(pexIf);
+		pWinRegInfo->remapLowRegOffs = PEX_WIN_EXP_ROM_REMAP_REG(pexIf);
+		pWinRegInfo->remapHighRegOffs = 0;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* pexBarNameGet - Get the string name of PEX BAR.
+*
+* DESCRIPTION:
+*		This function get the string name of PEX BAR.
+*
+* INPUT:
+*       bar - PEX bar number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       pointer to the string name of PEX BAR.
+*
+*******************************************************************************/
+const MV_8 *pexBarNameGet(MV_U32 bar)
+{
+	switch (bar) {
+	case PEX_INTER_REGS_BAR:
+		return "Internal Regs Bar0....";
+	case PEX_DRAM_BAR:
+		return "DRAM Bar1.............";
+	case PEX_DEVICE_BAR:
+		return "Devices Bar2..........";
+	default:
+		return "Bar unknown";
+	}
+}
+
+#if 0
+/*******************************************************************************
+* mvPexAddrDecShow - Print the PEX address decode map (BARs and windows).
+*
+* DESCRIPTION:
+*		This function print the PEX address decode map (BARs and windows).
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvPexAddrDecShow(MV_VOID)
+{
+	MV_PEX_BAR pexBar;
+	MV_PEX_DEC_WIN win;
+	MV_U32 pexIf;
+	MV_U32 bar, winNum;
+
+	for (pexIf = 0; pexIf < mvCtrlPexMaxIfGet(); pexIf++) {
+		if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf))
+			continue;
+		mvOsOutput("\n");
+		mvOsOutput("PEX%d:\n", pexIf);
+		mvOsOutput("-----\n");
+
+		mvOsOutput("\nPex Bars \n\n");
+
+		for (bar = 0; bar < PEX_MAX_BARS; bar++) {
+			memset(&pexBar, 0, sizeof(MV_PEX_BAR));
+
+			mvOsOutput("%s ", pexBarNameGet(bar));
+
+			if (mvPexBarGet(pexIf, bar, &pexBar) == MV_OK) {
+				if (pexBar.enable) {
+					mvOsOutput("base %08x, ", pexBar.addrWin.baseLow);
+					mvSizePrint(pexBar.addrWin.size);
+					mvOsOutput("\n");
+				} else
+					mvOsOutput("disable\n");
+			}
+		}
+		mvOsOutput("\nPex Decode Windows\n\n");
+
+		for (winNum = 0; winNum < PEX_MAX_TARGET_WIN - 2; winNum++) {
+			memset(&win, 0, sizeof(MV_PEX_DEC_WIN));
+
+			mvOsOutput("win%d - ", winNum);
+
+			if (mvPexTargetWinGet(pexIf, winNum, &win) == MV_OK) {
+				if (win.enable) {
+					mvOsOutput("%s base %08x, ",
+						   mvCtrlTargetNameGet(win.target), win.addrWin.baseLow);
+					mvOsOutput("....");
+					mvSizePrint(win.addrWin.size);
+
+					mvOsOutput("\n");
+				} else
+					mvOsOutput("disable\n");
+			}
+		}
+
+		memset(&win, 0, sizeof(MV_PEX_DEC_WIN));
+
+		mvOsOutput("default win - ");
+
+		if (mvPexTargetWinGet(pexIf, MV_PEX_WIN_DEFAULT, &win) == MV_OK) {
+			mvOsOutput("%s ", mvCtrlTargetNameGet(win.target));
+			mvOsOutput("\n");
+		}
+		memset(&win, 0, sizeof(MV_PEX_DEC_WIN));
+
+		mvOsOutput("Expansion ROM - ");
+
+		if (mvPexTargetWinGet(pexIf, MV_PEX_WIN_EXP_ROM, &win) == MV_OK) {
+			mvOsOutput("%s ", mvCtrlTargetNameGet(win.target));
+			mvOsOutput("\n");
+		}
+	}
+}
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/pex/mvPexRegs.h b/arch/arm/plat-feroceon/mv_hal/pex/mvPexRegs.h
new file mode 100755
index 0000000..1d7d90b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pex/mvPexRegs.h
@@ -0,0 +1,925 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCPEXREGSH
+#define __INCPEXREGSH
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+#include "mvSysPexConfig.h"
+
+/* defines */
+#define MAX_PEX_DEVICES         32
+#define MAX_PEX_FUNCS           8
+#define MAX_PEX_BUSSES          256
+
+/*********************************************************/
+/* PCI Express Configuration Cycles Generation Registers */
+/*********************************************************/
+
+#define PEX_CFG_ADDR_REG(pexIf)		((MV_PEX_IF_REGS_BASE(pexIf)) + 0x18F8)
+#define PEX_CFG_DATA_REG(pexIf)		((MV_PEX_IF_REGS_BASE(pexIf)) + 0x18FC)
+#define PEX_PHY_ACCESS_REG(pexIf)	((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1B00)
+
+/* PCI Express Configuration Address Register */
+/* PEX_CFG_ADDR_REG (PXCAR) */
+#define PXCAR_REG_NUM_OFFS			2
+#define PXCAR_REG_NUM_MAX			0x3F
+#define PXCAR_REG_NUM_MASK			(PXCAR_REG_NUM_MAX << PXCAR_REG_NUM_OFFS)
+#define PXCAR_FUNC_NUM_OFFS			8
+#define PXCAR_FUNC_NUM_MAX			0x7
+#define PXCAR_FUNC_NUM_MASK			(PXCAR_FUNC_NUM_MAX << PXCAR_FUNC_NUM_OFFS)
+#define PXCAR_DEVICE_NUM_OFFS		11
+#define PXCAR_DEVICE_NUM_MAX		0x1F
+#define PXCAR_DEVICE_NUM_MASK		(PXCAR_DEVICE_NUM_MAX << PXCAR_DEVICE_NUM_OFFS)
+#define PXCAR_BUS_NUM_OFFS			16
+#define PXCAR_BUS_NUM_MAX			0xFF
+#define PXCAR_BUS_NUM_MASK			(PXCAR_BUS_NUM_MAX << PXCAR_BUS_NUM_OFFS)
+#define PXCAR_EXT_REG_NUM_OFFS		24
+#define PXCAR_EXT_REG_NUM_MAX		0xF
+
+/* in pci express register address is now the legacy register address (8 bits)
+   with the new extended register address (more 4 bits) , below is the mask of
+   the upper 4 bits of the full register address */
+#define PXCAR_REAL_EXT_REG_NUM_OFFS	8
+#define PXCAR_EXT_REG_NUM_MASK		(PXCAR_EXT_REG_NUM_MAX << PXCAR_EXT_REG_NUM_OFFS)
+#define PXCAR_CONFIG_EN				BIT31
+
+#define PXCAR_REAL_EXT_REG_NUM_OFFS     8
+#define PXCAR_REAL_EXT_REG_NUM_MASK     (0xF << PXCAR_REAL_EXT_REG_NUM_OFFS)
+
+/* The traditional PCI spec defined 6-bit field to describe register offset. */
+/* The new PCI Express extend the register offset by an extra 4-bits.       */
+/* The below macro assign 10-bit register offset into the apprpreate        */
+/* fields in the CFG_ADDR_REG                                               */
+#define PXCAR_REG_OFFS_SET(regOffs)                         \
+ ((regOff & PXCAR_REG_NUM_MASK) | \
+   (((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >> PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS))
+
+/***********************************/
+/* PCI Express Interrupt registers */
+/***********************************/
+#define PEX_CAUSE_REG(pexIf)		((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1900)
+#define PEX_MASK_REG(pexIf)		((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1910)
+
+#define PXICR_TX_REQ_IN_DLDOWN_ERR  BIT0	/* Transmit request while field   */
+/* <DLDown> of the PCI Express    */
+/* PCI Express Interrupt Cause */
+/* PEX_INT_CAUSE_REG  (PXICR) */
+/* PEX_INT_MASK_REG */
+/*
+   NOTE:All bits except bits[27:24] are Read/Write Clear only. A cause bit sets
+   upon an error event occurrence. A write of 0 clears the bit. A write of 1 has
+   no affect. Bits[24:27] are set and cleared upon reception of interrupt
+   emulation messages.
+   Mask bit per cause bit. If a bit is set to 1, the corresponding event is
+   enabled. Mask does not affect setting of the Interrupt Cause register bits;
+   it only affects the assertion of the interrupt . */
+
+#define PXICR_MDIS_CAUSE			BIT1	/* Attempt to generate PCI transaction
+							   while master is disabled */
+#define PXICR_ERR_WRTO_REG_CAUSE		BIT3	/* Erroneous write attempt to
+							   PCI Express internal register */
+#define PXICR_HIT_DFLT_WIN_ERR			BIT4	/* Hit Default Window Error */
+#define PXICR_RX_RAM_PAR_ERR			BIT6	/* Rx RAM Parity Error */
+#define PXICR_TX_RAM_PAR_ERR			BIT7	/* Tx RAM Parity Error */
+#define PXICR_COR_ERR_DET			BIT8	/* Correctable Error Detected */
+#define PXICR_NF_ERR_DET			BIT9	/* Non-Fatal Error Detected */
+#define PXICR_FERR_DET				BIT10	/* Fatal Error Detected */
+#define PXICR_DSTATE_CHANGE			BIT11	/* Dstate Change Indication */
+#define PXICR_BIST				BIT12	/* PCI-Express BIST activated */
+#define PXICR_FLW_CTRL_PROT			BIT14	/* Flow Control Protocol Error */
+
+#define PXICR_RCV_UR_CA_ERR			BIT15	/* Received UR or CA status. */
+#define PXICR_RCV_ERR_FATAL			BIT16	/* Received ERR_FATAL message. */
+#define PXICR_RCV_ERR_NON_FATAL			BIT17	/* Received ERR_NONFATAL message */
+#define PXICR_RCV_ERR_COR			BIT18	/* Received ERR_COR message. */
+#define PXICR_RCV_CRS				BIT19	/* Received CRS completion status */
+#define PXICR_SLV_HOT_RESET			BIT20	/* Received Hot Reset Indication */
+#define PXICR_SLV_DIS_LINK			BIT21	/* Slave Disable Link Indication */
+#define PXICR_SLV_LB				BIT22	/* Slave Loopback Indication */
+#define PXICR_LINK_FAIL				BIT23	/* Link Failure indication. */
+#define PXICR_RCV_INTA				BIT24	/* IntA status. */
+#define PXICR_RCV_INTB				BIT25	/* IntB status. */
+#define PXICR_RCV_INTC				BIT26	/* IntC status. */
+#define PXICR_RCV_INTD				BIT27	/* IntD status. */
+#define PXICR_RCV_PM_PME			BIT28	/* Received PM_PME message. */
+
+/********************************************/
+/* PCI Express Control and Status Registers */
+/********************************************/
+#define PEX_CTRL_REG(pexIf)				((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A00)
+#define PEX_STATUS_REG(pexIf)				((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A04)
+#define PEX_COMPLT_TMEOUT_REG(pexIf)			((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A10)
+#define PEX_PWR_MNG_EXT_REG(pexIf)			((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A18)
+#define PEX_FLOW_CTRL_REG(pexIf)			((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A20)
+#define PEX_ACK_TMR_4X_REG(pexIf)			((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A30)
+#define PEX_ACK_TMR_1X_REG(pexIf)			((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A40)
+#define PEX_TL_CTRL_REG(pexIf)				(MV_PEX_IF_REGS_BASE(pexIf) - (pexIf)*0x10000)
+
+#define PEX_RAM_PARITY_CTRL_REG(pexIf) 			((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A50)
+#define PEX_DBG_CTRL_REG(pexIf) 			((MV_PEX_IF_REGS_BASE(pexIf)) + 0x1A60)
+
+/* PCI Express Control Register */
+/* PEX_CTRL_REG (PXCR) */
+
+#define PXCR_CONF_LINK_OFFS			0
+#define PXCR_CONF_LINK_MASK			(1 << PXCR_CONF_LINK_OFFS)
+#define PXCR_CONF_LINK_X4			(0 << PXCR_CONF_LINK_OFFS)
+#define PXCR_CONF_LINK_X1			(1 << PXCR_CONF_LINK_OFFS)
+#define PXCR_DEV_TYPE_CTRL_OFFS			1	/*PCI ExpressDevice Type Control */
+#define PXCR_DEV_TYPE_CTRL_MASK			BIT1
+#define PXCR_DEV_TYPE_CTRL_CMPLX		(1 << PXCR_DEV_TYPE_CTRL_OFFS)
+#define PXCR_DEV_TYPE_CTRL_POINT		(0 << PXCR_DEV_TYPE_CTRL_OFFS)
+#define PXCR_CFG_MAP_TO_MEM_EN			BIT2	/* Configuration Header Mapping
+							   to Memory Space Enable         */
+
+#define PXCR_CFG_MAP_TO_MEM_EN			BIT2	/* Configuration Header Mapping
+							   to Memory Space Enable */
+
+#define PXCR_RSRV1_OFFS				5
+#define PXCR_RSRV1_MASK				(0x7 << PXCR_RSRV1_OFFS)
+#define PXCR_RSRV1_VAL				(0x0 << PXCR_RSRV1_OFFS)
+
+#define PXCR_CONF_MAX_OUTSTND_OFFS		8	/*Maximum outstanding NP requests as a master */
+#define PXCR_CONF_MAX_OUTSTND_MASK		(0x3 << PXCR_CONF_MAX_OUTSTND_OFFS)
+
+#define PXCR_CONF_NFTS_OFFS			16	/*number of FTS Ordered-Sets */
+#define PXCR_CONF_NFTS_MASK			(0xff << PXCR_CONF_NFTS_OFFS)
+
+#define PXCR_CONF_MSTR_HOT_RESET		BIT24	/*Master Hot-Reset. */
+#define PXCR_CONF_MSTR_LB			BIT26	/* Master Loopback */
+#define PXCR_CONF_MSTR_DIS_SCRMB		BIT27	/* Master Disable Scrambling */
+#define PXCR_CONF_DIRECT_DIS_SCRMB		BIT28	/* Direct Disable Scrambling */
+
+/* PCI Express Status Register */
+/* PEX_STATUS_REG (PXSR) */
+
+#define PXSR_DL_DOWN				BIT0	/* DL_Down indication. */
+
+#define PXSR_PEX_BUS_NUM_OFFS			8	/* Bus Number Indication */
+#define PXSR_PEX_BUS_NUM_MASK			(0xff << PXSR_PEX_BUS_NUM_OFFS)
+
+#define PXSR_PEX_DEV_NUM_OFFS			16	/* Device Number Indication */
+#define PXSR_PEX_DEV_NUM_MASK			(0x1f << PXSR_PEX_DEV_NUM_OFFS)
+
+#define PXSR_PEX_SLV_HOT_RESET			BIT24	/* Slave Hot Reset Indication */
+#define PXSR_PEX_SLV_DIS_LINK			BIT25	/* Slave Disable Link Indication */
+#define PXSR_PEX_SLV_LB					BIT26	/* Slave Loopback Indication */
+#define PXSR_PEX_SLV_DIS_SCRMB			BIT27	/* Slave Disable Scrambling Indication */
+
+/* PCI Express Completion Timeout Register */
+/* PEX_COMPLT_TMEOUT_REG (PXCTR) */
+
+#define PXCTR_CMP_TO_THRSHLD_OFFS		0	/* Completion Timeout Threshold */
+#define PXCTR_CMP_TO_THRSHLD_MASK		(0xffff << PXCTR_CMP_TO_THRSHLD_OFFS)
+
+/* PCI Express Power Management Extended Register */
+/* PEX_PWR_MNG_EXT_REG (PXPMER) */
+
+#define PXPMER_L1_ASPM_EN_OFFS			1
+#define PXPMER_L1_ASPM_EN_MASK			(0x1 << PXPMER_L1_ASPM_EN_OFFS)
+
+/* PCI Express Flow Control Register */
+/* PEX_FLOW_CTRL_REG (PXFCR) */
+
+#define PXFCR_PH_INIT_FC_OFFS			0	/*Posted Headers Flow Control Credit
+							  Initial Value. */
+#define PXFCR_PH_INIT_FC_MASK			(0xff << PXFCR_PH_INIT_FC_OFFS)
+
+#define PXFCR_NPH_INIT_FC_OFFS			8	/* Classified Non-Posted Headers
+							   Flow Control Credit Initial Value */
+#define PXFCR_NPH_INIT_FC_MASK			(0xff << PXFCR_NPH_INIT_FC_OFFS)
+
+#define PXFCR_CH_INIT_FC_OFFS			16	/* Completion Headers Flow Control
+							   Credit Initial Value Infinite */
+
+#define PXFCR_CH_INIT_FC_MASK			(0xff << PXFCR_CH_INIT_FC_OFFS)
+
+#define PXFCR_FC_UPDATE_TO_OFFS			24	/* Flow Control Update Timeout */
+#define PXFCR_FC_UPDATE_TO_MASK			(0xff << PXFCR_FC_UPDATE_TO_OFFS)
+
+/* PCI Express Acknowledge Timers (4X) Register */
+/* PEX_ACK_TMR_4X_REG (PXAT4R) */
+#define PXAT1R_ACK_LAT_TOX4_OFFS		0	/* Ack Latency Timer Timeout Value */
+#define PXAT1R_ACK_LAT_TOX4_MASK		(0xffff << PXAT4R_ACK_LAT_TOX1_OFFS)
+#define PXAT1R_ACK_RPLY_TOX4_OFFS		16	/* Ack Replay Timer Timeout Value  */
+#define PXAT1R_ACK_RPLY_TOX4_MASK		(0xffff << PXAT1R_ACK_RPLY_TOX1_OFFS)
+
+/* PCI Express Acknowledge Timers (1X) Register */
+/* PEX_ACK_TMR_1X_REG (PXAT1R) */
+
+#define PXAT1R_ACK_LAT_TOX1_OFFS		0	/* Acknowledge Latency Timer Timeout
+							   Value for 1X Link */
+#define PXAT1R_ACK_LAT_TOX1_MASK		(0xffff << PXAT1R_ACK_LAT_TOX1_OFFS)
+
+#define PXAT1R_ACK_RPLY_TOX1_OFFS		16	/* Acknowledge Replay Timer Timeout
+							   Value for 1X */
+#define PXAT1R_ACK_RPLY_TOX1_MASK		(0xffff << PXAT1R_ACK_RPLY_TOX1_OFFS)
+
+/* PCI Express TL Control Register */
+/* PEX_TL_CTRL_REG (PXTCR) */
+
+#define PXTCR_TX_CMP_BUFF_NO_OFFS		8	/*Number of completion buffers in Tx */
+#define PXTCR_TX_CMP_BUFF_NO_MASK		(0xf << PXTCR_TX_CMP_BUFF_NO_OFFS)
+
+/* PCI Express Debug MAC Control Register */
+/* PEX_DEBUG_MAC_CTRL_REG (PXDMCR) */
+
+#define PXDMCR_LINKUP				BIT4
+
+/**********************************************/
+/* PCI Express Configuration Header Registers */
+/**********************************************/
+
+#define PEX_CFG_DIRECT_ACCESS(pexIf, cfgReg)	(MV_PEX_IF_REGS_BASE(pexIf) + (cfgReg))
+
+#define PEX_DEVICE_AND_VENDOR_ID					0x000
+#define PEX_STATUS_AND_COMMAND						0x004
+#define PEX_CLASS_CODE_AND_REVISION_ID					0x008
+#define PEX_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE				0x00C
+#define PEX_MEMORY_BAR_BASE_ADDR(barNum)				(0x010 + ((barNum) << 2))
+#define PEX_MV_BAR_BASE(barNum)						(0x010 + (barNum) * 8)
+#define PEX_MV_BAR_BASE_HIGH(barNum)					(0x014 + (barNum) * 8)
+#define PEX_BAR0_INTER_REG						0x010
+#define PEX_BAR0_INTER_REG_HIGH						0x014
+#define PEX_BAR1_REG							0x018
+#define PEX_BAR1_REG_HIGH						0x01C
+#define PEX_BAR2_REG							0x020
+#define PEX_BAR2_REG_HIGH						0x024
+
+#define PEX_SUBSYS_ID_AND_SUBSYS_VENDOR_ID				0x02C
+#define PEX_EXPANSION_ROM_BASE_ADDR_REG					0x030
+#define PEX_CAPABILTY_LIST_POINTER					0x034
+#define PEX_INTERRUPT_PIN_AND_LINE					0x03C
+
+/* capability list */
+#define PEX_POWER_MNG_CAPABILITY					0x040
+#define PEX_POWER_MNG_STATUS_CONTROL					0x044
+
+#define PEX_MSI_MESSAGE_CONTROL						0x050
+#define PEX_MSI_MESSAGE_ADDR						0x054
+#define PEX_MSI_MESSAGE_HIGH_ADDR					0x058
+#define PEX_MSI_MESSAGE_DATA						0x05C
+
+#define PEX_CAPABILITY_REG						0x60
+#define PEX_DEV_CAPABILITY_REG						0x64
+#define PEX_DEV_CTRL_STAT_REG						0x68
+#define PEX_LINK_CAPABILITY_REG						0x6C
+#define PXLC_MAX_LNK_SPEED_OFFS						0
+#define PXLC_MAX_LNK_SPEED_MASK						(0xf << PXLC_MAX_LNK_SPEED_OFFS)
+
+#define PEX_LINK_CTRL_STAT_REG						0x70
+
+#define PEX_ADV_ERR_RPRT_HDR_TRGT_REG					0x100
+#define PEX_UNCORRECT_ERR_STAT_REG					0x104
+#define PEX_UNCORRECT_ERR_MASK_REG					0x108
+#define PEX_UNCORRECT_ERR_SERVITY_REG					0x10C
+#define PEX_CORRECT_ERR_STAT_REG					0x110
+#define PEX_CORRECT_ERR_MASK_REG					0x114
+#define PEX_ADV_ERR_CAPABILITY_CTRL_REG					0x118
+#define PEX_HDR_LOG_FIRST_DWORD_REG					0x11C
+#define PEX_HDR_LOG_SECOND_DWORD_REG					0x120
+#define PEX_HDR_LOG_THIRD_DWORD_REG					0x124
+#define PEX_HDR_LOG_FOURTH_DWORD_REG					0x128
+
+/* PCI Express Device and Vendor ID Register */
+/* PEX_DEVICE_AND_VENDOR_ID (PXDAVI) */
+
+#define PXDAVI_VEN_ID_OFFS			0	/* Vendor ID */
+#define PXDAVI_VEN_ID_MASK			(0xffff << PXDAVI_VEN_ID_OFFS)
+
+#define PXDAVI_DEV_ID_OFFS			16	/* Device ID */
+#define PXDAVI_DEV_ID_MASK 			(0xffff << PXDAVI_DEV_ID_OFFS)
+
+/* PCI Express Command and Status Register */
+/* PEX_STATUS_AND_COMMAND (PXSAC) */
+
+#define PXSAC_IO_EN			BIT0	/* IO Enable                                                      */
+#define PXSAC_MEM_EN			BIT1	/* Memory Enable                                                  */
+#define PXSAC_MASTER_EN			BIT2	/* Master Enable                                                  */
+#define PXSAC_PERR_EN			BIT6	/* Parity Errors Respond Enable                   */
+#define PXSAC_SERR_EN			BIT8	/* Ability to assert SERR# line                   */
+#define PXSAC_INT_DIS			BIT10	/* Interrupt Disable                                      */
+#define PXSAC_INT_STAT			BIT19	/* Interrupt Status                     */
+#define PXSAC_CAP_LIST			BIT20	/* Capability List Support                                */
+#define PXSAC_MAS_DATA_PERR		BIT24	/* Master Data Parity Error                               */
+#define PXSAC_SLAVE_TABORT		BIT27	/* Signalled Target Abort       */
+#define PXSAC_RT_ABORT			BIT28	/* Recieved Target Abort        */
+#define PXSAC_MABORT			BIT29	/* Recieved Master Abort        */
+#define PXSAC_SYSERR			BIT30	/* Signalled system error       */
+#define PXSAC_DET_PARERR		BIT31	/* Detect Parity Error          */
+
+/* PCI Express Class Code and Revision ID Register */
+/* PEX_CLASS_CODE_AND_REVISION_ID (PXCCARI) */
+
+#define PXCCARI_REVID_OFFS		0	/* Revision ID */
+#define PXCCARI_REVID_MASK		(0xff << PXCCARI_REVID_OFFS)
+
+#define PXCCARI_FULL_CLASS_OFFS		8	/* Full Class Code */
+#define PXCCARI_FULL_CLASS_MASK		(0xffffff << PXCCARI_FULL_CLASS_OFFS)
+
+#define PXCCARI_PROGIF_OFFS		8	/* Prog .I/F */
+#define PXCCARI_PROGIF_MASK		(0xff << PXCCARI_PROGIF_OFFS)
+
+#define PXCCARI_SUB_CLASS_OFFS		16	/* Sub Class */
+#define PXCCARI_SUB_CLASS_MASK		(0xff << PXCCARI_SUB_CLASS_OFFS)
+
+#define PXCCARI_BASE_CLASS_OFFS		24	/* Base Class */
+#define PXCCARI_BASE_CLASS_MASK		(0xff << PXCCARI_BASE_CLASS_OFFS)
+
+/* PCI Express BIST, Header Type and Cache Line Size Register */
+/* PEX_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE (PXBHTLTCL) */
+
+#define PXBHTLTCL_CACHELINE_OFFS	0	/* Specifies the cache line size */
+#define PXBHTLTCL_CACHELINE_MASK	(0xff << PXBHTLTCL_CACHELINE_OFFS)
+
+#define PXBHTLTCL_HEADTYPE_FULL_OFFS	16	/* Full Header Type */
+#define PXBHTLTCL_HEADTYPE_FULL_MASK	(0xff << PXBHTLTCL_HEADTYPE_FULL_OFFS)
+
+#define PXBHTLTCL_MULTI_FUNC		BIT23	/* Multi/Single function */
+
+#define PXBHTLTCL_HEADER_OFFS			16	/* Header type */
+#define PXBHTLTCL_HEADER_MASK			(0x7f << PXBHTLTCL_HEADER_OFFS)
+#define PXBHTLTCL_HEADER_STANDARD		(0x0 << PXBHTLTCL_HEADER_OFFS)
+#define PXBHTLTCL_HEADER_PCI2PCI_BRIDGE		(0x1 << PXBHTLTCL_HEADER_OFFS)
+
+#define PXBHTLTCL_BISTCOMP_OFFS			24	/* BIST Completion Code */
+#define PXBHTLTCL_BISTCOMP_MASK			(0xf << PXBHTLTCL_BISTCOMP_OFFS)
+
+#define PXBHTLTCL_BISTACT			BIT30	/* BIST Activate bit */
+#define PXBHTLTCL_BISTCAP			BIT31	/* BIST Capable Bit */
+#define PXBHTLTCL_BISTCAP_OFFS			31
+#define PXBHTLTCL_BISTCAP_MASK			BIT31
+#define PXBHTLTCL_BISTCAP_VAL			0
+
+/* PCI Express Subsystem Device and Vendor ID */
+/* PEX_SUBSYS_ID_AND_SUBSYS_VENDOR_ID (PXSIASVI) */
+
+#define PXSIASVI_VENID_OFFS	0	/* Subsystem Manufacturer Vendor ID Number */
+#define PXSIASVI_VENID_MASK	(0xffff << PXSIASVI_VENID_OFFS)
+
+#define PXSIASVI_DEVID_OFFS	16	/* Subsystem Device ID Number */
+#define PXSIASVI_DEVID_MASK	(0xffff << PXSIASVI_DEVID_OFFS)
+
+/* PCI Express Capability List Pointer Register */
+/* PEX_CAPABILTY_LIST_POINTER (PXCLP) */
+
+#define PXCLP_CAPPTR_OFFS	0	/* Capability List Pointer */
+#define PXCLP_CAPPTR_MASK	(0xff << PXCLP_CAPPTR_OFFS)
+
+/* PCI Express Interrupt Pin and Line Register */
+/*PEX_INTERRUPT_PIN_AND_LINE (PXIPAL) */
+
+#define PXIPAL_INTLINE_OFFS	0	/* Interrupt line (IRQ) */
+#define PXIPAL_INTLINE_MASK	(0xff << PXIPAL_INTLINE_OFFS)
+
+#define PXIPAL_INTPIN_OFFS	8	/* interrupt pin (A, B, C, D) */
+#define PXIPAL_INTPIN_MASK	(0xff << PXIPAL_INTPIN_OFFS)
+
+/* PCI Express Power Management Capability Header Register */
+/* PEX_POWER_MNG_CAPABILITY (PXPMC) */
+
+#define PXPMC_CAP_ID_OFFS		0	/* Capability ID */
+#define PXPMC_CAP_ID_MASK		(0xff << PXPMC_CAP_ID_OFFS)
+
+#define PXPMC_NEXT_PTR_OFFS		8	/* Next Item Pointer */
+#define PXPMC_NEXT_PTR_MASK		(0xff << PXPMC_NEXT_PTR_OFFS)
+
+#define PXPMC_PMC_VER_OFFS		16	/* PCI Power Management Capability Version */
+#define PXPMC_PMC_VER_MASK		(0x7 << PXPMC_PMC_VER_OFFS)
+
+#define PXPMC_DSI 				BIT21	/* Device Specific Initialization */
+
+#define PXPMC_AUX_CUR_OFFS		22	/* Auxiliary Current Requirements */
+#define PXPMC_AUX_CUR_MASK		(0x7 << PXPMC_AUX_CUR_OFFS)
+
+#define PXPMC_D1_SUP 			BIT25	/* D1 Power Management support */
+
+#define PXPMC_D2_SUP 			BIT26	/* D2 Power Management support */
+
+#define PXPMC_PME_SUP_OFFS		27	/* PM Event generation support */
+#define PXPMC_PME_SUP_MASK		(0x1f << PXPMC_PME_SUP_OFFS)
+
+/* PCI Express Power Management Control and Status Register */
+/* PEX_POWER_MNG_STATUS_CONTROL (PXPMSC) */
+
+#define PXPMSC_PM_STATE_OFFS	0	/* Power State */
+#define PXPMSC_PM_STATE_MASK	(0x3 << PXPMSC_PM_STATE_OFFS)
+#define PXPMSC_PM_STATE_D0		(0x0 << PXPMSC_PM_STATE_OFFS)
+#define PXPMSC_PM_STATE_D1		(0x1 << PXPMSC_PM_STATE_OFFS)
+#define PXPMSC_PM_STATE_D2		(0x2 << PXPMSC_PM_STATE_OFFS)
+#define PXPMSC_PM_STATE_D3		(0x3 << PXPMSC_PM_STATE_OFFS)
+
+#define PXPMSC_PME_EN			BIT8	/* PM_PME Message Generation Enable */
+
+#define PXPMSC_PM_DATA_SEL_OFFS	9	/* Data Select */
+#define PXPMSC_PM_DATA_SEL_MASK	(0xf << PXPMSC_PM_DATA_SEL_OFFS)
+
+#define PXPMSC_PM_DATA_SCALE_OFFS	13	/* Data Scale */
+#define PXPMSC_PM_DATA_SCALE_MASK	(0x3 << PXPMSC_PM_DATA_SCALE_OFFS)
+
+#define PXPMSC_PME_STAT				BIT15	/* PME Status */
+
+#define PXPMSC_PM_DATA_OFFS			24	/* State Data */
+#define PXPMSC_PM_DATA_MASK			(0xff << PXPMSC_PM_DATA_OFFS)
+
+/* PCI Express MSI Message Control Register */
+/* PEX_MSI_MESSAGE_CONTROL (PXMMC) */
+
+#define PXMMC_CAP_ID_OFFS			0	/* Capability ID */
+#define PXMMC_CAP_ID_MASK			(0xff << PXMMC_CAP_ID_OFFS)
+
+#define PXMMC_NEXT_PTR_OFFS			8	/* Next Item Pointer */
+#define PXMMC_NEXT_PTR_MASK			(0xff << PXMMC_NEXT_PTR_OFFS)
+
+#define PXMMC_MSI_EN				BIT18	/* MSI Enable */
+
+#define PXMMC_MULTI_CAP_OFFS			17	/* Multiple Message Capable */
+#define PXMMC_MULTI_CAP_MASK			(0x7 << PXMMC_MULTI_CAP_OFFS)
+
+#define PXMMC_MULTI_EN_OFFS			20	/* Multiple Messages Enable */
+#define PXMMC_MULTI_EN_MASK			(0x7 << PXMMC_MULTI_EN_OFFS)
+
+#define PXMMC_ADDR64				BIT23	/* 64-bit Addressing Capable */
+
+/* PCI Express MSI Message Address Register */
+/* PEX_MSI_MESSAGE_ADDR (PXMMA) */
+
+#define PXMMA_MSI_ADDR_OFFS			2	/* Message Address  corresponds to
+			Address[31:2] of the MSI MWr TLP */
+#define PXMMA_MSI_ADDR_MASK			(0x3fffffff << PXMMA_MSI_ADDR_OFFS)
+
+/* PCI Express MSI Message Address (High) Register */
+/* PEX_MSI_MESSAGE_HIGH_ADDR (PXMMHA) */
+
+#define PXMMA_MSI_ADDR_H_OFFS			0	/* Message Upper Address corresponds to
+							   Address[63:32] of the MSI MWr TLP */
+#define PXMMA_MSI_ADDR_H_MASK			(0xffffffff << PXMMA_MSI_ADDR_H_OFFS)
+
+/* PCI Express MSI Message Data Register */
+/* PEX_MSI_MESSAGE_DATA (PXMMD) */
+
+#define PXMMD_MSI_DATA_OFFS			0	/* Message Data */
+#define PXMMD_MSI_DATA_MASK			(0xffff << PXMMD_MSI_DATA_OFFS)
+
+/* PCI Express Capability Register */
+/* PEX_CAPABILITY_REG (PXCR) */
+
+#define PXCR_CAP_ID_OFFS			0	/* Capability ID */
+#define PXCR_CAP_ID_MASK			(0xff << PXCR_CAP_ID_OFFS)
+
+#define PXCR_NEXT_PTR_OFFS			8	/* Next Item Pointer */
+#define PXCR_NEXT_PTR_MASK			(0xff << PXCR_NEXT_PTR_OFFS)
+
+#define PXCR_CAP_VER_OFFS			16	/* Capability Version */
+#define PXCR_CAP_VER_MASK			(0xf << PXCR_CAP_VER_OFFS)
+
+#define PXCR_DEV_TYPE_OFFS			20	/*  Device/Port Type */
+#define PXCR_DEV_TYPE_MASK			(0xf << PXCR_DEV_TYPE_OFFS)
+
+#define PXCR_SLOT_IMP 				BIT24	/* Slot Implemented */
+
+#define PXCR_INT_MSG_NUM_OFFS			25	/* Interrupt Message Number */
+#define PXCR_INT_MSG_NUM_MASK			(0x1f << PXCR_INT_MSG_NUM_OFFS)
+
+/* PCI Express Device Capabilities Register */
+/* PEX_DEV_CAPABILITY_REG (PXDCR) */
+
+#define PXDCR_MAX_PLD_SIZE_SUP_OFFS		0	/* Maximum Payload Size Supported */
+#define PXDCR_MAX_PLD_SIZE_SUP_MASK		(0x7 << PXDCR_MAX_PLD_SIZE_SUP_OFFS)
+
+#define PXDCR_EP_L0S_ACC_LAT_OFFS		6	/* Endpoint L0s Acceptable Latency */
+#define PXDCR_EP_L0S_ACC_LAT_MASK		(0x7 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+#define PXDCR_EP_L0S_ACC_LAT_64NS_LESS		(0x0 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+#define PXDCR_EP_L0S_ACC_LAT_64NS_128NS		(0x1 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+#define PXDCR_EP_L0S_ACC_LAT_128NS_256NS	(0x2 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+#define PXDCR_EP_L0S_ACC_LAT_256NS_512NS	(0x3 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+#define PXDCR_EP_L0S_ACC_LAT_512NS_1US		(0x4 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+#define PXDCR_EP_L0S_ACC_LAT_1US_2US		(0x5 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+#define PXDCR_EP_L0S_ACC_LAT_2US_4US		(0x6 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+#define PXDCR_EP_L0S_ACC_LAT_4US_MORE		(0x7 << PXDCR_EP_L0S_ACC_LAT_OFFS)
+
+#define PXDCR_EP_L1_ACC_LAT_OFFS		9	/* Endpoint L1 Acceptable Latency */
+#define PXDCR_EP_L1_ACC_LAT_MASK		(0x7 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXDCR_EP_L1_ACC_LAT_64NS_LESS		(0x0 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXDCR_EP_L1_ACC_LAT_64NS_128NS		(0x1 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXDCR_EP_L1_ACC_LAT_128NS_256NS		(0x2 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXDCR_EP_L1_ACC_LAT_256NS_512NS		(0x3 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXDCR_EP_L1_ACC_LAT_512NS_1US		(0x4 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXDCR_EP_L1_ACC_LAT_1US_2US		(0x5 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXDCR_EP_L1_ACC_LAT_2US_4US		(0x6 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXDCR_EP_L1_ACC_LAT_4US_MORE		(0x7 << PXDCR_EP_L1_ACC_LAT_OFFS)
+
+#define PXDCR_ATT_BUT_PRS_OFFS			12	/* Attention Button Present */
+#define PXDCR_ATT_BUT_PRS_MASK			BIT12
+#define PXDCR_ATT_BUT_PRS_IMPLEMENTED		BIT12
+
+#define PXDCR_ATT_IND_PRS_OFFS			13	/* Attention Indicator Present */
+#define PXDCR_ATT_IND_PRS_MASK			BIT13
+#define PXDCR_ATT_IND_PRS_IMPLEMENTED		BIT13
+
+#define PXDCR_PWR_IND_PRS_OFFS			14	/* Power Indicator Present */
+#define PXDCR_PWR_IND_PRS_MASK			BIT14
+#define PXDCR_PWR_IND_PRS_IMPLEMENTED		BIT14
+
+#define PXDCR_CAP_SPL_VAL_OFFS			18	/* Captured Slot Power Limit
+							   Value */
+#define PXDCR_CAP_SPL_VAL_MASK			(0xff << PXDCR_CAP_SPL_VAL_OFFS)
+
+#define PXDCR_CAP_SP_LSCL_OFFS			26	/* Captured Slot Power Limit
+							   Scale */
+#define PXDCR_CAP_SP_LSCL_MASK			(0x3 << PXDCR_CAP_SP_LSCL_OFFS)
+
+/* PCI Express Device Control Status Register */
+/* PEX_DEV_CTRL_STAT_REG (PXDCSR) */
+
+#define PXDCSR_COR_ERR_REP_EN			BIT0	/* Correctable Error Reporting Enable */
+#define PXDCSR_NF_ERR_REP_EN			BIT1	/* Non-Fatal Error Reporting Enable */
+#define PXDCSR_F_ERR_REP_EN			BIT2	/* Fatal Error Reporting Enable */
+#define PXDCSR_UR_REP_EN			BIT3	/* Unsupported Request (UR)
+							   Reporting Enable */
+#define PXDCSR_EN_RO 				BIT4	/* Enable Relaxed Ordering */
+
+#define PXDCSR_MAX_PLD_SZ_OFFS		5	/* Maximum Payload Size */
+#define PXDCSR_MAX_PLD_SZ_MASK		(0x7 << PXDCSR_MAX_PLD_SZ_OFFS)
+#define PXDCSR_MAX_PLD_SZ_128B		(0x0 << PXDCSR_MAX_PLD_SZ_OFFS)
+#define PXDCSR_EN_NS				BIT11	/* Enable No Snoop */
+
+#define PXDCSR_MAX_RD_RQ_SZ_OFFS	12	/* Maximum Read Request Size */
+#define PXDCSR_MAX_RD_RQ_SZ_MASK	(0x7 << PXDCSR_MAX_RD_RQ_SZ_OFFS)
+#define PXDCSR_MAX_RD_RQ_SZ_128B	(0x0 << PXDCSR_MAX_RD_RQ_SZ_OFFS)
+#define PXDCSR_MAX_RD_RQ_SZ_256B	(0x1 << PXDCSR_MAX_RD_RQ_SZ_OFFS)
+#define PXDCSR_MAX_RD_RQ_SZ_512B	(0x2 << PXDCSR_MAX_RD_RQ_SZ_OFFS)
+#define PXDCSR_MAX_RD_RQ_SZ_1KB		(0x3 << PXDCSR_MAX_RD_RQ_SZ_OFFS)
+#define PXDCSR_MAX_RD_RQ_SZ_2KB		(0x4 << PXDCSR_MAX_RD_RQ_SZ_OFFS)
+#define PXDCSR_MAX_RD_RQ_SZ_4KB		(0x5 << PXDCSR_MAX_RD_RQ_SZ_OFFS)
+
+#define PXDCSR_COR_ERR_DET			BIT16	/* Correctable Error Detected */
+#define PXDCSR_NF_ERR_DET			BIT17	/* Non-Fatal Error Detected. */
+#define PXDCSR_F_ERR_DET			BIT18	/* Fatal Error Detected. */
+#define PXDCSR_UR_DET				BIT19	/* Unsupported Request Detected */
+#define PXDCSR_AUX_PWR_DET			BIT20	/* Reserved */
+
+#define PXDCSR_TRANS_PEND_OFFS			21	/* Transactions Pending */
+#define PXDCSR_TRANS_PEND_MASK			BIT21
+#define PXDCSR_TRANS_PEND_NOT_COMPLETED		(0x1 << PXDCSR_TRANS_PEND_OFFS)
+
+/* PCI Express Link Capabilities Register */
+/* PEX_LINK_CAPABILITY_REG (PXLCR) */
+
+#define PXLCR_MAX_LINK_SPD_OFFS		0	/* Maximum Link Speed */
+#define PXLCR_MAX_LINK_SPD_MASK		(0xf << PXLCR_MAX_LINK_SPD_OFFS)
+
+#define PXLCR_MAX_LNK_WDTH_OFFS 	3	/* Maximum Link Width */
+#define PXLCR_MAX_LNK_WDTH_MASK		(0x3f << PXLCR_MAX_LNK_WDTH_OFFS)
+
+#define PXLCR_ASPM_SUP_OFFS 		10	/* Active State Link PM Support */
+#define PXLCR_ASPM_SUP_MASK			(0x3 << PXLCR_ASPM_SUP_OFFS)
+
+#define PXLCR_L0S_EXT_LAT_OFFS 			12	/* L0s Exit Latency */
+#define PXLCR_L0S_EXT_LAT_MASK			(0x7 << PXLCR_L0S_EXT_LAT_OFFS)
+#define PXLCR_L0S_EXT_LAT_64NS_LESS     (0x0 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXLCR_L0S_EXT_LAT_64NS_128NS   	(0x1 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXLCR_L0S_EXT_LAT_128NS_256NS   (0x2 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXLCR_L0S_EXT_LAT_256NS_512NS   (0x3 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXLCR_L0S_EXT_LAT_512NS_1US     (0x4 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXLCR_L0S_EXT_LAT_1US_2US       (0x5 << PXDCR_EP_L1_ACC_LAT_OFFS)
+#define PXLCR_L0S_EXT_LAT_2US_4US       (0x6 << PXDCR_EP_L1_ACC_LAT_OFFS)
+
+#define PXLCR_POR_TNUM_OFFS 			24	/* Port Number */
+#define PXLCR_POR_TNUM_MASK			(0xff << PXLCR_POR_TNUM_OFFS)
+
+/* PCI Express Link Control Status Register */
+/* PEX_LINK_CTRL_STAT_REG (PXLCSR) */
+
+#define PXLCSR_ASPM_CNT_OFFS			0	/* Active State Link PM Control */
+#define PXLCSR_ASPM_CNT_MASK			(0x3 << PXLCSR_ASPM_CNT_OFFS)
+#define PXLCSR_ASPM_CNT_DISABLED		(0x0 << PXLCSR_ASPM_CNT_OFFS)
+#define PXLCSR_ASPM_CNT_L0S_ENT_SUPP		(0x1 << PXLCSR_ASPM_CNT_OFFS)
+#define PXLCSR_ASPM_CNT_L1S_ENT_SUPP		(0x2 << PXLCSR_ASPM_CNT_OFFS)
+#define PXLCSR_ASPM_CNT_L0S_L1S_ENT_SUPP	(0x3 << PXLCSR_ASPM_CNT_OFFS)
+
+#define PXLCSR_RCB_OFFS				3	/* Read Completion Boundary */
+#define PXLCSR_RCB_MASK				BIT3
+#define PXLCSR_RCB_64B				(0 << PXLCSR_RCB_OFFS)
+#define PXLCSR_RCB_128B				(1 << PXLCSR_RCB_OFFS)
+
+#define PXLCSR_LNK_DIS 				BIT4	/* Link Disable */
+#define PXLCSR_RETRN_LNK 			BIT5	/* Retrain Link */
+#define PXLCSR_CMN_CLK_CFG			BIT6	/* Common Clock Configuration */
+#define PXLCSR_EXTD_SNC 			BIT7	/* Extended Sync */
+
+#define PXLCSR_LNK_SPD_OFFS 			16	/* Link Speed */
+#define PXLCSR_LNK_SPD_MASK			(0xf << PXLCSR_LNK_SPD_OFFS)
+
+#define PXLCSR_NEG_LNK_WDTH_OFFS		20	/* Negotiated Link Width */
+#define PXLCSR_NEG_LNK_WDTH_MASK 		(0x3f << PXLCSR_NEG_LNK_WDTH_OFFS)
+#define PXLCSR_NEG_LNK_WDTH_X1			(0x1 << PXLCSR_NEG_LNK_WDTH_OFFS)
+
+#define PXLCSR_LNK_TRN 				BIT27	/* Link Training */
+
+#define PXLCSR_SLT_CLK_CFG_OFFS			28	/* Slot Clock Configuration */
+#define PXLCSR_SLT_CLK_CFG_MASK			BIT28
+#define PXLCSR_SLT_CLK_CFG_INDPNT		(0x0 << PXLCSR_SLT_CLK_CFG_OFFS)
+#define PXLCSR_SLT_CLK_CFG_REF			(0x1 << PXLCSR_SLT_CLK_CFG_OFFS)
+
+/* PCI Express Advanced Error Report Header Register */
+/* PEX_ADV_ERR_RPRT_HDR_TRGT_REG (PXAERHTR) */
+
+/* PCI Express Uncorrectable Error Status Register */
+/* PEX_UNCORRECT_ERR_STAT_REG (PXUESR) */
+
+/* PCI Express Uncorrectable Error Mask Register */
+/* PEX_UNCORRECT_ERR_MASK_REG (PXUEMR) */
+
+/* PCI Express Uncorrectable Error Severity Register */
+/* PEX_UNCORRECT_ERR_SERVITY_REG (PXUESR) */
+
+/* PCI Express Correctable Error Status Register */
+/* PEX_CORRECT_ERR_STAT_REG (PXCESR) */
+
+/* PCI Express Correctable Error Mask Register */
+/* PEX_CORRECT_ERR_MASK_REG (PXCEMR) */
+
+/* PCI Express Advanced Error Capability and Control Register */
+/* PEX_ADV_ERR_CAPABILITY_CTRL_REG (PXAECCR) */
+
+/* PCI Express Header Log First DWORD Register */
+/* PEX_HDR_LOG_FIRST_DWORD_REG (PXHLFDR) */
+
+/* PCI Express Header Log Second DWORD Register */
+/* PEX_HDR_LOG_SECOND_DWORD_REG (PXHLSDR) */
+
+/* PCI Express Header Log Third DWORD Register */
+/* PEX_HDR_LOG_THIRD_DWORD_REG (PXHLTDR) */
+
+/* PCI Express Header Log Fourth DWORD Register */
+/* PEX_HDR_LOG_FOURTH_DWORD_REG (PXHLFDR) */
+
+/* 4KB granularity */
+#define MINIMUM_WINDOW_SIZE		0x1000
+#define MINIMUM_BAR_SIZE		0x1000
+#define MINIMUM_BAR_SIZE_MASK		0xFFFFF000
+#define BAR_SIZE_OFFS			12
+#define BAR_SIZE_MASK			(0xFFFFF << BAR_SIZE_OFFS)
+
+#define MV_PEX_WIN_DEFAULT		6
+#define MV_PEX_WIN_EXP_ROM		7
+#define PEX_MAX_TARGET_WIN		8
+
+#define PEX_MAX_BARS			3
+#define PEX_INTER_REGS_BAR		0
+#define PEX_DRAM_BAR			1
+#define PEX_DEVICE_BAR			2
+
+/*************************************/
+/* PCI Express BAR Control Registers */
+/*************************************/
+#define PEX_BAR_CTRL_REG(pexIf, bar)		(MV_PEX_IF_REGS_BASE(pexIf) + 0x1804 + (bar-1)*4)
+#define PEX_EXP_ROM_BAR_CTRL_REG(pexIf)		(MV_PEX_IF_REGS_BASE(pexIf) + 0x180C)
+
+/* PCI Express BAR Control Register */
+/* PEX_BAR_CTRL_REG (PXBCR) */
+
+#define PXBCR_BAR_EN				BIT0
+#define PXBCR_BAR_SIZE_OFFS			16
+#define PXBCR_BAR_SIZE_MASK			(0xffff << PXBCR_BAR_SIZE_OFFS)
+#define PXBCR_BAR_SIZE_ALIGNMENT		0x10000
+
+/* PCI Express Expansion ROM BAR Control Register */
+/* PEX_EXP_ROM_BAR_CTRL_REG (PXERBCR) */
+
+#define PXERBCR_EXPROM_EN		BIT0
+#define PXERBCR_EXPROMSZ_OFFS		19
+#define PXERBCR_EXPROMSZ_MASK		(0xf << PXERBCR_EXPROMSZ_OFFS)
+#define PXERBCR_EXPROMSZ_512KB		(0x0 << PXERBCR_EXPROMSZ_OFFS)
+#define PXERBCR_EXPROMSZ_1024KB		(0x1 << PXERBCR_EXPROMSZ_OFFS)
+#define PXERBCR_EXPROMSZ_2048KB		(0x3 << PXERBCR_EXPROMSZ_OFFS)
+#define PXERBCR_EXPROMSZ_4096KB		(0x7 << PXERBCR_EXPROMSZ_OFFS)
+
+/************************************************/
+/* PCI Express Address Window Control Registers */
+/************************************************/
+#define PEX_WIN0_3_CTRL_REG(pexIf, winNum) \
+			    (MV_PEX_IF_REGS_BASE(pexIf) + 0x1820 + (winNum) * 0x10)
+#define PEX_WIN0_3_BASE_REG(pexIf, winNum) \
+			    (MV_PEX_IF_REGS_BASE(pexIf) + 0x1824 + (winNum) * 0x10)
+#define PEX_WIN0_3_REMAP_REG(pexIf, winNum) \
+			     (MV_PEX_IF_REGS_BASE(pexIf) + 0x182C + (winNum) * 0x10)
+#define PEX_WIN4_5_CTRL_REG(pexIf, winNum) \
+			    (MV_PEX_IF_REGS_BASE(pexIf) + 0x1860 + (winNum - 4) * 0x20)
+#define PEX_WIN4_5_BASE_REG(pexIf, winNum) \
+			    (MV_PEX_IF_REGS_BASE(pexIf) + 0x1864 + (winNum - 4) * 0x20)
+#define PEX_WIN4_5_REMAP_REG(pexIf, winNum) \
+			     (MV_PEX_IF_REGS_BASE(pexIf) + 0x186C + (winNum - 4) * 0x20)
+#define PEX_WIN4_5_REMAP_HIGH_REG(pexIf, winNum) \
+			      (MV_PEX_IF_REGS_BASE(pexIf) + 0x1870 + (winNum - 4) * 0x20)
+
+#define PEX_WIN_DEFAULT_CTRL_REG(pexIf)		(MV_PEX_IF_REGS_BASE(pexIf) + 0x18B0)
+#define PEX_WIN_EXP_ROM_CTRL_REG(pexIf)		(MV_PEX_IF_REGS_BASE(pexIf) + 0x18C0)
+#define PEX_WIN_EXP_ROM_REMAP_REG(pexIf)	(MV_PEX_IF_REGS_BASE(pexIf) + 0x18C4)
+
+/* PCI Express Window Control Register */
+/* PEX_WIN_CTRL_REG (PXWCR) */
+
+#define	PXWCR_WIN_EN				BIT0	/* Window Enable. */
+
+#define	PXWCR_WIN_BAR_MAP_OFFS			1	/* Mapping to BAR. */
+#define	PXWCR_WIN_BAR_MAP_MASK			BIT1
+#define	PXWCR_WIN_BAR_MAP_BAR1			(0 << PXWCR_WIN_BAR_MAP_OFFS)
+#define	PXWCR_WIN_BAR_MAP_BAR2			(1 << PXWCR_WIN_BAR_MAP_OFFS)
+
+#define	PXWCR_TARGET_OFFS			4	/*Unit ID */
+#define	PXWCR_TARGET_MASK			(0xf << PXWCR_TARGET_OFFS)
+
+#define	PXWCR_ATTRIB_OFFS			8	/* target attributes */
+#define	PXWCR_ATTRIB_MASK			(0xff << PXWCR_ATTRIB_OFFS)
+
+#define	PXWCR_SIZE_OFFS				16	/* size */
+#define	PXWCR_SIZE_MASK				(0xffff << PXWCR_SIZE_OFFS)
+#define	PXWCR_SIZE_ALIGNMENT			0x10000
+
+/* PCI Express Window Base Register */
+/* PEX_WIN_BASE_REG (PXWBR) */
+
+#define PXWBR_BASE_OFFS				16	/* address[31:16] */
+#define PXWBR_BASE_MASK				(0xffff << PXWBR_BASE_OFFS)
+#define PXWBR_BASE_ALIGNMENT			0x10000
+
+/* PCI Express Window Remap Register */
+/* PEX_WIN_REMAP_REG (PXWRR) */
+
+#define PXWRR_REMAP_EN				BIT0
+#define PXWRR_REMAP_OFFS			16
+#define PXWRR_REMAP_MASK			(0xffff << PXWRR_REMAP_OFFS)
+#define PXWRR_REMAP_ALIGNMENT			0x10000
+
+/* PCI Express Window Remap (High) Register */
+/* PEX_WIN_REMAP_HIGH_REG (PXWRHR) */
+
+#define PXWRHR_REMAP_HIGH_OFFS			0
+#define PXWRHR_REMAP_HIGH_MASK			(0xffffffff << PXWRHR_REMAP_HIGH_OFFS)
+
+/* PCI Express Default Window Control Register */
+/* PEX_WIN_DEFAULT_CTRL_REG (PXWDCR) */
+
+#define	PXWDCR_TARGET_OFFS			4	/*Unit ID */
+#define	PXWDCR_TARGET_MASK			(0xf << PXWDCR_TARGET_OFFS)
+#define	PXWDCR_ATTRIB_OFFS			8	/* target attributes */
+#define	PXWDCR_ATTRIB_MASK			(0xff << PXWDCR_ATTRIB_OFFS)
+
+/* PCI Express Expansion ROM Window Control Register */
+/* PEX_WIN_EXP_ROM_CTRL_REG (PXWERCR) */
+
+#define	PXWERCR_TARGET_OFFS			4	/*Unit ID */
+#define	PXWERCR_TARGET_MASK			(0xf << PXWERCR_TARGET_OFFS)
+#define	PXWERCR_ATTRIB_OFFS			8	/* target attributes */
+#define	PXWERCR_ATTRIB_MASK			(0xff << PXWERCR_ATTRIB_OFFS)
+
+/* PCI Express Expansion ROM Window Remap Register */
+/* PEX_WIN_EXP_ROM_REMAP_REG (PXWERRR) */
+
+#define PXWERRR_REMAP_EN			BIT0
+#define PXWERRR_REMAP_OFFS			16
+#define PXWERRR_REMAP_MASK			(0xffff << PXWERRR_REMAP_OFFS)
+#define PXWERRR_REMAP_ALIGNMENT			0x10000
+
+/* PEX_MEMORY_BAR_BASE_ADDR(barNum) (PXMBBA) */
+/* PCI Express BAR0 Internal Register */
+/* PEX BAR0_INTER_REG (PXBIR) */
+
+#define PXBIR_IOSPACE			BIT0	/* Memory Space Indicator */
+
+#define PXBIR_TYPE_OFFS			1	/* BAR Type/Init Val. */
+#define PXBIR_TYPE_MASK			(0x3 << PXBIR_TYPE_OFFS)
+#define PXBIR_TYPE_32BIT_ADDR		(0x0 << PXBIR_TYPE_OFFS)
+#define PXBIR_TYPE_64BIT_ADDR		(0x2 << PXBIR_TYPE_OFFS)
+
+#define PXBIR_PREFETCH_EN		BIT3	/* Prefetch Enable */
+
+#define PXBIR_BASE_OFFS		20	/* Base address. Address bits [31:20] */
+#define PXBIR_BASE_MASK		(0xfff << PXBIR_BASE_OFFS)
+#define PXBIR_BASE_ALIGNMET	(1 << PXBIR_BASE_OFFS)
+
+/* PCI Express BAR0 Internal (High) Register */
+/* PEX BAR0_INTER_REG_HIGH (PXBIRH) */
+
+#define PXBIRH_BASE_OFFS			0	/* Base address. Bits [63:32] */
+#define PXBIRH_BASE_MASK			(0xffffffff << PBBHR_BASE_OFFS)
+
+#define PEX_BAR_DEFAULT_ATTRIB		0xc	/* Memory - Prefetch - 64 bit address */
+#define PEX_BAR0_DEFAULT_ATTRIB	    	PEX_BAR_DEFAULT_ATTRIB
+#define PEX_BAR1_DEFAULT_ATTRIB		PEX_BAR_DEFAULT_ATTRIB
+#define PEX_BAR2_DEFAULT_ATTRIB		PEX_BAR_DEFAULT_ATTRIB
+
+/* PCI Express BAR1 Register */
+/* PCI Express BAR2 Register */
+/* PEX BAR1_REG (PXBR) */
+/* PEX BAR2_REG (PXBR) */
+
+#define PXBR_IOSPACE			BIT0	/* Memory Space Indicator */
+
+#define PXBR_TYPE_OFFS			1	/* BAR Type/Init Val. */
+#define PXBR_TYPE_MASK			(0x3 << PXBR_TYPE_OFFS)
+#define PXBR_TYPE_32BIT_ADDR		(0x0 << PXBR_TYPE_OFFS)
+#define PXBR_TYPE_64BIT_ADDR		(0x2 << PXBR_TYPE_OFFS)
+
+#define PXBR_PREFETCH_EN		BIT3	/* Prefetch Enable */
+
+#define PXBR_BASE_OFFS		16	/* Base address. Address bits [31:16] */
+#define PXBR_BASE_MASK		(0xffff << PXBR_BASE_OFFS)
+#define PXBR_BASE_ALIGNMET	(1 << PXBR_BASE_OFFS)
+
+/* PCI Express BAR1 (High) Register */
+/* PCI Express BAR2 (High) Register */
+/* PEX BAR1_REG_HIGH (PXBRH) */
+/* PEX BAR2_REG_HIGH (PXBRH) */
+
+#define PXBRH_BASE_OFFS			0	/* Base address. Address bits [63:32] */
+#define PXBRH_BASE_MASK			(0xffffffff << PXBRH_BASE_OFFS)
+
+/* PCI Express Expansion ROM BAR Register */
+/* PEX_EXPANSION_ROM_BASE_ADDR_REG (PXERBAR) */
+
+#define PXERBAR_EXPROMEN		BIT0	/* Expansion ROM Enable */
+
+#define PXERBAR_BASE_512K_OFFS		19	/* Expansion ROM Base Address */
+#define PXERBAR_BASE_512K_MASK		(0x1fff << PXERBAR_BASE_512K_OFFS)
+
+#define PXERBAR_BASE_1MB_OFFS		20	/* Expansion ROM Base Address */
+#define PXERBAR_BASE_1MB_MASK		(0xfff << PXERBAR_BASE_1MB_OFFS)
+
+#define PXERBAR_BASE_2MB_OFFS		21	/* Expansion ROM Base Address */
+#define PXERBAR_BASE_2MB_MASK		(0x7ff << PXERBAR_BASE_2MB_OFFS)
+
+#define PXERBAR_BASE_4MB_OFFS		22	/* Expansion ROM Base Address */
+#define PXERBAR_BASE_4MB_MASK		(0x3ff << PXERBAR_BASE_4MB_OFFS)
+
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+#endif				/* #ifndef __INCPEXREGSH */
diff --git a/arch/arm/plat-feroceon/mv_hal/pex/mvSysPex.h b/arch/arm/plat-feroceon/mv_hal/pex/mvSysPex.h
new file mode 100755
index 0000000..7245044
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pex/mvSysPex.h
@@ -0,0 +1,94 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSysPexH
+#define __INCmvSysPexH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+* mvSysPexCpuIfEnable -
+*
+* DESCRIPTION:
+*	Enable PCI-E in CPU subsystem.
+*
+* INPUT:
+*       pexIf - The PCI-E Interface number to enable.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvSysPexCpuIfEnable(MV_U32 pexIf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/pex/mvVrtBrgPex.c b/arch/arm/plat-feroceon/mv_hal/pex/mvVrtBrgPex.c
new file mode 100755
index 0000000..08b8eaf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pex/mvVrtBrgPex.c
@@ -0,0 +1,267 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvPex.h"
+
+/* #define MV_DEBUG */
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+/* locals */
+typedef struct {
+	MV_U32 data;
+	MV_U32 mask;
+} PEX_HEADER_DATA;
+
+/* local function forwad decleration */
+MV_U32 mvPexHwConfigRead(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff);
+MV_STATUS mvPexHwConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff, MV_U32 data);
+void resetPexConfig(MV_U32 pexIf, MV_U32 bus, MV_U32 dev);
+
+PEX_HEADER_DATA configHdr[16] = {
+	{0x888811ab, 0x00000000},	/*[device ID, vendor ID] */
+	{0x00100007, 0x0000ffff},	/*[status register, command register] */
+	{0x0604000e, 0x00000000},	/*[programming interface, sub class code, class code, revision ID] */
+	{0x00010008, 0x00000000},	/*[BIST, header type, latency time, cache line] */
+	{0x00000000, 0x00000000},	/*[base address 0] */
+	{0x00000000, 0x00000000},	/*[base address 1] */
+	{0x00000000, 0x00ffffff},	/*[secondary latency timersubordinate bus number,
+					   secondary bus number, primary bus number] */
+	{0x0000f101, 0x00000000},	/*[secondary status ,IO limit, IO base] */
+	{0x9ff0a000, 0x00000000},	/*[memory limit, memory base] */
+	{0x0001fff1, 0x00000000},	/*[prefetch memory limit, prefetch memory base] */
+	{0xffffffff, 0x00000000},	/*[prefetch memory base upper] */
+	{0x00000000, 0x00000000},	/*[prefetch memory limit upper] */
+	{0xeffff000, 0x00000000},	/*[IO limit upper 16 bits, IO base upper 16 bits] */
+	{0x00000000, 0x00000000},	/*[reserved, capability pointer] */
+	{0x00000000, 0x00000000},	/*[expansion ROM base address] */
+	{0x00000000, 0x000000FF},	/*[bridge control, interrupt pin, interrupt line] */
+};
+
+#define HEADER_WRITE(data, offset) configHdr[offset/4].data = \
+					((configHdr[offset/4].data & ~configHdr[offset/4].mask) | \
+					(data & configHdr[offset/4].mask))
+#define HEADER_READ(offset) configHdr[offset/4].data
+
+/*******************************************************************************
+* mvVrtBrgPexInit - Initialize PEX interfaces
+*
+* Description:
+*		This function is responsible of intialization of the Pex Interface , It
+*		configure the Pex Bars and Windows in the following manner:
+*
+* Assumptions :
+*		Bar0 is always internal registers bar
+*		Bar1 is always the DRAM bar
+*		Bar2 is always the Device bar
+*
+*		1) Sets the Internal registers bar base by obtaining the base from
+*		   the CPU Interface
+*		2) Sets the DRAM bar base and size by getting the base and size from
+*		   the CPU Interface when the size is the sum of all enabled DRAM
+*		   chip selects and the base is the base of CS0 .
+*		3) Sets the Device bar base and size by getting these values from the
+*		   CPU Interface when the base is the base of the lowest base of the
+*		   Device chip selects, and the
+*
+* INPUT:
+*	pexIf	- PEX interface number.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM
+*
+*******************************************************************************/
+MV_STATUS mvPexVrtBrgInit(MV_U32 pexIf)
+{
+	/* reset PEX tree to recover previous U-boot/Boot configurations */
+	MV_U32 localBus = mvPexLocalBusNumGet(pexIf);
+
+	resetPexConfig(pexIf, localBus, 1);
+	return MV_OK;
+}
+
+MV_U32 mvPexVrtBrgConfigRead(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff)
+{
+
+	MV_U32 localBus = mvPexLocalBusNumGet(pexIf);
+	MV_U32 localDev = mvPexLocalDevNumGet(pexIf);
+	MV_U32 val;
+	if (bus == localBus) {
+		if (dev > 1) {
+			/* on the local device allow only device #0 & #1 */
+			return 0xffffffff;
+		} else if (dev == localDev) {
+			/* read the memory controller registers */
+			return mvPexHwConfigRead(pexIf, bus, dev, func, regOff);
+		} else {
+			/* access the virtual brg header */
+			return HEADER_READ(regOff);
+		}
+	} else if (bus == (localBus + 1)) {
+		/* access the device behind the virtual bridge */
+		if ((dev == localDev) || (dev > 1)) {
+			return 0xffffffff;
+		} else {
+			/* access the device behind the virtual bridge, in this case
+			 *  change the bus number to the local bus number in order to
+			 *  generate type 0 config cycle
+			 */
+			mvPexLocalBusNumSet(pexIf, bus);
+			mvPexLocalDevNumSet(pexIf, 1);
+			val = mvPexHwConfigRead(pexIf, bus, 0, func, regOff);
+			mvPexLocalBusNumSet(pexIf, localBus);
+			mvPexLocalDevNumSet(pexIf, localDev);
+			return val;
+		}
+	}
+	/* for all other devices use the HW function to get the
+	 *  requested registers
+	 */
+	mvPexLocalDevNumSet(pexIf, 1);
+	val = mvPexHwConfigRead(pexIf, bus, dev, func, regOff);
+	mvPexLocalDevNumSet(pexIf, localDev);
+	return val;
+}
+
+MV_STATUS mvPexVrtBrgConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff, MV_U32 data)
+{
+	MV_U32 localBus = mvPexLocalBusNumGet(pexIf);
+	MV_U32 localDev = mvPexLocalDevNumGet(pexIf);
+	MV_STATUS status;
+
+	if (bus == localBus) {
+		if (dev > 1) {
+			/* on the local device allow only device #0 & #1 */
+			return MV_ERROR;
+		} else if (dev == localDev) {
+			/* read the memory controller registers */
+			return mvPexHwConfigWrite(pexIf, bus, dev, func, regOff, data);
+		} else {
+			/* access the virtual brg header */
+			HEADER_WRITE(data, regOff);
+			return MV_OK;
+		}
+	} else if (bus == (localBus + 1)) {
+		/* access the device behind the virtual bridge */
+		if ((dev == localDev) || (dev > 1)) {
+			return MV_ERROR;
+		} else {
+			/* access the device behind the virtual bridge, in this case
+			 *  change the bus number to the local bus number in order to
+			 *  generate type 0 config cycle
+			 */
+			/* return mvPexHwConfigWrite (pexIf, localBus, dev, func, regOff, data); */
+			mvPexLocalBusNumSet(pexIf, bus);
+			mvPexLocalDevNumSet(pexIf, 1);
+			status = mvPexHwConfigWrite(pexIf, bus, 0, func, regOff, data);
+			mvPexLocalBusNumSet(pexIf, localBus);
+			mvPexLocalDevNumSet(pexIf, localDev);
+			return status;
+
+		}
+	}
+	/* for all other devices use the HW function to get the
+	 *  requested registers
+	 */
+	mvPexLocalDevNumSet(pexIf, 1);
+	status = mvPexHwConfigWrite(pexIf, bus, dev, func, regOff, data);
+	mvPexLocalDevNumSet(pexIf, localDev);
+	return status;
+}
+
+void resetPexConfig(MV_U32 pexIf, MV_U32 bus, MV_U32 dev)
+{
+	MV_U32 tData;
+	MV_U32 i;
+
+	/* restore the PEX configuration to initialization state */
+	/* in case PEX P2P call recursive and reset config */
+	tData = mvPexHwConfigRead(pexIf, bus, dev, 0x0, 0x0);
+	if (tData != 0xffffffff) {
+		/* agent had been found - check whether P2P */
+		tData = mvPexHwConfigRead(pexIf, bus, dev, 0x0, 0x8);
+		if ((tData & 0xffff0000) == 0x06040000) {	/* P2P */
+			/* get the sec bus and the subordinate */
+			MV_U32 secBus;
+			tData = mvPexHwConfigRead(pexIf, bus, dev, 0x0, 0x18);
+			secBus = ((tData >> 8) & 0xff);
+
+			/* now scan on sec bus */
+			for (i = 0; i < 0xff; i++)
+				resetPexConfig(pexIf, secBus, i);
+
+			/* now reset this device */
+			DB(mvOsPrintf("Reset bus %d dev %d\n", bus, dev));
+			mvPexHwConfigWrite(pexIf, bus, dev, 0x0, 0x18, 0x0);
+			DB(mvOsPrintf("Reset bus %d dev %d\n", bus, dev));
+		}
+	}
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/pex/mvVrtBrgPex.h b/arch/arm/plat-feroceon/mv_hal/pex/mvVrtBrgPex.h
new file mode 100755
index 0000000..6969db4
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pex/mvVrtBrgPex.h
@@ -0,0 +1,86 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+	*	Redistributions of source code must retain the above copyright notice,
+		this list of conditions and the following disclaimer.
+
+	*	Redistributions in binary form must reproduce the above copyright
+		notice, this list of conditions and the following disclaimer in the
+		documentation and/or other materials provided with the distribution.
+
+	*	Neither the name of Marvell nor the names of its contributors may be
+		used to endorse or promote products derived from this software without
+		specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCVRTBRGPEXH
+#define __INCVRTBRGPEXH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	/* Global Functions prototypes */
+	/* mvPexInit - Initialize PEX interfaces */
+	MV_STATUS mvPexVrtBrgInit(MV_U32 pexIf);
+
+	/* mvPexConfigRead - Read from configuration space */
+	MV_U32 mvPexVrtBrgConfigRead(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff);
+
+	/* mvPexConfigWrite - Write to configuration space */
+	MV_STATUS mvPexVrtBrgConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev,
+					 MV_U32 func, MV_U32 regOff, MV_U32 data);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* #ifndef __INCPEXH */
diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuDefines.h b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuDefines.h
new file mode 100755
index 0000000..9620b1d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuDefines.h
@@ -0,0 +1,409 @@
+/*******************************************************************************

+Copyright (C) Marvell International Ltd. and its affiliates

+

+This software file (the "File") is owned and distributed by Marvell

+International Ltd. and/or its affiliates ("Marvell") under the following

+alternative licensing terms.  Once you have made an election to distribute the

+File under one of the following license alternatives, please (i) delete this

+introductory statement regarding license alternatives, (ii) delete the two

+license alternatives that you have not elected to use and (iii) preserve the

+Marvell copyright notice above.

+

+********************************************************************************

+Marvell Commercial License Option

+

+If you received this File from Marvell and you have entered into a commercial

+license agreement (a "Commercial License") with Marvell, the File is licensed

+to you under the terms of the applicable Commercial License.

+

+********************************************************************************

+Marvell GPL License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or

+modify this File in accordance with the terms and conditions of the General

+Public License Version 2, June 1991 (the "GPL License"), a copy of which is

+available along with the File in the license.txt file or by writing to the Free

+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or

+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY

+DISCLAIMED.  The GPL License provides additional details about this warranty

+disclaimer.

+********************************************************************************

+Marvell BSD License Option

+

+If you received this File from Marvell, you may opt to use, redistribute and/or

+modify this File under the following licensing terms.

+Redistribution and use in source and binary forms, with or without modification,

+are permitted provided that the following conditions are met:

+

+    *   Redistributions of source code must retain the above copyright notice,

+	    this list of conditions and the following disclaimer.

+

+    *   Redistributions in binary form must reproduce the above copyright

+        notice, this list of conditions and the following disclaimer in the

+        documentation and/or other materials provided with the distribution.

+

+    *   Neither the name of Marvell nor the names of its contributors may be

+        used to endorse or promote products derived from this software without

+        specific prior written permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+*******************************************************************************/

+

+#ifndef _ONU_GPON_DEFINES_H

+#define _ONU_GPON_DEFINES_H

+

+/* Include Files

+------------------------------------------------------------------------------*/

+

+/* Definitions

+------------------------------------------------------------------------------*/

+

+#ifdef CONFIG_PON_Z1

+#define PON_Z1

+#endif /* CONFIG_PON_Z1 */

+

+#ifdef CONFIG_PON_Z2

+#define PON_Z2

+#endif /* CONFIG_PON_Z2 */

+

+#ifdef CONFIG_PON_FPGA

+#define PON_FPGA

+#endif /* CONFIG_PON_FPGA */

+

+#define ONU_GPON_MAX_NUM_OF_T_CONTS (CONFIG_MV_PON_TCONTS)

+#define EPON_MAX_MAC_NUM (CONFIG_MV_EPON_LLID) 

+#if defined(ONU_GPON_MAX_NUM_OF_T_CONTS) && (ONU_GPON_MAX_NUM_OF_T_CONTS < EPON_MAX_MAC_NUM)

+#error ERROR: Invalid Init Params - #num of T-Conts < #num of LLID

+#endif

+

+#ifdef CONFIG_MV_GPON

+

+#ifdef CONFIG_MV_GPON_STATIC_GEM_PORT

+#define MV_GPON_STATIC_GEM_PORT

+#endif /* CONFIG_MV_GPON_STATIC_GEM_PORT */

+

+#ifdef CONFIG_MV_GPON_DEBUG_PRINT

+#define MV_GPON_DEBUG_PRINT

+#endif /* CONFIG_MV_GPON_DEBUG_PRINT */

+

+#ifdef CONFIG_MV_GPON_PERFORMANCE_CHECK

+#define MV_GPON_PERFORMANCE_CHECK

+#endif /* CONFIG_MV_GPON_PERFORMANCE_CHECK */

+

+#ifdef CONFIG_MV_GPON_HW_INTERRUPT

+#define MV_GPON_HW_INTERRUPT

+#endif /* CONFIG_MV_GPON_HW_INTERRUPT */

+

+#endif /* CONFIG_MV_GPON */

+

+#ifdef CONFIG_MV_EPON

+

+#ifdef CONFIG_MV_EPON_HW_INTERRUPT

+#define MV_EPON_HW_INTERRUPT

+#endif /* CONFIG_MV_EPON_HW_INTERRUPT */

+

+#define ONU_EPON_DBA_LOW_RATE_VALUE       (CONFIG_MV_EPON_DBA_LOW_RATE_VALUE)

+#define ONU_EPON_DBA_LOW_RATE_THRESHOLD   (CONFIG_MV_EPON_DBA_LOW_RATE_THRESHOLD)

+#define ONU_EPON_DBA_LOW_RATE_CONST_VALUE (CONFIG_MV_EPON_DBA_LOW_RATE_CONST_VALUE)

+#define ONU_EPON_DBA_HIGH_RATE_THRESHOLD  (CONFIG_MV_EPON_DBA_HIGH_RATE_THRESHOLD)

+#define ONU_EPON_DBA_HIGH_RATE_VALUE      (CONFIG_MV_EPON_DBA_HIGH_RATE_VALUE)

+

+#endif /* CONFIG_MV_EPON */

+

+

+/* GEM MAC Ports */

+#define GPON_ONU_MAC_OPEN_DS_BROADCAST_PORT	(1000)

+#define GPON_ONU_MAC_SYNC_DS_BROADCAST_PORT	(500)

+#define GPON_US_622_PLOU_TOTAL_BYTES_SIZE	(64/8)

+#define	GPON_US_1244_PLOU_TOTAL_BYTES_SIZE	(96/8)

+#define GPON_ONU_MAX_GEM_PORTS			(4096)

+

+/* gpon definitions */

+#define ONU_GPON_NUM_OF_EVENTS			(64)

+#define ONU_GPON_NUM_OF_STATES			(8)

+#define ONU_GPON_NUM_OF_ALARMS			(14)

+

+#define ONU_GPON_UNDEFINED_ONU_ID		(0xFF)	 

+#define ONU_GPON_BROADCAST_ONU_ID		(0xFF)

+

+#define ONU_GPON_DS_DEF_RATE			(2488)     /* M Bit per sec */

+

+/* BER definitions */

+#define ONU_GPON_DEF_INTERNAL_BER_INTERVAL	(10)	/* 10 seconds */

+#define ONU_GPON_MAX_INTERNAL_BER_INTERVAL	(10)	/* 10 seconds */

+#define ONU_GPON_BER_DEF_COEFF_NUMERATOR	(1)

+#define ONU_GPON_BER_DEF_COEFF_DENOMINATOR	(10)

+#define ONU_GPON_DEF_SF_THRESHOLD		(5)

+#define ONU_GPON_DEF_SD_THRESHOLD		(9)

+#define ONU_GPON_MAX_SF_THRESHOLD		(9)

+#define ONU_GPON_MIN_SF_THRESHOLD		(4)

+#define ONU_GPON_MAX_SD_THRESHOLD		(8)

+#define ONU_GPON_MIN_SD_THRESHOLD		(3)

+#define ONU_GPON_DEF_REI_SEQ_NUM		(0)

+

+/* overhead message status options */

+#define ONU_GPON_OVER_MSG_STATUS_XX		(0xC0)

+#define ONU_GPON_OVER_MSG_STATUS_E		(0x20)

+#define ONU_GPON_OVER_MSG_STATUS_M		(0x10)

+#define ONU_GPON_OVER_MSG_STATUS_SS		(0x0C)

+#define ONU_GPON_OVER_MSG_STATUS_PP		(0x03)

+

+/* Dying Gasp definitions */

+#define ONU_GPON_DG_DEF_DEBUG_THRESH		(16000000)

+#define ONU_GPON_DG_DEF_NORMAL_THRESH		(1600)

+#define ONU_GPON_DG_DEF_PIN_NUMBER		(1)

+#define ONU_GPON_DG_DEF_STATUS			(0)

+#define ONU_GPON_DG_ACTIVE_HIGH			(1)

+#define ONU_GPON_DG_ACTIVE_LOW			(3)

+ 

+/* port definitions */

+#define ONU_GPON_PORT_ID_SHIFT			(4)

+

+/* States */

+/* ====== */

+#define ONU_GPON_01_INIT			(0x01)

+#define ONU_GPON_02_STANDBY			(0x02)

+#define ONU_GPON_03_SERIAL_NUM			(0x03)

+#define ONU_GPON_04_RANGING			(0x04)

+#define ONU_GPON_05_OPERATION			(0x05)

+#define ONU_GPON_06_POPUP			(0x06)

+#define ONU_GPON_07_EMERGANCY_STOP		(0x07)

+

+/* Messages */

+/* ======== */

+

+/* Downstream */

+#define ONU_GPON_DS_MSG_OVERHEAD		(0x01)

+#define ONU_GPON_DS_MSG_SN_MASK			(0x02)

+#define ONU_GPON_DS_MSG_ASSIGN_ONU_ID		(0x03)

+#define ONU_GPON_DS_MSG_RANGING_TIME		(0x04)

+#define ONU_GPON_DS_MSG_DACT_ONU_ID		(0x05)

+#define ONU_GPON_DS_MSG_DIS_SN			(0x06)

+#define ONU_GPON_DS_MSG_CONFIG_VP_VC		(0x07)

+#define ONU_GPON_DS_MSG_ENCRYPT_VPI_PORT_ID	(0x08)

+#define ONU_GPON_DS_MSG_REQ_PASSWORD		(0x09)

+#define ONU_GPON_DS_MSG_ASSIGN_ALLOC_ID		(0x0A)

+#define ONU_GPON_DS_MSG_NO_MESSAGE		(0x0B)

+#define ONU_GPON_DS_MSG_POPUP			(0x0C)

+#define ONU_GPON_DS_MSG_REQ_KEY			(0x0D)

+#define ONU_GPON_DS_MSG_CONFIG_PORT_ID		(0x0E)

+#define ONU_GPON_DS_MSG_PHYSICAL_EQUIP_ERR	(0x0F)

+#define ONU_GPON_DS_MSG_CHANGE_POWER_LEVEL	(0x10)

+#define ONU_GPON_DS_MSG_PST			(0x11)

+#define ONU_GPON_DS_MSG_BER_INTERVAL		(0x12)

+#define ONU_GPON_DS_MSG_KEY_SWITCH_TIME		(0x13)

+#define ONU_GPON_DS_MSG_EXT_BURST_LEN		(0x14)

+#define ONU_GPON_DS_MSG_LAST			(0x14)

+

+/* Upstream */

+#define ONU_GPON_US_MSG_SN_ONU                 (0x01)

+#define ONU_GPON_US_MSG_PASSWORD               (0x02)

+#define ONU_GPON_US_MSG_DYING_GASP             (0x03)

+#define ONU_GPON_US_MSG_NO_MESSAGE             (0x04)

+#define ONU_GPON_US_MSG_ENCRYPT_KEY            (0x05)

+#define ONU_GPON_US_MSG_PHYSICAL_EQUIP_ERR     (0x06)

+#define ONU_GPON_US_MSG_PST                    (0x07)

+#define ONU_GPON_US_MSG_REI                    (0x08)

+#define ONU_GPON_US_MSG_ACK                    (0x09)

+#define ONU_GPON_US_MSG_LAST                   (0x09)

+

+/* Alarms */

+/* ====== */

+#define ONU_GPON_EVENT_ALARM_LOS		(0x0)

+#define ONU_GPON_EVENT_ALARM_LOF		(0x1)

+#define ONU_GPON_EVENT_ALARM_LCD		(0x2)

+#define ONU_GPON_EVENT_ALARM_LCDG		(0x3)

+#define ONU_GPON_EVENT_ALARM_TF			(0x4)

+#define ONU_GPON_EVENT_ALARM_SUF		(0x5)

+#define ONU_GPON_EVENT_ALARM_MEM		(0x6)

+#define ONU_GPON_EVENT_ALARM_DACT		(0x7)

+#define ONU_GPON_EVENT_ALARM_DIS		(0x8)

+#define ONU_GPON_EVENT_ALARM_MIS		(0x9)

+#define ONU_GPON_EVENT_ALARM_PEE		(0xA)

+#define ONU_GPON_EVENT_ALARM_RDI		(0xB)

+

+/* Generate alarm */

+#define ONU_GPON_ALARM_GEN_BASE			(0x20)

+

+/* Cancel alarm */

+#define ONU_GPON_ALARM_CAN_BASE			(0x30)

+

+/* Events */

+/* ====== */

+

+/* Messages */

+#define ONU_GPON_EVENT_MSG_OVERHEAD		(ONU_GPON_DS_MSG_OVERHEAD)

+#define ONU_GPON_EVENT_MSG_SN_MASK		(ONU_GPON_DS_MSG_SN_MASK)

+#define ONU_GPON_EVENT_MSG_ASSIGN_ONU_ID	(ONU_GPON_DS_MSG_ASSIGN_ONU_ID)

+#define ONU_GPON_EVENT_MSG_RANGING_TIME		(ONU_GPON_DS_MSG_RANGING_TIME)

+#define ONU_GPON_EVENT_MSG_DACT_ONU_ID		(ONU_GPON_DS_MSG_DACT_ONU_ID)

+#define ONU_GPON_EVENT_MSG_DIS_SN		(ONU_GPON_DS_MSG_DIS_SN)

+#define ONU_GPON_EVENT_MSG_CONFIG_VP_VC		(ONU_GPON_DS_MSG_CONFIG_VP_VC)

+#define ONU_GPON_EVENT_MSG_ENCRYPT_VPI_PORT_ID	(ONU_GPON_DS_MSG_ENCRYPT_VPI_PORT_ID)

+#define ONU_GPON_EVENT_MSG_REQ_PASSWORD		(ONU_GPON_DS_MSG_REQ_PASSWORD)

+#define ONU_GPON_EVENT_MSG_ASSIGN_ALLOC_ID	(ONU_GPON_DS_MSG_ASSIGN_ALLOC_ID)

+#define ONU_GPON_EVENT_MSG_NO_MESSAGE		(ONU_GPON_DS_MSG_NO_MESSAGE)

+#define ONU_GPON_EVENT_MSG_POPUP		(ONU_GPON_DS_MSG_POPUP)

+#define ONU_GPON_EVENT_MSG_REQ_KEY		(ONU_GPON_DS_MSG_REQ_KEY)

+#define ONU_GPON_EVENT_MSG_CONFIG_PORT_ID	(ONU_GPON_DS_MSG_CONFIG_PORT_ID)

+#define ONU_GPON_EVENT_MSG_PHYSICAL_EQUIP_ERR	(ONU_GPON_DS_MSG_PHYSICAL_EQUIP_ERR)

+#define ONU_GPON_EVENT_MSG_CHANGE_POWER_LEVEL	(ONU_GPON_DS_MSG_CHANGE_POWER_LEVEL)

+#define ONU_GPON_EVENT_MSG_PST			(ONU_GPON_DS_MSG_PST)

+#define ONU_GPON_EVENT_MSG_BER_INTERVAL		(ONU_GPON_DS_MSG_BER_INTERVAL)

+#define ONU_GPON_EVENT_MSG_KEY_SWITCH_TIME	(ONU_GPON_DS_MSG_KEY_SWITCH_TIME)

+#define ONU_GPON_EVENT_MSG_EXT_BURST_LEN	(ONU_GPON_DS_MSG_EXT_BURST_LEN)

+

+/* Alarms */

+#define ONU_GPON_EVENT_ALM_GEN_BASE		(ONU_GPON_ALARM_GEN_BASE)

+#define ONU_GPON_EVENT_ALM_GEN_LOS		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_LOS )

+#define ONU_GPON_EVENT_ALM_GEN_LOF		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_LOF )

+#define ONU_GPON_EVENT_ALM_GEN_LCDA		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_LCDA)

+#define ONU_GPON_EVENT_ALM_GEN_LCDG		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_LCDG)

+#define ONU_GPON_EVENT_ALM_GEN_TF		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_TF  ) 

+#define ONU_GPON_EVENT_ALM_GEN_SUF		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_SUF )

+#define ONU_GPON_EVENT_ALM_GEN_MEM		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_MEM )

+#define ONU_GPON_EVENT_ALM_GEN_DACT		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_DACT)

+#define ONU_GPON_EVENT_ALM_GEN_DIS		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_DIS )

+#define ONU_GPON_EVENT_ALM_GEN_MIS		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_MIS )

+#define ONU_GPON_EVENT_ALM_GEN_PEE		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_PEE )

+#define ONU_GPON_EVENT_ALM_GEN_RDI		(ONU_GPON_ALARM_GEN_BASE + ONU_GPON_EVENT_ALARM_RDI )

+

+#define ONU_GPON_EVENT_ALM_CAN_BASE		(ONU_GPON_ALARM_CAN_BASE) 

+#define ONU_GPON_EVENT_ALM_CAN_LOS		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_LOS )

+#define ONU_GPON_EVENT_ALM_CAN_LOF		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_LOF )

+#define ONU_GPON_EVENT_ALM_CAN_LCDA		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_LCDA)

+#define ONU_GPON_EVENT_ALM_CAN_LCDG		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_LCDG)

+#define ONU_GPON_EVENT_ALM_CAN_TF		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_TF  ) 

+#define ONU_GPON_EVENT_ALM_CAN_SUF		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_SUF )

+#define ONU_GPON_EVENT_ALM_CAN_MEM		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_MEM )

+#define ONU_GPON_EVENT_ALM_CAN_DACT		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_DACT)

+#define ONU_GPON_EVENT_ALM_CAN_DIS		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_DIS )

+#define ONU_GPON_EVENT_ALM_CAN_MIS		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_MIS )

+#define ONU_GPON_EVENT_ALM_CAN_PEE		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_PEE )

+#define ONU_GPON_EVENT_ALM_CAN_RDI		(ONU_GPON_ALARM_CAN_BASE + ONU_GPON_EVENT_ALARM_RDI )

+

+/* Default Serial Number - Before init time */

+#define ONU_GPON_SN_DEF_BYTE_1			(0x01)

+#define ONU_GPON_SN_DEF_BYTE_2			(0x02)

+#define ONU_GPON_SN_DEF_BYTE_3			(0x03)

+#define ONU_GPON_SN_DEF_BYTE_4			(0x04)

+#define ONU_GPON_SN_DEF_BYTE_5			(0x05)

+#define ONU_GPON_SN_DEF_BYTE_6			(0x06)

+#define ONU_GPON_SN_DEF_BYTE_7			(0x07)

+#define ONU_GPON_SN_DEF_BYTE_8			(0x08)

+

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_01		(ONU_GPON_UNDEFINED_ONU_ID) /* should be update after assign onu Id */

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_02		(ONU_GPON_US_MSG_NO_MESSAGE)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_03		(0x01)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_04		(0x02)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_05		(0x03)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_06		(0x04)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_07		(0x05)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_08		(0x06)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_09		(0x07)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_10		(0x08)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_11		(0x09)

+#define ONU_GPON_IDLE_MSG_DEF_BYTE_12		(0x0A)

+

+#define ONU_GPON_SN_MSG_DEF_BYTE_01		(ONU_GPON_UNDEFINED_ONU_ID) /* should be update after assign onu Id */

+#define ONU_GPON_SN_MSG_DEF_BYTE_02		(ONU_GPON_US_MSG_SN_ONU)

+#define ONU_GPON_SN_MSG_DEF_BYTE_03		(ONU_GPON_SN_DEF_BYTE_1)

+#define ONU_GPON_SN_MSG_DEF_BYTE_04		(ONU_GPON_SN_DEF_BYTE_2)

+#define ONU_GPON_SN_MSG_DEF_BYTE_05		(ONU_GPON_SN_DEF_BYTE_3)

+#define ONU_GPON_SN_MSG_DEF_BYTE_06		(ONU_GPON_SN_DEF_BYTE_4)

+#define ONU_GPON_SN_MSG_DEF_BYTE_07		(ONU_GPON_SN_DEF_BYTE_5)

+#define ONU_GPON_SN_MSG_DEF_BYTE_08		(ONU_GPON_SN_DEF_BYTE_6)

+#define ONU_GPON_SN_MSG_DEF_BYTE_09		(ONU_GPON_SN_DEF_BYTE_7)

+#define ONU_GPON_SN_MSG_DEF_BYTE_10		(ONU_GPON_SN_DEF_BYTE_8)

+#define ONU_GPON_SN_MSG_DEF_BYTE_11		(0x00)

+#define ONU_GPON_SN_MSG_DEF_BYTE_12		(0x05)     /* GEM Supported / Medium Power */

+

+#define ONU_GPON_SN_MSK_GEN_ENA			(MV_FALSE)

+#define ONU_GPON_SN_MSK_DEF_MATCH		(MV_TRUE)

+

+#define ONU_GPON_SN_DEFAULT		        {'M','R','V','L','9','9','9','9'}

+#define ONU_GPON_PASSWORD_DEFAULT		{'1','2','3','4','5','6','7','8','9','0'}

+

+#define ONU_DBA_DEF_HIGHEST_QUEUE           (7)

+#define ONU_DBA_MAX_QUEUE                   (8)

+

+

+/* MIB Counters - the follow are element numbers in array

+*******************************************************************************/

+#define ONU_GPON_MIB_PM_GoodOctetsReceived_low           0        // (0x0)  

+#define ONU_GPON_MIB_PM_GoodOctetsReceived_high          1        // (0x4)  

+#define ONU_GPON_MIB_PM_BadOctetsReceived                2        // (0x8)  

+#define ONU_GPON_MIB_PM_MACTransError                    3        // (0xC)  

+#define ONU_GPON_MIB_PM_GoodFramesReceived               4        // (0x10)  

+#define ONU_GPON_MIB_PM_BadFramesReceived                5        // (0x14)  

+#define ONU_GPON_MIB_PM_BroadcastFramesReceived          6        // (0x18)  

+#define ONU_GPON_MIB_PM_MulticastFramesReceived          7        // (0x1C)  

+#define ONU_GPON_MIB_PM_Frames64Octets                   8        // (0x20)  

+#define ONU_GPON_MIB_PM_Frames65to127Octets              9        // (0x24)  

+#define ONU_GPON_MIB_PM_Frames128to255Octets             10       // (0x28)  

+#define ONU_GPON_MIB_PM_Frames256to511Octets             11       // (0x2C)  

+#define ONU_GPON_MIB_PM_Frames512to1023Octets            12       // (0x30)  

+#define ONU_GPON_MIB_PM_Frames1024toMaxOctets            13       // (0x34)  

+#define ONU_GPON_MIB_PM_GoodOctetsSent_low               14       // (0x38)  

+#define ONU_GPON_MIB_PM_GoodOctetsSent_high              15       // (0x3C)  

+#define ONU_GPON_MIB_PM_GoodFramesSent                   16       // (0x40)  

+#define ONU_GPON_MIB_PM_MulticastFramesSent              18       // (0x48)  

+#define ONU_GPON_MIB_PM_BroadcastFramesSent              19       // (0x4C)  

+

+

+

+/* MIB Counter Control - valid,counterset,gemport

+*******************************************************************************/

+#define MIB_COUNTER_CONTROL_VALID_BIT     (1)

+#define MIB_COUNTER_CONTROL_INVALID_BIT   (0)

+#define MAKE_MIB_COUNTER_CONTROL(v,c,g)   ((((v) & 0x1) << 15) | (((c) & 0x7) << 12) | ((g) &0xFFF))

+

+

+/* Enums

+------------------------------------------------------------------------------*/

+typedef enum

+{

+	ONU_GPON_PREM_TYPE_01        = 0,

+	ONU_GPON_PREM_TYPE_02        = 1,

+	ONU_GPON_PREM_TYPE_03        = 2

+}E_OnuOverheadPreambleType;

+

+typedef enum

+{

+	ONU_GPON_DELM_BYTE_01        = 0,

+	ONU_GPON_DELM_BYTE_02        = 1,

+	ONU_GPON_DELM_BYTE_03        = 2

+}E_OnuOverheadDelimiterByte;

+

+typedef enum

+{

+	ONU_GPON_PREM_TYPE_03_DEF    = 0,

+	ONU_GPON_PREM_TYPE_03_CHNG   = 1

+}E_OnuOverheadExtPreambleType3;

+

+/* Typedefs

+------------------------------------------------------------------------------*/

+

+/* Global variables

+------------------------------------------------------------------------------*/

+

+/* Global functions

+------------------------------------------------------------------------------*/

+

+/* Macros

+------------------------------------------------------------------------------*/

+

+#endif /* _ONU_GPON_DEFINES_H */

diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.c b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.c
new file mode 100755
index 0000000..85741ef
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.c
@@ -0,0 +1,8142 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "mvTypes.h"
+#include "mvOs.h"
+
+#include "mvPonOnuDefines.h"
+#include "mvPonOnuRegs.h"
+#include "mvPonOnuMac.h"
+
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           =========   =========   =========   ===       ==           == */
+/* ==           =========   =========   =========   ====      ==           == */
+/* ==           ==          ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==          ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           =========   =========   ==     ==   ==   ==   ==           == */
+/* ==           =========   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==     ==   ==          ==     ==   ==     == ==           == */
+/* ==           ==     ==   ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define __FILE_DESC__ "mv_hal/pon/mvPonOnuMac.c"
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+MV_U32	       onuGponPortAesStatusImage[GPON_ONU_MAX_GEM_PORTS/32];
+MV_BOOL	       onuGponPortValidStatusImage[GPON_ONU_MAX_GEM_PORTS/32];
+S_MacTxPloamPm mvOnuGponMacPloamCnt;
+S_MacFifoCtrl  fifoCtrl;
+MV_U32         fifoReadIdx  = 0;
+MV_U32         fifoWriteIdx = 0;
+
+MV_32          fifoAuditEnter   = 0;
+MV_32          fifoAuditAction  = 0;
+MV_32          fifoMacMsgSend   = 0;
+MV_32          fifoMacMsgAdd    = 0;
+MV_32          fifoMacMsgFree   = 0;
+MV_32          fifoMacPloamSend = 0;
+MV_32          fifoSupported    = 1;
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+static inline MV_STATUS mvOnuGponMacFifoMsgAlloc(MV_U32 **buffer, MV_U32 *bufferIndex);
+static inline void      mvOnuGponMacFifoMsgSend(MV_U32 bufferIndex);
+static inline MV_STATUS mvOnuGponMacFifoMsgRece(MV_U32 **buffer, MV_U32 *bufferIndex);
+static inline void      mvOnuGponMacFifoMsgFree(MV_U32 bufferIndex);
+static inline int       mvOnuGponMacFifoEmpty(void);
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                           RX Low Level Routines                            */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacVersionGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the asic version
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     asic version
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacVersionGet(MV_U32 *version)
+{
+  MV_STATUS rcode;
+
+  rcode = asicOntGlbRegRead(mvAsicReg_GPON_GEN_MAC_VERSION, version, 0);
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Rx config enable register
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxConfigSet(MV_BOOL enable)
+{
+  MV_STATUS status;
+  MV_U32    enBit;
+
+  enBit = (enable == MV_TRUE) ? 1 : 0;
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_RX_CONFIG_EN, enBit, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxConfigBitOrderSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Rx config bit order register
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxConfigBitOrderSet(MV_U32 value)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_RX_CONFIG_BIT_ORDER, value, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPsaConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Rx PSA config register
+**
+**  PARAMETERS:  MV_U32 syncFsmM1
+**               MV_U32 syncFsmM2
+**               MV_U32 syncFsmM3
+**               MV_U32 fecHyst
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPsaConfigSet(MV_U32 syncFsmM1,
+                                   MV_U32 syncFsmM2,
+                                   MV_U32 syncFsmM3,
+                                   MV_U32 fecHyst)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_RX_PSA_CONFIG_SFM1, syncFsmM1, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PSA_CONFIG_SFM2, syncFsmM2, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PSA_CONFIG_SFM3, syncFsmM3, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PSA_CONFIG_FHM1, fecHyst, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxFecConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Rx FEC config register
+**
+**  PARAMETERS:  MV_BOOL swIndication
+**               MV_BOOL forceSw
+**               MV_BOOL ignoreParity
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxFecConfigSet(MV_BOOL swIndication,
+                                   MV_BOOL forceSw,
+                                   MV_BOOL ignoreParity)
+{
+  MV_STATUS status;
+  MV_U32    swiBit;
+  MV_U32    fswBit;
+  MV_U32    ipaBit;
+
+  swiBit  = (swIndication == MV_TRUE) ? 1 : 0;
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_RX_FEC_CONFIG_SWVAL, swiBit, 0);
+  fswBit  = (forceSw == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_FEC_CONFIG_FSW, fswBit, 0);
+  ipaBit  = (ignoreParity == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_FEC_CONFIG_IGNP, ipaBit, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxFecStatusGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get Rx FEC Ind register
+**
+**  PARAMETERS:  MV_U32 *fecStatus
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxFecStatusGet(MV_U32 *fecStatus)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_FEC_CONFIG_IND, fecStatus, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPloamDataGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx Ploam data
+**
+**  PARAMETERS:  MV_U32 *ploamData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPloamDataGet(MV_U32 *ploamData)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_PLOAMD_DATA_READ, ploamData, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPloamDataUsedGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the Rx ploam fifo size
+**
+**  PARAMETERS:  MV_U32 *ploamFifoSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPloamDataUsedGet(MV_U32 *ploamFifoSize)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_PLOAMD_DATA_USED, ploamFifoSize, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPlenConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Rx Plen config register
+**
+**  PARAMETERS:  MV_BOOL forceNum
+**               MV_BOOL useForce
+**               MV_BOOL ignDiff
+**               MV_BOOL notFix
+**               MV_BOOL ignCrc
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPlenConfigSet(MV_BOOL forceNum,
+                                    MV_BOOL useForce,
+                                    MV_BOOL ignDiff,
+                                    MV_BOOL notFix,
+                                    MV_BOOL ignCrc)
+{
+  MV_STATUS status;
+  MV_U32    fnBit;
+  MV_U32    ufBit;
+  MV_U32    idBit;
+  MV_U32    nfBit;
+  MV_U32    icBit;
+
+  fnBit   = (forceNum == MV_TRUE) ? 1 : 0;
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_RX_PLEND_CONFIG_FN, fnBit, 0);
+  ufBit   = (useForce == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PLEND_CONFIG_UF, ufBit, 0);
+  idBit   = (ignDiff == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PLEND_CONFIG_IGND, idBit, 0);
+  nfBit   = (notFix == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PLEND_CONFIG_DFIX, nfBit, 0);
+  icBit   = (ignCrc == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PLEND_CONFIG_IGNC, icBit, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPlenConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Rx Ploam config register
+**
+**  PARAMETERS:  MV_BOOL ignCrc
+**               MV_BOOL ignBrd
+**               MV_BOOL fwdAll
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPloamConfigSet(MV_BOOL ignCrc,
+                                     MV_BOOL ignBrd,
+                                     MV_BOOL fwdAll)
+{
+  MV_STATUS status;
+  MV_U32    icBit;
+  MV_U32    igBit;
+  MV_U32    faBit;
+
+  icBit   = (ignCrc == MV_TRUE) ? 1 : 0;
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_RX_PLOAMD_CONFIG_IGNC, icBit, 0);
+  igBit   = (ignBrd == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PLOAMD_CONFIG_IGNB, igBit, 0);
+  faBit   = (fwdAll == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_PLOAMD_CONFIG_FALL, faBit, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxBwMapConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Rx BW Map config register
+**
+**  PARAMETERS:  MV_U32  minSaDelta
+**               MV_BOOL notCrcFix
+**               MV_BOOL ignCrc
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxBwMapConfigSet(MV_U32 minSaDelta,
+                                     MV_BOOL notCrcFix,
+                                     MV_BOOL ignCrc)
+{
+  MV_STATUS status;
+  MV_U32    ncfBit;
+  MV_U32    icBit;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_RX_BWMAP_CONFIG_MSD, minSaDelta, 0);
+  ncfBit  = (notCrcFix == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_BWMAP_CONFIG_DFIX, ncfBit, 0);
+  icBit   = (ignCrc == MV_TRUE) ? 1 : 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_BWMAP_CONFIG_IGNC, icBit, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxBwMapSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the onu Tx bw map table
+**
+**  PARAMETERS:  MV_U32  entry
+**               MV_U32  allocId
+**               MV_U32  tcontCnt
+**               MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxBwMapSet(MV_U32 entry,
+                               MV_U32 allocId,
+                               MV_U32 tcontCnt,
+                               MV_BOOL enable)
+{
+  MV_STATUS status;
+  MV_U32    enableVal;
+
+  enableVal = (enable == MV_TRUE) ? 1 : 0;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_RX_BW_MAP_TCN, tcontCnt, entry);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_BW_MAP_EN, enableVal, entry);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_RX_BW_MAP_ALID, allocId, entry);
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxBwMapGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the onu Tx bw translation table
+**
+**  PARAMETERS:  MV_U32 entry,
+**               MV_U32 *allocId,
+**               MV_U32 *enable,
+**               MV_U32 *tcontCnt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxBwMapGet(MV_U32 entry,
+                               MV_U32 *allocId,
+                               MV_BOOL *enable,
+                               MV_U32 *tcontCnt)
+{
+  MV_STATUS status;
+  MV_U32    enableVal;
+
+  status  = asicOntGlbRegRead(mvAsicReg_GPON_RX_BW_MAP_TCN, tcontCnt, entry);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_RX_BW_MAP_EN, &enableVal, entry);
+  *enable = (enableVal == 0) ? MV_FALSE : MV_TRUE;
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_RX_BW_MAP_ALID, allocId, entry);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxEqualizationDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the onu equalization delay
+**
+**  PARAMETERS:  MV_U32 delay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxEqualizationDelaySet(MV_U32 delay)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_RX_EQULIZATION_DELAY, delay, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxEqualizationDelayGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the onu equalization delay
+**
+**  PARAMETERS:  MV_U32 *delay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxEqualizationDelayGet(MV_U32 *delay)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_EQULIZATION_DELAY, delay, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxInternalDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the onu const delay
+**
+**  PARAMETERS:  MV_U32 txConstDelay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxInternalDelaySet(MV_U32 delay)
+{
+  MV_STATUS  status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_RX_INTERNAL_DELAY, delay, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxInternalDelayGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the onu const delay
+**
+**  PARAMETERS:  MV_U32 *txConstDelay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxInternalDelayGet(MV_U32 *delay)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_INTERNAL_DELAY, delay, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxSuperFrameCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reads Super Frame Counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxSuperFrameCounterGet(MV_U32 *counter)
+{
+	return(asicOntGlbRegRead(mvAsicReg_GPON_RX_SFRAME_COUNTER, counter, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxSuperFrameCounterSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets Super Frame Counter
+**
+**  PARAMETERS:  MV_U32 counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxSuperFrameCounterSet(MV_U32 counter)
+{
+	return(asicOntGlbRegWrite(mvAsicReg_GPON_RX_SFRAME_COUNTER, counter, 0));
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                           TX Low Level Routines                            */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxDelimiterSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the Tx delimiter
+**
+**  PARAMETERS:  MV_U32 delimiterPattern
+**               MV_U32 delimiterSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxDelimiterSet(MV_U32 delimiterPattern, MV_U32 delimiterSize)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_TX_DELIMITER_PAT, delimiterPattern, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_DELIMITER_SIZE, delimiterSize, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxDelimiterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the Tx delimiter
+**
+**  PARAMETERS:  MV_U32 *pattern
+**               MV_U32 *size
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxDelimiterGet(MV_U32 *pattern, MV_U32 *size)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_GPON_TX_DELIMITER_PAT, pattern, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_TX_DELIMITER_SIZE, size, 0);
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxPloamDataFifoSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the Tx ploam data fifo - one entry
+**
+**  PARAMETERS:  MV_U32 txPloamData
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxPloamDataFifoSet(MV_U32 txPloamData)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_TX_PLOAM_DATA_WRITE, txPloamData, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxPloamDataFreeGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the Tx ploam data fifo size
+**
+**  PARAMETERS:  MV_U32 *ploamFifoSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxPloamDataFreeGet(MV_U32 *ploamFifoSize)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_PLOAM_DATA_WRITE_FREE, ploamFifoSize, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacBurstEnParamSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the burst enable parameters
+**
+**  PARAMETERS:  MV_U32 mask
+**               MV_U32 polarity
+**               MV_U32 delay
+**               MV_U32 enStop
+**               MV_U32 enStart
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxBurstEnParamSet(MV_U32 mask,
+                                      MV_U32 polarity,
+                                      MV_U32 delay,
+                                      MV_U32 enStop,
+                                      MV_U32 enStart)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_TX_BURST_EN_PARAM_STR, enStart, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_BURST_EN_PARAM_STP, enStop, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_BURST_EN_PARAM_DLY, delay, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_BURST_EN_PARAM_P, polarity, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_BURST_EN_PARAM_MASK, mask, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxBurstEnPolaritySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the burst enable polarity
+**
+**  PARAMETERS:  MV_U32 polarity
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxBurstEnPolaritySet(MV_U32 polarity)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_TX_BURST_EN_PARAM_P, polarity, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxBurstEnParamGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the burst enable parameters
+**
+**  PARAMETERS:  MV_U32 *mask
+**               MV_U32 *polarity
+**               MV_U32 *delay
+**               MV_U32 *enStop
+**               MV_U32 *enStart
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxBurstEnParamGet(MV_U32 *mask,
+                                      MV_U32 *polarity,
+                                      MV_U32 *order,
+                                      MV_U32 *enStop,
+                                      MV_U32 *enStart)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_GPON_TX_BURST_EN_PARAM_STR, enStart, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_TX_BURST_EN_PARAM_STP, enStop, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_TX_BURST_EN_PARAM_DLY, order, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_TX_BURST_EN_PARAM_P, polarity, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_TX_BURST_EN_PARAM_MASK, mask, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxFinalDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the Tx final delay
+**
+**  PARAMETERS:  MV_U32 txFinalDelay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxFinalDelaySet(MV_U32 txFinalDelay)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_TX_FDELAY, txFinalDelay, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxFinalDelayGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the Tx final delay
+**
+**  PARAMETERS:  MV_U32 *txFinalDelay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxFinalDelayGet(MV_U32 *txFinalDelay)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_FDELAY, txFinalDelay, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxPreambleSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the Tx preamble type (1,2,3)
+**
+**  PARAMETERS:  MV_U32 preamType
+**               MV_U32 preamCnt
+**               MV_U32 preamVal
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxPreambleSet(MV_U32 type, MV_U32 pattern, MV_U32 size)
+{
+  MV_STATUS status;
+
+  if (type >= 3)
+  {
+    return(MV_ERROR);
+  }
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_TX_PREAMBLE_PATT, pattern, type);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_PREAMBLE_SIZE, size, type);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxPlsSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the Tx PLS
+**
+**  PARAMETERS:  MV_U32 pattern
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxPlsSet(MV_U32 pattern)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_TX_PLS_CONSTANT, pattern, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxConstIdleMsgSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the Tx const data ram - one entry
+**
+**  PARAMETERS:  MV_U32 onuId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxConstIdleMsgSet(MV_U32 onuId)
+{
+  MV_STATUS status;
+  MV_U32    dataWord;
+
+  dataWord = ((onuId & 0xFF) << 24) | (ONU_GPON_US_MSG_NO_MESSAGE << 16);
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_TX_CONST_DATA_RAM_IDLE, dataWord, 0);
+  dataWord = 0;
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_CONST_DATA_RAM_IDLE, dataWord, 1);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_CONST_DATA_RAM_IDLE, dataWord, 2);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxConstIdleMsgSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the Tx const data ram - one entry
+**
+**  PARAMETERS:  MV_U32 onuId
+**               MV_U8  *serialNumber
+**               MV_U32 randomDelay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxConstSerialNumberMsgSet(MV_U32 onuId,
+                                              MV_U8 *serialNumber,
+                                              MV_U32 randomDelay)
+{
+  MV_STATUS status;
+  MV_U32    dataWord;
+
+  dataWord = ((onuId & 0xFF) << 24) | (ONU_GPON_US_MSG_SN_ONU << 16) |
+             (((MV_U32)(serialNumber[0])) << 8) | (MV_U32)(serialNumber[1]);
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_TX_CONST_DATA_RAM_SN, dataWord, 0);
+
+  dataWord = (((MV_U32)(serialNumber[2])) << 24) | (((MV_U32)(serialNumber[3])) << 16) |
+             (((MV_U32)(serialNumber[4])) << 8) | (MV_U32)(serialNumber[5]);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_CONST_DATA_RAM_SN, dataWord, 1);
+
+  dataWord = (((MV_U32)(serialNumber[6])) << 24) | (((MV_U32)(serialNumber[7])) << 16) |
+             (((randomDelay >> 4) & 0xFF) << 8) | ((randomDelay & 0xF) << 4 | 5);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_TX_CONST_DATA_RAM_SN, dataWord, 2);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxDbrBlockSizeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the Tx DBR Block size
+**
+**  PARAMETERS:  MV_U32 blockSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxDbrBlockSizeSet(MV_U32 blockSize)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_TX_DBR_REPORT_BLOCK_IDX, blockSize, 0);
+
+  return(status);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                           General Low Level Routines                       */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacOnuIdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the ONU ID
+**
+**  PARAMETERS:  MV_U32 onuId
+**               MV_BOOL   valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacOnuIdSet(MV_U32 onuId, MV_BOOL valid)
+{
+  MV_STATUS status;
+  MV_U32    validBit;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_ONU_ID_OID, onuId, 0);
+
+  validBit = (valid == MV_TRUE) ? 1 : 0;
+
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_ONU_ID_V, validBit, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacOnuStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the onu state
+**
+**  PARAMETERS:  MV_U32 onuState
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacOnuStateSet(MV_U32 onuState)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_ONU_STATE, onuState, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacSerialNumberSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set 2 bytes of Serial Number
+**				 it is for ASIC random value creation - so the 2 last bytes
+**				 should be put here
+**
+**  PARAMETERS:  MV_U32 serialNum
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacSerialNumberSet(MV_U32 serialNum)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_TX_SERIAL_NUMBER, serialNum, 0);
+
+  return(status);
+}
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                           Gem Low Level Routines                           */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemPayloadLenSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the max gem payload length
+**
+**  PARAMETERS:  MV_U32 payloadlen
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemPayloadLenSet(MV_U32 payloadlen)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CONFIG_PLI, payloadlen, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemPayloadLenGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the max gem payload length
+**
+**  PARAMETERS:  MV_U32 *payloadlen
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemPayloadLenGet(MV_U32 *payloadlen)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_CONFIG_PLI, payloadlen, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemEthFrameLenSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the max / min ethernet frame length
+**
+**  PARAMETERS:  MV_U32 maxFrameLen
+**               MV_U32 minFrameLen
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemEthFrameLenSet(MV_U32 maxFrameLen, MV_U32 minFrameLen)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MAX, maxFrameLen, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MIN, minFrameLen, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemEthFrameLenGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the max / min ethernet frame length
+**
+**  PARAMETERS:  MV_U32 maxFrameLen
+**               MV_U32 minFrameLen
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemEthFrameLenGet(MV_U32 *maxFrameLen, MV_U32 *minFrameLen)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MAX, maxFrameLen, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MIN, minFrameLen, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemOmciFrameLenSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the max / min omci frame length
+**
+**  PARAMETERS:  MV_U32 maxFrameLen
+**               MV_U32 minFrameLen
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemOmciFrameLenSet(MV_U32 maxFrameLen, MV_U32 minFrameLen)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MAX, maxFrameLen, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MIN, minFrameLen, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemOmciFrameLenGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the max / min omci frame length
+**
+**  PARAMETERS:  MV_U32 maxFrameLen
+**               MV_U32 minFrameLen
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemOmciFrameLenGet(MV_U32 *maxFrameLen, MV_U32 *minFrameLen)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MAX, maxFrameLen, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MIN, minFrameLen, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemOmciPortIdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the omci port Id
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemOmciPortIdSet(MV_U32 portId, MV_U32 valid)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_ID,    portId, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_VALID, valid, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemOmciPortIdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the omci port Id
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemOmciPortIdGet(MV_U32 *portId, MV_U32 *valid)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_ID,    portId, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_VALID, valid, 0);
+
+  return(status);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                           UTM Low Level Routines                           */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacUtmOmciPortIdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the omci port Id
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacUtmOmciPortIdSet(MV_U32 portId, MV_U32 valid)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_ID,    portId, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_VALID, valid, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacUtmOmciPortIdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the omci port Id
+**
+**  PARAMETERS:  MV_U32 *portId
+**               MV_U32 *valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacUtmOmciPortIdGet(MV_U32 *portId, MV_U32 *valid)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_ID,    portId, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_VALID, valid, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacUtmTcPeriodSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the TC period
+**
+**  PARAMETERS:  MV_U32 period
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacUtmTcPeriodSet(MV_U32 period)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD, period, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacUtmTcValidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the TC valid
+**
+**  PARAMETERS:  MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacUtmTcValidSet(MV_U32 valid)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD_VALID, valid, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacUtmTcConfigGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the TC configuration
+**
+**  PARAMETERS:  MV_U32 *period
+**               MV_U32 *valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacUtmTcConfigGet(MV_U32 *period, MV_U32 *valid)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD,       period, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD_VALID, valid, 0);
+
+  return(status);
+}
+
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                           Interrupt Low Level Routines                     */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacPonInterruptGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the interrupt event
+**
+**  PARAMETERS:  MV_U32 *interrupt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacPonInterruptGet(MV_U32 *interrupt)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_INTERRUPT_PON, interrupt, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacPonInterruptMaskGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the interrupt mask
+**
+**  PARAMETERS:  MV_U32 *mask
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacPonInterruptMaskGet(MV_U32 *mask)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_INTERRUPT_PON_MASK, mask, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacPonInterruptMaskSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the interrupt mask
+**
+**  PARAMETERS:  MV_U32 *mask
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacPonInterruptMaskSet(MV_U32 mask)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_INTERRUPT_PON_MASK, mask, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacBipStatusValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the BIP8 general counter
+**
+**  PARAMETERS:  MV_U32 *value
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacBipStatusValueGet(MV_U32 *value)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_BIP_STATUS, value, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacBipInterruptIntervalSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the BIP8 interrupt interval (in frames)
+**
+**  PARAMETERS:  MV_U32 interval
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacBipInterruptIntervalSet(MV_U32 interval)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_BIP_INTR_INTERVAL, interval, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacBipStatusValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the BIP8 interrupt counter
+**
+**  PARAMETERS:  MV_U32 *value
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacBipInterruptStatusValueGet(MV_U32 *value)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_RX_BIP_STATUS_FOR_INTERRUPT, value, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacBipInterruptIntervalSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set ram test configuration
+**
+**  PARAMETERS:  MV_U32 interval
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRamTestCfgSet(MV_U32 config)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_RAM_TEST_CONFIG, config, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRamTestCfgGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return ram test configuration
+**
+**  PARAMETERS:  MV_U32 *value
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRamTestCfgGet(MV_U32 *config)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_RAM_TEST_CONFIG, config, 0);
+
+  return(status);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                           Statistics Low Level Routines                    */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                       GEM Statistics Low Level Routines                    */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdIdleGemFramesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received idle gem frames counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdIdleGemFramesCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_IDLE_GEM_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdValidGemFramesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received valid gem frames counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdValidGemFramesCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_VALID_GEM_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdUndefGemFramesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received undefined gem frames counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdUndefGemFramesCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_UNDEF_GEM_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdOmciFramesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received omci frames counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdOmciFramesCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_VALID_OMCI_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemDropGemFramesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received dropped gem frames counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemDropGemFramesCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_DROPPED_GEM_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemDropOmciFramesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received dropped omci frames counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemDropOmciFramesCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_DROPPED_OMCI_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdGemFramesWithUncorrHecErrCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received gem frames with uncorrect hec error counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdGemFramesWithUncorrHecErrCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_ERROR_GEM_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdGemFramesWithOneFixedHecErrCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received gem frames with one fixed hec error counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdGemFramesWithOneFixedHecErrCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_ONE_FIXED_HEC_ERR_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdGemFramesWithTwoFixedHecErrCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received gem frames with two fixed hec error counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdGemFramesWithTwoFixedHecErrCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_TWO_FIXED_HEC_ERR_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdValidGemFramesTotalByteCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received valid gem frames total bytes counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdValidGemFramesTotalByteCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_VALID_GEM_PAYLOAD_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdUndefGemFramesTotalByteCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received undefined gem frames total bytes counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdUndefGemFramesTotalByteCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_UNDEF_GEM_PAYLOAD_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemReassembleMemoryFlushCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received gem reassemble memory flush counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemReassembleMemoryFlushCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_RSMBL_MEM_FLUSH_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemSynchLostCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return gem synch lost counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemSynchLostCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_LCDGi_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdEthFramesWithCorrFcsCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received ethernet frames with correct FCS counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdEthFramesWithCorrFcsCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_CORR_ETH_FRAME_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdEthFramesWithFcsErrCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received ethernet frames with FCS error counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdEthFramesWithFcsErrCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_ERR_ETH_FRAME_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdOmciFramesWithCorrCrcCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received omci frames with correct CRC counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdOmciFramesWithCorrCrcCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_CORR_OMCI_FRAME_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemRcvdOmciFramesWithCrcErrCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received omci frames with CRC error counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemRcvdOmciFramesWithCrcErrCounterGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_GEM_STAT_ERR_OMCI_FRAME_CNT, cntValue, 0);
+
+  return(status);
+}
+
+/* ========================================================================== */
+/*                  Rx PLOAM Statistics Low Level Routines                    */
+/* ========================================================================== */
+
+/******************************************************************************
+**
+**  mvOnuGponMacRxPloamLostCrcCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx ploam lost crc counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPloamLostCrcCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  *counter = 0;
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_PLOAMD_LOST_CRC_STATUS, counter, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPloamLostFullCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx ploam lost full counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPloamLostFullCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  *counter = 0;
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_PLOAMD_LOST_FULL_STATUS, counter, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPloamRcvdIdleCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx ploam received idle counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPloamRcvdIdleCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  *counter = 0;
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_PLOAMD_RCVD_IDLE_STATUS, counter, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPloamRcvdBroadCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx ploam received broadcast counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPloamRcvdBroadCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  *counter = 0;
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_PLOAMD_RCVD_BROAD_STATUS, counter, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxPloamRcvdOnuIdCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx ploam received Onu Id counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxPloamRcvdOnuIdCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  *counter = 0;
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_PLOAMD_RCVD_MYID_STATUS, counter, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/* ========================================================================== */
+/*                        Tx Statistics Low Level Routines                    */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxGemPtiTypeOneFrameCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the num of trans gem frames with pti = 1
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxGemPtiTypeOneFrameCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_STAT_GEM_PTI1, counter, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxGemPtiTypeZeroFrameCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the num of trans gem frames with pti = 0
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxGemPtiTypeZeroFrameCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_STAT_GEM_PTI0, counter, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxIdleGemFramesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the num of trans idle gem frames
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxIdleGemFramesCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_STAT_GEM_IDLE, counter, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxTxEnableCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the num of cycles with tx enable asserted
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxTxEnableCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_STAT_TX_EN_CNT, counter, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxTxEnableCounterThresholdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return tx enable counter threshold
+**
+**  PARAMETERS:  MV_U32 *threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxTxEnableCounterThresholdGet(MV_U32 *threshold)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_CONFIG_EN_THRESHOLD, threshold, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxTxEnableCounterThresholdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set tx enable counter threshold
+**
+**  PARAMETERS:  MV_U32 threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxTxEnableCounterThresholdSet(MV_U32 threshold)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_TX_CONFIG_EN_THRESHOLD, threshold, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxGseTransCounterThresholdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GSE threshold for starting forwarding data to
+**               the TX burst FIFO
+**
+**  PARAMETERS:  MV_U32 *threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxGseTransCounterThresholdGet(MV_U32 *threshold)
+{
+   MV_STATUS status;
+
+   status = asicOntGlbRegRead(mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD, threshold, 0);
+
+   return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxGseTransCounterThresholdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set GSE threshold for starting forwarding data to
+**               the TX burst FIFO
+**
+**  PARAMETERS:  MV_U32 threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxGseTransCounterThresholdSet(MV_U32 threshold)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD, threshold, 0);
+
+  return(status);
+}
+
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxGseTransConfigAcCouplingSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set GSE Transmit Configuration AC coupling
+**
+**  PARAMETERS:  MV_U32 busrtMode          - GPON_TX_AC_COUPL_BUST_MODE_0 or
+**					     GPON_TX_AC_COUPL_BUST_MODE_1
+**		 MV_U32 preActiveBurstTime - time from burst to TX pattern2
+**		 MV_U8  dataPattern1       - Pattern1
+**		 MV_U8  dataPattern2       - Pattern2
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxConfigAcCouplingGet(MV_U32 *busrtMode,
+					    MV_U32 *preActiveBurstTime,
+					    MV_U8  *dataPattern1,
+					    MV_U8  *dataPattern2)
+{
+	MV_STATUS status;
+	MV_U32    reg;
+
+	status = asicOntGlbRegRead(mvAsicReg_GPON_TX_CFG_AC_COUPLING, &reg, 0);
+	if (status == MV_OK) {
+		*busrtMode           = (reg >> 30) & 0x3;
+		*preActiveBurstTime  = (reg >> 16) & 0x3FFF;
+		*dataPattern2        = (reg >>  8) & 0xFF;
+		*dataPattern1        = reg & 0xFF;
+	}
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxGseTransConfigAcCouplingSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set GSE Transmit Configuration AC coupling
+**
+**  PARAMETERS:  MV_U32 busrtMode          - GPON_TX_AC_COUPL_BUST_MODE_0 or
+**					     GPON_TX_AC_COUPL_BUST_MODE_1
+**		 MV_U32 preActiveBurstTime - time from burst to TX pattern2
+**		 MV_U8  dataPattern1       - Pattern1
+**		 MV_U8  dataPattern2       - Pattern2
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxConfigAcCouplingSet(MV_U32 busrtMode,
+					    MV_U32 preActiveBurstTime,
+					    MV_U8  dataPattern1,
+					    MV_U8  dataPattern2)
+{
+	MV_U32    reg = 0;
+
+	if (busrtMode != GPON_TX_AC_COUPL_BUST_MODE_0)
+		reg = 1 << 30;
+
+	reg |= (preActiveBurstTime & 0x3FFF) << 16;
+	reg |= dataPattern1 | (dataPattern2 << 8);
+
+	return(asicOntGlbRegWrite(mvAsicReg_GPON_TX_CFG_AC_COUPLING, reg, 0));
+}
+
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxEthFramesTcontiCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return number of trans ethernet frames via tcont
+**
+**  PARAMETERS:  MV_U32 tcontNum
+**               MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxEthFramesTcontiCounterGet(MV_U32 tcontNum, MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  if (tcontNum >= ONU_GPON_MAX_NUM_OF_T_CONTS)
+      return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_FRAMES, counter, tcontNum);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxEthBytesTcontiCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return number of trans ethernet bytes via tcont
+**
+**  PARAMETERS:  MV_U32 tcontNum
+**               MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxEthBytesTcontiCounterGet(MV_U32 tcontNum, MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  if (tcontNum >= ONU_GPON_MAX_NUM_OF_T_CONTS)
+      return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_BYTES, counter, tcontNum);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxGemFramesTcontiCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return number of trans gem frames via tcont
+**
+**  PARAMETERS:  MV_U32 tcontNum
+**               MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxGemFramesTcontiCounterGet(MV_U32 tcontNum, MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  if (tcontNum >= ONU_GPON_MAX_NUM_OF_T_CONTS)
+      return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_STAT_TCONT_i_GEM_FRAMES, counter, tcontNum);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxIdleGemFramesTcontiCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return number of trans idle gem frames via tcont
+**
+**  PARAMETERS:  MV_U32 tcontNum
+**               MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxIdleGemFramesTcontiCounterGet(MV_U32 tcontNum, MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  if (tcontNum >= ONU_GPON_MAX_NUM_OF_T_CONTS)
+      return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_TX_STAT_TCONT_i_IDLE_GEM, counter, tcontNum);
+
+  return(status);
+}
+
+/* ========================================================================== */
+/*                       FEC Statistics Low Level Routines                    */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxFecBytesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx FEC Bytes counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxFecBytesCounterGet(MV_U32 *counter)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_FEC_STAT0, counter, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxFecCorrectBytesCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx FEC correct Bytes counter
+**
+**  PARAMETERS:  MV_U32 *bytes
+**               MV_U32 *bits
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxFecCorrectCounterGet(MV_U32 *bytes, MV_U32 *bits)
+{
+  MV_STATUS status;
+  MV_U32    regVal;
+
+  *bytes = 0;
+  *bits  = 0;
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_FEC_STAT1, &regVal, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  *bits  =  regVal & 0xFFFF;
+  *bytes = (regVal >> 16) & 0xFFFF;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxFecInorrectCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx FEC Incorrect Bytes counter
+**
+**  PARAMETERS:  MV_U32 *bytes
+**               MV_U32 *bits
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxFecInorrectCounterGet(MV_U32 *bytes, MV_U32 *bits)
+{
+  MV_STATUS status;
+  MV_U32    regVal;
+
+  *bytes = 0;
+  *bits  = 0;
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_FEC_STAT2, &regVal, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  *bits  = regVal & 0xFFFF;
+  *bytes = (regVal >> 16) & 0xFFFF;
+
+  return(MV_OK);
+}
+
+/* ========================================================================== */
+/*                    Bw Map Statistics Low Level Routines                    */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxBwMapAllocatrionsCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx Bw Map allocation counters
+**
+**  PARAMETERS:  MV_U32 *cor
+**               MV_U32 *incor
+**               MV_U32 *crcCor
+**               MV_U32 *errCrc
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxBwMapAllocatrionsCounterGet(MV_U32 *cor,
+                                                    MV_U32 *incor,
+                                                    MV_U32 *crcCor,
+                                                    MV_U32 *errCrc)
+{
+  MV_STATUS status;
+  MV_U32    regVal;
+
+  *cor    = 0;
+  *incor  = 0;
+  *crcCor = 0;
+  *errCrc = 0;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_BWMAP_STATUS0, &regVal, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  *incor  = regVal & 0xFF;
+  *crcCor = (regVal >> 8) & 0xFF;
+  *cor    = (regVal >> 16) & 0xFF;
+  *errCrc = (regVal >> 24) & 0xFF;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacRxBwMapTotalBwGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx Bw total Bw counter
+**
+**  PARAMETERS:  MV_U32 *bw
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacRxBwMapTotalBwGet(MV_U32 *bw)
+{
+  MV_STATUS status;
+  MV_U32    regVal;
+
+  *bw = 0;
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_BWMAP_STATUS1, &regVal, 0);
+  if (status != MV_OK)
+  {
+    return(status);
+  }
+
+  *bw = regVal & 0x7FFFF;
+
+  return(MV_OK);
+}
+
+/* ========================================================================== */
+/*                     Plend Statistics Low Level Routines                    */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  onuGponInComingPlendCntGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return InComing Plend counter
+**
+**  PARAMETERS:  MV_U32 *cntValue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacInComingPlendCntGet(MV_U32 *cntValue)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_GPON_RX_PLEND_STATUS, cntValue, 0);
+
+  return(status);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         High-Level MAC Section                             */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacMessageReceive
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function read message from the message fifo
+**               The ploam size is 12 octets - each read get 32 bits
+**               3 read actions needed
+**
+**  PARAMETERS:  msgData  - 10 bytes (buffer is allocated by calling)
+**               msgOnuId - the ONU ID on the message
+**               msgId    - the message ID on the message
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacMessageReceive(MV_U8 *msgOnuId, MV_U8 *msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U32    ploamFifoData_1;
+  MV_U32    ploamFifoData_2;
+  MV_U32    ploamFifoData_3;
+
+  rcode  = mvOnuGponMacRxPloamDataGet(&ploamFifoData_1);
+  rcode |= mvOnuGponMacRxPloamDataGet(&ploamFifoData_2);
+  rcode |= mvOnuGponMacRxPloamDataGet(&ploamFifoData_3);
+
+  if (rcode != MV_OK)
+    return(rcode);
+
+  /* Outputs */
+  *msgOnuId  = (MV_U8)((ploamFifoData_1 >> 24) & UINT8_MASK);  /* MSB */
+  *msgId     = (MV_U8)((ploamFifoData_1 >> 16) & UINT8_MASK);
+  msgData[0] = (MV_U8)((ploamFifoData_1 >> 8)  & UINT8_MASK);
+  msgData[1] = (MV_U8) (ploamFifoData_1        & UINT8_MASK);  /* LSB */
+  msgData[2] = (MV_U8)((ploamFifoData_2 >> 24) & UINT8_MASK);  /* MSB */
+  msgData[3] = (MV_U8)((ploamFifoData_2 >> 16) & UINT8_MASK);
+  msgData[4] = (MV_U8)((ploamFifoData_2 >> 8)  & UINT8_MASK);
+  msgData[5] = (MV_U8) (ploamFifoData_2        & UINT8_MASK);  /* LSB */
+  msgData[6] = (MV_U8)((ploamFifoData_3 >> 24) & UINT8_MASK);  /* MSB */
+  msgData[7] = (MV_U8)((ploamFifoData_3 >> 16) & UINT8_MASK);
+  msgData[8] = (MV_U8)((ploamFifoData_3 >> 8)  & UINT8_MASK);
+  msgData[9] = (MV_U8) (ploamFifoData_3        & UINT8_MASK);  /* LSB */
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxPloamSend
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function writes PLOAM message to HW FIFO
+**
+**  PARAMETERS:  msgData  - 10 bytes (buffer is allocated by calling)
+**               msgOnuId - the ONU ID on the message
+**               msgId    - the message ID on the message
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxPloamSend(MV_U8 msgOnuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U32    ploamFifoData;
+
+  fifoMacPloamSend++;
+
+  /* Write ONU ID and Message ID and data[0:1] */
+  ploamFifoData =  (((MV_U32)msgOnuId) << 24) | (((MV_U32)msgId) << 16) |
+                   (((MV_U32)msgData[0]) << 8) |(((MV_U32)msgData[1]) << 0);
+  rcode = mvOnuGponMacTxPloamDataFifoSet(ploamFifoData);
+
+  /* Write data[2:5] */
+  ploamFifoData =  (((MV_U32)msgData[2]) << 24) | (((MV_U32)msgData[3]) << 16) |
+                   (((MV_U32)msgData[4]) << 8) |(((MV_U32)msgData[5]) << 0);
+  rcode |= mvOnuGponMacTxPloamDataFifoSet(ploamFifoData);
+
+  /* Write data[6:9] */
+  ploamFifoData =  (((MV_U32)msgData[6]) << 24) | (((MV_U32)msgData[7]) << 16) |
+                   (((MV_U32)msgData[8]) << 8) |(((MV_U32)msgData[9]) << 0);
+  rcode |= mvOnuGponMacTxPloamDataFifoSet(ploamFifoData);
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacMessageAdd
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function adds message to the SW FIFO
+**
+**  PARAMETERS:  msgData  - 10 bytes (buffer is allocated by calling)
+**               msgOnuId - the ONU ID on the message
+**               msgId    - the message ID on the message
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_FULL
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacMessageAdd(MV_U8 msgOnuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U8     *buffer;
+  MV_U32    bufferIndex;
+
+  /* Get pointer to and index of the free SW FIFO entry */
+  rcode = mvOnuGponMacFifoMsgAlloc((MV_U32**)&buffer, &bufferIndex);
+  if (rcode == MV_OK)
+  {
+    buffer[0] = msgOnuId;
+    buffer[1] = msgId;
+    memcpy(&buffer[2], msgData, GPON_PLOAM_MSG_BYTES - 2);
+
+    mvOnuGponMacFifoMsgSend(bufferIndex);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacMessageSend
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function write message to the message fifo
+**
+**  PARAMETERS:  msgData  - 10 bytes (buffer is allocated by calling)
+**               msgOnuId - the ONU ID on the message
+**               msgId    - the message ID on the message
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK, MV_FULL or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacMessageSend(MV_U8 msgOnuId, MV_U8 msgId, MV_U8 *msgData)
+{
+  MV_STATUS rcode;
+  MV_U32    ploamFifoSize;
+  MV_U8     *buffer;
+  MV_U32    bufferIndex;
+  int       i, moved_num;
+
+  fifoMacMsgSend++;
+
+  /* Check first if PLOAM FIFO has free place */
+  rcode = mvOnuGponMacTxPloamDataFreeGet(&ploamFifoSize);
+
+  if (rcode != MV_OK)
+    return(rcode);
+
+  /* SW FIFO is not supported */
+  if (!fifoSupported)
+  {
+    if (ploamFifoSize < GPON_PLOAM_MSG_WORDS)
+      return(MV_ERROR);
+
+    return mvOnuGponMacTxPloamSend(msgOnuId, msgId, msgData);
+  }
+
+  /* There is no free entries in  HW FIFO */
+  if (ploamFifoSize < GPON_PLOAM_MSG_WORDS)
+  {
+    rcode = mvOnuGponMacMessageAdd(msgOnuId, msgId, msgData);
+  }
+  else
+  {
+    /* HW FIFO has free entries. Verify whether SW FIFO is empty */
+    if (mvOnuGponMacFifoEmpty())
+    {
+        rcode = mvOnuGponMacTxPloamSend(msgOnuId, msgId, msgData);
+    }
+    else
+    {
+      /* Add received PLOAM to SW FIFO */
+      rcode = mvOnuGponMacMessageAdd(msgOnuId, msgId, msgData);
+
+      /* Move up to GPON_MAX_US_MSG_MOVING (3) PLOAMs from SW to HW FIFO */
+      moved_num = ploamFifoSize/GPON_PLOAM_MSG_WORDS;
+      if (moved_num > GPON_MAX_US_MSG_MOVING) {
+          moved_num = GPON_MAX_US_MSG_MOVING;
+      }
+
+      for (i=0; i<moved_num; i++)
+      {
+        rcode = mvOnuGponMacFifoMsgRece((MV_U32**)&buffer, &bufferIndex);
+        if (rcode == MV_EMPTY)
+          break;
+
+        rcode = mvOnuGponMacTxPloamSend(buffer[0], buffer[1], &buffer[2]);
+        if(rcode != MV_OK)
+          break;
+
+        mvOnuGponMacFifoMsgFree(bufferIndex);
+      }
+    }
+  }
+
+  return rcode;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacMessageCleanSwFifo
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function clean the SW transmit message fifo
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK, MV_FULL or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacMessageCleanSwFifo(void)
+{
+  MV_STATUS rcode;
+  MV_U8     *buffer;
+  MV_U32    bufferIndex;
+
+  do
+  {
+    rcode = mvOnuGponMacFifoMsgRece((MV_U32**)&buffer, &bufferIndex);
+    if (rcode == MV_EMPTY)
+      break;
+
+    mvOnuGponMacFifoMsgFree(bufferIndex);
+
+  } while (1);
+
+  return MV_OK;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacPreambleSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the onu overhead preamble bytes
+**
+**  PARAMETERS:  preamType1Val - preamble type 1 value
+**               preamType1Cnt - preamble type 1 count
+**               preamType2Val - preamble type 2 value
+**               preamType2Cnt - preamble type 2 count
+**               preamType3Val - preamble type 3 value
+**               preamType3Cnt - preamble type 3 count
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacPreambleSet(MV_U32 preamType1Val,
+                                MV_U32 preamType1Cnt,
+                                MV_U32 preamType2Val,
+                                MV_U32 preamType2Cnt,
+                                MV_U32 preamType3Val,
+                                MV_U32 preamType3Cnt)
+{
+  MV_STATUS rcode;
+
+  rcode = mvOnuGponMacTxPreambleSet(ONU_GPON_PREM_TYPE_01, preamType1Val, preamType1Cnt);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  rcode = mvOnuGponMacTxPreambleSet(ONU_GPON_PREM_TYPE_02, preamType2Val, preamType2Cnt);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  rcode = mvOnuGponMacTxPreambleSet(ONU_GPON_PREM_TYPE_03, preamType3Val, preamType3Cnt);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacPreambleType3Set
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set the onu overhead preamble type3
+**
+**  PARAMETERS:  preamType3Val - preamble type 3 value
+**               preamType3Cnt - preamble type 3 count
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacPreambleType3Set(MV_U32 preamType3Val, MV_U32 preamType3Cnt)
+{
+  MV_STATUS rcode;
+
+  rcode = mvOnuGponMacTxPreambleSet(ONU_GPON_PREM_TYPE_03, preamType3Val, preamType3Cnt);
+  if (rcode != MV_OK)
+  {
+    return(rcode);
+  }
+
+  return(MV_OK);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                      Upstream Messages MAC Section                         */
+/* ========================================================================== */
+/******************************************************************************/
+#ifndef PON_FPGA
+/*******************************************************************************
+**
+**  mvOnuGponMacDgMessageSend
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sends dying gasp message in the US direction
+**
+**  PARAMETERS:  MV_U8  onuId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacDgMessageSend(MV_U8 onuId)
+{
+  MV_U32    i;
+  MV_STATUS rcode;
+  MV_U8     data[12];
+
+  for (i = 0; i < 3; i++)
+  {
+    rcode = mvOnuGponMacMessageSend(onuId, ONU_GPON_US_MSG_DYING_GASP, data);
+    if (rcode != MV_OK)
+    {
+      mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_DYING_GASP, MV_FALSE);
+      return(rcode);
+    }
+    else
+    {
+      mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_DYING_GASP, MV_TRUE);
+    }
+  }
+  return(MV_OK);
+}
+#endif /* PON_FPGA */
+
+/*******************************************************************************
+**
+**  mvOnuGponMacPasswordMessageSend
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sends password message in the US direction
+**
+**  PARAMETERS:  MV_U8  onuId
+**               MV_U8  *password
+**               MV_U32 counter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacPasswordMessageSend(MV_U8 onuId, MV_U8 *password, MV_U32 counter)
+{
+  MV_U32    time;
+  MV_U32    i;
+  MV_STATUS rcode;
+  time = (counter > 3) ? 3 : counter;
+
+  for (i = 0; i < time; i++)
+  {
+    rcode = mvOnuGponMacMessageSend(onuId, ONU_GPON_US_MSG_PASSWORD, password);
+    if (rcode != MV_OK)
+    {
+      mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_PASSWORD, MV_FALSE);
+      return(rcode);
+    }
+    else
+    {
+      mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_PASSWORD, MV_TRUE);
+    }
+  }
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacReiMessageSend
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sends dying gasp message in the US direction
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 errorsCounter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacReiMessageSend(MV_U8 onuId, MV_U32 errorsCounter)
+{
+  MV_STATUS     rcode;
+  static MV_U8 sequenceNumber = 0;
+  MV_U8        data[12];
+
+  data[0] = (MV_U8)((errorsCounter >> 24) & 0xFF);
+  data[1] = (MV_U8)((errorsCounter >> 16) & 0xFF);
+  data[2] = (MV_U8)((errorsCounter >> 8) & 0xFF);
+  data[3] = (MV_U8)(errorsCounter & 0xFF);
+  data[4] = sequenceNumber;
+
+  sequenceNumber++;
+  if (sequenceNumber > 0xF) sequenceNumber = 0;
+
+  rcode = mvOnuGponMacMessageSend(onuId, ONU_GPON_US_MSG_REI, data);
+  if (rcode != MV_OK)
+  {
+    mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_REI, MV_FALSE);
+    return(rcode);
+  }
+  else
+  {
+    mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_REI, MV_TRUE);
+  }
+
+	return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacAcknowledgeMessageSend
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sends acknowledge message in the US direction
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 errorsCounter
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacAcknowledgeMessageSend(MV_U8 onuId, MV_U8 dmId, MV_U8 *dmByte)
+{
+  MV_STATUS rcode;
+  MV_U8    data[12];
+
+  data[0] = dmId;
+
+  data[1] = onuId;
+  data[2] = dmId;
+  data[3] = dmByte[0];
+  data[4] = dmByte[1];
+  data[5] = dmByte[2];
+  data[6] = dmByte[3];
+  data[7] = dmByte[4];
+  data[8] = dmByte[5];
+  data[9] = dmByte[6];
+
+  rcode = mvOnuGponMacMessageSend(onuId, ONU_GPON_US_MSG_ACK, data);
+  if (rcode != MV_OK)
+  {
+    mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_ACK, MV_FALSE);
+    return(rcode);
+  }
+  else
+  {
+    mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_ACK, MV_TRUE);
+  }
+
+	return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacEncryptionKeyMessageSend
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sends encryption key message in the US direction
+**
+**  PARAMETERS:  MV_U8 onuId
+**               MV_U8 KeyIndex
+**               MV_U8 fragIndex
+**               MV_U8 *key
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacEncryptionKeyMessageSend(MV_U8 onuId,
+                                             MV_U8 KeyIndex,
+                                             MV_U8 fragIndex,
+                                             MV_U8 *key)
+{
+  MV_STATUS rcode;
+  MV_U8    data[12];
+
+  data[0] = KeyIndex;
+  data[1] = fragIndex;
+  data[2] = key[0];
+  data[3] = key[1];
+  data[4] = key[2];
+  data[5] = key[3];
+  data[6] = key[4];
+  data[7] = key[5];
+  data[8] = key[6];
+  data[9] = key[7];
+
+  rcode = mvOnuGponMacMessageSend(onuId, ONU_GPON_US_MSG_ENCRYPT_KEY, data);
+  if (rcode != MV_OK)
+  {
+    mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_ENCRYPT_KEY, MV_FALSE);
+    return(rcode);
+  }
+  else
+  {
+    mvOnuGponMacTxSwCountersAdd(ONU_GPON_US_MSG_ENCRYPT_KEY, MV_TRUE);
+  }
+
+	return(rcode);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                              AES Support                                   */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacAesInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu AES
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacAesInit(void)
+{
+  MV_U32    i;
+  MV_STATUS rcode = MV_OK;
+
+  for (i = 0 ; i < (GPON_ONU_MAX_GEM_PORTS/32) ; i++)
+  {
+    onuGponPortAesStatusImage[i] = 0;
+    rcode |= asicOntGlbRegWrite(mvAsicReg_GPON_GEM_AES_PID_TABLE, onuGponPortAesStatusImage[i], i);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacAesEnableSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enable onu AES
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacAesEnableSet(MV_BOOL enable)
+{
+  MV_STATUS rcode = MV_OK;
+  MV_U32    enableBit;
+
+  enableBit = (enable == MV_TRUE) ? 1 : 0;
+
+  rcode = asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CONFIG_AES , enableBit, 0);
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacAesPortIdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function AES for port Id
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_BOOL   status
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacAesPortIdSet(MV_U32 portId, MV_BOOL status)
+{
+  MV_STATUS rcode;
+  MV_U32    group;
+  MV_U32    groupOffset;
+  MV_U32    regData;
+  MV_U32    statusBit;
+
+  group       = portId / 32;
+  groupOffset = portId % 32;
+  statusBit   = (status == MV_TRUE) ? 1 : 0;
+
+  /* Get Image */
+  regData = onuGponPortAesStatusImage[group];
+
+  /* Update the bit */
+  regData &= ~(1 << groupOffset);                 /* Clear the bit */
+  regData |= (statusBit << groupOffset);          /* Set the status */
+  onuGponPortAesStatusImage[group] = regData;   /* Update the Image */
+  rcode = asicOntGlbRegWrite (mvAsicReg_GPON_GEM_AES_PID_TABLE , regData, group);
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacAesPortIdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return port Id AES state
+**
+**  PARAMETERS:  MV_U32 portId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_BOOL mvOnuGponMacAesPortIdGet(MV_U32 portId)
+{
+  MV_U32  group;
+  MV_U32  groupOffset;
+  MV_U32  statusBit;
+  MV_BOOL status;
+
+  group       = portId / 32;
+  groupOffset = portId % 32;
+  statusBit = (onuGponPortAesStatusImage[group] >> groupOffset) & 1;
+
+  status = (statusBit == 0) ? MV_FALSE : MV_TRUE;
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacAesKeyShadowWrite
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function write AES key to GPON MAC
+**
+**  PARAMETERS:  MV_U8 *key
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacAesKeyShadowWrite(MV_U8 *key)
+{
+  MV_U32    i;
+  MV_U32    regData;
+  MV_STATUS rcode = MV_OK;
+
+  for (i = 0 ; i < 4 ; i++)
+  {
+    regData = (((MV_U32)(key[i * 4]))     << 24) |
+              (((MV_U32)(key[i * 4 + 1])) << 16) |
+              (((MV_U32)(key[i * 4 + 2])) <<  8) |
+               ((MV_U32)(key[i * 4 + 3]));
+    rcode |= asicOntGlbRegWrite (mvAsicReg_GPON_GEM_AES_SHADOW_KEY, regData, i);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacIpgValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets IPG value
+**
+**  PARAMETERS:  MV_U32 ipgVal
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacIpgValueSet(MV_U32 ipgVal)
+{
+	return(asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CFG_IPG_VALUE , ipgVal, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacIpgValueGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns IPG value
+**
+**  PARAMETERS:  MV_U32 *ipgVal
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacIpgValueGet(MV_U32 *ipgVal)
+{
+	return(asicOntGlbRegRead(mvAsicReg_GPON_GEM_CFG_IPG_VALUE, ipgVal, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacIpgValidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enables IPG value settings
+**
+**  PARAMETERS:  MV_BOOL enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacIpgValidSet(MV_BOOL enable)
+{
+	MV_U32    enableBit = (enable == MV_TRUE) ? 1 : 0;
+
+	return(asicOntGlbRegWrite(mvAsicReg_GPON_GEM_CFG_IPG_VALID , enableBit, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacIpgValidGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get IPG value inabled/disabled status
+**
+**  PARAMETERS:  MV_BOOL *enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacIpgValidGet(MV_BOOL *enable)
+{
+	MV_STATUS rcode = MV_OK;
+	MV_U32    enableBit;
+
+	if (enable == 0)
+		return(MV_BAD_PARAM);
+
+	rcode  = asicOntGlbRegRead(mvAsicReg_GPON_GEM_CFG_IPG_VALID , &enableBit, 0);
+	if (rcode == MV_OK)
+		*enable = (enableBit == 0) ? MV_FALSE : MV_TRUE;
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacGemInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function init onu Gem
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacGemInit(void)
+{
+  MV_U32    i;
+  MV_STATUS rcode = MV_OK;
+
+  for (i = 0 ; i < (GPON_ONU_MAX_GEM_PORTS/32) ; i++)
+  {
+    onuGponPortValidStatusImage[i] = 0;
+    rcode |= asicOntGlbRegWrite (mvAsicReg_GPON_GEM_VALID_PID_TABLE, onuGponPortValidStatusImage[i], i);
+  }
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacPortIdValidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set valid for port Id
+**
+**  PARAMETERS:  MV_U32 portId
+**               MV_BOOL   status
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacPortIdValidSet(MV_U32 portId, MV_BOOL status)
+{
+  MV_STATUS rcode;
+  MV_U32    group;
+  MV_U32    groupOffset;
+  MV_U32    regData;
+  MV_U32    statusBit;
+
+  group       = portId / 32;
+  groupOffset = portId % 32;
+  statusBit   = (status == MV_TRUE) ? 1 : 0;
+
+  /* Get Image */
+  regData = onuGponPortValidStatusImage[group];
+
+  /* Update the bit */
+  regData &= ~(1 << groupOffset);                 /* Clear the bit */
+  regData |= (statusBit << groupOffset);          /* Set the status */
+  onuGponPortValidStatusImage[group] = regData;   /* Update the Image */
+  rcode = asicOntGlbRegWrite (mvAsicReg_GPON_GEM_VALID_PID_TABLE , regData, group);
+
+  return(rcode);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacPortIdValidGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return port Id valid state
+**
+**  PARAMETERS:  MV_U32 portId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_BOOL mvOnuGponMacPortIdValidGet(MV_U32 portId)
+{
+  MV_U32  group;
+  MV_U32  groupOffset;
+  MV_U32  statusBit;
+  MV_BOOL status;
+
+  group       = portId / 32;
+  groupOffset = portId % 32;
+  statusBit   = (onuGponPortValidStatusImage[group] >> groupOffset) & 1;
+
+  status = (statusBit == 0) ? MV_FALSE : MV_TRUE;
+
+  return(status);
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                        SW FIFO                                             */
+/* ========================================================================== */
+/******************************************************************************/
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoInit
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function inits SW FIFO
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void mvOnuGponMacFifoInit(void)
+{
+  fifoCtrl.fifoReadIndex    = 0;
+  fifoCtrl.fifoWriteIndex   = 0;
+  fifoCtrl.fifoReparoundNum = 0;
+
+  memset(fifoCtrl.fifoData, 0, GPON_SW_FIFO_SIZE * sizeof(S_MacPloamMsg));
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoMsgAlloc
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function allocates a buffer from the FIFO
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     MV_U32 **buffer
+**               MV_U32 *bufferIndex
+**
+**  RETURNS:     MV_OK or MV_FULL
+**
+*******************************************************************************/
+static inline MV_STATUS mvOnuGponMacFifoMsgAlloc(MV_U32 **buffer,
+                                                 MV_U32 *bufferIndex)
+{
+  MV_U32  nextWriteIndex;
+
+  nextWriteIndex = fifoCtrl.fifoWriteIndex + 1;
+
+  /* roll over */
+  if (nextWriteIndex >= GPON_SW_FIFO_SIZE)
+  {
+    nextWriteIndex = 0;
+    fifoCtrl.fifoReparoundNum++;
+  }
+
+  if (nextWriteIndex != fifoCtrl.fifoReadIndex)
+  {
+    *buffer      = (MV_U32*)(&(fifoCtrl.fifoData[nextWriteIndex]));
+    *bufferIndex = nextWriteIndex;
+
+    return (MV_OK);
+  }
+
+   return(MV_FULL);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoMsgSend
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets the buffer (message) for transmission
+**
+**  PARAMETERS:  MV_U32 bufferIndex
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+static inline void  mvOnuGponMacFifoMsgSend(MV_U32 bufferIndex)
+{
+  fifoCtrl.fifoWriteIndex = bufferIndex;
+  fifoMacMsgAdd++;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoMsgRece
+**  ____________________________________________ ________________________________
+**
+**  DESCRIPTION: The function receives a message  from the FIFO
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     MV_U32 **buffer
+**               MV_U32 *bufferIndex
+**
+**  RETURNS:     MV_OK or MV_EMPTY
+**
+*******************************************************************************/
+static inline MV_STATUS mvOnuGponMacFifoMsgRece(MV_U32 **buffer,
+                                                MV_U32 *bufferIndex)
+{
+  MV_U32  nextReadIndex;
+
+  if (fifoCtrl.fifoReadIndex != fifoCtrl.fifoWriteIndex)
+  {
+    nextReadIndex = fifoCtrl.fifoReadIndex + 1;
+
+    /* roll over */
+    if (nextReadIndex >= GPON_SW_FIFO_SIZE)
+        nextReadIndex = 0;
+
+    *buffer      = (MV_U32*)(&(fifoCtrl.fifoData[nextReadIndex]));
+    *bufferIndex = nextReadIndex;
+
+    return(MV_OK);
+  }
+
+  return (MV_EMPTY);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoMsgFree
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns a buffer to the FIFO
+**
+**  PARAMETERS:  MV_U32 bufferIndex
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+static inline void  mvOnuGponMacFifoMsgFree(MV_U32 bufferIndex)
+{
+  fifoCtrl.fifoReadIndex = bufferIndex;
+  fifoMacMsgFree++;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoEmpty
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function returns an answer whether the FIFO is empty
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     1 - SW FIFO is empty
+**               0 - SW FIFO includes PLOAM messages
+**
+*******************************************************************************/
+static inline int mvOnuGponMacFifoEmpty(void)
+{
+  return(fifoCtrl.fifoReadIndex == fifoCtrl.fifoWriteIndex);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoGetInfo
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Debug function
+**
+**  PARAMETERS:
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void mvOnuGponMacFifoGetInfo(S_MacFifoCtrl **ptr, MV_32 *supported)
+{
+  *ptr = &fifoCtrl;
+  *supported = fifoSupported;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoGetStat
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Debug function
+**
+**  PARAMETERS:
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void mvOnuGponMacFifoGetStat(MV_32 *callCnt, MV_32 *addSwCnt, MV_32 *freeSwCnt, MV_32 *sendHwCnt)
+{
+  *callCnt   = fifoMacMsgSend;
+  *addSwCnt  = fifoMacMsgAdd;
+  *freeSwCnt = fifoMacMsgFree;
+  *sendHwCnt = fifoMacPloamSend;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoAuditGetStat
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Debug function
+**
+**  PARAMETERS:
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void mvOnuGponMacFifoAuditGetStat(MV_32 *enterCnt, MV_32 *actionCnt)
+{
+  *enterCnt  = fifoAuditEnter;
+  *actionCnt = fifoAuditAction;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoSupportSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Debug function
+**
+**  PARAMETERS:
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void mvOnuGponMacFifoSupportSet(MV_32 value)
+{
+  fifoSupported = value;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacFifoCountersSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Debug function
+**
+**  PARAMETERS:
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void mvOnuGponMacFifoCountersSet(MV_U32 value)
+{
+  fifoMacMsgSend   = value;
+  fifoMacMsgAdd    = value;
+  fifoMacMsgFree   = value;
+  fifoMacPloamSend = value;
+  fifoAuditEnter   = value;
+  fifoAuditAction  = value;
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponFifoAuditTimerExpireHndl
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function moves PLOAMs from SW to HW FIFO in case there is
+**               no new DS PLOAMs
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     None
+**
+*******************************************************************************/
+void mvOnuGponFifoAuditTimerExpireHndl(void)
+{
+  MV_STATUS rc;
+  MV_U32    hwFifoFreeEntries;
+  MV_32     i;
+  MV_U8     *buffer;
+  MV_U32    bufferIndex;
+
+  fifoAuditEnter++;
+
+  if (fifoAuditEnter <= 0)
+  {
+    fifoAuditEnter  = 0;
+    fifoAuditAction = 0;
+  }
+
+  /* Verify whether SW FIFO is empty */
+  if (mvOnuGponMacFifoEmpty())
+    return;
+
+  /* Verify whether HW FIFO has free place */
+  rc = mvOnuGponMacTxPloamDataFreeGet(&hwFifoFreeEntries);
+
+  if((rc != MV_OK) || (hwFifoFreeEntries < GPON_PLOAM_MSG_WORDS))
+    return;
+
+  /* Verify whether FIFO indexes have been changed from the last Audit cycle */
+  if ((fifoReadIdx  == fifoCtrl.fifoReadIndex) &&
+      (fifoWriteIdx == fifoCtrl.fifoWriteIndex))
+  {
+    fifoAuditAction++;
+
+    /* Lock GPON interrupt */
+    /*onuPonIrqLock(onuPonResourceTbl_s.onuPonIrqId);   */
+
+    for (i=0; i<GPON_MAX_US_MSG_TO_PROCESS; i++)
+    {
+        if (mvOnuGponMacFifoMsgRece((MV_U32**)&buffer, &bufferIndex) == MV_EMPTY)
+          break;
+
+        if (mvOnuGponMacTxPloamSend(buffer[0], buffer[1], &buffer[2]) != MV_OK)
+          break;
+
+        mvOnuGponMacFifoMsgFree(bufferIndex);
+    }
+
+    /* Unlock GPON interrupt */
+    /*onuPonIrqUnlock(onuPonResourceTbl_s.onuPonIrqId); */
+    fifoReadIdx = fifoCtrl.fifoReadIndex;
+  }
+  else
+  {
+    /* Save current values of the FIFO indexes */
+    fifoReadIdx  = fifoCtrl.fifoReadIndex;
+    fifoWriteIdx = fifoCtrl.fifoWriteIndex;
+  }
+}
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Low-Level MAC Section                              */
+/* ========================================================================== */
+/******************************************************************************/
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                            GENERAL Routines                                */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuGponMacAsicVersionGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the onu asic version
+**
+**  PARAMETERS:  MV_U32 *asicVer
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacAsicVersionGet(MV_U32 *asicVer)
+{
+  MV_STATUS rcode;
+  MV_U32    asicVerVal;
+
+  rcode = asicOntGlbRegRead (mvAsicReg_GPON_GEN_MAC_VERSION, &asicVerVal, 0);
+  if (rcode != MV_OK) return(rcode);
+  else *asicVer = asicVerVal;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacMicroSecCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return the onu micro sec counter
+**
+**  PARAMETERS:  MV_U32 *microSec
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacMicroSecCounterGet(MV_U32 *microSec)
+{
+  MV_STATUS rcode;
+  MV_U32    asicVerVal;
+
+  rcode = asicOntGlbRegRead (mvAsicReg_GPON_GEN_MICRO_SEC_CNT, &asicVerVal, 0);
+  if (rcode != MV_OK) return(rcode);
+  else *microSec = asicVerVal;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacDyingGaspConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function enables and sets GPIO and DeBouncer registers to allow
+**               Dying Gasp interrupt.
+**
+**  PARAMETERS:  id- Dying Gasp 0 or 1.
+**               disableEnable 0 Disable 1 Enable.
+**               threshold - The number of sampling values in the debouncer before an input is asserted.
+**                           1 = 6.4n sec.
+**               polarity - 1= active on high, 3 = active on low.
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacDyingGaspConfigSet(MV_U32 id,
+                                       MV_U32 disableEnable,
+                                       MV_U32 polarity,
+                                       MV_U32 threshold)
+{
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacXvrReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function execute xvr reset sequence
+**
+**  PARAMETERS:  MV_U32 xvrType
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacXvrReset(MV_U32 xvrType)
+{
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacXvrActivate
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function activates xvr
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacXvrActivate(void)
+{
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  mvOnuGponMacTxSwCountersAdd
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function updates Tx Ploam message counters
+**
+**  PARAMETERS:  MV_U8   msgId
+**               MV_BOOL sucsses
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxSwCountersAdd(MV_U8 msgId, MV_BOOL sucsses)
+{
+  mvOnuGponMacPloamCnt.txMsgTotalPloamCounter++;
+
+  if (sucsses == MV_FALSE) mvOnuGponMacPloamCnt.txErrMsgIdPloamCounter[msgId]++;
+  else                     mvOnuGponMacPloamCnt.txMsgIdPloamCounter[msgId]++;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  ponOnuMacTxSwCountersGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function updates Tx Ploam message counters
+**
+**  PARAMETERS:  MV_U8   msgId
+**               MV_BOOL sucsses
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS mvOnuGponMacTxSwCountersGet(void* txPloamPm)
+{
+  MV_U32 numOfMsgIdIndex;
+  S_MacTxPloamPm *outTxPloamPm = (S_MacTxPloamPm*)txPloamPm;
+
+  outTxPloamPm->txMsgTotalPloamCounter = mvOnuGponMacPloamCnt.txMsgTotalPloamCounter;
+
+  for (numOfMsgIdIndex = ONU_GPON_US_MSG_SN_ONU;
+       numOfMsgIdIndex <= ONU_GPON_US_MSG_ACK;
+       numOfMsgIdIndex++)
+  {
+    outTxPloamPm->txMsgIdPloamCounter[numOfMsgIdIndex]    = mvOnuGponMacPloamCnt.txMsgIdPloamCounter[numOfMsgIdIndex];
+    outTxPloamPm->txErrMsgIdPloamCounter[numOfMsgIdIndex] = mvOnuGponMacPloamCnt.txErrMsgIdPloamCounter[numOfMsgIdIndex];
+  }
+
+  return(MV_OK);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           =========   =========   =========   ===       ==           == */
+/* ==           =========   =========   =========   ====      ==           == */
+/* ==           ==          ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==          ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           =========   =========   ==     ==   ==   ==   ==           == */
+/* ==           =========   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==          ==          ==     ==   ==     == ==           == */
+/* ==           ==          ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                        Interrupt Functions Section                         */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPonInterruptGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return interrupt status
+**
+**  PARAMETERS:  MV_U32 *interrupt
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPonInterruptGet(MV_U32 *interrupt)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_INTR_REG, interrupt, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPonInterruptrMaskGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return interrupt mask
+**
+**  PARAMETERS:  MV_U32 *mask
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPonInterruptMaskGet(MV_U32 *mask)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_INTR_MASK, mask, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPonInterruptrMaskSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set interrupt mask
+**
+**  PARAMETERS:  MV_U32 mask
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPonInterruptMaskSet(MV_U32 mask)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_INTR_MASK, mask, 0);
+
+  return(status);
+}
+
+/* ========================================================================== */
+/*                        General Functions Section                           */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacVersionGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return mac version
+**
+**  PARAMETERS:  MV_U32 *version
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacVersionGet(MV_U32 *version)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GEN_MAC_VERSION_ADDR, version, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuEnableSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu Rx & Tx enable
+**
+**  PARAMETERS:  MV_U32 rxEnable
+**               MV_U32 txEnable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuEnableSet(MV_U32 rxEnable, MV_U32 txEnable)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_RX_ENABLE, rxEnable, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_TX_ENABLE, txEnable, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuRxEnableSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu Rx & Tx enable
+**
+**  PARAMETERS:  MV_U32 rxEnable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuRxEnableSet(MV_U32 rxEnable)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_RX_ENABLE, rxEnable, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuTxEnableSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu Rx & Tx enable
+**
+**  PARAMETERS:  MV_U32 txEnable
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuTxEnableSet(MV_U32 txEnable, MV_U32 macId)
+{
+  MV_STATUS status;
+  MV_U32    currOnuTxEnable;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_GEN_ONT_TX_ENABLE, &currOnuTxEnable, 0);
+
+  if (txEnable == 0) currOnuTxEnable &= ~(1 << macId);
+  else               currOnuTxEnable |=  (1 << macId);
+
+  status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_TX_ENABLE, currOnuTxEnable, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu state
+**
+**  PARAMETERS:  MV_U32 onuState
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuStateSet(MV_U32 onuState, MV_U32 macId)
+{
+  MV_STATUS status;
+  MV_U32    currOnuState;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_GEN_ONT_STATE_REG, &currOnuState, 0);
+
+  if (onuState == 0) currOnuState &= ~(1 << macId);
+  else               currOnuState |=  (1 << macId);
+
+  status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_STATE_REG, currOnuState, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu state
+**
+**  PARAMETERS:  MV_U32 *onuState
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuStateGet(MV_U32 *onuState, MV_U32 macId)
+{
+  MV_STATUS status;
+  MV_U32    currOnuState;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_GEN_ONT_STATE_REG, &currOnuState, 0);
+
+  *onuState = ((currOnuState >> macId) & (0x1));
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuRegAutoUpdateStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu register auto update params
+**
+**  PARAMETERS:  MV_U32 value
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuRegAutoUpdateStateSet(MV_U32 value)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_STATE_REG_AUTO_EN, value, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuReRegAutoUpdateStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu re-register auto update params
+**
+**  PARAMETERS:  MV_U32 value
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuReRegAutoUpdateStateSet(MV_U32 value)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_STATE_REREG_AUTO_EN, value, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuDeRegAutoUpdateStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu de-register auto update params
+**
+**  PARAMETERS:  MV_U32 value
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuDeRegAutoUpdateStateSet(MV_U32 value)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_STATE_DEREG_AUTO_EN, value, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacOnuNackAutoUpdateStateSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu nack auto update params
+**
+**  PARAMETERS:  MV_U32 value
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacOnuNackAutoUpdateStateSet(MV_U32 value)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_STATE_NACK_AUTO_EN, value, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenTqSizeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu TQ size
+**
+**  PARAMETERS:  MV_U32 tqRxSize
+**               MV_U32 tqTxSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenTqSizeSet(MV_U32 tqRxSize, MV_U32 tqTxSize)
+{
+  MV_STATUS status;
+  MV_U32    tqSize;
+
+  tqSize = ((tqTxSize & 0xF) << 4) |
+            (tqRxSize & 0xF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_TQ_SIZE, tqSize, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenLaserParamSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu laser params
+**
+**  PARAMETERS:  MV_U32 onOffTime
+**               MV_U32 onTime
+**               MV_U32 offTime
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenLaserParamSet(MV_U32 onOffTime, MV_U32 onTime, MV_U32 offTime)
+{
+  MV_STATUS status;
+  MV_U32    lazerTime;
+
+  lazerTime =  ((onOffTime & 0xFF) << 16) |
+                 ((offTime & 0xFF) << 8)  |
+                   (onTime & 0xFF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_LASER_PARAM, lazerTime, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenLaserParamGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return laser params
+**
+**  PARAMETERS:  MV_U32 *onOffTime
+**               MV_U32 *onTime
+**               MV_U32 *offTime
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenLaserParamGet(MV_U32 *onOffTime, MV_U32 *onTime, MV_U32 *offTime)
+{
+  MV_STATUS status;
+  MV_U32    lazerTime;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GEN_LASER_PARAM, &lazerTime, 0);
+
+  *onTime    =  (lazerTime        & 0xFF);
+  *offTime   = ((lazerTime >>  8) & 0xFF);
+  *onOffTime = ((lazerTime >> 16) & 0xFF);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenProcessingTimeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu processing time
+**
+**  PARAMETERS:  MV_U32 packetTailGuard
+**               MV_U32 tailGuard
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenTailGuardSet(MV_U32 packetTailGuard, MV_U32 tailGuard)
+{
+  MV_STATUS status;
+  MV_U32    guard;
+
+  guard =  ((packetTailGuard  & 0xFF) << 8)  |
+                  (tailGuard  & 0xFF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_TAIL_GUARD, guard, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenSyncTimeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu sync time
+**
+**  PARAMETERS:  MV_U32 syncTime
+**               MV_U32 addSyncTime
+**               MV_U32 forceSwUpdate
+**               MV_U32 disAutoUpdate
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenSyncTimeSet(MV_U32 syncTime,
+                                     MV_U32 addSyncTime,
+                                     MV_U32 forceSwUpdate,
+                                     MV_U32 disGateAutoUpdate,
+                                     MV_U32 disDiscoveryAutoUpdate)
+{
+  MV_STATUS status;
+  MV_U32    sync;
+
+  sync =         ((addSyncTime   & 0x00FF) << 24) |
+        ((disDiscoveryAutoUpdate & 0x0001) << 18) |
+             ((disGateAutoUpdate & 0x0001) << 17) |
+                ((forceSwUpdate  & 0x0001) << 16) |
+                      (syncTime  & 0xFFFF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_SYNC_TIME, sync, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenSyncTimeGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu sync time
+**
+**  PARAMETERS:  MV_U32 *syncTime
+**               MV_U32 *addSyncTime
+**               MV_U32 *forceSwUpdate
+**               MV_U32 *disAutoUpdate
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenSyncTimeGet(MV_U32 *syncTime,
+                                     MV_U32 *addSyncTime,
+                                     MV_U32 *forceSwUpdate,
+                                     MV_U32 *disGateAutoUpdate,
+                                     MV_U32 *disDiscoveryAutoUpdate)
+{
+  MV_STATUS status;
+  MV_U32    sync;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GEN_SYNC_TIME, &sync, 0);
+
+  *addSyncTime            = ((sync >> 24) & 0x00FF);
+  *disDiscoveryAutoUpdate = ((sync >> 18) & 0x0001);
+  *disGateAutoUpdate      = ((sync >> 17) & 0x0001);
+  *forceSwUpdate          = ((sync >> 16) & 0x0001);
+  *syncTime               = ((sync)       & 0xFFFF);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenBcastAddrSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu mac broadcast address
+**
+**  PARAMETERS:  MV_U32 bcastMacAddrHigh
+**               MV_U32 bcastMacAddrLow
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenBcastAddrSet(MV_U32 bcastMacAddrHigh, MV_U32 bcastMacAddrLow)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_BROADCAST_ADDR_LOW,  bcastMacAddrLow, 0);
+  status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_BROADCAST_ADDR_HIGH, bcastMacAddrHigh & 0xFFFF, 0);
+
+  return(status);
+}
+
+ /*******************************************************************************
+**
+**  mvOnuEponMacGenSyncTimeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu configuration
+**
+**  PARAMETERS:  MV_U32 rxFec
+**               MV_U32 txFec
+**               MV_U32 reportAutoResponse
+**               MV_U32 ackAutoResponse
+**               MV_U32 requestAutoResponse
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenOnuConfigSet(MV_U32 rxPcsFecEn,
+                                      MV_U32 txPcsFecEn,
+                                      MV_U32 reportAutoResponse,
+                                      MV_U32 ackAutoResponse,
+                                      MV_U32 requestAutoResponse,
+                                      MV_U32 txFecEn)
+{
+  MV_STATUS status;
+  MV_U32    config;
+
+  config =             ((txFecEn & 0x00FF) << 8) |
+           ((requestAutoResponse & 0x0001) << 6) |
+               ((ackAutoResponse & 0x0001) << 5) |
+            ((reportAutoResponse & 0x0001) << 4) |
+                    ((rxPcsFecEn & 0x0001) << 1) |
+                     (txPcsFecEn & 0x0001);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_CONFIGURATION, config, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenOnuConfigAutoReportSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu configuration auto report
+**
+**  PARAMETERS:  MV_U32 reportAutoResponse
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenOnuConfigAutoReportSet(MV_U32 reportAutoResponse)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_REPORT, reportAutoResponse, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenOnuConfigAutoAckSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu configuration auto ack
+**
+**  PARAMETERS:  MV_U32 ackAutoResponse
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenOnuConfigAutoAckSet(MV_U32 ackAutoResponse)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_ACK, ackAutoResponse, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenOnuConfigAutoRequestSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu configuration auto response
+**
+**  PARAMETERS:  MV_U32 requestAutoResponse
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenOnuConfigAutoRequestSet(MV_U32 requestAutoResponse)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_REQUEST, requestAutoResponse, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenSldSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SLD
+**
+**  PARAMETERS:  MV_U32 sld
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenSldSet(MV_U32 sld)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_SLD, sld, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenCtrlTypeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set control type (Ether type)
+**
+**  PARAMETERS:  MV_U32 sld
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenCtrlTypeSet(MV_U32 type)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_MAC_CONTROL_TYPE, type, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenLocalTimeStampSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu local timestamp
+**
+**  PARAMETERS:  MV_U32 timeStamp
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenLocalTimeStampSet(MV_U32 timeStamp)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_LOCAL_TIMESTAMP, timeStamp, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenLocalTimeStampGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu local timestamp
+**
+**  PARAMETERS:  MV_U32 *timeStamp
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenLocalTimeStampGet(MV_U32 *timeStamp)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_GEN_LOCAL_TIMESTAMP, timeStamp, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenPendGrantSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu pending grants
+**
+**  PARAMETERS:  MV_U32 grant
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenPendGrantSet(MV_U32 grant)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_NUM_OF_PENDING_GRANTS, grant, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenPendGrantSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu SGL status
+**
+**  PARAMETERS:  MV_U32 *status
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenSglStatusGet(MV_U32 *sglStatus)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_GEN_SGL_STATUS, sglStatus, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenPonPhyDbgSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu PON phy debug
+**
+**  PARAMETERS:  MV_U32 ponDebug
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenPonPhyDbgSet(MV_U32 ponDebug)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_PON_PHY_DEBUG, ponDebug, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenPonPhyDbgGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu PON phy debug
+**
+**  PARAMETERS:  MV_U32 *ponDebug
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenPonPhyDbgGet(MV_U32 *ponDebug)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_GEN_PON_PHY_DEBUG, ponDebug, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenSglSwReset
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return onu SGL sw reset
+**
+**  PARAMETERS:  MV_U32 swReset
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenSglSwReset(MV_U32 swReset)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_SGL_SW_RESET, swReset, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenSglConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SGL configuration
+**
+**  PARAMETERS:  startThreshold
+**               dataAlignment
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenSglConfig(MV_U32 startThreshold,
+                                   MV_U32 dataAlignment)
+{
+  MV_STATUS status;
+  MV_U32    config;
+
+  config = ((dataAlignment  & 0x0001) << 4) |
+            (startThreshold & 0x000F);
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_SGL_CONFIG, config, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenSglDebounceConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SGL Debounce configuration
+**
+**  PARAMETERS:  MV_U32 polarity
+**               MV_U32 threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenSglDebounceConfig(MV_U32 polarity,
+                                           MV_U32 threshold)
+{
+  MV_STATUS status;
+  MV_U32    config;
+
+  config = ((polarity  & 0x0001) << 16) |
+            (threshold & 0xFFFF);
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_SGL_DEBOUNCE_CONFIG, config, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenSglDebounceEnable
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu SGL Debounce enable
+**
+**  PARAMETERS:  MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenSglDebounceEnable(MV_U32 enable)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_SGL_DEBOUNCE_ENABLE, enable, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenChurningKeySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu churning key
+**
+**  PARAMETERS:  MV_U32 enable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenChurningKeySet(MV_U32 key)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_TCH_CHURNING_KEY, key, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenOpcodeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu additional opcode
+**
+**  PARAMETERS:  MV_U32 opcodeType
+**               MV_U32 value
+**               MV_U32 index
+**               MV_U32 timestamp
+**               MV_U32 valid
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenOpcodeSet(MV_U32 opcodeType,
+                                   MV_U32 value,
+                                   MV_U32 index,
+                                   MV_U32 timestamp,
+                                   MV_U32 valid)
+{
+  MV_STATUS status = MV_OK;
+  MV_U32    opcode;
+
+  opcode =     ((valid & 0x0001) << 20) |
+           ((timestamp & 0x0001) << 19) |
+               ((index & 0x0007) << 16) |
+                (value & 0xFFFF);
+
+  if      (opcodeType == ADDITIONAL_OPCODE_1)
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE1, opcode, 0);
+  else if (opcodeType == ADDITIONAL_OPCODE_2)
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE2, opcode, 0);
+  else if (opcodeType == ADDITIONAL_OPCODE_3)
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE3, opcode, 0);
+
+  return(status);
+}
+#ifdef PON_Z2
+/*******************************************************************************
+**
+**  mvOnuEponMacGenTimestampConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu timestamp configuration
+**
+**  PARAMETERS:  MV_U32 threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenTimestampConfig(MV_U32 gpmAddSyncTimeToTimestamp,
+                                         MV_U32 gpmAimestampOffset,
+                                         MV_U32 txmAddSyncTimeToTimestamp,
+                                         MV_U32 txmUseTimestampImage,
+                                         MV_U32 txmTimestampOffset)
+{
+  MV_STATUS status;
+  MV_U32    timestampConfig;
+
+  timestampConfig = ((gpmAddSyncTimeToTimestamp & 0x0001) << 31) |
+                           ((gpmAimestampOffset & 0x07FF) << 16) |
+                    ((txmAddSyncTimeToTimestamp & 0x0001) << 15) |
+                         ((txmUseTimestampImage & 0x0001) << 14) |
+                            (txmTimestampOffset & 0x07FF);
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_TIMESTAMP_CONFIG, timestampConfig, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenRxTimestampConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu RX timestamp configuration
+**
+**  PARAMETERS:
+**		MV_U32 rxpTimestampSelect	- 0 or 1
+**		MV_U32 rxpTimestampSign		- 0 or 1
+**		MV_U32 rxpTimestampOffset	- 0 to 0x7FF
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenRxTimestampConfigSet(MV_U32 rxpTimestampSelect,
+						MV_U32 rxpTimestampSign,
+						MV_U32 rxpTimestampOffset)
+{
+	MV_U32		timestampConfig;
+
+	timestampConfig = ((rxpTimestampSelect & 0x1) << 15) |
+			((rxpTimestampSign & 0x1) << 11) |
+			(rxpTimestampOffset & 0x07FF);
+
+	return(asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_RX_TIMESTAMP_CONFIG, timestampConfig, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenRxTimestampConfigGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function reads onu RX timestamp configuration
+**
+**  PARAMETERS:
+**		MV_U32 *rxpTimestampSelect	- 0 or 1
+**		MV_U32 *rxpTimestampSign	- 0 or 1
+**		MV_U32 *rxpTimestampOffset	- 0 to 0x7FF
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenRxTimestampConfigGet(MV_U32 *rxpTimestampSelect,
+											MV_U32 *rxpTimestampSign,
+											MV_U32 *rxpTimestampOffset)
+{
+	MV_STATUS	status;
+	MV_U32		timestampConfig;
+
+	if ((rxpTimestampSelect == 0) || (rxpTimestampSign == 0) || (rxpTimestampOffset == 0))
+		return(MV_BAD_PARAM);
+
+	status = asicOntGlbRegRead(mvAsicReg_EPON_GEN_ONT_RX_TIMESTAMP_CONFIG, &timestampConfig, 0);
+
+	if (status == MV_OK) {
+		*rxpTimestampSelect = (timestampConfig >> 15) & 0x1;
+		*rxpTimestampSign = (timestampConfig >> 11) & 0x1;
+		*rxpTimestampOffset = timestampConfig & 0x7FF;
+	}
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenRegPacketPaddingGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function gets onu packet padding
+**
+**  PARAMETERS:
+**		MV_U32 regAckPadding	- padding value for Ack (0 - 0xFF)
+**		MV_U32 regReqPadding	- padding value for Request (0 - 0xFF)
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenRegPacketPaddingGet(MV_U32 *regAckPadding, MV_U32 *regReqPadding)
+{
+	MV_STATUS	status;
+	MV_U32		paddingConfig;
+
+	if ((regAckPadding == 0) || (regReqPadding == 0))
+		return(MV_BAD_PARAM);
+
+	status = asicOntGlbRegRead(mvAsicReg_EPON_GEN_ONT_REGISTER_PACKET_PADDING, &paddingConfig, 0);
+
+	if (status == MV_OK) {
+		*regAckPadding = (paddingConfig >> 8) & 0xFF;
+		*regReqPadding = paddingConfig & 0xFF;
+	}
+
+	return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenRegPacketPaddingSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets onu packet padding
+**
+**  PARAMETERS:
+**		MV_U32 *regAckPadding	- padding value for Ack
+**		MV_U32 *regReqPadding	- padding value for Request
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenRegPacketPaddingSet(MV_U32 regAckPadding, MV_U32 regReqPadding)
+{
+	MV_U32		paddingConfig;
+
+	paddingConfig = ((regAckPadding & 0xFF) << 8) | (regReqPadding & 0xFF);
+
+	return(asicOntGlbRegWrite(mvAsicReg_EPON_GEN_ONT_REGISTER_PACKET_PADDING, paddingConfig, 0));
+}
+
+#endif /* PON_Z2 */
+/*******************************************************************************
+**
+**  mvOnuEponMacGenDriftThresholdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu drift threshold
+**
+**  PARAMETERS:  MV_U32 threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenDriftThresholdSet(MV_U32 threshold)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_DRIFT_THRESHOLD, threshold, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenTimeStampForIntrSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu timestamp for interrupt
+**
+**  PARAMETERS:  MV_U32 timestamp
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenTimeStampForIntrSet(MV_U32 timestamp)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_TIMESTAMP_VAL_FOR_INTR, timestamp, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenTimeStampForIntrGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get onu timestamp for interrupt
+**
+**  PARAMETERS:  MV_U32 *timestamp
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenTimeStampForIntrGet(MV_U32 *timestamp)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_GEN_TIMESTAMP_VAL_FOR_INTR, timestamp, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenUcastAddrSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu mac address
+**
+**  PARAMETERS:  MV_U32 ucastMacAddrHigh
+**               MV_U32 ucastMacAddrLow
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenUcastAddrSet(MV_U32 ucastMacAddrHigh, MV_U32 ucastMacAddrLow, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_MAC_ADDR_LOW,  ucastMacAddrLow, macId);
+  status |= asicOntGlbRegWrite(mvAsicReg_EPON_GEN_MAC_ADDR_HIGH, ucastMacAddrHigh & 0xFFFF, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenUtmTcPeriodSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu TC period
+**
+**  PARAMETERS:  MV_U32 tcPeriod
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenUtmTcPeriodSet(MV_U32 tcPeriod)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_UTM_TC_PERIOD, tcPeriod, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenUtmTcPeriodEnSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu TC period enable
+**
+**  PARAMETERS:  MV_U32 tcPeriodEnable
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenUtmTcPeriodEnSet(MV_U32 tcPeriodEnable)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_UTM_TC_PERIOD_VALID, tcPeriodEnable, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenGemIpgValueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu IPG value
+**
+**  PARAMETERS:  MV_U32 ipgVal
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenGemIpgValueSet(MV_U32 ipgVal)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_GEM_IPG_VAL, ipgVal, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGenGemIpgValueEnSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set onu IPG value enable
+**
+**  PARAMETERS:  MV_U32 ipgValEn
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGenGemIpgValueEnSet(MV_U32 ipgValEn)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegWrite(mvAsicReg_EPON_GEN_GEM_IPG_VAL_VALID, ipgValEn, 0);
+
+  return(status);
+}
+
+/* ========================================================================== */
+/*                        RXP Functions Section                               */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpPacketSizeLimitSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set packet min / mac size
+**
+**  PARAMETERS:  MV_U32 minSize
+**               MV_U32 maxSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpPacketSizeLimitSet(MV_U32 minSize,
+                                            MV_U32 maxSize)
+{
+  MV_STATUS status;
+  MV_U32    size;
+
+  size = ((maxSize & 0x0FFF) << 16) |
+          (minSize & 0x0FFF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_RXP_PACKET_SIZE_LIMIT, size, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpPacketSizeLimitGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return packet min / mac size
+**
+**  PARAMETERS:  MV_U32 *minSize
+**               MV_U32 *maxSize
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpPacketSizeLimitGet(MV_U32 *minSize,
+                                            MV_U32 *maxSize)
+{
+  MV_STATUS status;
+  MV_U32    size;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_RXP_PACKET_SIZE_LIMIT, &size, 0);
+
+  *minSize =  size        & 0x0FFF;
+  *maxSize = (size >> 16) & 0x0FFF;
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpPacketFilterSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set packet filtering
+**
+**  PARAMETERS:  MV_U32 ignoreLlidCrcError
+**               MV_U32 ignoreFcsError
+**               MV_U32 ignoreGmiiError
+**               MV_U32 ignoreLengthError
+**               MV_U32 forwardAllLlid
+**               MV_U32 forwardBc0FFF
+**               MV_U32 forwardBc1FFF
+**               MV_U32 forwardBc1xxx
+**               MV_U32 dropBc1nnn
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpPacketFilterSet(MV_U32 ignoreLlidCrcError,
+                                         MV_U32 ignoreFcsError,
+                                         MV_U32 ignoreGmiiError,
+                                         MV_U32 ignoreLengthError,
+                                         MV_U32 forwardAllLlid,
+                                         MV_U32 forwardBc0FFF,
+                                         MV_U32 forwardBc1FFF,
+                                         MV_U32 forwardBc1xxx,
+                                         MV_U32 dropBc1nnn)
+{
+  MV_STATUS status;
+  MV_U32    filter;
+
+  filter =        ((dropBc1nnn & 0x0001) << 8) |
+               ((forwardBc1xxx & 0x0001) << 7) |
+               ((forwardBc1FFF & 0x0001) << 6) |
+               ((forwardBc0FFF & 0x0001) << 5) |
+              ((forwardAllLlid & 0x0001) << 4) |
+           ((ignoreLengthError & 0x0001) << 3) |
+             ((ignoreGmiiError & 0x0001) << 2) |
+              ((ignoreFcsError & 0x0001) << 1) |
+           (ignoreLlidCrcError & 0x0001);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_RXP_PACKET_FILTER, filter, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpPacketFilterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return packet filtering
+**
+**  PARAMETERS:  MV_U32 *ignoreLlidCrcError
+**               MV_U32 *ignoreFcsError
+**               MV_U32 *ignoreGmiiError
+**               MV_U32 *ignoreLengthError
+**               MV_U32 *forwardAllLlid
+**               MV_U32 *forwardBc0FFF
+**               MV_U32 *forwardBc1FFF
+**               MV_U32 *forwardBc1xxx
+**               MV_U32 *dropBc1nnn
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpPacketFilterGet(MV_U32 *ignoreLlidCrcError,
+                                         MV_U32 *ignoreFcsError,
+                                         MV_U32 *ignoreGmiiError,
+                                         MV_U32 *ignoreLengthError,
+                                         MV_U32 *forwardAllLlid,
+                                         MV_U32 *forwardBc0FFF,
+                                         MV_U32 *forwardBc1FFF,
+                                         MV_U32 *forwardBc1xxx,
+                                         MV_U32 *dropBc1nnn)
+{
+  MV_STATUS status;
+  MV_U32    filter;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_RXP_PACKET_FILTER, &filter, 0);
+
+  *dropBc1nnn         = ((filter >> 8) & 0x0001);
+  *forwardBc1xxx      = ((filter >> 7) & 0x0001);
+  *forwardBc1FFF      = ((filter >> 6) & 0x0001);
+  *forwardBc0FFF      = ((filter >> 5) & 0x0001);
+  *forwardAllLlid     = ((filter >> 4) & 0x0001);
+  *ignoreLengthError  = ((filter >> 3) & 0x0001);
+  *ignoreGmiiError    = ((filter >> 2) & 0x0001);
+  *ignoreFcsError     = ((filter >> 1) & 0x0001);
+  *ignoreLlidCrcError = ( filter       & 0x0001);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpPacketForwardSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set packet forwarding
+**
+**  PARAMETERS:  MV_U32 ctrlFrameToDataQueue
+**               MV_U32 ctrlFrameToCtrlQueue
+**               MV_U32 rprtFrameToDataQueue
+**               MV_U32 rprtFrameToRprtQueue
+**               MV_U32 slowFrameToRprtQueue
+**               MV_U32 slowFrameToCtrlQueue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpPacketForwardSet(MV_U32 ctrlFrameToDataQueue,
+                                          MV_U32 ctrlFrameToCtrlQueue,
+                                          MV_U32 rprtFrameToDataQueue,
+                                          MV_U32 rprtFrameToRprtQueue,
+                                          MV_U32 slowFrameToRprtQueue,
+                                          MV_U32 slowFrameToCtrlQueue)
+{
+  MV_STATUS status;
+  MV_U32    forward;
+
+  forward = ((slowFrameToCtrlQueue & 0x0001) << 5) |
+            ((slowFrameToRprtQueue & 0x0001) << 4) |
+            ((rprtFrameToRprtQueue & 0x0001) << 3) |
+            ((rprtFrameToDataQueue & 0x0001) << 2) |
+            ((ctrlFrameToCtrlQueue & 0x0001) << 1) |
+             (ctrlFrameToDataQueue & 0x0001);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_RXP_CTRL_FRAME_FORWARD, forward, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpPacketForwardGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return packet forwarding
+**
+**  PARAMETERS:  MV_U32 *ctrlFrameToDataQueue
+**               MV_U32 *ctrlFrameToCtrlQueue
+**               MV_U32 *rprtFrameToDataQueue
+**               MV_U32 *rprtFrameToRprtQueue
+**               MV_U32 *slowFrameToRprtQueue
+**               MV_U32 *slowFrameToCtrlQueue
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpPacketForwardGet(MV_U32 *ctrlFrameToDataQueue,
+                                          MV_U32 *ctrlFrameToCtrlQueue,
+                                          MV_U32 *rprtFrameToDataQueue,
+                                          MV_U32 *rprtFrameToRprtQueue,
+                                          MV_U32 *slowFrameToRprtQueue,
+                                          MV_U32 *slowFrameToCtrlQueue)
+{
+  MV_STATUS status;
+  MV_U32    forward;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_RXP_CTRL_FRAME_FORWARD, &forward, 0);
+
+  *slowFrameToCtrlQueue = ((forward >> 5) & 0x0001);
+  *slowFrameToRprtQueue = ((forward >> 4) & 0x0001);
+  *rprtFrameToRprtQueue = ((forward >> 3) & 0x0001);
+  *rprtFrameToDataQueue = ((forward >> 2) & 0x0001);
+  *ctrlFrameToCtrlQueue = ((forward >> 1) & 0x0001);
+  *ctrlFrameToDataQueue = ( forward       & 0x0001);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpLlidDataSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set LLID Data entry
+**
+**  PARAMETERS:  MV_U32 llid
+**               MV_U32 index
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpLlidDataSet(MV_U32 llid, MV_U32 index)
+{
+  MV_STATUS status;
+
+  if (index >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_RXP_LLT_LLID_DATA, llid, index);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpLlidDataGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return LLID Data entry
+**
+**  PARAMETERS:  MV_U32 *llid
+**               MV_U32 index
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpLlidDataGet(MV_U32 *llid, MV_U32 index)
+{
+  MV_STATUS status;
+
+  if (index >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_RXP_LLT_LLID_DATA, llid, index);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpEncConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Encryption configuration
+**
+**  PARAMETERS:  MV_U32 config
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpEncConfigSet(MV_U32 config)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_RXP_ENCRYPTION_CONFIG, config, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpEncConfigGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Encryption configuration
+**
+**  PARAMETERS:  MV_U32 *config
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpEncConfigGet(MV_U32 *config)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_RXP_ENCRYPTION_CONFIG, config, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpEncKeySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Encryption key
+**
+**  PARAMETERS:  MV_U32 key
+**               MV_U32 index
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpEncKeySet(MV_U32 key, MV_U32 index, MV_U32 macId)
+{
+  MV_STATUS status = MV_OK;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  if (index == 0)
+  {
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_RXP_ENCRYPTION_KEY0, key, macId);
+  }
+  else if (index == 1)
+  {
+    status = asicOntGlbRegWrite(mvAsicReg_EPON_RXP_ENCRYPTION_KEY1, key, macId);
+  }
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpEncKeyGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set Encryption key
+**
+**  PARAMETERS:  MV_U32 *keyIndex0
+**               MV_U32 *keyIndex1
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpEncKeyGet(MV_U32 *keyIndex0, MV_U32 *keyIndex1, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_RXP_ENCRYPTION_KEY0, keyIndex0, macId);
+  status |= asicOntGlbRegRead(mvAsicReg_EPON_RXP_ENCRYPTION_KEY1, keyIndex1, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpDataFifoThresholdSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function sets Data FIFO Threshold
+**
+**  PARAMETERS:  MV_U32 threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpDataFifoThresholdSet(MV_U32 threshold)
+{
+	return(asicOntGlbRegWrite(mvAsicReg_EPON_RXP_DATA_FIFO_THRESH, threshold, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxpDataFifoThresholdGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function gets Data FIFO Threshold
+**
+**  PARAMETERS:  MV_U32 *threshold
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxpDataFifoThresholdGet(MV_U32 *threshold)
+{
+	return(asicOntGlbRegRead(mvAsicReg_EPON_RXP_DATA_FIFO_THRESH, threshold, 0));
+}
+
+
+/* ========================================================================== */
+/*                        GPM Functions Section                               */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmMacFutureGrantTimeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set future grants
+**
+**  PARAMETERS:  MV_U32 grant
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmMacFutureGrantTimeSet(MV_U32 grant)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GPM_MAX_FUTURE_GRANT_TIME, grant, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmMinProcessingTimeSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set min processing time
+**
+**  PARAMETERS:  MV_U32 processingTime
+**               MV_U32 effectiveLength
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmMinProcessingTimeSet(MV_U32 processingTime, MV_U32 effectiveLength)
+{
+  MV_STATUS status;
+  MV_U32    minProcTime;
+
+  minProcTime = ((effectiveLength & 0x00FF) << 16) |
+                 (processingTime  & 0xFFFF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GPM_MIN_PROCESSING_TIME, minProcTime, 0);
+
+  return(status);
+}
+#ifdef PON_Z2
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmDiscoveryGrantLengthSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set discovery grant length
+**
+**  PARAMETERS:  MV_U32 grantLength
+**               MV_U32 addOffsetForCalc
+**               MV_U32 grantLengthMultiTq
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmDiscoveryGrantLengthSet(MV_U32 grantLength,
+                                                 MV_U32 addOffsetForCalc,
+                                                 MV_U32 grantLengthMultiTq)
+{
+  MV_STATUS status;
+  MV_U32    discoveryGrantLength;
+
+  discoveryGrantLength = ((grantLengthMultiTq & 0x0FFF) << 16) |
+                           ((addOffsetForCalc & 0x000F) << 12) |
+                                (grantLength  & 0x0FFF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GPM_DISCOVERY_GRANT_LENGTH, discoveryGrantLength, 0);
+
+  return(status);
+}
+
+#endif /* PON_Z2 */
+#ifdef PON_Z1
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmDiscoveryGrantLengthSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set discovery grant length
+**
+**  PARAMETERS:  MV_U32 grantLength
+**               MV_U32 grantLengthMultiTq
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmDiscoveryGrantLengthSet(MV_U32 grantLength, MV_U32 grantLengthMultiTq)
+{
+  MV_STATUS status;
+  MV_U32    discoveryGrantLength;
+
+  discoveryGrantLength = ((grantLengthMultiTq & 0x0FFF) << 16) |
+                                (grantLength  & 0x0FFF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_GPM_DISCOVERY_GRANT_LENGTH, discoveryGrantLength, 0);
+
+  return(status);
+}
+#endif /* PON_Z1 */
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmRxSyncGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return Rx sync time
+**
+**  PARAMETERS:  MV_U32 *syncTime
+**               MV_U32 *syncTimeUpdateInd
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmRxSyncGet(MV_U32 *syncTime, MV_U32 *syncTimeUpdateInd)
+{
+  MV_STATUS status;
+  MV_U32    time;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_RX_SYNC_TIME, &time, 0);
+
+  *syncTimeUpdateInd = ((time >> 16) & 0x0001);
+  *syncTime          =  (time        & 0xFFFF);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmGrantValidCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmGrantValidCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_GRANT_VALID, counter, macId);
+
+  return(status);
+}
+
+/*****************************************************S**************************
+**
+**  mvOnuEponMacGpmGrantMaxFutureTimeErrorCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmGrantMaxFutureTimeErrorCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_GRANT_MAX_FUTURE_TIME_ERR, counter, macId);
+
+  return(status);
+}
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmMinProcTimeErrorCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmMinProcTimeErrorCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_MIN_PROC_TIME_ERR, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmLengthErrorCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmLengthErrorCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_LENGTH_ERR, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmDiscoveryAndRegisterCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmDiscoveryAndRegisterCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_DISCOVERY_AND_REGISTERED_ERR, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmFifoFullErrorCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmFifoFullErrorCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_FIFO_FULL_ERR, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmOpcDiscoveryNotRegisterBcastCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmOpcDiscoveryNotRegisterBcastCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_OPC_DISC_NOT_REG_BCAST, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmOpcRegisterNotDiscoveryCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmOpcRegisterNotDiscoveryCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_OPC_REG_NOT_DISC, counter, macId);
+
+  return(status);
+}
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmOpcDiscoveryNotRegisterNotBcastCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmOpcDiscoveryNotRegisterNotBcastCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_OPC_DISC_NOT_REG_NOT_BCAST, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmOpcDropGrantCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmOpcDropGrantCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_OPC_DROPED_GRANT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmOpcHiddenGrantCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmOpcHiddenGrantCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_OPC_HIDDEN_GRANT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacGpmOpcBackToBackCounterGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return GPM counters
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacGpmOpcBackToBackCounterGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_GPM_OPC_BACK_TO_BACK_GRANT, counter, macId);
+
+  return(status);
+}
+
+/* ========================================================================== */
+/*                        TXM Functions Section                               */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmOverheadSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX module overhead
+**
+**  PARAMETERS:  MV_U32 overhead
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmOverheadSet(MV_U32 overhead)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_DEFAULT_OVERHEAD, overhead, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmOverheadGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get TX module overhead
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     MV_U32 overhead
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmOverheadGet(MV_U32 *overhead)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_TXM_DEFAULT_OVERHEAD, overhead, 0);
+
+  return(status);
+}
+
+#ifdef PON_Z2
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX configuration
+**
+**  PARAMETERS:  MV_U32 mode
+**               MV_U32 alignment
+**               MV_U32 priority
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmConfigSet(MV_U32 tFec1Cfg, MV_U32 tFec2Cfg, MV_U32 ctrlFifoDisFcs,
+                                   MV_U32 maskGmiiSignal, MV_U32 blockDataFromDataPath,
+                                   MV_U32 addIpgToLenCalc, MV_U32 mode, MV_U32 alignment,
+                                   MV_U32 priority)
+{
+  MV_STATUS status;
+  MV_U32    config;
+
+  config =              ((tFec1Cfg & 0x0007) << 13) |
+                        ((tFec2Cfg & 0x0007) << 10) |
+                  ((ctrlFifoDisFcs & 0x0001) <<  8) |
+                  ((maskGmiiSignal & 0x0001) <<  7) |
+           ((blockDataFromDataPath & 0x0001) <<  6) |
+                 ((addIpgToLenCalc & 0x0001) <<  5) |
+                            ((mode & 0x0003) <<  3) |
+                       ((alignment & 0x0003) <<  1) |
+                         (priority & 0x0001);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CONFIGURATION, config, 0);
+
+  return(status);
+}
+#endif /* PON_Z2 */
+#ifdef PON_Z1
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX configuration
+**
+**  PARAMETERS:  MV_U32 mode
+**               MV_U32 alignment
+**               MV_U32 priority
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmConfigSet(MV_U32 mode, MV_U32 alignment, MV_U32 priority)
+{
+  MV_STATUS status;
+  MV_U32    config;
+
+  config =      ((mode & 0x0003) << 3) |
+           ((alignment & 0x0003) << 1) |
+             (priority & 0x0001);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CONFIGURATION, config, 0);
+
+  return(status);
+}
+#endif /* PON_Z1 */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmLlidSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX LLID
+**
+**  PARAMETERS:  MV_U32 llid
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmLlidSet(MV_U32 llid, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_TX_LLID, llid, macId);
+
+  return(status);
+}
+#ifdef PON_Z2
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX CPP Report configuration
+**
+**  PARAMETERS:  MV_U32 config
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportConfig(MV_U32 queueReportQ2, MV_U32 reportBitmapQ2,
+                                         MV_U32 queueReport, MV_U32 queueSet,
+                                         MV_U32 reportBitmap, MV_U32 macId)
+{
+  MV_STATUS status;
+  MV_U32    config;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  config = ((queueReportQ2 & 0x00FF) << 18) |
+          ((reportBitmapQ2 & 0x0001) << 16) |
+             ((queueReport & 0x00FF) << 2)  |
+                ((queueSet & 0x0003) << 1)  |
+             (reportBitmap & 0x0001);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_CONFIG, config, macId);
+
+  return(status);
+}
+#endif /* PON_Z2 */
+#ifdef PON_Z1
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX CPP Report configuration
+**
+**  PARAMETERS:  MV_U32 config
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportConfig(MV_U32 config, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_CONFIG, config, macId);
+
+  return(status);
+}
+#endif /* PON_Z1 */
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportBitMap
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX CPP Report Bit Map
+**
+**  PARAMETERS:  MV_U32 bitMap
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportBitMap(MV_U32 bitMap, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP, bitMap, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportBitMapGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX CPP Report Bit Map
+**
+**  PARAMETERS:  MV_U32 bitMap
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportBitMapGet(MV_U32 *bitMap, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP, bitMap, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueueSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX CPP Report Queue Set
+**
+**  PARAMETERS:  MV_U32 queueSet
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueueSet(MV_U32 queueSet, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET, queueSet, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueueSetGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue Set
+**
+**  PARAMETERS:  MV_U32 *queueSet
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueueSetGet(MV_U32 *queueSet, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET, queueSet, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueue0
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueue0(MV_U32 queue, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0, queue, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueue1
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueue1(MV_U32 queue, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1, queue, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueue2
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueue2(MV_U32 queue, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2, queue, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueue3
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueue3(MV_U32 queue, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3, queue, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueue4
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueue4(MV_U32 queue, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4, queue, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueue5
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueue5(MV_U32 queue, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5, queue, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueue6
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueue6(MV_U32 queue, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6, queue, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueue7
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueue7(MV_U32 queue, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7, queue, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportQueueX
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue 0 - 7
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportQueueX(MV_U32 queueNum, MV_U32 queueCfg, MV_U32 macId)
+{
+  MV_STATUS status = MV_OK;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  if      (queueNum == 0) {status |= mvOnuEponMacTxmCppReportQueue0(queueCfg, macId); }
+  else if (queueNum == 1) {status |= mvOnuEponMacTxmCppReportQueue1(queueCfg, macId); }
+  else if (queueNum == 2) {status |= mvOnuEponMacTxmCppReportQueue2(queueCfg, macId); }
+  else if (queueNum == 3) {status |= mvOnuEponMacTxmCppReportQueue3(queueCfg, macId); }
+  else if (queueNum == 4) {status |= mvOnuEponMacTxmCppReportQueue4(queueCfg, macId); }
+  else if (queueNum == 5) {status |= mvOnuEponMacTxmCppReportQueue5(queueCfg, macId); }
+  else if (queueNum == 6) {status |= mvOnuEponMacTxmCppReportQueue6(queueCfg, macId); }
+  else if (queueNum == 7) {status |= mvOnuEponMacTxmCppReportQueue7(queueCfg, macId); }
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportUpdate
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return TX CPP Report Queue
+**
+**  PARAMETERS:  MV_U32 queue
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportUpdate(MV_U32 validQueueReport, MV_U32 highestReportQueue, MV_U32 macId)
+{
+  MV_STATUS status;
+  MV_U32    queueNum;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return (MV_ERROR);
+
+  status  = mvOnuEponMacTxmCppReportConfig(0xFF,   /* Queueset2 not supported - set to 0xFF (queueReportQ2) */
+    					   0x1,    /* Queueset2 not supported - set to 0x1, Software (reportBitmapQ2) */
+    					   ~(validQueueReport & 0xFF),    /* Queueset1 supported - set to 0, means all 8 queues are active (queueReport) */
+    					   0x1,    /* Number of queueSet - support for 1 queueset */
+    					   0x1,    /* Queueset1 supported - set to 0x1, Software (reportBitmap) */
+    					   macId);
+  status |= mvOnuEponMacTxmCppReportBitMap(validQueueReport & 0xFF, macId); /* Queueset1 - 8 queues enabled(0xFF) , Queueset1 - 8 queues disabled(0x00) */
+  status |= mvOnuEponMacTxmCppReportQueueSet(0x1, macId);  /* Number of queuesets - support for 1 queueset */
+
+  for (queueNum = 0; queueNum < ONU_DBA_MAX_QUEUE; queueNum++)
+  {
+    if (validQueueReport & (1 << queueNum))
+    {
+      if (queueNum == highestReportQueue) {status |= mvOnuEponMacTxmCppReportQueueX(queueNum, 0x000053ff, macId); }
+      else                                {status |= mvOnuEponMacTxmCppReportQueueX(queueNum, 0x000003ff, macId); }
+    }
+    else
+    {
+      status |= mvOnuEponMacTxmCppReportQueueX(queueNum, 0x0, macId);
+    }
+  }
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxmCppReportFecConfig
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set TX CPP Report FEC config
+**
+**  PARAMETERS:  MV_U32 fecConst1
+**               MV_U32 fecConst2
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxmCppReportFecConfig(MV_U32 fecConst1, MV_U32 fecConst2)
+{
+  MV_STATUS status;
+  MV_U32    config;
+
+  config = ((fecConst2 & 0x00FF) << 16) |
+            (fecConst1 & 0xFFFF);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_TXM_CPP_RPRT_FEC_CONFIG, config, 0);
+
+  return(status);
+}
+
+/* ========================================================================== */
+/*                        PCS Functions Section                               */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPcsConfigSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set PCS configuration
+**
+**  PARAMETERS:  MV_U32 config
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPcsConfigSet(MV_U32 config)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_PCS_CONFIGURATION, config, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPcsConfigGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get PCS configuration
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     MV_U32 config
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPcsConfigGet(MV_U32 *config)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_PCS_CONFIGURATION, config, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPcsDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set PCS delay
+**
+**  PARAMETERS:  MV_U32 delay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPcsDelaySet(MV_U32 delay)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_PCS_DELAY_CONFIG, delay, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPcsStatsGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get PCS stats (0,1,2,3,4)
+**
+**  PARAMETERS:
+**		MV_U32 *legalFrameCnt,
+**		MV_U32 *maxFrameSizeErrCnt,
+**		MV_U32 *parityLenErrCnt,
+**		MV_U32 *longGateErrCnt,
+**		MV_U32 *protocolErrCnt,
+**		MV_U32 *minFrameSizeErrCnt,
+**		MV_U32 *legalFecFrameCnt,
+**		MV_U32 *legalNonFecFrameCnt
+**  OUTPUTS:
+**		Counter values assigned to input parameters
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPcsStatsGet(MV_U32 *legalFrameCnt,
+				MV_U32 *maxFrameSizeErrCnt,
+				MV_U32 *parityLenErrCnt,
+				MV_U32 *longGateErrCnt,
+				MV_U32 *protocolErrCnt,
+				MV_U32 *minFrameSizeErrCnt,
+				MV_U32 *legalFecFrameCnt,
+				MV_U32 *legalNonFecFrameCnt)
+{
+	MV_U32			regVal;
+  MV_STATUS status;
+
+	if ((legalFrameCnt == 0) || (maxFrameSizeErrCnt == 0) ||
+		(parityLenErrCnt == 0) || (longGateErrCnt == 0) ||
+		(protocolErrCnt == 0) || (minFrameSizeErrCnt == 0) ||
+		(legalFecFrameCnt == 0) || (legalNonFecFrameCnt == 0))
+		return(MV_BAD_PARAM);
+
+	status = asicOntGlbRegRead(mvAsicReg_EPON_PCS_STATS_0, &regVal, 0);
+	*legalFrameCnt = regVal;
+
+	status |= asicOntGlbRegRead(mvAsicReg_EPON_PCS_STATS_1, &regVal, 0);
+	*maxFrameSizeErrCnt = (regVal >> 16) & 0xFFFF;
+
+	status |= asicOntGlbRegRead(mvAsicReg_EPON_PCS_STATS_1, &regVal, 0);
+	*parityLenErrCnt = regVal & 0xFFFF;
+
+	status |= asicOntGlbRegRead(mvAsicReg_EPON_PCS_STATS_2, &regVal, 0);
+	*longGateErrCnt = (regVal >> 16) & 0xFFFF;
+
+	status |= asicOntGlbRegRead(mvAsicReg_EPON_PCS_STATS_2, &regVal, 0);
+	*protocolErrCnt = regVal & 0xFFFF;
+
+	status |= asicOntGlbRegRead(mvAsicReg_EPON_PCS_STATS_3, &regVal, 0);
+	*minFrameSizeErrCnt = regVal & 0xFFFF;
+
+	status |= asicOntGlbRegRead(mvAsicReg_EPON_PCS_STATS_4, &regVal, 0);
+	*legalFecFrameCnt = (regVal >> 16) & 0xFFFF;
+
+	status |= asicOntGlbRegRead(mvAsicReg_EPON_PCS_STATS_4, &regVal, 0);
+	*legalNonFecFrameCnt = regVal & 0xFFFF;
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPcsFrameSizeLimitsSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set PCS frame size  limits
+**
+**  PARAMETERS:  MV_U32 size      - maximum frame size
+**               MV_U32 latency   - FEC decoder latency
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPcsFrameSizeLimitsSet(MV_U32 size, MV_U32 latency)
+{
+	MV_U32    reg_val;
+
+	reg_val  = size & 0xFFF;
+	reg_val |= (latency & 0x1FFF) << 16;
+
+	return(asicOntGlbRegWrite(mvAsicReg_EPON_PCS_FRAME_SZ_LIMITS, reg_val, 0));
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacPcsFrameSizeLimitsGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function get PCS frime size limits
+**
+**  PARAMETERS:  None
+**
+**  OUTPUTS:     MV_U32 *size      - maximum framce size
+**               MV_U32 *latency   - FEC decoder latency
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacPcsFrameSizeLimitsGet(MV_U32 *size, MV_U32 *latency)
+{
+	MV_STATUS status;
+	MV_U32    reg_val;
+
+	status = asicOntGlbRegRead(mvAsicReg_EPON_PCS_FRAME_SZ_LIMITS, &reg_val, 0);
+	if (status == MV_OK) {
+		*size = reg_val & 0xFFF;
+		*latency = (reg_val >> 16) & 0x1FFF;
+	}
+
+	return(status);
+}
+
+/* ========================================================================== */
+/*                        DDM Functions Section                               */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacDdmDelaySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set DDM delay
+**
+**  PARAMETERS:  MV_U32 delay
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacDdmDelaySet(MV_U32 delay)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_DDM_DELAY_CONFIG, delay, 0);
+
+  return(status);
+}
+#ifdef PON_Z2
+/*******************************************************************************
+**
+**  mvOnuEponMacDdmTxPolaritySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set DDM polarity
+**
+**  PARAMETERS:  MV_U32 txEnable
+**               MV_U32 polarity
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacDdmTxPolaritySet(MV_U32 txEnable, MV_U32 polarity)
+{
+  MV_STATUS status;
+  MV_U32    config;
+
+  config = ((txEnable & 0x3) << 1)  |
+            (polarity & 0x1);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_DDM_TX_POLARITY, config, 0);
+
+  return(status);
+}
+#elif defined PON_Z1
+/*******************************************************************************
+**
+**  mvOnuEponMacDdmTxPolaritySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set DDM polarity
+**
+**  PARAMETERS:  MV_U32 polarity
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacDdmTxPolaritySet(MV_U32 polarity)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_DDM_TX_POLARITY, polarity, 0);
+
+  return(status);
+}
+#else
+/*******************************************************************************
+**
+**  mvOnuEponMacDdmTxPolaritySet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function set DDM polarity
+**
+**  PARAMETERS:  MV_U32 txEnable       - mask TX enabled with TX allowed
+**               MV_U32 txPolarity     - TX polarity (0 - active high)
+**               MV_U32 serdesPolarity - SERDES shutdown polarity (0 - active low)
+**               MV_U32 xvrPolarity    - XVR shutdown polarity (0 - active low)
+**               MV_U32 burstEnabl     - burst enable mode
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacDdmTxPolaritySet(MV_U32 txEnable,
+				       MV_U32 txPolarity,
+				       MV_U32 serdesPolarity,
+				       MV_U32 xvrPolarity,
+				       MV_U32 burstEnable)
+{
+	MV_U32    config;
+
+	config = ((burstEnable & 0x1)    << 5) |
+		 ((xvrPolarity & 0x1)    << 4) |
+		 ((serdesPolarity & 0x1) << 3) |
+		 ((txEnable & 0x3)       << 1) |
+		 (txPolarity & 0x1);
+
+	return(asicOntGlbRegWrite(mvAsicReg_EPON_DDM_TX_POLARITY, config, 0));
+}
+#endif
+
+/* ========================================================================== */
+/*                        Statistics Functions Section                        */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxStatsFcsErrorGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received with FCS error counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxStatsFcsErrorGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_RXP_FCS_ERROR_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxStatsShortErrorGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received short packets error counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxStatsShortErrorGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_RXP_SHORT_ERROR_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxStatsLongErrorGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received long packets error counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxStatsLongErrorGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_RXP_LONG_ERROR_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxStatsDataFrameGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received data frames counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxStatsDataFrameGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_RXP_DATA_FRAMES_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxStatsCtrlFrameGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received control frames counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxStatsCtrlFrameGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_RXP_CTRL_FRAMES_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxStatsReportFrameGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received report frames counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxStatsReportFrameGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_RXP_REPORT_FRAMES_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacRxStatsGateFrameGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return received gate frames counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacRxStatsGateFrameGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_RXP_GATE_FRAMES_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxStatsCtrlRegReqFrameGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return transmitted REGISTER REQUEST frames counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxStatsCtrlRegReqFrameGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_TXP_CTRL_REG_REQ_FRAMES_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxStatsCtrlRegAckFrameGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return transmitted REGISTER ACK frames counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxStatsCtrlRegAckFrameGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_TXP_CTRL_REG_ACK_FRAMES_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxStatsCtrlReportFrameGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return transmitted report frames counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxStatsCtrlReportFrameGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_TXP_CTRL_REPORT_FRAMES_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxStatsDataFrameGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return transmitted data frames counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxStatsDataFrameGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_TXP_DATA_FRAMES_CNT, counter, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacTxStatsTxAllowedByteCountGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return transmitted Tx Allowed byte counter
+**
+**  PARAMETERS:  MV_U32 *counter
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacTxStatsTxAllowedByteCountGet(MV_U32 *counter, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+	return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_STAT_TXP_TX_ALLOWED_BYTE_CNT, counter, macId);
+
+  return(status);
+}
+
+/* ========================================================================== */
+/*                        CPQ Functions Section                               */
+/* ========================================================================== */
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqRxCtrlHeaderQueueUsedCountGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return control header queue used count
+**
+**  PARAMETERS:  MV_U32 *usedCount
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqRxCtrlHeaderQueueUsedCountGet(MV_U32 *usedCount)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_CTRL_HQ_USED, usedCount, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqRxCtrlHeaderQueueReadData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return control header queue data
+**
+**  PARAMETERS:  MV_U32 *dataLow
+**               MV_U32 *dataHigh
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqRxCtrlHeaderQueueReadData(MV_U32 *dataLow, MV_U32 *dataHigh)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_L, dataLow, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_H, dataHigh, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqRxCtrlQueueUsedCountGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return control queue used count
+**
+**  PARAMETERS:  MV_U32 *usedCount
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqRxCtrlQueueUsedCountGet(MV_U32 *usedCount)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_CTRL_Q_USED, usedCount, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqRxCtrlQueueReadData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return control queue data
+**
+**  PARAMETERS:  MV_U32 *data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqRxCtrlQueueReadData(MV_U32 *data)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_CTRL_Q_READ, data, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqRxRprtHeaderQueueUsedCountGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return report header queue used count
+**
+**  PARAMETERS:  MV_U32 *usedCount
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqRxRprtHeaderQueueUsedCountGet(MV_U32 *usedCount)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_RPRT_HQ_USED, usedCount, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqRxRprtHeaderQueueReadData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return report header queue data
+**
+**  PARAMETERS:  MV_U32 *dataLow
+**               MV_U32 *dataHigh
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqRxRprtHeaderQueueReadData(MV_U32 *dataLow, MV_U32 *dataHigh)
+{
+  MV_STATUS status;
+
+  status  = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_L, dataLow, 0);
+  status |= asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_H, dataHigh, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqRxRprtQueueUsedCountGet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return report queue used count
+**
+**  PARAMETERS:  MV_U32 *usedCount
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqRxRprtQueueUsedCountGet(MV_U32 *usedCount)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_RPRT_Q_USED, usedCount, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqRxRprtQueueReadData
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return report queue data
+**
+**  PARAMETERS:  MV_U32 *data
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqRxRprtQueueReadData(MV_U32 *data)
+{
+  MV_STATUS status;
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_RX_RPRT_Q_READ, data, 0);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqTxCtrlHeaderQueueFree
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return control header queue free count
+**
+**  PARAMETERS:  MV_U32 *freeCount
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqTxCtrlHeaderQueueFree(MV_U32 *freeCount, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_TX_CTRL_HQ_FREE, freeCount, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqTxCtrlHeaderQueueWrite
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function write control header queue data
+**
+**  PARAMETERS:  MV_U32 data
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqTxCtrlHeaderQueueWrite(MV_U32 data, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_CPQ_TX_CTRL_HQ_WRITE, data, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqTxCtrlQueueFree
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function return control queue free count
+**
+**  PARAMETERS:  MV_U32 *freeCount
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqTxCtrlQueueFree(MV_U32 *freeCount, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegRead(mvAsicReg_EPON_CPQ_TX_CTRL_Q_FREE, freeCount, macId);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuEponMacCpqTxCtrlQueueWrite
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function write control queue data
+**
+**  PARAMETERS:  MV_U32 data
+**               MV_U32 macId
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or MV_ERROR
+**
+*******************************************************************************/
+MV_STATUS mvOnuEponMacCpqTxCtrlQueueWrite(MV_U32 data, MV_U32 macId)
+{
+  MV_STATUS status;
+
+  if (macId >= EPON_MAX_MAC_NUM)
+    return(MV_ERROR);
+
+  status = asicOntGlbRegWrite(mvAsicReg_EPON_CPQ_TX_CTRL_Q_WRITE, data, macId);
+
+  return(status);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           ==     ==   =========   =========   ==        ==           == */
+/* ==           ==     ==   =========   =========   ===       ==           == */
+/* ==           ==     ==   ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==     ==   ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           ==     ==   =========   ==     ==   ==   ==   ==           == */
+/* ==           ==     ==   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==     ==   ==          ==     ==   ==     == ==           == */
+/* ==           ==     ==   ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+#ifndef PON_FPGA
+/*******************************************************************************
+**
+**  mvOnuPonMacDgInterruptEn
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function configure Dying Gasp interrupt
+**
+**  PARAMETERS:  void
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuPonMacDgInterruptEn(MV_U32 dgPol)
+{
+  MV_STATUS status;
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_DG_CTRL_EN, 0x1, 0); /* Enable */
+  if (status != MV_OK)
+    return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_DG_CTRL_POLARITY, dgPol, 0); /* Active High/Low */
+  if (status != MV_OK)
+      return(status);
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_DG_THRESHOLD, 0x61A80, 0); /* Threshold */
+  if (status != MV_OK)
+      return(status);
+
+  return(status);
+}
+
+/*******************************************************************************
+**
+**  mvOnuPonMacDgInterruptDis
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: The function disable Dying Gasp interrupt
+**
+**  PARAMETERS:  void
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS mvOnuPonMacDgInterruptDis(void)
+{
+  MV_STATUS status;
+
+  status  = asicOntMiscRegWrite(mvAsicReg_PON_DG_CTRL_EN, 0x0, 0); /* Disable */
+  if (status != MV_OK)
+    return(status);
+
+  return(status);
+}
+#endif /* PON_FPGA */
diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.h b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.h
new file mode 100755
index 0000000..7c1f720
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuMac.h
@@ -0,0 +1,737 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _ONU_PON_MAC_H
+#define _ONU_PON_MAC_H
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           =========   =========   =========   ===       ==           == */
+/* ==           =========   =========   =========   ====      ==           == */
+/* ==           ==          ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==          ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           =========   =========   ==     ==   ==   ==   ==           == */
+/* ==           =========   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==     ==   ==          ==     ==   ==     == ==           == */
+/* ==           ==     ==   ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define UINT8_MASK		                    (0xFF)
+#define	UINT8_OFFSET	                    (8)
+#define UINT8_NUM_OF_BITS                   (8)
+
+/* Frame lengths */
+#define GPON_MAX_GEM_PAYLOAD_LEN            (0x800)             /* GEM payload length */
+#define GPON_MIN_ETH_FRAME_LEN              (0x40)              /* Min ETH frame length */
+#define GPON_MAX_ETH_FRAME_LEN              (0x800)             /* Max ETH frame length */
+#define GPON_MIN_OMCI_FRAME_LEN             (0x30)              /* Min OMCI frame length */
+#define GPON_MAX_OMCI_FRAME_LEN             (0x30)              /* Max OMCI frame length */
+
+/* Frame Delineation Register */
+#define GPON_FRAME_DELINEATION_FR_1244      (0x0000)            /* DS Frequency - 1.244Gb */
+#define GPON_FRAME_DELINEATION_FR_2488      (0x0001)            /* DS Frequency - 2.488Gb */
+#define GPON_FRAME_DELINEATION_FR           (GPON_FRAME_DELINEATION_FR_1244)
+#define GPON_FRAME_DELINEATION_M1           (0x0002)            /* M1 field */
+#define GPON_FRAME_DELINEATION_M2           (0x0005)            /* M2 field */
+
+/* ONU-ID Register */
+#define GPON_ONU_ID_ONU_ID_DEF              (ONU_GPON_UNDEFINED_ONU_ID) /* ONU-ID Field */
+
+/* ONU State Register */
+#define GPON_ONU_ID_STATE_01                (ONU_GPON_01_INIT)  /* ONU State 01 */
+
+/* ONU BIP period Counter Register */
+#define GPON_BIP_PERIOD_CNTR                (0) 				/* BIP period Counter */
+
+/* TX BW Translation Register */
+#define GPON_BW_MAP_IDLE_TCONT              (0)
+
+/* TX Delay Register - const */
+#define GPON_TX_DELAY_TD_622                (0x0AA1)            /* Const Delay */
+#define GPON_TX_DELAY_TD_1244               (0x1542)            /* Const Delay */
+
+/* TX Delay Register - equilization */
+#define GPON_TX_EQUAL_DELAY_TD              (0x0000)            /* Equilization Delay */
+
+/* TX Preamble Register */
+#define ONU_TX_PREAMBLE_TYPE_03_DEF_US_155  (0x0001)            /* Preamble type 3 counter - default US rate 155M */
+#define ONU_TX_PREAMBLE_TYPE_03_DEF_US_622  (0x0003)            /* Preamble type 3 counter - default US rate 622M */
+#define ONU_TX_PREAMBLE_TYPE_03_DEF_US_1244 (0x0005)            /* Preamble type 3 counter - default US rate 1244M */
+#define ONU_TX_PREAMBLE_TYPE_03_DEF_US_2488 (0x000D)            /* Preamble type 3 counter - default US rate 2488M */
+
+#define ONU_TX_PREAMBLE_TYPE_03_RATE_622    (0x0008)            /* Preamble type 3 counter - US rate 622M */
+#define ONU_TX_PREAMBLE_TYPE_03_RATE_1244   (0x0010)            /* Preamble type 3 counter - US rate 1244M */
+#define ONU_TX_PREAMBLE_TYPE_03_RATE_2488   (0x0020)            /* Preamble type 3 counter - US rate 2488M */
+
+#define ONU_TX_PREAMBLE_TYPE_01_P        	(0x00FF)            /* Preamble type 1 value */
+#define ONU_TX_PREAMBLE_TYPE_01_PC       	(0)    			 	/* Preamble type 1 counter */
+#define ONU_TX_PREAMBLE_TYPE_02_P       	(0x0000)            /* Preamble type 2 value */
+#define ONU_TX_PREAMBLE_TYPE_02_PC       	(0)    				/* Preamble type 2 counter */
+#define ONU_TX_PREAMBLE_TYPE_03_P        	(0x00AA)            /* Preamble type 3 value */
+#define ONU_TX_PREAMBLE_TYPE_03_DEF_PC      (ONU_TX_PREAMBLE_TYPE_03_DEF_US_622) /* Preamble type 3 counter - default */
+#define ONU_TX_PREAMBLE_TYPE_03_RT_PC       (ONU_TX_PREAMBLE_TYPE_03_RATE_622)   /* Preamble type 3 counter - runtime */
+
+/* TX Delimiter Register */
+#if 0
+#define GPON_TX_DELIMITER                   (0x02BEB433)
+#define GPON_TX_DELIMITER_D0                (0x0083)            /* Delimiter 0 */
+#define GPON_TX_DELIMITER_D1                (0x00B4)            /* Delimiter 1 */
+#define GPON_TX_DELIMITER_D2                (0x00BE)            /* Delimiter 2 */
+#define GPON_TX_DELIMITER_DS                (0x0002)            /* Delimiter size */
+#else
+#define GPON_TX_DELIMITER                   (0x02AB5983)
+#define GPON_TX_DELIMITER_D0                (0x0083)            /* Delimiter 0 */
+#define GPON_TX_DELIMITER_D1                (0x0059)            /* Delimiter 1 */
+#define GPON_TX_DELIMITER_D2                (0x00AB)            /* Delimiter 2 */
+#define GPON_TX_DELIMITER_DS                (0x0003)            /* Delimiter size */
+#endif
+
+/* TX Final Delay Register */
+#define GPON_TX_FINAL_DELAY_FD              (0x0020)            /* Final Delay */
+#define GPON_TX_FINAL_DELAY_MASK            (0x0007)
+#define GPON_TX_FINAL_DELAY_MAX             (0x003F)
+#define GPON_TX_FINAL_DELAY_MIN             (0x0000)
+#define GPON_TX_EQUAL_DELAY_MASK            (0x000FFFFF)
+#define GPON_TX_EQUAL_DELAY_SHIFT           (3)
+
+/* BURST enable parameter  */
+#define GPON_BURST_EN_P_ACT_HIGH            (0x0000)            /* BURST enable parameter - polarity active high */
+#define GPON_BURST_EN_P_ACT_LOW             (0x0001)            /* BURST enable parameter - polarity active low */
+
+#define GPON_BURST_EN_MASK                  (0x00C0)
+#define GPON_BURST_EN_P                     (GPON_BURST_EN_P_ACT_HIGH)
+#ifndef PON_FPGA
+#define GPON_BURST_EN_ORDER                 (1)
+#else
+#define GPON_BURST_EN_ORDER                 (0)
+#endif /* PON_FPGA */
+
+#ifndef PON_FPGA
+#define GPON_BURST_EN_START                 (0x0001)            /* BURST enable parameter - start */
+#define GPON_BURST_EN_STOP                  (0x0000)            /* BURST enable parameter - stop */
+#else /* PON_FPGA */
+#define GPON_BURST_EN_START                 (0x0006)            /* BURST enable parameter - start */
+#define GPON_BURST_EN_STOP                  (0x0006)            /* BURST enable parameter - stop */
+#endif /* PON_FPGA */
+#define GPON_BURST_THRESHOLD                (0x4E20)            /* 20000 bytes */
+
+#define MAC_LAST_UPSTREAM_PLOAM             (ONU_GPON_US_MSG_ACK)
+#define MAC_LAST_DOWNSTREAM_PLOAM           (ONU_GPON_DS_MSG_EXT_BURST_LEN)
+
+/* SW FIFO parameters */
+#define GPON_SW_FIFO_SIZE                   (1024)              /* Size of SW FIFO pool for PLOAM messages */
+#define GPON_PLOAM_MSG_WORDS                (3)                 /* PLOAM message length is 12 bytes or 3 words */
+#define GPON_PLOAM_MSG_BYTES                (12)                /* PLOAM message length is 12 bytes or 3 words */
+#define GPON_MAX_US_MSG_MOVING              (3)                 /* Max SW FIFO entries which can be moved from SW to HW FIFO by ISR */
+#define GPON_MAX_US_MSG_TO_PROCESS          (10)                /* Max SW FIFO entries which can be processed by FIFO Audit */
+
+/*AC coupling burst mode*/
+#define GPON_TX_AC_COUPL_BUST_MODE_0        (0)
+#define GPON_TX_AC_COUPL_BUST_MODE_1        (1)
+#define GPON_TX_AC_COUPL_PREACT_BURST_TIME  (0x0)
+#define GPON_TX_AC_COUPL_DATA_PATTERN_1     (0x0)
+#define GPON_TX_AC_COUPL_DATA_PATTERN_2     (0x0)
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+typedef MV_STATUS (*MACTXPLOAMCTRFUNC)(MV_U8 msgId, MV_BOOL status);
+typedef MV_STATUS (*MACRXPLOAMCTRFUNC)(MV_U8 msgId);
+
+typedef struct
+{
+  MV_U32 txErrMsgIdPloamCounter [ONU_GPON_US_MSG_LAST+1];
+  MV_U32 txMsgIdPloamCounter    [ONU_GPON_US_MSG_LAST+1];
+  MV_U32 txMsgTotalPloamCounter;
+}S_MacTxPloamPm;
+
+typedef struct
+{
+  MV_U32  msg[GPON_PLOAM_MSG_WORDS];
+}S_MacPloamMsg;
+
+typedef struct
+{
+  MV_U32        fifoWriteIndex;
+  MV_U32        fifoReadIndex;
+  MV_U32        fifoReparoundNum;
+  S_MacPloamMsg fifoData[GPON_SW_FIFO_SIZE];
+}S_MacFifoCtrl;
+
+/* Macros
+------------------------------------------------------------------------------*/
+#define M_ONU_GPON_RANG_MSG_FINAL_DELAY(eqD) (eqD & GPON_TX_FINAL_DELAY_MASK)
+#define M_ONU_GPON_RANG_MSG_EQUAL_DELAY(eqD) ((eqD >> GPON_TX_EQUAL_DELAY_SHIFT) & GPON_TX_EQUAL_DELAY_MASK)
+
+#define M_ONU_GPON_BASE_ADDRESS(address) ((address != NULL) ? (address) : (0))
+
+/* Global functions
+------------------------------------------------------------------------------*/
+/******************************************************************************/
+/* ========================================================================== */
+/*                         High-Level MAC Section                             */
+/* ========================================================================== */
+/******************************************************************************/
+MV_STATUS mvOnuGponMacMessageReceive(MV_U8 *msgOnuId, MV_U8 *msgId, MV_U8 *msgData);
+MV_STATUS mvOnuGponMacMessageSend(MV_U8 msgOnuId, MV_U8 msgId, MV_U8 *msgData);
+MV_STATUS mvOnuGponMacMessageCleanSwFifo(void);
+MV_STATUS mvOnuGponMacPreambleSet(MV_U32 preamType1Val, MV_U32 preamType1Cnt,
+                                  MV_U32 preamType2Val, MV_U32 preamType2Cnt,
+                                  MV_U32 preamType3Val, MV_U32 preamType3Cnt);
+MV_STATUS mvOnuGponMacPreambleType3Set(MV_U32 preamType3Val, MV_U32 preamType3Cnt);
+
+/* Upstream Messages send routines */
+MV_STATUS mvOnuGponMacPasswordMessageSend(MV_U8 onuId, MV_U8 *password, MV_U32 counter);
+MV_STATUS mvOnuGponMacReiMessageSend(MV_U8 onuId, MV_U32 errorsCounter);
+MV_STATUS mvOnuGponMacAcknowledgeMessageSend(MV_U8 onuId, MV_U8 dmId, MV_U8 *dmByte);
+MV_STATUS mvOnuGponMacEncryptionKeyMessageSend(MV_U8 onuId, MV_U8 KeyIndex, MV_U8 fragIndex, MV_U8 *key);
+#ifndef PON_FPGA
+MV_STATUS mvOnuGponMacDgMessageSend(MV_U8 onuId);
+#endif /* PON_FPGA */
+
+/******************************************************************************/
+/* ========================================================================== */
+/*                         Low-Level MAC Section                              */
+/* ========================================================================== */
+/******************************************************************************/
+
+/* ========================================================================== */
+/*                        Rx Functions Section                                */
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacRxConfigSet(MV_BOOL enable);
+MV_STATUS mvOnuGponMacRxConfigBitOrderSet(MV_U32 value);
+MV_STATUS mvOnuGponMacRxPsaConfigSet(MV_U32 syncFsmM1, MV_U32 syncFsmM2, MV_U32 syncFsmM3, MV_U32 fecHyst);
+MV_STATUS mvOnuGponMacRxFecConfigSet(MV_BOOL swIndication, MV_BOOL forceSw, MV_BOOL ignoreParity);
+MV_STATUS mvOnuGponMacRxFecStatusGet(MV_U32 *fecStatus);
+MV_STATUS mvOnuGponMacRxPloamDataGet(MV_U32  *ploamData);
+MV_STATUS mvOnuGponMacRxPloamDataUsedGet(MV_U32 *ploamFifoSize);
+MV_STATUS mvOnuGponMacRxPlenConfigSet(MV_BOOL forceNum, MV_BOOL useForce, MV_BOOL ignDiff, MV_BOOL notFix, MV_BOOL ignCrc);
+MV_STATUS mvOnuGponMacRxPloamConfigSet(MV_BOOL ignCrc, MV_BOOL ignBrd, MV_BOOL fwdAll);
+MV_STATUS mvOnuGponMacRxBwMapConfigSet(MV_U32 minSaDelta, MV_BOOL notCrcFix, MV_BOOL ignCrc);
+MV_STATUS mvOnuGponMacRxBwMapSet(MV_U32 entry, MV_U32 allocId, MV_U32 tcontCnt, MV_BOOL enable);
+MV_STATUS mvOnuGponMacRxBwMapGet(MV_U32 entry, MV_U32 *allocId, MV_BOOL *enable, MV_U32 *tcontCnt);
+MV_STATUS mvOnuGponMacRxEqualizationDelaySet(MV_U32 delay);
+MV_STATUS mvOnuGponMacRxEqualizationDelayGet(MV_U32 *delay);
+MV_STATUS mvOnuGponMacRxInternalDelaySet(MV_U32 delay);
+MV_STATUS mvOnuGponMacRxInternalDelayGet(MV_U32 *delay);
+MV_STATUS mvOnuGponMacRxSuperFrameCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacRxSuperFrameCounterSet(MV_U32 counter);
+
+/* ========================================================================== */
+/*                        Tx Functions Section                                */
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacTxDelimiterSet(MV_U32 delimiterPattern, MV_U32 delimiterSize);
+MV_STATUS mvOnuGponMacTxDelimiterGet(MV_U32 *pattern, MV_U32 *size);
+MV_STATUS mvOnuGponMacTxPloamDataFifoSet(MV_U32 txPloamData);
+MV_STATUS mvOnuGponMacTxPloamDataFreeGet(MV_U32 *ploamFifoSize);
+MV_STATUS mvOnuGponMacTxBurstEnParamSet(MV_U32 mask, MV_U32 polarity, MV_U32 delay, MV_U32 enStop, MV_U32 enStart);
+MV_STATUS mvOnuGponMacTxBurstEnPolaritySet(MV_U32 polarity);
+MV_STATUS mvOnuGponMacTxBurstEnParamGet(MV_U32 *mask, MV_U32 *polarity, MV_U32 *order, MV_U32 *enStop, MV_U32 *enStart);
+MV_STATUS mvOnuGponMacTxFinalDelaySet(MV_U32 txFinalDelay);
+MV_STATUS mvOnuGponMacTxFinalDelayGet(MV_U32 *txFinalDelay);
+MV_STATUS mvOnuGponMacTxPreambleSet(MV_U32 type, MV_U32 pattern, MV_U32 size);
+MV_STATUS mvOnuGponMacTxPlsSet(MV_U32 pattern);
+MV_STATUS mvOnuGponMacTxConstIdleMsgSet(MV_U32 onuId);
+MV_STATUS mvOnuGponMacTxConstSerialNumberMsgSet(MV_U32 onuId, MV_U8 *serialNumber, MV_U32 randomDelay);
+MV_STATUS mvOnuGponMacTxDbrBlockSizeSet(MV_U32 blockSize);
+MV_STATUS mvOnuGponMacTxSwCountersAdd(MV_U8 msgId ,MV_BOOL sucsses);
+MV_STATUS mvOnuGponMacTxSwCountersGet(void *txPloamPm);
+/* ========================================================================== */
+/*                        General Functions Section                           */
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacVersionGet(MV_U32 *version);
+MV_STATUS mvOnuGponMacOnuIdSet(MV_U32 onuId, MV_BOOL valid);
+MV_STATUS mvOnuGponMacOnuStateSet(MV_U32 onuState);
+MV_STATUS mvOnuGponMacSerialNumberSet(MV_U32 serialNum);
+/* ========================================================================== */
+/*                        Gem Functions Section                               */
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacGemPayloadLenSet(MV_U32 payloadlen);
+MV_STATUS mvOnuGponMacGemPayloadLenGet(MV_U32 *payloadlen);
+MV_STATUS mvOnuGponMacGemEthFrameLenSet(MV_U32 maxFrameLen, MV_U32 minFrameLen);
+MV_STATUS mvOnuGponMacGemEthFrameLenGet(MV_U32 *maxFrameLen, MV_U32 *minFrameLen);
+MV_STATUS mvOnuGponMacGemOmciFrameLenSet(MV_U32 maxFrameLen, MV_U32 minFrameLen);
+MV_STATUS mvOnuGponMacGemOmciFrameLenGet(MV_U32 *maxFrameLen, MV_U32 *minFrameLen);
+MV_STATUS mvOnuGponMacGemOmciPortIdSet(MV_U32 portId, MV_U32 valid);
+MV_STATUS mvOnuGponMacGemOmciPortIdGet(MV_U32 *portId, MV_U32 *valid);
+/* ========================================================================== */
+/*                        UTM Functions Section                               */
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacUtmOmciPortIdSet(MV_U32 portId, MV_U32 valid);
+MV_STATUS mvOnuGponMacUtmOmciPortIdGet(MV_U32 *portId, MV_U32 *valid);
+MV_STATUS mvOnuGponMacUtmTcPeriodSet(MV_U32 period );
+MV_STATUS mvOnuGponMacUtmTcValidSet(MV_U32 valid);
+MV_STATUS mvOnuGponMacUtmTcConfigGet(MV_U32 *period, MV_U32 *valid);
+/* ========================================================================== */
+/*                        Interrupt Functions Section                         */
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacPonInterruptGet(MV_U32 *interrupt);
+MV_STATUS mvOnuGponMacPonInterruptMaskGet(MV_U32 *mask);
+MV_STATUS mvOnuGponMacPonInterruptMaskSet(MV_U32 mask);
+MV_STATUS mvOnuGponMacBipStatusValueGet(MV_U32 *value);
+MV_STATUS mvOnuGponMacBipInterruptIntervalSet(MV_U32 interval);
+MV_STATUS mvOnuGponMacBipInterruptStatusValueGet(MV_U32 *value);
+MV_STATUS mvOnuGponMacRamTestCfgSet(MV_U32 config);
+MV_STATUS mvOnuGponMacRamTestCfgGet(MV_U32 *config);
+/* ========================================================================== */
+/*                        Statistics Functions Section                        */
+/* ========================================================================== */
+/* Gem */
+/* === */
+MV_STATUS mvOnuGponMacGemRcvdIdleGemFramesCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdValidGemFramesCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdUndefGemFramesCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdOmciFramesCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemDropGemFramesCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemDropOmciFramesCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdGemFramesWithUncorrHecErrCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdGemFramesWithOneFixedHecErrCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdGemFramesWithTwoFixedHecErrCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdValidGemFramesTotalByteCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdUndefGemFramesTotalByteCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemReassembleMemoryFlushCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemSynchLostCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdEthFramesWithCorrFcsCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdEthFramesWithFcsErrCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdOmciFramesWithCorrCrcCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacGemRcvdOmciFramesWithCrcErrCounterGet(MV_U32 *counter);
+/* Rx Ploam */
+/* ======== */
+MV_STATUS mvOnuGponMacRxPloamLostCrcCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacRxPloamLostFullCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacRxPloamRcvdIdleCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacRxPloamRcvdBroadCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacRxPloamRcvdOnuIdCounterGet(MV_U32 *counter);
+/* Tx */
+/* == */
+MV_STATUS mvOnuGponMacTxGemPtiTypeOneFrameCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacTxGemPtiTypeZeroFrameCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacTxIdleGemFramesCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacTxTxEnableCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacTxTxEnableCounterThresholdGet(MV_U32 *threshold);
+MV_STATUS mvOnuGponMacTxTxEnableCounterThresholdSet(MV_U32 threshold);
+MV_STATUS mvOnuGponMacTxGseTransCounterThresholdGet(MV_U32 *threshold);
+MV_STATUS mvOnuGponMacTxGseTransCounterThresholdSet(MV_U32 threshold);
+MV_STATUS mvOnuGponMacTxConfigAcCouplingGet(MV_U32 *busrtMode,
+					    MV_U32 *preActiveBurstTime,
+					    MV_U8  *dataPattern1,
+					    MV_U8  *dataPattern2);
+MV_STATUS mvOnuGponMacTxConfigAcCouplingSet(MV_U32 busrtMode,
+					    MV_U32 preActiveBurstTime,
+					    MV_U8  dataPattern1,
+					    MV_U8  dataPattern2);
+MV_STATUS mvOnuGponMacTxEthFramesTcontiCounterGet(MV_U32 tcontNum, MV_U32 *counter);
+MV_STATUS mvOnuGponMacTxEthBytesTcontiCounterGet(MV_U32 tcontNum, MV_U32 *counter);
+MV_STATUS mvOnuGponMacTxGemFramesTcontiCounterGet(MV_U32 tcontNum, MV_U32 *counter);
+MV_STATUS mvOnuGponMacTxIdleGemFramesTcontiCounterGet(MV_U32 tcontNum, MV_U32 *counter);
+/* FEC */
+/* === */
+MV_STATUS mvOnuGponMacRxFecBytesCounterGet(MV_U32 *counter);
+MV_STATUS mvOnuGponMacRxFecCorrectCounterGet(MV_U32 *bytes, MV_U32 *bits);
+MV_STATUS mvOnuGponMacRxFecInorrectCounterGet(MV_U32 *bytes, MV_U32 *bits);
+/* Bw Map */
+/* ====== */
+MV_STATUS mvOnuGponMacRxBwMapAllocatrionsCounterGet(MV_U32 *cor, MV_U32 *incor, MV_U32 *crcCor, MV_U32 *errCrc);
+MV_STATUS mvOnuGponMacRxBwMapTotalBwGet(MV_U32 *bw);
+/* Plend */
+/* ===== */
+MV_STATUS mvOnuGponMacInComingPlendCntGet(MV_U32 *cntValue);
+
+/* ========================================================================== */
+/*                        AES                                                 */
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacAesInit(void);
+MV_STATUS mvOnuGponMacAesEnableSet(MV_BOOL enable);
+MV_STATUS mvOnuGponMacAesPortIdSet(MV_U32 portId, MV_BOOL status);
+MV_BOOL   mvOnuGponMacAesPortIdGet(MV_U32 portId);
+MV_STATUS mvOnuGponMacAesKeyShadowWrite(MV_U8 *key);
+
+/* ========================================================================== */
+/*                        GEM Port                                            */
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacIpgValueSet(MV_U32 ipgVal);
+MV_STATUS mvOnuGponMacIpgValueGet(MV_U32 *ipgVal);
+MV_STATUS mvOnuGponMacIpgValidSet(MV_BOOL enable);
+MV_STATUS mvOnuGponMacIpgValidGet(MV_BOOL *enable);
+/* ========================================================================== */
+MV_STATUS mvOnuGponMacGemInit(void);
+MV_STATUS mvOnuGponMacPortIdValidSet(MV_U32 portId, MV_BOOL status);
+MV_BOOL   mvOnuGponMacPortIdValidGet(MV_U32 portId);
+
+MV_STATUS mvOnuGponMacXvrReset(MV_U32 xvrType);
+MV_STATUS mvOnuGponMacXvrActivate(void);
+MV_STATUS mvOnuGponMacAsicVersionGet(MV_U32 *asicVer);
+MV_STATUS mvOnuGponMacMicroSecCounterGet(MV_U32 *microSec);
+MV_STATUS mvOnuGponMacDyingGaspConfigSet(MV_U32 a_id,MV_U32 a_disableEnable,MV_U32 a_polarity, MV_U32 a_threshold);
+
+/* ========================================================================== */
+/*                        SW FIFO                                             */
+/* ========================================================================== */
+void      mvOnuGponMacFifoInit(void);
+void      mvOnuGponFifoAuditTimerExpireHndl(void);
+void      mvOnuGponMacFifoGetInfo(S_MacFifoCtrl **ptr, MV_32 *supported);
+void      mvOnuGponMacFifoGetStat(MV_32 *callCnt, MV_32 *addSwCnt, MV_32 *freeSwCnt, MV_32 *sendHwCnt);
+void      mvOnuGponMacFifoAuditGetStat(MV_32 *enterCnt, MV_32 *actionCnt);
+void      mvOnuGponMacFifoCountersSet(MV_U32 value);
+void      mvOnuGponMacFifoSupportSet(MV_32 value);
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           =========   =========   =========   ==        ==           == */
+/* ==           =========   =========   =========   ===       ==           == */
+/* ==           ==          ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==          ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           =========   =========   ==     ==   ==   ==   ==           == */
+/* ==           =========   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==          ==          ==     ==   ==     == ==           == */
+/* ==           ==          ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define ADDITIONAL_OPCODE_1                 (1)
+#define	ADDITIONAL_OPCODE_2                 (2)
+#define ADDITIONAL_OPCODE_3                 (3)
+
+/*EPON TX MUX POWER UP*/
+#define EPON_DDM_TX_EN_MASK_DEFAULT          (0)
+#define EPON_DDM_TX_TX_POL_DEFAULT           (0)
+#define EPON_DDM_TX_SERDES_POL_DEFAULT       (0)
+#define EPON_DDM_TX_XVR_POL_DEFAULT          (0)
+#define EPON_DDM_TX_BURST_ENA_DEFAULT        (0)
+
+/* Global functions
+------------------------------------------------------------------------------*/
+
+/* ========================================================================== */
+/*                        Interrupt Functions Section                         */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacPonInterruptGet(MV_U32 *interrupt);
+MV_STATUS mvOnuEponMacPonInterruptMaskGet(MV_U32 *mask);
+MV_STATUS mvOnuEponMacPonInterruptMaskSet(MV_U32 mask);
+
+/* ========================================================================== */
+/*                        General Functions Section                           */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacVersionGet(MV_U32 *version);
+MV_STATUS mvOnuEponMacOnuEnableSet(MV_U32 rxEnable, MV_U32 txEnable);
+MV_STATUS mvOnuEponMacOnuRxEnableSet(MV_U32 rxEnable);
+MV_STATUS mvOnuEponMacOnuTxEnableSet(MV_U32 txEnable, MV_U32 macId);
+MV_STATUS mvOnuEponMacOnuStateSet(MV_U32 onuState, MV_U32 macId);
+MV_STATUS mvOnuEponMacOnuStateGet(MV_U32 *onuState, MV_U32 macId);
+MV_STATUS mvOnuEponMacOnuRegAutoUpdateStateSet(MV_U32 value);
+MV_STATUS mvOnuEponMacOnuReRegAutoUpdateStateSet(MV_U32 value);
+MV_STATUS mvOnuEponMacOnuDeRegAutoUpdateStateSet(MV_U32 value);
+MV_STATUS mvOnuEponMacOnuNackAutoUpdateStateSet(MV_U32 value);
+MV_STATUS mvOnuEponMacGenTqSizeSet(MV_U32 tqRxSize, MV_U32 tqTxSize);
+MV_STATUS mvOnuEponMacGenTqSizeGet(MV_U32 *tqRxSize, MV_U32 *tqTxSize);
+MV_STATUS mvOnuEponMacGenLaserParamSet(MV_U32 onOffTime, MV_U32 onTime, MV_U32 offTime);
+MV_STATUS mvOnuEponMacGenLaserParamGet(MV_U32 *onOffTime, MV_U32 *onTime, MV_U32 *offTime);
+MV_STATUS mvOnuEponMacGenTailGuardSet(MV_U32 packetTailGuard, MV_U32 tailGuard);
+MV_STATUS mvOnuEponMacGenSyncTimeSet(MV_U32 syncTime, MV_U32 addSyncTime, MV_U32 forceSwUpdate,
+                                     MV_U32 disGateAutoUpdate, MV_U32 disDiscoveryAutoUpdate);
+MV_STATUS mvOnuEponMacGenSyncTimeGet(MV_U32 *syncTime, MV_U32 *addSyncTime, MV_U32 *forceSwUpdate,
+                                     MV_U32 *disGateAutoUpdate, MV_U32 *disDiscoveryAutoUpdate);
+MV_STATUS mvOnuEponMacGenBcastAddrSet(MV_U32 bcastMacAddrHigh, MV_U32 bcastMacAddrLow);
+MV_STATUS mvOnuEponMacGenUcastAddrSet(MV_U32 bcastMacAddrHigh, MV_U32 bcastMacAddrLow, MV_U32 macId);
+MV_STATUS mvOnuEponMacGenOnuConfigSet(MV_U32 rxPcsFecEn, MV_U32 txPcsFecEn, MV_U32 reportAutoResponse,
+                                      MV_U32 ackAutoResponse, MV_U32 requestAutoResponse, MV_U32 txFecEn);
+MV_STATUS mvOnuEponMacGenOnuConfigAutoReportSet(MV_U32 reportAutoResponse);
+MV_STATUS mvOnuEponMacGenOnuConfigAutoAckSet(MV_U32 ackAutoResponse);
+MV_STATUS mvOnuEponMacGenOnuConfigAutoRequestSet(MV_U32 requestAutoResponse);
+MV_STATUS mvOnuEponMacGenSldSet(MV_U32 sld);
+MV_STATUS mvOnuEponMacGenCtrlTypeSet(MV_U32 type);
+MV_STATUS mvOnuEponMacGenLocalTimeStampSet(MV_U32 timeStamp);
+MV_STATUS mvOnuEponMacGenLocalTimeStampGet(MV_U32 *timeStamp);
+MV_STATUS mvOnuEponMacGenPendGrantSet(MV_U32 grant);
+MV_STATUS mvOnuEponMacGenSglStatusGet(MV_U32 *sglStatus);
+MV_STATUS mvOnuEponMacGenPonPhyDbgSet(MV_U32 ponDebug);
+MV_STATUS mvOnuEponMacGenPonPhyDbgGet(MV_U32 *ponDebug);
+MV_STATUS mvOnuEponMacGenSglSwReset(MV_U32 swReset);
+MV_STATUS mvOnuEponMacGenSglConfig(MV_U32 startThreshold, MV_U32 dataAlignment);
+MV_STATUS mvOnuEponMacGenSglDebounceConfig(MV_U32 polarity, MV_U32 threshold);
+MV_STATUS mvOnuEponMacGenSglDebounceEnable(MV_U32 enable);
+MV_STATUS mvOnuEponMacGenChurningKeySet(MV_U32 key);
+MV_STATUS mvOnuEponMacGenOpcodeSet(MV_U32 opcodeType, MV_U32 value, MV_U32 index,
+                                   MV_U32 timestamp, MV_U32 valid);
+#ifdef PON_Z2
+MV_STATUS mvOnuEponMacGenTimestampConfig(MV_U32 gpmAddSyncTimeToTimestamp,
+                                         MV_U32 gpmAimestampOffset,
+                                         MV_U32 txmAddSyncTimeToTimestamp,
+                                         MV_U32 txmUseTimestampImage,
+                                         MV_U32 txmTimestampOffset);
+MV_STATUS mvOnuEponMacGenRxTimestampConfigSet(MV_U32 rxpTimestampSelect,
+										MV_U32 rxpTimestampSign,
+										MV_U32 rxpTimestampOffset);
+MV_STATUS mvOnuEponMacGenRxTimestampConfigGet(MV_U32 *rxpTimestampSelect,
+										MV_U32 *rxpTimestampSign,
+										MV_U32 *rxpTimestampOffset);
+MV_STATUS mvOnuEponMacGenRegPacketPaddingSet(MV_U32 regAckPadding, MV_U32 regReqPadding);
+MV_STATUS mvOnuEponMacGenRegPacketPaddingGet(MV_U32 *regAckPadding, MV_U32 *regReqPadding);
+#endif /* PON_Z2 */
+MV_STATUS mvOnuEponMacGenDriftThresholdSet(MV_U32 threshold);
+MV_STATUS mvOnuEponMacGenTimeStampForIntrSet(MV_U32 timestamp);
+MV_STATUS mvOnuEponMacGenTimeStampForIntrGet(MV_U32 *timestamp);
+MV_STATUS mvOnuEponMacGenUtmTcPeriodSet(MV_U32 tcPeriod);
+MV_STATUS mvOnuEponMacGenUtmTcPeriodEnSet(MV_U32 tcPeriodEnable);
+MV_STATUS mvOnuEponMacGenGemIpgValueSet(MV_U32 ipgVal);
+MV_STATUS mvOnuEponMacGenGemIpgValueEnSet(MV_U32 ipgValEn);
+
+/* ========================================================================== */
+/*                        RXP Functions Section                               */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacRxpPacketSizeLimitSet(MV_U32 minSize, MV_U32 maxSize);
+MV_STATUS mvOnuEponMacRxpPacketSizeLimitGet(MV_U32 *minSize, MV_U32 *maxSize);
+MV_STATUS mvOnuEponMacRxpPacketFilterSet(MV_U32 ignoreLlidCrcError, MV_U32 ignoreFcsError,
+                                         MV_U32 ignoreGmiiError, MV_U32 ignoreLengthError,
+                                         MV_U32 forwardAllLlid, MV_U32 forwardBc0FFF,
+                                         MV_U32 forwardBc1FFF, MV_U32 forwardBc1xxx, MV_U32 dropBc1nnn);
+MV_STATUS mvOnuEponMacRxpPacketFilterGet(MV_U32 *ignoreLlidCrcError, MV_U32 *ignoreFcsError,
+                                         MV_U32 *ignoreGmiiError, MV_U32 *ignoreLengthError,
+                                         MV_U32 *forwardAllLlid, MV_U32 *forwardBc0FFF,
+                                         MV_U32 *forwardBc1FFF, MV_U32 *forwardBc1xxx, MV_U32 *dropBc1nnn);
+MV_STATUS mvOnuEponMacRxpPacketForwardSet(MV_U32 ctrlFrameToDataQueue, MV_U32 ctrlFrameToCtrlQueue,
+                                          MV_U32 rprtFrameToDataQueue, MV_U32 rprtFrameToRprtQueue,
+                                          MV_U32 slowFrameToRprtQueue, MV_U32 slowFrameToCtrlQueue);
+MV_STATUS mvOnuEponMacRxpPacketForwardGet(MV_U32 *ctrlFrameToDataQueue, MV_U32 *ctrlFrameToCtrlQueue,
+                                          MV_U32 *rprtFrameToDataQueue, MV_U32 *rprtFrameToRprtQueue,
+                                          MV_U32 *slowFrameToRprtQueue, MV_U32 *slowFrameToCtrlQueue);
+MV_STATUS mvOnuEponMacRxpLlidDataSet(MV_U32 llid, MV_U32 index);
+MV_STATUS mvOnuEponMacRxpLlidDataGet(MV_U32 *llid, MV_U32 index);
+MV_STATUS mvOnuEponMacRxpEncConfigSet(MV_U32 config);
+MV_STATUS mvOnuEponMacRxpEncConfigGet(MV_U32 *config);
+MV_STATUS mvOnuEponMacRxpEncKeySet(MV_U32 key, MV_U32 index, MV_U32 macId);
+MV_STATUS mvOnuEponMacRxpEncKeyGet(MV_U32 *keyIndex0, MV_U32 *keyIndex1, MV_U32 macId);
+MV_STATUS mvOnuEponMacRxpDataFifoThresholdSet(MV_U32 threshold);
+MV_STATUS mvOnuEponMacRxpDataFifoThresholdGet(MV_U32 *threshold);
+
+/* ========================================================================== */
+/*                        GPM Functions Section                               */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacGpmMacFutureGrantTimeSet(MV_U32 grant);
+MV_STATUS mvOnuEponMacGpmMinProcessingTimeSet(MV_U32 processingTime, MV_U32 effectiveLength);
+#ifdef PON_Z2
+MV_STATUS mvOnuEponMacGpmDiscoveryGrantLengthSet(MV_U32 grantLength, MV_U32 addOffsetForCalc, MV_U32 grantLengthMultiTq);
+#endif /* PON_Z2 */
+#ifdef PON_Z1
+MV_STATUS mvOnuEponMacGpmDiscoveryGrantLengthSet(MV_U32 grantLength, MV_U32 grantLengthMultiTq);
+#endif /* PON_Z1 */
+MV_STATUS mvOnuEponMacGpmRxSyncGet(MV_U32 *syncTime, MV_U32 *syncTimeUpdateInd);
+MV_STATUS mvOnuEponMacGpmGrantValidCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmGrantMaxFutureTimeErrorCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmMinProcTimeErrorCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmLengthErrorCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmDiscoveryAndRegisterCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmFifoFullErrorCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmOpcDiscoveryNotRegisterBcastCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmOpcRegisterNotDiscoveryCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmOpcDiscoveryNotRegisterNotBcastCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmOpcDropGrantCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmOpcHiddenGrantCounterGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacGpmOpcBackToBackCounterGet(MV_U32 *counter, MV_U32 macId);
+
+/* ========================================================================== */
+/*                        TXM Functions Section                               */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacTxmOverheadSet(MV_U32 overhead);
+MV_STATUS mvOnuEponMacTxmOverheadGet(MV_U32 *overhead);
+#ifdef PON_Z2
+MV_STATUS mvOnuEponMacTxmConfigSet(MV_U32 tFec1Cfg, MV_U32 tFec2Cfg, MV_U32 ctrlFifoDisFcs,
+                                   MV_U32 maskGmiiSignal, MV_U32 blockDataFromDataPath,
+                                   MV_U32 addIpgToLenCalc, MV_U32 mode, MV_U32 alignment,
+                                   MV_U32 priority);
+#endif /* PON_Z2 */
+#ifdef PON_Z1
+MV_STATUS mvOnuEponMacTxmConfigSet(MV_U32 mode, MV_U32 alignment, MV_U32 priority);
+#endif /* PON_Z1 */
+
+MV_STATUS mvOnuEponMacTxmLlidSet(MV_U32 llid, MV_U32 macId);
+
+#ifdef PON_Z2
+MV_STATUS mvOnuEponMacTxmCppReportConfig(MV_U32 queueReportQ2, MV_U32 reportBitmapQ2,
+                                         MV_U32 queueReport, MV_U32 queueSet,
+                                         MV_U32 reportBitmap, MV_U32 macId);
+#endif /* PON_Z2 */
+#ifdef PON_Z1
+MV_STATUS mvOnuEponMacTxmCppReportConfig(MV_U32 config, MV_U32 macId);
+#endif /* PON_Z1 */
+MV_STATUS mvOnuEponMacTxmCppReportBitMap(MV_U32 bitMap, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxmCppReportBitMapGet(MV_U32 *bitMap, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxmCppReportQueueSet(MV_U32 queueSet, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxmCppReportQueueSetGet(MV_U32 *queueSet, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxmCppReportQueueX(MV_U32 queueNum, MV_U32 queueCfg, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxmCppReportUpdate(MV_U32 validQueueReport, MV_U32 highestReportQueue, MV_U32 macId);
+
+/* ========================================================================== */
+/*                        PCS Functions Section                               */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacPcsConfigSet(MV_U32 config);
+MV_STATUS mvOnuEponMacPcsConfigGet(MV_U32 *config);
+MV_STATUS mvOnuEponMacPcsDelaySet(MV_U32 delay);
+MV_STATUS mvOnuEponMacPcsStatsGet(MV_U32 *legalFrameCnt,
+								MV_U32 *maxFrameSizeErrCnt,
+								MV_U32 *parityLenErrCnt,
+								MV_U32 *longGateErrCnt,
+								MV_U32 *protocolErrCnt,
+								MV_U32 *minFrameSizeErrCnt,
+								MV_U32 *legalFecFrameCnt,
+								MV_U32 *legalNonFecFrameCnt);
+MV_STATUS mvOnuEponMacPcsFrameSizeLimitsSet(MV_U32 size, MV_U32 latency);
+MV_STATUS mvOnuEponMacPcsFrameSizeLimitsGet(MV_U32 *size, MV_U32 *latency);
+
+/* ========================================================================== */
+/*                        DDM Functions Section                               */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacDdmDelaySet(MV_U32 delay);
+#ifdef PON_Z2
+MV_STATUS mvOnuEponMacDdmTxPolaritySet(MV_U32 txEnable, MV_U32 polarity);
+#elif defined PON_Z1
+MV_STATUS mvOnuEponMacDdmTxPolaritySet(MV_U32 polarity);
+#else
+MV_STATUS mvOnuEponMacDdmTxPolaritySet(MV_U32 txEnable,
+				       MV_U32 txPolarity,
+				       MV_U32 serdesPolarity,
+				       MV_U32 xvrPolarity,
+				       MV_U32 burstEnable);
+#endif
+/* ========================================================================== */
+/*                        Statistics Functions Section                        */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacRxStatsFcsErrorGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacRxStatsShortErrorGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacRxStatsLongErrorGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacRxStatsDataFrameGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacRxStatsCtrlFrameGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacRxStatsReportFrameGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacRxStatsGateFrameGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxStatsCtrlRegReqFrameGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxStatsCtrlRegAckFrameGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxStatsCtrlReportFrameGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxStatsDataFrameGet(MV_U32 *counter, MV_U32 macId);
+MV_STATUS mvOnuEponMacTxStatsTxAllowedByteCountGet(MV_U32 *counter, MV_U32 macId);
+
+/* ========================================================================== */
+/*                        CPQ Functions Section                               */
+/* ========================================================================== */
+MV_STATUS mvOnuEponMacCpqRxCtrlHeaderQueueUsedCountGet(MV_U32 *usedCount);
+MV_STATUS mvOnuEponMacCpqRxCtrlHeaderQueueReadData(MV_U32 *dataLow, MV_U32 *dataHigh);
+MV_STATUS mvOnuEponMacCpqRxCtrlQueueUsedCountGet(MV_U32 *usedCount);
+MV_STATUS mvOnuEponMacCpqRxCtrlQueueReadData(MV_U32 *data);
+MV_STATUS mvOnuEponMacCpqRxRprtHeaderQueueUsedCountGet(MV_U32 *usedCount);
+MV_STATUS mvOnuEponMacCpqRxRprtHeaderQueueReadData(MV_U32 *dataLow, MV_U32 *dataHigh);
+MV_STATUS mvOnuEponMacCpqRxRprtQueueUsedCountGet(MV_U32 *usedCount);
+MV_STATUS mvOnuEponMacCpqRxRprtQueueReadData(MV_U32 *data);
+MV_STATUS mvOnuEponMacCpqTxCtrlHeaderQueueFree(MV_U32 *freeCount, MV_U32 macId);
+MV_STATUS mvOnuEponMacCpqTxCtrlHeaderQueueWrite(MV_U32 data, MV_U32 macId);
+MV_STATUS mvOnuEponMacCpqTxCtrlQueueFree(MV_U32 *freeCount, MV_U32 macId);
+MV_STATUS mvOnuEponMacCpqTxCtrlQueueWrite(MV_U32 data, MV_U32 macId);
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           ==     ==   =========   =========   ==        ==           == */
+/* ==           ==     ==   =========   =========   ===       ==           == */
+/* ==           ==     ==   ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==     ==   ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           ==     ==   =========   ==     ==   ==   ==   ==           == */
+/* ==           ==     ==   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==     ==   ==          ==     ==   ==     == ==           == */
+/* ==           ==     ==   ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+#ifndef PON_FPGA
+/* ========================================================================== */
+/*                        DG Functions Section                                */
+/* ========================================================================== */
+MV_STATUS mvOnuPonMacDgInterruptEn(MV_U32 dgPol);
+MV_STATUS mvOnuPonMacDgInterruptDis(void);
+#endif /* PON_FPGA */
+
+#endif /* _ONU_PON_MAC_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.c b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.c
new file mode 100755
index 0000000..497a288
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.c
@@ -0,0 +1,1124 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* Include Files
+------------------------------------------------------------------------------*/
+#include "mvTypes.h"
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+#include "mvPonOnuDefines.h"
+#include "mvPonOnuRegs.h"
+#include "mvPonOnuMac.h"
+
+/* Local Constant
+------------------------------------------------------------------------------*/
+#define MV_ASIC_ONT_GLB_ADDR   (MV_ASIC_ONT_BASE)
+
+/* Global Variables
+------------------------------------------------------------------------------*/
+MV_U32 ponOnuGlbAddr;
+
+/* Local Variables
+------------------------------------------------------------------------------*/
+
+S_asicGlobalRegDb asicGlbDb[] =
+{
+/* Enumeration                                                                                          |Address                        |Offset   |Access     |Mask           |Shift  |Table |Table  |Cnt   |Description
+ *                                                                                                      |                               |         |Type       |               |       |Len   |Entry  |      |
+ *                                                                                                      |                               |         |           |               |       |      |Size   |      |
+ * ============================================================================================================================================================================================================================= */
+  [mvAsicReg_Start]                                 = {mvAsicReg_Start},
+
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           =========   =========   =========   ===       ==           == */
+/* ==           =========   =========   =========   ====      ==           == */
+/* ==           ==          ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==          ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           =========   =========   ==     ==   ==   ==   ==           == */
+/* ==           =========   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==     ==   ==          ==     ==   ==     == ==           == */
+/* ==           ==     ==   ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+
+  /* =========================== */
+  /*  Interrupts Registers       */
+  /* =========================== */
+  [mvAsicReg_GPON_INTERRUPT_PON]                    = {mvAsicReg_GPON_INTERRUPT_PON,                    MV_ASIC_ONT_GLB_ADDR + 0x0000,   0x0000,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Interrupt PON"},
+  [mvAsicReg_GPON_INTERRUPT_PON_MASK]               = {mvAsicReg_GPON_INTERRUPT_PON_MASK,               MV_ASIC_ONT_GLB_ADDR + 0x0004,   0x0004,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Interrupt PON Mask"},
+  [mvAsicReg_BIP_INTR_INTERVAL]                     = {mvAsicReg_BIP_INTR_INTERVAL,                     MV_ASIC_ONT_GLB_ADDR + 0x0008,   0x0008,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "BIP INTR interval"},
+  [mvAsicReg_RX_BIP_STATUS_FOR_INTERRUPT]           = {mvAsicReg_RX_BIP_STATUS_FOR_INTERRUPT,           MV_ASIC_ONT_GLB_ADDR + 0x000C,   0x000C,   asicRO,     0x0000FFFF,     0,      0,     0,      0,     "BIP INTR stats accumulator"},
+  [mvAsicReg_RAM_TEST_CONFIG]                       = {mvAsicReg_RAM_TEST_CONFIG,                       MV_ASIC_ONT_GLB_ADDR + 0x0010,   0x000C,   asicRW,     0x0000000F,     0,      0,     0,      0,     "Ram test config PE polarity"},
+
+  /* =========================== */
+  /*  General Registers          */
+  /* =========================== */
+  [mvAsicReg_GPON_GEN_MAC_VERSION]                  = {mvAsicReg_GPON_GEN_MAC_VERSION,                  MV_ASIC_ONT_GLB_ADDR + 0x0400,   0x0400,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "GPON version"},
+  [mvAsicReg_GPON_GEN_MAC_VERSION_ID]               = {mvAsicReg_GPON_GEN_MAC_VERSION_ID,               MV_ASIC_ONT_GLB_ADDR + 0x0400,   0x0400,   asicRO,     0x0000FFFF,     0,      0,     0,      0,     "GPON MAC version"},
+  [mvAsicReg_GPON_GEN_MAC_VERSION_MAC_ID]           = {mvAsicReg_GPON_GEN_MAC_VERSION_MAC_ID,           MV_ASIC_ONT_GLB_ADDR + 0x0400,   0x0400,   asicRO,     0x0000FFFF,    16,      0,     0,      0,     "GPON MAC Id"},
+  [mvAsicReg_GPON_GEN_MAC_SCRATCH]                  = {mvAsicReg_GPON_GEN_MAC_SCRATCH,                  MV_ASIC_ONT_GLB_ADDR + 0x0404,   0x0404,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "MAC scratch register"},
+  [mvAsicReg_GPON_ONU_STATE]                        = {mvAsicReg_GPON_ONU_STATE,                        MV_ASIC_ONT_GLB_ADDR + 0x0408,   0x0408,   asicRW,     0x000000FF,     0,      0,     0,      0,     "ONU state"},
+  [mvAsicReg_GPON_GEN_MICRO_SEC_CNT]                = {mvAsicReg_GPON_GEN_MICRO_SEC_CNT,                MV_ASIC_ONT_GLB_ADDR + 0x040C,   0x040C,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Micro second counter"},
+  [mvAsicReg_GPON_TX_SERIAL_NUMBER]                 = {mvAsicReg_GPON_TX_SERIAL_NUMBER,                 MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "Tx serial number"},
+  [mvAsicReg_GPON_ONU_ID]                           = {mvAsicReg_GPON_ONU_ID,                           MV_ASIC_ONT_GLB_ADDR + 0x0414,   0x0414,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "ONU Id"},
+  [mvAsicReg_GPON_ONU_ID_OID]                       = {mvAsicReg_GPON_ONU_ID_OID,                       MV_ASIC_ONT_GLB_ADDR + 0x0414,   0x0414,   asicRW,     0x000000FF,     0,      0,     0,      0,     "GPON ONU Id"},
+  [mvAsicReg_GPON_ONU_ID_V]                         = {mvAsicReg_GPON_ONU_ID_V,                         MV_ASIC_ONT_GLB_ADDR + 0x0414,   0x0414,   asicRW,     0x00000001,     8,      0,     0,      0,     "GPON ONU valid indication"},
+
+  /* =========================== */
+  /*  Rx Registers               */
+  /* =========================== */
+  [mvAsicReg_GPON_RX_CONFIG]                        = {mvAsicReg_GPON_RX_CONFIG,                        MV_ASIC_ONT_GLB_ADDR + 0x0800,   0x0800,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx config"},
+  [mvAsicReg_GPON_RX_CONFIG_EN]                     = {mvAsicReg_GPON_RX_CONFIG_EN,                     MV_ASIC_ONT_GLB_ADDR + 0x0800,   0x0800,   asicRW,     0x00000001,     0,      0,     0,      0,     "Rx config - enable"},
+  [mvAsicReg_GPON_RX_CONFIG_BIT_ORDER]              = {mvAsicReg_GPON_RX_CONFIG_BIT_ORDER,              MV_ASIC_ONT_GLB_ADDR + 0x0800,   0x0800,   asicRW,     0x00000001,     1,      0,     0,      0,     "Rx config - bit order"},
+  [mvAsicReg_GPON_RX_PSA_CONFIG]                    = {mvAsicReg_GPON_RX_PSA_CONFIG,                    MV_ASIC_ONT_GLB_ADDR + 0x0804,   0x0804,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx PSA config"},
+  [mvAsicReg_GPON_RX_PSA_CONFIG_SFM3]               = {mvAsicReg_GPON_RX_PSA_CONFIG_SFM3,               MV_ASIC_ONT_GLB_ADDR + 0x0804,   0x0804,   asicRW,     0x000000FF,     0,      0,     0,      0,     "PLOAM Sync SM: sync => hunt state"},
+  [mvAsicReg_GPON_RX_PSA_CONFIG_SFM2]               = {mvAsicReg_GPON_RX_PSA_CONFIG_SFM2,               MV_ASIC_ONT_GLB_ADDR + 0x0804,   0x0804,   asicRW,     0x000000FF,     8,      0,     0,      0,     "PLOAM Sync SM: sync => hunt state"},
+  [mvAsicReg_GPON_RX_PSA_CONFIG_SFM1]               = {mvAsicReg_GPON_RX_PSA_CONFIG_SFM1,               MV_ASIC_ONT_GLB_ADDR + 0x0804,   0x0804,   asicRW,     0x000000FF,     16,     0,     0,      0,     "PLOAM Sync SM: pre-sync => sync state"},
+  [mvAsicReg_GPON_RX_PSA_CONFIG_FHM1]               = {mvAsicReg_GPON_RX_PSA_CONFIG_FHM1,               MV_ASIC_ONT_GLB_ADDR + 0x0804,   0x0804,   asicRW,     0x0000000F,     24,     0,     0,      0,     "FEC hysteresis mechanisem"},
+  [mvAsicReg_GPON_RX_FEC_CONFIG]                    = {mvAsicReg_GPON_RX_FEC_CONFIG,                    MV_ASIC_ONT_GLB_ADDR + 0x0808,   0x0808,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx FEC config"},
+  [mvAsicReg_GPON_RX_FEC_CONFIG_SWVAL]              = {mvAsicReg_GPON_RX_FEC_CONFIG_SWVAL,              MV_ASIC_ONT_GLB_ADDR + 0x0808,   0x0808,   asicRW,     0x00000001,     0,      0,     0,      0,     "SW value for internal FEC indication"},
+  [mvAsicReg_GPON_RX_FEC_CONFIG_FSW]                = {mvAsicReg_GPON_RX_FEC_CONFIG_FSW,                MV_ASIC_ONT_GLB_ADDR + 0x0808,   0x0808,   asicRW,     0x00000001,     1,      0,     0,      0,     "Force SW FEC indication"},
+  [mvAsicReg_GPON_RX_FEC_CONFIG_IGNP]               = {mvAsicReg_GPON_RX_FEC_CONFIG_IGNP,               MV_ASIC_ONT_GLB_ADDR + 0x0808,   0x0808,   asicRW,     0x00000001,     2,      0,     0,      0,     "Force SW FEC ignore parity"},
+  [mvAsicReg_GPON_RX_FEC_CONFIG_IND]                = {mvAsicReg_GPON_RX_FEC_CONFIG_IND,                MV_ASIC_ONT_GLB_ADDR + 0x0808,   0x0808,   asicRO,     0x00000001,     31,     0,     0,      0,     "Internal FEC indication"},
+  [mvAsicReg_GPON_RX_FEC_STAT0]                     = {mvAsicReg_GPON_RX_FEC_STAT0,                     MV_ASIC_ONT_GLB_ADDR + 0x080C,   0x080C,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of bytes rece from last read"},
+  [mvAsicReg_GPON_RX_FEC_STAT1]                     = {mvAsicReg_GPON_RX_FEC_STAT1,                     MV_ASIC_ONT_GLB_ADDR + 0x0810,   0x0810,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of correct bytes / bits"},
+  [mvAsicReg_GPON_RX_FEC_STAT2]                     = {mvAsicReg_GPON_RX_FEC_STAT2,                     MV_ASIC_ONT_GLB_ADDR + 0x0814,   0x0814,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of incorrect / rece bytes"},
+  [mvAsicReg_GPON_RX_SFRAME_COUNTER]                = {mvAsicReg_GPON_RX_SFRAME_COUNTER,                MV_ASIC_ONT_GLB_ADDR + 0x0818,   0x0818,   asicRO,     0x3FFFFFFF,     0,      0,     0,      0,     "Rx Superframe Counter"},
+  [mvAsicReg_GPON_RX_PLOAMD_DATA_READ]              = {mvAsicReg_GPON_RX_PLOAMD_DATA_READ,              MV_ASIC_ONT_GLB_ADDR + 0x081C,   0x081C,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx PLOAM data fifo, PLOAM = 3xread"},
+  [mvAsicReg_GPON_RX_PLOAMD_DATA_USED]              = {mvAsicReg_GPON_RX_PLOAMD_DATA_USED,              MV_ASIC_ONT_GLB_ADDR + 0x0820,   0x0820,   asicRO,     0x000000FF,     0,      0,     0,      0,     "Num of free entry's in PLOAM data fifo"},
+  [mvAsicReg_GPON_RX_PLOAMD_CONFIG]                 = {mvAsicReg_GPON_RX_PLOAMD_CONFIG,                 MV_ASIC_ONT_GLB_ADDR + 0x0824,   0x0824,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx PLOAM config"},
+  [mvAsicReg_GPON_RX_PLOAMD_CONFIG_IGNC]            = {mvAsicReg_GPON_RX_PLOAMD_CONFIG_IGNC,            MV_ASIC_ONT_GLB_ADDR + 0x0824,   0x0824,   asicRW,     0x00000001,     0,      0,     0,      0,     "Ignore PLOAM crc, forward regardless of crc"},
+  [mvAsicReg_GPON_RX_PLOAMD_CONFIG_IGNB]            = {mvAsicReg_GPON_RX_PLOAMD_CONFIG_IGNB,            MV_ASIC_ONT_GLB_ADDR + 0x0824,   0x0824,   asicRW,     0x00000001,     1,      0,     0,      0,     "Ignore broadcast PLOAM, forward only onuId"},
+  [mvAsicReg_GPON_RX_PLOAMD_CONFIG_FALL]            = {mvAsicReg_GPON_RX_PLOAMD_CONFIG_FALL,            MV_ASIC_ONT_GLB_ADDR + 0x0824,   0x0824,   asicRW,     0x00000001,     2,      0,     0,      0,     "Forward all PLOAM"},
+  [mvAsicReg_GPON_RX_PLOAMD_LOST_CRC_STATUS]        = {mvAsicReg_GPON_RX_PLOAMD_LOST_CRC_STATUS,        MV_ASIC_ONT_GLB_ADDR + 0x0828,   0x0828,   asicRO,     0x0000FFFF,     0,      0,     0,      0,     "Num of PLOAM lost due to faulty crc"},
+  [mvAsicReg_GPON_RX_PLOAMD_LOST_FULL_STATUS]       = {mvAsicReg_GPON_RX_PLOAMD_LOST_FULL_STATUS,       MV_ASIC_ONT_GLB_ADDR + 0x082C,   0x082C,   asicRO,     0x0000FFFF,     0,      0,     0,      0,     "Num of PLOAM lost due to cpu fifo full"},
+  [mvAsicReg_GPON_RX_PLOAMD_RCVD_IDLE_STATUS]       = {mvAsicReg_GPON_RX_PLOAMD_RCVD_IDLE_STATUS,       MV_ASIC_ONT_GLB_ADDR + 0x0830,   0x0830,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of idle PLOAM rece"},
+  [mvAsicReg_GPON_RX_PLOAMD_RCVD_BROAD_STATUS]      = {mvAsicReg_GPON_RX_PLOAMD_RCVD_BROAD_STATUS,      MV_ASIC_ONT_GLB_ADDR + 0x0834,   0x0834,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of broadcast PLOAM rece"},
+  [mvAsicReg_GPON_RX_PLOAMD_RCVD_MYID_STATUS]       = {mvAsicReg_GPON_RX_PLOAMD_RCVD_MYID_STATUS,       MV_ASIC_ONT_GLB_ADDR + 0x0838,   0x0838,   asicRO,     0x0000FFFF,     0,      0,     0,      0,     "Num of PLOAM rece assigned to MYID"},
+  [mvAsicReg_GPON_RX_BIP_STATUS]                    = {mvAsicReg_GPON_RX_BIP_STATUS,                    MV_ASIC_ONT_GLB_ADDR + 0x083C,   0x083C,   asicRO,     0x0000FFFF,     0,      0,     0,      0,     "Num of BIP errors since last read"},
+  [mvAsicReg_GPON_RX_PLEND_CONFIG]                  = {mvAsicReg_GPON_RX_PLEND_CONFIG,                  MV_ASIC_ONT_GLB_ADDR + 0x0840,   0x0840,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx PLEND config"},
+  [mvAsicReg_GPON_RX_PLEND_CONFIG_FN]               = {mvAsicReg_GPON_RX_PLEND_CONFIG_FN,               MV_ASIC_ONT_GLB_ADDR + 0x0840,   0x0840,   asicRW,     0x00000001,     0,      0,     0,      0,     "Force SW plend field selection"},
+  [mvAsicReg_GPON_RX_PLEND_CONFIG_UF]               = {mvAsicReg_GPON_RX_PLEND_CONFIG_UF,               MV_ASIC_ONT_GLB_ADDR + 0x0840,   0x0840,   asicRW,     0x00000001,     1,      0,     0,      0,     "SW use of plend field"},
+  [mvAsicReg_GPON_RX_PLEND_CONFIG_IGND]             = {mvAsicReg_GPON_RX_PLEND_CONFIG_IGND,             MV_ASIC_ONT_GLB_ADDR + 0x0840,   0x0840,   asicRW,     0x00000001,     2,      0,     0,      0,     "Ignore diff between two plend fields"},
+  [mvAsicReg_GPON_RX_PLEND_CONFIG_DFIX]             = {mvAsicReg_GPON_RX_PLEND_CONFIG_DFIX,             MV_ASIC_ONT_GLB_ADDR + 0x0840,   0x0840,   asicRW,     0x00000001,     3,      0,     0,      0,     "Do not fix plend field according to crc result"},
+  [mvAsicReg_GPON_RX_PLEND_CONFIG_IGNC]             = {mvAsicReg_GPON_RX_PLEND_CONFIG_IGNC,             MV_ASIC_ONT_GLB_ADDR + 0x0840,   0x0840,   asicRW,     0x00000001,     4,      0,     0,      0,     "Ignore crc during plend field selection"},
+  [mvAsicReg_GPON_RX_PLEND_STATUS]                  = {mvAsicReg_GPON_RX_PLEND_STATUS,                  MV_ASIC_ONT_GLB_ADDR + 0x0844,   0x0844,   asicRO,     0x0000FFFF,     0,      0,     0,      0,     "Rx PLEND status"},
+  [mvAsicReg_GPON_RX_BWMAP_CONFIG]                  = {mvAsicReg_GPON_RX_BWMAP_CONFIG,                  MV_ASIC_ONT_GLB_ADDR + 0x0848,   0x0848,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx BW map config"},
+  [mvAsicReg_GPON_RX_BWMAP_CONFIG_MSD]              = {mvAsicReg_GPON_RX_BWMAP_CONFIG_MSD,              MV_ASIC_ONT_GLB_ADDR + 0x0848,   0x0848,   asicRW,     0x00000FFF,     0,      0,     0,      0,     "Min num of bytes between bursts"},
+  [mvAsicReg_GPON_RX_BWMAP_CONFIG_DFIX]             = {mvAsicReg_GPON_RX_BWMAP_CONFIG_DFIX,             MV_ASIC_ONT_GLB_ADDR + 0x0848,   0x0848,   asicRW,     0x00000001,    12,      0,     0,      0,     "Do not fix BW map according to crc result"},
+  [mvAsicReg_GPON_RX_BWMAP_CONFIG_IGNC]             = {mvAsicReg_GPON_RX_BWMAP_CONFIG_IGNC,             MV_ASIC_ONT_GLB_ADDR + 0x0848,   0x0848,   asicRW,     0x00000001,    13,      0,     0,      0,     "Ignore crc result for BW allocation"},
+  [mvAsicReg_GPON_RX_BWMAP_STATUS0]                 = {mvAsicReg_GPON_RX_BWMAP_STATUS0,                 MV_ASIC_ONT_GLB_ADDR + 0x084C,   0x084C,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of BW bytes rece with crc: bad/error/corr/uncorr"},
+  [mvAsicReg_GPON_RX_BWMAP_STATUS1]                 = {mvAsicReg_GPON_RX_BWMAP_STATUS1,                 MV_ASIC_ONT_GLB_ADDR + 0x0850,   0x0850,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of BW bytes rece from last read"},
+  [mvAsicReg_GPON_RX_AES_CONFIG]                    = {mvAsicReg_GPON_RX_AES_CONFIG,                    MV_ASIC_ONT_GLB_ADDR + 0x0854,   0x0854,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx AES key switch config"},
+  [mvAsicReg_GPON_RX_AES_CONFIG_TIME]               = {mvAsicReg_GPON_RX_AES_CONFIG_TIME,               MV_ASIC_ONT_GLB_ADDR + 0x0854,   0x0854,   asicRW,     0x3FFFFFFF,     0,      0,     0,      0,     "AES Key switch time value based on superframe counter"},
+  [mvAsicReg_GPON_RX_AES_CONFIG_SWS]                = {mvAsicReg_GPON_RX_AES_CONFIG_SWS,                MV_ASIC_ONT_GLB_ADDR + 0x0854,   0x0854,   asicRW,     0x00000001,    30,      0,     0,      0,     "AES SW Force key switch according to superframe counter"},
+  [mvAsicReg_GPON_RX_AES_STATUS]                    = {mvAsicReg_GPON_RX_AES_STATUS,                    MV_ASIC_ONT_GLB_ADDR + 0x0858,   0x0858,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Rx AES status"},
+  [mvAsicReg_GPON_RX_AES_STATUS_HST]                = {mvAsicReg_GPON_RX_AES_STATUS_HST,                MV_ASIC_ONT_GLB_ADDR + 0x0858,   0x0858,   asicRO,     0x3FFFFFFF,     0,      0,     0,      0,     "Indicates the time to switch AES Key"},
+  [mvAsicReg_GPON_RX_AES_STATUS_HWS]                = {mvAsicReg_GPON_RX_AES_STATUS_HWS,                MV_ASIC_ONT_GLB_ADDR + 0x0858,   0x0858,   asicRO,     0x00000001,    30,      0,     0,      0,     "indicates AES key switch time is valid"},
+  [mvAsicReg_GPON_RX_EQULIZATION_DELAY]             = {mvAsicReg_GPON_RX_EQULIZATION_DELAY,             MV_ASIC_ONT_GLB_ADDR + 0x085C,   0x085C,   asicRW,     0x000FFFFF,     0,      0,     0,      0,     "Rx equalization delay, sent from the OLT"},
+  [mvAsicReg_GPON_RX_INTERNAL_DELAY]                = {mvAsicReg_GPON_RX_INTERNAL_DELAY,                MV_ASIC_ONT_GLB_ADDR + 0x0860,   0x0860,   asicRW,     0x00001FFF,     0,      0,     0,      0,     "Rx Internal Delay - Constant"},
+  [mvAsicReg_GPON_RX_BW_MAP]                        = {mvAsicReg_GPON_RX_BW_MAP,                        MV_ASIC_ONT_GLB_ADDR + 0x0880,   0x0880,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Rx BW map"},
+  [mvAsicReg_GPON_RX_BW_MAP_ALID]                   = {mvAsicReg_GPON_RX_BW_MAP_ALID,                   MV_ASIC_ONT_GLB_ADDR + 0x0880,   0x0880,   asicRW,     0x00000FFF,     0,      8,     1,      0,     "Alloc Id number to be mapped to tcont number"},
+  [mvAsicReg_GPON_RX_BW_MAP_TCN]                    = {mvAsicReg_GPON_RX_BW_MAP_TCN,                    MV_ASIC_ONT_GLB_ADDR + 0x0880,   0x0880,   asicRW,     0x0000000F,    12,      8,     1,      0,     "Tcont number to which the allocId will be mapped"},
+  [mvAsicReg_GPON_RX_BW_MAP_EN]                     = {mvAsicReg_GPON_RX_BW_MAP_EN,                     MV_ASIC_ONT_GLB_ADDR + 0x0880,   0x0880,   asicRW,     0x00000001,    16,      8,     1,      0,     "Rx BW map mapping fields are valid"},
+
+  /* =========================== */
+  /*  GEM Registers              */
+  /* =========================== */
+  [mvAsicReg_GPON_GEM_STAT_IDLE_GEM_CNT]            = {mvAsicReg_GPON_GEM_STAT_IDLE_GEM_CNT,            MV_ASIC_ONT_GLB_ADDR + 0x0C00,   0x0C00,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece idle gem frames"},
+  [mvAsicReg_GPON_GEM_STAT_VALID_GEM_CNT]           = {mvAsicReg_GPON_GEM_STAT_VALID_GEM_CNT,           MV_ASIC_ONT_GLB_ADDR + 0x0C04,   0x0C04,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece valid gem frames"},
+  [mvAsicReg_GPON_GEM_STAT_UNDEF_GEM_CNT]           = {mvAsicReg_GPON_GEM_STAT_UNDEF_GEM_CNT,           MV_ASIC_ONT_GLB_ADDR + 0x0C08,   0x0C08,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece undefined gem frames"},
+  [mvAsicReg_GPON_GEM_STAT_VALID_OMCI_CNT]          = {mvAsicReg_GPON_GEM_STAT_VALID_OMCI_CNT,          MV_ASIC_ONT_GLB_ADDR + 0x0C0C,   0x0C0C,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece omci frames"},
+  [mvAsicReg_GPON_GEM_STAT_DROPPED_GEM_CNT]         = {mvAsicReg_GPON_GEM_STAT_DROPPED_GEM_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x0C10,   0x0C10,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of dropped gem frames"},
+  [mvAsicReg_GPON_GEM_STAT_DROPPED_OMCI_CNT]        = {mvAsicReg_GPON_GEM_STAT_DROPPED_OMCI_CNT,        MV_ASIC_ONT_GLB_ADDR + 0x0C14,   0x0C14,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of dropped omci frames"},
+  [mvAsicReg_GPON_GEM_STAT_ERROR_GEM_CNT]           = {mvAsicReg_GPON_GEM_STAT_ERROR_GEM_CNT,           MV_ASIC_ONT_GLB_ADDR + 0x0C18,   0x0C18,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece gem frames with uncorr HEC errors"},
+  [mvAsicReg_GPON_GEM_STAT_ONE_FIXED_HEC_ERR_CNT]   = {mvAsicReg_GPON_GEM_STAT_ONE_FIXED_HEC_ERR_CNT,   MV_ASIC_ONT_GLB_ADDR + 0x0C1C,   0x0C1C,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece gem frames with 1 HEC error in gem header"},
+  [mvAsicReg_GPON_GEM_STAT_TWO_FIXED_HEC_ERR_CNT]   = {mvAsicReg_GPON_GEM_STAT_TWO_FIXED_HEC_ERR_CNT,   MV_ASIC_ONT_GLB_ADDR + 0x0C20,   0x0C20,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece gem frames with 2 HEC error in gem header"},
+  [mvAsicReg_GPON_GEM_STAT_VALID_GEM_PAYLOAD_CNT]   = {mvAsicReg_GPON_GEM_STAT_VALID_GEM_PAYLOAD_CNT,   MV_ASIC_ONT_GLB_ADDR + 0x0C24,   0x0C24,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Total payload byte count of rece valid gem frames"},
+  [mvAsicReg_GPON_GEM_STAT_UNDEF_GEM_PAYLOAD_CNT]   = {mvAsicReg_GPON_GEM_STAT_UNDEF_GEM_PAYLOAD_CNT,   MV_ASIC_ONT_GLB_ADDR + 0x0C28,   0x0C28,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Total payload byte count of rece undefined gem frames"},
+  [mvAsicReg_GPON_GEM_STAT_RSMBL_MEM_FLUSH_CNT]     = {mvAsicReg_GPON_GEM_STAT_RSMBL_MEM_FLUSH_CNT,     MV_ASIC_ONT_GLB_ADDR + 0x0C2C,   0x0C2C,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of times gem reassemble memory was flushed"},
+  [mvAsicReg_GPON_GEM_STAT_LCDGi_CNT]               = {mvAsicReg_GPON_GEM_STAT_LCDGi_CNT,               MV_ASIC_ONT_GLB_ADDR + 0x0C30,   0x0C30,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of times gem synchronization was lost"},
+  [mvAsicReg_GPON_GEM_STAT_CORR_ETH_FRAME_CNT]      = {mvAsicReg_GPON_GEM_STAT_CORR_ETH_FRAME_CNT,      MV_ASIC_ONT_GLB_ADDR + 0x0C34,   0x0C34,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece ethernet frames with corr fcs"},
+  [mvAsicReg_GPON_GEM_STAT_ERR_ETH_FRAME_CNT]       = {mvAsicReg_GPON_GEM_STAT_ERR_ETH_FRAME_CNT,       MV_ASIC_ONT_GLB_ADDR + 0x0C38,   0x0C38,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece ethernet frames with fcs error"},
+  [mvAsicReg_GPON_GEM_STAT_CORR_OMCI_FRAME_CNT]     = {mvAsicReg_GPON_GEM_STAT_CORR_OMCI_FRAME_CNT,     MV_ASIC_ONT_GLB_ADDR + 0x0C3C,   0x0C3C,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece omci frames with corr crc"},
+  [mvAsicReg_GPON_GEM_STAT_ERR_OMCI_FRAME_CNT]      = {mvAsicReg_GPON_GEM_STAT_ERR_OMCI_FRAME_CNT,      MV_ASIC_ONT_GLB_ADDR + 0x0C40,   0x0C40,   asicRO,     0xFFFFFFFF,      0,     0,     0,      0,     "Num of rece omci frames with crc error"},
+  [mvAsicReg_GPON_GEM_CONFIG_PLI]                   = {mvAsicReg_GPON_GEM_CONFIG_PLI,                   MV_ASIC_ONT_GLB_ADDR + 0x0C44,   0x0C44,   asicRW,     0x00000FFF,      0,     0,     0,      0,     "Gem frames max payload length"},
+  [mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN]         = {mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN,         MV_ASIC_ONT_GLB_ADDR + 0x0C48,   0x0C48,   asicRW,     0xFFFFFFFF,      0,     0,     0,      0,     "Gem ethernet frames length config"},
+  [mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MAX]     = {mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MAX,     MV_ASIC_ONT_GLB_ADDR + 0x0C48,   0x0C48,   asicRW,     0x00000FFF,      0,     0,     0,      0,     "Gem ethernet frames max length"},
+  [mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MIN]     = {mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MIN,     MV_ASIC_ONT_GLB_ADDR + 0x0C48,   0x0C48,   asicRW,     0x00000FFF,     16,     0,     0,      0,     "Gem ethernet frames min length"},
+  [mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN]        = {mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN,        MV_ASIC_ONT_GLB_ADDR + 0x0C4C,   0x0C4C,   asicRW,     0xFFFFFFFF,      0,     0,     0,      0,     "Gem omci frames length config"},
+  [mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MAX]    = {mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MAX,    MV_ASIC_ONT_GLB_ADDR + 0x0C4C,   0x0C4C,   asicRW,     0x00000FFF,      0,     0,     0,      0,     "Gem omci frames max length"},
+  [mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MIN]    = {mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MIN,    MV_ASIC_ONT_GLB_ADDR + 0x0C4C,   0x0C4C,   asicRW,     0x00000FFF,     16,     0,     0,      0,     "Gem omci frames min length"},
+  [mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT]             = {mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT,             MV_ASIC_ONT_GLB_ADDR + 0x0C50,   0x0C50,   asicRW,     0xFFFFFFFF,      0,     0,     0,      0,     "Omci gem port Id config"},
+  [mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_ID]          = {mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_ID,          MV_ASIC_ONT_GLB_ADDR + 0x0C50,   0x0C50,   asicRW,     0x00000FFF,      0,     0,     0,      0,     "Omci gem port Id value"},
+  [mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_VALID]       = {mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_VALID,       MV_ASIC_ONT_GLB_ADDR + 0x0C50,   0x0C50,   asicRW,     0x00000001,     16,     0,     0,      0,     "Omci gem port Id valid indication"},
+  [mvAsicReg_GPON_GEM_CONFIG_AES]                   = {mvAsicReg_GPON_GEM_CONFIG_AES,                   MV_ASIC_ONT_GLB_ADDR + 0x0C54,   0x0C54,   asicRW,     0x00000001,      0,     0,     0,      0,     "Gem AES enable"},
+  [mvAsicReg_GPON_GEM_AES_SHADOW_KEY]               = {mvAsicReg_GPON_GEM_AES_SHADOW_KEY,               MV_ASIC_ONT_GLB_ADDR + 0x0C58,   0x0C58,   asicRW,     0xFFFFFFFF,      0,     4,     1,      0,     "Rx AES shadow key"},
+  [mvAsicReg_GPON_GEM_CFG_IPG_VALUE]                = {mvAsicReg_GPON_GEM_CFG_IPG_VALUE,                MV_ASIC_ONT_GLB_ADDR + 0x0C68,   0x0C68,   asicRW,     0x000000FF,      0,     0,     0,      0,     "Gem Cfg IPG Value"},
+  [mvAsicReg_GPON_GEM_CFG_IPG_VALID]                = {mvAsicReg_GPON_GEM_CFG_IPG_VALID,                MV_ASIC_ONT_GLB_ADDR + 0x0C6C,   0x0C6C,   asicRW,     0x00000001,      0,     0,     0,      0,     "Gem Cfg IPG Valid"},
+
+  /* =========================== */
+  /*  Tx Registers               */
+  /* =========================== */
+  [mvAsicReg_GPON_TX_PREAMBLE]                      = {mvAsicReg_GPON_TX_PREAMBLE,                      MV_ASIC_ONT_GLB_ADDR + 0x1000,   0x1000,   asicRW,     0xFFFFFFFF,     0,      3,     1,      0,     "Tx preamble config"},
+  [mvAsicReg_GPON_TX_PREAMBLE_PATT]                 = {mvAsicReg_GPON_TX_PREAMBLE_PATT,                 MV_ASIC_ONT_GLB_ADDR + 0x1000,   0x1000,   asicRW,     0x000000FF,     0,      3,     1,      0,     "Tx preamble type 1/2/3 pattern"},
+  [mvAsicReg_GPON_TX_PREAMBLE_SIZE]                 = {mvAsicReg_GPON_TX_PREAMBLE_SIZE,                 MV_ASIC_ONT_GLB_ADDR + 0x1000,   0x1000,   asicRW,     0x000000FF,     8,      3,     1,      0,     "Tx preamble type 1/2/3 size"},
+  [mvAsicReg_GPON_TX_DELIMITER]                     = {mvAsicReg_GPON_TX_DELIMITER,                     MV_ASIC_ONT_GLB_ADDR + 0x100C,   0x100C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Tx delimiter config"},
+  [mvAsicReg_GPON_TX_DELIMITER_PAT]                 = {mvAsicReg_GPON_TX_DELIMITER_PAT,                 MV_ASIC_ONT_GLB_ADDR + 0x100C,   0x100C,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "Tx delimiter byte 1/2/3 pattern"},
+  [mvAsicReg_GPON_TX_DELIMITER_SIZE]                = {mvAsicReg_GPON_TX_DELIMITER_SIZE,                MV_ASIC_ONT_GLB_ADDR + 0x100C,   0x100C,   asicRW,     0x000000FF,     24,     0,     0,      0,     "Tx delimiter size"},
+  [mvAsicReg_GPON_TX_BURST_EN_PARAM]                = {mvAsicReg_GPON_TX_BURST_EN_PARAM,                MV_ASIC_ONT_GLB_ADDR + 0x1010,   0x1010,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Tx burst enable config"},
+  [mvAsicReg_GPON_TX_BURST_EN_PARAM_STR]            = {mvAsicReg_GPON_TX_BURST_EN_PARAM_STR,            MV_ASIC_ONT_GLB_ADDR + 0x1010,   0x1010,   asicRW,     0x0000001F,     0,      0,     0,      0,     "Num of tx enable bytes before first US data bit is trans"},
+  [mvAsicReg_GPON_TX_BURST_EN_PARAM_STP]            = {mvAsicReg_GPON_TX_BURST_EN_PARAM_STP,            MV_ASIC_ONT_GLB_ADDR + 0x1010,   0x1010,   asicRW,     0x0000001F,     8,      0,     0,      0,     "Num of tx enable bytes after last US data bit is trans"},
+  [mvAsicReg_GPON_TX_BURST_EN_PARAM_DLY]            = {mvAsicReg_GPON_TX_BURST_EN_PARAM_DLY,            MV_ASIC_ONT_GLB_ADDR + 0x1010,   0x1010,   asicRW,     0x00000001,     14,     0,     0,      0,     "Swap the order of tx data and tx enable bytes"},
+  [mvAsicReg_GPON_TX_BURST_EN_PARAM_P]              = {mvAsicReg_GPON_TX_BURST_EN_PARAM_P,              MV_ASIC_ONT_GLB_ADDR + 0x1010,   0x1010,   asicRW,     0x00000001,     15,     0,     0,      0,     "Tx Burst enable polarity"},
+  [mvAsicReg_GPON_TX_BURST_EN_PARAM_MASK]           = {mvAsicReg_GPON_TX_BURST_EN_PARAM_MASK,           MV_ASIC_ONT_GLB_ADDR + 0x1010,   0x1010,   asicRW,     0x000000FF,     16,     0,     0,      0,     "Mask for 8 bits that are added to the end of tx enable signal"},
+  [mvAsicReg_GPON_TX_FDELAY]                        = {mvAsicReg_GPON_TX_FDELAY,                        MV_ASIC_ONT_GLB_ADDR + 0x1014,   0x1014,   asicRW,     0x0000003F,     0,      0,     0,      0,     "Tx final delay"},
+  [mvAsicReg_GPON_TX_PLOAM_DATA_WRITE]              = {mvAsicReg_GPON_TX_PLOAM_DATA_WRITE,              MV_ASIC_ONT_GLB_ADDR + 0x1018,   0x1018,   asicWO,     0xFFFFFFFF,     0,      0,     0,      0,     "Tx PLOAM data fifo"},
+  [mvAsicReg_GPON_TX_PLOAM_DATA_WRITE_FREE]         = {mvAsicReg_GPON_TX_PLOAM_DATA_WRITE_FREE,         MV_ASIC_ONT_GLB_ADDR + 0x101C,   0x101C,   asicRO,     0x000000FF,     0,      0,     0,      0,     "Num of free entry's in Us PLOAM data fifo"},
+  [mvAsicReg_GPON_TX_PLS_CONSTANT]                  = {mvAsicReg_GPON_TX_PLS_CONSTANT,                  MV_ASIC_ONT_GLB_ADDR + 0x1020,   0x1020,   asicRW,     0x000000FF,     0,      0,     0,      0,     "Tx PLS Constant"},
+  [mvAsicReg_GPON_TX_DBR_REPORT_BLOCK_IDX]          = {mvAsicReg_GPON_TX_DBR_REPORT_BLOCK_IDX,          MV_ASIC_ONT_GLB_ADDR + 0x1024,   0x1024,   asicRW,     0x000000FF,     0,      0,     0,      0,     "Tx dbr block index"},
+  [mvAsicReg_GPON_TX_FE_RDI_INDICATION]             = {mvAsicReg_GPON_TX_FE_RDI_INDICATION,             MV_ASIC_ONT_GLB_ADDR + 0x1028,   0x1028,   asicRW,     0x00000001,     0,      0,     0,      0,     "Tx rdi indication for US trans"},
+  [mvAsicReg_GPON_TX_STAT_GEM_PTI1]                 = {mvAsicReg_GPON_TX_STAT_GEM_PTI1,                 MV_ASIC_ONT_GLB_ADDR + 0x102C,   0x102C,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Total num of trans gem frames with pti indication set to 1"},
+  [mvAsicReg_GPON_TX_STAT_GEM_PTI0]                 = {mvAsicReg_GPON_TX_STAT_GEM_PTI0,                 MV_ASIC_ONT_GLB_ADDR + 0x1030,   0x1030,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Total num of trans gem frames with pti indication set to 0"},
+  [mvAsicReg_GPON_TX_STAT_GEM_IDLE]                 = {mvAsicReg_GPON_TX_STAT_GEM_IDLE,                 MV_ASIC_ONT_GLB_ADDR + 0x1034,   0x1034,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Total num of trans idle gem frames"},
+  [mvAsicReg_GPON_TX_STAT_TX_EN_CNT]                = {mvAsicReg_GPON_TX_STAT_TX_EN_CNT,                MV_ASIC_ONT_GLB_ADDR + 0x1038,   0x1038,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "Total num of cycles with tx enable indication asserted"},
+  [mvAsicReg_GPON_TX_CONFIG_EN_THRESHOLD]           = {mvAsicReg_GPON_TX_CONFIG_EN_THRESHOLD,           MV_ASIC_ONT_GLB_ADDR + 0x103C,   0x103C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Saturation threshold for tx enable indication counter"},
+  [mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD]           = {mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD,           MV_ASIC_ONT_GLB_ADDR + 0x1040,   0x1040,   asicRO,     0x00FFFFFF,     0,      0,     0,      0,     "GSE threshold for starting forwarding data to the tx burst fifo"},
+  [mvAsicReg_GPON_TX_CFG_AC_COUPLING]               = {mvAsicReg_GPON_TX_CFG_AC_COUPLING,               MV_ASIC_ONT_GLB_ADDR + 0x104C,   0x104C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Transmit Configuration AC Coupling"},
+  [mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_FRAMES]       = {mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_FRAMES,       MV_ASIC_ONT_GLB_ADDR + 0x10A0,   0x10A0,   asicRO,     0xFFFFFFFF,     0,      8,     1,      0,     "Num of ethernet frames trans via tcont i"},
+  [mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_BYTES]        = {mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_BYTES,        MV_ASIC_ONT_GLB_ADDR + 0x10C8,   0x10C8,   asicRO,     0xFFFFFFFF,     0,      8,     1,      0,     "Num of ethernet payload bytes trans via tcont i"},
+  [mvAsicReg_GPON_TX_STAT_TCONT_i_GEM_FRAMES]       = {mvAsicReg_GPON_TX_STAT_TCONT_i_GEM_FRAMES,       MV_ASIC_ONT_GLB_ADDR + 0x10F0,   0x10F0,   asicRO,     0xFFFFFFFF,     0,      8,     1,      0,     "Num of gem frames trans via tcont i"},
+  [mvAsicReg_GPON_TX_STAT_TCONT_i_IDLE_GEM]         = {mvAsicReg_GPON_TX_STAT_TCONT_i_IDLE_GEM,         MV_ASIC_ONT_GLB_ADDR + 0x1118,   0x1118,   asicRO,     0xFFFFFFFF,     0,      8,     1,      0,     "Num of idle gem frames trans via tcont i"},
+
+  /* =========================== */
+  /*  UTM Registers              */
+  /* =========================== */
+  [mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_ID]          = {mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_ID,          MV_ASIC_ONT_GLB_ADDR + 0x1400,   0x1400,   asicRW,     0x00000FFF,     0,      0,     0,      0,     "Omci gem port Id - upstream direction"},
+  [mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_VALID]       = {mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_VALID,       MV_ASIC_ONT_GLB_ADDR + 0x1404,   0x1404,   asicRW,     0x00000001,     0,      0,     0,      0,     "Omci gem port valid - upstream direction"},
+  [mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD]             = {mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD,             MV_ASIC_ONT_GLB_ADDR + 0x1408,   0x1408,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Num of cycles to pause between two counter gathering sweeps"},
+  [mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD_VALID]       = {mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD_VALID,       MV_ASIC_ONT_GLB_ADDR + 0x140C,   0x140C,   asicRW,     0x00000001,     0,      0,     0,      0,     "Tc period valid"},
+
+  /* =========================== */
+  /*  SGL Registers              */
+  /* =========================== */
+  [mvAsicReg_GPON_SGL_SW_RESET]                     = {mvAsicReg_GPON_SGL_SW_RESET,                     MV_ASIC_ONT_GLB_ADDR + 0x1800,   0x1800,   asicRW,     0x00000001,     0,      0,     0,      0,     "Serdes glue logic - sw reset"},
+  [mvAsicReg_GPON_SGL_CONFIG_REG]                   = {mvAsicReg_GPON_SGL_CONFIG_REG,                   MV_ASIC_ONT_GLB_ADDR + 0x1804,   0x1804,   asicRW,     0x0000000F,     0,      0,     0,      0,     "Serdes glue logic - config"},
+  [mvAsicReg_GPON_SGL_STATS_REG]                    = {mvAsicReg_GPON_SGL_STATS_REG,                    MV_ASIC_ONT_GLB_ADDR + 0x1808,   0x1808,   asicRO,     0x000000FF,     0,      0,     0,      0,     "Serdes glue logic - stats"},
+
+  /* =========================== */
+  /*  Memory Registers           */
+  /* =========================== */
+  [mvAsicReg_GPON_TX_CONST_DATA_RAM]                = {mvAsicReg_GPON_TX_CONST_DATA_RAM,                MV_ASIC_ONT_GLB_ADDR + 0x2000,   0x2000,   asicWO,     0xFFFFFFFF,     0,      8,     1,      0,     "Tx constantant data ram"},
+  [mvAsicReg_GPON_TX_CONST_DATA_RAM_IDLE]           = {mvAsicReg_GPON_TX_CONST_DATA_RAM_IDLE,           MV_ASIC_ONT_GLB_ADDR + 0x2000,   0x2000,   asicWO,     0xFFFFFFFF,     0,      3,     1,      0,     "Tx constantant data - Idle message"},
+  [mvAsicReg_GPON_TX_CONST_DATA_RAM_SN]             = {mvAsicReg_GPON_TX_CONST_DATA_RAM_SN,             MV_ASIC_ONT_GLB_ADDR + 0x2020,   0x2020,   asicWO,     0xFFFFFFFF,     0,      3,     1,      0,     "Tx constantant data - SN message"},
+
+  [mvAsicReg_GPON_GEM_AES_PID_TABLE]                = {mvAsicReg_GPON_GEM_AES_PID_TABLE,                MV_ASIC_ONT_GLB_ADDR + 0x2200,   0x2200,   asicWO,     0xFFFFFFFF,     0,      128,   1,      0,     "Gem AES port Id table"},
+  [mvAsicReg_GPON_GEM_VALID_PID_TABLE]              = {mvAsicReg_GPON_GEM_VALID_PID_TABLE,              MV_ASIC_ONT_GLB_ADDR + 0x2400,   0x2400,   asicWO,     0xFFFFFFFF,     0,      128,   1,      0,     "Gem valid port Id table"},
+
+  [mvAsicReg_GPON_TEST]                             = {mvAsicReg_GPON_TEST,                             MV_ASIC_ONT_GLB_ADDR + 0x0940,   0x0940,   asicRW,     0x03FF03FF,     0,      0,     0,      0,     "Gem valid port Id table"},
+
+  /* =========================== */
+  /*  GEM Port MIB Counters      */
+  /* =========================== */
+  [mvAsicReg_PON_MAC_MIB_COUNTERS_0]                = {mvAsicReg_PON_MAC_MIB_COUNTERS_0,                0xA3000,                         0xA3000,  asicRO,     0xFFFFFFFF,     0,      32,     1,      0,     "PON MAC MIB Counter Set #0"},
+  [mvAsicReg_PON_MAC_MIB_COUNTERS_1]                = {mvAsicReg_PON_MAC_MIB_COUNTERS_1,                0xA3080,                         0xA3080,  asicRO,     0xFFFFFFFF,     0,      32,     1,      0,     "PON MAC MIB Counter Set #1"},
+  [mvAsicReg_PON_MAC_MIB_COUNTERS_2]                = {mvAsicReg_PON_MAC_MIB_COUNTERS_2,                0xA3100,                         0xA3100,  asicRO,     0xFFFFFFFF,     0,      32,     1,      0,     "PON MAC MIB Counter Set #2"},
+  [mvAsicReg_PON_MAC_MIB_COUNTERS_3]                = {mvAsicReg_PON_MAC_MIB_COUNTERS_3,                0xA3180,                         0xA3180,  asicRO,     0xFFFFFFFF,     0,      32,     1,      0,     "PON MAC MIB Counter Set #3"},
+  [mvAsicReg_PON_MAC_MIB_COUNTERS_4]                = {mvAsicReg_PON_MAC_MIB_COUNTERS_4,                0xA3200,                         0xA3200,  asicRO,     0xFFFFFFFF,     0,      32,     1,      0,     "PON MAC MIB Counter Set #4"},
+  [mvAsicReg_PON_MAC_MIB_COUNTERS_5]                = {mvAsicReg_PON_MAC_MIB_COUNTERS_5,                0xA3280,                         0xA3280,  asicRO,     0xFFFFFFFF,     0,      32,     1,      0,     "PON MAC MIB Counter Set #5"},
+  [mvAsicReg_PON_MAC_MIB_COUNTERS_6]                = {mvAsicReg_PON_MAC_MIB_COUNTERS_6,                0xA3300,                         0xA3300,  asicRO,     0xFFFFFFFF,     0,      32,     1,      0,     "PON MAC MIB Counter Set #6"},
+  [mvAsicReg_PON_MAC_MIB_COUNTERS_7]                = {mvAsicReg_PON_MAC_MIB_COUNTERS_7,                0xA3380,                         0xA3380,  asicRO,     0xFFFFFFFF,     0,      32,     1,      0,     "PON MAC MIB Counter Set #7"},
+
+  [mvAsicReg_RX_MIB_CTRL]                           = {mvAsicReg_RX_MIB_CTRL,                           0xA3800,                         0xA3800,  asicRW,     0xFFFFFFFF,     0,      32,     1,      0,     "RX MIB Control table"},
+  [mvAsicReg_RX_MIB_DEFAULT]                        = {mvAsicReg_RX_MIB_DEFAULT,                        0xA3880,                         0xA3880,  asicRW,     0xFFFFFFFF,     0,      0,      0,      0,     "RX MIB Default"},
+
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           =========   =========   =========   ===       ==           == */
+/* ==           =========   =========   =========   ====      ==           == */
+/* ==           ==          ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==          ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           =========   =========   ==     ==   ==   ==   ==           == */
+/* ==           =========   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==          ==          ==     ==   ==     == ==           == */
+/* ==           ==          ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+
+  /* =========================== */
+  /*  EPON Interrupt Registers   */
+  /* =========================== */
+  [mvAsicReg_EPON_INTR_REG]                         = {mvAsicReg_EPON_INTR_REG,                         MV_ASIC_ONT_GLB_ADDR + 0x0000,   0x0000,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Interrupt PON"},
+  [mvAsicReg_EPON_INTR_MASK]                        = {mvAsicReg_EPON_INTR_MASK,                        MV_ASIC_ONT_GLB_ADDR + 0x0004,   0x0004,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Interrupt PON Mask"},
+
+  /* =========================== */
+  /*  EPON General Registers     */
+  /* =========================== */
+  [mvAsicReg_EPON_GEN_MAC_VERSION_ADDR]             = {mvAsicReg_EPON_GEN_MAC_VERSION_ADDR,             MV_ASIC_ONT_GLB_ADDR + 0x0400,   0x0400,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "EPON MAC version"},
+  [mvAsicReg_EPON_GEN_ONT_ENABLE]                   = {mvAsicReg_EPON_GEN_ONT_ENABLE,                   MV_ASIC_ONT_GLB_ADDR + 0x040C,   0x040C,   asicRW,     0x0000FF01,     0,      0,     0,      0,     "ONU Rx/Tx Enable"},
+  [mvAsicReg_EPON_GEN_ONT_RX_ENABLE]                = {mvAsicReg_EPON_GEN_ONT_RX_ENABLE,                MV_ASIC_ONT_GLB_ADDR + 0x040C,   0x040C,   asicRW,     0x00000001,     0,      0,     0,      0,     "ONU Rx Enable"},
+  [mvAsicReg_EPON_GEN_ONT_TX_ENABLE]                = {mvAsicReg_EPON_GEN_ONT_TX_ENABLE,                MV_ASIC_ONT_GLB_ADDR + 0x040C,   0x040C,   asicRW,     0x000000FF,     8,      0,     0,      0,     "ONU Tx Enable"},
+#ifdef PON_Z1
+  [mvAsicReg_EPON_GEN_ONT_STATE]                    = {mvAsicReg_EPON_GEN_ONT_STATE,                    MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x00000003,     0,      0,     0,      0,     "ONU State"},
+  [mvAsicReg_EPON_GEN_ONT_STATE_REG_AUTO_EN]        = {mvAsicReg_EPON_GEN_ONT_STATE_REG_AUTO_EN,        MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x00000001,     1,      0,     0,      0,     "ONU Register State Auto Enable"},
+  [mvAsicReg_EPON_GEN_ONT_STATE_REG]                = {mvAsicReg_EPON_GEN_ONT_STATE_REG,                MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x00000001,     0,      0,     0,      0,     "ONU Register State"},
+#else /* PON_Z2 */
+  [mvAsicReg_EPON_GEN_ONT_STATE]                    = {mvAsicReg_EPON_GEN_ONT_STATE,                    MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x00000FFF,     0,      0,     0,      0,     "ONU State"},
+  [mvAsicReg_EPON_GEN_ONT_STATE_REG]                = {mvAsicReg_EPON_GEN_ONT_STATE_REG,                MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x000000FF,     0,      0,     0,      0,     "ONU Register State"},
+  [mvAsicReg_EPON_GEN_ONT_STATE_REG_AUTO_EN]        = {mvAsicReg_EPON_GEN_ONT_STATE_REG_AUTO_EN,        MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x00000001,     8,      0,     0,      0,     "ONU Register State Auto Enable"},
+#endif /* PON_Z2  */
+  [mvAsicReg_EPON_GEN_ONT_STATE_REREG_AUTO_EN]      = {mvAsicReg_EPON_GEN_ONT_STATE_REREG_AUTO_EN,      MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x00000001,     9,      0,     0,      0,     "ONU ReRegister State Auto Enable"},
+  [mvAsicReg_EPON_GEN_ONT_STATE_DEREG_AUTO_EN]      = {mvAsicReg_EPON_GEN_ONT_STATE_DEREG_AUTO_EN,      MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x00000001,    10,      0,     0,      0,     "ONU DeRegister State Auto Enable"},
+  [mvAsicReg_EPON_GEN_ONT_STATE_NACK_AUTO_EN]       = {mvAsicReg_EPON_GEN_ONT_STATE_NACK_AUTO_EN,       MV_ASIC_ONT_GLB_ADDR + 0x0410,   0x0410,   asicRW,     0x00000001,    11,      0,     0,      0,     "ONU Nack State Auto Enable"},
+  [mvAsicReg_EPON_GEN_TQ_SIZE]                      = {mvAsicReg_EPON_GEN_TQ_SIZE,                      MV_ASIC_ONT_GLB_ADDR + 0x0414,   0x0414,   asicRW,     0x000000FF,     0,      0,     0,      0,     "TQ Size"},
+  [mvAsicReg_EPON_GEN_LASER_PARAM]                  = {mvAsicReg_EPON_GEN_LASER_PARAM,                  MV_ASIC_ONT_GLB_ADDR + 0x0418,   0x0418,   asicRW,     0x01FFFFFF,     0,      0,     0,      0,     "Laser Params"},
+  [mvAsicReg_EPON_GEN_TAIL_GUARD]                   = {mvAsicReg_EPON_GEN_TAIL_GUARD,                   MV_ASIC_ONT_GLB_ADDR + 0x0420,   0x0420,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "Tail Guard"},
+  [mvAsicReg_EPON_GEN_SYNC_TIME]                    = {mvAsicReg_EPON_GEN_SYNC_TIME,                    MV_ASIC_ONT_GLB_ADDR + 0x0424,   0x0424,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Sync Time"},
+  [mvAsicReg_EPON_GEN_BROADCAST_ADDR_LOW]           = {mvAsicReg_EPON_GEN_BROADCAST_ADDR_LOW,           MV_ASIC_ONT_GLB_ADDR + 0x0428,   0x0428,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Broadcast Address Low"},
+  [mvAsicReg_EPON_GEN_BROADCAST_ADDR_HIGH]          = {mvAsicReg_EPON_GEN_BROADCAST_ADDR_HIGH,          MV_ASIC_ONT_GLB_ADDR + 0x042C,   0x042C,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "Broadcast Address High"},
+#ifdef PON_Z1
+  [mvAsicReg_EPON_GEN_CONFIGURATION]                = {mvAsicReg_EPON_GEN_CONFIGURATION,                MV_ASIC_ONT_GLB_ADDR + 0x0430,   0x0430,   asicRW,     0x00000073,     0,      0,     0,      0,     "Gen Configuration"},
+#else /* PON_Z2 */
+  [mvAsicReg_EPON_GEN_CONFIGURATION]                = {mvAsicReg_EPON_GEN_CONFIGURATION,                MV_ASIC_ONT_GLB_ADDR + 0x0430,   0x0430,   asicRW,     0x0000FF73,     0,      0,     0,      0,     "Gen Configuration"},
+  [mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_REPORT]    = {mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_REPORT,    MV_ASIC_ONT_GLB_ADDR + 0x0430,   0x0430,   asicRW,     0x00000001,     4,      0,     0,      0,     "Gen Configuration Auto Report"},
+  [mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_ACK]       = {mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_ACK,       MV_ASIC_ONT_GLB_ADDR + 0x0430,   0x0430,   asicRW,     0x00000001,     5,      0,     0,      0,     "Gen Configuration Auto Ack"},
+  [mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_REQUEST]   = {mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_REQUEST,   MV_ASIC_ONT_GLB_ADDR + 0x0430,   0x0430,   asicRW,     0x00000001,     6,      0,     0,      0,     "Gen Configuration Auto Request"},
+
+
+#endif /* PON_Z2  */
+  [mvAsicReg_EPON_GEN_SLD]                          = {mvAsicReg_EPON_GEN_SLD,                          MV_ASIC_ONT_GLB_ADDR + 0x0434,   0x0434,   asicRW,     0x000000FF,     0,      0,     0,      0,     "Sld"},
+  [mvAsicReg_EPON_GEN_MAC_CONTROL_TYPE]             = {mvAsicReg_EPON_GEN_MAC_CONTROL_TYPE,             MV_ASIC_ONT_GLB_ADDR + 0x0438,   0x0438,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "Mac Control type"},
+  [mvAsicReg_EPON_GEN_LOCAL_TIMESTAMP]              = {mvAsicReg_EPON_GEN_LOCAL_TIMESTAMP,              MV_ASIC_ONT_GLB_ADDR + 0x043C,   0x043C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Local TimeStamp"},
+  [mvAsicReg_EPON_GEN_NUM_OF_PENDING_GRANTS]        = {mvAsicReg_EPON_GEN_NUM_OF_PENDING_GRANTS,        MV_ASIC_ONT_GLB_ADDR + 0x0448,   0x0448,   asicRW,     0x000000FF,     0,      0,     0,      0,     "Num Of Pending Grants"},
+  [mvAsicReg_EPON_GEN_SGL_STATUS]                   = {mvAsicReg_EPON_GEN_SGL_STATUS,                   MV_ASIC_ONT_GLB_ADDR + 0x044C,   0x044C,   asicRW,     0x000000FF,     0,      0,     0,      0,     "SGL Status"},
+  [mvAsicReg_EPON_GEN_PON_PHY_DEBUG]                = {mvAsicReg_EPON_GEN_PON_PHY_DEBUG,                MV_ASIC_ONT_GLB_ADDR + 0x0450,   0x0450,   asicRW,     0x000000FF,     0,      0,     0,      0,     "Phy Debug"},
+  [mvAsicReg_EPON_GEN_SGL_SW_RESET]                 = {mvAsicReg_EPON_GEN_SGL_SW_RESET,                 MV_ASIC_ONT_GLB_ADDR + 0x0454,   0x0454,   asicRW,     0x00000001,     0,      0,     0,      0,     "SGL SW Reset"},
+  [mvAsicReg_EPON_GEN_SGL_CONFIG]                   = {mvAsicReg_EPON_GEN_SGL_CONFIG,                   MV_ASIC_ONT_GLB_ADDR + 0x0458,   0x0458,   asicRW,     0x0000001F,     0,      0,     0,      0,     "SGL Config"},
+  [mvAsicReg_EPON_GEN_SGL_DEBOUNCE_CONFIG]          = {mvAsicReg_EPON_GEN_SGL_DEBOUNCE_CONFIG,          MV_ASIC_ONT_GLB_ADDR + 0x045C,   0x045C,   asicRW,     0x0001FFFF,     0,      0,     0,      0,     "SGL Debounce Config"},
+  [mvAsicReg_EPON_GEN_SGL_DEBOUNCE_ENABLE]          = {mvAsicReg_EPON_GEN_SGL_DEBOUNCE_ENABLE,          MV_ASIC_ONT_GLB_ADDR + 0x0460,   0x0460,   asicRW,     0x00000001,     0,      0,     0,      0,     "SGL Debounce Enable"},
+  [mvAsicReg_EPON_GEN_TCH_CHURNING_KEY]             = {mvAsicReg_EPON_GEN_TCH_CHURNING_KEY,             MV_ASIC_ONT_GLB_ADDR + 0x0464,   0x0464,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "Churning Key random for SW"},
+  [mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE1]           = {mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE1,           MV_ASIC_ONT_GLB_ADDR + 0x0468,   0x0468,   asicRW,     0x001FFFFF,     0,      0,     0,      0,     "Additional Opcode 01"},
+  [mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE2]           = {mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE2,           MV_ASIC_ONT_GLB_ADDR + 0x046C,   0x046C,   asicRW,     0x001FFFFF,     0,      0,     0,      0,     "Additional Opcode 02"},
+  [mvAsicReg_EPON_GEN_DRIFT_THRESHOLD]              = {mvAsicReg_EPON_GEN_DRIFT_THRESHOLD,              MV_ASIC_ONT_GLB_ADDR + 0x0470,   0x0470,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "Drift Threshold"},
+  [mvAsicReg_EPON_GEN_TIMESTAMP_VAL_FOR_INTR]       = {mvAsicReg_EPON_GEN_TIMESTAMP_VAL_FOR_INTR,       MV_ASIC_ONT_GLB_ADDR + 0x0474,   0x0474,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Timestamp valuer for interrupt"},
+  [mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE3]           = {mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE3,           MV_ASIC_ONT_GLB_ADDR + 0x0478,   0x0478,   asicRW,     0x001FFFFF,     0,      0,     0,      0,     "Additional Opcode 03"},
+#ifdef PON_Z2
+  [mvAsicReg_EPON_GEN_LLID_CRC_CONFIG]              = {mvAsicReg_EPON_GEN_LLID_CRC_CONFIG,              MV_ASIC_ONT_GLB_ADDR + 0x047C,   0x047C,   asicRW,     0x000003FF,     0,      0,     0,      0,     "LLID configuration"},
+  [mvAsicReg_EPON_GEN_TIMESTAMP_CONFIG]             = {mvAsicReg_EPON_GEN_TIMESTAMP_CONFIG,             MV_ASIC_ONT_GLB_ADDR + 0x0480,   0x0480,   asicRW,     0x87FFC7FF,     0,      0,     0,      0,     "Timestamp configuration"},
+  [mvAsicReg_EPON_GEN_ONT_RX_TIMESTAMP_CONFIG]      = {mvAsicReg_EPON_GEN_ONT_RX_TIMESTAMP_CONFIG,      MV_ASIC_ONT_GLB_ADDR + 0x0484,   0x0484,   asicRW,     0x00008FFF,     0,      0,     0,      0,     "ONT Rx Timestamp configuration"},
+  [mvAsicReg_EPON_GEN_ONT_REGISTER_PACKET_PADDING]  = {mvAsicReg_EPON_GEN_ONT_REGISTER_PACKET_PADDING,  MV_ASIC_ONT_GLB_ADDR + 0x0488,   0x0488,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "ONT Register packet pading"},
+#endif /* PON_Z2 */
+#ifdef PON_Z1
+  [mvAsicReg_EPON_GEN_MAC_ADDR_LOW]                 = {mvAsicReg_EPON_GEN_MAC_ADDR_LOW,                 MV_ASIC_ONT_GLB_ADDR + 0x0440,   0x0440,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "MAC address low part"},
+  [mvAsicReg_EPON_GEN_MAC_ADDR_HIGH]                = {mvAsicReg_EPON_GEN_MAC_ADDR_HIGH,                MV_ASIC_ONT_GLB_ADDR + 0x0444,   0x0444,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "MAC address high part"},
+#else /* PON_Z2 */
+  [mvAsicReg_EPON_GEN_MAC_ADDR_LOW]                 = {mvAsicReg_EPON_GEN_MAC_ADDR_LOW,                 MV_ASIC_ONT_GLB_ADDR + 0x04A0,   0x04A0,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "MAC address low part"},
+  [mvAsicReg_EPON_GEN_MAC_ADDR_HIGH]                = {mvAsicReg_EPON_GEN_MAC_ADDR_HIGH,                MV_ASIC_ONT_GLB_ADDR + 0x04C8,   0x04C8,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "MAC address high part"},
+#endif /* PON_Z2 */
+  [mvAsicReg_EPON_GEN_UTM_TC_PERIOD]                = {mvAsicReg_EPON_GEN_UTM_TC_PERIOD,                MV_ASIC_ONT_GLB_ADDR + 0x0720,   0x0720,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "UTM TC Period"},
+  [mvAsicReg_EPON_GEN_UTM_TC_PERIOD_VALID]          = {mvAsicReg_EPON_GEN_UTM_TC_PERIOD_VALID,          MV_ASIC_ONT_GLB_ADDR + 0x0724,   0x0724,   asicRW,     0x00000001,     0,      0,     0,      0,     "UTM TC Period valid"},
+  [mvAsicReg_EPON_GEN_GEM_IPG_VAL]                  = {mvAsicReg_EPON_GEN_GEM_IPG_VAL,                  MV_ASIC_ONT_GLB_ADDR + 0x0728,   0x0728,   asicRW,     0x000000FF,     0,      0,     0,      0,     "IPG Value"},
+  [mvAsicReg_EPON_GEN_GEM_IPG_VAL_VALID]            = {mvAsicReg_EPON_GEN_GEM_IPG_VAL_VALID,            MV_ASIC_ONT_GLB_ADDR + 0x072C,   0x072C,   asicRW,     0x00000001,     0,      0,     0,      0,     "IPG Value valid"},
+
+  /* =========================== */
+  /*  EPON RXP Registers         */
+  /* =========================== */
+  [mvAsicReg_EPON_RXP_PACKET_SIZE_LIMIT]            = {mvAsicReg_EPON_RXP_PACKET_SIZE_LIMIT,            MV_ASIC_ONT_GLB_ADDR + 0x0810,   0x0810,   asicRW,     0x0FFF0FFF,     0,      0,     0,      0,     "Rxp packet limit size"},
+#ifdef PON_Z1
+  [mvAsicReg_EPON_RXP_PACKET_FILTER]                = {mvAsicReg_EPON_RXP_PACKET_FILTER,                MV_ASIC_ONT_GLB_ADDR + 0x0814,   0x0814,   asicRW,     0x000000FF,     0,      0,     0,      0,     "Rxp packet filter"},
+#else /* PON_Z2 and higher */
+  [mvAsicReg_EPON_RXP_PACKET_FILTER]                = {mvAsicReg_EPON_RXP_PACKET_FILTER,                MV_ASIC_ONT_GLB_ADDR + 0x0814,   0x0814,   asicRW,     0x000001FF,     0,      0,     0,      0,     "Rxp packet filter"},
+#endif /* PON_Z2 and higher */
+  [mvAsicReg_EPON_RXP_CTRL_FRAME_FORWARD]           = {mvAsicReg_EPON_RXP_CTRL_FRAME_FORWARD,           MV_ASIC_ONT_GLB_ADDR + 0x0818,   0x0818,   asicRW,     0x0000003F,     0,      0,     0,      0,     "Rxp ctrl frame forward"},
+  [mvAsicReg_EPON_RXP_LLT_LLID_DATA]                = {mvAsicReg_EPON_RXP_LLT_LLID_DATA,                MV_ASIC_ONT_GLB_ADDR + 0x081C,   0x081C,   asicRW,     0x000FFFFF,     0,     10,     1,      0,     "Rxp LLID data"},
+  [mvAsicReg_EPON_RXP_LLT_LLID_DATA_VALUE]          = {mvAsicReg_EPON_RXP_LLT_LLID_DATA_VALUE,          MV_ASIC_ONT_GLB_ADDR + 0x081C,   0x081C,   asicRW,     0x00007FFF,     0,     10,     1,      0,     "Rxp LLID data value"},
+  [mvAsicReg_EPON_RXP_LLT_LLID_DATA_INDEX]          = {mvAsicReg_EPON_RXP_LLT_LLID_DATA_INDEX,          MV_ASIC_ONT_GLB_ADDR + 0x081C,   0x081C,   asicRW,     0x0000000F,    18,     10,     1,      0,     "Rxp LLID data index"},
+  [mvAsicReg_EPON_RXP_LLT_LLID_DATA_VALID]          = {mvAsicReg_EPON_RXP_LLT_LLID_DATA_VALID,          MV_ASIC_ONT_GLB_ADDR + 0x081C,   0x081C,   asicRW,     0x00000001,    19,     10,     1,      0,     "Rxp LLID data valid"},
+  [mvAsicReg_EPON_RXP_ENCRYPTION_CONFIG]            = {mvAsicReg_EPON_RXP_ENCRYPTION_CONFIG,            MV_ASIC_ONT_GLB_ADDR + 0x0844,   0x0844,   asicRW,     0x00000031,     0,      0,     0,      0,     "Rxp Enctyption Config"},
+#ifdef PON_Z1
+  [mvAsicReg_EPON_RXP_ENCRYPTION_KEY0]              = {mvAsicReg_EPON_RXP_ENCRYPTION_KEY0,              MV_ASIC_ONT_GLB_ADDR + 0x0848,   0x0848,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "Rxp Enctyption Key 0"},
+  [mvAsicReg_EPON_RXP_ENCRYPTION_KEY1]              = {mvAsicReg_EPON_RXP_ENCRYPTION_KEY1,              MV_ASIC_ONT_GLB_ADDR + 0x084C,   0x084C,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "Rxp Enctyption Key 1"},
+#else /* PON_Z2 and higher */
+  [mvAsicReg_EPON_RXP_ENCRYPTION_KEY0]              = {mvAsicReg_EPON_RXP_ENCRYPTION_KEY0,              MV_ASIC_ONT_GLB_ADDR + 0x0850,   0x0850,   asicRW,     0x00FFFFFF,     0,      8,     1,      0,     "Rxp Enctyption Key 0"},
+  [mvAsicReg_EPON_RXP_ENCRYPTION_KEY1]              = {mvAsicReg_EPON_RXP_ENCRYPTION_KEY1,              MV_ASIC_ONT_GLB_ADDR + 0x0878,   0x0878,   asicRW,     0x00FFFFFF,     0,      8,     1,      0,     "Rxp Enctyption Key 1"},
+#endif /* PON_Z2 and higher */
+  [mvAsicReg_EPON_RXP_DATA_FIFO_THRESH]             = {mvAsicReg_EPON_RXP_DATA_FIFO_THRESH,             MV_ASIC_ONT_GLB_ADDR + 0x08C0,   0x08C0,   asicRW,     0x00000FFF,     0,      8,     1,      0,     "Rxp FIFO Threshold"},
+
+  /* =========================== */
+  /*  EPON GPM Registers         */
+  /* =========================== */
+  [mvAsicReg_EPON_GPM_MAX_FUTURE_GRANT_TIME]        = {mvAsicReg_EPON_GPM_MAX_FUTURE_GRANT_TIME,        MV_ASIC_ONT_GLB_ADDR + 0x0C10,   0x0C10,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Max future grant time"},
+#ifdef PON_Z1
+  [mvAsicReg_EPON_GPM_MIN_PROCESSING_TIME]          = {mvAsicReg_EPON_GPM_MIN_PROCESSING_TIME,          MV_ASIC_ONT_GLB_ADDR + 0x0C14,   0x0C14,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "Min processing time"},
+#else /* PON_Z2 */
+  [mvAsicReg_EPON_GPM_MIN_PROCESSING_TIME]          = {mvAsicReg_EPON_GPM_MIN_PROCESSING_TIME,          MV_ASIC_ONT_GLB_ADDR + 0x0C14,   0x0C14,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "Min processing time"},
+#endif /* PON_Z2  */
+  [mvAsicReg_EPON_GPM_DISCOVERY_GRANT_LENGTH]       = {mvAsicReg_EPON_GPM_DISCOVERY_GRANT_LENGTH,       MV_ASIC_ONT_GLB_ADDR + 0x0C18,   0x0C18,   asicRW,     0x0FFFFFFF,     0,      0,     0,      0,     "Discovery grant length"},
+  [mvAsicReg_EPON_GPM_RX_SYNC_TIME]                 = {mvAsicReg_EPON_GPM_RX_SYNC_TIME,                 MV_ASIC_ONT_GLB_ADDR + 0x0C1C,   0x0C1C,   asicRW,     0x0001FFFF,     0,      0,     0,      0,     "Rx sync time"},
+  [mvAsicReg_EPON_GPM_GRANT_VALID]                  = {mvAsicReg_EPON_GPM_GRANT_VALID,                  MV_ASIC_ONT_GLB_ADDR + 0x0C50,   0x0C50,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Grant valid counter"},
+  [mvAsicReg_EPON_GPM_GRANT_MAX_FUTURE_TIME_ERR]    = {mvAsicReg_EPON_GPM_GRANT_MAX_FUTURE_TIME_ERR,    MV_ASIC_ONT_GLB_ADDR + 0x0C70,   0x0C70,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Grant max future time error counter"},
+  [mvAsicReg_EPON_GPM_MIN_PROC_TIME_ERR]            = {mvAsicReg_EPON_GPM_MIN_PROC_TIME_ERR,            MV_ASIC_ONT_GLB_ADDR + 0x0C90,   0x0C90,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Min proc time error counter"},
+  [mvAsicReg_EPON_GPM_LENGTH_ERR]                   = {mvAsicReg_EPON_GPM_LENGTH_ERR,                   MV_ASIC_ONT_GLB_ADDR + 0x0CB0,   0x0CB0,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Length error counter"},
+  [mvAsicReg_EPON_GPM_DISCOVERY_AND_REGISTERED_ERR] = {mvAsicReg_EPON_GPM_DISCOVERY_AND_REGISTERED_ERR, MV_ASIC_ONT_GLB_ADDR + 0x0CD0,   0x0CD0,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Discovery and register error counter"},
+  [mvAsicReg_EPON_GPM_FIFO_FULL_ERR]                = {mvAsicReg_EPON_GPM_FIFO_FULL_ERR,                MV_ASIC_ONT_GLB_ADDR + 0x0CF0,   0x0CF0,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Fifo full error counter"},
+  [mvAsicReg_EPON_GPM_OPC_DISC_NOT_REG_BCAST]       = {mvAsicReg_EPON_GPM_OPC_DISC_NOT_REG_BCAST,       MV_ASIC_ONT_GLB_ADDR + 0x0D10,   0x0D10,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "OPC discard not register broadcast counter"},
+  [mvAsicReg_EPON_GPM_OPC_REG_NOT_DISC]             = {mvAsicReg_EPON_GPM_OPC_REG_NOT_DISC,             MV_ASIC_ONT_GLB_ADDR + 0x0D30,   0x0D30,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "OPC register not broadcast counter"},
+  [mvAsicReg_EPON_GPM_OPC_DISC_NOT_REG_NOT_BCAST]   = {mvAsicReg_EPON_GPM_OPC_DISC_NOT_REG_NOT_BCAST,   MV_ASIC_ONT_GLB_ADDR + 0x0D50,   0x0D50,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "OPC discard not register not broadcast counter"},
+  [mvAsicReg_EPON_GPM_OPC_DROPED_GRANT]             = {mvAsicReg_EPON_GPM_OPC_DROPED_GRANT,             MV_ASIC_ONT_GLB_ADDR + 0x0D70,   0x0D70,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "OPC dropped grant counter"},
+  [mvAsicReg_EPON_GPM_OPC_HIDDEN_GRANT]             = {mvAsicReg_EPON_GPM_OPC_HIDDEN_GRANT,             MV_ASIC_ONT_GLB_ADDR + 0x0D90,   0x0D90,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "OPC hidden grant counter"},
+  [mvAsicReg_EPON_GPM_OPC_BACK_TO_BACK_GRANT]       = {mvAsicReg_EPON_GPM_OPC_BACK_TO_BACK_GRANT,       MV_ASIC_ONT_GLB_ADDR + 0x0DB0,   0x0DB0,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "OPC back to back grant counter"},
+
+  /* =========================== */
+  /*  EPON TXM Registers         */
+  /* =========================== */
+#ifdef PON_Z1
+  [mvAsicReg_EPON_TXM_DEFAULT_OVERHEAD]             = {mvAsicReg_EPON_TXM_DEFAULT_OVERHEAD,             MV_ASIC_ONT_GLB_ADDR + 0x1010,   0x1010,   asicRW,     0x000000FF,     0,      0,     0,      0,     "Default overhead"},
+  [mvAsicReg_EPON_TXM_CONFIGURATION]                = {mvAsicReg_EPON_TXM_CONFIGURATION,                MV_ASIC_ONT_GLB_ADDR + 0x1018,   0x1018,   asicRW,     0x00000007,     0,      0,     0,      0,     "Tx Configuration"},
+  [mvAsicReg_EPON_TXM_TX_LLID]                      = {mvAsicReg_EPON_TXM_TX_LLID,                      MV_ASIC_ONT_GLB_ADDR + 0x1014,   0x1014,   asicRW,     0x00007FFF,     0,      0,     0,      0,     "Tx LLID"},
+#else /* PON_Z2 and higher */
+  [mvAsicReg_EPON_TXM_DEFAULT_OVERHEAD]             = {mvAsicReg_EPON_TXM_DEFAULT_OVERHEAD,             MV_ASIC_ONT_GLB_ADDR + 0x1010,   0x1010,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "Default overhead"},
+  [mvAsicReg_EPON_TXM_CONFIGURATION]                = {mvAsicReg_EPON_TXM_CONFIGURATION,                MV_ASIC_ONT_GLB_ADDR + 0x1018,   0x1018,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "Tx Configuration"},
+  [mvAsicReg_EPON_TXM_TX_LLID]                      = {mvAsicReg_EPON_TXM_TX_LLID,                      MV_ASIC_ONT_GLB_ADDR + 0x1050,   0x1050,   asicRW,     0x00007FFF,     0,      8,     1,      0,     "Tx LLID"},
+#endif /* PON_Z2 and higher */
+#ifdef PON_Z1
+  [mvAsicReg_EPON_TXM_CPP_RPRT_CONFIG]              = {mvAsicReg_EPON_TXM_CPP_RPRT_CONFIG,              MV_ASIC_ONT_GLB_ADDR + 0x1078,   0x1078,   asicRW,     0x000003FF,     0,      8,     1,      0,     "Cpp report configuration"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP]             = {mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP,             MV_ASIC_ONT_GLB_ADDR + 0x1098,   0x1098,   asicRW,     0x000000FF,     0,      8,     1,      0,     "Cpp report bit map"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET]           = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET,           MV_ASIC_ONT_GLB_ADDR + 0x10B8,   0x10B8,   asicRW,     0x0000003F,     0,      8,     1,      0,     "Cpp report queue sets"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0,             MV_ASIC_ONT_GLB_ADDR + 0x10D8,   0x10D8,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report queue0"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1,             MV_ASIC_ONT_GLB_ADDR + 0x10F8,   0x10F8,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report queue1"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2,             MV_ASIC_ONT_GLB_ADDR + 0x1118,   0x1118,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report queue2"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3,             MV_ASIC_ONT_GLB_ADDR + 0x1138,   0x1138,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report queue3"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4,             MV_ASIC_ONT_GLB_ADDR + 0x1158,   0x1158,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report queue4"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5,             MV_ASIC_ONT_GLB_ADDR + 0x1178,   0x1178,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report queue5"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6,             MV_ASIC_ONT_GLB_ADDR + 0x1198,   0x1198,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report queue6"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7,             MV_ASIC_ONT_GLB_ADDR + 0x11B8,   0x11B8,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report queue7"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_FEC_CONFIG]          = {mvAsicReg_EPON_TXM_CPP_RPRT_FEC_CONFIG,          MV_ASIC_ONT_GLB_ADDR + 0x11DC,   0x11DC,   asicRW,     0x00FFFFFF,     0,      8,     1,      0,     "Cpp report fec config"},
+#else /* PON_Z2 and higher */
+  [mvAsicReg_EPON_TXM_CPP_RPRT_CONFIG]              = {mvAsicReg_EPON_TXM_CPP_RPRT_CONFIG,              MV_ASIC_ONT_GLB_ADDR + 0x1078,   0x1078,   asicRW,     0x03FD03FF,     0,      8,     1,      0,     "Cpp report configuration"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP]             = {mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP,             MV_ASIC_ONT_GLB_ADDR + 0x1098,   0x1098,   asicRW,     0x0000FFFF,     0,      8,     1,      0,     "Cpp report bit map"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET]           = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET,           MV_ASIC_ONT_GLB_ADDR + 0x10B8,   0x10B8,   asicRW,     0x0000003F,     0,      8,     1,      0,     "Cpp report queue sets"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0,             MV_ASIC_ONT_GLB_ADDR + 0x10D8,   0x10D8,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Cpp report queue0"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1,             MV_ASIC_ONT_GLB_ADDR + 0x10F8,   0x10F8,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Cpp report queue1"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2,             MV_ASIC_ONT_GLB_ADDR + 0x1118,   0x1118,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Cpp report queue2"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3,             MV_ASIC_ONT_GLB_ADDR + 0x1138,   0x1138,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Cpp report queue3"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4,             MV_ASIC_ONT_GLB_ADDR + 0x1158,   0x1158,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Cpp report queue4"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5,             MV_ASIC_ONT_GLB_ADDR + 0x1178,   0x1178,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Cpp report queue5"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6,             MV_ASIC_ONT_GLB_ADDR + 0x1198,   0x1198,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Cpp report queue6"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7]             = {mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7,             MV_ASIC_ONT_GLB_ADDR + 0x11B8,   0x11B8,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "Cpp report queue7"},
+  [mvAsicReg_EPON_TXM_CPP_RPRT_FEC_CONFIG]          = {mvAsicReg_EPON_TXM_CPP_RPRT_FEC_CONFIG,          MV_ASIC_ONT_GLB_ADDR + 0x11DC,   0x11DC,   asicRW,     0x00FFFFFF,     0,      8,     1,      0,     "Cpp report fec config"},
+#endif /* PON_Z2  and higher */
+
+  /* =========================== */
+  /*  EPON PCS Registers         */
+  /* =========================== */
+  [mvAsicReg_EPON_PCS_CONFIGURATION]                = {mvAsicReg_EPON_PCS_CONFIGURATION,                MV_ASIC_ONT_GLB_ADDR + 0x1414,   0x1414,   asicRW,     0x00000033,     0,      0,     0,      0,     "PCS configuration"},
+  [mvAsicReg_EPON_PCS_DELAY_CONFIG]                 = {mvAsicReg_EPON_PCS_DELAY_CONFIG,                 MV_ASIC_ONT_GLB_ADDR + 0x1418,   0x1418,   asicRW,     0x00001FFF,     0,      0,     0,      0,     "PCS delay config"},
+  [mvAsicReg_EPON_PCS_STATS_FEC_0]                  = {mvAsicReg_EPON_PCS_STATS_FEC_0,                  MV_ASIC_ONT_GLB_ADDR + 0x141C,   0x141C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats Fec 0"},
+  [mvAsicReg_EPON_PCS_STATS_FEC_1]                  = {mvAsicReg_EPON_PCS_STATS_FEC_1,                  MV_ASIC_ONT_GLB_ADDR + 0x1420,   0x1420,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats Fec 1"},
+  [mvAsicReg_EPON_PCS_STATS_FEC_2]                  = {mvAsicReg_EPON_PCS_STATS_FEC_2,                  MV_ASIC_ONT_GLB_ADDR + 0x1424,   0x1424,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "PCS stats Fec 2"},
+  [mvAsicReg_EPON_PCS_STATS_0]                      = {mvAsicReg_EPON_PCS_STATS_0,                      MV_ASIC_ONT_GLB_ADDR + 0x1428,   0x1428,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats 0"},
+  [mvAsicReg_EPON_PCS_STATS_1]                      = {mvAsicReg_EPON_PCS_STATS_1,                      MV_ASIC_ONT_GLB_ADDR + 0x142C,   0x142C,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats 1"},
+  [mvAsicReg_EPON_PCS_STATS_2]                      = {mvAsicReg_EPON_PCS_STATS_2,                      MV_ASIC_ONT_GLB_ADDR + 0x1430,   0x1430,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats 2"},
+  [mvAsicReg_EPON_PCS_STATS_3]                      = {mvAsicReg_EPON_PCS_STATS_3,                      MV_ASIC_ONT_GLB_ADDR + 0x1434,   0x1434,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats 3"},
+  [mvAsicReg_EPON_PCS_STATS_4]                      = {mvAsicReg_EPON_PCS_STATS_4,                      MV_ASIC_ONT_GLB_ADDR + 0x1438,   0x1438,   asicRO,     0xFFFFFFFF,     0,      0,     0,      0,     "PCS stats 4"},
+  [mvAsicReg_EPON_PCS_FRAME_SZ_LIMITS]              = {mvAsicReg_EPON_PCS_FRAME_SZ_LIMITS,              MV_ASIC_ONT_GLB_ADDR + 0x143C,   0x143C,   asicRW,     0x1FFF0FFF,     0,      0,     0,      0,     "PCS Frame Size Limits"},
+
+  /* =========================== */
+  /*  EPON DDM Registers         */
+  /* =========================== */
+  [mvAsicReg_EPON_DDM_DELAY_CONFIG]                 = {mvAsicReg_EPON_DDM_DELAY_CONFIG,                 MV_ASIC_ONT_GLB_ADDR + 0x1814,   0x1814,   asicRW,     0x0000FFFF,     0,      0,     0,      0,     "DDM delay config"},
+  [mvAsicReg_EPON_DDM_TX_POLARITY]                  = {mvAsicReg_EPON_DDM_TX_POLARITY,                  MV_ASIC_ONT_GLB_ADDR + 0x1818,   0x1818,   asicRW,     0x0000003F,     0,      0,     0,      0,     "DDM tx ploarity"},
+#ifdef PON_Z1
+  [mvAsicReg_EPON_STAT_RXP_FCS_ERROR_CNT]           = {mvAsicReg_EPON_STAT_RXP_FCS_ERROR_CNT,           MV_ASIC_ONT_GLB_ADDR + 0x1828,   0x1828,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP fcs error counter"},
+  [mvAsicReg_EPON_STAT_RXP_SHORT_ERROR_CNT]         = {mvAsicReg_EPON_STAT_RXP_SHORT_ERROR_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x182c,   0x182c,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP short error counter"},
+  [mvAsicReg_EPON_STAT_RXP_LONG_ERROR_CNT]          = {mvAsicReg_EPON_STAT_RXP_LONG_ERROR_CNT,          MV_ASIC_ONT_GLB_ADDR + 0x1830,   0x1830,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP long error counter"},
+  [mvAsicReg_EPON_STAT_RXP_DATA_FRAMES_CNT]         = {mvAsicReg_EPON_STAT_RXP_DATA_FRAMES_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x1834,   0x1834,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP data frame counter"},
+  [mvAsicReg_EPON_STAT_RXP_CTRL_FRAMES_CNT]         = {mvAsicReg_EPON_STAT_RXP_CTRL_FRAMES_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x1838,   0x1838,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP ctrl frame counter"},
+  [mvAsicReg_EPON_STAT_RXP_REPORT_FRAMES_CNT]       = {mvAsicReg_EPON_STAT_RXP_REPORT_FRAMES_CNT,       MV_ASIC_ONT_GLB_ADDR + 0x183C,   0x183C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP report frame counter"},
+  [mvAsicReg_EPON_STAT_RXP_GATE_FRAMES_CNT]         = {mvAsicReg_EPON_STAT_RXP_GATE_FRAMES_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x1840,   0x1840,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP gate frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_CTRL_REG_REQ_FRAMES_CNT] = {mvAsicReg_EPON_STAT_TXP_CTRL_REG_REQ_FRAMES_CNT, MV_ASIC_ONT_GLB_ADDR + 0x1844,   0x1844,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "TXP ctrl register req frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_CTRL_REG_ACK_FRAMES_CNT] = {mvAsicReg_EPON_STAT_TXP_CTRL_REG_ACK_FRAMES_CNT, MV_ASIC_ONT_GLB_ADDR + 0x1848,   0x1848,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "TXP ctrl register ack frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_CTRL_REPORT_FRAMES_CNT]  = {mvAsicReg_EPON_STAT_TXP_CTRL_REPORT_FRAMES_CNT,  MV_ASIC_ONT_GLB_ADDR + 0x184C,   0x184C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "TXP ctrl report frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_DATA_FRAMES_CNT]         = {mvAsicReg_EPON_STAT_TXP_DATA_FRAMES_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x1850,   0x1850,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "TXP data frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_TX_ALLOWED_BYTE_CNT]     = {mvAsicReg_EPON_STAT_TXP_TX_ALLOWED_BYTE_CNT,     MV_ASIC_ONT_GLB_ADDR + 0x1854,   0x1854,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "TXP tx allowed byte counter"},
+#else /* PON_Z2 */
+  [mvAsicReg_EPON_STAT_RXP_FCS_ERROR_CNT]           = {mvAsicReg_EPON_STAT_RXP_FCS_ERROR_CNT,           MV_ASIC_ONT_GLB_ADDR + 0x1828,   0x1828,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP fcs error counter"},
+  [mvAsicReg_EPON_STAT_RXP_SHORT_ERROR_CNT]         = {mvAsicReg_EPON_STAT_RXP_SHORT_ERROR_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x1848,   0x1848,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP short error counter"},
+  [mvAsicReg_EPON_STAT_RXP_LONG_ERROR_CNT]          = {mvAsicReg_EPON_STAT_RXP_LONG_ERROR_CNT,          MV_ASIC_ONT_GLB_ADDR + 0x1868,   0x1868,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP long error counter"},
+  [mvAsicReg_EPON_STAT_RXP_DATA_FRAMES_CNT]         = {mvAsicReg_EPON_STAT_RXP_DATA_FRAMES_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x1888,   0x1888,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP data frame counter"},
+  [mvAsicReg_EPON_STAT_RXP_CTRL_FRAMES_CNT]         = {mvAsicReg_EPON_STAT_RXP_CTRL_FRAMES_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x18A8,   0x18A8,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP ctrl frame counter"},
+  [mvAsicReg_EPON_STAT_RXP_REPORT_FRAMES_CNT]       = {mvAsicReg_EPON_STAT_RXP_REPORT_FRAMES_CNT,       MV_ASIC_ONT_GLB_ADDR + 0x18C8,   0x18C8,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP report frame counter"},
+  [mvAsicReg_EPON_STAT_RXP_GATE_FRAMES_CNT]         = {mvAsicReg_EPON_STAT_RXP_GATE_FRAMES_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x18E8,   0x18E8,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "RXP gate frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_CTRL_REG_REQ_FRAMES_CNT] = {mvAsicReg_EPON_STAT_TXP_CTRL_REG_REQ_FRAMES_CNT, MV_ASIC_ONT_GLB_ADDR + 0x1908,   0x1908,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "TXP ctrl register req frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_CTRL_REG_ACK_FRAMES_CNT] = {mvAsicReg_EPON_STAT_TXP_CTRL_REG_ACK_FRAMES_CNT, MV_ASIC_ONT_GLB_ADDR + 0x1928,   0x1928,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "TXP ctrl register ack frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_CTRL_REPORT_FRAMES_CNT]  = {mvAsicReg_EPON_STAT_TXP_CTRL_REPORT_FRAMES_CNT,  MV_ASIC_ONT_GLB_ADDR + 0x1948,   0x1948,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "TXP ctrl report frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_DATA_FRAMES_CNT]         = {mvAsicReg_EPON_STAT_TXP_DATA_FRAMES_CNT,         MV_ASIC_ONT_GLB_ADDR + 0x1968,   0x1968,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "TXP data frame counter"},
+  [mvAsicReg_EPON_STAT_TXP_TX_ALLOWED_BYTE_CNT]     = {mvAsicReg_EPON_STAT_TXP_TX_ALLOWED_BYTE_CNT,     MV_ASIC_ONT_GLB_ADDR + 0x1988,   0x1988,   asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "TXP tx allowed byte counter"},
+#endif /* PON_Z2  */
+
+  /* ===================================== */
+  /*  EPON Control Packet queue Registers  */
+  /* ===================================== */
+  [mvAsicReg_EPON_CPQ_RX_CTRL_Q_READ]               = {mvAsicReg_EPON_CPQ_RX_CTRL_Q_READ,               MV_ASIC_ONT_GLB_ADDR + 0x1C10,   0x1C10,   asicRW,     0x000000FF,     0,      0,     0,      0,     "CPQ rx ctrl queue read"},
+  [mvAsicReg_EPON_CPQ_RX_CTRL_Q_USED]               = {mvAsicReg_EPON_CPQ_RX_CTRL_Q_USED,               MV_ASIC_ONT_GLB_ADDR + 0x1C14,   0x1C14,   asicRW,     0x000007FF,     0,      0,     0,      0,     "CPQ rx ctrl queue used"},
+  [mvAsicReg_EPON_CPQ_RX_RPRT_Q_READ]               = {mvAsicReg_EPON_CPQ_RX_RPRT_Q_READ,               MV_ASIC_ONT_GLB_ADDR + 0x1C18,   0x1C18,   asicRW,     0x000000FF,     0,      0,     0,      0,     "CPQ rx report queue read"},
+  [mvAsicReg_EPON_CPQ_RX_RPRT_Q_USED]               = {mvAsicReg_EPON_CPQ_RX_RPRT_Q_USED,               MV_ASIC_ONT_GLB_ADDR + 0x1C1C,   0x1C1C,   asicRW,     0x000007FF,     0,      0,     0,      0,     "CPQ rx report queue used"},
+  [mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_L]            = {mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_L,            MV_ASIC_ONT_GLB_ADDR + 0x1C20,   0x1C20,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "CPQ rx ctrl header queue read L"},
+  [mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_H]            = {mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_H,            MV_ASIC_ONT_GLB_ADDR + 0x1C24,   0x1C24,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "CPQ rx ctrl header queue read H"},
+  [mvAsicReg_EPON_CPQ_RX_CTRL_HQ_USED]              = {mvAsicReg_EPON_CPQ_RX_CTRL_HQ_USED,              MV_ASIC_ONT_GLB_ADDR + 0x1C28,   0x1C28,   asicRW,     0x0000001F,     0,      0,     0,      0,     "CPQ rx ctrl header queue read used"},
+  [mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_L]            = {mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_L,            MV_ASIC_ONT_GLB_ADDR + 0x1C2C,   0x1C2C,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "CPQ rx report header queue read L"},
+  [mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_H]            = {mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_H,            MV_ASIC_ONT_GLB_ADDR + 0x1C30,   0x1C30,   asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "CPQ rx report header queue read H"},
+  [mvAsicReg_EPON_CPQ_RX_RPRT_HQ_USED]              = {mvAsicReg_EPON_CPQ_RX_RPRT_HQ_USED,              MV_ASIC_ONT_GLB_ADDR + 0x1C34,   0x1C34,   asicRW,     0x0000001F,     0,      0,     0,      0,     "CPQ rx report header queue read used"},
+#ifdef PON_Z1
+  [mvAsicReg_EPON_CPQ_TX_CTRL_Q_WRITE]              = {mvAsicReg_EPON_CPQ_TX_CTRL_Q_WRITE,              MV_ASIC_ONT_GLB_ADDR + 0x1C38,   0x1C38,   asicRW,     0x000000FF,     0,      0,     0,      0,     "CPQ tx ctrl queue write"},
+  [mvAsicReg_EPON_CPQ_TX_CTRL_Q_FREE]               = {mvAsicReg_EPON_CPQ_TX_CTRL_Q_FREE,               MV_ASIC_ONT_GLB_ADDR + 0x1C3C,   0x1C3C,   asicRW,     0x000001FF,     0,      0,     0,      0,     "CPQ tx ctrl queue free"},
+#else /* PON_Z2 */
+  [mvAsicReg_EPON_CPQ_TX_CTRL_Q_WRITE]              = {mvAsicReg_EPON_CPQ_TX_CTRL_Q_WRITE,              MV_ASIC_ONT_GLB_ADDR + 0x1C78,   0x1C78,   asicRW,     0x000000FF,     0,      8,     1,      0,     "CPQ tx ctrl queue write"},
+  [mvAsicReg_EPON_CPQ_TX_CTRL_Q_FREE]               = {mvAsicReg_EPON_CPQ_TX_CTRL_Q_FREE,               MV_ASIC_ONT_GLB_ADDR + 0x1C98,   0x1C98,   asicRW,     0x000001FF,     0,      8,     1,      0,     "CPQ tx ctrl queue free"},
+#endif /* PON_Z2  */
+#ifdef PON_Z1
+  [mvAsicReg_EPON_CPQ_TX_CTRL_HQ_WRITE]             = {mvAsicReg_EPON_CPQ_TX_CTRL_HQ_WRITE,             MV_ASIC_ONT_GLB_ADDR + 0x1C48,   0x1C48,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "CPQ tx ctrl header queue write"},
+  [mvAsicReg_EPON_CPQ_TX_CTRL_HQ_FREE]              = {mvAsicReg_EPON_CPQ_TX_CTRL_HQ_FREE,              MV_ASIC_ONT_GLB_ADDR + 0x1C4C,   0x1C4C,   asicRW,     0x00FFFFFF,     0,      0,     0,      0,     "CPQ tx ctrl header queue free"},
+#else /* PON_Z2 */
+  [mvAsicReg_EPON_CPQ_TX_CTRL_HQ_WRITE]             = {mvAsicReg_EPON_CPQ_TX_CTRL_HQ_WRITE,             MV_ASIC_ONT_GLB_ADDR + 0x1CB8,   0x1CB8,   asicRW,     0x00FFFFFF,     0,      8,     1,      0,     "CPQ tx ctrl header queue write"},
+  [mvAsicReg_EPON_CPQ_TX_CTRL_HQ_FREE]              = {mvAsicReg_EPON_CPQ_TX_CTRL_HQ_FREE,              MV_ASIC_ONT_GLB_ADDR + 0x1CD8,   0x1CD8,   asicRW,     0x00FFFFFF,     0,      8,     1,      0,     "CPQ tx ctrl header queue free"},
+#endif /* PON_Z2  */
+
+  /* =========================== */
+  /*  P2P Registers              */
+  /* =========================== */
+  [mvAsicReg_P2P_GEN_ONT_MODE]                      = {mvAsicReg_P2P_GEN_ONT_MODE,                      MV_ASIC_ONT_GLB_ADDR + 0x040C,   0x040C,   asicRW,     0x00000001,    31,      0,     0,      0,     "ONU mode"},
+  [mvAsicReg_P2P_PCS_CONFIGURATION]                 = {mvAsicReg_P2P_PCS_CONFIGURATION,                 MV_ASIC_ONT_GLB_ADDR + 0x1414,   0x1414,   asicRW,     0x00000613,    16,      0,     0,      0,     "P2P PCS configuration"},
+  [mvAsicReg_P2P_TXM_CFG_MODE]                      = {mvAsicReg_P2P_TXM_CFG_MODE,                      MV_ASIC_ONT_GLB_ADDR + 0x1018,   0x1018,   asicRW,     0x00000003,     3,      0,     0,      0,     "Tx Configuration mode"},
+
+
+#ifndef PON_FPGA
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0]                 = {mvAsicReg_PON_SERDES_PHY_CTRL_0,                 0x184F4,                         0x184F4,  asicRW,     0xFFFFFFFF,     0,      0,     0,      0,     "Gpon Phy Control 0"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll]          = {mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll,          0x184F4,                         0x184F4,  asicRW,     0x00000001,     0,      0,     0,      0,     "Gpon Phy Control 0 Power Up Pll"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX]           = {mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX,           0x184F4,                         0x184F4,  asicRW,     0x00000001,     1,      0,     0,      0,     "Gpon Phy Control 0 Power Up Rx"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX]           = {mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX,           0x184F4,                         0x184F4,  asicRW,     0x00000001,     2,      0,     0,      0,     "Gpon Phy Control 0 Power Up Tx"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_RST]             = {mvAsicReg_PON_SERDES_PHY_CTRL_0_RST,             0x184F4,                         0x184F4,  asicRW,     0x00000001,     3,      0,     0,      0,     "Gpon Phy Control 0 Reset"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_RST_TX_DOUT]     = {mvAsicReg_PON_SERDES_PHY_CTRL_0_RST_TX_DOUT,     0x184F4,                         0x184F4,  asicRW,     0x00000001,     4,      0,     0,      0,     "Gpon Phy Control 0 Reset Tx Dout"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT]         = {mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT,         0x184F4,                         0x184F4,  asicRW,     0x00000001,     5,      0,     0,      0,     "Gpon Phy Control 0 Rx Init"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_RATE]         = {mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_RATE,         0x184F4,                         0x184F4,  asicRW,     0x00000001,     6,      0,     0,      0,     "Gpon Phy Control 0 Rx Rate"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_GEPON]       = {mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_GEPON,       0x184F4,                         0x184F4,  asicRW,     0x00000001,     7,      0,     0,      0,     "Gpon Phy Control 0 Sel GEPON"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_REF_CLK]     = {mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_REF_CLK,     0x184F4,                         0x184F4,  asicRW,     0x00000003,     8,      0,     0,      0,     "Gpon Phy Control 0 Sel Ref Clk"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_CID_REV]         = {mvAsicReg_PON_SERDES_PHY_CTRL_0_CID_REV,         0x184F4,                         0x184F4,  asicRW,     0x000000FF,    16,      0,     0,      0,     "Gpon Phy Control 0 Cid Rev"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_TX_RATE]         = {mvAsicReg_PON_SERDES_PHY_CTRL_0_TX_RATE,         0x184F4,                         0x184F4,  asicRW,     0x00000001,    24,      0,     0,      0,     "Gpon Phy Control 0 Tx Rate"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_REF_CLK_25M]     = {mvAsicReg_PON_SERDES_PHY_CTRL_0_REF_CLK_25M,     0x184F4,                         0x184F4,  asicRW,     0x00000001,    25,      0,     0,      0,     "Gpon Phy Control 0 Ref Clk 25M"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE]       = {mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE,       0x184F4,                         0x184F4,  asicRW,     0x00000001,    29,      0,     0,      0,     "Gpon Phy Control 0 Rx Init Done"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_TX]        = {mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_TX,        0x184F4,                         0x184F4,  asicRW,     0x00000001,    30,      0,     0,      0,     "Gpon Phy Control 0 Pll Ready Tx"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_RX]        = {mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_RX,        0x184F4,                         0x184F4,  asicRW,     0x00000001,    31,      0,     0,      0,     "Gpon Phy Control 0 Pll Ready Rx"},
+
+  [mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN]       = {mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN,       0x184F8,                         0x184F8,  asicRW,     0x00000001,    24,      0,     0,      0,     "Gpon Phy Control 1 BEN IO Enable"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_EN] = {mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_EN, 0x184F8,                         0x184F8,  asicRW,     0x00000001,    25,      0,     0,      0,     "Gpon Phy Control 1 Force BEN IO Enable"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL]= {mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL,0x184F8,                         0x184F8,  asicRW,     0x00000001,    26,      0,     0,      0,     "Gpon Phy Control 1 Force BEN IO Value"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_HW_SELECT]= {mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_HW_SELECT,0x184F8,                         0x184F8,  asicRW,     0x00000001,    27,      0,     0,      0,     "Gpon Phy Control 1 Select MC SW or HW Control"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_FORCE]    = {mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_FORCE,    0x184F8,                         0x184F8,  asicRW,     0x00000001,    28,      0,     0,      0,     "Gpon Phy Control 1 MC Software Control Force Enable"},
+  [mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_VALUE]    = {mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_VALUE,    0x184F8,                         0x184F8,  asicRW,     0x00000001,    29,      0,     0,      0,     "Gpon Phy Control 1 MC Software Control Force Value"},
+
+  [mvAsicReg_PON_SERDES_CLK_SEL]                    = {mvAsicReg_PON_SERDES_CLK_SEL,                    0x18748,                         0x18748,  asicRW,     0x00000001,     8,      0,     0,      0,     "Gpon Serded Clock Select"},
+  [mvAsicReg_PON_SERDES_CLK_EN]                     = {mvAsicReg_PON_SERDES_CLK_EN,                     0x18748,                         0x18748,  asicRW,     0x00000001,     9,      0,     0,      0,     "Gpon Serded Clock Enable"},
+
+  [mvAsicReg_PON_SERDES_XPON_CTRL]                  = {mvAsicReg_PON_SERDES_XPON_CTRL,                  0x184FC,                         0x184FC,  asicRW,     0x00000001,     0,      0,     0,      0,     "Gpon Serded XPON MAC Control"},
+
+  [mvAsicReg_PON_SERDES_INTERNAL_PASSWORD]          = {mvAsicReg_PON_SERDES_INTERNAL_PASSWORD,          0xA2E88,                         0xA2E88,  asicRW,     0x000000FF,     0,      0,     0,      0,     "Gpon Serded Internal - password"},
+  [mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING]    = {mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING,    0xA2E8C,                         0xA2E8C,  asicRW,     0x00000001,    12,      0,     0,      0,     "Gpon Serded Internal - enable loop timing"},
+  [mvAsicReg_PON_SERDES_INTERNAL_PON_SELECT]        = {mvAsicReg_PON_SERDES_INTERNAL_PON_SELECT,        0xA2E8C,                         0xA2E8C,  asicRW,     0x00000003,    10,      0,     0,      0,     "Gpon Serded Internal - pon select"},
+  [mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR]      = {mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR,      0xA2E98,                         0xA2E98,  asicRW,     0x00000001,     8,      0,     0,      0,     "Gpon Serded Internal - open tx door"},
+
+  [mvAsicReg_PON_MAC_GPON_CLK_EN]                   = {mvAsicReg_PON_MAC_GPON_CLK_EN,                   0x1821C,                         0x1821C,  asicRW,     0x00000001,    28,      0,     0,      0,     "Gpon MAC Gpon T-Clock Enable"},
+  [mvAsicReg_PON_MAC_SW_RESET_CTRL]                 = {mvAsicReg_PON_MAC_SW_RESET_CTRL,                 0x18220,                         0x18220,  asicRW,     0x00000001,    10,      0,     0,      0,     "Gpon MAC Software Reset Control"},
+
+  [mvAsicReg_PON_MPP_00]                            = {mvAsicReg_PON_MPP_00,                            0x18000,                         0x18000,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 00"},
+  [mvAsicReg_PON_MPP_01]                            = {mvAsicReg_PON_MPP_01,                            0x18000,                         0x18000,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 01"},
+  [mvAsicReg_PON_MPP_02]                            = {mvAsicReg_PON_MPP_02,                            0x18000,                         0x18000,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 02"},
+  [mvAsicReg_PON_MPP_03]                            = {mvAsicReg_PON_MPP_03,                            0x18000,                         0x18000,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 03"},
+  [mvAsicReg_PON_MPP_04]                            = {mvAsicReg_PON_MPP_04,                            0x18000,                         0x18000,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 04"},
+  [mvAsicReg_PON_MPP_05]                            = {mvAsicReg_PON_MPP_05,                            0x18000,                         0x18000,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 05"},
+  [mvAsicReg_PON_MPP_06]                            = {mvAsicReg_PON_MPP_06,                            0x18000,                         0x18000,  asicRW,     0x0000000F,    24,      0,     0,      0,     "Gpon MMP 06"},
+  [mvAsicReg_PON_MPP_07]                            = {mvAsicReg_PON_MPP_07,                            0x18000,                         0x18000,  asicRW,     0x0000000F,    28,      0,     0,      0,     "Gpon MMP 07"},
+  [mvAsicReg_PON_MPP_08]                            = {mvAsicReg_PON_MPP_08,                            0x18004,                         0x18004,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 08"},
+  [mvAsicReg_PON_MPP_09]                            = {mvAsicReg_PON_MPP_09,                            0x18004,                         0x18004,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 09"},
+  [mvAsicReg_PON_MPP_10]                            = {mvAsicReg_PON_MPP_10,                            0x18004,                         0x18004,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 10"},
+  [mvAsicReg_PON_MPP_11]                            = {mvAsicReg_PON_MPP_11,                            0x18004,                         0x18004,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 11"},
+  [mvAsicReg_PON_MPP_12]                            = {mvAsicReg_PON_MPP_12,                            0x18004,                         0x18004,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 12"},
+  [mvAsicReg_PON_MPP_13]                            = {mvAsicReg_PON_MPP_13,                            0x18004,                         0x18004,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 13"},
+  [mvAsicReg_PON_MPP_14]                            = {mvAsicReg_PON_MPP_14,                            0x18004,                         0x18004,  asicRW,     0x0000000F,    24,      0,     0,      0,     "Gpon MMP 14"},
+  [mvAsicReg_PON_MPP_15]                            = {mvAsicReg_PON_MPP_15,                            0x18004,                         0x18004,  asicRW,     0x0000000F,    28,      0,     0,      0,     "Gpon MMP 15"},
+  [mvAsicReg_PON_MPP_16]                            = {mvAsicReg_PON_MPP_16,                            0x18008,                         0x18008,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 16"},
+  [mvAsicReg_PON_MPP_17]                            = {mvAsicReg_PON_MPP_17,                            0x18008,                         0x18008,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 17"},
+  [mvAsicReg_PON_MPP_18]                            = {mvAsicReg_PON_MPP_18,                            0x18008,                         0x18008,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 18, DB Board XVR SD"},
+  [mvAsicReg_PON_MPP_19]                            = {mvAsicReg_PON_MPP_19,                            0x18008,                         0x18008,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 19"},
+  [mvAsicReg_PON_MPP_20]                            = {mvAsicReg_PON_MPP_20,                            0x18008,                         0x18008,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 20"},
+  [mvAsicReg_PON_MPP_21]                            = {mvAsicReg_PON_MPP_21,                            0x18008,                         0x18008,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 21"},
+  [mvAsicReg_PON_MPP_22]                            = {mvAsicReg_PON_MPP_22,                            0x18008,                         0x18008,  asicRW,     0x0000000F,    24,      0,     0,      0,     "Gpon MMP 22, DB Board Dying Gasp"},
+  [mvAsicReg_PON_MPP_23]                            = {mvAsicReg_PON_MPP_23,                            0x18008,                         0x18008,  asicRW,     0x0000000F,    28,      0,     0,      0,     "Gpon MMP 23"},
+  [mvAsicReg_PON_MPP_24]                            = {mvAsicReg_PON_MPP_24,                            0x1800C,                         0x1800C,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 24"},
+  [mvAsicReg_PON_MPP_25]                            = {mvAsicReg_PON_MPP_25,                            0x1800C,                         0x1800C,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 25"},
+  [mvAsicReg_PON_MPP_26]                            = {mvAsicReg_PON_MPP_26,                            0x1800C,                         0x1800C,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 26"},
+  [mvAsicReg_PON_MPP_27]                            = {mvAsicReg_PON_MPP_27,                            0x1800C,                         0x1800C,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 27"},
+  [mvAsicReg_PON_MPP_28]                            = {mvAsicReg_PON_MPP_28,                            0x1800C,                         0x1800C,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 28"},
+  [mvAsicReg_PON_MPP_29]                            = {mvAsicReg_PON_MPP_29,                            0x1800C,                         0x1800C,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 29"},
+  [mvAsicReg_PON_MPP_30]                            = {mvAsicReg_PON_MPP_30,                            0x1800C,                         0x1800C,  asicRW,     0x0000000F,    24,      0,     0,      0,     "Gpon MMP 30"},
+  [mvAsicReg_PON_MPP_31]                            = {mvAsicReg_PON_MPP_31,                            0x1800C,                         0x1800C,  asicRW,     0x0000000F,    28,      0,     0,      0,     "Gpon MMP 31"},
+  [mvAsicReg_PON_MPP_32]                            = {mvAsicReg_PON_MPP_32,                            0x18010,                         0x18010,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 32"},
+  [mvAsicReg_PON_MPP_33]                            = {mvAsicReg_PON_MPP_33,                            0x18010,                         0x18010,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 33"},
+  [mvAsicReg_PON_MPP_34]                            = {mvAsicReg_PON_MPP_34,                            0x18010,                         0x18010,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 34"},
+  [mvAsicReg_PON_MPP_35]                            = {mvAsicReg_PON_MPP_35,                            0x18010,                         0x18010,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 35"},
+  [mvAsicReg_PON_MPP_36]                            = {mvAsicReg_PON_MPP_36,                            0x18010,                         0x18010,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 36"},
+  [mvAsicReg_PON_MPP_37]                            = {mvAsicReg_PON_MPP_37,                            0x18010,                         0x18010,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 37"},
+  [mvAsicReg_PON_MPP_38]                            = {mvAsicReg_PON_MPP_38,                            0x18010,                         0x18010,  asicRW,     0x0000000F,    24,      0,     0,      0,     "Gpon MMP 38"},
+  [mvAsicReg_PON_MPP_39]                            = {mvAsicReg_PON_MPP_39,                            0x18010,                         0x18010,  asicRW,     0x0000000F,    28,      0,     0,      0,     "Gpon MMP 39"},
+  [mvAsicReg_PON_MPP_40]                            = {mvAsicReg_PON_MPP_40,                            0x18014,                         0x18014,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 40"},
+  [mvAsicReg_PON_MPP_41]                            = {mvAsicReg_PON_MPP_41,                            0x18014,                         0x18014,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 41"},
+  [mvAsicReg_PON_MPP_42]                            = {mvAsicReg_PON_MPP_42,                            0x18014,                         0x18014,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 42"},
+  [mvAsicReg_PON_MPP_43]                            = {mvAsicReg_PON_MPP_43,                            0x18014,                         0x18014,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 43"},
+  [mvAsicReg_PON_MPP_44]                            = {mvAsicReg_PON_MPP_44,                            0x18014,                         0x18014,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 44"},
+  [mvAsicReg_PON_MPP_45]                            = {mvAsicReg_PON_MPP_45,                            0x18014,                         0x18014,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 45"},
+  [mvAsicReg_PON_MPP_46]                            = {mvAsicReg_PON_MPP_46,                            0x18014,                         0x18014,  asicRW,     0x0000000F,    24,      0,     0,      0,     "Gpon MMP 46"},
+  [mvAsicReg_PON_MPP_47]                            = {mvAsicReg_PON_MPP_47,                            0x18014,                         0x18014,  asicRW,     0x0000000F,    28,      0,     0,      0,     "Gpon MMP 47"},
+  [mvAsicReg_PON_MPP_48]                            = {mvAsicReg_PON_MPP_48,                            0x18018,                         0x18018,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 48"},
+  [mvAsicReg_PON_MPP_49]                            = {mvAsicReg_PON_MPP_49,                            0x18018,                         0x18018,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 49"},
+  [mvAsicReg_PON_MPP_50]                            = {mvAsicReg_PON_MPP_50,                            0x18018,                         0x18018,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 50, RD Board Dying Gasp"},
+  [mvAsicReg_PON_MPP_51]                            = {mvAsicReg_PON_MPP_51,                            0x18018,                         0x18018,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 51"},
+  [mvAsicReg_PON_MPP_52]                            = {mvAsicReg_PON_MPP_52,                            0x18018,                         0x18018,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 52"},
+  [mvAsicReg_PON_MPP_53]                            = {mvAsicReg_PON_MPP_53,                            0x18018,                         0x18018,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 53"},
+  [mvAsicReg_PON_MPP_54]                            = {mvAsicReg_PON_MPP_54,                            0x18018,                         0x18018,  asicRW,     0x0000000F,    24,      0,     0,      0,     "Gpon MMP 54"},
+  [mvAsicReg_PON_MPP_55]                            = {mvAsicReg_PON_MPP_55,                            0x18018,                         0x18018,  asicRW,     0x0000000F,    28,      0,     0,      0,     "Gpon MMP 55"},
+  [mvAsicReg_PON_MPP_56]                            = {mvAsicReg_PON_MPP_56,                            0x1801C,                         0x1801C,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 56"},
+  [mvAsicReg_PON_MPP_57]                            = {mvAsicReg_PON_MPP_57,                            0x1801C,                         0x1801C,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 57"},
+  [mvAsicReg_PON_MPP_58]                            = {mvAsicReg_PON_MPP_58,                            0x1801C,                         0x1801C,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 58"},
+  [mvAsicReg_PON_MPP_59]                            = {mvAsicReg_PON_MPP_59,                            0x1801C,                         0x1801C,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 59"},
+  [mvAsicReg_PON_MPP_60]                            = {mvAsicReg_PON_MPP_60,                            0x1801C,                         0x1801C,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 60"},
+  [mvAsicReg_PON_MPP_61]                            = {mvAsicReg_PON_MPP_61,                            0x1801C,                         0x1801C,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 61"},
+  [mvAsicReg_PON_MPP_62]                            = {mvAsicReg_PON_MPP_62,                            0x1801C,                         0x1801C,  asicRW,     0x0000000F,    24,      0,     0,      0,     "Gpon MMP 62"},
+  [mvAsicReg_PON_MPP_63]                            = {mvAsicReg_PON_MPP_63,                            0x1801C,                         0x1801C,  asicRW,     0x0000000F,    28,      0,     0,      0,     "Gpon MMP 63"},
+  [mvAsicReg_PON_MPP_64]                            = {mvAsicReg_PON_MPP_64,                            0x18020,                         0x18020,  asicRW,     0x0000000F,     0,      0,     0,      0,     "Gpon MMP 64"},
+  [mvAsicReg_PON_MPP_65]                            = {mvAsicReg_PON_MPP_65,                            0x18020,                         0x18020,  asicRW,     0x0000000F,     4,      0,     0,      0,     "Gpon MMP 65"},
+  [mvAsicReg_PON_MPP_66]                            = {mvAsicReg_PON_MPP_66,                            0x18020,                         0x18020,  asicRW,     0x0000000F,     8,      0,     0,      0,     "Gpon MMP 66"},
+  [mvAsicReg_PON_MPP_67]                            = {mvAsicReg_PON_MPP_67,                            0x18020,                         0x18020,  asicRW,     0x0000000F,    12,      0,     0,      0,     "Gpon MMP 67"},
+  [mvAsicReg_PON_MPP_68]                            = {mvAsicReg_PON_MPP_68,                            0x18020,                         0x18020,  asicRW,     0x0000000F,    16,      0,     0,      0,     "Gpon MMP 68"},
+  [mvAsicReg_PON_MPP_69]                            = {mvAsicReg_PON_MPP_69,                            0x18020,                         0x18020,  asicRW,     0x0000000F,    20,      0,     0,      0,     "Gpon MMP 69, RD Board XVR SD"},
+  [mvAsicReg_PON_XVR_TX_DATA_OUT_17]                = {mvAsicReg_PON_XVR_TX_DATA_OUT_17,                0x18104,                         0x18104,  asicRW,     0x00000001,    17,      0,     0,      0,     "GPIO 17 data out transmit"},
+  [mvAsicReg_PON_XVR_TX_DATA_OUT_37]                = {mvAsicReg_PON_XVR_TX_DATA_OUT_37,                0x18144,                         0x18144,  asicRW,     0x00000001,    5,       0,     0,      0,     "GPIO 37 data out transmit"},
+  [mvAsicReg_PON_XVR_TX_DATA_OUT_68]                = {mvAsicReg_PON_XVR_TX_DATA_OUT_68,                0x18184,                         0x18184,  asicRW,     0x00000001,    4,       0,     0,      0,     "GPIO 68 data out transmit"},
+  [mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_17]           = {mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_17,           0x18100,                         0x18100,  asicRW,     0x00000001,    17,      0,     0,      0,     "GPIO 17 data out enabled"},
+  [mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_37]           = {mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_37,           0x18140,                         0x18140,  asicRW,     0x00000001,    5,       0,     0,      0,     "GPIO 37 data out enabled"},
+  [mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_68]           = {mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_68,           0x18180,                         0x18180,  asicRW,     0x00000001,    4,       0,     0,      0,     "GPIO 68 data out enabled"},
+  [mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR_15]   = {mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR_15,   0xA2E98,                         0xA2E98,  asicRW,     0x00000001,    15,      0,     0,      0,     "Gpon Serded Internal - open tx door"},
+  [mvAsicReg_PON_SERDES_POWER_PHY_MODE]             = {mvAsicReg_PON_SERDES_POWER_PHY_MODE,             0xA2E04,                         0xA2E04,  asicRW,     0x0000FFFF,    0,       0,     0,      0,     "Gpon Serded power up in PHY mode"},
+  [mvAsicReg_PON_SYS_LED_ENABLE]                    = {mvAsicReg_PON_SYS_LED_ENABLE,                    0x18144,                         0x18144,  asicRW,     0x00000001,    12,      0,     0,      0,     "ONU Sys Led enable"},
+  [mvAsicReg_PON_SYS_LED_STATE]                     = {mvAsicReg_PON_SYS_LED_STATE,                     0x18140,                         0x18140,  asicRW,     0x00000001,    12,      0,     0,      0,     "ONU Sys Led state"},
+  [mvAsicReg_PON_SYS_LED_BLINK]                     = {mvAsicReg_PON_SYS_LED_BLINK,                     0x18148,                         0x18148,  asicRW,     0x00000001,    12,      0,     0,      0,     "ONU Sys Led blink"},
+  [mvAsicReg_PON_SYS_LED_BLINK_FREQ]                = {mvAsicReg_PON_SYS_LED_BLINK_FREQ,                0x18160,                         0x18160,  asicRW,     0x00000001,    12,      0,     0,      0,     "ONU Sys Led blink freq"},
+  [mvAsicReg_PON_SYNC_LED_ENABLE]                   = {mvAsicReg_PON_SYNC_LED_ENABLE,                   0x18144,                         0x18144,  asicRW,     0x00000001,    13,      0,     0,      0,     "ONU Sync Led enable"},
+  [mvAsicReg_PON_SYNC_LED_STATE]                    = {mvAsicReg_PON_SYNC_LED_STATE,                    0x18140,                         0x18140,  asicRW,     0x00000001,    13,      0,     0,      0,     "ONU Sync Led state"},
+  [mvAsicReg_PON_SYNC_LED_BLINK]                    = {mvAsicReg_PON_SYNC_LED_BLINK,                    0x18148,                         0x18148,  asicRW,     0x00000001,    13,      0,     0,      0,     "ONU Sync Led blink"},
+  [mvAsicReg_PON_SYNC_LED_BLINK_FREQ]               = {mvAsicReg_PON_SYNC_LED_BLINK_FREQ,               0x18160,                         0x18160,  asicRW,     0x00000001,    13,      0,     0,      0,     "ONU Sync Led blink freq"},
+  [mvAsicReg_PON_LED_BLINK_FREQ_A_ON]               = {mvAsicReg_PON_LED_BLINK_FREQ_A_ON,               0x181C0,                         0x181C0,  asicRW,     0x00000000,     0,      0,     0,      0,     "ONU Led Freq A On"},
+  [mvAsicReg_PON_LED_BLINK_FREQ_A_OFF]              = {mvAsicReg_PON_LED_BLINK_FREQ_A_OFF,              0x181C4,                         0x181C4,  asicRW,     0x00000000,     0,      0,     0,      0,     "ONU Led Freq A Off"},
+  [mvAsicReg_PON_LED_BLINK_FREQ_B_ON]               = {mvAsicReg_PON_LED_BLINK_FREQ_B_ON,               0x181C8,                         0x181C8,  asicRW,     0x00000000,     0,      0,     0,      0,     "ONU Led Freq B On"},
+  [mvAsicReg_PON_LED_BLINK_FREQ_B_OFF]              = {mvAsicReg_PON_LED_BLINK_FREQ_B_OFF,              0x181CC,                         0x181CC,  asicRW,     0x00000000,     0,      0,     0,      0,     "ONU Led Freq B Off"},
+  [mvAsicReg_PON_DG_CTRL_EN]                        = {mvAsicReg_PON_DG_CTRL_EN,                        0x18270,                         0x18270,  asicRW,     0x00000001,     0,      0,     0,      0,     "ONU Dying Gasp enable"},
+  [mvAsicReg_PON_DG_CTRL_POLARITY]                  = {mvAsicReg_PON_DG_CTRL_POLARITY,                  0x18270,                         0x18270,  asicRW,     0x00000001,     1,      0,     0,      0,     "ONU Dying Gasp polarity"},
+  [mvAsicReg_PON_DG_THRESHOLD]                      = {mvAsicReg_PON_DG_THRESHOLD,                      0x18274,                         0x18274,  asicRW,     0x00000000,     0,      0,     0,      0,     "ONU Dying Gasp threshold"},
+  [mvAsicReg_PT_PATTERN_SELECT]                     = {mvAsicReg_PT_PATTERN_SELECT,                     0xA2E54,                         0xA2E54,  asicRW,     0x00000007,     5,      0,     0,      0,     "PHY test pattern select"},
+  [mvAsicReg_PT_PATTERN_ENABLED]                    = {mvAsicReg_PT_PATTERN_ENABLED,                    0xA2E54,                         0xA2E54,  asicRW,     0x00000001,     15,     0,     0,      0,     "PHY test pattern enabled"},
+  [mvAsicReg_PT_PATTERN_DATA]                       = {mvAsicReg_PT_PATTERN_DATA,                       0xA2E6C,                         0xA2E6C,  asicRW,     0x000000FF,     0,      0,     0,      0,     "PHY test pattern data"},
+  [mvAsicReg_GUNIT_TX_0_QUEUES]                     = {mvAsicReg_GUNIT_TX_0_QUEUES,                     0xA5900,                         0xA5900,  asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "GPON GUNIT Queues for TX 0"},
+  [mvAsicReg_GUNIT_TX_1_QUEUES]                     = {mvAsicReg_GUNIT_TX_1_QUEUES,                     0xA5D00,                         0xA5D00,  asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "GPON GUNIT Queues for TX 1"},
+  [mvAsicReg_GUNIT_TX_2_QUEUES]                     = {mvAsicReg_GUNIT_TX_2_QUEUES,                     0xA7900,                         0xA7900,  asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "GPON GUNIT Queues for TX 2"},
+  [mvAsicReg_GUNIT_TX_3_QUEUES]                     = {mvAsicReg_GUNIT_TX_3_QUEUES,                     0xA7D00,                         0xA7D00,  asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "GPON GUNIT Queues for TX 3"},
+  [mvAsicReg_GUNIT_TX_4_QUEUES]                     = {mvAsicReg_GUNIT_TX_4_QUEUES,                     0xA9900,                         0xA9900,  asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "GPON GUNIT Queues for TX 4"},
+  [mvAsicReg_GUNIT_TX_5_QUEUES]                     = {mvAsicReg_GUNIT_TX_5_QUEUES,                     0xA9D00,                         0xA9D00,  asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "GPON GUNIT Queues for TX 5"},
+  [mvAsicReg_GUNIT_TX_6_QUEUES]                     = {mvAsicReg_GUNIT_TX_6_QUEUES,                     0xAB900,                         0xAB900,  asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "GPON GUNIT Queues for TX 6"},
+  [mvAsicReg_GUNIT_TX_7_QUEUES]                     = {mvAsicReg_GUNIT_TX_7_QUEUES,                     0xABD00,                         0xABD00,  asicRW,     0xFFFFFFFF,     0,      8,     1,      0,     "GPON GUNIT Queues for TX 7"},
+
+  [mvAsicReg_GUNIT_TX_0_PKT_MOD_MAX_HEAD_SIZE_CFG]  = {mvAsicReg_GUNIT_TX_0_PKT_MOD_MAX_HEAD_SIZE_CFG,  0xA59D0,                         0xA59D0,  asicRW,     0x000000FE,     1,      0,     0,      0,     "GPON GUNIT Pkt Mod Mac Head Size for TX 0"},
+  [mvAsicReg_GUNIT_TX_1_PKT_MOD_MAX_HEAD_SIZE_CFG]  = {mvAsicReg_GUNIT_TX_1_PKT_MOD_MAX_HEAD_SIZE_CFG,  0xA5DD0,                         0xA5DD0,  asicRW,     0x000000FE,     1,      0,     0,      0,     "GPON GUNIT Pkt Mod Mac Head Size for TX 1"},
+  [mvAsicReg_GUNIT_TX_2_PKT_MOD_MAX_HEAD_SIZE_CFG]  = {mvAsicReg_GUNIT_TX_2_PKT_MOD_MAX_HEAD_SIZE_CFG,  0xA79D0,                         0xA79D0,  asicRW,     0x000000FE,     1,      0,     0,      0,     "GPON GUNIT Pkt Mod Mac Head Size for TX 2"},
+  [mvAsicReg_GUNIT_TX_3_PKT_MOD_MAX_HEAD_SIZE_CFG]  = {mvAsicReg_GUNIT_TX_3_PKT_MOD_MAX_HEAD_SIZE_CFG,  0xA7DD0,                         0xA7DD0,  asicRW,     0x000000FE,     1,      0,     0,      0,     "GPON GUNIT Pkt Mod Mac Head Size for TX 3"},
+  [mvAsicReg_GUNIT_TX_4_PKT_MOD_MAX_HEAD_SIZE_CFG]  = {mvAsicReg_GUNIT_TX_4_PKT_MOD_MAX_HEAD_SIZE_CFG,  0xA99D0,                         0xA99D0,  asicRW,     0x000000FE,     1,      0,     0,      0,     "GPON GUNIT Pkt Mod Mac Head Size for TX 4"},
+  [mvAsicReg_GUNIT_TX_5_PKT_MOD_MAX_HEAD_SIZE_CFG]  = {mvAsicReg_GUNIT_TX_5_PKT_MOD_MAX_HEAD_SIZE_CFG,  0xA9DD0,                         0xA9DD0,  asicRW,     0x000000FE,     1,      0,     0,      0,     "GPON GUNIT Pkt Mod Mac Head Size for TX 5"},
+  [mvAsicReg_GUNIT_TX_6_PKT_MOD_MAX_HEAD_SIZE_CFG]  = {mvAsicReg_GUNIT_TX_6_PKT_MOD_MAX_HEAD_SIZE_CFG,  0xAB9D0,                         0xAB9D0,  asicRW,     0x000000FE,     1,      0,     0,      0,     "GPON GUNIT Pkt Mod Mac Head Size for TX 6"},
+  [mvAsicReg_GUNIT_TX_7_PKT_MOD_MAX_HEAD_SIZE_CFG]  = {mvAsicReg_GUNIT_TX_7_PKT_MOD_MAX_HEAD_SIZE_CFG,  0xABDD0,                         0xABDD0,  asicRW,     0x000000FE,     1,      0,     0,      0,     "GPON GUNIT Pkt Mod Mac Head Size for TX 7"},
+
+  [mvAsicReg_GUNIT_TX_0_PKT_MOD_STATS_PKT_COUNT]    = {mvAsicReg_GUNIT_TX_0_PKT_MOD_STATS_PKT_COUNT,    0xA59D8,                         0xA59D8,  asicRW,     0x0000FFFF,     0,      0,     0,      0,     "GPON GUNIT Pkt Mod Packet Count for TX 0"},
+  [mvAsicReg_GUNIT_TX_1_PKT_MOD_STATS_PKT_COUNT]    = {mvAsicReg_GUNIT_TX_1_PKT_MOD_STATS_PKT_COUNT,    0xA5DD8,                         0xA5DD8,  asicRW,     0x0000FFFF,     0,      0,     0,      0,     "GPON GUNIT Pkt Mod Packet Count for TX 1"},
+  [mvAsicReg_GUNIT_TX_2_PKT_MOD_STATS_PKT_COUNT]    = {mvAsicReg_GUNIT_TX_2_PKT_MOD_STATS_PKT_COUNT,    0xA79D8,                         0xA79D8,  asicRW,     0x0000FFFF,     0,      0,     0,      0,     "GPON GUNIT Pkt Mod Packet Count for TX 2"},
+  [mvAsicReg_GUNIT_TX_3_PKT_MOD_STATS_PKT_COUNT]    = {mvAsicReg_GUNIT_TX_3_PKT_MOD_STATS_PKT_COUNT,    0xA7DD8,                         0xA7DD8,  asicRW,     0x0000FFFF,     0,      0,     0,      0,     "GPON GUNIT Pkt Mod Packet Count for TX 3"},
+  [mvAsicReg_GUNIT_TX_4_PKT_MOD_STATS_PKT_COUNT]    = {mvAsicReg_GUNIT_TX_4_PKT_MOD_STATS_PKT_COUNT,    0xA99D8,                         0xA99D8,  asicRW,     0x0000FFFF,     0,      0,     0,      0,     "GPON GUNIT Pkt Mod Packet Count for TX 4"},
+  [mvAsicReg_GUNIT_TX_5_PKT_MOD_STATS_PKT_COUNT]    = {mvAsicReg_GUNIT_TX_5_PKT_MOD_STATS_PKT_COUNT,    0xA9DD8,                         0xA9DD8,  asicRW,     0x0000FFFF,     0,      0,     0,      0,     "GPON GUNIT Pkt Mod Packet Count for TX 5"},
+  [mvAsicReg_GUNIT_TX_6_PKT_MOD_STATS_PKT_COUNT]    = {mvAsicReg_GUNIT_TX_6_PKT_MOD_STATS_PKT_COUNT,    0xAB9D8,                         0xAB9D8,  asicRW,     0x0000FFFF,     0,      0,     0,      0,     "GPON GUNIT Pkt Mod Packet Count for TX 6"},
+  [mvAsicReg_GUNIT_TX_7_PKT_MOD_STATS_PKT_COUNT]    = {mvAsicReg_GUNIT_TX_7_PKT_MOD_STATS_PKT_COUNT,    0xABDD8,                         0xABDD8,  asicRW,     0x0000FFFF,     0,      0,     0,      0,     "GPON GUNIT Pkt Mod Packet Count for TX 7"}
+
+#endif /* PON_FPGA */
+};
+
+/* Export Functions
+------------------------------------------------------------------------------*/
+
+/* Local Functions
+------------------------------------------------------------------------------*/
+MV_STATUS asicOntGlbRegValidation(E_asicGlobalRegs  reg,
+                                  S_asicGlobalRegDb **pRegEntry,
+                                  MV_U32            entry,
+                                  MV_U32            accessType);
+
+/*******************************************************************************
+**
+**  asicOntGlbAddrSet
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Set ASIC global address
+**
+**  PARAMETERS:  MV_U32 address
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK
+**
+*******************************************************************************/
+MV_STATUS ponOnuGlbAddrSet(MV_U32 address)
+{
+  ponOnuGlbAddr = address;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  asicOntGlbRegValidation
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Validate ASIC register
+**
+**  PARAMETERS:  E_asicGlobalRegs  reg,
+**               S_asicGlobalRegDb **pRegEntry
+**               MV_U32            entry
+**               MV_U32            accessType
+**
+**  OUTPUTS:     S_asicGlobalRegDb **pRegEntry
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS asicOntGlbRegValidation(E_asicGlobalRegs   reg,
+                                   S_asicGlobalRegDb **pRegEntry,
+                                   MV_U32            entry,
+                                   MV_U32            accessType)
+{
+  /* Check range */
+  if (reg >= mvAsicReg_MAX_NUM_OF_REGS)
+    return(MV_ERROR);
+
+  /* Get the register entry in DB */
+  *pRegEntry = &(asicGlbDb[reg]);
+
+  /* Check DB coherency */
+  if ((*pRegEntry)->enumVal != reg)
+    return(MV_ERROR);
+
+  /* Check access type */
+  if (accessType == funcRegR) /* Read */
+  {
+    if ((*pRegEntry)->accessType == asicWO)
+      return(MV_ERROR);
+  }
+  else if (accessType == funcRegW) /* Write */
+  {
+    if((*pRegEntry)->accessType == asicRO)
+      return(MV_ERROR);
+  }
+
+  /* Check table entry - only valid for tables */
+  if (entry > (*pRegEntry)->tblLength)
+    return(MV_ERROR);
+
+  /* Update the access count to this register */
+  (*pRegEntry)->accessCount++;
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  asicOntGlbRegRead
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Read the contents of MV_U32 ASIC register
+**
+**  PARAMETERS:  E_asicGlobalRegs reg
+**               MV_U32           *pValue
+**               MV_U32           entry
+**
+**  OUTPUTS:     a_value_p
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS asicOntGlbRegRead(E_asicGlobalRegs reg,
+                             MV_U32          *pValue,
+                             MV_U32          entry)
+{
+  MV_STATUS          rcode;
+  S_asicGlobalRegDb *pRegEntry = NULL;
+  MV_U32             regAddr;
+  MV_U32             baseAddr;
+  MV_U32             regValue;
+
+  rcode = asicOntGlbRegValidation(reg, &pRegEntry, entry, funcRegR);
+  if (rcode != MV_OK)
+    return(rcode);
+
+  baseAddr = pRegEntry->address;
+
+  /* Absolute register address */
+  regAddr = (baseAddr + (pRegEntry->tblEntrySize *
+                         entry                   *
+                         sizeof (MV_U32)));
+
+  /* Read the value of the register */
+  regValue = MV_REG_READ(ponOnuGlbAddr + regAddr);
+
+  *pValue = ((regValue >> (pRegEntry->shift)) & (pRegEntry->mask));
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  asicOntGlbRegWrite
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Write the contents of MV_U32 ASIC register
+**
+**  PARAMETERS:  E_asicGlobalRegs reg
+**               MV_U32           value
+**               MV_U32           entry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS asicOntGlbRegWrite(E_asicGlobalRegs reg,
+                              MV_U32          value,
+                              MV_U32          entry)
+{
+  MV_STATUS          rcode;
+  S_asicGlobalRegDb *pRegEntry = NULL;
+  MV_U32             regAddr;
+  MV_U32             tempValue;
+  MV_U32             baseAddr;
+
+  rcode = asicOntGlbRegValidation(reg, &pRegEntry, entry, funcRegW);
+  if (rcode != MV_OK)
+    return(rcode);
+
+  baseAddr = pRegEntry->address;
+
+  /* Absolute register address */
+  regAddr = (baseAddr + (pRegEntry->tblEntrySize *
+                         entry                   *
+                         sizeof (MV_U32)));
+
+  tempValue = MV_REG_READ(ponOnuGlbAddr + regAddr);
+
+  /* Clear field */
+  tempValue &= ~((pRegEntry->mask) << (pRegEntry->shift));
+
+  /* Set field */
+  tempValue |= (((value) & (pRegEntry->mask)) << (pRegEntry->shift));
+
+  /* Write the value of the register */
+  MV_REG_WRITE((ponOnuGlbAddr + regAddr) , tempValue);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  asicOntGlbRegReadNoCheck
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Read fast (with no checkings) the contents of MV_U32 ASIC register
+**
+**  PARAMETERS:  E_asicGlobalRegs reg
+**               MV_U32           *pValue
+**               MV_U32           entry
+**
+**  OUTPUTS:     a_value_p
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS asicOntGlbRegReadNoCheck(E_asicGlobalRegs reg,
+                                     MV_U32         *pValue,
+                                     MV_U32         entry)
+{
+  S_asicGlobalRegDb *pRegEntry = NULL;
+  MV_U32             regAddr;
+  MV_U32             baseAddr;
+  MV_U32             regValue;
+
+  /* Check range */
+  if (reg >= mvAsicReg_MAX_NUM_OF_REGS)
+    return(MV_ERROR);
+
+  /* Get the register entry in DB */
+  pRegEntry = &(asicGlbDb[reg]);
+
+  /* Update the access count to this register */
+  pRegEntry->accessCount++;
+
+  baseAddr = pRegEntry->address;
+
+  /* Absolute register address */
+  regAddr = (baseAddr + (pRegEntry->tblEntrySize *
+                         entry                   *
+                         sizeof (MV_U32)));
+
+  /* Read the value of the register */
+  regValue = MV_REG_READ(ponOnuGlbAddr + regAddr);
+
+  *pValue = ((regValue >> (pRegEntry->shift)) & (pRegEntry->mask));
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  asicOntGlbRegWriteNoCheck
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Write fast (with no checkings) the contents of MV_U32 ASIC register
+**
+**  PARAMETERS:  E_asicGlobalRegs reg
+**               MV_U32           value
+**               MV_U32           entry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS asicOntGlbRegWriteNoCheck(E_asicGlobalRegs reg,
+                                       MV_U32        value,
+                                       MV_U32        entry)
+{
+  S_asicGlobalRegDb *pRegEntry = NULL;
+  MV_U32             regAddr;
+  MV_U32             tempValue;
+  MV_U32             baseAddr;
+
+  /* Check range */
+  if (reg >= mvAsicReg_MAX_NUM_OF_REGS)
+    return(MV_ERROR);
+
+  /* Get the register entry in DB */
+  pRegEntry = &(asicGlbDb[reg]);
+
+  /* Update the access count to this register */
+  pRegEntry->accessCount++;
+
+  baseAddr = pRegEntry->address;
+
+  /* Absolute register address */
+  regAddr = (baseAddr + (pRegEntry->tblEntrySize *
+                         entry                   *
+                         sizeof (MV_U32)));
+
+  tempValue = MV_REG_READ(ponOnuGlbAddr + regAddr);
+
+  /* Clear field */
+  tempValue &= ~((pRegEntry->mask) << (pRegEntry->shift));
+
+  /* Set field */
+  tempValue |= (((value) & (pRegEntry->mask)) << (pRegEntry->shift));
+
+  /* Write the value of the register */
+  MV_REG_WRITE((ponOnuGlbAddr + regAddr) , tempValue);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  asicOntGlbSerdesRegWrite
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Write the contents of MV_U32 ASIC register
+**
+**  PARAMETERS:  E_asicGlobalRegs reg
+**               MV_U32           value
+**               MV_U32           entry
+**
+**  OUTPUTS:     None
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS asicOntMiscRegWrite(E_asicGlobalRegs reg,
+                                MV_U32         value,
+                                MV_U32         entry)
+{
+  MV_STATUS          rcode;
+  S_asicGlobalRegDb *pRegEntry = NULL;
+  MV_U32             regAddr;
+  MV_U32             tempValue;
+  MV_U32             baseAddr;
+
+
+  rcode = asicOntGlbRegValidation(reg, &pRegEntry, entry, funcRegW);
+  if (rcode != MV_OK)
+    return(rcode);
+
+  baseAddr = pRegEntry->address;
+
+  /* Absolute register address */
+  regAddr = (baseAddr + (pRegEntry->tblEntrySize *
+                         entry                   *
+                         sizeof (MV_U32)));
+
+  tempValue = MV_REG_READ(regAddr);
+
+  /* Clear field */
+  tempValue &= ~((pRegEntry->mask) << (pRegEntry->shift));
+
+  /* Set field */
+  tempValue |= (((value) & (pRegEntry->mask)) << (pRegEntry->shift));
+
+  /* Write the value of the register */
+  MV_REG_WRITE(regAddr , tempValue);
+
+  return(MV_OK);
+}
+
+/*******************************************************************************
+**
+**  asicOntMiscRegRead
+**  ____________________________________________________________________________
+**
+**  DESCRIPTION: Read the contents of MV_U32 ASIC register
+**
+**  PARAMETERS:  E_asicGlobalRegs reg
+**               MV_U32           *pValue
+**               MV_U32           entry
+**
+**  OUTPUTS:     a_value_p
+**
+**  RETURNS:     MV_OK or error
+**
+*******************************************************************************/
+MV_STATUS asicOntMiscRegRead(E_asicGlobalRegs reg,
+                             MV_U32          *pValue,
+                             MV_U32          entry)
+{
+  MV_STATUS          rcode;
+  S_asicGlobalRegDb *pRegEntry = NULL;
+  MV_U32             regAddr;
+  MV_U32             baseAddr;
+  MV_U32             regValue;
+
+  rcode = asicOntGlbRegValidation(reg, &pRegEntry, entry, funcRegR);
+  if (rcode != MV_OK)
+    return(rcode);
+
+  baseAddr = pRegEntry->address;
+
+  /* Absolute register address */
+  regAddr = (baseAddr + (pRegEntry->tblEntrySize *
+                         entry                   *
+                         sizeof (MV_U32)));
+
+  /* Read the value of the register */
+  regValue = MV_REG_READ(regAddr);
+
+  *pValue = ((regValue >> (pRegEntry->shift)) & (pRegEntry->mask));
+
+  return(MV_OK);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.h b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.h
new file mode 100755
index 0000000..6fa151b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/pon/mvPonOnuRegs.h
@@ -0,0 +1,698 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _ONU_GPON_REG_H
+#define _ONU_GPON_REG_H
+
+/* Include Files
+------------------------------------------------------------------------------*/
+
+/* Definitions
+------------------------------------------------------------------------------*/
+#define MV_ASIC_ONT_BASE (0)
+
+//#define KW2_ASIC
+/* Enums
+------------------------------------------------------------------------------*/
+
+/* ========================== */
+/* = New ASIC Register Enum = */
+/* ========================== */
+typedef enum
+{
+/* Enumeration                         	                Description                        */
+/* ======================================================================================= */
+  mvAsicReg_Start                               = 0,
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           =========   =========   =========   ===       ==           == */
+/* ==           =========   =========   =========   ====      ==           == */
+/* ==           ==          ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==          ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           =========   =========   ==     ==   ==   ==   ==           == */
+/* ==           =========   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==     ==   ==          ==     ==   ==     == ==           == */
+/* ==           ==     ==   ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+
+  /* Interrupt Registers */
+  /* =================== */
+  mvAsicReg_GPON_INTERRUPT_PON                  = 1,    /* GponMainInterrupt               */
+  mvAsicReg_GPON_INTERRUPT_PON_MASK             = 2,    /* GponMainInterruptMask           */
+  mvAsicReg_BIP_INTR_INTERVAL                   = 3,    /* GponBipInterruptCfgInterval     */
+  mvAsicReg_RX_BIP_STATUS_FOR_INTERRUPT         = 4,    /* GponBipInterruptStatAccumulator */
+  mvAsicReg_RAM_TEST_CONFIG                     = 5,    /* RamTestCfg                      */
+
+  /* General Registers */
+  /* ================= */
+  mvAsicReg_GPON_GEN_MAC_VERSION                = 6,    /* GenMACVersion                   */
+  mvAsicReg_GPON_GEN_MAC_VERSION_ID             = 7,
+  mvAsicReg_GPON_GEN_MAC_VERSION_MAC_ID         = 8,
+  mvAsicReg_GPON_GEN_MAC_SCRATCH                = 9,    /* GenMACScratch                   */
+  mvAsicReg_GPON_ONU_STATE                      = 10,   /* GenONUState                     */
+  mvAsicReg_GPON_GEN_MICRO_SEC_CNT              = 11,   /* GenMicroSecCnt                  */
+  mvAsicReg_GPON_TX_SERIAL_NUMBER               = 12,   /* GenSerialNumber                 */
+  mvAsicReg_GPON_ONU_ID                         = 13,   /* GenONUId                        */
+  mvAsicReg_GPON_ONU_ID_OID                     = 14,
+  mvAsicReg_GPON_ONU_ID_V                       = 15,
+
+  /* RX Registers */
+  /* ============ */
+  mvAsicReg_GPON_RX_CONFIG                      = 18,   /* GrxCfg                          */
+  mvAsicReg_GPON_RX_CONFIG_EN                   = 19,
+  mvAsicReg_GPON_RX_CONFIG_BIT_ORDER            = 20,
+  mvAsicReg_GPON_RX_PSA_CONFIG                  = 21,   /* GrxCfgPsa                       */
+  mvAsicReg_GPON_RX_PSA_CONFIG_SFM3             = 22,
+  mvAsicReg_GPON_RX_PSA_CONFIG_SFM2             = 23,
+  mvAsicReg_GPON_RX_PSA_CONFIG_SFM1             = 24,
+  mvAsicReg_GPON_RX_PSA_CONFIG_FHM1             = 25,
+  mvAsicReg_GPON_RX_FEC_CONFIG                  = 26,   /* GrxCfgFec                       */
+  mvAsicReg_GPON_RX_FEC_CONFIG_SWVAL            = 27,
+  mvAsicReg_GPON_RX_FEC_CONFIG_FSW              = 28,
+  mvAsicReg_GPON_RX_FEC_CONFIG_IGNP             = 29,
+  mvAsicReg_GPON_RX_FEC_CONFIG_IND              = 30,
+  mvAsicReg_GPON_RX_FEC_STAT0                   = 31,   /* GrxStatFec0                     */
+  mvAsicReg_GPON_RX_FEC_STAT1                   = 32,   /* GrxStatFec1                     */
+  mvAsicReg_GPON_RX_FEC_STAT2                   = 33,   /* GrxStatFec2                     */
+  mvAsicReg_GPON_RX_SFRAME_COUNTER              = 34,   /* GrxStatSuperFrameCnt            */
+  mvAsicReg_GPON_RX_PLOAMD_DATA_READ            = 35,   /* GrxDataPloamRead                */
+  mvAsicReg_GPON_RX_PLOAMD_DATA_USED            = 36,   /* GrxDataPloamUsed                */
+  mvAsicReg_GPON_RX_PLOAMD_CONFIG               = 37,   /* GrxCfgPrm                       */
+  mvAsicReg_GPON_RX_PLOAMD_CONFIG_IGNC          = 38,
+  mvAsicReg_GPON_RX_PLOAMD_CONFIG_IGNB          = 39,
+  mvAsicReg_GPON_RX_PLOAMD_CONFIG_FALL          = 40,
+  mvAsicReg_GPON_RX_PLOAMD_LOST_CRC_STATUS      = 41,   /* GrxStatPrmLostCrcCnt            */
+  mvAsicReg_GPON_RX_PLOAMD_LOST_FULL_STATUS     = 42,   /* GrxStatPrmLostFullCnt           */
+  mvAsicReg_GPON_RX_PLOAMD_RCVD_IDLE_STATUS     = 43,   /* GrxStatPrmRcvdIdleCnt           */
+  mvAsicReg_GPON_RX_PLOAMD_RCVD_BROAD_STATUS    = 44,   /* GrxStatPrmRcvdBroadCnt          */
+  mvAsicReg_GPON_RX_PLOAMD_RCVD_MYID_STATUS     = 45,   /* GrxStatPrmRcvdMyIdCnt           */
+  mvAsicReg_GPON_RX_BIP_STATUS                  = 46,   /* GrxStatBip                      */
+  mvAsicReg_GPON_RX_PLEND_CONFIG                = 47,   /* GrxCfgPdb                       */
+  mvAsicReg_GPON_RX_PLEND_CONFIG_FN             = 48,
+  mvAsicReg_GPON_RX_PLEND_CONFIG_UF             = 49,
+  mvAsicReg_GPON_RX_PLEND_CONFIG_IGND           = 50,
+  mvAsicReg_GPON_RX_PLEND_CONFIG_DFIX           = 51,
+  mvAsicReg_GPON_RX_PLEND_CONFIG_IGNC           = 52,
+  mvAsicReg_GPON_RX_PLEND_STATUS                = 53,   /* GrxStatPdb                      */
+  mvAsicReg_GPON_RX_BWMAP_CONFIG                = 54,   /* GrxCfgBmd                       */
+  mvAsicReg_GPON_RX_BWMAP_CONFIG_MSD            = 55,
+  mvAsicReg_GPON_RX_BWMAP_CONFIG_DFIX           = 56,
+  mvAsicReg_GPON_RX_BWMAP_CONFIG_IGNC           = 57,
+  mvAsicReg_GPON_RX_BWMAP_STATUS0               = 58,   /* GrxStatBmd0                     */
+  mvAsicReg_GPON_RX_BWMAP_STATUS1               = 59,   /* GrxStatBmd1                     */
+  mvAsicReg_GPON_RX_AES_CONFIG                  = 60,   /* GrxCfgAesKeySwitch              */
+  mvAsicReg_GPON_RX_AES_CONFIG_TIME             = 61,   /* GrxStatAesKeySwitch             */
+  mvAsicReg_GPON_RX_AES_CONFIG_SWS              = 62,
+  mvAsicReg_GPON_RX_AES_STATUS                  = 63,
+  mvAsicReg_GPON_RX_AES_STATUS_HST              = 64,
+  mvAsicReg_GPON_RX_AES_STATUS_HWS              = 65,
+  mvAsicReg_GPON_RX_EQULIZATION_DELAY           = 66,   /* GrxCfgEqDelay                   */
+  mvAsicReg_GPON_RX_INTERNAL_DELAY              = 67,   /* GrxCfgInterDelay                */
+  mvAsicReg_GPON_RX_BW_MAP                      = 68,   /* GrxCfgBmdMapTcont               */
+  mvAsicReg_GPON_RX_BW_MAP_ALID                 = 60,
+  mvAsicReg_GPON_RX_BW_MAP_TCN                  = 70,
+  mvAsicReg_GPON_RX_BW_MAP_EN                   = 71,
+
+  /* GEM Registers */
+  /* ============= */
+  mvAsicReg_GPON_GEM_STAT_IDLE_GEM_CNT          = 72,   /* GemStatIdleGEMCnt               */
+  mvAsicReg_GPON_GEM_STAT_VALID_GEM_CNT         = 73,   /* GemStatValidGEMCnt              */
+  mvAsicReg_GPON_GEM_STAT_UNDEF_GEM_CNT         = 74,   /* GemStatUndefGEMCnt              */
+  mvAsicReg_GPON_GEM_STAT_VALID_OMCI_CNT        = 75,   /* GemStatValidOMCICnt             */
+  mvAsicReg_GPON_GEM_STAT_DROPPED_GEM_CNT       = 76,   /* GemStatDroppedGEMCnt            */
+  mvAsicReg_GPON_GEM_STAT_DROPPED_OMCI_CNT      = 77,   /* GemStatDroppedOMCICnt           */
+  mvAsicReg_GPON_GEM_STAT_ERROR_GEM_CNT         = 78,   /* GemStatErrorGEMCnt              */
+  mvAsicReg_GPON_GEM_STAT_ONE_FIXED_HEC_ERR_CNT = 79,   /* GemStatOneFixedHecErrCnt        */
+  mvAsicReg_GPON_GEM_STAT_TWO_FIXED_HEC_ERR_CNT = 80,   /* GemStatTwoFixedHecErrCnt        */
+  mvAsicReg_GPON_GEM_STAT_VALID_GEM_PAYLOAD_CNT = 81,   /* GemStatValidGEMPayload          */
+  mvAsicReg_GPON_GEM_STAT_UNDEF_GEM_PAYLOAD_CNT = 82,   /* GemStatUndefGEMPayload          */
+  mvAsicReg_GPON_GEM_STAT_RSMBL_MEM_FLUSH_CNT   = 83,   /* GemStatRsmblMemFlushCnt         */
+  mvAsicReg_GPON_GEM_STAT_LCDGi_CNT             = 84,   /* GemStatLCDGiCnt                 */
+  mvAsicReg_GPON_GEM_STAT_CORR_ETH_FRAME_CNT    = 85,   /* GemStatCorrEthFrameCnt          */
+  mvAsicReg_GPON_GEM_STAT_ERR_ETH_FRAME_CNT     = 86,   /* GemStatErrEthFrameCnt           */
+  mvAsicReg_GPON_GEM_STAT_CORR_OMCI_FRAME_CNT   = 87,   /* GemStatCorrOMCIFrameCnt         */
+  mvAsicReg_GPON_GEM_STAT_ERR_OMCI_FRAME_CNT    = 88,   /* GemStatErrOMCIFrameCnt          */
+  mvAsicReg_GPON_GEM_CONFIG_PLI                 = 89,   /* GemCfgPLI                       */
+  mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN       = 90,   /* GemCfgEthLength                 */
+  mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MAX   = 91,
+  mvAsicReg_GPON_GEM_CONFIG_ETH_FRAME_LEN_MIN   = 92,
+  mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN      = 93,   /* GemCfgOMCILength                */
+  mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MAX  = 94,
+  mvAsicReg_GPON_GEM_CONFIG_OMCI_FRAME_LEN_MIN  = 95,
+  mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT           = 96,   /* GemCfgOMCIPort                  */
+  mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_ID        = 97,
+  mvAsicReg_GPON_GEM_CONFIG_OMCI_PORT_VALID     = 98,
+  mvAsicReg_GPON_GEM_CONFIG_AES                 = 99,   /* GemCfgAES                       */
+  mvAsicReg_GPON_GEM_AES_SHADOW_KEY             = 100,   /* GemCfgAESShadowKey0/1/2/3       */
+  mvAsicReg_GPON_GEM_CFG_IPG_VALUE              = 101,   /* GemCfgIPGValue                  */
+  mvAsicReg_GPON_GEM_CFG_IPG_VALID              = 102,  /* GemCfgIPGValid                  */
+
+  /* TX Registers */
+  /* ============ */
+  mvAsicReg_GPON_TX_PREAMBLE                    = 103,   /* GtxCfgPreamble0/1/2             */
+  mvAsicReg_GPON_TX_PREAMBLE_PATT               = 104,
+  mvAsicReg_GPON_TX_PREAMBLE_SIZE               = 105,
+  mvAsicReg_GPON_TX_DELIMITER                   = 106,  /* GtxCfgDelimiter                 */
+  mvAsicReg_GPON_TX_DELIMITER_PAT               = 107,
+  mvAsicReg_GPON_TX_DELIMITER_SIZE              = 108,
+  mvAsicReg_GPON_TX_BURST_EN_PARAM              = 109,  /* GtxCfgBurstEnable               */
+  mvAsicReg_GPON_TX_BURST_EN_PARAM_STR          = 110,
+  mvAsicReg_GPON_TX_BURST_EN_PARAM_STP          = 111,
+  mvAsicReg_GPON_TX_BURST_EN_PARAM_DLY          = 112,
+  mvAsicReg_GPON_TX_BURST_EN_PARAM_P            = 113,
+  mvAsicReg_GPON_TX_BURST_EN_PARAM_MASK         = 114,
+  mvAsicReg_GPON_TX_FDELAY                      = 115,  /* GtxCfgFinelDelay                */
+  mvAsicReg_GPON_TX_PLOAM_DATA_WRITE            = 116,  /* GtxDataPloamWrite               */
+  mvAsicReg_GPON_TX_PLOAM_DATA_WRITE_FREE       = 117,  /* GtxDataPloamStatus              */
+  mvAsicReg_GPON_TX_PLS_CONSTANT                = 118,  /* GtxCfgPls                       */
+  mvAsicReg_GPON_TX_DBR_REPORT_BLOCK_IDX        = 119,  /* GtxCfgDbr                       */
+  mvAsicReg_GPON_TX_FE_RDI_INDICATION           = 120,  /* GtxCfgRdi                       */
+  mvAsicReg_GPON_TX_STAT_GEM_PTI1               = 121,  /* GtxStatGemPti1                  */
+  mvAsicReg_GPON_TX_STAT_GEM_PTI0               = 122,  /* GtxStatGemPti0                  */
+  mvAsicReg_GPON_TX_STAT_GEM_IDLE               = 123,  /* GtxStatGemIdle                  */
+  mvAsicReg_GPON_TX_STAT_TX_EN_CNT              = 124,  /* GtxStatTxEnableCounter          */
+  mvAsicReg_GPON_TX_CONFIG_EN_THRESHOLD         = 125,  /* GtxCfgTxEnableThreshold         */
+  mvAsicReg_GPON_TX_GSE_TRANS_THRESHOLD         = 126,  /* GtxCfgGseTransThreshold         */
+  mvAsicReg_GPON_TX_CFG_AC_COUPLING             = 127,  /* GtxCfgAcCoupling                */
+  mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_FRAMES     = 129,  /* GtxStatTcontiEtherFrames        */
+  mvAsicReg_GPON_TX_STAT_TCONT_i_ETH_BYTES      = 130,  /* GtxStatTcontiEtherBytes         */
+  mvAsicReg_GPON_TX_STAT_TCONT_i_GEM_FRAMES     = 131,  /* GtxStatTcontiGemFrames          */
+  mvAsicReg_GPON_TX_STAT_TCONT_i_IDLE_GEM       = 132,  /* GtxStatTcontiIdleGem            */
+
+  /* UTM Registers */
+  /* ============= */
+  mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_ID        = 133,  /* UtmCfgOmciPnum                  */
+  mvAsicReg_GPON_UTM_CONFIG_OMCI_PORT_VALID     = 134,  /* UtmCfgOmciPvalid                */
+  mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD           = 135,  /* UtmCfgTcPeriod                  */
+  mvAsicReg_GPON_UTM_CONFIG_TC_PERIOD_VALID     = 136,  /* UtmCfgTcPeriodValid             */
+
+  /* SGL Registers */
+  /* ============= */
+  mvAsicReg_GPON_SGL_SW_RESET                   = 139,  /* SglSwResetReg                   */
+  mvAsicReg_GPON_SGL_CONFIG_REG                 = 140,  /* SglCfgReg                       */
+  mvAsicReg_GPON_SGL_STATS_REG                  = 141,  /* SglStatReg                      */
+
+  /*  Memory Registers           */
+  /* =========================== */
+  mvAsicReg_GPON_TX_CONST_DATA_RAM              = 142,
+  mvAsicReg_GPON_TX_CONST_DATA_RAM_IDLE         = 143,
+  mvAsicReg_GPON_TX_CONST_DATA_RAM_SN           = 144,
+  mvAsicReg_GPON_GEM_AES_PID_TABLE              = 145,
+  mvAsicReg_GPON_GEM_VALID_PID_TABLE            = 146,
+  mvAsicReg_GPON_TEST                           = 147,
+
+  /*  GPON MIB Counter Set       */
+  /* =========================== */
+  mvAsicReg_PON_MAC_MIB_COUNTERS_0              = 148,
+  mvAsicReg_PON_MAC_MIB_COUNTERS_1              = 149,
+  mvAsicReg_PON_MAC_MIB_COUNTERS_2              = 150,
+  mvAsicReg_PON_MAC_MIB_COUNTERS_3              = 151,
+  mvAsicReg_PON_MAC_MIB_COUNTERS_4              = 152,
+  mvAsicReg_PON_MAC_MIB_COUNTERS_5              = 153,
+  mvAsicReg_PON_MAC_MIB_COUNTERS_6              = 154,
+  mvAsicReg_PON_MAC_MIB_COUNTERS_7              = 155,
+
+  /*  GPON MIB Counter Control Registers */
+  /* =================================== */
+  mvAsicReg_RX_MIB_CTRL                         = 156,
+  mvAsicReg_RX_MIB_DEFAULT                      = 157,
+
+
+/******************************************************************************/
+/******************************************************************************/
+/* ========================================================================== */
+/* ========================================================================== */
+/* ==                                                                      == */
+/* ==           =========   =========   =========   ===       ==           == */
+/* ==           =========   =========   =========   ====      ==           == */
+/* ==           ==          ==     ==   ==     ==   == ==     ==           == */
+/* ==           ==          ==     ==   ==     ==   ==  ==    ==           == */
+/* ==           =========   =========   ==     ==   ==   ==   ==           == */
+/* ==           =========   =========   ==     ==   ==    ==  ==           == */
+/* ==           ==          ==          ==     ==   ==     == ==           == */
+/* ==           ==          ==          ==     ==   ==      ====           == */
+/* ==           =========   ==          =========   ==       ===           == */
+/* ==           =========   ==          =========   ==        ==           == */
+/* ==                                                                      == */
+/* ========================================================================== */
+/* ========================================================================== */
+/******************************************************************************/
+/******************************************************************************/
+
+  /*  EPON Interrupt Registers   */
+  /* =========================== */
+  mvAsicReg_EPON_INTR_REG                            = 180,
+  mvAsicReg_EPON_INTR_MASK                           = 181,
+
+  /*  EPON General Registers     */
+  /* =========================== */
+  mvAsicReg_EPON_GEN_MAC_VERSION_ADDR                = 184,
+  mvAsicReg_EPON_GEN_ONT_ENABLE                      = 185,
+  mvAsicReg_EPON_GEN_ONT_RX_ENABLE                   = 186,
+  mvAsicReg_EPON_GEN_ONT_TX_ENABLE                   = 187,
+  mvAsicReg_EPON_GEN_ONT_STATE                       = 188,
+  mvAsicReg_EPON_GEN_ONT_STATE_REG_AUTO_EN           = 189,
+  mvAsicReg_EPON_GEN_ONT_STATE_REG                   = 190,
+  mvAsicReg_EPON_GEN_ONT_STATE_REREG_AUTO_EN         = 191,
+  mvAsicReg_EPON_GEN_ONT_STATE_DEREG_AUTO_EN         = 192,
+  mvAsicReg_EPON_GEN_ONT_STATE_NACK_AUTO_EN          = 193,
+  mvAsicReg_EPON_GEN_TQ_SIZE                         = 194,
+  mvAsicReg_EPON_GEN_LASER_PARAM                     = 195,
+  mvAsicReg_EPON_GEN_TAIL_GUARD                      = 196,
+  mvAsicReg_EPON_GEN_SYNC_TIME                       = 197,
+  mvAsicReg_EPON_GEN_BROADCAST_ADDR_LOW              = 198,
+  mvAsicReg_EPON_GEN_BROADCAST_ADDR_HIGH             = 199,
+  mvAsicReg_EPON_GEN_CONFIGURATION                   = 200,
+  mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_REPORT       = 201,
+  mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_ACK          = 202,
+  mvAsicReg_EPON_GEN_CONFIGURATION_AUTO_REQUEST      = 203,
+  mvAsicReg_EPON_GEN_SLD                             = 204,
+  mvAsicReg_EPON_GEN_MAC_CONTROL_TYPE                = 205,
+  mvAsicReg_EPON_GEN_LOCAL_TIMESTAMP                 = 206,
+  mvAsicReg_EPON_GEN_NUM_OF_PENDING_GRANTS           = 207,
+  mvAsicReg_EPON_GEN_SGL_STATUS                      = 208,
+  mvAsicReg_EPON_GEN_PON_PHY_DEBUG                   = 209,
+  mvAsicReg_EPON_GEN_SGL_SW_RESET                    = 210,
+  mvAsicReg_EPON_GEN_SGL_CONFIG                      = 211,
+  mvAsicReg_EPON_GEN_SGL_DEBOUNCE_CONFIG             = 212,
+  mvAsicReg_EPON_GEN_SGL_DEBOUNCE_ENABLE             = 213,
+  mvAsicReg_EPON_GEN_TCH_CHURNING_KEY                = 214,
+  mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE1              = 215,
+  mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE2              = 216,
+  mvAsicReg_EPON_GEN_DRIFT_THRESHOLD                 = 217,
+  mvAsicReg_EPON_GEN_TIMESTAMP_VAL_FOR_INTR          = 218,
+  mvAsicReg_EPON_GEN_ADDITIONAL_OPCODE3              = 219,
+#ifdef PON_Z2
+  mvAsicReg_EPON_GEN_LLID_CRC_CONFIG                 = 220,
+  mvAsicReg_EPON_GEN_TIMESTAMP_CONFIG                = 221,
+  mvAsicReg_EPON_GEN_ONT_RX_TIMESTAMP_CONFIG         = 222,
+  mvAsicReg_EPON_GEN_ONT_REGISTER_PACKET_PADDING     = 223,
+#endif /* PON_Z2 */
+  mvAsicReg_EPON_GEN_MAC_ADDR_LOW                    = 224,
+  mvAsicReg_EPON_GEN_MAC_ADDR_HIGH                   = 225,
+  mvAsicReg_EPON_GEN_UTM_TC_PERIOD                   = 226,
+  mvAsicReg_EPON_GEN_UTM_TC_PERIOD_VALID             = 227,
+  mvAsicReg_EPON_GEN_GEM_IPG_VAL                     = 228,
+  mvAsicReg_EPON_GEN_GEM_IPG_VAL_VALID               = 229,
+
+  /*  EPON RXP Registers         */
+  /* =========================== */
+  mvAsicReg_EPON_RXP_PACKET_SIZE_LIMIT               = 233,
+  mvAsicReg_EPON_RXP_PACKET_FILTER                   = 234,
+  mvAsicReg_EPON_RXP_CTRL_FRAME_FORWARD              = 235,
+  mvAsicReg_EPON_RXP_LLT_LLID_DATA                   = 236,
+  mvAsicReg_EPON_RXP_LLT_LLID_DATA_VALUE             = 237,
+  mvAsicReg_EPON_RXP_LLT_LLID_DATA_INDEX             = 238,
+  mvAsicReg_EPON_RXP_LLT_LLID_DATA_VALID             = 239,
+  mvAsicReg_EPON_RXP_ENCRYPTION_CONFIG               = 240,
+  mvAsicReg_EPON_RXP_ENCRYPTION_KEY0                 = 241,
+  mvAsicReg_EPON_RXP_ENCRYPTION_KEY1                 = 242,
+  mvAsicReg_EPON_RXP_DATA_FIFO_THRESH                = 243,
+
+  /*  EPON GPM Registers         */
+  /* =========================== */
+  mvAsicReg_EPON_GPM_MAX_FUTURE_GRANT_TIME           = 250,
+  mvAsicReg_EPON_GPM_MIN_PROCESSING_TIME             = 251,
+  mvAsicReg_EPON_GPM_DISCOVERY_GRANT_LENGTH          = 252,
+  mvAsicReg_EPON_GPM_RX_SYNC_TIME                    = 253,
+  mvAsicReg_EPON_GPM_GRANT_VALID                     = 254,
+  mvAsicReg_EPON_GPM_GRANT_MAX_FUTURE_TIME_ERR       = 255,
+  mvAsicReg_EPON_GPM_MIN_PROC_TIME_ERR               = 256,
+  mvAsicReg_EPON_GPM_LENGTH_ERR                      = 257,
+  mvAsicReg_EPON_GPM_DISCOVERY_AND_REGISTERED_ERR    = 258,
+  mvAsicReg_EPON_GPM_FIFO_FULL_ERR                   = 259,
+  mvAsicReg_EPON_GPM_OPC_DISC_NOT_REG_BCAST          = 260,
+  mvAsicReg_EPON_GPM_OPC_REG_NOT_DISC                = 261,
+  mvAsicReg_EPON_GPM_OPC_DISC_NOT_REG_NOT_BCAST      = 262,
+  mvAsicReg_EPON_GPM_OPC_DROPED_GRANT                = 263,
+  mvAsicReg_EPON_GPM_OPC_HIDDEN_GRANT                = 264,
+  mvAsicReg_EPON_GPM_OPC_BACK_TO_BACK_GRANT          = 265,
+
+  /*  EPON TXM Registers         */
+  /* =========================== */
+  mvAsicReg_EPON_TXM_DEFAULT_OVERHEAD                = 266,
+  mvAsicReg_EPON_TXM_CONFIGURATION                   = 267,
+  mvAsicReg_EPON_TXM_TX_LLID                         = 269,
+  mvAsicReg_EPON_TXM_CPP_RPRT_CONFIG                 = 270,
+  mvAsicReg_EPON_TXM_CPP_RPRT_BIT_MAP                = 271,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_SET              = 272,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_0                = 273,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_1                = 274,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_2                = 275,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_3                = 276,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_4                = 277,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_5                = 278,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_6                = 279,
+  mvAsicReg_EPON_TXM_CPP_RPRT_QUEUE_7                = 280,
+  mvAsicReg_EPON_TXM_CPP_RPRT_FEC_CONFIG             = 281,
+
+  /*  EPON PCS Registers         */
+  /* =========================== */
+  mvAsicReg_EPON_PCS_CONFIGURATION                   = 284,
+  mvAsicReg_EPON_PCS_DELAY_CONFIG                    = 285,
+  mvAsicReg_EPON_PCS_STATS_FEC_0                     = 286,
+  mvAsicReg_EPON_PCS_STATS_FEC_1                     = 287,
+  mvAsicReg_EPON_PCS_STATS_FEC_2                     = 288,
+  mvAsicReg_EPON_PCS_STATS_0                         = 290,
+  mvAsicReg_EPON_PCS_STATS_1                         = 291,
+  mvAsicReg_EPON_PCS_STATS_2                         = 292,
+  mvAsicReg_EPON_PCS_STATS_3                         = 293,
+  mvAsicReg_EPON_PCS_STATS_4                         = 294,
+  mvAsicReg_EPON_PCS_FRAME_SZ_LIMITS                 = 295,
+
+  /*  EPON DDM Registers         */
+  /* =========================== */
+  mvAsicReg_EPON_DDM_DELAY_CONFIG                    = 296,
+  mvAsicReg_EPON_DDM_TX_POLARITY                     = 297,
+  /* statistics */
+  mvAsicReg_EPON_STAT_RXP_FCS_ERROR_CNT              = 298,
+  mvAsicReg_EPON_STAT_RXP_SHORT_ERROR_CNT            = 299,
+  mvAsicReg_EPON_STAT_RXP_LONG_ERROR_CNT             = 300,
+  mvAsicReg_EPON_STAT_RXP_DATA_FRAMES_CNT            = 301,
+  mvAsicReg_EPON_STAT_RXP_CTRL_FRAMES_CNT            = 302,
+  mvAsicReg_EPON_STAT_RXP_REPORT_FRAMES_CNT          = 303,
+  mvAsicReg_EPON_STAT_RXP_GATE_FRAMES_CNT            = 304,
+  mvAsicReg_EPON_STAT_TXP_CTRL_REG_REQ_FRAMES_CNT    = 305,
+  mvAsicReg_EPON_STAT_TXP_CTRL_REG_ACK_FRAMES_CNT    = 306,
+  mvAsicReg_EPON_STAT_TXP_CTRL_REPORT_FRAMES_CNT     = 307,
+  mvAsicReg_EPON_STAT_TXP_DATA_FRAMES_CNT            = 308,
+  mvAsicReg_EPON_STAT_TXP_TX_ALLOWED_BYTE_CNT        = 309,
+
+  /*  EPON Control Packet queue Registers   */
+  /* =====================================  */
+  mvAsicReg_EPON_CPQ_RX_CTRL_Q_READ                  = 310,
+  mvAsicReg_EPON_CPQ_RX_CTRL_Q_USED                  = 311,
+  mvAsicReg_EPON_CPQ_RX_RPRT_Q_READ                  = 312,
+  mvAsicReg_EPON_CPQ_RX_RPRT_Q_USED                  = 313,
+  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_L               = 314,
+  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_READ_H               = 315,
+  mvAsicReg_EPON_CPQ_RX_CTRL_HQ_USED                 = 316,
+  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_L               = 317,
+  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_READ_H               = 318,
+  mvAsicReg_EPON_CPQ_RX_RPRT_HQ_USED                 = 319,
+  mvAsicReg_EPON_CPQ_TX_CTRL_Q_WRITE                 = 320,
+  mvAsicReg_EPON_CPQ_TX_CTRL_Q_FREE                  = 321,
+  mvAsicReg_EPON_CPQ_TX_CTRL_HQ_WRITE                = 322,
+  mvAsicReg_EPON_CPQ_TX_CTRL_HQ_FREE                 = 323,
+
+
+  /*  P2P Registers                         */
+  /* =====================================  */
+  mvAsicReg_P2P_GEN_ONT_MODE                         = 330,
+  mvAsicReg_P2P_PCS_CONFIGURATION                    = 331,
+  mvAsicReg_P2P_TXM_CFG_MODE                         = 332,
+
+#ifndef PON_FPGA
+  mvAsicReg_PON_SERDES_PHY_CTRL_0                    = 333,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_Pll             = 334,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_RX              = 335,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_PU_TX              = 336,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_RST                = 337,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_RST_TX_DOUT        = 338,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_INIT            = 339,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_RX_RATE            = 340,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_GEPON          = 341,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_SEL_REF_CLK        = 342,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_CID_REV            = 343,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_TX_RATE            = 344,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_REF_CLK_25M        = 345,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_INIT_DONE          = 346,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_TX           = 347,
+  mvAsicReg_PON_SERDES_PHY_CTRL_0_READY_RX           = 348,
+  mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_IO_EN          = 349,
+  mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_EN    = 350,
+  mvAsicReg_PON_SERDES_PHY_CTRL_1_FORCE_BEN_IO_VAL   = 351,
+  mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_HW_SELECT   = 352,
+  mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_FORCE       = 353,
+  mvAsicReg_PON_SERDES_PHY_CTRL_1_BEN_SW_VALUE       = 354,
+  mvAsicReg_PON_SERDES_CLK_SEL                       = 355,
+  mvAsicReg_PON_SERDES_CLK_EN                        = 356,
+  mvAsicReg_PON_SERDES_XPON_CTRL                     = 357,
+  mvAsicReg_PON_SERDES_INTERNAL_PASSWORD             = 358,
+  mvAsicReg_PON_SERDES_INTERNAL_EN_LOOP_TIMING       = 359,
+  mvAsicReg_PON_SERDES_INTERNAL_PON_SELECT           = 360,
+  mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR         = 361,
+  mvAsicReg_PON_MAC_GPON_CLK_EN                      = 362,
+  mvAsicReg_PON_MAC_SW_RESET_CTRL                    = 363,
+  mvAsicReg_PON_MPP_00                               = 364,
+  mvAsicReg_PON_MPP_01                               = 365,
+  mvAsicReg_PON_MPP_02                               = 366,
+  mvAsicReg_PON_MPP_03                               = 367,
+  mvAsicReg_PON_MPP_04                               = 368,
+  mvAsicReg_PON_MPP_05                               = 369,
+  mvAsicReg_PON_MPP_06                               = 370,
+  mvAsicReg_PON_MPP_07                               = 371,
+  mvAsicReg_PON_MPP_08                               = 372,
+  mvAsicReg_PON_MPP_09                               = 373,
+  mvAsicReg_PON_MPP_10                               = 374,
+  mvAsicReg_PON_MPP_11                               = 375,
+  mvAsicReg_PON_MPP_12                               = 376,
+  mvAsicReg_PON_MPP_13                               = 377,
+  mvAsicReg_PON_MPP_14                               = 378,
+  mvAsicReg_PON_MPP_15                               = 379,
+  mvAsicReg_PON_MPP_16                               = 380,
+  mvAsicReg_PON_MPP_17                               = 381,
+  mvAsicReg_PON_MPP_18                               = 382,
+  mvAsicReg_PON_MPP_19                               = 383,
+  mvAsicReg_PON_MPP_20                               = 384,
+  mvAsicReg_PON_MPP_21                               = 385,
+  mvAsicReg_PON_MPP_22                               = 386,
+  mvAsicReg_PON_MPP_23                               = 387,
+  mvAsicReg_PON_MPP_24                               = 388,
+  mvAsicReg_PON_MPP_25                               = 389,
+  mvAsicReg_PON_MPP_26                               = 390,
+  mvAsicReg_PON_MPP_27                               = 391,
+  mvAsicReg_PON_MPP_28                               = 392,
+  mvAsicReg_PON_MPP_29                               = 393,
+  mvAsicReg_PON_MPP_30                               = 394,
+  mvAsicReg_PON_MPP_31                               = 395,
+  mvAsicReg_PON_MPP_32                               = 396,
+  mvAsicReg_PON_MPP_33                               = 397,
+  mvAsicReg_PON_MPP_34                               = 398,
+  mvAsicReg_PON_MPP_35                               = 399,
+  mvAsicReg_PON_MPP_36                               = 400,
+  mvAsicReg_PON_MPP_37                               = 401,
+  mvAsicReg_PON_MPP_38                               = 402,
+  mvAsicReg_PON_MPP_39                               = 403,
+  mvAsicReg_PON_MPP_40                               = 404,
+  mvAsicReg_PON_MPP_41                               = 405,
+  mvAsicReg_PON_MPP_42                               = 406,
+  mvAsicReg_PON_MPP_43                               = 407,
+  mvAsicReg_PON_MPP_44                               = 408,
+  mvAsicReg_PON_MPP_45                               = 409,
+  mvAsicReg_PON_MPP_46                               = 410,
+  mvAsicReg_PON_MPP_47                               = 411,
+  mvAsicReg_PON_MPP_48                               = 412,
+  mvAsicReg_PON_MPP_49                               = 413,
+  mvAsicReg_PON_MPP_50                               = 414,
+  mvAsicReg_PON_MPP_51                               = 415,
+  mvAsicReg_PON_MPP_52                               = 416,
+  mvAsicReg_PON_MPP_53                               = 417,
+  mvAsicReg_PON_MPP_54                               = 418,
+  mvAsicReg_PON_MPP_55                               = 419,
+  mvAsicReg_PON_MPP_56                               = 420,
+  mvAsicReg_PON_MPP_57                               = 421,
+  mvAsicReg_PON_MPP_58                               = 422,
+  mvAsicReg_PON_MPP_59                               = 423,
+  mvAsicReg_PON_MPP_60                               = 424,
+  mvAsicReg_PON_MPP_61                               = 425,
+  mvAsicReg_PON_MPP_62                               = 426,
+  mvAsicReg_PON_MPP_63                               = 427,
+  mvAsicReg_PON_MPP_64                               = 428,
+  mvAsicReg_PON_MPP_65                               = 429,
+  mvAsicReg_PON_MPP_66                               = 430,
+  mvAsicReg_PON_MPP_67                               = 431,
+  mvAsicReg_PON_MPP_68                               = 432,
+  mvAsicReg_PON_MPP_69                               = 433,
+  mvAsicReg_PON_XVR_TX_DATA_OUT_17                   = 434,
+  mvAsicReg_PON_XVR_TX_DATA_OUT_37                   = 435,
+  mvAsicReg_PON_XVR_TX_DATA_OUT_68                   = 436,
+  mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_17              = 437,
+  mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_37              = 438,
+  mvAsicReg_PON_XVR_TX_OUTPUT_ENABLE_68              = 439,
+  mvAsicReg_PON_SERDES_INTERNAL_OPEN_TX_DOOR_15      = 440,
+  mvAsicReg_PON_SERDES_POWER_PHY_MODE                = 441,
+  mvAsicReg_PON_SYS_LED_ENABLE                       = 442,
+  mvAsicReg_PON_SYS_LED_STATE                        = 443,
+  mvAsicReg_PON_SYS_LED_BLINK                        = 444,
+  mvAsicReg_PON_SYS_LED_BLINK_FREQ                   = 445,
+  mvAsicReg_PON_SYNC_LED_ENABLE                      = 446,
+  mvAsicReg_PON_SYNC_LED_STATE                       = 447,
+  mvAsicReg_PON_SYNC_LED_BLINK                       = 448,
+  mvAsicReg_PON_SYNC_LED_BLINK_FREQ                  = 449,
+  mvAsicReg_PON_LED_BLINK_FREQ_A_ON                  = 450,
+  mvAsicReg_PON_LED_BLINK_FREQ_A_OFF                 = 451,
+  mvAsicReg_PON_LED_BLINK_FREQ_B_ON                  = 452,
+  mvAsicReg_PON_LED_BLINK_FREQ_B_OFF                 = 453,
+  mvAsicReg_PON_DG_CTRL_EN                           = 454,
+  mvAsicReg_PON_DG_CTRL_POLARITY                     = 455,
+  mvAsicReg_PON_DG_THRESHOLD                         = 456,
+  mvAsicReg_PT_PATTERN_SELECT                        = 457,
+  mvAsicReg_PT_PATTERN_ENABLED                       = 458,
+  mvAsicReg_PT_PATTERN_DATA                          = 459,
+
+  mvAsicReg_GUNIT_TX_0_QUEUES                        = 460,
+  mvAsicReg_GUNIT_TX_1_QUEUES                        = 461,
+  mvAsicReg_GUNIT_TX_2_QUEUES                        = 462,
+  mvAsicReg_GUNIT_TX_3_QUEUES                        = 463,
+  mvAsicReg_GUNIT_TX_4_QUEUES                        = 464,
+  mvAsicReg_GUNIT_TX_5_QUEUES                        = 465,
+  mvAsicReg_GUNIT_TX_6_QUEUES                        = 466,
+  mvAsicReg_GUNIT_TX_7_QUEUES                        = 467,
+
+  mvAsicReg_GUNIT_TX_0_PKT_MOD_MAX_HEAD_SIZE_CFG     = 470,
+  mvAsicReg_GUNIT_TX_1_PKT_MOD_MAX_HEAD_SIZE_CFG     = 471,
+  mvAsicReg_GUNIT_TX_2_PKT_MOD_MAX_HEAD_SIZE_CFG     = 472,
+  mvAsicReg_GUNIT_TX_3_PKT_MOD_MAX_HEAD_SIZE_CFG     = 473,
+  mvAsicReg_GUNIT_TX_4_PKT_MOD_MAX_HEAD_SIZE_CFG     = 474,
+  mvAsicReg_GUNIT_TX_5_PKT_MOD_MAX_HEAD_SIZE_CFG     = 475,
+  mvAsicReg_GUNIT_TX_6_PKT_MOD_MAX_HEAD_SIZE_CFG     = 476,
+  mvAsicReg_GUNIT_TX_7_PKT_MOD_MAX_HEAD_SIZE_CFG     = 477,
+
+  mvAsicReg_GUNIT_TX_0_PKT_MOD_STATS_PKT_COUNT       = 480,
+  mvAsicReg_GUNIT_TX_1_PKT_MOD_STATS_PKT_COUNT       = 481,
+  mvAsicReg_GUNIT_TX_2_PKT_MOD_STATS_PKT_COUNT       = 482,
+  mvAsicReg_GUNIT_TX_3_PKT_MOD_STATS_PKT_COUNT       = 483,
+  mvAsicReg_GUNIT_TX_4_PKT_MOD_STATS_PKT_COUNT       = 484,
+  mvAsicReg_GUNIT_TX_5_PKT_MOD_STATS_PKT_COUNT       = 485,
+  mvAsicReg_GUNIT_TX_6_PKT_MOD_STATS_PKT_COUNT       = 486,
+  mvAsicReg_GUNIT_TX_7_PKT_MOD_STATS_PKT_COUNT       = 487,
+
+#endif /* PON_FPGA */
+  mvAsicReg_MAX_NUM_OF_REGS
+
+} E_asicGlobalRegs;
+
+/* Register access enumeration */
+typedef enum
+{
+  asicRO = 0x01,
+  asicWO = 0x02,
+  asicRW = 0x03
+} E_asicAccessType;
+
+typedef enum
+{
+  funcRegR = 0x00,
+  funcRegW = 0x01
+} E_asicRegFuncType;
+
+/* Typedefs
+------------------------------------------------------------------------------*/
+typedef struct
+{
+  E_asicGlobalRegs enumVal;          /* The enumeration value of the Register */
+  MV_U32           address;          /* The absolute address of the Register */
+  MV_U32           offset;           /* The relative address of the Register */
+  E_asicAccessType accessType;       /* Access Type: Read Only, Write Only, Read/Write */
+  MV_U32           mask;             /* Mask for sub-fields Register */
+  MV_U32           shift;            /* Shift field location for sub-fields Register */
+  MV_U32           tblLength;        /* Number of entries in the table, Only relevant for tables */
+  MV_U32           tblEntrySize;     /* The length in interval of 32bits of a table entry, Only relevant for tables */
+  MV_U32           accessCount;      /* Number accesses to the specific Register */
+  MV_U8            description[64];  /* Description */
+} S_asicGlobalRegDb;
+
+/* Global variables
+------------------------------------------------------------------------------*/
+
+/* Global functions
+------------------------------------------------------------------------------*/
+MV_STATUS asicOntGlbRegRead(E_asicGlobalRegs reg, MV_U32 *pvalue_p, MV_U32 entry);
+MV_STATUS asicOntGlbRegWrite(E_asicGlobalRegs reg, MV_U32 value, MV_U32 entry);
+MV_STATUS asicOntGlbRegReadNoCheck(E_asicGlobalRegs reg, MV_U32 *pvalue, MV_U32 entry);
+MV_STATUS asicOntGlbRegWriteNoCheck (E_asicGlobalRegs reg, MV_U32 value, MV_U32 entry);
+MV_STATUS asicOntMiscRegWrite(E_asicGlobalRegs reg, MV_U32 value, MV_U32 entry);
+MV_STATUS asicOntMiscRegRead(E_asicGlobalRegs reg, MV_U32 *pvalue, MV_U32 entry);
+
+/* Macros
+------------------------------------------------------------------------------*/
+#define PON_GPIO_NOT_USED (0xFFFF)
+#define PON_GPIO_GET(gppClass, gpioGroup, gpioMask)\
+{\
+  MV_32 gpioNum;\
+  gpioNum = mvBoarGpioPinNumGet(gppClass, 0);\
+  if (gpioNum < 0)\
+  {\
+    gpioGroup = PON_GPIO_NOT_USED;\
+    gpioMask  = PON_GPIO_NOT_USED;\
+  }\
+  else\
+  {\
+    gpioGroup = gpioNum >> 5;\
+    gpioMask  = (1 << (gpioNum & 0x1F));\
+  }\
+}
+
+#endif /* _ONU_GPON_REG_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/README b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/README
new file mode 100755
index 0000000..5ab23b7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/README
@@ -0,0 +1,28 @@
+This directory includes a test program that runs on Marvell platform, such as
+DB-88E6218, RD-88E6218, DB-88E6318, and RD-88E6318 with VxWorks.
+It is not part of the DSDT Driver Suite, rather, 
+it runs through each and every API of the Driver Suite to test it out. 
+
+Please notes that it is provided for "Reference Only" and some of the system 
+specific files cannot be compiled unless related BSP is provided.
+
+The test program covers :
+
+1) How to initialize single or multiple Marvell SOHO Switchs.
+	msApiInit.c : Single Address Mode Device
+	msApiMultiInit.c : Multiple Address Mode Device
+
+	Refer to Device DataSheet for detailed information of each Address Mode.
+	
+2) How to utilize each APIs. (testApi.c)
+
+3) How to provide two platform specific MII access routines. 
+	(qdFFMii.c for 88E6218 board, ev96122mii.c for EV-96122 board)
+
+4) How to enable SOHO Switch Interrupt, if applicable. (qdInt.c)
+
+5) How to run VCT(Virtual Cable Tester) test. (vctTest.c)
+
+6) How to provide Semaphore routines if required. (osSem.c)
+
+       
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/ev96122mii.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/ev96122mii.c
new file mode 100755
index 0000000..2c3b88d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/ev96122mii.c
@@ -0,0 +1,213 @@
+#include <Copyright.h>
+/********************************************************************************
+* ev96122mii.c
+*
+* DESCRIPTION:
+*       SMI access routines for EV-96122 board
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include <msSample.h>
+
+/*
+ * For each platform, all we need is 
+ * 1) Assigning functions into 
+ * 		fgtReadMii : to read MII registers, and
+ * 		fgtWriteMii : to write MII registers.
+ *
+ * 2) Register Interrupt (Not Defined Yet.)
+*/
+
+/* 
+ *  EV-96122 Specific Definition
+*/
+
+#define SMI_OP_CODE_BIT_READ                    1
+#define SMI_OP_CODE_BIT_WRITE                   0
+#define SMI_BUSY                                1<<28
+#define READ_VALID                              1<<27
+
+#ifdef FIREFOX
+#define ETHER_SMI_REG                   0x10 
+#define internalRegBaseAddr 0x80008000
+#define NONE_CACHEABLE		0x00000000
+#define CACHEABLE			0x00000000
+#define SMI_RX_TIMEOUT		1000
+#else
+#define ETHER_SMI_REG                   0x080810 
+#define internalRegBaseAddr 0x14000000
+#define NONE_CACHEABLE		0xa0000000
+#define CACHEABLE			0x80000000
+#define SMI_RX_TIMEOUT		10000000
+#endif
+
+typedef unsigned int              SMI_REG;
+
+#ifdef LE /* Little Endian */          	
+#define SHORT_SWAP(X) (X)
+#define WORD_SWAP(X) (X)
+#define LONG_SWAP(X) ((l64)(X))
+
+#else    /* Big Endian */
+#define SHORT_SWAP(X) ((X <<8 ) | (X >> 8))
+
+#define WORD_SWAP(X) (((X)&0xff)<<24)+      \
+                    (((X)&0xff00)<<8)+      \
+                    (((X)&0xff0000)>>8)+    \
+                    (((X)&0xff000000)>>24)
+
+#define LONG_SWAP(X) ( (l64) (((X)&0xffULL)<<56)+               \
+                            (((X)&0xff00ULL)<<40)+              \
+                            (((X)&0xff0000ULL)<<24)+            \
+                            (((X)&0xff000000ULL)<<8)+           \
+                            (((X)&0xff00000000ULL)>>8)+         \
+                            (((X)&0xff0000000000ULL)>>24)+      \
+                            (((X)&0xff000000000000ULL)>>40)+    \
+                            (((X)&0xff00000000000000ULL)>>56))   
+
+#endif
+
+#define GT_REG_READ(offset, pData)                                          \
+*pData = ( (volatile unsigned int)*((unsigned int *)                        \
+           (NONE_CACHEABLE | internalRegBaseAddr | (offset))) );            \
+*pData = WORD_SWAP(*pData)
+
+#define GT_REG_WRITE(offset, data)                                          \
+(volatile unsigned int)*((unsigned int *)(NONE_CACHEABLE |                  \
+          internalRegBaseAddr | (offset))) = WORD_SWAP(data)
+
+typedef enum _bool{false,true} bool;
+
+/*****************************************************************************
+*
+* bool etherReadMIIReg (unsigned int portNumber , unsigned int MIIReg,
+* unsigned int* value)
+*
+* Description
+* This function will access the MII registers and will read the value of
+* the MII register , and will retrieve the value in the pointer.
+* Inputs
+* portNumber - one of the 2 possiable Ethernet ports (0-1).
+* MIIReg - the MII register offset.
+* Outputs
+* value - pointer to unsigned int which will receive the value.
+* Returns Value
+* true if success.
+* false if fail to make the assignment.
+* Error types (and exceptions if exist)
+*/
+
+GT_BOOL gtBspReadMii (GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                        unsigned int* value)
+{
+SMI_REG smiReg;
+unsigned int phyAddr;
+unsigned int timeOut = 10; /* in 100MS units */
+int i;
+
+/* first check that it is not busy */
+    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+    if(smiReg & SMI_BUSY) 
+    {
+        for(i = 0 ; i < SMI_RX_TIMEOUT ; i++);
+        do {
+            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+            if(timeOut-- < 1 ) {
+    	        return false;
+    	    }
+        } while (smiReg & SMI_BUSY);
+    }
+/* not busy */
+
+    phyAddr = portNumber;
+
+    smiReg =  (phyAddr << 16) | (SMI_OP_CODE_BIT_READ << 26) | (MIIReg << 21) |
+         SMI_OP_CODE_BIT_READ<<26;
+
+    GT_REG_WRITE (ETHER_SMI_REG,*((unsigned int*)&smiReg));
+    timeOut = 10; /* initialize the time out var again */
+    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+    if(!(smiReg & READ_VALID)) 
+        {
+            i=0;
+            while(i < SMI_RX_TIMEOUT)
+            {
+                i++;
+            }
+        {
+        }
+        do {
+            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+            if(timeOut-- < 1 ) {
+    	        return false;
+    	    }
+        } while (!(smiReg & READ_VALID));
+     }
+    *value = (unsigned int)(smiReg & 0xffff);
+    
+    return true;
+
+
+}
+
+/*****************************************************************************
+* 
+* bool etherWriteMIIReg (unsigned int portNumber , unsigned int MIIReg,
+* unsigned int value)
+* 
+* Description
+* This function will access the MII registers and will write the value
+* to the MII register.
+* Inputs
+* portNumber - one of the 2 possiable Ethernet ports (0-1).
+* MIIReg - the MII register offset.
+* value -the value that will be written.
+* Outputs
+* Returns Value
+* true if success.
+* false if fail to make the assignment.
+* Error types (and exceptions if exist)
+*/
+
+GT_BOOL gtBspWriteMii (GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                       unsigned int value)
+{
+SMI_REG smiReg;
+unsigned int phyAddr;
+unsigned int timeOut = 10; /* in 100MS units */
+int i;
+
+/* first check that it is not busy */
+    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+    if(smiReg & SMI_BUSY) 
+    {
+        for(i = 0 ; i < SMI_RX_TIMEOUT ; i++);
+        do {
+            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+            if(timeOut-- < 1 ) {
+    	        return false;
+    	    }
+        } while (smiReg & SMI_BUSY);
+    }
+/* not busy */
+
+    phyAddr = portNumber;
+
+    smiReg = 0; /* make sure no garbage value in reserved bits */
+    smiReg = smiReg | (phyAddr << 16) | (SMI_OP_CODE_BIT_WRITE << 26) |
+             (MIIReg << 21) | (value & 0xffff);
+
+    GT_REG_WRITE (ETHER_SMI_REG,*((unsigned int*)&smiReg));
+
+    return(true);
+}
+
+
+void gtBspMiiInit(GT_QD_DEV* dev)
+{
+	return;	
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/makefile b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/makefile
new file mode 100755
index 0000000..0a6f158
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/makefile
@@ -0,0 +1,49 @@
+# makefile - build main object file

+#

+# modification history

+# --------------------

+# 04-15-02,mj	created

+#

+#######################################################################

+

+DEMONAME = msDiag

+WORK_TO_DO = $(DEMONAME).o

+

+exe : $(WORK_TO_DO)

+

+# Include common variable definitions

+include $(TOOL_DIR)/make.defs

+

+.PHONY : exe

+

+QDLIB = $(LIB_DIR)/$(PROJ_NAME).o

+

+OBJDIRS	= $(subst /,\,$(dir $(QDLIB)))

+
+#CSOURCES = osSem.c ev96122mii.c testApi.c qdSim.c msApiInit.c utils.c vctTest.c

+#CSOURCES = osSem.c testApi.c qdSim.c utils.c vctTest.c

+CSOURCES = osSem.c testApi.c qdSim.c utils.c vctTest.c msApiMultiInit.c

+

+COBJECTS  	= $(CSOURCES:.c=.o)

+AOBJECTS  	= $(ASOURCES:.s=.o)

+ifeq ($(OBJECTS),)

+OBJECTS  	= $(COBJECTS) $(AOBJECTS)

+endif

+

+ifeq ($(TARGET_CPU),ARM)

+EXTRA_DEFINE	+= -DFIREFOX

+endif

+

+$(DEMONAME).o : $(OBJECTS) $(QDLIB)

+	$(LD) $(LDFLAGS) -Map $(DEMONAME).map -o $(DEMONAME).o $(OBJECTS) $(QDLIB)

+

+$(OBJECTS) : %.o : %.c

+.c.o :

+	$(CC) $(CFLAGS) $(EXTRA_DEFINE) $(EXTRA_INCLUDE) $(ADDED_CFLAGS) -c $< -o $(notdir $@)

+

+.PHONY : clean

+clean :

+	$(RM) *.o

+	$(RM) *.map

+

+#end of file

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msApiInit.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msApiInit.c
new file mode 100755
index 0000000..9a027c8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msApiInit.c
@@ -0,0 +1,115 @@
+#include <Copyright.h>
+/********************************************************************************
+* msApiInit.c
+*
+* DESCRIPTION:
+*       MS API initialization routine
+*
+* DEPENDENCIES:   Platform
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+/*
+#define MULTI_ADDR_MODE
+#define MANUAL_MODE
+*/
+
+GT_SYS_CONFIG   cfg;
+GT_QD_DEV       diagDev;
+GT_QD_DEV       *dev=&diagDev;
+
+
+/*
+ *  Initialize the QuarterDeck. This should be done in BSP driver init routine.
+ *	Since BSP is not combined with QuarterDeck driver, we are doing here.
+*/
+
+GT_STATUS qdStart(int cpuPort, int useQdSim, int devId) /* devId is used for simulator only */
+{
+GT_STATUS status;
+
+	/*
+	 *  Register all the required functions to QuarterDeck Driver.
+	*/
+	memset((char*)&cfg,0,sizeof(GT_SYS_CONFIG));
+	memset((char*)&diagDev,0,sizeof(GT_QD_DEV));
+
+	if(useQdSim == 0) /* use EV-96122 */
+	{
+		cfg.BSPFunctions.readMii   = gtBspReadMii;
+		cfg.BSPFunctions.writeMii  = gtBspWriteMii;
+#ifdef USE_SEMAPHORE
+		cfg.BSPFunctions.semCreate = osSemCreate;
+		cfg.BSPFunctions.semDelete = osSemDelete;
+		cfg.BSPFunctions.semTake   = osSemWait;
+		cfg.BSPFunctions.semGive   = osSemSignal;
+#else
+		cfg.BSPFunctions.semCreate = NULL;
+		cfg.BSPFunctions.semDelete = NULL;
+		cfg.BSPFunctions.semTake   = NULL;
+		cfg.BSPFunctions.semGive   = NULL;
+#endif
+		gtBspMiiInit(dev);
+	}
+	else	/* use QuaterDeck Simulator (No QD Device Required.) */
+	{
+		cfg.BSPFunctions.readMii   = qdSimRead;
+		cfg.BSPFunctions.writeMii  = qdSimWrite;
+#ifdef USE_SEMAPHORE
+		cfg.BSPFunctions.semCreate = osSemCreate;
+		cfg.BSPFunctions.semDelete = osSemDelete;
+		cfg.BSPFunctions.semTake   = osSemWait;
+		cfg.BSPFunctions.semGive   = osSemSignal;
+#else
+		cfg.BSPFunctions.semCreate = NULL;
+		cfg.BSPFunctions.semDelete = NULL;
+		cfg.BSPFunctions.semTake   = NULL;
+		cfg.BSPFunctions.semGive   = NULL;
+#endif
+
+		qdSimInit(devId,0);
+	}
+
+	cfg.initPorts = GT_TRUE;	/* Set switch ports to Forwarding mode. If GT_FALSE, use Default Setting. */
+	cfg.cpuPortNum = cpuPort;
+#ifdef MANUAL_MODE	/* not defined. this is only for sample */
+	/* user may want to use this mode when there are two QD switchs on the same MII bus. */
+	cfg.mode.scanMode = SMI_MANUAL_MODE;	/* Use QD located at manually defined base addr */
+	cfg.mode.baseAddr = 0x10;	/* valid value in this case is either 0 or 0x10 */
+#else
+#ifdef MULTI_ADDR_MODE
+	cfg.mode.scanMode = SMI_MULTI_ADDR_MODE;	/* find a QD in indirect access mode */
+	cfg.mode.baseAddr = 1;		/* this is the phyAddr used by QD family device. 
+								Valid value are 1 ~ 31.*/
+#else
+	cfg.mode.scanMode = SMI_AUTO_SCAN_MODE;	/* Scan 0 or 0x10 base address to find the QD */
+	cfg.mode.baseAddr = 0;
+#endif
+#endif
+	if((status=qdLoadDriver(&cfg, dev)) != GT_OK)
+	{
+		MSG_PRINT(("qdLoadDriver return Failed\n"));
+		return status;
+	}
+
+	MSG_PRINT(("Device ID     : 0x%x\n",dev->deviceId));
+	MSG_PRINT(("Base Reg Addr : 0x%x\n",dev->baseRegAddr));
+	MSG_PRINT(("No of Ports   : %d\n",dev->numOfPorts));
+	MSG_PRINT(("CPU Ports     : %d\n",dev->cpuPortNum));
+
+	/*
+	 *  start the QuarterDeck
+	*/
+	if((status=sysEnable(dev)) != GT_OK)
+	{
+		MSG_PRINT(("sysConfig return Failed\n"));
+		return status;
+	}
+
+	MSG_PRINT(("QuarterDeck has been started.\n"));
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msApiMultiInit.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msApiMultiInit.c
new file mode 100755
index 0000000..4488842
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msApiMultiInit.c
@@ -0,0 +1,424 @@
+#include <Copyright.h>
+/********************************************************************************
+* msApiInit.c
+*
+* DESCRIPTION:
+*		MS API initialization routine for devices supporting Multi Address Mode,
+*		such as 88E6183. Following setup will be used for this sample code.
+*
+*	  	------------------
+*		|CPU Ethernet Dev|
+*		------------------
+*		 |		
+*		 |		
+*		 |   8--------------9    8--------------9   8--------------
+*		 |----| QD Device 0|------| QD Device 1|-----| QD Device 2|
+*             --------------      --------------     --------------
+*               0 1 2 ... 7         0 1 2 ... 7        0 1 2 ... 7
+*
+*
+*		Ethernet port of CPU is connected to port 8 of Device 0,
+*		port 9 of Device 0 is connected to port 8 of Device 1, and
+*		port 9 of Device 1 is connected to port 8 of Device 2.
+*
+*		Device 0 uses Phy Address 1, 
+*		Device 1 uses Phy Address 2, and
+*		Device 2 uses Phy Address 3
+*		Notes: Phy Address 0 cannot be used in a Multi Chip Address Mode.
+*
+*		Each Switch Device has to be configured to Multi Chip Address Mode.
+*		For detailed information for Multi Chip Address Mode configuration,
+*		please refer to your device's Datasheet.
+*
+* DEPENDENCIES:   Platform
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+/*
+#define MULTI_ADDR_MODE
+#define MANUAL_MODE
+*/
+
+#define MULTI_ADDR_MODE
+#define N_OF_QD_DEVICES		2	/* number of 88E6183 devices connected */
+
+#define DEVICE0_ID		1
+#define DEVICE1_ID		DEVICE0_ID + 1
+#define DEVICE2_ID		DEVICE0_ID + 2
+
+#define DEVICE0_PHY_ADDR	0x11
+#define DEVICE1_PHY_ADDR	DEVICE0_PHY_ADDR + 1
+#define DEVICE2_PHY_ADDR	DEVICE0_PHY_ADDR + 2
+
+#define S_CPU_DEVICE		DEVICE0_ID
+
+#define DEVICE0_CPU_PORT		7
+#define DEVICE0_CASCADE_PORT	6
+#define DEVICE1_CPU_PORT		7
+#define DEVICE1_CASCADE_PORT	6
+#define DEVICE2_CPU_PORT		7
+#define DEVICE2_CASCADE_PORT	6
+
+extern GT_QD_DEV       	qddev[4];
+
+GT_QD_DEV       *qdMultiDev[N_OF_QD_DEVICES] = {0,};
+GT_QD_DEV       *qdDev0 = &qddev[1];
+GT_QD_DEV       *qdDev1 = NULL;
+GT_QD_DEV       *qdDev2 = NULL;
+
+/*
+ * read mii register - see qdFFmii.c
+ */ 
+extern GT_BOOL ffReadMii(GT_QD_DEV* dev, 
+		      unsigned int portNumber , 
+		      unsigned int MIIReg, unsigned int* value
+		      );
+
+/*
+ * write mii register - see qdFFmii.c
+ */ 
+extern GT_BOOL ffWriteMii(GT_QD_DEV* dev, 
+		       unsigned int portNumber , 
+		       unsigned int MIIReg, 
+		       unsigned int value
+		       );
+
+GT_STATUS RubyStart(int phyAddr, GT_QD_DEV* d)
+{
+	GT_STATUS status = GT_FAIL;
+	GT_SYS_CONFIG   cfg;
+
+	memset((char*)&cfg,0,sizeof(GT_SYS_CONFIG));
+	MSG_PRINT(("Size of GT_QD_DEV %i\n",sizeof(GT_QD_DEV)));
+
+	if(d == NULL)
+	{
+		MSG_PRINT(("Device Structure is NULL.\n"));
+		return GT_FAIL;
+	}
+
+	memset((char*)d,0,sizeof(GT_QD_DEV));
+
+	cfg.BSPFunctions.readMii   = ffReadMii;
+	cfg.BSPFunctions.writeMii  = ffWriteMii;
+#ifdef USE_SEMAPHORE
+	cfg.BSPFunctions.semCreate = osSemCreate;
+	cfg.BSPFunctions.semDelete = osSemDelete;
+	cfg.BSPFunctions.semTake   = osSemWait;
+	cfg.BSPFunctions.semGive   = osSemSignal;
+#else
+	cfg.BSPFunctions.semCreate = NULL;
+	cfg.BSPFunctions.semDelete = NULL;
+	cfg.BSPFunctions.semTake   = NULL;
+	cfg.BSPFunctions.semGive   = NULL;
+#endif
+
+	cfg.initPorts = GT_TRUE;	/* Set switch ports to Forwarding mode. If GT_FALSE, use Default Setting. */
+	cfg.cpuPortNum = 10;
+
+	cfg.mode.scanMode = SMI_MULTI_ADDR_MODE;	
+	cfg.mode.baseAddr = phyAddr;	/* valid value in this case is either 0 or 0x10 */
+
+	if((status=qdLoadDriver(&cfg, d)) != GT_OK)
+	{
+		MSG_PRINT(("qdLoadDriver return Failed\n"));
+		return status;
+	}
+
+	MSG_PRINT(("Device ID     : 0x%x\n",d->deviceId));
+	MSG_PRINT(("PHY Addr      : 0x%x\n",d->phyAddr));
+	MSG_PRINT(("Base Addr     : 0x%x\n",d->baseRegAddr));
+	MSG_PRINT(("CPU Ports     : %d\n",d->cpuPortNum));
+	MSG_PRINT(("N Ports       : %d\n",d->numOfPorts));
+	MSG_PRINT(("Device Group  : 0x%x\n",d->devName));
+	MSG_PRINT(("QDDev         : %#x\n",(unsigned long)&d));
+
+	/*
+	 *  start the QuarterDeck
+	*/
+	if((status=sysEnable(d)) != GT_OK)
+	{
+		MSG_PRINT(("sysConfig return Failed\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+GT_STATUS SwStart(int phyAddr, GT_QD_DEV* d)
+{
+	return RubyStart(phyAddr,d);
+}
+
+GT_QD_DEV* loadDev(GT_QD_DEV* dev, int mode, int phyAddr, int cpuPort, unsigned int cfgMode)
+{
+	GT_QD_DEV* d = dev;
+	GT_STATUS status = GT_FAIL;
+	GT_SYS_CONFIG   cfg;
+
+	if((int)dev == -1)
+		goto printUse;
+
+	memset((char*)&cfg,0,sizeof(GT_SYS_CONFIG));
+
+	if(d == NULL)
+	{
+		d = (GT_QD_DEV*)malloc(sizeof(GT_QD_DEV));
+		
+		if(d == NULL)
+		{
+			MSG_PRINT(("Failed to allocate Device Structure\n"));
+			return NULL;
+		}
+	}
+
+	memset((char*)d,0,sizeof(GT_QD_DEV));
+
+	cfg.BSPFunctions.readMii   = ffReadMii;
+	cfg.BSPFunctions.writeMii  = ffWriteMii;
+#ifdef USE_SEMAPHORE
+	cfg.BSPFunctions.semCreate = osSemCreate;
+	cfg.BSPFunctions.semDelete = osSemDelete;
+	cfg.BSPFunctions.semTake   = osSemWait;
+	cfg.BSPFunctions.semGive   = osSemSignal;
+#else
+	cfg.BSPFunctions.semCreate = NULL;
+	cfg.BSPFunctions.semDelete = NULL;
+	cfg.BSPFunctions.semTake   = NULL;
+	cfg.BSPFunctions.semGive   = NULL;
+#endif
+
+	cfg.initPorts = GT_TRUE;	/* Set switch ports to Forwarding mode. If GT_FALSE, use Default Setting. */
+	cfg.cpuPortNum = cpuPort;
+	cfg.skipInitSetup = (GT_U32)cfgMode;
+
+	switch(mode)
+	{
+		case SMI_MANUAL_MODE:		/* Use QD located at manually defined base addr */
+		case SMI_MULTI_ADDR_MODE:	/* Use QD in multi chip address mode */
+			cfg.mode.scanMode = mode;	
+			cfg.mode.baseAddr = phyAddr;	/* valid value in this case is either 0 or 0x10 */
+			break;
+		case SMI_AUTO_SCAN_MODE:	/* Scan 0 or 0x10 base address to find the QD */
+			cfg.mode.scanMode = mode;
+			cfg.mode.baseAddr = 0;
+			break;
+		default:
+			MSG_PRINT(("Unknown Mode %i\n",mode));
+			goto printUse;
+	}
+
+	if((status=qdLoadDriver(&cfg, d)) != GT_OK)
+	{
+		MSG_PRINT(("qdLoadDriver return Failed\n"));
+		goto loadErr;
+	}
+
+	MSG_PRINT(("Device ID     : 0x%x\n",d->deviceId));
+	MSG_PRINT(("PHY Addr      : 0x%x\n",d->phyAddr));
+	MSG_PRINT(("Base Addr     : 0x%x\n",d->baseRegAddr));
+	MSG_PRINT(("CPU Ports     : %d\n",d->cpuPortNum));
+
+	/*
+	 *  start the QuarterDeck
+	*/
+	if((status=sysEnable(d)) != GT_OK)
+	{
+		MSG_PRINT(("sysConfig return Failed\n"));
+		goto loadErr;
+	}
+
+	return d;
+
+printUse:
+	MSG_PRINT(("Usage: loadDev(Dev,mode,phyAddr,cpuPort)\n",SMI_AUTO_SCAN_MODE));
+	MSG_PRINT(("\tSMI_AUTO_SCAN_MODE :  %i\n",SMI_AUTO_SCAN_MODE));
+	MSG_PRINT(("\tSMI_MANUAL_MODE :     %i\n",SMI_MANUAL_MODE));
+	MSG_PRINT(("\tSMI_MULTI_ADDR_MODE : %i\n",SMI_MULTI_ADDR_MODE));
+	MSG_PRINT(("Example: loadDev(0,1,0x10,5)\n"));
+	MSG_PRINT(("for Manual mode, phy base address 0x10, and cpu port 5\n"));
+	
+loadErr:
+	
+	if(dev)
+		return NULL;
+
+	if(d)
+		free(d);
+
+	return NULL;
+}
+
+/*
+ * Initialize each Switch Devices. This should be done in BSP driver init routine.
+ *	Since BSP is not combined with QuarterDeck driver, we are doing here.
+ * This routine will setup Switch Devices according to the above description.
+*/
+GT_STATUS qdMultiDevStart()
+{
+	GT_STATUS status = GT_FAIL;
+	int cpuPort;
+	int cascadePort;
+	int i,j;
+
+	/* 
+	 *	Create QD Device Structure for each device.
+	 */
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		if(qdMultiDev[i] == NULL)
+		{
+			qdMultiDev[i] = (GT_QD_DEV*)malloc(sizeof(GT_QD_DEV));
+		
+			if(qdMultiDev[i] == NULL)
+			{
+				while(i--)
+				{
+					free(qdMultiDev[i]);
+					qdMultiDev[i] = NULL;
+				}
+				return GT_FAIL;
+			}
+		}
+
+		memset((char*)qdMultiDev[i],0,sizeof(GT_QD_DEV));
+	}
+	
+	/*
+	 *  Register all the required functions to QuarterDeck Driver for each device.
+	*/
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		switch (i)
+		{
+			case 0: /* if we are registering device 0 */
+				cpuPort = DEVICE0_CPU_PORT;
+				break;
+			case 1: /* if we are registering device 1 */
+				cpuPort = DEVICE1_CPU_PORT;	/* where device 0 is connected */
+				break;
+			case 2: /* if we are registering device 2 */
+				cpuPort = DEVICE2_CPU_PORT;	/* where device 1 is connected */
+				break;
+			default: /* we don't have any more device. it shouldn't happen in our sample setup. */
+				goto errorExit;
+		}
+
+		MSG_PRINT(("Initializing QD Device %i...\n",i));
+		if(loadDev(qdMultiDev[i],SMI_MULTI_ADDR_MODE,DEVICE0_PHY_ADDR + i,cpuPort,0) == NULL)
+		{
+			MSG_PRINT(("QD Device %i is not initialized.\n",i));
+			free(qdMultiDev[i]);
+			qdMultiDev[i] = NULL;
+			continue;
+		}
+
+		/* 
+			Now, we need to configure Cascading information for each devices.
+			1. Set Interswitch port mode for port 8 and 9 for device 0,1,and 2,
+				so that switch device can expect Marvell Tag from frames 
+				ingressing/egressing this port.
+			2. Set CPU Port information (for To_CPU frame) for each port of device.
+			3. Set Cascading Port information (for From_CPU fram) for each device.
+			4. Set Device ID (if required)
+				Note: DeviceID is hardware configurable.
+		*/
+		switch (i)
+		{
+			case 0: /* if we are registering device 0 */
+				cpuPort = DEVICE0_CPU_PORT; 		/* where CPU Enet port is connected */
+				cascadePort = DEVICE0_CASCADE_PORT;	/* where device 1 is connected */
+				qdDev0 = qdMultiDev[i];
+				MSG_PRINT(("Use qdDev0 to access Device 0.\n"));
+				break;
+			case 1: /* if we are registering device 1 */
+				cpuPort = DEVICE1_CPU_PORT; 		/* where device 0 is connected */
+				cascadePort = DEVICE1_CASCADE_PORT;	/* where device 2 is connected */
+				qdDev1 = qdMultiDev[i];
+				MSG_PRINT(("Use qdDev1 to access Device 1.\n"));
+				break;
+			case 2: /* if we are registering device 2 */
+				cpuPort = DEVICE2_CPU_PORT; 		/* where device 1 is connected */
+				cascadePort = DEVICE2_CASCADE_PORT;	/* no need to setup for the given sample setup */
+				qdDev2 = qdMultiDev[i];
+				MSG_PRINT(("Use qdDev2 to access Device 2.\n"));
+				break;
+			default: /* we don't have any more device. it shouldn't happen in our sample setup. */
+				goto errorExit;
+		}
+
+		/*
+			1. Set Interswitch port mode for port 8 and 9 for device 0,1,and 2,
+				so that switch device can expect Marvell Tag from frames 
+				ingressing/egressing this port.
+			2. Set CPU Port information (for To_CPU frame) for each port of device.
+		*/			
+		MSG_PRINT(("Setting InterSwitch Port and CPU Port...\n"));
+		for(j=0; j<qdMultiDev[i]->numOfPorts; j++)
+		{
+			if((j == cpuPort) || (j == cascadePort))
+			{
+				if((status=gprtSetInterswitchPort(qdMultiDev[i],j,GT_TRUE)) != GT_OK)
+				{
+					MSG_PRINT(("gprtSetInterswitchPort returned %i (port %i, mode TRUE)\n",status,j));
+					break;
+				}
+			}
+			else
+			{
+				if((status=gprtSetInterswitchPort(qdMultiDev[i],j,GT_FALSE)) != GT_OK)
+				{
+					MSG_PRINT(("gprtSetInterswitchPort returned %i (port %i, mode FALSE)\n",status,j));
+					break;
+				}
+			}
+
+			if((status=gprtSetCPUPort(qdMultiDev[i],j,cpuPort)) != GT_OK)
+			{
+				MSG_PRINT(("gprtSetCPUPort returned %i\n",status));
+					break;
+			}
+		}
+
+		/*
+			3. Set Cascading Port information (for From_CPU fram) for each device.
+		*/	 	
+		MSG_PRINT(("Setting Cascade Port...\n"));
+		if((status=gsysSetCascadePort(qdMultiDev[i],cascadePort)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetCascadePort returned %i\n",status));
+			continue;
+		}
+
+		/*
+			4. Set Device ID (if required)
+		*/	 	
+		MSG_PRINT(("Setting Device ID (%i)...\n",DEVICE0_ID+i));
+		if((status=gsysSetDeviceNumber(qdMultiDev[i],DEVICE0_ID+i)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetDeviceNumber returned %i\n",status));
+			continue;
+		}
+
+	}	
+
+	return GT_OK;
+
+errorExit:
+
+	/* code will be reached here only if N_OF_QD_DEVICES > 3 */
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		if(qdMultiDev[i] != NULL)
+		{
+	  		free(qdMultiDev[i]);
+			qdMultiDev[i] = NULL;
+		}
+	}	
+
+	return GT_FAIL;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msSample.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msSample.h
new file mode 100755
index 0000000..de7c449
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/msSample.h
@@ -0,0 +1,187 @@
+#include <Copyright.h>
+/********************************************************************************
+* msSample.h
+*
+* DESCRIPTION:
+*       Types definitions for Sample program
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __pfTesth
+#define __pfTesth
+
+#ifdef _VXWORKS
+#include "vxWorks.h"
+#include "logLib.h"
+#endif
+#include "stdio.h"
+#include "stdarg.h"
+#include "stdlib.h"
+#include "time.h"
+#include "string.h"
+
+#include "msApi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef GT_U32 (*GT_API_VOID) (GT_QD_DEV*);
+typedef int (*GT_CMP_FUNC) (void*, int, int);
+
+typedef GT_STATUS (*GT_API_SET_BOOL) (GT_QD_DEV*, GT_BOOL);
+typedef GT_STATUS (*GT_API_GET_BOOL) (GT_QD_DEV*, GT_BOOL*);
+
+typedef GT_STATUS (*GT_API_SET_U16) (GT_QD_DEV*, GT_U16);
+typedef GT_STATUS (*GT_API_GET_U16) (GT_QD_DEV*, GT_U16*);
+
+typedef GT_STATUS (*GT_API_SET_U32) (GT_QD_DEV*, GT_U32);
+typedef GT_STATUS (*GT_API_GET_U32) (GT_QD_DEV*, GT_U32*);
+
+typedef GT_STATUS (*GT_API_MAC_ADDR) (GT_QD_DEV*, GT_ETHERADDR*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_BOOL) (GT_QD_DEV*, GT_LPORT,GT_BOOL);
+typedef GT_STATUS (*GT_API_GET_PORT_BOOL) (GT_QD_DEV*, GT_LPORT,GT_BOOL*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U16) (GT_QD_DEV*, GT_LPORT,GT_U16);
+typedef GT_STATUS (*GT_API_GET_PORT_U16) (GT_QD_DEV*, GT_LPORT,GT_U16*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U32) (GT_QD_DEV*, GT_LPORT,GT_U32);
+typedef GT_STATUS (*GT_API_GET_PORT_U32) (GT_QD_DEV*, GT_LPORT,GT_U32*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U8) (GT_QD_DEV*, GT_LPORT,GT_U8);
+typedef GT_STATUS (*GT_API_GET_PORT_U8) (GT_QD_DEV*, GT_LPORT,GT_U8*);
+
+typedef struct _TEST_API
+{
+	union
+	{
+		GT_API_SET_BOOL bool;
+		GT_API_SET_U16 u16;
+		GT_API_SET_U32 u32;
+		GT_API_MAC_ADDR mac;
+		GT_API_SET_PORT_BOOL port_bool;
+		GT_API_SET_PORT_U8 port_u8;
+		GT_API_SET_PORT_U16 port_u16;
+		GT_API_SET_PORT_U32 port_u32;
+	} setFunc;
+
+	union
+	{
+		GT_API_GET_BOOL bool;
+		GT_API_GET_U16 u16;
+		GT_API_GET_U32 u32;
+		GT_API_MAC_ADDR mac;
+		GT_API_GET_PORT_BOOL port_bool;
+		GT_API_GET_PORT_U8 port_u8;
+		GT_API_GET_PORT_U16 port_u16;
+		GT_API_GET_PORT_U32 port_u32;
+	} getFunc;
+
+}TEST_API;
+
+typedef struct _TEST_STRUCT
+{
+	char strTest[16];
+	GT_API_VOID testFunc;
+	GT_U32 testResults;
+} TEST_STRUCT;
+
+#define MSG_PRINT(x) testPrint x
+
+#define MAX_MAC_ENTRIES	    8192
+#define TEST_MAC_ENTRIES 	64
+#define MAX_BUCKET_SIZE		2048
+
+typedef struct _TEST_ATU_ENTRY
+{
+	GT_ATU_ENTRY atuEntry[TEST_MAC_ENTRIES];
+}TEST_ATU_ENTRY;
+
+typedef struct _ATU_ENTRY_INFO
+{
+	GT_ATU_ENTRY atuEntry;
+	GT_U16	hash;
+	GT_U16	bucket;
+} ATU_ENTRY_INFO;
+
+extern GT_SYS_CONFIG   pfTestSysCfg;
+extern ATU_ENTRY_INFO *gAtuEntry;
+extern GT_QD_DEV       *dev;
+
+GT_STATUS qdStart(int,int,int);
+GT_STATUS qdSimSetPhyInt(unsigned int portNumber, unsigned short u16Data);
+GT_STATUS qdSimSetGlobalInt(unsigned short u16Data);
+
+GT_STATUS testAll(GT_QD_DEV*);
+void testPrint(char* format, ...);
+GT_U32 testATU(GT_QD_DEV *dev);
+GT_STATUS testATUStress(GT_QD_DEV *dev);
+GT_U32 testVTU(GT_QD_DEV *dev);
+
+extern FGT_INT_HANDLER qdIntHandler;
+
+int vtuEntryCmpFunc(void* buf, int a, int b);
+int atuEntryCmpFunc(void* buf, int a, int b);
+GT_STATUS gtSort(int list[], GT_CMP_FUNC cmpFunc, void* buf, GT_U32 len);
+GT_U16 createATUList(GT_QD_DEV *dev, TEST_ATU_ENTRY atuEntry[], GT_U16 entrySize, GT_U16 dbNumSize, 
+					GT_U16 sameMacsInEachDb, GT_U16 bSize);
+GT_STATUS testFillUpAtu(GT_QD_DEV *dev, ATU_ENTRY_INFO *atuEntry, GT_U8 atuSize, 
+					GT_U32 dbNum, GT_U16 first2Bytes, GT_ATU_UC_STATE state);
+GT_U16 runQDHash(GT_U8* eaddr, GT_U16 dbNum, int bSize, GT_U16* pHash, 
+					GT_U16* preBucket, GT_U16* posBucket);
+GT_STATUS testDisplayATUList(GT_QD_DEV *dev);
+
+#ifdef USE_SEMAPHORE
+GT_SEM osSemCreate(GT_SEM_BEGIN_STATE state);
+GT_STATUS osSemDelete(GT_SEM smid);
+GT_STATUS osSemWait(GT_SEM smid, GT_U32 timeOut);
+GT_STATUS osSemSignal(GT_SEM smid);
+#endif
+
+GT_BOOL gtBspReadMii ( GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                      unsigned int* value);
+GT_BOOL gtBspWriteMii ( GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                       unsigned int value);
+void gtBspMiiInit(GT_QD_DEV* dev);
+
+GT_BOOL qdSimRead (GT_QD_DEV* dev,unsigned int portNumber , unsigned int miiReg, unsigned int* value);
+GT_BOOL qdSimWrite (GT_QD_DEV* dev,unsigned int portNumber , unsigned int miiReg, unsigned int value);
+void qdSimInit(GT_DEVICE devId, int baseAddr);
+
+
+#if 1 /* This is for testing */
+
+#define TEST_MASK		0
+#define TEST_MASK_0		0
+#define TEST_MASK_1		1
+#define TEST_MASK_2		2
+#define TEST_MASK_3		3
+#define TEST_MASK_4		4
+#define TEST_MASK_5		5
+#define TEST_MASK_6		6
+#define TEST_MASK_7		7
+
+#define GET_TEST_MASK(_index, _mask)	\
+		((_index == 0)?_mask##_0:		\
+		(_index == 1)?_mask##_1:		\
+		(_index == 2)?_mask##_2:		\
+		(_index == 3)?_mask##_3:		\
+		(_index == 4)?_mask##_4:		\
+		(_index == 5)?_mask##_5:		\
+		(_index == 6)?_mask##_6:		\
+		(_index == 7)?_mask##_7:0)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif   /* __pfTesth */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/osSem.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/osSem.c
new file mode 100755
index 0000000..7c95204
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/osSem.c
@@ -0,0 +1,232 @@
+#include <Copyright.h>
+/********************************************************************************
+* osSem.c
+*
+* DESCRIPTION:
+*       Semaphore related routines
+*
+* DEPENDENCIES:
+*       OS Dependent.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifdef _VXWORKS
+#include "vxWorks.h"
+#include "semLib.h"
+#include "errnoLib.h"
+#include "objLib.h"
+int sysClkRateGet(void);
+
+#elif defined(WIN32)
+#include "windows.h"
+/* #include "wdm.h" */
+#elif defined(LINUX)
+#include "/usr/include/semaphore.h"
+typedef    sem_t          semaphore ;
+#endif
+
+#include <msApi.h>
+
+GT_SEM osSemCreate( GT_SEM_BEGIN_STATE state);
+GT_STATUS osSemDelete(GT_SEM smid);
+GT_STATUS osSemWait(  GT_SEM smid, GT_U32 timeOut);
+GT_STATUS osSemSignal(GT_SEM smid);
+
+/*******************************************************************************
+* osSemCreate
+*
+* DESCRIPTION:
+*       Create semaphore.
+*
+* INPUTS:
+*       name   - semaphore Name
+*       init   - init value of semaphore counter
+*       count  - max counter (must be >= 1)
+*
+* OUTPUTS:
+*       smid - semaphore Id
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_SEM osSemCreate(GT_SEM_BEGIN_STATE state)
+{
+#ifdef _VXWORKS
+#if 0
+	return (GT_SEM)semBCreate(SEM_Q_FIFO, state);
+#else
+	GT_SEM semid;
+	semid =(GT_SEM)semBCreate(SEM_Q_FIFO, state);
+	return semid;
+#endif
+
+#elif defined(WIN32)
+	return (GT_SEM)CreateSemaphore(NULL, state, 1, NULL);
+#elif defined(LINUX)
+	semaphore lxSem;
+
+	sem_init(&lxSem, state, 1);
+	return lxSem;
+#else
+	return 1;
+#endif
+	return GT_OK;
+}
+
+/*******************************************************************************
+* osSemDelete
+*
+* DESCRIPTION:
+*       Delete semaphore.
+*
+* INPUTS:
+*       smid - semaphore Id
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS osSemDelete(GT_SEM smid)
+{
+#ifdef _VXWORKS
+	STATUS rc;
+
+	rc = semDelete((SEM_ID) smid);
+	if (rc != OK)
+		return GT_FAIL;
+
+#elif defined(WIN32)
+	if (CloseHandle((HANDLE)smid) == 0)
+		return GT_FAIL;
+
+#elif defined(LINUX)
+	sem_destroy((semaphore*) smid);
+#else
+	return GT_OK;
+#endif
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* osSemWait
+*
+* DESCRIPTION:
+*       Wait on semaphore.
+*
+* INPUTS:
+*       smid    - semaphore Id
+*       timeOut - time out in miliseconds or 0 to wait forever
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       OS_TIMEOUT - on time out
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS osSemWait(GT_SEM smid, GT_U32 timeOut)
+{
+#ifdef _VXWORKS
+	STATUS rc;
+
+	if (timeOut == 0)
+	rc = semTake ((SEM_ID) smid, WAIT_FOREVER);
+	else
+	{
+		int num, delay;
+
+		num = sysClkRateGet();
+		delay = (num * timeOut) / 1000;
+		if (delay < 1)
+			rc = semTake ((SEM_ID) smid, 1);
+		else
+			rc = semTake ((SEM_ID) smid, delay);
+	}
+
+	if (rc != OK)
+	{
+		if (errno == S_objLib_OBJ_TIMEOUT)
+			return GT_TIMEOUT;
+		else
+			return GT_FAIL;
+	}
+
+#elif defined(WIN32)
+	DWORD rc;
+
+	rc = WaitForSingleObject((HANDLE)smid, timeOut);
+
+	if (rc == WAIT_ABANDONED)
+		return GT_FAIL;
+	if (rc == WAIT_TIMEOUT)
+		return GT_TIMEOUT;
+
+#elif defined(LINUX)
+	sem_wait((semaphore*) smid) ; 
+#else
+	return GT_OK;
+
+#endif
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* osSemSignal
+*
+* DESCRIPTION:
+*       Signal a semaphore.
+*
+* INPUTS:
+*       smid    - semaphore Id
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS osSemSignal(GT_SEM smid)
+{
+#ifdef _VXWORKS
+	STATUS rc;
+	rc = semGive ((SEM_ID) smid);
+	if (rc != OK)
+		return GT_FAIL;
+
+#elif defined(WIN32)
+	if(ReleaseSemaphore((HANDLE) smid, 1, NULL) == 0)
+		return GT_FAIL;
+
+#elif defined(LINUX)
+	sem_post((semaphore*) smid) ; 
+#else
+	return GT_OK;
+#endif
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdFFmii.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdFFmii.c
new file mode 100755
index 0000000..7092e9b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdFFmii.c
@@ -0,0 +1,156 @@
+/*******************************************************************************
+*                Copyright 2002, Marvell International Ltd.
+* This code contains confidential information of Marvell semiconductor, inc.
+* no rights are granted herein under any patent, mask work right or copyright
+* of Marvell or any third party.
+* Marvell reserves the right at its sole discretion to request that this code
+* be immediately returned to Marvell. This code is provided "as is".
+* Marvell makes no warranties, express, implied or otherwise, regarding its
+* accuracy, completeness or performance.
+*********************************************************************************/
+/* 
+ * FILENAME:    $Workfile: qdFFmii.c $ 
+ * REVISION:    $Revision: 8 $ 
+ * LAST UPDATE: $Modtime: 3/03/03 3:24a $ 
+ * 
+ * DESCRIPTION: SMI access routines for Firefox board
+ *     
+ */
+#include "mv_platform.h"
+#include "mv_os.h"
+#include "mv_qd.h"
+
+/*
+ * For each platform, all we need is 
+ * 1) Assigning functions into 
+ * 		fgtReadMii : to read MII registers, and
+ * 		fgtWriteMii : to write MII registers.
+ *
+ * 2) Register Interrupt (Not Defined Yet.)
+*/
+
+/* 
+ *  Firefox Specific Definition
+ */
+#define SMI_OP_CODE_BIT_READ                    1
+#define SMI_OP_CODE_BIT_WRITE                   0
+#define SMI_BUSY                                1<<28
+#define READ_VALID                              1<<27
+
+#define SMI_TIMEOUT_COUNTER				1000
+
+/*****************************************************************************
+*
+* GT_BOOL qdFFReadMii (GT_QD_DEV* dev, unsigned int portNumber , 
+*                      unsigned int MIIReg, unsigned int* value)
+*
+* Description
+* This function will access the MII registers and will read the value of
+* the MII register , and will retrieve the value in the pointer.
+* Inputs
+* portNumber - one of the 2 possiable Ethernet ports (0-1).
+* MIIReg - the MII register offset.
+* Outputs
+* value - pointer to unsigned int which will receive the value.
+* Returns Value
+* true if success.
+* false if fail to make the assignment.
+* Error types (and exceptions if exist)
+*/
+GT_BOOL ffReadMii (GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                        unsigned int* value)
+{
+ 	GT_U32			smiReg;
+	unsigned int	phyAddr;
+	unsigned int	timeOut = SMI_TIMEOUT_COUNTER; /* in 100MS units */
+	int	i;
+
+	/* first check that it is not busy */
+    smiReg = gtOsGtRegRead(GT_REG_ETHER_SMI_REG);	
+    if (smiReg & SMI_BUSY) 
+    {
+        for(i=0; i<SMI_TIMEOUT_COUNTER; i++);
+        do 
+		{
+            smiReg = gtOsGtRegRead(GT_REG_ETHER_SMI_REG);
+            if (timeOut-- < 1) 
+			{
+                return GT_FALSE;
+    	    }			
+        } while (smiReg & SMI_BUSY);
+    }	
+	/* not busy */
+    phyAddr = portNumber;
+    smiReg =  (phyAddr << 16) | (SMI_OP_CODE_BIT_READ << 26) | (MIIReg << 21) 
+			| SMI_OP_CODE_BIT_READ << 26;
+
+    gtOsGtRegWrite(GT_REG_ETHER_SMI_REG, smiReg);
+    timeOut = SMI_TIMEOUT_COUNTER; /* initialize the time out var again */
+    smiReg = gtOsGtRegRead(GT_REG_ETHER_SMI_REG);
+    if (!(smiReg & READ_VALID)) 
+    {
+		for(i = 0 ; i < SMI_TIMEOUT_COUNTER; i++);
+        do 
+		{
+            smiReg = gtOsGtRegRead(GT_REG_ETHER_SMI_REG);
+            if (timeOut-- < 1 ) 
+			{
+                return GT_FALSE;
+    	    }
+        } while (!(smiReg & READ_VALID));
+    }
+    *value = (unsigned int)(smiReg & 0xffff);    
+
+    return GT_TRUE;
+}
+
+/*****************************************************************************
+* 
+* GT_BOOL qdFFWriteMii (GT_QD_DEV* dev, unsigned int portNumber , 
+*                       unsigned int MIIReg, unsigned int value)
+* 
+* Description
+* This function will access the MII registers and will write the value
+* to the MII register.
+* Inputs
+* portNumber - one of the 2 possiable Ethernet ports (0-1).
+* MIIReg - the MII register offset.
+* value -the value that will be written.
+* Outputs
+* Returns Value
+* true if success.
+* false if fail to make the assignment.
+* Error types (and exceptions if exist)
+*/
+GT_BOOL ffWriteMii (GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                       unsigned int value)
+{
+	GT_U32			smiReg;
+	unsigned int	phyAddr;
+	unsigned int	timeOut = SMI_TIMEOUT_COUNTER; /* in 100MS units */
+	int	i;
+
+	/* first check that it is not busy */	
+    smiReg = gtOsGtRegRead(GT_REG_ETHER_SMI_REG);
+    if (smiReg & SMI_BUSY) 
+    {
+   	    for(i=0; i<SMI_TIMEOUT_COUNTER; i++);
+        do 
+		{
+            smiReg = gtOsGtRegRead(GT_REG_ETHER_SMI_REG);
+            if (timeOut-- < 1) 
+			{
+                return GT_FALSE;
+    	    }			
+        } while (smiReg & SMI_BUSY);
+    }
+	/* not busy */
+    phyAddr = portNumber;
+
+    smiReg = 0; /* make sure no garbage value in reserved bits */
+    smiReg = smiReg | (phyAddr << 16) | (SMI_OP_CODE_BIT_WRITE << 26) |
+             (MIIReg << 21) | (value & 0xffff);	
+    gtOsGtRegWrite(GT_REG_ETHER_SMI_REG, smiReg);	
+
+    return GT_TRUE;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdInit.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdInit.c
new file mode 100755
index 0000000..503a1df
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdInit.c
@@ -0,0 +1,287 @@
+/*******************************************************************************
+*                Copyright 2002, Marvell International Ltd.
+* This code contains confidential information of Marvell semiconductor, inc.
+* no rights are granted herein under any patent, mask work right or copyright
+* of Marvell or any third party.
+* Marvell reserves the right at its sole discretion to request that this code
+* be immediately returned to Marvell. This code is provided "as is".
+* Marvell makes no warranties, express, implied or otherwise, regarding its
+* accuracy, completeness or performance.
+*********************************************************************************/
+/* 
+ * FILENAME:    $Workfile: qdInit.c $ 
+ * REVISION:    $Revision: 12 $ 
+ * LAST UPDATE: $Modtime: 3/03/03 12:01p $ 
+ * 
+ * DESCRIPTION: QD initialization module
+ *     
+ */
+#include "mv_qd.h"
+#include "mv_debug.h"
+#include "mv_os.h"
+
+void qdStatus(void);
+
+
+/*
+ * A system configuration structure
+ * It used to configure the QD driver with configuration data
+ * and with platform specific implementation functions 
+ */
+GT_SYS_CONFIG   	cfg;
+
+/*
+ * The QD device.
+ * This struct is a logical representation of the QD switch HW device.
+ */
+GT_QD_DEV       	qddev[4] = {{0}};
+
+/*
+ * The QD device pointer.
+ * A constant pointer to the one and only QD device.
+ */
+GT_QD_DEV       	*qd_dev = &qddev[0];
+GT_QD_DEV       	*qd_ext = &qddev[1];
+
+
+/*
+ * read mii register - see qdFFmii.c
+ */ 
+extern GT_BOOL ffReadMii(GT_QD_DEV* dev, 
+		      unsigned int portNumber , 
+		      unsigned int MIIReg, unsigned int* value
+		      );
+
+/*
+ * write mii register - see qdFFmii.c
+ */ 
+extern GT_BOOL ffWriteMii(GT_QD_DEV* dev, 
+		       unsigned int portNumber , 
+		       unsigned int MIIReg, 
+		       unsigned int value
+		       );
+
+/*
+ * A phy patch for deviceId == GT_88E6063
+ */
+static GT_STATUS phyPatch(GT_QD_DEV *dev)
+{
+	GT_U32 u32Data;
+	/*
+	 * Set Bit2 of Register 29 of any phy
+	 */
+    if(gsysReadMiiReg(dev, dev->baseRegAddr,29,&u32Data) != GT_OK)
+	{		
+		return GT_FAIL;
+	}
+
+    if(gsysWriteMiiReg(dev, (GT_U32)dev->baseRegAddr,29,(GT_U16)(u32Data|0x4)) != GT_OK)
+	{		
+		return GT_FAIL;
+	}
+
+	/*
+	 * ReSet Bit6 of Register 30 of any phy
+	 */
+    if(gsysReadMiiReg(dev,dev->baseRegAddr,30,&u32Data) != GT_OK)
+	{		
+		return GT_FAIL;
+	}
+
+    if(gsysWriteMiiReg(dev, (GT_U32)dev->baseRegAddr,30,(GT_U16)(u32Data&(~0x40))) != GT_OK)
+	{		
+		return GT_FAIL;
+	}
+	return GT_OK;
+}
+
+/*
+*  Initialize the QuarterDeck. This should be done in BSP driver init routine.
+*	Since BSP is not combined with QuarterDeck driver, we are doing here.
+*/
+GT_STATUS qdStart(void) /* devId is used for simulator only */
+{
+	GT_STATUS status;
+	/*
+	 *  Register all the required functions to QuarterDeck Driver.
+	 */
+	cfg.BSPFunctions.readMii   = ffReadMii;
+	cfg.BSPFunctions.writeMii  = ffWriteMii;
+#ifdef USE_SEMAPHORE
+	cfg.BSPFunctions.semCreate = osSemCreate;
+	cfg.BSPFunctions.semDelete = osSemDelete;
+	cfg.BSPFunctions.semTake   = osSemWait;
+	cfg.BSPFunctions.semGive   = osSemSignal;
+#else /* USE_SEMAPHORE */
+	cfg.BSPFunctions.semCreate = NULL;
+	cfg.BSPFunctions.semDelete = NULL;
+	cfg.BSPFunctions.semTake   = NULL;
+	cfg.BSPFunctions.semGive   = NULL;
+#endif /* USE_SEMAPHORE */
+
+	cfg.initPorts = GT_TRUE;	
+	cfg.cpuPortNum = GT_CPU_SWITCH_PORT;	
+	qd_dev->cpuPortNum = GT_CPU_SWITCH_PORT;	
+	if((status = qdLoadDriver(&cfg, qd_dev)) != GT_OK) {		
+	  gtOsPrintf("qdLoadDriver is failed: status = 0x%x\n", status);
+	  return status;
+	}
+	
+	/*
+	*  start the QuarterDeck
+	*/
+	if (qd_dev->deviceId == GT_88E6063) {
+	  phyPatch(qd_dev);
+	}
+
+	/* to which VID should we set the CPU_PORT? (1 is temporary)*/
+	if((status = gvlnSetPortVid(qd_dev, GT_CPU_SWITCH_PORT, 5)) != GT_OK) {
+	  gtOsPrintf("gprtSetPortVid returned fail for CPU port.\n");
+	  return status;
+	}
+
+#ifdef QD_TRAILER_MODE
+	/* set ingress trailer mode*/
+	gprtSetIngressMode(qd_dev, GT_CPU_SWITCH_PORT, GT_TRAILER_INGRESS);	
+	/* set egress trailer*/
+	gprtSetTrailerMode(qd_dev, GT_CPU_SWITCH_PORT, GT_TRUE);
+#endif
+
+#ifdef QD_HEADER_MODE
+	if((status = gprtSetHeaderMode(qd_dev, GT_CPU_SWITCH_PORT, GT_TRUE)) != GT_OK)
+	{
+	  gtOsPrintf("gprtSetHeaderMode return Failed\n");
+	  return status;
+	}   
+#endif
+
+	return GT_OK;    
+}
+
+
+void qdClose(void) 
+{
+	if (qd_dev->devEnabled)
+		qdUnloadDriver(qd_dev);
+}
+
+
+GT_STATUS qdInit(void)
+{
+	GT_STATUS	 status = GT_OK;	
+	unsigned int i;
+
+	status = qdStart();
+	if (GT_OK != status)
+	{
+		gtOsPrintf("qdStart is failed: status = 0x%x\n", status);
+		return status;
+	}
+
+#ifdef DB_6093_88E6218
+	/* start 88E6090 device, assumes SMI Address 0x11 and CPU Port 10 */
+
+	if(loadDev(qd_ext, SMI_MULTI_ADDR_MODE, 0x11, 10) == NULL)
+	{
+		gtOsPrintf("Failed to start External Device. Please check the SMI Address 0x11!\n");
+	}
+
+	/* allow larger than 1522 bytes of frame (header + marvell tag) */
+	gsysSetMaxFrameSize(qd_dev,GT_FALSE);
+
+#endif
+
+    for (i=0; i<qd_dev->numOfPorts; i++) 
+    {
+      /* default port prio to three */
+      gcosSetPortDefaultTc(qd_dev, i, 3);       
+      /* disable IP TOS Prio */
+      gqosIpPrioMapEn(qd_dev, i, GT_FALSE);  
+      /* disable QOS Prio */
+      gqosUserPrioMapEn(qd_dev, i, GT_FALSE);
+      /* Force flow control for all ports */
+      gprtSetForceFc(qd_dev, i, GT_FALSE);
+    }
+
+	/* Enable port #6 */
+	status = gstpSetPortState(qd_dev, 6, GT_PORT_FORWARDING);
+
+	if((status = gprtClearAllCtr(qd_dev)) != GT_OK)
+	{		
+		return status;
+	}	
+	for (i=0; i<GT_CPU_SWITCH_PORT; i++)
+	{
+		gprtSetMcRateLimit(qd_dev, i, GT_MC_100_PERCENT_RL);
+	}
+
+#ifdef QD_DEBUG
+    for (i=0; i<qd_dev->numOfPorts; i++) 
+	{
+		short sdata;
+	  
+	  	hwReadPortReg(qd_dev, i, 0x4, &sdata);
+	  	gtOsPrintf("Control reg for port[%d] is: %x\n",i,sdata);
+
+	  	hwReadPortReg(qd_dev, i, 0x0, &sdata);
+	  	gtOsPrintf("Status reg for port[%d] is: %x\n",i,sdata);
+
+	}
+    qdStatus();
+#endif /* QD_DEBUG */
+
+    gtOsPrintf("QD initiated\n");
+
+	return status;    
+}
+
+static const char* qdPortStpStates[] = 
+	{"DISABLE",
+     "BLOCKING",
+     "LEARNING",
+     "FORWARDING"};	
+
+static char* qdPortListToStr(GT_LPORT* portList, int portListNum,
+							char* portListStr)
+{
+	int	port, idx, strIdx=0;
+	
+	for(idx=0; idx<portListNum; idx++)
+	{
+		port = portList[idx];
+		sprintf(&portListStr[strIdx], "%d,", port);
+		strIdx = strlen(portListStr);
+	}
+	portListStr[strIdx] = '\0';
+	return portListStr;
+}
+
+void qdStatus(void)
+{
+	int 				port;
+	GT_BOOL				linkState;
+	GT_PORT_STP_STATE 	stpState;
+	GT_PORT_STAT    	counters;
+	GT_U16				pvid;
+	GT_LPORT 			portList[GT_NUM_OF_SWITCH_PORTS];
+    GT_U8    			portNum;
+	char				portListStr[100];
+
+	gtOsPrintf("Port  Link   PVID    Group       State       RxCntr      TxCntr\n\n");
+
+    for (port=0; port<GT_NUM_OF_SWITCH_PORTS; port++) 
+	{
+		gprtGetLinkState(qd_dev, port, &linkState);
+		gstpGetPortState(qd_dev, port, &stpState);
+		gprtGetPortCtr(qd_dev,port, &counters);
+		gstpGetPortState(qd_dev, port, &stpState);
+		gvlnGetPortVid(qd_dev, port, &pvid);
+		gvlnGetPortVlanPorts(qd_dev, port, portList, &portNum);
+		qdPortListToStr(portList, portNum, portListStr);
+
+		gtOsPrintf(" %d.   %4s    %d     %-10s  %-10s   0x%-8x  0x%-8x\n",
+					port, (linkState==GT_TRUE) ? "UP" : "DOWN",
+					pvid, portListStr, qdPortStpStates[stpState],
+					counters.rxCtr, counters.txCtr);
+	}
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdInt.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdInt.c
new file mode 100755
index 0000000..c274554
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdInt.c
@@ -0,0 +1,355 @@
+#include <Copyright.h>
+/********************************************************************************
+* qdInt.c
+*
+* DESCRIPTION:
+*		This sample shows how to call QuarterDeck Interrupt handler when QD INT
+*		raised, and how to take care each Interrupt Cause.
+*
+* DEPENDENCIES:   NONE.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include "msSample.h"
+
+#ifdef QD_DEBUG
+#ifdef _VXWORKS
+#define INT_MSG_PRINT	logMsg
+#else
+#define INT_MSG_PRINT	printf
+#endif
+#else	/* QD_DEBUG */
+#define INT_MSG_PRINT(_x,_a0,_a1,_a2,_a3,_a4,_a5)	while(0){}
+#endif
+
+GT_U32 QDIntMask = GT_VTU_PROB|GT_ATU_PROB|GT_PHY_INTERRUPT;
+
+/*
+ *	To enable quarterDeck interrupt, you need to call eventSetActive() and
+ *	gprtPhyIntEnable(), as following sample routine.
+ *	sampleQDIntEnable will enable all interrupt causes.
+ *	For Port, GT_ATU_FULL, GT_ATU_DONE, GT_PHY_INTERRUPT, and GT_EE_INTERRUPT
+ *	are enabled.
+ *	For every Phy (0 ~ 4), GT_SPEED_CHANGED, GT_DUPLEX_CHANGED, GT_PAGE_RECEIVED,
+ *	GT_AUTO_NEG_COMPLETED, GT_LINK_STATUS_CHANGED, GT_SYMBOL_ERROR, 
+ *	GT_FALSE_CARRIER, GT_FIFO_FLOW, GT_CROSSOVER_CHANGED, GT_POLARITY_CHANGED,
+ *	and GT_JABBER are enabled.
+*/
+GT_STATUS qdIntEnable(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_U16 data;
+	int port;
+
+	/* 
+	 *	Enable QuarterDeck interrupt for ATUFull, ATUDone, PHYInt, and EEInt.
+	 *	If writing 0 into eventSetActive(), all port interrupt will be disabled.
+	*/
+	data = QDIntMask;
+	if((status = eventSetActive(dev,data)) != GT_OK)
+	{
+		MSG_PRINT(("eventSetActive returned fail.\n"));
+		return status;
+	}
+
+	/* 
+	 *	Enable Phy interrupt for every possible interrupt cause.
+	 *	If writing 0 into gprtPhyIntEnable(), all port interrupt will be disabled.
+	*/
+	data = 	GT_SPEED_CHANGED|GT_DUPLEX_CHANGED|GT_LINK_STATUS_CHANGED;
+
+	for(port=0; port<3; port++)
+	{
+		if((status = gprtPhyIntEnable(dev,port,data)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPhyIntEnable returned fail.\n"));
+			return status;
+		}
+	}
+
+	return GT_OK;
+}
+
+/*
+ *	Disable QuarterDeck Interrupt.
+*/
+GT_STATUS qdIntDisable(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	int port;
+
+	/* 
+	 *	Writing 0 into eventSetActive(), all port interrupt will be disabled.
+	*/
+	if((status = eventSetActive(dev,0)) != GT_OK)
+	{
+		MSG_PRINT(("eventSetActive returned fail.\n"));
+		return status;
+	}
+
+	for(port=0; port<3; port++)
+	{
+		if((status = gprtPhyIntEnable(dev,port,0)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPhyIntEnable returned fail.\n"));
+			return status;
+		}
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ *	Assume that the following function, sampleQDIntVector(), is registered 
+ *	when BSP calls intConnect for QD Interrupt.
+ *	This sample will show how to deal with QuarterDeck Interrupt.
+*/
+GT_STATUS qdIntVector(GT_QD_DEV *dev)
+{
+	GT_U16 intCause,data,phyIntCause;
+    GT_VTU_INT_STATUS vtuIntStatus;
+    GT_ATU_INT_STATUS atuIntStatus;
+	int port;
+
+	/*
+	 *	Disable QuarterDeck Interrupt in System Level.
+	 *	ToDo...
+	*/
+
+	/*
+	 *	Check if QD generated the interrupt.
+	*/
+	if(eventGetIntStatus(dev,&intCause) != GT_TRUE)
+	{
+		/* QD didn't generate the interrupt. */
+		return GT_FAIL;
+	}
+
+	/*
+	 *	QD generated interrupt with the reason in intCause.
+	*/
+	if(intCause & GT_VTU_PROB)
+	{
+		INT_MSG_PRINT("VTU PROB INT for Dev %#x.\n",(int)dev,0,0,0,0,0);
+		/* 
+		 *	VTU member violation, miss violation, or full violation.
+		*/
+		do
+		{
+			if(gvtuGetIntStatus(dev, &vtuIntStatus) != GT_OK)
+			{
+				/* reading VTU Int Status Failed */
+				INT_MSG_PRINT("VTU INT Status read failure.\n",0,0,0,0,0,0);
+				break;
+			}
+			INT_MSG_PRINT("VTU INT : Cause %#x, SPID %i, VID %i\n",vtuIntStatus.vtuIntCause,vtuIntStatus.spid,vtuIntStatus.vid,0,0,0);
+		} while (vtuIntStatus.vtuIntCause);
+	}
+
+	if(intCause & GT_ATU_PROB)
+	{
+		/* 
+		 *	ATU cannot load or learn a new mapping due to all the available
+		 *	locations for an address being locked.
+		 *	ToDo...
+		*/
+		INT_MSG_PRINT("ATU PROB INT for Dev %#x.\n",(int)dev,0,0,0,0,0);
+
+		do
+		{
+			if(gatuGetIntStatus(dev, &atuIntStatus) != GT_OK)
+			{
+				/* reading ATU Int Status Failed */
+				INT_MSG_PRINT("ATU INT Status read failure.\n",0,0,0,0,0,0);
+				break;
+			}
+			INT_MSG_PRINT("ATU INT : Cause %#x, SPID %i, DBNum %i\n",atuIntStatus.atuIntCause,atuIntStatus.spid,atuIntStatus.dbNum,0,0,0);
+			INT_MSG_PRINT("ATU INT : MAC %02x-%02x-%02x-%02x-%02x-%02x\n",
+									atuIntStatus.macAddr.arEther[0],
+									atuIntStatus.macAddr.arEther[1],
+									atuIntStatus.macAddr.arEther[2],
+									atuIntStatus.macAddr.arEther[3],
+									atuIntStatus.macAddr.arEther[4],
+									atuIntStatus.macAddr.arEther[5]);
+		} while (atuIntStatus.atuIntCause);
+
+	}
+
+	if(intCause & GT_ATU_DONE)
+	{
+		/* 
+		 *	There is a transitions from a one to a zero on ATUBusy bit
+		 *	(Refer to ATU Operation Register.)
+		 *	ToDo...
+		*/
+		INT_MSG_PRINT("ATU Done INT for Dev %#x.\n",(int)dev,0,0,0,0,0);
+	}
+
+#if 1
+
+	if(intCause & GT_PHY_INTERRUPT)
+	{
+		/* 
+		 *	At least one of the Phy generated interrupt.
+		 *	We need to read Phy Interrupt Summary and go through each phy
+		 *	based on the summary.
+		*/
+
+		if(gprtGetPhyIntPortSummary(dev,&data) != GT_OK)
+		{
+			return GT_FAIL;
+		}
+
+		INT_MSG_PRINT("Phy INT (Port Vector %#x).\n",(int)data,0,0,0,0,0);
+
+		port = 0;
+		while(data)
+		{
+			if(data & 0x01)
+			{
+				/*
+				 *	Call gprtGetPhyIntStatus to get intCause
+				*/
+				if(gprtGetPhyIntStatus(dev,port,&phyIntCause) != GT_OK)
+				{
+					/* 
+					 *	Something wrong with the system. Need to do the 
+					 *	necessary work. 
+					 *	ToDo...
+					*/
+				}
+
+				INT_MSG_PRINT("Port %i: %#x.\n",port,phyIntCause,0,0,0,0);
+
+				if(phyIntCause & GT_SPEED_CHANGED)
+				{
+					/* 
+					 *	Speed has been changed.
+					 *	ToDo...
+					*/
+					INT_MSG_PRINT("SPEED CHANGE\n",0,0,0,0,0,0);
+				}
+
+				if(phyIntCause & GT_DUPLEX_CHANGED)
+				{
+					/* 
+					 *	Duplex mode has been changed.
+					 *	ToDo...
+					*/
+					INT_MSG_PRINT("DUPLEX CHANGE\n",0,0,0,0,0,0);
+				}
+
+				if(phyIntCause & GT_PAGE_RECEIVED)
+				{
+					/* 
+					 *	Page received.
+					 *	ToDo...
+					*/
+
+					INT_MSG_PRINT("PAGE RECEIVED\n",0,0,0,0,0,0);
+				}
+
+				if(phyIntCause & GT_AUTO_NEG_COMPLETED)
+				{
+					/* 
+					 *	AutoNegotiation completed.
+					 *	ToDo...
+					*/
+					INT_MSG_PRINT("AUTO NEG COMPLETED\n",0,0,0,0,0,0);
+
+				}
+
+				if(phyIntCause & GT_LINK_STATUS_CHANGED)
+				{
+					/* 
+					 *	Link Status changed.
+					 *	ToDo...
+					*/
+
+					INT_MSG_PRINT("LINK CHANGE\n",0,0,0,0,0,0);
+				}
+
+				if(phyIntCause & GT_SYMBOL_ERROR)
+				{
+					/* 
+					 *	Symbol error
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_FALSE_CARRIER)
+				{
+					/* 
+					 *	False Carrier.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_FIFO_FLOW)
+				{
+					/* 
+					 *	Fifo Overflow/underflow error
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_CROSSOVER_CHANGED)
+				{
+					/* 
+					 *	MDI/MDIX crossover changed.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_POLARITY_CHANGED)
+				{
+					/* 
+					 *	Polarity changed.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_JABBER)
+				{
+					/* 
+					 *	Jabber
+					 *	ToDo...
+					*/
+
+				}
+			}
+
+			data >>= 1;
+			port++;
+		}
+	}
+
+	if(intCause & GT_EE_INTERRUPT)
+	{
+		/* 
+		 *	EEPROM is done loading registers.
+		 *	ToDo...
+		*/
+
+	}
+
+
+	/*
+	 *	Now, all the QuarterDeck related interrupt have been cleared,
+	 *	so it's OK to enable QuarterDeck Interrupt in System Level.
+	 *	ToDo...
+	*/
+
+#endif
+	
+	return GT_OK;
+
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdSim.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdSim.c
new file mode 100755
index 0000000..557df5f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdSim.c
@@ -0,0 +1,2004 @@
+#include <Copyright.h>
+/********************************************************************************
+* qdSim.c
+*
+* DESCRIPTION:
+*       Simulate QuaterDeck Device(88E6052)'s register map. When QuareterDeck API 
+*		try to read/write a bit or bits into QuaterDeck, the simulator will redirect to
+* 		its own memory place and performing the function very close to QuaterDeck.
+*		For example, 
+*		1) user can set/reset a certain bit of QuarterDeck registers(Phy,Port,and General registers).
+*		2) user can access ATU (flush, load, purge, etc. with max MAC addresses of 32)
+*		3) user can manually generate an Interrupt and test the Interrupt routine.
+*		4) when user read a register, it will clear a certain register if it's a Self Clear register.
+*		5) when user write a register, it will return ERROR if it's read only register.
+*		 
+*
+* DEPENDENCIES:   QuaterDeck (88E6052) Register MAP.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include <msApi.h>
+#include <qdSimRegs.h>
+
+#define IS_BROADCAST_ADDR(_addr)                                \
+            (((_addr)[0] == 0xFF) && ((_addr)[1] == 0xFF) &&    \
+             ((_addr)[2] == 0xFF) && ((_addr)[3] == 0xFF) &&    \
+             ((_addr)[4] == 0xFF) && ((_addr)[5] == 0xFF))
+
+#define IS_GLOBAL_REG(_port)	((int)(_port) == qdSimDev.qdSimGlobalRegBase)
+#define IS_PORT_REG(_port) (((int)(_port) >= qdSimDev.qdSimPortBase) && ((int)(_port) < qdSimDev.qdSimPortBase + qdSimDev.qdSimNumOfPorts))
+#define IS_PHY_REG(_port) (((int)(_port) >= qdSimDev.qdSimPhyBase) && ((int)(_port) < qdSimDev.qdSimPhyBase + qdSimDev.qdSimNumOfPhys))
+
+typedef struct _QD_SIM_DEV
+{
+	int qdSimUsed;
+	unsigned int qdSimDevId;
+	int qdSimNumOfPorts;
+	int qdSimPortBase;
+	int qdSimNumOfPhys;
+	int qdSimPhyBase;
+	int qdSimGlobalRegBase;
+	int qdSimPortStatsClear[10];
+	int qdSimStatsCapturedPort;
+	int vtuSize;
+	int atuSize;
+} QD_SIM_DEV;
+
+static QD_SIM_DEV qdSimDev = {0};
+
+void qdSimRegsInit();
+GT_BOOL qdSimRead (GT_QD_DEV *dev, unsigned int portNumber , unsigned int miiReg, unsigned int* value);
+GT_BOOL qdSimWrite(GT_QD_DEV *dev, unsigned int portNumber , unsigned int miiReg, unsigned int value);
+
+/*
+ *	This Array will simulate the QuarterDeck Registers.
+ *	To use it, qdSimRegs has to be initialized with its default values and
+ *	Call qdSimRead and qdSimWrite functions.
+*/
+#define MAX_SMI_ADDRESS		0x20
+#define MAX_REG_ADDRESS		0x20
+#define MAX_ATU_ADDRESS		0x800
+#define MAX_QD_VTU_ENTRIES	0x40
+
+GT_U16 qdSimRegs[MAX_SMI_ADDRESS][MAX_REG_ADDRESS];
+
+typedef struct _QDSIM_ATU_ENTRY
+{
+	GT_U16 atuData;
+	GT_U16 DBNum;
+	GT_U8 atuMac[6];
+} QDSIM_ATU_ENTRY;
+
+/* 
+	Since QuarterDeck Simulator supports only fixed size of atu entry,
+	we are going with array list not dynamic linked list.
+*/
+typedef struct _QDSIM_ATU_NODE
+{
+	QDSIM_ATU_ENTRY atuEntry;
+	GT_U32 nextEntry;
+} QDSIM_ATU_NODE;
+
+typedef struct _QDSIM_ATU_LIST
+{
+	int atuSize;
+	GT_U32 head;
+} QDSIM_ATU_LIST;
+
+QDSIM_ATU_NODE ATUNode[MAX_ATU_ADDRESS];
+QDSIM_ATU_LIST ATUList;
+
+typedef struct _QDSIM_VTU_ENTRY
+{
+	GT_U16 DBNum;
+	GT_U16 memberTag[10];
+	GT_U16 vid;
+} QDSIM_VTU_ENTRY;
+
+/* 
+	Since QuarterDeck Simulator supports only fixed size of atu entry,
+	we are going with array list not dynamic linked list.
+*/
+typedef struct _QDSIM_VTU_NODE
+{
+	QDSIM_VTU_ENTRY vtuEntry;
+	GT_U32 nextEntry;
+} QDSIM_VTU_NODE;
+
+typedef struct _QDSIM_VTU_LIST
+{
+	int vtuSize;
+	GT_U32 head;
+} QDSIM_VTU_LIST;
+
+QDSIM_VTU_NODE VTUNode[MAX_QD_VTU_ENTRIES];
+QDSIM_VTU_LIST VTUList;
+
+/*******************************************************************************
+* qdMemSet
+*
+* DESCRIPTION:
+*       Set a block of memory
+*
+* INPUTS:
+*       start  - start address of memory block for setting
+*       simbol - character to store, converted to an unsigned char
+*       size   - size of block to be set
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       Pointer to set memory block
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void * qdMemSet
+(
+    IN void * start,
+    IN int    symbol,
+    IN GT_U32 size
+)
+{
+	GT_U32 i;
+	char* buf;
+	
+	buf = (char*)start;
+		
+	for(i=0; i<size; i++)
+	{
+		*buf++ = (char)symbol;
+	}
+
+	return start;
+}
+
+/*******************************************************************************
+* qdMemCpy
+*
+* DESCRIPTION:
+*       Copies 'size' characters from the object pointed to by 'source' into
+*       the object pointed to by 'destination'. If copying takes place between
+*       objects that overlap, the behavior is undefined.
+*
+* INPUTS:
+*       destination - destination of copy
+*       source      - source of copy
+*       size        - size of memory to copy
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       Pointer to destination
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void * qdMemCpy
+(
+    IN void *       destination,
+    IN const void * source,
+    IN GT_U32       size
+)
+{
+	GT_U32 i;
+	char* buf;
+	char* src;
+	
+	buf = (char*)destination;
+	src = (char*)source;
+		
+	for(i=0; i<size; i++)
+	{
+		*buf++ = *src++;
+	}
+
+	return destination;
+}
+
+/*******************************************************************************
+* qdMemCmp
+*
+* DESCRIPTION:
+*       Compares given memories.
+*
+* INPUTS:
+*       src1 - source 1
+*       src2 - source 2
+*       size - size of memory to copy
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       0, if equal.
+*		negative number, if src1 < src2.
+*		positive number, if src1 > src2.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int qdMemCmp
+(
+    IN char src1[],
+    IN char src2[],
+    IN GT_U32 size
+)
+{
+	GT_U32 i;
+	int value;
+
+	for(i=0; i<size; i++)
+	{
+		if((value = (int)(src1[i] - src2[i])) != 0)
+			return value; 
+	}
+
+	return 0;
+}
+
+/*
+	Compare the given ethernet addresses.
+	0, if they are equal.
+	Negative int, if mac2 is bigger than mac1.
+	Positive int, if mac1 is bigger than mac2.
+*/
+int cmpEtherMac(unsigned char* mac1, unsigned char* mac2)
+{
+	int i, tmp;
+
+	for(i=0; i<6; i++)
+	{
+		if((tmp = mac1[i] - mac2[i]) != 0)
+			return tmp;
+	}
+	return 0;
+}
+
+/*
+	entry index, if found.
+	MAX_ATU_ADDRESS, otherwise.
+*/
+int qdSimATUFindNext(QDSIM_ATU_ENTRY* entry)
+{
+	int i;
+	int node = ATUList.head;
+
+	if (IS_BROADCAST_ADDR(entry->atuMac))
+	{
+		if(ATUList.atuSize != 0)
+		{
+			if (ATUNode[node].atuEntry.DBNum == entry->DBNum)
+				return node;
+			else
+			{
+				for(i=0; i<ATUList.atuSize; i++)
+				{
+					if(ATUNode[node].atuEntry.DBNum == entry->DBNum)
+						return node;
+					node = ATUNode[node].nextEntry;
+				}
+			}
+				
+		}
+		return MAX_ATU_ADDRESS;
+	}
+
+	for(i=0; i<ATUList.atuSize; i++)
+	{
+		if(cmpEtherMac(ATUNode[node].atuEntry.atuMac,entry->atuMac) > 0)
+		{
+			if(ATUNode[node].atuEntry.DBNum == entry->DBNum)
+				break;
+		}
+		node = ATUNode[node].nextEntry;
+	}
+
+	if (i == ATUList.atuSize)
+		return MAX_ATU_ADDRESS;
+
+	return node;
+}
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimATUAdd(QDSIM_ATU_ENTRY* entry)
+{
+	int i, freeNode, preNode, node;
+
+	preNode = node = ATUList.head;
+
+	if (ATUList.atuSize >= MAX_ATU_ADDRESS)
+		return GT_FALSE;
+
+	/* find a free entry from our global memory. */
+	for(i=0; i<MAX_ATU_ADDRESS; i++)
+	{
+		if(ATUNode[i].nextEntry == MAX_ATU_ADDRESS)
+			break;
+	}
+	
+	if (i==MAX_ATU_ADDRESS)
+	{
+		return GT_FALSE;
+	}
+
+	freeNode = i;
+
+	/* find the smallest entry which is bigger than the given entry */
+	for(i=0; i<ATUList.atuSize; i++)
+	{
+		if(cmpEtherMac(ATUNode[node].atuEntry.atuMac,entry->atuMac) >= 0)
+			break;
+		preNode = node;
+		node = ATUNode[node].nextEntry;
+	}	
+
+	/* if the same Mac address is in the list and dbnum is identical, then just update and return. */
+	if (i != ATUList.atuSize)
+		if(cmpEtherMac(ATUNode[node].atuEntry.atuMac,entry->atuMac) == 0)
+		{
+			if(ATUNode[node].atuEntry.DBNum == entry->DBNum)
+			{
+				ATUNode[node].atuEntry.atuData = entry->atuData;
+				return GT_TRUE;
+			}
+		}
+
+	qdMemCpy(ATUNode[freeNode].atuEntry.atuMac, entry->atuMac, 6);
+	ATUNode[freeNode].atuEntry.atuData = entry->atuData;
+	ATUNode[freeNode].atuEntry.DBNum = entry->DBNum;
+
+	/* Add it to head */
+	if (i == 0)
+	{
+		ATUNode[freeNode].nextEntry = ATUList.head;
+		ATUList.head = freeNode;
+	}
+	/* Add it to tail */
+	else if (i == ATUList.atuSize)
+	{
+		ATUNode[preNode].nextEntry = freeNode;
+		ATUNode[freeNode].nextEntry = ATUList.head;
+	}
+	/* Add it in the middle of the list */
+	else
+	{
+		ATUNode[freeNode].nextEntry = ATUNode[preNode].nextEntry;
+		ATUNode[preNode].nextEntry = freeNode;
+	}
+	ATUList.atuSize++;
+	return GT_TRUE;
+}
+
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimATUDel(QDSIM_ATU_ENTRY* entry)
+{
+	int i, preNode, node;
+
+	preNode = node = ATUList.head;
+
+	/* find the entry */
+	for(i=0; i<ATUList.atuSize; i++)
+	{
+		if(cmpEtherMac(ATUNode[node].atuEntry.atuMac,entry->atuMac) == 0)
+		{
+			if(ATUNode[node].atuEntry.DBNum == entry->DBNum)
+				break;
+		}
+		preNode = node;
+		node = ATUNode[node].nextEntry;
+	}	
+
+	if (i == ATUList.atuSize)
+	{
+		/* cannot find the given entry to be deleted. */
+		return GT_FALSE;
+	}
+
+	/* Delete it from head */
+	if (i == 0)
+	{
+		ATUList.head = ATUNode[node].nextEntry;
+	}
+	/* Delete it in the middle of the list */
+	else if (i != ATUList.atuSize-1)
+	{
+		ATUNode[preNode].nextEntry = ATUNode[node].nextEntry;
+	}
+	ATUList.atuSize--;
+	ATUNode[node].nextEntry = MAX_ATU_ADDRESS;
+
+	return GT_TRUE;
+}
+
+
+GT_BOOL qdSimATUFlushUnlockedEntry()
+{
+	int i;
+
+	for (i=0; i<MAX_ATU_ADDRESS; i++)
+	{
+		if(((ATUNode[i].atuEntry.atuData & 0xF) != 0xF)	&&
+			(!(ATUNode[i].atuEntry.atuMac[0] & 1)) 		&&
+			(ATUNode[i].nextEntry != MAX_ATU_ADDRESS))
+		{
+			qdSimATUDel(&ATUNode[i].atuEntry);
+		}			
+	}
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimATUFlushInDB(int dbNum)
+{
+	int i;
+
+	for (i=0; i<MAX_ATU_ADDRESS; i++)
+	{
+		if(ATUNode[i].atuEntry.DBNum != dbNum)
+			continue;
+		qdSimATUDel(&ATUNode[i].atuEntry);
+	}
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimATUFlushUnlockedInDB(int dbNum)
+{
+	int i;
+
+	for (i=0; i<MAX_ATU_ADDRESS; i++)
+	{
+		if(ATUNode[i].atuEntry.DBNum != dbNum)
+			continue;
+		
+		if(((ATUNode[i].atuEntry.atuData & 0xF) != 0xF)	&&
+			(!(ATUNode[i].atuEntry.atuMac[0] & 1)) 		&&
+			(ATUNode[i].nextEntry != MAX_ATU_ADDRESS))
+		{
+			qdSimATUDel(&ATUNode[i].atuEntry);
+		}			
+	}
+	return GT_TRUE;
+}
+
+
+void qdSimATUInit()
+{
+	int i;
+
+	qdMemSet((char*)ATUNode, 0, sizeof(ATUNode));
+
+	/* MAX_ATU_ADDRESS means entry i is free, otherwise, it's not free */
+	for (i=0; i<MAX_ATU_ADDRESS; i++)
+		ATUNode[i].nextEntry = MAX_ATU_ADDRESS;
+
+	ATUList.atuSize = 0;	
+	ATUList.head = 0;	
+}
+
+void qdSimGetATUInfo(QDSIM_ATU_ENTRY* entry)
+{
+	entry->atuData = qdSimRegs[qdSimDev.qdSimGlobalRegBase][12];
+	entry->atuMac[0] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] >> 8) & 0xFF;
+	entry->atuMac[1] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] & 0xFF;
+	entry->atuMac[2] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] >> 8) & 0xFF;
+	entry->atuMac[3] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] & 0xFF;
+	entry->atuMac[4] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] >> 8) & 0xFF;
+	entry->atuMac[5] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] & 0xFF;
+	entry->DBNum = qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] & 0xF;
+	return;
+}
+
+void qdSimSetATUInfo(QDSIM_ATU_ENTRY* entry)
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][12] = entry->atuData;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] = (entry->atuMac[0]<<8) | entry->atuMac[1];
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] = (entry->atuMac[2]<<8) | entry->atuMac[3];
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] = (entry->atuMac[4]<<8) | entry->atuMac[5];
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] |= (entry->DBNum & 0xF);
+
+	return;
+}
+
+void qdSimReSetATUInfo()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][12] = 0;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] = 0xFFFF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] = 0xFFFF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] = 0xFFFF;
+
+	return;
+}
+
+GT_BOOL qdSimATUOperation(unsigned int value)
+{
+	QDSIM_ATU_ENTRY entry;
+	int	index;
+
+	switch((value & 0x7000) >> 12)
+	{
+		case 1:
+			/* Flush ALL */
+			qdSimATUInit();
+			break;
+		case 2:
+			/* Flush all unlocked entries */
+			return qdSimATUFlushUnlockedEntry();
+		case 3:
+			/* Load or Purge entry */
+			qdSimGetATUInfo(&entry);
+			if(entry.atuData & 0xF)
+				return qdSimATUAdd(&entry);
+			else
+				return qdSimATUDel(&entry);
+			break;
+		case 4:
+			/* Get Next Entry */
+			qdSimGetATUInfo(&entry);
+			index = qdSimATUFindNext(&entry);
+			if (index == MAX_ATU_ADDRESS)
+			{
+				qdSimReSetATUInfo();
+				return GT_TRUE;
+			}
+			else
+			{
+				qdSimSetATUInfo(&ATUNode[index].atuEntry);
+				return GT_TRUE;
+			}
+			break;
+		case 5:
+			/* Flush ALL in a DBNum */
+			return qdSimATUFlushInDB(value & 0xF);
+			break;
+		case 6:
+			/* Flush all unlocked entries */
+			return qdSimATUFlushUnlockedInDB(value & 0xF);
+		default:
+			break;
+	}
+	return GT_TRUE;
+}
+
+/*
+	VTU Related Routines
+*/
+
+/*
+	entry index, if found.
+	MAX_QD_VTU_ENTRIES, otherwise.
+*/
+int qdSimVTUFindNext(QDSIM_VTU_ENTRY* entry)
+{
+	int i;
+	int node = VTUList.head;
+
+	if (entry->vid == 0xFFF)
+	{
+		if(VTUList.vtuSize != 0)
+			return node;
+		else
+			return MAX_QD_VTU_ENTRIES;
+	}
+		
+	for(i=0; i<VTUList.vtuSize; i++)
+	{
+		if(VTUNode[node].vtuEntry.vid > entry->vid)
+			break;
+		node = VTUNode[node].nextEntry;
+	}
+
+	if (i == VTUList.vtuSize)
+		return MAX_QD_VTU_ENTRIES;
+
+	return node;
+}
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimVTUAdd(QDSIM_VTU_ENTRY* entry)
+{
+	int i, freeNode, preNode, node;
+
+	preNode = node = VTUList.head;
+
+	if (VTUList.vtuSize >= qdSimDev.vtuSize)
+		return GT_FALSE;
+
+	/* find a free entry from our global memory. */
+	for(i=0; i<MAX_QD_VTU_ENTRIES; i++)
+	{
+		if(VTUNode[i].nextEntry == MAX_QD_VTU_ENTRIES)
+			break;
+	}
+	
+	if (i==MAX_QD_VTU_ENTRIES)
+	{
+		return GT_FALSE;
+	}
+
+	freeNode = i;
+
+	/* find the smallest entry which is bigger than the given entry */
+	for(i=0; i<VTUList.vtuSize; i++)
+	{
+		if(VTUNode[node].vtuEntry.vid >= entry->vid)
+			break;
+		preNode = node;
+		node = VTUNode[node].nextEntry;
+	}	
+
+	/* if the same vid is in the list, then just update and return. */
+	if (i != VTUList.vtuSize)
+		if(VTUNode[node].vtuEntry.vid == entry->vid)
+		{
+			qdMemCpy(&VTUNode[node].vtuEntry, entry, sizeof(QDSIM_VTU_ENTRY));
+			return GT_TRUE;
+		}
+
+	qdMemCpy(&VTUNode[freeNode].vtuEntry, entry, sizeof(QDSIM_VTU_ENTRY));
+
+	/* Add it to head */
+	if (i == 0)
+	{
+		VTUNode[freeNode].nextEntry = VTUList.head;
+		VTUList.head = freeNode;
+	}
+	/* Add it to tail */
+	else if (i == VTUList.vtuSize)
+	{
+		VTUNode[preNode].nextEntry = freeNode;
+		VTUNode[freeNode].nextEntry = VTUList.head;
+	}
+	/* Add it in the middle of the list */
+	else
+	{
+		VTUNode[freeNode].nextEntry = VTUNode[preNode].nextEntry;
+		VTUNode[preNode].nextEntry = freeNode;
+	}
+	VTUList.vtuSize++;
+	return GT_TRUE;
+}
+
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimVTUDel(QDSIM_VTU_ENTRY* entry)
+{
+	int i, preNode, node;
+
+	preNode = node = VTUList.head;
+
+	/* find the entry */
+	for(i=0; i<VTUList.vtuSize; i++)
+	{
+		if(VTUNode[node].vtuEntry.vid == entry->vid)
+			break;
+		preNode = node;
+		node = VTUNode[node].nextEntry;
+	}	
+
+	if (i == VTUList.vtuSize)
+	{
+		/* cannot find the given entry to be deleted. */
+		return GT_FALSE;
+	}
+
+	/* Delete it from head */
+	if (i == 0)
+	{
+		VTUList.head = VTUNode[node].nextEntry;
+	}
+	/* Delete it in the middle of the list */
+	else if (i != VTUList.vtuSize-1)
+	{
+		VTUNode[preNode].nextEntry = VTUNode[node].nextEntry;
+	}
+	VTUList.vtuSize--;
+	VTUNode[node].nextEntry = MAX_QD_VTU_ENTRIES;
+
+	return GT_TRUE;
+}
+
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimVTUUpdate(QDSIM_VTU_ENTRY* entry)
+{
+	int i;
+	int node = VTUList.head;
+
+	/* find the entry */
+	for(i=0; i<VTUList.vtuSize; i++)
+	{
+		if(VTUNode[node].vtuEntry.vid == entry->vid)
+			break;
+		node = VTUNode[node].nextEntry;
+	}	
+
+	if (i == VTUList.vtuSize)
+	{
+		/* cannot find the given entry to be deleted. */
+		return GT_FALSE;
+	}
+
+	/* Update the found entry */
+	qdMemCpy(&VTUNode[node].vtuEntry, entry, sizeof(QDSIM_VTU_ENTRY));
+
+	return GT_TRUE;
+}
+
+void qdSimVTUInit()
+{
+	int i;
+
+	qdMemSet((char*)VTUNode, 0, sizeof(VTUNode));
+
+	/* MAX_ATU_ADDRESS means entry i is free, otherwise, it's not free */
+	for (i=0; i<MAX_QD_VTU_ENTRIES; i++)
+		VTUNode[i].nextEntry = MAX_QD_VTU_ENTRIES;
+
+	VTUList.vtuSize = 0;	
+	VTUList.head = 0;	
+}
+
+void qdSimGetVTUInfo(QDSIM_VTU_ENTRY* entry)
+{
+	entry->DBNum = qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] & 0xF;
+	entry->vid = qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] & 0x1FFF;
+	entry->memberTag[0] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] & 0x3;
+	entry->memberTag[1] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] >> 4) & 0x3;
+	entry->memberTag[2] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] >> 8) & 0x3;
+	entry->memberTag[3] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] >> 12) & 0x3;
+	entry->memberTag[4] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] & 0x3;
+	entry->memberTag[5] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] >> 4) & 0x3;
+	entry->memberTag[6] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] >> 8) & 0x3;
+	entry->memberTag[7] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] >> 12) & 0x3;
+	entry->memberTag[8] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][9] & 0x3;
+	entry->memberTag[9] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][9] >> 4) & 0x3;
+
+	return;
+}
+
+void qdSimSetVTUInfo(QDSIM_VTU_ENTRY* entry)
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= entry->DBNum;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = (entry->vid & 0xFFF) | 0x1000;
+
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] = 	entry->memberTag[0] |
+						(entry->memberTag[1] << 4) |
+						(entry->memberTag[2] << 8) |
+						(entry->memberTag[3] << 12);
+
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] = 	entry->memberTag[4] |
+						(entry->memberTag[5] << 4) |
+						(entry->memberTag[6] << 8) |
+						(entry->memberTag[7] << 12);
+
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][9] = 	entry->memberTag[8] |
+						(entry->memberTag[9] << 4);
+
+	return;
+}
+
+void qdSimReSetVTUInfo()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 0xFFF;
+
+	return;
+}
+
+void qdSimVTUGetViolation()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0xFFF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= 1;	/* assume port 1 causes the violation */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 1;	/* assume vid 1 causes the violation */
+}
+
+void qdSimVTUResetBusy()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0x8000;
+
+	return;
+}
+
+GT_BOOL qdSimVTUOperation(unsigned int value)
+{
+	QDSIM_VTU_ENTRY entry;
+	int	index;
+
+	if(!(value & 0x8000))
+		return GT_FALSE;
+
+	qdSimVTUResetBusy();
+
+	switch((value & 0x7000) >> 12)
+	{
+		case 1:
+			/* Flush ALL */
+			qdSimVTUInit();
+			break;
+		case 3:
+			/* Load or Purge entry */
+			qdSimGetVTUInfo(&entry);
+			if(entry.vid & 0x1000)
+			{
+				entry.vid &= ~0x1000;
+				return qdSimVTUAdd(&entry);
+			}
+			else
+				return qdSimVTUDel(&entry);
+			break;
+		case 4:
+			/* Get Next Entry */
+			qdSimGetVTUInfo(&entry);
+			entry.vid &= ~0x1000;
+			index = qdSimVTUFindNext(&entry);
+			if (index == MAX_QD_VTU_ENTRIES)
+			{
+				qdSimReSetVTUInfo();
+				return GT_TRUE;
+			}
+			else
+			{
+				qdSimSetVTUInfo(&VTUNode[index].vtuEntry);
+				return GT_TRUE;
+			}
+			break;
+		case 7:
+			qdSimVTUGetViolation();
+			break;
+		default:
+			break;
+	}
+	return GT_TRUE;
+}
+
+void qdSimStatsInit()
+{
+	int i;
+
+	for(i=0; i<qdSimDev.qdSimNumOfPorts; i++)
+		qdSimDev.qdSimPortStatsClear[i] = 0;
+
+}
+
+GT_BOOL qdSimStatsOperation(unsigned int value)
+{
+	int	i;
+
+	if(!(value & 0x8000))
+		return GT_FALSE;
+
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][29] &= ~0x8000;
+
+	switch((value & 0x7000) >> 12)
+	{
+		case 1:
+			/* Flush ALL */
+			for(i=0; i<qdSimDev.qdSimNumOfPorts; i++)
+				qdSimDev.qdSimPortStatsClear[i] = 1;
+			break;
+		case 2:
+			/* Flush a port */
+			if ((value & 0x3F) >= (unsigned int)qdSimDev.qdSimNumOfPorts)
+				return GT_FALSE;
+			qdSimDev.qdSimPortStatsClear[value & 0x3F] = 1;
+			break;
+		case 4:
+			/* Read a counter */
+			if(qdSimDev.qdSimPortStatsClear[qdSimDev.qdSimStatsCapturedPort] == 1)
+			{
+				qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = 0;
+				qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = 0;
+			}
+			else
+			{
+				qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = qdSimDev.qdSimStatsCapturedPort;
+				qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = value & 0x3F;
+			}
+			break;
+		case 5:
+			if ((value & 0x3F) >= (unsigned int)qdSimDev.qdSimNumOfPorts)
+				return GT_FALSE;
+			qdSimDev.qdSimStatsCapturedPort = value & 0x3F;
+			break;
+		default:
+			return GT_FALSE;
+	}
+	return GT_TRUE;
+}
+
+#define QD_PHY_CONTROL_RW (QD_PHY_RESET|QD_PHY_LOOPBACK|QD_PHY_SPEED|QD_PHY_AUTONEGO|QD_PHY_POWER|QD_PHY_RESTART_AUTONEGO|QD_PHY_DUPLEX)
+#define QD_PHY_CONTROL_RO (~QD_PHY_CONTROL_RW)
+
+GT_BOOL qdSimPhyControl(unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+
+	/* reset all the Read Only bits. */
+	value &= QD_PHY_CONTROL_RW;
+
+	/* If powerDown is set, add Reset and Restart Auto bits. */
+	if(value & QD_PHY_POWER)
+	{
+		value |= (QD_PHY_RESET|QD_PHY_RESTART_AUTONEGO);
+		qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+		return GT_TRUE;
+	}
+
+	/* If Power Down was set, clear Reset and Restart Auto bits. */
+	if(qdSimRegs[portNumber][miiReg] & QD_PHY_POWER)
+	{
+		value &= ~(QD_PHY_RESET|QD_PHY_RESTART_AUTONEGO);
+		qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+		return GT_TRUE;
+	}
+
+	/* If Reset or Restart Auto set, replace with current value and clear Reset/Restart Auto. */
+	if (value & (QD_PHY_RESET|QD_PHY_RESTART_AUTONEGO))
+	{
+		value &= ~(QD_PHY_RESET|QD_PHY_RESTART_AUTONEGO);
+		qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+		return GT_TRUE;
+	}
+	else
+	{
+		value &= ~(QD_PHY_SPEED|QD_PHY_AUTONEGO|QD_PHY_DUPLEX);
+		qdSimRegs[portNumber][miiReg] &= (QD_PHY_SPEED|QD_PHY_AUTONEGO|QD_PHY_DUPLEX);
+		qdSimRegs[portNumber][miiReg] |= (GT_U16)value;
+		return GT_TRUE;
+	}
+
+	return GT_TRUE;
+}
+
+void qdSimRegsInit_6021()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] = 0;	/* VTU Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 0;	/* VTU VID Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][29] = 0;	/* Stats Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = 0;	/* Stats Counter Register Bytes 3,2 */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = 0;	/* Stats Counter Register Bytes 1,0 */
+}
+
+void qdSimRegsInit_6063()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] = 0;	/* VTU Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 0;	/* VTU VID Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][29] = 0;	/* Stats Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = 0;	/* Stats Counter Register Bytes 3,2 */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = 0;	/* Stats Counter Register Bytes 1,0 */
+}
+
+void qdSimRegsInit_6083()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] = 0;	/* VTU Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 0;	/* VTU VID Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][9] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][29] = 0;	/* Stats Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = 0;	/* Stats Counter Register Bytes 3,2 */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = 0;	/* Stats Counter Register Bytes 1,0 */
+}
+
+void qdSimRegsInit()
+{
+	int i;
+
+	qdMemSet(qdSimRegs, 0xff, sizeof(qdSimRegs));
+	
+	/* 
+		PHY Registers Setup
+	*/
+	for(i=0; i<qdSimDev.qdSimNumOfPhys; i++)
+	{
+		qdSimRegs[i][0] = 0x3100;	/* PHY Control */
+		qdSimRegs[i][1] = 0x7849;	/* PHY Status */
+		qdSimRegs[i][2] = 0x0141;	/* PHY Id 1 */
+		qdSimRegs[i][3] = 0x0c1f;	/* PHY Id 2 */
+		qdSimRegs[i][4] = 0x01e1;	/* AutoNego Ad */
+		qdSimRegs[i][5] = 0;		/* Partner Ability */
+		qdSimRegs[i][6] = 4;		/* AutoNego Expansion */
+		qdSimRegs[i][7] = 0x2001;	/* Next Page Transmit */
+		qdSimRegs[i][8] = 0;		/* Link Partner Next Page */
+		qdSimRegs[i][16] = 0x130;	/* Phy Specific Control */
+		qdSimRegs[i][17] = 0x40;	/* Phy Specific Status */
+		qdSimRegs[i][18] = 0;		/* Phy Interrupt Enable */
+		qdSimRegs[i][19] = 0x40;	/* Phy Interrupt Status */
+		qdSimRegs[i][20] = 0;		/* Interrupt Port Summary */
+		qdSimRegs[i][21] = 0;		/* Receive Error Counter */
+		qdSimRegs[i][22] = 0xa34;	/* LED Parallel Select */
+		qdSimRegs[i][23] = 0x3fc;	/* LED Stream Select */
+		qdSimRegs[i][24] = 0x42bf;	/* LED Control */
+	}
+
+	/*
+		Port Registers Setup
+	*/
+	for(i=qdSimDev.qdSimPortBase; i<qdSimDev.qdSimNumOfPorts+qdSimDev.qdSimPortBase; i++)
+	{
+		qdSimRegs[i][0] = 0x800;	/* Port Status */
+		qdSimRegs[i][3] = (GT_U16)qdSimDev.qdSimDevId << 4;	/* Switch ID */
+		qdSimRegs[i][4] = 0x7f;	/* Port Control */
+		qdSimRegs[i][6] = 0x7f & (~(1 << (i-8)));	/* Port Based Vlan Map */
+		qdSimRegs[i][7] = 1;		/* Default Port Vlan ID & Priority */
+		qdSimRegs[i][16] = 0;		/* Rx Frame Counter */
+		qdSimRegs[i][17] = 0;		/* Tx Frame Counter */
+	}
+
+	/*
+		Global Registers Setup
+	*/
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][0] = 0x3c01;	/* Global Status */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][1] = 0;		/* Switch Mac Addr 0 ~ 1 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][2] = 0;		/* Switch Mac Addr 2 ~ 3 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][3] = 0;		/* Switch Mac Addr 4 ~ 5 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][4] = 0x81;	/* Global Control */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][10] = 0x1130;		/* ATU Control */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] = 0;				/* ATU Operation */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][12] = 0;				/* ATU Data */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] = 0;				/* ATU Mac Addr 0 ~ 1 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] = 0;				/* ATU Mac Addr 2 ~ 3 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] = 0;				/* ATU Mac Addr 4 ~ 5 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][16] = 0;			/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][17] = 0;			/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][18] = 0x5555;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][19] = 0x5555;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][20] = 0xaaaa;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][21] = 0xaaaa;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][22] = 0xffff;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][23] = 0xffff;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][24] = 0xfa41;	/* IEEE-PRI Mapping */
+			  
+	switch(qdSimDev.qdSimDevId)
+	{
+		case GT_88E6021:
+			qdSimRegsInit_6021();
+			break;
+		case GT_88E6063:
+		case GT_FF_HG:
+		case GT_FF_EG:
+		case GT_FH_VPN:
+			qdSimRegsInit_6063();
+			break;
+		case GT_88E6083:
+			qdSimRegsInit_6083();
+			break;
+		default:
+			break;
+	}
+}
+
+GT_BOOL qdSimRead_6052(unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	*value = (unsigned int) qdSimRegs[portNumber][miiReg];
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					qdSimRegs[portNumber][miiReg] &= ~0xF;
+					if(qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG])
+						qdSimRegs[portNumber][miiReg] |= 0x2;
+
+					break;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+			case QD_REG_GLOBAL_CONTROL:
+			case QD_REG_ATU_CONTROL:
+			case QD_REG_ATU_OPERATION:
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					break;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					break;
+			case QD_PHY_INT_ENABLE_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+					qdSimRegs[portNumber][miiReg] = 0;
+					qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+					break;
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					*value = (unsigned int) qdSimRegs[0][miiReg];
+					break;
+		}
+	}
+
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimRead_6021(unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	*value = (unsigned int) qdSimRegs[portNumber][miiReg];
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					qdSimRegs[portNumber][miiReg] &= ~0x7F;
+					if(qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG])
+						qdSimRegs[portNumber][miiReg] |= 0x2;
+
+					break;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+			case QD_REG_VTU_OPERATION:
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+			case QD_REG_GLOBAL_CONTROL:
+			case QD_REG_ATU_CONTROL:
+			case QD_REG_ATU_OPERATION:
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+			case QD_REG_STATS_OPERATION:
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					break;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+			case QD_REG_Q_COUNTER:
+					break;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					break;
+			case QD_PHY_INT_ENABLE_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+					qdSimRegs[portNumber][miiReg] = 0;
+					qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+					break;
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					*value = (unsigned int) qdSimRegs[0][miiReg];
+					break;
+		}
+	}
+
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimRead_6063(unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	*value = (unsigned int) qdSimRegs[portNumber][miiReg];
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					qdSimRegs[portNumber][miiReg] &= ~0x7F;
+					if(qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG])
+						qdSimRegs[portNumber][miiReg] |= 0x2;
+
+					break;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+			case QD_REG_VTU_OPERATION:
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+			case QD_REG_GLOBAL_CONTROL:
+			case QD_REG_ATU_CONTROL:
+			case QD_REG_ATU_OPERATION:
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+			case QD_REG_STATS_OPERATION:
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					break;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+			case QD_REG_Q_COUNTER:
+					break;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					break;
+			case QD_PHY_INT_ENABLE_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+					qdSimRegs[portNumber][miiReg] = 0;
+					qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+					break;
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					*value = (unsigned int) qdSimRegs[0][miiReg];
+					break;
+		}
+	}
+
+	return GT_TRUE;
+}
+
+
+GT_BOOL qdSimRead_6083(unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	*value = (unsigned int) qdSimRegs[portNumber][miiReg];
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					qdSimRegs[portNumber][miiReg] &= ~0x7F;
+					if(qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG])
+						qdSimRegs[portNumber][miiReg] |= 0x2;
+
+					break;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+			case QD_REG_VTU_OPERATION:
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+			case QD_REG_GLOBAL_CONTROL:
+			case QD_REG_ATU_CONTROL:
+			case QD_REG_ATU_OPERATION:
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+			case QD_REG_STATS_OPERATION:
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					break;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+			case QD_REG_Q_COUNTER:
+					break;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					break;
+			case QD_PHY_INT_ENABLE_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+					qdSimRegs[portNumber][miiReg] = 0;
+					qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+					break;
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					*value = (unsigned int) qdSimRegs[0][miiReg];
+					break;
+		}
+	}
+
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimRead (GT_QD_DEV *dev,unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	if (portNumber >= MAX_SMI_ADDRESS)
+		portNumber -= MAX_SMI_ADDRESS;
+
+	if ((portNumber >= MAX_SMI_ADDRESS) || (miiReg >= MAX_REG_ADDRESS))
+		return GT_FALSE;
+
+	switch(qdSimDev.qdSimDevId)
+	{
+		case GT_88E6051:
+		case GT_88E6052:
+			return qdSimRead_6052(portNumber, miiReg, value);
+		case GT_88E6021:
+			return qdSimRead_6021(portNumber, miiReg, value);
+		case GT_88E6063:
+		case GT_FF_HG:
+		case GT_FF_EG:
+		case GT_FH_VPN:
+			return qdSimRead_6063(portNumber, miiReg, value);
+		case GT_88E6083:
+			return qdSimRead_6083(portNumber, miiReg, value);
+		default:
+			break;
+	}
+
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimWrite_6052 (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_BOOL status;
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					/* readonly register */
+					return GT_FALSE;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+					break;
+			case QD_REG_GLOBAL_CONTROL:
+					if(value & 0x200)
+					{
+						/* Reload EEPROM values */
+						qdSimRegsInit();
+						qdSimRegs[portNumber][QD_REG_GLOBAL_STATUS] |= 0x1;
+						return GT_TRUE;
+					}
+					break;
+			case QD_REG_ATU_CONTROL:
+					value &= ~0x8000;
+					break;
+			case QD_REG_ATU_OPERATION:
+					status = qdSimATUOperation(value);
+					return status;
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+					break;
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					/* readonly registers */
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					return qdSimPhyControl(portNumber,miiReg,value);
+			case QD_PHY_INT_ENABLE_REG:
+			case QD_PHY_AUTONEGO_AD_REG:
+			case QD_PHY_NEXTPAGE_TX_REG:
+			case QD_PHY_SPEC_CONTROL_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else
+		return GT_FALSE;
+
+	qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimWrite_6021 (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_BOOL status;
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					/* readonly register */
+					return GT_FALSE;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+					break;
+			case QD_REG_VTU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= (value & 0xF);
+					status = qdSimVTUOperation(value);
+					return status;
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+					break;
+			case QD_REG_GLOBAL_CONTROL:
+					if(value & 0x200)
+					{
+						/* Reload EEPROM values */
+						qdSimRegsInit();
+						qdSimRegs[portNumber][QD_REG_GLOBAL_STATUS] |= 0x1;
+						return GT_TRUE;
+					}
+					break;
+			case QD_REG_ATU_CONTROL:
+					value &= ~0x8000;
+					break;
+			case QD_REG_ATU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] |= (value & 0xF);
+					status = qdSimATUOperation(value);
+					return status;
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+			case QD_REG_STATS_OPERATION:
+					status = qdSimStatsOperation(value);
+					return status;
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+					if(portNumber > 9)
+					{
+						qdSimRegs[portNumber][miiReg] &= ~QD_PORT_STATUS_DUPLEX;
+						qdSimRegs[portNumber][miiReg] |= (value & QD_PORT_STATUS_DUPLEX);
+						return GT_TRUE;
+					}
+			case QD_REG_SWITCH_ID:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+					break;
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_Q_COUNTER:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					return qdSimPhyControl(portNumber,miiReg,value);
+			case QD_PHY_INT_ENABLE_REG:
+			case QD_PHY_AUTONEGO_AD_REG:
+			case QD_PHY_NEXTPAGE_TX_REG:
+			case QD_PHY_SPEC_CONTROL_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else
+		return GT_FALSE;
+
+	qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimWrite_6063 (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_BOOL status;
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					/* readonly register */
+					return GT_FALSE;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+					break;
+			case QD_REG_VTU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= (value & 0xF);
+					status = qdSimVTUOperation(value);
+					return status;
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+					break;
+			case QD_REG_GLOBAL_CONTROL:
+					if(value & 0x200)
+					{
+						/* Reload EEPROM values */
+						qdSimRegsInit();
+						qdSimRegs[portNumber][QD_REG_GLOBAL_STATUS] |= 0x1;
+						return GT_TRUE;
+					}
+					break;
+			case QD_REG_ATU_CONTROL:
+					value &= ~0x8000;
+					break;
+			case QD_REG_ATU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] |= (value & 0xF);
+					status = qdSimATUOperation(value);
+					return status;
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+			case QD_REG_STATS_OPERATION:
+					status = qdSimStatsOperation(value);
+					return status;
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+					if(portNumber > 12)
+					{
+						qdSimRegs[portNumber][miiReg] &= ~QD_PORT_STATUS_DUPLEX;
+						qdSimRegs[portNumber][miiReg] |= (value & QD_PORT_STATUS_DUPLEX);
+						return GT_TRUE;
+					}
+			case QD_REG_SWITCH_ID:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+					break;
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_Q_COUNTER:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					return qdSimPhyControl(portNumber,miiReg,value);
+			case QD_PHY_INT_ENABLE_REG:
+			case QD_PHY_AUTONEGO_AD_REG:
+			case QD_PHY_NEXTPAGE_TX_REG:
+			case QD_PHY_SPEC_CONTROL_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else
+		return GT_FALSE;
+
+	qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimWrite_6083 (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_BOOL status;
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					/* readonly register */
+					return GT_FALSE;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+					break;
+			case QD_REG_VTU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= (value & 0xF);
+					status = qdSimVTUOperation(value);
+					return status;
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+			case QD_REG_VTU_DATA3_REG:
+					break;
+			case QD_REG_GLOBAL_CONTROL:
+					if(value & 0x200)
+					{
+						/* Reload EEPROM values */
+						qdSimRegsInit();
+						qdSimRegs[portNumber][QD_REG_GLOBAL_STATUS] |= 0x1;
+						return GT_TRUE;
+					}
+					break;
+			case QD_REG_ATU_CONTROL:
+					value &= ~0x8000;
+					break;
+			case QD_REG_ATU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] |= (value & 0xF);
+					status = qdSimATUOperation(value);
+					return status;
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+			case QD_REG_STATS_OPERATION:
+					status = qdSimStatsOperation(value);
+					return status;
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+					if(portNumber > 12)
+					{
+						qdSimRegs[portNumber][miiReg] &= ~QD_PORT_STATUS_DUPLEX;
+						qdSimRegs[portNumber][miiReg] |= (value & QD_PORT_STATUS_DUPLEX);
+						return GT_TRUE;
+					}
+			case QD_REG_SWITCH_ID:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+					break;
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_Q_COUNTER:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					return qdSimPhyControl(portNumber,miiReg,value);
+			case QD_PHY_INT_ENABLE_REG:
+			case QD_PHY_AUTONEGO_AD_REG:
+			case QD_PHY_NEXTPAGE_TX_REG:
+			case QD_PHY_SPEC_CONTROL_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else
+		return GT_FALSE;
+
+	qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+	return GT_TRUE;
+}
+
+
+GT_BOOL qdSimWrite (GT_QD_DEV *dev,unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	if (portNumber >= MAX_SMI_ADDRESS)
+		portNumber -= MAX_SMI_ADDRESS;
+
+	if ((portNumber >= MAX_SMI_ADDRESS) || (miiReg >= MAX_REG_ADDRESS))
+		return GT_FALSE;
+
+	switch(qdSimDev.qdSimDevId)
+	{
+		case GT_88E6051:
+		case GT_88E6052:
+			return qdSimWrite_6052(portNumber, miiReg, value);
+		case GT_88E6021:
+			return qdSimWrite_6021(portNumber, miiReg, value);
+		case GT_88E6063:
+		case GT_FF_HG:
+		case GT_FF_EG:
+		case GT_FH_VPN:
+			return qdSimWrite_6063(portNumber, miiReg, value);
+		case GT_88E6083:
+			return qdSimWrite_6083(portNumber, miiReg, value);
+
+		default:
+			break;
+	}
+
+	return GT_TRUE;
+}
+
+GT_STATUS qdSimSetPhyInt(unsigned int portNumber, unsigned short u16Data)
+{
+	if(!qdSimDev.qdSimUsed)
+		return GT_FAIL;
+
+	qdSimRegs[portNumber][QD_PHY_INT_STATUS_REG] = u16Data;
+	if(u16Data)
+		qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] |= (1<<portNumber);
+	else
+		qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+	
+	qdSimRegs[MAX_SMI_ADDRESS-1][QD_REG_GLOBAL_STATUS] |= 0x2;
+	return GT_OK;
+}
+
+GT_STATUS qdSimSetGlobalInt(unsigned short u16Data)
+{
+	if(!qdSimDev.qdSimUsed)
+		return GT_FAIL;
+
+	qdSimRegs[MAX_SMI_ADDRESS-1][QD_REG_GLOBAL_STATUS] |= (u16Data & 0xF);
+	return GT_OK;
+}
+
+
+void qdSimInit(GT_DEVICE devId, int baseAddr)
+{
+	qdSimDev.qdSimUsed = 1;
+
+	qdSimDev.qdSimDevId = devId;
+	qdSimDev.vtuSize = 0;
+
+	qdSimDev.qdSimPhyBase = baseAddr;
+	qdSimDev.qdSimPortBase = baseAddr + 0x8;
+	qdSimDev.qdSimGlobalRegBase = baseAddr + 0xF;
+
+	switch(devId)
+	{
+		case GT_88E6021:
+			qdSimDev.vtuSize = 16;
+			qdSimDev.qdSimNumOfPhys = 2;
+			qdSimDev.qdSimNumOfPorts = 3;
+			break;
+		case GT_88E6051:
+			qdSimDev.qdSimNumOfPhys = 5;
+			qdSimDev.qdSimNumOfPorts = 6;
+			break;
+		case GT_88E6063:
+		case GT_FH_VPN:
+			qdSimDev.vtuSize = 64;
+		case GT_88E6052:
+		case GT_FF_HG:
+		case GT_FF_EG:
+			qdSimDev.qdSimNumOfPhys = 5;
+			qdSimDev.qdSimNumOfPorts = 7;
+			break;
+		case GT_88E6083:
+			qdSimDev.vtuSize = 64;
+			qdSimDev.qdSimNumOfPhys = 8;
+			qdSimDev.qdSimNumOfPorts = 10;
+			qdSimDev.qdSimPhyBase = 0;
+			qdSimDev.qdSimPortBase = 0x10;
+			qdSimDev.qdSimGlobalRegBase = 0x1b;
+			break;
+		default:
+			qdSimDev.vtuSize = 64;
+			qdSimDev.qdSimDevId = GT_88E6063;
+			qdSimDev.qdSimNumOfPhys = 5;
+			qdSimDev.qdSimNumOfPorts = 7;
+			break;
+	}
+
+	qdSimATUInit();
+	qdSimVTUInit();
+	qdSimRegsInit();
+
+	return;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdSimRegs.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdSimRegs.h
new file mode 100755
index 0000000..7976f8b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/qdSimRegs.h
@@ -0,0 +1,131 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtSimRegs.h
+*
+* DESCRIPTION:
+*       This file includes the declaration of the struct to hold the addresses
+*       of switch (global & per-port).
+*
+* DEPENDENCIES:
+*       QuarterDeck register MAP.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __qdSimRegsh
+#define __qdSimRegsh
+
+/* QuarterDeck Per Port Registers */
+#define QD_REG_PORT_STATUS		0x0
+#define QD_REG_SWITCH_ID		0x3
+#define QD_REG_PORT_CONTROL		0x4
+#define QD_REG_PORT_VLAN_MAP	0x6
+#define QD_REG_PVID				0x7
+#define QD_REG_RATE_CTRL		0xA
+#define QD_REG_PAV				0xB
+#define QD_REG_RXCOUNTER		0x10
+#define QD_REG_TXCOUNTER		0x11
+#define QD_REG_Q_COUNTER		0x1B
+
+/* QuarterDeck Global Registers */
+#define QD_REG_GLOBAL_STATUS	0x0
+#define QD_REG_MACADDR_01		0x1
+#define QD_REG_MACADDR_23		0x2
+#define QD_REG_MACADDR_45		0x3
+#define QD_REG_GLOBAL_CONTROL	0x4
+
+/* the following VTU entries are added for Fullsail and Clippership */
+#define QD_REG_VTU_OPERATION		0x5
+#define QD_REG_VTU_VID_REG		0x6
+#define QD_REG_VTU_DATA1_REG		0x7
+#define QD_REG_VTU_DATA2_REG		0x8
+#define QD_REG_VTU_DATA3_REG		0x9
+#define QD_REG_STATS_OPERATION		0x1D
+#define QD_REG_STATS_COUNTER3_2		0x1E
+#define QD_REG_STATS_COUNTER1_0		0x1F
+ 
+#define QD_REG_ATU_CONTROL		0xA
+#define QD_REG_ATU_OPERATION	0xB
+#define QD_REG_ATU_DATA_REG		0xC
+#define QD_REG_ATU_MAC_BASE		0xD
+#define QD_REG_ATU_MAC_01		0xD
+#define QD_REG_ATU_MAC_23		0xE
+#define QD_REG_ATU_MAC_45		0xF
+#define QD_REG_IP_PRI_BASE		0x10
+#define QD_REG_IP_PRI_REG0		0x10
+#define QD_REG_IP_PRI_REG1		0x11
+#define QD_REG_IP_PRI_REG2		0x12
+#define QD_REG_IP_PRI_REG3		0x13
+#define QD_REG_IP_PRI_REG4		0x14
+#define QD_REG_IP_PRI_REG5		0x15
+#define QD_REG_IP_PRI_REG6		0x16
+#define QD_REG_IP_PRI_REG7		0x17
+#define QD_REG_IEEE_PRI			0x18
+
+/* Definition for QD_REG_PORT_STATUS */
+#define QD_PORT_STATUS_DUPLEX	0x200
+
+/* Definitions for MIB Counter */
+#define GT_STATS_NO_OP			0x0
+#define GT_STATS_FLUSH_ALL		0x1
+#define GT_STATS_FLUSH_PORT		0x2
+#define GT_STATS_READ_COUNTER		0x4
+#define GT_STATS_CAPTURE_PORT		0x5
+
+#define QD_PHY_CONTROL_REG				0
+#define QD_PHY_AUTONEGO_AD_REG			4
+#define QD_PHY_NEXTPAGE_TX_REG			7
+#define QD_PHY_SPEC_CONTROL_REG			16
+#define QD_PHY_INT_ENABLE_REG			18
+#define QD_PHY_INT_STATUS_REG			19
+#define QD_PHY_INT_PORT_SUMMARY_REG		20
+
+/* Bit Definition for QD_PHY_CONTROL_REG */
+#define QD_PHY_RESET			0x8000
+#define QD_PHY_LOOPBACK			0x4000
+#define QD_PHY_SPEED			0x2000
+#define QD_PHY_AUTONEGO			0x1000
+#define QD_PHY_POWER			0x800
+#define QD_PHY_ISOLATE			0x400
+#define QD_PHY_RESTART_AUTONEGO		0x200
+#define QD_PHY_DUPLEX			0x100
+
+#define QD_PHY_POWER_BIT				11
+#define QD_PHY_RESTART_AUTONEGO_BIT		9
+
+/* Bit Definition for QD_PHY_AUTONEGO_AD_REG */
+#define QD_PHY_NEXTPAGE			0x8000
+#define QD_PHY_REMOTEFAULT		0x4000
+#define QD_PHY_PAUSE			0x400
+#define QD_PHY_100_FULL			0x100
+#define QD_PHY_100_HALF			0x80
+#define QD_PHY_10_FULL			0x40
+#define QD_PHY_10_HALF			0x20
+
+#define QD_PHY_MODE_AUTO_AUTO	(QD_PHY_100_FULL | QD_PHY_100_HALF | QD_PHY_10_FULL | QD_PHY_10_HALF)
+#define QD_PHY_MODE_100_AUTO	(QD_PHY_100_FULL | QD_PHY_100_HALF)
+#define QD_PHY_MODE_10_AUTO		(QD_PHY_10_FULL | QD_PHY_10_HALF)
+#define QD_PHY_MODE_AUTO_FULL	(QD_PHY_100_FULL | QD_PHY_10_FULL)
+#define QD_PHY_MODE_AUTO_HALF	(QD_PHY_100_HALF | QD_PHY_10_HALF)
+
+#define QD_PHY_MODE_100_FULL	QD_PHY_100_FULL
+#define QD_PHY_MODE_100_HALF	QD_PHY_100_HALF
+#define QD_PHY_MODE_10_FULL		QD_PHY_10_FULL	
+#define QD_PHY_MODE_10_HALF		QD_PHY_10_HALF	
+
+/* Bit definition for QD_PHY_INT_ENABLE_REG */
+#define QD_PHY_INT_SPEED_CHANGED		0x4000
+#define QD_PHY_INT_DUPLEX_CHANGED		0x2000
+#define QD_PHY_INT_PAGE_RECEIVED		0x1000
+#define QD_PHY_INT_AUTO_NEG_COMPLETED		0x800
+#define QD_PHY_INT_LINK_STATUS_CHANGED		0x400
+#define QD_PHY_INT_SYMBOL_ERROR			0x200
+#define QD_PHY_INT_FALSE_CARRIER		0x100
+#define QD_PHY_INT_FIFO_FLOW			0x80
+#define QD_PHY_INT_CROSSOVER_CHANGED		0x40
+#define QD_PHY_INT_POLARITY_CHANGED		0x2
+#define QD_PHY_INT_JABBER			0x1
+
+#endif /* __qdSimRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/sampleTest.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/sampleTest.c
new file mode 100755
index 0000000..58f7848
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/sampleTest.c
@@ -0,0 +1,447 @@
+#include <Copyright.h>
+/********************************************************************************
+* sample.c
+*
+* DESCRIPTION:
+*		This is a sample program shows how to use DSDT APIs.
+*		
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*
+* COMMENTS:
+*******************************************************************************/
+
+#include "msSample.h"
+
+#define N_OF_QD_DEVICES	2
+extern GT_QD_DEV       *qdMultiDev[N_OF_QD_DEVICES];
+
+GT_STATUS qdMultiDevStart();
+GT_STATUS sampleIsolatedCPUPort(GT_QD_DEV *dev, GT_U8* macAddr);
+GT_STATUS setTagMode(int vid, char* tag);
+GT_STATUS crossChipTrunkSetup();
+
+
+GT_STATUS enableTag()
+{
+	char tag[4] = {0xc0,0,0,0x1};
+	setTagMode(2,tag);
+	return GT_OK;
+}
+
+
+GT_STATUS sampleTest()
+{
+	GT_U8 macAddr[6] = {0x0,0x23,0x45,0x67,0x89,0xab};
+	qdMultiDevStart();
+	enableTag();
+	sampleIsolatedCPUPort(qdMultiDev[0],macAddr);
+	crossChipTrunkSetup();
+	return GT_OK;
+}
+
+/*
+	0) Remove CPU port from VLAN Member Table.
+	   (this sample deals with Port Based Vlan only.)
+	1) Mirror ARPs to the CPU with To_CPU Marvell Tag
+	2) Convert unicast frames directed to the CPU into To_CPU Marvell Tag
+	Assumption : Device ID, Cascading Port, CPU Port, and Interswitch Port are
+		already set properly. For more information, please refer to the 
+		sample/MultiDevice/msApiInit.c
+*/
+
+GT_STATUS sampleIsolatedCPUPort(GT_QD_DEV *dev, GT_U8* macAddr)
+{
+	GT_STATUS status;
+	int i;
+	GT_LPORT memPorts[16], cpuPort;
+	GT_U8 memPortsLen, index;
+    GT_ATU_ENTRY macEntry;
+
+	cpuPort = (GT_LPORT)dev->cpuPortNum;
+
+	/*
+	 *	Remove CPU port from VLAN Member Table.
+	*/ 
+	for(i=0; i<dev->numOfPorts; i++)
+	{
+		if((status = gvlnGetPortVlanPorts(dev,(GT_LPORT)i,memPorts,&memPortsLen)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnGetPortVlanPorts return Failed\n"));
+			return status;
+		}
+
+		for(index=0; index<memPortsLen; index++)
+		{
+			if (memPorts[index] == cpuPort)
+				break;
+		}
+
+		if(index != memPortsLen)
+		{
+			/* CPU Port is the member of the port vlan */
+			if((memPortsLen-1) != index)
+			{
+				memPorts[index] = memPorts[memPortsLen-1];
+			}
+			memPortsLen--;
+
+			if((status = gvlnSetPortVlanPorts(dev,(GT_LPORT)i,memPorts,memPortsLen)) != GT_OK)
+			{
+				MSG_PRINT(("gvlnSetPortVlanPorts return Failed\n"));
+				return status;
+			}
+		}
+	}
+
+	/*
+	 *	Mirror ARPs to the CPU with To_CPU Marvell Tag.
+	*/
+	if((status = gsysSetARPDest(dev,cpuPort)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSetARPDest return Failed\n"));
+		return status;
+	}
+
+	/*
+	 *	Convert unicast frames directed to the CPU into To_CPU Marvell Tag.
+	 *  This sample assumes that DBNum is not used. If DBNum is used,
+	 *  the macEntry has to be added for each DBNum used.
+	*/
+	memset(&macEntry,0,sizeof(GT_ATU_ENTRY));
+	memcpy(macEntry.macAddr.arEther,macAddr,6);
+	macEntry.portVec = 1 << dev->cpuPortNum;
+	macEntry.prio = 0;			/* Priority (2bits). When these bits are used they override
+								any other priority determined by the frame's data */
+	macEntry.entryState.ucEntryState = GT_UC_TO_CPU_STATIC;
+	macEntry.DBNum = 0;
+	macEntry.trunkMember = GT_FALSE;
+
+	if((status = gfdbAddMacEntry(dev,&macEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSetARPDest return Failed\n"));
+		return status;
+	}
+
+	
+	return GT_OK;
+}
+
+
+/*
+	Assumption 1: Device ID, Cascading Port, CPU Port, and Interswitch Port are
+		already set properly. For more information, please refer to the 
+		sample/MultiDevice/msApiInit.c
+
+	Assumption 2: Port 0,1,2 of Device 0 and Port 0 of Device 1 are member of a 
+		trunk with Trunk ID 1.
+*/
+
+GT_STATUS sampleFixedCrossChipTrunk(GT_QD_DEV *dev[])
+{
+	GT_STATUS status;
+	int i;
+	GT_U32 mask, trunkBit, trunkId;
+
+	/*
+	 *	Enable Trunk for each member of the Trunk and set the Trunk ID (1).
+	*/ 
+
+	trunkId = 1;
+
+	if((dev[0] == NULL) || (!dev[0]->devEnabled))
+	{
+		printf("Device 0 is not initialized\n");
+		return GT_FAIL;
+	}
+	if((dev[1] == NULL) || (!dev[1]->devEnabled))
+	{
+		printf("Device 1 is not initialized\n");
+		return GT_FAIL;
+	}
+
+	/* setup for Device 0 port 0 */
+	if((status = gprtSetTrunkPort(dev[0],0,GT_TRUE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+		return status;
+	}
+
+	/* setup for Device 0 port 1 */
+	if((status = gprtSetTrunkPort(dev[0],1,GT_TRUE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+		return status;
+	}
+
+	/* setup for Device 0 port 2 */
+	if((status = gprtSetTrunkPort(dev[0],2,GT_TRUE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+		return status;
+	}
+
+	/* setup for Device 1 port 0 */
+	if((status = gprtSetTrunkPort(dev[1],0,GT_TRUE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+		return status;
+	}
+
+
+	/*
+	 *	Set Trunk Route Table for the given Trunk ID.
+	*/ 
+
+	/* setup for Device 0, trunk ID 1 : port 0,1,2, and 9 (cascading port, assumption1) */
+	if((status = gsysSetTrunkRouting(dev[0],trunkId,0x7|0x200)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSetTrunkRouting return Failed\n"));
+		return status;
+	}
+
+	/* setup for Device 1, trunk ID 1 : port 0, and 8 (cascading port, assumption1) */
+	if((status = gsysSetTrunkRouting(dev[1],trunkId,0x1|0x100)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSetTrunkRouting return Failed\n"));
+		return status;
+	}
+
+
+	/*
+	 *	Set Trunk Mask Table for load balancing.
+	*/ 
+
+	/*
+	   Trunk Mask Table for Device 0:
+ 
+						10	9	8	7	6	5	4	3	2	1	0
+	   TrunkMask[0]		1	1	1	1	1	1	1	1	0	0	1
+	   TrunkMask[1]		1	1	1	1	1	1	1	1	0	1	0
+	   TrunkMask[2]		1	1	1	1	1	1	1	1	1	0	0
+	   TrunkMask[3]		1	1	1	1	1	1	1	1	0	0	0
+	   TrunkMask[4]		1	1	1	1	1	1	1	1	0	0	1
+	   TrunkMask[5]		1	1	1	1	1	1	1	1	0	1	0
+	   TrunkMask[6]		1	1	1	1	1	1	1	1	1	0	0
+	   TrunkMask[7]		1	1	1	1	1	1	1	1	0	0	0
+
+
+	   Trunk Mask Table for Device 1:
+ 
+						10	9	8	7	6	5	4	3	2	1	0
+	   TrunkMask[0]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[1]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[2]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[3]		1	1	1	1	1	1	1	1	1	1	1
+	   TrunkMask[4]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[5]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[6]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[7]		1	1	1	1	1	1	1	1	1	1	1
+
+	*/
+
+	/* setup for Device 0 */
+	for(i=0; i<8; i++)
+	{
+		if((i%4) == 3)
+		{
+			trunkBit = 0;
+		}
+		else
+		{
+			trunkBit = 1 << (i%4);
+		}		
+
+		mask = 0x7F8 | trunkBit;
+	
+		if((status = gsysSetTrunkMaskTable(dev[0],i,mask)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkMaskTable return Failed\n"));
+			return status;
+		}
+
+	}
+	
+	/* setup for Device 1 */
+	for(i=0; i<8; i++)
+	{
+		if((i%4) == 3)
+		{
+			trunkBit = 1;
+		}
+		else
+		{
+			trunkBit = 0;
+		}		
+
+		mask = 0x7FE | trunkBit;
+	
+		if((status = gsysSetTrunkMaskTable(dev[1],i,mask)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkMaskTable return Failed\n"));
+			return status;
+		}
+
+	}
+	return GT_OK;
+}
+
+#define MAX_PORT_IN_TRUNK 4
+
+typedef struct _TRUNK_SET {
+	GT_U32	devIndex;
+	GT_U32	port;
+} TRUNK_SET;
+
+typedef struct _TRUNK_MEMBER {
+	GT_U32	trunkId;
+	GT_U32	nTrunkPort;
+	TRUNK_SET trunkSet[MAX_PORT_IN_TRUNK];
+} TRUNK_MEMBER;
+
+GT_STATUS sampleCrossChipTrunk(GT_QD_DEV *dev[], TRUNK_MEMBER* tm);
+
+/*
+	Setup Trunk with the following member ports:
+		Port 0,1,2 of Device 0, and
+		Port 0 of Device 1,
+	where Device 0 is the first Switch Device Structure in qdMultiDev array 
+	and Device 1 is the second Switch Device Structure in qdMultiDev array.
+*/
+GT_STATUS crossChipTrunkSetup()
+{
+	TRUNK_MEMBER tm;
+
+	tm.trunkId = 1;
+	tm.nTrunkPort = 4;
+	tm.trunkSet[0].devIndex = 0;
+	tm.trunkSet[0].port = 0;
+	tm.trunkSet[1].devIndex = 0;
+	tm.trunkSet[1].port = 1;
+	tm.trunkSet[2].devIndex = 0;
+	tm.trunkSet[2].port = 2;
+	tm.trunkSet[3].devIndex = 1;
+	tm.trunkSet[3].port = 0;
+
+	return sampleCrossChipTrunk(qdMultiDev, &tm);
+}
+
+GT_STATUS sampleCrossChipTrunk(GT_QD_DEV *dev[], TRUNK_MEMBER* tm)
+{
+	GT_STATUS status;
+	int i,j,index;
+	GT_U32 mask, trunkId;
+	TRUNK_SET* ts;
+	GT_U32 portVec[N_OF_QD_DEVICES];	
+	GT_U32 casecadeVec = 0xC0;	/* Port 6 and 7. ToDo : get this value from user or device */
+
+	/*
+	 *	Enable Trunk for each member of the Trunk and set the Trunk ID (1).
+	*/ 
+
+	printf("Setting TRUNK\n");
+	printf("Trunk ID : %i\n",(unsigned int)tm->trunkId);
+	printf("N Ports  : %i\n",(unsigned int)tm->nTrunkPort);
+	printf("1st Port  : Dev %i, Port %i\n",
+			(unsigned int)tm->trunkSet[0].devIndex,(unsigned int)tm->trunkSet[0].port);
+	printf("2nd Port  : Dev %i, Port %i\n",
+			(unsigned int)tm->trunkSet[1].devIndex,(unsigned int)tm->trunkSet[1].port);
+	printf("3rd Port  : Dev %i, Port %i\n",
+			(unsigned int)tm->trunkSet[2].devIndex,(unsigned int)tm->trunkSet[2].port);
+	printf("4th Port  : Dev %i, Port %i\n",
+			(unsigned int)tm->trunkSet[3].devIndex,(unsigned int)tm->trunkSet[3].port);
+
+	trunkId = tm->trunkId;
+
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+		portVec[i] = 0;
+
+	printf("Enabling TRUNK for each member port.\n");
+	for(i=0; i<tm->nTrunkPort; i++)
+	{
+		ts = &tm->trunkSet[i];
+
+		if(ts->devIndex >= N_OF_QD_DEVICES)
+		{
+			printf("Device %i is supported. Max Device Number is %i\n",(unsigned int)ts->devIndex,N_OF_QD_DEVICES-1);
+			return GT_FAIL;
+		}
+
+		if((dev[ts->devIndex] == NULL) || (!dev[ts->devIndex]->devEnabled))
+		{
+			printf("Device %i is not initialized\n",(unsigned int)ts->devIndex);
+			return GT_FAIL;
+		}
+
+		/* enabled trunk on the given port */
+		if((status = gprtSetTrunkPort(dev[ts->devIndex],ts->port,GT_TRUE,trunkId)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+			return status;
+		}
+
+		portVec[ts->devIndex] |= (1 << ts->port);
+	}
+
+	/*
+	 *	Set Trunk Route Table for the given Trunk ID.
+	*/ 
+	printf("Setting TRUNK Routing Table\n");
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		if((dev[i] == NULL) || (!dev[i]->devEnabled))
+		{
+			printf("Device %i is not initialized\n",i);
+			break;
+		}
+
+		if((status = gsysSetTrunkRouting(dev[i],trunkId,portVec[i]|casecadeVec)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkRouting return Failed\n"));
+			return status;
+		}
+	}
+
+	/*
+	 *	Set Trunk Mask Table for load balancing.
+	*/ 
+	printf("Setting TRUNK Mask for Load Balancing\n");
+	for(i=0; i<8; i++)
+	{
+		/* choose a port to be used for the given addr combo index */
+		index = i % tm->nTrunkPort;
+		ts = &tm->trunkSet[index];
+		
+		for(j=0; j<N_OF_QD_DEVICES; j++)
+		{
+			if((dev[j] == NULL) || (!dev[j]->devEnabled))
+			{
+				printf("Device %i is not initialized\n",j);
+				continue;
+			}
+
+			if(portVec[j] == 0)
+				continue;
+
+			if((status = gsysGetTrunkMaskTable(dev[j],i,&mask)) != GT_OK)
+			{
+				MSG_PRINT(("gsysGetTrunkMaskTable return Failed\n"));
+				return status;
+			}
+
+			mask &= ~portVec[j];
+
+			if(ts->devIndex == j)
+				mask |= (1 << ts->port);
+			
+			if((status = gsysSetTrunkMaskTable(dev[j],i,mask)) != GT_OK)
+			{
+				MSG_PRINT(("gsysSetTrunkMaskTable return Failed\n"));
+				return status;
+			}
+		}
+	}
+	
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/testApi.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/testApi.c
new file mode 100755
index 0000000..f394007
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/testApi.c
@@ -0,0 +1,8879 @@
+#include <Copyright.h>
+/********************************************************************************
+* testApi.c
+*
+* DESCRIPTION:
+*       API test functions
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+/*
+#define TEST_DEBUG
+*/
+#define MAX_TEST_RUN			16
+
+ATU_ENTRY_INFO *gAtuEntry = NULL;
+int gAgeDelayTime = 0;
+
+GT_U32 testSysCtrl(GT_QD_DEV *dev);
+GT_U32 testPort(GT_QD_DEV *dev);
+GT_U32 testATU(GT_QD_DEV *dev);
+GT_U32 testVlan(GT_QD_DEV *dev);
+GT_U32 testSTP(GT_QD_DEV *dev);
+GT_U32 testPhy(GT_QD_DEV *dev);
+GT_U32 testPortStatus(GT_QD_DEV *dev);
+GT_U32 testQoSRule(GT_QD_DEV *dev);
+GT_U32 testQoSMap(GT_QD_DEV *dev);
+GT_U32 testRMON(GT_QD_DEV *dev);
+GT_U32 testVTU(GT_QD_DEV *dev);
+GT_U32 testSysStatus(GT_QD_DEV *dev);
+GT_U32 testPortRateCtrl(GT_QD_DEV *dev);
+GT_U32 testPortPAV(GT_QD_DEV *dev);
+GT_U32 testInterrupt(GT_QD_DEV *dev);
+GT_U32 testPCSCtrl(GT_QD_DEV *dev);
+GT_U32 testPIRL(GT_QD_DEV *dev);
+
+TEST_STRUCT testStruct[] = 
+	{
+	{"SysCtrl    :", testSysCtrl,    0},
+	{"PortCtrl   :", testPort,       0},
+	{"ATU        :", testATU,        0},
+	{"VLAN       :", testVlan,       0},
+	{"STP        :", testSTP,        0},
+	{"PhyCtrl    :", testPhy,        0},
+	{"Port Status:", testPortStatus, 0},
+	{"QoS Rule   :", testQoSRule,    0},
+	{"QoS Map    :", testQoSMap,     0},
+	{"RMON       :", testRMON,       0},
+	{"VTU        :", testVTU,        0},
+	{"Sys Status :", testSysStatus,  0},
+	{"Port Rate  :", testPortRateCtrl, 0},
+	{"Port PAV   :", testPortPAV,    0},
+	{"PCSCtrl    :", testPCSCtrl,    0},
+	/*Interrupt is tested only on simulator
+	{"Interrupt  :", testInterrupt,  GT_OK},
+	*/
+	{"PIRL       :", testPIRL,    0},
+	{"", NULL,GT_OK}
+	};
+#if 0
+TEST_STRUCT testStructG[] = 
+	{
+	{"SysCtrl(G)    :", testSysCtrlG,    0},
+	{"PortCtrl(G)   :", testPortG,       0},
+	{"ATU(G)        :", testATUG,        0},
+	{"VLAN(G)       :", testVlanG,       0},
+	{"STP(G)        :", testSTPG,        0},
+	{"PhyCtrl(G)    :", testPhyG,        0},
+	{"Port Status(G):", testPortStatusG, 0},
+	{"QoS Rule(G)   :", testQoSRuleG,    0},
+	{"QoS Map(G)    :", testQoSMapG,     0},
+	{"RMON(G)       :", testRMONG,       0},
+	{"VTU(G)        :", testVTUG,        0},
+	{"Sys Status(G) :", testSysStatusG,  0},
+	{"Port Rate(G)  :", testPortRateCtrlG, 0},
+	{"Port PAV(G)   :", testPortPAVG,    0},
+	/*Interrupt is tested only on simulator
+	{"Interrupt  :", testInterrupt,  GT_OK},
+	*/
+	{"", NULL,GT_OK}
+	};
+#endif
+
+void testDisplayStatus(GT_STATUS status)
+{
+	switch(status)
+	{
+		case GT_OK :
+			MSG_PRINT(("Passed.\n"));
+			break;
+		case GT_FAIL :
+			MSG_PRINT(("Failed.\n"));
+			break;
+		case GT_BAD_PARAM :
+			MSG_PRINT(("Bad Parameter.\n"));
+			break;
+		case GT_NOT_SUPPORTED :
+			MSG_PRINT(("Not Supported.\n"));
+			break;
+		case GT_NOT_FOUND :
+			MSG_PRINT(("Not Found.\n"));
+			break;
+		case GT_NO_MORE :
+			MSG_PRINT(("No more Item.\n"));
+			break;
+		case GT_NO_SUCH :
+			MSG_PRINT(("No Such Item.\n"));
+			break;
+		default:
+			MSG_PRINT(("Failed.\n"));
+			break;
+	}
+}
+
+void printATUEntry(GT_ATU_ENTRY *entry)
+{
+	MSG_PRINT(("(%02x-%02x-%02x-%02x-%02x-%02x), DBNum %i, PortVec %#x, Pri %#x, State %#x\n",
+					entry->macAddr.arEther[0],
+					entry->macAddr.arEther[1],
+					entry->macAddr.arEther[2],
+					entry->macAddr.arEther[3],
+					entry->macAddr.arEther[4],
+					entry->macAddr.arEther[5],
+					entry->DBNum,
+					entry->portVec,
+					entry->prio,
+					entry->entryState.mcEntryState));
+}
+
+void dumpMemory(char* startAddr, int length)
+{	int i;
+
+	printf("\n");
+	while(length>16)
+	{
+		for(i=0; i<16; i++)
+			printf("%02x ",(unsigned char)*startAddr++);
+		printf("\n");
+		length -= 16;
+	}
+	for(i=0; i<length; i++)
+		printf("%02x ",(unsigned char)*startAddr++);
+	printf("\n");
+}
+
+GT_STATUS testBoolType(GT_QD_DEV *dev, TEST_API* api)
+{
+	GT_STATUS status;
+	GT_BOOL orgValue, tmpValue;
+	GT_STATUS testResult = GT_OK;
+	
+	/* Get the Original value */
+	if((status=api->getFunc.bool(dev,&orgValue)) != GT_OK)
+	{
+		MSG_PRINT(("Reading Bool Value Failed (%#x).\n", status));
+		return status;
+	}
+
+	/* Set to 1 */
+	if((status=api->setFunc.bool(dev,GT_TRUE)) != GT_OK)
+	{
+		MSG_PRINT(("Writing Bool Value Failed (%#x).\n", status));
+		return status;
+	}
+
+	/* Get the modified value */
+	if((status=api->getFunc.bool(dev,&tmpValue)) != GT_OK)
+	{
+		MSG_PRINT(("Reading Bool Value Failed (%#x).\n", status));
+		return status;
+	}
+
+	if(tmpValue != GT_TRUE)
+	{
+		MSG_PRINT(("Test Value Mismatch (expected GT_TRUE).\n"));
+		testResult = GT_FAIL;
+	}
+
+	/* Set to 0 */
+	if((status=api->setFunc.bool(dev,GT_FALSE)) != GT_OK)
+	{
+		MSG_PRINT(("Writing Bool Value Failed (%#x).\n", status));
+		return status;
+	}
+
+	/* Get the modified value */
+	if((status=api->getFunc.bool(dev,&tmpValue)) != GT_OK)
+	{
+		MSG_PRINT(("Reading Bool Value Failed (%#x).\n", status));
+		return status;
+	}
+
+	if(tmpValue != GT_FALSE)
+	{
+		MSG_PRINT(("Test Value Mismatch (expected GT_FALSE).\n"));
+		testResult = GT_FAIL;
+	}
+
+	/* Set to original value */
+	if((status=api->setFunc.bool(dev,orgValue)) != GT_OK)
+	{
+		MSG_PRINT(("Writing Bool Value Failed (%#x).\n", status));
+		return status;
+	}
+
+	return testResult;		
+}
+
+GT_STATUS testU16Type(GT_QD_DEV *dev, TEST_API* api, int testLimit)
+{
+	GT_STATUS status;
+	GT_U16 orgValue, tmpValue, i;
+	GT_STATUS testResult = GT_OK;
+		
+	/* Get the Original value */
+	if((status=api->getFunc.u16(dev,&orgValue)) != GT_OK)
+	{
+		MSG_PRINT(("Reading U16 Value Failed (%#x).\n", status));
+		return status;
+	}
+
+	/* Set to 0 */
+	for(i=0; i<(GT_U16)testLimit; i++)
+	{
+		if((status=api->setFunc.u16(dev,i)) != GT_OK)
+		{
+			MSG_PRINT(("Writing U16 Value Failed (%#x, value %i).\n", status,i));
+			return status;
+		}
+
+		/* Get the modified value */
+		if((status=api->getFunc.u16(dev,&tmpValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading U16 Value Failed (%#x, value %i).\n", status,i));
+			return status;
+		}
+
+		if(tmpValue != i)
+		{
+			MSG_PRINT(("Test Value Mismatch (write %i, read %i).\n",i,tmpValue));
+			testResult = GT_FAIL;
+		}
+	}
+
+	/* Set to original value */
+	if((status=api->setFunc.u16(dev,orgValue)) != GT_OK)
+	{
+		MSG_PRINT(("Writing U16 Value Failed (%#x, org value %i).\n", status, orgValue));
+		return status;
+	}
+
+	return testResult;		
+}
+
+
+GT_STATUS testU32Type(GT_QD_DEV *dev, TEST_API* api, int testLimit)
+{
+	GT_STATUS status;
+	GT_U32 orgValue, tmpValue, i;
+	GT_STATUS testResult = GT_OK;
+		
+	/* Get the Original value */
+	if((status=api->getFunc.u32(dev,&orgValue)) != GT_OK)
+	{
+		MSG_PRINT(("Reading U32 Value Failed (%#x).\n", status));
+		return status;
+	}
+
+	/* Set to 0 */
+	for(i=0; i<(GT_U32)testLimit; i++)
+	{
+		if((status=api->setFunc.u32(dev,i)) != GT_OK)
+		{
+			MSG_PRINT(("Writing U32 Value Failed (%#x, value %i).\n", status,i));
+			return status;
+		}
+
+		/* Get the modified value */
+		if((status=api->getFunc.u32(dev,&tmpValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading U32 Value Failed (%#x, value %i).\n", status,i));
+			return status;
+		}
+
+		if(tmpValue != i)
+		{
+			MSG_PRINT(("Test Value Mismatch (write %i, read %i).\n",i,tmpValue));
+			testResult = GT_FAIL;
+		}
+	}
+
+	/* Set to original value */
+	if((status=api->setFunc.u32(dev,orgValue)) != GT_OK)
+	{
+		MSG_PRINT(("Writing U32 Value Failed (%#x, org value %i).\n", status, orgValue));
+		return status;
+	}
+
+	return testResult;		
+}
+
+
+GT_STATUS testMacType(GT_QD_DEV *dev, TEST_API* api)
+{
+	GT_STATUS status;
+	GT_ETHERADDR orgMac, tmpMacIn, tmpMacOut;
+	GT_STATUS testResult = GT_OK;
+		
+	/* Get the Discard Excessive state */
+	if((status=api->getFunc.mac(dev,&orgMac)) != GT_OK)
+	{
+		MSG_PRINT(("Reading MAC Address Failed (%#x).\n", status));
+		return status;
+	}
+
+	tmpMacIn.arEther[0] = 0xAA;
+	tmpMacIn.arEther[1] = 0xAA;
+	tmpMacIn.arEther[2] = 0xAA;
+	tmpMacIn.arEther[3] = 0xAA;
+	tmpMacIn.arEther[4] = 0xAA;
+	tmpMacIn.arEther[5] = 0xAA;
+
+	/* Set the Discard Excessive state */
+	if((status=api->setFunc.mac(dev,&tmpMacIn)) != GT_OK)
+	{
+		MSG_PRINT(("Writing MAC Address Failed (%#x).\n", status));
+		return status;
+	}
+
+	/* Get the Discardl Excessive state */
+	if((status=api->getFunc.mac(dev,&tmpMacOut)) != GT_OK)
+	{
+		MSG_PRINT(("Reading MAC Address Failed (%#x).\n", status));
+		return status;
+	}
+
+	if(memcmp(&tmpMacIn,&tmpMacOut,6) != 0)
+	{
+		MSG_PRINT(("Unexpected MAC address(%#x-%#x-%#x-%#x-%#x-%#x)\n",
+					tmpMacOut.arEther[0],
+					tmpMacOut.arEther[1],
+					tmpMacOut.arEther[2],
+					tmpMacOut.arEther[3],
+					tmpMacOut.arEther[4],
+					tmpMacOut.arEther[5]));
+
+		testResult = GT_FAIL;
+	}
+
+	tmpMacIn.arEther[0] = 0x54;
+	tmpMacIn.arEther[1] = 0x55;
+	tmpMacIn.arEther[2] = 0x55;
+	tmpMacIn.arEther[3] = 0x55;
+	tmpMacIn.arEther[4] = 0x55;
+	tmpMacIn.arEther[5] = 0x55;
+
+	/* Set the Discard Excessive state */
+	if((status=api->setFunc.mac(dev,&tmpMacIn)) != GT_OK)
+	{
+		MSG_PRINT(("Writing MAC Address Failed (%#x).\n", status));
+		return status;
+	}
+
+	/* Get the Discardl Excessive state */
+	if((status=api->getFunc.mac(dev,&tmpMacOut)) != GT_OK)
+	{
+		MSG_PRINT(("Reading MAC Address Failed (%#x).\n", status));
+		return status;
+	}
+
+	if(memcmp(&tmpMacIn,&tmpMacOut,6) != 0)
+	{
+		MSG_PRINT(("Unexpected MAC address(%#x-%#x-%#x-%#x-%#x-%#x)\n",
+					tmpMacOut.arEther[0],
+					tmpMacOut.arEther[1],
+					tmpMacOut.arEther[2],
+					tmpMacOut.arEther[3],
+					tmpMacOut.arEther[4],
+					tmpMacOut.arEther[5]));
+
+		testResult = GT_FAIL;
+	}
+
+	tmpMacIn.arEther[0] = 0x00;
+	tmpMacIn.arEther[1] = 0x00;
+	tmpMacIn.arEther[2] = 0x00;
+	tmpMacIn.arEther[3] = 0x00;
+	tmpMacIn.arEther[4] = 0x00;
+	tmpMacIn.arEther[5] = 0x01;
+
+	/* Set the Discard Excessive state */
+	if((status=api->setFunc.mac(dev,&tmpMacIn)) != GT_OK)
+	{
+		MSG_PRINT(("Writing MAC Address Failed (%#x).\n", status));
+		return status;
+	}
+
+	/* Get the Discardl Excessive state */
+	if((status=api->getFunc.mac(dev,&tmpMacOut)) != GT_OK)
+	{
+		MSG_PRINT(("Reading MAC Address Failed (%#x).\n", status));
+		return status;
+	}
+
+	if(memcmp(&tmpMacIn,&tmpMacOut,6) != 0)
+	{
+		MSG_PRINT(("Unexpected MAC address(%#x-%#x-%#x-%#x-%#x-%#x)\n",
+					tmpMacOut.arEther[0],
+					tmpMacOut.arEther[1],
+					tmpMacOut.arEther[2],
+					tmpMacOut.arEther[3],
+					tmpMacOut.arEther[4],
+					tmpMacOut.arEther[5]));
+
+		testResult = GT_FAIL;
+	}
+
+	/* Set the Discard Excessive state with original value */
+	if((status=api->setFunc.mac(dev,&orgMac)) != GT_OK)
+	{
+		MSG_PRINT(("Writing MAC Address Failed (%#x).\n", status));
+		return status;
+	}
+
+	return testResult;		
+}
+
+
+GT_STATUS testPortBoolType(GT_QD_DEV *dev, TEST_API* api)
+{
+	GT_STATUS status;
+	GT_BOOL orgValue, tmpValue;
+	GT_STATUS testResult = GT_OK;
+	GT_LPORT port;
+	int portIndex;
+		
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		/* Get the Original value */
+		if((status=api->getFunc.port_bool(dev,port,&orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading Bool Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		/* Set to 1 */
+		if((status=api->setFunc.port_bool(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("Writing Bool Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		/* Get the modified value */
+		if((status=api->getFunc.port_bool(dev,port,&tmpValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading Bool Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		if(tmpValue != GT_TRUE)
+		{
+			MSG_PRINT(("Test Value Mismatch (expected GT_TRUE).\n"));
+			testResult = GT_FAIL;
+		}
+
+		/* Set to 0 */
+		if((status=api->setFunc.port_bool(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("Writing Bool Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		/* Get the modified value */
+		if((status=api->getFunc.port_bool(dev,port,&tmpValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading Bool Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		if(tmpValue != GT_FALSE)
+		{
+			MSG_PRINT(("Test Value Mismatch (expected GT_FALSE).\n"));
+			testResult = GT_FAIL;
+		}
+
+		/* Set to original value */
+		if((status=api->setFunc.port_bool(dev,port,orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Writing Bool Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		if (testResult != GT_OK)
+			return testResult;
+
+	}
+	return testResult;		
+}
+
+
+GT_STATUS testPortU8Type(GT_QD_DEV *dev, TEST_API* api, int testLimit)
+{
+	GT_STATUS status;
+	GT_U8 orgValue, tmpValue, i;
+	GT_STATUS testResult = GT_OK;
+	GT_LPORT port;
+	int portIndex;
+		
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		/* Get the Original value */
+		if((status=api->getFunc.port_u8(dev,port,&orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading U8 Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		/* Set to 0 */
+		for(i=0; i<(GT_U8)testLimit; i++)
+		{
+			if((status=api->setFunc.port_u8(dev,port,i)) != GT_OK)
+			{
+				MSG_PRINT(("Writing U8 Value Failed (%#x).\n", status));
+				return status;
+			}
+
+			/* Get the modified value */
+			if((status=api->getFunc.port_u8(dev,port,&tmpValue)) != GT_OK)
+			{
+				MSG_PRINT(("Reading U8 Value Failed (%#x).\n", status));
+				return status;
+			}
+
+			if(tmpValue != i)
+			{
+				MSG_PRINT(("U16 Value Mismatch (port %i, write %#x, read %#x).\n", portIndex,i,tmpValue));
+				testResult = GT_FAIL;
+			}
+		}
+
+		/* Set to original value */
+		if((status=api->setFunc.port_u8(dev,port,orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Writing U8 Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		if (testResult != GT_OK)
+			return testResult;
+
+	}
+	return testResult;		
+}
+
+GT_STATUS testPortU16Type(GT_QD_DEV *dev, TEST_API* api, int testLimit)
+{
+	GT_STATUS status;
+	GT_U16 orgValue, tmpValue, i;
+	GT_STATUS testResult = GT_OK;
+	GT_LPORT port;
+	int portIndex;
+		
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		/* Get the Original value */
+		if((status=api->getFunc.port_u16(dev,port,&orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading U16 Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		/* Set to 0 */
+		for(i=0; i<(GT_U16)testLimit; i++)
+		{
+			if((status=api->setFunc.port_u16(dev,port,i)) != GT_OK)
+			{
+				MSG_PRINT(("Writing U16 Value Failed (%#x).\n", status));
+				return status;
+			}
+
+			/* Get the modified value */
+			if((status=api->getFunc.port_u16(dev,port,&tmpValue)) != GT_OK)
+			{
+				MSG_PRINT(("Reading U16 Value Failed (%#x).\n", status));
+				return status;
+			}
+
+			if(tmpValue != i)
+			{
+				MSG_PRINT(("U16 Value Mismatch (port %i, write %#x, read %#x).\n", portIndex,i,tmpValue));
+				testResult = GT_FAIL;
+				return GT_FAIL; /* MJ Temp */
+			}
+		}
+
+		/* Set to original value */
+		if((status=api->setFunc.port_u16(dev,port,orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Writing U16 Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		if (testResult != GT_OK)
+			return testResult;
+
+	}
+	return testResult;		
+}
+
+GT_STATUS testPortU32Type(GT_QD_DEV *dev, TEST_API* api, int testLimit)
+{
+	GT_STATUS status;
+	GT_U32 orgValue, tmpValue, i;
+	GT_STATUS testResult = GT_OK;
+	GT_LPORT port;
+	int portIndex;
+		
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+		
+		/* Get the Original value */
+		if((status=api->getFunc.port_u32(dev,port,&orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading U32 Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		/* Set to 0 */
+		for(i=0; i<(GT_U32)testLimit; i++)
+		{
+			if((status=api->setFunc.port_u32(dev,port,i)) != GT_OK)
+			{
+				MSG_PRINT(("Writing U32 Value Failed (port%i,data%i,%#x).\n", port,i,status));
+				return status;
+			}
+
+			/* Get the modified value */
+			if((status=api->getFunc.port_u32(dev,port,&tmpValue)) != GT_OK)
+			{
+				MSG_PRINT(("Reading U32 Value Failed (%#x).\n", status));
+				return status;
+			}
+
+			if(tmpValue != i)
+			{
+				MSG_PRINT(("U16 Value Mismatch (port %i, write %#x, read %#x).\n", port,i,tmpValue));
+				testResult = GT_FAIL;
+			}
+		}
+
+		/* Set to original value */
+		if((status=api->setFunc.port_u32(dev,port,orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Writing Org Value Failed (value %i,%#x).\n", orgValue,status));
+			return status;
+		}
+
+		if (testResult != GT_OK)
+			return testResult;
+
+	}
+	return testResult;		
+}
+
+GT_STATUS testU32U32Type(GT_QD_DEV *dev, TEST_API* api, int indexLimit, int testLimit)
+{
+	GT_STATUS status;
+	GT_U32 orgValue, tmpValue, i;
+	GT_STATUS testResult = GT_OK;
+	int index;
+
+	for(index=0; index<indexLimit; index++)
+	{
+		/* Get the Original value */
+		if((status=api->getFunc.port_u32(dev,index,&orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Reading U32 Org Value Failed (%#x).\n", status));
+			return status;
+		}
+
+		/* Set to 0 */
+		for(i=0; i<(GT_U32)testLimit; i++)
+		{
+			if((status=api->setFunc.port_u32(dev,index,i)) != GT_OK)
+			{
+				MSG_PRINT(("Writing U32 Value Failed (%#x) index:%i,value:%i.\n", status,index,i));
+				return status;
+			}
+
+			/* Get the modified value */
+			if((status=api->getFunc.port_u32(dev,index,&tmpValue)) != GT_OK)
+			{
+				MSG_PRINT(("Reading U32 Value Failed (%#x) index:%i,value:%i.\n", status,index,i));
+				return status;
+			}
+
+			if(tmpValue != i)
+			{
+				MSG_PRINT(("U16 Value Mismatch (index %i, write %#x, read %#x).\n", index,i,tmpValue));
+				testResult = GT_FAIL;
+			}
+		}
+
+		/* Set to original value */
+		if((status=api->setFunc.port_u32(dev,index,orgValue)) != GT_OK)
+		{
+			MSG_PRINT(("Writing U32 Org Value Failed (%#x) index:%i,value:%i.\n", status,index,orgValue));
+			return status;
+		}
+
+		if (testResult != GT_OK)
+			return testResult;
+
+	}
+	return testResult;		
+}
+
+GT_STATUS testTrunkPortSetup(GT_QD_DEV *dev, int portIndex)
+{
+	GT_STATUS status;
+	GT_U32 orgTrunkId, trunkId, tmpId;
+	GT_LPORT port;
+	GT_BOOL orgEn, tmpEn;
+
+	port = (GT_LPORT)portIndex;
+
+	if((status = gprtGetTrunkPort(dev,port,&orgEn,&orgTrunkId)) != GT_OK)
+	{
+		MSG_PRINT(("Getting Org. TrunkPort setup failed (port%i, status:%#x).\n", port,status));
+		return status;		
+	}
+
+	for(trunkId=0; trunkId<16; trunkId++)
+	{
+		if((status = gprtSetTrunkPort(dev,port,GT_TRUE,trunkId)) != GT_OK)
+		{
+			MSG_PRINT(("Setting TrunkPort setup failed (port%i,trunkId:%i,status:%#x).\n", port,trunkId,status));
+			return status;		
+		}
+
+		if((status = gprtGetTrunkPort(dev,port,&tmpEn,&tmpId)) != GT_OK)
+		{
+			MSG_PRINT(("Getting TrunkPort setup failed (port%i, status:%#x).\n", port,status));
+			return status;		
+		}
+
+		if((tmpEn != GT_TRUE) || (tmpId != trunkId))
+		{
+			MSG_PRINT(("TrunkPort Enable failed (ID:%i,%i).\n", trunkId,tmpId));
+			return status;		
+		}
+
+	}
+
+	if((status = gprtSetTrunkPort(dev,port,GT_FALSE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("Setting TrunkPort setup failed (port%i,trunkId:%i,status:%#x).\n", port,trunkId,status));
+		return status;		
+	}
+
+	if((status = gprtGetTrunkPort(dev,port,&tmpEn,&tmpId)) != GT_OK)
+	{
+		MSG_PRINT(("Getting TrunkPort setup failed (port%i, status:%#x).\n", port,status));
+		return status;		
+	}
+
+	if(tmpEn != GT_FALSE)
+	{
+		MSG_PRINT(("TrunkPort Disable failed (En:%i,%i).\n", GT_FALSE,tmpEn));
+		return status;		
+	}
+
+	if((status = gprtSetTrunkPort(dev,port,orgEn,orgTrunkId)) != GT_OK)
+	{
+		MSG_PRINT(("Setting TrunkPort setup failed (port%i,trunkId:%i,status:%#x).\n", port,trunkId,status));
+		return status;		
+	}
+
+	return GT_OK;
+}
+
+GT_U32 testSysCtrlG(GT_QD_DEV *dev )
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	GT_U32 data;
+	TEST_API testAPI;
+
+	/*
+	 *  PPU Setup API
+	 */
+	testAPI.getFunc.bool = gsysGetPPUEn;
+	testAPI.setFunc.bool = gsysSetPPUEn;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("PPU Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Cascade Port Setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetCascadePort;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetCascadePort;
+	if((status = testU32Type(dev,&testAPI,dev->numOfPorts)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Cascade Port Setup API test "));
+	testDisplayStatus(status);
+	/*
+	 *  Device Number Setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetDeviceNumber;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetDeviceNumber;
+	if((status = testU32Type(dev,&testAPI,32)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Device Number Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Core Tag Type setup API
+	 */
+	testAPI.getFunc.u16 = (GT_API_GET_U16)gsysGetCoreTagType;
+	testAPI.setFunc.u16 = (GT_API_SET_U16)gsysSetCoreTagType;
+	if((status = testU16Type(dev,&testAPI,64)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Core Tag Type Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  IngressMonitorDest setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetIngressMonitorDest;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetIngressMonitorDest;
+	if((status = testU32Type(dev,&testAPI,dev->numOfPorts)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("IngressMonitorDest Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  EngressMonitorDest setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetEgressMonitorDest;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetEgressMonitorDest;
+	if((status = testU32Type(dev,&testAPI,dev->numOfPorts)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("EngressMonitorDest Setup API test "));
+	testDisplayStatus(status);
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+			return testResults;
+		default:
+			break;
+	}			
+
+	/*
+	 *  ARPDest setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetARPDest;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetARPDest;
+	if((status = testU32Type(dev,&testAPI,dev->numOfPorts)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("ARPDest Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Rsvd2CpuEnables setup API
+	 */
+	testAPI.getFunc.u16 = (GT_API_GET_U16)gsysGetRsvd2CpuEnables;
+	testAPI.setFunc.u16 = (GT_API_SET_U16)gsysSetRsvd2CpuEnables;
+	if((status = testU16Type(dev,&testAPI,0x8001)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Rsvd2CpuEnables Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Rsvd2Cpu setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetRsvd2Cpu;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetRsvd2Cpu;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Rsvd2Cpu Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  MGMTPri setup API
+	 */
+	testAPI.getFunc.u16 = (GT_API_GET_U16)gsysGetMGMTPri;
+	testAPI.setFunc.u16 = (GT_API_SET_U16)gsysSetMGMTPri;
+	if((status = testU16Type(dev,&testAPI,8)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("MGMTPri Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  UseDoubleTagData setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetUseDoubleTagData;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetUseDoubleTagData;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("UseDoubleTagData Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  PreventLoops setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetPreventLoops;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetPreventLoops;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("PreventLoops Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  FlowControlMessage setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetFlowControlMessage;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetFlowControlMessage;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("FlowControlMessage Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  gsysSetForceFlowControlPri setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetForceFlowControlPri;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetForceFlowControlPri;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("ForceFlowControlPri Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  FcPri setup API
+	 */
+	testAPI.getFunc.u16 = (GT_API_GET_U16)gsysGetFCPri;
+	testAPI.setFunc.u16 = (GT_API_SET_U16)gsysSetFCPri;
+	if((status = testU16Type(dev,&testAPI,8)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("FCPri Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  gsysSetHashTrunk setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetHashTrunk;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetHashTrunk;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("HashTrunk Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  FlowCtrlDelay Setup
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gsysGetFlowCtrlDelay;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gsysSetFlowCtrlDelay;
+	if((status = testU32U32Type(dev,&testAPI,3,0x2000)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("FlowCtrlDelay Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DevRoutingTable Setup
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gsysGetDevRoutingTable;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gsysSetDevRoutingTable;
+	if((status = testU32U32Type(dev,&testAPI,32,dev->numOfPorts)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DevRoutingTable Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  TrunkMaskTable Setup
+	 */
+	switch (dev->deviceId)
+	{
+		case GT_88E6031:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6061:
+		case GT_88E6065:
+				data = 4;
+				break;
+		default:
+				data = 8;
+				break;
+	}
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gsysGetTrunkMaskTable;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gsysSetTrunkMaskTable;
+	if((status = testU32U32Type(dev,&testAPI,data,(1<<(dev->numOfPorts-1)))) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("TrunkMaskTable Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  gsysSetTrunkRouting Setup
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gsysGetTrunkRouting;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gsysSetTrunkRouting;
+	if((status = testU32U32Type(dev,&testAPI,8,(1<<(dev->numOfPorts-1)))) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("TrunkRouting Setup API test "));
+	testDisplayStatus(status);
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6092:
+		case GT_88E6095:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+			if (dev->revision < 2)
+				return testResults;
+			break;
+		case GT_88E6131:
+		case GT_88E6108:
+		default:
+			break;
+	}			
+
+	/*
+	 *  gsysSetRateLimitMode Setup
+	 */
+	testAPI.getFunc.bool = (GT_API_GET_BOOL)gsysGetRateLimitMode;
+	testAPI.setFunc.bool = (GT_API_SET_BOOL)gsysSetRateLimitMode;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Rate Limit Mode Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  gsysSetAgeInt Setup
+	 */
+	testAPI.getFunc.bool = gsysGetAgeInt;
+	testAPI.setFunc.bool = gsysSetAgeInt;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Age Interrupt Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  gsysSetForceSnoopPri setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetForceSnoopPri;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetForceSnoopPri;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("ForceSnoopPri Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Snoop Pri setup API
+	 */
+	testAPI.getFunc.u16 = (GT_API_GET_U16)gsysGetSnoopPri;
+	testAPI.setFunc.u16 = (GT_API_SET_U16)gsysSetSnoopPri;
+	if((status = testU16Type(dev,&testAPI,8)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Snoop Pri Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  gsysSetForceARPPri setup API
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetForceARPPri;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetForceARPPri;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("ForceARPPri Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  ARP Pri setup API
+	 */
+	testAPI.getFunc.u16 = (GT_API_GET_U16)gsysGetARPPri;
+	testAPI.setFunc.u16 = (GT_API_SET_U16)gsysSetARPPri;
+	if((status = testU16Type(dev,&testAPI,8)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("ARP Pri Setup API test "));
+	testDisplayStatus(status);
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6131:
+		case GT_88E6108:
+			return testResults;
+		default:
+			break;
+	}			
+
+	/*
+	 *  Use Port Schedule API
+	 */
+	testAPI.getFunc.bool = gsysGetUsePortSchedule;
+	testAPI.setFunc.bool = gsysSetUsePortSchedule;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Use Port Schedule API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Use Old Header API
+	 */
+	testAPI.getFunc.bool = gsysGetOldHader;
+	testAPI.setFunc.bool = gsysSetOldHader;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Use Old Header API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Recursive Stripping Disable API
+	 */
+	testAPI.getFunc.bool = gsysGetRecursiveStrippingDisable;
+	testAPI.setFunc.bool = gsysSetRecursiveStrippingDisable;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Recursive Stripping Disable API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  CPU Port
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gsysGetCPUPort;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gsysSetCPUPort;
+	if((status = testU32Type(dev,&testAPI,dev->numOfPorts)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("CPU Port API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+}
+
+GT_U32 testSysCtrl(GT_QD_DEV *dev )
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+
+	/* Sw Reset */
+	if((status=gsysSwReset(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSwReset returned Fail (%#x).\n", status));
+		testResults |= 1 << status;
+		return testResults;
+	}
+	testResult = GT_OK;
+
+	/*
+	 *  Testing Discard Excessive State API
+	 */
+	testAPI.getFunc.bool = gsysGetDiscardExcessive;
+	testAPI.setFunc.bool = gsysSetDiscardExcessive;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DiscardExcessive API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Testing Scheduling Mose API
+	 */
+	testAPI.getFunc.bool = gsysGetSchedulingMode;
+	testAPI.setFunc.bool = gsysSetSchedulingMode;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Scheduling Mode API test "));
+	testDisplayStatus(status);
+
+
+	/*
+	 *  Testing Max Frame Size API
+	 */
+	testAPI.getFunc.bool = gsysGetMaxFrameSize;
+	testAPI.setFunc.bool = gsysSetMaxFrameSize;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("MAX Frame Size API test "));
+	testDisplayStatus(status);
+
+
+	/*
+	 *  Testing WatchDog API
+	 */
+	testAPI.getFunc.bool = gsysGetWatchDog;
+	testAPI.setFunc.bool = gsysSetWatchDog;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("WatchDog API test "));
+	testDisplayStatus(status);
+
+
+	/*
+	 *  Testing PerPortDuplexPauseMac API
+	 */
+	testAPI.getFunc.bool = gsysGetPerPortDuplexPauseMac;
+	testAPI.setFunc.bool = gsysSetPerPortDuplexPauseMac;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Per Port Duplex Pause Mac API test "));
+	testDisplayStatus(status);
+
+
+#if 0
+	/*
+	 *  Retransmit Mode API
+	 */
+	testAPI.getFunc.bool = gsysGetRetransmitMode;
+	testAPI.setFunc.bool = gsysSetRetransmitMode;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Retransmit Mode API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Limit Backoff API
+	 */
+	testAPI.getFunc.bool = gsysGetLimitBackoff;
+	testAPI.setFunc.bool = gsysSetLimitBackoff;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Limit Backoff API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Rsv Queue's Request Priority API
+	 */
+	testAPI.getFunc.bool = gsysGetRsvReqPri;
+	testAPI.setFunc.bool = gsysSetRsvReqPri;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Rsv Queue's Request Priority API test "));
+	testDisplayStatus(status);
+#endif
+
+	/*
+	 *  Testing DuplexPauseMac API
+	 */
+	testAPI.getFunc.mac = gsysGetDuplexPauseMac;
+	testAPI.setFunc.mac = gsysSetDuplexPauseMac;
+	if((status = testMacType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Duplex Pause Mac API test "));
+	testDisplayStatus(status);
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+		case GT_88E6031:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6061:
+		case GT_88E6065:
+			testResults |= testSysCtrlG(dev);
+			break;
+		default:
+			break;
+	}
+	
+#if 0
+	/* Reload EEPROM value */
+	if((status=gsysReLoad(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gsysReLoad returned Fail (%#x).\n", status));
+		testResults |= 1 << status;
+		return testResults;
+	}
+#endif
+
+	return testResults;
+}
+
+GT_U32 testPCSCtrl(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+
+	testResult = GT_OK;
+
+	/*
+	 *  Inband Auto-Nego Bypass Setup API
+	 */
+	testAPI.getFunc.port_bool = gpcsGetAnBypassMode;
+	testAPI.setFunc.port_bool = gpcsSetAnBypassMode;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Inband Auto-Nego Bypass Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  PCS Inband Auto-Nego Setup API
+	 */
+	testAPI.getFunc.port_bool = gpcsGetPCSAnEn;
+	testAPI.setFunc.port_bool = gpcsSetPCSAnEn;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("PCS Inband Auto-Nego Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Link Value Setup
+	 */
+	testAPI.getFunc.port_bool = gpcsGetLinkValue;
+	testAPI.setFunc.port_bool = gpcsSetLinkValue;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Link Value Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Forced Link Setup
+	 */
+	testAPI.getFunc.port_bool = gpcsGetForcedLink;
+	testAPI.setFunc.port_bool = gpcsSetForcedLink;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Forced Link Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Duplex Value Setup
+	 */
+	testAPI.getFunc.port_bool = gpcsGetDpxValue;
+	testAPI.setFunc.port_bool = gpcsSetDpxValue;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Duplex Value Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Forced Duplex Setup
+	 */
+	testAPI.getFunc.port_bool = gpcsGetForcedDpx;
+	testAPI.setFunc.port_bool = gpcsSetForcedDpx;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Forced Duplex Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Forced Speed Setup
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gpcsGetForceSpeed;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gpcsSetForceSpeed;
+	if((status = testPortU32Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Forced Speed Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Flow control Value Setup
+	 */
+	testAPI.getFunc.port_bool = gpcsGetFCValue;
+	testAPI.setFunc.port_bool = gpcsSetFCValue;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Flow Control Value Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Forced Flow control Setup
+	 */
+	testAPI.getFunc.port_bool = gpcsGetForcedFC;
+	testAPI.setFunc.port_bool = gpcsSetForcedFC;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Forced Flow Control Setup API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+}
+
+GT_U32 testPortEnhancedFE(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+	int portIndex;
+
+	testResult = GT_OK;
+
+	/*
+	 *  Drop on Lock
+	 */
+	testAPI.getFunc.port_bool = gprtGetDropOnLock;
+	testAPI.setFunc.port_bool = gprtSetDropOnLock;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Drop on Lock API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Double Tag
+	 */
+	testAPI.getFunc.port_bool = gprtGetDoubleTag;
+	testAPI.setFunc.port_bool = gprtSetDoubleTag;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Double Tag API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Interswitch Port
+	 */
+	testAPI.getFunc.port_bool = gprtGetInterswitchPort;
+	testAPI.setFunc.port_bool = gprtSetInterswitchPort;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Interswith port setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Learning Disable
+	 */
+	testAPI.getFunc.port_bool = gprtGetLearnDisable;
+	testAPI.setFunc.port_bool = gprtSetLearnDisable;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Learning Disable API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  FCS Ignore
+	 */
+	testAPI.getFunc.port_bool = gprtGetIgnoreFCS;
+	testAPI.setFunc.port_bool = gprtSetIgnoreFCS;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("FCS Ignore API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  VTU Priority Override
+	 */
+	testAPI.getFunc.port_bool = gprtGetVTUPriOverride;
+	testAPI.setFunc.port_bool = gprtSetVTUPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("VTU Priority Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  SA Priority Override
+	 */
+	testAPI.getFunc.port_bool = gprtGetSAPriOverride;
+	testAPI.setFunc.port_bool = gprtSetSAPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("SA Priority Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DA Priority Override
+	 */
+	testAPI.getFunc.port_bool = gprtGetDAPriOverride;
+	testAPI.setFunc.port_bool = gprtSetDAPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DA Priority Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  CPU Port Setup
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetCPUPort;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetCPUPort;
+	if((status = testPortU32Type(dev,&testAPI,dev->numOfPorts)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("CPU Port Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Locked Port Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetLockedPort;
+	testAPI.setFunc.port_bool = gprtSetLockedPort;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Locked Port Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Ignore Wrong Data Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetIgnoreWrongData;
+	testAPI.setFunc.port_bool = gprtSetIgnoreWrongData;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Ignore Wrong Data Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  UseCoreTag Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetUseCoreTag;
+	testAPI.setFunc.port_bool = gprtSetUseCoreTag;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("UseCoreTag Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DiscardTagged Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetDiscardTagged;
+	testAPI.setFunc.port_bool = gprtSetDiscardTagged;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DiscardTagged Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DiscardUntagged Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetDiscardUntagged;
+	testAPI.setFunc.port_bool = gprtSetDiscardUntagged;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DiscardUntagged Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  MapDA Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetMapDA;
+	testAPI.setFunc.port_bool = gprtSetMapDA;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("MapDA Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DefaultForward Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetDefaultForward;
+	testAPI.setFunc.port_bool = gprtSetDefaultForward;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DefaultForward Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  EgressMonitorSource Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetEgressMonitorSource;
+	testAPI.setFunc.port_bool = gprtSetEgressMonitorSource;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("EgressMonitorSource Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  IngressMonitorSource Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetIngressMonitorSource;
+	testAPI.setFunc.port_bool = gprtSetIngressMonitorSource;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("IngressMonitorSource Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  MessagePort Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetMessagePort;
+	testAPI.setFunc.port_bool = gprtSetMessagePort;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("MessagePort Setup API test "));
+	testDisplayStatus(status);
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		if((status = testTrunkPortSetup(dev,portIndex)) != GT_OK)
+		{
+			testResult = GT_FAIL;
+			testResults |= 1 << status;
+			portIndex = 0xFF;
+			break;		
+		}
+	}
+	MSG_PRINT(("TrunkPort Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  AGE Int Setup
+	 */
+	testAPI.getFunc.port_bool = geventGetAgeIntEn;
+	testAPI.setFunc.port_bool = geventSetAgeIntEn;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("AGE Interrupt Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  SA Filtering
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetSAFiltering;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetSAFiltering;
+	if((status = testPortU32Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("SA Filtering Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  ARP to CPU Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetARPtoCPU;
+	testAPI.setFunc.port_bool = gprtSetARPtoCPU;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("ARP to CPU Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Egress Flood
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetEgressFlood;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetEgressFlood;
+	if((status = testPortU32Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Egress Flood Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Port Scheduling
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetPortSched;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetPortSched;
+	if((status = testPortU32Type(dev,&testAPI,2)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Port Scheduling Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Provider Tag
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetProviderTag;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetProviderTag;
+	if((status = testPortU32Type(dev,&testAPI,0xFF)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Provider Tag Setup API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+}
+
+GT_U32 testPortG(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+	int portIndex;
+
+	testResult = GT_OK;
+
+	/*
+	 *  Drop on Lock
+	 */
+	testAPI.getFunc.port_bool = gprtGetDropOnLock;
+	testAPI.setFunc.port_bool = gprtSetDropOnLock;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Drop on Lock API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Double Tag
+	 */
+	testAPI.getFunc.port_bool = gprtGetDoubleTag;
+	testAPI.setFunc.port_bool = gprtSetDoubleTag;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Double Tag API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Interswitch Port
+	 */
+	testAPI.getFunc.port_bool = gprtGetInterswitchPort;
+	testAPI.setFunc.port_bool = gprtSetInterswitchPort;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Interswith port setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Learning Disable
+	 */
+	testAPI.getFunc.port_bool = gprtGetLearnDisable;
+	testAPI.setFunc.port_bool = gprtSetLearnDisable;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Learning Disable API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  FCS Ignore
+	 */
+	testAPI.getFunc.port_bool = gprtGetIgnoreFCS;
+	testAPI.setFunc.port_bool = gprtSetIgnoreFCS;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("FCS Ignore API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  VTU Priority Override
+	 */
+	testAPI.getFunc.port_bool = gprtGetVTUPriOverride;
+	testAPI.setFunc.port_bool = gprtSetVTUPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("VTU Priority Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  SA Priority Override
+	 */
+	testAPI.getFunc.port_bool = gprtGetSAPriOverride;
+	testAPI.setFunc.port_bool = gprtSetSAPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("SA Priority Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DA Priority Override
+	 */
+	testAPI.getFunc.port_bool = gprtGetDAPriOverride;
+	testAPI.setFunc.port_bool = gprtSetDAPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DA Priority Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  CPU Port Setup
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetCPUPort;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetCPUPort;
+	if((status = testPortU32Type(dev,&testAPI,dev->numOfPorts)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("CPU Port Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Locked Port Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetLockedPort;
+	testAPI.setFunc.port_bool = gprtSetLockedPort;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Locked Port Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Ignore Wrong Data Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetIgnoreWrongData;
+	testAPI.setFunc.port_bool = gprtSetIgnoreWrongData;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Ignore Wrong Data Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  UseCoreTag Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetUseCoreTag;
+	testAPI.setFunc.port_bool = gprtSetUseCoreTag;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("UseCoreTag Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DiscardTagged Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetDiscardTagged;
+	testAPI.setFunc.port_bool = gprtSetDiscardTagged;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DiscardTagged Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DiscardUntagged Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetDiscardUntagged;
+	testAPI.setFunc.port_bool = gprtSetDiscardUntagged;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DiscardUntagged Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  MapDA Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetMapDA;
+	testAPI.setFunc.port_bool = gprtSetMapDA;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("MapDA Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DefaultForward Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetDefaultForward;
+	testAPI.setFunc.port_bool = gprtSetDefaultForward;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DefaultForward Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  EgressMonitorSource Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetEgressMonitorSource;
+	testAPI.setFunc.port_bool = gprtSetEgressMonitorSource;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("EgressMonitorSource Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  IngressMonitorSource Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetIngressMonitorSource;
+	testAPI.setFunc.port_bool = gprtSetIngressMonitorSource;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("IngressMonitorSource Setup API test "));
+	testDisplayStatus(status);
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+			return testResults;
+		default:
+			break;
+	}			
+	
+	/*
+	 *  MessagePort Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetMessagePort;
+	testAPI.setFunc.port_bool = gprtSetMessagePort;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("MessagePort Setup API test "));
+	testDisplayStatus(status);
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		if((status = testTrunkPortSetup(dev,portIndex)) != GT_OK)
+		{
+			testResult = GT_FAIL;
+			testResults |= 1 << status;
+			portIndex = 0xFF;
+			break;		
+		}
+	}
+	MSG_PRINT(("TrunkPort Setup API test "));
+	testDisplayStatus(status);
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6092:
+		case GT_88E6095:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+			if (dev->revision < 1)
+				return testResults;
+			break;
+		case GT_88E6131:
+		case GT_88E6108:
+			break;
+		default:
+			return testResults;
+	}			
+	
+	/*
+	 *  Discard Broadcast Mode Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetDiscardBCastMode;
+	testAPI.setFunc.port_bool = gprtSetDiscardBCastMode;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Discard BCast Setup API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  FC On RateLimit Mode Setup
+	 */
+	testAPI.getFunc.port_bool = gprtGetFCOnRateLimitMode;
+	testAPI.setFunc.port_bool = gprtSetFCOnRateLimitMode;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("FC On RateLimit Setup API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+}
+
+GT_U32 testPort(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+
+	testResult = GT_OK;
+
+	/*
+	 *  Force FlowControl
+	 */
+	testAPI.getFunc.port_bool = gprtGetForceFc;
+	testAPI.setFunc.port_bool = gprtSetForceFc;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Force FlowControl API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Trailer Mode
+	 */
+	testAPI.getFunc.port_bool = gprtGetTrailerMode;
+	testAPI.setFunc.port_bool = gprtSetTrailerMode;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Trailer Mode API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Ingress Mode
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetIngressMode;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetIngressMode;
+	if((status = testPortU32Type(dev,&testAPI,3)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Ingress Mode API test "));
+	testDisplayStatus(status);
+
+
+	/*
+	 *  Muticast Rate Limit
+	 *  This feature is only avalable on 6021/6051/6052
+	 *  It is replace with Rate Control Register in Clippership and beyond
+	 */
+	if( (dev->deviceId == GT_88E6021) ||
+	    (dev->deviceId == GT_88E6051) ||
+	    (dev->deviceId == GT_88E6052) 
+	  ){
+
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetMcRateLimit;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetMcRateLimit;
+	if((status = testPortU32Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Multicast Rate Limit API test "));
+	testDisplayStatus(status);
+	};
+
+	/*
+	 *  IGMP Snoop
+	 */
+	testAPI.getFunc.port_bool = gprtGetIGMPSnoop;
+	testAPI.setFunc.port_bool = gprtSetIGMPSnoop;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("IGMP Snoop API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Header Mode
+	 */
+	testAPI.getFunc.port_bool = gprtGetHeaderMode;
+	testAPI.setFunc.port_bool = gprtSetHeaderMode;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Header Mode API test "));
+	testDisplayStatus(status);
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+			testResults |= testPortG(dev);
+			break;
+		case GT_88E6031:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6061:
+		case GT_88E6065:
+			testResults |= testPortEnhancedFE(dev);
+			break;
+		default:
+			break;
+	}			
+	return testResults;
+}
+
+GT_U32 testPortRCforEnhancedFE(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+
+	testResult = GT_OK;
+
+	/*
+	 *  VID NRL En
+	 */
+	testAPI.getFunc.port_bool = grcGetVidNrlEn;
+	testAPI.setFunc.port_bool = grcSetVidNrlEn;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("VID NRL En API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  SA NRL En
+	 */
+	testAPI.getFunc.port_bool = grcGetSaNrlEn;
+	testAPI.setFunc.port_bool = grcSetSaNrlEn;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("SA NRL En API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DA NRL En
+	 */
+	testAPI.getFunc.port_bool = grcGetDaNrlEn;
+	testAPI.setFunc.port_bool = grcSetDaNrlEn;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DA NRL En API test "));
+	testDisplayStatus(status);
+
+
+	/*
+	 *  Egress Limit Mode
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)grcGetELimitMode;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)grcSetELimitMode;
+	if((status = testPortU32Type(dev,&testAPI,3)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Egress Limit Mode API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Rsvd NRL En
+	 */
+	testAPI.getFunc.bool = grcGetRsvdNrlEn;
+	testAPI.setFunc.bool = grcSetRsvdNrlEn;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Rsvd NRL En API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+}
+
+GT_U32 testPortRateCtrl(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult, tmpResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+	GT_LPORT port;
+	int portIndex;
+	GT_BURST_RATE bLimit, rbLimit, obLimit;
+	GT_BURST_SIZE bSize, rbSize, obSize;
+	GT_U32 RateCtrl[5];
+
+	testResult = GT_OK;
+
+	/*
+	 *  Ingress Rate Limit Mode
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)grcGetLimitMode;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)grcSetLimitMode;
+	if((status = testPortU32Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Ingress Rate Limit Mode API test "));
+	testDisplayStatus(status);
+
+
+	/*
+	 *  Priority 3 Frames Rate Limit
+	 */
+	testAPI.getFunc.port_bool = grcGetPri3Rate;
+	testAPI.setFunc.port_bool = grcSetPri3Rate;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Priority 3 Frames Rate Limit API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Priority 2 Frames Rate Limit
+	 */
+	testAPI.getFunc.port_bool = grcGetPri2Rate;
+	testAPI.setFunc.port_bool = grcSetPri2Rate;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Priority 2 Frames Rate Limit API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Priority 1 Frames Rate Limit
+	 */
+	testAPI.getFunc.port_bool = grcGetPri1Rate;
+	testAPI.setFunc.port_bool = grcSetPri1Rate;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Priority 1 Frames Rate Limit API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Priority 0 Frames Rate Limit
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)grcGetPri0Rate;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)grcSetPri0Rate;
+	if((status = testPortU32Type(dev,&testAPI,8)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Priority 0 Frames Rate Limit API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Included Bytes in Rate Control API
+	 */
+	tmpResult = GT_OK;
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		GT_BOOL limitMGMT, countIFG, countPre;
+		GT_BOOL orgLimitMGMT, orgCountIFG, orgCountPre;
+		GT_BOOL tmpLimitMGMT, tmpCountIFG, tmpCountPre;
+
+		port = portIndex;
+		
+		if((status = grcGetBytesCount(dev,port,&orgLimitMGMT,&orgCountIFG,&orgCountPre)) != GT_OK)
+		{
+			MSG_PRINT(("grcSetBytesCount returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			tmpResult = status;
+			break;
+		}
+
+		limitMGMT = GT_TRUE;
+		countIFG = GT_FALSE;
+		countPre = GT_TRUE;
+
+		if((status = grcSetBytesCount(dev,port,limitMGMT,countIFG,countPre)) != GT_OK)
+		{
+			MSG_PRINT(("grcSetBytesCount returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = grcGetBytesCount(dev,port,&tmpLimitMGMT,&tmpCountIFG,&tmpCountPre))
+			!= GT_OK)
+		{
+			MSG_PRINT(("grcGetBytesCount returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if ((limitMGMT != tmpLimitMGMT) ||
+			(countIFG != tmpCountIFG) ||
+			(countPre != tmpCountPre))
+		{
+			MSG_PRINT(("grcGetBytesCount returned unexpected value(s)\n"));
+			MSG_PRINT(("Expecting: limitMgmg %i, countIFG %i, countPre %i\n",
+						limitMGMT,countIFG,countPre));
+			MSG_PRINT(("Returned : limitMgmg %i, countIFG %i, countPre %i\n",
+						tmpLimitMGMT,tmpCountIFG,tmpCountPre));
+			tmpResult = GT_FAIL;
+			testResults |= 1 << tmpResult;
+		}
+
+		limitMGMT = GT_FALSE;
+		countIFG = GT_TRUE;
+		countPre = GT_FALSE;
+
+		if((status = grcSetBytesCount(dev,port,limitMGMT,countIFG,countPre)) != GT_OK)
+		{
+			MSG_PRINT(("grcSetBytesCount returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = grcGetBytesCount(dev,port,&tmpLimitMGMT,&tmpCountIFG,&tmpCountPre))
+			!= GT_OK)
+		{
+			MSG_PRINT(("grcGetBytesCount returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if ((limitMGMT != tmpLimitMGMT) ||
+			(countIFG != tmpCountIFG) ||
+			(countPre != tmpCountPre))
+		{
+			MSG_PRINT(("grcGetBytesCount returned unexpected value(s)\n"));
+			MSG_PRINT(("Expecting: limitMgmg %i, countIFG %i, countPre %i\n",
+						limitMGMT,countIFG,countPre));
+			MSG_PRINT(("Returned : limitMgmg %i, countIFG %i, countPre %i\n",
+						tmpLimitMGMT,tmpCountIFG,tmpCountPre));
+			tmpResult = GT_FAIL;
+			testResults |= 1 << tmpResult;
+		}
+
+		if((status = grcSetBytesCount(dev,port,orgLimitMGMT,orgCountIFG,orgCountPre))
+			!= GT_OK)
+		{
+			MSG_PRINT(("grcSetBytesCount returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	}
+	if(tmpResult != GT_OK)
+	{
+		MSG_PRINT(("Count Bytes API test Failed.\n"));
+		testResult = tmpResult;
+		testResults |= 1 << testResult;
+	}
+	else
+	{
+		MSG_PRINT(("Count Bytes API test Passed.\n"));
+	}
+
+	/*
+	 *  Egress Rate Limit
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)grcGetEgressRate;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)grcSetEgressRate;
+	if((status = testPortU32Type(dev,&testAPI,8)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Egress Rate Limit API test "));
+	testDisplayStatus(status);
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6092:
+		case GT_88E6095:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+			if (dev->revision < 1)
+				return testResults;
+			break;
+		case GT_88E6031:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6061:
+		case GT_88E6065:
+			testResults |= testPortRCforEnhancedFE(dev);
+			break;
+		case GT_88E6131:
+		case GT_88E6108:
+			break;
+		default:
+			return testResults;
+	}			
+
+	/*
+	 *  Burst Size based Rate Limit API
+	 */
+	RateCtrl[0] = 0x7FFFF; /* No_Limit, 64k ~ 256M */
+	RateCtrl[1] = 0x7FFFD; /* No_Limit, 128k ~ 256M */
+	RateCtrl[2] = 0x7FFF9; /* No_Limit, 256k ~ 256M */
+	RateCtrl[3] = 0x7FFE1; /* No_Limit, 512k ~ 256M */
+	RateCtrl[4] = 0;
+	if(grcGetBurstRate(dev,0,&rbSize,&rbLimit) == GT_NOT_SUPPORTED)
+		testResult = GT_NOT_SUPPORTED;
+	else
+	{
+		testResult = GT_OK;
+
+		for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+		{
+			if((status=grcGetBurstRate(dev,portIndex,&obSize,&obLimit)) != GT_OK)
+			{
+				MSG_PRINT(("Get Burst Rate returned wrong (bsize %i, rate %i)\n",obSize,obLimit));
+				testResult = GT_FAIL;
+				testResults |= 1 << status;
+				break;
+			}
+
+			for(bSize=GT_BURST_SIZE_12K; bSize<=GT_BURST_SIZE_96K+1; bSize++)
+			{
+				for(bLimit=GT_BURST_NO_LIMIT; bLimit<=GT_BURST_256M+1; bLimit++)
+				{
+					if((status=grcSetBurstRate(dev,portIndex,bSize,bLimit)) != GT_OK)
+					{
+						if(RateCtrl[bSize] & (1<<bLimit))
+						{
+							MSG_PRINT(("Burst Rate Control returned wrong (bsize %i, rate %i)\n",bSize,bLimit));
+							testResult = GT_FAIL;
+							testResults |= 1 << GT_FAIL;
+						}
+					}
+					else
+					{
+						if (!(RateCtrl[bSize] & (1<<bLimit)))
+						{
+							MSG_PRINT(("Burst Rate Control returned GT_OK (bsize %i, rate %i)\n",bSize,bLimit));
+							testResult = GT_FAIL;
+							testResults |= 1 << GT_FAIL;
+							continue;
+						}
+
+						if((status=grcGetBurstRate(dev,portIndex,&rbSize,&rbLimit)) != GT_OK)
+						{
+							MSG_PRINT(("Get Burst Rate returned wrong (bsize %i, rate %i)\n",bSize,bLimit));
+							testResult = GT_FAIL;
+							testResults |= 1 << status;
+						}
+
+						if ((bSize != rbSize) || (bLimit != rbLimit))
+						{
+							MSG_PRINT(("Burst Rate returned value not consistant (bsize %i %i, rate %i %i)\n",
+										bSize,rbSize,bLimit,rbLimit));
+							testResult = GT_FAIL;
+							testResults |= 1 << GT_FAIL;
+						}
+					}
+				}
+			}
+
+			if((status=grcSetBurstRate(dev,portIndex,obSize,obLimit)) != GT_OK)
+			{
+				MSG_PRINT(("Set Burst Rate returned wrong (bsize %i, rate %i)\n",obSize,obLimit));
+				testResult = GT_FAIL;
+				testResults |= 1 << status;
+				break;
+			}
+		}
+	}
+
+	MSG_PRINT(("Burst Rate Limit API test "));
+	testDisplayStatus(testResult);
+
+	/*
+	 *  TCP/IP Burst Rate Limit API
+	 */
+	RateCtrl[0] = 0x7FF; /* No_Limit, 64k ~ 1500k */
+	if(grcGetTCPBurstRate(dev,0,&rbLimit) == GT_NOT_SUPPORTED)
+		testResult = GT_NOT_SUPPORTED;
+	else
+	{
+		testResult = GT_OK;
+
+		for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+		{
+			if((status=grcGetTCPBurstRate(dev,portIndex,&obLimit)) != GT_OK)
+			{
+				MSG_PRINT(("Get TCP Burst Rate returned wrong (rate %i)\n",obLimit));
+				testResult = GT_FAIL;
+				testResults |= 1 << status;
+				break;
+			}
+
+			for(bLimit=GT_BURST_NO_LIMIT; bLimit<=GT_BURST_256M; bLimit++)
+			{
+				if(grcSetTCPBurstRate(dev,portIndex,bLimit) != GT_OK)
+				{
+					if(RateCtrl[0] & (1<<bLimit))
+					{
+						MSG_PRINT(("TCP Burst Rate Control returned wrong (rate %i)\n",bLimit));
+						testResult = GT_FAIL;
+						testResults |= 1 << GT_FAIL;
+					}
+				}
+				else
+				{
+					if((status=grcGetTCPBurstRate(dev,portIndex,&rbLimit)) != GT_OK)
+					{
+						MSG_PRINT(("Get TCP Burst Rate returned wrong (rate %i)\n",bLimit));
+						testResult = GT_FAIL;
+						testResults |= 1 << status;
+					}
+
+					if (bLimit != rbLimit)
+					{
+						MSG_PRINT(("TCP Burst Rate returned value not consistant (rate %i %i)\n",
+									bLimit,rbLimit));
+						testResult = GT_FAIL;
+						testResults |= 1 << GT_FAIL;
+					}
+				}
+			}		
+
+			if((status=grcSetTCPBurstRate(dev,portIndex,obLimit)) != GT_OK)
+			{
+				MSG_PRINT(("Get TCP Burst Rate returned wrong (rate %i)\n",obLimit));
+				testResult = GT_FAIL;
+				testResults |= 1 << status;
+				break;
+			}
+
+		}
+	}
+	MSG_PRINT(("TCP Burst Rate Limit API test "));
+	testDisplayStatus(testResult);
+
+	return testResults;
+}
+
+GT_U32 testPortPAV(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+
+	testResult = GT_OK;
+
+	/*
+	 *  Port Association Vector API
+	 */
+	testAPI.getFunc.port_u16 = gpavGetPAV;
+	testAPI.setFunc.port_u16 = gpavSetPAV;
+	if((status = testPortU16Type(dev,&testAPI,(1<<dev->numOfPorts)-1)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Port Association Vector API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Ingress Monitor
+	 */
+	testAPI.getFunc.port_bool = gpavGetIngressMonitor;
+	testAPI.setFunc.port_bool = gpavSetIngressMonitor;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Ingress Monitor API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+}
+
+
+GT_U32 testATUSetup(GT_QD_DEV *dev )
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+
+	/*
+	 *  Learn2All Setup API
+	 */
+	testAPI.getFunc.bool = gfdbGetLearn2All;
+	testAPI.setFunc.bool = gfdbSetLearn2All;
+	if((status = testBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Learn2All Setup API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+}
+
+
+GT_STATUS testDisplayATUList(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_ATU_ENTRY tmpMacEntry;
+	GT_U32 dbNum,i;
+	int entries;
+
+	MSG_PRINT(("ATU List:\n"));
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6051:
+		case GT_88E6052:
+		case GT_FF_HG:
+		case GT_FF_EG:
+			dbNum = 1;
+			break;
+		case GT_88E6021:
+		case GT_88E6061:
+		case GT_88E6063:
+		case GT_FH_VPN:
+		case GT_88E6083:
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+			dbNum = 16;
+			break;
+		case GT_88E6065:
+			dbNum = 64;
+			break;
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+			dbNum = 256;
+			break;
+		default:
+			dbNum = 1;
+			break;
+	}
+
+	for(i=0; i<dbNum; i++)
+	{
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		tmpMacEntry.DBNum = (GT_U8)i;
+		entries = 0;
+		MSG_PRINT(("DB %i :\n",i));
+		while(1)
+		{
+			/* Get the sorted list of MAC Table. */
+			if((status = gfdbGetAtuEntryNext(dev,&tmpMacEntry)) != GT_OK)
+			{
+				break;
+			}
+			entries++;
+			printATUEntry(&tmpMacEntry);
+
+		}
+		MSG_PRINT(("DB %i : entry %i\n",i,entries));
+
+	}
+	return GT_OK;
+}
+
+GT_U16 testDisplayAtuDbNumList(GT_QD_DEV *dev,GT_U32 dbNum)
+{
+	GT_STATUS status;
+	GT_ATU_ENTRY tmpMacEntry;
+	GT_U16 entries = 0;
+
+	MSG_PRINT(("ATU List for DBNum %i:\n", dbNum));
+
+	memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+	tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+	while(1)
+	{
+		/* Get the sorted list of MAC Table. */
+		if((status = gfdbGetAtuEntryNext(dev,&tmpMacEntry)) != GT_OK)
+		{
+			break;
+		}
+
+		entries++;
+		printATUEntry(&tmpMacEntry);
+	}
+	return entries;
+}
+
+/*******************************************************************************
+* testATUDBNum
+*
+* DESCRIPTION:
+*       Testing ATU related APIs.
+*		(SetAtuSize, SetAgingTimeout, GetAgingTimeRange, LearnEnable, AddEntry,
+*		DeleteEntry, GetFirst, GetNext, FindEntry, Flush, GetDynamicCount)
+*		
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on fail
+*
+* COMMENTS:
+*		1. Setup ATU Size.
+*		2. Disable AGING.
+*		3. Disable Learning.
+*		4. Flush all the ATU Entries.
+*		5. Create ATU Entries (random, with arg).
+*		6. Keep the Sorted list of the entries.
+*		7. Write the entries into the device.
+*		8. Check the Dynamic Counter.
+*		9. Get the First Entry and Check if it's correct.
+*		10.Delete the First entry.
+*		11.Get the First Entry and check if it's correct.
+*		12.Get the next entry and check if it's correct.
+*		13.Find the middle entry and check if it's correct.
+*		14.Find the last entry and check if it's correct.
+*		15.Find the next entry of the last entry.(It should fail.)
+*		16.Find the deleted entry.(It should fail.)
+*		17.Repeat 9 ~ 16 for each DBNum
+*		18.If the device supports MOVE, 
+*			18.1 Move all the entries in DB (maxDbNum-1) to port 1 and verify
+*			18.2 Move all the entries to port 0 and verify
+*		19.Check Dynamic count.
+*		20.Flush All in a DB
+*
+*******************************************************************************/
+GT_STATUS testAtuDbNum(GT_QD_DEV *dev,int arg, GT_U32 entrySize, GT_U32 maxDbNum, GT_U8 sameMacs, GT_U8 atuSize)
+{
+	GT_STATUS status;
+	GT_STATUS testResult = GT_OK;
+	GT_U32 u32Data1, u32Data2, dbNum;
+	TEST_ATU_ENTRY *macEntry;
+	int *macList[256];
+	GT_ATU_ENTRY tmpMacEntry;
+	int i, j, dynamicMacs;
+	GT_BOOL found;
+	GT_BOOL sapphire, aging15, moveAllowed;
+	GT_LPORT port, portDest;
+	GT_STATUS secResult;
+	volatile int timer;
+
+	if(entrySize < 4)
+		entrySize = 4;
+
+	if(entrySize > TEST_MAC_ENTRIES)
+		entrySize = TEST_MAC_ENTRIES;
+
+	if (entrySize*maxDbNum > (256 << atuSize))
+	{
+		entrySize = (256 << atuSize) / maxDbNum;
+	}
+
+	macEntry = NULL;
+	for(dbNum=0; dbNum < maxDbNum; dbNum++)
+		macList[dbNum] = NULL;
+	
+	switch(dev->deviceId)
+	{
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+			sapphire = GT_TRUE;
+			aging15 = GT_TRUE;
+			moveAllowed = GT_TRUE;
+			break;
+		case GT_88E6031:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6061:
+		case GT_88E6065:
+			moveAllowed = GT_TRUE;
+			sapphire = GT_FALSE;
+			aging15 = GT_TRUE;
+			break;
+		default:
+			moveAllowed = GT_FALSE;
+			sapphire = GT_FALSE;
+			aging15 = GT_FALSE;
+			break;
+	}			
+	/* Set ATU Size will cause ATU reset and SW reset, so call before any other setup. */
+	MSG_PRINT(("Setting ATU Size : %i\n",256<<atuSize));
+	if((status = gfdbSetAtuSize(dev,atuSize)) != GT_OK)
+	{
+		if(sapphire != GT_TRUE)
+		{
+			MSG_PRINT(("gfdbSetAtuSize returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+	}
+
+	/* Aging Time Range is between 16 and 4080 */
+	MSG_PRINT(("Getting Aging Time Range... \n"));
+	if((status = gfdbGetAgingTimeRange(dev,&u32Data1, &u32Data2)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbAgingTimeRange returned "));
+		testDisplayStatus(status);
+		goto errorExit;
+	}
+
+	if((u32Data2 != 16) || (u32Data1 != 4080))
+	{
+		if(aging15 != GT_TRUE)
+		{
+			MSG_PRINT(("AgingTimeRange is between %d and %d.\n",u32Data1,u32Data2));
+			testResult = GT_FAIL;
+		}
+	}
+
+	/* Disable Aging */
+	MSG_PRINT(("Disable Aging Timeout... \n"));
+	if((status = gfdbSetAgingTimeout(dev,0)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbSetAgingTimeout returned "));
+		testDisplayStatus(status);
+		goto errorExit;
+	}
+
+	/* Disable Learning */
+	MSG_PRINT(("Disable Learning... \n"));
+	if((status = gfdbLearnEnable(dev,GT_FALSE)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbLearnEnable returned "));
+		testDisplayStatus(status);
+		goto errorExit;
+	}
+
+	/* Flush all addresses from the ATU table. */
+	MSG_PRINT(("Flush out all the entries in the ATU Table ... \n"));
+	if((status = gfdbFlush(dev,GT_FLUSH_ALL)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbFlush returned "));
+		testDisplayStatus(status);
+		goto errorExit;
+	}
+
+	/* Get Atu Dynamic Count, which should be 0, since we flush them all. */
+	if((status = gfdbGetAtuDynamicCount(dev,&u32Data1)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbGetAtuDynamicCount returned "));
+		testDisplayStatus(status);
+		goto errorExit;
+	}
+
+	MSG_PRINT(("Atu Dynamic Count : %d.\n", u32Data1));
+
+	if(u32Data1)
+	{
+		testResult = GT_FAIL;
+	}
+	
+	/* Now ATU table is clean. Play with our own MAC entries */	
+	MSG_PRINT(("Setup Testing Table... \n"));
+
+	macEntry = (TEST_ATU_ENTRY*)malloc(maxDbNum*sizeof(TEST_ATU_ENTRY));
+	if(macEntry == NULL)
+	{
+		MSG_PRINT(("Failed to allocate MAC Entries. \n"));
+		goto errorExit;
+	}
+
+	memset(macEntry,0,sizeof(macEntry));
+
+	for(dbNum=0; dbNum < maxDbNum; dbNum++)
+	{
+		macList[dbNum] = (int*)malloc(TEST_MAC_ENTRIES*sizeof(int));
+		if(macList[dbNum] == NULL)
+		{
+			MSG_PRINT(("Failed to allocate MAC Entries. \n"));
+			goto errorExit;
+		}
+	}
+
+	MSG_PRINT(("Creating ATU List... \n"));
+	dynamicMacs = createATUList(dev,macEntry,entrySize,(GT_U16)maxDbNum,sameMacs,64 << atuSize);
+
+	if (dynamicMacs > entrySize*maxDbNum)
+	{
+		MSG_PRINT(("Cannot create ATU List for testing... \n"));
+		goto errorExit;
+	}
+
+	for(i=0; i<entrySize; i++)
+	{
+		for(dbNum=0; dbNum < maxDbNum; dbNum++)
+		{
+			macList[dbNum][i] = i;
+		}
+	}	
+
+	/* Get Sorted List for the arg, 0 or 1. */
+
+	MSG_PRINT(("Sorting the created ATU List... \n"));
+	for(dbNum=0; dbNum < maxDbNum; dbNum++)
+		gtSort(macList[dbNum], atuEntryCmpFunc, (void*)macEntry[dbNum].atuEntry, entrySize);
+
+	MSG_PRINT(("Writing ATU Entries... \n"));
+	for (dbNum=0; dbNum<maxDbNum; dbNum++)
+	{
+
+		for(i=0; i<entrySize; i++)
+		{
+			switch (arg)
+			{
+				case 0: /* ascending order */
+					j = macList[dbNum][i];
+					break;
+				case 1: /* descending order */
+					j = macList[dbNum][entrySize - 1 - i];
+					break;
+				default:
+					j = i;
+					break;
+			}
+
+			if((status = gfdbAddMacEntry(dev,&macEntry[dbNum].atuEntry[j])) != GT_OK)
+			{
+				MSG_PRINT(("gfdbAddMacEntry returned "));
+				testDisplayStatus(status);
+				dumpMemory((char*)&macEntry[dbNum].atuEntry[j], sizeof(GT_ATU_ENTRY));
+				MSG_PRINT(("dbNum %i, entry %i\n",dbNum,j));
+				goto errorExit;
+			}
+
+#ifdef TEST_DEBUG
+			printATUEntry(&macEntry[dbNum].atuEntry[j]);
+			
+			memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+			tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+			if((status = gfdbGetAtuEntryFirst(dev,&tmpMacEntry)) != GT_OK)
+			{
+				MSG_PRINT(("gfdbGetAtuEntryFirst returned "));
+				testDisplayStatus(status);
+				MSG_PRINT(("Expected entry:"));
+				dumpMemory((char*)&macEntry[dbNum].atuEntry[macList[dbNum][0]], sizeof(GT_ATU_ENTRY));
+				testDisplayATUList(dev);
+				goto errorExit;
+			}
+
+			if(memcmp(&tmpMacEntry, &macEntry[dbNum].atuEntry[macList[dbNum][0]], sizeof(GT_ATU_ENTRY)))
+			{
+				MSG_PRINT(("gfdbGetAtuEntryFirst returned wrong entry."));
+				dumpMemory((char*)&tmpMacEntry, sizeof(GT_ATU_ENTRY));
+				MSG_PRINT(("Expected entry:"));
+				dumpMemory((char*)&macEntry[dbNum].atuEntry[macList[dbNum][0]], sizeof(GT_ATU_ENTRY));
+		
+				testDisplayATUList(dev);
+				goto errorExit;
+			}
+#endif
+		}	
+	}
+
+	timer = gAgeDelayTime;
+	while(timer>0)
+		timer--;
+
+#ifdef TEST_DEBUG
+	testDisplayATUList(dev);
+#endif
+	/* 
+		Now we have entrySize*16 entries in the table. 
+	*/
+
+	/* Get Atu Dynamic Count, which should be dynamicMacs. */
+	if((status = gfdbGetAtuDynamicCount(dev,&u32Data1)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbGetAtuDynamicCount returned "));
+		testDisplayStatus(status);
+		goto errorExit;
+	}
+
+	MSG_PRINT(("Dynamic Macs in the table : %d\n", dynamicMacs));
+	if (u32Data1 != dynamicMacs)
+	{
+		MSG_PRINT(("Atu Dynamic Count returned %d.(should be %d)\n", u32Data1,dynamicMacs));
+		testResult = GT_FAIL;
+	}
+
+	/* Get First Entry in the Table, which should be macEntry[0]. */
+
+	for (dbNum=0; dbNum<maxDbNum; dbNum++)
+	{
+		MSG_PRINT(("Running ATU Test for DBNum %i\n", dbNum));
+
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+		if((status = gfdbGetAtuEntryFirst(dev,&tmpMacEntry)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbGetAtuEntryFirst returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+
+		if(memcmp(&tmpMacEntry, &macEntry[dbNum].atuEntry[macList[dbNum][0]], sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbGetAtuEntryFirst returned wrong entry."));
+			dumpMemory((char*)&tmpMacEntry, sizeof(GT_ATU_ENTRY));
+			MSG_PRINT(("Expected entry:"));
+			dumpMemory((char*)&macEntry[dbNum].atuEntry[macList[dbNum][0]], sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("Getting First Entry is passed. \n"));
+
+		/* Delete the first entry for each DBNum */
+		MSG_PRINT(("Delete the First Entry\n"));
+
+		if((status = gfdbDelAtuEntry(dev,&macEntry[dbNum].atuEntry[macList[dbNum][0]])) != GT_OK)
+		{
+			MSG_PRINT(("gfdbAddMacEntry returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+
+		if(!(macEntry[dbNum].atuEntry[macList[dbNum][0]].macAddr.arEther[0] & 0x1) && 
+			(macEntry[dbNum].atuEntry[macList[dbNum][0]].entryState.ucEntryState == GT_UC_DYNAMIC))
+				dynamicMacs--;
+
+		/* Get First Entry in the Table, which should be macEntry[1]. */
+
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+		if((status = gfdbGetAtuEntryFirst(dev,&tmpMacEntry)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbGetAtuEntryFirst returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+
+		if(memcmp(&tmpMacEntry, &macEntry[dbNum].atuEntry[macList[dbNum][1]], sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbGetAtuEntryFirst returned wrong entry:"));
+			dumpMemory((char*)&tmpMacEntry, sizeof(GT_ATU_ENTRY));
+		
+			MSG_PRINT(("Expecting entry."));
+			dumpMemory((char*)&macEntry[dbNum].atuEntry[macList[dbNum][1]], sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("Getting First Entry is passed. \n"));
+
+		if((status = gfdbGetAtuEntryNext(dev,&tmpMacEntry)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbGetAtuEntryNext returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+
+		if(memcmp(&tmpMacEntry, &macEntry[dbNum].atuEntry[macList[dbNum][2]], sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbGetAtuEntryNext returned wrong entry."));
+			dumpMemory((char*)&tmpMacEntry, sizeof(GT_ATU_ENTRY));
+			MSG_PRINT(("Expected entry:"));
+			dumpMemory((char*)&macEntry[dbNum].atuEntry[macList[dbNum][2]], sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("Getting Next Entry is passed. \n"));
+
+		/* Find Mac Entry (use macEntry[TEST_MAC_ENTRIES/2]) */
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		i = entrySize/2;
+		tmpMacEntry.macAddr.arEther[0] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[0];
+		tmpMacEntry.macAddr.arEther[1] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[1];
+		tmpMacEntry.macAddr.arEther[2] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[2];
+		tmpMacEntry.macAddr.arEther[3] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[3];
+		tmpMacEntry.macAddr.arEther[4] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[4];
+		tmpMacEntry.macAddr.arEther[5] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[5];
+
+		tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+		if((status = gfdbFindAtuMacEntry(dev,&tmpMacEntry,&found)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+
+		if (found == GT_FALSE)
+		{
+			MSG_PRINT(("Cannot find the middle entry.\n"));
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("Successfully Found the middle Mac Entry (PASS). \n"));
+
+		if(memcmp(&tmpMacEntry, &macEntry[dbNum].atuEntry[macList[dbNum][i]], sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned wrong entry."));
+			dumpMemory((char*)&tmpMacEntry, sizeof(GT_ATU_ENTRY));
+			MSG_PRINT(("Expected entry:"));
+			dumpMemory((char*)&macEntry[dbNum].atuEntry[macList[dbNum][i]], sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("Found Entry is valid (PASS). \n"));
+
+		/* Find Mac Entry (use macEntry[TEST_MAC_ENTRIES-1]) */
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		i = entrySize-1;
+		tmpMacEntry.macAddr.arEther[0] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[0];
+		tmpMacEntry.macAddr.arEther[1] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[1];
+		tmpMacEntry.macAddr.arEther[2] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[2];
+		tmpMacEntry.macAddr.arEther[3] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[3];
+		tmpMacEntry.macAddr.arEther[4] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[4];
+		tmpMacEntry.macAddr.arEther[5] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[5];
+
+		tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+		if((status = gfdbFindAtuMacEntry(dev,&tmpMacEntry,&found)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+
+		if (found == GT_FALSE)
+		{
+			MSG_PRINT(("Cannot find the last entry.\n"));
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("Successfully Found the last Mac Entry (PASS). \n"));
+
+		if(memcmp(&tmpMacEntry, &macEntry[dbNum].atuEntry[macList[dbNum][i]], sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned wrong entry."));
+			dumpMemory((char*)&tmpMacEntry, sizeof(GT_ATU_ENTRY));
+			MSG_PRINT(("Expected entry:"));
+			dumpMemory((char*)&macEntry[dbNum].atuEntry[macList[dbNum][i]], sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("Found Entry is valid (PASS). \n"));
+
+		/* Error Checking */
+
+		/* Now tmpMacEntry is pointing to the last entry. So, GetNext should return error */
+		i = entrySize-1;
+		tmpMacEntry.macAddr.arEther[0] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[0];
+		tmpMacEntry.macAddr.arEther[1] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[1];
+		tmpMacEntry.macAddr.arEther[2] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[2];
+		tmpMacEntry.macAddr.arEther[3] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[3];
+		tmpMacEntry.macAddr.arEther[4] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[4];
+		tmpMacEntry.macAddr.arEther[5] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[5];
+
+		tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+		if((status = gfdbGetAtuEntryNext(dev,&tmpMacEntry)) == GT_OK)
+		{
+			MSG_PRINT(("gfdbGetAtuEntryNext should return fail.\n"));
+			printATUEntry(&tmpMacEntry);
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("Getting Next Entry from the last entry returned %i (PASS).\n", status));
+
+		/* macEntry[0] has been deleted. So, finding the entry should return not found */
+
+		if((status = gfdbFindAtuMacEntry(dev,&macEntry[dbNum].atuEntry[macList[dbNum][0]],&found)) == GT_OK)
+		{
+			if (found == GT_TRUE)
+			{
+				MSG_PRINT(("gfdbFindAtuMacEntry should not be found.(%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						macEntry[dbNum].atuEntry[macList[dbNum][0]].macAddr.arEther[0],
+						macEntry[dbNum].atuEntry[macList[dbNum][0]].macAddr.arEther[1],
+						macEntry[dbNum].atuEntry[macList[dbNum][0]].macAddr.arEther[2],
+						macEntry[dbNum].atuEntry[macList[dbNum][0]].macAddr.arEther[3],
+						macEntry[dbNum].atuEntry[macList[dbNum][0]].macAddr.arEther[4],
+						macEntry[dbNum].atuEntry[macList[dbNum][0]].macAddr.arEther[5]));
+				testResult = GT_FAIL;
+			}
+			else
+				MSG_PRINT(("Finding invalid entry returned not found (PASS).\n"));
+
+		}
+		else
+		{
+			MSG_PRINT(("Finding invalid entry returned not OK (PASS).\n"));
+		}
+	}
+	/* If the device supports MOVE, 
+	 *		Move all the entries in DB 0 to port 1 and verify
+	 *		Move all the entries to port 0 and verify
+	*/
+
+	if (moveAllowed)
+	{
+		secResult = GT_OK;
+		
+		/* move all the entries in DB (maxDbNum-1) to port 1 */
+		portDest = 1;
+		dbNum = maxDbNum-1;
+
+		MSG_PRINT(("Moving entries to Port 1... (in DB %i) \n", dbNum));
+		
+		for(port=0; port<dev->numOfPorts; port++)
+		{
+			if(port == portDest)
+				continue;
+
+			if((status = gfdbMoveInDB(dev,GT_MOVE_ALL,(GT_U8)dbNum,port,portDest)) != GT_OK)
+			{
+				MSG_PRINT(("gfdbMove returned "));
+				testDisplayStatus(status);
+				if (status == GT_NOT_SUPPORTED)
+					break;
+				goto errorExit;
+			}
+		}
+
+		/* verify Move, First Entry has been deleted from previous test */
+		for(i=1; i<entrySize; i++)
+		{
+			if (status == GT_NOT_SUPPORTED)
+				break;
+
+			memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+			tmpMacEntry.macAddr.arEther[0] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[0];
+			tmpMacEntry.macAddr.arEther[1] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[1];
+			tmpMacEntry.macAddr.arEther[2] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[2];
+			tmpMacEntry.macAddr.arEther[3] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[3];
+			tmpMacEntry.macAddr.arEther[4] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[4];
+			tmpMacEntry.macAddr.arEther[5] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[5];
+
+			tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+			if((status = gfdbFindAtuMacEntry(dev,&tmpMacEntry,&found)) != GT_OK)
+			{
+				MSG_PRINT(("gfdbFindAtuMacEntry returned "));
+				testDisplayStatus(status);
+				goto errorExit;
+			}
+			
+			if (found == GT_FALSE)
+			{
+				MSG_PRINT(("Cannot find the last entry.\n"));
+				secResult = GT_FAIL;
+				testResult = GT_FAIL;
+			}
+			/* verify if the port is portDest */
+			if ((tmpMacEntry.portVec & (1 << portDest)) == 0)
+			{
+				MSG_PRINT(("Move to port %i failed (portVec %#x, dbnum %i, orgVec %#x).\n",
+							portDest,tmpMacEntry.portVec,dbNum,
+							macEntry[dbNum].atuEntry[macList[dbNum][i]].portVec));
+				MSG_PRINT(("Entry : \n"));
+				printATUEntry(&tmpMacEntry);
+				secResult = GT_FAIL;
+				testResult = GT_FAIL;
+			}
+		}
+
+		if(secResult == GT_FAIL)
+		{
+			MSG_PRINT(("Moving entry Failed.\n"));
+		}
+		else
+		{
+			MSG_PRINT(("Moving entry Passed.\n"));                          
+		}
+		
+		/* move all the entries to port 0 */
+		portDest = 0;
+		secResult = GT_OK;
+		MSG_PRINT(("Moving entries to Port 0...\n"));                          
+		for(port=0; port<dev->numOfPorts; port++)
+		{
+			if(port == portDest)
+				continue;
+
+			if((status = gfdbMove(dev,GT_MOVE_ALL,port,portDest)) != GT_OK)
+			{
+				MSG_PRINT(("gfdbMove returned "));
+				testDisplayStatus(status);
+				if (status == GT_NOT_SUPPORTED)
+					break;
+				goto errorExit;
+			}
+		}
+
+		/* verify Move. First Entry has been deleted from previous test */
+		for(i=1; i<entrySize; i++)
+		{
+			if (status == GT_NOT_SUPPORTED)
+				break;
+
+			for (dbNum=0; dbNum<maxDbNum; dbNum++)
+			{
+				memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+				tmpMacEntry.macAddr.arEther[0] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[0];
+				tmpMacEntry.macAddr.arEther[1] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[1];
+				tmpMacEntry.macAddr.arEther[2] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[2];
+				tmpMacEntry.macAddr.arEther[3] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[3];
+				tmpMacEntry.macAddr.arEther[4] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[4];
+				tmpMacEntry.macAddr.arEther[5] = macEntry[dbNum].atuEntry[macList[dbNum][i]].macAddr.arEther[5];
+
+				tmpMacEntry.DBNum = (GT_U8)dbNum;
+
+				if((status = gfdbFindAtuMacEntry(dev,&tmpMacEntry,&found)) != GT_OK)
+				{
+					MSG_PRINT(("gfdbFindAtuMacEntry returned "));
+					testDisplayStatus(status);
+					goto errorExit;
+				}
+			
+				if (found == GT_FALSE)
+				{
+					MSG_PRINT(("Cannot find the last entry.\n"));
+					secResult = GT_FAIL;
+					testResult = GT_FAIL;
+				}
+				/* verify if the port is portDest */
+				if ((tmpMacEntry.portVec & (1 << portDest)) == 0)
+				{
+					MSG_PRINT(("Move to port %i failed (portVec %#x, dbnum %i, orgVec %#x).\n",
+								portDest,tmpMacEntry.portVec,dbNum,
+								macEntry[dbNum].atuEntry[macList[dbNum][i]].portVec));
+					MSG_PRINT(("Entry :\n"));
+					printATUEntry(&tmpMacEntry);
+					secResult = GT_FAIL;
+					testResult = GT_FAIL;
+				}
+			}
+		}
+
+		if(secResult == GT_FAIL)
+		{
+			MSG_PRINT(("Moving entry Failed.\n"));
+		}
+		else
+		{
+			MSG_PRINT(("Moving entry Passed.\n"));                          
+		}
+
+	}
+
+
+	MSG_PRINT(("Checking Dynamic Count... \n"));
+	/* Get Atu Dynamic Count, which should be dynamicMacs. */
+	if((status = gfdbGetAtuDynamicCount(dev,&u32Data1)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbGetAtuDynamicCount returned "));
+		testDisplayStatus(status);
+		goto errorExit;
+	}
+
+	if (u32Data1 != dynamicMacs)
+	{
+		MSG_PRINT(("gfdbGetAtuDynamicCount returned %d (should be %d).\n",u32Data1,dynamicMacs));
+		testResult = GT_FAIL;
+	}
+	else
+		MSG_PRINT(("Dynamic Entries : %d (PASS).\n",u32Data1));
+
+	/* Flush all non-static addresses from the ATU table. */
+	MSG_PRINT(("Flush out all the Dynamic Entries...\n"));
+	for (dbNum=0; dbNum<maxDbNum; dbNum++)
+	{
+		if((status = gfdbFlushInDB(dev,GT_FLUSH_ALL_UNBLK,dbNum)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFlushInDB returned "));
+			testDisplayStatus(status);
+			if (status == GT_NOT_SUPPORTED)
+				break;
+			goto errorExit;
+		}
+	}
+
+	if (dbNum != maxDbNum)
+	{
+		MSG_PRINT(("Call gfdbFlush \n"));
+		if((status = gfdbFlush(dev,GT_FLUSH_ALL_UNBLK)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFlush returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+	}
+
+	/* Get Atu Dynamic Count, which should be 0. */
+	if((status = gfdbGetAtuDynamicCount(dev,&u32Data1)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbGetAtuDynamicCount returned "));
+		testDisplayStatus(status);
+		goto errorExit;
+	}
+
+	if (u32Data1)
+	{
+		MSG_PRINT(("gfdbGetAtuDynamicCount returned %d (should be 0).\n",u32Data1));
+		testResult = GT_FAIL;
+	}
+	else
+		MSG_PRINT(("Dynamic Entries : %d (PASS).\n",u32Data1));
+
+	/* Flush all addresses from the ATU table. */
+	MSG_PRINT(("Flush out all the Entries...\n"));
+	for (dbNum=0; dbNum<maxDbNum; dbNum++)
+	{
+		if((status = gfdbFlushInDB(dev,GT_FLUSH_ALL,dbNum)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFlushInDB returned "));
+			testDisplayStatus(status);
+			if (status == GT_NOT_SUPPORTED)
+				break;
+			goto errorExit;
+		}
+	}
+
+	if (dbNum != maxDbNum)
+	{
+		MSG_PRINT(("Call gfdbFlush \n"));
+		if((status = gfdbFlush(dev,GT_FLUSH_ALL_UNBLK)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFlush returned "));
+			testDisplayStatus(status);
+			goto errorExit;
+		}
+	}
+
+	return testResult;
+
+errorExit:
+
+	for(dbNum=0; dbNum < maxDbNum; dbNum++)
+		if(macList[dbNum])
+			free(macList[dbNum]);
+	if(macEntry)
+		free(macEntry);
+	return status;
+}
+
+GT_STATUS testFillUpAtu(GT_QD_DEV *dev,ATU_ENTRY_INFO *atuEntry, GT_U8 atuSize, GT_U32 dbNum, GT_U16 first2Bytes, GT_ATU_UC_STATE state)
+{
+	char buckets[MAX_BUCKET_SIZE];
+	GT_U16 binSize,bSize;
+	GT_U16 hash, bucket, tmpBucket, preBucket;
+	GT_U32 maxMacs,entry,i,addr;
+	char eaddr[6];
+
+	if(atuSize >= 5)
+		return GT_BAD_PARAM;
+
+	maxMacs = 256 << atuSize;
+	bSize = 64 << atuSize;
+	binSize = 4;
+
+	gtMemSet(buckets,0,MAX_BUCKET_SIZE);
+
+	i = entry = 0;
+
+	while(1)
+	{
+		if (i == 0xFFFFFFFF)
+		{
+			MSG_PRINT(("32bit is not enough.\n"));
+			return GT_FAIL;
+		}
+
+		i++;
+
+		if ((i & 0xFFFFFF) == 0)
+		{
+			MSG_PRINT(("loop %#x : entry %#x\n", i,entry));
+			dumpMemory(buckets,bSize);
+		}
+
+		*(GT_U16*)eaddr = first2Bytes;
+		eaddr[2] = (i >> 24) & 0xff;
+		eaddr[3] = (i >> 16) & 0xff;
+		eaddr[4] = (i >> 8) & 0xff;
+		eaddr[5] = i & 0xff;
+		bucket = runQDHash(eaddr, dbNum, bSize, &hash, &preBucket, &tmpBucket);
+		if(buckets[bucket] == binSize)
+			continue;
+		addr = bucket*binSize + buckets[bucket];
+		buckets[bucket]++;
+		memcpy(atuEntry[addr].atuEntry.macAddr.arEther,eaddr,6);
+		atuEntry[addr].atuEntry.entryState.ucEntryState = state;
+		atuEntry[addr].atuEntry.portVec = 1;
+		atuEntry[addr].atuEntry.prio = 0;
+		atuEntry[addr].atuEntry.DBNum = (GT_U8)dbNum;
+		atuEntry[addr].hash = hash;
+		atuEntry[addr].bucket = bucket;
+#if 0
+		MSG_PRINT(("EADDR : %02x-%02x-%02x-%02x, ", eaddr[2],eaddr[3],eaddr[4],eaddr[5]));
+		MSG_PRINT(("Hash : %03x, ", hash));
+		MSG_PRINT(("bucket : %03x, ", preBucket));
+		MSG_PRINT(("bucket(db) : %03x, ", bucket));
+		MSG_PRINT(("bins : %02x\n", buckets[bucket]-1));
+#endif
+		entry++;
+		if (entry >= maxMacs)
+		{
+			MSG_PRINT(("loop %#x\n", i));
+			break;
+		}
+		
+	}
+
+	return GT_OK;
+}
+
+/*
+	1. Set ATU Size.
+	2. Disable AGING.
+	3. Disable Learning.
+	4. Flush all the ATU entries.
+	5. Check Dynamic Counts.
+	6. Create Filled ATU Table in system memory with EntryState = 0x7.
+	7. Write the table into the device.
+	8. Compare ATU Entries.
+	9. Create Filled ATU Table in system memory with EntryState = 0x7.
+	10.Write the table into the device.
+	11.Compare ATU Entries. (Only First Entry in each bucket got replaced.)
+	12.Create Filled ATU Table in system memory with EntryState = 0xF.
+	13.Write the table into the device.
+	14.Compare ATU Entries.
+	15.Write the table which was created in step 9.
+	16.Make it sure that no entry is written.
+*/
+GT_STATUS testFilledATU(GT_QD_DEV *dev,GT_U8 atuSize, GT_U32 dbNum)
+{
+	GT_STATUS testResult, status;
+	ATU_ENTRY_INFO *atuEntry;
+	ATU_ENTRY_INFO *tmpAtuEntry;
+	ATU_ENTRY_INFO *tmpSingleAtuEntry;
+	GT_ATU_ENTRY tmpMacEntry;
+	GT_U16 maxMacs, i;
+	GT_BOOL found;
+	GT_U32 u32Data;
+
+	if(atuSize > 5)
+		return GT_FAIL;
+
+	testResult = GT_OK;
+	maxMacs = 256 << atuSize;
+
+	if (gAtuEntry == NULL)
+		gAtuEntry = (ATU_ENTRY_INFO *)malloc(sizeof(ATU_ENTRY_INFO)*4096);
+
+	atuEntry = gAtuEntry;
+
+	gtMemSet(atuEntry,0,sizeof(ATU_ENTRY_INFO)*maxMacs);
+
+	MSG_PRINT(("Setting ATU Size : %i\n",256<<atuSize));
+	if((status = gfdbSetAtuSize(dev,atuSize)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbSetAtuSize returned "));
+		testDisplayStatus(status);
+		if (status != GT_NOT_SUPPORTED)
+			return status;
+	}
+
+	MSG_PRINT(("Disable Aging Timeout... \n"));
+	if((status = gfdbSetAgingTimeout(dev,0)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbSetAgingTimeout returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	/* Disable Learning */
+	MSG_PRINT(("Disable Learning... \n"));
+	if((status = gfdbLearnEnable(dev,GT_FALSE)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbSetAtuSize returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	/* Flush all addresses from the ATU table. */
+	MSG_PRINT(("Flush out all the entries in the ATU Table ... \n"));
+	if((status = gfdbFlush(dev,GT_FLUSH_ALL)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbFlush returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	/* Get Atu Dynamic Count, which should be 0, since we flush them all. */
+	if((status = gfdbGetAtuDynamicCount(dev,&u32Data)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbGetAtuDynamicCount returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	MSG_PRINT(("Atu Dynamic Count : %d.\n", u32Data));
+
+	/*
+	 *	Entry State 0x7
+	 */
+
+	MSG_PRINT(("Getting ATU List(%i).\n",maxMacs));
+	if((status=testFillUpAtu(dev,atuEntry,atuSize,dbNum,0,GT_UC_DYNAMIC)) != GT_OK)
+	{
+		MSG_PRINT(("testFillUpAtu returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	MSG_PRINT(("Writing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		if((status = gfdbAddMacEntry(dev,&atuEntry[i].atuEntry)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbAddMacEntry returned "));
+			testDisplayStatus(status);
+			return status;
+		}
+	}
+
+	MSG_PRINT(("Comparing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		tmpMacEntry.macAddr.arEther[0] = atuEntry[i].atuEntry.macAddr.arEther[0];
+		tmpMacEntry.macAddr.arEther[1] = atuEntry[i].atuEntry.macAddr.arEther[1];
+		tmpMacEntry.macAddr.arEther[2] = atuEntry[i].atuEntry.macAddr.arEther[2];
+		tmpMacEntry.macAddr.arEther[3] = atuEntry[i].atuEntry.macAddr.arEther[3];
+		tmpMacEntry.macAddr.arEther[4] = atuEntry[i].atuEntry.macAddr.arEther[4];
+		tmpMacEntry.macAddr.arEther[5] = atuEntry[i].atuEntry.macAddr.arEther[5];
+
+		tmpMacEntry.DBNum = atuEntry[i].atuEntry.DBNum;
+
+		if((status = gfdbFindAtuMacEntry(dev,&tmpMacEntry,&found)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned "));
+			testDisplayStatus(status);
+			MSG_PRINT(("Entry to find : (%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						tmpMacEntry.macAddr.arEther[0],
+						tmpMacEntry.macAddr.arEther[1],
+						tmpMacEntry.macAddr.arEther[2],
+						tmpMacEntry.macAddr.arEther[3],
+						tmpMacEntry.macAddr.arEther[4],
+						tmpMacEntry.macAddr.arEther[5]));
+			return status;
+		}
+
+		if (found == GT_FALSE)
+		{
+			MSG_PRINT(("Cannot find the Entry : (%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						tmpMacEntry.macAddr.arEther[0],
+						tmpMacEntry.macAddr.arEther[1],
+						tmpMacEntry.macAddr.arEther[2],
+						tmpMacEntry.macAddr.arEther[3],
+						tmpMacEntry.macAddr.arEther[4],
+						tmpMacEntry.macAddr.arEther[5]));
+
+			testResult = GT_FAIL;
+			return testResult;
+		}
+
+		if(memcmp(&tmpMacEntry, &atuEntry[i].atuEntry, sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned wrong entry.\n"));
+			dumpMemory((char*)&tmpMacEntry,sizeof(GT_ATU_ENTRY));
+			MSG_PRINT(("Expecting:\n"));
+			dumpMemory((char*)&atuEntry[i].atuEntry,sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+		{	
+			if(((i & 0x3F) == 0) && (i != 0))
+				MSG_PRINT(("Compared %i ATU Entries.\n",i));
+		}
+	}
+
+	/*
+	 *	Entry State 0x7
+	 */
+
+	if((tmpAtuEntry = (ATU_ENTRY_INFO *)malloc(sizeof(ATU_ENTRY_INFO)*maxMacs)) == NULL)
+		return GT_FAIL;
+	gtMemSet(tmpAtuEntry,0,sizeof(ATU_ENTRY_INFO)*maxMacs);
+
+	MSG_PRINT(("Getting ATU List(%i).\n",maxMacs));
+	if((status=testFillUpAtu(dev,tmpAtuEntry,atuSize,dbNum,0xA0A0,GT_UC_DYNAMIC)) != GT_OK)
+	{
+		MSG_PRINT(("testFillUpAtu returned "));
+		testDisplayStatus(status);
+		free(tmpAtuEntry);
+		return status;
+	}
+	MSG_PRINT(("Writing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		if((status = gfdbAddMacEntry(dev,&tmpAtuEntry[i].atuEntry)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbAddMacEntry returned "));
+			testDisplayStatus(status);
+			free(tmpAtuEntry);
+			return status;
+		}
+	}
+
+	MSG_PRINT(("Comparing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		if ((i%4) == 0)
+			tmpSingleAtuEntry = &tmpAtuEntry[i+3];
+		else
+			tmpSingleAtuEntry = &atuEntry[i];
+
+		tmpMacEntry.macAddr.arEther[0] = tmpSingleAtuEntry->atuEntry.macAddr.arEther[0];
+		tmpMacEntry.macAddr.arEther[1] = tmpSingleAtuEntry->atuEntry.macAddr.arEther[1];
+		tmpMacEntry.macAddr.arEther[2] = tmpSingleAtuEntry->atuEntry.macAddr.arEther[2];
+		tmpMacEntry.macAddr.arEther[3] = tmpSingleAtuEntry->atuEntry.macAddr.arEther[3];
+		tmpMacEntry.macAddr.arEther[4] = tmpSingleAtuEntry->atuEntry.macAddr.arEther[4];
+		tmpMacEntry.macAddr.arEther[5] = tmpSingleAtuEntry->atuEntry.macAddr.arEther[5];
+		tmpMacEntry.DBNum = tmpSingleAtuEntry->atuEntry.DBNum;
+
+		if((status = gfdbFindAtuMacEntry(dev,&tmpMacEntry,&found)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned "));
+			testDisplayStatus(status);
+			MSG_PRINT(("Entry to find : (%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						tmpMacEntry.macAddr.arEther[0],
+						tmpMacEntry.macAddr.arEther[1],
+						tmpMacEntry.macAddr.arEther[2],
+						tmpMacEntry.macAddr.arEther[3],
+						tmpMacEntry.macAddr.arEther[4],
+						tmpMacEntry.macAddr.arEther[5]));
+			free(tmpAtuEntry);
+			return status;
+		}
+
+		if (found == GT_FALSE)
+		{
+			MSG_PRINT(("Cannot find the Entry : (%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						tmpMacEntry.macAddr.arEther[0],
+						tmpMacEntry.macAddr.arEther[1],
+						tmpMacEntry.macAddr.arEther[2],
+						tmpMacEntry.macAddr.arEther[3],
+						tmpMacEntry.macAddr.arEther[4],
+						tmpMacEntry.macAddr.arEther[5]));
+
+			free(tmpAtuEntry);
+			testResult = GT_FAIL;
+			return testResult;
+		}
+
+		if(memcmp(&tmpMacEntry, &(tmpSingleAtuEntry->atuEntry), sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned wrong entry.\n"));
+			dumpMemory((char*)&tmpMacEntry,sizeof(GT_ATU_ENTRY));
+			MSG_PRINT(("Expecting:\n"));
+			dumpMemory((char*)&(tmpSingleAtuEntry->atuEntry),sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+		{	
+			if(((i & 0x3F) == 0) && (i != 0))
+				MSG_PRINT(("Compared %i ATU Entries.\n",i));
+		}
+	}
+
+	/*
+	 *	Entry State 0xF
+	 */
+
+	MSG_PRINT(("Getting ATU List(%i).\n",maxMacs));
+	gtMemSet(atuEntry,0,sizeof(ATU_ENTRY_INFO)*maxMacs);
+	if((status=testFillUpAtu(dev,atuEntry,atuSize,dbNum,0xAA00,GT_UC_STATIC)) != GT_OK)
+	{
+		MSG_PRINT(("testFillUpAtu returned "));
+		testDisplayStatus(status);
+		free(tmpAtuEntry);
+		return status;
+	}
+
+	MSG_PRINT(("Writing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		if((status = gfdbAddMacEntry(dev,&atuEntry[i].atuEntry)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbAddMacEntry returned "));
+			testDisplayStatus(status);
+			free(tmpAtuEntry);
+			return status;
+		}
+	}
+
+	MSG_PRINT(("Comparing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		tmpMacEntry.macAddr.arEther[0] = atuEntry[i].atuEntry.macAddr.arEther[0];
+		tmpMacEntry.macAddr.arEther[1] = atuEntry[i].atuEntry.macAddr.arEther[1];
+		tmpMacEntry.macAddr.arEther[2] = atuEntry[i].atuEntry.macAddr.arEther[2];
+		tmpMacEntry.macAddr.arEther[3] = atuEntry[i].atuEntry.macAddr.arEther[3];
+		tmpMacEntry.macAddr.arEther[4] = atuEntry[i].atuEntry.macAddr.arEther[4];
+		tmpMacEntry.macAddr.arEther[5] = atuEntry[i].atuEntry.macAddr.arEther[5];
+
+		tmpMacEntry.DBNum = atuEntry[i].atuEntry.DBNum;
+
+		if((status = gfdbFindAtuMacEntry(dev,&tmpMacEntry,&found)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned "));
+			testDisplayStatus(status);
+			MSG_PRINT(("Entry to find : (%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						tmpMacEntry.macAddr.arEther[0],
+						tmpMacEntry.macAddr.arEther[1],
+						tmpMacEntry.macAddr.arEther[2],
+						tmpMacEntry.macAddr.arEther[3],
+						tmpMacEntry.macAddr.arEther[4],
+						tmpMacEntry.macAddr.arEther[5]));
+			free(tmpAtuEntry);
+			return status;
+		}
+
+		if (found == GT_FALSE)
+		{
+			MSG_PRINT(("Cannot find the Entry : (%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						tmpMacEntry.macAddr.arEther[0],
+						tmpMacEntry.macAddr.arEther[1],
+						tmpMacEntry.macAddr.arEther[2],
+						tmpMacEntry.macAddr.arEther[3],
+						tmpMacEntry.macAddr.arEther[4],
+						tmpMacEntry.macAddr.arEther[5]));
+
+			testResult = GT_FAIL;
+			free(tmpAtuEntry);
+			return testResult;
+		}
+
+		if(memcmp(&tmpMacEntry, &atuEntry[i].atuEntry, sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned wrong entry.\n"));
+			dumpMemory((char*)&tmpMacEntry,sizeof(GT_ATU_ENTRY));
+			MSG_PRINT(("Expecting:\n"));
+			dumpMemory((char*)&atuEntry[i].atuEntry,sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+		{	
+			if(((i & 0x3F) == 0) && (i != 0))
+				MSG_PRINT(("Compared %i ATU Entries.\n",i));
+		}
+	}
+
+	MSG_PRINT(("Writing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		if((status = gfdbAddMacEntry(dev,&tmpAtuEntry[i].atuEntry)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbAddMacEntry returned "));
+			testDisplayStatus(status);
+			free(tmpAtuEntry);
+			return status;
+		}
+	}
+
+	MSG_PRINT(("Comparing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+		tmpMacEntry.macAddr.arEther[0] = atuEntry[i].atuEntry.macAddr.arEther[0];
+		tmpMacEntry.macAddr.arEther[1] = atuEntry[i].atuEntry.macAddr.arEther[1];
+		tmpMacEntry.macAddr.arEther[2] = atuEntry[i].atuEntry.macAddr.arEther[2];
+		tmpMacEntry.macAddr.arEther[3] = atuEntry[i].atuEntry.macAddr.arEther[3];
+		tmpMacEntry.macAddr.arEther[4] = atuEntry[i].atuEntry.macAddr.arEther[4];
+		tmpMacEntry.macAddr.arEther[5] = atuEntry[i].atuEntry.macAddr.arEther[5];
+
+		tmpMacEntry.DBNum = atuEntry[i].atuEntry.DBNum;
+
+		if((status = gfdbFindAtuMacEntry(dev,&tmpMacEntry,&found)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned "));
+			testDisplayStatus(status);
+			MSG_PRINT(("Entry to find : (%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						tmpMacEntry.macAddr.arEther[0],
+						tmpMacEntry.macAddr.arEther[1],
+						tmpMacEntry.macAddr.arEther[2],
+						tmpMacEntry.macAddr.arEther[3],
+						tmpMacEntry.macAddr.arEther[4],
+						tmpMacEntry.macAddr.arEther[5]));
+			free(tmpAtuEntry);
+			return status;
+		}
+
+		if (found == GT_FALSE)
+		{
+			MSG_PRINT(("Cannot find the Entry : (%#x-%#x-%#x-%#x-%#x-%#x)\n",
+						tmpMacEntry.macAddr.arEther[0],
+						tmpMacEntry.macAddr.arEther[1],
+						tmpMacEntry.macAddr.arEther[2],
+						tmpMacEntry.macAddr.arEther[3],
+						tmpMacEntry.macAddr.arEther[4],
+						tmpMacEntry.macAddr.arEther[5]));
+
+			testResult = GT_FAIL;
+			free(tmpAtuEntry);
+			return testResult;
+		}
+
+		if(memcmp(&tmpMacEntry, &atuEntry[i].atuEntry, sizeof(GT_ATU_ENTRY)))
+		{
+			MSG_PRINT(("gfdbFindAtuMacEntry returned wrong entry.\n"));
+			dumpMemory((char*)&tmpMacEntry,sizeof(GT_ATU_ENTRY));
+			MSG_PRINT(("Expecting:\n"));
+			dumpMemory((char*)&atuEntry[i].atuEntry,sizeof(GT_ATU_ENTRY));
+
+			testResult = GT_FAIL;
+		}
+		else
+		{	
+			if(((i & 0x3F) == 0) && (i != 0))
+				MSG_PRINT(("Compared %i ATU Entries.\n",i));
+		}
+	}
+	
+	/* Flush all addresses from the ATU table. */
+	free(tmpAtuEntry);
+	MSG_PRINT(("Flush out all the entries in the ATU Table ... \n"));
+	if((status = gfdbFlush(dev,GT_FLUSH_ALL)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbFlush returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if(testResult == GT_OK)
+		MSG_PRINT(("PASSED with Atu Size %i\n", 256<<atuSize));
+	else
+		MSG_PRINT(("FAILED with Atu Size %i\n", 256<<atuSize));
+
+	return testResult;
+}
+
+GT_U32 testATU(GT_QD_DEV *dev)
+{
+	GT_STATUS testResult, status;
+	GT_U32 testResults = 0;
+	int arg, atuSize, sameMacs, dbNum, atuStart, atuEnd;
+	GT_BOOL dbNumSupport = GT_FALSE;
+
+	testResult = GT_OK;
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6051:
+		case GT_FF_EG:
+			dbNumSupport = GT_FALSE;
+			atuStart = ATU_SIZE_512;
+			atuEnd = ATU_SIZE_4096;
+			break;
+
+		case GT_88E6021:
+		case GT_88E6060:
+		case GT_88E6031:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6061:
+		case GT_88E6065:
+			/* dbNum test is not performed at this time */
+			dbNumSupport = GT_TRUE;
+			dbNumSupport = GT_FALSE;
+			atuStart = ATU_SIZE_256;
+			atuEnd = ATU_SIZE_2048;
+			break;
+
+		case GT_88E6052:
+		case GT_FF_HG:
+			dbNumSupport = GT_FALSE;
+			atuStart = ATU_SIZE_512;
+			atuEnd = ATU_SIZE_2048;
+			break;
+
+		case GT_88E6063:
+		case GT_FH_VPN:
+		case GT_88E6083:
+			/* dbNum test is not performed at this time */
+			dbNumSupport = GT_TRUE;
+			dbNumSupport = GT_FALSE;
+			atuStart = ATU_SIZE_512;
+			atuEnd = ATU_SIZE_2048;
+			break;
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+			/* dbNum test is not performed at this time */
+			dbNumSupport = GT_TRUE;
+			dbNumSupport = GT_FALSE;
+			atuStart = ATU_SIZE_4096;
+			atuEnd = ATU_SIZE_4096;
+			break;
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+			/* dbNum test is not performed at this time */
+			dbNumSupport = GT_TRUE;
+			dbNumSupport = GT_FALSE;
+			atuStart = ATU_SIZE_4096;
+			atuEnd = ATU_SIZE_8192;
+			break;
+		default:
+			MSG_PRINT(("Cannot run ATU test.(Unknown device)\n"));
+			return GT_FAIL;
+	}
+
+	switch (dev->deviceId)
+	{
+		case GT_88E6093:
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+				if(testATUSetup(dev) != GT_OK)
+					return GT_FAIL;
+		default:
+				break;
+	}
+
+	for(arg=0; arg<1; arg++)
+	{
+		for(atuSize=atuStart; atuSize<=atuEnd; atuSize++)
+		{
+			if(dbNumSupport == GT_TRUE)
+			{
+				dbNum = (64<<atuSize)/TEST_MAC_ENTRIES;
+				if (dbNum > 16)
+					dbNum = 16;
+			}
+			else
+				dbNum = 1;
+
+			for(sameMacs=0;sameMacs<=dbNum;sameMacs+=4)
+			{
+				MSG_PRINT(("Running ATU Test : arg %i, macEntries %i, dbNum %i, atuSize %i\n",
+							arg, TEST_MAC_ENTRIES, dbNum, 256 << atuSize));
+				if((status=testAtuDbNum(dev,arg,TEST_MAC_ENTRIES,dbNum,sameMacs,atuSize)) != GT_OK)
+				{
+					MSG_PRINT(("ATU Test Fail(%d), arg %i,dbNum %i,sameMacs %i,atuSize %i\n", 
+								status,arg,dbNum,sameMacs,256<<atuSize));
+					testResult = GT_FAIL;
+					testResults |= 1 << status;
+					break;
+				}
+				else
+				{
+					MSG_PRINT(("ATU Test Pass with arg %i\n", arg));
+				}
+				MSG_PRINT((" \n"));
+			}
+			if (testResult != GT_OK)
+				break;
+		}
+		if (testResult != GT_OK)
+			break;
+	}
+
+#if 0
+	MSG_PRINT(("Exercising Full ATU Table...\n"));
+	for(atuSize=atuStart; atuSize<=atuEnd; atuSize++)
+	{
+		if((status = testFilledATU(dev,atuSize,0)) != GT_OK)
+		{
+			testResults |= 1 << status;
+			testResult = GT_FAIL;
+		}
+		if(dbNumSupport == GT_TRUE)
+		{
+		  if((status = testFilledATU(dev,atuSize,15)) != GT_OK)
+		  {
+			testResults |= 1 << status;
+			testResult = GT_FAIL;
+		  }
+		}
+	}
+#endif
+
+	/* Sw Reset */
+	if((status=gsysSwReset(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSwReset returned Fail (%#x).\n", status));
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	return testResults;
+}
+
+
+GT_STATUS testATUStress(GT_QD_DEV *dev)
+{
+	GT_STATUS testResult, status;
+	int arg, atuSize, sameMacs, dbNum, maxDbNum, atuStart, atuEnd;
+	GT_BOOL dbNumSupport = GT_FALSE;
+
+	testResult = GT_OK;
+	maxDbNum = 16;
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6051:
+		case GT_FF_EG:
+			dbNumSupport = GT_FALSE;
+			atuStart = ATU_SIZE_512;
+			atuEnd = ATU_SIZE_4096;
+			break;
+
+		case GT_88E6021:
+		case GT_88E6060:
+		case GT_88E6031:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6061:
+		case GT_88E6065:
+			dbNumSupport = GT_TRUE;
+			atuStart = ATU_SIZE_256;
+			atuEnd = ATU_SIZE_2048;
+			break;
+
+		case GT_88E6052:
+		case GT_FF_HG:
+			dbNumSupport = GT_FALSE;
+			atuStart = ATU_SIZE_512;
+			atuEnd = ATU_SIZE_2048;
+			break;
+
+		case GT_88E6063:
+		case GT_FH_VPN:
+		case GT_88E6083:
+			dbNumSupport = GT_TRUE;
+			atuStart = ATU_SIZE_512;
+			atuEnd = ATU_SIZE_2048;
+			break;
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+			dbNumSupport = GT_TRUE;
+			atuStart = ATU_SIZE_4096;
+			atuEnd = ATU_SIZE_4096;
+			break;
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+			dbNumSupport = GT_TRUE;
+			maxDbNum = 256;
+			atuStart = ATU_SIZE_4096;
+			atuEnd = ATU_SIZE_4096;
+			break;
+		case GT_88E6131:
+		case GT_88E6108:
+			dbNumSupport = GT_TRUE;
+			maxDbNum = 256;
+			atuStart = ATU_SIZE_1024;
+			atuEnd = ATU_SIZE_1024;
+			break;
+		default:
+			MSG_PRINT(("Cannot run ATU test.(Unknown device)\n"));
+			return GT_FAIL;
+	}
+
+	for(arg=0; arg<3; arg++)
+	{
+		for(atuSize=atuStart; atuSize<=atuEnd; atuSize++)
+		{
+			if(dbNumSupport == GT_TRUE)
+			{
+				if(atuStart == atuEnd)
+				{
+					dbNum = maxDbNum;
+				}
+				else
+				{
+					dbNum = (64<<atuSize)/TEST_MAC_ENTRIES;
+					if (dbNum > maxDbNum)
+						dbNum = maxDbNum;
+				}
+			}
+			else
+				dbNum = 1;
+
+			for(sameMacs=0;sameMacs<=4;sameMacs+=2)
+			{
+				MSG_PRINT(("Running ATU Test: arg %i,macEntries %i,dbNum %i,atuSize %i,sameMac %i\n",
+							arg, TEST_MAC_ENTRIES, dbNum, 256 << atuSize, sameMacs));
+				if((status=testAtuDbNum(dev,arg,TEST_MAC_ENTRIES,dbNum,sameMacs,atuSize)) != GT_OK)
+				{
+					MSG_PRINT(("ATU Test Fail(%d), arg %i,dbNum %i,sameMacs %i,atuSize %i\n", 
+								status,arg,dbNum,sameMacs,256<< atuSize));
+					testResult = GT_FAIL;
+					break;
+				}
+				else
+				{
+					MSG_PRINT(("ATU Test Pass with arg %i\n", arg));
+				}
+				MSG_PRINT((" \n"));
+			}
+			if (testResult != GT_OK)
+				break;
+
+		}
+		if (testResult != GT_OK)
+			break;
+	}
+
+	MSG_PRINT(("Exercising Full ATU Table...\n"));
+	for(atuSize=atuStart; atuSize<=atuEnd; atuSize++)
+	{
+		if((status = testFilledATU(dev,atuSize,0)) != GT_OK)
+			testResult = GT_FAIL;
+		if((status = testFilledATU(dev,atuSize,maxDbNum-1)) != GT_OK)
+			testResult = GT_FAIL;
+	}
+
+	/* Sw Reset */
+	if((status=gsysSwReset(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSwReset returned Fail (%#x).\n", status));
+		return status;
+	}
+
+	return testResult;
+}
+
+
+/*******************************************************************************
+* testVlan
+*
+* DESCRIPTION:
+*       Testing Vlan related APIs. (Set/Get)
+*		(EgressMode, VlanTunnel, PortVlanPorts, PortUserPriLsb, and PortVid access)
+*		
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on fail
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U32 testVlan(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult, mapTest;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+	GT_LPORT port;
+	GT_LPORT portList[MAX_SWITCH_PORTS];
+	GT_LPORT tmpPortList[MAX_SWITCH_PORTS];
+	GT_LPORT orgPortList[MAX_SWITCH_PORTS];
+	GT_U8 i, portCount, orgCount, tmpCount;
+	int portIndex;
+
+	testResult = GT_OK;
+
+	/*
+	 *  Egress Mode
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gprtGetEgressMode;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gprtSetEgressMode;
+	if((status = testPortU32Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Egress Mode API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Vlan Tunnel
+	 */
+	testAPI.getFunc.port_bool = gprtGetVlanTunnel;
+	testAPI.setFunc.port_bool = gprtSetVlanTunnel;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Vlan Tunnel API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  user priority (VPT) LSB bit
+	 */
+	testAPI.getFunc.port_bool = gvlnGetPortUserPriLsb;
+	testAPI.setFunc.port_bool = gvlnSetPortUserPriLsb;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("user priority (VPT) LSB bit API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Port VID
+	 */
+	testAPI.getFunc.port_u16 = gvlnGetPortVid;
+	testAPI.setFunc.port_u16 = gvlnSetPortVid;
+	if((status = testPortU16Type(dev,&testAPI,7)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Port VID API test "));
+	testDisplayStatus(status);
+
+	/* Port Vlan Mapping */
+	mapTest = GT_OK;
+
+	portCount = (4 < (dev->numOfPorts-1))?4:(dev->numOfPorts-1);
+
+	for(portIndex=0; portIndex<portCount; portIndex++)
+		portList[portIndex] = portIndex;
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		if((status = gvlnGetPortVlanPorts(dev,port,orgPortList,&orgCount)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnGetPortVlanPorts returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gvlnSetPortVlanPorts(dev,port,portList,portCount)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnSetPortVlanPorts returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gvlnGetPortVlanPorts(dev,port,tmpPortList,&tmpCount)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnGetPortVlanPorts returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if (portCount != tmpCount)
+		{
+			MSG_PRINT(("gvlnGetPortVlanPorts returned wrong portCount(%i:%i).\n",portCount,tmpCount));
+			mapTest = GT_FAIL;
+			testResults |= 1 << mapTest;
+		}
+		
+		for(i=0; i<portCount; i++)
+		{
+			if(tmpPortList[i] != portList[i])
+			{
+				MSG_PRINT(("Returned wrong portList(i %d, port %d, should be port %d).\n"
+							,i,tmpPortList[i],portList[i]));
+				mapTest = GT_FAIL;
+				testResults |= 1 << mapTest;
+			}
+		}
+
+		if((status = gvlnSetPortVlanPorts(dev,port,orgPortList,orgCount)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnSetPortVlanPorts returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	}
+	if(mapTest != GT_OK)
+	{
+		MSG_PRINT(("VLAN MAP API Test Fail.\n"));
+		testResult = mapTest;
+	}
+	else
+		MSG_PRINT(("VLAN MAP API Test Pass.\n"));
+
+#ifdef DEBUG_FEATURE 
+	/*
+	 *  Port DBNum
+	 */
+	testAPI.getFunc.port_u8 = gvlnGetPortVlanDBNum;
+	testAPI.setFunc.port_u8 = gvlnSetPortVlanDBNum;
+	if((status = testPortU8Type(dev,&testAPI,16)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Port DBNum API test "));
+	testDisplayStatus(status);
+#endif
+
+	/*
+	 *  Port Vlan 802.1Q Mode
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gvlnGetPortVlanDot1qMode;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gvlnSetPortVlanDot1qMode;
+	if((status = testPortU32Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Port 802.1Q Mode API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Force Default VID
+	 */
+	testAPI.getFunc.port_bool = gvlnGetPortVlanForceDefaultVID;
+	testAPI.setFunc.port_bool = gvlnSetPortVlanForceDefaultVID;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Force Default VID API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Force MAP
+	 */
+	testAPI.getFunc.port_bool = gvlnGetForceMap;
+	testAPI.setFunc.port_bool = gvlnSetForceMap;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Force MAP API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+
+}
+
+/*******************************************************************************
+* testSTP
+*
+* DESCRIPTION:
+*       Test STP(Spanning Tree Protocol) related APIs
+*		
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on fail
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U32 testSTP(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult, sectionResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+
+	testResult = sectionResult = GT_OK;
+
+	/*
+	 *	STP Port State
+	 */
+	testAPI.getFunc.port_u32 = (GT_API_GET_PORT_U32)gstpGetPortState;
+	testAPI.setFunc.port_u32 = (GT_API_SET_PORT_U32)gstpSetPortState;
+	if((status = testPortU32Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("STP Port State API test "));
+	testDisplayStatus(status);
+
+	return testResults;
+}
+
+
+GT_U32 testPhy1(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	GT_LPORT port;
+	GT_U16 u16Data, tmpData;
+	GT_PHY_AUTO_MODE mode;
+	int portIndex, nPhys;
+	GT_BOOL state;
+	GT_PHY_PAUSE_MODE pause_state;
+	GT_PHY_SPEED speed;
+
+	testResult = GT_OK;
+	switch(dev->numOfPorts)
+	{
+		case 3:
+			nPhys = 2;
+			break;
+		default:
+			nPhys = 5;
+			break;
+	}
+
+	for(portIndex=0; portIndex<nPhys; portIndex++)
+	{
+		port = portIndex;
+		
+		if(port == dev->cpuPortNum)
+			continue;
+
+		/* Test Reset API */
+		MSG_PRINT(("Reset Phy (port %i).\n",port));
+		if((status = gprtPhyReset(dev,port)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPhyReset returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gprtGetPhyReg(dev,port,0,&u16Data) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPhyReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(!(u16Data & 0x1000))
+		{
+			MSG_PRINT(("gprtPhyReset failed.\n"));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Reset, Phy (port %i) Reg 0 : %#x.\n",port,u16Data));
+
+
+		/* 
+		 *  Set AutoNego disable, LoopBack enable, 100Mbps, Duplex On,
+		 */
+		if((status = gprtPortAutoNegEnable(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortAutoNegEnable returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	   	 if(gprtGetPortAutoNegState(dev,port,&state) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortAutoNegState returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+		 
+		if((status = gprtSetPortLoopback(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortLoopback returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtGetPortLoopback(dev,port,&state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortLoopback returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtSetPortSpeed(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtGetPortSpeed(dev,port,&speed)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		
+		if((status = gprtSetPortDuplexMode(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortDuplexMode returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gprtGetPhyReg(dev,port,0,&u16Data) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPhyReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(0x6100 != (u16Data & 0x6100))
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x6100).\n", u16Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+		{
+			if(u16Data & 0x1000)
+			{
+				MSG_PRINT(("Set Failed (%#x, should be 0x6100).\n", u16Data));
+				testResults |= 1 << GT_FAIL;
+				testResult = GT_FAIL;
+			}
+			else
+				MSG_PRINT(("After Loopback and 100Full, Phy (port %i) Reg 0 : %#x.\n",port,u16Data));
+		}
+
+		/* 
+		 *  Set 10Mbps, Half Duplex.
+		 */
+		if((status = gprtSetPortLoopback(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortLoopback returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtGetPortLoopback(dev,port,&state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortLoopback returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}		
+		
+		if((status = gprtSetPortSpeed(dev,port,PHY_SPEED_10_MBPS)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtGetPortSpeed(dev,port,&speed)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		
+		if((status = gprtSetPortDuplexMode(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortDuplexMode returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gprtGetPhyReg(dev,port,0,&u16Data) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPhyReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(u16Data != 0x0000)
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x0000).\n", u16Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After 10Half, Phy (port %i) Reg 0 : %#x.\n",port,u16Data));
+
+		/* 
+		 *  Set Power Down
+		 */
+		if((status = gprtPortPowerDown(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortPowerDown returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		/*
+		 * Get PHY port Power State
+		*/
+		if((status = gprtGetPortPowerDown(dev,port,&state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortPowerDown returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}	
+		
+	    if(gprtGetPhyReg(dev,port,0,&u16Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* Power Down bit should be set. */
+		if(!(u16Data & 0x0800))
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x0800).\n", u16Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After PowerDown, Phy (port %i) Reg 0 : %#x.\n",port,u16Data));
+
+		/* 
+		 *  Set Power Up
+		 */
+		if((status = gprtPortPowerDown(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortPowerDown returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		/*
+		 * Get PHY port Power State
+		*/
+		if((status = gprtGetPortPowerDown(dev,port,&state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortPowerDown returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+	    if(gprtGetPhyReg(dev,port,0,&u16Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After power up, Power Down bit should be cleared.*/
+		if(u16Data &= 0x0800)
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x0000).\n", u16Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Power back up, Phy (port %i) Reg 0 : %#x.\n",port,u16Data));
+
+		/* 
+		 *  Set Autonego and Restart AutoNego.
+		 */
+		if((status = gprtPortAutoNegEnable(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortAutoNegEnable returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	   	 if(gprtGetPortAutoNegState(dev,port,&state) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortAutoNegState returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+		 
+		if((status = gprtPortRestartAutoNeg(dev,port)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortRestartAutoNeg returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gprtGetPhyReg(dev,port,0,&u16Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(!(u16Data & 0x1000))
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x1000).\n", u16Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Auto, Phy (port %i) Reg 0 : %#x.\n",port,u16Data));
+
+
+		/*
+		 *	Enable PAUSE
+		*/
+		if((status = gprtSetPause(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		if((status = gprtGetPause(dev,port,&pause_state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}		
+
+	    if(gprtGetPhyReg(dev,port,4,&u16Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(!(u16Data & 0x400))
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x400).\n", u16Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Pause set, Phy (port %i) Reg 4 : %#x.\n",port,u16Data));
+
+		/*
+		 *	Disable PAUSE
+		*/
+		if((status = gprtSetPause(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		if((status = gprtGetPause(dev,port,&pause_state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gprtGetPhyReg(dev,port,4,&u16Data) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPhyReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(u16Data & 0x400)
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x00).\n", u16Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Pause reset, Phy (port %i) Reg 4 : %#x.\n",port,u16Data));
+
+		/*
+		 *	Disable PAUSE
+		*/
+		for(mode=SPEED_AUTO_DUPLEX_AUTO;mode<=SPEED_AUTO_DUPLEX_HALF;mode++)
+		{
+			switch(mode)
+			{
+				case SPEED_1000_DUPLEX_AUTO:
+				case SPEED_1000_DUPLEX_FULL:
+				case SPEED_1000_DUPLEX_HALF:
+						continue;
+				default:
+						break;
+			}
+
+			if((status = gprtSetPortAutoMode(dev,port,mode)) != GT_OK)
+			{
+				MSG_PRINT(("gprtSetPortAutoMode returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+
+			/* Autonego should be enabled. */
+	    	if(gprtGetPhyReg(dev,port,0,&u16Data) != GT_OK)
+			{
+				MSG_PRINT(("gprtGetPhyReg returned Fail.\n"));
+				testResults |= 1 << GT_FAIL;
+				return testResults;
+			}
+
+			/* After reset AutoNego should be enabled. */
+			if(!(u16Data & 0x1000))
+			{
+				MSG_PRINT(("Set Failed (%#x, should be 0x1000).\n", u16Data));
+				testResults |= 1 << GT_FAIL;
+				testResult = GT_FAIL;
+			}
+			else
+			{
+		    	if(gprtGetPhyReg(dev,port,4,&u16Data) != GT_OK)
+				{
+					MSG_PRINT(("gprtGetPhyReg returned Fail.\n"));
+					testResults |= 1 << GT_FAIL;
+					return testResults;
+				}
+
+				switch(mode)
+				{
+					case SPEED_AUTO_DUPLEX_AUTO:
+							tmpData = 0x1e0;
+							break;
+					case SPEED_100_DUPLEX_AUTO:
+							tmpData = 0x180;
+							break;
+					case SPEED_10_DUPLEX_AUTO:
+							tmpData = 0x060;
+							break;
+					case SPEED_AUTO_DUPLEX_FULL:
+							tmpData = 0x140;
+							break;
+					case SPEED_AUTO_DUPLEX_HALF:
+							tmpData = 0x0a0;
+							break;
+					default:
+							tmpData = 0;
+							break;
+				}
+
+				if((u16Data & 0x1e0) != tmpData)
+				{
+					MSG_PRINT(("Set AutoMode(%i) Failed (%#x, should be %#x).\n", mode,u16Data,tmpData));
+					testResult = GT_FAIL;
+					testResults |= 1 << GT_FAIL;
+				}
+				else
+					MSG_PRINT(("After Mode(%d) set, Phy (port %i) Reg 4 : %#x.\n",mode,port,u16Data));
+
+			}
+		}
+
+
+	}
+	return testResults;
+}
+
+GT_U32 testPhy2(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	GT_LPORT port;
+	GT_U32 u32Data, tmpData;
+	GT_PHY_AUTO_MODE mode;
+	int portIndex, nPhys;
+	GT_BOOL state;
+	GT_PHY_PAUSE_MODE pause_state;
+	GT_PHY_SPEED speed;
+
+	testResult = GT_OK;
+	switch(dev->numOfPorts)
+	{
+		case 3:
+			nPhys = 2;
+			break;
+		default:
+			nPhys = 5;
+			break;
+	}
+
+	for(portIndex=0; portIndex<nPhys; portIndex++)
+	{
+		port = portIndex;
+		
+		if(port == dev->cpuPortNum)
+			continue;
+
+		/* Test Reset API */
+		MSG_PRINT(("Reset Phy (port %i).\n",port));
+		if((status = gprtPhyReset(dev,port)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPhyReset returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gsysReadMiiReg(dev, dev->baseRegAddr+port,0,&u32Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(!(u32Data & 0x1000))
+		{
+			MSG_PRINT(("gprtPhyReset failed.\n"));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Reset, Phy (port %i) Reg 0 : %#x.\n",port,u32Data));
+
+
+		/* 
+		 *  Set AutoNego disable, LoopBack enable, 100Mbps, Duplex On,
+		 */
+		if((status = gprtPortAutoNegEnable(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortAutoNegEnable returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	   	 if(gprtGetPortAutoNegState(dev,port,&state) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortAutoNegState returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+		 
+		if((status = gprtSetPortLoopback(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortLoopback returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtGetPortLoopback(dev,port,&state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortLoopback returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}		
+		
+		if((status = gprtSetPortSpeed(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtGetPortSpeed(dev,port,&speed)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		
+		if((status = gprtSetPortDuplexMode(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortDuplexMode returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gsysReadMiiReg(dev, dev->baseRegAddr+port,0,&u32Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(0x6100 != (u32Data & 0x6100))
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x6100).\n", u32Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+		{
+			if(u32Data & 0x1000)
+			{
+				MSG_PRINT(("Set Failed (%#x, should be 0x6100).\n", u32Data));
+				testResults |= 1 << GT_FAIL;
+				testResult = GT_FAIL;
+			}
+			else
+				MSG_PRINT(("After Loopback and 100Full, Phy (port %i) Reg 0 : %#x.\n",port,u32Data));
+		}
+
+		/* 
+		 *  Set 10Mbps, Half Duplex.
+		 */
+		if((status = gprtSetPortLoopback(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortLoopback returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtGetPortLoopback(dev,port,&state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortLoopback returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}		
+		
+		if((status = gprtSetPortSpeed(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gprtGetPortSpeed(dev,port,&speed)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		
+		if((status = gprtSetPortDuplexMode(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortDuplexMode returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gsysReadMiiReg(dev,dev->baseRegAddr+port,0,&u32Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(u32Data != 0x0000)
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x0000).\n", u32Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After 10Half, Phy (port %i) Reg 0 : %#x.\n",port,u32Data));
+
+		/* 
+		 *  Set Power Down
+		 */
+		if((status = gprtPortPowerDown(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortPowerDown returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		/*
+		 * Get PHY port Power State
+		*/
+		if((status = gprtGetPortPowerDown(dev,port,&state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortPowerDown returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}			
+
+	    if(gsysReadMiiReg(dev,dev->baseRegAddr+port,0,&u32Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* Power Down bit should be set. */
+		if(!(u32Data & 0x0800))
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x0800).\n", u32Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After PowerDown, Phy (port %i) Reg 0 : %#x.\n",port,u32Data));
+
+		/* 
+		 *  Set Power Up
+		 */
+		if((status = gprtPortPowerDown(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortPowerDown returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		/*
+		 * Get PHY port Power State
+		*/
+		if((status = gprtGetPortPowerDown(dev,port,&state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortPowerDown returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+	    if(gsysReadMiiReg(dev,dev->baseRegAddr+port,0,&u32Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After power up, Power Down bit should be cleared.*/
+		if(u32Data &= 0x0800)
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x0000).\n", u32Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Power back up, Phy (port %i) Reg 0 : %#x.\n",port,u32Data));
+
+		/* 
+		 *  Set Autonego and Restart AutoNego.
+		 */
+		if((status = gprtPortAutoNegEnable(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortAutoNegEnable returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	   	 if(gprtGetPortAutoNegState(dev,port,&state) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortAutoNegState returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+		 
+		if((status = gprtPortRestartAutoNeg(dev,port)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPortRestartAutoNeg returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+	    if(gsysReadMiiReg(dev,dev->baseRegAddr+port,0,&u32Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(!(u32Data & 0x1000))
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x1000).\n", u32Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Auto, Phy (port %i) Reg 0 : %#x.\n",port,u32Data));
+
+
+		/*
+		 *	Enable PAUSE
+		*/
+		if((status = gprtSetPause(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		if((status = gprtGetPause(dev,port,&u16Data)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+	    if(gsysReadMiiReg(dev,dev->baseRegAddr+port,4,&u32Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(!(u32Data & 0x400))
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x400).\n", u32Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Pause set, Phy (port %i) Reg 4 : %#x.\n",port,u32Data));
+
+		/*
+		 *	Disable PAUSE
+		*/
+		if((status = gprtSetPause(dev,port,GT_FALSE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		if((status = gprtGetPause(dev,port,&pause_state)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+	    if(gsysReadMiiReg(dev,dev->baseRegAddr+port,4,&u32Data) != GT_OK)
+		{
+			MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+			testResults |= 1 << GT_FAIL;
+			return testResults;
+		}
+
+		/* After reset AutoNego should be enabled. */
+		if(u32Data & 0x400)
+		{
+			MSG_PRINT(("Set Failed (%#x, should be 0x00).\n", u32Data));
+			testResults |= 1 << GT_FAIL;
+			testResult = GT_FAIL;
+		}
+		else
+			MSG_PRINT(("After Pause reset, Phy (port %i) Reg 4 : %#x.\n",port,u32Data));
+
+		/*
+		 *	Disable PAUSE
+		*/
+		for(mode=SPEED_AUTO_DUPLEX_AUTO;mode<=SPEED_AUTO_DUPLEX_HALF;mode++)
+		{
+			if((status = gprtSetPortAutoMode(dev,port,mode)) != GT_OK)
+			{
+				MSG_PRINT(("gprtSetPortAutoMode returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+
+			/* Autonego should be enabled. */
+	    	if(gsysReadMiiReg(dev,dev->baseRegAddr+port,0,&u32Data) != GT_OK)
+			{
+				MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+				testResults |= 1 << GT_FAIL;
+				return testResults;
+			}
+
+			/* After reset AutoNego should be enabled. */
+			if(!(u32Data & 0x1000))
+			{
+				MSG_PRINT(("Set Failed (%#x, should be 0x1000).\n", u32Data));
+				testResults |= 1 << GT_FAIL;
+				testResult = GT_FAIL;
+			}
+			else
+			{
+		    	if(gsysReadMiiReg(dev,dev->baseRegAddr+port,4,&u32Data) != GT_OK)
+				{
+					MSG_PRINT(("gsysReadMiiReg returned Fail.\n"));
+					testResults |= 1 << GT_FAIL;
+					return testResults;
+				}
+
+				switch(mode)
+				{
+					case SPEED_AUTO_DUPLEX_AUTO:
+							tmpData = 0x1e0;
+							break;
+					case SPEED_100_DUPLEX_AUTO:
+							tmpData = 0x180;
+							break;
+					case SPEED_10_DUPLEX_AUTO:
+							tmpData = 0x060;
+							break;
+					case SPEED_AUTO_DUPLEX_FULL:
+							tmpData = 0x140;
+							break;
+					case SPEED_AUTO_DUPLEX_HALF:
+							tmpData = 0x0a0;
+							break;
+					default:
+							tmpData = 0;
+							break;
+				}
+
+				if((u32Data & 0x1e0) != tmpData)
+				{
+					MSG_PRINT(("Set AutoMode(%i) Failed (%#x, should be %#x).\n", mode,u32Data,tmpData));
+					testResult = GT_FAIL;
+					testResults |= 1 << GT_FAIL;
+				}
+				else
+					MSG_PRINT(("After Mode(%d) set, Phy (port %i) Reg 4 : %#x.\n",mode,port,u32Data));
+
+			}
+		}
+
+
+	}
+	return testResults;
+}
+
+GT_U32 testPhy(GT_QD_DEV *dev)
+{
+	switch(dev->deviceId)
+	{
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+			MSG_PRINT(("Not Implemented.\n"));
+			break;
+		default:
+			return testPhy1(dev);	
+	}
+	return 0;
+}
+
+GT_STATUS readStatistics(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_LPORT port;
+	GT_PORT_STAT portStat;
+
+	MSG_PRINT(("Current Port Statistics\n"));
+	for (port=0; port<dev->numOfPorts; port++)
+	{
+		if((status = gprtGetPortCtr(dev,port,&portStat)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortCtr returned fail.\n"));
+			return status;
+		}
+
+		MSG_PRINT(("Port %i : Rx %i, Tx %i.\n",port,portStat.rxCtr,portStat.txCtr));
+	}
+
+	MSG_PRINT(("After Clear Port Statistics\n"));
+	for (port=0; port<dev->numOfPorts; port++)
+	{
+		if((status = gprtClearAllCtr(dev)) != GT_OK)
+		{
+			MSG_PRINT(("gprtClearAllCtr returned fail.\n"));
+			return status;
+		}
+
+		if((status = gprtGetPortCtr(dev,port,&portStat)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortCtr returned fail.\n"));
+			return status;
+		}
+
+		MSG_PRINT(("Port %i : Rx %i, Tx %i.\n",port,portStat.rxCtr,portStat.txCtr));
+	}
+	return GT_OK;
+}
+
+GT_STATUS testGoodPkt(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+
+	if((status = gprtSetCtrMode(dev,GT_CTR_ALL)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetCtrMode returned fail.\n"));
+		return status;
+	}
+	return GT_OK;
+}
+
+GT_STATUS testBadPkt(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+
+	if((status = gprtSetCtrMode(dev,GT_CTR_ERRORS)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetCtrMode returned fail.\n"));
+		return status;
+	}
+	return GT_OK;
+}
+
+
+GT_U32 testPortStatus(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	GT_LPORT port;
+	GT_BOOL mode;
+	GT_U32	u32Mode;
+	GT_U16	u16Mode;
+	int portIndex;
+
+	testResult = GT_OK;
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+		
+		MSG_PRINT(("Port %i :\n",port));
+
+		if((status = gprtGetPartnerLinkPause(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPartnerLinkPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("His Link Pause : %i    ",(int)mode));
+
+		if((status = gprtGetSelfLinkPause(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetSelfLinkPause returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("My Link Pause  : %i\n",(int)mode));
+
+		if((status = gprtGetLinkState(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetLinkState returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("Link Status    : %i    ",(int)mode));
+
+		if((status = gprtGetResolve(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetResolve returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("Resolve        : %i\n",(int)mode));
+
+		if((status = gprtGetPortMode(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPortMode returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("Port Mode      : %i    ",(int)mode));
+
+		if((status = gprtGetPhyMode(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPhyMode returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("Phy Mode       : %i\n",(int)mode));
+
+		if((status = gprtGetSpeed(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetSpeed returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("Port Speed     : %i    ",(int)mode));
+
+		if((status = gprtGetDuplex(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetDuplex returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("Port Duplex    : %i\n",(int)mode));
+
+		MSG_PRINT(("Setting Port Duplex : %i\n",1-(int)mode));
+		if((status = gprtSetDuplex(dev,port,1-mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetDuplex returned "));
+			testDisplayStatus(status);
+			switch(dev->deviceId)
+			{
+				case GT_88E6021:
+					if(port != dev->cpuPortNum)
+						break;
+					else
+					{
+						testResults |= 1 << status;
+						if(status == GT_FAIL)
+						return testResults;
+					}
+				case GT_88E6051:
+				case GT_88E6052:
+				case GT_FF_HG:
+				case GT_FF_EG:
+					break;
+				case GT_88E6063:
+				case GT_FH_VPN:
+					if(port < 5)
+						break;
+					else
+					{
+						testResults |= 1 << status;
+						if(status == GT_FAIL)
+						return testResults;
+					}
+					break;
+				default:
+					break;
+			}
+
+		}
+		else
+		{
+			GT_BOOL tmpMode;
+			if((status = gprtGetDuplex(dev,port,&tmpMode)) != GT_OK)
+			{
+				MSG_PRINT(("gprtGetDuplex returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+			if(tmpMode != (1-mode))
+			{
+				MSG_PRINT(("Setting Port Duplex Failed (current mode %i)\n",tmpMode));
+				testResults |= 1 << GT_FAIL;
+				testResult = GT_FAIL;
+			}
+			else
+				MSG_PRINT(("Setting Port Duplex Passed.\n"));
+
+			MSG_PRINT(("Setting Port Duplex : %i\n",mode));
+			if((status = gprtSetDuplex(dev,port,mode)) != GT_OK)
+			{
+				MSG_PRINT(("gprtSetDuplex returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				if(status == GT_FAIL)
+					return testResults;
+			}
+
+			if((status = gprtGetDuplex(dev,port,&tmpMode)) != GT_OK)
+			{
+				MSG_PRINT(("gprtGetDuplex returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+			if(tmpMode != mode)
+			{
+				MSG_PRINT(("Setting Port Duplex Failed (current mode %i)\n",tmpMode));
+				testResult = GT_FAIL;
+				testResults |= 1 << GT_FAIL;
+			}
+			else
+				MSG_PRINT(("Setting Port Duplex Passed.\n"));
+
+		}
+
+		if((status = gprtGetTxPaused(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetTxPaused returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("TxPaused       : %i    ",(int)mode));
+
+		if((status = gprtGetFlowCtrl(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetFlowCtrl returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("FlowCtrl       : %i\n",(int)mode));
+
+		if((status = gprtGetPxMode(dev,port,&u32Mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetPxMode returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("PxMode         : %i    ",(int)u32Mode));
+
+		if((status = gprtGetMiiInterface(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetMiiInterface returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("Mii Interface  : %i\n",(int)mode));
+
+		if((status = gprtGetHdFlowDis(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetHdFlowDis returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("HD Flow Dis.   : %i    ",(int)mode));
+
+		if((status = gprtGetFdFlowDis(dev,port,&mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetFdFlowDis returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("FD Flow Dis.   : %i\n",(int)mode));
+
+		if((status = gprtGetOutQSize(dev,port,&u16Mode)) != GT_OK)
+		{
+			MSG_PRINT(("gprtGetOutQSize returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+		MSG_PRINT(("Out Q Size     : %i\n",(int)u16Mode));
+
+	}
+
+	return testResults;
+}
+
+GT_U32 testQoSRule(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	TEST_API testAPI;
+
+	testResult = GT_OK;
+
+	/*
+	 *  Priority Map Rule (IEEE if Both IEEE and IP)
+	 */
+	testAPI.getFunc.port_bool = gqosGetPrioMapRule;
+	testAPI.setFunc.port_bool = gqosSetPrioMapRule;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Priority Map Rule API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  IP Priority Map Rule (use IP)
+	 */
+	testAPI.getFunc.port_bool = gqosGetIpPrioMapEn;
+	testAPI.setFunc.port_bool = gqosIpPrioMapEn;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("IP Priority Map Rule API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  IEEE Priority Map Rule (use IEEE Tag)
+	 */
+	testAPI.getFunc.port_bool = gqosGetUserPrioMapEn;
+	testAPI.setFunc.port_bool = gqosUserPrioMapEn;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("IEEE Priority Map Rule API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  VID FPri Override
+	 */
+	testAPI.getFunc.port_bool = gqosGetVIDFPriOverride;
+	testAPI.setFunc.port_bool = gqosSetVIDFPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("VID FPri Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  SA FPri Override
+	 */
+	testAPI.getFunc.port_bool = gqosGetSAFPriOverride;
+	testAPI.setFunc.port_bool = gqosSetSAFPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("SA FPri Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DA FPri Override
+	 */
+	testAPI.getFunc.port_bool = gqosGetDAFPriOverride;
+	testAPI.setFunc.port_bool = gqosSetDAFPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DA FPri Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  VID QPri Override
+	 */
+	testAPI.getFunc.port_bool = gqosGetVIDQPriOverride;
+	testAPI.setFunc.port_bool = gqosSetVIDQPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("VID QPri Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  SA QPri Override
+	 */
+	testAPI.getFunc.port_bool = gqosGetSAQPriOverride;
+	testAPI.setFunc.port_bool = gqosSetSAQPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("SA QPri Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  DA QPri Override
+	 */
+	testAPI.getFunc.port_bool = gqosGetDAQPriOverride;
+	testAPI.setFunc.port_bool = gqosSetDAQPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("DA QPri Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  ARP QPri Override
+	 */
+	testAPI.getFunc.port_bool = gqosGetARPQPriOverride;
+	testAPI.setFunc.port_bool = gqosSetARPQPriOverride;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("ARP QPri Override API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Force QPri
+	 */
+	testAPI.getFunc.port_bool = gqosGetForceQPri;
+	testAPI.setFunc.port_bool = gqosSetForceQPri;
+	if((status = testPortBoolType(dev,&testAPI)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Force QPri API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  QPri Value
+	 */
+	testAPI.getFunc.port_u8 = gqosGetQPriValue;
+	testAPI.setFunc.port_u8 = gqosSetQPriValue;
+	if((status = testPortU8Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("QPri Value API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  Default FPri Value
+	 */
+	testAPI.getFunc.port_u8 = gqosGetDefFPri;
+	testAPI.setFunc.port_u8 = gqosSetDefFPri;
+	if((status = testPortU8Type(dev,&testAPI,8)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Default FPri Value API test "));
+	testDisplayStatus(status);
+
+	/*
+	 *  ARP QPri Value
+	 */
+	testAPI.getFunc.u16 = (GT_API_GET_U16)gqosGetArpQPri;
+	testAPI.setFunc.u16 = (GT_API_SET_U16)gqosSetArpQPri;
+	if((status = testU16Type(dev,&testAPI,4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("ARP QPri Value API test "));
+	testDisplayStatus(status);
+
+
+	return testResults;
+}
+
+GT_U32 testQoSMapG(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult, sectionResult;
+	GT_U32 testResults = 0;
+	GT_U8 priority, remapped, tmpPri;
+	GT_LPORT port;
+	int portIndex;
+
+	testResult = sectionResult = GT_OK;
+
+	for(priority=0; priority<8; priority++)
+	{
+		remapped = 7 - priority;
+
+		for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+		{
+			port = portIndex;
+					
+			if((status = gqosSetTagRemap(dev,portIndex, priority, remapped)) != GT_OK)
+			{
+				MSG_PRINT(("gqosSetTagRemap returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+
+			tmpPri = 8;
+			if((status = gqosGetTagRemap(dev,portIndex, priority, &tmpPri)) != GT_OK)
+			{
+				MSG_PRINT(("gqosGetTagRemap returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+
+			if (tmpPri != remapped)
+			{
+				MSG_PRINT(("QoS Remapping setup problem (pri:%#x,remap:%#x,port).\n",priority, remapped, port));
+				sectionResult = GT_FAIL;
+				testResults |= 1 << GT_FAIL;
+			}
+		}
+	}
+
+	if(sectionResult == GT_OK)
+	{
+		MSG_PRINT(("QoS Remapping setup Pass.\n"));
+	}
+	else
+	{
+		MSG_PRINT(("Qos Remapping setup Fail.\n"));
+		testResult = sectionResult;
+		sectionResult = GT_OK;
+	}
+
+	return testResults;
+}
+
+GT_U32 testQoSMap(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult, sectionResult;
+	GT_U32 testResults = 0;
+	GT_U8 priority, trClass;
+	TEST_API testAPI;
+
+	testResult = sectionResult = GT_OK;
+
+	/*
+	 *  Default Traffic Class Map
+	 */
+	testAPI.getFunc.port_u8 = gcosGetPortDefaultTc;
+	testAPI.setFunc.port_u8 = gcosSetPortDefaultTc;
+	if((status = testPortU8Type(dev,&testAPI, 4)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Default Traffic Class Setup "));
+	testDisplayStatus(status);
+
+	for(priority=0; priority<8; priority++)
+	{
+		if((status = gcosSetUserPrio2Tc(dev,priority,(priority&0x3))) != GT_OK)
+		{
+			MSG_PRINT(("gcosSetUserPrio2Tc returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gcosGetUserPrio2Tc(dev,priority,&trClass)) != GT_OK)
+		{
+			MSG_PRINT(("gcosSetUserPrio2Tc returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if (trClass != (priority&0x3))
+		{
+			MSG_PRINT(("IEEE traffic Class setup problem (tr:%#x,pr:%#x).\n",trClass,priority));
+			sectionResult = GT_FAIL;
+			testResults |= 1 << GT_FAIL;
+		}
+	}
+
+	if(sectionResult == GT_OK)
+	{
+		MSG_PRINT(("IEEE traffic Class setup Pass.\n"));
+	}
+	else
+	{
+		MSG_PRINT(("IEEE traffic Class setup Fail.\n"));
+		testResult = sectionResult;
+		sectionResult = GT_OK;
+	}
+
+	for(priority=0; priority<0x40; priority++)
+	{
+		if((status = gcosSetDscp2Tc(dev,priority,(priority&0x3))) != GT_OK)
+		{
+			MSG_PRINT(("gcosSetDscp2Tc returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gcosGetDscp2Tc(dev,priority,&trClass)) != GT_OK)
+		{
+			MSG_PRINT(("gcosGetDscp2Tc returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if (trClass != (priority&0x3))
+		{
+			MSG_PRINT(("IP traffic Class setup problem (tr:%#x,pr:%#x).\n",trClass,priority));
+			sectionResult = GT_FAIL;
+			testResults |= 1 << GT_FAIL;
+		}
+	}
+	if(sectionResult == GT_OK)
+	{
+		MSG_PRINT(("IP traffic Class setup Pass.\n"));
+	}
+	else
+	{
+		MSG_PRINT(("IP traffic Class setup Fail.\n"));
+		testResult = sectionResult;
+		sectionResult = GT_OK;
+	}
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6065:
+			testResults |= testQoSMapG(dev);
+			break;
+		default:
+			break;
+	}			
+	return testResults;
+}
+
+
+GT_U32 testInterrupt(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult;
+	GT_U32 testResults = 0;
+	GT_LPORT port;
+	GT_U16 data, portIntCause, phyIntCause, tmpData;
+	int portIndex, phyCount;
+
+	MSG_PRINT(("\ntesting Interrupt Handler : \n"));
+
+	testResult = GT_OK;
+
+	MSG_PRINT(("\nSetting up Interrupt Test...\n"));
+
+	/* Enable QuarterDeck interrupt for ATUFull, ATUDone, PHYInt, and EEInt */
+	data = GT_ATU_FULL|GT_ATU_DONE|GT_PHY_INTERRUPT|GT_EE_INTERRUPT;
+	if((status = eventSetActive(dev,data)) != GT_OK)
+	{
+		MSG_PRINT(("eventSetActive returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	/* 
+	 Enable Phy interrupt for Link Status Change, Speed Change,
+	 *	AutoNego Complete, and Duplex Changed for all phys.
+	*/
+	data = GT_SPEED_CHANGED|GT_DUPLEX_CHANGED|GT_AUTO_NEG_COMPLETED|GT_LINK_STATUS_CHANGED;
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6021:
+			phyCount = 2;
+			break;
+		case GT_88E6051:
+			phyCount = 4;
+			break;
+		case GT_88E6052:
+		case GT_88E6063:
+		case GT_FF_HG:
+		case GT_FF_EG:
+		case GT_FH_VPN:
+			phyCount = 5;
+			break;
+		default:
+			MSG_PRINT(("Unknown DEVICE. Assuming 88E6052.\n"));
+			phyCount = 5;
+			break;
+	}
+
+	for(portIndex=0; portIndex<phyCount; portIndex++)
+	{
+		port = portIndex;
+
+		if((status = gprtPhyIntEnable(dev,port,data)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPhyIntEnable returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+	}
+
+	/* Set QuarterDeck interrupt ATUFull, PHYInt, and EEInt */
+	portIntCause = GT_ATU_FULL|GT_PHY_INTERRUPT|GT_EE_INTERRUPT;
+	if(qdSimSetGlobalInt(portIntCause) != GT_OK)
+	{
+		MSG_PRINT(("QD Simulator is not used.\n"));
+		testResults |= 1 << GT_NOT_SUPPORTED;
+		return testResults;
+	}
+
+	/* 
+	 * 	Set PHY Interrupt Link Status Change, Speed Change, and AutoNego
+	 * 	Complete for Port 0 and Port 4.
+	*/
+	phyIntCause = GT_SPEED_CHANGED|GT_AUTO_NEG_COMPLETED|GT_LINK_STATUS_CHANGED;
+	if(qdSimSetPhyInt(0,phyIntCause) != GT_OK)
+	{
+		MSG_PRINT(("QD Simulator is not used.\n"));
+		testResults |= 1 << GT_NOT_SUPPORTED;
+		return testResults;
+	}
+
+	if(qdSimSetPhyInt(4,phyIntCause) != GT_OK)
+	{
+		MSG_PRINT(("QD Simulator is not used.\n"));
+		testResults |= 1 << GT_NOT_SUPPORTED;
+		return testResults;
+	}
+
+	MSG_PRINT(("Calling QD Interrupt Handler with portInt %#x, phyInt %#x\n",portIntCause,phyIntCause));
+
+	/*
+	 *	Call QuarterDeck Interrupt Handler.
+	*/
+	if(eventGetIntStatus(dev,&tmpData) != GT_TRUE)
+	{
+		MSG_PRINT(("qdIntHander returned GT_FALSE.\n"));
+		testResults |= 1 << GT_FAIL;
+		return testResults;
+	}
+
+	if(tmpData != portIntCause)
+	{
+		MSG_PRINT(("qdIntHander returned wrong intCause(%#x).\n",tmpData));
+		testResults |= 1 << GT_FAIL;
+		testResult = GT_FAIL;
+	}
+	else
+		MSG_PRINT(("QD Interrupt Handler returned intCause(%#x).\n",tmpData));
+
+
+	/*
+	 *	Call gprtGetPhyIntPortSummary to get Port Int Summary
+	*/
+	if((status = gprtGetPhyIntPortSummary(dev,&tmpData)) != GT_OK)
+	{
+		MSG_PRINT(("gprtGetPhyIntPortSummary returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	if(tmpData != 0x11)	/* port 0 and port 4 should be set. */
+	{
+		MSG_PRINT(("gprtGetPhyIntPortSummary returned wrong summary(%#x).\n",tmpData));
+		testResult = GT_FAIL;
+		testResults |= 1 << GT_FAIL;
+	}
+	else
+		MSG_PRINT(("Port Summary returned %#x.\n",tmpData));
+
+	/*
+	 *	Call gprtGetPhyIntStatus to get intCause
+	*/
+	if((status = gprtGetPhyIntStatus(dev,0,&tmpData)) != GT_OK)
+	{
+		MSG_PRINT(("gprtGetPhyIntStatus returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	if(tmpData != phyIntCause)
+	{
+		MSG_PRINT(("gprtGetPhyIntStatus returned wrong phyIntCause(%#x).\n",tmpData));
+		testResult = GT_FAIL;
+		testResults |= 1 << GT_FAIL;
+	}
+	else
+		MSG_PRINT(("PHY Int Status(port 0) returned %#x.\n",tmpData));
+		
+	/*
+	 *	Call gprtGetPhyIntStatus to get intCause
+	*/
+	if((status = gprtGetPhyIntStatus(dev,4,&tmpData)) != GT_OK)
+	{
+		MSG_PRINT(("gprtGetPhyIntStatus returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	if(tmpData != phyIntCause)
+	{
+		MSG_PRINT(("gprtGetPhyIntStatus returned wrong phyIntCause(%#x).\n",tmpData));
+		testResult = GT_FAIL;
+		testResults |= 1 << GT_FAIL;
+	}
+	else
+		MSG_PRINT(("PHY Int Status(port 4) returned %#x.\n",tmpData));
+
+	/* Set QuarterDeck interrupt ATUFull, PHYInt, and EEInt */
+	portIntCause = GT_PHY_INTERRUPT;
+	if(qdSimSetGlobalInt(portIntCause) != GT_OK)
+	{
+		MSG_PRINT(("QD Simulator is not used.\n"));
+		testResults |= 1 << GT_NOT_SUPPORTED;
+		return testResults;
+	}
+
+	/* 
+	 * 	Set PHY Interrupt Link Status Change, Speed Change, and AutoNego
+	 * 	Complete for Port 0 and Port 4.
+	*/
+	phyIntCause = GT_SPEED_CHANGED|GT_DUPLEX_CHANGED;
+	if(qdSimSetPhyInt(0,phyIntCause) != GT_OK)
+	{
+		MSG_PRINT(("QD Simulator is not used.\n"));
+		testResults |= 1 << GT_NOT_SUPPORTED;
+		return testResults;
+	}
+
+	if(qdSimSetPhyInt(3,phyIntCause) != GT_OK)
+	{
+		MSG_PRINT(("QD Simulator is not used.\n"));
+		testResults |= 1 << GT_NOT_SUPPORTED;
+		return testResults;
+	}
+
+	MSG_PRINT(("\nCalling QD Interrupt Handler with portInt %#x, phyInt %#x\n",portIntCause,phyIntCause));
+
+	/*
+	 *	Call QuarterDeck Interrupt Handler.
+	*/
+	if(eventGetIntStatus(dev,&tmpData) != GT_TRUE)
+	{
+		MSG_PRINT(("qdIntHander returned GT_FALSE.\n"));
+		testResults |= 1 << GT_FAIL;
+		return testResults;
+	}
+
+	if(tmpData != portIntCause)
+	{
+		MSG_PRINT(("qdIntHander returned wrong intCause(%#x).\n",tmpData));
+		testResult = GT_FAIL;
+		testResults |= 1 << GT_FAIL;
+	}
+	else
+		MSG_PRINT(("QD Interrupt Handler returned intCause(%#x).\n",tmpData));
+
+
+	/*
+	 *	Call gprtGetPhyIntPortSummary to get Port Int Summary
+	*/
+	if((status = gprtGetPhyIntPortSummary(dev,&tmpData)) != GT_OK)
+	{
+		MSG_PRINT(("gprtGetPhyIntPortSummary returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	if(tmpData != 0x9)	/* port 0 and port 3 should be set. */
+	{
+		MSG_PRINT(("gprtGetPhyIntPortSummary returned wrong summary(%#x).\n",tmpData));
+		testResult = GT_FAIL;
+		testResults |= 1 << GT_FAIL;
+	}
+	else
+		MSG_PRINT(("Port Summary returned %#x.\n",tmpData));
+
+	/*
+	 *	Call gprtGetPhyIntStatus to get intCause
+	*/
+	if((status = gprtGetPhyIntStatus(dev,0,&tmpData)) != GT_OK)
+	{
+		MSG_PRINT(("gprtGetPhyIntStatus returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	if(tmpData != phyIntCause)
+	{
+		MSG_PRINT(("gprtGetPhyIntStatus returned wrong phyIntCause(%#x).\n",tmpData));
+		testResults |= 1 << GT_FAIL;
+		testResult = GT_FAIL;
+	}
+	else
+		MSG_PRINT(("PHY Int Status(port 0) returned %#x.\n",tmpData));
+	
+	/*
+	 *	Call gprtGetPhyIntStatus to get intCause
+	*/
+	if((status = gprtGetPhyIntStatus(dev,3,&tmpData)) != GT_OK)
+	{
+		MSG_PRINT(("gprtGetPhyIntStatus returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	if(tmpData != phyIntCause)
+	{
+		MSG_PRINT(("gprtGetPhyIntStatus returned wrong phyIntCause(%#x).\n",tmpData));
+		testResult = GT_FAIL;
+		testResults |= 1 << GT_FAIL;
+	}
+	else
+		MSG_PRINT(("PHY Int Status(port 3) returned %#x.\n",tmpData));
+
+	return testResults;
+}
+
+void testDisplayCounter(GT_STATS_COUNTER_SET *statsCounter)
+{
+	MSG_PRINT(("InUnicasts    %08i    ", statsCounter->InUnicasts));
+	MSG_PRINT(("InBroadcasts  %08i   \n", statsCounter->InBroadcasts));
+	MSG_PRINT(("InPause       %08i    ", statsCounter->InPause));
+	MSG_PRINT(("InMulticasts  %08i   \n", statsCounter->InMulticasts));
+	MSG_PRINT(("InFCSErr      %08i    ", statsCounter->InFCSErr));
+	MSG_PRINT(("AlignErr      %08i   \n", statsCounter->AlignErr));
+	MSG_PRINT(("InGoodOctets  %08i    ", statsCounter->InGoodOctets));
+	MSG_PRINT(("InBadOctets   %08i   \n", statsCounter->InBadOctets));
+	MSG_PRINT(("Undersize     %08i    ", statsCounter->Undersize));
+	MSG_PRINT(("Fragments     %08i   \n", statsCounter->Fragments));
+	MSG_PRINT(("In64Octets    %08i    ", statsCounter->In64Octets));
+	MSG_PRINT(("In127Octets   %08i   \n", statsCounter->In127Octets));
+	MSG_PRINT(("In255Octets   %08i    ", statsCounter->In255Octets));
+	MSG_PRINT(("In511Octets   %08i   \n", statsCounter->In511Octets));
+	MSG_PRINT(("In1023Octets  %08i    ", statsCounter->In1023Octets));
+	MSG_PRINT(("InMaxOctets   %08i   \n", statsCounter->InMaxOctets));
+	MSG_PRINT(("Jabber        %08i    ", statsCounter->Jabber));
+	MSG_PRINT(("Oversize      %08i   \n", statsCounter->Oversize));
+	MSG_PRINT(("InDiscards    %08i    ", statsCounter->InDiscards));
+	MSG_PRINT(("Filtered      %08i   \n", statsCounter->Filtered));
+	MSG_PRINT(("OutUnicasts   %08i    ", statsCounter->OutUnicasts));
+	MSG_PRINT(("OutBroadcasts %08i   \n", statsCounter->OutBroadcasts));
+	MSG_PRINT(("OutPause      %08i    ", statsCounter->OutPause));
+	MSG_PRINT(("OutMulticasts %08i   \n", statsCounter->OutMulticasts));
+	MSG_PRINT(("OutFCSErr     %08i    ", statsCounter->OutFCSErr));
+	MSG_PRINT(("OutGoodOctets %08i   \n", statsCounter->OutGoodOctets));
+	MSG_PRINT(("Out64Octets   %08i    ", statsCounter->Out64Octets));
+	MSG_PRINT(("Out127Octets  %08i   \n", statsCounter->Out127Octets));
+	MSG_PRINT(("Out255Octets  %08i    ", statsCounter->Out255Octets));
+	MSG_PRINT(("Out511Octets  %08i   \n", statsCounter->Out511Octets));
+	MSG_PRINT(("Out1023Octets %08i    ", statsCounter->Out1023Octets));
+	MSG_PRINT(("OutMaxOctets  %08i   \n", statsCounter->OutMaxOctets));
+	MSG_PRINT(("Collisions    %08i    ", statsCounter->Collisions));
+	MSG_PRINT(("Late          %08i   \n", statsCounter->Late));
+	MSG_PRINT(("Excessive     %08i    ", statsCounter->Excessive));
+	MSG_PRINT(("Multiple      %08i   \n", statsCounter->Multiple));
+	MSG_PRINT(("Single        %08i    ", statsCounter->Single));
+	MSG_PRINT(("Deferred      %08i   \n", statsCounter->Deferred));
+	MSG_PRINT(("OutDiscards   %08i   \n", statsCounter->OutDiscards));
+}
+
+GT_STATUS testDisplayRMONCounter(GT_QD_DEV *dev,GT_LPORT port)
+{
+	GT_STATUS status;
+	GT_STATS_COUNTER_SET	statsCounterSet;
+
+	MSG_PRINT(("Getting counters for port %i.\n", port));
+		
+	if((status = gstatsGetPortAllCounters(dev,port,&statsCounterSet)) != GT_OK)
+	{
+		MSG_PRINT(("gstatsGetPortAllCounters returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	testDisplayCounter(&statsCounterSet);
+	return GT_OK;
+}
+
+GT_U32 testRMON1(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult, tmpResult;
+	GT_U32 testResults = 0;
+	GT_STATS_COUNTERS	counter;
+	GT_STATS_COUNTER_SET	statsCounterSet;
+	GT_U32	statsData;
+	GT_LPORT port;	
+	int portIndex;
+
+	testResult=GT_OK;
+
+	MSG_PRINT(("\ntesting RMON Counter :\n"));
+	MSG_PRINT(("RMON testing assumes no more activities in the device.\n"));
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		tmpResult = GT_OK;
+		port = portIndex;
+
+		MSG_PRINT(("Getting all counters for port %i.\n", port));
+		
+		if((status = gstatsGetPortAllCounters(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		MSG_PRINT(("Getting individual counter for port %i.\n", port));
+
+		for(counter=STATS_InUnicasts; counter<=STATS_OutDiscards; counter++)
+		{
+			if((status = gstatsGetPortCounter(dev,port, counter, &statsData)) != GT_OK)
+			{
+				MSG_PRINT(("gstatsGetPortCounter returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+
+			if (statsData != *((GT_U32*)&statsCounterSet + counter))
+			{
+				MSG_PRINT(("gstatsGetPortCounter(%i) mismatches gstatsGetPortAllCounter (%i : %i).\n",
+							counter,statsData,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+
+		}
+
+		if(tmpResult == GT_OK)
+		{
+			MSG_PRINT(("Comparing counters: (PASS)\n"));
+		}
+		else
+		{
+			MSG_PRINT(("Comparing counters: (FAIL)\n"));
+		}
+
+		if (!(port % 2))
+			continue;
+
+		MSG_PRINT(("Flushing the counter for port %i\n",port));
+
+		tmpResult = GT_OK;
+
+		if((status = gstatsFlushPort(dev,port)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsFlushPort returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gstatsGetPortAllCounters(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		for(counter=STATS_InUnicasts; counter<=STATS_OutDiscards; counter++)
+		{
+			if (*((GT_U32*)&statsCounterSet + counter) != 0)
+			{
+				MSG_PRINT(("gstatsFlushPort(%i) failed (counter : %i).\n",
+							counter,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+		}
+
+		if(tmpResult == GT_OK)
+		{
+			MSG_PRINT(("Flush: (PASS)\n"));
+		}
+		else
+		{
+			MSG_PRINT(("Flush: (FAIL)\n"));
+		}
+
+	}
+
+	/* Now RMON counters of the ports with even numbers are flushed */
+	MSG_PRINT(("Flushing the counters for all port\n"));
+	tmpResult = GT_OK;
+	if((status = gstatsFlushAll(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gstatsFlushAll returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		if((status = gstatsGetPortAllCounters(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		for(counter=STATS_InUnicasts; counter<=STATS_OutDiscards; counter++)
+		{
+			if (*((GT_U32*)&statsCounterSet + counter) != 0)
+			{
+				MSG_PRINT(("gstatsFlushPort(%i) failed (stats : %i).\n",
+							counter,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+		}
+
+	}			
+
+	if(tmpResult == GT_OK)
+	{
+		MSG_PRINT(("Flush ALL: (PASS)\n"));
+	}
+	else
+	{
+		MSG_PRINT(("Flush ALL: (FAIL)\n"));
+	}
+
+	return testResults;
+}
+
+void testDisplayCounter2(GT_STATS_COUNTER_SET2 *statsCounter)
+{
+	MSG_PRINT(("InGoodOctetsHi  %08i    ", statsCounter->InGoodOctetsHi));
+	MSG_PRINT(("InGoodOctetsLo  %08i   \n", statsCounter->InGoodOctetsLo));
+	MSG_PRINT(("InBadOctets     %08i    ", statsCounter->InBadOctets));
+	MSG_PRINT(("OutDiscards     %08i   \n", statsCounter->OutDiscards));
+	MSG_PRINT(("InGoodFrames    %08i    ", statsCounter->InGoodFrames));
+	MSG_PRINT(("InBadFrames     %08i   \n", statsCounter->InBadFrames));
+	MSG_PRINT(("InBroadcasts    %08i    ", statsCounter->InBroadcasts));
+	MSG_PRINT(("InMulticasts    %08i   \n", statsCounter->InMulticasts));
+	MSG_PRINT(("64Octets        %08i    ", statsCounter->Octets64));
+	MSG_PRINT(("127Octets       %08i   \n", statsCounter->Octets127));
+	MSG_PRINT(("255Octets       %08i    ", statsCounter->Octets255));
+	MSG_PRINT(("511Octets       %08i   \n", statsCounter->Octets511));
+	MSG_PRINT(("1023Octets      %08i    ", statsCounter->Octets1023));
+	MSG_PRINT(("MaxOctets       %08i   \n", statsCounter->OctetsMax));
+	MSG_PRINT(("OutOctetsHi     %08i    ", statsCounter->OutOctetsHi));
+	MSG_PRINT(("OutOctetsLo     %08i   \n", statsCounter->OutOctetsLo));
+	MSG_PRINT(("OutFrames       %08i    ", statsCounter->OutFrames));
+	MSG_PRINT(("Excessive       %08i   \n", statsCounter->Excessive));
+	MSG_PRINT(("OutMulticasts   %08i    ", statsCounter->OutMulticasts));
+	MSG_PRINT(("OutBroadcasts   %08i    ", statsCounter->OutBroadcasts));
+	MSG_PRINT(("InBadMACCtrl    %08i    ", statsCounter->InBadMACCtrl));
+	MSG_PRINT(("OutPause        %08i   \n", statsCounter->OutPause));
+	MSG_PRINT(("InPause         %08i    ", statsCounter->InPause));
+	MSG_PRINT(("InDiscards      %08i   \n", statsCounter->InDiscards));
+	MSG_PRINT(("Undersize       %08i    ", statsCounter->Undersize));
+	MSG_PRINT(("Fragments       %08i   \n", statsCounter->Fragments));
+	MSG_PRINT(("Oversize        %08i    ", statsCounter->Oversize));
+	MSG_PRINT(("Jabber          %08i   \n", statsCounter->Jabber));
+	MSG_PRINT(("MACRcvErr       %08i    ", statsCounter->MACRcvErr));
+	MSG_PRINT(("InFCSErr        %08i   \n", statsCounter->InFCSErr));
+	MSG_PRINT(("Collisions      %08i    ", statsCounter->Collisions));
+	MSG_PRINT(("Late            %08i   \n", statsCounter->Late));
+}
+
+GT_STATUS testDisplayRMONCounter2(GT_QD_DEV *dev,GT_LPORT port)
+{
+	GT_STATUS status;
+	GT_STATS_COUNTER_SET2 statsCounterSet;
+
+	MSG_PRINT(("Getting counters for port %i.\n", port));
+		
+	if((status = gstatsGetPortAllCounters2(dev,port,&statsCounterSet)) != GT_OK)
+	{
+		MSG_PRINT(("gstatsGetPortAllCounters2 returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	testDisplayCounter2(&statsCounterSet);
+	return GT_OK;
+}
+
+GT_U32 testRMON2(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult, tmpResult;
+	GT_U32 testResults = 0;
+	GT_STATS_COUNTERS2 counter;
+	GT_STATS_COUNTER_SET2 statsCounterSet;
+	GT_U32	statsData;
+	GT_LPORT port;	
+	int portIndex;
+	TEST_API testAPI;
+
+	testResult=GT_OK;
+
+	/*
+	 *	Histogram Mode Setup
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gstatsGetHistogramMode;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gstatsSetHistogramMode;
+	if((status = testU32Type(dev,&testAPI,3)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Histogram Mode Setup API test "));
+	testDisplayStatus(status);
+	MSG_PRINT(("\ntesting RMON Counter :\n"));
+	MSG_PRINT(("RMON testing assumes no more activities in the device.\n"));
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		tmpResult = GT_OK;
+		port = portIndex;
+
+		MSG_PRINT(("Getting all counters for port %i.\n", port));
+		
+		if((status = gstatsGetPortAllCounters2(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters2 returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		MSG_PRINT(("Getting individual counter for port %i.\n", port));
+
+		for(counter=STATS2_InGoodOctetsHi; counter<=STATS2_Late; counter++)
+		{
+			if((status = gstatsGetPortCounter2(dev,port, counter, &statsData)) != GT_OK)
+			{
+				MSG_PRINT(("gstatsGetPortCounter2 returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+
+			if (statsData != *((GT_U32*)&statsCounterSet + counter))
+			{
+				MSG_PRINT(("gstatsGetPortCounter2(%i) mismatches gstatsGetPortAllCounter2 (%i : %i).\n",
+							counter,statsData,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+
+		}
+
+		if(tmpResult == GT_OK)
+		{
+			MSG_PRINT(("Comparing counters: (PASS)\n"));
+		}
+		else
+		{
+			MSG_PRINT(("Comparing counters: (FAIL)\n"));
+		}
+
+		if (!(port % 2))
+			continue;
+
+		MSG_PRINT(("Flushing the counter for port %i\n",port));
+
+		tmpResult = GT_OK;
+
+		if((status = gstatsFlushPort(dev,port)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsFlushPort returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gstatsGetPortAllCounters2(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		for(counter=STATS2_InGoodOctetsHi; counter<=STATS2_Late; counter++)
+		{
+			if (*((GT_U32*)&statsCounterSet + counter) != 0)
+			{
+				MSG_PRINT(("gstatsFlushPort(%i) failed (counter : %i).\n",
+							counter,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+		}
+
+		if(tmpResult == GT_OK)
+		{
+			MSG_PRINT(("Flush: (PASS)\n"));
+		}
+		else
+		{
+			MSG_PRINT(("Flush: (FAIL)\n"));
+		}
+
+	}
+
+	/* Now RMON counters of the ports with even numbers are flushed */
+	MSG_PRINT(("Flushing the counters for all port\n"));
+	tmpResult = GT_OK;
+	if((status = gstatsFlushAll(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gstatsFlushAll returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		if((status = gstatsGetPortAllCounters2(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		for(counter=STATS2_InGoodOctetsHi; counter<=STATS2_Late; counter++)
+		{
+			if (*((GT_U32*)&statsCounterSet + counter) != 0)
+			{
+				MSG_PRINT(("gstatsFlushPort(%i) failed (stats : %i).\n",
+							counter,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+		}
+
+	}			
+
+	if(tmpResult == GT_OK)
+	{
+		MSG_PRINT(("Flush ALL: (PASS)\n"));
+	}
+	else
+	{
+		MSG_PRINT(("Flush ALL: (FAIL)\n"));
+	}
+
+	return testResults;
+}
+
+void testDisplayCounter3(GT_STATS_COUNTER_SET3 *statsCounter)
+{
+	MSG_PRINT(("InGoodOctetsLo  %08i    ", statsCounter->InGoodOctetsLo));
+	MSG_PRINT(("InGoodOctetsHi  %08i   \n", statsCounter->InGoodOctetsHi));
+	MSG_PRINT(("InBadOctets     %08i    ", statsCounter->InBadOctets));
+	MSG_PRINT(("OutFCSErr       %08i   \n", statsCounter->OutFCSErr));
+	MSG_PRINT(("InUnicasts      %08i    ", statsCounter->InUnicasts));
+	MSG_PRINT(("Deferred        %08i   \n", statsCounter->Deferred));
+	MSG_PRINT(("InBroadcasts    %08i    ", statsCounter->InBroadcasts));
+	MSG_PRINT(("InMulticasts    %08i   \n", statsCounter->InMulticasts));
+	MSG_PRINT(("64Octets        %08i    ", statsCounter->Octets64));
+	MSG_PRINT(("127Octets       %08i   \n", statsCounter->Octets127));
+	MSG_PRINT(("255Octets       %08i    ", statsCounter->Octets255));
+	MSG_PRINT(("511Octets       %08i   \n", statsCounter->Octets511));
+	MSG_PRINT(("1023Octets      %08i    ", statsCounter->Octets1023));
+	MSG_PRINT(("MaxOctets       %08i   \n", statsCounter->OctetsMax));
+	MSG_PRINT(("OutOctetsLo     %08i    ", statsCounter->OutOctetsLo));
+	MSG_PRINT(("OutOctetsHi     %08i   \n", statsCounter->OutOctetsHi));
+	MSG_PRINT(("OutUnicasts     %08i    ", statsCounter->OutUnicasts));
+	MSG_PRINT(("Excessive       %08i   \n", statsCounter->Excessive));
+	MSG_PRINT(("OutMulticasts   %08i    ", statsCounter->OutMulticasts));
+	MSG_PRINT(("OutBroadcasts   %08i   \n", statsCounter->OutBroadcasts));
+	MSG_PRINT(("Single          %08i    ", statsCounter->Single));
+	MSG_PRINT(("OutPause        %08i   \n", statsCounter->OutPause));
+	MSG_PRINT(("InPause         %08i    ", statsCounter->InPause));
+	MSG_PRINT(("Multiple        %08i   \n", statsCounter->Multiple));
+	MSG_PRINT(("Undersize       %08i    ", statsCounter->Undersize));
+	MSG_PRINT(("Fragments       %08i   \n", statsCounter->Fragments));
+	MSG_PRINT(("Oversize        %08i    ", statsCounter->Oversize));
+	MSG_PRINT(("Jabber          %08i   \n", statsCounter->Jabber));
+	MSG_PRINT(("InMACRcvErr     %08i    ", statsCounter->InMACRcvErr));
+	MSG_PRINT(("InFCSErr        %08i   \n", statsCounter->InFCSErr));
+	MSG_PRINT(("Collisions      %08i    ", statsCounter->Collisions));
+	MSG_PRINT(("Late            %08i   \n", statsCounter->Late));
+}
+
+GT_STATUS testDisplayRMONCounter3(GT_QD_DEV *dev,GT_LPORT port)
+{
+	GT_STATUS status;
+	GT_STATS_COUNTER_SET3 statsCounterSet;
+
+	MSG_PRINT(("Getting counters for port %i.\n", port));
+		
+	if((status = gstatsGetPortAllCounters3(dev,port,&statsCounterSet)) != GT_OK)
+	{
+		MSG_PRINT(("gstatsGetPortAllCounters3 returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	testDisplayCounter3(&statsCounterSet);
+	return GT_OK;
+}
+
+GT_U32 testRMON3(GT_QD_DEV *dev)
+{
+	GT_STATUS status, testResult, tmpResult;
+	GT_U32 testResults = 0;
+	GT_STATS_COUNTERS3 counter;
+	GT_STATS_COUNTER_SET3 statsCounterSet;
+	GT_U32	statsData;
+	GT_LPORT port;	
+	int portIndex;
+	TEST_API testAPI;
+
+	testResult=GT_OK;
+
+	/*
+	 *	Histogram Mode Setup
+	 */
+	testAPI.getFunc.u32 = (GT_API_GET_U32)gstatsGetHistogramMode;
+	testAPI.setFunc.u32 = (GT_API_SET_U32)gstatsSetHistogramMode;
+	if((status = testU32Type(dev,&testAPI,3)) != GT_OK)
+	{
+		testResult = GT_FAIL;
+		testResults |= 1 << status;
+	}
+	MSG_PRINT(("Histogram Mode Setup API test "));
+	testDisplayStatus(status);
+	MSG_PRINT(("\ntesting RMON Counter :\n"));
+	MSG_PRINT(("RMON testing assumes no more activities in the device.\n"));
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		tmpResult = GT_OK;
+		port = portIndex;
+
+		MSG_PRINT(("Getting all counters for port %i.\n", port));
+		
+		if((status = gstatsGetPortAllCounters3(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters3 returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		MSG_PRINT(("Getting individual counter for port %i.\n", port));
+
+		for(counter=STATS3_InGoodOctetsLo; counter<=STATS3_Late; counter++)
+		{
+			if((status = gstatsGetPortCounter3(dev,port, counter, &statsData)) != GT_OK)
+			{
+				MSG_PRINT(("gstatsGetPortCounter3 returned "));
+				testDisplayStatus(status);
+				testResults |= 1 << status;
+				return testResults;
+			}
+
+			if (statsData != *((GT_U32*)&statsCounterSet + counter))
+			{
+				MSG_PRINT(("gstatsGetPortCounter3(%i) mismatches gstatsGetPortAllCounter3 (%i : %i).\n",
+							counter,statsData,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+
+		}
+
+		if(tmpResult == GT_OK)
+		{
+			MSG_PRINT(("Comparing counters: (PASS)\n"));
+		}
+		else
+		{
+			MSG_PRINT(("Comparing counters: (FAIL)\n"));
+		}
+
+		if (!(port % 2))
+			continue;
+
+		MSG_PRINT(("Flushing the counter for port %i\n",port));
+
+		tmpResult = GT_OK;
+
+		if((status = gstatsFlushPort(dev,port)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsFlushPort returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		if((status = gstatsGetPortAllCounters3(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		for(counter=STATS3_InGoodOctetsLo; counter<=STATS3_Late; counter++)
+		{
+			if (*((GT_U32*)&statsCounterSet + counter) != 0)
+			{
+				MSG_PRINT(("gstatsFlushPort(%i) failed (counter : %i).\n",
+							counter,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+		}
+
+		if(tmpResult == GT_OK)
+		{
+			MSG_PRINT(("Flush: (PASS)\n"));
+		}
+		else
+		{
+			MSG_PRINT(("Flush: (FAIL)\n"));
+		}
+
+	}
+
+	/* Now RMON counters of the ports with even numbers are flushed */
+	MSG_PRINT(("Flushing the counters for all port\n"));
+	tmpResult = GT_OK;
+	if((status = gstatsFlushAll(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gstatsFlushAll returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		return testResults;
+	}
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		if((status = gstatsGetPortAllCounters3(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			return testResults;
+		}
+
+		for(counter=STATS3_InGoodOctetsLo; counter<=STATS3_Late; counter++)
+		{
+			if (*((GT_U32*)&statsCounterSet + counter) != 0)
+			{
+				MSG_PRINT(("gstatsFlushPort(%i) failed (stats : %i).\n",
+							counter,*((GT_U32*)&statsCounterSet + counter)));
+				testResult = GT_FAIL;
+				tmpResult = GT_FAIL;
+				testResults |= 1 << tmpResult;
+				continue;
+			}
+		}
+
+	}			
+
+	if(tmpResult == GT_OK)
+	{
+		MSG_PRINT(("Flush ALL: (PASS)\n"));
+	}
+	else
+	{
+		MSG_PRINT(("Flush ALL: (FAIL)\n"));
+	}
+
+	return testResults;
+}
+
+GT_U32 testRMON(GT_QD_DEV *dev)
+{
+	GT_U32 testResults;
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6153:
+		case GT_88E6183:
+			testResults = testRMON2(dev);
+			break;
+		case GT_88E6093:
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6065:
+			testResults = testRMON3(dev);
+			break;
+		default:
+			testResults = testRMON1(dev);
+			break;
+	}
+
+	return testResults;
+}
+
+void testDisplayVTUEntry(GT_QD_DEV *dev, GT_VTU_ENTRY *vtuEntry)
+{
+	GT_LPORT port;	
+	int portIndex;
+
+	MSG_PRINT(("DBNum:%i, VID:%i, ",vtuEntry->DBNum,vtuEntry->vid));
+	MSG_PRINT(("Tag: "));
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		MSG_PRINT(("%#x ",port,vtuEntry->vtuData.memberTagP[port]));
+	}
+	MSG_PRINT(("\n"));
+
+	MSG_PRINT(("%i,%i,%i,%i,%i,%i,%i\n",
+				vtuEntry->vidPriOverride,
+				vtuEntry->vidPriority,
+				vtuEntry->vidExInfo.useVIDFPri,
+				vtuEntry->vidExInfo.vidFPri,
+				vtuEntry->vidExInfo.useVIDQPri,
+				vtuEntry->vidExInfo.vidQPri,
+				vtuEntry->vidExInfo.vidNRateLimit
+				));
+
+}
+
+void testDisplayVTUList(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+    GT_VTU_ENTRY vtuEntry;
+
+	memset(&vtuEntry,0,sizeof(GT_VTU_ENTRY));
+	vtuEntry.vid = 0xfff;
+	if((status = gvtuGetEntryFirst(dev,&vtuEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuGetEntryCount returned "));
+		testDisplayStatus(status);
+		return;
+	}
+
+	testDisplayVTUEntry(dev,&vtuEntry);
+
+	while(1)
+	{
+		if((status = gvtuGetEntryNext(dev,&vtuEntry)) != GT_OK)
+		{
+			break;
+		}
+		testDisplayVTUEntry(dev,&vtuEntry);
+	}
+
+}
+
+GT_STATUS testWriteVTU(GT_QD_DEV *dev, GT_VTU_ENTRY *vtuEntry, GT_U32 vid, GT_U32 DBNum, GT_U32 portVec)
+{
+	int i;
+
+	vtuEntry->vid = vid & 0xFFF;
+	vtuEntry->DBNum = DBNum & 0xF;
+	vtuEntry->vidPriOverride = 0;
+	vtuEntry->vidPriority = 0;
+
+	for(i=0; i<16; i++)
+	{
+		if((portVec>>i) & 0x1)
+			vtuEntry->vtuData.memberTagP[i] = 3;
+		else
+			vtuEntry->vtuData.memberTagP[i] = 0;
+			
+	}
+
+	return GT_OK;
+}
+
+/*
+	VTU APIs Test Scenario:
+	1) Flush VTU entries and check Entry Count.
+	2) Create a list of 16 VID entries based on arg param.
+		(descending, ascending, and random order)
+	3) Add a Entry.
+	4) check Entry Count, call EntryFirst and EntryNext.
+	5) Add 16/64/4096 more Entries.(Last entry should be failed to be added)
+	6) Delete 2 valid entries and 1 invalid entry
+	7) Check Entry Count, and try to find a valid entry and deleted entry.
+*/
+
+GT_STATUS testVTUCtrl(GT_QD_DEV *dev,int arg)
+{
+#define MAX_VTU_ENTRIES	4096
+	GT_STATUS status, testResult, tmpResult;
+    GT_VTU_ENTRY vtuEntry[MAX_VTU_ENTRIES+1];
+    GT_VTU_ENTRY tmpVtuEntry;
+	GT_U32 u32Data1, u32Data2, u32Data3, maxDbNum, priType;
+	GT_BOOL found;
+	int i, j, portIndex;
+	GT_LPORT port;
+	int maxVtuEntries;
+	GT_BOOL supportMaxEntry = GT_FALSE;
+
+	testResult = GT_OK;
+	maxDbNum = 1;
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6021:
+			maxVtuEntries = 16;
+			maxDbNum = 1;
+			priType =  0;	/* no VID Priority override support */
+			break;
+		case GT_88E6063:
+		case GT_FH_VPN:
+		case GT_88E6083:
+			maxVtuEntries = 64;
+			maxDbNum = 16;
+			priType =  0;	/* no VID Priority override support */
+			break;
+		case GT_88E6153:
+		case GT_88E6183:
+		case GT_88E6093:
+			maxVtuEntries = 64;
+			maxDbNum = 16;
+			supportMaxEntry = GT_TRUE;
+			priType =  1;	/* VID Priority override support */
+			break;
+		case GT_88E6031:
+		case GT_88E6061:
+			maxVtuEntries = 16;
+			maxDbNum = 16;
+			priType =  2;	/* Extended VID Priority override support */
+			break;
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6065:
+			maxVtuEntries = 64;
+			maxDbNum = 64;
+			priType =  3;	/* Extended VID Priority override support */
+			break;
+		case GT_88E6095:
+		case GT_88E6092:
+		case GT_88E6152:
+		case GT_88E6155:
+		case GT_88E6182:
+		case GT_88E6185:
+		case GT_88E6131:
+		case GT_88E6108:
+			maxVtuEntries = 64;
+			maxDbNum = 256;
+			supportMaxEntry = GT_TRUE;
+			priType =  1;	/* VID Priority override support */
+			break;
+		default:
+			maxVtuEntries = 16;
+			priType =  0;	/* no VID Priority override support */
+			break;
+	}
+
+	/* 1) Flush VTU entries and check Entry Count */
+	MSG_PRINT(("Flushing VTU entries: "));
+	if((status = gvtuFlush(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuFlush returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if((status = gvtuGetEntryCount(dev,&u32Data1)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuGetEntryCount returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if(u32Data1 != 0)
+	{
+		MSG_PRINT(("\nEntryCount %i (Failed, should be 0)\n",u32Data1));
+		testResult = GT_FAIL;
+	}
+	else
+	{
+		MSG_PRINT(("(PASS)\n"));
+	}
+
+	/*
+		2) Create a list of 16 VID entries based on arg param.
+			(descending, ascending, and random order)
+	*/
+	MSG_PRINT(("Creating a list of %i VID\n",maxVtuEntries+1));
+	srand((unsigned)time(NULL));
+	switch (arg)
+	{
+		case 0: /* Ascending order */
+			/* check if it supports MX_VTU_ENTRIES */
+			if (maxVtuEntries == MAX_VTU_ENTRIES)
+			{
+				for(i=0; i<maxVtuEntries+1; i++)
+				{
+					memset(&vtuEntry[i],0,sizeof(GT_VTU_ENTRY));
+					vtuEntry[i].DBNum = 1;
+					vtuEntry[i].vid = i;
+					for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+					{
+						port = portIndex;
+
+						vtuEntry[i].vtuData.memberTagP[port] = (vtuEntry[i].vid+port)%4;
+					}
+					switch(priType)
+					{
+						case 0:
+							break;
+						case 1:
+							vtuEntry[i].vidPriOverride = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							if(vtuEntry[i].vidPriOverride == GT_TRUE)
+								vtuEntry[i].vidPriority = (GT_U8)(rand() & 0x7);
+							break;
+						case 2:
+							vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							break;
+						case 3:
+							vtuEntry[i].vidExInfo.useVIDFPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							if (vtuEntry[i].vidExInfo.useVIDFPri == GT_TRUE)
+								vtuEntry[i].vidExInfo.vidFPri = (GT_U8)(rand() & 0x7);
+							vtuEntry[i].vidExInfo.useVIDQPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							if (vtuEntry[i].vidExInfo.useVIDQPri == GT_TRUE)
+								vtuEntry[i].vidExInfo.vidQPri = (GT_U8)(rand() & 0x3);
+							vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							break;
+						default:
+							break;
+					}
+				}
+				break;
+			}
+
+			u32Data1 = (rand()%1024) + 1;
+			u32Data2 = (rand()%32) + 1;
+			for(i=0; i<maxVtuEntries+1; i++)
+			{
+				memset(&vtuEntry[i],0,sizeof(GT_VTU_ENTRY));
+				vtuEntry[i].DBNum = 1;
+				vtuEntry[i].vid = u32Data1 + u32Data2 * i;
+				for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+				{
+					port = portIndex;
+
+					vtuEntry[i].vtuData.memberTagP[port] = (vtuEntry[i].vid+port)%4;
+				}
+				switch(priType)
+				{
+					case 0:
+						break;
+					case 1:
+						vtuEntry[i].vidPriOverride = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if(vtuEntry[i].vidPriOverride == GT_TRUE)
+							vtuEntry[i].vidPriority = (GT_U8)(rand() & 0x7);
+						break;
+					case 2:
+						vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						break;
+					case 3:
+						vtuEntry[i].vidExInfo.useVIDFPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if (vtuEntry[i].vidExInfo.useVIDFPri == GT_TRUE)
+							vtuEntry[i].vidExInfo.vidFPri = (GT_U8)(rand() & 0x7);
+						vtuEntry[i].vidExInfo.useVIDQPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if (vtuEntry[i].vidExInfo.useVIDQPri == GT_TRUE)
+							vtuEntry[i].vidExInfo.vidQPri = (GT_U8)(rand() & 0x3);
+						vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						break;
+					default:
+						break;
+				}
+			}
+			break;
+
+		case 1: /* Descending order */
+			/* check if it supports MX_VTU_ENTRIES */
+			if (maxVtuEntries == MAX_VTU_ENTRIES)
+			{
+				for(i=0; i<maxVtuEntries; i++)
+				{
+					memset(&vtuEntry[i],0,sizeof(GT_VTU_ENTRY));
+					vtuEntry[i].DBNum = 2;
+					vtuEntry[i].vid = maxVtuEntries - i;
+					for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+					{
+						port = portIndex;
+
+						vtuEntry[i].vtuData.memberTagP[port] = (vtuEntry[i].vid+port)%4;
+					}
+					switch(priType)
+					{
+						case 0:
+							break;
+						case 1:
+							vtuEntry[i].vidPriOverride = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							if(vtuEntry[i].vidPriOverride == GT_TRUE)
+								vtuEntry[i].vidPriority = (GT_U8)(rand() & 0x7);
+							break;
+						case 2:
+							vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							break;
+						case 3:
+							vtuEntry[i].vidExInfo.useVIDFPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							if (vtuEntry[i].vidExInfo.useVIDFPri == GT_TRUE)
+								vtuEntry[i].vidExInfo.vidFPri = (GT_U8)(rand() & 0x7);
+							vtuEntry[i].vidExInfo.useVIDQPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							if (vtuEntry[i].vidExInfo.useVIDQPri == GT_TRUE)
+								vtuEntry[i].vidExInfo.vidQPri = (GT_U8)(rand() & 0x3);
+							vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+							break;
+						default:
+							break;
+					}
+				}
+				memset(&vtuEntry[i],0,sizeof(GT_VTU_ENTRY));
+				vtuEntry[i].DBNum = 2;
+				vtuEntry[i].vid = 5;	/* choose any value. this entry is only for checking error. */
+				for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+				{
+					port = portIndex;
+
+					vtuEntry[i].vtuData.memberTagP[port] = (vtuEntry[i].vid+port)%4;
+				}
+
+				break;
+			
+			}
+			u32Data1 = (rand()%1024) + 1;
+			u32Data2 = (rand()%32) + 1;
+			for(i=0; i<maxVtuEntries+1; i++)
+			{
+				memset(&vtuEntry[maxVtuEntries-i],0,sizeof(GT_VTU_ENTRY));
+				vtuEntry[maxVtuEntries-i].DBNum = 2;
+				vtuEntry[maxVtuEntries-i].vid = u32Data1 + u32Data2 * i;
+				for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+				{
+					port = portIndex;
+
+					vtuEntry[maxVtuEntries-i].vtuData.memberTagP[port] = (vtuEntry[maxVtuEntries-i].vid+port)%4;
+				}
+				switch(priType)
+				{
+					case 0:
+						break;
+					case 1:
+						vtuEntry[i].vidPriOverride = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if(vtuEntry[i].vidPriOverride == GT_TRUE)
+							vtuEntry[i].vidPriority = (GT_U8)(rand() & 0x7);
+						break;
+					case 2:
+						vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						break;
+					case 3:
+						vtuEntry[i].vidExInfo.useVIDFPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if (vtuEntry[i].vidExInfo.useVIDFPri == GT_TRUE)
+							vtuEntry[i].vidExInfo.vidFPri = (GT_U8)(rand() & 0x7);
+						vtuEntry[i].vidExInfo.useVIDQPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if (vtuEntry[i].vidExInfo.useVIDQPri == GT_TRUE)
+							vtuEntry[i].vidExInfo.vidQPri = (GT_U8)(rand() & 0x3);
+						vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						break;
+					default:
+						break;
+				}
+			}
+			break;
+
+		default: /* random order */
+			for(i=0; i<maxVtuEntries+1; i++)
+			{
+				memset(&vtuEntry[i],0,sizeof(GT_VTU_ENTRY));
+				vtuEntry[i].DBNum = (maxDbNum > i)?(maxDbNum-i)%maxDbNum:(i-maxDbNum)%maxDbNum;
+				vtuEntry[i].vid = (rand() & 0xF) | ((rand() & 0xF) << 4) | ((rand() & 0xF) << 8);
+				for(j=0; j<i; j++)
+				{
+					if(vtuEntry[j].vid == vtuEntry[i].vid)
+					{
+						vtuEntry[i].vid = (rand() & 0xF) | ((rand() & 0xF) << 4) | ((rand() & 0xF) << 8);
+						j = -1;
+					}
+				}
+
+				for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+				{
+					port = portIndex;
+
+					vtuEntry[i].vtuData.memberTagP[port] = (vtuEntry[i].vid+port)%4;
+				}
+				switch(priType)
+				{
+					case 0:
+						break;
+					case 1:
+						vtuEntry[i].vidPriOverride = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if(vtuEntry[i].vidPriOverride == GT_TRUE)
+							vtuEntry[i].vidPriority = (GT_U8)(rand() & 0x7);
+						break;
+					case 2:
+						vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						break;
+					case 3:
+						vtuEntry[i].vidExInfo.useVIDFPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if (vtuEntry[i].vidExInfo.useVIDFPri == GT_TRUE)
+							vtuEntry[i].vidExInfo.vidFPri = (GT_U8)(rand() & 0x7);
+						vtuEntry[i].vidExInfo.useVIDQPri = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						if (vtuEntry[i].vidExInfo.useVIDQPri == GT_TRUE)
+							vtuEntry[i].vidExInfo.vidQPri = (GT_U8)(rand() & 0x3);
+						vtuEntry[i].vidExInfo.vidNRateLimit = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+						break;
+					default:
+						break;
+				}
+			}
+			break;
+
+	}			 
+
+#if 0	/* display VTU entries */
+	for(i=0; i<maxVtuEntries+1; i++)
+		testDisplayVTUEntry(dev,&vtuEntry[i]);
+#endif
+
+	/*
+		3) Add a Entry.
+	*/
+	MSG_PRINT(("Adding a Entry: "));
+	if((status = gvtuAddEntry(dev,&vtuEntry[0])) != GT_OK)
+	{
+		MSG_PRINT(("gvtuAddEntry returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	/*
+		4) check Entry Count, call EntryFirst and EntryNext
+	*/
+	if((status = gvtuGetEntryCount(dev,&u32Data1)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuGetEntryCount returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if(u32Data1 != 1)
+	{
+		MSG_PRINT(("\nEntryCount %i (Failed, should be 1)\n",u32Data1));
+		testResult = GT_FAIL;
+	}
+	else
+	{
+		MSG_PRINT(("(PASS)\n"));
+	}
+
+	MSG_PRINT(("Getting the first Entry: "));
+	memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+	tmpVtuEntry.vid = 0xfff;
+	if((status = gvtuGetEntryFirst(dev,&tmpVtuEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuGetEntryCount returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if(memcmp(&tmpVtuEntry,&vtuEntry[0],sizeof(GT_VTU_ENTRY)) != 0)
+	{
+		MSG_PRINT(("Unexpected VTU entry\n"));
+		testDisplayVTUEntry(dev,&tmpVtuEntry);
+		testResult = GT_FAIL;
+	}
+	else
+	{
+		MSG_PRINT(("(PASS)\n"));
+	}
+
+	if((status = gvtuGetEntryNext(dev,&tmpVtuEntry)) == GT_OK)
+	{
+		MSG_PRINT(("gvtuGetEntryNext should returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	/*
+		5) Add 16 more Entries.(Last entry should be failed to be added)
+	*/
+	MSG_PRINT(("Adding %i VTU entries: ",maxVtuEntries+1));
+	for(i=1; i<maxVtuEntries; i++)
+	{
+		if((status = gvtuAddEntry(dev,&vtuEntry[i])) != GT_OK)
+		{
+			MSG_PRINT(("gvtuAddEntry returned "));
+			testDisplayStatus(status);
+			MSG_PRINT(("Failed VID : %i\n",vtuEntry[i].vid));
+			MSG_PRINT(("Number of Entries should be in VTU : %i\n",i));
+			return status;
+		}
+	}
+
+	if(supportMaxEntry != GT_TRUE)
+	{
+		if((status = gvtuAddEntry(dev,&vtuEntry[maxVtuEntries])) == GT_OK)
+		{
+			MSG_PRINT(("gvtuAddEntry should return "));
+			testDisplayStatus(GT_FAIL);
+			for(i=0; i<maxVtuEntries+1; i++)
+				testDisplayVTUEntry(dev,&vtuEntry[i]);
+			return GT_FAIL;
+		}
+	}
+	MSG_PRINT(("(PASS)\n"));
+
+	/*
+		6) Delete 3 valid entries and 1 invalid entry
+	*/
+	MSG_PRINT(("Deleting entries: "));
+	u32Data1 = 0;
+	u32Data2 = 12;
+	u32Data3 = maxVtuEntries-1;
+	if((status = gvtuDelEntry(dev,&vtuEntry[u32Data1])) != GT_OK)
+	{
+		MSG_PRINT(("gvtuDelEntry returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+	if((status = gvtuDelEntry(dev,&vtuEntry[u32Data2])) != GT_OK)
+	{
+		MSG_PRINT(("gvtuDelEntry returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+	if((status = gvtuDelEntry(dev,&vtuEntry[u32Data3])) != GT_OK)
+	{
+		MSG_PRINT(("gvtuDelEntry returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+#if 0
+	if((status = gvtuDelEntry(dev,&vtuEntry[maxVtuEntries])) == GT_OK)
+	{
+		MSG_PRINT(("gvtuDelEntry should not return "));
+		testDisplayStatus(status);
+		return status;
+	}
+#endif
+	/*
+		7) Check Entry Count, and try to find a valid entry and deleted entry.
+	*/
+
+	MSG_PRINT(("Checking Entry count: "));
+	if((status = gvtuGetEntryCount(dev,&u32Data1)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuGetEntryCount returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if(u32Data1 != maxVtuEntries-3)
+	{
+		MSG_PRINT(("EntryCount %i (Failed, should be %i)\n",u32Data1,maxVtuEntries-3));
+		testResult = GT_FAIL;
+	}
+	else
+	{
+		MSG_PRINT(("(PASS)\n"));
+	}
+
+	MSG_PRINT(("Finding entries: "));
+
+	tmpResult = GT_OK;
+
+	memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+	tmpVtuEntry.vid = vtuEntry[2].vid;
+	if((status = gvtuFindVidEntry(dev,&tmpVtuEntry, &found)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuFindVidEntry returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if (found != GT_TRUE)
+	{
+		MSG_PRINT(("gvtuFindVidEntry returned OK with Found not true\n"));
+		testResult = GT_FAIL;
+		tmpResult = GT_FAIL;
+	}
+
+	if(memcmp(&tmpVtuEntry,&vtuEntry[2],sizeof(GT_VTU_ENTRY)) != 0)
+	{
+		MSG_PRINT(("Unexpected VTU entry (%i)\n",2));
+		testDisplayVTUEntry(dev,&tmpVtuEntry);
+		testResult = GT_FAIL;
+		tmpResult = GT_FAIL;
+	}
+
+	memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+	tmpVtuEntry.vid = vtuEntry[14].vid;
+	if((status = gvtuFindVidEntry(dev,&tmpVtuEntry, &found)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuFindVidEntry returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if (found != GT_TRUE)
+	{
+		MSG_PRINT(("gvtuFindVidEntry returned OK with Found not true\n"));
+		testResult = GT_FAIL;
+		tmpResult = GT_FAIL;
+	}
+
+	if(memcmp(&tmpVtuEntry,&vtuEntry[14],sizeof(GT_VTU_ENTRY)) != 0)
+	{
+		MSG_PRINT(("Unexpected VTU entry (%i)\n", 14));
+		testDisplayVTUEntry(dev,&tmpVtuEntry);
+		testResult = GT_FAIL;
+		tmpResult = GT_FAIL;
+	}
+
+	memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+	tmpVtuEntry.vid = vtuEntry[4].vid;
+	if((status = gvtuFindVidEntry(dev,&tmpVtuEntry, &found)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuFindVidEntry returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	if (found != GT_TRUE)
+	{
+		MSG_PRINT(("gvtuFindVidEntry returned OK with Found not true\n"));
+		testResult = GT_FAIL;
+		tmpResult = GT_FAIL;
+	}
+
+	if(memcmp(&tmpVtuEntry,&vtuEntry[4],sizeof(GT_VTU_ENTRY)) != 0)
+	{
+		MSG_PRINT(("Unexpected VTU entry (%i)\n", 4));
+		testDisplayVTUEntry(dev,&tmpVtuEntry);
+		testResult = GT_FAIL;
+		tmpResult = GT_FAIL;
+	}
+
+	/* try to find deleted entry */
+	MSG_PRINT(("Find Deleted Entry... "));
+	memset(&tmpVtuEntry,0,sizeof(GT_VTU_ENTRY));
+	tmpVtuEntry.vid = vtuEntry[u32Data2].vid;
+	if((status = gvtuFindVidEntry(dev,&tmpVtuEntry, &found)) == GT_OK)
+	{
+		if(found == GT_TRUE)
+		{
+			MSG_PRINT(("gvtuFindVidEntry found a deleted entry.\n"));
+			testDisplayVTUEntry(dev,&tmpVtuEntry);
+			testResult = GT_FAIL;
+			tmpResult = GT_FAIL;
+		}
+	}
+
+	if(tmpResult == GT_OK)
+		MSG_PRINT(("(PASS)\n"));
+
+	return testResult;
+}
+
+GT_U32 testVTU(GT_QD_DEV *dev)
+{
+	GT_STATUS testResult, status;
+	GT_U32 testResults = 0;
+	int arg;
+
+	testResult = GT_OK;
+
+	for(arg=0; arg<5; arg++)
+	{
+		if((status=testVTUCtrl(dev,arg)) != GT_OK)
+		{
+			MSG_PRINT(("VTU Test Fail(%d) with arg %i\n", status,arg));
+			testResults |= 1 << status;
+			testResult = GT_FAIL;
+		}
+		else
+		{
+			MSG_PRINT(("VTU Test Pass with arg %i\n", arg));
+		}
+		MSG_PRINT((" \n"));
+	}
+
+	return testResults;
+}
+
+GT_U32 testSysStatus(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_U32 testResults = 0;
+	GT_BOOL mode;
+	GT_U16	data;
+	GT_U32	u32data;
+
+	MSG_PRINT(("Get Switch Mode\n"));
+
+	if((status = gsysGetSW_Mode(dev,&mode)) != GT_OK)
+	{
+		MSG_PRINT(("gsysGetSW_Mode returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		if (status == GT_FAIL)
+			return testResults;
+	}
+	MSG_PRINT(("Switch Mode : %i\n",(int)mode));
+
+	MSG_PRINT(("Get Init Ready\n"));
+
+	if((status = gsysGetInitReady(dev,&mode)) != GT_OK)
+	{
+		MSG_PRINT(("gsysGetInitReady returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		if (status == GT_FAIL)
+			return testResults;
+	}
+	MSG_PRINT(("Init Ready : %i\n",(int)mode));
+
+	MSG_PRINT(("Get Free Q Size\n"));
+
+	if((status = gsysGetFreeQSize(dev,&data)) != GT_OK)
+	{
+		MSG_PRINT(("gsysGetFreeQSize returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		if (status == GT_FAIL)
+			return testResults;
+	}
+	MSG_PRINT(("Free QSize : %i\n",(int)data));
+
+	if((status = gsysGetPPUState(dev,(GT_PPU_STATE*)&u32data)) != GT_OK)
+	{
+		MSG_PRINT(("gsysGetPPUState returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		if (status == GT_FAIL)
+			return testResults;
+	}
+	MSG_PRINT(("PPU State  : %i\n",(int)u32data));
+
+#ifdef DEBUG_FEATURE
+	MSG_PRINT(("Get QC Pointer Collision\n"));
+
+	if((status = gsysGetPtrCollision(dev,&mode)) != GT_OK)
+	{
+		MSG_PRINT(("gsysGetPtrCollision returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		if (status == GT_FAIL)
+			return testResults;
+	}
+	MSG_PRINT(("QC Pointer Collision : %i\n",(int)mode));
+
+	MSG_PRINT(("Get Dest. PortVector Corrupt\n"));
+
+	if((status = gsysGetDpvCorrupt(dev,&mode)) != GT_OK)
+	{
+		MSG_PRINT(("gsysGetDpvCorrupt returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		if (status == GT_FAIL)
+			return testResults;
+	}
+	MSG_PRINT(("Dest. PortVector Corrupt : %i\n",(int)mode));
+
+	MSG_PRINT(("Get Missing Pointer Error\n"));
+
+	if((status = gsysGetMissingPointers(dev,&mode)) != GT_OK)
+	{
+		MSG_PRINT(("gsysGetMissingPointers returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+		if (status == GT_FAIL)
+			return testResults;
+	}
+	MSG_PRINT(("Missing Pointer Error : %i\n",(int)mode));
+#endif
+
+	return testResults;
+}
+
+GT_U32 fillupPIRLData(GT_QD_DEV *dev, GT_PIRL_DATA *pdata, GT_U32 *vec)
+{
+	GT_U32	data;
+	GT_LPORT port;
+	GT_BOOL	restrict;
+
+	switch (dev->deviceId)
+	{
+		case GT_88E6031:
+		case GT_88E6061:
+			restrict = GT_TRUE;
+			break;
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6065:
+			restrict = GT_FALSE;
+			break;
+		default:
+			return GT_NOT_SUPPORTED;
+	}
+
+	/* Ingress Rate */
+	data = rand() % 200001;
+	if(data == 0)
+		data = 64;
+	else if(data < 1000)
+		data = data - (data % 64);
+	else if(data < 100000)
+		data = data - (data % 1000);
+	else
+		data = data - (data % 10000);
+
+	pdata->ingressRate = data;
+
+	pdata->accountQConf = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+	pdata->accountFiltered = (rand() & 0x1)?GT_TRUE:GT_FALSE;
+	pdata->ebsLimitAction = (rand() & 0x1);
+	if (restrict)
+	{
+		pdata->bktRateType = 0;
+		pdata->bktTypeMask = (rand() & 0xF);
+	}
+	else
+	{
+		pdata->bktRateType = (rand() & 0x1);
+		if (pdata->bktRateType == 0)
+			pdata->bktTypeMask = (rand() & 0x7F);
+		else
+			pdata->bktTypeMask = 0;
+	}
+
+	pdata->byteTobeCounted = (rand() % 3);
+
+	*vec = rand() & ((1<<dev->numOfPorts) - 1);
+	if(*vec == 0)
+		*vec = 0x7;
+
+	if(pdata->ebsLimitAction == 0)
+	{
+		return GT_OK;
+	}
+
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		if(*vec & (1 << port))
+			pdata->fcDeassertMode[port] = port & 0x1;
+	}
+
+	return GT_OK;
+}
+
+GT_U32 testPIRL(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_U32 testResults = 0;
+	GT_U32	i, portVec[12], tmpPortVec, pirlSize;
+	GT_PIRL_DATA	pirlData[12], tmpPirlData;
+	
+	srand((unsigned)time(NULL));
+
+	memset(&pirlData[0],0,sizeof(GT_PIRL_DATA));
+
+	switch (dev->deviceId)
+	{
+		case GT_88E6031:
+			pirlSize = 3;
+			break;
+		case GT_88E6061:
+		case GT_88E6035:
+			pirlSize = 6;
+			break;
+		case GT_88E6055:
+		case GT_88E6065:
+			pirlSize = 12;
+			break;
+		default:
+			return 1 << GT_NOT_SUPPORTED;
+	}
+
+
+	MSG_PRINT(("Try Invalid PIRL API call\n"));
+
+	/* try PIRL APIs without Activating it */
+
+	pirlData[0].ingressRate = 64;
+
+	if((status = gpirlUpdateParam(dev, 0, &pirlData[0])) == GT_OK)
+	{
+		MSG_PRINT(("gpirlUpdateParam returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << GT_FAIL;
+	}
+	if (status == GT_NOT_SUPPORTED)
+		return status;
+
+	portVec[0] = 0x7;
+
+	if((status = gpirlUpdatePortVec(dev, 0, portVec[0])) == GT_OK)
+	{
+		MSG_PRINT(("gpirlUpdateParam returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << GT_FAIL;
+	}
+
+	if (testResults)
+	{
+		MSG_PRINT(("Invalid PIRL API call failed\n"));
+	}
+	else
+	{
+		MSG_PRINT(("Invalid PIRL API call successed\n"));
+	}
+
+
+	/* Activate PIRL */
+	MSG_PRINT(("Filling up the PIRL Data...\n"));
+	for(i=0; i<pirlSize; i++)
+	{
+		memset(&pirlData[i],0,sizeof(GT_PIRL_DATA));
+		fillupPIRLData(dev, &pirlData[i], &portVec[i]);
+	}		
+
+	MSG_PRINT(("Activate Pirl...\n"));
+	for(i=0; i<pirlSize; i++)
+	{
+		if((status = gpirlActivate(dev,i,portVec[i],&pirlData[i])) != GT_OK)
+		{
+			MSG_PRINT(("gpirlActivate returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+		}
+		if (status == GT_FAIL)
+			return testResults;
+	}	
+
+	MSG_PRINT(("Comparing...\n"));
+	for(i=0; i<pirlSize; i++)
+	{
+		memset(&tmpPirlData,0,sizeof(GT_PIRL_DATA));
+		if((status = gpirlReadParam(dev,i,&tmpPirlData)) != GT_OK)
+		{
+			MSG_PRINT(("gpirlReadParam returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+			continue;
+		}
+
+		if(memcmp(&tmpPirlData, &pirlData[i], sizeof(GT_PIRL_DATA)))
+		{
+			MSG_PRINT(("gpirlReadParam returned wrong entry (unit %i).",i));
+			dumpMemory((char*)&tmpPirlData, sizeof(GT_PIRL_DATA));
+			MSG_PRINT(("Expected entry:"));
+			dumpMemory((char*)&pirlData[i], sizeof(GT_PIRL_DATA));
+			testResults |= 1 << GT_FAIL;
+		}
+
+		if((status = gpirlReadPortVec(dev,i,&tmpPortVec)) != GT_OK)
+		{
+			MSG_PRINT(("gpirlReadParam returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+		}
+
+		if(tmpPortVec != portVec[i])
+		{
+			MSG_PRINT(("gpirlReadPortVec returned wrong data (unit %i) : %#x.\n",i,tmpPortVec));
+			MSG_PRINT(("Expected vector: %#x\n",portVec[i]));
+			testResults |= 1 << GT_FAIL;
+		}
+	}
+
+	i = 1;	/* IRL Unit number to be played with */
+
+	MSG_PRINT(("Update Unit %i's IRL Data.\n",i));
+
+	memset(&pirlData[i],0,sizeof(GT_PIRL_DATA));
+	fillupPIRLData(dev, &pirlData[i], &portVec[i]);
+	
+	if((status = gpirlUpdateParam(dev,i,&pirlData[i])) != GT_OK)
+	{
+		MSG_PRINT(("gpirlUpdateParam returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+	}
+	if (status == GT_FAIL)
+		return testResults;
+	
+	if((status = gpirlUpdatePortVec(dev,i,portVec[i])) != GT_OK)
+	{
+		MSG_PRINT(("gpirlUpdatePortVec returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+	}
+	if (status == GT_FAIL)
+		return testResults;
+	
+	MSG_PRINT(("Comparing Updated data...\n"));
+
+	memset(&tmpPirlData,0,sizeof(GT_PIRL_DATA));
+	if((status = gpirlReadParam(dev,i,&tmpPirlData)) != GT_OK)
+	{
+		MSG_PRINT(("gpirlReadParam returned "));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+	}
+
+	if(memcmp(&tmpPirlData, &pirlData[i], sizeof(GT_PIRL_DATA)))
+	{
+		MSG_PRINT(("gpirlReadParam returned wrong entry (unit %i).",i));
+		dumpMemory((char*)&tmpPirlData, sizeof(GT_PIRL_DATA));
+		MSG_PRINT(("Expected entry:"));
+		dumpMemory((char*)&pirlData[i], sizeof(GT_PIRL_DATA));
+		testResults |= 1 << GT_FAIL;
+	}
+
+	if((status = gpirlReadPortVec(dev,i,&tmpPortVec)) != GT_OK)
+	{
+		MSG_PRINT(("gpirlReadParam returned \n"));
+		testDisplayStatus(status);
+		testResults |= 1 << status;
+	}
+
+	if(tmpPortVec != portVec[i])
+	{
+		MSG_PRINT(("gpirlReadPortVec returned wrong data (unit %i) : %#x.\n",i,tmpPortVec));
+		MSG_PRINT(("Expected vector: %#x\n",portVec[i]));
+		testResults |= 1 << GT_FAIL;
+	}
+
+	MSG_PRINT(("Deactivate Pirl...\n"));
+	for(i=0; i<pirlSize; i++)
+	{
+		if((status = gpirlDeactivate(dev,i)) != GT_OK)
+		{
+			MSG_PRINT(("gpirlDeactivate returned "));
+			testDisplayStatus(status);
+			testResults |= 1 << status;
+		}
+		if (status == GT_FAIL)
+			return testResults;
+	}	
+
+	return testResults;
+}
+
+
+GT_STATUS testPartialAll(GT_QD_DEV *dev, GT_U32 tests)
+{
+	int i,j;
+	GT_STATUS testResult = GT_OK;
+	GT_U32	testResults[32];
+	
+	i = 0;
+	while(1)
+	{
+		if (testStruct[i].testFunc == NULL)
+			break;
+
+		if (!(tests & (1<<i)))
+		{
+			i++;
+			continue;
+		}
+
+		testResults[i] = testStruct[i].testFunc(dev);
+		i++;
+	}
+
+	printf("\nTest Result\n");
+	i = 0;
+	while(1)
+	{
+		if (testStruct[i].testFunc == NULL)
+			break;
+
+		if (!(tests & (1<<i)))
+		{
+			i++;
+			continue;
+		}
+
+		printf("%s ",testStruct[i].strTest);
+		
+		if(testResults[i] == 0)
+		{
+		 	printf("PASS\n");
+			i++;
+			continue;
+		}
+		for(j=0;j<32;j++)
+		{
+			if(testResults[i] & (1<<j))
+			{
+				switch(j)
+				{
+					case GT_OK:
+						printf("PASS ");
+						break;
+					case GT_FAIL :
+						printf("one or more Failure ");
+						break;
+					case GT_NOT_SUPPORTED :
+						printf("one or more Not Supported ");
+						break;
+					default:
+						printf("one or more FAIL ");
+						break;
+				}
+			}
+		}
+		printf("\n");
+		i++;
+	}
+
+	return testResult;
+}
+
+
+GT_STATUS testAll(GT_QD_DEV *dev)
+{
+	int i,j;
+	GT_STATUS testResult = GT_OK;
+	
+	i = 0;
+	while(1)
+	{
+		if (testStruct[i].testFunc == NULL)
+			break;
+
+		MSG_PRINT(("\nTesting %s\n",testStruct[i].strTest));
+		
+		testStruct[i].testResults = testStruct[i].testFunc(dev);
+		i++;
+	}
+
+	MSG_PRINT(("\nTest Result\n"));
+	i = 0;
+	while(1)
+	{
+		if (testStruct[i].testFunc == NULL)
+			break;
+
+		MSG_PRINT(("%s ",testStruct[i].strTest));
+		
+		if(testStruct[i].testResults == 0)
+		{
+		 	MSG_PRINT(("PASS\n"));
+			i++;
+			continue;
+		}
+		for(j=0;j<32;j++)
+		{
+			if(testStruct[i].testResults & (1<<j))
+			{
+				switch(j)
+				{
+					case GT_OK:
+						MSG_PRINT(("PASS "));
+						break;
+					case GT_FAIL :
+						MSG_PRINT(("one or more Failure "));
+						break;
+					case GT_NOT_SUPPORTED :
+						MSG_PRINT(("one or more Not Supported "));
+						break;
+					default:
+						MSG_PRINT(("one or more FAIL "));
+						break;
+				}
+			}
+		}
+		MSG_PRINT(("\n"));
+		i++;
+	}
+
+	return testResult;
+}
+
+
+/*
+ * Start Packet Generator.
+ * Input:
+ *      pktload - enum GT_PG_PAYLOAD (GT_PG_PAYLOAD_RANDOM or GT_PG_PAYLOAD_5AA5)
+ *      length  - enum GT_PG_LENGTH  (GT_PG_LENGTH_64 or GT_PG_LENGTH_1514)
+ *      tx      - enum GT_PG_TX      (GT_PG_TX_NORMAL or GT_PG_TX_ERROR)
+*/
+GT_STATUS testStartPktGen
+(
+    GT_QD_DEV      *dev,
+    GT_LPORT       port,
+    GT_PG_PAYLOAD  payload,
+    GT_PG_LENGTH   length,
+    GT_PG_TX       tx
+)
+{
+    GT_STATUS status;
+    GT_PG     pktInfo;
+
+    if (dev == 0)
+    {
+        MSG_PRINT(("GT driver is not initialized\n"));
+        return GT_FAIL;
+    }
+
+    MSG_PRINT(("Start Packet Generator for port %i\n",(int)port));
+
+    pktInfo.payload = payload; /* Pseudo-random, 5AA55AA5... */
+    pktInfo.length = length;   /* 64 bytes, 1514 bytes */
+    pktInfo.tx = tx;           /* normal packet, error packet */
+
+    /*
+     *	Start Packet Generator
+    */
+    if((status = gprtSetPktGenEnable(dev,port,GT_TRUE,&pktInfo)) != GT_OK)
+    {
+        MSG_PRINT(("gprtSetPktGenEnable return Failed\n"));
+        return status;
+    }
+
+    return GT_OK;
+}
+
+
+/*
+ * Stop Packet Generator.
+ */
+GT_STATUS testStopPktGen(GT_QD_DEV *dev,GT_LPORT port)
+{
+    GT_STATUS status;
+
+    if (dev == 0)
+    {
+        MSG_PRINT(("GT driver is not initialized\n"));
+        return GT_FAIL;
+    }
+
+    MSG_PRINT(("Stopping Packet Generator for port %i\n",(int)port));
+
+    /*
+     *	Start Packet Generator
+    */
+    if((status = gprtSetPktGenEnable(dev,port,GT_FALSE,NULL)) != GT_OK)
+    {
+        MSG_PRINT(("gprtSetPktGenEnable return Failed\n"));
+        return status;
+    }
+
+    return GT_OK;
+}
+
+void testDisplayCableTestResult
+(
+	GT_TEST_STATUS *cableStatus, 
+	GT_CABLE_LEN *cableLen
+)
+{
+	switch(*cableStatus)
+	{
+		case GT_TEST_FAIL:
+			MSG_PRINT(("Cable Test Failed\n"));
+			break;
+		case GT_NORMAL_CABLE:
+			MSG_PRINT(("Cable Test Passed. No problem found.\n"));
+			switch(cableLen->normCableLen)
+			{
+				case GT_LESS_THAN_50M:
+					MSG_PRINT(("Cable Length is less than 50M.\n"));
+					break;
+				case GT_50M_80M:
+					MSG_PRINT(("Cable Length is between 50M and 80M.\n"));
+					break;
+				case GT_80M_110M:
+					MSG_PRINT(("Cable Length is between 80M and 110M.\n"));
+					break;
+				case GT_110M_140M:
+					MSG_PRINT(("Cable Length is between 110M and 140M.\n"));
+					break;
+				case GT_MORE_THAN_140:
+					MSG_PRINT(("Cable Length is over 140M.\n"));
+					break;
+				default:
+					MSG_PRINT(("Cable Length is unknown.\n"));
+					break;
+			}
+			break;
+		case GT_OPEN_CABLE:
+			MSG_PRINT(("Cable Test Passed. Cable is open.\n"));
+			MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableLen->errCableLen));
+			break;
+		case GT_SHORT_CABLE:
+			MSG_PRINT(("Cable Test Passed. Cable is short.\n"));
+			MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableLen->errCableLen));
+			break;
+		default:
+			MSG_PRINT(("Unknown Test Result.\n"));
+			break;
+	}
+}
+
+GT_STATUS dumpATUInfo(ATU_ENTRY_INFO *atuInfo, int entry)
+{
+	int i;
+
+	for(i=0; i<entry; i++)
+	{
+		printATUEntry(&atuInfo->atuEntry);
+		atuInfo++;
+	}
+	return GT_OK;
+}
+
+GT_STATUS testWriteATU(GT_QD_DEV *dev,GT_U8 atuSize,GT_U8 dbNum,GT_U32 entryState,GT_U32 macHiAddr,GT_U32 entries)
+{
+	GT_STATUS status;
+	ATU_ENTRY_INFO *atuEntry;
+	GT_U16 maxMacs, i;
+
+	if(atuSize >= 5)
+		return GT_FAIL;
+
+	if(entries == 0)
+		maxMacs = 256 << atuSize;
+	else
+		maxMacs = entries;
+
+	if (gAtuEntry == NULL)
+		gAtuEntry = (ATU_ENTRY_INFO *)malloc(sizeof(ATU_ENTRY_INFO)*4096);
+
+	atuEntry = gAtuEntry;
+
+	gtMemSet(atuEntry,0,sizeof(ATU_ENTRY_INFO)*maxMacs);
+
+	MSG_PRINT(("Getting ATU List(%i).\n",maxMacs));
+	if((status=testFillUpAtu(dev,atuEntry,atuSize,dbNum,(GT_U16)macHiAddr,entryState)) != GT_OK)
+	{
+		MSG_PRINT(("testFillUpAtu returned "));
+		testDisplayStatus(status);
+		return status;
+	}
+
+	MSG_PRINT(("Writing ATU List(%i).\n",maxMacs));
+	for(i=0; i<maxMacs; i++)
+	{
+		if((status = gfdbAddMacEntry(dev,&atuEntry[i].atuEntry)) != GT_OK)
+		{
+			MSG_PRINT(("gfdbAddMacEntry returned "));
+			testDisplayStatus(status);
+			return status;
+		}
+	}
+
+	return GT_OK;
+}
+
+GT_STATUS runRWDir(GT_QD_DEV *dev, int port, int reg, int iter, int startV, int endV, int timeout)
+{
+	int i;
+	GT_U32 data, tmpData;
+	volatile int d;
+
+	for (i=0; i<iter; i++)
+	{
+		for(data = startV; data <= endV; data++)
+		{
+			gsysWriteMiiReg(dev,port,reg,data);
+	        for(d = 0 ; d <timeout  ; d++);
+			gsysReadMiiReg(dev,port,reg,&tmpData);
+			if(data != tmpData)
+			{
+				MSG_PRINT(("Data Mismatch : iter %i, wrote %#x, read %#x \n",i,data,tmpData));
+				return GT_FAIL;
+			}
+		}
+		
+	}
+	MSG_PRINT(("Success\n"));
+	return GT_OK;
+}
+
+GT_STATUS testDisplayTrunkRouting(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_U32 route, id;
+
+	printf("Trunk Routing Table\n");
+
+	for (id=0; id<16; id++)
+	{
+		if((status = gsysGetTrunkRouting(dev,id,&route)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkRouting return Failed\n"));
+			return status;
+		}
+		if(!route)
+			continue;
+		printf("ID %i : %#x\n",(int)id,(int)route);
+	}
+	return GT_OK;
+}
+
+GT_STATUS testDisplayTrunkMask(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	int i;
+	GT_U32 mask;
+
+	printf("Trunk Mask Table\n");
+
+	for (i=0; i<8; i++)
+	{
+		if((status = gsysGetTrunkMaskTable(dev,i,&mask)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkMaskTable return Failed\n"));
+			return status;
+		}
+		printf("%i : %#x\n",i+1,(int)mask);
+	}
+	return GT_OK;
+}
+
+GT_STATUS qdStatusShow(GT_QD_DEV *dev)
+{
+	GT_U32 regBaseAddr,u32Data;
+	GT_LPORT port;
+	int portIndex;
+
+	regBaseAddr	= dev->baseRegAddr;
+
+	MSG_PRINT(("Switch Status (offset 0): "));
+	gsysReadMiiReg(dev,regBaseAddr+0xF,0,&u32Data);
+	MSG_PRINT(("%#04x\n",u32Data & 0xFFFF));
+	
+	MSG_PRINT(("VTU Status (offset 5)   : "));
+	gsysReadMiiReg(dev,regBaseAddr+0xF,5,&u32Data);
+	MSG_PRINT(("%#04x\n",u32Data & 0xFFFF));
+	
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+		
+		MSG_PRINT(("Port %i Status (offset 0): ", port));
+		gsysReadMiiReg(dev,regBaseAddr+0x8+port,0,&u32Data);
+		MSG_PRINT(("%#04x\n",u32Data & 0xFFFF));
+	}
+	return GT_OK;
+}
+GT_STATUS testHelp()
+{
+	MSG_PRINT(("qdStart - to Initialize QuarterDeck driver\n"));
+	MSG_PRINT(("testSysCtrl - to test System Control API\n"));
+	MSG_PRINT(("testPort - to test Port Control API\n"));
+	MSG_PRINT(("testATU - to test ATU related API\n"));
+	MSG_PRINT(("testRMON - to test RMON related API\n"));
+	MSG_PRINT(("testVTU - to test VTU related API\n"));
+	MSG_PRINT(("testSysStatus - to test System Status related API\n"));
+	MSG_PRINT(("testVlan - to test Vlan related API\n"));
+	MSG_PRINT(("testSTP - to test STP related API\n"));
+	MSG_PRINT(("testPhy - to test Phy related API\n"));
+	MSG_PRINT(("testPortStatus - to test Port Status related API\n"));
+	MSG_PRINT(("testQosRule - to test QoS Rule related API\n"));
+	MSG_PRINT(("testQosMap - to test QoS Map related API\n"));
+	MSG_PRINT(("testPortRateCtrl - to test Port Rate Control API\n"));
+	MSG_PRINT(("testPortPAV - to test Port Association Vector API\n"));
+	MSG_PRINT(("testInterrupt - to test Interrupt related API\n"));
+	MSG_PRINT(("testAll - to run all the test specified above.\n"));
+	MSG_PRINT(("\n"));
+	MSG_PRINT(("vctTest - to run Virtual Cable Test on a given port.\n"));
+	MSG_PRINT(("defaultVlan - to setup Vlan for firewall app\n"));
+	MSG_PRINT(("readStatistics - to read statistics\n"));
+	MSG_PRINT(("testGoodPkt - to setup Good Packet only mode\n"));
+	MSG_PRINT(("testBadPkt - to setup Bad Packet only mode\n"));
+	MSG_PRINT(("testDisplayATUList - to display ATU list in the device\n"));
+	MSG_PRINT(("testDisplayRMONCounter - to display RMON counter of a port\n"));
+	MSG_PRINT(("testDisplayVTUList - to display VTU list in the device\n"));
+	MSG_PRINT(("qdStatusShow - to display the status of the device\n"));
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/utils.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/utils.c
new file mode 100755
index 0000000..8327638
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/utils.c
@@ -0,0 +1,711 @@
+#include <Copyright.h>
+/********************************************************************************
+* utils.c
+*
+* DESCRIPTION:
+*       Collection of Utility functions
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+static GT_U16 hashMode = 0;
+int testPrintEnable = 1;
+
+void testPrint(char* format, ...)
+{
+	va_list argP;
+	char dbgStr[1000] = "";
+
+	if(testPrintEnable == 0)
+		return;
+
+	va_start(argP, format);
+
+	vsprintf(dbgStr, format, argP);
+
+	printf("%s",dbgStr);
+
+	return;
+}
+
+int vtuEntryCmpFunc(void* buf, int a, int b)
+{
+    GT_VTU_ENTRY* vtuEntry = (GT_VTU_ENTRY*)buf;
+
+	if ((vtuEntry+a)->vid > (vtuEntry+b)->vid)
+		return 1;
+	else if ((vtuEntry+a)->vid < (vtuEntry+b)->vid)
+		return -1;
+	else
+		return 0;
+}
+
+int atuEntryCmpFunc(void* buf, int a, int b)
+{
+	GT_ATU_ENTRY *atuEntry = (GT_ATU_ENTRY *)buf;
+	GT_U8* aChar,* bChar;
+	int i;
+
+	aChar = (GT_U8*)((atuEntry+a)->macAddr.arEther);
+	bChar = (GT_U8*)((atuEntry+b)->macAddr.arEther);
+
+	for (i=0; i<6; i++)
+	{
+		if(*aChar > *bChar)
+			return 1;
+		else if (*aChar < *bChar)
+			return -1;
+		aChar++;
+		bChar++;
+	}
+
+	return 0;
+
+}
+
+/* insertion sort */
+GT_STATUS gtSort(int list[], GT_CMP_FUNC cmpFunc, void* buf, GT_U32 len)
+{
+	GT_U32 index;
+	int curValue, preValue;
+
+	if (len <= 1)
+		return GT_FAIL;
+
+	preValue = list[0];
+
+	for (index = 1; index < len; ++index)
+	{
+		curValue = list[index];
+		if ((*cmpFunc)(buf, preValue, curValue) > 0)
+		{
+			/* out of order: list[index-1] > list[index] */
+			GT_U32 index2;
+			list[index] = preValue; /* move up the larger item first */
+
+			/* find the insertion point for the smaller item */
+			for (index2 = index - 1; index2 > 0;)
+			{
+				int temp_val = list[index2 - 1];
+				if ((*cmpFunc)(buf, temp_val, curValue) > 0)
+				{
+					list[index2--] = temp_val;
+					/* still out of order, move up 1 slot to make room */
+				}
+				else
+					break;
+			}
+			list[index2] = curValue; /* insert the smaller item right here */
+		}
+		else
+		{
+			/* in order, advance to next element */
+			preValue = curValue;
+		}
+	}
+	return GT_OK;
+}
+ 
+
+GT_U16 hashFunction(char eaddr[])
+{
+	GT_U16 crc_reg;
+	GT_U8 crc_in;
+	int i,j;
+
+	crc_reg=0;
+	
+	for(i=0; i<6; i++)
+	{
+		crc_in = eaddr[5-i];
+		for(j=0; j<8; j++)
+		{
+			crc_reg = ((((crc_in & 1) ^ ((crc_reg>>15) & 1)) ^ 
+						((crc_reg>>14) & 1)) << 15)				|	/* bit 15 */
+						((crc_reg & 0x3FFC) << 1) 				|	/* bit 14:3 */
+						((((crc_in & 1) ^ ((crc_reg>>15) & 1)) ^ 
+						((crc_reg>>1) & 1)) << 2) 				|	/* bit 2 */
+						((crc_reg & 1) << 1)					| 	/* bit 1 */
+						((crc_in & 1) ^ ((crc_reg>>15) & 1));		/* bit 0 */
+
+			crc_in >>= 1;
+		}
+	}
+
+	return crc_reg;
+}
+
+
+GT_U16 hashToBucket(GT_U16 hash, GT_U16 mode)
+{
+	GT_U16 bucket;
+
+	switch (mode)
+	{
+		case 0:
+			bucket = 
+			(((hash >> 7) & 1) << 10) |		/* bit 10 */
+			(((hash >> 11) & 1) << 9) |		/* bit 9 */
+			(((hash >> 3 ) & 1) << 8) |		/* bit 8 */
+			(((hash >> 14) & 1) << 7) |		/* bit 7 */
+			(((hash >> 12) & 1) << 6) |		/* bit 6 */
+			(((hash >> 10) & 1) << 5) |		/* bit 5 */
+			(((hash >> 8 ) & 1) << 4) |		/* bit 4 */
+			(((hash >> 6 ) & 1) << 3) |		/* bit 3 */
+			(((hash >> 4 ) & 1) << 2) |		/* bit 2 */
+			(((hash >> 2 ) & 1) << 1) |		/* bit 1 */
+			(( hash >> 0 ) & 1); 			/* bit 0 */
+			break;
+		case 1:
+			bucket = 
+			(((hash >> 2) & 1) << 10) |		/* bit 10 */
+			(((hash >> 12) & 1) << 9) |		/* bit 9 */
+			(((hash >> 0 ) & 1) << 8) |		/* bit 8 */
+			(((hash >> 10) & 1) << 7) |		/* bit 7 */
+			(((hash >> 8 ) & 1) << 6) |		/* bit 6 */
+			(((hash >> 7 ) & 1) << 5) |		/* bit 5 */
+			(((hash >> 6 ) & 1) << 4) |		/* bit 4 */
+			(((hash >> 5 ) & 1) << 3) |		/* bit 3 */
+			(((hash >> 4 ) & 1) << 2) |		/* bit 2 */
+			(((hash >> 3 ) & 1) << 1) |		/* bit 1 */
+			(( hash >> 1 ) & 1); 			/* bit 0 */
+			break;
+		case 2:
+			bucket = 
+			(((hash >> 13) & 1) << 10)|		/* bit 10 */
+			(((hash >> 15) & 1) << 9) |		/* bit 9 */
+			(((hash >> 3 ) & 1) << 8) |		/* bit 8 */
+			(((hash >> 14) & 1) << 7) |		/* bit 7 */
+			(((hash >> 12) & 1) << 6) |		/* bit 6 */
+			(((hash >> 11) & 1) << 5) |		/* bit 5 */
+			(((hash >> 10) & 1) << 4) |		/* bit 4 */
+			(((hash >> 9 ) & 1) << 3) |		/* bit 3 */
+			(((hash >> 8 ) & 1) << 2) |		/* bit 2 */
+			(((hash >> 7 ) & 1) << 1) |		/* bit 1 */
+			(( hash >> 5 ) & 1); 			/* bit 0 */
+			break;
+		case 3:
+			bucket = 
+			(((hash >> 10) & 1) << 10)|		/* bit 10 */
+			(((hash >> 8 ) & 1) << 9) |		/* bit 9 */
+			(((hash >> 7 ) & 1) << 8) |		/* bit 8 */
+			(((hash >> 13) & 1) << 7) |		/* bit 7 */
+			(((hash >> 12) & 1) << 6) |		/* bit 6 */
+			(((hash >> 10) & 1) << 5) |		/* bit 5 */
+			(((hash >> 9 ) & 1) << 4) |		/* bit 4 */
+			(((hash >> 6 ) & 1) << 3) |		/* bit 3 */
+			(((hash >> 5 ) & 1) << 2) |		/* bit 2 */
+			(((hash >> 3 ) & 1) << 1) |		/* bit 1 */
+			(( hash >> 2 ) & 1); 			/* bit 0 */
+			break;
+		default:
+			/* treat as case 0 */
+			bucket = 
+			(((hash >> 7) & 1) << 10) |		/* bit 10 */
+			(((hash >> 11) & 1) << 9) |		/* bit 9 */
+			(((hash >> 3 ) & 1) << 8) |		/* bit 8 */
+			(((hash >> 14) & 1) << 7) |		/* bit 7 */
+			(((hash >> 12) & 1) << 6) |		/* bit 6 */
+			(((hash >> 10) & 1) << 5) |		/* bit 5 */
+			(((hash >> 8 ) & 1) << 4) |		/* bit 4 */
+			(((hash >> 6 ) & 1) << 3) |		/* bit 3 */
+			(((hash >> 4 ) & 1) << 2) |		/* bit 2 */
+			(((hash >> 2 ) & 1) << 1) |		/* bit 1 */
+			(( hash >> 0 ) & 1); 			/* bit 0 */
+			break;
+	}
+	return bucket;
+}
+
+GT_U16 dbNumMap(GT_U32 bucket, GT_U32 dbNum)
+{
+	return (GT_U16)(bucket + dbNum);
+}
+
+GT_U16 runQDHash(GT_U8* eaddr, GT_U16 dbNum, int bSize, GT_U16* pHash, GT_U16* preBucket, GT_U16* posBucket)
+{
+	GT_U16 hash, bucket;
+
+	hash = hashFunction(eaddr);
+	if (pHash)
+		*pHash = hash;
+	bucket = hashToBucket(hash,hashMode);
+	bucket &= (bSize-1);
+	if (preBucket)
+		*preBucket = bucket;
+	bucket = dbNumMap(bucket,dbNum);
+	if (posBucket)
+		*posBucket = bucket;
+	bucket &= (bSize-1);
+
+	return bucket;
+}
+
+GT_U16 hashTest(unsigned int maxMacs, int maxDbNum, int bSize)
+{
+	char eaddr[6] = {0,0,0,0,0,0};
+	char buckets[MAX_BUCKET_SIZE];
+	GT_U32 i, dbNum;
+	GT_U16 hash, bucket, tmpBucket;
+
+	gtMemSet(buckets,0,MAX_BUCKET_SIZE);
+
+	for(dbNum=0; dbNum<(GT_U32)maxDbNum; dbNum++)
+	{
+		MSG_PRINT(("DBNum %i:\n", dbNum));
+		for(i=1; i<maxMacs; i++)
+		{
+			eaddr[2] = (char)((i >> 24) & 0xff);
+			eaddr[3] = (char)((i >> 16) & 0xff);
+			eaddr[4] = (char)((i >> 8) & 0xff);
+			eaddr[5] = (char)(i & 0xff);
+			tmpBucket=runQDHash((GT_U8*)eaddr, (GT_U16)dbNum, bSize, &hash, &bucket, NULL);
+			buckets[tmpBucket]++;
+			MSG_PRINT(("EADDR : %02x-%02x-%02x-%02x, ", eaddr[2],eaddr[3],eaddr[4],eaddr[5]));
+			MSG_PRINT(("Hash : %03x, ", hash));
+			MSG_PRINT(("bucket : %03x, ", bucket));
+			MSG_PRINT(("bins : %02x\n", buckets[tmpBucket]-1));
+		}
+
+	}
+
+	return 0;
+}
+
+GT_U16 hashFindEntriesInBucket(unsigned int maxMacs, int bucketNum, int bSize)
+{
+	char eaddr[6] = {0,0,0,0,0,0};
+	char buckets[MAX_BUCKET_SIZE];
+	GT_U32 i, dbNum;
+	GT_U16 hash, bucket, tmpBucket;
+
+	gtMemSet(buckets,0,MAX_BUCKET_SIZE);
+
+	dbNum = 0;
+	MSG_PRINT(("DBNum %i:\n", dbNum));
+	for(i=1; i<maxMacs; i++)
+	{
+		eaddr[2] = (char)((i >> 24) & 0xff);
+		eaddr[3] = (char)((i >> 16) & 0xff);
+		eaddr[4] = (char)((i >> 8) & 0xff);
+		eaddr[5] = (char)(i & 0xff);
+		tmpBucket=runQDHash((GT_U8*)eaddr, (GT_U16)dbNum, bSize, &hash, &bucket, NULL);
+		buckets[tmpBucket]++;
+		if (tmpBucket != bucketNum)
+			continue;
+		MSG_PRINT(("EADDR : %02x-%02x-%02x-%02x, ", eaddr[2],eaddr[3],eaddr[4],eaddr[5]));
+		MSG_PRINT(("Hash : %03x, ", hash));
+		MSG_PRINT(("bucket : %03x, ", bucket));
+		MSG_PRINT(("bins : %02x\n", buckets[tmpBucket]-1));
+	}
+
+	return 0;
+}
+
+void displayHash(char* eaddr, GT_U16 dbNum, GT_U32 bSize)
+{
+	GT_U16 hash, posBucket, preBucket;
+
+	posBucket=runQDHash(eaddr, dbNum, bSize, &hash, &preBucket, NULL);
+	MSG_PRINT(("EADDR : %02x-%02x-%02x-%02x, ", eaddr[2],eaddr[3],eaddr[4],eaddr[5]));
+	MSG_PRINT(("Hash : %03x, ", hash));
+	MSG_PRINT(("bucket : %03x, ", preBucket));
+	MSG_PRINT(("bucket(db) : %03x, ", posBucket));
+	MSG_PRINT(("bSize : %03x\n", bSize));
+}
+
+GT_U16 hashWrap(int bSize, int entry)
+{
+	char eaddr[6] = {0,0,0,0,0,0};
+	char buckets[MAX_BUCKET_SIZE];
+	GT_U32 i, maxMacs;
+	GT_U16 hash, bucket, tmpBucket, preBucket;
+	int wrapping = 0;
+	maxMacs =0xFFFFFFFF;
+	gtMemSet(buckets,0,MAX_BUCKET_SIZE);
+
+	MSG_PRINT(("Wrapped Entry :\n"));
+	for(i=1; i<maxMacs; i++)
+	{
+		eaddr[2] = (char)((i >> 24) & 0xff);
+		eaddr[3] = (char)((i >> 16) & 0xff);
+		eaddr[4] = (char)((i >> 8) & 0xff);
+		eaddr[5] = (char)(i & 0xff);
+		tmpBucket = runQDHash(eaddr, 15, bSize, &hash, &preBucket, &bucket);
+		buckets[tmpBucket]++;
+		if(bucket != tmpBucket)
+		{
+			wrapping++;
+			MSG_PRINT(("EADDR : %02x-%02x-%02x-%02x, ", eaddr[2],eaddr[3],eaddr[4],eaddr[5]));
+			MSG_PRINT(("Hash : %03x, ", hash));
+			MSG_PRINT(("bucket : %03x, ", preBucket));
+			MSG_PRINT(("bucket(db) : %03x, ", tmpBucket));
+			MSG_PRINT(("bins : %02x\n", buckets[tmpBucket]-1));
+		}
+		if (wrapping >= entry)
+			break;
+	}
+
+	return wrapping;
+}
+
+/*
+	This routine will create ATU Entry List.
+	Input
+		entrySize - entry size for each dbNum
+		dbNumSize - number of DBNums
+		sameMacs  - how many same MAC addresses are in the ATU database.
+				 	Each of the same addresses are beloging to different DBNum.
+*/
+GT_U16 createATUList(GT_QD_DEV *dev,TEST_ATU_ENTRY entry[], GT_U16 entrySize, GT_U16 dbNumSize, GT_U16 sameMacs, GT_U16 bSize)
+{
+	GT_U16 i;
+	char* buckets;
+	GT_U16 dynamicMacs = 0;
+	GT_U16 bucket,dbNum,binSize;
+	GT_BOOL	exPrio, fqPri;
+
+	if(dbNumSize == 0)
+		return entrySize+1;
+	if(entrySize < sameMacs)
+		return entrySize+1;
+
+	buckets = (char*)malloc(MAX_BUCKET_SIZE);
+	if(buckets == NULL)
+	{
+		printf("No more available memories\n");
+		return -1;
+	}
+	gtMemSet(buckets,0,MAX_BUCKET_SIZE);
+
+#ifndef TEST_DEBUG
+	srand((unsigned)time(NULL));
+#else
+	srand((unsigned)1);
+#endif
+
+	binSize = 4;
+	switch(dev->deviceId)
+	{
+		case GT_88E6131:
+		case GT_88E6108:
+			hashMode = 1;
+			exPrio = GT_FALSE;
+			fqPri = GT_FALSE;
+			break;
+		case GT_88E6031:
+		case GT_88E6061:
+			hashMode = 1;
+			exPrio = GT_TRUE;
+			fqPri = GT_FALSE;
+			break;
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6065:
+			hashMode = 1;
+			exPrio = GT_TRUE;
+			fqPri = GT_TRUE;
+			break;
+		default:
+			exPrio = GT_FALSE;
+			fqPri = GT_FALSE;
+			hashMode = 0;
+			break;
+	}			
+
+	for(i=0; i<entrySize; i++)
+	{
+		if(sameMacs)
+		{
+			memset(&entry[0].atuEntry[i],0,sizeof(GT_ATU_ENTRY));
+			
+			*(GT_U16*)entry[0].atuEntry[i].macAddr.arEther = (GT_U16)rand();
+			*(GT_U16*)(entry[0].atuEntry[i].macAddr.arEther+2) = (GT_U16)(rand() & 0xFFFF);
+
+			do 
+			{
+				GT_U16 tmpBucket[256];
+				*(GT_U16*)(entry[0].atuEntry[i].macAddr.arEther+4) = (GT_U16)(rand() & 0xFFFF);
+
+				for (dbNum=0; dbNum<dbNumSize; dbNum++)
+				{
+					/* In current implementation, each dbNum will located in different bucket. */
+
+					tmpBucket[dbNum] = runQDHash(entry[0].atuEntry[i].macAddr.arEther, dbNum, bSize, NULL,NULL,NULL);
+					if (buckets[tmpBucket[dbNum]] >= binSize)
+					{
+						/* if bucket is full, find another entry. */
+						break;
+					}
+					else
+					{
+						continue;
+					}
+				}
+
+				if (dbNum == dbNumSize)
+				{
+					/* we found a entry which meets our requirement. */
+					entry[0].atuEntry[i].portVec = (GT_U32)(rand() & 0x3FF) % (1<<dev->numOfPorts);
+					if(entry[0].atuEntry[i].portVec == 0)
+						entry[0].atuEntry[i].portVec = 0x3;
+					if(!exPrio)
+					{
+						entry[0].atuEntry[i].prio = (GT_U8)(rand() & 0x3);
+					}
+					else
+					{
+						entry[0].atuEntry[i].exPrio.macQPri = (GT_U8)(rand() & 0x3);
+						if(fqPri)
+						{
+							entry[0].atuEntry[i].exPrio.macFPri = (GT_U8)(rand() & 0x7);
+							entry[0].atuEntry[i].exPrio.useMacFPri = GT_TRUE;
+						}
+					}
+
+					if(entry[0].atuEntry[i].macAddr.arEther[0] & 0x1)
+					{
+						entry[0].atuEntry[i].entryState.mcEntryState = GT_MC_STATIC;
+					}
+					else
+					{
+						entry[0].atuEntry[i].entryState.ucEntryState = GT_UC_DYNAMIC;
+						dynamicMacs+=dbNumSize;
+					}
+
+					buckets[tmpBucket[0]]++;
+					for (dbNum=1; dbNum<dbNumSize; dbNum++)
+					{
+						buckets[tmpBucket[dbNum]]++;
+						memcpy(&entry[dbNum].atuEntry[i],&entry[0].atuEntry[i],sizeof(GT_ATU_ENTRY));
+						entry[dbNum].atuEntry[i].DBNum = (GT_U8)dbNum;
+					}
+#ifdef TEST_DEBUG
+					MSG_PRINT(("MAC : %02x-%02x-%02x-%02x-%02x-%02x, ",
+									entry[dbNum].atuEntry[i].macAddr.arEther[0],
+									entry[dbNum].atuEntry[i].macAddr.arEther[1],
+									entry[dbNum].atuEntry[i].macAddr.arEther[2],
+									entry[dbNum].atuEntry[i].macAddr.arEther[3],
+									entry[dbNum].atuEntry[i].macAddr.arEther[4],
+									entry[dbNum].atuEntry[i].macAddr.arEther[5] ));
+					MSG_PRINT(("dbNum 0 ~ %x, bucket %03x ~ %03x\n", dbNumSize, tmpBucket[0], tmpBucket[dbNumSize-1]));
+#endif
+					break;	/* we are done with current dbNum. so exit the while loop */
+				}
+			} while (1);
+
+			sameMacs--;
+		}
+		else
+		{
+			for(dbNum=0; dbNum<dbNumSize; dbNum++)
+			{
+				memset(&entry[dbNum].atuEntry[i],0,sizeof(GT_ATU_ENTRY));
+			
+				*(GT_U16*)entry[dbNum].atuEntry[i].macAddr.arEther = (GT_U16)rand();
+				*(GT_U16*)(entry[dbNum].atuEntry[i].macAddr.arEther+2) = (GT_U16)(rand() & 0xFFFF);
+
+				do 
+				{
+					*(GT_U16*)(entry[dbNum].atuEntry[i].macAddr.arEther+4) = (GT_U16)(rand() & 0xFFFF);
+
+					bucket=runQDHash(entry[dbNum].atuEntry[i].macAddr.arEther, dbNum, bSize, NULL,NULL,NULL);
+					if (buckets[bucket] >= binSize)
+						continue;
+					else
+					{
+#ifdef TEST_DEBUG
+						MSG_PRINT(("MAC : %02x-%02x-%02x-%02x-%02x-%02x, ",
+									entry[dbNum].atuEntry[i].macAddr.arEther[0],
+									entry[dbNum].atuEntry[i].macAddr.arEther[1],
+									entry[dbNum].atuEntry[i].macAddr.arEther[2],
+									entry[dbNum].atuEntry[i].macAddr.arEther[3],
+									entry[dbNum].atuEntry[i].macAddr.arEther[4],
+									entry[dbNum].atuEntry[i].macAddr.arEther[5] ));
+						MSG_PRINT(("dbNum : %04x, ", dbNum));
+						MSG_PRINT(("bucket : %03x, bins : %02x\n", bucket,buckets[bucket]));
+#endif
+						buckets[bucket]++;
+						break;
+					}
+
+				} while (1);
+
+				entry[dbNum].atuEntry[i].portVec = (GT_U32)(rand() & 0x3FF) % (1<<dev->numOfPorts);
+				if(entry[dbNum].atuEntry[i].portVec == 0)
+					entry[dbNum].atuEntry[i].portVec = 0x3;
+				if(!exPrio)
+				{
+					entry[dbNum].atuEntry[i].prio = (GT_U8)(rand() & 0x3);
+				}
+				else
+				{
+					entry[dbNum].atuEntry[i].exPrio.macQPri = (GT_U8)(rand() & 0x3);
+					if(fqPri)
+					{
+						entry[dbNum].atuEntry[i].exPrio.macFPri = (GT_U8)(rand() & 0x7);
+						entry[dbNum].atuEntry[i].exPrio.useMacFPri = GT_TRUE;
+					}
+				}
+				entry[dbNum].atuEntry[i].DBNum = (GT_U8)dbNum;
+
+				if(entry[dbNum].atuEntry[i].macAddr.arEther[0] & 0x1)
+				{
+					entry[dbNum].atuEntry[i].entryState.mcEntryState = GT_MC_STATIC;
+				}
+				else
+				{
+					entry[dbNum].atuEntry[i].entryState.ucEntryState = GT_UC_DYNAMIC;
+					dynamicMacs++;
+				}
+			}
+		}
+	}
+
+	free(buckets);
+
+	return dynamicMacs;
+}
+
+
+GT_STATUS testFixedAtu(GT_QD_DEV *dev,GT_U8 dbNum,GT_U8 atuSize)
+{
+	GT_STATUS status;
+	GT_ATU_ENTRY macEntry[16];
+	int i;
+	GT_U32 u32Data1;
+
+	/* Set ATU Size will cause ATU reset and SW reset, so call before any other setup. */
+	MSG_PRINT(("Setting ATU Size\n"));
+	if((status = gfdbSetAtuSize(dev,atuSize)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbSetAtuSize returned fail.\n"));
+		return status;
+	}
+
+	/* Disable Aging */
+	MSG_PRINT(("Disable Aging Timeout... \n"));
+	if((status = gfdbSetAgingTimeout(dev,0)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbSetAgingTimeout returned fail.\n"));
+		return status;
+	}
+
+	/* Disable Learning */
+	MSG_PRINT(("Disable Learning... \n"));
+	if((status = gfdbLearnEnable(dev,GT_FALSE)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbSetAtuSize returned fail.\n"));
+		return status;
+	}
+
+	/* Flush all addresses from the ATU table. */
+	MSG_PRINT(("Flush out all the entries in the ATU Table ... \n"));
+	if((status = gfdbFlush(dev,GT_FLUSH_ALL)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbFlush returned fail.\n"));
+		return status;
+	}
+
+	/* Get Atu Dynamic Count, which should be 0, since we flush them all. */
+	if((status = gfdbGetAtuDynamicCount(dev,&u32Data1)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbGetAtuDynamicCount returned fail.\n"));
+		return status;
+	}
+
+	MSG_PRINT(("Atu Dynamic Count : %d.\n", u32Data1));
+
+	/* Now ATU table is clean. Play with our own MAC entries */	
+	MSG_PRINT(("Setup Testing Table... \n"));
+
+	gtMemSet(macEntry,0,sizeof(macEntry));
+
+	/* bucket 0xee */
+	*(GT_U16*)&macEntry[0].macAddr.arEther[4] = 0xd1b;
+	macEntry[0].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[0].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[1].macAddr.arEther[4] = 0xd1e;
+	macEntry[1].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[1].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[2].macAddr.arEther[4] = 0xddb;
+	macEntry[2].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[2].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[3].macAddr.arEther[4] = 0xdde;
+	macEntry[3].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[3].DBNum = dbNum;
+
+	/* bucket 0xef */
+	*(GT_U16*)&macEntry[4].macAddr.arEther[4] = 0xd1a;
+	macEntry[4].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[4].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[5].macAddr.arEther[4] = 0xd1f;
+	macEntry[5].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[5].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[6].macAddr.arEther[4] = 0xdda;
+	macEntry[6].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[6].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[7].macAddr.arEther[4] = 0xddf;
+	macEntry[7].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[7].DBNum = dbNum;
+
+	/* bucket 0xf0 */
+	*(GT_U16*)&macEntry[8].macAddr.arEther[4] = 0x440;
+	macEntry[8].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[8].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[9].macAddr.arEther[4] = 0x485;
+	macEntry[9].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[9].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[10].macAddr.arEther[4] = 0x1123;
+	macEntry[10].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[10].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[11].macAddr.arEther[4] = 0x1223;
+	macEntry[11].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[11].DBNum = dbNum;
+
+	/* bucket 0xf0 */
+	*(GT_U16*)&macEntry[12].macAddr.arEther[4] = 0x441;
+	macEntry[12].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[12].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[13].macAddr.arEther[4] = 0x484;
+	macEntry[13].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[13].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[14].macAddr.arEther[4] = 0xb41;
+	macEntry[14].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[14].DBNum = dbNum;
+
+	*(GT_U16*)&macEntry[15].macAddr.arEther[4] = 0x444;
+	macEntry[15].entryState.ucEntryState = GT_UC_DYNAMIC;
+	macEntry[15].DBNum = dbNum;
+
+	
+	for(i=0; i<16; i++)
+	{
+		displayHash(macEntry[i].macAddr.arEther,dbNum,64<<atuSize);
+		if((status = gfdbAddMacEntry(dev,&macEntry[i])) != GT_OK)
+		{
+			MSG_PRINT(("gfdbAddMacEntry returned fail.\n"));
+			return status;
+		}
+	}
+
+	testDisplayATUList(dev);
+	return GT_OK;
+
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/vctTest.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/vctTest.c
new file mode 100755
index 0000000..589ad61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Diag/vctTest.c
@@ -0,0 +1,181 @@
+#include <Copyright.h>
+/********************************************************************************
+* testApi.c
+*
+* DESCRIPTION:
+*       API test functions
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+void displayVCTResult
+(
+	GT_TEST_STATUS *cableStatus, 
+	GT_CABLE_LEN *cableLen
+)
+{
+	switch(*cableStatus)
+	{
+		case GT_TEST_FAIL:
+			MSG_PRINT(("Cable Test Failed\n"));
+			break;
+		case GT_NORMAL_CABLE:
+			MSG_PRINT(("Cable Test Passed. No problem found.\n"));
+			switch(cableLen->normCableLen)
+			{
+				case GT_LESS_THAN_50M:
+					MSG_PRINT(("Cable Length is less than 50M.\n"));
+					break;
+				case GT_50M_80M:
+					MSG_PRINT(("Cable Length is between 50M and 80M.\n"));
+					break;
+				case GT_80M_110M:
+					MSG_PRINT(("Cable Length is between 80M and 110M.\n"));
+					break;
+				case GT_110M_140M:
+					MSG_PRINT(("Cable Length is between 110M and 140M.\n"));
+					break;
+				case GT_MORE_THAN_140:
+					MSG_PRINT(("Cable Length is over 140M.\n"));
+					break;
+				default:
+					MSG_PRINT(("Cable Length is unknown.\n"));
+					break;
+			}
+			break;
+		case GT_IMPEDANCE_MISMATCH:
+			MSG_PRINT(("Cable Test Passed with Impedance Mismatch.\n"));
+			MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableLen->errCableLen));
+			break;
+		case GT_OPEN_CABLE:
+			MSG_PRINT(("Cable Test Passed. Cable is open.\n"));
+			MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableLen->errCableLen));
+			break;
+		case GT_SHORT_CABLE:
+			MSG_PRINT(("Cable Test Passed. Cable is short.\n"));
+			MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableLen->errCableLen));
+			break;
+		default:
+			MSG_PRINT(("Unknown Test Result.\n"));
+			break;
+	}
+}
+
+
+GT_STATUS vctTest(GT_QD_DEV *dev,GT_LPORT port)
+{
+	GT_STATUS status;
+    GT_CABLE_STATUS cableStatus;
+	int i;
+
+	if (dev == 0)
+	{
+		MSG_PRINT(("QD driver is not initialized\n"));
+		return GT_FAIL;
+#if 0
+		dev = &qdDev;
+		memset(dev, 0, sizeof(GT_QD_DEV));
+		dev->fgtReadMii = gtBspReadMii;
+		dev->fgtWriteMii = gtBspWriteMii;
+#endif
+	}
+
+	/*
+	 *	Start and get Cable Test Result
+	*/
+	if((status = gvctGetCableDiag(dev,port, &cableStatus)) != GT_OK)
+	{
+		MSG_PRINT(("gvctGetCableDiag return Failed\n"));
+		return status;
+	}
+
+	MSG_PRINT(("Cable Test Result for Port %i\n",port));
+
+	if(cableStatus.phyType == PHY_100M)
+	{
+		MSG_PRINT(("RX PAIR :\n"));
+		displayVCTResult(&cableStatus.cableStatus[MDI_RX_PAIR],
+									&cableStatus.cableLen[MDI_RX_PAIR]);
+		MSG_PRINT(("TX PAIR :\n"));
+		displayVCTResult(&cableStatus.cableStatus[MDI_TX_PAIR],
+									&cableStatus.cableLen[MDI_TX_PAIR]);
+	}
+	else /* phyType must be PHY_1000M */
+	{
+		for(i=0; i<GT_MDI_PAIR_NUM; i++)
+		{
+			MSG_PRINT(("MDI PAIR %i:\n",i));
+			displayVCTResult(&cableStatus.cableStatus[i],
+									&cableStatus.cableLen[i]);
+		}
+	}
+
+	return GT_OK;
+}
+
+
+GT_STATUS getExtendedStatus(GT_QD_DEV *dev,GT_LPORT port)
+{
+	GT_STATUS status;
+	GT_1000BT_EXTENDED_STATUS extendedStatus;
+	int i;
+
+	if (dev == 0)
+	{
+		MSG_PRINT(("QD driver is not initialized\n"));
+		return GT_FAIL;
+#if 0
+		dev = &qdDev;
+		memset(dev, 0, sizeof(GT_QD_DEV));
+		dev->fgtReadMii = gtBspReadMii;
+		dev->fgtWriteMii = gtBspWriteMii;
+#endif
+	}
+
+	/*
+	 * 	Start getting Extended Information.
+	 */
+	if((status = gvctGet1000BTExtendedStatus(dev,port, &extendedStatus)) != GT_OK)
+	{
+		MSG_PRINT(("gvctGetCableDiag return Failed\n"));
+		return status;
+	}
+
+	if (!extendedStatus.isValid)
+	{
+		MSG_PRINT(("Not able to get Extended Status.\n"));
+		return status;
+
+	}
+
+	/* Pair Polarity */
+	MSG_PRINT(("Pair Polarity:\n"));
+	for(i=0; i<GT_MDI_PAIR_NUM; i++)
+	{
+		MSG_PRINT(("MDI PAIR %i: %s\n",i,
+				(extendedStatus.pairPolarity[i] == GT_POSITIVE)?"Positive":"Negative"));
+	}
+	
+	/* Pair Swap */
+	MSG_PRINT(("Pair Swap:\n"));
+	for(i=0; i<GT_CHANNEL_PAIR_NUM; i++)
+	{
+		MSG_PRINT(("CHANNEL PAIR %i: %s\n",i,
+				(extendedStatus.pairSwap[i] == GT_STRAIGHT_CABLE)?"Straight":"Crossover"));
+	}
+	
+	/* Pair Polarity */
+	MSG_PRINT(("Pair Skew:\n"));
+	for(i=0; i<GT_MDI_PAIR_NUM; i++)
+	{
+		MSG_PRINT(("MDI PAIR %i: %ins\n",i,extendedStatus.pairSkew[i]));
+	}
+	
+	return GT_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/Copyright.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/Copyright.h
new file mode 100755
index 0000000..4875a66
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/Copyright.h
@@ -0,0 +1,60 @@
+
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms. Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+********************************************************************************
+Marvell Commercial License Option
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED. The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+* Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+* Neither the name of Marvell nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef _msCopyright_h
+#define _msCopyright_h
+
+#define MSAPI_COPYRIGHT "Copyright 2000~2009, Marvell International Ltd."
+#define MSAPI_VERSION "2.8b"
+
+#endif /* _msCopyright_h */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvConfig.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvConfig.h
new file mode 100755
index 0000000..8b655ad
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvConfig.h
@@ -0,0 +1,249 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtDrvConfig.h
+*
+* DESCRIPTION:
+*       Includes driver level configuration and initialization function.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 4 $
+*
+*******************************************************************************/
+
+#ifndef __gtDrvConfigh
+#define __gtDrvConfigh
+
+#include <msApi.h>
+#include <gtVct.h>
+#include <gtDrvSwRegs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+* driverConfig
+*
+* DESCRIPTION:
+*       This function initializes the driver level of the quarterDeck software.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success, or
+*       GT_OUT_OF_CPU_MEM   - if failed to allocate CPU memory,
+*       GT_FAIL             - otherwise.
+*
+* COMMENTS:
+*       1.  This function should perform the following:
+*           -   Initialize the global switch configuration structure.
+*           -   Initialize Mii Interface
+*           -   Set the CPU port into trailer mode (Ingress and Egress).
+*
+*******************************************************************************/
+GT_STATUS driverConfig(IN GT_QD_DEV *dev);
+
+/*******************************************************************************
+* driverEnable
+*
+* DESCRIPTION:
+*       This function enables the switch for full operation, after the driver
+*       Config function was called.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverEnable(IN GT_QD_DEV *dev);
+
+/*******************************************************************************
+* driverIsPhyAttached
+*
+* DESCRIPTION:
+*       This function reads and returns Phy ID (register 3) of Marvell Phy.
+*
+* INPUTS:
+*       hwPort	- port number where the Phy is connected
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       phyId - if Marvell Phy exists
+*		0	  - otherwise
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U32 driverIsPhyAttached
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort
+);
+
+/*******************************************************************************
+* driverGetPhyID
+*
+* DESCRIPTION:
+*       This function reads and returns Phy ID (register 3) of Marvell Phy.
+*
+* INPUTS:
+*       hwPort	- port number where the Phy is connected
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       phyId - if Marvell Phy exists
+*		GT_INVALID_PORT	  - otherwise
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U32 driverGetPhyID
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort
+);
+
+/*******************************************************************************
+* driverGetSerdesPort
+*
+* DESCRIPTION:
+*       This function converts port to Serdes port
+*
+* INPUTS:
+*       hwPort	 - port number where the Phy is connected
+*
+* OUTPUTS:
+*       hwPort	 - port number where the Phy is connected
+*
+* RETURNS:
+*       GT_OK 	- if success
+*       GT_FAIL - othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverGetSerdesPort(GT_QD_DEV *dev, GT_U8* hwPort);
+
+
+/*******************************************************************************
+* driverPagedAccessStart
+*
+* DESCRIPTION:
+*       This function stores page register and Auto Reg Selection mode if needed.
+*
+* INPUTS:
+*       hwPort	 - port number where the Phy is connected
+*		pageType - type of the page registers
+*
+* OUTPUTS:
+*       autoOn	- GT_TRUE if Auto Reg Selection enabled, GT_FALSE otherwise.
+*		pageReg - Page Register Data
+*
+* RETURNS:
+*       GT_OK 	- if success
+*       GT_FAIL - othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverPagedAccessStart
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort,
+	IN	GT_U8		 pageType,
+	OUT	GT_BOOL		 *autoOn,
+	OUT	GT_U16		 *pageReg
+);
+
+
+/*******************************************************************************
+* driverPagedAccessStop
+*
+* DESCRIPTION:
+*       This function restores page register and Auto Reg Selection mode if needed.
+*
+* INPUTS:
+*       hwPort	 - port number where the Phy is connected
+*		pageType - type of the page registers
+*       autoOn	 - GT_TRUE if Auto Reg Selection enabled, GT_FALSE otherwise.
+*		pageReg  - Page Register Data
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK 	- if success
+*       GT_FAIL - othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverPagedAccessStop
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort,
+	IN	GT_U8		 pageType,
+	IN	GT_BOOL		 autoOn,
+	IN	GT_U16		 pageReg
+);
+
+
+/*******************************************************************************
+* driverFindPhyInformation
+*
+* DESCRIPTION:
+*       This function gets information of Phy connected to the given port.
+*
+* INPUTS:
+*       hwPort	- port number where the Phy is connected
+*
+* OUTPUTS:
+*       phyId	- Phy ID
+*
+* RETURNS:
+*       GT_OK 	- if found Marvell Phy,
+*       GT_FAIL - othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverFindPhyInformation
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort,
+	OUT	GT_PHY_INFO	 *phyInfo
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gtDrvConfigh */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvEvents.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvEvents.h
new file mode 100755
index 0000000..cfb4723
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvEvents.h
@@ -0,0 +1,87 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtDrvEvents.h
+*
+* DESCRIPTION:
+*       This file includes function declarations for QuarterDeck interrupts
+*       configuration and handling.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1 $
+*
+*******************************************************************************/
+
+#ifndef __gtDrvEventsh
+#define __gtDrvEventsh
+
+#include <msApi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+* drvEventInit
+*
+* DESCRIPTION:
+*       This function initializes the driver's interrupt handling mechanism.
+*
+* INPUTS:
+*       intVecNum   - The interrupt vector the switch is connected to.
+*       isrFunc     - A pointer to the Interrupt Service Routine to be
+*                     connected to the given interrupt vector.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success,
+*       GT_FAIL - otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS drvEventsInit
+(
+    IN  GT_QD_DEV     *dev,
+    IN GT_U32         intVecNum,
+    IN GT_VOIDFUNCPTR isrFunc
+);
+
+
+
+/*******************************************************************************
+* eventQdSr
+*
+* DESCRIPTION:
+*       QuarterDeck interrupt service routine.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_BOOL eventQdSr
+(
+	IN  GT_QD_DEV  *dev,
+	OUT GT_U16*    intCause
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gtDrvEventsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvSwRegs.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvSwRegs.h
new file mode 100755
index 0000000..0bdc5e9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtDrvSwRegs.h
@@ -0,0 +1,238 @@
+#include <Copyright.h>
+
+/********************************************************************************
+ * * gtDrvSwRegs.h
+ * *
+ * * DESCRIPTION:
+ * *       definitions of the register map of QuarterDeck Device
+ * *
+ * * DEPENDENCIES:
+ * *
+ * * FILE REVISION NUMBER:
+ * *
+ * *******************************************************************************/
+#ifndef __gtDrvSwRegsh
+#define __gtDrvSwRegsh
+
+/* QuarterDeck Per Port Registers */
+#define QD_REG_PORT_STATUS		0x0
+#define QD_REG_PCS_CONTROL		0x1		/* for Sapphire family */
+#define QD_REG_LIMIT_PAUSE_CONTROL		0x2		/* Jamming control register */
+#define QD_REG_SWITCH_ID		0x3
+#define QD_REG_PORT_CONTROL		0x4
+#define QD_REG_PORT_CONTROL1		0x5
+#define QD_REG_PORT_VLAN_MAP		0x6
+#define QD_REG_PVID			0x7
+#define QD_REG_PORT_CONTROL2		0x8	/* for Sapphire family */
+#define QD_REG_INGRESS_RATE_CTRL	0x9	/* for Sapphire family */
+#define QD_REG_EGRESS_RATE_CTRL		0xA	/* for Sapphire family */
+#define QD_REG_RATE_CTRL0		0x9
+#define QD_REG_RATE_CTRL		0xA
+#define QD_REG_PAV			0xB
+#define QD_REG_PORT_ATU_CONTROL		0xC
+#define QD_REG_PRI_OVERRIDE		0xD
+#define QD_REG_POLICY_CONTROL	0xE
+#define QD_REG_PORT_ETH_TYPE	0xF
+#define QD_REG_RX_COUNTER		0x10
+#define QD_REG_TX_COUNTER		0x11
+#define QD_REG_DROPPED_COUNTER	0x12
+
+#define QD_REG_INDISCARD_LO_COUNTER		0x10
+#define QD_REG_INDISCARD_HI_COUNTER		0x11
+#define QD_REG_INFILTERED_COUNTER		0x12
+#define QD_REG_OUTFILTERED_COUNTER		0x13
+
+#define QD_REG_LED_CONTROL		0x16
+
+#define QD_REG_Q_COUNTER		0x1B
+#define QD_REG_RATE_CONTROL		0x0A
+#define QD_REG_PORT_ASSOCIATION		0x0B
+#define QD_REG_IEEE_PRI_REMAP_3_0	0x18	/* for Sapphire family */
+#define QD_REG_IEEE_PRI_REMAP_7_4	0x19	/* for Sapphire family */
+
+#define QD_REG_PROVIDER_TAG		0x1A		/* for Schooner family */
+
+/* QuarterDeck Global Registers */
+#define QD_REG_GLOBAL_STATUS		0x0
+#define QD_REG_MACADDR_01		0x1
+#define QD_REG_MACADDR_23		0x2
+#define QD_REG_MACADDR_45		0x3
+#define QD_REG_GLOBAL_CONTROL		0x4
+#define QD_REG_GLOBAL_CONTROL2		0x1C	/* for Sapphire, Schooner family */
+#define QD_REG_CORETAG_TYPE		0x19		/* for Ruby family */
+#define QD_REG_IP_MAPPING_TABLE	0x19		/* for Amber family */
+#define QD_REG_MONITOR_CONTROL	0x1A		/* for Ruby family */
+#define QD_REG_MANGEMENT_CONTROL	0x1A	/* for Schooner family */
+#define QD_REG_TOTAL_FREE_COUNTER	0x1B	/* for Schooner family */
+
+/* QuarterDeck Global 2 Registers */
+#define QD_REG_PHYINT_SOURCE	0x0
+#define QD_REG_DEVINT_SOURCE	0x0
+#define QD_REG_DEVINT_MASK		0x1
+#define QD_REG_MGMT_ENABLE_2X	0x2
+#define QD_REG_MGMT_ENABLE		0x3
+#define QD_REG_FLOWCTRL_DELAY	0x4
+#define QD_REG_MANAGEMENT		0x5
+#define QD_REG_ROUTING_TBL		0x6
+#define QD_REG_TRUNK_MASK_TBL	0x7
+#define QD_REG_TRUNK_ROUTING	0x8
+#define QD_REG_INGRESS_RATE_COMMAND	0x9
+#define QD_REG_INGRESS_RATE_DATA	0xA
+#define QD_REG_PVT_ADDR			0xB
+#define QD_REG_PVT_DATA			0xC
+#define QD_REG_SWITCH_MAC		0xD
+#define QD_REG_ATU_STATS		0xE
+#define QD_REG_PRIORITY_OVERRIDE	0xF
+#define QD_REG_EEPROM_COMMAND	0x14
+#define QD_REG_EEPROM_DATA		0x15
+#define QD_REG_PTP_COMMAND		0x16
+#define QD_REG_PTP_DATA			0x17
+#define QD_REG_SMI_PHY_CMD		0x18
+#define QD_REG_SMI_PHY_DATA		0x19
+#define QD_REG_SCRATCH_MISC		0x1A
+#define QD_REG_WD_CONTROL		0x1B
+#define QD_REG_QOS_WEIGHT		0x1C
+#define QD_REG_SDET_POLARITY	0x1D
+
+
+/* Definition for STU,VTU,RMON,and ATU Registers */
+#define QD_REG_ATU_FID_REG		0x1
+#define QD_REG_VTU_FID_REG		0x2
+#define QD_REG_STU_SID_REG		0x3
+#define QD_REG_VTU_OPERATION		0x5
+#define QD_REG_VTU_VID_REG		0x6
+#define QD_REG_VTU_DATA1_REG		0x7
+#define QD_REG_VTU_DATA2_REG		0x8
+#define QD_REG_VTU_DATA3_REG		0x9
+#define QD_REG_STATS_OPERATION		0x1D
+#define QD_REG_STATS_COUNTER3_2		0x1E
+#define QD_REG_STATS_COUNTER1_0		0x1F
+ 
+#define QD_REG_ATU_CONTROL		0xA
+#define QD_REG_ATU_OPERATION		0xB
+#define QD_REG_ATU_DATA_REG		0xC
+#define QD_REG_ATU_MAC_BASE		0xD
+#define QD_REG_IP_PRI_BASE		0x10
+#define QD_REG_IEEE_PRI			0x18
+
+
+/* Definitions for MIB Counter */
+#define GT_STATS_NO_OP			0x0
+#define GT_STATS_FLUSH_ALL		0x1
+#define GT_STATS_FLUSH_PORT		0x2
+#define GT_STATS_READ_COUNTER		0x4
+#define GT_STATS_CAPTURE_PORT		0x5
+
+#define QD_PHY_CONTROL_REG			0
+#define QD_PHY_AUTONEGO_AD_REG			4
+#define QD_PHY_NEXTPAGE_TX_REG			7
+#define QD_PHY_AUTONEGO_1000AD_REG		9
+#define QD_PHY_SPEC_CONTROL_REG			16
+#define QD_PHY_INT_ENABLE_REG			18
+#define QD_PHY_INT_STATUS_REG			19
+#define QD_PHY_INT_PORT_SUMMARY_REG		20
+
+/* Definitions for VCT registers */
+#define QD_REG_MDI0_VCT_STATUS     16
+#define QD_REG_MDI1_VCT_STATUS     17
+#define QD_REG_MDI2_VCT_STATUS     18
+#define QD_REG_MDI3_VCT_STATUS     19
+#define QD_REG_ADV_VCT_CONTROL_5	23
+#define QD_REG_ADV_VCT_CONTROL_8	20
+#define QD_REG_PAIR_SKEW_STATUS    20
+#define QD_REG_PAIR_SWAP_STATUS    21
+
+
+/* Bit Definition for QD_PHY_CONTROL_REG */
+#define QD_PHY_RESET			0x8000
+#define QD_PHY_LOOPBACK			0x4000
+#define QD_PHY_SPEED			0x2000
+#define QD_PHY_AUTONEGO			0x1000
+#define QD_PHY_POWER			0x800
+#define QD_PHY_ISOLATE			0x400
+#define QD_PHY_RESTART_AUTONEGO		0x200
+#define QD_PHY_DUPLEX			0x100
+#define QD_PHY_SPEED_MSB		0x40
+
+#define QD_PHY_POWER_BIT			11
+#define QD_PHY_RESTART_AUTONEGO_BIT		9
+
+/* Bit Definition for QD_PHY_AUTONEGO_AD_REG */
+#define QD_PHY_NEXTPAGE			0x8000
+#define QD_PHY_REMOTEFAULT		0x4000
+#define QD_PHY_PAUSE			0x400
+#define QD_PHY_100_FULL			0x100
+#define QD_PHY_100_HALF			0x80
+#define QD_PHY_10_FULL			0x40
+#define QD_PHY_10_HALF			0x20
+
+#define QD_PHY_MODE_AUTO_AUTO	(QD_PHY_100_FULL | QD_PHY_100_HALF | QD_PHY_10_FULL | QD_PHY_10_HALF)
+#define QD_PHY_MODE_100_AUTO	(QD_PHY_100_FULL | QD_PHY_100_HALF)
+#define QD_PHY_MODE_10_AUTO		(QD_PHY_10_FULL | QD_PHY_10_HALF)
+#define QD_PHY_MODE_AUTO_FULL	(QD_PHY_100_FULL | QD_PHY_10_FULL)
+#define QD_PHY_MODE_AUTO_HALF	(QD_PHY_100_HALF | QD_PHY_10_HALF)
+
+#define QD_PHY_MODE_100_FULL	QD_PHY_100_FULL
+#define QD_PHY_MODE_100_HALF	QD_PHY_100_HALF
+#define QD_PHY_MODE_10_FULL		QD_PHY_10_FULL	
+#define QD_PHY_MODE_10_HALF		QD_PHY_10_HALF	
+
+/* Gigabit Phy related definition */
+#define QD_GIGPHY_1000X_FULL_CAP	0x8
+#define QD_GIGPHY_1000X_HALF_CAP	0x4
+#define QD_GIGPHY_1000T_FULL_CAP	0x2
+#define QD_GIGPHY_1000T_HALF_CAP	0x1
+
+#define QD_GIGPHY_1000X_CAP		(QD_GIGPHY_1000X_FULL_CAP|QD_GIGPHY_1000X_HALF_CAP)
+#define QD_GIGPHY_1000T_CAP		(QD_GIGPHY_1000T_FULL_CAP|QD_GIGPHY_1000T_HALF_CAP)
+
+#define QD_GIGPHY_1000X_FULL		0x20
+#define QD_GIGPHY_1000X_HALF		0x40
+
+#define QD_GIGPHY_1000T_FULL		0x200
+#define QD_GIGPHY_1000T_HALF		0x100
+
+/* Bit definition for QD_PHY_INT_ENABLE_REG */
+#define QD_PHY_INT_SPEED_CHANGED		0x4000
+#define QD_PHY_INT_DUPLEX_CHANGED		0x2000
+#define QD_PHY_INT_PAGE_RECEIVED		0x1000
+#define QD_PHY_INT_AUTO_NEG_COMPLETED		0x800
+#define QD_PHY_INT_LINK_STATUS_CHANGED		0x400
+#define QD_PHY_INT_SYMBOL_ERROR			0x200
+#define QD_PHY_INT_FALSE_CARRIER		0x100
+#define QD_PHY_INT_FIFO_FLOW			0x80
+#define QD_PHY_INT_CROSSOVER_CHANGED		0x40
+#define QD_PHY_INT_POLARITY_CHANGED		0x2
+#define QD_PHY_INT_JABBER			0x1
+
+/*Line loopback register related definition*/
+#define QD_PHY_FE_LINE_LOOPBACK_REG			0x1c
+#define QD_PHY_GE_LINE_LOOPBACK_REG			0x15
+
+/* Bit definition for DEVICE Interrupt */
+#define QD_DEV_INT_WATCHDOG			0x8000
+#define QD_DEV_INT_JAMLIMIT			0x4000
+#define QD_DEV_INT_DUPLEX_MISMATCH	0x2000
+
+/* Definition for Multi Address Mode */
+#define QD_REG_SMI_COMMAND		0x0
+#define QD_REG_SMI_DATA			0x1
+
+/* Bit definition for QD_REG_SMI_COMMAND */
+#define QD_SMI_BUSY				0x8000
+#define QD_SMI_MODE				0x1000
+#define QD_SMI_MODE_BIT			12
+#define QD_SMI_OP_BIT			10
+#define QD_SMI_OP_SIZE			2
+#define QD_SMI_DEV_ADDR_BIT		5
+#define QD_SMI_DEV_ADDR_SIZE	5
+#define QD_SMI_REG_ADDR_BIT		0
+#define QD_SMI_REG_ADDR_SIZE	5
+
+#define QD_SMI_CLAUSE45			0
+#define QD_SMI_CLAUSE22			1
+
+#define QD_SMI_WRITE			0x01
+#define QD_SMI_READ				0x02
+
+#endif /* __gtDrvSwRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtHwCntl.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtHwCntl.h
new file mode 100755
index 0000000..5d459df
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/driver/gtHwCntl.h
@@ -0,0 +1,891 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtHwCntl.h
+*
+* DESCRIPTION:
+*       Functions declarations for Hw accessing quarterDeck phy, internal and
+*       global registers.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*
+*******************************************************************************/
+
+#ifndef __gtHwCntlh
+#define __gtHwCntlh
+
+#include <msApi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This macro is used to calculate the register's SMI   */
+/* device address, according to the baseAddr            */
+/* field in the Switch configuration struct.            */
+#define CALC_SMI_DEV_ADDR(_dev, _portNum, _accessType)        \
+            portToSmiMapping(_dev, _portNum, _accessType)
+
+/* This macro calculates the mask for partial read /    */
+/* write of register's data.                            */
+#define CALC_MASK(fieldOffset,fieldLen,mask)        \
+            if((fieldLen + fieldOffset) >= 16)      \
+                mask = (0 - (1 << fieldOffset));    \
+            else                                    \
+                mask = (((1 << (fieldLen + fieldOffset))) - (1 << fieldOffset))
+
+#define GT_GET_PAGE_ADDR(_regAddr) ((_regAddr<29)?22:29)
+
+/* Start address of phy related register.               */
+#define PHY_REGS_START_ADDR     0x0
+#define PHY_REGS_START_ADDR_8PORT	0x0
+
+/* Start address of ports related register.             */
+#define PORT_REGS_START_ADDR    	0x8
+#define PORT_REGS_START_ADDR_8PORT	0x10
+
+/* Start address of global register.                    */
+#define GLOBAL_REGS_START_ADDR  0xF
+#define GLOBAL_REGS_START_ADDR_8PORT  0x1B
+
+#define PHY_ACCESS			1
+#define PORT_ACCESS			2
+#define GLOBAL_REG_ACCESS	3
+#define GLOBAL2_REG_ACCESS	4
+
+#define QD_SMI_ACCESS_LOOP		1000
+#define QD_SMI_TIMEOUT			2
+
+
+/****************************************************************************/
+/* Phy registers related functions.                                         */
+/****************************************************************************/
+
+/*******************************************************************************
+* hwReadPhyReg
+*
+* DESCRIPTION:
+*       This function reads a switch's port phy register.
+*
+* INPUTS:
+*       portNum - Port number to read the register for.
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadPhyReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     portNum,
+    IN  GT_U8     regAddr,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwWritePhyReg
+*
+* DESCRIPTION:
+*       This function writes to a switch's port phy register.
+*
+* INPUTS:
+*       portNum - Port number to write the register for.
+*       regAddr - The register's address.
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWritePhyReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     portNum,
+    IN  GT_U8     regAddr,
+    IN  GT_U16    data
+);
+
+
+/*******************************************************************************
+* hwGetPhyRegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's port phy register.
+*
+* INPUTS:
+*       portNum     - Port number to read the register for.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetPhyRegField
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     portNum,
+    IN  GT_U8     regAddr,
+    IN  GT_U8     fieldOffset,
+    IN  GT_U8     fieldLength,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwSetPhyRegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's port phy register.
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetPhyRegField
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     portNum,
+    IN  GT_U8     regAddr,
+    IN  GT_U8     fieldOffset,
+    IN  GT_U8     fieldLength,
+    IN  GT_U16    data
+);
+
+/*******************************************************************************
+* hwPhyReset
+*
+* DESCRIPTION:
+*       This function performs softreset and waits until reset completion.
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       u16Data     - data should be written into Phy control register.
+*					  if this value is 0xFF, normal operation occcurs (read, 
+*					  update, and write back.)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS hwPhyReset
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U8     portNum,
+	IN	GT_U16		u16Data
+);
+
+
+/*******************************************************************************
+* hwReadPagedPhyReg
+*
+* DESCRIPTION:
+*       This function reads a switch's port phy register in page mode.
+*
+* INPUTS:
+*       portNum - Port number to read the register for.
+*       pageNum - Page number of the register to be read.
+*       regAddr - The register's address.
+*		anyPage - register list(vector) that are common to all pages
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadPagedPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    pageNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U32	 anyPage,
+	OUT GT_U16   *data
+);
+
+
+/*******************************************************************************
+* hwWritePagedPhyReg
+*
+* DESCRIPTION:
+*       This function writes to a switch's port phy register in page mode.
+*
+* INPUTS:
+*       portNum - Port number to write the register for.
+*       pageNum - Page number of the register to be written.
+*       regAddr - The register's address.
+*		anyPage - Register list(vector) that are common to all pages
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWritePagedPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    pageNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U32	 anyPage,
+	IN  GT_U16   data
+);
+
+/*******************************************************************************
+* hwGetPagedPhyRegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's port phy register
+*		in page mode.
+*
+* INPUTS:
+*       portNum     - Port number to read the register for.
+*       pageNum 	- Page number of the register to be read.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*		anyPage - Register list(vector) that are common to all pages
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetPagedPhyRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    pageNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+	IN  GT_U32	 anyPage,
+    OUT GT_U16   *data
+);
+
+/*******************************************************************************
+* hwSetPagedPhyRegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's port phy register
+*		in page mode
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       pageNum 	- Page number of the register to be read.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*		anyPage 	- Register list(vector) that are common to all pages
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetPagedPhyRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    pageNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+	IN  GT_U32	 anyPage,
+    IN  GT_U16   data
+);
+
+
+/****************************************************************************/
+/* Per port registers related functions.                                    */
+/****************************************************************************/
+
+/*******************************************************************************
+* hwReadPortReg
+*
+* DESCRIPTION:
+*       This function reads a switch's port register.
+*
+* INPUTS:
+*       portNum - Port number to read the register for.
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadPortReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     portNum,
+    IN  GT_U8     regAddr,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwWritePortReg
+*
+* DESCRIPTION:
+*       This function writes to a switch's port register.
+*
+* INPUTS:
+*       portNum - Port number to write the register for.
+*       regAddr - The register's address.
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWritePortReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     portNum,
+    IN  GT_U8     regAddr,
+    IN  GT_U16    data
+);
+
+
+/*******************************************************************************
+* hwGetPortRegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's port register.
+*
+* INPUTS:
+*       portNum     - Port number to read the register for.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetPortRegField
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     portNum,
+    IN  GT_U8     regAddr,
+    IN  GT_U8     fieldOffset,
+    IN  GT_U8     fieldLength,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwSetPortRegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's port register.
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetPortRegField
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     portNum,
+    IN  GT_U8     regAddr,
+    IN  GT_U8     fieldOffset,
+    IN  GT_U8     fieldLength,
+    IN  GT_U16    data
+);
+
+/*******************************************************************************
+* hwSetPortRegBits
+*
+* DESCRIPTION:
+*       This function writes to specified bits in a switch's port register.
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       regAddr     - The register's address.
+*       mask 		- The bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  When Data is 0x1002 and mask is 0xF00F, 0001b is written to bit[31:24]
+*			and 0010b is written to bit[3:0]
+*
+*******************************************************************************/
+GT_STATUS hwSetPortRegBits
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   mask,
+    IN  GT_U16   data
+);
+
+/****************************************************************************/
+/* Global registers related functions.                                      */
+/****************************************************************************/
+
+/*******************************************************************************
+* hwReadGlobalReg
+*
+* DESCRIPTION:
+*       This function reads a switch's global register.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadGlobalReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     regAddr,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwWriteGlobalReg
+*
+* DESCRIPTION:
+*       This function writes to a switch's global register.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWriteGlobalReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     regAddr,
+    IN  GT_U16    data
+);
+
+
+/*******************************************************************************
+* hwGetGlobalRegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's global register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetGlobalRegField
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     regAddr,
+    IN  GT_U8     fieldOffset,
+    IN  GT_U8     fieldLength,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwSetGlobalRegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's global register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetGlobalRegField
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     regAddr,
+    IN  GT_U8     fieldOffset,
+    IN  GT_U8     fieldLength,
+    IN  GT_U16    data
+);
+
+
+/****************************************************************************/
+/* Global 2 registers related functions.                                      */
+/****************************************************************************/
+
+/*******************************************************************************
+* hwReadGlobal2Reg
+*
+* DESCRIPTION:
+*       This function reads a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadGlobal2Reg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     regAddr,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwWriteGlobal2Reg
+*
+* DESCRIPTION:
+*       This function writes to a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWriteGlobal2Reg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     regAddr,
+    IN  GT_U16    data
+);
+
+
+/*******************************************************************************
+* hwGetGlobal2RegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetGlobal2RegField
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     regAddr,
+    IN  GT_U8     fieldOffset,
+    IN  GT_U8     fieldLength,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwSetGlobal2RegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS hwSetGlobal2RegField
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     regAddr,
+    IN  GT_U8     fieldOffset,
+    IN  GT_U8     fieldLength,
+    IN  GT_U16    data
+);
+
+/*******************************************************************************
+* hwSetGlobal2RegBits
+*
+* DESCRIPTION:
+*       This function writes to specified bits in a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       mask 		- The bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  When Data is 0x1002 and mask is 0xF00F, 0001b is written to bit[31:24]
+*			and 0010b is written to bit[3:0]
+*
+*******************************************************************************/
+GT_STATUS hwSetGlobal2RegBits
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   mask,
+    IN  GT_U16   data
+);
+
+/*******************************************************************************
+* hwReadMiiReg
+*
+* DESCRIPTION:
+*       This function reads a switch register.
+*
+* INPUTS:
+*       phyAddr - Phy Address to read the register for.( 0 ~ 0x1F )
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadMiiReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     phyAddr,
+    IN  GT_U8     regAddr,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* hwWriteMiiReg
+*
+* DESCRIPTION:
+*       This function writes a switch register.
+*
+* INPUTS:
+*       phyAddr - Phy Address to read the register for.( 0 ~ 0x1F )
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWriteMiiReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     phyAddr,
+    IN  GT_U8     regAddr,
+    IN  GT_U16    data
+);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __gtHwCntlh */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/gtVct.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/gtVct.h
new file mode 100755
index 0000000..70626bc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/gtVct.h
@@ -0,0 +1,184 @@
+/*******************************************************************************
+*              Copyright 2002, GALILEO TECHNOLOGY, LTD.
+*
+* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL. NO RIGHTS ARE GRANTED
+* HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT OF MARVELL OR ANY THIRD
+* PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE DISCRETION TO REQUEST THAT THIS
+* CODE BE IMMEDIATELY RETURNED TO MARVELL. THIS CODE IS PROVIDED "AS IS".
+* MARVELL MAKES NO WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS
+* ACCURACY, COMPLETENESS OR PERFORMANCE. MARVELL COMPRISES MARVELL TECHNOLOGY
+* GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, MARVELL INTERNATIONAL LTD. (MIL),
+* MARVELL TECHNOLOGY, INC. (MTI), MARVELL SEMICONDUCTOR, INC. (MSI), MARVELL
+* ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K. (MJKK), GALILEO TECHNOLOGY LTD. (GTL)
+* AND GALILEO TECHNOLOGY, INC. (GTI).
+********************************************************************************
+* gtPhy.h
+*
+* DESCRIPTION:
+*       API definitions for Marvell Phy functionality.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1 $
+*******************************************************************************/
+
+#ifndef __gtPhyh
+#define __gtPhyh
+
+#include "msApi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MARVELL_OUI_MSb		0x0141
+#define MARVELL_OUI_LSb		0x0C00
+#define OUI_LSb_MASK		0xFC00
+#define PHY_MODEL_MASK		0x03F0
+#define PHY_REV_MASK		0x000F
+
+#define DEV_E3082		0x8 << 4
+#define DEV_E104X		0x2 << 4
+#define DEV_E1111		0xC << 4
+#define DEV_E1112		0x9 << 4
+#define DEV_E114X		0xD << 4
+#define DEV_E1149		0xA << 4
+#define DEV_E1181		0xE << 4
+#define DEV_EC010		0x3 << 4
+#define DEV_G15LV		0xB << 4	/* 88E6165 internal copper phy, 88E1240 */
+#define DEV_S15LV		0x0 << 4	/* 88E6165 internal SERDES */
+#define DEV_G65G		0x27 << 4	/* 88E6375 internal copper phy, 88E1340 */
+#define DEV_G65FE		0x26 << 4	/* FE phy intergrated in 88E6500*/
+#define DEV_G65GE		0x2B << 4	/* GE phy intergrated in 88E6500*/
+#define DEV_QUAD3		0x1F << 4	/* YuvalC 1545 quad_phy - phy connected to amber_switch_3 */
+
+typedef struct _GT_PHY_INFO
+{
+	GT_U32	phyId;		/* Marvell PHY ID (register 3) */
+	GT_U32	anyPage;	/* each bit represents if the corresponding register is any page */
+	GT_U32	flag;		/* see below for definition */
+	GT_U8	vctType;	/* VCT Register Type */
+	GT_U8	exStatusType;	/* EX Status Register Type */
+	GT_U8	dteType;	/* DTE Register Type */
+	GT_U8	pktGenType;	/* Pkt Generator Reg. Type */
+	GT_U8	macIfLoopType;		/* MAC IF Loopback Reg. Type */
+	GT_U8	lineLoopType;		/* Line Loopback Reg. Type */
+	GT_U8	exLoopType;		/* External Loopback Reg. Type */
+	GT_U8	pageType;		/* Page Restriction Type */
+} GT_PHY_INFO;
+
+/* GT_PHY_INFO flag definition */
+#define GT_PHY_VCT_CAPABLE		0x0001
+#define GT_PHY_DTE_CAPABLE		0x0002
+#define GT_PHY_EX_CABLE_STATUS	0x0004
+#define GT_PHY_ADV_VCT_CAPABLE	0x0008
+#define GT_PHY_PKT_GENERATOR	0x0010
+#define GT_PHY_MAC_IF_LOOP		0x0100
+#define GT_PHY_LINE_LOOP		0x0200
+#define GT_PHY_EXTERNAL_LOOP	0x0400
+#define GT_PHY_RESTRICTED_PAGE	0x0800
+#define GT_PHY_GIGABIT			0x8000
+#define GT_PHY_COPPER			0x4000
+#define GT_PHY_FIBER			0x2000
+#define GT_PHY_SERDES_CORE		0x1000
+
+/* VCT Register Type */
+#define GT_PHY_VCT_TYPE1	1	/* 10/100 Fast Ethernet */
+#define GT_PHY_VCT_TYPE2	2	/* 1000M without page support */
+#define GT_PHY_VCT_TYPE3	3	/* 1000M without page but with work around */
+#define GT_PHY_VCT_TYPE4	4	/* 1000M with page support */
+
+/* ADV VCT Register Type */
+#define GT_PHY_ADV_VCT_TYPE1	5	/* 88E1181 type device, not supported */
+#define GT_PHY_ADV_VCT_TYPE2	6	/* 88E6165 family devies */
+
+/* Extended Status Type */
+#define GT_PHY_EX_STATUS_TYPE1	1	/* 88E1111, 88E1141, 88E1145 */
+#define GT_PHY_EX_STATUS_TYPE2	2	/* 88E1112 */
+#define GT_PHY_EX_STATUS_TYPE3	3	/* 88E1149 */
+#define GT_PHY_EX_STATUS_TYPE4	4	/* 88E1181 */
+#define GT_PHY_EX_STATUS_TYPE5	5	/* 88E1116 */
+#define GT_PHY_EX_STATUS_TYPE6	6	/* 88E6165 family devices */
+
+/* DTE Register Type */
+#define GT_PHY_DTE_TYPE1	1	/* 10/100 Fast Ethernet with workaround */
+#define GT_PHY_DTE_TYPE2	2	/* 1000M without page support */
+#define GT_PHY_DTE_TYPE3	3	/* 1000M without page but with work around */
+#define GT_PHY_DTE_TYPE4	4	/* 1000M with page support */
+#define GT_PHY_DTE_TYPE5	5	/* 10/100 Fast Ethernet */
+
+/* Pkt Generator Register Type */
+#define GT_PHY_PKTGEN_TYPE1	1	/* Uses Register 30 */
+#define GT_PHY_PKTGEN_TYPE2	2	/* Uses Register 16 */
+#define GT_PHY_PKTGEN_TYPE3	3	/* Uses Register 25 */
+
+/* MAC Interface Loopback Register Type */
+#define GT_PHY_LOOPBACK_TYPE0	0	/* Don't do anything */
+#define GT_PHY_LOOPBACK_TYPE1	1	/* 0.14 only */
+#define GT_PHY_LOOPBACK_TYPE2	2	/* For DEV_G15LV like device */
+#define GT_PHY_LOOPBACK_TYPE3	3	/* For DEV_S15LV like device */
+#define GT_PHY_LOOPBACK_TYPE4	4	/* For DEV_E1111 like device */
+
+/* Line Loopback Register Type */
+#define GT_PHY_LINE_LB_TYPE1	1	/* 0_2.14 */
+#define GT_PHY_LINE_LB_TYPE2	2	/* 21_2.14 */
+#define GT_PHY_LINE_LB_TYPE3	3	/* 20.14 */
+#define GT_PHY_LINE_LB_TYPE4	4	/* 16.12 */
+
+/* External Loopback Register Type */
+#define GT_PHY_EX_LB_TYPE0	0	/* Don't do anything */
+#define GT_PHY_EX_LB_TYPE1	1	/* For DEV_E1111 like dev */
+#define GT_PHY_EX_LB_TYPE2	2	/* For DEV_E1149 like dev */
+
+/* Restricted Page Access Type */
+#define GT_PHY_PAGE_WRITE_BACK	0	/* For every device */
+#define GT_PHY_PAGE_DIS_AUTO1	1	/* For 88E1111 type */
+#define GT_PHY_PAGE_DIS_AUTO2	2	/* For 88E1121 type */
+#define GT_PHY_NO_PAGE			3	/* No Pages */
+
+
+/* definition for formula to calculate actual distance */
+#ifdef FP_SUPPORT
+#define FORMULA_PHY100M(_data)	((_data)*0.7861 - 18.862)
+#define FORMULA_PHY1000M(_data)	((_data)*0.8018 - 28.751)
+#else
+#define FORMULA_PHY100M(_data)	(((long)(_data)*7861 - 188620)/10000 + (((((long)(_data)*7861 - 188620)%10000) >= 5000)?1:0))
+#define FORMULA_PHY1000M(_data)	(((long)(_data)*8018 - 287510)/10000 + (((((long)(_data)*8018 - 287510)%10000) >= 5000)?1:0))
+#endif
+
+#define GT_ADV_VCT_CALC(_data)	    \
+        (((long)(_data)*8333 - 191667)/10000 + (((((long)(_data)*8333 - 191667)%10000) >= 5000)?1:0))
+
+#define GT_ADV_VCT_CALC_SHORT(_data)	    \
+        (((long)(_data)*7143 - 71429)/10000 + (((((long)(_data)*7143 - 71429)%10000) >= 5000)?1:0)) 
+
+/* macro to check VCT Failure */
+#define IS_VCT_FAILED(_reg)		\
+		(((_reg) & 0xFF) == 0xFF)
+
+/* macro to find out if Amplitude is zero */
+#define IS_ZERO_AMPLITUDE(_reg)	\
+		(((_reg) & 0x7F00) == 0)
+
+/* macro to retrieve Amplitude */
+#define GET_AMPLITUDE(_reg)	\
+		(((_reg) & 0x7F00) >> 8)
+		
+/* macro to find out if Amplitude is positive */
+#define IS_POSITIVE_AMPLITUDE(_reg)	\
+		(((_reg) & 0x8000) == 0x8000)
+
+typedef struct _VCT_REGISTER
+{
+	GT_U8	page;
+	GT_U8	regOffset;
+} VCT_REGISTER;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gtPhyh */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/msApiInternal.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/msApiInternal.h
new file mode 100755
index 0000000..c5c0f4b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/msApi/msApiInternal.h
@@ -0,0 +1,1431 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* msApiPrototype.h
+*
+* DESCRIPTION:
+*       API Prototypes for QuarterDeck Device
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __msApiInternal_h
+#define __msApiInternal_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef GT_USE_SIMPLE_PORT_MAPPING
+#define GT_LPORT_2_PORT(_lport)      (GT_U8)((_lport) & 0xff)
+#define GT_PORT_2_LPORT(_port)       (GT_LPORT)((_port) & 0xff)
+#define GT_LPORTVEC_2_PORTVEC(_lvec)      (GT_U32)((_lvec) & 0xffff)
+#define GT_PORTVEC_2_LPORTVEC(_pvec)       (GT_U32)((_pvec) & 0xffff)
+#define GT_LPORT_2_PHY(_lport)      (GT_U8)((_lport) & 0xff)
+#else
+#define GT_LPORT_2_PORT(_lport)      lport2port(dev->validPortVec, _lport)
+#define GT_PORT_2_LPORT(_port)       port2lport(dev->validPortVec, _port)
+#define GT_LPORTVEC_2_PORTVEC(_lvec)	lportvec2portvec(dev->validPortVec, _lvec)
+#define GT_PORTVEC_2_LPORTVEC(_pvec)	portvec2lportvec(dev->validPortVec, _pvec)
+#define GT_LPORT_2_PHY(_lport) 			lport2phy(dev,_lport)
+#endif
+
+#define GT_IS_PORT_SET(_portVec, _port)	\
+			((_portVec) & (0x1 << (_port)))
+
+#define GT_IS_IRLUNIT_VALID(_dev,_unit)		\
+		(((_dev)->deviceId == GT_88E6065)?(_unit < 12):	\
+		(((_dev)->deviceId == GT_88E6055)?(_unit < 12):	\
+		(((_dev)->deviceId == GT_88E6061)?(_unit < 6):	\
+		(((_dev)->deviceId == GT_88E6035)?(_unit < 6):	\
+										 (_unit < 3)))))
+
+
+/* The following macro converts a binary    */
+/* value (of 1 bit) to a boolean one.       */
+/* 0 --> GT_FALSE                           */
+/* 1 --> GT_TRUE                            */
+#define BIT_2_BOOL(binVal,boolVal)                                  \
+            (boolVal) = (((binVal) == 0) ? GT_FALSE : GT_TRUE)
+
+/* The following macro converts a boolean   */
+/* value to a binary one (of 1 bit).        */
+/* GT_FALSE --> 0                           */
+/* GT_TRUE --> 1                            */
+#define BOOL_2_BIT(boolVal,binVal)                                  \
+            (binVal) = (((boolVal) == GT_TRUE) ? 1 : 0)
+
+/* The following macro converts a binary    */
+/* value (of 1 bit) to a boolean one.       */
+/* 0 --> GT_TRUE                            */
+/* 1 --> GT_FALSE                           */
+#define BIT_2_BOOL_R(binVal,boolVal)                                  \
+            (boolVal) = (((binVal) == 0) ? GT_TRUE : GT_FALSE)
+
+/* The following macro converts a boolean   */
+/* value to a binary one (of 1 bit).        */
+/* GT_FALSE --> 1                           */
+/* GT_TRUE --> 0                            */
+#define BOOL_2_BIT_R(boolVal,binVal)                                  \
+            (binVal) = (((boolVal) == GT_TRUE) ? 0 : 1)
+
+/* Bit definition for devStorage */
+/* Ingress/Egress Rate type (grcSetPri0Rate,	grcSetEgressRate) */
+#define GT_RATE_ENUM_NOT_USED		0x10000
+#define GT_RATE_ENUM_USED			0x00000
+
+/* device name - devName */
+#define DEV_88E6051                      0x0001    /* quarterdeck 6051      */
+#define DEV_88E6052                      0x0002    /* quarterdeck 6052      */
+#define DEV_88E6021                      0x0004    /* fullsail              */
+#define DEV_88E6060                      0x0008    /* Gondola               */
+#define DEV_88E6063                      0x0010    /* clippership 6063      */
+#define DEV_FF_EG                        0x0020    /* FireFox-EG            */
+#define DEV_FF_HG                        0x0040    /* FireFox-HG            */
+#define DEV_FH_VPN                       0x0080    /* FireHawk-VPN          */
+#define DEV_88E6083                      0x0100    /* Octane 6083           */
+#define DEV_88E6181                      0x0200    /* Sapphire 88E6181      */
+#define DEV_88E6183                      0x0400    /* Sapphire 88E6153,88E6183 */
+#define DEV_88E6093	 	                 0x0800   /* 88E6093                  */
+#define DEV_88E6092	 	                 0x1000   /* 88E6092                  */
+#define DEV_88E6095	 	                 0x2000   /* 88E6095                  */
+#define DEV_88E6182                      0x4000   /* Jade 88E6152, 88E6182 */
+#define DEV_88E6185                      0x8000   /* Jade 88E6155, 88E6185 */
+#define DEV_88E6108                      0x10000   /* 88E6108 */
+#define DEV_88E6061                      0x20000   /* 88E6031, 88E6061 */
+#define DEV_88E6065                      0x40000   /* 88E6035, 88E6055, 88E6065 */
+#define DEV_88E6096                      0x80000   /* 88E6096, 88E6046 */
+#define DEV_88E6097                      0x100000   /* 88E6097, 88E6047 */
+#define DEV_88E6161                      0x200000   /* 88E6161 */
+#define DEV_88E6165                      0x400000   /* 88E6165 */
+
+#define DEV_88E6351                      0x800000   /* 88E6351 */
+#define DEV_88E6175                      0x1000000  /* 88E6175 */
+#define DEV_88E6171                      0x2000000  /* 88E6125 and 88E6171 */
+#define DEV_88E6371                      0x4000000  /* 88E6321, 88E6350 */
+
+#define DEV_88E6097_FAMILY	( DEV_88E6096 | DEV_88E6097 )
+#define DEV_88E6165_FAMILY	( DEV_88E6161 | DEV_88E6165 )
+
+#define DEV_88E6351_AVB_FAMILY	( DEV_88E6351 | DEV_88E6371 )
+#define DEV_88E6351_NO_AVB_FAMILY	( DEV_88E6175 | DEV_88E6171 )
+#define DEV_88E6351_FAMILY	( DEV_88E6351_AVB_FAMILY | DEV_88E6351_NO_AVB_FAMILY)
+
+#define DEV_88E6095_FAMILY	( DEV_88E6092 | DEV_88E6095 )
+#define DEV_88E6185_FAMILY	( DEV_88E6182 | DEV_88E6185 | DEV_88E6108)
+
+#define DEV_88E6065_FAMILY	( DEV_88E6061 | DEV_88E6065 )
+
+#define DEV_NEW_FEATURE_IN_REV (DEV_88E6095_FAMILY | DEV_88E6182 | DEV_88E6185)
+
+#define DEV_BURST_RATE		( DEV_88E6108 )
+#define DEV_DROP_BCAST		( DEV_88E6108 )
+#define DEV_ARP_PRI	    ( DEV_88E6108 )
+#define DEV_SNOOP_PRI	    ( DEV_88E6108 )
+#define DEV_SERDES_CORE	( DEV_88E6108 | DEV_88E6165_FAMILY )
+
+#define DEV_AGE_INTERRUPT		\
+						( DEV_88E6108 | DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+#define DEV_AGE_INT_GLOBAL2	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_AGE_OUT_INT		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_AGE_HOLD			\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_DEVICE_INTERRUPT	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_DEVICE_INT_TYPE1	\
+						( DEV_88E6097_FAMILY )	/* Serdes Int bit[10:8] */
+#define DEV_DEVICE_INT_TYPE2	\
+						( DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )	/* Serdes Int bit[12:11], Phy Int bit[4:0] */
+
+#define DEV_WATCHDOG_EVENT		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_PORT_BASED_AGE_INT	( DEV_88E6065_FAMILY )
+
+#define DEV_DEV_PHY_INTERRUPT	\
+						( DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )	/* device interrupt includes phy int */
+
+#define DEV_AVB_INTERRUPT		\
+						( DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_AUTO_REFRESH_LOCKED	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_PPU_PHY_ACCESS			\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+#define DEV_PPU_PHY_ACCESS_RES	( DEV_88E6097_FAMILY )
+
+#define DEV_PPU_READ_ONLY			\
+						( DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_PPU_SERDES_ACCESS_RES	( DEV_88E6165_FAMILY )
+
+#define DEV_NO_EGRESS_POLICY		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+/* DEV_8PORT_SWITCH is used to access the given device's Register Map */
+#define DEV_8PORT_SWITCH	( DEV_88E6083 | DEV_88E6181 | DEV_88E6183 | 	\
+							  DEV_88E6093 | DEV_88E6097_FAMILY |			\
+							  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |		\
+							  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_PORT_SECURITY	( DEV_88E6083 | DEV_88E6183 | DEV_88E6093 | 	\
+							  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )
+
+#define DEV_BROADCAST_INVALID	( DEV_88E6051 | DEV_88E6052 | DEV_FF_EG | DEV_FF_HG)
+
+/* Configurable ATU Size */
+#define DEV_ATU_256_2048 		( DEV_88E6021 | DEV_88E6060 | DEV_88E6065_FAMILY )
+#define DEV_ATU_562_2048 		\
+						( DEV_88E6052 | DEV_88E6063 | DEV_FF_HG | 	\
+						  DEV_FH_VPN | DEV_88E6083 )
+
+#define DEV_ATU_SIZE_FIXED	DEV_GIGABIT_SWITCH
+
+#define DEV_ATU_1024	(DEV_88E6108)	/* Not used */
+#define DEV_ATU_8192	(DEV_88E6095_FAMILY | DEV_88E6182 | DEV_88E6185)	/* Not used */
+
+#define DEV_ATU_LIMIT		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_ATU_LIMIT_READ		\
+						( DEV_88E6351_FAMILY )
+
+#define DEV_DBNUM_FULL 	\
+						( DEV_88E6021 | DEV_88E6060 | DEV_88E6063 | 	\
+						  DEV_FH_VPN |  DEV_88E6083 |					\
+						  DEV_88E6183 | DEV_88E6093 | DEV_88E6061 )
+
+#define DEV_DBNUM_64 	( DEV_88E6065 )
+#define DEV_DBNUM_256 	( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )
+#define DEV_DBNUM_4096 	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_STATIC_ADDR	\
+						( DEV_88E6021 | DEV_FF_EG | DEV_FF_HG |			\
+						  DEV_88E6052 | DEV_88E6063 | DEV_FH_VPN |		\
+						  DEV_88E6083 |	DEV_88E6183 | DEV_88E6093 | 	\
+						  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |		\
+						  DEV_88E6065_FAMILY | DEV_88E6097_FAMILY |		\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_TRAILER		\
+						( DEV_88E6021 | DEV_FF_HG | DEV_88E6052 |  		\
+						  DEV_88E6063 | DEV_FH_VPN | DEV_88E6083 )
+
+#define DEV_TRAILER_P5		( DEV_FF_EG )
+#define DEV_TRAILER_P4P5	( DEV_88E6060 )
+
+#define DEV_HEADER		\
+						( DEV_FF_HG | DEV_88E6063 | DEV_FH_VPN |	\
+						  DEV_88E6083 |	DEV_88E6183 | DEV_88E6093 | \
+						  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |	\
+						  DEV_88E6065_FAMILY | DEV_88E6097_FAMILY |	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_HEADER_P5		( DEV_FF_EG )
+#define DEV_HEADER_P4P5  	( DEV_88E6060 )
+
+/* DEV_QoS : Devices with multiple Queues for QoS Priority Support */
+#define DEV_QoS			\
+						( DEV_88E6021 | DEV_FF_HG |	DEV_88E6051 | 		\
+						  DEV_88E6052 | DEV_88E6063 | DEV_FH_VPN |		\
+						  DEV_88E6083 | DEV_88E6181 | DEV_88E6183 | 	\
+						  DEV_88E6093 | DEV_88E6095_FAMILY |			\
+						  DEV_88E6185_FAMILY | DEV_88E6065_FAMILY | 	\
+						  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_QoS_FPRI_QPRI	( DEV_88E6065_FAMILY )
+#define DEV_QoS_WEIGHT		( DEV_88E6097 | DEV_88E6165 | DEV_88E6351_AVB_FAMILY | DEV_88E6175 )
+
+#define DEV_TAGGING			DEV_QoS
+
+#define DEV_EGRESS_DOUBLE_TAGGING	\
+						( DEV_QoS & ~(DEV_88E6051 | DEV_88E6092 | DEV_88E6182 | \
+									  DEV_88E6061 ) )
+
+#define DEV_INGRESS_DOUBLE_TAGGING	\
+						( DEV_88E6181 | DEV_88E6183 | DEV_88E6093 | 	\
+						  DEV_88E6095 | DEV_88E6185 | DEV_88E6108 )
+
+#define DEV_PRIORITY_REMAPPING		\
+						( DEV_88E6181 | DEV_88E6183 | DEV_88E6093 | 	\
+						  DEV_88E6095 | DEV_88E6185 | DEV_88E6108 |		\
+						  DEV_88E6065 | DEV_88E6097_FAMILY | 			\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+
+#define DEV_802_1Q		( DEV_88E6021 | DEV_88E6063 | DEV_FH_VPN | 			\
+						  DEV_88E6083 | DEV_88E6183 | DEV_88E6093 | 		\
+						  DEV_88E6095 | DEV_88E6092 | DEV_88E6185_FAMILY |	\
+						  DEV_88E6065_FAMILY | DEV_88E6097_FAMILY |			\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_802_1S		( DEV_88E6095 | DEV_88E6185 | DEV_88E6108 | DEV_88E6065 )
+#define DEV_802_1S_STU	( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_802_1W		( DEV_88E6183 | DEV_88E6093 | DEV_88E6095 | 	\
+						  DEV_88E6185 | DEV_88E6108 | DEV_88E6065 |		\
+						  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_ATU_15SEC_AGING	( DEV_GIGABIT_SWITCH | DEV_88E6065_FAMILY )
+#define DEV_ATU_RM_PORTS	( DEV_88E6093_FAMILY | DEV_88E6065 )
+#define DEV_ATU_EXT_PRI		( DEV_88E6065_FAMILY )
+
+#define DEV_VTU_EXT_INFO	( DEV_88E6065_FAMILY )
+
+#define DEV_RMON		( DEV_88E6021 | DEV_88E6063 | DEV_FH_VPN | 			\
+						  DEV_88E6083 | DEV_88E6183 | DEV_88E6093 | 		\
+						  DEV_88E6092 | DEV_88E6095 | DEV_88E6185_FAMILY |	\
+						  DEV_88E6065 | DEV_88E6097_FAMILY |				\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY ) 
+
+#define DEV_RMON_TYPE_1	( DEV_88E6021 | DEV_88E6063 | DEV_FH_VPN | DEV_88E6083 ) 
+#define DEV_RMON_TYPE_2 ( DEV_88E6183 )
+#define DEV_RMON_TYPE_3 	\
+						( DEV_88E6093 | DEV_88E6095 | DEV_88E6092 | 	\
+						  DEV_88E6185_FAMILY | DEV_88E6065 | 			\
+						  DEV_88E6097_FAMILY |		\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_RMON_REALTIME_SUPPORT	\
+						( DEV_88E6065 | DEV_88E6065_FAMILY |	\
+						  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |	\
+						  DEV_88E6351_FAMILY )
+#define DEV_RMON_PORT_BITS	( DEV_88E6065 | DEV_88E6065_FAMILY )
+
+#define DEV_IGMP_SNOOPING	\
+						( DEV_88E6021 | DEV_88E6063 | DEV_FH_VPN |			\
+						  DEV_88E6083 | DEV_88E6183 | DEV_88E6093 | 		\
+						  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |			\
+						  DEV_88E6065_FAMILY | DEV_88E6097_FAMILY |			\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_PORT_MONITORING	\
+						( DEV_88E6060 | DEV_88E6063 | DEV_FH_VPN |			\
+						  DEV_88E6083 | DEV_88E6183 | DEV_88E6093 | 		\
+						  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |			\
+						  DEV_88E6065_FAMILY | DEV_88E6097_FAMILY |			\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_ENABLE_MONITORING	\
+						( DEV_88E6060 | DEV_88E6063 | DEV_FH_VPN |			\
+						  DEV_88E6083 | DEV_88E6183 | DEV_88E6093 |			\
+						  DEV_88E6065_FAMILY )
+
+#define DEV_MC_RATE_PERCENT	\
+						( DEV_88E6021 | DEV_88E6051 | DEV_88E6052 )
+
+#define DEV_MC_RATE_KBPS	\
+						( DEV_FF_HG | DEV_88E6063 | DEV_FH_VPN |			\
+						  DEV_88E6083 )
+
+#define DEV_INGRESS_RATE_KBPS	\
+						( DEV_FF_HG | DEV_88E6063 | DEV_FH_VPN |			\
+						  DEV_88E6083 | DEV_88E6181 | DEV_88E6183 | 		\
+						  DEV_88E6093 | DEV_88E6095_FAMILY | DEV_88E6185_FAMILY)
+
+#define DEV_EGRESS_RATE_KBPS	\
+						( DEV_FF_HG | DEV_88E6063 | DEV_FH_VPN |			\
+						  DEV_88E6083 | DEV_88E6181 | DEV_88E6183 | 		\
+						  DEV_88E6093 | DEV_88E6095 | DEV_88E6185 | 		\
+						  DEV_88E6108 | DEV_88E6065_FAMILY | 				\
+						  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 		\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_ELIMIT_FRAME_BASED	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_PIRL_RESOURCE	\
+						( DEV_88E6065_FAMILY )
+
+#define DEV_PIRL2_RESOURCE	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_RESTRICTED_PIRL_RESOURCE	\
+						( DEV_88E6061 )
+
+#define DEV_RESTRICTED_PIRL2_RESOURCE	\
+						( DEV_88E6096 | DEV_88E6161 | DEV_88E6171 )
+
+
+#define DEV_NONE_RATE_LIMIT		\
+						( DEV_88E6065 )
+
+#define DEV_MII_DUPLEX_CONFIG	\
+						( DEV_88E6021 | DEV_88E6063 | DEV_FH_VPN |			\
+						  DEV_88E6083 )
+
+#define DEV_QD_PLUS 	\
+					( DEV_88E6021 | DEV_FF_EG | DEV_FF_HG |					\
+					  DEV_88E6060 | DEV_88E6063 | DEV_FH_VPN |				\
+					  DEV_88E6083 | DEV_88E6181 | DEV_88E6183 | 			\
+					  DEV_88E6093 | 										\
+					  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |				\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY  |			\
+					  DEV_88E6351_FAMILY )
+
+#define DEV_FASTETH_SWITCH	\
+					( DEV_88E6051 | DEV_88E6052 | DEV_88E6021 | 		\
+					  DEV_FF_EG | DEV_FF_HG | DEV_88E6060 | 			\
+					  DEV_88E6063 | DEV_FH_VPN | DEV_88E6083 |			\
+					  DEV_88E6065_FAMILY )
+
+#define DEV_ENHANCED_FE_SWITCH		( DEV_88E6065_FAMILY )
+
+#define DEV_EXTERNAL_PHY	\
+					( DEV_88E6181 | DEV_88E6183 | DEV_88E6093 |			\
+					  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |			\
+					  DEV_88E6097_FAMILY )
+
+#define DEV_EXTERNAL_PHY_ONLY	( DEV_88E6181 | DEV_88E6183 | DEV_88E6182 | DEV_88E6185 )
+
+#define DEV_INTERNAL_GPHY   ( DEV_88E6108 )
+
+#define DEV_FC_WITH_VALUE			\
+					( DEV_88E6093 | DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |	\
+					  DEV_88E6065_FAMILY | DEV_88E6097_FAMILY |					\
+					  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_FC_STATUS				\
+					( DEV_88E6181 | DEV_88E6183 | DEV_88E6093 | 	\
+					  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY | 	\
+					  DEV_88E6065_FAMILY | DEV_88E6097_FAMILY |		\
+					  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_FC_DIS_STATUS	( DEV_88E6065_FAMILY )
+
+#define DEV_CORE_TAG		( DEV_88E6093 | DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )
+
+#define DEV_PCS_LINK		( DEV_88E6093 | DEV_88E6095_FAMILY | 	\
+							  DEV_88E6185_FAMILY | DEV_88E6097_FAMILY |	\
+							  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_MGMII_STATUS	( DEV_88E6093 | DEV_88E6095_FAMILY | 	\
+							  DEV_88E6185_FAMILY | DEV_88E6097_FAMILY |	\
+							  DEV_88E6165_FAMILY )
+
+#define DEV_MGMII_REVERSE_STATUS	( DEV_88E6165_FAMILY )
+
+#define DEV_88E6183_FAMILY		( DEV_88E6183 | DEV_88E6185_FAMILY )
+#define DEV_88E6093_FAMILY		( DEV_88E6093 | DEV_88E6095_FAMILY | 		\
+								  DEV_88E6185_FAMILY | DEV_88E6097_FAMILY |	\
+								  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_UNMANAGED_SWITCH	( DEV_88E6181 )
+
+#define DEV_PCS					\
+					( DEV_88E6181 | DEV_88E6183 | DEV_88E6093 | 	\
+					  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY | 	\
+					  DEV_88E6097_FAMILY )
+
+#define DEV_GIGABIT_SWITCH		\
+					( DEV_88E6181 | DEV_88E6183 | DEV_88E6093 | 	\
+					  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY | 	\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+					  DEV_88E6351_FAMILY )
+
+#define DEV_GIGABIT_MANAGED_SWITCH	\
+					( DEV_88E6183 | DEV_88E6093 | \
+					  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY | 	\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+					  DEV_88E6351_FAMILY )
+
+#define DEV_CASCADE_PORT	\
+					( DEV_88E6183 | DEV_88E6093 | \
+					  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )
+
+
+#define DEV_CROSS_CHIP_VLAN		\
+					( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )
+
+#define DEV_CROSS_CHIP_PORT_VLAN	\
+					( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |	\
+					  DEV_88E6351_FAMILY )
+
+#define DEV_TRUNK	( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |		\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+					  DEV_88E6351_FAMILY )
+
+#define DEV_8_TRUNKING	( DEV_88E6092 | DEV_88E6182 )
+
+#define DEV_TRUNK_NEW_ID_LOCATION	\
+					( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+					  DEV_88E6351_FAMILY )
+
+#define DEV_REDUCED_TRUNK	( DEV_88E6065_FAMILY )
+
+#define DEV_STACKING	\
+					( DEV_88E6095 | DEV_88E6185 | DEV_88E6108 |		\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+					  DEV_88E6351_FAMILY )
+
+#define DEV_FRAME_SIZE_1632		\
+					( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )		/* Not used */
+
+#define DEV_FLOW_CTRL_DELAY		\
+					( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |		\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+					  DEV_88E6351_FAMILY )
+
+/* port based CPU Port */
+#define DEV_ENHANCED_CPU_PORT	\
+					( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |		\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+					  DEV_88E6351_FAMILY )
+
+#define DEV_CPU_DEST_PER_PORT	\
+					( DEV_88E6183 | DEV_88E6093 | \
+					  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )
+
+#define DEV_CPU_PORT	( DEV_88E6065_FAMILY )
+#define DEV_MULTICAST	( DEV_88E6065_FAMILY )
+
+#define DEV_CPU_DEST		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+#define DEV_MIRROR_DEST	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_QVLAN_ONLY		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY )
+#define DEV_5BIT_PORT		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+#define DEV_SDET_POLARITY	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY )
+#define DEV_LIMITED_SDET	\
+						( DEV_88E6165_FAMILY ) 	/* only port 4 & 5 support SDET Polarity */
+
+/* supports Reserved Multicast, etc */
+#define DEV_ENHANCED_MULTICAST	\
+						( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |		\
+						  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_ENHANCED_MULTICAST_2X	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | \
+						  DEV_88E6351_FAMILY )
+
+
+#define DEV_ARP_DEST_SUPPORT		( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )
+
+#define DEV_MARVELL_TAG_FLOW_CTRL	\
+						( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |		\
+						  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY |		\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_USE_DOUBLE_TAG_DATA		\
+						( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )		/* Not Used */
+
+#define DEV_MARVELL_TAG_LOOP_BLOCK	( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )
+
+#define DEV_LOOPBACK_FILTER		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+#define DEV_FLOOD_BROADCAST		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+#define DEV_TAG_FLOW_CONTROL		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+#define DEV_ALWAYS_USE_VTU		( DEV_88E6097_FAMILY )
+
+#define DEV_RM_ONE_PTAG			\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+					
+#define DEV_PRIORITY_OVERRIDE	\
+						( DEV_88E6183 | DEV_88E6093 | DEV_88E6095 | 	\
+						  DEV_88E6185 | DEV_88E6108 | DEV_88E6097_FAMILY |	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_EXT_PRIORITY_OVERRIDE		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_PRIORITY_OVERRIDE_TABLE	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_FQPRI_IN_TABLE		( DEV_88E6065 )
+
+#define DEV_FQPRI_OVERRIDE		( DEV_88E6065 )
+
+#define DEV_Px_MODE 	( DEV_88E6065_FAMILY )
+
+#define DEV_SA_FILTERING	\
+						( DEV_88E6065 | DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | \
+						  DEV_88E6351_FAMILY )
+
+#define DEV_ARP_TO_CPU		\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_EGRESS_FLOOD	\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_FORCE_MAP		( DEV_88E6065_FAMILY )
+
+#define DEV_PORT_SCHEDULE	( DEV_88E6065 )
+
+#define DEV_PORT_MIXED_SCHEDULE		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_OUT_Q_SIZE		\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_OUT_Q_512		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+#define DEV_FULL_Q_COUNTER		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_PROVIDER_TAG	( DEV_88E6065_FAMILY )
+
+#define DEV_OLD_HEADER		( DEV_88E6065_FAMILY )
+
+#define DEV_RECURSIVE_TAG_STRIP		( DEV_88E6065_FAMILY )
+
+#define DEV_FORCE_WITH_VALUE			\
+						( DEV_88E6181 | DEV_88E6183 | DEV_88E6093 | 	\
+						  DEV_88E6095_FAMILY | DEV_88E6185_FAMILY |		\
+						  DEV_88E6065_FAMILY | DEV_88E6097_FAMILY |		\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+/* Grouping ATU Entry State for Unicast */
+
+#define DEV_UC_7_DYNAMIC		\
+					( DEV_88E6065_FAMILY | DEV_88E6095_FAMILY |	DEV_88E6185_FAMILY |	\
+					  DEV_88E6183 | DEV_88E6093 | DEV_88E6097_FAMILY |					\
+					  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_UC_NO_PRI_TO_CPU_STATIC_NRL		\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_UC_TO_CPU_STATIC_NRL			\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_UC_NO_PRI_STATIC_NRL			\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_UC_STATIC_NRL					\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_UC_NO_PRI_TO_CPU_STATIC			\
+					( DEV_88E6065_FAMILY | DEV_88E6095_FAMILY |	DEV_88E6185_FAMILY |	\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_UC_TO_CPU_STATIC			\
+					( DEV_88E6065_FAMILY | DEV_88E6095_FAMILY |	DEV_88E6185_FAMILY |	\
+					  DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_UC_NO_PRI_STATIC			\
+					( DEV_88E6065_FAMILY | DEV_88E6095_FAMILY |	DEV_88E6185_FAMILY |	\
+					  DEV_88E6183 | DEV_88E6093 | DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | \
+					  DEV_88E6351_FAMILY )
+
+#define DEV_UC_STATIC	( DEV_STATIC_ADDR )
+
+
+/* Grouping ATU Entry State for Multicast */
+
+#define DEV_MC_MGM_STATIC_UNLIMITED_RATE		\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_MC_PRIO_MGM_STATIC_UNLIMITED_RATE	\
+						( DEV_88E6065_FAMILY | DEV_88E6097_FAMILY | 	\
+						  DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_MC_STATIC_UNLIMITED_RATE	( DEV_STATIC_ADDR & ~DEV_88E6052 )
+
+#define DEV_MC_MGM_STATIC		( DEV_STATIC_ADDR )
+
+#define DEV_MC_STATIC				( DEV_STATIC_ADDR )
+#define DEV_MC_PRIO_MGM_STATIC		( DEV_STATIC_ADDR )
+
+#define DEV_MC_PRIO_STATIC_UNLIMITED_RATE ( DEV_STATIC_ADDR & ~ (DEV_88E6083|DEV_88E6052) )
+
+#define DEV_MC_PRIO_STATIC		( DEV_STATIC_ADDR & ~DEV_88E6083 )
+
+
+/* Grouping Devices that support Pause Limit */
+#define DEV_PAUSE_LIMIT		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+/* Grouping Devices that support Frame Mode */
+#define DEV_FRAME_MODE			\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | 	\
+						  DEV_88E6351_FAMILY )
+
+#define DEV_POLICY			\
+						( DEV_88E6097 | DEV_88E6165 | DEV_88E6351_AVB_FAMILY | DEV_88E6175 )
+
+#define DEV_PORT_ETYPE		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_FID_REG		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_FRAME_TO_REGISTER	\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_RMU_MODE	( DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_SWITCH_MAC_REG		\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_ATU_STATS			\
+						( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+
+#define DEV_JUMBO_MODE		\
+						( DEV_88E6165_FAMILY | DEV_88E6351_FAMILY )
+#define DEV_PTP		( DEV_88E6165_FAMILY | DEV_88E6351_AVB_FAMILY )
+#define DEV_PTP_2		( DEV_88E6351_AVB_FAMILY )
+#define DEV_TAI		( DEV_88E6351_AVB_FAMILY )
+#define DEV_AVB_POLICY	( DEV_88E6351_AVB_FAMILY )
+#define DEV_QAV		( DEV_88E6351_AVB_FAMILY )
+
+#define DEV_TSM_RESOURCE	( DEV_88E6351_AVB_FAMILY )
+
+#define DEV_200BASE_CFG	( DEV_88E6351_FAMILY )
+#define DEV_RGMII_TIMING	( DEV_88E6351_FAMILY )
+#define DEV_Q_COUNTER_TABLE	( DEV_88E6351_FAMILY )
+#define DEV_LED_CFG		( DEV_88E6351_FAMILY )
+
+#define DEV_MAC_AVB		( DEV_88E6351_AVB_FAMILY )
+
+#define DEV_CLK_125		( DEV_88E6351_FAMILY )
+
+#define DEV_QAVB_PRIORITY_OVERRIDE_TABLE	\
+						( DEV_88E6351_AVB_FAMILY )
+#define DEV_FRAME_PRIORITY_OVERRIDE_TABLE	\
+						( DEV_88E6351_FAMILY )
+
+#define DEV_SCRATCH_MISC_CTRL		( DEV_88E6351_FAMILY )
+#define DEV_IP_MAPPING_TABLE		( DEV_88E6351_FAMILY )
+#define DEV_EEPROM					( DEV_88E6351_FAMILY )
+
+
+/* Macros to utilize Device Group */
+
+#define IS_IN_DEV_GROUP(dev,_group) (dev->devName & (_group))
+
+/* need to check port number(_hwPort) later */
+#define IS_VALID_API_CALL(dev,_hwPort, _devName)	    	\
+	((_hwPort == GT_INVALID_PORT) ? GT_BAD_PARAM :			\
+	(!(dev->devName & (_devName)) ? GT_NOT_SUPPORTED : GT_OK))
+
+#define DOES_DEVPORT_SUPPORT_PCS(dev, _hwPort)			\
+	(!(dev->devName & DEV_GIGABIT_SWITCH) || \
+	 (dev->devName & DEV_INTERNAL_GPHY) ||   \
+	(!(dev->devName & DEV_EXTERNAL_PHY_ONLY) && (((_hwPort) < 8) || ((_hwPort) > 10)))	\
+	? 0 : 1)
+
+#define IS_CONFIGURABLE_PHY(dev,_hwPort)	driverIsPhyAttached(dev,_hwPort)
+#define GT_GET_PHY_ID(dev,_hwPort)			driverGetPhyID(dev,_hwPort)
+
+#define GT_GET_SERDES_PORT(dev,_hwPort)		driverGetSerdesPort(dev,_hwPort)
+
+#define GT_GIG_PHY_INT_MASK(dev,_portVct)    ((_portVct) = (_portVct) & 0xF7)
+
+
+#define RECOMMENDED_ESB_LIMIT(dev, _bps)					\
+		((IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))?16777200:0xFFFFF0)
+
+#define RECOMMENDED_CBS_LIMIT(dev, _bps)					\
+		((IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))?393216:5000000/*0x200000*/)
+                                                           
+
+#define RECOMMENDED_BUCKET_INCREMENT(dev, _bps)				\
+		((IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))?174:		\
+		((_bps) < 1000)?3125:           	    			\
+		((_bps) < 10000)?25: 5)
+
+#define FACTOR_FROM_BUCKET_INCREMENT(dev, _bInc, _f)		\
+	{														\
+		if(IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))			\
+		{													\
+			if((_bInc) == 174) {(_f) = 64;}					\
+			else {(_f) = 0;}								\
+		}													\
+		else												\
+		{													\
+			if((_bInc) == 3125) {(_f) = 32;}				\
+			else if((_bInc) == 25) {(_f) = 4;}  			\
+			else if((_bInc) == 50) {(_f) = 8;}              \
+			else if((_bInc) == 5) {(_f) = 8;}   			\
+			else {(_f) = 0;}								\
+		}													\
+	}
+
+
+#define TSM_GET_CBS(_rate,_cts)	((_rate)/((_cts)*8))
+#define TSM_GET_RATE(_cbs,_cts)	((_cbs)*8*(_cts))
+
+
+#define GT_PTP_BUILD_TIME(_time1, _time2)       (((_time1) << 16) | (_time2))
+#define GT_PTP_L16_TIME(_time1) ((_time1) & 0xFFFF)
+#define GT_PTP_H16_TIME(_time1) (((_time1) >> 16) & 0xFFFF)
+
+/*
+ * typedef: enum GT_ATU_STATS_OP
+ *
+ * Description: Enumeration of the ATU Statistics operation
+ *
+ * Enumerations:
+ *   GT_ATU_STATS_ALL        - count all valid entry
+ *   GT_ATU_STATS_NON_STATIC - count all vaild non-static entry
+ *   GT_ATU_STATS_ALL_FID    - count all valid entry in the given DBNum(or FID) 
+ *   GT_ATU_STATS_NON_STATIC_FID - count all valid non-static entry in the given DBNum(or FID)
+ */
+typedef enum
+{
+    GT_ATU_STATS_ALL = 0,
+    GT_ATU_STATS_NON_STATIC,
+    GT_ATU_STATS_ALL_FID,
+	GT_ATU_STATS_NON_STATIC_FID
+}GT_ATU_STATS_OP;
+
+
+/*
+ *  typedef: struct GT_ATU_STAT
+ *
+ *  Description: 
+ *		This structure is used to count ATU entries.
+ *
+ *  Fields:
+ *      op 	  - counter type
+ *		DBNum - required only if op is either GT_ATU_STATS_FID or 
+ *				GT_ATU_STATS_NON_STATIC_FID
+ */
+typedef struct
+{
+	GT_ATU_STATS_OP	op;
+	GT_U32 			DBNum;
+} GT_ATU_STAT;
+
+
+typedef struct _EXTRA_OP_DATA
+{
+	GT_U32 moveFrom;
+	GT_U32 moveTo;
+	GT_U32 intCause;
+	GT_U32 reserved;
+} GT_EXTRA_OP_DATA;
+
+/*******************************************************************************
+* gvtuGetViolation
+*
+* DESCRIPTION:
+*       Get VTU Violation data
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       vtuIntStatus - interrupt cause, source portID, and vid.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORT  - if current device does not support this feature.
+*
+* COMMENTS:
+*		This is an internal function. No user should call this function.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetViolation
+(
+    IN GT_QD_DEV*       dev,
+    OUT GT_VTU_INT_STATUS *vtuIntStatus
+);
+
+/*******************************************************************************
+* gvtuGetViolation2
+*
+* DESCRIPTION:
+*       Get VTU Violation data (for Gigabit Device)
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       vtuIntStatus - interrupt cause, source portID, and vid.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORT  - if current device does not support this feature.
+*
+* COMMENTS:
+*		This is an internal function. No user should call this function.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetViolation2
+(
+    IN GT_QD_DEV*       dev,
+    OUT GT_VTU_INT_STATUS *vtuIntStatus
+);
+
+/*******************************************************************************
+* gvtuGetViolation3
+*
+* DESCRIPTION:
+*       Get VTU Violation data (for Spinnaker family Device)
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       vtuIntStatus - interrupt cause, source portID, and vid.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORT  - if current device does not support this feature.
+*
+* COMMENTS:
+*		This is an internal function. No user should call this function.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetViolation3
+(
+    IN GT_QD_DEV*       dev,
+    OUT GT_VTU_INT_STATUS *vtuIntStatus
+);
+
+/*******************************************************************************
+* gatuGetViolation
+*
+* DESCRIPTION:
+*       Get ATU Violation data
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       atuIntStatus - interrupt cause, source portID, and vid.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORT  - if current device does not support this feature.
+*
+* COMMENTS:
+*		This is an internal function. No user should call this function.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gatuGetViolation
+(
+    IN  GT_QD_DEV         *dev,
+    OUT GT_ATU_INT_STATUS *atuIntStatus
+);
+
+/*******************************************************************************
+* gsysSetRetransmitMode
+*
+* DESCRIPTION:
+*       This routine set the Retransmit Mode.
+*
+* INPUTS:
+*       en - GT_TRUE Retransimt Mode is enabled, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetRetransmitMode
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_BOOL en
+);
+
+/*******************************************************************************
+* gsysGetRetransmitMode
+*
+* DESCRIPTION:
+*       This routine get the Retransmit Mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE Retransmit Mode is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetRetransmitMode
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_BOOL *en
+);
+
+/*******************************************************************************
+* gsysSetLimitBackoff
+*
+* DESCRIPTION:
+*       This routine set the Limit Backoff bit.
+*
+* INPUTS:
+*       en - GT_TRUE:  uses QoS half duplex backoff operation  
+*            GT_FALSE: uses normal half duplex backoff operation
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetLimitBackoff
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_BOOL en
+);
+
+/*******************************************************************************
+* gsysGetLimitBackoff
+*
+* DESCRIPTION:
+*       This routine set the Limit Backoff bit.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE:  uses QoS half duplex backoff operation  
+*            GT_FALSE: uses normal half duplex backoff operation
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetLimitBackoff
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_BOOL *en
+);
+
+/*******************************************************************************
+* gsysSetRsvRegPri
+*
+* DESCRIPTION:
+*       This routine set the Reserved Queue's Requesting Priority 
+*
+* INPUTS:
+*       en - GT_TRUE: use the last received frome's priority
+*            GT_FALSE:use the last switched frame's priority 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetRsvReqPri
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_BOOL en
+);
+
+/*******************************************************************************
+* gsysGetRsvReqPri
+*
+* DESCRIPTION:
+*       This routine get the Reserved Queue's Requesting Priority 
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE: use the last received frome's priority
+*            GT_FALSE:use the last switched frame's priority 
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetRsvReqPri
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_BOOL *en
+);
+
+/*******************************************************************************
+* gsysGetPtrCollision
+*
+* DESCRIPTION:
+*       This routine get the QC Pointer Collision.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE Discard is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+* 		This feature is for both clippership and fullsail
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPtrCollision
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_BOOL *mode
+);
+
+/*******************************************************************************
+* gsysGetDpvCorrupt
+*
+* DESCRIPTION:
+*       This routine get the DpvCorrupt bit. This bit is set to a one when the 
+*       QC detects a destination vector error
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE: destination vector corrupt, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+* 	This feature is on clippership, but not on fullsail
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetDpvCorrupt
+(
+    IN GT_BOOL *mode
+);
+
+/*******************************************************************************
+* gsysGetMissingPointers
+*
+* DESCRIPTION:
+*       This routine get the Missing Pointer bit. This bit is set to a one when  
+*       the Register File detects less than 64 pointers in the Link List. 
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE: Missing Pointers error, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+* 	This feature is on clippership, but not on fullsail
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetMissingPointers
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_BOOL *mode
+);
+
+/*******************************************************************************
+* gtDbgPrint
+*
+* DESCRIPTION:
+*       .
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void gtDbgPrint(char* format, ...);
+
+
+/*******************************************************************************
+* gtSemRegister
+*
+* DESCRIPTION:
+*       Assign QuarterDeck Semaphore functions to the given semaphore set.
+*		QuarterDeck maintains its own memory for the structure.
+*
+* INPUTS:
+*		semFunctions - point to the GT_SEM_ROUTINES
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtSemRegister
+(
+    IN GT_QD_DEV*       dev,
+    IN  GT_SEM_ROUTINES* semRoutines
+);
+
+
+/*******************************************************************************
+* gpirlInitialize
+*
+* DESCRIPTION:
+*       This routine initializes PIRL Resources.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlInitialize
+(
+    IN  GT_QD_DEV  			*dev
+);
+
+/*******************************************************************************
+* gpirl2Initialize
+*
+* DESCRIPTION:
+*       This routine initializes PIRL2 Resources.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirl2Initialize
+(
+    IN  GT_QD_DEV  			*dev
+);
+
+
+
+/*******************************************************************************
+* lport2port
+*
+* DESCRIPTION:
+*       This function converts logical port number to physical port number
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		port    - logical port number
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       physical port number
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_U8 lport2port
+(
+    IN GT_U16    portVec,
+	IN GT_LPORT	 port
+);
+
+/*******************************************************************************
+* port2lport
+*
+* DESCRIPTION:
+*       This function converts physical port number to logical port number
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		port    - logical port number
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       physical port number
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_LPORT port2lport
+(
+    IN GT_U16    portVec,
+	IN GT_U8	 hwPort
+);
+
+/*******************************************************************************
+* lportvec2portvec
+*
+* DESCRIPTION:
+*       This function converts logical port vector to physical port vector
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		lVec 	- logical port vector
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       physical port vector
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_U32 lportvec2portvec
+(
+    IN GT_U16    portVec,
+	IN GT_U32	 lVec
+);
+
+/*******************************************************************************
+* portvec2lportvec
+*
+* DESCRIPTION:
+*       This function converts physical port vector to logical port vector
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		pVec 	- physical port vector
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       logical port vector
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_U32 portvec2lportvec
+(
+    IN GT_U16    portVec,
+	IN GT_U32	 pVec
+);
+
+
+/*******************************************************************************
+* lport2phy
+*
+* DESCRIPTION:
+*       This function converts logical port number to physical phy number.
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		port    - logical port number
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       physical port number
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_U8 lport2phy
+(
+    IN GT_QD_DEV    *dev,
+	IN GT_LPORT	 port
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __msApiInternal_h */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/gtMiiSmiIf.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/gtMiiSmiIf.h
new file mode 100755
index 0000000..74fd0f8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/gtMiiSmiIf.h
@@ -0,0 +1,156 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtMiiSmiIf.h
+*
+* DESCRIPTION:
+*       Includes functions prototypes for initializing and accessing the
+*       MII / SMI interface.
+*       This is the only file to be included from upper layers.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 2 $
+*
+*******************************************************************************/
+
+#ifndef __gtMiiSmiIfh
+#define __gtMiiSmiIfh
+
+
+#include <msApi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+* miiSmiIfInit
+*
+* DESCRIPTION:
+*       This function initializes the MII / SMI interface.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       highSmiDevAddr - Indicates whether to use the high device register
+*                     addresses when accessing switch's registers (of all kinds)
+*                     i.e, the devices registers range is 0x10 to 0x1F, or to
+*                     use the low device register addresses (range 0x0 to 0xF).
+*                       GT_TRUE     - use high addresses (0x10 to 0x1F).
+*                       GT_FALSE    - use low addresses (0x0 to 0xF).
+*
+* RETURNS:
+*       DEVICE_ID       - on success
+*       0     - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U16 miiSmiIfInit
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   * highSmiDevAddr
+);
+
+/*******************************************************************************
+* miiSmiManualIfInit
+*
+* DESCRIPTION:
+*       This function returns Device ID from the given base address
+*
+* INPUTS:
+*       baseAddr - either 0x0 or 0x10. Indicates whether to use the low device 
+*					register address or high device register address.
+*					The device register range is from 0x0 to 0xF or from 0x10 
+*					to 0x1F for 5 port switchs and from 0x0 to 0x1B for 8 port 
+*					switchs.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       DEVICE_ID       - on success
+*       0    - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U16 miiSmiManualIfInit
+(
+	IN  GT_QD_DEV   *dev,
+	IN  GT_U32		baseAddr
+);
+
+/*******************************************************************************
+* miiSmiIfReadRegister
+*
+* DESCRIPTION:
+*       This function reads a register throw the SMI / MII interface, to be used
+*       by upper layers.
+*
+* INPUTS:
+*       phyAddr     - The PHY address to be read.
+*       regAddr     - The register address to read.
+*
+* OUTPUTS:
+*       data        - The register's data.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS miiSmiIfReadRegister
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     phyAddr,
+    IN  GT_U8     regAddr,
+    OUT GT_U16    *data
+);
+
+
+/*******************************************************************************
+* miiSmiIfWriteRegister
+*
+* DESCRIPTION:
+*       This function writes to a register throw the SMI / MII interface, to be
+*       used by upper layers.
+*
+* INPUTS:
+*       phyAddr     - The PHY address to be read.
+*       regAddr     - The register address to read.
+*       data        - The data to be written to the register.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS miiSmiIfWriteRegister
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     phyAddr,
+    IN  GT_U8     regAddr,
+    IN  GT_U16    data
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gtMiiSmiIfh */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/gtSem.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/gtSem.h
new file mode 100755
index 0000000..74a057c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/gtSem.h
@@ -0,0 +1,153 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtOs.h
+*
+* DESCRIPTION:
+*       Operating System wrapper
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+
+#ifndef __gtSemh
+#define __gtSemh
+
+#include <msApi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***** Defines  ********************************************************/
+
+#define OS_WAIT_FOREVER             0
+
+#define OS_MAX_TASKS                30
+#define OS_MAX_TASK_NAME_LENGTH     10
+
+#define OS_MAX_QUEUES               30
+#define OS_MAX_QUEUE_NAME_LENGTH    10
+
+#define OS_MAX_EVENTS               10
+
+#define OS_MAX_SEMAPHORES           50
+
+#define OS_EOF                      (-1)
+
+
+/*******************************************************************************
+* gtSemCreate
+*
+* DESCRIPTION:
+*       Create semaphore.
+*
+* INPUTS:
+*		state - beginning state of the semaphore, either SEM_EMPTY or SEM_FULL
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_SEM if success. Otherwise, NULL
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_SEM gtSemCreate
+(
+	IN GT_QD_DEV    *dev,
+	IN GT_SEM_BEGIN_STATE state
+);
+
+/*******************************************************************************
+* gtSemDelete
+*
+* DESCRIPTION:
+*       Delete semaphore.
+*
+* INPUTS:
+*       smid - semaphore Id
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtSemDelete
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_SEM       smid
+);
+
+/*******************************************************************************
+* gtSemTake
+*
+* DESCRIPTION:
+*       Wait for semaphore.
+*
+* INPUTS:
+*       smid    - semaphore Id
+*       timeOut - time out in miliseconds or 0 to wait forever
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       OS_TIMEOUT - on time out
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtSemTake
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_SEM       smid,
+    IN GT_U32       timeOut
+);
+
+/*******************************************************************************
+* gtSemGive
+*
+* DESCRIPTION:
+*       release the semaphore which was taken previously.
+*
+* INPUTS:
+*       smid    - semaphore Id
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtSemGive
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_SEM       smid
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __gtSemh */
+/* Do Not Add Anything Below This Line */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/platformDeps.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/platformDeps.h
new file mode 100755
index 0000000..0bba7be
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/h/platform/platformDeps.h
@@ -0,0 +1,31 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* platformDeps.h
+*
+* DESCRIPTION:
+*       platform dependent definitions
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __platformDepsh
+#define __platformDepsh
+
+#include <msApi.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GT_BOOL defaultMiiRead (unsigned int portNumber , unsigned int miiReg, unsigned int* value);
+GT_BOOL defaultMiiWrite (unsigned int portNumber , unsigned int miiReg, unsigned int value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif   /* platformDepsh */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApi.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApi.h
new file mode 100755
index 0000000..5ebeba1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApi.h
@@ -0,0 +1,22 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* msApi.h
+*
+* DESCRIPTION:
+*       API definitions for QuarterDeck Device
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __msApi_h
+#define __msApi_h
+
+#include <msApiDefs.h>
+#include <msApiInternal.h>
+#include <msApiPrototype.h>
+
+#endif /* __msApi_h */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiDefs.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiDefs.h
new file mode 100755
index 0000000..6e238e6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiDefs.h
@@ -0,0 +1,3903 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* msApiDefs.h
+*
+* DESCRIPTION:
+*       API definitions for QuarterDeck Device
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __msApiDefs_h
+#define __msApiDefs_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <msApiTypes.h>
+/* Debug function   */
+#ifdef DEBUG_QD
+#define DBG_INFO(x) gtDbgPrint x
+#else
+#define DBG_INFO(x);
+#endif /* DEBUG_QD */
+
+typedef GT_U32 GT_SEM;
+
+#define ETHERNET_HEADER_SIZE	GT_ETHERNET_HEADER_SIZE
+#define IS_MULTICAST_MAC		GT_IS_MULTICAST_MAC
+#define IS_BROADCAST_MAC		GT_IS_BROADCAST_MAC
+
+#define GT_INVALID_PHY			0xFF
+#define GT_INVALID_PORT			0xFF
+#define GT_INVALID_PORT_VEC		0xFFFFFFFF
+
+#define GT_UNUSED_PARAM(_a)		(_a)=(_a)
+
+/*
+ *   Logical Port value based on a Port
+ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |0|  reserved                                   |    port       |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *
+ *   The following macros should be used to extract specific info
+ *   from a Logical Port index
+ */
+typedef GT_U32 GT_LPORT;
+typedef GT_U32 GT_ETYPE;
+
+
+/* Define the different device type that may exist in system        */
+typedef enum
+{
+	GT_88E6021  = 0x021,
+	GT_88E6051  = 0x051,
+	GT_88E6052  = 0x052,
+	GT_88E6060  = 0x060,
+	GT_88E6063	= 0x153,
+	GT_FH_VPN	= 0xF53,
+	GT_FF_EG	= 0xF91,
+	GT_FF_HG	= 0xF93,
+	
+	GT_88E6083	= 0x083,
+
+	GT_88E6181	= 0x1A0,
+
+	GT_88E6153	= 0x1A1,
+	GT_88E6183	= 0x1A3,
+
+	GT_88E6093	= 0x093,
+	GT_88E6092	= 0x097,
+	GT_88E6045	= 0x094,
+	GT_88E6095	= 0x095,
+
+	GT_88E6152	= 0x1A4,
+	GT_88E6155	= 0x1A5,
+	GT_88E6182	= 0x1A6,
+	GT_88E6185	= 0x1A7,
+
+	GT_88E6121	= 0x104,
+	GT_88E6122	= 0x105,
+	GT_88E6131	= 0x106,
+	GT_88E6108	= 0x107,
+
+	GT_88E6031	= 0x031,
+	GT_88E6035	= 0x035,
+	GT_88E6055	= 0x055,
+	GT_88E6061	= 0x061,
+	GT_88E6065	= 0x065,
+
+	GT_88E6046	= 0x048,
+	GT_88E6047	= 0x049,
+	GT_88E6085	= 0x04A,
+	GT_88E6096	= 0x098,
+	GT_88E6097	= 0x099,
+
+	GT_88E6123	= 0x121,
+	GT_88E6140	= 0x141,
+	GT_88E6161	= 0x161,
+	GT_88E6165	= 0x165,
+
+	GT_88E6351	= 0x375,
+	GT_88E6175	= 0x175,
+	GT_88E6125	= 0x124,	/* was 88E6124 */
+	GT_88E6171	= 0x171,
+	GT_88E6321	= 0x324,	/* was 88E6325 */
+	GT_88E6350	= 0x371,	/* was 88E6371 */
+	GT_KW2_INT	= 0x044		/* Internal Swiych in KW2 */
+
+}GT_DEVICE;
+
+
+/* Definition for the revision number of the device        */
+typedef enum
+{
+	GT_REV_0 = 0,
+	GT_REV_1,
+	GT_REV_2,
+	GT_REV_3
+}GT_DEVICE_REV;
+
+
+/* ToDo: No Used */
+typedef enum
+{
+	INTR_MODE_DISABLE =0,
+	INTR_MODE_ENABLE
+}INTERRUPT_MODE;
+
+/* Definition for the Port Speed */
+typedef enum
+{
+	PORT_SPEED_10_MBPS = 0,
+	PORT_SPEED_100_MBPS = 1,
+	PORT_SPEED_200_MBPS = 2,	/* valid only if device support */
+	PORT_SPEED_1000_MBPS = 2 ,	/* valid only if device support */
+	PORT_SPEED_UNKNOWN = 3
+} GT_PORT_SPEED_MODE;
+
+/* Definition for the forced Port Speed */
+typedef enum
+{
+	PORT_FORCE_SPEED_10_MBPS = 0,
+	PORT_FORCE_SPEED_100_MBPS = 1,
+	PORT_FORCE_SPEED_200_MBPS = 2,	/* valid only if device support */
+	PORT_FORCE_SPEED_1000_MBPS = 2,	/* valid only if device support */
+	PORT_DO_NOT_FORCE_SPEED =3
+} GT_PORT_FORCED_SPEED_MODE;
+
+/* Definition for the forced Port Duplex mode */
+typedef enum
+{
+	PORT_DO_NOT_FORCE_DUPLEX,
+	PORT_FORCE_FULL_DUPLEX,
+	PORT_FORCE_HALF_DUPLEX
+} GT_PORT_FORCED_DUPLEX_MODE;
+
+/* Definition for the forced Port Link */
+typedef enum
+{
+	PORT_DO_NOT_FORCE_LINK,
+	PORT_FORCE_LINK_UP,
+	PORT_FORCE_LINK_DOWN
+} GT_PORT_FORCED_LINK_MODE;
+
+/* Definition for the forced flow control mode */
+typedef enum
+{
+	PORT_DO_NOT_FORCE_FC,
+	PORT_FORCE_FC_ENABLED,
+	PORT_FORCE_FC_DISABLED
+} GT_PORT_FORCED_FC_MODE;
+
+/* Definition for the PPU state */
+typedef enum
+{
+	PPU_STATE_DISABLED_AT_RESET,
+	PPU_STATE_ACTIVE,
+	PPU_STATE_DISABLED_AFTER_RESET,
+	PPU_STATE_POLLING
+} GT_PPU_STATE;
+
+
+/*
+ * Typedef: enum GT_PORT_CONFIG_MODE
+ *
+ * Description: Defines port's interface type configuration mode determined at 
+ *				reset. This definition may not represent the device under use.
+ *				Please refer to the device datasheet for detailed information.
+ *
+ */
+typedef enum
+{
+	PORTCFG_GMII_125MHZ = 0,		/* Px_GTXCLK = 125MHz, 1000BASE */
+	PORTCFG_FD_MII_0MHZ = 1,		/* Px_GTXCLK = 0 MHz, Power Save */
+	PORTCFG_FDHD_MII_25MHZ = 2,		/* Px_GTXCLK = 25MHz, 100BASE */ 
+	PORTCFG_FDHD_MII_2_5MHZ = 3,	/* Px_GTXCLK = 2.5MHz, 10BASE */
+	PORTCFG_FD_SERDES = 4,			/* Default value */
+	PORTCFG_FD_1000BASE_X = 5,		
+	PORTCFG_MGMII = 6,				/* duplex, speed determined by the PPU */
+	PORTCFG_DISABLED = 7			
+} GT_PORT_CONFIG_MODE;
+
+
+typedef enum
+{
+	GT_SA_FILTERING_DISABLE = 0,
+	GT_SA_DROP_ON_LOCK,
+	GT_SA_DROP_ON_UNLOCK,
+	GT_SA_DROP_TO_CPU
+} GT_SA_FILTERING;
+
+
+/* Definition for the Ingree/Egress Frame Mode */
+typedef enum
+{
+	GT_FRAME_MODE_NORMAL = 0,	/* Normal Network */
+	GT_FRAME_MODE_DSA,			/* Distributed Switch Architecture */
+	GT_FRAME_MODE_PROVIDER,		/* Provider */
+	GT_FRAME_MODE_ETHER_TYPE_DSA	/* Ether Type DSA */
+} GT_FRAME_MODE;
+
+/*
+ * Typedef: enum GT_JUMBO_MODE
+ *
+ * Description: Defines Jumbo Frame Size allowed to be tx and rx
+ *
+ * Fields:
+ *      GT_JUMBO_MODE_1522 - Rx and Tx frames with max byte of 1522.
+ *      GT_JUMBO_MODE_2048 - Rx and Tx frames with max byte of 2048.
+ *      GT_JUMBO_MODE_10240 - Rx and Tx frames with max byte of 10240.
+ *				 
+ */
+typedef enum
+{
+	GT_JUMBO_MODE_1522 = 0,
+	GT_JUMBO_MODE_2048,
+	GT_JUMBO_MODE_10240
+} GT_JUMBO_MODE;
+
+
+/*
+ * Typedef: enum GT_PRI_OVERRIDE
+ *
+ * Description: Defines the priority override
+ *
+ * Fields:
+ *      PRI_OVERRIDE_NONE - Normal frame priority processing occurs.
+ *		PRI_OVERRIDE_FRAME_QUEUE -
+ *			Both frame and queue overrides take place on the frame.
+ *      PRI_OVERRIDE_FRAME - 
+ *			Overwite the frame's FPri (frame priority).
+ *			If the frame egresses tagged, the priority in the frame will be
+ *			the overwritten priority value.
+ *		PRI_OVERRIDE_QUEUE -
+ *			Overwite the frame's QPri (queue priority).
+ *			QPri is used internally to map the frame to one of the egress
+ *			queues inside the switch.
+ *
+ */
+typedef enum
+{
+	PRI_OVERRIDE_NONE = 0,
+	PRI_OVERRIDE_FRAME_QUEUE,
+	PRI_OVERRIDE_FRAME,
+	PRI_OVERRIDE_QUEUE
+} GT_PRI_OVERRIDE;
+
+
+/*
+ * Typedef: enum GT_FRAME_POLICY
+ *
+ * Description: Defines the policy of the frame
+ *
+ * Fields:
+ *      FRAME_POLICY_NONE - Normal frame switching
+ *      FRAME_POLICY_MIRROR - Mirror(copy) frame to the MirrorDest port
+ *      FRAME_POLICY_TRAP - Trap(re-direct) frame to the CPUDest port
+ *      FRAME_POLICY_DISCARD - Discard(filter) the frame
+ *
+ */
+typedef enum
+{
+	FRAME_POLICY_NONE = 0,
+	FRAME_POLICY_MIRROR,
+	FRAME_POLICY_TRAP,
+	FRAME_POLICY_DISCARD
+} GT_FRAME_POLICY;
+
+
+/*
+ * Typedef: enum GT_POLICY_TYPE
+ *
+ * Description: Defines the policy type
+ *
+ * Fields:
+ *      POLICY_TYPE_DA 	- Policy based on Destination Address
+ *      POLICY_TYPE_SA 	- Policy based on Source Address
+ *      POLICY_TYPE_VTU 	- Policy based on VID
+ *		POLICY_TYPE_ETYPE	- based on Ether Type of a frame
+ *		POLICY_TYPE_PPPoE	- Policy for the frame with Ether Type of 0x8863
+ *		POLICY_TYPE_VBAS	- Policy for the frame with Ether Type of 0x8200
+ *		POLICY_TYPE_OPT82	- Policy for the frame with DHCP Option 82
+ *		POLICY_TYPE_UDP	- Policy for the frame with Broadcast IPv4 UDP or
+ *						Multicast IPv6 UDP
+ */
+typedef enum
+{
+	POLICY_TYPE_DA,
+	POLICY_TYPE_SA,
+	POLICY_TYPE_VTU,
+	POLICY_TYPE_ETYPE,
+	POLICY_TYPE_PPPoE,
+	POLICY_TYPE_VBAS,
+	POLICY_TYPE_OPT82,
+	POLICY_TYPE_UDP
+} GT_POLICY_TYPE;
+
+
+/*
+ * Typedef: enum GT_PRI_OVERRIDE_FTYPE
+ *
+ * Description: Definition of the frame type for priority override
+ *
+ * Fields:
+ *		FTYPE_DSA_TO_CPU_BPDU -
+ *			Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+ *			Not used on non-DSA Control frames.
+ *		FTYPE_DSA_TO_CPU_F2R -
+ *			Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+ *			Reply). Not used on non-DSA Control frames.
+ *		FTYPE_DSA_TO_CPU_IGMP -
+ *			Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+ *			and on non-DSA Control frames that are IGMP or MLD trapped
+ *		FTYPE_DSA_TO_CPU_TRAP -
+ *			Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+ *			on non-DSA Control frames that are Policy Trapped
+ *		FTYPE_DSA_TO_CPU_ARP -
+ *			Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+ *			on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+ *		FTYPE_DSA_TO_CPU_MIRROR -
+ *			Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+ *			on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+ *		FTYPE_DSA_TO_CPU_RESERVED -
+ *			Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+ *			used on non-DSA Control frames.
+ *		FTYPE_DSA_TO_CPU_UCAST_MGMT -
+ *			Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+ *			MGMT). Not used on non-DSA Control frames.
+ *		FTYPE_DSA_FROM_CPU -
+ *			Used on DSA From_CPU frames. Not used on non-DSA Control frame
+ *		FTYPE_DSA_CROSS_CHIP_FC -
+ *			Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+ *			Control). Not used on non-DSA Control frames.
+ *		FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+ *			Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+ *			Not used on non-DSA Control frames.
+ *		FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+ *			Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+ *			Not used on non-DSA Control frames.
+ *		FTYPE_PORT_ETYPE_MATCH -
+ *			Used on normal network ports (see gprtSetFrameMode API)
+ *			on frames whose Ethertype matches the port's PortEType register.
+ *			Not used on non-DSA Control frames.
+ *		FTYPE_BCAST_NON_DSA_CONTROL -
+ *			Used on Non-DSA Control frames that contain a Broadcast
+ *			destination address. Not used on DSA Control frames.
+ *		FTYPE_PPPoE_NON_DSA_CONTROL -
+ *			Used on Non-DSA Control frames that contain an Ether Type 0x8863
+ *			(i.e., PPPoE frames). Not used on DSA Control frames.
+ *		FTYPE_IP_NON_DSA_CONTROL -
+ *			Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+ *			Type. Not used on DSA Control frames.
+ */
+typedef enum
+{
+	FTYPE_DSA_TO_CPU_BPDU = 0,
+	FTYPE_DSA_TO_CPU_F2R,
+	FTYPE_DSA_TO_CPU_IGMP,
+	FTYPE_DSA_TO_CPU_TRAP,
+	FTYPE_DSA_TO_CPU_ARP,
+	FTYPE_DSA_TO_CPU_MIRROR,
+	FTYPE_DSA_TO_CPU_RESERVED,
+	FTYPE_DSA_TO_CPU_UCAST_MGMT,
+	FTYPE_DSA_FROM_CPU,
+	FTYPE_DSA_CROSS_CHIP_FC,
+	FTYPE_DSA_CROSS_CHIP_EGRESS_MON,
+	FTYPE_DSA_CROSS_CHIP_INGRESS_MON,
+	FTYPE_PORT_ETYPE_MATCH,
+	FTYPE_BCAST_NON_DSA_CONTROL,
+	FTYPE_PPPoE_NON_DSA_CONTROL,
+	FTYPE_IP_NON_DSA_CONTROL
+} GT_PRI_OVERRIDE_FTYPE;
+
+
+/*
+ * Typedef: struct GT_QPRI_TBL_ENTRY
+ *
+ * Description: This structure is used for the entry of Queue Priority Override
+ *				Table.
+ *
+ * Fields:
+ *		qPriEn    - GT_TRUE to enable Queue Priority, GT_FALSE otherwise
+ *		qPriority - priority to be overridden ( 0 ~ 3 ) only if qPriEn is GT_TRUE
+ *					When qPriEn is GT_FALSE, qPriority should be ignored.
+ *
+ * Notes: If device does not support qPriAvbEn, qPriAvbEn and qAvbPriority fields
+ *		will be ignored.
+ */
+typedef struct
+{
+	GT_BOOL		qPriEn;
+	GT_U32		qPriority;
+}GT_QPRI_TBL_ENTRY;
+
+
+/*
+ * Typedef: struct GT_FPRI_TBL_ENTRY
+ *
+ * Description: This structure is used for the entry of Frame Priority Override
+ *				Table.
+ *
+ * Fields:
+ *		fPriEn    - GT_TRUE to enable Frame Priority, GT_FALSE otherwise
+ *		fPriority - priority to be overridden ( 0 ~ 7 ) only if fPriEn is GT_TRUE
+ *					When fPriEn is GT_FALSE, fPriority should be ignored.
+ */
+typedef struct
+{
+	GT_BOOL		fPriEn;
+	GT_U32		fPriority;
+}GT_FPRI_TBL_ENTRY;
+
+
+/* Maximam number of ports a switch may have. */
+#define MAX_SWITCH_PORTS    11
+#define VERSION_MAX_LEN 	30
+#define MAX_QOS_WEIGHTS		128
+
+/*
+ * Typedef: struct GT_QoS_WEIGHT
+ *
+ * Description: This structure is used for Programmable Round Robin Weights.
+ *
+ * Fields:
+ *      len    - length of the valid queue data
+ *		queue  - upto 128 queue data
+ */
+typedef struct
+{
+	GT_U32		len;
+	GT_U8		queue[MAX_QOS_WEIGHTS];
+}GT_QoS_WEIGHT;
+
+
+
+/*
+ * Typedef: struct GT_VERSION
+ *
+ * Description: This struct holds the package version.
+ *
+ * Fields:
+ *      version - string array holding the version.
+ *
+ */
+typedef struct
+{
+	GT_U8   version[VERSION_MAX_LEN];
+}GT_VERSION;
+
+
+/*
+ * typedef: struct GT_RMU
+ *
+ * Description: This struct holds the Remote Management Unit mode.
+ *
+ * Fields:
+ *		rmuEn	- enable or disable RMU
+ *		port	- logical port where RMU is enabled
+ */
+typedef struct
+{
+	GT_BOOL		rmuEn;
+	GT_LPORT	port;
+} GT_RMU;
+
+
+
+/*
+ * Typedef:
+ *
+ * Description: Defines the different sizes of the Mac address table.
+ *
+ * Fields:
+ *      ATU_SIZE_256    -   256 entries Mac address table.
+ *      ATU_SIZE_512    -   512 entries Mac address table.
+ *      ATU_SIZE_1024   -   1024 entries Mac address table.
+ *      ATU_SIZE_2048   -   2048 entries Mac address table.
+ *      ATU_SIZE_4096   -   4096 entries Mac address table.
+ *      ATU_SIZE_8192   -   8192 entries Mac address table.
+ *
+ */
+typedef enum
+{
+	ATU_SIZE_256,
+	ATU_SIZE_512,
+	ATU_SIZE_1024,
+	ATU_SIZE_2048,
+	ATU_SIZE_4096,
+	ATU_SIZE_8192
+}ATU_SIZE;
+
+
+/*
+ * typedef: enum GT_PORT_STP_STATE
+ *
+ * Description: Enumeration of the port spanning tree state.
+ *
+ * Enumerations:
+ *   GT_PORT_DISABLE    - port is disabled.
+ *   GT_PORT_BLOCKING   - port is in blocking/listening state.
+ *   GT_PORT_LEARNING   - port is in learning state.
+ *   GT_PORT_FORWARDING - port is in forwarding state.
+ */
+typedef enum
+{
+	GT_PORT_DISABLE = 0,
+	GT_PORT_BLOCKING,
+	GT_PORT_LEARNING,
+	GT_PORT_FORWARDING
+} GT_PORT_STP_STATE;
+
+
+/*
+ * typedef: enum GT_EGRESS_MODE
+ *
+ * Description: Enumeration of the port egress mode.
+ *
+ * Enumerations:
+ *   GT_UNMODIFY_EGRESS - frames are transmited unmodified.
+ *   GT_TAGGED_EGRESS   - all frames are transmited tagged.
+ *   GT_UNTAGGED_EGRESS - all frames are transmited untagged.
+ *   GT_ADD_TAG         - always add a tag. (or double tag)
+ */
+typedef enum
+{
+	GT_UNMODIFY_EGRESS = 0,
+	GT_UNTAGGED_EGRESS,
+	GT_TAGGED_EGRESS,
+	GT_ADD_TAG
+} GT_EGRESS_MODE;
+
+/*  typedef: enum GT_DOT1Q_MODE */
+
+typedef enum
+{
+	GT_DISABLE = 0,
+	GT_FALLBACK,
+	GT_CHECK,
+	GT_SECURE
+} GT_DOT1Q_MODE;
+
+
+/* typedef: enum GT_SW_MODE */
+
+typedef enum
+{
+	GT_CPU_ATTATCHED = 0, /* ports come up disabled */
+	GT_BACKOFF,           /* EEPROM attac mode with old half duplex backoff mode */
+	GT_STAND_ALONE,       /* ports come up enabled, ignore EEPROM */
+	GT_EEPROM_ATTATCHED   /* EEPROM defined prot states */
+} GT_SW_MODE;
+
+
+/*
+ * Typedef: enum GT_ATU_OPERARION
+ *
+ * Description: Defines the different ATU and VTU operations
+ *
+ * Fields:
+ *      FLUSH_ALL           - Flush all entries.
+ *      FLUSH_UNLOCKED      - Flush all unlocked entries in ATU.
+ *      LOAD_PURGE_ENTRY    - Load / Purge entry.
+ *      GET_NEXT_ENTRY      - Get next ATU or VTU  entry.
+ *      FLUSH_ALL_IN_DB     - Flush all entries in a particular DBNum.
+ *      FLUSH_UNLOCKED_IN_DB - Flush all unlocked entries in a particular DBNum.
+ *      SERVICE_VIOLATONS   - sevice violations of VTU
+ *
+ */
+typedef enum
+{
+	FLUSH_ALL = 1,		/* for both atu and vtu */
+	FLUSH_UNLOCKED,		/* for atu only */
+	LOAD_PURGE_ENTRY,	/* for both atu and vtu */
+	GET_NEXT_ENTRY,		/* for both atu and vtu */
+	FLUSH_ALL_IN_DB,	/* for atu only */
+	FLUSH_UNLOCKED_IN_DB,	/* for atu only */
+	SERVICE_VIOLATIONS 	/* for vtu only */
+} GT_ATU_OPERATION, GT_VTU_OPERATION;
+
+
+/*
+ * typedef: enum GT_FLUSH_CMD
+ *
+ * Description: Enumeration of the address translation unit flush operation.
+ *
+ * Enumerations:
+ *   GT_FLUSH_ALL       - flush all entries.
+ *   GT_FLUSH_ALL_UNBLK - flush all unblocked (or unlocked).
+ *   GT_FLUSH_ALL_UNLOCKED - flush all unblocked (or unlocked).
+ */
+typedef enum
+{
+    GT_FLUSH_ALL       = 1,
+    GT_FLUSH_ALL_UNBLK = 2,
+    GT_FLUSH_ALL_UNLOCKED = 2
+}GT_FLUSH_CMD;
+
+/*
+ * typedef: enum GT_MOVE_CMD
+ *
+ * Description: Enumeration of the address translation unit move or remove operation.
+ *	 When destination port is set to 0xF, Remove operation occurs.
+ *
+ * Enumerations:
+ *   GT_MOVE_ALL       - move all entries.
+ *   GT_MOVE_ALL_UNBLK - move all unblocked (or unlocked).
+ *   GT_MOVE_ALL_UNLOCKED - move all unblocked (or unlocked).
+ */
+typedef enum
+{
+	GT_MOVE_ALL       = 1,
+	GT_MOVE_ALL_UNBLK = 2,
+	GT_MOVE_ALL_UNLOCKED = 2
+}GT_MOVE_CMD;
+
+
+/*
+ * typedef: enum GT_ATU_UC_STATE
+ *
+ * Description:
+ *      Enumeration of the address translation unit entry state of unicast
+ *      entris.
+ *
+ * Enumerations:
+ *		GT_UC_INVALID   - invalid entry.
+ *		GT_UC_DYNAMIC   - unicast dynamic entry.
+ *		GT_UC_NO_PRI_TO_CPU_STATIC_NRL 
+ *				- static unicast entry that will be forwarded to CPU without 
+ *					forcing priority and without rate limiting.
+ *		GT_UC_TO_CPU_STATIC_NRL 
+ *				- static unicast entry that will be forwarded to CPU without
+ *					rate limiting.
+ *		GT_UC_NO_PRI_STATIC_NRL 
+ *				- static unicast entry without forcing priority and without.
+ *					rate limiting.
+ *		GT_UC_NO_PRI_STATIC_AVB_ENTRY 
+ *				- static unicast AVB entry without forcing priority if MacAvb is enabled.
+ *		GT_UC_STATIC_NRL    - static unicast entry without rate limiting.
+ *		GT_UC_STATIC_AVB_ENTRY - static unicast AVB entry if MacAvb is enabled .
+ *		GT_UC_NO_PRI_TO_CPU_STATIC
+ *				- static unicast entry that will be forwarded to CPU without 
+ *					forcing priority.
+ *		GT_UC_TO_CPU_STATIC - static unicast entry that will be forwarded to CPU.
+ *		GT_UC_NO_PRI_STATIC - static unicast entry without forcing priority.
+ *		GT_UC_STATIC    - static unicast entry.
+ *
+ * Note: Please refer to the device datasheet for detailed unicast entry states
+ *		that are supported by the device.
+ */
+typedef enum
+{
+	GT_UC_INVALID      = 0,
+	GT_UC_DYNAMIC      = 0x1,
+
+	GT_UC_NO_PRI_TO_CPU_STATIC_NRL	= 0x8,
+	GT_UC_TO_CPU_STATIC_NRL			= 0x9,
+	GT_UC_NO_PRI_STATIC_NRL			= 0xA,
+	GT_UC_NO_PRI_STATIC_AVB_ENTRY	= 0xA,
+	GT_UC_STATIC_NRL 				= 0xB,
+	GT_UC_STATIC_AVB_ENTRY			= 0xB,
+
+	GT_UC_NO_PRI_TO_CPU_STATIC	= 0xC,
+	GT_UC_TO_CPU_STATIC 		= 0xD,
+	GT_UC_NO_PRI_STATIC 		= 0xE,
+	GT_UC_STATIC  				= 0xF
+} GT_ATU_UC_STATE;
+
+
+/*
+ * typedef: enum GT_ATU_MC_STATE
+ *
+ * Description:
+ *      Enumeration of the address translation unit entry state of multicast
+ *      entris.
+ *
+ * Enumerations:
+ *      GT_MC_INVALID         - invalid entry.
+ *      GT_MC_MGM_STATIC      - static multicast management entries.
+ *      GT_MC_STATIC          - static multicast regular entris.
+ *      GT_MC_STATIC_AVB_ENTRY- static AVB entry if MacAvb is enalbed.
+ *      GT_MC_PRIO_MGM_STATIC - static multicast management entries with
+ *                              priority.
+ *      GT_MC_PRIO_STATIC     - static multicast regular entris with priority.
+ *      GT_MC_PRIO_STATIC_AVB_ENTRY      - static multicast AVB Entry with priority if MacAvb is enabled
+ *      GT_MC_PRIO_STATIC_UNLIMITED_RATE - static multicast regular entris with priority
+ *											and without rate limiting.
+ *      GT_MC_MGM_STATIC_UNLIMITED_RATE	 - static multicast management entries without
+ *											rate limiting.
+ *      GT_MC_STATIC_UNLIMITED_RATE      - static multicast regular entris without
+ *											rate limiting.
+ *      GT_MC_PRIO_MGM_STATIC_UNLIMITED_RATE - static multicast management entries with
+ *                              priority and without rate limiting.
+ *
+ * Note: Please refer to the device datasheet for detailed multicast entry states
+ *		that are supported by the device.
+ */
+typedef enum
+{
+	GT_MC_INVALID         = 0,
+	GT_MC_MGM_STATIC_UNLIMITED_RATE = 0x4,
+	GT_MC_STATIC_UNLIMITED_RATE	= 0x5,
+	GT_MC_STATIC_AVB_ENTRY	= 0x5,
+	GT_MC_MGM_STATIC      = 0x6,
+	GT_MC_STATIC          = 0x7,
+	GT_MC_PRIO_MGM_STATIC_UNLIMITED_RATE = 0xC,
+	GT_MC_PRIO_STATIC_UNLIMITED_RATE	= 0xD,
+	GT_MC_PRIO_STATIC_AVB_ENTRY	= 0xD,
+	GT_MC_PRIO_MGM_STATIC = 0xE,
+	GT_MC_PRIO_STATIC     = 0xF
+} GT_ATU_MC_STATE;
+
+
+/*
+ *  typedef: struct GT_ATU_EXT_PRI
+ *
+ *  Description: 
+ *		Extanded priority information for the address tarnslaton unit entry.
+ *
+ *		macFPri data is used to override the frame priority on any frame associated
+ *		with this MAC, if the useMacFPri is GT_TRUE and the port's SA and/or 
+ *		DA FPriOverride are enabled. SA Frame Priority Overrides can only occur on 
+ *		MAC addresses that are Static or where the Port is Locked, and where the port 
+ *		is mapped source port for the MAC address.
+ *
+ *		macQPri data is used to override the queue priority on any frame associated
+ *		with this MAC, if the EntryState indicates Queue Priority Override and the 
+ *		port's SA and/or DA QPriOverride are enabled. 
+ *
+ *  Fields:
+ *      useMacFPri - Use MAC frame priority override. When this is GT_TRUE,
+ *					 MacFPri data can be used to override the frame priority on
+ *					 any frame associated with this MAC.
+ *      macFPri    - MAC frame priority data (0 ~ 7).
+ *      macQPri    - MAC queue priority data (0 ~ 3).
+ *
+ *  Comment:
+ *      Please refer to the device datasheet to find out if this feature is supported.
+ *		When this structure is implemented, the followings are the devices supporting 
+ *		this feature:
+ *			88E6065, 88E6035, and 88E6055 support all extanded priority data.
+ *			88E6061 and 88E6031 support only macQPri data
+ */
+typedef struct
+{
+	GT_BOOL			useMacFPri;
+	GT_U8 			macFPri;
+	GT_U8 			macQPri;
+} GT_ATU_EXT_PRI;
+
+
+/*
+ *  typedef: struct GT_ATU_ENTRY
+ *
+ *  Description: address tarnslaton unit Entry
+ *
+ *  Fields:
+ *      macAddr    - mac address
+ *      trunkMember- GT_TRUE if entry belongs to a Trunk. This field will be
+ *					 ignored if device does not support Trunk.
+ *      portVec    - port Vector. 
+ *					 If trunkMember field is GT_TRUE, this value represents trunk ID.
+ *      prio       - entry priority.
+ *      entryState - the entry state.
+ *		DBNum	   - ATU MAC Address Database number. If multiple address 
+ *					 databases are not being used, DBNum should be zero.
+ *					 If multiple address databases are being used, this value
+ *					 should be set to the desired address database number.
+ *		exPrio     - extanded priority information. If device support extanded 
+ *					 priority, prio field should be ignored.
+ *
+ *  Comment:
+ *      The entryState union Type is determine according to the Mac Type.
+ */
+typedef struct
+{
+	GT_ETHERADDR 	macAddr;
+	GT_BOOL			trunkMember;
+	GT_U32			portVec;
+	GT_U8			prio;
+	GT_U8			reserved;
+	GT_U16			DBNum;
+	union
+	{
+		GT_ATU_UC_STATE ucEntryState;
+		GT_ATU_MC_STATE mcEntryState;
+	} entryState;
+	GT_ATU_EXT_PRI	exPrio;
+} GT_ATU_ENTRY;
+
+
+/*
+ *  typedef: struct GT_VTU_DATA
+ *
+ *  Description: VLAN  tarnslaton unit Data Register
+ *
+ *  Fields:
+ *      memberTagP - Membership and Egress Tagging
+ *                   memberTagP[0] is for Port 0, MemberTagP[1] is for port 1, and so on 
+ *
+ *  Comment:
+ * 	MAX_SWITCH_PORTS is 10 for Octane.
+ * 	In the case of FullSail, there are 3 ports. So, the rest 7 is ignored in memeberTagP
+ */
+typedef struct
+{
+	GT_U8     memberTagP[MAX_SWITCH_PORTS];
+	GT_U8     portStateP[MAX_SWITCH_PORTS];
+} GT_VTU_DATA;
+
+/*
+ *  definition for MEMBER_TAG
+ */
+#define MEMBER_EGRESS_UNMODIFIED	0
+#define NOT_A_MEMBER				1
+#define MEMBER_EGRESS_UNTAGGED		2
+#define MEMBER_EGRESS_TAGGED		3
+
+/*
+ *  typedef: struct GT_VTU_EXT_INFO
+ *
+ *  Description: 
+ *		Extanded VTU Entry information for Priority Override and Non Rate Limit.
+ *		Frame Priority is used to as the tag's PRI bits if the frame egresses
+ *		the switch tagged. The egresss queue the frame is switch into is not
+ *		modified by the Frame Priority Override.
+ *		Queue Priority is used to determine the egress queue the frame is
+ *		switched into. If the frame egresses tagged, the priority in the frame 
+ *		will not be modified by a Queue Priority Override.
+ *		NonRateLimit for VID is used to indicate any frames associated with this 
+ *		VID are to bypass ingress and egress rate limiting, if the ingress 
+ *		port's VID NRateLimit is also enabled.
+ *
+ *  Fields:
+ *      useVIDFPri - Use VID frame priority override. When this is GT_TRUE and 
+ *					 VIDFPriOverride of the ingress port of the frame is enabled,
+ *					 vidFPri data is used to override the frame priority on
+ *					 any frame associated with this VID.
+ *      vidFPri    - VID frame priority data (0 ~ 7).
+ *      useVIDQPri - Use VID queue priority override. When this is GT_TRUE and
+ *					 VIDQPriOverride of the ingress port of the frame is enabled,
+ *					 vidQPri data can be used to override the queue priority on
+ *					 any frame associated with this VID.
+ *      vidQPri    - VID queue priority data (0 ~ 3).
+ *      vidNRateLimit - bypass rate ingress and egress limiting
+ *
+ *  Comment:
+ *      Please refer to the device datasheet to find out if this feature is supported.
+ *		When this structure is implemented, the followings are the devices supporting 
+ *		this feature:
+ *			88E6065, 88E6035, and 88E6055 support all data.
+ *			88E6061 and 88E6031 support only vidNRateLimit.
+ */
+typedef struct
+{
+	GT_BOOL			useVIDFPri;
+	GT_U8 			vidFPri;
+	GT_BOOL			useVIDQPri;
+	GT_U8 			vidQPri;
+	GT_BOOL			vidNRateLimit;
+} GT_VTU_EXT_INFO;
+
+ 
+/*
+ *  typedef: struct GT_VTU_ENTRY
+ *
+ *  Description: VLAN tarnslaton unit Entry
+ *		Each field in the structure is device specific, i.e., some fields may not
+ *		be supported by the used switch device. In such case, those fields are
+ *		ignored by the DSDT driver. Please refer to the datasheet for the list of
+ *		supported fields.
+ *
+ *  Fields:
+ *      DBNum      - database number or FID (forwarding information database)
+ *      vid        - VLAN ID 
+ *      vtuData    - VTU data
+ *		vidPriOverride - override the priority on any frame associated with this VID
+ *		vidPriority - VID Priority bits (0 ~ 7)
+ *		sid	       - 802.1s Port State Database ID
+ *		vidPolicy  - indicate that the frame with this VID uses VID Policy
+ *		             (see gprtSetPolicy API).
+ *		vidExInfo  - extanded information for VTU entry. If the device supports extanded 
+ *					 information, vidPriorityOverride and vidPriority values are 
+ *					 ignored.
+ */
+typedef struct
+{
+	GT_U16        DBNum;
+	GT_U16        vid;
+	GT_VTU_DATA   vtuData;
+	GT_BOOL		  vidPriOverride;
+	GT_U8		  vidPriority;
+	GT_U8		  sid;
+	GT_BOOL		  vidPolicy;
+	GT_VTU_EXT_INFO	vidExInfo;
+} GT_VTU_ENTRY;
+
+
+/*
+ * Typedef: enum GT_STU_OPERARION
+ *
+ * Description: Defines the STU operations
+ *
+ * Fields:
+ *      LOAD_PURGE_STU_ENTRY    - Load / Purge entry.
+ *      GET_NEXT_STU_ENTRY      - Get next STU  entry.
+ *
+ */
+typedef enum
+{
+	LOAD_PURGE_STU_ENTRY = 5,
+	GET_NEXT_STU_ENTRY =6 
+} GT_STU_OPERATION;
+
+
+/*
+ *  typedef: struct GT_STU_ENTRY
+ *
+ *  Description: 802.1s Port State Information Database (STU) Entry
+ *
+ *  Fields:
+ *      sid       - STU ID 
+ *		portState - Per VLAN Port States for each port.
+ */
+typedef struct
+{
+	GT_U16				sid;
+	GT_PORT_STP_STATE	portState[MAX_SWITCH_PORTS];
+} GT_STU_ENTRY;
+
+
+/*
+ *  typedef: struct GT_VTU_INT_STATUS
+ *
+ *  Description: VLAN tarnslaton unit interrupt status
+ *
+ *  Fields:
+ *      intCause  - VTU Interrupt Cause
+ *					GT_VTU_FULL_VIOLATION,GT_MEMEBER_VIOLATION,or
+ *					GT_MISS_VIOLATION
+ *      SPID      - source port number
+ * 					if intCause is GT_VTU_FULL_VIOLATION, it means nothing
+ *      vid       - VLAN ID 
+ * 					if intCause is GT_VTU_FULL_VIOLATION, it means nothing
+ */
+typedef struct
+{
+	GT_U16   vtuIntCause;
+	GT_U8    spid;
+	GT_U16   vid;
+} GT_VTU_INT_STATUS;
+
+/*
+ *  typedef: struct GT_ATU_INT_STATUS
+ *
+ *  Description: VLAN tarnslaton unit interrupt status
+ *
+ *  Fields:
+ *      intCause  - ATU Interrupt Cause
+ *					GT_FULL_VIOLATION,GT_MEMEBER_VIOLATION,
+ *					GT_MISS_VIOLATION, GT_AGE_VIOLATION, or 
+ *					GT_AGE_OUT_VIOLATION
+ *      SPID      - source port number
+ * 					if intCause is GT_FULL_VIOLATION, it means nothing
+ *      DBNum     - DB Num (or FID)
+ * 					if intCause is GT_FULL_VIOLATION, it means nothing
+ *		macAddr	  - MAC Address
+ */
+typedef struct
+{
+	GT_U16   atuIntCause;
+	GT_U8    spid;
+	GT_U8    dbNum;
+	GT_ETHERADDR  macAddr;
+} GT_ATU_INT_STATUS;
+
+/*
+* Definition for VTU interrupt
+*/
+#define GT_MEMBER_VIOLATION		0x4
+#define GT_MISS_VIOLATION		0x2
+#define GT_VTU_FULL_VIOLATION	0x1
+/*
+* Definitions for ATU interrupt in Gigabit switch are the same as 
+* the ones for VTU interrupt. Here we just redefine the FULL_VIOLATION for
+* both VTU and ATU.
+*/
+#define GT_FULL_VIOLATION		0x1
+
+#define GT_AGE_VIOLATION		0x8
+#define GT_AGE_OUT_VIOLATION	0x10
+
+
+/*
+ * Typedef: enum GT_PVT_OPERATION
+ *
+ * Description: Defines the PVT (Cross Chip Port VLAN Table) Operation type
+ *
+ * Fields:
+ *      PVT_INITIALIZE - Initialize all resources to the inital state
+ *      PVT_WRITE      - Write to the selected PVT entry
+ *      PVT_READ       - Read from the selected PVT entry
+ */
+typedef enum
+{
+	PVT_INITIALIZE 	= 0x1,
+	PVT_WRITE		= 0x3,
+	PVT_READ		= 0x4
+} GT_PVT_OPERATION;
+
+
+/*
+ *  typedef: struct GT_PVT_OP_DATA
+ *
+ *  Description: data required by PVT (Cross Chip Port VLAN Table) Operation
+ *
+ *  Fields:
+ *      pvtAddr - pointer to the desired entry of PVT
+ *      pvtData - Cross Chip Port VLAN data for the entry pointed by pvtAddr
+ */
+typedef struct
+{
+	GT_U32	pvtAddr;
+	GT_U32	pvtData;
+} GT_PVT_OP_DATA;
+
+
+/*
+ *  typedef: enum GT_PIRL_FC_DEASSERT
+ *
+ *  Description: Enumeration of the port flow control de-assertion mode on PIRL.
+ *
+ *  Enumerations:
+ *      GT_PIRL_FC_DEASSERT_EMPTY -
+ *				De-assert when the ingress rate resource has become empty
+ *		GT_PIRL_FC_DEASSERT_CBS_LIMIT -
+ *				De-assert when the ingress rate resource has enough room as
+ *				specified by the CBSLimit.
+ */
+typedef enum
+{
+	GT_PIRL_FC_DEASSERT_EMPTY = 0,
+	GT_PIRL_FC_DEASSERT_CBS_LIMIT
+} GT_PIRL_FC_DEASSERT;
+
+
+/*
+ *  typedef: enum GT_PIRL_ELIMIT_MODE
+ *
+ *  Description: Enumeration of the port egress rate limit counting mode.
+ *
+ *  Enumerations:
+ *      GT_PIRL_ELIMIT_FRAME -
+ *				Count the number of frames
+ *      GT_PIRL_ELIMIT_LAYER1 -
+ *				Count all Layer 1 bytes: 
+ *				Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
+ *      GT_PIRL_ELIMIT_LAYER2 -
+ *				Count all Layer 2 bytes: Frame's DA to CRC
+ *      GT_PIRL_ELIMIT_LAYER3 -
+ *				Count all Layer 3 bytes: 
+ *				Frame's DA to CRC - 18 - 4 (if frame is tagged)
+ */
+typedef enum
+{
+	GT_PIRL_ELIMIT_FRAME = 0,
+	GT_PIRL_ELIMIT_LAYER1,
+	GT_PIRL_ELIMIT_LAYER2,
+	GT_PIRL_ELIMIT_LAYER3
+} GT_PIRL_ELIMIT_MODE;
+
+
+/* typedef: enum GT_RATE_LIMIT_MODE
+ * The ingress limit mode in the rate control register (0xA)
+ */
+
+typedef enum
+{
+	GT_LIMT_ALL = 0, 		/* limit and count all frames */
+	GT_LIMIT_FLOOD,      	/* limit and count Broadcast, Multicast and flooded unicast frames */
+	GT_LIMIT_BRDCST_MLTCST,	/* limit and count Broadcast and Multicast frames */
+	GT_LIMIT_BRDCST   		/* limit and count Broadcast frames */
+} GT_RATE_LIMIT_MODE;
+
+/* typedef: enum GT_PRI0_RATE
+ * The ingress data rate limit for priority 0 frames 
+ */
+
+typedef enum
+{
+	GT_NO_LIMIT = 0, 	/* Not limited   */
+	GT_128K,      		/* 128K bits/sec */
+	GT_256K,      		/* 256K bits/sec */
+	GT_512K,      		/* 512 bits/sec */
+	GT_1M,      		/* 1M  bits/sec */
+	GT_2M,      		/* 2M  bits/sec */
+	GT_4M,      		/* 4M  bits/sec */
+	GT_8M,      		/* 8M  bits/sec */
+	GT_16M,      		/* 16M  bits/sec, Note: supported only by Gigabit Ethernet Switch */
+	GT_32M,      		/* 32M  bits/sec, Note: supported only by Gigabit Ethernet Switch */
+	GT_64M,      		/* 64M  bits/sec, Note: supported only by Gigabit Ethernet Switch */
+	GT_128M,      		/* 128M  bits/sec, Note: supported only by Gigabit Ethernet Switch */
+	GT_256M      		/* 256M  bits/sec, Note: supported only by Gigabit Ethernet Switch */
+} GT_PRI0_RATE,GT_EGRESS_RATE;
+
+
+/*
+ * Typedef: union GT_ERATE_TYPE
+ *
+ * Description: Egress Rate
+ *
+ * Fields:
+ *      definedRate - GT_EGRESS_RATE enum type should be used on the following devices:
+ *						88E6218, 88E6318, 88E6063, 88E6083, 88E6181, 88E6183, 88E6093
+ *						88E6095, 88E6185, 88E6108, 88E6065, 88E6061, and their variations.
+ *      kbRate      - rate in kbps that should be used on the following devices:
+ *						88E6097, 88E6096 with count mode of non frame, such as
+ *									ALL_LAYER1, ALL_LAYER2, and ALL_LAYER3
+ *						64kbps ~ 1Mbps    : increments of 64kbps,
+ *						1Mbps ~ 100Mbps   : increments of 1Mbps, and
+ *						100Mbps ~ 1000Mbps: increments of 10Mbps
+ *						Therefore, the valid values are:
+ *							64, 128, 192, 256, 320, 384,..., 960,
+ *							1000, 2000, 3000, 4000, ..., 100000,
+ *							110000, 120000, 130000, ..., 1000000.
+ *      fRate 		- frame per second that should be used on the following devices:
+ *						88E6097, 88E6096 with count mode of frame (GT_PIRL_COUNT_FRAME)
+ */
+typedef union
+{
+	GT_EGRESS_RATE	definedRate;
+	GT_U32			kbRate;
+	GT_U32			fRate;
+} GT_ERATE_TYPE;
+
+/*
+ * Formula for Rate Limit of Gigabit Switch family and Enhanced FastEthernet Switch
+ */
+#define GT_GET_RATE_LIMIT(_kbps)	\
+		((_kbps)?(8000000 / (28 * (_kbps))):0)
+#define GT_GET_RATE_LIMIT2(_kbps)	\
+		((_kbps)?(8000000 / (32 * (_kbps)) + (8000000 % (32 * (_kbps))?1:0)):0)
+#define GT_GET_RATE_LIMIT3(_kbps)	\
+		((_kbps)?(8000000 / (40 * (_kbps)) + (8000000 % (40 * (_kbps))?1:0)):0)
+
+#define MAX_RATE_LIMIT		256000	/* unit of Kbps */
+#define MIN_RATE_LIMIT		65		/* unit of Kbps */
+
+
+#define GT_GET_RATE_LIMIT_PER_FRAME(_frames, _dec)	\
+		((_frames)?(1000000000 / (32 * (_frames)) + (1000000000 % (32 * (_frames))?1:0)):0)
+
+#define GT_GET_RATE_LIMIT_PER_BYTE(_kbps, _dec)	\
+		((_kbps)?((8000000*(_dec)) / (32 * (_kbps)) + ((8000000*(_dec)) % (32 * (_kbps))?1:0)):0)
+
+/* 
+ * typedef: enum GT_BURST_SIZE
+ * The ingress data rate limit burst size windows selection
+ */
+
+typedef enum
+{
+	GT_BURST_SIZE_12K = 0, 	/* 12K byte burst size */
+	GT_BURST_SIZE_24K,		/* 24K byte burst size */
+	GT_BURST_SIZE_48K,		/* 48K byte burst size */
+	GT_BURST_SIZE_96K 	 	/* 96K byte burst size */
+} GT_BURST_SIZE;
+
+/* 
+ * typedef: enum GT_BURST_RATE
+ * The ingress data rate limit based on burst size
+ */
+
+typedef enum
+{
+	GT_BURST_NO_LIMIT = 0, 	/* Not limited   */
+	GT_BURST_64K,  		/* 64K bits/sec */
+	GT_BURST_128K,  	/* 128K bits/sec */
+	GT_BURST_256K,  	/* 256K bits/sec */
+	GT_BURST_384K,  	/* 384K bits/sec */
+	GT_BURST_512K,  	/* 512 bits/sec */
+	GT_BURST_640K,  	/* 640K bits/sec */
+	GT_BURST_768K,  	/* 768K bits/sec */
+	GT_BURST_896K,  	/* 896K bits/sec */
+	GT_BURST_1M,    	/* 1M  bits/sec */
+	GT_BURST_1500K,  	/* 1.5M bits/sec */
+	GT_BURST_2M,    	/* 2M  bits/sec */
+	GT_BURST_4M,    	/* 4M  bits/sec */
+	GT_BURST_8M,   		/* 8M  bits/sec */
+	GT_BURST_16M,  		/* 16M  bits/sec */
+	GT_BURST_32M,  		/* 32M  bits/sec */
+	GT_BURST_64M,  		/* 64M  bits/sec */
+	GT_BURST_128M, 		/* 128M  bits/sec */
+	GT_BURST_256M  		/* 256M  bits/sec */
+} GT_BURST_RATE;
+
+/*
+ * Formula for burst based Rate Limit
+ */
+#define GT_GET_BURST_RATE_LIMIT(_bsize,_kbps)	\
+		((_kbps)?(((_bsize)+1)*8000000 / (32 * (_kbps)) + 		\
+				(((_bsize)+1)*8000000 % (32 * (_kbps))?1:0))	\
+				:0)
+
+/*
+ * Typedef: enum GT_PIRL_OPERATION
+ *
+ * Description: Defines the PIRL (Port Ingress Rate Limit) Operation type
+ *
+ * Fields:
+ *      PIRL_INIT_ALL_RESOURCE - Initialize all resources to the inital state
+ *      PIRL_INIT_RESOURCE     - Initialize selected resources to the inital state
+ *      PIRL_WRITE_RESOURCE    - Write to the selected resource/register
+ *      PIRL_READ_RESOURCE     - Read from the selected resource/register
+ */
+typedef enum
+{
+	PIRL_INIT_ALL_RESOURCE 	= 0x1,
+	PIRL_INIT_RESOURCE		= 0x2,
+	PIRL_WRITE_RESOURCE		= 0x3,
+	PIRL_READ_RESOURCE		= 0x4
+} GT_PIRL_OPERATION, GT_PIRL2_OPERATION;
+
+
+/*
+ *  typedef: struct GT_PIRL_OP_DATA
+ *
+ *  Description: data required by PIRL Operation
+ *
+ *  Fields:
+ *      irlUnit   - Ingress Rate Limit Unit that defines one of IRL resources.
+ *      irlReg    - Ingress Rate Limit Register.
+ *      irlData   - Ingress Rate Limit Data.
+ */
+typedef struct
+{
+	GT_U32	irlUnit;
+	GT_U32	irlReg;
+	GT_U32	irlData;
+} GT_PIRL_OP_DATA;
+
+/*
+ *  typedef: struct GT_PIRL2_OP_DATA
+ *
+ *  Description: data required by PIRL Operation
+ *
+ *  Fields:
+ *      irlPort   - Ingress Rate Limiting port (physical port number).
+ *      irlRes    - Ingress Rate Limit Resource.
+ *      irlReg    - Ingress Rate Limit Register.
+ *      irlData   - Ingress Rate Limit Data.
+ */
+typedef struct
+{
+	GT_U32	irlPort;
+	GT_U32	irlRes;
+	GT_U32	irlReg;
+	GT_U32	irlData;
+} GT_PIRL2_OP_DATA;
+
+/*
+ * Typedef: enum GT_PIRL_ACTION
+ *
+ * Description: Defines the Action that should be taken when
+ *		there there are not enough tokens to accept the entire incoming frame
+ *
+ * Fields:
+ *		PIRL_ACTION_ACCEPT - accept the frame
+ *		PIRL_ACTION_USE_LIMIT_ACTION - use ESB Limit Action
+ */
+typedef enum
+{
+	PIRL_ACTION_USE_LIMIT_ACTION = 0x0,
+	PIRL_ACTION_ACCEPT 	= 0x1
+} GT_PIRL_ACTION;
+
+/*
+ * Typedef: enum GT_ESB_LIMIT_ACTION
+ *
+ * Description: Defines the ESB Limit Action that should be taken when
+ *		the incoming port information rate exceeds the EBS_Limit.
+ *
+ * Fields:
+ *		ESB_LIMIT_ACTION_DROP - drop packets
+ *		ESB_LIMIT_ACTION_FC   - send flow control packet
+ */
+typedef enum
+{
+	ESB_LIMIT_ACTION_DROP 	= 0x0,
+	ESB_LIMIT_ACTION_FC		= 0x1
+} GT_ESB_LIMIT_ACTION;
+
+
+/*
+ * Typedef: enum GT_BUCKET_RATE_TYPE
+ *
+ * Description: Defines the Bucket Rate Type
+ *
+ * Fields:
+ *		BUCKET_TYPE_TRAFFIC_BASED	- bucket is traffic type based
+ *		BUCKET_TYPE_RATE_BASED		- bucket is rate based
+ */
+typedef enum
+{
+	BUCKET_TYPE_TRAFFIC_BASED	= 0x0,
+	BUCKET_TYPE_RATE_BASED		= 0x1
+} GT_BUCKET_RATE_TYPE;
+
+/*
+ * Definition for GT_BUCKET_TYPE_TRAFFIC_BASED
+ *
+ * Description: Defines the Traffic Type that is used when Bucket Rate Type
+ *		is traffic type based (BUCKET_TYPE_TRAFFIC_BASED).
+ *		Please refer to the device datasheet in order to check which traffic
+ *		types are supported.
+ *
+ * Definition:
+ *		BUCKET_TRAFFIC_UNKNOWN_UNICAST	- unknown unicast frame
+ *		BUCKET_TRAFFIC_UNKNOWN_MULTICAST- unknown multicast frame
+ *		BUCKET_TRAFFIC_BROADCAST		- broadcast frame
+ *		BUCKET_TRAFFIC_MULTICAST		- multicast frame
+ *		BUCKET_TRAFFIC_UNICAST			- unicast frame
+ *		BUCKET_TRAFFIC_MGMT_FRAME		- management frame
+ *		BUCKET_TRAFFIC_ARP				- arp frame
+ *		BUCKET_TRAFFIC_TCP_DATA			- TCP Data
+ *		BUCKET_TRAFFIC_TCP_CTRL			- TCP Ctrl (if any of the TCP Flags[5:0] are set)
+ *		BUCKET_TRAFFIC_UDP				- UDP
+ *		BUCKET_TRAFFIC_NON_TCPUDP		- covers IGMP,ICMP,GRE,IGRP,L2TP
+ *		BUCKET_TRAFFIC_IMS				- Ingress Monitor Source
+ *		BUCKET_TRAFFIC_POLICY_MIRROR	- Policy Mirror
+ *		BUCKET_TRAFFIC_PLICY_TRAP		- Policy Trap
+ */
+#define BUCKET_TRAFFIC_UNKNOWN_UNICAST  	0x01
+#define BUCKET_TRAFFIC_UNKNOWN_MULTICAST	0x02
+#define BUCKET_TRAFFIC_BROADCAST			0x04
+#define BUCKET_TRAFFIC_MULTICAST			0x08
+#define BUCKET_TRAFFIC_UNICAST				0x10
+#define BUCKET_TRAFFIC_MGMT_FRAME			0x20
+#define BUCKET_TRAFFIC_ARP					0x40
+#define BUCKET_TRAFFIC_TCP_DATA				0x100
+#define BUCKET_TRAFFIC_TCP_CTRL				0x200
+#define BUCKET_TRAFFIC_UDP					0x400
+#define BUCKET_TRAFFIC_NON_TCPUDP			0x800
+#define BUCKET_TRAFFIC_IMS					0x1000
+#define BUCKET_TRAFFIC_POLICY_MIRROR		0x2000
+#define BUCKET_TRAFFIC_PLICY_TRAP			0x4000
+
+/*
+ *  typedef: enum GT_PIRL_COUNT_MODE
+ *
+ *  Description: Enumeration of the port egress rate limit counting mode.
+ *
+ *  Enumerations:
+ *      GT_PIRL_COUNT_ALL_LAYER1 -
+ *				Count all Layer 1 bytes: 
+ *				Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
+ *      GT_PIRL_COUNT_ALL_LAYER2 -
+ *				Count all Layer 2 bytes: Frame's DA to CRC
+ *      GT_PIRL_COUNT_ALL_LAYER3 -
+ *				Count all Layer 3 bytes: 
+ *				Frame's DA to CRC - 18 - 4 (if frame is tagged)
+ */
+typedef enum
+{
+	GT_PIRL_COUNT_ALL_LAYER1 = 0,
+	GT_PIRL_COUNT_ALL_LAYER2,
+	GT_PIRL_COUNT_ALL_LAYER3
+} GT_PIRL_COUNT_MODE;
+
+/*
+ *  typedef: enum GT_PIRL2_COUNT_MODE
+ *
+ *  Description: Enumeration of the port egress rate limit counting mode.
+ *
+ *  Enumerations:
+ *      GT_PIRL2_COUNT_FRAME -
+ *				Count the number of frames
+ *      GT_PIRL2_COUNT_ALL_LAYER1 -
+ *				Count all Layer 1 bytes: 
+ *				Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
+ *      GT_PIRL2_COUNT_ALL_LAYER2 -
+ *				Count all Layer 2 bytes: Frame's DA to CRC
+ *      GT_PIRL2_COUNT_ALL_LAYER3 -
+ *				Count all Layer 3 bytes: 
+ *				Frame's DA to CRC - 18 - 4 (if frame is tagged)
+ */
+typedef enum
+{
+	GT_PIRL2_COUNT_FRAME = 0,
+	GT_PIRL2_COUNT_ALL_LAYER1,
+	GT_PIRL2_COUNT_ALL_LAYER2,
+	GT_PIRL2_COUNT_ALL_LAYER3
+} GT_PIRL2_COUNT_MODE;
+
+
+
+/*
+ *  typedef: struct GT_PIRL_RESOURCE
+ *
+ *  Description: data structure that represents a PIRL Resource
+ *
+ *  Fields:
+ *      accountQConf    - account discarded frames due to queue congestion
+ *      accountFiltered - account filtered frames
+ *		ebsLimitAction  - action should be taken when the incoming rate exceeds
+ *						  the ebsLimit.
+ *								ESB_LIMIT_ACTION_DROP - drop packets
+ *								ESB_LIMIT_ACTION_FC   - send flow control packet
+ *		ebsLimit        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+ *		cbsLimit		- Committed BUrst Size limit (expected to be 2kBytes)
+ *		bktRateFactor   - bucket rate factor = bucketDecrement/updateInterval,
+ *						  where updateInterval indicates the rate at which the 
+ *						  bucket needs to be updated with tokens, or 1/CIR, 
+ *						  where CIR is the committed information rate in kbps.
+ *						  bucketDecrement indicates the amount of tokens that 
+ *						  need to be removed per each bucket decrement.
+ *		bktIncrement    - the amount of tokens that need to be added for each 
+ *						  byte of packet information.
+ *		bktRateType		- bucket is either rate based or traffic type based.
+ *								BUCKET_TYPE_RATE_BASED, or
+ *								BUCKET_TYPE_TRAFFIC_BASED
+ *		bktTypeMask		- used if bktRateType is BUCKET_TYPE_TRAFFIC_BASED. 
+ *						  any combination of the following definitions:
+ *								BUCKET_TRAFFIC_UNKNOWN_UNICAST,
+ *								BUCKET_TRAFFIC_UNKNOWN_MULTICAST,
+ *								BUCKET_TRAFFIC_BROADCAST,
+ *								BUCKET_TRAFFIC_MULTICAST,
+ *								BUCKET_TRAFFIC_UNICAST,
+ *								BUCKET_TRAFFIC_MGMT_FRAME, and
+ *								BUCKET_TRAFFIC_ARP
+ *		byteTobeCounted	- bytes to be counted for accounting
+ *								GT_PIRL_COUNT_ALL_LAYER1,
+ *								GT_PIRL_COUNT_ALL_LAYER2, or
+ *								GT_PIRL_COUNT_ALL_LAYER3
+ *
+ */
+typedef struct
+{
+	GT_BOOL		accountQConf;
+	GT_BOOL		accountFiltered;
+	GT_ESB_LIMIT_ACTION ebsLimitAction;
+	GT_U32		ebsLimit;
+	GT_U32		cbsLimit;
+	GT_U32		bktRateFactor;
+	GT_U32		bktIncrement;
+	GT_BUCKET_RATE_TYPE	bktRateType;
+	GT_U32		bktTypeMask;
+	GT_PIRL_COUNT_MODE	byteTobeCounted;
+} GT_PIRL_RESOURCE;
+
+/*
+ *  typedef: struct GT_PIRL_CUSTOM_RATE_LIMIT
+ *
+ *  Description: The parameters that decides Ingress Rate Limit vary depending on
+ *				the application. Since DSDT driver cannot cover all the cases,
+ *				this structure is provided for the custom parameter setting.
+ *				However, in most cases, user may ingore this structure by setting
+ *				isValid to GT_FALSE. If Ingress Rate Limit is too much off from
+ *				the expected rate, please contact FAE and gets the correct ebsLimit,
+ *				cbsLimit,bktIncrement, and bktRateFactor value and use this structure 
+ *				to do custom parameter setting.
+ *
+ *		isValid         - If GT_TRUE, the paramers in this structure are used 
+ *						  to program PIRL Resource's Rate Limit. And ingressRate
+ *						  in GT_PIRL_BUCKET_DATA structure are ignored.
+ *						  If GT_FALSE, ingressRate in GT_PIRL_BUCKET_DATA structure 
+ *						  is used for Resource's Rate Limit.
+ *		ebsLimit        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+ *		cbsLimit		- Committed Burst Size limit (expected to be 2kBytes)
+ *		bktIncrement    - the amount of tokens that need to be added for each 
+ *						  byte of packet information.
+ *		bktRateFactor   - bucket rate factor = bucketDecrement/updateInterval,
+ *						  where updateInterval indicates the rate at which the 
+ *						  bucket needs to be updated with tokens, or 1/CIR, 
+ *						  where CIR is the committed information rate in kbps.
+ *						  bucketDecrement indicates the amount of tokens that 
+ *						  need to be removed per each bucket decrement.
+*/
+typedef struct
+{
+	GT_BOOL		isValid;
+	GT_U32		ebsLimit;
+	GT_U32		cbsLimit;
+	GT_U32		bktIncrement;
+	GT_U32		bktRateFactor;
+} GT_PIRL_CUSTOM_RATE_LIMIT;
+
+/*
+ *  typedef: struct GT_PIRL_BUCKET_DATA
+ *
+ *  Description: data structure for PIRL Bucket programing that is resource based
+ *
+ *  Fields:
+ *		ingressRate   	- commited ingress rate in kbps.
+ *						  64kbps ~ 1Mbps    : increments of 64kbps,
+ *						  1Mbps ~ 100Mbps   : increments of 1Mbps, and
+ *						  100Mbps ~ 200Mbps : increments of 10Mbps
+ *						  Therefore, the valid values are:
+ *								64, 128, 192, 256, 320, 384,..., 960,
+ *								1000, 2000, 3000, 4000, ..., 100000,
+ *								110000, 120000, 130000, ..., 200000.
+ *		customSetup   	- custom ingress rate parameter setup. please refer to
+ *						  GT_PIRL_CUSTOM_RATE_LIMIT structure.
+ *      accountQConf    - account discarded frames due to queue congestion
+ *      accountFiltered - account filtered frames
+ *		esbLimitAction 	- action should be taken when the incoming rate exceeds
+ *						  the limit.
+ *								ESB_LIMIT_ACTION_DROP - drop packets
+ *								ESB_LIMIT_ACTION_FC   - send flow control packet
+ *		fcDeassertMode	- port flow control de-assertion mode when limitAction is
+ *						  set to ESB_LIMIT_ACTION_FC.
+ *						  fcDeassertMode[0] for port 0, fcDeassertMode[1] for 
+ *						  port 1, etc. If port x does not share the bucket,
+ *						  fcDeassertMode[x] data will be ignored.
+ *								GT_PIRL_FC_DEASSERT_EMPTY -
+ *									De-assert when the ingress rate resource has 
+ *									become empty.
+ *								GT_PIRL_FC_DEASSERT_CBS_LIMIT -
+ *									De-assert when the ingress rate resource has 
+ *									enough room as specified by the CBSLimit.
+ *		bktRateType		- bucket is either rate based or traffic type based.
+ *								BUCKET_TYPE_RATE_BASED, or
+ *								BUCKET_TYPE_TRAFFIC_BASED
+ *		bktTypeMask		- used if bktRateType is BUCKET_TYPE_TRAFFIC_BASED. 
+ *						  any combination of the following definitions:
+ *								BUCKET_TRAFFIC_UNKNOWN_UNICAST,
+ *								BUCKET_TRAFFIC_UNKNOWN_MULTICAST,
+ *								BUCKET_TRAFFIC_BROADCAST,
+ *								BUCKET_TRAFFIC_MULTICAST,
+ *								BUCKET_TRAFFIC_UNICAST,
+ *								BUCKET_TRAFFIC_MGMT_FRAME, and
+ *								BUCKET_TRAFFIC_ARP
+ *		byteTobeCounted	- bytes to be counted for accounting
+ *								GT_PIRL_COUNT_ALL_LAYER1,
+ *								GT_PIRL_COUNT_ALL_LAYER2, or
+ *								GT_PIRL_COUNT_ALL_LAYER3
+ *
+ */
+typedef struct
+{
+	GT_U32		ingressRate;
+	GT_PIRL_CUSTOM_RATE_LIMIT customSetup;
+	GT_BOOL		accountQConf;
+	GT_BOOL		accountFiltered;
+	GT_ESB_LIMIT_ACTION ebsLimitAction;
+	GT_PIRL_FC_DEASSERT fcDeassertMode[MAX_SWITCH_PORTS];
+	GT_BUCKET_RATE_TYPE	bktRateType;
+	GT_U32		bktTypeMask;
+	GT_PIRL_COUNT_MODE	byteTobeCounted;
+} GT_PIRL_DATA;
+
+
+/*
+ *  typedef: struct GT_PIRL2_RESOURCE
+ *
+ *  Description: data structure that represents a PIRL Resource
+ *
+ *  Fields:
+ *      accountQConf    - account discarded frames due to queue congestion
+ *      accountFiltered - account filtered frames
+ *      mgmtNrlEn 		- exclude management frame from ingress rate limiting calculation
+ *      saNrlEn 		- exclude from ingress rate limiting calculation if the SA of the
+ *						  frame is in ATU with EntryState that indicates Non Rate Limited.
+ *      daNrlEn 		- exclude from ingress rate limiting calculation if the DA of the
+ *						  frame is in ATU with EntryState that indicates Non Rate Limited.
+ *		samplingMode	- sample one out of so many frames/bytes for a stream of frames
+ *		actionMode		- action should be taken when there are not enough tokens
+ *						  to accept the entire incoming frame
+ *								PIRL_ACTION_ACCEPT - accept the frame
+ *								PIRL_ACTION_USE_LIMIT_ACTION - use limitAction
+ *		ebsLimitAction  - action should be taken when the incoming rate exceeds
+ *						  the ebsLimit.
+ *								ESB_LIMIT_ACTION_DROP - drop packets
+ *								ESB_LIMIT_ACTION_FC   - send flow control packet
+ *		ebsLimit        - Excess Burst Size limit ( 0 ~ 0xFFFFFF)
+ *		cbsLimit		- Committed BUrst Size limit (expected to be 2kBytes)
+ *		bktRateFactor   - bucket rate factor = bucketDecrement/updateInterval,
+ *						  where updateInterval indicates the rate at which the 
+ *						  bucket needs to be updated with tokens, or 1/CIR, 
+ *						  where CIR is the committed information rate in kbps.
+ *						  bucketDecrement indicates the amount of tokens that 
+ *						  need to be removed per each bucket decrement.
+ *		bktIncrement    - the amount of tokens that need to be added for each 
+ *						  byte of packet information.
+ *		fcDeassertMode	- flow control de-assertion mode when limitAction is
+ *						  set to ESB_LIMIT_ACTION_FC.
+ *								GT_PIRL_FC_DEASSERT_EMPTY -
+ *									De-assert when the ingress rate resource has 
+ *									become empty.
+ *								GT_PIRL_FC_DEASSERT_CBS_LIMIT -
+ *									De-assert when the ingress rate resource has 
+ *									enough room as specified by the CBSLimit.
+ *		bktRateType		- bucket is either rate based or traffic type based.
+ *								BUCKET_TYPE_RATE_BASED, or
+ *								BUCKET_TYPE_TRAFFIC_BASED
+ *      priORpt         - determine the incoming frames that get rate limited using
+ *						  this ingress rate resource.
+ *						  		GT_TRUE - typeMask OR priMask
+ *						  		GT_FALSE - typeMask AND priMask
+ *		priMask         - priority bit mask that each bit indicates one of the four
+ *						  queue priorities. Setting each one of these bits indicates
+ *						  that this particular rate resource is slated to account for
+ *						  incoming frames with the enabled bits' priority.
+ *		bktTypeMask		- used if bktRateType is BUCKET_TYPE_TRAFFIC_BASED. 
+ *						  any combination of the following definitions:
+ *								BUCKET_TRAFFIC_UNKNOWN_UNICAST,
+ *								BUCKET_TRAFFIC_UNKNOWN_MULTICAST,
+ *								BUCKET_TRAFFIC_BROADCAST,
+ *								BUCKET_TRAFFIC_MULTICAST,
+ *								BUCKET_TRAFFIC_UNICAST,
+ *								BUCKET_TRAFFIC_MGMT_FRAME,
+ *								BUCKET_TRAFFIC_ARP,
+ *								BUCKET_TRAFFIC_TCP_DATA,
+ *								BUCKET_TRAFFIC_TCP_CTRL,
+ *								BUCKET_TRAFFIC_UDP,
+ *								BUCKET_TRAFFIC_NON_TCPUDP,
+ *								BUCKET_TRAFFIC_IMS,
+ *								BUCKET_TRAFFIC_POLICY_MIRROR, and
+ *								BUCKET_TRAFFIC_PLICY_TRAP
+ *		byteTobeCounted	- bytes to be counted for accounting
+ *								GT_PIRL2_COUNT_FRAME,
+ *								GT_PIRL2_COUNT_ALL_LAYER1,
+ *								GT_PIRL2_COUNT_ALL_LAYER2, or
+ *								GT_PIRL2_COUNT_ALL_LAYER3
+ *
+ */
+typedef struct
+{
+	GT_BOOL		accountQConf;
+	GT_BOOL		accountFiltered;
+	GT_BOOL		mgmtNrlEn;
+	GT_BOOL		saNrlEn;
+	GT_BOOL		daNrlEn;
+	GT_BOOL		samplingMode;
+	GT_PIRL_ACTION	actionMode;
+	GT_ESB_LIMIT_ACTION ebsLimitAction;
+	GT_U32		ebsLimit;
+	GT_U32		cbsLimit;
+	GT_U32		bktRateFactor;
+	GT_U32		bktIncrement;
+	GT_PIRL_FC_DEASSERT fcDeassertMode;
+	GT_BUCKET_RATE_TYPE	bktRateType;
+	GT_BOOL		priORpt;
+	GT_U32		priMask;
+	GT_U32		bktTypeMask;
+	GT_PIRL2_COUNT_MODE	byteTobeCounted;
+} GT_PIRL2_RESOURCE;
+
+
+/*
+ *  typedef: struct GT_PIRL2_BUCKET_DATA
+ *
+ *  Description: data structure for PIRL2 Bucket programing that is port based.
+ *
+ *  Fields:
+ *		ingressRate   	- commited ingress rate in kbps.
+ *						  64kbps ~ 1Mbps    : increments of 64kbps,
+ *						  1Mbps ~ 100Mbps   : increments of 1Mbps, and
+ *						  100Mbps ~ 200Mbps : increments of 10Mbps
+ *						  Therefore, the valid values are:
+ *								64, 128, 192, 256, 320, 384,..., 960,
+ *								1000, 2000, 3000, 4000, ..., 100000,
+ *								110000, 120000, 130000, ..., 200000.
+ *		customSetup   	- custom ingress rate parameter setup. please refer to
+ *						  GT_PIRL_CUSTOM_RATE_LIMIT structure.
+ *      accountQConf    - account discarded frames due to queue congestion
+ *      accountFiltered - account filtered frames
+ *      mgmtNrlEn 		- exclude management frame from ingress rate limiting calculation
+ *      saNrlEn 		- exclude from ingress rate limiting calculation if the SA of the
+ *						  frame is in ATU with EntryState that indicates Non Rate Limited.
+ *      daNrlEn 		- exclude from ingress rate limiting calculation if the DA of the
+ *						  frame is in ATU with EntryState that indicates Non Rate Limited.
+ *		samplingMode	- sample one out of so many frames/bytes for a stream of frames
+ *		actionMode		- action should be taken when there are not enough tokens
+ *						  to accept the entire incoming frame
+ *								PIRL_ACTION_ACCEPT - accept the frame
+ *								PIRL_ACTION_USE_LIMIT_ACTION - use limitAction
+ *		ebsLimitAction 	- action should be taken when the incoming rate exceeds
+ *						  the limit.
+ *								ESB_LIMIT_ACTION_DROP - drop packets
+ *								ESB_LIMIT_ACTION_FC   - send flow control packet
+ *		fcDeassertMode	- flow control de-assertion mode when limitAction is
+ *						  set to ESB_LIMIT_ACTION_FC.
+ *								GT_PIRL_FC_DEASSERT_EMPTY -
+ *									De-assert when the ingress rate resource has 
+ *									become empty.
+ *								GT_PIRL_FC_DEASSERT_CBS_LIMIT -
+ *									De-assert when the ingress rate resource has 
+ *									enough room as specified by the CBSLimit.
+ *		bktRateType		- bucket is either rate based or traffic type based.
+ *								BUCKET_TYPE_RATE_BASED, or
+ *								BUCKET_TYPE_TRAFFIC_BASED
+ *      priORpt         - determine the incoming frames that get rate limited using
+ *						  this ingress rate resource.
+ *						  		GT_TRUE - typeMask OR priMask
+ *						  		GT_FALSE - typeMask AND priMask
+ *		priMask         - priority bit mask that each bit indicates one of the four
+ *						  queue priorities. Setting each one of these bits indicates
+ *						  that this particular rate resource is slated to account for
+ *						  incoming frames with the enabled bits' priority.
+ *		bktTypeMask		- used if bktRateType is BUCKET_TYPE_TRAFFIC_BASED. 
+ *						  any combination of the following definitions:
+ *								BUCKET_TRAFFIC_UNKNOWN_UNICAST,
+ *								BUCKET_TRAFFIC_UNKNOWN_MULTICAST,
+ *								BUCKET_TRAFFIC_BROADCAST,
+ *								BUCKET_TRAFFIC_MULTICAST,
+ *								BUCKET_TRAFFIC_UNICAST,
+ *								BUCKET_TRAFFIC_MGMT_FRAME,
+ *								BUCKET_TRAFFIC_ARP,
+ *								BUCKET_TRAFFIC_TCP_DATA,
+ *								BUCKET_TRAFFIC_TCP_CTRL,
+ *								BUCKET_TRAFFIC_UDP,
+ *								BUCKET_TRAFFIC_NON_TCPUDP,
+ *								BUCKET_TRAFFIC_IMS,
+ *								BUCKET_TRAFFIC_POLICY_MIRROR, and
+ *								BUCKET_TRAFFIC_PLICY_TRAP
+ *		byteTobeCounted	- bytes to be counted for accounting
+ *								GT_PIRL2_COUNT_FRAME,
+ *								GT_PIRL2_COUNT_ALL_LAYER1,
+ *								GT_PIRL2_COUNT_ALL_LAYER2, or
+ *								GT_PIRL2_COUNT_ALL_LAYER3
+ *
+ */
+typedef struct
+{
+	GT_U32		ingressRate;
+	GT_PIRL_CUSTOM_RATE_LIMIT customSetup;
+	GT_BOOL		accountQConf;
+	GT_BOOL		accountFiltered;
+	GT_BOOL		mgmtNrlEn;
+	GT_BOOL		saNrlEn;
+	GT_BOOL		daNrlEn;
+	GT_BOOL		samplingMode;
+	GT_PIRL_ACTION	actionMode;
+	GT_ESB_LIMIT_ACTION ebsLimitAction;
+	GT_PIRL_FC_DEASSERT fcDeassertMode;
+	GT_BUCKET_RATE_TYPE	bktRateType;
+	GT_BOOL		priORpt;
+	GT_U32		priMask;
+	GT_U32		bktTypeMask;
+	GT_PIRL2_COUNT_MODE	byteTobeCounted;
+} GT_PIRL2_DATA;
+
+
+
+/*
+ *  typedef: struct GT_PIRL_CUSTOM_TSM_CFG
+ *
+ *  Description: The parameters that decides Ingress Rate Limit for AVB frames vary 
+ * 				depending on the application. Since DSDT driver cannot cover all the cases,
+ *				this structure is provided for the custom parameter setting.
+ *				However, in most cases, user may ingore this structure by setting
+ *				isValid to GT_FALSE. If Ingress Rate Limit is too much off from
+ *				the expected rate, please contact FAE and gets the correct ebsLimit,
+ *				cbsLimit, CTS interval, and action mode value and use this structure 
+ *				to do custom parameter setting.
+ *
+ *		isValid         - If GT_TRUE, the paramers in this structure are used 
+ *						  to program PIRL Resource's Rate Limit. And ingressRate
+ *						  in GT_PIRL_TSM_DATA structure are ignored.
+ *						  If GT_FALSE, ingressRate in GT_PIRL_TSM_DATA structure 
+ *						  is used for Resource's Rate Limit.
+ *		ebsLimit        - Excess Burst Size limit (0 ~ 0xFFFF)
+ *		cbsLimit		- Committed Burst Size limit (0 ~ 0xFFFF)
+ *		ctsIntv         - Class Time Slot Interval
+ *						  0 - interval is 62.5us
+ *						  1 - interval is 125us
+ *						  2 - interval is 250us
+ *						  3 - interval is 1000us
+ *		actionMode		- action should be taken when there are not enough tokens
+ *						  to accept the entire incoming frame
+ *								PIRL_ACTION_ACCEPT - accept the frame
+ *								PIRL_ACTION_USE_LIMIT_ACTION - use limitAction
+*/
+typedef struct
+{
+	GT_BOOL		isValid;
+	GT_U32		ebsLimit;
+	GT_U32		cbsLimit;
+	GT_U32		ctsIntv;
+	GT_PIRL_ACTION		actionMode;
+} GT_PIRL_CUSTOM_TSM_CFG;
+
+
+/*
+ *  typedef: struct GT_PIRL2_TSM_DATA
+ *
+ *  Description: data structure for PIRL2 TSM Ingress Rate Limit.
+ *
+ *  Fields:
+ *		ebsLimit        - Excess Burst Size limit (0 ~ 0xFFFF)
+ *		cbsLimit		- Committed Burst Size limit (0 ~ 0xFFFF)
+ *		ctsIntv         - Class Time Slot Interval
+ *						  0 - interval is 62.5us
+ *						  1 - interval is 125us
+ *						  2 - interval is 250us
+ *						  3 - interval is 1000us
+ *		actionMode		- action should be taken when there are not enough tokens
+ *						  to accept the entire incoming frame
+ *								PIRL_ACTION_ACCEPT - accept the frame
+ *								PIRL_ACTION_USE_LIMIT_ACTION - use limitAction
+ * 		mgmtNrlEn 		- exclude management frame from ingress rate limiting calculation
+ *		priMask         - priority bit mask that each bit indicates one of the four
+ *						  queue priorities. Setting each one of these bits indicates
+ *						  that this particular rate resource is slated to account for
+ *						  incoming frames with the enabled bits' priority.
+ *
+ */
+typedef struct
+{
+	GT_BOOL		tsmMode;
+	GT_U32		ebsLimit;
+	GT_U32		cbsLimit;
+	GT_U32		ctsIntv;
+	GT_PIRL_ACTION		actionMode;
+	GT_BOOL		mgmtNrlEn;
+	GT_U32		priMask;
+} GT_PIRL2_TSM_RESOURCE;
+
+
+
+/*
+ *  typedef: struct GT_PIRL2_TSM_DATA
+ *
+ *  Description: data structure for PIRL2 TSM Ingress Rate Limit.
+ *
+ *  Fields:
+ *		tsmMode			- enable/disable TSM mode. 
+ *						  The following fields are ignored if diable
+ *		ingressRate   	- commited ingress rate in kbps.(min 64 for 64kbps)
+ *		customSetup   	- custom ingress rate parameter setup. please refer to
+ *						  GT_PIRL_CUSTOM_TSM_CFG structure.
+ *		mgmtNrlEn		- exclude management frame from ingress rate limiting calculation
+ *		priMask         - priority bit mask that each bit indicates one of the four
+ *						  queue priorities. Setting each one of these bits indicates
+ *						  that this particular rate resource is slated to account for
+ *						  incoming frames with the enabled bits' priority.
+ *
+ */
+typedef struct
+{
+	GT_BOOL		tsmMode;
+	GT_U32		ingressRate;
+	GT_PIRL_CUSTOM_TSM_CFG customSetup;
+	GT_BOOL		mgmtNrlEn;
+	GT_U32		priMask;
+} GT_PIRL2_TSM_DATA;
+
+
+
+#define MAX_PTP_CONSECUTIVE_READ	4
+
+/*
+ * Typedef: enum GT_PTP_OPERATION
+ *
+ * Description: Defines the PTP (Precise Time Protocol) Operation type
+ *
+ * Fields:
+ *      PTP_WRITE_DATA 			- Write data to the PTP register
+ *      PTP_READ_DATA			- Read data from PTP register
+ *      PTP_READ_MULTIPLE_DATA	- Read multiple data from PTP register
+ *      PTP_READ_TIMESTAMP_DATA	- Read timestamp data from PTP register
+ *					valid bit will be reset after read
+ */
+typedef enum
+{
+	PTP_WRITE_DATA 			= 0x3,
+	PTP_READ_DATA  			= 0x4,
+	PTP_READ_MULTIPLE_DATA	= 0x6,
+	PTP_READ_TIMESTAMP_DATA	= 0x8,
+} GT_PTP_OPERATION;
+
+
+/*
+ * Typedef: enum GT_PTP_SPEC
+ *
+ * Description: Defines the PTP (Precise Time Protocol) SPEC type
+ *
+ * Fields:
+ *      PTP_IEEE_1588 		- IEEE 1588
+ *      PTP_IEEE_802_1AS	- IEEE 802.1as
+ */
+typedef enum
+{
+	PTP_IEEE_1588		= 0x0,
+	PTP_IEEE_802_1AS	= 0x1
+} GT_PTP_SPEC;
+
+
+/*
+ *  typedef: struct GT_PTP_OP_DATA
+ *
+ *  Description: data required by PTP Operation
+ *
+ *  Fields:
+ *      ptpPort		- physical port of the device
+ *      ptpAddr 	- register address
+ *      ptpData 	- data for ptp register.
+ *      ptpMultiData- used for multiple read operation.
+ *      nData 		- number of data to be read on multiple read operation.
+ */
+typedef struct
+{
+	GT_U32	ptpPort;
+	GT_U32	ptpBlock;
+	GT_U32	ptpAddr;
+	GT_U32	ptpData;
+	GT_U32	ptpMultiData[MAX_PTP_CONSECUTIVE_READ];
+	GT_U32	nData;
+} GT_PTP_OP_DATA;
+
+
+/*
+ *  typedef: struct GT_PTP_CONFIG
+ *
+ *  Description: PTP configuration parameters
+ *
+ *  Fields:
+ *      ptpEType	- PTP Ether Type
+ *      msgIdTSEn 	- Message IDs that needs time stamp
+ *      tsArrPtr 	- Time stamp arrival time counter pointer (either Arr0Time or Arr1Time)
+ *      ptpArrIntEn	- PTP port arrival interrupt enable
+ *      ptpDepIntEn	- PTP port departure interrupt enable
+ *      transSpec	- This is to differentiate between various timing protocols.
+ *      msgIdStartBit 	- Message ID starting bit in the PTP common header
+ *      disTSOverwrite 	- disable time stamp counter overwriting until the corresponding
+ *						  timer valid bit is cleared.
+ */
+typedef struct
+{
+	GT_U32	ptpEType;
+	GT_U32	msgIdTSEn;
+	GT_U32	tsArrPtr;
+	GT_U32	ptpArrIntEn;
+	GT_U32	ptpDepIntEn;
+	GT_PTP_SPEC	transSpec;
+	GT_U32	msgIdStartBit;
+	GT_BOOL	disTSOverwrite;
+} GT_PTP_CONFIG;
+
+
+/*
+ *  typedef: struct GT_PTP_GLOBAL_CONFIG
+ *
+ *  Description: PTP global configuration parameters
+ *
+ *  Fields:
+ *      ptpEType	- PTP Ether Type
+ *      msgIdTSEn 	- Message IDs that needs time stamp
+ *      tsArrPtr 	- Time stamp arrival time counter pointer (either Arr0Time or Arr1Time)
+ */
+typedef struct
+{
+	GT_U32	ptpEType;
+	GT_U32	msgIdTSEn;
+	GT_U32	tsArrPtr;
+} GT_PTP_GLOBAL_CONFIG;
+
+
+/*
+ *  typedef: struct GT_PTP_PORT_CONFIG
+ *
+ *  Description: PTP configuration parameters for each port
+ *
+ *  Fields:
+ *      transSpec	- This is to differentiate between various timing protocols.
+ *      disTSpec 	- Disable Transport specific check
+ *      etJump 		- offset to Ether type start address in bytes
+ *      ipJump 		- offset to IP header start address counting from Ether type offset
+ *      ptpArrIntEn	- PTP port arrival interrupt enable
+ *      ptpDepIntEn	- PTP port departure interrupt enable
+ *      disTSOverwrite 	- disable time stamp counter overwriting until the corresponding
+ *						  timer valid bit is cleared.
+ */
+typedef struct
+{
+	GT_PTP_SPEC	transSpec;
+	GT_BOOL	disTSpec;
+	GT_U32	etJump;
+	GT_U32	ipJump;
+	GT_BOOL	ptpArrIntEn;
+	GT_BOOL	ptpDepIntEn;
+	GT_BOOL	disTSOverwrite;
+} GT_PTP_PORT_CONFIG;
+
+
+/*
+ * Typedef: enum GT_PTP_TIME
+ *
+ * Description: Defines the PTP Time to be read
+ *
+ * Fields:
+ *      PTP_WRITE_DATA 			- Write data to the PTP register
+ *      PTP_READ_DATA			- Read data from PTP register
+ *      PTP_READ_MULTIPLE_DATA	- Read multiple data from PTP register
+ */
+typedef enum
+{
+	PTP_ARR0_TIME = 0x0,
+	PTP_ARR1_TIME = 0x1,
+	PTP_DEP_TIME = 0x2
+} GT_PTP_TIME;
+
+
+/*
+ * Typedef: enum GT_PTP_INT_STATUS
+ *
+ * Description: Defines the PTP Port interrupt status for time stamp
+ *
+ * Fields:
+ *      PTP_INT_NORMAL		- No error condition occurred
+ *      PTP_INT_OVERWRITE 	- PTP logic has to process more than one PTP frame
+ *						  		that needs time stamping before the current read.
+ *								Only the latest one is saved.
+ *      PTP_INT_DROP	  	- PTP logic has to process more than one PTP frame
+ *						  		that needs time stamping before the current read.
+ *								Only the oldest one is saved.
+ *
+ */
+typedef enum
+{
+	PTP_INT_NORMAL 		= 0x0,
+	PTP_INT_OVERWRITE 	= 0x1,
+	PTP_INT_DROP 		= 0x2
+} GT_PTP_INT_STATUS;
+
+
+/*
+ *  typedef: struct GT_PTP_TS_STATUS
+ *
+ *  Description: PTP port status of time stamp
+ *
+ *  Fields:
+ *      isValid		- time stamp is valid
+ *      status		- time stamp error status
+ *      timeStamped	- time stamp value of a PTP frame that needs to be time stamped
+ *      ptpSeqId	- sequence ID of the frame whose time stamp information has been captured
+ */
+typedef struct
+{
+	GT_BOOL	isValid;
+	GT_U32	timeStamped;
+	GT_U32	ptpSeqId;
+	GT_PTP_INT_STATUS	status;
+} GT_PTP_TS_STATUS;
+
+
+/*
+ *  typedef: struct GT_PTP_PORT_DISCARD_STATS
+ *
+ *  Description: PTP port discard statistics. The counter (4 bit wide) wraps around after 15. 
+ *
+ *  Fields:
+ *      tsDepDisCtr	- PTP departure frame discard counter for PTP frames that need time stamping.
+ *      ntsDepDisCtr	- PTP departure frame discard counter for PTP frames that do not need time stamping.
+ *      tsArrDisCtr	- PTP arrival frame discard counter for PTP frames that need time stamping.
+ *      ntsArrDisCtr	- PTP arrival frame discard counter for PTP frames that do not need time stamping.
+ */
+typedef struct
+{
+	GT_U32	tsDepDisCtr;
+	GT_U32	ntsDepDisCtr;
+	GT_U32	tsArrDisCtr;
+	GT_U32	ntsArrDisCtr;
+} GT_PTP_PORT_DISCARD_STATS;
+
+
+#ifdef CONFIG_AVB_FPGA
+
+typedef enum
+{
+	PTP_CLOCK_SRC_AD_DEVICE = 0,	/* PTP Clock source is from A/D device */
+	PTP_CLOCK_SRC_FPGA				/* PTP Clock source is from Cesium FPGA */
+} GT_PTP_CLOCK_SRC;
+
+typedef enum
+{
+	PTP_P9_MODE_GMII = 0, 	/* Port 9 uses GMII connect to 88E1111 */
+	PTP_P9_MODE_MII,		/* Port 9 uses MII connect to 88E1111 */
+	PTP_P9_MODE_MII_CONNECTOR,		/* Port 9 connect to MII connector */
+	PTP_P9_MODE_JUMPER		/* Use Jumper setup */
+} GT_PTP_P9_MODE;
+
+typedef enum
+{
+	GT_PTP_SIGN_NEGATIVE = 0,	/* apply Minus sign to the Duty Cycle */
+	GT_PTP_SIGN_PLUS			/* apply Plus sign to the Duty Cycle */
+} GT_PTP_SIGN;
+
+typedef struct
+{
+	GT_PTP_SIGN	adjSign;	/* determine the plus/minus sign of the duty cycle adj */
+	GT_U32	cycleStep;		/* number of steps which will be applied in adjusting the duty cycle high time 
+								of the 8KHz clock cycle. 
+								valid values are 0 ~ 7 */
+	GT_U32	cycleInterval;	/* define the interval of clock cycles for which a duty cycle adj will occur */
+	GT_U32	cycleAdjust;	/* define the number of 8KHz clock cycles for which duty cycle adj will occur
+								within each PTP clock clycle interval.
+								Note that (cycleAdjust <= cycleInterval) for proper operation */
+} GT_PTP_CLOCK_ADJUSTMENT;
+
+#endif
+
+/*
+ *  typedef: struct GT_TAI_EVENT_CONFIG
+ *
+ *  Description: TAI event capture configuration parameters
+ *
+ *  Fields:
+ *      eventOverwrite	- event capture overwrite
+ *      eventCtrStart	 	- event counter start
+ *      intEn 			- event capture interrupt enable
+ */
+typedef struct
+{
+	GT_BOOL	eventOverwrite;
+	GT_BOOL	eventCtrStart;
+	GT_BOOL	intEn;
+} GT_TAI_EVENT_CONFIG;
+
+
+/*
+ *  typedef: struct GT_TAI_EVENT_STATUS
+ *
+ *  Description: TAI event capture status
+ *
+ *  Fields:
+ *      isValid		- eventTime is valid
+ *      eventTime 	- PTP global time when event is registered.
+ *      eventCtr	- event capture counter. increamented only if eventCtrStart is set.
+ *      eventErr	- isValid is already set when a new event is observed.
+ */
+typedef struct
+{
+	GT_BOOL	isValid;
+	GT_U32	eventTime;
+	GT_U32	eventCtr;
+	GT_BOOL	eventErr;
+} GT_TAI_EVENT_STATUS;
+
+
+typedef enum
+{
+	GT_TAI_TRIG_PERIODIC_PURSE = 0,	/* generate periodic purse */
+	GT_TAI_TRIG_ON_GIVEN_TIME		/* generate purse when 
+									PTP global time matches with given time */
+} GT_TAI_TRIG_MODE;
+
+
+/*
+ *  typedef: struct GT_TAI_TRIGGER_CONFIG
+ *
+ *  Description: TAI trigger generator configuration parameters
+ *
+ *  Fields:
+ *      intEn 		- trigger generator interrupt enable
+ *      mode		- trigger mode, either GT_TAI_TRIG_PERIODIC_PURSE or 
+ *					  GT_TAI_TRIG_ON_GIVEN_TIME
+ *      trigGenAmt 	- if mode is GT_TAI_TRIG_PERIODIC_PURSE,
+ *					  this value is used as a clock period in TSClkPer increments
+ *					  If mode is GT_TAI_TRIG_ON_GIVEN_TIME,
+ *					  this value is used to compare with PTP global time.
+ *      pulseWidth		- pulse width in units of TSClkPer.
+ *					  this value should be 1 ~ 0xF. If it's 0, no changes made.
+ *					  this value is valid only in GT_TAI_TRIG_ON_GIVEN_TIME mode.
+ *      trigClkComp	- trigger mode clock compensation amount in pico sec.
+ *					  this value is valid only in GT_TAI_TRIG_PERIODIC_PURSE mode.
+ */
+typedef struct
+{
+	GT_BOOL	intEn;
+	GT_TAI_TRIG_MODE 	mode;
+	GT_U32	trigGenAmt;
+	GT_U32	pulseWidth;
+	GT_U32	trigClkComp;
+} GT_TAI_TRIGGER_CONFIG;
+
+
+typedef enum
+{
+	GT_AVB_HI_FPRI,		/* AVB Hi Frame Priority */
+	GT_AVB_HI_QPRI,		/* AVB Hi Queue Priority */
+	GT_AVB_LO_FPRI,		/* AVB Lo Frame Priority */
+	GT_AVB_LO_QPRI,		/* AVB Lo Queue Priority */
+	GT_LEGACY_HI_FPRI,	/* Legacy Hi Frame Priority */
+	GT_LEGACY_HI_QPRI,	/* Legacy Hi Queue Priority */
+	GT_LEGACY_LO_FPRI,	/* Legacy Lo Frame Priority */
+	GT_LEGACY_LO_QPRI	/* Legacy Lo Queue Priority */
+} GT_AVB_PRI_TYPE;
+
+
+typedef enum
+{
+	GT_AVB_LEGACY_MODE,			/* all frames entering the port are considered 
+									legacy */
+	GT_AVB_STANDARD_AVB_MODE,	/* any tagged frame that ends up with an AVB frame 
+									priority is considered AVB */
+	GT_AVB_ENHANCED_AVB_MODE,	/* any frame that ends up with an AVB frame priority 
+									whose DA is contained in the ATU with an AVB Entry 
+									state is considered AVB */
+	GT_AVB_SECURE_AVB_MODE		/* any frame that ends up with an AVB frame priority 
+									whose DA is contained in the ATU with an AVB 
+									entry state and whose DPV has this source port's 
+									bit set to a one is considered AVB. */
+} GT_AVB_MODE;
+
+
+/*
+ * Typedef: enum GT_AVB_FRAME_POLICY
+ *
+ * Description: Defines the policy of the frame
+ *
+ * Fields:
+ *      AVB_FRAME_POLICY_NONE - Normal frame switching
+ *      AVB_FRAME_POLICY_MIRROR - Mirror(copy) frame to the MirrorDest port
+ *      AVB_FRAME_POLICY_TRAP - Trap(re-direct) frame to the CPUDest port
+ *
+ */
+typedef enum
+{
+	AVB_FRAME_POLICY_NONE = 0,
+	AVB_FRAME_POLICY_MIRROR,
+	AVB_FRAME_POLICY_TRAP
+} GT_AVB_FRAME_POLICY;
+
+
+/*
+ * Typedef: enum GT_AVB_FRAME_TYPE
+ *
+ * Description: 
+ *		Defines the AVB frame type.
+ *		AVB Hi Frame is one that DA of the frame is contained in the ATU with an 
+ *		Entry State that indicates AVB with priority override where the overridden 
+ *		priority equals the Hi AVB frame priority(refer to gavbGetPriority API) and 
+ *		when the port's DA AvbOverride is enabled.
+ *		AVB Lo Frame is one that DA of the frame is contained in the ATU with an 
+ *		Entry State that indicates AVB with priority override where the overridden 
+ *		priority equals the Lo AVB frame priority(refer to gavbGetPriority API) and 
+ *		when the port's DA AvbOverride is enabled.
+ *
+ * Fields:
+ *      AVB_HI_FRAME	- AVB Hi Frame
+ *      AVB_LO_FRAME	- AVB Lo Frame
+ */
+typedef enum
+{
+	AVB_HI_FRAME,
+	AVB_LO_FRAME
+} GT_AVB_FRAME_TYPE;
+
+
+/*
+ * typedef: enum GT_EVENT_TYPE
+ *
+ * Description: Enumeration of the available hardware driven events.
+ *
+ * Enumerations:
+ *   GT_AVB_INT    - AVB Interrupt Enable
+ *   GT_DEVICE_INT - Device Interrupt (GT_DEVICE_INT_TYPE) Enable
+ *   GT_STATS_DONE - Statistics Operation Done interrrupt Enable 
+ *   GT_VTU_PROB - VLAN Problem/Violation Interrupt Enable
+ *   GT_VTU_DONE - VALN Table Operation Done Interrupt Enable
+ *   GT_ATU_PROB - ATU Problem/Violation Interrupt Enable, for Gigabit Switch
+ *   GT_ATU_FULL - ATU full interrupt enable, for Fast Ethernet Switch
+ *   GT_ATU_DONE - ATU Done interrupt enable.
+ *   GT_PHY_INT  - PHY interrupt enable, for Fast Ethernet Switch
+ *   GT_EE_INT   - EEPROM Done interrupt enable.
+ */
+#define GT_AVB_INT           	0x100
+#define GT_DEVICE_INT           0x80
+#define GT_STATS_DONE           0x40
+#define GT_VTU_PROB             0x20
+#define GT_VTU_DONE             0x10
+#define GT_ATU_PROB 		0x8
+#define GT_ATU_FULL 		0x8
+#define GT_ATU_DONE		0x4
+#define GT_PHY_INTERRUPT	0x2		/* Device may not support PHY Int. Please refer to datasheet. */
+#define GT_EE_INTERRUPT		0x1
+
+#define GT_INT_MASK			\
+		(GT_AVB_INT | GT_DEVICE_INT | GT_STATS_DONE | GT_VTU_PROB | GT_VTU_DONE | GT_ATU_FULL | 	\
+		GT_ATU_DONE | GT_PHY_INTERRUPT | GT_EE_INTERRUPT)
+#define GT_NO_INTERNAL_PHY_INT_MASK		\
+		(GT_AVB_INT | GT_DEVICE_INT | GT_STATS_DONE | GT_VTU_PROB | GT_VTU_DONE | GT_ATU_PROB | 	\
+		GT_ATU_DONE | GT_EE_INTERRUPT)
+
+
+/*
+ *  typedef: struct GT_DEV_EVENT
+ *
+ *  Description: Device interrupt status
+ *
+ *  Fields:
+ *      event     - Device Interrupts to be enabled
+ *					GT_DEV_INT_WATCHDOG, GT_DEV_INT_JAMLIMIT,
+ *					GT_DEV_INT_DUPLEX_MISMATCH, and/or GT_DEV_INT_SERDES_LINK
+ *      portList  - SERDES port list where GT_DEV_INT_SERDES_LINK interrupt needs
+ *					to be asserted. It's in vector format, Bit 10 is for port 10, 
+ *					Bit 9 is for port 9, etc.
+ *					valid only if GT_DEV_INT_SERDES_LINK bit is set.
+ *      phyList   - Phy list where GT_DEV_INT_PHY interrupt needs to be asserted.
+ *					It's in vector format, Bit 0 is for port 0, 
+ *					Bit 1 is for port 1, etc.
+ *					valid only if GT_DEV_INT_PHY bit is set.
+ */
+typedef struct
+{
+	GT_U32		event;
+	GT_U32		portList;
+	GT_U32		phyList;
+} GT_DEV_EVENT;
+
+
+/*
+ *  typedef: struct GT_DEV_INT_STATUS
+ *
+ *  Description: Device interrupt status
+ *
+ *  Fields:
+ *      intCause  - Device Interrupt Cause
+ *					GT_DEV_INT_WATCHDOG, GT_DEV_INT_JAMLIMIT,
+ *					GT_DEV_INT_DUPLEX_MISMATCH, and/or GT_DEV_INT_SERDES_LINK
+ *		port	  - logical port where GT_DEV_INT_DUPLEX_MISMATCH occurred.
+ *					valid only if GT_DEV_INT_DUPLEX_MISMATCH is set.
+ *      linkInt   - SERDES port list where GT_DEV_INT_SERDES_LINK interrupt is
+ *					asserted. It's in vector format, Bit 10 is for port 10, 
+ *					Bit 9 is for port 9, etc.
+ *					valid only if GT_DEV_INT_SERDES_LINK bit is set.
+ *					These bits are only valid of the port that is in 1000Base-X mode.
+ */
+typedef struct
+{
+	GT_U32		devIntCause;
+	GT_LPORT	port;
+	GT_U32		linkInt;
+	GT_U32		phyInt;
+} GT_DEV_INT_STATUS;
+
+
+/*
+* GT_DEVICE_INT
+*
+* Description: Enumeration of Device interrupt
+*	GT_DEV_INT_WATCHDOG		- WatchDog event interrupt (WatchDog event can be
+*							  configured with gwdSetEvent API)
+*	GT_DEV_INT_JAMLIMIT		- any of the ports detect an Ingress Jam Limit violation
+*							  (gprtSetPauseLimitIn API)
+*	GT_DEV_INT_DUPLEX_MISMATCH	- any of the ports detect a duplex mismatch 
+*							  (i.e., the local port is in half duplex mode while 
+*							  the link partner is in full duplex mode)
+*	GT_DEV_INT_SERDES_LINK	- SERDES link chage interrupt.
+*							  An interrupt occurs when a SERDES port changes link 
+*							  status (link up or link down)
+*/
+
+#define GT_DEV_INT_WATCHDOG			0x8
+#define GT_DEV_INT_JAMLIMIT			0x4
+#define GT_DEV_INT_DUPLEX_MISMATCH	0x2
+#define GT_DEV_INT_SERDES_LINK		0x1
+#define GT_DEV_INT_PHY				0x10
+
+/*
+* GT_WATCHDOG_EVENT
+*
+* Description: Enumeration of WatchDog event
+*		GT_WD_QC  - Queue Controller Watch Dog enable.
+*					When enabled, the QC's watch dog circuit checks for link
+*					list errors and any errors found in the QC.
+*		GT_WD_EGRESS - Egress Watch Dog enable.
+*					When enabled, each port's egress circuit checks for problems
+*					between the port and the Queue Controller.
+*		GT_WD_FORCE - Force a Watch Dog event.
+*/
+
+#define GT_WD_QC		0x1
+#define GT_WD_EGRESS	0x2
+#define GT_WD_FORCE		0x4
+
+
+/*
+* typedef: struct GT_WD_EVENT_HISTORY
+*
+* Description: WatchDog Event History (cleared only by a hardware reset)
+*		wdEvent   - When it's set to GT_TRUE, some enabled Watch Dog event occurred.
+*					The following events are possible:
+*						QC WatchDog Event (GT_WD_QC)
+*						Egress WatchDog Event (GT_WD_EGRESS)
+*						Forced WatchDog Event (GT_WD_FORCE)
+*		egressEvent-If any port's egress logic detects an egress watch dog issue,
+*					this field is set to GT_TRUE, regardless of the enabling GT_WD_EGRESS
+*					event.
+*/
+typedef struct
+{
+	GT_BOOL	wdEvent;
+	GT_BOOL egressEvent;
+} GT_WD_EVENT_HISTORY;
+
+
+/*
+* typedef: enum GT_PHY_INT
+*
+* Description: Enumeration of PHY interrupt
+*/
+
+#define GT_SPEED_CHANGED 		0x4000
+#define GT_DUPLEX_CHANGED		0x2000
+#define GT_PAGE_RECEIVED		0x1000
+#define GT_AUTO_NEG_COMPLETED	0x800
+#define GT_LINK_STATUS_CHANGED	0x400
+#define GT_SYMBOL_ERROR			0x200
+#define GT_FALSE_CARRIER		0x100
+#define GT_FIFO_FLOW			0x80
+#define GT_CROSSOVER_CHANGED	0x40
+#define GT_POLARITY_CHANGED		0x2
+#define GT_JABBER				0x1
+
+#define GT_AUTO_NEG_ERROR		0x8000
+#define GT_DOWNSHIFT_DETECT		0x20
+#define GT_ENERGY_DETECT		0x10
+
+/*
+* typedef: enum GT_PHY_AUTO_MODE
+*
+* Description: Enumeration of Autonegotiation mode.
+*	Auto for both speed and duplex.
+*	Auto for speed only and Full duplex.
+*	Auto for speed only and Half duplex. (1000Mbps is not supported)
+*	Auto for duplex only and speed 1000Mbps.
+*	Auto for duplex only and speed 100Mbps.
+*	Auto for duplex only and speed 10Mbps.
+*	1000Mbps Full duplex.
+*	100Mbps Full duplex.
+*	100Mbps Half duplex.
+*	10Mbps Full duplex.
+*	10Mbps Half duplex.
+*/
+
+typedef enum
+{
+	SPEED_AUTO_DUPLEX_AUTO,
+	SPEED_1000_DUPLEX_AUTO,
+	SPEED_100_DUPLEX_AUTO,
+	SPEED_10_DUPLEX_AUTO,
+	SPEED_AUTO_DUPLEX_FULL,
+	SPEED_AUTO_DUPLEX_HALF,
+	SPEED_1000_DUPLEX_FULL,
+	SPEED_1000_DUPLEX_HALF,
+	SPEED_100_DUPLEX_FULL,
+	SPEED_100_DUPLEX_HALF,
+	SPEED_10_DUPLEX_FULL,
+	SPEED_10_DUPLEX_HALF
+}GT_PHY_AUTO_MODE;
+
+
+/*
+* typedef: enum GT_PHY_PAUSE_MODE
+*
+* Description: Enumeration of Pause Mode in the Phy.
+*
+* Enumerations:
+*	GT_PHY_NO_PAUSE		- disable pause
+*	GT_PHY_PAUSE		- support pause
+*	GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*	GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*/
+typedef enum
+{
+	GT_PHY_NO_PAUSE = 0,
+	GT_PHY_PAUSE,
+	GT_PHY_ASYMMETRIC_PAUSE,
+	GT_PHY_BOTH_PAUSE
+} GT_PHY_PAUSE_MODE;
+
+
+/*
+* typedef: enum GT_PHY_SPEED
+*
+* Description: Enumeration of Phy Speed
+*
+* Enumerations:
+*	PHY_SPEED_10_MBPS   - 10Mbps
+*	PHY_SPEED_100_MBPS	- 100Mbps
+*	PHY_SPEED_1000_MBPS - 1000Mbps
+*/
+typedef enum
+{
+	PHY_SPEED_10_MBPS,
+	PHY_SPEED_100_MBPS,
+	PHY_SPEED_1000_MBPS
+} GT_PHY_SPEED;
+
+/*
+* typedef: enum GT_PHY_LOOPBACK_MODE
+*
+* Description: Enumeration of Phy loopback mode
+*
+* Enumerations:
+	PHY_INTERNAL_LOOPBACK: internal loopback mode
+	PHY_EXTERNAL_LOOPBACK:external loopback mode
+*/
+typedef enum
+{
+	PHY_INTERNAL_LOOPBACK,
+	PHY_EXTERNAL_LOOPBACK
+} GT_PHY_LOOPBACK_MODE;
+
+/*
+* typedef: enum GT_MIRROR_MODE
+*
+* Description: Enumeration of Phy Speed
+*
+* Enumerations:
+*	SW_MIRROR_INGRESS   - mirror ingress packets to destination port
+*	SW_MIRROR_EGRESS	- mirror egress packets to destination port
+*/
+typedef enum
+{
+	SW_MIRROR_INGRESS,
+	SW_MIRROR_EGRESS
+} GT_MIRROR_MODE;
+
+
+/*
+* typedef: enum GT_SERDES_MODE
+*
+* Description: Enumeration of Serdes mode
+*
+* Enumerations:
+*	PHY_SERDES_100FX	 - 100 FX
+*	PHY_SERDES_1000X	 - 1000 X
+*	PHY_SERDES_SGMII_PHY - SGMII PHY
+*	PHY_SERDES_SGMII_MAC - SGMII MAC
+*/
+typedef enum
+{
+	PHY_SERDES_100FX = 0,
+	PHY_SERDES_1000X,	
+	PHY_SERDES_SGMII_PHY,
+	PHY_SERDES_SGMII_MAC
+} GT_SERDES_MODE;
+
+
+/*
+* typedef: enum GT_EDETECT_MODE
+*
+* Description: Enumeration of Energy Detect mode
+*
+* Enumerations:
+*	GT_EDETECT_OFF		- Energy Detect disabled
+*	GT_EDETECT_SENSE_PULSE	- Energy Detect enabled with sense and pulse
+*	GT_EDETECT_SENSE	- Energy Detect enabled only with sense
+*/
+typedef enum
+{
+	GT_EDETECT_OFF = 0,
+	GT_EDETECT_SENSE_PULSE,
+	GT_EDETECT_SENSE
+} GT_EDETECT_MODE;
+
+/*
+ * typedef: enum GT_INGRESS_MODE
+ *
+ * Description: Enumeration of the port ingress mode.
+ *
+ * Enumerations:
+ *   GT_UNMODIFY_INGRESS - frames are receive unmodified.
+ *   GT_TRAILER_INGRESS  - all frames are received with trailer.
+ *   GT_UNTAGGED_INGRESS  - remove tag on receive (for double tagging).
+ *   GT_CPUPORT_INGRESS - no trailer. used to identify the CPU port for IGMP/MLD Snooping
+ */
+typedef enum
+{
+	GT_UNMODIFY_INGRESS = 0,  /* 0x00 */
+	GT_TRAILER_INGRESS,       /* 0x01 */
+	GT_UNTAGGED_INGRESS,      /* 0x10 */
+	GT_CPUPORT_INGRESS        /* 0x11 */
+} GT_INGRESS_MODE;
+
+
+/*
+ * typedef: enum GT_EGRESS_FLOOD
+ *
+ * Description: Enumeration of the port ingress mode.
+ *
+ * Enumerations:
+ *   GT_BLOCK_EGRESS_UNKNOWN - do not egress frame with unknown DA
+ *   GT_BLOCK_EGRESS_UNKNOWN_MULTICAST - do not egress frame with unknown multicast DA
+ *   GT_BLOCK_EGRESS_UNKNOWN_UNIICAST - do not egress frame with unknown unicast DA
+ *   GT_BLOCK_EGRESS_NONE - egress all frames with unknown DA
+ */
+typedef enum
+{
+	GT_BLOCK_EGRESS_UNKNOWN = 0,
+	GT_BLOCK_EGRESS_UNKNOWN_MULTICAST,
+	GT_BLOCK_EGRESS_UNKNOWN_UNICAST,
+	GT_BLOCK_EGRESS_NONE
+} GT_EGRESS_FLOOD;
+
+
+/*
+ *  typedef: enum GT_MC_RATE
+ *
+ *  Description: Enumeration of the port ingress mode.
+ *
+ *  Enumerations:
+ *      GT_MC_3_PERCENT_RL   - multicast rate is limited to 3 percent.
+ *      GT_MC_6_PERCENT_RL   - multicast rate is limited to 6 percent.
+ *      GT_MC_12_PERCENT_RL  - multicast rate is limited to 12 percent.
+ *      GT_MC_100_PERCENT_RL - unlimited multicast rate.
+ */
+typedef enum
+{
+	GT_MC_3_PERCENT_RL = 0,
+	GT_MC_6_PERCENT_RL,
+	GT_MC_12_PERCENT_RL,
+	GT_MC_100_PERCENT_RL,
+} GT_MC_RATE;
+
+
+/*
+ *  typedef: enum GT_INGRESS_RATE_MODE
+ *
+ *  Description: Enumeration of the port ingress rate limit mode.
+ *
+ *  Enumerations:
+ *      GT_RATE_PRI_BASE   - Priority based rate limiting
+ *		GT_RATE_BURST_BASE - Burst Size based rate limiting
+ */
+typedef enum
+{
+	GT_RATE_PRI_BASE = 0,
+	GT_RATE_BURST_BASE
+} GT_INGRESS_RATE_MODE;
+
+
+/*
+ *  typedef: enum GT_PORT_SCHED_MODE
+ *
+ *  Description: Enumeration of port scheduling mode
+ *
+ *  Fields:
+ *	 	GT_PORT_SCHED_WEIGHTED_RRB - use 8,4,2,1 weighted fair scheduling
+ *	 	GT_PORT_SCHED_STRICT_PRI - use a strict priority scheme
+ *	 	GT_PORT_SCHED_STRICT_PRI3 - use a strict for priority 3 and weighted 
+ *									round robin for the priority 2,1,and 0
+ *	 	GT_PORT_SCHED_STRICT_PRI2_3 - use a strict for priority 2,3 and weighted 
+ *									round robin for the priority 1,and 0
+ *
+ *  Comment:
+ */
+typedef enum
+{
+	GT_PORT_SCHED_WEIGHTED_RRB = 0,
+	GT_PORT_SCHED_STRICT_PRI,
+	GT_PORT_SCHED_STRICT_PRI3,
+	GT_PORT_SCHED_STRICT_PRI2_3
+} GT_PORT_SCHED_MODE;
+
+
+/*
+ *  typedef: struct GT_PORT_STAT
+ *
+ *  Description: port statistic struct.
+ *
+ *  Fields:
+ *      rxCtr   - port receive counter.
+ *      txCtr   - port transmit counter.
+ *      dropped - dropped frame counter.
+ *
+ *  Comment:
+ *		dropped frame counter is supported by only limited devices.
+ *		At this moment, 88E6061/88E6065 are the devices supporting
+ *		dropped frame counter.
+ */
+typedef struct
+{
+	GT_U16  rxCtr;
+	GT_U16  txCtr;
+	GT_U16  dropped;
+} GT_PORT_STAT;
+
+/*
+ *  typedef: struct GT_PORT_STAT2
+ *
+ *  Description: port statistic struct.
+ *
+ *  Fields:
+ *      inDiscardLo - InDiscards Low Frame Counter
+ *      inDiscardHi - InDiscards High Frame Counter
+ *      inFiltered  - InFiltered Frame Counter
+ *      outFiltered - OutFiltered Frame Counter
+ *
+ *  Comment:
+ */
+typedef struct
+{
+	GT_U16  inDiscardLo;
+	GT_U16  inDiscardHi;
+	GT_U16  inFiltered;
+	GT_U16  outFiltered;
+} GT_PORT_STAT2;
+
+
+/*
+ **  typedef: struct GT_PORT_Q_COUNTERS
+ **
+ **  Description: port queue statistic struct.
+ **
+ **  Fields:
+ **      OutQ_Size - port egress queue size coi
+ **      Rsv_Size  - ingress reserved e counter
+ **
+ **/
+typedef struct
+{
+	GT_U16  OutQ_Size;
+	GT_U16  Rsv_Size;
+} GT_PORT_Q_STAT;
+
+/*
+ * typedef: enum GT_CTR_MODE
+ *
+ * Description: Enumeration of the port counters mode.
+ *
+ * Enumerations:
+ *   GT_CTR_ALL    - In this mode the counters counts Rx receive and transmit
+ *                   frames.
+ *   GT_CTR_ERRORS - In this mode the counters counts Rx Errors and collisions.
+ */
+typedef enum
+{
+	GT_CTR_ALL = 0,
+	GT_CTR_ERRORS,
+} GT_CTR_MODE;
+
+typedef struct _GT_QD_DEV GT_QD_DEV;
+
+/*
+ * semaphore related definitions.
+ * User Applications may register Semaphore functions using following definitions
+ */
+typedef enum
+{
+	GT_SEM_EMPTY,
+	GT_SEM_FULL
+} GT_SEM_BEGIN_STATE;
+
+typedef GT_SEM (*FGT_SEM_CREATE)(
+						GT_SEM_BEGIN_STATE state);
+typedef GT_STATUS (*FGT_SEM_DELETE)(
+						GT_SEM semId);
+typedef GT_STATUS (*FGT_SEM_TAKE)(
+						GT_SEM semId, GT_U32 timOut);
+typedef GT_STATUS (*FGT_SEM_GIVE)(
+						GT_SEM semId);
+
+typedef struct
+{
+	FGT_SEM_CREATE	semCreate; 	/* create semapore */
+	FGT_SEM_DELETE	semDelete; 	/* delete the semapore */
+	FGT_SEM_TAKE	semTake;	/* try to get a semapore */
+	FGT_SEM_GIVE	semGive;	/* return semaphore */
+}GT_SEM_ROUTINES;
+
+/*
+ * definitions for registering MII access functions.
+ *
+*/
+typedef GT_BOOL (*FGT_READ_MII)(
+						GT_QD_DEV*   dev,
+						unsigned int phyAddr, 
+						unsigned int miiReg, 
+						unsigned int* value);
+typedef GT_BOOL (*FGT_WRITE_MII)(
+						GT_QD_DEV*   dev,
+						unsigned int phyAddr, 
+						unsigned int miiReg, 
+						unsigned int value);
+typedef GT_BOOL (*FGT_INT_HANDLER)(
+						GT_QD_DEV*   dev,
+						GT_U16*);
+
+typedef struct _BSP_FUNCTIONS
+{
+	FGT_READ_MII 	readMii;	/* read MII Registers */
+	FGT_WRITE_MII 	writeMii;	/* write MII Registers */
+	FGT_SEM_CREATE	semCreate; 	/* create semapore */
+	FGT_SEM_DELETE	semDelete; 	/* delete the semapore */
+	FGT_SEM_TAKE	semTake;	/* try to get a semapore */
+	FGT_SEM_GIVE	semGive;	/* return semaphore */
+}BSP_FUNCTIONS;
+
+
+/*
+ *	Type definition for MIB counter operation
+*/
+typedef enum 
+{
+	STATS_FLUSH_ALL,		/* Flush all counters for all ports */
+	STATS_FLUSH_PORT,		/* Flush all counters for a port */
+	STATS_READ_COUNTER,		/* Read a specific counter from a port */
+	STATS_READ_REALTIME_COUNTER,	/* Read a realtime counter from a port */
+	STATS_READ_ALL			/* Read all counters from a port */
+
+} GT_STATS_OPERATION;
+
+typedef struct _GT_STATS_COUNTER_SET
+{
+	GT_U32	InUnicasts;
+	GT_U32	InBroadcasts;
+	GT_U32	InPause;
+	GT_U32	InMulticasts;
+	GT_U32	InFCSErr;
+	GT_U32	AlignErr;
+	GT_U32	InGoodOctets;
+	GT_U32	InBadOctets;
+	GT_U32	Undersize;
+	GT_U32	Fragments;
+	GT_U32	In64Octets;		/* 64 Octets */
+	GT_U32	In127Octets;	/* 65 to 127 Octets */
+	GT_U32	In255Octets;	/* 128 to 255 Octets */
+	GT_U32	In511Octets;	/* 256 to 511 Octets */
+	GT_U32	In1023Octets;	/* 512 to 1023 Octets */
+	GT_U32	InMaxOctets;	/* 1024 to Max Octets */
+	GT_U32	Jabber;
+	GT_U32	Oversize;
+	GT_U32	InDiscards;
+	GT_U32	Filtered;
+	GT_U32	OutUnicasts;
+	GT_U32	OutBroadcasts;
+	GT_U32	OutPause;
+	GT_U32	OutMulticasts;
+	GT_U32	OutFCSErr;
+	GT_U32	OutGoodOctets;
+	GT_U32	Out64Octets;	/* 64 Octets */
+	GT_U32	Out127Octets;	/* 65 to 127 Octets */
+	GT_U32	Out255Octets;	/* 128 to 255 Octets */
+	GT_U32	Out511Octets;	/* 256 to 511 Octets */
+	GT_U32	Out1023Octets;	/* 512 to 1023 Octets */
+	GT_U32	OutMaxOctets;	/* 1024 to Max Octets */
+	GT_U32	Collisions;
+	GT_U32	Late;
+	GT_U32	Excessive;
+	GT_U32	Multiple;
+	GT_U32	Single;
+	GT_U32	Deferred;
+	GT_U32	OutDiscards;
+
+} GT_STATS_COUNTER_SET;
+
+
+typedef enum
+{
+	STATS_InUnicasts = 0,
+	STATS_InBroadcasts,
+	STATS_InPause,
+	STATS_InMulticasts,
+	STATS_InFCSErr,
+	STATS_AlignErr,
+	STATS_InGoodOctets,
+	STATS_InBadOctets,
+	STATS_Undersize,
+	STATS_Fragments,
+	STATS_In64Octets,
+	STATS_In127Octets,
+	STATS_In255Octets,
+	STATS_In511Octets,
+	STATS_In1023Octets,
+	STATS_InMaxOctets,
+	STATS_Jabber,
+	STATS_Oversize,
+	STATS_InDiscards,
+	STATS_Filtered,
+	STATS_OutUnicasts,
+	STATS_OutBroadcasts,
+	STATS_OutPause,
+	STATS_OutMulticasts,
+	STATS_OutFCSErr,
+	STATS_OutGoodOctets,
+	STATS_Out64Octets,
+	STATS_Out127Octets,
+	STATS_Out255Octets,
+	STATS_Out511Octets,
+	STATS_Out1023Octets,
+	STATS_OutMaxOctets,
+	STATS_Collisions,
+	STATS_Late,
+	STATS_Excessive,
+	STATS_Multiple,
+	STATS_Single,
+	STATS_Deferred,
+	STATS_OutDiscards
+
+} GT_STATS_COUNTERS;
+/*
+ * typedef: enum GT_HISTOGRAM_MODE
+ *
+ * Description: Enumeration of the histogram counters mode.
+ *
+ * Enumerations:
+ *   GT_COUNT_RX_ONLY - In this mode, Rx Histogram Counters are counted.
+ *   GT_COUNT_TX_ONLY - In this mode, Tx Histogram Counters are counted.
+ *   GT_COUNT_RX_TX   - In this mode, Rx and Tx Histogram Counters are counted.
+ */
+typedef enum
+{
+	GT_COUNT_RX_ONLY = 0,
+	GT_COUNT_TX_ONLY,
+	GT_COUNT_RX_TX
+} GT_HISTOGRAM_MODE;
+
+/*
+	Counter set 2 is used by 88E6183
+*/
+typedef struct _GT_STATS_COUNTER_SET2
+{
+	GT_U32	InGoodOctetsHi;
+	GT_U32	InGoodOctetsLo;
+	GT_U32	InBadOctets;
+	GT_U32	OutDiscards;
+	GT_U32	InGoodFrames;
+	GT_U32	InBadFrames;
+	GT_U32	InBroadcasts;
+	GT_U32	InMulticasts;
+	/* 
+		Histogram Counters : Rx Only, Tx Only, or both Rx and Tx 
+		(refer to Histogram Mode) 
+	*/
+	GT_U32	Octets64;		/* 64 Octets */
+	GT_U32	Octets127;		/* 65 to 127 Octets */
+	GT_U32	Octets255;		/* 128 to 255 Octets */
+	GT_U32	Octets511;		/* 256 to 511 Octets */
+	GT_U32	Octets1023;		/* 512 to 1023 Octets */
+	GT_U32	OctetsMax;		/* 1024 to Max Octets */
+	GT_U32	OutOctetsHi;
+	GT_U32	OutOctetsLo;
+	GT_U32	OutFrames;
+	GT_U32	Excessive;
+	GT_U32	OutMulticasts;
+	GT_U32	OutBroadcasts;
+	GT_U32	InBadMACCtrl;
+
+	GT_U32	OutPause;
+	GT_U32	InPause;
+	GT_U32	InDiscards;
+	GT_U32	Undersize;
+	GT_U32	Fragments;
+	GT_U32	Oversize;
+	GT_U32	Jabber;
+	GT_U32	MACRcvErr;
+	GT_U32	InFCSErr;
+	GT_U32	Collisions;
+	GT_U32	Late;
+
+} GT_STATS_COUNTER_SET2;
+
+
+typedef enum
+{
+	STATS2_InGoodOctetsHi = 0,
+	STATS2_InGoodOctetsLo,
+	STATS2_InBadOctets,
+	
+	STATS2_OutDiscards,
+	STATS2_InGoodFrames,
+	STATS2_InBadFrames,
+	STATS2_InBroadcasts,
+	STATS2_InMulticasts,
+	STATS2_64Octets,
+	STATS2_127Octets,
+	STATS2_255Octets,
+	STATS2_511Octets,
+	STATS2_1023Octets,
+	STATS2_MaxOctets,
+	STATS2_OutOctetsHi,
+	STATS2_OutOctetsLo,
+	STATS2_OutFrames,
+	STATS2_Excessive,
+	STATS2_OutMulticasts,
+	STATS2_OutBroadcasts,
+	STATS2_InBadMACCtrl,
+	STATS2_OutPause,
+	STATS2_InPause,
+	STATS2_InDiscards,
+	STATS2_Undersize,
+	STATS2_Fragments,
+	STATS2_Oversize,
+	STATS2_Jabber,
+	STATS2_MACRcvErr,
+	STATS2_InFCSErr,
+	STATS2_Collisions,
+	STATS2_Late
+
+} GT_STATS_COUNTERS2;
+
+/*
+	Counter set 3 is used by 88E6093 and 88E6065
+*/
+typedef struct _GT_STATS_COUNTER_SET3
+{
+	GT_U32	InGoodOctetsLo;	/* offset 0 */
+	GT_U32	InGoodOctetsHi;	/* offset 1, not supported by 88E6065 */
+	GT_U32	InBadOctets;		/* offset 2 */
+	GT_U32	OutFCSErr;			/* offset 3 */
+	GT_U32	InUnicasts;			/* offset 4 */
+	GT_U32	Deferred;			/* offset 5 */
+	GT_U32	InBroadcasts;		/* offset 6 */
+	GT_U32	InMulticasts;		/* offset 7 */
+	/* 
+		Histogram Counters : Rx Only, Tx Only, or both Rx and Tx 
+		(refer to Histogram Mode) 
+	*/
+	GT_U32	Octets64;		/* 64 Octets, offset 8 */
+	GT_U32	Octets127;		/* 65 to 127 Octets, offset 9 */
+	GT_U32	Octets255;		/* 128 to 255 Octets, offset 10 */
+	GT_U32	Octets511;		/* 256 to 511 Octets, offset 11 */
+	GT_U32	Octets1023;		/* 512 to 1023 Octets, offset 12 */
+	GT_U32	OctetsMax;		/* 1024 to Max Octets, offset 13 */
+	GT_U32	OutOctetsLo;	/* offset 14 */
+	GT_U32	OutOctetsHi;	/* offset 15, not supported by 88E6065 */
+	GT_U32	OutUnicasts;	/* offset 16 */
+	GT_U32	Excessive;		/* offset 17 */
+	GT_U32	OutMulticasts;	/* offset 18 */
+	GT_U32	OutBroadcasts;	/* offset 19 */
+	GT_U32	Single;			/* offset 20 */
+
+	GT_U32	OutPause;		/* offset 21 */
+	GT_U32	InPause;			/* offset 22 */
+	GT_U32	Multiple;		/* offset 23 */
+	GT_U32	Undersize;		/* offset 24 */
+	GT_U32	Fragments;		/* offset 25 */
+	GT_U32	Oversize;		/* offset 26 */
+	GT_U32	Jabber;			/* offset 27 */
+	GT_U32	InMACRcvErr;	/* offset 28 */
+	GT_U32	InFCSErr;		/* offset 29 */
+	GT_U32	Collisions;		/* offset 30 */
+	GT_U32	Late;				/* offset 31 */
+
+} GT_STATS_COUNTER_SET3;
+
+/*
+	PM Counter  is used by 88E6093 and 88E6065
+*/
+typedef struct _GT_STATS_PM_COUNTER
+{
+      GT_STATS_COUNTER_SET3  Counterset3;
+      GT_PORT_STAT2  	 Counterstat2;
+
+} GT_STATS_PM_COUNTER;
+
+
+
+typedef enum
+{
+	STATS3_InGoodOctetsLo = 0,
+	STATS3_InGoodOctetsHi,
+	STATS3_InBadOctets,
+	
+	STATS3_OutFCSErr,
+	STATS3_InUnicasts,
+	STATS3_Deferred,			/* offset 5 */
+	STATS3_InBroadcasts,
+	STATS3_InMulticasts,
+	STATS3_64Octets,
+	STATS3_127Octets,
+	STATS3_255Octets,			/* offset 10 */
+	STATS3_511Octets,
+	STATS3_1023Octets,
+	STATS3_MaxOctets,
+	STATS3_OutOctetsLo,
+	STATS3_OutOctetsHi,
+	STATS3_OutUnicasts,		/* offset 16 */
+	STATS3_Excessive,
+	STATS3_OutMulticasts,
+	STATS3_OutBroadcasts,
+	STATS3_Single,
+	STATS3_OutPause,
+	STATS3_InPause,
+	STATS3_Multiple,
+	STATS3_Undersize,			/* offset 24 */
+	STATS3_Fragments,
+	STATS3_Oversize,
+	STATS3_Jabber,
+	STATS3_InMACRcvErr,
+	STATS3_InFCSErr,
+	STATS3_Collisions,
+	STATS3_Late					/* offset 31 */
+
+} GT_STATS_COUNTERS3;
+
+
+
+/*
+ * typedef: struct GT_1000T_MASTER_SLAVE
+ *
+ * Description: 1000Base-T Master/Slave Configuration
+ *
+ * Fields:
+ *      autoConfig   - GT_TRUE for auto-config, GT_FALSE for manual setup.
+ *      masterPrefer - GT_TRUE if Master configuration is preferred.
+ *
+ */
+typedef struct _GT_1000T_MASTER_SLAVE
+{
+	GT_BOOL	autoConfig;
+	GT_BOOL masterPrefer;
+} GT_1000T_MASTER_SLAVE;
+
+
+#define GT_MDI_PAIR_NUM     	4	/* (1,2),(3,6),(4,5),(7,8) */
+#define GT_CHANNEL_PAIR_NUM     2	/* (channel A,B),(channel C,D) */
+
+
+/*
+ * typedef: enum GT_PHY_LINK_STATUS
+ *
+ * Description: Enumeration of Link Status
+ *
+ * Enumerations:
+ *		GT_PHY_LINK_OFF		- No Link
+ *		GT_PHY_LINK_COPPER	- Link on Copper
+ *		GT_PHY_LINK_FIBER	- Link on Fiber
+ */
+typedef enum
+{
+	GT_PHY_LINK_OFF = 0,
+	GT_PHY_LINK_COPPER = 1,
+	GT_PHY_LINK_FIBER = 2
+} GT_PHY_LINK_STATUS;
+
+
+/* Definition for packet generator */
+
+/* Payload */
+typedef enum
+{
+	GT_PG_PAYLOAD_RANDOM = 0,	/* Pseudo-random */
+	GT_PG_PAYLOAD_5AA5		/* 5A,A5,5A,A5,... */
+} GT_PG_PAYLOAD;
+
+/* Length */
+typedef enum
+{
+	GT_PG_LENGTH_64 = 0,		/* 64 bytes */
+	GT_PG_LENGTH_1514
+} GT_PG_LENGTH;
+
+/* Error */
+typedef enum
+{
+	GT_PG_TX_NORMAL = 0,		/* No Error */
+	GT_PG_TX_ERROR			/* Tx packets with CRC error and Symbol error */
+} GT_PG_TX;
+
+/* Structure for packet generator */
+typedef struct
+{
+	GT_PG_PAYLOAD  payload;
+	GT_PG_LENGTH   length;
+	GT_PG_TX       tx;
+} GT_PG;
+
+
+/*
+ * typedef: enum GT_TEST_STATUS
+ *
+ * Description: Enumeration of VCT test status
+ *
+ * Enumerations:
+ *      GT_TEST_FAIL    - virtual cable test failed.
+ *      GT_NORMAL_CABLE - normal cable.
+ *      GT_IMPEDANCE_MISMATCH - impedance mismatch.
+ *      GT_OPEN_CABLE   - open in cable.
+ *      GT_SHORT_CABLE  - short in cable.
+ *
+ */
+typedef enum
+{
+	GT_TEST_FAIL,
+	GT_NORMAL_CABLE,
+	GT_IMPEDANCE_MISMATCH,
+	GT_OPEN_CABLE,
+	GT_SHORT_CABLE,
+} GT_TEST_STATUS;
+
+
+/*
+ * typedef: enum GT_NORMAL_CABLE_LEN
+ *
+ * Description: Enumeration for normal cable length
+ *
+ * Enumerations:
+ *      GT_LESS_THAN_50M - cable length less than 50 meter.
+ *      GT_50M_80M       - cable length between 50 - 80 meter.
+ *      GT_80M_110M      - cable length between 80 - 110 meter.
+ *      GT_110M_140M     - cable length between 110 - 140 meter.
+ *      GT_MORE_THAN_140 - cable length more than 140 meter.
+ *      GT_UNKNOWN_LEN   - unknown length.
+ *
+ */
+typedef enum
+{
+	GT_LESS_THAN_50M,
+	GT_50M_80M,
+	GT_80M_110M,
+	GT_110M_140M,
+	GT_MORE_THAN_140,
+	GT_UNKNOWN_LEN,
+
+} GT_NORMAL_CABLE_LEN;
+
+
+/*
+ * typedef: enum GT_CABLE_LEN
+ *
+ * Description: Enumeration cable length
+ *
+ * Enumerations:
+ *      normCableLen - cable lenght for normal cable.
+ *      errCableLen  - for cable failure the estimate fault distance in meters.
+ *
+ */
+typedef union
+{
+	GT_NORMAL_CABLE_LEN normCableLen;
+	GT_U8               errCableLen;
+
+} GT_CABLE_LEN;
+
+/*
+ * typedef: struct GT_CABLE_STATUS
+ *
+ * Description: virtual cable diagnostic status per MDI pair.
+ *
+ * Fields:
+ *      cableStatus - VCT cable status.
+ *      cableLen    - VCT cable length.
+ *	phyType	    - type of phy (100M phy or Gigabit phy)
+ */
+typedef struct
+{
+	GT_TEST_STATUS  cableStatus[GT_MDI_PAIR_NUM];
+	GT_CABLE_LEN    cableLen[GT_MDI_PAIR_NUM];
+	GT_U16	    phyType;
+
+} GT_CABLE_STATUS;
+
+
+/*
+ * typedef: enum GT_CABLE_TYPE
+ *
+ * Description: Enumeration of Cable Type
+ *
+ * Enumerations:
+ *		GT_STRAIGHT_CABLE	_ straight cable
+ *      GT_CROSSOVER_CABLE 	- crossover cable
+ */
+typedef enum
+{
+	GT_STRAIGHT_CABLE,
+	GT_CROSSOVER_CABLE
+
+} GT_CABLE_TYPE;
+
+
+/*
+ * typedef: enum GT_RX_CHANNEL
+ *
+ * Description: Enumeration of Receiver Channel Assignment
+ *
+ * Enumerations:
+ *		GT_CHANNEL_A   - Channel A
+ *		GT_CHANNEL_B   - Channel B
+ *		GT_CHANNEL_C   - Channel C
+ *		GT_CHANNEL_D   - Channel D
+ */
+typedef enum
+{
+    GT_CHANNEL_A,
+    GT_CHANNEL_B,
+    GT_CHANNEL_C,
+    GT_CHANNEL_D
+} GT_RX_CHANNEL;
+
+
+/*
+ * typedef: enum GT_POLARITY_STATUS
+ *
+ * Description: Enumeration of polarity status
+ *
+ * Enumerations:
+ *		GT_POSITIVE	- positive polarity
+ *      GT_NEGATIVE	- negative polarity
+ */
+typedef enum
+{
+	GT_POSITIVE,
+	GT_NEGATIVE
+
+} GT_POLARITY_STATUS;
+
+
+/*
+ * typedef: struct GT_1000BT_EXTENDED_STATUS
+ *
+ * Description: Currently the 1000Base-T PCS can determine the cable polarity
+ * 		on pairs A,B,C,D; crossover on pairs A,B and C,D; and skew among 
+ *		the pares. These status enhance the capability of the virtual cable tester
+ *
+ * Fields:
+ *      isValid		- GT_TRUE if this structure have valid information, 
+ * 					  GT_FALSE otherwise.
+ *					  It is valid only if 1000BASE-T Link is up.
+ *      pairSwap    - GT_CROSSOVER_CABLE, if the cable is crossover,
+ *					  GT_STRAIGHT_CABLE, otherwise
+ *		pairPolarity- GT_POSITIVE, if polarity is positive,
+ *					  GT_NEGATIVE, otherwise
+ *		pairSkew	- pair skew in units of ns
+ */
+typedef struct
+{
+	GT_BOOL				isValid;
+	GT_CABLE_TYPE		pairSwap[GT_CHANNEL_PAIR_NUM];
+	GT_POLARITY_STATUS	pairPolarity[GT_MDI_PAIR_NUM];
+	GT_U32			    pairSkew[GT_MDI_PAIR_NUM];
+
+} GT_1000BT_EXTENDED_STATUS;
+
+
+/*
+ * typedef: struct GT_ADV_EXTENDED_STATUS
+ *
+ * Description: Currently the 1000Base-T PCS can determine the cable polarity
+ * 		on pairs A,B,C,D; crossover on pairs A,B and C,D; and skew among 
+ *		the pares. These status enhance the capability of the virtual cable tester
+ *
+ * Fields:
+ *      isValid		- GT_TRUE if this structure have valid information, 
+ * 					  GT_FALSE otherwise.
+ *					  It is valid only if 1000BASE-T Link is up.
+ *      pairSwap    - Receive channel assignement
+ *		pairPolarity- GT_POSITIVE, if polarity is positive,
+ *					  GT_NEGATIVE, otherwise
+ *		pairSkew	- pair skew in units of ns
+ *		cableLen	- cable length based on DSP
+ */
+typedef struct
+{
+    GT_BOOL            isValid;
+    GT_RX_CHANNEL      pairSwap[GT_MDI_PAIR_NUM];
+    GT_POLARITY_STATUS pairPolarity[GT_MDI_PAIR_NUM];
+    GT_U32             pairSkew[GT_MDI_PAIR_NUM];
+	GT_U32				cableLen[GT_MDI_PAIR_NUM];
+} GT_ADV_EXTENDED_STATUS;
+
+
+/*
+ * if isGigPhy in GT_CABLE_STATUS is not GT_TRUE, cableStatus and cableLen 
+ * will have only 2 pairs available.
+ * One is RX Pair and the other is TX Pair.
+ */
+#define MDI_RX_PAIR		0	/* cableStatus[0] or cableLen[0] */
+#define MDI_TX_PAIR		1	/* cableStatus[1] or cableLen[1] */
+
+/* definition for Phy Type */
+#define PHY_100M		0 /* 10/100M phy, E3082 or E3083 */
+#define PHY_1000M		1 /* Gigabit phy, the rest phys */
+#define PHY_10000M		2 /* 10 Gigabit phy, unused */
+#define PHY_1000M_B		3 /* Gigabit phy which needs work-around */
+#define PHY_1000M_MP	4 /* Gigabit phy with multiple page mode */
+
+
+/* Definition for Advance Virtual Cable Test */
+
+/*
+ * typedef: enum GT_ADV_VCT_TRANS_CHAN_SEL
+ *
+ * Description: Enumeration of Advanced VCT Transmitter channel select
+ *
+ * Enumerations:
+ *		GT_ADV_VCT_NO_CROSSPAIR - Transmitter channel select is 000
+ *		GT_ADV_VCT_CROSSPAIR    - Transmitter channelselect is 100/101/110/111
+ */
+typedef enum
+{
+	/* Advanced VCT Mode */
+    GT_ADV_VCT_TCS_NO_CROSSPAIR		= 0,
+    GT_ADV_VCT_TCS_CROSSPAIR_0		    = 0x4,
+    GT_ADV_VCT_TCS_CROSSPAIR_1		    = 0x5,
+    GT_ADV_VCT_TCS_CROSSPAIR_2		    = 0x6,
+    GT_ADV_VCT_TCS_CROSSPAIR_3		    = 0x7
+} GT_ADV_VCT_TRANS_CHAN_SEL;
+
+
+typedef enum
+{
+	/* Advanced VCT Mode */
+    GT_ADV_VCT_SAVG_2		= 0,
+    GT_ADV_VCT_SAVG_4		= 1,
+    GT_ADV_VCT_SAVG_8		= 2,
+    GT_ADV_VCT_SAVG_16		= 3,
+    GT_ADV_VCT_SAVG_32		= 4,
+    GT_ADV_VCT_SAVG_64		= 5,
+    GT_ADV_VCT_SAVG_128	= 6,
+    GT_ADV_VCT_SAVG_256	= 7
+} GT_ADV_VCT_SAMPLE_AVG;
+
+typedef enum
+{
+	/* Advanced VCT Mode */
+    GT_ADV_VCT_MAX_PEAK		=0x00,
+    GT_ADV_VCT_FIRST_PEAK		=0x01,
+} GT_ADV_VCT_MOD;
+
+
+typedef unsigned int GT_ADV_VCT_PEAKDET_HYST;
+
+/*
+ * typedef: enum GT_ADV_VCT_MODE
+ *
+ * Description: Enumeration of Advanced VCT Mode and Transmitter channel select
+ *
+ * Enumerations:
+ *      GT_ADV_VCT_FIRST_PEAK   - first peak above a certain threshold is reported.
+ *      GT_ADV_VCT_MAX_PEAK     - maximum peak above a certain threshold is reported.
+ *		GT_ADV_VCT_OFFSE	     - offset
+ *		GT_ADV_VCT_SAMPLE_POINT - sample point
+ *
+ *		GT_ADV_VCT_NO_CROSSPAIR - Transmitter channel select is 000
+ *		GT_ADV_VCT_CROSSPAIR    - Transmitter channelselect is 100/101/110/111
+ *   Example: mode = GT_ADV_VCT_FIRST_PEAK | GT_ADV_VCT_CROSSPAIR.
+ */
+typedef struct
+{
+    GT_ADV_VCT_MOD					mode;
+    GT_ADV_VCT_TRANS_CHAN_SEL      transChanSel;
+    GT_ADV_VCT_SAMPLE_AVG			sampleAvg;
+	GT_ADV_VCT_PEAKDET_HYST		peakDetHyst;
+} GT_ADV_VCT_MODE;
+
+
+/*
+ * typedef: enum GT_ADV_VCT_STATUS
+ *
+ * Description: Enumeration of Advanced VCT status
+ *
+ * Enumerations:
+ *      GT_ADV_VCT_FAIL     - advanced virtual cable test failed.
+ *                             cable lengh cannot be determined.
+ *      GT_ADV_VCT_NORMAL   - normal cable.
+ *                             cable lengh may not be determined.
+ *      GT_ADV_VCT_IMP_GREATER_THAN_115 - impedance mismatch > 115 ohms
+ *                             cable lengh is valid.
+ *      GT_ADV_VCT_IMP_LESS_THAN_85 - impedance mismatch < 85 ohms
+ *                             cable lengh is valid.
+ *      GT_ADV_VCT_OPEN 	 - cable open
+ *                             cable lengh is valid.
+ *      GT_ADV_VCT_SHORT 	 - cable shorted
+ *                             cable lengh is valid.
+ *      GT_ADV_VCT_CROSS_PAIR_SHORT - cross pair short.
+ *                             cable lengh for each channel is valid.
+ */
+typedef enum
+{
+    GT_ADV_VCT_FAIL,
+    GT_ADV_VCT_NORMAL,
+    GT_ADV_VCT_IMP_GREATER_THAN_115,
+    GT_ADV_VCT_IMP_LESS_THAN_85,
+    GT_ADV_VCT_OPEN,
+    GT_ADV_VCT_SHORT,
+    GT_ADV_VCT_CROSS_PAIR_SHORT
+} GT_ADV_VCT_STATUS;
+
+
+/*
+ * typedef: struct GT_CROSS_PAIR_LIST
+ *
+ * Description: strucuture for cross pair short channels.
+ *
+ * Fields:
+ *      channel - cross pair short channel list
+ *                channel[i] is GT_TRUE if the channel[i] is cross pair short
+ *                with the current channel under test.
+ *      dist2fault - estimated distance to the shorted location.
+ *                   valid only if related channel (above) is GT_TRUE.
+ */
+typedef struct _GT_CROSS_SHORT_LIST
+{
+    GT_BOOL    channel[GT_MDI_PAIR_NUM];
+    GT_16     dist2fault[GT_MDI_PAIR_NUM];
+} GT_CROSS_SHORT_LIST;
+
+
+/*
+ * typedef: struct GT_ADV_CABLE_STATUS
+ *
+ * Description: strucuture for advanced cable status.
+ *
+ * Fields:
+ *      cableStatus - VCT cable status for each channel.
+ *      crossShort  - cross pair short list for each channel. 
+ *                    Valid only if relative cableStatus is GT_ADV_VCT_CROSS_PAIR_SHORT.
+ *      dist2fault  - estimated distance to fault for each channel.
+ *                    Valid if relative cableStatus is one of the followings:
+ *                      GT_ADV_VCT_NORMAL
+ *                      GT_ADV_VCT_IMP_GREATER_THAN_115
+ *                      GT_ADV_VCT_IMP_LESS_THAN_85,
+ *                      GT_ADV_VCT_OPEN, or
+ *						GT_ADV_VCT_SHORT
+  */
+typedef struct
+{
+    GT_ADV_VCT_STATUS   cableStatus[GT_MDI_PAIR_NUM];
+    union {
+        GT_CROSS_SHORT_LIST crossShort;
+        GT_16     dist2fault;
+    }u[GT_MDI_PAIR_NUM];
+} GT_ADV_CABLE_STATUS;
+
+
+/*
+ * Definition:
+ *		GT_LED_LINK_ACT_SPEED 	- off = no link, on = link, blink = activity, blink speed = link speed
+ *		GT_LED_LINK_ACT	 		- off = no link, on = link, blink = activity
+ *		GT_LED_LINK		 		- off = no link, on = link
+ *		GT_LED_10_LINK_ACT		- off = no link, on = 10, blink = activity
+ *		GT_LED_10_LINK			- off = no link, on = 10
+ *		GT_LED_100_LINK_ACT		- off = no link, on = 100 link, blink = activity
+ *		GT_LED_100_LINK			- off = no link, on = 100 link
+ *		GT_LED_1000_LINK_ACT	- off = no link, on = 1000 link, blink = activity
+ *		GT_LED_1000_LINK		- off = no link, on = 1000 link
+ *		GT_LED_10_100_LINK_ACT	- off = no link, on = 10 or 100 link, blink = activity
+ *		GT_LED_10_100_LINK		- off = no link, on = 10 or 100 link
+ *		GT_LED_10_1000_LINK_ACT	- off = no link, on = 10 or 1000 link, blink = activity
+ *		GT_LED_10_1000_LINK		- off = no link, on = 10 or 1000 link
+ *		GT_LED_100_1000_LINK_ACT- off = no link, on = 100 or 1000 link, blink = activity
+ *		GT_LED_100_1000_LINK	- off = no link, on = 100 or 1000 link
+ *		GT_LED_SPECIAL			- special leds
+ *		GT_LED_DUPLEX_COL		- off = half duplx, on = full duplex, blink = collision
+ *		GT_LED_ACTIVITY			- off = no link, blink on = activity
+ *		GT_LED_PTP_ACT			- blink on = PTP activity
+ *		GT_LED_FORCE_BLINK		- force blink
+ *		GT_LED_FORCE_OFF		- force off
+ *		GT_LED_FORCE_ON			- force on
+*/
+#define GT_LED_LINK_ACT_SPEED		1
+#define GT_LED_LINK_ACT			2
+#define GT_LED_LINK				3
+#define GT_LED_10_LINK_ACT			4
+#define GT_LED_10_LINK				5
+#define GT_LED_100_LINK_ACT		6
+#define GT_LED_100_LINK			7
+#define GT_LED_1000_LINK_ACT		8
+#define GT_LED_1000_LINK			9
+#define GT_LED_10_100_LINK_ACT		10
+#define GT_LED_10_100_LINK			11
+#define GT_LED_10_1000_LINK_ACT	12
+#define GT_LED_10_1000_LINK		13
+#define GT_LED_100_1000_LINK_ACT	14
+#define GT_LED_100_1000_LINK		15
+#define GT_LED_SPECIAL				16
+#define GT_LED_DUPLEX_COL			17
+#define GT_LED_ACTIVITY			18
+#define GT_LED_PTP_ACT				19
+#define GT_LED_FORCE_BLINK			20
+#define GT_LED_FORCE_OFF			21
+#define GT_LED_FORCE_ON			22
+#define GT_LED_RESERVE				23
+
+
+/*
+ * typedef: enum GT_LED_CFG
+ *
+ * Description: Enumeration for LED configuration type
+ *
+ * Enumerations:
+ *		GT_LED_CFG_LED0		- read/write led0 value (GT_LED_xxx definition)
+ *		GT_LED_CFG_LED1		- read/write led1 value
+ *		GT_LED_CFG_LED2		- read/write led2 value
+ *		GT_LED_CFG_LED3		- read/write led3 value
+ *		GT_LED_CFG_PULSE_STRETCH	- read/write pulse stretch (0 ~ 4)
+ *		GT_LED_CFG_BLINK_RATE		- read/write blink rate	(0 ~ 5)
+ *		GT_LED_CFG_SPECIAL_CONTROL	- read/write special control (port vector)
+ */
+typedef enum
+{
+	GT_LED_CFG_LED0,
+	GT_LED_CFG_LED1,
+	GT_LED_CFG_LED2,
+	GT_LED_CFG_LED3,
+	GT_LED_CFG_PULSE_STRETCH,
+	GT_LED_CFG_BLINK_RATE,
+	GT_LED_CFG_SPECIAL_CONTROL
+} GT_LED_CFG;
+
+
+/*
+ * typedef: enum GT_AVB_RECOVERED_CLOCK
+ *
+ * Description: Enumeration for recovered clock type
+ *
+ * Enumerations:
+ *		GT_PRIMARY_RECOVERED_CLOCK 		- primary recovered clock
+ *		GT_SECONDARY_RECOVERED_CLOCK 	- secondary recovered clock
+ */
+typedef enum
+{
+	GT_PRIMARY_RECOVERED_CLOCK,
+	GT_SECONDARY_RECOVERED_CLOCK
+} GT_AVB_RECOVERED_CLOCK;
+
+
+/* Define QAV interrupt bits */
+
+#define GT_QAV_INT_STATUS_ENQ_LMT_BIT			0x8000	/* EnQ Limit Interrupt Enable */
+#define GT_QAV_INT_STATUS_ISO_DEL_BIT			0x0400	/* Iso Delay Interrupt Enable */
+#define GT_QAV_INT_STATUS_ISO_DIS_BIT			0x0200  /* Iso Discard Interrupt Enable */
+#define GT_QAV_INT_STATUS_ISO_LIMIT_EX_BIT		0x0100  /* Iso Packet Memory Exceeded Interrupt Enable */
+
+#define GT_QAV_INT_ENABLE_ENQ_LMT_BIT			0x80  /* EnQ Limit Interrupt Enable */
+#define GT_QAV_INT_ENABLE_ISO_DEL_BIT			0x04  /* Iso Delay Interrupt Enable */
+#define GT_QAV_INT_ENABLE_ISO_DIS_BIT			0x02  /* Iso Discard Interrupt Enable */
+#define GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT		0x01  /* Iso Packet Memory Exceeded Interrupt Enable */
+
+
+/*
+ * Typedef: enum GT_EEPROM_OPERATION
+ *
+ * Description: Defines the EEPROM Operation type
+ *
+ * Fields:
+ *      PTP_WRITE_DATA 			- Write data to the EEPROM register
+ *      PTP_READ_DATA			- Read data from EEPROM register
+ *      PTP_RESTART				- Restart EEPROM oprition
+ */
+typedef enum
+{
+	GT_EEPROM_NO_OP		 			= 0x0,
+	GT_EEPROM_WRITE_DATA 			= 0x3,
+	GT_EEPROM_READ_DATA  			= 0x4,
+	GT_EEPROM_RESTART				= 0x6,
+	GT_EEPROM_HALT					= 0x7,
+} GT_EEPROM_OPERATION;
+
+
+/*
+ *  typedef: struct GT_EEPROM_OP_DATA
+ *
+ *  Description: data required by EEPROM Operation
+ *
+ *  Fields:
+ *      eepromPort		- physical port of the device
+ *      eepromAddr 	- register address
+ *      eepromData 	- data for ptp register.
+ */
+typedef struct
+{
+	GT_U32	eepromPort;
+	GT_U32	eepromBlock;
+	GT_U32	eepromAddr;
+	GT_U32	eepromData;
+} GT_EEPROM_OP_DATA;
+
+#define GT_EEPROM_OP_ST_RUNNING_MASK		0x800
+#define GT_EEPROM_OP_ST_WRITE_EN_MASK		0x400
+
+#define GT_SCRAT_MISC_REG_SCRAT_0	0x00 /* Scratch Byte 0 */
+#define GT_SCRAT_MISC_REG_SCRAT_1	0x01 /* Scratch Byte 1 */
+#define GT_SCRAT_MISC_REG_GPIO_CFG	0x60 /* GPIO Configuration */
+										 /* 0x61 = Reserved for future use */
+#define GT_SCRAT_MISC_REG_GPIO_DIR	0x62 /* GPIO Direction */
+#define GT_SCRAT_MISC_REG_GPIO_DAT	0x63 /* GPIO Data */
+#define GT_SCRAT_MISC_REG_CFG_DAT0	0x70 /* CONFIG Data 0 */
+#define GT_SCRAT_MISC_REG_CFG_DAT1	0x71 /* CONFIG Data 1 */
+#define GT_SCRAT_MISC_REG_CFG_DAT2	0x72 /* CONFIG Data 2 */
+#define GT_SCRAT_MISC_REG_CFG_DAT3	0x73 /* CONFIG Data 3 */
+#define GT_SCRAT_MISC_REG_SYNCE		0x7C /* SyncE & TAICLK125Â’s Drive */
+#define GT_SCRAT_MISC_REG_P5_CLK	0x7D /* P5Â’s & CLK125Â’s Clock Drive */
+#define GT_SCRAT_MISC_REG_P6_CLK	0x7E /* P6Â’s Clock Drive */
+#define GT_SCRAT_MISC_REG_EEPROM	0x7F /* EEPROM Pad drive */
+#define GT_SCRAT_MISC_REG_MAX		0x80 /* Maximun register pointer */
+
+#define GT_GPIO_BIT_0	0x1
+#define GT_GPIO_BIT_1	0x2
+#define GT_GPIO_BIT_2	0x4
+#define GT_GPIO_BIT_3	0x8
+#define GT_GPIO_BIT_4	0x10
+#define GT_GPIO_BIT_5	0x20
+#define GT_GPIO_BIT_6	0x40
+
+typedef struct
+{
+	GT_U8         user : 3;
+	GT_U8         addr : 5;
+}GT_CONFIG_DATA_0;
+
+typedef struct
+{
+	GT_U8         led  : 2;
+	GT_U8         fourcol : 1;
+	GT_U8         normCx : 1;
+	GT_U8         jumbo : 1;
+	GT_U8         ee_we : 1;
+	GT_U8         fd_flow : 1;
+	GT_U8         hd_flow : 1;
+}GT_CONFIG_DATA_1;
+
+typedef struct
+{
+	GT_U8         p5_mod : 3;
+	GT_U8         bit4	 : 1;
+	GT_U8         p6_mod : 3;
+}GT_CONFIG_DATA_2;
+
+typedef struct
+{
+	GT_U8         rmu_mod : 2;
+}GT_CONFIG_DATA_3;
+
+typedef struct
+{
+	union {
+		GT_U8				Byte;
+		GT_CONFIG_DATA_0	Data;
+	} cfgData0;
+	union {
+		GT_U8				Byte;
+		GT_CONFIG_DATA_0	Data;
+	} cfgData1;
+	union {
+		GT_U8				Byte;
+		GT_CONFIG_DATA_0	Data;
+	} cfgData2;
+	union {
+		GT_U8				Byte;
+		GT_CONFIG_DATA_0	Data;
+	} cfgData3;
+}GT_CONFIG_DATA;
+
+
+/* definition for Trunking */
+#define IS_TRUNK_ID_VALID(_dev, _id)	(((_id) < 16) ? 1 : 0)
+
+
+/* definition for device scan mode */
+#define SMI_AUTO_SCAN_MODE		0	/* Scan 0 or 0x10 base address to find the QD */
+#define SMI_MANUAL_MODE			1	/* Use QD located at manually defined base addr */
+#define SMI_MULTI_ADDR_MODE		2	/* Use QD at base addr and use indirect access */
+typedef struct
+{
+	GT_U32	scanMode;	/* check definition for device scan mode */
+	GT_U32	baseAddr;	/* meaningful if scanMode is not SMI_AUTO_SCAN_MODE */
+} GT_SCAN_MODE;
+
+
+#define GT_SKIP_INIT_SETUP	0x736b6970
+
+/*
+ * Typedef: struct GT_SYS_CONFIG
+ *
+ * Description: System configuration Parameters struct.
+ *
+ * Fields:
+ *	devNum		- Switch Device Number 
+ *  cpuPortNum  - The physical port used to connect the device to CPU.
+ *                This is the port to which packets destined to CPU are
+ *                forwarded.
+ *  initPorts   - Whether to initialize the ports state.
+ *                GT_FALSE    - leave in default state.
+ *                GT_TRUE     - Initialize to Forwarding state.
+ *  skipInitSetup - skip init setup, if value is GT_SKIP_INIT_SETUP
+ *                  perform init setup, otherwise
+ *	                Initializing port state is not affected by this variable.
+ *	BSPFunctions	- Group of BSP specific functions.
+ *				SMI Read/Write and Semaphore Related functions.
+ */
+typedef struct
+{
+	GT_U8         devNum;
+	GT_U8         cpuPortNum;
+	GT_BOOL       initPorts;
+	BSP_FUNCTIONS BSPFunctions;
+	GT_SCAN_MODE  mode;
+	GT_U32        skipInitSetup;
+}GT_SYS_CONFIG;
+
+
+
+/*
+ * Typedef: struct GT_QD_DEV
+ *
+ * Description: Includes Tapi layer switch configuration data.
+ *
+ * Fields:
+ *   deviceId       - The device type identifier.
+ *   revision       - The device revision number.
+ *   baseRegAddr    - Switch Base Register address.
+ *   numOfPorts     - Number of active ports.
+ *   maxPorts       - max ports. This field is only for driver's use.
+ *   cpuPortNum     - Logical port number whose physical port is connected to the CPU.
+ *   maxPhyNum      - max configurable Phy address.
+ *   stpMode        - current switch STP mode (0 none, 1 en, 2 dis)
+ *   accessMode	    - shows how to find and access the device.
+ *   phyAddr        - SMI address used to access Switch registers(only for SMI_MULTI_ADDR_MODE).
+ *   validPortVec   - valid port list in vector format
+ *   validPhyVec	- valid phy list in vector format
+ *   validSerdesVec	- valid serdes list in vector format
+ *   devGroup	    - the device group
+ *   devName	    - name of the device
+ *   devStorage	    - driver internal use (hold various temp information)
+ *   multiAddrSem   - Semaphore for Accessing SMI Device
+ *   atuRegsSem     - Semaphore for ATU access
+ *   vtuRegsSem     - Semaphore for VTU access
+ *   statsRegsSem   - Semaphore for RMON counter access
+ *   pirlRegsSem    - Semaphore for PIRL Resource access
+ *   ptpRegsSem     - Semaphore for PTP Resource access
+ *   tblRegsSem     - Semaphore for various Table Resource access,
+ *                    such as Trunk Tables and Device Table
+ *   eepromRegsSem  - Semaphore for eeprom control access
+ *   phyRegsSem     - Semaphore for PHY Device access
+ *   fgtReadMii     - platform specific SMI register Read function
+ *   fgtWriteMii    - platform specific SMI register Write function
+ *   semCreate      - function to create semapore
+ *   semDelete      - function to delete the semapore
+ *   semTake        - function to get a semapore
+ *   semGive        - function to return semaphore
+ *   appData        - application data that user may use
+ */
+struct _GT_QD_DEV
+{
+	GT_DEVICE   deviceId;
+	GT_LPORT    cpuPortNum;
+	GT_U8       revision;
+	GT_U8		devNum;
+	GT_U8		devEnabled;
+	GT_U8       baseRegAddr;
+	GT_U8       numOfPorts;
+	GT_U8		maxPorts;
+	GT_U8       maxPhyNum;
+	GT_U8		stpMode;
+	GT_U8		accessMode;
+	GT_U8		phyAddr;
+	GT_U16		reserved;
+	GT_U16		validPortVec;
+	GT_U16		validPhyVec;
+	GT_U16		validSerdesVec;
+	GT_U16		devGroup;
+	GT_U32		devName;
+	GT_U32		devStorage;
+	GT_SEM		multiAddrSem;
+	GT_SEM		atuRegsSem;
+	GT_SEM		vtuRegsSem;
+	GT_SEM		statsRegsSem;
+	GT_SEM		pirlRegsSem;
+	GT_SEM		ptpRegsSem;
+	GT_SEM		tblRegsSem;
+	GT_SEM		eepromRegsSem;
+	GT_SEM		phyRegsSem;
+
+	FGT_READ_MII 	fgtReadMii;
+	FGT_WRITE_MII 	fgtWriteMii;
+
+	FGT_SEM_CREATE	semCreate; 	/* create semaphore */
+	FGT_SEM_DELETE	semDelete; 	/* delete the semaphore */
+	FGT_SEM_TAKE	semTake;	/* try to get a semaphore */
+	FGT_SEM_GIVE	semGive;	/* return semaphore */
+	void*		appData;
+
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __msApi_h */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiMadConfig.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiMadConfig.h
new file mode 100755
index 0000000..5d8f451
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiMadConfig.h
@@ -0,0 +1,31 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* msApiMadConfig.h
+*
+* DESCRIPTION:
+*       Marvell Alaska Device (MAD) Configuration header file
+*       If DSDT does not need to load MAD driver for internal Gigabit Phy,
+*       MAD_INCLUDE should be undefined.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __msApiMadConfig_h
+#define __msApiMadConfig_h
+
+#define MAD_INCLUDE
+
+/*
+ * uncomment the following #undef for DSDT not to include MAD
+*/
+/* #undef MAD_INCLUDE */
+
+#ifdef MAD_INCLUDE
+#include <madApi.h>
+#endif
+
+#endif /* __msApiMadConfig_h */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiPrototype.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiPrototype.h
new file mode 100755
index 0000000..f02972e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiPrototype.h
@@ -0,0 +1,21130 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* msApiPrototype.h
+*
+* DESCRIPTION:
+*       API Prototypes for QuarterDeck Device
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __msApiPrototype_h
+#define __msApiPrototype_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* gtBrgFdb.c */
+
+/*******************************************************************************
+* gfdbSetAtuSize
+*
+* DESCRIPTION:
+*       Sets the Mac address table size.
+*
+* INPUTS:
+*       size    - Mac address table size.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbSetAtuSize
+(
+    IN GT_QD_DEV *dev,
+    IN ATU_SIZE size
+);
+
+
+/*******************************************************************************
+* gfdbGetAgingTimeRange
+*
+* DESCRIPTION:
+*       Gets the maximal and minimum age times that the hardware can support.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       maxTimeout - max aging time in secounds.
+*       minTimeout - min aging time in secounds.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAgingTimeRange
+(
+    IN GT_QD_DEV *dev,
+    OUT GT_U32 *maxTimeout,
+    OUT GT_U32 *minTimeout
+);
+
+/*******************************************************************************
+* gfdbGetAgingTimeout
+*
+* DESCRIPTION:
+*       Gets the timeout period in seconds for aging out dynamically learned
+*       forwarding information. The returned value may not be the same as the value
+*		programmed with <gfdbSetAgingTimeout>. Please refer to the description of
+*		<gfdbSetAgingTimeout>.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       timeout - aging time in seconds.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAgingTimeout
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_U32       *timeout
+);
+
+/*******************************************************************************
+* gfdbSetAgingTimeout
+*
+* DESCRIPTION:
+*       Sets the timeout period in seconds for aging out dynamically learned
+*       forwarding information. The standard recommends 300 sec.
+*		Supported aging timeout values are multiple of time-base, where time-base
+*		is either 15 or 16 seconds, depending on the Switch device. For example,
+*		88E6063 uses time-base 16, and so supported aging timeouts are 0,16,32,
+*		48,..., and 4080. If unsupported timeout value (bigger than 16) is used, 
+*		the value will be rounded to the nearest supported value smaller than the 
+*		given timeout. If the given timeout is less than 16, minimum timeout value
+*		16 will be used instead. E.g.) 35 becomes 32 and 5 becomes 16.
+*		<gfdbGetAgingTimeRange> function can be used to find the time-base.
+*
+* INPUTS:
+*       timeout - aging time in seconds.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbSetAgingTimeout
+(
+    IN GT_QD_DEV *dev,
+    IN GT_U32 timeout
+);
+
+
+
+/*******************************************************************************
+* gfdbGetAtuDynamicCount
+*
+* DESCRIPTION:
+*       Gets the current number of dynamic unicast entries in this
+*       Filtering Database.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       numDynEntries - number of dynamic entries.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - vlan does not exist.
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuDynamicCount
+(
+    IN GT_QD_DEV *dev,
+    OUT GT_U32 *numDynEntries
+);
+
+
+
+/*******************************************************************************
+* gfdbGetAtuEntryFirst
+*
+* DESCRIPTION:
+*       Gets first lexicographic MAC address entry from the ATU.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       atuEntry - match Address translate unit entry.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - table is empty.
+*
+* COMMENTS:
+*       Search starts from Mac[00:00:00:00:00:00]
+*
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuEntryFirst
+(
+    IN GT_QD_DEV *dev,
+    OUT GT_ATU_ENTRY    *atuEntry
+);
+
+
+
+/*******************************************************************************
+* gfdbGetAtuEntryNext
+*
+* DESCRIPTION:
+*       Gets next lexicographic MAC address from the specified Mac Addr.
+*
+* INPUTS:
+*       atuEntry - the Mac Address to start the search.
+*
+* OUTPUTS:
+*       atuEntry - match Address translate unit entry.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*
+* COMMENTS:
+*       Search starts from atu.macAddr[xx:xx:xx:xx:xx:xx] specified by the
+*       user.
+*
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuEntryNext
+(
+    IN GT_QD_DEV *dev,
+    INOUT GT_ATU_ENTRY  *atuEntry
+);
+
+
+
+/*******************************************************************************
+* gfdbFindAtuMacEntry
+*
+* DESCRIPTION:
+*       Find FDB entry for specific MAC address from the ATU.
+*
+* INPUTS:
+*       atuEntry - the Mac address to search.
+*
+* OUTPUTS:
+*       found    - GT_TRUE, if the appropriate entry exists.
+*       atuEntry - the entry parameters.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*
+* COMMENTS:
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+*******************************************************************************/
+GT_STATUS gfdbFindAtuMacEntry
+(
+    IN GT_QD_DEV *dev,
+    INOUT GT_ATU_ENTRY  *atuEntry,
+    OUT GT_BOOL         *found
+);
+
+
+
+/*******************************************************************************
+* gfdbFlush
+*
+* DESCRIPTION:
+*       This routine flush all or unblocked addresses from the MAC Address
+*       Table.
+*
+* INPUTS:
+*       flushCmd - the flush operation type.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NO_RESOURCE  - failed to allocate a t2c struct
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbFlush
+(
+    IN GT_QD_DEV *dev,
+    IN GT_FLUSH_CMD flushCmd
+);
+
+/*******************************************************************************
+* gfdbFlushInDB
+*
+* DESCRIPTION:
+*       This routine flush all or unblocked addresses from the particular
+*       ATU Database (DBNum). If multiple address databases are being used, this
+*		API can be used to flush entries in a particular DBNum database.
+*
+* INPUTS:
+*       flushCmd - the flush operation type.
+*		DBNum	 - ATU MAC Address Database Number. 
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORTED- if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbFlushInDB
+(
+    IN GT_QD_DEV *dev,
+    IN GT_FLUSH_CMD flushCmd,
+	IN GT_U32 DBNum
+);
+/*******************************************************************************
+* gfdbClearAtuDynamicEntry
+*
+* DESCRIPTION:
+*       Clear all non-static entries.
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gfdbClearAtuDynamicEntry
+(
+    IN  GT_QD_DEV 	*dev
+);
+/*******************************************************************************
+* gfdbAddMacEntry
+*
+* DESCRIPTION:
+*       Creates the new entry in MAC address table.
+*
+* INPUTS:
+*       macEntry    - mac address entry to insert to the ATU.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK             - on success
+*       GT_FAIL           - on error
+*       GT_NO_RESOURCE    - failed to allocate a t2c struct
+*       GT_OUT_OF_CPU_MEM - oaMalloc failed
+*
+* COMMENTS:
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbAddMacEntry
+(
+    IN GT_QD_DEV *dev,
+    IN GT_ATU_ENTRY *macEntry
+);
+
+
+
+/*******************************************************************************
+* gfdbDelMacEntry
+*
+* DESCRIPTION:
+*       Deletes MAC address entry.
+*
+* INPUTS:
+*       macAddress - mac address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NO_RESOURCE  - failed to allocate a t2c struct
+*       GT_NO_SUCH      - if specified address entry does not exist
+*
+* COMMENTS:
+*       For SVL mode vlan Id is ignored.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbDelMacEntry
+(
+    IN GT_QD_DEV *dev,
+    IN GT_ETHERADDR  *macAddress
+);
+
+/*******************************************************************************
+* gfdbDelAtuEntry
+*
+* DESCRIPTION:
+*       Deletes ATU entry.
+*
+* INPUTS:
+*       atuEntry - the ATU entry to be deleted.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NO_RESOURCE  - failed to allocate a t2c struct
+*       GT_NO_SUCH      - if specified address entry does not exist
+*
+* COMMENTS:
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+*******************************************************************************/
+GT_STATUS gfdbDelAtuEntry
+(
+    IN GT_QD_DEV *dev,
+    IN GT_ATU_ENTRY  *atuEntry
+);
+
+/*******************************************************************************
+* gfdbLearnEnable
+*
+* DESCRIPTION:
+*       Enable/disable automatic learning of new source MAC addresses on port
+*       ingress.
+*
+* INPUTS:
+*       en - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbLearnEnable
+(
+    IN GT_QD_DEV *dev,
+    IN GT_BOOL  en
+);
+
+
+/*******************************************************************************
+* gfdbGetLearnEnable
+*
+* DESCRIPTION:
+*       Get automatic learning status of new source MAC addresses on port ingress.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       en - GT_TRUE if enabled  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetLearnEnable
+(
+    IN GT_QD_DEV    *dev,
+    OUT GT_BOOL  *en
+);
+
+/*******************************************************************************
+* gstpSetMode
+*
+* DESCRIPTION:
+*       This routine Enable the Spanning tree.
+*
+* INPUTS:
+*       en - GT_TRUE for enable, GT_FALSE for disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       when enabled, this function sets all port to blocking state, and inserts
+*       the BPDU MAC into the ATU to be captured to CPU, on disable all port are
+*       being modified to be in forwarding state.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstpSetMode
+(
+    IN GT_QD_DEV *dev,
+    IN GT_BOOL  en
+);
+
+
+
+/*******************************************************************************
+* gstpSetPortState
+*
+* DESCRIPTION:
+*       This routine set the port state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*       state - the port state to set.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstpSetPortState
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT           port,
+    IN GT_PORT_STP_STATE  state
+);
+
+
+
+/*******************************************************************************
+* gstpGetPortState
+*
+* DESCRIPTION:
+*       This routine returns the port state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       state - the current port state.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstpGetPortState
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT           port,
+    OUT GT_PORT_STP_STATE  *state
+);
+
+/*******************************************************************************
+* gprtSetEgressMode
+*
+* DESCRIPTION:
+*       This routine set the egress mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the egress mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetEgressMode
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT        port,
+    IN GT_EGRESS_MODE  mode
+);
+
+
+
+/*******************************************************************************
+* gprtGetEgressMode
+*
+* DESCRIPTION:
+*       This routine get the egress mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - the egress mode.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetEgressMode
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT        port,
+    OUT GT_EGRESS_MODE  *mode
+);
+
+
+
+/*******************************************************************************
+* gprtSetVlanTunnel
+*
+* DESCRIPTION:
+*       This routine sets the vlan tunnel mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the vlan tunnel mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetVlanTunnel
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+
+
+/*******************************************************************************
+* gprtGetVlanTunnel
+*
+* DESCRIPTION:
+*       This routine get the vlan tunnel mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - the vlan tunnel mode..
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetVlanTunnel
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+
+/*******************************************************************************
+* gprtSetIGMPSnoop
+*
+* DESCRIPTION:
+* 		This routine set the IGMP Snoop. When set to one and this port receives
+*		IGMP frame, the frame is switched to the CPU port, overriding all other 
+*		switching decisions, with exception for CPU's Trailer.
+*		CPU port is determined by the Ingress Mode bits. A port is considered 
+*		the CPU port if its Ingress Mode are either GT_TRAILER_INGRESS or 
+*		GT_CPUPORT_INGRESS.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for IGMP Snoop or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIGMPSnoop
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+/*******************************************************************************
+* gprtGetIGMPSnoop
+*
+* DESCRIPTION:
+*		This routine get the IGMP Snoop mode.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: IGMP Snoop enabled
+*  			GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIGMPSnoop
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+/* the following two APIs are added to support clippership */
+
+/*******************************************************************************
+* gprtSetHeaderMode
+*
+* DESCRIPTION:
+*		This routine set ingress and egress header mode of a switch port. 
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for header mode  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetHeaderMode
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+/*******************************************************************************
+* gprtGetHeaderMode
+*
+* DESCRIPTION:
+*		This routine gets ingress and egress header mode of a switch port. 
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: header mode enabled
+*  			GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHeaderMode
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+
+/*******************************************************************************
+* gprtSetProtectedMode
+*
+* DESCRIPTION:
+*		This routine set protected mode of a switch port. 
+*		When this mode is set to GT_TRUE, frames are allowed to egress port
+*		defined by the 802.1Q VLAN membership for the frame's VID 'AND'
+*		by the port's VLANTable if 802.1Q is enabled on the port. Both must
+*		allow the frame to Egress.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for protected mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetProtectedMode
+(
+    IN  GT_QD_DEV   *dev,
+    IN GT_LPORT     port,
+    IN GT_BOOL      mode
+);
+
+/*******************************************************************************
+* gprtGetProtectedMode
+*
+* DESCRIPTION:
+*		This routine gets protected mode of a switch port. 
+*		When this mode is set to GT_TRUE, frames are allowed to egress port
+*		defined by the 802.1Q VLAN membership for the frame's VID 'AND'
+*		by the port's VLANTable if 802.1Q is enabled on the port. Both must
+*		allow the frame to Egress.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: header mode enabled
+*  			GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetProtectedMode
+(
+    IN  GT_QD_DEV		*dev,
+    IN  GT_LPORT		port,
+    OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gprtSetForwardUnknown
+*
+* DESCRIPTION:
+*		This routine set Forward Unknown mode of a switch port. 
+*		When this mode is set to GT_TRUE, normal switch operation occurs.
+*		When this mode is set to GT_FALSE, unicast frame with unknown DA addresses
+*		will not egress out this port.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for protected mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetForwardUnknown
+(
+    IN GT_QD_DEV	*dev,
+    IN GT_LPORT	port,
+    IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetForwardUnknown
+*
+* DESCRIPTION:
+*		This routine gets Forward Unknown mode of a switch port. 
+*		When this mode is set to GT_TRUE, normal switch operation occurs.
+*		When this mode is set to GT_FALSE, unicast frame with unknown DA addresses
+*		will not egress out this port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: header mode enabled
+*				GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetForwardUnknown
+(
+    IN  GT_QD_DEV		*dev,
+    IN  GT_LPORT		port,
+    OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gprtGetSwitchReg
+*
+* DESCRIPTION:
+*       This routine reads Switch Port Registers.
+*
+* INPUTS:
+*       port    - logical port number
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSwitchReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+    IN  GT_U32	     regAddr,
+    OUT GT_U16	     *data
+);
+
+/*******************************************************************************
+* gprtSetSwitchReg
+*
+* DESCRIPTION:
+*       This routine writes Switch Port Registers.
+*
+* INPUTS:
+*       port    - logical port number
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetSwitchReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+    IN  GT_U32	     regAddr,
+    IN  GT_U16	     data
+);
+
+
+/*******************************************************************************
+* gprtGetGlobalReg
+*
+* DESCRIPTION:
+*       This routine reads Switch Global Registers.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetGlobalReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U32	     regAddr,
+    OUT GT_U16	     *data
+);
+
+/*******************************************************************************
+* gprtSetGlobalReg
+*
+* DESCRIPTION:
+*       This routine writes Switch Global Registers.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetGlobalReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U32	     regAddr,
+    IN  GT_U16	     data
+);
+
+
+
+/*******************************************************************************
+* gvlnSetPortVlanPorts
+*
+* DESCRIPTION:
+*       This routine sets the port VLAN group port membership list.
+*
+* INPUTS:
+*       port        - logical port number to set.
+*       memPorts    - array of logical ports.
+*       memPortsLen - number of members in memPorts array
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVlanPorts
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_LPORT memPorts[],
+    IN GT_U8    memPortsLen
+);
+
+
+
+/*******************************************************************************
+* gvlnGetPortVlanPorts
+*
+* DESCRIPTION:
+*       This routine gets the port VLAN group port membership list.
+*
+* INPUTS:
+*       port        - logical port number to set.
+*
+* OUTPUTS:
+*       memPorts    - array of logical ports.
+*       memPortsLen - number of members in memPorts array
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVlanPorts
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_LPORT memPorts[],
+    OUT GT_U8    *memPortsLen
+);
+
+
+
+
+/*******************************************************************************
+* gvlnSetPortUserPriLsb
+*
+* DESCRIPTION:
+*       This routine Set the user priority (VPT) LSB bit, to be added to the
+*       user priority on the egress.
+*
+* INPUTS:
+*       port       - logical port number to set.
+*       userPriLsb - GT_TRUE for 1, GT_FALSE for 0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortUserPriLsb
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  userPriLsb
+);
+
+
+
+/*******************************************************************************
+* gvlnGetPortUserPriLsb
+*
+* DESCRIPTION:
+*       This routine gets the user priority (VPT) LSB bit.
+*
+* INPUTS:
+*       port       - logical port number to set.
+*
+* OUTPUTS:
+*       userPriLsb - GT_TRUE for 1, GT_FALSE for 0.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortUserPriLsb
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT    port,
+    OUT GT_BOOL     *userPriLsb
+);
+
+
+/*******************************************************************************
+* gvlnSetPortVid
+*
+* DESCRIPTION:
+*       This routine Set the port default vlan id.
+*
+* INPUTS:
+*       port - logical port number to set.
+*       vid  - the port vlan id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVid
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_U16   vid
+);
+
+
+/*******************************************************************************
+* gvlnGetPortVid
+*
+* DESCRIPTION:
+*       This routine Get the port default vlan id.
+*
+* INPUTS:
+*       port - logical port number to set.
+*
+* OUTPUTS:
+*       vid  - the port vlan id.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVid
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_U16   *vid
+);
+
+/*******************************************************************************
+* gvlnSetPortVlanDBNum
+*
+* DESCRIPTION:
+*       This routine sets the port VLAN database number (DBNum).
+*
+* INPUTS:
+*       port	- logical port number to set.
+*       DBNum 	- database number for this port 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:IN GT_INGRESS_MODE mode
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVlanDBNum
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_U32   DBNum
+);
+
+
+/*******************************************************************************
+* gvlnGetPortVlanDBNum
+*
+* DESCRIPTION:IN GT_INGRESS_MODE mode
+*       This routine gets the port VLAN database number (DBNum).
+*
+* INPUTS:
+*       port 	- logical port number to get.
+*
+* OUTPUTS:
+*       DBNum 	- database number for this port 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVlanDBNum
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_U32    *DBNum
+);
+
+/********************************************************************
+* gvlnSetPortVlanDot1qMode
+*
+* DESCRIPTION:
+*       This routine sets the port 802.1q mode (11:10) 
+*
+* INPUTS:
+*       port	- logical port number to set.
+*       mode 	- 802.1q mode for this port 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:IN GT_INGRESS_MODE mode
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVlanDot1qMode
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT 	port,
+    IN GT_DOT1Q_MODE	mode
+);
+
+/*******************************************************************************
+* gvlnGetPortVlanDot1qMode
+*
+* DESCRIPTION:
+*       This routine gets the port 802.1q mode (bit 11:10).
+*
+* INPUTS:
+*       port 	- logical port number to get.
+*
+* OUTPUTS:
+*       mode 	- 802.1q mode for this port 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVlanDot1qMode
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_DOT1Q_MODE    *mode
+);
+
+
+/********************************************************************
+* gvlnSetPortVlanForceDefaultVID
+*
+* DESCRIPTION:
+*       This routine sets the port 802.1q mode (11:10) 
+*
+* INPUTS:
+*       port	- logical port number to set.
+*       mode    - GT_TRUE, force to use default VID
+*                 GT_FAULSE, otherwise 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVlanForceDefaultVID
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT 	port,
+    IN GT_BOOL  	mode
+);
+
+/*******************************************************************************
+* gvlnGetPortVlanForceDefaultVID
+*
+* DESCRIPTION:
+*       This routine gets the port mode for ForceDefaultVID (bit 12).
+*
+* INPUTS:
+*       port 	- logical port number to get.
+*
+* OUTPUTS:
+*       mode 	- ForceDefaultVID mode for this port 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVlanForceDefaultVID
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT 	 port,
+    OUT GT_BOOL    	*mode
+);
+
+/*******************************************************************************
+* eventSetActive
+*
+* DESCRIPTION:
+*       This routine enables/disables the receive of an hardware driven event.
+*
+* INPUTS:
+*       eventType - the event type. any combination of the folowing: 
+*       	GT_STATS_DONE, GT_VTU_PROB, GT_VTU_DONE, GT_ATU_FULL,  
+*       	GT_ATU_DONE, GT_PHY_INTERRUPT, GT_EE_INTERRUPT, and GT_DEVICE_INT
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       Each switch device has its own set of event Types. Please refer to the
+*		device datasheet for the list of event types that the device supports.
+*
+*******************************************************************************/
+GT_STATUS eventSetActive
+(
+    IN GT_QD_DEV 	*dev,
+    IN GT_U32 		eventType
+);
+
+/*******************************************************************************
+* eventGetIntStatus
+*
+* DESCRIPTION:
+*       This routine reads an hardware driven event status.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       intCause -  It provides the source of interrupt of the following:
+*				GT_STATS_DONE, GT_VTU_PROB, GT_VTU_DONE, GT_ATU_FULL,  
+*				GT_ATU_DONE, GT_PHY_INTERRUPT, and GT_EE_INTERRUPT.
+*				For Gigabit Switch, GT_ATU_FULL is replaced with GT_ATU_FULL and 
+*				GT_PHY_INTERRUPT is not supported.
+*				GT_DEVICE_INT may not be available on the devices, so please refer
+*				to the datasheet for details.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS eventGetIntStatus
+(
+    IN  GT_QD_DEV 	*dev,
+    OUT GT_U16		*intCause
+);
+
+/*******************************************************************************
+* gvtuGetIntStatus
+*
+* DESCRIPTION:
+* 		Check to see if a specific type of VTU interrupt occured
+*
+* INPUTS:
+*       intType - the type of interrupt which causes an interrupt.
+*			any combination of 
+*			GT_MEMEBER_VIOLATION,
+*			GT_MISS_VIOLATION,
+*			GT_FULL_VIOLATION
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK   - on success
+* 		GT_FAIL - on error
+*
+* COMMENTS:
+* 		FULL_VIOLATION is only for Fast Ethernet Switch (not for Gigabit Switch).
+*
+*******************************************************************************/
+
+GT_STATUS gvtuGetIntStatus
+(
+    IN  GT_QD_DEV 			*dev,
+    OUT GT_VTU_INT_STATUS 	*vtuIntStatus
+);
+
+/*******************************************************************************
+* gvtuGetEntryCount
+*
+* DESCRIPTION:
+*       Gets the current number of entries in the VTU table
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       numEntries - number of VTU entries.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - vlan does not exist.
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetEntryCount
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U32 		*numEntries
+);
+
+/*******************************************************************************
+* gvtuGetEntryFirst
+*
+* DESCRIPTION:
+*       Gets first lexicographic entry from the VTU.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       vtuEntry - match VTU entry.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - table is empty.
+*
+* COMMENTS:
+*       Search starts from vid of all one's
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetEntryFirst
+(
+	IN  GT_QD_DEV 		*dev,
+	OUT GT_VTU_ENTRY	*vtuEntry
+);
+
+/*******************************************************************************
+* gvtuGetEntryNext
+*
+* DESCRIPTION:
+*       Gets next lexicographic VTU entry from the specified VID.
+*
+* INPUTS:
+*       vtuEntry - the VID to start the search.
+*
+* OUTPUTS:
+*       vtuEntry - match VTU  entry.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*
+* COMMENTS:
+*       Search starts from the VID specified by the user.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetEntryNext
+(
+	IN  GT_QD_DEV 		*dev,
+	INOUT GT_VTU_ENTRY  *vtuEntry
+);
+
+/*******************************************************************************
+* gvtuFindVidEntry
+*
+* DESCRIPTION:
+*       Find VTU entry for a specific VID, it will return the entry, if found, 
+*       along with its associated data 
+*
+* INPUTS:
+*       vtuEntry - contains the VID to search for.
+*
+* OUTPUTS:
+*       found    - GT_TRUE, if the appropriate entry exists.
+*       vtuEntry - the entry parameters.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuFindVidEntry
+(
+	IN GT_QD_DEV 		*dev,
+	INOUT GT_VTU_ENTRY  *vtuEntry,
+	OUT GT_BOOL         *found
+);
+
+/*******************************************************************************
+* gvtuFlush
+*
+* DESCRIPTION:
+*       This routine removes all entries from VTU Table.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuFlush
+(
+    IN GT_QD_DEV *dev
+);
+
+/*******************************************************************************
+* gvtuAddEntry
+*
+* DESCRIPTION:
+*       Creates the new entry in VTU table based on user input.
+*
+* INPUTS:
+*       vtuEntry    - vtu entry to insert to the VTU.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK             - on success
+*       GT_FAIL           - on error
+*       GT_FULL			  - vtu table is full
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuAddEntry
+(
+    IN GT_QD_DEV 	*dev,
+    IN GT_VTU_ENTRY *vtuEntry
+);
+
+/*******************************************************************************
+* gvtuDelEntry
+*
+* DESCRIPTION:
+*       Deletes VTU entry specified by user.
+*
+* INPUTS:
+*       vtuEntry - the VTU entry to be deleted 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NO_SUCH      - if specified address entry does not exist
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuDelEntry
+(
+    IN GT_QD_DEV 	*dev,
+    IN GT_VTU_ENTRY *vtuEntry
+);
+
+/* gtPhyCtrl.c */
+
+/*******************************************************************************
+* gprtPhyReset
+*
+* DESCRIPTION:
+*		This routine preforms PHY reset.
+*		After reset, phy will be in Autonegotiation mode.
+*
+* INPUTS:
+* 		port - The logical port number
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+* COMMENTS:
+* 		data sheet register 0.15 - Reset
+* 		data sheet register 0.13 - Speed
+* 		data sheet register 0.12 - Autonegotiation
+* 		data sheet register 0.8  - Duplex Mode
+*
+*******************************************************************************/
+
+GT_STATUS gprtPhyReset
+(
+    IN GT_QD_DEV 	*dev,
+    IN GT_LPORT 	port
+);
+
+
+/*******************************************************************************
+* gprtSetPortLoopback
+*
+* DESCRIPTION:
+* Enable/Disable Internal Port Loopback. 
+* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and 
+*   forces speed to be 10Mbps.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
+*   it is recommended to call gprtSetPortAutoMode for PHY configuration after 
+*   Loopback test.
+* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled and Link is active, the current speed is used.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   All other cases, default MAC Interface speed is used. Please refer to the data
+*   sheet for the information of the default MAC Interface speed.
+*
+* INPUTS:
+* 		port - logical port number
+* 		enable - If GT_TRUE, enable loopback mode
+* 					If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetPortLoopback
+(
+	IN GT_QD_DEV 	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL 		enable
+);
+
+/*******************************************************************************
+* gprtGetPortLoopback
+*
+* DESCRIPTION:
+* Get Internal Port Loopback state. 
+* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and 
+*   forces speed to be 10Mbps.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
+*   it is recommended to call gprtSetPortAutoMode for PHY configuration after 
+*   Loopback test.
+* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled and Link is active, the current speed is used.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   All other cases, default MAC Interface speed is used. Please refer to the data
+*   sheet for the information of the default MAC Interface speed.
+*   
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* enable - If GT_TRUE,  loopback mode is enabled
+* If GT_FALSE,  loopback mode is disabled
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortLoopback
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	OUT GT_BOOL   *enable
+);
+/*******************************************************************************
+* gprtSetPortLineLoopback
+*
+* DESCRIPTION:
+* Enable/Disable Port Line Loopback. 
+*   
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register FE:28.4, GE:21_2.14  - Loop_back
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetPortLineLoopback
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	IN GT_BOOL   enable
+);
+/*******************************************************************************
+* gprtGetPortLineLoopback
+*
+* DESCRIPTION:
+* Get Port Line Loopback status. 
+*   
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register FE:28.4, GE:21_2.14  - Loop_back
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetPortLineLoopback
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	OUT GT_BOOL*   enable
+);
+/*******************************************************************************
+* gprtSetPortSpeed
+*
+* DESCRIPTION:
+* 		Sets speed for a specific logical port. This function will keep the duplex 
+*		mode and loopback mode to the previous value, but disable others, such as 
+*		Autonegotiation.
+*
+* INPUTS:
+* 		port  - logical port number
+* 		speed - port speed.
+*				PHY_SPEED_10_MBPS for 10Mbps
+*				PHY_SPEED_100_MBPS for 100Mbps
+*				PHY_SPEED_1000_MBPS for 1000Mbps
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.13 - Speed Selection (LSB)
+* data sheet register 0.6  - Speed Selection (MSB)
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetPortSpeed
+(
+	IN GT_QD_DEV 	*dev,
+	IN GT_LPORT 	port,
+	IN GT_PHY_SPEED	speed
+);
+
+/*******************************************************************************
+* gprtGetPortSpeed
+*
+* DESCRIPTION:
+* 		Gets speed for a specific logical port. 
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* 		speed - port speed.
+*				PHY_SPEED_10_MBPS for 10Mbps
+*				PHY_SPEED_100_MBPS for 100Mbps
+*				PHY_SPEED_1000_MBPS for 1000Mbps
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.13 - Speed Selection (LSB)
+* data sheet register 0.6  - Speed Selection (MSB)
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortSpeed
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+IN GT_PHY_SPEED *speed
+);
+/*******************************************************************************
+* gprtPortAutoNegEnable
+*
+* DESCRIPTION:
+* 		Enable/disable an Auto-Negotiation for duplex mode on specific
+* 		logical port. When Autonegotiation is disabled, phy will be in 10Mbps Half 
+*		Duplex mode. Enabling Autonegotiation will set 100BASE-TX Full Duplex, 
+*		100BASE-TX Full Duplex, 100BASE-TX Full Duplex, and 100BASE-TX Full Duplex
+*		in AutoNegotiation Advertisement register.
+*
+* INPUTS:
+* 		port - logical port number
+* 		state - GT_TRUE for enable Auto-Negotiation for duplex mode,
+* 					GT_FALSE otherwise
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.12 - Auto-Negotiation Enable
+* 		data sheet register 4.8, 4.7, 4.6, 4.5 - Auto-Negotiation Advertisement
+*
+*******************************************************************************/
+
+GT_STATUS gprtPortAutoNegEnable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL 		state
+);
+/*******************************************************************************
+* gprtGetPortAutoNegState
+*
+* DESCRIPTION:
+* 		Read the auto negotiation state of specific logical port.
+*		This routine simply reads Auto Negotiation bit (bit 12) of Control 
+*		Register.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* 		state 	- GT_TRUE for enable Auto-Negotiation,
+*				   GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.12 - Auto-Negotiation Enable
+* 		data sheet register 4.8, 4.7, 4.6, 4.5 - Auto-Negotiation Advertisement
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortAutoNegState
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	OUT GT_BOOL   *state
+);
+
+/*******************************************************************************
+* gprtPortPowerDown
+*
+* DESCRIPTION:
+* 		Enable/disable (power down) on specific logical port. When this function 
+*		is called with normal operation request, phy will set to Autonegotiation 
+*		mode.
+*
+* INPUTS:
+* 		port	- logical port number
+* 		state	-  GT_TRUE: power down
+* 					GT_FALSE: normal operation
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.11 - Power Down
+*
+*******************************************************************************/
+
+GT_STATUS gprtPortPowerDown
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		state
+);
+
+/*******************************************************************************
+* gprtGetPortPowerDown
+*
+* DESCRIPTION:
+* 		Read Port state (power down/normal operation) on specific logical port.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* 		state -	GT_TRUE: power down
+* 				GT_FALSE: normal operation
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.11 - Power Down
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortPowerDown
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+OUT GT_BOOL   *state
+);
+
+/*******************************************************************************
+* gprtPortRestartAutoNeg
+*
+* DESCRIPTION:
+* 		Restart AutoNegotiation. If AutoNegotiation is not enabled, it'll enable 
+*		it. Loopback and Power Down will be disabled by this routine.
+*
+* INPUTS:
+* 		port - logical port number
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.9 - Restart Auto-Negotiation
+*
+*******************************************************************************/
+
+GT_STATUS gprtPortRestartAutoNeg
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+);
+
+
+/*******************************************************************************
+* gprtSetPortDuplexMode
+*
+* DESCRIPTION:
+* 		Sets duplex mode for a specific logical port. This function will keep 
+*		the speed and loopback mode to the previous value, but disable others,
+*		such as Autonegotiation.
+*
+* INPUTS:
+* 		port 	- logical port number
+* 		dMode	- dulpex mode
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetPortDuplexMode
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		dMode
+);
+
+/*******************************************************************************
+* gprtPortGetDuplexMode
+*
+* DESCRIPTION:
+* 		Gets duplex mode for a specific logical port. 
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* 		dMode	- dulpex mode
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - duplex mode
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortDuplexMode
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+OUT GT_BOOL*   dMode
+);
+/*******************************************************************************
+* gprtSetPortAutoMode
+*
+* DESCRIPTION:
+* 		This routine sets up the port with given Auto Mode.
+*		Supported mode is as follows:
+*		- Auto for both speed and duplex.
+*		- Auto for speed only and Full duplex.
+*		- Auto for speed only and Half duplex.
+*		- Auto for duplex only and speed 1000Mbps.
+*		- Auto for duplex only and speed 100Mbps.
+*		- Auto for duplex only and speed 10Mbps.
+*		- Speed 1000Mbps and Full duplex.
+*		- Speed 1000Mbps and Half duplex.
+*		- Speed 100Mbps and Full duplex.
+*		- Speed 100Mbps and Half duplex.
+*		- Speed 10Mbps and Full duplex.
+*		- Speed 10Mbps and Half duplex.
+*		
+*
+* INPUTS:
+* 		port - The logical port number
+* 		mode - Auto Mode to be written
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+* COMMENTS:
+* 		data sheet register 4.8, 4.7, 4.6, and 4.5 Autonegotiation Advertisement
+* 		data sheet register 4.6, 4.5 Autonegotiation Advertisement for 1000BX
+* 		data sheet register 9.9, 9.8 Autonegotiation Advertisement for 1000BT
+*******************************************************************************/
+
+GT_STATUS gprtSetPortAutoMode
+(
+	IN GT_QD_DEV 	*dev,
+	IN GT_LPORT 	port,
+	IN GT_PHY_AUTO_MODE mode
+);
+
+/*******************************************************************************
+* gprtGetPortAutoMode
+*
+* DESCRIPTION:
+*         This routine get Auto Mode of specific port.
+*        Supported mode is as follows:
+*        - Auto for both speed and duplex.
+*        - Auto for speed only and Full duplex.
+*        - Auto for speed only and Half duplex.
+*        - Auto for duplex only and speed 1000Mbps.
+*        - Auto for duplex only and speed 100Mbps.
+*        - Auto for duplex only and speed 10Mbps.
+*        - Speed 1000Mbps and Full duplex.
+*        - Speed 1000Mbps and Half duplex.
+*        - Speed 100Mbps and Full duplex.
+*        - Speed 100Mbps and Half duplex.
+*        - Speed 10Mbps and Full duplex.
+*        - Speed 10Mbps and Half duplex.
+*        
+*
+* INPUTS:
+*        port -    The logical port number, unless SERDES device is accessed
+*                  The physical address, if SERDES device is accessed  
+*
+* OUTPUTS:
+*        mode -    Auto Mode to be written
+*
+* RETURNS:
+*        GT_OK   - on success
+*        GT_FAIL - on error
+*        GT_NOT_SUPPORTED - on device without copper
+*
+* COMMENTS:
+*         data sheet register 4.8, 4.7, 4.6, and 4.5 Autonegotiation Advertisement
+*         data sheet register 4.6, 4.5 Autonegotiation Advertisement for 1000BX
+*         data sheet register 9.9, 9.8 Autonegotiation Advertisement for 1000BT
+*******************************************************************************/
+
+GT_STATUS gprtGetPortAutoMode
+(
+    IN  GT_QD_DEV        *dev,
+    IN  GT_LPORT         port,
+    OUT GT_PHY_AUTO_MODE *mode
+);
+
+/*******************************************************************************
+* gprtSetPause
+*
+* DESCRIPTION:
+*       This routine will set the pause bit in Autonegotiation Advertisement
+*		Register. And restart the autonegotiation.
+*
+* INPUTS:
+* port - The logical port number
+* state - GT_PHY_PAUSE_MODE enum value.
+*			GT_PHY_NO_PAUSE		- disable pause
+* 			GT_PHY_PAUSE		- support pause
+*			GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*			GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+GT_STATUS gprtSetPause
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_PHY_PAUSE_MODE state
+);
+/*******************************************************************************
+* gprtGetPause
+*
+* DESCRIPTION:
+*       This routine will get the pause bit in Autonegotiation Advertisement
+*		Register.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+*
+* OUTPUTS:
+*		state - GT_PHY_PAUSE_MODE enum value.
+*				GT_PHY_NO_PAUSE		- disable pause
+* 				GT_PHY_PAUSE		- support pause
+*				GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*				GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+GT_STATUS gprtGetPause
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+OUT  GT_PHY_PAUSE_MODE *state
+);
+/*******************************************************************************
+* gprtGetPhyReg
+*
+* DESCRIPTION:
+*       This routine reads Phy Registers.
+*
+* INPUTS:
+*       port    - logical port number
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPhyReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+    IN  GT_U32	     regAddr,
+    OUT GT_U16	     *data
+);
+
+/*******************************************************************************
+* gprtSetPhyReg
+*
+* DESCRIPTION:
+*       This routine writes Phy Registers.
+*
+* INPUTS:
+*       port    - logical port number
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPhyReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+    IN  GT_U32	     regAddr,
+    IN  GT_U16	     data
+);
+
+
+/*******************************************************************************
+* gprtPhyIntEnable
+*
+* DESCRIPTION:
+* Enable/Disable one PHY Interrupt
+* This register determines whether the INT# pin is asserted when an interrupt 
+* event occurs. When an interrupt occurs, the corresponding bit is set and
+* remains set until register 19 is read via the SMI. When interrupt enable
+* bits are not set in register 18, interrupt status bits in register 19 are 
+* still set when the corresponding interrupt events occur. However, the INT# 
+* is not asserted.
+*
+* INPUTS:
+* port    - logical port number
+* intType - the type of interrupt to enable/disable. any combination of 
+*			GT_SPEED_CHANGED,
+*			GT_DUPLEX_CHANGED,
+*			GT_PAGE_RECEIVED,
+*			GT_AUTO_NEG_COMPLETED,
+*			GT_LINK_STATUS_CHANGED,
+*			GT_SYMBOL_ERROR,
+*			GT_FALSE_CARRIER,
+*			GT_FIFO_FLOW,
+*			GT_CROSSOVER_CHANGED,
+*			GT_POLARITY_CHANGED, and
+*			GT_JABBER
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* 88E3081 data sheet register 18
+*
+*******************************************************************************/
+
+GT_STATUS gprtPhyIntEnable
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT   port,
+IN GT_U16	intType
+);
+
+
+/*******************************************************************************
+* gprtGetPhyIntStatus
+*
+* DESCRIPTION:
+* Check to see if a specific type of  interrupt occured
+*
+* INPUTS:
+* port - logical port number
+* intType - the type of interrupt which causes an interrupt.
+*			any combination of 
+*			GT_SPEED_CHANGED,
+*			GT_DUPLEX_CHANGED,
+*			GT_PAGE_RECEIVED,
+*			GT_AUTO_NEG_COMPLETED,
+*			GT_LINK_STATUS_CHANGED,
+*			GT_SYMBOL_ERROR,
+*			GT_FALSE_CARRIER,
+*			GT_FIFO_FLOW,
+*			GT_CROSSOVER_CHANGED,
+*			GT_POLARITY_CHANGED, and
+*			GT_JABBER
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* 88E3081 data sheet register 19
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetPhyIntStatus
+(
+IN GT_QD_DEV *dev,
+IN  GT_LPORT port,
+OUT  GT_U16* intType
+);
+
+/*******************************************************************************
+* gprtGetPhyIntPortSummary
+*
+* DESCRIPTION:
+* Lists the ports that have active interrupts. It provides a quick way to 
+* isolate the interrupt so that the MAC or switch does not have to poll the
+* interrupt status register (19) for all ports. Reading this register does not
+* de-assert the INT# pin
+*
+* INPUTS:
+* none
+*
+* OUTPUTS:
+* GT_U8 *intPortMask - bit Mask with the bits set for the corresponding 
+* phys with active interrupt. E.g., the bit number 0 and 2 are set when 
+* port number 0 and 2 have active interrupt
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* 88E3081 data sheet register 20
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetPhyIntPortSummary
+(
+IN GT_QD_DEV *dev,
+OUT GT_U16 *intPortMask
+);
+
+
+
+/*******************************************************************************
+* gprtSetForceFc
+*
+* DESCRIPTION:
+*       This routine set the force flow control state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*       force - GT_TRUE for force flow control  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetForceFc
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  force
+);
+
+
+
+/*******************************************************************************
+* gprtGetForceFc
+*
+* DESCRIPTION:
+*       This routine get the force flow control state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       force - GT_TRUE for force flow control  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetForceFc
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *force
+);
+
+
+
+/*******************************************************************************
+* gprtSetTrailerMode
+*
+* DESCRIPTION:
+*       This routine set the egress trailer mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE for add trailer or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetTrailerMode
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+
+
+/*******************************************************************************
+* gprtGetTrailerMode
+*
+* DESCRIPTION:
+*       This routine get the egress trailer mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for add trailer or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetTrailerMode
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+
+
+/*******************************************************************************
+* gprtSetIngressMode
+*
+* DESCRIPTION:
+*       This routine set the ingress mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the ingress mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIngressMode
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT        port,
+    IN GT_INGRESS_MODE mode
+);
+
+
+
+/*******************************************************************************
+* gprtGetIngressMode
+*
+* DESCRIPTION:
+*       This routine get the ingress mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - the ingress mode.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIngressMode
+(
+    IN GT_QD_DEV        *dev,
+    IN  GT_LPORT        port,
+    OUT GT_INGRESS_MODE *mode
+);
+
+
+
+/*******************************************************************************
+* gprtSetMcRateLimit
+*
+* DESCRIPTION:
+*       This routine set the port multicast rate limit.
+*
+* INPUTS:
+*       port - the logical port number.
+*       rate - GT_TRUE to Enable, GT_FALSE for otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetMcRateLimit
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT     port,
+    IN GT_MC_RATE   rate
+);
+
+
+
+/*******************************************************************************
+* gprtGetMcRateLimit
+*
+* DESCRIPTION:
+*       This routine Get the port multicast rate limit.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       rate - GT_TRUE to Enable, GT_FALSE for otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMcRateLimit
+(
+    IN GT_QD_DEV    *dev,
+    IN  GT_LPORT    port,
+    OUT GT_MC_RATE  *rate
+);
+
+
+
+/*******************************************************************************
+* gprtSetCtrMode
+*
+* DESCRIPTION:
+*       This routine sets the port counters mode of operation.
+*
+* INPUTS:
+*       mode  - the counter mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetCtrMode
+(
+    IN GT_QD_DEV *dev,
+    IN GT_CTR_MODE  mode
+);
+
+
+
+/*******************************************************************************
+* gprtClearAllCtr
+*
+* DESCRIPTION:
+*       This routine clears all port counters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtClearAllCtr
+(
+    IN GT_QD_DEV *dev
+);
+
+
+/*******************************************************************************
+* gprtGetPortCtr
+*
+* DESCRIPTION:
+*       This routine gets the port counters.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       ctr - the counters value.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortCtr
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT        port,
+    OUT GT_PORT_STAT    *ctr
+);
+
+
+
+
+/*******************************************************************************
+* gprtGetPartnerLinkPause
+*
+* DESCRIPTION:
+*       This routine retrives the link partner pause state.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       state - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPartnerLinkPause
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *state
+);
+
+
+
+/*******************************************************************************
+* gprtGetSelfLinkPause
+*
+* DESCRIPTION:
+*       This routine retrives the link pause state.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       state - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSelfLinkPause
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *state
+);
+
+
+
+/*******************************************************************************
+* gprtGetResolve
+*
+* DESCRIPTION:
+*       This routine retrives the resolve state.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       state - GT_TRUE for Done  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetResolve
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *state
+);
+
+
+
+/*******************************************************************************
+* gprtGetLinkState
+*
+* DESCRIPTION:
+*       This routine retrives the link state.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       state - GT_TRUE for Up  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetLinkState
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *state
+);
+
+
+
+/*******************************************************************************
+* gprtGetPortMode
+*
+* DESCRIPTION:
+*       This routine retrives the port mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for MII  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortMode
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+
+
+/*******************************************************************************
+* gprtGetPhyMode
+*
+* DESCRIPTION:
+*       This routine retrives the PHY mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for MII PHY  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPhyMode
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+
+
+/*******************************************************************************
+* gprtGetDuplex
+*
+* DESCRIPTION:
+*       This routine retrives the port duplex mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for Full  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDuplex
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+
+
+/*******************************************************************************
+* gprtGetSpeed
+*
+* DESCRIPTION:
+*       This routine retrives the port speed.
+*
+* INPUTS:
+*       speed - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for 100Mb/s  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSpeed
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *speed
+);
+
+/*******************************************************************************
+* gprtSetDuplex
+*
+* DESCRIPTION:
+*       This routine sets the duplex mode of MII/SNI/RMII ports.
+*
+* INPUTS:
+*       port - 	the logical port number.
+*				(for FullSail, it will be port 2, and for ClipperShip, 
+*				it could be either port 5 or port 6.)
+*       mode -  GT_TRUE for Full Duplex,
+*				GT_FALSE for Half Duplex.
+*
+* OUTPUTS: None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDuplex
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    IN  GT_BOOL  mode
+);
+
+
+/*******************************************************************************
+* gqosSetPortDefaultTc
+*
+* DESCRIPTION:
+*       Sets the default traffic class for a specific port.
+*
+* INPUTS:
+*       port      - logical port number
+*       trafClass - default traffic class of a port.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gcosSetPortDefaultTc
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_U8    trafClass
+);
+
+
+/*******************************************************************************
+* gcosGetPortDefaultTc
+*
+* DESCRIPTION:
+*       Gets the default traffic class for a specific port.
+*
+* INPUTS:
+*       port      - logical port number
+*
+* OUTPUTS:
+*       trafClass - default traffic class of a port.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gcosGetPortDefaultTc
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_LPORT   port,
+    OUT GT_U8     *trafClass
+);
+
+
+/*******************************************************************************
+* gqosSetPrioMapRule
+*
+* DESCRIPTION:
+*       This routine sets priority mapping rule.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE for user prio rule, GT_FALSE for otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetPrioMapRule
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+
+
+/*******************************************************************************
+* gqosGetPrioMapRule
+*
+* DESCRIPTION:
+*       This routine get the priority mapping rule.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for user prio rule, GT_FALSE for otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetPrioMapRule
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+
+
+/*******************************************************************************
+* gqosIpPrioMapEn
+*
+* DESCRIPTION:
+*       This routine enables the IP priority mapping.
+*
+* INPUTS:
+*       port - the logical port number.
+*       en   - GT_TRUE to Enable, GT_FALSE for otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosIpPrioMapEn
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  en
+);
+
+
+
+/*******************************************************************************
+* gqosGetIpPrioMapEn
+*
+* DESCRIPTION:
+*       This routine return the IP priority mapping state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       en    - GT_TRUE for user prio rule, GT_FALSE for otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetIpPrioMapEn
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *en
+);
+
+
+
+/*******************************************************************************
+* gqosUserPrioMapEn
+*
+* DESCRIPTION:
+*       This routine enables the user priority mapping.
+*
+* INPUTS:
+*       port - the logical port number.
+*       en   - GT_TRUE to Enable, GT_FALSE for otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosUserPrioMapEn
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  en
+);
+
+
+
+/*******************************************************************************
+* gqosGetUserPrioMapEn
+*
+* DESCRIPTION:
+*       This routine return the user priority mapping state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       en    - GT_TRUE for user prio rule, GT_FALSE for otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetUserPrioMapEn
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *en
+);
+
+
+
+/*******************************************************************************
+* gcosGetUserPrio2Tc
+*
+* DESCRIPTION:
+*       Gets the traffic class number for a specific 802.1p user priority.
+*
+* INPUTS:
+*       userPrior - user priority
+*
+* OUTPUTS:
+*       trClass - The Traffic Class the received frame is assigned.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*       Table - UserPrio2Tc
+*
+*******************************************************************************/
+GT_STATUS gcosGetUserPrio2Tc
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    userPrior,
+    OUT GT_U8   *trClass
+);
+
+
+/*******************************************************************************
+* gcosSetUserPrio2Tc
+*
+* DESCRIPTION:
+*       Sets the traffic class number for a specific 802.1p user priority.
+*
+* INPUTS:
+*       userPrior - user priority of a port.
+*       trClass   - the Traffic Class the received frame is assigned.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*       Table - UserPrio2Tc
+*
+*******************************************************************************/
+GT_STATUS gcosSetUserPrio2Tc
+(
+    IN GT_QD_DEV *dev,
+    IN GT_U8    userPrior,
+    IN GT_U8    trClass
+);
+
+
+/*******************************************************************************
+* gcosGetDscp2Tc
+*
+* DESCRIPTION:
+*       This routine retrieves the traffic class assigned for a specific
+*       IPv4 Dscp.
+*
+* INPUTS:
+*       dscp    - the IPv4 frame dscp to query.
+*
+* OUTPUTS:
+*       trClass - The Traffic Class the received frame is assigned.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*       Table - UserPrio2Tc
+*
+*******************************************************************************/
+GT_STATUS gcosGetDscp2Tc
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8   dscp,
+    OUT GT_U8   *trClass
+);
+
+
+/*******************************************************************************
+* gcosSetDscp2Tc
+*
+* DESCRIPTION:
+*       This routine sets the traffic class assigned for a specific
+*       IPv4 Dscp.
+*
+* INPUTS:
+*       dscp    - the IPv4 frame dscp to map.
+*       trClass - the Traffic Class the received frame is assigned.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*       Table - UserPrio2Tc
+*
+*******************************************************************************/
+GT_STATUS gcosSetDscp2Tc
+(
+    IN GT_QD_DEV *dev,
+    IN GT_U8    dscp,
+    IN GT_U8    trClass
+);
+
+
+/*******************************************************************************
+* qdLoadDriver
+*
+* DESCRIPTION:
+*       QuarterDeck Driver Initialization Routine. 
+*       This is the first routine that needs be called by system software. 
+*       It takes sysCfg from system software, and retures a pointer (*dev) 
+*       to a data structure which includes infomation related to this QuarterDeck
+*       device. This pointer (*dev) is then used for all the API functions. 
+*
+* INPUTS:
+*       sysCfg      - Holds system configuration parameters.
+*
+* OUTPUTS:
+*       dev         - Holds general system information.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_ALREADY_EXIST    - if device already started
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+* 	qdUnloadDriver is provided when the driver is not to be used anymore.
+*
+*******************************************************************************/
+GT_STATUS qdLoadDriver
+(
+    IN  GT_SYS_CONFIG   *sysCfg,
+    OUT GT_QD_DEV	*dev
+);
+
+
+/*******************************************************************************
+* qdUnloadDriver
+*
+* DESCRIPTION:
+*       This function unloads the QuaterDeck Driver.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       1.  This function should be called only after successful execution of
+*           qdLoadDriver().
+*
+*******************************************************************************/
+GT_STATUS qdUnloadDriver
+(
+    IN GT_QD_DEV* dev
+);
+
+
+/*******************************************************************************
+* sysEnable
+*
+* DESCRIPTION:
+*       This function enables the system for full operation.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS sysEnable
+(
+    IN GT_QD_DEV* dev
+);
+
+
+/*******************************************************************************
+* gsysSwReset
+*
+* DESCRIPTION:
+*       This routine preforms switch software reset.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSwReset
+(
+    IN GT_QD_DEV* dev
+);
+
+
+/*******************************************************************************
+* gsysSetDiscardExcessive
+*
+* DESCRIPTION:
+*       This routine set the Discard Excessive state.
+*
+* INPUTS:
+*       en - GT_TRUE Discard is enabled, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetDiscardExcessive
+(
+    IN GT_QD_DEV* dev,
+    IN GT_BOOL en
+);
+
+
+
+/*******************************************************************************
+* gsysGetDiscardExcessive
+*
+* DESCRIPTION:
+*       This routine get the Discard Excessive state.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE Discard is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetDiscardExcessive
+(
+    IN GT_QD_DEV* dev,
+    IN GT_BOOL *en
+);
+
+
+
+/*******************************************************************************
+* gsysSetSchedulingMode
+*
+* DESCRIPTION:
+*       This routine set the Scheduling Mode.
+*
+* INPUTS:
+*       mode - GT_TRUE wrr, GT_FALSE strict.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetSchedulingMode
+(
+    IN GT_QD_DEV* dev,
+    IN GT_BOOL mode
+);
+
+
+
+/*******************************************************************************
+* gsysGetSchedulingMode
+*
+* DESCRIPTION:
+*       This routine get the Scheduling Mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE wrr, GT_FALSE strict.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetSchedulingMode
+(
+    IN GT_QD_DEV *dev,
+    OUT GT_BOOL *mode
+);
+
+
+
+/*******************************************************************************
+* gsysSetMaxFrameSize
+*
+* DESCRIPTION:
+*       This routine Set the max frame size allowed.
+*
+* INPUTS:
+*       mode - GT_TRUE max size 1522, GT_FALSE max size 1535.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetMaxFrameSize
+(
+    IN GT_QD_DEV* dev,
+    IN GT_BOOL mode
+);
+
+
+
+/*******************************************************************************
+* gsysGetMaxFrameSize
+*
+* DESCRIPTION:
+*       This routine Get the max frame size allowed.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE max size 1522, GT_FALSE max size 1535.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetMaxFrameSize
+(
+    IN GT_QD_DEV *dev,
+    OUT GT_BOOL *mode
+);
+
+
+
+/*******************************************************************************
+* gsysReLoad
+*
+* DESCRIPTION:
+*       This routine cause to the switch to reload the EEPROM.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysReLoad
+(
+    IN GT_QD_DEV* dev
+);
+
+
+/*******************************************************************************
+* gsysSetWatchDog
+*
+* DESCRIPTION:
+*       This routine Set the the watch dog mode.
+*
+* INPUTS:
+*       en - GT_TRUE enables, GT_FALSE disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetWatchDog
+(
+    IN GT_QD_DEV* dev,
+    IN GT_BOOL en
+);
+
+
+
+/*******************************************************************************
+* gsysGetWatchDog
+*
+* DESCRIPTION:
+*       This routine Get the the watch dog mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE enables, GT_FALSE disable.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetWatchDog
+(
+    IN GT_QD_DEV* dev,
+    OUT GT_BOOL *en
+);
+
+
+/*******************************************************************************
+* gsysSetDuplexPauseMac
+*
+* DESCRIPTION:
+*       This routine sets the full duplex pause src Mac Address.
+*
+* INPUTS:
+*       mac - The Mac address to be set.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetDuplexPauseMac
+(
+    IN GT_QD_DEV* dev,
+    IN GT_ETHERADDR *mac
+);
+
+
+/*******************************************************************************
+* gsysGetDuplexPauseMac
+*
+* DESCRIPTION:
+*       This routine Gets the full duplex pause src Mac Address.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mac - the Mac address.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetDuplexPauseMac
+(
+    IN GT_QD_DEV* dev,
+    OUT GT_ETHERADDR *mac
+);
+
+
+
+/*******************************************************************************
+* gsysSetPerPortDuplexPauseMac
+*
+* DESCRIPTION:
+*       This routine sets whether the full duplex pause src Mac Address is per
+*       port or per device.
+*
+* INPUTS:
+*       en - GT_TURE per port mac, GT_FALSE global mac.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetPerPortDuplexPauseMac
+(
+    IN GT_QD_DEV* dev,
+    IN GT_BOOL en
+);
+
+
+
+/*******************************************************************************
+* gsysGetPerPortDuplexPauseMac
+*
+* DESCRIPTION:
+*       This routine Gets whether the full duplex pause src Mac Address is per
+*       port or per device.
+*
+* INPUTS:
+*       en - GT_TURE per port mac, GT_FALSE global mac.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPerPortDuplexPauseMac
+(
+    IN GT_QD_DEV* dev,
+    IN GT_BOOL *en
+);
+
+
+/*******************************************************************************
+* gsysReadMiiRegister
+*
+* DESCRIPTION:
+*       This routine reads QuarterDeck Registers. Since this routine is only for
+*		Diagnostic Purpose, no error checking will be performed.
+*		User has to know exactly which phy address(0 ~ 0x1F) will be read.
+*
+* INPUTS:
+*       phyAddr - Phy Address to read the register for.( 0 ~ 0x1F )
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysReadMiiReg
+(
+    IN GT_QD_DEV* dev,
+    IN  GT_U32	phyAddr,
+    IN  GT_U32	regAddr,
+    OUT GT_U32	*data
+);
+
+/*******************************************************************************
+* gsysWriteMiiRegister
+*
+* DESCRIPTION:
+*       This routine writes QuarterDeck Registers. Since this routine is only for
+*		Diagnostic Purpose, no error checking will be performed.
+*		User has to know exactly which phy address(0 ~ 0x1F) will be read.
+*
+* INPUTS:
+*       phyAddr - Phy Address to read the register for.( 0 ~ 0x1F )
+*       regAddr - The register's address.
+*       data    - data to be written.
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysWriteMiiReg
+(
+    IN GT_QD_DEV* dev,
+    IN  GT_U32	phyAddr,
+    IN  GT_U32	regAddr,
+    IN  GT_U16	data
+);
+
+/*******************************************************************************
+* gsysGetSW_Mode
+*
+* DESCRIPTION:
+*       This routine get the Switch mode. These two bits returen 
+*       the current value of the SW_MODE[1:0] pins.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE Discard is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+* 		This feature is for both clippership and fullsail
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetSW_Mode
+(
+    IN GT_QD_DEV* dev,
+    IN GT_SW_MODE *mode
+);
+
+/*******************************************************************************
+* gsysGetInitReady
+*
+* DESCRIPTION:
+*       This routine get the InitReady bit. This bit is set to a one when the ATU,
+*       the Queue Controller and the Statistics Controller are done with their 
+*       initialization and are ready to accept frames.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE: switch is ready, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+* 		This feature is for both clippership and fullsail
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetInitReady
+(
+    IN GT_QD_DEV* dev,
+    IN GT_BOOL *mode
+);
+
+
+/*******************************************************************************
+* gstatsFlushAll
+*
+* DESCRIPTION:
+*       Flush All RMON counters for all ports.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsFlushAll
+(
+    IN GT_QD_DEV* dev
+);
+
+/*******************************************************************************
+* gstatsFlushPort
+*
+* DESCRIPTION:
+*       Flush All RMON counters for a given port.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsFlushPort
+(
+    IN GT_QD_DEV* dev,
+    IN GT_LPORT	port
+);
+
+/*******************************************************************************
+* gstatsGetPortCounter
+*
+* DESCRIPTION:
+*		This routine gets a specific counter of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*		counter - the counter which will be read
+*
+* OUTPUTS:
+*		statsData - points to 32bit data storage for the MIB counter
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*		None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortCounter
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	IN  GT_STATS_COUNTERS	counter,
+	OUT GT_U32			*statsData
+);
+
+/*******************************************************************************
+* gstatsGetPortAllCounters
+*
+* DESCRIPTION:
+*       This routine gets all RMON counters of the given port
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       statsCounterSet - points to GT_STATS_COUNTER_SET for the MIB counters
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortAllCounters
+(
+	IN  GT_QD_DEV* dev,
+	IN  GT_LPORT		port,
+	OUT GT_STATS_COUNTER_SET	*statsCounterSet
+);
+
+
+/*******************************************************************************
+* grcSetLimitMode
+*
+* DESCRIPTION:
+*       This routine sets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       port	- logical port number.
+*       mode 	- rate control ingress limit mode. 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*******************************************************************************/
+GT_STATUS grcSetLimitMode
+(
+    IN GT_QD_DEV*            dev,
+    IN GT_LPORT 	     port,
+    IN GT_RATE_LIMIT_MODE    mode
+);
+
+/*******************************************************************************
+* grcGetLimitMode
+*
+* DESCRIPTION:
+*       This routine gets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       mode 	- rate control ingress limit mode. 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS grcGetLimitMode
+(
+    IN GT_QD_DEV* dev,
+    IN  GT_LPORT port,
+    OUT GT_RATE_LIMIT_MODE    *mode
+);
+
+/*******************************************************************************
+* grcSetPri3Rate
+*
+* DESCRIPTION:
+*       This routine sets the ingress data rate limit for priority 3 frames.
+*       Priority 3 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the priority 3 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri2Rate
+*              GT_TRUE:  use twice the rate as Pri2Rate
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+*******************************************************************************/
+GT_STATUS grcSetPri3Rate
+(
+    IN GT_QD_DEV*            dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+/*******************************************************************************
+* grcGetPri3Rate
+*
+* DESCRIPTION:
+*       This routine gets the ingress data rate limit for priority 3 frames.
+*       Priority 3 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       
+* OUTPUTS:
+*       mode - the priority 3 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri2Rate
+*              GT_TRUE:  use twice the rate as Pri2Rate
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS grcGetPri3Rate
+(
+    IN GT_QD_DEV* dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+/*******************************************************************************
+* grcSetPri2Rate
+*
+* DESCRIPTION:
+*       This routine sets the ingress data rate limit for priority 2 frames.
+*       Priority 2 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the priority 2 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri1Rate
+*              GT_TRUE:  use twice the rate as Pri1Rate
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+*******************************************************************************/
+GT_STATUS grcSetPri2Rate
+(
+    IN GT_QD_DEV*            dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+/*******************************************************************************
+* grcGetPri2Rate
+*
+* DESCRIPTION:
+*       This routine gets the ingress data rate limit for priority 2 frames.
+*       Priority 2 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       
+* OUTPUTS:
+*       mode - the priority 2 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri1Rate
+*              GT_TRUE:  use twice the rate as Pri1Rate
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS grcGetPri2Rate
+(
+    IN GT_QD_DEV*            dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+/*******************************************************************************
+* grcSetPri1Rate
+*
+* DESCRIPTION:
+*       This routine sets the ingress data rate limit for priority 1 frames.
+*       Priority 1 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the priority 1 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri0Rate
+*              GT_TRUE:  use twice the rate as Pri0Rate
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+*******************************************************************************/
+GT_STATUS grcSetPri1Rate
+(
+    IN GT_QD_DEV*            dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+/*******************************************************************************
+* grcGetPri1Rate
+*
+* DESCRIPTION:
+*       This routine gets the ingress data rate limit for priority 1 frames.
+*       Priority 1 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       
+* OUTPUTS:
+*       mode - the priority 1 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri0Rate
+*              GT_TRUE:  use twice the rate as Pri0Rate
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS grcGetPri1Rate
+(
+    IN GT_QD_DEV*            dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+/*******************************************************************************
+* grcSetPri0Rate
+*
+* DESCRIPTION:
+*       This routine sets the port's ingress data limit for priority 0 frames.
+*
+* INPUTS:
+*       port	- logical port number.
+*       rate    - ingress data rate limit for priority 0 frames. These frames
+*       	  will be discarded after the ingress rate selected is reached 
+*       	  or exceeded. 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS grcSetPri0Rate
+(
+    IN GT_QD_DEV*            dev,
+    IN GT_LPORT        port,
+    IN GT_PRI0_RATE    rate
+);
+
+/*******************************************************************************
+* grcGetPri0Rate
+*
+* DESCRIPTION:
+*       This routine gets the port's ingress data limit for priority 0 frames.
+*
+* INPUTS:
+*       port	- logical port number to set.
+*
+* OUTPUTS:
+*       rate    - ingress data rate limit for priority 0 frames. These frames
+*       	  will be discarded after the ingress rate selected is reached 
+*       	  or exceeded. 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS grcGetPri0Rate
+(
+    IN GT_QD_DEV*            dev,
+    IN  GT_LPORT port,
+    OUT GT_PRI0_RATE    *rate
+);
+
+/*******************************************************************************
+* grcSetBytesCount
+*
+* DESCRIPTION:
+*       This routine sets the byets to count for limiting needs to be determined
+*
+* INPUTS:
+*       port	  - logical port number to set.
+*    	limitMGMT - GT_TRUE: To limit and count MGMT frame bytes
+*    		    GT_FALSE: otherwise
+*    	countIFG  - GT_TRUE: To count IFG bytes
+*    		    GT_FALSE: otherwise
+*    	countPre  - GT_TRUE: To count Preamble bytes
+*    		    GT_FALSE: otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS grcSetBytesCount
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_LPORT        	port,
+    IN GT_BOOL 		limitMGMT,
+    IN GT_BOOL 		countIFG,
+    IN GT_BOOL 		countPre
+);
+
+/*******************************************************************************
+* grcGetBytesCount
+*
+* DESCRIPTION:
+*       This routine gets the byets to count for limiting needs to be determined
+*
+* INPUTS:
+*       port	- logical port number 
+*
+* OUTPUTS:
+*    	limitMGMT - GT_TRUE: To limit and count MGMT frame bytes
+*    		    GT_FALSE: otherwise
+*    	countIFG  - GT_TRUE: To count IFG bytes
+*    		    GT_FALSE: otherwise
+*    	countPre  - GT_TRUE: To count Preamble bytes
+*    		    GT_FALSE: otherwise
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS grcGetBytesCount
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_LPORT        	port,
+    IN GT_BOOL 		*limitMGMT,
+    IN GT_BOOL 		*countIFG,
+    IN GT_BOOL 		*countPre
+);
+
+/*******************************************************************************
+* grcSetEgressRate
+*
+* DESCRIPTION:
+*       This routine sets the port's egress data limit.
+*		
+*
+* INPUTS:
+*       port      - logical port number.
+*       rateType  - egress data rate limit (GT_ERATE_TYPE union type). 
+*					union type is used to support multiple devices with the
+*					different formats of egress rate.
+*					GT_ERATE_TYPE has the following fields:
+*						definedRate - GT_EGRESS_RATE enum type should used for the 
+*							following devices:
+*							88E6218, 88E6318, 88E6063, 88E6083, 88E6181, 88E6183,
+*							88E6093, 88E6095, 88E6185, 88E6108, 88E6065, 88E6061, 
+*							and their variations
+*						kbRate - rate in kbps that should used for the following 
+*							devices:
+*							88E6097, 88E6096 with the GT_PIRL_ELIMIT_MODE of 
+*								GT_PIRL_ELIMIT_LAYER1,
+*								GT_PIRL_ELIMIT_LAYER2, or 
+*								GT_PIRL_ELIMIT_LAYER3 (see grcSetELimitMode)
+*							64kbps ~ 1Mbps    : increments of 64kbps,
+*							1Mbps ~ 100Mbps   : increments of 1Mbps, and
+*							100Mbps ~ 1000Mbps: increments of 10Mbps
+*							Therefore, the valid values are:
+*								64, 128, 192, 256, 320, 384,..., 960,
+*								1000, 2000, 3000, 4000, ..., 100000,
+*								110000, 120000, 130000, ..., 1000000.
+*						fRate - frame per second that should used for the following
+*							devices:
+*							88E6097, 88E6096 with GT_PIRL_ELIMIT_MODE of 
+*								GT_PIRL_ELIMIT_FRAME
+*							Valid values are between 7600 and 1488000
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*			GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_EGRESS_RATE enum
+*			are supported only by Gigabit Ethernet Switch.
+*
+*******************************************************************************/
+GT_STATUS grcSetEgressRate
+(
+    IN GT_QD_DEV       *dev,
+    IN GT_LPORT        port,
+    IN GT_ERATE_TYPE   *rateType
+);
+
+/*******************************************************************************
+* grcGetEgressRate
+*
+* DESCRIPTION:
+*       This routine gets the port's egress data limit.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       rateType  - egress data rate limit (GT_ERATE_TYPE union type). 
+*					union type is used to support multiple devices with the
+*					different formats of egress rate.
+*					GT_ERATE_TYPE has the following fields:
+*						definedRate - GT_EGRESS_RATE enum type should used for the 
+*							following devices:
+*							88E6218, 88E6318, 88E6063, 88E6083, 88E6181, 88E6183,
+*							88E6093, 88E6095, 88E6185, 88E6108, 88E6065, 88E6061, 
+*							and their variations
+*						kbRate - rate in kbps that should used for the following 
+*							devices:
+*							88E6097, 88E6096 with the GT_PIRL_ELIMIT_MODE of 
+*								GT_PIRL_ELIMIT_LAYER1,
+*								GT_PIRL_ELIMIT_LAYER2, or 
+*								GT_PIRL_ELIMIT_LAYER3 (see grcSetELimitMode)
+*							64kbps ~ 1Mbps    : increments of 64kbps,
+*							1Mbps ~ 100Mbps   : increments of 1Mbps, and
+*							100Mbps ~ 1000Mbps: increments of 10Mbps
+*							Therefore, the valid values are:
+*								64, 128, 192, 256, 320, 384,..., 960,
+*								1000, 2000, 3000, 4000, ..., 100000,
+*								110000, 120000, 130000, ..., 1000000.
+*						fRate - frame per second that should used for the following
+*							devices:
+*							88E6097, 88E6096 with GT_PIRL_ELIMIT_MODE of 
+*								GT_PIRL_ELIMIT_FRAME
+*							Valid values are between 7600 and 1488000
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*			GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_EGRESS_RATE enum
+*			are supported only by Gigabit Ethernet Switch.
+*
+*******************************************************************************/
+GT_STATUS grcGetEgressRate
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_ERATE_TYPE  *rateType
+);
+
+
+/*******************************************************************************
+* gpavSetPAV
+*
+* DESCRIPTION:
+*       This routine sets the Port Association Vector 
+*
+* INPUTS:
+*       port	- logical port number.
+*       pav 	- Port Association Vector 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS gpavSetPAV
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_LPORT	port,
+    IN GT_U16	pav
+);
+
+/*******************************************************************************
+* gpavGetPAV
+*
+* DESCRIPTION:
+*       This routine gets the Port Association Vector 
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       pav 	- Port Association Vector 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS gpavGetPAV
+(
+    IN GT_QD_DEV*       dev,
+    IN  GT_LPORT port,
+    OUT GT_U16    *pav
+);
+
+/*******************************************************************************
+* gpavSetIngressMonitor
+*
+* DESCRIPTION:
+*       This routine sets the Ingress Monitor bit in the PAV.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the ingress monitor bit in the PAV
+*              GT_FALSE: Ingress Monitor enabled 
+*              GT_TRUE:  Ingress Monitor disabled 
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*******************************************************************************/
+GT_STATUS gpavSetIngressMonitor
+(
+    IN GT_QD_DEV*       dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+);
+
+/*******************************************************************************
+* gpavGetIngressMonitor
+*
+* DESCRIPTION:
+*       This routine gets the Ingress Monitor bit in the PAV.
+*
+* INPUTS:
+*       port - the logical port number.
+*       
+* OUTPUTS:
+*       mode - the ingress monitor bit in the PAV
+*              GT_FALSE: Ingress Monitor enabled 
+*              GT_TRUE:  Ingress Monitor disabled 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+*******************************************************************************/
+GT_STATUS gpavGetIngressMonitor
+(
+    IN GT_QD_DEV*       dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+);
+
+/*******************************************************************************
+* gvctGetCableStatus
+*
+* DESCRIPTION:
+*       This routine perform the virtual cable test for the requested port,
+*       and returns the the status per MDI pair.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*       cableStatus - the port copper cable status.
+*       cableLen    - the port copper cable length.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED- if current device does not support this feature.
+*
+* COMMENTS:
+*       Internal Gigabit Phys in 88E6165 family and 88E6351 family devices
+*		are not supported by this API. For those devices, gvctGetAdvCableDiag 
+*		API can be used, instead.
+*
+*******************************************************************************/
+GT_STATUS gvctGetCableDiag
+(
+    IN GT_QD_DEV*       dev,
+    IN  GT_LPORT        port,
+    OUT GT_CABLE_STATUS *cableStatus
+);
+
+
+/*******************************************************************************
+* gvctGet1000BTExtendedStatus
+*
+* DESCRIPTION:
+*       This routine retrieves extended cable status, such as Pair Poloarity,
+*		Pair Swap, and Pair Skew. Note that this routine will be success only
+*		if 1000Base-T Link is up.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*       extendedStatus - the extended cable status.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED- if current device does not support this feature.
+*
+* COMMENTS:
+*       Internal Gigabit Phys in 88E6165 family and 88E6351 family devices
+*		are not supported by this API. For those devices, gvctGetAdvExtendedStatus 
+*		API can be used, instead.
+*
+*******************************************************************************/
+GT_STATUS gvctGet1000BTExtendedStatus
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_LPORT        port,
+    OUT GT_1000BT_EXTENDED_STATUS *extendedStatus
+);
+
+
+/*******************************************************************************
+* gtMemSet
+*
+* DESCRIPTION:
+*       Set a block of memory
+*
+* INPUTS:
+*       start  - start address of memory block for setting
+*       simbol - character to store, converted to an unsigned char
+*       size   - size of block to be set
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       Pointer to set memory block
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void * gtMemSet
+(
+    IN void * start,
+    IN int    symbol,
+    IN GT_U32 size
+);
+
+/*******************************************************************************
+* gtMemCpy
+*
+* DESCRIPTION:
+*       Copies 'size' characters from the object pointed to by 'source' into
+*       the object pointed to by 'destination'. If copying takes place between
+*       objects that overlap, the behavior is undefined.
+*
+* INPUTS:
+*       destination - destination of copy
+*       source      - source of copy
+*       size        - size of memory to copy
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       Pointer to destination
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void * gtMemCpy
+(
+    IN void *       destination,
+    IN const void * source,
+    IN GT_U32       size
+);
+
+
+/*******************************************************************************
+* gtMemCmp
+*
+* DESCRIPTION:
+*       Compares given memories.
+*
+* INPUTS:
+*       src1 - source 1
+*       src2 - source 2
+*       size - size of memory to copy
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       0, if equal.
+*		negative number, if src1 < src2.
+*		positive number, if src1 > src2.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int gtMemCmp
+(
+    IN char src1[],
+    IN char src2[],
+    IN GT_U32 size
+);
+
+/*******************************************************************************
+* gtStrlen
+*
+* DESCRIPTION:
+*       Determine the length of a string
+* INPUTS:
+*       source  - string
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       size    - number of characters in string, not including EOS.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_U32 gtStrlen
+(
+    IN const void * source
+);
+
+/*******************************************************************************
+* gtDelay
+*
+* DESCRIPTION:
+*       Wait for the given uSec and return.
+*		Current Switch devices with Gigabit Ethernet Support require 250 uSec
+*		of delay time for PPU to be disabled.
+*		Since this function is System and/or OS dependent, it should be provided
+*		by each DSDT user.
+*
+* INPUTS:
+*       delayTime - delay in uSec.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void gtDelay
+(
+    IN const unsigned int delayTime
+);
+
+
+/*******************************************************************************
+* gtVersion
+*
+* DESCRIPTION:
+*       This function returns the version of the QuarterDeck SW suite.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       version     - QuarterDeck software version.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_BAD_PARAM on bad parameters,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gtVersion
+(
+    OUT GT_VERSION   *version
+);
+
+
+/* Prototypes added for Gigabit Ethernet Switch Support */
+
+
+/* gtBrgFdb.c */
+
+/*******************************************************************************
+* gfdbMove
+*
+* DESCRIPTION:
+*		This routine moves all or unblocked addresses from a port to another.
+*
+* INPUTS:
+*		moveCmd  - the move operation type.
+*		moveFrom - port where moving from
+*		moveTo   - port where moving to
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbMove
+(
+	IN GT_QD_DEV 	*dev,
+	IN GT_MOVE_CMD	moveCmd,
+	IN GT_U32		moveFrom,
+	IN GT_U32		moveTo
+);
+
+/*******************************************************************************
+* gfdbMoveInDB
+*
+* DESCRIPTION:
+* 		This routine move all or unblocked addresses which are in the particular
+* 		ATU Database (DBNum) from a port to another.
+*
+* INPUTS:
+* 		moveCmd  - the move operation type.
+*		DBNum	 	- ATU MAC Address Database Number.
+*		moveFrom - port where moving from
+*		moveTo   - port where moving to
+*
+* OUTPUTS:
+*     None
+*
+* RETURNS:
+* 		GT_OK           - on success
+* 		GT_FAIL         - on error
+* 		GT_NOT_SUPPORTED- if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbMoveInDB
+(
+	IN GT_QD_DEV   *dev,
+	IN GT_MOVE_CMD moveCmd,
+	IN GT_U32 		DBNum,
+	IN GT_U32		moveFrom,
+	IN GT_U32		moveTo
+);
+
+/* gtBrgStp.c */
+
+/* gtBrgVlan.c */
+
+/* gtBrgVtu.c */
+
+/* gtEvents.c */
+
+/*******************************************************************************
+* gatuGetIntStatus
+*
+* DESCRIPTION:
+*		Check to see if a specific type of ATU interrupt occured
+*
+* INPUTS:
+*     intType - the type of interrupt which causes an interrupt.
+*					GT_MEMEBER_VIOLATION, GT_MISS_VIOLATION, or GT_FULL_VIOLATION 
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gatuGetIntStatus
+(
+	IN  GT_QD_DEV				*dev,
+	OUT GT_ATU_INT_STATUS	*atuIntStatus
+);
+
+
+/* gtPhyCtrl.c */
+
+/*******************************************************************************
+* gprtSet1000TMasterMode
+*
+* DESCRIPTION:
+*		This routine set the port multicast rate limit.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_1000T_MASTER_SLAVE structure
+*				autoConfig   - GT_TRUE for auto, GT_FALSE for manual setup.
+*				masterPrefer - GT_TRUE if Master configuration is preferred.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSet1000TMasterMode
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_1000T_MASTER_SLAVE	*mode
+);
+
+/*******************************************************************************
+* gprtGet1000TMasterMode
+*
+* DESCRIPTION:
+*		This routine set the port multicast rate limit.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_1000T_MASTER_SLAVE structure
+*				autoConfig   - GT_TRUE for auto, GT_FALSE for manual setup.
+*				masterPrefer - GT_TRUE if Master configuration is preferred.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGet1000TMasterMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_1000T_MASTER_SLAVE	*mode
+);
+
+/*******************************************************************************
+* gprtGetPhyReg
+*
+* DESCRIPTION:
+*		This routine reads Phy Registers.
+*
+* INPUTS:
+*		port    - logical port number
+*		regAddr - The register's address.
+*
+* OUTPUTS:
+*		data    - The read register's data.
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_FAIL         - on error
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPhyReg
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_U32	 	regAddr,
+	OUT GT_U16	 	*data
+);
+
+/*******************************************************************************
+* gprtSetPhyReg
+*
+* DESCRIPTION:
+*		This routine writes Phy Registers.
+*		
+* INPUTS:
+*		port    - logical port number
+*		regAddr - The register's address.
+*
+* OUTPUTS:
+*		data    - The read register's data.
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_FAIL         - on error
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPhyReg
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_U32	 	regAddr,
+	IN  GT_U16	 	data
+);
+
+
+/* gtPortCtrl.c */
+
+/*******************************************************************************
+* gprtSetDropOnLock
+*
+* DESCRIPTION:
+*		This routine set the Drop on Lock. When set to one, Ingress frames will
+*		be discarded if their SA field is not in the ATU's address database.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for Unknown SA drop or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDropOnLock
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetDropOnLock
+*
+* DESCRIPTION:
+*		This routine gets DropOnLock mode.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: DropOnLock enabled,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDropOnLock
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gprtSetDoubleTag
+*
+* DESCRIPTION:
+*		This routine set the Ingress Double Tag Mode. When set to one, 
+*		ingressing frames are examined to see if they contain an 802.3ac tag.
+*		If they do, the tag is removed and then the frame is processed from
+*		there (i.e., removed tag is ignored). Essentially, untagged frames
+*		remain untagged, single tagged frames become untagged and double tagged
+*		frames become single tagged.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for DoulbeTag mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDoubleTag
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetDoubleTag
+*
+* DESCRIPTION:
+*		This routine gets DoubleTag mode.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: DoubleTag enabled,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDoubleTag
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gprtSetInterswitchPort
+*
+* DESCRIPTION:
+*		This routine set Interswitch Port. When set to one, 
+*		it indicates this port is a interswitch port used to communicated with
+*		CPU or to cascade with another switch device.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for Interswitch port or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetInterswitchPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetInterswithPort
+*
+* DESCRIPTION:
+*		This routine gets InterswitchPort.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: This port is interswitch port,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetInterswitchPort
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gprtSetLearnDisable
+*
+* DESCRIPTION:
+*		This routine enables/disables automatic learning of new source MAC
+*		addresses on the given port ingress
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for disable or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetLearnDisable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+);
+
+
+/*******************************************************************************
+* gprtGetLearnDisable
+*
+* DESCRIPTION:
+*		This routine gets LearnDisable setup
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: Learning disabled on the given port ingress frames,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetLearnDisable
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+/*******************************************************************************
+* gprtSetLearnEnable
+*
+* DESCRIPTION:
+*		This routine enables/disables automatic learning of new source MAC
+*		addresses on the given port ingress
+*
+* INPUTS:
+*		port - the logical port number.
+*		enable - GT_TRUE for disable or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetLearnEnable
+( 
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		enable
+);
+/*******************************************************************************
+* gfdbGetLearnEnable
+*
+* DESCRIPTION:
+*       Get automatic learning status of new source MAC addresses on port ingress.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*       enable - GT_TRUE if enabled  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetLearnEnable
+(
+    IN GT_QD_DEV  *dev,
+	 IN GT_LPORT		port,    
+    OUT GT_BOOL  *enble
+);
+/*******************************************************************************
+* gprtSetIgnoreFCS
+*
+* DESCRIPTION:
+*		This routine sets FCS Ignore mode. When this bit is set to a one,
+*		the last four bytes of frames received on this port are overwritten with
+*		a good CRC and the frames will be accepted by the switch.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for ignore FCS or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIgnoreFCS
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL 		mode
+);
+
+/*******************************************************************************
+* gprtGetIgnoreFCS
+*
+* DESCRIPTION:
+*		This routine gets Ignore FCS setup
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: Ignore FCS on the given port's ingress frames,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIgnoreFCS
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gprtSetVTUPriOverride
+*
+* DESCRIPTION:
+*		VTU Priority Override. The following modes are supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's VID (in the VTU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's VID (in the VTU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_PRI_OVERRIDE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if mode is invalid
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtSetVTUPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_PRI_OVERRIDE		mode
+);
+
+/*******************************************************************************
+* gprtGetVTUPriOverride
+*
+* DESCRIPTION:
+*		VTU Priority Override. The following modes are supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's VID (in the VTU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's VID (in the VTU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_PRI_OVERRIDE type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtGetVTUPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_PRI_OVERRIDE		*mode
+);
+
+/*******************************************************************************
+* gprtSetSAPriOverride
+*
+* DESCRIPTION:
+*		SA Priority Override. The following mode is supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's SA (in the ATU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's SA (in the ATU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_PRI_OVERRIDE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if mode is invalid
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtSetSAPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetSAPriOverride
+*
+* DESCRIPTION:
+*		SA Priority Override. The following mode is supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's SA (in the ATU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's SA (in the ATU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_PRI_OVERRIDE type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtGetSAPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_PRI_OVERRIDE		*mode
+);
+
+/*******************************************************************************
+* gprtSetDAPriOverride
+*
+* DESCRIPTION:
+*		DA Priority Override. The following mode is supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's DA (in the ATU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's DA (in the ATU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_PRI_OVERRIDE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if mode is invalid
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtSetDAPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_PRI_OVERRIDE		mode
+);
+
+/*******************************************************************************
+* gprtGetDAPriOverride
+*
+* DESCRIPTION:
+*		DA Priority Override. The following mode is supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's DA (in the ATU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's DA (in the ATU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_PRI_OVERRIDE type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtGetDAPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_PRI_OVERRIDE		*mode
+);
+
+/*******************************************************************************
+* gprtSetCPUPort
+*
+* DESCRIPTION:
+*		This routine sets CPU Port number. When Snooping is enabled on this port
+*		or when this port is configured as an Interswitch Port and it receives a 
+*		To_CPU frame, the switch needs to know what port on this device the frame 
+*		should egress.
+*
+* INPUTS:
+*		port - the logical port number.
+*		cpuPort - CPU Port number or interswitch port where CPU Port is connected
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetCPUPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_LPORT 	cpuPort
+);
+
+/*******************************************************************************
+* gprtGetCPUPort
+*
+* DESCRIPTION:
+*		This routine gets CPU Logical Port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		cpuPort - CPU Port's logical number
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetCPUPort
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_LPORT 	*cpuLPort
+);
+
+/*******************************************************************************
+* gprtSetLockedPort
+*
+* DESCRIPTION:
+*		This routine sets LockedPort. When it's set to one, CPU directed 
+*		learning for 802.1x MAC authentication is enabled on this port. In this
+*		mode, an ATU Miss Violation interrupt will occur when a new SA address
+*		is received in a frame on this port. Automatically SA learning and 
+*		refreshing is disabled in this mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for Locked Port, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetLockedPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetLockedPort
+*
+* DESCRIPTION:
+*		This routine gets Locked Port mode for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if LockedPort, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetLockedPort
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL  	*mode
+);
+
+/*******************************************************************************
+* gprtSetIgnoreWrongData
+*
+* DESCRIPTION:
+*		This routine sets Ignore Wrong Data. If the frame's SA address is found 
+*		in the database and if the entry is 'static' or if the port is 'locked'
+*		the source port's bit is checked to insure the SA has been assigned to 
+*		this port. If the SA is NOT assigned to this port, it is considered an 
+*		ATU Member Violation. If the IgnoreWrongData is set to GT_FALSE, an ATU
+*		Member Violation interrupt will be generated. If it's set to GT_TRUE,
+*		the ATU Member Violation error will be masked and ignored.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for IgnoreWrongData, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIgnoreWrongData
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+);
+
+
+/*******************************************************************************
+* gprtGetIgnoreWrongData
+*
+* DESCRIPTION:
+*		This routine gets Ignore Wrong Data mode for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if IgnoreWrongData, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIgnoreWrongData
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+);
+
+
+/* gtPortRateCtrl.c */
+
+/* gtPortRmon.c */
+
+/*******************************************************************************
+* gstatsGetPortCounter2
+*
+* DESCRIPTION:
+*		This routine gets a specific counter of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*		counter - the counter which will be read
+*
+* OUTPUTS:
+*		statsData - points to 32bit data storage for the MIB counter
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*		This function supports Gigabit Switch only
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortCounter2
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	IN  GT_STATS_COUNTERS2	counter,
+	OUT GT_U32			*statsData
+);
+
+
+/*******************************************************************************
+* gstatsGetPortAllCounters2
+*
+* DESCRIPTION:
+*		This routine gets all counters of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		statsCounterSet - points to GT_STATS_COUNTER_SET for the MIB counters
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*		This function supports Gigabit Switch only
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortAllCounters2
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	OUT GT_STATS_COUNTER_SET2	*statsCounterSet
+);
+
+/*******************************************************************************
+* gstatsGetHistogramMode
+*
+* DESCRIPTION:
+*		This routine gets the Histogram Counters Mode.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - Histogram Mode (GT_COUNT_RX_ONLY, GT_COUNT_TX_ONLY, 
+*					and GT_COUNT_RX_TX)
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_BAD_PARAM    - on bad parameter
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		This function supports Gigabit Switch only
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetHistogramMode
+(
+	IN  GT_QD_DEV				*dev,
+	OUT GT_HISTOGRAM_MODE	*mode
+);
+
+/*******************************************************************************
+* gstatsSetHistogramMode
+*
+* DESCRIPTION:
+*		This routine sets the Histogram Counters Mode.
+*
+* INPUTS:
+*		mode - Histogram Mode (GT_COUNT_RX_ONLY, GT_COUNT_TX_ONLY, 
+*					and GT_COUNT_RX_TX)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_BAD_PARAM    - on bad parameter
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsSetHistogramMode
+(
+	IN GT_QD_DEV 				*dev,
+	IN GT_HISTOGRAM_MODE		mode
+);
+
+
+/* gtPortStatus.c */
+
+/*******************************************************************************
+* gprtGetPauseEn
+*
+* DESCRIPTION:
+*		This routine retrives the link pause state.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE for enable or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		If set MAC Pause (for Full Duplex flow control) is implemented in the
+*		link partner and in MyPause
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPauseEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*state
+);
+
+/*******************************************************************************
+* gprtGetHdFlow
+*
+* DESCRIPTION:
+*		This routine retrives the half duplex flow control value.
+*		If set, Half Duplex back pressure will be used on this port if this port
+*		is in a half duplex mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE for enable or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHdFlow
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL 	*state
+);
+
+/*******************************************************************************
+* gprtGetPHYDetect
+*
+* DESCRIPTION:
+*		This routine retrives the information regarding PHY detection.
+*		If set, An 802.3 PHY is attached to this port.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if connected or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPHYDetect
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL 	*state
+);
+
+/*******************************************************************************
+* gprtSetPHYDetect
+*
+* DESCRIPTION:
+*		This routine sets PHYDetect bit which make PPU change its polling.
+*		PPU's pool routine uses these bits to determine which port's to poll
+*		PHYs on for Link, Duplex, Speed, and Flow Control.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE or GT_FALSE
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		This function should not be called if gsysGetPPUState returns 
+*		PPU_STATE_ACTIVE.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPHYDetect
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_BOOL  	state
+);
+
+/*******************************************************************************
+* gprtGetSpeedMode
+*
+* DESCRIPTION:
+*       This routine retrives the port speed.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_PORT_SPEED_MODE type.
+*					(PORT_SPEED_1000_MBPS,PORT_SPEED_100_MBPS, or PORT_SPEED_10_MBPS)
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSpeedMode
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_PORT_SPEED_MODE   *speed
+);
+
+/*******************************************************************************
+* gprtGetHighErrorRate
+*
+* DESCRIPTION:
+*		This routine retrives the PCS High Error Rate.
+*		This routine returns GT_TRUE if the rate of invalid code groups seen by
+*		PCS has exceeded 10 to the power of -11.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE or GT_FALSE
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHighErrorRate
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gprtGetTxPaused
+*
+* DESCRIPTION:
+*		This routine retrives Transmit Pause state.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Rx MAC receives a PAUSE frame with none-zero Puase Time
+*				  GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetTxPaused
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+
+/*******************************************************************************
+* gprtGetFlowCtrl
+*
+* DESCRIPTION:
+*		This routine retrives Flow control state.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Rx MAC determines that no more data should be 
+*					entering this port.
+*				  GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetFlowCtrl
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gprtGetC_Duplex
+*
+* DESCRIPTION:
+*		This routine retrives Port 9's duplex configuration mode determined
+*		at reset.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if configured as Full duplex operation
+*				  GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Return value is valid only if the given port is 9.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetC_Duplex
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gprtGetC_Mode
+*
+* DESCRIPTION:
+*		This routine retrives port's interface type configuration mode 
+*		determined at reset.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - one of value in GT_PORT_CONFIG_MODE enum type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Return value is valid only if the given port is 9.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetC_Mode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_PORT_CONFIG_MODE   *state
+);
+
+
+/* gtSysCtrl.c */
+
+/*******************************************************************************
+* gsysSetPPUEn
+*
+* DESCRIPTION:
+*		This routine enables/disables Phy Polling Unit.
+*
+* INPUTS:
+*		en - GT_TRUE to enable PPU, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetPPUEn
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL 		en
+);
+
+/*******************************************************************************
+* gsysGetPPUEn
+*
+* DESCRIPTION:
+*		This routine get the PPU state.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if PPU is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_BAD_PARAM    - on bad parameter
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPPUEn
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetCascadePort
+*
+* DESCRIPTION:
+*		This routine sets Cascade Port number.
+*		In multichip systems frames coming from a CPU need to know when they
+*		have reached their destination chip.
+*
+* INPUTS:
+*		port - Cascade Port
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetCascadePort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port
+);
+
+/*******************************************************************************
+* gsysGetCascadePort
+*
+* DESCRIPTION:
+*		This routine gets Cascade Port number.
+*		In multichip systems frames coming from a CPU need to know when they
+*		have reached their destination chip.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port - Cascade Port
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetCascadePort
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT 	*port
+);
+
+/*******************************************************************************
+* gsysSetDeviceNumber
+*
+* DESCRIPTION:
+*		This routine sets Device Number.
+*		In multichip systems frames coming from a CPU need to know when they
+*		have reached their destination chip. From CPU frames whose Dev_Num
+*		fieldmatches these bits have reachedtheir destination chip and are sent
+*		out this chip using the port number indicated in the frame's Trg_Port 
+*		field.
+*
+* INPUTS:
+*		devNum - Device Number (0 ~ 31)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetDeviceNumber
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		devNum
+);
+
+/*******************************************************************************
+* gsysGetDeviceNumber
+*
+* DESCRIPTION:
+*		This routine gets Device Number.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		devNum - Device Number (0 ~ 31)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetDeviceNumber
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U32  	*devNum
+);
+
+
+/* gtPCSCtrl.c */
+
+
+/*******************************************************************************
+* gpcsGetCommaDet
+*
+* DESCRIPTION:
+*		This routine retrieves Comma Detection status in PCS
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE for Comma Detected or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetCommaDet
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsGetSyncOK
+*
+* DESCRIPTION:
+*		This routine retrieves SynOK bit. It is set to a one when the PCS has
+*		detected a few comma patterns and is synchronized with its peer PCS 
+*		layer.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if synchronized or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetSyncOK
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsGetSyncFail
+*
+* DESCRIPTION:
+*		This routine retrieves SynFail bit.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if synchronizaion failed or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetSyncFail
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsGetAnBypassed
+*
+* DESCRIPTION:
+*		This routine retrieves Inband Auto-Negotiation bypass status.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if AN is bypassed or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetAnBypassed
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsGetAnBypassMode
+*
+* DESCRIPTION:
+*		This routine retrieves Enable mode of Inband Auto-Negotiation bypass.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE if AN bypass is enabled or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetAnBypassMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*mode
+);
+
+/*******************************************************************************
+* gpcsSetAnBypassMode
+*
+* DESCRIPTION:
+*		This routine retrieves Enable mode of Inband Auto-Negotiation bypass.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to enable AN bypass mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetAnBypassMode
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL  	mode
+);
+
+/*******************************************************************************
+* gpcsGetPCSAnEn
+*
+* DESCRIPTION:
+*		This routine retrieves Enable mode of PCS Inband Auto-Negotiation.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE if PCS AN is enabled or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetPCSAnEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*mode
+);
+
+/*******************************************************************************
+* gpcsSetPCSAnEn
+*
+* DESCRIPTION:
+*		This routine sets Enable mode of PCS Inband Auto-Negotiation.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to enable PCS AN mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetPCSAnEn
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL  	mode
+);
+
+/*******************************************************************************
+* gpcsSetRestartPCSAn
+*
+* DESCRIPTION:
+*		This routine restarts PCS Inband Auto-Negotiation.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetRestartPCSAn
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port
+);
+
+/*******************************************************************************
+* gpcsGetPCSAnDone
+*
+* DESCRIPTION:
+*		This routine retrieves completion information of PCS Auto-Negotiation.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE if PCS AN is done or never done
+*			    GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetPCSAnDone
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*mode
+);
+
+/*******************************************************************************
+* gpcsSetLinkValue
+*
+* DESCRIPTION:
+*		This routine sets Link's force value
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force link up, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetLinkValue
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+);
+
+/*******************************************************************************
+* gpcsGetLinkValue
+*
+* DESCRIPTION:
+*		This routine retrieves Link Value which will be used for Forcing Link 
+*		up or down.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Link Force value is one (link up)
+*			     GT_FALSE otherwise (link down)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetLinkValue
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsSetForcedLink
+*
+* DESCRIPTION:
+*		This routine forces Link. If LinkValue is set to one, calling this 
+*		routine with GT_TRUE will force Link to be up.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force link (up or down), GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetForcedLink
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+);
+
+/*******************************************************************************
+* gpcsGetForcedLink
+*
+* DESCRIPTION:
+*		This routine retrieves Forced Link bit
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if ForcedLink bit is one,
+*			     GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetForcedLink
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsSetDpxValue
+*
+* DESCRIPTION:
+*		This routine sets Duplex's Forced value. This function needs to be
+*		called prior to gpcsSetForcedDpx.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force full duplex, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetDpxValue
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+);
+
+/*******************************************************************************
+* gpcsGetDpxValue
+*
+* DESCRIPTION:
+*		This routine retrieves Duplex's Forced value
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Duplex's Forced value is set to Full duplex,
+*			     GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetDpxValue
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsSetForcedDpx
+*
+* DESCRIPTION:
+*		This routine forces duplex mode. If DpxValue is set to one, calling this 
+*		routine with GT_TRUE will force duplex mode to be full duplex.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force duplex mode, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetForcedDpx
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+);
+
+/*******************************************************************************
+* gpcsGetForcedDpx
+*
+* DESCRIPTION:
+*		This routine retrieves Forced Duplex.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if ForcedDpx bit is one,
+*			     GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetForcedDpx
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsSetForceSpeed
+*
+* DESCRIPTION:
+*		This routine forces speed. 
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_PORT_FORCED_SPEED_MODE (10, 100, 1000, or No Speed Force)
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetForceSpeed
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_PORT_FORCED_SPEED_MODE  mode
+);
+
+/*******************************************************************************
+* gpcsGetForceSpeed
+*
+* DESCRIPTION:
+*		This routine retrieves Force Speed value
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_PORT_FORCED_SPEED_MODE (10, 100, 1000, or no force speed)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetForceSpeed
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_PORT_FORCED_SPEED_MODE   *mode
+);
+
+
+
+/* gtQosMap.c */
+
+/*******************************************************************************
+* gqosGetTagRemap
+*
+* DESCRIPTION:
+*		Gets the remapped priority value for a specific 802.1p priority on a
+*		given port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*		pri   - 802.1p priority
+*
+* OUTPUTS:
+*		remappedPri - remapped Priority
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetTagRemap
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_U8    	pri,
+	OUT GT_U8   	*remappedPri
+);
+
+/*******************************************************************************
+* gqosSetTagRemap
+*
+* DESCRIPTION:
+*		Sets the remapped priority value for a specific 802.1p priority on a
+*		given port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*		pri   - 802.1p priority
+*		remappedPri - remapped Priority
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetTagRemap
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_U8    	pri,
+	IN GT_U8    	remappedPri
+);
+
+
+/* gtSysConfig.c */
+
+/* gtSysStatus.c */
+
+/*******************************************************************************
+* gsysGetPPUState
+*
+* DESCRIPTION:
+*		This routine get the PPU State. These two bits return 
+*		the current value of the PPU.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - GT_PPU_STATE
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_BAD_PARAM    - on bad parameter
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPPUState
+(
+	IN  GT_QD_DEV   	*dev,
+	OUT GT_PPU_STATE	*mode
+);
+
+
+/* Prototypes added for 88E6093 */
+
+
+/* gtBrgFdb.c */
+
+/*******************************************************************************
+* gfdbGetLearn2All
+*
+* DESCRIPTION:
+*		When more than one Marvell device is used to form a single 'switch', it
+*		may be desirable for all devices in the 'switch' to learn any address this 
+*		device learns. When this bit is set to a one all other devices in the 
+*		'switch' learn the same addresses this device learns. When this bit is 
+*		cleared to a zero, only the devices that actually receive frames will learn
+*		from those frames. This mode typically supports more active MAC addresses 
+*		at one time as each device in the switch does not need to learn addresses 
+*		it may nerver use.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if Learn2All is enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetLearn2All
+(
+	IN  GT_QD_DEV    *dev,
+	OUT GT_BOOL 	*mode
+);
+
+/*******************************************************************************
+* gfdbSetLearn2All
+*
+* DESCRIPTION:
+*		Enable or disable Learn2All mode.
+*
+* INPUTS:
+*		mode - GT_TRUE to set Learn2All, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbSetLearn2All
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gfdbRemovePort
+*
+* DESCRIPTION:
+*       This routine deassociages all or unblocked addresses from a port.
+*
+* INPUTS:
+*       moveCmd - the move operation type.
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbRemovePort
+(
+	IN GT_QD_DEV    *dev,
+    IN GT_MOVE_CMD 	moveCmd,
+    IN GT_LPORT		port
+);
+
+/*******************************************************************************
+* gfdbRemovePortInDB
+*
+* DESCRIPTION:
+*       This routine deassociages all or unblocked addresses from a port in the
+*       particular ATU Database (DBNum).
+*
+* INPUTS:
+*       moveCmd  - the move operation type.
+*       port - the logical port number.
+*		DBNum	 - ATU MAC Address Database Number.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORTED- if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbRemovePortInDB
+(
+	IN GT_QD_DEV    *dev,
+    IN GT_MOVE_CMD 	moveCmd,
+    IN GT_LPORT		port,
+	IN GT_U32 		DBNum
+);
+
+
+
+/* gtBrgStp.c */
+
+/* gtBrgVlan.c */
+
+/* gtBrgVtu.c */
+
+/* gtEvents.c */
+
+/* gtPCSCtrl.c */
+
+/*******************************************************************************
+* gpcsGetPCSLink
+*
+* DESCRIPTION:
+*		This routine retrieves Link up status in PCS
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE for Comma Detected or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetPCSLink
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsSetFCValue
+*
+* DESCRIPTION:
+*		This routine sets Flow Control's force value
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force flow control enabled, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetFCValue
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+);
+
+/*******************************************************************************
+* gpcsGetFCValue
+*
+* DESCRIPTION:
+*		This routine retrieves Flow Control Value which will be used for Forcing 
+*		Flow Control enabled or disabled.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if FC Force value is one (flow control enabled)
+*			     GT_FALSE otherwise (flow control disabled)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetFCValue
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gpcsSetForcedFC
+*
+* DESCRIPTION:
+*		This routine forces Flow Control. If FCValue is set to one, calling this 
+*		routine with GT_TRUE will force Flow Control to be enabled.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force flow control (enable or disable), GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetForcedFC
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+);
+
+/*******************************************************************************
+* gpcsGetForcedFC
+*
+* DESCRIPTION:
+*		This routine retrieves Forced Flow Control bit
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if ForcedFC bit is one,
+*			     GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetForcedFC
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+
+
+/* gtPhyCtrl.c */
+
+/*******************************************************************************
+* gprtGetPagedPhyReg
+*
+* DESCRIPTION:
+*       This routine reads phy register of the given page
+*
+* INPUTS:
+*		port 	- port to be read
+*		regAddr	- register offset to be read
+*		page	- page number to be read
+*
+* OUTPUTS:
+*		data	- value of the read register
+*
+* RETURNS:
+*       GT_OK   			- if read successed
+*       GT_FAIL   			- if read failed
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gprtGetPagedPhyReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U32  port,
+	IN	GT_U32  regAddr,
+	IN	GT_U32  page,
+    OUT GT_U16* data
+);
+
+/*******************************************************************************
+* gprtSetPagedPhyReg
+*
+* DESCRIPTION:
+*       This routine writes a value to phy register of the given page
+*
+* INPUTS:
+*		port 	- port to be read
+*		regAddr	- register offset to be read
+*		page	- page number to be read
+*		data	- value of the read register
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*       GT_OK   			- if read successed
+*       GT_FAIL   			- if read failed
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gprtSetPagedPhyReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U32 port,
+	IN	GT_U32 regAddr,
+	IN	GT_U32 page,
+    IN  GT_U16 data
+);
+
+
+/* gtPortCtrl.c */
+
+/*******************************************************************************
+* gprtSetUseCoreTag
+*
+* DESCRIPTION:
+*       This routine set the UseCoreTag bit in Port Control Register.
+*			When this bit is cleared to a zero, ingressing frames are considered
+*			Tagged if the 16-bits following the frame's Source Address is 0x8100.
+*			When this bit is set to a one, ingressing frames are considered Tagged
+*			if the 16-bits following the frame's Source Address is equal to the 
+*			CoreTag register value.
+*
+* INPUTS:
+*       port  - the logical port number.
+*       force - GT_TRUE for force flow control  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetUseCoreTag
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    force
+);
+
+/*******************************************************************************
+* gprtGetUseCoreTag
+*
+* DESCRIPTION:
+*       This routine get the Use Core Tag state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       force - GT_TRUE for using core tag register  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetUseCoreTag
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_BOOL    *force
+);
+
+/*******************************************************************************
+* gprtSetDiscardTagged
+*
+* DESCRIPTION:
+*		When this bit is set to a one, all non-MGMT frames that are processed as 
+*		Tagged will be discarded as they enter this switch port. Priority only 
+*		tagged frames (with a VID of 0x000) are considered tagged.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to discard tagged frame, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDiscardTagged
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetDiscardTagged
+*
+* DESCRIPTION:
+*		This routine gets DiscardTagged bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if DiscardTagged bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDiscardTagged
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+);
+
+/*******************************************************************************
+* gprtSetDiscardUntagged
+*
+* DESCRIPTION:
+*		When this bit is set to a one, all non-MGMT frames that are processed as 
+*		Untagged will be discarded as they enter this switch port. Priority only 
+*		tagged frames (with a VID of 0x000) are considered tagged.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to discard untagged frame, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDiscardUntagged
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetDiscardUntagged
+*
+* DESCRIPTION:
+*		This routine gets DiscardUntagged bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if DiscardUntagged bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDiscardUntagged
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+);
+
+/*******************************************************************************
+* gprtSetMapDA
+*
+* DESCRIPTION:
+*		When this bit is set to a one, normal switch operation will occur where a 
+*		frame's DA address is used to direct the frame out the correct port.
+*		When this be is cleared to a zero, the frame will be sent out the port(s) 
+*		defined by ForwardUnknown bits or the DefaultForward bits even if the DA 
+*		is ound in the address database.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to use MapDA, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetMapDA
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetMapDA
+*
+* DESCRIPTION:
+*		This routine gets MapDA bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if MapDA bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMapDA
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+);
+
+/*******************************************************************************
+* gprtSetDefaultForward
+*
+* DESCRIPTION:
+*		When this bit is set to a one, normal switch operation will occurs and 
+*		multicast frames with unknown DA addresses are allowed to egress out this 
+*		port (assuming the VLAN settings allow the frame to egress this port too).
+*		When this be is cleared to a zero, multicast frames with unknown DA 
+*		addresses will not egress out this port.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to use DefaultForward, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDefaultForward
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetDefaultForward
+*
+* DESCRIPTION:
+*		This routine gets DefaultForward bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if DefaultForward bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDefaultForward
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+);
+
+/*******************************************************************************
+* gprtSetEgressMonitorSource
+*
+* DESCRIPTION:
+*		When this be is cleared to a zero, normal network switching occurs.
+*		When this bit is set to a one, any frame that egresses out this port will
+*		also be sent to the EgressMonitorDest Port
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to set EgressMonitorSource, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetEgressMonitorSource
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetEgressMonitorSource
+*
+* DESCRIPTION:
+*		This routine gets EgressMonitorSource bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if EgressMonitorSource bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetEgressMonitorSource
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+);
+
+/*******************************************************************************
+* gprtSetIngressMonitorSource
+*
+* DESCRIPTION:
+*		When this be is cleared to a zero, normal network switching occurs.
+*		When this bit is set to a one, any frame that egresses out this port will
+*		also be sent to the EgressMonitorDest Port
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to set EgressMonitorSource, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIngressMonitorSource
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetIngressMonitorSource
+*
+* DESCRIPTION:
+*		This routine gets IngressMonitorSource bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if IngressMonitorSource bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIngressMonitorSource
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+);
+
+
+/* gtPortPAV.c */
+
+/* gtPortRateCtrl.c */
+
+/* gtPortRmon.c */
+
+/*******************************************************************************
+* gstatsGetPortCounter3
+*
+* DESCRIPTION:
+*		This routine gets a specific counter of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*		counter - the counter which will be read
+*
+* OUTPUTS:
+*		statsData - points to 32bit data storage for the MIB counter
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*		This function supports Gigabit Switch only
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortCounter3
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	IN  GT_STATS_COUNTERS3	counter,
+	OUT GT_U32			*statsData
+);
+
+/*******************************************************************************
+* gstatsGetPortAllCounters3
+*
+* DESCRIPTION:
+*		This routine gets all counters of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		statsCounterSet - points to GT_STATS_COUNTER_SET for the MIB counters
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*		This function supports Gigabit Switch only
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortAllCounters3
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	OUT GT_STATS_COUNTER_SET3	*statsCounterSet
+);
+
+
+/* gtPortStat.c */
+
+/*******************************************************************************
+* gprtGetPortCtr2
+*
+* DESCRIPTION:
+*       This routine gets the port InDiscards, InFiltered, and OutFiltered counters.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       ctr - the counters value.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortCtr2
+(
+    IN  GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_PORT_STAT2   *ctr
+);
+
+/* gtPortStatus.c */
+
+/*******************************************************************************
+* gprtGetMGMII
+*
+* DESCRIPTION:
+*		SERDES Interface mode. When this bit is cleared to a zero and a PHY is 
+*		detected connected to this port, the SERDES interface between this port
+*		and the PHY will be SGMII.  When this bit is set toa one and a PHY is
+*		detected connected to this port, the SERDES interface between this port 
+*		and the PHY will be MGMII. When no PHY is detected on this port and the 
+*		SERDES interface is being used, it will be configured in 1000Base-X mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE or GT_FALSE
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMGMII
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gprtSetMGMII
+*
+* DESCRIPTION:
+*		SERDES Interface mode. When this bit is cleared to a zero and a PHY is 
+*		detected connected to this port, the SERDES interface between this port
+*		and the PHY will be SGMII.  When this bit is set toa one and a PHY is
+*		detected connected to this port, the SERDES interface between this port 
+*		and the PHY will be MGMII. When no PHY is detected on this port and the 
+*		SERDES interface is being used, it will be configured in 1000Base-X mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE or GT_FALSE
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetMGMII
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_BOOL  	state
+);
+
+
+/* gtQosMap.c */
+
+/* gtSysCtrl.c */
+
+/*******************************************************************************
+* gsysSetCoreTagType
+*
+* DESCRIPTION:
+*		This routine sets Ether Core Tag Type.
+*		This Ether Type is added to frames that egress the switch as Double Tagged 
+*		frames. It is also the Ether Type expected during Ingress to determine if 
+*		a frame is Tagged or not on ports configured as UseCoreTag mode.
+*
+* INPUTS:
+*		etherType - Core Tag Type (2 bytes)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetCoreTagType
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16  		etherType
+);
+
+/*******************************************************************************
+* gsysGetCoreTagType
+*
+* DESCRIPTION:
+*		This routine gets CoreTagType
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		etherType - Core Tag Type (2 bytes)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetCoreTagType
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*etherType
+);
+
+/*******************************************************************************
+* gsysSetIngressMonitorDest
+*
+* DESCRIPTION:
+*		This routine sets Ingress Monitor Destination Port. Frames that are 
+*		targeted toward an Ingress Monitor Destination go out the port number 
+*		indicated in these bits. This includes frames received on a Marvell Tag port
+*		with the Ingress Monitor type, and frames received on a Network port that 
+*		is enabled to be the Ingress Monitor Source Port.
+*		If the Ingress Monitor Destination Port resides in this device these bits 
+*		should point to the Network port where these frames are to egress. If the 
+*		Ingress Monitor Destination Port resides in another device these bits 
+*		should point to the Marvell Tag port in this device that is used to get 
+*		to the device that contains the Ingress Monitor Destination Port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetIngressMonitorDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+);
+
+/*******************************************************************************
+* gsysGetIngressMonitorDest
+*
+* DESCRIPTION:
+*		This routine gets Ingress Monitor Destination Port.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetIngressMonitorDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+);
+
+/*******************************************************************************
+* gsysSetEgressMonitorDest
+*
+* DESCRIPTION:
+*		This routine sets Egress Monitor Destination Port. Frames that are 
+*		targeted toward an Egress Monitor Destination go out the port number 
+*		indicated in these bits. This includes frames received on a Marvell Tag port
+*		with the Egress Monitor type, and frames transmitted on a Network port that 
+*		is enabled to be the Egress Monitor Source Port.
+*		If the Egress Monitor Destination Port resides in this device these bits 
+*		should point to the Network port where these frames are to egress. If the 
+*		Egress Monitor Destination Port resides in another device these bits 
+*		should point to the Marvell Tag port in this device that is used to get 
+*		to the device that contains the Egress Monitor Destination Port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetEgressMonitorDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+);
+
+/*******************************************************************************
+* gsysGetEgressMonitorDest
+*
+* DESCRIPTION:
+*		This routine gets Egress Monitor Destination Port.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetEgressMonitorDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+);
+
+
+/* gtSysConfig.c */
+
+/* gtSysStatus.c */
+
+
+/* functions added on rev 2.2 */
+
+/* gtPortCtrl.c */
+
+/*******************************************************************************
+* gprtSetMessagePort
+*
+* DESCRIPTION:
+*		When the Learn2All bit is set to one, learning message frames are 
+*		generated. These frames will be sent out all ports whose Message Port is 
+*		set to one.
+* 		If this feature is used, it is recommended that all Marvell Tag ports, 
+*		except for the CPU's port, have their MessagePort bit set to one. 
+*		Ports that are not Marvell Tag ports should not have their Message Port
+*		bit set to one.
+*		
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to make this port a Message Port. GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetMessagePort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetMessagePort
+*
+* DESCRIPTION:
+*		When the Learn2All bit is set to one, learning message frames are 
+*		generated. These frames will be sent out all ports whose Message Port is 
+*		set to one.
+* 		If this feature is used, it is recommended that all Marvell Tag ports, 
+*		except for the CPU's port, have their MessagePort bit set to one. 
+*		Ports that are not Marvell Tag ports should not have their Message Port
+*		bit set to one.
+*
+*		
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to make this port a Message Port. GT_FALSE, otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMessagePort
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+);
+
+
+/*******************************************************************************
+* gprtSetTrunkPort
+*
+* DESCRIPTION:
+*		This function enables/disables and sets the trunk ID.
+*		
+* INPUTS:
+*		port - the logical port number.
+*		en - GT_TRUE to make the port be a member of a trunk with the given trunkId.
+*			 GT_FALSE, otherwise.
+*		trunkId - valid ID is 0 ~ 15.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkId is neither valid nor INVALID_TRUNK_ID
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetTrunkPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL 		en,
+	IN GT_U32		trunkId
+);
+
+
+/*******************************************************************************
+* gprtGetTrunkPort
+*
+* DESCRIPTION:
+*		This function returns trunk state of the port.
+*		When trunk is disabled, trunkId field won't have valid value.
+*		
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		en - GT_TRUE, if the port is a member of a trunk,
+*			 GT_FALSE, otherwise.
+*		trunkId - 0 ~ 15, valid only if en is GT_TRUE
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetTrunkPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	OUT GT_BOOL 	*en,
+	OUT GT_U32		*trunkId
+);
+
+
+
+
+/*******************************************************************************
+* gprtGetGlobal2Reg
+*
+* DESCRIPTION:
+*       This routine reads Switch Global 2 Registers.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetGlobal2Reg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U32	     regAddr,
+    OUT GT_U16	     *data
+);
+
+/*******************************************************************************
+* gprtSetGlobal2Reg
+*
+* DESCRIPTION:
+*       This routine writes Switch Global2 Registers.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetGlobal2Reg
+(
+    IN  GT_QD_DEV		*dev,
+    IN  GT_U32			regAddr,
+    IN  GT_U16			data
+);
+
+/* gtSysCtrl.c */
+/*******************************************************************************
+* gsysSetARPDest
+*
+* DESCRIPTION:
+*		This routine sets ARP Monitor Destination Port. Tagged or untagged 
+*		frames that ingress Network ports with the Broadcast Destination Address 
+*		and with an Ethertype of 0x0806 are mirrored to this port. The ARPDest 
+*		should point to the port that directs these frames to the switch's CPU 
+*		that will process ARPs. This target port should be a Marvell Tag port so 
+*		that frames will egress with a To_CPU Marvell Tag with a CPU Code of ARP.
+*		To_CPU Marvell Tag frames with a CPU Code off ARP that ingress a Marvell 
+*		Tag port will be sent to the port number definded in ARPDest.
+*
+*		If ARPDest =  0xF, ARP Monitoring is disabled and ingressing To_CPU ARP 
+*		frames will be discarded.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetARPDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+);
+
+/*******************************************************************************
+* gsysGetARPDest
+*
+* DESCRIPTION:
+*		This routine gets ARP Monitor Destination Port. Tagged or untagged 
+*		frames that ingress Network ports with the Broadcast Destination Address 
+*		and with an Ethertype of 0x0806 are mirrored to this port. The ARPDest 
+*		should point to the port that directs these frames to the switch's CPU 
+*		that will process ARPs. This target port should be a Marvell Tag port so 
+*		that frames will egress with a To_CPU Marvell Tag with a CPU Code of ARP.
+*		To_CPU Marvell Tag frames with a CPU Code off ARP that ingress a Marvell 
+*		Tag port will be sent to the port number definded in ARPDest.
+*
+*		If ARPDest =  0xF, ARP Monitoring is disabled and ingressing To_CPU ARP 
+*		frames will be discarded.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetARPDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+);
+
+/*******************************************************************************
+* gsysSetRsvd2CpuEnables
+*
+* DESCRIPTION:
+*		Reserved DA Enables. When the function, gsysSetRsvd2Cpu, is called with 
+*		en = GT_TRUE, the 16 reserved multicast DA addresses, whose bit in this 
+*		enBits(or register) are also set to a one, are treated as MGMT frames. 
+*		All the reserved DA's take the form 01:80:C2:00:00:0x. When x = 0x0, 
+*		bit 0 of this register is tested. When x = 0x2, bit 2 of this field is 
+*		tested and so on.
+*		If the tested bit in this register is cleared to a zero, the frame will 
+*		be treated as a normal (non-MGMT) frame.
+*
+* INPUTS:
+*		enBits - bit vector of enabled Reserved Multicast.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetRsvd2CpuEnables
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		enBits
+);
+
+/*******************************************************************************
+* gsysGetRsvd2CpuEnables
+*
+* DESCRIPTION:
+*		Reserved DA Enables. When the function, gsysSetRsvd2Cpu, is called with 
+*		en = GT_TRUE, the 16 reserved multicast DA addresses, whose bit in this 
+*		enBits(or register) are also set to a one, are treated as MGMT frames. 
+*		All the reserved DA's take the form 01:80:C2:00:00:0x. When x = 0x0, 
+*		bit 0 of this register is tested. When x = 0x2, bit 2 of this field is 
+*		tested and so on.
+*		If the tested bit in this register is cleared to a zero, the frame will 
+*		be treated as a normal (non-MGMT) frame.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		enBits - bit vector of enabled Reserved Multicast.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetRsvd2CpuEnables
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*enBits
+);
+
+/*******************************************************************************
+* gsysSetRsvd2Cpu
+*
+* DESCRIPTION:
+*		When the Rsvd2Cpu is set to a one(GT_TRUE), frames with a Destination 
+*		Address in the range 01:80:C2:00:00:0x, regardless of their VLAN 
+*		membership, will be considered MGMT frames and sent to the port's CPU 
+*		Port as long as the associated Rsvd2CpuEnable bit (gsysSetRsvd2CpuEnable 
+*		function) for the frames's DA is also set to a one.
+*
+* INPUTS:
+*		en - GT_TRUE if Rsvd2Cpu is set. GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetRsvd2Cpu
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetRsvd2Cpu
+*
+* DESCRIPTION:
+*		When the Rsvd2Cpu is set to a one(GT_TRUE), frames with a Destination 
+*		Address in the range 01:80:C2:00:00:0x, regardless of their VLAN 
+*		membership, will be considered MGMT frames and sent to the port's CPU 
+*		Port as long as the associated Rsvd2CpuEnable bit (gsysSetRsvd2CpuEnable 
+*		function) for the frames's DA is also set to a one.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Rsvd2Cpu is set. GT_FALSE, otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetRsvd2Cpu
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetMGMTPri
+*
+* DESCRIPTION:
+*		These bits are used as the PRI[2:0] bits on Rsvd2CPU MGMT frames.
+*
+* INPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - If pri is not less than 8.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetMGMTPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		pri
+);
+
+/*******************************************************************************
+* gsysGetMGMTPri
+*
+* DESCRIPTION:
+*		These bits are used as the PRI[2:0] bits on Rsvd2CPU MGMT frames.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetMGMTPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*pri
+);
+
+/*******************************************************************************
+* gsysSetUseDoubleTagData
+*
+* DESCRIPTION:
+*		This bit is used to determine if Double Tag data that is removed from a 
+*		Double Tag frame is used or ignored when making switching decisions on 
+*		the frame.
+*
+* INPUTS:
+*		en - GT_TRUE to use removed tag data, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetUseDoubleTagData
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetUseDoubleTagData
+*
+* DESCRIPTION:
+*		This bit is used to determine if Double Tag data that is removed from a 
+*		Double Tag frame is used or ignored when making switching decisions on 
+*		the frame.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if removed tag data is used, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetUseDoubleTagData
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetPreventLoops
+*
+* DESCRIPTION:
+*		When a Marvell Tag port receives a Forward Marvell Tag whose Src_Dev 
+*		field equals this device's Device Number, the following action will be 
+*		taken depending upon the value of this bit.
+*		GT_TRUE (1) - The frame will be discarded.
+*		GT_FALSE(0) - The frame will be prevented from going out its original 
+*						source port as defined by the frame's Src_Port field.
+*
+* INPUTS:
+*		en - GT_TRUE to discard the frame as described above, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetPreventLoops
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetPreventLoops
+*
+* DESCRIPTION:
+*		When a Marvell Tag port receives a Forward Marvell Tag whose Src_Dev 
+*		field equals this device's Device Number, the following action will be 
+*		taken depending upon the value of this bit.
+*		GT_TRUE (1) - The frame will be discarded.
+*		GT_FALSE(0) - The frame will be prevented from going out its original 
+*						source port as defined by the frame's Src_Port field.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to discard the frame as described above, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPreventLoops
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetFlowControlMessage
+*
+* DESCRIPTION:
+*		When this bit is set to one, Marvell Tag Flow Control messages will be 
+*		generated when an output queue becomes congested and received Marvell Tag 
+*		Flow Control messages will pause MACs inside this device. When this bit 
+*		is cleared to a zero, Marvell Tag Flow Control messages will not be 
+*		generated and any received will be ignored at the target MAC.
+*
+* INPUTS:
+*		en - GT_TRUE to use Marvell Tag Flow Control message, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetFlowControlMessage
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetFlowControlMessage
+*
+* DESCRIPTION:
+*		When this bit is set to one, Marvell Tag Flow Control messages will be 
+*		generated when an output queue becomes congested and received Marvell Tag 
+*		Flow Control messages will pause MACs inside this device. When this bit 
+*		is cleared to a zero, Marvell Tag Flow Control messages will not be 
+*		generated and any received will be ignored at the target MAC.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use Marvell Tag Flow Control message, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetFlowControlMessage
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetForceFlowControlPri
+*
+* DESCRIPTION:
+*		When this bit is set to a one the PRI[2:0] bits of generated Marvell Tag 
+*		Flow Control frames will be set to the value of the FC Pri bits (set by 
+*		gsysSetFCPri function call). When this bit is cleared to a zero, generated 
+*		Marvell Tag Flow Control frames will retain the PRI[2:0] bits from the 
+*		frames that caused the congestion. This bit will have no effect if the 
+*		FlowControlMessage bit(gsysSetFlowControlMessage function call) is 
+*		cleared to a zero.
+*
+* INPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetForceFlowControlPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetForceFlowControlPri
+*
+* DESCRIPTION:
+*		When this bit is set to a one the PRI[2:0] bits of generated Marvell Tag 
+*		Flow Control frames will be set to the value of the FC Pri bits (set by 
+*		gsysSetFCPri function call). When this bit is cleared to a zero, generated 
+*		Marvell Tag Flow Control frames will retain the PRI[2:0] bits from the 
+*		frames that caused the congestion. This bit will have no effect if the 
+*		FlowControlMessage bit(gsysSetFlowControlMessage function call) is 
+*		cleared to a zero.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetForceFlowControlPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetFCPri
+*
+* DESCRIPTION:
+*		These bits are used as the PRI[2:0] bits on generated Marvell Tag Flow 
+*		Control frames if the ForceFlowControlPri bit(gsysSetForceFlowControlPri)
+*		is set to a one.
+*
+* INPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - If pri is not less than 8.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetFCPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		pri
+);
+
+/*******************************************************************************
+* gsysGetFCPri
+*
+* DESCRIPTION:
+*		These bits are used as the PRI[2:0] bits on generated Marvell Tag Flow 
+*		Control frames if the ForceFlowControlPri bit(gsysSetForceFlowControlPri)
+*		is set to a one.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetFCPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*pri
+);
+
+/*******************************************************************************
+* gsysSetFlowCtrlDelay
+*
+* DESCRIPTION:
+*		This function sets Flow control delay time for 10Mbps, 100Mbps, and 
+*		1000Mbps. 
+*
+* INPUTS:
+*		sp - PORT_SPEED_10_MBPS, PORT_SPEED_100_MBPS, or PORT_SPEED_1000_MBPS
+*		delayTime - actual delay time will be (this value x 2.048uS).
+*					the value cannot exceed 0x1FFF (or 8191 in decimal).
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if sp is not valid or delayTime is > 0x1FFF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetFlowCtrlDelay
+(
+	IN GT_QD_DEV			*dev,
+	IN GT_PORT_SPEED_MODE	sp,
+	IN GT_U32				delayTime
+);
+
+/*******************************************************************************
+* gsysGetFlowCtrlDelay
+*
+* DESCRIPTION:
+*		This function retrieves Flow control delay time for 10Mbps, 100Mbps, and
+*		1000Mbps. 
+*
+* INPUTS:
+*		sp - PORT_SPEED_10_MBPS, PORT_SPEED_100_MBPS, or PORT_SPEED_1000_MBPS
+*
+* OUTPUTS:
+*		delayTime - actual delay time will be (this value x 2.048uS).
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if sp is not valid or delayTime is > 0x1FFF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetFlowCtrlDelay
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_PORT_SPEED_MODE	sp,
+	OUT GT_U32		*delayTime
+);
+
+/*******************************************************************************
+* gsysSetDevRoutingTable
+*
+* DESCRIPTION:
+*		This function sets Device to Port mapping (which device is connected to 
+*		which port of this device). 
+*
+* INPUTS:
+*		devNum - target device number.
+*		portNum - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if devNum >= 32 or port >= total number of ports.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetDevRoutingTable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		devNum,
+	IN GT_LPORT 	port
+);
+
+/*******************************************************************************
+* gsysGetDevRoutingTable
+*
+* DESCRIPTION:
+*		This function gets Device to Port mapping (which device is connected to 
+*		which port of this device). 
+*
+* INPUTS:
+*		devNum - target device number.
+*
+* OUTPUTS:
+*		portNum - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if devNum >= 32
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetDevRoutingTable
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32 		devNum,
+	OUT GT_LPORT 	*port
+);
+
+/*******************************************************************************
+* gsysSetTrunkMaskTable
+*
+* DESCRIPTION:
+*		This function sets Trunk mask vector table for load balancing.
+*		This vector will be AND'ed with where the frame was originally egressed to.
+*		To insure all trunks are load balanced correctly, the data in this table
+*		needs to be correctly configured.
+*
+* INPUTS:
+*		trunkNum - one of the eight Trunk mask vectors.
+*		trunkMask - Trunk Mask bits. Bit 0 controls trunk masking for port 0,
+*					bit 1 for port 1 , etc.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkNum > 0x7 or trunMask > 0x7FF (or port vector).
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetTrunkMaskTable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		trunkNum,
+	IN GT_U32		trunkMask
+);
+
+/*******************************************************************************
+* gsysGetTrunkMaskTable
+*
+* DESCRIPTION:
+*		This function sets Trunk mask vector table for load balancing.
+*		This vector will be AND'ed with where the frame was originally egressed to.
+*		To insure all trunks are load balanced correctly, the data in this table
+*		needs to be correctly configured.
+*
+* INPUTS:
+*		trunkNum - one of the eight Trunk mask vectors.
+*
+* OUTPUTS:
+*		trunkMask - Trunk Mask bits. Bit 0 controls trunk masking for port 0,
+*					bit 1 for port 1 , etc.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkNum > 0x7.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetTrunkMaskTable
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32 		trunkNum,
+	OUT GT_U32		*trunkMask
+);
+
+/*******************************************************************************
+* gsysSetHashTrunk
+*
+* DESCRIPTION:
+*		Hash DA & SA for TrunkMask selection. Trunk load balancing is accomplished 
+*		by using the frame's DA and SA fields to access one of eight Trunk Masks. 
+*		When this bit is set to a one, the hashed computed for address table 
+*		lookups is used for the TrunkMask selection. When this bit is cleared to 
+*		a zero the lower 3 bits of the frame's DA and SA are XOR'ed together to 
+*		select the TrunkMask to use.
+*
+* INPUTS:
+*		en - GT_TRUE to use lookup table, GT_FALSE to use XOR.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetHashTrunk
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetHashTrunk
+*
+* DESCRIPTION:
+*		Hash DA & SA for TrunkMask selection. Trunk load balancing is accomplished 
+*		by using the frame's DA and SA fields to access one of eight Trunk Masks. 
+*		When this bit is set to a one, the hashed computed for address table 
+*		lookups is used for the TrunkMask selection. When this bit is cleared to 
+*		a zero the lower 3 bits of the frame's DA and SA are XOR'ed together to 
+*		select the TrunkMask to use.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use lookup table, GT_FALSE to use XOR.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetHashTrunk
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetTrunkRouting
+*
+* DESCRIPTION:
+*		This function sets routing information for the given Trunk ID.
+*
+* INPUTS:
+*		trunkId - Trunk ID.
+*		trunkRoute - Trunk route bits. Bit 0 controls trunk routing for port 0,
+*					bit 1 for port 1 , etc.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkId > 0xF or trunkRoute > 0x7FF(or port vector).
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetTrunkRouting
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		trunkId,
+	IN GT_U32		trunkRoute
+);
+
+/*******************************************************************************
+* gsysGetTrunkRouting
+*
+* DESCRIPTION:
+*		This function retrieves routing information for the given Trunk ID.
+*
+* INPUTS:
+*		trunkId - Trunk ID.
+*
+* OUTPUTS:
+*		trunkRoute - Trunk route bits. Bit 0 controls trunk routing for port 0,
+*					bit 1 for port 1 , etc.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkId > 0xF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetTrunkRouting
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32 		trunkId,
+	OUT GT_U32		*trunkRoute
+);
+
+
+
+/* Prototype added for 88E6095 Rev 1 or Rev 2 */
+
+/* gtPortCtrl.c */
+/*******************************************************************************
+* gprtGetDiscardBCastMode
+*
+* DESCRIPTION:
+*       This routine gets the Discard Broadcast Mode. If the mode is enabled,
+*		all the broadcast frames to the given port will be discarded.
+*
+* INPUTS:
+*       port - logical port number
+*
+* OUTPUTS:
+*		en - GT_TRUE, if enabled,
+*			 GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDiscardBCastMode
+(
+	IN  GT_QD_DEV    *dev,
+	IN  GT_LPORT     port,
+	OUT GT_BOOL 	 *en
+);
+
+/*******************************************************************************
+* gprtSetDiscardBCastMode
+*
+* DESCRIPTION:
+*       This routine sets the Discard Broadcast mode.
+*		If the mode is enabled, all the broadcast frames to the given port will 
+*		be discarded.
+*
+* INPUTS:
+*       port - logical port number
+*		en - GT_TRUE, to enable the mode,
+*			 GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDiscardBCastMode
+(
+	IN  GT_QD_DEV    *dev,
+	IN  GT_LPORT     port,
+	IN  GT_BOOL 	 en
+);
+
+/*******************************************************************************
+* gprtGetFCOnRateLimitMode
+*
+* DESCRIPTION:
+*       This routine returns mode that tells if ingress rate limiting uses Flow 
+*		Control. When this mode is enabled and the port receives frames over the 
+*		limit, Ingress Rate Limiting will be performed by stalling the 
+*		link partner using flow control, instead of discarding frames.
+*
+* INPUTS:
+*       port - logical port number
+*
+* OUTPUTS:
+*		en - GT_TRUE, if the mode is enabled,
+*			 GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetFCOnRateLimitMode
+(
+	IN  GT_QD_DEV    *dev,
+	IN  GT_LPORT     port,
+	OUT GT_BOOL 	 *en
+);
+
+/*******************************************************************************
+* gprtSetFCOnRateLimitMode
+*
+* DESCRIPTION:
+*       This routine sets the mode that tells if ingress rate limiting uses Flow 
+*		Control. When this mode is enabled and the port receives frames over the 
+*		limit, Ingress Rate Limiting will be performed by stalling the 
+*		link partner using flow control, instead of discarding frames.
+*
+* INPUTS:
+*       port - logical port number
+*		en - GT_TRUE, to enable the mode,
+*			 GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetFCOnRateLimitMode
+(
+	IN  GT_QD_DEV    *dev,
+	IN  GT_LPORT     port,
+	IN  GT_BOOL 	 en
+);
+
+
+/* gtPortRateCtrl.c */
+
+/*******************************************************************************
+* grcSetBurstRate
+*
+* DESCRIPTION:
+*       This routine sets the port's ingress data limit based on burst size.
+*
+* INPUTS:
+*       port	- logical port number.
+*       bsize	- burst size.
+*       rate    - ingress data rate limit. These frames will be discarded after 
+*				the ingress rate selected is reached or exceeded. 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters 
+*								Minimum rate for Burst Size 24K byte is 128Kbps
+*								Minimum rate for Burst Size 48K byte is 256Kbps
+*								Minimum rate for Burst Size 96K byte is 512Kbps
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*		If the device supports both priority based Rate Limiting and burst size
+*		based Rate limiting, user has to manually change the mode to burst size
+*		based Rate limiting by calling gsysSetRateLimitMode.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetBurstRate
+(
+    IN GT_QD_DEV       *dev,
+    IN GT_LPORT        port,
+    IN GT_BURST_SIZE   bsize,
+    IN GT_BURST_RATE   rate
+);
+
+/*******************************************************************************
+* grcGetBurstRate
+*
+* DESCRIPTION:
+*       This routine retrieves the port's ingress data limit based on burst size.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       bsize	- burst size.
+*       rate    - ingress data rate limit. These frames will be discarded after 
+*				the ingress rate selected is reached or exceeded. 
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetBurstRate
+(
+    IN  GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_BURST_SIZE   *bsize,
+    OUT GT_BURST_RATE   *rate
+);
+
+
+/*******************************************************************************
+* grcSetTCPBurstRate
+*
+* DESCRIPTION:
+*       This routine sets the port's TCP/IP ingress data limit based on burst size.
+*
+* INPUTS:
+*       port	- logical port number.
+*       rate    - ingress data rate limit for TCP/IP packets. These frames will 
+*				be discarded after the ingress rate selected is reached or exceeded. 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters 
+*								Valid rate is GT_BURST_NO_LIMIT, or between
+*								64Kbps and 1500Kbps.
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*		If the device supports both priority based Rate Limiting and burst size
+*		based Rate limiting, user has to manually change the mode to burst size
+*		based Rate limiting by calling gsysSetRateLimitMode.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetTCPBurstRate
+(
+    IN GT_QD_DEV       *dev,
+    IN GT_LPORT        port,
+    IN GT_BURST_RATE   rate
+);
+
+
+/*******************************************************************************
+* grcGetTCPBurstRate
+*
+* DESCRIPTION:
+*       This routine sets the port's TCP/IP ingress data limit based on burst size.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       rate    - ingress data rate limit for TCP/IP packets. These frames will 
+*				be discarded after the ingress rate selected is reached or exceeded. 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_VALUE        - register value is not known
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*		If the device supports both priority based Rate Limiting and burst size
+*		based Rate limiting, user has to manually change the mode to burst size
+*		based Rate limiting by calling gsysSetRateLimitMode.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetTCPBurstRate
+(
+    IN  GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_BURST_RATE   *rate
+);
+
+
+/* gtSysCtrl.c */
+/*******************************************************************************
+* gsysSetRateLimitMode
+*
+* DESCRIPTION:
+*		Ingress Rate Limiting can be either Priority based or Burst Size based.
+*		This routine sets which mode to use.
+*
+* INPUTS:
+*		mode - either GT_RATE_PRI_BASE or GT_RATE_BURST_BASE
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if invalid mode is used.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRateLimitMode
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_INGRESS_RATE_MODE mode
+);
+
+/*******************************************************************************
+* gsysGetRateLimitMode
+*
+* DESCRIPTION:
+*		Ingress Rate Limiting can be either Priority based or Burst Size based.
+*		This routine gets which mode is being used.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - either GT_RATE_PRI_BASE or GT_RATE_BURST_BASE
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRateLimitMode
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_INGRESS_RATE_MODE *mode
+);
+
+/*******************************************************************************
+* gsysSetAgeInt
+*
+* DESCRIPTION:
+*		Enable/Disable Age Refresh Interrupt. If CPU Directed Learning is being
+*		used (gprtSetLockedPort), it may be desirable to know when an address is
+*		still being used before it totally ages out of the switch. This can be 
+*		accomplished by enabling Age Refresh Interrupt (or ATU Age Violation Int).
+*		An ATU Age Violation looks identical to and reported the same as an ATU 
+*		Miss Violation. The only difference is when this reported. Normal ATU Miss
+*		Violation only occur if a new SA arrives at a LockedPort. The Age version 
+*		of the ATU Miss Violation occurs if an SA arrives at a LockedPort, where
+*		the address is contained in the ATU's database, but where its EntryState 
+*		is less than 0x4 (i.e., it has aged more than 1/2 way).
+*		GT_ATU_PROB Interrupt should be enabled for this interrupt to occur.
+*		Refer to eventSetActive routine to enable GT_ATU_PROB.
+*		
+*
+* INPUTS:
+*		en - GT_TRUE, to enable,
+*			 GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetAgeInt
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetAgeInt
+*
+* DESCRIPTION:
+*		Get state of Age Refresh Interrupt mode. If CPU Directed Learning is being
+*		used (gprtSetLockedPort), it may be desirable to know when an address is
+*		still being used before it totally ages out of the switch. This can be 
+*		accomplished by enabling Age Refresh Interrupt (or ATU Age Violation Int).
+*		An ATU Age Violation looks identical to and reported the same as an ATU 
+*		Miss Violation. The only difference is when this reported. Normal ATU Miss
+*		Violation only occur if a new SA arrives at a LockedPort. The Age version 
+*		of the ATU Miss Violation occurs if an SA arrives at a LockedPort, where
+*		the address is contained in the ATU's database, but where its EntryState 
+*		is less than 0x4 (i.e., it has aged more than 1/2 way).
+*		GT_ATU_PROB Interrupt should be enabled for this interrupt to occur.
+*		Refer to eventSetActive routine to enable GT_ATU_PROB.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE, if enabled,
+*			 GT_FALSE, otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetAgeInt
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL		*en
+);
+
+
+/* For Zephyr */
+
+/* gtPhyCtrl.c */
+/*******************************************************************************
+* gprtGetPhyLinkStatus
+*
+* DESCRIPTION:
+*       This routine retrieves the Link status.
+*
+* INPUTS:
+* 		port 	- The logical port number
+*
+* OUTPUTS:
+*       linkStatus - GT_FALSE if link is not established,
+*				     GT_TRUE if link is established.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPhyLinkStatus
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+    IN GT_BOOL 	 *linkStatus
+);
+
+
+/*******************************************************************************
+* gprtSetPktGenEnable
+*
+* DESCRIPTION:
+*       This routine enables or disables Packet Generator.
+*       Link should be established first prior to enabling the packet generator,
+*       and generator will generate packets at the speed of the established link.
+*		When enables packet generator, the following information should be 
+*       provided:
+*           Payload Type:  either Random or 5AA55AA5
+*           Packet Length: either 64 or 1514 bytes
+*           Error Packet:  either Error packet or normal packet
+*
+* INPUTS:
+* 		port 	- The logical port number
+*       en      - GT_TRUE to enable, GT_FALSE to disable
+*       pktInfo - packet information(GT_PG structure pointer), if en is GT_TRUE.
+*                 ignored, if en is GT_FALSE
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPktGenEnable
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+    IN GT_BOOL   en,
+    IN GT_PG     *pktInfo
+);
+
+/*******************************************************************************
+* gprtGetSerdesMode
+*
+* DESCRIPTION:
+*       This routine reads Serdes Interface Mode.
+*
+* INPUTS:
+*       port    - logical port number
+*
+* OUTPUTS:
+*       mode    - Serdes Interface Mode
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSerdesMode
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+	IN  GT_SERDES_MODE *mode
+);
+
+/*******************************************************************************
+* gprtSetSerdesMode
+*
+* DESCRIPTION:
+*       This routine sets Serdes Interface Mode.
+*
+* INPUTS:
+*       port    - logical port number
+*       mode    - Serdes Interface Mode
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetSerdesMode
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+	IN  GT_SERDES_MODE mode
+);
+
+
+/* gtSysCtrl.c */
+
+/*******************************************************************************
+* gsysSetForceSnoopPri
+*
+* DESCRIPTION:
+*		Force Snooping Priority. The priority on IGMP or MLD Snoop frames are
+*		set to the SnoopPri value (gsysSetSnoopPri API) when Force Snooping
+*       Priority is enabled. When it's disabled, the priority on these frames
+*		is not modified.
+*
+* INPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetForceSnoopPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetForceSnoopPri
+*
+* DESCRIPTION:
+*		Force Snooping Priority. The priority on IGMP or MLD Snoop frames are
+*		set to the SnoopPri value (gsysSetSnoopPri API) when Force Snooping
+*       Priority is enabled. When it's disabled, the priority on these frames
+*		is not modified.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetForceSnoopPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+
+/*******************************************************************************
+* gsysSetSnoopPri
+*
+* DESCRIPTION:
+*		Snoop Priority. When ForceSnoopPri (gsysSetForceSnoopPri API) is enabled,
+*       this priority is used as the egressing frame's PRI[2:0] bits on generated
+*       Marvell Tag To_CPU Snoop frames and higher 2 bits of the priority are
+*       used as the internal Queue Priority to use on IGMP/MLD snoop frames.
+*
+* INPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - If pri is not less than 8.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetSnoopPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		pri
+);
+
+
+/*******************************************************************************
+* gsysGetSnoopPri
+*
+* DESCRIPTION:
+*		Snoop Priority. When ForceSnoopPri (gsysSetForceSnoopPri API) is enabled,
+*       this priority is used as the egressing frame's PRI[2:0] bits on generated
+*       Marvell Tag To_CPU Snoop frames and higher 2 bits of the priority are
+*       used as the internal Queue Priority to use on IGMP/MLD snoop frames.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetSnoopPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*pri
+);
+
+
+/*******************************************************************************
+* gsysSetForceARPPri
+*
+* DESCRIPTION:
+*		Force ARP Priority. The priority on ARP frames are set to the ARPPri 
+*       value (gsysSetARPPri API) when Force ARP Priority is enabled. When it's 
+*       disabled, the priority on these frames is not modified.
+*
+* INPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetForceARPPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetForceARPPri
+*
+* DESCRIPTION:
+*		Force ARP Priority. The priority on ARP frames are set to the ARPPri 
+*       value (gsysSetARPPri API) when Force ARP Priority is enabled. When it's 
+*       disabled, the priority on these frames is not modified.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetForceARPPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+
+/*******************************************************************************
+* gsysSetARPPri
+*
+* DESCRIPTION:
+*		ARP Priority. When ForceARPPri (gsysSetForceARPPri API) is enabled,
+*       this priority is used as the egressing frame's PRI[2:0] bits on generated
+*       Marvell Tag To_CPU ARP frames and higher 2 bits of the priority are
+*       used as the internal Queue Priority to use on ARP frames.
+*
+* INPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - If pri is not less than 8.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetARPPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		pri
+);
+
+
+/*******************************************************************************
+* gsysGetARPPri
+*
+* DESCRIPTION:
+*		ARP Priority. When ForceARPPri (gsysSetForceARPPri API) is enabled,
+*       this priority is used as the egressing frame's PRI[2:0] bits on generated
+*       Marvell Tag To_CPU ARP frames and higher 2 bits of the priority are
+*       used as the internal Queue Priority to use on ARP frames.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetARPPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*pri
+);
+
+
+/* added for 88E6065 */
+
+/* gtBrgVlan.c */
+
+/********************************************************************
+* gvlnSetForceMap
+*
+* DESCRIPTION:
+*       This routine enables/disables Force Map feature.
+*		When Force Map feature is enabled, all received frames will be
+*		considered MGMT and they are mapped to the port or ports defined
+*		in the VLAN Table overriding the mapping from the address database.
+*
+* INPUTS:
+*       port    - logical port number to set.
+*       mode    - GT_TRUE, to enable force map feature
+*                 GT_FAULSE, otherwise 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gvlnSetForceMap
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT 	port,
+    IN  GT_BOOL  	mode
+);
+
+
+/********************************************************************
+* gvlnGetForceMap
+*
+* DESCRIPTION:
+*       This routine checks if Force Map feature is enabled.
+*		When Force Map feature is enabled, all received frames will be
+*		considered MGMT and they are mapped to the port or ports defined
+*		in the VLAN Table overriding the mapping from the address database.
+*
+* INPUTS:
+*       port    - logical port number to set.
+*
+* OUTPUTS:
+*       mode    - GT_TRUE, to enable force map feature
+*                 GT_FAULSE, otherwise 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gvlnGetForceMap
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT 	port,
+    OUT GT_BOOL  	*mode
+);
+
+/* gtEvents.c */
+
+/*******************************************************************************
+* geventSetAgeIntEn
+*
+* DESCRIPTION:
+*		This routine enables/disables Age Interrupt for a port.
+*		When it's enabled, ATU Age Violation interrupts from this port are enabled.
+*		An Age Violation will occur anytime a port is Locked(gprtSetLockedPort) 
+*		and the ingressing frame's SA is contained in the ATU as a non-Static 
+*		entry with a EntryState less than 0x4.
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_TRUE to enable Age Interrupt,
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventSetAgeIntEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* geventGetAgeIntEn
+*
+* DESCRIPTION:
+*		This routine gets Age Interrupt Enable for the port.
+*		When it's enabled, ATU Age Violation interrupts from this port are enabled.
+*		An Age Violation will occur anytime a port is Locked(gprtSetLockedPort) 
+*		and the ingressing frame's SA is contained in the ATU as a non-Static 
+*		entry with a EntryState less than 0x4.
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_TRUE to enable Age Interrupt,
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventGetAgeIntEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+
+/* gtPIRL.c */
+
+/*******************************************************************************
+* gpirlActivate
+*
+* DESCRIPTION:
+*       This routine activates Ingress Rate Limiting for the given ports by 
+*		initializing a resource bucket, assigning ports, and configuring
+*		Bucket Parameters.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*       portVec  - the list of ports that share the bucket.
+*		pirlData - PIRL resource parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlActivate
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	IN  GT_U32		portVec,
+	IN  GT_PIRL_DATA	*pirlData
+);
+
+/*******************************************************************************
+* gpirlDeactivate
+*
+* DESCRIPTION:
+*       This routine deactivates Ingress Rate Limiting for the given bucket.
+*		It simply removes every ports from the Ingress Rate Resource.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be deactivated
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlDeactivate
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit
+);
+
+/*******************************************************************************
+* gpirlUpdateParam
+*
+* DESCRIPTION:
+*       This routine updates IRL Parameter.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the given irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11)
+*		pirlData - PIRL resource parameters
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlUpdateParam
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	IN  GT_PIRL_DATA	*pirlData
+);
+
+/*******************************************************************************
+* gpirlReadParam
+*
+* DESCRIPTION:
+*       This routine retrieves IRL Parameter.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the given irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*
+* OUTPUTS:
+*		pirlData - PIRL resource parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlReadParam
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	OUT GT_PIRL_DATA	*pirlData
+);
+
+/*******************************************************************************
+* gpirlUpdatePortVec
+*
+* DESCRIPTION:
+*       This routine updates port list that share the bucket.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the given irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*       portVec  - the list of ports that share the bucket.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlUpdatePortVec
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	IN  GT_U32		portVec
+);
+
+/*******************************************************************************
+* gpirlReadPortVec
+*
+* DESCRIPTION:
+*       This routine retrieves port list that share the bucket.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the given irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*
+* OUTPUTS:
+*       portVec  - the list of ports that share the bucket.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlReadPortVec
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	OUT GT_U32		*portVec
+);
+
+/*******************************************************************************
+* grcGetPirlFcMode
+*
+* DESCRIPTION:
+*       This routine gets Port Ingress Rate Limit Flow Control mode.
+*		When EBSLimitAction is programmed to generate a flow control message, 
+*		the deassertion of flow control is controlled by this mode.
+*			GT_PIRL_FC_DEASSERT_EMPTY:
+*				De-assert when the ingress rate resource has become empty
+*			GT_PIRL_FC_DEASSERT_CBS_LIMIT
+*				De-assert when the ingress rate resource has enough room as
+*				specified by the CBSLimit.
+*		Please refer to GT_PIRL_RESOURCE structure for EBSLimitAction and
+*		CBSLimit.
+*
+* INPUTS:
+*       port - logical port number
+*
+* OUTPUTS:
+*		mode - GT_PIRL_FC_DEASSERT enum type
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetPirlFcMode
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_PIRL_FC_DEASSERT		*mode
+);
+
+/*******************************************************************************
+* gpirlGetIngressRateResource
+*
+* DESCRIPTION:
+*       This routine gets Ingress Rate Limiting Resources assigned to the port.
+*		This vector is used to attach specific counter resources to the physical
+*		port. And the same counter resource can be attached to more than one port.
+*
+* INPUTS:
+*       port   - logical port number
+*
+* OUTPUTS:
+*		resVec - resource vector (bit 0 for irl unit 0, bit 1 for irl unit 1, etc.)
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gpirlGetIngressRateResource
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_U32		*resVec
+);
+
+
+
+/* gtPortStatus.c */
+
+/*******************************************************************************
+* gprtGetPxMode
+*
+* DESCRIPTION:
+*		This routine retrives 4 bits of Px_MODE Configuration value.
+*		If speed and duplex modes are forced, the returned mode value would be
+*		different from the configuration pin values.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - Px_MODE configuration value
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPxMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_U32  	*mode
+);
+
+/*******************************************************************************
+* gprtGetMiiInterface
+*
+* DESCRIPTION:
+*		This routine retrives Mii Interface Mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Mii Interface is enabled,
+*				  GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMiiInterface
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gprtGetFdFlowDis
+*
+* DESCRIPTION:
+*		This routine retrives the read time value of the Full Duplex Flow Disable.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Full Duplex Flow Disable.
+*	   		    GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetFdFlowDis
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gprtGetHdFlowDis
+*
+* DESCRIPTION:
+*		This routine retrives the read time value of the Half Duplex Flow Disable.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Half Duplex Flow Disable.
+*	   		    GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHdFlowDis
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+);
+
+/*******************************************************************************
+* gprtGetOutQSize
+*
+* DESCRIPTION:
+*		This routine gets egress queue size counter value.
+*		This counter reflects the current number of Egress buffers switched to 
+*		this port. This is the total number of buffers across all four priority 
+*		queues.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		count - egress queue size counter value
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetOutQSize
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*count
+);
+
+
+/* gtPortCtrl.c */
+
+/*******************************************************************************
+* gprtSetSAFiltering
+*
+* DESCRIPTION:
+*		This routine set the Source Address(SA) fitering method.
+*			GT_SA_FILTERING_DISABLE :
+*				no frame will be filtered.
+*			GT_SA_DROP_ON_LOCK :
+*				discard if SA field is not in the ATU's address database.
+*			GT_SA_DROP_ON_UNLOC : 
+*				discard if SA field is in the ATU's address database as Static 
+*				entry with a PortVec of all zeros.
+*			GT_SA_DROP_TO_CPU : 
+*				Ingressing frames will be mapped to the CPU Port if their SA 
+*				field is in the ATU's address database as Static entry with a 
+*				PortVec of all zeros. Otherwise, the frames will be discarded 
+*				if their SA field is not in the ATU's address database or if this
+*				port's bit is not set in the PortVec bits for the frame's SA.
+*		
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_SA_FILTERING structure
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS gprtSetSAFiltering
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT   port,
+    IN GT_SA_FILTERING    mode
+);
+
+/*******************************************************************************
+* gprtGetSAFiltering
+*
+* DESCRIPTION:
+*		This routine gets the Source Address(SA) fitering method.
+*			GT_SA_FILTERING_DISABLE :
+*				no frame will be filtered.
+*			GT_SA_DROP_ON_LOCK :
+*				discard if SA field is not in the ATU's address database.
+*			GT_SA_DROP_ON_UNLOC : 
+*				discard if SA field is in the ATU's address database as Static 
+*				entry with a PortVec of all zeros.
+*			GT_SA_DROP_TO_CPU : 
+*				Ingressing frames will be mapped to the CPU Port if their SA 
+*				field is in the ATU's address database as Static entry with a 
+*				PortVec of all zeros. Otherwise, the frames will be discarded 
+*				if their SA field is not in the ATU's address database or if this
+*				port's bit is not set in the PortVec bits for the frame's SA.
+*		
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_SA_FILTERING structure
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS gprtGetSAFiltering
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_SA_FILTERING    *mode
+);
+
+
+/*******************************************************************************
+* gprtSetARPtoCPU
+*
+* DESCRIPTION:
+*		When ARPtoCPU is set to GT_TRUE, ARP frames are mapped to the CPU port.
+*		
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE, to map ARP frames to CPU Port,
+*			   GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS gprtSetARPtoCPU
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    mode
+);
+
+
+/*******************************************************************************
+* gprtGetARPtoCPU
+*
+* DESCRIPTION:
+*		When ARPtoCPU is set to GT_TRUE, ARP frames are mapped to the CPU port.
+*		
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE, to map ARP frames to CPU Port,
+*			   GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS gprtGetARPtoCPU
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_BOOL    *mode
+);
+
+/*******************************************************************************
+* gprtSetEgressFlood
+*
+* DESCRIPTION:
+*       This routine set Egress Flooding Mode.
+*		Frames with unknown DA (Destination Address that is not in ATU database)
+*		generally flood out all the ports. This mode can be used to prevent
+*		those frames from egressing this port as follows:
+*			GT_BLOCK_EGRESS_UNKNOWN
+*				do not egress frame with unknown DA (both unicast and multicast)
+*			GT_BLOCK_EGRESS_UNKNOWN_MULTICAST
+*				do not egress frame with unknown multicast DA
+*			GT_BLOCK_EGRESS_UNKNOWN_UNICAST
+*				do not egress frame with unknown unicast DA
+*			GT_BLOCK_EGRESS_NONE
+*				egress all frames with unknown DA
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_EGRESS_FLOOD structure
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetEgressFlood
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT     port,
+    IN  GT_EGRESS_FLOOD      mode
+);
+
+/*******************************************************************************
+* gprtGetEgressFlood
+*
+* DESCRIPTION:
+*       This routine gets Egress Flooding Mode.
+*		Frames with unknown DA (Destination Address that is not in ATU database)
+*		generally flood out all the ports. This mode can be used to prevent
+*		those frames from egressing this port as follows:
+*			GT_BLOCK_EGRESS_UNKNOWN
+*				do not egress frame with unknown DA (both unicast and multicast)
+*			GT_BLOCK_EGRESS_UNKNOWN_MULTICAST
+*				do not egress frame with unknown multicast DA
+*			GT_BLOCK_EGRESS_UNKNOWN_UNICAST
+*				do not egress frame with unknown unicast DA
+*			GT_BLOCK_EGRESS_NONE
+*				egress all frames with unknown DA
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_EGRESS_FLOOD structure
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetEgressFlood
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT     port,
+    OUT GT_EGRESS_FLOOD      *mode
+);
+
+/*******************************************************************************
+* gprtSetPortSched
+*
+* DESCRIPTION:
+*		This routine sets Port Scheduling Mode.
+*		When usePortSched is enablied, this mode is used to select the Queue
+*		controller's scheduling on the port as follows:
+*			GT_PORT_SCHED_WEIGHTED_RRB - use 8,4,2,1 weighted fair scheduling
+*			GT_PORT_SCHED_STRICT_PRI - use a strict priority scheme
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_PORT_SCHED_MODE enum type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetPortSched
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_PORT_SCHED_MODE		mode
+);
+
+/*******************************************************************************
+* gprtGetPortSched
+*
+* DESCRIPTION:
+*		This routine gets Port Scheduling Mode.
+*		When usePortSched is enablied, this mode is used to select the Queue
+*		controller's scheduling on the port as follows:
+*			GT_PORT_SCHED_WEIGHTED_RRB - use 8,4,2,1 weighted fair scheduling
+*			GT_PORT_SCHED_STRICT_PRI - use a strict priority scheme
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		mode - GT_PORT_SCHED_MODE enum type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortSched
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_PORT_SCHED_MODE		*mode
+);
+
+
+/*******************************************************************************
+* gprtSetProviderTag
+*
+* DESCRIPTION:
+*		This routine sets Provider Tag which indicates the provider tag (Ether 
+*		Type) value that needs to be matched to in ingress to determine if a
+*		frame is Provider tagged or not.
+*
+* INPUTS:
+*		port - the logical port number
+*		tag  - Provider Tag (Ether Type)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetProviderTag
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U16		tag
+);
+
+/*******************************************************************************
+* gprtGetProviderTag
+*
+* DESCRIPTION:
+*		This routine gets Provider Tag which indicates the provider tag (Ether 
+*		Type) value that needs to be matched to in ingress to determine if a
+*		frame is Provider tagged or not.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		tag  - Provider Tag (Ether Type)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetProviderTag
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*tag
+);
+
+
+
+/* gtPortRateCtrl.c */
+
+/*******************************************************************************
+* grcSetVidNrlEn
+*
+* DESCRIPTION:
+*       This routine enables/disables VID None Rate Limit (NRL).
+*		When VID NRL is enabled and the determined VID of a frame results in a VID
+*		whose VIDNonRateLimit in the VTU Table is set to GT_TURE, then the frame
+*		will not be ingress nor egress rate limited.
+*
+* INPUTS:
+*       port - logical port number.
+*		mode - GT_TRUE to enable VID None Rate Limit
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetVidNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* grcGetVidNrlEn
+*
+* DESCRIPTION:
+*       This routine gets VID None Rate Limit (NRL) mode.
+*		When VID NRL is enabled and the determined VID of a frame results in a VID
+*		whose VIDNonRateLimit in the VTU Table is set to GT_TURE, then the frame
+*		will not be ingress nor egress rate limited.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable VID None Rate Limit
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetVidNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* grcSetSaNrlEn
+*
+* DESCRIPTION:
+*       This routine enables/disables SA None Rate Limit (NRL).
+*		When SA NRL is enabled and the source address of a frame results in a ATU
+*		hit where the SA's MAC address returns an EntryState that indicates Non
+*		Rate Limited, then the frame will not be ingress nor egress rate limited.
+*
+* INPUTS:
+*       port - logical port number.
+*		mode - GT_TRUE to enable SA None Rate Limit
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetSaNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* grcGetSaNrlEn
+*
+* DESCRIPTION:
+*       This routine gets SA None Rate Limit (NRL) mode.
+*		When SA NRL is enabled and the source address of a frame results in a ATU
+*		hit where the SA's MAC address returns an EntryState that indicates Non
+*		Rate Limited, then the frame will not be ingress nor egress rate limited.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable SA None Rate Limit
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetSaNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* grcSetDaNrlEn
+*
+* DESCRIPTION:
+*       This routine enables/disables DA None Rate Limit (NRL).
+*		When DA NRL is enabled and the destination address of a frame results in 
+*		a ATU hit where the DA's MAC address returns an EntryState that indicates 
+*		Non Rate Limited, then the frame will not be ingress nor egress rate 
+*		limited.
+*
+* INPUTS:
+*       port - logical port number.
+*		mode - GT_TRUE to enable DA None Rate Limit
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetDaNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* grcGetDaNrlEn
+*
+* DESCRIPTION:
+*       This routine gets SA None Rate Limit (NRL) mode.
+*		When DA NRL is enabled and the destination address of a frame results in 
+*		a ATU hit where the DA's MAC address returns an EntryState that indicates 
+*		Non Rate Limited, then the frame will not be ingress nor egress rate 
+*		limited.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable DA None Rate Limit
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetDaNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* grcSetELimitMode
+*
+* DESCRIPTION:
+*       This routine sets Egress Rate Limit counting mode.
+*		The supported modes are as follows:
+*			GT_PIRL_ELIMIT_FRAME -
+*				Count the number of frames
+*			GT_PIRL_ELIMIT_LAYER1 -
+*				Count all Layer 1 bytes: 
+*				Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
+*			GT_PIRL_ELIMIT_LAYER2 -
+*				Count all Layer 2 bytes: Frame's DA to CRC
+*			GT_PIRL_ELIMIT_LAYER1 -
+*				Count all Layer 1 bytes: 
+*				Frame's DA to CRC - 18 - 4 (if frame is tagged)
+*
+* INPUTS:
+*       port - logical port number
+*		mode - GT_PIRL_ELIMIT_MODE enum type
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*		GT_PIRL_ELIMIT_FRAME mode is supported by only a few devices.
+*		Please refer to the device datasheet for details.
+*
+*******************************************************************************/
+GT_STATUS grcSetELimitMode
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_PIRL_ELIMIT_MODE		mode
+);
+
+/*******************************************************************************
+* grcGetELimitMode
+*
+* DESCRIPTION:
+*       This routine gets Egress Rate Limit counting mode.
+*		The supported modes are as follows:
+*			GT_PIRL_ELIMIT_FRAME -
+*				Count the number of frames
+*			GT_PIRL_ELIMIT_LAYER1 -
+*				Count all Layer 1 bytes: 
+*				Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
+*			GT_PIRL_ELIMIT_LAYER2 -
+*				Count all Layer 2 bytes: Frame's DA to CRC
+*			GT_PIRL_ELIMIT_LAYER1 -
+*				Count all Layer 1 bytes: 
+*				Frame's DA to CRC - 18 - 4 (if frame is tagged)
+*
+* INPUTS:
+*       port - logical port number
+*
+* OUTPUTS:
+*		mode - GT_PIRL_ELIMIT_MODE enum type
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*		GT_PIRL_ELIMIT_FRAME mode is supported by only a few devices.
+*		Please refer to the device datasheet for details.
+*
+*******************************************************************************/
+GT_STATUS grcGetELimitMode
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_PIRL_ELIMIT_MODE		*mode
+);
+
+/*******************************************************************************
+* grcSetRsvdNrlEn
+*
+* DESCRIPTION:
+*       This routine sets Reserved Non Rate Limit.
+*		When this feature is enabled, frames that match the requirements of the 
+*		Rsvd2Cpu bit below will also be considered to be ingress and egress non 
+*		rate limited.
+*
+* INPUTS:
+*       en - GT_TRUE to enable Reserved Non Rate Limit,
+*			 GT_FALSE to disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS grcSetRsvdNrlEn
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+);
+
+/*******************************************************************************
+* grcGetRsvdNrlEn
+*
+* DESCRIPTION:
+*       This routine gets Reserved Non Rate Limit.
+*		When this feature is enabled, frames that match the requirements of the 
+*		Rsvd2Cpu bit below will also be considered to be ingress and egress non 
+*		rate limited.
+*
+* INPUTS:
+*       en - GT_TRUE to enable Reserved Non Rate Limit,
+*			 GT_FALSE to disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS grcGetRsvdNrlEn
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+);
+
+
+/* gtPortRmon.c */
+
+/*******************************************************************************
+* gstatsGetRealtimePortCounter
+*
+* DESCRIPTION:
+*		This routine gets a specific realtime counter of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*		counter - the counter which will be read
+*
+* OUTPUTS:
+*		statsData - points to 32bit data storage for the MIB counter
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetRealtimePortCounter
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	IN  GT_STATS_COUNTERS3	counter,
+	OUT GT_U32			*statsData
+);
+
+
+/* gtQosMap.c */
+
+/*******************************************************************************
+* gqosSetVIDFPriOverride
+*
+* DESCRIPTION:
+*		This routine sets VID Frame Priority Override. When this feature is enabled,
+*		VID Frame priority overrides can occur on this port.
+*		VID Frame priority override occurs when the determined VID of a frame 
+*		results in a VTU entry whose useVIDFPri override field is set to GT_TRUE.
+*		When this occurs the VIDFPri value assigned to the frame's VID (in the 
+*		VTU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new VIDFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for VID Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetVIDFPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gqosGetVIDFPriOverride
+*
+* DESCRIPTION:
+*		This routine gets VID Frame Priority Override. When this feature is enabled,
+*		VID Frame priority overrides can occur on this port.
+*		VID Frame priority override occurs when the determined VID of a frame 
+*		results in a VTU entry whose useVIDFPri override field is set to GT_TRUE.
+*		When this occurs the VIDFPri value assigned to the frame's VID (in the 
+*		VTU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new VIDFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for VID Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetVIDFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gqosSetSAFPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Source Address(SA) Frame Priority Override. 
+*		When this feature is enabled, SA Frame priority overrides can occur on 
+*		this port.
+*		SA ATU Frame priority override occurs when the determined source address
+*		of a frame results in an ATU hit where the SA's MAC address entry contains 
+*		the useATUFPri field set to GT_TRUE.
+*		When this occurs the ATUFPri value assigned to the frame's SA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new ATUFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for SA Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetSAFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gqosGetSAFPriOverride
+*
+* DESCRIPTION:
+*		This routine gets Source Address(SA) Frame Priority Override. 
+*		When this feature is enabled, SA Frame priority overrides can occur on 
+*		this port.
+*		SA ATU Frame priority override occurs when the determined source address
+*		of a frame results in an ATU hit where the SA's MAC address entry contains 
+*		the useATUFPri field set to GT_TRUE.
+*		When this occurs the ATUFPri value assigned to the frame's SA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new ATUFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for SA Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetSAFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gqosSetDAFPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Destination Address(DA) Frame Priority Override. 
+*		When this feature is enabled, DA Frame priority overrides can occur on 
+*		this port.
+*		DA ATU Frame priority override occurs when the determined destination address
+*		of a frame results in an ATU hit where the DA's MAC address entry contains 
+*		the useATUFPri field set to GT_TRUE.
+*		When this occurs the ATUFPri value assigned to the frame's DA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new ATUFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for DA Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetDAFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gqosGetDAFPriOverride
+*
+* DESCRIPTION:
+*		This routine gets Destination Address(DA) Frame Priority Override. 
+*		When this feature is enabled, DA Frame priority overrides can occur on 
+*		this port.
+*		DA ATU Frame priority override occurs when the determined destination address
+*		of a frame results in an ATU hit where the DA's MAC address entry contains 
+*		the useATUFPri field set to GT_TRUE.
+*		When this occurs the ATUFPri value assigned to the frame's DA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new ATUFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for DA Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetDAFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gqosSetVIDQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets VID Queue Priority Override. When this feature is enabled,
+*		VID Queue priority overrides can occur on this port.
+*		VID Queue priority override occurs when the determined VID of a frame 
+*		results in a VTU entry whose useVIDQPri override field is set to GT_TRUE.
+*		When this occurs the VIDQPri value assigned to the frame's VID (in the 
+*		VTU Table) is used to overwrite the frame's previously determined queue 
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new VIDQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for VID Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetVIDQPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gqosGetVIDQPriOverride
+*
+* DESCRIPTION:
+*		This routine gets VID Queue Priority Override. When this feature is enabled,
+*		VID Queue priority overrides can occur on this port.
+*		VID Queue priority override occurs when the determined VID of a frame 
+*		results in a VTU entry whose useVIDQPri override field is set to GT_TRUE.
+*		When this occurs the VIDQPri value assigned to the frame's VID (in the 
+*		VTU Table) is used to overwrite the frame's previously determined queue 
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new VIDQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for VID Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetVIDQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gqosSetSAQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Source Address(SA) Queue Priority Override. 
+*		When this feature is enabled, SA Queue priority overrides can occur on 
+*		this port.
+*		SA ATU Queue priority override occurs when the determined source address
+*		of a frame results in an ATU hit where the SA's MAC address entry contains 
+*		the useATUQPri field set to GT_TRUE.
+*		When this occurs the ATUQPri value assigned to the frame's SA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined queue 
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new ATUQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for SA Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetSAQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gqosGetSAQPriOverride
+*
+* DESCRIPTION:
+*		This routine gets Source Address(SA) Queue Priority Override. 
+*		When this feature is enabled, SA Queue priority overrides can occur on 
+*		this port.
+*		SA ATU Queue priority override occurs when the determined source address
+*		of a frame results in an ATU hit where the SA's MAC address entry contains 
+*		the useATUQPri field set to GT_TRUE.
+*		When this occurs the ATUQPri value assigned to the frame's SA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined queue 
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new ATUQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for SA Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetSAQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gqosSetDAQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Destination Address(DA) Queue Priority Override. 
+*		When this feature is enabled, DA Queue priority overrides can occur on 
+*		this port.
+*		DA ATU Queue priority override occurs when the determined destination address
+*		of a frame results in an ATU hit where the DA's MAC address entry contains 
+*		the useATUQPri field set to GT_TRUE.
+*		When this occurs the ATUQPri value assigned to the frame's DA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined queue
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new ATUQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for DA Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetDAQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gqosGetDAQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Destination Address(DA) Queue Priority Override. 
+*		When this feature is enabled, DA Queue priority overrides can occur on 
+*		this port.
+*		DA ATU Queue priority override occurs when the determined destination address
+*		of a frame results in an ATU hit where the DA's MAC address entry contains 
+*		the useATUQPri field set to GT_TRUE.
+*		When this occurs the ATUQPri value assigned to the frame's DA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined queue
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new ATUQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for DA Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetDAQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gqosSetARPQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets ARP Queue Priority Override. 
+*		When this feature is enabled, ARP Queue priority overrides can occur on 
+*		this port.
+*		ARP Queue priority override occurs for all ARP frames.
+*		When this occurs, the frame's previously determined egress queue priority
+*		will be overwritten with ArpQPri.
+*		If the frame egresses tagged the priority in the frame will not
+*		be modified. When used, the two bits of the ArpQPri priority determine the
+*		egress queue the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for ARP Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetARPQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gqosGetARPQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets ARP Queue Priority Override. 
+*		When this feature is enabled, ARP Queue priority overrides can occur on 
+*		this port.
+*		ARP Queue priority override occurs for all ARP frames.
+*		When this occurs, the frame's previously determined egress queue priority
+*		will be overwritten with ArpQPri.
+*		If the frame egresses tagged the priority in the frame will not
+*		be modified. When used, the two bits of the ArpQPri priority determine the
+*		egress queue the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for ARP Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetARPQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+
+/*******************************************************************************
+* gqosSetQPriValue
+*
+* DESCRIPTION:
+*       This routine sets Queue priority value to used when forced.
+*		When ForceQPri is enabled (gqosSetForceQPri), all frames entering this port
+*		are mapped to the priority queue defined in this value, unless a VTU, SA,
+*		DA or ARP priority override occurs. The Frame's priority (FPri) is not
+*		effected by this value.
+*
+* INPUTS:
+*       port - the logical port number.
+*       pri  - Queue priority value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if pri > 3
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosSetQPriValue
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    IN  GT_U8      pri
+);
+
+/*******************************************************************************
+* gqosGetQPriValue
+*
+* DESCRIPTION:
+*       This routine gets Queue priority value to used when forced.
+*		When ForceQPri is enabled (gqosSetForceQPri), all frames entering this port
+*		are mapped to the priority queue defined in this value, unless a VTU, SA,
+*		DA or ARP priority override occurs. The Frame's priority (FPri) is not
+*		effected by this value.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       pri  - Queue priority value
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosGetQPriValue
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_U8      *pri
+);
+
+/*******************************************************************************
+* gqosSetForceQPri
+*
+* DESCRIPTION:
+*       This routine enables/disables forcing Queue priority.
+*		When ForceQPri is disabled, normal priority queue mapping is used on all 
+*		ingressing frames entering this port. When it's enabled, all frames
+*		entering this port are mapped to the QPriValue (gqosSetQPriValue), unless
+*		a VTU, SA, DA or ARP priority override occurs. The frame's priorty (FPri)
+*		is not effected by this feature.
+*
+* INPUTS:
+*       port - the logical port number.
+*       en   - GT_TRUE, to force Queue Priority,
+*			   GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosSetForceQPri
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    IN  GT_BOOL    en
+);
+
+/*******************************************************************************
+* gqosGetForceQPri
+*
+* DESCRIPTION:
+*       This routine checks if forcing Queue priority is enabled.
+*		When ForceQPri is disabled, normal priority queue mapping is used on all 
+*		ingressing frames entering this port. When it's enabled, all frames
+*		entering this port are mapped to the QPriValue (gqosSetQPriValue), unless
+*		a VTU, SA, DA or ARP priority override occurs. The frame's priorty (FPri)
+*		is not effected by this feature.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       en   - GT_TRUE, to force Queue Priority,
+*			   GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosGetForceQPri
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_BOOL    *en
+);
+
+/*******************************************************************************
+* gqosSetDefFPri
+*
+* DESCRIPTION:
+*       This routine sets the default frame priority (0 ~ 7).
+*		This priority is used as the default frame priority (FPri) to use when 
+*		no other priority information is available.
+*
+* INPUTS:
+*       port - the logical port number
+*       pri  - default frame priority
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if pri > 7
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosSetDefFPri
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    IN  GT_U8      pri
+);
+
+/*******************************************************************************
+* gqosGetDefFPri
+*
+* DESCRIPTION:
+*       This routine gets the default frame priority (0 ~ 7).
+*		This priority is used as the default frame priority (FPri) to use when 
+*		no other priority information is available.
+*
+* INPUTS:
+*       port - the logical port number
+*
+* OUTPUTS:
+*       pri  - default frame priority
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosGetDefFPri
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_U8      *pri
+);
+
+
+/*******************************************************************************
+* gqosSetArpQPri
+*
+* DESCRIPTION:
+*       This routine sets ARP queue Priority to use for ARP QPri Overridden 
+*		frames. When a ARP frame is received on a por tthat has its ARP 
+*		QPriOVerride is enabled, the QPri assigned to the frame comes from
+*		this value
+*
+* INPUTS:
+*       pri - ARP Queue Priority (0 ~ 3)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if pri > 3
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gqosSetArpQPri
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     pri
+);
+
+
+/*******************************************************************************
+* gqosGetArpQPri
+*
+* DESCRIPTION:
+*       This routine gets ARP queue Priority to use for ARP QPri Overridden 
+*		frames. When a ARP frame is received on a por tthat has its ARP 
+*		QPriOVerride is enabled, the QPri assigned to the frame comes from
+*		this value
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       pri - ARP Queue Priority (0 ~ 3)
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gqosGetArpQPri
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_U8     *pri
+);
+
+
+/* gtSysCtrl.c */
+
+/*******************************************************************************
+* gsysSetUsePortSchedule
+*
+* DESCRIPTION:
+*       This routine sets per port scheduling mode
+*
+* INPUTS:
+*       en - GT_TRUE enables per port scheduling, 
+*			 GT_FALSE disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetUsePortSchedule
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+);
+
+/*******************************************************************************
+* gsysGetUsePortSchedule
+*
+* DESCRIPTION:
+*       This routine gets per port scheduling mode
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE enables per port scheduling, 
+*			 GT_FALSE disable.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetUsePortSchedule
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+);
+
+/*******************************************************************************
+* gsysSetOldHader
+*
+* DESCRIPTION:
+*       This routine sets Egress Old Header.
+*		When this feature is enabled and frames are egressed with a Marvell Header, 
+*		the format of the Header is slightly modified to be backwards compatible 
+*		with previous devices that used the original Header. Specifically, bit 3
+*		of the Header's 2nd octet is cleared to a zero such that only FPri[2:1]
+*		is available in the Header.
+*
+* INPUTS:
+*       en - GT_TRUE to enable Old Header Mode,
+*			 GT_FALSE to disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetOldHader
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+);
+
+/*******************************************************************************
+* gsysGetOldHader
+*
+* DESCRIPTION:
+*       This routine gets Egress Old Header.
+*		When this feature is enabled and frames are egressed with a Marvell Header, 
+*		the format of the Header is slightly modified to be backwards compatible 
+*		with previous devices that used the original Header. Specifically, bit 3
+*		of the Header's 2nd octet is cleared to a zero such that only FPri[2:1]
+*		is available in the Header.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE to enable Old Header Mode,
+*			 GT_FALSE to disable
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetOldHader
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+);
+
+/*******************************************************************************
+* gsysSetRecursiveStrippingDisable
+*
+* DESCRIPTION:
+*       This routine determines if recursive tag stripping feature needs to be
+*		disabled.
+*
+* INPUTS:
+*       en - GT_TRUE to disable Recursive Tag Stripping,
+*			 GT_FALSE to enable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRecursiveStrippingDisable
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+);
+
+/*******************************************************************************
+* gsysGetRecursiveStrippingDisable
+*
+* DESCRIPTION:
+*       This routine checks if recursive tag stripping feature is disabled.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE, if Recursive Tag Stripping is disabled,
+*			 GT_FALSE, otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRecursiveStrippingDisable
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+);
+
+/*******************************************************************************
+* gsysSetCPUPort
+*
+* DESCRIPTION:
+*       This routine sets CPU Port where Rsvd2Cpu frames and IGMP/MLD Snooped 
+*		frames are destined.
+*
+* INPUTS:
+*       cpuPort - CPU Port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetCPUPort
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  cpuPort
+);
+
+/*******************************************************************************
+* gsysGetCPUPort
+*
+* DESCRIPTION:
+*       This routine gets CPU Port where Rsvd2Cpu frames and IGMP/MLD Snooped 
+*		frames are destined.
+*
+* INPUTS:
+*       cpuPort - CPU Port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetCPUPort
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_LPORT  *cpuPort
+);
+
+
+
+/* gtSysStatus.c */
+
+/*******************************************************************************
+* gsysGetFreeQSize
+*
+* DESCRIPTION:
+*       This routine gets Free Queue Counter. This counter reflects the 
+*		current number of unalllocated buffers available for all the ports.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       count - Free Queue Counter
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetFreeQSize
+(
+    IN  GT_QD_DEV	*dev,
+    OUT GT_U16 		*count
+);
+
+/*******************************************************************************
+				New APIs in DSDT 2.6
+*******************************************************************************/
+
+/* gtBrgFdb.c */
+
+/*******************************************************************************
+* gfdbSetPortAtuLearnLimit
+*
+* DESCRIPTION:
+*       Port's auto learning limit. When the limit is non-zero value, the number
+*		of MAC addresses that can be learned on this port are limited to the value
+*		specified in this API. When the learn limit has been reached any frame 
+*		that ingresses this port with a source MAC address not already in the 
+*		address database that is associated with this port will be discarded. 
+*		Normal auto-learning will resume on the port as soon as the number of 
+*		active unicast MAC addresses associated to this port is less than the 
+*		learn limit.
+*		CPU directed ATU Load, Purge, or Move will not have any effect on the 
+*		learn limit.
+*		This feature is disabled when the limit is zero.
+*		The following care is needed when enabling this feature:
+*			1) disable learning on the ports
+*			2) flush all non-static addresses in the ATU
+*			3) define the desired limit for the ports
+*			4) re-enable learing on the ports
+*
+* INPUTS:
+*       port  - logical port number
+*       limit - auto learning limit ( 0 ~ 255 )
+*											  
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if limit > 0xFF
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbSetPortAtuLearnLimit
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT  	port,
+    IN  GT_U32   	limit
+);
+
+
+/*******************************************************************************
+* gfdbGetPortAtuLearnCnt
+*
+* DESCRIPTION:
+*       Read the current number of active unicast MAC addresses associated with 
+*		the given port. This counter (LearnCnt) is held at zero if learn limit
+*		(gfdbSetPortAtuLearnLimit API) is set to zero.
+*
+* INPUTS:
+*       port  - logical port number
+*											  
+* OUTPUTS:
+*       count - current auto learning count
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetPortAtuLearnCnt
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT  	port,
+    IN  GT_U32   	*count
+);
+
+/*******************************************************************************
+* gfdbGetAtuAllCount
+*
+* DESCRIPTION:
+*       Counts all entries in the Address Translation Unit.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       count - number of valid entries.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuAllCount
+(
+    IN  GT_QD_DEV 	*dev,
+    OUT GT_U32 		*count
+);
+
+/*******************************************************************************
+* gfdbGetAtuAllCountInDBNum
+*
+* DESCRIPTION:
+*       Counts all entries in the defined FID (or DBNum).
+*
+* INPUTS:
+*       dbNum - DBNum of FID
+*
+* OUTPUTS:
+*       count - number of valid entries in FID (or DBNum).
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuAllCountInDBNum
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_U32 		dbNum,
+    OUT GT_U32 		*count
+);
+
+/*******************************************************************************
+* gfdbGetAtuDynamicCountInDBNum
+*
+* DESCRIPTION:
+*       Counts all non-static entries in the defined FID (or DBNum).
+*
+* INPUTS:
+*       dbNum - DBNum or FID
+*
+* OUTPUTS:
+*       count - number of valid non-static entries in FID (or DBNum).
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuDynamicCountInDBNum
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_U32 		dbNum,
+    OUT GT_U32 		*count
+);
+
+
+/* gtBrgStu.c */
+
+/*******************************************************************************
+* gstuGetEntryCount
+*
+* DESCRIPTION:
+*       Gets the current number of valid entries in the STU table
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       numEntries - number of STU entries.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gstuGetEntryCount
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_U32    *numEntries
+);
+
+/*******************************************************************************
+* gstuGetEntryFirst
+*
+* DESCRIPTION:
+*       Gets first lexicographic entry from the STU.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       stuEntry - find the first valid STU entry.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - table is empty.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstuGetEntryFirst
+(
+    IN  GT_QD_DEV       *dev,
+    OUT GT_STU_ENTRY    *stuEntry
+);
+
+/*******************************************************************************
+* gstuGetEntryNext
+*
+* DESCRIPTION:
+*       Gets next lexicographic STU entry from the specified SID.
+*
+* INPUTS:
+*       stuEntry - the SID to start the search.
+*
+* OUTPUTS:
+*       stuEntry - next STU entry.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstuGetEntryNext
+(
+    IN  GT_QD_DEV       *dev,
+    INOUT GT_STU_ENTRY  *stuEntry
+);
+
+/*******************************************************************************
+* gstuFindSidEntry
+*
+* DESCRIPTION:
+*       Find STU entry for a specific SID, it will return the entry, if found, 
+*       along with its associated data 
+*
+* INPUTS:
+*       stuEntry - contains the SID to searche for 
+*
+* OUTPUTS:
+*       found    - GT_TRUE, if the appropriate entry exists.
+*       stuEntry - the entry parameters.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no such entry.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstuFindSidEntry
+(
+    IN  GT_QD_DEV       *dev,
+    INOUT GT_STU_ENTRY  *stuEntry,
+    OUT GT_BOOL         *found
+);
+
+/*******************************************************************************
+* gstuAddEntry
+*
+* DESCRIPTION:
+*       Creates or update the entry in STU table based on user input.
+*
+* INPUTS:
+*       stuEntry    - stu entry to insert to the STU.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK             - on success
+*       GT_FAIL           - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gstuAddEntry
+(
+    IN  GT_QD_DEV   	*dev,
+    IN  GT_STU_ENTRY	*stuEntry
+);
+
+/*******************************************************************************
+* gstuDelEntry
+*
+* DESCRIPTION:
+*       Deletes STU entry specified by user.
+*
+* INPUTS:
+*       stuEntry - the STU entry to be deleted 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstuDelEntry
+(
+    IN  GT_QD_DEV   	*dev,
+    IN  GT_STU_ENTRY 	*stuEntry
+);
+
+
+/* gtCCPVT.c */
+
+/*******************************************************************************
+* gpvtInitialize
+*
+* DESCRIPTION:
+*       This routine initializes the PVT Table to all one's (initial state)
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpvtInitialize
+(
+	IN  GT_QD_DEV 	*dev
+);
+
+/*******************************************************************************
+* gpvtWritePVTData
+*
+* DESCRIPTION:
+*       This routine write Cross Chip Port Vlan Data.
+*		Cross chip Port VLAN Data used as a bit mask to limit where cross chip
+*		frames can egress (in chip Port VLANs are masked using gvlnSetPortVlanPorts
+*		API). Cross chip frames are Forward frames that ingress a DSA or Ether 
+*		Type DSA port (see gprtSetFrameMode API). Bit 0 is a mask for port 0, 
+*		bit 1 for port 1, etc. When a port's mask bit is one, frames are allowed 
+*		to egress that port on this device. When a port's mask bit is zero,
+*		frames are not allowed to egress that port on this device.
+*
+*		The Cross Chip Port VLAN Table is accessed by ingressing frames based
+*		upon the original source port of the frame using the Forward frame's DSA tag
+*		fields Src_Dev, Src_Port/Src_Trunk and Src_Is_Trunk. The 1 entry of the 512
+*		that is accessed by the frame is:
+*			If 5 Bit Port (in Global 2, offset 0x1D) = 0:
+*				If Src_Is_Trunk = 0   Src_Dev[4:0], Src_Port[3:0]119
+*				If Src_Is_Trunk = 1   Device Number (global offset 0x1C), Src_Trunk[3:0]
+*			If 5 Bit Port (in Global 2, offset 0x1D) = 1:
+*				If Src_Is_Trunk = 0   Src_Dev[3:0], Src_Port[4:0]120
+*				If Src_Is_Trunk = 1   Device Number[3:0], Src_Trunk[4:0]
+*
+*		Cross chip port VLANs with Trunks are supported in the table where this
+*		device's entries would be stored (defined by this device's Device Number).
+*		This portion of the table is available for Trunk entries because this device's
+*		port VLAN mappings to ports inside this device are masked by the port's
+*		VLAN Table (see gvlnSetPortVlanPorts API).
+*
+*
+* INPUTS:
+*		pvtPointer - pointer to the desired entry of PVT (0 ~ 511)
+*		pvtData    - Cross Chip Port Vlan Data
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpvtWritePVTData
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		pvtPointer,
+	IN  GT_U32		pvtData
+);
+
+/*******************************************************************************
+* gpvtReadPVTData
+*
+* DESCRIPTION:
+*       This routine reads Cross Chip Port Vlan Data.
+*		Cross chip Port VLAN Data used as a bit mask to limit where cross chip
+*		frames can egress (in chip Port VLANs are masked using gvlnSetPortVlanPorts
+*		API). Cross chip frames are Forward frames that ingress a DSA or Ether 
+*		Type DSA port (see gprtSetFrameMode API). Bit 0 is a mask for port 0, 
+*		bit 1 for port 1, etc. When a port's mask bit is one, frames are allowed 
+*		to egress that port on this device. When a port's mask bit is zero,
+*		frames are not allowed to egress that port on this device.
+*
+*		The Cross Chip Port VLAN Table is accessed by ingressing frames based
+*		upon the original source port of the frame using the Forward frame's DSA tag
+*		fields Src_Dev, Src_Port/Src_Trunk and Src_Is_Trunk. The 1 entry of the 512
+*		that is accessed by the frame is:
+*			If 5 Bit Port (in Global 2, offset 0x1D) = 0:
+*				If Src_Is_Trunk = 0   Src_Dev[4:0], Src_Port[3:0]119
+*				If Src_Is_Trunk = 1   Device Number (global offset 0x1C), Src_Trunk[3:0]
+*			If 5 Bit Port (in Global 2, offset 0x1D) = 1:
+*				If Src_Is_Trunk = 0   Src_Dev[3:0], Src_Port[4:0]120
+*				If Src_Is_Trunk = 1   Device Number[3:0], Src_Trunk[4:0]
+*
+*		Cross chip port VLANs with Trunks are supported in the table where this
+*		device's entries would be stored (defined by this device's Device Number).
+*		This portion of the table is available for Trunk entries because this device's
+*		port VLAN mappings to ports inside this device are masked by the port's
+*		VLAN Table (see gvlnSetPortVlanPorts API).
+*
+*
+* INPUTS:
+*		pvtPointer - pointer to the desired entry of PVT (0 ~ 511)
+*
+* OUTPUTS:
+*		pvtData    - Cross Chip Port Vlan Data
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpvtReadPVTData
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		pvtPointer,
+	OUT GT_U32		*pvtData
+);
+
+
+/* gtEvents.c */
+
+/*******************************************************************************
+* geventGetDevIntStatus
+*
+* DESCRIPTION:
+* 		Check to see which device interrupts (WatchDog, JamLimit, Duplex Mismatch, and
+*		SERDES Link Int) have occurred.
+*
+* INPUTS:
+*       intType - the type of interrupt which causes an interrupt.
+*				  any combination of 
+*					GT_DEV_INT_WATCHDOG,
+*					GT_DEV_INT_JAMLIMIT,
+*					GT_DEV_INT_DUPLEX_MISMATCH,
+*					GT_DEV_INT_SERDES_LINK
+*		port	- logical port where GT_DEV_INT_DUPLEX_MISMATCH occurred.
+*				  valid only if GT_DEV_INT_DUPLEX_MISMATCH is set in intType.
+*		linkInt - SERDES port list where GT_DEV_INT_SERDES_LINK interrupt is
+*				  asserted. It's in vector format, Bit 10 is for port 10, 
+*				  Bit 9 is for port 9, etc.
+*				  valid only if GT_DEV_INT_SERDES_LINK bit is set in intType.
+*				  These bits are only valid of the port that is in 1000Base-X mode.
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK - on success
+* 		GT_FAIL - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS geventGetDevIntStatus
+(
+    IN  GT_QD_DEV 			*dev,
+    OUT GT_DEV_INT_STATUS	*devIntStatus
+);
+
+/*******************************************************************************
+* geventSetAgeOutIntEn
+*
+* DESCRIPTION:
+*		Interrupt on Age Out. When aging is enabled, all non-static address 
+*		entries in the ATU's address database are periodically aged.
+*		When this feature is set to GT_TRUE and an entry associated with this 
+*		port is aged out, an AgeOutViolation will be captured for that entry.
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_TRUE to enable Age Out Interrupt,
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventSetAgeOutIntEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* geventGetAgeOutIntEn
+*
+* DESCRIPTION:
+*		Interrupt on Age Out. When aging is enabled, all non-static address 
+*		entries in the ATU's address database are periodically aged.
+*		When this feature is set to GT_TRUE and an entry associated with this 
+*		port is aged out, an AgeOutViolation will be captured for that entry.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		mode - GT_TRUE, if Age Out Interrupt is enabled
+*			   GT_FALUSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventGetAgeOutIntEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* geventSetOverLimitInt
+*
+* DESCRIPTION:
+*		This routine enables/disables Over Limit Interrupt for a port.
+*		If it's enabled, an ATU Miss violation will be generated when port auto
+*		learn reached the limit(refer to gfdbGetPortAtuLimitReached API).
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_TRUE to enable Over Limit Interrupt,
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventSetOverLimitInt
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+);
+
+/*******************************************************************************
+* geventGetOverLimitInt
+*
+* DESCRIPTION:
+*		This routine enables/disables Over Limit Interrupt for a port.
+*		If it's enabled, an ATU Miss violation will be generated when port auto
+*		learn reached the limit(refer to gfdbSetPortAtuLearnLimit API).
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable Over Limit Interrupt,
+*			   GT_FALUSE to disable
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventGetOverLimitInt
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* geventGetPortAtuLimitReached
+*
+* DESCRIPTION:
+*       This routine checks if learn limit has been reached.
+*		When it reached, the port can no longer auto learn any more MAC addresses
+*		because the address learn limit set on this port has been reached.
+*
+* INPUTS:
+*       port  - logical port number
+*											  
+* OUTPUTS:
+*       limit - GT_TRUE, if limit has been reached
+*			    GT_FALSE, otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*
+*******************************************************************************/
+GT_STATUS geventGetPortAtuLimitReached
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT  	port,
+    IN  GT_BOOL   	*limit
+);
+
+/*******************************************************************************
+* eventSetDevInt
+*
+* DESCRIPTION:
+*		Device Interrupt.
+*		The following device interrupts are supported:
+*			GT_DEV_INT_WATCHDOG	- 
+*				WatchDog event interrupt (WatchDog event can be configured with 
+*				gwdSetEvent API)
+*			GT_DEV_INT_JAMLIMIT	-
+*				any of the ports detect an Ingress Jam Limit violation
+*				(see gprtSetPauseLimitIn API)
+*			GT_DEV_INT_DUPLEX_MISMATCH - 
+*				any of the ports detect a duplex mismatch (i.e., the local port is 
+*				in half duplex mode while the link partner is in full duplex mode)
+*			GT_DEV_INT_SERDES_LINK - 
+*				SERDES link chage interrupt.
+*				An interrupt occurs when a SERDES port changes link status
+*				(link up or link down)
+*			
+*		If any of the above events is enabled, GT_DEVICE_INT interrupt will
+*		be asserted by the enabled event when GT_DEV_INT is enabled with 
+*		eventSetActive API.
+*		
+* INPUTS:
+*		devInt - GT_DEV_INT
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS eventSetDevInt
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_DEV_EVENT    *devInt
+);
+
+/*******************************************************************************
+* gwdSetEvent
+*
+* DESCRIPTION:
+*		Watch Dog Event.
+*		The following Watch Dog events are supported:
+*			GT_WD_QC  - Queue Controller Watch Dog enable.
+*						When enabled, the QC's watch dog circuit checks for link
+*						list errors and any errors found in the QC.
+*			GT_WD_EGRESS - Egress Watch Dog enable.
+*						When enabled, each port's egress circuit checks for problems
+*						between the port and the Queue Controller.
+*			GT_WD_FORCE - Force a Watch Dog event.
+*			
+*		If any of the above events is enabled, GT_DEVICE_INT interrupt will
+*		be asserted by the enabled WatchDog event when GT_DEV_INT_WATCHDOG is
+*		enabled with eventSetDevActive API and GT_DEV_INT is enabled with 
+*		eventSetActive API.
+*		
+* INPUTS:
+*		wdEvent - Watch Dog Events
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdSetEvent
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32	    wdEvent
+);
+
+/*******************************************************************************
+* gwdSetSWResetOnWD
+*
+* DESCRIPTION:
+*		SWReset on Watch Dog Event.
+*		When this feature is enabled, any enabled watch dog event (gwdSetEvent API) 
+*		will automatically reset the switch core's datapath just as if gsysSwReset
+*		API is called.
+*
+*		The Watch Dog History (gwdGetHistory API) won't be cleared by this 
+*		automatic SWReset. This allows the user to know if any watch dog event 
+*		ever occurred even if the swich is configured to automatically recover 
+*		from a watch dog.
+*
+*		When this feature is disabled, enabled watch dog events will not cause a
+*		SWReset.
+*
+* INPUTS:
+*		en   - GT_TRUE to enable SWReset on WD
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdSetSWResetOnWD
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL	    en
+);
+
+/*******************************************************************************
+* gwdGetSWResetOnWD
+*
+* DESCRIPTION:
+*		SWReset on Watch Dog Event.
+*		When this feature is enabled, any enabled watch dog event (gwdSetEvent API) 
+*		will automatically reset the switch core's datapath just as if gsysSwReset
+*		API is called.
+*
+*		The Watch Dog History (gwdGetHistory API) won't be cleared by this 
+*		automatic SWReset. This allows the user to know if any watch dog event 
+*		ever occurred even if the swich is configured to automatically recover 
+*		from a watch dog.
+*
+*		When this feature is disabled, enabled watch dog events will not cause a
+*		SWReset.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en   - GT_TRUE, if SWReset on WD is enabled
+*			   GT_FALUSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdGetSWResetOnWD
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL	    *en
+);
+
+/*******************************************************************************
+* gwdGetHistory
+*
+* DESCRIPTION:
+*		This routine retrieves Watch Dog history. They are
+*
+*		wdEvent - 
+*			When it's set to GT_TRUE, some enabled Watch Dog event occurred.
+*			The following events are possible:
+*				QC WatchDog Event (GT_WD_QC)
+*				Egress WatchDog Event (GT_WD_EGRESS)
+*				Forced WatchDog Event (GT_WD_FORCE)
+*		egressEvent -
+*			If any port's egress logic detects an egress watch dog issue,
+*			this field is set to GT_TRUE, regardless of the enabling GT_WD_EGRESS
+*			event.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		history - GT_WD_EVENT_HISTORY structure
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdGetHistory
+(
+	IN  GT_QD_DEV			*dev,
+	OUT GT_WD_EVENT_HISTORY	*history
+);
+
+
+/* gtPIRL2.c */
+
+/*******************************************************************************
+* gpirl2WriteResource
+*
+* DESCRIPTION:
+*       This routine writes resource bucket parameters to the given resource
+*		of the port.
+*
+* INPUTS:
+*       port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 4).
+*		pirlData - PIRL resource parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirl2WriteResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes,
+	IN  GT_PIRL2_DATA	*pirlData
+);
+
+/*******************************************************************************
+* gpirl2ReadResource
+*
+* DESCRIPTION:
+*       This routine retrieves IRL Parameter.
+*
+* INPUTS:
+*       port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 4).
+*
+* OUTPUTS:
+*		pirlData - PIRL resource parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirl2ReadResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes,
+	OUT GT_PIRL2_DATA	*pirlData
+);
+
+/*******************************************************************************
+* gpirl2DisableResource
+*
+* DESCRIPTION:
+*       This routine disables Ingress Rate Limiting for the given bucket.
+*
+* INPUTS:
+*       port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 4).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirl2DisableResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes
+);
+
+
+/* gtPolicy.c */
+
+/*******************************************************************************
+* gprtSetPolicy
+*
+* DESCRIPTION:
+*       This routine sets the Policy for ports.
+*		Supported Policies are defined as GT_FRAME_POLICY as follows:
+*			FRAME_POLICY_NONE    - normal frame switching
+*			FRAME_POLICY_MIRROR  - mirror (copy) frame to MirrorDest port
+*			FRAME_POLICY_TRAP    - trap(re-direct) frame to the CPUDest port
+*			FRAME_POLICY_DISCARD - discard(filter) the frame
+*		Supported Policy types are defined as GT_POLICY_TYPE:
+*			POLICY_TYPE_DA - DA Policy Mapping
+*				DA Policy Mapping occurs when the DA of a frame is contained in 
+*				the ATU address database with an Entry State that indicates Policy.
+*			POLICY_TYPE_SA - SA Policy Mapping
+*				SA Policy Mapping occurs when the SA of a frame is contained in 
+*				the ATU address database with an Entry State that indicates Policy.
+*			POLICY_TYPE_VTU - VTU Policy Mapping
+*				VTU Policy Mapping occurs when the VID of a frame is contained in
+*				the VTU database with the VidPolicy is enabled.
+*			POLICY_TYPE_ETYPE - EtherType Policy Mapping
+*				EType Policy Mapping occurs when the EtherType of a frame matches
+*				the PortEType (see gprtSetPortEType API)
+*			POLICY_TYPE_PPPoE - PPPoE Policy Mapping
+*				PPPoE Policy Mapping occurs when the EtherType of a frame matches 0x8863
+*			POLICY_TYPE_VBAS - VBAS Policy Mapping
+*				VBAS Policy Mapping occurs when the EtherType of a frame matches 0x8200
+*			POLICY_TYPE_OPT82 - DHCP Option 82 Policy Mapping
+*				DHCP Option 82 Policy Mapping occurs when the ingressing frame is an
+*				IPv4 UDP with a UDP Destination port = 0x0043 or 0x0044, or an
+*				IPv6 UDP with a UDP Destination port = 0x0223 or 0x0222
+*			POLICY_TYPE_UDP - UDP Policy Mapping
+*				UDP Policy Mapping occurs when the ingressing frame is
+*				a Broadcast IPv4 UDP or a Multicast IPv6 UDP.
+*
+* INPUTS:
+*       port	- logical port number.
+*       type 	- policy type (GT_POLICY_TYPE)
+*       policy 	- policy (GT_FRAME_POLICY)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*       GT_BAD_PARAM     - on bad parameters
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPolicy
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT 	port,
+    IN  GT_POLICY_TYPE	type,
+	IN	GT_FRAME_POLICY	policy
+);
+
+/*******************************************************************************
+* gprtGetPolicy
+*
+* DESCRIPTION:
+*       This routine gets the Policy of the given policy type.
+*		Supported Policies are defined as GT_FRAME_POLICY as follows:
+*			FRAME_POLICY_NONE    - normal frame switching
+*			FRAME_POLICY_MIRROR  - mirror (copy) frame to MirrorDest port
+*			FRAME_POLICY_TRAP    - trap(re-direct) frame to the CPUDest port
+*			FRAME_POLICY_DISCARD - discard(filter) the frame
+*		Supported Policy types are defined as GT_POLICY_TYPE:
+*			POLICY_TYPE_DA - DA Policy Mapping
+*				DA Policy Mapping occurs when the DA of a frame is contained in 
+*				the ATU address database with an Entry State that indicates Policy.
+*			POLICY_TYPE_SA - SA Policy Mapping
+*				SA Policy Mapping occurs when the SA of a frame is contained in 
+*				the ATU address database with an Entry State that indicates Policy.
+*			POLICY_TYPE_VTU - VTU Policy Mapping
+*				VTU Policy Mapping occurs when the VID of a frame is contained in
+*				the VTU database with the VidPolicy is enabled.
+*			POLICY_TYPE_ETYPE - EtherType Policy Mapping
+*				EType Policy Mapping occurs when the EtherType of a frame matches
+*				the PortEType (see gprtSetPortEType API)
+*			POLICY_TYPE_PPPoE - PPPoE Policy Mapping
+*				PPPoE Policy Mapping occurs when the EtherType of a frame matches 0x8863
+*			POLICY_TYPE_VBAS - VBAS Policy Mapping
+*				VBAS Policy Mapping occurs when the EtherType of a frame matches 0x8200
+*			POLICY_TYPE_OPT82 - DHCP Option 82 Policy Mapping
+*				DHCP Option 82 Policy Mapping occurs when the ingressing frame is an
+*				IPv4 UDP with a UDP Destination port = 0x0043 or 0x0044, or an
+*				IPv6 UDP with a UDP Destination port = 0x0223 or 0x0222
+*			POLICY_TYPE_UDP - UDP Policy Mapping
+*				UDP Policy Mapping occurs when the ingressing frame is
+*				a Broadcast IPv4 UDP or a Multicast IPv6 UDP.
+*
+* INPUTS:
+*       port	- logical port number.
+*       type 	- policy type (GT_POLICY_TYPE)
+*
+* OUTPUTS:
+*       policy 	- policy (GT_FRAME_POLICY)
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*       GT_BAD_PARAM     - on bad parameters
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPolicy
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT 	port,
+    IN  GT_POLICY_TYPE	type,
+	OUT GT_FRAME_POLICY	*policy
+);
+
+
+/* gtPortCtrl.c */
+
+/*******************************************************************************
+* gprtSetPauseLimitOut
+*
+* DESCRIPTION:
+*		Limit the number of continuous Pause refresh frames that can be transmitted
+*		from this port. When full duplex Flow Control is enabled on this port,
+*		these bits are used to limit the number of Pause refresh frames that can 
+*		be generated from this port to keep this port's link partner from sending
+*		any data.
+*		Setting this value to 0 will allow continuous Pause frame refreshes to 
+*		egress this port as long as this port remains congested.
+*		Setting this value to 1 will allow 1 Pause frame to egress from this port
+*		for each congestion situation.
+*		Setting this value to 2 will allow 2 Pause frames to egress from this port
+*		for each congestion situation, etc.
+*		
+* INPUTS:
+*		port - the logical port number
+*		limit - the max number of Pause refresh frames for each congestion situation
+*				( 0 ~ 0xFF)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if limit > 0xFF
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetPauseLimitOut
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U16		limit
+);
+
+/*******************************************************************************
+* gprtGetPauseLimitOut
+*
+* DESCRIPTION:
+*		Limit the number of continuous Pause refresh frames that can be transmitted
+*		from this port. When full duplex Flow Control is enabled on this port,
+*		these bits are used to limit the number of Pause refresh frames that can 
+*		be generated from this port to keep this port's link partner from sending
+*		any data.
+*		Setting this value to 0 will allow continuous Pause frame refreshes to 
+*		egress this port as long as this port remains congested.
+*		Setting this value to 1 will allow 1 Pause frame to egress from this port
+*		for each congestion situation.
+*		Setting this value to 2 will allow 2 Pause frames to egress from this port
+*		for each congestion situation, etc.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		limit - the max number of Pause refresh frames for each congestion situation
+*				( 0 ~ 0xFF)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetPauseLimitOut
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*limit
+);
+
+/*******************************************************************************
+* gprtSetPauseLimitIn
+*
+* DESCRIPTION:
+*		Limit the number of continuous Pause refresh frames that can be received
+*		on this port. When a port has flow Control enabled, this value can be 
+*		used to limit how long this port can be Paused off to prevent a port stall
+*		through jamming.
+*		When this value is in the range of 0x01 to 0xFF, and a frame is ready to
+*		be transmitted out this port, but it cannot be transmitted due to the port
+*		being jammed, this limit mechanism starts. The limit mechanism starts 
+*		counting new Pause refresh frames or counts of 16 consecutive collisions.
+*		If the counter reaches the value set through this API, the following event
+*		will occur:
+*			1) Port's ForceFC is enabled,
+*			2) Port's FCValue is cleared to a zero, and
+*			3) Jam Limit Interrupt is asserted.
+*		This effectively disables Flow Control on the port once the Pause timer 
+*		expires. If a frame gets transmitted out this port before the counter
+*		reaches this limit, then this limit mechanism counter resets back to zero.
+*
+*		Setting this value to 0 will allow continuous jamming to be received on 
+*		this port without the Port's ForceFC and FCValue getting modified.
+*
+*		The modification of Port's ForceFC and FCValue is the only indication that 
+*		the limit was reached on this port.
+*		
+* INPUTS:
+*		port - the logical port number
+*		limit - the max number of continuous Pause refresh frames for each trasmition
+*				( 0 ~ 0xFF)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if limit > 0xFF
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetPauseLimitIn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U16		limit
+);
+
+/*******************************************************************************
+* gprtGetPauseLimitIn
+*
+* DESCRIPTION:
+*		Limit the number of continuous Pause refresh frames that can be received
+*		on this port. When a port has flow Control enabled, this value can be 
+*		used to limit how long this port can be Paused off to prevent a port stall
+*		through jamming.
+*		When this value is in the range of 0x01 to 0xFF, and a frame is ready to
+*		be transmitted out this port, but it cannot be transmitted due to the port
+*		being jammed, this limit mechanism starts. The limit mechanism starts 
+*		counting new Pause refresh frames or counts of 16 consecutive collisions.
+*		If the counter reaches the value set through this API, the following event
+*		will occur:
+*			1) Port's ForceFC is enabled,
+*			2) Port's FCValue is cleared to a zero, and
+*			3) Jam Limit Interrupt is asserted.
+*		This effectively disables Flow Control on the port once the Pause timer 
+*		expires. If a frame gets transmitted out this port before the counter
+*		reaches this limit, then this limit mechanism counter resets back to zero.
+*
+*		Setting this value to 0 will allow continuous jamming to be received on 
+*		this port without the Port's ForceFC and FCValue getting modified.
+*
+*		The modification of Port's ForceFC and FCValue is the only indication that 
+*		the limit was reached on this port.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		limit - the max number of continuous Pause refresh frames for each trasmition
+*				( 0 ~ 0xFF)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetPauseLimitIn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*limit
+);
+
+/*******************************************************************************
+* gprtSetFrameMode
+*
+* DESCRIPTION:
+*		Frmae Mode is used to define the expected Ingress and the generated Egress
+*		tagging frame format for this port as follows:
+*			GT_FRAME_MODE_NORMAL -
+*				Normal Network mode uses industry standard IEEE 802.3ac Tagged or 
+*				Untagged frames. Tagged frames use an Ether Type of 0x8100.
+*			GT_FRAME_MODE_DSA -
+*				DSA mode uses a Marvell defined tagged frame format for 
+*				Chip-to-Chip and Chip-to-CPU connections.
+*			GT_FRAME_MODE_PROVIDER -
+*				Provider mode uses user definable Ether Types per port 
+*				(see gprtSetPortEType/gprtGetPortEType API).
+*			GT_FRAME_MODE_ETHER_TYPE_DSA -
+*				Ether Type DSA mode uses standard Marvell DSA Tagged frame info 
+*				flowing a user definable Ether Type. This mode allows the mixture
+*				of Normal Network frames with DSA Tagged frames and is useful to 
+*				be used on ports that connect to a CPU.
+*		
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_FRAME_MODE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if mode is unknown
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetFrameMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_FRAME_MODE	mode
+);
+
+/*******************************************************************************
+* gprtGetFrameMode
+*
+* DESCRIPTION:
+*		Frmae Mode is used to define the expected Ingress and the generated Egress
+*		tagging frame format for this port as follows:
+*			GT_FRAME_MODE_NORMAL -
+*				Normal Network mode uses industry standard IEEE 802.3ac Tagged or 
+*				Untagged frames. Tagged frames use an Ether Type of 0x8100.
+*			GT_FRAME_MODE_DSA -
+*				DSA mode uses a Marvell defined tagged frame format for 
+*				Chip-to-Chip and Chip-to-CPU connections.
+*			GT_FRAME_MODE_PROVIDER -
+*				Provider mode uses user definable Ether Types per port 
+*				(see gprtSetPortEType/gprtGetPortEType API).
+*			GT_FRAME_MODE_ETHER_TYPE_DSA -
+*				Ether Type DSA mode uses standard Marvell DSA Tagged frame info 
+*				flowing a user definable Ether Type. This mode allows the mixture
+*				of Normal Network frames with DSA Tagged frames and is useful to 
+*				be used on ports that connect to a CPU.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		mode - GT_FRAME_MODE type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetFrameMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_FRAME_MODE	*mode
+);
+
+/*******************************************************************************
+* gprtSetHoldAt1
+*
+* DESCRIPTION:
+*		Hold Aging ATU Entries at an Entry State value of 1. When this feature
+*		is set to GT_TRUE, ATU entries associated with this port will age down 
+*		to an Entry State of 0x1, but will not go to 0x0 (0x0 would purge the
+*		entry)
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to hold aging ATU entry with Entry State of 1, 
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetHoldAt1
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetHoldAt1
+*
+* DESCRIPTION:
+*		Hold Aging ATU Entries at an Entry State value of 1. When this feature
+*		is set to GT_TRUE, ATU entries associated with this port will age down 
+*		to an Entry State of 0x1, but will not go to 0x0 (0x0 would purge the
+*		entry)
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to hold aging ATU entry with Entry State of 1, 
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHoldAt1
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL  	*mode
+);
+
+/*******************************************************************************
+* gprtSetRefreshLocked
+*
+* DESCRIPTION:
+*		Auto Refresh known addresses when port is Locked. Already known addresses 
+*		will be auto refreshed when this feature is enabled. When this feature
+*		is disabled, auto refreshing will not occur on Locked ports.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to enable Auto Refresh known addresses on locked port
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetRefreshLocked
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gprtGetRefreshLocked
+*
+* DESCRIPTION:
+*		Auto Refresh known addresses when port is Locked. Already known addresses 
+*		will be auto refreshed when this feature is enabled. When this feature
+*		is disabled, auto refreshing will not occur on Locked ports.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable Auto Refresh known addresses on locked port
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetRefreshLocked
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL  	*mode
+);
+
+/*******************************************************************************
+* gprtSetPortEType
+*
+* DESCRIPTION:
+*		This routine sets the port's special Ether Type. This Ether Type is used
+*		for Policy (see gprtSetPolicy API) and FrameMode (see gprtSetFrameMode API).
+*
+* INPUTS:
+*		port  - the logical port number
+*		etype - port's special ether type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetPortEType
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_ETYPE		etype
+);
+
+/*******************************************************************************
+* gprtGetPortEType
+*
+* DESCRIPTION:
+*		This routine retrieves the port's special Ether Type. This Ether Type is used
+*		for Policy (see gprtSetPolicy API) and FrameMode (see gprtSetFrameMode API).
+*
+* INPUTS:
+*		port  - the logical port number
+*
+* OUTPUTS:
+*		etype - port's special ether type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortEType
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_ETYPE	*etype
+);
+
+
+/* gtPortRateCtr.c */
+
+/*******************************************************************************
+* grcSetFrameOverhead
+*
+* DESCRIPTION:
+*       Egress rate frame overhead adjustment.
+*		This field is used to adjust the number of bytes that need to be added to a
+*		frame's IFG on a per frame basis.
+*
+*		The egress rate limiter multiplies the value programmed in this field by four
+*		for computing the frame byte offset adjustment value (i.e., the amount the
+*		IPG is increased for every frame). This adjustment, if enabled, is made to
+*		every egressing frame's IPG and it is made in addition to any other IPG
+*		adjustments due to other Egress Rate Control settings.
+*
+*		The egress overhead adjustment can add the following number of byte times
+*		to each frame's IPG: 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
+*		56 and 60.
+*
+*		Example:
+*		If FrameOverhead = 11, the egress rate limiter would increase the IPG
+*		between every frame by an additional 44 bytes.
+*
+*		Note: When the Count Mode (port offset 0x0A) is in Frame based egress rate
+*		shaping mode, these Frame Overhead bits must be 0x0.
+*
+* INPUTS:
+*       port	 - logical port number.
+*       overhead - Frame overhead (0 ~ 15)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetFrameOverhead
+(
+    IN GT_QD_DEV		*dev,
+    IN GT_LPORT			port,
+    IN GT_32			overhead
+);
+
+/*******************************************************************************
+* grcGetFrameOverhead
+*
+* DESCRIPTION:
+*       Egress rate frame overhead adjustment.
+*		This field is used to adjust the number of bytes that need to be added to a
+*		frame's IFG on a per frame basis.
+*
+*		The egress rate limiter multiplies the value programmed in this field by four
+*		for computing the frame byte offset adjustment value (i.e., the amount the
+*		IPG is increased for every frame). This adjustment, if enabled, is made to
+*		every egressing frame's IPG and it is made in addition to any other IPG
+*		adjustments due to other Egress Rate Control settings.
+*
+*		The egress overhead adjustment can add the following number of byte times
+*		to each frame's IPG: 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
+*		56 and 60.
+*
+*		Example:
+*		If FrameOverhead = 11, the egress rate limiter would increase the IPG
+*		between every frame by an additional 44 bytes.
+*
+*		Note: When the Count Mode (port offset 0x0A) is in Frame based egress rate
+*		shaping mode, these Frame Overhead bits must be 0x0.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       overhead - Frame overhead (0 ~ 15)
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+*******************************************************************************/
+GT_STATUS grcGetFrameOverhead
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_32    *overhead
+);
+
+
+/* gtPortStatus.c */
+
+/*******************************************************************************
+* gprtGetBufHigh
+*
+* DESCRIPTION:
+*		Output from QC telling the MAC that it should perform Flow Control.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		bufHigh - GT_TRUE, if Flow control required
+*				  GT_FALSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetBufHigh
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*bufHigh
+);
+
+/*******************************************************************************
+* gprtGetFcEn
+*
+* DESCRIPTION:
+*		Input into the QC telling it that Flow Control is enabled on this port.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		fcEn - GT_TRUE, if Flow control is enabled
+*			   GT_FALSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetFcEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*fcEn
+);
+
+/*******************************************************************************
+* gprtGetRsvSize
+*
+* DESCRIPTION:
+*		This routine gets Ingress reserved queue size counter.
+*		This counter reflects the current number of reserved ingress buffers 
+*		assigned to this port.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		count - reserved ingress queue size counter value
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetRsvSize
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*count
+);
+
+
+/* gtPriTable.c */
+
+/*******************************************************************************
+* gsysSetQPriOverrideTable
+*
+* DESCRIPTION:
+*       Queue Priority Override.
+*		When a frame enters a port, its type is determined and the type is used 
+*		to access the Queue Priority Table. If the type's qPriEn (in GT_QPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Queue Priority will be overridden
+*		with the value written in qPriority (in GT_QPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*       entry - Q Priority Override Table entry (GT_QPRI_TBL_ENTRY)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetQPriOverrideTable
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_PRI_OVERRIDE_FTYPE	fType,
+    IN  GT_QPRI_TBL_ENTRY	*entry
+);
+
+/*******************************************************************************
+* gsysGetQPriOverrideTable
+*
+* DESCRIPTION:
+*       Queue Priority Override.
+*		When a frame enters a port, its type is determined and the type is used 
+*		to access the Queue Priority Table. If the type's qPriEn (in GT_QPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Queue Priority will be overridden
+*		with the value written in qPriority (in GT_QPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*
+* OUTPUTS:
+*       entry - Q Priority Override Table entry (GT_QPRI_TBL_ENTRY)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetQPriOverrideTable
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_PRI_OVERRIDE_FTYPE	fType,
+    OUT GT_QPRI_TBL_ENTRY	*entry
+);
+
+
+/* gtSysCtrl.c */
+
+/*******************************************************************************
+* gsysSetCPUDest
+*
+* DESCRIPTION:
+*		This routine sets CPU Destination Port. CPU Destination port indicates the
+*		port number on this device where the CPU is connected (either directly or
+*		indirectly through another Marvell switch device).
+*
+*		Many modes of frame processing need to know where the CPU is located.
+*		These modes are:
+*		1. When IGMP/MLD frame is received and Snooping is enabled
+*		2. When the port is configured as a DSA port and it receives a To_CPU frame
+*		3. When a Rsvd2CPU frame enters the port
+*		4. When the port's SA Filtering mode is Drop to CPU
+*		5. When any of the port's Policy Options trap the frame to the CPU
+*		6. When the ingressing frame is an ARP and ARP mirroring is enabled in the
+*		   device
+*
+*		In all cases, except for ARP, the frames that meet the enabled criteria 
+*		are mapped to the CPU Destination port, overriding where the frame would 
+*		normally go. In the case of ARP, the frame will be mapped normally and it 
+*		will also get copied to this port.
+*		Frames that filtered or discarded will not be mapped to the CPU Destination 
+*		port with the exception of the Rsvd2CPU and DSA Tag cases.
+*
+*		If CPUDest = 0xF, the remapped frames will be discarded, no ARP mirroring 
+*		will occur and ingressing To_CPU frames will be discarded.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetCPUDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+);
+
+/*******************************************************************************
+* gsysGetCPUDest
+*
+* DESCRIPTION:
+*		This routine gets CPU Destination Port. CPU Destination port indicates the
+*		port number on this device where the CPU is connected (either directly or
+*		indirectly through another Marvell switch device).
+*
+*		Many modes of frame processing need to know where the CPU is located.
+*		These modes are:
+*		1. When IGMP/MLD frame is received and Snooping is enabled
+*		2. When the port is configured as a DSA port and it receives a To_CPU frame
+*		3. When a Rsvd2CPU frame enters the port
+*		4. When the port's SA Filtering mode is Drop to CPU
+*		5. When any of the port's Policy Options trap the frame to the CPU
+*		6. When the ingressing frame is an ARP and ARP mirroring is enabled in the
+*		   device
+*
+*		In all cases, except for ARP, the frames that meet the enabled criteria 
+*		are mapped to the CPU Destination port, overriding where the frame would 
+*		normally go. In the case of ARP, the frame will be mapped normally and it 
+*		will also get copied to this port.
+*		Frames that filtered or discarded will not be mapped to the CPU Destination 
+*		port with the exception of the Rsvd2CPU and DSA Tag cases.
+*
+*		If CPUDest = 0xF, the remapped frames will be discarded, no ARP mirroring 
+*		will occur and ingressing To_CPU frames will be discarded.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetCPUDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+);
+
+/*******************************************************************************
+* gsysSetMirrorDest
+*
+* DESCRIPTION:
+*		This routine sets Mirror Destination Port. Frames that ingress a port 
+*		that trigger a policy mirror are mapped (copied) to this port as long as 
+*		the frame is not filtered or discarded. 
+*		The Mirror Destination port should point to the port that directs these 
+*		frames to the CPU that will process these frames. This target port should 
+*		be a DSA Tag port so the frames will egress with a To_CPU DSA Tag with a 
+*		CPU Code of Policy Mirror.
+*		To_CPU DSA Tag frames with a CPU Code of Policy Mirror that ingress a DSA 
+*		Tag port will be sent to the port number defined in MirrorDest.
+*
+*		If MirrorDest = 0xF, Policy Mirroring is disabled and ingressing To_CPU 
+*		Policy Mirror frames will be discarded.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetMirrorDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+);
+
+/*******************************************************************************
+* gsysGetMirrorDest
+*
+* DESCRIPTION:
+*		This routine gets Mirror Destination Port. Frames that ingress a port 
+*		that trigger a policy mirror are mapped (copied) to this port as long as 
+*		the frame is not filtered or discarded. 
+*		The Mirror Destination port should point to the port that directs these 
+*		frames to the CPU that will process these frames. This target port should 
+*		be a DSA Tag port so the frames will egress with a To_CPU DSA Tag with a 
+*		CPU Code of Policy Mirror.
+*		To_CPU DSA Tag frames with a CPU Code of Policy Mirror that ingress a DSA 
+*		Tag port will be sent to the port number defined in MirrorDest.
+*
+*		If MirrorDest = 0xF, Policy Mirroring is disabled and ingressing To_CPU 
+*		Policy Mirror frames will be discarded.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetMirrorDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+);
+
+/*******************************************************************************
+* gsysSetRMPort
+*
+* DESCRIPTION:
+*		Remote Management feature is enabled only on one port. Since not all ports
+*		can be enabled for Remote Management feature, please refer to the device
+*		datasheet for detailed information.
+*		For example, 88E6097 device allows logical port 9 or 10, and 88E6047 
+*		device allows logical port 4 and 5.
+*		
+* INPUTS:
+*		port - Remote Management Port
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM     - on unallowable port
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRMPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port
+);
+
+/*******************************************************************************
+* gsysGetRMPort
+*
+* DESCRIPTION:
+*		Remote Management feature is enabled only on one port. Since not all ports
+*		can be enabled for Remote Management feature, please refer to the device
+*		datasheet for detailed information.
+*		For example, 88E6097 device allows logical port 9 or 10, and 88E6047 
+*		device allows logical port 4 and 5.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port - Remote Management Port
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRMPort
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT 	*port
+);
+
+/*******************************************************************************
+* gsysSetRMDACheck
+*
+* DESCRIPTION:
+*		Check the DA on Remote Management frames. 
+*		When DA Check is enabled, the DA of Remote Management frames must be 
+*		contained in this device's address database (ATU) as a Static entry 
+*		(either unicast or multicast). If the DA of the frame is not contained 
+*		in this device's address database, the frame will be not be processed as 
+*		a Frame-to-Regter frame.
+*		When DA Check is disabled, the DA of Remote Management frames is not 
+*		validated before processing the frame.
+*		
+* INPUTS:
+*		en - GT_TRUE to enable DA Check, 
+*			 GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRMDACheck
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL 		en
+);
+
+/*******************************************************************************
+* gsysGetRMDACheck
+*
+* DESCRIPTION:
+*		Check the DA on Remote Management frames. 
+*		When DA Check is enabled, the DA of Remote Management frames must be 
+*		contained in this device's address database (ATU) as a Static entry 
+*		(either unicast or multicast). If the DA of the frame is not contained 
+*		in this device's address database, the frame will be not be processed as 
+*		a Frame-to-Regter frame.
+*		When DA Check is disabled, the DA of Remote Management frames is not 
+*		validated before processing the frame.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if DA Check is enabled, 
+*			 GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRMDACheck
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL 	*en
+);
+
+/*******************************************************************************
+* gsysSetRMEnable
+*
+* DESCRIPTION:
+*		Enable or disable Remote Management feature. This feature can be enabled
+*		only on one port (see gsysSetRMPort API).
+*		
+* INPUTS:
+*		en - GT_TRUE to enable Remote Management feature, 
+*			 GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRMEnable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL 		en
+);
+
+/*******************************************************************************
+* gsysGetRMEnable
+*
+* DESCRIPTION:
+*		Enable or disable Remote Management feature. This feature can be enabled
+*		only on one port (see gsysSetRMPort API).
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Remote Management feature is enabled, 
+*			 GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRMEnable
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL 	*en
+);
+
+/*******************************************************************************
+* gsysSetRsvd2CpuEnables2X
+*
+* DESCRIPTION:
+*		Reserved DA Enables for the form of 01:80:C2:00:00:2x.
+*		When the Rsvd2Cpu(gsysSetRsvd2Cpu) is set to a one, the 16 reserved 
+*		multicast DA addresses, whose bit in this register are also set to a one, 
+*		are treadted as MGMT frames. All the reserved DA's take the form 
+*		01:80:C2:00:00:2x. When x = 0x0, bit 0 of this register is tested. 
+*		When x = 0x2, bit 2 of this field is tested and so on.
+*		If the tested bit in this register is cleared to a zero, the frame will 
+*		be treated as a normal (non-MGMT) frame.
+*
+* INPUTS:
+*		enBits - bit vector of enabled Reserved Multicast.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRsvd2CpuEnables2X
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		enBits
+);
+
+/*******************************************************************************
+* gsysGetRsvd2CpuEnables2X
+*
+* DESCRIPTION:
+*		Reserved DA Enables for the form of 01:80:C2:00:00:2x.
+*		When the Rsvd2Cpu(gsysSetRsvd2Cpu) is set to a one, the 16 reserved 
+*		multicast DA addresses, whose bit in this register are also set to a one, 
+*		are treadted as MGMT frames. All the reserved DA's take the form 
+*		01:80:C2:00:00:2x. When x = 0x0, bit 0 of this register is tested. 
+*		When x = 0x2, bit 2 of this field is tested and so on.
+*		If the tested bit in this register is cleared to a zero, the frame will 
+*		be treated as a normal (non-MGMT) frame.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		enBits - bit vector of enabled Reserved Multicast.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRsvd2CpuEnables2X
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*enBits
+);
+
+/*******************************************************************************
+* gsysSetFloodBC
+*
+* DESCRIPTION:
+*		Flood Broadcast.
+*		When Flood Broadcast is enabled, frames with the Broadcast destination 
+*		address will flood out all the ports regardless of the setting of the
+*		port's Egress Floods mode (see gprtSetEgressFlood API). VLAN rules and 
+*		other switch policy still applies to these Broadcast frames. 
+*		When this feature is disabled, frames with the Broadcast destination
+*		address are considered Multicast frames and will be affected by port's 
+*		Egress Floods mode.
+*
+* INPUTS:
+*		en - GT_TRUE to enable Flood Broadcast, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetFloodBC
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetFloodBC
+*
+* DESCRIPTION:
+*		Flood Broadcast.
+*		When Flood Broadcast is enabled, frames with the Broadcast destination 
+*		address will flood out all the ports regardless of the setting of the
+*		port's Egress Floods mode (see gprtSetEgressFlood API). VLAN rules and 
+*		other switch policy still applies to these Broadcast frames. 
+*		When this feature is disabled, frames with the Broadcast destination
+*		address are considered Multicast frames and will be affected by port's 
+*		Egress Floods mode.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Flood Broadcast is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetFloodBC
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetRemove1PTag
+*
+* DESCRIPTION:
+*		Remove One Provider Tag.
+*		When this feature is enabled and a port is configured as a Provider Port
+*		(see gprtSetFrameMode API), recursive Provider Tag stripping will NOT be 
+*		performed. Only the first Provider Tag found on the frame will be 
+*		extracted and removed. Its extracted data will be used for switching.
+*		When it's disabled and a port is configured as a Provider Port, recursive 
+*		Provider Tag stripping will be performed. The first Provider Tag's data 
+*		will be extracted and used for switching, and then all subsequent Provider 
+*		Tags found in the frame will also be removed. This will only occur if the 
+*		port's PortEType (see gprtSetPortEType API) is not 0x8100.
+*
+* INPUTS:
+*		en - GT_TRUE to enable Remove One Provider Tag, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRemove1PTag
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetRemove1PTag
+*
+* DESCRIPTION:
+*		Remove One Provider Tag.
+*		When this feature is enabled and a port is configured as a Provider Port
+*		(see gprtSetFrameMode API), recursive Provider Tag stripping will NOT be 
+*		performed. Only the first Provider Tag found on the frame will be 
+*		extracted and removed. Its extracted data will be used for switching.
+*		When it's disabled and a port is configured as a Provider Port, recursive 
+*		Provider Tag stripping will be performed. The first Provider Tag's data 
+*		will be extracted and used for switching, and then all subsequent Provider 
+*		Tags found in the frame will also be removed. This will only occur if the 
+*		port's PortEType (see gprtSetPortEType API) is not 0x8100.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Remove One Provider Tag is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRemove1PTag
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL		*en
+);
+
+/*******************************************************************************
+* gsysSetTagFlowControl
+*
+* DESCRIPTION:
+*		Use and generate source port Flow Control status for Cross-Chip Flow 
+*		Control.
+*		When this feature is enabled, bit 17 of the DSA Tag Forward frames is 
+*		defined to be Src_FC and it is added to these frames when generated and 
+*		it is inspected on these frames when received. The QC will use the Src_FC 
+*		bit on DSA ports instead of the DSA port's Flow Control mode bit for the 
+*		QC Flow Control algorithm.
+*		When it is disabled, bit 17 of the DSA Tag Forward frames is defined to 
+*		be Reserved and it will be zero on these frames when generated and it 
+*		will not be used on these frames when received (this is a backwards 
+*		compatibility mode).
+*
+* INPUTS:
+*		en - GT_TRUE to enable Tag Flow Control, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetTagFlowControl
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetTagFlowControl
+*
+* DESCRIPTION:
+*		Use and generate source port Flow Control status for Cross-Chip Flow 
+*		Control.
+*		When this feature is enabled, bit 17 of the DSA Tag Forward frames is 
+*		defined to be Src_FC and it is added to these frames when generated and 
+*		it is inspected on these frames when received. The QC will use the Src_FC 
+*		bit on DSA ports instead of the DSA port's Flow Control mode bit for the 
+*		QC Flow Control algorithm.
+*		When it is disabled, bit 17 of the DSA Tag Forward frames is defined to 
+*		be Reserved and it will be zero on these frames when generated and it 
+*		will not be used on these frames when received (this is a backwards 
+*		compatibility mode).
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Tag Flow Control is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetTagFlowControl
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetAlwaysUseVTU
+*
+* DESCRIPTION:
+*		Always use VTU. 
+*		When this feature is enabled, VTU hit data will be used to map frames 
+*		even if 802.1Q is Disabled on the port. 
+*		When it's disabled, data will be ignored when mapping frames on ports 
+*		where 802.1Q is Disabled.
+*
+* INPUTS:
+*		en - GT_TRUE to use VTU always, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetAlwaysUseVTU
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetAlwaysUseVTU
+*
+* DESCRIPTION:
+*		Always use VTU. 
+*		When this feature is enabled, VTU hit data will be used to map frames 
+*		even if 802.1Q is Disabled on the port. 
+*		When it's disabled, data will be ignored when mapping frames on ports 
+*		where 802.1Q is Disabled.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if VTU is always used, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetAlwaysUseVTU
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetQVlansOnly
+*
+* DESCRIPTION:
+*		802.1Q VLANs Only.
+*		When this feature is disabled, the egress mapping of the frame is 
+*		limited by the frame's VID (using the MemberTag data found in the VTU) 
+*		together with the port based VLANs (using the source port's PortVLANTable, 
+*		gvlnSetPortVlanPorts API). The two methods are always used together in 
+*		this mode.
+*		When this feature is enabled, the egress mapping of the frame is limitied
+*		by the frame's VID only, if the VID was found in the VTU. If the frame's
+*		VID was not found in the VTU the egress mapping of the frame is limited
+*		by the source port's PortVLANTable only. The two methods are never
+*		used together in this mode.
+*
+* INPUTS:
+*		en - GT_TRUE to use 802.1Q Vlan Only feature, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetQVlansOnly
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGetQVlansOnly
+*
+* DESCRIPTION:
+*		802.1Q VLANs Only.
+*		When this feature is disabled, the egress mapping of the frame is 
+*		limited by the frame's VID (using the MemberTag data found in the VTU) 
+*		together with the port based VLANs (using the source port's PortVLANTable, 
+*		gvlnSetPortVlanPorts API). The two methods are always used together in 
+*		this mode.
+*		When this feature is enabled, the egress mapping of the frame is limitied
+*		by the frame's VID only, if the VID was found in the VTU. If the frame's
+*		VID was not found in the VTU the egress mapping of the frame is limited
+*		by the source port's PortVLANTable only. The two methods are never
+*		used together in this mode.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if 802.1Q Vlan Only feature is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetQVlansOnly
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSet5BitPort
+*
+* DESCRIPTION:
+*		Use 5 bits for Port data in the Port VLAN Table (PVT). 
+*		When this feature is enabled, the 9 bits used to access the PVT memory is:
+*			Addr[8:5] = Source Device[3:0] or Device Number[3:0]
+*			Addr[4:0] = Source Port/Trunk[4:0]
+*		When it's disabled, the 9 bits used to access the PVT memory is:
+*			Addr[8:4] = Source Device[4:0] or Device Number[4:0]
+*			Addr[3:0] = Source Port/Trunk[3:0]
+*
+* INPUTS:
+*		en - GT_TRUE to use 5 bit as a Source port in PVT, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSet5BitPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+/*******************************************************************************
+* gsysGet5BitPort
+*
+* DESCRIPTION:
+*		Use 5 bits for Port data in the Port VLAN Table (PVT). 
+*		When this feature is enabled, the 9 bits used to access the PVT memory is:
+*			Addr[8:5] = Source Device[3:0] or Device Number[3:0]
+*			Addr[4:0] = Source Port/Trunk[4:0]
+*		When it's disabled, the 9 bits used to access the PVT memory is:
+*			Addr[8:4] = Source Device[4:0] or Device Number[4:0]
+*			Addr[3:0] = Source Port/Trunk[3:0]
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if 5 bit is used as a Source Port in PVT, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGet5BitPort
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+/*******************************************************************************
+* gsysSetSDETPolarity
+*
+* DESCRIPTION:
+*		SDET (Signal Detect) Polarity select bits for each port. 
+*		Bit 10 is for Port 10, bit 9 is for Port 9, etc. SDET is used to help 
+*		determine link on fiber ports. This bit affects the active level of a 
+*		port's SDET pins as follows:
+*			0 = SDET is active low. A low level on the port's SDET pin is 
+*				required for link to occur.
+*			1 = SDET is active high. A high level on the portÂ’s SDET pin is 
+*				required for link to occur.
+*		SDET is used when the port is configured as a fiber port. In all other 
+*		port modes the SDET pins are ignored and these bits have no effect.
+*
+* INPUTS:
+*		sdetVec - SDET Polarity for each port in Vector format
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if sdetVec is invalid
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetSDETPolarity
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		sdetVec
+);
+
+/*******************************************************************************
+* gsysSetSDETPolarity
+*
+* DESCRIPTION:
+*		SDET (Signal Detect) Polarity select bits for each port. 
+*		Bit 10 is for Port 10, bit 9 is for Port 9, etc. SDET is used to help 
+*		determine link on fiber ports. This bit affects the active level of a 
+*		port's SDET pins as follows:
+*			0 = SDET is active low. A low level on the port's SDET pin is 
+*				required for link to occur.
+*			1 = SDET is active high. A high level on the portÂ’s SDET pin is 
+*				required for link to occur.
+*		SDET is used when the port is configured as a fiber port. In all other 
+*		port modes the SDET pins are ignored and these bits have no effect.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		sdetVec - SDET Polarity for each port in Vector format
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetSDETPolarity
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U32  	*sdetVec
+);
+
+
+/* gtBrgVlan.c for 2.6 release */
+
+/*******************************************************************************
+* gvlnSetNoEgrPolicy
+*
+* DESCRIPTION:
+*		No Egress Policy. When this bit is set to a one Egress 802.1Q Secure and
+*		Check discards are not performed. This mode allowsa non-802.1Q enabled 
+*		port to send a frame to an 802.1Q enabled port that is configured in the
+*		Secure or Check 802.1Q mode. In this situation the frames will egress 
+*		even if the VID assigned to the frame is not found in the VTU.
+*
+* INPUTS:
+*		mode - no egress policy mode
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gvlnSetNoEgrPolicy
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		mode
+);
+
+
+/*******************************************************************************
+* gvlnGetNoEgrPolicy
+*
+* DESCRIPTION:
+*		No Egress Policy. When this bit is set to a one Egress 802.1Q Secure and
+*		Check discards are not performed. This mode allowsa non-802.1Q enabled 
+*		port to send a frame to an 802.1Q enabled port that is configured in the
+*		Secure or Check 802.1Q mode. In this situation the frames will egress 
+*		even if the VID assigned to the frame is not found in the VTU.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - no egress policy mode
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gvlnGetNoEgrPolicy
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL		*mode
+);
+
+/*******************************************************************************
+* gwdSetRMUTimeOut
+*
+* DESCRIPTION:
+*		Remote Management Timeout. When this bit is set to a one the Remote
+*		Management Unit(RMU) will timeout on Wait on Bit commands. If the bit that
+*		is being tested has not gone to the specified value after 1 sec. has elapsed
+*		the Wait on Bit command will be terminated and the Response frame will be
+*		sent without any further processing.
+*
+*		When this bit is cleared to a zero the Wait on Bit command will wait 
+*		until the bit that is being tested has changed to the specified value.
+*
+* INPUTS:
+*		en   - GT_TRUE to enable RMU Timeout
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdSetRMUTimeOut
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL	    en
+);
+
+/*******************************************************************************
+* gwdGetRMUTimeOut
+*
+* DESCRIPTION:
+*		Remote Management Timeout. When this bit is set to a one the Remote
+*		Management Unit(RMU) will timeout on Wait on Bit commands. If the bit that
+*		is being tested has not gone to the specified value after 1 sec. has elapsed
+*		the Wait on Bit command will be terminated and the Response frame will be
+*		sent without any further processing.
+*
+*		When this bit is cleared to a zero the Wait on Bit command will wait 
+*		until the bit that is being tested has changed to the specified value.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en   - GT_TRUE to enable RMU Timeout
+*			   GT_FALUSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdGetRMUTimeOut
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL	    *en
+);
+
+/*******************************************************************************
+* gwdGetEgressWDEvent
+*
+* DESCRIPTION:
+*		If any port's egress logic detects an egress watch dog issue, this bit
+*		will be set to a one, regardless of the setting of the GT_WD_EGRESS in
+*		gwdSetEvent function.
+*		
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		event - GT_TRUE, if egress logic has detected any egress watch dog issue
+*			    GT_FALUSE, otherwise
+*
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdGetEgressWDEvent
+(
+	IN  GT_QD_DEV		*dev,
+	OUT GT_BOOL			*event
+);
+
+
+/*******************************************************************************
+* gsysSetQoSWeight
+*
+* DESCRIPTION:
+*       Programmable Round Robin Weights.
+*		Each port has 4 output Queues. Queue 3 has the highest priority and 
+*		Queue 0 has the lowest priority. When a scheduling mode of port is 
+*		configured as Weighted Round Robin queuing mode, the access sequece of the 
+*		Queue is 3,2,3,1,3,2,3,0,3,2,3,1,3,2,3 by default.
+*		This sequence can be configured with this API.
+*
+* INPUTS:
+*       weight - access sequence of the queue
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetQoSWeight
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_QoS_WEIGHT	*weight
+);
+
+/*******************************************************************************
+* gsysGetQoSWeight
+*
+* DESCRIPTION:
+*       Programmable Round Robin Weights.
+*		Each port has 4 output Queues. Queue 3 has the highest priority and 
+*		Queue 0 has the lowest priority. When a scheduling mode of port is 
+*		configured as Weighted Round Robin queuing mode, the access sequece of the 
+*		Queue is 3,2,3,1,3,2,3,0,3,2,3,1,3,2,3 by default.
+*		This routine retrieves the access sequence of the Queue.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       weight - access sequence of the queue
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetQoSWeight
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT GT_QoS_WEIGHT	*weight
+);
+
+
+/*
+ *	gtPortCtrl.c
+*/
+
+/*******************************************************************************
+* gsysSetJumboMode
+*
+* DESCRIPTION:
+*       This routine Set the max frame size allowed to be received and transmitted
+*		from or to a given port.
+*
+* INPUTS:
+*		port - the logical port number
+*       mode - GT_JUMBO_MODE (1522, 2048, or 10240)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gsysSetJumboMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_JUMBO_MODE   mode
+);
+
+/*******************************************************************************
+* gsysGetJumboMode
+*
+* DESCRIPTION:
+*       This routine gets the max frame size allowed to be received and transmitted
+*		from or to a given port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_JUMBO_MODE (1522, 2048, or 10240)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gsysGetJumboMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_JUMBO_MODE   *mode
+);
+
+/*
+ *  gtPhyCtrl.c
+*/
+/*******************************************************************************
+* gprtGetEnergyDetect
+*
+* DESCRIPTION:
+*       Energy Detect power down mode enables or disables the PHY to wake up on
+*		its own by detecting activity on the CAT 5 cable. 
+*
+* INPUTS:
+* 		port - The logical port number
+*
+* OUTPUTS:
+*       mode - GT_EDETECT_MODE type
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetEnergyDetect
+(
+	IN  GT_QD_DEV *dev,
+	IN  GT_LPORT  port,
+	OUT GT_EDETECT_MODE   *mode
+);
+
+/*******************************************************************************
+* gprtSetEnergyDetect
+*
+* DESCRIPTION:
+*       Energy Detect power down mode enables or disables the PHY to wake up on
+*		its own by detecting activity on the CAT 5 cable. 
+*
+* INPUTS:
+* 		port - The logical port number
+*       mode - GT_EDETECT_MODE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetEnergyDetect
+(
+	IN  GT_QD_DEV *dev,
+	IN  GT_LPORT  port,
+	IN  GT_EDETECT_MODE   mode
+);
+
+
+/*
+ *	gtSysCtrl.c
+*/
+
+/*******************************************************************************
+* gsysSetRMUMode
+*
+* DESCRIPTION:
+*		Set Rmote Management Unit Mode: disable, enable on port 4 or 5, or enable
+*		on port 9 or 10. Devices, such as 88E6097, support RMU on port 9 and 10, 
+*		while other devices, such as 88E6165, support RMU on port 4 and 5. So,
+*		please refer to the device datasheet for detail.
+*		When RMU is enabled and this device receives a Remote Management Request
+*		frame directed to this device, the frame will be processed and a Remote 
+*		Management Response frame will be generated and sent out.
+*		
+*		Note: enabling RMU has no effect if the Remote Management port is in half
+*		duplex mode. The port's FrameMode must be DSA or EtherType DSA as well.
+*		
+* INPUTS:
+*		rmu - GT_RMU structure
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM     - on bad parameter
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRMUMode
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_RMU		*rmu
+);
+
+/*******************************************************************************
+* gsysGetRMUMode
+*
+* DESCRIPTION:
+*		Get Rmote Management Unit Mode: disable, enable on port 4 or 5, or enable
+*		on port 9 or 10. Devices, such as 88E6097, support RMU on port 9 and 10, 
+*		while other devices, such as 88E6165, support RMU on port 4 and 5. So,
+*		please refer to the device datasheet for detail.
+*		When RMU is enabled and this device receives a Remote Management Request
+*		frame directed to this device, the frame will be processed and a Remote 
+*		Management Response frame will be generated and sent out.
+*		
+*		Note: enabling RMU has no effect if the Remote Management port is in half
+*		duplex mode. The port's FrameMode must be DSA or EtherType DSA as well.
+*		
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		rmu - GT_RMU structure
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRMUMode
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_RMU		*rmu
+);
+
+/*******************************************************************************
+* gsysPort2Lport
+*
+* DESCRIPTION:
+*		This routine converts physical port number to logical port number.
+*
+* INPUTS:
+*		port - physical port number
+*
+* OUTPUTS:
+*		lport - logical port number
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysPort2Lport
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32 		port,
+	OUT GT_LPORT	*lport
+);
+
+/*******************************************************************************
+* gsysLport2Port
+*
+* DESCRIPTION:
+*		This routine converts logical port number to physical port number.
+*
+* INPUTS:
+*		lport - logical port number
+*
+* OUTPUTS:
+*		port - physical port number
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysLport2Port
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	lport,
+	OUT GT_U32 		*port
+);
+
+/*******************************************************************************
+* gsysPortvec2Lportvec
+*
+* DESCRIPTION:
+*		This routine converts physical port vector to logical port vector.
+*
+* INPUTS:
+*		portvec - physical port vector
+*
+* OUTPUTS:
+*		lportvec - logical port vector
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysPortvec2Lportvec
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32		portvec,
+	OUT GT_U32 		*lportvec
+);
+
+/*******************************************************************************
+* gsysLportvec2Portvec
+*
+* DESCRIPTION:
+*		This routine converts logical port vector to physical port vector.
+*
+* INPUTS:
+*		lportvec - logical port vector
+*
+* OUTPUTS:
+*		portvec - physical port vector
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysLportvec2Portvec
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32		lportvec,
+	OUT GT_U32 		*portvec
+);
+
+
+/*
+ * gtPIRL.c
+ */
+
+/*******************************************************************************
+* gpirlSetCurTimeUpInt
+*
+* DESCRIPTION:
+*       This function sets the current time update interval.
+*		Please contact FAE for detailed information.
+*
+* INPUTS:
+*       upInt - updata interval (0 ~ 7)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gpirlSetCurTimeUpInt
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				upInt
+);
+
+
+/*
+ * gtPIRL2.c
+ */
+
+/*******************************************************************************
+* gpirl2SetCurTimeUpInt
+*
+* DESCRIPTION:
+*       This function sets the current time update interval.
+*		Please contact FAE for detailed information.
+*
+* INPUTS:
+*       upInt - updata interval (0 ~ 7)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gpirl2SetCurTimeUpInt
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				upInt
+);
+
+
+/*
+ * gtPTP.c
+ */
+
+/*******************************************************************************
+* gptpSetConfig
+*
+* DESCRIPTION:
+*       This routine writes PTP configuration parameters.
+*
+* INPUTS:
+*		ptpData  - PTP configuration parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_CONFIG	*ptpData
+);
+
+/*******************************************************************************
+* gptpGetConfig
+*
+* DESCRIPTION:
+*       This routine reads PTP configuration parameters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpData  - PTP configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_CONFIG	*ptpData
+);
+
+/*******************************************************************************
+* gptpSetGlobalConfig
+*
+* DESCRIPTION:
+*       This routine writes PTP global configuration parameters.
+*
+* INPUTS:
+*		ptpData  - PTP global configuration parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetGlobalConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_GLOBAL_CONFIG	*ptpData
+);
+
+/*******************************************************************************
+* gptpGetGlobalConfig
+*
+* DESCRIPTION:
+*       This routine reads PTP global configuration parameters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpData  - PTP global configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetGlobalConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_GLOBAL_CONFIG	*ptpData
+);
+
+/*******************************************************************************
+* gptpSetPortConfig
+*
+* DESCRIPTION:
+*       This routine writes PTP port configuration parameters.
+*
+* INPUTS:
+*		ptpData  - PTP port configuration parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetPortConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_PTP_PORT_CONFIG	*ptpData
+);
+
+/*******************************************************************************
+* gptpGetPortConfig
+*
+* DESCRIPTION:
+*       This routine reads PTP configuration parameters for a port.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpData  - PTP port configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPortConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_PTP_PORT_CONFIG	*ptpData
+);
+
+/*******************************************************************************
+* gptpSetPTPEn
+*
+* DESCRIPTION:
+*       This routine enables or disables PTP.
+*
+* INPUTS:
+*		en - GT_TRUE to enable PTP, GT_FALSE to disable PTP
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetPTPEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en
+);
+
+/*******************************************************************************
+* gptpGetPTPEn
+*
+* DESCRIPTION:
+*       This routine checks if PTP is enabled.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPTPEn
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en
+);
+
+/*******************************************************************************
+* gptpSetPortPTPEn
+*
+* DESCRIPTION:
+*       This routine enables or disables PTP on a port.
+*
+* INPUTS:
+*		en - GT_TRUE to enable PTP, GT_FALSE to disable PTP
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetPortPTPEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+);
+
+/*******************************************************************************
+* gptpGetPortPTPEn
+*
+* DESCRIPTION:
+*       This routine checks if PTP is enabled on a port.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPortPTPEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+);
+
+
+/*******************************************************************************
+* gptpGetPTPInt
+*
+* DESCRIPTION:
+*       This routine gets PTP interrupt status for each port.
+*		The PTP Interrupt bit gets set for a given port when an incoming PTP 
+*		frame is time stamped and PTPArrIntEn for that port is set to 0x1.
+*		Similary PTP Interrupt bit gets set for a given port when an outgoing
+*		PTP frame is time stamped and PTPDepIntEn for that port is set to 0x1.
+*		This bit gets cleared upon software reading and clearing the corresponding
+*		time counter valid bits that are valid for that port.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpInt 	- interrupt status for each port (bit 0 for port 0, bit 1 for port 1, etc.)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPTPInt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*ptpInt
+);
+
+/*******************************************************************************
+* gptpGetPTPGlobalTime
+*
+* DESCRIPTION:
+*       This routine gets the global timer value that is running off of the free
+*		running switch core clock.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpTime	- PTP global time
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPTPGlobalTime
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*ptpTime
+);
+
+/*******************************************************************************
+* gptpGetTimeStamped
+*
+* DESCRIPTION:
+*		This routine retrieves the PTP port status that includes time stamp value 
+*		and sequce Id that are captured by PTP logic for a PTP frame that needs 
+*		to be time stamped.
+*
+* INPUTS:
+*       port 		- logical port number.
+*       timeToRead	- Arr0, Arr1, or Dep time (GT_PTP_TIME enum type)
+*
+* OUTPUTS:
+*		ptpStatus	- PTP port status
+*
+* RETURNS:
+*       GT_OK 		- on success
+*       GT_FAIL 	- on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetTimeStamped
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN	GT_PTP_TIME	timeToRead,
+	OUT GT_PTP_TS_STATUS	*ptpStatus
+);
+
+/*******************************************************************************
+* gptpResetTimeStamp
+*
+* DESCRIPTION:
+*		This routine resets PTP Time valid bit so that PTP logic can time stamp
+*		a next PTP frame that needs to be time stamped.
+*
+* INPUTS:
+*       port 		- logical port number.
+*       timeToReset	- Arr0, Arr1, or Dep time (GT_PTP_TIME enum type)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK 		- on success
+*       GT_FAIL 	- on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpResetTimeStamp
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN	GT_PTP_TIME	timeToReset
+);
+
+/*******************************************************************************
+* gptpGetReg
+*
+* DESCRIPTION:
+*       This routine reads PTP register.
+*
+* INPUTS:
+*       port 		- logical port number.
+*       regOffset	- register to read
+*
+* OUTPUTS:
+*		data		- register data
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetReg
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		regOffset,
+	OUT GT_U32		*data
+);
+
+/*******************************************************************************
+* gptpSetReg
+*
+* DESCRIPTION:
+*       This routine writes data to PTP register.
+*
+* INPUTS:
+*       port 		- logical port number
+*       regOffset	- register to be written
+*		data		- data to be written
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetReg
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		regOffset,
+	IN  GT_U32		data
+);
+
+
+#ifdef CONFIG_AVB_FPGA
+
+/*******************************************************************************
+* gptpSetFPGAIntStatus
+*
+* DESCRIPTION:
+*       This routine sets interrupt status of PTP logic.
+*
+* INPUTS:
+*		intStatus	- PTP Int Status
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetFPGAIntStatus
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32	intStatus
+);
+
+
+/*******************************************************************************
+* gptpGetFPGAIntStatus
+*
+* DESCRIPTION:
+*       This routine gets interrupt status of PTP logic.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		intStatus	- PTP Int Status
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetFPGAIntStatus
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32	*intStatus
+);
+
+
+/*******************************************************************************
+* gptpSetFPGAIntEn
+*
+* DESCRIPTION:
+*       This routine enables PTP interrupt.
+*
+* INPUTS:
+*		intEn	- enable/disable PTP interrupt (1 to enable, 0 to disable)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetFPGAIntEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32	intEn
+);
+
+/*******************************************************************************
+* gptpGetClockSource
+*
+* DESCRIPTION:
+*       This routine gets PTP Clock source mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		clkSrc	- PTP clock source (A/D Device or FPGA)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetClockSource
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_CLOCK_SRC 	*clkSrc
+);
+
+/*******************************************************************************
+* gptpSetClockSource
+*
+* DESCRIPTION:
+*       This routine sets PTP Clock source mode.
+*
+* INPUTS:
+*		clkSrc	- PTP clock source (A/D Device or FPGA)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetClockSource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_CLOCK_SRC 	clkSrc
+);
+
+/*******************************************************************************
+* gptpGetP9Mode
+*
+* DESCRIPTION:
+*       This routine gets Port 9 Mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		mode - Port 9 mode (GT_PTP_P9_MODE enum type)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetP9Mode
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_P9_MODE 	*mode
+);
+
+/*******************************************************************************
+* gptpSetP9Mode
+*
+* DESCRIPTION:
+*       This routine sets Port 9 Mode.
+*
+* INPUTS:
+*		mode - Port 9 mode (GT_PTP_P9_MODE enum type)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetP9Mode
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_P9_MODE 	mode
+);
+
+/*******************************************************************************
+* gptpReset
+*
+* DESCRIPTION:
+*       This routine performs software reset for PTP logic.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpReset
+(
+	IN  GT_QD_DEV 	*dev
+);
+
+
+/*******************************************************************************
+* gptpGetCycleAdjustEn
+*
+* DESCRIPTION:
+*       This routine checks if PTP Duty Cycle Adjustment is enabled.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		adjEn	- GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetCycleAdjustEn
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*adjEn
+);
+
+
+/*******************************************************************************
+* gptpSetCycleAdjustEn
+*
+* DESCRIPTION:
+*       This routine enables/disables PTP Duty Cycle Adjustment.
+*
+* INPUTS:
+*		adjEn	- GT_TRUE to enable, GT_FALSE to disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetCycleAdjustEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		adjEn
+);
+
+
+/*******************************************************************************
+* gptpGetCycleAdjust
+*
+* DESCRIPTION:
+*       This routine gets clock duty cycle adjustment value.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		adj	- adjustment value (GT_PTP_CLOCK_ADJUSTMENT structure)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetCycleAdjust
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_CLOCK_ADJUSTMENT		*adj
+);
+
+/*******************************************************************************
+* gptpSetCycleAdjust
+*
+* DESCRIPTION:
+*       This routine sets clock duty cycle adjustment value.
+*
+* INPUTS:
+*		adj	- adjustment value (GT_PTP_CLOCK_ADJUSTMENT structure)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetCycleAdjust
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_CLOCK_ADJUSTMENT		*adj
+);
+
+/*******************************************************************************
+* gptpGetPLLEn
+*
+* DESCRIPTION:
+*       This routine checks if PLL is enabled.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*		freqSel	- PLL Frequency Selection (default 0x3 - 22.368MHz)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       PLL Frequence selection is based on the Clock Recovery PLL device.
+*		IDT MK1575-01 is the default PLL device.
+*
+*******************************************************************************/
+GT_STATUS gptpGetPLLEn
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en,
+	OUT GT_U32		*freqSel
+);
+
+/*******************************************************************************
+* gptpSetPLLEn
+*
+* DESCRIPTION:
+*       This routine enables/disables PLL device.
+*
+* INPUTS:
+*		en		- GT_TRUE to enable, GT_FALSE to disable
+*		freqSel	- PLL Frequency Selection (default 0x3 - 22.368MHz)
+*				  Meaningful only when enabling PLL device
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       PLL Frequence selection is based on the Clock Recovery PLL device.
+*		IDT MK1575-01 is the default PLL device.
+*
+*******************************************************************************/
+GT_STATUS gptpSetPLLEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en,
+	IN  GT_U32		freqSel
+);
+#endif
+
+/* Amber APIs */
+
+/* gtBrgFdb.c */
+
+/*******************************************************************************
+* gfdbGetMacAvb
+*
+* DESCRIPTION:
+*		ATU MAC entry in AVB mode.
+*		When enabled, ATU entries operate in AVB mode:
+*
+*		GT_ATU_UC_STATE - support
+*			GT_UC_NO_PRI_STATIC_AVB_ENTRY, and 
+*			GT_UC_STATIC_AVB_ENTRY
+*
+*		GT_ATU_MC_STATE - support
+*			GT_MC_STATIC_AVB_ENTRY, and
+*			GT_MC_PRIO_STATIC_AVB_ENTRY
+*
+*		When disabled, ATU entries operate in non-AVB mode:
+*
+*		GT_ATU_UC_STATE - support
+*			GT_UC_NO_PRI_STATIC_NRL, and 
+*			GT_UC_STATIC_NRL
+*
+*		GT_ATU_MC_STATE - support
+*			GT_MC_STATIC_UNLIMITED_RATE, and
+*			GT_MC_PRIO_STATIC_UNLIMITED_RATE
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if MacAvb is enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*
+*******************************************************************************/
+GT_STATUS gfdbGetMacAvb
+(
+	IN  GT_QD_DEV    *dev,
+	OUT GT_BOOL 	*mode
+);
+
+/*******************************************************************************
+* gfdbSetMacAvb
+*
+* DESCRIPTION:
+*		ATU MAC entry in AVB mode.
+*		When enabled, ATU entries operate in AVB mode:
+*
+*		GT_ATU_UC_STATE - support
+*			GT_UC_NO_PRI_STATIC_AVB_ENTRY, and 
+*			GT_UC_STATIC_AVB_ENTRY
+*
+*		GT_ATU_MC_STATE - support
+*			GT_MC_STATIC_AVB_ENTRY, and
+*			GT_MC_PRIO_STATIC_AVB_ENTRY
+*
+*		When disabled, ATU entries operate in non-AVB mode:
+*
+*		GT_ATU_UC_STATE - support
+*			GT_UC_NO_PRI_STATIC_NRL, and 
+*			GT_UC_STATIC_NRL
+*
+*		GT_ATU_MC_STATE - support
+*			GT_MC_STATIC_UNLIMITED_RATE, and
+*			GT_MC_PRIO_STATIC_UNLIMITED_RATE
+*
+* INPUTS:
+*		mode - GT_TRUE to enable MacAvb, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gfdbSetMacAvb
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		mode
+);
+
+/*******************************************************************************
+* gfdbGetPortAtuLearnLimit
+*
+* DESCRIPTION:
+*      Port's auto learning limit. When the limit is non-zero value, the number
+*		of MAC addresses that can be learned on this port are limited to the value
+*		specified in this API. When the learn limit has been reached any frame 
+*		that ingresses this port with a source MAC address not already in the 
+*		address database that is associated with this port will be discarded. 
+*		Normal auto-learning will resume on the port as soon as the number of 
+*		active unicast MAC addresses associated to this port is less than the 
+*		learn limit.
+*		CPU directed ATU Load, Purge, or Move will not have any effect on the 
+*		learn limit.
+*		This feature is disabled when the limit is zero.
+*		The following care is needed when enabling this feature:
+*			1) dsable learning on the ports
+*			2) flush all non-static addresses in the ATU
+*			3) define the desired limit for the ports
+*			4) re-enable learing on the ports
+*
+* INPUTS:
+*		port  - logical port number
+*											  
+* OUTPUTS:
+*		limit - auto learning limit ( 0 ~ 255 )
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if limit > 0xFF
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gfdbGetPortAtuLearnLimit
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT  	port,
+	OUT GT_U32   	*limit
+);
+
+/* gtPCSCtrl.c */
+
+/*******************************************************************************
+* gpcsGetRGMIITimingDelay
+*
+* DESCRIPTION:
+*		RGMII receive/transmit Timing Control. This api adds delay to RXCLK for
+*		IND inputs and GTXCLK for OUTD outputs when port is in RGMII mode.
+*		Change to this bit are disruptive to normal operation. Hence any changes
+*		to this register must be done only while the port's link is down.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		rxmode - GT_FALSE for default setup, GT_TRUE for adding delay to rxclk
+*		txmode - GT_FALSE for default setup, GT_TRUE for adding delay to txclk
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetRGMIITimingDelay
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*rxmode,
+	OUT GT_BOOL  	*txmode
+);
+
+/*******************************************************************************
+* gpcsSetRGMIITimingDelay
+*
+* DESCRIPTION:
+*		RGMII receive/transmit Timing Control. This api adds delay to RXCLK for
+*		IND inputs and GTXCLK for OUTD outputs when port is in RGMII mode.
+*		Change to this bit are disruptive to normal operation. Hence any changes
+*		to this register must be done only while the port's link is down.
+*
+* INPUTS:
+*		port - the logical port number.
+*		rxmode - GT_FALSE for default setup, GT_TRUE for adding delay to rxclk
+*		txmode - GT_FALSE for default setup, GT_TRUE for adding delay to txclk
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetRGMIITimingDelay
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_BOOL  	rxmode,
+	IN  GT_BOOL  	txmode
+);
+
+
+/* gtPortLed.c */
+
+/*******************************************************************************
+* gprtSetLED
+*
+* DESCRIPTION:
+*		This API allows to configure 4 LED sections, Pulse stretch, Blink rate,
+*		and special controls.
+*
+* INPUTS:
+*		port	- the logical port number
+*		cfg 	- GT_LED_CFG value
+*		value 	- value to be configured
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gprtSetLED
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_LED_CFG	cfg,
+	IN  GT_U32		value
+);
+
+
+/*******************************************************************************
+* gprtGetLED
+*
+* DESCRIPTION:
+*		This API allows to retrieve 4 LED sections, Pulse stretch, Blink rate,
+*		and special controls.
+*
+* INPUTS:
+*		port	- the logical port number
+*		cfg 	- GT_LED_CFG value
+*
+* OUTPUTS:
+*		value 	- configured value
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gprtGetLED
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_LED_CFG	cfg,
+	OUT GT_U32		*value
+);
+
+
+
+
+
+/* gtPortStatus.c */
+
+/*******************************************************************************
+* gprtGetQSizePerQPri
+*
+* DESCRIPTION:
+*		This routine gets egress queue size for port's each QPri (0 ~ 3).
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		counts - egress queue size per QPri (should be 4 * 16bytes)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetQSizePerQPri
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*counts
+);
+
+
+/* gtSysCtrl.c */
+
+
+/*******************************************************************************
+* gsysGetARPwoBC
+*
+* DESCRIPTION:
+*       ARP detection without Broadcast checking. When enabled the switch core
+*       does not check for a Btoadcast MAC address as part of the ARP frame
+*       detection. It only checkes the Ether Type (0x0806).
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE if enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetARPwoBC
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		*en
+);
+
+/*******************************************************************************
+* gsysSetARPwoBC
+*
+* DESCRIPTION:
+*       ARP detection without Broadcast checking. When enabled the switch core
+*       does not check for a Btoadcast MAC address as part of the ARP frame
+*       detection. It only checkes the Ether Type (0x0806).
+*
+* INPUTS:
+*       en - GT_TRUE to enable, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetARPwoBC
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL 	en
+);
+
+
+/*******************************************************************************
+* gsysGetCLK125En
+*
+* DESCRIPTION:
+*		Clock 125MHz Enable.
+*		When this feature is enabled, the CLK125 pin has a free running 125 MHz
+*		clock output.
+*		When it's disabled, the CLK125 pin will be in tri-state.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if 125MHz clock is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetCLK125En
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+);
+
+
+/*******************************************************************************
+* gsysSetCLK125En
+*
+* DESCRIPTION:
+*		Clock 125MHz Enable.
+*		When this feature is enabled, the CLK125 pin has a free running 125 MHz
+*		clock output.
+*		When it's disabled, the CLK125 pin will be in tri-state.
+*
+* INPUTS:
+*		en - GT_TRUE to enable 125 MHz clock, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetCLK125En
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+);
+
+
+/* gtPriTable.c */
+
+/*******************************************************************************
+* gsysSetFPriOverrideTable
+*
+* DESCRIPTION:
+* 		Frame Priority Override.
+*		When a frame enters a port, its type is determined and the type is used 
+*		to access the Frame Priority Table. If the type's fPriEn (in GT_FPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Frame Priority will be overridden
+*		with the value written in fPriority (in GT_FPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*       entry - Frame Priority Override Table entry (GT_FPRI_TBL_ENTRY)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetFPriOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	IN  GT_FPRI_TBL_ENTRY	*entry
+);
+
+
+/*******************************************************************************
+* gsysGetFPriOverrideTable
+*
+* DESCRIPTION:
+* 		Frame Priority Override.
+*		When a frame enters a port, its type is determined and the type is used 
+*		to access the Frame Priority Table. If the type's fPriEn (in GT_FPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Frame Priority will be overridden
+*		with the value written in fPriority (in GT_FPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*
+* OUTPUTS:
+*       entry - Frame Priority Override Table entry (GT_FPRI_TBL_ENTRY)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM     - on unknown frame type
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetFPriOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	OUT GT_FPRI_TBL_ENTRY	*entry
+);
+
+
+/*******************************************************************************
+* gsysSetQPriAvbOverrideTable
+*
+* DESCRIPTION:
+* 		Queue Priority Override for AVB enabled ports or AvbOverride enabled ports.
+*		When a frame enters a AVB port, its type is determined and the type is used 
+*		to access the Queue Priority Table. If the type's qPriEn (in GT_QPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Queue Priority will be overridden
+*		with the value written in qPriority (in GT_QPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*       entry - Q Priority Override Table entry (GT_QPRI_TBL_ENTRY)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetQPriAvbOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	IN  GT_QPRI_TBL_ENTRY	*entry
+);
+
+
+/*******************************************************************************
+* gsysGetQPriAvbOverrideTable
+*
+* DESCRIPTION:
+* 		Queue Priority Override for AVB enabled ports or AvbOverride enabled ports.
+*		When a frame enters a AVB port, its type is determined and the type is used 
+*		to access the Queue Priority Table. If the type's qPriEn (in GT_QPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Queue Priority will be overridden
+*		with the value written in qPriority (in GT_QPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*
+* OUTPUTS:
+*       entry - Q Priority Override Table entry (GT_QPRI_TBL_ENTRY)
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetQPriAvbOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	OUT GT_QPRI_TBL_ENTRY	*entry
+);
+
+
+/* gtPortCtrl.c */
+
+/*******************************************************************************
+* gprtGet200Base
+*
+* DESCRIPTION:
+*		200 Base mode. This bit can be used to change the port's Px_GTXCLK
+*		frequency to 50MHz to support 200 BASE mode as follows:
+*		0 = 25MHz Px_GTXCLK
+*		1 = 50MHz Px_GTXCLK
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - 0 for 100Mbps, 1 for 200Mbps
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		C_Mode should be set to 0x2 in order for this API to work
+*
+*******************************************************************************/
+GT_STATUS gprtGet200Base
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_U32  	*mode
+);
+
+
+/*******************************************************************************
+* gprtSet200Base
+*
+* DESCRIPTION:
+*		200 Base mode. This bit can be used to change the port's Px_GTXCLK
+*		frequency to 50MHz to support 200 BASE mode as follows:
+*			0 = 25MHz Px_GTXCLK
+*			1 = 50MHz Px_GTXCLK
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - 0 for 100Mbps, 1 for 200Mbps
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		C_Mode should be set to 0x2 in order for this API to work
+*
+*******************************************************************************/
+GT_STATUS gprtSet200Base
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_U32  	mode
+);
+
+
+/* gtPIRL2.c */
+
+/*******************************************************************************
+* gpirl2WriteTSMResource
+*
+* DESCRIPTION:
+*		This routine writes rate resource bucket parameters in Time Slot Metering
+*		mode to the given resource of the port.
+*
+* INPUTS:
+*		port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 1).
+*		pirlData - PIRL TSM resource parameters.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Only Resource 0 and 1 can be supported for TSM Mode.
+*
+*******************************************************************************/
+GT_STATUS gpirl2WriteTSMResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes,
+	IN  GT_PIRL2_TSM_DATA	*pirlData
+);
+
+
+/*******************************************************************************
+* gpirl2ReadTSMResource
+*
+* DESCRIPTION:
+*		This routine retrieves IRL Parameter.
+*		Returned ingressRate would be rough number. Instead, customSetup will
+*		have the exact configured value.
+*
+* INPUTS:
+*		port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 1).
+*
+* OUTPUTS:
+*		pirlData - PIRL resource parameters.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Only Resource 0 and 1 can be supported for TSM Mode.
+*
+*******************************************************************************/
+GT_STATUS gpirl2ReadTSMResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes,
+	OUT GT_PIRL2_TSM_DATA	*pirlData
+);
+
+
+/* gtPTP.c */
+
+/*******************************************************************************
+* gtaiSetEventConfig
+*
+* DESCRIPTION:
+*       This routine sets TAI Event Capture configuration parameters.
+*
+* INPUTS:
+*		eventData  - TAI Event Capture configuration parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetEventConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_TAI_EVENT_CONFIG	*eventData
+);
+
+
+/*******************************************************************************
+* gtaiGetEventConfig
+*
+* DESCRIPTION:
+*       This routine gets TAI Event Capture configuration parameters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		eventData  - TAI Event Capture configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetEventConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_TAI_EVENT_CONFIG	*eventData
+);
+
+/*******************************************************************************
+* gtaiGetEventStatus
+*
+* DESCRIPTION:
+*       This routine gets TAI Event Capture status.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		eventData  - TAI Event Capture configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetEventStatus
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_TAI_EVENT_STATUS	*status
+);
+
+/*******************************************************************************
+* gtaiGetEventInt
+*
+* DESCRIPTION:
+*       This routine gets TAI Event Capture Interrupt status.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		intStatus 	- interrupt status for TAI Event capture
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetEventInt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*intStatus
+);
+
+
+/*******************************************************************************
+* gtaiGetTrigInt
+*
+* DESCRIPTION:
+*       This routine gets TAI Trigger Interrupt status.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		intStatus 	- interrupt status for TAI Trigger
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetTrigInt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*intStatus
+);
+
+/*******************************************************************************
+* gtaiSetTrigConfig
+*
+* DESCRIPTION:
+*       This routine sets TAI Trigger configuration parameters.
+*
+* INPUTS:
+*		trigEn    - enable/disable TAI Trigger.
+*		trigData  - TAI Trigger configuration parameters (valid only if trigEn is GT_TRUE).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetTrigConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL 	trigEn,
+	IN  GT_TAI_TRIGGER_CONFIG	*trigData
+);
+
+/*******************************************************************************
+* gtaiGetTrigConfig
+*
+* DESCRIPTION:
+*       This routine gets TAI Trigger configuration parameters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		trigEn    - enable/disable TAI Trigger.
+*		trigData  - TAI Trigger configuration parameters (valid only if trigEn is GT_TRUE).
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetTrigConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL 	*trigEn,
+	OUT GT_TAI_TRIGGER_CONFIG	*trigData
+);
+
+/*******************************************************************************
+* gtaiGetTSClkPer
+*
+* DESCRIPTION:
+* 		Time Stamping Clock Period in pico seconds.
+*		This routine specifies the clock period for the time stamping clock supplied 
+*		to the PTP hardware logic.
+*		This is the clock that is used by the hardware logic to update the PTP 
+*		Global Time Counter.
+*
+* INPUTS:
+* 		None.
+*
+* OUTPUTS:
+*		clk		- time stamping clock period
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetTSClkPer
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*clk
+);
+
+
+/*******************************************************************************
+* gtaiSetTSClkPer
+*
+* DESCRIPTION:
+* 		Time Stamping Clock Period in pico seconds.
+*		This routine specifies the clock period for the time stamping clock supplied 
+*		to the PTP hardware logic.
+*		This is the clock that is used by the hardware logic to update the PTP 
+*		Global Time Counter.
+*
+* INPUTS:
+*		clk		- time stamping clock period
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetTSClkPer
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		clk
+);
+
+/*******************************************************************************
+* gtaiSetMultiPTPSync
+*
+* DESCRIPTION:
+* 		This routine sets Multiple PTP device sync mode and sync time (TrigGenAmt).
+*		When enabled, the hardware logic detects a low to high transition on the 
+*		EventRequest(GPIO) and transfers the sync time into the PTP Global Time
+*		register. The EventCapTime is also updated at that instant.
+*
+* INPUTS:
+*		multiEn		- enable/disable Multiple PTP device sync mode
+*		syncTime	- sync time (valid only if multiEn is GT_TRUE)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		When enabled, gtaiSetTrigConfig, gtaiSetEventConfig, gtaiSetTimeInc,
+*		and gtaiSetTimeDec APIs are not operational.
+*
+*******************************************************************************/
+GT_STATUS gtaiSetMultiPTPSync
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL 	multiEn,
+	IN  GT_32		syncTime
+);
+
+/*******************************************************************************
+* gtaiGetMultiPTPSync
+*
+* DESCRIPTION:
+* 		This routine gets Multiple PTP device sync mode and sync time (TrigGenAmt).
+*		When enabled, the hardware logic detects a low to high transition on the 
+*		EventRequest(GPIO) and transfers the sync time into the PTP Global Time
+*		register. The EventCapTime is also updated at that instant.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		multiEn		- enable/disable Multiple PTP device sync mode
+*		syncTime	- sync time (valid only if multiEn is GT_TRUE)
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		When enabled, gtaiSetTrigConfig, gtaiSetEventConfig, gtaiSetTimeInc,
+*		and gtaiSetTimeDec APIs are not operational.
+*
+*******************************************************************************/
+GT_STATUS gtaiGetMultiPTPSync
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL 	*multiEn,
+	OUT GT_32		*syncTime
+);
+
+/*******************************************************************************
+* gtaiGetTimeIncDec
+*
+* DESCRIPTION:
+* 		This routine retrieves Time increment/decrement setup.
+*		This amount specifies the number of units of PTP Global Time that need to be 
+*		incremented or decremented. This is used for adjusting the PTP Global Time 
+*		counter value by a certain amount.
+*
+* INPUTS:
+* 		None.
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*		inc		- GT_TRUE if increment, GT_FALSE if decrement
+*		amount	- increment/decrement amount
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetTimeIncDec
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en,
+	OUT GT_BOOL		*inc,
+	OUT GT_U32		*amount
+);
+
+/*******************************************************************************
+* gtaiSetTimeInc
+*
+* DESCRIPTION:
+* 		This routine enables time increment by the specifed time increment amount.
+*		The amount specifies the number of units of PTP Global Time that need to be 
+*		incremented. This is used for adjusting the PTP Global Time counter value by
+*		a certain amount.
+*		Increment occurs just once.
+*
+* INPUTS:
+*		amount	- time increment amount (0 ~ 0xFF)
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetTimeInc
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		amount
+);
+
+/*******************************************************************************
+* gtaiSetTimeDec
+*
+* DESCRIPTION:
+* 		This routine enables time decrement by the specifed time decrement amount.
+*		The amount specifies the number of units of PTP Global Time that need to be 
+*		decremented. This is used for adjusting the PTP Global Time counter value by
+*		a certain amount.
+*		Decrement occurs just once.
+*
+* INPUTS:
+*		amount	- time decrement amount (0 ~ 0x7FF)
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetTimeDec
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		amount
+);
+
+
+/*******************************************************************************
+* gavbGetPriority
+*
+* DESCRIPTION:
+*		Priority overwrite.
+*		Supported priority type is defined as GT_AVB_PRI_TYPE.
+*		Priority is either 3 bits or 2 bits depending on priority type.
+*			GT_AVB_HI_FPRI		- priority is 0 ~ 7
+*			GT_AVB_HI_QPRI		- priority is 0 ~ 3
+*			GT_AVB_LO_FPRI		- priority is 0 ~ 7
+*			GT_AVB_LO_QPRI		- priority is 0 ~ 3
+*			GT_LEGACY_HI_FPRI	- priority is 0 ~ 7
+*			GT_LEGACY_HI_QPRI	- priority is 0 ~ 3
+*			GT_LEGACY_LO_FPRI	- priority is 0 ~ 7
+*			GT_LEGACY_LO_QPRI	- priority is 0 ~ 3
+*
+* INPUTS:
+* 		priType	- GT_AVB_PRI_TYPE
+*
+* OUTPUTS:
+*		pri	- priority
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetPriority
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_AVB_PRI_TYPE		priType,
+	OUT GT_U32		*pri
+);
+
+/*******************************************************************************
+* gavbSetPriority
+*
+* DESCRIPTION:
+*		Priority overwrite.
+*		Supported priority type is defined as GT_AVB_PRI_TYPE.
+*		Priority is either 3 bits or 2 bits depending on priority type.
+*			GT_AVB_HI_FPRI		- priority is 0 ~ 7
+*			GT_AVB_HI_QPRI		- priority is 0 ~ 3
+*			GT_AVB_LO_FPRI		- priority is 0 ~ 7
+*			GT_AVB_LO_QPRI		- priority is 0 ~ 3
+*			GT_LEGACY_HI_FPRI	- priority is 0 ~ 7
+*			GT_LEGACY_HI_QPRI	- priority is 0 ~ 3
+*			GT_LEGACY_LO_FPRI	- priority is 0 ~ 7
+*			GT_LEGACY_LO_QPRI	- priority is 0 ~ 3
+*
+* INPUTS:
+* 		priType	- GT_AVB_PRI_TYPE
+*		pri	- priority
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetPriority
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_AVB_PRI_TYPE		priType,
+	IN  GT_U32		pri
+);
+
+/*******************************************************************************
+* gavbGetAVBHiLimit
+*
+* DESCRIPTION:
+*		AVB Hi Frame Limit.
+*		When these bits are zero, normal frame processing occurs. 
+*		When it's non-zero, they are used to define the maximum frame size allowed
+*		for AVB frames that can be placed into the GT_AVB_HI_QPRI queue. Frames
+*		that are over this size limit are filtered. The only exception to this 
+*		is non-AVB frames that get their QPriAvb assigned by the Priority Override 
+*		Table
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		limit	- Hi Frame Limit
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAVBHiLimit
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*limit
+);
+
+/*******************************************************************************
+* gavbSetAVBHiLimit
+*
+* DESCRIPTION:
+*		AVB Hi Frame Limit.
+*		When these bits are zero, normal frame processing occurs. 
+*		When it's non-zero, they are used to define the maximum frame size allowed
+*		for AVB frames that can be placed into the GT_AVB_HI_QPRI queue. Frames
+*		that are over this size limit are filtered. The only exception to this 
+*		is non-AVB frames that get their QPriAvb assigned by the Priority Override 
+*		Table
+*
+* INPUTS:
+*		limit	- Hi Frame Limit
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAVBHiLimit
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		limit
+);
+
+/*******************************************************************************
+* gavbGetPtpExtClk
+*
+* DESCRIPTION:
+*		PTP external clock select.
+*		When this bit is cleared to a zero, the PTP core gets its clock from 
+*		an internal 125MHz clock based on the device's XTAL_IN input. 
+*		When this bit is set to a one, the PTP core gets its clock from the device's
+*		PTP_EXTCLK pin.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		extClk	- GT_TRUE if external clock is selected, GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetPtpExtClk
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*extClk
+);
+
+/*******************************************************************************
+* gavbSetPtpExtClk
+*
+* DESCRIPTION:
+*		PTP external clock select.
+*		When this bit is cleared to a zero, the PTP core gets its clock from 
+*		an internal 125MHz clock based on the device's XTAL_IN input. 
+*		When this bit is set to a one, the PTP core gets its clock from the device's
+*		PTP_EXTCLK pin.
+*
+* INPUTS:
+*		extClk	- GT_TRUE if external clock is selected, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetPtpExtClk
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		extClk
+);
+
+/*******************************************************************************
+* gavbGetRecClkSel
+*
+* DESCRIPTION:
+*		Synchronous Ethernet Recovered Clock Select.
+*		This field indicate the internal PHY number whose recovered clock will
+*		be presented on the SE_RCLK0 or SE_RCLK1 pin depending on the recClk selection.
+*
+* INPUTS:
+*		recClk	- GT_AVB_RECOVERED_CLOCK type
+*
+* OUTPUTS:
+*		clkSel	- recovered clock selection
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetRecClkSel
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_AVB_RECOVERED_CLOCK	recClk,
+	OUT GT_U32		*clkSel
+);
+
+
+/*******************************************************************************
+* gavbSetRecClkSel
+*
+* DESCRIPTION:
+*		Synchronous Ethernet Recovered Clock Select.
+*		This field indicate the internal PHY number whose recovered clock will
+*		be presented on the SE_RCLK0 or SE_RCLK1 pin depending on the recClk selection.
+*
+* INPUTS:
+*		recClk	- GT_AVB_RECOVERED_CLOCK type
+*		clkSel	- recovered clock selection (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetRecClkSel
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_AVB_RECOVERED_CLOCK	recClk,
+	IN  GT_U32		clkSel
+);
+
+/*******************************************************************************
+* gavbGetAvbOuiBytes
+*
+* DESCRIPTION:
+*		AVB OUI Limit Filter bytes(0 ~ 2).
+*		When all three of the AvbOui Bytes are zero, normal frame processing occurs.
+*		When any of the three AvbOui Bytes are non-zero, all AVB frames must have a
+*		destination address whose 1st three bytes of the DA match these three 
+*		AvbOui Bytes or the frame will be filtered.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		ouiBytes	- 3 bytes of OUI field in Ethernet address format
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbOuiBytes
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*obiBytes
+);
+
+/*******************************************************************************
+* gavbSetAvbOuiBytes
+*
+* DESCRIPTION:
+*		AVB OUI Limit Filter bytes(0 ~ 2).
+*		When all three of the AvbOui Bytes are zero, normal frame processing occurs.
+*		When any of the three AvbOui Bytes are non-zero, all AVB frames must have a
+*		destination address whose 1st three bytes of the DA match these three 
+*		AvbOui Bytes or the frame will be filtered.
+*
+* INPUTS:
+*		ouiBytes	- 3 bytes of OUI field in Ethernet address format
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbOuiBytes
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U8		*obiBytes
+);
+
+/*******************************************************************************
+* gavbGetAvbMode
+*
+* DESCRIPTION:
+*		Port's AVB Mode.
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		mode	- GT_AVB_MODE type
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbMode
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_AVB_MODE	*mode
+);
+
+/*******************************************************************************
+* gavbSetAvbMode
+*
+* DESCRIPTION:
+*		Port's AVB Mode.
+*
+* INPUTS:
+*		port	- the logical port number
+*		mode	- GT_AVB_MODE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbMode
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_AVB_MODE	mode
+);
+
+/*******************************************************************************
+* gavbGetAvbOverride
+*
+* DESCRIPTION:
+*		AVB Override.
+*		When disabled, normal frame processing occurs.
+*		When enabled, the egress portion of this port is considered AVB even if 
+*		the ingress portion is not.
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbOverride
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+);
+
+/*******************************************************************************
+* gavbSetAvbOverride
+*
+* DESCRIPTION:
+*		AVB Override.
+*		When disabled, normal frame processing occurs.
+*		When enabled, the egress portion of this port is considered AVB even if 
+*		the ingress portion is not.
+*
+* INPUTS:
+*		port	- the logical port number
+*		en		- GT_TRUE to enable, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbOverride
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+);
+
+
+/*******************************************************************************
+* gavbGetFilterBadAvb
+*
+* DESCRIPTION:
+*		Filter Bad AVB frames.
+*		When disabled, normal frame processing occurs.
+*		When enabled, frames that are considered Bad AVB frames are filtered.
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetFilterBadAvb
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+);
+
+/*******************************************************************************
+* gavbSetFilterBadAvb
+*
+* DESCRIPTION:
+*		Filter Bad AVB frames.
+*		When disabled, normal frame processing occurs.
+*		When enabled, frames that are considered Bad AVB frames are filtered.
+*
+* INPUTS:
+*		port	- the logical port number
+*		en		- GT_TRUE to enable, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetFilterBadAvb
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+);
+
+
+/*******************************************************************************
+* gavbGetAvbTunnel
+*
+* DESCRIPTION:
+*		AVB Tunnel.
+*		When disabled, normal frame processing occurs.
+*		When enabled, the port based VLAN Table masking, 802.1Q VLAN membership 
+*		masking and the Trunk Masking is bypassed for any frame entering this port
+*		that is considered AVB by DA. This includes unicast as well as multicast
+*		frame
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbTunnel
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+);
+
+
+/*******************************************************************************
+* gavbSetAvbTunnel
+*
+* DESCRIPTION:
+*		AVB Tunnel.
+*		When disabled, normal frame processing occurs.
+*		When enabled, the port based VLAN Table masking, 802.1Q VLAN membership 
+*		masking and the Trunk Masking is bypassed for any frame entering this port
+*		that is considered AVB by DA. This includes unicast as well as multicast
+*		frame
+*
+* INPUTS:
+*		port	- the logical port number
+*		en		- GT_TRUE to enable, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbTunnel
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+);
+
+
+/*******************************************************************************
+* gavbGetAvbFramePolicy
+*
+* DESCRIPTION:
+*		AVB Hi or Lo frame policy mapping.
+*		Supported policies are defined in GT_AVB_FRAME_POLICY.
+*			
+* INPUTS:
+*		port	- the logical port number
+*		fType	- GT_AVB_FRAME_TYPE 
+*
+* OUTPUTS:
+*		policy	- GT_AVB_FRAME_POLICY
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbFramePolicy
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN	GT_AVB_FRAME_TYPE	fType,
+	OUT GT_AVB_FRAME_POLICY		*policy
+);
+
+
+/*******************************************************************************
+* gavbSetAvbFramePolicy
+*
+* DESCRIPTION:
+*		AVB Hi or Lo frame policy mapping.
+*		Supported policies are defined in GT_AVB_FRAME_POLICY.
+*
+* INPUTS:
+*		port	- the logical port number
+*		fType	- GT_AVB_FRAME_TYPE 
+*		policy	- GT_AVB_FRAME_POLICY
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbFramePolicy
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN	GT_AVB_FRAME_TYPE	fType,
+	IN  GT_AVB_FRAME_POLICY		policy
+);
+
+/* Amber QAV API */
+/*******************************************************************************/
+/* Amber QAV API */
+/*******************************************************************************
+* gqavSetPortQpriXQTSToken
+*
+* DESCRIPTION:
+*		This routine set Priority Queue 0-3 time slot tokens on a port.
+*		The setting value is number of tokens that need to be subtracted at each 
+*		QTS interval boundary.
+*
+* INPUTS:
+*		port	- the logical port number
+*		queue	 - 0 - 3
+*		qtsToken - number of tokens.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gqavSetPortQpriXQTSToken
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_U8		queue,
+	IN  GT_U16		qtsToken
+);
+
+/*******************************************************************************
+* gqavGetPortQpriXQTSToken
+*
+* DESCRIPTION:
+*		This routine get Priority Queue 0-3 time slot tokens on a port.
+*		The setting value is number of tokens that need to be subtracted at each 
+*		QTS interval boundary.
+*
+* INPUTS:
+*		port	- the logical port number
+*		queue - 0 - 3
+*
+* OUTPUTS:
+*		qtsToken - number of tokens
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gqavGetPortQpriXQTSToken
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_U8		queue,
+	OUT GT_U16		*qtsToken
+);
+
+/*******************************************************************************
+* gqavSetPortQpriXBurstBytes
+*
+* DESCRIPTION:
+*		This routine set Priority Queue 0-3 Burst Bytes on a port.
+*		This value specifies the number of credits in bytes that can be 
+*		accumulated when the queue is blocked from sending out a frame due to 
+*		higher priority queue frames being sent out.
+*
+* INPUTS:
+*		port	- the logical port number
+*		queue - 0 - 3
+*		burst - number of credits in bytes .
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetPortQpriXBurstBytes
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_U8		queue,
+	IN  GT_U16		burst
+);
+
+/*******************************************************************************
+* gqavGetPortQpriXBurstBytes
+*
+* DESCRIPTION:
+*		This routine get Priority Queue 0-3 Burst Bytes on a port.
+*		This value specifies the number of credits in bytes that can be 
+*		accumulated when the queue is blocked from sending out a frame due to 
+*		higher priority queue frames being sent out.
+*
+* INPUTS:
+*		port	- the logical port number
+*		queue	- 0 - 3
+*
+* OUTPUTS:
+*		burst - number of credits in bytes .
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetPortQpriXBurstBytes
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_U8		queue,
+	OUT GT_U16		*burst
+);
+
+/*******************************************************************************
+* gqavSetPortQavEnable
+*
+* DESCRIPTION:
+*		This routine set QAV enable status on a port.
+*
+* INPUTS:
+*		port	- the logical port number
+*		en		- GT_TRUE: QAV enable, GT_FALSE: QAV disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetPortQavEnable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+);
+
+/*******************************************************************************
+* gqavGetPortQavEnable
+*
+* DESCRIPTION:
+*		This routine get QAV enable status on a port.
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		en		- GT_TRUE: QAV enable, GT_FALSE: QAV disable
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetPortQavEnable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+);
+
+/*******************************************************************************/
+/* QAV Global registers processing */
+/*******************************************************************************
+* gqavSetGlobalAdminMGMT
+*
+* DESCRIPTION:
+*		This routine set to accept Admit Management Frames always.
+*
+* INPUTS:
+*		en - GT_TRUE to set MGMT frame accepted always, 
+*			 GT_FALSE do not set MGMT frame accepted always
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalAdminMGMT
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en
+);
+
+/*******************************************************************************
+* gqavGetGlobalAdminMGMT
+*
+* DESCRIPTION:
+*		This routine get setting of Admit Management Frames always.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to set MGMT frame accepted always, 
+*			 GT_FALSE do not set MGMT frame accepted always
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalAdminMGMT
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en
+);
+
+/*******************************************************************************
+* gqavSetGlobalIsoPtrThreshold
+*
+* DESCRIPTION:
+*		This routine set Global Isochronous Queue Pointer Threshold.
+*		This field indicates the total number of isochronous pointers 
+*		that are reserved for isochronous streams. The value is expected to be 
+*		computed in SRP software and programmed into hardware based on the total 
+*		aggregate isochronous streams configured to go through this device..
+*
+* INPUTS:
+*		isoPtrs -  total number of isochronous pointers 
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoPtrThreshold
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U16		isoPtrs
+);
+
+/*******************************************************************************
+* gqavGetGlobalIsoPtrThreshold
+*
+* DESCRIPTION:
+*		This routine get Global Isochronous Queue Pointer Threshold.
+*		This field indicates the total number of isochronous pointers 
+*		that are reserved for isochronous streams. The value is expected to be 
+*		computed in SRP software and programmed into hardware based on the total 
+*		aggregate isochronous streams configured to go through this device..
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		isoPtrs -  total number of isochronous pointers 
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoPtrThreshold
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U16		*isoPtrs
+);
+
+/*******************************************************************************
+* gqavSetGlobalDisQSD4MGMT
+*
+* DESCRIPTION:
+*		This routine set Disable Queue Scheduler Delays for Management frames..
+*
+* INPUTS:
+*		en - GT_TRUE, it indicates to the Queue Controller to disable applying Queue
+*			Scheduler Delays and the corresponding rate regulator does not account
+*			for MGMT frames through this queue.
+*			GT_FALSE, the MGMT frames follow similar rate regulation and delay
+*			regulation envelope as specified for the isochronous queue that the
+*			MGMT frames are sharing with.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalDisQSD4MGMT
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en
+);
+
+/*******************************************************************************
+* gqavGetGlobalDisQSD4MGMT
+*
+* DESCRIPTION:
+*		This routine Get Disable Queue Scheduler Delays for Management frames..
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE, it indicates to the Queue Controller to disable applying Queue
+*			Scheduler Delays and the corresponding rate regulator does not account
+*			for MGMT frames through this queue.
+*			GT_FALSE, the MGMT frames follow similar rate regulation and delay
+*			regulation envelope as specified for the isochronous queue that the
+*			MGMT frames are sharing with.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalDisQSD4MGMT
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en
+);
+
+/*******************************************************************************
+* gqavSetGlobalInterrupt
+*
+* DESCRIPTION:
+*		This routine set QAV interrupt enable, 
+*		The QAV interrypts include:
+*		[GT_QAV_INT_ENABLE_ENQ_LMT_BIT]      # EnQ Limit Interrupt Enable 
+*		[GT_QAV_INT_ENABLE_ISO_DEL_BIT]      # Iso Delay Interrupt Enable   
+*		[GT_QAV_INT_ENABLE_ISO_DIS_BIT]      # Iso Discard Interrupt Enable 
+*		[GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT] # Iso Packet Memory Exceeded 
+*											  Interrupt Enable 
+*
+* INPUTS:
+*		intEn - [GT_QAV_INT_ENABLE_ENQ_LMT_BIT] OR  
+*				[GT_QAV_INT_ENABLE_ISO_DEL_BIT] OR    
+*				[GT_QAV_INT_ENABLE_ISO_DIS_BIT] OR  
+*				[GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT]   
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalInterrupt
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U16		intEn
+);
+
+/*******************************************************************************
+* gqavGetGlobalInterrupt
+*
+* DESCRIPTION:
+*       This routine get QAV interrupt status and enable status, 
+*		The QAV interrypt status include:
+*		 [GT_QAV_INT_STATUS_ENQ_LMT_BIT]      # Enqueue Delay Limit exceeded  
+*		 [GT_QAV_INT_STATUS_ISO_DEL_BIT]      # Iso Delay Interrupt Status   
+*		 [GT_QAV_INT_STATUS_ISO_DIS_BIT]      # Iso Discard Interrupt Status 
+*		 [GT_QAV_INT_STATUS_ISO_LIMIT_EX_BIT] # Iso Packet Memory Exceeded 
+*											    Interrupt Status 
+*		The QAV interrypt enable status include:
+*		 [GT_QAV_INT_ENABLE_ENQ_LMT_BIT]      # EnQ Limit Interrupt Enable 
+*		 [GT_QAV_INT_ENABLE_ISO_DEL_BIT]      # Iso Delay Interrupt Enable   
+*		 [GT_QAV_INT_ENABLE_ISO_DIS_BIT]      # Iso Discard Interrupt Enable 
+*		 [GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT] # Iso Packet Memory Exceeded 
+*												  Interrupt Enable 
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		intEnSt - [GT_QAV_INT_STATUS_ENQ_LMT_BIT] OR     
+*				[GT_QAV_INT_STATUS_ISO_DEL_BIT] OR   
+*				[GT_QAV_INT_STATUS_ISO_DIS_BIT] OR   
+*				[GT_QAV_INT_STATUS_ISO_LIMIT_EX_BIT] OR
+*				[GT_QAV_INT_ENABLE_ENQ_LMT_BIT] OR  
+*				[GT_QAV_INT_ENABLE_ISO_DEL_BIT] OR    
+*				[GT_QAV_INT_ENABLE_ISO_DIS_BIT] OR  
+*				[GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT]   
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalInterrupt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U16		*intEnSt
+);
+
+/*******************************************************************************
+* gqavGetGlobalIsoInterruptPort
+*
+* DESCRIPTION:
+*		This routine get Isochronous interrupt port.
+*		This field indicates the port number for IsoDisInt or IsoLimitExInt 
+*		bits. Only one such interrupt condition can be detected by hardware at one 
+*		time. Once an interrupt bit has been set along with the IsoIntPort, the 
+*		software would have to come and clear the bits before hardware records 
+*		another interrupt event.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port - port number for IsoDisInt or IsoLimitExInt bits.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoInterruptPort
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*port
+);
+
+/*******************************************************************************
+* gqavSetGlobalIsoDelayLmt
+*
+* DESCRIPTION:
+*		This routine set Isochronous queue delay Limit
+*		This field represents a per-port isochronous delay limit that 
+*		will be checked by the queue controller logic to ensure no isochronous 
+*		packets suffer more than this delay w.r.t to their eligibility time slot.
+*		This represents the number of Queue Time Slots. The interval for the QTS 
+*		can be configured using the register in Qav Global Configuration, Offset 0x2.
+*
+* INPUTS:
+*		limit - per-port isochronous delay limit.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoDelayLmt
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U8		limit
+);
+
+/*******************************************************************************
+* gqavGetGlobalIsoDelayLmt
+*
+* DESCRIPTION:
+*		This routine get Isochronous queue delay Limit
+*		This field represents a per-port isochronous delay limit that 
+*		will be checked by the queue controller logic to ensure no isochronous 
+*		packets suffer more than this delay w.r.t to their eligibility time slot.
+*		This represents the number of Queue Time Slots. The interval for the QTS 
+*		can be configured using the register in Qav Global Configuration, Offset 0x2.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		limit - per-port isochronous delay limit.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoDelayLmt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*limit
+);
+
+/*******************************************************************************
+* gqavSetGlobalIsoMonEn
+*
+* DESCRIPTION:
+*       This routine set Isochronous monitor enable
+*		Set GT_TRUE: this bit enables the statistics gathering capabilities stated
+*		in PTP Global Status Registers Offset 0xD, 0xE and 0xF. Once enabled, the
+*		software is expected to program the IsoMonPort (PTP Global Status Offset
+*		0xD) indicating which port of the device does the software wants to monitor.
+*		Upon setting this bit, the hardware collects IsoHiDisCtr, IsoLoDisCtr and
+*		IsoSchMissCtr values for the port indicated by IsoMonPort till this bit is 
+*		set to a zero.
+*		Set GT_FALSE: this bit disables the statistics gathering capabilities.
+*
+* INPUTS:
+*		en - GT_TRUE / GT_FALSE.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoMonEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en
+);
+
+/*******************************************************************************
+* gqavGetGlobalIsoMonEn
+*
+* DESCRIPTION:
+*		This routine get Isochronous monitor enable
+*		Set GT_TRUE: this bit enables the statistics gathering capabilities stated
+*		in PTP Global Status Registers Offset 0xD, 0xE and 0xF. Once enabled, the
+*		software is expected to program the IsoMonPort (PTP Global Status Offset
+*		0xD) indicating which port of the device does the software wants to monitor.
+*		Upon setting this bit, the hardware collects IsoHiDisCtr, IsoLoDisCtr and
+*		IsoSchMissCtr values for the port indicated by IsoMonPort till this bit is 
+*		set to a zero.
+*		Set GT_FALSE: this bit disables the statistics gathering capabilities.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE / GT_FALSE.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoMonEn
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en
+);
+
+/*******************************************************************************
+* gqavSetGlobalIsoMonPort
+*
+* DESCRIPTION:
+*		This routine set Isochronous monitoring port.
+*		This field is updated by software along with Iso Mon En bit 
+*		(Qav Global Status, offset 0xD) and it indicates the port number that 
+*		the software wants the hardware to start monitoring i.e., start updating 
+*		IsoHiDisCtr, IsoLoDisCtr and IsoSchMissCtr. The queue controller clears 
+*		the above stats when IsoMonPort is changed..
+*
+* INPUTS:
+*		port -  port number .
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoMonPort
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U16		port
+);
+
+/*******************************************************************************
+* gqavGetGlobalIsoMonPort
+*
+* DESCRIPTION:
+*		This routine get Isochronous monitoring port.
+*		This field is updated by software along with Iso Mon En bit 
+*		(Qav Global Status, offset 0xD) and it indicates the port number that 
+*		the software wants the hardware to start monitoring i.e., start updating 
+*		IsoHiDisCtr, IsoLoDisCtr and IsoSchMissCtr. The queue controller clears 
+*		the above stats when IsoMonPort is changed..
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port -  port number.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoMonPort
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U16		*port
+);
+
+/*******************************************************************************
+* gqavSetGlobalIsoHiDisCtr
+*
+* DESCRIPTION:
+*		This routine set Isochronous hi queue discard counter.
+*		This field is updated by hardware when instructed to do so by 
+*		enabling the IsoMonEn bit in Qav Global Status Register Offset 0xD. 
+*		This is an upcounter of number of isochronous hi packets discarded 
+*		by Queue Controller.
+*
+* INPUTS:
+*		disCtr - upcounter of number of isochronous hi packets discarded 
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoHiDisCtr
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U8		disCtr
+);
+
+/*******************************************************************************
+* gqavGetGlobalIsoHiDisCtr
+*
+* DESCRIPTION:
+*		This routine get Isochronous hi queue discard counter.
+*		This field is updated by hardware when instructed to do so by 
+*		enabling the IsoMonEn bit in Qav Global Status Register Offset 0xD. 
+*		This is an upcounter of number of isochronous hi packets discarded 
+*		by Queue Controller.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		disCtr - upcounter of number of isochronous hi packets discarded 
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoHiDisCtr
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*disCtr
+);
+
+/*******************************************************************************
+* gqavSetGlobalIsoLoDisCtr
+*
+* DESCRIPTION:
+*		This routine set Isochronous Lo queue discard counter.
+*		This field is updated by hardware when instructed to do so by 
+*		enabling the IsoMonEn bit in Qav Global Status Register Offset 0xD. 
+*		This is an upcounter of number of isochronous lo packets discarded 
+*		by Queue Controller.
+*
+* INPUTS:
+*		disCtr - upcounter of number of isochronous lo packets discarded 
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoLoDisCtr
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U8		disCtr
+);
+
+/*******************************************************************************
+* gqavGetGlobalIsoLoDisCtr
+*
+* DESCRIPTION:
+*		This routine set Isochronous Lo queue discard counter.
+*		This field is updated by hardware when instructed to do so by 
+*		enabling the IsoMonEn bit in Qav Global Status Register Offset 0xD. 
+*		This is an upcounter of number of isochronous lo packets discarded 
+*		by Queue Controller.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		disCtr - upcounter of number of isochronous lo packets discarded 
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoLoDisCtr
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*disCtr
+);
+
+/*******************************************************************************
+* gsysSetUseIpMappingTable
+*
+* DESCRIPTION:
+*		This API set to use IP Frame Priorities from this table. 
+*		Set GT_TRUE:  The IP_FPRI data in this table is used as the frameÂ’s 
+*			initial IP_FPRI use Ip Mappingg table priorities.
+*		Set GT_FALSE: The IP_FPRI data in this table is ignored. Instead the 
+*			frameÂ’s initial IP_FPRI is generated by using the frameÂ’s IP_QPRI
+*			as the IP_FPRIÂ’s upper two bits, and the IP_FPRIÂ’s lowest bit comes 
+*			from bit 0 of the frameÂ’s source portÂ’s Default PRI (Port offset 0x07).
+*
+* INPUTS:
+*		en	- [GT_TRUE] / [GT_FALSE]
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetUseIpMappingTable
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_BOOL			en
+);
+
+/*******************************************************************************
+* gsysGetUseIpMappingTable
+*
+* DESCRIPTION:
+*		This API get to use IP Frame Priorities from this table. 
+*		Set GT_TRUE:  The IP_FPRI data in this table is used as the frameÂ’s 
+*			initial IP_FPRI use Ip Mappingg table priorities.
+*		Set GT_FALSE: The IP_FPRI data in this table is ignored. Instead the 
+*			frameÂ’s initial IP_FPRI is generated by using the frameÂ’s IP_QPRI
+*			as the IP_FPRIÂ’s upper two bits, and the IP_FPRIÂ’s lowest bit comes 
+*			from bit 0 of the frameÂ’s source portÂ’s Default PRI (Port offset 0x07).
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en	- [GT_TRUE] / [GT_FALSE]
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetUseIpMappingTable
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_BOOL			*en
+);
+
+/*******************************************************************************
+* gsysSetIpMappingPrio
+*
+* DESCRIPTION:
+*		Set IPv4 and IPv6 Frame Priority Mapping, and 
+*		IPv4 and IPv6 Queue Priority Mapping.
+*       The ipFpri value is used as the frames initial FPRI when the frame is 
+*		an IPv4 or an IPv6 frame, and the portÂ’s InitialPri (Port offset 0x04) 
+*		is configured to use IP FPriÂ’s.
+*       The ipQpri value is used as the frameÂ’s initial QPRI when the frame is 
+*		an IPv4 or an IPv6 frame, and the portÂ’s InitialPri and TagIfBoth 
+*		registers (Port offset 0x04) are configured to use IP QPriÂ’s.
+*
+* INPUTS:
+*		point - Pointer to the Ip Mapping Table.
+*				0 - 0x3f;
+*		ipFpri -  The value is 0 - 7
+*		ipQpri -  The value is 0 - 3.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetIpMappingPrio
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			point,
+    IN  GT_U8			ipFpri,
+    IN  GT_U8			ipQpri
+);
+
+/*******************************************************************************
+* gsysGetIpMappingPrio
+*
+* DESCRIPTION:
+*		Get IPv4 and IPv6 Frame Priority Mapping, and 
+*		IPv4 and IPv6 Queue Priority Mapping.
+*       The ipFpri value is used as the frames initial FPRI when the frame is 
+*		an IPv4 or an IPv6 frame, and the portÂ’s InitialPri (Port offset 0x04) 
+*		is configured to use IP FPriÂ’s.
+*		The ipQpri value is used as the frameÂ’s initial QPRI when the frame is 
+*		an IPv4 or an IPv6 frame, and the portÂ’s InitialPri and TagIfBoth 
+*		registers (Port offset 0x04) are configured to use IP QPriÂ’s.
+*
+* INPUTS:
+*		point - Pointer to the Ip Mapping Table.
+*				0 - 0x3f;
+*
+* OUTPUTS:
+*		ipFpri -  The value is 0 - 7
+*		ipQpri -  The value is 0 - 3.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetIpMappingPrio
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			point,
+    OUT  GT_U8			*ipFpri,
+    OUT  GT_U8			*ipQpri
+);
+
+/*******************************************************************************
+* gsysReadEeprom
+*
+* DESCRIPTION:
+*		Read EEPROM from EEPROMÂ’s address where the EEOp is performed.
+*
+* INPUTS:
+*		addr - EEPROM Address. 
+*
+* OUTPUTS:
+*		data -  Data that was read back from the EEPROM.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysReadEeprom
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			addr,
+    OUT  GT_U8			*data
+);
+
+/*******************************************************************************
+* gsysWriteEeprom
+*
+* DESCRIPTION:
+*		Write EEPROM at the EEPROMÂ’s address where the EEOp is performed.
+*
+* INPUTS:
+*		addr - EEPROM Address. 
+*		data - Data to be written to the EEPROM
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysWriteEeprom
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			addr,
+    IN  GT_U8			data
+);
+
+/*******************************************************************************
+* gsysRestartEeprom
+*
+* DESCRIPTION:
+*		Restart Register Loader execution at the EEPROMÂ’s address where the EEOp 
+*		is performed
+*
+* INPUTS:
+*		addr - EEPROM Address. .
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysRestartEeprom
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			addr
+);
+
+/*******************************************************************************
+* gsysHaltEeprom
+*
+* DESCRIPTION:
+*		Halt (stop executing the EEPROM if its not already stopped)
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysHaltEeprom
+(
+    IN  GT_QD_DEV 		*dev
+);
+
+/*******************************************************************************
+* gsysGetStEeprom
+*
+* DESCRIPTION:
+*		Get EEPROM status. They are Register Loader Running status and EEPROM 
+*		Write Enable status
+*		runSt is GT_TRUE: Register Loader Running, whenever the register loader 
+*			is busy executing the instructions contained in the EEPROM.
+*		writeEn is GT_TRUE: EEPROM Write Enable, that indicates that writing to 
+*			the EEPROM is possible. 
+*		writeEn is GT_FALSE: the Write EEPROM EEOp above will not do anything.
+*			This reflects the value of the EE_WE configuration pin after Reset.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		runSt   -   [GT_TRUE] / [GT_FALSE)
+*		writeEn -   [GT_TRUE] / [GT_FALSE)
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetStEeprom
+(
+    IN  GT_QD_DEV 		*dev,
+	OUT GT_BOOL			*writeEn,
+	OUT GT_BOOL			*runSt
+);
+
+/*******************************************************************************
+* gsysSetScratchMiscCtrl
+*
+* DESCRIPTION:
+*		Set Scratch and Misc control data to the Scratch and Misc Control register. 
+*		The register of Scratch and Misc control are.
+*				Scratch Byte 0
+*				Scratch Byte 1
+*				GPIO Configuration
+*				Reserved for future use
+*				GPIO Direction
+*				GPIO Data
+*				CONFIG Data 0
+*				CONFIG Data 1
+*				CONFIG Data 2
+*				CONFIG Data 3
+*				SyncE & TAICLK125Â’s Drive
+*				P5Â’s & CLK125Â’s Clock Drive
+*				P6Â’s Clock Drive
+*				EEPROM Pad drive
+*
+* INPUTS:
+*		point - Pointer to the Scratch and Misc. Control register.
+*		data  - Scratch and Misc. Control data written to the register 
+*				pointed to by the point above.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetScratchMiscCtrl
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			point,
+    IN  GT_U8			data
+);
+
+/*******************************************************************************
+* gsysGetScratchMiscCtrl
+*
+* DESCRIPTION:
+*		Get Scratch and Misc control data from the Scratch and Misc Control register. 
+*		The register of Scratch and Misc control are.
+*				Scratch Byte 0
+*				Scratch Byte 1
+*				GPIO Configuration
+*				Reserved for future use
+*				GPIO Direction
+*				GPIO Data
+*				CONFIG Data 0
+*				CONFIG Data 1
+*				CONFIG Data 2
+*				CONFIG Data 3
+*				SyncE & TAICLK125Â’s Drive
+*				P5Â’s & CLK125Â’s Clock Drive
+*				P6Â’s Clock Drive
+*				EEPROM Pad drive
+
+*
+* INPUTS:
+*		point - Pointer to the Scratch and Misc. Control register.
+*
+* OUTPUTS:
+*		data - Scratch and Misc. Control data read from the register 
+*				pointed to by the point above.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetScratchMiscCtrl
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			point,
+    OUT  GT_U8			*data
+);
+
+/*******************************************************************************
+* gsysSetScratchBits
+*
+* DESCRIPTION:
+*		Set bits to the Scratch and Misc Control register <scratch byte 0 and 1>.
+*		These bits are 100% available to software for whatever purpose desired. 
+*		These bits do not connect to any hardware function.
+*
+* INPUTS:
+*		scritch - written bits.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetScratchBits
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U16			scratch
+);
+
+/*******************************************************************************
+* gsysGetScratchBits
+*
+* DESCRIPTION:
+*		Get bits from the Scratch and Misc Control register <scratch byte 0 and 1>.
+*		These bits are 100% available to software for whatever purpose desired. 
+*		These bits do not connect to any hardware function.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		scritch - read bits.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetScratchBits
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U16			*scratch
+);
+
+/*******************************************************************************
+* gsysSetGpioConfigMod
+*
+* DESCRIPTION:
+*		Set bits to the Scratch and Misc Control register <GPIO Configuration>
+*		to configure GPIO mode.
+*		The bits are shared General Purpose Input Output mode Bits:
+*		Bit 6 - GT_GPIO_BIT_6:	1:GPIO[6]	0:SE_RCLK1
+*		Bit 5 - GT_GPIO_BIT_5:	1:GPIO[5]	0:SE_RCLK0
+*		Now, folloing bits are read only. 
+*		Bit 4 - GT_GPIO_BIT_4:	1:GPIO[4]	0:
+*		Bit 3 - GT_GPIO_BIT_3:	1:GPIO[3]	0:
+*		Bit 2 - GT_GPIO_BIT_2:	1:GPIO[2]	0:
+*		Bit 1 - GT_GPIO_BIT_1:	1:GPIO[1]	0:P6_COL
+*		Bit 0 - GT_GPIO_BIT_0:	1:GPIO[0]	0:P6_CRS
+*
+* INPUTS:
+*		mode - OR [GT_GPIO_BIT_x]
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetGpioConfigMod
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			mode
+);
+
+/*******************************************************************************
+* gsysGetGpioConfigMod
+*
+* DESCRIPTION:
+*		Get mode from the Scratch and Misc Control register <GPIO Configuration>.
+*		The bits are shared General Purpose Input Output mode Bits:
+*		Bit 6 - GT_GPIO_BIT_6:	1:GPIO[6]	0:SE_RCLK1
+*		Bit 5 - GT_GPIO_BIT_5:	1:GPIO[5]	0:SE_RCLK0
+*		Now, folloing bits are read only. 
+*		Bit 4 - GT_GPIO_BIT_4:	1:GPIO[4]	0:
+*		Bit 3 - GT_GPIO_BIT_3:	1:GPIO[3]	0:
+*		Bit 2 - GT_GPIO_BIT_2:	1:GPIO[2]	0:
+*		Bit 1 - GT_GPIO_BIT_1:	1:GPIO[1]	0:P6_COL
+*		Bit 0 - GT_GPIO_BIT_0:	1:GPIO[0]	0:P6_CRS
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - OR [GT_GPIO_BIT_x]
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetGpioConfigMod
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			*mode
+);
+
+/*******************************************************************************
+* gsysSetGpioDirection
+*
+* DESCRIPTION:
+*		Set Gpio direction to the Scratch and Misc Control register <GPIO Direction>.
+*		The bits are used to control the direction of GPIO[6:0]. 
+*		When a GPIOÂ’s bit is set to a one that GPIO will become an input. When a
+*		GPIOÂ’s bit is cleared to a zero that GPIO will become an output
+*		General Purpose Input Output direction bits are:
+*		Bit 6 - GT_GPIO_BIT_6
+*		Bit 5 - GT_GPIO_BIT_5
+*		Bit 4 - GT_GPIO_BIT_4
+*		Bit 3 - GT_GPIO_BIT_3
+*		Bit 2 - GT_GPIO_BIT_2
+*		Bit 1 - GT_GPIO_BIT_1
+*		Bit 0 - GT_GPIO_BIT_0
+*
+* INPUTS:
+*		dir - OR [GT_GPIO_BIT_x]
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetGpioDirection
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			dir
+);
+
+/*******************************************************************************
+* gsysGetGpioDirection
+*
+* DESCRIPTION:
+*		get Gpio direction from the Scratch and Misc Control register <GPIO Direction>.
+*		The bits are used to control the direction of GPIO[6:0]. 
+*		When a GPIOÂ’s bit is set to a one that GPIO will become an input. When a
+*		GPIOÂ’s bit is cleared to a zero that GPIO will become an output
+*		General Purpose Input Output direction bits are:
+*		Bit 6 - GT_GPIO_BIT_6
+*		Bit 5 - GT_GPIO_BIT_5
+*		Bit 4 - GT_GPIO_BIT_4
+*		Bit 3 - GT_GPIO_BIT_3
+*		Bit 2 - GT_GPIO_BIT_2
+*		Bit 1 - GT_GPIO_BIT_1
+*		Bit 0 - GT_GPIO_BIT_0
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		dir - OR [GT_GPIO_BIT_x]
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetGpioDirection
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U32			*dir
+);
+
+/*******************************************************************************
+* gsysSetGpioData
+*
+* DESCRIPTION:
+*		Set Gpio data to the Scratch and Misc Control register <GPIO data>.
+*		When a GPIOÂ’s bit is set to be an input, data written to this bit will go 
+*		to a holding register but will not appear on the pin nor in this register. 
+*		Reads of this register will return the actual, real-time, data that is 
+*		appearing on the GPIOÂ’s pin.
+*		When a GPIOÂ’s bit is set to be an output, data written to this bit will go 
+*		to a holding register and will appear on the GPIOÂ’s pin. Reads of this register 
+*		will return the actual, real-time, data that is appearing on the GPIOÂ’s pin 
+*		(which in this case should be the data written, but if its isnÂ’t that would 
+*		be an indication of a conflict).
+*		When a pinÂ’s direction changes from input to output, the data last written 
+*		to the holding register appears on the GPIOÂ’s pin
+*		General Purpose Input Output data bits are:
+*		Bit 6 - GT_GPIO_BIT_6
+*		Bit 5 - GT_GPIO_BIT_5
+*		Bit 4 - GT_GPIO_BIT_4
+*		Bit 3 - GT_GPIO_BIT_3
+*		Bit 2 - GT_GPIO_BIT_2
+*		Bit 1 - GT_GPIO_BIT_1
+*		Bit 0 - GT_GPIO_BIT_0
+*
+* INPUTS:
+*		data - OR [GT_GPIO_BIT_x]
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetGpioData
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			data
+);
+
+/*******************************************************************************
+* gsysGetGpioData
+*
+* DESCRIPTION:
+*		get Gpio data to the Scratch and Misc Control register <GPIO data>.
+*		When a GPIOÂ’s bit is set to be an input, data written to this bit will go 
+*		to a holding register but will not appear on the pin nor in this register. 
+*		Reads of this register will return the actual, real-time, data that is 
+*		appearing on the GPIOÂ’s pin.
+*		When a GPIOÂ’s bit is set to be an output, data written to this bit will go 
+*		to a holding register and will appear on the GPIOÂ’s pin. Reads of this register 
+*		will return the actual, real-time, data that is appearing on the GPIOÂ’s pin 
+*		(which in this case should be the data written, but if its isnÂ’t that would 
+*		be an indication of a conflict).
+*		When a pinÂ’s direction changes from input to output, the data last written 
+*		to the holding register appears on the GPIOÂ’s pin
+*		General Purpose Input Output data bits are:
+*		Bit 6 - GT_GPIO_BIT_6
+*		Bit 5 - GT_GPIO_BIT_5
+*		Bit 4 - GT_GPIO_BIT_4
+*		Bit 3 - GT_GPIO_BIT_3
+*		Bit 2 - GT_GPIO_BIT_2
+*		Bit 1 - GT_GPIO_BIT_1
+*		Bit 0 - GT_GPIO_BIT_0
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		data - OR [GT_GPIO_BIT_x]
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetGpioData
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			*data
+);
+
+/*******************************************************************************
+* gsysGetConfigData
+*
+* DESCRIPTION:
+*		Get Reset Configuration Pin Data 0-3. 
+*		These registers return the values observed after a hardware Reset on the 
+*		listed CONFIG data listed below.
+*			Config data 0:
+*			  Bit	Config	Pin's Primary Name
+*				0	USER[0]		P6_OUTD[5]
+*				1	USER[1]		P6_OUTD[6]
+*				2	USER[2]		P6_OUTD[7]
+*				3	ADDR[0]		P5_OUTD[0]
+*				4	ADDR[1]		P5_OUTD[5]
+*				5	ADDR[2]		P5_OUTD[6]
+*				6	ADDR]3]		P5_OUTD[7]
+*				7	ADDR[4]		P5_OUTD[1]
+*			Config data 1:
+*				0	LED_SEL[0]	P1_LED
+*				1	LED_SEL[1]	P2_LED
+*				2	4COL P3_LED
+*				3	NormCx		P4_LED
+*				4	Jumbo		P0_LED
+*				5	EE_WE		EE_CS/C2_LED
+*				6	FD_FLOW		EE_CLK/C1_LED
+*				7	HD_FLOW		EE_DIN/C0_LED
+*			Config data 2:
+*				0	P5_MODE[0]	P5_OUTD[2]
+*				1	P5_MODE[1]	P5_OUTD[3]
+*				2	P5_MODE[2]	P5_OUTD[4]
+*				3	Reserved for future use
+*				4	P6_MODE[0]	P6_OUTD[2]
+*				5	P6_MODE[1]	P6_OUTD[3]
+*				6	P6_MODE[2]	P6_OUTD[4]
+*				7	Reserved for future use
+*			Config data 3:
+*				0	RMU_MODE[0] P6_OUTD[0]
+*				1	RMU_MODE[1] P6_OUTD[1]
+*				2	S_VDDOS[0]	PTP_TRIG 
+*				3	CLK125EN	CLK125
+*				4	P5_VDDOS[0] P5_GTXCLK
+*				5	P5_VDDOS[1] P5_OUTEN
+*				6	P6_VDDOS[0] P5_GTXCLK
+*				7	P6_VDDOS[1] P6_OUTEN
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*       cfgDat - GT_CONFIG_DTTA
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetConfigData
+(
+    IN  GT_QD_DEV 			*dev,
+    OUT  GT_CONFIG_DATA		*cfgData
+);
+
+/*******************************************************************************
+* gsysSetSyncETai
+*
+* DESCRIPTION:
+*		Set SyncE and Tai to the Scratch and Misc. Control register <SyncE and TAI pad>.
+*
+* INPUTS:
+*		zpr - ZPR for SyncE and TAI
+*		znr - ZNR for SyncE and TAI
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetSyncETai
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8			zpr,
+    IN  GT_U8			znr
+);
+
+/*******************************************************************************
+* gsysGetSyncETai
+*
+* DESCRIPTION:
+*		Get SyncE and Tai from the Scratch and Misc Control register <SyncE and TAI pad>.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		zpr - ZPR for SyncE and TAI
+*		znr - ZNR for SyncE and TAI*
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetSyncETai
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U8			*zpr,
+    OUT  GT_U8			*znr
+);
+
+/*******************************************************************************
+* gsysSetP6_Clock
+*
+* DESCRIPTION:
+*		Set P6_clock to the Scratch and Misc Control register <P6_Clock pad>.
+*
+* INPUTS:
+*		zpr - ZPR for P6_Clock
+*		znr - ZNR for P6_Clock
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetP6_Clock
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8			zpr,
+    IN  GT_U8			znr
+);
+
+/*******************************************************************************
+* gsysGetP6_Clock
+*
+* DESCRIPTION:
+*       Get P6_clock from the Scratch and Misc Control register <P6_Clock pad>.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		zpr - ZPR for P6_Clock
+*		znr - ZNR for P6_Clock
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetP6_Clock
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U8			*zpr,
+    OUT  GT_U8			*znr
+);
+
+/*******************************************************************************
+* gsysSetP5_Clock
+*
+* DESCRIPTION:
+*       Set P5_clock to the Scratch and Misc Control register <P5_Clock pad>.
+*
+* INPUTS:
+*		zpr - ZPR for P5_Clock
+*		znr - ZNR for P5_Clock
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetP5_Clock
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8			zpr,
+    IN  GT_U8			znr
+);
+
+/*******************************************************************************
+* gsysGetP5_Clock
+*
+* DESCRIPTION:
+*       Get P5_clock from the Scratch and Misc Control register <P5_Clock pad>.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		zpr - ZPR for P5_Clock
+*		znr - ZNR for P5_Clock
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetP5_Clock
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U8			*zpr,
+    OUT  GT_U8			*znr
+);
+
+/*******************************************************************************
+* gsysSetEEPROM
+*
+* DESCRIPTION:
+*       Set EEPROM cycle to the Scratch and Misc Control register <EEPROM pad>.
+*
+* INPUTS:
+*		dsm - DSM for EEPROM cycle
+*		zpr - ZPR for EEPROM cycle
+*		znr - ZNR for EEPROM cycle
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysSetEEPROM
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8			dsm,
+    IN  GT_U8			zpr,
+    IN  GT_U8			znr
+);
+
+/*******************************************************************************
+* gsysGetEEPROM
+*
+* DESCRIPTION:
+*       Get EEPROM cycle to the Scratch and Misc Control register <EEPROM pad>.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		dsm - DSM for EEPROM cycle
+*		zpr - ZPR for EEPROM cycle
+*		znr - ZNR for EEPROM cycle
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gsysGetEEPROM
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U8			*dsm,
+    OUT  GT_U8			*zpr,
+    OUT  GT_U8			*znr
+);
+
+
+/* gtAdvVct.c */
+
+/*******************************************************************************
+* gvctGetAdvCableDiag
+*
+* DESCRIPTION:
+*       This routine perform the advanced virtual cable test for the requested
+*       port and returns the the status per MDI pair.
+*
+* INPUTS:
+*       port - logical port number.
+*       mode - advance VCT mode (either First Peak or Maximum Peak)
+*
+* OUTPUTS:
+*       cableStatus - the port copper cable status.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       Internal Gigabit Phys in 88E6165 family and 88E6351 family devices
+*		are supporting this API.
+*
+*******************************************************************************/
+GT_STATUS gvctGetAdvCableDiag
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT        port,
+    IN  GT_ADV_VCT_MODE mode,
+    OUT GT_ADV_CABLE_STATUS *cableStatus
+);
+
+/*******************************************************************************
+* gvctGetAdvExtendedStatus
+*
+* DESCRIPTION:
+*		This routine retrieves extended cable status, such as Pair Poloarity,
+*		Pair Swap, and Pair Skew. Note that this routine will be success only
+*		if 1000Base-T Link is up.
+*		DSP based cable length is also provided.
+*
+* INPUTS:
+*       dev  - pointer to GT driver structure returned from mdLoadDriver
+*       port - logical port number.
+*
+* OUTPUTS:
+*       extendedStatus - the extended cable status.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*		Supporting Device list:
+*       	88E1111, 88E1112, 88E1141~6, 88E1149, and Internal Gigabit Phys 
+*			in 88E6165 family and 88E6351 family devices
+*
+*******************************************************************************/
+GT_STATUS gvctGetAdvExtendedStatus
+(
+    IN  GT_QD_DEV     *dev,
+    IN  GT_LPORT   port,
+    OUT GT_ADV_EXTENDED_STATUS *extendedStatus
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __msApi_h */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiTypes.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiTypes.h
new file mode 100755
index 0000000..1f6ff26
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiTypes.h
@@ -0,0 +1,105 @@
+/* 
+ * Copyright 2002, Marvell International Ltd.
+ * 
+ * THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL SEMICONDUCTOR, INC.
+ * NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT
+ * OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE
+ * DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.
+ * THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESS, IMPLIED
+ * OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.
+ */
+
+/*
+ * FILENAME:    $Workfile: mv_types.h $
+ * REVISION:    $Revision: 3 $
+ * LAST UPDATE: $Modtime: 12/24/02 5:37p $
+ *
+ * DESCRIPTION:
+ *     This file defines common data types used on Host and NetGX sides.
+ */
+
+
+#ifndef MV_TYPES_H
+#define MV_TYPES_H
+
+
+/* general */
+
+#undef IN
+#define IN
+#undef OUT
+#define OUT
+#undef INOUT
+#define INOUT
+
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+typedef void  GT_VOID;
+typedef char  GT_8;
+typedef short GT_16; 
+typedef long  GT_32;
+
+typedef unsigned char  GT_U8;
+typedef unsigned short GT_U16;
+typedef unsigned long  GT_U32;
+typedef unsigned int   GT_UINT; 
+
+typedef union {
+	GT_U8	c[8];
+	GT_U16	s[4];
+	GT_U32	l[2];
+} GT_U64;
+
+
+typedef enum {
+    GT_FALSE = 0,
+    GT_TRUE  = 1
+} GT_BOOL;
+
+typedef void          (*GT_VOIDFUNCPTR) (void); /* ptr to function returning void */
+typedef unsigned int  (*GT_INTFUNCPTR)  (void); /* ptr to function returning int  */
+
+
+/* module state */
+typedef enum {
+	GT_STATE_NONE = 0,	/* Uninitialized */
+	GT_STATE_IDLE,		/* Initialized, but not started (or stopped) */
+	GT_STATE_ACTIVE		/* Started */
+} GT_STATE;
+
+
+#define	GT_ETHERNET_HEADER_SIZE		(6)
+
+typedef struct
+{
+    GT_U8       arEther[GT_ETHERNET_HEADER_SIZE];
+}GT_ETHERADDR;
+
+/* This macro checks for a multicast mac address    */
+#define GT_IS_MULTICAST_MAC(mac)  ((mac.arEther[0] & 0x1) == 1)
+
+
+/* This macro checks for an broadcast mac address     */
+#define GT_IS_BROADCAST_MAC(mac) (((mac).arEther[0] == 0xFF) && ((mac).arEther[1] == 0xFF) && ((mac).arEther[2] == 0xFF) && ((mac).arEther[3] == 0xFF) && ((mac).arEther[4] == 0xFF) && ((mac).arEther[5] == 0xFF))
+
+
+/* status / error codes */
+typedef int GT_STATUS;
+
+#define GT_ERROR		   (-1)
+#define GT_OK			   (0x00)	/* Operation succeeded                   */
+#define GT_FAIL			   (0x01)	/* Operation failed                      */
+#define GT_BAD_VALUE       (0x02)   /* Illegal value (general)               */
+#define GT_BAD_PARAM       (0x04)   /* Illegal parameter in function called  */
+#define GT_NOT_FOUND       (0x0B)   /* Item not found                        */
+#define GT_NO_MORE         (0x0C)   /* No more items found                   */
+#define GT_NO_SUCH         (0x0D)   /* No such item                          */
+#define GT_TIMEOUT         (0x0E)   /* Time Out                              */
+#define GT_NOT_SUPPORTED   (0x10)   /* This request is not support           */
+#define GT_ALREADY_EXIST   (0x1B)   /* Tried to create existing item         */
+#define GT_BAD_CPU_PORT    (0x20)   /* Input CPU Port is not valid physical port number */
+
+#endif /* MV_TYPES_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiWince.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiWince.h
new file mode 100755
index 0000000..075046c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/Include/msApiWince.h
@@ -0,0 +1,561 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* msApiWince.h
+*
+* DESCRIPTION:
+*       Wince Application need to include only this header file.
+*
+* DEPENDENCIES:   None
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __msApiFunc_h
+#define __msApiFunc_h
+
+#include "msApiDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef GT_STATUS (*FGT_PRT_ATUSIZE)(ATU_SIZE);
+typedef GT_STATUS (*FGT_PRT_U32_U32)(GT_U32*,GT_U32*);
+typedef GT_STATUS (*FGT_VALUE_U32)(GT_U32);
+typedef GT_STATUS (*FGT_PTR_U32)(GT_U32*);
+typedef GT_STATUS (*FGT_PTR_U16)(GT_U16*);
+typedef GT_STATUS (*FGT_PTR_U32_U32_U32)(GT_U32,GT_U32,GT_U32*);
+typedef GT_STATUS (*FGT_PTR_ATUENTRY)(GT_ATU_ENTRY*);
+typedef GT_STATUS (*FGT_PTR_ATUENTRY_BOOL)(GT_ATU_ENTRY*, GT_BOOL*);
+typedef GT_STATUS (*FGT_VALUE_FLUSHCMD)(GT_FLUSH_CMD);
+typedef GT_STATUS (*FGT_PTR_ETHERADDR)(GT_ETHERADDR*);
+typedef GT_STATUS (*FGT_PTR_BOOL)(GT_BOOL*);
+typedef GT_STATUS (*FGT_VALUE_BOOL)(GT_BOOL);
+typedef GT_STATUS (*FGT_VALUE_PORT_STPSTATE)(GT_LPORT,GT_PORT_STP_STATE);
+typedef GT_STATUS (*FGT_PTR_PORT_STPSTATE)(GT_LPORT,GT_PORT_STP_STATE*);
+typedef GT_STATUS (*FGT_VALUE_PORT_EGRESSMODE)(GT_LPORT,GT_EGRESS_MODE);
+typedef GT_STATUS (*FGT_PTR_PORT_EGRESSMODE)(GT_LPORT,GT_EGRESS_MODE*);
+typedef GT_STATUS (*FGT_VALUE_PORT_BOOL)(GT_LPORT,GT_BOOL);
+typedef GT_STATUS (*FGT_PTR_PORT_BOOL)(GT_LPORT,GT_BOOL*);
+typedef GT_STATUS (*FGT_VALUE_PORT_PORTS_U8)(GT_LPORT,GT_LPORT*,GT_U8);
+typedef GT_STATUS (*FGT_PTR_PORT_PORTS_U8)(GT_LPORT,GT_LPORT*,GT_U8*);
+typedef GT_STATUS (*FGT_VALUE_PORT_U16)(GT_LPORT,GT_U16);
+typedef GT_STATUS (*FGT_PTR_PORT_U16)(GT_LPORT,GT_U16*);
+typedef GT_STATUS (*FGT_VALUE_PORT_AUTOMODE)(GT_LPORT,GT_PHY_AUTO_MODE);
+
+typedef GT_STATUS (*FGT_VALUE_PORT)(GT_LPORT);
+typedef GT_STATUS (*FGT_VALUE_U8)(GT_U8);
+typedef GT_STATUS (*FGT_PTR_U8)(GT_U8*);
+typedef GT_STATUS (*FGT_VALUE_PORT_U8)(GT_LPORT,GT_U8);
+typedef GT_STATUS (*FGT_PTR_PORT_U8)(GT_LPORT,GT_U8*);
+typedef GT_STATUS (*FGT_VALUE_PORT_INGRESSMODE)(GT_LPORT,GT_INGRESS_MODE);
+typedef GT_STATUS (*FGT_PTR_PORT_INGRESSMODE)(GT_LPORT,GT_INGRESS_MODE*);
+typedef GT_STATUS (*FGT_VALUE_PORT_MCRATE)(GT_LPORT,GT_MC_RATE);
+typedef GT_STATUS (*FGT_PTR_PORT_MCRATE)(GT_LPORT,GT_MC_RATE*);
+typedef GT_STATUS (*FGT_VALUE_CTRMODE)(GT_CTR_MODE);
+typedef GT_STATUS (*FGT_PTR_CTRMODE)(GT_CTR_MODE*);
+typedef GT_STATUS (*FGT_VOID)(void);
+typedef GT_STATUS (*FGT_PTR_PORT_PORTSTAT)(GT_LPORT,GT_PORT_STAT*);
+typedef GT_STATUS (*FGT_VALUE_U8_U8)(GT_U8,GT_U8);
+typedef GT_STATUS (*FGT_PTR_U8_U8)(GT_U8,GT_U8*);
+typedef GT_STATUS (*FGT_PTR_CONFIG_INFO)(GT_SYS_CONFIG*,GT_SYS_INFO*);
+typedef GT_STATUS (*FGT_PTR_VERSION)(GT_VERSION*);
+typedef GT_STATUS (*FGT_PTR_REGISTER)(BSP_FUNCTIONS*);
+typedef GT_STATUS (*FGT_PTR_INT_HANDLER)(FGT_INT_HANDLER*);
+
+typedef GT_STATUS (*FGT_PTR_U32_U32_U16)(GT_U32,GT_U32,GT_U16);
+
+
+extern FGT_PRT_ATUSIZE 			gfdbSetAtuSize;
+extern FGT_PRT_U32_U32 			gfdbGetAgingTimeRange;
+extern FGT_VALUE_U32 			gfdbSetAgingTimeout;
+extern FGT_PTR_U32 				gfdbGetAtuDynamicCount;
+extern FGT_PTR_ATUENTRY 		gfdbGetAtuEntryFirst;
+extern FGT_PTR_ATUENTRY 		gfdbGetAtuEntryNext;
+extern FGT_PTR_ATUENTRY_BOOL 	gfdbFindAtuMacEntry;
+extern FGT_VALUE_FLUSHCMD 		gfdbFlush;
+extern FGT_PTR_ATUENTRY 		gfdbAddMacEntry; //liane
+extern FGT_PTR_ETHERADDR 		gfdbDelMacEntry;
+extern FGT_VALUE_BOOL 			gfdbLearnEnable;
+extern FGT_VALUE_BOOL 				gstpSetMode;
+extern FGT_VALUE_PORT_STPSTATE 		gstpSetPortState;
+extern FGT_PTR_PORT_STPSTATE 		gstpGetPortState;
+extern FGT_VALUE_PORT_EGRESSMODE 	gprtSetEgressMode;
+extern FGT_PTR_PORT_EGRESSMODE 		gprtGetEgressMode;
+extern FGT_VALUE_PORT_BOOL 			gprtSetVlanTunnel;
+extern FGT_PTR_PORT_BOOL 			gprtGetVlanTunnel;
+extern FGT_VALUE_PORT_PORTS_U8		gvlnSetPortVlanPorts;
+extern FGT_PTR_PORT_PORTS_U8		gvlnGetPortVlanPorts;
+extern FGT_VALUE_PORT_BOOL			gvlnSetPortUserPriLsb;
+extern FGT_PTR_PORT_BOOL			gvlnGetPortUserPriLsb;
+extern FGT_VALUE_PORT_U16			gvlnSetPortVid;
+extern FGT_PTR_PORT_U16				gvlnGetPortVid;
+extern FGT_VALUE_U32				eventSetActive;
+extern FGT_PTR_U16					eventGetIntStatus;
+extern FGT_VALUE_PORT				gprtPhyReset;
+extern FGT_VALUE_PORT_BOOL			gprtSetPortLoopback;
+extern FGT_VALUE_PORT_BOOL			gprtGetPortLoopback;
+extern FGT_VALUE_PORT_BOOL			gprtSetPortSpeed;
+extern FGT_VALUE_PORT_BOOL			gprtGetPortSpeed;
+extern FGT_VALUE_PORT_BOOL			gprtPortAutoNegEnable;
+extern FGT_VALUE_PORT_BOOL			gprtPortAutoNegEnable;
+extern FGT_VALUE_PORT_BOOL			gprtPortPowerDown;
+extern FGT_VALUE_PORT_BOOL			gprtGetPortPowerDown;
+extern FGT_VALUE_PORT				gprtPortRestartAutoNeg;
+extern FGT_VALUE_PORT_BOOL			gprtSetPortDuplexMode;
+extern FGT_VALUE_PORT_AUTOMODE		gprtSetPortAutoMode;
+extern FGT_VALUE_PORT_BOOL			gprtSetPause;
+extern FGT_VALUE_PORT_BOOL			gprtGetPause;
+extern FGT_VALUE_PORT_U16			gprtPhyIntEnable;
+extern FGT_PTR_PORT_U16				gprtGetPhyIntStatus;
+extern FGT_PTR_U16					gprtGetPhyIntPortSummary;
+extern FGT_VALUE_PORT_BOOL			gprtSetForceFc;
+extern FGT_PTR_PORT_BOOL			gprtGetForceFc;
+extern FGT_VALUE_PORT_BOOL			gprtSetTrailerMode;
+extern FGT_PTR_PORT_BOOL			gprtGetTrailerMode;
+extern FGT_VALUE_PORT_INGRESSMODE	gprtSetIngressMode;
+extern FGT_PTR_PORT_INGRESSMODE		gprtGetIngressMode;
+extern FGT_VALUE_PORT_MCRATE		gprtSetMcRateLimit;
+extern FGT_PTR_PORT_MCRATE			gprtGetMcRateLimit;
+extern FGT_VALUE_CTRMODE			gprtSetCtrMode;
+extern FGT_VOID					gprtClearAllCtr;
+extern FGT_PTR_PORT_PORTSTAT	gprtGetPortCtr;
+extern FGT_PTR_PORT_BOOL		gprtGetPartnerLinkPause;
+extern FGT_PTR_PORT_BOOL		gprtGetSelfLinkPause;
+extern FGT_PTR_PORT_BOOL		gprtGetResolve;
+extern FGT_PTR_PORT_BOOL		gprtGetLinkState;
+extern FGT_PTR_PORT_BOOL		gprtGetPortMode;
+extern FGT_PTR_PORT_BOOL		gprtGetPhyMode;
+extern FGT_PTR_PORT_BOOL		gprtGetDuplex;
+extern FGT_PTR_PORT_BOOL		gprtGetSpeed;
+extern FGT_VALUE_PORT_U8		gcosSetPortDefaultTc;
+extern FGT_VALUE_PORT_BOOL		gqosSetPrioMapRule;
+extern FGT_PTR_PORT_BOOL		gqosGetPrioMapRule;
+extern FGT_VALUE_PORT_BOOL		gqosIpPrioMapEn;
+extern FGT_PTR_PORT_BOOL		gqosGetIpPrioMapEn;
+extern FGT_VALUE_PORT_BOOL		gqosUserPrioMapEn;
+extern FGT_PTR_PORT_BOOL		gqosGetUserPrioMapEn;
+extern FGT_PTR_U8_U8			gcosGetUserPrio2Tc;
+extern FGT_VALUE_U8_U8			gcosSetUserPrio2Tc;
+extern FGT_PTR_U8_U8			gcosGetDscp2Tc;
+extern FGT_VALUE_U8_U8			gcosSetDscp2Tc;
+extern FGT_PTR_CONFIG_INFO		sysConfig;
+extern FGT_VOID					sysEnable;
+extern FGT_VOID					gsysSwReset;
+extern FGT_VALUE_BOOL			gsysSetDiscardExcessive;
+extern FGT_PTR_BOOL				gsysGetDiscardExcessive;
+extern FGT_VALUE_BOOL			gsysSetSchedulingMode;
+extern FGT_PTR_BOOL				gsysGetSchedulingMode;
+extern FGT_VALUE_BOOL			gsysSetMaxFrameSize;
+extern FGT_PTR_BOOL				gsysGetMaxFrameSize;
+extern FGT_VOID					gsysReLoad;
+extern FGT_VALUE_BOOL			gsysSetWatchDog;
+extern FGT_PTR_BOOL				gsysGetWatchDog;
+extern FGT_PTR_ETHERADDR		gsysSetDuplexPauseMac;
+extern FGT_PTR_ETHERADDR		gsysGetDuplexPauseMac;
+extern FGT_VALUE_BOOL			gsysSetPerPortDuplexPauseMac;
+extern FGT_PTR_BOOL				gsysGetPerPortDuplexPauseMac;
+extern FGT_PTR_U32_U32_U32		gsysReadMiiReg;
+extern FGT_PTR_VERSION			gtVersion;
+extern FGT_PTR_REGISTER			gtRegister;
+
+extern FGT_PTR_U32_U32_U16		gsysWriteMiiReg;
+
+/*
+ * This function will get the all the MS APIs and assign to local function pointers.
+ */
+int qdGetMSApiFunc();
+
+GT_U32 gtStrlen
+(
+    IN const void * source
+);
+
+//*****************************************************************************
+//  I O C T L S
+//*****************************************************************************
+#include "windev.h"
+
+typedef struct _GT_IOCTL_PARAM
+{
+	union 
+	{
+		GT_LPORT	portList[8];
+		GT_LPORT	port;
+		GT_U8  		u8Data;
+		GT_U16  	u16Data;
+		GT_U32  	u32Data;
+		GT_BOOL 	boolData;
+
+		GT_CTR_MODE	ctrMode;
+		GT_PORT_STP_STATE	stpState;
+		GT_EGRESS_MODE		egressMode;
+		GT_INGRESS_MODE		ingressMode;
+		GT_MC_RATE		mcRate;
+		GT_PORT_STAT	portStat;
+		ATU_SIZE 		atuSize;
+		GT_FLUSH_CMD 	flushCmd;
+
+		GT_ATU_ENTRY 	atuEntry;
+		GT_ETHERADDR 	etherAddr;
+		GT_SYS_CONFIG 	sysConfig;
+		GT_SYS_INFO		sysInfo;
+
+	} FirstParam;
+
+	union 
+	{
+		GT_LPORT	port;
+		GT_LPORT	portList[8];
+		GT_U8		u8Data;
+		GT_U16		u16Data;
+		GT_U32		u32Data;
+		GT_BOOL		boolData;
+		GT_PORT_STP_STATE	stpState;
+		GT_EGRESS_MODE		egressMode;
+		GT_INGRESS_MODE		ingressMode;
+		GT_MC_RATE		mcRate;
+
+		GT_PORT_STAT	portStat;
+
+		GT_PHY_AUTO_MODE	phyAutoMode;
+
+	} SecondParam;
+
+	union
+	{
+		GT_U8	u8Data;
+		GT_U16	u16Data;
+		GT_U32	u32Data;
+
+	} ThirdParam;
+
+} GT_IOCTL_PARAM, *PGT_IOCTL_PARAM;
+
+#define GET_FUNC_FROM_CTL_CODE(_ioctl) ((_ioctl>>2) & 0xFFF)
+
+/*
+	Microsoft allows for us to use 0x800 ~ 0xFFF
+	So, our program is using 6 bits for function group,
+	and 6 bits for each function.
+*/
+#define SUB_FUNC_MASK		0xFC0
+#define SYS_CFG_FUNC_MASK	(1 << 6) | 0x800
+#define SYS_CTRL_FUNC_MASK	(2 << 6) | 0x800
+#define FDB_FUNC_MASK		(3 << 6) | 0x800
+#define VLAN_FUNC_MASK		(4 << 6) | 0x800
+#define STP_FUNC_MASK		(5 << 6) | 0x800
+#define PORT_CTRL_FUNC_MASK		(6 << 6) | 0x800
+#define PORT_STATUS_FUNC_MASK	(7 << 6) | 0x800
+#define PORT_STATS_FUNC_MASK	(8 << 6) | 0x800
+#define QOS_FUNC_MASK			(9 << 6) | 0x800
+#define PHY_CTRL_FUNC_MASK		(10 << 6) | 0x800
+#define SYS_EVENT_FUNC_MASK		(11 << 6) | 0x800
+#define PHY_INT_FUNC_MASK		(12 << 6) | 0x800
+
+/*
+	Functions for SYS Configuration
+*/
+#define IOCTL_sysConfig    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CFG_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysReadMiiReg    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CFG_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysWriteMiiReg    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CFG_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gtVersion    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CFG_FUNC_MASK + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+/*
+	Functions for ATU
+*/
+#define IOCTL_gfdbSetAtuSize    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbGetAgingTimeRange    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbSetAgingTimeout    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbGetAtuDynamicCount    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbGetAtuEntryFirst    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbGetAtuEntryNext    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbFindAtuMacEntry    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbFlush    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbAddMacEntry    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbDelMacEntry    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 9, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gfdbLearnEnable    \
+    CTL_CODE(FILE_DEVICE_NETWORK , FDB_FUNC_MASK + 10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+/*
+	Functions for STP
+*/
+#define IOCTL_gstpSetMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , STP_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gstpSetPortState    \
+    CTL_CODE(FILE_DEVICE_NETWORK , STP_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gstpGetPortState    \
+    CTL_CODE(FILE_DEVICE_NETWORK , STP_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+/*
+	Functions for VLAN
+*/
+#define IOCTL_gprtSetEgressMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetEgressMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetVlanTunnel    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetVlanTunnel    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gvlnSetPortVlanPorts    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gvlnGetPortVlanPorts    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gvlnSetPortUserPriLsb    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gvlnGetPortUserPriLsb    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gvlnSetPortVid    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gvlnGetPortVid    \
+    CTL_CODE(FILE_DEVICE_NETWORK , VLAN_FUNC_MASK + 9, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+/*
+	Functions for System Event
+*/
+#define IOCTL_eventSetActive    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_EVENT_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_eventGetIntStatus    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_EVENT_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+/*
+	Functions for Phy Control
+*/
+#define IOCTL_gprtPhyReset    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetPortLoopback    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetPortSpeed    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtPortAutoNegEnable    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtPortPowerDown    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtPortRestartAutoNeg    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetPortDuplexMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetPortAutoMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetPause    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_CTRL_FUNC_MASK + 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+/* 
+	Functions for Phy Interrupt
+*/
+#define IOCTL_gprtPhyIntEnable    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_INT_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetPhyIntStatus    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_INT_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetPhyIntPortSummary    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PHY_INT_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+/*
+	Functions for Port Control
+*/
+#define IOCTL_gprtSetForceFc    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_CTRL_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetForceFc    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_CTRL_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetTrailerMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_CTRL_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetTrailerMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_CTRL_FUNC_MASK + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetIngressMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_CTRL_FUNC_MASK + 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetIngressMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_CTRL_FUNC_MASK + 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtSetMcRateLimit    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_CTRL_FUNC_MASK + 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetMcRateLimit    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_CTRL_FUNC_MASK + 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+/*
+	Functions for Port Statistics
+*/
+#define IOCTL_gprtSetCtrMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATS_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtClearAllCtr    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATS_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetPortCtr    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATS_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+/*
+	Functions for Port Status
+*/
+#define IOCTL_gprtGetPartnerLinkPause    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATUS_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetSelfLinkPause    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATUS_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetResolve    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATUS_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetLinkState    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATUS_FUNC_MASK + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetPortMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATUS_FUNC_MASK + 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetPhyMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATUS_FUNC_MASK + 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetDuplex    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATUS_FUNC_MASK + 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gprtGetSpeed    \
+    CTL_CODE(FILE_DEVICE_NETWORK , PORT_STATUS_FUNC_MASK + 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+/*
+	Functions for QoS Mapping
+*/
+#define IOCTL_gcosSetPortDefaultTc    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gqosSetPrioMapRule    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gqosGetPrioMapRule    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gqosIpPrioMapEn    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gqosGetIpPrioMapEn    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gqosUserPrioMapEn    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gqosGetUserPrioMapEn    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gcosGetUserPrio2Tc    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gcosSetUserPrio2Tc    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gcosGetDscp2Tc    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 9, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gcosSetDscp2Tc    \
+    CTL_CODE(FILE_DEVICE_NETWORK , QOS_FUNC_MASK + 10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+/*
+	Functions for Sys Control
+*/
+#define IOCTL_gsysSwReset    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysSetDiscardExcessive    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysGetDiscardExcessive    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysSetSchedulingMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 3, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysGetSchedulingMode    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 4, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysSetMaxFrameSize    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysGetMaxFrameSize    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysReLoad    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysSetWatchDog    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysGetWatchDog    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 9, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysSetDuplexPauseMac    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysGetDuplexPauseMac    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 11, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysSetPerPortDuplexPauseMac    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define IOCTL_gsysGetPerPortDuplexPauseMac    \
+    CTL_CODE(FILE_DEVICE_NETWORK , SYS_CTRL_FUNC_MASK + 13, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/README b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/README
new file mode 100755
index 0000000..b9b290c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/README
@@ -0,0 +1,393 @@
+
+                    DSDT Release version 2.8b
+                   ==========================
+
+Table of Content:
+-----------------
+1) Release History 
+2) Source Code Organization
+3) General Introduction
+4) HOW TO - Build qdDrv.o for vxWorks
+5) HOW TO - Build qdDrv.lib for WinCE
+6) HOW TO - Build qdDrv.o for Linux
+7) Changes
+8) New APIs
+
+
+1) Release History 
+------------------
+DSDT2.8b.zip - Oct. 2009 Added GPL and BSD license options to copyright header.
+
+DSDT2.8a.zip - Mar. 2009. Bug fixes.
+         1. Bug fixes for SERDES interface configuration.
+         2. VCT fixes for 88E616x, 88E617x, 88E635x internal PHYs.
+         3. Auto Scan issues on 88E617x, 88E635x family.
+         4. msgIdStartBit in GT_PTP_CONFIG is obsolete.
+         5. TRUNK ATU entries for 88E616x, 88E617x, 88E635x are configured properly.
+         6. Port mapping macros with GT_USE_SIMPLE_PORT_MAPPING are casted properly.
+         7. Deleted to support 6095 family for Ingress Rate Limit with Flow control.
+         8. Deleted unused definition in GT_QPRI_TBL_ENTRY.
+         9. Device definition for GT_88E6124, GT_88E6325, GT_88E6371 has been corrected to
+		     GT_88E6125, GT_88E6321, GT_88E6350, respectively.
+
+DSDT2.8.zip - Nov. 2008. added support for 88E6351 family (88E6351,88E6175,88E6124)
+		  1. New APIs are added to support new devices.
+
+DSDT2.7a.zip - March. 2008.
+		  1. Fixed known bugs.
+		  2. Enhanced some of the APIs.
+
+DSDT2.7.zip - May. 2007. added support for 88E6165 family (88E6123,88E6125,88E6140,88E6161)
+		  1. New APIs are added to support new devices.
+		  2. Bug fix
+			GT_PIRL2_DATA structure includes GT_PIRL_COUNT_MODE enum type, 
+			which should be GT_PIRL2_COUNT_MODE.
+			88E6083 support Static Management frame.
+			gprtSetForwardUnknown deals with wrong bit.
+		  3. Removed Diag program that make user confused with missing files.
+
+DSDT2.6b.zip - Jan. 2007.
+		  1. Bug Fixes
+		  2. PIRL Rate Limiting Parameter update
+
+DSDT2.6a.zip - Nov. 2006. added support for 88E6045.
+
+DSDT2.6.zip - Jul. 2006. added support for 88E6097, 88E6096, 88E6046, 88E6047, and 88E6085.
+		  1. New APIs are added to support new devices.
+		  2. Bug fixes those were in 2.6 preliminary release.
+
+DSDT2.6pre.zip - Apr. 2006. added preliminary support for 88E6097.
+		  1. New features are added.
+		  2. Some parameters in the existing APIs are modified to support extended feature.
+
+DSDT2.5b.zip - Jan. 2006.
+		  1. added gtDelay function after disabling PPU
+		  	Since delay function is system/OS dependent, it is required that DSDT user
+		  	fill up the gtDelay function based its platform parameters.
+		  	gtDelay function is located in src\msApi\gtUtils.c
+		  2. Unused GT_STATUS definitions are removed.
+
+DSDT2.5a.zip - Jan. 2006, added support for 88E6122 and 88E6121 and new feature that bypasses
+		  initial device setup, and bug fixes in the previous release.
+		  1. Bypass initial configuration when loading driver.
+		  2. Bug fixes: 
+		  	1) synchronization issues.
+		  	2) port vector of 0xFF was treated as an invalid vector.
+
+DSDT2.5.zip - Nov. 2005, added support for 88E6065, 88E6035, 88E6055, 88E6061, and 88E6031,
+		  and bug fixes in the previous release.
+		  1. New APIs are added to support new devices.
+		  2. Bug fixes: 
+		  	1) gfdbGetAtuEntryNext API returns GT_NO_SUCH when Entry's MAC is Broadcast address.
+		  	2) entryState in GT_ATU_ENTRY follows the definition.
+		  	3) gsysSetTrunkMaskTable API does not overwrite HashTrunk value anymore.
+		  	4) 10/100 FastEthernet Phy Reset occurs along with Speed, Duplex modification.
+
+
+DSDT2.4a.zip - Oct. 2005, added support for 88E6131 and a bug fix.
+		  1. gprtPortPowerDown(gtPhyCtrl.c) didn't work due to reset - reset is not called after PowerDown bit change.
+
+DSDT2.4.zip - Aug. 2005, bug fixes and modifications
+		  1. gprtSetPktGenEnable(gtPhyCtrl.c) didn't work with Serdes Device - resolved.
+		  2. gprtSetPortAutoMode(gtPhyCtrl.c) dropped 1000Mbps Half duplex mode - resolved.
+		  3. gprtGetPhyLinkStatus(gtPhyCtrl.c) returned LinkOn when there is no phy connected - resolved.
+		  4. gprtSetPortDuplexMode(gtPhyCtrl.c) reset 1000M Speed - resolved.
+		  5. gfdbSetAtuSize(gtBrgFdb.c), now, returns GT_NOT_SUPPORT if ATU size of the device 
+		     is not configurable.
+		  6. gprtSetPortLoopback(gtPhyCtrl.c) treats Fast Ethernet Phy and Gigabit Ethernet Phy
+		  	 differently.
+		  7. GT_GET_SERDES_PORT, now, does the error checking.
+		  8. IS_CONFIGURABLE_PHY reads PHY ID and returns the ID
+
+DSDT2.4pre.zip - July. 2005, added support for 88E6108
+		  1. New features are added.
+		  2. Arguments in gprtSetPause and gprtSetPortSpeed are modified to support
+			 1000M Phys.
+		  3. Driver functions are added to support Marvell Alask Phys and to be
+		     expanded easily for the future Phys.
+
+DSDT2.3c.zip - May. 2005,
+		  1. New features in Rev1 or Rev2 of 88E6095 are added
+		  2. gfdbGetAgingTimeout, and gfdbGetLearnEnable are added
+		  3. Bug fixes in grcSetEgressRate and grcSetPri0Rate
+		  4. Resetting TrunkID, when gprtSetTrunkPort is called to disable Trunk, is applied
+		     only to Rev0 of 88E6095 and 88E6185
+
+DSDT2.3b.zip - Mar. 2005, 
+		  1. gstpSetMode function does not modify Port State any more, since STP module
+		     sets the port state. gstpSetMode sets the switch so that it can receive 
+			  BPDU packets.
+		  2. gtLoadDriver clears Rsvd2Cpu and Rsvd2CpuEn bits.
+		  3. TrunkID will be reset when gprtSetTrunkPort is called to disable Trunk.
+		  4. "Check PPU Status in order to verify PPU disabled" is applied to gtVct.c
+
+DSDT2.3a.zip - Jan. 2005, added support for 88E6152, 88E6155, 88E6182, and 88E6092 
+		  devices, removed non-existing devices, and bug fix in 2.3 release.
+		  Fix :
+		  Check PPU Status in order to verify PPU disabled.
+
+DSDT2.3.zip - Nov. 2004, support for 88E6185 and bug fixes in 2.3 preliminary release.
+		  Fixes :
+		  1) Provide some delay after disabling PPU.
+		  2) VCT runs after disabling PPU.
+
+DSDT2.3pre.zip - Nov. 2004, added preliminary support for 88E6185.
+
+DSDT2.2a.zip - Nov. 2004, added semaphore support for MII Access with multi address mode.
+
+DSDT2.2.zip - Oct. 2004, support for 88E6095 and bug fixes in 2.2 preliminary release.
+
+DSDT2.2pre.zip - Sep. 2004, added preliminary support for 88E6095 and work-around for VCT
+		  based on VCT Application Note.
+
+DSDT2.1a.zip - Apr. 2004, support 88E6093 and bug fixes.
+		  Device Driver Package name has been changed from QDDriver to DSDT(Datacom
+		  Same Driver Technology).
+		  Bug Fixes : 
+		  1) DBNum was not correctly handled while getting entry from VTU Table.
+		  2) Member Tag in VTU entry was not defined correctly for 88E6183 family.
+		  3) Correction of 88E6183 RMON Counter Structure and Enum.
+		  4) ATU Interrupt Handling routine
+
+qdDriver2.1-pre.zip - Apr. 2004, added preliminary support for 88E6093 and bug fixes.
+		  Bug Fixes : 
+		  1) DBNum was not incorrectly handled while getting entry from 
+		  VTU Table.
+		  2) Member Tag in VTU entry was not defined correctly for 88E6183 family.
+		
+qdDriver2.0a.zip - Dec. 2003, provides functions, which can read/write  
+		  Switch Port Registers and Switch Global Registers:
+		  gprtGetSwitchReg,
+		  gprtSetSwitchReg,
+		  gprtGetGlobalReg, and
+		  gprtSetGlobalReg
+
+qdDriver2.0.zip - July. 2003, supports Multi Address Mode for upcoming device.
+		  AUTO_SCAN_MODE, MANUAL_MODE, and MULTI_ADDR_MODE are added
+		  to find a QD Family device.
+		  Supports Sapphire (10 port Gigabit switch).
+
+qdDriver1.4a.zip - Apr. 2003, bug fixes.
+		  Bug fixes on portVec in GT_ATU_ENTRY structure, which supported only 
+		  total of 8 ports (defined as GT_U8). It's now defined as GT_U32.
+		  utils.c and testApi.c in Diag directory also modified to support 
+		  the switch with more than 8 ports.
+
+qdDriver1.4.zip - Apr. 2003, added support for Ocatne (6083).
+		  Removed NO-OPs, which created when DBG_PRINT is undefined. 
+		  Bug fixes on gprtSetIGMPSnoop and gprtGetIGMPSnoop functions,
+		  and GT_PRI0_RATE enum type.
+
+qdDriver1.3h.zip - Feb. 2003, added support for Extended Cable Status, 
+		  such as Impediance mismatch, Pair Skew, Pair Swap and Pair Polarity.
+		  Bug fixes on FFox-EG and FFox-XP device ID.
+
+qdDriver1.3g.zip - Dec. 2002, added preliminary support for Octane (6083)
+
+qdDriver1.3.zip - Oct. 2002, added support for ClipperShip (6063)
+		  This driver works with all released devices, including
+		  6051, 6052, 6021, and 6063
+
+qdDriver1.2.zip - Aug. 2002, added support for FullSail (6021)
+				
+qdDriver1.1.zip - June, 2002 OS independent QuarterDeck Driver Release 
+		  Based on 1.0 release, but removed OS dependency. The driver
+		  is designed to work with any OS without code changes.
+
+qdDriver1.0.zip - Feb. 2002, Initial QuaterDeck Driver Release
+		  Based on vxWorks OS, support 6051/6052
+
+
+2) Source Code Organization
+--------------------------
+	2.1) src
+		DSDT Driver Suite Source Code.
+
+	2.2) Include directory
+		DSDT Driver Suite Header files and Prototype files
+
+	2.3) Library
+		Object files for DSDT driver Suite
+
+	2.4) Sample
+		Sample Code that shows how to use MSAPIs, e.g., init DSDT, setup VLAN for Home Gateway, etc.
+
+	* The DSDT Driver Suite Source Code is OS independent, and fully supported by Marvell.
+	* The Sample Codes are tested under vxworks, and is provided for reference only.
+
+
+3) General Introduction
+-----------------------
+
+The DSDT driver suite is standalone program, which is independent of both OS and Platform. 
+As such, applications of MSAPIs need to register platform specific functions. 
+This is done by calling qdLoadDriver function. This function returns a pointer (*dev), 
+which contains the device and platform information. It will then be used for each MSAPI call. 
+
+msApiInit.c file in Diag directory and Sample\Initialization directory demonstrate 
+how you can register those functions.
+
+msApiInit.c
+	qdStart is the main function to initialize DSDT Driver and does the 
+	followings:
+	a) register the platform specific functions. 
+	   1.1 and 1.2 below are required. 1.3 to 1.6 is optional.
+		1.1) readMii - BSP specific MII read function 
+		1.2) writeMii - BSP specific MII write function 
+		1.3) semCreate - OS specific semaphore create function.
+		1.4) semDelete - OS specific semaphore delete function.
+		1.5) semTake - OS specific semaphore take function.
+		1.6) semGive - OS specific semaphore give function.
+
+		Notes) The given example will use DB-88E6218 BSP as an example.
+
+	b) Initialize BSP provided routine (if required).
+
+	c) Calls qdLoadDriver routine.
+		1.1) Input (GT_SYS_CONFIG) - CPU Port Number (Board Specific) and Port Mode 
+		(either 1 for Forwarding mode or 0 for Hardware default mode)
+		1.2) Output (GT_QD_DEV) - Contains all device (QD) and platform specific info.
+		     It will be used for all API calls.
+
+	d) Calls sysEnable (for future use.)
+
+
+4) HOW TO - Build qdDrv.o for vxWorks
+-------------------------------------
+
+1. Extract the given ZIP file into c:\DSDT_2.x directory
+   You may change the directory name to your choice, and change the environment variable below accordingly.
+2. Edit setenv.bat file in c:\DSDT_2.x\tools
+3. Modify the following variables according to your setup.
+set USER_BASE=C:\DSDT_2.x
+set PROJ_NAME=qdDrv
+set WIND_BASE=C:\Tornado
+set TARGETCPU=MIPS		;ARM for ARM Cpu
+set WIND_HOST_TYPE=x86-win32
+4. run "setenv"
+5. Change directory to c:\DSDT_2.x\src
+6. run "make"
+7. qdDrv.o and qdDrv.map will be created in c:\DSDT_2.x\Library.
+
+
+5) HOW TO - Build qdDrv.lib for WinCE
+-------------------------------------
+
+1. Extract the given ZIP file into c:\DSDT_2.x directory(directory can be changed)
+2. Edit setenv.bat file in c:\DSDT_2.x\tools
+3. Modify the following variables according to your setup.
+set USER_BASE=C:\DSDT_2.x
+set PROJ_NAME=qdDrv
+set TARGETCPU=x86		;MIPSIV for MIPS IV
+set WCEROOT=C:\WINCE400
+
+4. run "setenv WINCE"
+5. Change directory to c:\DSDT_2.x\src
+6. run "make"
+7. qdDrv.lib will be created in c:\DSDT_2.x\Library.
+
+
+6) HOW TO - Build qdDrv.o for Linux
+-----------------------------------
+
+1. Extract the given ZIP file into $HOME/DSDT_2.x directory(directory can be changed)
+	in Linux system (verified with RedHat 7.3)
+2. Edit setenv file in $HOME/DSDT_2.x/tools
+3. Modify the following variables according to your setup.
+	declare -x USER_BASE=$HOME/DSDT_2.x
+	declare -x PROJ_NAME=qdDrv
+4. run "source setenv"
+5. Change directory to $HOME/DSDT_2.x/src
+6. run "make"
+7. qdDrv.o and qdDrv.map will be created in $HOME/DSDT_2.x/Library.
+
+
+7) Changes
+-----------
+1. SERDES interface configuration
+	1) APIs in gtPhyCtrl.c can be used for SERDES interface.
+	2) When SERDES interface is accessed, physical SMI address should be used
+	   instead of logical number. This is due to the logical address confliction 
+	   between external phys and SERDES.
+	e.g.) To change the Speed for the first SERDES port (SMI address 0xC)
+		the following API can be used:
+		gprtSetPortSpeed(sw_dev, 0xC, PHY_SPEED_1000_MBPS);
+
+2. VCT for 88E616x, 88E617x, 88E635x
+	1) New APIs added as defined the following section
+
+3. Supports Auto Scan mode for 88E617x, 88E635x devices
+4. msgIdStartBit in GT_PTP_CONFIG is obsolete.
+5. TRUNK ATU entries for 88E616x, 88E617x, 88E635x are configured properly.
+6. Port mapping macros with GT_USE_SIMPLE_PORT_MAPPING are casted properly.
+7. Deleted to support 6095 family for Ingress Rate Limit with Flow control.
+8. Deleted unused definition in GT_QPRI_TBL_ENTRY.
+9. Device definition for GT_88E6124, GT_88E6325, GT_88E6371 has been corrected to
+	GT_88E6125, GT_88E6321, GT_88E6350, respectively.
+
+
+8) New APIs
+-----------
+
+1. gtAdvVct.c
+
+	1.1) gvctGetAdvCableDiag
+
+	DESCRIPTION
+		This routine perform the advanced virtual cable test (TDR) for the requested
+		port and returns the the status per MDI pair.
+		DSP based cable length is not provided. Please refer to the API, 
+		gvctGetAdvExtendedStatus, for DSP.
+
+	SYNOPSIS
+		GT_STATUS gvctGetAdvCableDiag
+		(
+		    IN  GT_QD_DEV *dev,
+		    IN  GT_LPORT        port,
+		    IN  GT_ADV_VCT_MODE mode,
+		    OUT GT_ADV_CABLE_STATUS *cableStatus
+		)
+
+	ARGUMENTS
+		INPUTS:
+			port - logical port number.
+			mode - advance VCT mode (either First Peak or Maximum Peak)
+
+		OUTPUTS:
+			cableStatus - the copper cable status.
+	
+	RETURNS
+		GT_OK   - on success
+		GT_FAIL - on error
+		GT_NOT_SUPPORTED - if current device does not support this feature.
+
+
+	1.2) gvctGetAdvExtendedStatus
+
+	DESCRIPTION
+		This routine retrieves extended cable status, such as Pair Poloarity,
+		Pair Swap, and Pair Skew. Note that this routine will be success only
+		if 1000Base-T Link is up.
+		DSP based cable length is also provided.
+
+	SYNOPSIS
+		GT_STATUS gvctGetAdvExtendedStatus
+		(
+		    IN  GT_QD_DEV     *dev,
+		    IN  GT_LPORT   port,
+		    OUT GT_ADV_EXTENDED_STATUS *extendedStatus
+		)
+
+
+	ARGUMENTS
+		INPUTS:
+			port - logical port number.
+
+		OUTPUTS:
+			extendedStatus - the extended cable status.
+	
+	RETURNS
+		GT_OK   - on success
+		GT_FAIL - on error
+		GT_NOT_SUPPORTED - if current device does not support this feature.
+	
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/mvCompVer.txt
new file mode 100755
index 0000000..38a9264
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.4

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/802.1Q/802_1q.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/802.1Q/802_1q.c
new file mode 100755
index 0000000..9e4d4b8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/802.1Q/802_1q.c
@@ -0,0 +1,332 @@
+#include <Copyright.h>
+/*******************************************************************************
+* 802_1q.c
+*
+* DESCRIPTION:
+*		There are three 802.1Q modes (GT_SECURE, GT_CHECK, and GT_FALLBACK).
+*		In GT_SECURE mode, the VID for the given frame must be contained in 
+*		the VTU, and the Ingress port must be a member of the VLAN or the 
+*		frame will be discarded.
+*		In GT_CHECK mode, the VID for the given frame must be contained in 
+*		the VTU or the frame will be discarded (the frame will not be 
+*		discarded if the Ingress port is not a memeber of the VLAN).
+*		In GT_FALLBACK mode, Frames are not discarded if their VID's are not 
+*		contained in the VTU. If the frame's VID is contained in the VTU, the 
+*		frame is allowed to exit only those ports that are members of the 
+*		frame's VLAN; otherwise the switch 'falls back' into Port Based VLAN 
+*		mode for the frame (88E6021 Spec. section 3.5.2.1).
+*
+*		Egress Tagging for a member port of a Vlan has the following three 
+*		choices:
+*		1) Unmodified,
+*		2) Untagged, and
+*		3) Tagged
+*
+*		This sample shows how to utilize 802.1Q feature in the device.
+*		For more information, please refer to 88E6021 Spec. section 3.5.2.3
+*
+* DEPENDENCIES:
+*		88E6021 and 88E6063 are supporting this feature.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include "msSample.h"
+
+
+/*****************************************************************************
+* sample802_1qSetup
+*
+* DESCRIPTION:
+*		This routine will show how to configure the switch device so that it 
+*		can be a Home Gateway. This example assumes that all the frames are not 
+*		VLAN-Tagged.
+*		1) to clear VLAN ID Table,
+* 		2) to enable 802.1Q in SECURE mode for each port except CPU port,
+*		3) to enable 802.1Q in FALL BACK mode for the CPU port. 
+*		4) to add VLAN ID 1 with member port 0 and CPU port 
+*		(untagged egress),
+*		5) to add VLAN ID 2 with member the rest of the ports and CPU port 
+*		(untagged egress), 
+*		6) to configure the default vid of each port:
+*		Port 0 have PVID 1, CPU port has PVID 3, and the rest ports have PVID 2.
+*		Note: CPU port's PVID should be unknown VID, so that QuarterDeck can use 
+*		VlanTable (header info) for TX.
+*
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*
+* COMMENTS: 
+*		WARNING!!
+*		If you create just two VLAN for this setup, Trailer mode or Header mode 
+*		for the CPU port has to be enabled and Ethernet driver which connects to
+*		CPU port should understand VLAN-TAGGING, Trailer mode, or Header mode.
+*
+*******************************************************************************/
+GT_STATUS sample802_1qSetup(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_DOT1Q_MODE mode;
+        GT_VTU_ENTRY vtuEntry;
+	GT_U16 vid;
+	GT_LPORT port;
+	int i;
+
+	/*
+	 *	1) Clear VLAN ID Table
+	*/
+	if((status = gvtuFlush(dev)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuFlush returned fail.\n"));
+		return status;
+	}
+
+	/*
+	 *	2) Enable 802.1Q for each port as GT_SECURE mode except CPU port.
+	*/
+	mode = GT_SECURE;
+	for(i=0; i<dev->numOfPorts; i++)
+	{
+		port = i;
+		if (port == dev->cpuPortNum)
+			continue;
+
+		if((status = gvlnSetPortVlanDot1qMode(dev,port, mode)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnSetPortVlanDot1qMode return Failed\n"));
+			return status;
+		}
+	}
+
+	/*
+	 *	3) Enable 802.1Q for CPU port as GT_FALLBACK mode
+	*/
+	if((status = gvlnSetPortVlanDot1qMode(dev, dev->cpuPortNum, GT_FALLBACK)) != GT_OK)
+	{
+		MSG_PRINT(("gvlnSetPortVlanDot1qMode return Failed\n"));
+		return status;
+	}
+
+	/*
+	 *	4) Add VLAN ID 1 with Port 0 and CPU Port as members of the Vlan.
+	*/
+	gtMemSet(&vtuEntry,0,sizeof(GT_VTU_ENTRY));
+	vtuEntry.DBNum = 0;
+	vtuEntry.vid = 1;
+	for(i=0; i<dev->numOfPorts; i++)
+	{
+		port = i;
+		if((i==0) || (port == dev->cpuPortNum))
+			vtuEntry.vtuData.memberTagP[port] = MEMBER_EGRESS_UNTAGGED;
+		else
+			vtuEntry.vtuData.memberTagP[port] = NOT_A_MEMBER;
+	}
+
+	if((status = gvtuAddEntry(dev,&vtuEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuAddEntry returned fail.\n"));
+		return status;
+	}
+
+	/*
+	 *	5) Add VLAN ID 2 with the rest of the Ports and CPU Port as members of 
+	 *	the Vlan.
+	*/
+	gtMemSet(&vtuEntry,0,sizeof(GT_VTU_ENTRY));
+	vtuEntry.DBNum = 0;
+	vtuEntry.vid = 2;
+	for(i=0; i<dev->numOfPorts; i++)
+	{
+		port = i;
+		if(i == 0)
+			vtuEntry.vtuData.memberTagP[port] = NOT_A_MEMBER;
+		else
+			vtuEntry.vtuData.memberTagP[port] = MEMBER_EGRESS_UNTAGGED;
+	}
+
+	if((status = gvtuAddEntry(dev,&vtuEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuAddEntry returned fail.\n"));
+		return status;
+	}
+
+
+	/*
+	 *	6) Configure the default vid for each port.
+	 *	Port 0 has PVID 1, CPU port has PVID 3, and the rest ports have PVID 2.
+	*/
+	for(i=0; i<dev->numOfPorts; i++)
+	{
+		port = i;
+		if(i==0)
+			vid = 1;
+		else if(port == dev->cpuPortNum)
+			vid = 3;
+		else
+			vid = 2;
+
+		if((status = gvlnSetPortVid(dev,port,vid)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnSetPortVid returned fail.\n"));
+			return status;
+		}
+	}
+
+	return GT_OK;
+
+}
+
+
+/*****************************************************************************
+* sampleAdmitOnlyTaggedFrame
+*
+* DESCRIPTION:
+*		This routine will show how to configure a port to accept only vlan
+*		tagged frames.
+*		This routine assumes that 802.1Q has been enabled for the given port.
+*
+* INPUTS:
+*       port - logical port to be configured.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*
+* COMMENTS: 
+*		Some device support Discard Untagged feature. If so, gprtSetDiscardUntagged
+*		function will do the work.
+*
+*******************************************************************************/
+GT_STATUS sampleAdmitOnlyTaggedFrame(GT_QD_DEV *dev,GT_LPORT port)
+{
+	GT_STATUS status;
+    GT_VTU_ENTRY vtuEntry;
+	int i;
+
+	/*
+	 *	0) If device support gprtSetDiscardUntagged, call the function.
+	*/
+	status = gprtSetDiscardUntagged(dev, port, GT_TRUE);
+	switch (status)
+	{
+		case GT_OK:
+			MSG_PRINT(("Done.\n"));
+			return status;
+		case GT_NOT_SUPPORTED:
+			MSG_PRINT(("Try other method.\n"));
+			break;
+		default:
+			MSG_PRINT(("Failure accessing device.\n"));
+			return status;
+	}
+			
+
+	/*
+	 *	1) Add VLAN ID 0xFFF with the given port as a member.
+	*/
+	gtMemSet(&vtuEntry,0,sizeof(GT_VTU_ENTRY));
+	vtuEntry.DBNum = 0;
+	vtuEntry.vid = 0xFFF;
+	for(i=0; i<dev->numOfPorts; i++)
+	{
+		vtuEntry.vtuData.memberTagP[i] = NOT_A_MEMBER;
+	}
+	vtuEntry.vtuData.memberTagP[port] = MEMBER_EGRESS_TAGGED;
+
+	if((status = gvtuAddEntry(dev,&vtuEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuAddEntry returned fail.\n"));
+		return status;
+	}
+
+	/*
+	 *	2) Configure the default vid for the given port with VID 0xFFF
+	*/
+	if((status = gvlnSetPortVid(dev,port,0xFFF)) != GT_OK)
+	{
+		MSG_PRINT(("gvlnSetPortVid returned fail.\n"));
+		return status;
+	}
+
+	return GT_OK;
+
+}
+
+
+/*****************************************************************************
+* sampleDisplayVIDTable
+*
+* DESCRIPTION:
+*		This routine will show how to enumerate each vid entry in the VTU table
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS sampleDisplayVIDTable(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+        GT_VTU_ENTRY vtuEntry;
+	GT_LPORT port;	
+	int portIndex;
+
+	gtMemSet(&vtuEntry,0,sizeof(GT_VTU_ENTRY));
+	vtuEntry.vid = 0xfff;
+	if((status = gvtuGetEntryFirst(dev,&vtuEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gvtuGetEntryCount returned fail.\n"));
+		return status;
+	}
+
+	MSG_PRINT(("DBNum:%i, VID:%i \n",vtuEntry.DBNum,vtuEntry.vid));
+
+	for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+	{
+		port = portIndex;
+
+		MSG_PRINT(("Tag%i:%#x  ",port,vtuEntry.vtuData.memberTagP[port]));
+	}
+	
+	MSG_PRINT(("\n"));
+
+	while(1)
+	{
+		if((status = gvtuGetEntryNext(dev,&vtuEntry)) != GT_OK)
+		{
+			break;
+		}
+
+		MSG_PRINT(("DBNum:%i, VID:%i \n",vtuEntry.DBNum,vtuEntry.vid));
+
+		for(portIndex=0; portIndex<dev->numOfPorts; portIndex++)
+		{
+			port = portIndex;
+
+			MSG_PRINT(("Tag%i:%#x  ",port,vtuEntry.vtuData.memberTagP[port]));
+		}
+	
+		MSG_PRINT(("\n"));
+
+	}
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/802.1Q/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/802.1Q/readme.txt
new file mode 100755
index 0000000..5fb522e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/802.1Q/readme.txt
@@ -0,0 +1,53 @@
+========================================================================

+			802.1Q Feature

+========================================================================

+

+There are three 802.1Q modes (GT_SECURE, GT_CHECK, and GT_FALLBACK).

+In GT_SECURE mode, the VID for the given frame must be contained in 

+the VTU, and the Ingress port must be a member of the VLAN or the 

+frame will be discarded.

+In GT_CHECK mode, the VID for the given frame must be contained in 

+the VTU or the frame will be discarded (the frame will not be 

+discarded if the Ingress port is not a memeber of the VLAN).

+In GT_FALLBACK mode, Frames are not discarded if their VID's are not 

+contained in the VTU. If the frame's VID is contained in the VTU, the 

+frame is allowed to exit only those ports that are members of the 

+frame's VLAN; otherwise the switch 'falls back' into Port Based VLAN 

+mode for the frame (88E6021 Spec. section 3.5.2.1).

+

+Egress Tagging for a member port of a Vlan has the following three 

+choices:

+1) Unmodified,

+2) Untagged, and

+3) Tagged

+

+This sample shows how to utilize 802.1Q feature in the device.

+For more information, please refer to 88E6021 Spec. section 3.5.2.3.

+

+802_1q.c

+	sample802_1qSetup

+		This routine will show

+		1) how to enable 802.1Q feature for each port,

+		2) how to clear VLAN ID (VTU) Table,

+ 		3) how to enable 802.1Q in SECURE mode for each port, 

+		4) how to add VLAN ID 1 with member port 0 and CPU port 

+		(unmodified egress),

+		5) how to add VLAN ID 2 with member the rest of the ports and CPU port 

+		(untagged egress), 

+		6) how to configure the default vid of each port:

+		Port 0 and CPU port have PVID 1 and the rest ports have PVID 2.

+

+	sampleAdmitOnlyTaggedFrame

+		This routine will show how to configure a port to accept only vlan

+		tagged frames.

+		This routine assumes that 802.1Q has been enabled for the given port.

+

+	sampleDisplayVIDTable

+		This routine will show how to enumerate each vid entry in the VTU table

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/advCableTest.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/advCableTest.c
new file mode 100755
index 0000000..c81a6cc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/advCableTest.c
@@ -0,0 +1,202 @@
+#include <Copyright.h>

+/********************************************************************************

+* testApi.c

+*

+* DESCRIPTION:

+*       API test functions

+*

+* DEPENDENCIES:   Platform.

+*

+* FILE REVISION NUMBER:

+*

+*******************************************************************************/

+#include "msSample.h"
+
+GT_STATUS advVctTest(GT_QD_DEV *dev, GT_LPORT port);

+GT_STATUS getAdvExtendedStatus(GT_QD_DEV *dev, GT_LPORT port);

+
+void displayAdvVCTResult

+(

+    GT_ADV_CABLE_STATUS *cableStatus, 

+    int	channel

+)

+{

+	int i;

+

+    switch(cableStatus->cableStatus[channel])

+    {

+        case GT_ADV_VCT_FAIL:

+            MSG_PRINT(("Advanced Cable Test Failed\n"));

+            break;

+        case GT_ADV_VCT_NORMAL:

+            MSG_PRINT(("Cable Test Passed. No problem found.\n"));

+            break;

+        case GT_ADV_VCT_IMP_GREATER_THAN_115:

+            MSG_PRINT(("Cable Test Passed. Impedance is greater than 115 Ohms.\n"));

+            MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableStatus->u[channel].dist2fault));

+            break;

+        case GT_ADV_VCT_IMP_LESS_THAN_85:

+            MSG_PRINT(("Cable Test Passed. Impedance is less than 85 Ohms.\n"));

+            MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableStatus->u[channel].dist2fault));

+            break;

+        case GT_ADV_VCT_OPEN:

+            MSG_PRINT(("Cable Test Passed. Open Cable.\n"));

+            MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableStatus->u[channel].dist2fault));

+            break;

+        case GT_ADV_VCT_SHORT:

+            MSG_PRINT(("Cable Test Passed. Shorted Cable.\n"));

+            MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableStatus->u[channel].dist2fault));

+            break;

+        case GT_ADV_VCT_CROSS_PAIR_SHORT:

+            MSG_PRINT(("Cable Test Passed.\n"));

+    		for(i=0; i<GT_MDI_PAIR_NUM; i++)

+			{

+				if(cableStatus->u[channel].crossShort.channel[i] == GT_TRUE)

+				{

+		            MSG_PRINT(("\tCross pair short with channel %i.\n",i));

+	            	MSG_PRINT(("\tApproximatly %i meters from the tested port.\n",

+									cableStatus->u[channel].crossShort.dist2fault[i]));

+				}

+			}

+            break;

+        default:

+            MSG_PRINT(("Unknown Test Result.\n"));

+            break;

+    }

+}

+

+/* Advanced VCT (TDR) */

+GT_STATUS advVctTest(GT_QD_DEV *dev, GT_LPORT port)

+{

+	GT_STATUS status;

+	int i, j;

+	GT_ADV_VCT_MODE mode;

+	GT_ADV_CABLE_STATUS advCableStatus;

+

+	GT_ADV_VCT_MOD mod[2] = {

+		GT_ADV_VCT_FIRST_PEAK,

+		GT_ADV_VCT_MAX_PEAK

+	};

+
+	char modeStr[2][32] = {

+		"(Adv VCT First PEAK)",

+		"(Adv VCT MAX PEAK)"

+	};

+

+	if (dev == 0)

+	{

+		MSG_PRINT(("GT driver is not initialized\n"));

+		return GT_FAIL;

+	}

+

+	for (j=0; j<2; j++)

+	{

+		mode.mode=mod[j];

+		mode.transChanSel=GT_ADV_VCT_TCS_NO_CROSSPAIR;   

+		mode.sampleAvg = 0;

+		mode.peakDetHyst =0;

+

+		/*

+		 *	Start and get Cable Test Result

+		 */

+		status = GT_OK;

+		if((status = gvctGetAdvCableDiag(dev,port,

+								mode,&advCableStatus)) != GT_OK)

+		{

+			MSG_PRINT(("gvctGetAdvCableDiag return Failed\n"));

+			return status;

+		}

+

+		MSG_PRINT(("\nCable Test Result %s for Port %i\n", modeStr[j], (int)port));

+

+		for(i=0; i<GT_MDI_PAIR_NUM; i++)

+		{

+			MSG_PRINT(("MDI PAIR %i:\n",i));

+			displayAdvVCTResult(&advCableStatus, i); 

+		}

+	}

+

+	return GT_OK;

+}

+

+/* Advanced DSP VCT */

+GT_STATUS getAdvExtendedStatus(GT_QD_DEV *dev, GT_LPORT port)

+{

+	GT_STATUS status;

+	GT_ADV_EXTENDED_STATUS extendedStatus;

+	int i;

+	char ch;

+

+	if (dev == 0)

+	{

+		MSG_PRINT(("GT driver is not initialized\n"));

+		return GT_FAIL;

+	}

+

+	/*

+	 * 	Start getting Extended Information.

+	 */

+	if((status = gvctGetAdvExtendedStatus(dev,port, &extendedStatus)) != GT_OK)

+	{

+		MSG_PRINT(("gvctGetAdvExtendedStatus return Failed\n"));

+		return status;

+	}

+

+	if (!extendedStatus.isValid)

+	{

+		MSG_PRINT(("Not able to get Extended Status.\n"));

+		MSG_PRINT(("Please check if 1000B-T Link is established on Port %i.\n",(int)port));

+		return status;

+	}

+

+	/* Pair Polarity */

+	MSG_PRINT(("Pair Polarity:\n"));

+	for(i=0; i<GT_MDI_PAIR_NUM; i++)

+	{

+		MSG_PRINT(("MDI PAIR %i: %s\n",i,

+					(extendedStatus.pairPolarity[i] == GT_POSITIVE)?"Positive":"Negative"));

+	}

+

+	/* Pair Swap */

+	MSG_PRINT(("Pair Swap:\n"));

+	for(i=0; i<GT_MDI_PAIR_NUM; i++)

+	{

+		switch(extendedStatus.pairSwap[i])

+		{

+			case GT_CHANNEL_A:

+				ch = 'A';

+				break;

+			case GT_CHANNEL_B:

+				ch = 'B';

+				break;

+			case GT_CHANNEL_C:

+				ch = 'C';

+				break;

+			case GT_CHANNEL_D:

+				ch = 'D';

+				break;

+			default:

+				MSG_PRINT(("Error: reported unknown Pair Swap %i\n",extendedStatus.pairSwap[i]));

+				ch = 'U';

+				break;

+		}

+

+		MSG_PRINT(("MDI PAIR %i: Channel %c\n",i,ch));

+	}

+

+	/* Pair Polarity */

+	MSG_PRINT(("Pair Skew:\n"));

+	for(i=0; i<GT_MDI_PAIR_NUM; i++)

+	{

+		MSG_PRINT(("MDI PAIR %i: %ins\n",i,(int)extendedStatus.pairSkew[i]));

+	}

+

+	/* Pair Polarity */

+	MSG_PRINT(("Cable Len:\n"));

+	for(i=0; i<GT_MDI_PAIR_NUM; i++)

+	{

+		MSG_PRINT(("MDI PAIR %i: approximately %im\n",i,(int)extendedStatus.cableLen[i]));

+	}

+

+	return GT_OK;

+}

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/cableTest.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/cableTest.c
new file mode 100755
index 0000000..f1d21e7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/cableTest.c
@@ -0,0 +1,110 @@
+#include <Copyright.h>
+/********************************************************************************
+* cableTest.c
+*
+* DESCRIPTION:
+*		This sample shows how to run Virtual Cable Test and how to use the 
+*		test result.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*
+* COMMENTS:
+*******************************************************************************/
+
+#include "msSample.h"
+
+void sampleDisplayCableTestResult
+(
+	GT_TEST_STATUS *cableStatus, 
+	GT_CABLE_LEN *cableLen
+)
+{
+	switch(*cableStatus)
+	{
+		case GT_TEST_FAIL:
+			MSG_PRINT(("Cable Test Failed\n"));
+			break;
+		case GT_NORMAL_CABLE:
+			MSG_PRINT(("Cable Test Passed. No problem found.\n"));
+			switch(cableLen->normCableLen)
+			{
+				case GT_LESS_THAN_50M:
+					MSG_PRINT(("Cable Length is less than 50M.\n"));
+					break;
+				case GT_50M_80M:
+					MSG_PRINT(("Cable Length is between 50M and 80M.\n"));
+					break;
+				case GT_80M_110M:
+					MSG_PRINT(("Cable Length is between 80M and 110M.\n"));
+					break;
+				case GT_110M_140M:
+					MSG_PRINT(("Cable Length is between 110M and 140M.\n"));
+					break;
+				case GT_MORE_THAN_140:
+					MSG_PRINT(("Cable Length is over 140M.\n"));
+					break;
+				default:
+					MSG_PRINT(("Cable Length is unknown.\n"));
+					break;
+			}
+			break;
+		case GT_IMPEDANCE_MISMATCH:
+			MSG_PRINT(("Cable Test Passed. Cable has Impedance Mismatch .\n"));
+			MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableLen->errCableLen));
+			break;
+		case GT_OPEN_CABLE:
+			MSG_PRINT(("Cable Test Passed. Cable is open.\n"));
+			MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableLen->errCableLen));
+			break;
+		case GT_SHORT_CABLE:
+			MSG_PRINT(("Cable Test Passed. Cable is short.\n"));
+			MSG_PRINT(("Approximatly %i meters from the tested port.\n",cableLen->errCableLen));
+			break;
+		default:
+			MSG_PRINT(("Unknown Test Result.\n"));
+			break;
+	}
+}
+
+
+GT_STATUS sampleCableTest(GT_QD_DEV *dev,GT_LPORT port)
+{
+	GT_STATUS status;
+    GT_CABLE_STATUS cableStatus;
+	int i;
+		
+	/*
+	 *	Start and get Cable Test Result
+	*/
+	if((status = gvctGetCableDiag(dev,port, &cableStatus)) != GT_OK)
+	{
+		MSG_PRINT(("gvctGetCableDiag return Failed\n"));
+		return status;
+	}
+
+	MSG_PRINT(("Cable Test Result for Port %i\n",port));
+
+	if(cableStatus.phyType == PHY_100M)
+	{
+		MSG_PRINT(("RX PAIR :\n"));
+		sampleDisplayCableTestResult(&cableStatus.cableStatus[MDI_RX_PAIR],
+									&cableStatus.cableLen[MDI_RX_PAIR]);
+		MSG_PRINT(("TX PAIR :\n"));
+		sampleDisplayCableTestResult(&cableStatus.cableStatus[MDI_TX_PAIR],
+									&cableStatus.cableLen[MDI_TX_PAIR]);
+	}
+	else /* phyType must be PHY_1000M */
+	{
+		for(i=0; i<GT_MDI_PAIR_NUM; i++)
+		{
+			MSG_PRINT(("MDI PAIR %i:\n",i));
+			sampleDisplayCableTestResult(&cableStatus.cableStatus[i],
+									&cableStatus.cableLen[i]);
+		}
+	}
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/readme.txt
new file mode 100755
index 0000000..8779e7c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CableTest/readme.txt
@@ -0,0 +1,19 @@
+========================================================================

+		Cable Test

+========================================================================

+

+This sample shows how to run VCT(Virtual Cable Tester).

+

+Notes: 

+

+cableTest.c

+	The function, sampleCableTest, can be used to run and display the result.

+

+advCableTest.c

+	The functions, advVctTest and getAdvExtendedStatus, can be used to run advanced VCT and display the result.

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CrossChipTrunk/crossChipTrunk.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CrossChipTrunk/crossChipTrunk.c
new file mode 100755
index 0000000..7431eb3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CrossChipTrunk/crossChipTrunk.c
@@ -0,0 +1,341 @@
+#include <Copyright.h>
+/********************************************************************************
+* crossChipTrunk.c
+*
+* DESCRIPTION:
+*		This sample shows how to setup the Cross Chip TRUNK
+*		
+* DEPENDENCIES:
+*		Please check the device's spec. if the device supports this feature.
+*		At the moment this sample was written, 88E6095 was the only device support
+*		this feature.
+*
+* FILE REVISION NUMBER:
+*
+* COMMENTS:
+*******************************************************************************/
+
+#include "msSample.h"
+
+#define N_OF_QD_DEVICES	2
+#define MAX_PORT_IN_TRUNK 4
+
+/* qdMultiDev is defined in sample/MultiDevice/msApiInit.c */
+extern GT_QD_DEV       *qdMultiDev[N_OF_QD_DEVICES];	
+
+typedef struct _TRUNK_SET {
+	GT_U32	devIndex;
+	GT_U32	port;
+} TRUNK_SET;
+
+typedef struct _TRUNK_MEMBER {
+	GT_U32	trunkId;
+	GT_U32	nTrunkPort;
+	TRUNK_SET trunkSet[MAX_PORT_IN_TRUNK];
+} TRUNK_MEMBER;
+
+GT_STATUS sampleCrossChipTrunk(GT_QD_DEV *dev[], TRUNK_MEMBER* tm);
+
+/*
+	Setup Trunk with the following member ports:
+		Port 0,1,2 of Device 0, and
+		Port 0 of Device 1,
+	where Device 0 is the first Switch Device Structure in qdMultiDev array 
+	and Device 1 is the second Switch Device Structure in qdMultiDev array.
+*/
+GT_STATUS crossChipTrunkSetup()
+{
+	TRUNK_MEMBER tm;
+
+	tm.trunkId = 1;
+	tm.nTrunkPort = 4;
+	tm.trunkSet[0].devIndex = 0;
+	tm.trunkSet[0].port = 0;
+	tm.trunkSet[1].devIndex = 0;
+	tm.trunkSet[1].port = 1;
+	tm.trunkSet[2].devIndex = 0;
+	tm.trunkSet[2].port = 2;
+	tm.trunkSet[3].devIndex = 1;
+	tm.trunkSet[3].port = 0;
+
+	return sampleCrossChipTrunk(qdMultiDev, &tm);
+}
+
+GT_STATUS sampleCrossChipTrunk(GT_QD_DEV *dev[], TRUNK_MEMBER* tm)
+{
+	GT_STATUS status;
+	int i,j,index;
+	GT_U32 mask, trunkId;
+	TRUNK_SET* ts;
+	GT_U32 portVec[N_OF_QD_DEVICES];	
+	GT_U32 casecadeVec = 0xC0;	/* Port 6 and 7. ToDo : get this value from user or device */
+
+	/*
+	 *	Enable Trunk for each member of the Trunk and set the Trunk ID (1).
+	*/ 
+
+	printf("Setting TRUNK\n");
+	printf("Trunk ID : %i\n",(unsigned int)tm->trunkId);
+	printf("N Ports  : %i\n",(unsigned int)tm->nTrunkPort);
+	printf("1st Port  : Dev %i, Port %i\n",
+			(unsigned int)tm->trunkSet[0].devIndex,(unsigned int)tm->trunkSet[0].port);
+	printf("2nd Port  : Dev %i, Port %i\n",
+			(unsigned int)tm->trunkSet[1].devIndex,(unsigned int)tm->trunkSet[1].port);
+	printf("3rd Port  : Dev %i, Port %i\n",
+			(unsigned int)tm->trunkSet[2].devIndex,(unsigned int)tm->trunkSet[2].port);
+	printf("4th Port  : Dev %i, Port %i\n",
+			(unsigned int)tm->trunkSet[3].devIndex,(unsigned int)tm->trunkSet[3].port);
+
+	trunkId = tm->trunkId;
+
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+		portVec[i] = 0;
+
+	printf("Enabling TRUNK for each member port.\n");
+	for(i=0; i<tm->nTrunkPort; i++)
+	{
+		ts = &tm->trunkSet[i];
+
+		if(ts->devIndex >= N_OF_QD_DEVICES)
+		{
+			printf("Device %i is supported. Max Device Number is %i\n",(unsigned int)ts->devIndex,N_OF_QD_DEVICES-1);
+			return GT_FAIL;
+		}
+
+		if((dev[ts->devIndex] == NULL) || (!dev[ts->devIndex]->devEnabled))
+		{
+			printf("Device %i is not initialized\n",(unsigned int)ts->devIndex);
+			return GT_FAIL;
+		}
+
+		/* enabled trunk on the given port */
+		if((status = gprtSetTrunkPort(dev[ts->devIndex],ts->port,GT_TRUE,trunkId)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+			return status;
+		}
+
+		portVec[ts->devIndex] |= (1 << ts->port);
+	}
+
+	/*
+	 *	Set Trunk Route Table for the given Trunk ID.
+	*/ 
+	printf("Setting TRUNK Routing Table\n");
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		if((dev[i] == NULL) || (!dev[i]->devEnabled))
+		{
+			printf("Device %i is not initialized\n",i);
+			break;
+		}
+
+		if((status = gsysSetTrunkRouting(dev[i],trunkId,portVec[i]|casecadeVec)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkRouting return Failed\n"));
+			return status;
+		}
+	}
+
+	/*
+	 *	Set Trunk Mask Table for load balancing.
+	*/ 
+	printf("Setting TRUNK Mask for Load Balancing\n");
+	for(i=0; i<8; i++)
+	{
+		/* choose a port to be used for the given addr combo index */
+		index = i % tm->nTrunkPort;
+		ts = &tm->trunkSet[index];
+		
+		for(j=0; j<N_OF_QD_DEVICES; j++)
+		{
+			if((dev[j] == NULL) || (!dev[j]->devEnabled))
+			{
+				printf("Device %i is not initialized\n",j);
+				continue;
+			}
+
+			if(portVec[j] == 0)
+				continue;
+
+			if((status = gsysGetTrunkMaskTable(dev[j],i,&mask)) != GT_OK)
+			{
+				MSG_PRINT(("gsysGetTrunkMaskTable return Failed\n"));
+				return status;
+			}
+
+			mask &= ~portVec[j];
+
+			if(ts->devIndex == j)
+				mask |= (1 << ts->port);
+			
+			if((status = gsysSetTrunkMaskTable(dev[j],i,mask)) != GT_OK)
+			{
+				MSG_PRINT(("gsysSetTrunkMaskTable return Failed\n"));
+				return status;
+			}
+		}
+	}
+	
+	return GT_OK;
+}
+
+
+
+/*
+	Assumption 1: Device ID, Cascading Port, CPU Port, and Interswitch Port are
+		already set properly. For more information, please refer to the 
+		sample/MultiDevice/msApiInit.c
+
+	Assumption 2: Port 0,1,2 of Device 0 and Port 0 of Device 1 are member of a 
+		trunk with Trunk ID 1.
+*/
+
+GT_STATUS sampleFixedCrossChipTrunk(GT_QD_DEV *dev[])
+{
+	GT_STATUS status;
+	int i;
+	GT_U32 mask, trunkBit, trunkId;
+
+	/*
+	 *	Enable Trunk for each member of the Trunk and set the Trunk ID (1).
+	*/ 
+
+	trunkId = 1;
+
+	if((dev[0] == NULL) || (!dev[0]->devEnabled))
+	{
+		printf("Device 0 is not initialized\n");
+		return GT_FAIL;
+	}
+	if((dev[1] == NULL) || (!dev[1]->devEnabled))
+	{
+		printf("Device 1 is not initialized\n");
+		return GT_FAIL;
+	}
+
+	/* setup for Device 0 port 0 */
+	if((status = gprtSetTrunkPort(dev[0],0,GT_TRUE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+		return status;
+	}
+
+	/* setup for Device 0 port 1 */
+	if((status = gprtSetTrunkPort(dev[0],1,GT_TRUE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+		return status;
+	}
+
+	/* setup for Device 0 port 2 */
+	if((status = gprtSetTrunkPort(dev[0],2,GT_TRUE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+		return status;
+	}
+
+	/* setup for Device 1 port 0 */
+	if((status = gprtSetTrunkPort(dev[1],0,GT_TRUE,trunkId)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrunkPort return Failed\n"));
+		return status;
+	}
+
+
+	/*
+	 *	Set Trunk Route Table for the given Trunk ID.
+	*/ 
+
+	/* setup for Device 0, trunk ID 1 : port 0,1,2, and 9 (cascading port, assumption1) */
+	if((status = gsysSetTrunkRouting(dev[0],trunkId,0x7|0x200)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSetTrunkRouting return Failed\n"));
+		return status;
+	}
+
+	/* setup for Device 1, trunk ID 1 : port 0, and 8 (cascading port, assumption1) */
+	if((status = gsysSetTrunkRouting(dev[1],trunkId,0x1|0x100)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSetTrunkRouting return Failed\n"));
+		return status;
+	}
+
+
+	/*
+	 *	Set Trunk Mask Table for load balancing.
+	*/ 
+
+	/*
+	   Trunk Mask Table for Device 0:
+ 
+						10	9	8	7	6	5	4	3	2	1	0
+	   TrunkMask[0]		1	1	1	1	1	1	1	1	0	0	1
+	   TrunkMask[1]		1	1	1	1	1	1	1	1	0	1	0
+	   TrunkMask[2]		1	1	1	1	1	1	1	1	1	0	0
+	   TrunkMask[3]		1	1	1	1	1	1	1	1	0	0	0
+	   TrunkMask[4]		1	1	1	1	1	1	1	1	0	0	1
+	   TrunkMask[5]		1	1	1	1	1	1	1	1	0	1	0
+	   TrunkMask[6]		1	1	1	1	1	1	1	1	1	0	0
+	   TrunkMask[7]		1	1	1	1	1	1	1	1	0	0	0
+
+
+	   Trunk Mask Table for Device 1:
+ 
+						10	9	8	7	6	5	4	3	2	1	0
+	   TrunkMask[0]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[1]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[2]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[3]		1	1	1	1	1	1	1	1	1	1	1
+	   TrunkMask[4]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[5]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[6]		1	1	1	1	1	1	1	1	1	1	0
+	   TrunkMask[7]		1	1	1	1	1	1	1	1	1	1	1
+
+	*/
+
+	/* setup for Device 0 */
+	for(i=0; i<8; i++)
+	{
+		if((i%4) == 3)
+		{
+			trunkBit = 0;
+		}
+		else
+		{
+			trunkBit = 1 << (i%4);
+		}		
+
+		mask = 0x7F8 | trunkBit;
+	
+		if((status = gsysSetTrunkMaskTable(dev[0],i,mask)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkMaskTable return Failed\n"));
+			return status;
+		}
+
+	}
+	
+	/* setup for Device 1 */
+	for(i=0; i<8; i++)
+	{
+		if((i%4) == 3)
+		{
+			trunkBit = 1;
+		}
+		else
+		{
+			trunkBit = 0;
+		}		
+
+		mask = 0x7FE | trunkBit;
+	
+		if((status = gsysSetTrunkMaskTable(dev[1],i,mask)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkMaskTable return Failed\n"));
+			return status;
+		}
+
+	}
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CrossChipTrunk/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CrossChipTrunk/readme.txt
new file mode 100755
index 0000000..22bf5ec
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/CrossChipTrunk/readme.txt
@@ -0,0 +1,19 @@
+========================================================================

+		Setup for Cross Chip Trunk

+========================================================================

+

+This sample shows how to setup the Cross Chip Trunk with the following 
+assumptions.
+	Assumption 1: Device ID, Cascading Port, CPU Port, and Interswitch Port are
+		already set properly. For more information, please refer to the 
+		sample/MultiDevice/msApiInit.c
+
+	Assumption 2: Port 0,1,2 of Device 0 and Port 0 of Device 1 are member of a 
+		trunk with Trunk ID, 1.
+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/FlowControl/flowCtrl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/FlowControl/flowCtrl.c
new file mode 100755
index 0000000..e5c6381
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/FlowControl/flowCtrl.c
@@ -0,0 +1,55 @@
+#include <Copyright.h>
+/********************************************************************************
+* flowCtrl.c
+*
+* DESCRIPTION:
+*       Sample program which will show how to Enable or Disable Flow Control of 
+*		the given Port of the QuaterDeck.
+*		
+*
+* DEPENDENCIES:   None.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include "msSample.h"
+
+/*
+ *	Enable or Disable Flow Control of the given port.
+ *	Input - port : port to be programmed.
+ *			enalble : either Enable or Disable.
+*/
+GT_STATUS sampleSetFlowControl(GT_QD_DEV *dev, GT_LPORT port, GT_BOOL enable)
+{
+	GT_STATUS status;
+
+	/* 
+	 *	Program Phy's Pause bit in AutoNegotiation Advertisement Register.
+	 */
+	if((status = gprtSetPause(dev,port,enable)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetForceFC return Failed\n"));
+		return status;
+	}
+
+	/* 
+	 *	Restart AutoNegotiation of the given Port's phy
+	 */
+	if((status = gprtPortRestartAutoNeg(dev,port)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetForceFC return Failed\n"));
+		return status;
+	}
+
+	/* 
+	 *	Program Port's Flow Control.
+	 */
+	if((status = gprtSetForceFc(dev,port,enable)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetForceFC return Failed\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/FlowControl/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/FlowControl/readme.txt
new file mode 100755
index 0000000..2a6ed76
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/FlowControl/readme.txt
@@ -0,0 +1,17 @@
+========================================================================

+		Flow Contorl Enable or Disable

+========================================================================

+

+Flow Control Setup requires multiple of DSDT API calls which can be

+examined in this sample.

+

+flowCtrl.c

+	sampleSetFlowControl can be used to enable or disable flow control

+	of the given port

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Header/header.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Header/header.c
new file mode 100755
index 0000000..a936e0f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Header/header.c
@@ -0,0 +1,45 @@
+#include <Copyright.h>
+/********************************************************************************
+* header.c
+*
+* DESCRIPTION:
+*		This sample shows how to enable/disable CPU port's ingress and egress 
+*		Header mode. For more information about Header mode, please refer to 
+*		88E6063 Data Book. Header mode sould be handled by Ethernet Device/Driver
+*		as well, since 88E6063, with header mode enabled, sends out a packet with
+*		header, which cannot be recognized by regular Ethernet device/driver,
+*		and expects header for every received packet.
+*
+* DEPENDENCIES:
+*		88E6051, 88E6052, and 88E6021 are not supporting this feature.
+*
+* FILE REVISION NUMBER:
+*
+* COMMENTS:
+*		WARNING!!
+*		When Header mode for the CPU port is enabled, Ethernet Device/Driver 
+*		which connects to the CPU port should understand Header Format.
+*		If Ethernet Device does not know about Header mode, then user may set
+*		the device to Promiscuous mode in order to receive packets from QD's CPU
+*		port. After that, it is Ethernet Device Driver's responsibility to handle
+*		Header properly.
+*******************************************************************************/
+
+#include "msSample.h"
+
+GT_STATUS sampleHeaderEnable(GT_QD_DEV *dev,GT_BOOL en)
+{
+	GT_STATUS status;
+
+	/*
+	 *	Enable/Disable Header mode
+	*/
+	if((status = gprtSetHeaderMode(dev,dev->cpuPortNum, en)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetHeaderMode return Failed\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Header/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Header/readme.txt
new file mode 100755
index 0000000..0568397
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Header/readme.txt
@@ -0,0 +1,26 @@
+========================================================================

+		CPU Header Mode Enable or Disable

+========================================================================

+

+This sample shows how to enable/disable header mode for CPU port.

+For more information about header mode, please refer to 88E6063 Spec.

+section 3.5.10 and section 3.7.5.

+

+Notes: 

+When Header mode for the CPU port is enabled, Ethernet Device/Driver 

+which is directly connected to the CPU port should understand Header Format.

+If Ethernet Device does not know about Header mode, then user may set
+the device to Promiscuous mode in order to receive packets from switch's CPU
+port. After that, it is Ethernet Device Driver's responsibility to handle
+Header properly.

+

+header.c

+	sampleHeaderEnable can be used to enable or disable CPU port's

+	header mode

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Include/msSample.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Include/msSample.h
new file mode 100755
index 0000000..310df7e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Include/msSample.h
@@ -0,0 +1,147 @@
+#include <Copyright.h>
+/********************************************************************************
+* msSample.h
+*
+* DESCRIPTION:
+*       Types definitions for Sample program
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __pfTesth
+#define __pfTesth
+
+#ifdef _VXWORKS
+#include "vxWorks.h"
+#include "logLib.h"
+#endif
+#include "stdio.h"
+#include "stdarg.h"
+#include "stdlib.h"
+#include "time.h"
+#include "string.h"
+
+#include "msApi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef GT_U32 (*GT_API_VOID) (GT_QD_DEV*);
+typedef int (*GT_CMP_FUNC) (void*, int, int);
+
+typedef GT_STATUS (*GT_API_SET_BOOL) (GT_QD_DEV*, GT_BOOL);
+typedef GT_STATUS (*GT_API_GET_BOOL) (GT_QD_DEV*, GT_BOOL*);
+
+typedef GT_STATUS (*GT_API_MAC_ADDR) (GT_QD_DEV*, GT_ETHERADDR*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_BOOL) (GT_QD_DEV*, GT_LPORT,GT_BOOL);
+typedef GT_STATUS (*GT_API_GET_PORT_BOOL) (GT_QD_DEV*, GT_LPORT,GT_BOOL*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U16) (GT_QD_DEV*, GT_LPORT,GT_U16);
+typedef GT_STATUS (*GT_API_GET_PORT_U16) (GT_QD_DEV*, GT_LPORT,GT_U16*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U32) (GT_QD_DEV*, GT_LPORT,GT_U32);
+typedef GT_STATUS (*GT_API_GET_PORT_U32) (GT_QD_DEV*, GT_LPORT,GT_U32*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U8) (GT_QD_DEV*, GT_LPORT,GT_U8);
+typedef GT_STATUS (*GT_API_GET_PORT_U8) (GT_QD_DEV*, GT_LPORT,GT_U8*);
+
+typedef struct _TEST_API
+{
+	union
+	{
+		GT_API_SET_BOOL bool;
+		GT_API_MAC_ADDR mac;
+		GT_API_SET_PORT_BOOL port_bool;
+		GT_API_SET_PORT_U8 port_u8;
+		GT_API_SET_PORT_U16 port_u16;
+		GT_API_SET_PORT_U32 port_u32;
+	} setFunc;
+
+	union
+	{
+		GT_API_GET_BOOL bool;
+		GT_API_MAC_ADDR mac;
+		GT_API_GET_PORT_BOOL port_bool;
+		GT_API_GET_PORT_U8 port_u8;
+		GT_API_GET_PORT_U16 port_u16;
+		GT_API_GET_PORT_U32 port_u32;
+	} getFunc;
+
+}TEST_API;
+
+typedef struct _TEST_STRUCT
+{
+	char strTest[16];
+	GT_API_VOID testFunc;
+	GT_U32 testResults;
+} TEST_STRUCT;
+
+#define MSG_PRINT(x) testPrint x
+
+#define TEST_MAC_ENTRIES	32
+typedef struct _TEST_ATU_ENTRY
+{
+	GT_ATU_ENTRY atuEntry[TEST_MAC_ENTRIES];
+}TEST_ATU_ENTRY;
+
+typedef struct _ATU_ENTRY_INFO
+{
+	GT_ATU_ENTRY atuEntry;
+	GT_U16	hash;
+	GT_U16	bucket;
+} ATU_ENTRY_INFO;
+
+extern GT_SYS_CONFIG   pfTestSysCfg;
+extern ATU_ENTRY_INFO *gAtuEntry;
+extern GT_QD_DEV       *dev;
+
+GT_STATUS qdStart(int,int,int);
+GT_STATUS qdSimSetPhyInt(unsigned int portNumber, unsigned short u16Data);
+GT_STATUS qdSimSetGlobalInt(unsigned short u16Data);
+
+GT_STATUS testAll(GT_QD_DEV*);
+void testPrint(char* format, ...);
+
+extern FGT_INT_HANDLER qdIntHandler;
+
+int vtuEntryCmpFunc(void* buf, int a, int b);
+int atuEntryCmpFunc(void* buf, int a, int b);
+GT_STATUS gtSort(int list[], GT_CMP_FUNC cmpFunc, void* buf, GT_U32 len);
+GT_U16 createATUList(GT_QD_DEV *dev, TEST_ATU_ENTRY atuEntry[], GT_U16 entrySize, GT_U16 dbNumSize, 
+					GT_U16 sameMacsInEachDb, GT_U16 bSize);
+GT_STATUS testFillUpAtu(GT_QD_DEV *dev, ATU_ENTRY_INFO *atuEntry, GT_U8 atuSize, 
+					GT_U8 dbNum, GT_U16 first2Bytes, GT_ATU_UC_STATE state);
+GT_U16 runQDHash(GT_U8* eaddr, GT_U16 dbNum, int bSize, GT_U16* pHash, 
+					GT_U16* preBucket, GT_U16* posBucket);
+GT_STATUS testDisplayATUList();
+
+#undef USE_SEMAPHORE
+
+#ifdef USE_SEMAPHORE
+GT_SEM osSemCreate(GT_SEM_BEGIN_STATE state);
+GT_STATUS osSemDelete(GT_SEM smid);
+GT_STATUS osSemWait(GT_SEM smid, GT_U32 timeOut);
+GT_STATUS osSemSignal(GT_SEM smid);
+#endif
+
+GT_BOOL gtBspReadMii ( GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                      unsigned int* value);
+GT_BOOL gtBspWriteMii ( GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                       unsigned int value);
+void gtBspMiiInit();
+
+GT_BOOL qdSimRead (GT_QD_DEV* dev,unsigned int portNumber , unsigned int miiReg, unsigned int* value);
+GT_BOOL qdSimWrite (GT_QD_DEV* dev,unsigned int portNumber , unsigned int miiReg, unsigned int value);
+void qdSimInit();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif   /* __pfTesth */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Include/qdSimRegs.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Include/qdSimRegs.h
new file mode 100755
index 0000000..7976f8b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Include/qdSimRegs.h
@@ -0,0 +1,131 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtSimRegs.h
+*
+* DESCRIPTION:
+*       This file includes the declaration of the struct to hold the addresses
+*       of switch (global & per-port).
+*
+* DEPENDENCIES:
+*       QuarterDeck register MAP.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __qdSimRegsh
+#define __qdSimRegsh
+
+/* QuarterDeck Per Port Registers */
+#define QD_REG_PORT_STATUS		0x0
+#define QD_REG_SWITCH_ID		0x3
+#define QD_REG_PORT_CONTROL		0x4
+#define QD_REG_PORT_VLAN_MAP	0x6
+#define QD_REG_PVID				0x7
+#define QD_REG_RATE_CTRL		0xA
+#define QD_REG_PAV				0xB
+#define QD_REG_RXCOUNTER		0x10
+#define QD_REG_TXCOUNTER		0x11
+#define QD_REG_Q_COUNTER		0x1B
+
+/* QuarterDeck Global Registers */
+#define QD_REG_GLOBAL_STATUS	0x0
+#define QD_REG_MACADDR_01		0x1
+#define QD_REG_MACADDR_23		0x2
+#define QD_REG_MACADDR_45		0x3
+#define QD_REG_GLOBAL_CONTROL	0x4
+
+/* the following VTU entries are added for Fullsail and Clippership */
+#define QD_REG_VTU_OPERATION		0x5
+#define QD_REG_VTU_VID_REG		0x6
+#define QD_REG_VTU_DATA1_REG		0x7
+#define QD_REG_VTU_DATA2_REG		0x8
+#define QD_REG_VTU_DATA3_REG		0x9
+#define QD_REG_STATS_OPERATION		0x1D
+#define QD_REG_STATS_COUNTER3_2		0x1E
+#define QD_REG_STATS_COUNTER1_0		0x1F
+ 
+#define QD_REG_ATU_CONTROL		0xA
+#define QD_REG_ATU_OPERATION	0xB
+#define QD_REG_ATU_DATA_REG		0xC
+#define QD_REG_ATU_MAC_BASE		0xD
+#define QD_REG_ATU_MAC_01		0xD
+#define QD_REG_ATU_MAC_23		0xE
+#define QD_REG_ATU_MAC_45		0xF
+#define QD_REG_IP_PRI_BASE		0x10
+#define QD_REG_IP_PRI_REG0		0x10
+#define QD_REG_IP_PRI_REG1		0x11
+#define QD_REG_IP_PRI_REG2		0x12
+#define QD_REG_IP_PRI_REG3		0x13
+#define QD_REG_IP_PRI_REG4		0x14
+#define QD_REG_IP_PRI_REG5		0x15
+#define QD_REG_IP_PRI_REG6		0x16
+#define QD_REG_IP_PRI_REG7		0x17
+#define QD_REG_IEEE_PRI			0x18
+
+/* Definition for QD_REG_PORT_STATUS */
+#define QD_PORT_STATUS_DUPLEX	0x200
+
+/* Definitions for MIB Counter */
+#define GT_STATS_NO_OP			0x0
+#define GT_STATS_FLUSH_ALL		0x1
+#define GT_STATS_FLUSH_PORT		0x2
+#define GT_STATS_READ_COUNTER		0x4
+#define GT_STATS_CAPTURE_PORT		0x5
+
+#define QD_PHY_CONTROL_REG				0
+#define QD_PHY_AUTONEGO_AD_REG			4
+#define QD_PHY_NEXTPAGE_TX_REG			7
+#define QD_PHY_SPEC_CONTROL_REG			16
+#define QD_PHY_INT_ENABLE_REG			18
+#define QD_PHY_INT_STATUS_REG			19
+#define QD_PHY_INT_PORT_SUMMARY_REG		20
+
+/* Bit Definition for QD_PHY_CONTROL_REG */
+#define QD_PHY_RESET			0x8000
+#define QD_PHY_LOOPBACK			0x4000
+#define QD_PHY_SPEED			0x2000
+#define QD_PHY_AUTONEGO			0x1000
+#define QD_PHY_POWER			0x800
+#define QD_PHY_ISOLATE			0x400
+#define QD_PHY_RESTART_AUTONEGO		0x200
+#define QD_PHY_DUPLEX			0x100
+
+#define QD_PHY_POWER_BIT				11
+#define QD_PHY_RESTART_AUTONEGO_BIT		9
+
+/* Bit Definition for QD_PHY_AUTONEGO_AD_REG */
+#define QD_PHY_NEXTPAGE			0x8000
+#define QD_PHY_REMOTEFAULT		0x4000
+#define QD_PHY_PAUSE			0x400
+#define QD_PHY_100_FULL			0x100
+#define QD_PHY_100_HALF			0x80
+#define QD_PHY_10_FULL			0x40
+#define QD_PHY_10_HALF			0x20
+
+#define QD_PHY_MODE_AUTO_AUTO	(QD_PHY_100_FULL | QD_PHY_100_HALF | QD_PHY_10_FULL | QD_PHY_10_HALF)
+#define QD_PHY_MODE_100_AUTO	(QD_PHY_100_FULL | QD_PHY_100_HALF)
+#define QD_PHY_MODE_10_AUTO		(QD_PHY_10_FULL | QD_PHY_10_HALF)
+#define QD_PHY_MODE_AUTO_FULL	(QD_PHY_100_FULL | QD_PHY_10_FULL)
+#define QD_PHY_MODE_AUTO_HALF	(QD_PHY_100_HALF | QD_PHY_10_HALF)
+
+#define QD_PHY_MODE_100_FULL	QD_PHY_100_FULL
+#define QD_PHY_MODE_100_HALF	QD_PHY_100_HALF
+#define QD_PHY_MODE_10_FULL		QD_PHY_10_FULL	
+#define QD_PHY_MODE_10_HALF		QD_PHY_10_HALF	
+
+/* Bit definition for QD_PHY_INT_ENABLE_REG */
+#define QD_PHY_INT_SPEED_CHANGED		0x4000
+#define QD_PHY_INT_DUPLEX_CHANGED		0x2000
+#define QD_PHY_INT_PAGE_RECEIVED		0x1000
+#define QD_PHY_INT_AUTO_NEG_COMPLETED		0x800
+#define QD_PHY_INT_LINK_STATUS_CHANGED		0x400
+#define QD_PHY_INT_SYMBOL_ERROR			0x200
+#define QD_PHY_INT_FALSE_CARRIER		0x100
+#define QD_PHY_INT_FIFO_FLOW			0x80
+#define QD_PHY_INT_CROSSOVER_CHANGED		0x40
+#define QD_PHY_INT_POLARITY_CHANGED		0x2
+#define QD_PHY_INT_JABBER			0x1
+
+#endif /* __qdSimRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/ev96122mii.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/ev96122mii.c
new file mode 100755
index 0000000..2c3b88d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/ev96122mii.c
@@ -0,0 +1,213 @@
+#include <Copyright.h>
+/********************************************************************************
+* ev96122mii.c
+*
+* DESCRIPTION:
+*       SMI access routines for EV-96122 board
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include <msSample.h>
+
+/*
+ * For each platform, all we need is 
+ * 1) Assigning functions into 
+ * 		fgtReadMii : to read MII registers, and
+ * 		fgtWriteMii : to write MII registers.
+ *
+ * 2) Register Interrupt (Not Defined Yet.)
+*/
+
+/* 
+ *  EV-96122 Specific Definition
+*/
+
+#define SMI_OP_CODE_BIT_READ                    1
+#define SMI_OP_CODE_BIT_WRITE                   0
+#define SMI_BUSY                                1<<28
+#define READ_VALID                              1<<27
+
+#ifdef FIREFOX
+#define ETHER_SMI_REG                   0x10 
+#define internalRegBaseAddr 0x80008000
+#define NONE_CACHEABLE		0x00000000
+#define CACHEABLE			0x00000000
+#define SMI_RX_TIMEOUT		1000
+#else
+#define ETHER_SMI_REG                   0x080810 
+#define internalRegBaseAddr 0x14000000
+#define NONE_CACHEABLE		0xa0000000
+#define CACHEABLE			0x80000000
+#define SMI_RX_TIMEOUT		10000000
+#endif
+
+typedef unsigned int              SMI_REG;
+
+#ifdef LE /* Little Endian */          	
+#define SHORT_SWAP(X) (X)
+#define WORD_SWAP(X) (X)
+#define LONG_SWAP(X) ((l64)(X))
+
+#else    /* Big Endian */
+#define SHORT_SWAP(X) ((X <<8 ) | (X >> 8))
+
+#define WORD_SWAP(X) (((X)&0xff)<<24)+      \
+                    (((X)&0xff00)<<8)+      \
+                    (((X)&0xff0000)>>8)+    \
+                    (((X)&0xff000000)>>24)
+
+#define LONG_SWAP(X) ( (l64) (((X)&0xffULL)<<56)+               \
+                            (((X)&0xff00ULL)<<40)+              \
+                            (((X)&0xff0000ULL)<<24)+            \
+                            (((X)&0xff000000ULL)<<8)+           \
+                            (((X)&0xff00000000ULL)>>8)+         \
+                            (((X)&0xff0000000000ULL)>>24)+      \
+                            (((X)&0xff000000000000ULL)>>40)+    \
+                            (((X)&0xff00000000000000ULL)>>56))   
+
+#endif
+
+#define GT_REG_READ(offset, pData)                                          \
+*pData = ( (volatile unsigned int)*((unsigned int *)                        \
+           (NONE_CACHEABLE | internalRegBaseAddr | (offset))) );            \
+*pData = WORD_SWAP(*pData)
+
+#define GT_REG_WRITE(offset, data)                                          \
+(volatile unsigned int)*((unsigned int *)(NONE_CACHEABLE |                  \
+          internalRegBaseAddr | (offset))) = WORD_SWAP(data)
+
+typedef enum _bool{false,true} bool;
+
+/*****************************************************************************
+*
+* bool etherReadMIIReg (unsigned int portNumber , unsigned int MIIReg,
+* unsigned int* value)
+*
+* Description
+* This function will access the MII registers and will read the value of
+* the MII register , and will retrieve the value in the pointer.
+* Inputs
+* portNumber - one of the 2 possiable Ethernet ports (0-1).
+* MIIReg - the MII register offset.
+* Outputs
+* value - pointer to unsigned int which will receive the value.
+* Returns Value
+* true if success.
+* false if fail to make the assignment.
+* Error types (and exceptions if exist)
+*/
+
+GT_BOOL gtBspReadMii (GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                        unsigned int* value)
+{
+SMI_REG smiReg;
+unsigned int phyAddr;
+unsigned int timeOut = 10; /* in 100MS units */
+int i;
+
+/* first check that it is not busy */
+    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+    if(smiReg & SMI_BUSY) 
+    {
+        for(i = 0 ; i < SMI_RX_TIMEOUT ; i++);
+        do {
+            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+            if(timeOut-- < 1 ) {
+    	        return false;
+    	    }
+        } while (smiReg & SMI_BUSY);
+    }
+/* not busy */
+
+    phyAddr = portNumber;
+
+    smiReg =  (phyAddr << 16) | (SMI_OP_CODE_BIT_READ << 26) | (MIIReg << 21) |
+         SMI_OP_CODE_BIT_READ<<26;
+
+    GT_REG_WRITE (ETHER_SMI_REG,*((unsigned int*)&smiReg));
+    timeOut = 10; /* initialize the time out var again */
+    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+    if(!(smiReg & READ_VALID)) 
+        {
+            i=0;
+            while(i < SMI_RX_TIMEOUT)
+            {
+                i++;
+            }
+        {
+        }
+        do {
+            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+            if(timeOut-- < 1 ) {
+    	        return false;
+    	    }
+        } while (!(smiReg & READ_VALID));
+     }
+    *value = (unsigned int)(smiReg & 0xffff);
+    
+    return true;
+
+
+}
+
+/*****************************************************************************
+* 
+* bool etherWriteMIIReg (unsigned int portNumber , unsigned int MIIReg,
+* unsigned int value)
+* 
+* Description
+* This function will access the MII registers and will write the value
+* to the MII register.
+* Inputs
+* portNumber - one of the 2 possiable Ethernet ports (0-1).
+* MIIReg - the MII register offset.
+* value -the value that will be written.
+* Outputs
+* Returns Value
+* true if success.
+* false if fail to make the assignment.
+* Error types (and exceptions if exist)
+*/
+
+GT_BOOL gtBspWriteMii (GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                       unsigned int value)
+{
+SMI_REG smiReg;
+unsigned int phyAddr;
+unsigned int timeOut = 10; /* in 100MS units */
+int i;
+
+/* first check that it is not busy */
+    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+    if(smiReg & SMI_BUSY) 
+    {
+        for(i = 0 ; i < SMI_RX_TIMEOUT ; i++);
+        do {
+            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
+            if(timeOut-- < 1 ) {
+    	        return false;
+    	    }
+        } while (smiReg & SMI_BUSY);
+    }
+/* not busy */
+
+    phyAddr = portNumber;
+
+    smiReg = 0; /* make sure no garbage value in reserved bits */
+    smiReg = smiReg | (phyAddr << 16) | (SMI_OP_CODE_BIT_WRITE << 26) |
+             (MIIReg << 21) | (value & 0xffff);
+
+    GT_REG_WRITE (ETHER_SMI_REG,*((unsigned int*)&smiReg));
+
+    return(true);
+}
+
+
+void gtBspMiiInit(GT_QD_DEV* dev)
+{
+	return;	
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/msApiInit.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/msApiInit.c
new file mode 100755
index 0000000..9a027c8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/msApiInit.c
@@ -0,0 +1,115 @@
+#include <Copyright.h>
+/********************************************************************************
+* msApiInit.c
+*
+* DESCRIPTION:
+*       MS API initialization routine
+*
+* DEPENDENCIES:   Platform
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+/*
+#define MULTI_ADDR_MODE
+#define MANUAL_MODE
+*/
+
+GT_SYS_CONFIG   cfg;
+GT_QD_DEV       diagDev;
+GT_QD_DEV       *dev=&diagDev;
+
+
+/*
+ *  Initialize the QuarterDeck. This should be done in BSP driver init routine.
+ *	Since BSP is not combined with QuarterDeck driver, we are doing here.
+*/
+
+GT_STATUS qdStart(int cpuPort, int useQdSim, int devId) /* devId is used for simulator only */
+{
+GT_STATUS status;
+
+	/*
+	 *  Register all the required functions to QuarterDeck Driver.
+	*/
+	memset((char*)&cfg,0,sizeof(GT_SYS_CONFIG));
+	memset((char*)&diagDev,0,sizeof(GT_QD_DEV));
+
+	if(useQdSim == 0) /* use EV-96122 */
+	{
+		cfg.BSPFunctions.readMii   = gtBspReadMii;
+		cfg.BSPFunctions.writeMii  = gtBspWriteMii;
+#ifdef USE_SEMAPHORE
+		cfg.BSPFunctions.semCreate = osSemCreate;
+		cfg.BSPFunctions.semDelete = osSemDelete;
+		cfg.BSPFunctions.semTake   = osSemWait;
+		cfg.BSPFunctions.semGive   = osSemSignal;
+#else
+		cfg.BSPFunctions.semCreate = NULL;
+		cfg.BSPFunctions.semDelete = NULL;
+		cfg.BSPFunctions.semTake   = NULL;
+		cfg.BSPFunctions.semGive   = NULL;
+#endif
+		gtBspMiiInit(dev);
+	}
+	else	/* use QuaterDeck Simulator (No QD Device Required.) */
+	{
+		cfg.BSPFunctions.readMii   = qdSimRead;
+		cfg.BSPFunctions.writeMii  = qdSimWrite;
+#ifdef USE_SEMAPHORE
+		cfg.BSPFunctions.semCreate = osSemCreate;
+		cfg.BSPFunctions.semDelete = osSemDelete;
+		cfg.BSPFunctions.semTake   = osSemWait;
+		cfg.BSPFunctions.semGive   = osSemSignal;
+#else
+		cfg.BSPFunctions.semCreate = NULL;
+		cfg.BSPFunctions.semDelete = NULL;
+		cfg.BSPFunctions.semTake   = NULL;
+		cfg.BSPFunctions.semGive   = NULL;
+#endif
+
+		qdSimInit(devId,0);
+	}
+
+	cfg.initPorts = GT_TRUE;	/* Set switch ports to Forwarding mode. If GT_FALSE, use Default Setting. */
+	cfg.cpuPortNum = cpuPort;
+#ifdef MANUAL_MODE	/* not defined. this is only for sample */
+	/* user may want to use this mode when there are two QD switchs on the same MII bus. */
+	cfg.mode.scanMode = SMI_MANUAL_MODE;	/* Use QD located at manually defined base addr */
+	cfg.mode.baseAddr = 0x10;	/* valid value in this case is either 0 or 0x10 */
+#else
+#ifdef MULTI_ADDR_MODE
+	cfg.mode.scanMode = SMI_MULTI_ADDR_MODE;	/* find a QD in indirect access mode */
+	cfg.mode.baseAddr = 1;		/* this is the phyAddr used by QD family device. 
+								Valid value are 1 ~ 31.*/
+#else
+	cfg.mode.scanMode = SMI_AUTO_SCAN_MODE;	/* Scan 0 or 0x10 base address to find the QD */
+	cfg.mode.baseAddr = 0;
+#endif
+#endif
+	if((status=qdLoadDriver(&cfg, dev)) != GT_OK)
+	{
+		MSG_PRINT(("qdLoadDriver return Failed\n"));
+		return status;
+	}
+
+	MSG_PRINT(("Device ID     : 0x%x\n",dev->deviceId));
+	MSG_PRINT(("Base Reg Addr : 0x%x\n",dev->baseRegAddr));
+	MSG_PRINT(("No of Ports   : %d\n",dev->numOfPorts));
+	MSG_PRINT(("CPU Ports     : %d\n",dev->cpuPortNum));
+
+	/*
+	 *  start the QuarterDeck
+	*/
+	if((status=sysEnable(dev)) != GT_OK)
+	{
+		MSG_PRINT(("sysConfig return Failed\n"));
+		return status;
+	}
+
+	MSG_PRINT(("QuarterDeck has been started.\n"));
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/msSample.h b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/msSample.h
new file mode 100755
index 0000000..310df7e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/msSample.h
@@ -0,0 +1,147 @@
+#include <Copyright.h>
+/********************************************************************************
+* msSample.h
+*
+* DESCRIPTION:
+*       Types definitions for Sample program
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifndef __pfTesth
+#define __pfTesth
+
+#ifdef _VXWORKS
+#include "vxWorks.h"
+#include "logLib.h"
+#endif
+#include "stdio.h"
+#include "stdarg.h"
+#include "stdlib.h"
+#include "time.h"
+#include "string.h"
+
+#include "msApi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef GT_U32 (*GT_API_VOID) (GT_QD_DEV*);
+typedef int (*GT_CMP_FUNC) (void*, int, int);
+
+typedef GT_STATUS (*GT_API_SET_BOOL) (GT_QD_DEV*, GT_BOOL);
+typedef GT_STATUS (*GT_API_GET_BOOL) (GT_QD_DEV*, GT_BOOL*);
+
+typedef GT_STATUS (*GT_API_MAC_ADDR) (GT_QD_DEV*, GT_ETHERADDR*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_BOOL) (GT_QD_DEV*, GT_LPORT,GT_BOOL);
+typedef GT_STATUS (*GT_API_GET_PORT_BOOL) (GT_QD_DEV*, GT_LPORT,GT_BOOL*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U16) (GT_QD_DEV*, GT_LPORT,GT_U16);
+typedef GT_STATUS (*GT_API_GET_PORT_U16) (GT_QD_DEV*, GT_LPORT,GT_U16*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U32) (GT_QD_DEV*, GT_LPORT,GT_U32);
+typedef GT_STATUS (*GT_API_GET_PORT_U32) (GT_QD_DEV*, GT_LPORT,GT_U32*);
+
+typedef GT_STATUS (*GT_API_SET_PORT_U8) (GT_QD_DEV*, GT_LPORT,GT_U8);
+typedef GT_STATUS (*GT_API_GET_PORT_U8) (GT_QD_DEV*, GT_LPORT,GT_U8*);
+
+typedef struct _TEST_API
+{
+	union
+	{
+		GT_API_SET_BOOL bool;
+		GT_API_MAC_ADDR mac;
+		GT_API_SET_PORT_BOOL port_bool;
+		GT_API_SET_PORT_U8 port_u8;
+		GT_API_SET_PORT_U16 port_u16;
+		GT_API_SET_PORT_U32 port_u32;
+	} setFunc;
+
+	union
+	{
+		GT_API_GET_BOOL bool;
+		GT_API_MAC_ADDR mac;
+		GT_API_GET_PORT_BOOL port_bool;
+		GT_API_GET_PORT_U8 port_u8;
+		GT_API_GET_PORT_U16 port_u16;
+		GT_API_GET_PORT_U32 port_u32;
+	} getFunc;
+
+}TEST_API;
+
+typedef struct _TEST_STRUCT
+{
+	char strTest[16];
+	GT_API_VOID testFunc;
+	GT_U32 testResults;
+} TEST_STRUCT;
+
+#define MSG_PRINT(x) testPrint x
+
+#define TEST_MAC_ENTRIES	32
+typedef struct _TEST_ATU_ENTRY
+{
+	GT_ATU_ENTRY atuEntry[TEST_MAC_ENTRIES];
+}TEST_ATU_ENTRY;
+
+typedef struct _ATU_ENTRY_INFO
+{
+	GT_ATU_ENTRY atuEntry;
+	GT_U16	hash;
+	GT_U16	bucket;
+} ATU_ENTRY_INFO;
+
+extern GT_SYS_CONFIG   pfTestSysCfg;
+extern ATU_ENTRY_INFO *gAtuEntry;
+extern GT_QD_DEV       *dev;
+
+GT_STATUS qdStart(int,int,int);
+GT_STATUS qdSimSetPhyInt(unsigned int portNumber, unsigned short u16Data);
+GT_STATUS qdSimSetGlobalInt(unsigned short u16Data);
+
+GT_STATUS testAll(GT_QD_DEV*);
+void testPrint(char* format, ...);
+
+extern FGT_INT_HANDLER qdIntHandler;
+
+int vtuEntryCmpFunc(void* buf, int a, int b);
+int atuEntryCmpFunc(void* buf, int a, int b);
+GT_STATUS gtSort(int list[], GT_CMP_FUNC cmpFunc, void* buf, GT_U32 len);
+GT_U16 createATUList(GT_QD_DEV *dev, TEST_ATU_ENTRY atuEntry[], GT_U16 entrySize, GT_U16 dbNumSize, 
+					GT_U16 sameMacsInEachDb, GT_U16 bSize);
+GT_STATUS testFillUpAtu(GT_QD_DEV *dev, ATU_ENTRY_INFO *atuEntry, GT_U8 atuSize, 
+					GT_U8 dbNum, GT_U16 first2Bytes, GT_ATU_UC_STATE state);
+GT_U16 runQDHash(GT_U8* eaddr, GT_U16 dbNum, int bSize, GT_U16* pHash, 
+					GT_U16* preBucket, GT_U16* posBucket);
+GT_STATUS testDisplayATUList();
+
+#undef USE_SEMAPHORE
+
+#ifdef USE_SEMAPHORE
+GT_SEM osSemCreate(GT_SEM_BEGIN_STATE state);
+GT_STATUS osSemDelete(GT_SEM smid);
+GT_STATUS osSemWait(GT_SEM smid, GT_U32 timeOut);
+GT_STATUS osSemSignal(GT_SEM smid);
+#endif
+
+GT_BOOL gtBspReadMii ( GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                      unsigned int* value);
+GT_BOOL gtBspWriteMii ( GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
+                       unsigned int value);
+void gtBspMiiInit();
+
+GT_BOOL qdSimRead (GT_QD_DEV* dev,unsigned int portNumber , unsigned int miiReg, unsigned int* value);
+GT_BOOL qdSimWrite (GT_QD_DEV* dev,unsigned int portNumber , unsigned int miiReg, unsigned int value);
+void qdSimInit();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif   /* __pfTesth */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/osSem.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/osSem.c
new file mode 100755
index 0000000..555c76e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/osSem.c
@@ -0,0 +1,233 @@
+#include <Copyright.h>
+/********************************************************************************
+* osSem.c
+*
+* DESCRIPTION:
+*       Semaphore related routines
+*
+* DEPENDENCIES:
+*       OS Dependent.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#ifdef _VXWORKS
+#include "vxWorks.h"
+#include "semLib.h"
+#include "errnoLib.h"
+#include "objLib.h"
+
+int sysClkRateGet(void);
+
+#elif defined(WIN32)
+#include "windows.h"
+#include "wdm.h"
+#elif defined(LINUX)
+#include "/usr/include/semaphore.h"
+typedef    sem_t          semaphore ;
+#endif
+
+#include <msApi.h>
+
+GT_SEM osSemCreate( GT_SEM_BEGIN_STATE state);
+GT_STATUS osSemDelete(GT_SEM smid);
+GT_STATUS osSemWait(  GT_SEM smid, GT_U32 timeOut);
+GT_STATUS osSemSignal(GT_SEM smid);
+
+/*******************************************************************************
+* osSemCreate
+*
+* DESCRIPTION:
+*       Create semaphore.
+*
+* INPUTS:
+*       name   - semaphore Name
+*       init   - init value of semaphore counter
+*       count  - max counter (must be >= 1)
+*
+* OUTPUTS:
+*       smid - semaphore Id
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_SEM osSemCreate(GT_SEM_BEGIN_STATE state)
+{
+#ifdef _VXWORKS
+#if 0
+	return (GT_SEM)semBCreate(SEM_Q_FIFO, state);
+#else
+	GT_SEM semid;
+	semid =(GT_SEM)semBCreate(SEM_Q_FIFO, state);
+	return semid;
+#endif
+
+#elif defined(WIN32)
+	return (GT_SEM)CreateSemaphore(NULL, state, 1, NULL);
+#elif defined(LINUX)
+	semaphore lxSem;
+
+	sem_init(&lxSem, state, 1);
+	return lxSem;
+#else
+	return 1;
+#endif
+	return GT_OK;
+}
+
+/*******************************************************************************
+* osSemDelete
+*
+* DESCRIPTION:
+*       Delete semaphore.
+*
+* INPUTS:
+*       smid - semaphore Id
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS osSemDelete(GT_SEM smid)
+{
+#ifdef _VXWORKS
+	STATUS rc;
+
+	rc = semDelete((SEM_ID) smid);
+	if (rc != OK)
+		return GT_FAIL;
+
+#elif defined(WIN32)
+	if (CloseHandle((HANDLE)smid) == 0)
+		return GT_FAIL;
+
+#elif defined(LINUX)
+	sem_destroy((semaphore*) smid);
+#else
+	return GT_OK;
+#endif
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* osSemWait
+*
+* DESCRIPTION:
+*       Wait on semaphore.
+*
+* INPUTS:
+*       smid    - semaphore Id
+*       timeOut - time out in miliseconds or 0 to wait forever
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       OS_TIMEOUT - on time out
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS osSemWait(GT_SEM smid, GT_U32 timeOut)
+{
+#ifdef _VXWORKS
+	STATUS rc;
+
+	if (timeOut == 0)
+	rc = semTake ((SEM_ID) smid, WAIT_FOREVER);
+	else
+	{
+		int num, delay;
+
+		num = sysClkRateGet();
+		delay = (num * timeOut) / 1000;
+		if (delay < 1)
+			rc = semTake ((SEM_ID) smid, 1);
+		else
+			rc = semTake ((SEM_ID) smid, delay);
+	}
+
+	if (rc != OK)
+	{
+		if (errno == S_objLib_OBJ_TIMEOUT)
+			return GT_TIMEOUT;
+		else
+			return GT_FAIL;
+	}
+
+#elif defined(WIN32)
+	DWORD rc;
+
+	rc = WaitForSingleObject((HANDLE)smid, timeOut);
+
+	if (rc == WAIT_ABANDONED)
+		return GT_FAIL;
+	if (rc == WAIT_TIMEOUT)
+		return GT_TIMEOUT;
+
+#elif defined(LINUX)
+	sem_wait((semaphore*) smid) ; 
+#else
+	return GT_OK;
+
+#endif
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* osSemSignal
+*
+* DESCRIPTION:
+*       Signal a semaphore.
+*
+* INPUTS:
+*       smid    - semaphore Id
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS osSemSignal(GT_SEM smid)
+{
+#ifdef _VXWORKS
+	STATUS rc;
+	rc = semGive ((SEM_ID) smid);
+	if (rc != OK)
+		return GT_FAIL;
+
+#elif defined(WIN32)
+	if(ReleaseSemaphore((HANDLE) smid, 1, NULL) == 0)
+		return GT_FAIL;
+
+#elif defined(LINUX)
+	sem_post((semaphore*) smid) ; 
+#else
+	return GT_OK;
+#endif
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/qdSim.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/qdSim.c
new file mode 100755
index 0000000..557df5f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/qdSim.c
@@ -0,0 +1,2004 @@
+#include <Copyright.h>
+/********************************************************************************
+* qdSim.c
+*
+* DESCRIPTION:
+*       Simulate QuaterDeck Device(88E6052)'s register map. When QuareterDeck API 
+*		try to read/write a bit or bits into QuaterDeck, the simulator will redirect to
+* 		its own memory place and performing the function very close to QuaterDeck.
+*		For example, 
+*		1) user can set/reset a certain bit of QuarterDeck registers(Phy,Port,and General registers).
+*		2) user can access ATU (flush, load, purge, etc. with max MAC addresses of 32)
+*		3) user can manually generate an Interrupt and test the Interrupt routine.
+*		4) when user read a register, it will clear a certain register if it's a Self Clear register.
+*		5) when user write a register, it will return ERROR if it's read only register.
+*		 
+*
+* DEPENDENCIES:   QuaterDeck (88E6052) Register MAP.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include <msApi.h>
+#include <qdSimRegs.h>
+
+#define IS_BROADCAST_ADDR(_addr)                                \
+            (((_addr)[0] == 0xFF) && ((_addr)[1] == 0xFF) &&    \
+             ((_addr)[2] == 0xFF) && ((_addr)[3] == 0xFF) &&    \
+             ((_addr)[4] == 0xFF) && ((_addr)[5] == 0xFF))
+
+#define IS_GLOBAL_REG(_port)	((int)(_port) == qdSimDev.qdSimGlobalRegBase)
+#define IS_PORT_REG(_port) (((int)(_port) >= qdSimDev.qdSimPortBase) && ((int)(_port) < qdSimDev.qdSimPortBase + qdSimDev.qdSimNumOfPorts))
+#define IS_PHY_REG(_port) (((int)(_port) >= qdSimDev.qdSimPhyBase) && ((int)(_port) < qdSimDev.qdSimPhyBase + qdSimDev.qdSimNumOfPhys))
+
+typedef struct _QD_SIM_DEV
+{
+	int qdSimUsed;
+	unsigned int qdSimDevId;
+	int qdSimNumOfPorts;
+	int qdSimPortBase;
+	int qdSimNumOfPhys;
+	int qdSimPhyBase;
+	int qdSimGlobalRegBase;
+	int qdSimPortStatsClear[10];
+	int qdSimStatsCapturedPort;
+	int vtuSize;
+	int atuSize;
+} QD_SIM_DEV;
+
+static QD_SIM_DEV qdSimDev = {0};
+
+void qdSimRegsInit();
+GT_BOOL qdSimRead (GT_QD_DEV *dev, unsigned int portNumber , unsigned int miiReg, unsigned int* value);
+GT_BOOL qdSimWrite(GT_QD_DEV *dev, unsigned int portNumber , unsigned int miiReg, unsigned int value);
+
+/*
+ *	This Array will simulate the QuarterDeck Registers.
+ *	To use it, qdSimRegs has to be initialized with its default values and
+ *	Call qdSimRead and qdSimWrite functions.
+*/
+#define MAX_SMI_ADDRESS		0x20
+#define MAX_REG_ADDRESS		0x20
+#define MAX_ATU_ADDRESS		0x800
+#define MAX_QD_VTU_ENTRIES	0x40
+
+GT_U16 qdSimRegs[MAX_SMI_ADDRESS][MAX_REG_ADDRESS];
+
+typedef struct _QDSIM_ATU_ENTRY
+{
+	GT_U16 atuData;
+	GT_U16 DBNum;
+	GT_U8 atuMac[6];
+} QDSIM_ATU_ENTRY;
+
+/* 
+	Since QuarterDeck Simulator supports only fixed size of atu entry,
+	we are going with array list not dynamic linked list.
+*/
+typedef struct _QDSIM_ATU_NODE
+{
+	QDSIM_ATU_ENTRY atuEntry;
+	GT_U32 nextEntry;
+} QDSIM_ATU_NODE;
+
+typedef struct _QDSIM_ATU_LIST
+{
+	int atuSize;
+	GT_U32 head;
+} QDSIM_ATU_LIST;
+
+QDSIM_ATU_NODE ATUNode[MAX_ATU_ADDRESS];
+QDSIM_ATU_LIST ATUList;
+
+typedef struct _QDSIM_VTU_ENTRY
+{
+	GT_U16 DBNum;
+	GT_U16 memberTag[10];
+	GT_U16 vid;
+} QDSIM_VTU_ENTRY;
+
+/* 
+	Since QuarterDeck Simulator supports only fixed size of atu entry,
+	we are going with array list not dynamic linked list.
+*/
+typedef struct _QDSIM_VTU_NODE
+{
+	QDSIM_VTU_ENTRY vtuEntry;
+	GT_U32 nextEntry;
+} QDSIM_VTU_NODE;
+
+typedef struct _QDSIM_VTU_LIST
+{
+	int vtuSize;
+	GT_U32 head;
+} QDSIM_VTU_LIST;
+
+QDSIM_VTU_NODE VTUNode[MAX_QD_VTU_ENTRIES];
+QDSIM_VTU_LIST VTUList;
+
+/*******************************************************************************
+* qdMemSet
+*
+* DESCRIPTION:
+*       Set a block of memory
+*
+* INPUTS:
+*       start  - start address of memory block for setting
+*       simbol - character to store, converted to an unsigned char
+*       size   - size of block to be set
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       Pointer to set memory block
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void * qdMemSet
+(
+    IN void * start,
+    IN int    symbol,
+    IN GT_U32 size
+)
+{
+	GT_U32 i;
+	char* buf;
+	
+	buf = (char*)start;
+		
+	for(i=0; i<size; i++)
+	{
+		*buf++ = (char)symbol;
+	}
+
+	return start;
+}
+
+/*******************************************************************************
+* qdMemCpy
+*
+* DESCRIPTION:
+*       Copies 'size' characters from the object pointed to by 'source' into
+*       the object pointed to by 'destination'. If copying takes place between
+*       objects that overlap, the behavior is undefined.
+*
+* INPUTS:
+*       destination - destination of copy
+*       source      - source of copy
+*       size        - size of memory to copy
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       Pointer to destination
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void * qdMemCpy
+(
+    IN void *       destination,
+    IN const void * source,
+    IN GT_U32       size
+)
+{
+	GT_U32 i;
+	char* buf;
+	char* src;
+	
+	buf = (char*)destination;
+	src = (char*)source;
+		
+	for(i=0; i<size; i++)
+	{
+		*buf++ = *src++;
+	}
+
+	return destination;
+}
+
+/*******************************************************************************
+* qdMemCmp
+*
+* DESCRIPTION:
+*       Compares given memories.
+*
+* INPUTS:
+*       src1 - source 1
+*       src2 - source 2
+*       size - size of memory to copy
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       0, if equal.
+*		negative number, if src1 < src2.
+*		positive number, if src1 > src2.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int qdMemCmp
+(
+    IN char src1[],
+    IN char src2[],
+    IN GT_U32 size
+)
+{
+	GT_U32 i;
+	int value;
+
+	for(i=0; i<size; i++)
+	{
+		if((value = (int)(src1[i] - src2[i])) != 0)
+			return value; 
+	}
+
+	return 0;
+}
+
+/*
+	Compare the given ethernet addresses.
+	0, if they are equal.
+	Negative int, if mac2 is bigger than mac1.
+	Positive int, if mac1 is bigger than mac2.
+*/
+int cmpEtherMac(unsigned char* mac1, unsigned char* mac2)
+{
+	int i, tmp;
+
+	for(i=0; i<6; i++)
+	{
+		if((tmp = mac1[i] - mac2[i]) != 0)
+			return tmp;
+	}
+	return 0;
+}
+
+/*
+	entry index, if found.
+	MAX_ATU_ADDRESS, otherwise.
+*/
+int qdSimATUFindNext(QDSIM_ATU_ENTRY* entry)
+{
+	int i;
+	int node = ATUList.head;
+
+	if (IS_BROADCAST_ADDR(entry->atuMac))
+	{
+		if(ATUList.atuSize != 0)
+		{
+			if (ATUNode[node].atuEntry.DBNum == entry->DBNum)
+				return node;
+			else
+			{
+				for(i=0; i<ATUList.atuSize; i++)
+				{
+					if(ATUNode[node].atuEntry.DBNum == entry->DBNum)
+						return node;
+					node = ATUNode[node].nextEntry;
+				}
+			}
+				
+		}
+		return MAX_ATU_ADDRESS;
+	}
+
+	for(i=0; i<ATUList.atuSize; i++)
+	{
+		if(cmpEtherMac(ATUNode[node].atuEntry.atuMac,entry->atuMac) > 0)
+		{
+			if(ATUNode[node].atuEntry.DBNum == entry->DBNum)
+				break;
+		}
+		node = ATUNode[node].nextEntry;
+	}
+
+	if (i == ATUList.atuSize)
+		return MAX_ATU_ADDRESS;
+
+	return node;
+}
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimATUAdd(QDSIM_ATU_ENTRY* entry)
+{
+	int i, freeNode, preNode, node;
+
+	preNode = node = ATUList.head;
+
+	if (ATUList.atuSize >= MAX_ATU_ADDRESS)
+		return GT_FALSE;
+
+	/* find a free entry from our global memory. */
+	for(i=0; i<MAX_ATU_ADDRESS; i++)
+	{
+		if(ATUNode[i].nextEntry == MAX_ATU_ADDRESS)
+			break;
+	}
+	
+	if (i==MAX_ATU_ADDRESS)
+	{
+		return GT_FALSE;
+	}
+
+	freeNode = i;
+
+	/* find the smallest entry which is bigger than the given entry */
+	for(i=0; i<ATUList.atuSize; i++)
+	{
+		if(cmpEtherMac(ATUNode[node].atuEntry.atuMac,entry->atuMac) >= 0)
+			break;
+		preNode = node;
+		node = ATUNode[node].nextEntry;
+	}	
+
+	/* if the same Mac address is in the list and dbnum is identical, then just update and return. */
+	if (i != ATUList.atuSize)
+		if(cmpEtherMac(ATUNode[node].atuEntry.atuMac,entry->atuMac) == 0)
+		{
+			if(ATUNode[node].atuEntry.DBNum == entry->DBNum)
+			{
+				ATUNode[node].atuEntry.atuData = entry->atuData;
+				return GT_TRUE;
+			}
+		}
+
+	qdMemCpy(ATUNode[freeNode].atuEntry.atuMac, entry->atuMac, 6);
+	ATUNode[freeNode].atuEntry.atuData = entry->atuData;
+	ATUNode[freeNode].atuEntry.DBNum = entry->DBNum;
+
+	/* Add it to head */
+	if (i == 0)
+	{
+		ATUNode[freeNode].nextEntry = ATUList.head;
+		ATUList.head = freeNode;
+	}
+	/* Add it to tail */
+	else if (i == ATUList.atuSize)
+	{
+		ATUNode[preNode].nextEntry = freeNode;
+		ATUNode[freeNode].nextEntry = ATUList.head;
+	}
+	/* Add it in the middle of the list */
+	else
+	{
+		ATUNode[freeNode].nextEntry = ATUNode[preNode].nextEntry;
+		ATUNode[preNode].nextEntry = freeNode;
+	}
+	ATUList.atuSize++;
+	return GT_TRUE;
+}
+
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimATUDel(QDSIM_ATU_ENTRY* entry)
+{
+	int i, preNode, node;
+
+	preNode = node = ATUList.head;
+
+	/* find the entry */
+	for(i=0; i<ATUList.atuSize; i++)
+	{
+		if(cmpEtherMac(ATUNode[node].atuEntry.atuMac,entry->atuMac) == 0)
+		{
+			if(ATUNode[node].atuEntry.DBNum == entry->DBNum)
+				break;
+		}
+		preNode = node;
+		node = ATUNode[node].nextEntry;
+	}	
+
+	if (i == ATUList.atuSize)
+	{
+		/* cannot find the given entry to be deleted. */
+		return GT_FALSE;
+	}
+
+	/* Delete it from head */
+	if (i == 0)
+	{
+		ATUList.head = ATUNode[node].nextEntry;
+	}
+	/* Delete it in the middle of the list */
+	else if (i != ATUList.atuSize-1)
+	{
+		ATUNode[preNode].nextEntry = ATUNode[node].nextEntry;
+	}
+	ATUList.atuSize--;
+	ATUNode[node].nextEntry = MAX_ATU_ADDRESS;
+
+	return GT_TRUE;
+}
+
+
+GT_BOOL qdSimATUFlushUnlockedEntry()
+{
+	int i;
+
+	for (i=0; i<MAX_ATU_ADDRESS; i++)
+	{
+		if(((ATUNode[i].atuEntry.atuData & 0xF) != 0xF)	&&
+			(!(ATUNode[i].atuEntry.atuMac[0] & 1)) 		&&
+			(ATUNode[i].nextEntry != MAX_ATU_ADDRESS))
+		{
+			qdSimATUDel(&ATUNode[i].atuEntry);
+		}			
+	}
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimATUFlushInDB(int dbNum)
+{
+	int i;
+
+	for (i=0; i<MAX_ATU_ADDRESS; i++)
+	{
+		if(ATUNode[i].atuEntry.DBNum != dbNum)
+			continue;
+		qdSimATUDel(&ATUNode[i].atuEntry);
+	}
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimATUFlushUnlockedInDB(int dbNum)
+{
+	int i;
+
+	for (i=0; i<MAX_ATU_ADDRESS; i++)
+	{
+		if(ATUNode[i].atuEntry.DBNum != dbNum)
+			continue;
+		
+		if(((ATUNode[i].atuEntry.atuData & 0xF) != 0xF)	&&
+			(!(ATUNode[i].atuEntry.atuMac[0] & 1)) 		&&
+			(ATUNode[i].nextEntry != MAX_ATU_ADDRESS))
+		{
+			qdSimATUDel(&ATUNode[i].atuEntry);
+		}			
+	}
+	return GT_TRUE;
+}
+
+
+void qdSimATUInit()
+{
+	int i;
+
+	qdMemSet((char*)ATUNode, 0, sizeof(ATUNode));
+
+	/* MAX_ATU_ADDRESS means entry i is free, otherwise, it's not free */
+	for (i=0; i<MAX_ATU_ADDRESS; i++)
+		ATUNode[i].nextEntry = MAX_ATU_ADDRESS;
+
+	ATUList.atuSize = 0;	
+	ATUList.head = 0;	
+}
+
+void qdSimGetATUInfo(QDSIM_ATU_ENTRY* entry)
+{
+	entry->atuData = qdSimRegs[qdSimDev.qdSimGlobalRegBase][12];
+	entry->atuMac[0] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] >> 8) & 0xFF;
+	entry->atuMac[1] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] & 0xFF;
+	entry->atuMac[2] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] >> 8) & 0xFF;
+	entry->atuMac[3] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] & 0xFF;
+	entry->atuMac[4] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] >> 8) & 0xFF;
+	entry->atuMac[5] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] & 0xFF;
+	entry->DBNum = qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] & 0xF;
+	return;
+}
+
+void qdSimSetATUInfo(QDSIM_ATU_ENTRY* entry)
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][12] = entry->atuData;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] = (entry->atuMac[0]<<8) | entry->atuMac[1];
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] = (entry->atuMac[2]<<8) | entry->atuMac[3];
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] = (entry->atuMac[4]<<8) | entry->atuMac[5];
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] |= (entry->DBNum & 0xF);
+
+	return;
+}
+
+void qdSimReSetATUInfo()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][12] = 0;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] = 0xFFFF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] = 0xFFFF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] = 0xFFFF;
+
+	return;
+}
+
+GT_BOOL qdSimATUOperation(unsigned int value)
+{
+	QDSIM_ATU_ENTRY entry;
+	int	index;
+
+	switch((value & 0x7000) >> 12)
+	{
+		case 1:
+			/* Flush ALL */
+			qdSimATUInit();
+			break;
+		case 2:
+			/* Flush all unlocked entries */
+			return qdSimATUFlushUnlockedEntry();
+		case 3:
+			/* Load or Purge entry */
+			qdSimGetATUInfo(&entry);
+			if(entry.atuData & 0xF)
+				return qdSimATUAdd(&entry);
+			else
+				return qdSimATUDel(&entry);
+			break;
+		case 4:
+			/* Get Next Entry */
+			qdSimGetATUInfo(&entry);
+			index = qdSimATUFindNext(&entry);
+			if (index == MAX_ATU_ADDRESS)
+			{
+				qdSimReSetATUInfo();
+				return GT_TRUE;
+			}
+			else
+			{
+				qdSimSetATUInfo(&ATUNode[index].atuEntry);
+				return GT_TRUE;
+			}
+			break;
+		case 5:
+			/* Flush ALL in a DBNum */
+			return qdSimATUFlushInDB(value & 0xF);
+			break;
+		case 6:
+			/* Flush all unlocked entries */
+			return qdSimATUFlushUnlockedInDB(value & 0xF);
+		default:
+			break;
+	}
+	return GT_TRUE;
+}
+
+/*
+	VTU Related Routines
+*/
+
+/*
+	entry index, if found.
+	MAX_QD_VTU_ENTRIES, otherwise.
+*/
+int qdSimVTUFindNext(QDSIM_VTU_ENTRY* entry)
+{
+	int i;
+	int node = VTUList.head;
+
+	if (entry->vid == 0xFFF)
+	{
+		if(VTUList.vtuSize != 0)
+			return node;
+		else
+			return MAX_QD_VTU_ENTRIES;
+	}
+		
+	for(i=0; i<VTUList.vtuSize; i++)
+	{
+		if(VTUNode[node].vtuEntry.vid > entry->vid)
+			break;
+		node = VTUNode[node].nextEntry;
+	}
+
+	if (i == VTUList.vtuSize)
+		return MAX_QD_VTU_ENTRIES;
+
+	return node;
+}
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimVTUAdd(QDSIM_VTU_ENTRY* entry)
+{
+	int i, freeNode, preNode, node;
+
+	preNode = node = VTUList.head;
+
+	if (VTUList.vtuSize >= qdSimDev.vtuSize)
+		return GT_FALSE;
+
+	/* find a free entry from our global memory. */
+	for(i=0; i<MAX_QD_VTU_ENTRIES; i++)
+	{
+		if(VTUNode[i].nextEntry == MAX_QD_VTU_ENTRIES)
+			break;
+	}
+	
+	if (i==MAX_QD_VTU_ENTRIES)
+	{
+		return GT_FALSE;
+	}
+
+	freeNode = i;
+
+	/* find the smallest entry which is bigger than the given entry */
+	for(i=0; i<VTUList.vtuSize; i++)
+	{
+		if(VTUNode[node].vtuEntry.vid >= entry->vid)
+			break;
+		preNode = node;
+		node = VTUNode[node].nextEntry;
+	}	
+
+	/* if the same vid is in the list, then just update and return. */
+	if (i != VTUList.vtuSize)
+		if(VTUNode[node].vtuEntry.vid == entry->vid)
+		{
+			qdMemCpy(&VTUNode[node].vtuEntry, entry, sizeof(QDSIM_VTU_ENTRY));
+			return GT_TRUE;
+		}
+
+	qdMemCpy(&VTUNode[freeNode].vtuEntry, entry, sizeof(QDSIM_VTU_ENTRY));
+
+	/* Add it to head */
+	if (i == 0)
+	{
+		VTUNode[freeNode].nextEntry = VTUList.head;
+		VTUList.head = freeNode;
+	}
+	/* Add it to tail */
+	else if (i == VTUList.vtuSize)
+	{
+		VTUNode[preNode].nextEntry = freeNode;
+		VTUNode[freeNode].nextEntry = VTUList.head;
+	}
+	/* Add it in the middle of the list */
+	else
+	{
+		VTUNode[freeNode].nextEntry = VTUNode[preNode].nextEntry;
+		VTUNode[preNode].nextEntry = freeNode;
+	}
+	VTUList.vtuSize++;
+	return GT_TRUE;
+}
+
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimVTUDel(QDSIM_VTU_ENTRY* entry)
+{
+	int i, preNode, node;
+
+	preNode = node = VTUList.head;
+
+	/* find the entry */
+	for(i=0; i<VTUList.vtuSize; i++)
+	{
+		if(VTUNode[node].vtuEntry.vid == entry->vid)
+			break;
+		preNode = node;
+		node = VTUNode[node].nextEntry;
+	}	
+
+	if (i == VTUList.vtuSize)
+	{
+		/* cannot find the given entry to be deleted. */
+		return GT_FALSE;
+	}
+
+	/* Delete it from head */
+	if (i == 0)
+	{
+		VTUList.head = VTUNode[node].nextEntry;
+	}
+	/* Delete it in the middle of the list */
+	else if (i != VTUList.vtuSize-1)
+	{
+		VTUNode[preNode].nextEntry = VTUNode[node].nextEntry;
+	}
+	VTUList.vtuSize--;
+	VTUNode[node].nextEntry = MAX_QD_VTU_ENTRIES;
+
+	return GT_TRUE;
+}
+
+
+/*
+	Return 1, if added successfully.
+	Return 0, otherwise.
+*/
+GT_BOOL qdSimVTUUpdate(QDSIM_VTU_ENTRY* entry)
+{
+	int i;
+	int node = VTUList.head;
+
+	/* find the entry */
+	for(i=0; i<VTUList.vtuSize; i++)
+	{
+		if(VTUNode[node].vtuEntry.vid == entry->vid)
+			break;
+		node = VTUNode[node].nextEntry;
+	}	
+
+	if (i == VTUList.vtuSize)
+	{
+		/* cannot find the given entry to be deleted. */
+		return GT_FALSE;
+	}
+
+	/* Update the found entry */
+	qdMemCpy(&VTUNode[node].vtuEntry, entry, sizeof(QDSIM_VTU_ENTRY));
+
+	return GT_TRUE;
+}
+
+void qdSimVTUInit()
+{
+	int i;
+
+	qdMemSet((char*)VTUNode, 0, sizeof(VTUNode));
+
+	/* MAX_ATU_ADDRESS means entry i is free, otherwise, it's not free */
+	for (i=0; i<MAX_QD_VTU_ENTRIES; i++)
+		VTUNode[i].nextEntry = MAX_QD_VTU_ENTRIES;
+
+	VTUList.vtuSize = 0;	
+	VTUList.head = 0;	
+}
+
+void qdSimGetVTUInfo(QDSIM_VTU_ENTRY* entry)
+{
+	entry->DBNum = qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] & 0xF;
+	entry->vid = qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] & 0x1FFF;
+	entry->memberTag[0] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] & 0x3;
+	entry->memberTag[1] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] >> 4) & 0x3;
+	entry->memberTag[2] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] >> 8) & 0x3;
+	entry->memberTag[3] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] >> 12) & 0x3;
+	entry->memberTag[4] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] & 0x3;
+	entry->memberTag[5] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] >> 4) & 0x3;
+	entry->memberTag[6] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] >> 8) & 0x3;
+	entry->memberTag[7] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] >> 12) & 0x3;
+	entry->memberTag[8] = qdSimRegs[qdSimDev.qdSimGlobalRegBase][9] & 0x3;
+	entry->memberTag[9] = (qdSimRegs[qdSimDev.qdSimGlobalRegBase][9] >> 4) & 0x3;
+
+	return;
+}
+
+void qdSimSetVTUInfo(QDSIM_VTU_ENTRY* entry)
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= entry->DBNum;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = (entry->vid & 0xFFF) | 0x1000;
+
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] = 	entry->memberTag[0] |
+						(entry->memberTag[1] << 4) |
+						(entry->memberTag[2] << 8) |
+						(entry->memberTag[3] << 12);
+
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] = 	entry->memberTag[4] |
+						(entry->memberTag[5] << 4) |
+						(entry->memberTag[6] << 8) |
+						(entry->memberTag[7] << 12);
+
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][9] = 	entry->memberTag[8] |
+						(entry->memberTag[9] << 4);
+
+	return;
+}
+
+void qdSimReSetVTUInfo()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 0xFFF;
+
+	return;
+}
+
+void qdSimVTUGetViolation()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0xFFF;
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= 1;	/* assume port 1 causes the violation */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 1;	/* assume vid 1 causes the violation */
+}
+
+void qdSimVTUResetBusy()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0x8000;
+
+	return;
+}
+
+GT_BOOL qdSimVTUOperation(unsigned int value)
+{
+	QDSIM_VTU_ENTRY entry;
+	int	index;
+
+	if(!(value & 0x8000))
+		return GT_FALSE;
+
+	qdSimVTUResetBusy();
+
+	switch((value & 0x7000) >> 12)
+	{
+		case 1:
+			/* Flush ALL */
+			qdSimVTUInit();
+			break;
+		case 3:
+			/* Load or Purge entry */
+			qdSimGetVTUInfo(&entry);
+			if(entry.vid & 0x1000)
+			{
+				entry.vid &= ~0x1000;
+				return qdSimVTUAdd(&entry);
+			}
+			else
+				return qdSimVTUDel(&entry);
+			break;
+		case 4:
+			/* Get Next Entry */
+			qdSimGetVTUInfo(&entry);
+			entry.vid &= ~0x1000;
+			index = qdSimVTUFindNext(&entry);
+			if (index == MAX_QD_VTU_ENTRIES)
+			{
+				qdSimReSetVTUInfo();
+				return GT_TRUE;
+			}
+			else
+			{
+				qdSimSetVTUInfo(&VTUNode[index].vtuEntry);
+				return GT_TRUE;
+			}
+			break;
+		case 7:
+			qdSimVTUGetViolation();
+			break;
+		default:
+			break;
+	}
+	return GT_TRUE;
+}
+
+void qdSimStatsInit()
+{
+	int i;
+
+	for(i=0; i<qdSimDev.qdSimNumOfPorts; i++)
+		qdSimDev.qdSimPortStatsClear[i] = 0;
+
+}
+
+GT_BOOL qdSimStatsOperation(unsigned int value)
+{
+	int	i;
+
+	if(!(value & 0x8000))
+		return GT_FALSE;
+
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][29] &= ~0x8000;
+
+	switch((value & 0x7000) >> 12)
+	{
+		case 1:
+			/* Flush ALL */
+			for(i=0; i<qdSimDev.qdSimNumOfPorts; i++)
+				qdSimDev.qdSimPortStatsClear[i] = 1;
+			break;
+		case 2:
+			/* Flush a port */
+			if ((value & 0x3F) >= (unsigned int)qdSimDev.qdSimNumOfPorts)
+				return GT_FALSE;
+			qdSimDev.qdSimPortStatsClear[value & 0x3F] = 1;
+			break;
+		case 4:
+			/* Read a counter */
+			if(qdSimDev.qdSimPortStatsClear[qdSimDev.qdSimStatsCapturedPort] == 1)
+			{
+				qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = 0;
+				qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = 0;
+			}
+			else
+			{
+				qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = qdSimDev.qdSimStatsCapturedPort;
+				qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = value & 0x3F;
+			}
+			break;
+		case 5:
+			if ((value & 0x3F) >= (unsigned int)qdSimDev.qdSimNumOfPorts)
+				return GT_FALSE;
+			qdSimDev.qdSimStatsCapturedPort = value & 0x3F;
+			break;
+		default:
+			return GT_FALSE;
+	}
+	return GT_TRUE;
+}
+
+#define QD_PHY_CONTROL_RW (QD_PHY_RESET|QD_PHY_LOOPBACK|QD_PHY_SPEED|QD_PHY_AUTONEGO|QD_PHY_POWER|QD_PHY_RESTART_AUTONEGO|QD_PHY_DUPLEX)
+#define QD_PHY_CONTROL_RO (~QD_PHY_CONTROL_RW)
+
+GT_BOOL qdSimPhyControl(unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+
+	/* reset all the Read Only bits. */
+	value &= QD_PHY_CONTROL_RW;
+
+	/* If powerDown is set, add Reset and Restart Auto bits. */
+	if(value & QD_PHY_POWER)
+	{
+		value |= (QD_PHY_RESET|QD_PHY_RESTART_AUTONEGO);
+		qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+		return GT_TRUE;
+	}
+
+	/* If Power Down was set, clear Reset and Restart Auto bits. */
+	if(qdSimRegs[portNumber][miiReg] & QD_PHY_POWER)
+	{
+		value &= ~(QD_PHY_RESET|QD_PHY_RESTART_AUTONEGO);
+		qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+		return GT_TRUE;
+	}
+
+	/* If Reset or Restart Auto set, replace with current value and clear Reset/Restart Auto. */
+	if (value & (QD_PHY_RESET|QD_PHY_RESTART_AUTONEGO))
+	{
+		value &= ~(QD_PHY_RESET|QD_PHY_RESTART_AUTONEGO);
+		qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+		return GT_TRUE;
+	}
+	else
+	{
+		value &= ~(QD_PHY_SPEED|QD_PHY_AUTONEGO|QD_PHY_DUPLEX);
+		qdSimRegs[portNumber][miiReg] &= (QD_PHY_SPEED|QD_PHY_AUTONEGO|QD_PHY_DUPLEX);
+		qdSimRegs[portNumber][miiReg] |= (GT_U16)value;
+		return GT_TRUE;
+	}
+
+	return GT_TRUE;
+}
+
+void qdSimRegsInit_6021()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] = 0;	/* VTU Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 0;	/* VTU VID Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][29] = 0;	/* Stats Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = 0;	/* Stats Counter Register Bytes 3,2 */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = 0;	/* Stats Counter Register Bytes 1,0 */
+}
+
+void qdSimRegsInit_6063()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] = 0;	/* VTU Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 0;	/* VTU VID Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][29] = 0;	/* Stats Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = 0;	/* Stats Counter Register Bytes 3,2 */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = 0;	/* Stats Counter Register Bytes 1,0 */
+}
+
+void qdSimRegsInit_6083()
+{
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] = 0;	/* VTU Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][6] = 0;	/* VTU VID Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][7] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][8] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][9] = 0;	/* VTU Data Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][29] = 0;	/* Stats Operation Register */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][30] = 0;	/* Stats Counter Register Bytes 3,2 */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][31] = 0;	/* Stats Counter Register Bytes 1,0 */
+}
+
+void qdSimRegsInit()
+{
+	int i;
+
+	qdMemSet(qdSimRegs, 0xff, sizeof(qdSimRegs));
+	
+	/* 
+		PHY Registers Setup
+	*/
+	for(i=0; i<qdSimDev.qdSimNumOfPhys; i++)
+	{
+		qdSimRegs[i][0] = 0x3100;	/* PHY Control */
+		qdSimRegs[i][1] = 0x7849;	/* PHY Status */
+		qdSimRegs[i][2] = 0x0141;	/* PHY Id 1 */
+		qdSimRegs[i][3] = 0x0c1f;	/* PHY Id 2 */
+		qdSimRegs[i][4] = 0x01e1;	/* AutoNego Ad */
+		qdSimRegs[i][5] = 0;		/* Partner Ability */
+		qdSimRegs[i][6] = 4;		/* AutoNego Expansion */
+		qdSimRegs[i][7] = 0x2001;	/* Next Page Transmit */
+		qdSimRegs[i][8] = 0;		/* Link Partner Next Page */
+		qdSimRegs[i][16] = 0x130;	/* Phy Specific Control */
+		qdSimRegs[i][17] = 0x40;	/* Phy Specific Status */
+		qdSimRegs[i][18] = 0;		/* Phy Interrupt Enable */
+		qdSimRegs[i][19] = 0x40;	/* Phy Interrupt Status */
+		qdSimRegs[i][20] = 0;		/* Interrupt Port Summary */
+		qdSimRegs[i][21] = 0;		/* Receive Error Counter */
+		qdSimRegs[i][22] = 0xa34;	/* LED Parallel Select */
+		qdSimRegs[i][23] = 0x3fc;	/* LED Stream Select */
+		qdSimRegs[i][24] = 0x42bf;	/* LED Control */
+	}
+
+	/*
+		Port Registers Setup
+	*/
+	for(i=qdSimDev.qdSimPortBase; i<qdSimDev.qdSimNumOfPorts+qdSimDev.qdSimPortBase; i++)
+	{
+		qdSimRegs[i][0] = 0x800;	/* Port Status */
+		qdSimRegs[i][3] = (GT_U16)qdSimDev.qdSimDevId << 4;	/* Switch ID */
+		qdSimRegs[i][4] = 0x7f;	/* Port Control */
+		qdSimRegs[i][6] = 0x7f & (~(1 << (i-8)));	/* Port Based Vlan Map */
+		qdSimRegs[i][7] = 1;		/* Default Port Vlan ID & Priority */
+		qdSimRegs[i][16] = 0;		/* Rx Frame Counter */
+		qdSimRegs[i][17] = 0;		/* Tx Frame Counter */
+	}
+
+	/*
+		Global Registers Setup
+	*/
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][0] = 0x3c01;	/* Global Status */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][1] = 0;		/* Switch Mac Addr 0 ~ 1 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][2] = 0;		/* Switch Mac Addr 2 ~ 3 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][3] = 0;		/* Switch Mac Addr 4 ~ 5 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][4] = 0x81;	/* Global Control */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][10] = 0x1130;		/* ATU Control */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] = 0;				/* ATU Operation */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][12] = 0;				/* ATU Data */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][13] = 0;				/* ATU Mac Addr 0 ~ 1 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][14] = 0;				/* ATU Mac Addr 2 ~ 3 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][15] = 0;				/* ATU Mac Addr 4 ~ 5 byte */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][16] = 0;			/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][17] = 0;			/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][18] = 0x5555;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][19] = 0x5555;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][20] = 0xaaaa;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][21] = 0xaaaa;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][22] = 0xffff;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][23] = 0xffff;	/* IP-PRI Mapping */
+	qdSimRegs[qdSimDev.qdSimGlobalRegBase][24] = 0xfa41;	/* IEEE-PRI Mapping */
+			  
+	switch(qdSimDev.qdSimDevId)
+	{
+		case GT_88E6021:
+			qdSimRegsInit_6021();
+			break;
+		case GT_88E6063:
+		case GT_FF_HG:
+		case GT_FF_EG:
+		case GT_FH_VPN:
+			qdSimRegsInit_6063();
+			break;
+		case GT_88E6083:
+			qdSimRegsInit_6083();
+			break;
+		default:
+			break;
+	}
+}
+
+GT_BOOL qdSimRead_6052(unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	*value = (unsigned int) qdSimRegs[portNumber][miiReg];
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					qdSimRegs[portNumber][miiReg] &= ~0xF;
+					if(qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG])
+						qdSimRegs[portNumber][miiReg] |= 0x2;
+
+					break;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+			case QD_REG_GLOBAL_CONTROL:
+			case QD_REG_ATU_CONTROL:
+			case QD_REG_ATU_OPERATION:
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					break;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					break;
+			case QD_PHY_INT_ENABLE_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+					qdSimRegs[portNumber][miiReg] = 0;
+					qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+					break;
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					*value = (unsigned int) qdSimRegs[0][miiReg];
+					break;
+		}
+	}
+
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimRead_6021(unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	*value = (unsigned int) qdSimRegs[portNumber][miiReg];
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					qdSimRegs[portNumber][miiReg] &= ~0x7F;
+					if(qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG])
+						qdSimRegs[portNumber][miiReg] |= 0x2;
+
+					break;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+			case QD_REG_VTU_OPERATION:
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+			case QD_REG_GLOBAL_CONTROL:
+			case QD_REG_ATU_CONTROL:
+			case QD_REG_ATU_OPERATION:
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+			case QD_REG_STATS_OPERATION:
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					break;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+			case QD_REG_Q_COUNTER:
+					break;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					break;
+			case QD_PHY_INT_ENABLE_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+					qdSimRegs[portNumber][miiReg] = 0;
+					qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+					break;
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					*value = (unsigned int) qdSimRegs[0][miiReg];
+					break;
+		}
+	}
+
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimRead_6063(unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	*value = (unsigned int) qdSimRegs[portNumber][miiReg];
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					qdSimRegs[portNumber][miiReg] &= ~0x7F;
+					if(qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG])
+						qdSimRegs[portNumber][miiReg] |= 0x2;
+
+					break;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+			case QD_REG_VTU_OPERATION:
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+			case QD_REG_GLOBAL_CONTROL:
+			case QD_REG_ATU_CONTROL:
+			case QD_REG_ATU_OPERATION:
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+			case QD_REG_STATS_OPERATION:
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					break;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+			case QD_REG_Q_COUNTER:
+					break;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					break;
+			case QD_PHY_INT_ENABLE_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+					qdSimRegs[portNumber][miiReg] = 0;
+					qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+					break;
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					*value = (unsigned int) qdSimRegs[0][miiReg];
+					break;
+		}
+	}
+
+	return GT_TRUE;
+}
+
+
+GT_BOOL qdSimRead_6083(unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	*value = (unsigned int) qdSimRegs[portNumber][miiReg];
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					qdSimRegs[portNumber][miiReg] &= ~0x7F;
+					if(qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG])
+						qdSimRegs[portNumber][miiReg] |= 0x2;
+
+					break;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+			case QD_REG_VTU_OPERATION:
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+			case QD_REG_GLOBAL_CONTROL:
+			case QD_REG_ATU_CONTROL:
+			case QD_REG_ATU_OPERATION:
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+			case QD_REG_STATS_OPERATION:
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					break;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+			case QD_REG_Q_COUNTER:
+					break;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					break;
+			case QD_PHY_INT_ENABLE_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+					qdSimRegs[portNumber][miiReg] = 0;
+					qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+					break;
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					*value = (unsigned int) qdSimRegs[0][miiReg];
+					break;
+		}
+	}
+
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimRead (GT_QD_DEV *dev,unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	if (portNumber >= MAX_SMI_ADDRESS)
+		portNumber -= MAX_SMI_ADDRESS;
+
+	if ((portNumber >= MAX_SMI_ADDRESS) || (miiReg >= MAX_REG_ADDRESS))
+		return GT_FALSE;
+
+	switch(qdSimDev.qdSimDevId)
+	{
+		case GT_88E6051:
+		case GT_88E6052:
+			return qdSimRead_6052(portNumber, miiReg, value);
+		case GT_88E6021:
+			return qdSimRead_6021(portNumber, miiReg, value);
+		case GT_88E6063:
+		case GT_FF_HG:
+		case GT_FF_EG:
+		case GT_FH_VPN:
+			return qdSimRead_6063(portNumber, miiReg, value);
+		case GT_88E6083:
+			return qdSimRead_6083(portNumber, miiReg, value);
+		default:
+			break;
+	}
+
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimWrite_6052 (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_BOOL status;
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					/* readonly register */
+					return GT_FALSE;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+					break;
+			case QD_REG_GLOBAL_CONTROL:
+					if(value & 0x200)
+					{
+						/* Reload EEPROM values */
+						qdSimRegsInit();
+						qdSimRegs[portNumber][QD_REG_GLOBAL_STATUS] |= 0x1;
+						return GT_TRUE;
+					}
+					break;
+			case QD_REG_ATU_CONTROL:
+					value &= ~0x8000;
+					break;
+			case QD_REG_ATU_OPERATION:
+					status = qdSimATUOperation(value);
+					return status;
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+			case QD_REG_SWITCH_ID:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+					break;
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					/* readonly registers */
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					return qdSimPhyControl(portNumber,miiReg,value);
+			case QD_PHY_INT_ENABLE_REG:
+			case QD_PHY_AUTONEGO_AD_REG:
+			case QD_PHY_NEXTPAGE_TX_REG:
+			case QD_PHY_SPEC_CONTROL_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else
+		return GT_FALSE;
+
+	qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimWrite_6021 (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_BOOL status;
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					/* readonly register */
+					return GT_FALSE;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+					break;
+			case QD_REG_VTU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= (value & 0xF);
+					status = qdSimVTUOperation(value);
+					return status;
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+					break;
+			case QD_REG_GLOBAL_CONTROL:
+					if(value & 0x200)
+					{
+						/* Reload EEPROM values */
+						qdSimRegsInit();
+						qdSimRegs[portNumber][QD_REG_GLOBAL_STATUS] |= 0x1;
+						return GT_TRUE;
+					}
+					break;
+			case QD_REG_ATU_CONTROL:
+					value &= ~0x8000;
+					break;
+			case QD_REG_ATU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] |= (value & 0xF);
+					status = qdSimATUOperation(value);
+					return status;
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+			case QD_REG_STATS_OPERATION:
+					status = qdSimStatsOperation(value);
+					return status;
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+					if(portNumber > 9)
+					{
+						qdSimRegs[portNumber][miiReg] &= ~QD_PORT_STATUS_DUPLEX;
+						qdSimRegs[portNumber][miiReg] |= (value & QD_PORT_STATUS_DUPLEX);
+						return GT_TRUE;
+					}
+			case QD_REG_SWITCH_ID:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+					break;
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_Q_COUNTER:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					return qdSimPhyControl(portNumber,miiReg,value);
+			case QD_PHY_INT_ENABLE_REG:
+			case QD_PHY_AUTONEGO_AD_REG:
+			case QD_PHY_NEXTPAGE_TX_REG:
+			case QD_PHY_SPEC_CONTROL_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else
+		return GT_FALSE;
+
+	qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimWrite_6063 (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_BOOL status;
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					/* readonly register */
+					return GT_FALSE;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+					break;
+			case QD_REG_VTU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= (value & 0xF);
+					status = qdSimVTUOperation(value);
+					return status;
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+					break;
+			case QD_REG_GLOBAL_CONTROL:
+					if(value & 0x200)
+					{
+						/* Reload EEPROM values */
+						qdSimRegsInit();
+						qdSimRegs[portNumber][QD_REG_GLOBAL_STATUS] |= 0x1;
+						return GT_TRUE;
+					}
+					break;
+			case QD_REG_ATU_CONTROL:
+					value &= ~0x8000;
+					break;
+			case QD_REG_ATU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] |= (value & 0xF);
+					status = qdSimATUOperation(value);
+					return status;
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+			case QD_REG_STATS_OPERATION:
+					status = qdSimStatsOperation(value);
+					return status;
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+					if(portNumber > 12)
+					{
+						qdSimRegs[portNumber][miiReg] &= ~QD_PORT_STATUS_DUPLEX;
+						qdSimRegs[portNumber][miiReg] |= (value & QD_PORT_STATUS_DUPLEX);
+						return GT_TRUE;
+					}
+			case QD_REG_SWITCH_ID:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+					break;
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_Q_COUNTER:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					return qdSimPhyControl(portNumber,miiReg,value);
+			case QD_PHY_INT_ENABLE_REG:
+			case QD_PHY_AUTONEGO_AD_REG:
+			case QD_PHY_NEXTPAGE_TX_REG:
+			case QD_PHY_SPEC_CONTROL_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else
+		return GT_FALSE;
+
+	qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+	return GT_TRUE;
+}
+
+GT_BOOL qdSimWrite_6083 (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_BOOL status;
+
+	if (IS_GLOBAL_REG(portNumber))	/* Global register */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_GLOBAL_STATUS:
+					/* readonly register */
+					return GT_FALSE;
+			case QD_REG_MACADDR_01:
+			case QD_REG_MACADDR_23:
+			case QD_REG_MACADDR_45:
+					break;
+			case QD_REG_VTU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][5] |= (value & 0xF);
+					status = qdSimVTUOperation(value);
+					return status;
+			case QD_REG_VTU_VID_REG:
+			case QD_REG_VTU_DATA1_REG:
+			case QD_REG_VTU_DATA2_REG:
+			case QD_REG_VTU_DATA3_REG:
+					break;
+			case QD_REG_GLOBAL_CONTROL:
+					if(value & 0x200)
+					{
+						/* Reload EEPROM values */
+						qdSimRegsInit();
+						qdSimRegs[portNumber][QD_REG_GLOBAL_STATUS] |= 0x1;
+						return GT_TRUE;
+					}
+					break;
+			case QD_REG_ATU_CONTROL:
+					value &= ~0x8000;
+					break;
+			case QD_REG_ATU_OPERATION:
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] &= ~0xF;
+					qdSimRegs[qdSimDev.qdSimGlobalRegBase][11] |= (value & 0xF);
+					status = qdSimATUOperation(value);
+					return status;
+			case QD_REG_ATU_DATA_REG:
+			case QD_REG_ATU_MAC_01:
+			case QD_REG_ATU_MAC_23:
+			case QD_REG_ATU_MAC_45:
+			case QD_REG_IP_PRI_REG0:
+			case QD_REG_IP_PRI_REG1:
+			case QD_REG_IP_PRI_REG2:
+			case QD_REG_IP_PRI_REG3:
+			case QD_REG_IP_PRI_REG4:
+			case QD_REG_IP_PRI_REG5:
+			case QD_REG_IP_PRI_REG6:
+			case QD_REG_IP_PRI_REG7:
+			case QD_REG_IEEE_PRI:
+					break;
+			case QD_REG_STATS_OPERATION:
+					status = qdSimStatsOperation(value);
+					return status;
+			case QD_REG_STATS_COUNTER3_2:
+			case QD_REG_STATS_COUNTER1_0:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PORT_REG(portNumber))	/* Port registers */
+	{
+		switch(miiReg)
+		{
+			case QD_REG_PORT_STATUS:
+					if(portNumber > 12)
+					{
+						qdSimRegs[portNumber][miiReg] &= ~QD_PORT_STATUS_DUPLEX;
+						qdSimRegs[portNumber][miiReg] |= (value & QD_PORT_STATUS_DUPLEX);
+						return GT_TRUE;
+					}
+			case QD_REG_SWITCH_ID:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_PORT_CONTROL:
+			case QD_REG_PORT_VLAN_MAP:
+			case QD_REG_PVID:
+			case QD_REG_RATE_CTRL:
+			case QD_REG_PAV:
+					break;
+			case QD_REG_RXCOUNTER:
+			case QD_REG_TXCOUNTER:
+					/* readonly registers */
+					return GT_FALSE;
+			case QD_REG_Q_COUNTER:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else if(IS_PHY_REG(portNumber))	/* phy registers */
+	{
+		switch(miiReg)
+		{
+			case QD_PHY_CONTROL_REG:
+					return qdSimPhyControl(portNumber,miiReg,value);
+			case QD_PHY_INT_ENABLE_REG:
+			case QD_PHY_AUTONEGO_AD_REG:
+			case QD_PHY_NEXTPAGE_TX_REG:
+			case QD_PHY_SPEC_CONTROL_REG:
+					break;
+			case QD_PHY_INT_STATUS_REG:
+			case QD_PHY_INT_PORT_SUMMARY_REG:
+					return GT_FALSE;
+			default:
+					return GT_FALSE;
+		}
+	}
+	else
+		return GT_FALSE;
+
+	qdSimRegs[portNumber][miiReg] = (GT_U16)value;
+	return GT_TRUE;
+}
+
+
+GT_BOOL qdSimWrite (GT_QD_DEV *dev,unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	if (portNumber >= MAX_SMI_ADDRESS)
+		portNumber -= MAX_SMI_ADDRESS;
+
+	if ((portNumber >= MAX_SMI_ADDRESS) || (miiReg >= MAX_REG_ADDRESS))
+		return GT_FALSE;
+
+	switch(qdSimDev.qdSimDevId)
+	{
+		case GT_88E6051:
+		case GT_88E6052:
+			return qdSimWrite_6052(portNumber, miiReg, value);
+		case GT_88E6021:
+			return qdSimWrite_6021(portNumber, miiReg, value);
+		case GT_88E6063:
+		case GT_FF_HG:
+		case GT_FF_EG:
+		case GT_FH_VPN:
+			return qdSimWrite_6063(portNumber, miiReg, value);
+		case GT_88E6083:
+			return qdSimWrite_6083(portNumber, miiReg, value);
+
+		default:
+			break;
+	}
+
+	return GT_TRUE;
+}
+
+GT_STATUS qdSimSetPhyInt(unsigned int portNumber, unsigned short u16Data)
+{
+	if(!qdSimDev.qdSimUsed)
+		return GT_FAIL;
+
+	qdSimRegs[portNumber][QD_PHY_INT_STATUS_REG] = u16Data;
+	if(u16Data)
+		qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] |= (1<<portNumber);
+	else
+		qdSimRegs[0][QD_PHY_INT_PORT_SUMMARY_REG] &= ~(1<<portNumber);
+	
+	qdSimRegs[MAX_SMI_ADDRESS-1][QD_REG_GLOBAL_STATUS] |= 0x2;
+	return GT_OK;
+}
+
+GT_STATUS qdSimSetGlobalInt(unsigned short u16Data)
+{
+	if(!qdSimDev.qdSimUsed)
+		return GT_FAIL;
+
+	qdSimRegs[MAX_SMI_ADDRESS-1][QD_REG_GLOBAL_STATUS] |= (u16Data & 0xF);
+	return GT_OK;
+}
+
+
+void qdSimInit(GT_DEVICE devId, int baseAddr)
+{
+	qdSimDev.qdSimUsed = 1;
+
+	qdSimDev.qdSimDevId = devId;
+	qdSimDev.vtuSize = 0;
+
+	qdSimDev.qdSimPhyBase = baseAddr;
+	qdSimDev.qdSimPortBase = baseAddr + 0x8;
+	qdSimDev.qdSimGlobalRegBase = baseAddr + 0xF;
+
+	switch(devId)
+	{
+		case GT_88E6021:
+			qdSimDev.vtuSize = 16;
+			qdSimDev.qdSimNumOfPhys = 2;
+			qdSimDev.qdSimNumOfPorts = 3;
+			break;
+		case GT_88E6051:
+			qdSimDev.qdSimNumOfPhys = 5;
+			qdSimDev.qdSimNumOfPorts = 6;
+			break;
+		case GT_88E6063:
+		case GT_FH_VPN:
+			qdSimDev.vtuSize = 64;
+		case GT_88E6052:
+		case GT_FF_HG:
+		case GT_FF_EG:
+			qdSimDev.qdSimNumOfPhys = 5;
+			qdSimDev.qdSimNumOfPorts = 7;
+			break;
+		case GT_88E6083:
+			qdSimDev.vtuSize = 64;
+			qdSimDev.qdSimNumOfPhys = 8;
+			qdSimDev.qdSimNumOfPorts = 10;
+			qdSimDev.qdSimPhyBase = 0;
+			qdSimDev.qdSimPortBase = 0x10;
+			qdSimDev.qdSimGlobalRegBase = 0x1b;
+			break;
+		default:
+			qdSimDev.vtuSize = 64;
+			qdSimDev.qdSimDevId = GT_88E6063;
+			qdSimDev.qdSimNumOfPhys = 5;
+			qdSimDev.qdSimNumOfPorts = 7;
+			break;
+	}
+
+	qdSimATUInit();
+	qdSimVTUInit();
+	qdSimRegsInit();
+
+	return;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/readme.txt
new file mode 100755
index 0000000..918ea3e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Initialization/readme.txt
@@ -0,0 +1,85 @@
+========================================================================

+		QuaterDeck Initialization called by BSP

+========================================================================

+

+Initialization Sample Program will show how to initialize the QuaterDeck 

+Driver/Device.

+

+This Sample includes the following files:

+	- msApiInit.c

+	- qdSim.c

+	- qdSimRegs.h

+	- ev96122mii.c

+	- osSem.c

+

+msApiInit.c

+	qdStart is the main function of this Sample and does the followings:

+	1) register the required functions.(gtRegister API)

+		1.1) readMii - BSP specific MII read function 

+						(provided by BSP and required by all QuarterDeck API)

+		1.2) writeMii - BSP specific MII write function 

+						(provided by BSP and required by all QuarterDeck API)

+		1.3) semCreate - OS specific semaphore create function.

+						(provided by BSP and recommanded by QuarterDeck MAC 

+						address database API)

+		1.4) semDelete - OS specific semaphore delete function.

+						(provided by BSP and recommanded by QuarterDeck MAC 

+						address database API)

+		1.5) semTake - OS specific semaphore take function.

+						(provided by BSP and recommanded by QuarterDeck MAC 

+						address database API)

+		1.6) semGive - OS specific semaphore give function.

+						(provided by BSP and recommanded by QuarterDeck MAC 

+						address database API)

+		Notes) The given example will use EV96122 BSP and QuarterDeck Simulator 

+		as an example.

+

+	2) Initialize BSP provided routine (if required).

+		Notes) QuarterDeck Simulator needs to be initialized.(qdSimInit)

+

+	3) Calls sysConfig routine.

+		1.1) Input (GT_SYS_CONFIG) - CPU Port Number (Board Specific, 

+		either port 5 or port 6) and Port state (either 1 for Forwarding mode 

+		or 0 for Blocked mode)

+		1.2) Output (GT_SYS_INFO) - Device ID, Base MII Address (either 0 or 

+		0x10), Number of Ports, and CPU port number.

+

+	4) Calls sysEnable (for future use.)

+

+qdSim.c (QuaterDeck Simulator)

+    Simulates QuaterDeck Device(88E6052)'s register map. When QuareterDeck API 

+	try to read/write a bit or bits into QuaterDeck, the simulator will 

+	redirect to its own memory place and performing the function very close to

+	QuaterDeck. For example, 

+	1) user can set/reset a certain bit of QuarterDeck registers

+		(Phy,Port,and General registers).

+	2) user can access ATU (flush, load, purge, etc. with max MAC addresses 

+		of 32)

+	3) user can manually generate an Interrupt and test the Interrupt routine.

+	4) when user read a register, it will clear a certain register if it's a 

+		Self Clear register.

+	5) when user write a register, it will return ERROR if it's read only 

+		register.

+	Notes) Simulator can be used when user has no QuarterDeck device connected Board.

+

+	Exported routines are :

+		qdSimRead 	for reading MII registers,

+		qdSimWrite 	for writing to MII registers, and

+		qdSimInit 	for initializing Simulator.

+

+ev96122mii.c

+	Provides EV-96122 Board specific MII access functions.

+

+	Exported routines are :

+		gtBspReadMii 	for reading MII registers,

+		gtBspWriteMii	for writing to MII registers, and

+		gtBspMiiInit 	for initializing EV-96122 and QuarterDeck connection.

+

+osSem.c

+	Provides OS specific Semapore Functions.

+

+	Exported routines are :

+		osSemCreate 	for semaphore creation

+		osSemDelete 	for semaphore deletion

+		osSemWait 		for taking semaphore

+		osSemSignal 	for releasing semaphore

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Interrupt/qdInt.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Interrupt/qdInt.c
new file mode 100755
index 0000000..16fdb06
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Interrupt/qdInt.c
@@ -0,0 +1,385 @@
+#include <Copyright.h>
+/********************************************************************************
+* qdInt.c
+*
+* DESCRIPTION:
+*		This sample shows how to call QuarterDeck Interrupt handler when QD INT
+*		raised, and how to take care each Interrupt Cause.
+*
+* DEPENDENCIES:   NONE.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include "msSample.h"
+
+
+/*
+ *	To enable quarterDeck interrupt, you need to call eventSetActive() and
+ *	gprtPhyIntEnable(), as following sample routine.
+ *	sampleQDIntEnable will enable all interrupt causes.
+ *	For Port, GT_ATU_FULL, GT_ATU_DONE, GT_PHY_INTERRUPT, and GT_EE_INTERRUPT
+ *	are enabled.
+ *
+ *	In this sample, GT_SPEED_CHANGED, GT_DUPLEX_CHANGED, and 
+ *  GT_LINK_STATUS_CHANGED are enabled for ports 0 ~ 2.
+*/
+GT_STATUS sampleQDIntEnable(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_LPORT port;
+	GT_U16 data;
+
+	/* 
+	 *	Enable QuarterDeck interrupt for ATUFull, ATUDone, PHYInt, and EEInt.
+	 *	If writing 0 into eventSetActive(), all port interrupt will be disabled.
+	*/
+	data = GT_STATS_DONE|GT_VTU_PROB|GT_VTU_DONE|
+		   GT_ATU_FULL|GT_ATU_DONE|GT_PHY_INTERRUPT|GT_EE_INTERRUPT;
+	if((status = eventSetActive(dev,data)) != GT_OK)
+	{
+		MSG_PRINT(("eventSetActive returned fail.\n"));
+		return status;
+	}
+
+	/* 
+	 *	Enable Phy interrupt for every possible interrupt cause.
+	 *	If writing 0 into gprtPhyIntEnable(), all port interrupt will be disabled.
+	*/
+	data = 	GT_SPEED_CHANGED|GT_DUPLEX_CHANGED|GT_LINK_STATUS_CHANGED;
+
+	for(port=0; port<3; port++)
+	{
+		if((status = gprtPhyIntEnable(dev,port,data)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPhyIntEnable returned fail.\n"));
+			return status;
+		}
+	}
+
+	return GT_OK;
+}
+
+/*
+ *	Disable QuarterDeck Interrupt.
+*/
+GT_STATUS sampleQDIntDisable(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_LPORT port;
+
+	/* 
+	 *	Writing 0 into eventSetActive(), all port interrupt will be disabled.
+	*/
+	if((status = eventSetActive(dev,0)) != GT_OK)
+	{
+		MSG_PRINT(("eventSetActive returned fail.\n"));
+		return status;
+	}
+
+	/* 
+	 *	Writing 0 into gprtPhyIntEnable(), all port interrupt will be disabled.
+	*/
+	for(port=0; port<3; port++)
+	{
+		if((status = gprtPhyIntEnable(dev,port,0)) != GT_OK)
+		{
+			MSG_PRINT(("gprtPhyIntEnable returned fail.\n"));
+			return status;
+		}
+	}
+	return GT_OK;
+}
+
+
+/*
+ *	Assume that the following function, sampleQDIntVector(), is registered 
+ *	when BSP calls intConnect for QD Interrupt.
+ *	This sample will show how to deal with QuarterDeck Interrupt.
+*/
+GT_STATUS sampleQDIntVector(GT_QD_DEV *dev)
+{
+	GT_U16 intCause, phyIntCause;
+	GT_U16 portVec;
+	GT_LPORT port;
+	GT_VTU_INT_STATUS vtuInt;
+	GT_ATU_INT_STATUS atuInt;
+
+	/*
+	 *	Disable QuarterDeck Interrupt in System Level.
+	 *	ToDo...
+	*/
+
+	/*
+	 *	Check if QD generated the interrupt.
+	*/
+	if(eventGetIntStatus(dev,&intCause) != GT_TRUE)
+	{
+		/* QD didn't generate the interrupt. */
+		return GT_FAIL;
+	}
+
+	/*
+	 *	QD generated interrupt with the reason in intCause.
+	*/
+
+	if(intCause & GT_STATS_DONE)
+	{
+		/* 
+		 *	Statistics Done Interrupt
+		 *	ToDo...
+		*/
+
+	}
+	if(intCause & GT_VTU_DONE)
+	{
+		/* 
+		 *	VTU Done Interrupt
+		 *	ToDo...
+		*/
+
+	}
+
+	if(intCause & GT_VTU_PROB)
+	{
+		/* 
+		 *	Vlan Table Problem/Violation.
+		 *	Need to read the cause.
+		*/
+		do {
+			if(gvtuGetIntStatus(dev,&vtuInt) != GT_OK)
+			{
+				/* failed to retrieve VTU Interrupt cause */
+				break;
+			}
+
+			if(vtuInt.vtuIntCause & GT_VTU_FULL_VIOLATION)
+			{
+				/* 
+				 *	Vlan Table is Full
+				 *	ToDo...
+				*/
+			}
+
+			if(vtuInt.vtuIntCause & GT_MEMBER_VIOLATION)
+			{
+				/* 
+				 *	Member Violation
+				 *	ToDo...
+				*/
+			}
+
+			if(vtuInt.vtuIntCause & GT_MISS_VIOLATION)
+			{
+				/* 
+				 *	Miss Violation
+				 *	ToDo...
+				*/
+			}
+		} while(vtuInt.vtuIntCause != 0);
+	}
+
+	if(intCause & GT_ATU_PROB)
+	{
+		/* 
+		 *	ATU cannot load or learn a new mapping due to all the available
+		 *	locations for an address being locked.
+		 *	ToDo...
+		*/
+		do {
+			if(gatuGetIntStatus(dev,&atuInt) != GT_OK)
+			{
+				/* failed to retrieve VTU Interrupt cause */
+				break;
+			}
+
+			if(atuInt.atuIntCause & GT_FULL_VIOLATION)
+			{
+				/* 
+				 *	Table is Full
+				 *	ToDo...
+				*/
+			}
+
+			if(atuInt.atuIntCause & GT_MEMBER_VIOLATION)
+			{
+				/* 
+				 *	Member Violation
+				 *	ToDo...
+				*/
+			}
+
+			if(atuInt.atuIntCause & GT_MISS_VIOLATION)
+			{
+				/* 
+				 *	Miss Violation
+				 *	ToDo...
+				*/
+			}
+		} while(atuInt.atuIntCause != 0);
+
+	}
+
+	if(intCause & GT_ATU_DONE)
+	{
+		/* 
+		 *	There is a transitions from a one to a zero on ATUBusy bit
+		 *	(Refer to ATU Operation Register.)
+		 *	ToDo...
+		*/
+
+	}
+
+	if(intCause & GT_PHY_INTERRUPT)
+	{
+		/* 
+		 *	At least one of the Phy generated interrupt.
+		 *	We need to read Phy Interrupt Summary and go through each phy
+		 *	based on the summary.
+		*/
+
+		if(gprtGetPhyIntPortSummary(dev,&portVec) != GT_OK)
+		{
+			return GT_FAIL;
+		}
+
+		port = 0;
+		while(portVec)
+		{
+			if(portVec & 0x01)
+			{
+				/*
+				 *	Call gprtGetPhyIntStatus to get intCause
+				*/
+				if(gprtGetPhyIntStatus(dev,port,&phyIntCause) != GT_OK)
+				{
+					/* 
+					 *	Something wrong with the system. Need to do the 
+					 *	necessary work. 
+					 *	ToDo...
+					*/
+				}
+
+				if(phyIntCause & GT_SPEED_CHANGED)
+				{
+					/* 
+					 *	Speed has been changed.
+					 *	ToDo...
+					*/
+				}
+
+				if(phyIntCause & GT_DUPLEX_CHANGED)
+				{
+					/* 
+					 *	Duplex mode has been changed.
+					 *	ToDo...
+					*/
+				}
+
+				if(phyIntCause & GT_PAGE_RECEIVED)
+				{
+					/* 
+					 *	Page received.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_AUTO_NEG_COMPLETED)
+				{
+					/* 
+					 *	AutoNegotiation completed.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_LINK_STATUS_CHANGED)
+				{
+					/* 
+					 *	Link Status changed.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_SYMBOL_ERROR)
+				{
+					/* 
+					 *	Symbol error
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_FALSE_CARRIER)
+				{
+					/* 
+					 *	False Carrier.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_FIFO_FLOW)
+				{
+					/* 
+					 *	Fifo Overflow/underflow error
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_CROSSOVER_CHANGED)
+				{
+					/* 
+					 *	MDI/MDIX crossover changed.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_POLARITY_CHANGED)
+				{
+					/* 
+					 *	Polarity changed.
+					 *	ToDo...
+					*/
+
+				}
+
+				if(phyIntCause & GT_JABBER)
+				{
+					/* 
+					 *	Jabber
+					 *	ToDo...
+					*/
+
+				}
+			}
+
+			portVec >>= 1;
+			port++;
+		}
+	}
+
+	if(intCause & GT_EE_INTERRUPT)
+	{
+		/* 
+		 *	EEPROM is done loading registers.
+		 *	ToDo...
+		*/
+
+	}
+
+
+	/*
+	 *	Now, all the QuarterDeck related interrupt have been cleared,
+	 *	so it's OK to enable QuarterDeck Interrupt in System Level.
+	 *	ToDo...
+	*/
+	
+	return GT_OK;
+
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Interrupt/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Interrupt/readme.txt
new file mode 100755
index 0000000..f4c6740
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Interrupt/readme.txt
@@ -0,0 +1,20 @@
+========================================================================

+		QuaterDeck Interrupt Handler called by BSP Interrupt Vector

+========================================================================

+

+This sample shows how to enable/disable QuaterDeck Interrupt, and how to

+handle each Interrupt.

+

+qdInt.c

+	sampleQDIntEnable() will enable all the interrupt supported by 

+	QuaterDeck.

+	sampleQDIntDisable() will disable QuarterDeck Interrupt.

+	sampleQDIntVector() will show how BSP interrupt service routine can

+	deal with QuarterDeck Interrupt.

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/LoadBalance/loadBalance.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/LoadBalance/loadBalance.c
new file mode 100755
index 0000000..10be0ac
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/LoadBalance/loadBalance.c
@@ -0,0 +1,57 @@
+#include <Copyright.h>
+/********************************************************************************
+* loadBalance.c
+*
+* DESCRIPTION:
+*		This sample shows how to setup load balance among Trunk ports.
+*		In this sample, port 0,1,2, and 3 will be in the Trunk group.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*
+* COMMENTS:
+*******************************************************************************/
+
+#include "msSample.h"
+
+
+/*
+   The following sample sets Trunk Mask Table as follows:
+ 
+					10	9	8	7	6	5	4	3	2	1	0
+   TrunkMask[0]		1	1	1	1	1	1	1	0	0	0	1
+   TrunkMask[1]		1	1	1	1	1	1	1	0	0	1	0
+   TrunkMask[2]		1	1	1	1	1	1	1	0	1	0	0
+   TrunkMask[3]		1	1	1	1	1	1	1	1	0	0	0
+   TrunkMask[4]		1	1	1	1	1	1	1	0	0	0	1
+   TrunkMask[5]		1	1	1	1	1	1	1	0	0	1	0
+   TrunkMask[6]		1	1	1	1	1	1	1	0	1	0	0
+   TrunkMask[7]		1	1	1	1	1	1	1	1	0	0	0
+*/
+
+GT_STATUS sampleLoadBalance(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	int i;
+	GT_U32 mask, baseMask;
+
+	baseMask = 0xFFF0;	/* clear bits for port 0 ~ 3 */
+
+	/*
+	 *	Set the trunk mask table for load balancing.
+	*/
+	for(i=0; i<8; i++)
+	{
+		mask = baseMask | (1 << (i%4));
+
+		if((status = gsysSetTrunkMaskTable(dev,i,mask)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetTrunkMaskTable return Failed\n"));
+			return status;
+		}
+	}
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/LoadBalance/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/LoadBalance/readme.txt
new file mode 100755
index 0000000..53935af
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/LoadBalance/readme.txt
@@ -0,0 +1,16 @@
+========================================================================

+		Setup for Load Balancing

+========================================================================

+

+This sample shows how to setup Trunk Mask Table for load balancing.

+For more information about load balancing, please refer to 88E6095 Spec.

+

+loadBalance.c

+	sampleLoadBalance demonstrates how to setup Trunk Mask Table.

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MACAddress/macAddr.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MACAddress/macAddr.c
new file mode 100755
index 0000000..fe8142b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MACAddress/macAddr.c
@@ -0,0 +1,223 @@
+#include <Copyright.h>
+/********************************************************************************
+* macAddr.c
+*
+* DESCRIPTION:
+*	This sample will demonstrate how to add/delete a static MAC Address 
+*	into/from the QuaterDeck MAC Address Data Base.
+*		
+* DEPENDENCIES:   None.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+/*
+ *	Add the CPU MAC address into the QuaterDeck MAC Address database.
+ *	Input - None
+*/
+GT_STATUS sampleAddCPUMac(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_ATU_ENTRY macEntry;
+
+	/* 
+	 *	Assume that Ethernet address for the CPU MAC is
+	 *	00-50-43-00-01-02.
+	*/
+	macEntry.macAddr.arEther[0] = 0x00;
+	macEntry.macAddr.arEther[1] = 0x50;
+	macEntry.macAddr.arEther[2] = 0x43;
+	macEntry.macAddr.arEther[3] = 0x00;
+	macEntry.macAddr.arEther[4] = 0x01;
+	macEntry.macAddr.arEther[5] = 0x02;
+
+	macEntry.portVec = 1 << dev->cpuPortNum; 	/* CPU Port number. 7bits are used for portVector. */
+
+	macEntry.prio = 0;			/* Priority (2bits). When these bits are used they override
+								any other priority determined by the frame's data. This value is
+								meaningful only if the device does not support extended priority
+								information such as MAC Queue Priority and MAC Frame Priority */
+
+	macEntry.exPrio.macQPri = 0;	/* If device doesnot support MAC Queue Priority override, 
+									this field is ignored. */
+	macEntry.exPrio.macFPri = 0;	/* If device doesnot support MAC Frame Priority override, 
+									this field is ignored. */
+	macEntry.exPrio.useMacFPri = 0;	/* If device doesnot support MAC Frame Priority override, 
+									this field is ignored. */
+
+	macEntry.entryState.ucEntryState = GT_UC_STATIC;
+								/* This address is locked and will not be aged out.
+								Refer to GT_ATU_UC_STATE in msApiDefs.h for other option. */
+
+	/* 
+	 *	Add the MAC Address.
+	 */
+	if((status = gfdbAddMacEntry(dev,&macEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbAddMacEntry returned fail.\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ *	Delete the CPU MAC address from the QuaterDeck MAC Address database.
+ *	Input - None
+*/
+GT_STATUS sampleDelCPUMac(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_ATU_ENTRY macEntry;
+
+	/* 
+	 *	Assume that Ethernet address for the CPU MAC is
+	 *	00-50-43-00-01-02.
+	*/
+	macEntry.macAddr.arEther[0] = 0x00;
+	macEntry.macAddr.arEther[1] = 0x50;
+	macEntry.macAddr.arEther[2] = 0x43;
+	macEntry.macAddr.arEther[3] = 0x00;
+	macEntry.macAddr.arEther[4] = 0x01;
+	macEntry.macAddr.arEther[5] = 0x02;
+
+	/* 
+	 *	Delete the CPU MAC Address.
+	 */
+	if((status = gfdbDelMacEntry(dev,&macEntry.macAddr)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbDelMacEntry returned fail.\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ *	Add a multicast MAC address into the QuaterDeck MAC Address database,
+ *	where address is 01-00-18-1a-00-00 and frames with this destination has
+ *	to be forwarding to Port 1, Port 2 and Port 4 (port starts from Port 0)
+ *	Input - None
+*/
+GT_STATUS sampleAddMulticastAddr(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_ATU_ENTRY macEntry;
+
+	/* 
+	 *	Assume that we want to add the following multicast address
+	 *	01-50-43-00-01-02.
+	*/
+	macEntry.macAddr.arEther[0] = 0x01;
+	macEntry.macAddr.arEther[1] = 0x50;
+	macEntry.macAddr.arEther[2] = 0x43;
+	macEntry.macAddr.arEther[3] = 0x00;
+	macEntry.macAddr.arEther[4] = 0x01;
+	macEntry.macAddr.arEther[5] = 0x02;
+
+	/*
+	 * 	Assume that a packet needs to be forwarded to the second Port (port 1),
+	 *	the third Port (port 2) and cpu Port, if the frame has destination of
+	 *	01-00-18-1a-00-00.
+	*/
+	macEntry.portVec = 	(1<<1) | /* the second port */
+				(1<<2) | /* the third port */
+				(1<<dev->cpuPortNum);
+
+	macEntry.prio = 0;			/* Priority (2bits). When these bits are used they override
+								any other priority determined by the frame's data. This value is
+								meaningful only if the device does not support extended priority
+								information such as MAC Queue Priority and MAC Frame Priority */
+
+	macEntry.exPrio.macQPri = 0;	/* If device doesnot support MAC Queue Priority override, 
+									this field is ignored. */
+	macEntry.exPrio.macFPri = 0;	/* If device doesnot support MAC Frame Priority override, 
+									this field is ignored. */
+	macEntry.exPrio.useMacFPri = 0;	/* If device doesnot support MAC Frame Priority override, 
+									this field is ignored. */
+
+	macEntry.entryState.ucEntryState = GT_MC_STATIC;
+								/* This address is locked and will not be aged out. 
+								Refer to GT_ATU_MC_STATE in msApiDefs.h for other option.*/
+
+	/* 
+	 *	Add the MAC Address.
+	 */
+	if((status = gfdbAddMacEntry(dev,&macEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbAddMacEntry returned fail.\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ *	Delete the Multicast MAC address of 01-00-18-1a-00-00.
+ *	Input - None
+*/
+GT_STATUS sampleDelMulticastAddr(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_ATU_ENTRY macEntry;
+
+	/* 
+	 *	Assume that Ethernet address for the CPU MAC is
+	 *	01-50-43-00-01-02.
+	*/
+	macEntry.macAddr.arEther[0] = 0x01;
+	macEntry.macAddr.arEther[1] = 0x50;
+	macEntry.macAddr.arEther[2] = 0x43;
+	macEntry.macAddr.arEther[3] = 0x00;
+	macEntry.macAddr.arEther[4] = 0x01;
+	macEntry.macAddr.arEther[5] = 0x02;
+
+	/* 
+	 *	Delete the given Multicast Address.
+	 */
+	if((status = gfdbDelMacEntry(dev,&macEntry.macAddr)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbDelMacEntry returned fail.\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ *	This sample function will show how to display all the MAC address
+ *	in the ATU.
+*/
+GT_STATUS sampleShowMacEntry(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_ATU_ENTRY tmpMacEntry;
+
+	MSG_PRINT(("ATU List:\n"));
+	memset(&tmpMacEntry,0,sizeof(GT_ATU_ENTRY));
+
+	while(1)
+	{
+		/* Get the sorted list of MAC Table. */
+		if((status = gfdbGetAtuEntryNext(dev,&tmpMacEntry)) != GT_OK)
+		{
+			return status;
+		}
+
+		MSG_PRINT(("(%02x-%02x-%02x-%02x-%02x-%02x) PortVec %#x\n",
+				tmpMacEntry.macAddr.arEther[0],
+				tmpMacEntry.macAddr.arEther[1],
+				tmpMacEntry.macAddr.arEther[2],
+				tmpMacEntry.macAddr.arEther[3],
+				tmpMacEntry.macAddr.arEther[4],
+				tmpMacEntry.macAddr.arEther[5],
+				tmpMacEntry.portVec));
+	}
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MACAddress/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MACAddress/readme.txt
new file mode 100755
index 0000000..5448c20
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MACAddress/readme.txt
@@ -0,0 +1,21 @@
+========================================================================

+		MAC Address ADD/DELETE Sample

+========================================================================

+

+This sample will demonstrate how to add/delete a static MAC Address 

+into/from the QuaterDeck MAC Address Data Base and how to enumerate

+all the MAC addresses in the Data Base.

+

+macAddr.c

+	sampleAddCPUMac : show how to add CPU Mac address into the QuterDeck 

+		Database.

+	sampleDelCPUMac : show how to delete CPU Mac address from the database.

+	sampleAddMulticastAddr : show how to add a multicast address into 

+		the QuaterDeck Database.

+	sampleDelMulticastAddr : show how to delete a multicast address.

+	sampleShowMacEntry : show how to get all the Mac addresses in the database.

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MinimizeCPUTraffic/minimizeCPUTraffic.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MinimizeCPUTraffic/minimizeCPUTraffic.c
new file mode 100755
index 0000000..1f51610
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MinimizeCPUTraffic/minimizeCPUTraffic.c
@@ -0,0 +1,186 @@
+#include <Copyright.h>
+/********************************************************************************
+* minizeCPUTraffic.c
+*
+* DESCRIPTION:
+*		This sample shows how to setup the CPU port not to be a member of any 
+*		VLAN, while it still be a manager of a switch. 
+*		
+* DEPENDENCIES:
+*		Please check the device's spec. if the device supports this feature.
+*		At the moment this sample was written, 88E6095 was the only device support
+*		this feature.
+*
+* FILE REVISION NUMBER:
+*
+* COMMENTS:
+*******************************************************************************/
+
+#include "msSample.h"
+
+/*
+	For the devices that support gsysSetARPDest API:
+
+	0) Remove CPU port from VLAN Member Table.
+	   (this sample deals with Port Based Vlan only.)
+	1) Mirror ARPs to the CPU with To_CPU Marvell Tag
+	2) Convert unicast frames directed to the CPU into To_CPU Marvell Tag
+	Assumption : Device ID, Cascading Port, CPU Port, and Interswitch Port are
+		already set properly. For more information, please refer to the 
+		sample/MultiDevice/msApiInit.c
+*/
+
+GT_STATUS sampleMinimizeCPUTraffic1(GT_QD_DEV *dev, GT_U8* macAddr)
+{
+	GT_STATUS status;
+	int i;
+	GT_LPORT memPorts[16], cpuPort;
+	GT_U8 memPortsLen, index;
+    GT_ATU_ENTRY macEntry;
+
+	cpuPort = (GT_LPORT)dev->cpuPortNum;
+
+	/*
+	 *	Remove CPU port from VLAN Member Table.
+	*/ 
+	for(i=0; i<dev->numOfPorts; i++)
+	{
+		if((status = gvlnGetPortVlanPorts(dev,(GT_LPORT)i,memPorts,&memPortsLen)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnGetPortVlanPorts return Failed\n"));
+			return status;
+		}
+
+		for(index=0; index<memPortsLen; index++)
+		{
+			if (memPorts[index] == cpuPort)
+				break;
+		}
+
+		if(index != memPortsLen)
+		{
+			/* CPU Port is the member of the port vlan */
+			if((memPortsLen-1) != index)
+			{
+				memPorts[index] = memPorts[memPortsLen-1];
+			}
+			memPortsLen--;
+
+			if((status = gvlnSetPortVlanPorts(dev,(GT_LPORT)i,memPorts,memPortsLen)) != GT_OK)
+			{
+				MSG_PRINT(("gvlnSetPortVlanPorts return Failed\n"));
+				return status;
+			}
+		}
+	}
+
+	/*
+	 *	Mirror ARPs to the CPU with To_CPU Marvell Tag.
+	*/
+	if((status = gsysSetARPDest(dev,cpuPort)) != GT_OK)
+	{
+		MSG_PRINT(("gsysSetARPDest return Failed\n"));
+		return status;
+	}
+
+	/*
+	 *	Convert unicast frames directed to the CPU into To_CPU Marvell Tag.
+	 *  This sample assumes that DBNum is not used. If DBNum is used,
+	 *  the macEntry has to be added for each DBNum used.
+	*/
+	memset(&macEntry,0,sizeof(GT_ATU_ENTRY));
+	memcpy(macEntry.macAddr.arEther,macAddr,6);
+	macEntry.portVec = 1 << dev->cpuPortNum;
+	macEntry.prio = 0;			/* Priority (2bits). When these bits are used they override
+								any other priority determined by the frame's data */
+	macEntry.entryState.ucEntryState = GT_UC_TO_CPU_STATIC;
+	macEntry.DBNum = 0;
+	macEntry.trunkMember = GT_FALSE;
+
+	if((status = gfdbAddMacEntry(dev,&macEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbAddMacEntry return Failed\n"));
+		return status;
+	}
+
+	
+	return GT_OK;
+}
+
+
+/*
+	For the devices that support gprtSetARPtoCPU API:
+
+	1) Enable ARP to CPU feature fore each port.
+	2) Set Egress Flood Mode to be Block Unknown DA on CPU Port.
+	3) Add CPU Port's MAC into address table.
+	4) Remove Broadcast address from address table.
+*/
+
+GT_STATUS sampleMinimizeCPUTraffic2(GT_QD_DEV *dev, GT_U8* macAddr)
+{
+	GT_STATUS status;
+	int i;
+	GT_LPORT cpuPort;
+    GT_ATU_ENTRY macEntry;
+
+	cpuPort = (GT_LPORT)dev->cpuPortNum;
+
+	/*
+	 *	Remove CPU port from VLAN Member Table.
+	*/ 
+	for(i=0; i<dev->numOfPorts; i++)
+	{
+		if (i == cpuPort)
+			continue;
+
+		if((status = gprtSetARPtoCPU(dev,i,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetARPtoCPU return Failed\n"));
+			return status;
+		}
+	}
+
+	/*
+	 * Set Egress Flood Mode to be Block Unknown DA on CPU Port.
+	*/
+	if((status = gprtSetEgressFlood(dev,cpuPort,GT_BLOCK_EGRESS_UNKNOWN)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetEgressFlood return Failed\n"));
+		return status;
+	}
+
+
+	/*
+	 *	Add CPU's MAC into address table.
+	 *  This sample assumes that DBNum is not used. If DBNum is used,
+	 *  the macEntry has to be added for each DBNum used.
+	*/
+	memset(&macEntry,0,sizeof(GT_ATU_ENTRY));
+	memcpy(macEntry.macAddr.arEther,macAddr,6);
+	macEntry.portVec = 1 << dev->cpuPortNum;
+	macEntry.prio = 0;			/* Priority (2bits). When these bits are used they override
+								any other priority determined by the frame's data */
+	macEntry.entryState.ucEntryState = GT_UC_STATIC;
+	macEntry.DBNum = 0;
+	macEntry.trunkMember = GT_FALSE;
+
+	if((status = gfdbAddMacEntry(dev,&macEntry)) != GT_OK)
+	{
+		MSG_PRINT(("gfdbAddMacEntry return Failed\n"));
+		return status;
+	}
+
+	/*
+	 *  Delete BroadCast Entry from address table if exists.
+	 *  This sample assumes that DBNum is not used. If DBNum is used,
+	 *  the macEntry has to be added for each DBNum used.
+	*/
+	memset(&macEntry,0,sizeof(GT_ATU_ENTRY));
+	memset(macEntry.macAddr.arEther,0xFF,6);
+	gfdbDelAtuEntry(dev,&macEntry);
+	
+	return GT_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MinimizeCPUTraffic/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MinimizeCPUTraffic/readme.txt
new file mode 100755
index 0000000..27311c1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MinimizeCPUTraffic/readme.txt
@@ -0,0 +1,29 @@
+========================================================================

+		Setup for CPU Port which is not a member of any VLAN

+========================================================================

+

+Previous SOHO switch devices were low port count and/or used for Routers.
+In this environment, the CPU must be a member of all VLANs, so it can
+route the frames from one VLAN to another.
+In a high port count managed switch, the CPU is not a router but the 
+manager of the switch. In this environment, the CPU doesn't want to be a 
+member of any VLAN. If it is, it can get saturated with non-management 
+frames preventing it from receiving the important management frames.
+
+In order to support the feature, the following has to be provided:

+

+1. For the devices that support gsysSetARPDest API:
+	0) Remove CPU port from VLAN Member Table.
+	1) Mirror ARPs to the CPU with To_CPU Marvell Tag.
+	2) Convert unicast frames directed to the CPU into To_CPU Marvell Tag.
+

+2. For the devices that support gprtSetARPtoCPU API:
+	0) Remove CPU port from VLAN Member Table.
+	1) Enable ARP to CPU for each port.
+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MultiDevice/msApiInit.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MultiDevice/msApiInit.c
new file mode 100755
index 0000000..d7a7d5b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/MultiDevice/msApiInit.c
@@ -0,0 +1,272 @@
+#include <Copyright.h>
+/********************************************************************************
+* msApiInit.c
+*
+* DESCRIPTION:
+*		MS API initialization routine for devices supporting Multi Address Mode,
+*		such as 88E6183. Following setup will be used for this sample code.
+*
+*	  	------------------
+*		|CPU Ethernet Dev|
+*		------------------
+*		 |		
+*		 |		
+*		 |   8--------------9	 8--------------9	  8--------------
+*		 |----| QD Device 0|------| QD Device 1|-----| QD Device 2|
+*	         --------------		  --------------		--------------
+*		       0 1 2 ... 7			 0 1 2 ... 7		  0 1 2 ... 7
+*
+*
+*		Ethernet port of CPU is connected to port 8 of Device 0,
+*		port 9 of Device 0 is connected to port 8 of Device 1, and
+*		port 9 of Device 1 is connected to port 8 of Device 2.
+*
+*		Device 0 uses Phy Address 1, 
+*		Device 1 uses Phy Address 2, and
+*		Device 2 uses Phy Address 3
+*		Notes: Phy Address 0 cannot be used in a Multi Chip Address Mode.
+*
+*		Each Switch Device has to be configured to Multi Chip Address Mode.
+*		For detailed information for Multi Chip Address Mode configuration,
+*		please refer to your device's Datasheet.
+*
+* DEPENDENCIES:   Platform
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+/*
+#define MULTI_ADDR_MODE
+#define MANUAL_MODE
+*/
+
+#define MULTI_ADDR_MODE
+#define N_OF_QD_DEVICES		3	/* number of 88E6183 devices connected */
+
+#define DEVICE0_ID		10
+#define DEVICE1_ID		DEVICE0_ID + 1
+#define DEVICE2_ID		DEVICE0_ID + 2
+
+#define DEVICE0_PHY_ADDR	1
+#define DEVICE1_PHY_ADDR	DEVICE0_PHY_ADDR + 1
+#define DEVICE2_PHY_ADDR	DEVICE0_PHY_ADDR + 2
+
+#define S_CPU_DEVICE		DEVICE0_ID
+
+#define DEVICE0_CPU_PORT		8
+#define DEVICE0_CASCADE_PORT	9
+#define DEVICE1_CPU_PORT		8
+#define DEVICE1_CASCADE_PORT	9
+#define DEVICE2_CPU_PORT		8
+#define DEVICE2_CASCADE_PORT	9
+
+GT_QD_DEV       *qdMultiDev[N_OF_QD_DEVICES] = {0,};
+
+/*
+ * Initialize each Switch Devices. This should be done in BSP driver init routine.
+ *	Since BSP is not combined with QuarterDeck driver, we are doing here.
+ * This routine will setup Switch Devices according to the above description.
+*/
+
+GT_STATUS qdMultiDevStart()
+{
+	GT_STATUS status = GT_FAIL;
+	GT_SYS_CONFIG   cfg;
+	int cpuPort;
+	int cascadePort;
+	int i,j;
+
+	memset((char*)&cfg,0,sizeof(GT_SYS_CONFIG));
+	
+	/* 
+	 *	Create QD Device Structure for each device.
+	 */
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		qdMultiDev[i] = (GT_QD_DEV*)malloc(sizeof(GT_QD_DEV));
+
+		if(qdMultiDev[i] == NULL)
+		{
+			while(i--)
+				free(qdMultiDev[i]);
+			return GT_FAIL;
+		}
+
+		memset((char*)qdMultiDev[i],0,sizeof(GT_QD_DEV));
+	}
+	
+	/*
+	 *  Register all the required functions to QuarterDeck Driver for each device.
+	*/
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		cfg.BSPFunctions.readMii   = gtBspReadMii;
+		cfg.BSPFunctions.writeMii  = gtBspWriteMii;
+#ifdef USE_SEMAPHORE
+		cfg.BSPFunctions.semCreate = osSemCreate;
+		cfg.BSPFunctions.semDelete = osSemDelete;
+		cfg.BSPFunctions.semTake   = osSemWait;
+		cfg.BSPFunctions.semGive   = osSemSignal;
+#else
+		cfg.BSPFunctions.semCreate = NULL;
+		cfg.BSPFunctions.semDelete = NULL;
+		cfg.BSPFunctions.semTake   = NULL;
+		cfg.BSPFunctions.semGive   = NULL;
+#endif
+
+		cfg.initPorts = GT_TRUE;	/* Set switch ports to Forwarding mode. If GT_FALSE, use Default Setting. */
+		switch (i)
+		{
+			case 0: /* if we are registering device 0 */
+				cfg.cpuPortNum = DEVICE0_CPU_PORT;
+				break;
+			case 1: /* if we are registering device 1 */
+				cfg.cpuPortNum = DEVICE1_CPU_PORT;	/* where device 0 is connected */
+				break;
+			case 2: /* if we are registering device 2 */
+				cfg.cpuPortNum = DEVICE2_CPU_PORT;	/* where device 1 is connected */
+				break;
+			default: /* we don't have any more device. it shouldn't happen in our sample setup. */
+				goto errorExit;
+		}
+
+#ifdef MANUAL_MODE	/* not defined. this is only for sample */
+		/* user may want to use this mode when there are two QD switchs on the same MII bus. */
+		cfg.mode.scanMode = SMI_MANUAL_MODE;	/* Use QD located at manually defined base addr */
+		cfg.mode.baseAddr = 0x10;	/* valid value in this case is either 0 or 0x10 */
+#else
+#ifdef MULTI_ADDR_MODE	/* It should have been defined for this sample code */
+		cfg.mode.scanMode = SMI_MULTI_ADDR_MODE;	/* find a QD in indirect access mode */
+		cfg.mode.baseAddr = DEVICE0_PHY_ADDR + i;		/* this is the phyAddr used by QD family device. 
+																		Valid values are 1 ~ 31.*/
+#else
+		cfg.mode.scanMode = SMI_AUTO_SCAN_MODE;	/* Scan 0 or 0x10 base address to find the QD */
+		cfg.mode.baseAddr = 0;
+#endif
+#endif
+
+		if((status=qdLoadDriver(&cfg, qdMultiDev[i])) != GT_OK)
+		{
+			MSG_PRINT(("qdLoadDriver return Failed\n"));
+			goto errorExit;
+		}
+
+		MSG_PRINT(("Device ID     : 0x%x\n",qdMultiDev[i]->deviceId));
+		MSG_PRINT(("Base Reg Addr : 0x%x\n",qdMultiDev[i]->baseRegAddr));
+		MSG_PRINT(("No of Ports   : %d\n",qdMultiDev[i]->numOfPorts));
+		MSG_PRINT(("CPU Ports     : %d\n",qdMultiDev[i]->cpuPortNum));
+
+		/*
+		 *  start the QuarterDeck
+		*/
+		if((status=sysEnable(qdMultiDev[i])) != GT_OK)
+		{
+			MSG_PRINT(("sysConfig return Failed\n"));
+			goto errorExit;
+		}
+	}
+
+	/* 
+		Now, we need to configure Cascading information for each devices.
+		1. Set Interswitch port mode for port 8 and 9 for device 0,1,and 2,
+			so that switch device can expect Marvell Tag from frames 
+			ingressing/egressing this port.
+		2. Set CPU Port information (for To_CPU frame) for each port of device.
+		3. Set Cascading Port information (for From_CPU fram) for each device.
+		4. Set Device ID (if required)
+			Note: DeviceID is hardware configurable.
+	*/
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		switch (i)
+		{
+			case 0: /* if we are registering device 0 */
+				cpuPort = DEVICE0_CPU_PORT; 		/* where CPU Enet port is connected */
+				cascadePort = DEVICE0_CASCADE_PORT;	/* where device 1 is connected */
+				break;
+			case 1: /* if we are registering device 1 */
+				cpuPort = DEVICE1_CPU_PORT; 		/* where device 0 is connected */
+				cascadePort = DEVICE1_CASCADE_PORT;	/* where device 2 is connected */
+				break;
+			case 2: /* if we are registering device 2 */
+				cpuPort = DEVICE2_CPU_PORT; 		/* where device 1 is connected */
+				cascadePort = DEVICE2_CASCADE_PORT;	/* no need to setup for the given sample setup */
+				break;
+			default: /* we don't have any more device. it shouldn't happen in our sample setup. */
+				goto errorExit;
+		}
+
+		/*
+			1. Set Interswitch port mode for port 8 and 9 for device 0,1,and 2,
+				so that switch device can expect Marvell Tag from frames 
+				ingressing/egressing this port.
+			2. Set CPU Port information (for To_CPU frame) for each port of device.
+		*/			
+		for(j=0; j<qdMultiDev[i]->numOfPorts; j++)
+		{
+			if((i == cpuPort) || (i == cascadePort))
+			{
+				if((status=gprtSetInterswitchPort(qdMultiDev[i],j,GT_TRUE)) != GT_OK)
+				{
+					MSG_PRINT(("gprtSetInterswitchPort returned %i (port %i, mode TRUE)\n",status,j));
+					goto errorExit;
+				}
+			}
+			else
+			{
+				if((status=gprtSetInterswitchPort(qdMultiDev[i],j,GT_FALSE)) != GT_OK)
+				{
+					MSG_PRINT(("gprtSetInterswitchPort returned %i (port %i, mode FALSE)\n",status,j));
+					goto errorExit;
+				}
+			}
+
+			if((status=gprtSetCPUPort(qdMultiDev[i],j,cpuPort)) != GT_OK)
+			{
+				MSG_PRINT(("gprtSetCPUPort returned %i\n",status));
+				goto errorExit;
+			}
+		}
+
+		/*
+			3. Set Cascading Port information (for From_CPU fram) for each device.
+		*/	 	
+		if((status=gsysSetCascadePort(qdMultiDev[i],cascadePort)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetCascadePort returned %i\n",status));
+			goto errorExit;
+		}
+
+		/*
+			4. Set Device ID (if required)
+		*/	 	
+		if((status=gsysSetDeviceNumber(qdMultiDev[i],DEVICE0_ID+i)) != GT_OK)
+		{
+			MSG_PRINT(("gsysSetDeviceNumber returned %i\n",status));
+			goto errorExit;
+		}
+
+	}	
+
+	MSG_PRINT(("QuarterDeck has been started.\n"));
+
+	return GT_OK;
+
+errorExit:
+
+	for(i=0; i<N_OF_QD_DEVICES; i++)
+	{
+		if(qdMultiDev[i] != NULL)
+		{
+			qdUnloadDriver(qdMultiDev[i]);
+	  		free(qdMultiDev[i]);
+		}
+	}	
+
+	MSG_PRINT(("QuarterDeck initialization failed.\n"));
+
+	return status;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/pirl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/pirl.c
new file mode 100755
index 0000000..0ad4d0e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/pirl.c
@@ -0,0 +1,93 @@
+#include <Copyright.h>
+/********************************************************************************
+* pirl.c
+*
+* DESCRIPTION:
+*       Setup PIRL buckets
+*
+* DEPENDENCIES:   None.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+
+/*
+ *  This setup function configures the Port 0 of Marvell SOHO Switch Device with
+ *	capability of PIRL to be :
+ *	
+ *	1) Ingress Rate    : 128Kbps (128K bit per sec)
+ *	2) Discarded frame : Do not account discarded frame due to queue congestion
+ *	3) Filtered frame  : Account filtered frame
+ *	4) Limit action    : Drop packets when the incoming rate exceeds the limit
+ *	5) Rate type       : Rate is based on Traffic type
+ *	6) Traffic type    : ARP, MGMT, Multicast, Broadcast, and Unicast frames are 
+ *						 tracked as part of the rate resource calculation.
+ *	7) Byte counted    : Account only Layer 3 bytes (IP header and payload)
+ *
+ *	Notes: This sample uses IRL Unit 0. The available number of IRL Units are 
+ *	various depending on the device. Please refer to the datasheet for detailed
+ *	information.
+ *
+ *	Notes: Port 0 will be blocked while programming PIRL.
+*/
+
+GT_STATUS samplePIRLSetup(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_PIRL_DATA pirlData;
+	GT_U32		irlUnit;
+	GT_LPORT 	port;
+
+	/* change Current Timer Update Interval */
+	status = gpirlSetCurTimeUpInt(dev,4);	
+	switch (status)
+	{
+		case GT_OK:
+			break;
+		case GT_NOT_SUPPORTED:
+			MSG_PRINT(("Device is not supporting PIRL.\n"));
+			return status;
+		default:
+			MSG_PRINT(("Failure to configure device.\n"));
+			return status;
+	}
+
+	irlUnit = 0;
+	port = 0;
+
+	pirlData.ingressRate 		= 128;
+	pirlData.accountQConf 		= GT_FALSE;
+	pirlData.accountFiltered	= GT_TRUE;
+	pirlData.ebsLimitAction		= ESB_LIMIT_ACTION_DROP;
+	pirlData.bktRateType		= BUCKET_TYPE_TRAFFIC_BASED;
+	pirlData.bktTypeMask		= BUCKET_TRAFFIC_BROADCAST |
+								  BUCKET_TRAFFIC_MULTICAST |
+								  BUCKET_TRAFFIC_UNICAST   |
+								  BUCKET_TRAFFIC_MGMT_FRAME|
+								  BUCKET_TRAFFIC_ARP;
+
+	pirlData.byteTobeCounted	= GT_PIRL_COUNT_ALL_LAYER3;
+
+	status = gpirlActivate(dev,irlUnit,(1<<port),&pirlData);
+
+	switch (status)
+	{
+		case GT_OK:
+			MSG_PRINT(("IRL Unit 0 is activated.\n"));
+			break;
+		case GT_BAD_PARAM:
+			MSG_PRINT(("Invalid parameters are given.\n"));
+			break;
+		case GT_NOT_SUPPORTED:
+			MSG_PRINT(("Device is not supporting PIRL.\n"));
+			break;
+		default:
+			MSG_PRINT(("Failure to configure device.\n"));
+			break;
+	}
+
+	return status;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/pirl2.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/pirl2.c
new file mode 100755
index 0000000..64f00c2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/pirl2.c
@@ -0,0 +1,201 @@
+#include <Copyright.h>
+/********************************************************************************
+* pirl2.c
+*
+* DESCRIPTION:
+*       Setup PIRL buckets for 88E6097 device family
+*
+* DEPENDENCIES:   None.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+
+/*
+ *  This setup function configures the resource 0 of Port 0 of Marvell SOHO 
+ *	Switch Device with capability of PIRL to be :
+ *	
+ *	1) Ingress Rate    : 128Kbps (128K bit per sec)
+ *	2) Custom setup for Ingress Rate : disabled
+ *	3) Discarded frame : Do not account discarded frame due to queue congestion
+ *	4) Filtered frame  : Account filtered frame
+ *	5) Mgmt frame      : Exclude management frame from rate limiting calculation
+ *	6) SA found in ATU : Exclude from ingress rate limiting calculation if the SA of the
+ *						 frame is in ATU with EntryState that indicates Non Rate Limited.
+ *	7) DA found in ATU : Include to ingress rate limiting calculation even though the DA of the
+ *						 frame is in ATU with EntryState that indicates Non Rate Limited.
+ *	8) Sampling Mode   : Disable the mode
+ *	9) Action Mode     : Follow Limit action when there are not enough tokens to accept the
+ *						 entire imcoming frame.
+ *	10) Limit action   : Drop packets when the incoming rate exceeds the limit
+ *	11) Rate type      : Rate is based on Traffic type
+ *	12) Traffic type   : ARP, MGMT, Multicast, Broadcast, and Unicast frames are 
+ *					  	 tracked as part of the rate resource calculation.
+ *	13) Byte counted   : Account only Layer 3 bytes (IP header and payload)
+ *
+*/
+
+GT_STATUS samplePIRL2Setup(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_PIRL2_DATA pirlData;
+	GT_U32		irlRes;
+	GT_LPORT 	port;
+
+	/* change Current Timer Update Interval */
+	status = gpirl2SetCurTimeUpInt(dev,4);	
+	switch (status)
+	{
+		case GT_OK:
+			break;
+		case GT_NOT_SUPPORTED:
+			MSG_PRINT(("Device is not supporting PIRL.\n"));
+			return status;
+		default:
+			MSG_PRINT(("Failure to configure device.\n"));
+			return status;
+	}
+
+	port = 0;
+	irlRes = 0;
+
+	pirlData.ingressRate 		= 128;
+
+	pirlData.customSetup.isValid = GT_FALSE;
+
+	pirlData.accountQConf 		= GT_FALSE;
+	pirlData.accountFiltered	= GT_TRUE;
+
+	pirlData.mgmtNrlEn = GT_TRUE;
+	pirlData.saNrlEn   = GT_TRUE;
+	pirlData.daNrlEn   = GT_FALSE;
+	pirlData.samplingMode = GT_FALSE;
+	pirlData.actionMode = PIRL_ACTION_USE_LIMIT_ACTION;
+
+	pirlData.ebsLimitAction		= ESB_LIMIT_ACTION_DROP;
+	pirlData.bktRateType		= BUCKET_TYPE_TRAFFIC_BASED;
+	pirlData.bktTypeMask		= BUCKET_TRAFFIC_BROADCAST |
+								  BUCKET_TRAFFIC_MULTICAST |
+								  BUCKET_TRAFFIC_UNICAST   |
+								  BUCKET_TRAFFIC_MGMT_FRAME|
+								  BUCKET_TRAFFIC_ARP;
+
+	pirlData.priORpt = GT_TRUE;
+	pirlData.priMask = 0;
+
+	pirlData.byteTobeCounted	= GT_PIRL2_COUNT_ALL_LAYER3;
+
+	status = gpirl2WriteResource(dev,port,irlRes,&pirlData);
+
+	switch (status)
+	{
+		case GT_OK:
+			MSG_PRINT(("PIRL2 writing completed.\n"));
+			break;
+		case GT_BAD_PARAM:
+			MSG_PRINT(("Invalid parameters are given.\n"));
+			break;
+		case GT_NOT_SUPPORTED:
+			MSG_PRINT(("Device is not supporting PIRL2.\n"));
+			break;
+		default:
+			MSG_PRINT(("Failure to configure device.\n"));
+			break;
+	}
+
+	return status;
+}
+
+
+
+/*
+ *	This setup function shows how to configure Ingress Rate of 128Kbps with the
+ *	custom data information.
+ *  it configures the resource 0 of Port 0 of Marvell SOHO Switch Device with 
+ *	capability of PIRL to be :
+ *	
+ *	1) Custom setup for Ingress Rate : Enabled
+ *	2) Custom EBS Limit : 0xFFFFFF
+ *	3) Custom CBS Limit : 0x200000
+ *	4) Custom Bucket Increament  : 0x3D
+ *	5) Custom Bucket Rate Factor : 2
+ *	6) Discarded frame : Do not account discarded frame due to queue congestion
+ *	7) Filtered frame  : Account filtered frame
+ *	8) Mgmt frame      : Exclude management frame from rate limiting calculation
+ *	9) SA found in ATU : Exclude from ingress rate limiting calculation if the SA of the
+ *						 frame is in ATU with EntryState that indicates Non Rate Limited.
+ *	10) DA found in ATU : Include to ingress rate limiting calculation even though the DA of the
+ *						 frame is in ATU with EntryState that indicates Non Rate Limited.
+ *	11) Sampling Mode   : Disable the mode
+ *	12) Action Mode     : Follow Limit action when there are not enough tokens to accept the
+ *						 entire imcoming frame.
+ *	13) Limit action   : Drop packets when the incoming rate exceeds the limit
+ *	14) Rate type      : Rate is based on Traffic type
+ *	15) Traffic type   : ARP, MGMT, Multicast, Broadcast, and Unicast frames are 
+ *					  	 tracked as part of the rate resource calculation.
+ *	16) Byte counted   : Account only Layer 3 bytes (IP header and payload)
+ *
+*/
+
+GT_STATUS samplePIRL2CustomSetup(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_PIRL2_DATA pirlData;
+	GT_U32		irlRes;
+	GT_LPORT 	port;
+
+	port = 0;
+	irlRes = 0;
+
+	pirlData.customSetup.isValid = GT_TRUE;
+	pirlData.customSetup.ebsLimit = 0xFFFFFF;
+	pirlData.customSetup.cbsLimit = 0x200000;
+	pirlData.customSetup.bktIncrement = 0x3D;
+	pirlData.customSetup.bktRateFactor = 2;
+
+	pirlData.accountQConf 		= GT_FALSE;
+	pirlData.accountFiltered	= GT_TRUE;
+
+	pirlData.mgmtNrlEn = GT_TRUE;
+	pirlData.saNrlEn   = GT_TRUE;
+	pirlData.daNrlEn   = GT_FALSE;
+	pirlData.samplingMode = GT_FALSE;
+	pirlData.actionMode = PIRL_ACTION_USE_LIMIT_ACTION;
+
+	pirlData.ebsLimitAction		= ESB_LIMIT_ACTION_DROP;
+	pirlData.bktRateType		= BUCKET_TYPE_TRAFFIC_BASED;
+	pirlData.bktTypeMask		= BUCKET_TRAFFIC_BROADCAST |
+								  BUCKET_TRAFFIC_MULTICAST |
+								  BUCKET_TRAFFIC_UNICAST   |
+								  BUCKET_TRAFFIC_MGMT_FRAME|
+								  BUCKET_TRAFFIC_ARP;
+
+	pirlData.priORpt = GT_TRUE;
+	pirlData.priMask = 0;
+
+	pirlData.byteTobeCounted	= GT_PIRL2_COUNT_ALL_LAYER3;
+
+	status = gpirl2WriteResource(dev,port,irlRes,&pirlData);
+
+	switch (status)
+	{
+		case GT_OK:
+			MSG_PRINT(("PIRL2 writing completed.\n"));
+			break;
+		case GT_BAD_PARAM:
+			MSG_PRINT(("Invalid parameters are given.\n"));
+			break;
+		case GT_NOT_SUPPORTED:
+			MSG_PRINT(("Device is not supporting PIRL2.\n"));
+			break;
+		default:
+			MSG_PRINT(("Failure to configure device.\n"));
+			break;
+	}
+
+	return status;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/readme.txt
new file mode 100755
index 0000000..6f61a1b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PIRL/readme.txt
@@ -0,0 +1,25 @@
+==================================================================
+		PIRL (Port based Ingress Rate Limit) Setup 
+==================================================================
+
+88E6065 device family, 88E6097 device family, and recent Marvell SOHO 
+Switch Devices support 'Best-in-Class' per port TCP/IP ingress rate limiting 
+(based on some kind of a bucket scheme to keep track of the bandwidth) along 
+with independent Storm prevention. 
+
+This sample shows how to use PIRL resources.
+
+pirl.c
+    this sample routines support 88E6065 device family.
+	
+pirl2.c
+    this sample routines support 88E6097 device family.
+
+	
+
+
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PTP/ptp.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PTP/ptp.c
new file mode 100755
index 0000000..cc0e62f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PTP/ptp.c
@@ -0,0 +1,276 @@
+#include <Copyright.h>
+/********************************************************************************
+* ptp.c
+*
+* DESCRIPTION:
+*       Setup PTP for 88E6165 device family.
+*
+* DEPENDENCIES:   None.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+
+/*
+ *  PTP Init routine
+ *	
+ *	1) Setup each port to forward PTP frame to CPU port
+ *	2) Enable PTP Interrupt (assumes that no other interrupt is used, but PTP)
+ *	3) Configure PTP
+ *	4) Enable PTP
+ *
+ *	Notes: This sample uses the following configuration
+ *	1) Enables only PTP interrupt
+ *	2) Assumes PTP Ethernet Type is 0x88F7
+ *	3) Time Stamp is enabled only for Message ID 0, 2, and 3
+ *	4) Message ID 0 and 2 use Arr0 pointer and ID 3 uses Arr1 pointer
+ *	5) PTP interrtups are enabled on Port 0 ~ 5
+ *
+ *	Notes: Forwarding PTP fram to CPU port is based on Ether Type DSA Tag (8 bytes).
+ *	Therefore, Ethernet device driver, that actually rx/tx the PTP frame,
+ *	should expect/insert Ether Type DSA Tag.
+*/
+
+STATUS samplePTPInit(GT_QD_DEV *dev)
+{
+ 	GT_PTP_CONFIG ptpCfg;
+	GT_LPORT port;
+	GT_STATUS status;
+
+
+	/*
+	 *	1) Setup each port to forward PTP frame to CPU port
+	*/
+
+	/* setup EtypeType and Policy */
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		if ((status = gprtSetPortEType(dev, port, (GT_ETYPE)0x88F7)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortEType returned not OK\n"));
+			return status;
+		}
+
+		if (port == dev->cpuPortNum)
+			continue;
+
+		if ((status = gprtSetPolicy(dev, port, POLICY_TYPE_ETYPE, FRAME_POLICY_TRAP)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPolicy returned not OK\n"));
+			return status;
+		}
+	}
+
+	/* setup Frame Mode for CPU port */
+	if ((status = gprtSetFrameMode(dev, dev->cpuPortNum, GT_FRAME_MODE_ETHER_TYPE_DSA)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetFrameMode return failed\n"));
+		return status;
+	}
+
+	/*
+	 *	2) Enable PTP Interrupt
+	*/
+	eventSetActive(dev, GT_AVB_INT);
+
+
+	/*
+	 *	3) Configure PTP
+	*/
+	ptpCfg.ptpEType = 0x88F7;
+	ptpCfg.msgIdTSEn = 0xd;		/* id 0, 2, and 3 */
+	ptpCfg.tsArrPtr = 0x8;		/* id 0 and 2 for ARR0, id 3 for ARR1 */
+
+	/* Transport specific bits present in PTP Common Header */
+	ptpCfg.transSpec = 1;		
+
+	/* starting bit location for the Message ID field in the PTP Common Header */
+	ptpCfg.msgIdStartBit = 4;	
+
+	ptpCfg.ptpArrIntEn = 0x3F;
+	ptpCfg.ptpDepIntEn = 0x3F;
+	ptpCfg.disTSOverwrite = 0;
+
+
+	if ((status = gptpSetConfig(dev, &ptpCfg)) != GT_OK)
+	{
+		MSG_PRINT(("gptpSetConfig return failed\n"));
+		return status;
+	}
+	if ((status = gptpSetPTPEn(dev, GT_TRUE)) != GT_OK)
+	{
+		MSG_PRINT(("gptpSetPTPEn return failed\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ *  PTP Interrupt Handler
+ *	
+ *	1) for each port that causes PTP interrup, do the followings
+ *	2) check Arrival 0 Time Stamp
+ *	3) check Arrival 1 Time Stamp
+ *	4) check Departure Time Stamp
+*/
+
+STATUS samplePTPIntHandler(GT_QD_DEV *dev)
+{
+	GT_U32 int_ports, i, int_status;
+	GT_STATUS status;
+	GT_PTP_TS_STATUS	ptpStatus;
+
+	/* disable AVB Interrupt */
+	eventSetActive(dev, 0);
+
+	/* read interrupt cause */
+	eventGetIntStatus(dev,(GT_U16*)&int_status);
+	if ((int_status & GT_AVB_INT) == 0)
+	{
+		/* it's not PTP interrupt */
+		return GT_FAIL;	
+	}
+
+	/* read AVB Int status */
+	if((status = gptpGetPTPInt(dev, &int_ports)) != GT_OK)
+	{
+	    MSG_PRINT(("gptpGetPTPInt return failed\n"));
+		goto ret_int;
+	}
+
+	/* for each port, get the timestamp information if necessary */
+	i = 0;
+	while(int_ports)
+	{
+		if(!(int_ports & 0x1))
+		{
+			i++;
+			int_ports >>= 1;
+			continue;
+		}
+
+		/* check Arrival0 Time Stamp */
+		if((status = gptpGetTimeStamped(dev, i, PTP_ARR0_TIME, &ptpStatus)) != GT_OK)
+		{
+		    MSG_PRINT(("gptpGetTimeStamped return failed\n"));
+			goto ret_int;
+		}
+
+		if (ptpStatus.isValid == GT_TRUE)
+		{
+			switch(ptpStatus.status)
+			{
+				case PTP_INT_NORMAL:
+					/* To Do: No error condition occurred. So store the time stamp and seqId */
+					break;
+
+				case PTP_INT_OVERWRITE:
+					/* To Do: PTP Logic received several PTP frames and only the last one is valid */
+					break;
+
+				case PTP_INT_DROP:
+					/* To Do: PTP Logic received several PTP frames and only the first one is valid */
+					break;
+
+				default:
+				    MSG_PRINT(("unknown ptp status %i\n", ptpStatus.status));
+					status = GT_FAIL;
+					goto ret_int;
+
+			}
+
+			if((status = gptpResetTimeStamp(dev, i, PTP_ARR0_TIME)) != GT_OK)
+			{
+			    MSG_PRINT(("gptpResetTimeStamp return failed\n"));
+				goto ret_int;
+			}
+		}
+		
+		/* check Arrival1 Time Stamp */
+		if((status = gptpGetTimeStamped(dev, i, PTP_ARR1_TIME, &ptpStatus)) != GT_OK)
+		{
+		    MSG_PRINT(("gptpGetTimeStamped return failed\n"));
+			goto ret_int;
+		}
+
+		if (ptpStatus.isValid == GT_TRUE)
+		{
+			switch(ptpStatus.status)
+			{
+				case PTP_INT_NORMAL:
+					/* To Do: No error condition occurred. So store the time stamp and seqId */
+					break;
+
+				case PTP_INT_OVERWRITE:
+					/* To Do: PTP Logic received several PTP frames and only the last one is valid */
+					break;
+
+				case PTP_INT_DROP:
+					/* To Do: PTP Logic received several PTP frames and only the first one is valid */
+					break;
+
+				default:
+				    MSG_PRINT(("unknown ptp status %i\n", ptpStatus.status));
+					status = GT_FAIL;
+					goto ret_int;
+			}
+
+			if((status = gptpResetTimeStamp(dev, i, PTP_ARR1_TIME)) != GT_OK)
+			{
+			    MSG_PRINT(("gptpResetTimeStamp return failed\n"));
+				goto ret_int;
+			}
+
+		}
+		
+		/* check Departure Time Stamp */
+		if((status = gptpGetTimeStamped(dev, i, PTP_DEP_TIME, &ptpStatus)) != GT_OK)
+		{
+		    MSG_PRINT(("gptpGetTimeStamped return failed\n"));
+			goto ret_int;
+		}
+
+		if (ptpStatus.isValid == GT_TRUE)
+		{
+			switch(ptpStatus.status)
+			{
+				case PTP_INT_NORMAL:
+					/* To Do: No error condition occurred. So store the time stamp and seqId */
+					break;
+
+				case PTP_INT_OVERWRITE:
+					/* To Do: PTP Logic received several PTP frames and only the last one is valid */
+					break;
+
+				case PTP_INT_DROP:
+					/* To Do: PTP Logic received several PTP frames and only the first one is valid */
+					break;
+
+				default:
+				    MSG_PRINT(("unknown ptp status %i\n", ptpStatus.status));
+					status = GT_FAIL;
+					goto ret_int;
+			}
+
+			if((status = gptpResetTimeStamp(dev, i, PTP_DEP_TIME)) != GT_OK)
+			{
+			    MSG_PRINT(("gptpResetTimeStamp return failed\n"));
+				goto ret_int;
+			}
+
+		}
+		
+		int_ports >>= 1;
+					
+	}
+
+ret_int:
+	eventSetActive(dev, GT_AVB_INT);
+
+	return status;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PTP/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PTP/readme.txt
new file mode 100755
index 0000000..9a160c2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PTP/readme.txt
@@ -0,0 +1,17 @@
+==================================================================
+                PTP (Precise Time Protocol) Setup 
+==================================================================
+
+88E6165 device family Switch Devices support PTP.
+
+This sample shows how to use PTP APIs.
+
+
+	
+
+
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PktGen/phyPktGenSample.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PktGen/phyPktGenSample.c
new file mode 100755
index 0000000..26d081a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PktGen/phyPktGenSample.c
@@ -0,0 +1,86 @@
+#include <Copyright.h>
+/********************************************************************************
+* phyPktGenSample.c
+*
+* DESCRIPTION:
+*       Packet Generator setup sample (startPktGenerator and stopPktGenerator).
+*
+* DEPENDENCIES:
+*		Please check the phy device's spec. if the device supports this feature.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+
+/*
+ * Start Packet Generator.
+ * Input:
+ *      pktload - enum GT_PG_PAYLOAD (GT_PG_PAYLOAD_RANDOM or GT_PG_PAYLOAD_5AA5)
+ *      length  - enum GT_PG_LENGTH  (GT_PG_LENGTH_64 or GT_PG_LENGTH_1514)
+ *      tx      - enum GT_PG_TX      (GT_PG_TX_NORMAL or GT_PG_TX_ERROR)
+*/
+GT_STATUS startPktGenerator
+(
+    GT_QD_DEV      *dev,
+    GT_LPORT       port,
+    GT_PG_PAYLOAD  payload,
+    GT_PG_LENGTH   length,
+    GT_PG_TX       tx
+)
+{
+    GT_STATUS status;
+    GT_PG     pktInfo;
+
+    if (dev == 0)
+    {
+        MSG_PRINT(("GT driver is not initialized\n"));
+        return GT_FAIL;
+    }
+
+    MSG_PRINT(("Start Packet Generator for port %i\n",(int)port));
+
+    pktInfo.payload = payload; /* Pseudo-random, 5AA55AA5... */
+    pktInfo.length = length;   /* 64 bytes, 1514 bytes */
+    pktInfo.tx = tx;           /* normal packet, error packet */
+
+    /*
+     *	Start Packet Generator
+    */
+    if((status = gprtSetPktGenEnable(dev,port,GT_TRUE,&pktInfo)) != GT_OK)
+    {
+        MSG_PRINT(("mdDiagSetPktGenEnable return Failed\n"));
+        return status;
+    }
+
+    return GT_OK;
+}
+
+
+/*
+ * Stop Packet Generator.
+ */
+GT_STATUS stopPktGenerator(GT_QD_DEV *dev,GT_LPORT port)
+{
+    GT_STATUS status;
+
+    if (dev == 0)
+    {
+        MSG_PRINT(("GT driver is not initialized\n"));
+        return GT_FAIL;
+    }
+
+    MSG_PRINT(("Stopping Packet Generator for port %i\n",(int)port));
+
+    /*
+     *	Start Packet Generator
+    */
+    if((status = gprtSetPktGenEnable(dev,port,GT_FALSE,NULL)) != GT_OK)
+    {
+        MSG_PRINT(("mdDiagSetPktGenEnable return Failed\n"));
+        return status;
+    }
+
+    return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PktGen/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PktGen/readme.txt
new file mode 100755
index 0000000..b707429
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PktGen/readme.txt
@@ -0,0 +1,20 @@
+

+            Sample for Packet Generator

+=======================================================

+

+This sample shows how to start/stop Packet Generator.

+

+Main Functions:

+    startPktGenerator - start Packet Generator

+    stopPktGenerator  - stop Packet Generator

+

+Used APIs:

+    gprtSetPktGenEnable

+		

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PortMonitor/portMonitor.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PortMonitor/portMonitor.c
new file mode 100755
index 0000000..2d5e99a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PortMonitor/portMonitor.c
@@ -0,0 +1,108 @@
+#include <Copyright.h>
+/********************************************************************************
+* portMonitor.c
+*
+* DESCRIPTION:
+*		This sample shows how to monitor a certain port. Port monitoring is 
+*		supported by the ClipperShip device with Egress only monitoring or 
+*		Egress and Ingress monitoring.
+*
+* DEPENDENCIES:
+*		Only ClipperShip Family supports this feature.
+*
+* FILE REVISION NUMBER:
+*
+* COMMENTS:
+*******************************************************************************/
+
+#include "msSample.h"
+
+/*
+ *	Enable EgressMonitoring for the monitoredPort.
+ *	With this setup, monitoringPort will receive every packet 
+ *	which egressed from monitoredPort.
+*/
+GT_STATUS sampleEgressMonitor(GT_QD_DEV *dev,GT_LPORT monitoredPort, GT_LPORT monitoringPort)
+{
+	GT_STATUS status;
+	GT_U16 pav;
+
+	/*
+	 *	Enable EgressMonitoring for the monitoredPort.
+	*/
+	pav = (1<<monitoringPort) || (1<<monitoredPort);
+
+	if((status = gpavSetPAV(dev,monitoredPort, pav)) != GT_OK)
+	{
+		MSG_PRINT(("gpavSetPAV return Failed\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+/*
+ *	Enable Egress Monitoring and Ingress Monitoring for the monitoredPort.
+ *	With this setup, monitoringPort will receive every packet 
+ *	which is both from monitoredPort and to monitoredPort.
+*/
+GT_STATUS samplePortMonitor(GT_QD_DEV *dev,GT_LPORT monitoredPort, GT_LPORT monitoringPort)
+{
+	GT_STATUS status;
+	GT_U16 pav;
+
+	/*
+	 *	Enable Egress Monitoring for the monitoredPort.
+	*/
+	pav = (1<<monitoringPort) || (1<<monitoredPort);
+
+	if((status = gpavSetPAV(dev,monitoredPort, pav)) != GT_OK)
+	{
+		MSG_PRINT(("gpavSetPAV return Failed\n"));
+		return status;
+	}
+
+	/*
+	 *	Enable Ingress Monitoring for the monitoredPort.
+	*/
+	if((status = gpavSetIngressMonitor(dev,monitoredPort, GT_TRUE)) != GT_OK)
+	{
+		MSG_PRINT(("gpavSetIngressMonitor return Failed\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ *	Disable Egress Monitoring and Ingress Monitoring for the monitoredPort.
+*/
+GT_STATUS sampleDisablePortMonitor(GT_QD_DEV *dev,GT_LPORT monitoredPort)
+{
+	GT_STATUS status;
+	GT_U16 pav;
+
+	/*
+	 *	Disable Egress Monitoring for the monitoredPort.
+	*/
+	pav = (1<<monitoredPort);
+
+	if((status = gpavSetPAV(dev,monitoredPort, pav)) != GT_OK)
+	{
+		MSG_PRINT(("gpavSetPAV return Failed\n"));
+		return status;
+	}
+
+	/*
+	 *	Disable Ingress Monitoring for the monitoredPort.
+	*/
+	if((status = gpavSetIngressMonitor(dev,monitoredPort, GT_FALSE)) != GT_OK)
+	{
+		MSG_PRINT(("gpavSetIngressMonitor return Failed\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PortMonitor/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PortMonitor/readme.txt
new file mode 100755
index 0000000..33af741
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/PortMonitor/readme.txt
@@ -0,0 +1,28 @@
+========================================================================

+		Port Monitor Setup

+========================================================================

+

+88E6063 device supports Port Monitoring, which allows a user to monitor
+all the traffic of a certain port. 
+This sample shows how to enable/disable Port Monitoring.

+For more information about Port Monitoring, please refer to 88E6063 Spec.

+
+Note :
+Port monitoring supported by ClipperShip has two modes:

+1. Egress only monitoring (monitor packets comming out of the 
+monitored port, and

+2. Egress and Ingress monitoring (monitor packet comming in and out
+from the monitored port)

+

+portMonitor.c

+	sampleEgressMonitor can be used to enable Egress only port monitoring.
+	samplePortMonitor can be used to enable Egress and Ingress monitoring.
+	sampleDisablePortMonitor can be used to disable monitoring 
+	(both Egress only mode and Egress and Ingress mode).

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/QoSSetup/qos.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/QoSSetup/qos.c
new file mode 100755
index 0000000..056faee
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/QoSSetup/qos.c
@@ -0,0 +1,196 @@
+#include <Copyright.h>
+/********************************************************************************
+* qos.c
+*
+* DESCRIPTION:
+*       Sample program which will show how to setup the Priority Queue for QoS
+*		
+*
+* DEPENDENCIES:   None.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+/*
+ *	sampleQoS will enable using both IEEE 802.3ac Tag and IPv4/IPv6 Traffic 
+ *	Class field and IEEE 802.3ac has a higher priority than IPv4/IPv6. 
+ *	The following is the QoS mapping programmed by sampleQos:
+ *	1) IEEE 802.3ac Tag (Priority 0 ~ 7, 3 bits)
+ *		Priority 1~3 is using QuarterDeck Queue 0.
+ *		Priority 0,4 is using QuarterDeck Queue 1.
+ *		Priority 6,7 is using QuarterDeck Queue 2.
+ *		Priority 5 is using QuarterDeck Queue 3.
+ *	2) IPv4/IPv6 (Priority 0 ~ 63, 6 bits)
+ *		Priority 0~7 is using QuaterDeck Queue 0.
+ *		Priority 8~31 is using QuaterDeck Queue 1.
+ *		Priority 32~55 is using QuaterDeck Queue 2.
+ *		Priority 56~63 is using QuaterDeck Queue 3.
+ *	3) Each port's default priority is set to 1.
+*/
+GT_STATUS sampleQos(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_U8 priority;
+	GT_LPORT port;
+
+	for(port=0; port<7; port++)
+	{
+		/*
+		 *  Use IEEE Tag
+		 */
+		if((status = gqosUserPrioMapEn(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gqosUserPrioMapEn return Failed\n"));
+			return status;
+		}
+
+		/*
+		 *  Use IPv4/IPv6 priority fields (use IP)
+		 */
+		if((status = gqosIpPrioMapEn(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gqosIpPrioMapEn return Failed\n"));
+			return status;
+		}
+
+		/*
+		 *  IEEE Tag has higher priority than IP priority fields
+		 */
+		if((status = gqosSetPrioMapRule(dev,port,GT_TRUE)) != GT_OK)
+		{
+			MSG_PRINT(("gqosSetPrioMapRule return Failed\n"));
+			return status;
+		}
+	}
+
+	/*
+	 *	IEEE 802.3ac Tag (Priority 0 ~ 7, 3 bits)
+	 *	Priority 1~3 is using QuarterDeck Queue 0.
+	 *	Priority 0,4 is using QuarterDeck Queue 1.
+	 *	Priority 6,7 is using QuarterDeck Queue 2.
+	 *	Priority 5 is using QuarterDeck Queue 3.
+	*/
+
+	/*	Priority 0 is using QuarterDeck Queue 1. */
+	if((status = gcosSetUserPrio2Tc(dev,0,1)) != GT_OK)
+	{
+		MSG_PRINT(("gcosSetUserPrio2Tc returned fail.\n"));
+		return status;
+	}
+
+	/*	Priority 1 is using QuarterDeck Queue 0. */
+	if((status = gcosSetUserPrio2Tc(dev,1,0)) != GT_OK)
+	{
+		MSG_PRINT(("gcosSetUserPrio2Tc returned fail.\n"));
+		return status;
+	}
+
+	/*	Priority 2 is using QuarterDeck Queue 0. */
+	if((status = gcosSetUserPrio2Tc(dev,2,0)) != GT_OK)
+	{
+		MSG_PRINT(("gcosSetUserPrio2Tc returned fail.\n"));
+		return status;
+	}
+
+	/*	Priority 3 is using QuarterDeck Queue 0. */
+	if((status = gcosSetUserPrio2Tc(dev,3,0)) != GT_OK)
+	{
+		MSG_PRINT(("gcosSetUserPrio2Tc returned fail.\n"));
+		return status;
+	}
+
+	/*	Priority 4 is using QuarterDeck Queue 1. */
+	if((status = gcosSetUserPrio2Tc(dev,4,1)) != GT_OK)
+	{
+		MSG_PRINT(("gcosSetUserPrio2Tc returned fail.\n"));
+		return status;
+	}
+
+	/*	Priority 5 is using QuarterDeck Queue 3. */
+	if((status = gcosSetUserPrio2Tc(dev,5,3)) != GT_OK)
+	{
+		MSG_PRINT(("gcosSetUserPrio2Tc returned fail.\n"));
+		return status;
+	}
+
+	/*	Priority 6 is using QuarterDeck Queue 2. */
+	if((status = gcosSetUserPrio2Tc(dev,6,2)) != GT_OK)
+	{
+		MSG_PRINT(("gcosSetUserPrio2Tc returned fail.\n"));
+		return status;
+	}
+
+	/*	Priority 7 is using QuarterDeck Queue 2. */
+	if((status = gcosSetUserPrio2Tc(dev,7,2)) != GT_OK)
+	{
+		MSG_PRINT(("gcosSetUserPrio2Tc returned fail.\n"));
+		return status;
+	}
+
+
+	/*
+	 *	IPv4/IPv6 (Priority 0 ~ 63, 6 bits)
+	 *	Priority 0~7 is using QuaterDeck Queue 0.
+	 *	Priority 8~31 is using QuaterDeck Queue 1.
+	 *	Priority 32~55 is using QuaterDeck Queue 2.
+	 *	Priority 56~63 is using QuaterDeck Queue 3.
+	*/
+
+	/*	Priority 0~7 is using QuaterDeck Queue 0. */
+	for(priority=0; priority<8; priority++)
+	{
+		if((status = gcosSetDscp2Tc(dev,priority,0)) != GT_OK)
+		{
+			MSG_PRINT(("gcosSetDscp2Tc returned fail.\n"));
+			return status;
+		}
+	}
+
+	/*	Priority 8~31 is using QuaterDeck Queue 1. */
+	for(priority=8; priority<32; priority++)
+	{
+		if((status = gcosSetDscp2Tc(dev,priority,1)) != GT_OK)
+		{
+			MSG_PRINT(("gcosSetDscp2Tc returned fail.\n"));
+			return status;
+		}
+	}
+
+	/*	Priority 32~55 is using QuaterDeck Queue 2. */
+	for(priority=32; priority<56; priority++)
+	{
+		if((status = gcosSetDscp2Tc(dev,priority,2)) != GT_OK)
+		{
+			MSG_PRINT(("gcosSetDscp2Tc returned fail.\n"));
+			return status;
+		}
+	}
+
+	/*	Priority 56~63 is using QuaterDeck Queue 3. */
+	for(priority=56; priority<64; priority++)
+	{
+		if((status = gcosSetDscp2Tc(dev,priority,3)) != GT_OK)
+		{
+			MSG_PRINT(("gcosSetDscp2Tc returned fail.\n"));
+			return status;
+		}
+	}
+
+	/*
+	 * Each port's default priority is set to 1.
+	*/
+	for(port=0; port<7; port++)
+	{
+		if((status = gcosSetPortDefaultTc(dev,port,1)) != GT_OK)
+		{
+			MSG_PRINT(("gcosSetDscp2Tc returned fail.\n"));
+			return status;
+		}
+	}
+
+	return GT_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/QoSSetup/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/QoSSetup/readme.txt
new file mode 100755
index 0000000..43b6216
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/QoSSetup/readme.txt
@@ -0,0 +1,41 @@
+========================================================================

+		Priority Queue Setup for QoS

+========================================================================

+

+QuarterDeck Device has 4 Priority Queues to support QoS. The priority of

+a frame is determined by (in priority order):

+	1) The CPU's Trailer if enabled on the port.

+	2) The DA address in the frame if the frame's DA address is in the address

+		database with a priority defined.

+	3) The IEEE 802.3ac Tag containing IEEE 802.1p priority information

+		if enabled on the port.

+	4) The IPv4 Type of Service (TOS)/DiffServ field or IPv6 Traffic Class 

+		field if enabled on the port.

+	5) The Port's default priority defined in DefPri.

+

+This sample program will deal with the above 3) ~ 5) cases.

+

+qos.c

+	sampleQoS will enable using both IEEE 802.3ac Tag and IPv4/IPv6 Traffic 

+	Class field and IEEE 802.3ac has a higher priority than IPv4/IPv6. 

+	The following is the QoS mapping programmed by sampleQos:

+	1) IEEE 802.3ac Tag (Priority 0 ~ 7, 3 bits)

+		Priority 1~3 is using QuarterDeck Queue 0.

+		Priority 0,4 is using QuarterDeck Queue 1.

+		Priority 6,7 is using QuarterDeck Queue 2.

+		Priority 5 is using QuarterDeck Queue 3.

+	2) IPv4/IPv6 (Priority 0 ~ 63, 6 bits)

+		Priority 0~7 is using QuaterDeck Queue 0.

+		Priority 8~31 is using QuaterDeck Queue 1.

+		Priority 32~55 is using QuaterDeck Queue 2.

+		Priority 56~63 is using QuaterDeck Queue 3.

+	3) Each port's default priority is set to 1.

+

+			

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/README b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/README
new file mode 100755
index 0000000..a30deea
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/README
@@ -0,0 +1,2 @@
+This directory includes sample code that demonstrats how to use the API of 

+the DSDT Suite. There is a readme.txt file in each of the subdirectories.

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/RMON/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/RMON/readme.txt
new file mode 100755
index 0000000..8241a5f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/RMON/readme.txt
@@ -0,0 +1,32 @@
+========================================================================

+		RMON Counters

+========================================================================

+

+This sample shows how to read/clear RMON counter in the device.

+Please notes that there are three groups of RMON counters in Marvell SOHO Switchs.

+Each group has different set of counters. Therefore it is necessary to find out

+which group the switch device belongs to.

+

+Group for GT_STATS_COUNTERS : 88E6021, 88E6063, and 88E6083

+Group for GT_STATS_COUNTERS2 : 88E6183

+Group for GT_STATS_COUNTERS3 : 88E6093, 88E6095, 88E6185, and 88E6065

+

+rmon.c

+	sampleClearRMONCounter

+		shows how to reset RMON counter for the given port

+

+	sampleGetRMONCounter

+		shows how to read RMON counter for each port

+        this routine is for the devices that use GT_STATS_COUNTERS.

+

+	sampleGetRMONCounter2

+		shows how to read RMON counter for each port

+        this routine is for the devices that use GT_STATS_COUNTERS2.

+

+	sampleGetRMONCounter3

+		shows how to read RMON counter for each port

+        this routine is for the devices that use GT_STATS_COUNTERS3.

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/RMON/rmon.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/RMON/rmon.c
new file mode 100755
index 0000000..394213e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/RMON/rmon.c
@@ -0,0 +1,238 @@
+#include <Copyright.h>
+/********************************************************************************
+* rmon.c
+*
+* DESCRIPTION:
+*		This sample shows how to read/clear RMON counter in the device
+*
+* DEPENDENCIES:   NONE.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include "msSample.h"
+
+
+/*
+ * This sample is for every device that support RMON counter.
+*/
+GT_STATUS sampleClearRMONCounter(GT_QD_DEV *dev,GT_LPORT port)
+{
+	GT_STATUS status;
+
+	if((status = gstatsFlushPort(dev,port)) != GT_OK)
+	{
+		MSG_PRINT(("gstatsFlushPort returned fail (%#x).\n",status));
+		return status;
+	}
+
+	return GT_OK;
+}
+
+/*
+ * This sample is for 88E6021, 88E6063, and 88E6083.
+*/
+void sampleDisplayCounter(GT_STATS_COUNTER_SET *statsCounter)
+{
+	MSG_PRINT(("InUnicasts    %08i    ", statsCounter->InUnicasts));
+	MSG_PRINT(("InBroadcasts  %08i   \n", statsCounter->InBroadcasts));
+	MSG_PRINT(("InPause       %08i    ", statsCounter->InPause));
+	MSG_PRINT(("InMulticasts  %08i   \n", statsCounter->InMulticasts));
+	MSG_PRINT(("InFCSErr      %08i    ", statsCounter->InFCSErr));
+	MSG_PRINT(("AlignErr      %08i   \n", statsCounter->AlignErr));
+	MSG_PRINT(("InGoodOctets  %08i    ", statsCounter->InGoodOctets));
+	MSG_PRINT(("InBadOctets   %08i   \n", statsCounter->InBadOctets));
+	MSG_PRINT(("Undersize     %08i    ", statsCounter->Undersize));
+	MSG_PRINT(("Fragments     %08i   \n", statsCounter->Fragments));
+	MSG_PRINT(("In64Octets    %08i    ", statsCounter->In64Octets));
+	MSG_PRINT(("In127Octets   %08i   \n", statsCounter->In127Octets));
+	MSG_PRINT(("In255Octets   %08i    ", statsCounter->In255Octets));
+	MSG_PRINT(("In511Octets   %08i   \n", statsCounter->In511Octets));
+	MSG_PRINT(("In1023Octets  %08i    ", statsCounter->In1023Octets));
+	MSG_PRINT(("InMaxOctets   %08i   \n", statsCounter->InMaxOctets));
+	MSG_PRINT(("Jabber        %08i    ", statsCounter->Jabber));
+	MSG_PRINT(("Oversize      %08i   \n", statsCounter->Oversize));
+	MSG_PRINT(("InDiscards    %08i    ", statsCounter->InDiscards));
+	MSG_PRINT(("Filtered      %08i   \n", statsCounter->Filtered));
+	MSG_PRINT(("OutUnicasts   %08i    ", statsCounter->OutUnicasts));
+	MSG_PRINT(("OutBroadcasts %08i   \n", statsCounter->OutBroadcasts));
+	MSG_PRINT(("OutPause      %08i    ", statsCounter->OutPause));
+	MSG_PRINT(("OutMulticasts %08i   \n", statsCounter->OutMulticasts));
+	MSG_PRINT(("OutFCSErr     %08i    ", statsCounter->OutFCSErr));
+	MSG_PRINT(("OutGoodOctets %08i   \n", statsCounter->OutGoodOctets));
+	MSG_PRINT(("Out64Octets   %08i    ", statsCounter->Out64Octets));
+	MSG_PRINT(("Out127Octets  %08i   \n", statsCounter->Out127Octets));
+	MSG_PRINT(("Out255Octets  %08i    ", statsCounter->Out255Octets));
+	MSG_PRINT(("Out511Octets  %08i   \n", statsCounter->Out511Octets));
+	MSG_PRINT(("Out1023Octets %08i    ", statsCounter->Out1023Octets));
+	MSG_PRINT(("OutMaxOctets  %08i   \n", statsCounter->OutMaxOctets));
+	MSG_PRINT(("Collisions    %08i    ", statsCounter->Collisions));
+	MSG_PRINT(("Late          %08i   \n", statsCounter->Late));
+	MSG_PRINT(("Excessive     %08i    ", statsCounter->Excessive));
+	MSG_PRINT(("Multiple      %08i   \n", statsCounter->Multiple));
+	MSG_PRINT(("Single        %08i    ", statsCounter->Single));
+	MSG_PRINT(("Deferred      %08i   \n", statsCounter->Deferred));
+	MSG_PRINT(("OutDiscards   %08i   \n", statsCounter->OutDiscards));
+}
+
+/*
+ * This sample is for 88E6021, 88E6063, and 88E6083.
+*/
+GT_STATUS sampleGetRMONCounter(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_LPORT port;
+	GT_STATS_COUNTER_SET	statsCounterSet;
+
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		MSG_PRINT(("Port %i :\n",port));
+
+		if((status = gstatsGetPortAllCounters(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters returned fail (%#x).\n",status));
+			return status;
+		}
+
+		sampleDisplayCounter(&statsCounterSet);
+
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ * This sample is for 88E6183
+*/
+void sampleDisplayCounter2(GT_STATS_COUNTER_SET2 *statsCounter)
+{
+	MSG_PRINT(("InGoodOctetsHi  %08i    ", statsCounter->InGoodOctetsHi));
+	MSG_PRINT(("InGoodOctetsLo  %08i   \n", statsCounter->InGoodOctetsLo));
+	MSG_PRINT(("InBadOctets     %08i    ", statsCounter->InBadOctets));
+	MSG_PRINT(("OutDiscards     %08i   \n", statsCounter->OutDiscards));
+	MSG_PRINT(("InGoodFrames    %08i    ", statsCounter->InGoodFrames));
+	MSG_PRINT(("InBadFrames     %08i   \n", statsCounter->InBadFrames));
+	MSG_PRINT(("InBroadcasts    %08i    ", statsCounter->InBroadcasts));
+	MSG_PRINT(("InMulticasts    %08i   \n", statsCounter->InMulticasts));
+	MSG_PRINT(("64Octets        %08i    ", statsCounter->Octets64));
+	MSG_PRINT(("127Octets       %08i   \n", statsCounter->Octets127));
+	MSG_PRINT(("255Octets       %08i    ", statsCounter->Octets255));
+	MSG_PRINT(("511Octets       %08i   \n", statsCounter->Octets511));
+	MSG_PRINT(("1023Octets      %08i    ", statsCounter->Octets1023));
+	MSG_PRINT(("MaxOctets       %08i   \n", statsCounter->OctetsMax));
+	MSG_PRINT(("OutOctetsHi     %08i    ", statsCounter->OutOctetsHi));
+	MSG_PRINT(("OutOctetsLo     %08i   \n", statsCounter->OutOctetsLo));
+	MSG_PRINT(("OutFrames       %08i    ", statsCounter->OutFrames));
+	MSG_PRINT(("Excessive       %08i   \n", statsCounter->Excessive));
+	MSG_PRINT(("OutMulticasts   %08i    ", statsCounter->OutMulticasts));
+	MSG_PRINT(("OutBroadcasts   %08i    ", statsCounter->OutBroadcasts));
+	MSG_PRINT(("InBadMACCtrl    %08i    ", statsCounter->InBadMACCtrl));
+	MSG_PRINT(("OutPause        %08i   \n", statsCounter->OutPause));
+	MSG_PRINT(("InPause         %08i    ", statsCounter->InPause));
+	MSG_PRINT(("InDiscards      %08i   \n", statsCounter->InDiscards));
+	MSG_PRINT(("Undersize       %08i    ", statsCounter->Undersize));
+	MSG_PRINT(("Fragments       %08i   \n", statsCounter->Fragments));
+	MSG_PRINT(("Oversize        %08i    ", statsCounter->Oversize));
+	MSG_PRINT(("Jabber          %08i   \n", statsCounter->Jabber));
+	MSG_PRINT(("MACRcvErr       %08i    ", statsCounter->MACRcvErr));
+	MSG_PRINT(("InFCSErr        %08i   \n", statsCounter->InFCSErr));
+	MSG_PRINT(("Collisions      %08i    ", statsCounter->Collisions));
+	MSG_PRINT(("Late            %08i   \n", statsCounter->Late));
+}
+
+/*
+ * This sample is for 88E6183
+*/
+GT_STATUS sampleGetRMONCounter2(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_LPORT port;
+	GT_STATS_COUNTER_SET2 statsCounterSet;
+
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		MSG_PRINT(("Port %i :\n",port));
+
+		if((status = gstatsGetPortAllCounters2(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters2 returned fail (%#x).\n",status));
+			return status;
+		}
+
+		sampleDisplayCounter2(&statsCounterSet);
+
+	}
+
+	return GT_OK;
+}
+
+
+
+/*
+ * This sample is for 88E6093, 88E6095, 88E6185, and 88E6065
+*/
+void sampleDisplayCounter3(GT_STATS_COUNTER_SET3 *statsCounter)
+{
+	MSG_PRINT(("InGoodOctetsLo  %08i    ", statsCounter->InGoodOctetsLo));
+	MSG_PRINT(("InGoodOctetsHi  %08i   \n", statsCounter->InGoodOctetsHi));
+	MSG_PRINT(("InBadOctets     %08i    ", statsCounter->InBadOctets));
+	MSG_PRINT(("OutFCSErr       %08i   \n", statsCounter->OutFCSErr));
+	MSG_PRINT(("InUnicasts      %08i    ", statsCounter->InUnicasts));
+	MSG_PRINT(("Deferred        %08i   \n", statsCounter->Deferred));
+	MSG_PRINT(("InBroadcasts    %08i    ", statsCounter->InBroadcasts));
+	MSG_PRINT(("InMulticasts    %08i   \n", statsCounter->InMulticasts));
+	MSG_PRINT(("64Octets        %08i    ", statsCounter->Octets64));
+	MSG_PRINT(("127Octets       %08i   \n", statsCounter->Octets127));
+	MSG_PRINT(("255Octets       %08i    ", statsCounter->Octets255));
+	MSG_PRINT(("511Octets       %08i   \n", statsCounter->Octets511));
+	MSG_PRINT(("1023Octets      %08i    ", statsCounter->Octets1023));
+	MSG_PRINT(("MaxOctets       %08i   \n", statsCounter->OctetsMax));
+	MSG_PRINT(("OutOctetsLo     %08i    ", statsCounter->OutOctetsLo));
+	MSG_PRINT(("OutOctetsHi     %08i   \n", statsCounter->OutOctetsHi));
+	MSG_PRINT(("OutUnicasts     %08i    ", statsCounter->OutUnicasts));
+	MSG_PRINT(("Excessive       %08i   \n", statsCounter->Excessive));
+	MSG_PRINT(("OutMulticasts   %08i    ", statsCounter->OutMulticasts));
+	MSG_PRINT(("OutBroadcasts   %08i   \n", statsCounter->OutBroadcasts));
+	MSG_PRINT(("Single          %08i    ", statsCounter->Single));
+	MSG_PRINT(("OutPause        %08i   \n", statsCounter->OutPause));
+	MSG_PRINT(("InPause         %08i    ", statsCounter->InPause));
+	MSG_PRINT(("Multiple        %08i   \n", statsCounter->Multiple));
+	MSG_PRINT(("Undersize       %08i    ", statsCounter->Undersize));
+	MSG_PRINT(("Fragments       %08i   \n", statsCounter->Fragments));
+	MSG_PRINT(("Oversize        %08i    ", statsCounter->Oversize));
+	MSG_PRINT(("Jabber          %08i   \n", statsCounter->Jabber));
+	MSG_PRINT(("InMACRcvErr     %08i    ", statsCounter->InMACRcvErr));
+	MSG_PRINT(("InFCSErr        %08i   \n", statsCounter->InFCSErr));
+	MSG_PRINT(("Collisions      %08i    ", statsCounter->Collisions));
+	MSG_PRINT(("Late            %08i   \n", statsCounter->Late));
+}
+
+
+/*
+ * This sample is for 88E6093, 88E6095, 88E6185, and 88E6065
+*/
+GT_STATUS sampleGetRMONCounter3(GT_QD_DEV *dev)
+{
+	GT_STATUS status;
+	GT_LPORT port;
+	GT_STATS_COUNTER_SET3 statsCounterSet;
+
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		MSG_PRINT(("Port %i :\n",port));
+
+		if((status = gstatsGetPortAllCounters3(dev,port,&statsCounterSet)) != GT_OK)
+		{
+			MSG_PRINT(("gstatsGetPortAllCounters3 returned fail (%#x).\n",status));
+			return status;
+		}
+
+		sampleDisplayCounter3(&statsCounterSet);
+
+	}
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Trailer/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Trailer/readme.txt
new file mode 100755
index 0000000..3891046
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Trailer/readme.txt
@@ -0,0 +1,19 @@
+========================================================================

+		CPU Trailer Mode Enable or Disable

+========================================================================

+

+This sample shows how to enable/disable CPU port's ingress trailer mode

+and engress trailer mode.

+For more information about trailer mode, please refer to 88E6052 Spec.

+section 3.5.5 and section 3.7.3

+

+trailer.c

+	sampleCPUTrailerEnable can be used to enable or disable CPU port's

+	trailer mode

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Trailer/trailer.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Trailer/trailer.c
new file mode 100755
index 0000000..9cbd093
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/Trailer/trailer.c
@@ -0,0 +1,50 @@
+#include <Copyright.h>
+/********************************************************************************
+* trailer.c
+*
+* DESCRIPTION:
+*		This sample shows how to enable/disable CPU port's ingress and egress 
+*		Trailer mode.
+*
+* DEPENDENCIES:   NONE.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include "msSample.h"
+
+GT_STATUS sampleCPUTrailerEnable(GT_QD_DEV *dev, GT_BOOL en)
+{
+	GT_STATUS status;
+	GT_INGRESS_MODE	inMode;
+
+	if (en)	/* Enable Trailer Mode */
+	{
+		inMode = GT_TRAILER_INGRESS;
+	}
+	else
+	{
+		inMode = GT_UNMODIFY_INGRESS;
+	}
+
+	/*
+	 *	Enable CPU's Ingress Trailer 
+	*/
+	if((status = gprtSetIngressMode(dev,dev->cpuPortNum, inMode)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetIngressMode return Failed\n"));
+		return status;
+	}
+
+	/*
+	 *	Enable CPU's Egress Trailer 
+	*/
+	if((status = gprtSetTrailerMode(dev,dev->cpuPortNum, en)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetTrailerMode return Failed\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/VlanSetup/hgVlan.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/VlanSetup/hgVlan.c
new file mode 100755
index 0000000..f2dae25
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/VlanSetup/hgVlan.c
@@ -0,0 +1,135 @@
+#include <Copyright.h>
+/********************************************************************************
+* hgVlan.c
+*
+* DESCRIPTION:
+*       Setup the VLAN table of QuaterDeck so that it can be used as a Home 
+*		Gateway.
+*		
+*
+* DEPENDENCIES:   None.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+#include "msSample.h"
+
+static GT_STATUS sampleHomeGatewayVlan(GT_QD_DEV *dev, 
+		                       GT_LPORT numOfPorts, 
+				       GT_LPORT cpuPort);
+
+/*
+ *  Get the required parameter from QuarterDeck driver.
+ *	Notes: This routine should be called after QuarterDeck Driver has been initialized.
+ *		(Refer to Initialization Sample)
+*/
+
+GT_STATUS sampleVlanSetup(GT_QD_DEV *dev)
+{
+	sampleHomeGatewayVlan(dev,dev->numOfPorts, dev->cpuPortNum);
+
+	return GT_OK;
+}
+
+
+/*
+ *	WAN Port (Port 0) and CPU Port (Port 5) are in VLAN 1 and
+ *	all ports (including CPU Port) except WAN Port are in VLAN 2.
+ *	1) Set PVID for each port. (CPU port has PVID 2, which is the same as LAN)
+ *	2) Set Port Based VLAN Map for each port. (CPU port's VLAN Map is set for all LAN ports)
+ *  Notes: 
+ *		1) Trailer Mode
+ *			When Ethernet Device, which is directly connected to CPU port, sends out a packet
+ *			to WAN, DPV in Trailer Tag should have WAN port bit set (bit 0 in this case), and
+ *			to LAN, Trailer Tag should be set to 0. 
+ *			Restriction : Only one group of VLAN can have multiple ports.
+ *		2) Header Mode
+ *			When Ethernet Device, which is directly connected to CPU port, sends out a packet
+ *			to WAN, VlanTable in Header Tag should have WAN ports bits set (bit 0 in this case), and
+ *			to LAN, VlanTable in Header Tag should have LAN ports bits set (bit 1~4 and 6 in this case)
+*/
+static GT_STATUS sampleHomeGatewayVlan(GT_QD_DEV *dev,GT_LPORT numOfPorts, GT_LPORT cpuPort)
+{
+	GT_STATUS status;
+	GT_LPORT index,port,portToSet;
+	GT_LPORT portList[MAX_SWITCH_PORTS];
+
+	/* 
+	 *  set PVID for each port.
+	 *	the first port(port 0, WAN) has default VID 2 and all others has 1.
+	 */
+
+	if((status = gvlnSetPortVid(dev,0,2)) != GT_OK)
+	{
+		MSG_PRINT(("gprtSetPortVid returned fail.\n"));
+		return status;
+	}
+
+	for (port=1; port<numOfPorts; port++)
+	{
+		if((status = gvlnSetPortVid(dev,port,1)) != GT_OK)
+		{
+			MSG_PRINT(("gprtSetPortVid returned fail.\n"));
+			return status;
+		}
+	}
+
+	/* 
+	 *  set Port VLAN Mapping.
+	 *	port 0 (WAN) and cpu port are in a vlan 2.
+	 *	And all the rest ports (LAN) and cpu port are in a vlan 1.
+	 */
+
+	/* port 0 : set cpuPort only */
+	portList[0] = cpuPort;
+	if((status = gvlnSetPortVlanPorts(dev,0,portList,1)) != GT_OK)
+	{
+		MSG_PRINT(("gvlnSetPortVlanPorts returned fail.\n"));
+		return status;
+	}
+
+	/* set all ports except port 0 and itself */
+	for (portToSet=1; portToSet<numOfPorts; portToSet++)
+	{
+		/* port 0 and cpuPort will be taken cared seperately. */
+		if (portToSet == cpuPort)
+		{
+			continue;
+		}
+
+		index = 0;
+		for (port=1; port<numOfPorts; port++)
+		{
+			if (port == portToSet)
+			{
+				continue;
+			}
+			portList[index++] = port;
+		}
+
+		if((status = gvlnSetPortVlanPorts(dev,portToSet,portList,index)) != GT_OK)
+		{
+			MSG_PRINT(("gvlnSetPortVlanPorts returned fail.\n"));
+			return status;
+		}
+	}
+
+	/* cpuPort : set all port except cpuPort and WAN port */
+	index = 0;
+	for (port=1; port<numOfPorts; port++)
+	{
+		if (port == cpuPort)
+		{
+			continue;
+		}
+		portList[index++] = port;
+	}
+
+	if((status = gvlnSetPortVlanPorts(dev,cpuPort,portList,index)) != GT_OK)
+	{
+		MSG_PRINT(("gvlnSetPortVlanPorts returned fail.\n"));
+		return status;
+	}
+
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/VlanSetup/readme.txt b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/VlanSetup/readme.txt
new file mode 100755
index 0000000..fe806c9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/VlanSetup/readme.txt
@@ -0,0 +1,38 @@
+========================================================================

+		VLAN Setup for Home Gateway Solution

+========================================================================

+

+Vlan Setup Program will show how to setup the QuaterDeck's vlan 

+for Home Gateway.

+In the sample program, Port 0 (WAN port) and CPU Port (Port 5) are in 

+a VLAN 2, and Port 1 ~ Port 6 (including CPU Port) are in a VLAN 1.

+
+VLAN MAP setting for the given sample program is:
+Port 0 (WAN) = 0x20,
+Port 1 (LAN) = 0x7C,
+Port 2 (LAN) = 0x7A,
+Port 3 (LAN) = 0x76,
+Port 4 (LAN) = 0x6E,
+Port 5 (CPU) = 0x5E, and
+Port 6 (LAN) = 0x3E
+
+Notes: 
+	1) Trailer Mode is enabled:
+		When Ethernet Device, which is directly connected to CPU port, sends out a packet
+		to WAN, DPV in Trailer Tag should have WAN port bit set (bit 0 in this case), and
+		to LAN, Trailer Tag should be set to 0. 
+		Restriction : Only one group of VLANs can have multiple ports.
+	2) Header Mode is enabled:
+		When Ethernet Device, which is directly connected to CPU port, sends out a packet
+		to WAN, VlanTable in Header Tag should have WAN ports bits set (bit 0 in this case), and
+		to LAN, VlanTable in Header Tag should have LAN ports bits set (bit 1~4 and 6 in this case)
+
+hgVlan.c

+	sampleHGVlanSetup is the main function for the Home Gateway setup.

+

+

+

+

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/makefile b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/makefile
new file mode 100755
index 0000000..4062834
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/sample/makefile
@@ -0,0 +1,53 @@
+# makefile - build main object file

+#

+# modification history

+# --------------------

+# 04-15-02,mj	created

+#

+#######################################################################

+

+DEMONAME = sample

+WORK_TO_DO = $(DEMONAME).o

+

+exe : $(WORK_TO_DO)

+

+# Include common variable definitions

+include $(TOOL_DIR)\make.defs

+

+.PHONY : exe

+

+QDLIB = $(LIB_DIR)/$(PROJ_NAME).o

+

+OBJDIRS	= $(subst /,\,$(dir $(QDLIB)))

+

+CSOURCES = FlowControl/flowCtrl.c Initialization/osSem.c Initialization/ev96122mii.c \

+           Initialization/qdSim.c Initialization/msApiInit.c  \

+	   MACAddress/macAddr.c QoSSetup/qos.c VlanSetup/hgVlan.c Interrupt/qdInt.c \

+		   Trailer/trailer.c RMON/rmon.c 802.1Q/802_1q.c Header/header.c \

+		   CableTest/cableTest.c CableTest/advCableTest.c PortMonitor/portMonitor.c MultiDevice/msApiInit.c \
+			CrossChipTrunk/crossChipTrunk.c MinimizeCPUTraffic\minimizeCPUTraffic.c	\

+			PktGen/phyPktGenSample.c PIRL/pirl.c PIRL/pirl2.c ptp/ptp.c

+

+EXTRA_INCLUDE = -I./Include -I./Initialization

+COBJECTS  	= $(CSOURCES:.c=.o)

+AOBJECTS  	= $(ASOURCES:.s=.o)

+ifeq ($(OBJECTS),)

+OBJECTS  	= $(COBJECTS) $(AOBJECTS)

+endif

+

+OBJECTS_MS= $(subst /,\,$(OBJECTS))

+

+$(DEMONAME).o : $(OBJECTS) $(QDLIB)

+	$(LD) $(LDFLAGS) -Map $(DEMONAME).map -o $(DEMONAME).o $(OBJECTS) $(QDLIB)

+

+$(OBJECTS) : %.o : %.c

+.c.o :

+	$(CC) $(CFLAGS) $(EXTRA_DEFINE) $(EXTRA_INCLUDE) $(ADDED_CFLAGS) -c $< -o $@

+

+.PHONY : clean

+clean :

+	@for %x in ($(OBJECTS_MS)) do \

+		$(RM) %x

+	$(RM) $(DEMONAME).*

+

+#end of file

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtDrvConfig.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtDrvConfig.c
new file mode 100755
index 0000000..fa44b5a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtDrvConfig.c
@@ -0,0 +1,1000 @@
+#include <Copyright.h>
+/********************************************************************************
+* gtDrvConfig.h
+*
+* DESCRIPTION:
+*       Includes driver level configuration and initialization function.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1.2 $
+*
+*******************************************************************************/
+
+#include <gtDrvSwRegs.h>
+#include <gtDrvConfig.h>
+#include <gtMiiSmiIf.h>
+#include <gtHwCntl.h>
+#include <gtVct.h>
+#include <msApiDefs.h>
+#include "boardEnv/mvBoardEnvLib.h"
+
+#define QSGMII_ENABLE_UNI_3 	1
+
+/*******************************************************************************
+* lport2port
+*
+* DESCRIPTION:
+*       This function converts logical port number to physical port number
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		port    - logical port number
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       physical port number
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_U8 lport2port
+(
+    IN GT_U16    portVec,
+	IN GT_LPORT	 port
+)
+{
+    GT_U8	hwPort, tmpPort;
+
+	tmpPort = hwPort = 0;
+
+	while (portVec)
+	{
+		if(portVec & 0x1)
+		{
+			if((GT_LPORT)tmpPort == port)
+				break;
+			tmpPort++;
+		}
+		hwPort++;
+		portVec >>= 1;
+	}
+
+	if (!portVec)
+		hwPort = GT_INVALID_PORT;
+
+	return hwPort;
+}
+
+/*******************************************************************************
+* port2lport
+*
+* DESCRIPTION:
+*       This function converts physical port number to logical port number
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		port    - logical port number
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       physical port number
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_LPORT port2lport
+(
+    IN GT_U16    portVec,
+	IN GT_U8	 hwPort
+)
+{
+    GT_U8		tmpPort,port;
+
+	port = 0;
+	
+	if (hwPort == GT_INVALID_PORT)
+		return (GT_LPORT)hwPort;
+
+	if (!GT_IS_PORT_SET(portVec, hwPort))
+		return (GT_LPORT)GT_INVALID_PORT;
+
+	for (tmpPort = 0; tmpPort <= hwPort; tmpPort++)
+	{
+		if(portVec & 0x1)
+		{
+			port++;
+		}
+		portVec >>= 1;
+	}
+
+	return (GT_LPORT)port-1;
+}
+
+/*******************************************************************************
+* lportvec2portvec
+*
+* DESCRIPTION:
+*       This function converts logical port vector to physical port vector
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		lVec 	- logical port vector
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       physical port vector
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_U32 lportvec2portvec
+(
+    IN GT_U16    portVec,
+	IN GT_U32	 lVec
+)
+{
+    GT_U32	pVec, vec;
+
+	pVec = 0;
+	vec = 1;
+
+	while (portVec)
+	{
+		if(portVec & 0x1)
+		{
+			if(lVec & 0x1)
+			{
+				pVec |= vec;
+			}
+			lVec >>= 1;
+		}
+
+		vec <<= 1;
+		portVec >>= 1;
+	}
+
+	if(lVec)
+		return GT_INVALID_PORT_VEC;
+
+	return pVec;
+}
+
+/*******************************************************************************
+* portvec2lportvec
+*
+* DESCRIPTION:
+*       This function converts physical port vector to logical port vector
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		pVec 	- physical port vector
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       logical port vector
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_U32 portvec2lportvec
+(
+    IN GT_U16    portVec,
+	IN GT_U32	 pVec
+)
+{
+    GT_U32	lVec, vec;
+
+	lVec = 0;
+	vec = 1;
+
+	while (portVec)
+	{
+		if(portVec & 0x1)
+		{
+			if(pVec & 0x1)
+			{
+				lVec |= vec;
+			}
+			vec <<= 1;
+		}
+
+		pVec >>= 1;
+		portVec >>= 1;
+	}
+
+	return lVec;
+}
+
+/*******************************************************************************
+* lport2phy
+*
+* DESCRIPTION:
+*       This function converts logical port number to physical phy number.
+*
+* INPUTS:
+*		portVec - physical port list in vector
+*		port    - logical port number
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       physical port number
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_U8 lport2phy
+(
+    IN GT_QD_DEV    *dev,
+	IN GT_LPORT	 port
+)
+{
+    GT_U8	hwPort;
+
+	/* check if it's for SERDES */
+	if(dev->validSerdesVec & (1<<port))
+	{
+		hwPort = (GT_U8)port;			
+	}
+	else
+	{
+		hwPort = GT_LPORT_2_PORT(port);
+	}
+
+	return hwPort;
+}
+
+
+/*******************************************************************************
+* driverConfig
+*
+* DESCRIPTION:
+*       This function initializes the driver level of the quarterDeck software.
+*
+* INPUTS:
+*		None.
+* OUTPUTS:
+*		None.
+* RETURNS:
+*       GT_OK               - on success, or
+*       GT_OUT_OF_CPU_MEM   - if failed to allocate CPU memory,
+*       GT_FAIL             - otherwise.
+*
+* COMMENTS:
+*       1.  This function should perform the following:
+*           -   Initialize the global switch configuration structure.
+*           -   Initialize Mii Interface
+*
+*******************************************************************************/
+GT_STATUS driverConfig
+(
+    IN GT_QD_DEV    *dev
+)
+{
+    GT_U16          deviceId;
+#ifdef CONFIG_ARCH_FEROCEON_KW
+    GT_U16          tmp, phy;
+#endif    
+    GT_BOOL         highSmiDevAddr;
+
+	if(dev->accessMode == SMI_AUTO_SCAN_MODE)
+	{	
+	    /* Initialize the MII / SMI interface, search for the device */
+    	if((deviceId = miiSmiIfInit(dev,&highSmiDevAddr)) == 0)
+	    {
+    	    return GT_FAIL;
+	    }
+
+		dev->baseRegAddr = (highSmiDevAddr)?0x10:0;
+	}
+	else
+	{
+    	if((deviceId = miiSmiManualIfInit(dev,(GT_U32)dev->baseRegAddr)) == 0)
+	    {
+    	    return GT_FAIL;
+	    }
+	}
+	
+    /* Init the device's config struct.             */
+    dev->deviceId       = deviceId >> 4;
+    dev->revision       = (GT_U8)deviceId & 0xF; 
+
+#ifdef CONFIG_ARCH_FEROCEON_KW
+    if(mvBoardIdGet() == RD_88F6281A_ID) {
+       /* Enable RGMII delay on Tx and Rx for CPU port */
+       miiSmiIfWriteRegister(dev, 0x14,0x1a, 0x81e7);
+       miiSmiIfReadRegister(dev, 0x15,0x1a,&tmp);
+       miiSmiIfWriteRegister(dev, 0x15,0x1a,0x18);
+       miiSmiIfWriteRegister(dev, 0x14,0x1a,0xc1e7);
+
+       /* swap MDI signals for PHYs 0,1,2,3,4 on RD_88F6281A_ID */
+        for(phy = 0; phy < 5; phy++) {
+               miiSmiIfWriteRegister(dev, 0x1c,0x19,0xf);
+               miiSmiIfWriteRegister(dev, 0x1c,0x18,(0x9414 + (phy*0x20)));
+               miiSmiIfReadRegister(dev, 0x1c, 0x19,&tmp); /* used for delay */
+               /*  testing - read phy register #20
+               miiSmiIfWriteRegister(dev, 0x1c,0x18,(0x9814+ (phy*0x20)));
+               miiSmiIfReadRegister(dev, 0x1c, 0x19,&tmp);
+               DBG_INFO(("phy-%d reg20 = 0x%x\n",phy,tmp));
+               */
+       }
+    }
+#endif
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* driverEnable
+*
+* DESCRIPTION:
+*       This function enables the switch for full operation, after the driver
+*       Config function was called.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverEnable
+(
+	IN GT_QD_DEV    *dev
+)
+{
+	GT_UNUSED_PARAM(dev);
+    return GT_OK;
+}
+
+
+GT_STATUS driverGetSerdesPort(GT_QD_DEV *dev, GT_U8* hwPort)
+{
+	switch(dev->deviceId)
+	{
+		case GT_88E6122:
+			if ((*hwPort<3) || (*hwPort>6))
+			{
+				*hwPort = GT_INVALID_PORT;
+			}
+			else
+			{
+				*hwPort += 9;
+			}
+			break;
+		case GT_88E6131:
+		case GT_88E6108:
+			if ((*hwPort<4) || (*hwPort>7))
+			{
+				*hwPort = GT_INVALID_PORT;
+			}
+			else
+			{
+				*hwPort += 8;
+			}
+			break;
+		case GT_88E6123:
+		case GT_88E6140:
+		case GT_88E6161:
+		case GT_88E6165:
+			if ((*hwPort<4) || (*hwPort>5))
+			{
+				*hwPort = GT_INVALID_PORT;
+			}
+			else
+			{
+				*hwPort += 8;
+			}
+			break;
+		default:
+			*hwPort = GT_INVALID_PORT;
+			break;
+	}
+	return GT_OK;
+}
+
+/*******************************************************************************
+* driverFindPhyID
+*
+* DESCRIPTION:
+*       This function get Phy ID from Phy register 2 and 3.
+*
+* INPUTS:
+*       hwPort	- port number where the Phy is connected
+*
+* OUTPUTS:
+*       phyId	- Phy ID
+*
+* RETURNS:
+*       GT_OK 	- if found Marvell Phy,
+*       GT_FAIL - othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+static GT_STATUS driverFindPhyID
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort,
+	OUT	GT_U32		 *phyID
+)
+{
+	GT_U16 ouiMsb, ouiLsb;
+	GT_STATUS status;
+	
+	if((status= hwReadPhyReg(dev,hwPort,2,&ouiMsb)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to read Phy Register.\n"));
+		return status;
+	}
+
+	if((status= hwReadPhyReg(dev,hwPort,3,&ouiLsb)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to read Phy Register.\n"));
+		return status;
+	}
+
+	if(ouiMsb != MARVELL_OUI_MSb)
+		return GT_FAIL;
+
+	*phyID = (GT_U32)ouiLsb;
+					
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* driverIsPhyAttached
+*
+* DESCRIPTION:
+*       This function verifies Marvell Phy.
+*
+* INPUTS:
+*       hwPort	- port number where the Phy is connected
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       1 - if Marvell Phy exists
+*		0 - otherwise
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U32 driverIsPhyAttached
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort
+)
+{
+	GT_U32		 phyId;
+
+	if(hwPort > dev->maxPhyNum)
+		return 0;
+
+	if(driverFindPhyID(dev,hwPort,&phyId) != GT_OK)
+	{
+	    DBG_INFO(("cannot find Marvell Phy.\n"));
+		return 0;
+	}
+
+	return 1;
+}
+
+/*******************************************************************************
+* driverGetPhyID
+*
+* DESCRIPTION:
+*       This function reads and returns Phy ID (register 3) of Marvell Phy.
+*
+* INPUTS:
+*       hwPort	- port number where the Phy is connected
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       phyId - if Marvell Phy exists
+*		GT_INVALID_PORT	  - otherwise
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U32 driverGetPhyID
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort
+)
+{
+	GT_U32		 phyId;
+
+	if(hwPort > dev->maxPhyNum)
+		return GT_INVALID_PHY;
+
+	if(driverFindPhyID(dev,hwPort,&phyId) != GT_OK)
+	{
+	    DBG_INFO(("cannot find Marvell Phy.\n"));
+		return GT_INVALID_PHY;
+	}
+
+	return phyId;
+}
+
+/*******************************************************************************
+* driverPagedAccessStart
+*
+* DESCRIPTION:
+*       This function stores page register and Auto Reg Selection mode if needed.
+*
+* INPUTS:
+*       hwPort	 - port number where the Phy is connected
+*		pageType - type of the page registers
+*
+* OUTPUTS:
+*       autoOn	- GT_TRUE if Auto Reg Selection enabled, GT_FALSE otherwise.
+*		pageReg - Page Register Data
+*
+* RETURNS:
+*       GT_OK 	- if success
+*       GT_FAIL - othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverPagedAccessStart
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort,
+	IN	GT_U8		 pageType,
+	OUT	GT_BOOL		 *autoOn,
+	OUT	GT_U16		 *pageReg
+)
+{
+	GT_U16 data;
+	GT_STATUS status;
+
+	switch(pageType)
+	{
+		case GT_PHY_PAGE_WRITE_BACK:
+			break;
+		case GT_PHY_PAGE_DIS_AUTO1:	/* 88E1111 Type */
+			if((status= hwGetPhyRegField(dev,hwPort,27,9,1,&data)) != GT_OK)
+			{
+	    		DBG_INFO(("Not able to read Phy Register.\n"));
+				return status;
+			}
+
+			data ^= 0x1;	/* toggle bit 0 */
+		    BIT_2_BOOL(data, *autoOn);
+
+			if (*autoOn) /* Auto On */
+			{
+				if((status= hwSetPhyRegField(dev,hwPort,27,9,1,data)) != GT_OK)
+				{
+	    			DBG_INFO(("Not able to write Phy Register.\n"));
+					return status;
+				}
+			}
+
+			break;	
+		case GT_PHY_PAGE_DIS_AUTO2:	/* 88E1112 Type */
+			if((status= hwGetPhyRegField(dev,hwPort,22,15,1,&data)) != GT_OK)
+			{
+	    		DBG_INFO(("Not able to read Phy Register.\n"));
+				return status;
+			}
+
+		    BIT_2_BOOL(data, *autoOn);
+			data ^= 0x1;	/* toggle bit 0 */
+
+			if (*autoOn) /* Auto On */
+			{
+				if((status= hwSetPhyRegField(dev,hwPort,22,15,1,data)) != GT_OK)
+				{
+	    			DBG_INFO(("Not able to write Phy Register.\n"));
+					return status;
+				}
+			}
+
+			break;	
+
+		case GT_PHY_NO_PAGE:
+		default:
+			/* Nothing to do */
+			return GT_OK;
+	}
+
+
+	if((status= hwGetPhyRegField(dev,hwPort,22,0,8,pageReg)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to read Phy Register.\n"));
+		return status;
+	}
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* driverPagedAccessStop
+*
+* DESCRIPTION:
+*       This function restores page register and Auto Reg Selection mode if needed.
+*
+* INPUTS:
+*       hwPort	 - port number where the Phy is connected
+*		pageType - type of the page registers
+*       autoOn	 - GT_TRUE if Auto Reg Selection enabled, GT_FALSE otherwise.
+*		pageReg  - Page Register Data
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK 	- if success
+*       GT_FAIL - othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverPagedAccessStop
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort,
+	IN	GT_U8		 pageType,
+	IN	GT_BOOL		 autoOn,
+	IN	GT_U16		 pageReg
+)
+{
+	GT_U16 data;
+	GT_STATUS status;
+
+	switch(pageType)
+	{
+		case GT_PHY_PAGE_WRITE_BACK:
+			break;
+		case GT_PHY_PAGE_DIS_AUTO1:	/* 88E1111 Type */
+			if (autoOn) /* Auto On */
+			{
+				data = 0;
+				if((status= hwSetPhyRegField(dev,hwPort,27,9,1,data)) != GT_OK)
+				{
+	    			DBG_INFO(("Not able to write Phy Register.\n"));
+					return status;
+				}
+			}
+
+			break;	
+		case GT_PHY_PAGE_DIS_AUTO2:	/* 88E1112 Type */
+			if (autoOn) /* Auto On */
+			{
+				data = 1;
+				if((status= hwSetPhyRegField(dev,hwPort,22,15,1,data)) != GT_OK)
+				{
+	    			DBG_INFO(("Not able to write Phy Register.\n"));
+					return status;
+				}
+			}
+
+			break;	
+
+		case GT_PHY_NO_PAGE:
+		default:
+			/* Nothing to do */
+			return GT_OK;
+	}
+
+
+	if((status= hwSetPhyRegField(dev,hwPort,22,0,8,pageReg)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to write Phy Register.\n"));
+		return status;
+	}
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* driverFindPhyInformation
+*
+* DESCRIPTION:
+*       This function gets information of Phy connected to the given port.
+*		PhyInfo structure should have valid Phy ID.
+*
+* INPUTS:
+*       hwPort	- port number where the Phy is connected
+*
+* OUTPUTS:
+*       phyId	- Phy ID
+*
+* RETURNS:
+*       GT_OK 	- if found Marvell Phy,
+*       GT_FAIL - othrwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS driverFindPhyInformation
+(
+	IN  GT_QD_DEV    *dev,
+	IN	GT_U8		 hwPort,
+	OUT	GT_PHY_INFO	 *phyInfo
+)
+{
+	GT_U32 phyId;
+	GT_U16 data;
+
+	phyId = phyInfo->phyId;
+
+	switch (phyId & PHY_MODEL_MASK)
+	{
+		case DEV_E3082:
+				phyInfo->anyPage = 0xFFFFFFFF;
+				phyInfo->flag = GT_PHY_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_EXTERNAL_LOOP|
+								GT_PHY_COPPER;
+				phyInfo->vctType = GT_PHY_VCT_TYPE1;
+				phyInfo->exStatusType = 0;
+				if ((phyId & PHY_REV_MASK) < 9)
+					phyInfo->dteType = GT_PHY_DTE_TYPE1;	/* need workaround */
+				else
+					phyInfo->dteType = GT_PHY_DTE_TYPE5;
+
+				phyInfo->pktGenType = 0;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+				phyInfo->lineLoopType = 0;
+				phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+				phyInfo->pageType = GT_PHY_NO_PAGE;
+				break;
+
+	    case DEV_E104X:
+				phyInfo->anyPage = 0xFFFFFFFF;
+				phyInfo->flag = GT_PHY_VCT_CAPABLE|GT_PHY_GIGABIT|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_EXTERNAL_LOOP;
+
+				phyInfo->dteType = 0;
+				if ((phyId & PHY_REV_MASK) < 3)
+					phyInfo->flag &= ~GT_PHY_VCT_CAPABLE; /* VCT is not supported */
+				else if ((phyId & PHY_REV_MASK) == 3)
+					phyInfo->vctType = GT_PHY_VCT_TYPE3;	/* Need workaround */
+				else 
+					phyInfo->vctType = GT_PHY_VCT_TYPE2;
+				phyInfo->exStatusType = 0;
+
+				phyInfo->pktGenType = 0;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+				phyInfo->lineLoopType = 0;
+				phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+				phyInfo->pageType = GT_PHY_NO_PAGE;
+
+				break;
+
+		case DEV_E1111:
+				phyInfo->anyPage = 0xFFF1FE0C;
+				phyInfo->flag = GT_PHY_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+								GT_PHY_EX_CABLE_STATUS|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP|
+								GT_PHY_GIGABIT|GT_PHY_RESTRICTED_PAGE;
+
+				phyInfo->vctType = GT_PHY_VCT_TYPE2;
+				phyInfo->exStatusType = GT_PHY_EX_STATUS_TYPE1;
+				if ((phyId & PHY_REV_MASK) < 2)
+					phyInfo->dteType = GT_PHY_DTE_TYPE3;	/* Need workaround */
+				else
+					phyInfo->dteType = GT_PHY_DTE_TYPE2;
+
+				phyInfo->pktGenType = GT_PHY_PKTGEN_TYPE1;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+				phyInfo->lineLoopType = 0;
+				phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+				phyInfo->pageType = GT_PHY_PAGE_DIS_AUTO1;
+				break;
+
+		case DEV_E1112:
+				phyInfo->anyPage = 0x1BC0780C;
+				phyInfo->flag = GT_PHY_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+								GT_PHY_EX_CABLE_STATUS|
+								GT_PHY_GIGABIT|GT_PHY_RESTRICTED_PAGE|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP|
+								GT_PHY_PKT_GENERATOR;
+
+				phyInfo->vctType = GT_PHY_VCT_TYPE4;
+				phyInfo->exStatusType = GT_PHY_EX_STATUS_TYPE2;
+				phyInfo->dteType = GT_PHY_DTE_TYPE4;
+
+				phyInfo->pktGenType = GT_PHY_PKTGEN_TYPE2;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+				phyInfo->lineLoopType = 0;
+				phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+				phyInfo->pageType = GT_PHY_PAGE_DIS_AUTO2;
+				break;
+
+		case DEV_E114X:
+				phyInfo->anyPage = 0x2FF1FE0C;
+				phyInfo->flag = GT_PHY_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+								GT_PHY_EX_CABLE_STATUS|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP|
+								GT_PHY_GIGABIT|GT_PHY_RESTRICTED_PAGE;
+
+				phyInfo->vctType = GT_PHY_VCT_TYPE2;
+				phyInfo->exStatusType = GT_PHY_EX_STATUS_TYPE1;
+				if ((phyId & PHY_REV_MASK) < 4)
+					phyInfo->dteType = GT_PHY_DTE_TYPE3;	/* Need workaround */
+				else
+					phyInfo->dteType = GT_PHY_DTE_TYPE2;
+
+				phyInfo->pktGenType = GT_PHY_PKTGEN_TYPE1;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+				phyInfo->lineLoopType = 0;
+				phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+				phyInfo->pageType = GT_PHY_PAGE_DIS_AUTO1;
+
+				break;
+
+		case DEV_E1149:
+				phyInfo->anyPage = 0x2040FFFF;
+				phyInfo->flag = GT_PHY_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+								GT_PHY_EX_CABLE_STATUS|
+								GT_PHY_GIGABIT|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP|
+								GT_PHY_PKT_GENERATOR;
+				phyInfo->vctType = GT_PHY_VCT_TYPE4;
+				phyInfo->exStatusType = GT_PHY_EX_STATUS_TYPE3;
+				phyInfo->dteType = GT_PHY_DTE_TYPE4;
+				phyInfo->pktGenType = GT_PHY_PKTGEN_TYPE2;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+				phyInfo->lineLoopType = 0;
+				phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+				phyInfo->pageType = GT_PHY_PAGE_WRITE_BACK;
+				break;
+
+		case DEV_G15LV:
+				if (IS_IN_DEV_GROUP(dev,DEV_88E6108))
+				{
+					phyInfo->anyPage = 0x2040FFFF;
+					phyInfo->flag = GT_PHY_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+									GT_PHY_EX_CABLE_STATUS|
+									GT_PHY_GIGABIT|
+									GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP|
+									GT_PHY_PKT_GENERATOR;
+					phyInfo->vctType = GT_PHY_VCT_TYPE4;
+					phyInfo->exStatusType = GT_PHY_EX_STATUS_TYPE3;
+					phyInfo->dteType = GT_PHY_DTE_TYPE4;
+					phyInfo->pktGenType = GT_PHY_PKTGEN_TYPE2;
+					phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+					phyInfo->lineLoopType = 0;
+					phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+					phyInfo->pageType = GT_PHY_PAGE_WRITE_BACK;
+				}
+				else /* 88E6165 family */
+				{
+					phyInfo->anyPage = 0x2040FFFF;
+					phyInfo->flag = GT_PHY_ADV_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+									GT_PHY_EX_CABLE_STATUS|
+									GT_PHY_GIGABIT|
+									GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP|
+									GT_PHY_PKT_GENERATOR;
+					phyInfo->vctType = GT_PHY_ADV_VCT_TYPE2;
+					phyInfo->exStatusType = GT_PHY_EX_STATUS_TYPE6;
+					phyInfo->dteType = GT_PHY_DTE_TYPE4;
+					phyInfo->pktGenType = GT_PHY_PKTGEN_TYPE2;
+					phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+					phyInfo->lineLoopType = 0;
+					phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+					phyInfo->pageType = GT_PHY_PAGE_WRITE_BACK;
+				}
+				break;
+
+		case DEV_EC010:
+				phyInfo->anyPage = 0x2040780C;
+				phyInfo->flag = GT_PHY_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+								GT_PHY_EX_CABLE_STATUS|
+								GT_PHY_GIGABIT|GT_PHY_RESTRICTED_PAGE|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP;
+				phyInfo->vctType = GT_PHY_VCT_TYPE2;
+				phyInfo->exStatusType = 0;
+				phyInfo->dteType = GT_PHY_DTE_TYPE3;	/* Need workaround */
+				phyInfo->pktGenType = 0;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+				phyInfo->lineLoopType = 0;
+				phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+				phyInfo->pageType = GT_PHY_PAGE_WRITE_BACK;
+				break;
+
+		case DEV_S15LV:
+				phyInfo->anyPage = 0xFFFFFFFF;
+				phyInfo->flag = GT_PHY_SERDES_CORE|GT_PHY_GIGABIT|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP|
+								GT_PHY_PKT_GENERATOR;
+				phyInfo->vctType = 0;
+				phyInfo->exStatusType = 0;
+				phyInfo->dteType = 0;
+				phyInfo->pktGenType = GT_PHY_PKTGEN_TYPE3;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE3;
+				phyInfo->lineLoopType = GT_PHY_LINE_LB_TYPE4;
+				phyInfo->exLoopType = 0;
+				phyInfo->pageType = GT_PHY_NO_PAGE;
+				break;
+
+		case DEV_G65G:
+				phyInfo->anyPage = 0x2040FFFF;
+				phyInfo->flag = GT_PHY_ADV_VCT_CAPABLE|GT_PHY_DTE_CAPABLE|
+								GT_PHY_EX_CABLE_STATUS|
+								GT_PHY_GIGABIT|
+								GT_PHY_MAC_IF_LOOP|GT_PHY_LINE_LOOP|GT_PHY_EXTERNAL_LOOP|
+								GT_PHY_PKT_GENERATOR;
+				phyInfo->vctType = GT_PHY_ADV_VCT_TYPE2;
+				phyInfo->exStatusType = GT_PHY_EX_STATUS_TYPE6;
+				phyInfo->dteType = GT_PHY_DTE_TYPE4;
+				phyInfo->pktGenType = GT_PHY_PKTGEN_TYPE2;
+				phyInfo->macIfLoopType = GT_PHY_LOOPBACK_TYPE1;
+				phyInfo->lineLoopType = 0;
+				phyInfo->exLoopType = GT_PHY_EX_LB_TYPE0;
+				phyInfo->pageType = GT_PHY_PAGE_WRITE_BACK;
+				break;
+
+		case DEV_G65FE:
+				/*Victor: only added flag information, fill other parameters if needed*/
+				phyInfo->flag = 0;
+				break;
+
+		case DEV_G65GE:
+				/*Victor: only added anyPage and flag information, fill other parameters if needed*/
+				phyInfo->anyPage = 0;				
+				phyInfo->pageType = GT_PHY_PAGE_WRITE_BACK;
+				phyInfo->flag = GT_PHY_GIGABIT;
+				break;
+#ifdef QSGMII_ENABLE_UNI_3
+        case DEV_QUAD3:
+                /*Yuval: The fourth QUAD_PHY phy_id  - switch_port(3) */
+                phyInfo->anyPage = 0;
+                phyInfo->flag = GT_PHY_GIGABIT;
+                break;
+#endif
+		default:
+			return GT_FAIL;
+	}
+				
+	if (phyInfo->flag & GT_PHY_GIGABIT)
+	{
+	    if(hwGetPhyRegField(dev,hwPort,15,12,4,&data) != GT_OK)
+		{
+        	DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,15));
+	   	    return GT_FAIL;
+		}
+
+		if(data & QD_GIGPHY_1000X_CAP)
+			phyInfo->flag |= GT_PHY_FIBER;
+
+		if(data & QD_GIGPHY_1000T_CAP)
+		{
+			phyInfo->flag |= GT_PHY_COPPER;
+		}
+		else
+		{
+			phyInfo->flag &= ~(GT_PHY_VCT_CAPABLE|GT_PHY_EX_CABLE_STATUS|GT_PHY_DTE_CAPABLE|GT_PHY_ADV_VCT_CAPABLE);
+		}
+	}
+
+    return GT_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtDrvEvents.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtDrvEvents.c
new file mode 100755
index 0000000..94fc59d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtDrvEvents.c
@@ -0,0 +1,95 @@
+#include <Copyright.h>
+/********************************************************************************
+* gtDrvEvents.c
+*
+* DESCRIPTION:
+*       This file includes function declarations for QuarterDeck interrupts
+*       configuration and handling.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1 $
+*
+*******************************************************************************/
+
+#include <gtDrvSwRegs.h>
+#include <gtHwCntl.h>
+#include <gtDrvEvents.h>
+
+/*******************************************************************************
+* drvEventsInit
+*
+* DESCRIPTION:
+*       This function initializes the driver's interrupt handling mechanism.
+*
+* INPUTS:
+*       intVecNum   - The interrupt vector the switch is connected to.
+*       isrFunc     - A pointer to the Interrupt Service Routine to be
+*                     connected to the given interrupt vector.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success,
+*       GT_FAIL - otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS drvEventsInit
+(
+    IN  GT_QD_DEV       *dev,
+    IN GT_U32           intVecNum,
+    IN GT_VOIDFUNCPTR   isrFunc
+)
+{
+	GT_UNUSED_PARAM(dev);
+	GT_UNUSED_PARAM(intVecNum);
+	GT_UNUSED_PARAM(isrFunc);
+#if 0
+    return osInterruptConnect(intVecNum,isrFunc,0);
+#endif
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* eventQdSr
+*
+* DESCRIPTION:
+*       QuarterDeck interrupt service routine.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       None.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_BOOL eventQdSr
+(
+	IN  GT_QD_DEV* dev,
+	OUT GT_U16* intCause
+)
+{
+    GT_STATUS       retVal;         /* Function calls return value.     */
+
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,0,4,intCause);
+
+    if(retVal != GT_OK)
+        return GT_FALSE;
+
+    return (*intCause)?GT_TRUE:GT_FALSE;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtHwCntl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtHwCntl.c
new file mode 100755
index 0000000..9c06a45
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/gtHwCntl.c
@@ -0,0 +1,2474 @@
+#include <Copyright.h>
+/********************************************************************************
+* gtHwCntl.c
+*
+* DESCRIPTION:
+*       Functions declarations for Hw accessing quarterDeck phy, internal and
+*       global registers.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*
+*******************************************************************************/
+
+#include <gtDrvSwRegs.h>
+#include <gtHwCntl.h>
+#include <gtMiiSmiIf.h>
+#include <gtSem.h>
+
+
+static GT_STATUS hwReadPPU(GT_QD_DEV *dev, GT_U16 *data);
+static GT_STATUS hwWritePPU(GT_QD_DEV *dev, GT_U16 data);
+static GT_STATUS coreReadPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    regAddr,
+	OUT GT_U16   *data
+);
+static GT_STATUS coreWritePhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U16   data
+);
+static GT_STATUS coreReadPagedPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    pageNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U32	 anyPage,
+	OUT GT_U16   *data
+);
+static GT_STATUS coreWritePagedPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    pageNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U32	 anyPage,
+	IN  GT_U16   data
+);
+
+static GT_STATUS phyRegReadPPUEn (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int regAddr,
+                        GT_U16* value);
+static GT_STATUS phyRegWritePPUEn (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int regAddr,
+                       GT_U16 value);
+static GT_STATUS phyReadGlobal2Reg
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    OUT GT_U16   *data
+);
+static GT_STATUS phyWriteGlobal2Reg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   data
+);
+
+
+/*******************************************************************************
+* portToSmiMapping
+*
+* DESCRIPTION:
+*       This function mapps port to smi address
+*
+* INPUTS:
+*		dev - device context
+*       portNum - Port number to read the register for.
+*		accessType - type of register (Phy, Port, or Global)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       smiAddr    - smi address.
+*
+*******************************************************************************/
+GT_U8 portToSmiMapping
+(
+    IN GT_QD_DEV *dev,
+    IN GT_U8	portNum,
+	IN GT_U32	accessType
+)
+{
+	GT_U8 smiAddr;
+
+	if(IS_IN_DEV_GROUP(dev,DEV_8PORT_SWITCH))
+	{
+		switch(accessType)
+		{
+			case PHY_ACCESS:
+					if (dev->validPhyVec & (1<<portNum))
+						smiAddr = PHY_REGS_START_ADDR_8PORT + portNum;
+					else
+						smiAddr = 0xFF;
+					break;
+			case PORT_ACCESS:
+					if (dev->validPortVec & (1<<portNum))
+						smiAddr = PORT_REGS_START_ADDR_8PORT + portNum;
+					else
+						smiAddr = 0xFF;
+					break;
+			case GLOBAL_REG_ACCESS:
+					smiAddr = GLOBAL_REGS_START_ADDR_8PORT;
+					break;
+			default:
+					smiAddr = GLOBAL_REGS_START_ADDR_8PORT + 1;
+					break;
+		}
+	}
+	else
+	{
+		smiAddr = dev->baseRegAddr;
+		switch(accessType)
+		{
+			case PHY_ACCESS:
+					if (dev->validPhyVec & (1<<portNum))
+						smiAddr += PHY_REGS_START_ADDR + portNum;
+					else
+						smiAddr = 0xFF;
+					break;
+			case PORT_ACCESS:
+					if (dev->validPortVec & (1<<portNum))
+						smiAddr += PORT_REGS_START_ADDR + portNum;
+					else
+						smiAddr = 0xFF;
+					break;
+			case GLOBAL_REG_ACCESS:
+					smiAddr += GLOBAL_REGS_START_ADDR;
+					break;
+			default:
+					smiAddr += GLOBAL_REGS_START_ADDR - 1;
+					break;
+		}
+	}
+
+    return smiAddr;
+}
+
+
+/****************************************************************************/
+/* Phy registers related functions.                                         */
+/****************************************************************************/
+
+/*******************************************************************************
+* hwReadPhyReg
+*
+* DESCRIPTION:
+*       This function reads a switch's port phy register.
+*
+* INPUTS:
+*       portNum - Port number to read the register for.
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    regAddr,
+	OUT GT_U16   *data
+)
+{
+	GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+	retVal = coreReadPhyReg(dev, portNum, regAddr, data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* hwWritePhyReg
+*
+* DESCRIPTION:
+*       This function writes to a switch's port phy register.
+*
+* INPUTS:
+*       portNum - Port number to write the register for.
+*       regAddr - The register's address.
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWritePhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U16   data
+)
+{
+	GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+	retVal = coreWritePhyReg(dev, portNum, regAddr, data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* hwGetPhyRegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's port phy register.
+*
+* INPUTS:
+*       portNum     - Port number to read the register for.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetPhyRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+    OUT GT_U16   *data
+)
+{
+    GT_U16 mask;            /* Bits mask to be read */
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+	retVal = coreReadPhyReg(dev, portNum, regAddr, &tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	if (retVal != GT_OK)
+		return retVal;
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+
+    tmpData = (tmpData & mask) >> fieldOffset;
+    *data = tmpData;
+
+    DBG_INFO(("Read from phy(%d) register: regAddr 0x%x, ",
+              portNum,regAddr));
+    DBG_INFO(("fOff %d, fLen %d, data 0x%x.\n",fieldOffset,fieldLength,*data));
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* hwSetPhyRegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's port phy register.
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetPhyRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+    IN  GT_U16   data
+)
+{
+    GT_U16 mask;
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+	retVal = coreReadPhyReg(dev, portNum, regAddr, &tmpData);
+
+    if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->multiAddrSem);
+        return retVal;
+	}
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+
+    /* Set the desired bits to 0.                       */
+    tmpData &= ~mask;
+    /* Set the given data into the above reset bits.    */
+    tmpData |= ((data << fieldOffset) & mask);
+
+    DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, ",
+              portNum,regAddr));
+    DBG_INFO(("fieldOff %d, fieldLen %d, data 0x%x.\n",fieldOffset,
+              fieldLength,data));
+
+	retVal = coreWritePhyReg(dev, portNum, regAddr, tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwReadPagedPhyReg
+*
+* DESCRIPTION:
+*       This function reads a switch's port phy register in page mode.
+*
+* INPUTS:
+*       portNum - Port number to read the register for.
+*       pageNum - Page number of the register to be read.
+*       regAddr - The register's address.
+*		anyPage - Any Page register vector
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadPagedPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    pageNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U32	 anyPage,
+	OUT GT_U16   *data
+)
+{
+	GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+	retVal = coreReadPagedPhyReg(dev,portNum,pageNum,regAddr,anyPage,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* hwWritePagedPhyReg
+*
+* DESCRIPTION:
+*       This function writes to a switch's port phy register in page mode.
+*
+* INPUTS:
+*       portNum - Port number to write the register for.
+*       pageNum - Page number of the register to be written.
+*       regAddr - The register's address.
+*		anyPage - Any Page register vector
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWritePagedPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    pageNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U32	 anyPage,
+	IN  GT_U16   data
+)
+{
+	GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+	retVal = coreWritePagedPhyReg(dev,portNum,pageNum,regAddr,anyPage,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* hwGetPagedPhyRegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's port phy register
+*		in page mode.
+*
+* INPUTS:
+*       portNum     - Port number to read the register for.
+*       pageNum 	- Page number of the register to be read.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*		anyPage 	- Any Page register vector
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetPagedPhyRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    pageNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+	IN  GT_U32	 anyPage,
+    OUT GT_U16   *data
+)
+{
+    GT_U16 mask;            /* Bits mask to be read */
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = coreReadPagedPhyReg(dev,portNum,pageNum,regAddr,anyPage,&tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	if(retVal != GT_OK)
+	{
+        return retVal;
+	}
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+
+    tmpData = (tmpData & mask) >> fieldOffset;
+    *data = tmpData;
+
+    DBG_INFO(("Read from phy(%d) register: regAddr 0x%x, ",
+              portNum,regAddr));
+    DBG_INFO(("fOff %d, fLen %d, data 0x%x.\n",fieldOffset,fieldLength,*data));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* hwSetPagedPhyRegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's port phy register
+*		in page mode
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       pageNum 	- Page number of the register to be read.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*		anyPage 	- Any Page register vector
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetPagedPhyRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    pageNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+	IN  GT_U32	 anyPage,
+    IN  GT_U16   data
+)
+{
+    GT_U16 mask;
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    if((retVal=coreReadPagedPhyReg(dev,portNum,pageNum,regAddr,anyPage,&tmpData)) != GT_OK)
+	{
+		gtSemGive(dev,dev->multiAddrSem);
+        return retVal;
+	}
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+
+    /* Set the desired bits to 0.                       */
+    tmpData &= ~mask;
+    /* Set the given data into the above reset bits.    */
+    tmpData |= ((data << fieldOffset) & mask);
+
+    DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, ",
+              portNum,regAddr));
+    DBG_INFO(("fieldOff %d, fieldLen %d, data 0x%x.\n",fieldOffset,
+              fieldLength,data));
+    retVal = coreWritePagedPhyReg(dev,portNum,pageNum,regAddr,anyPage,tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	return retVal;	
+}
+
+
+/*******************************************************************************
+* hwPhyReset
+*
+* DESCRIPTION:
+*       This function performs softreset and waits until reset completion.
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       u16Data     - data should be written into Phy control register.
+*					  if this value is 0xFF, normal operation occcurs (read, 
+*					  update, and write back.)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS hwPhyReset
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_U8		portNum,
+	IN	GT_U16		u16Data
+)
+{
+    GT_U16 tmpData;
+    GT_STATUS   retVal;
+    GT_U32 retryCount;
+	GT_BOOL	pd = GT_FALSE;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    if((retVal=coreReadPhyReg(dev,portNum,0,&tmpData)) 
+   	    != GT_OK)
+    {
+   	    DBG_INFO(("Reading Register failed\n"));
+		gtSemGive(dev,dev->multiAddrSem);
+       	return retVal;
+    }
+
+	if (tmpData & 0x800)
+	{
+		pd = GT_TRUE;
+	}
+
+	if (u16Data != 0xFF)
+	{
+		tmpData = u16Data;
+	}
+
+    /* Set the desired bits to 0. */
+	if (pd)
+	{
+	    tmpData |= 0x800;
+	}
+	else
+	{
+	    tmpData |= 0x8000;
+	}
+
+    if((retVal=coreWritePhyReg(dev,portNum,0,tmpData)) 
+        != GT_OK)
+    {
+        DBG_INFO(("Writing to register failed\n"));
+		gtSemGive(dev,dev->multiAddrSem);
+        return retVal;
+    }
+
+	if (pd)
+	{
+		gtSemGive(dev,dev->multiAddrSem);
+	    return GT_OK;
+	}
+
+    for (retryCount = 0x1000; retryCount > 0; retryCount--)
+    {
+        if((retVal=coreReadPhyReg(dev,portNum,0,&tmpData)) != GT_OK)
+        {
+            DBG_INFO(("Reading register failed\n"));
+			gtSemGive(dev,dev->multiAddrSem);
+            return retVal;
+        }
+        if ((tmpData & 0x8000) == 0)
+            break;
+    }
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    if (retryCount == 0)
+    {
+        DBG_INFO(("Reset bit is not cleared\n"));
+        return GT_FAIL;
+    }
+
+    return GT_OK;
+}
+
+/****************************************************************************/
+/* Per port registers related functions.                                    */
+/****************************************************************************/
+
+/*******************************************************************************
+* hwReadPortReg
+*
+* DESCRIPTION:
+*       This function reads a switch's port register.
+*
+* INPUTS:
+*       portNum - Port number to read the register for.
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadPortReg
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    regAddr,
+    OUT GT_U16   *data
+)
+{
+    GT_U8       phyAddr;
+    GT_STATUS   retVal;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PORT_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal =  miiSmiIfReadRegister(dev,phyAddr,regAddr,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    DBG_INFO(("Read from port(%d) register: phyAddr 0x%x, regAddr 0x%x, ",
+              portNum,phyAddr,regAddr));
+    DBG_INFO(("data 0x%x.\n",*data));
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwWritePortReg
+*
+* DESCRIPTION:
+*       This function writes to a switch's port register.
+*
+* INPUTS:
+*       portNum - Port number to write the register for.
+*       regAddr - The register's address.
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWritePortReg
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   data
+)
+{
+    GT_U8   phyAddr;
+    GT_STATUS   retVal;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PORT_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    DBG_INFO(("Write to port(%d) register: phyAddr 0x%x, regAddr 0x%x, ",
+              portNum,phyAddr,regAddr));
+    DBG_INFO(("data 0x%x.\n",data));
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* hwGetPortRegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's port register.
+*
+* INPUTS:
+*       portNum     - Port number to read the register for.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetPortRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+    OUT GT_U16   *data
+)
+{
+    GT_U16 mask;            /* Bits mask to be read */
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PORT_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal =  miiSmiIfReadRegister(dev,phyAddr,regAddr,&tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	if (retVal != GT_OK)
+		return retVal;
+		
+    CALC_MASK(fieldOffset,fieldLength,mask);
+
+    tmpData = (tmpData & mask) >> fieldOffset;
+    *data = tmpData;
+    DBG_INFO(("Read from port(%d) register: regAddr 0x%x, ",
+              portNum,regAddr));
+    DBG_INFO(("fOff %d, fLen %d, data 0x%x.\n",fieldOffset,fieldLength,*data));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* hwSetPortRegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's port register.
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetPortRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+    IN  GT_U16   data
+)
+{
+    GT_U16 mask;
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PORT_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal =  miiSmiIfReadRegister(dev,phyAddr,regAddr,&tmpData);
+
+    if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->multiAddrSem);
+        return retVal;
+	}
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+
+    /* Set the desired bits to 0.                       */
+    tmpData &= ~mask;
+    /* Set the given data into the above reset bits.    */
+    tmpData |= ((data << fieldOffset) & mask);
+    DBG_INFO(("Write to port(%d) register: regAddr 0x%x, ",
+              portNum,regAddr));
+    DBG_INFO(("fieldOff %d, fieldLen %d, data 0x%x.\n",fieldOffset,
+              fieldLength,data));
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwSetPortRegBits
+*
+* DESCRIPTION:
+*       This function writes to specified bits in a switch's port register.
+*
+* INPUTS:
+*       portNum     - Port number to write the register for.
+*       regAddr     - The register's address.
+*       mask 		- The bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  When Data is 0x1002 and mask is 0xF00F, 0001b is written to bit[31:24]
+*			and 0010b is written to bit[3:0]
+*
+*******************************************************************************/
+GT_STATUS hwSetPortRegBits
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    portNum,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   mask,
+    IN  GT_U16   data
+)
+{
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PORT_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal =  miiSmiIfReadRegister(dev,phyAddr,regAddr,&tmpData);
+
+    if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->multiAddrSem);
+        return retVal;
+	}
+
+    /* Set the desired bits to 0.                       */
+    tmpData &= ~mask;
+    /* Set the given data into the above reset bits.    */
+    tmpData |= (data & mask);
+    DBG_INFO(("Write to port(%d) register: regAddr 0x%x, ",
+              portNum,regAddr));
+    DBG_INFO(("mask %d, data 0x%x.\n",mask,data));
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    return retVal;
+}
+
+
+
+/****************************************************************************/
+/* Global registers related functions.                                      */
+/****************************************************************************/
+
+/*******************************************************************************
+* hwReadGlobalReg
+*
+* DESCRIPTION:
+*       This function reads a switch's global register.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadGlobalReg
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    OUT GT_U16   *data
+)
+{
+    GT_U8       phyAddr;
+    GT_STATUS   retVal;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    DBG_INFO(("read from global register: phyAddr 0x%x, regAddr 0x%x, ",
+              phyAddr,regAddr));
+    DBG_INFO(("data 0x%x.\n",*data));
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwWriteGlobalReg
+*
+* DESCRIPTION:
+*       This function writes to a switch's global register.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWriteGlobalReg
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   data
+)
+{
+    GT_U8   phyAddr;
+    GT_STATUS   retVal;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
+
+    DBG_INFO(("Write to global register: phyAddr 0x%x, regAddr 0x%x, ",
+              phyAddr,regAddr));
+    DBG_INFO(("data 0x%x.\n",data));
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* hwGetGlobalRegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's global register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetGlobalRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+    OUT GT_U16   *data
+)
+{
+    GT_U16 mask;            /* Bits mask to be read */
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,&tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    if(retVal != GT_OK)
+	{
+        return retVal;
+	}
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+    tmpData = (tmpData & mask) >> fieldOffset;
+    *data = tmpData;
+    DBG_INFO(("Read from global register: regAddr 0x%x, ",
+              regAddr));
+    DBG_INFO(("fOff %d, fLen %d, data 0x%x.\n",fieldOffset,fieldLength,*data));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* hwSetGlobalRegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's global register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetGlobalRegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+    IN  GT_U16   data
+)
+{
+    GT_U16 mask;
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal =  miiSmiIfReadRegister(dev,phyAddr,regAddr,&tmpData);
+
+    if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->multiAddrSem);
+        return retVal;
+	}
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+
+    /* Set the desired bits to 0.                       */
+    tmpData &= ~mask;
+    /* Set the given data into the above reset bits.    */
+    tmpData |= ((data << fieldOffset) & mask);
+
+    DBG_INFO(("Write to global register: regAddr 0x%x, ",
+              regAddr));
+    DBG_INFO(("fieldOff %d, fieldLen %d, data 0x%x.\n",fieldOffset,
+              fieldLength,data));
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    return retVal;
+}
+
+/*******************************************************************************
+* hwReadGlobal2Reg
+*
+* DESCRIPTION:
+*       This function reads a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadGlobal2Reg
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    OUT GT_U16   *data
+)
+{
+    GT_U8       phyAddr;
+    GT_STATUS   retVal;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    DBG_INFO(("read from global 2 register: phyAddr 0x%x, regAddr 0x%x, ",
+              phyAddr,regAddr));
+    DBG_INFO(("data 0x%x.\n",*data));
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwWriteGlobal2Reg
+*
+* DESCRIPTION:
+*       This function writes to a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*       data    - The data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWriteGlobal2Reg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   data
+)
+{
+    GT_U8   phyAddr;
+    GT_STATUS   retVal;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    DBG_INFO(("Write to global 2 register: phyAddr 0x%x, regAddr 0x%x, ",
+              phyAddr,regAddr));
+    DBG_INFO(("data 0x%x.\n",data));
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwGetGlobal2RegField
+*
+* DESCRIPTION:
+*       This function reads a specified field from a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to read.
+*
+* OUTPUTS:
+*       data        - The read register field.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwGetGlobal2RegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+    OUT GT_U16   *data
+)
+{
+    GT_U16 mask;            /* Bits mask to be read */
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,&tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    if(retVal != GT_OK)
+        return retVal;
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+    tmpData = (tmpData & mask) >> fieldOffset;
+    *data = tmpData;
+    DBG_INFO(("Read from global 2 register: regAddr 0x%x, ",
+              regAddr));
+    DBG_INFO(("fOff %d, fLen %d, data 0x%x.\n",fieldOffset,fieldLength,*data));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* hwSetGlobal2RegField
+*
+* DESCRIPTION:
+*       This function writes to specified field in a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       fieldOffset - The field start bit index. (0 - 15)
+*       fieldLength - Number of bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  The sum of fieldOffset & fieldLength parameters must be smaller-
+*           equal to 16.
+*
+*******************************************************************************/
+GT_STATUS hwSetGlobal2RegField
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U8    fieldOffset,
+    IN  GT_U8    fieldLength,
+    IN  GT_U16   data
+)
+{
+    GT_U16 mask;
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,&tmpData);
+
+    if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->multiAddrSem);
+        return retVal;
+	}
+
+    CALC_MASK(fieldOffset,fieldLength,mask);
+
+    /* Set the desired bits to 0.                       */
+    tmpData &= ~mask;
+    /* Set the given data into the above reset bits.    */
+    tmpData |= ((data << fieldOffset) & mask);
+
+    DBG_INFO(("Write to global 2 register: regAddr 0x%x, ",
+              regAddr));
+    DBG_INFO(("fieldOff %d, fieldLen %d, data 0x%x.\n",fieldOffset,
+              fieldLength,data));
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    return retVal;
+}
+
+/*******************************************************************************
+* hwSetGlobal2RegBits
+*
+* DESCRIPTION:
+*       This function writes to specified bits in a switch's global 2 register.
+*
+* INPUTS:
+*       regAddr     - The register's address.
+*       mask 		- The bits to write.
+*       data        - Data to be written.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  When Data is 0x1002 and mask is 0xF00F, 0001b is written to bit[31:24]
+*			and 0010b is written to bit[3:0]
+*
+*******************************************************************************/
+GT_STATUS hwSetGlobal2RegBits
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   mask,
+    IN  GT_U16   data
+)
+{
+    GT_U16 tmpData;
+	GT_STATUS   retVal;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,&tmpData);
+
+    if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->multiAddrSem);
+        return retVal;
+	}
+
+    /* Set the desired bits to 0.                       */
+    tmpData &= ~mask;
+    /* Set the given data into the above reset bits.    */
+    tmpData |= (data & mask);
+
+    DBG_INFO(("Write to global 2 register: regAddr 0x%x, ",
+              regAddr));
+    DBG_INFO(("mask %d, data 0x%x.\n",mask,data));
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,tmpData);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwReadMiiReg
+*
+* DESCRIPTION:
+*       This function reads a switch register.
+*
+* INPUTS:
+*       phyAddr - Phy Address to read the register for.( 0 ~ 0x1F )
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwReadMiiReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     phyAddr,
+    IN  GT_U8     regAddr,
+    OUT GT_U16    *data
+)
+{
+    GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,data);
+
+ 	gtSemGive(dev,dev->multiAddrSem);
+
+    DBG_INFO(("Read from phy(0x%x) register: regAddr 0x%x, data 0x%x.\n",
+              phyAddr,regAddr,*data));
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwWriteMiiReg
+*
+* DESCRIPTION:
+*       This function writes a switch register.
+*
+* INPUTS:
+*       phyAddr - Phy Address to read the register for.( 0 ~ 0x1F )
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK on success, or
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS hwWriteMiiReg
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    phyAddr,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   data
+)
+{
+    GT_STATUS   retVal;
+
+	gtSemTake(dev,dev->multiAddrSem,OS_WAIT_FOREVER);
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,data);
+
+	gtSemGive(dev,dev->multiAddrSem);
+
+    DBG_INFO(("Write to phy(0x%x) register: regAddr 0x%x, data 0x%x.\n",
+              phyAddr,regAddr,data));
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* hwReadPPU
+*
+* DESCRIPTION:
+*			This function reads PPU bit in Global Register
+*
+* INPUTS:
+*			None.
+*
+* OUTPUTS:
+*			data    - The read register's data.
+*
+* RETURNS:
+*			GT_OK on success, or
+*			GT_FAIL otherwise.
+*
+* COMMENTS:
+*			This function can be used to access PHY register connected to Gigabit
+*			Switch.
+*			Semaphore should be acquired before this function get called.
+*
+*******************************************************************************/
+static GT_STATUS hwReadPPU
+(
+	IN  GT_QD_DEV *dev,
+	OUT GT_U16    *data
+)
+{
+	GT_STATUS   retVal;
+	GT_U16		tmpData;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    retVal =  miiSmiIfReadRegister(dev,phyAddr,4,&tmpData);
+
+    if(retVal != GT_OK)
+	{
+        return retVal;
+	}
+
+	*data = (tmpData >> 14) & 0x1;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* hwWritePPU
+*
+* DESCRIPTION:
+*			This function writes PPU bit in Global Register
+*
+* INPUTS:
+*			data - The value to write into PPU bit
+*
+* OUTPUTS:
+*			None.
+*
+* RETURNS:
+*			GT_OK on success, or
+*			GT_FAIL otherwise.
+*
+* COMMENTS:
+*			This function can be used to access PHY register connected to Gigabit
+*			Switch.
+*			Semaphore should be acquired before this function get called.
+*
+*******************************************************************************/
+static GT_STATUS hwWritePPU
+(
+	IN  GT_QD_DEV *dev,
+	IN  GT_U16    data
+)
+{
+	GT_STATUS   retVal;
+	GT_U16		tmpData;
+    GT_U8       phyAddr;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    retVal =  miiSmiIfReadRegister(dev,phyAddr,4,&tmpData);
+
+    if(retVal != GT_OK)
+	{
+        return retVal;
+	}
+
+	if (data)
+		tmpData |= (0x1 << 14);
+	else
+		tmpData &= ~(0x1 << 14);
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,4,tmpData);
+
+    if(retVal != GT_OK)
+	{
+        return retVal;
+	}
+
+	/* busy wait - till PPU is actually disabled */
+	if (data == 0) /* disable PPU */
+	{
+		gtDelay(250);
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+static GT_STATUS coreReadPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    regAddr,
+	OUT GT_U16   *data
+)
+{
+	GT_U8       phyAddr;
+	GT_STATUS   retVal, retPPU;
+	GT_U16		orgPPU = 0;
+	GT_BOOL		usePPU = GT_FALSE;
+
+	phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PHY_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	if(IS_IN_DEV_GROUP(dev,DEV_PPU_READ_ONLY))
+	{
+		if((IS_IN_DEV_GROUP(dev,DEV_PPU_SERDES_ACCESS_RES)) && (dev->validSerdesVec && (1<<phyAddr)))
+		{
+			if((retPPU=hwReadPPU(dev, &orgPPU)) != GT_OK)
+			{
+				return retPPU;
+			}
+
+			if(orgPPU)
+			{
+				/* Disable PPU so that External Phy can be accessible */
+				if((retPPU=hwWritePPU(dev, 0)) != GT_OK)
+				{
+					return retPPU;
+				}
+			}
+		}
+		else
+			usePPU = GT_TRUE;
+	}
+	else if(IS_IN_DEV_GROUP(dev,DEV_EXTERNAL_PHY))
+	{
+		if((retPPU=hwReadPPU(dev, &orgPPU)) != GT_OK)
+		{
+			return retPPU;
+		}
+
+		if(orgPPU)
+		{
+			if(IS_IN_DEV_GROUP(dev,DEV_PPU_PHY_ACCESS))
+			{
+				if(IS_IN_DEV_GROUP(dev,DEV_PPU_PHY_ACCESS_RES))
+				{
+					if(dev->revision != 0)
+						usePPU = GT_TRUE;
+				}
+				else
+				{
+				 	usePPU = GT_TRUE;
+				}
+			}
+
+			/* Disable PPU so that External Phy can be accessible */
+			if (!usePPU)
+			{
+				if((retPPU=hwWritePPU(dev, 0)) != GT_OK)
+				{
+					return retPPU;
+				}
+			}
+		}
+	}
+
+	if (usePPU)
+	{
+		retVal = phyRegReadPPUEn (dev,phyAddr,regAddr,data);
+	}
+	else
+	{
+		retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,data);
+	}
+
+	DBG_INFO(("Read from phy(%d) register: phyAddr 0x%x, regAddr 0x%x, ",
+				portNum,phyAddr,regAddr));
+
+	if(orgPPU && (!usePPU))
+	{
+		if((retPPU=hwWritePPU(dev, orgPPU)) != GT_OK)
+		{
+			return retPPU;
+		}
+	}
+
+	return retVal;
+}
+
+
+static GT_STATUS coreWritePhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U16   data
+)
+{
+	GT_U8   		phyAddr;
+	GT_STATUS   retVal, retPPU;
+	GT_U16		orgPPU = 0;
+	GT_BOOL		usePPU = GT_FALSE;
+
+	phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PHY_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	if(IS_IN_DEV_GROUP(dev,DEV_PPU_READ_ONLY))
+	{
+		if((IS_IN_DEV_GROUP(dev,DEV_PPU_SERDES_ACCESS_RES)) && (dev->validSerdesVec && (1<<phyAddr)))
+		{
+			if((retPPU=hwReadPPU(dev, &orgPPU)) != GT_OK)
+			{
+				return retPPU;
+			}
+
+			if(orgPPU)
+			{
+				/* Disable PPU so that External Phy can be accessible */
+				if((retPPU=hwWritePPU(dev, 0)) != GT_OK)
+				{
+						return retPPU;
+				}
+			}
+		}
+		else
+			usePPU = GT_TRUE;
+	}
+	else if(IS_IN_DEV_GROUP(dev,DEV_EXTERNAL_PHY))
+	{
+		if((retPPU=hwReadPPU(dev, &orgPPU)) != GT_OK)
+		{
+			return retPPU;
+		}
+
+		if(orgPPU)
+		{
+			if(IS_IN_DEV_GROUP(dev,DEV_PPU_PHY_ACCESS))
+			{
+				if(IS_IN_DEV_GROUP(dev,DEV_PPU_PHY_ACCESS_RES))
+				{
+					if(dev->revision != 0)
+						usePPU = GT_TRUE;
+				}
+				else
+				{
+				 	usePPU = GT_TRUE;
+				}
+			}
+
+			/* Disable PPU so that External Phy can be accessible */
+			if (!usePPU)
+			{
+				if((retPPU=hwWritePPU(dev, 0)) != GT_OK)
+				{
+					return retPPU;
+				}
+			}
+		}
+	}
+
+	DBG_INFO(("Write to phy(%d) register: phyAddr 0x%x, regAddr 0x%x, ",
+				portNum,phyAddr,regAddr));
+	DBG_INFO(("data 0x%x.\n",data));
+
+	if (usePPU)
+	{
+		retVal = phyRegWritePPUEn (dev,phyAddr,regAddr,data);
+	}
+	else
+	{
+		retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,data);
+	}
+
+	if(orgPPU && (!usePPU))
+	{
+		if((retPPU=hwWritePPU(dev, orgPPU)) != GT_OK)
+		{
+			return retPPU;
+		}
+	}
+
+	return retVal;
+}
+
+
+static GT_STATUS coreReadPagedPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    pageNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U32	 anyPage,
+	OUT GT_U16   *data
+)
+{
+	GT_U8       phyAddr,pageAddr;
+	GT_STATUS   retVal, retPPU;
+	GT_U16		orgPPU, tmpData, orgPage;
+	GT_BOOL		usePPU = GT_FALSE;
+
+	phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PHY_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	orgPPU = 0;
+
+	if(IS_IN_DEV_GROUP(dev,DEV_PPU_READ_ONLY))
+	{
+		if((IS_IN_DEV_GROUP(dev,DEV_PPU_SERDES_ACCESS_RES)) && (dev->validSerdesVec && (1<<phyAddr)))
+		{
+			if((retPPU=hwReadPPU(dev, &orgPPU)) != GT_OK)
+			{
+				return retPPU;
+			}
+
+			if(orgPPU)
+			{
+				/* Disable PPU so that External Phy can be accessible */
+				if((retPPU=hwWritePPU(dev, 0)) != GT_OK)
+				{
+					return retPPU;
+				}
+			}
+		}
+		else
+			usePPU = GT_TRUE;
+	}
+	else if(IS_IN_DEV_GROUP(dev,DEV_EXTERNAL_PHY))
+	{
+		if((retPPU=hwReadPPU(dev, &orgPPU)) != GT_OK)
+		{
+			return retPPU;
+		}
+
+		if(orgPPU)
+		{
+			if(IS_IN_DEV_GROUP(dev,DEV_PPU_PHY_ACCESS))
+			{
+				if(IS_IN_DEV_GROUP(dev,DEV_PPU_PHY_ACCESS_RES))
+				{
+					if(dev->revision != 0)
+						usePPU = GT_TRUE;
+				}
+				else
+				{
+				 	usePPU = GT_TRUE;
+				}
+			}
+
+			/* Disable PPU so that External Phy can be accessible */
+			if (!usePPU)
+			{
+				if((retPPU=hwWritePPU(dev, 0)) != GT_OK)
+				{
+					return retPPU;
+				}
+			}
+		}
+	}
+
+	if(anyPage & (1 << regAddr))
+	{
+		if (usePPU)
+		{
+			retVal = phyRegReadPPUEn (dev,phyAddr,regAddr,data);
+		}
+		else
+		{
+			retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,data);
+		}
+		DBG_INFO(("Read from phy(%d) register: smiAddr 0x%x, pageNum 0x%x, regAddr 0x%x\n",
+					portNum,phyAddr,pageNum,regAddr));
+	}
+	else
+	{
+	    pageAddr = GT_GET_PAGE_ADDR(regAddr);
+
+		if (usePPU)
+		{
+			retVal = phyRegReadPPUEn (dev,phyAddr,regAddr,&orgPage);
+		}
+		else
+		{
+			retVal = miiSmiIfReadRegister(dev,phyAddr,pageAddr,&orgPage);
+		}
+
+		if (retVal != GT_OK)
+		{
+			DBG_INFO(("Reading page register failed\n"));
+			return retVal;
+		}
+
+		if(pageAddr == 22)
+			tmpData = orgPage & 0xFF00;
+		else
+			tmpData = orgPage & 0xFFC0;
+		tmpData |= pageNum;
+
+		if (usePPU)
+		{
+			if((retVal = phyRegWritePPUEn(dev,phyAddr,pageAddr,tmpData)) == GT_OK)
+			{
+				retVal = phyRegReadPPUEn (dev,phyAddr,regAddr,data);
+
+				DBG_INFO(("Read from phy(%d) register: smiAddr 0x%x, pageNum 0x%x, regAddr 0x%x\n",
+							portNum,phyAddr,pageNum,regAddr));
+			}
+		}
+		else
+		{
+			if((retVal = miiSmiIfWriteRegister(dev,phyAddr,pageAddr,tmpData)) == GT_OK)
+			{
+				retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,data);
+
+				DBG_INFO(("Read from phy(%d) register: smiAddr 0x%x, pageNum 0x%x, regAddr 0x%x\n",
+							portNum,phyAddr,pageNum,regAddr));
+			}
+		}
+	}
+
+	if(orgPPU && (!usePPU))
+	{
+		if((retPPU=hwWritePPU(dev, orgPPU)) != GT_OK)
+		{
+			return retPPU;
+		}
+	}
+
+	return retVal;
+
+}
+
+
+static GT_STATUS coreWritePagedPhyReg
+(
+	IN GT_QD_DEV *dev,
+	IN  GT_U8    portNum,
+	IN  GT_U8    pageNum,
+	IN  GT_U8    regAddr,
+	IN  GT_U32	 anyPage,
+	IN  GT_U16   data
+)
+{
+	GT_U8   		phyAddr,pageAddr;
+	GT_STATUS   retVal, retPPU;
+	GT_U16		orgPPU, tmpData, orgPage;
+	GT_BOOL		usePPU = GT_FALSE;
+
+	phyAddr = CALC_SMI_DEV_ADDR(dev, portNum, PHY_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	orgPPU = 0;
+
+	if(IS_IN_DEV_GROUP(dev,DEV_PPU_READ_ONLY))
+	{
+		if((IS_IN_DEV_GROUP(dev,DEV_PPU_SERDES_ACCESS_RES)) && (dev->validSerdesVec && (1<<phyAddr)))
+		{
+			if((retPPU=hwReadPPU(dev, &orgPPU)) != GT_OK)
+			{
+				return retPPU;
+			}
+
+			if(orgPPU)
+			{
+				/* Disable PPU so that External Phy can be accessible */
+				if((retPPU=hwWritePPU(dev, 0)) != GT_OK)
+				{
+					return retPPU;
+				}
+			}
+		}
+		else
+			usePPU = GT_TRUE;
+	}
+	else if(IS_IN_DEV_GROUP(dev,DEV_EXTERNAL_PHY))
+	{
+		if((retPPU=hwReadPPU(dev, &orgPPU)) != GT_OK)
+		{
+			return retPPU;
+		}
+
+		if(orgPPU)
+		{
+			if(IS_IN_DEV_GROUP(dev,DEV_PPU_PHY_ACCESS))
+			{
+				if(IS_IN_DEV_GROUP(dev,DEV_PPU_PHY_ACCESS_RES))
+				{
+					if(dev->revision != 0)
+						usePPU = GT_TRUE;
+				}
+				else
+				{
+				 	usePPU = GT_TRUE;
+				}
+			}
+
+			/* Disable PPU so that External Phy can be accessible */
+			if (!usePPU)
+			{
+				if((retPPU=hwWritePPU(dev, 0)) != GT_OK)
+				{
+					return retPPU;
+				}
+			}
+		}
+	}
+
+	DBG_INFO(("Write to phy(%d) register: smiAddr 0x%x, pageNum 0x%x, regAddr 0x%x\n",
+				portNum,phyAddr,pageNum,regAddr));
+	DBG_INFO(("data 0x%x.\n",data));
+
+	if(anyPage & (1 << regAddr))
+	{
+		if (usePPU)
+		{
+			retVal = phyRegWritePPUEn (dev,phyAddr,regAddr,data);
+		}
+		else
+		{
+			retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,data);
+		}
+	}
+	else
+	{
+	    pageAddr = GT_GET_PAGE_ADDR(regAddr);
+
+		if (usePPU)
+		{
+			retVal = phyRegReadPPUEn (dev,phyAddr,regAddr,&orgPage);
+		}
+		else
+		{
+			retVal = miiSmiIfReadRegister(dev,phyAddr,pageAddr,&orgPage);
+		}
+
+		if (retVal != GT_OK)
+		{
+			DBG_INFO(("Reading page register failed\n"));
+			return retVal;
+		}
+
+		if(pageAddr == 22)
+			tmpData = orgPage & 0xFF00;
+		else
+			tmpData = orgPage & 0xFFC0;
+		tmpData |= pageNum;
+
+		if (usePPU)
+		{
+			if((retVal = phyRegWritePPUEn(dev,phyAddr,pageAddr,tmpData)) == GT_OK)
+			{
+				retVal = phyRegWritePPUEn(dev,phyAddr,regAddr,data);
+			}
+		}
+		else
+		{
+			if((retVal = miiSmiIfWriteRegister(dev,phyAddr,pageAddr,tmpData)) == GT_OK)
+			{
+				retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,data);
+			}
+		}
+	}
+
+	if(orgPPU && (!usePPU))
+	{
+		if((retPPU=hwWritePPU(dev, orgPPU)) != GT_OK)
+		{
+			return retPPU;
+		}
+	}
+
+	return retVal;
+}
+
+
+/*****************************************************************************
+* phyRegReadPPUEn
+*
+* DESCRIPTION:
+*       This function reads phy register data when PPU is enabled.
+*
+* INPUTS:
+*       phyAddr     - The PHY address to be read.
+*       regAddr     - The register address to read.
+*       value       - The storage where register date to be saved.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_TRUE   - on success
+*       GT_FALSE  - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+static GT_STATUS phyRegReadPPUEn (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int regAddr,
+                        unsigned short* value)
+{
+	volatile unsigned int timeOut; /* in 100MS units */
+	volatile int i;
+	GT_U16 smiReg;
+
+	DBG_INFO(("Read Phy register while PPU Enabled\n"));
+
+	/* first check that it is not busy */
+    if(phyReadGlobal2Reg(dev,QD_REG_SMI_PHY_CMD, &smiReg) != GT_OK)
+    {
+		DBG_INFO(("Reading Phy register Failed\n"));
+        return GT_FAIL;
+    }
+    timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
+
+    if(smiReg & QD_SMI_BUSY) 
+    {
+        for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
+        do 
+        {
+            if(timeOut-- < 1 ) 
+            {
+				DBG_INFO(("Reading Phy register Timed Out\n"));
+    	        return GT_FAIL;
+    	    }
+		    if(phyReadGlobal2Reg(dev,QD_REG_SMI_PHY_CMD, &smiReg) != GT_OK)
+		    {
+				DBG_INFO(("Reading Phy register Failed\n"));
+		        return GT_FAIL;
+		    }
+        } while (smiReg & QD_SMI_BUSY);
+    }
+
+    smiReg =  QD_SMI_BUSY | (phyAddr << QD_SMI_DEV_ADDR_BIT) | (QD_SMI_READ << QD_SMI_OP_BIT) | 
+    		(regAddr << QD_SMI_REG_ADDR_BIT) | (QD_SMI_CLAUSE22 << QD_SMI_MODE_BIT);
+
+    if(phyWriteGlobal2Reg(dev,QD_REG_SMI_PHY_CMD, smiReg) != GT_OK)
+    {
+        return GT_FAIL;
+    }
+    timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
+    if(phyReadGlobal2Reg(dev,QD_REG_SMI_PHY_CMD, &smiReg) != GT_OK)
+    {
+        return GT_FAIL;
+    }
+
+    if(smiReg & QD_SMI_BUSY) 
+    {
+        for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
+		do 
+		{
+            if(timeOut-- < 1 ) 
+            {
+				DBG_INFO(("Reading Phy register Timed Out\n"));
+    	        return GT_FALSE;
+    	    }
+		    if(phyReadGlobal2Reg(dev,QD_REG_SMI_PHY_CMD, &smiReg) != GT_OK)
+		    {
+				DBG_INFO(("Reading Phy register Failed\n"));
+		        return GT_FAIL;
+		    }
+        } while (smiReg & QD_SMI_BUSY);
+	}
+    if(phyReadGlobal2Reg(dev,QD_REG_SMI_PHY_DATA, &smiReg) != GT_OK)
+    {
+		DBG_INFO(("Reading Phy register Failed\n"));
+        return GT_FAIL;
+    }
+	*value = (unsigned short)smiReg;
+    
+	return GT_OK;
+}
+
+/*****************************************************************************
+* phyRegWritePPUEn
+*
+* DESCRIPTION:
+*       This function writes data to a phy register when PPU is enabled.
+*
+* INPUTS:
+*       phyAddr     - The PHY address to be read.
+*       regAddr     - The register address to read.
+*       value       - The data to be written into the register.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_TRUE   - on success
+*       GT_FALSE  - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+
+static GT_STATUS phyRegWritePPUEn (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int regAddr,
+                       unsigned short value)
+{
+	volatile unsigned int timeOut; /* in 100MS units */
+	volatile int i;
+	GT_U16 smiReg;
+
+	DBG_INFO(("Writing Phy register while PPU Enabled\n"));
+
+	/* first check that it is not busy */
+    if(phyReadGlobal2Reg(dev,QD_REG_SMI_PHY_CMD, &smiReg) != GT_OK)
+    {
+		DBG_INFO(("Reading Phy register Failed\n"));
+        return GT_FAIL;
+    }
+    timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
+
+    if(smiReg & QD_SMI_BUSY) 
+    {
+        for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
+        do 
+        {
+            if(timeOut-- < 1 ) 
+            {
+				DBG_INFO(("Writing Phy register Timed Out\n"));
+    	        return GT_FALSE;
+    	    }
+		    if(phyReadGlobal2Reg(dev,QD_REG_SMI_PHY_CMD, &smiReg) != GT_OK)
+		    {
+				DBG_INFO(("Writing Phy register Failed\n"));
+		        return GT_FAIL;
+		    }
+        } while (smiReg & QD_SMI_BUSY);
+    }
+
+    if(phyWriteGlobal2Reg(dev,QD_REG_SMI_PHY_DATA, value) != GT_OK)
+    {
+		DBG_INFO(("Writing Phy Data register Failed\n"));
+        return GT_FAIL;
+    }
+    smiReg = QD_SMI_BUSY | (phyAddr << QD_SMI_DEV_ADDR_BIT) | (QD_SMI_WRITE << QD_SMI_OP_BIT) | 
+			(regAddr << QD_SMI_REG_ADDR_BIT) | (QD_SMI_CLAUSE22 << QD_SMI_MODE_BIT);
+
+    if(phyWriteGlobal2Reg(dev,QD_REG_SMI_PHY_CMD, smiReg) != GT_OK)
+    {
+		DBG_INFO(("Writing Phy Command register Failed\n"));
+        return GT_FAIL;
+    }
+
+    return GT_OK;
+}
+
+
+static GT_STATUS phyReadGlobal2Reg
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    OUT GT_U16   *data
+)
+{
+    GT_U8       phyAddr;
+    GT_STATUS   retVal;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    retVal = miiSmiIfReadRegister(dev,phyAddr,regAddr,data);
+
+    DBG_INFO(("read from global 2 register: phyAddr 0x%x, regAddr 0x%x, ",
+              phyAddr,regAddr));
+    DBG_INFO(("data 0x%x.\n",*data));
+    return retVal;
+}
+
+
+static GT_STATUS phyWriteGlobal2Reg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8    regAddr,
+    IN  GT_U16   data
+)
+{
+    GT_U8   phyAddr;
+    GT_STATUS   retVal;
+
+    phyAddr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS);
+	if (phyAddr == 0xFF)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    retVal = miiSmiIfWriteRegister(dev,phyAddr,regAddr,data);
+
+    return retVal;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/makefile b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/makefile
new file mode 100755
index 0000000..f6a5efc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/driver/makefile
@@ -0,0 +1,32 @@
+# Source files in this directory
+CSOURCES	= gtDrvConfig.c gtDrvEvents.c gtHwCntl.c
+ASOURCES	=
+
+# Include common variable definitions
+ifeq ($(OS_RUN),VXWORKS)
+include $(TOOL_DIR)\make.defs
+endif
+ifeq ($(OS_RUN),WIN32)
+include $(TOOL_DIR)\makewce.defs
+endif
+ifeq ($(OS_RUN),LINUX)
+include $(TOOL_DIR)/makelnx.defs
+endif
+
+# Add in extra stuffs
+EXTRA_INCLUDE	+=
+EXTRA_DEFINE	+=
+ADDED_CFLAGS	+=
+
+# Include common build rules
+ifeq ($(OS_RUN),VXWORKS)
+include $(TOOL_DIR)\make.rules
+endif
+ifeq ($(OS_RUN),WIN32)
+include $(TOOL_DIR)\makewce.rules
+endif
+ifeq ($(OS_RUN),LINUX)
+include $(TOOL_DIR)/makelnx.rules
+endif
+
+# end of file
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/makefile b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/makefile
new file mode 100755
index 0000000..af07875
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/makefile
@@ -0,0 +1,96 @@
+# makefile - build main object file
+#
+# modification history
+# --------------------
+# 04-15-02,mj	created
+#
+#######################################################################
+
+TARGET = $(PROJ_NAME)
+
+ifeq ($(OS_RUN),VXWORKS)
+WORK_TO_DO = $(PROJ_NAME).o
+
+# Include common variable definitions
+include $(TOOL_DIR)\make.defs
+endif
+
+ifeq ($(OS_RUN),LINUX)
+WORK_TO_DO = $(PROJ_NAME).o
+
+# Include common variable definitions
+include $(TOOL_DIR)/makelnx.defs
+endif
+
+exe : $(WORK_TO_DO)
+
+.PHONY : exe
+
+vpath %.o    $(OBJDIR)
+vpath %.lib  $(OBJDIR)
+
+MAINDRV_PATH = $(SRC_BASE_PATH)
+
+OBJECTS_LIST = $(MAINDRV_PATH)/driver/$(OBJDIR)/driver.o \
+               $(MAINDRV_PATH)/msapi/$(OBJDIR)/msapi.o \
+               $(MAINDRV_PATH)/platform/$(OBJDIR)/platform.o
+
+OBJECTS = $(OBJECTS_LIST)
+
+OBJDIRS	= $(subst /,\,$(dir $(OBJECTS)))
+LIBDIRS	= $(subst /,\,$(LIB_DIR))
+
+OBJDIRS_/ = $(subst \,/,$(OBJDIRS))
+LIBDIRS_/ = $(subst \,/,$(LIBDIRS))
+
+ifeq ($(OS_RUN),VXWORKS)
+$(PROJ_NAME).o : $(OBJECTS) $(MAD_OBJ)
+	@ $(ECHO) '------------'
+	@ $(ECHO) 'Building $@'
+	$(LD) $(LDFLAGS) -Map $(LIB_DIR)/$(PROJ_NAME).map -o $(LIB_DIR)/$(PROJ_NAME).o $(OBJECTS) $(MAD_OBJ)
+
+$(OBJECTS) : FORCE
+	@($(CD) $(subst /,\,$(dir $(@D)))) && $(MAKE)
+
+$(MAD_OBJ) : FORCE
+	$(MAKE) -C $(MAD_ROOT)/src
+
+endif
+
+ifeq ($(OS_RUN),LINUX)
+$(PROJ_NAME).o : $(OBJECTS) $(MAD_OBJ)
+	@ $(ECHO) '------------'
+	@ $(ECHO) 'Building $@'
+	$(LD) $(LDFLAGS) -Map $(LIB_DIR)/$(PROJ_NAME).map -o $(LIB_DIR)/$(PROJ_NAME).o $(OBJECTS) $(MAD_OBJ)
+
+$(OBJECTS) : FORCE
+	@cd $(dir $(@D)); $(MAKE)
+
+$(MAD_OBJ) : FORCE
+	$(MAKE) -C $(MAD_ROOT)/src
+
+endif
+
+FORCE :
+
+.PHONY : clean
+ifeq ($(OS_RUN),VXWORKS)
+clean :
+	@for %x in ($(OBJDIRS)) do \
+	    @($(CD) %x..) && $(MAKE) clean
+	- ($(CD) $(LIBDIRS)) && $(RM) $(PROJ_NAME).o
+	- ($(CD) $(LIBDIRS)) && $(RM) $(PROJ_NAME).map
+	@if exist $(MAD_ROOT) $(MAKE) -C $(MAD_ROOT)/src clean
+endif
+
+ifeq ($(OS_RUN),LINUX)
+clean :
+	@for i in $(OBJDIRS_/); do	\
+		cd $$i..; $(MAKE) clean;	\
+	done
+	@cd $(LIBDIRS_/); $(RM) $(PROJ_NAME).o
+	@cd $(LIBDIRS_/); $(RM) $(PROJ_NAME).map
+	@if exist $(MAD_ROOT) $(MAKE) -C $(MAD_ROOT)/src clean
+endif
+
+#end of file
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtAdvVct.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtAdvVct.c
new file mode 100755
index 0000000..0b73422
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtAdvVct.c
@@ -0,0 +1,1855 @@
+#include <Copyright.h>

+/*******************************************************************************

+* gtAdvVct.c

+*

+* DESCRIPTION:

+*       API for Marvell Virtual Cable Tester.

+*

+* DEPENDENCIES:

+*       None.

+*

+* FILE REVISION NUMBER:

+*       $Revision: 1 $

+*******************************************************************************/

+#include <msApi.h>

+#include <gtVct.h>

+#include <gtDrvConfig.h>

+#include <gtDrvSwRegs.h>

+#include <gtHwCntl.h>

+#include <gtSem.h>

+

+#define GT_LOOKUP_TABLE_ENTRY  128  /* 73 */

+

+#define GT_ADV_VCT_ACCEPTABLE_SHORT_CABLE  11

+

+static  GT_U8 tbl_1181[GT_LOOKUP_TABLE_ENTRY] = 

+                    {  2,  4,  8, 14, 18, 20, 25, 30, 33, 36,

+                      39, 42, 46, 48, 51, 54, 57, 59, 62, 64,

+                      66, 69, 71, 73, 75, 77, 80, 81, 83, 85,

+                      87, 88, 90, 93, 95, 97, 98,100,101,103,

+                     104,106,106,107,109,110,111,113,114,115,

+                     116,118,119,120,121,122,124,125,126,127,

+                     128,129,130,131,132,133,134,135,136,137,

+                     138,139,140};

+

+static  GT_U8 tbl_1111[GT_LOOKUP_TABLE_ENTRY] = 

+                    {  0,  2,  4, 5, 6, 9, 13, 17, 20, 23,

+                      27, 30, 33, 35, 38, 41, 43, 46, 48, 51,

+                      53, 55, 58, 60, 62, 64, 66, 68, 70, 72,

+                      73, 75, 77, 79, 80, 82, 84, 85, 87, 88,

+                      90, 91, 93, 94, 96, 97, 98,100,101,102,

+                     104,105,106,107,109,110,111,112,113,114,

+                     116,117,118,119,120,121,122,123,124,125,

+                     126,127,128,129,130,131,132,133,134,134};

+

+static  GT_U8 tbl_1112[GT_LOOKUP_TABLE_ENTRY] =   /* from 17*/

+                    {  0,  4,  8, 11, 14, 18, 21, 24, 28, 31, 

+					  34, 37, 39, 42, 44, 47, 49, 52, 54, 56, 

+					  58, 60, 62, 64, 66, 68, 70, 72, 74, 75, 

+					  77, 79, 80, 82, 83, 85, 87, 88, 89, 91, 

+					  92, 94, 95, 96, 98, 99,100,101,103,104,

+					  105,106,107,108,109,111,112,113,114,115,

+					  116,117,118,119,120,121,122,123,124,124,

+					  125,126,127,128,129,130,131,131,132,133,

+					  134,135,135,136,137,138,139,139,140,141,

+					  142,142,143,144,144,145,146,147,147,148};

+

+static  GT_U8 tbl_1116[GT_LOOKUP_TABLE_ENTRY] =   /* from 16*/

+                    {  2,  4,  8, 14, 18, 20, 25, 30, 33, 36, 

+					  39, 42, 46, 48, 51, 54, 57, 59, 62, 64, 

+					  66, 69, 71, 73, 75, 77, 80, 81, 83, 85, 

+					  87, 88, 90, 93, 95, 97, 98, 100, 101, 103, 

+					  104,106,106,107,109,110,111,113,114,115,

+					  116,118,119,120,121,122,124,125,126,127,

+					  128,129,130,131,132,133,134,135,136,137,

+					  138,139,140};

+

+static  GT_U8 tbl_1240[GT_LOOKUP_TABLE_ENTRY] = 

+                    {  1,  2,  5, 10, 13, 15, 18, 22, 26, 30, 
+                      33, 35, 38, 40, 43, 45, 48, 51, 53, 55, 
+                      58, 60, 63, 65, 68, 69, 70, 71, 73, 75, 
+                      77, 79, 80, 81, 82, 83, 85, 87, 88, 90, 
+                      91, 92, 93, 95, 97, 98,100,101,102,103,
+                     105,106,107,108,109,110,111,112,113,114,
+                     115,116,117,118,119,120,121,122,123,124,
+                     125,126,127,128,129,130};

+

+

+/*******************************************************************************

+* getDetailedAdvVCTResult

+*

+* DESCRIPTION:

+*		This routine differenciate Open/Short from Impedance mismatch.

+*

+* INPUTS:

+*		amp - amplitude

+*		len - distance to fault

+*		vctResult - test result 

+*					(Impedance mismatch, either > 115 ohms, or < 85 ohms)

+*

+* OUTPUTS:

+*

+* RETURNS:

+*       GT_ADV_VCT_STATUS

+*

+* COMMENTS:

+*       This routine assumes test result is not normal nor cross pair short.

+*

+*******************************************************************************/

+static

+GT_ADV_VCT_STATUS getDetailedAdvVCTResult

+(

+	IN  GT_U32  devType,

+	IN  GT_U32  amp,

+	IN  GT_U32  len,

+	IN  GT_ADV_VCT_STATUS result

+)

+{

+	GT_ADV_VCT_STATUS vctResult;

+	GT_BOOL    update = GT_FALSE;

+

+	DBG_INFO(("getDetailedAdvVCTResult Called.\n"));

+
+	if (devType == GT_PHY_ADV_VCT_TYPE2)

+	{

+		if(len < 10)

+		{

+			if(amp > 54)  /* 90 x 0.6 */

+				update = GT_TRUE;

+		}

+		else if(len < 50)

+		{

+			if(amp > 42) /* 70 x 0.6 */

+				update = GT_TRUE;

+		}

+		else if(len < 110)

+		{

+			if(amp > 30)  /* 50 x 0.6 */

+				update = GT_TRUE;

+		}

+		else if(len < 140)

+		{

+			if(amp > 24)  /* 40 x 0.6 */

+				update = GT_TRUE;

+		}

+		else

+		{

+			if(amp > 18) /* 30 x 0.6 */

+				update = GT_TRUE;

+		}

+	}

+	else

+	{

+		if(len < 10)

+		{

+			if(amp > 90)  

+				update = GT_TRUE;

+		}

+		else if(len < 50)

+		{

+			if(amp > 70) 

+				update = GT_TRUE;

+		}

+		else if(len < 110)

+		{

+			if(amp > 50)  

+				update = GT_TRUE;

+		}

+		else if(len < 140)

+		{

+			if(amp > 40)  

+				update = GT_TRUE;

+		}

+		else

+		{

+			if(amp > 30) 

+				update = GT_TRUE;

+		}

+	}

+

+

+	switch (result)

+	{

+		case GT_ADV_VCT_IMP_GREATER_THAN_115:

+				if(update)

+					vctResult = GT_ADV_VCT_OPEN;

+				else

+					vctResult = result;

+				break;

+		case GT_ADV_VCT_IMP_LESS_THAN_85:

+				if(update)

+					vctResult = GT_ADV_VCT_SHORT;

+				else

+					vctResult = result;

+				break;

+		default:

+				vctResult = result;

+				break;

+	}

+

+	return vctResult;

+}

+

+/*******************************************************************************

+* analizeAdvVCTResult

+*

+* DESCRIPTION:

+*		This routine analize the Advanced VCT result.

+*

+* INPUTS:

+*		channel - channel number where test was run

+*		crossChannelReg - register values after the test is completed

+*		mode    - use formula for normal cable case

+*

+* OUTPUTS:

+*		cableStatus - analized test result.

+*

+* RETURNS:

+*		-1, or distance to fault

+*

+* COMMENTS:

+*		None.

+*

+*******************************************************************************/

+static

+GT_16 analizeAdvVCTNoCrosspairResult

+(

+	IN  GT_U32  devType,

+	IN  int     channel, 

+	IN  GT_U16 *crossChannelReg, 

+	IN  GT_BOOL isShort,

+	OUT GT_ADV_CABLE_STATUS *cableStatus

+)

+{

+	int len;

+	GT_16 dist2fault;

+	GT_ADV_VCT_STATUS vctResult = GT_ADV_VCT_NORMAL;

+

+	DBG_INFO(("analizeAdvVCTNoCrosspairResult Called.\n"));

+	DBG_INFO(("analizeAdvVCTNoCrosspairResult chan %d reg data %x\n", channel, crossChannelReg[channel]));

+

+	dist2fault = -1;

+

+	/* check if test is failed */

+	if(IS_VCT_FAILED(crossChannelReg[channel]))

+	{

+		cableStatus->cableStatus[channel] = GT_ADV_VCT_FAIL;

+		return dist2fault;

+	}

+

+	/* Check if fault detected */

+	if(IS_ZERO_AMPLITUDE(crossChannelReg[channel]))

+	{

+		cableStatus->cableStatus[channel] = GT_ADV_VCT_NORMAL;

+		return dist2fault;

+	}

+

+	/* find out test result by reading Amplitude */

+	if(IS_POSITIVE_AMPLITUDE(crossChannelReg[channel]))

+	{

+		vctResult = GT_ADV_VCT_IMP_GREATER_THAN_115;

+	}

+	else

+	{

+		vctResult = GT_ADV_VCT_IMP_LESS_THAN_85;

+	}

+

+	/* 

+	 * now, calculate the distance for GT_ADV_VCT_IMP_GREATER_THAN_115 and

+	 * GT_ADV_VCT_IMP_LESS_THAN_85

+	 */

+	switch (vctResult)

+	{

+		case GT_ADV_VCT_IMP_GREATER_THAN_115:

+		case GT_ADV_VCT_IMP_LESS_THAN_85:

+			if(!isShort)

+			{

+				len = (int)GT_ADV_VCT_CALC(crossChannelReg[channel] & 0xFF);

+			}

+			else

+			{

+				len = (int)GT_ADV_VCT_CALC_SHORT(crossChannelReg[channel] & 0xFF);

+			}

+			DBG_INFO(("@@@@ no cross len %d\n", len));

+
+			if (len < 0)

+				len = 0;

+			cableStatus->u[channel].dist2fault = (GT_16)len;

+			vctResult = getDetailedAdvVCTResult(
+									devType,
+									GET_AMPLITUDE(crossChannelReg[channel]),

+									len,

+									vctResult);

+			dist2fault = (GT_16)len;

+			break;

+		default:

+			break;

+	}

+

+	cableStatus->cableStatus[channel] = vctResult;

+

+	return dist2fault;

+}

+

+

+static

+GT_16 analizeAdvVCTResult

+(

+	IN  GT_U32  devType,

+	IN  int     channel, 

+	IN  GT_U16 *crossChannelReg, 

+	IN  GT_BOOL isShort,

+	OUT GT_ADV_CABLE_STATUS *cableStatus

+)

+{

+	int i, len;

+	GT_16 dist2fault;

+	GT_ADV_VCT_STATUS vctResult = GT_ADV_VCT_NORMAL;

+

+	DBG_INFO(("analizeAdvVCTResult(Crosspair) chan %d reg data %x\n", channel, crossChannelReg[channel]));

+	DBG_INFO(("analizeAdvVCTResult Called.\n"));

+

+	dist2fault = -1;

+

+	/* check if test is failed */

+	for (i=0; i<GT_MDI_PAIR_NUM; i++)

+	{

+		if(IS_VCT_FAILED(crossChannelReg[i]))

+		{

+			cableStatus->cableStatus[channel] = GT_ADV_VCT_FAIL;

+			return dist2fault;

+		}

+	}

+

+	/* find out test result by reading Amplitude */

+	for (i=0; i<GT_MDI_PAIR_NUM; i++)

+	{

+		if (i == channel)

+		{

+			if(!IS_ZERO_AMPLITUDE(crossChannelReg[i]))

+			{

+				if(IS_POSITIVE_AMPLITUDE(crossChannelReg[i]))

+				{

+					vctResult = GT_ADV_VCT_IMP_GREATER_THAN_115;

+				}

+				else

+				{

+					vctResult = GT_ADV_VCT_IMP_LESS_THAN_85;

+				}

+			}

+			continue;

+		}

+

+		if(IS_ZERO_AMPLITUDE(crossChannelReg[i]))

+			continue;

+

+		vctResult = GT_ADV_VCT_CROSS_PAIR_SHORT;

+		break;

+	}

+

+	/* if it is cross pair short, check the distance for each channel */

+	if(vctResult == GT_ADV_VCT_CROSS_PAIR_SHORT)

+	{

+		cableStatus->cableStatus[channel] = GT_ADV_VCT_CROSS_PAIR_SHORT;

+		for (i=0; i<GT_MDI_PAIR_NUM; i++)

+		{

+			if(IS_ZERO_AMPLITUDE(crossChannelReg[i]))

+			{

+				cableStatus->u[channel].crossShort.channel[i] = GT_FALSE;

+				cableStatus->u[channel].crossShort.dist2fault[i] = 0;

+				continue;

+			}

+            

+			cableStatus->u[channel].crossShort.channel[i] = GT_TRUE;

+			if(!isShort)

+				len = (int)GT_ADV_VCT_CALC(crossChannelReg[i] & 0xFF);

+			else

+				len = (int)GT_ADV_VCT_CALC_SHORT(crossChannelReg[i] & 0xFF);

+			DBG_INFO(("@@@@ len %d\n", len));

+
+			if (len < 0)

+				len = 0;

+			cableStatus->u[channel].crossShort.dist2fault[i] = (GT_16)len;

+			dist2fault = (GT_16)len;

+		}

+

+		return dist2fault;

+	}

+

+	/* 

+	 * now, calculate the distance for GT_ADV_VCT_IMP_GREATER_THAN_115 and

+	 * GT_ADV_VCT_IMP_LESS_THAN_85

+	 */

+	switch (vctResult)

+	{

+		case GT_ADV_VCT_IMP_GREATER_THAN_115:

+		case GT_ADV_VCT_IMP_LESS_THAN_85:

+			if(isShort)

+				len = (int)GT_ADV_VCT_CALC(crossChannelReg[channel] & 0xFF);

+			else

+				len = (int)GT_ADV_VCT_CALC_SHORT(crossChannelReg[channel] & 0xFF);

+			if (len < 0)

+				len = 0;

+			cableStatus->u[channel].dist2fault = (GT_16)len;

+			vctResult = getDetailedAdvVCTResult(

+									devType,

+									GET_AMPLITUDE(crossChannelReg[channel]),

+									len,

+									vctResult);

+			dist2fault = (GT_16)len;

+			break;

+		default:

+			break;

+	}

+

+	cableStatus->cableStatus[channel] = vctResult;

+

+	return dist2fault;

+}

+

+

+/*******************************************************************************

+* runAdvCableTest_1181

+*

+* DESCRIPTION:

+*		This routine performs the advanced virtual cable test for the PHY with

+*		multiple page mode and returns the the status per MDIP/N.

+*

+* INPUTS:

+*		port - logical port number.

+*		mode - GT_TRUE, if short cable detect is required

+*			   GT_FALSE, otherwise

+*

+* OUTPUTS:

+*		cableStatus - the port copper cable status.

+*		tooShort    - if known distance to fault is too short

+*

+* RETURNS:

+*		GT_OK   - on success

+*		GT_FAIL - on error

+*

+* COMMENTS:

+*		None.

+*

+*******************************************************************************/

+static 

+GT_STATUS runAdvCableTest_1181

+(	

+	IN  GT_QD_DEV       *dev,

+	IN  GT_U8           hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+	IN  GT_BOOL         mode,

+	OUT GT_ADV_CABLE_STATUS *cableStatus,

+	OUT GT_BOOL         *tooShort

+)

+{

+	GT_STATUS retVal;

+	GT_U16 u16Data;

+	GT_U16 crossChannelReg[GT_MDI_PAIR_NUM];

+	int i,j;

+	GT_16  dist2fault;

+

+	VCT_REGISTER regList[GT_MDI_PAIR_NUM][GT_MDI_PAIR_NUM] = {

+							{{8,16},{8,17},{8,18},{8,19}},  /* channel 0 */

+							{{8,24},{8,25},{8,26},{8,27}},  /* channel 1 */

+							{{9,16},{9,17},{9,18},{9,19}},  /* channel 2 */

+							{{9,24},{9,25},{9,26},{9,27}}   /* channel 3 */

+							};

+

+	DBG_INFO(("runAdvCableTest_1181 Called.\n"));

+

+	if (mode)

+		*tooShort = GT_FALSE;

+

+	/* 

+	 * start Advanced Virtual Cable Tester

+	 */

+	if((retVal = hwSetPagedPhyRegField(

+						dev,hwPort,8,QD_REG_ADV_VCT_CONTROL_8,15,1,phyInfo->anyPage,1)) != GT_OK)

+	{

+		DBG_INFO(("Writing to paged phy reg failed.\n"));

+		return retVal;

+	}

+

+	/* 

+	 * loop until test completion and result is valid

+	 */

+	do

+	{

+		if((retVal = hwReadPagedPhyReg(

+							dev,hwPort,8,QD_REG_ADV_VCT_CONTROL_8,phyInfo->anyPage,&u16Data)) != GT_OK)

+		{

+			DBG_INFO(("Reading from paged phy reg failed.\n"));

+			return retVal;

+		}

+	} while(u16Data & 0x8000);

+

+	DBG_INFO(("Page 8 of Reg20 after test : %0#x.\n", u16Data));

+

+	for (i=0; i<GT_MDI_PAIR_NUM; i++)

+	{

+		/*

+		 * read the test result for the cross pair against selected MDI Pair

+		 */

+		for (j=0; j<GT_MDI_PAIR_NUM; j++)

+		{

+			if((retVal = hwReadPagedPhyReg(

+								dev,hwPort,

+								regList[i][j].page,

+								regList[i][j].regOffset,
+								phyInfo->anyPage,

+								&crossChannelReg[j])) != GT_OK)

+			{

+				DBG_INFO(("Reading from paged phy reg failed.\n"));

+				return retVal;

+			}

+		}

+

+		/*

+		 * analyze the test result for RX Pair

+		 */

+		dist2fault = analizeAdvVCTResult(phyInfo->vctType, i, crossChannelReg, mode, cableStatus);

+

+		if(mode)

+		{

+			if ((dist2fault>=0) && (dist2fault<GT_ADV_VCT_ACCEPTABLE_SHORT_CABLE))

+			{

+				DBG_INFO(("Distance to Fault is too Short. So, rerun after changing pulse width\n"));

+				*tooShort = GT_TRUE;

+				break;

+			}

+		}

+	}

+

+	return GT_OK;

+}

+

+
+
+/*******************************************************************************

+* getAdvCableStatus_1181

+*

+* DESCRIPTION:

+*		This routine performs the virtual cable test for the PHY with

+*		multiple page mode and returns the the status per MDIP/N.

+*

+* INPUTS:

+*		port - logical port number.

+*		mode - advance VCT mode (either First Peak or Maximum Peak)

+*

+* OUTPUTS:

+*		cableStatus - the port copper cable status.

+*

+* RETURNS:

+*		GT_OK   - on success

+*		GT_FAIL - on error

+*

+* COMMENTS:

+*		None.

+*

+*******************************************************************************/

+static 

+GT_STATUS getAdvCableStatus_1181

+(	

+	IN  GT_QD_DEV          *dev,

+	IN  GT_U8           hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+	IN  GT_ADV_VCT_MODE mode,

+	OUT GT_ADV_CABLE_STATUS *cableStatus

+)

+{

+	GT_STATUS retVal;

+	GT_U16 orgPulse, u16Data;

+	GT_BOOL flag, tooShort;

+

+	flag = GT_TRUE;

+

+	/*

+	 * set Adv VCT Mode

+	 */

+	switch (mode.mode)

+	{

+		case GT_ADV_VCT_FIRST_PEAK:

+			break;

+		case GT_ADV_VCT_MAX_PEAK:

+			break;

+		default:

+			DBG_INFO(("Unknown Advanced VCT Mode.\n"));

+			return GT_BAD_PARAM;

+	}

+

+	u16Data = (mode.mode<<6) | (mode.peakDetHyst) | (mode.sampleAvg<<8);

+	if((retVal = hwSetPagedPhyRegField(

+						dev,hwPort,8,QD_REG_ADV_VCT_CONTROL_8,0,11,phyInfo->anyPage,u16Data)) != GT_OK)

+	{

+		DBG_INFO(("Writing to paged phy reg failed.\n"));

+		return retVal;

+	}

+

+	if (flag)

+	{

+		/* save original Pulse Width */

+		if((retVal = hwGetPagedPhyRegField(

+							dev,hwPort,9,23,10,2,phyInfo->anyPage,&orgPulse)) != GT_OK)

+		{

+			DBG_INFO(("Reading paged phy reg failed.\n"));

+			return retVal;

+		}

+

+		/* set the Pulse Width with default value */

+		if (orgPulse != 0)

+		{

+			if((retVal = hwSetPagedPhyRegField(

+								dev,hwPort,9,23,10,2,phyInfo->anyPage,0)) != GT_OK)

+			{

+				DBG_INFO(("Writing to paged phy reg failed.\n"));

+				return retVal;

+			}

+		}

+	}

+

+	if((retVal=runAdvCableTest_1181(dev,hwPort,phyInfo,flag,cableStatus,&tooShort)) != GT_OK)

+	{

+		DBG_INFO(("Running advanced VCT failed.\n"));

+		return retVal;

+	}

+

+	if (flag)

+	{

+		if(tooShort)

+		{

+			/* set the Pulse Width with minimum width */

+			if((retVal = hwSetPagedPhyRegField(

+								dev,hwPort,9,23,10,2,phyInfo->anyPage,3)) != GT_OK)

+			{

+				DBG_INFO(("Writing to paged phy reg failed.\n"));

+				return retVal;

+			}

+

+			/* run the Adv VCT again */

+			if((retVal=runAdvCableTest_1181(dev,hwPort,phyInfo,GT_FALSE,cableStatus,&tooShort)) != GT_OK)

+			{

+				DBG_INFO(("Running advanced VCT failed.\n"));

+				return retVal;

+			}

+

+		}

+

+		/* set the Pulse Width back to the original value */

+		if((retVal = hwSetPagedPhyRegField(

+							dev,hwPort,9,23,10,2,phyInfo->anyPage,orgPulse)) != GT_OK)

+		{

+			DBG_INFO(("Writing to paged phy reg failed.\n"));

+			return retVal;

+		}

+

+	}

+

+	return GT_OK;

+}

+
+

+static 

+GT_STATUS runAdvCableTest_1116_set

+(	

+	IN  GT_QD_DEV          *dev,

+	IN  GT_U8           hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+	IN  GT_32           channel,

+	IN  GT_ADV_VCT_TRANS_CHAN_SEL		crosspair

+)

+{

+	GT_STATUS retVal;

+

+	DBG_INFO(("runAdvCableTest_1116_set Called.\n"));

+
+	/* 

+	 * start Advanced Virtual Cable Tester

+	 */

+	if((retVal = hwSetPagedPhyRegField(

+						dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,15,1,phyInfo->anyPage,1)) != GT_OK)

+	{

+		DBG_INFO(("Writing to paged phy reg failed.\n"));

+		return retVal;

+	}

+

+	return GT_OK;

+}

+

+static 

+GT_STATUS runAdvCableTest_1116_check

+(	

+	IN  GT_QD_DEV       *dev,

+	IN  GT_U8           hwPort,

+	IN	GT_PHY_INFO		*phyInfo

+)

+{

+	GT_STATUS retVal;

+	GT_U16 u16Data;

+
+	/* 

+	 * loop until test completion and result is valid

+	 */
+	do {

+		if((retVal = hwReadPagedPhyReg(

+							dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,phyInfo->anyPage,&u16Data)) != GT_OK)

+		{

+			DBG_INFO(("Reading from paged phy reg failed.\n"));

+			return retVal;

+		}
+	} while (u16Data & 0x8000);
+

+	return GT_OK;

+}

+

+static 

+GT_STATUS runAdvCableTest_1116_get

+(	

+	IN  GT_QD_DEV          *dev,

+	IN  GT_U8           hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+	IN  GT_ADV_VCT_TRANS_CHAN_SEL	crosspair,

+	IN  GT_32			channel,

+	OUT GT_ADV_CABLE_STATUS *cableStatus,

+	OUT GT_BOOL         *tooShort

+)

+{

+	GT_STATUS retVal;

+	GT_U16 u16Data;

+	GT_U16 crossChannelReg[GT_MDI_PAIR_NUM];

+	int j;

+	GT_16  dist2fault;

+	GT_BOOL         mode;

+	GT_BOOL         localTooShort[GT_MDI_PAIR_NUM];

+

+	VCT_REGISTER regList[GT_MDI_PAIR_NUM] = { {5,16},{5,17},{5,18},{5,19} };

+
+	mode = GT_TRUE;

+

+	DBG_INFO(("runAdvCableTest_1116_get Called.\n"));

+

+	if ((retVal = hwReadPagedPhyReg(

+						dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,phyInfo->anyPage,&u16Data)) != GT_OK)

+	{

+		DBG_INFO(("Reading from paged phy reg failed.\n"));

+		return retVal;

+	}

+

+	DBG_INFO(("Page 5 of Reg23 after test : %0#x.\n", u16Data));

+

+	/*

+	 * read the test result for the cross pair against selected MDI Pair

+	 */

+	for (j=0; j<GT_MDI_PAIR_NUM; j++)

+	{

+		if((retVal = hwReadPagedPhyReg(

+								dev,hwPort,

+								regList[j].page,

+								regList[j].regOffset,
+								phyInfo->anyPage,

+								&crossChannelReg[j])) != GT_OK)

+		{

+			DBG_INFO(("Reading from paged phy reg failed.\n"));

+			return retVal;

+		}

+		DBG_INFO(("@@@@@ reg channel %d is %x \n", j, crossChannelReg[j]));

+	}

+

+	/*

+	 * analyze the test result for RX Pair

+	 */

+	for (j=0; j<GT_MDI_PAIR_NUM; j++)

+	{

+		if (crosspair!=GT_ADV_VCT_TCS_NO_CROSSPAIR)

+			dist2fault = analizeAdvVCTResult(phyInfo->vctType, j, crossChannelReg, mode&(*tooShort), cableStatus);

+		else

+			dist2fault = analizeAdvVCTNoCrosspairResult(phyInfo->vctType, j, crossChannelReg, mode&(*tooShort), cableStatus);

+

+		localTooShort[j]=GT_FALSE;

+		if((mode)&&(*tooShort==GT_FALSE))

+		{

+			if ((dist2fault>=0) && (dist2fault<GT_ADV_VCT_ACCEPTABLE_SHORT_CABLE))

+			{

+				DBG_INFO(("@@@#@@@@ it is too short dist2fault %d\n", dist2fault));

+				DBG_INFO(("Distance to Fault is too Short. So, rerun after changing pulse width\n"));

+				localTooShort[j]=GT_TRUE;

+			}

+		}

+	}

+
+	/* check and decide if length is too short */

+	for (j=0; j<GT_MDI_PAIR_NUM; j++)

+	{

+		if (localTooShort[j]==GT_FALSE) break;

+	}

+

+	if (j==GT_MDI_PAIR_NUM)

+		*tooShort = GT_TRUE;

+

+	return GT_OK;

+}

+

+static 

+GT_STATUS runAdvCableTest_1116

+(	

+    IN  GT_QD_DEV          *dev,

+    IN  GT_U8           hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+    IN  GT_BOOL         mode,

+    IN  GT_ADV_VCT_TRANS_CHAN_SEL   crosspair,

+    OUT GT_ADV_CABLE_STATUS *cableStatus,

+    OUT GT_BOOL         *tooShort

+)

+{

+	GT_STATUS retVal;

+	GT_32  channel;

+

+	DBG_INFO(("runAdvCableTest_1116 Called.\n"));

+

+	if (crosspair!=GT_ADV_VCT_TCS_NO_CROSSPAIR)

+	{

+		channel = crosspair - GT_ADV_VCT_TCS_CROSSPAIR_0;

+	}

+	else

+	{

+		channel = 0;

+	}

+
+	/* Set transmit channel */

+	if((retVal=runAdvCableTest_1116_set(dev,hwPort, phyInfo,channel, crosspair)) != GT_OK) 

+	{

+		DBG_INFO(("Running advanced VCT failed.\n"));

+		return retVal;

+	}

+

+	/* 

+	 * check test completion

+	 */

+	retVal = runAdvCableTest_1116_check(dev,hwPort,phyInfo);
+	if (retVal != GT_OK)
+	{

+		DBG_INFO(("Running advanced VCT failed.\n"));

+		return retVal;

+	}
+

+	/*

+	 * read the test result for the cross pair against selected MDI Pair

+	 */

+	retVal = runAdvCableTest_1116_get(dev, hwPort, phyInfo, crosspair,

+									channel,cableStatus,(GT_BOOL *)tooShort);

+
+	if(retVal != GT_OK)

+	{

+		DBG_INFO(("Running advanced VCT get failed.\n"));

+	}

+
+	return retVal;

+}

+

+static 

+GT_STATUS getAdvCableStatus_1116

+(	

+	IN  GT_QD_DEV       *dev,

+	IN  GT_U8           hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+	IN  GT_ADV_VCT_MODE mode,

+	OUT GT_ADV_CABLE_STATUS *cableStatus

+)

+{

+	GT_STATUS retVal;

+	GT_U16 orgPulse, u16Data;

+	GT_BOOL flag, tooShort;

+	GT_ADV_VCT_TRANS_CHAN_SEL crosspair;

+

+	flag = GT_TRUE;

+	crosspair = mode.transChanSel;

+

+	/*

+	 * Check Adv VCT Mode

+	 */

+	switch (mode.mode)

+	{

+		case GT_ADV_VCT_FIRST_PEAK:

+		case GT_ADV_VCT_MAX_PEAK:

+				break;

+
+		default:

+				DBG_INFO(("Unknown ADV VCT Mode.\n"));

+				return GT_NOT_SUPPORTED;

+	}

+

+	if((retVal = hwGetPagedPhyRegField(

+							dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,0,13,phyInfo->anyPage,&u16Data)) != GT_OK)

+	{

+		DBG_INFO(("Reading paged phy reg failed.\n"));

+		return retVal;

+	}

+
+	u16Data |= ((mode.mode<<6) | (mode.transChanSel<<11));

+	if (mode.peakDetHyst) u16Data |= (mode.peakDetHyst);

+	if (mode.sampleAvg) u16Data |= (mode.sampleAvg<<8) ;

+
+	if((retVal = hwSetPagedPhyRegField(

+						dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,0,13,phyInfo->anyPage,u16Data)) != GT_OK)

+	{

+		DBG_INFO(("Writing to paged phy reg failed.\n"));

+		return retVal;

+	}

+

+	if (flag)

+	{

+		/* save original Pulse Width */

+		if((retVal = hwGetPagedPhyRegField(dev,hwPort,5,28,10,2,phyInfo->anyPage,&orgPulse)) != GT_OK)

+		{

+			DBG_INFO(("Reading paged phy reg failed.\n"));

+			return retVal;

+		}

+

+		/* set the Pulse Width with default value */

+		if (orgPulse != 0)

+		{

+			if((retVal = hwSetPagedPhyRegField(dev,hwPort,5,28,10,2,phyInfo->anyPage,0)) != GT_OK)

+			{

+				DBG_INFO(("Writing to paged phy reg failed.\n"));

+				return retVal;

+			}

+		}

+		tooShort=GT_FALSE;

+	}

+
+	if((retVal=runAdvCableTest_1116(dev,hwPort,phyInfo,flag,crosspair, 

+									cableStatus,&tooShort)) != GT_OK)

+	{

+		DBG_INFO(("Running advanced VCT failed.\n"));

+		return retVal;

+	}

+

+	if (flag)

+	{

+		if(tooShort)

+		{

+			/* set the Pulse Width with minimum width */

+			if((retVal = hwSetPagedPhyRegField(

+										dev,hwPort,5,28,10,2,phyInfo->anyPage,3)) != GT_OK)

+			{

+				DBG_INFO(("Writing to paged phy reg failed.\n"));

+				return retVal;

+			}

+

+			/* run the Adv VCT again */

+			if((retVal=runAdvCableTest_1116(dev,hwPort,phyInfo,GT_FALSE,crosspair,

+										cableStatus,&tooShort)) != GT_OK)

+			{

+				DBG_INFO(("Running advanced VCT failed.\n"));

+				return retVal;

+			}

+

+		}

+

+		/* set the Pulse Width back to the original value */

+		if((retVal = hwSetPagedPhyRegField(

+								dev,hwPort,5,28,10,2,phyInfo->anyPage,orgPulse)) != GT_OK)

+		{

+			DBG_INFO(("Writing to paged phy reg failed.\n"));

+			return retVal;

+		}

+

+	}

+

+	return GT_OK;

+}

+
+
+/*******************************************************************************

+* gvctGetAdvCableStatus

+*

+* DESCRIPTION:

+*       This routine perform the advanced virtual cable test for the requested

+*       port and returns the the status per MDI pair.

+*

+* INPUTS:

+*       port - logical port number.

+*       mode - advance VCT mode (either First Peak or Maximum Peak)

+*

+* OUTPUTS:

+*       cableStatus - the port copper cable status.

+*

+* RETURNS:

+*       GT_OK   - on success

+*       GT_FAIL - on error

+*

+* COMMENTS:

+*       Internal Gigabit Phys in 88E6165 family and 88E6351 family devices
+*		are supporting this API.

+*

+*******************************************************************************/

+GT_STATUS gvctGetAdvCableDiag

+(

+    IN  GT_QD_DEV *dev,

+    IN  GT_LPORT        port,

+    IN  GT_ADV_VCT_MODE mode,

+    OUT GT_ADV_CABLE_STATUS *cableStatus

+)

+{

+	GT_STATUS status;

+	GT_U8 hwPort;

+	GT_U16 u16Data, org0;

+	GT_BOOL ppuEn;

+	GT_PHY_INFO	phyInfo;

+	GT_BOOL			autoOn, autoNeg;

+	GT_U16			pageReg;
+	int i;

+

+    DBG_INFO(("gvctGetCableDiag Called.\n"));

+	hwPort = GT_LPORT_2_PHY(port);

+

+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);

+

+	/* check if the port is configurable */

+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)

+	{

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_NOT_SUPPORTED;

+	}

+

+	/* check if the port supports VCT */

+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)

+	{

+	    DBG_INFO(("Unknown PHY device.\n"));

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_FAIL;

+	}

+

+	if (!(phyInfo.flag & GT_PHY_ADV_VCT_CAPABLE))

+	{

+		DBG_INFO(("Not Supported\n"));

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_NOT_SUPPORTED;

+	}

+

+	/* Need to disable PPUEn for safe. */

+	if(gsysGetPPUEn(dev,&ppuEn) != GT_OK)

+	{

+		ppuEn = GT_FALSE;

+	}

+

+	if(ppuEn != GT_FALSE)

+	{

+		if((status= gsysSetPPUEn(dev,GT_FALSE)) != GT_OK)

+		{

+	    	DBG_INFO(("Not able to disable PPUEn.\n"));

+			gtSemGive(dev,dev->phyRegsSem);

+			return status;

+		}

+		gtDelay(250);

+	}

+		

+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)

+	{

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_FAIL;

+	}

+

+	/*

+	 * If Fiber is used, simply return with test fail.

+	 */

+	if(phyInfo.flag & GT_PHY_FIBER)

+	{

+		if((status= hwReadPagedPhyReg(dev,hwPort,1,17,phyInfo.anyPage,&u16Data)) != GT_OK)

+		{

+			return status;

+		}

+

+		if(u16Data & 0x400)

+		{

+			for (i=0; i<GT_MDI_PAIR_NUM; i++)

+			{

+				cableStatus->cableStatus[i] = GT_ADV_VCT_FAIL;

+			}

+			return GT_OK;

+		}

+	}

+
+	/*

+	 * Check the link

+	 */

+	if((status= hwReadPagedPhyReg(dev,hwPort,0,17,phyInfo.anyPage,&u16Data)) != GT_OK)

+	{

+	    DBG_INFO(("Not able to reset the Phy.\n"));

+		return status;

+	}

+
+	autoNeg = GT_FALSE;
+	org0 = 0;
+	if (!(u16Data & 0x400))
+	{
+		/* link is down, so disable auto-neg if enabled */
+		if((status= hwReadPagedPhyReg(dev,hwPort,0,0,phyInfo.anyPage,&u16Data)) != GT_OK)

+		{

+		    DBG_INFO(("Not able to reset the Phy.\n"));

+			return status;

+		}

+		
+		org0 = u16Data;
+
+		if (u16Data & 0x1000)
+		{
+			u16Data = 0x140;
+
+			/* link is down, so disable auto-neg if enabled */
+			if((status= hwWritePagedPhyReg(dev,hwPort,0,0,phyInfo.anyPage,u16Data)) != GT_OK)

+			{

+			    DBG_INFO(("Not able to reset the Phy.\n"));

+				return status;

+			}

+
+			if((status= hwPhyReset(dev,hwPort,0xFF)) != GT_OK)

+			{

+			    DBG_INFO(("Not able to reset the Phy.\n"));

+				return status;

+			}
+			autoNeg = GT_TRUE;		
+		}
+	}
+
+	switch(phyInfo.vctType)

+	{

+		case GT_PHY_ADV_VCT_TYPE1:

+			status = getAdvCableStatus_1181(dev,hwPort,&phyInfo,mode,cableStatus);

+			break;

+		case GT_PHY_ADV_VCT_TYPE2:

+			status = getAdvCableStatus_1116(dev,hwPort,&phyInfo,mode,cableStatus);

+			break;

+		default:

+			status = GT_FAIL;

+			break;

+	}

+
+	if (autoNeg)
+	{
+		if((status= hwPhyReset(dev,hwPort,org0)) != GT_OK)

+		{

+		    DBG_INFO(("Not able to reset the Phy.\n"));

+			goto cableDiagCleanup;

+			return status;

+		}

+	}
+
+cableDiagCleanup:

+

+	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)

+	{

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_FAIL;

+	}

+

+	if(ppuEn != GT_FALSE)

+	{

+		if(gsysSetPPUEn(dev,ppuEn) != GT_OK)

+		{

+	    	DBG_INFO(("Not able to enable PPUEn.\n"));

+			status = GT_FAIL;

+		}

+	}

+

+	gtSemGive(dev,dev->phyRegsSem);

+	return status;	

+}

+

+

+/*******************************************************************************

+* dspLookup

+*

+* DESCRIPTION:

+*       This routine returns cable length (meters) by reading DSP Lookup table.

+*

+* INPUTS:

+*       regValue - register 21

+*

+* OUTPUTS:

+*       cableLen - cable length (unit of meters).

+*

+* RETURNS:

+*       GT_OK   - on success

+*       GT_FAIL - on error

+*

+* COMMENTS:

+*       None.

+*

+*******************************************************************************/

+static

+GT_STATUS dspLookup

+(

+	IN	GT_PHY_INFO		*phyInfo,

+    IN  GT_U16 regValue, 

+    OUT GT_32  *cableLen

+)

+{

+    GT_U16 startEntry,tableEntry;

+    GT_U8* tbl;

+    switch(phyInfo->exStatusType)

+    {

+        case GT_PHY_EX_STATUS_TYPE1:	/* 88E1111/88E1141/E1145 */

+            startEntry = 18-1;

+            tableEntry = 80;

+            tbl = tbl_1111;

+            break;

+

+        case GT_PHY_EX_STATUS_TYPE2:	/* 88E1112 */

+            startEntry = 17;

+            tableEntry = 100;

+            tbl = tbl_1112;

+            break;

+

+        case GT_PHY_EX_STATUS_TYPE3:   /* 88E1149 has no reference constans*/

+            startEntry = 16;

+            tableEntry = 73;

+            tbl = tbl_1181;

+            break;

+

+        case GT_PHY_EX_STATUS_TYPE4:   /* 88E1181 */

+            startEntry = 16;

+            tableEntry = 73;

+            tbl = tbl_1181;

+            break;

+

+        case GT_PHY_EX_STATUS_TYPE5:   /* 88E1116 88E1121 */

+            startEntry = 16;

+            tableEntry = 73;

+            tbl = tbl_1116;

+            break;

+
+        case GT_PHY_EX_STATUS_TYPE6:   /* 88E6165 Internal Phy */
+			if ((phyInfo->phyId & PHY_MODEL_MASK) == DEV_G65G)
+	            startEntry = 18;
+			else

+	            startEntry = 21;

+            tableEntry = 76;

+            tbl = tbl_1240;

+            break;

+

+		default:

+			return GT_NOT_SUPPORTED;

+    }

+

+    if (tbl == NULL)

+    {

+        *cableLen = -1;

+        return GT_OK;

+    }

+

+    if (regValue < startEntry)

+    {

+        *cableLen = 0;

+        return GT_OK;

+    }

+

+    if (regValue >= (tableEntry+startEntry-1))

+    {

+        regValue = tableEntry-1;

+    }

+    else

+    {

+        regValue -= startEntry;

+    }

+

+    *cableLen = (GT_32)tbl[regValue];

+    return GT_OK;

+}

+

+/*******************************************************************************

+* getDSPDistance_1111

+*

+* DESCRIPTION:

+*       This routine returns cable length (meters) from DSP method.

+*       This routine is for the 88E1111 like devices.

+*

+* INPUTS:

+*       mdi - pair of each MDI (0..3).

+*

+* OUTPUTS:

+*       cableLen - cable length (unit of meters).

+*

+* RETURNS:

+*       GT_OK   - on success

+*       GT_FAIL - on error

+*

+* COMMENTS:

+*       None.

+*

+*******************************************************************************/

+static

+GT_STATUS getDSPDistance_1111

+(

+    IN  GT_QD_DEV *dev,

+    IN  GT_U8  hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+    IN  GT_U32 mdi,

+    OUT GT_32 *cableLen

+)

+{

+    GT_U16     data, pageNum;

+    GT_STATUS  retVal;

+

+    DBG_INFO(("getDSPDistance Called.\n"));

+

+    pageNum = 0x8754 + (GT_U16)((mdi << 12)&0xf000);

+

+    if((retVal = hwReadPagedPhyReg(dev,hwPort,(GT_U8)pageNum,31,phyInfo->anyPage,&data)) != GT_OK)

+    {

+        DBG_INFO(("Reading length of MDI pair failed.\n"));

+        return retVal;

+    }

+

+    return dspLookup(phyInfo,data,cableLen);

+}

+

+

+/*******************************************************************************

+* getDSPDistance_1181

+*

+* DESCRIPTION:

+*       This routine returns cable length (meters) from DSP method.

+*       This routine is for the 88E1181 like devices.

+*

+* INPUTS:

+*       mdi - pair of each MDI (0..3).

+*

+* OUTPUTS:

+*       cableLen - cable length (unit of meters).

+*

+* RETURNS:

+*       GT_OK   - on success

+*       GT_FAIL - on error

+*

+* COMMENTS:

+*       None.

+*

+*******************************************************************************/

+static

+GT_STATUS getDSPDistance_1181

+(

+    IN  GT_QD_DEV *dev,

+    IN  GT_U8  hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+    IN  GT_U32 mdi,

+    OUT GT_32 *cableLen

+)

+{

+    GT_U16     data, retryCount;

+    GT_STATUS  retVal;

+

+    DBG_INFO(("getDSPDistance Called.\n"));

+

+    /* Set the required bits for Cable length register */

+    if((retVal = hwWritePagedPhyReg(dev,hwPort,0xff,19,phyInfo->anyPage,(GT_U16)(0x1018+(0xff&mdi)))) != GT_OK)

+    {

+        DBG_INFO(("Writing to paged phy reg failed.\n"));

+        return retVal;

+    }

+

+    retryCount = 1000;

+

+    do

+    {

+        if(retryCount == 0)

+        {

+            DBG_INFO(("Ready bit of Cable length resiter is not set.\n"));

+            return GT_FAIL;

+        }

+

+        /* Check the ready bit of Cable length register */

+        if((retVal = hwGetPagedPhyRegField(dev,hwPort,0xff,19,15,1,phyInfo->anyPage,&data)) != GT_OK)

+        {

+            DBG_INFO(("Writing to paged phy reg failed.\n"));

+            return retVal;

+        }

+

+        retryCount--;

+

+    } while(!data);

+

+    /* read length of MDI pair */

+    if((retVal = hwReadPagedPhyReg(dev,hwPort,0xff,21,phyInfo->anyPage,&data)) != GT_OK)

+    {

+        DBG_INFO(("Reading length of MDI pair failed.\n"));

+        return retVal;

+    }

+

+    return dspLookup(phyInfo,data,cableLen);

+}

+

+

+/*******************************************************************************

+* getDSPDistance_1240

+*

+* DESCRIPTION:

+*       This routine returns cable length (meters) from DSP method.

+*       This routine is for the 88E1181 like devices.

+*

+* INPUTS:

+*       mdi - pair of each MDI (0..3).

+*

+* OUTPUTS:

+*       cableLen - cable length (unit of meters).

+*

+* RETURNS:

+*       GT_OK   - on success

+*       GT_FAIL - on error

+*

+* COMMENTS:

+*       None.

+*

+*******************************************************************************/

+static

+GT_STATUS getDSPDistance_1240

+(

+    IN  GT_QD_DEV *dev,

+    IN  GT_U8  hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+    IN  GT_U32 mdi,

+    OUT GT_32 *cableLen

+)

+{

+    GT_U16     data, retryCount;

+    GT_STATUS  retVal;

+

+    DBG_INFO(("getDSPDistance Called.\n"));

+

+    /* Set the required bits for Cable length register */

+    if((retVal = hwWritePagedPhyReg(dev,hwPort,0xff,16,phyInfo->anyPage,(GT_U16)(0x1118+(0xff&mdi)))) != GT_OK)

+    {

+        DBG_INFO(("Writing to paged phy reg failed.\n"));

+        return retVal;

+    }

+

+    retryCount = 1000;

+

+    do

+    {

+        if(retryCount == 0)

+        {

+            DBG_INFO(("Ready bit of Cable length resiter is not set.\n"));

+            return GT_FAIL;

+        }

+

+        /* Check the ready bit of Cable length register */

+        if((retVal = hwGetPagedPhyRegField(dev,hwPort,0xff,16,15,1,phyInfo->anyPage,&data)) != GT_OK)

+        {

+            DBG_INFO(("Writing to paged phy reg failed.\n"));

+            return retVal;

+        }

+

+        retryCount--;

+

+    } while(!data);

+

+    /* read length of MDI pair */

+    if((retVal = hwReadPagedPhyReg(dev,hwPort,0xff,18,phyInfo->anyPage,&data)) != GT_OK)

+    {

+        DBG_INFO(("Reading length of MDI pair failed.\n"));

+        return retVal;

+    }

+

+    return dspLookup(phyInfo,data,cableLen);

+}

+

+

+

+/*******************************************************************************

+* getExStatus_28

+*

+* DESCRIPTION:

+*       This routine retrieves Pair Skew, Pair Swap, and Pair Polarity

+*		for 1000M phy with multiple page mode

+*

+* INPUTS:

+*       dev - device context.

+*       port - logical port number.

+*

+* OUTPUTS:

+*       extendedStatus - extended cable status.

+*

+* RETURNS:

+*       GT_OK   - on success

+*       GT_FAIL - on error

+*

+* COMMENTS:

+*       None.

+*

+*******************************************************************************/

+static GT_STATUS getExStatus_28

+(

+    IN  GT_QD_DEV 		*dev,

+    IN  GT_U8	        hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+    OUT GT_ADV_EXTENDED_STATUS *extendedStatus

+)

+{

+    GT_STATUS retVal;

+    GT_U16 u16Data, i;

+

+    extendedStatus->isValid = GT_FALSE;

+    /* DSP based cable length */

+    for (i=0; i<GT_MDI_PAIR_NUM; i++)

+    {

+        if((retVal = getDSPDistance_1111(dev,hwPort,phyInfo,i,&extendedStatus->cableLen[i])) != GT_OK)

+        {

+            DBG_INFO(("getDSPDistance failed.\n"));

+            return retVal;

+        }

+    }

+

+

+    /*

+     * get data from 28_5 register for pair swap

+     */

+    if((retVal = hwReadPagedPhyReg(

+                    dev,hwPort,5,28,phyInfo->anyPage,&u16Data)) != GT_OK)

+    {

+        DBG_INFO(("Reading from paged phy reg failed.\n"));

+        return retVal;

+    }

+

+    /* if bit 6 is not set, it's not valid. */

+    if (!(u16Data & 0x40))

+    {

+        DBG_INFO(("Valid Bit is not set (%0#x).\n", u16Data));

+        return GT_OK;

+    }

+

+	extendedStatus->isValid = GT_TRUE;

+	

+    /* get Pair Polarity */

+    for(i=0; i<GT_MDI_PAIR_NUM; i++)

+    {

+        switch((u16Data >> i) & 0x1)

+        {

+            case 0:

+                extendedStatus->pairPolarity[i] = GT_POSITIVE;

+                break;

+            default:

+                extendedStatus->pairPolarity[i] = GT_NEGATIVE;

+            break;

+        }

+    }

+

+    /* get Pair Swap for Channel A and B */

+    if (u16Data & 0x10)

+    {

+        extendedStatus->pairSwap[0] = GT_CHANNEL_A;

+        extendedStatus->pairSwap[1] = GT_CHANNEL_B;

+    }

+    else

+    {

+        extendedStatus->pairSwap[0] = GT_CHANNEL_B;

+        extendedStatus->pairSwap[1] = GT_CHANNEL_A;

+    }

+

+    /* get Pair Swap for Channel C and D */

+    if (u16Data & 0x20)

+    {

+        extendedStatus->pairSwap[2] = GT_CHANNEL_C;

+        extendedStatus->pairSwap[3] = GT_CHANNEL_D;

+    }

+    else

+    {

+        extendedStatus->pairSwap[2] = GT_CHANNEL_D;

+        extendedStatus->pairSwap[3] = GT_CHANNEL_C;

+    }

+

+    /*

+     * get data from 28_4 register for pair skew

+     */

+    if((retVal = hwReadPagedPhyReg(

+                    dev,hwPort,4,28,phyInfo->anyPage,&u16Data)) != GT_OK)

+    {

+        DBG_INFO(("Reading from paged phy reg failed.\n"));

+        return retVal;

+    }

+

+    /* get Pair Skew */

+    for(i=0; i<GT_MDI_PAIR_NUM; i++)

+    {

+        extendedStatus->pairSkew[i] = ((u16Data >> i*4) & 0xF) * 8;

+    }

+

+    return GT_OK;

+}

+

+

+/*******************************************************************************

+* getExStatus

+*

+* DESCRIPTION:

+*       This routine retrieves Pair Skew, Pair Swap, and Pair Polarity

+*		for 1000M phy with multiple page mode

+*

+* INPUTS:

+*       dev - device context.

+*       port - logical port number.

+*

+* OUTPUTS:

+*       extendedStatus - extended cable status.

+*

+* RETURNS:

+*       GT_OK   - on success

+*       GT_FAIL - on error

+*

+* COMMENTS:

+*       None.

+*

+*******************************************************************************/

+static GT_STATUS getExStatus

+(

+    IN  GT_QD_DEV 		*dev,

+    IN  GT_U8	        hwPort,

+	IN	GT_PHY_INFO		*phyInfo,

+    OUT GT_ADV_EXTENDED_STATUS *extendedStatus

+)

+{

+    GT_STATUS retVal;

+    GT_U16 u16Data, i;

+

+    extendedStatus->isValid = GT_FALSE;

+    /* DSP based cable length */

+    switch(phyInfo->exStatusType)

+    {

+        case GT_PHY_EX_STATUS_TYPE1:

+        case GT_PHY_EX_STATUS_TYPE2:

+            for (i=0; i<GT_MDI_PAIR_NUM; i++)

+            {

+                if((retVal = getDSPDistance_1111(dev,hwPort,phyInfo,i,&extendedStatus->cableLen[i])) != GT_OK)

+                {

+                    DBG_INFO(("getDSPDistance failed.\n"));

+                    return retVal;

+                }

+            }

+            break;

+        case GT_PHY_EX_STATUS_TYPE3:

+        case GT_PHY_EX_STATUS_TYPE4:

+        case GT_PHY_EX_STATUS_TYPE5:

+            for (i=0; i<GT_MDI_PAIR_NUM; i++)

+            {

+                if((retVal = getDSPDistance_1181(dev,hwPort,phyInfo,i,&extendedStatus->cableLen[i])) != GT_OK)

+                {

+                    DBG_INFO(("getDSPDistance failed.\n"));

+                    return retVal;

+                }

+            }

+            break;

+

+        case GT_PHY_EX_STATUS_TYPE6:

+            for (i=0; i<GT_MDI_PAIR_NUM; i++)

+            {

+                if((retVal = getDSPDistance_1240(dev,hwPort,phyInfo,i,&extendedStatus->cableLen[i])) != GT_OK)

+                {

+                    DBG_INFO(("getDSPDistance failed.\n"));

+                    return retVal;

+                }

+            }

+            break;
+

+        default:

+			return GT_NOT_SUPPORTED;

+    }

+

+    /*

+     * get data from 21_5 register for pair swap

+     */

+    if((retVal = hwReadPagedPhyReg(

+                    dev,hwPort,5,QD_REG_PAIR_SWAP_STATUS,phyInfo->anyPage,&u16Data)) != GT_OK)

+    {

+        DBG_INFO(("Reading from paged phy reg failed.\n"));

+        return retVal;

+    }

+

+    /* if bit 6 is not set, it's not valid. */

+    if (!(u16Data & 0x40))

+    {

+        DBG_INFO(("Valid Bit is not set (%0#x).\n", u16Data));

+        return GT_OK;

+    }

+

+	extendedStatus->isValid = GT_TRUE;

+	

+    /* get Pair Polarity */

+    for(i=0; i<GT_MDI_PAIR_NUM; i++)

+    {

+        switch((u16Data >> i) & 0x1)

+        {

+            case 0:

+                extendedStatus->pairPolarity[i] = GT_POSITIVE;

+                break;

+            default:

+                extendedStatus->pairPolarity[i] = GT_NEGATIVE;

+            break;

+        }

+    }

+

+    /* get Pair Swap for Channel A and B */

+    if (u16Data & 0x10)

+    {

+        extendedStatus->pairSwap[0] = GT_CHANNEL_A;

+        extendedStatus->pairSwap[1] = GT_CHANNEL_B;

+    }

+    else

+    {

+        extendedStatus->pairSwap[0] = GT_CHANNEL_B;

+        extendedStatus->pairSwap[1] = GT_CHANNEL_A;

+    }

+

+    /* get Pair Swap for Channel C and D */

+    if (u16Data & 0x20)

+    {

+        extendedStatus->pairSwap[2] = GT_CHANNEL_C;

+        extendedStatus->pairSwap[3] = GT_CHANNEL_D;

+    }

+    else

+    {

+        extendedStatus->pairSwap[2] = GT_CHANNEL_D;

+        extendedStatus->pairSwap[3] = GT_CHANNEL_C;

+    }

+

+    /*

+     * get data from 20_5 register for pair skew

+     */

+    if((retVal = hwReadPagedPhyReg(

+                    dev,hwPort,5,QD_REG_PAIR_SKEW_STATUS,phyInfo->anyPage,&u16Data)) != GT_OK)

+    {

+        DBG_INFO(("Reading from paged phy reg failed.\n"));

+        return retVal;

+    }

+

+    /* get Pair Skew */

+    for(i=0; i<GT_MDI_PAIR_NUM; i++)

+    {

+        extendedStatus->pairSkew[i] = ((u16Data >> i*4) & 0xF) * 8;

+    }

+

+

+    return GT_OK;

+}

+

+

+/*******************************************************************************

+* gvctGetAdvExtendedStatus

+*

+* DESCRIPTION:

+*       This routine retrieves extended cable status, such as Pair Poloarity,

+*		Pair Swap, and Pair Skew. Note that this routine will be success only

+*		if 1000Base-T Link is up.

+*		Note: Since DSP based cable length in extended status is based on 

+*             constants from test results. At present, only E1181, E1111, and

+*             E1112 are available.

+*

+* INPUTS:

+*       dev  - pointer to GT driver structure returned from mdLoadDriver

+*       port - logical port number.

+*

+* OUTPUTS:

+*       extendedStatus - the extended cable status.

+*

+* RETURNS:

+*       GT_OK   - on success

+*       GT_FAIL - on error

+*

+* COMMENTS:

+*		Supporting Device list:

+*       	88E1111, 88E1112, 88E1141~6, 88E1149, and Internal Gigabit Phys 
+*			in 88E6165 family and 88E6351 family devices
+*

+*******************************************************************************/

+GT_STATUS gvctGetAdvExtendedStatus

+(

+    IN  GT_QD_DEV     *dev,

+    IN  GT_LPORT   port,

+    OUT GT_ADV_EXTENDED_STATUS *extendedStatus

+)

+{

+	GT_STATUS retVal;

+	GT_U8 hwPort;

+	GT_BOOL ppuEn;

+	GT_PHY_INFO	phyInfo;

+	GT_BOOL			autoOn;

+	GT_U16			pageReg;

+

+    DBG_INFO(("gvctGetAdvExtendedStatus Called.\n"));

+	hwPort = GT_LPORT_2_PHY(port);

+

+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);

+

+	/* check if the port is configurable */

+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)

+	{

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_NOT_SUPPORTED;

+	}

+
+	/* check if the port supports VCT */

+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)

+	{

+	    DBG_INFO(("Unknown PHY device.\n"));

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_FAIL;

+	}

+

+	if (!(phyInfo.flag & GT_PHY_EX_CABLE_STATUS))

+	{

+		DBG_INFO(("Not Supported\n"));

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_NOT_SUPPORTED;

+	}

+

+	/* Need to disable PPUEn for safe. */

+	if(gsysGetPPUEn(dev,&ppuEn) != GT_OK)

+	{

+		ppuEn = GT_FALSE;

+	}

+

+	if(ppuEn != GT_FALSE)

+	{

+		if((retVal = gsysSetPPUEn(dev,GT_FALSE)) != GT_OK)

+		{

+	    	DBG_INFO(("Not able to disable PPUEn.\n"));

+			gtSemGive(dev,dev->phyRegsSem);

+			return retVal;

+		}

+		gtDelay(250);

+	}

+

+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)

+	{

+		gtSemGive(dev,dev->phyRegsSem);

+		return GT_FAIL;

+	}

+

+    switch(phyInfo.exStatusType)

+    {

+        case GT_PHY_EX_STATUS_TYPE1:

+            if((retVal = getExStatus_28(dev,hwPort,&phyInfo,extendedStatus)) != GT_OK)

+            {

+                DBG_INFO(("Getting Extanded Cable Status failed.\n"));

+                break;

+            }

+            break;

+

+        case GT_PHY_EX_STATUS_TYPE2:

+        case GT_PHY_EX_STATUS_TYPE3:

+        case GT_PHY_EX_STATUS_TYPE4:

+        case GT_PHY_EX_STATUS_TYPE5:

+        case GT_PHY_EX_STATUS_TYPE6:

+            if((retVal = getExStatus(dev,hwPort,&phyInfo,extendedStatus)) != GT_OK)

+            {

+                DBG_INFO(("Getting Extanded Cable Status failed.\n"));

+                break;

+            }

+

+            break;

+        default:

+			retVal = GT_NOT_SUPPORTED;

+    }

+

+	return retVal;

+}

+

diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgFdb.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgFdb.c
new file mode 100755
index 0000000..5499034
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgFdb.c
@@ -0,0 +1,3194 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtBrgFdb.c
+*
+* DESCRIPTION:
+*       API definitions for Multiple Forwarding Databases 
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 9 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+/****************************************************************************/
+/* Forward function declaration.                                            */
+/****************************************************************************/
+static GT_STATUS atuOperationPerform
+(
+    IN      GT_QD_DEV           *dev,
+    IN      GT_ATU_OPERATION    atuOp,
+	INOUT	GT_EXTRA_OP_DATA	*opData,
+    INOUT 	GT_ATU_ENTRY    	*atuEntry
+);
+
+static GT_STATUS atuStateAppToDev
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL		unicast,
+	IN  GT_U32		state,
+	OUT GT_U32		*newOne
+);
+
+static GT_STATUS atuStateDevToApp
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL		unicast,
+	IN  GT_U32		state,
+	OUT GT_U32		*newOne
+);
+
+static GT_STATUS atuGetStats
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_ATU_STAT	*atuStat,
+	OUT GT_U32		*count
+);
+
+
+/*******************************************************************************
+* gfdbSetPortAtuLearnLimit
+*
+* DESCRIPTION:
+*       Port's auto learning limit. When the limit is non-zero value, the number
+*		of MAC addresses that can be learned on this port are limited to the value
+*		specified in this API. When the learn limit has been reached any frame 
+*		that ingresses this port with a source MAC address not already in the 
+*		address database that is associated with this port will be discarded. 
+*		Normal auto-learning will resume on the port as soon as the number of 
+*		active unicast MAC addresses associated to this port is less than the 
+*		learn limit.
+*		CPU directed ATU Load, Purge, or Move will not have any effect on the 
+*		learn limit.
+*		This feature is disabled when the limit is zero.
+*		The following care is needed when enabling this feature:
+*			1) dsable learning on the ports
+*			2) flush all non-static addresses in the ATU
+*			3) define the desired limit for the ports
+*			4) re-enable learing on the ports
+*
+* INPUTS:
+*       port  - logical port number
+*       limit - auto learning limit ( 0 ~ 255 )
+*											  
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if limit > 0xFF
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbSetPortAtuLearnLimit
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT  	port,
+	IN  GT_U32   	limit
+)
+{
+	GT_U16          data, mask;
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gfdbSetPortAtuLearnLimit Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Check device if it has fixed ATU Size. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ATU_LIMIT))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (limit > 0xFF)
+	{
+		DBG_INFO(("Bad Parameter\n"));
+		return GT_BAD_PARAM;
+	}
+
+	mask = 0x80FF;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_ATU_LIMIT_READ))
+		mask |= 0x1000;
+
+	data = (GT_U16) limit;
+
+	/* Set the learn limit bits.                  */
+	retVal = hwSetPortRegBits(dev,hwPort, QD_REG_PORT_ATU_CONTROL, mask, data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetPortAtuLearnLimit
+*
+* DESCRIPTION:
+*      Port's auto learning limit. When the limit is non-zero value, the number
+*		of MAC addresses that can be learned on this port are limited to the value
+*		specified in this API. When the learn limit has been reached any frame 
+*		that ingresses this port with a source MAC address not already in the 
+*		address database that is associated with this port will be discarded. 
+*		Normal auto-learning will resume on the port as soon as the number of 
+*		active unicast MAC addresses associated to this port is less than the 
+*		learn limit.
+*		CPU directed ATU Load, Purge, or Move will not have any effect on the 
+*		learn limit.
+*		This feature is disabled when the limit is zero.
+*		The following care is needed when enabling this feature:
+*			1) dsable learning on the ports
+*			2) flush all non-static addresses in the ATU
+*			3) define the desired limit for the ports
+*			4) re-enable learing on the ports
+*
+* INPUTS:
+*		port  - logical port number
+*											  
+* OUTPUTS:
+*		limit - auto learning limit ( 0 ~ 255 )
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if limit > 0xFF
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gfdbGetPortAtuLearnLimit
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT  	port,
+	OUT GT_U32   	*limit
+)
+{
+	GT_U16          data, mask;
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gfdbGetPortAtuLearnLimit Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Check device if it has fixed ATU Size. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ATU_LIMIT_READ))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	mask = 0x9000;
+	data = (GT_U16) 0x1000;
+
+	/* Set the learn limit bits.                  */
+	retVal = hwSetPortRegBits(dev,hwPort, QD_REG_PORT_ATU_CONTROL, mask, data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	/* Get the ReadLearnLimit bit. */
+	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ATU_CONTROL, 0, 8, &data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	*limit = (GT_U32)data;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gfdbGetPortAtuLearnCnt
+*
+* DESCRIPTION:
+*       Read the current number of active unicast MAC addresses associated with 
+*		the given port. This counter (LearnCnt) is held at zero if learn limit
+*		(gfdbSetPortAtuLearnLimit API) is set to zero.
+*
+* INPUTS:
+*       port  - logical port number
+*											  
+* OUTPUTS:
+*       count - current auto learning count
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetPortAtuLearnCnt
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT  	port,
+    IN  GT_U32   	*count
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gfdbGetPortAtuLearnCnt Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Check device if this feature is supported. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ATU_LIMIT))
+    {
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the ReadLearnCnt bit. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ATU_CONTROL, 15, 1, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if(data == 0)
+	{
+	    /* Set the ReadLearnCnt bit. */
+    	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ATU_CONTROL, 15, 1, 1);
+	    if(retVal != GT_OK)
+    	{
+        	DBG_INFO(("Failed.\n"));
+	        return retVal;
+    	}
+	}
+
+    /* Get the LearnCnt bits. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ATU_CONTROL, 0, 8, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	*count = (GT_U32)data;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetAtuAllCount
+*
+* DESCRIPTION:
+*       Counts all entries in the Address Translation Unit.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       count - number of valid entries.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuAllCount
+(
+    IN  GT_QD_DEV 	*dev,
+    OUT GT_U32 		*count
+)
+{
+    GT_U32          dbNum, maxDbNum, numOfEntries;
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+	GT_ATU_STAT		atuStat;
+
+    DBG_INFO(("gfdbGetAtuAllCount Called.\n"));
+
+	if(IS_IN_DEV_GROUP(dev,DEV_ATU_STATS))
+	{
+		atuStat.op = GT_ATU_STATS_ALL;
+		return atuGetStats(dev,&atuStat,count);
+	}
+
+    numOfEntries = 0;
+	
+	if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_FULL))
+		maxDbNum = 16;
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+		maxDbNum = 64;
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+		maxDbNum = 256;
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_4096))
+		maxDbNum = 4096;
+	else
+		maxDbNum = 1;
+
+	for(dbNum=0; dbNum<maxDbNum; dbNum++)
+	{
+		entry.DBNum = (GT_U16)dbNum;
+
+		if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+		    gtMemSet(entry.macAddr.arEther,0,sizeof(GT_ETHERADDR));
+		else
+    		gtMemSet(entry.macAddr.arEther,0xFF,sizeof(GT_ETHERADDR));
+
+	    while(1)
+    	{
+	        retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+        	if(retVal != GT_OK)
+	        {
+    	        DBG_INFO(("Failed.\n"));
+        	    return retVal;
+	        }
+
+    	    if(IS_BROADCAST_MAC(entry.macAddr))
+			{
+				if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+					break;
+				else if(entry.entryState.ucEntryState == 0)
+					break;
+	        	numOfEntries++;
+				break;
+			}
+
+        	numOfEntries++;
+	    }
+	}
+
+    *count = numOfEntries;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetAtuAllCountInDBNum
+*
+* DESCRIPTION:
+*       Counts all entries in the defined FID (or DBNum).
+*
+* INPUTS:
+*       dbNum - 
+*
+* OUTPUTS:
+*       count - number of valid entries in FID (or DBNum).
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuAllCountInDBNum
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_U32 		dbNum,
+    OUT GT_U32 		*count
+)
+{
+    GT_U32          numOfEntries;
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+	GT_ATU_STAT		atuStat;
+
+    DBG_INFO(("gfdbGetAtuAllCountInDBNum Called.\n"));
+
+	if(IS_IN_DEV_GROUP(dev,DEV_ATU_STATS))
+	{
+		atuStat.op = GT_ATU_STATS_ALL_FID;
+		atuStat.DBNum = dbNum;
+		return atuGetStats(dev,&atuStat,count);
+	}
+
+    numOfEntries = 0;
+	
+	entry.DBNum = (GT_U16)dbNum;
+
+	if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+	    gtMemSet(entry.macAddr.arEther,0,sizeof(GT_ETHERADDR));
+	else
+    	gtMemSet(entry.macAddr.arEther,0xFF,sizeof(GT_ETHERADDR));
+
+	while(1)
+    {
+	    retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+    	if(retVal != GT_OK)
+	    {
+            DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+
+        if(IS_BROADCAST_MAC(entry.macAddr))
+		{
+			if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+				break;
+			else if(entry.entryState.ucEntryState == 0)
+				break;
+	    	numOfEntries++;
+			break;
+		}
+
+    	numOfEntries++;
+	}
+
+    *count = numOfEntries;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetAtuDynamicCountInDBNum
+*
+* DESCRIPTION:
+*       Counts all non-static entries in the defined FID (or DBNum).
+*
+* INPUTS:
+*       dbNum - 
+*
+* OUTPUTS:
+*       count - number of valid non-static entries in FID (or DBNum).
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuDynamicCountInDBNum
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_U32 		dbNum,
+    OUT GT_U32 		*count
+)
+{
+    GT_U32          numOfEntries, tmpState;
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+	GT_ATU_UC_STATE	state;
+	GT_ATU_STAT		atuStat;
+
+    DBG_INFO(("gfdbGetAtuDynamicCountInDBNum Called.\n"));
+
+	if(IS_IN_DEV_GROUP(dev,DEV_ATU_STATS))
+	{
+		atuStat.op = GT_ATU_STATS_NON_STATIC_FID;
+		atuStat.DBNum = dbNum;
+		return atuGetStats(dev,&atuStat,count);
+	}
+
+    numOfEntries = 0;
+	
+	entry.DBNum = (GT_U16)dbNum;
+
+	if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+	    gtMemSet(entry.macAddr.arEther,0,sizeof(GT_ETHERADDR));
+	else
+    	gtMemSet(entry.macAddr.arEther,0xFF,sizeof(GT_ETHERADDR));
+
+	while(1)
+    {
+	    retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+        if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+            return retVal;
+	    }
+
+    	if(IS_BROADCAST_MAC(entry.macAddr))
+            break;
+
+	    if(IS_MULTICAST_MAC(entry.macAddr))
+	    {
+	        continue;
+    	}
+
+		atuStateDevToApp(dev,GT_TRUE,entry.entryState.ucEntryState,&tmpState);
+		state = (GT_ATU_UC_STATE)tmpState;
+		if (state == GT_UC_DYNAMIC)
+		{
+	    	numOfEntries++;
+		}
+	}
+	
+    *count = numOfEntries;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gfdbSetAtuSize
+*
+* DESCRIPTION:
+*       Sets the Mac address table size.
+*
+* INPUTS:
+*       size    - Mac address table size.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbSetAtuSize
+(
+    IN GT_QD_DEV    *dev,
+    IN ATU_SIZE     size
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gfdbSetAtuSize Called.\n"));
+
+	switch(size)
+	{
+		case ATU_SIZE_256:
+			if (IS_IN_DEV_GROUP(dev,DEV_ATU_256_2048))
+				data = 0;
+			else
+				return GT_NOT_SUPPORTED;
+			break;
+    	case ATU_SIZE_512:
+    	case ATU_SIZE_1024:
+    	case ATU_SIZE_2048:
+			if (IS_IN_DEV_GROUP(dev,DEV_ATU_256_2048))
+				data = (GT_U16)size;
+			else
+				data = (GT_U16)size - 1;
+			break;
+
+    	case ATU_SIZE_4096:
+			if ((IS_IN_DEV_GROUP(dev,DEV_ATU_256_2048))||(IS_IN_DEV_GROUP(dev,DEV_ATU_562_2048)))
+				return GT_NOT_SUPPORTED;
+			else
+				data = 3;
+			break;
+		default:
+			return GT_NOT_SUPPORTED;
+	}
+	
+	/* Check device if it has fixed ATU Size. */
+	if (IS_IN_DEV_GROUP(dev,DEV_ATU_SIZE_FIXED))
+    {
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Set the Software reset bit.                  */
+    retVal = hwSetGlobalRegField(dev,QD_REG_ATU_CONTROL,12,2,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    /* Make sure the reset operation is completed.  */
+    data = 0;
+    while(data == 0)
+    {
+        retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,11,1,&data);
+        if(retVal != GT_OK)
+        {
+            DBG_INFO(("Failed.\n"));
+            return retVal;
+        }
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetAgingTimeRange
+*
+* DESCRIPTION:
+*       Gets the maximal and minimum age times that the hardware can support.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       maxTimeout - max aging time in secounds.
+*       minTimeout - min aging time in secounds.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAgingTimeRange
+(
+    IN GT_QD_DEV    *dev,
+    OUT GT_U32 *maxTimeout,
+    OUT GT_U32 *minTimeout
+)
+{
+    DBG_INFO(("gfdbGetAgingTimeRange Called.\n"));
+    if((maxTimeout == NULL) || (minTimeout == NULL))
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_ATU_15SEC_AGING))
+	{
+		*minTimeout = 15;
+		*maxTimeout = 3825;
+	}
+	else
+	{
+		*minTimeout = 16;
+		*maxTimeout = 4080;
+	}
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetAgingTimeout
+*
+* DESCRIPTION:
+*       Gets the timeout period in seconds for aging out dynamically learned
+*       forwarding information. The returned value may not be the same as the value
+*		programmed with <gfdbSetAgingTimeout>. Please refer to the description of
+*		<gfdbSetAgingTimeout>.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       timeout - aging time in seconds.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAgingTimeout
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_U32       *timeout
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+	GT_U16			timeBase;
+
+    DBG_INFO(("gfdbGetAgingTimeout Called.\n"));
+ 
+	if (IS_IN_DEV_GROUP(dev,DEV_ATU_15SEC_AGING))
+		timeBase = 15;
+	else
+		timeBase = 16;
+
+    /* Get the Time Out value.              */
+    retVal = hwGetGlobalRegField(dev,QD_REG_ATU_CONTROL,4,8,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	*timeout = data*timeBase;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbSetAgingTimeout
+*
+* DESCRIPTION:
+*       Sets the timeout period in seconds for aging out dynamically learned
+*       forwarding information. The standard recommends 300 sec.
+*		Supported aging timeout values are multiple of time-base, where time-base
+*		is either 15 or 16 seconds, depending on the Switch device. For example,
+*		88E6063 uses time-base 16, and so supported aging timeouts are 0,16,32,
+*		48,..., and 4080. If unsupported timeout value (bigger than 16) is used, 
+*		the value will be rounded to the nearest supported value smaller than the 
+*		given timeout. If the given timeout is less than 16, minimum timeout value
+*		16 will be used instead. E.g.) 35 becomes 32 and 5 becomes 16.
+*		<gfdbGetAgingTimeRange> function can be used to find the time-base.
+*
+* INPUTS:
+*       timeout - aging time in seconds.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbSetAgingTimeout
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_U32 timeout
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+	GT_U16			timeBase;
+
+    DBG_INFO(("gfdbSetAgingTimeout Called.\n"));
+ 
+	if (IS_IN_DEV_GROUP(dev,DEV_ATU_15SEC_AGING))
+		timeBase = 15;
+	else
+		timeBase = 16;
+
+	if((timeout < timeBase) && (timeout != 0))
+	{	
+ 	   data = 1;
+	}
+	else
+	{
+ 	   data = (GT_U16)(timeout/timeBase);
+	   if (data & 0xFF00)
+			data = 0xFF;
+	}
+
+    /* Set the Time Out value.              */
+    retVal = hwSetGlobalRegField(dev,QD_REG_ATU_CONTROL,4,8,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetLearn2All
+*
+* DESCRIPTION:
+*		When more than one Marvell device is used to form a single 'switch', it
+*		may be desirable for all devices in the 'switch' to learn any address this 
+*		device learns. When this bit is set to a one all other devices in the 
+*		'switch' learn the same addresses this device learns. When this bit is 
+*		cleared to a zero, only the devices that actually receive frames will learn
+*		from those frames. This mode typically supports more active MAC addresses 
+*		at one time as each device in the switch does not need to learn addresses 
+*		it may nerver use.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if Learn2All is enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*
+*******************************************************************************/
+GT_STATUS gfdbGetLearn2All
+(
+	IN  GT_QD_DEV    *dev,
+	OUT GT_BOOL 	*mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* to keep the read valve       */
+
+	DBG_INFO(("gprtGetLearn2All Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get the Learn2All. */
+	retVal = hwGetGlobalRegField(dev,QD_REG_ATU_CONTROL, 3, 1, &data);
+
+	BIT_2_BOOL(data, *mode);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	return retVal;
+}
+
+/*******************************************************************************
+* gfdbSetLearn2All
+*
+* DESCRIPTION:
+*		Enable or disable Learn2All mode.
+*
+* INPUTS:
+*		mode - GT_TRUE to set Learn2All, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbSetLearn2All
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		mode
+)
+{
+	GT_U16          data;           /* Used to poll the SWReset bit */
+	GT_STATUS       retVal;         /* Functions return value.      */
+
+	DBG_INFO(("gprtSetLearn2All Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate BOOL to binary */
+	BOOL_2_BIT(mode, data);
+
+	/* Set Learn2All. */
+	retVal = hwSetGlobalRegField(dev,QD_REG_ATU_CONTROL, 3, 1, data);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gfdbGetMacAvb
+*
+* DESCRIPTION:
+*		ATU MAC entry in AVB mode.
+*		When enabled, ATU entries operate in AVB mode:
+*
+*		GT_ATU_UC_STATE - support
+*			GT_UC_NO_PRI_STATIC_AVB_ENTRY, and 
+*			GT_UC_STATIC_AVB_ENTRY
+*
+*		GT_ATU_MC_STATE - support
+*			GT_MC_STATIC_AVB_ENTRY, and
+*			GT_MC_PRIO_STATIC_AVB_ENTRY
+*
+*		When disabled, ATU entries operate in non-AVB mode:
+*
+*		GT_ATU_UC_STATE - support
+*			GT_UC_NO_PRI_STATIC_NRL, and 
+*			GT_UC_STATIC_NRL
+*
+*		GT_ATU_MC_STATE - support
+*			GT_MC_STATIC_UNLIMITED_RATE, and
+*			GT_MC_PRIO_STATIC_UNLIMITED_RATE
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if MacAvb is enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*
+*******************************************************************************/
+GT_STATUS gfdbGetMacAvb
+(
+	IN  GT_QD_DEV    *dev,
+	OUT GT_BOOL 	*mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* to keep the read valve       */
+
+	DBG_INFO(("gfdbGetMacAvb Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MAC_AVB))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get the bit. */
+	retVal = hwGetGlobalRegField(dev,QD_REG_ATU_CONTROL, 15, 1, &data);
+
+	BIT_2_BOOL(data, *mode);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	return retVal;
+}
+
+/*******************************************************************************
+* gfdbSetMacAvb
+*
+* DESCRIPTION:
+*		ATU MAC entry in AVB mode.
+*		When enabled, ATU entries operate in AVB mode:
+*
+*		GT_ATU_UC_STATE - support
+*			GT_UC_NO_PRI_STATIC_AVB_ENTRY, and 
+*			GT_UC_STATIC_AVB_ENTRY
+*
+*		GT_ATU_MC_STATE - support
+*			GT_MC_STATIC_AVB_ENTRY, and
+*			GT_MC_PRIO_STATIC_AVB_ENTRY
+*
+*		When disabled, ATU entries operate in non-AVB mode:
+*
+*		GT_ATU_UC_STATE - support
+*			GT_UC_NO_PRI_STATIC_NRL, and 
+*			GT_UC_STATIC_NRL
+*
+*		GT_ATU_MC_STATE - support
+*			GT_MC_STATIC_UNLIMITED_RATE, and
+*			GT_MC_PRIO_STATIC_UNLIMITED_RATE
+*
+* INPUTS:
+*		mode - GT_TRUE to enable MacAvb, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gfdbSetMacAvb
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		mode
+)
+{
+	GT_U16          data;           /* Used to poll the SWReset bit */
+	GT_STATUS       retVal;         /* Functions return value.      */
+
+	DBG_INFO(("gprtSetMacAvb Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MAC_AVB))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate BOOL to binary */
+	BOOL_2_BIT(mode, data);
+
+	/* Set the bit */
+	retVal = hwSetGlobalRegField(dev,QD_REG_ATU_CONTROL, 15, 1, data);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gfdbGetAtuDynamicCount
+*
+* DESCRIPTION:
+*       Gets the current number of dynamic unicast (non-static) entries in this
+*       Filtering Database.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       numDynEntries - number of dynamic entries.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - vlan does not exist.
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuDynamicCount
+(
+    IN  GT_QD_DEV 	*dev,
+    OUT GT_U32 		*numDynEntries
+)
+{
+    GT_U32          dbNum, maxDbNum, numOfEntries, tmpState;
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+	GT_ATU_UC_STATE	state;
+	GT_ATU_STAT		atuStat;
+
+    DBG_INFO(("gfdbGetAtuDynamicCount Called.\n"));
+
+	if(IS_IN_DEV_GROUP(dev,DEV_ATU_STATS))
+	{
+		atuStat.op = GT_ATU_STATS_NON_STATIC;
+		return atuGetStats(dev,&atuStat,numDynEntries);
+	}
+
+    numOfEntries = 0;
+	
+	if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_FULL))
+		maxDbNum = 16;
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+		maxDbNum = 64;
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+		maxDbNum = 256;
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_4096))
+		maxDbNum = 4096;
+	else
+		maxDbNum = 1;
+
+	for(dbNum=0; dbNum<maxDbNum; dbNum++)
+	{
+		entry.DBNum = (GT_U16)dbNum;
+
+		if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+		    gtMemSet(entry.macAddr.arEther,0,sizeof(GT_ETHERADDR));
+		else
+    		gtMemSet(entry.macAddr.arEther,0xFF,sizeof(GT_ETHERADDR));
+
+	    while(1)
+    	{
+	        retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+        	if(retVal != GT_OK)
+	        {
+    	        DBG_INFO(("Failed.\n"));
+        	    return retVal;
+	        }
+
+    	    if(IS_BROADCAST_MAC(entry.macAddr))
+        	    break;
+
+	        if(IS_MULTICAST_MAC(entry.macAddr))
+	        {
+	            continue;
+    	    }
+
+			atuStateDevToApp(dev,GT_TRUE,(GT_U32)entry.entryState.ucEntryState,&tmpState);
+			state = (GT_ATU_UC_STATE)tmpState;
+			if (state == GT_UC_DYNAMIC)
+			{
+	        	numOfEntries++;
+			}
+	    }
+	}
+
+    *numDynEntries = numOfEntries;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetAtuEntryFirst
+*
+* DESCRIPTION:
+*       Gets first lexicographic MAC address entry from the ATU.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       atuEntry - match Address translate unit entry.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - table is empty.
+*
+* COMMENTS:
+*       Search starts from Mac[00:00:00:00:00:00]
+*
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuEntryFirst
+(
+    IN GT_QD_DEV    *dev,
+    OUT GT_ATU_ENTRY    *atuEntry
+)
+{
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+
+    DBG_INFO(("gfdbGetAtuEntryFirst Called.\n"));
+
+	if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+	    gtMemSet(entry.macAddr.arEther,0,sizeof(GT_ETHERADDR));
+	else
+    	gtMemSet(entry.macAddr.arEther,0xFF,sizeof(GT_ETHERADDR));
+
+	entry.DBNum = atuEntry->DBNum;
+
+    DBG_INFO(("DBNum : %i\n",entry.DBNum));
+
+    retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (atuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    if(IS_BROADCAST_MAC(entry.macAddr))
+    {
+		if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+		{
+	        DBG_INFO(("Failed (Invalid Mac).\n"));
+    	    return GT_NO_SUCH;
+		}
+		else if(entry.entryState.ucEntryState == 0)
+		{
+	        DBG_INFO(("Failed (Invalid Mac).\n"));
+    	    return GT_NO_SUCH;
+		}
+    }
+
+    gtMemCpy(atuEntry->macAddr.arEther,entry.macAddr.arEther,6);
+    atuEntry->portVec   = GT_PORTVEC_2_LPORTVEC(entry.portVec);
+    atuEntry->prio      = entry.prio;
+    atuEntry->trunkMember = entry.trunkMember;
+	atuEntry->exPrio.useMacFPri = entry.exPrio.useMacFPri;
+	atuEntry->exPrio.macFPri = entry.exPrio.macFPri;
+	atuEntry->exPrio.macQPri = entry.exPrio.macQPri;
+
+    if(IS_MULTICAST_MAC(entry.macAddr))
+    {
+        if(dev->deviceId == GT_88E6051)
+        {
+            DBG_INFO(("Failed.\n"));
+            return GT_FAIL;
+        }
+
+		atuStateDevToApp(dev,GT_FALSE,(GT_U32)entry.entryState.ucEntryState,
+						(GT_U32*)&atuEntry->entryState.mcEntryState);
+    }
+    else
+    {
+		atuStateDevToApp(dev,GT_TRUE,(GT_U32)entry.entryState.ucEntryState,
+						(GT_U32*)&atuEntry->entryState.ucEntryState);
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gfdbGetAtuEntryNext
+*
+* DESCRIPTION:
+*       Gets next lexicographic MAC address from the specified Mac Addr.
+*
+* INPUTS:
+*       atuEntry - the Mac Address to start the search.
+*
+* OUTPUTS:
+*       atuEntry - match Address translate unit entry.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*
+* COMMENTS:
+*       Search starts from atu.macAddr[xx:xx:xx:xx:xx:xx] specified by the
+*       user.
+*
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+*******************************************************************************/
+GT_STATUS gfdbGetAtuEntryNext
+(
+    IN GT_QD_DEV    *dev,
+    INOUT GT_ATU_ENTRY  *atuEntry
+)
+{
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+
+    DBG_INFO(("gfdbGetAtuEntryNext Called.\n"));
+
+    if(IS_BROADCAST_MAC(atuEntry->macAddr))
+    {
+   	    return GT_NO_SUCH;
+    }
+
+    gtMemCpy(entry.macAddr.arEther,atuEntry->macAddr.arEther,6);
+
+	entry.DBNum = atuEntry->DBNum;
+    DBG_INFO(("DBNum : %i\n",entry.DBNum));
+
+    retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (atuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    if(IS_BROADCAST_MAC(entry.macAddr))
+    {
+		if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+		{
+	        DBG_INFO(("Failed (Invalid Mac).\n"));
+    	    return GT_NO_SUCH;
+		}
+		else if(entry.entryState.ucEntryState == 0)
+		{
+	        DBG_INFO(("Failed (Invalid Mac).\n"));
+    	    return GT_NO_SUCH;
+		}
+    }
+
+    gtMemCpy(atuEntry->macAddr.arEther,entry.macAddr.arEther,6);
+    atuEntry->portVec   = GT_PORTVEC_2_LPORTVEC(entry.portVec);
+    atuEntry->prio      = entry.prio;
+    atuEntry->trunkMember = entry.trunkMember;
+	atuEntry->exPrio.useMacFPri = entry.exPrio.useMacFPri;
+	atuEntry->exPrio.macFPri = entry.exPrio.macFPri;
+	atuEntry->exPrio.macQPri = entry.exPrio.macQPri;
+
+    if(IS_MULTICAST_MAC(entry.macAddr))
+    {
+        if(dev->deviceId == GT_88E6051)
+        {
+            DBG_INFO(("Failed.\n"));
+            return GT_FAIL;
+        }
+
+		atuStateDevToApp(dev,GT_FALSE,(GT_U32)entry.entryState.ucEntryState,
+						(GT_U32*)&atuEntry->entryState.mcEntryState);
+    }
+    else
+    {
+		atuStateDevToApp(dev,GT_TRUE,(GT_U32)entry.entryState.ucEntryState,
+						(GT_U32*)&atuEntry->entryState.ucEntryState);
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gfdbFindAtuMacEntry
+*
+* DESCRIPTION:
+*       Find FDB entry for specific MAC address from the ATU.
+*
+* INPUTS:
+*       atuEntry - the Mac address to search.
+*
+* OUTPUTS:
+*       found    - GT_TRUE, if the appropriate entry exists.
+*       atuEntry - the entry parameters.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*       GT_BAD_PARAM    - on bad parameter
+*
+* COMMENTS:
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+*******************************************************************************/
+GT_STATUS gfdbFindAtuMacEntry
+(
+    IN GT_QD_DEV    *dev,
+    INOUT GT_ATU_ENTRY  *atuEntry,
+    OUT GT_BOOL         *found
+)
+{
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+    int           i;
+
+    DBG_INFO(("gfdbFindAtuMacEntry Called.\n"));
+    *found = GT_FALSE;
+    gtMemCpy(entry.macAddr.arEther,atuEntry->macAddr.arEther,6);
+	entry.DBNum = atuEntry->DBNum;
+
+    /* Decrement 1 from mac address.    */
+    for(i=5; i >= 0; i--)
+    {
+        if(entry.macAddr.arEther[i] != 0)
+        {
+            entry.macAddr.arEther[i] -= 1;
+            break;
+        }
+		else
+            entry.macAddr.arEther[i] = 0xFF;
+    }
+
+    /* Check if the given mac equals zero   */
+    if((i == -1) && IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+    {
+        DBG_INFO(("Address should not be all zeros.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    if(IS_BROADCAST_MAC(entry.macAddr))
+    {
+		if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+		{
+	        DBG_INFO(("Failed (Broadcast addr is not valid).\n"));
+    	    return GT_NO_SUCH;
+		}
+		else if(entry.entryState.ucEntryState == 0)
+		{
+	        DBG_INFO(("Failed (Invalid Mac).\n"));
+    	    return GT_NO_SUCH;
+		}
+    }
+
+	if(gtMemCmp((char*)atuEntry->macAddr.arEther,(char*)entry.macAddr.arEther,ETHERNET_HEADER_SIZE))
+	{
+        DBG_INFO(("Failed.\n"));
+        return GT_NO_SUCH;
+	}
+
+    atuEntry->portVec   = GT_PORTVEC_2_LPORTVEC(entry.portVec);
+    atuEntry->prio      = entry.prio;
+    atuEntry->trunkMember = entry.trunkMember;
+	atuEntry->exPrio.useMacFPri = entry.exPrio.useMacFPri;
+	atuEntry->exPrio.macFPri = entry.exPrio.macFPri;
+	atuEntry->exPrio.macQPri = entry.exPrio.macQPri;
+
+    if(IS_MULTICAST_MAC(entry.macAddr))
+    {
+        if(dev->deviceId == GT_88E6051)
+        {
+            DBG_INFO(("Failed.\n"));
+            return GT_FAIL;
+        }
+
+		atuStateDevToApp(dev,GT_FALSE,(GT_U32)entry.entryState.ucEntryState,
+						(GT_U32*)&atuEntry->entryState.mcEntryState);
+    }
+    else
+    {
+		atuStateDevToApp(dev,GT_TRUE,(GT_U32)entry.entryState.ucEntryState,
+						(GT_U32*)&atuEntry->entryState.ucEntryState);
+    }
+
+    *found = GT_TRUE;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gfdbFlush
+*
+* DESCRIPTION:
+*       This routine flush all or unblocked addresses from the MAC Address
+*       Table.
+*
+* INPUTS:
+*       flushCmd - the flush operation type.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NO_RESOURCE  - failed to allocate a t2c struct
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbFlush
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_FLUSH_CMD flushCmd
+)
+{
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+
+    DBG_INFO(("gfdbFlush Called.\n"));
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_STATIC_ADDR))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	entry.DBNum = 0;
+	entry.entryState.ucEntryState = 0;
+
+    if(flushCmd == GT_FLUSH_ALL)
+        retVal = atuOperationPerform(dev,FLUSH_ALL,NULL,&entry);
+    else
+        retVal = atuOperationPerform(dev,FLUSH_UNLOCKED,NULL,&entry);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbFlushInDB
+*
+* DESCRIPTION:
+*       This routine flush all or unblocked addresses from the particular
+*       ATU Database (DBNum). If multiple address databases are being used, this
+*		API can be used to flush entries in a particular DBNum database.
+*
+* INPUTS:
+*       flushCmd - the flush operation type.
+*		DBNum	 - ATU MAC Address Database Number. 
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORTED- if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbFlushInDB
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_FLUSH_CMD flushCmd,
+	IN GT_U32 DBNum
+)
+{
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+
+    DBG_INFO(("gfdbFlush Called.\n"));
+    DBG_INFO(("gfdbFush: dev=%x, dev->atuRegsSem=%d \n",dev, dev->atuRegsSem));
+
+    /* check if device supports this feature */
+	if ((!IS_IN_DEV_GROUP(dev,DEV_DBNUM_FULL)) && 
+		(!IS_IN_DEV_GROUP(dev,DEV_DBNUM_64)) && 
+		(!IS_IN_DEV_GROUP(dev,DEV_DBNUM_4096)) && 
+		(!IS_IN_DEV_GROUP(dev,DEV_DBNUM_256)))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	entry.DBNum = (GT_U16)DBNum;
+	entry.entryState.ucEntryState = 0;
+
+    if(flushCmd == GT_FLUSH_ALL)
+        retVal = atuOperationPerform(dev,FLUSH_ALL_IN_DB,NULL,&entry);
+    else
+        retVal = atuOperationPerform(dev,FLUSH_UNLOCKED_IN_DB,NULL,&entry);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbMove
+*
+* DESCRIPTION:
+*       This routine moves all or unblocked addresses from a port to another.
+*
+* INPUTS:
+* 		moveCmd  - the move operation type.
+*		moveFrom - port where moving from
+*		moveTo   - port where moving to
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbMove
+(
+	IN GT_QD_DEV    *dev,
+	IN GT_MOVE_CMD  moveCmd,
+	IN GT_LPORT		moveFrom,
+	IN GT_LPORT		moveTo
+)
+{
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+	GT_EXTRA_OP_DATA	opData;
+
+    DBG_INFO(("gfdbMove Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_802_1W))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	entry.DBNum = 0;
+	entry.entryState.ucEntryState = 0xF;
+	if (moveTo == 0xF)
+		opData.moveTo = moveTo;
+	else
+		opData.moveTo = (GT_U32)GT_LPORT_2_PORT(moveTo);
+	opData.moveFrom = (GT_U32)GT_LPORT_2_PORT(moveFrom);
+
+	if((opData.moveTo == 0xFF) || (opData.moveFrom == 0xFF))
+		return GT_BAD_PARAM;
+
+    if(moveCmd == GT_MOVE_ALL)
+        retVal = atuOperationPerform(dev,FLUSH_ALL,&opData,&entry);
+    else
+        retVal = atuOperationPerform(dev,FLUSH_UNLOCKED,&opData,&entry);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbMoveInDB
+*
+* DESCRIPTION:
+*       This routine move all or unblocked addresses which are in the particular
+*       ATU Database (DBNum) from a port to another.
+*
+* INPUTS:
+*       moveCmd  - the move operation type.
+*		DBNum	 - ATU MAC Address Database Number.
+*		moveFrom - port where moving from
+*		moveTo   - port where moving to
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORTED- if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbMoveInDB
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_MOVE_CMD 	moveCmd,
+	IN GT_U32 		DBNum,
+	IN GT_LPORT		moveFrom,
+	IN GT_LPORT		moveTo
+)
+{
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+	GT_EXTRA_OP_DATA	opData;
+
+    DBG_INFO(("gfdbMoveInDB Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_802_1W))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	entry.DBNum = (GT_U16)DBNum;
+	entry.entryState.ucEntryState = 0xF;
+
+	if (moveTo == 0xF)
+		opData.moveTo = moveTo;
+	else
+		opData.moveTo = (GT_U32)GT_LPORT_2_PORT(moveTo);
+	opData.moveFrom = (GT_U32)GT_LPORT_2_PORT(moveFrom);
+
+	if((opData.moveTo == 0xFF) || (opData.moveFrom == 0xFF))
+		return GT_BAD_PARAM;
+
+    if(moveCmd == GT_MOVE_ALL)
+        retVal = atuOperationPerform(dev,FLUSH_ALL_IN_DB,&opData,&entry);
+    else
+        retVal = atuOperationPerform(dev,FLUSH_UNLOCKED_IN_DB,&opData,&entry);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbRemovePort
+*
+* DESCRIPTION:
+*       This routine deassociages all or unblocked addresses from a port.
+*
+* INPUTS:
+*       moveCmd - the move operation type.
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbRemovePort
+(
+	IN GT_QD_DEV    *dev,
+    IN GT_MOVE_CMD 	moveCmd,
+    IN GT_LPORT		port
+)
+{
+    DBG_INFO(("gfdbRemovePort Called.\n"));
+
+	/* Only 88E6093 Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ATU_RM_PORTS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	return gfdbMove(dev,moveCmd,port,(GT_LPORT)0xF);
+}
+
+
+/*******************************************************************************
+* gfdbRemovePortInDB
+*
+* DESCRIPTION:
+*       This routine deassociages all or unblocked addresses from a port in the
+*       particular ATU Database (DBNum).
+*
+* INPUTS:
+*       moveCmd  - the move operation type.
+*       port - the logical port number.
+*		DBNum	 - ATU MAC Address Database Number.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORTED- if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbRemovePortInDB
+(
+	IN GT_QD_DEV    *dev,
+    IN GT_MOVE_CMD 	moveCmd,
+    IN GT_LPORT		port,
+	IN GT_U32 		DBNum
+)
+{
+    DBG_INFO(("gfdbRemovePortInDB Called.\n"));
+
+	/* Only 88E6093 Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ATU_RM_PORTS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+	return gfdbMoveInDB(dev,moveCmd,DBNum,port,(GT_LPORT)0xF);
+}
+
+
+/*******************************************************************************
+* gfdbAddMacEntry
+*
+* DESCRIPTION:
+*       Creates the new entry in MAC address table.
+*
+* INPUTS:
+*       macEntry    - mac address entry to insert to the ATU.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK          - on success
+*       GT_FAIL        - on error
+*       GT_BAD_PARAM   - on invalid port vector
+*
+* COMMENTS:
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbAddMacEntry
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_ATU_ENTRY *macEntry
+)
+{
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+
+    DBG_INFO(("gfdbAddMacEntry Called.\n"));
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_STATIC_ADDR))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    gtMemCpy(entry.macAddr.arEther,macEntry->macAddr.arEther,6);
+	entry.DBNum		= macEntry->DBNum;
+    entry.portVec     = GT_LPORTVEC_2_PORTVEC(macEntry->portVec);
+	if(entry.portVec == GT_INVALID_PORT_VEC)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	if(IS_IN_DEV_GROUP(dev,DEV_ATU_EXT_PRI))
+	{
+		if(IS_IN_DEV_GROUP(dev,DEV_FQPRI_IN_TABLE))
+		{
+			entry.exPrio.useMacFPri = macEntry->exPrio.useMacFPri;
+			entry.exPrio.macFPri = macEntry->exPrio.macFPri;
+			entry.exPrio.macQPri = macEntry->exPrio.macQPri;
+		}
+		else
+		{
+			entry.exPrio.useMacFPri = 0;
+			entry.exPrio.macFPri = 0;
+			entry.exPrio.macQPri = macEntry->exPrio.macQPri;
+		}
+    	entry.prio	    = 0;
+	}
+	else
+	{
+		entry.exPrio.useMacFPri = 0;
+		entry.exPrio.macFPri = 0;
+		entry.exPrio.macQPri = 0;
+    	entry.prio	    = macEntry->prio;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+	{
+	    entry.trunkMember = macEntry->trunkMember;
+	}
+	else
+	{
+	    entry.trunkMember = GT_FALSE;
+	}
+
+    if(IS_MULTICAST_MAC(entry.macAddr))
+    {
+		atuStateAppToDev(dev,GT_FALSE,(GT_U32)macEntry->entryState.mcEntryState,
+							(GT_U32*)&entry.entryState.ucEntryState);
+    }
+    else
+	{
+		atuStateAppToDev(dev,GT_TRUE,(GT_U32)macEntry->entryState.ucEntryState,
+							(GT_U32*)&entry.entryState.ucEntryState);
+	}
+
+	if (entry.entryState.ucEntryState == 0)
+	{
+        DBG_INFO(("Entry State should not be ZERO.\n"));
+		return GT_BAD_PARAM;
+	}
+
+    retVal = atuOperationPerform(dev,LOAD_PURGE_ENTRY,NULL,&entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gfdbDelMacEntry
+*
+* DESCRIPTION:
+*       Deletes MAC address entry. If DBNum or FID is used, gfdbDelAtuEntry API
+*		would be the better choice to delete an entry in ATU.
+*
+* INPUTS:
+*       macAddress - mac address.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NO_RESOURCE  - failed to allocate a t2c struct
+*       GT_NO_SUCH      - if specified address entry does not exist
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gfdbDelMacEntry
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_ETHERADDR  *macAddress
+)
+{
+    GT_STATUS retVal;
+    GT_ATU_ENTRY    entry;
+
+    DBG_INFO(("gfdbDelMacEntry Called.\n"));
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_STATIC_ADDR))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    gtMemCpy(entry.macAddr.arEther,macAddress->arEther,6);
+	entry.DBNum = 0;
+	entry.prio = 0;
+	entry.portVec = 0;
+	entry.entryState.ucEntryState = 0;
+	entry.trunkMember = GT_FALSE;
+	entry.exPrio.useMacFPri = GT_FALSE;
+	entry.exPrio.macFPri = 0;
+	entry.exPrio.macQPri = 0;
+
+    retVal = atuOperationPerform(dev,LOAD_PURGE_ENTRY,NULL,&entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbDelAtuEntry
+*
+* DESCRIPTION:
+*       Deletes ATU entry.
+*
+* INPUTS:
+*       atuEntry - the ATU entry to be deleted.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NO_RESOURCE  - failed to allocate a t2c struct
+*       GT_NO_SUCH      - if specified address entry does not exist
+*
+* COMMENTS:
+*		DBNum in atuEntry - 
+*			ATU MAC Address Database number. If multiple address 
+*			databases are not being used, DBNum should be zero.
+*			If multiple address databases are being used, this value
+*			should be set to the desired address database number.
+*
+*******************************************************************************/
+GT_STATUS gfdbDelAtuEntry
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_ATU_ENTRY  *atuEntry
+)
+{
+    GT_ATU_ENTRY    entry;
+    GT_STATUS retVal;
+
+    DBG_INFO(("gfdbDelMacEntry Called.\n"));
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_STATIC_ADDR))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    gtMemCpy(entry.macAddr.arEther,atuEntry->macAddr.arEther,6);
+	entry.DBNum = atuEntry->DBNum;
+	entry.prio = 0;
+	entry.portVec = 0;
+    entry.entryState.ucEntryState = 0;
+    entry.trunkMember = GT_FALSE;
+	entry.exPrio.useMacFPri = GT_FALSE;
+	entry.exPrio.macFPri = 0;
+	entry.exPrio.macQPri = 0;
+
+    retVal = atuOperationPerform(dev,LOAD_PURGE_ENTRY,NULL,&entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gfdbLearnEnable
+*
+* DESCRIPTION:
+*       Enable/disable automatic learning of new source MAC addresses on port
+*       ingress.
+*
+* INPUTS:
+*       en - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbLearnEnable
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_BOOL  en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+	GT_LPORT	port;
+	GT_BOOL		mode;
+
+    DBG_INFO(("gfdbLearnEnable Called.\n"));
+    BOOL_2_BIT(en,data);
+    data = 1 - data;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		mode = (en)?GT_FALSE:GT_TRUE;
+
+		for (port=0; port<dev->numOfPorts; port++)
+		{
+			retVal = gprtSetLearnDisable(dev,port,mode);
+		    if(retVal != GT_OK)
+    		{
+	    	    DBG_INFO(("Failed.\n"));
+    	    	return retVal;
+		    }
+		}
+	}
+	else
+	{
+	    /* Set the Learn Enable bit.            */
+    	retVal = hwSetGlobalRegField(dev,QD_REG_ATU_CONTROL,14,1,data);
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	}	
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gfdbGetLearnEnable
+*
+* DESCRIPTION:
+*       Get automatic learning status of new source MAC addresses on port ingress.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       en - GT_TRUE if enabled  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gfdbGetLearnEnable
+(
+    IN GT_QD_DEV    *dev,
+    OUT GT_BOOL  *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gfdbGetLearnEnable Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+	else
+	{
+	    /* Get the Learn Enable bit.            */
+    	retVal = hwGetGlobalRegField(dev,QD_REG_ATU_CONTROL,14,1,&data);
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	}	
+
+    data = 1 - data;
+    BOOL_2_BIT(data, *en);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/****************************************************************************/
+/* Internal use functions.                                                  */
+/****************************************************************************/
+
+/*******************************************************************************
+* gatuGetViolation
+*
+* DESCRIPTION:
+*       Get ATU Violation data
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       atuIntStatus - interrupt cause, source portID, and vid.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORT  - if current device does not support this feature.
+*
+* COMMENTS:
+*		This is an internal function. No user should call this function.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gatuGetViolation
+(
+    IN  GT_QD_DEV         *dev,
+    OUT GT_ATU_INT_STATUS *atuIntStatus
+)
+{
+    GT_U16              intCause;
+    GT_STATUS       	retVal;
+    GT_ATU_ENTRY    	entry;
+	GT_EXTRA_OP_DATA	opData;
+	GT_BOOL				found, ageInt;
+
+    DBG_INFO(("gatuGetViolation Called.\n"));
+
+	/* check which Violation occurred */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,3,1,&intCause);
+    if(retVal != GT_OK)
+    {
+	    DBG_INFO(("ERROR to read ATU OPERATION Register.\n"));
+        return retVal;
+    }
+
+	if (!intCause)
+	{
+		/* No Violation occurred. */
+		atuIntStatus->atuIntCause = 0;
+		return GT_OK;
+	}
+
+    retVal = atuOperationPerform(dev,SERVICE_VIOLATIONS,&opData,&entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (atuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    gtMemCpy(atuIntStatus->macAddr.arEther,entry.macAddr.arEther,6);
+
+	atuIntStatus->atuIntCause = (GT_U16)opData.intCause;
+	atuIntStatus->spid = entry.entryState.ucEntryState;
+
+	if(atuIntStatus->spid != 0xF)
+		atuIntStatus->spid = (GT_U8)GT_PORT_2_LPORT(atuIntStatus->spid);
+			
+	if (IS_IN_DEV_GROUP(dev,DEV_AGE_OUT_INT))
+	{
+		if (opData.intCause == GT_AGE_VIOLATION)
+		{
+			atuIntStatus->atuIntCause = GT_AGE_OUT_VIOLATION;
+		}
+		else if (opData.intCause == GT_MISS_VIOLATION)
+		{
+			/* check if it's AGE Violation */
+			if((retVal = gsysGetAgeInt(dev, &ageInt)) != GT_OK)
+				return retVal;
+
+			if(ageInt)
+			{
+				gfdbFindAtuMacEntry(dev, &entry, &found);
+				if ((found) && (entry.entryState.ucEntryState <= 4))
+					atuIntStatus->atuIntCause = GT_AGE_VIOLATION;
+			}
+			
+		}
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* atuOperationPerform
+*
+* DESCRIPTION:
+*       This function is used by all ATU control functions, and is responsible
+*       to write the required operation into the ATU registers.
+*
+* INPUTS:
+*       atuOp       - The ATU operation bits to be written into the ATU
+*                     operation register.
+*       DBNum       - ATU Database Number for CPU accesses
+*       entryPri    - The EntryPri field in the ATU Data register.
+*       portVec     - The portVec field in the ATU Data register.
+*       entryState  - The EntryState field in the ATU Data register.
+*       atuMac      - The Mac address to be written to the ATU Mac registers.
+*
+* OUTPUTS:
+*       entryPri    - The EntryPri field in case the atuOp is GetNext.
+*       portVec     - The portVec field in case the atuOp is GetNext.
+*       entryState  - The EntryState field in case the atuOp is GetNext.
+*       atuMac      - The returned Mac address in case the atuOp is GetNext.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*       1.  if atuMac == NULL, nothing needs to be written to ATU Mac registers.
+*
+*******************************************************************************/
+static GT_STATUS atuOperationPerform
+(
+    IN      GT_QD_DEV           *dev,
+    IN      GT_ATU_OPERATION    atuOp,
+	INOUT	GT_EXTRA_OP_DATA	*opData,
+    INOUT 	GT_ATU_ENTRY    	*entry
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U16          opcodeData;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           i;
+    GT_U16			portMask;
+
+    gtSemTake(dev,dev->atuRegsSem,OS_WAIT_FOREVER);
+
+	portMask = (1 << dev->maxPorts) - 1;
+
+    /* Wait until the ATU in ready. */
+    data = 1;
+    while(data == 1)
+    {
+        retVal = hwGetGlobalRegField(dev,QD_REG_ATU_OPERATION,15,1,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->atuRegsSem);
+            return retVal;
+        }
+    }
+
+	opcodeData = 0;
+
+	switch (atuOp)
+	{
+		case LOAD_PURGE_ENTRY:
+				if (IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY) || 
+					IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+				{
+					if (IS_IN_DEV_GROUP(dev,DEV_TRUNK) && entry->trunkMember)
+					{
+						/* portVec represents trunk ID */
+				        data = (GT_U16)( 0x8000 | (((entry->portVec) & 0xF) << 4) |
+        			         (((entry->entryState.ucEntryState) & 0xF)) );
+					}
+					else
+					{
+				        data = (GT_U16)( (((entry->portVec) & portMask) << 4) |
+        			         (((entry->entryState.ucEntryState) & 0xF)) );
+					}
+					opcodeData |= (entry->prio & 0x7) << 8;
+				}
+				else if(IS_IN_DEV_GROUP(dev,DEV_ATU_EXT_PRI))
+				{
+			        data = (GT_U16)( (((entry->portVec) & portMask) << 4) |
+        			         (((entry->entryState.ucEntryState) & 0xF)) |
+        			         (((entry->exPrio.macQPri) & 0x3) << 14) );
+					if(entry->exPrio.useMacFPri == GT_TRUE)
+						data |= ((1 << 13) | ((entry->exPrio.macFPri & 0x7) << 10));
+				}
+				else
+				{
+			        data = (GT_U16)( (((entry->prio) & 0x3) << 14) | 
+			        		(((entry->portVec) & portMask) << 4) |
+        					(((entry->entryState.ucEntryState) & 0xF)) );
+				}
+		        retVal = hwWriteGlobalReg(dev,QD_REG_ATU_DATA_REG,data);
+        		if(retVal != GT_OK)
+		        {
+        		    gtSemGive(dev,dev->atuRegsSem);
+		            return retVal;
+        		}
+				/* pass thru */
+
+		case GET_NEXT_ENTRY:
+		        for(i = 0; i < 3; i++)
+        		{
+		            data=(entry->macAddr.arEther[2*i] << 8)|(entry->macAddr.arEther[1 + 2*i]);
+        		    retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_ATU_MAC_BASE+i),data);
+		            if(retVal != GT_OK)
+        		    {
+		                gtSemGive(dev,dev->atuRegsSem);
+        		        return retVal;
+		            }
+        		}
+				break;
+
+		case FLUSH_ALL:
+		case FLUSH_UNLOCKED:
+		case FLUSH_ALL_IN_DB:
+		case FLUSH_UNLOCKED_IN_DB:
+				if (entry->entryState.ucEntryState == 0xF)
+				{
+			        data = (GT_U16)(0xF | ((opData->moveFrom & 0xF) << 4) | ((opData->moveTo & 0xF) << 8));
+				}
+				else
+				{
+			        data = 0;
+				}
+		        retVal = hwWriteGlobalReg(dev,QD_REG_ATU_DATA_REG,data);
+       			if(retVal != GT_OK)
+	        	{
+       		    	gtSemGive(dev,dev->atuRegsSem);
+		            return retVal;
+   	    		}
+				break;
+
+		case SERVICE_VIOLATIONS:
+
+				break;
+
+		default :
+				return GT_FAIL;
+	}
+
+    /* Set DBNum */
+	if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
+	{
+	    retVal = hwSetGlobalRegField(dev,QD_REG_ATU_FID_REG,0,12,(GT_U16)(entry->DBNum & 0xFFF));
+    	if(retVal != GT_OK)
+	    {
+    	    gtSemGive(dev,dev->atuRegsSem);
+        	return retVal;
+	    }
+	}
+	else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+	{
+	    retVal = hwSetGlobalRegField(dev,QD_REG_ATU_CONTROL,12,4,(GT_U16)((entry->DBNum & 0xF0) >> 4));
+    	if(retVal != GT_OK)
+	    {
+    	    gtSemGive(dev,dev->atuRegsSem);
+        	return retVal;
+	    }
+	}
+	else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+	{
+	    opcodeData |= ((entry->DBNum & 0x30) << 4);	/* Op Reg bit 9:8 */
+	}
+
+    /* Set the ATU Operation register in addtion to DBNum setup  */
+
+	if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
+	    opcodeData |= ((1 << 15) | (atuOp << 12));
+	else
+	    opcodeData |= ((1 << 15) | (atuOp << 12) | (entry->DBNum & 0xF));
+
+    retVal = hwWriteGlobalReg(dev,QD_REG_ATU_OPERATION,opcodeData);
+    if(retVal != GT_OK)
+    {
+        gtSemGive(dev,dev->atuRegsSem);
+        return retVal;
+    }
+
+	/* If the operation is to service violation operation wait for the response   */
+	if(atuOp == SERVICE_VIOLATIONS)
+	{
+		/* Wait until the VTU in ready. */
+		data = 1;
+		while(data == 1)
+		{
+			retVal = hwGetGlobalRegField(dev,QD_REG_ATU_OPERATION,15,1,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->atuRegsSem);
+				return retVal;
+			}
+		}
+
+		/* get the Interrupt Cause */
+		retVal = hwGetGlobalRegField(dev,QD_REG_ATU_OPERATION,4,4,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->atuRegsSem);
+			return retVal;
+		}
+
+		if (!IS_IN_DEV_GROUP(dev,DEV_AGE_OUT_INT))
+		{
+			data &= 0x7;	/* only 3 bits are valid for non age_out_int group */
+		}
+
+		switch (data)
+		{
+			case 8:	/* Age Interrupt */
+				opData->intCause = GT_AGE_VIOLATION;
+				break;
+			case 4:	/* Member Violation */
+				opData->intCause = GT_MEMBER_VIOLATION;
+				break;
+			case 2:	/* Miss Violation */
+				opData->intCause = GT_MISS_VIOLATION;
+				break;
+			case 1:	/* Full Violation */
+				opData->intCause = GT_FULL_VIOLATION;
+				break;
+			default:
+				opData->intCause = 0;
+				gtSemGive(dev,dev->atuRegsSem);
+				return GT_OK;
+		}
+
+		/* get the DBNum that was involved in the violation */
+
+		entry->DBNum = 0;
+
+		if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
+		{
+		    retVal = hwGetGlobalRegField(dev,QD_REG_ATU_FID_REG,0,12,&data);
+    		if(retVal != GT_OK)
+	    	{
+	    	    gtSemGive(dev,dev->atuRegsSem);
+    	    	return retVal;
+	    	}
+			entry->DBNum = (GT_U16)data;
+		}
+		else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+		{
+		    retVal = hwGetGlobalRegField(dev,QD_REG_ATU_CONTROL,12,4,&data);
+    		if(retVal != GT_OK)
+	    	{
+	    	    gtSemGive(dev,dev->atuRegsSem);
+    	    	return retVal;
+	    	}
+			entry->DBNum = (GT_U16)data << 4;
+		}
+		else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+		{
+			retVal = hwGetGlobalRegField(dev,QD_REG_ATU_OPERATION,8,2,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->atuRegsSem);
+				return retVal;
+			}
+			entry->DBNum = (GT_U16)data << 4;
+		}
+
+		if(!IS_IN_DEV_GROUP(dev,DEV_FID_REG))
+		{
+			retVal = hwGetGlobalRegField(dev,QD_REG_ATU_OPERATION,0,4,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->atuRegsSem);
+				return retVal;
+			}
+
+			entry->DBNum |= (GT_U8)(data & 0xF);
+		}
+
+		/* get the Source Port ID that was involved in the violation */
+
+		retVal = hwReadGlobalReg(dev,QD_REG_ATU_DATA_REG,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->atuRegsSem);
+			return retVal;
+		}
+
+		entry->entryState.ucEntryState = data & 0xF;
+
+        /* Get the Mac address  */
+        for(i = 0; i < 3; i++)
+        {
+            retVal = hwReadGlobalReg(dev,(GT_U8)(QD_REG_ATU_MAC_BASE+i),&data);
+            if(retVal != GT_OK)
+            {
+                gtSemGive(dev,dev->atuRegsSem);
+                return retVal;
+            }
+            entry->macAddr.arEther[2*i] = data >> 8;
+            entry->macAddr.arEther[1 + 2*i] = data & 0xFF;
+        }
+
+
+	} /* end of service violations */
+    /* If the operation is a gen next operation wait for the response   */
+    if(atuOp == GET_NEXT_ENTRY)
+    {
+		entry->trunkMember = GT_FALSE;
+		entry->exPrio.useMacFPri = GT_FALSE;
+		entry->exPrio.macFPri = 0;
+        entry->exPrio.macQPri = 0;
+
+        /* Wait until the ATU in ready. */
+        data = 1;
+        while(data == 1)
+        {
+            retVal = hwGetGlobalRegField(dev,QD_REG_ATU_OPERATION,15,1,&data);
+            if(retVal != GT_OK)
+            {
+                gtSemGive(dev,dev->atuRegsSem);
+                return retVal;
+            }
+        }
+
+        /* Get the Mac address  */
+        for(i = 0; i < 3; i++)
+        {
+            retVal = hwReadGlobalReg(dev,(GT_U8)(QD_REG_ATU_MAC_BASE+i),&data);
+            if(retVal != GT_OK)
+            {
+                gtSemGive(dev,dev->atuRegsSem);
+                return retVal;
+            }
+            entry->macAddr.arEther[2*i] = data >> 8;
+            entry->macAddr.arEther[1 + 2*i] = data & 0xFF;
+        }
+
+        retVal = hwReadGlobalReg(dev,QD_REG_ATU_DATA_REG,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->atuRegsSem);
+            return retVal;
+        }
+
+        /* Get the Atu data register fields */
+		if(IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_TRUNK))
+		{
+			if (IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+			{
+				entry->trunkMember = (data & 0x8000)?GT_TRUE:GT_FALSE;
+			}
+
+			entry->portVec = (data >> 4) & portMask;
+			entry->entryState.ucEntryState = data & 0xF;
+			retVal = hwGetGlobalRegField(dev,QD_REG_ATU_OPERATION,8,3,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->atuRegsSem);
+				return retVal;
+			}
+			entry->prio = (GT_U8)data;
+		}
+		else if(IS_IN_DEV_GROUP(dev,DEV_ATU_EXT_PRI))
+		{
+	        entry->prio = 0;
+    	    entry->portVec = (data >> 4) & portMask;
+        	entry->entryState.ucEntryState = data & 0xF;
+			entry->exPrio.useMacFPri = (data & 0x2000)?GT_TRUE:GT_FALSE;
+			entry->exPrio.macFPri = (data >> 10) & 0x7;
+	        entry->exPrio.macQPri = data >> 14;
+		}
+		else
+		{
+	        entry->prio = data >> 14;
+    	    entry->portVec = (data >> 4) & portMask;
+        	entry->entryState.ucEntryState = data & 0xF;
+		}
+    }
+
+    gtSemGive(dev,dev->atuRegsSem);
+    return GT_OK;
+}
+
+static GT_STATUS atuStateAppToDev
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL		unicast,
+	IN  GT_U32		state,
+	OUT GT_U32		*newOne
+)
+{
+	GT_U32	newState;
+	GT_STATUS	retVal = GT_OK;
+
+	if(unicast)
+	{
+		switch ((GT_ATU_UC_STATE)state)
+		{
+			case GT_UC_INVALID:
+				newState = state;
+				break;
+
+			case GT_UC_DYNAMIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_7_DYNAMIC))
+				{
+					newState = 7;
+				}
+				else
+				{
+					newState = 0xE;
+				}
+				break;
+
+			case GT_UC_NO_PRI_TO_CPU_STATIC_NRL:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_NO_PRI_TO_CPU_STATIC_NRL))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_UC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_UC_TO_CPU_STATIC_NRL:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_TO_CPU_STATIC_NRL))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_UC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_UC_NO_PRI_STATIC_NRL:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_NO_PRI_STATIC_NRL))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_UC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_UC_STATIC_NRL:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_STATIC_NRL))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_UC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_UC_NO_PRI_TO_CPU_STATIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_NO_PRI_TO_CPU_STATIC))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_UC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_UC_TO_CPU_STATIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_TO_CPU_STATIC))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_UC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_UC_NO_PRI_STATIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_NO_PRI_STATIC))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_UC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_UC_STATIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_STATIC))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_UC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			default:
+				if (IS_IN_DEV_GROUP(dev,DEV_UC_7_DYNAMIC))
+				{
+					newState = 7;
+				}
+				else
+				{
+					newState = 0xE;
+				}
+				retVal = GT_BAD_PARAM;
+				break;
+
+		}
+	}
+	else
+	{
+		switch ((GT_ATU_UC_STATE)state)
+		{
+			case GT_MC_INVALID:
+				newState = state;
+				break;
+
+			case GT_MC_MGM_STATIC_UNLIMITED_RATE:
+				if (IS_IN_DEV_GROUP(dev,DEV_MC_MGM_STATIC_UNLIMITED_RATE))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_MC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_MC_STATIC_UNLIMITED_RATE:
+				if (IS_IN_DEV_GROUP(dev,DEV_MC_STATIC_UNLIMITED_RATE))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_MC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_MC_MGM_STATIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_MC_MGM_STATIC))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_MC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_MC_STATIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_MC_STATIC))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_MC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_MC_PRIO_MGM_STATIC_UNLIMITED_RATE:
+				if (IS_IN_DEV_GROUP(dev,DEV_MC_PRIO_MGM_STATIC_UNLIMITED_RATE))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_MC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_MC_PRIO_STATIC_UNLIMITED_RATE:
+				if (IS_IN_DEV_GROUP(dev,DEV_MC_PRIO_STATIC_UNLIMITED_RATE))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_MC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_MC_PRIO_MGM_STATIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_MC_PRIO_MGM_STATIC))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_MC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			case GT_MC_PRIO_STATIC:
+				if (IS_IN_DEV_GROUP(dev,DEV_MC_PRIO_STATIC))
+				{
+					newState = state;
+				}
+				else
+				{
+					newState = (GT_U32)GT_MC_STATIC;
+					retVal = GT_BAD_PARAM;
+				}
+				break;
+
+			default:
+				newState = (GT_U32)GT_MC_STATIC;
+				retVal = GT_BAD_PARAM;
+				break;
+
+		}
+	}
+	
+	*newOne = newState;
+	return retVal;
+}
+
+static GT_STATUS atuStateDevToApp
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL		unicast,
+	IN  GT_U32		state,
+	OUT GT_U32		*newOne
+)
+{
+	GT_U32	newState;
+	GT_STATUS	retVal = GT_OK;
+
+	if(unicast)
+	{
+		if (state == 0)
+		{
+			newState = (GT_U32)GT_UC_INVALID;
+		}
+		else if (state <= 7)
+		{
+			newState = (GT_U32)GT_UC_DYNAMIC;
+		}
+		else if ((state <= 0xE) && (!IS_IN_DEV_GROUP(dev,DEV_UC_7_DYNAMIC)))
+		{
+			newState = (GT_U32)GT_UC_DYNAMIC;
+		}
+		else
+		{
+			newState = state;
+		}
+	}
+	else
+	{
+		newState = state;
+	}
+
+	*newOne = newState;
+	return retVal;
+}
+
+
+static GT_STATUS atuGetStats
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_ATU_STAT	*atuStat,
+	OUT GT_U32		*count
+)
+{
+    GT_U32          numOfEntries, dbNum;
+    GT_ATU_ENTRY    entry;
+	GT_U16			data,mode,bin;
+    GT_STATUS       retVal;
+
+    DBG_INFO(("atuGetStats Called.\n"));
+
+	switch (atuStat->op)
+	{
+		case GT_ATU_STATS_ALL:
+		case GT_ATU_STATS_NON_STATIC:
+			dbNum = 0;
+			break;
+		case GT_ATU_STATS_ALL_FID:
+		case GT_ATU_STATS_NON_STATIC_FID:
+			dbNum = atuStat->DBNum;
+			break;
+		default:
+			return GT_FALSE;
+	}
+
+    numOfEntries = 0;
+	mode = atuStat->op;
+
+	for(bin=0; bin<4; bin++)
+	{	
+		data = (bin << 14) | (mode << 12);
+
+	    retVal = hwWriteGlobal2Reg(dev, QD_REG_ATU_STATS, data);
+       	if(retVal != GT_OK)
+        {
+   	        DBG_INFO(("Failed.\n"));
+       	    return retVal;
+        }
+		
+		entry.DBNum = (GT_U16)dbNum;
+	    gtMemSet(entry.macAddr.arEther,0,sizeof(GT_ETHERADDR));
+
+        retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+       	if(retVal == GT_FAIL)
+        {
+   	        DBG_INFO(("Failed.\n"));
+       	    return retVal;
+        }
+
+	    retVal = hwReadGlobal2Reg(dev, QD_REG_ATU_STATS, &data);
+       	if(retVal != GT_OK)
+        {
+   	        DBG_INFO(("Failed.\n"));
+       	    return retVal;
+        }
+		
+		numOfEntries += (data & 0xFFF);
+	}
+
+	*count = numOfEntries;
+
+	return GT_OK;
+}
+/*******************************************************************************
+* gfdbClearAtuDynamicEntry
+*
+* DESCRIPTION:
+*       Clear all non-static entries.
+*
+* INPUTS:
+*
+* OUTPUTS:
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gfdbClearAtuDynamicEntry
+(
+    IN  GT_QD_DEV 	*dev
+)
+{
+    GT_U32          dbNum, maxDbNum;
+    GT_STATUS       retVal;
+    GT_ATU_ENTRY    entry;
+    GT_U32          tmpState;
+    GT_ATU_UC_STATE	state;
+    GT_ATU_ENTRY    tmpEntry;
+    
+    DBG_INFO(("gfdbClearAtuDynamicEntry Called.\n"));
+    
+    if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_FULL))
+    	maxDbNum = 16;
+    else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+    	maxDbNum = 64;
+    else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+    	maxDbNum = 256;
+    else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_4096))
+    	maxDbNum = 4096;
+    else
+    	maxDbNum = 1;
+    
+    /*Currently switch integrated in 88F6500 use one Db*/
+    maxDbNum = 1;
+    
+    for(dbNum=0; dbNum<maxDbNum; dbNum++)
+    {
+        entry.DBNum = (GT_U16)dbNum;
+        
+        if(IS_IN_DEV_GROUP(dev,DEV_BROADCAST_INVALID))
+            gtMemSet(entry.macAddr.arEther,0,sizeof(GT_ETHERADDR));
+        else
+            gtMemSet(entry.macAddr.arEther,0xFF,sizeof(GT_ETHERADDR));
+        
+        while(1)
+    	{
+            retVal = atuOperationPerform(dev,GET_NEXT_ENTRY,NULL,&entry);
+            if(retVal != GT_OK)
+            {
+                DBG_INFO(("Failed.\n"));
+                return retVal;
+            }
+            
+            if(IS_BROADCAST_MAC(entry.macAddr))
+                break;
+            
+            if(IS_MULTICAST_MAC(entry.macAddr))
+            {
+                continue;
+            }
+
+	     /*delete dynamic ATU entry*/
+            atuStateDevToApp(dev,GT_TRUE,entry.entryState.ucEntryState,&tmpState);
+            state = (GT_ATU_UC_STATE)tmpState;
+            if (state == GT_UC_DYNAMIC)
+            {
+                gtMemCpy(tmpEntry.macAddr.arEther, entry.macAddr.arEther, 6);	
+                tmpEntry.DBNum = entry.DBNum;
+                tmpEntry.prio = entry.prio;
+                tmpEntry.portVec = entry.portVec;
+                tmpEntry.entryState.ucEntryState = 0;
+                tmpEntry.trunkMember = entry.trunkMember;
+                tmpEntry.exPrio.useMacFPri = entry.exPrio.useMacFPri;
+                tmpEntry.exPrio.macFPri = entry.exPrio.macFPri;
+                tmpEntry.exPrio.macQPri = entry.exPrio.macQPri ;
+                
+                retVal = atuOperationPerform(dev,LOAD_PURGE_ENTRY,NULL,&tmpEntry);
+                if(retVal != GT_OK)
+                {
+                    DBG_INFO(("Failed.\n"));
+                    return retVal;
+                }
+            }
+        }
+    }
+    
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgStp.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgStp.c
new file mode 100755
index 0000000..cc39c6b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgStp.c
@@ -0,0 +1,333 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtBrgStp.c
+*
+* DESCRIPTION:
+*       API definitions to handle port spanning tree state.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+static GT_STATUS enhancedBPDUSet(GT_QD_DEV *dev,GT_BOOL en)
+{
+    GT_STATUS       retVal = GT_OK; /* Functions return value.      */
+	GT_U16			enBits;
+
+	/* If disable, reset the BPDU bit(bit0) from Rsvd2CpuEnables register */
+   	if(en == GT_FALSE)
+	{
+		if((retVal = gsysGetRsvd2CpuEnables(dev,&enBits)) != GT_OK)
+		{
+	        DBG_INFO(("gsysGetRsvd2CpuEnables failed.\n"));
+			return retVal;
+		}
+		enBits &= ~0x1;
+
+		if((retVal = gsysSetRsvd2CpuEnables(dev,enBits)) != GT_OK)
+		{
+    	    DBG_INFO(("gsysSetRsvd2CpuEnables failed.\n"));
+			return retVal;
+		}
+
+		return retVal;
+	}
+
+	/* 
+		If enable, 
+		1) Set MGMT Pri bits, 
+		2) Set BPDU bit(bit0) from Rsvd2CpuEnables register,
+		3) Enable Rsvd2Cpu
+	*/
+	if((retVal = gsysSetMGMTPri(dev,7)) != GT_OK)
+	{
+        DBG_INFO(("gsysSetMGMTPri failed.\n"));
+		return retVal;
+	}
+
+	if((retVal = gsysGetRsvd2CpuEnables(dev,&enBits)) != GT_OK)
+	{
+        DBG_INFO(("gsysGetRsvd2CpuEnables failed.\n"));
+		return retVal;
+	}
+	enBits |= 0x1;
+	if((retVal = gsysSetRsvd2CpuEnables(dev,enBits)) != GT_OK)
+	{
+        DBG_INFO(("gsysSetRsvd2CpuEnables failed.\n"));
+		return retVal;
+	}
+
+	if((retVal = gsysSetRsvd2Cpu(dev,GT_TRUE)) != GT_OK)
+	{
+        DBG_INFO(("gsysSetRsvd2Cpu failed.\n"));
+		return retVal;
+	}
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gstpSetMode
+*
+* DESCRIPTION:
+*       This routine Enable the Spanning tree.
+*
+* INPUTS:
+*       en - GT_TRUE for enable, GT_FALSE for disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       when enabled, this function sets all port to blocking state, and inserts
+*       the BPDU MAC into the ATU to be captured to CPU, on disable all port are
+*       being modified to be in forwarding state.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstpSetMode
+(
+    IN GT_QD_DEV *dev,
+    IN GT_BOOL  en
+)
+{
+    GT_STATUS       retVal = GT_OK; /* Functions return value.      */
+    GT_ATU_ENTRY        atuEntry;   /* The ATU entry data to be set */
+    GT_U32          i, dbNum;
+
+    DBG_INFO(("gstpSetMode Called.\n"));
+    if(dev->deviceId == GT_88E6051)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+    if((en == GT_TRUE) && (dev->stpMode == 1))
+    {
+        DBG_INFO(("OK.\n"));
+        return GT_OK;
+    }
+
+	switch(dev->deviceId)
+	{
+		case GT_88E6051:
+		case GT_88E6052:
+			dbNum = 1;
+			break;
+		case GT_FF_HG:
+		case GT_FF_EG:
+		case GT_88E6021:
+		case GT_88E6060:
+		case GT_88E6031:
+		case GT_88E6061:
+		case GT_88E6063:
+		case GT_FH_VPN:
+		case GT_88E6083:
+		case GT_88E6153:
+		case GT_88E6181:
+		case GT_88E6183:
+		case GT_88E6093:
+			dbNum = 16;
+			break;
+		case GT_88E6035:
+		case GT_88E6055:
+		case GT_88E6065:
+			dbNum = 64;
+			break;
+		default:
+			if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST))
+			{
+				dbNum = 64;
+			}
+			else
+			{
+				dbNum = 0;
+				retVal = enhancedBPDUSet(dev,en);
+			}
+			break;
+	}
+
+	for (i=0; i<dbNum; i++)
+	{
+	    /* Set the Atu entry parameters.    */
+    	atuEntry.macAddr.arEther[0] = 0x01;
+	    atuEntry.macAddr.arEther[1] = 0x80;
+    	atuEntry.macAddr.arEther[2] = 0xC2;
+	    atuEntry.macAddr.arEther[3] = 0x00;
+    	atuEntry.macAddr.arEther[4] = 0x00;
+	    atuEntry.macAddr.arEther[5] = 0x00;
+    	atuEntry.portVec = GT_LPORTVEC_2_PORTVEC((1<<dev->cpuPortNum));
+		if(IS_IN_DEV_GROUP(dev,DEV_ATU_EXT_PRI))
+		{
+			if(IS_IN_DEV_GROUP(dev,DEV_FQPRI_IN_TABLE))
+			{
+				atuEntry.exPrio.useMacFPri = GT_TRUE;
+				atuEntry.exPrio.macFPri = 7;
+			}
+			else
+			{
+				atuEntry.exPrio.useMacFPri = 0;
+				atuEntry.exPrio.macFPri = 0;
+			}
+			atuEntry.exPrio.macQPri = 3;
+		    atuEntry.prio    = 0;
+		}
+		else
+		{
+		    atuEntry.prio    = 3;
+			atuEntry.exPrio.useMacFPri = 0;
+			atuEntry.exPrio.macFPri = 0;
+			atuEntry.exPrio.macQPri = 0;
+		}
+		atuEntry.DBNum = (GT_U8)i;
+	    atuEntry.entryState.mcEntryState = GT_MC_PRIO_MGM_STATIC;
+
+    	if(en == GT_TRUE)
+	    {
+    	    retVal = gfdbAddMacEntry(dev,&atuEntry);
+	    }
+    	else
+		{
+			if(dev->stpMode == 0)
+				break;
+        	retVal = gfdbDelAtuEntry(dev,&atuEntry);
+		}
+
+		if (retVal != GT_OK)
+			break;
+	}
+
+    if(retVal == GT_OK)
+	{
+	    if(en == GT_TRUE)
+    	    dev->stpMode = 1;
+	    else
+    	    dev->stpMode = 2;
+        DBG_INFO(("OK.\n"));
+	}
+    else
+	{
+   	    dev->stpMode = 0;
+        DBG_INFO(("Failed.\n"));
+	}
+
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gstpSetPortState
+*
+* DESCRIPTION:
+*       This routine set the port state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*       state - the port state to set.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstpSetPortState
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT           port,
+    IN GT_PORT_STP_STATE  state
+)
+{
+    GT_U8           phyPort;        /* Physical port                */
+    GT_U16          data;           /* Data to write to register.   */
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gstpSetPortState Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+    data    = state;
+
+    /* Set the port state bits.             */
+    retVal= hwSetPortRegField(dev,phyPort, QD_REG_PORT_CONTROL,0,2,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gstpGetPortState
+*
+* DESCRIPTION:
+*       This routine returns the port state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       state - the current port state.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstpGetPortState
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT           port,
+    OUT GT_PORT_STP_STATE  *state
+)
+{
+    GT_U8           phyPort;        /* Physical port                */
+    GT_U16          data;           /* Data read from register.     */
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gstpGetPortState Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* Get the port state bits.             */
+    retVal = hwGetPortRegField(dev,phyPort, QD_REG_PORT_CONTROL,0,2,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *state = data & 0x3;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgStu.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgStu.c
new file mode 100755
index 0000000..983333b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgStu.c
@@ -0,0 +1,848 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtBrgStu.c
+*
+* DESCRIPTION:
+*       API definitions for SID (VTU 802.1s Port State Information Database) 
+*		Translation Unit.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/****************************************************************************/
+/* Forward function declaration.                                            */
+/****************************************************************************/
+
+static GT_STATUS stuOperationPerform
+(
+    IN	    GT_QD_DEV           *dev,
+    IN      GT_STU_OPERATION    stuOp,
+    INOUT   GT_U8               *valid,
+    INOUT 	GT_STU_ENTRY    	*stuEntry
+);
+
+/*******************************************************************************
+* gstuGetEntryCount
+*
+* DESCRIPTION:
+*       Gets the current number of valid entries in the STU table
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       numEntries - number of STU entries.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gstuGetEntryCount
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_U32    *numEntries
+)
+{
+    GT_U8               valid;
+    GT_U32				numOfEntries;
+    GT_STATUS       	retVal;
+    GT_STU_ENTRY    	entry;
+
+    DBG_INFO(("gstuGetEntryCount Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    entry.sid = 0;
+    numOfEntries = 0;
+
+    while(1)
+    {
+		retVal = stuOperationPerform(dev,GET_NEXT_STU_ENTRY,&valid,&entry);
+		if(retVal != GT_OK)
+		{
+		    DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
+	    	return retVal;
+		}
+
+		if( entry.sid==0x3F )
+		{
+			if (valid==1) numOfEntries++;
+			break;
+		}
+
+        numOfEntries++;
+    }
+
+    *numEntries = numOfEntries;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gstuGetEntryFirst
+*
+* DESCRIPTION:
+*       Gets first lexicographic entry from the STU.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       stuEntry - find the first valid STU entry.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - table is empty.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstuGetEntryFirst
+(
+    IN  GT_QD_DEV       *dev,
+    OUT GT_STU_ENTRY    *stuEntry
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_U8       		port; 
+    GT_LPORT       		lport; 
+    GT_STU_ENTRY    	entry;
+
+    DBG_INFO(("gstuGetEntryFirst Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    entry.sid = 0;
+    valid = 0;
+
+    retVal = stuOperationPerform(dev,GET_NEXT_STU_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    /* retrieve the value from the operation */
+
+    if((entry.sid == 0x3F) && (valid == 0))
+		return GT_NO_SUCH;
+
+    stuEntry->sid = entry.sid;
+
+    for(lport=0; lport<dev->numOfPorts; lport++)
+    {
+		port = GT_LPORT_2_PORT(lport);
+		stuEntry->portState[lport]=entry.portState[port];
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gstuGetEntryNext
+*
+* DESCRIPTION:
+*       Gets next lexicographic STU entry from the specified SID.
+*
+* INPUTS:
+*       stuEntry - the SID to start the search.
+*
+* OUTPUTS:
+*       stuEntry - next STU entry.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstuGetEntryNext
+(
+    IN  GT_QD_DEV       *dev,
+    INOUT GT_STU_ENTRY  *stuEntry
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_U8       		port; 
+    GT_LPORT       		lport; 
+    GT_STU_ENTRY    	entry;
+
+    DBG_INFO(("gstuGetEntryNext Called.\n"));
+    
+    /* check if device supports this feature */
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    if(stuEntry->sid >= 0x3F)
+	{
+		return GT_NO_SUCH;
+	}
+	else
+	{
+	    entry.sid = stuEntry->sid;
+	}
+    valid = 0;
+
+    retVal = stuOperationPerform(dev,GET_NEXT_STU_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    /* retrieve the value from the operation */ 
+
+	if((entry.sid == 0x3F) && (valid == 0))
+		return GT_NO_SUCH;
+
+    stuEntry->sid = entry.sid;
+
+    for(lport=0; lport<dev->numOfPorts; lport++)
+    {
+		port = GT_LPORT_2_PORT(lport);
+		stuEntry->portState[lport]=entry.portState[port];
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gstuFindSidEntry
+*
+* DESCRIPTION:
+*       Find STU entry for a specific SID, it will return the entry, if found, 
+*       along with its associated data 
+*
+* INPUTS:
+*       stuEntry - contains the SID to searche for 
+*
+* OUTPUTS:
+*       found    - GT_TRUE, if the appropriate entry exists.
+*       stuEntry - the entry parameters.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no such entry.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Valid SID is 1 ~ 63.
+*
+*******************************************************************************/
+GT_STATUS gstuFindSidEntry
+(
+    IN  GT_QD_DEV       *dev,
+    INOUT GT_STU_ENTRY  *stuEntry,
+    OUT GT_BOOL         *found
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_U8               port;
+    GT_LPORT            lport;
+    GT_STU_ENTRY    	entry;
+
+    DBG_INFO(("gstuFindSidEntry Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    if((stuEntry->sid == 0) || (stuEntry->sid > 0x3F))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+    *found = GT_FALSE;
+
+    /* Decrement 1 from sid */
+    entry.sid   = stuEntry->sid-1;
+    valid = 0; /* valid is not used as input in this operation */
+
+    retVal = stuOperationPerform(dev,GET_NEXT_STU_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    /* retrive the value from the operation */ 
+    if ((entry.sid != stuEntry->sid) | (valid == 0))
+		return GT_NO_SUCH;
+
+    for(lport=0; lport<dev->numOfPorts; lport++)
+    {
+		port = GT_LPORT_2_PORT(lport);
+		stuEntry->portState[lport]=entry.portState[port];
+    }
+
+    *found = GT_TRUE;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gstuAddEntry
+*
+* DESCRIPTION:
+*       Creates or update the entry in STU table based on user input.
+*
+* INPUTS:
+*       stuEntry    - stu entry to insert to the STU.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK             - on success
+*       GT_FAIL           - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Valid SID is 1 ~ 63.
+*
+*******************************************************************************/
+GT_STATUS gstuAddEntry
+(
+    IN  GT_QD_DEV   	*dev,
+    IN  GT_STU_ENTRY	*stuEntry
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_U8       	port; 
+    GT_LPORT       	lport; 
+    GT_STU_ENTRY 	tmpStuEntry;
+	GT_BOOL		 	found;
+	int				count = 50000;
+    GT_STU_ENTRY    	entry;
+
+    DBG_INFO(("gstuAddEntry Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    if((stuEntry->sid == 0) || (stuEntry->sid > 0x3F))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+    entry.sid = stuEntry->sid;
+
+    valid = 1; /* for load operation */
+
+    for(port=0; port<dev->maxPorts; port++)
+    {
+		lport = GT_PORT_2_LPORT(port);
+		if (lport == GT_INVALID_PORT)
+			entry.portState[port] = 0;
+		else
+			entry.portState[port] = stuEntry->portState[lport];
+    }
+
+    retVal = stuOperationPerform(dev,LOAD_PURGE_STU_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+		DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+	/* verify that the given entry has been added */
+	tmpStuEntry.sid = stuEntry->sid;
+
+	if((retVal = gstuFindSidEntry(dev,&tmpStuEntry,&found)) != GT_OK)
+	{
+		while(count--);
+		if((retVal = gstuFindSidEntry(dev,&tmpStuEntry,&found)) != GT_OK)
+		{
+			DBG_INFO(("Added entry cannot be found\n"));
+			return retVal;
+		}
+	}
+	if(found == GT_FALSE)
+	{
+		DBG_INFO(("Added entry cannot be found\n"));
+		return GT_FAIL;
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gstuDelEntry
+*
+* DESCRIPTION:
+*       Deletes STU entry specified by user.
+*
+* INPUTS:
+*       stuEntry - the STU entry to be deleted 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Valid SID is 1 ~ 63.
+*
+*******************************************************************************/
+GT_STATUS gstuDelEntry
+(
+    IN  GT_QD_DEV   	*dev,
+    IN  GT_STU_ENTRY 	*stuEntry
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_STU_ENTRY    	entry;
+
+    DBG_INFO(("gstuDelEntry Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+    
+    if((stuEntry->sid == 0) || (stuEntry->sid > 0x3F))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+    entry.sid = stuEntry->sid;
+    valid = 0; /* for delete operation */
+
+    retVal = stuOperationPerform(dev,LOAD_PURGE_STU_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/****************************************************************************/
+/* Internal use functions.                                                  */
+/****************************************************************************/
+
+static GT_STATUS stuSetSTUData
+(
+    IN	GT_QD_DEV           *dev,
+	IN	GT_STU_ENTRY    	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data1,data2,data3;           /* Data to be set into the      */
+	GT_U16			nStuData = 0;
+
+	data1 = data2 = data3 = 0;
+
+	switch (dev->maxPorts)
+	{
+		case 11:
+			data3 |= (entry->portState[10] & 3) << 10;
+			/* pass through */
+		case 10:
+			data3 |= (entry->portState[9] & 3) << 6;
+			/* pass through */
+		case 9:
+			data3 |= (entry->portState[8] & 3) << 2;
+			nStuData++;
+
+			/* pass through */
+		case 8:
+			data2 |= (entry->portState[7] & 3) << 14;
+			/* pass through */
+		case 7:
+			data2 |= (entry->portState[6] & 3) << 10;
+			/* pass through */
+		case 6:
+			data2 |= (entry->portState[5] & 3) << 6;
+			/* pass through */
+		case 5:
+			data2 |= (entry->portState[4] & 3) << 2;
+			nStuData++;
+
+			/* pass through */
+		case 4:
+			data1 |= (entry->portState[3] & 3) << 14;
+			/* pass through */
+		case 3:
+			data1 |= (entry->portState[2] & 3) << 10;
+			/* pass through */
+		case 2:
+			data1 |= (entry->portState[1] & 3) << 6;
+			/* pass through */
+		case 1:
+			data1 |= (entry->portState[0] & 3) << 2;
+			nStuData++;
+			break;
+
+		default:
+			return GT_FAIL;
+	}
+
+	switch(nStuData)
+	{
+		case 3:
+			retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA3_REG,data3);
+			if(retVal != GT_OK)
+			{
+				return retVal;
+			}
+			/* pass through */
+		case 2:
+			retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA2_REG,data2);
+			if(retVal != GT_OK)
+			{
+				return retVal;
+			}
+			/* pass through */
+		case 1:
+			retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA1_REG,data1);
+			if(retVal != GT_OK)
+			{
+				return retVal;
+			}
+			break;
+		default:
+			return GT_FAIL;
+	}
+	
+	return retVal;		
+}
+
+static GT_STATUS stuGetSTUData
+(
+    IN	GT_QD_DEV           *dev,
+	OUT	GT_STU_ENTRY    	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data1,data2,data3;           /* Data to be set into the      */
+	GT_U16			nStuData = 0;
+
+	data1 = data2 = data3 = 0;
+
+	gtMemSet((void*)entry->portState,0,sizeof(entry->portState));
+
+	switch (dev->maxPorts)
+	{
+		case 11:
+		case 10:
+		case 9:
+			nStuData = 3;
+			break;
+
+		case 8:
+		case 7:
+		case 6:
+		case 5:
+			nStuData = 2;
+			break;
+
+		case 4:
+		case 3:
+		case 2:
+		case 1:
+			nStuData = 1;
+			break;
+
+		default:
+			return GT_FAIL;
+	}
+
+	switch(nStuData)
+	{
+		case 3:
+			retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA3_REG,&data3);
+			if(retVal != GT_OK)
+			{
+				return retVal;
+			}
+			/* pass through */
+		case 2:
+			retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA2_REG,&data2);
+			if(retVal != GT_OK)
+			{
+				return retVal;
+			}
+			/* pass through */
+		case 1:
+			retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA1_REG,&data1);
+			if(retVal != GT_OK)
+			{
+				return retVal;
+			}
+			break;
+		default:
+			return GT_FAIL;
+	}
+	
+	switch (dev->maxPorts)
+	{
+		case 11:
+			entry->portState[10]  = (data3 >> 10) & 3 ;
+			/* pass through */
+		case 10:
+			entry->portState[9]  = (data3 >> 6) & 3 ;
+			/* pass through */
+		case 9:
+			entry->portState[8]  = (data3 >> 2) & 3 ;
+			/* pass through */
+		case 8:
+			entry->portState[7]  = (data2 >> 14) & 3 ;
+			/* pass through */
+		case 7:
+			entry->portState[6]  = (data2 >> 10) & 3 ;
+			/* pass through */
+		case 6:
+			entry->portState[5]  = (data2 >> 6) & 3 ;
+			/* pass through */
+		case 5:
+			entry->portState[4]  = (data2 >> 2) & 3 ;
+			/* pass through */
+		case 4:
+			entry->portState[3]  = (data1 >> 14) & 3 ;
+			/* pass through */
+		case 3:
+			entry->portState[2]  = (data1 >> 10) & 3 ;
+			/* pass through */
+		case 2:
+			entry->portState[1]  = (data1 >> 6) & 3 ;
+			/* pass through */
+		case 1:
+			entry->portState[0]  = (data1 >> 2) & 3 ;
+			break;
+
+		default:
+			return GT_FAIL;
+	}
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* stuOperationPerform
+*
+* DESCRIPTION:
+*       This function is used by all STU control functions, and is responsible
+*       to write the required operation into the STU registers.
+*
+* INPUTS:
+*       stuOp       - The STU operation bits to be written into the STU
+*                     operation register.
+*       sid         - sid
+*       valid       - valid bit
+*       stuData     - STU Data with port state information
+*
+* OUTPUTS:
+*       sid         - sid
+*       valid       - valid bit
+*       stuData     - STU Data with port state information
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+static GT_STATUS stuOperationPerform
+(
+    IN	    GT_QD_DEV           *dev,
+    IN      GT_STU_OPERATION    stuOp,
+    INOUT   GT_U8               *valid,
+	INOUT	GT_STU_ENTRY    	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* Data to be set into the      */
+                                /* register.                    */
+
+	gtSemTake(dev,dev->vtuRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the VTU in ready. */
+	data = 1;
+    while(data == 1)
+    {
+		retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+	}
+
+	/* Set the VTU data register if Load operation is required. */
+	if (stuOp == LOAD_PURGE_STU_ENTRY)
+	{
+		if (*valid == 1)
+		{
+			/* set the Port State for all the ports */
+			retVal = stuSetSTUData(dev,entry);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+
+			/* Set the valid bit (QD_REG_VTU_VID_REG) */
+	   		data= *valid << 12 ;
+    	    retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_VID_REG),data);
+	   		if(retVal != GT_OK)
+    	    {
+	   			gtSemGive(dev,dev->vtuRegsSem);
+	    		return retVal;
+   		   	}		
+		}
+		else
+		{
+			/* Clear the valid bit (QD_REG_VTU_VID_REG) */
+	   		data= 0 ;
+    	    retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_VID_REG),data);
+	   		if(retVal != GT_OK)
+    	    {
+	   			gtSemGive(dev,dev->vtuRegsSem);
+	    		return retVal;
+   		   	}		
+		}
+    }
+
+	/* Set the SID register (QD_REG_STU_SID_REG) */
+   	data= (entry->sid) & 0x3F;
+    retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_STU_SID_REG),data);
+   	if(retVal != GT_OK)
+    {
+   		gtSemGive(dev,dev->vtuRegsSem);
+    	return retVal;
+   	}		
+
+	/* Start the STU Operation by defining the stuOp and VTUBusy */
+	data = (1 << 15) | (stuOp << 12);
+
+	retVal = hwWriteGlobalReg(dev,QD_REG_VTU_OPERATION,data);
+	if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->vtuRegsSem);
+		return retVal;
+	}
+
+	/* If the operation is a get next operation wait for the response   */
+	if(stuOp == GET_NEXT_STU_ENTRY)
+	{
+		/* Wait until the STU in ready. */
+		data = 1;
+		while(data == 1)
+		{
+			retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+		}
+
+		/****************** get the valid bit *******************/
+		retVal = hwGetGlobalRegField(dev,QD_REG_VTU_VID_REG,12,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+
+		*valid = (GT_U8)data;
+
+		/****************** get the sid *******************/
+
+		retVal = hwReadGlobalReg(dev,QD_REG_STU_SID_REG,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+
+		/* the sid is bits 0-5 */
+		entry->sid   = data & 0x3F;
+
+		if (*valid)
+		{
+			/* get the Port State for all the ports */
+			retVal = stuGetSTUData(dev,entry);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+
+		} /* entry is valid */
+
+	} /* end of get next entry */
+
+	gtSemGive(dev,dev->vtuRegsSem);
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVlan.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVlan.c
new file mode 100755
index 0000000..64a886f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVlan.c
@@ -0,0 +1,1289 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtBrgVlan.c
+*
+* DESCRIPTION:
+*       API definitions to handle port-based vlan configuration.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/*******************************************************************************
+* gprtSetEgressMode
+*
+* DESCRIPTION:
+*       This routine set the egress mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the egress mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetEgressMode
+(
+    IN GT_QD_DEV       *dev,
+    IN GT_LPORT        port,
+    IN GT_EGRESS_MODE  mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gprtSetEgressMode Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_TAGGING)) != GT_OK ) 
+      return retVal;
+	
+    switch (mode)
+    {
+        case (GT_UNMODIFY_EGRESS):
+            data = 0;
+            break;
+
+        case (GT_TAGGED_EGRESS):
+            data = 2;
+            break;
+
+        case (GT_UNTAGGED_EGRESS):
+            data = 1;
+            break;
+
+        case (GT_ADD_TAG):
+			if(!IS_IN_DEV_GROUP(dev,DEV_EGRESS_DOUBLE_TAGGING))
+			{
+		        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+				return GT_NOT_SUPPORTED;
+			}
+            data = 3;
+            break;
+        default:
+            DBG_INFO(("Failed.\n"));
+            return GT_FAIL;
+    }
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL,12,2,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gprtGetEgressMode
+*
+* DESCRIPTION:
+*       This routine get the egress mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - the egress mode.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetEgressMode
+(
+    IN GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_EGRESS_MODE  *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    if(mode == NULL)
+        return GT_BAD_PARAM;
+
+    DBG_INFO(("gprtGetEgressMode Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL,12,2,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    switch (data)
+    {
+        case (0):
+            *mode = GT_UNMODIFY_EGRESS;
+            break;
+
+        case (2):
+            *mode = GT_TAGGED_EGRESS;
+            break;
+
+        case (1):
+            *mode = GT_UNTAGGED_EGRESS;
+            break;
+
+        case (3):
+            *mode = GT_ADD_TAG;
+            break;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gprtSetVlanTunnel
+*
+* DESCRIPTION:
+*       This routine sets the vlan tunnel mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the vlan tunnel mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetVlanTunnel
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT  port,
+    IN GT_BOOL   mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gprtSetVlanTunnel Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+    BOOL_2_BIT(mode,data);
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL,7,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gprtGetVlanTunnel
+*
+* DESCRIPTION:
+*       This routine get the vlan tunnel mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - the vlan tunnel mode..
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetVlanTunnel
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gprtGetVlanTunnel Called.\n"));
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL,7,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gvlnSetPortVlanPorts
+*
+* DESCRIPTION:
+*       This routine sets the port VLAN group port membership list.
+*
+* INPUTS:
+*       port        - logical port number to set.
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVlanPorts
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT  port,
+    IN GT_LPORT  memPorts[],
+    IN GT_U8     memPortsLen
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U8           i;
+
+    DBG_INFO(("gvlnSetPortVlanPorts Called.\n"));
+    if(memPorts == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+    data = 0;
+
+	if(memPortsLen > dev->numOfPorts)
+    {
+        DBG_INFO(("Failed (PortsLen Too Big).\n"));
+        return GT_BAD_PARAM;
+    }
+
+    for(i = 0; i < memPortsLen; i++)
+        data |= (1 << GT_LPORT_2_PORT(memPorts[i]));
+
+    /* numOfPorts = 3 for fullsail, = 10 for octane, = 7 for others */
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,0,dev->maxPorts,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gvlnGetPortVlanPorts
+*
+* DESCRIPTION:
+*       This routine gets the port VLAN group port membership list.
+*
+* INPUTS:
+*       port        - logical port number to set.
+*
+* OUTPUTS:
+*       memPorts    - array of logical ports in the same vlan.
+*       memPortsLen - number of members in memPorts array
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVlanPorts
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_LPORT memPorts[],
+    OUT GT_U8    *memPortsLen
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U8           i;
+
+    DBG_INFO(("gvlnGetPortVlanPorts Called.\n"));
+    if((memPorts == NULL) || (memPortsLen == NULL))
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* memPortsLen = 3 for fullsail, =7 for others */
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,0,dev->maxPorts,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    i = 0;
+    for(phyPort = 0; phyPort < dev->maxPorts; phyPort++)
+    {
+		if(!GT_IS_PORT_SET(dev->validPortVec, phyPort))
+			continue;
+
+        if(((1 << phyPort) & data) != 0)
+        {
+            memPorts[i] = GT_PORT_2_LPORT(phyPort);
+            i++;
+        }
+    }
+    *memPortsLen = i;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gvlnSetPortUserPriLsb
+*
+* DESCRIPTION:
+*       This routine Set the user priority (VPT) LSB bit, to be added to the
+*       user priority on the egress.
+*
+* INPUTS:
+*       port       - logical port number to set.
+*       userPriLsb - GT_TRUE for 1, GT_FALSE for 0.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortUserPriLsb
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT  port,
+    IN GT_BOOL   userPriLsb
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gvlnSetPortUserPriLsb Called.\n"));
+
+	/* Gigabit Switch does not support this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+    BOOL_2_BIT(userPriLsb,data);
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PVID,13,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gvlnGetPortUserPriLsb
+*
+* DESCRIPTION:
+*       This routine gets the user priority (VPT) LSB bit.
+*
+* INPUTS:
+*       port       - logical port number to set.
+*
+* OUTPUTS:
+*       userPriLsb - GT_TRUE for 1, GT_FALSE for 0.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortUserPriLsb
+(
+    IN GT_QD_DEV    *dev,
+    IN  GT_LPORT    port,
+    OUT GT_BOOL     *userPriLsb
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gvlnGetPortUserPriLsb Called.\n"));
+
+	/* Gigabit Switch does not support this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    if(userPriLsb == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PVID,13,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*userPriLsb);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gvlnSetPortVid
+*
+* DESCRIPTION:
+*       This routine Set the port default vlan id.
+*
+* INPUTS:
+*       port - logical port number to set.
+*       vid  - the port vlan id.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVid
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_LPORT     port,
+    IN GT_U16       vid
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gvlnSetPortVid Called.\n"));
+    phyPort = GT_LPORT_2_PORT(port);
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PVID,0,12, vid);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gvlnGetPortVid
+*
+* DESCRIPTION:
+*       This routine Get the port default vlan id.
+*
+* INPUTS:
+*       port - logical port number to set.
+*
+* OUTPUTS:
+*       vid  - the port vlan id.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVid
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_U16   *vid
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gvlnGetPortVid Called.\n"));
+    if(vid == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PVID,0,12, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *vid = data;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gvlnSetPortVlanDBNum
+*
+* DESCRIPTION:
+*       This routine sets the port's default VLAN database number (DBNum or 
+*		FID, Forwarding Information Database).
+*
+* INPUTS:
+*       port	- logical port number to set.
+*       DBNum 	- database number for this port (or FID)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:IN GT_INGRESS_MODE mode
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVlanDBNum
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT  port,
+    IN GT_U32    DBNum
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gvlnSetPortVlanDBNum Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_4096))
+	{
+		if(DBNum > 4095)
+		{
+			return GT_BAD_PARAM;
+		}
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL1,0,8,(GT_U16)((DBNum & 0xFF0) >> 4));
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,12,4,(GT_U16)(DBNum & 0x000F));
+	}
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+	{
+		if(DBNum > 255)
+		{
+			return GT_BAD_PARAM;
+		}
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL1,0,4,(GT_U16)((DBNum & 0xF0) >> 4));
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,12,4,(GT_U16)(DBNum & 0x0F));
+	}
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+	{
+		if(DBNum > 63)
+		{
+			return GT_BAD_PARAM;
+		}
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,6,2,(GT_U16)((DBNum & 0x30) >> 4));
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,12,4,(GT_U16)(DBNum & 0x0F));
+	}
+	else
+	{
+		if(DBNum > 15)
+		{
+			return GT_BAD_PARAM;
+		}
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,12,4,(GT_U16)(DBNum & 0x0F));
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gvlnGetPortVlanDBNum
+*
+* DESCRIPTION:
+*       This routine gets the port's default VLAN database number (DBNum or
+*		FID, Forwarding Information Database).
+*
+* INPUTS:
+*       port 	- logical port number to get.
+*
+* OUTPUTS:
+*       DBNum 	- database number for this port (or FID)
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVlanDBNum
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_U32   *DBNum
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data,dataH;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gvlnGetPortVlanDBNum Called.\n"));
+
+    if(DBNum == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_4096))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL1,0,8, &dataH);
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,12,4, &data);
+	}
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL1,0,4, &dataH);
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,12,4, &data);
+	}
+	else if(IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,6,2, &dataH);
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,12,4, &data);
+	}
+	else
+	{
+		dataH = 0;
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,12,4, &data);
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *DBNum = (GT_U32)(data | (dataH << 4));
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/********************************************************************
+* gvlnSetPortVlanDot1qMode
+*
+* DESCRIPTION:
+*       This routine sets the IEEE 802.1q mode for this port (11:10) 
+*
+* INPUTS:
+*       port	- logical port number to set.
+*       mode 	- 802.1q mode for this port 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:IN GT_INGRESS_MODE mode
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVlanDot1qMode
+(
+    IN GT_QD_DEV        *dev,
+    IN GT_LPORT 	port,
+    IN GT_DOT1Q_MODE	mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gvlnSetPortVlanDot1qMode Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_802_1Q)) != GT_OK ) 
+      return retVal;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL2,10,2,(GT_U16)mode );
+	}
+	else
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,10,2,(GT_U16)mode );
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gvlnGetPortVlanDot1qMode
+*
+* DESCRIPTION:
+*       This routine gets the IEEE 802.1q mode for this (bit 11:10).
+*
+* INPUTS:
+*       port 	- logical port number to get.
+*
+* OUTPUTS:
+*       mode 	- 802.1q mode for this port 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVlanDot1qMode
+(
+    IN GT_QD_DEV        *dev,
+    IN  GT_LPORT        port,
+    OUT GT_DOT1Q_MODE   *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gvlnGetPortVlanDot1qMode Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_802_1Q)) != GT_OK ) 
+      return retVal;
+
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_CONTROL2,10,2, &data);
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_VLAN_MAP,10,2, &data);
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *mode = data;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/********************************************************************
+* gvlnSetPortVlanForceDefaultVID
+*
+* DESCRIPTION:
+*       This routine sets the mode for forcing to use default VID
+*
+* INPUTS:
+*       port    - logical port number to set.
+*       mode    - GT_TRUE, force to use default VID
+*                 GT_FAULSE, otherwise 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnSetPortVlanForceDefaultVID
+(
+    IN GT_QD_DEV        *dev,
+    IN GT_LPORT 	port,
+    IN GT_BOOL  	mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U16          data;           /* Data to be set into the      */
+
+    DBG_INFO(("gvlnSetPortForceDefaultVID Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_802_1Q)) != GT_OK ) 
+      return retVal;
+
+    BOOL_2_BIT(mode,data);
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PVID,12,1,data );
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gvlnGetPortVlanForceDefaultVID
+*
+* DESCRIPTION:
+*       This routine gets the port mode for ForceDefaultVID (bit 12).
+*
+* INPUTS:
+*       port 	- logical port number to get.
+*
+* OUTPUTS:
+*       mode 	- ForceDefaultVID mode for this port 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvlnGetPortVlanForceDefaultVID
+(
+    IN GT_QD_DEV        *dev,
+    IN  GT_LPORT 	port,
+    OUT GT_BOOL    	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+
+    DBG_INFO(("gvlnGetPortVlanDot1qMode Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_802_1Q)) != GT_OK ) 
+      return retVal;
+
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PVID,12,1, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/********************************************************************
+* gvlnSetForceMap
+*
+* DESCRIPTION:
+*       This routine enables/disables Force Map feature.
+*		When Force Map feature is enabled, all received frames will be
+*		considered MGMT and they are mapped to the port or ports defined
+*		in the VLAN Table overriding the mapping from the address database.
+*
+* INPUTS:
+*       port    - logical port number to set.
+*       mode    - GT_TRUE, to enable force map feature
+*                 GT_FAULSE, otherwise 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gvlnSetForceMap
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT 	port,
+    IN  GT_BOOL  	mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U16          data;           /* Data to be set into the reg  */
+
+    DBG_INFO(("gvlnSetForceMap Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_MAP))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+    BOOL_2_BIT(mode,data);
+
+    retVal = hwSetPortRegField(dev,phyPort, QD_REG_PORT_VLAN_MAP, 8, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+
+/********************************************************************
+* gvlnGetForceMap
+*
+* DESCRIPTION:
+*       This routine checks if Force Map feature is enabled.
+*		When Force Map feature is enabled, all received frames will be
+*		considered MGMT and they are mapped to the port or ports defined
+*		in the VLAN Table overriding the mapping from the address database.
+*
+* INPUTS:
+*       port    - logical port number to set.
+*
+* OUTPUTS:
+*       mode    - GT_TRUE, to enable force map feature
+*                 GT_FAULSE, otherwise 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gvlnGetForceMap
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT 	port,
+    OUT GT_BOOL  	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U16          data;           /* Data to be set into the reg  */
+
+    DBG_INFO(("gvlnGetForceMap Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_MAP))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+    retVal = hwGetPortRegField(dev,phyPort, QD_REG_PORT_VLAN_MAP, 8, 1, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data, *mode);
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gvlnSetNoEgrPolicy
+*
+* DESCRIPTION:
+*		No Egress Policy. When this bit is set to a one Egress 802.1Q Secure and
+*		Check discards are not performed. This mode allowsa non-802.1Q enabled 
+*		port to send a frame to an 802.1Q enabled port that is configured in the
+*		Secure or Check 802.1Q mode. In this situation the frames will egress 
+*		even if the VID assigned to the frame is not found in the VTU.
+*
+* INPUTS:
+*		mode - no egress policy mode
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gvlnSetNoEgrPolicy
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+
+    DBG_INFO(("gvlnSetNoEgrPolicy Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_NO_EGRESS_POLICY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(mode,data);
+
+    /* Set related register */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_SDET_POLARITY,13,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gvlnGetNoEgrPolicy
+*
+* DESCRIPTION:
+*		No Egress Policy. When this bit is set to a one Egress 802.1Q Secure and
+*		Check discards are not performed. This mode allowsa non-802.1Q enabled 
+*		port to send a frame to an 802.1Q enabled port that is configured in the
+*		Secure or Check 802.1Q mode. In this situation the frames will egress 
+*		even if the VID assigned to the frame is not found in the VTU.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - no egress policy mode
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gvlnGetNoEgrPolicy
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gvlnGetNoEgrPolicy Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_NO_EGRESS_POLICY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related register */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_SDET_POLARITY,13,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*mode);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVtu.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVtu.c
new file mode 100755
index 0000000..efe1f05
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtBrgVtu.c
@@ -0,0 +1,1531 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtBrgVtu.c
+*
+* DESCRIPTION:
+*       API definitions for Vlan Translation Unit for 802.1Q.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 9 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/****************************************************************************/
+/* Forward function declaration.                                            */
+/****************************************************************************/
+#define MEMBER_TAG_CONV_FOR_APP(_dev,_tag)	memberTagConversionForApp(_dev,_tag)
+#define MEMBER_TAG_CONV_FOR_DEV(_dev,_tag)	memberTagConversionForDev(_dev,_tag)
+
+static GT_U8 memberTagConversionForApp
+(
+    IN	GT_QD_DEV           *dev,
+    IN	GT_U8               tag
+)
+{
+	GT_U8 convTag;
+
+	/* check if memberTag needs to be converted */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+		return tag;
+
+	switch(tag)
+	{
+		case 0:
+				convTag = MEMBER_EGRESS_UNMODIFIED;
+				break;
+		case 1:
+				convTag = MEMBER_EGRESS_UNTAGGED;
+				break;
+		case 2:
+				convTag = MEMBER_EGRESS_TAGGED;
+				break;
+		case 3:
+				convTag = NOT_A_MEMBER;
+				break;
+		default:
+				DBG_INFO(("Unknown Tag (%#x) from Device !!!.\n",tag));
+				convTag = 0xFF;
+				break;
+			
+	}
+
+	return convTag;
+}
+
+static GT_U8 memberTagConversionForDev
+(
+    IN	GT_QD_DEV           *dev,
+    IN	GT_U8               tag
+)
+{
+	GT_U8 convTag;
+
+	/* check if memberTag needs to be converted */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+		return tag;
+
+	switch(tag)
+	{
+		case MEMBER_EGRESS_UNMODIFIED:
+				convTag = 0;
+				break;
+		case NOT_A_MEMBER:
+				convTag = 3;
+				break;
+		case MEMBER_EGRESS_UNTAGGED:
+				convTag = 1;
+				break;
+		case MEMBER_EGRESS_TAGGED:
+				convTag = 2;
+				break;
+		default:
+				DBG_INFO(("Unknown Tag (%#x) from App. !!!.\n",tag));
+				convTag = 0xFF;
+				break;
+			
+	}
+
+	return convTag;
+}
+
+static GT_STATUS vtuOperationPerform
+(
+    IN	    GT_QD_DEV           *dev,
+    IN      GT_VTU_OPERATION    vtuOp,
+    INOUT   GT_U8               *valid,
+    INOUT 	GT_VTU_ENTRY    	*vtuEntry
+);
+
+/*******************************************************************************
+* gvtuGetEntryCount
+*
+* DESCRIPTION:
+*       Gets the current number of valid entries in the VTU table
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       numEntries - number of VTU entries.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - vlan does not exist.
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetEntryCount
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_U32    *numEntries
+)
+{
+    GT_U8               valid;
+    GT_U32		numOfEntries;
+    GT_STATUS       	retVal;
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuGetEntryCount Called.\n"));
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
+      return retVal;
+
+    entry.vid = 0xFFF;
+    entry.DBNum = 0;
+
+    numOfEntries = 0;
+    while(1)
+    {
+		retVal = vtuOperationPerform(dev,GET_NEXT_ENTRY,&valid,&entry);
+		if(retVal != GT_OK)
+		{
+		    DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+	    	return retVal;
+		}
+
+		if( entry.vid==0xFFF )
+		{
+			if (valid==1) numOfEntries++;
+			break;
+		}
+
+        numOfEntries++;
+    }
+
+    *numEntries = numOfEntries;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gvtuGetEntryFirst
+*
+* DESCRIPTION:
+*       Gets first lexicographic entry from the VTU.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       vtuEntry - match VTU entry.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NO_SUCH - table is empty.
+*
+* COMMENTS:
+*       Search starts from vid of all one's
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetEntryFirst
+(
+    IN  GT_QD_DEV       *dev,
+    OUT GT_VTU_ENTRY    *vtuEntry
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_U8       		port; 
+    GT_LPORT       		lport; 
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuGetEntryFirst Called.\n"));
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
+      return retVal;
+
+    entry.vid = 0xFFF;
+    entry.DBNum = 0;
+
+    retVal = vtuOperationPerform(dev,GET_NEXT_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    /* retrive the value from the operation */ 
+
+    if((entry.vid == 0xFFF) && (valid == 0))
+		return GT_NO_SUCH;
+
+    vtuEntry->DBNum = entry.DBNum;
+    vtuEntry->vid   = entry.vid;
+
+	vtuEntry->vidPriOverride = entry.vidPriOverride;
+	vtuEntry->vidPriority = entry.vidPriority;
+
+	vtuEntry->vidPolicy = entry.vidPolicy;
+	vtuEntry->sid = entry.sid;
+
+	vtuEntry->vidExInfo.useVIDFPri = entry.vidExInfo.useVIDFPri;
+	vtuEntry->vidExInfo.vidFPri = entry.vidExInfo.vidFPri;
+	vtuEntry->vidExInfo.useVIDQPri = entry.vidExInfo.useVIDQPri;
+	vtuEntry->vidExInfo.vidQPri = entry.vidExInfo.vidQPri;
+	vtuEntry->vidExInfo.vidNRateLimit = entry.vidExInfo.vidNRateLimit;
+
+    for(lport=0; lport<dev->numOfPorts; lport++)
+    {
+		port = GT_LPORT_2_PORT(lport);
+		vtuEntry->vtuData.memberTagP[lport]=MEMBER_TAG_CONV_FOR_APP(dev,entry.vtuData.memberTagP[port]);
+		vtuEntry->vtuData.portStateP[lport]=entry.vtuData.portStateP[port];
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gvtuGetEntryNext
+*
+* DESCRIPTION:
+*       Gets next lexicographic VTU entry from the specified VID.
+*
+* INPUTS:
+*       vtuEntry - the VID to start the search.
+*
+* OUTPUTS:
+*       vtuEntry - match VTU  entry.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*
+* COMMENTS:
+*       Search starts from the VID specified by the user.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetEntryNext
+(
+    IN  GT_QD_DEV       *dev,
+    INOUT GT_VTU_ENTRY  *vtuEntry
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_U8       		port; 
+    GT_LPORT       		lport; 
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuGetEntryNext Called.\n"));
+    
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
+      return retVal;
+
+    entry.DBNum = vtuEntry->DBNum;
+    entry.vid   = vtuEntry->vid;
+    valid = 0;
+
+    retVal = vtuOperationPerform(dev,GET_NEXT_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    /* retrieve the value from the operation */ 
+
+	if((entry.vid == 0xFFF) && (valid == 0))
+		return GT_NO_SUCH;
+
+    vtuEntry->DBNum = entry.DBNum;
+    vtuEntry->vid   = entry.vid;
+
+	vtuEntry->vidPriOverride = entry.vidPriOverride;
+	vtuEntry->vidPriority = entry.vidPriority;
+
+	vtuEntry->vidPolicy = entry.vidPolicy;
+	vtuEntry->sid = entry.sid;
+
+	vtuEntry->vidExInfo.useVIDFPri = entry.vidExInfo.useVIDFPri;
+	vtuEntry->vidExInfo.vidFPri = entry.vidExInfo.vidFPri;
+	vtuEntry->vidExInfo.useVIDQPri = entry.vidExInfo.useVIDQPri;
+	vtuEntry->vidExInfo.vidQPri = entry.vidExInfo.vidQPri;
+	vtuEntry->vidExInfo.vidNRateLimit = entry.vidExInfo.vidNRateLimit;
+
+    for(lport=0; lport<dev->numOfPorts; lport++)
+    {
+		port = GT_LPORT_2_PORT(lport);
+		vtuEntry->vtuData.memberTagP[lport]=MEMBER_TAG_CONV_FOR_APP(dev,entry.vtuData.memberTagP[port]);
+		vtuEntry->vtuData.portStateP[lport]=entry.vtuData.portStateP[port];
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gvtuFindVidEntry
+*
+* DESCRIPTION:
+*       Find VTU entry for a specific VID, it will return the entry, if found, 
+*       along with its associated data 
+*
+* INPUTS:
+*       vtuEntry - contains the VID to searche for 
+*
+* OUTPUTS:
+*       found    - GT_TRUE, if the appropriate entry exists.
+*       vtuEntry - the entry parameters.
+*
+* RETURNS:
+*       GT_OK      - on success.
+*       GT_FAIL    - on error or entry does not exist.
+*       GT_NO_SUCH - no more entries.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuFindVidEntry
+(
+    IN  GT_QD_DEV       *dev,
+    INOUT GT_VTU_ENTRY  *vtuEntry,
+    OUT GT_BOOL         *found
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_U8               port;
+    GT_LPORT            lport;
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuFindVidEntry Called.\n"));
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
+      return retVal;
+
+    *found = GT_FALSE;
+
+    /* Decrement 1 from vid    */
+    entry.vid   = vtuEntry->vid-1;
+    valid = 0; /* valid is not used as input in this operation */
+    entry.DBNum = vtuEntry->DBNum;
+
+    retVal = vtuOperationPerform(dev,GET_NEXT_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+    /* retrive the value from the operation */ 
+
+    if( (entry.vid !=vtuEntry->vid) | (valid !=1) )
+    {
+          DBG_INFO(("Failed.\n"));
+          return GT_NO_SUCH;
+    }
+
+    vtuEntry->DBNum = entry.DBNum;
+
+	vtuEntry->vidPriOverride = entry.vidPriOverride;
+	vtuEntry->vidPriority = entry.vidPriority;
+
+	vtuEntry->vidPolicy = entry.vidPolicy;
+	vtuEntry->sid = entry.sid;
+
+	vtuEntry->vidExInfo.useVIDFPri = entry.vidExInfo.useVIDFPri;
+	vtuEntry->vidExInfo.vidFPri = entry.vidExInfo.vidFPri;
+	vtuEntry->vidExInfo.useVIDQPri = entry.vidExInfo.useVIDQPri;
+	vtuEntry->vidExInfo.vidQPri = entry.vidExInfo.vidQPri;
+	vtuEntry->vidExInfo.vidNRateLimit = entry.vidExInfo.vidNRateLimit;
+
+    for(lport=0; lport<dev->numOfPorts; lport++)
+    {
+		port = GT_LPORT_2_PORT(lport);
+		vtuEntry->vtuData.memberTagP[lport]=MEMBER_TAG_CONV_FOR_APP(dev,entry.vtuData.memberTagP[port]);
+		vtuEntry->vtuData.portStateP[lport]=entry.vtuData.portStateP[port];
+    }
+
+    *found = GT_TRUE;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gvtuFlush
+*
+* DESCRIPTION:
+*       This routine removes all entries from VTU Table.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuFlush
+(
+    IN  GT_QD_DEV       *dev
+)
+{
+    GT_STATUS       retVal;
+
+    DBG_INFO(("gvtuFlush Called.\n"));
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK)
+	{
+		return retVal;
+	}
+
+    retVal = vtuOperationPerform(dev,FLUSH_ALL,NULL,NULL);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gvtuAddEntry
+*
+* DESCRIPTION:
+*       Creates the new entry in VTU table based on user input.
+*
+* INPUTS:
+*       vtuEntry    - vtu entry to insert to the VTU.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK             - on success
+*       GT_FAIL           - on error
+*       GT_FULL			  - vtu table is full
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuAddEntry
+(
+    IN  GT_QD_DEV   *dev,
+    IN GT_VTU_ENTRY *vtuEntry
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_U8       	port; 
+    GT_LPORT       	lport; 
+    GT_VTU_ENTRY 	tmpVtuEntry;
+	GT_BOOL		 	found;
+	int				count = 5000;
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuAddEntry Called.\n"));
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
+      return retVal;
+
+    entry.DBNum = vtuEntry->DBNum;
+    entry.vid   = vtuEntry->vid;
+
+	if(IS_IN_DEV_GROUP(dev,DEV_VTU_EXT_INFO))
+	{
+		entry.vidPriOverride = 0;
+		entry.vidPriority = 0;
+
+		entry.vidPolicy = GT_FALSE;
+		entry.sid = 0;
+
+		if(IS_IN_DEV_GROUP(dev,DEV_FQPRI_IN_TABLE))
+		{
+			entry.vidExInfo.useVIDFPri = vtuEntry->vidExInfo.useVIDFPri;
+			entry.vidExInfo.vidFPri = vtuEntry->vidExInfo.vidFPri;
+			entry.vidExInfo.useVIDQPri = vtuEntry->vidExInfo.useVIDQPri;
+			entry.vidExInfo.vidQPri = vtuEntry->vidExInfo.vidQPri;
+			entry.vidExInfo.vidNRateLimit = vtuEntry->vidExInfo.vidNRateLimit;
+		}
+		else
+		{
+			entry.vidExInfo.useVIDFPri = 0;
+			entry.vidExInfo.vidFPri = 0;
+			entry.vidExInfo.useVIDQPri = 0;
+			entry.vidExInfo.vidQPri = 0;
+			entry.vidExInfo.vidNRateLimit = vtuEntry->vidExInfo.vidNRateLimit;
+		}
+	}
+	else
+	{
+		entry.vidPriOverride = vtuEntry->vidPriOverride;
+		entry.vidPriority = vtuEntry->vidPriority;
+
+		if(IS_IN_DEV_GROUP(dev,DEV_POLICY))
+		{
+			entry.vidPolicy = vtuEntry->vidPolicy;
+		}
+		else
+		{
+			entry.vidPolicy = GT_FALSE;
+		}
+
+		if(IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+		{
+			entry.sid = vtuEntry->sid;
+		}
+		else
+		{
+			entry.sid = 0;
+		}
+
+		entry.vidExInfo.useVIDFPri = 0;
+		entry.vidExInfo.vidFPri = 0;
+		entry.vidExInfo.useVIDQPri = 0;
+		entry.vidExInfo.vidQPri = 0;
+		entry.vidExInfo.vidNRateLimit = 0;
+	}
+
+    valid = 1; /* for load operation */
+
+    for(port=0; port<dev->maxPorts; port++)
+    {
+		lport = GT_PORT_2_LPORT(port);
+		if(lport == GT_INVALID_PORT)
+		{
+			entry.vtuData.memberTagP[port] = MEMBER_TAG_CONV_FOR_DEV(dev,NOT_A_MEMBER);
+			entry.vtuData.portStateP[port] = 0;
+		}
+		else
+		{
+			entry.vtuData.memberTagP[port] = MEMBER_TAG_CONV_FOR_DEV(dev,vtuEntry->vtuData.memberTagP[lport]);
+			if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
+				entry.vtuData.portStateP[port] = vtuEntry->vtuData.portStateP[lport];
+			else
+				entry.vtuData.portStateP[port] = 0;
+		}
+    }
+
+    retVal = vtuOperationPerform(dev,LOAD_PURGE_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+		DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+	/* verify that the given entry has been added */
+	tmpVtuEntry.vid = vtuEntry->vid;
+	tmpVtuEntry.DBNum = vtuEntry->DBNum;
+
+	if((retVal = gvtuFindVidEntry(dev,&tmpVtuEntry,&found)) != GT_OK)
+	{
+		while(count--);
+		if((retVal = gvtuFindVidEntry(dev,&tmpVtuEntry,&found)) != GT_OK)
+		{
+			DBG_INFO(("Added entry cannot be found\n"));
+			return retVal;
+		}
+	}
+	if(found == GT_FALSE)
+	{
+		DBG_INFO(("Added entry cannot be found\n"));
+		return GT_FAIL;
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gvtuDelEntry
+*
+* DESCRIPTION:
+*       Deletes VTU entry specified by user.
+*
+* INPUTS:
+*       vtuEntry - the VTU entry to be deleted 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NO_SUCH      - if specified address entry does not exist
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuDelEntry
+(
+    IN  GT_QD_DEV   *dev,
+    IN GT_VTU_ENTRY *vtuEntry
+)
+{
+    GT_U8               valid;
+    GT_STATUS       	retVal;
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuDelEntry Called.\n"));
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
+      return retVal;
+    
+    entry.DBNum = vtuEntry->DBNum;
+    entry.vid   = vtuEntry->vid;
+    valid = 0; /* for delete operation */
+
+    retVal = vtuOperationPerform(dev,LOAD_PURGE_ENTRY,&valid, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/****************************************************************************/
+/* Internal use functions.                                                  */
+/****************************************************************************/
+
+/*******************************************************************************
+* gvtuGetViolation
+*
+* DESCRIPTION:
+*       Get VTU Violation data
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       vtuIntStatus - interrupt cause, source portID, and vid.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORT  - if current device does not support this feature.
+*
+* COMMENTS:
+*		This is an internal function. No user should call this function.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetViolation
+(
+    IN  GT_QD_DEV         *dev,
+    OUT GT_VTU_INT_STATUS *vtuIntStatus
+)
+{
+    GT_U8               spid;
+    GT_U16               vid;
+    GT_U16               intCause;
+    GT_STATUS       	retVal;
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuGetViolation Called.\n"));
+
+	/* check which Violation occurred */
+    retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,4,3,&intCause);
+    if(retVal != GT_OK)
+    {
+	    DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
+        return retVal;
+    }
+
+	if (intCause == 0)
+	{
+		/* No Violation occurred. */
+		vtuIntStatus->vtuIntCause = 0;
+		return GT_OK;
+	}
+
+    entry.DBNum = 0;
+
+    retVal = vtuOperationPerform(dev,SERVICE_VIOLATIONS,NULL, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+	spid = entry.DBNum & 0xF;
+	vid = entry.vid;
+
+	if(spid == 0xF)
+	{
+		vtuIntStatus->vtuIntCause = GT_VTU_FULL_VIOLATION;
+		vtuIntStatus->spid = spid;
+		vtuIntStatus->vid = 0;
+	}
+	else
+	{
+		vtuIntStatus->vtuIntCause = intCause & (GT_MEMBER_VIOLATION | GT_MISS_VIOLATION);
+		vtuIntStatus->spid = spid;
+		vtuIntStatus->vid = vid;
+	}
+	
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gvtuGetViolation2
+*
+* DESCRIPTION:
+*       Get VTU Violation data (for Gigabit Device)
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       vtuIntStatus - interrupt cause, source portID, and vid.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORT  - if current device does not support this feature.
+*
+* COMMENTS:
+*		This is an internal function. No user should call this function.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetViolation2
+(
+    IN  GT_QD_DEV         *dev,
+    OUT GT_VTU_INT_STATUS *vtuIntStatus
+)
+{
+    GT_U16               intCause;
+    GT_STATUS       	retVal;
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuGetViolation2 Called.\n"));
+
+	/* check if Violation occurred */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,5,1,&intCause);
+    if(retVal != GT_OK)
+    {
+	    DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
+        return retVal;
+    }
+
+	if (intCause == 0)
+	{
+		/* No Violation occurred. */
+		vtuIntStatus->vtuIntCause = 0;
+		return GT_OK;
+	}
+
+    entry.DBNum = 0;
+
+    retVal = vtuOperationPerform(dev,SERVICE_VIOLATIONS,NULL, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+	/* check which Violation occurred */
+    retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,5,2,&intCause);
+    if(retVal != GT_OK)
+    {
+	    DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
+        return retVal;
+    }
+
+	switch (intCause)
+	{
+		case 0:
+			/* No Violation occurred. */
+			vtuIntStatus->vtuIntCause = 0;
+			return GT_OK;
+		case 1:
+			/* Miss Violation */
+			vtuIntStatus->vtuIntCause = GT_MISS_VIOLATION;
+			break;
+		case 2:
+			/* Member Violation */
+			vtuIntStatus->vtuIntCause = GT_MEMBER_VIOLATION;
+			break;
+		default :
+			return GT_FAIL;
+	}
+
+	vtuIntStatus->spid = entry.DBNum & 0xF;
+	vtuIntStatus->vid = entry.vid;
+	
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gvtuGetViolation3
+*
+* DESCRIPTION:
+*       Get VTU Violation data
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       vtuIntStatus - interrupt cause, source portID, and vid.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*       GT_NOT_SUPPORT  - if current device does not support this feature.
+*
+* COMMENTS:
+*		This is an internal function. No user should call this function.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gvtuGetViolation3
+(
+    IN  GT_QD_DEV         *dev,
+    OUT GT_VTU_INT_STATUS *vtuIntStatus
+)
+{
+    GT_U16               intCause;
+    GT_STATUS       	retVal;
+    GT_VTU_ENTRY    	entry;
+
+    DBG_INFO(("gvtuGetViolation3 Called.\n"));
+
+	/* check if Violation occurred */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,5,1,&intCause);
+    if(retVal != GT_OK)
+    {
+	    DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
+        return retVal;
+    }
+
+	if (intCause == 0)
+	{
+		/* No Violation occurred. */
+		vtuIntStatus->vtuIntCause = 0;
+		return GT_OK;
+	}
+
+    entry.DBNum = 0;
+
+    retVal = vtuOperationPerform(dev,SERVICE_VIOLATIONS,NULL, &entry);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
+        return retVal;
+    }
+
+	/* check which Violation occurred */
+    retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,4,3,&intCause);
+    if(retVal != GT_OK)
+    {
+	    DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
+        return retVal;
+    }
+
+	vtuIntStatus->vtuIntCause = 0;
+
+	if(intCause & 0x1)
+	{
+		vtuIntStatus->vtuIntCause |= GT_VTU_FULL_VIOLATION;
+	}
+
+	if(intCause & 0x2)
+	{
+		vtuIntStatus->vtuIntCause |= GT_MISS_VIOLATION;
+	}
+
+	if(intCause & 0x4)
+	{
+		vtuIntStatus->vtuIntCause |= GT_MEMBER_VIOLATION;
+	}
+			
+	vtuIntStatus->spid = entry.DBNum & 0xF;
+	vtuIntStatus->vid = entry.vid;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* vtuOperationPerform
+*
+* DESCRIPTION:
+*       This function is used by all VTU control functions, and is responsible
+*       to write the required operation into the VTU registers.
+*
+* INPUTS:
+*       vtuOp       - The VTU operation bits to be written into the VTU
+*                     operation register.
+*       DBNum       - DBNum where the given vid belongs to
+*       vid         - vlan id
+*       valid       - valid bit
+*       vtuData     - VTU Data with memberTag information
+*
+* OUTPUTS:
+*       DBNum       - DBNum where the given vid belongs to
+*       vid         - vlan id
+*       valid       - valid bit
+*       vtuData     - VTU Data with memberTag information
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+static GT_STATUS vtuOperationPerform
+(
+    IN	    GT_QD_DEV           *dev,
+    IN      GT_VTU_OPERATION    vtuOp,
+    INOUT   GT_U8               *valid,
+	INOUT	GT_VTU_ENTRY    	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* Data to be set into the      */
+                                /* register.                    */
+
+	gtSemTake(dev,dev->vtuRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the VTU in ready. */
+	data = 1;
+    while(data == 1)
+    {
+		retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+	}
+
+	/* Set the VTU data register    */
+	/* There is no need to setup data reg. on flush, get next, or service violation */
+	if((vtuOp != FLUSH_ALL) && (vtuOp != GET_NEXT_ENTRY) && (vtuOp != SERVICE_VIOLATIONS))
+	{
+
+		/****************** VTU DATA 1 REG *******************/
+
+		/* get data and wirte to QD_REG_VTU_DATA1_REG (ports 0 to 3) */
+
+		data =  (entry->vtuData.memberTagP[0] & 3)     |
+				((entry->vtuData.memberTagP[1] & 3)<<4) | 
+				((entry->vtuData.memberTagP[2] & 3)<<8);
+
+		if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
+			data |= ((entry->vtuData.portStateP[0] & 3)<<2)	|
+					((entry->vtuData.portStateP[1] & 3)<<6) | 
+					((entry->vtuData.portStateP[2] & 3)<<10);
+			
+		if(dev->maxPorts > 3)
+		{
+			data |= ((entry->vtuData.memberTagP[3] & 3)<<12) ;
+			if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
+				data |= ((entry->vtuData.portStateP[3] & 3)<<14) ;
+		}
+
+		retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA1_REG,data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+
+		/****************** VTU DATA 2 REG *******************/
+
+		/* get data and wirte to QD_REG_VTU_DATA2_REG (ports 4 to 7) */
+
+		if(dev->maxPorts > 4)
+		{
+			/* also need to set data register  ports 4 to 6 */
+
+			data =  (entry->vtuData.memberTagP[4] & 3)   |
+					((entry->vtuData.memberTagP[5] & 3) << 4);
+
+			if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
+				data |= ((entry->vtuData.portStateP[4] & 3) << 2) |
+						((entry->vtuData.portStateP[5] & 3) << 6); 
+
+			if(dev->maxPorts > 6)
+			{
+				data |= ((entry->vtuData.memberTagP[6] & 3)<<8) ;
+				if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
+					data |= ((entry->vtuData.portStateP[6] & 3)<<10) ;
+			}
+
+			if(dev->maxPorts > 7)
+			{
+				data |= ((entry->vtuData.memberTagP[7] & 3)<<12) ;
+				if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
+					data |= ((entry->vtuData.portStateP[7] & 3)<<14) ;
+			}
+
+			if (IS_IN_DEV_GROUP(dev,DEV_VTU_EXT_INFO))
+			{
+				if(entry->vidExInfo.useVIDFPri == GT_TRUE)
+					data |= ((1 << 15) | ((entry->vidExInfo.vidFPri & 0x7) << 12));
+				if(entry->vidExInfo.useVIDQPri == GT_TRUE)
+					data |= ((1 << 11) | ((entry->vidExInfo.vidQPri & 0x3) << 9));
+				if(entry->vidExInfo.vidNRateLimit == GT_TRUE)
+					data |= (1 << 8);
+			}
+
+			retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA2_REG,data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+		}
+
+
+		/****************** VTU DATA 3 REG *******************/
+
+		/* get data and wirte to QD_REG_VTU_DATA3_REG (ports 8 to 10) */
+
+		if(dev->maxPorts > 7)
+		{
+			/* also need to set data register  ports 8 to 9 */
+
+			data =  (entry->vtuData.memberTagP[8] & 3)   |
+					((entry->vtuData.memberTagP[9] & 3) << 4);
+
+			if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
+				data |= ((entry->vtuData.portStateP[8] & 3) << 2)	|
+						((entry->vtuData.portStateP[9] & 3) << 6);
+
+			if(dev->maxPorts > 10)
+			{
+				data |= (entry->vtuData.memberTagP[10] & 3) << 8;
+
+				if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
+					data |= (entry->vtuData.portStateP[10] & 3) << 10;
+			}
+			
+			if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+			{
+				if(entry->vidPriOverride == GT_TRUE)
+					data |= ((1 << 15) | ((entry->vidPriority & 0x7) << 12));
+			}
+
+			retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA3_REG,data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+		}
+		else if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+		{
+			if(entry->vidPriOverride == GT_TRUE)
+				data = ((1 << 15) | ((entry->vidPriority & 0x7) << 12));
+			else
+				data = 0;
+
+			retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA3_REG,data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+		}
+    }
+
+	/* Set the VID register (QD_REG_VTU_VID_REG) */
+	/* There is no need to setup VID reg. on flush and service violation */
+	if((vtuOp != FLUSH_ALL) && (vtuOp != SERVICE_VIOLATIONS) )
+	{
+    	data= ( (entry->vid) & 0xFFF ) | ( (*valid) << 12 );
+	    retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_VID_REG),data);
+    	if(retVal != GT_OK)
+	    {
+    		gtSemGive(dev,dev->vtuRegsSem);
+	    	return retVal;
+    	}		
+	}
+
+	/* Set SID, FID, VIDPolicy, if it's Load operation */
+	if((vtuOp == LOAD_PURGE_ENTRY) && (*valid == 1))
+	{
+		if(IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+		{
+	    	data= (entry->sid) & 0x3F;
+		    retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_STU_SID_REG),data);
+    		if(retVal != GT_OK)
+		    {
+    			gtSemGive(dev,dev->vtuRegsSem);
+	    		return retVal;
+	    	}		
+		}
+
+		data = 0;
+
+		if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
+		{
+			if(IS_IN_DEV_GROUP(dev,DEV_POLICY))
+			{
+	    		data= entry->vidPolicy << 12;
+			}
+
+	    	data |= (entry->DBNum & 0xFFF);
+
+		    retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_FID_REG),data);
+    		if(retVal != GT_OK)
+		    {
+    			gtSemGive(dev,dev->vtuRegsSem);
+	    		return retVal;
+	    	}		
+		}
+
+
+	}
+
+	/* Start the VTU Operation by defining the DBNum, vtuOp and VTUBusy    */
+	/* 
+	 * Flush operation will skip the above two setup (for data and vid), and 
+	 * come to here directly
+	 */
+
+	if(vtuOp == FLUSH_ALL)
+		data = (1 << 15) | (vtuOp << 12);
+	else
+	{
+		if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
+		{
+			data = (1 << 15) | (vtuOp << 12);
+		}
+		else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+		{
+			/* Since DBNum is defined as GT_U8, it cannot be >= 256. */
+			#if 0
+			if(entry->DBNum >= 256)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return GT_BAD_PARAM;
+			}	
+			#endif
+			data = (1 << 15) | (vtuOp << 12) | ((entry->DBNum & 0xF0) << 4) | (entry->DBNum & 0x0F);
+		}
+		else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+		{
+			if(entry->DBNum >= 64)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return GT_BAD_PARAM;
+			}	
+			data = (1 << 15) | (vtuOp << 12) | ((entry->DBNum & 0x30) << 4) | (entry->DBNum & 0x0F);
+		}
+		else
+		{
+			if(entry->DBNum >= 16)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return GT_BAD_PARAM;
+			}	
+			data = (1 << 15) | (vtuOp << 12) | entry->DBNum;
+		}
+	}
+
+	retVal = hwWriteGlobalReg(dev,QD_REG_VTU_OPERATION,data);
+	if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->vtuRegsSem);
+		return retVal;
+	}
+
+	/* only two operations need to go through the mess below to get some data 
+	 * after the operations -  service violation and get next entry
+	 */
+
+	/* If the operation is to service violation operation wait for the response   */
+	if(vtuOp == SERVICE_VIOLATIONS)
+	{
+		/* Wait until the VTU in ready. */
+		data = 1;
+		while(data == 1)
+		{
+			retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+		}
+
+		/* get the Source Port ID that was involved in the violation */
+		retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,0,4,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+
+		entry->DBNum = (GT_U8)(data & 0xF);
+
+		/* get the VID that was involved in the violation */
+
+		retVal = hwReadGlobalReg(dev,QD_REG_VTU_VID_REG,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+
+		/* Get the vid - bits 0-11 */
+		entry->vid   = data & 0xFFF;
+
+
+	} /* end of service violations */
+
+	/* If the operation is a get next operation wait for the response   */
+	if(vtuOp == GET_NEXT_ENTRY)
+	{
+		entry->vidExInfo.useVIDFPri = GT_FALSE;
+		entry->vidExInfo.vidFPri = 0;
+
+		entry->vidExInfo.useVIDQPri = GT_FALSE;
+		entry->vidExInfo.vidQPri = 0;
+
+		entry->vidExInfo.vidNRateLimit = GT_FALSE;
+
+    	entry->sid = 0;
+   		entry->vidPolicy = GT_FALSE;
+
+		/* Wait until the VTU in ready. */
+		data = 1;
+		while(data == 1)
+		{
+			retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+		}
+
+		/****************** get the vid *******************/
+
+		retVal = hwReadGlobalReg(dev,QD_REG_VTU_VID_REG,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+
+		/* the vid is bits 0-11 */
+		entry->vid   = data & 0xFFF;
+
+		/* the vid valid is bits 12 */
+		*valid   = (data >> 12) & 1;
+		
+		if (*valid == 0)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return GT_OK;
+		}
+
+		/****************** get the SID *******************/
+		if(IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
+		{
+		    retVal = hwReadGlobalReg(dev,(GT_U8)(QD_REG_STU_SID_REG),&data);
+    		if(retVal != GT_OK)
+		    {
+    			gtSemGive(dev,dev->vtuRegsSem);
+	    		return retVal;
+	    	}		
+	    	entry->sid = data & 0x3F;
+		}
+
+		/****************** get the DBNum *******************/
+		if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
+		{
+		    retVal = hwReadGlobalReg(dev,(GT_U8)(QD_REG_VTU_FID_REG),&data);
+    		if(retVal != GT_OK)
+		    {
+    			gtSemGive(dev,dev->vtuRegsSem);
+	    		return retVal;
+	    	}		
+
+			if(IS_IN_DEV_GROUP(dev,DEV_POLICY))
+			{
+	    		entry->vidPolicy = (data >> 12) & 0x1;
+			}
+
+	    	entry->DBNum = data & 0xFFF;
+
+		}
+		else
+		{
+			retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,0,4,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+
+			entry->DBNum = data & 0xF;
+		
+			if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
+			{
+				retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,8,4,&data);
+				if(retVal != GT_OK)
+				{
+					gtSemGive(dev,dev->vtuRegsSem);
+					return retVal;
+				}
+
+				entry->DBNum |= ((data & 0xF) << 4);
+			}
+			else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
+			{
+				retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,8,2,&data);
+				if(retVal != GT_OK)
+				{
+					gtSemGive(dev,dev->vtuRegsSem);
+					return retVal;
+				}
+
+				entry->DBNum |= ((data & 0x3) << 4);
+			}
+		}
+
+
+		/****************** get the MemberTagP *******************/
+		retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA1_REG,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->vtuRegsSem);
+			return retVal;
+		}
+
+		/* get data from data register for ports 0 to 2 */
+		entry->vtuData.memberTagP[0]  =  data & 3 ;
+		entry->vtuData.memberTagP[1]  = (data >> 4) & 3 ;
+		entry->vtuData.memberTagP[2]  = (data >> 8) & 3 ;
+		entry->vtuData.portStateP[0]  = (data >> 2) & 3 ;
+		entry->vtuData.portStateP[1]  = (data >> 6) & 3 ;
+		entry->vtuData.portStateP[2]  = (data >> 10) & 3 ;
+
+		/****************** for the switch more than 3 ports *****************/
+
+		if(dev->maxPorts > 3)
+		{
+			/* fullsail has 3 ports, clippership has 7 prots */
+			entry->vtuData.memberTagP[3]  = (data >>12) & 3 ;
+			entry->vtuData.portStateP[3]  = (data >>14) & 3 ;
+
+			/* get data from data register for ports 4 to 6 */
+			retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA2_REG,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+			entry->vtuData.memberTagP[4]  = data & 3 ;
+			entry->vtuData.memberTagP[5]  = (data >> 4) & 3 ;
+			entry->vtuData.portStateP[4]  = (data >> 2) & 3 ;
+			entry->vtuData.portStateP[5]  = (data >> 6) & 3 ;
+
+			if(dev->maxPorts > 6)
+			{
+				entry->vtuData.memberTagP[6]  = (data >> 8) & 3 ;
+				entry->vtuData.portStateP[6]  = (data >> 10) & 3 ;
+			}
+			
+			if (IS_IN_DEV_GROUP(dev,DEV_VTU_EXT_INFO))
+			{
+				entry->vidPriOverride = 0;
+				entry->vidPriority = 0;
+
+				entry->vidExInfo.useVIDFPri = (data & 0x8000)?GT_TRUE:GT_FALSE;
+				entry->vidExInfo.vidFPri = (data >> 12) & 0x7;
+
+				entry->vidExInfo.useVIDQPri = (data & 0x0800)?GT_TRUE:GT_FALSE;
+				entry->vidExInfo.vidQPri = (data >> 9) & 0x3;
+
+				entry->vidExInfo.vidNRateLimit = (data & 0x0100)?GT_TRUE:GT_FALSE;
+			}
+		}
+		/****************** upto 7 port switch *******************/
+
+		/****************** for the switch more than 7 ports *****************/
+
+		if(dev->maxPorts > 7)
+		{
+			/* fullsail has 3 ports, clippership has 7 prots */
+			entry->vtuData.memberTagP[7]  = (data >>12) & 3 ;
+			entry->vtuData.portStateP[7]  = (data >>14) & 3 ;
+
+			/* get data from data register for ports 4 to 6 */
+			retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA3_REG,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+			entry->vtuData.memberTagP[8]  = data & 3 ;
+			entry->vtuData.memberTagP[9]  = (data >> 4) & 3 ;
+			entry->vtuData.portStateP[8]  = (data >> 2) & 3 ;
+			entry->vtuData.portStateP[9]  = (data >> 6) & 3 ;
+
+			if(dev->maxPorts > 10)
+			{
+				entry->vtuData.memberTagP[10]  = (data >> 8) & 3 ;
+				entry->vtuData.portStateP[10]  = (data >> 10) & 3 ;
+			}
+
+			if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+			{
+				if (data & 0x8000)
+				{
+					entry->vidPriOverride = GT_TRUE;
+					entry->vidPriority = (data >> 12) & 0x7;
+				}
+				else
+				{
+					entry->vidPriOverride = GT_FALSE;
+					entry->vidPriority = 0;
+				}
+			}
+
+		}
+		else if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+		{
+			/* get data from data register for ports 4 to 6 */
+			retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA3_REG,&data);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->vtuRegsSem);
+				return retVal;
+			}
+
+			if (data & 0x8000)
+			{
+				entry->vidPriOverride = GT_TRUE;
+				entry->vidPriority = (data >> 12) & 0x7;
+			}
+			else
+			{
+				entry->vidPriOverride = GT_FALSE;
+				entry->vidPriority = 0;
+			}
+		}
+
+		/****************** upto 11 ports switch *******************/
+
+	} /* end of get next entry */
+
+	gtSemGive(dev,dev->vtuRegsSem);
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtCCPVT.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtCCPVT.c
new file mode 100755
index 0000000..7333820
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtCCPVT.c
@@ -0,0 +1,401 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtCCPVT.c
+*
+* DESCRIPTION:
+*       API definitions for Cross Chip Port Vlan Data Table
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/****************************************************************************/
+/* Cross Chip Port Vlan operation function declaration.                                    */
+/****************************************************************************/
+static GT_STATUS pvtOperationPerform
+(
+    IN   GT_QD_DEV 			*dev,
+    IN   GT_PVT_OPERATION	pvtOp,
+    INOUT GT_PVT_OP_DATA	*opData
+);
+
+
+/*******************************************************************************
+* gpvtInitialize
+*
+* DESCRIPTION:
+*       This routine initializes the PVT Table to all one's (initial state)
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpvtInitialize
+(
+	IN  GT_QD_DEV 	*dev
+)
+{
+	GT_STATUS       	retVal;
+	GT_PVT_OPERATION	op;
+
+	DBG_INFO(("gpvtInitialize Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CROSS_CHIP_PORT_VLAN))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	/* Program Tuning register */
+	op = PVT_INITIALIZE;
+	retVal = pvtOperationPerform(dev,op,NULL);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (pvtOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gpvtWritePVTData
+*
+* DESCRIPTION:
+*       This routine write Cross Chip Port Vlan Data.
+*		Cross chip Port VLAN Data used as a bit mask to limit where cross chip
+*		frames can egress (in chip Port VLANs are masked using gvlnSetPortVlanPorts
+*		API). Cross chip frames are Forward frames that ingress a DSA or Ether 
+*		Type DSA port (see gprtSetFrameMode API). Bit 0 is a mask for port 0, 
+*		bit 1 for port 1, etc. When a port's mask bit is one, frames are allowed 
+*		to egress that port on this device. When a port's mask bit is zero,
+*		frames are not allowed to egress that port on this device.
+*
+*		The Cross Chip Port VLAN Table is accessed by ingressing frames based
+*		upon the original source port of the frame using the Forward frame's DSA tag
+*		fields Src_Dev, Src_Port/Src_Trunk and Src_Is_Trunk. The 1 entry of the 512
+*		that is accessed by the frame is:
+*			If 5 Bit Port (in Global 2, offset 0x1D) = 0:
+*				If Src_Is_Trunk = 0   Src_Dev[4:0], Src_Port[3:0]119
+*				If Src_Is_Trunk = 1   Device Number (global offset 0x1C), Src_Trunk[3:0]
+*			If 5 Bit Port (in Global 2, offset 0x1D) = 1:
+*				If Src_Is_Trunk = 0   Src_Dev[3:0], Src_Port[4:0]120
+*				If Src_Is_Trunk = 1   Device Number[3:0], Src_Trunk[4:0]
+*
+*		Cross chip port VLANs with Trunks are supported in the table where this
+*		device's entries would be stored (defined by this device's Device Number).
+*		This portion of the table is available for Trunk entries because this device's
+*		port VLAN mappings to ports inside this device are masked by the port's
+*		VLAN Table (see gvlnSetPortVlanPorts API).
+*
+*
+* INPUTS:
+*		pvtPointer - pointer to the desired entry of PVT (0 ~ 511)
+*		pvtData    - Cross Chip Port Vlan Data
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpvtWritePVTData
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		pvtPointer,
+	IN  GT_U32		pvtData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PVT_OPERATION	op;
+	GT_PVT_OP_DATA		opData;
+
+	DBG_INFO(("gpvtWritePVTData Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CROSS_CHIP_PORT_VLAN))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if the given pointer is valid */
+	if (pvtPointer > 0x1FF)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+    /* check if the given pvtData is valid */
+	if (pvtData >= (GT_U32)(1 << dev->maxPorts))
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	/* Program Tuning register */
+	op = PVT_WRITE;
+	opData.pvtAddr = pvtPointer;
+
+	if((opData.pvtData = GT_LPORTVEC_2_PORTVEC(pvtData)) == GT_INVALID_PORT_VEC)
+	{
+		DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+
+	retVal = pvtOperationPerform(dev,op,&opData);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed (pvtOperationPerform returned GT_FAIL).\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gpvtReadPVTData
+*
+* DESCRIPTION:
+*       This routine reads Cross Chip Port Vlan Data.
+*		Cross chip Port VLAN Data used as a bit mask to limit where cross chip
+*		frames can egress (in chip Port VLANs are masked using gvlnSetPortVlanPorts
+*		API). Cross chip frames are Forward frames that ingress a DSA or Ether 
+*		Type DSA port (see gprtSetFrameMode API). Bit 0 is a mask for port 0, 
+*		bit 1 for port 1, etc. When a port's mask bit is one, frames are allowed 
+*		to egress that port on this device. When a port's mask bit is zero,
+*		frames are not allowed to egress that port on this device.
+*
+*		The Cross Chip Port VLAN Table is accessed by ingressing frames based
+*		upon the original source port of the frame using the Forward frame's DSA tag
+*		fields Src_Dev, Src_Port/Src_Trunk and Src_Is_Trunk. The 1 entry of the 512
+*		that is accessed by the frame is:
+*			If 5 Bit Port (in Global 2, offset 0x1D) = 0:
+*				If Src_Is_Trunk = 0   Src_Dev[4:0], Src_Port[3:0]119
+*				If Src_Is_Trunk = 1   Device Number (global offset 0x1C), Src_Trunk[3:0]
+*			If 5 Bit Port (in Global 2, offset 0x1D) = 1:
+*				If Src_Is_Trunk = 0   Src_Dev[3:0], Src_Port[4:0]120
+*				If Src_Is_Trunk = 1   Device Number[3:0], Src_Trunk[4:0]
+*
+*		Cross chip port VLANs with Trunks are supported in the table where this
+*		device's entries would be stored (defined by this device's Device Number).
+*		This portion of the table is available for Trunk entries because this device's
+*		port VLAN mappings to ports inside this device are masked by the port's
+*		VLAN Table (see gvlnSetPortVlanPorts API).
+*
+*
+* INPUTS:
+*		pvtPointer - pointer to the desired entry of PVT (0 ~ 511)
+*
+* OUTPUTS:
+*		pvtData    - Cross Chip Port Vlan Data
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpvtReadPVTData
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		pvtPointer,
+	OUT GT_U32		*pvtData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PVT_OPERATION	op;
+	GT_PVT_OP_DATA		opData;
+
+	DBG_INFO(("gpvtReadPVTData Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CROSS_CHIP_PORT_VLAN))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if the given pointer is valid */
+	if (pvtPointer > 0x1FF)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	/* Program Tuning register */
+	op = PVT_READ;
+	opData.pvtAddr = pvtPointer;
+	retVal = pvtOperationPerform(dev,op,&opData);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (pvtOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	opData.pvtData &= (1 << dev->maxPorts) - 1;
+	*pvtData = GT_PORTVEC_2_LPORTVEC(opData.pvtData);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/****************************************************************************/
+/* Internal functions.                                                  */
+/****************************************************************************/
+
+
+/*******************************************************************************
+* pvtOperationPerform
+*
+* DESCRIPTION:
+*       This function accesses PVT Table
+*
+* INPUTS:
+*       pvtOp   - The pvt operation
+*       pvtData - address and data to be written into PVT
+*
+* OUTPUTS:
+*       pvtData - data read from PVT pointed by address
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pvtOperationPerform
+(
+    IN    GT_QD_DEV           *dev,
+    IN    GT_PVT_OPERATION   pvtOp,
+    INOUT GT_PVT_OP_DATA     *opData
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+
+    gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+    /* Wait until the pvt in ready. */
+    data = 1;
+    while(data == 1)
+    {
+        retVal = hwGetGlobal2RegField(dev,QD_REG_PVT_ADDR,15,1,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->tblRegsSem);
+            return retVal;
+        }
+    }
+
+    /* Set the PVT Operation register */
+	switch (pvtOp)
+	{
+		case PVT_INITIALIZE:
+			data = (1 << 15) | (pvtOp << 12);
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PVT_ADDR,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->tblRegsSem);
+            	return retVal;
+	        }
+			break;
+
+		case PVT_WRITE:
+			data = (GT_U16)opData->pvtData;
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PVT_DATA,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->tblRegsSem);
+            	return retVal;
+	        }
+
+			data = (GT_U16)((1 << 15) | (pvtOp << 12) | opData->pvtAddr);
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PVT_ADDR,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->tblRegsSem);
+            	return retVal;
+	        }
+			break;
+
+		case PVT_READ:
+			data = (GT_U16)((1 << 15) | (pvtOp << 12) | opData->pvtAddr);
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PVT_ADDR,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->tblRegsSem);
+            	return retVal;
+	        }
+
+		    data = 1;
+		    while(data == 1)
+		    {
+		        retVal = hwGetGlobal2RegField(dev,QD_REG_PVT_ADDR,15,1,&data);
+		        if(retVal != GT_OK)
+		        {
+		            gtSemGive(dev,dev->tblRegsSem);
+		            return retVal;
+        		}
+		    }
+
+			retVal = hwReadGlobal2Reg(dev,QD_REG_PVT_DATA,&data);
+			opData->pvtData = (GT_U32)data;
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->tblRegsSem);
+            	return retVal;
+	        }
+	
+			break;
+
+		default:
+			
+			gtSemGive(dev,dev->tblRegsSem);
+			return GT_FAIL;
+	}
+
+    gtSemGive(dev,dev->tblRegsSem);
+    return retVal;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtEvents.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtEvents.c
new file mode 100755
index 0000000..1f6b020
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtEvents.c
@@ -0,0 +1,1489 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtEvents.c
+*
+* DESCRIPTION:
+*       API definitions for system interrupt events handling.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/*******************************************************************************
+* eventSetActive
+*
+* DESCRIPTION:
+*       This routine enables/disables the receive of an hardware driven event.
+*
+* INPUTS:
+*       eventType - the event type. any combination of the folowing: 
+*       	GT_STATS_DONE, GT_VTU_PROB, GT_VTU_DONE, GT_ATU_FULL(or GT_ATU_PROB),
+*       	GT_ATU_DONE, GT_PHY_INTERRUPT, GT_EE_INTERRUPT, GT_DEVICE_INT,
+*			and GT_AVB_INTERRUPT
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       Each switch device has its own set of event Types. Please refer to the
+*		device datasheet for the list of event types that the device supports.
+*
+*******************************************************************************/
+GT_STATUS eventSetActive
+(
+    IN GT_QD_DEV *dev,
+    IN GT_U32 	 eventType
+)
+{
+    GT_STATUS   retVal;   
+    GT_U16 	data;
+	GT_U16	intMask;
+    GT_U8 	len;
+
+    DBG_INFO(("eventSetActive Called.\n"));
+
+	data = (GT_U16) eventType;
+	len = 9;
+
+	if ((IS_IN_DEV_GROUP(dev,DEV_EXTERNAL_PHY_ONLY)) || 
+		(IS_IN_DEV_GROUP(dev,DEV_DEV_PHY_INTERRUPT)))
+    {
+		intMask = GT_NO_INTERNAL_PHY_INT_MASK;
+    }
+	else
+	{
+		intMask = GT_INT_MASK;
+	}
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_INTERRUPT))
+	{
+		intMask &= ~GT_AVB_INT;
+		len = 8;
+	}
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_DEVICE_INTERRUPT))
+	{
+		intMask &= ~GT_DEVICE_INT;
+		len = 7;
+	}
+
+	
+	if(data & ~intMask)
+	{
+	    DBG_INFO(("Invalid event type.\n"));
+		return GT_FAIL;
+	}
+
+    /* Set the IntEn bit.               */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,0,len,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* eventGetIntStatus
+*
+* DESCRIPTION:
+*       This routine reads an hardware driven event status.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       intCause - It provides the source of interrupt of the following:
+*       		GT_STATS_DONE, GT_VTU_PROB, GT_VTU_DONE, GT_ATU_FULL,  
+*       		GT_ATU_DONE, GT_PHY_INTERRUPT, GT_EE_INTERRUPT, GT_DEVICE_INT,
+*				and GT_AVB_INTERRUPT
+*				For Gigabit Switch, GT_ATU_FULL is replaced with GT_ATU_PROB and 
+*				if there is no internal phy, GT_PHY_INTERRUPT is not supported.
+*
+* RETURNS:
+*       GT_OK   - read success.
+*       GT_FAIL - otherwise
+*
+* COMMENTS:
+*       Each switch device has its own set of event Types. Please refer to the
+*		device datasheet for the list of event types that the device supports.
+*
+*******************************************************************************/
+GT_STATUS eventGetIntStatus
+(
+    IN GT_QD_DEV *dev,
+    OUT GT_U16   *intCause
+)
+{
+    GT_STATUS 	retVal;         /* Function calls return value.     */
+    GT_U8 		len;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_AVB_INTERRUPT))
+		len = 9;
+	else if (IS_IN_DEV_GROUP(dev,DEV_DEVICE_INTERRUPT))
+		len = 8;
+	else
+		len = 7;
+
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,0,len,intCause);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gvtuGetIntStatus
+*
+* DESCRIPTION:
+* Check to see if a specific type of VTU interrupt occured
+*
+* INPUTS:
+*       intType - the type of interrupt which causes an interrupt.
+*			any combination of 
+*			GT_MEMEBER_VIOLATION,
+*			GT_MISS_VIOLATION,
+*			GT_FULL_VIOLATION
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK - on success
+* 		GT_FAIL - on error
+*
+* COMMENTS:
+* 	FULL_VIOLATION is not supported by all switch devices.
+*	Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gvtuGetIntStatus
+(
+    IN GT_QD_DEV          *dev,
+    OUT GT_VTU_INT_STATUS *vtuIntStatus
+)
+{
+    GT_STATUS       retVal;      
+
+    DBG_INFO(("gvtuGetIntStatus Called.\n"));
+   
+    /* check if device supports this feature */
+    if((IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK ) 
+      return GT_FAIL; 
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+	    retVal = gvtuGetViolation2(dev,vtuIntStatus);
+	}
+	else if (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH))
+	{
+	    retVal = gvtuGetViolation3(dev,vtuIntStatus);
+	}
+	else
+	{
+	    retVal = gvtuGetViolation(dev,vtuIntStatus);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    
+    return retVal;
+}
+
+/*******************************************************************************
+* gatuGetIntStatus
+*
+* DESCRIPTION:
+* Check to see if a specific type of ATU interrupt occured
+*
+* INPUTS:
+*      	intType - the type of interrupt which causes an interrupt.
+*			any combination of 
+*			GT_AGE_OUT_VIOLATION,
+*			GT_AGE_VIOLATION,
+*			GT_MEMEBER_VIOLATION,
+*			GT_MISS_VIOLATION,
+*			GT_FULL_VIOLATION 
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK - on success
+* 		GT_FAIL - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS gatuGetIntStatus
+(
+    IN GT_QD_DEV          *dev,
+    OUT GT_ATU_INT_STATUS *atuIntStatus
+)
+{
+    GT_STATUS       retVal;      
+
+    DBG_INFO(("gatuGetIntStatus Called.\n"));
+   
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    retVal = gatuGetViolation(dev,atuIntStatus);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    
+    return retVal;
+}
+
+
+/*******************************************************************************
+* geventGetDevIntStatus
+*
+* DESCRIPTION:
+* 		Check to see which device interrupts (WatchDog, JamLimit, Duplex Mismatch,
+*		SERDES Link Int, and Phy Int) have occurred.
+*
+* INPUTS:
+*       intType - the type of interrupt which causes an interrupt.
+*				  any combination of 
+*					GT_DEV_INT_WATCHDOG,
+*					GT_DEV_INT_JAMLIMIT,
+*					GT_DEV_INT_DUPLEX_MISMATCH,
+*					GT_DEV_INT_SERDES_LINK
+*					GT_DEV_INT_PHY
+*		port	- logical port where GT_DEV_INT_DUPLEX_MISMATCH occurred.
+*				  valid only if GT_DEV_INT_DUPLEX_MISMATCH is set in intType.
+*		linkInt - SERDES port list where GT_DEV_INT_SERDES_LINK interrupt is
+*				  asserted. It's in vector format, Bit 10 is for port 10, 
+*				  Bit 9 is for port 9, etc.
+*				  valid only if GT_DEV_INT_SERDES_LINK bit is set in intType.
+*				  These bits are only valid of the port that is in 1000Base-X mode.
+*		phyInt  - port list where GT_DEV_INT_PHY interrupt is asserted.
+*				  It's in vector format, Bit 0 is for port 0, Bit 1 is for port 1, etc.
+*				  valid only if GT_DEV_INT_PHY bit is set in intType.
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK - on success
+* 		GT_FAIL - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS geventGetDevIntStatus
+(
+    IN  GT_QD_DEV 			*dev,
+    OUT GT_DEV_INT_STATUS	*devIntStatus
+)
+{
+    GT_STATUS       retVal;
+	GT_U16			data, hwPort;
+
+    DBG_INFO(("geventGetDevIntStatus Called.\n"));
+   
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_DEVICE_INTERRUPT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+	
+	devIntStatus->devIntCause = 0;
+
+    retVal = hwReadGlobal2Reg(dev,QD_REG_DEVINT_SOURCE,&data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	/* check SERDES Link Int and Phy Int, if applicable */
+	if (IS_IN_DEV_GROUP(dev,DEV_DEVICE_INT_TYPE1))
+	{
+		/* check SERDES Link Int */
+		if (data & (0x7 << 8))
+		{
+			devIntStatus->devIntCause |= GT_DEV_INT_SERDES_LINK;
+			devIntStatus->linkInt = GT_PORTVEC_2_LPORTVEC((data & (7<<8)));
+		}
+	}
+	else	/* DEV_DEVICE_INT_TYPE2 */
+	{
+		if (data & (0x3 << 11))
+		{
+			devIntStatus->devIntCause |= GT_DEV_INT_SERDES_LINK;
+			devIntStatus->linkInt = GT_PORTVEC_2_LPORTVEC((data & (0x3 << 11)) >> 7);
+		}
+
+		if (data & 0x1F)
+		{
+			devIntStatus->devIntCause |= GT_DEV_INT_PHY;
+			devIntStatus->phyInt = GT_PORTVEC_2_LPORTVEC((data & 0x1F));
+		}
+	}
+
+	if (data & QD_DEV_INT_DUPLEX_MISMATCH)
+	{
+		devIntStatus->devIntCause |= GT_DEV_INT_DUPLEX_MISMATCH;
+
+		/* read port that causes the interrupt */
+	    retVal = hwGetGlobal2RegField(dev, QD_REG_WD_CONTROL, 12, 4, &hwPort);
+	    if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Failed.\n"));
+			return retVal;
+		}
+
+		/* re-arm the interrupt event */
+	    retVal = hwSetGlobal2RegField(dev, QD_REG_WD_CONTROL, 12, 4, 0xF);
+	    if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Failed.\n"));
+			return retVal;
+		}
+
+		devIntStatus->port = GT_PORT_2_LPORT((GT_U8)hwPort);
+	}
+	    
+	if (data & QD_DEV_INT_WATCHDOG)
+	{
+		devIntStatus->devIntCause |= GT_DEV_INT_WATCHDOG;
+	}
+
+	if (data & QD_DEV_INT_JAMLIMIT)
+	{
+		devIntStatus->devIntCause |= GT_DEV_INT_JAMLIMIT;
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* geventSetAgeIntEn
+*
+* DESCRIPTION:
+*		This routine enables/disables Age Interrupt for a port.
+*		When it's enabled, ATU Age Violation interrupts from this port are enabled.
+*		An Age Violation will occur anytime a port is Locked(gprtSetLockedPort) 
+*		and the ingressing frame's SA is contained in the ATU as a non-Static 
+*		entry with a EntryState less than 0x4.
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_TRUE to enable Age Interrupt,
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventSetAgeIntEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("geventSetAgeIntEn Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PORT_BASED_AGE_INT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set Age Interrupt Enable Mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION,11,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* geventGetAgeIntEn
+*
+* DESCRIPTION:
+*		This routine gets Age Interrupt Enable for the port.
+*		When it's enabled, ATU Age Violation interrupts from this port are enabled.
+*		An Age Violation will occur anytime a port is Locked(gprtSetLockedPort) 
+*		and the ingressing frame's SA is contained in the ATU as a non-Static 
+*		entry with a EntryState less than 0x4.
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_TRUE to enable Age Interrupt,
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventGetAgeIntEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("geventGetAgeIntEn Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PORT_BASED_AGE_INT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get Age Interrupt Enable Mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION,11,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* geventSetAgeOutIntEn
+*
+* DESCRIPTION:
+*		Interrupt on Age Out. When aging is enabled, all non-static address 
+*		entries in the ATU's address database are periodically aged.
+*		When this feature is set to GT_TRUE and an entry associated with this 
+*		port is aged out, an AgeOutViolation will be captured for that entry.
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_TRUE to enable Age Out Interrupt,
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventSetAgeOutIntEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("geventSetAgeOutIntEn Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_AGE_OUT_INT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set Age Out Interrupt Enable Mode. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION,14,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* geventGetAgeOutIntEn
+*
+* DESCRIPTION:
+*		Interrupt on Age Out. When aging is enabled, all non-static address 
+*		entries in the ATU's address database are periodically aged.
+*		When this feature is set to GT_TRUE and an entry associated with this 
+*		port is aged out, an AgeOutViolation will be captured for that entry.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		mode - GT_TRUE, if Age Out Interrupt is enabled
+*			   GT_FALUSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventGetAgeOutIntEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("geventGetAgeOutIntEn Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_AGE_OUT_INT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get Age Out Interrupt Enable Mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION,14,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* geventSetOverLimitInt
+*
+* DESCRIPTION:
+*		This routine enables/disables Over Limit Interrupt for a port.
+*		If it's enabled, an ATU Miss violation will be generated when port auto
+*		learn reached the limit(refer to gfdbGetPortAtuLimitReached API).
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_TRUE to enable Over Limit Interrupt,
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventSetOverLimitInt
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("geventSetOverLimitInt Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_ATU_LIMIT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set Over Limit Interrupt Enable Mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ATU_CONTROL, 13, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* geventGetOverLimitInt
+*
+* DESCRIPTION:
+*		This routine enables/disables Over Limit Interrupt for a port.
+*		If it's enabled, an ATU Miss violation will be generated when port auto
+*		learn reached the limit(refer to gfdbSetPortAtuLearnLimit API).
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable Over Limit Interrupt,
+*			   GT_FALUSE to disable
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS geventGetOverLimitInt
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("geventGetOverLimitInt Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_ATU_LIMIT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Set Over Limit Interrupt Enable Mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ATU_CONTROL, 13, 1, &data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+/*******************************************************************************
+* geventGetPortAtuLimitReached
+*
+* DESCRIPTION:
+*       This routine checks if learn limit has been reached.
+*		When it reached, the port can no longer auto learn any more MAC addresses
+*		because the address learn limit set on this port has been reached.
+*
+* INPUTS:
+*       port  - logical port number
+*											  
+* OUTPUTS:
+*       limit - GT_TRUE, if limit has been reached
+*			    GT_FALSE, otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*
+*******************************************************************************/
+GT_STATUS geventGetPortAtuLimitReached
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT  	port,
+    IN  GT_BOOL   	*limit
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("geventGetPortAtuLimitReached Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Check device if this feature is supported. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ATU_LIMIT))
+    {
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the LimitReached bit. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ATU_CONTROL, 14, 1, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data, *limit);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* eventSetDevInt
+*
+* DESCRIPTION:
+*		Device Interrupt.
+*		The following device interrupts are supported:
+*			GT_DEV_INT_WATCHDOG	- 
+*				WatchDog event interrupt (WatchDog event can be configured with 
+*				gwdSetEvent API)
+*			GT_DEV_INT_JAMLIMIT	-
+*				any of the ports detect an Ingress Jam Limit violation
+*				(see gprtSetPauseLimitIn API)
+*			GT_DEV_INT_DUPLEX_MISMATCH - 
+*				any of the ports detect a duplex mismatch (i.e., the local port is 
+*				in half duplex mode while the link partner is in full duplex mode)
+*			GT_DEV_INT_SERDES_LINK - 
+*				SERDES link change interrupt.
+*				An interrupt occurs when a SERDES port changes link status
+*				(link up or link down)
+*			GT_DEV_INT_PHY - Phy interrupt.
+*			
+*		If any of the above events is enabled, GT_DEVICE_INT interrupt will
+*		be asserted by the enabled event when GT_DEV_INT is enabled with 
+*		eventSetActive API.
+*		
+* INPUTS:
+*		devInt - GT_DEV_INT
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS eventSetDevInt
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_DEV_EVENT    *devInt
+)
+{
+	GT_U16          data, event;
+	GT_U16			serdesMask, phyMask, mask;
+	GT_U32			pList;
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("eventSetDevInt Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_DEVICE_INTERRUPT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	event = (GT_U16)devInt->event;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_DEVICE_INT_TYPE1))
+	{
+		serdesMask = mask = 7 << 8;	/* SERDES Port List */
+		phyMask = 0;
+	}
+	else
+	{
+		serdesMask = mask = 3 << 11;	/* SERDES Port List */
+		mask |= 0x1F;	/* Phy list */
+		phyMask = 0x1F;
+	}
+	mask |= QD_DEV_INT_WATCHDOG | QD_DEV_INT_JAMLIMIT | QD_DEV_INT_DUPLEX_MISMATCH;
+
+	data = 0;
+
+ 	if (event & GT_DEV_INT_SERDES_LINK)
+ 	{
+		/* check for valid SERDES Port List */
+		if (IS_IN_DEV_GROUP(dev,DEV_DEVICE_INT_TYPE1))
+		{
+			pList = GT_LPORTVEC_2_PORTVEC(devInt->portList);
+			if ((GT_U16)pList & (~serdesMask))
+			{
+		        DBG_INFO(("GT_BAD_PARAM portList\n"));
+				return GT_BAD_PARAM;
+			}
+			data = (GT_U16)pList;
+		}
+		else
+		{
+			pList = GT_LPORTVEC_2_PORTVEC(devInt->portList);
+			pList <<= 7;
+			if ((GT_U16)pList & (~serdesMask))
+			{
+		        DBG_INFO(("GT_BAD_PARAM portList\n"));
+				return GT_BAD_PARAM;
+			}
+			data = (GT_U16)pList;
+		}
+	}
+
+	if (event & GT_DEV_INT_PHY)
+	{
+		/* check for valid Phy List */
+		if (IS_IN_DEV_GROUP(dev,DEV_DEVICE_INT_TYPE1))
+ 		{
+	        DBG_INFO(("GT_BAD_PARAM: PHY Int not supported.\n"));
+ 			return GT_BAD_PARAM;
+ 		}
+		else
+		{
+			pList = GT_LPORTVEC_2_PORTVEC(devInt->phyList);
+			if ((GT_U16)pList & (~phyMask))
+			{
+		        DBG_INFO(("GT_BAD_PARAM phyList\n"));
+				return GT_BAD_PARAM;
+			}
+
+			data |= (GT_U16)pList;
+		}
+ 	}
+
+	if (event & GT_DEV_INT_WATCHDOG)
+	{
+		data |= QD_DEV_INT_WATCHDOG;
+	}
+
+	if (event & GT_DEV_INT_JAMLIMIT)
+	{
+		data |= QD_DEV_INT_JAMLIMIT;
+	}
+
+	if (event & GT_DEV_INT_DUPLEX_MISMATCH)
+	{
+		data |= QD_DEV_INT_DUPLEX_MISMATCH;
+	}
+
+	if (data & (~mask))
+	{
+        DBG_INFO(("GT_BAD_PARAM portList\n"));
+		return GT_BAD_PARAM;
+	}
+
+	if (data & GT_DEV_INT_DUPLEX_MISMATCH)
+	{
+	    retVal = hwSetGlobal2RegField(dev, QD_REG_WD_CONTROL, 12, 4, 0xF);
+	    if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Failed.\n"));
+			return retVal;
+		}
+	}
+
+    /* Set the related bit. */
+    retVal = hwSetGlobal2RegBits(dev,QD_REG_DEVINT_MASK, mask, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gwdSetEvent
+*
+* DESCRIPTION:
+*		Watch Dog Event.
+*		The following Watch Dog events are supported:
+*			GT_WD_QC  - Queue Controller Watch Dog enable.
+*						When enabled, the QC's watch dog circuit checks for link
+*						list errors and any errors found in the QC.
+*			GT_WD_EGRESS - Egress Watch Dog enable.
+*						When enabled, each port's egress circuit checks for problems
+*						between the port and the Queue Controller.
+*			GT_WD_FORCE - Force a Watch Dog event.
+*			
+*		If any of the above events is enabled, GT_DEVICE_INT interrupt will
+*		be asserted by the enabled WatchDog event when GT_DEV_INT_WATCHDOG is
+*		enabled with eventSetDevActive API and GT_DEV_INT is enabled with 
+*		eventSetActive API.
+*		
+* INPUTS:
+*		wdEvent - Watch Dog Events
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdSetEvent
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32	    wdEvent
+)
+{
+    GT_U16          data, mask;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gwdSetEvent Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_WATCHDOG_EVENT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	mask = (1 << 5) | (1 << 3) | (1 << 2);
+	data = 0;
+
+	if (wdEvent & GT_WD_QC)
+	{
+		data |= (1 << 5);
+	}
+
+	if (wdEvent & GT_WD_EGRESS)
+	{
+		data |= (1 << 3);
+	}
+
+	if (wdEvent & GT_WD_FORCE)
+	{
+		data |= (1 << 2);
+	}
+
+    /* Set the related bit. */
+    retVal = hwSetGlobal2RegBits(dev,QD_REG_WD_CONTROL, mask, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gwdSetSWResetOnWD
+*
+* DESCRIPTION:
+*		SWReset on Watch Dog Event.
+*		When this feature is enabled, any enabled watch dog event (gwdSetEvent API) 
+*		will automatically reset the switch core's datapath just as if gsysSwReset
+*		API is called.
+*
+*		The Watch Dog History (gwdGetHistory API) won't be cleared by this 
+*		automatic SWReset. This allows the user to know if any watch dog event 
+*		ever occurred even if the swich is configured to automatically recover 
+*		from a watch dog.
+*
+*		When this feature is disabled, enabled watch dog events will not cause a
+*		SWReset.
+*
+* INPUTS:
+*		en   - GT_TRUE to enable SWReset on WD
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdSetSWResetOnWD
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL	    en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gwdSetSWResetOnWD Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_WATCHDOG_EVENT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the related bit. */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_WD_CONTROL, 0, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gwdGetSWResetOnWD
+*
+* DESCRIPTION:
+*		SWReset on Watch Dog Event.
+*		When this feature is enabled, any enabled watch dog event (gwdSetEvent API) 
+*		will automatically reset the switch core's datapath just as if gsysSwReset
+*		API is called.
+*
+*		The Watch Dog History (gwdGetHistory API) won't be cleared by this 
+*		automatic SWReset. This allows the user to know if any watch dog event 
+*		ever occurred even if the swich is configured to automatically recover 
+*		from a watch dog.
+*
+*		When this feature is disabled, enabled watch dog events will not cause a
+*		SWReset.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en   - GT_TRUE, if SWReset on WD is enabled
+*			   GT_FALUSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdGetSWResetOnWD
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL	    *en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gwdSetSWResetOnWD Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_WATCHDOG_EVENT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the related bit. */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_WD_CONTROL, 0, 1, &data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *en);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gwdGetHistory
+*
+* DESCRIPTION:
+*		This routine retrieves Watch Dog history. They are
+*
+*		wdEvent - 
+*			When it's set to GT_TRUE, some enabled Watch Dog event occurred.
+*			The following events are possible:
+*				QC WatchDog Event (GT_WD_QC)
+*				Egress WatchDog Event (GT_WD_EGRESS)
+*				Forced WatchDog Event (GT_WD_FORCE)
+*		egressEvent -
+*			If any port's egress logic detects an egress watch dog issue,
+*			this field is set to GT_TRUE, regardless of the enabling GT_WD_EGRESS
+*			event.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		history - GT_WD_EVENT_HISTORY structure
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdGetHistory
+(
+	IN  GT_QD_DEV			*dev,
+	OUT GT_WD_EVENT_HISTORY	*history
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gwdSetSWResetOnWD Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_WATCHDOG_EVENT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the related bit. */
+    retVal = hwReadGlobal2Reg(dev,QD_REG_WD_CONTROL,&data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	    return retVal;
+	}
+
+	if (data & (1 << 4))
+	{
+		history->egressEvent = GT_TRUE;
+	}
+	else
+	{
+		history->egressEvent = GT_FALSE;
+	}
+
+	if (data & (1 << 1))
+	{
+		history->wdEvent = GT_TRUE;
+	}
+	else
+	{
+		history->wdEvent = GT_FALSE;
+	}
+
+	DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gwdSetRMUTimeOut
+*
+* DESCRIPTION:
+*		Remote Management Timeout. When this bit is set to a one the Remote
+*		Management Unit(RMU) will timeout on Wait on Bit commands. If the bit that
+*		is being tested has not gone to the specified value after 1 sec. has elapsed
+*		the Wait on Bit command will be terminated and the Response frame will be
+*		sent without any further processing.
+*
+*		When this bit is cleared to a zero the Wait on Bit command will wait 
+*		until the bit that is being tested has changed to the specified value.
+*
+* INPUTS:
+*		en   - GT_TRUE to enable RMU Timeout
+*			   GT_FALUSE to disable
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdSetRMUTimeOut
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL	    en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gwdSetRMUTimeOut Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_WATCHDOG_EVENT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the related bit. */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_WD_CONTROL, 6, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gwdGetRMUTimeOut
+*
+* DESCRIPTION:
+*		Remote Management Timeout. When this bit is set to a one the Remote
+*		Management Unit(RMU) will timeout on Wait on Bit commands. If the bit that
+*		is being tested has not gone to the specified value after 1 sec. has elapsed
+*		the Wait on Bit command will be terminated and the Response frame will be
+*		sent without any further processing.
+*
+*		When this bit is cleared to a zero the Wait on Bit command will wait 
+*		until the bit that is being tested has changed to the specified value.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en   - GT_TRUE to enable RMU Timeout
+*			   GT_FALUSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdGetRMUTimeOut
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL	    *en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gwdGetRMUTimeOut Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_WATCHDOG_EVENT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the related bit. */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_WD_CONTROL, 6, 1, &data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *en);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gwdGetEgressWDEvent
+*
+* DESCRIPTION:
+*		If any port's egress logic detects an egress watch dog issue, this bit
+*		will be set to a one, regardless of the setting of the GT_WD_EGRESS in
+*		gwdSetEvent function.
+*		
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		event - GT_TRUE, if egress logic has detected any egress watch dog issue
+*			    GT_FALUSE, otherwise
+*
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gwdGetEgressWDEvent
+(
+	IN  GT_QD_DEV		*dev,
+	OUT GT_BOOL			*event
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gwdGetEgressWDEvent Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_WATCHDOG_EVENT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the related bit. */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_WD_CONTROL, 7, 1, &data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *event);
+
+    return retVal;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtMisc.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtMisc.c
new file mode 100755
index 0000000..ec4e460
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtMisc.c
@@ -0,0 +1,2027 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtMisc.c
+*
+* DESCRIPTION:
+*       API definitions for Ip Mapping Table
+*							EEPROM access
+*							Scratch and Misc Control
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+/*******************************************************************************
+* gsysSetUseIpMappingTable
+*
+* DESCRIPTION:
+*       This API set to use IP Frame Priorities from this table. 
+*		Set GT_TRUE:  The IP_FPRI data in this table is used as the frameÂ’s 
+*			initial IP_FPRI use Ip Mappingg table priorities.
+*		Set GT_FALSE: The IP_FPRI data in this table is ignored. Instead the 
+*			frameÂ’s initial IP_FPRI is generated by using the frameÂ’s IP_QPRI
+*			as the IP_FPRIÂ’s upper two bits, and the IP_FPRIÂ’s lowest bit comes 
+*			from bit 0 of the frameÂ’s source portÂ’s Default PRI (Port offset 0x07).
+*
+* INPUTS:
+*		en	- [GT_TRUE] / [GT_FALSE]
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetUseIpMappingTable
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_BOOL			en
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data;
+
+    DBG_INFO(("gsysSetUseIpMappingTable Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_IP_MAPPING_TABLE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	data = (en==GT_TRUE)?1:0;
+
+    retVal = hwSetGlobalRegField(dev,QD_REG_IP_MAPPING_TABLE,14,1,data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetUseIpMappingTable
+*
+* DESCRIPTION:
+*       This API get to use IP Frame Priorities from this table. 
+*		Set GT_TRUE:  The IP_FPRI data in this table is used as the frameÂ’s 
+*			initial IP_FPRI use Ip Mappingg table priorities.
+*		Set GT_FALSE: The IP_FPRI data in this table is ignored. Instead the 
+*			frameÂ’s initial IP_FPRI is generated by using the frameÂ’s IP_QPRI
+*			as the IP_FPRIÂ’s upper two bits, and the IP_FPRIÂ’s lowest bit comes 
+*			from bit 0 of the frameÂ’s source portÂ’s Default PRI (Port offset 0x07).
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en	- [GT_TRUE] / [GT_FALSE]
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetUseIpMappingTable
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_BOOL			*en
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data;
+
+    DBG_INFO(("gsysGetUseIpMappingTable Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_IP_MAPPING_TABLE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+
+    retVal = hwGetGlobalRegField(dev,QD_REG_IP_MAPPING_TABLE,14,1,&data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	*en= (data==1)?GT_TRUE:GT_FALSE;
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetIpMappingPrio
+*
+* DESCRIPTION:
+*       Set IPv4 and IPv6 Frame Priority Mapping, and 
+*			IPv4 and IPv6 Queue Priority Mapping.
+*           The ipFpri value is used as the frames initial FPRI when the frame is 
+*			an IPv4 or an IPv6 frame, and the portÂ’s InitialPri (Port offset 0x04) 
+*			is configured to use IP FPriÂ’s.
+*           The ipQpri value is used as the frameÂ’s initial QPRI when the frame is 
+*			an IPv4 or an IPv6 frame, and the portÂ’s InitialPri and TagIfBoth 
+*			registers (Port offset 0x04) are configured to use IP QPriÂ’s.
+*
+* INPUTS:
+*       point - Pointer to the Ip Mapping Table.
+*				  0 - 0x3f;
+*       ipFpri -  The value is 0 - 7
+*       ipQpri -  The value is 0 - 3.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetIpMappingPrio
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			point,
+    IN  GT_U8			ipFpri,
+    IN  GT_U8			ipQpri
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data;
+
+    DBG_INFO(("gsysSetIpMappingPrio Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_IP_MAPPING_TABLE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if ((point>0x3f)||(ipFpri>7)||(ipQpri>3))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+    /* Wait until the Scratch and Misc control is ready. */
+   	data = 1;
+    while(data == 1)
+   	{
+        retVal = hwGetGlobalRegField(dev,QD_REG_IP_MAPPING_TABLE,15,1,&data);
+   	    if(retVal != GT_OK)
+       	{
+			gtSemGive(dev,dev->tblRegsSem);
+   	        return retVal;
+       	}
+    }
+
+	data = (((ipFpri&7)<<4) | (ipQpri&3));
+	data |=  ((GT_U16)((1 << 15) | (point << 8)));
+
+	retVal = hwWriteGlobalReg(dev, QD_REG_IP_MAPPING_TABLE, data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+        gtSemGive(dev,dev->tblRegsSem);
+   	    return retVal;
+    }
+
+
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetIpMappingPrio
+*
+* DESCRIPTION:
+*       get IPv4 and IPv6 Frame Priority Mapping, and 
+*			IPv4 and IPv6 Queue Priority Mapping.
+*           The ipFpri value is used as the frames initial FPRI when the frame is 
+*			an IPv4 or an IPv6 frame, and the portÂ’s InitialPri (Port offset 0x04) 
+*			is configured to use IP FPriÂ’s.
+*           The ipQpri value is used as the frameÂ’s initial QPRI when the frame is 
+*			an IPv4 or an IPv6 frame, and the portÂ’s InitialPri and TagIfBoth 
+*			registers (Port offset 0x04) are configured to use IP QPriÂ’s.
+*
+* INPUTS:
+*       point - Pointer to the Ip Mapping Table.
+*				  0 - 0x3f;
+*
+* OUTPUTS:
+*       ipFpri -  The value is 0 - 7
+*       ipQpri -  The value is 0 - 3.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetIpMappingPrio
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			point,
+    OUT  GT_U8			*ipFpri,
+    OUT  GT_U8			*ipQpri
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data;
+
+    DBG_INFO(("gsysGetIpMappingPrio Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_IP_MAPPING_TABLE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (point > 0x3f)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	do {
+		retVal = hwReadGlobalReg(dev, QD_REG_IP_MAPPING_TABLE, &data);
+		if(retVal != GT_OK)
+   		{
+   			DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+   			return retVal;
+		}
+	} while (data&0x8000);
+
+
+	*ipFpri = (data >> 4) & 7;
+	*ipQpri = (data) & 3;
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* eepromOperationPerform
+*
+* DESCRIPTION:
+*       This function accesses EEPROM Command Register and Data Register.
+*       The device supports the following EEPROM 
+*			operations
+*			GT_EEPROM_NO_OP = No Operation
+*			GT_EEPROM_WRITE_DATA = Write EEPROM at Addr.
+*			GT_EEPROM_READ_DATA = Read EEPROM from Addr.
+*			GT_EEPROM_RESTART = Restart Register Loader execution at Addr 
+*				(eepromData = donÂ’t care in this case)
+*			GT_EEPROM_HALT = Halt (stop executing the EEPROM if its not already 
+*				stopped)
+*
+* INPUTS:
+*       eepromOp      - EEPROM Opcode.
+*       eepromData    - Data to be written to the EEPROM 
+*
+* OUTPUTS:
+*       eepromData    - Data that was read back from the EEPROM. 
+*
+Command register above.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS eepromOperationPerform
+(
+    IN    GT_QD_DEV 			*dev,
+    IN    GT_EEPROM_OPERATION	eepromOp,
+    INOUT GT_EEPROM_OP_DATA		*opData
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+    DBG_INFO(("eepromOperationPerform Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_EEPROM))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (eepromOp>GT_EEPROM_HALT)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+    gtSemTake(dev,dev->eepromRegsSem,OS_WAIT_FOREVER);
+
+
+    /* Wait until the eeprom in ready. */
+    data = 1;
+    while(data == 1)
+    {
+        retVal = hwGetGlobal2RegField(dev,QD_REG_EEPROM_COMMAND,15,1,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->eepromRegsSem);
+            return retVal;
+        }
+    }
+
+
+    /* Set the EEPROM Operation register */
+	switch (eepromOp)
+	{
+		case GT_EEPROM_WRITE_DATA:
+		    retVal = hwGetGlobal2RegField(dev,QD_REG_EEPROM_COMMAND,10,1,&data);
+		    if(retVal != GT_OK)
+		    {
+		        gtSemGive(dev,dev->eepromRegsSem);
+		        return retVal;
+			}
+			if (data==0)
+		    {
+		        gtSemGive(dev,dev->eepromRegsSem);
+				DBG_INFO(("EEPROM is not writablen"));
+		        return GT_FAIL;
+			}
+
+		    retVal = hwGetGlobal2RegField(dev,QD_REG_EEPROM_COMMAND,11,1,&data);
+		    if(retVal != GT_OK)
+		    {
+		        gtSemGive(dev,dev->eepromRegsSem);
+		        return retVal;
+			}
+			if (data==1)
+		    {
+		        gtSemGive(dev,dev->eepromRegsSem);
+				DBG_INFO(("EEPROM Loader is running"));
+		        return GT_FAIL;
+			}
+
+			data = (GT_U16)opData->eepromData;
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_EEPROM_DATA,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->eepromRegsSem);
+            	return retVal;
+	        }
+
+			data = (GT_U16)((1 << 15) | (GT_EEPROM_WRITE_DATA << 12) | 
+					(opData->eepromAddr & 0xFF));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_EEPROM_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->eepromRegsSem);
+            	return retVal;
+	        }
+			break;
+
+		case GT_EEPROM_READ_DATA:
+		    retVal = hwGetGlobal2RegField(dev,QD_REG_EEPROM_COMMAND,11,1,&data);
+		    if(retVal != GT_OK)
+		    {
+		        gtSemGive(dev,dev->eepromRegsSem);
+		        return retVal;
+			}
+			if (data==1)
+		    {
+		        gtSemGive(dev,dev->eepromRegsSem);
+				DBG_INFO(("EEPROM Loader is running"));
+		        return GT_FAIL;
+			}
+
+			data = (GT_U16)((1 << 15) | (GT_EEPROM_READ_DATA << 12) | 
+					(opData->eepromAddr & 0xFF));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_EEPROM_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->eepromRegsSem);
+            	return retVal;
+	        }
+
+			
+		    data = 1;
+		    while(data == 1)
+		    {
+		        retVal = hwGetGlobal2RegField(dev,QD_REG_EEPROM_COMMAND,15,1,&data);
+		        if(retVal != GT_OK)
+		        {
+		            gtSemGive(dev,dev->eepromRegsSem);
+		            return retVal;
+        		}
+		    }
+			
+
+			retVal = hwReadGlobal2Reg(dev,QD_REG_EEPROM_DATA,&data);
+			opData->eepromData = (GT_U32)data;
+
+			break;
+
+		case GT_EEPROM_RESTART:
+			data = (GT_U16)((1 << 15) | (GT_EEPROM_RESTART << 12) | 
+					(opData->eepromAddr & 0xFF));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_EEPROM_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->eepromRegsSem);
+            	return retVal;
+	        }
+
+
+			break;
+
+		case GT_EEPROM_HALT:
+			data = (GT_U16)((1 << 15) | (GT_EEPROM_HALT << 12) | 
+					(opData->eepromAddr & 0xFF));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_EEPROM_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->eepromRegsSem);
+            	return retVal;
+	        }
+
+			break;
+		default:
+			gtSemGive(dev,dev->eepromRegsSem);
+			return GT_FAIL;
+	}
+
+	gtSemGive(dev,dev->eepromRegsSem);
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysReadEeprom
+*
+* DESCRIPTION:
+*       Read EEPROM from EEPROMÂ’s address where the EEOp is performed.
+*
+* INPUTS:
+*       addr - EEPROM Address. 
+*
+* OUTPUTS:
+*       data -  Data that was read back from the EEPROM.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysReadEeprom
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			addr,
+    OUT  GT_U8			*data
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+    GT_EEPROM_OPERATION	eepromOp;
+    GT_EEPROM_OP_DATA	opData;
+ 
+	eepromOp = GT_EEPROM_READ_DATA;
+	opData.eepromAddr = addr;
+
+	retVal = eepromOperationPerform(dev,eepromOp,&opData);
+    if(retVal != GT_OK)
+    {
+      return retVal;
+    }
+	*data = (GT_U8)opData.eepromData;
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysWriteEeprom
+*
+* DESCRIPTION:
+*       Write EEPROM at the EEPROMÂ’s address where the EEOp is performed.
+
+*
+* INPUTS:
+*       addr - EEPROM Address. 
+*       data - Data to be written to the EEPROM
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysWriteEeprom
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			addr,
+    IN  GT_U8			data
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+    GT_EEPROM_OPERATION	eepromOp;
+    GT_EEPROM_OP_DATA	opData;
+ 
+	eepromOp = GT_EEPROM_WRITE_DATA;
+	opData.eepromAddr = addr;
+	opData.eepromData = data;
+
+	retVal = eepromOperationPerform(dev,eepromOp,&opData);
+    if(retVal != GT_OK)
+    {
+      return retVal;
+    }
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysRestartEeprom
+*
+* DESCRIPTION:
+*       Restart Register Loader execution at the EEPROMÂ’s address where the EEOp 
+*		is performed
+*
+* INPUTS:
+*       addr - EEPROM Address. .
+*
+* OUTPUTS:
+*       none   
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysRestartEeprom
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			addr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+    GT_EEPROM_OPERATION	eepromOp;
+    GT_EEPROM_OP_DATA	opData;
+ 
+	eepromOp = GT_EEPROM_RESTART;
+	opData.eepromAddr = addr;
+
+	retVal = eepromOperationPerform(dev,eepromOp,&opData);
+    if(retVal != GT_OK)
+    {
+      return retVal;
+    }
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysHaltEeprom
+*
+* DESCRIPTION:
+*       Halt (stop executing the EEPROM if its not already stopped)
+
+*
+* INPUTS:
+*       none  .
+*
+* OUTPUTS:
+*       none   
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysHaltEeprom
+(
+    IN  GT_QD_DEV 		*dev
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+    GT_EEPROM_OPERATION	eepromOp;
+    GT_EEPROM_OP_DATA	opData;
+ 
+	eepromOp = GT_EEPROM_HALT;
+
+	retVal = eepromOperationPerform(dev,eepromOp,  &opData);
+    if(retVal != GT_OK)
+    {
+      return retVal;
+    }
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetStEeprom
+*
+* DESCRIPTION:
+*       Get EEPROM status. They are Register Loader Running status and EEPROM 
+*		Write Enable status
+*       runSt is GT_TRUE: Register Loader Running, whenever the register loader 
+*			is busy executing the instructions contained in the EEPROM.
+*       writeEn is GT_TRUE: EEPROM Write Enable, that indicates that writing to 
+*			the EEPROM is possible. 
+*		writeEn is GT_FALSE: the Write EEPROM EEOp above will not do anything.
+*			This reflects the value of the EE_WE configuration pin after Reset.
+*
+* INPUTS:
+*       none  .
+*
+* OUTPUTS:
+*       runSt   -   [GT_TRUE] / [GT_FALSE)
+*       writeEn -   [GT_TRUE] / [GT_FALSE)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetStEeprom
+(
+    IN  GT_QD_DEV 		*dev,
+	OUT GT_BOOL			*writeEn,
+	OUT GT_BOOL			*runSt
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+    GT_U16      data; 			/* temporary Data storage */
+ 
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_EEPROM))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = hwReadGlobal2Reg(dev,QD_REG_EEPROM_COMMAND, &data);
+    if(retVal != GT_OK)
+    {
+       	return retVal;
+    }
+
+
+	*runSt   = (data&GT_EEPROM_OP_ST_RUNNING_MASK)?GT_TRUE:GT_FALSE;
+	*writeEn = (data&GT_EEPROM_OP_ST_WRITE_EN_MASK)?GT_TRUE:GT_FALSE;
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysSetScratchMiscCtrl
+*
+* DESCRIPTION:
+*       Set Scratch and Misc control data to the Pointer to the Scratch and Misc. 
+*		Control register.
+*				Scratch Byte 0
+*				Scratch Byte 1
+*				GPIO Configuration
+*				Reserved for future use
+*				GPIO Direction
+*				GPIO Data
+*				CONFIG Data 0
+*				CONFIG Data 1
+*				CONFIG Data 2
+*				CONFIG Data 3
+*				SyncE & TAICLK125Â’s Drive
+*				P5Â’s & CLK125Â’s Clock Drive
+*				P6Â’s Clock Drive
+*				EEPROM Pad drive
+*
+* INPUTS:
+*       point - Pointer to the Scratch and Misc. Control register.
+*       data - Scratch and Misc. Control data written to the register 
+*				pointed to by the point above.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetScratchMiscCtrl
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			point,
+    IN  GT_U8			data
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+    IN  GT_U16			tmpData;
+
+	if (point > GT_SCRAT_MISC_REG_MAX)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	if ((point>0x7f)||(data>0xff))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* program QoS Weight Table, 4 sequences at a time */
+
+    /* Wait until the Scratch and Misc control is ready. */
+   	tmpData = 1;
+    while(tmpData == 1)
+   	{
+        retVal = hwGetGlobal2RegField(dev,QD_REG_SCRATCH_MISC,15,1,&tmpData);
+   	    if(retVal != GT_OK)
+       	{
+			gtSemGive(dev,dev->tblRegsSem);
+   	        return retVal;
+       	}
+    }
+
+	tmpData =  (GT_U16)((1 << 15) | (point << 8) | data);
+
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_SCRATCH_MISC, tmpData);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+           gtSemGive(dev,dev->tblRegsSem);
+   	    return retVal;
+    }
+
+
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+   	return retVal;
+
+}
+
+
+/*******************************************************************************
+* gsysGetScratchMiscCtrl
+*
+* DESCRIPTION:
+*       Get Scratch and Misc control data to the Pointer to the Scratch and Misc. 
+*		Control register.
+*				Scratch Byte 0
+*				Scratch Byte 1
+*				GPIO Configuration
+*				Reserved for future use
+*				GPIO Direction
+*				GPIO Data
+*				CONFIG Data 0
+*				CONFIG Data 1
+*				CONFIG Data 2
+*				CONFIG Data 3
+*				SyncE & TAICLK125Â’s Drive
+*				P5Â’s & CLK125Â’s Clock Drive
+*				P6Â’s Clock Drive
+*				EEPROM Pad drive
+
+*
+* INPUTS:
+*       point - Pointer to the Scratch and Misc. Control register.
+*
+* OUTPUTS:
+*       data - Scratch and Misc. Control data read from the register 
+*				pointed to by the point above.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetScratchMiscCtrl
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			point,
+    OUT  GT_U8			*data
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+    OUT  GT_U16			tmpData;
+
+	if (point > GT_SCRAT_MISC_REG_MAX)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	if (point>0x7f)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* program QoS Weight Table, 4 sequences at a time */
+
+	do {
+		retVal = hwReadGlobal2Reg(dev, QD_REG_SCRATCH_MISC, &tmpData);
+		if(retVal != GT_OK)
+   		{
+   			DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+   			return retVal;
+		}
+	} while (tmpData&0x8000);
+
+    *data = tmpData&0xff;
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gsysSetScratchBits
+*
+* DESCRIPTION:
+*       Set the Scratch and Misc. Control register <scratch byte 0 and 1> bits.
+*		Scratch bits. These bits are 100% available to software for whatever 
+*		purpose desired. These bits do not connect to any hardware function.
+*
+* INPUTS:
+*       scritch - written bits.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetScratchBits
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U16			scratch
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetScratchBits Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_SCRAT_0, (GT_U8)(scratch&0xff));
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_SCRAT_1, (GT_U8)((scratch>>8)&0xff));
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetScratchBits
+*
+* DESCRIPTION:
+*       Get the Scratch and Misc. Control register <scratch byte 0 and 1> bits.
+*		Scratch bits. These bits are 100% available to software for whatever 
+*		purpose desired. These bits do not connect to any hardware function.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       scritch - read bits.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetScratchBits
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U16			*scratch
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysGetScratchBits Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_SCRAT_1, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+	*scratch = data;
+	*scratch = *scratch<<8;
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_SCRAT_0, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+	
+	*scratch |= data;
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysSetGpioConfigMod
+*
+* DESCRIPTION:
+*       Set the Scratch and Misc. Control register <GPIO Configuration>.
+*		General Purpose Input Output Bits:
+*		Bit 6 - GT_GPIO_BIT_6:	1:GPIO[6]	0:SE_RCLK1
+*		Bit 5 - GT_GPIO_BIT_5:	1:GPIO[5]	0:SE_RCLK0
+*		Now, folloing bits are read only. 
+*		Bit 4 - GT_GPIO_BIT_4:	1:GPIO[4]	0:
+*		Bit 3 - GT_GPIO_BIT_3:	1:GPIO[3]	0:
+*		Bit 2 - GT_GPIO_BIT_2:	1:GPIO[2]	0:
+*		Bit 1 - GT_GPIO_BIT_1:	1:GPIO[1]	0:P6_COL
+*		Bit 0 - GT_GPIO_BIT_0:	1:GPIO[0]	0:P6_CRS
+
+*
+* INPUTS:
+*       mode - OR [GT_GPIO_BIT_x]
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetGpioConfigMod
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			mode
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetGpioConfigMod Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_GPIO_CFG, (GT_U8)(mode&0x7f));
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetGpioConfigMod
+*
+* DESCRIPTION:
+*       Get the Scratch and Misc. Control register <GPIO Configuration>.
+*		General Purpose Input Output Bits:
+*		Bit 6 - GT_GPIO_BIT_6:	1:GPIO[6]	0:SE_RCLK1
+*		Bit 5 - GT_GPIO_BIT_5:	1:GPIO[5]	0:SE_RCLK0
+*		Now, folloing bits are read only. 
+*		Bit 4 - GT_GPIO_BIT_4:	1:GPIO[4]	0:
+*		Bit 3 - GT_GPIO_BIT_3:	1:GPIO[3]	0:
+*		Bit 2 - GT_GPIO_BIT_2:	1:GPIO[2]	0:
+*		Bit 1 - GT_GPIO_BIT_1:	1:GPIO[1]	0:P6_COL
+*		Bit 0 - GT_GPIO_BIT_0:	1:GPIO[0]	0:P6_CRS
+
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - OR [GT_GPIO_BIT_x]
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetGpioConfigMod
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			*mode
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysGetGpioConfigMod Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_GPIO_CFG, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+	
+	*mode = 0x7f&data;
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysSetGpioDirection
+*
+* DESCRIPTION:
+*       Set the Scratch and Misc. Control register <GPIO Direction>.
+*		General Purpose Input Output Bits:
+*		Bit 6 - GT_GPIO_BIT_6:	1:GPIO[6]	0:SE_RCLK1
+*		Bit 5 - GT_GPIO_BIT_5:	1:GPIO[5]	0:SE_RCLK0
+*		Now, folloing bits are read only. 
+*		Bit 4 - GT_GPIO_BIT_4:	1:GPIO[4]	0:
+*		Bit 3 - GT_GPIO_BIT_3:	1:GPIO[3]	0:
+*		Bit 2 - GT_GPIO_BIT_2:	1:GPIO[2]	0:
+*		Bit 1 - GT_GPIO_BIT_1:	1:GPIO[1]	0:P6_COL
+*		Bit 0 - GT_GPIO_BIT_0:	1:GPIO[0]	0:P6_CRS
+*
+* INPUTS:
+*       dir - OR [GT_GPIO_BIT_x]
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetGpioDirection
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			dir
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetGpioDirection Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_GPIO_DIR, (GT_U8)(dir&0x7f));
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetGpioDirection
+*
+* DESCRIPTION:
+*       Get the Scratch and Misc. Control register <GPIO Direction>.
+*		General Purpose Input Output Bits:
+*		Bit 6 - GT_GPIO_BIT_6:	1:GPIO[6]	0:SE_RCLK1
+*		Bit 5 - GT_GPIO_BIT_5:	1:GPIO[5]	0:SE_RCLK0
+*		Now, folloing bits are read only. 
+*		Bit 4 - GT_GPIO_BIT_4:	1:GPIO[4]	0:
+*		Bit 3 - GT_GPIO_BIT_3:	1:GPIO[3]	0:
+*		Bit 2 - GT_GPIO_BIT_2:	1:GPIO[2]	0:
+*		Bit 1 - GT_GPIO_BIT_1:	1:GPIO[1]	0:P6_COL
+*		Bit 0 - GT_GPIO_BIT_0:	1:GPIO[0]	0:P6_CRS
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       dir - OR [GT_GPIO_BIT_x]
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetGpioDirection
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U32			*dir
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysGetGpioDirection Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_GPIO_DIR, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	*dir = data;
+
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gsysSetGpioData
+*
+* DESCRIPTION:
+*       Set the Scratch and Misc. Control register <GPIO data>.
+*		General Purpose Input Output Bits:
+*		Bit 6 - GT_GPIO_BIT_6:	1:GPIO[6]	0:SE_RCLK1
+*		Bit 5 - GT_GPIO_BIT_5:	1:GPIO[5]	0:SE_RCLK0
+*		Now, folloing bits are read only. 
+*		Bit 4 - GT_GPIO_BIT_4:	1:GPIO[4]	0:
+*		Bit 3 - GT_GPIO_BIT_3:	1:GPIO[3]	0:
+*		Bit 2 - GT_GPIO_BIT_2:	1:GPIO[2]	0:
+*		Bit 1 - GT_GPIO_BIT_1:	1:GPIO[1]	0:P6_COL
+*		Bit 0 - GT_GPIO_BIT_0:	1:GPIO[0]	0:P6_CRS
+*
+* INPUTS:
+*       data - OR [GT_GPIO_BIT_x]
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetGpioData
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			data
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetGpioData Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_GPIO_DAT, (GT_U8)(data&0x7f));
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetGpioData
+*
+* DESCRIPTION:
+*       Get the Scratch and Misc. Control register <GPIO data>.
+*		General Purpose Input Output Bits:
+*		Bit 6 - GT_GPIO_BIT_6:	1:GPIO[6]	0:SE_RCLK1
+*		Bit 5 - GT_GPIO_BIT_5:	1:GPIO[5]	0:SE_RCLK0
+*		Now, folloing bits are read only. 
+*		Bit 4 - GT_GPIO_BIT_4:	1:GPIO[4]	0:
+*		Bit 3 - GT_GPIO_BIT_3:	1:GPIO[3]	0:
+*		Bit 2 - GT_GPIO_BIT_2:	1:GPIO[2]	0:
+*		Bit 1 - GT_GPIO_BIT_1:	1:GPIO[1]	0:P6_COL
+*		Bit 0 - GT_GPIO_BIT_0:	1:GPIO[0]	0:P6_CRS
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       data - OR [GT_GPIO_BIT_x]
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetGpioData
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U32			*data
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		tmpData;
+
+    DBG_INFO(("gsysGetGpioData Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_GPIO_DAT, &tmpData);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	*data = tmpData;
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetConfigData
+*
+* DESCRIPTION:
+*       Get Reset Configuration pin data 0-3. 
+*		These registers return the values observed after a hardware Reset on the 
+*		listed CONFIG data listed below.
+*			Config data 0:
+*				0 USER[0] P6_OUTD[5]
+*				1 USER[1] P6_OUTD[6]
+*				2 USER[2] P6_OUTD[7]
+*				3 ADDR[0] P5_OUTD[0]
+*				4 ADDR[1] P5_OUTD[5]
+*				5 ADDR[2] P5_OUTD[6]
+*				6 ADDR]3] P5_OUTD[7]
+*				7 ADDR[4] P5_OUTD[1]
+*			Config data 1:
+*				0 LED_SEL[0] P1_LED
+*				1 LED_SEL[1] P2_LED
+*				2 4COL P3_LED
+*				3 NormCx P4_LED
+*				4 Jumbo P0_LED
+*				5 EE_WE EE_CS/C2_LED
+*				6 FD_FLOW EE_CLK/C1_LED
+*				7 HD_FLOW EE_DIN/C0_LED
+*			Config data 2:
+*				0 P5_MODE[0] P5_OUTD[2]
+*				1 P5_MODE[1] P5_OUTD[3]
+*				2 P5_MODE[2] P5_OUTD[4]
+*				3 Reserved for future useP5_HALFDPX P5_OUTEN
+*				4 P6_MODE[0] P6_OUTD[2]
+*				5 P6_MODE[1] P6_OUTD[3]
+*				6 P6_MODE[2] P6_OUTD[4]
+*				7 Reserved for future useP6_HALFDPX P6_OUTEN
+*			Config data 2:
+*				0 RMU_MODE[0] P6_OUTD[0]
+*				1 RMU_MODE[1] P6_OUTD[1]
+*				2 
+*				3
+*				4
+*				5
+*				6
+*				7
+
+* INPUTS:
+*       none.
+*
+* OUTPUTS:
+*       cfgDat - GT_CONFIG_DTTA
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetConfigData
+(
+    IN  GT_QD_DEV 			*dev,
+    OUT  GT_CONFIG_DATA		*cfgData
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		tmpData;
+
+    DBG_INFO(("gsysGetConfigData Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_CFG_DAT0, &tmpData);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	cfgData->cfgData0.Byte = tmpData;
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_CFG_DAT1, &tmpData);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	cfgData->cfgData1.Byte = tmpData;
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_CFG_DAT2, &tmpData);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	cfgData->cfgData2.Byte = tmpData;
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_CFG_DAT3, &tmpData);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	cfgData->cfgData3.Byte = tmpData;
+
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gsysSetSyncETai
+*
+* DESCRIPTION:
+*       Set the Scratch and Misc. Control register <SyncE and TAI pad>.
+*
+* INPUTS:
+*       zpr - ZPR for SyncE and TAI
+*       znr - ZNR for SyncE and TAI
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetSyncETai
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8			zpr,
+    IN  GT_U8			znr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysSetSyncETai Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if ((zpr>0x7) || (znr>0x7))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	data = ((zpr&0x7)<<3) | (znr&0x7);
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_SYNCE, data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetSyncETai
+*
+* DESCRIPTION:
+*       Get the Scratch and Misc. Control register <SyncE and TAI pad>.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       zpr - ZPR for SyncE and TAI
+*       znr - ZNR for SyncE and TAI*
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetSyncETai
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U8			*zpr,
+    OUT  GT_U8			*znr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysGetSyncETai Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_SYNCE, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+	
+	*zpr = 0x7 &(data>>3);
+	*znr = 0x7 &(data);
+
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gsysSetP6_Clock
+*
+* DESCRIPTION:
+*       Set the Scratch and Misc. Control register <P6_Clock pad>.
+*
+* INPUTS:
+*       zpr - ZPR for P6_Clock
+*       znr - ZNR for P6_Clock
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetP6_Clock
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8			zpr,
+    IN  GT_U8			znr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysSetP6_Clock Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if ((zpr>0x7) || (znr>0x7))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	data = ((zpr&0x7)<<3) | (znr&0x7);
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_P6_CLK, data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetP6_Clock
+*
+*       Get the Scratch and Misc. Control register <P6_Clock pad>.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       zpr - ZPR for P6_Clock
+*       znr - ZNR for P6_Clock*
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetP6_Clock
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U8			*zpr,
+    OUT  GT_U8			*znr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysGetP6_Clock Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_P6_CLK, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+	
+	*zpr = 0x7 &(data>>3);
+	*znr = 0x7 &(data);
+
+	return GT_OK;
+
+}
+
+
+
+/*******************************************************************************
+* gsysSetP5_Clock
+*
+* DESCRIPTION:
+*       Set the Scratch and Misc. Control register <P5_Clock pad>.
+*
+* INPUTS:
+*       zpr - ZPR for P5_Clock
+*       znr - ZNR for P5_Clock
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetP5_Clock
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8			zpr,
+    IN  GT_U8			znr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysSetP5_Clock Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if ((zpr>0x7) || (znr>0x7))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	data = ((zpr&0x7)<<3) | (znr&0x7);
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_P5_CLK, data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetP5_Clock
+*
+* DESCRIPTION:
+*       Get the Scratch and Misc. Control register <P5_Clock pad>.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       zpr - ZPR for P5_Clock
+*       znr - ZNR for P5_Clock
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetP5_Clock
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U8			*zpr,
+    OUT  GT_U8			*znr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysGetP6_Clock Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_P5_CLK, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+	
+	*zpr = 0x7 &(data>>3);
+	*znr = 0x7 &(data);
+
+	return GT_OK;
+
+}
+
+
+
+/*******************************************************************************
+* gsysSetEEPROM
+*
+* DESCRIPTION:
+*       Set the Scratch and Misc. Control register <EEPROM pad>.
+*
+* INPUTS:
+*       dsm - DSM for EEPROM
+*       zpr - ZPR for EEPROM
+*       znr - ZNR for EEPROM
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetEEPROM
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8			dsm,
+    IN  GT_U8			zpr,
+    IN  GT_U8			znr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysSetEEPROM Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if ((zpr>0x7) || (znr>0x7))
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	data = ((dsm&0x3)<<6) | ((zpr&0x7)<<3) | (znr&0x7);
+
+	retVal = gsysSetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_EEPROM, data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gsysGetEEPROM
+*
+* DESCRIPTION:
+*       Get the Scratch and Misc. Control register <EEPROM pad>.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       dsm - DSM for EEPROM
+*       zpr - ZPR for EEPROM
+*       znr - ZNR for EEPROM
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetEEPROM
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT  GT_U8			*dsm,
+    OUT  GT_U8			*zpr,
+    OUT  GT_U8			*znr
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8		data;
+
+    DBG_INFO(("gsysGetEEPROM Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SCRATCH_MISC_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = gsysGetScratchMiscCtrl(dev, GT_SCRAT_MISC_REG_EEPROM, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+	
+	*dsm = 0x3 &(data>>6);
+	*zpr = 0x7 &(data>>3);
+	*znr = 0x7 &(data);
+
+	return GT_OK;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPCSCtrl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPCSCtrl.c
new file mode 100755
index 0000000..b30b308
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPCSCtrl.c
@@ -0,0 +1,1878 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPCSCtrl.c
+*
+* DESCRIPTION:
+*       API implementation for 1000BASE-X PCS block register access.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+/*******************************************************************************
+* gpcsGetCommaDet
+*
+* DESCRIPTION:
+*		This routine retrieves Comma Detection status in PCS
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE for Comma Detected or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetCommaDet
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetCommaDet Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PCS_LINK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the CommaDet bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,15,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetPCSLink
+*
+* DESCRIPTION:
+*		This routine retrieves Link up status in PCS
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE for Comma Detected or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetPCSLink
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetPCSLink Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS_LINK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the PCS Link bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,15,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetSyncOK
+*
+* DESCRIPTION:
+*		This routine retrieves SynOK bit. It is set to a one when the PCS has
+*		detected a few comma patterns and is synchronized with its peer PCS 
+*		layer.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if synchronized or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetSyncOK
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetSyncOK Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the SyncOK bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,14,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gpcsGetSyncFail
+*
+* DESCRIPTION:
+*		This routine retrieves SynFail bit.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if synchronizaion failed or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetSyncFail
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetSyncFail Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the SyncFail bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,13,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gpcsGetAnBypassed
+*
+* DESCRIPTION:
+*		This routine retrieves Inband Auto-Negotiation bypass status.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if AN is bypassed or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetAnBypassed
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetAnBypassed Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the AnBypassed bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,12,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetAnBypassMode
+*
+* DESCRIPTION:
+*		This routine retrieves Enable mode of Inband Auto-Negotiation bypass.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE if AN bypass is enabled or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetAnBypassMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetAnBypassMode Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the AnBypass bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,11,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gpcsSetAnBypassMode
+*
+* DESCRIPTION:
+*		This routine retrieves Enable mode of Inband Auto-Negotiation bypass.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to enable AN bypass mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetAnBypassMode
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL  	mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetAnBypassMode Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the AnBypass bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,11,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetPCSAnEn
+*
+* DESCRIPTION:
+*		This routine retrieves Enable mode of PCS Inband Auto-Negotiation.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE if PCS AN is enabled or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetPCSAnEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetPCSAnEn Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        if (!IS_IN_DEV_GROUP(dev, DEV_INTERNAL_GPHY))
+        {
+            DBG_INFO(("GT_NOT_SUPPORTED\n"));
+	    	return GT_NOT_SUPPORTED;
+        }
+
+        if ((hwPort < 4) || (hwPort > 7))
+        {
+            DBG_INFO(("GT_NOT_SUPPORTED\n"));
+	    	return GT_NOT_SUPPORTED;
+        }
+    }
+
+    /* Get the PCSAnEn bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,10,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gpcsSetPCSAnEn
+*
+* DESCRIPTION:
+*		This routine sets Enable mode of PCS Inband Auto-Negotiation.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to enable PCS AN mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetPCSAnEn
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL  	mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetPCSAnEn Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        if (!IS_IN_DEV_GROUP(dev, DEV_INTERNAL_GPHY))
+        {
+            DBG_INFO(("GT_NOT_SUPPORTED\n"));
+	    	return GT_NOT_SUPPORTED;
+        }
+
+        if ((hwPort < 4) || (hwPort > 7))
+        {
+            DBG_INFO(("GT_NOT_SUPPORTED\n"));
+	    	return GT_NOT_SUPPORTED;
+        }
+    }
+
+    /* Get the PCSAnEn bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,10,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gpcsSetRestartPCSAn
+*
+* DESCRIPTION:
+*		This routine restarts PCS Inband Auto-Negotiation.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetRestartPCSAn
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetRestartPCSAn Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    data = 1;	/* to set RestartPCSAn bit */
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the RestartPCSAn bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,9,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetPCSAnDone
+*
+* DESCRIPTION:
+*		This routine retrieves completion information of PCS Auto-Negotiation.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE if PCS AN is done or never done
+*			    GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetPCSAnDone
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetPCSAnDone Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PCS))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given port supports PCS */
+	if (!DOES_DEVPORT_SUPPORT_PCS(dev,hwPort))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the PCSAnDone bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,8,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsSetFCValue
+*
+* DESCRIPTION:
+*		This routine sets Flow Control's force value
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force flow control enabled, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetFCValue
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetFCValue Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FC_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(state, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Set the FCValue bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,7,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetFCValue
+*
+* DESCRIPTION:
+*		This routine retrieves Flow Control Value which will be used for Forcing 
+*		Flow Control enabled or disabled.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if FC Force value is one (flow control enabled)
+*			     GT_FALSE otherwise (flow control disabled)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetFCValue
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetFCValue Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FC_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the FCValue bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,7,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsSetForcedFC
+*
+* DESCRIPTION:
+*		This routine forces Flow Control. If FCValue is set to one, calling this 
+*		routine with GT_TRUE will force Flow Control to be enabled.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force flow control (enable or disable), GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetForcedFC
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetForcedFC Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FC_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(state, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the ForcedFC bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,6,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetForcedFC
+*
+* DESCRIPTION:
+*		This routine retrieves Forced Flow Control bit
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if ForcedFC bit is one,
+*			     GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetForcedFC
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetForcedLink Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FC_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the ForcedLink bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,6,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gpcsSetLinkValue
+*
+* DESCRIPTION:
+*		This routine sets Link's force value
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force link up, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetLinkValue
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetLinkValue Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(state, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the LinkValue bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,5,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetLinkValue
+*
+* DESCRIPTION:
+*		This routine retrieves Link Value which will be used for Forcing Link 
+*		up or down.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Link Force value is one (link up)
+*			     GT_FALSE otherwise (link down)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetLinkValue
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetLinkValue Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the LinkValue bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,5,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsSetForcedLink
+*
+* DESCRIPTION:
+*		This routine forces Link. If LinkValue is set to one, calling this 
+*		routine with GT_TRUE will force Link to be up.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force link (up or down), GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetForcedLink
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetForcedLink Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(state, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the ForcedLink bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,4,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetForcedLink
+*
+* DESCRIPTION:
+*		This routine retrieves Forced Link bit
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if ForcedLink bit is one,
+*			     GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetForcedLink
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetForcedLink Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the ForcedLink bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,4,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsSetDpxValue
+*
+* DESCRIPTION:
+*		This routine sets Duplex's Forced value. This function needs to be
+*		called prior to gpcsSetForcedDpx.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force full duplex, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetDpxValue
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetDpxValue Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(state, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the DpxValue bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,3,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetDpxValue
+*
+* DESCRIPTION:
+*		This routine retrieves Duplex's Forced value
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Duplex's Forced value is set to Full duplex,
+*			     GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetDpxValue
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetForcedLink Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the DpxValue bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,3,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsSetForcedDpx
+*
+* DESCRIPTION:
+*		This routine forces duplex mode. If DpxValue is set to one, calling this 
+*		routine with GT_TRUE will force duplex mode to be full duplex.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE to force duplex mode, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetForcedDpx
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN	GT_BOOL		state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetForcedDpx Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(state, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the ForcedDpx bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,2,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetForcedDpx
+*
+* DESCRIPTION:
+*		This routine retrieves Forced Duplex.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if ForcedDpx bit is one,
+*			     GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetForcedDpx
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetForcedDpx Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the ForcedDpx bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,2,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsSetForceSpeed
+*
+* DESCRIPTION:
+*		This routine forces Speed.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_PORT_FORCED_SPEED_MODE (10, 100, 1000, or no force speed)
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetForceSpeed
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_PORT_FORCED_SPEED_MODE  mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsSetForceSpeed Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Set the Force Speed bits.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,0,2,(GT_U16)mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetForceSpeed
+*
+* DESCRIPTION:
+*		This routine retrieves Force Speed value
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_PORT_FORCED_SPEED_MODE (10, 100, 1000, or no force speed)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetForceSpeed
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_PORT_FORCED_SPEED_MODE   *mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gpcsGetForceSpeed Called.\n"));
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FORCE_WITH_VALUE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the ForceSpeed bits.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,0,2,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+	
+	*mode = data;
+
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gpcsGetRGMIITimingDelay
+*
+* DESCRIPTION:
+*		RGMII receive/transmit Timing Control. This api adds delay to RXCLK for
+*		IND inputs and GTXCLK for OUTD outputs when port is in RGMII mode.
+*		Change to this bit are disruptive to normal operation. Hence any changes
+*		to this register must be done only while the port's link is down.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		rxmode - GT_FALSE for default setup, GT_TRUE for adding delay to rxclk
+*		txmode - GT_FALSE for default setup, GT_TRUE for adding delay to txclk
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gpcsGetRGMIITimingDelay
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*rxmode,
+	OUT GT_BOOL  	*txmode
+)
+{
+	GT_U16          data;
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gpcsGetRGMIITimingDelay Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_RGMII_TIMING))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	if (hwPort < (dev->maxPorts - 2))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get the register bit(s).  */
+	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,14,2,&data);
+
+	*rxmode = (data & 0x2)?GT_TRUE:GT_FALSE;
+	*txmode = (data & 0x1)?GT_TRUE:GT_FALSE;
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	/* return */
+	return retVal;
+}
+
+/*******************************************************************************
+* gpcsSetRGMIITimingDelay
+*
+* DESCRIPTION:
+*		RGMII receive/transmit Timing Control. This api adds delay to RXCLK for
+*		IND inputs and GTXCLK for OUTD outputs when port is in RGMII mode.
+*		Change to this bit are disruptive to normal operation. Hence any changes
+*		to this register must be done only while the port's link is down.
+*
+* INPUTS:
+*		port - the logical port number.
+*		rxmode - GT_FALSE for default setup, GT_TRUE for adding delay to rxclk
+*		txmode - GT_FALSE for default setup, GT_TRUE for adding delay to txclk
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gpcsSetRGMIITimingDelay
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_BOOL  	rxmode,
+	IN  GT_BOOL  	txmode
+)
+{
+	GT_U16          data;
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gpcsSetRGMIITimingDelay Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_RGMII_TIMING))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	if (hwPort < (dev->maxPorts - 2))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	data = (rxmode) ? 2 : 0;
+	data |= (txmode) ? 1 : 0;
+
+	/* Set the register bit(s).  */
+	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,14,2,data);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	/* return */
+	return retVal;
+}
+
+
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL.c
new file mode 100755
index 0000000..3132160
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL.c
@@ -0,0 +1,1771 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtPIRL.c
+*
+* DESCRIPTION:
+*       API definitions for PIRL Resources
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/****************************************************************************/
+/* STATS operation function declaration.                                    */
+/****************************************************************************/
+static GT_STATUS pirlOperationPerform
+(
+    IN   GT_QD_DEV            *dev,
+    IN   GT_PIRL_OPERATION    pirlOp,
+    INOUT GT_PIRL_OP_DATA     *opData
+);
+
+static GT_STATUS pirlInitialize
+(
+    IN  GT_QD_DEV  			*dev
+);
+
+static GT_STATUS pirlInitIRLUnit
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlUnit
+);
+
+static GT_STATUS pirlDataToResource
+(
+    IN  GT_QD_DEV  			*dev,
+    IN  GT_PIRL_DATA		*pirlData,
+    OUT GT_PIRL_RESOURCE	*res
+);
+
+static GT_STATUS pirlResourceToData
+(
+    IN  GT_QD_DEV  			*dev,
+    IN  GT_PIRL_RESOURCE	*res,
+    OUT GT_PIRL_DATA		*pirlData
+);
+
+static GT_STATUS pirlWriteResource
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlUnit,
+    IN  GT_PIRL_RESOURCE	*res
+);
+
+static GT_STATUS pirlReadResource
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlUnit,
+    OUT GT_PIRL_RESOURCE	*res
+);
+
+static GT_STATUS pirlSetPortVec
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_U32		irlUnit,
+	IN  GT_U32		portVec
+);
+
+static GT_STATUS pirlGetPortVec
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_U32		irlUnit,
+	OUT GT_U32		*portVec
+);
+
+static GT_STATUS pirlSetFcMode
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_PIRL_FC_DEASSERT		mode
+);
+
+/*******************************************************************************
+* gpirlActivate
+*
+* DESCRIPTION:
+*       This routine activates Ingress Rate Limiting for the given ports by 
+*		initializing a resource bucket, assigning ports, and configuring
+*		Bucket Parameters.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*       portVec  - the list of ports that share the bucket.
+*		pirlData - PIRL resource parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlActivate
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	IN  GT_U32		portVec,
+	IN  GT_PIRL_DATA	*pirlData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PORT_STP_STATE	pState[MAX_SWITCH_PORTS];
+	GT_LPORT			port;
+	GT_PIRL_OPERATION	op;
+	GT_PIRL_OP_DATA		opData;
+	GT_PIRL_RESOURCE	pirlRes;
+
+	DBG_INFO(("gpirlActivate Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if the given bucket number is valid */
+	if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
+    {
+        DBG_INFO(("GT_BAD_PARAM irlUnit\n"));
+		return GT_BAD_PARAM;
+    }
+
+    /* check if the given portVec is valid */
+	if ((!portVec) || (portVec >= (GT_U32)(1<<dev->numOfPorts)))
+    {
+        DBG_INFO(("GT_BAD_PARAM portVec\n"));
+		return GT_BAD_PARAM;
+    }
+
+	/* set or reset port's ingress resource bit based on the portVec */
+	retVal = pirlSetPortVec(dev, irlUnit, portVec);
+	if(retVal != GT_OK)
+	{
+        DBG_INFO(("Getting Port State failed\n"));
+		return retVal;
+	}
+
+	/* Disable ports that share the bucket */
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		if(!GT_IS_PORT_SET(portVec,port))
+			continue;
+
+		retVal = gstpGetPortState(dev, port, &pState[port]);
+		if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Getting Port State failed\n"));
+			return retVal;
+		}
+
+		retVal = gstpSetPortState(dev, port, GT_PORT_DISABLE);
+		if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Getting Port State failed\n"));
+			return retVal;
+		}
+	}
+
+	/* Program Tuning register */
+	op = PIRL_WRITE_RESOURCE;
+	opData.irlUnit = irlUnit;
+	opData.irlReg = 0xF;
+	opData.irlData = 0x7;
+	retVal = pirlOperationPerform(dev,op,&opData);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	/* Program the Ingress Rate Resource Parameters */
+	retVal = pirlDataToResource(dev,pirlData,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Data to PIRL Resource conversion failed.\n"));
+    	return retVal;
+	}
+
+	retVal = pirlWriteResource(dev,irlUnit,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Write Resource failed.\n"));
+    	return retVal;
+	}
+
+	/* Initialize internal counters */
+	retVal = pirlInitIRLUnit(dev,irlUnit);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Write Resource failed.\n"));
+    	return retVal;
+	}
+
+	/* Program PirlFCMode for each port that shares Bucket */
+	if (pirlRes.ebsLimitAction == ESB_LIMIT_ACTION_FC)
+	{
+		for(port=0; port<dev->numOfPorts; port++)
+		{
+			if(!GT_IS_PORT_SET(portVec,port))
+				continue;
+
+			retVal = pirlSetFcMode(dev,port,pirlData->fcDeassertMode[port]);
+			if(retVal != GT_OK)
+			{
+			    DBG_INFO(("PIRL FC Mode set failed.\n"));
+    			return retVal;
+			}
+		}
+	}
+
+	/* Set the ports in their original state */
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		if(!GT_IS_PORT_SET(portVec,port))
+			continue;
+
+		retVal = gstpSetPortState(dev, port, pState[port]);
+		if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Getting Port State failed\n"));
+			return retVal;
+		}
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gpirlDeactivate
+*
+* DESCRIPTION:
+*       This routine deactivates Ingress Rate Limiting for the given bucket.
+*		It simply removes every ports from the Ingress Rate Resource.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlDeactivate
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit
+)
+{
+	GT_STATUS       	retVal;
+
+	DBG_INFO(("gpirlDectivate Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if the given bucket number is valid */
+	if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	/* reset port's ingress resource bit */
+	retVal = pirlSetPortVec(dev, irlUnit, 0);
+	if(retVal != GT_OK)
+	{
+        DBG_INFO(("Getting Port State failed\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gpirlUpdateParam
+*
+* DESCRIPTION:
+*       This routine updates IRL Parameter.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the given irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*		pirlData - PIRL resource parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlUpdateParam
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	IN  GT_PIRL_DATA	*pirlData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PORT_STP_STATE	pState[MAX_SWITCH_PORTS];
+	GT_LPORT			port;
+	GT_PIRL_RESOURCE	pirlRes;
+	GT_U32				portVec;
+
+	DBG_INFO(("gpirlUpdateParam Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if the given bucket number is valid */
+	if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	/* get port list that share ingress resource */
+	retVal = pirlGetPortVec(dev, irlUnit, &portVec);
+	if(retVal != GT_OK)
+	{
+        DBG_INFO(("Getting Port State failed\n"));
+		return retVal;
+	}
+
+    /* check if the given portVec is valid */
+	if (!portVec)
+    {
+        DBG_INFO(("IRL Unit not Activated\n"));
+		return GT_FAIL;
+    }
+
+	/* Disable ports that share the bucket */
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		if(!GT_IS_PORT_SET(portVec,port))
+			continue;
+
+		retVal = gstpGetPortState(dev, port, &pState[port]);
+		if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Getting Port State failed\n"));
+			return retVal;
+		}
+
+		retVal = gstpSetPortState(dev, port, GT_PORT_DISABLE);
+		if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Getting Port State failed\n"));
+			return retVal;
+		}
+	}
+
+	/* Program the Ingress Rate Resource Parameters */
+	retVal = pirlDataToResource(dev,pirlData,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Data to PIRL Resource conversion failed.\n"));
+    	return retVal;
+	}
+
+	retVal = pirlWriteResource(dev,irlUnit,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Write Resource failed.\n"));
+    	return retVal;
+	}
+
+	/* Initialize internal counrters for the bucket */
+	retVal = pirlInitIRLUnit(dev,irlUnit);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Write Resource failed.\n"));
+    	return retVal;
+	}
+
+	/* Program PirlFCMode for each port that shares Bucket */
+	if (pirlRes.ebsLimitAction == ESB_LIMIT_ACTION_FC)
+	{
+		for(port=0; port<dev->numOfPorts; port++)
+		{
+			if(!GT_IS_PORT_SET(portVec,port))
+				continue;
+
+			retVal = pirlSetFcMode(dev,port,pirlData->fcDeassertMode[port]);
+			if(retVal != GT_OK)
+			{
+			    DBG_INFO(("PIRL FC Mode set failed.\n"));
+    			return retVal;
+			}
+		}
+	}
+
+	/* Set the ports in their original state */
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		if(!GT_IS_PORT_SET(portVec,port))
+			continue;
+
+		retVal = gstpSetPortState(dev, port, pState[port]);
+		if(retVal != GT_OK)
+		{
+	        DBG_INFO(("Getting Port State failed\n"));
+			return retVal;
+		}
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gpirlReadParam
+*
+* DESCRIPTION:
+*       This routine retrieves IRL Parameter.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the given irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*
+* OUTPUTS:
+*		pirlData - PIRL resource parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlReadParam
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	OUT GT_PIRL_DATA	*pirlData
+)
+{
+	GT_STATUS       	retVal;
+	GT_LPORT			port;
+	GT_PIRL_RESOURCE	pirlRes;
+	GT_U32				portVec;
+
+	DBG_INFO(("gpirlReadParam Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if the given bucket number is valid */
+	if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	/* get port list that share ingress resource */
+	retVal = pirlGetPortVec(dev, irlUnit, &portVec);
+	if(retVal != GT_OK)
+	{
+        DBG_INFO(("Getting Port State failed\n"));
+		return retVal;
+	}
+
+    /* check if the given portVec is valid */
+	if (!portVec)
+    {
+        DBG_INFO(("IRL Unit not Activated\n"));
+		return GT_FAIL;
+    }
+
+	/* Read the Ingress Rate Resource Parameters */
+	retVal = pirlReadResource(dev,irlUnit,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Read Resource failed.\n"));
+    	return retVal;
+	}
+
+	retVal = pirlResourceToData(dev,&pirlRes,pirlData);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Resource to PIRL Data conversion failed.\n"));
+    	return retVal;
+	}
+
+	/* Program PirlFCMode for each port that shares Bucket */
+	if (pirlRes.ebsLimitAction == ESB_LIMIT_ACTION_FC)
+	{
+		for(port=0; port<dev->numOfPorts; port++)
+		{
+			if(!GT_IS_PORT_SET(portVec,port))
+				continue;
+		
+			retVal = grcGetPirlFcMode(dev,port,&pirlData->fcDeassertMode[port]);
+			if(retVal != GT_OK)
+			{
+			    DBG_INFO(("PIRL FC Mode get failed.\n"));
+    			return retVal;
+			}
+		}
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+
+/*******************************************************************************
+* gpirlUpdatePortVec
+*
+* DESCRIPTION:
+*       This routine updates port list that share the bucket.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the given irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*       portVec  - the list of ports that share the bucket.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlUpdatePortVec
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	IN  GT_U32		portVec
+)
+{
+	GT_STATUS       retVal;
+	GT_U32			tmpVec;
+
+	DBG_INFO(("gpirlActivate Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if the given bucket number is valid */
+	if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+    /* check if the given portVec is valid */
+	if ((!portVec) || (portVec > (GT_U32)(1<<dev->numOfPorts)))
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	/* get port list that share ingress resource */
+	retVal = pirlGetPortVec(dev, irlUnit, &tmpVec);
+	if(retVal != GT_OK)
+	{
+        DBG_INFO(("Getting Port State failed\n"));
+		return retVal;
+	}
+
+    /* check if the given portVec is valid */
+	if (!tmpVec)
+    {
+        DBG_INFO(("IRL Unit not Activated\n"));
+		return GT_FAIL;
+    }
+
+	/* set or reset port's ingress resource bit based on the portVec */
+	retVal = pirlSetPortVec(dev, irlUnit, portVec);
+	if(retVal != GT_OK)
+	{
+        DBG_INFO(("Getting Port State failed\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gpirlReadPortVec
+*
+* DESCRIPTION:
+*       This routine retrieves port list that share the bucket.
+*		It is assumed that gpirlActivate has been successfully called with
+*		the given irlUnit before this function is called.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used (0 ~ 11).
+*
+* OUTPUTS:
+*       portVec  - the list of ports that share the bucket.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlReadPortVec
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		irlUnit,
+	OUT GT_U32		*portVec
+)
+{
+	GT_STATUS       retVal;
+
+	DBG_INFO(("gpirlReadPortVec Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if the given bucket number is valid */
+	if (!GT_IS_IRLUNIT_VALID(dev,irlUnit))
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	/* get port list that share ingress resource */
+	retVal = pirlGetPortVec(dev, irlUnit, portVec);
+	if(retVal != GT_OK)
+	{
+        DBG_INFO(("Getting Port State failed\n"));
+		return retVal;
+	}
+
+    /* check if the given portVec is valid */
+	if (!*portVec)
+    {
+        DBG_INFO(("IRL Unit not Activated\n"));
+		return GT_FAIL;
+    }
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+
+/*******************************************************************************
+* grcGetPirlFcMode
+*
+* DESCRIPTION:
+*       This routine gets Port Ingress Rate Limit Flow Control mode.
+*		When EBSLimitAction is programmed to generate a flow control message, 
+*		the deassertion of flow control is controlled by this mode.
+*			GT_PIRL_FC_DEASSERT_EMPTY:
+*				De-assert when the ingress rate resource has become empty
+*			GT_PIRL_FC_DEASSERT_CBS_LIMIT
+*				De-assert when the ingress rate resource has enough room as
+*				specified by the CBSLimit.
+*		Please refer to GT_PIRL_RESOURCE structure for EBSLimitAction and
+*		CBSLimit.
+*
+* INPUTS:
+*       port - logical port number
+*
+* OUTPUTS:
+*		mode - GT_PIRL_FC_DEASSERT enum type
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetPirlFcMode
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_PIRL_FC_DEASSERT		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetDaNrlEn Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the PirlFcMode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,12,1,&data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    *mode = (GT_PIRL_FC_DEASSERT)data;
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gpirlGetIngressRateResource
+*
+* DESCRIPTION:
+*       This routine gets Ingress Rate Limiting Resources assigned to the port.
+*		This vector is used to attach specific counter resources to the physical
+*		port. And the same counter resource can be attached to more than one port.
+*
+* INPUTS:
+*       port   - logical port number
+*
+* OUTPUTS:
+*		resVec - resource vector (bit 11:0, since there is 12 resources)
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gpirlGetIngressRateResource
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_U32		*resVec
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+	GT_U16			data;
+
+    DBG_INFO(("grcGetIngressRateResource Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the resource vector.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,0,12,&data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	*resVec = (GT_U32)data;
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gpirlSetCurTimeUpInt
+*
+* DESCRIPTION:
+*       This function sets the current time update interval.
+*		Please contact FAE for detailed information.
+*
+* INPUTS:
+*       upInt - updata interval (0 ~ 7)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gpirlSetCurTimeUpInt
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				upInt
+)
+{
+    GT_STATUS       retVal;		/* Functions return value */
+	GT_PIRL_OPERATION	op;
+	GT_PIRL_OP_DATA		opData;
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (upInt > 0x7)
+		return GT_BAD_PARAM;
+
+	op = PIRL_READ_RESOURCE;
+
+	opData.irlUnit = 0xF;
+	opData.irlReg = 1;
+	opData.irlData = 0;
+
+	retVal = pirlOperationPerform(dev, op, &opData);
+	if (retVal != GT_OK)
+	{
+   	    DBG_INFO(("PIRL OP Failed.\n"));
+       	return retVal;
+	}
+
+	op = PIRL_WRITE_RESOURCE;
+	opData.irlData = (opData.irlData & 0xFFF8) | (GT_U16)upInt;
+
+	retVal = pirlOperationPerform(dev, op, &opData);
+	if (retVal != GT_OK)
+	{
+   	    DBG_INFO(("PIRL OP Failed.\n"));
+       	return retVal;
+	}
+
+	return GT_OK;	
+}
+
+/****************************************************************************/
+/* Internal functions.                                                  */
+/****************************************************************************/
+
+/*******************************************************************************
+* gpirlInitialize
+*
+* DESCRIPTION:
+*       This routine initializes PIRL Resources.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirlInitialize
+(
+    IN  GT_QD_DEV  			*dev
+)
+{
+	GT_STATUS       	retVal;
+	GT_LPORT		port;
+    GT_U8           hwPort;        /* Physical port.               */
+
+	/* reset port's ingress resource bit */
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+	    hwPort = GT_LPORT_2_PORT(port);
+
+	    /* Set the resource vector.            */
+    	retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,0,12,0);
+	    if(retVal != GT_OK)
+   		{
+	        DBG_INFO(("Failed.\n"));
+   		    return retVal;
+	    }
+	}
+
+	retVal = pirlInitialize(dev);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	    return retVal;
+    }
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* statsOperationPerform
+*
+* DESCRIPTION:
+*       This function accesses Ingress Rate Command Register and Data Register.
+*
+* INPUTS:
+*       pirlOp       - The stats operation bits to be written into the stats
+*                     operation register.
+*       port        - port number
+*       counter     - counter to be read if it's read operation
+*
+* OUTPUTS:
+*       pirlData   - points to the data storage where the MIB counter will be saved.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pirlOperationPerform
+(
+    IN    GT_QD_DEV           *dev,
+    IN    GT_PIRL_OPERATION   pirlOp,
+    INOUT GT_PIRL_OP_DATA     *opData
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+
+    gtSemTake(dev,dev->pirlRegsSem,OS_WAIT_FOREVER);
+
+    /* Wait until the pirl in ready. */
+    data = 1;
+    while(data == 1)
+    {
+        retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->pirlRegsSem);
+            return retVal;
+        }
+    }
+
+    /* Set the PIRL Operation register */
+	switch (pirlOp)
+	{
+		case PIRL_INIT_ALL_RESOURCE:
+			data = (1 << 15) | (PIRL_INIT_ALL_RESOURCE << 12);
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+			break;
+		case PIRL_INIT_RESOURCE:
+			data = (GT_U16)((1 << 15) | (PIRL_INIT_RESOURCE << 12) | 
+					((opData->irlUnit&0xF)<< 4));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+			break;
+
+		case PIRL_WRITE_RESOURCE:
+			data = (GT_U16)opData->irlData;
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_DATA,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+
+			data = (GT_U16)((1 << 15) | (PIRL_WRITE_RESOURCE << 12) | 
+					((opData->irlUnit&0xF) << 4) | (opData->irlReg & 0xF));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+			break;
+
+		case PIRL_READ_RESOURCE:
+			data = (GT_U16)((1 << 15) | (PIRL_READ_RESOURCE << 12) | 
+					((opData->irlUnit&0xF) << 4) | (opData->irlReg & 0xF));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+
+		    data = 1;
+		    while(data == 1)
+		    {
+		        retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
+		        if(retVal != GT_OK)
+		        {
+		            gtSemGive(dev,dev->pirlRegsSem);
+		            return retVal;
+        		}
+		    }
+
+			retVal = hwReadGlobal2Reg(dev,QD_REG_INGRESS_RATE_DATA,&data);
+			opData->irlData = (GT_U32)data;
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+		    gtSemGive(dev,dev->pirlRegsSem);
+		    return retVal;
+
+		default:
+			
+			gtSemGive(dev,dev->pirlRegsSem);
+			return GT_FAIL;
+	}
+
+    /* Wait until the pirl in ready. */
+    data = 1;
+    while(data == 1)
+    {
+        retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->pirlRegsSem);
+            return retVal;
+        }
+    }
+
+    gtSemGive(dev,dev->pirlRegsSem);
+    return retVal;
+}
+
+/*
+ * Initialize all PIRL resources to the inital state.
+*/
+static GT_STATUS pirlInitialize
+(
+    IN  GT_QD_DEV  			*dev
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+	GT_PIRL_OPERATION	op;
+
+	op = PIRL_INIT_ALL_RESOURCE;
+
+	retVal = pirlOperationPerform(dev, op, NULL);
+	if (retVal != GT_OK)
+	{
+   	    DBG_INFO(("PIRL OP Failed.\n"));
+       	return retVal;
+	}
+
+	retVal = gpirlSetCurTimeUpInt(dev,7);
+	if (retVal != GT_OK)
+	{
+   	    DBG_INFO(("PIRL OP Failed.\n"));
+	}
+
+	return retVal;
+}
+
+/*
+ * Initialize the selected PIRL resource to the inital state.
+ * This function initializes only the BSM structure for the IRL Unit.
+*/
+static GT_STATUS pirlInitIRLUnit
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlUnit
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+	GT_PIRL_OPERATION	op;
+	GT_PIRL_OP_DATA		opData;
+
+	op = PIRL_INIT_RESOURCE;
+	opData.irlUnit = irlUnit;
+
+	retVal = pirlOperationPerform(dev, op, &opData);
+	if (retVal != GT_OK)
+	{
+   	    DBG_INFO(("PIRL OP Failed.\n"));
+       	return retVal;
+	}
+
+	return retVal;
+}
+
+/*
+ * convert PIRL Data structure to PIRL Resource structure.
+ * if PIRL Data is not valid, return GT_BAD_PARARM;
+*/
+static GT_STATUS pirlDataToResource
+(
+    IN  GT_QD_DEV  			*dev,
+    IN  GT_PIRL_DATA		*pirlData,
+    OUT GT_PIRL_RESOURCE	*res
+)
+{
+	GT_U16 typeMask;
+
+	switch(pirlData->accountQConf)
+	{
+		case GT_FALSE:
+		case GT_TRUE:
+			res->accountQConf = pirlData->accountQConf;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	switch(pirlData->accountFiltered)
+	{
+		case GT_FALSE:
+		case GT_TRUE:
+			res->accountFiltered = pirlData->accountFiltered;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	switch(pirlData->ebsLimitAction)
+	{
+		case ESB_LIMIT_ACTION_DROP:
+		case ESB_LIMIT_ACTION_FC:
+			res->ebsLimitAction = pirlData->ebsLimitAction;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	if(pirlData->customSetup.isValid == GT_TRUE)
+	{
+		res->ebsLimit = pirlData->customSetup.ebsLimit;
+		res->cbsLimit = pirlData->customSetup.cbsLimit;
+		res->bktIncrement = pirlData->customSetup.bktIncrement;
+		res->bktRateFactor = pirlData->customSetup.bktRateFactor;
+	}
+	else
+	{
+		if(pirlData->ingressRate == 0)
+			return GT_BAD_PARAM;
+
+		if(pirlData->ingressRate < 1000)	/* less than 1Mbps */
+		{
+			/* it should be divided by 64 */
+			if(pirlData->ingressRate % 64)
+				return GT_BAD_PARAM;
+			res->bktRateFactor = pirlData->ingressRate/64;
+		}
+		else if(pirlData->ingressRate <= 100000)	/* less than or equal to 100Mbps */
+		{
+			/* it should be divided by 1000 */
+			if(pirlData->ingressRate % 1000)
+				return GT_BAD_PARAM;
+			res->bktRateFactor = pirlData->ingressRate/64 + ((pirlData->ingressRate % 64)?1:0);
+		}
+		else if(pirlData->ingressRate <= 200000)	/* less than or equal to 200Mbps */
+		{
+			/* it should be divided by 10000 */
+			if(pirlData->ingressRate % 10000)
+				return GT_BAD_PARAM;
+			res->bktRateFactor = pirlData->ingressRate/64 + ((pirlData->ingressRate % 64)?1:0);
+		}
+		else
+			return GT_BAD_PARAM;
+
+		res->ebsLimit = RECOMMENDED_ESB_LIMIT(dev, pirlData->ingressRate);
+		res->cbsLimit = RECOMMENDED_CBS_LIMIT(dev, pirlData->ingressRate);
+		res->bktIncrement = RECOMMENDED_BUCKET_INCREMENT(dev, pirlData->ingressRate);
+	}
+
+	switch(pirlData->bktRateType)
+	{
+		case BUCKET_TYPE_TRAFFIC_BASED:
+			res->bktRateType = pirlData->bktRateType;
+
+			if (IS_IN_DEV_GROUP(dev,DEV_RESTRICTED_PIRL_RESOURCE))
+			{
+				typeMask = 0xF;
+			}
+			else
+			{
+				typeMask = 0x7F;
+			}
+
+			if (pirlData->bktTypeMask > typeMask)
+			{
+				return GT_BAD_PARAM;
+			}
+			else
+			{
+				res->bktTypeMask = pirlData->bktTypeMask;
+			}
+
+			break;
+
+		case BUCKET_TYPE_RATE_BASED:
+			if (IS_IN_DEV_GROUP(dev,DEV_RESTRICTED_PIRL_RESOURCE))
+				return GT_BAD_PARAM;
+			res->bktRateType = pirlData->bktRateType;
+			res->bktTypeMask = 0;
+			break;
+
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	switch(pirlData->byteTobeCounted)
+	{
+		case GT_PIRL_COUNT_ALL_LAYER1:
+			res->byteTobeCounted = 1;
+			break;
+		case GT_PIRL_COUNT_ALL_LAYER2:
+			res->byteTobeCounted = 2;
+			break;
+		case GT_PIRL_COUNT_ALL_LAYER3:
+			res->byteTobeCounted = 6;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	return GT_OK;			
+}
+
+/*
+ * convert PIRL Resource structure to PIRL Data structure.
+*/
+static GT_STATUS pirlResourceToData
+(
+    IN  GT_QD_DEV  			*dev,
+    IN  GT_PIRL_RESOURCE	*res,
+    OUT GT_PIRL_DATA		*pirlData
+)
+{
+	GT_U32	rate;
+	GT_U32	factor;
+
+	pirlData->accountQConf = res->accountQConf;
+	pirlData->accountFiltered = res->accountFiltered;
+	pirlData->ebsLimitAction = res->ebsLimitAction;
+
+	pirlData->customSetup.isValid = GT_FALSE;
+
+	FACTOR_FROM_BUCKET_INCREMENT(dev,res->bktIncrement,factor);
+
+	rate = res->bktRateFactor * factor;
+	if(rate == 0)
+	{
+		pirlData->ingressRate = 0;
+		pirlData->customSetup.isValid = GT_TRUE;
+		pirlData->customSetup.ebsLimit = res->ebsLimit;
+		pirlData->customSetup.cbsLimit = res->cbsLimit;
+		pirlData->customSetup.bktIncrement = res->bktIncrement;
+		pirlData->customSetup.bktRateFactor = res->bktRateFactor;
+	}
+	else if(rate < 1000)
+	{
+		pirlData->ingressRate = rate;
+	}
+	else if(rate < 100000)
+	{
+		pirlData->ingressRate = rate - (rate % 1000);
+	}
+	else
+	{
+		pirlData->ingressRate = rate - (rate % 10000);
+	}
+
+	pirlData->bktRateType = res->bktRateType;
+	pirlData->bktTypeMask = res->bktTypeMask;
+
+	switch(res->byteTobeCounted)
+	{
+		case 1:
+			pirlData->byteTobeCounted = GT_PIRL_COUNT_ALL_LAYER1;
+			break;
+		case 2:
+			pirlData->byteTobeCounted = GT_PIRL_COUNT_ALL_LAYER2;
+			break;
+		case 6:
+			pirlData->byteTobeCounted = GT_PIRL_COUNT_ALL_LAYER3;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	return GT_OK;			
+}
+
+/*******************************************************************************
+* pirlWriteResource
+*
+* DESCRIPTION:
+*       This function writes IRL Resource to BCM (Bucket Configuration Memory)
+*
+* INPUTS:
+*		irlUnit - resource unit to be accessed
+*       res 	- IRL Resource data
+*
+* OUTPUTS:
+*       Nont.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pirlWriteResource
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlUnit,
+    IN  GT_PIRL_RESOURCE	*res
+)
+{
+    GT_STATUS       retVal;			/* Functions return value */
+    GT_U16          data[8]; 	/* temporary Data storage */
+	GT_PIRL_OPERATION	op;
+	GT_PIRL_OP_DATA		opData;
+	int				i;
+
+	op = PIRL_WRITE_RESOURCE;
+
+	/* reg0 data */
+	data[0] = (GT_U16)((res->bktRateType << 15) |	/* Bit[15] : Bucket Rate Type */
+			  		(res->bktTypeMask << 4 ) |		/* Bit[14:4] : Traffic Type   */
+			  		res->byteTobeCounted );			/* Bit[3:0] : Bytes to be counted */
+
+	/* reg1 data */
+	data[1] = (GT_U16)res->bktIncrement;	/* Bit[11:0] : Bucket Increment */
+
+	/* reg2 data */
+	data[2] = (GT_U16)res->bktRateFactor;	/* Bit[15:0] : Bucket Rate Factor */
+
+	/* reg3 data */
+	data[3] = (GT_U16)(res->cbsLimit & 0xFFF) << 4;	/* Bit[15:4] : CBS Limit[11:0] */
+
+	/* reg4 data */
+	data[4] = (GT_U16)(res->cbsLimit >> 12);		/* Bit[11:0] : CBS Limit[23:12] */
+
+	/* reg5 data */
+	data[5] = (GT_U16)(res->ebsLimit & 0xFFFF);		/* Bit[15:0] : EBS Limit[15:0] */
+
+	/* reg6 data */
+	data[6] = (GT_U16)((res->ebsLimit >> 16)	|	/* Bit[7:0] : EBS Limit[23:16] */
+					(res->ebsLimitAction << 12)	|	/* Bit[12] : EBS Limit Action */
+					(res->accountFiltered << 14)|	/* Bit[14] : Account Filtered */
+					(res->accountQConf << 15));		/* Bit[15] : Account QConf */
+	/* reg7 data */
+	data[7] = 0;	/* Reserved */
+
+	for(i=0; i<8; i++)
+	{
+		opData.irlUnit = irlUnit;
+		opData.irlReg = i;
+		opData.irlData = data[i];
+
+		retVal = pirlOperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+	}
+
+	return GT_OK;	
+}
+
+
+/*******************************************************************************
+* pirlReadResource
+*
+* DESCRIPTION:
+*       This function reads IRL Resource from BCM (Bucket Configuration Memory)
+*
+* INPUTS:
+*		irlUnit - resource unit to be accessed
+*
+* OUTPUTS:
+*       res - IRL Resource data
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pirlReadResource
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlUnit,
+    OUT GT_PIRL_RESOURCE	*res
+)
+{
+    GT_STATUS       retVal;			/* Functions return value */
+    GT_U16          data[8]; 	/* temporary Data storage */
+	GT_PIRL_OPERATION	op;
+	GT_PIRL_OP_DATA		opData;
+	int				i;
+
+	op = PIRL_READ_RESOURCE;
+
+	for(i=0; i<8; i++)
+	{
+		opData.irlUnit = irlUnit;
+		opData.irlReg = i;
+		opData.irlData = 0;
+
+		retVal = pirlOperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+
+		data[i] = (GT_U16)opData.irlData;
+	}
+	
+
+	/* reg0 data */
+	res->bktRateType = (data[0] >> 15) & 0x1;
+	res->bktTypeMask = (data[0] >> 4) & 0x7F;
+
+	res->byteTobeCounted = data[0] & 0xF;
+
+	/* reg1 data */
+	res->bktIncrement = data[1] & 0xFFF;
+
+	/* reg2 data */
+	res->bktRateFactor = data[2] & 0xFFFF;
+
+	/* reg3,4 data */
+	res->cbsLimit = ((data[3] >> 4) & 0xFFF) | ((data[4] & 0xFFF) << 12);
+
+	/* reg5,6 data */
+	res->ebsLimit = data[5] | ((data[6] & 0xFF) << 16);
+													   
+	/* reg6 data */
+	res->ebsLimitAction = (data[6] >> 12) & 0x1;
+	res->accountFiltered = (data[6] >> 14) & 0x1;
+	res->accountQConf = (data[6] >> 15) & 0x1;
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* pirlSetPortVec
+*
+* DESCRIPTION:
+*       This routine sets port list that share the bucket and resets ports that
+*		do not share the bucket.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used.
+*       portVec  - the list of ports that share the bucket.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+static GT_STATUS pirlSetPortVec
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_U32		irlUnit,
+	IN  GT_U32		portVec
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_LPORT		port;
+    GT_U8           hwPort;        /* Physical port.               */
+	GT_U16			data;
+
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+		if(GT_IS_PORT_SET(portVec,port))
+			data = 1;
+		else
+			data = 0;
+
+	    hwPort = GT_LPORT_2_PORT(port);
+
+	    /* Set the resource vector.            */
+    	retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,(GT_U8)irlUnit,1,data);
+	    if(retVal != GT_OK)
+   		{
+	        DBG_INFO(("Failed.\n"));
+   		    return retVal;
+	    }
+	}
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* pirlGetPortVec
+*
+* DESCRIPTION:
+*       This routine gets port list that share the bucket.
+*
+* INPUTS:
+*		irlUnit  - bucket to be used.
+*
+* OUTPUTS:
+*       portVec  - the list of ports that share the bucket.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+static GT_STATUS pirlGetPortVec
+(
+    IN  GT_QD_DEV	*dev,
+	IN  GT_U32		irlUnit,
+	OUT GT_U32		*portVec
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_LPORT		port;
+    GT_U8           hwPort;        /* Physical port.               */
+	GT_U16			data;
+
+	*portVec = 0;
+
+	for(port=0; port<dev->numOfPorts; port++)
+	{
+	    hwPort = GT_LPORT_2_PORT(port);
+
+	    /* Set the resource vector.            */
+    	retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,(GT_U8)irlUnit,1,&data);
+	    if(retVal != GT_OK)
+   		{
+	        DBG_INFO(("Failed.\n"));
+   		    return retVal;
+	    }
+
+		if(data == 1)
+			*portVec |= (1 << port);
+	}
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* pirlSetFcMode
+*
+* DESCRIPTION:
+*       This routine gets Port Ingress Rate Limit Flow Control mode.
+*		When EBSLimitAction is programmed to generate a flow control message, 
+*		the deassertion of flow control is controlled by this mode.
+*			GT_PIRL_FC_DEASSERT_EMPTY:
+*				De-assert when the ingress rate resource has become empty
+*			GT_PIRL_FC_DEASSERT_CBS_LIMIT
+*				De-assert when the ingress rate resource has enough room as
+*				specified by the CBSLimit.
+*		Please refer to GT_PIRL_RESOURCE structure for EBSLimitAction and
+*		CBSLimit.
+*
+* INPUTS:
+*       port - logical port number
+*		mode - GT_PIRL_FC_DEASSERT enum type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+static GT_STATUS pirlSetFcMode
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_PIRL_FC_DEASSERT		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("pirlSetFcMode Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	data = (GT_U16) mode;
+
+    /* Set the PirlFcMode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,12,1,data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+#define PIRL_DEBUG
+#ifdef PIRL_DEBUG
+/*******************************************************************************
+* pirlDumpResource
+*
+* DESCRIPTION:
+*       This function dumps IRL Resource register values.
+*
+* INPUTS:
+*		irlUnit  - resource unit to be accessed
+*		dataLen  - data size.
+*
+* OUTPUTS:
+*       data - IRL Resource data
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS pirlDumpResource
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlUnit,
+	IN	GT_U32				dataLen,
+    OUT GT_U16				*data
+)
+{
+    GT_STATUS       retVal;		/* Functions return value */
+	GT_PIRL_OPERATION	op;
+	GT_PIRL_OP_DATA		opData;
+	GT_U32				i;
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	op = PIRL_READ_RESOURCE;
+
+	for(i=0; i<dataLen; i++)
+	{
+		opData.irlUnit = irlUnit;
+		opData.irlReg = i;
+		opData.irlData = 0;
+
+		retVal = pirlOperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+
+		data[i] = (GT_U16)opData.irlData;
+	}
+
+	return GT_OK;	
+}
+#endif /* PIRL_DEBUG */
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL2.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL2.c
new file mode 100755
index 0000000..f5b2193
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPIRL2.c
@@ -0,0 +1,1697 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtPIRL2.c
+*
+* DESCRIPTION:
+*       API definitions for Port based PIRL Resources
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+
+/****************************************************************************/
+/* PIRL operation function declaration.                                    */
+/****************************************************************************/
+static GT_STATUS pirl2OperationPerform
+(
+	IN   GT_QD_DEV            *dev,
+	IN   GT_PIRL2_OPERATION    pirlOp,
+	INOUT GT_PIRL2_OP_DATA     *opData
+);
+
+static GT_STATUS pirl2Initialize
+(
+	IN  GT_QD_DEV  			*dev
+);
+
+static GT_STATUS pirl2InitIRLResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes
+);
+
+static GT_STATUS pirl2DisableIRLResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes
+);
+
+static GT_STATUS pirl2DataToResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN  GT_PIRL2_DATA		*pirlData,
+	OUT GT_PIRL2_RESOURCE	*res
+);
+
+static GT_STATUS pirl2ResourceToData
+(
+	IN  GT_QD_DEV  			*dev,
+	IN  GT_PIRL2_RESOURCE	*res,
+	OUT GT_PIRL2_DATA		*pirlData
+);
+
+static GT_STATUS pirl2WriteResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	IN  GT_PIRL2_RESOURCE	*res
+);
+
+static GT_STATUS pirl2ReadResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	OUT GT_PIRL2_RESOURCE	*res
+);
+
+static GT_STATUS pirl2WriteTSMResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	IN  GT_PIRL2_TSM_RESOURCE	*res
+);
+
+static GT_STATUS pirl2ReadTSMResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	OUT GT_PIRL2_TSM_RESOURCE	*res
+);
+
+/*******************************************************************************
+* gpirl2WriteResource
+*
+* DESCRIPTION:
+*		This routine writes resource bucket parameters to the given resource
+*		of the port.
+*
+* INPUTS:
+*		port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 4).
+*		pirlData - PIRL resource parameters.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gpirl2WriteResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes,
+	IN  GT_PIRL2_DATA	*pirlData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PIRL2_RESOURCE	pirlRes;
+	GT_U32           	irlPort;         /* the physical port number     */
+	GT_U32				maxRes;
+
+	DBG_INFO(("gpirl2WriteResource Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* check if the given bucket number is valid */
+	if (IS_IN_DEV_GROUP(dev,DEV_RESTRICTED_PIRL2_RESOURCE))
+	{
+		maxRes = 2;
+	}
+	else
+	{
+		maxRes = 5;
+	}
+
+	if (irlRes >= maxRes)
+	{
+		DBG_INFO(("GT_BAD_PARAM irlRes\n"));
+		return GT_BAD_PARAM;
+	}
+
+	irlPort = (GT_U32)GT_LPORT_2_PORT(port);
+	if (irlPort == GT_INVALID_PORT)
+	{
+		DBG_INFO(("GT_BAD_PARAM port\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* Initialize internal counters */
+	retVal = pirl2InitIRLResource(dev,irlPort,irlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Write Resource failed.\n"));
+    	return retVal;
+	}
+
+	/* Program the Ingress Rate Resource Parameters */
+	retVal = pirl2DataToResource(dev,pirlData,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Data to PIRL Resource conversion failed.\n"));
+    	return retVal;
+	}
+
+	retVal = pirl2WriteResource(dev,irlPort,irlRes,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Write Resource failed.\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gpirl2ReadResource
+*
+* DESCRIPTION:
+*		This routine retrieves IRL Parameter.
+*
+* INPUTS:
+*		port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 4).
+*
+* OUTPUTS:
+*		pirlData - PIRL resource parameters.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gpirl2ReadResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes,
+	OUT GT_PIRL2_DATA	*pirlData
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				irlPort;
+	GT_PIRL2_RESOURCE	pirlRes;
+	GT_U32				maxRes;
+
+	DBG_INFO(("gpirl2ReadResource Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* check if the given bucket number is valid */
+	if (IS_IN_DEV_GROUP(dev,DEV_RESTRICTED_PIRL2_RESOURCE))
+	{
+		maxRes = 2;
+	}
+	else
+	{
+		maxRes = 5;
+	}
+
+	if (irlRes >= maxRes)
+	{
+		DBG_INFO(("GT_BAD_PARAM irlRes\n"));
+		return GT_BAD_PARAM;
+	}
+
+	irlPort = (GT_U32)GT_LPORT_2_PORT(port);
+	if (irlPort == GT_INVALID_PORT)
+	{
+		DBG_INFO(("GT_BAD_PARAM port\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* Read the Ingress Rate Resource Parameters */
+	retVal = pirl2ReadResource(dev,irlPort,irlRes,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Read Resource failed.\n"));
+    	return retVal;
+	}
+
+	retVal = pirl2ResourceToData(dev,&pirlRes,pirlData);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Resource to PIRL Data conversion failed.\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gpirl2DisableResource
+*
+* DESCRIPTION:
+*       This routine disables Ingress Rate Limiting for the given bucket.
+*
+* INPUTS:
+*       port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 4).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirl2DisableResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				irlPort;
+	GT_U32				maxRes;
+
+	DBG_INFO(("gpirl2Dectivate Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* check if the given bucket number is valid */
+	if (IS_IN_DEV_GROUP(dev,DEV_RESTRICTED_PIRL2_RESOURCE))
+	{
+		maxRes = 2;
+	}
+	else
+	{
+		maxRes = 5;
+	}
+
+	if (irlRes >= maxRes)
+	{
+		DBG_INFO(("GT_BAD_PARAM irlRes\n"));
+		return GT_BAD_PARAM;
+	}
+
+	irlPort = (GT_U32)GT_LPORT_2_PORT(port);
+	if (irlPort == GT_INVALID_PORT)
+	{
+		DBG_INFO(("GT_BAD_PARAM port\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* disable irl resource */
+	retVal = pirl2DisableIRLResource(dev, irlPort, irlRes);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Getting Port State failed\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gpirl2SetCurTimeUpInt
+*
+* DESCRIPTION:
+*       This function sets the current time update interval.
+*		Please contact FAE for detailed information.
+*
+* INPUTS:
+*       upInt - updata interval (0 ~ 7)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gpirl2SetCurTimeUpInt
+(
+    IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				upInt
+)
+{
+    GT_STATUS       retVal;		/* Functions return value */
+	GT_PIRL2_OPERATION	op;
+	GT_PIRL2_OP_DATA	opData;
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (upInt > 0x7)
+		return GT_BAD_PARAM;
+
+	op = PIRL_READ_RESOURCE;
+
+	opData.irlPort = 0xF;
+	opData.irlRes = 0;
+	opData.irlReg = 1;
+	opData.irlData = 0;
+
+	retVal = pirl2OperationPerform(dev, op, &opData);
+	if (retVal != GT_OK)
+	{
+   	    DBG_INFO(("PIRL OP Failed.\n"));
+       	return retVal;
+	}
+
+	op = PIRL_WRITE_RESOURCE;
+	opData.irlData = (opData.irlData & 0xFFF8) | (GT_U16)upInt;
+
+	retVal = pirl2OperationPerform(dev, op, &opData);
+	if (retVal != GT_OK)
+	{
+   	    DBG_INFO(("PIRL OP Failed.\n"));
+       	return retVal;
+	}
+
+	return GT_OK;	
+}
+
+
+/*******************************************************************************
+* gpirl2WriteTSMResource
+*
+* DESCRIPTION:
+*		This routine writes rate resource bucket parameters in Time Slot Metering
+*		mode to the given resource of the port.
+*
+* INPUTS:
+*		port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 1).
+*		pirlData - PIRL TSM resource parameters.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Only Resource 0 and 1 can be supported for TSM Mode.
+*
+*******************************************************************************/
+GT_STATUS gpirl2WriteTSMResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes,
+	IN  GT_PIRL2_TSM_DATA	*pirlData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PIRL2_TSM_RESOURCE	pirlRes;
+	GT_U32           	irlPort;         /* the physical port number     */
+	GT_U32				maxRes;
+	GT_U32				cbs, cts, i, rate;
+
+	DBG_INFO(("gpirl2WriteTSMResource Called.\n"));
+
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TSM_RESOURCE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* check if the given bucket number is valid */
+	maxRes = 2;
+
+	if (irlRes >= maxRes)
+	{
+		DBG_INFO(("GT_BAD_PARAM irlRes\n"));
+		return GT_BAD_PARAM;
+	}
+
+	irlPort = (GT_U32)GT_LPORT_2_PORT(port);
+	if (irlPort == GT_INVALID_PORT)
+	{
+		DBG_INFO(("GT_BAD_PARAM port\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* Initialize internal counters */
+	retVal = pirl2InitIRLResource(dev,irlPort,irlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Write Resource failed.\n"));
+    	return retVal;
+	}
+
+	if (pirlData->customSetup.isValid == GT_TRUE)
+	{
+		pirlRes.cbsLimit = pirlData->customSetup.cbsLimit;
+		pirlRes.ctsIntv = pirlData->customSetup.ctsIntv;
+		pirlRes.ebsLimit = pirlData->customSetup.ebsLimit;
+		pirlRes.actionMode = pirlData->customSetup.actionMode;
+	}
+	else
+	{
+		/* convert ingressRate to cbsLimit and ctsIntv */
+		cts = 1; 
+		cbs = 0;
+		i = 3;
+		rate = pirlData->ingressRate;
+		while(cts < 16)
+		{
+			cbs = TSM_GET_CBS(rate, cts);
+			if ((cbs == 0) || (cbs <= 0xFFFF))
+				break;
+			cts += i;
+			i = cts;
+		}
+
+		if (cts > 16)
+		{
+			return GT_BAD_PARAM;
+		}
+
+		switch (cts)
+		{
+			case 1:
+				pirlRes.ctsIntv = 3;
+				break;
+			case 4:
+				pirlRes.ctsIntv = 2;
+				break;
+			case 8:
+				pirlRes.ctsIntv = 1;
+				break;
+			case 16:
+				pirlRes.ctsIntv = 0;
+				break;
+			default:
+				return GT_FAIL;
+		}
+
+		pirlRes.cbsLimit = cbs;
+		pirlRes.ebsLimit = 0xFFFF;
+		pirlRes.actionMode = 1;
+	}
+
+	pirlRes.mgmtNrlEn = pirlData->mgmtNrlEn;
+	pirlRes.priMask = pirlData->priMask;
+	pirlRes.tsmMode = GT_TRUE;
+
+	if (pirlData->tsmMode == GT_FALSE)
+	{
+		pirlRes.tsmMode = 0;
+		pirlRes.cbsLimit = 0;
+		pirlRes.ctsIntv = 0;
+		pirlRes.ebsLimit = 0;
+		pirlRes.actionMode = 0;
+		pirlRes.mgmtNrlEn = 0;
+		pirlRes.priMask = 0;
+	}
+
+	retVal = pirl2WriteTSMResource(dev,irlPort,irlRes,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Write Resource failed.\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gpirl2ReadTSMResource
+*
+* DESCRIPTION:
+*		This routine retrieves IRL Parameter.
+*		Returned ingressRate would be rough number. Instead, customSetup will
+*		have the exact configured value.
+*
+* INPUTS:
+*		port     - logical port number.
+*		irlRes   - bucket to be used (0 ~ 1).
+*
+* OUTPUTS:
+*		pirlData - PIRL resource parameters.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Only Resource 0 and 1 can be supported for TSM Mode.
+*
+*******************************************************************************/
+GT_STATUS gpirl2ReadTSMResource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		irlRes,
+	OUT GT_PIRL2_TSM_DATA	*pirlData
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				irlPort;
+	GT_PIRL2_TSM_RESOURCE	pirlRes;
+	GT_U32				maxRes, cbs, cts;
+
+	DBG_INFO(("gpirl2ReadTSMResource Called.\n"));
+
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TSM_RESOURCE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* check if the given bucket number is valid */
+	maxRes = 2;
+
+	if (irlRes >= maxRes)
+	{
+		DBG_INFO(("GT_BAD_PARAM irlRes\n"));
+		return GT_BAD_PARAM;
+	}
+
+	irlPort = (GT_U32)GT_LPORT_2_PORT(port);
+	if (irlPort == GT_INVALID_PORT)
+	{
+		DBG_INFO(("GT_BAD_PARAM port\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* Read the Ingress Rate Resource Parameters */
+	retVal = pirl2ReadTSMResource(dev,irlPort,irlRes,&pirlRes);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("PIRL Read Resource failed.\n"));
+    	return retVal;
+	}
+
+	if (pirlRes.tsmMode == 0)
+	{
+		/* TMS Mode is not enabled */
+		pirlData->tsmMode = GT_FALSE;
+		pirlData->ingressRate = 0;
+		pirlData->mgmtNrlEn = 0;
+		pirlData->priMask = 0;
+		pirlData->customSetup.isValid = 0;
+		pirlData->customSetup.cbsLimit = 0;
+		pirlData->customSetup.ctsIntv = 0;
+		pirlData->customSetup.ebsLimit = 0;
+		pirlData->customSetup.actionMode = 0;
+		return GT_OK;
+	}
+
+	cbs = pirlRes.cbsLimit;
+	switch (pirlRes.ctsIntv)
+	{
+		case 0:
+			cts = 16;
+			break;
+		case 1:
+			cts = 8;
+			break;
+		case 2:
+			cts = 4;
+			break;
+		case 3:
+			cts = 1;
+			break;
+		default:
+			return GT_FAIL;
+	}
+
+	pirlData->ingressRate = TSM_GET_RATE(cbs,cts);
+
+	pirlData->mgmtNrlEn = pirlRes.mgmtNrlEn;
+	pirlData->priMask = pirlRes.priMask;
+
+	pirlData->customSetup.isValid = GT_TRUE;
+	pirlData->customSetup.cbsLimit = pirlRes.cbsLimit;
+	pirlData->customSetup.ctsIntv = pirlRes.ctsIntv;
+	pirlData->customSetup.ebsLimit = pirlRes.ebsLimit;
+	pirlData->customSetup.actionMode = pirlRes.actionMode;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+
+/****************************************************************************/
+/* Internal functions.                                                  */
+/****************************************************************************/
+
+/*******************************************************************************
+* gpirl2Initialize
+*
+* DESCRIPTION:
+*       This routine initializes PIRL Resources.
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gpirl2Initialize
+(
+    IN  GT_QD_DEV  			*dev
+)
+{
+	GT_STATUS       	retVal;
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = pirl2Initialize(dev);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	    return retVal;
+    }
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* pirl2OperationPerform
+*
+* DESCRIPTION:
+*       This function accesses Ingress Rate Command Register and Data Register.
+*
+* INPUTS:
+*       pirlOp     - The stats operation bits to be written into the stats
+*                    operation register.
+*
+* OUTPUTS:
+*       pirlData   - points to the data storage where the MIB counter will be saved.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pirl2OperationPerform
+(
+    IN    GT_QD_DEV 			*dev,
+    IN    GT_PIRL2_OPERATION	pirlOp,
+    INOUT GT_PIRL2_OP_DATA		*opData
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+
+    gtSemTake(dev,dev->pirlRegsSem,OS_WAIT_FOREVER);
+
+    /* Wait until the pirl in ready. */
+    data = 1;
+    while(data == 1)
+    {
+        retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->pirlRegsSem);
+            return retVal;
+        }
+    }
+
+    /* Set the PIRL Operation register */
+	switch (pirlOp)
+	{
+		case PIRL_INIT_ALL_RESOURCE:
+			data = (1 << 15) | (PIRL_INIT_ALL_RESOURCE << 12);
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+			break;
+		case PIRL_INIT_RESOURCE:
+			data = (GT_U16)((1 << 15) | (PIRL_INIT_RESOURCE << 12) | 
+					(opData->irlPort << 8) |
+					(opData->irlRes << 5));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+			break;
+
+		case PIRL_WRITE_RESOURCE:
+			data = (GT_U16)opData->irlData;
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_DATA,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+
+			data = (GT_U16)((1 << 15) | (PIRL_WRITE_RESOURCE << 12) | 
+					(opData->irlPort << 8)	|
+					(opData->irlRes << 5)	|
+					(opData->irlReg & 0xF));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+			break;
+
+		case PIRL_READ_RESOURCE:
+			data = (GT_U16)((1 << 15) | (PIRL_READ_RESOURCE << 12) | 
+					(opData->irlPort << 8)	|
+					(opData->irlRes << 5)	|
+					(opData->irlReg & 0xF));
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_INGRESS_RATE_COMMAND,data);
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+
+		    data = 1;
+		    while(data == 1)
+		    {
+		        retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
+		        if(retVal != GT_OK)
+		        {
+		            gtSemGive(dev,dev->pirlRegsSem);
+		            return retVal;
+        		}
+		    }
+
+			retVal = hwReadGlobal2Reg(dev,QD_REG_INGRESS_RATE_DATA,&data);
+			opData->irlData = (GT_U32)data;
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->pirlRegsSem);
+            	return retVal;
+	        }
+		    gtSemGive(dev,dev->pirlRegsSem);
+		    return retVal;
+
+		default:
+			
+			gtSemGive(dev,dev->pirlRegsSem);
+			return GT_FAIL;
+	}
+
+    /* Wait until the pirl in ready. */
+    data = 1;
+    while(data == 1)
+    {
+        retVal = hwGetGlobal2RegField(dev,QD_REG_INGRESS_RATE_COMMAND,15,1,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->pirlRegsSem);
+            return retVal;
+        }
+    }
+
+    gtSemGive(dev,dev->pirlRegsSem);
+    return retVal;
+}
+
+/*
+ * Initialize all PIRL resources to the inital state.
+*/
+static GT_STATUS pirl2Initialize
+(
+    IN  GT_QD_DEV  			*dev
+)
+{
+	GT_STATUS       retVal;	/* Functions return value */
+	GT_PIRL2_OPERATION	op;
+
+	op = PIRL_INIT_ALL_RESOURCE;
+
+	retVal = pirl2OperationPerform(dev, op, NULL);
+	if (retVal != GT_OK)
+	{
+		DBG_INFO(("PIRL OP Failed.\n"));
+		return retVal;
+	}
+
+	retVal = gpirl2SetCurTimeUpInt(dev,4);
+	if (retVal != GT_OK)
+	{
+		DBG_INFO(("PIRL OP Failed.\n"));
+	}
+
+	return retVal;
+}
+
+/*
+ * Initialize the selected PIRL resource to the inital state.
+ * This function initializes only the BSM structure for the IRL Unit.
+*/
+static GT_STATUS pirl2InitIRLResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes
+)
+{
+	GT_STATUS       retVal;	/* Functions return value */
+	GT_PIRL2_OPERATION	op;
+	GT_PIRL2_OP_DATA 	opData;
+
+	op = PIRL_INIT_RESOURCE;
+	opData.irlPort = irlPort;
+	opData.irlRes = irlRes;
+
+	retVal = pirl2OperationPerform(dev, op, &opData);
+	if (retVal != GT_OK)
+	{
+		DBG_INFO(("PIRL OP Failed.\n"));
+		return retVal;
+	}
+
+	return retVal;
+}
+
+/*
+ * Disable the selected PIRL resource.
+*/
+static GT_STATUS pirl2DisableIRLResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes
+)
+{
+    GT_STATUS       retVal;			/* Functions return value */
+	GT_PIRL2_OPERATION	op;
+	GT_PIRL2_OP_DATA	opData;
+	int				i;
+
+	op = PIRL_WRITE_RESOURCE;
+
+	for(i=0; i<8; i++)
+	{
+		opData.irlPort = irlPort;
+		opData.irlRes = irlRes;
+		opData.irlReg = i;
+		opData.irlData = 0;
+
+		retVal = pirl2OperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+	}
+
+	return GT_OK;	
+}
+
+/*
+ * convert PIRL Data structure to PIRL Resource structure.
+ * if PIRL Data is not valid, return GT_BAD_PARARM;
+*/
+static GT_STATUS pirl2DataToResource
+(
+    IN  GT_QD_DEV  			*dev,
+    IN  GT_PIRL2_DATA		*pirlData,
+    OUT GT_PIRL2_RESOURCE	*res
+)
+{
+	GT_U32 typeMask;
+	GT_U32 data;
+    GT_U32 bktIncrementFactor = 1;
+    
+
+	gtMemSet((void*)res,0,sizeof(GT_PIRL2_RESOURCE));
+
+	data = (GT_U32)(pirlData->accountQConf|pirlData->accountFiltered|
+					pirlData->mgmtNrlEn|pirlData->saNrlEn|pirlData->daNrlEn|
+					pirlData->samplingMode);
+
+	if (data > 1)
+	{
+		DBG_INFO(("GT_BAD_PARAM (Boolean)\n"));
+		return GT_BAD_PARAM;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_RESTRICTED_PIRL2_RESOURCE))
+	{
+		if (pirlData->samplingMode != GT_FALSE)
+		{
+			DBG_INFO(("GT_BAD_PARAM (sampling mode)\n"));
+			return GT_BAD_PARAM;
+		}
+	}
+
+	res->accountQConf = pirlData->accountQConf;
+	res->accountFiltered = pirlData->accountFiltered;
+	res->mgmtNrlEn = pirlData->mgmtNrlEn;
+	res->saNrlEn = pirlData->saNrlEn;
+	res->daNrlEn = pirlData->daNrlEn;
+	res->samplingMode = pirlData->samplingMode;
+
+	switch(pirlData->actionMode)
+	{
+		case PIRL_ACTION_ACCEPT:
+		case PIRL_ACTION_USE_LIMIT_ACTION:
+			res->actionMode = pirlData->actionMode;
+			break;
+		default:
+			DBG_INFO(("GT_BAD_PARAM actionMode\n"));
+			return GT_BAD_PARAM;
+	}
+
+	switch(pirlData->ebsLimitAction)
+	{
+		case ESB_LIMIT_ACTION_DROP:
+		case ESB_LIMIT_ACTION_FC:
+			res->ebsLimitAction = pirlData->ebsLimitAction;
+			break;
+		default:
+			DBG_INFO(("GT_BAD_PARAM ebsLimitAction\n"));
+			return GT_BAD_PARAM;
+	}
+
+	switch(pirlData->fcDeassertMode)
+	{
+		case GT_PIRL_FC_DEASSERT_EMPTY:
+		case GT_PIRL_FC_DEASSERT_CBS_LIMIT:
+			res->fcDeassertMode = pirlData->fcDeassertMode;
+			break;
+		default:
+			if(res->ebsLimitAction != ESB_LIMIT_ACTION_FC)
+			{
+				res->fcDeassertMode	= GT_PIRL_FC_DEASSERT_EMPTY;
+				break;
+			}
+			DBG_INFO(("GT_BAD_PARAM fcDeassertMode\n"));
+			return GT_BAD_PARAM;
+	}
+
+	if(pirlData->customSetup.isValid == GT_TRUE)
+	{
+		res->ebsLimit = pirlData->customSetup.ebsLimit;
+		res->cbsLimit = pirlData->customSetup.cbsLimit;
+		res->bktIncrement = pirlData->customSetup.bktIncrement;
+		res->bktRateFactor = pirlData->customSetup.bktRateFactor;
+	}
+	else
+	{
+		if(pirlData->ingressRate == 0)
+		{
+			DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
+			return GT_BAD_PARAM;
+		}
+
+		if(pirlData->ingressRate < 1000)	/* less than 1Mbps */
+		{
+			/* it should be divided by 64 */
+			if(pirlData->ingressRate % 64)
+			{
+				DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
+				return GT_BAD_PARAM;
+			}
+			res->bktRateFactor = pirlData->ingressRate/64 * 32;
+		}
+		else if(pirlData->ingressRate < 10000)	/* less than or equal to 10Mbps */
+		{
+			/* it should be divided by 1000 */
+			if(pirlData->ingressRate % 1000)
+			{
+				DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
+				return GT_BAD_PARAM;
+			}
+            res->bktRateFactor = pirlData->ingressRate/1000 * 4;
+		}
+		else /* greater than or equal to 10Mbps */
+		{
+			/* it should be divided by 1000 */
+			if(pirlData->ingressRate % 1000)
+			{
+				DBG_INFO(("GT_BAD_PARAM ingressRate(%i)\n",pirlData->ingressRate));
+				return GT_BAD_PARAM;
+			}
+            res->bktRateFactor = pirlData->ingressRate/1000 * 8;
+            bktIncrementFactor = 10;
+           
+		}
+	
+		/*If custom ebslimit exists, use the custom value, otherwize use recommended value*/
+		if(pirlData->customSetup.ebsLimit)
+		{
+           res->ebsLimit = pirlData->customSetup.ebsLimit;
+		}
+		else
+		{
+		res->ebsLimit = RECOMMENDED_ESB_LIMIT(dev, pirlData->ingressRate);
+		}
+
+		/*If custom cbslimit exists, use the custom value, otherwize use recommended value*/
+		if(pirlData->customSetup.cbsLimit)
+		{
+           res->cbsLimit = pirlData->customSetup.cbsLimit;
+		}
+		else
+		{
+		res->cbsLimit = RECOMMENDED_CBS_LIMIT(dev, pirlData->ingressRate);
+		}
+	
+		res->bktIncrement = RECOMMENDED_BUCKET_INCREMENT(dev, pirlData->ingressRate)*bktIncrementFactor;
+	}
+
+	switch(pirlData->bktRateType)
+	{
+		case BUCKET_TYPE_TRAFFIC_BASED:
+			res->bktRateType = pirlData->bktRateType;
+
+			typeMask = 0x7FFF;
+
+			if (pirlData->bktTypeMask > typeMask)
+			{
+				DBG_INFO(("GT_BAD_PARAM bktTypeMask(%#x)\n",pirlData->bktTypeMask));
+				return GT_BAD_PARAM;
+			}
+
+		   	res->bktTypeMask = pirlData->bktTypeMask;
+
+			if (pirlData->bktTypeMask & BUCKET_TRAFFIC_ARP)
+			{
+				res->bktTypeMask &= ~BUCKET_TRAFFIC_ARP;
+				res->bktTypeMask |= 0x80;
+			}
+			
+			if (pirlData->priORpt > 1)
+			{
+				DBG_INFO(("GT_BAD_PARAM rpiORpt\n"));
+				return GT_BAD_PARAM;
+			}
+
+			res->priORpt = pirlData->priORpt;
+
+			if (pirlData->priMask >= (1 << 4))
+			{
+				DBG_INFO(("GT_BAD_PARAM priMask(%#x)\n",pirlData->priMask));
+				return GT_BAD_PARAM;
+			}
+
+			res->priMask = pirlData->priMask;
+
+			break;
+
+		case BUCKET_TYPE_RATE_BASED:
+			res->bktRateType = pirlData->bktRateType;
+		   	res->bktTypeMask = pirlData->bktTypeMask;
+			res->priORpt = pirlData->priORpt;
+			res->priMask = pirlData->priMask;
+			break;
+
+		default:
+			DBG_INFO(("GT_BAD_PARAM bktRateType(%#x)\n",pirlData->bktRateType));
+			return GT_BAD_PARAM;
+	}
+
+	switch(pirlData->byteTobeCounted)
+	{
+		case GT_PIRL2_COUNT_FRAME:
+		case GT_PIRL2_COUNT_ALL_LAYER1:
+		case GT_PIRL2_COUNT_ALL_LAYER2:
+		case GT_PIRL2_COUNT_ALL_LAYER3:
+			res->byteTobeCounted = pirlData->byteTobeCounted;
+			break;
+		default:
+			DBG_INFO(("GT_BAD_PARAM byteTobeCounted(%#x)\n",pirlData->byteTobeCounted));
+			return GT_BAD_PARAM;
+	}
+
+	return GT_OK;			
+}
+
+/*
+ * convert PIRL Resource structure to PIRL Data structure.
+*/
+static GT_STATUS pirl2ResourceToData
+(
+    IN  GT_QD_DEV  			*dev,
+    IN  GT_PIRL2_RESOURCE	*res,
+    OUT GT_PIRL2_DATA		*pirlData
+)
+{
+	GT_U32	rate;
+	GT_U32	factor;
+
+	pirlData->accountQConf = res->accountQConf;
+	pirlData->accountFiltered = res->accountFiltered;
+	pirlData->mgmtNrlEn = res->mgmtNrlEn;
+	pirlData->saNrlEn = res->saNrlEn;
+	pirlData->daNrlEn = res->daNrlEn;
+	pirlData->samplingMode = res->samplingMode;
+	pirlData->ebsLimitAction = res->ebsLimitAction;
+	pirlData->actionMode = res->actionMode;
+	pirlData->fcDeassertMode = res->fcDeassertMode;
+	pirlData->customSetup.bktIncrement = res->bktIncrement;
+	pirlData->customSetup.bktRateFactor = res->bktRateFactor;	
+    pirlData->customSetup.ebsLimit = res->ebsLimit;
+    pirlData->customSetup.cbsLimit = res->cbsLimit;
+
+	pirlData->customSetup.isValid = GT_FALSE;
+
+	FACTOR_FROM_BUCKET_INCREMENT(dev,res->bktIncrement,factor);
+	
+	rate = res->bktRateFactor * factor;
+	if(factor == 32)
+	{
+		pirlData->ingressRate = (res->bktRateFactor/factor)*64;
+	}
+	else if (factor == 4)
+	{
+		pirlData->ingressRate = (res->bktRateFactor/factor)*1000;
+	}
+	else if (factor == 8)
+	{
+		pirlData->ingressRate = (res->bktRateFactor/factor)*1000;
+	}
+	else
+	{
+		pirlData->ingressRate = 0;
+	}	
+
+	pirlData->bktRateType = res->bktRateType;
+	pirlData->bktTypeMask = res->bktTypeMask;
+
+	if (pirlData->bktTypeMask & 0x80)
+	{
+		res->bktTypeMask &= ~0x80;
+		res->bktTypeMask |= BUCKET_TRAFFIC_ARP;
+	}
+			
+	pirlData->priORpt = res->priORpt;
+	pirlData->priMask = res->priMask;
+
+	pirlData->byteTobeCounted = res->byteTobeCounted;
+
+	return GT_OK;			
+}
+
+/*******************************************************************************
+* pirl2WriteResource
+*
+* DESCRIPTION:
+*       This function writes IRL Resource to BCM (Bucket Configuration Memory)
+*
+* INPUTS:
+*       irlPort - physical port number.
+*		irlRes  - bucket to be used (0 ~ 4).
+*       res 	- IRL Resource data
+*
+* OUTPUTS:
+*       Nont.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pirl2WriteResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	IN  GT_PIRL2_RESOURCE	*res
+)
+{
+	GT_STATUS       retVal;			/* Functions return value */
+	GT_U16          data[8]; 	/* temporary Data storage */
+	GT_PIRL2_OPERATION	op;
+	GT_PIRL2_OP_DATA 	opData;
+	int				i;
+
+	op = PIRL_WRITE_RESOURCE;
+
+	/* reg0 data */
+	data[0] = (GT_U16)((res->bktRateType << 15) |	/* Bit[15] : Bucket Rate Type */
+			  		(res->bktTypeMask << 0 )); 		/* Bit[14:0] : Traffic Type   */
+
+	/* reg1 data */
+	data[1] = (GT_U16)res->bktIncrement;	/* Bit[11:0] : Bucket Increment */
+
+	/* reg2 data */
+	data[2] = (GT_U16)res->bktRateFactor;	/* Bit[15:0] : Bucket Rate Factor */
+
+	/* reg3 data */
+	data[3] = (GT_U16)((res->cbsLimit & 0xFFF) << 4)|	/* Bit[15:4] : CBS Limit[11:0] */
+					(res->byteTobeCounted << 2);		/* Bit[3:0] : Bytes to be counted */
+
+	/* reg4 data */
+	data[4] = (GT_U16)(res->cbsLimit >> 12);		/* Bit[11:0] : CBS Limit[23:12] */
+
+	/* reg5 data */
+	data[5] = (GT_U16)(res->ebsLimit & 0xFFFF);		/* Bit[15:0] : EBS Limit[15:0] */
+
+	/* reg6 data */
+	data[6] = (GT_U16)((res->ebsLimit >> 16)	|	/* Bit[7:0] : EBS Limit[23:16] */
+					(res->samplingMode << 11)	|	/* Bit[11] : Sampling Mode */
+					(res->ebsLimitAction << 12)	|	/* Bit[12] : EBS Limit Action */
+					(res->actionMode << 13)		|	/* Bit[13] : Action Mode */
+					(res->fcDeassertMode << 14));	/* Bit[14] : Flow control mode */
+
+	/* reg7 data */
+	data[7] = (GT_U16)((res->daNrlEn)			|	/* Bit[0]  : DA Nrl En */
+					(res->saNrlEn << 1)			|	/* Bit[1]  : SA Nrl En */
+					(res->mgmtNrlEn << 2) 		|	/* Bit[2]  : MGMT Nrl En */
+					(res->priMask << 8) 		|	/* Bit[11:8] : Priority Queue Mask */
+					(res->priORpt << 12) 		|	/* Bit[12] : Priority OR PacketType */
+					(res->accountFiltered << 14)|	/* Bit[14] : Account Filtered */
+					(res->accountQConf << 15));		/* Bit[15] : Account QConf */
+
+	for(i=0; i<8; i++)
+	{
+		opData.irlPort = irlPort;
+		opData.irlRes = irlRes;
+		opData.irlReg = i;
+		opData.irlData = data[i];
+
+		retVal = pirl2OperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+	}
+
+	return GT_OK;	
+}
+
+
+/*******************************************************************************
+* pirl2ReadResource
+*
+* DESCRIPTION:
+*       This function reads IRL Resource from BCM (Bucket Configuration Memory)
+*
+* INPUTS:
+*       irlPort  - physical port number.
+*		irlRes   - bucket to be used (0 ~ 4).
+*
+* OUTPUTS:
+*       res - IRL Resource data
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pirl2ReadResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	OUT GT_PIRL2_RESOURCE	*res
+)
+{
+	GT_STATUS       retVal;		/* Functions return value */
+	GT_U16          data[8]; 	/* temporary Data storage */
+	GT_PIRL2_OPERATION	op;
+	GT_PIRL2_OP_DATA	opData;
+	int				i;
+
+	op = PIRL_READ_RESOURCE;
+
+	for(i=0; i<8; i++)
+	{
+		opData.irlPort = irlPort;
+		opData.irlRes = irlRes;
+		opData.irlReg = i;
+		opData.irlData = 0;
+
+		retVal = pirl2OperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+
+		data[i] = (GT_U16)opData.irlData;
+	}
+	
+
+	/* reg0 data */
+	res->bktRateType = (data[0] >> 15) & 0x1;
+	res->bktTypeMask = (data[0] >> 0) & 0x7FFF;
+
+	/* reg1 data */
+	res->bktIncrement = data[1] & 0xFFF;
+
+	/* reg2 data */
+	res->bktRateFactor = data[2] & 0xFFFF;
+
+	/* reg3,4 data */
+	res->byteTobeCounted = (data[3] >> 2) & 0x3;
+	res->cbsLimit = ((data[3] >> 4) & 0xFFF) | ((data[4] & 0xFFF) << 12);
+
+	/* reg5,6 data */
+	res->ebsLimit = data[5] | ((data[6] & 0xFF) << 16);
+													   
+	/* reg6 data */
+	res->samplingMode = (data[6] >> 11) & 0x1;
+	res->ebsLimitAction = (data[6] >> 12) & 0x1;
+	res->actionMode = (data[6] >> 13) & 0x1;
+	res->fcDeassertMode = (data[6] >> 14) & 0x1;
+
+	/* reg7 data */
+	res->daNrlEn = (data[7] >> 0) & 0x1;
+	res->saNrlEn = (data[7] >> 1) & 0x1;
+	res->mgmtNrlEn = (data[7] >> 2) & 0x1;
+	res->priMask = (data[7] >> 8) & 0xF;
+	res->priORpt = (data[7] >> 12) & 0x1;
+	res->accountFiltered = (data[7] >> 14) & 0x1;
+	res->accountQConf = (data[7] >> 15) & 0x1;
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* pirl2WriteTSMResource
+*
+* DESCRIPTION:
+* 		This function writes IRL Resource to BCM (Bucket Configuration Memory)
+*		in Time Slot Metering Mode.
+*
+* INPUTS:
+*		irlPort - physical port number.
+*		irlRes  - bucket to be used (0 ~ 1).
+*		res 	- IRL Resource data
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK on success,
+*		GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pirl2WriteTSMResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	IN  GT_PIRL2_TSM_RESOURCE	*res
+)
+{
+	GT_STATUS       retVal;			/* Functions return value */
+	GT_U16          data[8]; 	/* temporary Data storage */
+	GT_PIRL2_OPERATION	op;
+	GT_PIRL2_OP_DATA 	opData;
+	int				i;
+
+	op = PIRL_WRITE_RESOURCE;
+
+	/* reg0 data */
+	data[0] = 0;
+
+	/* reg1 data */
+	data[1] = 0;
+
+	/* reg2 data */
+	data[2] = 0;
+
+	/* reg3 data */
+	data[3] = (GT_U16)(((res->cbsLimit & 0xFFF) << 4)|	/* Bit[15:4] : CBS Limit[11:0] */
+					(0x2 << 2));						/* Bit[3:0] : Bytes to be counted */
+
+	/* reg4 data */
+	data[4] = (GT_U16)(res->cbsLimit >> 12);		/* Bit[11:0] : CBS Limit[23:12] */
+
+	/* reg5 data */
+	data[5] = (GT_U16)(res->ebsLimit & 0xFFFF);		/* Bit[15:0] : EBS Limit[15:0] */
+
+	/* reg6 data */
+	data[6] = (GT_U16)(res->actionMode << 13);		/* Bit[13] : Action Mode */
+
+	/* reg7 data */
+	data[7] = (GT_U16)((res->tsmMode << 7)		|	/* Bit[7]  : TSM Mode */
+					(res->mgmtNrlEn << 2) 		|	/* Bit[2]  : MGMT Nrl En */
+					(res->priMask << 8) 		|	/* Bit[11:8] : Priority Queue Mask */
+					(res->ctsIntv << 4));			/* Bit[5:4] : Class Timer Slot Interval */
+
+	for(i=0; i<8; i++)
+	{
+		opData.irlPort = irlPort;
+		opData.irlRes = irlRes;
+		opData.irlReg = i;
+		opData.irlData = data[i];
+
+		retVal = pirl2OperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+	}
+
+	return GT_OK;	
+}
+
+
+/*******************************************************************************
+* pirl2ReadTSMResource
+*
+* DESCRIPTION:
+*		This function reads IRL Resource from BCM (Bucket Configuration Memory)
+*		in Time Slot Metering Mode.
+*
+* INPUTS:
+*		irlPort  - physical port number.
+*		irlRes   - bucket to be used (0 ~ 1).
+*
+* OUTPUTS:
+*		res - IRL Resource data
+*
+* RETURNS:
+* 		GT_OK on success,
+* 		GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS pirl2ReadTSMResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	OUT GT_PIRL2_TSM_RESOURCE	*res
+)
+{
+	GT_STATUS       retVal;		/* Functions return value */
+	GT_U16          data[8]; 	/* temporary Data storage */
+	GT_PIRL2_OPERATION	op;
+	GT_PIRL2_OP_DATA	opData;
+	int				i;
+
+	op = PIRL_READ_RESOURCE;
+
+	for(i=0; i<8; i++)
+	{
+		opData.irlPort = irlPort;
+		opData.irlRes = irlRes;
+		opData.irlReg = i;
+		opData.irlData = 0;
+
+		retVal = pirl2OperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+
+		data[i] = (GT_U16)opData.irlData;
+	}
+	
+	res->tsmMode = data[7] & (1<<7);
+
+	if(res->tsmMode == GT_FALSE)
+	{
+		/* TMS mode is not set */
+		res->cbsLimit = 0;
+		res->ebsLimit = 0;
+		res->actionMode = 0;
+		res->mgmtNrlEn = 0;
+		res->priMask = 0;
+		res->ctsIntv = 0;
+
+		return GT_OK;
+	}
+
+	/* reg3,4 data */
+	res->cbsLimit = ((data[3] >> 4) & 0xFFF) | ((data[4] & 0xF) << 12);
+
+	/* reg5,6 data */
+	res->ebsLimit = data[5];
+													   
+	/* reg6 data */
+	res->actionMode = (data[6] >> 13) & 0x1;
+
+	/* reg7 data */
+	res->mgmtNrlEn = (data[7] >> 2) & 0x1;
+	res->priMask = (data[7] >> 8) & 0xF;
+	res->ctsIntv = (data[7] >> 4) & 0x3;
+
+	return GT_OK;
+}
+
+#define PIRL2_DEBUG
+#ifdef PIRL2_DEBUG
+/*******************************************************************************
+* pirl2DumpResource
+*
+* DESCRIPTION:
+*       This function dumps IRL Resource register values.
+*
+* INPUTS:
+*       irlPort  - physical port number.
+*		irlRes   - bucket to be used (0 ~ 4).
+*		dataLen  - data size.
+*
+* OUTPUTS:
+*       data - IRL Resource data
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS pirl2DumpResource
+(
+	IN  GT_QD_DEV  			*dev,
+	IN	GT_U32				irlPort,
+	IN	GT_U32				irlRes,
+	IN	GT_U32				dataLen,
+	OUT GT_U16				*data
+)
+{
+	GT_STATUS       retVal;		/* Functions return value */
+	GT_PIRL2_OPERATION	op;
+	GT_PIRL2_OP_DATA	opData;
+	GT_U32				i;
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	op = PIRL_READ_RESOURCE;
+
+	for(i=0; i<dataLen; i++)
+	{
+		opData.irlPort = irlPort;
+		opData.irlRes = irlRes;
+		opData.irlReg = i;
+		opData.irlData = 0;
+
+		retVal = pirl2OperationPerform(dev, op, &opData);
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("PIRL OP Failed.\n"));
+        	return retVal;
+		}
+
+		data[i] = (GT_U16)opData.irlData;
+	}
+
+	return GT_OK;	
+}
+#endif /* PIRL2_DEBUG */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPTP.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPTP.c
new file mode 100755
index 0000000..0d14476
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPTP.c
@@ -0,0 +1,7613 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtPTP.c
+*
+* DESCRIPTION:
+*       API definitions for Precise Time Protocol logic
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+#ifdef CONFIG_AVB_FPGA
+
+#undef USE_SINGLE_READ
+
+#define AVB_SMI_ADDR		0xC
+
+#define QD_REG_PTP_INT_OFFSET		0
+#define QD_REG_PTP_INTEN_OFFSET		1
+#define QD_REG_PTP_FREQ_OFFSET		4
+#define QD_REG_PTP_PHASE_OFFSET		6
+#define QD_REG_PTP_CLK_CTRL_OFFSET	4
+#define QD_REG_PTP_CYCLE_INTERVAL_OFFSET		5
+#define QD_REG_PTP_CYCLE_ADJ_OFFSET				6
+#define QD_REG_PTP_PLL_CTRL_OFFSET	7
+#define QD_REG_PTP_CLK_SRC_OFFSET	0x9
+#define QD_REG_PTP_P9_MODE_OFFSET	0xA
+#define QD_REG_PTP_RESET_OFFSET		0xB
+
+#define GT_PTP_MERGE_32BIT(_high16,_low16)	(((_high16)<<16)|(_low16))
+#define GT_PTP_GET_HIGH16(_data)	((_data) >> 16) & 0xFFFF
+#define GT_PTP_GET_LOW16(_data)		(_data) & 0xFFFF
+
+#define AVB_FPGA_READ_REG	gsysReadMiiReg
+#define AVB_FPGA_WRITE_REG	gsysWriteMiiReg
+
+#endif
+
+#if 0
+#define GT_PTP_BUILD_TIME(_time1, _time2)	(((_time1) << 16) | (_time2))
+#define GT_PTP_L16_TIME(_time1)	((_time1) & 0xFFFF)
+#define GT_PTP_H16_TIME(_time1)	(((_time1) >> 16) & 0xFFFF)
+#endif
+
+
+/****************************************************************************/
+/* PTP operation function declaration.                                    */
+/****************************************************************************/
+static GT_STATUS ptpOperationPerform
+(
+    IN   GT_QD_DEV 			*dev,
+    IN   GT_PTP_OPERATION	ptpOp,
+    INOUT GT_PTP_OP_DATA 	*opData
+);
+
+
+/*******************************************************************************
+* gptpSetConfig
+*
+* DESCRIPTION:
+*       This routine writes PTP configuration parameters.
+*
+* INPUTS:
+*		ptpData  - PTP configuration parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_CONFIG	*ptpData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_LPORT			port;
+	GT_PTP_PORT_CONFIG	ptpPortData;
+
+	DBG_INFO(("gptpSetConfig Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_WRITE_DATA;
+
+	/* setting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	opData.ptpData = ptpData->ptpEType;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	/* setting MsgIDTSEn, offset 1 */
+	opData.ptpAddr = 1;
+	opData.ptpData = ptpData->msgIdTSEn;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing MsgIDTSEn.\n"));
+		return GT_FAIL;
+	}
+
+	/* setting TSArrPtr, offset 2 */
+	opData.ptpAddr = 2;
+	opData.ptpData = ptpData->tsArrPtr;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing TSArrPtr.\n"));
+		return GT_FAIL;
+	}
+
+#ifndef CONFIG_AVB_FPGA
+	if (IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+#endif
+    {
+		ptpPortData.transSpec = ptpData->transSpec;
+		ptpPortData.disTSpec = 1;	/* default value */
+		ptpPortData.disTSOverwrite = ptpData->disTSOverwrite;
+		ptpPortData.ipJump = 2;		/* default value */
+		ptpPortData.etJump = 12;	/* default value */
+
+		/* per port configuration */
+		for(port=0; port<dev->numOfPorts; port++)
+		{
+			ptpPortData.ptpArrIntEn = (ptpData->ptpArrIntEn & (1 << port))? GT_TRUE : GT_FALSE;
+			ptpPortData.ptpDepIntEn = (ptpData->ptpDepIntEn & (1 << port))? GT_TRUE : GT_FALSE;
+
+			if((retVal = gptpSetPortConfig(dev, port, &ptpPortData)) != GT_OK)
+			{
+        		DBG_INFO(("Failed gptpSetPortConfig.\n"));
+				return GT_FAIL;
+			}
+		}
+
+		return GT_OK;
+    }
+
+	/* setting PTPArrIntEn, offset 3 */
+	opData.ptpAddr = 3;
+	opData.ptpData = GT_LPORTVEC_2_PORTVEC(ptpData->ptpArrIntEn);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing PTPArrIntEn.\n"));
+		return GT_FAIL;
+	}
+
+	/* setting PTPDepIntEn, offset 4 */
+	opData.ptpAddr = 4;
+	opData.ptpData = GT_LPORTVEC_2_PORTVEC(ptpData->ptpDepIntEn);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing PTPDepIntEn.\n"));
+		return GT_FAIL;
+	}
+
+	/* TransSpec, MsgIDStartBit, DisTSOverwrite bit, offset 5 */
+	op = PTP_READ_DATA;
+	opData.ptpAddr = 5;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+#ifdef CONFIG_AVB_FPGA
+	opData.ptpData = ((ptpData->transSpec&0xF) << 12) | ((ptpData->msgIdStartBit&0x7) << 9) | 
+					(opData.ptpData & 0x1) | ((ptpData->disTSOverwrite?1:0) << 1);
+#else
+	opData.ptpData = ((ptpData->transSpec&0xF) << 12) | (opData.ptpData & 0x1) | ((ptpData->disTSOverwrite?1:0) << 1);
+#endif
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing MsgIDStartBit & DisTSOverwrite.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetConfig
+*
+* DESCRIPTION:
+*       This routine reads PTP configuration parameters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpData  - PTP configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_CONFIG	*ptpData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_LPORT			port;
+	GT_PTP_PORT_CONFIG	ptpPortData;
+
+	DBG_INFO(("gptpGetConfig Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	/* getting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->ptpEType = opData.ptpData;
+
+	/* getting MsgIDTSEn, offset 1 */
+	opData.ptpAddr = 1;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading MsgIDTSEn.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->msgIdTSEn = opData.ptpData;
+
+	/* getting TSArrPtr, offset 2 */
+	opData.ptpAddr = 2;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading TSArrPtr.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->tsArrPtr = opData.ptpData;
+
+#ifndef CONFIG_AVB_FPGA
+	if (IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+#endif
+    {
+		ptpData->ptpArrIntEn = 0;
+		ptpData->ptpDepIntEn = 0;
+
+		/* per port configuration */
+		for(port=0; port<dev->numOfPorts; port++)
+		{
+			if((retVal = gptpGetPortConfig(dev, port, &ptpPortData)) != GT_OK)
+			{
+        		DBG_INFO(("Failed gptpGetPortConfig.\n"));
+				return GT_FAIL;
+			}
+
+			ptpData->ptpArrIntEn |= (ptpPortData.ptpArrIntEn ? (1 << port) : 0);
+			ptpData->ptpDepIntEn |= (ptpPortData.ptpDepIntEn ? (1 << port) : 0);
+		}
+
+		ptpData->transSpec = ptpPortData.transSpec;
+		ptpData->disTSOverwrite = ptpPortData.disTSOverwrite;
+
+		ptpData->msgIdStartBit = 4;
+
+		return GT_OK;
+    }
+
+	/* getting PTPArrIntEn, offset 3 */
+	opData.ptpAddr = 3;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPArrIntEn.\n"));
+		return GT_FAIL;
+	}
+	opData.ptpData &= dev->validPortVec;
+	ptpData->ptpArrIntEn = GT_PORTVEC_2_LPORTVEC(opData.ptpData);
+
+
+	/* getting PTPDepIntEn, offset 4 */
+	opData.ptpAddr = 4;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPDepIntEn.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= dev->validPortVec;
+	ptpData->ptpDepIntEn = GT_PORTVEC_2_LPORTVEC(opData.ptpData);
+
+	/* MsgIDStartBit, DisTSOverwrite bit, offset 5 */
+	opData.ptpAddr = 5;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->transSpec = (opData.ptpData >> 12) & 0xF;
+#ifdef CONFIG_AVB_FPGA
+	ptpData->msgIdStartBit = (opData.ptpData >> 9) & 0x7;
+#else
+	ptpData->msgIdStartBit = 0;
+#endif
+	ptpData->disTSOverwrite = ((opData.ptpData >> 1) & 0x1) ? GT_TRUE : GT_FALSE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpSetGlobalConfig
+*
+* DESCRIPTION:
+*       This routine writes PTP global configuration parameters.
+*
+* INPUTS:
+*		ptpData  - PTP global configuration parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetGlobalConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_GLOBAL_CONFIG	*ptpData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gptpSetGlobalConfig Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_WRITE_DATA;
+
+	/* setting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	opData.ptpData = ptpData->ptpEType;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	/* setting MsgIDTSEn, offset 1 */
+	opData.ptpAddr = 1;
+	opData.ptpData = ptpData->msgIdTSEn;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing MsgIDTSEn.\n"));
+		return GT_FAIL;
+	}
+
+	/* setting TSArrPtr, offset 2 */
+	opData.ptpAddr = 2;
+	opData.ptpData = ptpData->tsArrPtr;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing TSArrPtr.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGlobalGetConfig
+*
+* DESCRIPTION:
+*       This routine reads PTP global configuration parameters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpData  - PTP global configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetGlobalConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_GLOBAL_CONFIG	*ptpData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gptpGetGlobalConfig Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	/* getting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->ptpEType = opData.ptpData;
+
+	/* getting MsgIDTSEn, offset 1 */
+	opData.ptpAddr = 1;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading MsgIDTSEn.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->msgIdTSEn = opData.ptpData;
+
+	/* getting TSArrPtr, offset 2 */
+	opData.ptpAddr = 2;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading TSArrPtr.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->tsArrPtr = opData.ptpData;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpSetPortConfig
+*
+* DESCRIPTION:
+*       This routine writes PTP port configuration parameters.
+*
+* INPUTS:
+*		ptpData  - PTP port configuration parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetPortConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_PTP_PORT_CONFIG	*ptpData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+    GT_U32          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gptpSetPortConfig Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	if (ptpData->transSpec > 0xF)	/* 4 bits */
+		return GT_BAD_PARAM;
+
+	if (ptpData->etJump > 0x1F)	/* 5 bits */
+		return GT_BAD_PARAM;
+
+	if (ptpData->ipJump > 0x3F)	/* 6 bits */
+		return GT_BAD_PARAM;
+
+	
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = hwPort;
+
+	/* TransSpec, DisTSpecCheck, DisTSOverwrite bit, offset 0 */
+	op = PTP_READ_DATA;
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+	opData.ptpData = (ptpData->transSpec << 12) | (opData.ptpData & 0x1) |
+					((ptpData->disTSpec?1:0) << 11) |
+					((ptpData->disTSOverwrite?1:0) << 1);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing TransSpec,DisTSpecCheck,DisTSOverwrite.\n"));
+		return GT_FAIL;
+	}
+
+	/* setting etJump and ipJump, offset 1 */
+	opData.ptpAddr = 1;
+	opData.ptpData = (ptpData->ipJump << 8) | ptpData->etJump;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing MsgIDTSEn.\n"));
+		return GT_FAIL;
+	}
+
+	/* setting Int, offset 2 */
+	opData.ptpAddr = 2;
+	opData.ptpData = (ptpData->ptpArrIntEn?1:0) |
+					((ptpData->ptpDepIntEn?1:0) << 1);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing TSArrPtr.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetPortConfig
+*
+* DESCRIPTION:
+*       This routine reads PTP configuration parameters for a port.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpData  - PTP port configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPortConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_PTP_PORT_CONFIG	*ptpData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+    GT_U32          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gptpGetPortConfig Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = hwPort;
+	op = PTP_READ_DATA;
+
+	/* TransSpec, DisTSpecCheck, DisTSOverwrite bit, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->transSpec = opData.ptpData >> 12;
+	ptpData->disTSpec = ((opData.ptpData >> 11) & 0x1) ? GT_TRUE : GT_FALSE;
+	ptpData->disTSOverwrite = ((opData.ptpData >> 1) & 0x1) ? GT_TRUE : GT_FALSE;
+
+	/* getting MsgIDTSEn, offset 1 */
+	opData.ptpAddr = 1;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading MsgIDTSEn.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->ipJump = (opData.ptpData >> 8) & 0x3F;
+	ptpData->etJump = opData.ptpData & 0x1F;
+
+	/* getting TSArrPtr, offset 2 */
+	opData.ptpAddr = 2;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading TSArrPtr.\n"));
+		return GT_FAIL;
+	}
+
+	ptpData->ptpDepIntEn = ((opData.ptpData >> 1) & 0x1) ? GT_TRUE : GT_FALSE;
+	ptpData->ptpArrIntEn = (opData.ptpData & 0x1) ? GT_TRUE : GT_FALSE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpSetPTPEn
+*
+* DESCRIPTION:
+*       This routine enables or disables PTP.
+*
+* INPUTS:
+*		en - GT_TRUE to enable PTP, GT_FALSE to disable PTP
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetPTPEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_LPORT			port;
+
+	DBG_INFO(("gptpSetPTPEn Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+#ifndef CONFIG_AVB_FPGA
+	if (IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+#endif
+    {
+		/* per port configuration */
+		for(port=0; port<dev->numOfPorts; port++)
+		{
+			if((retVal = gptpSetPortPTPEn(dev, port, en)) != GT_OK)
+			{
+        		DBG_INFO(("Failed gptpSetPortPTPEn.\n"));
+				return GT_FAIL;
+			}
+		}
+
+		return GT_OK;
+    }
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+	opData.ptpAddr = 5;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+	opData.ptpData &= ~0x1;
+	opData.ptpData |= (en ? 0 : 1);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing MsgIDStartBit & DisTSOverwrite.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetPTPEn
+*
+* DESCRIPTION:
+*       This routine checks if PTP is enabled.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPTPEn
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gptpGetPTPEn Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+#ifndef CONFIG_AVB_FPGA
+	if (IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+#endif
+    {
+		if((retVal = gptpGetPortPTPEn(dev, 0, en)) != GT_OK)
+		{
+       		DBG_INFO(("Failed gptpGetPortPTPEn.\n"));
+			return GT_FAIL;
+		}
+
+		return GT_OK;
+    }
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+	opData.ptpAddr = 5;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*en = (opData.ptpData & 0x1) ? GT_FALSE : GT_TRUE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpSetPortPTPEn
+*
+* DESCRIPTION:
+*       This routine enables or disables PTP on a port.
+*
+* INPUTS:
+*		en - GT_TRUE to enable PTP, GT_FALSE to disable PTP
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetPortPTPEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32			hwPort;
+
+	DBG_INFO(("gptpSetPortPTPEn Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+	opData.ptpAddr = 0;
+
+	opData.ptpPort = hwPort;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	if (en)
+		opData.ptpData &= ~0x1;
+	else
+		opData.ptpData |= 0x1;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing TransSpec,DisTSpecCheck,DisTSOverwrite.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gptpGetPortPTPEn
+*
+* DESCRIPTION:
+*       This routine checks if PTP is enabled on a port.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPortPTPEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32			hwPort;
+
+	DBG_INFO(("gptpGetPortPTPEn Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpAddr = 0;
+	opData.ptpPort = hwPort;
+
+	op = PTP_READ_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*en = (opData.ptpData & 0x1) ? GT_FALSE : GT_TRUE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetPTPInt
+*
+* DESCRIPTION:
+*       This routine gets PTP interrupt status for each port.
+*		The PTP Interrupt bit gets set for a given port when an incoming PTP 
+*		frame is time stamped and PTPArrIntEn for that port is set to 0x1.
+*		Similary PTP Interrupt bit gets set for a given port when an outgoing
+*		PTP frame is time stamped and PTPDepIntEn for that port is set to 0x1.
+*		This bit gets cleared upon software reading and clearing the corresponding
+*		time counter valid bits that are valid for that port.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpInt 	- interrupt status for each port (bit 0 for port 0, bit 1 for port 1, etc.)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPTPInt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*ptpInt
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gptpGetPTPInt Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+	opData.ptpAddr = 8;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= (1 << dev->maxPorts) - 1;
+
+	*ptpInt = GT_PORTVEC_2_LPORTVEC(opData.ptpData);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetPTPGlobalTime
+*
+* DESCRIPTION:
+*       This routine gets the global timer value that is running off of the free
+*		running switch core clock.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpTime	- PTP global time
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetPTPGlobalTime
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*ptpTime
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gptpGetPTPGlobalTime Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+#ifndef USE_SINGLE_READ
+	opData.ptpBlock = 0x0;	/* PTP register space */
+	opData.ptpPort = IS_IN_DEV_GROUP(dev,DEV_TAI)?0xE:0xF;	/* Global register */
+	op = PTP_READ_MULTIPLE_DATA;
+	opData.ptpAddr = IS_IN_DEV_GROUP(dev,DEV_TAI)?0xE:9;
+	opData.nData = 2;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*ptpTime = GT_PTP_BUILD_TIME(opData.ptpMultiData[1],opData.ptpMultiData[0]);
+#else
+	{
+	GT_U32 data[2];
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+	opData.ptpPort = IS_IN_DEV_GROUP(dev,DEV_TAI)?0xE:0xF;	/* Global register */
+	op = PTP_READ_DATA;
+	opData.ptpAddr = IS_IN_DEV_GROUP(dev,DEV_TAI)?0xE:9;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	data[0] = opData.ptpData;
+
+	op = PTP_READ_DATA;
+	opData.ptpAddr++;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	data[1] = opData.ptpData;
+
+	*ptpTime = GT_PTP_BUILD_TIME(data[1],data[0]);
+
+	}
+#endif
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetTimeStamped
+*
+* DESCRIPTION:
+*		This routine retrieves the PTP port status that includes time stamp value 
+*		and sequce Id that are captured by PTP logic for a PTP frame that needs 
+*		to be time stamped.
+*
+* INPUTS:
+*       port 		- logical port number.
+*       timeToRead	- Arr0, Arr1, or Dep time (GT_PTP_TIME enum type)
+*
+* OUTPUTS:
+*		ptpStatus	- PTP port status
+*
+* RETURNS:
+*       GT_OK 		- on success
+*       GT_FAIL 	- on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetTimeStamped
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN	GT_PTP_TIME	timeToRead,
+	OUT GT_PTP_TS_STATUS	*ptpStatus
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				hwPort;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32				baseReg;
+
+	DBG_INFO(("gptpGetTimeStamped Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+	{
+        DBG_INFO(("Invalid port number\n"));
+		return GT_BAD_PARAM;
+	}
+
+#ifndef CONFIG_AVB_FPGA
+	if (IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+		baseReg = 8;
+	else
+		baseReg = 0;
+#else
+	baseReg = 8;
+#endif
+
+	switch (timeToRead)
+	{
+		case PTP_ARR0_TIME:
+			opData.ptpAddr = baseReg + 0;
+			break;
+		case PTP_ARR1_TIME:
+			opData.ptpAddr = baseReg + 4;
+			break;
+		case PTP_DEP_TIME:
+			opData.ptpAddr = baseReg + 8;
+			break;
+		default:
+        	DBG_INFO(("Invalid time to be read\n"));
+			return GT_BAD_PARAM;
+	}
+
+	opData.ptpPort = hwPort;
+	opData.ptpBlock = 0;
+
+#ifndef USE_SINGLE_READ
+	op = PTP_READ_TIMESTAMP_DATA;
+	opData.nData = 4;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	ptpStatus->isValid = (opData.ptpMultiData[0] & 0x1) ? GT_TRUE : GT_FALSE;
+	ptpStatus->status = (GT_PTP_INT_STATUS)((opData.ptpMultiData[0] >> 1) & 0x3);
+	ptpStatus->timeStamped = GT_PTP_BUILD_TIME(opData.ptpMultiData[2],opData.ptpMultiData[1]);
+	ptpStatus->ptpSeqId = opData.ptpMultiData[3];
+#else
+	{
+	GT_U32 data[4], i;
+
+	op = PTP_READ_DATA;
+
+	for (i=0; i<4; i++)
+	{
+		if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+		{
+        	DBG_INFO(("Failed reading DisPTP.\n"));
+			return GT_FAIL;
+		}
+	
+		data[i] = opData.ptpData;
+		opData.ptpAddr++;
+	}
+
+	ptpStatus->isValid = (data[0] & 0x1) ? GT_TRUE : GT_FALSE;
+	ptpStatus->status = (GT_PTP_INT_STATUS)((data[0] >> 1) & 0x3);
+	ptpStatus->timeStamped = GT_PTP_BUILD_TIME(data[2],data[1]);
+	ptpStatus->ptpSeqId = data[3];
+
+	}
+#endif
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpResetTimeStamp
+*
+* DESCRIPTION:
+*		This routine resets PTP Time valid bit so that PTP logic can time stamp
+*		a next PTP frame that needs to be time stamped.
+*
+* INPUTS:
+*       port 		- logical port number.
+*       timeToReset	- Arr0, Arr1, or Dep time (GT_PTP_TIME enum type)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK 		- on success
+*       GT_FAIL 	- on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpResetTimeStamp
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN	GT_PTP_TIME	timeToReset
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				hwPort;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32				baseReg;
+
+	DBG_INFO(("gptpResetTimeStamp Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+	{
+        DBG_INFO(("Invalid port number\n"));
+		return GT_BAD_PARAM;
+	}
+
+#ifndef CONFIG_AVB_FPGA
+	if (IS_IN_DEV_GROUP(dev,DEV_PTP_2))
+		baseReg = 8;
+	else
+		baseReg = 0;
+#else
+	baseReg = 8;
+#endif
+
+	switch (timeToReset)
+	{
+		case PTP_ARR0_TIME:
+			opData.ptpAddr = baseReg + 0;
+			break;
+		case PTP_ARR1_TIME:
+			opData.ptpAddr = baseReg + 4;
+			break;
+		case PTP_DEP_TIME:
+			opData.ptpAddr = baseReg + 8;
+			break;
+		default:
+        	DBG_INFO(("Invalid time to reset\n"));
+			return GT_BAD_PARAM;
+	}
+
+	opData.ptpPort = hwPort;
+	opData.ptpData = 0;
+	opData.ptpBlock = 0;
+	op = PTP_WRITE_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Port Status.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetReg
+*
+* DESCRIPTION:
+*       This routine reads PTP register.
+*
+* INPUTS:
+*       port 		- logical port number.
+*       regOffset	- register to read
+*
+* OUTPUTS:
+*		data		- register data
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetReg
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		regOffset,
+	OUT GT_U32		*data
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				hwPort;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gptpGetReg Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+    hwPort = (GT_U32)port;
+
+	if (regOffset > 0x1F)
+	{
+        DBG_INFO(("Invalid reg offset\n"));
+		return GT_BAD_PARAM;
+	}
+
+	op = PTP_READ_DATA;
+	opData.ptpPort = hwPort;
+	opData.ptpAddr = regOffset;
+	opData.ptpBlock = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*data = opData.ptpData;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpSetReg
+*
+* DESCRIPTION:
+*       This routine writes data to PTP register.
+*
+* INPUTS:
+*       port 		- logical port number
+*       regOffset	- register to be written
+*		data		- data to be written
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetReg
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U32		regOffset,
+	IN  GT_U32		data
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				hwPort;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gptpSetReg Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PTP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+    hwPort = (GT_U32)port;
+
+	if ((regOffset > 0x1F) || (data > 0xFFFF))
+	{
+        DBG_INFO(("Invalid reg offset/data\n"));
+		return GT_BAD_PARAM;
+	}
+
+	op = PTP_WRITE_DATA;
+	opData.ptpPort = hwPort;
+	opData.ptpAddr = regOffset;
+	opData.ptpData = data;
+	opData.ptpBlock = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gtaiSetEventConfig
+*
+* DESCRIPTION:
+*       This routine sets TAI Event Capture configuration parameters.
+*
+* INPUTS:
+*		eventData  - TAI Event Capture configuration parameters.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetEventConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_TAI_EVENT_CONFIG	*eventData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiSetEventConfig Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	/* getting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= ~((3<<14)|(1<<8));
+	if (eventData->intEn)
+		opData.ptpData |= (1 << 8);
+	if (eventData->eventOverwrite)
+		opData.ptpData |= (1 << 15);
+	if (eventData->eventCtrStart)
+		opData.ptpData |= (1 << 14);
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gtaiGetEventConfig
+*
+* DESCRIPTION:
+*       This routine gets TAI Event Capture configuration parameters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		eventData  - TAI Event Capture configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetEventConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_TAI_EVENT_CONFIG	*eventData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiGetEventConfig Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	/* getting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	eventData->intEn = (opData.ptpData & (1<<8))?GT_TRUE:GT_FALSE;
+	eventData->eventOverwrite = (opData.ptpData & (1<<15))?GT_TRUE:GT_FALSE;
+	eventData->eventCtrStart = (opData.ptpData & (1<<14))?GT_TRUE:GT_FALSE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gtaiGetEventStatus
+*
+* DESCRIPTION:
+*       This routine gets TAI Event Capture status.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		eventData  - TAI Event Capture configuration parameters.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetEventStatus
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_TAI_EVENT_STATUS	*status
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32 				data[2];
+
+	DBG_INFO(("gtaiGetEventStatus Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 9;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	status->isValid = (opData.ptpData & (1<<8))?GT_TRUE:GT_FALSE;
+	status->eventCtr = opData.ptpData & 0xFF;
+	status->eventErr = (opData.ptpData & (1<<9))?GT_TRUE:GT_FALSE;
+
+	if (status->isValid == GT_FALSE)
+	{
+		return GT_OK;
+	}
+
+	opData.ptpAddr = 10;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+	data[0] = opData.ptpData;
+
+	opData.ptpAddr = 11;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+	data[1] = opData.ptpData;
+
+	status->eventTime = GT_PTP_BUILD_TIME(data[1],data[0]);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gtaiGetEventInt
+*
+* DESCRIPTION:
+*       This routine gets TAI Event Capture Interrupt status.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		intStatus 	- interrupt status for TAI Event capture
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetEventInt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*intStatus
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiGetEventInt Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpPort = 0xE;	/* Global register */
+	op = PTP_READ_DATA;
+	opData.ptpAddr = 9;
+	opData.ptpBlock = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*intStatus = (opData.ptpData & 0x8000)?GT_TRUE:GT_FALSE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gtaiGetTrigInt
+*
+* DESCRIPTION:
+*       This routine gets TAI Trigger Interrupt status.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		intStatus 	- interrupt status for TAI Trigger
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetTrigInt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*intStatus
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiGetTrigInt Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpPort = 0xE;	/* Global register */
+	op = PTP_READ_DATA;
+	opData.ptpAddr = 8;
+	opData.ptpBlock = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*intStatus = (opData.ptpData & 0x8000)?GT_TRUE:GT_FALSE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gtaiSetTrigConfig
+*
+* DESCRIPTION:
+*       This routine sets TAI Trigger configuration parameters.
+*
+* INPUTS:
+*		trigEn    - enable/disable TAI Trigger.
+*		trigData  - TAI Trigger configuration parameters (valid only if trigEn is GT_TRUE).
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetTrigConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL 	trigEn,
+	IN  GT_TAI_TRIGGER_CONFIG	*trigData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiSetTrigConfig Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	/* getting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= ~(3|(1<<9));
+
+	if (trigEn == GT_FALSE)
+	{
+		op = PTP_WRITE_DATA;
+
+		if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+		{
+        	DBG_INFO(("Failed writing PTPEType.\n"));
+			return GT_FAIL;
+		}
+
+		return GT_OK;
+	}
+
+	opData.ptpData |= 1;
+
+	if (trigData->intEn)
+		opData.ptpData |= (1 << 9);
+
+	if (trigData->mode == GT_TAI_TRIG_ON_GIVEN_TIME)
+		opData.ptpData |= (1 << 1);
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpAddr = 2;
+	opData.ptpData = GT_PTP_L16_TIME(trigData->trigGenAmt);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpAddr = 3;
+	opData.ptpData = GT_PTP_H16_TIME(trigData->trigGenAmt);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	if (trigData->mode == GT_TAI_TRIG_ON_GIVEN_TIME)
+	{
+		if ((trigData->pulseWidth >= 0) && (trigData->pulseWidth <= 0xF))
+		{			
+			op = PTP_READ_DATA;
+			opData.ptpAddr = 5;		/* PulseWidth */
+
+			if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+			{
+				DBG_INFO(("Failed writing PTPEType.\n"));
+				return GT_FAIL;
+			}
+
+			op = PTP_WRITE_DATA;
+			opData.ptpAddr = 5;		/* PulseWidth */
+			opData.ptpData &= (~0xF000);
+			opData.ptpData |= (GT_U16)(trigData->pulseWidth << 12);
+
+			if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+			{
+				DBG_INFO(("Failed writing PTPEType.\n"));
+				return GT_FAIL;
+			}
+		}
+	}
+	else
+	{
+		op = PTP_WRITE_DATA;
+		opData.ptpAddr = 4;		/* TrigClkComp */
+		opData.ptpData = (GT_U16)trigData->trigClkComp;
+
+		if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+		{
+			DBG_INFO(("Failed writing PTPEType.\n"));
+			return GT_FAIL;
+		}
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gtaiGetTrigConfig
+*
+* DESCRIPTION:
+*       This routine gets TAI Trigger configuration parameters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		trigEn    - enable/disable TAI Trigger.
+*		trigData  - TAI Trigger configuration parameters (valid only if trigEn is GT_TRUE).
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetTrigConfig
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL 	*trigEn,
+	OUT GT_TAI_TRIGGER_CONFIG	*trigData
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32 				data[2];
+
+	DBG_INFO(("gtaiGetTrigConfig Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	/* getting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	if (!(opData.ptpData & 1))
+	{
+		*trigEn = GT_FALSE;
+		return GT_OK;
+	}
+
+	if (trigData == NULL)
+	{
+		return GT_BAD_PARAM;
+	}
+
+	*trigEn = GT_TRUE;
+	trigData->mode = (opData.ptpData >> 1) & 1;
+	trigData->intEn = (opData.ptpData >> 9) & 1;
+
+	opData.ptpAddr = 2;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+	data[0] = opData.ptpData;
+
+	opData.ptpAddr = 3;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+	data[1] = opData.ptpData;
+
+	trigData->trigGenAmt = GT_PTP_BUILD_TIME(data[1],data[0]);
+
+	opData.ptpAddr = 5;		/* PulseWidth */
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed writing PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	trigData->pulseWidth = (GT_U32)((opData.ptpData >> 12) & 0xF);
+
+	/* getting TrigClkComp, offset 4 */
+	opData.ptpAddr = 4;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading PTPEType.\n"));
+		return GT_FAIL;
+	}
+
+	trigData->trigClkComp = (GT_U32)opData.ptpData;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gtaiGetTSClkPer
+*
+* DESCRIPTION:
+* 		Time Stamping Clock Period in pico seconds.
+*		This routine specifies the clock period for the time stamping clock supplied 
+*		to the PTP hardware logic.
+*		This is the clock that is used by the hardware logic to update the PTP 
+*		Global Time Counter.
+*
+* INPUTS:
+* 		None.
+*
+* OUTPUTS:
+*		clk		- time stamping clock period
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiGetTSClkPer
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*clk
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiGetTSClkPer Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 1;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*clk = (GT_U32)opData.ptpData;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gtaiSetTSClkPer
+*
+* DESCRIPTION:
+* 		Time Stamping Clock Period in pico seconds.
+*		This routine specifies the clock period for the time stamping clock supplied 
+*		to the PTP hardware logic.
+*		This is the clock that is used by the hardware logic to update the PTP 
+*		Global Time Counter.
+*
+* INPUTS:
+*		clk		- time stamping clock period
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetTSClkPer
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		clk
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiSetTSClkPer Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 1;
+
+	opData.ptpData = (GT_U16)clk; 
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gtaiSetMultiPTPSync
+*
+* DESCRIPTION:
+* 		This routine sets Multiple PTP device sync mode and sync time (TrigGenAmt).
+*		When enabled, the hardware logic detects a low to high transition on the 
+*		EventRequest(GPIO) and transfers the sync time into the PTP Global Time
+*		register. The EventCapTime is also updated at that instant.
+*
+* INPUTS:
+*		multiEn		- enable/disable Multiple PTP device sync mode
+*		syncTime	- sync time (valid only if multiEn is GT_TRUE)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		When enabled, gtaiSetTrigConfig, gtaiSetEventConfig, gtaiSetTimeInc,
+*		and gtaiSetTimeDec APIs are not operational.
+*
+*******************************************************************************/
+GT_STATUS gtaiSetMultiPTPSync
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL 	multiEn,
+	IN  GT_32		syncTime
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiSetMultiPTPSync Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	/* getting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= ~(1 << 2);
+
+	if (multiEn == GT_FALSE)
+	{
+		op = PTP_WRITE_DATA;
+
+		if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+		{
+			DBG_INFO(("Failed writing TAI register.\n"));
+			return GT_FAIL;
+		}
+
+		return GT_OK;
+	}
+
+	opData.ptpData |= (1 << 2);
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed writing TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpAddr = 2;
+	opData.ptpData = GT_PTP_L16_TIME(syncTime);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed writing TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpAddr = 3;
+	opData.ptpData = GT_PTP_H16_TIME(syncTime);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed writing TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gtaiGetMultiPTPSync
+*
+* DESCRIPTION:
+* 		This routine sets Multiple PTP device sync mode and sync time (TrigGenAmt).
+*		When enabled, the hardware logic detects a low to high transition on the 
+*		EventRequest(GPIO) and transfers the sync time into the PTP Global Time
+*		register. The EventCapTime is also updated at that instant.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		multiEn		- enable/disable Multiple PTP device sync mode
+*		syncTime	- sync time (valid only if multiEn is GT_TRUE)
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		When enabled, gtaiSetTrigConfig, gtaiSetEventConfig, gtaiSetTimeInc,
+*		and gtaiSetTimeDec APIs are not operational.
+*
+*******************************************************************************/
+GT_STATUS gtaiGetMultiPTPSync
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL 	*multiEn,
+	OUT GT_32		*syncTime
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32 				data[2];
+
+	DBG_INFO(("gtaiGetMultiPTPSync Called.\n"));
+
+    /* check if device supports this feature */
+#ifndef CONFIG_AVB_FPGA
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	/* getting PTPEType, offset 0 */
+	opData.ptpAddr = 0;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	if(!(opData.ptpData & (1 << 2)))
+	{
+		*multiEn = GT_FALSE;
+		*syncTime = 0;
+		return GT_OK;
+	}
+
+	opData.ptpAddr = 2;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading TAI register.\n"));
+		return GT_FAIL;
+	}
+	data[0] = opData.ptpData;
+
+	opData.ptpAddr = 3;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading TAI register.\n"));
+		return GT_FAIL;
+	}
+	data[1] = opData.ptpData;
+
+	*syncTime = GT_PTP_BUILD_TIME(data[1],data[0]);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gtaiGetTimeIncDec
+*
+* DESCRIPTION:
+* 		This routine retrieves Time increment/decrement setup.
+*		This amount specifies the number of units of PTP Global Time that need to be 
+*		incremented or decremented. This is used for adjusting the PTP Global Time 
+*		counter value by a certain amount.
+*
+* INPUTS:
+* 		None.
+*
+* OUTPUTS:
+*		expired	- GT_TRUE if inc/dec occurred, GT_FALSE otherwise
+*		inc		- GT_TRUE if increment, GT_FALSE if decrement
+*		amount	- increment/decrement amount
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		Time increment or decrement will be excuted once.
+*
+*******************************************************************************/
+GT_STATUS gtaiGetTimeIncDec
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*expired,
+	OUT GT_BOOL		*inc,
+	OUT GT_U32		*amount
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiGetTimeIncDec Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 5;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*inc = (opData.ptpData & 0x800)?GT_FALSE:GT_TRUE;
+	*amount = (GT_U32)(opData.ptpData & 0x7FF);
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*expired = (opData.ptpData & 0x8)?GT_FALSE:GT_TRUE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gtaiSetTimeInc
+*
+* DESCRIPTION:
+* 		This routine enables time increment by the specifed time increment amount.
+*		The amount specifies the number of units of PTP Global Time that need to be 
+*		incremented. This is used for adjusting the PTP Global Time counter value by
+*		a certain amount.
+*		Increment occurs just once.
+*
+* INPUTS:
+*		amount	- time increment amount (0 ~ 0x7FF)
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetTimeInc
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		amount
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiSetTimeInc Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+#endif
+
+	/* set TimeIncAmt */
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 5;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= 0xF000;
+	opData.ptpData |= amount;
+
+	op = PTP_WRITE_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	/* set TimeIncEn */
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData |= 0x8;
+
+	op = PTP_WRITE_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gtaiSetTimeDec
+*
+* DESCRIPTION:
+* 		This routine enables time decrement by the specifed time decrement amount.
+*		The amount specifies the number of units of PTP Global Time that need to be 
+*		decremented. This is used for adjusting the PTP Global Time counter value by
+*		a certain amount.
+*		Decrement occurs just once.
+*
+* INPUTS:
+*		amount	- time decrement amount (0 ~ 0x7FF)
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gtaiSetTimeDec
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		amount
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gtaiSetTimeInc Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAI))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* set TimeIncAmt */
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 5;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= 0xF000;
+	opData.ptpData |= amount;
+	opData.ptpData |= 0x800;	/* decrement */
+
+	op = PTP_WRITE_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed writing TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	/* set TimeIncEn */
+	opData.ptpBlock = 0x0;	/* PTP register space */
+
+	opData.ptpPort = 0xE;	/* TAI register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData |= 0x8;
+
+	op = PTP_WRITE_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed writing TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbGetPriority
+*
+* DESCRIPTION:
+*		Priority overwrite.
+*		Supported priority type is defined as GT_AVB_PRI_TYPE.
+*		Priority is either 3 bits or 2 bits depending on priority type.
+*			GT_AVB_HI_FPRI		- priority is 0 ~ 7
+*			GT_AVB_HI_QPRI		- priority is 0 ~ 3
+*			GT_AVB_LO_FPRI		- priority is 0 ~ 7
+*			GT_AVB_LO_QPRI		- priority is 0 ~ 3
+*			GT_LEGACY_HI_FPRI	- priority is 0 ~ 7
+*			GT_LEGACY_HI_QPRI	- priority is 0 ~ 3
+*			GT_LEGACY_LO_FPRI	- priority is 0 ~ 7
+*			GT_LEGACY_LO_QPRI	- priority is 0 ~ 3
+*
+* INPUTS:
+* 		priType	- GT_AVB_PRI_TYPE
+*
+* OUTPUTS:
+*		pri	- priority
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetPriority
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_AVB_PRI_TYPE		priType,
+	OUT GT_U32		*pri
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U16		mask, reg, bitPos;
+
+	DBG_INFO(("gavbGetPriority Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	switch (priType)
+	{
+		case GT_AVB_HI_FPRI:
+			mask = 0x7;
+			reg = 0;
+			bitPos = 12;
+			break;
+		case GT_AVB_HI_QPRI:
+			mask = 0x3;
+			reg = 0;
+			bitPos = 8;
+			break;
+		case GT_AVB_LO_FPRI:
+			mask = 0x7;
+			reg = 0;
+			bitPos = 4;
+			break;
+		case GT_AVB_LO_QPRI:
+			mask = 0x3;
+			reg = 0;
+			bitPos = 0;
+			break;
+		case GT_LEGACY_HI_FPRI:
+			mask = 0x7;
+			reg = 4;
+			bitPos = 12;
+			break;
+		case GT_LEGACY_HI_QPRI:
+			mask = 0x3;
+			reg = 4;
+			bitPos = 8;
+			break;
+		case GT_LEGACY_LO_FPRI:
+			mask = 0x7;
+			reg = 4;
+			bitPos = 4;
+			break;
+		case GT_LEGACY_LO_QPRI:
+			mask = 0x3;
+			reg = 4;
+			bitPos = 0;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = reg;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	*pri = (GT_U32)(opData.ptpData >> bitPos) & mask;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbSetPriority
+*
+* DESCRIPTION:
+*		Priority overwrite.
+*		Supported priority type is defined as GT_AVB_PRI_TYPE.
+*		Priority is either 3 bits or 2 bits depending on priority type.
+*			GT_AVB_HI_FPRI		- priority is 0 ~ 7
+*			GT_AVB_HI_QPRI		- priority is 0 ~ 3
+*			GT_AVB_LO_FPRI		- priority is 0 ~ 7
+*			GT_AVB_LO_QPRI		- priority is 0 ~ 3
+*			GT_LEGACY_HI_FPRI	- priority is 0 ~ 7
+*			GT_LEGACY_HI_QPRI	- priority is 0 ~ 3
+*			GT_LEGACY_LO_FPRI	- priority is 0 ~ 7
+*			GT_LEGACY_LO_QPRI	- priority is 0 ~ 3
+*
+* INPUTS:
+* 		priType	- GT_AVB_PRI_TYPE
+*		pri	- priority
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetPriority
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_AVB_PRI_TYPE		priType,
+	IN  GT_U32		pri
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U16		mask, reg, bitPos;
+
+	DBG_INFO(("gavbSetPriority Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	switch (priType)
+	{
+		case GT_AVB_HI_FPRI:
+			mask = 0x7;
+			reg = 0;
+			bitPos = 12;
+			break;
+		case GT_AVB_HI_QPRI:
+			mask = 0x3;
+			reg = 0;
+			bitPos = 8;
+			break;
+		case GT_AVB_LO_FPRI:
+			mask = 0x7;
+			reg = 0;
+			bitPos = 4;
+			break;
+		case GT_AVB_LO_QPRI:
+			mask = 0x3;
+			reg = 0;
+			bitPos = 0;
+			break;
+		case GT_LEGACY_HI_FPRI:
+			mask = 0x7;
+			reg = 4;
+			bitPos = 12;
+			break;
+		case GT_LEGACY_HI_QPRI:
+			mask = 0x3;
+			reg = 4;
+			bitPos = 8;
+			break;
+		case GT_LEGACY_LO_FPRI:
+			mask = 0x7;
+			reg = 4;
+			bitPos = 4;
+			break;
+		case GT_LEGACY_LO_QPRI:
+			mask = 0x3;
+			reg = 4;
+			bitPos = 0;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	if (pri & (~mask))
+	{
+		return GT_BAD_PARAM;
+	}
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = reg;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= ~(mask << bitPos);
+	opData.ptpData |= (pri << bitPos);
+
+	op = PTP_WRITE_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed writing TAI register.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gavbGetAVBHiLimit
+*
+* DESCRIPTION:
+*		AVB Hi Frame Limit.
+*		When these bits are zero, normal frame processing occurs. 
+*		When it's non-zero, they are used to define the maximum frame size allowed
+*		for AVB frames that can be placed into the GT_AVB_HI_QPRI queue. Frames
+*		that are over this size limit are filtered. The only exception to this 
+*		is non-AVB frames that get their QPriAvb assigned by the Priority Override 
+*		Table
+*
+* INPUTS:
+* 		None
+*
+* OUTPUTS:
+*		limit	- Hi Frame Limit
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAVBHiLimit
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*limit
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gavbGetAVBHiLimit Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 8;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*limit = (GT_U32)(opData.ptpData & 0x7FF);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbSetAVBHiLimit
+*
+* DESCRIPTION:
+*		AVB Hi Frame Limit.
+*		When these bits are zero, normal frame processing occurs. 
+*		When it's non-zero, they are used to define the maximum frame size allowed
+*		for AVB frames that can be placed into the GT_AVB_HI_QPRI queue. Frames
+*		that are over this size limit are filtered. The only exception to this 
+*		is non-AVB frames that get their QPriAvb assigned by the Priority Override 
+*		Table
+*
+* INPUTS:
+*		limit	- Hi Frame Limit
+*
+* OUTPUTS:
+* 		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAVBHiLimit
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		limit
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gavbSetAVBHiLimit Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 8;
+	opData.ptpData = (GT_U16)limit;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbGetPtpExtClk
+*
+* DESCRIPTION:
+*		PTP external clock select.
+*		When this bit is cleared to a zero, the PTP core gets its clock from 
+*		an internal 125MHz clock based on the device's XTAL_IN input. 
+*		When this bit is set to a one, the PTP core gets its clock from the device's
+*		PTP_EXTCLK pin.
+*
+* INPUTS:
+* 		None
+*
+* OUTPUTS:
+*		extClk	- GT_TRUE if external clock is selected, GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetPtpExtClk
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*extClk
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gavbGetPtpExtClk Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0xB;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*extClk = (GT_U32)(opData.ptpData >> 15) & 0x1;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gavbSetPtpExtClk
+*
+* DESCRIPTION:
+*		PTP external clock select.
+*		When this bit is cleared to a zero, the PTP core gets its clock from 
+*		an internal 125MHz clock based on the device's XTAL_IN input. 
+*		When this bit is set to a one, the PTP core gets its clock from the device's
+*		PTP_EXTCLK pin.
+*
+* INPUTS:
+*		extClk	- GT_TRUE if external clock is selected, GT_FALSE otherwise
+*
+* OUTPUTS:
+* 		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetPtpExtClk
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		extClk
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gavbSetPtpExtClk Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0xB;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	if(extClk)
+		opData.ptpData |= 0x8000;
+	else
+		opData.ptpData &= ~0x8000;
+
+	op = PTP_WRITE_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbGetRecClkSel
+*
+* DESCRIPTION:
+*		Synchronous Ethernet Recovered Clock Select.
+*		This field indicate the internal PHY number whose recovered clock will
+*		be presented on the SE_RCLK0 or SE_RCLK1 pin depending on the recClk selection.
+*
+* INPUTS:
+*		recClk	- GT_AVB_RECOVERED_CLOCK type
+*
+* OUTPUTS:
+*		clkSel	- recovered clock selection
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetRecClkSel
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_AVB_RECOVERED_CLOCK	recClk,
+	OUT GT_U32		*clkSel
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U16		bitPos;
+
+	DBG_INFO(("gavbGetRecClkSel Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	switch (recClk)
+	{
+		case GT_PRIMARY_RECOVERED_CLOCK:
+			bitPos = 0;
+			break;
+		case GT_SECONDARY_RECOVERED_CLOCK:
+			bitPos = 4;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0xB;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*clkSel = (GT_U32)(opData.ptpData >> bitPos) & 0x7;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbSetRecClkSel
+*
+* DESCRIPTION:
+*		Synchronous Ethernet Recovered Clock Select.
+*		This field indicate the internal PHY number whose recovered clock will
+*		be presented on the SE_RCLK0 or SE_RCLK1 pin depending on the recClk selection.
+*
+* INPUTS:
+*		recClk	- GT_AVB_RECOVERED_CLOCK type
+*		clkSel	- recovered clock selection (should be less than 8)
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetRecClkSel
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_AVB_RECOVERED_CLOCK	recClk,
+	IN  GT_U32		clkSel
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U16		bitPos;
+
+	DBG_INFO(("gavbSetRecClkSel Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	if (clkSel > 0x7)
+		return GT_BAD_PARAM;
+
+	switch (recClk)
+	{
+		case GT_PRIMARY_RECOVERED_CLOCK:
+			bitPos = 0;
+			break;
+		case GT_SECONDARY_RECOVERED_CLOCK:
+			bitPos = 4;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0xB;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= ~(0x7 << bitPos);
+	opData.ptpData |= clkSel << bitPos;
+
+	op = PTP_WRITE_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbGetAvbOuiBytes
+*
+* DESCRIPTION:
+*		AVB OUI Limit Filter bytes(0 ~ 2).
+*		When all three of the AvbOui Bytes are zero, normal frame processing occurs.
+*		When any of the three AvbOui Bytes are non-zero, all AVB frames must have a
+*		destination address whose 1st three bytes of the DA match these three 
+*		AvbOui Bytes or the frame will be filtered.
+*
+* INPUTS:
+* 		None
+*
+* OUTPUTS:
+*		ouiBytes	- 3 bytes of OUI field in Ethernet address format
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbOuiBytes
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*obiBytes
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gavbGetAvbOuiBytes Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0xC;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	obiBytes[0] = (GT_U8)((opData.ptpData >> 8) & 0xFF);
+	obiBytes[1] = (GT_U8)(opData.ptpData & 0xFF);
+
+	opData.ptpAddr = 0xD;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	obiBytes[2] = (GT_U8)((opData.ptpData >> 8) & 0xFF);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gavbSetAvbOuiBytes
+*
+* DESCRIPTION:
+*		AVB OUI Limit Filter bytes(0 ~ 2).
+*		When all three of the AvbOui Bytes are zero, normal frame processing occurs.
+*		When any of the three AvbOui Bytes are non-zero, all AVB frames must have a
+*		destination address whose 1st three bytes of the DA match these three 
+*		AvbOui Bytes or the frame will be filtered.
+*
+* INPUTS:
+*		ouiBytes	- 3 bytes of OUI field in Ethernet address format
+*
+* OUTPUTS:
+* 		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbOuiBytes
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U8		*obiBytes
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gavbSetAvbOuiBytes Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = 0xF;	/* Global register */
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0xC;
+
+	opData.ptpData = (obiBytes[0] << 8) | obiBytes[1];
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpAddr = 0xD;
+	opData.ptpData = (obiBytes[2] << 8);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbGetAvbMode
+*
+* DESCRIPTION:
+*		Port's AVB Mode.
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		mode	- GT_AVB_MODE type
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbMode
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_AVB_MODE	*mode
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gavbGetAvbMode Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	*mode = (GT_AVB_MODE)((opData.ptpData >> 14) & 0x3);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbSetAvbMode
+*
+* DESCRIPTION:
+*		Port's AVB Mode.
+*
+* INPUTS:
+*		port	- the logical port number
+*		mode	- GT_AVB_MODE type
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbMode
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_AVB_MODE	mode
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gavbSetAvbMode Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= ~(0x3 << 14);
+	opData.ptpData |= (mode << 14);
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading DisPTP.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gavbGetAvbOverride
+*
+* DESCRIPTION:
+*		AVB Override.
+*		When disabled, normal frame processing occurs.
+*		When enabled, the egress portion of this port is considered AVB even if 
+*		the ingress portion is not.
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbOverride
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gavbGetAvbOverride Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	*en = (opData.ptpData >> 13) & 0x1;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbSetAvbOverride
+*
+* DESCRIPTION:
+*		AVB Override.
+*		When disabled, normal frame processing occurs.
+*		When enabled, the egress portion of this port is considered AVB even if 
+*		the ingress portion is not.
+*
+* INPUTS:
+*		port	- the logical port number
+*		en		- GT_TRUE to enable, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbOverride
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gavbSetAvbOverride Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	if (en)
+		opData.ptpData |= (0x1 << 13);
+	else
+		opData.ptpData &= ~(0x1 << 13);
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbGetFilterBadAvb
+*
+* DESCRIPTION:
+*		Filter Bad AVB frames.
+*		When disabled, normal frame processing occurs.
+*		When enabled, frames that are considered Bad AVB frames are filtered.
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetFilterBadAvb
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gavbGetFilterBadAvb Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	*en = (opData.ptpData >> 12) & 0x1;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbSetFilterBadAvb
+*
+* DESCRIPTION:
+*		Filter Bad AVB frames.
+*		When disabled, normal frame processing occurs.
+*		When enabled, frames that are considered Bad AVB frames are filtered.
+*
+* INPUTS:
+*		port	- the logical port number
+*		en		- GT_TRUE to enable, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetFilterBadAvb
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gavbSetFilterBadAvb Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	if (en)
+		opData.ptpData |= (0x1 << 12);
+	else
+		opData.ptpData &= ~(0x1 << 12);
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbGetAvbTunnel
+*
+* DESCRIPTION:
+*		AVB Tunnel.
+*		When disabled, normal frame processing occurs.
+*		When enabled, the port based VLAN Table masking, 802.1Q VLAN membership 
+*		masking and the Trunk Masking is bypassed for any frame entering this port
+*		that is considered AVB by DA. This includes unicast as well as multicast
+*		frame
+*
+* INPUTS:
+*		port	- the logical port number
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbTunnel
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gavbGetAvbTunnel Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	*en = (opData.ptpData >> 11) & 0x1;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbSetAvbTunnel
+*
+* DESCRIPTION:
+*		AVB Tunnel.
+*		When disabled, normal frame processing occurs.
+*		When enabled, the port based VLAN Table masking, 802.1Q VLAN membership 
+*		masking and the Trunk Masking is bypassed for any frame entering this port
+*		that is considered AVB by DA. This includes unicast as well as multicast
+*		frame
+*
+* INPUTS:
+*		port	- the logical port number
+*		en		- GT_TRUE to enable, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbTunnel
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8          hwPort;         /* the physical port number     */
+
+	DBG_INFO(("GT_STATUS gavbGetAvbTunnel Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	if (en)
+		opData.ptpData |= (0x1 << 11);
+	else
+		opData.ptpData &= ~(0x1 << 11);
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gavbGetAvbFramePolicy
+*
+* DESCRIPTION:
+*		AVB Hi or Lo frame policy mapping.
+*		Supported policies are defined in GT_AVB_FRAME_POLICY.
+*			
+* INPUTS:
+*		port	- the logical port number
+*		fType	- GT_AVB_FRAME_TYPE 
+*
+* OUTPUTS:
+*		policy	- GT_AVB_FRAME_POLICY
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbGetAvbFramePolicy
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN	GT_AVB_FRAME_TYPE	fType,
+	OUT GT_AVB_FRAME_POLICY		*policy
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8 		hwPort;         /* the physical port number     */
+	GT_U16		bitPos;
+
+	DBG_INFO(("gavbGetAvbFramePolicy Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	switch (fType)
+	{
+		case AVB_HI_FRAME:
+			bitPos = 2;
+			break;
+		case AVB_LO_FRAME:
+			bitPos = 0;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	*policy = (opData.ptpData >> bitPos) & 0x3;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gavbSetAvbFramePolicy
+*
+* DESCRIPTION:
+*		AVB Hi or Lo frame policy mapping.
+*		Supported policies are defined in GT_AVB_FRAME_POLICY.
+*
+* INPUTS:
+*		port	- the logical port number
+*		fType	- GT_AVB_FRAME_TYPE 
+*		policy	- GT_AVB_FRAME_POLICY
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+* 		GT_OK      - on success
+* 		GT_FAIL    - on error
+* 		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+* 		None
+*
+*******************************************************************************/
+GT_STATUS gavbSetAvbFramePolicy
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN	GT_AVB_FRAME_TYPE	fType,
+	IN  GT_AVB_FRAME_POLICY		policy
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U8 		hwPort;         /* the physical port number     */
+	GT_U16		bitPos;
+
+	DBG_INFO(("gavbSetAvbFramePolicy Called.\n"));
+
+#ifndef CONFIG_AVB_FPGA
+	/* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AVB_POLICY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+#endif
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort == GT_INVALID_PORT)
+		return GT_BAD_PARAM;
+
+	switch (fType)
+	{
+		case AVB_HI_FRAME:
+			bitPos = 2;
+			break;
+		case AVB_LO_FRAME:
+			bitPos = 0;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	opData.ptpBlock = 0x1;	/* AVB Policy register space */
+
+	opData.ptpPort = (GT_U16)hwPort;
+	op = PTP_READ_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	opData.ptpData &= ~(0x3 << bitPos);
+	opData.ptpData |= (policy & 0x3) << bitPos;
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpAddr = 0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed AVB operation.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+
+/****************************************************************************/
+/* Internal functions.                                                  */
+/****************************************************************************/
+
+/*******************************************************************************
+* ptpOperationPerform
+*
+* DESCRIPTION:
+*       This function accesses PTP Command Register and Data Register.
+*
+* INPUTS:
+*       ptpOp      - The stats operation bits to be written into the stats
+*                    operation register.
+*
+* OUTPUTS:
+*       ptpData    - points to the data storage that the operation requires.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+static GT_STATUS ptpOperationPerform
+(
+    IN    GT_QD_DEV 			*dev,
+    IN    GT_PTP_OPERATION		ptpOp,
+    INOUT GT_PTP_OP_DATA		*opData
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+	GT_U32 			i;
+
+#ifdef CONFIG_AVB_FPGA
+	GT_U32 			tmpData;
+#endif
+
+    gtSemTake(dev,dev->ptpRegsSem,OS_WAIT_FOREVER);
+
+    /* Wait until the ptp in ready. */
+    data = 1;
+    while(data == 1)
+    {
+#ifndef CONFIG_AVB_FPGA
+        retVal = hwGetGlobal2RegField(dev,QD_REG_PTP_COMMAND,15,1,&data);
+#else
+        retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,&tmpData);
+		data = (GT_U16)tmpData;
+		data = (data >> 15) & 0x1;
+#endif
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->ptpRegsSem);
+            return retVal;
+        }
+    }
+
+    /* Set the PTP Operation register */
+	switch (ptpOp)
+	{
+		case PTP_WRITE_DATA:
+			data = (GT_U16)opData->ptpData;
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PTP_DATA,data);
+#else
+			tmpData = (GT_U32)data;
+	        retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_DATA,tmpData);
+#endif
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+	        }
+
+			data = (GT_U16)((1 << 15) | (PTP_WRITE_DATA << 12) | 
+					(opData->ptpPort << 8)	|
+					(opData->ptpBlock << 5)	|
+					(opData->ptpAddr & 0x1F));
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PTP_COMMAND,data);
+#else
+			tmpData = (GT_U32)data;
+	        retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,tmpData);
+#endif
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+	        }
+			break;
+
+		case PTP_READ_DATA:
+			data = (GT_U16)((1 << 15) | (PTP_READ_DATA << 12) | 
+					(opData->ptpPort << 8)	|
+					(opData->ptpBlock << 5)	|
+					(opData->ptpAddr & 0x1F));
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PTP_COMMAND,data);
+#else
+			tmpData = (GT_U32)data;
+	        retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,tmpData);
+#endif
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+	        }
+
+		    data = 1;
+		    while(data == 1)
+		    {
+#ifndef CONFIG_AVB_FPGA
+		        retVal = hwGetGlobal2RegField(dev,QD_REG_PTP_COMMAND,15,1,&data);
+#else
+        		retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,&tmpData);
+				data = (GT_U32)tmpData;
+				data = (data >> 15) & 0x1;
+#endif
+		        if(retVal != GT_OK)
+		        {
+		            gtSemGive(dev,dev->ptpRegsSem);
+		            return retVal;
+        		}
+		    }
+
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwReadGlobal2Reg(dev,QD_REG_PTP_DATA,&data);
+#else
+	        retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_DATA,&tmpData);
+			data = (GT_U32)tmpData;
+#endif
+			opData->ptpData = (GT_U32)data;
+		    gtSemGive(dev,dev->ptpRegsSem);
+		    return retVal;
+
+		case PTP_READ_MULTIPLE_DATA:
+			data = (GT_U16)((1 << 15) | (PTP_READ_MULTIPLE_DATA << 12) | 
+					(opData->ptpPort << 8)	|
+					(opData->ptpBlock << 5)	|
+					(opData->ptpAddr & 0x1F));
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PTP_COMMAND,data);
+#else
+			tmpData = (GT_U32)data;
+	        retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,tmpData);
+#endif
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+	        }
+
+		    data = 1;
+		    while(data == 1)
+		    {
+#ifndef CONFIG_AVB_FPGA
+		        retVal = hwGetGlobal2RegField(dev,QD_REG_PTP_COMMAND,15,1,&data);
+#else
+        		retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,&tmpData);
+				data = (GT_U32)tmpData;
+				data = (data >> 15) & 0x1;
+#endif
+		        if(retVal != GT_OK)
+		        {
+		            gtSemGive(dev,dev->ptpRegsSem);
+		            return retVal;
+        		}
+		    }
+
+			for(i=0; i<opData->nData; i++)
+			{
+#ifndef CONFIG_AVB_FPGA
+				retVal = hwReadGlobal2Reg(dev,QD_REG_PTP_DATA,&data);
+#else
+		        retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_DATA,&tmpData);
+				data = (GT_U32)tmpData;
+#endif
+				opData->ptpMultiData[i] = (GT_U32)data;
+	    	    if(retVal != GT_OK)
+    	    	{
+        	    	gtSemGive(dev,dev->ptpRegsSem);
+	            	return retVal;
+		        }
+			}
+
+		    gtSemGive(dev,dev->ptpRegsSem);
+		    return retVal;
+
+		case PTP_READ_TIMESTAMP_DATA:
+			data = (GT_U16)((1 << 15) | (PTP_READ_MULTIPLE_DATA << 12) | 
+					(opData->ptpPort << 8)	|
+					(opData->ptpBlock << 5)	|
+					(opData->ptpAddr & 0x1F));
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PTP_COMMAND,data);
+#else
+			tmpData = (GT_U32)data;
+	        retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,tmpData);
+#endif
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+	        }
+
+		    data = 1;
+		    while(data == 1)
+		    {
+#ifndef CONFIG_AVB_FPGA
+		        retVal = hwGetGlobal2RegField(dev,QD_REG_PTP_COMMAND,15,1,&data);
+#else
+        		retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,&tmpData);
+				data = (GT_U32)tmpData;
+				data = (data >> 15) & 0x1;
+#endif
+		        if(retVal != GT_OK)
+		        {
+		            gtSemGive(dev,dev->ptpRegsSem);
+		            return retVal;
+        		}
+		    }
+
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwReadGlobal2Reg(dev,QD_REG_PTP_DATA,&data);
+#else
+	        retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_DATA,&tmpData);
+			data = (GT_U32)tmpData;
+#endif
+			opData->ptpMultiData[0] = (GT_U32)data;
+    	    if(retVal != GT_OK)
+   	    	{
+       	    	gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+	        }
+
+			if (!(data & 0x1))
+			{
+				/* valid bit is not set */
+       	    	gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+			}
+
+			for(i=1; i<opData->nData; i++)
+			{
+#ifndef CONFIG_AVB_FPGA
+				retVal = hwReadGlobal2Reg(dev,QD_REG_PTP_DATA,&data);
+#else
+		        retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_DATA,&tmpData);
+				data = (GT_U32)tmpData;
+#endif
+				opData->ptpMultiData[i] = (GT_U32)data;
+	    	    if(retVal != GT_OK)
+    	    	{
+        	    	gtSemGive(dev,dev->ptpRegsSem);
+	            	return retVal;
+		        }
+			}
+
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PTP_DATA,0);
+#else
+	        retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_DATA,0);
+#endif
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+	        }
+
+			data = (GT_U16)((1 << 15) | (PTP_WRITE_DATA << 12) | 
+					(opData->ptpPort << 8)	|
+					(opData->ptpBlock << 5)	|
+					(opData->ptpAddr & 0x1F));
+#ifndef CONFIG_AVB_FPGA
+			retVal = hwWriteGlobal2Reg(dev,QD_REG_PTP_COMMAND,data);
+#else
+			tmpData = (GT_U32)data;
+	        retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,tmpData);
+#endif
+	        if(retVal != GT_OK)
+    	    {
+        	    gtSemGive(dev,dev->ptpRegsSem);
+            	return retVal;
+	        }
+
+
+		    gtSemGive(dev,dev->ptpRegsSem);
+			break;
+
+		default:
+			
+			gtSemGive(dev,dev->ptpRegsSem);
+			return GT_FAIL;
+	}
+
+    /* Wait until the ptp is ready. */
+    data = 1;
+    while(data == 1)
+    {
+#ifndef CONFIG_AVB_FPGA
+        retVal = hwGetGlobal2RegField(dev,QD_REG_PTP_COMMAND,15,1,&data);
+#else
+        retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_COMMAND,&tmpData);
+		data = (GT_U16)tmpData;
+		data = (data >> 15) & 0x1;
+#endif
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->ptpRegsSem);
+            return retVal;
+        }
+    }
+
+    gtSemGive(dev,dev->ptpRegsSem);
+    return retVal;
+}
+
+
+#ifdef CONFIG_AVB_FPGA
+
+
+/*******************************************************************************
+* gptpGetFPGAIntStatus
+*
+* DESCRIPTION:
+*       This routine gets interrupt status of PTP logic.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		ptpInt	- PTP Int Status
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetFPGAIntStatus
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32		*ptpInt
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpGetPTPIntStatus Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_INT_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	*ptpInt = (GT_U32)data & 0x1;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpSetFPGAIntStatus
+*
+* DESCRIPTION:
+*       This routine sets interrupt status of PTP logic.
+*
+* INPUTS:
+*	ptpInt	- PTP Int Status
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetFPGAIntStatus
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U32	ptpInt
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpSetPTPIntStatus Called.\n"));
+
+	data = ptpInt?1:0;
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_INT_OFFSET,ptpInt);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gptpSetFPGAIntEn
+*
+* DESCRIPTION:
+*       This routine enables PTP interrupt.
+*
+* INPUTS:
+*		ptpInt	- PTP Int Status (1 to enable, 0 to disable)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetFPGAIntEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32		ptpInt
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpGetPTPIntEn Called.\n"));
+
+	data = (ptpInt == 0)?0:1;
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_INTEN_OFFSET,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpGetClockSource
+*
+* DESCRIPTION:
+*       This routine gets PTP Clock source setup.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		clkSrc	- PTP clock source (A/D Device or FPGA)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetClockSource
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_CLOCK_SRC 	*clkSrc
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpGetClockSource Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_SRC_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	*clkSrc = (GT_PTP_CLOCK_SRC)(data & 0x1);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpSetClockSource
+*
+* DESCRIPTION:
+*       This routine sets PTP Clock source setup.
+*
+* INPUTS:
+*		clkSrc	- PTP clock source (A/D Device or FPGA)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetClockSource
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_CLOCK_SRC 	clkSrc
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpSetClockSource Called.\n"));
+
+	data = (GT_U32)clkSrc;
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_SRC_OFFSET,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpGetP9Mode
+*
+* DESCRIPTION:
+*       This routine gets Port 9 Mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		mode - Port 9 mode (GT_PTP_P9_MODE enum type)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetP9Mode
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_P9_MODE 	*mode
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpGetP9Mode Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_P9_MODE_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	if (data & 0x1)
+	{
+		switch (data & 0x6)
+		{
+			case 0:
+				*mode = PTP_P9_MODE_GMII;
+				break;
+			case 2:
+				*mode = PTP_P9_MODE_MII;
+				break;
+			case 4:
+				*mode = PTP_P9_MODE_MII_CONNECTOR;
+				break;
+			default:
+				return GT_BAD_PARAM;
+		}
+	}
+	else
+	{
+		*mode = PTP_P9_MODE_JUMPER;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpSetP9Mode
+*
+* DESCRIPTION:
+*       This routine sets Port 9 Mode.
+*
+* INPUTS:
+*		mode - Port 9 mode (GT_PTP_P9_MODE enum type)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetP9Mode
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_P9_MODE 	mode
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpSetP9Mode Called.\n"));
+
+	switch (mode)
+	{
+		case PTP_P9_MODE_GMII:
+			data = 1;
+			break;
+		case PTP_P9_MODE_MII:
+			data = 3;
+			break;
+		case PTP_P9_MODE_MII_CONNECTOR:
+			data = 5;
+			break;
+		case PTP_P9_MODE_JUMPER:
+			data = 0;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_P9_MODE_OFFSET,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpReset
+*
+* DESCRIPTION:
+*       This routine performs software reset for PTP logic.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpReset
+(
+	IN  GT_QD_DEV 	*dev
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpReset Called.\n"));
+
+	data = 1;
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_RESET_OFFSET,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetCycleAdjustEn
+*
+* DESCRIPTION:
+*       This routine checks if PTP Duty Cycle Adjustment is enabled.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		adjEn	- GT_TRUE if enabled, GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetCycleAdjustEn
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*adjEn
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpGetCycleAdjustEn Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_CTRL_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	*adjEn = (data & 0x2)?GT_TRUE:GT_FALSE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpSetCycleAdjustEn
+*
+* DESCRIPTION:
+*       This routine enables/disables PTP Duty Cycle Adjustment.
+*
+* INPUTS:
+*		adjEn	- GT_TRUE to enable, GT_FALSE to disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetCycleAdjustEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		adjEn
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpGetCycleAdjustEn Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_CTRL_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	if (adjEn == GT_FALSE)
+		data &= ~0x3;	/* clear both Enable bit and Valid bit */
+	else
+		data |= 0x2;
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_CTRL_OFFSET,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetCycleAdjust
+*
+* DESCRIPTION:
+*       This routine gets clock duty cycle adjustment value.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		adj	- adjustment value (GT_PTP_CLOCK_ADJUSTMENT structure)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetCycleAdjust
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_PTP_CLOCK_ADJUSTMENT	*adj
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpGetCycleAdjust Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_CTRL_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	adj->adjSign = (data & 0x4)?GT_PTP_SIGN_PLUS:GT_PTP_SIGN_NEGATIVE;
+	adj->cycleStep = (data >> 3) & 0x7;
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CYCLE_INTERVAL_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	adj->cycleInterval = data;
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CYCLE_ADJ_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	adj->cycleAdjust = data;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gptpSetCycleAdjust
+*
+* DESCRIPTION:
+*       This routine sets clock duty cycle adjustment value.
+*
+* INPUTS:
+*		adj	- adjustment value (GT_PTP_CLOCK_ADJUSTMENT structure)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetCycleAdjust
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PTP_CLOCK_ADJUSTMENT	*adj
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data, data1;
+
+	DBG_INFO(("gptpSetCycleAdjust Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_CTRL_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	data &= ~0x1;	/* clear Valid bit */
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_CTRL_OFFSET,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* Setup the Cycle Interval */
+	data1 = adj->cycleInterval & 0xFFFF;
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CYCLE_INTERVAL_OFFSET,data1);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* Setup the Cycle Adjustment */
+	data1 = adj->cycleAdjust & 0xFFFF;
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CYCLE_ADJ_OFFSET,data1);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* clear Sign bit and Cycle Step bits on QD_REG_PTP_CLK_CTRL_OFFSET value */
+	data &= ~0x3C;
+
+	switch (adj->adjSign)
+	{
+		case GT_PTP_SIGN_PLUS:
+			data |= 0x4;
+			break;
+			
+		case GT_PTP_SIGN_NEGATIVE:
+			break;
+
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	data |= ((adj->cycleStep & 0x7) << 3);	/* setup Step bits */
+	data |= 0x1;							/* set Valid bit */
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_CLK_CTRL_OFFSET,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetPLLEn
+*
+* DESCRIPTION:
+*       This routine checks if PLL is enabled.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en		- GT_TRUE if enabled, GT_FALSE otherwise
+*		freqSel	- PLL Frequency Selection (default 0x3 - 22.368MHz)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       PLL Frequence selection is based on the Clock Recovery PLL device.
+*		IDT MK1575-01 is the default PLL device.
+*
+*******************************************************************************/
+GT_STATUS gptpGetPLLEn
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en,
+	OUT GT_U32		*freqSel
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpGetPLLEn Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_PLL_CTRL_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	*en = (data & 0x1)?GT_TRUE:GT_FALSE;
+
+	*freqSel = (data >> 1) & 0x7;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpSetPLLEn
+*
+* DESCRIPTION:
+*       This routine enables/disables PLL device.
+*
+* INPUTS:
+*		en		- GT_TRUE to enable, GT_FALSE to disable
+*		freqSel	- PLL Frequency Selection (default 0x3 - 22.368MHz)
+*				  Meaningful only when enabling PLL device
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       PLL Frequence selection is based on the Clock Recovery PLL device.
+*		IDT MK1575-01 is the default PLL device.
+*
+*******************************************************************************/
+GT_STATUS gptpSetPLLEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en,
+	IN  GT_U32		freqSel
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32				data;
+
+	DBG_INFO(("gptpSetPPLEn Called.\n"));
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_PLL_CTRL_OFFSET,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	if(en == GT_FALSE)
+	{
+		data |= 0x1;
+	}
+	else
+	{
+		data &= ~0x1;
+		data |= (freqSel & 0x7) << 1;
+	}
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,QD_REG_PTP_PLL_CTRL_OFFSET,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gptpGetDDSReg
+*
+* DESCRIPTION:
+*       This routine gets DDS register data.
+*
+* INPUTS:
+*	ddsReg	- DDS Register
+*
+* OUTPUTS:
+*	ddsData	- register data
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpGetDDSReg
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32	ddsReg,
+	OUT GT_U32	*ddsData
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32			data;
+	GT_U32			timeout = 0x100000;
+
+	DBG_INFO(("gptpGetDDSReg Called.\n"));
+
+	if (ddsReg > 0x3f)
+		return GT_BAD_PARAM;
+	do 
+	{
+		retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,12,&data);
+		if (retVal != GT_OK)
+			return retVal;
+		timeout--;
+		if (timeout == 0)
+			return GT_FAIL;
+	} while (data & 0x8000);
+
+	data = 0x8000 | 0x4000 | (ddsReg << 8);
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,12,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,12,&data);
+	if (retVal != GT_OK)
+		return retVal;
+
+	*ddsData = data & 0xFF;
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,12,0);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gptpSetDDSReg
+*
+* DESCRIPTION:
+*       This routine sets DDS register data.
+*	DDS register data written by this API are not affected until gptpUpdateDDSReg API is called.
+*
+* INPUTS:
+*	ddsReg	- DDS Register
+*	ddsData	- register data
+*
+* OUTPUTS:
+*	none
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetDDSReg
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32	ddsReg,
+	IN  GT_U32	ddsData
+)
+{
+	GT_STATUS       	retVal;
+	GT_U32			data;
+	GT_U32			timeout = 0x100000;
+
+	DBG_INFO(("gptpSetDDSReg Called.\n"));
+
+	if ((ddsReg > 0x3f) || (ddsData > 0xff))
+		return GT_BAD_PARAM;
+
+	do 
+	{
+		retVal = AVB_FPGA_READ_REG(dev,AVB_SMI_ADDR,12,&data);
+		if (retVal != GT_OK)
+			return retVal;
+		timeout--;
+		if (timeout == 0)
+			return GT_FAIL;
+	} while (data & 0x8000);
+
+	data = 0x8000 | (ddsReg << 8) | (ddsData);
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,12,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,12,0);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gptpUpdateDDSReg
+*
+* DESCRIPTION:
+*       This routine updates DDS register data.
+*	DDS register data written by gptpSetDDSReg are not affected until this API is called.
+*
+* INPUTS:
+*	none
+*
+* OUTPUTS:
+*	none
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpUpdateDDSReg
+(
+	IN  GT_QD_DEV 	*dev
+)
+{
+	GT_STATUS       	retVal;
+
+	DBG_INFO(("gptpUpdateDDSReg Called.\n"));
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,13,0x0);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,13,0x1);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gptpSetADFReg
+*
+* DESCRIPTION:
+*       This routine sets ADF4156 register data.
+*
+* INPUTS:
+*	adfData	- register data
+*
+* OUTPUTS:
+*	none
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gptpSetADFReg
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U32	adfData
+)
+{
+	GT_STATUS       	retVal;
+
+	DBG_INFO(("gptpSetADFReg Called.\n"));
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,14,(adfData & 0xFFFF));
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = AVB_FPGA_WRITE_REG(dev,AVB_SMI_ADDR,15,((adfData>>16) & 0xFFFF));
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+#endif
+
+
+/******************************************************************************
+*
+*
+*******************************************************************************/
+/* Amber QAV API */
+
+/*******************************************************************************
+* gqavSetPortQpriXQTSToken
+*
+* DESCRIPTION:
+*       This routine set Priority Queue 0-3 time slot tokens on a port.
+*		The setting value is number of tokens that need to be subtracted at each 
+*		QTS interval boundary.
+*
+* INPUTS:
+*		queue	 - 0 - 3
+*		qtsToken - number of tokens.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetPortQpriXQTSToken
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_U8		queue,
+	IN  GT_U16		qtsToken
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32			hwPort;
+
+	DBG_INFO(("gqavSetPortQpriXQTSToken Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if queue is beyond range */
+	if (queue>0x3)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+    /* check if qtsToken is beyond range */
+	if (qtsToken>0x7fff)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = queue*2;
+
+	opData.ptpPort = hwPort;
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData = qtsToken&0x7fff;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing QTS token for port %d queue %d.\n", port, queue));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetPortQpriXQTSToken
+*
+* DESCRIPTION:
+*       This routine get Priority Queue 0-3 time slot tokens on a port.
+*		The setting value is number of tokens that need to be subtracted at each 
+*		QTS interval boundary.
+*
+* INPUTS:
+*		queue - 0 - 3
+*
+* OUTPUTS:
+*		qtsToken - number of tokens
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetPortQpriXQTSToken
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_U8		queue,
+	OUT GT_U16		*qtsToken
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32			hwPort;
+
+	DBG_INFO(("gqavGetPortQpriXQTSToken Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if queue is beyond range */
+	if (queue>0x3)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+
+	opData.ptpAddr = queue*2;
+	opData.ptpPort = hwPort;
+
+	op = PTP_READ_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading QTS token for port %d queue %d.\n", port, queue));
+		return GT_FAIL;
+	}
+
+	*qtsToken =	(GT_U16)(opData.ptpData&0x7fff);
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gqavSetPortQpriXBurstBytes
+*
+* DESCRIPTION:
+*       This routine set Priority Queue 0-3 Burst Bytes on a port.
+*		This value specifies the number of credits in bytes that can be 
+*		accumulated when the queue is blocked from sending out a frame due to 
+*		higher priority queue frames being sent out.
+*
+* INPUTS:
+*		queue - 0 - 3
+*		burst - number of credits in bytes .
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetPortQpriXBurstBytes
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_U8		queue,
+	IN  GT_U16		burst
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32			hwPort;
+
+	DBG_INFO(("gqavSetPortQpriXBurstBytes Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if queue is beyond range */
+	if (queue>0x3)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+    /* check if burst is beyond range */
+	if (burst>0x7fff)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = queue*2+1;
+
+	opData.ptpPort = hwPort;
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData = burst&0x7fff;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Burst bytes for port %d queue %d.\n", port, queue));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetPortQpriXBurstBytes
+*
+* DESCRIPTION:
+*       This routine get Priority Queue 0-3 Burst Bytes on a port.
+*		This value specifies the number of credits in bytes that can be 
+*		accumulated when the queue is blocked from sending out a frame due to 
+*		higher priority queue frames being sent out.
+*
+* INPUTS:
+*		queue - 0 - 3
+*
+* OUTPUTS:
+*		burst - number of credits in bytes .
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetPortQpriXBurstBytes
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_U8		queue,
+	OUT GT_U16		*burst
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32			hwPort;
+
+	DBG_INFO(("gqavgetPortQpriXBurstBytes Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if queue is beyond range */
+	if (queue>0x3)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+
+	opData.ptpAddr = queue*2+1;
+	opData.ptpPort = hwPort;
+
+	op = PTP_READ_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading Burst bytes for port %d queue %d.\n", port, queue));
+		return GT_FAIL;
+	}
+
+	*burst = (GT_U16)opData.ptpData&0x7fff;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gqavSetPortQavEnable
+*
+* DESCRIPTION:
+*       This routine set QAV enable status on a port.
+*
+* INPUTS:
+*		en - GT_TRUE: QAV enable, GT_FALSE: QAV disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetPortQavEnable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32			hwPort;
+
+	DBG_INFO(("gqavSetPortQavEnable Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 8;
+
+	opData.ptpPort = hwPort;
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData = (en==GT_TRUE)?0x8000:0;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing QAV enable for port %d.\n", port));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetPortQavEnable
+*
+* DESCRIPTION:
+*       This routine get QAV enable status on a port.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en - GT_TRUE: QAV enable, GT_FALSE: QAV disable
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetPortQavEnable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN	GT_LPORT	port,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+	GT_U32			hwPort;
+
+	DBG_INFO(("gqavGetPortQavEnable Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = (GT_U32)GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 8;
+
+	opData.ptpPort = hwPort;
+
+	op = PTP_READ_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed reading QAV enable for port %d.\n", port));
+		return GT_FAIL;
+	}
+
+	*en = ((opData.ptpData&0x8000)==0)?GT_FALSE:GT_TRUE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************/
+/* QAV Global resters processing */
+/*******************************************************************************
+* gqavSetGlobalAdminMGMT
+*
+* DESCRIPTION:
+*       This routine set to accept Admit Management Frames always.
+*
+* INPUTS:
+*		en - GT_TRUE to set MGMT frame accepted always, 
+*			 GT_FALSE do not set MGMT frame accepted always
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalAdminMGMT
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalAdminMGMT Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 0;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading QAV global config admin MGMT.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0x8000;
+	if (en)
+		opData.ptpData |= 0x8000;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing QAV global config admin MGMT.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetGlobalAdminMGMT
+*
+* DESCRIPTION:
+*       This routine get setting of Admit Management Frames always.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to set MGMT frame accepted always, 
+*			 GT_FALSE do not set MGMT frame accepted always
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalAdminMGMT
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalAdminMGMT Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 0;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading QAV global config admin MGMT.\n"));
+		return GT_FAIL;
+	}
+
+	if (opData.ptpData&0x8000)
+	  *en = GT_TRUE;
+	else
+	  *en = GT_FALSE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gqavSetGlobalIsoPtrThreshold
+*
+* DESCRIPTION:
+*       This routine set Global Isochronous Queue Pointer Threshold.
+*		This field indicates the total number of isochronous pointers 
+*		that are reserved for isochronous streams. The value is expected to be 
+*		computed in SRP software and programmed into hardware based on the total 
+*		aggregate isochronous streams configured to go through this device..
+*
+* INPUTS:
+*		isoPtrs -  total number of isochronous pointers 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoPtrThreshold
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U16		isoPtrs
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalIsoPtrThreshold Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if isoPtrs is beyond range */
+	if (isoPtrs>0x3ff)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 0;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading QAV global config Isochronous Queue Pointer Threshold.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0x3ff;
+	opData.ptpData |= isoPtrs;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing QAV global config Isochronous Queue Pointer Threshold.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gqavGetGlobalIsoPtrThreshold
+*
+* DESCRIPTION:
+*       This routine get Global Isochronous Queue Pointer Threshold.
+*		This field indicates the total number of isochronous pointers 
+*		that are reserved for isochronous streams. The value is expected to be 
+*		computed in SRP software and programmed into hardware based on the total 
+*		aggregate isochronous streams configured to go through this device..
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		isoPtrs -  total number of isochronous pointers 
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoPtrThreshold
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U16		*isoPtrs
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalIsoPtrThreshold Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 0;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous Queue Pointer Threshold.\n"));
+		return GT_FAIL;
+	}
+
+	*isoPtrs = (GT_U16)opData.ptpData&0x3ff;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gqavSetGlobalDisQSD4MGMT
+*
+* DESCRIPTION:
+*       This routine set Disable Queue Scheduler Delays for Management frames..
+*
+* INPUTS:
+*		en - GT_TRUE, it indicates to the Queue Controller to disable applying Queue
+*		Scheduler Delays and the corresponding rate regulator does not account
+*		for MGMT frames through this queue.
+*			 GT_FALSE, the MGMT frames follow similar rate regulation and delay
+*		regulation envelope as specified for the isochronous queue that the
+*		MGMT frames are sharing with.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalDisQSD4MGMT
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalDisQSD4MGMT Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 3;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Disable Queue Scheduler Delay for MGMT frames.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0x4000;
+	if (en==GT_TRUE)
+		opData.ptpData |= 0x4000;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Disable Queue Scheduler Delay for MGMT frames.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetGlobalDisQSD4MGMT
+*
+* DESCRIPTION:
+*       This routine Get Disable Queue Scheduler Delays for Management frames..
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en - GT_TRUE, it indicates to the Queue Controller to disable applying Queue
+*		Scheduler Delays and the corresponding rate regulator does not account
+*		for MGMT frames through this queue.
+*			 GT_FALSE, the MGMT frames follow similar rate regulation and delay
+*		regulation envelope as specified for the isochronous queue that the
+*		MGMT frames are sharing with.
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalDisQSD4MGMT
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalDisQSD4MGMT Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 3;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Disable Queue Scheduler Delay for MGMT frames.\n"));
+		return GT_FAIL;
+	}
+
+	if (opData.ptpData&0x4000)
+	  *en = GT_TRUE;
+	else
+	  *en = GT_FALSE;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gqavSetGlobalInterrupt
+*
+* DESCRIPTION:
+*       This routine set QAV interrupt enable, The QAV interrypts include:
+*		 [GT_QAV_INT_ENABLE_ENQ_LMT_BIT]      # EnQ Limit Interrupt Enable 
+*		 [GT_QAV_INT_ENABLE_ISO_DEL_BIT]      # Iso Delay Interrupt Enable   
+*		 [GT_QAV_INT_ENABLE_ISO_DIS_BIT]      # Iso Discard Interrupt Enable 
+*		 [GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT]   # Iso Packet Memory Exceeded 
+*												  Interrupt Enable 
+*
+* INPUTS:
+*		intEn - [GT_QAV_INT_ENABLE_ENQ_LMT_BIT] OR  
+*				[GT_QAV_INT_ENABLE_ISO_DEL_BIT] OR    
+*				[GT_QAV_INT_ENABLE_ISO_DIS_BIT] OR  
+*				[GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT]   
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalInterrupt
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U16		intEn
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalInterrupt Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 8;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Interrupt enable status.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0xff;
+	opData.ptpData |= (intEn&0xff);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Interrupt enable status.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetGlobalInterrupt
+*
+* DESCRIPTION:
+*       This routine get QAV interrupt enable, The QAV interrypts include:
+*		 [GT_QAV_INT_STATUS_ISO_DEL_BIT]      # Iso Delay Interrupt Status   
+*		 [GT_QAV_INT_STATUS_ISO_DIS_BIT]      # Iso Discard Interrupt Status 
+*		 [GT_QAV_INT_STATUS_ISO_LIMIT_EX_BIT]   # Iso Packet Memory Exceeded 
+*												  Interrupt Status 
+*		 [GT_QAV_INT_ENABLE_ENQ_LMT_BIT]      # EnQ Limit Interrupt Enable 
+*		 [GT_QAV_INT_ENABLE_ISO_DEL_BIT]      # Iso Delay Interrupt Enable   
+*		 [GT_QAV_INT_ENABLE_ISO_DIS_BIT]      # Iso Discard Interrupt Enable 
+*		 [GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT]   # Iso Packet Memory Exceeded 
+*												  Interrupt Enable 
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+* INPUTS:
+*		intEn - [GT_QAV_INT_STATUS_ISO_DEL_BIT] OR     
+*				[GT_QAV_INT_STATUS_ISO_DIS_BIT] OR   
+*				[GT_QAV_INT_STATUS_ISO_LIMIT_EX_BIT] OR
+*				[GT_QAV_INT_ENABLE_ENQ_LMT_BIT] OR  
+*				[GT_QAV_INT_ENABLE_ISO_DEL_BIT] OR    
+*				[GT_QAV_INT_ENABLE_ISO_DIS_BIT] OR  
+*				[GT_QAV_INT_ENABLE_ISO_LIMIT_EX_BIT]   
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalInterrupt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U16		*intSt
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalInterrupt Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 8;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Interrupt status.\n"));
+		return GT_FAIL;
+	}
+
+	*intSt = (GT_U16)opData.ptpData;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetGlobalIsoInterruptPort
+*
+* DESCRIPTION:
+*       This routine get Isochronous interrupt port.
+*		This field indicates the port number for IsoDisInt or IsoLimitExInt 
+*		bits. Only one such interrupt condition can be detected by hardware at one 
+*		time. Once an interrupt bit has been set along with the IsoIntPort, the 
+*		software would have to come and clear the bits before hardware records 
+*		another interrupt event.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		port - port number for IsoDisInt or IsoLimitExInt bits.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoInterruptPort
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*port
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalIsoInterruptPort Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 9;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous interrupt port..\n"));
+		return GT_FAIL;
+	}
+
+	*port = (GT_U8)opData.ptpData&0xf;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gqavSetGlobalIsoDelayLmt
+*
+* DESCRIPTION:
+*       This routine set Isochronous queue delay Limit
+*		This field represents a per-port isochronous delay limit that 
+*		will be checked by the queue controller logic to ensure no isochronous 
+*		packets suffer more than this delay w.r.t to their eligibility time slot.
+*		This represents the number of Queue Time Slots. The interval for the QTS 
+*		can be configured using the register in Qav Global Configuration, Offset 0x2.
+*
+* INPUTS:
+*		limit - per-port isochronous delay limit.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoDelayLmt
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U8		limit
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalIsoDelayLmt Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 10;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous queue delay Limit.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0xff;
+	opData.ptpData |= (limit&0xff);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Isochronous queue delay Limit.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetGlobalIsoDelayLmt
+*
+* DESCRIPTION:
+*       This routine get Isochronous queue delay Limit
+*		This field represents a per-port isochronous delay limit that 
+*		will be checked by the queue controller logic to ensure no isochronous 
+*		packets suffer more than this delay w.r.t to their eligibility time slot.
+*		This represents the number of Queue Time Slots. The interval for the QTS 
+*		can be configured using the register in Qav Global Configuration, Offset 0x2.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		limit - per-port isochronous delay limit.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoDelayLmt
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*limit
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalIsoDelayLmt Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 10;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous queue delay Limit.\n"));
+		return GT_FAIL;
+	}
+
+	*limit = (GT_U8)(opData.ptpData)&0xff;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavSetGlobalIsoMonEn
+*
+* DESCRIPTION:
+*       This routine set Isochronous monitor enable
+*		Set 1: this bit enables the statistics gathering capabilities stated
+*		in PTP Global Status Registers Offset 0xD, 0xE and 0xF. Once enabled, the
+*		software is expected to program the IsoMonPort (PTP Global Status Offset
+*		0xD) indicating which port of the device does the software wants to monitor.
+*		Upon setting this bit, the hardware collects IsoHiDisCtr, IsoLoDisCtr and
+*		IsoSchMissCtr values for the port indicated by IsoMonPort till this bit is 
+*		set to a zero.
+*		Set 0: this bit disables the statistics gathering capabilities.
+*
+* INPUTS:
+*		en - [1]/[0].
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoMonEn
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalIsoMonEn Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 12;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous monitor enable.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0x8000;
+	if (en)
+		opData.ptpData |= 0x8000;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Isochronous monitor enable.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetGlobalIsoMonEn
+*
+* DESCRIPTION:
+*       This routine get Isochronous monitor enable
+*		Set 1: this bit enables the statistics gathering capabilities stated
+*		in PTP Global Status Registers Offset 0xD, 0xE and 0xF. Once enabled, the
+*		software is expected to program the IsoMonPort (PTP Global Status Offset
+*		0xD) indicating which port of the device does the software wants to monitor.
+*		Upon setting this bit, the hardware collects IsoHiDisCtr, IsoLoDisCtr and
+*		IsoSchMissCtr values for the port indicated by IsoMonPort till this bit is 
+*		set to a zero.
+*		Set 0: this bit disables the statistics gathering capabilities.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		en - [1]/[0].
+
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoMonEn
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_BOOL		*en
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalIsoMonEn Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 12;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous monitor enable.\n"));
+		return GT_FAIL;
+	}
+
+	if (opData.ptpData&0x8000)
+	  *en = 1;
+	else
+	  *en = 0;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavSetGlobalIsoMonPort
+*
+* DESCRIPTION:
+*       This routine set Isochronous monitoring port.
+*		This field is updated by software along with Iso Mon En bit 
+*		(Qav Global Status, offset 0xD) and it indicates the port number that 
+*		the software wants the hardware to start monitoring i.e., start updating 
+*		IsoHiDisCtr, IsoLoDisCtr and IsoSchMissCtr. The queue controller clears 
+*		the above stats when IsoMonPort is changed..
+*
+* INPUTS:
+*		port -  port number .
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoMonPort
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U16		port
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalIsoMonPort Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if port is beyond range */
+	if (port>0xf)
+    {
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 12;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous monitoring port.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0xf;
+	opData.ptpData |= port;
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Isochronous monitoring port.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gqavGetGlobalIsoMonPort
+*
+* DESCRIPTION:
+*       This routine get Isochronous monitoring port.
+*		This field is updated by software along with Iso Mon En bit 
+*		(Qav Global Status, offset 0xD) and it indicates the port number that 
+*		the software wants the hardware to start monitoring i.e., start updating 
+*		IsoHiDisCtr, IsoLoDisCtr and IsoSchMissCtr. The queue controller clears 
+*		the above stats when IsoMonPort is changed..
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		port -  port number .
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoMonPort
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U16		*port
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalIsoMonPort Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 12;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous monitoring port.\n"));
+		return GT_FAIL;
+	}
+
+	*port = (GT_U16)opData.ptpData&0xf;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavSetGlobalIsoHiDisCtr
+*
+* DESCRIPTION:
+*       This routine set Isochronous hi queue discard counter.
+*		This field is updated by hardware when instructed to do so by 
+*		enabling the IsoMonEn bit in Qav Global Status Register Offset 0xD. 
+*		This is an upcounter of number of isochronous hi packets discarded 
+*		by Queue Controller.
+*
+* INPUTS:
+*		disCtr - upcounter of number of isochronous hi packets discarded 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoHiDisCtr
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U8		disCtr
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalIsoHiDisCtr Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 13;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous hi queue discard counter..\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0xff00;
+	if (disCtr)
+		opData.ptpData |= (disCtr<<8);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Isochronous hi queue discard counter..\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetGlobalIsoHiDisCtr
+*
+* DESCRIPTION:
+*       This routine get Isochronous hi queue discard counter.
+*		This field is updated by hardware when instructed to do so by 
+*		enabling the IsoMonEn bit in Qav Global Status Register Offset 0xD. 
+*		This is an upcounter of number of isochronous hi packets discarded 
+*		by Queue Controller.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*		disCtr - upcounter of number of isochronous hi packets discarded 
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoHiDisCtr
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*disCtr
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalIsoHiDisCtr Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 13;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous hi queue discard counter.\n"));
+		return GT_FAIL;
+	}
+
+	*disCtr = (GT_U8)(opData.ptpData>>8)&0xff;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gqavSetGlobalIsoLoDisCtr
+*
+* DESCRIPTION:
+*       This routine set Isochronous Lo queue discard counter.
+*		This field is updated by hardware when instructed to do so by 
+*		enabling the IsoMonEn bit in Qav Global Status Register Offset 0xD. 
+*		This is an upcounter of number of isochronous lo packets discarded 
+*		by Queue Controller.
+*
+* INPUTS:
+*		disCtr - upcounter of number of isochronous lo packets discarded 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavSetGlobalIsoLoDisCtr
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_U8		disCtr
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavSetGlobalIsoLoDisCtr Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 13;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous lo queue discard counter.\n"));
+		return GT_FAIL;
+	}
+
+	op = PTP_WRITE_DATA;
+
+	opData.ptpData &= ~0xff;
+	opData.ptpData |= (disCtr&0xff);
+
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+        DBG_INFO(("Failed writing Isochronous lo queue discard counter.\n"));
+		return GT_FAIL;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gqavGetGlobalIsoLoDisCtr
+*
+* DESCRIPTION:
+*       This routine set Isochronous Lo queue discard counter.
+*		This field is updated by hardware when instructed to do so by 
+*		enabling the IsoMonEn bit in Qav Global Status Register Offset 0xD. 
+*		This is an upcounter of number of isochronous lo packets discarded 
+*		by Queue Controller.
+*
+* INPUTS:
+*		None
+*
+* OUTPUTS:
+*		disCtr - upcounter of number of isochronous lo packets discarded 
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM - if input parameters are beyond range.
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gqavGetGlobalIsoLoDisCtr
+(
+	IN  GT_QD_DEV 	*dev,
+	OUT GT_U8		*disCtr
+)
+{
+	GT_STATUS       	retVal;
+	GT_PTP_OPERATION	op;
+	GT_PTP_OP_DATA		opData;
+
+	DBG_INFO(("gqavGetGlobalIsoLoDisCtr Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAV))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	opData.ptpBlock = 0x2;	/* QAV register space */
+	opData.ptpAddr = 13;
+
+	opData.ptpPort = 0xF;
+
+	op = PTP_READ_DATA;
+	if((retVal = ptpOperationPerform(dev, op, &opData)) != GT_OK)
+	{
+		DBG_INFO(("Failed reading Isochronous lo queue discard counter.\n"));
+		return GT_FAIL;
+	}
+
+	*disCtr = (GT_U8)(opData.ptpData)&0xff;
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyCtrl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyCtrl.c
new file mode 100755
index 0000000..edec2c3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyCtrl.c
@@ -0,0 +1,3969 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPhyCtrl.h
+* 
+* DESCRIPTION:
+* API definitions for PHY control facility.
+*
+* DEPENDENCIES:
+* None.
+*
+* FILE REVISION NUMBER:
+* $Revision: 10 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvConfig.h>
+#include <gtDrvSwRegs.h>
+#include <gtVct.h>
+#include <gtSem.h>
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+/*
+ * This routine set Auto-Negotiation Ad Register for Fast Ethernet Phy
+*/
+static 
+GT_STATUS feSetAutoMode
+(
+	IN GT_QD_DEV *dev,
+	IN GT_U8 	 hwPort,
+	IN GT_PHY_INFO	 *phyInfo,
+	IN GT_PHY_AUTO_MODE mode
+)
+{
+    GT_U16 			u16Data;
+
+	GT_UNUSED_PARAM(phyInfo);
+
+    DBG_INFO(("feSetAutoMode Called.\n"));
+
+    if(hwReadPhyReg(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+   	    return GT_FAIL;
+	}
+
+	/* Mask out all auto mode related bits. */
+	u16Data &= ~QD_PHY_MODE_AUTO_AUTO;
+
+	switch(mode)
+	{
+		case SPEED_AUTO_DUPLEX_AUTO:
+				u16Data |= QD_PHY_MODE_AUTO_AUTO;
+				break;
+		case SPEED_100_DUPLEX_AUTO:
+				u16Data |= QD_PHY_MODE_100_AUTO;
+				break;
+		case SPEED_10_DUPLEX_AUTO:
+				u16Data |= QD_PHY_MODE_10_AUTO;
+				break;
+		case SPEED_AUTO_DUPLEX_FULL:
+				u16Data |= QD_PHY_MODE_AUTO_FULL;
+				break;
+		case SPEED_AUTO_DUPLEX_HALF:
+				u16Data |= QD_PHY_MODE_AUTO_HALF;
+				break;
+		case SPEED_100_DUPLEX_FULL:
+				u16Data |= QD_PHY_100_FULL;
+				break;
+		case SPEED_100_DUPLEX_HALF:
+				u16Data |= QD_PHY_100_HALF;
+				break;
+		case SPEED_10_DUPLEX_FULL:
+				u16Data |= QD_PHY_10_FULL;
+				break;
+		case SPEED_10_DUPLEX_HALF:
+				u16Data |= QD_PHY_10_HALF;
+				break;
+		default:
+	 	        DBG_INFO(("Unknown Auto Mode (%d)\n",mode));
+				return GT_BAD_PARAM;
+	}
+
+    /* Write to Phy AutoNegotiation Advertisement Register.  */
+    if(hwWritePhyReg(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data));
+   	    return GT_FAIL;
+	}
+
+	return GT_OK;
+}
+
+/*
+ * This routine get Auto-Negotiation Ad Register for Fast Ethernet Phy
+*/
+static 
+GT_STATUS feGetAutoMode
+(
+    IN  GT_QD_DEV        *dev,
+    IN  GT_U8            hwPort,
+    IN  GT_PHY_INFO      *phyInfo,
+    OUT GT_PHY_AUTO_MODE *mode
+)
+{
+    GT_U16  u16Data;
+
+    GT_UNUSED_PARAM(phyInfo);
+
+    DBG_INFO(("feGetAutoMode Called.\n"));
+
+    if(hwReadPhyReg(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,&u16Data) != GT_OK)
+    {
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+           return GT_FAIL;
+    }
+
+    /* Pick out all auto mode related bits. */
+    u16Data &= QD_PHY_MODE_AUTO_AUTO;
+
+    switch(u16Data)
+    {
+        case QD_PHY_MODE_10_HALF:
+                *mode = SPEED_10_DUPLEX_HALF;
+                break;
+        case QD_PHY_MODE_10_FULL:
+                *mode = SPEED_10_DUPLEX_FULL;
+                break;
+        case QD_PHY_MODE_100_HALF:
+                *mode = SPEED_100_DUPLEX_HALF;
+                break;
+        case QD_PHY_MODE_100_FULL:
+                *mode = SPEED_100_DUPLEX_FULL;
+                break;
+        case QD_PHY_MODE_AUTO_HALF:
+                *mode = SPEED_AUTO_DUPLEX_HALF;
+                break;
+        case QD_PHY_MODE_AUTO_FULL:
+                *mode = SPEED_AUTO_DUPLEX_FULL;
+                break;
+        case QD_PHY_MODE_10_AUTO:
+                *mode = SPEED_10_DUPLEX_AUTO;
+                break;
+        case QD_PHY_MODE_100_AUTO:
+                *mode = SPEED_100_DUPLEX_AUTO;
+                break;
+        case QD_PHY_MODE_AUTO_AUTO:
+                *mode = SPEED_AUTO_DUPLEX_AUTO;
+                break;
+        default:
+                DBG_INFO(("Unknown Auto Mode (%d)\n", u16Data));
+                *mode = SPEED_AUTO_DUPLEX_AUTO;
+                break;
+    }
+
+    return GT_OK;
+}
+
+/*
+ * This routine set Auto-Negotiation Ad Register for Copper
+*/
+static 
+GT_STATUS gigCopperSetAutoMode
+(
+	IN GT_QD_DEV *dev,
+	IN GT_U8 hwPort,
+	IN GT_PHY_INFO	 *phyInfo,
+	IN GT_PHY_AUTO_MODE mode
+)
+{
+    GT_U16 			u16Data,u16Data1;
+
+    DBG_INFO(("gigCopperSetAutoMode Called.\n"));
+
+    if(hwReadPagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+   	    return GT_FAIL;
+	}
+
+	/* Mask out all auto mode related bits. */
+	u16Data &= ~QD_PHY_MODE_AUTO_AUTO;
+
+    if(hwReadPagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_1000AD_REG,phyInfo->anyPage,&u16Data1) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+   	    return GT_FAIL;
+	}
+
+	/* Mask out all auto mode related bits. */
+	u16Data1 &= ~(QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF);
+
+	switch(mode)
+	{
+		case SPEED_AUTO_DUPLEX_AUTO:
+				u16Data |= QD_PHY_MODE_AUTO_AUTO;
+		case SPEED_1000_DUPLEX_AUTO:
+				u16Data1 |= QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF;
+				break;
+		case SPEED_AUTO_DUPLEX_FULL:
+				u16Data  |= QD_PHY_MODE_AUTO_FULL;
+				u16Data1 |= QD_GIGPHY_1000T_FULL;
+				break;
+		case SPEED_1000_DUPLEX_FULL:
+				u16Data1 |= QD_GIGPHY_1000T_FULL;
+				break;
+		case SPEED_1000_DUPLEX_HALF:
+				u16Data1 |= QD_GIGPHY_1000T_HALF;
+				break;
+		case SPEED_AUTO_DUPLEX_HALF:
+				u16Data  |= QD_PHY_MODE_AUTO_HALF;
+				u16Data1 |= QD_GIGPHY_1000T_HALF;
+				break;
+		case SPEED_100_DUPLEX_AUTO:
+				u16Data |= QD_PHY_MODE_100_AUTO;
+				break;
+		case SPEED_10_DUPLEX_AUTO:
+				u16Data |= QD_PHY_MODE_10_AUTO;
+				break;
+		case SPEED_100_DUPLEX_FULL:
+				u16Data |= QD_PHY_100_FULL;
+				break;
+		case SPEED_100_DUPLEX_HALF:
+				u16Data |= QD_PHY_100_HALF;
+				break;
+		case SPEED_10_DUPLEX_FULL:
+				u16Data |= QD_PHY_10_FULL;
+				break;
+		case SPEED_10_DUPLEX_HALF:
+				u16Data |= QD_PHY_10_HALF;
+				break;
+		default:
+				DBG_INFO(("Unknown Auto Mode (%d)\n",mode));
+				return GT_BAD_PARAM;
+	}
+
+    /* Write to Phy AutoNegotiation Advertisement Register.  */
+    if(hwWritePagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data));
+   	    return GT_FAIL;
+	}
+
+    /* Write to Phy AutoNegotiation 1000B Advertisement Register.  */
+    if(hwWritePagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_1000AD_REG,phyInfo->anyPage,u16Data1) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+   	    return GT_FAIL;
+	}
+
+	return GT_OK;
+}
+
+/*
+ * This routine get Auto-Negotiation Ad Register for Copper
+*/
+static 
+GT_STATUS gigCopperGetAutoMode
+(
+    IN GT_QD_DEV        *dev,
+    IN GT_U8            hwPort,
+    IN GT_PHY_INFO      *phyInfo,
+    IN GT_PHY_AUTO_MODE *mode
+)
+{
+    GT_U16 u16Data, u16Data1;
+    GT_U32 u32Data;
+
+    DBG_INFO(("gigCopperGetAutoMode Called.\n"));
+
+    if(hwReadPagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,&u16Data) != GT_OK)
+    {
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+           return GT_FAIL;
+    }
+
+    /* Pick out all auto mode related bits. */
+    u16Data &= QD_PHY_MODE_AUTO_AUTO;
+
+    if(hwReadPagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_1000AD_REG,phyInfo->anyPage,&u16Data1) != GT_OK)
+    {
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+           return GT_FAIL;
+    }
+
+    /* Pick out all auto mode related bits. */
+    u16Data1 &= (QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF);
+
+    u32Data  = (u16Data&0xffff)|((u16Data1&0xffff)<<16);
+
+    switch(u32Data)
+    {
+        case QD_PHY_MODE_10_HALF:
+                *mode = SPEED_10_DUPLEX_HALF;
+                break;
+        case QD_PHY_MODE_10_FULL:
+                *mode = SPEED_10_DUPLEX_FULL;
+                break;
+        case QD_PHY_MODE_100_HALF:
+                *mode = SPEED_100_DUPLEX_HALF;
+                break;
+        case QD_PHY_MODE_100_FULL:
+                *mode = SPEED_100_DUPLEX_FULL;
+                break;
+        case (QD_GIGPHY_1000T_HALF<<16):
+                *mode = SPEED_1000_DUPLEX_HALF;
+                break;
+        case (QD_GIGPHY_1000T_FULL<<16):
+                *mode = SPEED_1000_DUPLEX_FULL;
+                break;                
+        case QD_PHY_MODE_AUTO_HALF|(QD_GIGPHY_1000T_HALF<<16):
+                *mode = SPEED_AUTO_DUPLEX_HALF;
+                break;
+        case QD_PHY_MODE_AUTO_FULL|(QD_GIGPHY_1000T_FULL<<16):
+                *mode = SPEED_AUTO_DUPLEX_FULL;
+                break;
+        case QD_PHY_MODE_10_AUTO:
+                *mode = SPEED_10_DUPLEX_AUTO;
+                break;
+        case QD_PHY_MODE_100_AUTO:
+                *mode = SPEED_100_DUPLEX_AUTO;
+                break;
+        case ((QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF)<<16):
+                *mode = SPEED_1000_DUPLEX_AUTO;
+                break;                
+        case QD_PHY_MODE_AUTO_AUTO|((QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF)<<16):
+                *mode = SPEED_AUTO_DUPLEX_AUTO;
+                break;
+        default:
+                *mode = SPEED_AUTO_DUPLEX_AUTO;
+                DBG_INFO(("Unknown Auto Mode (%08x)\n", u32Data));
+                break;
+    }
+
+    return GT_OK;
+}
+
+/*
+ * This routine set Auto-Negotiation Ad Register for Fiber
+*/
+static 
+GT_STATUS gigFiberSetAutoMode
+(
+	IN GT_QD_DEV *dev,
+	IN GT_U8 hwPort,
+	IN GT_PHY_INFO	 *phyInfo,
+	IN GT_PHY_AUTO_MODE mode
+)
+{
+    GT_U16 			u16Data;
+
+    DBG_INFO(("gigPhySetAutoMode Called.\n"));
+
+    if(hwReadPagedPhyReg(dev,hwPort,1,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+   	    return GT_FAIL;
+	}
+
+	/* Mask out all auto mode related bits. */
+	u16Data &= ~(QD_GIGPHY_1000X_FULL|QD_GIGPHY_1000X_HALF);
+
+	switch(mode)
+	{
+		case SPEED_AUTO_DUPLEX_AUTO:
+		case SPEED_1000_DUPLEX_AUTO:
+				u16Data |= QD_GIGPHY_1000X_FULL|QD_GIGPHY_1000X_HALF;
+				break;
+		case SPEED_AUTO_DUPLEX_FULL:
+		case SPEED_1000_DUPLEX_FULL:
+				u16Data |= QD_GIGPHY_1000X_FULL;
+				break;
+		case SPEED_AUTO_DUPLEX_HALF:
+		case SPEED_1000_DUPLEX_HALF:
+				u16Data |= QD_GIGPHY_1000X_HALF;
+				break;
+		default:
+	 	       	DBG_INFO(("Unknown Auto Mode (%d)\n",mode));
+				return GT_BAD_PARAM;
+	}
+
+    /* Write to Phy AutoNegotiation Advertisement Register.  */
+    if(hwWritePagedPhyReg(dev,hwPort,1,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data));
+   	    return GT_FAIL;
+	}
+
+	return GT_OK;
+}
+
+/*
+ * This routine sets Auto Mode and Reset the phy
+*/
+static 
+GT_STATUS phySetAutoMode
+(
+	IN GT_QD_DEV *dev,
+	IN GT_U8 hwPort,
+	IN GT_PHY_INFO *phyInfo,
+	IN GT_PHY_AUTO_MODE mode
+)
+{
+    GT_U16 		u16Data;
+	GT_STATUS	status;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+    DBG_INFO(("phySetAutoMode Called.\n"));
+
+	if (!(phyInfo->flag & GT_PHY_GIGABIT))
+	{
+		if((status=feSetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK)
+		{
+   		    return status;
+		}
+
+		u16Data = QD_PHY_SPEED | QD_PHY_DUPLEX | QD_PHY_AUTONEGO;
+
+    	DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+        	      hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+		/* soft reset */
+		return hwPhyReset(dev,hwPort,u16Data);
+	}
+
+	if(driverPagedAccessStart(dev,hwPort,phyInfo->pageType,&autoOn,&pageReg) != GT_OK)
+	{
+		return GT_FAIL;
+	}
+
+	if(phyInfo->flag & GT_PHY_COPPER)
+	{
+		if((status=gigCopperSetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK)
+		{
+   		    return status;
+		}
+
+		u16Data = QD_PHY_AUTONEGO;
+
+    	DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+        	      hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+	    /* Write to Phy Control Register.  */
+	    if(hwWritePagedPhyReg(dev,hwPort,0,QD_PHY_CONTROL_REG,phyInfo->anyPage,u16Data) != GT_OK)
+    		return GT_FAIL;
+	}
+	else if(phyInfo->flag & GT_PHY_FIBER)
+	{
+		if((status=gigFiberSetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK)
+		{
+   		    return status;
+		}
+		u16Data = QD_PHY_AUTONEGO;
+
+    	DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+        	      hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+	    /* Write to Phy Control Register.  */
+	    if(hwWritePagedPhyReg(dev,hwPort,1,QD_PHY_CONTROL_REG,phyInfo->anyPage,u16Data) != GT_OK)
+    		return GT_FAIL;
+	}
+
+	if(driverPagedAccessStop(dev,hwPort,phyInfo->pageType,autoOn,pageReg) != GT_OK)
+	{
+		return GT_FAIL;
+	}
+
+	return hwPhyReset(dev,hwPort,0xFF);
+}
+
+/*
+ * This routine gets Auto Mode
+*/
+static 
+GT_STATUS phyGetAutoMode
+(
+    IN  GT_QD_DEV        *dev,
+    IN  GT_U8            hwPort,
+    IN  GT_PHY_INFO      *phyInfo,
+    OUT GT_PHY_AUTO_MODE *mode
+)
+{
+    GT_STATUS    status;
+    GT_BOOL      autoOn;
+    GT_U16       pageReg;
+
+    DBG_INFO(("phyGetAutoMode Called.\n"));
+
+    if (!(phyInfo->flag & GT_PHY_GIGABIT))
+    {
+        if((status=feGetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK)
+        {
+               return status;
+        }
+        return status;
+    }
+
+    if(driverPagedAccessStart(dev,hwPort,phyInfo->pageType,&autoOn,&pageReg) != GT_OK)
+    {
+        return GT_FAIL;
+    }
+
+    if(phyInfo->flag & GT_PHY_COPPER)
+    {
+        if((status=gigCopperGetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK)
+        {
+               return status;
+        }
+    }
+    else if(phyInfo->flag & GT_PHY_FIBER)
+    {
+        return GT_NOT_SUPPORTED;
+    }
+
+    if(driverPagedAccessStop(dev,hwPort,phyInfo->pageType,autoOn,pageReg) != GT_OK)
+    {
+        return GT_FAIL;
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+* gprtPhyReset
+*
+* DESCRIPTION:
+*       This routine preforms PHY reset.
+*		After reset, phy will be in Autonegotiation mode.
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+* COMMENTS:
+* data sheet register 0.15 - Reset
+* data sheet register 0.13 - Speed
+* data sheet register 0.12 - Autonegotiation
+* data sheet register 0.8  - Duplex Mode
+*******************************************************************************/
+
+GT_STATUS gprtPhyReset
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_PHY_INFO		phyInfo;
+
+    DBG_INFO(("gprtPhyReset Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	/* set Auto Negotiation AD Register */
+	retVal = phySetAutoMode(dev,hwPort,&phyInfo,SPEED_AUTO_DUPLEX_AUTO);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetPortLoopback
+*
+* DESCRIPTION:
+* Enable/Disable Internal Port Loopback. 
+* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and 
+*   forces speed to be 10Mbps.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
+*   it is recommended to call gprtSetPortAutoMode for PHY configuration after 
+*   Loopback test.
+* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled and Link is active, the current speed is used.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   All other cases, default MAC Interface speed is used. Please refer to the data
+*   sheet for the information of the default MAC Interface speed.
+*   
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetPortLoopback
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	IN GT_BOOL   enable
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+	GT_PHY_INFO		phyInfo;
+
+    DBG_INFO(("gprtSetPortLoopback Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+    if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+	}
+
+	/* Is this Fast Ethernet Phy? */
+	if (!(phyInfo.flag & GT_PHY_GIGABIT))
+	{
+		if(enable)
+		{
+			if(u16Data & QD_PHY_AUTONEGO)
+			{
+				/* Disable Auto-Neg*/
+				u16Data &= ~QD_PHY_AUTONEGO;
+
+				if((retVal=hwPhyReset(dev,hwPort,u16Data)) != GT_OK)
+				{
+					DBG_INFO(("Softreset failed.\n"));
+					gtSemGive(dev,dev->phyRegsSem);
+					return retVal;
+				}
+			}
+		}
+		else
+		{
+			if(!(u16Data & QD_PHY_AUTONEGO))
+			{
+				/* Enable Auto-Neg*/
+				u16Data |= QD_PHY_RESET | QD_PHY_AUTONEGO;
+
+				if((retVal=hwPhyReset(dev,hwPort,u16Data)) != GT_OK)
+				{
+					DBG_INFO(("Softreset failed.\n"));
+					gtSemGive(dev,dev->phyRegsSem);
+					return retVal;
+				}
+			}
+
+		}
+	}
+
+	BOOL_2_BIT(enable,u16Data);
+
+    /* Write to Phy Control Register.  */
+    retVal = hwSetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,14,1,u16Data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+	gtSemGive(dev,dev->phyRegsSem);
+    return retVal;
+}
+/*******************************************************************************
+* gprtGetPortLoopback
+*
+* DESCRIPTION:
+* Get Internal Port Loopback state. 
+* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and 
+*   forces speed to be 10Mbps.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
+*   it is recommended to call gprtSetPortAutoMode for PHY configuration after 
+*   Loopback test.
+* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
+*   If Auto-Negotiation is enabled and Link is active, the current speed is used.
+*   If Auto-Negotiation is disabled, the forced speed is used.
+*   All other cases, default MAC Interface speed is used. Please refer to the data
+*   sheet for the information of the default MAC Interface speed.
+*   
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* enable - If GT_TRUE,  loopback mode is enabled
+* If GT_FALSE,  loopback mode is disabled
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.14 - Loop_back
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortLoopback
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	OUT GT_BOOL   *enable
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+	GT_PHY_INFO		phyInfo;
+
+    DBG_INFO(("gprtGetPortLoopback Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	/*get loopback state*/
+	retVal = hwGetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,14,1,&u16Data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+        BIT_2_BOOL(u16Data, *enable);
+	}
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtSetPortLineLoopback
+*
+* DESCRIPTION:
+* Enable/Disable Port Line Loopback. 
+*   
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register FE:28.4, GE:21_2.14  - Loop_back
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetPortLineLoopback
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	IN GT_BOOL   enable
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+    GT_PHY_INFO		phyInfo;
+    GT_U16		    pageReg;
+    
+    DBG_INFO(("gprtSetPortLineLoopback Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+    
+    gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+    
+    /* check if the port is configurable */
+    if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+    {
+        gtSemGive(dev,dev->phyRegsSem);
+        return GT_NOT_SUPPORTED;
+    }
+    
+    if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+    {
+        DBG_INFO(("Unknown PHY device.\n"));
+        gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+    }
+
+	BOOL_2_BIT(enable,u16Data);
+		
+	 /* GE Phy */
+    if ((phyInfo.flag & GT_PHY_GIGABIT))
+    {
+        if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,0,&pageReg) != GT_OK)
+        {
+            return GT_FAIL;
+        } 
+        
+		/* Write to GE PHY MAC specific control register.  */
+		retVal = hwSetPagedPhyRegField(dev,hwPort, 2, QD_PHY_GE_LINE_LOOPBACK_REG,14,1,phyInfo.anyPage, u16Data);
+
+    	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,0,pageReg) != GT_OK)
+    	{
+    		return GT_FAIL;
+    	}
+    }
+    else /* FE Phy */
+    {
+    	/* Write to FE PHY specific control register.  */
+		retVal = hwSetPhyRegField(dev,hwPort,QD_PHY_FE_LINE_LOOPBACK_REG,4,1,u16Data);
+    }
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+    }
+    else
+    {
+        DBG_INFO(("OK.\n"));
+    }
+    gtSemGive(dev,dev->phyRegsSem);
+    return retVal;
+}
+/*******************************************************************************
+* gprtGetPortLineLoopback
+*
+* DESCRIPTION:
+* Get Port Line Loopback status. 
+*   
+*
+* INPUTS:
+* port - The logical port number, unless SERDES device is accessed
+*        The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode* enable - If GT_TRUE, enable loopback mode
+* If GT_FALSE, disable loopback mode
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register FE:28.4, GE:21_2.14  - Loop_back
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetPortLineLoopback
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	OUT GT_BOOL*   enable
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+    GT_PHY_INFO		phyInfo;
+    GT_U16		    pageReg;
+    
+    DBG_INFO(("gprtGetPortLineLoopback Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+    
+    gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+    
+    /* check if the port is configurable */
+    if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+    {
+        gtSemGive(dev,dev->phyRegsSem);
+        return GT_NOT_SUPPORTED;
+    }
+    
+    if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+    {
+        DBG_INFO(("Unknown PHY device.\n"));
+        gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+    }
+		
+	 /* GE Phy */
+    if ((phyInfo.flag & GT_PHY_GIGABIT))
+    {
+        if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,0,&pageReg) != GT_OK)
+        {
+            return GT_FAIL;
+        } 
+        
+		/* Read to GE PHY MAC specific control register.  */
+		retVal = hwGetPagedPhyRegField(dev,hwPort, 2, QD_PHY_GE_LINE_LOOPBACK_REG,14,1,phyInfo.anyPage,&u16Data);
+
+    	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,0,pageReg) != GT_OK)
+    	{
+    		return GT_FAIL;
+    	}		
+    }
+    else /* FE Phy */
+    {
+    	/* Read to FE PHY specific control register.  */
+		retVal = hwGetPhyRegField(dev,hwPort,QD_PHY_FE_LINE_LOOPBACK_REG,4,1,&u16Data);
+    }
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+    }
+    else
+    {
+        DBG_INFO(("OK.\n"));
+    }
+
+	BIT_2_BOOL(u16Data, *enable);
+	
+    gtSemGive(dev,dev->phyRegsSem);
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtSetPortSpeed
+*
+* DESCRIPTION:
+* 		Sets speed for a specific logical port. This function will keep the duplex 
+*		mode and loopback mode to the previous value, but disable others, such as 
+*		Autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*		speed - port speed.
+*				PHY_SPEED_10_MBPS for 10Mbps
+*				PHY_SPEED_100_MBPS for 100Mbps
+*				PHY_SPEED_1000_MBPS for 1000Mbps
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.13 - Speed Selection (LSB)
+* data sheet register 0.6  - Speed Selection (MSB)
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetPortSpeed
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+IN GT_PHY_SPEED speed
+)
+{
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+	GT_PHY_INFO		phyInfo;
+	GT_STATUS		retVal;
+
+    DBG_INFO(("gprtSetPortSpeed Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+    if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+	}
+
+	switch(speed)
+	{
+		case PHY_SPEED_10_MBPS:
+			if ((phyInfo.flag & GT_PHY_GIGABIT) && !(phyInfo.flag & GT_PHY_COPPER))
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_BAD_PARAM;
+			}
+			u16Data = u16Data & (QD_PHY_LOOPBACK | QD_PHY_AUTONEGO | QD_PHY_DUPLEX);
+			break;
+		case PHY_SPEED_100_MBPS:
+			u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_AUTONEGO | QD_PHY_DUPLEX)) | QD_PHY_SPEED;
+			break;
+		case PHY_SPEED_1000_MBPS:
+			if (!(phyInfo.flag & GT_PHY_GIGABIT))
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_BAD_PARAM;
+			}
+			u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_AUTONEGO | QD_PHY_DUPLEX)) | QD_PHY_SPEED_MSB;
+			break;
+		default:
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+	}
+
+    DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+              hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+	retVal = hwPhyReset(dev,hwPort,u16Data);
+  	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPortSpeed
+*
+* DESCRIPTION:
+* 		Gets speed for a specific logical port. 
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* 		speed - port speed.
+*				PHY_SPEED_10_MBPS for 10Mbps
+*				PHY_SPEED_100_MBPS for 100Mbps
+*				PHY_SPEED_1000_MBPS for 1000Mbps
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* data sheet register 0.13 - Speed Selection (LSB)
+* data sheet register 0.6  - Speed Selection (MSB)
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortSpeed
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+IN GT_PHY_SPEED *speed
+)
+{
+    GT_U8         hwPort;  /* The physical port number */
+    GT_U16 			u16Data;
+    GT_PHY_INFO		phyInfo;
+
+    DBG_INFO(("gprtGetPortSpeed Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+    if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+	}
+
+	if ((phyInfo.flag & GT_PHY_GIGABIT) && !(phyInfo.flag & GT_PHY_COPPER))
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_BAD_PARAM;
+	}
+	
+	if ((phyInfo.flag & GT_PHY_GIGABIT) && (u16Data & QD_PHY_SPEED_MSB))
+	{
+		*speed = PHY_SPEED_1000_MBPS;
+	}
+	else
+	{
+		if (u16Data & QD_PHY_SPEED)
+		{
+			*speed = PHY_SPEED_100_MBPS;
+		}
+		else
+		{
+			*speed = PHY_SPEED_10_MBPS;
+		}			
+	}
+
+    DBG_INFO(("Read phy(%d) register: regAddr 0x%x, data %#x, speed[%d] \r\n",
+              hwPort,QD_PHY_CONTROL_REG,u16Data, *speed));
+
+  	gtSemGive(dev,dev->phyRegsSem);
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtPortAutoNegEnable
+*
+* DESCRIPTION:
+* 		Enable/disable an Auto-Negotiation.
+*		This routine simply sets Auto Negotiation bit (bit 12) of Control 
+*		Register and reset the phy.
+*		For Speed and Duplex selection, please use gprtSetPortAutoMode.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+* 		state - GT_TRUE for enable Auto-Negotiation,
+*				GT_FALSE otherwise
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.12 - Auto-Negotiation Enable
+* 		data sheet register 4.8, 4.7, 4.6, 4.5 - Auto-Negotiation Advertisement
+*
+*******************************************************************************/
+GT_STATUS gprtPortAutoNegEnable
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	IN GT_BOOL   state
+)
+{
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+	GT_STATUS		retVal;
+
+    DBG_INFO(("gprtPortAutoNegEnable Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+    if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+	}
+
+	if(state)
+	{
+		u16Data = (u16Data & (QD_PHY_SPEED | QD_PHY_DUPLEX)) | QD_PHY_AUTONEGO;
+	}
+	else
+	{
+		u16Data = u16Data & (QD_PHY_SPEED | QD_PHY_DUPLEX);
+	}
+
+
+    DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+              hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+	retVal = hwPhyReset(dev,hwPort,u16Data);
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+/*******************************************************************************
+* gprtGetPortAutoNegState
+*
+* DESCRIPTION:
+* 		Read the auto negotiation state of specific logical port.
+*		This routine simply reads Auto Negotiation bit (bit 12) of Control 
+*		Register.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* 		state 	- GT_TRUE for enable Auto-Negotiation,
+*				   GT_FALSE otherwise
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.12 - Auto-Negotiation Enable
+* 		data sheet register 4.8, 4.7, 4.6, 4.5 - Auto-Negotiation Advertisement
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortAutoNegState
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	OUT GT_BOOL   *state
+)
+{
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+    GT_STATUS		retVal;
+
+    DBG_INFO(("gprtGetPortAutoNegState Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+    gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+    
+    /* check if the port is configurable */
+    if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+    {
+    	gtSemGive(dev,dev->phyRegsSem);
+    	return GT_NOT_SUPPORTED;
+    }
+
+    /*read the auto negotiation state from bit 12 of PHY control register*/	
+    if((retVal=hwGetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,12,1,&u16Data)) != GT_OK)
+    {
+        	DBG_INFO(("Failed.\n"));
+    	gtSemGive(dev,dev->phyRegsSem);
+    	return retVal;
+    }
+    
+    BIT_2_BOOL(u16Data, *state);
+	
+    gtSemGive(dev,dev->phyRegsSem);
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtPortPowerDown
+*
+* DESCRIPTION:
+* 		Enable/disable (power down) on specific logical port.
+*		Phy configuration remains unchanged after Power down.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+* 		state -	GT_TRUE: power down
+* 				GT_FALSE: normal operation
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.11 - Power Down
+*
+*******************************************************************************/
+
+GT_STATUS gprtPortPowerDown
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+IN GT_BOOL   state
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+
+    DBG_INFO(("gprtPortPowerDown Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	BOOL_2_BIT(state,u16Data);
+
+	if((retVal=hwSetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,11,1,u16Data)) != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return retVal;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gprtGetPortPowerDown
+*
+* DESCRIPTION:
+* 		Read Port state (power down/normal operation) on specific logical port.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* 		state -	GT_TRUE: power down
+* 				GT_FALSE: normal operation
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.11 - Power Down
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortPowerDown
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+OUT GT_BOOL   *state
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+
+    DBG_INFO(("gprtGetPortPowerDown Called.\n"));
+
+    if(state == NULL)
+    {
+	DBG_INFO(("Input point state equals NULL which is illegal,  return\n"));
+    }
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+    gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+    
+    /* check if the port is configurable */
+    if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+    {
+    	gtSemGive(dev,dev->phyRegsSem);
+    	return GT_NOT_SUPPORTED;
+    }
+    
+    if((retVal=hwGetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,11,1,&u16Data)) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+    	gtSemGive(dev,dev->phyRegsSem);
+    	return retVal;
+    }
+    
+    BIT_2_BOOL(u16Data, *state);
+    
+    gtSemGive(dev,dev->phyRegsSem);
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtPortRestartAutoNeg
+*
+* DESCRIPTION:
+* 		Restart AutoNegotiation. If AutoNegotiation is not enabled, it'll enable 
+*		it. Loopback and Power Down will be disabled by this routine.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.9 - Restart Auto-Negotiation
+*
+*******************************************************************************/
+
+GT_STATUS gprtPortRestartAutoNeg
+( 
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port
+)
+{
+    GT_STATUS       retVal;      
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+
+    DBG_INFO(("gprtPortRestartAutoNeg Called.\n"));
+  
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+    if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+	}
+
+	u16Data &= (QD_PHY_DUPLEX | QD_PHY_SPEED);
+	u16Data |= (QD_PHY_RESTART_AUTONEGO | QD_PHY_AUTONEGO);
+
+    DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+              hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+    /* Write to Phy Control Register.  */
+    retVal = hwWritePhyReg(dev,hwPort,QD_PHY_CONTROL_REG,u16Data);
+	gtSemGive(dev,dev->phyRegsSem);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtSetPortDuplexMode
+*
+* DESCRIPTION:
+* 		Sets duplex mode for a specific logical port. This function will keep 
+*		the speed and loopback mode to the previous value, but disable others,
+*		such as Autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+* 		dMode	- dulpex mode
+*
+* OUTPUTS:
+* 		None.
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - Duplex Mode
+*
+*******************************************************************************/
+GT_STATUS gprtSetPortDuplexMode
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+IN GT_BOOL   dMode
+)
+{
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+	GT_STATUS		retVal;
+
+    DBG_INFO(("gprtSetPortDuplexMode Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+    if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	{
+        DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+	}
+
+	if(dMode)
+	{
+		u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_SPEED | QD_PHY_SPEED_MSB)) | QD_PHY_DUPLEX;
+	}
+	else
+	{
+		u16Data = u16Data & (QD_PHY_LOOPBACK | QD_PHY_SPEED | QD_PHY_SPEED_MSB);
+	}
+
+
+    DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+              hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+    /* Write to Phy Control Register.  */
+	retVal = hwPhyReset(dev,hwPort,u16Data);
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+/*******************************************************************************
+* gprtPortGetDuplexMode
+*
+* DESCRIPTION:
+* 		Gets duplex mode for a specific logical port. 
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* 		dMode	- dulpex mode
+*
+* RETURNS:
+* 		GT_OK 	- on success
+* 		GT_FAIL 	- on error
+*
+* COMMENTS:
+* 		data sheet register 0.8 - duplex mode
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortDuplexMode
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+OUT GT_BOOL*   dMode
+)
+{
+    GT_STATUS   retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* the physical port number   */
+    GT_U16 			u16Data;
+
+    DBG_INFO(("gprtPortGetDuplexMode Called.\n"));
+
+    if(dMode == NULL)
+    {
+		DBG_INFO(("Input point state equals NULL which is illegal,  return\n"));
+    }
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+    gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+    
+    /* check if the port is configurable */
+    if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+    {
+    	gtSemGive(dev,dev->phyRegsSem);
+    	return GT_NOT_SUPPORTED;
+    }
+    
+    if((retVal=hwGetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,8,1,&u16Data)) != GT_OK)
+    {
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return retVal;
+    }
+    
+    BIT_2_BOOL(u16Data, *dMode);
+    
+    gtSemGive(dev,dev->phyRegsSem);
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtSetPortAutoMode
+*
+* DESCRIPTION:
+* 		This routine sets up the port with given Auto Mode.
+*		Supported mode is as follows:
+*		- Auto for both speed and duplex.
+*		- Auto for speed only and Full duplex.
+*		- Auto for speed only and Half duplex.
+*		- Auto for duplex only and speed 1000Mbps.
+*		- Auto for duplex only and speed 100Mbps.
+*		- Auto for duplex only and speed 10Mbps.
+*		- Speed 1000Mbps and Full duplex.
+*		- Speed 1000Mbps and Half duplex.
+*		- Speed 100Mbps and Full duplex.
+*		- Speed 100Mbps and Half duplex.
+*		- Speed 10Mbps and Full duplex.
+*		- Speed 10Mbps and Half duplex.
+*		
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+* 		mode - Auto Mode to be written
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - on device without copper
+*
+* COMMENTS:
+* 		data sheet register 4.8, 4.7, 4.6, and 4.5 Autonegotiation Advertisement
+* 		data sheet register 4.6, 4.5 Autonegotiation Advertisement for 1000BX
+* 		data sheet register 9.9, 9.8 Autonegotiation Advertisement for 1000BT
+*******************************************************************************/
+
+GT_STATUS gprtSetPortAutoMode
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	IN GT_PHY_AUTO_MODE mode
+)
+{
+
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_PHY_INFO		phyInfo;
+
+	DBG_INFO(("gprtSetPortAutoMode Called.\n"));
+    
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	retVal = GT_NOT_SUPPORTED;
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	retVal = phySetAutoMode(dev,hwPort,&phyInfo,mode);
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+
+}
+
+/*******************************************************************************
+* gprtGetPortAutoMode
+*
+* DESCRIPTION:
+*         This routine get Auto Mode of specific port.
+*        Supported mode is as follows:
+*        - Auto for both speed and duplex.
+*        - Auto for speed only and Full duplex.
+*        - Auto for speed only and Half duplex.
+*        - Auto for duplex only and speed 1000Mbps.
+*        - Auto for duplex only and speed 100Mbps.
+*        - Auto for duplex only and speed 10Mbps.
+*        - Speed 1000Mbps and Full duplex.
+*        - Speed 1000Mbps and Half duplex.
+*        - Speed 100Mbps and Full duplex.
+*        - Speed 100Mbps and Half duplex.
+*        - Speed 10Mbps and Full duplex.
+*        - Speed 10Mbps and Half duplex.
+*        
+*
+* INPUTS:
+*        port -    The logical port number, unless SERDES device is accessed
+*                  The physical address, if SERDES device is accessed  
+*
+* OUTPUTS:
+*        mode -    Auto Mode to be written
+*
+* RETURNS:
+*        GT_OK   - on success
+*        GT_FAIL - on error
+*        GT_NOT_SUPPORTED - on device without copper
+*
+* COMMENTS:
+*         data sheet register 4.8, 4.7, 4.6, and 4.5 Autonegotiation Advertisement
+*         data sheet register 4.6, 4.5 Autonegotiation Advertisement for 1000BX
+*         data sheet register 9.9, 9.8 Autonegotiation Advertisement for 1000BT
+*******************************************************************************/
+
+GT_STATUS gprtGetPortAutoMode
+(
+    IN  GT_QD_DEV        *dev,
+    IN  GT_LPORT         port,
+    OUT GT_PHY_AUTO_MODE *mode
+)
+{
+    GT_STATUS       retVal; /* Functions return value.  */
+    GT_U8           hwPort; /* the physical port number */
+    GT_PHY_INFO     phyInfo;
+
+    DBG_INFO(("gprtGetPortAutoMode Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+    retVal = GT_NOT_SUPPORTED;
+
+    gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+    /* check if the port is configurable */
+    if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+    {
+        gtSemGive(dev,dev->phyRegsSem);
+        return GT_NOT_SUPPORTED;
+    }
+
+    if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+    {
+        DBG_INFO(("Unknown PHY device.\n"));
+        gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+    }
+
+    retVal = phyGetAutoMode(dev,hwPort,&phyInfo,mode);
+
+    gtSemGive(dev,dev->phyRegsSem);
+    return retVal;
+
+}
+
+/*******************************************************************************
+* gprtSetPause
+*
+* DESCRIPTION:
+*       This routine will set the pause bit in Autonegotiation Advertisement
+*		Register. And restart the autonegotiation.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*		state - GT_PHY_PAUSE_MODE enum value.
+*				GT_PHY_NO_PAUSE		- disable pause
+* 				GT_PHY_PAUSE		- support pause
+*				GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*				GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+
+GT_STATUS gprtSetPause
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+IN GT_PHY_PAUSE_MODE state
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 			u16Data,regStart;
+	GT_STATUS		retVal = GT_OK;
+	GT_PHY_INFO		phyInfo;
+
+	DBG_INFO(("phySetPause Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	regStart = 10;
+
+	if(state & GT_PHY_ASYMMETRIC_PAUSE)
+	{
+		if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+		{
+	    	DBG_INFO(("Unknown PHY device.\n"));
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+		}
+
+		if (!(phyInfo.flag & GT_PHY_GIGABIT))
+		{
+			DBG_INFO(("Not Supported\n"));
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_BAD_PARAM;
+		}
+
+		if(!(phyInfo.flag & GT_PHY_COPPER))
+		{
+			regStart = 7;
+		}
+
+	}
+
+	u16Data = state;
+
+	/* Write to Phy AutoNegotiation Advertisement Register.  */
+	if((retVal=hwSetPhyRegField(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,(GT_U8)regStart,2,u16Data)) != GT_OK)
+	{
+		DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	/* Restart auto negotiation.  */
+       if(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_OK)
+	{
+        	DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	u16Data |= (QD_PHY_RESTART_AUTONEGO);
+
+    DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
+              hwPort,QD_PHY_CONTROL_REG,u16Data));
+
+    /* Write to Phy Control Register.  */
+    retVal = hwWritePhyReg(dev,hwPort,QD_PHY_CONTROL_REG,u16Data);
+	gtSemGive(dev,dev->phyRegsSem);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+    }
+    else
+    {
+        DBG_INFO(("OK.\n"));
+    }
+	
+	gtSemGive(dev,dev->phyRegsSem);
+	
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPause
+*
+* DESCRIPTION:
+*       This routine will get the pause bit in Autonegotiation Advertisement
+*		Register.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+*
+* OUTPUTS:
+*		state - GT_PHY_PAUSE_MODE enum value.
+*				GT_PHY_NO_PAUSE		- disable pause
+* 				GT_PHY_PAUSE		- support pause
+*				GT_PHY_ASYMMETRIC_PAUSE	- support asymmetric pause
+*				GT_PHY_BOTH_PAUSE	- support both pause and asymmetric pause
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+* COMMENTS:
+* data sheet register 4.10 Autonegotiation Advertisement Register
+*******************************************************************************/
+GT_STATUS gprtGetPause
+(
+IN GT_QD_DEV *dev,
+IN GT_LPORT  port,
+OUT  GT_PHY_PAUSE_MODE *state
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 			u16Data,regStart;
+	GT_STATUS		retVal = GT_OK;
+	GT_PHY_INFO		phyInfo;
+
+	DBG_INFO(("gprtGetPause Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	regStart = 10;
+
+	/* Read Phy AutoNegotiation Advertisement Register.  */
+	if((retVal=hwGetPhyRegField(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,(GT_U8)regStart,2,&u16Data)) != GT_OK)
+	{
+		DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+
+	*state = u16Data;
+	
+	return retVal;
+}
+
+static
+GT_STATUS dteWorkAround_Phy100M
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8            hwPort
+)
+{
+	GT_STATUS status = GT_OK;
+	GT_U32 threshold[] = {0x000B,0x0000,0x8780,0x0000,0x8F80,0x0000,
+						  0x9780,0x0000,0x9F80,0x0000,0xA780,0x0000,
+						  0xAF80,0x0000,0xB780,0x0000,0xBF80,0x0000,
+						  0xC780,0x0000,0xCF80,0x0000,0xD780,0x0000,
+						  0xDF80,0x0000,0xE780,0x0000,0xEF80,0x0000,
+						  0xF780,0x0000,0xFF80,0x0000};
+	int i, thresholdSize;
+
+	/* force r125 clock */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0003)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0x807f)) != GT_OK)
+	{
+		return status;
+	}
+
+	/* write thresholds */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x000B)) != GT_OK)
+	{
+		return status;
+	}
+
+	thresholdSize = sizeof(threshold)/sizeof(GT_U32);
+
+	for(i=0; i<thresholdSize; i++)
+	{
+		if((status= hwWritePhyReg(dev,hwPort,0x1E,(GT_U16)threshold[i])) != GT_OK)
+		{
+			return status;
+		}
+	}
+
+	/* setting adc Masking */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0001)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0x4000)) != GT_OK)
+	{
+		return status;
+	}
+
+	/* setting noise level */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0005)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0xA000)) != GT_OK)
+	{
+		return status;
+	}
+
+	/* 
+		offseting cable length measurement by 6.72m(2*4*0.84m)
+		set 30_10.14:11 to 0x1001 for cable length measure.
+	*/ 
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x000a)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0x4840)) != GT_OK)
+	{
+		return status;
+	}
+
+	/* release force r125 clock */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0003)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0x0000)) != GT_OK)
+	{
+		return status;
+	}
+
+
+	return status;
+}
+
+static
+GT_STATUS dteWorkAround_Phy1000M
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8            hwPort
+)
+{
+	GT_STATUS status = GT_OK;
+	GT_U32 threshold[] = {0x0000,0x8780,0x0000,0x8F80,0x0000,0x9780,
+						  0x0000,0x9F80,0x0000,0xA780,0x0000,0xAF80,
+						  0x0000,0xB780,0x0000,0xBF80,0x0000,0xC780,
+						  0x0000,0xCF80,0x0000,0xD780,0x0000,0xDF80,
+						  0x0000,0xE780,0x0000,0xEF80,0x0000,0xF780,
+						  0x0000,0xFF80,0x0000};
+	int i, thresholdSize;
+
+	/*  */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x001B)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0x43FF)) != GT_OK)
+	{
+		return status;
+	}
+
+	/*  */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x001C)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0x9999)) != GT_OK)
+	{
+		return status;
+	}
+
+	/*  */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x001F)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0xE00C)) != GT_OK)
+	{
+		return status;
+	}
+
+	/*  */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0018)) != GT_OK)
+	{
+		return status;
+	}
+	if((status= hwWritePhyReg(dev,hwPort,0x1E,0xFFA1)) != GT_OK)
+	{
+		return status;
+	}
+
+	/* write thresholds */
+	if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0010)) != GT_OK)
+	{
+		return status;
+	}
+
+	thresholdSize = sizeof(threshold)/sizeof(GT_U32);
+
+	for(i=0; i<thresholdSize; i++)
+	{
+		if((status= hwWritePhyReg(dev,hwPort,0x1E,(GT_U16)threshold[i])) != GT_OK)
+		{
+			return status;
+		}
+	}
+
+	return status;
+}
+
+static
+GT_STATUS feSetDTE
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     hwPort,
+	IN  GT_BOOL   state
+)
+{
+	GT_U16 			u16Data;
+	GT_STATUS		retVal = GT_OK;
+
+	if((retVal = hwReadPhyReg(dev,hwPort,0x10,&u16Data)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	u16Data = state?(u16Data|0x8000):(u16Data&(~0x8000));
+
+	if((retVal = hwWritePhyReg(dev,hwPort,0x10,u16Data)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* soft reset */
+	if((retVal = hwPhyReset(dev,hwPort,0xFF)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	return retVal;
+}
+
+static
+GT_STATUS gigSetDTE
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     hwPort,
+	IN  GT_BOOL   state
+)
+{
+	GT_U16 			u16Data;
+	GT_STATUS		retVal = GT_OK;
+
+	if((retVal = hwReadPhyReg(dev,hwPort,20,&u16Data)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	u16Data = state?(u16Data|0x4):(u16Data&(~0x4));
+
+	if((retVal = hwWritePhyReg(dev,hwPort,20,u16Data)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* soft reset */
+	if((retVal = hwPhyReset(dev,hwPort,0xFF)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	return retVal;
+}
+
+static
+GT_STATUS gigMPSetDTE
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     hwPort,
+	IN  GT_BOOL   state
+)
+{
+	GT_U16 			u16Data;
+	GT_STATUS		retVal = GT_OK;
+
+	if((retVal = hwReadPagedPhyReg(dev,hwPort,0,26,0,&u16Data)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	u16Data = state?(u16Data|0x100):(u16Data&(~0x100));
+
+	if((retVal = hwWritePagedPhyReg(dev,hwPort,0,26,0,u16Data)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* soft reset */
+	if((retVal = hwPhyReset(dev,hwPort,0xFF)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtSetDTEDetect
+*
+* DESCRIPTION:
+*       This routine enables/disables DTE.
+*
+* INPUTS:
+* 		port - The logical port number
+* 		mode - either GT_TRUE(for enable) or GT_FALSE(for disable)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetDTEDetect
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+	IN GT_BOOL   state
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_STATUS		retVal = GT_OK;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+	DBG_INFO(("phySetDTE Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* check if the port supports DTE */
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (!(phyInfo.flag & GT_PHY_DTE_CAPABLE))
+	{
+		DBG_INFO(("Not Supported\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch(phyInfo.dteType)
+	{
+		case GT_PHY_DTE_TYPE1:
+			/* FE Phy needs work-around */
+			if((retVal = feSetDTE(dev,hwPort,state)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+
+			if(state == GT_FALSE)
+				break;
+
+			if((retVal = dteWorkAround_Phy100M(dev,hwPort)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			break;
+		case GT_PHY_DTE_TYPE3:
+			/* Gigabit Phy with work-around required */
+			if((retVal = gigSetDTE(dev,hwPort,state)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+
+			if(state == GT_FALSE)
+				break;
+
+			if((retVal = dteWorkAround_Phy1000M(dev,hwPort)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			break;
+
+		case GT_PHY_DTE_TYPE2:
+			/* no workaround required */
+			if((retVal = gigSetDTE(dev,hwPort,state)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+
+			break;
+		case GT_PHY_DTE_TYPE4:
+			/* no workaround required */
+			if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+			}
+
+			if((retVal = gigMPSetDTE(dev,hwPort,state)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+
+			if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+			}
+			break;
+		case GT_PHY_DTE_TYPE5:
+			/* FE Phy */
+			if((retVal = feSetDTE(dev,hwPort,state)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			break;
+
+		default:
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_NOT_SUPPORTED;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetDTEDetectStatus
+*
+* DESCRIPTION:
+*       This routine gets DTE status.
+*
+* INPUTS:
+* 		port - The logical port number
+*
+* OUTPUTS:
+*       status - GT_TRUE, if link partner needs DTE power.
+*				 GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetDTEDetectStatus
+(
+	IN  GT_QD_DEV *dev,
+	IN  GT_LPORT  port,
+	OUT GT_BOOL   *state
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 			u16Data,pageReg;
+	GT_STATUS		retVal = GT_OK;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+
+	DBG_INFO(("gprtGetDTEStatus Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* check if the port supports DTE */
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (!(phyInfo.flag & GT_PHY_DTE_CAPABLE))
+	{
+		DBG_INFO(("Not Supported\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch(phyInfo.dteType)
+	{
+		case GT_PHY_DTE_TYPE1:
+			/* FE Phy needs work-around */
+			if((retVal = hwReadPhyReg(dev,hwPort,17,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			*state = (u16Data & 0x8000)?GT_TRUE:GT_FALSE;
+
+			break;
+		case GT_PHY_DTE_TYPE2:
+		case GT_PHY_DTE_TYPE3:
+			if((retVal = hwReadPhyReg(dev,hwPort,27,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			*state = (u16Data & 0x10)?GT_TRUE:GT_FALSE;
+			
+			break;
+		case GT_PHY_DTE_TYPE4:
+			if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+			}
+				
+			if((retVal = hwReadPagedPhyReg(dev,hwPort,0,17,phyInfo.anyPage,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			*state = (u16Data & 0x4)?GT_TRUE:GT_FALSE;
+
+			if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+			}
+
+			break;
+		default:
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_NOT_SUPPORTED;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetDTEDetectDropWait
+*
+* DESCRIPTION:
+*       Once the PHY no longer detects that the link partner filter, the PHY
+*		will wait a period of time before clearing the power over Ethernet 
+*		detection status bit. The wait time is 5 seconds multiplied by the 
+*		given value.
+*
+* INPUTS:
+* 		port - The logical port number
+*       waitTime - 0 ~ 15 (unit of 4 sec.)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetDTEDetectDropWait
+(
+	IN  GT_QD_DEV *dev,
+	IN  GT_LPORT  port,
+	IN  GT_U16    waitTime
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 			u16Data;
+	GT_STATUS		retVal = GT_OK;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+	DBG_INFO(("gprtSetDTEDropWait Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* check if the port supports DTE */
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (!(phyInfo.flag & GT_PHY_DTE_CAPABLE))
+	{
+		DBG_INFO(("Not Supported\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch(phyInfo.dteType)
+	{
+		case GT_PHY_DTE_TYPE1:
+			if((retVal = hwReadPhyReg(dev,hwPort,22,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			u16Data = (u16Data & ~(0xF<<12)) | ((waitTime & 0xF) << 12);
+
+			if((retVal = hwWritePhyReg(dev,hwPort,22,u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			break;
+		case GT_PHY_DTE_TYPE2:
+		case GT_PHY_DTE_TYPE3:
+			if((retVal = hwReadPhyReg(dev,hwPort,27,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			u16Data = (u16Data & ~(0xF<<5)) | ((waitTime & 0xF) << 5);
+
+			if((retVal = hwWritePhyReg(dev,hwPort,27,u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			
+			break;
+		case GT_PHY_DTE_TYPE4:
+			if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+			}
+
+			if((retVal = hwReadPagedPhyReg(dev,hwPort,0,26,phyInfo.anyPage,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			u16Data = (u16Data & ~(0xF<<4)) | ((waitTime & 0xF) << 4);
+			if((retVal = hwWritePagedPhyReg(dev,hwPort,0,26,phyInfo.anyPage,u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+
+			if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+			}
+
+			break;
+		default:
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_NOT_SUPPORTED;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetDTEDetectDropWait
+*
+* DESCRIPTION:
+*       Once the PHY no longer detects that the link partner filter, the PHY
+*		will wait a period of time before clearing the power over Ethernet 
+*		detection status bit. The wait time is 5 seconds multiplied by the 
+*		returned value.
+*
+* INPUTS:
+* 		port - The logical port number
+*
+* OUTPUTS:
+*       waitTime - 0 ~ 15 (unit of 4 sec.)
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetDTEDetectDropWait
+(
+	IN  GT_QD_DEV *dev,
+	IN  GT_LPORT  port,
+	OUT GT_U16    *waitTime
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 			u16Data;
+	GT_STATUS		retVal = GT_OK;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+	DBG_INFO(("gprtSetDTEDropWait Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (!(phyInfo.flag & GT_PHY_DTE_CAPABLE))
+	{
+		DBG_INFO(("Not Supported\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch(phyInfo.dteType)
+	{
+		case GT_PHY_DTE_TYPE1:
+			if((retVal = hwReadPhyReg(dev,hwPort,22,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			u16Data = (u16Data >> 12) & 0xF;
+
+			break;
+		case GT_PHY_DTE_TYPE2:
+		case GT_PHY_DTE_TYPE3:
+			if((retVal = hwReadPhyReg(dev,hwPort,27,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			u16Data = (u16Data >> 5) & 0xF;
+
+			break;
+		case GT_PHY_DTE_TYPE4:
+			if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+			}
+
+			if((retVal = hwReadPagedPhyReg(dev,hwPort,0,26,phyInfo.anyPage,&u16Data)) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return retVal;
+			}
+			u16Data = (u16Data >> 4) & 0xF;
+
+			if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+			{
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+			}
+			break;
+		default:
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_NOT_SUPPORTED;
+	}
+
+	*waitTime = u16Data;
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetEnergyDetect
+*
+* DESCRIPTION:
+*       Energy Detect power down mode enables or disables the PHY to wake up on
+*		its own by detecting activity on the CAT 5 cable. 
+*
+* INPUTS:
+* 		port - The logical port number
+*       mode - GT_EDETECT_MODE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if invalid parameter is given
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS gprtSetEnergyDetect
+(
+	IN  GT_QD_DEV *dev,
+	IN  GT_LPORT  port,
+	IN  GT_EDETECT_MODE   mode
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 			u16Data;
+	GT_STATUS		retVal = GT_OK;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+	DBG_INFO(("gprtSetEnergyDetect Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (phyInfo.flag & GT_PHY_SERDES_CORE)
+	{
+	    DBG_INFO(("Not Supported.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+	else if (phyInfo.flag & GT_PHY_GIGABIT)
+	{
+		/* check if the mode is valid */
+		switch (mode)
+		{
+			case GT_EDETECT_OFF:
+				u16Data = 0;
+				break;
+			case GT_EDETECT_SENSE_PULSE:
+				u16Data = 3;
+				break;
+			case GT_EDETECT_SENSE:
+				u16Data = 2;
+				break;
+			default:
+			    DBG_INFO(("Invalid paramerter.\n"));
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_BAD_PARAM;
+		}
+
+		if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+		}
+
+		if((retVal = hwSetPagedPhyRegField(dev,hwPort,0,0x10,8,2,phyInfo.anyPage,u16Data)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return retVal;
+		}
+
+		if((retVal = hwPhyReset(dev,hwPort,0xFF)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return retVal;
+		}
+
+		if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+		}
+	}
+	else	/* it's a Fast Ethernet device */
+	{
+		/* check if the mode is valid */
+		switch (mode)
+		{
+			case GT_EDETECT_OFF:
+				u16Data = 0;
+				break;
+			case GT_EDETECT_SENSE_PULSE:
+				u16Data = 1;
+				break;
+			case GT_EDETECT_SENSE:
+			default:
+			    DBG_INFO(("Invalid paramerter.\n"));
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_BAD_PARAM;
+		}
+
+		if((retVal = hwSetPhyRegField(dev,hwPort,0x10,14,1,u16Data)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return retVal;
+		}
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetEnergyDetect
+*
+* DESCRIPTION:
+*       Energy Detect power down mode enables or disables the PHY to wake up on
+*		its own by detecting activity on the CAT 5 cable. 
+*
+* INPUTS:
+* 		port - The logical port number
+*
+* OUTPUTS:
+*       mode - GT_EDETECT_MODE type
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetEnergyDetect
+(
+	IN  GT_QD_DEV *dev,
+	IN  GT_LPORT  port,
+	OUT GT_EDETECT_MODE   *mode
+)
+{
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16 			u16Data;
+	GT_STATUS		retVal = GT_OK;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+	DBG_INFO(("gprtGetEnergyDetect Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (phyInfo.flag & GT_PHY_SERDES_CORE)
+	{
+	    DBG_INFO(("Not Supported.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+	else if (phyInfo.flag & GT_PHY_GIGABIT)
+	{
+		/* read the mode */
+
+		if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+		}
+
+		if((retVal = hwGetPagedPhyRegField(dev,hwPort,0,0x10,8,2,phyInfo.anyPage,&u16Data)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return retVal;
+		}
+
+		if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+		}
+
+		switch (u16Data)
+		{
+			case 0:
+			case 1:
+				*mode = GT_EDETECT_OFF;
+				break;
+			case 2:
+				*mode = GT_EDETECT_SENSE;
+				break;
+			case 3:
+				*mode = GT_EDETECT_SENSE_PULSE;
+				break;
+			default:
+			    DBG_INFO(("Unknown value (shouldn't happen).\n"));
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+		}
+
+	}
+	else	/* it's a Fast Ethernet device */
+	{
+		/* read the mode */
+		if((retVal = hwGetPhyRegField(dev,hwPort,0x10,14,1,&u16Data)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return retVal;
+		}
+
+		switch (u16Data)
+		{
+			case 0:
+				*mode = GT_EDETECT_OFF;
+				break;
+			case 1:
+				*mode = GT_EDETECT_SENSE_PULSE;
+				break;
+			default:
+			    DBG_INFO(("Unknown value (shouldn't happen).\n"));
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+		}
+
+	}
+
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSet1000TMasterMode
+*
+* DESCRIPTION:
+*       This routine sets the ports 1000Base-T Master mode and restart the Auto
+*		negotiation.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_1000T_MASTER_SLAVE structure
+*				autoConfig   - GT_TRUE for auto, GT_FALSE for manual setup.
+*				masterPrefer - GT_TRUE if Master configuration is preferred.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSet1000TMasterMode
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT     port,
+    IN  GT_1000T_MASTER_SLAVE   *mode
+)
+{
+	GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8			hwPort;         /* the physical port number     */
+	GT_U16		data;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+	DBG_INFO(("gprtSet1000TMasterMode Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (!(phyInfo.flag & GT_PHY_GIGABIT) || !(phyInfo.flag & GT_PHY_COPPER))
+	{
+		DBG_INFO(("Not Supported\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(mode->autoConfig == GT_TRUE)
+	{
+		if(mode->masterPrefer == GT_TRUE)
+		{
+			data = 0x1;
+		}
+		else
+		{
+			data = 0x0;
+		}
+	}
+	else
+	{
+		if(mode->masterPrefer == GT_TRUE)
+		{
+			data = 0x6;
+		}
+		else
+		{
+			data = 0x4;
+		}
+	}
+
+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	/* Set the Master Mode.    */
+	retVal = hwSetPagedPhyRegField(dev,hwPort,0,9,10,3,phyInfo.anyPage,data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return retVal;
+	}
+    else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	/* Restart Auto Negotiation */
+	if((retVal=hwSetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,9,1,1)) != GT_OK)
+	{
+		DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_CONTROL_REG,1));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGet1000TMasterMode
+*
+* DESCRIPTION:
+*       This routine retrieves 1000Base-T Master Mode
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_1000T_MASTER_SLAVE structure
+*				autoConfig   - GT_TRUE for auto, GT_FALSE for manual setup.
+*				masterPrefer - GT_TRUE if Master configuration is preferred.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGet1000TMasterMode
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT     port,
+    OUT GT_1000T_MASTER_SLAVE   *mode
+)
+{
+	GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U8			hwPort;         /* the physical port number     */
+	GT_U16		data;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+	DBG_INFO(("gprtGet1000TMasterMode Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (!(phyInfo.flag & GT_PHY_GIGABIT) || !(phyInfo.flag & GT_PHY_COPPER))
+	{
+		DBG_INFO(("Not Supported\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	/* Set the Master Mode.    */
+	retVal = hwGetPagedPhyRegField(dev,hwPort,0,9,10,3,phyInfo.anyPage,&data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return retVal;
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(data & 0x4)	/* Manual Mode */
+	{
+		mode->autoConfig = GT_FALSE;
+
+		if(data & 0x2)
+		{
+			mode->masterPrefer = GT_TRUE;
+		}
+		else
+		{
+			mode->masterPrefer = GT_FALSE;
+		}
+	}
+	else	/* Auto Mode */
+	{
+		mode->autoConfig = GT_TRUE;
+
+		if(data & 0x1)
+		{
+			mode->masterPrefer = GT_TRUE;
+		}
+		else
+		{
+			mode->masterPrefer = GT_FALSE;
+		}
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPhyLinkStatus
+*
+* DESCRIPTION:
+*       This routine retrieves the Link status.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*
+* OUTPUTS:
+*       linkStatus - GT_FALSE if link is not established,
+*				     GT_TRUE if link is established.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPhyLinkStatus
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+    IN GT_BOOL 	 *linkStatus
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			u16Data;
+	GT_PHY_INFO		phyInfo;
+
+    DBG_INFO(("gprtGetPhyLinkStatus Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+	 	return GT_NOT_SUPPORTED;
+	}
+
+	if((retVal=hwGetPhyRegField(dev,hwPort,17,10,1,&u16Data)) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return retVal;
+	}
+
+	BIT_2_BOOL(u16Data,*linkStatus);
+
+	gtSemGive(dev,dev->phyRegsSem);
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetPktGenEnable
+*
+* DESCRIPTION:
+*       This routine enables or disables Packet Generator.
+*       Link should be established first prior to enabling the packet generator,
+*       and generator will generate packets at the speed of the established link.
+*		When enables packet generator, the following information should be 
+*       provided:
+*           Payload Type:  either Random or 5AA55AA5
+*           Packet Length: either 64 or 1514 bytes
+*           Error Packet:  either Error packet or normal packet
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*       en      - GT_TRUE to enable, GT_FALSE to disable
+*       pktInfo - packet information(GT_PG structure pointer), if en is GT_TRUE.
+*                 ignored, if en is GT_FALSE
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPktGenEnable
+(
+	IN GT_QD_DEV *dev,
+	IN GT_LPORT  port,
+    IN GT_BOOL   en,
+    IN GT_PG     *pktInfo
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16 			data;
+	GT_BOOL			link;
+	GT_PHY_INFO		phyInfo;
+	GT_U8			page,reg, offset, len;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+    DBG_INFO(("gprtSetPktGenEnable Called.\n"));
+    
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(!(phyInfo.flag & GT_PHY_PKT_GENERATOR))
+	{
+	    DBG_INFO(("Not Supported.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (phyInfo.pktGenType)
+	{
+		case GT_PHY_PKTGEN_TYPE1:	/* 30_18.5:2 */
+				page = 18;
+				reg = 30;
+				offset = 2;
+				break;
+		case GT_PHY_PKTGEN_TYPE2:	/* 16_6.3:0 */
+				page = 6;
+				reg = 16;
+				offset = 0;
+				break;
+		case GT_PHY_PKTGEN_TYPE3:	/* 25.3:0 */
+				page = 0;
+				reg = 25;
+				offset = 0;
+				break;
+		default:
+			    DBG_INFO(("Unknown PKTGEN Type.\n"));
+				gtSemGive(dev,dev->phyRegsSem);
+				return GT_FAIL;
+	}
+
+	if (en)
+	{
+		if((retVal = gprtGetPhyLinkStatus(dev,port,&link)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+		}
+	
+		if (link == GT_FALSE)
+		{
+		    DBG_INFO(("Link should be on to run Packet Generator.\n"));
+			gtSemGive(dev,dev->phyRegsSem);
+			return GT_FAIL;
+		}
+
+		data = 0x8;
+
+        if (pktInfo->payload == GT_PG_PAYLOAD_5AA5)
+            data |= 0x4;
+
+        if (pktInfo->length == GT_PG_LENGTH_1514)
+            data |= 0x2;
+
+        if (pktInfo->tx == GT_PG_TX_ERROR)
+            data |= 0x1;
+
+        len = 4;
+	}
+	else
+	{
+		data = 0;
+		len = 1;
+		offset += 3;
+	}
+
+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if((retVal=hwSetPagedPhyRegField(dev,hwPort,
+				page,reg,offset,len,phyInfo.anyPage,data)) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return retVal;
+	}
+
+	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetSerdesMode
+*
+* DESCRIPTION:
+*       This routine reads Serdes Interface Mode.
+*
+* INPUTS:
+*		port -	The physical SERDES device address
+*				(logical port number is also supported for backward comparibility)
+*
+* OUTPUTS:
+*       mode    - Serdes Interface Mode
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       logical port number is supported only for the devices made production 
+*		before 2009. (88E6131, 88E6122, 88E6108, 88E6161, and 88E6165)
+*
+*******************************************************************************/
+GT_STATUS gprtGetSerdesMode
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+	IN  GT_SERDES_MODE *mode
+)
+{
+    GT_U16          u16Data;           /* The register's read data.    */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetSerdesMode Called.\n"));
+
+	if(!IS_IN_DEV_GROUP(dev,DEV_SERDES_CORE))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* check if input is logical port number */	
+    hwPort = GT_LPORT_2_PORT(port);
+	GT_GET_SERDES_PORT(dev,&hwPort);
+
+	if(hwPort > dev->maxPhyNum)
+	{
+		/* check if input is physical serdes address */	
+		if(dev->validSerdesVec & (1<<port))
+		{
+			hwPort = (GT_U8)port;
+		}
+		else
+			return GT_NOT_SUPPORTED;
+	}
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+    /* Get Phy Register. */
+    if(hwGetPhyRegField(dev,hwPort,16,0,2,&u16Data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+    }
+
+	*mode = u16Data;
+
+	gtSemGive(dev,dev->phyRegsSem);
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtSetSerdesMode
+*
+* DESCRIPTION:
+*       This routine sets Serdes Interface Mode.
+*
+* INPUTS:
+*		port -	The physical SERDES device address
+*				(logical port number is also supported for backward comparibility)
+*       mode    - Serdes Interface Mode
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       logical port number is supported only for the devices made production 
+*		before 2009. (88E6131, 88E6122, 88E6108, 88E6161, and 88E6165)
+*
+*******************************************************************************/
+GT_STATUS gprtSetSerdesMode
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+	IN  GT_SERDES_MODE mode
+)
+{
+    GT_U16          u16Data;           /* The register's read data.    */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_STATUS		retVal;
+
+    DBG_INFO(("gprtSetSerdesMode Called.\n"));
+
+	if(!IS_IN_DEV_GROUP(dev,DEV_SERDES_CORE))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+	
+	/* check if input is logical port number */	
+    hwPort = GT_LPORT_2_PORT(port);
+	GT_GET_SERDES_PORT(dev,&hwPort);
+
+	if(hwPort > dev->maxPhyNum)
+	{
+		/* check if input is physical serdes address */	
+		if(dev->validSerdesVec & (1<<port))
+		{
+			hwPort = (GT_U8)port;
+		}
+		else
+			return GT_NOT_SUPPORTED;
+	}
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	u16Data = mode;
+
+    /* Get Phy Register. */
+    if(hwSetPhyRegField(dev,hwPort,16,0,2,u16Data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+    }
+
+	retVal = hwPhyReset(dev,hwPort,0xFF);
+	gtSemGive(dev,dev->phyRegsSem);
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetPhyReg
+*
+* DESCRIPTION:
+*       This routine reads Phy Registers.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPhyReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+    IN  GT_U32	     regAddr,
+    OUT GT_U16	     *data
+)
+{
+    GT_U16          u16Data;           /* The register's read data.    */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPhyReg Called.\n"));
+
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+    /* Get Phy Register. */
+    if(hwReadPhyReg(dev,hwPort,(GT_U8)regAddr,&u16Data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+    }
+
+	*data = u16Data;
+
+	gtSemGive(dev,dev->phyRegsSem);
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtSetPhyReg
+*
+* DESCRIPTION:
+*       This routine writes Phy Registers.
+*
+* INPUTS:
+*		port -	The logical port number, unless SERDES device is accessed
+*				The physical address, if SERDES device is accessed
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPhyReg
+(
+    IN  GT_QD_DEV		*dev,
+    IN  GT_LPORT		port,
+    IN  GT_U32			regAddr,
+    IN  GT_U16			data
+)
+{
+    GT_U8           hwPort;         /* the physical port number     */
+    
+    DBG_INFO(("gprtSetPhyReg Called.\n"));
+
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+    /* Write to Phy Register */
+    if(hwWritePhyReg(dev,hwPort,(GT_U8)regAddr,data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+        return GT_FAIL;
+    }
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gprtGetPagedPhyReg
+*
+* DESCRIPTION:
+*       This routine reads phy register of the given page
+*
+* INPUTS:
+*		port 	- logical port to be read
+*		regAddr	- register offset to be read
+*		page	- page number to be read
+*
+* OUTPUTS:
+*		data	- value of the read register
+*
+* RETURNS:
+*       GT_OK   			- if read successed
+*       GT_FAIL   			- if read failed
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gprtGetPagedPhyReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U32  port,
+	IN	GT_U32  regAddr,
+	IN	GT_U32  page,
+    OUT GT_U16* data
+)
+{
+	GT_PHY_INFO		phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+	GT_U8			hwPort;
+
+    hwPort = GT_LPORT_2_PHY(port);
+	
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(hwReadPagedPhyReg(dev,hwPort,(GT_U8)page,
+								(GT_U8)regAddr,0,data) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gprtSetPagedPhyReg
+*
+* DESCRIPTION:
+*       This routine writes a value to phy register of the given page
+*
+* INPUTS:
+*		port 	- logical port to be read
+*		regAddr	- register offset to be read
+*		page	- page number to be read
+*		data	- value of the read register
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*       GT_OK   			- if read successed
+*       GT_FAIL   			- if read failed
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gprtSetPagedPhyReg
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U32 port,
+	IN	GT_U32 regAddr,
+	IN	GT_U32 page,
+    IN  GT_U16 data
+)
+{
+	GT_PHY_INFO		phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+	GT_U8			hwPort;
+
+    hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(hwWritePagedPhyReg(dev,hwPort,(GT_U8)page,
+								(GT_U8)regAddr,0,data) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return GT_OK;
+}
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyInt.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyInt.c
new file mode 100755
index 0000000..26819f9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPhyInt.c
@@ -0,0 +1,279 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPhyInt.h
+* 
+* DESCRIPTION:
+* API definitions for PHY interrupt handling 
+*
+* DEPENDENCIES:
+* None.
+*
+* FILE REVISION NUMBER:
+* $Revision: 10 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+#include <gtDrvConfig.h>
+
+/*******************************************************************************
+* gprtPhyIntEnable
+*
+* DESCRIPTION:
+* Enable/Disable one PHY Interrupt
+* This register determines whether the INT# pin is asserted when an interrupt 
+* event occurs. When an interrupt occurs, the corresponding bit is set and
+* remains set until register 19 is read via the SMI. When interrupt enable
+* bits are not set in register 18, interrupt status bits in register 19 are 
+* still set when the corresponding interrupt events occur. However, the INT# 
+* is not asserted.
+*
+* INPUTS:
+* port -   The logical port number, unless SERDES device is accessed
+*          The physical address, if SERDES device is accessed
+* intType - the type of interrupt to enable/disable. any combination of 
+*			GT_SPEED_CHANGED,
+*			GT_DUPLEX_CHANGED,
+*			GT_PAGE_RECEIVED,
+*			GT_AUTO_NEG_COMPLETED,
+*			GT_LINK_STATUS_CHANGED,
+*			GT_SYMBOL_ERROR,
+*			GT_FALSE_CARRIER,
+*			GT_FIFO_FLOW,
+*			GT_CROSSOVER_CHANGED,	( Copper only )
+*			GT_DOWNSHIFT_DETECT,	( for 1000M Copper only )
+*			GT_ENERGY_DETECT,		( for 1000M Copper only )
+*			GT_POLARITY_CHANGED, and ( Copper only )
+*			GT_JABBER				(Copper only )
+*
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* For 88E6131, 88E6122, and 88E6108 devices, Serdes port can be accessed using  
+* logical port number.
+* For 88E6161 and 88E6165 devices, Serdes port 5 (address 0xD) can be accessed
+* using logical port number, but not port 4 (since port 4 could be an internal 
+* PHY.)
+*******************************************************************************/
+
+
+GT_STATUS gprtPhyIntEnable
+(
+IN GT_QD_DEV    *dev,
+IN GT_LPORT	port,
+IN GT_U16	intType
+)
+{
+    GT_STATUS       retVal;      
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtPhyIntEnable Called.\n"));
+    
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PHY(port);
+
+	if((IS_IN_DEV_GROUP(dev,DEV_SERDES_CORE)) && (hwPort > 3))
+	{
+		if(!(dev->validSerdesVec & (1 << hwPort)))
+		{
+			if(!((IS_IN_DEV_GROUP(dev,DEV_88E6165_FAMILY)) && (hwPort == 4)))
+				GT_GET_SERDES_PORT(dev,&hwPort);
+		}
+		if(hwPort >= dev->maxPhyNum)
+		{
+			return GT_NOT_SUPPORTED;
+		}
+	}
+
+	/* check if the port is configurable */
+	if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	retVal = hwWritePhyReg(dev,hwPort, QD_PHY_INT_ENABLE_REG, intType);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    
+    return retVal;
+
+}
+
+/*******************************************************************************
+* gprtGetPhyIntStatus
+*
+* DESCRIPTION:
+* Check to see if a specific type of interrupt occured
+*
+* INPUTS:
+* port -   The logical port number, unless SERDES device is accessed
+*          The physical address, if SERDES device is accessed
+* intType - the type of interrupt which causes an interrupt.
+*			any combination of 
+*			GT_SPEED_CHANGED,
+*			GT_DUPLEX_CHANGED,
+*			GT_PAGE_RECEIVED,
+*			GT_AUTO_NEG_COMPLETED,
+*			GT_LINK_STATUS_CHANGED,
+*			GT_SYMBOL_ERROR,
+*			GT_FALSE_CARRIER,
+*			GT_FIFO_FLOW,
+*			GT_CROSSOVER_CHANGED,	( Copper only )
+*			GT_DOWNSHIFT_DETECT,	( for 1000M Copper only )
+*			GT_ENERGY_DETECT,		( for 1000M Copper only )
+*			GT_POLARITY_CHANGED, and ( Copper only )
+*			GT_JABBER				(Copper only )
+*
+* OUTPUTS:
+* None.
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* For 88E6131, 88E6122, and 88E6108 devices, Serdes port can be accessed using  
+* logical port number.
+* For 88E6161 and 88E6165 devices, Serdes port 5 (address 0xD) can be accessed
+* using logical port number, but not port 4 (since port 4 could be an internal 
+* PHY.)
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetPhyIntStatus
+(
+IN   GT_QD_DEV  *dev,
+IN   GT_LPORT   port,
+OUT  GT_U16*    intType
+)
+{
+    GT_STATUS       retVal;      
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPhyIntStatus Called.\n"));
+   
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PHY(port);
+	if((IS_IN_DEV_GROUP(dev,DEV_SERDES_CORE)) && (hwPort > 3))
+	{
+		if(!(dev->validSerdesVec & (1 << hwPort)))
+		{
+			if(!((IS_IN_DEV_GROUP(dev,DEV_88E6165_FAMILY)) && (hwPort == 4)))
+				GT_GET_SERDES_PORT(dev,&hwPort);
+		}
+		if(hwPort >= dev->maxPhyNum)
+		{
+			return GT_NOT_SUPPORTED;
+		}
+	}
+
+	/* check if the port is configurable */
+	if(!IS_CONFIGURABLE_PHY(dev,hwPort))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	retVal = hwReadPhyReg(dev,hwPort, QD_PHY_INT_STATUS_REG, intType);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPhyIntPortSummary
+*
+* DESCRIPTION:
+* Lists the ports that have active interrupts. It provides a quick way to 
+* isolate the interrupt so that the MAC or switch does not have to poll the
+* interrupt status register (19) for all ports. Reading this register does not
+* de-assert the INT# pin
+*
+* INPUTS:
+* none
+*
+* OUTPUTS:
+* GT_U8 *intPortMask - bit Mask with the bits set for the corresponding 
+* phys with active interrupt. E.g., the bit number 0 and 2 are set when 
+* port number 0 and 2 have active interrupt
+*
+* RETURNS:
+* GT_OK - on success
+* GT_FAIL - on error
+*
+* COMMENTS:
+* 88E3081 data sheet register 20
+* For 88E6165, 88E6375 devices, geventGetDevIntStatus should be used instead.
+*
+*******************************************************************************/
+
+GT_STATUS gprtGetPhyIntPortSummary
+(
+IN  GT_QD_DEV  *dev,
+OUT GT_U16     *intPortMask
+)
+{
+    GT_STATUS       retVal;      
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			portVec;
+
+    DBG_INFO(("gprtGetPhyIntPortSummary Called.\n"));
+   
+    /* translate LPORT 0 to hardware port */
+    hwPort = GT_LPORT_2_PORT(0);
+
+    *intPortMask=0;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_DEV_PHY_INTERRUPT))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_INTERNAL_GPHY))
+	{
+	    /* get the interrupt port summary from global register */
+	    retVal = hwGetGlobal2RegField(dev,QD_REG_PHYINT_SOURCE,0,dev->maxPorts,&portVec);
+		GT_GIG_PHY_INT_MASK(dev,portVec);
+		*intPortMask = (GT_U16)GT_PORTVEC_2_LPORTVEC(portVec);
+	}
+	else
+	{
+	    /* get the interrupt port summary from phy */
+		retVal = hwReadPhyReg(dev,hwPort, QD_PHY_INT_PORT_SUMMARY_REG, &portVec);
+		*intPortMask = (GT_U16)GT_PORTVEC_2_LPORTVEC(portVec);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	return retVal;
+
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPolicy.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPolicy.c
new file mode 100755
index 0000000..4db5745
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPolicy.c
@@ -0,0 +1,277 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPolicy.c
+*
+* DESCRIPTION:
+*       API definitions to handle Policy Mapping
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/*******************************************************************************
+* gprtSetPolicy
+*
+* DESCRIPTION:
+*       This routine sets the Policy for ports.
+*		Supported Policies are defined as GT_FRAME_POLICY as follows:
+*			FRAME_POLICY_NONE    - normal frame switching
+*			FRAME_POLICY_MIRROR  - mirror (copy) frame to MirrorDest port
+*			FRAME_POLICY_TRAP    - trap(re-direct) frame to the CPUDest port
+*			FRAME_POLICY_DISCARD - discard(filter) the frame
+*		Supported Policy types are defined as GT_POLICY_TYPE:
+*			POLICY_TYPE_DA - DA Policy Mapping
+*				DA Policy Mapping occurs when the DA of a frame is contained in 
+*				the ATU address database with an Entry State that indicates Policy.
+*			POLICY_TYPE_SA - SA Policy Mapping
+*				SA Policy Mapping occurs when the SA of a frame is contained in 
+*				the ATU address database with an Entry State that indicates Policy.
+*			POLICY_TYPE_VTU - VTU Policy Mapping
+*				VTU Policy Mapping occurs when the VID of a frame is contained in
+*				the VTU database with the VidPolicy is enabled.
+*			POLICY_TYPE_ETYPE - EtherType Policy Mapping
+*				EType Policy Mapping occurs when the EtherType of a frame matches
+*				the PortEType (see gprtSetPortEType API)
+*			POLICY_TYPE_PPPoE - PPPoE Policy Mapping
+*				PPPoE Policy Mapping occurs when the EtherType of a frame matches 0x8863
+*			POLICY_TYPE_VBAS - VBAS Policy Mapping
+*				VBAS Policy Mapping occurs when the EtherType of a frame matches 0x8200
+*			POLICY_TYPE_OPT82 - DHCP Option 82 Policy Mapping
+*				DHCP Option 82 Policy Mapping occurs when the ingressing frame is an
+*				IPv4 UDP with a UDP Destination port = 0x0043 or 0x0044, or an
+*				IPv6 UDP with a UDP Destination port = 0x0223 or 0x0222
+*			POLICY_TYPE_UDP - UDP Policy Mapping
+*				UDP Policy Mapping occurs when the ingressing frame is
+*				a Broadcast IPv4 UDP or a Multicast IPv6 UDP.
+*
+* INPUTS:
+*       port	- logical port number.
+*       type 	- policy type (GT_POLICY_TYPE)
+*       policy 	- policy (GT_FRAME_POLICY)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*       GT_BAD_PARAM     - on bad parameters
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPolicy
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT 	port,
+    IN  GT_POLICY_TYPE	type,
+	IN	GT_FRAME_POLICY	policy
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* Physical port.               */
+    GT_U8	    	offset;
+
+    DBG_INFO(("gprtSetPolicy Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_POLICY))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (policy)
+	{
+		case FRAME_POLICY_NONE:
+		case FRAME_POLICY_MIRROR:
+		case FRAME_POLICY_TRAP:
+		case FRAME_POLICY_DISCARD:
+			break;
+		default:
+	        DBG_INFO(("Bad Policy\n"));
+			return GT_BAD_PARAM;
+	}
+		
+	switch (type)
+	{
+		case POLICY_TYPE_DA:
+			offset = 14;
+			break;
+		case POLICY_TYPE_SA:
+			offset = 12;
+			break;
+		case POLICY_TYPE_VTU:
+			offset = 10;
+			break;
+		case POLICY_TYPE_ETYPE:
+			offset = 8;
+			break;
+		case POLICY_TYPE_PPPoE:
+			offset = 6;
+			break;
+		case POLICY_TYPE_VBAS:
+			offset = 4;
+			break;
+		case POLICY_TYPE_OPT82:
+			offset = 2;
+			break;
+		case POLICY_TYPE_UDP:
+			offset = 0;
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_POLICY_CONTROL, offset, 2, (GT_U16)policy);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtGetPolicy
+*
+* DESCRIPTION:
+*       This routine gets the Policy of the given policy type.
+*		Supported Policies are defined as GT_FRAME_POLICY as follows:
+*			FRAME_POLICY_NONE    - normal frame switching
+*			FRAME_POLICY_MIRROR  - mirror (copy) frame to MirrorDest port
+*			FRAME_POLICY_TRAP    - trap(re-direct) frame to the CPUDest port
+*			FRAME_POLICY_DISCARD - discard(filter) the frame
+*		Supported Policy types are defined as GT_POLICY_TYPE:
+*			POLICY_TYPE_DA - DA Policy Mapping
+*				DA Policy Mapping occurs when the DA of a frame is contained in 
+*				the ATU address database with an Entry State that indicates Policy.
+*			POLICY_TYPE_SA - SA Policy Mapping
+*				SA Policy Mapping occurs when the SA of a frame is contained in 
+*				the ATU address database with an Entry State that indicates Policy.
+*			POLICY_TYPE_VTU - VTU Policy Mapping
+*				VTU Policy Mapping occurs when the VID of a frame is contained in
+*				the VTU database with the VidPolicy is enabled.
+*			POLICY_TYPE_ETYPE - EtherType Policy Mapping
+*				EType Policy Mapping occurs when the EtherType of a frame matches
+*				the PortEType (see gprtSetPortEType API)
+*			POLICY_TYPE_PPPoE - PPPoE Policy Mapping
+*				PPPoE Policy Mapping occurs when the EtherType of a frame matches 0x8863
+*			POLICY_TYPE_VBAS - VBAS Policy Mapping
+*				VBAS Policy Mapping occurs when the EtherType of a frame matches 0x8200
+*			POLICY_TYPE_OPT82 - DHCP Option 82 Policy Mapping
+*				DHCP Option 82 Policy Mapping occurs when the ingressing frame is an
+*				IPv4 UDP with a UDP Destination port = 0x0043 or 0x0044, or an
+*				IPv6 UDP with a UDP Destination port = 0x0223 or 0x0222
+*			POLICY_TYPE_UDP - UDP Policy Mapping
+*				UDP Policy Mapping occurs when the ingressing frame is
+*				a Broadcast IPv4 UDP or a Multicast IPv6 UDP.
+*
+* INPUTS:
+*       port	- logical port number.
+*       type 	- policy type (GT_POLICY_TYPE)
+*
+* OUTPUTS:
+*       policy 	- policy (GT_FRAME_POLICY)
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*       GT_BAD_PARAM     - on bad parameters
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPolicy
+(
+    IN  GT_QD_DEV 	*dev,
+    IN  GT_LPORT 	port,
+    IN  GT_POLICY_TYPE	type,
+	OUT GT_FRAME_POLICY	*policy
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* Physical port.               */
+    GT_U8	    	offset;
+	GT_U16			data;
+
+    DBG_INFO(("gprtGetPolicy Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_POLICY))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+	
+	switch (type)
+	{
+		case POLICY_TYPE_DA:
+			offset = 14;
+			break;
+		case POLICY_TYPE_SA:
+			offset = 12;
+			break;
+		case POLICY_TYPE_VTU:
+			offset = 10;
+			break;
+		case POLICY_TYPE_ETYPE:
+			offset = 8;
+			break;
+		case POLICY_TYPE_PPPoE:
+			offset = 6;
+			break;
+		case POLICY_TYPE_VBAS:
+			offset = 4;
+			break;
+		case POLICY_TYPE_OPT82:
+			offset = 2;
+			break;
+		case POLICY_TYPE_UDP:
+			offset = 0;
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_POLICY_CONTROL, offset, 2, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	*policy = (GT_FRAME_POLICY)data;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortCtrl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortCtrl.c
new file mode 100755
index 0000000..3a202b3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortCtrl.c
@@ -0,0 +1,6821 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPortCtrl.c
+*
+* DESCRIPTION:
+*       API implementation for switch port control.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/*******************************************************************************
+* gprtSetForceFc
+*
+* DESCRIPTION:
+*       This routine set the force flow control state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*       force - GT_TRUE for force flow control  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetForceFc
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    force
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_PORT_STP_STATE  state;
+
+    DBG_INFO(("gprtSetForceFc Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (IS_IN_DEV_GROUP(dev,DEV_FC_WITH_VALUE))
+	{
+		if(force)
+			data = 3;
+		else
+			data = 0;
+			
+		retVal = hwSetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,6,2,data);
+		if(retVal != GT_OK)
+		{
+			DBG_INFO(("Failed.\n"));
+		}
+		else
+		{
+			DBG_INFO(("OK.\n"));
+		}
+		return retVal;		
+	}
+
+	/* Port should be disabled before Set Force Flow Control bit */
+	retVal = gstpGetPortState(dev,port, &state);
+    if(retVal != GT_OK)
+	{
+	    DBG_INFO(("gstpGetPortState failed.\n"));
+		return retVal;
+	}
+
+	retVal = gstpSetPortState(dev,port, GT_PORT_DISABLE);
+    if(retVal != GT_OK)
+	{
+	    DBG_INFO(("gstpSetPortState failed.\n"));
+		return retVal;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(force, data);
+
+    /* Set the force flow control bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,15,1,data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	/* Restore original stp state. */
+	if(gstpSetPortState(dev,port, state) != GT_OK)
+	{
+	    DBG_INFO(("gstpSetPortState failed.\n"));
+		return GT_FAIL;
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetForceFc
+*
+* DESCRIPTION:
+*       This routine get the force flow control state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       force - GT_TRUE for force flow control  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetForceFc
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_BOOL    *force
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetForceFc Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (IS_IN_DEV_GROUP(dev,DEV_FC_WITH_VALUE))
+	{
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_PCS_CONTROL,6,2,&data);
+		if(retVal != GT_OK)
+		{
+			DBG_INFO(("Failed.\n"));
+		}
+		else
+		{
+			DBG_INFO(("OK.\n"));
+		}
+
+		if(data & 0x1)
+			*force = GT_TRUE;
+		else
+			*force = GT_FALSE;
+			
+		return retVal;		
+	}
+
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,15,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *force);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetUseCoreTag
+*
+* DESCRIPTION:
+*		This routine set the UseCoreTag bit in Port Control Register.
+*		When this bit is cleared to a zero, ingressing frames are considered
+*		Tagged if the 16-bits following the frame's Source Address is 0x8100.
+*		When this bit is set to a one, ingressing frames are considered Tagged
+*		if the 16-bits following the frame's Source Address is equal to the 
+*		CoreTag register value.
+*
+* INPUTS:
+*       port  - the logical port number.
+*       force - GT_TRUE for force flow control  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetUseCoreTag
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    force
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetUseCoreTag Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CORE_TAG))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(force, data);
+
+    /* Set the UseCoreTag bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,15,1,data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetUseCoreTag
+*
+* DESCRIPTION:
+*       This routine get the Use Core Tag state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       force - GT_TRUE for using core tag register  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetUseCoreTag
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_BOOL    *force
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetUseCoreTag Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_CORE_TAG))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the UseCoreTag bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,15,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *force);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetTrailerMode
+*
+* DESCRIPTION:
+*       This routine set the egress trailer mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE for add trailer or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetTrailerMode
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetTrailerMode Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRAILER|DEV_TRAILER_P5|DEV_TRAILER_P4P5))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if(hwPort < 4)
+	{
+	    /* check if device supports this feature for this port */
+		if (IS_IN_DEV_GROUP(dev,DEV_TRAILER_P5|DEV_TRAILER_P4P5))
+		{
+	        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+    	    return GT_NOT_SUPPORTED;
+		}
+	}
+	else if(hwPort == 4)
+	{
+	    /* check if device supports this feature for this port*/
+		if (IS_IN_DEV_GROUP(dev,DEV_TRAILER_P5))
+		{
+	        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+    	    return GT_NOT_SUPPORTED;
+		}
+	}
+
+    /* Set the trailer mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,14,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetTrailerMode
+*
+* DESCRIPTION:
+*       This routine get the egress trailer mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for add trailer or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetTrailerMode
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_BOOL    *mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetTrailerMode Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRAILER|DEV_TRAILER_P5|DEV_TRAILER_P4P5))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if(hwPort < 4)
+	{
+	    /* check if device supports this feature for this port */
+		if (IS_IN_DEV_GROUP(dev,DEV_TRAILER_P5|DEV_TRAILER_P4P5))
+		{
+	        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+    	    return GT_NOT_SUPPORTED;
+		}
+	}
+	else if(hwPort == 4)
+	{
+	    /* check if device supports this feature for this port */
+		if (IS_IN_DEV_GROUP(dev,DEV_TRAILER_P5))
+		{
+	        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+    	    return GT_NOT_SUPPORTED;
+		}
+	}
+
+    /* Get the Trailer mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,14,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+
+/*******************************************************************************
+* gprtSetIngressMode
+*
+* DESCRIPTION:
+*       This routine set the ingress mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the ingress mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIngressMode
+(
+    IN  GT_QD_DEV      *dev,
+    IN GT_LPORT        port,
+    IN GT_INGRESS_MODE mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetIngressMode Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Gigabit Switch does not support this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* check if device supports this feature */
+    switch (mode)
+    {
+        case (GT_UNMODIFY_INGRESS):
+            break;
+
+        case (GT_TRAILER_INGRESS):
+		    if(!(IS_IN_DEV_GROUP(dev,DEV_TRAILER|DEV_TRAILER_P5|DEV_TRAILER_P4P5)))
+			{
+			    DBG_INFO(("Given ingress mode is not supported by this device\n"));
+				return GT_NOT_SUPPORTED;
+			}
+            break;
+
+        case (GT_UNTAGGED_INGRESS):
+		    if(!(IS_IN_DEV_GROUP(dev,DEV_TAGGING)))
+			{
+			    DBG_INFO(("Given ingress mode is not supported by this device\n"));
+				return GT_NOT_SUPPORTED;
+			}
+            break;
+
+        case (GT_CPUPORT_INGRESS):
+		    if(!(IS_IN_DEV_GROUP(dev,DEV_IGMP_SNOOPING)))
+			{
+			    DBG_INFO(("Given ingress mode is not supported by this device\n"));
+				return GT_NOT_SUPPORTED;
+			}
+
+			if(hwPort != GT_LPORT_2_PORT(dev->cpuPortNum))
+			{
+			    DBG_INFO(("Given ingress mode is supported by CPU port only\n"));
+				return GT_NOT_SUPPORTED;
+			}
+
+            break;
+
+        default:
+            DBG_INFO(("Failed.\n"));
+            return GT_FAIL;
+    }
+
+    /* Set the Ingress Mode.        */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,8,2,(GT_U16)mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetIngressMode
+*
+* DESCRIPTION:
+*       This routine get the ingress mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - the ingress mode.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIngressMode
+(
+    IN  GT_QD_DEV      *dev,
+    IN  GT_LPORT        port,
+    OUT GT_INGRESS_MODE *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetIngressMode Called.\n"));
+
+	/* Gigabit Switch does not support this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    /* Get the Ingress Mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 8, 2,&data);
+    *mode = data;
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetMcRateLimit
+*
+* DESCRIPTION:
+*       This routine set the port multicast rate limit.
+*
+* INPUTS:
+*       port - the logical port number.
+*       rate - GT_TRUE to Enable, GT_FALSE for otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetMcRateLimit
+(
+    IN  GT_QD_DEV   *dev,
+    IN GT_LPORT     port,
+    IN GT_MC_RATE   rate
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetMcRateLimit Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* this feature only exits in 6051, 6052, and 6012. It is replace with
+     * Rate Cotrol Register in the future products, starting from clippership
+     */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_MC_RATE_PERCENT)) != GT_OK)
+        return retVal;
+
+    /* Set the multicast rate limit.    */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,2,2,(GT_U16)rate);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetMcRateLimit
+*
+* DESCRIPTION:
+*       This routine Get the port multicast rate limit.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       rate - GT_TRUE to Enable, GT_FALSE for otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMcRateLimit
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT    port,
+    OUT GT_MC_RATE  *rate
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read data        */
+
+    DBG_INFO(("gprtGetMcRateLimit Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* this feature only exits in 6051, 6052, and 6012. It is replace with
+     * Rate Cotrol Register in the future products, starting from clippership
+     */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_MC_RATE_PERCENT)) != GT_OK)
+        return retVal;
+
+    /* Get the multicast rate limit.    */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 2, 2,&data);
+    *rate = data;
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/* the following two APIs are added to support fullsail and clippership */
+
+/*******************************************************************************
+* gprtSetIGMPSnoop
+*
+* DESCRIPTION:
+* 		This routine set the IGMP Snoop. When set to one and this port receives
+*		IGMP frame, the frame is switched to the CPU port, overriding all other 
+*		switching decisions, with exception for CPU's Trailer.
+*		CPU port is determined by the Ingress Mode bits. A port is considered 
+*		the CPU port if its Ingress Mode are either GT_TRAILER_INGRESS or 
+*		GT_CPUPORT_INGRESS.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for IGMP Snoop or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIGMPSnoop
+(
+    IN  GT_QD_DEV   *dev,
+    IN GT_LPORT     port,
+    IN GT_BOOL      mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetIGMPSnoop Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_IGMP_SNOOPING)) != GT_OK)
+      return retVal;
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the IGMP Snooping mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,10,1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetIGMPSnoop
+*
+* DESCRIPTION:
+*       This routine get the IGMP Snoop mode.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE: IGMP Snoop enabled
+*	       GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIGMPSnoop
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT    port,
+    OUT GT_BOOL     *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetIGMPSnoop Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_IGMP_SNOOPING)) != GT_OK)
+      return retVal;
+
+    /* Get the Ingress Mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 10, 1, &data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+/* the following two APIs are added to support clippership */
+
+/*******************************************************************************
+* gprtSetHeaderMode
+*
+* DESCRIPTION:
+*       This routine set ingress and egress header mode of a switch port. 
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE for header mode  or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetHeaderMode
+(
+    IN  GT_QD_DEV   *dev,
+    IN GT_LPORT     port,
+    IN GT_BOOL      mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetHeaderMode Called.\n"));
+
+    /* only devices beyond quarterdeck (6052) has this feature */
+    /* Fullsail (DEV_QD_88E6502) is an exception, and does not support this feature */
+    if(IS_VALID_API_CALL(dev,port, DEV_HEADER|DEV_HEADER_P5|DEV_HEADER_P4P5) != GT_OK)
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if(hwPort < 4)
+	{
+		if (IS_IN_DEV_GROUP(dev,DEV_HEADER_P5|DEV_HEADER_P4P5))
+		{
+	        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+    	    return GT_NOT_SUPPORTED;
+		}
+	}
+	else if(hwPort == 4)
+	{
+		if (IS_IN_DEV_GROUP(dev,DEV_HEADER_P5))
+		{
+	        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+    	    return GT_NOT_SUPPORTED;
+		}
+	}
+
+    /* Set the header mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,11,1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetHeaderMode
+*
+* DESCRIPTION:
+*       This routine gets ingress and egress header mode of a switch port. 
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE: header mode enabled
+*	       GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHeaderMode
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT    port,
+    OUT GT_BOOL     *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetHeaderMode Called.\n"));
+
+    /* only devices beyond quarterdeck (6052) has this feature */
+    /* Fullsail (DEV_QD_88E602) is an exception, and does not support this feature */
+    if(IS_VALID_API_CALL(dev,port, DEV_HEADER|DEV_HEADER_P5|DEV_HEADER_P4P5) != GT_OK)
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if(hwPort < 4)
+	{
+		if (IS_IN_DEV_GROUP(dev,DEV_HEADER_P5|DEV_HEADER_P4P5))
+		{
+	        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+    	    return GT_NOT_SUPPORTED;
+		}
+	}
+	else if(hwPort == 4)
+	{
+		if (IS_IN_DEV_GROUP(dev,DEV_HEADER_P5))
+		{
+	        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+    	    return GT_NOT_SUPPORTED;
+		}
+	}
+
+    /* Get the Header Mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 11, 1, &data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+/* the following four APIs are added to support Octane */
+
+/*******************************************************************************
+* gprtSetProtectedMode
+*
+* DESCRIPTION:
+*       This routine set protected mode of a switch port. 
+*		When this mode is set to GT_TRUE, frames are allowed to egress port
+*		defined by the 802.1Q VLAN membership for the frame's VID 'AND'
+*		by the port's VLANTable if 802.1Q is enabled on the port. Both must
+*		allow the frame to Egress.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE for protected mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetProtectedMode
+(
+    IN  GT_QD_DEV   *dev,
+    IN GT_LPORT     port,
+    IN GT_BOOL      mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetProtectedMode Called.\n"));
+
+	/* Check if this feature is supported */
+    if(IS_VALID_API_CALL(dev,port, DEV_PORT_SECURITY) != GT_OK)
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_CROSS_CHIP_VLAN))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Set the protected mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,3,1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetProtectedMode
+*
+* DESCRIPTION:
+*       This routine gets protected mode of a switch port. 
+*		When this mode is set to GT_TRUE, frames are allowed to egress port
+*		defined by the 802.1Q VLAN membership for the frame's VID 'AND'
+*		by the port's VLANTable if 802.1Q is enabled on the port. Both must
+*		allow the frame to Egress.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE: header mode enabled
+*	       GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetProtectedMode
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT    port,
+    OUT GT_BOOL     *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetProtectedMode Called.\n"));
+
+    if(IS_VALID_API_CALL(dev,port, DEV_PORT_SECURITY) != GT_OK)
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_CROSS_CHIP_VLAN))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the protected Mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 3, 1, &data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtSetForwardUnknown
+*
+* DESCRIPTION:
+*       This routine set Forward Unknown mode of a switch port. 
+*		When this mode is set to GT_TRUE, normal switch operation occurs.
+*		When this mode is set to GT_FALSE, unicast frame with unknown DA addresses
+*		will not egress out this port.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE for protected mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetForwardUnknown
+(
+    IN  GT_QD_DEV   *dev,
+    IN GT_LPORT     port,
+    IN GT_BOOL      mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetForwardUnknown Called.\n"));
+
+    if(IS_VALID_API_CALL(dev,port, DEV_PORT_SECURITY|DEV_EGRESS_FLOOD) != GT_OK)
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Set the forward unknown mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,2,1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetForwardUnknown
+*
+* DESCRIPTION:
+*       This routine gets Forward Unknown mode of a switch port. 
+*		When this mode is set to GT_TRUE, normal switch operation occurs.
+*		When this mode is set to GT_FALSE, unicast frame with unknown DA addresses
+*		will not egress out this port.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE: header mode enabled
+*	       GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetForwardUnknown
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT    port,
+    OUT GT_BOOL     *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetForwardUnknown Called.\n"));
+
+    if(IS_VALID_API_CALL(dev,port, DEV_PORT_SECURITY|DEV_EGRESS_FLOOD) != GT_OK)
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the forward unknown Mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 2, 1, &data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetDropOnLock
+*
+* DESCRIPTION:
+*		This routine set the Drop on Lock. When set to one, Ingress frames will
+*		be discarded if their SA field is not in the ATU's address database.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for Unknown SA drop or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDropOnLock
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+)
+{
+	GT_U16          data;           
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtSetDropOnLock Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CASCADE_PORT))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate BOOL to binary */
+	BOOL_2_BIT(mode, data);
+
+	/* Set the DropOnLock mode.            */
+	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,14,1,data);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+	return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetDropOnLock
+*
+* DESCRIPTION:
+*		This routine gets DropOnLock mode.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: DropOnLock enabled,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDropOnLock
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16          data;           /* to keep the read valve       */
+
+	DBG_INFO(("gprtGetDropOnLock Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CASCADE_PORT))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get the DropOnLock Mode.            */
+	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 14, 1, &data);
+
+	/* translate binary to BOOL  */
+	BIT_2_BOOL(data, *mode);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtSetDoubleTag
+*
+* DESCRIPTION:
+*		This routine set the Ingress Double Tag Mode. When set to one, 
+*		ingressing frames are examined to see if they contain an 802.3ac tag.
+*		If they do, the tag is removed and then the frame is processed from
+*		there (i.e., removed tag is ignored). Essentially, untagged frames
+*		remain untagged, single tagged frames become untagged and double tagged
+*		frames become single tagged.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for DoulbeTag mode or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDoubleTag
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+)
+{
+	GT_U16          data;           
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtSetDoubleTag Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_INGRESS_DOUBLE_TAGGING))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate BOOL to binary */
+	BOOL_2_BIT(mode, data);
+
+	/* Set the DoubleTag mode.            */
+	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,9,1,data);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+	return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetDoubleTag
+*
+* DESCRIPTION:
+*		This routine gets DoubleTag mode.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: DoubleTag enabled,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDoubleTag
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16          data;           /* to keep the read valve       */
+
+	DBG_INFO(("gprtGetDoubleTag Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_INGRESS_DOUBLE_TAGGING))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get the DoubleTag Mode.            */
+	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 9, 1, &data);
+
+	/* translate binary to BOOL  */
+	BIT_2_BOOL(data, *mode);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetInterswitchPort
+*
+* DESCRIPTION:
+*		This routine set Interswitch Port. When set to one, 
+*		it indicates this port is a interswitch port used to communicated with
+*		CPU or to cascade with another switch device.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for Interswitch port or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetInterswitchPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+)
+{
+	GT_U16          data;           
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtSetInterswitchPort Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CASCADE_PORT))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate BOOL to binary */
+	BOOL_2_BIT(mode, data);
+
+	/* Set the InterswitchPort.            */
+	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,8,1,data);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+	return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetInterswithPort
+*
+* DESCRIPTION:
+*		This routine gets InterswitchPort.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: This port is interswitch port,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetInterswitchPort
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16          data;           /* to keep the read valve       */
+
+	DBG_INFO(("gprtGetInterswitchPort Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CASCADE_PORT))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get the InterswitchPort Mode.            */
+	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 8, 1, &data);
+
+	/* translate binary to BOOL  */
+	BIT_2_BOOL(data, *mode);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtSetLearnDisable
+*
+* DESCRIPTION:
+*		This routine enables/disables automatic learning of new source MAC
+*		addresses on the given port ingress
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for disable or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetLearnDisable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+)
+{
+	GT_U16          data;           
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtSetLearnDisable Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate BOOL to binary */
+	BOOL_2_BIT(mode, data);
+
+	/* Set the LearnDisable mode.            */
+	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_VLAN_MAP,11,1,data);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetLearnDisable
+*
+* DESCRIPTION:
+*		This routine gets LearnDisable setup
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: Learning disabled on the given port ingress frames,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetLearnDisable
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16          data;           /* to keep the read valve       */
+
+	DBG_INFO(("gprtGetLearnDisable Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get the LearnDisable Mode.            */
+	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_VLAN_MAP, 11, 1, &data);
+
+	/* translate binary to BOOL  */
+	if(data == 1)
+		*mode = GT_FALSE;
+	else
+		*mode = GT_TRUE;
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	return retVal;
+}
+/*******************************************************************************
+* gprtSetLearnEnable
+*
+* DESCRIPTION:
+*		This routine enables/disables automatic learning of new source MAC
+*		addresses on the given port ingress
+*
+* INPUTS:
+*		port - the logical port number.
+*		enable - GT_TRUE for disable or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetLearnEnable
+( 
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		enable
+)
+{
+    GT_STATUS retVal = GT_OK;
+    GT_U16 data;           /* Data to be set into the register. */
+    GT_BOOL mode;
+
+    DBG_INFO(("gprtSetLearnEnable Called.\n"));	
+
+	if(enable == GT_FALSE)
+	{
+		mode = GT_TRUE;
+		data = 1;
+	}
+	else
+	{
+		mode = GT_FALSE;
+		data = 0;
+	}	
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		/*set MAC learn diable */
+		retVal = gprtSetLearnDisable(dev, port, mode);
+		if(retVal != GT_OK)
+		{
+		    DBG_INFO(("Failed.\n"));
+		  	return retVal;
+		}
+
+	}
+	else
+	{
+	    /* Set the global learn enable bit.*/
+    	retVal = hwSetGlobalRegField(dev,QD_REG_ATU_CONTROL,14,1,data);
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	}	
+    DBG_INFO(("OK.\n"));
+    return retVal;
+}
+/*******************************************************************************
+* gfdbGetLearnEnable
+*
+* DESCRIPTION:
+*       Get automatic learning status of new source MAC addresses on port ingress.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*       enable - GT_TRUE if enabled  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetLearnEnable
+(
+    IN GT_QD_DEV  *dev,
+	 IN GT_LPORT		port,    
+    OUT GT_BOOL  *enble
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gprtGetLearnEnable Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		retVal = gprtGetLearnDisable(dev, port, enble);
+		if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	}
+	else
+	{
+	    /* Get the Learn Enable bit.            */
+    	retVal = hwGetGlobalRegField(dev,QD_REG_ATU_CONTROL,14,1,&data);
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+		if(data == 1)
+			*enble = GT_FALSE;
+		else
+			*enble = GT_TRUE;
+	}	
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtSetIgnoreFCS
+*
+* DESCRIPTION:
+*		This routine sets FCS Ignore mode. When this bit is set to a one,
+*		the last four bytes of frames received on this port are overwritten with
+*		a good CRC and the frames will be accepted by the switch.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for ignore FCS or GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIgnoreFCS
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL 		mode
+)
+{
+	GT_U16          data;           
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtSetIgnoreFCS Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate BOOL to binary */
+	BOOL_2_BIT(mode, data);
+
+	/* Set the IgnoreFCS mode.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_ENHANCED_FE_SWITCH))
+	{
+		retVal = hwSetPortRegField(dev,hwPort,QD_REG_PORT_CONTROL2,15,1,data );
+	}
+	else
+	{
+		retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_VLAN_MAP,10,1,data);
+	}
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetIgnoreFCS
+*
+* DESCRIPTION:
+*		This routine gets Ignore FCS setup
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE: Ignore FCS on the given port's ingress frames,
+*				 GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIgnoreFCS
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetIgnoreFCS Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the IgnoreFCS Mode.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_ENHANCED_FE_SWITCH))
+	{
+		retVal = hwGetPortRegField(dev,hwPort,QD_REG_PORT_CONTROL2,15,1,&data );
+	}
+	else
+	{
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_VLAN_MAP, 10, 1, &data);
+	}
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetVTUPriOverride
+*
+* DESCRIPTION:
+*		VTU Priority Override. The following modes are supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's VID (in the VTU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's VID (in the VTU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_PRI_OVERRIDE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if mode is invalid
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtSetVTUPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_PRI_OVERRIDE		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetVTUPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	switch (mode)
+	{
+		case PRI_OVERRIDE_NONE:
+			data = 0;
+			break;
+		case PRI_OVERRIDE_FRAME_QUEUE:
+			if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+				data = 3;
+			}
+			else
+			{
+				data = 1;
+			}
+			break;
+		case PRI_OVERRIDE_FRAME:
+			if (!IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+		        DBG_INFO(("Bad Parameter\n"));
+				return GT_BAD_PARAM;
+			}
+			data = 1;
+			break;
+		case PRI_OVERRIDE_QUEUE:
+			if (!IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+		        DBG_INFO(("Bad Parameter\n"));
+				return GT_BAD_PARAM;
+			}
+			data = 2;
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    /* Set the VTUPri Override mode.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+	{
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PRI_OVERRIDE,10,2,data);
+	}
+	else
+	{
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,14,1,data);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetVTUPriOverride
+*
+* DESCRIPTION:
+*		VTU Priority Override. The following modes are supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's VID (in the VTU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's VID (in the VTU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_PRI_OVERRIDE type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtGetVTUPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_PRI_OVERRIDE		*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetVTUPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the VTUPriOverride Mode.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PRI_OVERRIDE,10,2,&data);
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 14, 1, &data);
+		if(data == 1) 
+			data = 3;
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	switch (data)
+	{
+		case 0:
+			*mode = PRI_OVERRIDE_NONE;
+			break;
+		case 3:
+			*mode = PRI_OVERRIDE_FRAME_QUEUE;
+			break;
+		case 1:
+			*mode = PRI_OVERRIDE_FRAME;
+			break;
+		case 2:
+			*mode = PRI_OVERRIDE_QUEUE;
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtSetSAPriOverride
+*
+* DESCRIPTION:
+*		SA Priority Override. The following mode is supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's SA (in the ATU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's SA (in the ATU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_PRI_OVERRIDE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if mode is invalid
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtSetSAPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetSAPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	switch (mode)
+	{
+		case PRI_OVERRIDE_NONE:
+			data = 0;
+			break;
+		case PRI_OVERRIDE_FRAME_QUEUE:
+			if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+				data = 3;
+			}
+			else
+			{
+				data = 1;
+			}
+			break;
+		case PRI_OVERRIDE_FRAME:
+			if (!IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+		        DBG_INFO(("Bad Parameter\n"));
+				return GT_BAD_PARAM;
+			}
+			data = 1;
+			break;
+		case PRI_OVERRIDE_QUEUE:
+			if (!IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+		        DBG_INFO(("Bad Parameter\n"));
+				return GT_BAD_PARAM;
+			}
+			data = 2;
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    /* Set the SAPriOverride mode.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+	{
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PRI_OVERRIDE,12,2,data);
+	}
+	else
+	{
+    	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,13,1,data);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetSAPriOverride
+*
+* DESCRIPTION:
+*		SA Priority Override. The following mode is supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's SA (in the ATU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's SA (in the ATU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_PRI_OVERRIDE type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtGetSAPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_PRI_OVERRIDE		*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetSAPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the SAPriOverride Mode.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PRI_OVERRIDE,12,2,&data);
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 13, 1, &data);
+		if(data == 1) 
+			data = 3;
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	switch (data)
+	{
+		case 0:
+			*mode = PRI_OVERRIDE_NONE;
+			break;
+		case 3:
+			*mode = PRI_OVERRIDE_FRAME_QUEUE;
+			break;
+		case 1:
+			*mode = PRI_OVERRIDE_FRAME;
+			break;
+		case 2:
+			*mode = PRI_OVERRIDE_QUEUE;
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtSetDAPriOverride
+*
+* DESCRIPTION:
+*		DA Priority Override. The following mode is supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's DA (in the ATU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's DA (in the ATU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_PRI_OVERRIDE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if mode is invalid
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtSetDAPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_PRI_OVERRIDE		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetDAPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	switch (mode)
+	{
+		case PRI_OVERRIDE_NONE:
+			data = 0;
+			break;
+		case PRI_OVERRIDE_FRAME_QUEUE:
+			if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+				data = 3;
+			}
+			else
+			{
+				data = 1;
+			}
+			break;
+		case PRI_OVERRIDE_FRAME:
+			if (!IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+		        DBG_INFO(("Bad Parameter\n"));
+				return GT_BAD_PARAM;
+			}
+			data = 1;
+			break;
+		case PRI_OVERRIDE_QUEUE:
+			if (!IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+			{
+		        DBG_INFO(("Bad Parameter\n"));
+				return GT_BAD_PARAM;
+			}
+			data = 2;
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    /* Set the DAPriOverride mode.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+	{
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PRI_OVERRIDE,14,2,data);
+	}
+	else
+	{
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,12,1,data);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetDAPriOverride
+*
+* DESCRIPTION:
+*		DA Priority Override. The following mode is supported:
+*			PRI_OVERRIDE_NONE -
+*				Normal frame priority processing occurs.
+*			PRI_OVERRIDE_FRAME -
+*				Priority assigned to the frame's DA (in the ATU table) is used
+*				to overwite the frame's FPri (frame priority).
+*				If the frame egresses tagged, the priority in the frame will be
+*				this new priority value.
+*			PRI_OVERRIDE_QUEUE -
+*				Priority assigned to the frame's DA (in the ATU table) is used
+*				to overwite the frame's QPri (queue priority).
+*				QPri is used internally to map the frame to one of the egress
+*				queues inside the switch.
+*			PRI_OVERRIDE_FRAME_QUEUE -
+*				Both frame and queue overrides take place on the frame.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_PRI_OVERRIDE type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		PRI_OVERRIDE_FRAME and PRI_OVERRIDE_QUEUE modes are supported only on
+*		certain switch device. Please refer to the device datasheet.
+*
+*******************************************************************************/
+GT_STATUS gprtGetDAPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_PRI_OVERRIDE		*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetDAPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the DAPriOverride Mode.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_EXT_PRIORITY_OVERRIDE))
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PRI_OVERRIDE,14,2,&data);
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 12, 1, &data);
+		if(data == 1) 
+			data = 3;
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	switch (data)
+	{
+		case 0:
+			*mode = PRI_OVERRIDE_NONE;
+			break;
+		case 3:
+			*mode = PRI_OVERRIDE_FRAME_QUEUE;
+			break;
+		case 1:
+			*mode = PRI_OVERRIDE_FRAME;
+			break;
+		case 2:
+			*mode = PRI_OVERRIDE_QUEUE;
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtSetCPUPort
+*
+* DESCRIPTION:
+*		This routine sets CPU Port number. When Snooping is enabled on this port
+*		or when this port is configured as an Interswitch Port and it receives a 
+*		To_CPU frame, the switch needs to know what port on this device the frame 
+*		should egress.
+*
+* INPUTS:
+*		port - the logical port number.
+*		cpuPort - CPU Port number or interswitch port where CPU Port is connected
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetCPUPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_LPORT 	cpuPort
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetCPUPort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    data = (GT_U16)GT_LPORT_2_PORT(cpuPort);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CPU_DEST_PER_PORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Set the CPU Port.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,0,4,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetCPUPort
+*
+* DESCRIPTION:
+*		This routine gets CPU Logical Port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		cpuPort - CPU Port's logical number
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetCPUPort
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_LPORT 	*cpuLPort
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetCPUPort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CPU_DEST_PER_PORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the CPUPort.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 0, 4, &data);
+
+    *cpuLPort = GT_PORT_2_LPORT((GT_U8)data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetLockedPort
+*
+* DESCRIPTION:
+*		This routine sets LockedPort. When it's set to one, CPU directed 
+*		learning for 802.1x MAC authentication is enabled on this port. In this
+*		mode, an ATU Miss Violation interrupt will occur when a new SA address
+*		is received in a frame on this port. Automatically SA learning and 
+*		refreshing is disabled in this mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for Locked Port, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetLockedPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetLockedPort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set Locked Port.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 13, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetLockedPort
+*
+* DESCRIPTION:
+*		This routine gets Locked Port mode for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if LockedPort, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetLockedPort
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL  	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetLockedPort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the LockedPort. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 13, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetIgnoreWrongData
+*
+* DESCRIPTION:
+*		This routine sets Ignore Wrong Data. If the frame's SA address is found 
+*		in the database and if the entry is 'static' or if the port is 'locked'
+*		the source port's bit is checked to insure the SA has been assigned to 
+*		this port. If the SA is NOT assigned to this port, it is considered an 
+*		ATU Member Violation. If the IgnoreWrongData is set to GT_FALSE, an ATU
+*		Member Violation interrupt will be generated. If it's set to GT_TRUE,
+*		the ATU Member Violation error will be masked and ignored.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for IgnoreWrongData, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIgnoreWrongData
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetIgnoreWrongData Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set IgnoreWrongData.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 12, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetIgnoreWrongData
+*
+* DESCRIPTION:
+*		This routine gets Ignore Wrong Data mode for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if IgnoreWrongData, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIgnoreWrongData
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetIgnoreWrongData Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the IgnoreWrongData. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 12, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetDiscardTagged
+*
+* DESCRIPTION:
+*		When this bit is set to a one, all non-MGMT frames that are processed as 
+*		Tagged will be discarded as they enter this switch port. Priority only 
+*		tagged frames (with a VID of 0x000) are considered tagged.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to discard tagged frame, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDiscardTagged
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetDiscardTagged Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set DiscardTagged. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 9, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetDiscardTagged
+*
+* DESCRIPTION:
+*		This routine gets DiscardTagged bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if DiscardTagged bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDiscardTagged
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetDiscardTagged Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the DiscardTagged. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 9, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetDiscardUntagged
+*
+* DESCRIPTION:
+*		When this bit is set to a one, all non-MGMT frames that are processed as 
+*		Untagged will be discarded as they enter this switch port. Priority only 
+*		tagged frames (with a VID of 0x000) are considered tagged.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to discard untagged frame, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDiscardUntagged
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetDiscardUntagged Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set DiscardUnTagged. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 8, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetDiscardUntagged
+*
+* DESCRIPTION:
+*		This routine gets DiscardUntagged bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if DiscardUntagged bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDiscardUntagged
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetDiscardUnTagged Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the DiscardUnTagged. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 8, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtSetMapDA
+*
+* DESCRIPTION:
+*		When this bit is set to a one, normal switch operation will occur where a 
+*		frame's DA address is used to direct the frame out the correct port.
+*		When this be is cleared to a zero, the frame will be sent out the port(s) 
+*		defined by ForwardUnknown bits or the DefaultForward bits even if the DA 
+*		is ound in the address database.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to use MapDA, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetMapDA
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetMapDA Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set MapDA. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 7, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetMapDA
+*
+* DESCRIPTION:
+*		This routine gets MapDA bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if MapDA bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMapDA
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetMapDA Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY|DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the MapDA. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 7, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetDefaultForward
+*
+* DESCRIPTION:
+*		When this bit is set to a one, normal switch operation will occurs and 
+*		multicast frames with unknown DA addresses are allowed to egress out this 
+*		port (assuming the VLAN settings allow the frame to egress this port too).
+*		When this bit is cleared to a zero, multicast frames with unknown DA 
+*		addresses will not egress out this port.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to use DefaultForward, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetDefaultForward
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetDefaultForward Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set DefaultForward. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_EGRESS_FLOOD))
+	{
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 6, 1, data);
+	}
+	else
+	{
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 3, 1, data);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetDefaultForward
+*
+* DESCRIPTION:
+*		This routine gets DefaultForward bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if DefaultForward bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDefaultForward
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetDefaultForward Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the DefaultForward. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_EGRESS_FLOOD))
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 6, 1, &data);
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 3, 1, &data);
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtSetEgressMonitorSource
+*
+* DESCRIPTION:
+*		When this be is cleared to a zero, normal network switching occurs.
+*		When this bit is set to a one, any frame that egresses out this port will
+*		also be sent to the EgressMonitorDest Port
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to set EgressMonitorSource, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetEgressMonitorSource
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetEgressMonitorSource Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set EgressMonitorSource. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 5, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetEgressMonitorSource
+*
+* DESCRIPTION:
+*		This routine gets EgressMonitorSource bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if EgressMonitorSource bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetEgressMonitorSource
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetEgressMonitorSource Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the EgressMonitorSource. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 5, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetIngressMonitorSource
+*
+* DESCRIPTION:
+*		When this be is cleared to a zero, normal network switching occurs.
+*		When this bit is set to a one, any frame that egresses out this port will
+*		also be sent to the EgressMonitorDest Port
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to set EgressMonitorSource, GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetIngressMonitorSource
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetIngressMonitorSource Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set IngressMonitorSource. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 4, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetIngressMonitorSource
+*
+* DESCRIPTION:
+*		This routine gets IngressMonitorSource bit for the given port
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode  - GT_TRUE if IngressMonitorSource bit is set, GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIngressMonitorSource
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetIngressMonitorSource Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the IngressMonitorSource. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2, 4, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetMessagePort
+*
+* DESCRIPTION:
+*		When the Learn2All bit is set to one, learning message frames are 
+*		generated. These frames will be sent out all ports whose Message Port is 
+*		set to one.
+* 		If this feature is used, it is recommended that all Marvell Tag ports, 
+*		except for the CPU's port, have their MessagePort bit set to one. 
+*		Ports that are not Marvell Tag ports should not have their Message Port
+*		bit set to one.
+*		
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to make this port a Message Port. GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetMessagePort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetMessagePort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set IngressMonitorSource. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 15, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetMessagePort
+*
+* DESCRIPTION:
+*		When the Learn2All bit is set to one, learning message frames are 
+*		generated. These frames will be sent out all ports whose Message Port is 
+*		set to one.
+* 		If this feature is used, it is recommended that all Marvell Tag ports, 
+*		except for the CPU's port, have their MessagePort bit set to one. 
+*		Ports that are not Marvell Tag ports should not have their Message Port
+*		bit set to one.
+*
+*		
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to make this port a Message Port. GT_FALSE, otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMessagePort
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetMessagePort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the IngressMonitorSource. */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 15, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetTrunkPort
+*
+* DESCRIPTION:
+*		This function enables/disables and sets the trunk ID.
+*		
+* INPUTS:
+*		port - the logical port number.
+*		en - GT_TRUE to make the port be a member of a trunk with the given trunkId.
+*			 GT_FALSE, otherwise.
+*		trunkId - valid ID is 0 ~ 15.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkId is neither valid nor INVALID_TRUNK_ID
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetTrunkPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL 		en,
+	IN GT_U32		trunkId
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetTrunkPort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(en, data);
+
+	if(en == GT_TRUE)
+	{
+		/* need to enable trunk. so check the trunkId */
+		if (!IS_TRUNK_ID_VALID(dev, trunkId))
+		{
+	        DBG_INFO(("GT_BAD_PARAM\n"));
+			return GT_BAD_PARAM;
+		}
+
+	    /* Set TrunkId. */
+		if (IS_IN_DEV_GROUP(dev,DEV_TRUNK_NEW_ID_LOCATION))
+		{
+	    	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 8, 4, (GT_U16)trunkId);
+		}
+		else
+		{
+	    	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 4, 4, (GT_U16)trunkId);
+		}
+
+	    if(retVal != GT_OK)
+		{
+	       	DBG_INFO(("Failed.\n"));
+			return retVal;	
+		}
+
+	}
+	else
+	{
+		/* 
+		   Need to reset trunkId for 88E6095 rev0.
+		*/
+		if (IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) &&
+			((GT_DEVICE_REV)dev->revision < GT_REV_1))
+		{
+			trunkId = 0;
+		
+	    	/* Set TrunkId. */
+	    	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 4, 4, (GT_U16)trunkId);
+		    if(retVal != GT_OK)
+			{
+		       	DBG_INFO(("Failed.\n"));
+				return retVal;	
+			}
+		}
+	}
+
+    /* Set TrunkPort bit. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 14, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetTrunkPort
+*
+* DESCRIPTION:
+*		This function returns trunk state of the port.
+*		When trunk is disabled, trunkId field won't have valid value.
+*		
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		en - GT_TRUE, if the port is a member of a trunk,
+*			 GT_FALSE, otherwise.
+*		trunkId - 0 ~ 15, valid only if en is GT_TRUE
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetTrunkPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	OUT GT_BOOL 	*en,
+	OUT GT_U32		*trunkId
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetTrunkPort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	data = 0;
+
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 14, 1, &data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+    BIT_2_BOOL(data, *en);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_TRUNK_NEW_ID_LOCATION))
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 8, 4, &data);
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL1, 4, 4, &data);
+	}
+
+	*trunkId = (GT_U32)data;
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetDiscardBCastMode
+*
+* DESCRIPTION:
+*       This routine gets the Discard Broadcast Mode. If the mode is enabled,
+*		all the broadcast frames to the given port will be discarded.
+*
+* INPUTS:
+*       port - logical port number
+*
+* OUTPUTS:
+*		en - GT_TRUE, if enabled,
+*			 GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDiscardBCastMode
+(
+	IN  GT_QD_DEV    *dev,
+	IN  GT_LPORT     port,
+	OUT GT_BOOL 	 *en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetDiscardBCastMode Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_DROP_BCAST))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_1))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+	data = 0;
+
+    retVal = hwGetPortRegField(dev,hwPort, 0x15, 6, 1, &data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+    BIT_2_BOOL(data, *en);
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtSetDiscardBCastMode
+*
+* DESCRIPTION:
+*       This routine sets the Discard Broadcast mode.
+*		If the mode is enabled, all the broadcast frames to the given port will 
+*		be discarded.
+*
+* INPUTS:
+*       port - logical port number
+*		en - GT_TRUE, to enable the mode,
+*			 GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDiscardBCastMode
+(
+	IN  GT_QD_DEV    *dev,
+	IN  GT_LPORT     port,
+	IN  GT_BOOL 	 en
+)
+{
+    GT_U16          data;           /* Used to poll the data */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetDiscardBCastMode Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_DROP_BCAST))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_1))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(en, data);
+
+    retVal = hwSetPortRegField(dev,hwPort, 0x15, 6, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtGetFCOnRateLimitMode
+*
+* DESCRIPTION:
+*       This routine returns mode that tells if ingress rate limiting uses Flow 
+*		Control. When this mode is enabled and the port receives frames over the 
+*		limit, Ingress Rate Limiting will be performed by stalling the 
+*		link partner using flow control, instead of discarding frames.
+*
+* INPUTS:
+*       port - logical port number
+*
+* OUTPUTS:
+*		en - GT_TRUE, if the mode is enabled,
+*			 GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		In order for this mode to work, Flow Control and Rate Limiting
+*		should be configured properly.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetFCOnRateLimitMode
+(
+	IN  GT_QD_DEV    *dev,
+	IN  GT_LPORT     port,
+	OUT GT_BOOL 	 *en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetFCOnRateLimitMode Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	data = 0;
+
+    retVal = hwGetPortRegField(dev,hwPort, 0x15, 4, 2, &data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	if (data == 0x3)
+		*en = GT_TRUE;
+	else
+		*en = GT_FALSE;
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtSetFCOnRateLimitMode
+*
+* DESCRIPTION:
+*       This routine sets the mode that tells if ingress rate limiting uses Flow 
+*		Control. When this mode is enabled and the port receives frames over the 
+*		limit, Ingress Rate Limiting will be performed by stalling the 
+*		link partner using flow control, instead of discarding frames.
+*
+* INPUTS:
+*       port - logical port number
+*		en - GT_TRUE, to enable the mode,
+*			 GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       This routine won't configure Flow Control or Rate Limiting.
+*		In order for this mode to work, Flow Control and Rate Limiting
+*		should be configured properly.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetFCOnRateLimitMode
+(
+	IN  GT_QD_DEV    *dev,
+	IN  GT_LPORT     port,
+	IN  GT_BOOL 	 en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetFCOnRateLimitMode Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+	if (en)
+		data = 0x3;
+	else
+		data = 0;
+
+    retVal = hwSetPortRegField(dev,hwPort, 0x15, 4, 2, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtSetSAFiltering
+*
+* DESCRIPTION:
+*		This routine set the Source Address(SA) fitering method.
+*			GT_SA_FILTERING_DISABLE :
+*				no frame will be filtered.
+*			GT_SA_DROP_ON_LOCK :
+*				discard if SA field is not in the ATU's address database.
+*			GT_SA_DROP_ON_UNLOCK : 
+*				discard if SA field is in the ATU's address database as Static 
+*				entry with a PortVec of all zeros.
+*			GT_SA_DROP_TO_CPU : 
+*				Ingressing frames will be mapped to the CPU Port if their SA 
+*				field is in the ATU's address database as Static entry with a 
+*				PortVec of all zeros. Otherwise, the frames will be discarded 
+*				if their SA field is not in the ATU's address database or if this
+*				port's bit is not set in the PortVec bits for the frame's SA.
+*		
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_SA_FILTERING structure
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS gprtSetSAFiltering
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT   port,
+    IN GT_SA_FILTERING    mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			data;
+
+    DBG_INFO(("gprtSetSAFiltering Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SA_FILTERING))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	data = (GT_U16) mode;
+
+    /* Set the SA Filtering bits.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,14,2,data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetSAFiltering
+*
+* DESCRIPTION:
+*		This routine gets the Source Address(SA) fitering method.
+*			GT_SA_FILTERING_DISABLE :
+*				no frame will be filtered.
+*			GT_SA_DROP_ON_LOCK :
+*				discard if SA field is not in the ATU's address database.
+*			GT_SA_DROP_ON_UNLOCK : 
+*				discard if SA field is in the ATU's address database as Static 
+*				entry with a PortVec of all zeros.
+*			GT_SA_DROP_TO_CPU : 
+*				Ingressing frames will be mapped to the CPU Port if their SA 
+*				field is in the ATU's address database as Static entry with a 
+*				PortVec of all zeros. Otherwise, the frames will be discarded 
+*				if their SA field is not in the ATU's address database or if this
+*				port's bit is not set in the PortVec bits for the frame's SA.
+*		
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_SA_FILTERING structure
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS gprtGetSAFiltering
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_SA_FILTERING    *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			data;
+
+    DBG_INFO(("gprtSetSAFiltering Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SA_FILTERING))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the SA Filtering bits.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,14,2,&data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	*mode = (GT_SA_FILTERING)data;
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetARPtoCPU
+*
+* DESCRIPTION:
+*		When ARPtoCPU (or ARP Mirror) is set to GT_TRUE, ARP frames are mirrored 
+*		to the CPU port.
+*		
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE, to map ARP frames to CPU Port,
+*			   GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS gprtSetARPtoCPU
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    mode
+)
+{
+	GT_U16			data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetARPtoCPU Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ARP_TO_CPU))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the ARPtoCPU bits.  */
+	if (IS_IN_DEV_GROUP(dev,DEV_FASTETH_SWITCH))
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,8,1,data);
+	else
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,6,1,data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetARPtoCPU
+*
+* DESCRIPTION:
+*		When ARPtoCPU (or ARP Mirror) is set to GT_TRUE, ARP frames are mirrored 
+*		to the CPU port.
+*		
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE, to map ARP frames to CPU Port,
+*			   GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS gprtGetARPtoCPU
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_BOOL    *mode
+)
+{
+	GT_U16			data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetARPtoCPU Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device supports the feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ARP_TO_CPU))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the ARPtoCPU bits.  */
+	if (IS_IN_DEV_GROUP(dev,DEV_FASTETH_SWITCH))
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,8,1,&data);
+	else
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,6,1,&data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetEgressFlood
+*
+* DESCRIPTION:
+*       This routine set Egress Flooding Mode.
+*		Frames with unknown DA (Destination Address that is not in ATU database)
+*		generally flood out all the ports. This mode can be used to prevent
+*		those frames from egressing this port as follows:
+*			GT_BLOCK_EGRESS_UNKNOWN
+*				do not egress frame with unknown DA (both unicast and multicast)
+*			GT_BLOCK_EGRESS_UNKNOWN_MULTICAST
+*				do not egress frame with unknown multicast DA
+*			GT_BLOCK_EGRESS_UNKNOWN_UNICAST
+*				do not egress frame with unknown unicast DA
+*			GT_BLOCK_EGRESS_NONE
+*				egress all frames with unknown DA
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_EGRESS_FLOOD type
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetEgressFlood
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT     port,
+    IN  GT_EGRESS_FLOOD      mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			data;
+
+    DBG_INFO(("gprtSetEgressFlood Called.\n"));
+
+	/* check if device supports the feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_EGRESS_FLOOD))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	data = (GT_U16) mode;
+
+    /* Set the Egress Flood mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,2,2,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetEgressFlood
+*
+* DESCRIPTION:
+*       This routine gets Egress Flooding Mode.
+*		Frames with unknown DA (Destination Address that is not in ATU database)
+*		generally flood out all the ports. This mode can be used to prevent
+*		those frames from egressing this port as follows:
+*			GT_BLOCK_EGRESS_UNKNOWN
+*				do not egress frame with unknown DA (both unicast and multicast)
+*			GT_BLOCK_EGRESS_UNKNOWN_MULTICAST
+*				do not egress frame with unknown multicast DA
+*			GT_BLOCK_EGRESS_UNKNOWN_UNICAST
+*				do not egress frame with unknown unicast DA
+*			GT_BLOCK_EGRESS_NONE
+*				egress all frames with unknown DA
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_EGRESS_FLOOD type
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetEgressFlood
+(
+    IN  GT_QD_DEV   *dev,
+    IN  GT_LPORT     port,
+    OUT GT_EGRESS_FLOOD      *mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetEgressFlood Called.\n"));
+
+	/* check if device supports the feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_EGRESS_FLOOD))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED.\n"));
+        return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* get the Egress Flood mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,2,2,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	*mode = (GT_EGRESS_FLOOD) data;
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetPortSched
+*
+* DESCRIPTION:
+*		This routine sets Port Scheduling Mode.
+*		When usePortSched is enablied, this mode is used to select the Queue
+*		controller's scheduling on the port as follows:
+*			GT_PORT_SCHED_WEIGHTED_RRB - use 8,4,2,1 weighted fair scheduling
+*			GT_PORT_SCHED_STRICT_PRI - use a strict priority scheme
+*
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_PORT_SCHED_MODE enum type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetPortSched
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_PORT_SCHED_MODE		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetPortSched Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PORT_SCHEDULE|DEV_PORT_MIXED_SCHEDULE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PORT_MIXED_SCHEDULE))
+    {
+		switch(mode)
+		{
+			case GT_PORT_SCHED_WEIGHTED_RRB:
+				data = 0;
+				break;
+			case GT_PORT_SCHED_STRICT_PRI:
+				data = 3;
+				break;
+			case GT_PORT_SCHED_STRICT_PRI3:
+				data = 1;
+				break;
+			case GT_PORT_SCHED_STRICT_PRI2_3:
+				data = 2;
+				break;
+			default:
+				return GT_BAD_PARAM;
+		}
+
+	    retVal = hwSetPortRegField(dev,hwPort, QD_REG_RATE_CTRL, 12,2,data);
+		
+	    if(retVal != GT_OK)
+		{
+        	DBG_INFO(("Failed.\n"));
+		}
+    	else
+		{
+    	    DBG_INFO(("OK.\n"));
+		}
+    	return retVal;
+
+    }
+
+
+	data = mode;
+
+    /* Set the gprtSetPortSched mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION,14,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPortSched
+*
+* DESCRIPTION:
+*		This routine gets Port Scheduling Mode.
+*		When usePortSched is enablied, this mode is used to select the Queue
+*		controller's scheduling on the port as follows:
+*			GT_PORT_SCHED_WEIGHTED_RRB - use 8,4,2,1 weighted fair scheduling
+*			GT_PORT_SCHED_STRICT_PRI - use a strict priority scheme
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		mode - GT_PORT_SCHED_MODE enum type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortSched
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_PORT_SCHED_MODE		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPortSched Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PORT_SCHEDULE|DEV_PORT_MIXED_SCHEDULE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PORT_MIXED_SCHEDULE))
+    {
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_RATE_CTRL, 12,2,&data);
+	    if(retVal != GT_OK)
+		{
+        	DBG_INFO(("Failed.\n"));
+	    	return retVal;
+		}
+
+		switch(data)
+		{
+			case 0:
+				*mode = GT_PORT_SCHED_WEIGHTED_RRB;
+				break;
+			case 1:
+				*mode = GT_PORT_SCHED_STRICT_PRI3;
+				break;
+			case 2:
+				*mode = GT_PORT_SCHED_STRICT_PRI2_3;
+				break;
+			case 3:
+				*mode = GT_PORT_SCHED_STRICT_PRI;
+				break;
+			default:
+				return GT_BAD_PARAM;
+		}
+
+    	return GT_OK;
+
+    }
+
+    /* Get the gprtGetPortSched mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION,14,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	*mode = (GT_PORT_SCHED_MODE)data;
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetProviderTag
+*
+* DESCRIPTION:
+*		This routine sets Provider Tag which indicates the provider tag (Ether 
+*		Type) value that needs to be matched to in ingress to determine if a
+*		frame is Provider tagged or not.
+*
+* INPUTS:
+*		port - the logical port number
+*		tag  - Provider Tag (Ether Type)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetProviderTag
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U16		tag
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetProviderTag Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PROVIDER_TAG))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Set Provider Tag.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PROVIDER_TAG, 0, 16, tag);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetProviderTag
+*
+* DESCRIPTION:
+*		This routine gets Provider Tag which indicates the provider tag (Ether 
+*		Type) value that needs to be matched to in ingress to determine if a
+*		frame is Provider tagged or not.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		tag  - Provider Tag (Ether Type)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetProviderTag
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*tag
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetProviderTag Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PROVIDER_TAG))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get Provider Tag.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PROVIDER_TAG, 0, 16, tag);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetPauseLimitOut
+*
+* DESCRIPTION:
+*		Limit the number of continuous Pause refresh frames that can be transmitted
+*		from this port. When full duplex Flow Control is enabled on this port,
+*		these bits are used to limit the number of Pause refresh frames that can 
+*		be generated from this port to keep this port's link partner from sending
+*		any data.
+*		Setting this value to 0 will allow continuous Pause frame refreshes to 
+*		egress this port as long as this port remains congested.
+*		Setting this value to 1 will allow 1 Pause frame to egress from this port
+*		for each congestion situation.
+*		Setting this value to 2 will allow 2 Pause frames to egress from this port
+*		for each congestion situation, etc.
+*		
+* INPUTS:
+*		port - the logical port number
+*		limit - the max number of Pause refresh frames for each congestion situation
+*				( 0 ~ 0xFF)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if limit > 0xFF
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetPauseLimitOut
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U16		limit
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetPauseLimitOut Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PAUSE_LIMIT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (limit > 0xFF)
+	{
+        DBG_INFO(("Bad Parameter\n"));
+		return GT_BAD_PARAM;
+	}
+
+    /* Set Pause Limit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_LIMIT_PAUSE_CONTROL, 8, 8, limit);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPauseLimitOut
+*
+* DESCRIPTION:
+*		Limit the number of continuous Pause refresh frames that can be transmitted
+*		from this port. When full duplex Flow Control is enabled on this port,
+*		these bits are used to limit the number of Pause refresh frames that can 
+*		be generated from this port to keep this port's link partner from sending
+*		any data.
+*		Setting this value to 0 will allow continuous Pause frame refreshes to 
+*		egress this port as long as this port remains congested.
+*		Setting this value to 1 will allow 1 Pause frame to egress from this port
+*		for each congestion situation.
+*		Setting this value to 2 will allow 2 Pause frames to egress from this port
+*		for each congestion situation, etc.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		limit - the max number of Pause refresh frames for each congestion situation
+*				( 0 ~ 0xFF)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetPauseLimitOut
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*limit
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPauseLimitOut Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PAUSE_LIMIT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get Pause Limit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_LIMIT_PAUSE_CONTROL, 8, 8, limit);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetPauseLimitIn
+*
+* DESCRIPTION:
+*		Limit the number of continuous Pause refresh frames that can be received
+*		on this port. When a port has flow Control enabled, this value can be 
+*		used to limit how long this port can be Paused off to prevent a port stall
+*		through jamming.
+*		When this value is in the range of 0x01 to 0xFF, and a frame is ready to
+*		be transmitted out this port, but it cannot be transmitted due to the port
+*		being jammed, this limit mechanism starts. The limit mechanism starts 
+*		counting new Pause refresh frames or counts of 16 consecutive collisions.
+*		If the counter reaches the value set through this API, the following event
+*		will occur:
+*			1) Port's ForceFC is enabled,
+*			2) Port's FCValue is cleared to a zero, and
+*			3) Jam Limit Interrupt is asserted.
+*		This effectively disables Flow Control on the port once the Pause timer 
+*		expires. If a frame gets transmitted out this port before the counter
+*		reaches this limit, then this limit mechanism counter resets back to zero.
+*
+*		Setting this value to 0 will allow continuous jamming to be received on 
+*		this port without the Port's ForceFC and FCValue getting modified.
+*
+*		The modification of Port's ForceFC and FCValue is the only indication that 
+*		the limit was reached on this port.
+*		
+* INPUTS:
+*		port - the logical port number
+*		limit - the max number of continuous Pause refresh frames for each trasmition
+*				( 0 ~ 0xFF)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if limit > 0xFF
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetPauseLimitIn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_U16		limit
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetPauseLimitIn Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PAUSE_LIMIT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (limit > 0xFF)
+	{
+        DBG_INFO(("Bad Parameter\n"));
+		return GT_BAD_PARAM;
+	}
+
+    /* Set Pause Limit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_LIMIT_PAUSE_CONTROL, 0, 8, limit);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPauseLimitIn
+*
+* DESCRIPTION:
+*		Limit the number of continuous Pause refresh frames that can be received
+*		on this port. When a port has flow Control enabled, this value can be 
+*		used to limit how long this port can be Paused off to prevent a port stall
+*		through jamming.
+*		When this value is in the range of 0x01 to 0xFF, and a frame is ready to
+*		be transmitted out this port, but it cannot be transmitted due to the port
+*		being jammed, this limit mechanism starts. The limit mechanism starts 
+*		counting new Pause refresh frames or counts of 16 consecutive collisions.
+*		If the counter reaches the value set through this API, the following event
+*		will occur:
+*			1) Port's ForceFC is enabled,
+*			2) Port's FCValue is cleared to a zero, and
+*			3) Jam Limit Interrupt is asserted.
+*		This effectively disables Flow Control on the port once the Pause timer 
+*		expires. If a frame gets transmitted out this port before the counter
+*		reaches this limit, then this limit mechanism counter resets back to zero.
+*
+*		Setting this value to 0 will allow continuous jamming to be received on 
+*		this port without the Port's ForceFC and FCValue getting modified.
+*
+*		The modification of Port's ForceFC and FCValue is the only indication that 
+*		the limit was reached on this port.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		limit - the max number of continuous Pause refresh frames for each trasmition
+*				( 0 ~ 0xFF)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetPauseLimitIn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*limit
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPauseLimitIn Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PAUSE_LIMIT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get Pause Limit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_LIMIT_PAUSE_CONTROL, 0, 8, limit);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetFrameMode
+*
+* DESCRIPTION:
+*		Frmae Mode is used to define the expected Ingress and the generated Egress
+*		tagging frame format for this port as follows:
+*			GT_FRAME_MODE_NORMAL -
+*				Normal Network mode uses industry standard IEEE 802.3ac Tagged or 
+*				Untagged frames. Tagged frames use an Ether Type of 0x8100.
+*			GT_FRAME_MODE_DSA -
+*				DSA mode uses a Marvell defined tagged frame format for 
+*				Chip-to-Chip and Chip-to-CPU connections.
+*			GT_FRAME_MODE_PROVIDER -
+*				Provider mode uses user definable Ether Types per port 
+*				(see gprtSetPortEType/gprtGetPortEType API).
+*			GT_FRAME_MODE_ETHER_TYPE_DSA -
+*				Ether Type DSA mode uses standard Marvell DSA Tagged frame info 
+*				flowing a user definable Ether Type. This mode allows the mixture
+*				of Normal Network frames with DSA Tagged frames and is useful to 
+*				be used on ports that connect to a CPU.
+*		
+* INPUTS:
+*		port - the logical port number
+*		mode - GT_FRAME_MODE type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if mode is unknown
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetFrameMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_FRAME_MODE	mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetFrameMode Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_MODE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    switch (mode)
+    {
+		case GT_FRAME_MODE_NORMAL:
+		case GT_FRAME_MODE_DSA:
+		case GT_FRAME_MODE_PROVIDER:
+		case GT_FRAME_MODE_ETHER_TYPE_DSA:
+			break;
+		default:
+	        DBG_INFO(("Bad Parameter\n"));
+			return GT_BAD_PARAM;
+	}
+
+    /* Set Frame Mode.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 8, 2, (GT_U16)mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetFrameMode
+*
+* DESCRIPTION:
+*		Frmae Mode is used to define the expected Ingress and the generated Egress
+*		tagging frame format for this port as follows:
+*			GT_FRAME_MODE_NORMAL -
+*				Normal Network mode uses industry standard IEEE 802.3ac Tagged or 
+*				Untagged frames. Tagged frames use an Ether Type of 0x8100.
+*			GT_FRAME_MODE_DSA -
+*				DSA mode uses a Marvell defined tagged frame format for 
+*				Chip-to-Chip and Chip-to-CPU connections.
+*			GT_FRAME_MODE_PROVIDER -
+*				Provider mode uses user definable Ether Types per port 
+*				(see gprtSetPortEType/gprtGetPortEType API).
+*			GT_FRAME_MODE_ETHER_TYPE_DSA -
+*				Ether Type DSA mode uses standard Marvell DSA Tagged frame info 
+*				flowing a user definable Ether Type. This mode allows the mixture
+*				of Normal Network frames with DSA Tagged frames and is useful to 
+*				be used on ports that connect to a CPU.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		mode - GT_FRAME_MODE type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetFrameMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_FRAME_MODE	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetFrameMode Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_MODE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get Pause Limit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL, 8, 2, &data);
+    *mode = data;
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetHoldAt1
+*
+* DESCRIPTION:
+*		Hold Aging ATU Entries at an Entry State value of 1. When this feature
+*		is set to GT_TRUE, ATU entries associated with this port will age down 
+*		to an Entry State of 0x1, but will not go to 0x0 (0x0 would purge the
+*		entry)
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to hold aging ATU entry with Entry State of 1, 
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetHoldAt1
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetHoldAt1 Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AGE_HOLD))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set HoldAt1 */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 15, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetHoldAt1
+*
+* DESCRIPTION:
+*		Hold Aging ATU Entries at an Entry State value of 1. When this feature
+*		is set to GT_TRUE, ATU entries associated with this port will age down 
+*		to an Entry State of 0x1, but will not go to 0x0 (0x0 would purge the
+*		entry)
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to hold aging ATU entry with Entry State of 1, 
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHoldAt1
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL  	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetHoldAt1 Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AGE_HOLD))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get HoldAt1 */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 15, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetIntOnAgeOut
+*
+* DESCRIPTION:
+*		Interrupt on Age Out. When aging is enabled, all non-static address 
+*		entries in the ATU's address database are periodically aged.
+*		When this feature is set to GT_TRUE and an entry associated with this 
+*		port is aged out, an AgeOutViolation will be captured for that entry.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to enable AgeOutViloation interrupt
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetIntOnAgeOut
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetIntOnAgeOut Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AGE_OUT_INT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set Age Out Interrupt Enable Mode. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 14, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetIntOnAgeOut
+*
+* DESCRIPTION:
+*		Interrupt on Age Out. When aging is enabled, all non-static address 
+*		entries in the ATU's address database are periodically aged.
+*		When this feature is set to GT_TRUE and an entry associated with this 
+*		port is aged out, an AgeOutViolation will be captured for that entry.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable AgeOutViloation interrupt
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetIntOnAgeOut
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL  	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetIntOnAgeOut Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AGE_OUT_INT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get IntOnAgeOut */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 14, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetRefreshLocked
+*
+* DESCRIPTION:
+*		Auto Refresh known addresses when port is Locked. Already known addresses 
+*		will be auto refreshed when this feature is enabled. When this feature
+*		is disabled, auto refreshing will not occur on Locked ports.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE to enable Auto Refresh known addresses on locked port
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetRefreshLocked
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetRefreshLocked Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AUTO_REFRESH_LOCKED))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set RefreshLocked */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 11, 1, data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetRefreshLocked
+*
+* DESCRIPTION:
+*		Auto Refresh known addresses when port is Locked. Already known addresses 
+*		will be auto refreshed when this feature is enabled. When this feature
+*		is disabled, auto refreshing will not occur on Locked ports.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable Auto Refresh known addresses on locked port
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetRefreshLocked
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL  	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* to keep the read valve       */
+
+    DBG_INFO(("gprtGetRefreshLocked Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if device allows to force a flowcontrol disabled */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AUTO_REFRESH_LOCKED))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get RefreshLocked */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_ASSOCIATION, 11, 1, &data);
+
+    BIT_2_BOOL(data, *mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetPortEType
+*
+* DESCRIPTION:
+*		This routine sets the port's special Ether Type. This Ether Type is used
+*		for Policy (see gprtSetPolicy API) and FrameMode (see gprtSetFrameMode API).
+*
+* INPUTS:
+*		port  - the logical port number
+*		etype - port's special ether type
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtSetPortEType
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_ETYPE		etype
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetPortEType Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PORT_ETYPE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    data = (GT_U16)etype;
+
+    /* Set the EtherType.            */
+    retVal = hwWritePortReg(dev,hwPort, QD_REG_PORT_ETH_TYPE,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetPortEType
+*
+* DESCRIPTION:
+*		This routine retrieves the port's special Ether Type. This Ether Type is used
+*		for Policy (see gprtSetPolicy API) and FrameMode (see gprtSetFrameMode API).
+*
+* INPUTS:
+*		port  - the logical port number
+*
+* OUTPUTS:
+*		etype - port's special ether type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortEType
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_ETYPE	*etype
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPortEType Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PORT_ETYPE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the EtherType.            */
+    retVal = hwReadPortReg(dev,hwPort, QD_REG_PORT_ETH_TYPE,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	*etype = (GT_ETYPE) data;
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gsysSetJumboMode
+*
+* DESCRIPTION:
+*       This routine Set the max frame size allowed to be received and transmitted
+*		from or to a given port.
+*
+* INPUTS:
+*		port - the logical port number
+*       mode - GT_JUMBO_MODE (1522, 2048, or 10240)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gsysSetJumboMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_JUMBO_MODE   mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gsysSetJumboMode Called.\n"));
+
+	if (mode > GT_JUMBO_MODE_10240)
+	{
+		DBG_INFO(("Bad Parameter\n"));
+		return GT_BAD_PARAM;
+	}
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_JUMBO_MODE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Set the Jumbo Fram Size bit.               */
+	retVal = hwSetPortRegField(dev,hwPort,QD_REG_PORT_CONTROL2,12,2,(GT_U16)mode);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetJumboMode
+*
+* DESCRIPTION:
+*       This routine gets the max frame size allowed to be received and transmitted
+*		from or to a given port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_JUMBO_MODE (1522, 2048, or 10240)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gsysGetJumboMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_JUMBO_MODE   *mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16          data;           /* to keep the read valve       */
+
+	DBG_INFO(("gsysGetJumboMode Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_JUMBO_MODE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	/* Get Jumbo Frame Mode.            */
+	retVal = hwGetPortRegField(dev,hwPort,QD_REG_PORT_CONTROL2,12,2,&data );
+
+	*mode = (GT_JUMBO_MODE)data;
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	return retVal;
+}
+ 
+
+/*******************************************************************************
+* gprtGet200Base
+*
+* DESCRIPTION:
+*		200 Base mode. This bit can be used to change the port's Px_GTXCLK
+*		frequency to 50MHz to support 200 BASE mode as follows:
+*		0 = 25MHz Px_GTXCLK
+*		1 = 50MHz Px_GTXCLK
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - 0 for 100Mbps, 1 for 200Mbps
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		C_Mode should be set to 0x2 in order for this API to work
+*
+*******************************************************************************/
+GT_STATUS gprtGet200Base
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_U32  	*mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			data;
+
+	DBG_INFO(("gprtGet200Base Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_200BASE_CFG))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	if (hwPort < (dev->maxPorts - 2))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get the high error rate bit.  */
+	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,6,1,&data);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	*mode = (GT_U32)data;
+
+	/* return */
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtSet200Base
+*
+* DESCRIPTION:
+*		200 Base mode. This bit can be used to change the port's Px_GTXCLK
+*		frequency to 50MHz to support 200 BASE mode as follows:
+*		0 = 25MHz Px_GTXCLK
+*		1 = 50MHz Px_GTXCLK
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - 0 for 100Mbps, 1 for 200Mbps
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		C_Mode should be set to 0x2 in order for this API to work
+*
+*******************************************************************************/
+GT_STATUS gprtSet200Base
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_U32  	mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtSet200Base Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_200BASE_CFG))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	if (hwPort < (dev->maxPorts - 2))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* Get the high error rate bit.  */
+	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,6,1,(GT_U16)(mode&0x1));
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	/* return */
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetSwitchReg
+*
+* DESCRIPTION:
+*       This routine reads Switch Port Registers.
+*
+* INPUTS:
+*       port    - logical port number
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSwitchReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_LPORT     port,
+    IN  GT_U32	     regAddr,
+    OUT GT_U16	     *data
+)
+{
+    GT_U16          u16Data;           /* The register's read data.    */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetSwitchReg Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get Phy Register. */
+    if(hwReadPortReg(dev,hwPort,(GT_U8)regAddr,&u16Data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+	*data = u16Data;
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtSetSwitchReg
+*
+* DESCRIPTION:
+*       This routine writes Switch Port Registers.
+*
+* INPUTS:
+*       port    - logical port number
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetSwitchReg
+(
+    IN  GT_QD_DEV		*dev,
+    IN  GT_LPORT		port,
+    IN  GT_U32			regAddr,
+    IN  GT_U16			data
+)
+{
+    GT_U8           hwPort;         /* the physical port number     */
+    
+    DBG_INFO(("gprtSetSwitchReg Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the Scheduling bit.              */
+    if(hwWritePortReg(dev,hwPort,(GT_U8)regAddr,data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtGetGlobalReg
+*
+* DESCRIPTION:
+*       This routine reads Switch Global Registers.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetGlobalReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U32	     regAddr,
+    OUT GT_U16	     *data
+)
+{
+    GT_U16          u16Data;           /* The register's read data.    */
+
+    DBG_INFO(("gprtGetGlobalReg Called.\n"));
+
+    /* Get Phy Register. */
+    if(hwReadGlobalReg(dev,(GT_U8)regAddr,&u16Data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+	*data = u16Data;
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtSetGlobalReg
+*
+* DESCRIPTION:
+*       This routine writes Switch Global Registers.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetGlobalReg
+(
+    IN  GT_QD_DEV		*dev,
+    IN  GT_U32			regAddr,
+    IN  GT_U16			data
+)
+{
+    DBG_INFO(("gprtSetGlobalReg Called.\n"));
+
+    /* Get the Scheduling bit.              */
+    if(hwWriteGlobalReg(dev,(GT_U8)regAddr,data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gprtGetGlobal2Reg
+*
+* DESCRIPTION:
+*       This routine reads Switch Global 2 Registers.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetGlobal2Reg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U32	     regAddr,
+    OUT GT_U16	     *data
+)
+{
+    GT_U16          u16Data;           /* The register's read data.    */
+
+    DBG_INFO(("gprtGetGlobal2Reg Called.\n"));
+
+    /* Get Phy Register. */
+    if(hwReadGlobal2Reg(dev,(GT_U8)regAddr,&u16Data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+	*data = u16Data;
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gprtSetGlobal2Reg
+*
+* DESCRIPTION:
+*       This routine writes Switch Global2 Registers.
+*
+* INPUTS:
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetGlobal2Reg
+(
+    IN  GT_QD_DEV		*dev,
+    IN  GT_U32			regAddr,
+    IN  GT_U16			data
+)
+{
+    DBG_INFO(("gprtSetGlobal2Reg Called.\n"));
+
+    /* Get the Scheduling bit.              */
+    if(hwWriteGlobal2Reg(dev,(GT_U8)regAddr,data) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+	return GT_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortLed.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortLed.c
new file mode 100755
index 0000000..aa4b542
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortLed.c
@@ -0,0 +1,801 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPortLed.c
+*
+* DESCRIPTION:
+*       API definitions for LED Control
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+static GT_STATUS convertLED2APP
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_LED_CFG	cfg,
+	IN  GT_U32		value,
+	OUT GT_U32		*data
+);
+
+
+static GT_STATUS convertAPP2LED
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_LED_CFG	cfg,
+	IN  GT_U32		value,
+	OUT GT_U32		*data
+);
+
+
+/*******************************************************************************
+* gprtSetLED
+*
+* DESCRIPTION:
+*		This API allows to configure 4 LED sections, Pulse stretch, Blink rate,
+*		and special controls.
+*
+* INPUTS:
+*		port	- the logical port number
+*		cfg 	- GT_LED_CFG value
+*		value 	- value to be configured
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gprtSetLED
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_LED_CFG	cfg,
+	IN  GT_U32		value
+)
+{
+	GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data;
+	GT_U32		ptr, conv, mask;
+    GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtSetLED Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort >= 5)
+		return GT_BAD_PARAM;
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_LED_CFG))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (cfg)
+	{
+		case GT_LED_CFG_LED0: 
+			ptr = 0;
+			mask = 0xF;
+			break;
+		case GT_LED_CFG_LED1: 
+			ptr = 0;
+			mask = 0xF0;
+			break;
+		case GT_LED_CFG_LED2: 
+			ptr = 1;
+			mask = 0xF;
+			break;
+		case GT_LED_CFG_LED3: 
+			ptr = 1;
+			mask = 0xF0;
+			break;
+		case GT_LED_CFG_PULSE_STRETCH: 
+			ptr = 6;
+			mask = 0x70;
+			break;
+		case GT_LED_CFG_BLINK_RATE: 
+			ptr = 6;
+			mask = 0x7;
+			break;
+		case GT_LED_CFG_SPECIAL_CONTROL: 
+			ptr = 7;
+			mask = (1 << dev->maxPorts) - 1;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	retVal = convertAPP2LED(dev,port,cfg,value,&conv);
+	if (retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the Table is ready. */
+	do	
+	{
+		retVal = hwGetPortRegField(dev,hwPort,QD_REG_LED_CONTROL,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+
+	} while(data == 1);
+
+	/* read the current data */
+	data = (GT_U16)(ptr << 12);
+
+	retVal = hwWritePortReg(dev, hwPort, QD_REG_LED_CONTROL, data);
+	if(retVal != GT_OK)
+  	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	retVal = hwGetPortRegField(dev, hwPort, QD_REG_LED_CONTROL,0,11,&data);
+	if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	/* overwrite the data */
+	data = (GT_U16)((1 << 15) | (ptr << 12) | (conv | (data & ~mask)));
+
+	retVal = hwWritePortReg(dev, hwPort, QD_REG_LED_CONTROL, data);
+	if(retVal != GT_OK)
+  	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtGetLED
+*
+* DESCRIPTION:
+*		This API allows to retrieve 4 LED sections, Pulse stretch, Blink rate,
+*		and special controls.
+*
+* INPUTS:
+*		port	- the logical port number
+*		cfg 	- GT_LED_CFG value
+*
+* OUTPUTS:
+*		value 	- value to be configured
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None
+*
+*******************************************************************************/
+GT_STATUS gprtGetLED
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_LED_CFG	cfg,
+	OUT GT_U32		*value
+)
+{
+	GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data;
+	GT_U32		ptr;
+    GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtGetLED Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+	if (hwPort >= 5)
+		return GT_BAD_PARAM;
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_LED_CFG))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (cfg)
+	{
+		case GT_LED_CFG_LED0: 
+			ptr = 0;
+			break;
+		case GT_LED_CFG_LED1: 
+			ptr = 0;
+			break;
+		case GT_LED_CFG_LED2: 
+			ptr = 1;
+			break;
+		case GT_LED_CFG_LED3: 
+			ptr = 1;
+			break;
+		case GT_LED_CFG_PULSE_STRETCH: 
+			ptr = 6;
+			break;
+		case GT_LED_CFG_BLINK_RATE: 
+			ptr = 6;
+			break;
+		case GT_LED_CFG_SPECIAL_CONTROL: 
+			ptr = 7;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the Table is ready. */
+	do	
+	{
+		retVal = hwGetPortRegField(dev,hwPort,QD_REG_LED_CONTROL,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+
+	} while(data == 1);
+
+	/* read the current data */
+	data = (GT_U16)(ptr << 12);
+
+	retVal = hwWritePortReg(dev, hwPort, QD_REG_LED_CONTROL, data);
+	if(retVal != GT_OK)
+  	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	retVal = hwGetPortRegField(dev, hwPort, QD_REG_LED_CONTROL,0,11,&data);
+	if(retVal != GT_OK)
+	{
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	retVal = convertLED2APP(dev,port,cfg,data,value);
+	if (retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	return GT_OK;
+}
+
+
+static GT_STATUS convertAPP2LED
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_LED_CFG	cfg,
+	IN  GT_U32		value,
+	OUT GT_U32		*data
+)
+{
+	GT_STATUS	retVal = GT_OK;
+
+	switch (cfg)
+	{
+		case GT_LED_CFG_LED0:
+			switch (value)
+			{
+				case GT_LED_LINK_ACT:
+					*data = 3;
+					break;
+				case GT_LED_LINK:
+					*data = 8;
+					break;
+				case GT_LED_10_LINK_ACT:
+					*data = 10;
+					break;
+				case GT_LED_10_LINK:
+					*data = 9;
+					break;
+				case GT_LED_1000_LINK_ACT:
+					*data = 2;
+					break;
+				case GT_LED_100_1000_LINK_ACT:
+					*data = 1;
+					break;
+				case GT_LED_100_1000_LINK:
+					*data = 11;
+					break;
+				case GT_LED_SPECIAL:
+					*data = 7;
+					break;
+				case GT_LED_DUPLEX_COL:
+					*data = 6;
+					break;
+				case GT_LED_PTP_ACT:
+					*data = 0;
+					break;
+				case GT_LED_FORCE_BLINK:
+					*data = 13;
+					break;
+				case GT_LED_FORCE_OFF:
+					*data = 14;
+					break;
+				case GT_LED_FORCE_ON:
+					*data = 15;
+					break;
+				default:
+					retVal = GT_BAD_PARAM;
+					break;
+			}
+			break;
+
+		case GT_LED_CFG_LED1:
+			switch (value)
+			{
+				case GT_LED_LINK_ACT_SPEED:
+					*data = 0;
+					break;
+				case GT_LED_100_LINK_ACT:
+					*data = 10;
+					break;
+				case GT_LED_100_LINK:
+					*data = 9;
+					break;
+				case GT_LED_1000_LINK:
+					*data = 3;
+					break;
+				case GT_LED_10_100_LINK_ACT:
+					*data = 1;
+					break;
+				case GT_LED_10_100_LINK:
+					*data = 11;
+					break;
+				case GT_LED_SPECIAL:
+					*data = 6;
+					break;
+				case GT_LED_DUPLEX_COL:
+					*data = 7;
+					break;
+				case GT_LED_ACTIVITY:
+					*data = 8;
+					break;
+				case GT_LED_PTP_ACT:
+					*data = 12;
+					break;
+				case GT_LED_FORCE_BLINK:
+					*data = 13;
+					break;
+				case GT_LED_FORCE_OFF:
+					*data = 14;
+					break;
+				case GT_LED_FORCE_ON:
+					*data = 15;
+					break;
+				default:
+					retVal = GT_BAD_PARAM;
+					break;
+			}
+			*data <<= 4;
+			break;
+
+		case GT_LED_CFG_LED2:
+			switch (value)
+			{
+				case GT_LED_10_LINK_ACT:
+					*data = 6;
+					break;
+				case GT_LED_100_LINK:
+					*data = 8;
+					break;
+				case GT_LED_1000_LINK_ACT:
+					*data = 10;
+					break;
+				case GT_LED_1000_LINK:
+					*data = 9;
+					break;
+				case GT_LED_10_1000_LINK_ACT:
+					*data = 1;
+					break;
+				case GT_LED_10_1000_LINK:
+					*data = 11;
+					break;
+				case GT_LED_100_1000_LINK_ACT:
+					*data = 7;
+					break;
+				case GT_LED_100_1000_LINK:
+					*data = 3;
+					break;
+				case GT_LED_SPECIAL:
+					*data = 2;
+					break;
+				case GT_LED_DUPLEX_COL:
+					*data = 0;
+					break;
+				case GT_LED_PTP_ACT:
+					*data = 12;
+					break;
+				case GT_LED_FORCE_BLINK:
+					*data = 13;
+					break;
+				case GT_LED_FORCE_OFF:
+					*data = 14;
+					break;
+				case GT_LED_FORCE_ON:
+					*data = 15;
+					break;
+				default:
+					retVal = GT_BAD_PARAM;
+					break;
+			}
+			break;
+
+		case GT_LED_CFG_LED3:
+			switch (value)
+			{
+				case GT_LED_LINK_ACT:
+					*data = 10;
+					break;
+				case GT_LED_LINK:
+					*data = 9;
+					break;
+				case GT_LED_10_LINK:
+					*data = 8;
+					break;
+				case GT_LED_100_LINK_ACT:
+					*data = 6;
+					break;
+				case GT_LED_10_1000_LINK_ACT:
+					*data = 7;
+					break;
+				case GT_LED_SPECIAL:
+					*data = 0;
+					break;
+				case GT_LED_DUPLEX_COL:
+					*data = 1;
+					break;
+				case GT_LED_ACTIVITY:
+					*data = 11;
+					break;
+				case GT_LED_PTP_ACT:
+					*data = 12;
+					break;
+				case GT_LED_FORCE_BLINK:
+					*data = 13;
+					break;
+				case GT_LED_FORCE_OFF:
+					*data = 14;
+					break;
+				case GT_LED_FORCE_ON:
+					*data = 15;
+					break;
+				default:
+					retVal = GT_BAD_PARAM;
+					break;
+			}
+			*data <<= 4;
+			break;
+
+		case GT_LED_CFG_PULSE_STRETCH:
+			if (value > 0x4)
+				retVal = GT_BAD_PARAM;
+			*data = value << 4;
+			break;
+		case GT_LED_CFG_BLINK_RATE:
+			if (value > 0x5)
+				retVal = GT_BAD_PARAM;
+			*data = value;
+			break;
+
+		case GT_LED_CFG_SPECIAL_CONTROL:
+			if (value >= (GT_U32)(1 << dev->maxPorts))
+				retVal = GT_BAD_PARAM;
+			*data = value;
+			break;
+			
+		default:
+			retVal = GT_BAD_PARAM;
+			break;
+	}
+
+	return retVal;
+
+}
+
+
+static GT_STATUS convertLED2APP
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_LED_CFG	cfg,
+	IN  GT_U32		value,
+	OUT GT_U32		*data
+)
+{
+	GT_STATUS retVal = GT_OK;
+
+	switch (cfg)
+	{
+		case GT_LED_CFG_LED0:
+			value &= 0xF;
+			switch (value)
+			{
+				case 0:
+					*data = GT_LED_PTP_ACT;
+					break;
+				case 1:
+					*data = GT_LED_100_1000_LINK_ACT;
+					break;
+				case 2:
+					*data = GT_LED_1000_LINK_ACT;
+					break;
+				case 3:
+					*data = GT_LED_LINK_ACT;
+					break;
+				case 4:
+					*data = GT_LED_RESERVE;
+					break;
+				case 5:
+					*data = GT_LED_RESERVE;
+					break;
+				case 6:
+					*data = GT_LED_DUPLEX_COL;
+					break;
+				case 7:
+					*data = GT_LED_SPECIAL;
+					break;
+				case 8:
+					*data = GT_LED_LINK;
+					break;
+				case 9:
+					*data = GT_LED_10_LINK;
+					break;
+				case 10:
+					*data = GT_LED_10_LINK_ACT;
+					break;
+				case 11:
+					*data = GT_LED_100_1000_LINK;
+					break;
+				case 12:
+					*data = GT_LED_PTP_ACT;
+					break;
+				case 13:
+					*data = GT_LED_FORCE_BLINK;
+					break;
+				case 14:
+					*data = GT_LED_FORCE_OFF;
+					break;
+				case 15:
+					*data = GT_LED_FORCE_ON;
+					break;
+				default:
+					retVal = GT_FAIL;
+					break;
+			}
+			break;
+
+		case GT_LED_CFG_LED1:
+			value >>= 4;
+			value &= 0xF;
+			switch (value)
+			{
+				case 0:
+					*data = GT_LED_LINK_ACT_SPEED;
+					break;
+				case 1:
+					*data = GT_LED_10_100_LINK_ACT;
+					break;
+				case 2:
+					*data = GT_LED_10_100_LINK_ACT;
+					break;
+				case 3:
+					*data = GT_LED_1000_LINK;
+					break;
+				case 4:
+					*data = GT_LED_RESERVE;
+					break;
+				case 5:
+					*data = GT_LED_RESERVE;
+					break;
+				case 6:
+					*data = GT_LED_SPECIAL;
+					break;
+				case 7:
+					*data = GT_LED_DUPLEX_COL;
+					break;
+				case 8:
+					*data = GT_LED_ACTIVITY;
+					break;
+				case 9:
+					*data = GT_LED_100_LINK;
+					break;
+				case 10:
+					*data = GT_LED_100_LINK_ACT;
+					break;
+				case 11:
+					*data = GT_LED_10_100_LINK;
+					break;
+				case 12:
+					*data = GT_LED_PTP_ACT;
+					break;
+				case 13:
+					*data = GT_LED_FORCE_BLINK;
+					break;
+				case 14:
+					*data = GT_LED_FORCE_OFF;
+					break;
+				case 15:
+					*data = GT_LED_FORCE_ON;
+					break;
+				default:
+					retVal = GT_FAIL;
+					break;
+			}
+			break;
+
+		case GT_LED_CFG_LED2:
+			value &= 0xF;
+			switch (value)
+			{
+				case 0:
+					*data = GT_LED_DUPLEX_COL;
+					break;
+				case 1:
+					*data = GT_LED_10_1000_LINK_ACT;
+					break;
+				case 2:
+					*data = GT_LED_SPECIAL;
+					break;
+				case 3:
+					*data = GT_LED_100_1000_LINK;
+					break;
+				case 4:
+					*data = GT_LED_RESERVE;
+					break;
+				case 5:
+					*data = GT_LED_RESERVE;
+					break;
+				case 6:
+					*data = GT_LED_10_LINK_ACT;
+					break;
+				case 7:
+					*data = GT_LED_100_1000_LINK_ACT;
+					break;
+				case 8:
+					*data = GT_LED_100_LINK;
+					break;
+				case 9:
+					*data = GT_LED_1000_LINK;
+					break;
+				case 10:
+					*data = GT_LED_1000_LINK_ACT;
+					break;
+				case 11:
+					*data = GT_LED_10_1000_LINK;
+					break;
+				case 12:
+					*data = GT_LED_PTP_ACT;
+					break;
+				case 13:
+					*data = GT_LED_FORCE_BLINK;
+					break;
+				case 14:
+					*data = GT_LED_FORCE_OFF;
+					break;
+				case 15:
+					*data = GT_LED_FORCE_ON;
+					break;
+				default:
+					retVal = GT_FAIL;
+					break;
+			}
+			break;
+
+		case GT_LED_CFG_LED3:
+			value >>= 4;
+			value &= 0xF;
+			switch (value)
+			{
+				case 0:
+					*data = GT_LED_SPECIAL;
+					break;
+				case 1:
+					*data = GT_LED_DUPLEX_COL;
+					break;
+				case 2:
+					*data = GT_LED_DUPLEX_COL;
+					break;
+				case 3:
+					*data = GT_LED_SPECIAL;
+					break;
+				case 4:
+					*data = GT_LED_RESERVE;
+					break;
+				case 5:
+					*data = GT_LED_RESERVE;
+					break;
+				case 6:
+					*data = GT_LED_100_LINK_ACT;
+					break;
+				case 7:
+					*data = GT_LED_10_1000_LINK_ACT;
+					break;
+				case 8:
+					*data = GT_LED_10_LINK;
+					break;
+				case 9:
+					*data = GT_LED_LINK;
+					break;
+				case 10:
+					*data = GT_LED_LINK_ACT;
+					break;
+				case 11:
+					*data = GT_LED_ACTIVITY;
+					break;
+				case 12:
+					*data = GT_LED_PTP_ACT;
+					break;
+				case 13:
+					*data = GT_LED_FORCE_BLINK;
+					break;
+				case 14:
+					*data = GT_LED_FORCE_OFF;
+					break;
+				case 15:
+					*data = GT_LED_FORCE_ON;
+					break;
+				default:
+					retVal = GT_FAIL;
+					break;
+			}
+			break;
+
+		case GT_LED_CFG_PULSE_STRETCH:
+			*data = (value >> 4) & 0x7;
+			break;
+
+		case GT_LED_CFG_BLINK_RATE:
+			*data = value & 0x7;
+			break;
+
+		case GT_LED_CFG_SPECIAL_CONTROL:
+			*data = value & ((1 << dev->maxPorts) - 1);
+			break;
+
+		default:
+			retVal = GT_BAD_PARAM;
+			break;
+	}
+
+	return retVal;
+
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortPav.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortPav.c
new file mode 100755
index 0000000..f900096
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortPav.c
@@ -0,0 +1,270 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPortPav.c
+*
+* DESCRIPTION:
+*       API definitions to handle Port Association Vector (0xB).
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/*******************************************************************************
+* gpavSetPAV
+*
+* DESCRIPTION:
+*       This routine sets the Port Association Vector 
+*
+* INPUTS:
+*       port	- logical port number.
+*       pav 	- Port Association Vector 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpavSetPAV
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT	 port,
+    IN GT_U16	 pav
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U16	    	hwPav;
+
+    DBG_INFO(("gpavSetPAV Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+    
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_PORT_MONITORING)) != GT_OK ) 
+      return retVal;
+	
+	/*
+	 * translate Logical Port Vector to Physical Port Vector.
+	 */
+	hwPav = (GT_U16)GT_LPORTVEC_2_PORTVEC(pav);
+
+	if(hwPav == (GT_U16)GT_INVALID_PORT_VEC)
+	{
+		return GT_BAD_PARAM;
+	}
+		
+    /* there are 7 ports in the switch */
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_ASSOCIATION,0,dev->maxPorts,hwPav);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gpavGetPAV
+*
+* DESCRIPTION:
+*       This routine gets the Port Association Vector 
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       pav 	- Port Association Vector 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpavGetPAV
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_U16   *pav
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gpavGetPAV Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_PORT_MONITORING)) != GT_OK ) 
+      return retVal;
+	
+    if(pav == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    retVal = hwGetPortRegField(dev,phyPort,(GT_U8)QD_REG_PORT_ASSOCIATION,0,dev->maxPorts,&data );
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	/*
+	 * translate Physical Port Vector to Logical Port Vector.
+	 */
+    *pav = (GT_U16)GT_PORTVEC_2_LPORTVEC(data);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gpavSetIngressMonitor
+*
+* DESCRIPTION:
+*       This routine sets the Ingress Monitor bit in the PAV.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the ingress monitor bit in the PAV
+*              GT_FALSE: Ingress Monitor enabled 
+*              GT_TRUE:  Ingress Monitor disabled 
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpavSetIngressMonitor
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT  port,
+    IN GT_BOOL   mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("gpavSetIngressMonitorCalled.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+    BOOL_2_BIT(mode,data);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENABLE_MONITORING))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_PORT_ASSOCIATION,15,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gpavGetIngressMonitor
+*
+* DESCRIPTION:
+*       This routine gets the Ingress Monitor bit in the PAV.
+*
+* INPUTS:
+*       port - the logical port number.
+*       
+* OUTPUTS:
+*       mode - the ingress monitor bit in the PAV
+*              GT_FALSE: Ingress Monitor enabled 
+*              GT_TRUE:  Ingress Monitor disabled 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gpavGetIngressMonitor
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetIngressMonitor Called.\n"));
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENABLE_MONITORING))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_PORT_ASSOCIATION,15,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortRateCtrl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortRateCtrl.c
new file mode 100755
index 0000000..d9a5cb1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortRateCtrl.c
@@ -0,0 +1,2811 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPortRateCtrl.c
+*
+* DESCRIPTION:
+*       API definitions to handle port rate control registers (0xA).
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/*
+ Convert given hw Rate Limit to sw defined Rate Limit.
+ This routine is only for Gigabit Managed Switch Device.
+ If the given device is not an accepted device, it'll simply copy the hw limit 
+ to sw limit.
+*/
+static GT_STATUS cRateLimit(GT_QD_DEV *dev, GT_U32 hwLimit, GT_U32* swLimit)
+{
+	GT_U32 sLimit, hLimit, startLimit, endLimit, i;
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH|DEV_ENHANCED_FE_SWITCH))
+	{
+		*swLimit = hwLimit;
+		return GT_OK;
+	}
+
+	if(hwLimit == 0)
+	{
+		*swLimit = GT_NO_LIMIT;
+		return GT_OK;
+	}
+		
+	sLimit = 1000;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH))
+		hLimit = GT_GET_RATE_LIMIT3(sLimit);
+	else if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
+		hLimit = GT_GET_RATE_LIMIT2(sLimit);
+	else
+		hLimit = GT_GET_RATE_LIMIT(sLimit);
+	if(hLimit == hwLimit)
+	{
+		*swLimit = GT_1M;
+		return GT_OK;
+	}
+	
+	if(hLimit > hwLimit)
+	{
+		startLimit = 2000;
+		endLimit = 256000;
+		*swLimit = GT_2M;
+	}
+	else
+	{
+		startLimit = 128;
+		endLimit = 512;
+		*swLimit = GT_128K;
+	}
+	
+	i = 0;
+	for(sLimit=startLimit;sLimit<=endLimit;sLimit *= 2, i++)
+	{
+		if (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH))
+			hLimit = GT_GET_RATE_LIMIT3(sLimit);
+		else if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
+			hLimit = GT_GET_RATE_LIMIT2(sLimit);
+		else
+			hLimit = GT_GET_RATE_LIMIT(sLimit);
+
+		if(hLimit == 0)
+			hLimit = 1;
+
+		if(hLimit == hwLimit)
+		{
+			*swLimit += i;
+			return GT_OK;
+		}
+
+		if(hLimit < hwLimit)
+			break;
+	}
+
+	*swLimit = hwLimit;
+	return GT_OK;
+}
+
+
+/*
+ Convert given sw defined Burst Rate to meaningful number.
+*/
+static GT_STATUS cBurstEnum2Number(GT_QD_DEV *dev, GT_BURST_RATE rate, GT_U32 *rLimit)
+{
+	GT_U32 rateLimit;
+
+	GT_UNUSED_PARAM(dev);
+
+	switch(rate)
+	{
+		case GT_BURST_NO_LIMIT :
+				rateLimit = 0; /* MAX_RATE_LIMIT; */
+				break;
+		case GT_BURST_64K :
+				rateLimit = 64;
+				break;
+		case GT_BURST_128K :
+				rateLimit = 128;
+				break;
+		case GT_BURST_256K :
+				rateLimit = 256;
+				break;
+		case GT_BURST_384K :
+				rateLimit = 384;
+				break;
+		case GT_BURST_512K :
+				rateLimit = 512;
+				break;
+		case GT_BURST_640K :
+				rateLimit = 640;
+				break;
+		case GT_BURST_768K :
+				rateLimit = 768;
+				break;
+		case GT_BURST_896K :
+				rateLimit = 896;
+				break;
+		case GT_BURST_1M :
+				rateLimit = 1000;
+				break;
+		case GT_BURST_1500K :
+				rateLimit = 1500;
+				break;
+		case GT_BURST_2M :
+				rateLimit = 2000;
+				break;
+		case GT_BURST_4M :
+				rateLimit = 4000;
+				break;
+		case GT_BURST_8M :
+				rateLimit = 8000;
+				break;
+		case GT_BURST_16M :
+				rateLimit = 16000;
+				break;
+		case GT_BURST_32M :
+				rateLimit = 32000;
+				break;
+		case GT_BURST_64M :
+				rateLimit = 64000;
+				break;
+		case GT_BURST_128M :
+				rateLimit = 128000;
+				break;
+		case GT_BURST_256M :
+				rateLimit = 256000;
+				break;
+		default :
+				return GT_BAD_PARAM;
+	}
+
+	*rLimit = rateLimit;
+	return GT_OK;
+}
+
+
+/*
+ Convert given hw Burst Rate Limit to sw defined Burst Rate Limit.
+*/
+static GT_STATUS cBurstRateLimit(GT_QD_DEV *dev, GT_U32 burstSize, GT_U32 hwLimit, GT_BURST_RATE* swLimit)
+{
+	GT_BURST_RATE sLimit, startLimit, endLimit;
+	GT_U32 rLimit, tmpLimit;
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+	if(hwLimit == 0)
+	{
+		*swLimit = GT_BURST_NO_LIMIT;
+		return GT_OK;
+	}
+		
+	startLimit = GT_BURST_64K;
+	endLimit = GT_BURST_256M;
+	
+	for(sLimit=startLimit;sLimit<=endLimit;sLimit++)
+	{
+		if((retVal = cBurstEnum2Number(dev, sLimit, &rLimit)) != GT_OK)
+		{
+        	DBG_INFO(("Failed.\n"));
+	   	    return retVal;
+		}
+
+		tmpLimit = GT_GET_BURST_RATE_LIMIT(burstSize,rLimit);
+
+		if(hwLimit == tmpLimit)
+		{
+			*swLimit = sLimit;
+			return GT_OK;
+		}
+	}
+
+	return GT_FAIL;
+}
+
+
+/*
+ Convert given sw defined Burst Rate to meaningful number.
+*/
+static GT_STATUS cTCPBurstRate(GT_QD_DEV *dev, GT_BURST_RATE rate, GT_U32 *data)
+{
+	GT_UNUSED_PARAM(dev);
+
+	switch(rate)
+	{
+		case GT_BURST_NO_LIMIT :
+				*data = 0; /* MAX_RATE_LIMIT; */
+				break;
+		case GT_BURST_64K :
+				*data = 0x1D00;
+				break;
+		case GT_BURST_128K :
+				*data = 0x3FFF;
+				break;
+		case GT_BURST_256K :
+				*data = 0x7FFF;
+				break;
+		case GT_BURST_384K :
+				*data = 0x7DE0;
+				break;
+		case GT_BURST_512K :
+				*data = 0x76F0;
+				break;
+		case GT_BURST_640K :
+				*data = 0x7660;
+				break;
+		case GT_BURST_768K :
+				*data = 0x7600;
+				break;
+		case GT_BURST_896K :
+				*data = 0x74EF;
+				break;
+		case GT_BURST_1M :
+				*data = 0x7340;
+				break;
+		case GT_BURST_1500K :
+				*data = 0x7300;
+				break;
+		default :
+				return GT_BAD_PARAM;
+	}
+
+	return GT_OK;
+}
+
+static GT_STATUS setEnhancedERate(GT_QD_DEV *dev, GT_LPORT port, GT_ERATE_TYPE *rateType)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data;
+	GT_U32		rate, eDec;
+	GT_PIRL_ELIMIT_MODE		mode;
+    GT_U8		phyPort;        /* Physical port.               */
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	if((retVal = grcGetELimitMode(dev,port,&mode)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	if (mode == GT_PIRL_ELIMIT_FRAME)	
+	{
+		/* Count Per Frame */
+		rate = rateType->fRate;
+
+		if (rate == 0) /* disable egress rate limit */
+		{
+			eDec = 0;
+			data = 0;
+		}
+		else if((rate < 7600)  || (rate > 1488000))
+		{
+			return GT_BAD_PARAM;
+		}
+		else
+		{
+			eDec = 1;
+			data = (GT_U16)GT_GET_RATE_LIMIT_PER_FRAME(rate,eDec);
+		}
+	}
+	else
+	{
+		/* Count Per Byte */
+		rate = rateType->kbRate;
+
+		if(rate == 0)
+		{
+			eDec = 0;
+		}
+		else if(rate < 1000)	/* less than 1Mbps */
+		{
+			/* it should be divided by 64 */
+			if(rate % 64)
+				return GT_BAD_PARAM;
+			eDec = rate/64;
+		}
+		else if(rate <= 100000)	/* less than or equal to 100Mbps */
+		{
+			/* it should be divided by 1000 */
+			if(rate % 1000)
+				return GT_BAD_PARAM;
+			eDec = rate/1000;
+		}
+		else if(rate <= 1000000)	/* less than or equal to 1000Mbps */
+		{
+			/* it should be divided by 10000 */
+			if(rate % 10000)
+				return GT_BAD_PARAM;
+			eDec = rate/10000;
+		}
+		else
+			return GT_BAD_PARAM;
+
+		if(rate == 0)
+		{
+			data = 0;
+		}
+		else
+		{
+			data = (GT_U16)GT_GET_RATE_LIMIT_PER_BYTE(rate,eDec);
+		}
+	}
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL0,0,7,(GT_U16)eDec);
+	if(retVal != GT_OK)
+	{
+    	DBG_INFO(("Failed.\n"));
+    	return retVal;
+	}
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,0,12,(GT_U16)data );
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+static GT_STATUS getEnhancedERate(GT_QD_DEV *dev, GT_LPORT port, GT_ERATE_TYPE *rateType)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		rate, eDec;
+	GT_PIRL_ELIMIT_MODE		mode;
+    GT_U8		phyPort;        /* Physical port.               */
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	if((retVal = grcGetELimitMode(dev,port,&mode)) != GT_OK)
+	{
+		return retVal;
+	}
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL0,0,7,&eDec);
+	if(retVal != GT_OK)
+	{
+    	DBG_INFO(("Failed.\n"));
+    	return retVal;
+	}
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,0,12,&rate );
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	if (mode == GT_PIRL_ELIMIT_FRAME)	
+	{
+		rateType->fRate = GT_GET_RATE_LIMIT_PER_FRAME(rate,eDec);
+	}
+	else
+	{
+		/* Count Per Byte */
+		rateType->kbRate = GT_GET_RATE_LIMIT_PER_BYTE(rate,eDec);
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetLimitMode
+*
+* DESCRIPTION:
+*       This routine sets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       port	- logical port number.
+*       mode 	- rate control ingress limit mode. 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetLimitMode
+(
+    IN GT_QD_DEV             *dev,
+    IN GT_LPORT 	     port,
+    IN GT_RATE_LIMIT_MODE    mode
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetLimitMode Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+#if 0 /* Dima M */
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
+      return retVal;
+#endif
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,14,2,(GT_U16)mode );
+	}
+	else
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,14,2,(GT_U16)mode );
+	}
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetLimitMode
+*
+* DESCRIPTION:
+*       This routine gets the port's rate control ingress limit mode.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       mode 	- rate control ingress limit mode. 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetLimitMode
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_RATE_LIMIT_MODE    *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetLimitMode Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+#if 0 /* Dima M */
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
+      return retVal;
+#endif
+	
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,14,2,&data );
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,14,2,&data );
+	}
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *mode = data;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcSetPri3Rate
+*
+* DESCRIPTION:
+*       This routine sets the ingress data rate limit for priority 3 frames.
+*       Priority 3 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the priority 3 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri2Rate
+*              GT_TRUE:  use twice the rate as Pri2Rate
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetPri3Rate
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetPri3Rate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
+      return retVal;
+	
+    BOOL_2_BIT(mode,data);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,14,1,data );
+	}
+	else
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,13,1,data);
+	}
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetPri3Rate
+*
+* DESCRIPTION:
+*       This routine gets the ingress data rate limit for priority 3 frames.
+*       Priority 3 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       
+* OUTPUTS:
+*       mode - the priority 3 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri2Rate
+*              GT_TRUE:  use twice the rate as Pri2Rate
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetPri3Rate
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetPri3Rate Called.\n"));
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
+      return retVal;
+	
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,14,1,&data );
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,13,1,&data);
+	}
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetPri2Rate
+*
+* DESCRIPTION:
+*       This routine sets the ingress data rate limit for priority 2 frames.
+*       Priority 2 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the priority 2 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri1Rate
+*              GT_TRUE:  use twice the rate as Pri1Rate
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetPri2Rate
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT port,
+    IN GT_BOOL  mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetPri2Rate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
+      return retVal;
+	
+    BOOL_2_BIT(mode,data);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,13,1,data );
+	}
+	else
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,12,1,data);
+	}
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetPri2Rate
+*
+* DESCRIPTION:
+*       This routine gets the ingress data rate limit for priority 2 frames.
+*       Priority 2 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       
+* OUTPUTS:
+*       mode - the priority 2 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri1Rate
+*              GT_TRUE:  use twice the rate as Pri1Rate
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetPri2Rate
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetPri2Rate Called.\n"));
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
+      return retVal;
+	
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,13,1,&data );
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,12,1,&data);
+	}
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetPri1Rate
+*
+* DESCRIPTION:
+*       This routine sets the ingress data rate limit for priority 1 frames.
+*       Priority 1 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - the priority 1 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri0Rate
+*              GT_TRUE:  use twice the rate as Pri0Rate
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetPri1Rate
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT  port,
+    IN GT_BOOL   mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetPri1Rate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
+      return retVal;
+	
+    BOOL_2_BIT(mode,data);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,12,1,data );
+	}
+	else
+	{
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,11,1,data);
+	}
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetPri1Rate
+*
+* DESCRIPTION:
+*       This routine gets the ingress data rate limit for priority 1 frames.
+*       Priority 1 frames will be discarded after the ingress rate selection
+*       is reached or exceeded.
+*
+* INPUTS:
+*       port - the logical port number.
+*       
+* OUTPUTS:
+*       mode - the priority 1 frame rate limit mode
+*              GT_FALSE: use the same rate as Pri0Rate
+*              GT_TRUE:  use twice the rate as Pri0Rate
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetPri1Rate
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_BOOL  *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetPri1Rate Called.\n"));
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
+      return retVal;
+	
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,12,1,&data );
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,11,1,&data);
+	}
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetPri0Rate
+*
+* DESCRIPTION:
+*       This routine sets the port's ingress data limit for priority 0 frames.
+*
+* INPUTS:
+*       port	- logical port number.
+*       rate    - ingress data rate limit for priority 0 frames. These frames
+*       	  will be discarded after the ingress rate selected is reached 
+*       	  or exceeded. 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*			GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_PRI0_RATE enum
+*			are supported only by Gigabit Ethernet Switch.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetPri0Rate
+(
+    IN GT_QD_DEV       *dev,
+    IN GT_LPORT        port,
+    IN GT_PRI0_RATE    rate
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+	GT_U32			rateLimit, tmpLimit;
+
+    DBG_INFO(("grcSetPri0Rate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
+      return retVal;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
+	{
+		dev->devStorage &= ~(GT_RATE_ENUM_NOT_USED);
+		switch(rate)
+		{
+			case GT_NO_LIMIT :
+					rateLimit = 0; /* MAX_RATE_LIMIT; */
+					break;
+			case GT_128K :
+					rateLimit = 128;
+					break;
+			case GT_256K :
+					rateLimit = 256;
+					break;
+			case GT_512K :
+					rateLimit = 512;
+					break;
+			case GT_1M :
+					rateLimit = 1000;
+					break;
+			case GT_2M :
+					rateLimit = 2000;
+					break;
+			case GT_4M :
+					rateLimit = 4000;
+					break;
+			case GT_8M :
+					rateLimit = 8000;
+					break;
+			case GT_16M :
+					rateLimit = 16000;
+					break;
+			case GT_32M :
+					rateLimit = 32000;
+					break;
+			case GT_64M :
+					rateLimit = 64000;
+					break;
+			case GT_128M :
+					rateLimit = 128000;
+					break;
+			case GT_256M :
+					rateLimit = 256000;
+					break;
+			default :
+					rateLimit = (GT_U32)rate;
+					dev->devStorage |= GT_RATE_ENUM_NOT_USED;
+					break;					
+		}
+
+		if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
+			tmpLimit = GT_GET_RATE_LIMIT2(rateLimit);
+		else
+			tmpLimit = GT_GET_RATE_LIMIT(rateLimit);
+
+		if((tmpLimit == 0) && (rateLimit != 0))
+			rateLimit = 1;
+		else
+			rateLimit = tmpLimit;
+
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,12,(GT_U16)rateLimit );
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	}
+	else
+	{
+		switch(rate)
+		{
+			case GT_NO_LIMIT :
+			case GT_128K :
+			case GT_256K :
+			case GT_512K :
+			case GT_1M :
+			case GT_2M :
+			case GT_4M :
+			case GT_8M :
+					break;
+			default :
+					return GT_BAD_PARAM;
+		}
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,8,3,(GT_U16)rate );
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	}
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetPri0Rate
+*
+* DESCRIPTION:
+*       This routine gets the port's ingress data limit for priority 0 frames.
+*
+* INPUTS:
+*       port	- logical port number to set.
+*
+* OUTPUTS:
+*       rate    - ingress data rate limit for priority 0 frames. These frames
+*       	  will be discarded after the ingress rate selected is reached 
+*       	  or exceeded. 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*			GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_PRI0_RATE enum
+*			are supported only by Gigabit Ethernet Switch.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetPri0Rate
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_PRI0_RATE    *rate
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+	GT_U32			tmpLimit;
+
+    DBG_INFO(("grcGetPri0Rate Called.\n"));
+
+    if(rate == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
+      return retVal;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,12,&data);
+		tmpLimit = (GT_U32)data;
+
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+
+		if(dev->devStorage & GT_RATE_ENUM_NOT_USED)
+		{
+			if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
+				*rate = GT_GET_RATE_LIMIT2(tmpLimit);
+			else
+				*rate = GT_GET_RATE_LIMIT(tmpLimit);
+		}
+		else
+		{
+			cRateLimit(dev, tmpLimit, (GT_U32*)rate);
+		}
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,8,3,&data );
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	    *rate = data;
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcSetBytesCount
+*
+* DESCRIPTION:
+*       This routine sets the byets to count for limiting needs to be determined
+*
+* INPUTS:
+*       port	  - logical port number to set.
+*    	limitMGMT - GT_TRUE: To limit and count MGMT frame bytes
+*    		    GT_FALSE: otherwise
+*    	countIFG  - GT_TRUE: To count IFG bytes
+*    		    GT_FALSE: otherwise
+*    	countPre  - GT_TRUE: To count Preamble bytes
+*    		    GT_FALSE: otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetBytesCount
+(
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT  port,
+    IN GT_BOOL 	 limitMGMT,
+    IN GT_BOOL 	 countIFG,
+    IN GT_BOOL 	 countPre
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U16          data;           /* data for bytes count         */
+
+    DBG_INFO(("grcSetBytesCount Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
+      return retVal;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+	    BOOL_2_BIT(limitMGMT,data);
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,15,1,data );
+		if (retVal != GT_OK)
+			return retVal;
+
+		data = 0;
+		if( countIFG == GT_TRUE ) data |= 2;
+		if( countPre == GT_TRUE ) data |= 1;
+
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,12,2,data );
+	}
+	else
+	{
+		data = 0;
+	    if(	limitMGMT == GT_TRUE ) data |=4;
+    	if(	 countIFG == GT_TRUE ) data |=2;
+	    if(	 countPre == GT_TRUE ) data |=1;
+
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,4,3,data );
+	}
+
+   	if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetBytesCount
+*
+* DESCRIPTION:
+*       This routine gets the byets to count for limiting needs to be determined
+*
+* INPUTS:
+*       port	- logical port number 
+*
+* OUTPUTS:
+*    	limitMGMT - GT_TRUE: To limit and count MGMT frame bytes
+*    		    GT_FALSE: otherwise
+*    	countIFG  - GT_TRUE: To count IFG bytes
+*    		    GT_FALSE: otherwise
+*    	countPre  - GT_TRUE: To count Preamble bytes
+*    		    GT_FALSE: otherwise
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetBytesCount
+(	
+    IN GT_QD_DEV *dev,
+    IN GT_LPORT  port,
+    IN GT_BOOL 	 *limitMGMT,
+    IN GT_BOOL 	 *countIFG,
+    IN GT_BOOL 	 *countPre
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetBytesCount Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
+      return retVal;
+
+    if (limitMGMT == NULL || countIFG == NULL || countPre == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+   	*limitMGMT = *countIFG = *countPre = GT_FALSE;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,15,1,&data );
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("Failed.\n"));
+			return retVal;
+		}
+
+	    BIT_2_BOOL(data,*limitMGMT);
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,12,2,&data );
+		if (retVal != GT_OK)
+		{
+    	    DBG_INFO(("Failed.\n"));
+			return retVal;
+		}
+
+		if( data & 0x2 ) *countIFG = GT_TRUE;
+		if( data & 0x1 ) *countPre = GT_TRUE;
+
+	}
+	else
+	{
+
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,4,3,&data );
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+        	return retVal;
+	    }
+
+	    if ( data & 4 ) *limitMGMT = GT_TRUE;
+    	if ( data & 2 ) *countIFG  = GT_TRUE;
+	    if ( data & 1 ) *countPre  = GT_TRUE;
+	
+	}
+	    
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcSetEgressRate
+*
+* DESCRIPTION:
+*       This routine sets the port's egress data limit.
+*		
+*
+* INPUTS:
+*       port      - logical port number.
+*       rateType  - egress data rate limit (GT_ERATE_TYPE union type). 
+*					union type is used to support multiple devices with the
+*					different formats of egress rate.
+*					GT_ERATE_TYPE has the following fields:
+*						definedRate - GT_EGRESS_RATE enum type should used for the 
+*							following devices:
+*							88E6218, 88E6318, 88E6063, 88E6083, 88E6181, 88E6183,
+*							88E6093, 88E6095, 88E6185, 88E6108, 88E6065, 88E6061, 
+*							and their variations
+*						kbRate - rate in kbps that should used for the following 
+*							devices:
+*							88E6097, 88E6096 with the GT_PIRL_ELIMIT_MODE of 
+*								GT_PIRL_ELIMIT_LAYER1,
+*								GT_PIRL_ELIMIT_LAYER2, or 
+*								GT_PIRL_ELIMIT_LAYER3 (see grcSetELimitMode)
+*							64kbps ~ 1Mbps    : increments of 64kbps,
+*							1Mbps ~ 100Mbps   : increments of 1Mbps, and
+*							100Mbps ~ 1000Mbps: increments of 10Mbps
+*							Therefore, the valid values are:
+*								64, 128, 192, 256, 320, 384,..., 960,
+*								1000, 2000, 3000, 4000, ..., 100000,
+*								110000, 120000, 130000, ..., 1000000.
+*						fRate - frame per second that should used for the following
+*							devices:
+*							88E6097, 88E6096 with GT_PIRL_ELIMIT_MODE of 
+*								GT_PIRL_ELIMIT_FRAME
+*							Valid values are between 7600 and 1488000
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS: 
+*			GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_EGRESS_RATE enum
+*			are supported only by Gigabit Ethernet Switch.
+*
+*******************************************************************************/
+GT_STATUS grcSetEgressRate
+(
+    IN GT_QD_DEV       *dev,
+    IN GT_LPORT        port,
+    IN GT_ERATE_TYPE   *rateType
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+	GT_U32			rateLimit, tmpLimit;
+    GT_EGRESS_RATE  rate;
+
+    DBG_INFO(("grcSetEgressRate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_EGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
+      return retVal;
+	
+	if (IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
+	{
+		return setEnhancedERate(dev,port,rateType);
+	}
+
+	rate = rateType->definedRate;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+	{
+		dev->devStorage &= ~(GT_RATE_ENUM_NOT_USED);
+		switch(rate)
+		{
+			case GT_NO_LIMIT :
+					rateLimit = 0; /* MAX_RATE_LIMIT; */
+					break;
+			case GT_128K :
+					rateLimit = 128;
+					break;
+			case GT_256K :
+					rateLimit = 256;
+					break;
+			case GT_512K :
+					rateLimit = 512;
+					break;
+			case GT_1M :
+					rateLimit = 1000;
+					break;
+			case GT_2M :
+					rateLimit = 2000;
+					break;
+			case GT_4M :
+					rateLimit = 4000;
+					break;
+			case GT_8M :
+					rateLimit = 8000;
+					break;
+			case GT_16M :
+					rateLimit = 16000;
+					break;
+			case GT_32M :
+					rateLimit = 32000;
+					break;
+			case GT_64M :
+					rateLimit = 64000;
+					break;
+			case GT_128M :
+					rateLimit = 128000;
+					break;
+			case GT_256M :
+					rateLimit = 256000;
+					break;
+			default :
+					rateLimit = (GT_U32)rate;
+					dev->devStorage |= GT_RATE_ENUM_NOT_USED;
+					break;					
+		}
+
+		if (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH))
+			tmpLimit = GT_GET_RATE_LIMIT3(rateLimit);
+		else if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
+			tmpLimit = GT_GET_RATE_LIMIT2(rateLimit);
+		else
+			tmpLimit = GT_GET_RATE_LIMIT(rateLimit);
+
+		if((tmpLimit == 0) && (rateLimit != 0))
+			rateLimit = 1;
+		else
+			rateLimit = tmpLimit;
+
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,0,12,(GT_U16)rateLimit );
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	}
+	else
+	{
+		switch(rate)
+		{
+			case GT_NO_LIMIT :
+			case GT_128K :
+			case GT_256K :
+			case GT_512K :
+			case GT_1M :
+			case GT_2M :
+			case GT_4M :
+			case GT_8M :
+					break;
+			default :
+					return GT_BAD_PARAM;
+		}
+	    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,0,3,(GT_U16)rate );
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetEgressRate
+*
+* DESCRIPTION:
+*       This routine gets the port's egress data limit.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       rateType  - egress data rate limit (GT_ERATE_TYPE union type). 
+*					union type is used to support multiple devices with the
+*					different formats of egress rate.
+*					GT_ERATE_TYPE has the following fields:
+*						definedRate - GT_EGRESS_RATE enum type should used for the 
+*							following devices:
+*							88E6218, 88E6318, 88E6063, 88E6083, 88E6181, 88E6183,
+*							88E6093, 88E6095, 88E6185, 88E6108, 88E6065, 88E6061, 
+*							and their variations
+*						kbRate - rate in kbps that should used for the following 
+*							devices:
+*							88E6097, 88E6096 with the GT_PIRL_ELIMIT_MODE of 
+*								GT_PIRL_ELIMIT_LAYER1,
+*								GT_PIRL_ELIMIT_LAYER2, or 
+*								GT_PIRL_ELIMIT_LAYER3 (see grcSetELimitMode)
+*							64kbps ~ 1Mbps    : increments of 64kbps,
+*							1Mbps ~ 100Mbps   : increments of 1Mbps, and
+*							100Mbps ~ 1000Mbps: increments of 10Mbps
+*							Therefore, the valid values are:
+*								64, 128, 192, 256, 320, 384,..., 960,
+*								1000, 2000, 3000, 4000, ..., 100000,
+*								110000, 120000, 130000, ..., 1000000.
+*						fRate - frame per second that should used for the following
+*							devices:
+*							88E6097, 88E6096 with GT_PIRL_ELIMIT_MODE of 
+*								GT_PIRL_ELIMIT_FRAME
+*							Valid values are between 7600 and 1488000
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+*			GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_EGRESS_RATE enum
+*			are supported only by Gigabit Ethernet Switch.
+*
+*******************************************************************************/
+GT_STATUS grcGetEgressRate
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_ERATE_TYPE  *rateType
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+	GT_U32			tmpLimit,tmpRate;
+
+    DBG_INFO(("grcGetEgressRate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_EGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
+      return retVal;
+	
+    if(rateType == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
+	{
+		return getEnhancedERate(dev,port,rateType);
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,0,12,&data );
+		tmpLimit = (GT_U32)data;
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+
+		if(dev->devStorage & GT_RATE_ENUM_NOT_USED)
+		{
+			if (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH))
+				tmpRate = GT_GET_RATE_LIMIT3(tmpLimit);
+			else if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
+				tmpRate = GT_GET_RATE_LIMIT2(tmpLimit);
+			else
+				tmpRate = GT_GET_RATE_LIMIT(tmpLimit);
+			rateType->kbRate = tmpRate;
+		}
+		else
+		{
+			cRateLimit(dev, tmpLimit, &tmpRate);
+			rateType->definedRate = (GT_EGRESS_RATE)tmpRate;
+		}
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,0,3,&data );
+	    if(retVal != GT_OK)
+    	{
+	        DBG_INFO(("Failed.\n"));
+    	    return retVal;
+	    }
+		
+		rateType->definedRate = (GT_EGRESS_RATE)data;
+	}
+
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetBurstRate
+*
+* DESCRIPTION:
+*       This routine sets the port's ingress data limit based on burst size.
+*
+* INPUTS:
+*       port	- logical port number.
+*       bsize	- burst size.
+*       rate    - ingress data rate limit. These frames will be discarded after 
+*				the ingress rate selected is reached or exceeded. 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters 
+*								Minimum rate for Burst Size 24K byte is 128Kbps
+*								Minimum rate for Burst Size 48K byte is 256Kbps
+*								Minimum rate for Burst Size 96K byte is 512Kbps
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*		If the device supports both priority based Rate Limiting and burst size
+*		based Rate limiting, user has to manually change the mode to burst size
+*		based Rate limiting by calling gsysSetRateLimitMode.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetBurstRate
+(
+    IN GT_QD_DEV       *dev,
+    IN GT_LPORT        port,
+    IN GT_BURST_SIZE   bsize,
+    IN GT_BURST_RATE   rate
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+	GT_U32			rateLimit;
+	GT_U32			burstSize =0;
+
+    DBG_INFO(("grcSetBurstRate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_1))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+	switch (bsize)
+	{
+		case GT_BURST_SIZE_12K:
+			burstSize = 0;
+			break;
+		case GT_BURST_SIZE_24K:
+			if ((rate < GT_BURST_128K) && (rate != GT_BURST_NO_LIMIT))
+				return GT_BAD_PARAM;
+			burstSize = 1;
+			break;
+		case GT_BURST_SIZE_48K:
+			if ((rate < GT_BURST_256K) && (rate != GT_BURST_NO_LIMIT))
+				return GT_BAD_PARAM;
+			burstSize = 3;
+			break;
+		case GT_BURST_SIZE_96K:
+			if ((rate < GT_BURST_512K) && (rate != GT_BURST_NO_LIMIT))
+				return GT_BAD_PARAM;
+			burstSize = 7;
+			break;
+		default:
+			return GT_BAD_PARAM;
+	}
+
+	if((retVal = cBurstEnum2Number(dev, rate, &rateLimit)) != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+	}
+
+	rateLimit = GT_GET_BURST_RATE_LIMIT(burstSize,rateLimit);
+
+	rateLimit |= (GT_U32)(burstSize << 12);
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,15,(GT_U16)rateLimit );
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcGetBurstRate
+*
+* DESCRIPTION:
+*       This routine retrieves the port's ingress data limit based on burst size.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       bsize	- burst size.
+*       rate    - ingress data rate limit. These frames will be discarded after 
+*				the ingress rate selected is reached or exceeded. 
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetBurstRate
+(
+    IN  GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_BURST_SIZE   *bsize,
+    OUT GT_BURST_RATE   *rate
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+	GT_U32			rateLimit, burstSize;
+	GT_U16			data;
+
+    DBG_INFO(("grcGetBurstRate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_1))
+    	{
+        	DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+    	}
+	}
+		
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,15,&data);
+	rateLimit = (GT_U32)data;
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	burstSize = rateLimit >> 12;
+	rateLimit &= 0x0FFF;
+
+	retVal = cBurstRateLimit(dev, burstSize, rateLimit, rate);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	switch (burstSize)
+	{
+		case 0:
+			*bsize = GT_BURST_SIZE_12K;
+			break;
+		case 1:
+			*bsize = GT_BURST_SIZE_24K;
+			break;
+		case 3:
+			*bsize = GT_BURST_SIZE_48K;
+			break;
+		case 7:
+			*bsize = GT_BURST_SIZE_96K;
+			break;
+		default:
+			return GT_BAD_VALUE;
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetTCPBurstRate
+*
+* DESCRIPTION:
+*       This routine sets the port's TCP/IP ingress data limit based on burst size.
+*
+* INPUTS:
+*       port	- logical port number.
+*       rate    - ingress data rate limit for TCP/IP packets. These frames will 
+*				be discarded after the ingress rate selected is reached or exceeded. 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters 
+*								Valid rate is GT_BURST_NO_LIMIT, or between
+*								64Kbps and 1500Kbps.
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*		If the device supports both priority based Rate Limiting and burst size
+*		based Rate limiting, user has to manually change the mode to burst size
+*		based Rate limiting by calling gsysSetRateLimitMode.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcSetTCPBurstRate
+(
+    IN GT_QD_DEV       *dev,
+    IN GT_LPORT        port,
+    IN GT_BURST_RATE   rate
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+	GT_U32			rateLimit;
+
+    DBG_INFO(("grcSetTCPBurstRate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_1))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+	if((retVal = cTCPBurstRate(dev, rate, &rateLimit)) != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+	}
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,15,(GT_U16)rateLimit );
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetTCPBurstRate
+*
+* DESCRIPTION:
+*       This routine sets the port's TCP/IP ingress data limit based on burst size.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       rate    - ingress data rate limit for TCP/IP packets. These frames will 
+*				be discarded after the ingress rate selected is reached or exceeded. 
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_VALUE        - register value is not known
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*		If the device supports both priority based Rate Limiting and burst size
+*		based Rate limiting, user has to manually change the mode to burst size
+*		based Rate limiting by calling gsysSetRateLimitMode.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS grcGetTCPBurstRate
+(
+    IN  GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_BURST_RATE   *rate
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+	GT_U32			rateLimit;
+	GT_U32			data;
+	GT_U16			u16Data;
+	GT_BURST_RATE sLimit, startLimit, endLimit;
+
+    DBG_INFO(("grcGetTCPBurstRate Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_1))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,15,&u16Data);
+	data = (GT_U32)u16Data;
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	if ((data & 0xFFF) == 0)
+	{
+		*rate = GT_BURST_NO_LIMIT;
+		return GT_OK;
+	}
+
+	startLimit = GT_BURST_64K;
+	endLimit = GT_BURST_1500K;
+
+	for(sLimit=startLimit;sLimit<=endLimit;sLimit++)
+	{
+		if((retVal = cTCPBurstRate(dev, sLimit, &rateLimit)) != GT_OK)
+		{
+        	break;
+		}
+
+		if(rateLimit == data)
+		{
+			*rate = sLimit;
+			return GT_OK;
+		}
+	}
+
+    DBG_INFO(("Fail to find TCP Rate.\n"));
+    return GT_BAD_VALUE;
+}
+
+
+/*******************************************************************************
+* grcSetVidNrlEn
+*
+* DESCRIPTION:
+*       This routine enables/disables VID None Rate Limit (NRL).
+*		When VID NRL is enabled and the determined VID of a frame results in a VID
+*		whose VIDNonRateLimit in the VTU Table is set to GT_TURE, then the frame
+*		will not be ingress nor egress rate limited.
+*
+* INPUTS:
+*       port - logical port number.
+*		mode - GT_TRUE to enable VID None Rate Limit
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetVidNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetVidNrlEn Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the VidNrlEn mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,15,1,data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcGetVidNrlEn
+*
+* DESCRIPTION:
+*       This routine gets VID None Rate Limit (NRL) mode.
+*		When VID NRL is enabled and the determined VID of a frame results in a VID
+*		whose VIDNonRateLimit in the VTU Table is set to GT_TURE, then the frame
+*		will not be ingress nor egress rate limited.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable VID None Rate Limit
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetVidNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetVidNrlEn Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the VidNrlEn mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,15,1,&data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    BIT_2_BOOL(data, *mode);
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetSaNrlEn
+*
+* DESCRIPTION:
+*       This routine enables/disables SA None Rate Limit (NRL).
+*		When SA NRL is enabled and the source address of a frame results in a ATU
+*		hit where the SA's MAC address returns an EntryState that indicates Non
+*		Rate Limited, then the frame will not be ingress nor egress rate limited.
+*
+* INPUTS:
+*       port - logical port number.
+*		mode - GT_TRUE to enable SA None Rate Limit
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetSaNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetSaNrlEn Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the SaNrlEn mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,14,1,data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcGetSaNrlEn
+*
+* DESCRIPTION:
+*       This routine gets SA None Rate Limit (NRL) mode.
+*		When SA NRL is enabled and the source address of a frame results in a ATU
+*		hit where the SA's MAC address returns an EntryState that indicates Non
+*		Rate Limited, then the frame will not be ingress nor egress rate limited.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable SA None Rate Limit
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetSaNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetSaNrlEn Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the SaNrlEn mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,14,1,&data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    BIT_2_BOOL(data, *mode);
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcSetDaNrlEn
+*
+* DESCRIPTION:
+*       This routine enables/disables DA None Rate Limit (NRL).
+*		When DA NRL is enabled and the destination address of a frame results in 
+*		a ATU hit where the DA's MAC address returns an EntryState that indicates 
+*		Non Rate Limited, then the frame will not be ingress nor egress rate 
+*		limited.
+*
+* INPUTS:
+*       port - logical port number.
+*		mode - GT_TRUE to enable DA None Rate Limit
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetDaNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetDaNrlEn Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the DaNrlEn mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,13,1,data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcGetDaNrlEn
+*
+* DESCRIPTION:
+*       This routine gets SA None Rate Limit (NRL) mode.
+*		When DA NRL is enabled and the destination address of a frame results in 
+*		a ATU hit where the DA's MAC address returns an EntryState that indicates 
+*		Non Rate Limited, then the frame will not be ingress nor egress rate 
+*		limited.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE to enable DA None Rate Limit
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetDaNrlEn
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetDaNrlEn Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the DaNrlEn mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,13,1,&data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    BIT_2_BOOL(data, *mode);
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetELimitMode
+*
+* DESCRIPTION:
+*       This routine sets Egress Rate Limit counting mode.
+*		The supported modes are as follows:
+*			GT_PIRL_ELIMIT_FRAME -
+*				Count the number of frames
+*			GT_PIRL_ELIMIT_LAYER1 -
+*				Count all Layer 1 bytes: 
+*				Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
+*			GT_PIRL_ELIMIT_LAYER2 -
+*				Count all Layer 2 bytes: Frame's DA to CRC
+*			GT_PIRL_ELIMIT_LAYER1 -
+*				Count all Layer 1 bytes: 
+*				Frame's DA to CRC - 18 - 4 (if frame is tagged)
+*
+* INPUTS:
+*       port - logical port number
+*		mode - GT_PIRL_ELIMIT_MODE enum type
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetELimitMode
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	IN  GT_PIRL_ELIMIT_MODE		mode
+)
+{
+	GT_U16			data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetELimitMode Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE|DEV_ELIMIT_FRAME_BASED))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
+	{
+		if(mode == GT_PIRL_ELIMIT_FRAME)
+			return GT_NOT_SUPPORTED;
+	}
+
+	data = (GT_U16)mode & 0x3;
+
+    /* Set the Elimit mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_EGRESS_RATE_CTRL,14,2,data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcGetELimitMode
+*
+* DESCRIPTION:
+*       This routine gets Egress Rate Limit counting mode.
+*		The supported modes are as follows:
+*			GT_PIRL_ELIMIT_FRAME -
+*				Count the number of frames
+*			GT_PIRL_ELIMIT_LAYER1 -
+*				Count all Layer 1 bytes: 
+*				Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
+*			GT_PIRL_ELIMIT_LAYER2 -
+*				Count all Layer 2 bytes: Frame's DA to CRC
+*			GT_PIRL_ELIMIT_LAYER1 -
+*				Count all Layer 1 bytes: 
+*				Frame's DA to CRC - 18 - 4 (if frame is tagged)
+*
+* INPUTS:
+*       port - logical port number
+*
+* OUTPUTS:
+*		mode - GT_PIRL_ELIMIT_MODE enum type
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*		GT_NOT_SUPPORTED    - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcGetELimitMode
+(
+    IN  GT_QD_DEV	*dev,
+    IN  GT_LPORT	port,
+	OUT GT_PIRL_ELIMIT_MODE		*mode
+)
+{
+	GT_U16			data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetELimitMode Called.\n"));
+
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* check if the given Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE|DEV_ELIMIT_FRAME_BASED))
+	{
+   	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the Elimit mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_EGRESS_RATE_CTRL,14,2,&data);
+    if(retVal != GT_OK)
+   	{
+        DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	*mode = data;
+
+    DBG_INFO(("OK.\n"));
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcSetRsvdNrlEn
+*
+* DESCRIPTION:
+*       This routine sets Reserved Non Rate Limit.
+*		When this feature is enabled, frames that match the requirements of the 
+*		Rsvd2Cpu bit below will also be considered to be ingress and egress non 
+*		rate limited.
+*
+* INPUTS:
+*       en - GT_TRUE to enable Reserved Non Rate Limit,
+*			 GT_FALSE to disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS grcSetRsvdNrlEn
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("grcSetRsvdNrlEn Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the RsvdNrl bit.            */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,4,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* grcGetRsvdNrlEn
+*
+* DESCRIPTION:
+*       This routine gets Reserved Non Rate Limit.
+*		When this feature is enabled, frames that match the requirements of the 
+*		Rsvd2Cpu bit below will also be considered to be ingress and egress non 
+*		rate limited.
+*
+* INPUTS:
+*       en - GT_TRUE to enable Reserved Non Rate Limit,
+*			 GT_FALSE to disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS grcGetRsvdNrlEn
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("grcGetRsvdNrlEn Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the RsvdNrl bit.            */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,4,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data, *en);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* grcSetFrameOverhead
+*
+* DESCRIPTION:
+*       Egress rate frame overhead adjustment.
+*		This field is used to adjust the number of bytes that need to be added to a
+*		frame's IFG on a per frame basis.
+*
+*		The egress rate limiter multiplies the value programmed in this field by four
+*		for computing the frame byte offset adjustment value (i.e., the amount the
+*		IPG is increased for every frame). This adjustment, if enabled, is made to
+*		every egressing frame's IPG and it is made in addition to any other IPG
+*		adjustments due to other Egress Rate Control settings.
+*
+*		The egress overhead adjustment can add the following number of byte times
+*		to each frame's IPG: 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
+*		56 and 60.
+*
+*		Example:
+*		If FrameOverhead = 11, the egress rate limiter would increase the IPG
+*		between every frame by an additional 44 bytes.
+*
+*		Note: When the Count Mode (port offset 0x0A) is in Frame based egress rate
+*		shaping mode, these Frame Overhead bits must be 0x0.
+*
+* INPUTS:
+*       port	 - logical port number.
+*       overhead - Frame overhead (0 ~ 15)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_BAD_PARAM        - on bad parameters
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS grcSetFrameOverhead
+(
+    IN GT_QD_DEV		*dev,
+    IN GT_LPORT			port,
+    IN GT_32			overhead
+)
+{
+
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcSetFrameOverhead Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (overhead > 15)
+	{
+        DBG_INFO(("GT_BAD_PARAM \n"));
+		return GT_BAD_PARAM;
+	}
+
+    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL0,8,4,(GT_U16)overhead );
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* grcGetFrameOverhead
+*
+* DESCRIPTION:
+*       Egress rate frame overhead adjustment.
+*		This field is used to adjust the number of bytes that need to be added to a
+*		frame's IFG on a per frame basis.
+*
+*		The egress rate limiter multiplies the value programmed in this field by four
+*		for computing the frame byte offset adjustment value (i.e., the amount the
+*		IPG is increased for every frame). This adjustment, if enabled, is made to
+*		every egressing frame's IPG and it is made in addition to any other IPG
+*		adjustments due to other Egress Rate Control settings.
+*
+*		The egress overhead adjustment can add the following number of byte times
+*		to each frame's IPG: 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
+*		56 and 60.
+*
+*		Example:
+*		If FrameOverhead = 11, the egress rate limiter would increase the IPG
+*		between every frame by an additional 44 bytes.
+*
+*		Note: When the Count Mode (port offset 0x0A) is in Frame based egress rate
+*		shaping mode, these Frame Overhead bits must be 0x0.
+*
+* INPUTS:
+*       port	- logical port number.
+*
+* OUTPUTS:
+*       overhead - Frame overhead (0 ~ 15)
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+*******************************************************************************/
+GT_STATUS grcGetFrameOverhead
+(
+    IN GT_QD_DEV *dev,
+    IN  GT_LPORT port,
+    OUT GT_32    *overhead
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U8           phyPort;        /* Physical port.               */
+
+    DBG_INFO(("grcGetFrameOverhead Called.\n"));
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+	
+    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL0,8,4,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *overhead = (GT_U32)data;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortRmon.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortRmon.c
new file mode 100755
index 0000000..ddeacf6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortRmon.c
@@ -0,0 +1,1113 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtPortCounter.c
+*
+* DESCRIPTION:
+*       API definitions for RMON counters
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/****************************************************************************/
+/* STATS operation function declaration.                                    */
+/****************************************************************************/
+static GT_STATUS statsOperationPerform
+(
+    IN   GT_QD_DEV            *dev,
+    IN   GT_STATS_OPERATION   statsOp,
+    IN   GT_U8                port,
+    IN   GT_STATS_COUNTERS    counter,
+    OUT  GT_VOID              *statsData
+);
+
+static GT_STATUS statsCapture
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_U8      port
+);
+
+static GT_STATUS statsReadCounter
+(
+    IN   GT_QD_DEV		*dev,
+    IN   GT_U32			counter,
+    OUT  GT_U32			*statsData
+);
+
+static GT_STATUS statsReadRealtimeCounter
+(
+    IN   GT_QD_DEV      *dev,
+    IN   GT_U8 		    port,
+    IN   GT_U32			counter,
+    OUT  GT_U32		    *statsData
+);
+
+
+/*******************************************************************************
+* gstatsFlushAll
+*
+* DESCRIPTION:
+*       Flush All counters for all ports.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsFlushAll
+(
+        IN GT_QD_DEV  *dev
+)
+{
+	GT_STATUS       	retVal;
+
+	DBG_INFO(("gstatsFlushAll Called.\n"));
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,1, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = statsOperationPerform(dev,STATS_FLUSH_ALL,0,0,NULL);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gstatsFlushPort
+*
+* DESCRIPTION:
+*       Flush All counters for a given port.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsFlushPort
+(
+    IN GT_QD_DEV  *dev,
+    IN GT_LPORT	  port
+)
+{
+	GT_STATUS	retVal;
+    GT_U8		hwPort;         /* physical port number         */
+
+	DBG_INFO(("gstatsFlushPort Called.\n"));
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = statsOperationPerform(dev,STATS_FLUSH_PORT,hwPort,0,NULL);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gstatsGetPortCounter
+*
+* DESCRIPTION:
+*		This routine gets a specific counter of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*		counter - the counter which will be read
+*
+* OUTPUTS:
+*		statsData - points to 32bit data storage for the MIB counter
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*		None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortCounter
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	IN  GT_STATS_COUNTERS	counter,
+	OUT GT_U32			*statsData
+)
+{
+    GT_STATUS	retVal;
+    GT_U8		hwPort;         /* physical port number         */
+
+	DBG_INFO(("gstatsFlushPort Called.\n"));
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* Gigabit Switch does not support this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RMON_TYPE_1))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = statsOperationPerform(dev,STATS_READ_COUNTER,hwPort,counter,(GT_VOID*)statsData);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gstatsGetPortAllCounters
+*
+* DESCRIPTION:
+*       This routine gets all counters of the given port
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       statsCounterSet - points to GT_STATS_COUNTER_SET for the MIB counters
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*
+* COMMENTS:
+*       None
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortAllCounters
+(
+    IN  GT_QD_DEV               *dev,
+    IN  GT_LPORT		port,
+    OUT GT_STATS_COUNTER_SET	*statsCounterSet
+)
+{
+	GT_STATUS	retVal;
+    GT_U8		hwPort;         /* physical port number         */
+
+	DBG_INFO(("gstatsFlushPort Called.\n"));
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* Gigabit Switch does not support this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RMON_TYPE_1))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = statsOperationPerform(dev,STATS_READ_ALL,hwPort,0,(GT_VOID*)statsCounterSet);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gstatsGetPortCounter2
+*
+* DESCRIPTION:
+*		This routine gets a specific counter of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*		counter - the counter which will be read
+*
+* OUTPUTS:
+*		statsData - points to 32bit data storage for the MIB counter
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortCounter2
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	IN  GT_STATS_COUNTERS2	counter,
+	OUT GT_U32			*statsData
+)
+{
+    GT_STATUS	retVal;
+    GT_U8		hwPort;         /* physical port number         */
+
+	DBG_INFO(("gstatsGetPortCounters2 Called.\n"));
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RMON_TYPE_2))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = statsOperationPerform(dev,STATS_READ_COUNTER,hwPort,counter,(GT_VOID*)statsData);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gstatsGetPortAllCounters2
+*
+* DESCRIPTION:
+*		This routine gets all counters of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		statsCounterSet - points to GT_STATS_COUNTER_SET for the MIB counters
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortAllCounters2
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	OUT GT_STATS_COUNTER_SET2	*statsCounterSet
+)
+{
+	GT_STATUS	retVal;
+    GT_U8		hwPort;         /* physical port number         */
+
+	DBG_INFO(("gstatsGetPortAllCounters2 Called.\n"));
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RMON_TYPE_2))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = statsOperationPerform(dev,STATS_READ_ALL,hwPort,0,(GT_VOID*)statsCounterSet);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gstatsGetPortCounter3
+*
+* DESCRIPTION:
+*		This routine gets a specific counter of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*		counter - the counter which will be read
+*
+* OUTPUTS:
+*		statsData - points to 32bit data storage for the MIB counter
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*		This function supports Gigabit Switch and Spinnaker family
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortCounter3
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	IN  GT_STATS_COUNTERS3	counter,
+	OUT GT_U32			*statsData
+)
+{
+    GT_STATUS	retVal;
+    GT_U8		hwPort;         /* physical port number         */
+
+	DBG_INFO(("gstatsGetPortCounters3 Called.\n"));
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* Only 88E6093 Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RMON_TYPE_3))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = statsOperationPerform(dev,STATS_READ_COUNTER,hwPort,counter,(GT_VOID*)statsData);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* gstatsGetPortAllCounters3
+*
+* DESCRIPTION:
+*		This routine gets all counters of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		statsCounterSet - points to GT_STATS_COUNTER_SET for the MIB counters
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*		This function supports Gigabit Switch and Spinnaker family
+*
+*******************************************************************************/
+GT_STATUS gstatsGetPortAllCounters3
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	OUT GT_STATS_COUNTER_SET3	*statsCounterSet
+)
+{
+	GT_STATUS	retVal;
+    GT_U8		hwPort;         /* physical port number         */
+
+	DBG_INFO(("gstatsGetPortAllCounters3 Called.\n"));
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RMON_TYPE_3))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = statsOperationPerform(dev,STATS_READ_ALL,hwPort,0,(GT_VOID*)statsCounterSet);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gstatsGetHistogramMode
+*
+* DESCRIPTION:
+*		This routine gets the Histogram Counters Mode.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - Histogram Mode (GT_COUNT_RX_ONLY, GT_COUNT_TX_ONLY, 
+*					and GT_COUNT_RX_TX)
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_BAD_PARAM    - on bad parameter
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetHistogramMode
+(
+	IN  GT_QD_DEV				*dev,
+	OUT GT_HISTOGRAM_MODE	*mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gstatsGetHistogramMode Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH|DEV_RMON_REALTIME_SUPPORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* Get the Histogram mode bit.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,10,2,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	*mode = data - 1; /* Software definition starts from 0 ~ 2, 
+						while hardware supports the values from 1 to 3 */
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gstatsSetHistogramMode
+*
+* DESCRIPTION:
+*		This routine sets the Histogram Counters Mode.
+*
+* INPUTS:
+*		mode - Histogram Mode (GT_COUNT_RX_ONLY, GT_COUNT_TX_ONLY, 
+*					and GT_COUNT_RX_TX)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_BAD_PARAM    - on bad parameter
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstatsSetHistogramMode
+(
+	IN GT_QD_DEV 				*dev,
+	IN GT_HISTOGRAM_MODE		mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gstatsSetHistogramMode Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH|DEV_RMON_REALTIME_SUPPORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	switch (mode)
+	{
+		case GT_COUNT_RX_ONLY:
+		case GT_COUNT_TX_ONLY:
+		case GT_COUNT_RX_TX:
+			break;
+		default:
+	        DBG_INFO(("Failed.\n"));
+    	    return GT_BAD_PARAM;
+    }
+
+	data = (GT_U16)mode + 1;
+
+    /* Set the Histogram mode bit.                */
+    retVal = hwSetGlobalRegField(dev,QD_REG_STATS_OPERATION,10,2,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gstatsGetRealtimePortCounter
+*
+* DESCRIPTION:
+*		This routine gets a specific realtime counter of the given port
+*
+* INPUTS:
+*		port - the logical port number.
+*		counter - the counter which will be read
+*
+* OUTPUTS:
+*		statsData - points to 32bit data storage for the MIB counter
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gstatsGetRealtimePortCounter
+(
+	IN  GT_QD_DEV		*dev,
+	IN  GT_LPORT		port,
+	IN  GT_STATS_COUNTERS3	counter,
+	OUT GT_U32			*statsData
+)
+{
+    GT_STATUS	retVal;
+    GT_U8		hwPort;         /* physical port number         */
+
+	DBG_INFO(("gstatsGetRealtimePortCounter Called.\n"));
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_RMON)) != GT_OK)
+	{
+		return retVal;
+	}
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RMON_REALTIME_SUPPORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	retVal = statsOperationPerform(dev,STATS_READ_REALTIME_COUNTER,hwPort,counter,(GT_VOID*)statsData);
+	if(retVal != GT_OK)
+	{
+	    DBG_INFO(("Failed (statsOperationPerform returned GT_FAIL).\n"));
+    	return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+
+}
+
+
+/****************************************************************************/
+/* Internal use functions.                                                  */
+/****************************************************************************/
+
+/*******************************************************************************
+* statsOperationPerform
+*
+* DESCRIPTION:
+*       This function is used by all stats control functions, and is responsible
+*       to write the required operation into the stats registers.
+*
+* INPUTS:
+*       statsOp       - The stats operation bits to be written into the stats
+*                     operation register.
+*       port        - port number
+*       counter     - counter to be read if it's read operation
+*
+* OUTPUTS:
+*       statsData   - points to the data storage where the MIB counter will be saved.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+static GT_STATUS statsOperationPerform
+(
+    IN   GT_QD_DEV            *dev,
+    IN   GT_STATS_OPERATION   statsOp,
+    IN   GT_U8                port,
+    IN   GT_STATS_COUNTERS    counter,
+    OUT  GT_VOID              *statsData
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data,histoData; /* Data to be set into the      */
+                                    /* register.                    */
+	GT_U32 statsCounter;
+	GT_U32 lastCounter;
+	GT_U16			portNum;
+
+    gtSemTake(dev,dev->statsRegsSem,OS_WAIT_FOREVER);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_RMON_REALTIME_SUPPORT))
+    {
+		lastCounter = (GT_U32)STATS_OutDiscards;
+    }
+	else
+	{
+		lastCounter = (GT_U32)STATS2_Late;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_RMON_PORT_BITS))
+	{
+		portNum = (port + 1) << 5;
+	}
+	else
+	{
+		portNum = (GT_U16)port;
+	}
+
+    /* Wait until the stats in ready. */
+    data = 1;
+    while(data == 1)
+    {
+        retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data);
+        if(retVal != GT_OK)
+        {
+            gtSemGive(dev,dev->statsRegsSem);
+            return retVal;
+        }
+    }
+
+    /* Get the Histogram mode bit.                */
+	retVal = hwReadGlobalReg(dev,QD_REG_STATS_OPERATION,&histoData);
+    if(retVal != GT_OK)
+    {
+        gtSemGive(dev,dev->statsRegsSem);
+        return retVal;
+    }
+	
+	histoData &= 0xC00;
+
+    /* Set the STAT Operation register */
+	switch (statsOp)
+	{
+		case STATS_FLUSH_ALL:
+			data = (1 << 15) | (GT_STATS_FLUSH_ALL << 12) | histoData;
+			retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data);
+			gtSemGive(dev,dev->statsRegsSem);
+			return retVal;
+
+		case STATS_FLUSH_PORT:
+			data = (1 << 15) | (GT_STATS_FLUSH_PORT << 12) | portNum | histoData;
+			retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data);
+			gtSemGive(dev,dev->statsRegsSem);
+			return retVal;
+
+		case STATS_READ_COUNTER:
+			retVal = statsCapture(dev,port);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->statsRegsSem);
+				return retVal;
+			}
+
+			retVal = statsReadCounter(dev,counter,(GT_U32*)statsData);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->statsRegsSem);
+				return retVal;
+			}
+			break;
+
+		case STATS_READ_REALTIME_COUNTER:
+			retVal = statsReadRealtimeCounter(dev,port,counter,(GT_U32*)statsData);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->statsRegsSem);
+				return retVal;
+			}
+
+			break;
+
+		case STATS_READ_ALL:
+			retVal = statsCapture(dev,port);
+			if(retVal != GT_OK)
+			{
+				gtSemGive(dev,dev->statsRegsSem);
+				return retVal;
+			}
+
+			for(statsCounter=0; statsCounter<=lastCounter; statsCounter++)
+			{
+				retVal = statsReadCounter(dev,statsCounter,((GT_U32*)statsData + statsCounter));
+				if(retVal != GT_OK)
+				{
+					gtSemGive(dev,dev->statsRegsSem);
+					return retVal;
+				}
+			}
+			break;
+
+		default:
+			
+			gtSemGive(dev,dev->statsRegsSem);
+			return GT_FAIL;
+	}
+
+    gtSemGive(dev,dev->statsRegsSem);
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* statsCapture
+*
+* DESCRIPTION:
+*       This function is used to capture all counters of a port.
+*
+* INPUTS:
+*       port        - port number
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*		If Semaphore is used, Semaphore should be acquired before this function call.
+*******************************************************************************/
+static GT_STATUS statsCapture
+(
+    IN GT_QD_DEV            *dev,
+    IN GT_U8 		    port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data, histoData;/* Data to be set into the      */
+                                    /* register.                    */
+	GT_U16			portNum;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_RMON_PORT_BITS))
+	{
+		portNum = (port + 1) << 5;
+	}
+	else
+	{
+		portNum = (GT_U16)port;
+	}
+
+    /* Get the Histogram mode bit.                */
+	retVal = hwReadGlobalReg(dev,QD_REG_STATS_OPERATION,&histoData);
+    if(retVal != GT_OK)
+    {
+        return retVal;
+    }
+	
+	histoData &= 0xC00;
+
+    data = 1;
+   	while(data == 1)
+    {
+        retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data);
+        if(retVal != GT_OK)
+   	    {
+           	return retVal;
+        }
+   	}
+
+	data = (1 << 15) | (GT_STATS_CAPTURE_PORT << 12) | portNum | histoData;
+	retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* statsReadCounter
+*
+* DESCRIPTION:
+*       This function is used to read a captured counter.
+*
+* INPUTS:
+*       counter     - counter to be read if it's read operation
+*
+* OUTPUTS:
+*       statsData   - points to the data storage where the MIB counter will be saved.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*		If Semaphore is used, Semaphore should be acquired before this function call.
+*******************************************************************************/
+static GT_STATUS statsReadCounter
+(
+    IN   GT_QD_DEV      *dev,
+    IN   GT_U32			counter,
+    OUT  GT_U32		    *statsData
+)
+{
+    GT_STATUS   retVal;         /* Functions return value.            */
+    GT_U16      data, histoData;/* Data to be set into the  register. */ 
+    GT_U16	counter3_2;     /* Counter Register Bytes 3 & 2       */
+    GT_U16	counter1_0;     /* Counter Register Bytes 1 & 0       */
+
+    /* Get the Histogram mode bit.                */
+	retVal = hwReadGlobalReg(dev,QD_REG_STATS_OPERATION,&histoData);
+    if(retVal != GT_OK)
+    {
+        return retVal;
+    }
+	
+	histoData &= 0xC00;
+
+    data = 1;
+   	while(data == 1)
+    {
+        retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data);
+        if(retVal != GT_OK)
+   	    {
+           	return retVal;
+        }
+   	}
+
+	data = (GT_U16)((1 << 15) | (GT_STATS_READ_COUNTER << 12) | counter | histoData);
+	retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+    data = 1;
+   	while(data == 1)
+    {
+   	 retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data);
+        if(retVal != GT_OK)
+   	    {
+           	return retVal;
+        }
+   	}
+
+	retVal = hwReadGlobalReg(dev,QD_REG_STATS_COUNTER3_2,&counter3_2);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = hwReadGlobalReg(dev,QD_REG_STATS_COUNTER1_0,&counter1_0);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	*statsData = (counter3_2 << 16) | counter1_0;
+
+	return GT_OK;
+
+}
+
+
+/*******************************************************************************
+* statsReadRealtimeCounter
+*
+* DESCRIPTION:
+*       This function is used to read a realtime counter.
+*
+* INPUTS:
+*       port     - port to be accessed
+*       counter  - counter to be read if it's read operation
+*
+* OUTPUTS:
+*       statsData   - points to the data storage where the MIB counter will be saved.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*		If Semaphore is used, Semaphore should be acquired before this function call.
+*******************************************************************************/
+static GT_STATUS statsReadRealtimeCounter
+(
+    IN   GT_QD_DEV      *dev,
+    IN   GT_U8 		    port,
+    IN   GT_U32			counter,
+    OUT  GT_U32		    *statsData
+)
+{
+    GT_STATUS   retVal;         /* Functions return value.            */
+    GT_U16      data, histoData;/* Data to be set into the  register. */ 
+    GT_U16	counter3_2;     /* Counter Register Bytes 3 & 2       */
+    GT_U16	counter1_0;     /* Counter Register Bytes 1 & 0       */
+
+    /* Get the Histogram mode bit.                */
+	retVal = hwReadGlobalReg(dev,QD_REG_STATS_OPERATION,&histoData);
+    if(retVal != GT_OK)
+    {
+        return retVal;
+    }
+	
+	histoData &= 0xC00;
+
+    data = 1;
+   	while(data == 1)
+    {
+        retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data);
+        if(retVal != GT_OK)
+   	    {
+           	return retVal;
+        }
+   	}
+
+	data = (GT_U16)((1 << 15) | (GT_STATS_READ_COUNTER << 12) | ((port+1) << 5) | counter | histoData);
+	retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+    data = 1;
+   	while(data == 1)
+    {
+   	 retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data);
+        if(retVal != GT_OK)
+   	    {
+           	return retVal;
+        }
+   	}
+
+	retVal = hwReadGlobalReg(dev,QD_REG_STATS_COUNTER3_2,&counter3_2);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = hwReadGlobalReg(dev,QD_REG_STATS_COUNTER1_0,&counter1_0);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	*statsData = (counter3_2 << 16) | counter1_0;
+
+	return GT_OK;
+
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortStat.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortStat.c
new file mode 100755
index 0000000..57d9488
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortStat.c
@@ -0,0 +1,355 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPortStat.c
+*
+* DESCRIPTION:
+*       API implementation for switch port rx/tx counters.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+/*******************************************************************************
+* gprtSetCtrMode
+*
+* DESCRIPTION:
+*       This routine sets the port rx/tx counters mode of operation.
+*
+* INPUTS:
+*       mode  - the counter mode.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetCtrMode
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_CTR_MODE  mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gprtSetCtrMode Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,8,1,(GT_U16)mode);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("gprtSetCtrMode Failed .\n"));
+        return GT_FAIL;
+    }
+
+    DBG_INFO(("gprtSetCtrMode OK .\n"));
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtClearAllCtr
+*
+* DESCRIPTION:
+*       This routine clears all port rx/tx counters.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtClearAllCtr
+(
+    IN GT_QD_DEV    *dev
+)
+{
+    IN GT_STATUS     retVal;         /* Functions return value.      */
+    IN GT_U16        mode;           /* hold counters current mode   */
+
+    DBG_INFO(("gprtClearAllCtr Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* get counter current mode  */
+    if(hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,8,1,&mode) != GT_OK)
+    {
+        DBG_INFO(("Failed (Get field).\n"));
+        return GT_FAIL;
+    }
+    /* write opposite value to reset counter */
+    if(hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,8,1,(GT_U16)(1 - mode)) != GT_OK)
+    {
+        DBG_INFO(("Failed (Get field).\n"));
+        return GT_FAIL;
+    }
+    /* restore counters mode */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,8,1,mode);
+
+    DBG_INFO(("OK.\n"));
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetPortCtr
+*
+* DESCRIPTION:
+*       This routine gets the port rx/tx counters.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       ctr - the counters value.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortCtr
+(
+    IN  GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_PORT_STAT    *ctr
+)
+{
+    GT_U16          count;          /* counters current value       */
+    GT_U8           hwPort;         /* physical port number         */
+
+    DBG_INFO(("gprtGetPortCtr Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    if(ctr  == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* get rx counter value  */
+    if(hwReadPortReg(dev,hwPort, QD_REG_RX_COUNTER, &count) != GT_OK)
+    {
+        DBG_INFO(("Failed (Read Rx).\n"));
+        return GT_FAIL;
+    }
+    ctr->rxCtr = count;
+    /* get tx counter value  */
+    if(hwReadPortReg(dev,hwPort, QD_REG_TX_COUNTER, &count) != GT_OK)
+    {
+        DBG_INFO(("Failed (Read Tx).\n"));
+        return GT_FAIL;
+    }
+    ctr->txCtr = count;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH))
+	{
+	    /* get dropped counter value  */
+    	if(hwReadPortReg(dev,hwPort, QD_REG_DROPPED_COUNTER, &count) != GT_OK)
+	    {
+    	    DBG_INFO(("Failed (Read Tx).\n"));
+        	return GT_FAIL;
+	    }
+		ctr->dropped = count;
+	}
+	else
+		ctr->dropped = 0;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtGetPortCtr2
+*
+* DESCRIPTION:
+*       This routine gets the port InDiscards, InFiltered, and OutFiltered counters.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       ctr - the counters value.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortCtr2
+(
+    IN  GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_PORT_STAT2   *ctr
+)
+{
+    GT_U16          count;          /* counters current value       */
+    GT_U8           hwPort;         /* physical port number         */
+
+    DBG_INFO(("gprtGetPortCtr2 Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    if(ctr  == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* get InDiscard Low counter value  */
+    if(hwReadPortReg(dev,hwPort, QD_REG_INDISCARD_LO_COUNTER, &count) != GT_OK)
+    {
+        DBG_INFO(("Failed (Read inDiscardLo).\n"));
+        return GT_FAIL;
+    }
+    ctr->inDiscardLo = count;
+    /* get InDiscard High counter value  */
+    if(hwReadPortReg(dev,hwPort, QD_REG_INDISCARD_HI_COUNTER, &count) != GT_OK)
+    {
+        DBG_INFO(("Failed (Read inDiscardHi).\n"));
+        return GT_FAIL;
+    }
+    ctr->inDiscardHi = count;
+
+    /* get InFiltered counter value  */
+    if(hwReadPortReg(dev,hwPort, QD_REG_INFILTERED_COUNTER, &count) != GT_OK)
+    {
+        DBG_INFO(("Failed (Read inFiltered).\n"));
+        return GT_FAIL;
+    }
+    ctr->inFiltered = count;
+
+    /* get OutFiltered counter value  */
+    if(hwReadPortReg(dev,hwPort, QD_REG_OUTFILTERED_COUNTER, &count) != GT_OK)
+    {
+        DBG_INFO(("Failed (Read outFiltered).\n"));
+        return GT_FAIL;
+    }
+    ctr->outFiltered = count;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+#ifdef DEBUG_FEATURE /* this is a debug feature*/
+/*******************************************************************************
+* gprtGetPortQueueCtr
+*
+* DESCRIPTION:
+*       This routine gets the port queue counters.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       ctr - the counters value.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS: 
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortQueueCtr
+(
+    IN  GT_QD_DEV       *dev,
+    IN  GT_LPORT        port,
+    OUT GT_PORT_Q_STAT  *ctr
+)
+{
+    GT_U16          count;          /* counters current value       */
+    GT_U8           hwPort;         /* physical port number         */
+
+    DBG_INFO(("gprtGetPortQueueCtr Called.\n"));
+
+    if(ctr  == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* translate logical port to physical port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* get queue counter value  */
+    if(hwReadPortReg(dev,hwPort, QD_REG_Q_COUNTER, &count) != GT_OK)
+    {
+        DBG_INFO(("Failed (Read Rx).\n"));
+        return GT_FAIL;
+    }
+
+    /* the fist 5 bits(4:0) are OutQ_Size */
+    ctr->OutQ_Size = count & 0x1F;
+
+    /* the Rsv_Size are bits 15:8 */
+    ctr->Rsv_Size  = count >> 8;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+#endif 
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortStatus.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortStatus.c
new file mode 100755
index 0000000..7888fb2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPortStatus.c
@@ -0,0 +1,2238 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPortCtrl.c
+*
+* DESCRIPTION:
+*       API implementation for switch port status.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+#include <gtDrvConfig.h>
+
+typedef struct _GT_Px_MODE
+{
+	GT_BOOL miiEn;
+	GT_BOOL portMode;
+	GT_BOOL phyMode;
+	GT_PORT_SPEED_MODE speed;
+	GT_BOOL duplex;
+} GT_Px_MODE;
+
+/*******************************************************************************
+* procPx_Mode
+*
+* DESCRIPTION:
+*       This routine retrieves Px_MODE and analize it.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - Px_MODE structure
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+*******************************************************************************/
+GT_STATUS procPx_Mode
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_Px_MODE   *mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("procPx_Mode Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,7,5,&data);
+	if (retVal != GT_OK)
+		return retVal;
+
+	if(data & 0x1)
+	{
+		/* MII Interface Enabled. */
+		mode->miiEn = GT_TRUE;		/* Mii Interface Enabled */
+
+		switch(data >> 1)
+		{
+			case 0:
+			case 1:
+			case 4:
+			case 5:
+				mode->speed = PORT_SPEED_10_MBPS;
+				mode->duplex = GT_FALSE;	/* half duplex */
+				mode->portMode = GT_FALSE;	/* not standard Mii, either SNI or 200 Mii */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 2:
+			case 6:
+				mode->speed = PORT_SPEED_10_MBPS;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_FALSE;	/* not standard Mii, either SNI or 200 Mii */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 3:
+				mode->speed = PORT_SPEED_200_MBPS;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_FALSE;	/* not standard Mii, either SNI or 200 Mii */
+				mode->phyMode = GT_FALSE;	/* MAC Mode */
+				break;
+			case 7:
+				mode->speed = PORT_SPEED_200_MBPS;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_FALSE;	/* not standard Mii, either SNI or 200 Mii */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 8:
+				mode->speed = PORT_SPEED_UNKNOWN;
+				mode->duplex = GT_FALSE;	/* half duplex */
+				mode->portMode = GT_TRUE;	/* Mii Mode */
+				mode->phyMode = GT_FALSE;	/* MAC Mode */
+				break;
+			case 9:
+				mode->speed = PORT_SPEED_UNKNOWN;
+				mode->duplex = GT_FALSE;	/* half duplex */
+				mode->portMode = GT_TRUE;	/* RMii Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 10:
+				mode->speed = PORT_SPEED_UNKNOWN;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_TRUE;	/* Mii Mode */
+				mode->phyMode = GT_FALSE;	/* MAC Mode */
+				break;
+			case 11:
+				mode->speed = PORT_SPEED_UNKNOWN;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_TRUE;	/* RMii Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 12:
+				mode->speed = PORT_SPEED_10_MBPS;
+				mode->duplex = GT_FALSE;	/* half duplex */
+				mode->portMode = GT_TRUE;	/* Mii Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 13:
+				mode->speed = PORT_SPEED_100_MBPS;
+				mode->duplex = GT_FALSE;	/* half duplex */
+				mode->portMode = GT_TRUE;	/* Mii Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 14:
+				mode->speed = PORT_SPEED_10_MBPS;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_TRUE;	/* Mii Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 15:
+				mode->speed = PORT_SPEED_100_MBPS;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_TRUE;	/* Mii Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			default:
+				return GT_FAIL;
+		}
+	}
+	else
+	{
+		/* MII Interface Disabled. */
+		mode->miiEn = GT_FALSE;
+
+		switch((data >> 1) & 0x3)
+		{
+			case 0:
+				mode->speed = PORT_SPEED_10_MBPS;
+				mode->duplex = GT_FALSE;	/* half duplex */
+				mode->portMode = GT_TRUE;	/* MII Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 1:
+				mode->speed = PORT_SPEED_100_MBPS;
+				mode->duplex = GT_FALSE;	/* half duplex */
+				mode->portMode = GT_TRUE;	/* MII Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 2:
+				mode->speed = PORT_SPEED_10_MBPS;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_TRUE;	/* MII Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			case 3:
+				mode->speed = PORT_SPEED_100_MBPS;
+				mode->duplex = GT_TRUE;		/* full duplex */
+				mode->portMode = GT_TRUE;	/* MII Mode */
+				mode->phyMode = GT_TRUE;	/* PHY Mode */
+				break;
+			default:
+				return GT_FAIL;
+		}
+	}
+
+    /* return */
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gprtGetPartnerLinkPause
+*
+* DESCRIPTION:
+*       This routine retrives the link partner pause state.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       state - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*		
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPartnerLinkPause
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPartnerLinkPause Called.\n"));
+
+	/* Gigabit Switch does not support this status. gprtGetPauseEn is supported instead. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,15,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPauseEn
+*
+* DESCRIPTION:
+*		This routine retrives the link pause state.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE for enable or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		If set MAC Pause (for Full Duplex flow control) is implemented in the
+*		link partner and in MyPause
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPauseEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL 	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPauseEn Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,15,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetSelfLinkPause
+*
+* DESCRIPTION:
+*       This routine retrives the link pause state.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       state - GT_TRUE for enable  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSelfLinkPause
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetSelfLinkPause Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,14,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetResolve
+*
+* DESCRIPTION:
+*       This routine retrives the resolve state.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       state - GT_TRUE for Done  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetResolve
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetResolve Called.\n"));
+
+	/* Gigabit Switch does not support this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,13,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetHdFlow
+*
+* DESCRIPTION:
+*		This routine retrives the half duplex flow control value.
+*		If set, Half Duplex back pressure will be used on this port if this port
+*		is in a half duplex mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE for enable or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHdFlow
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL 	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetHdFlow Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,13,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPHYDetect
+*
+* DESCRIPTION:
+*		This routine retrives the information regarding PHY detection.
+*		If set, An 802.3 PHY is attached to this port.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if connected or GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPHYDetect
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL 	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPHYDetect Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,12,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtSetPHYDetect
+*
+* DESCRIPTION:
+*		This routine sets PHYDetect bit which make PPU change its polling.
+*		PPU's pool routine uses these bits to determine which port's to poll
+*		PHYs on for Link, Duplex, Speed, and Flow Control.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE or GT_FALSE
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		This function should not be called if gsysGetPPUState returns 
+*		PPU_STATE_ACTIVE.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetPHYDetect
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_BOOL  	state
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetPHYDetect Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Set the PHY Detect bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,12,1,(GT_U16)state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetLinkState
+*
+* DESCRIPTION:
+*       This routine retrives the link state.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       state - GT_TRUE for Up  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetLinkState
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_U8			bitNumber;
+
+    DBG_INFO(("gprtGetLinkState Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		bitNumber = 11;
+	}
+	else
+	{
+		bitNumber = 12;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,bitNumber,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetPortMode
+*
+* DESCRIPTION:
+*       This routine retrives the port mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for MII 10/100 or RMII 100,
+*			   GT_FALSE for SNI 10 or MII 200
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPortMode
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_Px_MODE		pxMode;
+
+    DBG_INFO(("gprtGetPortMode Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_Px_MODE))
+	{
+		retVal = procPx_Mode(dev,port,&pxMode);
+		if (retVal != GT_OK)
+		{
+	        DBG_INFO(("procPx_Mode return Fail\n"));
+			return retVal;
+		}
+		*mode = pxMode.portMode;
+		return GT_OK;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,11,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetPhyMode
+*
+* DESCRIPTION:
+*       This routine retrives the PHY mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for MII PHY Mode, 
+*			   GT_FALSE for MII MAC Mode
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPhyMode
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *mode
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_Px_MODE		pxMode;
+
+    DBG_INFO(("gprtGetPhyMode Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_Px_MODE))
+	{
+		retVal = procPx_Mode(dev,port,&pxMode);
+		if (retVal != GT_OK)
+		{
+	        DBG_INFO(("procPx_Mode return Fail\n"));
+			return retVal;
+		}
+		*mode = pxMode.phyMode;
+		return GT_OK;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,10,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetDuplex
+*
+* DESCRIPTION:
+*       This routine retrives the port duplex mode.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for Full  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetDuplex
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *mode
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_U8			bitNumber;
+	GT_Px_MODE		pxMode;
+
+    DBG_INFO(("gprtGetDuplex Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_Px_MODE))
+	{
+		retVal = procPx_Mode(dev,port,&pxMode);
+		if (retVal != GT_OK)
+		{
+	        DBG_INFO(("procPx_Mode return Fail\n"));
+			return retVal;
+		}
+		*mode = pxMode.duplex;
+		return GT_OK;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		bitNumber = 10;
+	}
+	else
+	{
+		bitNumber = 9;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,bitNumber,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetSpeed
+*
+* DESCRIPTION:
+*       This routine retrives the port speed.
+*
+* INPUTS:
+*       speed - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for 100Mb/s  or GT_FALSE otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSpeed
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *speed
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_Px_MODE		pxMode;
+
+    DBG_INFO(("gprtGetSpeed Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_Px_MODE))
+	{
+		retVal = procPx_Mode(dev,port,&pxMode);
+		if (retVal != GT_OK)
+		{
+	        DBG_INFO(("procPx_Mode return Fail\n"));
+			return retVal;
+		}
+		*speed = (pxMode.speed==PORT_SPEED_100_MBPS)?GT_TRUE:GT_FALSE;
+		return GT_OK;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+    /* Get the force flow control bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,8,1,&data);
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *speed);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetSpeedMode
+*
+* DESCRIPTION:
+*       This routine retrives the port speed.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_PORT_SPEED_MODE type.
+*				(PORT_SPEED_1000_MBPS,PORT_SPEED_100_MBPS, PORT_SPEED_10_MBPS, 
+*				etc.)
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetSpeedMode
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_PORT_SPEED_MODE   *speed
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_Px_MODE		pxMode;
+
+    DBG_INFO(("gprtGetSpeed Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_Px_MODE))
+	{
+		retVal = procPx_Mode(dev,port,&pxMode);
+		if (retVal != GT_OK)
+		{
+	        DBG_INFO(("procPx_Mode return Fail\n"));
+			return retVal;
+		}
+		*speed = pxMode.speed;
+		return GT_OK;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+	    /* Get the force flow control bit.  */
+    	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,8,2,&data);
+	}
+	else
+	{
+    	retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,8,1,&data);
+	}
+
+	*speed = (GT_PORT_SPEED_MODE)data;
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtSetDuplex
+*
+* DESCRIPTION:
+*       This routine sets the duplex mode of MII/SNI/RMII ports.
+*
+* INPUTS:
+*       port - 	the logical port number.
+*				(for FullSail, it will be port 2, and for ClipperShip, 
+*				it could be either port 5 or port 6.)
+*       mode -  GT_TRUE for Full Duplex,
+*				GT_FALSE for Half Duplex.
+*
+* OUTPUTS: None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetDuplex
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    IN  GT_BOOL   mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetDuplex Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_MII_DUPLEX_CONFIG)) != GT_OK)
+	{
+		return retVal;
+	}
+
+	/* check if phy is not configurable. */
+	if(IS_CONFIGURABLE_PHY(dev, hwPort))
+	{
+		/* 
+		 * phy is configurable. this function is not for the port where phy 
+		 * can be configured.
+		 */
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Set the duplex mode. */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,9,1,(GT_U16)mode);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetHighErrorRate
+*
+* DESCRIPTION:
+*		This routine retrives the PCS High Error Rate.
+*		This routine returns GT_TRUE if the rate of invalid code groups seen by
+*		PCS has exceeded 10 to the power of -11.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE or GT_FALSE
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHighErrorRate
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetHighErrorRate Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_MGMII_STATUS) || IS_IN_DEV_GROUP(dev,DEV_200BASE_CFG))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the high error rate bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,6,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetMGMII
+*
+* DESCRIPTION:
+*		SERDES Interface mode. When this bit is cleared to a zero and a PHY is 
+*		detected connected to this port, the SERDES interface between this port
+*		and the PHY will be SGMII.  When this bit is set to a one and a PHY is
+*		detected connected to this port, the SERDES interface between this port 
+*		and the PHY will be MGMII. When no PHY is detected on this port and the 
+*		SERDES interface is being used, it will be configured in 1000Base-X mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE or GT_FALSE
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMGMII
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetMGMII Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_MGMII_STATUS))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the high error rate bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,6,1,&data);
+
+    /* translate binary to BOOL  */
+	if (IS_IN_DEV_GROUP(dev,DEV_MGMII_REVERSE_STATUS))
+	{
+    	BIT_2_BOOL_R(data, *state);
+	}
+	else
+	{
+    	BIT_2_BOOL(data, *state);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtSetMGMII
+*
+* DESCRIPTION:
+*		SERDES Interface mode. When this bit is cleared to a zero and a PHY is 
+*		detected connected to this port, the SERDES interface between this port
+*		and the PHY will be SGMII.  When this bit is set toa one and a PHY is
+*		detected connected to this port, the SERDES interface between this port 
+*		and the PHY will be MGMII. When no PHY is detected on this port and the 
+*		SERDES interface is being used, it will be configured in 1000Base-X mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*		state - GT_TRUE or GT_FALSE
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtSetMGMII
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_BOOL  	state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtSetMGMII Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_MGMII_STATUS))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_MGMII_REVERSE_STATUS))
+	{
+	    BOOL_2_BIT_R(state,data);
+	}
+	else
+	{
+	    BOOL_2_BIT(state,data);
+	}
+
+    /* Get the high error rate bit.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,6,1,data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gprtGetTxPaused
+*
+* DESCRIPTION:
+*		This routine retrives Transmit Pause state.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Rx MAC receives a PAUSE frame with none-zero Puase Time
+*				  GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetTxPaused
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetTxPaused Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FC_STATUS))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the TxPaused bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,5,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetFlowCtrl
+*
+* DESCRIPTION:
+*		This routine retrives Flow control state.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Rx MAC determines that no more data should be 
+*					entering this port.
+*				  GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetFlowCtrl
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetFlowCtrl Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FC_STATUS))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the FlowCtrl bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,4,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetFdFlowDis
+*
+* DESCRIPTION:
+*		This routine retrives the read time value of the Full Duplex Flow Disable.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Full Duplex Flow Disable.
+*	   		    GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetFdFlowDis
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetFdFlowDis Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FC_DIS_STATUS))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the FdFlowDis bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,3,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetHdFlowDis
+*
+* DESCRIPTION:
+*		This routine retrives the read time value of the Half Duplex Flow Disable.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Half Duplex Flow Disable.
+*	   		    GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetHdFlowDis
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetHdFlowDis Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FC_DIS_STATUS))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the HdFlowDis bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,2,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetPxMode
+*
+* DESCRIPTION:
+*		This routine retrives 4 bits of Px_MODE Configuration value.
+*		If speed and duplex modes are forced, the returned mode value would be
+*		different from the configuration pin values.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - Px_MODE configuration value
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetPxMode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_U32  	*mode
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetPxMode Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_Px_MODE))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the Px_Mode bits.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,8,4,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	*mode = (GT_U32) data;
+
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetMiiInterface
+*
+* DESCRIPTION:
+*		This routine retrives Mii Interface Mode.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if Mii Interface is enabled,
+*				  GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gprtGetMiiInterface
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetMiiInterface Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_Px_MODE))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the Mii bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,7,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetOutQSize
+*
+* DESCRIPTION:
+*		This routine gets egress queue size counter value.
+*		This counter reflects the current number of Egress buffers switched to 
+*		this port. This is the total number of buffers across all four priority 
+*		queues.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		count - egress queue size counter value
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetOutQSize
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*count
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetOutQSize Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_OUT_Q_SIZE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get OutQ_Size.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_Q_COUNTER_TABLE))
+	{
+		if((retVal = hwWritePortReg(dev,hwPort, QD_REG_Q_COUNTER, 0x8000)) != GT_OK)
+			return retVal;
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,0,9,count);
+	}
+	else if (IS_IN_DEV_GROUP(dev,DEV_OUT_Q_512))
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,7,9,count);
+	}
+	else
+	{
+	    retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,8,8,count);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetBufHigh
+*
+* DESCRIPTION:
+*		Output from QC telling the MAC that it should perform Flow Control.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		bufHigh - GT_TRUE, if Flow control required
+*				  GT_FALSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetBufHigh
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*bufHigh
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			data;
+
+	DBG_INFO(("gprtGetBufHigh Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FULL_Q_COUNTER))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get BufHigh.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_Q_COUNTER_TABLE))
+	{
+		if((retVal = hwWritePortReg(dev,hwPort, QD_REG_Q_COUNTER, 0x9000)) != GT_OK)
+			return retVal;
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,1,1,&data);
+	}
+	else
+	{
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,6,1,&data);
+	}
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	/* translate binary to BOOL  */
+	BIT_2_BOOL(data, *bufHigh);
+
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtGetFcEn
+*
+* DESCRIPTION:
+*		Input into the QC telling it that Flow Control is enabled on this port.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		fcEn - GT_TRUE, if Flow control is enabled
+*			   GT_FALSE, otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetFcEn
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*fcEn
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			data;
+
+	DBG_INFO(("gprtGetFcEn Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FULL_Q_COUNTER))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get FcEn.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_Q_COUNTER_TABLE))
+	{
+		if((retVal = hwWritePortReg(dev,hwPort, QD_REG_Q_COUNTER, 0xa000)) != GT_OK)
+			return retVal;
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,0,1,&data);
+	}
+	else
+	{
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,5,1,&data);
+	}
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+
+	/* translate binary to BOOL  */
+	BIT_2_BOOL(data, *fcEn);
+	
+	return retVal;
+}
+
+/*******************************************************************************
+* gprtGetRsvSize
+*
+* DESCRIPTION:
+*		This routine gets Ingress reserved queue size counter.
+*		This counter reflects the current number of reserved ingress buffers 
+*		assigned to this port.
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		count - reserved ingress queue size counter value
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetRsvSize
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*count
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtGetRsvSize Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_OUT_Q_SIZE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get Rsv_Size.            */
+	if (IS_IN_DEV_GROUP(dev,DEV_Q_COUNTER_TABLE))
+	{
+		if((retVal = hwWritePortReg(dev,hwPort, QD_REG_Q_COUNTER, 0x9000)) != GT_OK)
+			return retVal;
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,0,9,count);
+	}
+	else
+	{
+		retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,0,5,count);
+	}
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+	}
+	else
+	{
+		DBG_INFO(("OK.\n"));
+	}
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetQSizePerQPri
+*
+* DESCRIPTION:
+*		This routine gets egress queue size for port's each QPri (0 ~ 3).
+*
+* INPUTS:
+*		port - the logical port number
+*
+* OUTPUTS:
+*		counts - egress queue size per QPri (should be 4 * 16bytes)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+*******************************************************************************/
+GT_STATUS gprtGetQSizePerQPri
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_U16		*counts
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8           hwPort;         /* the physical port number     */
+
+	DBG_INFO(("gprtGetQSizePerQPri Called.\n"));
+
+	/* translate LPORT to hardware port */
+	hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_Q_COUNTER_TABLE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if((retVal = hwWritePortReg(dev,hwPort, QD_REG_Q_COUNTER, 0x800)) != GT_OK)
+		return retVal;
+
+	if((retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,0,9,&counts[0])) != GT_OK)
+		return retVal;
+
+	if((retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,0,9,&counts[1])) != GT_OK)
+		return retVal;
+
+	if((retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,0,9,&counts[2])) != GT_OK)
+		return retVal;
+
+	if((retVal = hwGetPortRegField(dev,hwPort, QD_REG_Q_COUNTER,0,9,&counts[3])) != GT_OK)
+		return retVal;
+
+	DBG_INFO(("OK.\n"));
+
+	return retVal;
+}
+
+
+/*******************************************************************************
+* gprtGetC_Duplex
+*
+* DESCRIPTION:
+*		This routine retrives Port 9's duplex configuration mode determined
+*		at reset.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - GT_TRUE if configured as Full duplex operation
+*				  GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Return value is valid only if the given port is 9.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetC_Duplex
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_BOOL  	*state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetC_Duplex Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the C_Duplex bit.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,3,1,&data);
+
+    /* translate binary to BOOL  */
+    BIT_2_BOOL(data, *state);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+/*******************************************************************************
+* gprtGetC_Mode
+*
+* DESCRIPTION:
+*		This routine retrives port's interface type configuration mode 
+*		determined at reset.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		state - one of value in GT_PORT_CONFIG_MODE enum type
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Return value is valid only if the given port is 9.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gprtGetC_Mode
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	OUT GT_PORT_CONFIG_MODE   *state
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gprtGetC_Mode Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* Get the C_Mode bits.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_STATUS,0,3,&data);
+
+    /* translate binary to BOOL  */
+    *state = (GT_PORT_CONFIG_MODE)data;
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    /* return */
+    return retVal;
+}
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPriTable.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPriTable.c
new file mode 100755
index 0000000..171e85f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtPriTable.c
@@ -0,0 +1,1017 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtPriTable.c
+*
+* DESCRIPTION:
+*       API definitions for Priority Override Table
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+/*******************************************************************************
+* gsysSetQPriOverrideTable
+*
+* DESCRIPTION:
+*       Queue Priority Override.
+*		When a frame enters a port, its type is determined and the type is used 
+*		to access the Queue Priority Table. If the type's qPriEn (in GT_QPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Queue Priority will be overridden
+*		with the value written in qPriority (in GT_QPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*       entry - Q Priority Override Table entry (GT_QPRI_TBL_ENTRY)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetQPriOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	IN  GT_QPRI_TBL_ENTRY	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data,qPri;
+
+	DBG_INFO(("gsysSetQPriOverrideTable Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_OVERRIDE_TABLE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (fType)
+	{
+		case FTYPE_DSA_TO_CPU_BPDU:
+		case FTYPE_DSA_TO_CPU_F2R:
+		case FTYPE_DSA_TO_CPU_IGMP:
+		case FTYPE_DSA_TO_CPU_TRAP:
+		case FTYPE_DSA_TO_CPU_ARP:
+		case FTYPE_DSA_TO_CPU_MIRROR:
+		case FTYPE_DSA_TO_CPU_RESERVED:
+		case FTYPE_DSA_TO_CPU_UCAST_MGMT:
+		case FTYPE_DSA_FROM_CPU:
+		case FTYPE_DSA_CROSS_CHIP_FC:
+		case FTYPE_DSA_CROSS_CHIP_EGRESS_MON:
+		case FTYPE_DSA_CROSS_CHIP_INGRESS_MON:
+		case FTYPE_PORT_ETYPE_MATCH:
+		case FTYPE_BCAST_NON_DSA_CONTROL:
+		case FTYPE_PPPoE_NON_DSA_CONTROL:
+		case FTYPE_IP_NON_DSA_CONTROL:
+			break;
+		default:
+	        DBG_INFO(("GT_BAD_PARAM\n"));
+			return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the Priority Override Table is ready. */
+	data = 1;
+	while(data == 1)
+	{
+		retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_QAVB_PRIORITY_OVERRIDE_TABLE))
+	{
+		data = fType << 8;
+
+		retVal = hwWriteGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, data);
+		if(retVal != GT_OK)
+		{
+			DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+	
+		retVal = hwReadGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, &data);
+		if(retVal != GT_OK)
+		{		
+			DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+
+		data &= ((1 << 7) | (3 << 4));	/* keep QPriAvb information */
+	}
+	else
+		data = 0;
+
+	if (entry->qPriEn)
+		qPri = (GT_U16)((1 << 3) | (entry->qPriority & 0x3));
+	else
+		qPri = 0;
+
+	data |= (GT_U16)((1 << 15) | (fType << 8) | qPri);
+
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+	
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetQPriOverrideTable
+*
+* DESCRIPTION:
+*       Queue Priority Override.
+*		When a frame enters a port, its type is determined and the type is used 
+*		to access the Queue Priority Table. If the type's qPriEn (in GT_QPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Queue Priority will be overridden
+*		with the value written in qPriority (in GT_QPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*
+* OUTPUTS:
+*       entry - Q Priority Override Table entry (GT_QPRI_TBL_ENTRY)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetQPriOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	OUT GT_QPRI_TBL_ENTRY	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+	DBG_INFO(("gsysGetQPriOverrideTable Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_OVERRIDE_TABLE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (fType)
+	{
+		case FTYPE_DSA_TO_CPU_BPDU:
+		case FTYPE_DSA_TO_CPU_F2R:
+		case FTYPE_DSA_TO_CPU_IGMP:
+		case FTYPE_DSA_TO_CPU_TRAP:
+		case FTYPE_DSA_TO_CPU_ARP:
+		case FTYPE_DSA_TO_CPU_MIRROR:
+		case FTYPE_DSA_TO_CPU_RESERVED:
+		case FTYPE_DSA_TO_CPU_UCAST_MGMT:
+		case FTYPE_DSA_FROM_CPU:
+		case FTYPE_DSA_CROSS_CHIP_FC:
+		case FTYPE_DSA_CROSS_CHIP_EGRESS_MON:
+		case FTYPE_DSA_CROSS_CHIP_INGRESS_MON:
+		case FTYPE_PORT_ETYPE_MATCH:
+		case FTYPE_BCAST_NON_DSA_CONTROL:
+		case FTYPE_PPPoE_NON_DSA_CONTROL:
+		case FTYPE_IP_NON_DSA_CONTROL:
+			break;
+		default:
+	        DBG_INFO(("GT_BAD_PARAM\n"));
+			return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the Priority Override Table is ready. */
+	data = 1;
+	while(data == 1)
+	{
+		retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+	}
+
+	data = fType << 8;
+
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+	
+	retVal = hwReadGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, &data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	if (data & (1 << 3))
+	{
+		entry->qPriEn = GT_TRUE;
+		entry->qPriority = data & 0x3;
+	}
+	else
+	{
+		entry->qPriEn = GT_FALSE;
+		entry->qPriority = data & 0x3; /* no meaning, but just in case */
+	}
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysSetFPriOverrideTable
+*
+* DESCRIPTION:
+* 		Frame Priority Override.
+*		When a frame enters a port, its type is determined and the type is used 
+*		to access the Frame Priority Table. If the type's fPriEn (in GT_FPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Frame Priority will be overridden
+*		with the value written in fPriority (in GT_FPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*       entry - Frame Priority Override Table entry (GT_FPRI_TBL_ENTRY)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetFPriOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	IN  GT_FPRI_TBL_ENTRY	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data,fPri;
+
+	DBG_INFO(("gsysSetFPriOverrideTable Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_PRIORITY_OVERRIDE_TABLE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}		
+
+	switch (fType)
+	{
+		case FTYPE_DSA_TO_CPU_BPDU:
+		case FTYPE_DSA_TO_CPU_F2R:
+		case FTYPE_DSA_TO_CPU_IGMP:
+		case FTYPE_DSA_TO_CPU_TRAP:
+		case FTYPE_DSA_TO_CPU_ARP:
+		case FTYPE_DSA_TO_CPU_MIRROR:
+		case FTYPE_DSA_TO_CPU_RESERVED:
+		case FTYPE_DSA_TO_CPU_UCAST_MGMT:
+		case FTYPE_DSA_FROM_CPU:
+		case FTYPE_DSA_CROSS_CHIP_FC:
+		case FTYPE_DSA_CROSS_CHIP_EGRESS_MON:
+		case FTYPE_DSA_CROSS_CHIP_INGRESS_MON:
+		case FTYPE_PORT_ETYPE_MATCH:
+		case FTYPE_BCAST_NON_DSA_CONTROL:
+		case FTYPE_PPPoE_NON_DSA_CONTROL:
+		case FTYPE_IP_NON_DSA_CONTROL:
+			break;
+		default:
+	        DBG_INFO(("GT_BAD_PARAM\n"));
+			return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the Priority Override Table is ready. */
+	data = 1;
+	while(data == 1)
+	{
+		retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+	}
+
+	if (entry->fPriEn)
+		fPri = (GT_U16)((1 << 3) | (entry->fPriority & 0x7));
+	else
+		fPri = 0;
+
+	data = (GT_U16)((1 << 15) | (fType << 8) | fPri | 0x1000);
+
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+	
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetQPriOverrideTable
+*
+* DESCRIPTION:
+* 		Frame Priority Override.
+*		When a frame enters a port, its type is determined and the type is used 
+*		to access the Frame Priority Table. If the type's fPriEn (in GT_FPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Frame Priority will be overridden
+*		with the value written in fPriority (in GT_FPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*
+* OUTPUTS:
+*       entry - Frame Priority Override Table entry (GT_FPRI_TBL_ENTRY)
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*       GT_BAD_PARAM     - on unknown frame type
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetFPriOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	OUT GT_FPRI_TBL_ENTRY	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+	DBG_INFO(("gsysGetFPriOverrideTable Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_PRIORITY_OVERRIDE_TABLE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (fType)
+	{
+		case FTYPE_DSA_TO_CPU_BPDU:
+		case FTYPE_DSA_TO_CPU_F2R:
+		case FTYPE_DSA_TO_CPU_IGMP:
+		case FTYPE_DSA_TO_CPU_TRAP:
+		case FTYPE_DSA_TO_CPU_ARP:
+		case FTYPE_DSA_TO_CPU_MIRROR:
+		case FTYPE_DSA_TO_CPU_RESERVED:
+		case FTYPE_DSA_TO_CPU_UCAST_MGMT:
+		case FTYPE_DSA_FROM_CPU:
+		case FTYPE_DSA_CROSS_CHIP_FC:
+		case FTYPE_DSA_CROSS_CHIP_EGRESS_MON:
+		case FTYPE_DSA_CROSS_CHIP_INGRESS_MON:
+		case FTYPE_PORT_ETYPE_MATCH:
+		case FTYPE_BCAST_NON_DSA_CONTROL:
+		case FTYPE_PPPoE_NON_DSA_CONTROL:
+		case FTYPE_IP_NON_DSA_CONTROL:
+			break;
+		default:
+	        DBG_INFO(("GT_BAD_PARAM\n"));
+			return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the Priority Override Table is ready. */
+	data = 1;
+	while(data == 1)
+	{
+		retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+	}
+
+	data = (fType << 8) | 0x1000;
+
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+	
+	retVal = hwReadGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, &data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	if (data & (1 << 3))
+	{
+		entry->fPriEn = GT_TRUE;
+		entry->fPriority = data & 0x7;
+	}
+	else
+	{
+		entry->fPriEn = GT_FALSE;
+		entry->fPriority = data & 0x7; /* no meaning, but just in case */
+	}
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetQPriAvbOverrideTable
+*
+* DESCRIPTION:
+* 		Queue Priority Override for AVB enabled ports or AvbOverride enabled ports.
+*		When a frame enters a AVB port, its type is determined and the type is used 
+*		to access the Queue Priority Table. If the type's qPriEn (in GT_QPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Queue Priority will be overridden
+*		with the value written in qPriority (in GT_QPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*       entry - Q Priority Override Table entry (GT_QPRI_TBL_ENTRY)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetQPriAvbOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	IN  GT_QPRI_TBL_ENTRY	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data,qPri;
+
+	DBG_INFO(("gsysSetQPriAvbOverrideTable Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAVB_PRIORITY_OVERRIDE_TABLE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (fType)
+	{
+		case FTYPE_DSA_TO_CPU_BPDU:
+		case FTYPE_DSA_TO_CPU_F2R:
+		case FTYPE_DSA_TO_CPU_IGMP:
+		case FTYPE_DSA_TO_CPU_TRAP:
+		case FTYPE_DSA_TO_CPU_ARP:
+		case FTYPE_DSA_TO_CPU_MIRROR:
+		case FTYPE_DSA_TO_CPU_RESERVED:
+		case FTYPE_DSA_TO_CPU_UCAST_MGMT:
+		case FTYPE_DSA_FROM_CPU:
+		case FTYPE_DSA_CROSS_CHIP_FC:
+		case FTYPE_DSA_CROSS_CHIP_EGRESS_MON:
+		case FTYPE_DSA_CROSS_CHIP_INGRESS_MON:
+		case FTYPE_PORT_ETYPE_MATCH:
+		case FTYPE_BCAST_NON_DSA_CONTROL:
+		case FTYPE_PPPoE_NON_DSA_CONTROL:
+		case FTYPE_IP_NON_DSA_CONTROL:
+			break;
+		default:
+	        DBG_INFO(("GT_BAD_PARAM\n"));
+			return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	data = fType << 8;
+
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+	
+	retVal = hwReadGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, &data);
+	if(retVal != GT_OK)
+	{		
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	data &= ((1 << 3) | (3 << 0));	/* keep QPri information */
+
+	if (entry->qPriEn)
+		qPri = (GT_U16)((1 << 7) | ((entry->qPriority & 0x3) << 4));
+	else
+		qPri = 0;
+
+	data |= (GT_U16)((1 << 15) | (fType << 8) | qPri);
+
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+	
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetQPriOverrideTable
+*
+* DESCRIPTION:
+* 		Queue Priority Override for AVB enabled ports or AvbOverride enabled ports.
+*		When a frame enters a AVB port, its type is determined and the type is used 
+*		to access the Queue Priority Table. If the type's qPriEn (in GT_QPRI_TBL_ENTRY
+*		structure) is enabled, then the frame's Queue Priority will be overridden
+*		with the value written in qPriority (in GT_QPRI_TBL_ENTRY structure).
+*		Frame Types supported are:
+*			FTYPE_DSA_TO_CPU_BPDU -
+*				Used on multicast DSA To_CPU frames with a Code of 0x0 (BPDU/MGMT).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_F2R -
+*				Used on DSA To_CPU frames with a Code of 0x1 (Frame to Register
+*				Reply). Not used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_IGMP -
+*				Used on DSA To_CPU frames with a Code of 0x2 (IGMP/MLD Trap)
+*				and on non-DSA Control frames that are IGMP or MLD trapped
+*			FTYPE_DSA_TO_CPU_TRAP -
+*				Used on DSA To_CPU frames with a Code of 0x3 (Policy Trap) and
+*				on non-DSA Control frames that are Policy Trapped
+*			FTYPE_DSA_TO_CPU_ARP -
+*				Used on DSA To_CPU frames with a Code of 0x4 (ARP Mirror) and
+*				on non-DSA Control frames that are ARP Mirrored (see gprtSetARPtoCPU API).
+*			FTYPE_DSA_TO_CPU_MIRROR -
+*				Used on DSA To_CPU frames with a Code of 0x5 (Policy Mirror) and
+*				on non-DSA Control frames that are Policy Mirrored (see gprtSetPolicy API).
+*			FTYPE_DSA_TO_CPU_RESERVED -
+*				Used on DSA To_CPU frames with a Code of 0x6 (Reserved). Not
+*				used on non-DSA Control frames.
+*			FTYPE_DSA_TO_CPU_UCAST_MGMT -
+*				Used on unicast DSA To_CPU frames with a Code of 0x0 (unicast
+*				MGMT). Not used on non-DSA Control frames.
+*			FTYPE_DSA_FROM_CPU -
+*				Used on DSA From_CPU frames. Not used on non-DSA Control frame
+*			FTYPE_DSA_CROSS_CHIP_FC -
+*				Used on DSA Cross Chip Flow Control frames (To_Sniffer Flow
+*				Control). Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_EGRESS_MON -
+*				Used on DSA Cross Chip Egress Monitor frames (To_Sniffer Tx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_DSA_CROSS_CHIP_INGRESS_MON -
+*				Used on DSA Cross Chip Ingress Monitor frames (To_Sniffer Rx).
+*				Not used on non-DSA Control frames.
+*			FTYPE_PORT_ETYPE_MATCH -
+*				Used on normal network ports (see gprtSetFrameMode API)
+*				on frames whose Ethertype matches the port's PortEType register.
+*				Not used on non-DSA Control frames.
+*			FTYPE_BCAST_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain a Broadcast
+*				destination address. Not used on DSA Control frames.
+*			FTYPE_PPPoE_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an Ether Type 0x8863
+*				(i.e., PPPoE frames). Not used on DSA Control frames.
+*			FTYPE_IP_NON_DSA_CONTROL -
+*				Used on Non-DSA Control frames that contain an IPv4 or IPv6 Ether
+*				Type. Not used on DSA Control frames.
+*
+* INPUTS:
+*       fType - frame type (GT_PRI_OVERRIDE_FTYPE)
+*
+* OUTPUTS:
+*       entry - Q Priority Override Table entry (GT_QPRI_TBL_ENTRY)
+*
+* RETURNS:
+*		GT_OK      - on success
+*		GT_FAIL    - on error
+*		GT_BAD_PARAM     - on unknown frame type
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetQPriAvbOverrideTable
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_PRI_OVERRIDE_FTYPE	fType,
+	OUT GT_QPRI_TBL_ENTRY	*entry
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+	DBG_INFO(("gsysGetQPriAvbOverrideTable Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QAVB_PRIORITY_OVERRIDE_TABLE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	switch (fType)
+	{
+		case FTYPE_DSA_TO_CPU_BPDU:
+		case FTYPE_DSA_TO_CPU_F2R:
+		case FTYPE_DSA_TO_CPU_IGMP:
+		case FTYPE_DSA_TO_CPU_TRAP:
+		case FTYPE_DSA_TO_CPU_ARP:
+		case FTYPE_DSA_TO_CPU_MIRROR:
+		case FTYPE_DSA_TO_CPU_RESERVED:
+		case FTYPE_DSA_TO_CPU_UCAST_MGMT:
+		case FTYPE_DSA_FROM_CPU:
+		case FTYPE_DSA_CROSS_CHIP_FC:
+		case FTYPE_DSA_CROSS_CHIP_EGRESS_MON:
+		case FTYPE_DSA_CROSS_CHIP_INGRESS_MON:
+		case FTYPE_PORT_ETYPE_MATCH:
+		case FTYPE_BCAST_NON_DSA_CONTROL:
+		case FTYPE_PPPoE_NON_DSA_CONTROL:
+		case FTYPE_IP_NON_DSA_CONTROL:
+			break;
+		default:
+	        DBG_INFO(("GT_BAD_PARAM\n"));
+			return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Wait until the Priority Override Table is ready. */
+	data = 1;
+	while(data == 1)
+	{
+		retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,15,1,&data);
+		if(retVal != GT_OK)
+		{
+			gtSemGive(dev,dev->tblRegsSem);
+			return retVal;
+		}
+	}
+
+	data = fType << 8;
+
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+	
+	retVal = hwReadGlobal2Reg(dev, QD_REG_PRIORITY_OVERRIDE, &data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return retVal;
+	}
+
+	if (data & (1 << 7))
+	{
+		entry->qPriEn = GT_TRUE;
+		entry->qPriority = (data >> 4) & 0x3;
+	}
+	else
+	{
+		entry->qPriEn = GT_FALSE;
+		entry->qPriority = (data >> 4) & 0x3; /* no meaning, but just in case */
+	}
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	return GT_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtQosMap.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtQosMap.c
new file mode 100755
index 0000000..0ee3fbf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtQosMap.c
@@ -0,0 +1,2421 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtQosMap.c
+*
+* DESCRIPTION:
+*       API implementation for qos mapping.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+/*******************************************************************************
+* gcosSetPortDefaultTc
+*
+* DESCRIPTION:
+*       Sets the default traffic class for a specific port.
+*
+* INPUTS:
+*       port      - logical port number
+*       trafClass - default traffic class of a port.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       Fast Ethernet switch family supports 2 bits (0 ~ 3) while Gigabit Switch
+*		family supports 3 bits (0 ~ 7)
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gcosSetPortDefaultTc
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_LPORT   port,
+    IN GT_U8      trafClass
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gcosSetPortDefaultTc Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_QoS)) != GT_OK ) 
+      return retVal;
+	
+	/* Only Gigabit Switch supports this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+	    /* Set the default port pri.  */
+    	retVal = hwSetPortRegField(dev,hwPort,QD_REG_PVID,13,3,trafClass);
+    }
+	else
+	{
+	    /* Set the default port pri.  */
+    	retVal = hwSetPortRegField(dev,hwPort,QD_REG_PVID,14,2,trafClass);
+	}
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gcosGetPortDefaultTc
+*
+* DESCRIPTION:
+*       Gets the default traffic class for a specific port.
+*
+* INPUTS:
+*       port      - logical port number
+*
+* OUTPUTS:
+*       trafClass - default traffic class of a port.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       Fast Ethernet switch family supports 2 bits (0 ~ 3) while Gigabit Switch
+*		family supports 3 bits (0 ~ 7)
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gcosGetPortDefaultTc
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_LPORT   port,
+    OUT GT_U8     *trafClass
+)
+{
+	GT_U16			data;
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gcosSetPortDefaultTc Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_QoS)) != GT_OK ) 
+      return retVal;
+	
+	/* Only Gigabit Switch supports this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH|DEV_ENHANCED_FE_SWITCH))
+    {
+	    /* Get the default port pri.  */
+	    retVal = hwGetPortRegField(dev,hwPort,QD_REG_PVID,13,3,&data);
+    }
+	else
+	{
+	    /* Get the default port pri.  */
+	    retVal = hwGetPortRegField(dev,hwPort,QD_REG_PVID,14,2,&data);
+	}
+
+	*trafClass = (GT_U8)data;
+	
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gqosSetPrioMapRule
+*
+* DESCRIPTION:
+*       This routine sets priority mapping rule.
+*		If the current frame is both IEEE 802.3ac tagged and an IPv4 or IPv6, 
+*		and UserPrioMap (for IEEE 802.3ac) and IPPrioMap (for IP frame) are 
+*		enabled, then priority selection is made based on this setup.
+*		If PrioMapRule is set to GT_TRUE, UserPrioMap is used.
+*		If PrioMapRule is reset to GT_FALSE, IPPrioMap is used.
+*
+* INPUTS:
+*       port - the logical port number.
+*       mode - GT_TRUE for user prio rule, GT_FALSE for otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetPrioMapRule
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    mode
+)
+{
+    GT_U16          data;           /* temporary data buffer */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetPrioMapRule Called.\n"));
+    /* translate bool to binary */
+    BOOL_2_BIT(mode, data);
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_QoS)) != GT_OK ) 
+      return retVal;
+	
+    /* Set the TagIfBoth.  */
+    retVal = hwSetPortRegField(dev,hwPort,QD_REG_PORT_CONTROL,6,1,data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gqosGetPrioMapRule
+*
+* DESCRIPTION:
+*       This routine gets priority mapping rule.
+*		If the current frame is both IEEE 802.3ac tagged and an IPv4 or IPv6, 
+*		and UserPrioMap (for IEEE 802.3ac) and IPPrioMap (for IP frame) are 
+*		enabled, then priority selection is made based on this setup.
+*		If PrioMapRule is set to GT_TRUE, UserPrioMap is used.
+*		If PrioMapRule is reset to GT_FALSE, IPPrioMap is used.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       mode - GT_TRUE for user prio rule, GT_FALSE for otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetPrioMapRule
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *mode
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetPrioMapRule Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_QoS)) != GT_OK ) 
+      return retVal;
+	
+    /* get the TagIfBoth.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,6,1,&data);
+    /* translate bool to binary */
+    BIT_2_BOOL(data, *mode);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gqosIpPrioMapEn
+*
+* DESCRIPTION:
+*       This routine enables the IP priority mapping.
+*
+* INPUTS:
+*       port - the logical port number.
+*       en   - GT_TRUE to Enable, GT_FALSE for otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosIpPrioMapEn
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    en
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosIpPrioMapEn Called.\n"));
+    /* translate bool to binary */
+    BOOL_2_BIT(en, data);
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_QoS)) != GT_OK ) 
+      return retVal;
+	
+    /* Set the useIp.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,5,1,data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+
+/*******************************************************************************
+* gqosGetIpPrioMapEn
+*
+* DESCRIPTION:
+*       This routine return the IP priority mapping state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       en    - GT_TRUE for user prio rule, GT_FALSE for otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetIpPrioMapEn
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *en
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetIpPrioMapEn Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_QoS)) != GT_OK ) 
+      return retVal;
+	
+    /* Get the UseIp.  */
+    retVal = hwGetPortRegField(dev,hwPort,QD_REG_PORT_CONTROL,5,1,&data);
+    /* translate bool to binary */
+    BIT_2_BOOL(data, *en);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+
+/*******************************************************************************
+* gqosUserPrioMapEn
+*
+* DESCRIPTION:
+*       This routine enables the user priority mapping.
+*
+* INPUTS:
+*       port - the logical port number.
+*       en   - GT_TRUE to Enable, GT_FALSE for otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosUserPrioMapEn
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_LPORT   port,
+    IN GT_BOOL    en
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosUserPrioMapEn Called.\n"));
+    /* translate bool to binary */
+    BOOL_2_BIT(en, data);
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_QoS)) != GT_OK ) 
+      return retVal;
+	
+    /* Set the useTag.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL,4,1,data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+
+/*******************************************************************************
+* gqosGetUserPrioMapEn
+*
+* DESCRIPTION:
+*       This routine return the user priority mapping state.
+*
+* INPUTS:
+*       port  - the logical port number.
+*
+* OUTPUTS:
+*       en    - GT_TRUE for user prio rule, GT_FALSE for otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetUserPrioMapEn
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  port,
+    OUT GT_BOOL   *en
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetUserPrioMapEn Called.\n"));
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+    if((retVal = IS_VALID_API_CALL(dev,hwPort, DEV_QoS)) != GT_OK ) 
+      return retVal;
+	
+    /* Get the UseTag.  */
+    retVal = hwGetPortRegField(dev,hwPort,QD_REG_PORT_CONTROL,4,1,&data);
+    /* translate bool to binary */
+    BIT_2_BOOL(data, *en);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gcosGetUserPrio2Tc
+*
+* DESCRIPTION:
+*       Gets the traffic class number for a specific 802.1p user priority.
+*
+* INPUTS:
+*       userPrior - user priority
+*
+* OUTPUTS:
+*       trClass - The Traffic Class the received frame is assigned.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gcosGetUserPrio2Tc
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     userPrior,
+    OUT GT_U8     *trClass
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           bitOffset;      /* the bit offset in the reg    */
+    GT_U16          data;           /* store the read data          */
+
+    DBG_INFO(("gcosGetUserPrio2Tc Called.\n"));
+
+    /* check if device supports this feature */
+    if(!IS_IN_DEV_GROUP(dev,DEV_QoS))
+		return GT_NOT_SUPPORTED;
+	
+    /* calc the bit offset */
+    bitOffset = ((userPrior & 0x7) * 2);
+    /* Get the traffic class for the VPT.  */
+    retVal = hwGetGlobalRegField(dev,QD_REG_IEEE_PRI,bitOffset,2,&data);
+    *trClass = (GT_U8)data;
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gcosSetUserPrio2Tc
+*
+* DESCRIPTION:
+*       Sets the traffic class number for a specific 802.1p user priority.
+*
+* INPUTS:
+*       userPrior - user priority of a port.
+*       trClass   - the Traffic Class the received frame is assigned.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gcosSetUserPrio2Tc
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_U8      userPrior,
+    IN GT_U8      trClass
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           bitOffset;      /* the bit offset in the reg    */
+
+    DBG_INFO(("gcosSetUserPrio2Tc Called.\n"));
+    /* check if device supports this feature */
+    if(!IS_IN_DEV_GROUP(dev,DEV_QoS))
+		return GT_NOT_SUPPORTED;
+	
+    /* calc the bit offset */
+    bitOffset = ((userPrior & 0x7) * 2);
+    /* Set the traffic class for the VPT.  */
+    retVal = hwSetGlobalRegField(dev,QD_REG_IEEE_PRI, bitOffset,2,trClass);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gcosGetDscp2Tc
+*
+* DESCRIPTION:
+*       This routine retrieves the traffic class assigned for a specific
+*       IPv4 Dscp.
+*
+* INPUTS:
+*       dscp    - the IPv4 frame dscp to query.
+*
+* OUTPUTS:
+*       trClass - The Traffic Class the received frame is assigned.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gcosGetDscp2Tc
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     dscp,
+    OUT GT_U8     *trClass
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           bitOffset;      /* the bit offset in the reg    */
+    GT_U8           regOffset;      /* the reg offset in the IP tbl */
+    GT_U16          data;           /* store the read data          */
+
+    DBG_INFO(("gcosGetDscp2Tc Called.\n"));
+    /* check if device supports this feature */
+    if(!IS_IN_DEV_GROUP(dev,DEV_QoS))
+		return GT_NOT_SUPPORTED;
+	
+    /* calc the bit offset */
+    bitOffset = (((dscp & 0x3f) % 8) * 2);
+    regOffset = ((dscp & 0x3f) / 8);
+    /* Get the traffic class for the IP dscp.  */
+    retVal = hwGetGlobalRegField(dev,(GT_U8)(QD_REG_IP_PRI_BASE+regOffset),
+                                 bitOffset, 2, &data);
+    *trClass = (GT_U8)data;
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gcosSetDscp2Tc
+*
+* DESCRIPTION:
+*       This routine sets the traffic class assigned for a specific
+*       IPv4 Dscp.
+*
+* INPUTS:
+*       dscp    - the IPv4 frame dscp to map.
+*       trClass - the Traffic Class the received frame is assigned.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gcosSetDscp2Tc
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_U8      dscp,
+    IN GT_U8      trClass
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           bitOffset;      /* the bit offset in the reg    */
+    GT_U8           regOffset;      /* the reg offset in the IP tbl */
+
+    DBG_INFO(("gcosSetDscp2Tc Called.\n"));
+    /* check if device supports this feature */
+    if(!IS_IN_DEV_GROUP(dev,DEV_QoS))
+		return GT_NOT_SUPPORTED;
+	
+    /* calc the bit offset */
+    bitOffset = (((dscp & 0x3f) % 8) * 2);
+    regOffset = ((dscp & 0x3f) / 8);
+    /* Set the traffic class for the IP dscp.  */
+    retVal = hwSetGlobalRegField(dev,(GT_U8)(QD_REG_IP_PRI_BASE+regOffset),
+                                 bitOffset, 2, trClass);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+
+/*******************************************************************************
+* gqosGetTagRemap
+*
+* DESCRIPTION:
+*		Gets the remapped priority value for a specific 802.1p priority on a
+*		given port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*		pri   - 802.1p priority
+*
+* OUTPUTS:
+*		remappedPri - remapped Priority
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetTagRemap
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT 	port,
+	IN  GT_U8    	pri,
+	OUT GT_U8   	*remappedPri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* store the read data          */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U8           regAddr;        /* register address.            */
+    GT_U8           bitOffset;      /* the bit offset in the reg    */
+	
+    DBG_INFO(("gqosGetTagRemap Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_REMAPPING))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	if (pri <= 3)
+	{
+		regAddr = QD_REG_IEEE_PRI_REMAP_3_0;
+	}
+	else
+	{
+		regAddr = QD_REG_IEEE_PRI_REMAP_7_4;
+	}
+
+    /* calc the bit offset */
+    bitOffset = 4 * (pri % 4);
+	
+    retVal = hwGetPortRegField(dev,phyPort,regAddr,bitOffset,3,&data );
+
+    *remappedPri = (GT_U8)data;
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetTagRemap
+*
+* DESCRIPTION:
+*		Sets the remapped priority value for a specific 802.1p priority on a
+*		given port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*		pri   - 802.1p priority
+*		remappedPri - remapped Priority
+*
+* OUTPUTS:
+*		None
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetTagRemap
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port,
+	IN GT_U8    	pri,
+	IN GT_U8    	remappedPri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           phyPort;        /* Physical port.               */
+    GT_U8           regAddr;        /* register address.            */
+    GT_U8           bitOffset;      /* the bit offset in the reg    */
+	
+    DBG_INFO(("gqosSetTagRemap Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_PRIORITY_REMAPPING))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+    phyPort = GT_LPORT_2_PORT(port);
+
+	if (pri <= 3)
+	{
+		regAddr = QD_REG_IEEE_PRI_REMAP_3_0;
+	}
+	else
+	{
+		regAddr = QD_REG_IEEE_PRI_REMAP_7_4;
+	}
+
+    /* calc the bit offset */
+    bitOffset = 4 * (pri % 4);
+	
+    retVal = hwSetPortRegField(dev,phyPort,regAddr,bitOffset,3,remappedPri);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetQPriValue
+*
+* DESCRIPTION:
+*       This routine sets Queue priority value to used when forced.
+*		When ForceQPri is enabled (gqosSetForceQPri), all frames entering this port
+*		are mapped to the priority queue defined in this value, unless a VTU, SA,
+*		DA or ARP priority override occurs. The Frame's priority (FPri) is not
+*		effected by this value.
+*
+* INPUTS:
+*       port - the logical port number.
+*       pri  - Queue priority value
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if pri > 3
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosSetQPriValue
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    IN  GT_U8      pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetQPriValue Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_FPRI_QPRI))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (pri > 3)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    /* Set the QPriValue.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_VLAN_MAP, 10, 2, (GT_U16)pri);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosGetQPriValue
+*
+* DESCRIPTION:
+*       This routine gets Queue priority value to used when forced.
+*		When ForceQPri is enabled (gqosSetForceQPri), all frames entering this port
+*		are mapped to the priority queue defined in this value, unless a VTU, SA,
+*		DA or ARP priority override occurs. The Frame's priority (FPri) is not
+*		effected by this value.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       pri  - Queue priority value
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosGetQPriValue
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_U8      *pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			data;
+
+    DBG_INFO(("gqosGetQPriValue Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_FPRI_QPRI))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the QPriValue.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_VLAN_MAP, 10, 2, &data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	*pri = (GT_U8)data;
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetForceQPri
+*
+* DESCRIPTION:
+*       This routine enables/disables forcing Queue priority.
+*		When ForceQPri is disabled, normal priority queue mapping is used on all 
+*		ingressing frames entering this port. When it's enabled, all frames
+*		entering this port are mapped to the QPriValue (gqosSetQPriValue), unless
+*		a VTU, SA, DA or ARP priority override occurs. The frame's priorty (FPri)
+*		is not effected by this feature.
+*
+* INPUTS:
+*       port - the logical port number.
+*       en   - GT_TRUE, to force Queue Priority,
+*			   GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosSetForceQPri
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    IN  GT_BOOL    en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetQPriValue Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(en, data);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_FPRI_QPRI))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Set the ForceQPri.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_VLAN_MAP, 9, 1, data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosGetForceQPri
+*
+* DESCRIPTION:
+*       This routine checks if forcing Queue priority is enabled.
+*		When ForceQPri is disabled, normal priority queue mapping is used on all 
+*		ingressing frames entering this port. When it's enabled, all frames
+*		entering this port are mapped to the QPriValue (gqosSetQPriValue), unless
+*		a VTU, SA, DA or ARP priority override occurs. The frame's priorty (FPri)
+*		is not effected by this feature.
+*
+* INPUTS:
+*       port - the logical port number.
+*
+* OUTPUTS:
+*       en   - GT_TRUE, to force Queue Priority,
+*			   GT_FALSE, otherwise.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosGetForceQPri
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_BOOL    *en
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetQPriValue Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_FPRI_QPRI))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the ForceQPri.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_VLAN_MAP, 9, 1, &data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *en);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetDefFPri
+*
+* DESCRIPTION:
+*       This routine sets the default frame priority (0 ~ 7).
+*		This priority is used as the default frame priority (FPri) to use when 
+*		no other priority information is available.
+*
+* INPUTS:
+*       port - the logical port number
+*       pri  - default frame priority
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if pri > 7
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosSetDefFPri
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    IN  GT_U8      pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetDefFPri Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_FPRI_QPRI))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (pri > 7)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    /* Set the DefFPri.  */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PVID, 13, 3, (GT_U16)pri);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosGetDefFPri
+*
+* DESCRIPTION:
+*       This routine gets the default frame priority (0 ~ 7).
+*		This priority is used as the default frame priority (FPri) to use when 
+*		no other priority information is available.
+*
+* INPUTS:
+*       port - the logical port number
+*
+* OUTPUTS:
+*       pri  - default frame priority
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gqosGetDefFPri
+(
+    IN  GT_QD_DEV  *dev,
+    IN  GT_LPORT   port,
+    OUT GT_U8      *pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+	GT_U16			data;
+
+    DBG_INFO(("gqosGetDefFPri Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_FPRI_QPRI))
+	{
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the DefFPri.  */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PVID, 13, 3, &data);
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+	*pri = (GT_U8)data;
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetVIDFPriOverride
+*
+* DESCRIPTION:
+*		This routine sets VID Frame Priority Override. When this feature is enabled,
+*		VID Frame priority overrides can occur on this port.
+*		VID Frame priority override occurs when the determined VID of a frame 
+*		results in a VTU entry whose useVIDFPri override field is set to GT_TRUE.
+*		When this occurs the VIDFPri value assigned to the frame's VID (in the 
+*		VTU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new VIDFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for VID Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetVIDFPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetVIDFPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the VIDFPriOverride mode.            */
+   	retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,14,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosGetVIDFPriOverride
+*
+* DESCRIPTION:
+*		This routine gets VID Frame Priority Override. When this feature is enabled,
+*		VID Frame priority overrides can occur on this port.
+*		VID Frame priority override occurs when the determined VID of a frame 
+*		results in a VTU entry whose useVIDFPri override field is set to GT_TRUE.
+*		When this occurs the VIDFPri value assigned to the frame's VID (in the 
+*		VTU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new VIDFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for VID Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetVIDFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetVIDFPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the VIDFPriOverride mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,14,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetSAFPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Source Address(SA) Frame Priority Override. 
+*		When this feature is enabled, SA Frame priority overrides can occur on 
+*		this port.
+*		SA ATU Frame priority override occurs when the determined source address
+*		of a frame results in an ATU hit where the SA's MAC address entry contains 
+*		the useATUFPri field set to GT_TRUE.
+*		When this occurs the ATUFPri value assigned to the frame's SA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new ATUFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for SA Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetSAFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetSAFPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the SAFPriOverride mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,13,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosGetSAFPriOverride
+*
+* DESCRIPTION:
+*		This routine gets Source Address(SA) Frame Priority Override. 
+*		When this feature is enabled, SA Frame priority overrides can occur on 
+*		this port.
+*		SA ATU Frame priority override occurs when the determined source address
+*		of a frame results in an ATU hit where the SA's MAC address entry contains 
+*		the useATUFPri field set to GT_TRUE.
+*		When this occurs the ATUFPri value assigned to the frame's SA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new ATUFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for SA Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetSAFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetSAFPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the SAFPriOverride mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,13,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosSetDAFPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Destination Address(DA) Frame Priority Override. 
+*		When this feature is enabled, DA Frame priority overrides can occur on 
+*		this port.
+*		DA ATU Frame priority override occurs when the determined destination address
+*		of a frame results in an ATU hit where the DA's MAC address entry contains 
+*		the useATUFPri field set to GT_TRUE.
+*		When this occurs the ATUFPri value assigned to the frame's DA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new ATUFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for DA Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetDAFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetDAFPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the DAFPriOverride mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,12,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosGetDAFPriOverride
+*
+* DESCRIPTION:
+*		This routine gets Destination Address(DA) Frame Priority Override. 
+*		When this feature is enabled, DA Frame priority overrides can occur on 
+*		this port.
+*		DA ATU Frame priority override occurs when the determined destination address
+*		of a frame results in an ATU hit where the DA's MAC address entry contains 
+*		the useATUFPri field set to GT_TRUE.
+*		When this occurs the ATUFPri value assigned to the frame's DA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined frame 
+*		priority. If the frame egresses tagged the priority in the frame will be
+*		this new ATUFPri value. This function does not affect the egress queue
+*		priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for DA Frame Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetDAFPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetDAFPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the DAFPriOverride mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,12,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetVIDQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets VID Queue Priority Override. When this feature is enabled,
+*		VID Queue priority overrides can occur on this port.
+*		VID Queue priority override occurs when the determined VID of a frame 
+*		results in a VTU entry whose useVIDQPri override field is set to GT_TRUE.
+*		When this occurs the VIDQPri value assigned to the frame's VID (in the 
+*		VTU Table) is used to overwrite the frame's previously determined queue 
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new VIDQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for VID Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetVIDQPriOverride
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port,
+	IN GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetVIDQPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the VIDQPriOverride mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,3,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosGetVIDQPriOverride
+*
+* DESCRIPTION:
+*		This routine gets VID Queue Priority Override. When this feature is enabled,
+*		VID Queue priority overrides can occur on this port.
+*		VID Queue priority override occurs when the determined VID of a frame 
+*		results in a VTU entry whose useVIDQPri override field is set to GT_TRUE.
+*		When this occurs the VIDQPri value assigned to the frame's VID (in the 
+*		VTU Table) is used to overwrite the frame's previously determined queue 
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new VIDQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for VID Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetVIDQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetVIDQPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the VIDQPriOverride mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,3,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetSAQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Source Address(SA) Queue Priority Override. 
+*		When this feature is enabled, SA Queue priority overrides can occur on 
+*		this port.
+*		SA ATU Queue priority override occurs when the determined source address
+*		of a frame results in an ATU hit where the SA's MAC address entry contains 
+*		the useATUQPri field set to GT_TRUE.
+*		When this occurs the ATUQPri value assigned to the frame's SA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined queue 
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new ATUQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for SA Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetSAQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetSAQPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the SAQPriOverride mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,2,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosGetSAQPriOverride
+*
+* DESCRIPTION:
+*		This routine gets Source Address(SA) Queue Priority Override. 
+*		When this feature is enabled, SA Queue priority overrides can occur on 
+*		this port.
+*		SA ATU Queue priority override occurs when the determined source address
+*		of a frame results in an ATU hit where the SA's MAC address entry contains 
+*		the useATUQPri field set to GT_TRUE.
+*		When this occurs the ATUQPri value assigned to the frame's SA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined queue 
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new ATUQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for SA Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetSAQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetSAQPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the SAQPriOverride mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,2,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosSetDAQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Destination Address(DA) Queue Priority Override. 
+*		When this feature is enabled, DA Queue priority overrides can occur on 
+*		this port.
+*		DA ATU Queue priority override occurs when the determined destination address
+*		of a frame results in an ATU hit where the DA's MAC address entry contains 
+*		the useATUQPri field set to GT_TRUE.
+*		When this occurs the ATUQPri value assigned to the frame's DA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined queue
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new ATUQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for DA Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetDAQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetDAQPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the DAQPriOverride mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,1,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosGetDAQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets Destination Address(DA) Queue Priority Override. 
+*		When this feature is enabled, DA Queue priority overrides can occur on 
+*		this port.
+*		DA ATU Queue priority override occurs when the determined destination address
+*		of a frame results in an ATU hit where the DA's MAC address entry contains 
+*		the useATUQPri field set to GT_TRUE.
+*		When this occurs the ATUQPri value assigned to the frame's DA (in the 
+*		ATU Table) is used to overwrite the frame's previously determined queue
+*		priority. If the frame egresses tagged the priority in the frame will not
+*		be modified by this new ATUQPri value. This function affects the egress
+*		queue priority (QPri) the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for DA Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetDAQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetDAQPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the DAQPriOverride mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,1,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosSetARPQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets ARP Queue Priority Override. 
+*		When this feature is enabled, ARP Queue priority overrides can occur on 
+*		this port.
+*		ARP Queue priority override occurs for all ARP frames.
+*		When this occurs, the frame's previously determined egress queue priority
+*		will be overwritten with ArpQPri.
+*		If the frame egresses tagged the priority in the frame will not
+*		be modified. When used, the two bits of the ArpQPri priority determine the
+*		egress queue the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*		mode - GT_TRUE for ARP Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosSetARPQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	IN  GT_BOOL		mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosSetARPQPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate BOOL to binary */
+    BOOL_2_BIT(mode, data);
+
+    /* Set the ARPQPriOverride mode.            */
+    retVal = hwSetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,0,1,data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+    return retVal;
+}
+
+/*******************************************************************************
+* gqosGetARPQPriOverride
+*
+* DESCRIPTION:
+*		This routine sets ARP Queue Priority Override. 
+*		When this feature is enabled, ARP Queue priority overrides can occur on 
+*		this port.
+*		ARP Queue priority override occurs for all ARP frames.
+*		When this occurs, the frame's previously determined egress queue priority
+*		will be overwritten with ArpQPri.
+*		If the frame egresses tagged the priority in the frame will not
+*		be modified. When used, the two bits of the ArpQPri priority determine the
+*		egress queue the frame is switched into.
+*
+* INPUTS:
+*		port - the logical port number.
+*
+* OUTPUTS:
+*		mode - GT_TRUE for ARP Queue Priority Override,
+*			   GT_FALSE otherwise
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS: 
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gqosGetARPQPriOverride
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	port,
+	OUT GT_BOOL		*mode
+)
+{
+    GT_U16          data;           
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gqosGetARPQPriOverride Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the ARPQPriOverride mode.            */
+    retVal = hwGetPortRegField(dev,hwPort, QD_REG_PORT_CONTROL2,0,1,&data);
+
+    if(retVal != GT_OK)
+	{
+        DBG_INFO(("Failed.\n"));
+	}
+    else
+	{
+        DBG_INFO(("OK.\n"));
+	}
+
+    BIT_2_BOOL(data, *mode);
+
+    return retVal;
+}
+
+
+/*******************************************************************************
+* gqosSetArpQPri
+*
+* DESCRIPTION:
+*       This routine sets ARP queue Priority to use for ARP QPri Overridden 
+*		frames. When a ARP frame is received on a por tthat has its ARP 
+*		QPriOVerride is enabled, the QPri assigned to the frame comes from
+*		this value
+*
+* INPUTS:
+*       pri - ARP Queue Priority (0 ~ 3)
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_BAD_PARAM - if pri > 3
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gqosSetArpQPri
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gqosSetArpQPri Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (pri > 3)
+	{
+		DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	data = (GT_U16)pri;
+
+    /* Set the ArpQPri bit.            */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,6,2,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gqosGetArpQPri
+*
+* DESCRIPTION:
+*       This routine gets ARP queue Priority to use for ARP QPri Overridden 
+*		frames. When a ARP frame is received on a por tthat has its ARP 
+*		QPriOVerride is enabled, the QPri assigned to the frame comes from
+*		this value
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       pri - ARP Queue Priority (0 ~ 3)
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gqosGetArpQPri
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_U8     *pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gqosGetArpQPri Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_FQPRI_OVERRIDE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the ArpQPri bit.            */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,6,2,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	*pri = (GT_U8)data;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysConfig.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysConfig.c
new file mode 100755
index 0000000..8372ba3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysConfig.c
@@ -0,0 +1,899 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtSysConfig.c
+*
+* DESCRIPTION:
+*       API definitions for system configuration, and enabling.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 4 $
+*
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtDrvConfig.h>
+#include <gtSem.h>
+#include <platformDeps.h>
+
+static GT_BOOL gtRegister(GT_QD_DEV *dev, BSP_FUNCTIONS* pBSPFunctions);
+
+/*******************************************************************************
+* qdLoadDriver
+*
+* DESCRIPTION:
+*       QuarterDeck Driver Initialization Routine. 
+*       This is the first routine that needs be called by system software. 
+*       It takes *cfg from system software, and retures a pointer (*dev) 
+*       to a data structure which includes infomation related to this QuarterDeck
+*       device. This pointer (*dev) is then used for all the API functions. 
+*
+* INPUTS:
+*       cfg  - Holds device configuration parameters provided by system software.
+*
+* OUTPUTS:
+*       dev  - Holds device information to be used for each API call.
+*
+* RETURNS:
+*       GT_OK               - on success
+*       GT_FAIL             - on error
+*       GT_ALREADY_EXIST    - if device already started
+*       GT_BAD_PARAM        - on bad parameters
+*
+* COMMENTS:
+* 	qdUnloadDriver is also provided to do driver cleanup.
+*
+*******************************************************************************/
+GT_STATUS qdLoadDriver
+(
+    IN  GT_SYS_CONFIG   *cfg,
+    OUT GT_QD_DEV	*dev
+)
+{
+    GT_STATUS   retVal;
+	GT_LPORT	port;
+
+    DBG_INFO(("qdLoadDriver Called.\n"));
+
+    /* Check for parameters validity        */
+    if(dev == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* Check for parameters validity        */
+    if(cfg == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* The initialization was already done. */
+    if(dev->devEnabled)
+    {
+        DBG_INFO(("QuarterDeck already started.\n"));
+        return GT_ALREADY_EXIST;
+    }
+
+    if(gtRegister(dev,&(cfg->BSPFunctions)) != GT_TRUE)
+    {
+       DBG_INFO(("gtRegister Failed.\n"));
+       return GT_FAIL;
+    }
+	dev->accessMode = (GT_U8)cfg->mode.scanMode;
+	if (dev->accessMode == SMI_MULTI_ADDR_MODE)
+	{
+		dev->baseRegAddr = 0;
+		dev->phyAddr = (GT_U8)cfg->mode.baseAddr;
+	}
+	else
+	{
+		dev->baseRegAddr = (GT_U8)cfg->mode.baseAddr;
+		dev->phyAddr = 0;
+	}
+
+    /* Initialize the driver    */
+    retVal = driverConfig(dev);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("driverConfig Failed.\n"));
+        return retVal;
+    }
+
+    /* Initialize dev fields.         */
+    dev->cpuPortNum = cfg->cpuPortNum;
+    dev->maxPhyNum = 5;
+    dev->devGroup = 0;
+    dev->devStorage = 0;
+
+    /* Assign Device Name */
+    switch(dev->deviceId)
+    {
+		case GT_88E6021:
+				dev->numOfPorts = 3;
+				dev->maxPorts = 3;
+				dev->maxPhyNum = 2;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6021;
+				break;
+
+		case GT_88E6051:
+				dev->numOfPorts = 5;
+				dev->maxPorts = 5;
+				dev->maxPhyNum = 5;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6051;
+				break;
+
+		case GT_88E6052:
+				dev->numOfPorts = 7;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 5;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6052;
+				break;
+
+		case GT_88E6060:
+				if((dev->cpuPortNum != 4)&&(dev->cpuPortNum != 5))
+				{
+					return GT_FAIL;
+				}
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 5;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6060;
+				break;
+
+		case GT_88E6031:
+				dev->numOfPorts = 3;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 3;
+				dev->validPortVec = 0x31;	/* port 0, 4, and 5 */
+				dev->validPhyVec = 0x31;	/* port 0, 4, and 5 */
+				dev->devName = DEV_88E6061;
+				break;
+
+		case GT_88E6061:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 6;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6061;
+				break;
+
+		case GT_88E6035:
+				dev->numOfPorts = 3;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 3;
+				dev->validPortVec = 0x31;	/* port 0, 4, and 5 */
+				dev->validPhyVec = 0x31;	/* port 0, 4, and 5 */
+				dev->devName = DEV_88E6065;
+				break;
+
+		case GT_88E6055:
+				dev->numOfPorts = 5;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 5;
+				dev->validPortVec = 0x2F;	/* port 0,1,2,3, and 5 */
+				dev->validPhyVec = 0x2F;	/* port 0,1,2,3, and 5 */
+				dev->devName = DEV_88E6065;
+				break;
+
+		case GT_88E6065:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 6;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6065;
+				break;
+
+		case GT_88E6063:
+				dev->numOfPorts = 7;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 5;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6063;
+				break;
+
+		case GT_FH_VPN:
+				dev->numOfPorts = 7;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 5;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_FH_VPN;
+				break;
+
+		case GT_FF_EG:
+				if(dev->cpuPortNum != 5)
+				{
+					return GT_FAIL;
+				}
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 5;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_FF_EG;
+				break;
+
+		case GT_FF_HG:
+				dev->numOfPorts = 7;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 5;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_FF_HG;
+				break;
+
+		case GT_88E6083:
+				dev->numOfPorts = 10;
+				dev->maxPorts = 10;
+				dev->maxPhyNum = 8;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6083;
+				break;
+
+		case GT_88E6153:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 6;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6183;
+				break;
+
+		case GT_88E6181:
+				dev->numOfPorts = 8;
+				dev->maxPorts = 8;
+				dev->maxPhyNum = 8;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6181;
+				break;
+
+		case GT_88E6183:
+				dev->numOfPorts = 10;
+				dev->maxPorts = 10;
+				dev->maxPhyNum = 10;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6183;
+				break;
+
+		case GT_88E6093:
+				dev->numOfPorts = 11;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6093;
+				break;
+
+		case GT_88E6092:
+				dev->numOfPorts = 11;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6092;
+				break;
+
+		case GT_88E6095:
+				dev->numOfPorts = 11;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6095;
+				break;
+
+		case GT_88E6045:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = 0x60F;
+				dev->validPhyVec = 0x60F;
+				dev->devName = DEV_88E6095;
+				break;
+
+		case GT_88E6097:
+				dev->numOfPorts = 11;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6097;
+				break;
+
+		case GT_88E6096:
+				dev->numOfPorts = 11;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6096;
+				break;
+
+		case GT_88E6047:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = 0x60F;
+				dev->validPhyVec = 0x60F;
+				dev->devName = DEV_88E6097;
+				break;
+
+		case GT_88E6046:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = 0x60F;
+				dev->validPhyVec = 0x60F;
+				dev->devName = DEV_88E6096;
+				break;
+
+		case GT_88E6085:
+				dev->numOfPorts = 10;
+				dev->maxPorts = 11;
+				dev->maxPhyNum = 11;
+				dev->validPortVec = 0x6FF;
+				dev->validPhyVec = 0x6FF;
+				dev->devName = DEV_88E6096;
+				break;
+
+		case GT_88E6152:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 6;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6182;
+				break;
+
+		case GT_88E6155:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 6;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6185;
+				break;
+
+		case GT_88E6182:
+				dev->numOfPorts = 10;
+				dev->maxPorts = 10;
+				dev->maxPhyNum = 10;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6182;
+				break;
+
+		case GT_88E6185:
+				dev->numOfPorts = 10;
+				dev->maxPorts = 10;
+				dev->maxPhyNum = 10;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->devName = DEV_88E6185;
+				break;
+
+		case GT_88E6121:
+				dev->numOfPorts = 3;
+				dev->maxPorts = 8;
+				dev->maxPhyNum = 3;
+				dev->validPortVec = 0xE;	/* port 1, 2, and 3 */
+				dev->validPhyVec = 0xE;		/* port 1, 2, and 3 */
+				dev->devName = DEV_88E6108;
+				break;
+
+		case GT_88E6122:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 8;
+				dev->maxPhyNum = 16;
+				dev->validPortVec = 0x7E;	/* port 1 ~ 6 */
+				dev->validPhyVec = 0xF07E;	/* port 1 ~ 6, 12 ~ 15 (serdes) */
+				dev->validSerdesVec = 0xF000;
+				dev->devName = DEV_88E6108;
+				break;
+
+		case GT_88E6131:
+		case GT_88E6108:
+				dev->numOfPorts = 8;
+				dev->maxPorts = 8;
+				dev->maxPhyNum = 16;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
+				dev->validSerdesVec = 0xF000;
+				dev->devName = DEV_88E6108;
+				break;
+
+		case GT_88E6123:
+				dev->numOfPorts = 3;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 14;
+				dev->validPortVec = 0x23;
+				dev->validPhyVec = 0x303F;
+				dev->validSerdesVec = 0x3000;
+				dev->devName = DEV_88E6161;
+				break;
+
+		case GT_88E6140:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 14;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = 0x303F;
+				dev->validSerdesVec = 0x3000;
+				dev->devName = DEV_88E6165;
+				break;
+
+		case GT_88E6161:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 14;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = 0x303F;
+				dev->validSerdesVec = 0x3000;
+				dev->devName = DEV_88E6161;
+				break;
+
+		case GT_88E6165:
+				dev->numOfPorts = 6;
+				dev->maxPorts = 6;
+				dev->maxPhyNum = 14;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = 0x303F;
+				dev->validSerdesVec = 0x3000;
+				dev->devName = DEV_88E6165;
+				break;
+
+		case GT_KW2_INT :
+				dev->deviceId = GT_88E6351;
+				/* fall through */
+		case GT_88E6351:
+				dev->numOfPorts = 7;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 7;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = 0x7F;
+				dev->devName = DEV_88E6351;
+				break;
+
+		case GT_88E6175:
+				dev->numOfPorts = 7;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 7;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = 0x7F;
+				dev->devName = DEV_88E6175;
+				break;
+
+		case GT_88E6125 :
+				dev->numOfPorts = 4;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 7;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPortVec &= ~(0x7);
+				dev->validPhyVec = 0x78;
+				dev->devName = DEV_88E6171;
+				break;
+
+		case GT_88E6171 :
+				dev->numOfPorts = 7;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 7;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = 0x7F;
+				dev->devName = DEV_88E6171;
+				break;
+
+		case GT_88E6321 :
+				dev->numOfPorts = 4;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 7;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPortVec &= ~(0x7);
+				dev->validPhyVec = 0x78;
+				dev->devName = DEV_88E6371;
+				break;
+
+		case GT_88E6350 :
+				dev->numOfPorts = 7;
+				dev->maxPorts = 7;
+				dev->maxPhyNum = 7;
+				dev->validPortVec = (1 << dev->numOfPorts) - 1;
+				dev->validPhyVec = 0x7F;
+				dev->devName = DEV_88E6371;
+				break;
+
+		default:
+				DBG_INFO(("Unknown Device. Initialization failed\n"));
+				return GT_FAIL;
+    }
+
+    dev->cpuPortNum = GT_PORT_2_LPORT(cfg->cpuPortNum);
+
+    if(dev->cpuPortNum == GT_INVALID_PORT)
+	{
+    	if(GT_LPORT_2_PORT((GT_LPORT)cfg->cpuPortNum) != GT_INVALID_PORT)
+		{
+		    dev->cpuPortNum = cfg->cpuPortNum;
+		}
+		else
+		{
+			return GT_BAD_CPU_PORT;
+		}
+	}
+
+    /* Initialize the MultiAddress Register Access semaphore.    */
+    if((dev->multiAddrSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+        DBG_INFO(("semCreate Failed.\n"));
+        qdUnloadDriver(dev);
+        return GT_FAIL;
+    }
+
+    /* Initialize the ATU semaphore.    */
+    if((dev->atuRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+        DBG_INFO(("semCreate Failed.\n"));
+        qdUnloadDriver(dev);
+        return GT_FAIL;
+    }
+
+    /* Initialize the VTU semaphore.    */
+    if((dev->vtuRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+        DBG_INFO(("semCreate Failed.\n"));
+		qdUnloadDriver(dev);
+        return GT_FAIL;
+    }
+
+    /* Initialize the STATS semaphore.    */
+    if((dev->statsRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+        DBG_INFO(("semCreate Failed.\n"));
+		qdUnloadDriver(dev);
+        return GT_FAIL;
+    }
+
+    /* Initialize the PIRL semaphore.    */
+    if((dev->pirlRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+        DBG_INFO(("semCreate Failed.\n"));
+		qdUnloadDriver(dev);
+        return GT_FAIL;
+    }
+
+    /* Initialize the PTP semaphore.    */
+    if((dev->ptpRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+        DBG_INFO(("semCreate Failed.\n"));
+		qdUnloadDriver(dev);
+        return GT_FAIL;
+    }
+
+    /* Initialize the Table semaphore.    */
+    if((dev->tblRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+		DBG_INFO(("semCreate Failed.\n"));
+		qdUnloadDriver(dev);
+		return GT_FAIL;
+    }
+
+    /* Initialize the EEPROM Configuration semaphore.    */
+    if((dev->eepromRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+		DBG_INFO(("semCreate Failed.\n"));
+		qdUnloadDriver(dev);
+		return GT_FAIL;
+    }
+
+    /* Initialize the PHY Device Register Access semaphore.    */
+    if((dev->phyRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
+    {
+        DBG_INFO(("semCreate Failed.\n"));
+        qdUnloadDriver(dev);
+        return GT_FAIL;
+    }
+
+    /* Initialize the ports states to forwarding mode. */
+    if(cfg->initPorts == GT_TRUE)
+    {
+		for (port=0; port<dev->numOfPorts; port++)
+		{
+			if((retVal = gstpSetPortState(dev,port,GT_PORT_FORWARDING)) != GT_OK)
+   			{
+	    	    DBG_INFO(("Failed.\n"));
+				qdUnloadDriver(dev);
+   		    	return retVal;
+	    	}
+		}
+    }
+
+    if(cfg->skipInitSetup == GT_SKIP_INIT_SETUP)
+	{
+	    dev->devEnabled = 1;
+    	dev->devNum = cfg->devNum;
+
+	    DBG_INFO(("OK.\n"));
+    	return GT_OK;
+	}
+
+	if(IS_IN_DEV_GROUP(dev,DEV_ENHANCED_CPU_PORT))
+	{
+		if((retVal = gsysSetRsvd2CpuEnables(dev,0)) != GT_OK)
+		{
+	        DBG_INFO(("gsysGetRsvd2CpuEnables failed.\n"));
+			qdUnloadDriver(dev);
+			return retVal;
+		}
+
+		if((retVal = gsysSetRsvd2Cpu(dev,GT_FALSE)) != GT_OK)
+		{
+	        DBG_INFO(("gsysSetRsvd2Cpu failed.\n"));
+			qdUnloadDriver(dev);
+			return retVal;
+		}
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_CPU_DEST_PER_PORT))
+	{
+		for (port=0; port<dev->numOfPorts; port++)
+		{
+			retVal = gprtSetCPUPort(dev,port,dev->cpuPortNum);
+		    if(retVal != GT_OK)
+    		{
+	    	    DBG_INFO(("Failed.\n"));
+				qdUnloadDriver(dev);
+	   	    	return retVal;
+		    }
+		}
+	}
+
+	if(IS_IN_DEV_GROUP(dev,DEV_CPU_PORT))
+	{
+		retVal = gsysSetCPUPort(dev,dev->cpuPortNum);
+	    if(retVal != GT_OK)
+   		{
+    	    DBG_INFO(("Failed.\n"));
+			qdUnloadDriver(dev);
+   	    	return retVal;
+	    }
+	}
+
+	if(IS_IN_DEV_GROUP(dev,DEV_CPU_DEST))
+	{
+		retVal = gsysSetCPUDest(dev,dev->cpuPortNum);
+	    if(retVal != GT_OK)
+   		{
+    	    DBG_INFO(("Failed.\n"));
+			qdUnloadDriver(dev);
+   	    	return retVal;
+	    }
+	}
+
+	if(IS_IN_DEV_GROUP(dev,DEV_MULTICAST))
+	{
+		if((retVal = gsysSetRsvd2Cpu(dev,GT_FALSE)) != GT_OK)
+		{
+	        DBG_INFO(("gsysSetRsvd2Cpu failed.\n"));
+			qdUnloadDriver(dev);
+			return retVal;
+		}
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
+	{
+		retVal = gpirlInitialize(dev);
+	    if(retVal != GT_OK)
+   		{
+    	    DBG_INFO(("Failed.\n"));
+			qdUnloadDriver(dev);
+   	    	return retVal;
+	    }
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
+	{
+		retVal = gpirl2Initialize(dev);
+	    if(retVal != GT_OK)
+   		{
+    	    DBG_INFO(("Failed.\n"));
+			qdUnloadDriver(dev);
+   	    	return retVal;
+	    }
+	}
+
+    dev->devEnabled = 1;
+    dev->devNum = cfg->devNum;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* sysEnable
+*
+* DESCRIPTION:
+*       This function enables the system for full operation.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       1.  This function should be called only after successful execution of
+*           qdLoadDriver().
+*
+*******************************************************************************/
+GT_STATUS sysEnable( GT_QD_DEV *dev)
+{
+    DBG_INFO(("sysEnable Called.\n"));
+    DBG_INFO(("OK.\n"));
+    return driverEnable(dev);
+}
+
+
+/*******************************************************************************
+* qdUnloadDriver
+*
+* DESCRIPTION:
+*       This function unloads the QuaterDeck Driver.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       1.  This function should be called only after successful execution of
+*           qdLoadDriver().
+*
+*******************************************************************************/
+GT_STATUS qdUnloadDriver
+(
+    IN GT_QD_DEV* dev
+)
+{
+    DBG_INFO(("qdUnloadDriver Called.\n"));
+
+    /* Delete the MultiAddress mode reagister access semaphore.    */
+    if(gtSemDelete(dev,dev->multiAddrSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+ 
+    /* Delete the ATU semaphore.    */
+    if(gtSemDelete(dev,dev->atuRegsSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+    /* Delete the VTU semaphore.    */
+    if(gtSemDelete(dev,dev->vtuRegsSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+    /* Delete the STATS semaphore.    */
+    if(gtSemDelete(dev,dev->statsRegsSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+    /* Delete the PIRL semaphore.    */
+    if(gtSemDelete(dev,dev->pirlRegsSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+    /* Delete the PTP semaphore.    */
+    if(gtSemDelete(dev,dev->ptpRegsSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+    /* Delete the Table semaphore.    */
+    if(gtSemDelete(dev,dev->tblRegsSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+    /* Delete the EEPROM Configuration semaphore.    */
+    if(gtSemDelete(dev,dev->eepromRegsSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+    /* Delete the PHY Device semaphore.    */
+    if(gtSemDelete(dev,dev->phyRegsSem) != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_FAIL;
+    }
+
+	gtMemSet(dev,0,sizeof(GT_QD_DEV));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gtRegister
+*
+* DESCRIPTION:
+*       BSP should register the following functions:
+*		1) MII Read - (Input, must provide)
+*			allows QuarterDeck driver to read QuarterDeck device registers.
+*		2) MII Write - (Input, must provice)
+*			allows QuarterDeck driver to write QuarterDeck device registers.
+*		3) Semaphore Create - (Input, optional)
+*			OS specific Semaphore Creat function.
+*		4) Semaphore Delete - (Input, optional)
+*			OS specific Semaphore Delete function.
+*		5) Semaphore Take - (Input, optional)
+*			OS specific Semaphore Take function.
+*		6) Semaphore Give - (Input, optional)
+*			OS specific Semaphore Give function.
+*		Notes: 3) ~ 6) should be provided all or should not be provided at all.
+*
+* INPUTS:
+*		pBSPFunctions - pointer to the structure for above functions.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_TRUE, if input is valid. GT_FALSE, otherwise.
+*
+* COMMENTS:
+*       This function should be called only once.
+*
+*******************************************************************************/
+static GT_BOOL gtRegister(GT_QD_DEV *dev, BSP_FUNCTIONS* pBSPFunctions)
+{
+	dev->fgtReadMii =  pBSPFunctions->readMii;
+	dev->fgtWriteMii = pBSPFunctions->writeMii;
+	
+	dev->semCreate = pBSPFunctions->semCreate;
+	dev->semDelete = pBSPFunctions->semDelete;
+	dev->semTake   = pBSPFunctions->semTake  ;
+	dev->semGive   = pBSPFunctions->semGive  ;
+	
+	return GT_TRUE;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysCtrl.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysCtrl.c
new file mode 100755
index 0000000..5ff8c21
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysCtrl.c
@@ -0,0 +1,7843 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtSysCtrl.c
+*
+* DESCRIPTION:
+*       API definitions for system global control.
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+#include <gtSem.h>
+
+static GT_STATUS writeSwitchMacReg
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_ETHERADDR *mac
+);
+
+static GT_STATUS readSwitchMacReg
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_ETHERADDR *mac
+);
+
+static GT_STATUS writeDiffMAC
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_U16		diffAddr
+);
+
+static GT_STATUS readDiffMAC
+(
+    IN  GT_QD_DEV	*dev,
+    OUT GT_U16		*diffAddr
+);
+
+
+/*******************************************************************************
+* gsysSwReset
+*
+* DESCRIPTION:
+*       This routine preforms switch software reset.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSwReset
+(
+    IN  GT_QD_DEV *dev
+)
+{
+    GT_U16          data;           /* Used to poll the SWReset bit */
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U8			regOffset;
+
+    DBG_INFO(("gsysSwReset Called.\n"));
+
+    /* Set the Software reset bit.                  */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		regOffset = QD_REG_GLOBAL_CONTROL;
+	}
+	else
+	{
+		regOffset = QD_REG_ATU_CONTROL;
+	}
+
+    retVal = hwSetGlobalRegField(dev,regOffset,15,1,1);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    /* Make sure the reset operation is completed.  */
+    data = 1;
+    while(data != 0)
+    {
+   	    retVal = hwGetGlobalRegField(dev,regOffset,15,1,&data);
+
+        if(retVal != GT_OK)
+        {
+            DBG_INFO(("Failed.\n"));
+            return retVal;
+        }
+    }
+	
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetPPUEn
+*
+* DESCRIPTION:
+*		This routine enables/disables Phy Polling Unit.
+*
+* INPUTS:
+*		en - GT_TRUE to enable PPU, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetPPUEn
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL 		en
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* Data to be set into the      */
+                                /* register.                    */
+	DBG_INFO(("gsysSetPPUEn Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PPU_READ_ONLY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	BOOL_2_BIT(en,data);
+
+	/* Set the PPUEn bit.                */
+	retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,14,1,data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+	
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetPPUEn
+*
+* DESCRIPTION:
+*		This routine get the PPU state.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if PPU is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_BAD_PARAM    - on bad parameter
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPPUEn
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* The register's read data.    */
+
+	DBG_INFO(("gsysGetPPUEn Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PPU_READ_ONLY))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(en == NULL)
+	{
+		DBG_INFO(("Failed.\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* Get the GetPPUEn bit.                */
+	retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,14,1,&data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	BIT_2_BOOL(data,*en);
+	DBG_INFO(("OK.\n"));
+
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetDiscardExcessive
+*
+* DESCRIPTION:
+*       This routine set the Discard Excessive state.
+*
+* INPUTS:
+*       en - GT_TRUE Discard is enabled, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetDiscardExcessive
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_BOOL en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetDiscardExcessive Called.\n"));
+    BOOL_2_BIT(en,data);
+
+    /* Set the Discard Exissive bit.                */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,13,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetDiscardExcessive
+*
+* DESCRIPTION:
+*       This routine get the Discard Excessive state.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE Discard is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetDiscardExcessive
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_BOOL    *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetDiscardExcessive Called.\n"));
+    if(en == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* Get the Discard Exissive bit.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,13,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysSetSchedulingMode
+*
+* DESCRIPTION:
+*       This routine set the Scheduling Mode.
+*
+* INPUTS:
+*       mode - GT_TRUE wrr, GT_FALSE strict.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetSchedulingMode
+(
+    IN  GT_QD_DEV *dev,
+    IN GT_BOOL    mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetSchedulingMode Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PORT_MIXED_SCHEDULE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(mode,data);
+    data = 1 - data;
+
+    /* Set the Schecduling bit.             */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,11,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetSchedulingMode
+*
+* DESCRIPTION:
+*       This routine get the Scheduling Mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE wrr, GT_FALSE strict.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetSchedulingMode
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetSchedulingMode Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev, DEV_PORT_MIXED_SCHEDULE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+    /* Get the Scheduling bit.              */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,11,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(1 - data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysSetMaxFrameSize
+*
+* DESCRIPTION:
+*       This routine Set the max frame size allowed.
+*
+* INPUTS:
+*       mode - GT_TRUE max size 1522, 
+*			   GT_FALSE max size 1535, 1632, or 2048.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Please refer to the device spec. to get the max frame size.
+*       88E6095 device supports upto 1632. 
+*       88E6065/88E6061 devices support upto 2048. 
+*
+*******************************************************************************/
+GT_STATUS gsysSetMaxFrameSize
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetMaxFrameSize Called.\n"));
+
+	if (IS_IN_DEV_GROUP(dev,DEV_JUMBO_MODE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    BOOL_2_BIT(mode,data);
+    data = 1 - data;
+
+    /* Set the Max Fram Size bit.               */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,10,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetMaxFrameSize
+*
+* DESCRIPTION:
+*       This routine Get the max frame size allowed.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE max size 1522, 
+*			   GT_FALSE max size 1535, 1632, or 2048.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Please refer to the device spec. to get the max frame size.
+*       88E6095 device supports upto 1632.
+*       88E6065/88E6061 devices support upto 2048. 
+*
+*******************************************************************************/
+GT_STATUS gsysGetMaxFrameSize
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetMaxFrameSize Called.\n"));
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_JUMBO_MODE))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the Max Frame Size bit.          */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,10,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(1 - data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysReLoad
+*
+* DESCRIPTION:
+*       This routine cause to the switch to reload the EEPROM.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysReLoad
+(
+    IN  GT_QD_DEV *dev
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysReLoad Called.\n"));
+    /* Set the Reload bit.                  */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,9,1,1);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    /* Should a check for reload completion. */
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysSetWatchDog
+*
+* DESCRIPTION:
+*       This routine Set the the watch dog mode.
+*
+* INPUTS:
+*       en - GT_TRUE enables, GT_FALSE disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetWatchDog
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetWatchDog Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH|DEV_WATCHDOG_EVENT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the WatchDog bit.            */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,7,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetWatchDog
+*
+* DESCRIPTION:
+*       This routine Get the the watch dog mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE enables, GT_FALSE disable.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetWatchDog
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetWatchDog Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    if(en == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* Get the WatchDog bit.            */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,7,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetDuplexPauseMac
+*
+* DESCRIPTION:
+*       This routine sets the full duplex pause src Mac Address.
+*		MAC address should be an Unicast address.
+*		For different MAC Addresses per port operation, 
+*		use gsysSetPerPortDuplexPauseMac API.
+*
+* INPUTS:
+*       mac - The Mac address to be set.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetDuplexPauseMac
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_ETHERADDR *mac
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetDuplexPauseMac Called.\n"));
+    if(mac == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	/* if the device has Switch MAC Register, we need the special operation */
+	if (IS_IN_DEV_GROUP(dev,DEV_SWITCH_MAC_REG))
+    {
+		return writeSwitchMacReg(dev,mac);
+    }
+
+    /* Set the first Mac register with diffAddr bit reset.  */
+    data = (((*mac).arEther[0] & 0xFE) << 8) | (*mac).arEther[1];
+    retVal = hwWriteGlobalReg(dev,QD_REG_MACADDR_01,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    /* Set the Mac23 address register.   */
+    data = ((*mac).arEther[2] << 8) | (*mac).arEther[3];
+    retVal = hwWriteGlobalReg(dev,QD_REG_MACADDR_23,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    /* Set the Mac45 address register.   */
+    data = ((*mac).arEther[4] << 8) | (*mac).arEther[5];
+    retVal = hwWriteGlobalReg(dev,QD_REG_MACADDR_45,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetDuplexPauseMac
+*
+* DESCRIPTION:
+*       This routine Gets the full duplex pause src Mac Address.
+*		For different MAC Addresses per port operation, 
+*		use gsysGetPerPortDuplexPauseMac API.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mac - the Mac address.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetDuplexPauseMac
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_ETHERADDR *mac
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to read from register.  */
+
+    DBG_INFO(("gsysGetDuplexPauseMac Called.\n"));
+    if(mac == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	/* if the device has Switch MAC Register, we need the special operation */
+	if (IS_IN_DEV_GROUP(dev,DEV_SWITCH_MAC_REG))
+    {
+		return readSwitchMacReg(dev,mac);
+    }
+
+    /* Get the Mac01 register.      */
+    retVal = hwReadGlobalReg(dev,QD_REG_MACADDR_01,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+#if 0	/* This should be always a unicast. */
+    /* The mac is allwasy a multicast mac   */
+    (*mac).arEther[0] = (data >> 8) | 0x01;
+    (*mac).arEther[1] = data & 0xFF;
+#else
+    (*mac).arEther[0] = (data >> 8) & ~0x01;
+    (*mac).arEther[1] = data & 0xFF;
+#endif
+    /* Get the Mac23 register.      */
+    retVal = hwReadGlobalReg(dev,QD_REG_MACADDR_23,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    (*mac).arEther[2] = data >> 8;
+    (*mac).arEther[3] = data & 0xFF;
+
+    /* Get the Mac45 register.      */
+    retVal = hwReadGlobalReg(dev,QD_REG_MACADDR_45,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    (*mac).arEther[4] = data >> 8;
+    (*mac).arEther[5] = data & 0xFF;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysSetPerPortDuplexPauseMac
+*
+* DESCRIPTION:
+*       This routine sets whether the full duplex pause src Mac Address is per
+*       port or per device.
+*
+* INPUTS:
+*       en - GT_TURE per port mac, GT_FALSE global mac.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetPerPortDuplexPauseMac
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_BOOL      en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetPerPortDuplexPauseMac Called.\n"));
+    BOOL_2_BIT(en,data);
+
+	/* if the device has Switch MAC Register, we need the special operation */
+	if (IS_IN_DEV_GROUP(dev,DEV_SWITCH_MAC_REG))
+    {
+		retVal = writeDiffMAC(dev,data);
+    }
+	else
+	{
+    	retVal = hwSetGlobalRegField(dev,QD_REG_MACADDR_01,8,1,data);
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetPerPortDuplexPauseMac
+*
+* DESCRIPTION:
+*       This routine Gets whether the full duplex pause src Mac Address is per
+*       port or per device.
+*
+* INPUTS:
+*       en - GT_TURE per port mac, GT_FALSE global mac.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPerPortDuplexPauseMac
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_BOOL      *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetPerPortDuplexPauseMac Called.\n"));
+    if(en == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	/* if the device has Switch MAC Register, we need the special operation */
+	if (IS_IN_DEV_GROUP(dev,DEV_SWITCH_MAC_REG))
+    {
+		retVal = readDiffMAC(dev,&data);
+    }
+	else
+	{
+	    retVal = hwGetGlobalRegField(dev,QD_REG_MACADDR_01,8,1,&data);
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysReadMiiReg
+*
+* DESCRIPTION:
+*       This routine reads QuarterDeck Registers. Since this routine is only for
+*		Diagnostic Purpose, no error checking will be performed.
+*		User has to know which phy address(0 ~ 0x1F) will be read.		
+*
+* INPUTS:
+*       phyAddr - Phy Address to read the register for.( 0 ~ 0x1F )
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysReadMiiReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U32	     phyAddr,
+    IN  GT_U32	     regAddr,
+    OUT GT_U32	     *data
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          u16Data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysReadMiiRegister Called.\n"));
+
+    /* Get the register data */
+    retVal = hwReadMiiReg(dev,(GT_U8)phyAddr,(GT_U8)regAddr,&u16Data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	*data = (GT_U32)u16Data;
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysWriteMiiReg
+*
+* DESCRIPTION:
+*       This routine writes QuarterDeck Registers. Since this routine is only for
+*		Diagnostic Purpose, no error checking will be performed.
+*		User has to know which phy address(0 ~ 0x1F) will be read.		
+*
+* INPUTS:
+*       phyAddr - Phy Address to read the register for.( 0 ~ 0x1F )
+*       regAddr - The register's address.
+*
+* OUTPUTS:
+*       data    - The read register's data.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysWriteMiiReg
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U32	     phyAddr,
+    IN  GT_U32	     regAddr,
+    IN  GT_U16	     data
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    
+    DBG_INFO(("gsysWriteMiiRegister Called.\n"));
+
+    /* Set the register data */
+    retVal = hwWriteMiiReg(dev,(GT_U8)phyAddr,(GT_U8)regAddr,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRetransmitMode
+*
+* DESCRIPTION:
+*       This routine set the Retransmit Mode.
+*
+* INPUTS:
+*       en - GT_TRUE Retransimt Mode is enabled, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetRetransmitMode
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_BOOL      en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetRetransmitMode Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+    BOOL_2_BIT(en,data);
+
+    /* Set the Retransmit Mode bit.                */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,15,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetRetransmitMode
+*
+* DESCRIPTION:
+*       This routine get the Retransmit Mode.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE Retransmit Mode is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetRetransmitMode
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_BOOL      *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetRetransmitMode Called.\n"));
+    if(en == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+	/* Only Gigabit Switch supports this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+    /* Get the bit.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,15,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetLimitBackoff
+*
+* DESCRIPTION:
+*       This routine set the Limit Backoff bit.
+*
+* INPUTS:
+*       en - GT_TRUE:  uses QoS half duplex backoff operation  
+*            GT_FALSE: uses normal half duplex backoff operation
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetLimitBackoff
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_BOOL      en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetLimitBackoff Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+    BOOL_2_BIT(en,data);
+
+    /* Set the bit.                */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,14,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetLimitBackoff
+*
+* DESCRIPTION:
+*       This routine set the Limit Backoff bit.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE:  uses QoS half duplex backoff operation  
+*            GT_FALSE: uses normal half duplex backoff operation
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetLimitBackoff
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_BOOL      *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetLimitBackoff Called.\n"));
+    if(en == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+	/* Only Gigabit Switch supports this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the bit.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,14,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRsvReqPri
+*
+* DESCRIPTION:
+*       This routine set the Reserved Queue's Requesting Priority 
+*
+* INPUTS:
+*       en - GT_TRUE: use the last received frome's priority
+*            GT_FALSE:use the last switched frame's priority 
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetRsvReqPri
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_BOOL      en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetRsvReqPri Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+    BOOL_2_BIT(en,data);
+
+    /* Set the bit.                */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,12,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetRsvReqPri
+*
+* DESCRIPTION:
+*       This routine get the Reserved Queue's Requesting Priority 
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE: use the last received frome's priority
+*            GT_FALSE:use the last switched frame's priority 
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetRsvReqPri
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_BOOL      *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetRsvReqPri Called.\n"));
+    if(en == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+	/* Only Gigabit Switch supports this status. */
+	if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* Get the bit.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,12,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetCascadePort
+*
+* DESCRIPTION:
+*		This routine sets Cascade Port number.
+*		In multichip systems frames coming from a CPU need to know when they
+*		have reached their destination chip.
+*
+*		Use Cascade Port = 0xE to indicate this chip has no Cascade port.
+*		Use Cascade Port = 0xF to use Routing table (gsysGetDevRoutingTable).
+*
+* INPUTS:
+*		port - Cascade Port
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetCascadePort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysSetCascadePort Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CASCADE_PORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+	if((port == 0xE) || (port == 0xF))
+		data = (GT_U16)port;
+	else
+	{
+	    data = (GT_U16)(GT_LPORT_2_PORT(port));
+		if (data == GT_INVALID_PORT)
+			return GT_BAD_PARAM;
+	}
+
+    /* Set the Cascade port.                */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,12,4,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetCascadePort
+*
+* DESCRIPTION:
+*		This routine gets Cascade Port number.
+*		In multichip systems frames coming from a CPU need to know when they
+*		have reached their destination chip.
+*
+*		Use Cascade Port = 0xE to indicate this chip has no Cascade port.
+*		Use Cascade Port = 0xF to use Routing table (gsysGetDevRoutingTable).
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port - Cascade Port
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetCascadePort
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT 	*port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysSetCascadePort Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CASCADE_PORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the Cascade port.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,12,4,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if((data == 0xE) || (data == 0xF))
+	{
+		*port = (GT_LPORT)data;
+	}
+	else
+	{
+	    *port = GT_PORT_2_LPORT((GT_U8)data);
+	}
+    
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetDeviceNumber
+*
+* DESCRIPTION:
+*		This routine sets Device Number.
+*		In multichip systems frames coming from a CPU need to know when they
+*		have reached their destination chip. From CPU frames whose Dev_Num
+*		fieldmatches these bits have reachedtheir destination chip and are sent
+*		out this chip using the port number indicated in the frame's Trg_Port 
+*		field.
+*
+* INPUTS:
+*		devNum - Device Number (0 ~ 31)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetDeviceNumber
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		devNum
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysSetDeviceNumber Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    data = ((GT_U16)devNum) & 0x1F; /* only 5 bits are valid */
+
+    /* Set the Device Number.                */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,0,5,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetDeviceNumber
+*
+* DESCRIPTION:
+*		This routine gets Device Number.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		devNum - Device Number (0 ~ 31)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetDeviceNumber
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U32  	*devNum
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetDeviceNumber Called.\n"));
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the Device Number.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,0,5,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *devNum = (GT_U32)data;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetCoreTagType
+*
+* DESCRIPTION:
+*		This routine sets Ether Core Tag Type.
+*		This Ether Type is added to frames that egress the switch as Double Tagged 
+*		frames. It is also the Ether Type expected during Ingress to determine if 
+*		a frame is Tagged or not on ports configured as UseCoreTag mode.
+*
+* INPUTS:
+*		etherType - Core Tag Type (2 bytes)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetCoreTagType
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16  		etherType
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetCoreTagType Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CORE_TAG))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Set the Ether Type */
+    retVal = hwWriteGlobalReg(dev,QD_REG_CORETAG_TYPE,etherType);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetCoreTagType
+*
+* DESCRIPTION:
+*		This routine gets CoreTagType
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		etherType - Core Tag Type (2 bytes)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetCoreTagType
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*etherType
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetCoreTagType Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CORE_TAG))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the Device Number.                */
+    retVal = hwReadGlobalReg(dev,QD_REG_CORETAG_TYPE,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *etherType = data;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetIngressMonitorDest
+*
+* DESCRIPTION:
+*		This routine sets Ingress Monitor Destination Port. Frames that are 
+*		targeted toward an Ingress Monitor Destination go out the port number 
+*		indicated in these bits. This includes frames received on a Marvell Tag port
+*		with the Ingress Monitor type, and frames received on a Network port that 
+*		is enabled to be the Ingress Monitor Source Port.
+*		If the Ingress Monitor Destination Port resides in this device these bits 
+*		should point to the Network port where these frames are to egress. If the 
+*		Ingress Monitor Destination Port resides in another device these bits 
+*		should point to the Marvell Tag port in this device that is used to get 
+*		to the device that contains the Ingress Monitor Destination Port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetIngressMonitorDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysSetIngressMonitorDest Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+	if(port == 0xF)
+		hwPort = (GT_U8)port;
+	else
+	{
+	    hwPort = (GT_U8)GT_LPORT_2_PORT(port);
+		if (hwPort == GT_INVALID_PORT)
+			return GT_BAD_PARAM;
+	}
+
+    /* Set the Ether Type */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 12, 4, (GT_U16)hwPort);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetIngressMonitorDest
+*
+* DESCRIPTION:
+*		This routine gets Ingress Monitor Destination Port.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetIngressMonitorDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetIngressMonitorDest Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the IngressMonitorDest. */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 12, 4, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if(data == 0xF)
+	{
+		*port = (GT_LPORT)data;
+	}
+	else
+	{
+	    *port = GT_PORT_2_LPORT((GT_U8)data);
+	}
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetEgressMonitorDest
+*
+* DESCRIPTION:
+*		This routine sets Egress Monitor Destination Port. Frames that are 
+*		targeted toward an Egress Monitor Destination go out the port number 
+*		indicated in these bits. This includes frames received on a Marvell Tag port
+*		with the Egress Monitor type, and frames transmitted on a Network port that 
+*		is enabled to be the Egress Monitor Source Port.
+*		If the Egress Monitor Destination Port resides in this device these bits 
+*		should point to the Network port where these frames are to egress. If the 
+*		Egress Monitor Destination Port resides in another device these bits 
+*		should point to the Marvell Tag port in this device that is used to get 
+*		to the device that contains the Egress Monitor Destination Port.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetEgressMonitorDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysSetEgressMonitorDest Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if(port == 0xF)
+		hwPort = (GT_U8)port;
+	else
+	{
+	    hwPort = (GT_U8)GT_LPORT_2_PORT(port);
+		if (hwPort == GT_INVALID_PORT)
+			return GT_BAD_PARAM;
+	}
+
+    /* Set EgressMonitorDest */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 8, 4, (GT_U16)hwPort);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetEgressMonitorDest
+*
+* DESCRIPTION:
+*		This routine gets Egress Monitor Destination Port.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetEgressMonitorDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetEgressMonitorDest Called.\n"));
+
+	/* Only Gigabit Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_88E6093_FAMILY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the EgressMonitorDest. */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 8, 4, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if(data == 0xF)
+	{
+		*port = (GT_LPORT)data;
+	}
+	else
+	{
+	    *port = GT_PORT_2_LPORT((GT_U8)data);
+	}
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetARPDest
+*
+* DESCRIPTION:
+*		This routine sets ARP Monitor Destination Port. Tagged or untagged 
+*		frames ingress Network ports that have the Broadcast Destination Address 
+*		with an Ethertype of 0x0806 are mirrored to this port. The ARPDest 
+*		should point to the port that directs these frames to the switch's CPU 
+*		that will process ARPs. This target port should be a Marvell Tag port so 
+*		that frames will egress with a To CPU Marvell Tag with a CPU Code of ARP.
+*		To CPU Marvell Tag frames with a CPU Code off ARP that ingress a Marvell 
+*		Tag port will be sent to the port number defineded in ARPDest.
+*
+*		If ARPDest =  0xF, ARP Monitoring is disabled and ingressing To CPU ARP 
+*		frames will be discarded.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetARPDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysSetARPDest Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ARP_DEST_SUPPORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+	if(port == 0xF)
+		hwPort = (GT_U8)port;
+	else
+	{
+	    hwPort = (GT_U8)(GT_LPORT_2_PORT(port));
+		if (hwPort == GT_INVALID_PORT)
+			return GT_BAD_PARAM;
+	}
+
+    /* Set related bit */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 4, 4, (GT_U16)hwPort);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetARPDest
+*
+* DESCRIPTION:
+*		This routine gets ARP Monitor Destination Port. Tagged or untagged 
+*		frames ingress Network ports that have the Broadcast Destination Address 
+*		with an Ethertype of 0x0806 are mirrored to this port. The ARPDest 
+*		should point to the port that directs these frames to the switch's CPU 
+*		that will process ARPs. This target port should be a Marvell Tag port so 
+*		that frames will egress with a To CPU Marvell Tag with a CPU Code of ARP.
+*		To CPU Marvell Tag frames with a CPU Code off ARP that ingress a Marvell 
+*		Tag port will be sent to the port number defineded in ARPDest.
+*
+*		If ARPDest =  0xF, ARP Monitoring is disabled and ingressing To CPU ARP 
+*		frames will be discarded.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetARPDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetARPDest Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ARP_DEST_SUPPORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 4, 4, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if(data == 0xF)
+	{
+		*port = (GT_LPORT)data;
+	}
+	else
+	{
+	    *port = GT_PORT_2_LPORT((GT_U8)data);
+	}
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRsvd2CpuEnables
+*
+* DESCRIPTION:
+*		Reserved DA Enables. When the Rsvd2Cpu(gsysSetRsvd2Cpu) is set to a one, 
+*		the 16 reserved multicast DA addresses, whose bit in this register are 
+*		also set to a one, are treadted as MGMT frames. All the reserved DA's 
+*		take the form 01:80:C2:00:00:0x. When x = 0x0, bit 0 of this register is 
+*		tested. When x = 0x2, bit 2 of this field is tested and so on.
+*		If the tested bit in this register is cleared to a zero, the frame will 
+*		be treated as a normal (non-MGMT) frame.
+*
+* INPUTS:
+*		enBits - bit vector of enabled Reserved Multicast.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetRsvd2CpuEnables
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		enBits
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetRsvd2CpuEnables Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Set related register */
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_MGMT_ENABLE, (GT_U16)enBits);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetRsvd2CpuEnables
+*
+* DESCRIPTION:
+*		Reserved DA Enables. When the Rsvd2Cpu(gsysSetRsvd2Cpu) is set to a one, 
+*		the 16 reserved multicast DA addresses, whose bit in this register are 
+*		also set to a one, are treadted as MGMT frames. All the reserved DA's 
+*		take the form 01:80:C2:00:00:0x. When x = 0x0, bit 0 of this register is 
+*		tested. When x = 0x2, bit 2 of this field is tested and so on.
+*		If the tested bit in this register is cleared to a zero, the frame will 
+*		be treated as a normal (non-MGMT) frame.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		enBits - bit vector of enabled Reserved Multicast.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetRsvd2CpuEnables
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*enBits
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysGetRsvd2CpuEnables Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related register */
+    retVal = hwReadGlobal2Reg(dev, QD_REG_MGMT_ENABLE, enBits);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRsvd2Cpu
+*
+* DESCRIPTION:
+*		When the Rsvd2Cpu is set to a one(GT_TRUE), frames with a Destination 
+*		Address in the range 01:80:C2:00:00:0x, regardless of their VLAN 
+*		membership, will be considered MGMT frames and sent to the CPU Port.
+*		If device supports Rsvd2CpuEnable (gsysSetRsvd2CpuEnable function),
+*		the frame will be considered MGMT frame when the associated Rsvd2CpuEnable
+*		bit for the frames's DA is also set to a one.
+*
+* INPUTS:
+*		en - GT_TRUE if Rsvd2Cpu is set. GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetRsvd2Cpu
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetRsvd2Cpu Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST|DEV_MULTICAST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+	if (IS_IN_DEV_GROUP(dev,DEV_MULTICAST))
+	{
+	    retVal = hwSetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,3,1, data);
+	}
+	else
+	{
+	    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 3, 1, data);
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetRsvd2Cpu
+*
+* DESCRIPTION:
+*		When the Rsvd2Cpu is set to a one(GT_TRUE), frames with a Destination 
+*		Address in the range 01:80:C2:00:00:0x, regardless of their VLAN 
+*		membership, will be considered MGMT frames and sent to the CPU Port.
+*		If device supports Rsvd2CpuEnable (gsysSetRsvd2CpuEnable function),
+*		the frame will be considered MGMT frame when the associated Rsvd2CpuEnable
+*		bit for the frames's DA is also set to a one.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Rsvd2Cpu is set. GT_FALSE, otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetRsvd2Cpu
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetRsvd2Cpu Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST|DEV_MULTICAST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+	if (IS_IN_DEV_GROUP(dev,DEV_MULTICAST))
+	{
+	    retVal = hwGetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,3,1,&data);
+	}
+	else
+	{
+	    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,3,1,&data);
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetMGMTPri
+*
+* DESCRIPTION:
+*		These bits are used as the PRI[2:0] bits on Rsvd2CPU frames.
+*
+* INPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - If pri is not less than 8.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetMGMTPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetMGMTPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (pri > 0x7)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 0, 3, pri);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetMGMTPri
+*
+* DESCRIPTION:
+*		These bits are used as the PRI[2:0] bits on Rsvd2CPU frames.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetMGMTPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    DBG_INFO(("gsysGetMGMTPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,0,3,pri);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetUseDoubleTagData
+*
+* DESCRIPTION:
+*		This bit is used to determine if Double Tag data that is removed from a 
+*		Double Tag frame is used or ignored when making switching decisions on 
+*		the frame.
+*
+* INPUTS:
+*		en - GT_TRUE to use removed tag data, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetUseDoubleTagData
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetUseDoubleTagData Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_LOOP_BLOCK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 15, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetUseDoubleTagData
+*
+* DESCRIPTION:
+*		This bit is used to determine if Double Tag data that is removed from a 
+*		Double Tag frame is used or ignored when making switching decisions on 
+*		the frame.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if removed tag data is used, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetUseDoubleTagData
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetUseDoubleTagData Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_LOOP_BLOCK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,15,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetPreventLoops
+*
+* DESCRIPTION:
+*		When a Marvell Tag port receives a Forward Marvell Tag whose Src_Dev 
+*		field equals this device's Device Number, the following action will be 
+*		taken depending upon the value of this bit.
+*		GT_TRUE (1) - The frame will be discarded.
+*		GT_FALSE(0) - The frame will be prevented from going out its original 
+*						source port as defined by the frame's Src_Port field.
+*
+* INPUTS:
+*		en - GT_TRUE to discard the frame as described above, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetPreventLoops
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetPreventLoops Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_LOOP_BLOCK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 14, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetPreventLoops
+*
+* DESCRIPTION:
+*		When a Marvell Tag port receives a Forward Marvell Tag whose Src_Dev 
+*		field equals this device's Device Number, the following action will be 
+*		taken depending upon the value of this bit.
+*		GT_TRUE (1) - The frame will be discarded.
+*		GT_FALSE(0) - The frame will be prevented from going out its original 
+*						source port as defined by the frame's Src_Port field.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to discard the frame as described above, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPreventLoops
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetPreventLoops Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_LOOP_BLOCK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,14,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetFlowControlMessage
+*
+* DESCRIPTION:
+*		When this bit is set to one, Marvell Tag Flow Control messages will be 
+*		generated when an output queue becomes congested and received Marvell Tag 
+*		Flow Control messages will pause MACs inside this device. When this bit 
+*		is cleared to a zero Marvell Tag Flow Control messages will not be 
+*		generated and any received will be ignored at the target MAC.
+*
+* INPUTS:
+*		en - GT_TRUE to use Marvell Tag Flow Control message, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetFlowControlMessage
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetFlowControlMessage Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_FLOW_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 13, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetFlowControlMessage
+*
+* DESCRIPTION:
+*		When this bit is set to one, Marvell Tag Flow Control messages will be 
+*		generated when an output queue becomes congested and received Marvell Tag 
+*		Flow Control messages will pause MACs inside this device. When this bit 
+*		is cleared to a zero Marvell Tag Flow Control messages will not be 
+*		generated and any received will be ignored at the target MAC.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use Marvell Tag Flow Control message, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetFlowControlMessage
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetFlowControlMessage Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_FLOW_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,13,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetForceFlowControlPri
+*
+* DESCRIPTION:
+*		When this bit is set to a one the PRI[2:0] bits of generated Marvell Tag 
+*		Flow Control frames will be set to the value of the FC Pri bits (set by 
+*		gsysSetFCPri function call). When this bit is cleared to a zero generated 
+*		Marvell Tag Flow Control frames will retain the PRI[2:0] bits from the 
+*		frames that caused the congestion. This bit will have no effect if the 
+*		FlowControlMessage bit(gsysSetFlowControlMessage function call) is 
+*		cleared to a zero.
+*
+* INPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetForceFlowControlPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetForceFlowControlPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_FLOW_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 7, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetForceFlowControlPri
+*
+* DESCRIPTION:
+*		When this bit is set to a one the PRI[2:0] bits of generated Marvell Tag 
+*		Flow Control frames will be set to the value of the FC Pri bits (set by 
+*		gsysSetFCPri function call). When this bit is cleared to a zero generated 
+*		Marvell Tag Flow Control frames will retain the PRI[2:0] bits from the 
+*		frames that caused the congestion. This bit will have no effect if the 
+*		FlowControlMessage bit(gsysSetFlowControlMessage function call) is 
+*		cleared to a zero.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetForceFlowControlPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetForceFlowControlPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_FLOW_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,7,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetFCPri
+*
+* DESCRIPTION:
+*		These bits are used as the PRI[2:0] bits on generated Marvell Tag Flow 
+*		Control frames if the ForceFlowControlPri bit(gsysSetForceFlowControlPri)
+*		is set to a one.
+*
+* INPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - If pri is not less than 8.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetFCPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetFCPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_FLOW_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (pri > 0x7)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 4, 3, pri);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetFCPri
+*
+* DESCRIPTION:
+*		These bits are used as the PRI[2:0] bits on generated Marvell Tag Flow 
+*		Control frames if the ForceFlowControlPri bit(gsysSetForceFlowControlPri)
+*		is set to a one.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetFCPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    DBG_INFO(("gsysGetFCPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MARVELL_TAG_FLOW_CTRL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,4,3,pri);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetFlowCtrlDelay
+*
+* DESCRIPTION:
+*		This function sets Flow control delay time for 10Mbps, 100Mbps, and 
+*		1000Mbps. 
+*
+* INPUTS:
+*		sp - PORT_SPEED_10_MBPS, PORT_SPEED_100_MBPS, or PORT_SPEED_1000_MBPS
+*		delayTime - delay time.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if sp is not valid or delayTime is > 0x1FFF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*	Actual delay time will be delayTime x 2.048uS (or x 8.192uS) depending on 
+*	switch device. Please refer to the device datasheet for detailed information.
+*
+*******************************************************************************/
+GT_STATUS gsysSetFlowCtrlDelay
+(
+	IN GT_QD_DEV			*dev,
+	IN GT_PORT_SPEED_MODE	sp,
+	IN GT_U32				delayTime
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetFlowCtrlDelay Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FLOW_CTRL_DELAY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Check if the register can be accessed. */
+	do
+	{
+	    retVal = hwReadGlobal2Reg(dev,QD_REG_FLOWCTRL_DELAY,&data);
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+        	return retVal;
+	    }
+	} while (data & 0x8000);
+
+	switch(sp)
+	{
+		case PORT_SPEED_10_MBPS:
+				data = 0;
+				break;
+		case PORT_SPEED_100_MBPS:
+				data = 1 << 13;
+				break;
+		case PORT_SPEED_1000_MBPS:
+				data = 2 << 13;
+				break;
+		default:
+		        DBG_INFO(("GT_BAD_PARAM (sp)\n"));
+				gtSemGive(dev,dev->tblRegsSem);
+				return GT_BAD_PARAM;
+	}
+
+	if (delayTime > 0x1FFF)
+	{
+		DBG_INFO(("GT_BAD_PARAM (delayTime)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	data |= (GT_U16)(0x8000 | delayTime);
+
+    /* Set related register */
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_FLOWCTRL_DELAY,data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetFlowCtrlDelay
+*
+* DESCRIPTION:
+*		This function retrieves Flow control delay time for 10Mbps, 100Mbps, and
+*		1000Mbps. 
+*
+* INPUTS:
+*		sp - PORT_SPEED_10_MBPS, PORT_SPEED_100_MBPS, or PORT_SPEED_1000_MBPS
+*
+* OUTPUTS:
+*		delayTime - delay time
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if sp is not valid or delayTime is > 0x1FFF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*	Actual delay time will be delayTime x 2.048uS (or x 8.192uS) depending on 
+*	switch device. Please refer to the device datasheet for detailed information.
+*
+*******************************************************************************/
+GT_STATUS gsysGetFlowCtrlDelay
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_PORT_SPEED_MODE	sp,
+	OUT GT_U32		*delayTime
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetFlowCtrlDelay Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FLOW_CTRL_DELAY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Check if the register can be accessed. */
+	do
+	{
+	    retVal = hwReadGlobal2Reg(dev,QD_REG_FLOWCTRL_DELAY,&data);
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+        	return retVal;
+	    }
+	} while (data & 0x8000);
+
+	switch(sp)
+	{
+		case PORT_SPEED_10_MBPS:
+				data = 0;
+				break;
+		case PORT_SPEED_100_MBPS:
+				data = 1 << 13;
+				break;
+		case PORT_SPEED_1000_MBPS:
+				data = 2 << 13;
+				break;
+		default:
+		        DBG_INFO(("GT_BAD_PARAM (sp)\n"));
+				gtSemGive(dev,dev->tblRegsSem);
+				return GT_BAD_PARAM;
+	}
+
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_FLOWCTRL_DELAY,data);
+   	if(retVal != GT_OK)
+    {
+   	    DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+       	return retVal;
+    }
+
+    retVal = hwReadGlobal2Reg(dev,QD_REG_FLOWCTRL_DELAY,&data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+   	if(retVal != GT_OK)
+    {
+   	    DBG_INFO(("Failed.\n"));
+       	return retVal;
+    }
+
+	*delayTime = (GT_U32)(data & 0x1FFF);
+		
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetDevRoutingTable
+*
+* DESCRIPTION:
+*		This function sets Device to Port mapping (which device is connected to 
+*		which port of this device). 
+*
+* INPUTS:
+*		devNum - target device number.
+*		portNum - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if sp is not valid or delayTime is > 0x1FFF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetDevRoutingTable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		devNum,
+	IN GT_LPORT 	port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysSetDevRoutingTable Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_STACKING))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	if(devNum > 0x1F)
+	{
+		DBG_INFO(("GT_BAD_PARAM (devNum)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	/* Check if the register can be accessed. */
+	do
+	{
+	    retVal = hwReadGlobal2Reg(dev,QD_REG_ROUTING_TBL,&data);
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+        	return retVal;
+	    }
+	} while (data & 0x8000);
+
+    /* translate LPORT to hardware port */
+	if(port >= dev->numOfPorts)
+	{
+		hwPort = 0xF;
+	}
+	else
+	{
+	    hwPort = GT_LPORT_2_PORT(port);
+	}
+
+	data = (GT_U16)(0x8000 | (devNum << 8) | hwPort);
+
+    /* Set related register */
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_ROUTING_TBL,data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetDevRoutingTable
+*
+* DESCRIPTION:
+*		This function gets Device to Port mapping (which device is connected to 
+*		which port of this device). 
+*
+* INPUTS:
+*		devNum - target device number.
+*
+* OUTPUTS:
+*		portNum - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if sp is not valid or delayTime is > 0x1FFF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetDevRoutingTable
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32 		devNum,
+	OUT GT_LPORT 	*port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetDevRoutingTable Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_STACKING))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	if(devNum > 0x1F)
+	{
+		DBG_INFO(("GT_BAD_PARAM (devNum)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	/* Check if the register can be accessed. */
+	do
+	{
+	    retVal = hwReadGlobal2Reg(dev,QD_REG_ROUTING_TBL,&data);
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+        	return retVal;
+	    }
+	} while (data & 0x8000);
+
+	data = (GT_U16)(devNum << 8);
+
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_ROUTING_TBL,data);
+   	if(retVal != GT_OK)
+    {
+   	    DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+       	return retVal;
+    }
+
+    retVal = hwReadGlobal2Reg(dev,QD_REG_ROUTING_TBL,&data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+   	if(retVal != GT_OK)
+    {
+   	    DBG_INFO(("Failed.\n"));
+       	return retVal;
+    }
+
+	*port = GT_PORT_2_LPORT((GT_U8)(data & 0xF));
+	if(*port == GT_INVALID_PORT)
+	{
+		*port = 0xF;
+	}	
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetTrunkMaskTable
+*
+* DESCRIPTION:
+*		This function sets Trunk Mask for the given Trunk Number.
+*
+* INPUTS:
+*		trunkNum - Trunk Number.
+*		trunkMask - Trunk mask bits. Bit 0 controls trunk masking for port 0,
+*					bit 1 for port 1 , etc.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkNum > 0x7 for 88E6095 and 88E6183 family and
+*					   if trunkNum > 0x3 for 88E6065 family.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetTrunkMaskTable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		trunkNum,
+	IN GT_U32		trunkMask
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+	GT_U32			mask;
+
+    DBG_INFO(("gsysSetTrunkMaskTable Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK|DEV_REDUCED_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Check if the register can be accessed. */
+	do
+	{
+	    retVal = hwReadGlobal2Reg(dev,QD_REG_TRUNK_MASK_TBL,&data);
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+        	return retVal;
+	    }
+	} while (data & 0x8000);
+
+	data &= 0x0800;
+
+	if(trunkNum > 0x7)
+	{
+		DBG_INFO(("GT_BAD_PARAM (trunkNum)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	if((trunkNum > 0x3) && IS_IN_DEV_GROUP(dev,DEV_REDUCED_TRUNK))
+	{
+		DBG_INFO(("GT_BAD_PARAM (trunkNum)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	mask = (1 << dev->numOfPorts) - 1;
+
+	if(trunkMask > mask)
+	{
+		DBG_INFO(("GT_BAD_PARAM (trunkMask)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	mask = GT_LPORTVEC_2_PORTVEC(trunkMask);
+
+	data = (GT_U16)(0x8000 | data | (trunkNum << 12) | mask);
+
+    /* Set related register */
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_TRUNK_MASK_TBL,data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetTrunkMaskTable
+*
+* DESCRIPTION:
+*		This function gets Trunk Mask for the given Trunk Number.
+*
+* INPUTS:
+*		trunkNum - Trunk Number.
+*
+* OUTPUTS:
+*		trunkMask - Trunk mask bits. Bit 0 controls trunk masking for port 0,
+*					bit 1 for port 1 , etc.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkNum > 0x7 for 88E6095 and 88E6183 family and
+*					   if trunkNum > 0x3 for 88E6065 family.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetTrunkMaskTable
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32 		trunkNum,
+	OUT GT_U32		*trunkMask
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+	GT_U32			mask;
+
+    DBG_INFO(("gsysGetTrunkMaskTable Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK|DEV_REDUCED_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Check if the register can be accessed. */
+	do
+	{
+	    retVal = hwReadGlobal2Reg(dev,QD_REG_TRUNK_MASK_TBL,&data);
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+        	return retVal;
+	    }
+	} while (data & 0x8000);
+
+	data &= 0x0800;
+
+	if(trunkNum > 0x7)
+	{
+		DBG_INFO(("GT_BAD_PARAM (trunkId)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	if((trunkNum > 0x3) && IS_IN_DEV_GROUP(dev,DEV_REDUCED_TRUNK))
+	{
+		DBG_INFO(("GT_BAD_PARAM (trunkNum)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	data = (GT_U16)(data | (trunkNum << 12));
+
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_TRUNK_MASK_TBL,data);
+   	if(retVal != GT_OK)
+    {
+   	    DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+       	return retVal;
+    }
+
+    retVal = hwReadGlobal2Reg(dev,QD_REG_TRUNK_MASK_TBL,&data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+   	if(retVal != GT_OK)
+    {
+   	    DBG_INFO(("Failed.\n"));
+       	return retVal;
+    }
+
+	mask = (1 << dev->maxPorts) - 1;
+
+	*trunkMask = GT_PORTVEC_2_LPORTVEC(data & mask);
+			
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetHashTrunk
+*
+* DESCRIPTION:
+*		Hash DA & SA for TrunkMask selection. Trunk load balancing is accomplished 
+*		by using the frame's DA and SA fields to access one of eight Trunk Masks. 
+*		When this bit is set to a one the hashed computed for address table 
+*		lookups is used for the TrunkMask selection. When this bit is cleared to 
+*		a zero the lower 3 bits of the frame's DA and SA are XOR'ed together to 
+*		select the TrunkMask to use.
+*
+* INPUTS:
+*		en - GT_TRUE to use lookup table, GT_FALSE to use XOR.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetHashTrunk
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetHashTrunk Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK|DEV_REDUCED_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_TRUNK_MASK_TBL, 11, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetHashTrunk
+*
+* DESCRIPTION:
+*		Hash DA & SA for TrunkMask selection. Trunk load balancing is accomplished 
+*		by using the frame's DA and SA fields to access one of eight Trunk Masks. 
+*		When this bit is set to a one the hashed computed for address table 
+*		lookups is used for the TrunkMask selection. When this bit is cleared to 
+*		a zero the lower 3 bits of the frame's DA and SA are XOR'ed together to 
+*		select the TrunkMask to use.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use lookup table, GT_FALSE to use XOR.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetHashTrunk
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetHashTrunk Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK|DEV_REDUCED_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_TRUNK_MASK_TBL,11,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetTrunkRouting
+*
+* DESCRIPTION:
+*		This function sets routing information for the given Trunk ID.
+*
+* INPUTS:
+*		trunkId - Trunk ID.
+*		trunkRoute - Trunk route bits. Bit 0 controls trunk routing for port 0,
+*					bit 1 for port 1 , etc.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkId > 0xF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysSetTrunkRouting
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		trunkId,
+	IN GT_U32		trunkRoute
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+	GT_U32			mask;
+	GT_U32			maxTrunk;
+
+    DBG_INFO(("gsysSetTrunkRouting Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Check if the register can be accessed. */
+	do
+	{
+	    retVal = hwReadGlobal2Reg(dev,QD_REG_TRUNK_ROUTING,&data);
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+        	return retVal;
+	    }
+	} while (data & 0x8000);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_8_TRUNKING))
+		maxTrunk = 8;
+	else
+		maxTrunk = 16;
+
+	if(trunkId >= maxTrunk)
+	{
+		DBG_INFO(("GT_BAD_PARAM (trunkId)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	mask = (1 << dev->numOfPorts) - 1;
+
+	if(trunkRoute > mask)
+	{
+		DBG_INFO(("GT_BAD_PARAM (trunkRoute)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	mask = GT_LPORTVEC_2_PORTVEC(trunkRoute);
+
+	data = (GT_U16)(0x8000 | (trunkId << 11) | mask);
+
+    /* Set related register */
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_TRUNK_ROUTING,data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetTrunkRouting
+*
+* DESCRIPTION:
+*		This function retrieves routing information for the given Trunk ID.
+*
+* INPUTS:
+*		trunkId - Trunk ID.
+*
+* OUTPUTS:
+*		trunkRoute - Trunk route bits. Bit 0 controls trunk routing for port 0,
+*					bit 1 for port 1 , etc.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if trunkId > 0xF.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetTrunkRouting
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32 		trunkId,
+	OUT GT_U32		*trunkRoute
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+	GT_U32			mask;
+	GT_U32			maxTrunk;
+
+    DBG_INFO(("gsysGetTrunkRouting Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TRUNK))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Check if the register can be accessed. */
+	do
+	{
+	    retVal = hwReadGlobal2Reg(dev,QD_REG_TRUNK_ROUTING,&data);
+    	if(retVal != GT_OK)
+	    {
+    	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+        	return retVal;
+	    }
+	} while (data & 0x8000);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_8_TRUNKING))
+		maxTrunk = 8;
+	else
+		maxTrunk = 16;
+
+	if(trunkId >= maxTrunk)
+	{
+		DBG_INFO(("GT_BAD_PARAM (trunkId)\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+		return GT_BAD_PARAM;
+	}
+
+	data = (GT_U16)(trunkId << 11);
+
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_TRUNK_ROUTING,data);
+   	if(retVal != GT_OK)
+    {
+   	    DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+       	return retVal;
+    }
+
+    retVal = hwReadGlobal2Reg(dev,QD_REG_TRUNK_ROUTING,&data);
+	gtSemGive(dev,dev->tblRegsSem);
+   	if(retVal != GT_OK)
+    {
+   	    DBG_INFO(("Failed.\n"));
+       	return retVal;
+    }
+
+	mask = (1 << dev->maxPorts) - 1;
+
+	*trunkRoute = GT_PORTVEC_2_LPORTVEC(data & mask);
+			
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRateLimitMode
+*
+* DESCRIPTION:
+*		Ingress Rate Limiting can be either Priority based or Burst Size based.
+*		This routine sets which mode to use.
+*
+* INPUTS:
+*		mode - either GT_RATE_PRI_BASE or GT_RATE_BURST_BASE
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if invalid mode is used.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRateLimitMode
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_INGRESS_RATE_MODE mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysSetRateLimitMode Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_2))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+	switch (mode)
+	{
+		case GT_RATE_PRI_BASE:
+			data = 0;
+			break;
+		case GT_RATE_BURST_BASE:
+			data = 1;
+			break;
+		default:
+	        DBG_INFO(("Not supported mode %i\n",mode));
+			return GT_BAD_PARAM;
+	}
+
+    hwPort = 7;
+
+    /* Set related bit */
+    retVal = hwSetPortRegField(dev,hwPort, 0x1A, 15, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetRateLimitMode
+*
+* DESCRIPTION:
+*		Ingress Rate Limiting can be either Priority based or Burst Size based.
+*		This routine gets which mode is being used.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - either GT_RATE_PRI_BASE or GT_RATE_BURST_BASE
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRateLimitMode
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_INGRESS_RATE_MODE *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysGetRateLimitMode Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_2))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+    hwPort = 7;
+	data = 0;
+
+    /* Get related bit */
+    retVal = hwGetPortRegField(dev,hwPort, 0x1A, 15, 1, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if (data == 0)
+		*mode = GT_RATE_PRI_BASE;
+	else
+		*mode = GT_RATE_BURST_BASE;
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetAgeInt
+*
+* DESCRIPTION:
+*		Enable/Disable Age Refresh Interrupt. If CPU Directed Learning is being
+*		used (gprtSetLockedPort), it may be desirable to know when an address is
+*		still being used before it totally ages out of the switch. This can be 
+*		accomplished by enabling Age Refresh Interrupt (or ATU Age Violation Int).
+*		An ATU Age Violation looks identical to and reported the same as an ATU 
+*		Miss Violation. The only difference is when this reported. Normal ATU Miss
+*		Violation only occur if a new SA arrives at a LockedPort. The Age version 
+*		of the ATU Miss Violation occurs if an SA arrives at a LockedPort, where
+*		the address is contained in the ATU's database, but where its EntryState 
+*		is less than 0x4 (i.e., it has aged more than 1/2 way).
+*		GT_ATU_PROB Interrupt should be enabled for this interrupt to occur.
+*		Refer to eventSetActive routine to enable GT_ATU_PROB.
+*
+*		If the device supports Refresh Locked feature (gprtSetRefreshLocked API),
+*		the feature must not be enabled for this Miss Violation to occur.
+*
+* INPUTS:
+*		en - GT_TRUE, to enable,
+*			 GT_FALSE, otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetAgeInt
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysSetAgeInt Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AGE_INTERRUPT))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_2))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+    BOOL_2_BIT(en, data);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_AGE_INT_GLOBAL2))
+	{
+	    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 10, 1, data);
+	}
+	else
+	{
+	    hwPort = 7;
+	    /* Set related bit */
+    	retVal = hwSetPortRegField(dev,hwPort, 0x1A, 14, 1, data);
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetAgeInt
+*
+* DESCRIPTION:
+*		Get state of Age Refresh Interrupt mode. If CPU Directed Learning is being
+*		used (gprtSetLockedPort), it may be desirable to know when an address is
+*		still being used before it totally ages out of the switch. This can be 
+*		accomplished by enabling Age Refresh Interrupt (or ATU Age Violation Int).
+*		An ATU Age Violation looks identical to and reported the same as an ATU 
+*		Miss Violation. The only difference is when this reported. Normal ATU Miss
+*		Violation only occur if a new SA arrives at a LockedPort. The Age version 
+*		of the ATU Miss Violation occurs if an SA arrives at a LockedPort, where
+*		the address is contained in the ATU's database, but where its EntryState 
+*		is less than 0x4 (i.e., it has aged more than 1/2 way).
+*		GT_ATU_PROB Interrupt should be enabled for this interrupt to occur.
+*		Refer to eventSetActive routine to enable GT_ATU_PROB.
+*
+*		If the device supports Refresh Locked feature (gprtSetRefreshLocked API),
+*		the feature must not be enabled for this Miss Violation to occur.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE, if enabled,
+*			 GT_FALSE, otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetAgeInt
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL		*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysGetAgeInt Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_AGE_INTERRUPT))
+	{
+		if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
+			((GT_DEVICE_REV)dev->revision < GT_REV_2))
+	    {
+    	    DBG_INFO(("GT_NOT_SUPPORTED\n"));
+			return GT_NOT_SUPPORTED;
+	    }
+	}
+
+	data = 0;
+
+	if (IS_IN_DEV_GROUP(dev,DEV_AGE_INT_GLOBAL2))
+	{
+	    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT, 10, 1, &data);
+	}
+	else
+	{
+ 	   hwPort = 7;
+    	/* Get related bit */
+	    retVal = hwGetPortRegField(dev,hwPort, 0x1A, 14, 1, &data);
+	}
+
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data, *en);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetForceSnoopPri
+*
+* DESCRIPTION:
+*		Force Snooping Priority. The priority on IGMP or MLD Snoop frames are
+*		set to the SnoopPri value (gsysSetSnoopPri API) when Force Snooping
+*       Priority is enabled. When it's disabled, the priority on these frames
+*		is not modified.
+*
+* INPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetForceSnoopPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetForceSnoopPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SNOOP_PRI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE, 7, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetForceSnoopPri
+*
+* DESCRIPTION:
+*		Force Snooping Priority. The priority on IGMP or MLD Snoop frames are
+*		set to the SnoopPri value (gsysSetSnoopPri API) when Force Snooping
+*       Priority is enabled. When it's disabled, the priority on these frames
+*		is not modified.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetForceSnoopPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetForceSnoopPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SNOOP_PRI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,7,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetSnoopPri
+*
+* DESCRIPTION:
+*		Snoop Priority. When ForceSnoopPri (gsysSetForceSnoopPri API) is enabled,
+*       this priority is used as the egressing frame's PRI[2:0] bits on generated
+*       Marvell Tag To_CPU Snoop frames and higher 2 bits of the priority are
+*       used as the internal Queue Priority to use on IGMP/MLD snoop frames.
+*
+* INPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - If pri is not less than 8.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetSnoopPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetSnoopPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SNOOP_PRI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (pri > 0x7)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE, 4, 3, pri);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetSnoopPri
+*
+* DESCRIPTION:
+*		Snoop Priority. When ForceSnoopPri (gsysSetForceSnoopPri API) is enabled,
+*       this priority is used as the egressing frame's PRI[2:0] bits on generated
+*       Marvell Tag To_CPU Snoop frames and higher 2 bits of the priority are
+*       used as the internal Queue Priority to use on IGMP/MLD snoop frames.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetSnoopPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    DBG_INFO(("gsysGetSnoopPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SNOOP_PRI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,4,3,pri);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetForceARPPri
+*
+* DESCRIPTION:
+*		Force ARP Priority. The priority on ARP frames are set to the ARPPri 
+*       value (gsysSetARPPri API) when Force ARP Priority is enabled. When it's 
+*       disabled, the priority on these frames is not modified.
+*
+* INPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetForceARPPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetForceARPPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ARP_PRI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE, 3, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetForceARPPri
+*
+* DESCRIPTION:
+*		Force ARP Priority. The priority on ARP frames are set to the ARPPri 
+*       value (gsysSetARPPri API) when Force ARP Priority is enabled. When it's 
+*       disabled, the priority on these frames is not modified.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE to use defined PRI bits, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetForceARPPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetForceARPPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ARP_PRI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,3,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetARPPri
+*
+* DESCRIPTION:
+*		ARP Priority. When ForceARPPri (gsysSetForceARPPri API) is enabled,
+*       this priority is used as the egressing frame's PRI[2:0] bits on generated
+*       Marvell Tag To_CPU ARP frames and higher 2 bits of the priority are
+*       used as the internal Queue Priority to use on ARP frames.
+*
+* INPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - If pri is not less than 8.
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetARPPri
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetARPPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ARP_PRI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (pri > 0x7)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE, 0, 3, pri);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetARPPri
+*
+* DESCRIPTION:
+*		ARP Priority. When ForceARPPri (gsysSetForceARPPri API) is enabled,
+*       this priority is used as the egressing frame's PRI[2:0] bits on generated
+*       Marvell Tag To_CPU ARP frames and higher 2 bits of the priority are
+*       used as the internal Queue Priority to use on ARP frames.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		pri - PRI[2:0] bits (should be less than 8)
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetARPPri
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*pri
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    DBG_INFO(("gsysGetARPPri Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ARP_PRI))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_PRIORITY_OVERRIDE,0,3,pri);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetUsePortSchedule
+*
+* DESCRIPTION:
+*       This routine sets per port scheduling mode
+*
+* INPUTS:
+*       en - GT_TRUE enables per port scheduling, 
+*			 GT_FALSE disable.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetUsePortSchedule
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetWatchDog Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PORT_SCHEDULE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the UsePortSchedule bit.            */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,12,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetUsePortSchedule
+*
+* DESCRIPTION:
+*       This routine gets per port scheduling mode
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE enables per port scheduling, 
+*			 GT_FALSE disable.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetUsePortSchedule
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* Data to be set into the      */
+                                    /* register.                    */
+    DBG_INFO(("gsysSetWatchDog Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_PORT_SCHEDULE))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the UsePortSchedule bit.            */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,12,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data, *en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetOldHader
+*
+* DESCRIPTION:
+*       This routine sets Egress Old Header.
+*		When this feature is enabled and frames are egressed with a Marvell Header, 
+*		the format of the Header is slightly modified to be backwards compatible 
+*		with previous devices that used the original Header. Specifically, bit 3
+*		of the Header's 2nd octet is cleared to a zero such that only FPri[2:1]
+*		is available in the Header.
+*
+* INPUTS:
+*       en - GT_TRUE to enable Old Header Mode,
+*			 GT_FALSE to disable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetOldHader
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetArpQPri Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_OLD_HEADER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the OldHader bit.            */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,5,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetOldHader
+*
+* DESCRIPTION:
+*       This routine gets Egress Old Header.
+*		When this feature is enabled and frames are egressed with a Marvell Header, 
+*		the format of the Header is slightly modified to be backwards compatible 
+*		with previous devices that used the original Header. Specifically, bit 3
+*		of the Header's 2nd octet is cleared to a zero such that only FPri[2:1]
+*		is available in the Header.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE to enable Old Header Mode,
+*			 GT_FALSE to disable
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetOldHader
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysGetArpQPri Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_OLD_HEADER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the OldHader bit.            */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,5,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data, *en);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRecursiveStrippingDisable
+*
+* DESCRIPTION:
+*       This routine determines if recursive tag stripping feature needs to be
+*		disabled.
+*
+* INPUTS:
+*       en - GT_TRUE to disable Recursive Tag Stripping,
+*			 GT_FALSE to enable
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRecursiveStrippingDisable
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_BOOL   en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetRecursiveStrippingDisable Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_RECURSIVE_TAG_STRIP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the RecursiveStrippingDisable bit.            */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,15,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetRecursiveStrippingDisable
+*
+* DESCRIPTION:
+*       This routine checks if recursive tag stripping feature is disabled.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE, if Recursive Tag Stripping is disabled,
+*			 GT_FALSE, otherwise
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRecursiveStrippingDisable
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_BOOL   *en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysGetRecursiveStrippingDisable Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_RECURSIVE_TAG_STRIP))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the RecursiveStrippingDisable bit.            */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,15,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data, *en);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetCPUPort
+*
+* DESCRIPTION:
+*       This routine sets CPU Port where Rsvd2Cpu frames and IGMP/MLD Snooped 
+*		frames are destined.
+*
+* INPUTS:
+*       cpuPort - CPU Port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetCPUPort
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT  cpuPort
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysSetCPUPort Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(cpuPort);
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_CPU_PORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (cpuPort >= dev->numOfPorts)
+	{
+		return GT_BAD_PARAM;
+	}
+
+    /* Set the CPU Port.            */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,0,3,(GT_U16)hwPort);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetCPUPort
+*
+* DESCRIPTION:
+*       This routine gets CPU Port where Rsvd2Cpu frames and IGMP/MLD Snooped 
+*		frames are destined.
+*
+* INPUTS:
+*       cpuPort - CPU Port
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetCPUPort
+(
+    IN  GT_QD_DEV *dev,
+    OUT GT_LPORT  *cpuPort
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysGetCPUPort Called.\n"));
+
+	if (!IS_IN_DEV_GROUP(dev,DEV_CPU_PORT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the CPU Port.            */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,0,3,&hwPort);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    /* translate hardware port to LPORT */
+    *cpuPort = (GT_LPORT)GT_PORT_2_LPORT((GT_U8)hwPort);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetCPUDest
+*
+* DESCRIPTION:
+*		This routine sets CPU Destination Port. CPU Destination port indicates the
+*		port number on this device where the CPU is connected (either directly or
+*		indirectly through another Marvell switch device).
+*
+*		Many modes of frame processing need to know where the CPU is located.
+*		These modes are:
+*		1. When IGMP/MLD frame is received and Snooping is enabled
+*		2. When the port is configured as a DSA port and it receives a To_CPU frame
+*		3. When a Rsvd2CPU frame enters the port
+*		4. When the port's SA Filtering mode is Drop to CPU
+*		5. When any of the port's Policy Options trap the frame to the CPU
+*		6. When the ingressing frame is an ARP and ARP mirroring is enabled in the
+*		   device
+*
+*		In all cases, except for ARP, the frames that meet the enabled criteria 
+*		are mapped to the CPU Destination port, overriding where the frame would 
+*		normally go. In the case of ARP, the frame will be mapped normally and it 
+*		will also get copied to this port.
+*		Frames that filtered or discarded will not be mapped to the CPU Destination 
+*		port with the exception of the Rsvd2CPU and DSA Tag cases.
+*
+*		If CPUDest = 0xF, the remapped frames will be discarded, no ARP mirroring 
+*		will occur and ingressing To_CPU frames will be discarded.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetCPUDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysSetCPUDest Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CPU_DEST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+	if(port == 0xF)
+		hwPort = (GT_U8)port;
+	else
+	{
+	    hwPort = (GT_U8)(GT_LPORT_2_PORT(port));
+		if (hwPort == GT_INVALID_PORT)
+			return GT_BAD_PARAM;
+	}
+
+    /* Set related bit */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 4, 4, (GT_U16)hwPort);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetCPUDest
+*
+* DESCRIPTION:
+*		This routine gets CPU Destination Port. CPU Destination port indicates the
+*		port number on this device where the CPU is connected (either directly or
+*		indirectly through another Marvell switch device).
+*
+*		Many modes of frame processing need to know where the CPU is located.
+*		These modes are:
+*		1. When IGMP/MLD frame is received and Snooping is enabled
+*		2. When the port is configured as a DSA port and it receives a To_CPU frame
+*		3. When a Rsvd2CPU frame enters the port
+*		4. When the port's SA Filtering mode is Drop to CPU
+*		5. When any of the port's Policy Options trap the frame to the CPU
+*		6. When the ingressing frame is an ARP and ARP mirroring is enabled in the
+*		   device
+*
+*		In all cases, except for ARP, the frames that meet the enabled criteria 
+*		are mapped to the CPU Destination port, overriding where the frame would 
+*		normally go. In the case of ARP, the frame will be mapped normally and it 
+*		will also get copied to this port.
+*		Frames that filtered or discarded will not be mapped to the CPU Destination 
+*		port with the exception of the Rsvd2CPU and DSA Tag cases.
+*
+*		If CPUDest = 0xF, the remapped frames will be discarded, no ARP mirroring 
+*		will occur and ingressing To_CPU frames will be discarded.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetCPUDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetCPUDest Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CPU_DEST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 4, 4, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if(data == 0xF)
+	{
+		*port = (GT_LPORT)data;
+	}
+	else
+	{
+	    *port = GT_PORT_2_LPORT((GT_U8)data);
+	}
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetMirrorDest
+*
+* DESCRIPTION:
+*		This routine sets Mirror Destination Port. Frames that ingress a port 
+*		that trigger a policy mirror are mapped (copied) to this port as long as 
+*		the frame is not filtered or discarded. 
+*		The Mirror Destination port should point to the port that directs these 
+*		frames to the CPU that will process these frames. This target port should 
+*		be a DSA Tag port so the frames will egress with a To_CPU DSA Tag with a 
+*		CPU Code of Policy Mirror.
+*		To_CPU DSA Tag frames with a CPU Code of Policy Mirror that ingress a DSA 
+*		Tag port will be sent to the port number defined in MirrorDest.
+*
+*		If MirrorDest = 0xF, Policy Mirroring is disabled and ingressing To_CPU 
+*		Policy Mirror frames will be discarded.
+*
+* INPUTS:
+*		port  - the logical port number.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetMirrorDest
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT		port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U8           hwPort;         /* the physical port number     */
+
+    DBG_INFO(("gsysSetMirrorDest Called.\n"));
+
+    /* translate LPORT to hardware port */
+    hwPort = GT_LPORT_2_PORT(port);
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_MIRROR_DEST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+	if(port == 0xF)
+		hwPort = (GT_U8)port;
+	else
+	{
+	    hwPort = (GT_U8)(GT_LPORT_2_PORT(port));
+		if (hwPort == GT_INVALID_PORT)
+			return GT_BAD_PARAM;
+	}
+
+    /* Set related bit */
+    retVal = hwSetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 0, 4, (GT_U16)hwPort);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetMirrorDest
+*
+* DESCRIPTION:
+*		This routine gets Mirror Destination Port. Frames that ingress a port 
+*		that trigger a policy mirror are mapped (copied) to this port as long as 
+*		the frame is not filtered or discarded. 
+*		The Mirror Destination port should point to the port that directs these 
+*		frames to the CPU that will process these frames. This target port should 
+*		be a DSA Tag port so the frames will egress with a To_CPU DSA Tag with a 
+*		CPU Code of Policy Mirror.
+*		To_CPU DSA Tag frames with a CPU Code of Policy Mirror that ingress a DSA 
+*		Tag port will be sent to the port number defined in MirrorDest.
+*
+*		If MirrorDest = 0xF, Policy Mirroring is disabled and ingressing To_CPU 
+*		Policy Mirror frames will be discarded.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port  - the logical port number.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetMirrorDest
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT  	*port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetMirrorDest Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CPU_DEST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobalRegField(dev,QD_REG_MONITOR_CONTROL, 0, 4, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if(data == 0xF)
+	{
+		*port = (GT_LPORT)data;
+	}
+	else
+	{
+	    *port = GT_PORT_2_LPORT((GT_U8)data);
+	}
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysSetRMPort
+*
+* DESCRIPTION:
+*		Remote Management feature is enabled only on one port. Since not all ports
+*		can be enabled for Remote Management feature, please refer to the device
+*		datasheet for detailed information.
+*		For example, 88E6097 device allows logical port 9 or 10, and 88E6047 
+*		device allows logical port 4 and 5.
+*		
+* INPUTS:
+*		port - Remote Management Port
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM     - on unallowable port
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Obsolete. Please uses gsysSetRMUMode API, instead.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRMPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_LPORT 	port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysSetRMPort Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_TO_REGISTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* translate LPORT to hardware port */
+	switch(GT_LPORT_2_PORT(port))
+	{
+		case 9:
+				data = 0;
+				break;
+		case 10:
+				data = 1;
+				break;
+		default:
+	    	    DBG_INFO(("Not Allowed Port.\n"));
+    	    	return GT_BAD_PARAM;
+	}
+
+    /* Set the F2R port. */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,13,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetRMPort
+*
+* DESCRIPTION:
+*		Remote Management feature is enabled only on one port. Since not all ports
+*		can be enabled for Remote Management feature, please refer to the device
+*		datasheet for detailed information.
+*		For example, 88E6097 device allows logical port 9 or 10, and 88E6047 
+*		device allows logical port 4 and 5.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		port - Remote Management Port
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Obsolete. Please uses gsysGetRMUMode API, instead.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRMPort
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_LPORT 	*port
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetRMPort Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_TO_REGISTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the F2R port.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,13,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if(data == 1)
+	{
+		*port = GT_PORT_2_LPORT(10);
+	}
+	else
+	{
+	    *port = GT_PORT_2_LPORT(9);
+	}
+    
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRMDACheck
+*
+* DESCRIPTION:
+*		Check the DA on Remote Management frames. 
+*		When DA Check is enabled, the DA of Remote Management frames must be 
+*		contained in this device's address database (ATU) as a Static entry 
+*		(either unicast or multicast). If the DA of the frame is not contained 
+*		in this device's address database, the frame will be not be processed as 
+*		a Remote Management frame.
+*		When DA Check is disabled, the DA of Remote Management frames is not 
+*		validated before processing the frame.
+*		
+* INPUTS:
+*		en - GT_TRUE to enable DA Check, 
+*			 GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRMDACheck
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL 		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysSetRMDACheck Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_TO_REGISTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the DA Check bit. */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,14,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetRMDACheck
+*
+* DESCRIPTION:
+*		Check the DA on Remote Management frames. 
+*		When DA Check is enabled, the DA of Remote Management frames must be 
+*		contained in this device's address database (ATU) as a Static entry 
+*		(either unicast or multicast). If the DA of the frame is not contained 
+*		in this device's address database, the frame will be not be processed as 
+*		a Frame-to-Regter frame.
+*		When DA Check is disabled, the DA of Remote Management frames is not 
+*		validated before processing the frame.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if DA Check is enabled, 
+*			 GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRMDACheck
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL 	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetRMDACheck Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_TO_REGISTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the DA Check bit.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,14,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRMEnable
+*
+* DESCRIPTION:
+*		Enable or disable Remote Management feature. This feature can be enabled
+*		only on one port (see gsysSetRMPort API).
+*		
+* INPUTS:
+*		en - GT_TRUE to enable Remote Management feature, 
+*			 GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Obsolete. Please uses gsysSetRMUMode API, instead.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRMEnable
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL 		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysSetRMEnable Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_TO_REGISTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set the F2R En bit. */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,12,1,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetRMEnable
+*
+* DESCRIPTION:
+*		Enable or disable Remote Management feature. This feature can be enabled
+*		only on one port (see gsysSetRMPort API).
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Remote Management feature is enabled, 
+*			 GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		Obsolete. Please uses gsysGetRMUMode API, instead.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRMEnable
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL 	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetRMEnable Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_TO_REGISTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the F2R En bit.                */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,12,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRMUMode
+*
+* DESCRIPTION:
+*		Set Rmote Management Unit Mode: disable, enable on port 4 or 5, or enable
+*		on port 9 or 10. Devices, such as 88E6097, support RMU on port 9 and 10, 
+*		while other devices, such as 88E6165, support RMU on port 4 and 5. So,
+*		please refer to the device datasheet for detail.
+*		When RMU is enabled and this device receives a Remote Management Request
+*		frame directed to this device, the frame will be processed and a Remote 
+*		Management Response frame will be generated and sent out.
+*		
+*		Note: enabling RMU has no effect if the Remote Management port is in half
+*		duplex mode. The port's FrameMode must be DSA or EtherType DSA as well.
+*		
+* INPUTS:
+*		rmu - GT_RMU structure
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM     - on bad parameter
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRMUMode
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_RMU		*rmu
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    GT_U16          port;
+
+    DBG_INFO(("gsysSetRMUMode Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_TO_REGISTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_RMU_MODE))
+	{
+		if (rmu->rmuEn == GT_TRUE)
+		{
+			port = GT_LPORT_2_PORT(rmu->port);
+			if (port == GT_INVALID_PORT)
+				return GT_BAD_PARAM;
+
+			switch(port)
+			{
+				case 4:
+					data = 1;
+					break;
+				case 5:
+					data = 2;
+					break;
+				default:
+					return GT_BAD_PARAM;
+			}
+		}
+		else
+		{
+			data = 0;
+		}
+	}
+	else
+	{
+		if (rmu->rmuEn)
+		{
+			port = GT_LPORT_2_PORT(rmu->port);
+			if (port == GT_INVALID_PORT)
+				return GT_BAD_PARAM;
+
+			switch(port)
+			{
+				case 9:
+					data = 1;
+					break;
+				case 10:
+					data = 3;
+					break;
+				default:
+					return GT_BAD_PARAM;
+			}
+		}
+		else
+		{
+			data = 0;
+		}
+	}
+
+    /* Set the RMUMode bit. */
+    retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,12,2,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetRMUMode
+*
+* DESCRIPTION:
+*		Get Rmote Management Unit Mode: disable, enable on port 4 or 5, or enable
+*		on port 9 or 10. Devices, such as 88E6097, support RMU on port 9 and 10, 
+*		while other devices, such as 88E6165, support RMU on port 4 and 5. So,
+*		please refer to the device datasheet for detail.
+*		When RMU is enabled and this device receives a Remote Management Request
+*		frame directed to this device, the frame will be processed and a Remote 
+*		Management Response frame will be generated and sent out.
+*		
+*		Note: enabling RMU has no effect if the Remote Management port is in half
+*		duplex mode. The port's FrameMode must be DSA or EtherType DSA as well.
+*		
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		rmu - GT_RMU structure
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRMUMode
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_RMU		*rmu
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetRMUMode Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FRAME_TO_REGISTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the RMUMode bit. */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL2,12,2,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_RMU_MODE))
+	{
+		switch (data)
+		{
+			case 0:
+					rmu->rmuEn = GT_FALSE;
+					break;
+
+			case 1:
+					rmu->rmuEn = GT_TRUE;
+					rmu->port = GT_PORT_2_LPORT(4);
+					break;
+
+			case 2:
+					rmu->rmuEn = GT_TRUE;
+					rmu->port = GT_PORT_2_LPORT(5);
+					break;
+
+			default:
+					return GT_FAIL;
+		}
+	}
+	else
+	{
+		switch (data)
+		{
+			case 0:
+					rmu->rmuEn = GT_FALSE;
+					break;
+
+			case 1:
+					rmu->rmuEn = GT_TRUE;
+					rmu->port = GT_PORT_2_LPORT(9);
+					break;
+
+			case 3:
+					rmu->rmuEn = GT_TRUE;
+					rmu->port = GT_PORT_2_LPORT(10);
+					break;
+
+			default:
+					rmu->rmuEn = GT_FALSE;
+					break;
+		}
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRsvd2CpuEnables2X
+*
+* DESCRIPTION:
+*		Reserved DA Enables for the form of 01:80:C2:00:00:2x.
+*		When the Rsvd2Cpu(gsysSetRsvd2Cpu) is set to a one, the 16 reserved 
+*		multicast DA addresses, whose bit in this register are also set to a one, 
+*		are treadted as MGMT frames. All the reserved DA's take the form 
+*		01:80:C2:00:00:2x. When x = 0x0, bit 0 of this register is tested. 
+*		When x = 0x2, bit 2 of this field is tested and so on.
+*		If the tested bit in this register is cleared to a zero, the frame will 
+*		be treated as a normal (non-MGMT) frame.
+*
+* INPUTS:
+*		enBits - bit vector of enabled Reserved Multicast.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRsvd2CpuEnables2X
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U16		enBits
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysSetRsvd2CpuEnables2X Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST_2X))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Set related register */
+    retVal = hwWriteGlobal2Reg(dev,QD_REG_MGMT_ENABLE_2X, (GT_U16)enBits);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetRsvd2CpuEnables2X
+*
+* DESCRIPTION:
+*		Reserved DA Enables for the form of 01:80:C2:00:00:2x.
+*		When the Rsvd2Cpu(gsysSetRsvd2Cpu) is set to a one, the 16 reserved 
+*		multicast DA addresses, whose bit in this register are also set to a one, 
+*		are treadted as MGMT frames. All the reserved DA's take the form 
+*		01:80:C2:00:00:2x. When x = 0x0, bit 0 of this register is tested. 
+*		When x = 0x2, bit 2 of this field is tested and so on.
+*		If the tested bit in this register is cleared to a zero, the frame will 
+*		be treated as a normal (non-MGMT) frame.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		enBits - bit vector of enabled Reserved Multicast.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRsvd2CpuEnables2X
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U16  	*enBits
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysGetRsvd2CpuEnables2X Called.\n"));
+
+	/* Check if Switch supports this status. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ENHANCED_MULTICAST_2X))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related register */
+    retVal = hwReadGlobal2Reg(dev, QD_REG_MGMT_ENABLE_2X, enBits);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetLoopbackFilter
+*
+* DESCRIPTION:
+*		Loopback Filter.
+*		When Loopback Filter is enabled,Forward DSA frames that ingress a DSA port
+*		that came from the same Src_Dev will be filtered to the same Src_Port,
+*		i.e., the frame will not be allowed to egress the source port on the 
+*		source device as indicated in the DSA Forward's Tag.
+*
+* INPUTS:
+*		en - GT_TRUE to enable LoopbackFilter, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetLoopbackFilter
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetLoopbackFilter Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_LOOPBACK_FILTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 15, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetLoopbackFilter
+*
+* DESCRIPTION:
+*		Loopback Filter.
+*		When Loopback Filter is enabled,Forward DSA frames that ingress a DSA port
+*		that came from the same Src_Dev will be filtered to the same Src_Port,
+*		i.e., the frame will not be allowed to egress the source port on the 
+*		source device as indicated in the DSA Forward's Tag.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if LoopbackFilter is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetLoopbackFilter
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetLoopbackFilter Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_LOOPBACK_FILTER))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,15,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetFloodBC
+*
+* DESCRIPTION:
+*		Flood Broadcast.
+*		When Flood Broadcast is enabled, frames with the Broadcast destination 
+*		address will flood out all the ports regardless of the setting of the
+*		port's Egress Floods mode (see gprtSetEgressFlood API). VLAN rules and 
+*		other switch policy still applies to these Broadcast frames. 
+*		When this feature is disabled, frames with the Broadcast destination
+*		address are considered Multicast frames and will be affected by port's 
+*		Egress Floods mode.
+*
+* INPUTS:
+*		en - GT_TRUE to enable Flood Broadcast, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetFloodBC
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetFloodBC Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FLOOD_BROADCAST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 12, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetFloodBC
+*
+* DESCRIPTION:
+*		Flood Broadcast.
+*		When Flood Broadcast is enabled, frames with the Broadcast destination 
+*		address will flood out all the ports regardless of the setting of the
+*		port's Egress Floods mode (see gprtSetEgressFlood API). VLAN rules and 
+*		other switch policy still applies to these Broadcast frames. 
+*		When this feature is disabled, frames with the Broadcast destination
+*		address are considered Multicast frames and will be affected by port's 
+*		Egress Floods mode.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Flood Broadcast is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetFloodBC
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetFloodBC Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_FLOOD_BROADCAST))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,12,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetRemove1PTag
+*
+* DESCRIPTION:
+*		Remove One Provider Tag.
+*		When this feature is enabled and a port is configured as a Provider Port
+*		(see gprtSetFrameMode API), recursive Provider Tag stripping will NOT be 
+*		performed. Only the first Provider Tag found on the frame will be 
+*		extracted and removed. Its extracted data will be used for switching.
+*		When it's disabled and a port is configured as a Provider Port, recursive 
+*		Provider Tag stripping will be performed. The first Provider Tag's data 
+*		will be extracted and used for switching, and then all subsequent Provider 
+*		Tags found in the frame will also be removed. This will only occur if the 
+*		port's PortEType (see gprtSetPortEType API) is not 0x8100.
+*
+* INPUTS:
+*		en - GT_TRUE to enable Remove One Provider Tag, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetRemove1PTag
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetRemove1PTag Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RM_ONE_PTAG))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 11, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetRemove1PTag
+*
+* DESCRIPTION:
+*		Remove One Provider Tag.
+*		When this feature is enabled and a port is configured as a Provider Port
+*		(see gprtSetFrameMode API), recursive Provider Tag stripping will NOT be 
+*		performed. Only the first Provider Tag found on the frame will be 
+*		extracted and removed. Its extracted data will be used for switching.
+*		When it's disabled and a port is configured as a Provider Port, recursive 
+*		Provider Tag stripping will be performed. The first Provider Tag's data 
+*		will be extracted and used for switching, and then all subsequent Provider 
+*		Tags found in the frame will also be removed. This will only occur if the 
+*		port's PortEType (see gprtSetPortEType API) is not 0x8100.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Remove One Provider Tag is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetRemove1PTag
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL		*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysGetRemove1PTag Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_RM_ONE_PTAG))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT, 11, 1, &data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetTagFlowControl
+*
+* DESCRIPTION:
+*		Use and generate source port Flow Control status for Cross-Chip Flow 
+*		Control.
+*		When this feature is enabled, bit 17 of the DSA Tag Forward frames is 
+*		defined to be Src_FC and it is added to these frames when generated and 
+*		it is inspected on these frames when received. The QC will use the Src_FC 
+*		bit on DSA ports instead of the DSA port's Flow Control mode bit for the 
+*		QC Flow Control algorithm.
+*		When it is disabled, bit 17 of the DSA Tag Forward frames is defined to 
+*		be Reserved and it will be zero on these frames when generated and it 
+*		will not be used on these frames when received (this is a backwards 
+*		compatibility mode).
+*
+* INPUTS:
+*		en - GT_TRUE to enable Tag Flow Control, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetTagFlowControl
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetTagFlowControl Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAG_FLOW_CONTROL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 9, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetTagFlowControl
+*
+* DESCRIPTION:
+*		Use and generate source port Flow Control status for Cross-Chip Flow 
+*		Control.
+*		When this feature is enabled, bit 17 of the DSA Tag Forward frames is 
+*		defined to be Src_FC and it is added to these frames when generated and 
+*		it is inspected on these frames when received. The QC will use the Src_FC 
+*		bit on DSA ports instead of the DSA port's Flow Control mode bit for the 
+*		QC Flow Control algorithm.
+*		When it is disabled, bit 17 of the DSA Tag Forward frames is defined to 
+*		be Reserved and it will be zero on these frames when generated and it 
+*		will not be used on these frames when received (this is a backwards 
+*		compatibility mode).
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if Tag Flow Control is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetTagFlowControl
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetTagFlowControl Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_TAG_FLOW_CONTROL))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,9,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetAlwaysUseVTU
+*
+* DESCRIPTION:
+*		Always use VTU. 
+*		When this feature is enabled, VTU hit data will be used to map frames 
+*		even if 802.1Q is Disabled on the port. 
+*		When it's disabled, data will be ignored when mapping frames on ports 
+*		where 802.1Q is Disabled.
+*
+* INPUTS:
+*		en - GT_TRUE to use VTU always, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetAlwaysUseVTU
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetAlwaysUseVTU Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ALWAYS_USE_VTU))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_MANAGEMENT, 8, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetAlwaysUseVTU
+*
+* DESCRIPTION:
+*		Always use VTU. 
+*		When this feature is enabled, VTU hit data will be used to map frames 
+*		even if 802.1Q is Disabled on the port. 
+*		When it's disabled, data will be ignored when mapping frames on ports 
+*		where 802.1Q is Disabled.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if VTU is always used, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetAlwaysUseVTU
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetAlwaysUseVTU Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_ALWAYS_USE_VTU))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_MANAGEMENT,8,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetQVlansOnly
+*
+* DESCRIPTION:
+*		802.1Q VLANs Only.
+*		When this feature is disabled, the egress mapping of the frame is 
+*		limited by the frame's VID (using the MemberTag data found in the VTU) 
+*		together with the port based VLANs (using the source port's PortVLANTable, 
+*		gvlnSetPortVlanPorts API). The two methods are always used together in 
+*		this mode.
+*		When this feature is enabled, the egress mapping of the frame is limitied
+*		by the frame's VID only, if the VID was found in the VTU. If the frame's
+*		VID was not found in the VTU the egress mapping of the frame is limited
+*		by the source port's PortVLANTable only. The two methods are never
+*		used together in this mode.
+*
+* INPUTS:
+*		en - GT_TRUE to use 802.1Q Vlan Only feature, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetQVlansOnly
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+    DBG_INFO(("gsysSetQVlansOnly Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QVLAN_ONLY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    BOOL_2_BIT(en,data);
+
+    /* Set related bit */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_SDET_POLARITY, 15, 1, data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetQVlansOnly
+*
+* DESCRIPTION:
+*		802.1Q VLANs Only.
+*		When this feature is disabled, the egress mapping of the frame is 
+*		limited by the frame's VID (using the MemberTag data found in the VTU) 
+*		together with the port based VLANs (using the source port's PortVLANTable, 
+*		gvlnSetPortVlanPorts API). The two methods are always used together in 
+*		this mode.
+*		When this feature is enabled, the egress mapping of the frame is limitied
+*		by the frame's VID only, if the VID was found in the VTU. If the frame's
+*		VID was not found in the VTU the egress mapping of the frame is limited
+*		by the source port's PortVLANTable only. The two methods are never
+*		used together in this mode.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if 802.1Q Vlan Only feature is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetQVlansOnly
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetQVlansOnly Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QVLAN_ONLY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get related bit */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_SDET_POLARITY,15,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*en);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSet5BitPort
+*
+* DESCRIPTION:
+*		Use 5 bits for Port data in the Port VLAN Table (PVT). 
+*		When this feature is enabled, the 9 bits used to access the PVT memory is:
+*			Addr[8:5] = Source Device[3:0] or Device Number[3:0]
+*			Addr[4:0] = Source Port/Trunk[4:0]
+*		When it's disabled, the 9 bits used to access the PVT memory is:
+*			Addr[8:4] = Source Device[4:0] or Device Number[4:0]
+*			Addr[3:0] = Source Port/Trunk[3:0]
+*
+* INPUTS:
+*		en - GT_TRUE to use 5 bit as a Source port in PVT, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSet5BitPort
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+	DBG_INFO(("gsysSet5BitPort Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_5BIT_PORT))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	BOOL_2_BIT(en,data);
+
+	/* Set related bit */
+	retVal = hwSetGlobal2RegField(dev,QD_REG_SDET_POLARITY, 14, 1, data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGet5BitPort
+*
+* DESCRIPTION:
+*		Use 5 bits for Port data in the Port VLAN Table (PVT). 
+*		When this feature is enabled, the 9 bits used to access the PVT memory is:
+*			Addr[8:5] = Source Device[3:0] or Device Number[3:0]
+*			Addr[4:0] = Source Port/Trunk[4:0]
+*		When it's disabled, the 9 bits used to access the PVT memory is:
+*			Addr[8:4] = Source Device[4:0] or Device Number[4:0]
+*			Addr[3:0] = Source Port/Trunk[3:0]
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if 5 bit is used as a Source Port in PVT, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGet5BitPort
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* The register's read data.    */
+	
+	DBG_INFO(("gsysGet5BitPort Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_5BIT_PORT))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get related bit */
+	retVal = hwGetGlobal2RegField(dev,QD_REG_SDET_POLARITY,14,1,&data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	BIT_2_BOOL(data,*en);
+	DBG_INFO(("OK.\n"));
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetSDETPolarity
+*
+* DESCRIPTION:
+*		SDET (Signal Detect) Polarity select bits for each port. 
+*		Bit 10 is for Port 10, bit 9 is for Port 9, etc. SDET is used to help 
+*		determine link on fiber ports. This bit affects the active level of a 
+*		port's SDET pins as follows:
+*			0 = SDET is active low. A low level on the port's SDET pin is 
+*				required for link to occur.
+*			1 = SDET is active high. A high level on the portÂ’s SDET pin is 
+*				required for link to occur.
+*		SDET is used when the port is configured as a fiber port. In all other 
+*		port modes the SDET pins are ignored and these bits have no effect.
+*
+* INPUTS:
+*		sdetVec - SDET Polarity for each port in Vector format
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_BAD_PARAM - if sdetVec is invalid
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetSDETPolarity
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_U32  		sdetVec
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysSetSDETPolarity Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SDET_POLARITY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    if ((GT_U16)sdetVec > ((1 << dev->numOfPorts) - 1))
+	{
+		DBG_INFO(("GT_BAD_PARAM \n"));
+		return GT_BAD_PARAM;
+	}
+
+	data = (GT_U16)GT_LPORTVEC_2_PORTVEC(sdetVec);
+
+	if (IS_IN_DEV_GROUP(dev,DEV_LIMITED_SDET))
+	{
+		if (data & (~0x30))	/* only port 4 and 5 of this device support SDET */
+		{
+			DBG_INFO(("GT_BAD_PARAM \n"));
+			return GT_BAD_PARAM;
+		}
+	}
+
+    /* Set the related bits. */
+    retVal = hwSetGlobal2RegField(dev,QD_REG_SDET_POLARITY,0,dev->maxPorts,data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetSDETPolarity
+*
+* DESCRIPTION:
+*		SDET (Signal Detect) Polarity select bits for each port. 
+*		Bit 10 is for Port 10, bit 9 is for Port 9, etc. SDET is used to help 
+*		determine link on fiber ports. This bit affects the active level of a 
+*		port's SDET pins as follows:
+*			0 = SDET is active low. A low level on the port's SDET pin is 
+*				required for link to occur.
+*			1 = SDET is active high. A high level on the portÂ’s SDET pin is 
+*				required for link to occur.
+*		SDET is used when the port is configured as a fiber port. In all other 
+*		port modes the SDET pins are ignored and these bits have no effect.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		sdetVec - SDET Polarity for each port in Vector format
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetSDETPolarity
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_U32  	*sdetVec
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+    DBG_INFO(("gsysGetSDETPolarity Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_SDET_POLARITY))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+    /* Get the related bits. */
+    retVal = hwGetGlobal2RegField(dev,QD_REG_SDET_POLARITY,0,dev->maxPorts,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+	if (IS_IN_DEV_GROUP(dev,DEV_LIMITED_SDET))
+	{
+		data &= 0x30;
+	}
+
+	*sdetVec = GT_PORTVEC_2_LPORTVEC(data);
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetARPwoBC
+*
+* DESCRIPTION:
+*       ARP detection without Broadcast checking. When enabled the switch core
+*       does not check for a Btoadcast MAC address as part of the ARP frame
+*       detection. It only checkes the Ether Type (0x0806).
+*
+* INPUTS:
+*       en - GT_TRUE to enable, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetARPwoBC
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_BOOL 	en
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* Data to be set into the      */
+                                /* register.                    */
+	DBG_INFO(("sysSetARPwoBC Called.\n"));
+	BOOL_2_BIT(en,data);
+
+	/* Set the Discard Exissive bit.                */
+	retVal = hwSetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,12,1,data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gsysGetARPwoBC
+*
+* DESCRIPTION:
+*       ARP detection without Broadcast checking. When enabled the switch core
+*       does not check for a Btoadcast MAC address as part of the ARP frame
+*       detection. It only checkes the Ether Type (0x0806).
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       en - GT_TRUE if enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetARPwoBC
+(
+	IN  GT_QD_DEV 	*dev,
+	IN  GT_BOOL		*en
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* The register's read data.    */
+
+	DBG_INFO(("gsysGetARPwoBC Called.\n"));
+	if(en == NULL)
+	{
+		DBG_INFO(("Failed.\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* Get the bit. */
+	retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_CONTROL,12,1,&data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	BIT_2_BOOL(data,*en);
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysSetCLK125En
+*
+* DESCRIPTION:
+*		Clock 125MHz Enable.
+*		When this feature is enabled, the CLK125 pin has a free running 125 MHz
+*		clock output.
+*		When it's disabled, the CLK125 pin will be in tri-state.
+*
+* INPUTS:
+*		en - GT_TRUE to enable 125 MHz clock, GT_FALSE otherwise.
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysSetCLK125En
+(
+	IN GT_QD_DEV	*dev,
+	IN GT_BOOL		en
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16			data;
+
+	DBG_INFO(("gsysSetCLK125En Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CLK_125))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	BOOL_2_BIT(en,data);
+
+	/* Set related bit */
+	retVal = hwSetGlobal2RegField(dev,QD_REG_SDET_POLARITY, 11, 1, data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetCLK125En
+*
+* DESCRIPTION:
+*		Clock 125MHz Enable.
+*		When this feature is enabled, the CLK125 pin has a free running 125 MHz
+*		clock output.
+*		When it's disabled, the CLK125 pin will be in tri-state.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		en - GT_TRUE if 125MHz clock is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysGetCLK125En
+(
+	IN  GT_QD_DEV	*dev,
+	OUT GT_BOOL  	*en
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* The register's read data.    */
+	
+	DBG_INFO(("gsysGetCLK125En Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_CLK_125))
+	{
+		DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Get related bit */
+	retVal = hwGetGlobal2RegField(dev,QD_REG_SDET_POLARITY,11,1,&data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	BIT_2_BOOL(data,*en);
+	DBG_INFO(("OK.\n"));
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysPort2Lport
+*
+* DESCRIPTION:
+*		This routine converts physical port number to logical port number.
+*
+* INPUTS:
+*		port - physical port number
+*
+* OUTPUTS:
+*		lport - logical port number
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysPort2Lport
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32 		port,
+	OUT GT_LPORT	*lport
+)
+{
+    DBG_INFO(("gsysPort2Lport Called.\n"));
+
+	if (port > 0xFF)
+	{
+		return GT_FAIL;
+	}
+
+	*lport = GT_PORT_2_LPORT((GT_U8)port);
+
+	if (*lport == GT_INVALID_PORT)
+	{
+		return GT_FAIL;
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysLport2Port
+*
+* DESCRIPTION:
+*		This routine converts logical port number to physical port number.
+*
+* INPUTS:
+*		lport - logical port number
+*
+* OUTPUTS:
+*		port - physical port number
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysLport2Port
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_LPORT	lport,
+	OUT GT_U32 		*port
+)
+{
+    DBG_INFO(("gsysLport2Port Called.\n"));
+
+	*port = (GT_U32)GT_LPORT_2_PORT(lport);
+
+	if (*port == GT_INVALID_PORT)
+	{
+		return GT_FAIL;
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysPortvec2Lportvec
+*
+* DESCRIPTION:
+*		This routine converts physical port vector to logical port vector.
+*
+* INPUTS:
+*		portvec - physical port vector
+*
+* OUTPUTS:
+*		lportvec - logical port vector
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysPortvec2Lportvec
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32		portvec,
+	OUT GT_U32 		*lportvec
+)
+{
+    DBG_INFO(("gsysPortvec2Lportvec Called.\n"));
+
+	if (portvec & (~((GT_U32)dev->validPortVec)))
+	{
+		return GT_FAIL;
+	}
+
+	*lportvec = GT_PORTVEC_2_LPORTVEC(portvec);
+
+	if (*lportvec == GT_INVALID_PORT_VEC)
+	{
+		return GT_FAIL;
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysLportvec2Portvec
+*
+* DESCRIPTION:
+*		This routine converts logical port vector to physical port vector.
+*
+* INPUTS:
+*		lportvec - logical port vector
+*
+* OUTPUTS:
+*		portvec - physical port vector
+*
+* RETURNS:
+*		GT_OK   - on success
+*		GT_FAIL - on error
+*
+* COMMENTS:
+*		None.
+*
+*******************************************************************************/
+GT_STATUS gsysLportvec2Portvec
+(
+	IN  GT_QD_DEV	*dev,
+	IN  GT_U32		lportvec,
+	OUT GT_U32 		*portvec
+)
+{
+    DBG_INFO(("gsysLportvec2Portvec Called.\n"));
+
+	*portvec = GT_LPORTVEC_2_PORTVEC(lportvec);
+
+	if (*portvec == GT_INVALID_PORT_VEC)
+	{
+		return GT_FAIL;
+	}
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
+
+/****************************************************************************/
+/* Internal functions.                                                  */
+/****************************************************************************/
+
+/*
+ * Write to Switch MAC Register
+ */
+static GT_STATUS writeSwitchMacReg
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_ETHERADDR *mac
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+	GT_U16			i;
+
+	for (i=0; i<GT_ETHERNET_HEADER_SIZE; i++)
+	{
+	    /* Wait until the device is ready. */
+	    data = 1;
+    	while(data == 1)
+	    {
+    	    retVal = hwGetGlobal2RegField(dev,QD_REG_SWITCH_MAC,15,1,&data);
+        	if(retVal != GT_OK)
+	        {
+        	    return retVal;
+	        }
+    	}
+
+		data = (1 << 15) | (i << 8) | mac->arEther[i];
+
+		retVal = hwWriteGlobal2Reg(dev,QD_REG_SWITCH_MAC,data);
+        if(retVal != GT_OK)
+   	    {
+           	return retVal;
+        }
+	}
+
+	return GT_OK;
+}
+
+/*
+ * Read from Switch MAC Register
+ */
+static GT_STATUS readSwitchMacReg
+(
+    IN  GT_QD_DEV    *dev,
+    OUT GT_ETHERADDR *mac
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+	GT_U16			i;
+
+    /* Wait until the device is ready. */
+    data = 1;
+   	while(data == 1)
+    {
+   	    retVal = hwGetGlobal2RegField(dev,QD_REG_SWITCH_MAC,15,1,&data);
+       	if(retVal != GT_OK)
+        {
+       	    return retVal;
+        }
+   	}
+
+	for (i=0; i<GT_ETHERNET_HEADER_SIZE; i++)
+	{
+		data = i << 8;
+
+		retVal = hwWriteGlobal2Reg(dev,QD_REG_SWITCH_MAC,data);
+        if(retVal != GT_OK)
+   	    {
+           	return retVal;
+        }
+
+		retVal = hwReadGlobal2Reg(dev,QD_REG_SWITCH_MAC,&data);
+        if(retVal != GT_OK)
+   	    {
+           	return retVal;
+        }
+
+		if (i == 0)
+			mac->arEther[i] = data & 0xFE;	/* bit 0 is for diffAddr */
+		else
+			mac->arEther[i] = data & 0xFF;
+	}
+
+	return GT_OK;
+}
+
+
+/*
+ * Write to Different MAC Address per port bit in Switch MAC Register
+ */
+static GT_STATUS writeDiffMAC
+(
+    IN GT_QD_DEV    *dev,
+    IN GT_U16		diffAddr
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+
+    /* Wait until the device is ready. */
+    data = 1;
+   	while(data == 1)
+    {
+   	    retVal = hwGetGlobal2RegField(dev,QD_REG_SWITCH_MAC,15,1,&data);
+       	if(retVal != GT_OK)
+        {
+       	    return retVal;
+        }
+   	}
+
+    /* Write to Swith MAC Reg for reading operation */
+	data = 0;
+	retVal = hwWriteGlobal2Reg(dev,QD_REG_SWITCH_MAC,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+    /* Read Swith MAC Reg */
+	retVal = hwReadGlobal2Reg(dev,QD_REG_SWITCH_MAC,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	data = (1 << 15) | (data & 0xFE) | (diffAddr & 0x1);
+
+    /* Write back to Swith MAC Reg with updated diffAddr */
+	retVal = hwWriteGlobal2Reg(dev,QD_REG_SWITCH_MAC,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	return GT_OK;
+}
+
+/*
+ * Read Different MAC Address per port bit in Switch MAC Register
+ */
+static GT_STATUS readDiffMAC
+(
+    IN  GT_QD_DEV	*dev,
+    OUT GT_U16		*diffAddr
+)
+{
+    GT_STATUS       retVal;	/* Functions return value */
+    GT_U16          data; 	/* temporary Data storage */
+
+    /* Wait until the device is ready. */
+    data = 1;
+   	while(data == 1)
+    {
+   	    retVal = hwGetGlobal2RegField(dev,QD_REG_SWITCH_MAC,15,1,&data);
+       	if(retVal != GT_OK)
+        {
+       	    return retVal;
+        }
+   	}
+
+    /* Write to Swith MAC Reg for reading operation */
+	data = 0;
+	retVal = hwWriteGlobal2Reg(dev,QD_REG_SWITCH_MAC,data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	retVal = hwReadGlobal2Reg(dev,QD_REG_SWITCH_MAC,&data);
+	if(retVal != GT_OK)
+	{
+		return retVal;
+	}
+
+	*diffAddr = data & 0x1;
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysStatus.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysStatus.c
new file mode 100755
index 0000000..3175bcd
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtSysStatus.c
@@ -0,0 +1,264 @@
+#include <Copyright.h>
+
+/*******************************************************************************
+* gtSysStatus.c
+*
+* DESCRIPTION:
+*       API definitions for system global status.
+* 	Added for fullsail
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: 5 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+/*******************************************************************************
+* gsysGetPPUState
+*
+* DESCRIPTION:
+*		This routine get the PPU State. These two bits return 
+*		the current value of the PPU.
+*
+* INPUTS:
+*		None.
+*
+* OUTPUTS:
+*		mode - GT_PPU_STATE
+*
+* RETURNS:
+*		GT_OK           - on success
+*		GT_BAD_PARAM    - on bad parameter
+*		GT_FAIL         - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*		None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetPPUState
+(
+	IN  GT_QD_DEV   	*dev,
+	OUT GT_PPU_STATE	*mode
+)
+{
+	GT_STATUS       retVal;         /* Functions return value.      */
+	GT_U16          data;           /* The register's read data.    */
+
+	DBG_INFO(("gsysGetPPUState Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
+	{
+		DBG_INFO(("Not Supported.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+	if(mode == NULL)
+	{
+		DBG_INFO(("Failed.\n"));
+		return GT_BAD_PARAM;
+	}
+
+	/* get the bits from hardware */
+	retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,14,2,&data);
+	if(retVal != GT_OK)
+	{
+		DBG_INFO(("Failed.\n"));
+		return retVal;
+	}
+
+	if (IS_IN_DEV_GROUP(dev,DEV_PPU_READ_ONLY))
+	{
+		data |= 0x4000;
+	}
+
+	*mode = data;
+	DBG_INFO(("OK.\n"));
+	return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetSW_Mode
+*
+* DESCRIPTION:
+*       This routine get the Switch mode. These two bits returen 
+*       the current value of the SW_MODE[1:0] pins.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE Discard is enabled, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetSW_Mode
+(
+    IN  GT_QD_DEV  *dev,
+    OUT GT_SW_MODE *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetSW_Mode Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QD_PLUS|DEV_ENHANCED_FE_SWITCH))
+	{
+        DBG_INFO(("Not Supported.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* get the bits from hardware */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,12,2,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    *mode = data;
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetInitReady
+*
+* DESCRIPTION:
+*       This routine get the InitReady bit. This bit is set to a one when the ATU,
+*       the Queue Controller and the Statistics Controller are done with their 
+*       initialization and are ready to accept frames.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       mode - GT_TRUE: switch is ready, GT_FALSE otherwise.
+*
+* RETURNS:
+*       GT_OK           - on success
+*       GT_BAD_PARAM    - on bad parameter
+*       GT_FAIL         - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetInitReady
+(
+    IN  GT_QD_DEV  *dev,
+    OUT GT_BOOL    *mode
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+    GT_U16          data;           /* The register's read data.    */
+
+    DBG_INFO(("gsysGetInitReady Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QD_PLUS|DEV_ENHANCED_FE_SWITCH))
+	{
+        DBG_INFO(("Not Supported.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    if(mode == NULL)
+    {
+        DBG_INFO(("Failed.\n"));
+        return GT_BAD_PARAM;
+    }
+
+    /* get the bits from hardware */
+    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,11,1,&data);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    BIT_2_BOOL(data,*mode);
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+/*******************************************************************************
+* gsysGetFreeQSize
+*
+* DESCRIPTION:
+*       This routine gets Free Queue Counter. This counter reflects the 
+*		current number of unalllocated buffers available for all the ports.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       count - Free Queue Counter
+*
+* RETURNS:
+*       GT_OK            - on success
+*       GT_FAIL          - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+GT_STATUS gsysGetFreeQSize
+(
+    IN  GT_QD_DEV	*dev,
+    OUT GT_U16 		*count
+)
+{
+    GT_STATUS       retVal;         /* Functions return value.      */
+
+    DBG_INFO(("gsysGetFreeQSize Called.\n"));
+
+    /* check if device supports this feature */
+	if (!IS_IN_DEV_GROUP(dev,DEV_OUT_Q_SIZE))
+	{
+        DBG_INFO(("Not Supported.\n"));
+		return GT_NOT_SUPPORTED;
+	}
+
+    /* get the counter */
+    retVal = hwGetGlobalRegField(dev,QD_REG_TOTAL_FREE_COUNTER,0,9,count);
+    if(retVal != GT_OK)
+    {
+        DBG_INFO(("Failed.\n"));
+        return retVal;
+    }
+
+    DBG_INFO(("OK.\n"));
+    return GT_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtUtils.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtUtils.c
new file mode 100755
index 0000000..9ee7c35
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtUtils.c
@@ -0,0 +1,213 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtUtils.c
+*
+* DESCRIPTION:
+*       Collection of Utility functions
+*
+* DEPENDENCIES:
+*       None
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include "mvOs.h"
+
+/*******************************************************************************
+* gtMemSet
+*
+* DESCRIPTION:
+*       Set a block of memory
+*
+* INPUTS:
+*       start  - start address of memory block for setting
+*       simbol - character to store, converted to an unsigned char
+*       size   - size of block to be set
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       Pointer to set memory block
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void * gtMemSet
+(
+    IN void * start,
+    IN int    symbol,
+    IN GT_U32 size
+)
+{
+	GT_U32 i;
+	char* buf;
+	
+	buf = (char*)start;
+		
+	for(i=0; i<size; i++)
+	{
+		*buf++ = (char)symbol;
+	}
+
+	return start;
+}
+
+/*******************************************************************************
+* gtMemCpy
+*
+* DESCRIPTION:
+*       Copies 'size' characters from the object pointed to by 'source' into
+*       the object pointed to by 'destination'. If copying takes place between
+*       objects that overlap, the behavior is undefined.
+*
+* INPUTS:
+*       destination - destination of copy
+*       source      - source of copy
+*       size        - size of memory to copy
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       Pointer to destination
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void * gtMemCpy
+(
+    IN void *       destination,
+    IN const void * source,
+    IN GT_U32       size
+)
+{
+	GT_U32 i;
+	char* buf;
+	char* src;
+	
+	buf = (char*)destination;
+	src = (char*)source;
+		
+	for(i=0; i<size; i++)
+	{
+		*buf++ = *src++;
+	}
+
+	return destination;
+}
+
+/*******************************************************************************
+* gtMemCmp
+*
+* DESCRIPTION:
+*       Compares given memories.
+*
+* INPUTS:
+*       src1 - source 1
+*       src2 - source 2
+*       size - size of memory to copy
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       0, if equal.
+*		negative number, if src1 < src2.
+*		positive number, if src1 > src2.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+int gtMemCmp
+(
+    IN char src1[],
+    IN char src2[],
+    IN GT_U32 size
+)
+{
+	GT_U32 i;
+	int value;
+
+	for(i=0; i<size; i++)
+	{
+		if((value = (int)(src1[i] - src2[i])) != 0)
+			return value; 
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+* gtStrlen
+*
+* DESCRIPTION:
+*       Determine the length of a string
+* INPUTS:
+*       source  - string
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       size    - number of characters in string, not including EOS.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_U32 gtStrlen
+(
+    IN const void * source
+)
+{
+	GT_U32 i = 0;
+	char* src;
+	
+	src = (char*)source;
+		
+	while(*src++) i++;
+
+    return i;
+}
+
+
+/*******************************************************************************
+* gtDelay
+*
+* DESCRIPTION:
+*       Wait for the given uSec and return.
+*		Current Switch devices with Gigabit Ethernet Support require 250 uSec
+*		of delay time for PPU to be disabled.
+*		Since this function is System and/or OS dependent, it should be provided
+*		by each DSDT user.
+*
+* INPUTS:
+*       delayTime - delay in uSec.
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       None
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+void gtDelay
+(
+    IN const unsigned int delayTime
+)
+{
+    mvOsUDelay(delayTime);
+}
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtVct.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtVct.c
new file mode 100755
index 0000000..5c5f74a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtVct.c
@@ -0,0 +1,1230 @@
+#include <Copyright.h>
+/*******************************************************************************
+* gtVct.c
+*
+* DESCRIPTION:
+*       API for Marvell Virtual Cable Tester.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1 $
+*******************************************************************************/
+#include <msApi.h>
+#include <gtVct.h>
+#include <gtDrvConfig.h>
+#include <gtDrvSwRegs.h>
+#include <gtHwCntl.h>
+#include <gtSem.h>
+
+
+
+/*******************************************************************************
+* analizePhy100MVCTResult
+*
+* DESCRIPTION:
+*       This routine analize the virtual cable test result for 10/100M Phy
+*
+* INPUTS:
+*       regValue - test result
+*
+* OUTPUTS:
+*       cableStatus - analized test result.
+*       cableLen    - cable length or the distance where problem occurs.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+static
+GT_STATUS analizePhy100MVCTResult
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U16 regValue, 
+    OUT GT_TEST_STATUS *cableStatus,
+    OUT GT_CABLE_LEN *cableLen
+)
+{
+	int len;
+
+	GT_UNUSED_PARAM(dev);
+
+	switch((regValue & 0x6000) >> 13)
+	{
+		case 0:
+			/* test passed. No problem found. */
+			/* check if there is impedance mismatch */
+			if ((regValue & 0xFF) == 0xFF)
+			{
+				*cableStatus = GT_NORMAL_CABLE;
+				cableLen->normCableLen = GT_UNKNOWN_LEN;
+			}
+			else
+			{
+				*cableStatus = GT_IMPEDANCE_MISMATCH;
+				len = (int)FORMULA_PHY100M(regValue & 0xFF);
+				if(len <= 0)
+					cableLen->errCableLen = 0;
+				else
+					cableLen->errCableLen = (GT_U8)len;
+			}
+				
+			break;
+		case 1:
+			/* test passed. Cable is short. */
+			*cableStatus = GT_SHORT_CABLE;
+			len = (int)FORMULA_PHY100M(regValue & 0xFF);
+			if(len <= 0)
+				cableLen->errCableLen = 0;
+			else
+				cableLen->errCableLen = (GT_U8)len;
+			break;
+		case 2:
+			/* test passed. Cable is open. */
+			*cableStatus = GT_OPEN_CABLE;
+			len = (int)FORMULA_PHY100M(regValue & 0xFF);
+			if(len <= 0)
+				cableLen->errCableLen = 0;
+			else
+				cableLen->errCableLen = (GT_U8)len;
+			break;
+		case 3:
+		default:
+			/* test failed. No result is valid. */
+			*cableStatus = GT_TEST_FAIL;
+			break;
+	}
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* getCableStatus_Phy100M
+*
+* DESCRIPTION:
+*       This routine perform the virtual cable test for the 10/100Mbps phy,
+*       and returns the the status per Rx/Tx pair.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*       cableStatus - the port copper cable status.
+*       cableLen    - the port copper cable length.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+static 
+GT_STATUS getCableStatus_Phy100M
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8            hwPort,
+    OUT GT_CABLE_STATUS *cableStatus
+)
+{
+	GT_STATUS status;
+	GT_U16 reg26, reg27;
+
+    DBG_INFO(("getCableStatus_100Phy Called.\n"));
+
+	/* 
+	 * 	phy should be in 100 Full Duplex.
+	 */
+	if((status= hwWritePhyReg(dev,hwPort,0,QD_PHY_RESET | QD_PHY_SPEED | QD_PHY_DUPLEX)) != GT_OK)
+	{
+		return status;
+	}
+
+	/* 
+	 * start Virtual Cable Tester
+	 */
+	if((status= hwWritePhyReg(dev,hwPort,26,0x8000)) != GT_OK)
+	{
+		return status;
+	}
+
+	do
+	{
+		if((status= hwReadPhyReg(dev,hwPort,26,&reg26)) != GT_OK)
+		{
+			return status;
+		}
+		
+	} while(reg26 & 0x8000);
+
+	/*
+	 * read the test result for RX Pair
+	 */
+	if((status= hwReadPhyReg(dev,hwPort,26,&reg26)) != GT_OK)
+	{
+		return status;
+	}
+		
+	/*
+	 * read the test result for TX Pair
+	 */
+	if((status= hwReadPhyReg(dev,hwPort,27,&reg27)) != GT_OK)
+	{
+		return status;
+	}
+		
+	cableStatus->phyType = PHY_100M;
+
+	/*
+	 * analyze the test result for RX Pair
+	 */
+	analizePhy100MVCTResult(dev, reg26, &cableStatus->cableStatus[MDI_RX_PAIR], 
+							&cableStatus->cableLen[MDI_RX_PAIR]);
+
+	/*
+	 * analyze the test result for TX Pair
+	 */
+	analizePhy100MVCTResult(dev, reg27, &cableStatus->cableStatus[MDI_TX_PAIR], 
+							&cableStatus->cableLen[MDI_TX_PAIR]);
+
+	return status;
+}
+
+static
+GT_STATUS  enable1stWorkAround_Phy100M
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     hwPort
+)
+{
+    GT_U16      value;
+    GT_STATUS   status;
+
+    /* enable 1st work-around */
+    if ((status = hwWritePhyReg(dev, hwPort, 29, 3)) != GT_OK)
+       return status;
+
+    value = 0x6440;
+    if ((status = hwWritePhyReg(dev, hwPort, 30, value)) != GT_OK)
+       return status;
+
+    return GT_OK;
+}
+
+static
+GT_STATUS  disable1stWorkAround_Phy100M
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     hwPort
+)
+{
+    GT_STATUS status;
+
+    /* disable 1st work-around */
+    if ((status = hwWritePhyReg(dev, hwPort, 29, 3)) != GT_OK)
+       return status;
+
+    if ((status = hwWritePhyReg(dev, hwPort, 30, 0)) != GT_OK)
+       return status;
+
+    return GT_OK;
+}
+
+static
+GT_STATUS workAround_Phy100M
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8            hwPort,
+    OUT GT_CABLE_STATUS *cableStatus
+)
+{
+	GT_STATUS status = GT_OK;
+
+	/* 
+	 * If Cable Status is OPEN and the length is less than 15m,
+	 * then apply Work Around.
+	 */
+
+	if((cableStatus->cableStatus[MDI_RX_PAIR] == GT_OPEN_CABLE) ||
+		(cableStatus->cableStatus[MDI_TX_PAIR] == GT_OPEN_CABLE))
+	{
+		/* must be disabled first and then enable again */
+        disable1stWorkAround_Phy100M(dev,hwPort);
+
+        enable1stWorkAround_Phy100M(dev,hwPort);
+
+		if((status= hwWritePhyReg(dev,hwPort,29,0x000A)) != GT_OK)
+		{
+			return status;
+		}
+		if((status= hwWritePhyReg(dev,hwPort,30,0x0002)) != GT_OK)
+		{
+			return status;
+		}
+
+		if((status = getCableStatus_Phy100M(dev,hwPort,cableStatus)) != GT_OK)
+		{
+			return status;
+		}
+		
+		if((status= hwWritePhyReg(dev,hwPort,29,0x000A)) != GT_OK)
+		{
+			return status;
+		}
+		if((status= hwWritePhyReg(dev,hwPort,30,0x0000)) != GT_OK)
+		{
+			return status;
+		}
+	}
+
+	return status;
+}
+
+
+static
+GT_STATUS  enable1stWorkAround_Phy1000M
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     hwPort
+)
+{
+    GT_STATUS   status;
+
+    /* enable 1st work-around */
+    if ((status = hwWritePhyReg(dev, hwPort, 29, 0x0018)) != GT_OK)
+       return status;
+
+    if ((status = hwWritePhyReg(dev, hwPort, 30, 0x00c2)) != GT_OK)
+       return status;
+
+    if ((status = hwWritePhyReg(dev, hwPort, 30, 0x00ca)) != GT_OK)
+       return status;
+
+    if ((status = hwWritePhyReg(dev, hwPort, 30, 0x00c2)) != GT_OK)
+       return status;
+
+    return GT_OK;
+}
+
+static
+GT_STATUS  disable1stWorkAround_Phy1000M
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8     hwPort
+)
+{
+    GT_STATUS status;
+
+    /* disable 1st work-around */
+    if ((status = hwWritePhyReg(dev, hwPort, 29, 0x0018)) != GT_OK)
+       return status;
+
+    if ((status = hwWritePhyReg(dev, hwPort, 30, 0x0042)) != GT_OK)
+       return status;
+
+    return GT_OK;
+}
+
+/*******************************************************************************
+* analizePhy1000MVCTResult
+*
+* DESCRIPTION:
+*       This routine analize the virtual cable test result for a Gigabit Phy
+*
+* INPUTS:
+*       reg17 - original value of register 17
+*       regValue - test result
+*
+* OUTPUTS:
+*       cableStatus - analized test result.
+*       cableLen    - cable length or the distance where problem occurs.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+static
+GT_STATUS analizePhy1000MVCTResult
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_U16 reg17,
+    IN  GT_U16 regValue, 
+    OUT GT_TEST_STATUS *cableStatus,
+    OUT GT_CABLE_LEN *cableLen
+)
+{
+	GT_U16 u16Data;
+	int len;
+
+	GT_UNUSED_PARAM(dev);
+
+	switch((regValue & 0x6000) >> 13)
+	{
+		case 0:
+
+			/* Check Impedance Mismatch */
+			if ((regValue & 0xFF) < 0xFF)
+			{
+				/*  if the reflected amplitude is low it is good cable too.
+					for this registers values it is a good cable:
+					0xE23, 0xE24, 0xE25, 0xE26, 0xE27 */
+				if ((regValue < 0xE23) || (regValue > 0xE27))
+				{
+					*cableStatus = GT_IMPEDANCE_MISMATCH;
+					len = (int)FORMULA_PHY1000M(regValue & 0xFF);
+					if(len <= 0)
+						cableLen->errCableLen = 0;
+					else
+						cableLen->errCableLen = (GT_U8)len;
+					break;
+				}
+			}
+
+			/* test passed. No problem found. */
+			*cableStatus = GT_NORMAL_CABLE;
+
+			u16Data = reg17;
+
+			/* To get Cable Length, Link should be on and Speed should be 100M or 1000M */
+			if(!(u16Data & 0x0400))
+			{
+				cableLen->normCableLen = GT_UNKNOWN_LEN;
+				break;
+			}
+
+			if((u16Data & 0xC000) != 0x8000)
+			{
+				cableLen->normCableLen = GT_UNKNOWN_LEN;
+				break;
+			}
+
+			/*
+			 * read the test result for the selected MDI Pair
+			 */
+
+			u16Data = ((u16Data >> 7) & 0x7);
+
+			switch(u16Data)
+			{
+				case 0:
+					cableLen->normCableLen = GT_LESS_THAN_50M;
+					break;
+				case 1:
+					cableLen->normCableLen = GT_50M_80M;
+					break;
+				case 2:
+					cableLen->normCableLen = GT_80M_110M;
+					break;
+				case 3:
+					cableLen->normCableLen = GT_110M_140M;
+					break;
+				case 4:
+					cableLen->normCableLen = GT_MORE_THAN_140;
+					break;
+				default:
+					cableLen->normCableLen = GT_UNKNOWN_LEN;
+					break;
+			}
+			break;
+		case 1:
+			/* test passed. Cable is short. */
+			*cableStatus = GT_SHORT_CABLE;
+			len = (int)FORMULA_PHY1000M(regValue & 0xFF);
+			if(len <= 0)
+				cableLen->errCableLen = 0;
+			else
+				cableLen->errCableLen = (GT_U8)len;
+			break;
+		case 2:
+			/* test passed. Cable is open. */
+			*cableStatus = GT_OPEN_CABLE;
+			len = (int)FORMULA_PHY1000M(regValue & 0xFF);
+			if(len <= 0)
+				cableLen->errCableLen = 0;
+			else
+				cableLen->errCableLen = (GT_U8)len;
+			break;
+		case 3:
+		default:
+			/* test failed. No result is valid. */
+			*cableStatus = GT_TEST_FAIL;
+			break;
+	}
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* getCableStatus_Phy1000M
+*
+* DESCRIPTION:
+*       This routine perform the virtual cable test for the 10/100Mbps phy,
+*       and returns the the status per Rx/Tx pair.
+*
+* INPUTS:
+*       port - logical port number.
+*		reg17 - original value of reg17.
+*
+* OUTPUTS:
+*       cableStatus - the port copper cable status.
+*       cableLen    - the port copper cable length.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+static 
+GT_STATUS getCableStatus_Phy1000M
+(	
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8			hwPort,
+    IN  GT_U16 			reg17,
+    OUT GT_CABLE_STATUS *cableStatus
+)
+{
+	GT_STATUS status;
+	GT_U16 reg28;
+	int i;
+
+    DBG_INFO(("getCableStatus_Phy1000M Called.\n"));
+
+	/* 
+	 * start Virtual Cable Tester
+	 */
+	if((status= hwWritePagedPhyReg(dev,hwPort,0,28,0,0x8000)) != GT_OK)
+	{
+		return status;
+	}
+
+	do
+	{
+		if((status= hwReadPhyReg(dev,hwPort,28,&reg28)) != GT_OK)
+		{
+			return status;
+		}
+		
+	} while(reg28 & 0x8000);
+
+	cableStatus->phyType = PHY_1000M;
+
+    DBG_INFO(("Reg28 after test : %0#x.\n", reg28));
+
+	for (i=0; i<GT_MDI_PAIR_NUM; i++)
+	{
+		/*
+		 * read the test result for the selected MDI Pair
+		 */
+		if((status= hwReadPagedPhyReg(dev,hwPort,(GT_U8)i,28,0,&reg28)) != GT_OK)
+		{
+			return status;
+		}
+		
+		/*
+		 * analyze the test result for RX Pair
+		 */
+		if((status = analizePhy1000MVCTResult(dev, reg17, reg28, 
+								&cableStatus->cableStatus[i], 
+								&cableStatus->cableLen[i])) != GT_OK)
+		{
+			return status;
+		}
+	}
+
+	return GT_OK;
+}
+
+static
+GT_STATUS workAround_Phy1000M
+(
+  GT_QD_DEV *dev,
+  GT_U8 hwPort
+)
+{
+	GT_STATUS status;
+
+    DBG_INFO(("workAround for Gigabit Phy Called.\n"));
+
+	if((status = hwWritePhyReg(dev,hwPort,29,0x1e)) != GT_OK)
+	{
+		return status;
+	}
+		
+	if((status = hwWritePhyReg(dev,hwPort,30,0xcc00)) != GT_OK)
+	{
+		return status;
+	}
+
+	if((status = hwWritePhyReg(dev,hwPort,30,0xc800)) != GT_OK)
+	{
+		return status;
+	}
+	if((status = hwWritePhyReg(dev,hwPort,30,0xc400)) != GT_OK)
+	{
+		return status;
+	}
+	if((status = hwWritePhyReg(dev,hwPort,30,0xc000)) != GT_OK)
+	{
+		return status;
+	}
+	if((status = hwWritePhyReg(dev,hwPort,30,0xc100)) != GT_OK)
+	{
+		return status;
+	}
+
+    DBG_INFO(("workAround for Gigabit Phy completed.\n"));
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* getCableStatus_Phy1000MPage
+*
+* DESCRIPTION:
+*       This routine perform the virtual cable test for the 10/100Mbps phy with
+*       multiple page mode and returns the the status per MDIP/N.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*       cableStatus - the port copper cable status.
+*       cableLen    - the port copper cable length.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+* GalTis:
+*
+*******************************************************************************/
+static 
+GT_STATUS getCableStatus_Phy1000MPage
+(	
+    IN  GT_QD_DEV *dev,
+    IN  GT_U8			hwPort,
+	IN  GT_PHY_INFO		*phyInfo,
+    OUT GT_CABLE_STATUS *cableStatus
+)
+{
+	GT_STATUS status;
+	GT_U16 u16Data;
+	GT_U16 reg17 = 0;
+	int i;
+
+    DBG_INFO(("getCableStatus_Phy1000M Called.\n"));
+
+	/*
+	 * If Fiber is used, simply return with test fail.
+	 */
+	if(phyInfo->flag & GT_PHY_FIBER)
+	{
+		if((status= hwReadPagedPhyReg(dev,hwPort,1,17,phyInfo->anyPage,&u16Data)) != GT_OK)
+		{
+			return status;
+		}
+
+		if(u16Data & 0x400)
+		{
+			for (i=0; i<GT_MDI_PAIR_NUM; i++)
+			{
+				cableStatus->cableStatus[i] = GT_TEST_FAIL;
+			}
+			return GT_OK;
+		}
+	}
+
+	/*
+	 * If Copper is used and Link is on, get DSP Distance and put it in the
+	 * old reg17 format.(bit9:7 with DSP Distance)
+	 */
+	if((status= hwReadPagedPhyReg(dev,hwPort,0,17,phyInfo->anyPage,&u16Data)) != GT_OK)
+	{
+		return status;
+	}
+
+	if(u16Data & 0x400)
+	{
+		reg17 = (u16Data & 0xC000) | 0x400;
+
+		if((status= hwReadPagedPhyReg(dev,hwPort,5,26,phyInfo->anyPage,&u16Data)) != GT_OK)
+		{
+			return status;
+		}
+		reg17 |= ((u16Data & 0x7) << 7);
+	}
+
+	/* 
+	 * start Virtual Cable Tester
+	 */
+	if((status= hwWritePagedPhyReg(dev,hwPort,5,16,phyInfo->anyPage,0x8000)) != GT_OK)
+	{
+		return status;
+	}
+
+	do
+	{
+		if((status= hwReadPagedPhyReg(dev,hwPort,5,16,phyInfo->anyPage,&u16Data)) != GT_OK)
+		{
+			return status;
+		}
+		
+	} while(u16Data & 0x8000);
+
+	cableStatus->phyType = PHY_1000M;
+
+    DBG_INFO(("Page 5 of Reg16 after test : %0#x.\n", u16Data));
+
+	for (i=0; i<GT_MDI_PAIR_NUM; i++)
+	{
+		/*
+		 * read the test result for the selected MDI Pair
+		 */
+		if((status= hwReadPagedPhyReg(dev,hwPort,5,(GT_U8)(16+i),phyInfo->anyPage,&u16Data)) != GT_OK)
+		{
+			return status;
+		}
+		
+		/*
+		 * analyze the test result for RX Pair
+		 */
+		if((status = analizePhy1000MVCTResult(dev, reg17, u16Data, 
+								&cableStatus->cableStatus[i], 
+								&cableStatus->cableLen[i])) != GT_OK)
+		{
+			return status;
+		}
+	}
+
+	return GT_OK;
+}
+
+
+
+/*******************************************************************************
+* gvctGetCableStatus
+*
+* DESCRIPTION:
+*       This routine perform the virtual cable test for the requested port,
+*       and returns the the status per MDI pair.
+*
+* INPUTS:
+*       port - logical port number.
+*
+* OUTPUTS:
+*       cableStatus - the port copper cable status.
+*       cableLen    - the port copper cable length.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       Internal Gigabit Phys in 88E6165 family and 88E6351 family devices
+*		are not supported by this API. For those devices, gvctGetAdvCableDiag 
+*		API can be used, instead.
+*
+*******************************************************************************/
+GT_STATUS gvctGetCableDiag
+(
+    IN  GT_QD_DEV *dev,
+    IN  GT_LPORT        port,
+    OUT GT_CABLE_STATUS *cableStatus
+)
+{
+	GT_STATUS status;
+	GT_U8 hwPort;
+	GT_U16 orgReg0, orgReg17;
+	GT_BOOL ppuEn;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+    DBG_INFO(("gvctGetCableDiag Called.\n"));
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* check if the port supports VCT */
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (!(phyInfo.flag & GT_PHY_VCT_CAPABLE))
+	{
+		DBG_INFO(("Not Supported\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Need to disable PPUEn for safe. */
+	if(gsysGetPPUEn(dev,&ppuEn) != GT_OK)
+	{
+		ppuEn = GT_FALSE;
+	}
+
+	if(ppuEn != GT_FALSE)
+	{
+		if((status= gsysSetPPUEn(dev,GT_FALSE)) != GT_OK)
+		{
+	    	DBG_INFO(("Not able to disable PPUEn.\n"));
+			gtSemGive(dev,dev->phyRegsSem);
+			return status;
+		}
+		gtDelay(250);
+	}
+		
+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	/*
+	 * save original register 17 value, which will be used later depending on
+	 * test result.
+	 */
+	if((status= hwReadPagedPhyReg(dev,hwPort,0,17,phyInfo.anyPage,&orgReg17)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to reset the Phy.\n"));
+		goto cableDiagCleanup;
+	}
+
+	/*
+	 * save Config Register data
+	 */
+	if((status= hwReadPagedPhyReg(dev,hwPort,0,0,phyInfo.anyPage,&orgReg0)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to reset the Phy.\n"));
+		goto cableDiagCleanup;
+	}
+
+	switch(phyInfo.vctType)
+	{
+		case GT_PHY_VCT_TYPE1:
+			enable1stWorkAround_Phy100M(dev,hwPort);
+			status = getCableStatus_Phy100M(dev,hwPort,cableStatus);
+            /* every fast ethernet phy requires this work-around */
+			workAround_Phy100M(dev,hwPort,cableStatus);
+			disable1stWorkAround_Phy100M(dev,hwPort);
+			break;
+		case GT_PHY_VCT_TYPE2:
+			enable1stWorkAround_Phy1000M(dev,hwPort);
+			status = getCableStatus_Phy1000M(dev,hwPort,orgReg17,cableStatus);
+			disable1stWorkAround_Phy1000M(dev,hwPort);
+			break;
+		case GT_PHY_VCT_TYPE3:
+			enable1stWorkAround_Phy1000M(dev,hwPort);
+			workAround_Phy1000M(dev,hwPort);
+			status = getCableStatus_Phy1000M(dev,hwPort,orgReg17,cableStatus);
+			disable1stWorkAround_Phy1000M(dev,hwPort);
+			break;
+		case GT_PHY_VCT_TYPE4:
+			status = getCableStatus_Phy1000MPage(dev,hwPort,&phyInfo,cableStatus);
+			break;
+		default:
+			status = GT_FAIL;
+			break;
+	}
+	
+	if (!(phyInfo.flag & GT_PHY_GIGABIT))
+	{
+		if((status = hwPhyReset(dev,hwPort,orgReg0)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return status;
+		}
+	}
+	else
+	{
+		/*
+		 * restore Config Register Data
+		 */
+		if((status= hwWritePagedPhyReg(dev,hwPort,0,0,phyInfo.anyPage,orgReg0)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return status;
+		}
+
+		/* soft reset */
+		if((status = hwPhyReset(dev,hwPort,0xFF)) != GT_OK)
+		{
+			gtSemGive(dev,dev->phyRegsSem);
+			return status;
+		}
+	}
+
+cableDiagCleanup:
+
+	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(ppuEn != GT_FALSE)
+	{
+		if(gsysSetPPUEn(dev,ppuEn) != GT_OK)
+		{
+	    	DBG_INFO(("Not able to enable PPUEn.\n"));
+			status = GT_FAIL;
+		}
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return status;	
+}
+
+
+/*******************************************************************************
+* getExStatus1000M
+*
+* DESCRIPTION:
+*       This routine retrieves Pair Skew, Pair Swap, and Pair Polarity
+*		for 1000M phy
+*
+* INPUTS:
+*       dev - device context.
+*       port - logical port number.
+*
+* OUTPUTS:
+*       extendedStatus - extended cable status.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+static GT_STATUS getExStatus1000M
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8           hwPort,
+    OUT GT_1000BT_EXTENDED_STATUS *extendedStatus
+)
+{
+	GT_STATUS status;
+	GT_U16 u16Data, i;
+
+	/*
+	 * get data from 28_5 register
+	 */
+	if((status= hwReadPagedPhyReg(dev,hwPort,5,28,0,&u16Data)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to read a Phy register.\n"));
+		return status;
+	}
+
+	/* if bit 6 is not set, it's not valid. */
+	if (!(u16Data & 0x0040))
+	{
+	    DBG_INFO(("Valid Bit is not set (%0#x).\n", u16Data));
+		extendedStatus->isValid = GT_FALSE;
+		return GT_OK;
+	}
+
+	extendedStatus->isValid = GT_TRUE;
+	
+	/* get Pair Polarity */
+	for(i=0; i<GT_MDI_PAIR_NUM; i++)
+	{
+		switch((u16Data >> i) & 0x1)
+		{
+			case 0:
+				extendedStatus->pairPolarity[i] = GT_POSITIVE;
+				break;
+			default:
+				extendedStatus->pairPolarity[i] = GT_NEGATIVE;
+				break;
+		}
+	}
+
+	/* get Pair Swap */
+	for(i=0; i<GT_CHANNEL_PAIR_NUM; i++)
+	{
+		switch((u16Data >> (i+4)) & 0x1)
+		{
+			case 0:
+				extendedStatus->pairSwap[i] = GT_STRAIGHT_CABLE;
+				break;
+			default:
+				extendedStatus->pairSwap[i] = GT_CROSSOVER_CABLE;
+				break;
+		}
+	}
+
+	/*
+	 * get data from 28_4 register
+	 */
+	if((status= hwReadPagedPhyReg(dev,hwPort,4,28,0,&u16Data)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to read a Phy register.\n"));
+		return status;
+	}
+
+	/* get Pair Skew */
+	for(i=0; i<GT_MDI_PAIR_NUM; i++)
+	{
+		extendedStatus->pairSkew[i] = ((u16Data >> i*4) & 0xF) * 8;
+	}
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* getExStatus1000MPage
+*
+* DESCRIPTION:
+*       This routine retrieves Pair Skew, Pair Swap, and Pair Polarity
+*		for 1000M phy with multiple page mode
+*
+* INPUTS:
+*       dev - device context.
+*       port - logical port number.
+*
+* OUTPUTS:
+*       extendedStatus - extended cable status.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+static GT_STATUS getExStatus1000MPage
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_U8	        hwPort,
+    OUT GT_1000BT_EXTENDED_STATUS *extendedStatus
+)
+{
+	GT_STATUS status;
+	GT_U16 u16Data, i;
+
+	/*
+	 * get data from 21_5 register for pair swap
+	 */
+	if((status= hwReadPagedPhyReg(dev,hwPort,5,21,0,&u16Data)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to read a paged Phy register.\n"));
+		return status;
+	}
+
+	/* if bit 6 is not set, it's not valid. */
+	if (!(u16Data & 0x0040))
+	{
+	    DBG_INFO(("Valid Bit is not set (%0#x).\n", u16Data));
+		extendedStatus->isValid = GT_FALSE;
+		return GT_OK;
+	}
+
+	extendedStatus->isValid = GT_TRUE;
+	
+	/* get Pair Polarity */
+	for(i=0; i<GT_MDI_PAIR_NUM; i++)
+	{
+		switch((u16Data >> i) & 0x1)
+		{
+			case 0:
+				extendedStatus->pairPolarity[i] = GT_POSITIVE;
+				break;
+			default:
+				extendedStatus->pairPolarity[i] = GT_NEGATIVE;
+				break;
+		}
+	}
+
+	/* get Pair Swap */
+	for(i=0; i<GT_CHANNEL_PAIR_NUM; i++)
+	{
+		switch((u16Data >> (i+4)) & 0x1)
+		{
+			case 0:
+				extendedStatus->pairSwap[i] = GT_STRAIGHT_CABLE;
+				break;
+			default:
+				extendedStatus->pairSwap[i] = GT_CROSSOVER_CABLE;
+				break;
+		}
+	}
+
+	/*
+	 * get data from 20_5 register for pair skew
+	 */
+	if((status= hwReadPagedPhyReg(dev,hwPort,5,20,0,&u16Data)) != GT_OK)
+	{
+	    DBG_INFO(("Not able to read a paged Phy register.\n"));
+		return status;
+	}
+
+	/* get Pair Skew */
+	for(i=0; i<GT_MDI_PAIR_NUM; i++)
+	{
+		extendedStatus->pairSkew[i] = ((u16Data >> i*4) & 0xF) * 8;
+	}
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gvctGet1000BTExtendedStatus
+*
+* DESCRIPTION:
+*       This routine retrieves Pair Skew, Pair Swap, and Pair Polarity
+*
+* INPUTS:
+*       dev - device context.
+*       port - logical port number.
+*
+* OUTPUTS:
+*       extendedStatus - extended cable status.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       Internal Gigabit Phys in 88E6165 family and 88E6351 family devices
+*		are not supported by this API. For those devices, gvctGetAdvExtendedStatus 
+*		API can be used, instead.
+*
+*******************************************************************************/
+GT_STATUS gvctGet1000BTExtendedStatus
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_LPORT        port,
+    OUT GT_1000BT_EXTENDED_STATUS *extendedStatus
+)
+{
+	GT_STATUS status;
+	GT_U8 hwPort;
+	GT_BOOL ppuEn;
+	GT_PHY_INFO	phyInfo;
+	GT_BOOL			autoOn;
+	GT_U16			pageReg;
+
+    DBG_INFO(("gvctGetCableDiag Called.\n"));
+	hwPort = GT_LPORT_2_PHY(port);
+
+	gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
+
+	/* check if the port is configurable */
+	if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* check if the port supports VCT */
+	if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
+	{
+	    DBG_INFO(("Unknown PHY device.\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if (!(phyInfo.flag & GT_PHY_EX_CABLE_STATUS))
+	{
+		DBG_INFO(("Not Supported\n"));
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_NOT_SUPPORTED;
+	}
+
+	/* Need to disable PPUEn for safe. */
+	if(gsysGetPPUEn(dev,&ppuEn) != GT_OK)
+	{
+		ppuEn = GT_FALSE;
+	}
+
+	if(ppuEn != GT_FALSE)
+	{
+		if((status= gsysSetPPUEn(dev,GT_FALSE)) != GT_OK)
+		{
+	    	DBG_INFO(("Not able to disable PPUEn.\n"));
+			gtSemGive(dev,dev->phyRegsSem);
+			return status;
+		}
+		gtDelay(250);
+	}
+
+	if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	switch(phyInfo.vctType)
+	{
+		case GT_PHY_VCT_TYPE2:
+			status = getExStatus1000M(dev,hwPort,extendedStatus);
+			break;
+		case GT_PHY_VCT_TYPE4:
+			status = getExStatus1000MPage(dev,hwPort,extendedStatus);
+			break;
+		default:
+	   		DBG_INFO(("Device is not supporting Extended Cable Status.\n"));
+			status = GT_NOT_SUPPORTED;
+	}
+
+	if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
+	{
+		gtSemGive(dev,dev->phyRegsSem);
+		return GT_FAIL;
+	}
+
+	if(ppuEn != GT_FALSE)
+	{
+		if(gsysSetPPUEn(dev,ppuEn) != GT_OK)
+		{
+	    	DBG_INFO(("Not able to enable PPUEn.\n"));
+			status = GT_FAIL;
+		}
+	}
+
+	gtSemGive(dev,dev->phyRegsSem);
+	return status;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtVersion.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtVersion.c
new file mode 100755
index 0000000..cf8ecd5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtVersion.c
@@ -0,0 +1,60 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtVersion.h
+*
+* DESCRIPTION:
+*       Includes software version information for the QuarterDeck software
+*       suite.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 1 $
+*
+*******************************************************************************/
+
+#include <msApi.h>
+
+char msApiCopyright[] = MSAPI_COPYRIGHT;
+char msApiVersion[] = MSAPI_VERSION;
+
+/*******************************************************************************
+* gtVersion
+*
+* DESCRIPTION:
+*       This function returns the version of the QuarterDeck SW suite.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       version     - QuarterDeck software version.
+*
+* RETURNS:
+*       GT_OK on success,
+*       GT_BAD_PARAM on bad parameters,
+*       GT_FAIL otherwise.
+*
+* COMMENTS:
+*
+*******************************************************************************/
+GT_STATUS gtVersion
+(
+    OUT GT_VERSION   *version
+)
+{
+    if(version == NULL)
+        return GT_BAD_PARAM;
+
+    if(gtStrlen(msApiVersion) > VERSION_MAX_LEN)
+    {
+        return GT_FAIL;
+    }
+
+    gtMemCpy(version->version,msApiVersion,gtStrlen(msApiVersion));
+    version->version[gtStrlen(msApiVersion)] = '\0';
+    return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtWeight.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtWeight.c
new file mode 100755
index 0000000..e2437d5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/gtWeight.c
@@ -0,0 +1,333 @@
+#include <Copyright.h>
+
+/********************************************************************************
+* gtWeight.c
+*
+* DESCRIPTION:
+*       API definitions for Round Robin Weight table access
+*
+* DEPENDENCIES:
+*
+* FILE REVISION NUMBER:
+*       $Revision: $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+#include <gtHwCntl.h>
+#include <gtDrvSwRegs.h>
+
+
+/*******************************************************************************
+* gsysSetQoSWeight
+*
+* DESCRIPTION:
+*       Programmable Round Robin Weights.
+*		Each port has 4 output Queues. Queue 3 has the highest priority and 
+*		Queue 0 has the lowest priority. When a scheduling mode of port is 
+*		configured as Weighted Round Robin queuing mode, the access sequece of the 
+*		Queue is 3,2,3,1,3,2,3,0,3,2,3,1,3,2,3 by default.
+*		This sequence can be configured with this API.
+*
+* INPUTS:
+*       weight - access sequence of the queue
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysSetQoSWeight
+(
+    IN  GT_QD_DEV 		*dev,
+    IN  GT_QoS_WEIGHT	*weight
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data;
+	GT_U32		len, i;
+
+    DBG_INFO(("gsysSetQoSWeight Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	if (weight->len > 128)
+	{
+        DBG_INFO(("GT_BAD_PARAM\n"));
+		return GT_BAD_PARAM;
+	}
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	len = weight->len/4;
+
+	/* program QoS Weight Table, 4 sequences at a time */
+
+	for(i=0; i<len; i++)
+	{
+	    /* Wait until the QoS Weight Table is ready. */
+    	data = 1;
+	    while(data == 1)
+    	{
+	        retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data);
+    	    if(retVal != GT_OK)
+        	{
+				gtSemGive(dev,dev->tblRegsSem);
+    	        return retVal;
+        	}
+	    }
+
+		data =  (GT_U16)((1 << 15) | (i << 8) | 
+				(weight->queue[i*4] & 0x3) |
+				((weight->queue[i*4+1] & 0x3) << 2) |
+				((weight->queue[i*4+2] & 0x3) << 4) |
+				((weight->queue[i*4+3] & 0x3) << 6));
+
+		retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
+	    if(retVal != GT_OK)
+    	{
+	   	    DBG_INFO(("Failed.\n"));
+            gtSemGive(dev,dev->tblRegsSem);
+    	    return retVal;
+	    }
+	}
+
+	/* program remaining sequences if any */
+	i = weight->len % 4;
+	if (i)
+	{
+	    /* Wait until the QoS Weight Table is ready. */
+    	data = 1;
+	    while(data == 1)
+    	{
+	        retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data);
+    	    if(retVal != GT_OK)
+        	{
+	            gtSemGive(dev,dev->tblRegsSem);
+    	        return retVal;
+        	}
+	    }
+		
+		data =  (GT_U16)((1 << 15) | (len << 8));
+		
+		switch (i)
+		{
+			case 3:
+				data |= ((weight->queue[len*4+2] & 0x3) << 4);
+			case 2:
+				data |= ((weight->queue[len*4+1] & 0x3) << 2);
+			case 1:
+				data |= ((weight->queue[len*4+0] & 0x3) << 0);
+				break;
+			default:
+		   	    DBG_INFO(("Should not come to this point.\n"));
+	            gtSemGive(dev,dev->tblRegsSem);
+				return GT_FALSE;
+		}
+
+		retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
+	    if(retVal != GT_OK)
+    	{
+	   	    DBG_INFO(("Failed.\n"));
+            gtSemGive(dev,dev->tblRegsSem);
+    	    return retVal;
+	    }
+	}
+
+	/* Write the lengh of the sequence */
+
+    /* Wait until the QoS Weight Table is ready. */
+   	data = 1;
+    while(data == 1)
+   	{
+        retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data);
+   	    if(retVal != GT_OK)
+       	{
+            gtSemGive(dev,dev->tblRegsSem);
+   	        return retVal;
+       	}
+    }
+
+	data =  (GT_U16)((1 << 15) | (0x20 << 8) | weight->len);
+		
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+   	    return retVal;
+    }
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gsysGetQoSWeight
+*
+* DESCRIPTION:
+*       Programmable Round Robin Weights.
+*		Each port has 4 output Queues. Queue 3 has the highest priority and 
+*		Queue 0 has the lowest priority. When a scheduling mode of port is 
+*		configured as Weighted Round Robin queuing mode, the access sequece of the 
+*		Queue is 3,2,3,1,3,2,3,0,3,2,3,1,3,2,3 by default.
+*		This routine retrieves the access sequence of the Queue.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       weight - access sequence of the queue
+*
+* RETURNS:
+*       GT_OK      - on success
+*       GT_FAIL    - on error
+*		GT_NOT_SUPPORTED - if current device does not support this feature.
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gsysGetQoSWeight
+(
+    IN  GT_QD_DEV 		*dev,
+    OUT GT_QoS_WEIGHT	*weight
+)
+{
+    GT_STATUS	retVal;         /* Functions return value.      */
+	GT_U16		data, i;
+	GT_U32		len;
+
+    DBG_INFO(("gsysGetQoSWeight Called.\n"));
+
+	/* Check if Switch supports this feature. */
+	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT))
+    {
+        DBG_INFO(("GT_NOT_SUPPORTED\n"));
+		return GT_NOT_SUPPORTED;
+    }
+
+	gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER);
+
+	/* Read the lengh of the sequence */
+
+    /* Wait until the QoS Weight Table is ready. */
+   	data = 1;
+    while(data == 1)
+   	{
+        retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data);
+   	    if(retVal != GT_OK)
+       	{
+			gtSemGive(dev,dev->tblRegsSem);
+   	        return retVal;
+       	}
+    }
+
+	data = (0x20 << 8);
+		
+	retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+   	    return retVal;
+    }
+
+	retVal = hwReadGlobal2Reg(dev, QD_REG_QOS_WEIGHT, &data);
+    if(retVal != GT_OK)
+   	{
+   	    DBG_INFO(("Failed.\n"));
+		gtSemGive(dev,dev->tblRegsSem);
+   	    return retVal;
+    }
+
+	weight->len = data & 0xFF;
+
+	len = weight->len/4;
+
+	/* read QoS Weight Table, 4 sequences at a time */
+
+	for(i=0; i<len; i++)
+	{
+		data = i << 8;
+
+		retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
+	    if(retVal != GT_OK)
+    	{
+	   	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+    	    return retVal;
+	    }
+
+		retVal = hwReadGlobal2Reg(dev, QD_REG_QOS_WEIGHT, &data);
+    	if(retVal != GT_OK)
+	   	{
+   		    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+   	    	return retVal;
+	    }
+
+		weight->queue[i*4] = data & 0x3;
+		weight->queue[i*4+1] = (data >> 2) & 0x3;
+		weight->queue[i*4+2] = (data >> 4) & 0x3;
+		weight->queue[i*4+3] = (data >> 6) & 0x3;
+
+	}
+
+	/* read remaining sequences if any */
+	i = (GT_U16) (weight->len % 4);
+	if (i)
+	{
+		data = (GT_U16)(len << 8);
+		
+		retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
+	    if(retVal != GT_OK)
+    	{
+	   	    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+    	    return retVal;
+	    }
+
+		retVal = hwReadGlobal2Reg(dev, QD_REG_QOS_WEIGHT, &data);
+    	if(retVal != GT_OK)
+	   	{
+   		    DBG_INFO(("Failed.\n"));
+			gtSemGive(dev,dev->tblRegsSem);
+   	    	return retVal;
+	    }
+
+		switch (i)
+		{
+			case 3:
+				weight->queue[len*4+2] = (data >> 4) & 0x3;
+			case 2:
+				weight->queue[len*4+1] = (data >> 2) & 0x3;
+			case 1:
+				weight->queue[len*4] = data & 0x3;
+				break;
+			default:
+		   	    DBG_INFO(("Should not come to this point.\n"));
+				gtSemGive(dev,dev->tblRegsSem);
+				return GT_FALSE;
+		}
+	}
+
+	gtSemGive(dev,dev->tblRegsSem);
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/makefile b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/makefile
new file mode 100755
index 0000000..96881a0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/msapi/makefile
@@ -0,0 +1,42 @@
+# Source files in this directory
+CSOURCES	= gtBrgFdb.c gtBrgStp.c gtBrgVlan.c \
+			gtEvents.c \
+			gtPortCtrl.c gtPortStat.c gtPortStatus.c \
+			gtQosMap.c gtPIRL.c	\
+			gtPhyCtrl.c gtPhyInt.c \
+			gtSysConfig.c gtSysCtrl.c gtVersion.c gtUtils.c \
+			gtBrgVtu.c gtPortRmon.c gtSysStatus.c \
+			gtPortRateCtrl.c gtPortPav.c gtVct.c gtAdvVct.c gtPCSCtrl.c \
+			gtBrgStu.c gtCCPVT.c gtPIRL2.c gtPolicy.c \
+			gtPriTable.c gtWeight.c gtPTP.c gtPortLed.c gtMisc.c
+
+ASOURCES	=
+
+# Include common variable definitions
+ifeq ($(OS_RUN),VXWORKS)
+include $(TOOL_DIR)\make.defs
+endif
+ifeq ($(OS_RUN),WIN32)
+include $(TOOL_DIR)\makewce.defs
+endif
+ifeq ($(OS_RUN),LINUX)
+include $(TOOL_DIR)/makelnx.defs
+endif
+
+# Add in extra stuffs
+EXTRA_INCLUDE	+=
+EXTRA_DEFINE	+=
+ADDED_CFLAGS	+=
+
+# Include common build rules
+ifeq ($(OS_RUN),VXWORKS)
+include $(TOOL_DIR)\make.rules
+endif
+ifeq ($(OS_RUN),WIN32)
+include $(TOOL_DIR)\makewce.rules
+endif
+ifeq ($(OS_RUN),LINUX)
+include $(TOOL_DIR)/makelnx.rules
+endif
+
+# end of file
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtDebug.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtDebug.c
new file mode 100755
index 0000000..4e24521
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtDebug.c
@@ -0,0 +1,79 @@
+#include <Copyright.h>
+/********************************************************************************
+* debug.c
+*
+* DESCRIPTION:
+*       Debug message display routine
+*
+* DEPENDENCIES:
+*       OS Dependent
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+#include <msApi.h>
+
+#ifdef DEBUG_QD
+#ifdef _VXWORKS
+#include "vxWorks.h"
+#include "logLib.h"
+#include "stdarg.h"
+#elif defined(WIN32)
+#include "windows.h"
+/* #include "wdm.h" */
+#elif defined(LINUX)
+#include "stdarg.h"
+#endif
+
+/*******************************************************************************
+* gtDbgPrint
+*
+* DESCRIPTION:
+*       .
+*
+* INPUTS:
+*       None
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+#if defined(_VXWORKS) || defined(WIN32) || defined(LINUX)
+void gtDbgPrint(char* format, ...)
+{
+    va_list argP;
+    char dbgStr[1000] = "";
+
+    va_start(argP, format);
+
+    vsprintf(dbgStr, format, argP);
+
+#ifdef _VXWORKS
+	printf("%s",dbgStr);
+/*	logMsg(dbgStr,0,1,2,3,4,5); */
+#elif defined(WIN32)
+	printf("%s",dbgStr);
+/*	DbgPrint(dbgStr);*/
+#elif defined(LINUX)
+	printk("%s",dbgStr);
+#endif
+	return;
+}
+#else
+void gtDbgPrint(char* format, ...)
+{
+	GT_UNUSED_PARAM(format);
+}
+#endif
+#else /* DEBUG_QD not defined */
+void gtDbgPrint(char* format, ...)
+{
+	GT_UNUSED_PARAM(format);
+}
+#endif /* DEBUG_QD */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtMiiSmiIf.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtMiiSmiIf.c
new file mode 100755
index 0000000..74500c1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtMiiSmiIf.c
@@ -0,0 +1,494 @@
+#include <Copyright.h>
+/********************************************************************************
+* gtMiiSmiIf.c
+*
+* DESCRIPTION:
+*       Includes functions prototypes for initializing and accessing the
+*       MII / SMI interface.
+*       This is the only file to be included from upper layers.
+*
+* DEPENDENCIES:
+*       None.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*
+*******************************************************************************/
+
+#include <gtDrvSwRegs.h>
+#include <gtHwCntl.h>
+#include <gtMiiSmiIf.h>
+#include <platformDeps.h>
+#include <gtSem.h>
+
+GT_BOOL qdMultiAddrRead (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int MIIReg,
+                        unsigned int* value);
+GT_BOOL qdMultiAddrWrite (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int MIIReg,
+                       unsigned int value);
+/*******************************************************************************
+* miiSmiIfInit
+*
+* DESCRIPTION:
+*       This function initializes the MII / SMI interface.
+*
+* INPUTS:
+*       None.
+*
+* OUTPUTS:
+*       highSmiDevAddr - Indicates whether to use the high device register
+*                     addresses when accessing switch's registers (of all kinds)
+*                     i.e, the devices registers range is 0x10 to 0x1F, or to
+*                     use the low device register addresses (range 0x0 to 0xF).
+*                       GT_TRUE     - use high addresses (0x10 to 0x1F).
+*                       GT_FALSE    - use low addresses (0x0 to 0xF).
+*
+* RETURNS:
+*       DEVICE_ID       - on success
+*       0    - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U16 miiSmiIfInit
+(
+	IN  GT_QD_DEV    *dev,
+	OUT GT_BOOL * highSmiDevAddr
+)
+{
+	GT_STATUS status;
+	GT_U16 data, data1;
+
+	if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR,QD_REG_SWITCH_ID,&data)) != GT_OK)
+	{
+		return 0;
+	}
+
+	if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR+1,QD_REG_SWITCH_ID,&data1)) != GT_OK)
+	{
+		return 0;
+	}
+
+	switch(data & 0xFF00)
+	{
+		case 0x0200:
+		case 0x0300:
+		case 0x0500:
+		case 0x0600:
+		case 0x1500:
+		case 0xF500:
+		case 0xF900:
+			if (data == data1)
+			{
+				*highSmiDevAddr = GT_FALSE;
+				return data;
+			}
+			break;
+		default:
+			break;
+	}
+
+	if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR+0x10,QD_REG_SWITCH_ID,&data)) != GT_OK)
+	{
+		return 0;
+	}
+
+	if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR+0x11,QD_REG_SWITCH_ID,&data1)) != GT_OK)
+	{
+		return 0;
+	}
+
+	switch(data & 0xFF00)
+	{
+		case 0x0200:
+		case 0x0300:
+		case 0x0500:
+		case 0x0600:
+		case 0x1500:
+		case 0xF500:
+		case 0xF900:
+			if (data == data1)
+			{
+				*highSmiDevAddr = GT_TRUE;
+				return data;
+			}
+			break;
+		default:
+			break;
+	}
+
+	if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR_8PORT,QD_REG_SWITCH_ID,&data)) != GT_OK)
+	{
+		return 0;
+	}
+
+	if((status = miiSmiIfReadRegister(dev,PORT_REGS_START_ADDR_8PORT+1,QD_REG_SWITCH_ID,&data1)) != GT_OK)
+	{
+		return 0;
+	}
+
+	switch(data & 0xFF00)
+	{
+		case 0x0800:
+		case 0x1A00:
+		case 0x1000:
+		case 0x0900:
+		case 0x0400:
+		case 0x1200:
+		case 0x1400:
+		case 0x1600:
+		case 0x1700:
+		case 0x3200:
+		case 0x3700:
+			if (data == data1)
+			{
+				*highSmiDevAddr = GT_FALSE;
+				return data;
+			}
+			break;
+		default:
+			break;
+	}
+
+    return 0;
+}
+
+
+/*******************************************************************************
+* miiSmiManualIfInit
+*
+* DESCRIPTION:
+*       This function returns Device ID from the given base address
+*
+* INPUTS:
+*       baseAddr - either 0x0 or 0x10. Indicates whether to use the low device 
+*					register address or high device register address.
+*					The device register range is from 0x0 to 0xF or from 0x10 
+*					to 0x1F for 5 port switchs and from 0x0 to 0x1B for 8 port 
+*					switchs.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       DEVICE_ID       - on success
+*       0    - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_U16 miiSmiManualIfInit
+(
+	IN  GT_QD_DEV   *dev,
+	IN  GT_U32		baseAddr
+)
+{
+	GT_STATUS status;
+	GT_U16 data;
+
+	if((status = miiSmiIfReadRegister(dev,(GT_U8)(PORT_REGS_START_ADDR+baseAddr),QD_REG_SWITCH_ID,&data)) != GT_OK)
+	{
+		return 0;
+	}
+
+	switch(data & 0xFF00)
+	{
+		case 0x0200:
+		case 0x0300:
+		case 0x0500:
+		case 0x0600:
+		case 0x1500:
+		case 0xF500:
+		case 0xF900:
+			return data;
+		default:
+			break;
+	}
+	if(baseAddr != 0)
+		return 0;
+
+	if((status = miiSmiIfReadRegister(dev,(GT_U8)(PORT_REGS_START_ADDR_8PORT+baseAddr),QD_REG_SWITCH_ID,&data)) != GT_OK)
+	{
+		return 0;
+	}
+
+	switch(data & 0xFF00)
+	{
+		case 0x0800:
+		case 0x1A00:
+		case 0x1000:
+		case 0x0900:
+		case 0x0400:
+		case 0x1200:
+		case 0x1400:
+		case 0x1600:
+		case 0x3200:
+		case 0x1700:
+		case 0x3700:
+			return data;
+		default:
+			break;
+	}
+
+    return 0;
+}
+
+
+/*******************************************************************************
+* miiSmiIfReadRegister
+*
+* DESCRIPTION:
+*       This function reads a register throw the SMI / MII interface, to be used
+*       by upper layers.
+*
+* INPUTS:
+*       phyAddr     - The PHY address to be read.
+*       regAddr     - The register address to read.
+*
+* OUTPUTS:
+*       data        - The register's data.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS miiSmiIfReadRegister
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U8        phyAddr,
+    IN  GT_U8        regAddr,
+    OUT GT_U16       *data
+)
+{
+    unsigned int tmpData;
+
+	if(dev->accessMode == SMI_MULTI_ADDR_MODE)
+	{
+     	if(qdMultiAddrRead(dev,(GT_U32)phyAddr,(GT_U32)regAddr,&tmpData) != GT_TRUE)
+	    {
+    	    return GT_FAIL;
+	    }
+	}
+    else
+	{
+     	if(dev->fgtReadMii(dev,(GT_U32)phyAddr,(GT_U32)regAddr,&tmpData) != GT_TRUE)
+	    {
+    	    return GT_FAIL;
+	    }
+	}
+    *data = (GT_U16)tmpData;
+    return GT_OK;
+}
+
+
+/*******************************************************************************
+* miiSmiIfWriteRegister
+*
+* DESCRIPTION:
+*       This function writes to a register throw the SMI / MII interface, to be
+*       used by upper layers.
+*
+* INPUTS:
+*       phyAddr     - The PHY address to be read.
+*       regAddr     - The register address to read.
+*       data        - The data to be written to the register.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_STATUS miiSmiIfWriteRegister
+(
+    IN  GT_QD_DEV    *dev,
+    IN  GT_U8        phyAddr,
+    IN  GT_U8        regAddr,
+    IN  GT_U16       data
+)
+{
+	if(dev->accessMode == SMI_MULTI_ADDR_MODE)
+	{
+     	if(qdMultiAddrWrite(dev,(GT_U32)phyAddr,(GT_U32)regAddr,(GT_U32)data) != GT_TRUE)
+	    {
+    	    return GT_FAIL;
+	    }
+	}
+    else
+	{
+	    if(dev->fgtWriteMii(dev,(GT_U32)phyAddr,(GT_U32)regAddr,(GT_U32)data) != GT_TRUE)
+	    {
+    	    return GT_FAIL;
+	    }
+	}
+	return GT_OK;
+}
+
+
+/*****************************************************************************
+* qdMultiAddrRead
+*
+* DESCRIPTION:
+*       This function reads data from a device in the secondary MII bus.
+*
+* INPUTS:
+*       phyAddr     - The PHY address to be read.
+*       regAddr     - The register address to read.
+*       value       - The storage where register date to be saved.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_TRUE   - on success
+*       GT_FALSE  - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_BOOL qdMultiAddrRead (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int regAddr,
+                        unsigned int* value)
+{
+	unsigned int smiReg;
+	volatile unsigned int timeOut; /* in 100MS units */
+	volatile int i;
+
+	/* first check that it is not busy */
+    if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
+    {
+        return GT_FALSE;
+    }
+    timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
+
+    if(smiReg & QD_SMI_BUSY) 
+    {
+        for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
+        do 
+        {
+            if(timeOut-- < 1 ) 
+            {
+    	        return GT_FALSE;
+    	    }
+		    if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
+		    {
+		        return GT_FALSE;
+		    }
+        } while (smiReg & QD_SMI_BUSY);
+    }
+
+    smiReg =  QD_SMI_BUSY | (phyAddr << QD_SMI_DEV_ADDR_BIT) | (QD_SMI_READ << QD_SMI_OP_BIT) | 
+    		(regAddr << QD_SMI_REG_ADDR_BIT) | (QD_SMI_CLAUSE22 << QD_SMI_MODE_BIT);
+
+    if(dev->fgtWriteMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, smiReg) != GT_TRUE)
+    {
+        return GT_FALSE;
+    }
+    timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
+    if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
+    {
+        return GT_FALSE;
+    }
+
+    if(smiReg & QD_SMI_BUSY) 
+    {
+        for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
+		do 
+		{
+            if(timeOut-- < 1 ) 
+            {
+    	        return GT_FALSE;
+    	    }
+		    if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
+		    {
+		        return GT_FALSE;
+		    }
+        } while (smiReg & QD_SMI_BUSY);
+	}
+    if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_DATA, &smiReg) != GT_TRUE)
+    {
+        return GT_FALSE;
+    }
+	*value = smiReg;
+    
+	return GT_TRUE;
+}
+
+/*****************************************************************************
+* qdMultiAddrWrite
+*
+* DESCRIPTION:
+*       This function writes data to the device in the secondary MII bus.
+*
+* INPUTS:
+*       phyAddr     - The PHY address to be read.
+*       regAddr     - The register address to read.
+*       value       - The data to be written into the register.
+*
+* OUTPUTS:
+*       None.
+*
+* RETURNS:
+*       GT_TRUE   - on success
+*       GT_FALSE  - on error
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+
+GT_BOOL qdMultiAddrWrite (GT_QD_DEV* dev, unsigned int phyAddr , unsigned int regAddr,
+                       unsigned int value)
+{
+	unsigned int smiReg;
+	volatile unsigned int timeOut; /* in 100MS units */
+	volatile int i;
+
+	/* first check that it is not busy */
+    if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
+    {
+        return GT_FALSE;
+    }
+    timeOut = QD_SMI_ACCESS_LOOP; /* initialize the loop count */
+
+    if(smiReg & QD_SMI_BUSY) 
+    {
+        for(i = 0 ; i < QD_SMI_TIMEOUT ; i++);
+        do 
+        {
+            if(timeOut-- < 1 ) 
+            {
+    	        return GT_FALSE;
+    	    }
+		    if(dev->fgtReadMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, &smiReg) != GT_TRUE)
+		    {
+		        return GT_FALSE;
+		    }
+        } while (smiReg & QD_SMI_BUSY);
+    }
+
+    if(dev->fgtWriteMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_DATA, value) != GT_TRUE)
+    {
+        return GT_FALSE;
+    }
+    smiReg = QD_SMI_BUSY | (phyAddr << QD_SMI_DEV_ADDR_BIT) | (QD_SMI_WRITE << QD_SMI_OP_BIT) | 
+			(regAddr << QD_SMI_REG_ADDR_BIT) | (QD_SMI_CLAUSE22 << QD_SMI_MODE_BIT);
+
+    if(dev->fgtWriteMii(dev,(GT_U32)dev->phyAddr,(GT_U32)QD_REG_SMI_COMMAND, smiReg) != GT_TRUE)
+    {
+        return GT_FALSE;
+    }
+
+    return GT_TRUE;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtSem.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtSem.c
new file mode 100755
index 0000000..dea85ff
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/gtSem.c
@@ -0,0 +1,149 @@
+#include <Copyright.h>
+/********************************************************************************
+* gtOs.c
+*
+* DESCRIPTION:
+*       Semaphore related routines
+*
+* DEPENDENCIES:
+*       OS Dependent.
+*
+* FILE REVISION NUMBER:
+*       $Revision: 3 $
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtSem.h>
+
+
+/*******************************************************************************
+* gtSemCreate
+*
+* DESCRIPTION:
+*       Create semaphore.
+*
+* INPUTS:
+*		state - beginning state of the semaphore, either GT_SEM_EMPTY or GT_SEM_FULL
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_SEM if success. Otherwise, NULL
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_SEM gtSemCreate
+(
+	IN GT_QD_DEV    *dev,
+	IN GT_SEM_BEGIN_STATE state
+)
+{
+	if(dev->semCreate)
+		return dev->semCreate(state);
+
+	return 1; /* should return any value other than 0 to let it keep going */
+}
+
+/*******************************************************************************
+* gtSemDelete
+*
+* DESCRIPTION:
+*       Delete semaphore.
+*
+* INPUTS:
+*       smid - semaphore Id
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtSemDelete
+(
+	IN GT_QD_DEV    *dev,
+	IN GT_SEM smid
+)
+{
+	if((dev->semDelete) && (smid))
+		return dev->semDelete(smid);
+
+	return GT_OK;
+}
+
+
+/*******************************************************************************
+* gtSemTake
+*
+* DESCRIPTION:
+*       Wait for semaphore.
+*
+* INPUTS:
+*       smid    - semaphore Id
+*       timeOut - time out in miliseconds or 0 to wait forever
+*
+* OUTPUTS:
+*       None
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*       OS_TIMEOUT - on time out
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtSemTake
+(
+	IN GT_QD_DEV    *dev,
+	IN GT_SEM smid, 
+	IN GT_U32 timeOut
+)
+{
+	if(dev->semTake)
+		return dev->semTake(smid, timeOut);
+
+	return GT_OK;
+
+}
+
+/*******************************************************************************
+* gtSemGive
+*
+* DESCRIPTION:
+*       release the semaphore which was taken previously.
+*
+* INPUTS:
+*       smid    - semaphore Id
+*
+* OUTPUTS:
+*       None
+*
+* RETURNS:
+*       GT_OK   - on success
+*       GT_FAIL - on error
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+GT_STATUS gtSemGive
+(
+	IN GT_QD_DEV    *dev,
+	IN GT_SEM       smid
+)
+{
+	if(dev->semGive)
+		return dev->semGive(smid);
+
+	return GT_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/makefile b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/makefile
new file mode 100755
index 0000000..40f8d03
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/makefile
@@ -0,0 +1,32 @@
+# Source files in this directory
+CSOURCES	= gtMiiSmiIf.c platformDeps.c gtSem.c gtDebug.c
+ASOURCES	=
+
+# Include common variable definitions
+ifeq ($(OS_RUN),VXWORKS)
+include $(TOOL_DIR)\make.defs
+endif
+ifeq ($(OS_RUN),WIN32)
+include $(TOOL_DIR)\makewce.defs
+endif
+ifeq ($(OS_RUN),LINUX)
+include $(TOOL_DIR)/makelnx.defs
+endif
+
+# Add in extra stuffs
+EXTRA_INCLUDE	+=
+EXTRA_DEFINE	+=
+ADDED_CFLAGS	+=
+
+# Include common build rules
+ifeq ($(OS_RUN),VXWORKS)
+include $(TOOL_DIR)\make.rules
+endif
+ifeq ($(OS_RUN),WIN32)
+include $(TOOL_DIR)\makewce.rules
+endif
+ifeq ($(OS_RUN),LINUX)
+include $(TOOL_DIR)/makelnx.rules
+endif
+
+# end of file
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/platformDeps.c b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/platformDeps.c
new file mode 100755
index 0000000..2290f0c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/src/platform/platformDeps.c
@@ -0,0 +1,90 @@
+#include <Copyright.h>
+/********************************************************************************
+* platformDeps.c
+*
+* DESCRIPTION:
+*       platform dependent functions
+*
+* DEPENDENCIES:   Platform.
+*
+* FILE REVISION NUMBER:
+*
+*******************************************************************************/
+
+#include <msApi.h>
+#include <gtDrvEvents.h>
+#include <gtHwCntl.h>
+#include <platformDeps.h>
+
+#if 0
+/*******************************************************************************
+* gtAssignFunctions
+*
+* DESCRIPTION:
+*       Exchange MII access functions and QuarterDeck Int Handler.
+*		MII access functions will be called by QuarterDeck driver and
+*		QD Int Handler should be called by BSP when BSP sees an interrupt which is related to
+*		QD (This interrupt has to be initialized by BSP, since QD has no idea which
+*		interrupt is assigned to QD)
+*
+* INPUTS:
+*       fReadMii 	- function to read MII registers
+*		fWriteMii	- functino to write MII registers
+*
+* OUTPUTS:
+*		None.
+*
+* RETURNS:
+*       GT_TRUE, if input is valid. GT_FALSE, otherwise.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+GT_BOOL gtAssignFunctions
+(
+   GT_QD_DEV      *dev,
+   FGT_READ_MII   fReadMii,
+   FGT_WRITE_MII fWriteMii
+)
+{
+	if((fReadMii == NULL) || (fWriteMii == NULL))
+		return GT_FALSE;
+
+	dev->fgtReadMii = fReadMii;
+	dev->fgtWriteMii = fWriteMii;
+	
+	return GT_TRUE;
+}
+
+#endif
+
+GT_BOOL defaultMiiRead (unsigned int portNumber , unsigned int miiReg, unsigned int* value)
+{
+	GT_UNUSED_PARAM(miiReg);
+
+	if (portNumber > GLOBAL_REGS_START_ADDR)
+		portNumber -= GLOBAL_REGS_START_ADDR;
+
+	if (portNumber > GLOBAL_REGS_START_ADDR)
+		return GT_FALSE;
+
+	*value = 0;
+
+	return GT_TRUE;
+}
+
+GT_BOOL defaultMiiWrite (unsigned int portNumber , unsigned int miiReg, unsigned int value)
+{
+	GT_UNUSED_PARAM(miiReg);
+
+	if (portNumber > GLOBAL_REGS_START_ADDR)
+		portNumber -= GLOBAL_REGS_START_ADDR;
+
+	if (portNumber > GLOBAL_REGS_START_ADDR)
+		return GT_FALSE;
+
+	value = value;
+
+	return GT_TRUE;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/make.defs b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/make.defs
new file mode 100755
index 0000000..822f752
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/make.defs
@@ -0,0 +1,107 @@
+# make.defs - common variable definitions
+#
+# modification history
+# --------------------
+# 04-12-02,mj	created
+#
+
+DEPENDENCIES=makedeps
+
+ifeq ($(TARGET_CPU),MIPS)
+
+CPU_TOOL=mips
+
+ifeq ($(TOR_VER),2.1)
+CPU=MIPS64
+CC_ARCH_SPEC1= -mips4 -G 0 -B$(VX_ROOT)/host/x86-win32/lib/gcc-lib/ -mno-branch-likely -fno-builtin -funroll-loops -Wall
+else
+CPU=R4000
+CC_ARCH_SPEC1= -mcpu=r4000 -mips3 -mgp32 -mfp32 -G 0 -B$(VX_ROOT)/host/x86-win32/lib/gcc-lib/
+endif
+
+ifeq ($(ENDIAN),EL)
+CC_ARCH_SPEC = -EL $(CC_ARCH_SPEC1)
+else
+CC_ARCH_SPEC = -EB $(CC_ARCH_SPEC1)
+endif
+
+# ARM CPU
+else
+
+CPU_TOOL=arm
+CPU		= ARMARCH4
+CC_ARCH_SPEC1 = -march=armv4 -mapcs-32
+
+ifeq ($(ENDIAN),LE)
+CC_ARCH_SPEC = $(CC_ARCH_SPEC1) -mlittle-endian
+else
+CC_ARCH_SPEC = $(CC_ARCH_SPEC1)
+endif
+
+endif
+
+TOOL       = gnu
+
+SW_ROOT = $(subst \,/,$(USER_BASE))
+SRC_BASE_PATH = $(SW_ROOT)/src
+QD_INCLUDE_PATH = $(SW_ROOT)/Include/h
+
+VX_ROOT = $(subst \,/,$(WIND_BASE))
+OS_INCLUDE_PATH = $(VX_ROOT)/target/h
+
+LIB_DIR = $(SW_ROOT)/library
+OBJDIR = obj
+
+CC      =cc$(CPU_TOOL)
+LD      =ld$(CPU_TOOL)
+MAKE    =make
+CD		=cd
+RM      =del
+ECHO	=echo
+
+CFLAGS = $(CFLAGS1) $(CFLAGS2) $(INCLUDE_PATH) $(CDEBUG_DEFINES)
+
+CFLAGS1 = -DCPU=$(CPU) -D_$(OS_RUN) $(CC_ARCH_SPEC) -g $(DEBUG_TYPE)
+CFLAGS2 = $(CC_OPTIM) $(CC_COMPILER) $(CC_WARNINGS_ALL)
+
+CC_OPTIM = $(CC_OPTIM_TARGET)
+
+ifeq ($(TARGET_CPU),MIPS)
+#CC_COMPILER	=  -ansi -nostdinc
+CC_COMPILER	=  -ansi
+else
+CC_COMPILER	=  -ansi -fdollars-in-identifiers -mno-sched-prolog -fvolatile
+endif
+
+CC_OPTIM_TARGET	= -O2 -funroll-loops -fno-for-scope -fno-builtin
+CC_WARNINGS_ALL	= -Wall
+
+ifeq ($(RELEASE),NO)
+CDEBUG_DEFINES=-DDEBUG=1 -DDEBUG_QD
+else
+CDEBUG_DEFINES=
+endif
+
+ifeq ($(TARGET_CPU),MIPS)
+LDFLAGS1 = -nostdlib -r -X -N
+ARFLAGS =  crus
+else
+#LDFLAGS	= -nostdlib -X -EL -r
+LDFLAGS1	= -nostdlib -X -N -r
+endif
+
+ifeq ($(ENDIAN),EL)
+LDFLAGS = $(LDFLAGS1) -EL
+else
+LDFLAGS = $(LDFLAGS1)
+endif
+
+
+INCLUDE_PATH = -I. \
+               -I$(QD_INCLUDE_PATH)/driver \
+               -I$(QD_INCLUDE_PATH)/msApi \
+               -I$(QD_INCLUDE_PATH)/platform \
+               -I$(SW_ROOT)/include \
+               -I$(OS_INCLUDE_PATH)
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/make.rules b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/make.rules
new file mode 100755
index 0000000..9208b04
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/make.rules
@@ -0,0 +1,54 @@
+# make.rules - common build rules
+#
+# modification history
+# --------------------
+# 04-15-02,mj	created
+#
+########################################################################
+ifeq ($(TARGET),)
+TARGET	= $(notdir $(subst \,/,$(shell cd)))
+endif
+default : $(TARGET).o
+
+# Set searching directories for target and dependencies
+vpath %.o    $(OBJDIR)
+
+# Include RULES file if it exists
+ifeq ($(shell if exist $(DEPENDENCIES) $(ECHO) 1),1)
+include $(DEPENDENCIES)
+endif
+
+# Accumulate source files specified in each directory makefile
+COBJECTS  	= $(CSOURCES:.c=.o)
+AOBJECTS  	= $(ASOURCES:.s=.o)
+ifeq ($(OBJECTS),)
+OBJECTS  	= $(COBJECTS) $(AOBJECTS)
+endif
+
+$(TARGET).o : $(OBJECTS) deps
+	@ $(ECHO) 'Building $@'
+	$(LD) $(LDFLAGS) -Map $(OBJDIR)/$(TARGET).map -o $(OBJDIR)/$(TARGET).o $(addprefix $(OBJDIR)/,$(notdir $(OBJECTS)))
+
+$(OBJECTS) : %.o : %.c
+.c.o :
+	@if not exist $(OBJDIR) mkdir $(OBJDIR)
+	$(CC) $(CFLAGS) $(EXTRA_DEFINE) $(EXTRA_INCLUDE) $(ADDED_CFLAGS) -c $< -o $(OBJDIR)/$(notdir $@)
+
+deps : $(CSOURCES)
+	@$(ECHO) '##' > $(DEPENDENCIES)
+	@$(ECHO) '## This file is generated by "make"!' >> $(DEPENDENCIES)
+	@$(ECHO) '##' >> $(DEPENDENCIES)
+	@for %x in ($^) do \
+	    @$(ECHO) '  %x' & \
+	     $(CC) -M -MG $(CFLAGS) %x >> $(DEPENDENCIES) & \
+	     @$(ECHO) '##' >> $(DEPENDENCIES)
+
+.PHONY: clean
+clean:
+	$(RM) $(DEPENDENCIES)
+	- ($(CD) $(OBJDIR)) && $(RM) *.o
+	- ($(CD) $(OBJDIR)) && $(RM) *.map
+
+FORCE :
+
+# end of file
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makelnx.defs b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makelnx.defs
new file mode 100755
index 0000000..2551436
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makelnx.defs
@@ -0,0 +1,52 @@
+# make.defs - common variable definitions
+#
+# modification history
+# --------------------
+# 04-12-02,mj	created
+#
+SHELL=/bin/sh -e
+
+CC_ARCH_SPEC=  -march=i386 -mcpu=i686
+
+SW_ROOT = $(USER_BASE)
+SRC_BASE_PATH = $(SW_ROOT)/src
+QD_INCLUDE_PATH = $(SW_ROOT)/Include/h
+
+LIB_DIR = $(SW_ROOT)/Library
+OBJDIR = obj
+
+CC      =cc
+LD      =ld
+MAKE    =make
+CD      =pwd
+RM      =rm -f
+ECHO    =echo
+
+DEPENDENCIES= makedeps
+
+CFLAGS = $(CFLAGS1) $(CFLAGS2) $(INCLUDE_PATH) $(CDEBUG_DEFINES)
+
+CFLAGS1 = $(CC_ARCH_SPEC) $(DEBUG_TYPE)
+CFLAGS2 = $(CC_OPTIM) $(CC_COMPILER) $(CC_WARNINGS_ALL)
+
+CC_OPTIM = $(CC_OPTIM_TARGET)
+CC_OPTIM_DRIVER	= -O
+CC_OPTIM_TARGET	= -O2
+CC_COMPILER = -ansi -nostdinc
+CC_WARNINGS_ALL	= -Wall
+
+ifeq ($(RELEASE),NO)
+CDEBUG_DEFINES=-DDEBUG=1 -DDEBUG_QD
+else
+CDEBUG_DEFINES=
+endif
+
+LDFLAGS = -nostdlib -r -X -N
+ARFLAGS = crus
+
+INCLUDE_PATH = -I. \
+               -I$(QD_INCLUDE_PATH)/driver \
+               -I$(QD_INCLUDE_PATH)/msApi \
+               -I$(QD_INCLUDE_PATH)/platform \
+               -I$(SW_ROOT)/Include
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makelnx.rules b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makelnx.rules
new file mode 100755
index 0000000..d91cfdf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makelnx.rules
@@ -0,0 +1,56 @@
+# make.rules - common build rules
+#
+# modification history
+# --------------------
+# 04-15-02,mj	created
+#
+########################################################################
+
+ifeq ($(TARGET),)
+TARGET	= $(notdir $(shell $(CD)))
+endif
+default : $(TARGET).o
+
+# Set searching directories for target and dependencies
+vpath %.o $(OBJDIR)
+
+# Include DEPENDENCIES file if it exists
+ifeq ($(shell if [ -a $(DEPENDENCIES) ]; then $(ECHO) 1; fi),1)
+include $(DEPENDENCIES)
+endif
+
+# Accumulate source files specified in each directory makefile
+COBJECTS  = $(CSOURCES:.c=.o)
+AOBJECTS  = $(ASOURCES:.s=.o)
+ifeq ($(OBJECTS),)
+OBJECTS  = $(COBJECTS) $(AOBJECTS)
+endif
+
+$(TARGET).o : $(OBJECTS) deps
+	@ $(ECHO) 'Building $@'
+	$(LD) $(LDFLAGS) -Map $(OBJDIR)/$(TARGET).map -o $(OBJDIR)/$(TARGET).o $(addprefix $(OBJDIR)/,$(notdir $(OBJECTS)))
+
+$(OBJECTS): %.o: %.c
+.c.o :
+	@if ! [ -a $(OBJDIR) ]; then mkdir $(OBJDIR); fi
+	$(CC) $(CFLAGS) $(EXTRA_DEFINE) $(EXTRA_INCLUDE) $(ADDED_CFLAGS) -c $< -o $(OBJDIR)/$(notdir $@)
+
+deps : $(CSOURCES)
+	@ $(ECHO) '##' > $(DEPENDENCIES)
+	@ $(ECHO) '## This file is generated by "make"!' >> $(DEPENDENCIES)
+	@ $(ECHO) '##' >> $(DEPENDENCIES)
+	@for i in $^ ; do \
+		$(ECHO) "  $$i"; \
+		$(CC) -M -MG $(CFLAGS) $$i >> $(DEPENDENCIES);  \
+		$(ECHO) '##' >> $(DEPENDENCIES);	\
+	done
+
+.PHONY: clean
+clean:
+	cd $(OBJDIR); $(RM) *.o
+	cd $(OBJDIR); $(RM) *.map
+	$(RM) $(DEPENDENCIES)
+
+FORCE :
+
+# end of file
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makewce.defs b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makewce.defs
new file mode 100755
index 0000000..17fc3a1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makewce.defs
@@ -0,0 +1,94 @@
+# makewce.defs - common variable definitions for wce
+#
+# modification history
+# --------------------
+# 04-24-02,mj	created
+#
+#######################################################################
+
+ifeq ($(TARGET),)
+TARGET	= $(notdir $(subst \,/,$(shell cd)))
+endif
+default : $(TARGET).lib
+
+SW_ROOT = $(subst \,/,$(USER_BASE))
+SRC_BASE_PATH = $(SW_ROOT)/src
+#INCLUDE_PATH = $(subst ;, -I,$(INCLUDE))
+
+LIB_DIR = $(SW_ROOT)/library
+OBJDIR = obj
+
+QD_INCLUDE_PATH = -I$(USER_BASE)\Include\h\driver \
+                  -I$(USER_BASE)\Include\h\msApi \
+                  -I$(USER_BASE)\Include\h\platform \
+                  -I$(USER_BASE)\Include
+
+MAKE    =make
+CD		=cd
+RM      =del
+ECHO	=echo
+LD      =lib
+
+ifeq ($(TARGETCPU),MIPSIV)
+CC      =clmips
+
+TGTCPUFAMILY=MIPS
+TGTCPUDEFINES=-D$(TGTCPUFAMILY) -D_MIPS_ -DR4000
+
+ifeq ($(RELEASE),NO)
+CDEBUG_DEFINES=-DDEBUG=1 -DDEBUG_QD
+CDEBUG_FLAGS=-Od
+else
+CDEBUG_DEFINES=
+CDEBUG_FLAGS=
+endif
+
+
+CDEFINES1=-DUNDER_CE -D_WIN32_WCE=400
+CDEFINES=-DWIN32 -DSTRICT $(TGTCPUDEFINES) $(CDEBUG_DEFINES) $(CDEFINES1)
+
+#CINCLUDES=-I. -I$(INCLUDE_PATH) -I$(QD_INCLUDE_PATH)
+CINCLUDES=-I. $(QD_INCLUDE_PATH)
+
+CFLAGS1= -W3 -c -QMFPE -nologo -QMmips2 -Gy
+#CFLAGS1= -W3 -Og -Oi -Os -Ob1 -YX -Gs8192 -c
+#CFLAGS2= -FAsc -Fa$(@R).cod -WX
+
+CFLAGS= $(CFLAGS1) $(CINCLUDES) $(CDEBUG_FLAGS) $(CDEFINES)
+
+LINKER_SUBSYSTEM=-subsystem:windowsce,4.00
+MACHINEOPTION=-machine:MIPS
+
+LDFLAGS = -nologo -nodefaultlib $(LINKER_SUBSYSTEM) $(TARGETOBJFILES) $(SOURCELIBS) $(MACHINEOPTION)
+
+else
+CC      =cl
+
+TGTCPUFAMILY=x86
+TGTCPUDEFINES=-D$(TGTCPUFAMILY) -D_X86_
+
+ifeq ($(RELEASE),NO)
+CDEBUG_DEFINES=-DDEBUG=1 -DDEBUG_QD
+CDEBUG_FLAGS=-Od
+else
+CDEBUG_DEFINES=
+CDEBUG_FLAGS=-Og
+endif
+
+CDEFINES1=-DUNDER_CE -D_WIN32_WCE=400
+CDEFINES=-DWIN32 -DSTRICT $(TGTCPUDEFINES) $(CDEBUG_DEFINES) $(CDEFINES1)
+
+#CINCLUDES=-I. -I$(INCLUDE_PATH) -I$(QD_INCLUDE_PATH)
+CINCLUDES=-I. $(QD_INCLUDE_PATH)
+
+CFLAGS1= -W3 -Oi -Os -Ob1 -YX -Gs8192 -c
+#CFLAGS2= -FAsc -Fa$(@R).cod -WX
+
+CFLAGS= $(CFLAGS1) $(CINCLUDES) $(CDEBUG_FLAGS) $(CDEFINES)
+
+LINKER_SUBSYSTEM=-subsystem:windowsce,4.00
+MACHINEOPTION=-machine:IX86
+
+LDFLAGS = -nologo -nodefaultlib $(LINKER_SUBSYSTEM) $(TARGETOBJFILES) $(SOURCELIBS) $(MACHINEOPTION)
+
+endif
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makewce.rules b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makewce.rules
new file mode 100755
index 0000000..925630b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/makewce.rules
@@ -0,0 +1,50 @@
+# makewce.rules - common build rules for wce
+#
+# modification history
+# --------------------
+# 04-25-02,mj	created
+#
+########################################################################
+
+# Set searching directories for target and dependencies
+vpath %.obj    $(OBJDIR)
+
+# Include RULES file if it exists
+#ifeq ($(shell if exist RULES $(ECHO) 1),1)
+#include RULES
+#endif
+
+# Accumulate source files specified in each directory makefile
+COBJECTS  	= $(CSOURCES:.c=.obj)
+AOBJECTS  	= $(ASOURCES:.s=.obj)
+ifeq ($(OBJECTS),)
+OBJECTS  	= $(COBJECTS) $(AOBJECTS)
+endif
+
+$(TARGET).lib : $(OBJECTS) $(CSOURCES)
+	@ $(ECHO) 'Building $@'
+	$(LD) $(LDFLAGS) -ignore:4001 -out:$(OBJDIR)\$(TARGET).lib $(addprefix $(OBJDIR)\,$(notdir $(OBJECTS)))
+
+$(OBJECTS) : %.obj : %.c
+	@if not exist $(OBJDIR) mkdir $(OBJDIR)
+	$(CC) $(CFLAGS) $(EXTRA_DEFINE) $(EXTRA_INCLUDE) $(ADDED_CFLAGS) -c $< -Fo$(OBJDIR)\$(notdir $@) 
+
+#deps : $(CSOURCES)
+#	@$(ECHO) '##' >> RULES
+#	@$(ECHO) '## This file is generated by \"make\" - DO NOT EDIT !' >> RULES
+#	@$(ECHO) '## $(shell $(DATE))' >> RULES
+#	@$(ECHO) '##' >> RULES
+#	@for %x in ($^) do \
+#	    @$(ECHO) "  %x" & \
+#	     $(CC) -M -MG $(CFLAGS) %x >> RULES & \
+#	     $(ECHO) >> RULES
+
+.PHONY: clean
+clean:
+	- ($(CD) $(OBJDIR)) && $(RM) *.obj
+	- ($(CD) $(OBJDIR)) && $(RM) *.lib
+
+FORCE :
+
+# end of file
+
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/setenv b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/setenv
new file mode 100755
index 0000000..0dba986
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/setenv
@@ -0,0 +1,5 @@
+declare -x USER_BASE=$HOME/DSDT_2.8a
+declare -x PROJ_NAME=qdDrv
+declare -x TOOL_DIR=$USER_BASE/tools
+declare -x RELEASE=YES
+declare -x OS_RUN=LINUX
diff --git a/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/setenv.bat b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/setenv.bat
new file mode 100755
index 0000000..48407d8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/qd-dsdt/tools/setenv.bat
@@ -0,0 +1,55 @@
+@echo off
+set REQ_OS=%1
+
+if "%REQ_OS%"==""        set OS_RUN=VXWORKS
+if "%REQ_OS%"=="VXWORKS" set OS_RUN=VXWORKS
+if "%REQ_OS%"=="vxworks" set OS_RUN=VXWORKS
+if "%REQ_OS%"=="vxWorks" set OS_RUN=VXWORKS
+if "%REQ_OS%"=="win32"   set OS_RUN=WIN32
+if "%REQ_OS%"=="WIN32"   set OS_RUN=WIN32
+if "%REQ_OS%"=="wince"   set OS_RUN=WIN32
+if "%REQ_OS%"=="WINCE"   set OS_RUN=WIN32
+
+set USER_BASE=C:\DSDT_2.8a
+set PROJ_NAME=qdDrv
+set TOOL_DIR=%USER_BASE%\tools
+set RELEASE=YES
+set TARGET_CPU=ARM
+rem set TARGET_CPU=MIPS
+
+if "%OS_RUN%"=="VXWORKS" goto VXWORKS_ENV
+if "%OS_RUN%"=="WIN32" goto WIN32_ENV
+
+echo Unknown Target OS!
+echo Supported Target OS is vxworks and wince.
+echo Assumes VxWorks as a Target OS.
+
+:VXWORKS_ENV
+
+set TOR_VER=2.1
+set ENDIAN=EL
+set WIND_BASE=C:\Tornado.arm
+rem set WIND_BASE=C:\Tornado2.1
+set WIND_HOST_TYPE=x86-win32
+
+set PATH=%WIND_BASE%\host\%WIND_HOST_TYPE%\bin;%PATH%
+
+echo Environment Variable for VxWorks has been set.
+
+goto DONE
+
+:WIN32_ENV
+
+set TARGETCPU=MIPSIV
+rem set TARGETCPU=x86
+set WCEROOT=C:\WINCE400
+
+set INCLUDE=%WCEROOT%\public\common\oak\inc;%WCEROOT%\public\common\sdk\inc;%WCEROOT%\public\common\ddk\inc;%INCLUDE%
+set PATH=%WCEROOT%\sdk\bin\i386;%WCEROOT%\public\common\oak\bin\i386;%USER_BASE%\tools;%path%
+
+echo Environment Variable for WinCE has been set.
+goto DONE
+
+:DONE
+cd %USER_BASE%\src
+
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339.c b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339.c
new file mode 100755
index 0000000..5518e23
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339.c
@@ -0,0 +1,321 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+/* includes */
+#include "rtc/ext_rtc/mvDS1339.h"
+#include "rtc/ext_rtc/mvDS1339Reg.h"
+
+static MV_VOID mvRtcCharWrite(MV_U32 offset, MV_U8 data);
+static MV_VOID mvRtcCharRead(MV_U32 offset, MV_U8 *data);
+
+
+/*******************************************************************************
+* mvRtcDS1339TimeSet - Set the Alarm of the Real time clock
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       time - A pointer to a structure RTC_TIME (defined in mvDS1339.h).
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS1339AlarmSet(MV_RTC_TIME *mvTime)
+{
+	return;
+}
+/*******************************************************************************
+* mvRtcDS1339TimeSet - Update the Real Time Clock.
+*
+* DESCRIPTION:
+*       This function sets a new time and date to the RTC from the given
+*       structure RTC_TIME . All fields within the structure must be assigned
+*		with a value prior to the use of this function.
+*
+* INPUT:
+*       time - A pointer to a structure RTC_TIME (defined in mvDS1339.h).
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS1339TimeSet(MV_RTC_TIME *mvTime)
+{
+	MV_U8 tempValue;
+	MV_U8 tens;
+	MV_U8 single;
+
+	/* seconds */
+	tens = mvTime->seconds / 10;
+	single = mvTime->seconds % 10;
+	tempValue = ((tens  << RTC_CLOCK_10SECONDS_SHF) & RTC_CLOCK_10SECONDS_MSK) |
+				((single << RTC_CLOCK_SECONDS_SHF) & RTC_CLOCK_SECONDS_MSK) ;
+	mvRtcCharWrite(RTC_CLOCK_SECONDS, tempValue);
+
+	/* minutes */
+	tens = mvTime->minutes / 10;
+	single = mvTime->minutes % 10;
+	tempValue = ((tens  << RTC_CLOCK_10MINUTES_SHF) & RTC_CLOCK_10MINUTES_MSK) |
+			    ((single << RTC_CLOCK_MINUTES_SHF) & RTC_CLOCK_MINUTES_MSK) ;
+	mvRtcCharWrite(RTC_CLOCK_MINUTES, tempValue);
+
+	/* hours (24) */
+	tens = mvTime->hours / 10;
+	single = mvTime->hours % 10;
+	tempValue = ((tens << RTC_CLOCK_10HOURS_SHF) & RTC_CLOCK_10HOURS_MSK2) |
+				((single << RTC_CLOCK_HOURS_SHF) & RTC_CLOCK_HOURS_MSK);
+	mvRtcCharWrite(RTC_CLOCK_HOUR, tempValue);
+
+	/* day */
+	single = mvTime->day;
+	tempValue = ((single << RTC_CLOCK_DAY_SHF) & RTC_CLOCK_DAY_MSK) ;
+	mvRtcCharWrite(RTC_CLOCK_DAY, tempValue);
+
+	/* date */
+	tens = mvTime->date / 10;
+	single = mvTime->date % 10;
+	tempValue = ((tens << RTC_CLOCK_10DATE_SHF) & RTC_CLOCK_10DATE_MSK) |
+				((single << RTC_CLOCK_DATE_SHF) & RTC_CLOCK_DATE_MSK) ;
+
+	/* month */
+	mvRtcCharWrite(RTC_CLOCK_DATE, tempValue);
+	tens = mvTime->month / 10;
+	single = mvTime->month % 10;
+	tempValue = ((tens << RTC_CLOCK_10MONTH_SHF) & RTC_CLOCK_10MONTH_MSK) |
+				((single << RTC_CLOCK_MONTH_SHF) & RTC_CLOCK_MONTH_MSK);
+	mvRtcCharWrite(RTC_CLOCK_MONTH_CENTURY, tempValue);
+
+	/* year */
+	tens = mvTime->year / 10;
+	single = mvTime->year % 10;
+	tempValue = ((tens << RTC_CLOCK_10YEAR_SHF) & RTC_CLOCK_10YEAR_MSK) |
+				((single << RTC_CLOCK_YEAR_SHF) & RTC_CLOCK_YEAR_MSK);
+	mvRtcCharWrite(RTC_CLOCK_YEAR, tempValue);
+
+	return;
+}
+
+/*******************************************************************************
+* mvRtcDS1339TimeGet - Read the time from the RTC.
+*
+* DESCRIPTION:
+*       This function reads the current time and date from the RTC into the
+*       structure RTC_TIME (defined in mvDS1339.h).
+*
+* INPUT:
+*       time - A pointer to a structure TIME (defined in mvDS1339.h).
+*
+* OUTPUT:
+*       The structure RTC_TIME is updated with the time read from the RTC.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS1339TimeGet(MV_RTC_TIME *mvTime)
+{
+	MV_U8 tempValue;
+	MV_U32 tens;
+	MV_U32 single;
+
+	/* seconds */
+	mvRtcCharRead(RTC_CLOCK_SECONDS, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10SECONDS_MSK) >> RTC_CLOCK_10SECONDS_SHF;
+	single = (tempValue & RTC_CLOCK_SECONDS_MSK) >> RTC_CLOCK_SECONDS_SHF ;
+	mvTime->seconds = 10*tens + single;
+
+	/* minutes */
+	mvRtcCharRead(RTC_CLOCK_MINUTES, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10MINUTES_MSK) >> RTC_CLOCK_10MINUTES_SHF;
+	single = (tempValue & RTC_CLOCK_MINUTES_MSK) >> RTC_CLOCK_MINUTES_SHF;
+	mvTime->minutes = 10*tens + single;
+
+	/* hours */
+	mvRtcCharRead(RTC_CLOCK_HOUR, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10HOURS_MSK2) >> RTC_CLOCK_10HOURS_SHF;
+	single = (tempValue & RTC_CLOCK_HOURS_MSK) >> RTC_CLOCK_HOURS_SHF;
+	mvTime->hours = 10*tens + single;
+
+	/* day */
+	mvRtcCharRead(RTC_CLOCK_DAY, &tempValue);
+	mvTime->day = (tempValue & RTC_CLOCK_DAY_MSK) >> RTC_CLOCK_DAY_SHF ;
+
+	/* date */
+	mvRtcCharRead(RTC_CLOCK_DATE, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10DATE_MSK) >> RTC_CLOCK_10DATE_SHF;
+	single = (tempValue & RTC_CLOCK_DATE_MSK) >> RTC_CLOCK_DATE_SHF;
+	mvTime->date = 10*tens + single;
+
+	/* century/ month */
+	mvRtcCharRead(RTC_CLOCK_MONTH_CENTURY, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10MONTH_MSK) >> RTC_CLOCK_10MONTH_SHF;
+	single = (tempValue & RTC_CLOCK_MONTH_MSK) >> RTC_CLOCK_MONTH_SHF;
+	mvTime->month = 10*tens + single;
+	mvTime->century = (tempValue & RTC_CLOCK_CENTURY_MSK)>>RTC_CLOCK_CENTURY_SHF;
+
+	/* year */
+	mvRtcCharRead(RTC_CLOCK_YEAR, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10YEAR_MSK) >> RTC_CLOCK_10YEAR_SHF;
+	single = (tempValue & RTC_CLOCK_YEAR_MSK) >> RTC_CLOCK_YEAR_SHF;
+	mvTime->year = 10*tens + single;
+
+	return;
+}
+
+/*******************************************************************************
+* mvRtcDS1339Init - Initialize the clock.
+*
+* DESCRIPTION:
+*       This function initialize the clock registers and read\write functions
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS1339Init(MV_VOID)
+{
+	MV_U8 ucTemp;
+
+	/* We will disable interrupts as default .*/
+	mvRtcCharRead(RTC_CONTROL, &ucTemp);
+	ucTemp |= RTC_CONTROL_INTCN_BIT;
+	mvRtcCharWrite(RTC_CONTROL, ucTemp);
+
+	/* disable trickle */
+	mvRtcCharWrite(RTC_TRICKLE_CHARGE, 0);
+
+	return;
+}
+
+
+/* assumption twsi is initialized !!! */
+/*******************************************************************************
+* mvRtcCharRead - Read a char from the RTC.
+*
+* DESCRIPTION:
+*       This function reads a char from the RTC offset.
+*
+* INPUT:
+*       offset - offset
+*
+* OUTPUT:
+*       data - char read from offset offset.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID	mvRtcCharRead(MV_U32 offset, MV_U8 *data)
+{
+	MV_TWSI_SLAVE   twsiSlave;
+
+	twsiSlave.slaveAddr.type = mvBoardRtcTwsiAddrTypeGet();
+	twsiSlave.slaveAddr.address = mvBoardRtcTwsiAddrGet();
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = offset;
+	twsiSlave.moreThen256 = MV_FALSE;
+	mvTwsiRead(MV_BOARD_RTC_I2C_CHANNEL, &twsiSlave, data, 1);
+	return;
+}
+
+/*******************************************************************************
+* mvRtcCharWrite - Write a char from the RTC.
+*
+* DESCRIPTION:
+*       This function writes a char to the RTC offset.
+*
+* INPUT:
+*       offset - offset
+*
+* OUTPUT:
+*       data - char write to addr address.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID mvRtcCharWrite(MV_U32 offset, MV_U8 data)
+{
+	MV_TWSI_SLAVE twsiSlave;
+
+	twsiSlave.slaveAddr.type = mvBoardRtcTwsiAddrTypeGet();
+	twsiSlave.slaveAddr.address = mvBoardRtcTwsiAddrGet();
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = offset;
+	twsiSlave.moreThen256 = MV_FALSE;
+	mvTwsiWrite(MV_BOARD_RTC_I2C_CHANNEL, &twsiSlave, &data, 1);
+	return;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339.h b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339.h
new file mode 100755
index 0000000..0800551
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339.h
@@ -0,0 +1,103 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __INCmvDS1339h
+#define __INCmvDS1339h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvTypes.h"
+#include "twsi/mvTwsi.h"
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "boardEnv/mvBoardEnvSpec.h"
+
+typedef struct time {
+	MV_U8  seconds;
+	MV_U8  minutes;
+	MV_U8  hours;
+	MV_U8  day;
+	MV_U8  date;
+	MV_U8  month;
+	MV_U8  century;
+	MV_U8  year;
+} MV_RTC_TIME;
+
+MV_VOID mvRtcDS1339Init(MV_VOID);
+
+MV_VOID mvRtcDS1339TimeSet(MV_RTC_TIME *time);
+
+MV_VOID mvRtcDS1339TimeGet(MV_RTC_TIME *time);
+
+MV_VOID mvRtcDS1339AlarmSet(MV_RTC_TIME *time);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif  /* __INCmvDS1511h */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339Reg.h b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339Reg.h
new file mode 100755
index 0000000..0e1931a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS1339Reg.h
@@ -0,0 +1,376 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __INCmvDS1339Regh
+#define __INCmvDS1339Regh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MSK
+#define MSK(n)						((1 << (n)) - 1)
+#endif
+
+#define RTC_CLOCK_SECONDS			0x0
+#define RTC_CLOCK_MINUTES			0x1
+#define RTC_CLOCK_HOUR				0x2
+#define RTC_CLOCK_DAY				0x3
+#define RTC_CLOCK_DATE				0x4
+#define RTC_CLOCK_MONTH_CENTURY		0x5
+#define RTC_CLOCK_YEAR				0x6
+#define RTC_ALARM_SECONDS			0x7
+#define RTC_ALARM_MINUTES			0x8
+#define RTC_ALARM_HOUR				0x9
+#define RTC_ALARM_DAY_DATE			0xa
+#define RTC_ALARM2_MINUTES			0xb
+#define RTC_ALARM2_HOUR				0xc
+#define RTC_ALARM2_DAY_DATE 		0xd
+#define RTC_CONTROL					0xe
+#define RTC_STATUS					0xf
+#define RTC_TRICKLE_CHARGE			0x10
+
+#define FIRST_REG_OFF				RTC_CLOCK_SECONDS
+#define LAST_REG_OFF				RTC_TRICKLE_CHARGE
+
+
+/* RTC_CLOCK_SECONDS   0x0*/
+
+#define RTC_CLOCK_SECONDS_SHF		0
+#define RTC_CLOCK_SECONDS_MSK		(MSK(4)<<RTC_CLOCK_SECONDS_SHF)
+
+#define RTC_CLOCK_10SECONDS_SHF		4
+#define RTC_CLOCK_10SECONDS_MSK		(MSK(3)<<RTC_CLOCK_10SECONDS_SHF)
+
+/* RTC_CLOCK_MINUTES   0x1*/
+
+#define RTC_CLOCK_MINUTES_SHF		0
+#define RTC_CLOCK_MINUTES_MSK		(MSK(4)<<RTC_CLOCK_MINUTES_SHF)
+
+#define RTC_CLOCK_10MINUTES_SHF		4
+#define RTC_CLOCK_10MINUTES_MSK		(MSK(3)<<RTC_CLOCK_10MINUTES_SHF)
+
+/* RTC_CLOCK_HOUR      0x2*/
+
+#define RTC_CLOCK_HOURS_SHF				0
+#define RTC_CLOCK_HOURS_MSK				(MSK(4)<<RTC_CLOCK_HOURS_SHF)
+
+#define RTC_CLOCK_10HOURS_SHF			4
+#define RTC_CLOCK_10HOURS_MSK1			(MSK(1)<<RTC_CLOCK_10HOURS_SHF)
+#define RTC_CLOCK_10HOURS_MSK2			(MSK(2)<<RTC_CLOCK_10HOURS_SHF)
+#define RTC_CLOCK_10HOURS_BIT			BIT4
+
+#define RTC_CLOCK_10HOURSAMPM_SHF		5
+#define RTC_CLOCK_10HOURSAMPM_MSK		(MSK(1)<<RTC_CLOCK_10HOURSAMPM_SHF)
+#define RTC_CLOCK_10HOURSAMPM_BIT		BIT5
+
+#define RTC_CLOCK_HOUR_12_24			6
+#define RTC_CLOCK_HOUR_12_24_MSK		(MSK(1)<<RTC_CLOCK_HOUR_12_24_SHF)
+#define RTC_CLOCK_HOUR_12_24_BIT		BIT6
+
+
+/* RTC_CLOCK_DAY       	0x3*/
+
+#define RTC_CLOCK_DAY_SHF				0
+#define RTC_CLOCK_DAY_MSK				(MSK(3)<<RTC_CLOCK_DAY_SHF)
+
+/* RTC_CLOCK_DATE      	0x4*/
+
+#define RTC_CLOCK_DATE_SHF				0
+#define RTC_CLOCK_DATE_MSK				(MSK(4)<<RTC_CLOCK_DATE_SHF)
+
+#define RTC_CLOCK_10DATE_SHF			4
+#define RTC_CLOCK_10DATE_MSK			(MSK(2)<<RTC_CLOCK_10DATE_SHF)
+
+
+/* RTC_CLOCK_MONTH_CENTURY    	0x5*/
+
+#define RTC_CLOCK_MONTH_SHF				0
+#define RTC_CLOCK_MONTH_MSK				(MSK(4)<<RTC_CLOCK_MONTH_SHF)
+
+#define RTC_CLOCK_10MONTH_SHF			4
+#define RTC_CLOCK_10MONTH_MSK			(MSK(1)<<RTC_CLOCK_10MONTH_SHF)
+#define RTC_CLOCK_10MONTH_BIT			BIT4
+
+
+#define RTC_CLOCK_CENTURY_SHF			7
+#define RTC_CLOCK_CENTURY_MSK			(MSK(1)<<RTC_CLOCK_CENTURY_SHF)
+#define RTC_CLOCK_CENTURY_BIT			BIT7
+
+
+/* RTC_CLOCK_YEAR      	0x6*/
+
+#define RTC_CLOCK_YEAR_SHF				0
+#define RTC_CLOCK_YEAR_MSK				(MSK(4)<<RTC_CLOCK_YEAR_SHF)
+
+#define RTC_CLOCK_10YEAR_SHF			4
+#define RTC_CLOCK_10YEAR_MSK			(MSK(4)<<RTC_CLOCK_10YEAR_SHF)
+
+
+/* RTC_ALARM_SECONDS  	0x7*/
+
+#define RTC_CLOCK_SECONDS_ALRM1_SHF		0
+#define RTC_CLOCK_SECONDS_ALRM1_MSK		(MSK(4)<<RTC_CLOCK_SECONDS_ALRM1_SHF)
+
+#define RTC_CLOCK_10SECONDS_ALRM1_SHF	4
+#define RTC_CLOCK_10SECONDS_ALRM1_MSK	(MSK(3)<<RTC_CLOCK_10SECONDS_ALRM1_SHF)
+
+#define RTC_CLOCK_A1M1_SHF				0
+#define RTC_CLOCK_A1M1_MSK				(MSK(1)<<RTC_CLOCK_A1M1_SHF)
+#define RTC_CLOCK_A1M1_BIT				BIT7
+
+
+/* RTC_ALARM_MINUTES   	0x8*/
+
+#define RTC_CLOCK_MINUTES_ALRM1_SHF		0
+#define RTC_CLOCK_MINUTES_ALRM1_MSK		(MSK(4)<<RTC_CLOCK_MINUTES_ALRM1_SHF)
+
+#define RTC_CLOCK_10MINUTES_ALRM1_SHF	4
+#define RTC_CLOCK_10MINUTES_ALRM1_MSK	(MSK(3)<<RTC_CLOCK_10MINUTES_ALRM1_SHF)
+
+#define RTC_CLOCK_A1M2_SHF				0
+#define RTC_CLOCK_A1M2_MSK				(MSK(1)<<RTC_CLOCK_A1M2_SHF)
+#define RTC_CLOCK_A1M2_BIT				BIT7
+
+/* RTC_ALARM_HOUR      	0x9*/
+
+#define RTC_CLOCK_HOURS_ALRM1_SHF		0
+#define RTC_CLOCK_HOURS_ALRM1_MSK		(MSK(4)<<RTC_CLOCK_HOURS_ALRM1_SHF)
+
+#define RTC_CLOCK_10HOURS_ALRM1_SHF		4
+#define RTC_CLOCK_10HOURS_ALRM1_MSK1	(MSK(1)<<RTC_CLOCK_10HOURS_ALRM1_SHF)
+#define RTC_CLOCK_10HOURS_ALRM1_MSK2	(MSK(2)<<RTC_CLOCK_10HOURS_ALRM1_SHF)
+#define RTC_CLOCK_10HOURS_ALRM1_BIT		BIT4
+
+#define RTC_CLOCK_10HOURS_ALRM1AMPM_SHF	5
+#define RTC_CLOCK_10HOURS_ALRM1AMPM_MSK	(MSK(1)<<RTC_CLOCK_10HOURS_ALRM1AMPM_SHF)
+#define RTC_CLOCK_10HOURS_ALRM1AMPM_BIT	BIT5
+
+#define RTC_CLOCK_HOUR_ALRM1_12_24		6
+#define RTC_CLOCK_HOUR_ALRM1_12_24_MSK	(MSK(1)<<RTC_CLOCK_HOUR_ALRM1_12_24_SHF)
+#define RTC_CLOCK_HOUR_ALRM1_12_24_BIT	BIT6
+
+#define RTC_CLOCK_A1M3_SHF				0
+#define RTC_CLOCK_A1M3_MSK				(MSK(1)<<RTC_CLOCK_A1M3_SHF)
+#define RTC_CLOCK_A1M3_BIT				BIT7
+
+
+/* RTC_ALARM_DAY_DATE  	0xa*/
+
+#define RTC_CLOCK_DAY_ALRM1_SHF			0
+#define RTC_CLOCK_DAY_ALRM1_MSK			(MSK(3)<<RTC_CLOCK_DAY_ALRM1_SHF)
+
+#define RTC_CLOCK_DATE_ALRM1_SHF		0
+#define RTC_CLOCK_DATE_ALRM1_MSK		(MSK(4)<<RTC_CLOCK_DATE_ALRM1_SHF)
+
+#define RTC_CLOCK_10DATE_ALRM1_SHF		4
+#define RTC_CLOCK_10DATE_ALRM1_MSK		(MSK(2)<<RTC_CLOCK_10DATE_ALRM1_SHF)
+
+#define RTC_CLOCK_DY_DT_ALRM1_SHF		6
+#define RTC_CLOCK_DY_DT_ALRM1_MSK		(MSK(1)<<RTC_CLOCK_DY_DT_ALRM1_SHF)
+#define RTC_CLOCK_DY_DT_ALRM1_BIT		BIT6
+
+#define RTC_CLOCK_A1M4_SHF				0
+#define RTC_CLOCK_A1M4_MSK				(MSK(1)<<RTC_CLOCK_A1M4_SHF)
+#define RTC_CLOCK_A1M4_BIT				BIT7
+
+/* RTC_ALARM2_MINUTES  	0xb*/
+
+#define RTC_CLOCK_MINUTES_ALRM2_SHF		0
+#define RTC_CLOCK_MINUTES_ALRM2_MSK		(MSK(4)<<RTC_CLOCK_MINUTES_ALRM2_SHF)
+
+#define RTC_CLOCK_10MINUTES_ALRM2_SHF	4
+#define RTC_CLOCK_10MINUTES_ALRM2_MSK	(MSK(3)<<RTC_CLOCK_10MINUTES_ALRM2_SHF)
+
+#define RTC_CLOCK_A2M2_SHF				0
+#define RTC_CLOCK_A2M2_MSK				(MSK(1)<<RTC_CLOCK_A2M2_SHF)
+#define RTC_CLOCK_A2M2_BIT				BIT7
+
+/* RTC_ALARM2_HOUR     	0xc*/
+
+#define RTC_CLOCK_HOURS_ALRM2_SHF		0
+#define RTC_CLOCK_HOURS_ALRM2_MSK		(MSK(4)<<RTC_CLOCK_HOURS_ALRM2_SHF)
+
+#define RTC_CLOCK_10HOURS_ALRM2_SHF		4
+#define RTC_CLOCK_10HOURS_ALRM2_MSK1	(MSK(1)<<RTC_CLOCK_10HOURS_ALRM2_SHF)
+#define RTC_CLOCK_10HOURS_ALRM2_MSK2	(MSK(2)<<RTC_CLOCK_10HOURS_ALRM2_SHF)
+#define RTC_CLOCK_10HOURS_ALRM2_BIT		BIT4
+
+#define RTC_CLOCK_10HOURS_ALRM2AMPM_SHF	5
+#define RTC_CLOCK_10HOURS_ALRM2AMPM_MSK	(MSK(1)<<RTC_CLOCK_10HOURS_ALRM2AMPM_SHF)
+#define RTC_CLOCK_10HOURS_ALRM2AMPM_BIT	BIT5
+
+#define RTC_CLOCK_HOUR_ALRM2_12_24		6
+#define RTC_CLOCK_HOUR_ALRM2_12_24_MSK	(MSK(1)<<RTC_CLOCK_HOUR_ALRM2_12_24_SHF)
+#define RTC_CLOCK_HOUR_ALRM2_12_24_BIT	BIT6
+
+
+#define RTC_CLOCK_A2M3_SHF 				0
+#define RTC_CLOCK_A2M3_MSK				(MSK(1)<<RTC_CLOCK_A2M3_SHF)
+#define RTC_CLOCK_A2M3_BIT				BIT7
+
+/* RTC_ALARM2_DAY_DATE 	0xd*/
+
+#define RTC_CLOCK_DAY_ALRM2_SHF			0
+#define RTC_CLOCK_DAY_ALRM2_MSK			(MSK(3)<<RTC_CLOCK_DAY_ALRM2_SHF)
+
+#define RTC_CLOCK_DATE_ALRM2_SHF		0
+#define RTC_CLOCK_DATE_ALRM2_MSK		(MSK(4)<<RTC_CLOCK_DATE_ALRM2_SHF)
+
+#define RTC_CLOCK_10DATE_ALRM2_SHF		4
+#define RTC_CLOCK_10DATE_ALRM2_MSK		(MSK(2)<<RTC_CLOCK_10DATE_ALRM2_SHF)
+
+#define RTC_CLOCK_DY_DT_ALRM2_SHF		6
+#define RTC_CLOCK_DY_DT_ALRM2_MSK		(MSK(1)<<RTC_CLOCK_DY_DT_ALRM2_SHF)
+#define RTC_CLOCK_DY_DT_ALRM2_BIT		BIT6
+
+
+#define RTC_CLOCK_A2M4_SHF				0
+#define RTC_CLOCK_A2M4_MSK				(MSK(1)<<RTC_CLOCK_A2M4_SHF)
+#define RTC_CLOCK_A2M4_BIT				BIT7
+
+/* RTC_CONTROL  			0xe*/
+
+#define RTC_CONTROL_A1IE_SHF			0
+#define RTC_CONTROL_A1IE_MSK			(MSK(1)<<RTC_CONTROL_A1IE_SHF)
+#define RTC_CONTROL_A1IE_BIT			BIT0
+
+#define RTC_CONTROL_A2IE_SHF			1
+#define RTC_CONTROL_A2IE_MSK			(MSK(1)<<RTC_CONTROL_A2IE_SHF)
+#define RTC_CONTROL_A2IE_BIT			BIT1
+
+#define RTC_CONTROL_INTCN_SHF			2
+#define RTC_CONTROL_INTCN_MSK			(MSK(1)<<RTC_CONTROL_INTCN_SHF)
+#define RTC_CONTROL_INTCN_BIT			BIT2
+
+#define RTC_CONTROL_RS1_SHF				3
+#define RTC_CONTROL_RS1_MSK				(MSK(1)<<RTC_CONTROL_RS1_SHF)
+#define RTC_CONTROL_RS1_BIT				BIT3
+
+#define RTC_CONTROL_RS2_SHF				4
+#define RTC_CONTROL_RS2_MSK				(MSK(1)<<RTC_CONTROL_RS2_SHF)
+#define RTC_CONTROL_RS2_BIT				BIT4
+
+#define RTC_CONTROL_BBSQI_SHF			5
+#define RTC_CONTROL_BBSQI_MSK			(MSK(1)<<RTC_CONTROL_BBSQI_SHF)
+#define RTC_CONTROL_BBSQI_BIT			BIT5
+
+#define RTC_CONTROL_EOSC_SHF			7
+#define RTC_CONTROL_EOSC_MSK			(MSK(1)<<RTC_CONTROL_EOSC_SHF)
+#define RTC_CONTROL_EOSC_BIT			BIT7
+
+
+/* RTC_STATUS  			0xf*/
+#define RTC_CONTROL_A1F_SHF				0
+#define RTC_CONTROL_A1F_MSK				(MSK(1)<<RTC_CONTROL_A1F_SHF)
+#define RTC_CONTROL_A1F_BIT				BIT0
+
+#define RTC_CONTROL_A2F_SHF				1
+#define RTC_CONTROL_A2F_MSK				(MSK(1)<<RTC_CONTROL_A2F_SHF)
+#define RTC_CONTROL_A2F_BIT				BIT1
+
+#define RTC_CONTROL_OSF_SHF				7
+#define RTC_CONTROL_OSF_MSK				(MSK(1)<<RTC_CONTROL_OSF_SHF)
+#define RTC_CONTROL_OSF_BIT				BIT7
+
+/* RTC_TRICKLE_CHARGE  	0x10*/
+#define RTC_CONTROL_ROUT0_SHF			0
+#define RTC_CONTROL_ROUT0_MSK			(MSK(1)<<RTC_CONTROL_ROUT0_SHF)
+#define RTC_CONTROL_ROUT0_BIT			BIT0
+
+#define RTC_CONTROL_ROUT1_SHF			1
+#define RTC_CONTROL_ROUT1_MSK			(MSK(1)<<RTC_CONTROL_ROUT1_SHF)
+#define RTC_CONTROL_ROUT1_BIT			BIT1
+
+#define RTC_CONTROL_DS0_SHF				2
+#define RTC_CONTROL_DS0_MSK				(MSK(1)<<RTC_CONTROL_DS0_SHF)
+#define RTC_CONTROL_DS0_BIT				BIT2
+
+#define RTC_CONTROL_DS1_SHF				3
+#define RTC_CONTROL_DS1_MSK				(MSK(1)<<RTC_CONTROL_DS1_SHF)
+#define RTC_CONTROL_DS1_BIT				BIT3
+
+#define RTC_CONTROL_TCS0_SHF			4
+#define RTC_CONTROL_TCS0_MSK			(MSK(1)<<RTC_CONTROL_TCS0_SHF)
+#define RTC_CONTROL_TCS0_BIT			BIT4
+
+#define RTC_CONTROL_TCS1_SHF			5
+#define RTC_CONTROL_TCS1_MSK			(MSK(1)<<RTC_CONTROL_TCS1_SHF)
+#define RTC_CONTROL_TCS1_BIT			BIT5
+
+#define RTC_CONTROL_TCS2_SHF			6
+#define RTC_CONTROL_TCS2_MSK			(MSK(1)<<RTC_CONTROL_TCS2_SHF)
+#define RTC_CONTROL_TCS2_BIT			BIT6
+
+#define RTC_CONTROL_TCS3_SHF			7
+#define RTC_CONTROL_TCS3_MSK			(MSK(1)<<RTC_CONTROL_TCS3_SHF)
+#define RTC_CONTROL_TCS3_BIT			BIT7
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCmvDS1339Regh */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133x.c b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133x.c
new file mode 100755
index 0000000..f3adbbb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133x.c
@@ -0,0 +1,354 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+/* includes */
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "rtc/ext_rtc/mvDS133x.h"
+#include "rtc/ext_rtc/mvDS133xReg.h"
+
+static MV_VOID mvRtcCharWrite(MV_U32 offset, MV_U8 data);
+static MV_VOID mvRtcCharRead(MV_U32 offset, MV_U8 *data);
+
+#define RTC_I2C_CH MV_BOARD_RTC_I2C_CHANNEL
+
+/*******************************************************************************
+* mvRtcDS133xAlarmSet - Set the Alarm of the Real time clock
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       time - A pointer to a structure RTC_TIME (defined in mvDS133x.h).
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS133xAlarmSet(MV_RTC_TIME *time)
+{
+	return;
+}
+/*******************************************************************************
+* mvRtcDS133xTimeSet - Update the Real Time Clock.
+*
+* DESCRIPTION:
+*       This function sets a new time and date to the RTC from the given
+*       structure RTC_TIME . All fields within the structure must be assigned
+*		with a value prior to the use of this function.
+*
+* INPUT:
+*       time - A pointer to a structure RTC_TIME (defined in mvDS133x.h).
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS133xTimeSet(MV_RTC_TIME *time)
+{
+	MV_U8 tempValue;
+	MV_U8 tens;
+	MV_U8 single;
+
+	/* seconds */
+	tens = time->seconds / 10;
+	single = time->seconds % 10;
+	tempValue = ((tens << RTC_CLOCK_10SECONDS_SHF) & RTC_CLOCK_10SECONDS_MSK)|
+				((single << RTC_CLOCK_SECONDS_SHF) & RTC_CLOCK_SECONDS_MSK) ;
+	mvRtcCharWrite(RTC_CLOCK_SECONDS, tempValue);
+
+	/* minutes */
+	tens = time->minutes / 10;
+	single = time->minutes % 10;
+	tempValue = ((tens  << RTC_CLOCK_10MINUTES_SHF) & RTC_CLOCK_10MINUTES_MSK)|
+			    ((single << RTC_CLOCK_MINUTES_SHF) & RTC_CLOCK_MINUTES_MSK) ;
+	mvRtcCharWrite(RTC_CLOCK_MINUTES, tempValue);
+
+	/* hours (24) */
+	tens = time->hours / 10;
+	single = time->hours % 10;
+	tempValue = ((tens << RTC_CLOCK_10HOURS_SHF) & RTC_CLOCK_10HOURS_MSK2)|
+				((single << RTC_CLOCK_HOURS_SHF) & RTC_CLOCK_HOURS_MSK);
+	mvRtcCharWrite(RTC_CLOCK_HOUR, tempValue);
+
+	/* day */
+	single = ++(time->day);
+	tempValue = ((single << RTC_CLOCK_DAY_SHF) & RTC_CLOCK_DAY_MSK) ;
+	mvRtcCharWrite(RTC_CLOCK_DAY, tempValue);
+
+	/* date */
+	tens = time->date / 10;
+	single = time->date % 10;
+	tempValue = ((tens << RTC_CLOCK_10DATE_SHF) & RTC_CLOCK_10DATE_MSK)|
+				((single << RTC_CLOCK_DATE_SHF) & RTC_CLOCK_DATE_MSK) ;
+
+	/* month */
+	mvRtcCharWrite(RTC_CLOCK_DATE, tempValue);
+	tens = time->month / 10;
+	single = time->month % 10;
+	tempValue = ((tens << RTC_CLOCK_10MONTH_SHF) & RTC_CLOCK_10MONTH_MSK)|
+				((single << RTC_CLOCK_MONTH_SHF) & RTC_CLOCK_MONTH_MSK);
+	mvRtcCharWrite(RTC_CLOCK_MONTH_CENTURY, tempValue);
+
+	/* year */
+	tens = time->year / 10;
+	single = time->year % 10;
+	tempValue = ((tens << RTC_CLOCK_10YEAR_SHF) & RTC_CLOCK_10YEAR_MSK)|
+				((single << RTC_CLOCK_YEAR_SHF) & RTC_CLOCK_YEAR_MSK);
+	mvRtcCharWrite(RTC_CLOCK_YEAR, tempValue);
+
+	return;
+}
+
+/*******************************************************************************
+* mvRtcDS133xTimeGet - Read the time from the RTC.
+*
+* DESCRIPTION:
+*       This function reads the current time and date from the RTC into the
+*       structure RTC_TIME (defined in mvDS133x.h).
+*
+* INPUT:
+*       time - A pointer to a structure TIME (defined in mvDS133x.h).
+*
+* OUTPUT:
+*       The structure RTC_TIME is updated with the time read from the RTC.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS133xTimeGet(MV_RTC_TIME *time)
+{
+	MV_U8 tempValue;
+	MV_U32 tens;
+	MV_U32 single;
+
+	/* seconds */
+	mvRtcCharRead(RTC_CLOCK_SECONDS, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10SECONDS_MSK) >> RTC_CLOCK_10SECONDS_SHF;
+	single = (tempValue & RTC_CLOCK_SECONDS_MSK) >> RTC_CLOCK_SECONDS_SHF ;
+	time->seconds = 10*tens + single;
+
+	/* minutes */
+	mvRtcCharRead(RTC_CLOCK_MINUTES, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10MINUTES_MSK) >> RTC_CLOCK_10MINUTES_SHF;
+	single = (tempValue & RTC_CLOCK_MINUTES_MSK) >> RTC_CLOCK_MINUTES_SHF;
+	time->minutes = 10*tens + single;
+
+	/* hours */
+	mvRtcCharRead(RTC_CLOCK_HOUR, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10HOURS_MSK2) >> RTC_CLOCK_10HOURS_SHF;
+	single = (tempValue & RTC_CLOCK_HOURS_MSK) >> RTC_CLOCK_HOURS_SHF;
+	time->hours = 10*tens + single;
+
+	/* day */
+	mvRtcCharRead(RTC_CLOCK_DAY, &tempValue);
+	time->day = (tempValue & RTC_CLOCK_DAY_MSK) >> RTC_CLOCK_DAY_SHF ;
+	time->day--;
+
+	/* date */
+	mvRtcCharRead(RTC_CLOCK_DATE, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10DATE_MSK) >> RTC_CLOCK_10DATE_SHF;
+	single = (tempValue & RTC_CLOCK_DATE_MSK) >> RTC_CLOCK_DATE_SHF;
+	time->date = 10*tens + single;
+
+	/* century/ month */
+	mvRtcCharRead(RTC_CLOCK_MONTH_CENTURY, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10MONTH_MSK) >> RTC_CLOCK_10MONTH_SHF;
+	single = (tempValue & RTC_CLOCK_MONTH_MSK) >> RTC_CLOCK_MONTH_SHF;
+	time->month = 10*tens + single;
+	time->century = (tempValue & RTC_CLOCK_CENTURY_MSK)>>RTC_CLOCK_CENTURY_SHF;
+
+	/* year */
+	mvRtcCharRead(RTC_CLOCK_YEAR, &tempValue);
+	tens = (tempValue & RTC_CLOCK_10YEAR_MSK) >> RTC_CLOCK_10YEAR_SHF;
+	single = (tempValue & RTC_CLOCK_YEAR_MSK) >> RTC_CLOCK_YEAR_SHF;
+	time->year = 10*tens + single;
+
+	return;
+}
+
+/*******************************************************************************
+* mvRtcDS1339Init - Initialize the clock.
+*
+* DESCRIPTION:
+*       This function initialize the clock registers and read\write functions
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS1339Init(MV_VOID)
+{
+	MV_U8 ucTemp;
+
+	/* We will disable interrupts as default .*/
+	mvRtcCharRead(RTC1339_CONTROL, &ucTemp);
+	ucTemp |= RTC_CONTROL_INTCN_BIT;
+	mvRtcCharWrite(RTC1339_CONTROL, ucTemp);
+
+	/* disable trickle */
+	mvRtcCharWrite(RTC_TRICKLE_CHARGE, 0);
+
+	return;
+}
+
+
+/*******************************************************************************
+* mvRtcDS1338Init - Initialize the clock.
+*
+* DESCRIPTION:
+*       This function initialize the clock registers and read\write functions
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcDS1338Init(MV_VOID)
+{
+	MV_U8 ucTemp;
+
+	/* We will enable OSC .*/
+	mvRtcCharRead(RTC_CLOCK_SECONDS, &ucTemp);
+	ucTemp &= ~RTC_CONTROL_EOSC_MSK;
+	mvRtcCharWrite(RTC_CLOCK_SECONDS, ucTemp);
+
+	return;
+}
+
+/* assumption twsi is initialized !!! */
+/*******************************************************************************
+* mvRtcCharRead - Read a char from the RTC.
+*
+* DESCRIPTION:
+*       This function reads a char from the RTC offset.
+*
+* INPUT:
+*       offset - offset
+*
+* OUTPUT:
+*       data - char read from offset offset.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID	mvRtcCharRead(MV_U32 offset, MV_U8 *data)
+{
+	MV_TWSI_SLAVE   twsiSlave;
+
+	twsiSlave.slaveAddr.type = mvBoardRtcTwsiAddrTypeGet();
+	twsiSlave.slaveAddr.address = mvBoardRtcTwsiAddrGet();
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = offset;
+	twsiSlave.moreThen256 = MV_FALSE;
+	mvTwsiRead(RTC_I2C_CH, &twsiSlave, data, 1);
+
+	return;
+}
+
+/*******************************************************************************
+* mvRtcCharWrite - Write a char from the RTC.
+*
+* DESCRIPTION:
+*       This function writes a char to the RTC offset.
+*
+* INPUT:
+*       offset - offset
+*
+* OUTPUT:
+*       data - char write to addr address.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID mvRtcCharWrite(MV_U32 offset, MV_U8 data)
+{
+	MV_TWSI_SLAVE twsiSlave;
+
+	twsiSlave.slaveAddr.type = mvBoardRtcTwsiAddrTypeGet();
+	twsiSlave.slaveAddr.address = mvBoardRtcTwsiAddrGet();
+	twsiSlave.validOffset = MV_TRUE;
+	twsiSlave.offset = offset;
+	twsiSlave.moreThen256 = MV_FALSE;
+	mvTwsiWrite(RTC_I2C_CH, &twsiSlave, &data, 1);
+
+	return;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133x.h b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133x.h
new file mode 100755
index 0000000..e618161
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133x.h
@@ -0,0 +1,107 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __INCmvDS133xh
+#define __INCmvDS133xh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvTypes.h"
+#include "twsi/mvTwsi.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "boardEnv/mvBoardEnvSpec.h"
+
+/*******************************************************************************/
+/* Support: DS1338 and DS1339						       */
+/*******************************************************************************/
+typedef struct time {
+	MV_U8  seconds;
+	MV_U8  minutes;
+	MV_U8  hours;
+	MV_U8  day;
+	MV_U8  date;
+	MV_U8  month;
+	MV_U8  century;
+	MV_U8  year;
+} MV_RTC_TIME;
+
+MV_VOID mvRtcDS1339Init(MV_VOID);
+MV_VOID mvRtcDS1338Init(MV_VOID);
+
+MV_VOID mvRtcDS133xTimeSet(MV_RTC_TIME *time);
+
+MV_VOID mvRtcDS133xTimeGet(MV_RTC_TIME *time);
+
+MV_VOID mvRtcDS133xAlarmSet(MV_RTC_TIME *time);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif  /* __INCmvDS133xh */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133xReg.h b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133xReg.h
new file mode 100755
index 0000000..73a3a1c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/ext_rtc/mvDS133xReg.h
@@ -0,0 +1,377 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __INCmvDS133xRegh
+#define __INCmvDS133xRegh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MSK
+#define MSK(n)						((1 << (n)) - 1)
+#endif
+
+#define RTC_CLOCK_SECONDS			0x0
+#define RTC_CLOCK_MINUTES			0x1
+#define RTC_CLOCK_HOUR				0x2
+#define RTC_CLOCK_DAY				0x3
+#define RTC_CLOCK_DATE				0x4
+#define RTC_CLOCK_MONTH_CENTURY			0x5
+#define RTC_CLOCK_YEAR				0x6
+#define RTC_ALARM_SECONDS			0x7
+#define RTC_ALARM_MINUTES			0x8
+#define RTC_ALARM_HOUR				0x9
+#define RTC_ALARM_DAY_DATE			0xa
+#define RTC_ALARM2_MINUTES			0xb
+#define RTC_ALARM2_HOUR				0xc
+#define RTC_ALARM2_DAY_DATE 			0xd
+#define RTC1339_CONTROL				0xe
+#define RTC1338_CONTROL				0x7
+#define RTC_STATUS				0xf
+#define RTC_TRICKLE_CHARGE			0x10
+
+#define FIRST_REG_OFF				RTC_CLOCK_SECONDS
+#define LAST_REG_OFF				RTC_TRICKLE_CHARGE
+
+
+/* RTC_CLOCK_SECONDS   0x0*/
+
+#define RTC_CLOCK_SECONDS_SHF		0
+#define RTC_CLOCK_SECONDS_MSK		(MSK(4)<<RTC_CLOCK_SECONDS_SHF)
+
+#define RTC_CLOCK_10SECONDS_SHF		4
+#define RTC_CLOCK_10SECONDS_MSK		(MSK(3)<<RTC_CLOCK_10SECONDS_SHF)
+
+/* RTC_CLOCK_MINUTES   0x1*/
+
+#define RTC_CLOCK_MINUTES_SHF		0
+#define RTC_CLOCK_MINUTES_MSK		(MSK(4)<<RTC_CLOCK_MINUTES_SHF)
+
+#define RTC_CLOCK_10MINUTES_SHF		4
+#define RTC_CLOCK_10MINUTES_MSK		(MSK(3)<<RTC_CLOCK_10MINUTES_SHF)
+
+/* RTC_CLOCK_HOUR      0x2*/
+
+#define RTC_CLOCK_HOURS_SHF			0
+#define RTC_CLOCK_HOURS_MSK			(MSK(4)<<RTC_CLOCK_HOURS_SHF)
+
+#define RTC_CLOCK_10HOURS_SHF			4
+#define RTC_CLOCK_10HOURS_MSK1			(MSK(1)<<RTC_CLOCK_10HOURS_SHF)
+#define RTC_CLOCK_10HOURS_MSK2			(MSK(2)<<RTC_CLOCK_10HOURS_SHF)
+#define RTC_CLOCK_10HOURS_BIT			BIT4
+
+#define RTC_CLOCK_10HOURSAMPM_SHF		5
+#define RTC_CLOCK_10HOURSAMPM_MSK		(MSK(1)<<RTC_CLOCK_10HOURSAMPM_SHF)
+#define RTC_CLOCK_10HOURSAMPM_BIT		BIT5
+
+#define RTC_CLOCK_HOUR_12_24			6
+#define RTC_CLOCK_HOUR_12_24_MSK		(MSK(1)<<RTC_CLOCK_HOUR_12_24_SHF)
+#define RTC_CLOCK_HOUR_12_24_BIT		BIT6
+
+
+/* RTC_CLOCK_DAY       	0x3*/
+
+#define RTC_CLOCK_DAY_SHF				0
+#define RTC_CLOCK_DAY_MSK				(MSK(3)<<RTC_CLOCK_DAY_SHF)
+
+/* RTC_CLOCK_DATE      	0x4*/
+
+#define RTC_CLOCK_DATE_SHF				0
+#define RTC_CLOCK_DATE_MSK				(MSK(4)<<RTC_CLOCK_DATE_SHF)
+
+#define RTC_CLOCK_10DATE_SHF			4
+#define RTC_CLOCK_10DATE_MSK			(MSK(2)<<RTC_CLOCK_10DATE_SHF)
+
+
+/* RTC_CLOCK_MONTH_CENTURY    	0x5*/
+
+#define RTC_CLOCK_MONTH_SHF				0
+#define RTC_CLOCK_MONTH_MSK				(MSK(4)<<RTC_CLOCK_MONTH_SHF)
+
+#define RTC_CLOCK_10MONTH_SHF			4
+#define RTC_CLOCK_10MONTH_MSK			(MSK(1)<<RTC_CLOCK_10MONTH_SHF)
+#define RTC_CLOCK_10MONTH_BIT			BIT4
+
+
+#define RTC_CLOCK_CENTURY_SHF			7
+#define RTC_CLOCK_CENTURY_MSK			(MSK(1)<<RTC_CLOCK_CENTURY_SHF)
+#define RTC_CLOCK_CENTURY_BIT			BIT7
+
+
+/* RTC_CLOCK_YEAR      	0x6*/
+
+#define RTC_CLOCK_YEAR_SHF			0
+#define RTC_CLOCK_YEAR_MSK			(MSK(4)<<RTC_CLOCK_YEAR_SHF)
+
+#define RTC_CLOCK_10YEAR_SHF			4
+#define RTC_CLOCK_10YEAR_MSK			(MSK(4)<<RTC_CLOCK_10YEAR_SHF)
+
+
+/* RTC_ALARM_SECONDS  	0x7*/
+
+#define RTC_CLOCK_SECONDS_ALRM1_SHF		0
+#define RTC_CLOCK_SECONDS_ALRM1_MSK		(MSK(4)<<RTC_CLOCK_SECONDS_ALRM1_SHF)
+
+#define RTC_CLOCK_10SECONDS_ALRM1_SHF		4
+#define RTC_CLOCK_10SECONDS_ALRM1_MSK		(MSK(3)<<RTC_CLOCK_10SECONDS_ALRM1_SHF)
+
+#define RTC_CLOCK_A1M1_SHF			0
+#define RTC_CLOCK_A1M1_MSK			(MSK(1)<<RTC_CLOCK_A1M1_SHF)
+#define RTC_CLOCK_A1M1_BIT			BIT7
+
+
+/* RTC_ALARM_MINUTES   	0x8*/
+
+#define RTC_CLOCK_MINUTES_ALRM1_SHF		0
+#define RTC_CLOCK_MINUTES_ALRM1_MSK		(MSK(4)<<RTC_CLOCK_MINUTES_ALRM1_SHF)
+
+#define RTC_CLOCK_10MINUTES_ALRM1_SHF		4
+#define RTC_CLOCK_10MINUTES_ALRM1_MSK		(MSK(3)<<RTC_CLOCK_10MINUTES_ALRM1_SHF)
+
+#define RTC_CLOCK_A1M2_SHF			0
+#define RTC_CLOCK_A1M2_MSK			(MSK(1)<<RTC_CLOCK_A1M2_SHF)
+#define RTC_CLOCK_A1M2_BIT			BIT7
+
+/* RTC_ALARM_HOUR      	0x9*/
+
+#define RTC_CLOCK_HOURS_ALRM1_SHF		0
+#define RTC_CLOCK_HOURS_ALRM1_MSK		(MSK(4)<<RTC_CLOCK_HOURS_ALRM1_SHF)
+
+#define RTC_CLOCK_10HOURS_ALRM1_SHF		4
+#define RTC_CLOCK_10HOURS_ALRM1_MSK1		(MSK(1)<<RTC_CLOCK_10HOURS_ALRM1_SHF)
+#define RTC_CLOCK_10HOURS_ALRM1_MSK2		(MSK(2)<<RTC_CLOCK_10HOURS_ALRM1_SHF)
+#define RTC_CLOCK_10HOURS_ALRM1_BIT		BIT4
+
+#define RTC_CLOCK_10HOURS_ALRM1AMPM_SHF		5
+#define RTC_CLOCK_10HOURS_ALRM1AMPM_MSK		(MSK(1)<<RTC_CLOCK_10HOURS_ALRM1AMPM_SHF)
+#define RTC_CLOCK_10HOURS_ALRM1AMPM_BIT		BIT5
+
+#define RTC_CLOCK_HOUR_ALRM1_12_24		6
+#define RTC_CLOCK_HOUR_ALRM1_12_24_MSK		(MSK(1)<<RTC_CLOCK_HOUR_ALRM1_12_24_SHF)
+#define RTC_CLOCK_HOUR_ALRM1_12_24_BIT		BIT6
+
+#define RTC_CLOCK_A1M3_SHF			0
+#define RTC_CLOCK_A1M3_MSK			(MSK(1)<<RTC_CLOCK_A1M3_SHF)
+#define RTC_CLOCK_A1M3_BIT			BIT7
+
+
+/* RTC_ALARM_DAY_DATE  	0xa*/
+
+#define RTC_CLOCK_DAY_ALRM1_SHF			0
+#define RTC_CLOCK_DAY_ALRM1_MSK			(MSK(3)<<RTC_CLOCK_DAY_ALRM1_SHF)
+
+#define RTC_CLOCK_DATE_ALRM1_SHF		0
+#define RTC_CLOCK_DATE_ALRM1_MSK		(MSK(4)<<RTC_CLOCK_DATE_ALRM1_SHF)
+
+#define RTC_CLOCK_10DATE_ALRM1_SHF		4
+#define RTC_CLOCK_10DATE_ALRM1_MSK		(MSK(2)<<RTC_CLOCK_10DATE_ALRM1_SHF)
+
+#define RTC_CLOCK_DY_DT_ALRM1_SHF		6
+#define RTC_CLOCK_DY_DT_ALRM1_MSK		(MSK(1)<<RTC_CLOCK_DY_DT_ALRM1_SHF)
+#define RTC_CLOCK_DY_DT_ALRM1_BIT		BIT6
+
+#define RTC_CLOCK_A1M4_SHF			0
+#define RTC_CLOCK_A1M4_MSK			(MSK(1)<<RTC_CLOCK_A1M4_SHF)
+#define RTC_CLOCK_A1M4_BIT			BIT7
+
+/* RTC_ALARM2_MINUTES  	0xb*/
+
+#define RTC_CLOCK_MINUTES_ALRM2_SHF		0
+#define RTC_CLOCK_MINUTES_ALRM2_MSK		(MSK(4)<<RTC_CLOCK_MINUTES_ALRM2_SHF)
+
+#define RTC_CLOCK_10MINUTES_ALRM2_SHF		4
+#define RTC_CLOCK_10MINUTES_ALRM2_MSK		(MSK(3)<<RTC_CLOCK_10MINUTES_ALRM2_SHF)
+
+#define RTC_CLOCK_A2M2_SHF			0
+#define RTC_CLOCK_A2M2_MSK			(MSK(1)<<RTC_CLOCK_A2M2_SHF)
+#define RTC_CLOCK_A2M2_BIT			BIT7
+
+/* RTC_ALARM2_HOUR     	0xc*/
+
+#define RTC_CLOCK_HOURS_ALRM2_SHF		0
+#define RTC_CLOCK_HOURS_ALRM2_MSK		(MSK(4)<<RTC_CLOCK_HOURS_ALRM2_SHF)
+
+#define RTC_CLOCK_10HOURS_ALRM2_SHF		4
+#define RTC_CLOCK_10HOURS_ALRM2_MSK1		(MSK(1)<<RTC_CLOCK_10HOURS_ALRM2_SHF)
+#define RTC_CLOCK_10HOURS_ALRM2_MSK2		(MSK(2)<<RTC_CLOCK_10HOURS_ALRM2_SHF)
+#define RTC_CLOCK_10HOURS_ALRM2_BIT		BIT4
+
+#define RTC_CLOCK_10HOURS_ALRM2AMPM_SHF		5
+#define RTC_CLOCK_10HOURS_ALRM2AMPM_MSK		(MSK(1)<<RTC_CLOCK_10HOURS_ALRM2AMPM_SHF)
+#define RTC_CLOCK_10HOURS_ALRM2AMPM_BIT		BIT5
+
+#define RTC_CLOCK_HOUR_ALRM2_12_24		6
+#define RTC_CLOCK_HOUR_ALRM2_12_24_MSK		(MSK(1)<<RTC_CLOCK_HOUR_ALRM2_12_24_SHF)
+#define RTC_CLOCK_HOUR_ALRM2_12_24_BIT		BIT6
+
+
+#define RTC_CLOCK_A2M3_SHF 			0
+#define RTC_CLOCK_A2M3_MSK			(MSK(1)<<RTC_CLOCK_A2M3_SHF)
+#define RTC_CLOCK_A2M3_BIT			BIT7
+
+/* RTC_ALARM2_DAY_DATE 	0xd*/
+
+#define RTC_CLOCK_DAY_ALRM2_SHF			0
+#define RTC_CLOCK_DAY_ALRM2_MSK			(MSK(3)<<RTC_CLOCK_DAY_ALRM2_SHF)
+
+#define RTC_CLOCK_DATE_ALRM2_SHF		0
+#define RTC_CLOCK_DATE_ALRM2_MSK		(MSK(4)<<RTC_CLOCK_DATE_ALRM2_SHF)
+
+#define RTC_CLOCK_10DATE_ALRM2_SHF		4
+#define RTC_CLOCK_10DATE_ALRM2_MSK		(MSK(2)<<RTC_CLOCK_10DATE_ALRM2_SHF)
+
+#define RTC_CLOCK_DY_DT_ALRM2_SHF		6
+#define RTC_CLOCK_DY_DT_ALRM2_MSK		(MSK(1)<<RTC_CLOCK_DY_DT_ALRM2_SHF)
+#define RTC_CLOCK_DY_DT_ALRM2_BIT		BIT6
+
+
+#define RTC_CLOCK_A2M4_SHF			0
+#define RTC_CLOCK_A2M4_MSK			(MSK(1)<<RTC_CLOCK_A2M4_SHF)
+#define RTC_CLOCK_A2M4_BIT			BIT7
+
+/* RTC_CONTROL  			0xe*/
+
+#define RTC_CONTROL_A1IE_SHF			0
+#define RTC_CONTROL_A1IE_MSK			(MSK(1)<<RTC_CONTROL_A1IE_SHF)
+#define RTC_CONTROL_A1IE_BIT			BIT0
+
+#define RTC_CONTROL_A2IE_SHF			1
+#define RTC_CONTROL_A2IE_MSK			(MSK(1)<<RTC_CONTROL_A2IE_SHF)
+#define RTC_CONTROL_A2IE_BIT			BIT1
+
+#define RTC_CONTROL_INTCN_SHF			2
+#define RTC_CONTROL_INTCN_MSK			(MSK(1)<<RTC_CONTROL_INTCN_SHF)
+#define RTC_CONTROL_INTCN_BIT			BIT2
+
+#define RTC_CONTROL_RS1_SHF			3
+#define RTC_CONTROL_RS1_MSK			(MSK(1)<<RTC_CONTROL_RS1_SHF)
+#define RTC_CONTROL_RS1_BIT			BIT3
+
+#define RTC_CONTROL_RS2_SHF			4
+#define RTC_CONTROL_RS2_MSK			(MSK(1)<<RTC_CONTROL_RS2_SHF)
+#define RTC_CONTROL_RS2_BIT			BIT4
+
+#define RTC_CONTROL_BBSQI_SHF			5
+#define RTC_CONTROL_BBSQI_MSK			(MSK(1)<<RTC_CONTROL_BBSQI_SHF)
+#define RTC_CONTROL_BBSQI_BIT			BIT5
+
+#define RTC_CONTROL_EOSC_SHF			7
+#define RTC_CONTROL_EOSC_MSK			(MSK(1)<<RTC_CONTROL_EOSC_SHF)
+#define RTC_CONTROL_EOSC_BIT			BIT7
+
+
+/* RTC_STATUS  			0xf*/
+#define RTC_CONTROL_A1F_SHF				0
+#define RTC_CONTROL_A1F_MSK				(MSK(1)<<RTC_CONTROL_A1F_SHF)
+#define RTC_CONTROL_A1F_BIT				BIT0
+
+#define RTC_CONTROL_A2F_SHF				1
+#define RTC_CONTROL_A2F_MSK				(MSK(1)<<RTC_CONTROL_A2F_SHF)
+#define RTC_CONTROL_A2F_BIT				BIT1
+
+#define RTC_CONTROL_OSF_SHF				7
+#define RTC_CONTROL_OSF_MSK				(MSK(1)<<RTC_CONTROL_OSF_SHF)
+#define RTC_CONTROL_OSF_BIT				BIT7
+
+/* RTC_TRICKLE_CHARGE  	0x10*/
+#define RTC_CONTROL_ROUT0_SHF			0
+#define RTC_CONTROL_ROUT0_MSK			(MSK(1)<<RTC_CONTROL_ROUT0_SHF)
+#define RTC_CONTROL_ROUT0_BIT			BIT0
+
+#define RTC_CONTROL_ROUT1_SHF			1
+#define RTC_CONTROL_ROUT1_MSK			(MSK(1)<<RTC_CONTROL_ROUT1_SHF)
+#define RTC_CONTROL_ROUT1_BIT			BIT1
+
+#define RTC_CONTROL_DS0_SHF				2
+#define RTC_CONTROL_DS0_MSK				(MSK(1)<<RTC_CONTROL_DS0_SHF)
+#define RTC_CONTROL_DS0_BIT				BIT2
+
+#define RTC_CONTROL_DS1_SHF				3
+#define RTC_CONTROL_DS1_MSK				(MSK(1)<<RTC_CONTROL_DS1_SHF)
+#define RTC_CONTROL_DS1_BIT				BIT3
+
+#define RTC_CONTROL_TCS0_SHF			4
+#define RTC_CONTROL_TCS0_MSK			(MSK(1)<<RTC_CONTROL_TCS0_SHF)
+#define RTC_CONTROL_TCS0_BIT			BIT4
+
+#define RTC_CONTROL_TCS1_SHF			5
+#define RTC_CONTROL_TCS1_MSK			(MSK(1)<<RTC_CONTROL_TCS1_SHF)
+#define RTC_CONTROL_TCS1_BIT			BIT5
+
+#define RTC_CONTROL_TCS2_SHF			6
+#define RTC_CONTROL_TCS2_MSK			(MSK(1)<<RTC_CONTROL_TCS2_SHF)
+#define RTC_CONTROL_TCS2_BIT			BIT6
+
+#define RTC_CONTROL_TCS3_SHF			7
+#define RTC_CONTROL_TCS3_MSK			(MSK(1)<<RTC_CONTROL_TCS3_SHF)
+#define RTC_CONTROL_TCS3_BIT			BIT7
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCmvDS133xRegh */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtc.c b/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtc.c
new file mode 100755
index 0000000..423544b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtc.c
@@ -0,0 +1,235 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
+
+*******************************************************************************/
+
+
+/* includes */
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysRtcConfig.h"
+#include "mvRtcReg.h"
+#include "mvRtc.h"
+
+
+/*******************************************************************************
+* mvRtcTimeSet - Update the Real Time Clock.
+*
+* DESCRIPTION:
+*       This function sets a new time and date to the RTC from the given
+*       structure RTC_TIME . All fields within the structure must be assigned
+*       with a value prior to the use of this function.
+*
+* INPUT:
+*       time - A pointer to a structure RTC_TIME (defined in mv.h).
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcTimeSet(MV_RTC_TIME *mvTime)
+{
+	MV_U32 timeVal = 0;
+	MV_U32 dateVal = 0;
+	MV_U32 tens;
+	MV_U32 single;
+
+	/* seconds */
+	tens = mvTime->seconds / 10;
+	single = mvTime->seconds % 10;
+	timeVal |= ((tens << RTC_TIME_10SECONDS_SHF) & RTC_TIME_10SECONDS_MSK) |
+		  ((single << RTC_TIME_SECONDS_SHF) & RTC_TIME_SECONDS_MSK);
+
+	/* minutes */
+	tens = mvTime->minutes / 10;
+	single = mvTime->minutes % 10;
+	timeVal |= ((tens  << RTC_TIME_10MINUTES_SHF) & RTC_TIME_10MINUTES_MSK) |
+		  ((single << RTC_TIME_MINUTES_SHF) & RTC_TIME_MINUTES_MSK);
+
+	/* hours (24) */
+	tens = mvTime->hours / 10;
+	single = mvTime->hours % 10;
+	timeVal |= ((tens  << RTC_TIME_10HOUR_SHF) & RTC_TIME_10HOUR_MSK) |
+		  ((single  << RTC_TIME_HOUR_SHF) & RTC_TIME_HOUR_MSK);
+
+	/* day */
+	single = ++(mvTime->day);
+	timeVal |= ((single << RTC_TIME_DAY_SHF) & RTC_TIME_DAY_MSK);
+
+	/* Update RTC Time Register */
+	MV_REG_WRITE(RTC_TIME_REG, timeVal);
+
+	/* date */
+	tens = mvTime->date / 10;
+	single = mvTime->date % 10;
+	dateVal = ((tens  << RTC_DATE_10DAY_SHF) & RTC_DATE_10DAY_MSK) |
+		  ((single << RTC_DATE_DAY_SHF) & RTC_DATE_DAY_MSK);
+
+	/* month */
+	tens = mvTime->month / 10;
+	single = mvTime->month % 10;
+	dateVal |= ((tens  << RTC_DATE_10MONTH_SHF) & RTC_DATE_10MONTH_MSK) |
+		  ((single << RTC_DATE_MONTH_SHF) & RTC_DATE_MONTH_MSK);
+
+	/* year */
+	tens = mvTime->year / 10;
+	single = mvTime->year % 10;
+	dateVal |= ((tens  << RTC_DATE_10YEAR_SHF) & RTC_DATE_10YEAR_MSK) |
+		  ((single << RTC_DATE_YEAR_SHF) & RTC_DATE_YEAR_MSK);
+
+	/* Update RTC Date Register */
+	MV_REG_WRITE(RTC_DATE_REG, dateVal);
+
+
+	return;
+}
+
+/*******************************************************************************
+* mvRtcTimeGet - Read the time from the RTC.
+*
+* DESCRIPTION:
+*       This function reads the current time and date from the RTC into the
+*       structure RTC_TIME (defined in mv.h).
+*
+* INPUT:
+*       time - A pointer to a structure TIME (defined in mv.h).
+*
+* OUTPUT:
+*       The structure RTC_TIME is updated with the time read from the RTC.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcTimeGet(MV_RTC_TIME *mvTime)
+{
+	MV_U32 timeVal;
+	MV_U32 dateVal;
+	MV_U8 tens;
+	MV_U8 single;
+
+	/* read Time register */
+	timeVal = MV_REG_READ(RTC_TIME_REG);
+
+	/* seconds */
+	tens = ((timeVal & RTC_TIME_10SECONDS_MSK) >> RTC_TIME_10SECONDS_SHF);
+	single = ((timeVal & RTC_TIME_SECONDS_MSK) >> RTC_TIME_SECONDS_SHF);
+	mvTime->seconds = 10*tens + single;
+
+	/* minutes */
+	tens = ((timeVal & RTC_TIME_10MINUTES_MSK) >> RTC_TIME_10MINUTES_SHF);
+	single = ((timeVal & RTC_TIME_MINUTES_MSK) >> RTC_TIME_MINUTES_SHF);
+	mvTime->minutes = 10*tens + single;
+
+	/* hours */
+	tens = ((timeVal & RTC_TIME_10HOUR_MSK) >> RTC_TIME_10HOUR_SHF);
+	single = ((timeVal & RTC_TIME_HOUR_MSK) >> RTC_TIME_HOUR_SHF);
+	mvTime->hours = 10*tens + single;
+
+	/* day */
+	mvTime->day = ((timeVal & RTC_TIME_DAY_MSK) >> RTC_TIME_DAY_SHF);
+	mvTime->day--;
+
+	/* read Date register */
+	dateVal = MV_REG_READ(RTC_DATE_REG);
+
+	/* day */
+	tens = ((dateVal & RTC_DATE_10DAY_MSK) >> RTC_DATE_10DAY_SHF);
+	single = ((dateVal & RTC_DATE_DAY_MSK) >> RTC_DATE_DAY_SHF);
+	mvTime->date = 10*tens + single;
+
+	/* month */
+	tens = ((dateVal & RTC_DATE_10MONTH_MSK) >> RTC_DATE_10MONTH_SHF);
+	single = ((dateVal & RTC_DATE_MONTH_MSK) >> RTC_DATE_MONTH_SHF);
+	mvTime->month = 10*tens + single;
+
+	/* year */
+	tens = ((dateVal & RTC_DATE_10YEAR_MSK) >> RTC_DATE_10YEAR_SHF);
+	single = ((dateVal  & RTC_DATE_YEAR_MSK) >> RTC_DATE_YEAR_SHF);
+	mvTime->year = 10*tens + single;
+
+	return;
+}
+
+/*******************************************************************************
+* mvRtcInit - Initialize the clock.
+*
+* DESCRIPTION:
+*       This function initialize the RTC integrated unit.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvRtcInit(MV_VOID)
+{
+	return;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtc.h b/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtc.h
new file mode 100755
index 0000000..9737773
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtc.h
@@ -0,0 +1,101 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __INCmvRtch
+#define __INCmvRtch
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysRtcConfig.h"
+
+typedef struct time {
+	MV_U8  seconds;
+	MV_U8  minutes;
+	MV_U8  hours;
+	MV_U8  day;
+	MV_U8  date;
+	MV_U8  month;
+	MV_U8  century;
+	MV_U8  year;
+} MV_RTC_TIME;
+
+MV_VOID mvRtcInit(MV_VOID);
+
+MV_VOID mvRtcTimeSet(MV_RTC_TIME *time);
+
+MV_VOID mvRtcTimeGet(MV_RTC_TIME *time);
+
+MV_VOID mvRtcAlarmSet(MV_RTC_TIME *time);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __INCmvRtch */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtcReg.h b/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtcReg.h
new file mode 100755
index 0000000..f3fe79e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/integ_rtc/mvRtcReg.h
@@ -0,0 +1,127 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#ifndef __INCmvRtcRegh
+#define __INCmvRtcRegh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvSysRtcConfig.h"
+
+/* RTC Time Register */
+#define RTC_TIME_REG				(MV_RTC_REGS_BASE + 0)
+
+/* RTC Date Register */
+#define RTC_DATE_REG				(MV_RTC_REGS_BASE + 4)
+
+
+/* RTC Time Bit Definitions */
+#define RTC_TIME_SECONDS_SHF			0
+#define RTC_TIME_SECONDS_MSK			(0xF << RTC_TIME_SECONDS_SHF)
+#define RTC_TIME_10SECONDS_SHF			4
+#define RTC_TIME_10SECONDS_MSK			(0x7 << RTC_TIME_10SECONDS_SHF)
+
+#define RTC_TIME_MINUTES_SHF			8
+#define RTC_TIME_MINUTES_MSK			(0xF << RTC_TIME_MINUTES_SHF)
+#define RTC_TIME_10MINUTES_SHF			12
+#define RTC_TIME_10MINUTES_MSK			(0x7 << RTC_TIME_10MINUTES_SHF)
+
+#define RTC_TIME_HOUR_SHF			16
+#define RTC_TIME_HOUR_MSK			(0xF << RTC_TIME_HOUR_SHF)
+#define RTC_TIME_10HOUR_SHF			20
+#define RTC_TIME_10HOUR_MSK			(0x3 << RTC_TIME_10HOUR_SHF)
+
+
+#define RTC_TIME_HOUR_FORMAT_SHF		22
+#define RTC_TIME_HOUR_FORMAT_12_MSK		(1 << RTC_TIME_HOUR_FORMAT_SHF)
+#define RTC_TIME_HOUR_FORMAT_24_MSK		(0 << RTC_TIME_HOUR_FORMAT_SHF)
+
+#define RTC_TIME_DAY_SHF			24
+#define RTC_TIME_DAY_MSK			(0x7 << RTC_TIME_DAY_SHF)
+
+/* RTC Date Bit Definitions */
+#define RTC_DATE_DAY_SHF			0
+#define RTC_DATE_DAY_MSK			(0xF << RTC_DATE_DAY_SHF)
+#define RTC_DATE_10DAY_SHF			4
+#define RTC_DATE_10DAY_MSK			(0x3 << RTC_DATE_10DAY_SHF)
+
+#define RTC_DATE_MONTH_SHF			8
+#define RTC_DATE_MONTH_MSK			(0xF << RTC_DATE_MONTH_SHF)
+#define RTC_DATE_10MONTH_SHF			12
+#define RTC_DATE_10MONTH_MSK			(0x1 << RTC_DATE_10MONTH_SHF)
+
+#define RTC_DATE_YEAR_SHF			16
+#define RTC_DATE_YEAR_MSK			(0xF << RTC_DATE_YEAR_SHF)
+#define RTC_DATE_10YEAR_SHF			20
+#define RTC_DATE_10YEAR_MSK			(0xF << RTC_DATE_10YEAR_SHF)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCmvRtcRegh */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/rtc/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/rtc/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/rtc/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvLog.c b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvLog.c
new file mode 100755
index 0000000..f5741e8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvLog.c
@@ -0,0 +1,175 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvLog - C File for implementation of the core driver logger
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*
+*******************************************************************************/
+#include "mvSataSoc.h"
+#include "mvOsS.h"
+
+#if defined(MV_LOG_DEBUG) || defined(MV_LOG_ERROR)
+
+const char *mvLogMsgType[MV_MAX_MESSAGE_TYPE] = {
+	" (FATAL_ERROR) ",
+	" (ERROR) ",
+	" (DEBUG INIT) ",
+	" (DEBUG INTERRUPTS) ",
+	" (DEBUG SATA LINK) ",
+	" (DEBUG UDMA COMMAND) ",
+	" (DEBUG NON UDMA COMMAND) ",
+	" (DEBUG PM) ",
+	" (DEBUG) ",
+	" (INFO) ",
+};
+
+static MV_LOG_FILTER_HEADER mvLogInstance[MV_MAX_LOG_MODULES] = {
+	{MV_FALSE, 0, NULL},
+	{MV_FALSE, 0, NULL},
+	{MV_FALSE, 0, NULL},
+	{MV_FALSE, 0, NULL},
+	{MV_FALSE, 0, NULL},
+	{MV_FALSE, 0, NULL},
+	{MV_FALSE, 0, NULL},
+	{MV_FALSE, 0, NULL},
+};
+
+static char szMessageBuffer[1024];
+
+MV_BOOLEAN mvLogRegisterModule(MV_U8 moduleId, MV_U32 filterMask, const char *name)
+{
+	if (moduleId >= MV_MAX_LOG_MODULES)
+		return MV_FALSE;
+
+	if (mvLogInstance[moduleId].used == MV_TRUE)
+		return MV_FALSE;
+
+	if (name == NULL)
+		return MV_FALSE;
+
+	mvLogInstance[moduleId].filterMask = filterMask;
+	mvLogInstance[moduleId].name = name;
+	mvLogInstance[moduleId].used = MV_TRUE;
+	return MV_TRUE;
+}
+
+MV_BOOLEAN mvLogSetModuleFilter(MV_U8 moduleId, MV_U32 filterMask)
+{
+	if (moduleId >= MV_MAX_LOG_MODULES)
+		return MV_FALSE;
+
+	if (mvLogInstance[moduleId].used == MV_FALSE)
+		return MV_FALSE;
+
+	mvLogInstance[moduleId].filterMask = filterMask;
+	return MV_TRUE;
+}
+
+MV_U32 mvLogGetModuleFilter(MV_U8 moduleId)
+{
+	if (moduleId >= MV_MAX_LOG_MODULES)
+		return 0;
+
+	if (mvLogInstance[moduleId].used == MV_FALSE)
+		return 0;
+
+	return mvLogInstance[moduleId].filterMask;
+}
+
+void mvLogMsg(MV_U8 moduleId, MV_U32 type, const char *format, ...)
+{
+	int len;
+	va_list args;
+
+	if (moduleId >= MV_MAX_LOG_MODULES)
+		return;
+
+	if ((moduleId != MV_RAW_MSG_ID) &&
+	    ((mvLogInstance[moduleId].used == MV_FALSE) || ((mvLogInstance[moduleId].filterMask & type) == 0)))
+		return;
+
+	if ((moduleId != MV_RAW_MSG_ID) && (type & 0x1ff)) {
+		MV_U8 msgType = 0;
+		/* find least significant 1 */
+		while (msgType < MV_MAX_MESSAGE_TYPE) {
+			if (type & (1 << msgType))
+				break;
+
+			msgType++;
+		}
+		len = sprintf(szMessageBuffer, "%s%s", mvLogInstance[moduleId].name, mvLogMsgType[msgType]);
+	} else {
+		len = 0;
+	}
+	va_start(args, format);
+	vsprintf(&szMessageBuffer[len], format, args);
+	va_end(args);
+	MV_LOG_PRINT("%s", szMessageBuffer);
+}
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvLog.h b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvLog.h
new file mode 100755
index 0000000..b33148a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvLog.h
@@ -0,0 +1,174 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvLog.h - Header File for CORE driver logger
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*
+*******************************************************************************/
+#ifndef __INCmvLogh
+#define __INCmvLogh
+
+#ifdef __cplusplus
+extern "C"			/*{ */
+#endif				/* __cplusplus */
+#include "mvOsS.h"
+/*-------------H file-----------------------------*/
+#define MV_DEBUG_FATAL_ERROR                    0x01
+#define MV_DEBUG_ERROR                          0x02
+#define MV_DEBUG_INIT                           0x04
+#define MV_DEBUG_INTERRUPTS                     0x08
+#define MV_DEBUG_SATA_LINK                      0x10
+#define MV_DEBUG_UDMA_COMMAND                   0x20
+#define MV_DEBUG_NON_UDMA_COMMAND               0x40
+#define MV_DEBUG_PM                             0x80
+#define MV_DEBUG                                0x100
+#define MV_DEBUG_INFO                           0x200
+#define MV_DEBUG_ENABLE_ALL			0x3FF
+#define MV_MAX_LOG_MODULES         16
+#define MV_MAX_MESSAGE_TYPE        10
+#define MV_RAW_MSG_ID              0xF
+     typedef struct {
+	MV_BOOLEAN used;
+	MV_U32 filterMask;
+	const char *name;
+	char *filters;
+} MV_LOG_FILTER_HEADER;
+
+#if defined(MV_LOG_DEBUG) || defined(MV_LOG_ERROR)
+#define MV_LOGGER       1
+#if defined(WIN32)
+ULONG _cdecl DbgPrint(PCH Format, ...
+    );
+#define MV_LOG_PRINT    DbgPrint
+#elif defined(LINUX)
+#define MV_LOG_PRINT    printk
+#elif defined __DOS__
+#define MV_LOG_PRINT    printf
+#elif defined __UBOOT__
+#define MV_LOG_PRINT    printf
+#else
+#define MV_LOG_PRINT	printf
+#endif
+
+MV_BOOLEAN mvLogRegisterModule(MV_U8 moduleId, MV_U32 filterMask, const char *name);
+MV_BOOLEAN mvLogSetModuleFilter(MV_U8 moduleId, MV_U32 filterMask);
+MV_U32 mvLogGetModuleFilter(MV_U8 moduleId);
+void mvLogMsg(MV_U8 moduleId, MV_U32 type, const char *format, ...);
+
+#else /*defined (MV_LOG_DEBUG) || defined (MV_LOG_ERROR) */
+
+#undef MV_LOGGER
+
+#if defined(WIN32)
+#define MV_LOG_PRINT
+#define mvLogRegisterModule
+#define mvLogGetModuleFilter
+#define mvLogRegisterAllModules
+#define mvLogMsg
+
+#elif defined(MV_LINUX)
+#define MV_LOG_PRINT(x...)
+#define mvLogRegisterModule(x...)
+#define mvLogSetModuleFilter(x...)
+#define mvLogGetModuleFilter(x...)
+#define mvLogRegisterAllModules(x...)
+#define mvLogMsg(x...)
+
+#elif defined(MV_UBOOT)
+#define MV_LOG_PRINT(x...)
+#define mvLogRegisterModule(x...)
+#define mvLogSetModuleFilter(x...)
+#define mvLogGetModuleFilter(x...)
+#define mvLogRegisterAllModules(x...)
+#define mvLogMsg(x...)
+
+#elif defined(__DOS__)
+#define MV_LOG_PRINT()
+#define mvLogRegisterModule()
+#define mvLogSetModuleFilter()
+#define mvLogGetModuleFilter()
+#define mvLogRegisterAllModules()
+#define mvLogMsg()
+
+#else
+#define MV_LOG_PRINT
+#define mvLogRegisterModule
+#define mvLogSetModuleFilter
+#define mvLogGetModuleFilter
+#define mvLogRegisterAllModules
+#define mvLogMsg
+#endif
+
+#endif /*!defined (MV_LOG_DEBUG) && !defined (MV_LOG_ERROR) */
+
+#ifdef __cplusplus
+
+/*}*/
+#endif /* __cplusplus */
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvOsS.h b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvOsS.h
new file mode 100755
index 0000000..374bc5f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvOsS.h
@@ -0,0 +1,100 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvOsSh
+#define __INCmvOsSh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes */
+#include "mvOs.h"
+
+#if defined(MV_LINUX)
+
+#include "mvOsSata.h"
+
+#elif defined(CV_PLATFORM)
+
+#include "mvOsSata.h"
+
+#elif defined(MV_UBOOT)
+
+#include "mvOsSata.h"
+
+#elif defined(MV_VXWORKS)
+
+#include "mvOsSVxw.h"
+
+#elif defined(MV_NETBSD)
+
+#include "mvOsSata.h"
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __INCmvOsSh */
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvRegs.h b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvRegs.h
new file mode 100755
index 0000000..44c60c2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvRegs.h
@@ -0,0 +1,410 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvRegs.h - Header file that includes the regs addresses
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __INCmvRegs
+#define __INCmvRegs
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+/* General Definitions */
+#define MV_BIT0                                 0x00000001
+#define MV_BIT1                                 0x00000002
+#define MV_BIT2                                 0x00000004
+#define MV_BIT3                                 0x00000008
+#define MV_BIT4                                 0x00000010
+#define MV_BIT5                                 0x00000020
+#define MV_BIT6                                 0x00000040
+#define MV_BIT7                                 0x00000080
+#define MV_BIT8                                 0x00000100
+#define MV_BIT9                                 0x00000200
+#define MV_BIT10                                0x00000400
+#define MV_BIT11                                0x00000800
+#define MV_BIT12                                0x00001000
+#define MV_BIT13                                0x00002000
+#define MV_BIT14                                0x00004000
+#define MV_BIT15                                0x00008000
+#define MV_BIT16                                0x00010000
+#define MV_BIT17                                0x00020000
+#define MV_BIT18                                0x00040000
+#define MV_BIT19                                0x00080000
+#define MV_BIT20                                0x00100000
+#define MV_BIT21                                0x00200000
+#define MV_BIT22                                0x00400000
+#define MV_BIT23                                0x00800000
+#define MV_BIT24                                0x01000000
+#define MV_BIT25                                0x02000000
+#define MV_BIT26                                0x04000000
+#define MV_BIT27                                0x08000000
+#define MV_BIT28                                0x10000000
+#define MV_BIT29                                0x20000000
+#define MV_BIT30                                0x40000000
+#define MV_BIT31                                0x80000000
+
+#define MV_PCI_REGS_OFFSET                      0x0
+
+/* PCI registers */
+
+#define MV_MAIN_INTERRUPT_CAUSE_REG_OFFSET      0x1d60
+
+#define MV_MAIN_INTERRUPT_MASK_REG_OFFSET       0x1d64
+#define MV_MAIN_INTERRUPT_MASK_REG_ALL_BITS     0x7ffff
+#define MV_MAIN_INTERRUPT_MASK_REG_PCIERR_BIT   MV_BIT18
+#define MV_MAIN_INTERRUPT_HOST_SELF_INT_BIT     MV_BIT23
+
+#define MV_PCI_CONTROL_REG_OFFSET               0x1d68
+#define MV_PCI_CONTROL_REG_H2H_INT_BIT          MV_BIT1
+
+/* enable ports error, coalescing done and pci error*/
+#define MV_MAIN_INTERRUPT_MASK_ENABLE_ALL       0x6ab55
+
+#define MV_PCI_DLL_STATUS_CONTROL_REG_OFFSET    0x1d20
+#define MV_PCI_COMMAND_REG_OFFSET               0xc00
+#define MV_PCI_COMMAND_REG_DEFAULT              0x0107E371
+#define MV_PCI_COMMAND_PCI_CONVENTIONAL_ONLY            \
+    (MV_BIT5|MV_BIT6|MV_BIT7|MV_BIT8|MV_BIT9|MV_BIT31)
+#define MV_PCI_MWRITE_COMBINE_BIT               MV_BIT4
+#define MV_PCI_MREAD_COMBINE_BIT                MV_BIT5
+
+#define MV_PCI_MODE_REG_OFFSET                  0xd00
+#define MV_PCI_MODE_MASK                        0x30
+#define MV_PCI_MODE_OFFSET                      4
+
+#define MV_PCI_DISCARD_TIMER_REG_OFFSET         0xd04
+
+#define MV_PCI_MSI_TRIGGER_REG_OFFSET           0xc38
+
+#define MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET 0xd2c
+
+#define MV_PCI_XBAR_IF_TIMEOUT_REG_OFFSET       0x1d04
+
+#define MV_PCI_SERR_MASK_REG_OFFSET             0xc28
+#define MV_PCI_SERR_MASK_REG_ENABLE_ALL         0xd77fe6
+
+#define MV_PCI_INTERRUPT_CAUSE_REG_OFFSET       0x1d58
+
+#define MV_PCI_INTERRUPT_MASK_REG_OFFSET        0x1d5c
+
+#define MV_PCI_INTERRUPT_MASK_REG_ENABLE_ALL    MV_PCI_SERR_MASK_REG_ENABLE_ALL
+
+#define MV_PCI_ERROR_LOW_ADDRESS_REG_OFFSET     0x1d40
+
+#define MV_PCI_ERROR_HIGH_ADDRESS_REG_OFFSET    0x1d44
+
+#define MV_PCI_ERROR_ATTRIBUTE_REG_OFFSET       0x1d48
+
+#define MV_PCI_ERROR_COMMAND_REG_OFFSET         0x1d50
+
+#define MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET   0xd30	/*Relevant for 60x1 only */
+#define MV_PCI_MAIN_COMMAND_DIS_CORE_CLK_MASK   MV_BIT0
+#define MV_PCI_MAIN_COMMAND_DIS_SHC1_CLK_MASK   MV_BIT0
+#define MV_PCI_MAIN_COMMAND_STOP_MASTER_MASK    MV_BIT2
+#define MV_PCI_MAIN_COMMAND_MASTER_EMPTY_MASK   MV_BIT3
+#define MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK   MV_BIT4
+
+/*PEX (PCI-Express registers*/
+#define MV_PCI_E_INTERRUPT_CAUSE_REG_OFFSET     0x1900
+#define MV_PCI_E_INTERRUPT_MASK_REG_OFFSET      0x1910
+#define MV_PCI_E_ERROR_MASK_VALUE               (MV_BIT10|MV_BIT9|MV_BIT8|MV_BIT3|MV_BIT1)
+/* Flash interface registers */
+#define MV_FLASH_PARAMS_REG_OFFSET              0x1046c
+
+#define MV_FLASH_GPIO_PORT_CONTROL_OFFSET       0x104f0
+
+#define MV_RESET_CONFIG_REG_OFFSET              0x180d8
+#define MV_RESET_CONFIG_TWSI_INIT_MASK          MV_BIT0
+#define MV_SATA_II_ALL_PORTS_INT_COAL_CMND_THR_REG_OFFSET 0x180cc
+
+#define MV_SATA_II_ALL_PORTS_INT_COAL_TIME_THR_REG_OFFSET 0x180d0
+
+#define MV_SATA_II_ALL_PORTS_INT_CAUSE_REG_OFFSET 0x18008
+
+/* SATAHC registers*/
+#define MV_SATAHC_0_REGS_BASE_OFFSET            0x20000	/* 128KByte offset */
+
+#define MV_SATAHC_1_REGS_BASE_OFFSET            0x30000	/* 192KByte offset */
+
+#define MV_SATAHC_REGS_BASE_OFFSET(unit)    ((unit) ? (MV_SATAHC_1_REGS_BASE_OFFSET) : (MV_SATAHC_0_REGS_BASE_OFFSET))
+
+#define MV_SATAHC_XBAR_CONF_REG_OFFSET          0x000
+
+#define MV_SATAHC_RESPONSE_Q_IN_POINTER_OFFSET  0x008
+
+#define MV_SATAHC_INT_COAL_THRE_REG_OFFSET      0x00c
+
+#define MV_SATAHC_INT_TIME_THRE_REG_OFFSET      0x010
+
+#define MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET    0x014
+
+#define MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET    0x018
+#define MV_SATA_I_TEST_CONTROL_PATTERN_MASK         0x7
+#define MV_SATA_I_TEST_CONTROL_PATTERN_OFFSET           10
+#define MV_SATA_I_TEST_CONTROL_PORT_MASK                0x3
+#define MV_SATA_I_TEST_CONTROL_PORT_OFFSET              13
+#define MV_SATA_I_TEST_CONTROL_PHY_SHUTDOWN_MASK(port)  ((MV_U32)1 << (24 + (port)))
+
+#define MV_SATA_I_HC_BRIDGES_TEST_STATUS_REG_OFFSET 0x01c
+#define MV_SATA_I_TEST_STATUS_LOOPBACK_PASS_BIT     MV_BIT8
+
+#define MV_SATA_I_HC_BRIDGES_PINS_CONFIG_REG_OFFSET 0x020
+
+#define MV_SATA_I_HC_R00_STATUS_BRIDGE_PORT_OFFSET(port)        \
+    (0x100 + (port)*0x100)
+
+#define MV_SATA_I_HC_R00_STATUS_BRIDGE_DET_OFFSET  0x0
+#define MV_SATA_I_HC_R00_STATUS_BRIDGE_DET_MASK 0xf
+
+#define MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port)    \
+    (0x108 + (port)*0x100)
+
+#define MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port)   \
+    (0x10C + (port)*0x100)
+
+#define MV_SATA_I_HC_R04_STATUS_BRIDGE_PORT_OFFSET(port)    \
+    (0x110 + (port)*0x100)
+#define MV_SATA_I_HC_R05_STATUS_BRIDGE_PORT_OFFSET(port)    \
+    (0x114 + (port)*0x100)
+#define MV_SATA_I_HC_R06_STATUS_BRIDGE_PORT_OFFSET(port)    \
+    (0x118 + (port)*0x100)
+#define MV_SATA_I_HC_R0F_STATUS_BRIDGE_PORT_OFFSET(port)    \
+    (0x13c + (port)*0x100)
+#define MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port)         \
+    (0x130 + ((port) * 0x100))
+#define MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port)  \
+    (0x174 + ((port) * 0x100))
+#define MV_SATA_I_PHY_MODE_AMP_MASK             0xe0
+#define MV_SATA_I_PHY_MODE_AMP_OFFSET               5
+#define MV_SATA_I_PHY_MODE_PRE_MASK             0x1800
+#define MV_SATA_I_PHY_MODE_PRE_OFFSET               11
+
+#define MV_SATA_II_PHY_MODE_1_REG_OFFSET        0x32c
+
+#define MV_SATA_II_PHY_MODE_2_REG_OFFSET        0x330
+#define MV_SATA_II_PHY_MODE_2_AMP_MASK          0x700
+#define MV_SATA_II_PHY_MODE_2_AMP_OFFSET        8
+#define MV_SATA_II_PHY_MODE_2_PRE_MASK          0xe0
+#define MV_SATA_II_PHY_MODE_2_PRE_OFFSET        5
+
+#define MV_SATA_II_PHY_MODE_3_REG_OFFSET        0x310
+
+#define MV_SATA_II_PHY_MODE_4_REG_OFFSET        0x314
+
+#define MV_SATA_II_IF_CONTROL_REG_OFFSET        0x344
+#define MV_SATA_II_IF_CONTROL_PMTX_OFFSET       0
+#define MV_SATA_II_IF_CONTROL_PMTX_MASK         0xf
+
+#define MV_SATA_II_IF_TEST_CTRL_REG_OFFSET		0x348
+
+#define MV_SATA_II_IF_STATUS_REG_OFFSET         0x34c
+#define MV_SATA_II_IF_STATUS_VUQ_DONE_MASK      MV_BIT12
+#define MV_SATA_II_IF_STATUS_VUQ_ERR_MASK       MV_BIT13
+#define MV_SATA_II_IF_STATUS_FSM_STATUS_MASK    0x3f000000
+
+#define MV_SATA_II_VENDOR_UQ_REG_OFFSET         0x35c
+
+#define MV_SATA_II_S_STATUS_REG_OFFSET          0x300
+
+#define MV_SATA_II_S_ERROR_REG_OFFSET           0x304
+
+#define MV_SATA_II_S_CONTROL_REG_OFFSET         0x308
+
+#define MV_SATA_II_SATA_CONFIG_REG_OFFSET       0x50
+
+#define MV_SATA_II_LP_EXT_CTRL_REG_OFFSET       0x58
+
+#define MV_SATA_II_PHY_MODE_9_GEN1_REG_OFFSET   0x39c
+#define MV_SATA_II_PHY_MODE_9_GEN2_REG_OFFSET   0x398
+/* EDMA registers */
+
+#define MV_EDMA_PORT_BASE_OFFSET(port)          (0x2000UL * ((port) + 1))
+
+#define MV_EDMA_CONFIG_REG_OFFSET               0x000
+#define MV_EDMA_CONFIG_Q_DEPTH_MASK             0x1f
+#define MV_EDMA_CONFIG_NATIVE_QUEUING_MASK      MV_BIT5	/* Relevant for 60x1 */
+#define MV_EDMA_CONFIG_BURST_SIZE_MASK          MV_BIT8
+#define MV_EDMA_CONFIG_EQUEUE_ENABLED_MASK      MV_BIT9
+#define MV_EDMA_CONFIG_STOP_ON_ERROR_MASK       MV_BIT10
+#define MV_EDMA_CONFIG_BURST_SIZE_EXT_MASK      MV_BIT11
+#define MV_EDMA_CONFIG_CONONDEVERR_MASK			MV_BIT14
+
+#define MV_EDMA_TIMER_REG_OFFSET                0x004
+
+#define MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET 0x008
+
+#define MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET  0x00c
+
+/* unrecoverable EDMA errors*/
+#define MV_EDMA_GEN_I_UNRECOVERABLE_EDMA_ERROR		0x00001E6B
+#define MV_EDMA_GEN_I_RECOVERABLE_EDMA_ERROR		0x00000000
+#define MV_EDMA_GEN_I_ERROR_MASK					0x00001118
+
+#define MV_EDMA_GEN_II_UNRECOVERABLE_EDMA_ERROR		0xFC1E9E0B
+#define MV_EDMA_GEN_II_RECOVERABLE_EDMA_ERROR		0x03E16020
+#define MV_EDMA_GEN_II_NORMAL_RCVRBL_EDMA_ERROR		0x02200000
+
+/*don't enable rcvrbl errors that occur too often*/
+#define MV_EDMA_GEN_II_ERROR_MASK					0xFDDFF198
+
+#define MV_EDMA_REQUEST_Q_BAH_REG_OFFSET        0x010
+
+#define MV_EDMA_REQUEST_Q_INP_REG_OFFSET        0x014
+#define MV_EDMA_REQUEST_Q_INP_MASK              0x000003e0
+#define MV_EDMA_REQUEST_Q_INP_OFFSET            5
+#define MV_EDMA_REQUEST_Q_BA_MASK               0xfffffc00
+
+#define MV_EDMA_GEN2E_REQUEST_Q_INP_MASK        0x00000fe0
+#define MV_EDMA_GEN2E_REQUEST_Q_BA_MASK         0xfffff000
+
+#define MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET       0x018
+#define MV_EDMA_REQUEST_Q_OUTP_MASK             0x000003e0
+
+#define MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET       0x01c
+
+#define MV_EDMA_RESPONSE_Q_INP_REG_OFFSET       0x020
+#define MV_EDMA_RESPONSE_Q_INP_MASK             0x000000f8
+
+#define MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET      0x024
+#define MV_EDMA_RESPONSE_Q_OUTP_MASK            0x000000f8
+#define MV_EDMA_RESPONSE_Q_OUTP_OFFSET          3
+
+#define MV_EDMA_RESPONSE_Q_BA_MASK              0xffffff00
+
+#define MV_EDMA_COMMAND_REG_OFFSET              0x028
+#define MV_EDMA_COMMAND_ENABLE_MASK             MV_BIT0
+#define MV_EDMA_COMMAND_DISABLE_MASK            MV_BIT1
+#define MV_EDMA_COMMAND_HARD_RST_MASK           MV_BIT2
+
+#define MV_EDMA_TEST_CONTROL_REG_OFFSET         0x02c
+#define MV_EDMA_LOOPBACK_MODE_BIT               MV_BIT1
+
+#define MV_EDMA_STATUS_REG_OFFSET               0x030
+#define MV_EDMA_STATUS_TAG_MASK                 0x1f
+#define MV_EDMA_STATUS_TAG_OFFSET               0
+#define MV_EDMA_STATUS_ECACHE_EMPTY_BIT			MV_BIT6
+#define MV_EDMA_STATUS_EDMA_IDLE_BIT			MV_BIT7
+
+#define MV_EDMA_IORDY_TIMEOUT_REG_OFFSET        0x034
+
+#define MV_EDMA_ARBITER_CNFG_REG_OFFSET         0x038
+#define MV_EDMA_NO_SNOOP_BIT                    MV_BIT6
+
+#define MV_EDMA_CMD_DELAY_THRE_REG_OFFSET       0x040
+
+#define MV_EDMA_HALT_CONDITIONS_REG_OFFSET      0x060
+
+#define MV_EDMA_TCQ_STATUS_REG_OFFSET           0x08c
+
+#define MV_EDMA_NCQTCQ0_OUTSTANDING_REG_OFFSET	0x094
+#define MV_EDMA_NCQTCQ1_OUTSTANDING_REG_OFFSET	0x098
+#define MV_EDMA_NCQTCQ2_OUTSTANDING_REG_OFFSET	0x09c
+#define MV_EDMA_NCQTCQ3_OUTSTANDING_REG_OFFSET	0x0a0
+
+#define MV_EDMA_FIS_CONFIGURATION_REG_OFFSET	0x360
+#define MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET	0x364
+#define MV_EDMA_FIS_INTERRUPT_MASK_REG_OFFSET	0x368
+/* C2C */
+/* BM DMA */
+#define MV_BMDMA_COMMAND_OFFSET                 0x224
+#define MV_BMDMA_STATUS_OFFSET                  0x228
+#define MV_BMDMA_PRD_TABLE_LOW_ADDRESS_OFFSET   0x22c
+#define MV_BMDMA_PRD_TABLE_HIGH_ADDRESS_OFFSET  0x230
+
+/* storage device registers*/
+
+#define MV_ATA_DEVICE_PIO_DATA_REG_OFFSET       0x100
+#define MV_ATA_DEVICE_FEATURES_REG_OFFSET       0x104
+#define MV_ATA_DEVICE_ERROR_REG_OFFSET          MV_ATA_DEVICE_FEATURES_REG_OFFSET
+#define MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET   0x108
+#define MV_ATA_DEVICE_LBA_LOW_REG_OFFSET        0x10c
+#define MV_ATA_DEVICE_LBA_MID_REG_OFFSET        0x110
+#define MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET       0x114
+#define MV_ATA_DEVICE_HEAD_REG_OFFSET           0x118
+#define MV_ATA_DEVICE_COMMAND_REG_OFFSET        0x11c
+#define MV_ATA_DEVICE_STATUS_REG_OFFSET         MV_ATA_DEVICE_COMMAND_REG_OFFSET
+#define MV_ATA_DEVICE_CONTROL_REG_OFFSET        0x120
+#define MV_ATA_DEVICE_ALTERNATE_REG_OFFSET      MV_ATA_DEVICE_CONTROL_REG_OFFSET
+
+#define MV_IOG_TRANS_LOW_BIT      (MV_BIT19)
+#define MV_IOG_TRANS_HIGH_BIT     (MV_BIT20)
+#define MV_IOG_TRANS_INT_MASK     (MV_IOG_TRANS_LOW_BIT | MV_IOG_TRANS_HIGH_BIT)
+#define MV_IOG_TRANS_LOW_REG_OFFSET  0x18088
+#define MV_IOG_TRANS_HIGH_REG_OFFSET 0x1808C
+#define MV_IOG_TRANS_CTRL_REG_OFFSET 0x18048
+
+#define MV_SATA_MAX_ADDR_DECODE_WIN 4
+
+#ifdef __cplusplus
+}
+#endif				/* __cplusplus */
+#endif				/* __INCmvRegs */
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSata.c b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSata.c
new file mode 100755
index 0000000..592aa8a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSata.c
@@ -0,0 +1,8362 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvSata - C File for implementation of the core driver for Marvell's Sata
+*           Adapters.
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*   mvOs.h
+*   mvSata.h.
+*   mvStorageDev.h
+*   mvRegs.h
+*
+*******************************************************************************/
+#include "mvSataSoc.h"
+#include "mvOsS.h"
+#include "mvSata.h"
+#include "mvStorageDev.h"
+#include "mvRegs.h"
+
+/* Defines */
+#define MV_SATA_PORT_PER_UNIT                   4
+
+#define MV_PHY_DET_STATE_NO_DEVICE              0
+#define MV_PHY_DET_STATE_DEVICE_NO_PHY_COM      1
+#define MV_PHY_DET_STATE_DEVICE_AND_PHY_COM     3
+#define MV_PHY_DET_STATE_PHY_OFFLINE            4
+#define MV_PHY_DET_CONTROL_START_NEGOTIATION    1
+#define MV_PHY_DET_CONTROL_SHUTDOWN             4
+#define MV_NEAR_END_LOOPBACK_TEST_WAIT_TIME     100	/* 100 uSec */
+#define MV_FAR_END_LOOPBACK_TEST_WAIT_TIME      5	/* 5 uSec */
+#define MV_PHY_COM_SETUP_WAIT                   5000	/* 5 mili seconds */
+#define MV_HARD_RESET_WAIT_ASSERT               25	/* 25 uSec */
+#define MV_HARD_RESET_WAIT_NEGATE               1000	/* 1  mSec */
+#define MV_HARD_RESET_WAIT_READY                2000	/* ms to wait after HR */
+/* before disk access */
+#define MV_HARD_RESET_WAIT_FOR_BUSY_LOOPS       10000
+#define MV_HARD_RESET_WAIT_FOR_BUSY_LOOP_DELAY  1000
+
+/* for the command result */
+#define MV_EDMA_REQUEST_COMMANDS_NUM            11
+
+/* Fix the watermark to the following default value */
+#define MV_WATER_MARK_FIX                       29	/* write 5'b11101 to bits 12:8 */
+
+extern MV_BOOLEAN waitWhileStorageDevIsBusy(MV_SATA_ADAPTER *pAdapter,
+					    MV_BUS_ADDR_T ioBaseAddr,
+					    MV_U32 eDmaRegsOffset, MV_U32 loops, MV_U32 delay);
+
+extern void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter,
+				   MV_U8 channelIndex, MV_BOOLEAN isEXT, MV_STORAGE_DEVICE_REGISTERS *pRegisters);
+
+extern MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel);
+
+MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel);
+
+extern MV_BOOLEAN executeNonUDMACommand(MV_SATA_ADAPTER *pAdapter,
+					MV_U8 channelIndex,
+					MV_U8 PMPort,
+					MV_NON_UDMA_PROTOCOL protocolType,
+					MV_BOOLEAN isEXT,
+					MV_U16_PTR bufPtr, MV_U32 count,
+					MV_U16 features,
+					MV_U16 sectorCount,
+					MV_U16 lbaLow, MV_U16 lbaMid, MV_U16 lbaHigh, MV_U8 device, MV_U8 command);
+
+extern MV_BOOLEAN waitForDRQ(MV_SATA_ADAPTER *pAdapter,
+			     MV_BUS_ADDR_T ioBaseAddr, MV_U32 eDmaRegsOffset, MV_U32 loops, MV_U32 delay);
+
+static void _setRegBits(MV_BUS_ADDR_T ioBaseAddr, MV_U32 offset, MV_U32 bits)
+{
+	MV_U32 regVal = MV_REG_READ_DWORD(ioBaseAddr, offset);
+	regVal |= bits;
+	MV_REG_WRITE_DWORD(ioBaseAddr, offset, regVal);
+}
+
+static void _clearRegBits(MV_BUS_ADDR_T ioBaseAddr, MV_U32 offset, MV_U32 bits)
+{
+	MV_U32 regVal = MV_REG_READ_DWORD(ioBaseAddr, offset);
+	regVal &= ~bits;
+	MV_REG_WRITE_DWORD(ioBaseAddr, offset, regVal);
+}
+
+static MV_U32 getRegField(MV_U32 regVal, MV_U32 fieldOff, MV_U32 bitsNum);
+
+static MV_BOOLEAN _checkSStatusAfterHReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+#ifdef MV_LOGGER
+
+void _dumpPCIRegs(MV_SATA_ADAPTER *pAdapter);
+void _dumpEDMARegs(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+void _dumpChannelQueues(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+void _dumpSataRegs(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+void _printATARegs(MV_STORAGE_DEVICE_REGISTERS *pDeviceRegs);
+
+#else
+
+#define _dumpPCIRegs(p)
+#define _dumpEDMARegs(p, i)
+#define _dumpChannelQueues(p, i)
+#define _dumpSataRegs(p, i)
+#define _printATARegs(p)
+
+#endif
+
+/* write ATA command register entry in a request entry */
+#define WRITE_ATA_COMMAND_REG(addr, data, reg, isLast)              \
+do {                                                                 \
+	*(addr) = MV_CPU_TO_LE16((((MV_U8)(data)) & 0xff) | ((reg) << 8) | (isLast));   \
+} while (0)
+
+#define MV_CHANNEL_INDEX(unit, port)    (((unit) << 2) | (port))
+
+/* Typedefs */
+
+typedef struct mvDmaRequestQueueEntry {
+	/* Fields set by CORE driver */
+	volatile MV_U32 prdLowAddr;
+	volatile MV_U32 prdHighAddr;
+	volatile MV_U16 controlFlags;
+	volatile MV_U16 command[MV_EDMA_REQUEST_COMMANDS_NUM];
+} MV_DMA_REQUEST_QUEUE_ENTRY;
+
+/*CRQP Data structure of the fourth generation devices*/
+typedef struct mvGen2EEdmaRequestQueueEntry {
+	/* Fields set by CORE driver */
+	volatile MV_U32 prdLowAddr;
+	volatile MV_U32 prdHighAddr;
+	volatile MV_U32 controlFlags;
+	volatile MV_U16 dataRegionByteCount;
+	volatile MV_U16 reserved[2];
+	volatile MV_U8 ATACommand;
+	volatile MV_U8 ATAFeatures;
+	volatile MV_U8 ATALBALow;
+	volatile MV_U8 ATALBAMid;
+	volatile MV_U8 ATALBAHigh;
+	volatile MV_U8 ATADevice;
+	volatile MV_U8 ATALBALowExp;
+	volatile MV_U8 ATALBAMidExp;
+	volatile MV_U8 ATALBAHighExp;
+	volatile MV_U8 ATAFeaturesExp;
+	volatile MV_U8 ATASectorCount;
+	volatile MV_U8 ATASectorCountExp;
+	volatile MV_U16 reserved2;
+} MV_GEN2E_EDMA_REQUEST_QUEUE_ENTRY;
+
+typedef struct mvDmaResponseQueueEntry {
+	/* Fields set by  hardware */
+	volatile MV_U16 id;
+	volatile MV_U16 responseFlags;
+	volatile MV_U32 timeStamp;
+} MV_DMA_RESPONSE_QUEUE_ENTRY;
+
+/* local functions  */
+
+/*static*/ MV_BOOLEAN waitForBusyAfterHReset(MV_SATA_ADAPTER *pAdapter,
+					     MV_U8 channelIndex);
+
+static void unmaskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static void maskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static void setupEdmaDeviceErrorHandlingConfiguration(MV_SATA_CHANNEL *pSataChannel);
+
+static void writeEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry,
+				  MV_SATA_CHANNEL *mvSataChannel,
+				  MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_UDMA_COMMAND_PARAMS *pUdmaParams);
+
+static void writeGen2EEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry,
+				       MV_SATA_CHANNEL *mvSataChannel,
+				       MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_UDMA_COMMAND_PARAMS *pUdmaParams);
+
+static void handleEdmaFailedCommand(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U16 eDmaErrorCause);
+
+static void handleEdmaResponse(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			       MV_DMA_RESPONSE_QUEUE_ENTRY *eDmaResponse);
+
+#ifdef MV_SATA_C2C_COMM
+static void handleBmDMAInterrupt(MV_SATA_ADAPTER *pAdapter,
+				 MV_BUS_ADDR_T ioBaseAddr,
+				 MV_SATA_CHANNEL *pSataChannel, MV_U8 channelIndex, MV_U32 edmaError);
+#endif
+
+static void handleEdmaInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit,
+				MV_U8 port, MV_U8 rspInPtr, MV_U32 responseDone, MV_U32 edmaError, MV_U32 unitCause);
+
+static void handleDeviceInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, MV_U8 port);
+
+static void handleEdmaError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static MV_VOID handleDisconnect(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static MV_VOID handleConnect(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static MV_BOOLEAN handleUnrecoverableError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause);
+
+static MV_BOOLEAN handleRecoverableError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause);
+
+static MV_BOOLEAN handleAsyncNotify(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause);
+
+static MV_BOOLEAN handleSelfDisable(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause);
+
+static MV_BOOLEAN handleDevErr(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause);
+
+#ifdef MV_SATA_C2C_COMM
+static void handleC2CInterrupt(MV_SATA_CHANNEL *pSataChannel);
+#endif
+static MV_BOOLEAN sendVendorUniqueFIS(MV_SATA_ADAPTER *pAdapter,
+				      MV_U8 channelIndex, MV_U32 *vendorUniqueBuffer, MV_U8 numOfDWords);
+
+static void handlePIOInterrupt(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry);
+
+static MV_BOOLEAN transferPIOData(MV_SATA_CHANNEL *pSataChannel, MV_NONE_UDMA_COMMAND_PARAMS *pNoneUdmaCommandParams);
+
+#ifdef MV_SUPPORT_ATAPI
+static MV_BOOLEAN transferPacketData(MV_SATA_CHANNEL *pSataChannel,
+				     MV_PACKET_COMMAND_PARAMS *pPacketCommandParams, MV_U16 byteCount);
+
+static void completePacketCommand(MV_SATA_CHANNEL *pSataChannel,
+				  MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_BOOLEAN failed);
+#endif
+static void completePIOCommand(MV_SATA_CHANNEL *pSataChannel,
+			       MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_BOOLEAN failed);
+
+static MV_BOOLEAN _resetEdmaQPointers(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_BOOLEAN resetEdmaChannel(MV_SATA_CHANNEL *pSataChannel);
+
+static void flushDmaQueue(MV_SATA_CHANNEL *pSataChannel, MV_FLUSH_TYPE flushType, MV_COMPLETION_TYPE, MV_U16);
+
+static void _fixPhyParams(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelIndex);
+
+static void _channelHardReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static void _establishSataComm(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static void _establishSataCommAll(MV_SATA_ADAPTER *pAdapter);
+
+void _setActivePMPort(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort);
+
+static void revertSataHCRegs(MV_SATA_ADAPTER *pAdapter);
+
+static void revertFlashInterfaceRegs(MV_SATA_ADAPTER *pAdapter);
+
+static void revertPCIInterfaceRegs(MV_SATA_ADAPTER *pAdapter);
+
+static void revertPEXInterfaceRegs(MV_SATA_ADAPTER *pAdapter);
+
+static void commandsQueueAddTail(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry);
+
+static void commandsQueueRemove(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry);
+
+static void addCommand(MV_SATA_CHANNEL *pSataChannel,
+		       MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_QUEUE_COMMAND_INFO *pCommandInfo);
+
+static void removeCommand(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry);
+
+static void enableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+void disableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static void _checkATAStatus(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static void activateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static void deactivateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+static void EdmaReqQueueInsert(MV_SATA_CHANNEL *pSataChannel,
+			       MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_UDMA_COMMAND_PARAMS *pUdmaParams);
+
+static MV_BOOLEAN sendNoneUdmaCommand(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry);
+
+static MV_BOOLEAN isGoodCompletionsExpected(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_VOID updatePortsWithErrors(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_VOID setAbortedCommands(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_VOID enterRequestSenseState(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_BOOLEAN _getHostTagByDeviceTag(MV_SATA_CHANNEL *pSataChannel,
+					 MV_U8 deviceTag, MV_U8 PMPort, MV_U8 *pHostTag);
+
+static MV_BOOLEAN parseReadLogExtOutPut(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_BOOLEAN
+ReadLogExtCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
+		       MV_U8 channelNum,
+		       MV_COMPLETION_TYPE comp_type,
+		       MV_VOID_PTR commandId,
+		       MV_U16 responseFlags, MV_U32 timeStamp, MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+static MV_VOID setReadLogExtCmndPointers(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_VOID insertReadLogExtCmnd(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_VOID handlePortError(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_VOID softResetErringPorts(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_VOID _insertQCommandsIntoEdma(MV_SATA_CHANNEL *pSataChannel);
+
+static MV_BOOLEAN _doDevErrorRecovery(MV_SATA_CHANNEL *pSataChannel);
+
+#if defined(MV_SUPPORT_ATAPI) || defined(MV_SATA_C2C_COMM)
+static void activateBMDmaMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			      MV_U32 prdTableHi, MV_U32 prdTableLow, MV_UDMA_TYPE dmaType);
+#endif
+static void _resetBmDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+#ifdef MV_SATA_C2C_COMM
+
+/* Channel 2 Channel */
+static MV_BOOLEAN sendVendorUniqueFIS(MV_SATA_ADAPTER *pAdapter,
+				      MV_U8 channelIndex, MV_U32 *vendorUniqueBuffer, MV_U8 numOfDWords);
+
+#endif
+
+#ifdef MV_SATA_IO_GRANULARITY
+
+static void setIoGranularityCount(MV_SATA_ADAPTER *pAdapter, MV_U8 transId, MV_U8 counter);
+static MV_U8 readIoGranularityCount(MV_SATA_ADAPTER *pAdapter, MV_U8 transId);
+static void iogInterrupt(MV_SATA_ADAPTER *pAdapter, MV_BUS_ADDR_T ioBaseAddr, MV_U32 mainCause);
+static void checkIogCompletion(MV_SATA_ADAPTER *pAdapter, MV_U32 iogCause, MV_U8 offset);
+static void checkIogBit(MV_SATA_ADAPTER *pAdapter, MV_U8 bitOffset, MV_U8 value);
+
+static MV_BOOLEAN iogReset(MV_SATA_ADAPTER *pAdapter);
+#endif
+
+/* Calculate the base address of the registers for a SATA channel */
+MV_U32 edmaRegOffst[MV_SATA_CHANNELS_NUM] = { 0x22000, 0x24000, 0x26000, 0x28000,
+	0x32000, 0x34000, 0x36000, 0x38000
+};
+
+#define getEdmaRegOffset(x) edmaRegOffst[(x)]
+
+MV_BOOLEAN waitForBusyAfterHReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 i;
+	MV_U8 ATAstatus;
+	mvMicroSecondsDelay(pAdapter, MV_HARD_RESET_WAIT_READY);
+	for (i = MV_HARD_RESET_WAIT_READY; i < 5000000; i += 10000) {
+		ATAstatus = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress,
+					     getEdmaRegOffset(channelIndex) + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+		if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0)
+			return MV_TRUE;
+		mvMicroSecondsDelay(pAdapter, 10000);
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: in Channel "
+		 "Hard Reset wait for busy, ATA STATUS=0x%02x\n", pAdapter->adapterId, channelIndex, ATAstatus);
+	return MV_FALSE;
+}
+
+static void unmaskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		/*clear SError */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   edmaRegOffst[channelIndex] + MV_SATA_II_S_ERROR_REG_OFFSET, 0xFFFFFFFF);
+		if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) {
+			/* clear FIS Interrupt cause register */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   edmaRegOffst[channelIndex] + MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET, 0);
+		}
+	}
+
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+			   getEdmaRegOffset(channelIndex) + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, 0);
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		/* Unmask EDMA self disable (bit 8), mask errors that cause self disable */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   getEdmaRegOffset(channelIndex) +
+				   MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_EDMA_GEN_I_ERROR_MASK);
+	} else {
+		/* Unmask EDMA self disable (bit 7), mask errors that cause self disable */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   getEdmaRegOffset(channelIndex) +
+				   MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_EDMA_GEN_II_ERROR_MASK);
+	}
+}
+
+static void maskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+			   getEdmaRegOffset(channelIndex) + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, 0);
+}
+
+/*******************************************************************************
+* writeEdmaRequestEntry  - Write a CRQB (COMMAND REQUEST QUEUE BLOCK)
+*
+* DESCRIPTION:
+*       write one CRQB for an EDMA request queue.
+*
+* INPUT:
+*       pReqEntry     - pointer to the CRQB area on the system memory
+*                       (HW reqeust Queue).
+*       mvSataChannel - pointer to the channel data structure
+*       pCommandEntry - pointer to the command entry data structure
+*                       (SW request Queue).
+*
+* RETURN:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+static void writeEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry,
+				  MV_SATA_CHANNEL *mvSataChannel,
+				  MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_UDMA_COMMAND_PARAMS *pUdmaParams)
+{
+	MV_U16 ControlFlags = 0;
+	volatile MV_U16 *pCommand = &pReqEntry->command[0];
+	MV_U8 ATACommand = 0;
+
+	pReqEntry->prdLowAddr = MV_CPU_TO_LE32(pUdmaParams->prdLowAddr);
+	pReqEntry->prdHighAddr = MV_CPU_TO_LE32(pUdmaParams->prdHighAddr);
+
+	/* Set the direction of the transaction (read/write) */
+	if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
+		ControlFlags |= 0x1;	/* Device to system memory */
+
+	ControlFlags |= (pCommandEntry->hostTag << 1);	/* the tag will be used also */
+#ifdef MV_SATA_IO_GRANULARITY
+
+	/*If valid IO Granularity transaction Id */
+	if (pUdmaParams->iogCurrentTransId < MV_IOG_INVALID_COMMAND_ID) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND, "%d %d: "
+			 "Edma request with IO granularity Id = 0x%x\n",
+			 mvSataChannel->mvSataAdapter->adapterId,
+			 mvSataChannel->channelNumber, pUdmaParams->iogCurrentTransId);
+		ControlFlags |= (((MV_U16) pUdmaParams->iogCurrentTransId) << 6);
+	}
+#endif
+	/* in Non-queue EDMA mode    */
+	ControlFlags |= (pCommandEntry->pCommandInfo->PMPort << 12);
+
+	pReqEntry->controlFlags = MV_CPU_TO_LE16(ControlFlags);
+
+	if ((mvSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) ||
+	    (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)) {
+		if (pUdmaParams->isEXT == MV_TRUE) {	/* Read/Write DMA QUEUED EXT */
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->numOfSectors & 0xFF00) >> 8, MV_EDMA_ATA_FEATURES_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->numOfSectors) & 0xFF, MV_EDMA_ATA_FEATURES_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pCommandEntry->deviceTag << 3) & 0xF8, MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++, (pUdmaParams->lowLBAAddress & 0xFF000000)
+					      >> 24, MV_EDMA_ATA_LBA_LOW_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress) & 0xFF, MV_EDMA_ATA_LBA_LOW_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++, (pUdmaParams->highLBAAddress &
+							   0xFF), MV_EDMA_ATA_LBA_MID_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress & 0xFF00) >> 8, MV_EDMA_ATA_LBA_MID_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->highLBAAddress & 0xFF00) >> 8,
+					      MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress & 0xFF0000) >>
+					      16, MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
+
+			if ((mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) && (pUdmaParams->FUA == MV_TRUE))
+				WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT7 | MV_BIT6, MV_EDMA_ATA_DEVICE_ADDR, 0);
+			else
+				WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT6, MV_EDMA_ATA_DEVICE_ADDR, 0);
+
+			if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) {
+				if (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)
+					ATACommand = MV_ATA_COMMAND_READ_FPDMA_QUEUED_EXT;
+				else
+					ATACommand = MV_ATA_COMMAND_READ_DMA_QUEUED_EXT;
+			} else {
+				if (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)
+					ATACommand = MV_ATA_COMMAND_WRITE_FPDMA_QUEUED_EXT;
+				else
+					ATACommand = MV_ATA_COMMAND_WRITE_DMA_QUEUED_EXT;
+			}
+		} else {	/* Read/Write DMA QUEUED */
+
+			WRITE_ATA_COMMAND_REG(pCommand++, (pUdmaParams->numOfSectors) &
+					      0xFF, MV_EDMA_ATA_FEATURES_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pCommandEntry->deviceTag << 3) & 0xF8, MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress) & 0xFF, MV_EDMA_ATA_LBA_LOW_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress & 0xFF00) >> 8, MV_EDMA_ATA_LBA_MID_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++, (pUdmaParams->lowLBAAddress & 0xFF0000)
+					      >> 16, MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT6 | (MV_U8) ((pUdmaParams->lowLBAAddress & 0xF000000)
+									     >> 24), MV_EDMA_ATA_DEVICE_ADDR, 0);
+
+			if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
+				ATACommand = MV_ATA_COMMAND_READ_DMA_QUEUED;
+			else
+				ATACommand = MV_ATA_COMMAND_WRITE_DMA_QUEUED;
+		}
+	} else {
+		if (pUdmaParams->isEXT == MV_TRUE) {	/* READ/WRITE DMA EXT */
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->numOfSectors & 0xFF00) >> 8,
+					      MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->numOfSectors) & 0xFF, MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++, (pUdmaParams->lowLBAAddress & 0xFF000000)
+					      >> 24, MV_EDMA_ATA_LBA_LOW_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress) & 0xFF, MV_EDMA_ATA_LBA_LOW_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->highLBAAddress & 0xFF), MV_EDMA_ATA_LBA_MID_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress & 0xFF00) >> 8, MV_EDMA_ATA_LBA_MID_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->highLBAAddress & 0xFF00) >> 8,
+					      MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++, (pUdmaParams->lowLBAAddress & 0xFF0000)
+					      >> 16, MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT6, MV_EDMA_ATA_DEVICE_ADDR, 0);
+
+			if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
+				ATACommand = MV_ATA_COMMAND_READ_DMA_EXT;
+			else
+				ATACommand = MV_ATA_COMMAND_WRITE_DMA_EXT;
+		} else {	/* READ/WRITE DMA */
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->numOfSectors) & 0xFF, MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress) & 0xFF, MV_EDMA_ATA_LBA_LOW_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      (pUdmaParams->lowLBAAddress & 0xFF00) >> 8, MV_EDMA_ATA_LBA_MID_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++, (pUdmaParams->lowLBAAddress & 0xFF0000)
+					      >> 16, MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
+
+			WRITE_ATA_COMMAND_REG(pCommand++,
+					      MV_BIT6 | (MV_U8) ((pUdmaParams->lowLBAAddress &
+								  0xF000000) >> 24), MV_EDMA_ATA_DEVICE_ADDR, 0);
+
+			if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
+				ATACommand = MV_ATA_COMMAND_READ_DMA;
+			else
+				ATACommand = MV_ATA_COMMAND_WRITE_DMA;
+		}
+	}
+	WRITE_ATA_COMMAND_REG(pCommand++, ATACommand, MV_EDMA_ATA_COMMAND_ADDR, MV_BIT15);
+}
+
+/*******************************************************************************
+* writeGen2EEdmaRequestEntry  - Write a Gen2E CRQB (COMMAND REQUEST QUEUE BLOCK)
+*
+* DESCRIPTION:
+*       write one CRQB for an EDMA request queue.
+*
+* INPUT:
+*       pReqEntry     - pointer to the CRQB area on the system memory
+*                       (HW reqeust Queue).
+*       mvSataChannel - pointer to the channel data structure
+*       pCommandEntry - pointer to the command entry data structure
+*                       (SW request Queue).
+*       pUdmaParams   - pointer to the UDMA command parameters data structure.
+*
+* RETURN:
+*       None
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+static void writeGen2EEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry,
+				       MV_SATA_CHANNEL *mvSataChannel,
+				       MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_UDMA_COMMAND_PARAMS *pUdmaParams)
+{
+	MV_GEN2E_EDMA_REQUEST_QUEUE_ENTRY *pGen2EReqEntry = (MV_GEN2E_EDMA_REQUEST_QUEUE_ENTRY *) pReqEntry;
+	MV_U32 ControlFlags = 0;
+	MV_U8 ATACommand = 0;
+
+	pGen2EReqEntry->prdLowAddr = MV_CPU_TO_LE32(pUdmaParams->prdLowAddr);
+	pGen2EReqEntry->prdHighAddr = MV_CPU_TO_LE32(pUdmaParams->prdHighAddr);
+
+	/* Set the direction of the transaction (read/write) */
+	if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
+		ControlFlags |= 0x1;	/* Device to system memory */
+#ifdef MV_SATA_IO_GRANULARITY
+
+	/*If valid IO Granularity transaction Id */
+	if (pUdmaParams->iogCurrentTransId < MV_IOG_INVALID_COMMAND_ID) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND, "%d %d: "
+			 "Edma request with IO granularity Id = 0x%x\n",
+			 mvSataChannel->mvSataAdapter->adapterId,
+			 mvSataChannel->channelNumber, pUdmaParams->iogCurrentTransId);
+		ControlFlags |= (((MV_U16) pUdmaParams->iogCurrentTransId) << 6);
+	}
+#endif
+	/* the tag will be used also in Non-queue EDMA mode    */
+	ControlFlags |= (pCommandEntry->deviceTag << 1);
+	ControlFlags |= (pCommandEntry->pCommandInfo->PMPort << 12);
+	ControlFlags |= (pCommandEntry->hostTag << 17);
+#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION
+	if (pUdmaParams->singleDataRegion == MV_TRUE) {
+		ControlFlags |= MV_BIT16;
+		pGen2EReqEntry->dataRegionByteCount = MV_CPU_TO_LE16(pUdmaParams->byteCount);
+	}
+#endif
+
+	pGen2EReqEntry->controlFlags = MV_CPU_TO_LE32(ControlFlags);
+	if ((mvSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) ||
+	    (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)) {
+		if (pUdmaParams->isEXT == MV_TRUE) {	/* Read/Write DMA QUEUED EXT */
+			pGen2EReqEntry->ATAFeaturesExp = (MV_U8) ((pUdmaParams->numOfSectors & 0xFF00) >> 8);
+			pGen2EReqEntry->ATAFeatures = (MV_U8) ((pUdmaParams->numOfSectors) & 0xFF);
+			pGen2EReqEntry->ATASectorCount = (MV_U8) ((pCommandEntry->deviceTag << 3) & 0xF8);
+			pGen2EReqEntry->ATALBALowExp = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF000000) >> 24);
+			pGen2EReqEntry->ATALBALow = (MV_U8) ((pUdmaParams->lowLBAAddress) & 0xFF);
+			pGen2EReqEntry->ATALBAMidExp = (MV_U8) (pUdmaParams->highLBAAddress & 0xFF);
+			pGen2EReqEntry->ATALBAMid = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF00) >> 8);
+			pGen2EReqEntry->ATALBAHighExp = (MV_U8) ((pUdmaParams->highLBAAddress & 0xFF00) >> 8);
+			pGen2EReqEntry->ATALBAHigh = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF0000) >> 16);
+			if ((mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) && (pUdmaParams->FUA == MV_TRUE))
+				pGen2EReqEntry->ATADevice = MV_BIT7 | MV_BIT6;
+			else
+				pGen2EReqEntry->ATADevice = MV_BIT6;
+
+			if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) {
+				if (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)
+					ATACommand = MV_ATA_COMMAND_READ_FPDMA_QUEUED_EXT;
+				else
+					ATACommand = MV_ATA_COMMAND_READ_DMA_QUEUED_EXT;
+			} else {
+				if (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)
+					ATACommand = MV_ATA_COMMAND_WRITE_FPDMA_QUEUED_EXT;
+				else
+					ATACommand = MV_ATA_COMMAND_WRITE_DMA_QUEUED_EXT;
+			}
+		} else {	/* Read/Write DMA QUEUED */
+
+			pGen2EReqEntry->ATAFeatures = (MV_U8) ((pUdmaParams->numOfSectors) & 0xFF);
+			pGen2EReqEntry->ATASectorCount = (MV_U8) ((pCommandEntry->deviceTag << 3) & 0xF8);
+			pGen2EReqEntry->ATALBALow = (MV_U8) ((pUdmaParams->lowLBAAddress) & 0xFF);
+			pGen2EReqEntry->ATALBAMid = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF00) >> 8);
+			pGen2EReqEntry->ATALBAHigh = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF0000) >> 16);
+			pGen2EReqEntry->ATADevice = MV_BIT6 | (MV_U8) ((pUdmaParams->lowLBAAddress & 0xF000000) >> 24);
+
+			if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
+				ATACommand = MV_ATA_COMMAND_READ_DMA_QUEUED;
+			else
+				ATACommand = MV_ATA_COMMAND_WRITE_DMA_QUEUED;
+		}
+	} else {
+		if (pUdmaParams->isEXT == MV_TRUE) {	/* READ/WRITE DMA EXT */
+			pGen2EReqEntry->ATASectorCountExp = (MV_U8) ((pUdmaParams->numOfSectors & 0xFF00) >> 8);
+			pGen2EReqEntry->ATASectorCount = (MV_U8) ((pUdmaParams->numOfSectors) & 0xFF);
+			pGen2EReqEntry->ATALBALowExp = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF000000) >> 24);
+			pGen2EReqEntry->ATALBALow = (MV_U8) ((pUdmaParams->lowLBAAddress) & 0xFF);
+			pGen2EReqEntry->ATALBAMidExp = (MV_U8) (pUdmaParams->highLBAAddress & 0xFF);
+			pGen2EReqEntry->ATALBAMid = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF00) >> 8);
+			pGen2EReqEntry->ATALBAHighExp = (MV_U8) ((pUdmaParams->highLBAAddress & 0xFF00) >> 8);
+			pGen2EReqEntry->ATALBAHigh = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF0000) >> 16);
+			pGen2EReqEntry->ATADevice = MV_BIT6;
+
+			if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
+				ATACommand = MV_ATA_COMMAND_READ_DMA_EXT;
+			else
+				ATACommand = MV_ATA_COMMAND_WRITE_DMA_EXT;
+		} else {	/* READ/WRITE DMA */
+
+			pGen2EReqEntry->ATASectorCount = (MV_U8) ((pUdmaParams->numOfSectors) & 0xFF);
+			pGen2EReqEntry->ATALBALow = (MV_U8) ((pUdmaParams->lowLBAAddress) & 0xFF);
+			pGen2EReqEntry->ATALBAMid = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF00) >> 8);
+			pGen2EReqEntry->ATALBAHigh = (MV_U8) ((pUdmaParams->lowLBAAddress & 0xFF0000) >> 16);
+			pGen2EReqEntry->ATADevice = MV_BIT6 | (MV_U8) ((pUdmaParams->lowLBAAddress & 0xF000000) >> 24);
+
+			if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
+				ATACommand = MV_ATA_COMMAND_READ_DMA;
+			else
+				ATACommand = MV_ATA_COMMAND_WRITE_DMA;
+		}
+	}
+	pGen2EReqEntry->ATACommand = ATACommand;
+}
+
+/*******************************************************************************
+* handleEdmaFailedCommand - Handle failed EDMA command which didn't commpleted.
+*
+* DESCRIPTION:
+*       This function handles the completion of failed EDMA command when no
+*       response received for that command.
+*
+* INPUT:
+*       pAdapter     - Pointer to the MV88SX50XX adapter data structure.
+*       channelIndex - The index of the channel where the response received.
+*       eDmaErrorCause - the value of the channel EDMA error cause register.
+*
+* RETURN:
+*       None
+*
+* COMMENTS:
+*       This function assumes that the channel semaphore is locked.
+*
+*******************************************************************************/
+static void handleEdmaFailedCommand(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U16 eDmaErrorCause)
+{
+	MV_QUEUED_COMMAND_ENTRY *pCommandEntry;
+	MV_UDMA_COMMAND_PARAMS *pUdmaCommandParams;
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	MV_STORAGE_DEVICE_REGISTERS deviceRegs;
+	MV_U32 eDmaStatus;
+	MV_U8 deviceTag = 0xFF;
+	MV_U8 hostTag;
+	MV_U8 PMPort = 0;
+
+	if (pSataChannel->PMSupported == MV_TRUE) {
+		MV_U32 regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						  pSataChannel->eDmaRegsOffset + MV_SATA_II_IF_STATUS_REG_OFFSET);
+		PMPort = (MV_U8) getRegField(regVal, 8, 4);
+	}
+	eDmaStatus = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+				       pSataChannel->eDmaRegsOffset + MV_EDMA_STATUS_REG_OFFSET);
+
+	switch (pSataChannel->queuedDMA) {
+	case MV_EDMA_MODE_QUEUED:
+		/* if only one command is queued */
+		if (pSataChannel->portQueuedCommands[PMPort] == 1) {
+			MV_QUEUED_COMMAND_ENTRY *pEntry = pSataChannel->commandsQueueHead;
+			while (pEntry != NULL) {
+				if (pEntry->isCommandInEdma == MV_TRUE) {
+					if (pEntry->pCommandInfo->PMPort == PMPort) {
+						deviceTag = pEntry->deviceTag;
+						mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+							 "%d %d %d: handleEdmaFailedCommand, found "
+							 "single erring command in TCQ mode "
+							 "deviceTag(0x%02x)\n",
+							 pSataChannel->mvSataAdapter->adapterId,
+							 pSataChannel->channelNumber, PMPort, deviceTag);
+						break;
+					}
+				} else {
+					/* stop once reached a command that has not been inserted into the
+					   EDMA since the next commands also must be outside the EDMA
+					 */
+					break;
+				}
+				pEntry = pEntry->next;
+			}
+			if (deviceTag == 0xFF) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+					 "%d %d %d: handleEdmaFailedCommand, failed to find "
+					 "device tag of single erring command in TCQ mode\n",
+					 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, PMPort);
+				return;
+			}
+		} else {
+			/*multiple commands are queued, take the tag from the disk */
+			deviceTag = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress,
+						     pSataChannel->eDmaRegsOffset +
+						     MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET);
+			deviceTag >>= 3;
+			deviceTag &= 0x1F;
+		}
+		break;
+	case MV_EDMA_MODE_NOT_QUEUED:
+		deviceTag = (MV_U8) getRegField(eDmaStatus, 0, 5);
+		break;
+	default:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: "
+			 "handleEdmaFailedCommand: called with wrong mode %d\n",
+			 pAdapter->adapterId, channelIndex, pSataChannel->queuedDMA);
+		return;
+	}
+
+	if (_getHostTagByDeviceTag(pSataChannel, deviceTag, PMPort, &hostTag) == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d %d: "
+			 "handleEdmaFailedCommand: "
+			 "Error - None Valid device tag (0x%02x)\n",
+			 pAdapter->adapterId, channelIndex, PMPort, deviceTag);
+		return;
+	}
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Handle failed command,"
+		 "host tag 0x%02x, error cause 0x%02x (eStatus Tag 0x%02x)\n",
+		 pAdapter->adapterId, channelIndex, hostTag,
+		 eDmaErrorCause, (eDmaStatus & MV_EDMA_STATUS_TAG_MASK) >> MV_EDMA_STATUS_TAG_OFFSET);
+	/* this function called only if FBS mode disable, then device tag equals to */
+	/* host tag */
+	pCommandEntry = &(pSataChannel->commandsQueue[hostTag]);
+	if (pCommandEntry->isFreeEntry == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d %d:"
+			 " Received response on a non-valid tag (0x%x),"
+			 " device Tag (0x%x)\n", pAdapter->adapterId, channelIndex, PMPort, hostTag, deviceTag);
+
+		_dumpSataRegs(pAdapter, channelIndex);
+		dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_TRUE, &deviceRegs);
+		_printATARegs(&deviceRegs);
+		return;
+	}
+	if (pSataChannel->PMSupported == MV_TRUE)
+		_setActivePMPort(pSataChannel, pCommandEntry->pCommandInfo->PMPort);
+
+	pUdmaCommandParams = &pCommandEntry->pCommandInfo->commandParams.udmaCommand;
+	dumpAtaDeviceRegisters(pAdapter, channelIndex, pUdmaCommandParams->isEXT, &deviceRegs);
+
+	pSataChannel->EdmaQueuedCommands--;
+	pUdmaCommandParams->callBack(pSataChannel->mvSataAdapter, channelIndex,
+				     MV_COMPLETION_TYPE_ERROR,
+				     pUdmaCommandParams->commandId, eDmaErrorCause, 0, &deviceRegs);
+	removeCommand(pSataChannel, pCommandEntry);
+}
+
+/*******************************************************************************
+* handleEdmaResponse - Handle an EDMA response queue entry.
+*
+* DESCRIPTION:
+*       This function handles the completion of EDMA command when a response
+*       entry is received.
+*
+* INPUT:
+*       pAdapter     - Pointer to the MV88SX50XX adapter data structure.
+*       channelIndex - The index of the channel where the response received.
+*       response     - Pointer to the received EDMA response block structure.
+*
+* RETURN:
+*       None
+*
+* COMMENTS:
+*       This function assumes that the channel semaphore is locked.
+*
+*******************************************************************************/
+static void handleEdmaResponse(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			       MV_DMA_RESPONSE_QUEUE_ENTRY *eDmaResponse)
+{
+	MV_QUEUED_COMMAND_ENTRY *pCommandEntry;
+	MV_UDMA_COMMAND_PARAMS *pUdmaCommandParams;
+	MV_STORAGE_DEVICE_REGISTERS deviceRegs;
+	MV_COMPLETION_TYPE compType = MV_COMPLETION_TYPE_NORMAL;
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	MV_DMA_RESPONSE_QUEUE_ENTRY response;
+	MV_U16 eDmaCause = 0;
+
+	response.id = MV_LE16_TO_CPU(eDmaResponse->id);
+	response.responseFlags = MV_LE16_TO_CPU(eDmaResponse->responseFlags);
+	response.timeStamp = MV_LE32_TO_CPU(eDmaResponse->timeStamp);
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: New Response Received. ptr %p, "
+		 "id 0x%02x, flags 0x%x ts 0x%08x\n", pAdapter->adapterId,
+		 channelIndex, eDmaResponse, response.id, response.responseFlags, response.timeStamp);
+
+	eDmaCause = (response.responseFlags & 0xff);
+	pCommandEntry = &(pSataChannel->commandsQueue[response.id & pSataChannel->EDMAQueuePtrMask]);
+	if (response.responseFlags & 0xFF) {
+		MV_BOOLEAN ignoreErrorInFlags = MV_FALSE;
+
+		/* response with errors, ignore SErrors since they are recoverable */
+		if ((pAdapter->sataAdapterGeneration != MV_SATA_GEN_I) &&
+		    (response.responseFlags & MV_BIT5) && ((response.responseFlags & 0xDF) == 0)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 "%d %d: Ignore Serror in response flags\n", pAdapter->adapterId, channelIndex);
+			ignoreErrorInFlags = MV_TRUE;
+			/* SError in EDMA error cause is masked. so we need to handle it here */
+			pSataChannel->recoveredErrorsCounter = 0;
+			handleRecoverableError(pAdapter, channelIndex, MV_BIT5);
+			/* clear SError bit in EDMA error cause */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   pSataChannel->eDmaRegsOffset +
+					   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, ~MV_BIT5);
+
+		}
+		/* in NCQ mode, Device error doesn't halt the EDMA operation. since the */
+		/* response flags are a snapshot of the EDMA error cause, then this */
+		/* error (Device error) is ignored   */
+		if ((pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) &&
+		    (response.responseFlags & MV_BIT2) && ((response.responseFlags & 0xDB) == 0)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 "%d %d: Ignore Device Error in response flags.\n", pAdapter->adapterId, channelIndex);
+			ignoreErrorInFlags = MV_TRUE;
+		}
+
+		if ((pSataChannel->queuedDMA != MV_EDMA_MODE_NATIVE_QUEUING) &&
+		    (pSataChannel->FBSEnabled == MV_TRUE) &&
+		    (response.responseFlags & MV_BIT2) && ((response.responseFlags & 0xDB) == 0)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 "%d %d: Device Error in response flags in FBS none NCQ mode."
+				 "outstanding commands %d \n",
+				 pAdapter->adapterId, channelIndex, pSataChannel->outstandingCommands);
+			ignoreErrorInFlags = MV_TRUE;
+			compType = MV_COMPLETION_TYPE_ERROR;
+		}
+
+		if (ignoreErrorInFlags == MV_FALSE) {
+			pSataChannel->queueCommandsEnabled = MV_FALSE;
+			pSataChannel->EdmaActive = MV_FALSE;
+			compType = MV_COMPLETION_TYPE_ERROR;
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 "%d %d: Response with Error. outstanding commands %d, "
+				 "response flags 0x%x\n",
+				 pAdapter->adapterId, channelIndex,
+				 pSataChannel->outstandingCommands, response.responseFlags);
+
+			/*
+			 * link & phy layers unrecoverable errors may be the reason for a
+			 * device errors, so we first check if any unrecoverable errors occured,
+			 * except PCI/internal parity, if yes then we don't count this response
+			 * the PCI/internal parity errors excluded since we want to complete
+			 * the commands with error indication so higher layers can receive it
+			 */
+			{
+				MV_U32 edmaErrorCause = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+									  pSataChannel->eDmaRegsOffset +
+									  MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
+				MV_U32 unrecoverableErrorMask;
+				if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
+					unrecoverableErrorMask = MV_EDMA_GEN_I_UNRECOVERABLE_EDMA_ERROR;
+				else
+					unrecoverableErrorMask = MV_EDMA_GEN_II_UNRECOVERABLE_EDMA_ERROR;
+
+				unrecoverableErrorMask &= ~(MV_BIT1 | MV_BIT0);
+				if (edmaErrorCause & unrecoverableErrorMask) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+						 "%d %d: Response ignored due to unrecoverable error,"
+						 " EDMA Error Cause: 0x%08x\n",
+						 pAdapter->adapterId, channelIndex, edmaErrorCause);
+					return;
+				}
+			}
+
+			/*
+			 * responseFlags will hold the low 8 bit of the EDMA error cause
+			 * regiter. For 88SX50XX set bit 8 sence each error causes to
+			 * eDmaSelfDisable.
+			 */
+			eDmaCause = (response.responseFlags & 0xff);
+			if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
+				eDmaCause |= MV_BIT8;
+			else
+				eDmaCause |= MV_BIT7;
+
+			if (pSataChannel->PMSupported == MV_TRUE)
+				_setActivePMPort(pSataChannel, pCommandEntry->pCommandInfo->PMPort);
+		}
+	}
+	pUdmaCommandParams = &pCommandEntry->pCommandInfo->commandParams.udmaCommand;
+	if (response.responseFlags & MV_BIT2) {	/*device error */
+		if (pSataChannel->queuedDMA != MV_EDMA_MODE_NATIVE_QUEUING) {
+			dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_TRUE, &deviceRegs);
+
+			if (pSataChannel->FBSEnabled == MV_TRUE) {
+				if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED) {
+					if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_IDLE) {
+						mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+							 "%d %d: First error\n", pAdapter->adapterId, channelIndex);
+						pSataChannel->ErrorHandlingInfo.state =
+						    MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS;
+					}
+					/*let transport layer resume */
+					setAbortedCommands(pSataChannel);
+				} else {
+					/*in TCQ/FBS mode, ignore responses with device error */
+					return;
+				}
+
+			}
+		}
+	}
+
+	if (pCommandEntry->isFreeEntry == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+			 "%d %d: Received response on a non-valid tag (%x), ts 0x%08x,"
+			 " address %p\n", pAdapter->adapterId, channelIndex,
+			 response.id, response.timeStamp, eDmaResponse);
+		_dumpEDMARegs(pAdapter, channelIndex);
+		_dumpChannelQueues(pAdapter, channelIndex);
+	} else {
+		pSataChannel->EdmaQueuedCommands--;
+
+		pUdmaCommandParams->callBack(pSataChannel->mvSataAdapter, channelIndex,
+					     compType, pUdmaCommandParams->commandId,
+					     eDmaCause, response.timeStamp, &deviceRegs);
+		removeCommand(pSataChannel, pCommandEntry);
+
+		if (pSataChannel->queueCommandsEnabled == MV_FALSE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND,
+				 "%d %d: Commands queuing is disabled\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+			return;
+		}
+
+		if (pSataChannel->ErrorHandlingInfo.state != MV_ERROR_HANDLING_STATE_IDLE) {
+			if (compType == MV_COMPLETION_TYPE_NORMAL) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "%d %d: Commands with Tag 0x%x completed successfly\n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, response.id & 0x1f);
+			}
+			if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS) {
+				if (isGoodCompletionsExpected(pSataChannel) == MV_FALSE) {
+					enterRequestSenseState(pSataChannel);
+					return;
+				}
+			}
+		}
+		if (pSataChannel->commandsQueueHead == NULL) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND,
+				 "%d %d: Commands queue is empty\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+			return;
+		}
+		if (pSataChannel->commandsQueueHead->pCommandInfo->type != MV_QUEUED_COMMAND_TYPE_UDMA) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND,
+				 "%d %d: Next Command isn't DMA\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+			deactivateEdma(pAdapter, channelIndex);
+			if (pSataChannel->PMSupported == MV_TRUE)
+				_setActivePMPort(pSataChannel, pSataChannel->commandsQueueHead->pCommandInfo->PMPort);
+
+			if (sendNoneUdmaCommand(pSataChannel, pSataChannel->commandsQueueHead) == MV_FALSE)
+				completePIOCommand(pSataChannel, pSataChannel->commandsQueueHead, MV_TRUE);
+
+		} else {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND,
+				 "%d %d: Next Command is UDMA nothing to do\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+
+		}
+	}
+}
+
+#ifdef MV_SATA_C2C_COMM
+/*******************************************************************************
+* handleBmDmaInterrupt - handle DMA interrupt received for a given channel
+*
+* DESCRIPTION:
+*   This function is called when response interrupt is issued when C2C DMA
+*   completion event occurs.
+*
+* INPUT:
+*   pAdapter   - pointer to the MV88SX50XX adapter data structure
+*   ioBaseAddr  - adapter rbase address
+*   pSataChannel  - SATA channel structure
+*   channelIndex  - SATA channel index
+*   edmaError   - if != zero then EDMA error happened.
+*
+* RETURN:
+*   None.
+*
+* COMMENTS:
+*   None
+*
+*******************************************************************************/
+
+static void handleBmDMAInterrupt(MV_SATA_ADAPTER *pAdapter,
+				 MV_BUS_ADDR_T ioBaseAddr,
+				 MV_SATA_CHANNEL *pSataChannel, MV_U8 channelIndex, MV_U32 edmaError)
+{
+	MV_U32 val;
+	MV_U32 eDmaErrorCause = 0;
+	mvOsSemTake(&pSataChannel->semaphore);
+	/*Reset BM dma */
+	_clearRegBits(ioBaseAddr, getEdmaRegOffset(channelIndex) + MV_BMDMA_COMMAND_OFFSET, MV_BIT0);
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, getEdmaRegOffset(channelIndex) + MV_SATA_II_IF_CONTROL_REG_OFFSET, 0);
+	if (edmaError) {
+		eDmaErrorCause = (MV_U16) MV_REG_READ_DWORD(ioBaseAddr,
+							    getEdmaRegOffset(channelIndex) +
+							    MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
+	}
+	mvOsSemRelease(&pSataChannel->semaphore);
+	if (pSataChannel->C2CCallback) {
+		if (!edmaError) {
+			pSataChannel->C2CCallback(pAdapter, pSataChannel, MV_C2C_BM_DMA_DONE, 0, NULL);
+		} else {
+			if (eDmaErrorCause & (MV_BIT17 | MV_BIT26))
+				pSataChannel->C2CCallback(pAdapter, pSataChannel, MV_C2C_BM_DMA_ERROR, 0, NULL);
+
+			if (eDmaErrorCause & (MV_BIT13 | MV_BIT21))
+				pSataChannel->C2CCallback(pAdapter,
+							  pSataChannel,
+							  MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_ERROR, 0, NULL);
+		}
+	}
+}
+#endif
+
+/*******************************************************************************
+* handleEdmaInterrupt - handle EDMA interrupt receivd for a given channel
+*
+* DESCRIPTION:
+*   this function called when response interrupt issuesed for a channel and it
+*    handles all EDMA responses.
+*
+* INPUT:
+*   *pAdapter   - pointer to the MV88SX50XX adapter data structure
+*   sataUnit    - the SATAHC unit this channel belongs to
+*   port        - the port number of the channel
+*   rspInPtr    - the value of eRPQIP of the channel
+*   responseDone   - if != zero then responses received on this channel
+*   edmaError   - if != zero then EDMA error happened.
+*
+* RETURN:
+*   None.
+*
+* COMMENTS:
+*   None.
+*
+*******************************************************************************/
+static void handleEdmaInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit,
+				MV_U8 port, MV_U8 rspInPtr, MV_U32 responseDone, MV_U32 edmaError, MV_U32 unitCause)
+{
+	MV_U8 rspOutPtr;
+	MV_U8 channelIndex;
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset;
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BOOLEAN responseWithErr = MV_FALSE;
+
+	channelIndex = MV_CHANNEL_INDEX(sataUnit, port);
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+
+	if (responseDone && (pSataChannel != NULL)) {	/* port Done */
+		mvOsSemTake(&pSataChannel->semaphore);
+		pSataChannel->recoveredErrorsCounter = 0;
+#ifdef MV_SATA_C2C_COMM
+		if (MV_FALSE == pSataChannel->C2CmodeEnabled) {
+#endif
+#ifdef MV_SUPPORT_ATAPI
+			if ((pSataChannel->commandsQueueHead)
+			    && (pSataChannel->commandsQueueHead->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET)) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: Basic DMA Interrupt\n",
+					 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " BMDMA status 0x%08x\n",
+					 MV_REG_READ_DWORD(ioBaseAddr,
+							   getEdmaRegOffset(pSataChannel->channelNumber) +
+							   MV_BMDMA_STATUS_OFFSET));
+				if (pSataChannel->waitForBMDMA == MV_TRUE)
+					completePacketCommand(pSataChannel, pSataChannel->commandsQueueHead, MV_FALSE);
+			} else {
+#endif
+				eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+				rspOutPtr = pSataChannel->rspOutPtr;
+				rspInPtr &= pSataChannel->EDMAQueuePtrMask;
+				/* here we should update the response out pointer though we didn't */
+				/* handled the new responses, these response entries will not be  */
+				/* accessed again by the EDMA sinse the number of queued commands */
+				/* (outstandingCommands) will be updated only after we handle each */
+				/* response entry                                                 */
+				MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
+						   MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET,
+						   pSataChannel->responseQueuePciLowAddress |
+						   (rspInPtr << MV_EDMA_RESPONSE_Q_OUTP_OFFSET));
+
+				while (rspOutPtr != rspInPtr) {
+					/*handleEdmaResponse may change the channel rspOutPtr due to */
+					/*device error in NCQ mode or FBS */
+					pSataChannel->rspOutPtr = (rspOutPtr + 1) & pSataChannel->EDMAQueuePtrMask;
+					handleEdmaResponse(pAdapter, channelIndex,
+							   &(pSataChannel->responseQueue[rspOutPtr]));
+					rspOutPtr++;
+					rspOutPtr &= pSataChannel->EDMAQueuePtrMask;
+				}
+#ifdef MV_SUPPORT_ATAPI
+			}
+#endif
+			/*
+			 * Check if queueCommandsEnabled flag is disabled.
+			 * If so, then an error has occured and auto flush must be triggered.
+			 * Basically it is enough to trigger auto flush upon edmaError flag,
+			 * but since edmaError is set before handleEdmaResponse is called
+			 * there could be a racing condition between the time edmaError is checked
+			 * and the response queue is checked.
+			 * The racing condition is that an error does not occur when setting
+			 * edmaError to MV_FALSE, but in handlEdmaResponse, the hardware
+			 * has completed a command with error.
+			 * The racing condition will complete the error command (through callback)
+			 * but will prevent the auto flush of all outstanding commands.
+			 */
+			if (pSataChannel->queueCommandsEnabled == MV_FALSE)
+				responseWithErr = MV_TRUE;
+
+			mvOsSemRelease(&pSataChannel->semaphore);
+#ifdef MV_SATA_C2C_COMM
+		} else {
+			mvOsSemRelease(&pSataChannel->semaphore);
+			handleBmDMAInterrupt(pAdapter, ioBaseAddr, pSataChannel, channelIndex, edmaError);
+		}
+#endif
+	}
+
+	if ((edmaError) || (responseWithErr == MV_TRUE))	/* EDMA error interrupt */
+		handleEdmaError(pAdapter, channelIndex);
+
+}
+
+static void handleEdmaError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_U32 eDmaErrorCause = 0;
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+
+	eDmaErrorCause = MV_REG_READ_DWORD(ioBaseAddr,
+					   getEdmaRegOffset(channelIndex) + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 "%d %d: Edma Error Reg 0x%x\n", pAdapter->adapterId,
+		 channelIndex, MV_REG_READ_DWORD(ioBaseAddr,
+						 getEdmaRegOffset(channelIndex) +
+						 MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET));
+	/* clear the channel's error cause register */
+	MV_REG_WRITE_DWORD(ioBaseAddr,
+			   getEdmaRegOffset(channelIndex) + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, ~eDmaErrorCause);
+	/*if PM connected, connect/disconnect interrupts storm could happen */
+	if (MV_REG_READ_DWORD(ioBaseAddr,
+			      getEdmaRegOffset(channelIndex) +
+			      MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET) & (MV_BIT3 & MV_BIT4)) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 "%d %d: Edma Error Reg 0x%x still set!!!!!!!!\n",
+			 pAdapter->adapterId, channelIndex,
+			 MV_REG_READ_DWORD(ioBaseAddr,
+					   getEdmaRegOffset(channelIndex) + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET));
+		if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+			/*wait 20ms till diconnect/connect interrupts finish */
+			mvMicroSecondsDelay(pAdapter, 20000);
+			eDmaErrorCause |= MV_REG_READ_DWORD(ioBaseAddr,
+							    getEdmaRegOffset(channelIndex) +
+							    MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
+			MV_REG_WRITE_DWORD(ioBaseAddr,
+					   getEdmaRegOffset(channelIndex) +
+					   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, ~eDmaErrorCause);
+		}
+	}
+	/* dump in case any kind of parity error */
+	if (eDmaErrorCause & (MV_BIT11 | MV_BIT10 | MV_BIT9 | MV_BIT1 | MV_BIT0)) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " PARITY ERROR Detected\n");
+		_dumpPCIRegs(pAdapter);
+		_dumpEDMARegs(pAdapter, channelIndex);
+		_dumpChannelQueues(pAdapter, channelIndex);
+	}
+	if (eDmaErrorCause & MV_BIT3) {	/*device disconneted */
+		handleDisconnect(pAdapter, channelIndex);
+		if (mvSataIsStorageDeviceConnected(pAdapter, channelIndex, NULL) == MV_FALSE) {
+			pAdapter->mvSataEventNotify(pAdapter,
+						    MV_EVENT_TYPE_SATA_CABLE,
+						    MV_SATA_CABLE_EVENT_DISCONNECT, channelIndex);
+			return;
+		}
+	}
+	if (eDmaErrorCause & MV_BIT4) {	/*device conneted */
+		handleConnect(pAdapter, channelIndex);
+		return;
+	}
+	/* unrecoverable error */
+	if (handleUnrecoverableError(pAdapter, channelIndex, eDmaErrorCause) == MV_TRUE)
+		return;
+
+	/*PM hot plug */
+	if (handleAsyncNotify(pAdapter, channelIndex, eDmaErrorCause) == MV_TRUE)
+		return;
+
+	/* device errors in none NCQ mode generate self disable interrupt */
+	if (handleSelfDisable(pAdapter, channelIndex, eDmaErrorCause) == MV_TRUE)
+		return;
+
+	/* Neither device error without completion nor self disable must be in NCQ
+	 *  mode and Port multiplier connected
+	 */
+	if (handleDevErr(pAdapter, channelIndex, eDmaErrorCause) == MV_TRUE)
+		return;
+
+	/* recoverable error */
+	if (handleRecoverableError(pAdapter, channelIndex, eDmaErrorCause) == MV_TRUE)
+		return;
+
+}
+
+static MV_VOID handleDisconnect(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+
+	if (pSataChannel) {
+		mvOsSemTake(&pSataChannel->semaphore);
+		pSataChannel->queueCommandsEnabled = MV_FALSE;
+		pSataChannel->EdmaActive = MV_FALSE;
+	}
+	/* If disk is disconnected, then disable the activity LED */
+	if (pAdapter->chipIs50XXB2 == MV_TRUE) {
+		MV_U32 regVal1, regVal2;
+		/* First enable flash controller clocks */
+		regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					    MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
+
+		regVal1 |= (MV_BIT0);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, regVal1);
+		regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					    MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
+		/* Disable activity LEDs */
+		regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
+		regVal2 |= (MV_BIT8 << channelIndex);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET, regVal2);
+		regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
+		/* Disable flash controller clocks */
+		regVal1 &= ~(MV_BIT0);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, regVal1);
+	}
+	/* Fix for 88SX50XX FEr SATA#2 */
+	if ((pAdapter->chipIs50XXB0 == MV_TRUE) || (pAdapter->chipIs50XXB2 == MV_TRUE)) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
+			 "%d %d: Before Hard RESET Main Cause %x\n",
+			 pAdapter->adapterId, channelIndex,
+			 MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainCauseOffset));
+		/* Hard Reset the channel so we can do re-connect */
+		_channelHardReset(pAdapter, channelIndex);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
+			 "%d %d: After Hard RESET Main Cause %x\n",
+			 pAdapter->adapterId, channelIndex,
+			 MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainCauseOffset));
+	} else {
+		if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+
+#ifdef MV_SATA_C2C_COMM
+			if (pSataChannel->C2CmodeEnabled == MV_FALSE) {
+#endif
+				_channelHardReset(pAdapter, channelIndex);
+				_establishSataComm(pAdapter, channelIndex);
+#ifdef MV_SATA_C2C_COMM
+			}
+#endif
+		}
+	}
+	/* after calling mvSataNotify we can not be sure that the channel */
+	/* data structure is still available so first we release the     */
+	/* semaphore, after notifying the upper-layer with the disconnect */
+	/* event, nothing else is done with that channel                 */
+	if (pSataChannel)
+		mvOsSemRelease(&pSataChannel->semaphore);
+
+}
+
+static MV_VOID handleConnect(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	/* Fix for 88SX50xx FEr SATA#2 */
+	if ((pAdapter->chipIs50XXB0 == MV_TRUE) || (pAdapter->chipIs50XXB2 == MV_TRUE)) {
+		_fixPhyParams(pAdapter, channelIndex);
+		/*TBD*/
+		    /* The following link re-establishment is due to non    */
+		    /* Marvell driven hard drives                           */
+		    _establishSataComm(pAdapter, channelIndex);
+		_establishSataComm(pAdapter, channelIndex);
+	}
+
+	/* If disk is connected, then enable the activity LED */
+	if (pAdapter->chipIs50XXB2 == MV_TRUE) {
+		MV_U32 regVal1, regVal2;
+		/* First enable flash controller clocks */
+		regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					    MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
+
+		regVal1 |= (MV_BIT0);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, regVal1);
+		regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					    MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
+		/* Enable activity LEDs */
+		regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
+		regVal2 &= ~(MV_BIT8 << channelIndex);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET, regVal2);
+		regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
+		/* Disable flash controller clocks */
+		regVal1 &= ~(MV_BIT0);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, regVal1);
+	}
+	if (mvSataIsStorageDeviceConnected(pAdapter, channelIndex, NULL) == MV_TRUE)
+		pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_CABLE,
+					    MV_SATA_CABLE_EVENT_CONNECT, channelIndex);
+}
+
+static MV_BOOLEAN handleUnrecoverableError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+
+	if (((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) &&
+	     (eDmaErrorCause & MV_EDMA_GEN_I_UNRECOVERABLE_EDMA_ERROR)) ||
+	    ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) &&
+	     (eDmaErrorCause & MV_EDMA_GEN_II_UNRECOVERABLE_EDMA_ERROR))) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Unrecoverable"
+			 " HW error detected.\n", pAdapter->adapterId, channelIndex);
+#ifdef MV_LOGGER
+		if (eDmaErrorCause & MV_BIT0) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtDataErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & MV_BIT1) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtPRDErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & MV_BIT3) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: eDevDis"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & MV_BIT9) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtCRQBErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & MV_BIT10) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtCRPBErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & MV_BIT11) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtIntErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & MV_BIT12) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: eIORdyErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & MV_BIT15) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkCtlRxErr[2]"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & (MV_BIT17 | MV_BIT18 | MV_BIT19 | MV_BIT20)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkDataRxErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & (MV_BIT26 | MV_BIT27 | MV_BIT28 | MV_BIT29 | MV_BIT30)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkDataTxErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & MV_BIT31) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: TransProtErr"
+				 "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+#endif
+		if (pSataChannel) {
+			mvOsSemTake(&pSataChannel->semaphore);
+			pSataChannel->queueCommandsEnabled = MV_FALSE;
+			pSataChannel->EdmaActive = MV_FALSE;
+			deactivateEdma(pAdapter, channelIndex);
+			disableSaDevInterrupts(pAdapter, channelIndex);
+			flushDmaQueue(pSataChannel, MV_FLUSH_TYPE_CALLBACK,
+				      MV_COMPLETION_TYPE_ABORT, (MV_U16) eDmaErrorCause);
+			resetEdmaChannel(pSataChannel);
+			mvOsSemRelease(&pSataChannel->semaphore);
+		}
+		if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) || (eDmaErrorCause & MV_BIT12) == 0)
+			_dumpSataRegs(pAdapter, channelIndex);
+
+		pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR,
+					    MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR, channelIndex);
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+static MV_BOOLEAN handleRecoverableError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+
+	if (((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) &&
+	     (eDmaErrorCause & MV_EDMA_GEN_I_RECOVERABLE_EDMA_ERROR)) ||
+	    ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) &&
+	     (eDmaErrorCause & MV_EDMA_GEN_II_RECOVERABLE_EDMA_ERROR))) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Recoverable"
+			 " HW error detected.\n", pAdapter->adapterId, channelIndex);
+#ifdef MV_LOGGER
+		if (eDmaErrorCause & MV_BIT5) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: SerrInt"
+				 "Recoverable error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & (MV_BIT13 | MV_BIT14 | MV_BIT16)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkCtlRxErr"
+				 "Recoverable error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+		if (eDmaErrorCause & (MV_BIT21 | MV_BIT22 | MV_BIT23 | MV_BIT24 | MV_BIT25)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkCtlTxErr"
+				 "Recoverable error detected.\n", pAdapter->adapterId, channelIndex);
+		}
+#endif
+		_dumpSataRegs(pAdapter, channelIndex);
+		if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && (eDmaErrorCause & MV_BIT5)) {
+			MV_U32 regVal;
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegOffst[channelIndex] + MV_SATA_II_S_ERROR_REG_OFFSET);
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Clear "
+				 " Serror register(0x%02x).\n", pAdapter->adapterId, channelIndex, regVal);
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   edmaRegOffst[channelIndex] + MV_SATA_II_S_ERROR_REG_OFFSET, regVal);
+			/* clear the channel's error cause register */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) +
+					   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, ~MV_BIT5);
+		}
+		pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR,
+					    MV_SATA_RECOVERABLE_COMMUNICATION_ERROR, channelIndex);
+		if (pSataChannel) {
+			mvOsSemTake(&pSataChannel->semaphore);
+			if (pSataChannel->recoveredErrorsCounter++ > 10) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "%d %d: Reached %d Recoverable errors "
+					 "notify unrecoverable error\n",
+					 pAdapter->adapterId, channelIndex, pSataChannel->recoveredErrorsCounter);
+				pSataChannel->queueCommandsEnabled = MV_FALSE;
+				pSataChannel->EdmaActive = MV_FALSE;
+				deactivateEdma(pAdapter, channelIndex);
+				disableSaDevInterrupts(pAdapter, channelIndex);
+				flushDmaQueue(pSataChannel, MV_FLUSH_TYPE_CALLBACK,
+					      MV_COMPLETION_TYPE_ABORT, (MV_U16) eDmaErrorCause);
+				resetEdmaChannel(pSataChannel);
+				mvOsSemRelease(&pSataChannel->semaphore);
+				pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR,
+							    MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR, channelIndex);
+			} else {
+				mvOsSemRelease(&pSataChannel->semaphore);
+				return MV_TRUE;
+			}
+		}
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+static MV_BOOLEAN handleAsyncNotify(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && (eDmaErrorCause & MV_BIT8)) {
+		MV_U32 regVal1;
+		if (pSataChannel != NULL)
+			mvOsSemTake(&pSataChannel->semaphore);
+
+		regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					    getEdmaRegOffset(channelIndex) + MV_SATA_II_IF_STATUS_REG_OFFSET);
+		/*Clear status */
+		if (regVal1 & (MV_BIT31 | MV_BIT30)) {
+			MV_U32 regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+							   getEdmaRegOffset(channelIndex) +
+							   MV_SATA_II_IF_CONTROL_REG_OFFSET);
+			regVal2 |= MV_BIT24;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_IF_CONTROL_REG_OFFSET, regVal2);
+		}
+		if (pSataChannel != NULL)
+			mvOsSemRelease(&pSataChannel->semaphore);
+
+		if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) {
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 "%d %d: PM asynchronous notification interrupt. FIS Cause %x\n",
+				 pAdapter->adapterId, channelIndex,
+				 MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   getEdmaRegOffset(channelIndex) +
+						   MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET));
+
+			/* clear FIS Interrupt cause register */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) +
+					   MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET, ~0xA00);
+			/* clear the channel's error cause register */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) +
+					   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, ~MV_BIT8);
+		}
+		if (((regVal1 & MV_BIT30) == 0) && ((regVal1 & MV_BIT31) == MV_BIT31)) {
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
+				 "%d %d: PM asynchronous notification interrupt.\n", pAdapter->adapterId, channelIndex);
+
+			pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_CABLE,
+						    MV_SATA_CABLE_EVENT_PM_HOT_PLUG, channelIndex);
+		}
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+static MV_BOOLEAN handleSelfDisable(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+
+	if ((((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) && (eDmaErrorCause & MV_BIT8)) ||
+	     ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && (eDmaErrorCause & MV_BIT7)))
+	    && (pSataChannel != NULL)) {	/* edma self disable */
+		mvOsSemTake(&pSataChannel->semaphore);
+		if (pSataChannel->EdmaActive == MV_TRUE) {
+			pSataChannel->queueCommandsEnabled = MV_FALSE;
+			pSataChannel->EdmaActive = MV_FALSE;
+
+			if (eDmaErrorCause & MV_BIT2) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "%d %d: Edma Self disabled due to device error"
+					 " without completion\n", pAdapter->adapterId, channelIndex);
+				switch (pSataChannel->queuedDMA) {
+				case MV_EDMA_MODE_NOT_QUEUED:
+				case MV_EDMA_MODE_QUEUED:
+					handleEdmaFailedCommand(pAdapter, channelIndex, (MV_U16) eDmaErrorCause);
+					break;
+				case MV_EDMA_MODE_NATIVE_QUEUING:
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+						 "%d %d: Edma Self disabled due to device "
+						 "error in NCQ mode!!!!\n", pAdapter->adapterId, channelIndex);
+
+					break;
+				default:
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+						 "%d %d: Unknown EDMA mode (%d)\n",
+						 pAdapter->adapterId, channelIndex, pSataChannel->queuedDMA);
+					break;
+
+				}
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS,
+					 "%d %d: Edma Self disable received without reason!!!\n",
+					 pAdapter->adapterId, channelIndex);
+
+			}
+		}
+		pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR, MV_SATA_DEVICE_ERROR, channelIndex);
+		if (_doDevErrorRecovery(pSataChannel) == MV_FALSE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS,
+				 "%d %d: Error Recovery Fails!!!\n", pAdapter->adapterId, channelIndex);
+			mvOsSemRelease(&pSataChannel->semaphore);
+			return MV_TRUE;
+		}
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+static MV_BOOLEAN handleDevErr(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 eDmaErrorCause)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && (eDmaErrorCause & MV_BIT2) && (pSataChannel != NULL)) {
+		mvOsSemTake(&pSataChannel->semaphore);
+		if (pSataChannel->EdmaActive == MV_TRUE) {
+			if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "%d %d: EDMA device error in NCQ mode\n", pAdapter->adapterId, channelIndex);
+				if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_IDLE) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+						 "%d %d: First error\n", pAdapter->adapterId, channelIndex);
+					pSataChannel->ErrorHandlingInfo.state =
+					    MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS;
+				}
+
+				updatePortsWithErrors(pSataChannel);
+				setAbortedCommands(pSataChannel);
+				if (isGoodCompletionsExpected(pSataChannel) == MV_FALSE)
+					enterRequestSenseState(pSataChannel);
+
+			} else if (pSataChannel->FBSEnabled == MV_TRUE) {
+				if (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) {
+					if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_IDLE) {
+						mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+							 "%d %d: First error\n", pAdapter->adapterId, channelIndex);
+						pSataChannel->ErrorHandlingInfo.state =
+						    MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS;
+					}
+					/*get the Device tag from the EDMA's internal memory then */
+					/*complete the failed command */
+					handleEdmaFailedCommand(pAdapter, channelIndex, MV_BIT2);
+					updatePortsWithErrors(pSataChannel);
+					setAbortedCommands(pSataChannel);
+					if (isGoodCompletionsExpected(pSataChannel) == MV_FALSE)
+						enterRequestSenseState(pSataChannel);
+				} else {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+						 "%d %d: EDMA device error in FBS none NCQ mode\n",
+						 pAdapter->adapterId, channelIndex);
+				}
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS,
+					 "%d %d: EDMA device error must be handled"
+					 "previously!!!\n", pAdapter->adapterId, channelIndex);
+			}
+		} else {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS,
+				 "%d %d: EDMA device error while EDMA not active!!!\n",
+				 pAdapter->adapterId, channelIndex);
+		}
+		pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR, MV_SATA_DEVICE_ERROR, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+static MV_VOID handlePCIErrorInterrupt(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U32 errorCause = 0;
+	if (pAdapter->hostInterface == MV_HOST_IF_PEX) {
+		errorCause = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					       MV_PCI_REGS_OFFSET + MV_PCI_E_INTERRUPT_CAUSE_REG_OFFSET);
+	} else if (pAdapter->hostInterface == MV_HOST_IF_PCI) {
+		errorCause = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					       MV_PCI_REGS_OFFSET + MV_PCI_INTERRUPT_CAUSE_REG_OFFSET);
+		_dumpPCIRegs(pAdapter);
+	}
+
+	{
+		MV_U8 i;
+
+		for (i = 0; i < pAdapter->numberOfChannels; i++) {
+			_dumpEDMARegs(pAdapter, i);
+			_dumpChannelQueues(pAdapter, i);
+		}
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS,
+		 " %d  : PCI error, pci interrupt cause register=%08x\n", pAdapter->adapterId, errorCause);
+	/* clear cause register */
+	if (pAdapter->hostInterface == MV_HOST_IF_PEX) {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_E_INTERRUPT_CAUSE_REG_OFFSET, ~errorCause);
+	} else if (pAdapter->hostInterface == MV_HOST_IF_PCI) {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_INTERRUPT_CAUSE_REG_OFFSET, ~errorCause);
+	}
+	pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_ADAPTER_ERROR, errorCause, 0);
+}
+
+#ifdef MV_SATA_C2C_COMM
+/*******************************************************************************
+* handleC2CInterrupt - channel 2 channel interrupt handler
+*
+*
+* DESCRIPTION:
+*   Handles channel 2 channel interrupt (register device 2 host FIS) and
+*   convert ATA registers values to user specific 10 bytes message
+*
+* INPUT:
+*   pSataChannel   - pointer to the Sata channel data structure
+*
+* RETURN:
+*   None
+*
+* COMMENTS:
+*   None
+*
+*******************************************************************************/
+static void handleC2CInterrupt(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+	MV_U8 port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1);
+	MV_U8 sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2;
+	MV_U8 ATAstatus;
+	MV_STORAGE_DEVICE_REGISTERS deviceRegs;
+
+	mvOsSemTake(&pSataChannel->semaphore);
+
+	MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_ALTERNATE_REG_OFFSET);
+
+	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+	/* clear DevInterrupt */
+	MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+			   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port));
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+		 "%d %d: C2C Interrupt: status 0x%02x\n",
+		 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ATAstatus);
+
+	dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter, pSataChannel->channelNumber, MV_TRUE, &deviceRegs);
+	mvOsSemRelease(&pSataChannel->semaphore);
+	if (pSataChannel->C2CCallback) {
+		MV_U8 msg[MV_C2C_MESSAGE_SIZE];
+		msg[0] = deviceRegs.errorRegister;
+		msg[1] = deviceRegs.lbaLowRegister & 0xFF;
+		msg[2] = deviceRegs.lbaMidRegister & 0xFF;
+		msg[3] = deviceRegs.lbaHighRegister & 0xFF;
+		msg[4] = deviceRegs.deviceRegister;
+		msg[5] = deviceRegs.lbaLowRegister >> 8;
+		msg[6] = deviceRegs.lbaMidRegister >> 8;
+		msg[7] = deviceRegs.lbaHighRegister >> 8;
+		msg[8] = deviceRegs.sectorCountRegister & 0xFF;
+		msg[9] = deviceRegs.sectorCountRegister >> 8;
+		pSataChannel->C2CCallback(pSataChannel->mvSataAdapter,
+					  pSataChannel,
+					  MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_DONE, MV_C2C_MESSAGE_SIZE, msg);
+	}
+}
+#endif
+
+static void handleDeviceInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, MV_U8 port)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_QUEUED_COMMAND_ENTRY *pCommandEntry;
+	MV_U8 channelIndex;
+
+	channelIndex = MV_CHANNEL_INDEX(sataUnit, port);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+		 "%d %d: SaDevInterrupt Received\n", pAdapter->adapterId, channelIndex);
+
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: SaDevInterrupt Received for disconnected channel\n",
+			 pAdapter->adapterId, channelIndex);
+		/* disable SaDevInterrupts from this channel */
+		disableSaDevInterrupts(pAdapter, channelIndex);
+		return;
+	}
+#ifdef MV_SATA_C2C_COMM
+	/*handle channel 2 channel communication mode */
+	if (pSataChannel->C2CmodeEnabled == MV_TRUE) {
+		handleC2CInterrupt(pSataChannel);
+		return;
+	}
+#endif
+
+	mvOsSemTake(&pSataChannel->semaphore);
+	if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_WAIT_FOR_BUSY) {
+		MV_U8 ATAstatus;
+
+		ATAstatus = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress,
+					     pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+		/* clear DevInterrupt */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port));
+
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: enter NCQ error handling request sense state\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_REQUEST_SENSE;
+		pSataChannel->ErrorHandlingInfo.CurrPort = 0;
+		setReadLogExtCmndPointers(pSataChannel);
+		handlePortError(pSataChannel);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return;
+	}
+
+	/* clear interrupt */
+
+	pCommandEntry = pSataChannel->commandsQueueHead;
+	if (pCommandEntry == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: SaDevInterrupt: No command is running!!!\n", pAdapter->adapterId, channelIndex);
+		_dumpSataRegs(pAdapter, channelIndex);
+		/* disable SaDevInterrupts from this channel */
+		disableSaDevInterrupts(pAdapter, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return;
+	}
+	if ((pCommandEntry->isFreeEntry == MV_TRUE) ||
+	    (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_UDMA)) {
+		if (pCommandEntry->isFreeEntry == MV_TRUE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_NON_UDMA_COMMAND,
+				 "%d %d: SaDevInterrupt: current command is free ???\n",
+				 pAdapter->adapterId, channelIndex);
+		} else {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_NON_UDMA_COMMAND,
+				 "%d %d: SaDevInterrupt: current command is Not PIO ???\n",
+				 pAdapter->adapterId, channelIndex);
+		}
+		/* disable SaDevInterrupts from this channel */
+		disableSaDevInterrupts(pAdapter, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return;
+	}
+	handlePIOInterrupt(pSataChannel, pCommandEntry);
+	mvOsSemRelease(&pSataChannel->semaphore);
+}
+
+static void handlePIOInterrupt(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+	MV_U8 port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1);
+	MV_U8 sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2;
+	MV_U8 ATAstatus;
+	MV_NON_UDMA_PROTOCOL protocolType;
+
+	MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_ALTERNATE_REG_OFFSET);
+
+	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+	/* clear DevInterrupt */
+	MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+			   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port));
+
+	if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET)
+		protocolType = pCommandEntry->pCommandInfo->commandParams.packetCommand.protocolType;
+	else
+		protocolType = pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.protocolType;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+		 "%d %d: PIO Interrupt: cmd 0x%02X, type %d. status 0x%02x\n",
+		 pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber,
+		 pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.command, protocolType, ATAstatus);
+	if (ATAstatus & MV_ATA_BUSY_STATUS) {
+		if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d: "
+				 "PIO Interrupt: drive is BUSY!!!! status 0x%02x\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ATAstatus);
+		}
+		return;
+	}
+	if (ATAstatus & MV_ATA_ERROR_STATUS) {
+		if (pSataChannel->FBSEnabled == MV_TRUE) {
+			/*clear interrupt cause to resume the transport layer operation */
+			MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+					   pSataChannel->eDmaRegsOffset +
+					   MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET, ~MV_BIT8);
+		}
+		if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA) {
+			completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
+			return;
+		}
+	}
+	switch (protocolType) {
+	case MV_NON_UDMA_PROTOCOL_NON_DATA:
+		/* command is successfully completed */
+		completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
+		break;
+	case MV_NON_UDMA_PROTOCOL_PIO_DATA_IN:
+		if (ATAstatus & MV_ATA_READY_STATUS) {
+			if (transferPIOData(pSataChannel,
+					    &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand) == MV_TRUE) {
+				if (pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.count == 0) {
+					ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
+								     MV_ATA_DEVICE_STATUS_REG_OFFSET);
+					if (ATAstatus & MV_ATA_DATA_REQUEST_STATUS) {
+						mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+							 "%d %d: PIO Interrupt: DRQ still set. ATA status 0x%02x\n",
+							 pSataChannel->mvSataAdapter->adapterId,
+							 pSataChannel->channelNumber, ATAstatus);
+						return;
+					}
+					completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
+					return;
+				}
+#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG
+
+				/* for Read long only */
+				if (pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.count == 4) {
+					if (transferPIOData(pSataChannel,
+							    &pCommandEntry->pCommandInfo->commandParams.
+							    NoneUdmaCommand) == MV_TRUE) {
+						completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
+					} else {
+						completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
+					}
+				}
+#endif /*MV_SATA_SUPPORT_READ_WRITE_LONG */
+
+			} else {
+				completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
+			}
+		} else {	/* when BUSY and DRQ cleared to zero then the device has */
+
+			/* completed the command with error                     */
+			completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
+			return;
+		}
+		break;
+	case MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:
+		if ((ATAstatus & MV_ATA_READY_STATUS) && !(ATAstatus & MV_ATA_DEVICE_FAULT_STATUS)) {
+			if (pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.count == 0) {
+				completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
+			} else {
+				if (transferPIOData(pSataChannel,
+						    &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand) ==
+				    MV_FALSE) {
+					completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
+				}
+			}
+		} else {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: PIO Interrupt: PIO"
+				 " Data Out command failed status 0x%02x\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ATAstatus);
+			completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
+		}
+		break;
+#ifdef MV_SUPPORT_ATAPI
+	case MV_NON_UDMA_PROTOCOL_PACKET_PIO_NON_DATA:
+		completePacketCommand(pSataChannel, pCommandEntry, MV_FALSE);
+		break;
+	case MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN:
+	case MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT:
+		{
+			MV_U8 ATASectorCount = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
+								MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET);
+
+			if ((ATAstatus & MV_ATA_ERROR_STATUS) || (ATAstatus & MV_ATA_DEVICE_FAULT_STATUS)) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "%d %d: Packet Interrupt: Command completed with error: ATA status 0x%02x\n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, ATAstatus);
+				completePacketCommand(pSataChannel, pCommandEntry, MV_TRUE);
+				return;
+			}
+			if ((ATAstatus & MV_ATA_DATA_REQUEST_STATUS) == 0) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+					 "%d %d: Packet Interrupt: Command completed ATA status 0x%02x\n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, ATAstatus);
+				completePacketCommand(pSataChannel, pCommandEntry, MV_FALSE);
+				return;
+			}
+			if (((ATAstatus & MV_ATA_READY_STATUS) != MV_ATA_READY_STATUS) ||
+			    (((ATASectorCount & 0x3) != MV_BIT1)
+			     && (protocolType == MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN))
+			    || (((ATASectorCount & 0x3) != 0)
+				&& (protocolType == MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT))
+			    ) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "%d %d: Packet Interrupt: unexpected ATA regs: ATA status 0x%02x,"
+					 " ATA SectorCount 0x%02x protocol %d\n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, ATAstatus, ATASectorCount, protocolType);
+
+				/* completed the command with error                     */
+				completePacketCommand(pSataChannel, pCommandEntry, MV_TRUE);
+				return;
+			} else {
+				MV_U8 LBAMid = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
+								MV_ATA_DEVICE_LBA_MID_REG_OFFSET);
+				MV_U8 LBAHigh = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
+								 MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET);
+				MV_U16 byteCount = (LBAHigh << 8) | LBAMid;
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+					 " Packet with Data: LBA Mid %x, LBA High %x\n", LBAMid, LBAHigh);
+				if (transferPacketData
+				    (pSataChannel, &pCommandEntry->pCommandInfo->commandParams.packetCommand,
+				     byteCount) != MV_TRUE) {
+					completePacketCommand(pSataChannel, pCommandEntry, MV_TRUE);
+				}
+			}
+		}
+		break;
+	case MV_NON_UDMA_PROTOCOL_PACKET_DMA:
+		{
+			MV_U32 BMDMA_status = MV_REG_READ_DWORD(ioBaseAddr,
+								getEdmaRegOffset(pSataChannel->channelNumber) +
+								MV_BMDMA_STATUS_OFFSET);
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+				 "%d %d: Packet Interrupt: in ATAPI DMA command ATA status 0x%02x\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ATAstatus);
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+				 "Packet Interrupt: BMDMA status 0x%08x\n", BMDMA_status);
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+				 " Packet Interrupt: EDMA Error cause 0x%08x\n",
+				 MV_REG_READ_DWORD(ioBaseAddr,
+						   getEdmaRegOffset(pSataChannel->channelNumber) +
+						   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET));
+			if (ATAstatus & MV_ATA_ERROR_STATUS) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "Packet Interrupt: DMA command completed with error BMDMA "
+					 "status 0x%08x, ATA status 0x%02x\n", BMDMA_status, ATAstatus);
+				_resetBmDma(pSataChannel->mvSataAdapter, pSataChannel->channelNumber);
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 ": BMDMA status(2) 0x%08x\n",
+					 MV_REG_READ_DWORD(ioBaseAddr,
+							   getEdmaRegOffset(pSataChannel->channelNumber) +
+							   MV_BMDMA_STATUS_OFFSET));
+
+				pCommandEntry->pCommandInfo->commandParams.packetCommand.transfered_data = 0;
+			} else {
+				pCommandEntry->pCommandInfo->commandParams.packetCommand.transfered_data =
+				    pCommandEntry->pCommandInfo->commandParams.packetCommand.buffer_len;
+
+#if 0
+				/* chech if the BMDMA still active */
+				if (BMDMA_status & MV_BIT0) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+						 "Packet Interrupt: BMDMA not finished yet. "
+						 "status 0x%08x, ATA status 0x%02x\n", BMDMA_status, ATAstatus);
+					/* wait for BMDMA done interrrupt */
+					pSataChannel->waitForBMDMA = MV_TRUE;
+					return;
+				}
+#endif
+				/* if BMDMA finished, call _resetBmDma to clear the Done interrupt */
+				_resetBmDma(pSataChannel->mvSataAdapter, pSataChannel->channelNumber);
+				/* chech if the BMDMA completed with errors */
+				if (BMDMA_status & MV_BIT1) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+						 "Packet Interrupt: BMDMA completed with error. "
+						 "status 0x%08x, ATA status 0x%02x\n", BMDMA_status, ATAstatus);
+					completePacketCommand(pSataChannel, pCommandEntry, MV_TRUE);
+					return;
+				}
+			}
+			completePacketCommand(pSataChannel, pCommandEntry, MV_FALSE);
+			return;
+		}
+		break;
+#endif
+	default:		/* never reached */
+		break;
+	}
+}
+
+static MV_BOOLEAN transferPIOData(MV_SATA_CHANNEL *pSataChannel, MV_NONE_UDMA_COMMAND_PARAMS *pNoneUdmaCommandParams)
+{
+	MV_U32 i;
+	MV_U32 dataBlockWords = pSataChannel->DRQDataBlockSize * ATA_SECTOR_SIZE_IN_WORDS;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+		 "%d %d: xfer data for PIO Data command.count %d\n",
+		 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, pNoneUdmaCommandParams->count);
+
+	switch (pNoneUdmaCommandParams->protocolType) {
+	case MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:
+		for (i = 0; i < dataBlockWords; i++) {
+			if (pNoneUdmaCommandParams->count == 0)
+				return MV_TRUE;
+
+			pNoneUdmaCommandParams->count--;
+			MV_REG_WRITE_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+					  pSataChannel->eDmaRegsOffset +
+					  MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, *pNoneUdmaCommandParams->bufPtr++);
+		}
+		break;
+	case MV_NON_UDMA_PROTOCOL_PIO_DATA_IN:
+		for (i = 0; i < dataBlockWords; i++) {
+			MV_U16 data;
+			if (pNoneUdmaCommandParams->count == 0)
+				return MV_TRUE;
+
+			pNoneUdmaCommandParams->count--;
+			data = MV_REG_READ_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+						pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET);
+#if defined(MV_NETBSD)
+			/* identify data is in big endian */
+			if ((pNoneUdmaCommandParams->command == MV_ATA_COMMAND_IDENTIFY) ||
+			    (pNoneUdmaCommandParams->command == MV_ATA_COMMAND_ATAPI_IDENTIFY))
+				data = MV_BE16_TO_CPU(data);
+			else
+				data = MV_CPU_TO_LE16(data);	/*should be LE16 TO CPU */
+#endif
+			*pNoneUdmaCommandParams->bufPtr++ = data;
+
+		}
+		break;
+	default:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d: in xfer data "
+			 "PIO: command protocol is not Data in/out\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		return MV_FALSE;
+	}
+	return MV_TRUE;
+}
+
+#ifdef MV_SUPPORT_ATAPI
+static MV_BOOLEAN transferPacketData(MV_SATA_CHANNEL *pSataChannel,
+				     MV_PACKET_COMMAND_PARAMS *pPacketCommandParams, MV_U16 byteCount)
+{
+	MV_U32 i;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+		 "%d %d: xfer data for Packet command.count %d\n",
+		 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, byteCount);
+	byteCount >>= 1;
+	switch (pPacketCommandParams->protocolType) {
+	case MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN:
+		for (i = 0; i < byteCount; i++) {
+			MV_U16 data;
+			if (pPacketCommandParams->transfered_data == pPacketCommandParams->buffer_len)
+				return MV_TRUE;
+
+			pPacketCommandParams->transfered_data += 2;
+			data = MV_REG_READ_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+						pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET);
+			*pPacketCommandParams->bufPtr++ = MV_CPU_TO_LE16(data);
+		}
+		break;
+	case MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT:
+		for (i = 0; i < byteCount; i++) {
+			if (pPacketCommandParams->transfered_data == pPacketCommandParams->buffer_len)
+				return MV_TRUE;
+
+			pPacketCommandParams->transfered_data += 2;
+			MV_REG_WRITE_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+					  pSataChannel->eDmaRegsOffset +
+					  MV_CPU_TO_LE16(MV_ATA_DEVICE_PIO_DATA_REG_OFFSET),
+					  *pPacketCommandParams->bufPtr++);
+		}
+		break;
+	default:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d: in xfer data "
+			 "Packet command: non valid protocol type (%d)\n",
+			 pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber, pPacketCommandParams->protocolType);
+		return MV_FALSE;
+	}
+	return MV_TRUE;
+}
+#endif
+
+static void completePIOCommand(MV_SATA_CHANNEL *pSataChannel,
+			       MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_BOOLEAN failed)
+{
+	MV_COMPLETION_TYPE compType = MV_COMPLETION_TYPE_NORMAL;
+	MV_STORAGE_DEVICE_REGISTERS deviceRegs;
+	MV_U8 hostTag;
+	MV_NONE_UDMA_COMMAND_PARAMS *pParams = &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand;
+
+	if (pCommandEntry->pCommandInfo->type != MV_QUEUED_COMMAND_TYPE_NONE_UDMA) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d: completePIOCommand called for"
+			 " wrong command\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+	}
+	dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter, pSataChannel->channelNumber, pParams->isEXT, &deviceRegs);
+	if (failed == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: PIO Command completed "
+			 "with error\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+
+		compType = MV_COMPLETION_TYPE_ERROR;
+		pSataChannel->queueCommandsEnabled = MV_FALSE;
+	} else {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: PIO Command completed successfully\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		pSataChannel->recoveredErrorsCounter = 0;
+	}
+	/* pCommandEntry is invalid after calling the callback function
+	   so we cache the tag to be used later */
+
+	hostTag = pCommandEntry->hostTag;
+	if (hostTag == 0xFF) {	/*NCQ Error handling ReadLogExt command */
+		/*sanity check */
+		if (pCommandEntry != pSataChannel->ErrorHandlingInfo.pReadLogExtEntry) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+				 "%d %d: in completePIOCommand, command is ReadLogExt"
+				 ", pointers mismatch \n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		}
+		commandsQueueRemove(pSataChannel, pCommandEntry);
+	} else {
+		removeCommand(pSataChannel, pCommandEntry);
+	}
+
+	pParams->callBack(pSataChannel->mvSataAdapter, pSataChannel->channelNumber,
+			  compType, pParams->commandId, 0, 0, &deviceRegs);
+
+	if (hostTag != 0xFF) {	/*if not NCQ Error handling ReadLogExt command */
+		if (failed == MV_TRUE)
+			_doDevErrorRecovery(pSataChannel);
+		else
+			_insertQCommandsIntoEdma(pSataChannel);
+	}
+}
+
+#ifdef MV_SUPPORT_ATAPI
+static void completePacketCommand(MV_SATA_CHANNEL *pSataChannel,
+				  MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_BOOLEAN failed)
+{
+	MV_COMPLETION_TYPE compType = MV_COMPLETION_TYPE_NORMAL;
+	MV_STORAGE_DEVICE_REGISTERS deviceRegs;
+	MV_PACKET_COMMAND_PARAMS *pParams = &pCommandEntry->pCommandInfo->commandParams.packetCommand;
+	MV_U32 transfered_data = pParams->transfered_data;
+
+	dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter, pSataChannel->channelNumber, MV_FALSE, &deviceRegs);
+	if (failed == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Packet Command completed "
+			 "with error\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+
+	} else {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: Packet Command completed successfully\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+	}
+	pSataChannel->recoveredErrorsCounter = 0;
+
+	removeCommand(pSataChannel, pCommandEntry);
+
+	pParams->callBack(pSataChannel->mvSataAdapter, pSataChannel->channelNumber,
+			  compType, pParams->commandId, 0, transfered_data, &deviceRegs);
+
+	_insertQCommandsIntoEdma(pSataChannel);
+}
+#endif
+static MV_VOID initTagsStack(struct _mvTagsStack *pTagsStack, MV_U8 *pTagsArray, MV_U8 size);
+
+static MV_U8 popTag(struct _mvTagsStack *pTagsStack);
+
+static MV_VOID pushTag(struct _mvTagsStack *pTagsStack, MV_U8 tag);
+
+static MV_BOOLEAN isEmpty(struct _mvTagsStack *pTagsStack);
+
+static MV_VOID initChannelTags(MV_SATA_CHANNEL *pSataChannel);
+static MV_BOOLEAN getTag(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort, MV_U8 *pHostTag, MV_U8 *pDeviceTag);
+static MV_VOID releaseTag(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort, MV_U8 hostTag, MV_U8 deviceTag);
+
+static MV_VOID initTagsStack(struct _mvTagsStack *pTagsStack, MV_U8 *pTagsArray, MV_U8 size)
+{
+	MV_U8 i;
+	pTagsStack->pTagsArray = pTagsArray;
+	pTagsStack->top = size;
+	for (i = 0; i < size; i++)
+		pTagsStack->pTagsArray[i] = size - 1 - i;
+}
+
+static MV_U8 popTag(struct _mvTagsStack *pTagsStack)
+{
+	return pTagsStack->pTagsArray[--pTagsStack->top];
+}
+
+static MV_VOID pushTag(struct _mvTagsStack *pTagsStack, MV_U8 tag)
+{
+	pTagsStack->pTagsArray[pTagsStack->top++] = tag;
+}
+
+static MV_BOOLEAN isEmpty(struct _mvTagsStack *pTagsStack)
+{
+	if (pTagsStack->top == 0)
+		return MV_TRUE;
+	return MV_FALSE;
+}
+
+static MV_VOID initChannelTags(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_U8 i;
+	for (i = 0; i < MV_SATA_GEN2E_TAG_POOLS_NUM; i++) {
+		initTagsStack(&pSataChannel->Tags.DeviceTagsPool[i],
+			      pSataChannel->Tags.DeviceTags[i], MV_SATA_TAGS_PER_POOL);
+	}
+	if (pSataChannel->use128Entries == MV_TRUE) {
+		initTagsStack(&pSataChannel->Tags.HostTagsPool,
+			      pSataChannel->Tags.HostTags, MV_SATA_GEN2E_SW_QUEUE_SIZE);
+	} else {
+		initTagsStack(&pSataChannel->Tags.HostTagsPool, pSataChannel->Tags.HostTags, MV_SATA_SW_QUEUE_SIZE);
+	}
+}
+
+static MV_BOOLEAN getTag(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort, MV_U8 *pHostTag, MV_U8 *pDeviceTag)
+{
+	MV_U8 pool = 0;		/*for Gen1-2 devices host tag must be equal to device tag */
+	if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE)
+		pool = PMPort & MV_SATA_GEN2E_TAG_PMPORT_MASK;
+
+	if ((MV_TRUE == isEmpty(&pSataChannel->Tags.HostTagsPool)) ||
+	    (MV_TRUE == isEmpty(&pSataChannel->Tags.DeviceTagsPool[pool])))
+		return MV_FALSE;
+
+	*pHostTag = popTag(&pSataChannel->Tags.HostTagsPool);
+	*pDeviceTag = popTag(&pSataChannel->Tags.DeviceTagsPool[pool]);
+	return MV_TRUE;
+}
+
+static MV_VOID releaseTag(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort, MV_U8 hostTag, MV_U8 deviceTag)
+{
+	MV_U8 pool = 0;		/*for Gen1-2 devices host tag must be equal to device tag */
+	if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE)
+		pool = PMPort & MV_SATA_GEN2E_TAG_PMPORT_MASK;
+
+	pushTag(&pSataChannel->Tags.HostTagsPool, hostTag);
+	pushTag(&pSataChannel->Tags.DeviceTagsPool[pool], deviceTag);
+}
+
+/*******************************************************************************
+* _resetEdmaQPointers - resets EDMA's Queues Pointers
+*
+*
+* DESCRIPTION:
+*
+* INPUT:
+*   *pSataChannel   - pointer to the Sata channel data structure
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+*
+* COMMENTS:
+*   this function assumes that the channel semaphore is locked
+*
+*******************************************************************************/
+static MV_BOOLEAN _resetEdmaQPointers(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: _resetEdmaQPointers\n",
+		 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+
+	pSataChannel->EdmaQueuedCommands = 0;
+	pSataChannel->reqInPtr = 0;
+	pSataChannel->rspOutPtr = 0;
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
+			   MV_EDMA_REQUEST_Q_BAH_REG_OFFSET, pSataChannel->requestQueuePciHiAddress);
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
+			   MV_EDMA_REQUEST_Q_INP_REG_OFFSET,
+			   pSataChannel->requestQueuePciLowAddress & MV_EDMA_REQUEST_Q_BA_MASK);
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET, 0);
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
+			   MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET, pSataChannel->responseQueuePciHiAddress);
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
+			   MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET, pSataChannel->responseQueuePciLowAddress);
+
+	return MV_TRUE;
+}
+
+static void setupEdmaDeviceErrorHandlingConfiguration(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+
+	if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) {
+		_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+			    MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_BIT2);
+
+		if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) {
+			_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				      MV_EDMA_HALT_CONDITIONS_REG_OFFSET, MV_BIT2);
+			_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				      MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT10 | MV_BIT8);
+		} else {
+			_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				    MV_EDMA_CONFIG_REG_OFFSET, MV_EDMA_CONFIG_CONONDEVERR_MASK);
+			/* Fix for 88SX60x1 FEr SATA#25 */
+			_setRegBits(ioBaseAddr, MV_FLASH_GPIO_PORT_CONTROL_OFFSET, MV_BIT22);
+		}
+	} else {
+
+		_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+			      MV_EDMA_CONFIG_REG_OFFSET, MV_EDMA_CONFIG_CONONDEVERR_MASK);
+		if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
+			_clearRegBits(ioBaseAddr, MV_FLASH_GPIO_PORT_CONTROL_OFFSET, MV_BIT22);
+
+		if (pSataChannel->FBSEnabled == MV_TRUE) {
+			if (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) {
+				_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+					    MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_BIT2);
+			} else {
+				_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+					      MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_BIT2);
+			}
+			_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				      MV_EDMA_HALT_CONDITIONS_REG_OFFSET, MV_BIT2);
+			_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				    MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT8);
+			_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				      MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT10);
+
+		} else {
+			_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				      MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_BIT2);
+			if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) {
+				_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+					    MV_EDMA_HALT_CONDITIONS_REG_OFFSET, MV_BIT2);
+				_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+					      MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT10 | MV_BIT8);
+			}
+		}
+	}
+}
+
+/*******************************************************************************
+* resetEdmaChannel - resets the channel data stucture and EDMA registers
+*
+*
+* DESCRIPTION:
+*   this function resets the low level EDMA fields of Sata channel data
+*   structure and initialize the EDMA register accourdingly
+*
+* INPUT:
+*   *pSataChannel   - pointer to the Sata channel data structure
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+*
+* COMMENTS:
+*   this function assumes that the channel semaphore is locked
+*
+*******************************************************************************/
+static MV_BOOLEAN resetEdmaChannel(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+	int i;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: resetEdmaChannel\n",
+		 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+
+	if (MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET) & MV_EDMA_COMMAND_HARD_RST_MASK) {
+		MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
+				   MV_EDMA_COMMAND_REG_OFFSET, MV_EDMA_COMMAND_DISABLE_MASK);
+
+		MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET);
+		mvMicroSecondsDelay(pSataChannel->mvSataAdapter, MV_HARD_RESET_WAIT_NEGATE);
+		_fixPhyParams(pSataChannel->mvSataAdapter, pSataChannel->channelNumber);
+	} else {
+		MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
+				   MV_EDMA_COMMAND_REG_OFFSET, MV_EDMA_COMMAND_DISABLE_MASK);
+	}
+
+	pSataChannel->outstandingCommands = 0;
+	for (i = 0; i <= MV_SATA_PM_MAX_PORTS; i++)
+		pSataChannel->portQueuedCommands[i] = 0;
+
+	pSataChannel->noneUdmaOutstandingCommands = 0;
+#ifdef MV_SUPPORT_ATAPI
+	pSataChannel->packetOutstandingCommands = 0;
+#endif
+	pSataChannel->EdmaActive = MV_FALSE;
+
+	/* init free entries stack */
+	initChannelTags(pSataChannel);
+	for (i = 0; i < pSataChannel->commandsQueueSize; i++)
+		pSataChannel->commandsQueue[i].isFreeEntry = MV_TRUE;
+
+	pSataChannel->commandsQueueHead = NULL;
+	pSataChannel->commandsQueueTail = NULL;
+	pSataChannel->queueCommandsEnabled = MV_FALSE;
+#ifdef MV_SATA_C2C_COMM
+
+	/* C2C */
+	pSataChannel->C2CmodeEnabled = MV_FALSE;
+#endif
+	pSataChannel->ErrorHandlingInfo.CurrPort = 0;
+	pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_IDLE;
+	pSataChannel->ErrorHandlingInfo.PortsWithErrors = 0;
+	pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA = MV_FALSE;
+	pSataChannel->recoveredErrorsCounter = 0;
+	_resetEdmaQPointers(pSataChannel);
+	return MV_TRUE;
+}
+
+static void flushDmaQueue(MV_SATA_CHANNEL *pSataChannel, MV_FLUSH_TYPE flushType,
+			  MV_COMPLETION_TYPE completionType, MV_U16 eDmaCause)
+{
+	mvSataCommandCompletionCallBack_t callBackFunc;
+	int i;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Flush DMA, type=%s, commands"
+		 " %d (on EDMA %d)\n", pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber,
+		 (flushType == MV_FLUSH_TYPE_CALLBACK) ? "CALLBACK" : "NONE",
+		 pSataChannel->outstandingCommands, pSataChannel->EdmaQueuedCommands);
+
+	if (flushType == MV_FLUSH_TYPE_CALLBACK) {
+		for (i = 0; i < pSataChannel->commandsQueueSize; i++) {
+			if (pSataChannel->commandsQueue[i].isFreeEntry == MV_FALSE) {
+				MV_STORAGE_DEVICE_REGISTERS deviceRegisters;
+				MV_BOOLEAN isEXT;
+				MV_VOID_PTR commandId;
+				switch (pSataChannel->commandsQueue[i].pCommandInfo->type) {
+				case MV_QUEUED_COMMAND_TYPE_NONE_UDMA:
+					isEXT =
+					    pSataChannel->commandsQueue[i].pCommandInfo->commandParams.NoneUdmaCommand.
+					    isEXT;
+					commandId =
+					    pSataChannel->commandsQueue[i].pCommandInfo->commandParams.NoneUdmaCommand.
+					    commandId;
+					callBackFunc =
+					    pSataChannel->commandsQueue[i].pCommandInfo->commandParams.NoneUdmaCommand.
+					    callBack;
+					break;
+				case MV_QUEUED_COMMAND_TYPE_UDMA:
+					isEXT =
+					    pSataChannel->commandsQueue[i].pCommandInfo->commandParams.udmaCommand.
+					    isEXT;
+					commandId =
+					    pSataChannel->commandsQueue[i].pCommandInfo->commandParams.udmaCommand.
+					    commandId;
+					callBackFunc =
+					    pSataChannel->commandsQueue[i].pCommandInfo->commandParams.udmaCommand.
+					    callBack;
+					break;
+				default:
+					/* MV_QUEUED_COMMAND_TYPE_PACKET: */
+					isEXT = MV_FALSE;
+					commandId =
+					    pSataChannel->commandsQueue[i].pCommandInfo->commandParams.packetCommand.
+					    commandId;
+					callBackFunc =
+					    pSataChannel->commandsQueue[i].pCommandInfo->commandParams.packetCommand.
+					    callBack;
+					break;
+				}
+
+				dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter,
+						       pSataChannel->channelNumber, isEXT, &deviceRegisters);
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "%d %d: Calling callBackFunc - host tag 0x%x (device tag 0x%x) at %p,"
+					 " next %p, prev %p, PMPort 0x%x\n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber,
+					 i,
+					 pSataChannel->commandsQueue[i].deviceTag,
+					 &pSataChannel->commandsQueue[i],
+					 pSataChannel->commandsQueue[i].next,
+					 pSataChannel->commandsQueue[i].prev,
+					 pSataChannel->commandsQueue[i].pCommandInfo->PMPort);
+				callBackFunc(pSataChannel->mvSataAdapter,
+					     pSataChannel->channelNumber, completionType,
+					     commandId, eDmaCause, 0, &deviceRegisters);
+			}
+		}
+	}
+}
+
+static void _fixPhyParams(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	/* Set unit 0 or 1 */
+	MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
+	/* Set port 0-3 */
+	MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+	MV_U32 regVal;
+
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+
+		if (pAdapter->chipIs50XXB0 == MV_TRUE) {
+			/* Fix for 88SX50xx FEr SATA#12 */
+			/* Disable auto-power management */
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+						   MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port));
+			regVal |= MV_BIT19;	/* disbale auto-power management */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+					   MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port), regVal);
+			/* 88SX50xx FEr SATA#9 */
+			/*Fix squelch threshold */
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+						   MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port));
+
+			regVal &= ~0x3;
+			regVal |= 0x1;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+					   MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port), regVal);
+		}
+		/* Revert values of pre-emphasis and signal amps to the saved ones */
+		{
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+						   MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port));
+			regVal &= ~MV_SATA_I_PHY_MODE_AMP_MASK;
+			regVal |= (pAdapter->signalAmps[channelIndex] << MV_SATA_I_PHY_MODE_AMP_OFFSET) &
+			    MV_SATA_I_PHY_MODE_AMP_MASK;
+			regVal &= ~MV_SATA_I_PHY_MODE_PRE_MASK;
+			regVal |= (pAdapter->pre[channelIndex] << MV_SATA_I_PHY_MODE_PRE_OFFSET) &
+			    MV_SATA_I_PHY_MODE_PRE_MASK;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+					   MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port), regVal);
+		}
+	}
+	if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) &&
+	    (pAdapter->chipIs62X1Z0 == MV_FALSE) && (pAdapter->chipIs65XXZ0 == MV_FALSE)) {
+		MV_U32 phyMode2Offset = getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_2_REG_OFFSET;
+		if ((pAdapter->chipIs60X1B2 == MV_TRUE) || (pAdapter->chipIs60X1C0 == MV_TRUE)) {
+			/* Fix for 88SX60X1 FEr SATA #23 */
+			/* 88SX6042/88SX7042 FEr SATA #23 */
+			/* 88F5182 FEr #SATA-S13 */
+			/* 88F5082 FEr #SATA-S13 */
+			MV_U32 regVal2;
+			regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						    getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_2_REG_OFFSET);
+			regVal2 |= MV_BIT31;
+			regVal2 &= ~MV_BIT16;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_2_REG_OFFSET, regVal2);
+			mvMicroSecondsDelay(pAdapter, 200);	/* Wait 200uSec */
+			regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						    getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_2_REG_OFFSET);
+			regVal2 &= ~MV_BIT31;
+			regVal2 &= ~MV_BIT16;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_2_REG_OFFSET, regVal2);
+			mvMicroSecondsDelay(pAdapter, 200);	/* Wait 200uSec */
+		}
+		/* Fix values in phyMode 3 register. */
+		{
+			MV_U32 regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+							   getEdmaRegOffset(channelIndex) +
+							   MV_SATA_II_PHY_MODE_3_REG_OFFSET);
+			regVal2 &= ~0x7F900000;
+			regVal2 |= 0x2A800000;
+
+			/* Implement Guidline 88F5182, 88F5082, 88F6082 (GL# SATA-S11) */
+			if ((pAdapter->pciConfigDeviceId == MV_SATA_DEVICE_ID_5182) ||
+			    (pAdapter->pciConfigDeviceId == MV_SATA_DEVICE_ID_5082) ||
+			    (pAdapter->pciConfigDeviceId == MV_SATA_DEVICE_ID_6082)) {
+				regVal2 &= ~0x1C;
+			}
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_3_REG_OFFSET, regVal2);
+		}
+		/* Fix values in phyMode 4 register. */
+		/* 88SX60x1 FEr SATA#10 */
+		/* 88F5182 GL #SATA-S10 */
+		/* 88F5082 GL #SATA-S10 */
+		if ((pAdapter->chipIs60X1B2 == MV_TRUE) || (pAdapter->chipIs60X1C0 == MV_TRUE)) {
+			MV_U32 phyMode4Value;
+			MV_U32 tempRegOffset, tempRegValue = 0;
+			MV_U32 phyMode4Offset = getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_4_REG_OFFSET;
+			tempRegOffset = getEdmaRegOffset(channelIndex) + 0x310;
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_SATA_LINK,
+				 "%d %d: PHY mode4 reg value before fix is %x\n",
+				 pAdapter->adapterId, channelIndex,
+				 MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, phyMode4Offset));
+			phyMode4Value = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, phyMode4Offset);
+			/* 88SX60x1 FEr SATA #13 */
+			if (pAdapter->chipIs60X1B2 == MV_TRUE)
+				tempRegValue = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, tempRegOffset);
+
+			phyMode4Value |= MV_BIT0;
+			phyMode4Value &= ~MV_BIT1;
+			/* phy mode 4 register of Gen IIE devices has some restriction */
+			if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) {
+				phyMode4Value &= ~0x5DE3FFFC;
+				phyMode4Value |= MV_BIT2;
+
+			}
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, phyMode4Offset, phyMode4Value);
+			/* 88SX60x1 FEr SATA #13 */
+			if (pAdapter->chipIs60X1B2 == MV_TRUE)
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, tempRegOffset, tempRegValue);
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_SATA_LINK,
+				 "%d %d: PHY mode4 reg value after fix is %x\n",
+				 pAdapter->adapterId, channelIndex,
+				 MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, phyMode4Offset));
+		}
+
+		/* Revert values of pre-emphasis and signal amps to the saved ones */
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, phyMode2Offset);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: PHY mode2 "
+			 "reg = %x (Before AMP/PRE modification)\n", pAdapter->adapterId, channelIndex, regVal);
+
+		regVal &= ~MV_SATA_II_PHY_MODE_2_AMP_MASK;
+		regVal |= (pAdapter->signalAmps[channelIndex] << MV_SATA_II_PHY_MODE_2_AMP_OFFSET) &
+		    MV_SATA_II_PHY_MODE_2_AMP_MASK;
+		regVal &= ~MV_SATA_II_PHY_MODE_2_PRE_MASK;
+		regVal |= (pAdapter->pre[channelIndex] << MV_SATA_II_PHY_MODE_2_PRE_OFFSET) &
+		    MV_SATA_II_PHY_MODE_2_PRE_MASK;
+		regVal &= ~MV_BIT16;	/* Should always write 0 to bit 16 in phymode 2 */
+
+		/*some reserved fields must be written with fixed values */
+		if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) {
+			regVal &= ~0xC30FF01F;
+			regVal |= 0x0000900F;
+		}
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, phyMode2Offset, regVal);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: PHY mode2 "
+			 "reg = %x (After AMP/PRE modification)\n",
+			 pAdapter->adapterId, channelIndex,
+			 MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, phyMode2Offset));
+	}
+	if (pAdapter->chipIs62X1Z0 == MV_TRUE) {
+
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_3_REG_OFFSET);
+
+		regVal &= ~0x78100000;
+		regVal |= 0x28000000;
+
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_3_REG_OFFSET, regVal);
+
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_4_REG_OFFSET);
+		regVal &= ~0x1;
+		regVal |= MV_BIT16;	/* must write 1 to this bit */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_4_REG_OFFSET, regVal);
+
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_9_GEN2_REG_OFFSET);
+		regVal &= ~0x7CFF;
+		regVal |= 0x00438;
+
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_9_GEN2_REG_OFFSET, regVal);
+
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_9_GEN1_REG_OFFSET);
+		regVal &= ~0x400F;
+		regVal |= 0x00008;
+
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_9_GEN1_REG_OFFSET, regVal);
+	}
+
+	if (pAdapter->chipIs65XXZ0 == MV_TRUE)
+		;	/* Do nothing */
+}
+
+static void _channelHardReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 EdmaCommandOffset = getEdmaRegOffset(channelIndex) + MV_EDMA_COMMAND_REG_OFFSET;
+
+	maskEdmaInterrupts(pAdapter, channelIndex);
+	/* 1. Set ATA reset bit */
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, EdmaCommandOffset, MV_EDMA_COMMAND_HARD_RST_MASK);
+	MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, EdmaCommandOffset);
+
+	/* 2. Wait 25uSeconds */
+	mvMicroSecondsDelay(pAdapter, MV_HARD_RESET_WAIT_ASSERT);
+
+	/* 3. Clear ATA reset bit */
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, EdmaCommandOffset, 0);
+	MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, EdmaCommandOffset);
+
+	/* 4. Change phy params (watermark + squelch) */
+	_fixPhyParams(pAdapter, channelIndex);
+	/* For Gen 1 devices, time delay is needed after resetingt the SATA bridge */
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
+		mvMicroSecondsDelay(pAdapter, MV_HARD_RESET_WAIT_NEGATE);
+
+	unmaskEdmaInterrupts(pAdapter, channelIndex);
+
+}
+
+static void _establishSataComm(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 SControlOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_CONTROL_REG_OFFSET;
+	MV_U32 SStatusOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET;
+	MV_U32 SStatus;
+	MV_U8 retryCount, commRetryCount = 5, retryWithGen1 = 0;
+
+	maskEdmaInterrupts(pAdapter, channelIndex);
+
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		/*  Set DET field in SControl register to 1 */
+		MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+		MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
+		SControlOffset = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+		    MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port);
+		SStatusOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET;
+	}
+
+	while (1) {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset, 0x301);
+		MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset);
+		MV_CPU_WRITE_BUFFER_FLUSH();
+		mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_DELAY);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset, 0x300);
+		MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset);
+		MV_CPU_WRITE_BUFFER_FLUSH();
+		mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_WAIT_DELAY);
+		unmaskEdmaInterrupts(pAdapter, channelIndex);
+		/*Wait 200 msec for PHY to become ready */
+		for (retryCount = 0; retryCount < 200; retryCount++) {
+			if (_checkSStatusAfterHReset(pAdapter, channelIndex) == MV_FALSE) {
+				mvMicroSecondsDelay(pAdapter, 1000);
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_SATA_LINK, "%d %d: SATA PHY ready "
+					 "after %d msec\n", pAdapter->adapterId, channelIndex, retryCount);
+
+				break;
+			}
+		}
+		if (retryCount == 200) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_SATA_LINK,
+				 "%d %d: SATA PHY not ready after 200 msec\n", pAdapter->adapterId, channelIndex);
+		}
+		SStatus = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SStatusOffset);
+		/* Fix for 88SX60X1 FEr #10 - retry SATA communication if failed 5 times */
+		/* this workaround applied for all devices for simplicity and robustness */
+		if ((SStatus == 0x0) || (SStatus == 0x113) || (SStatus == 0x123))
+			break;
+
+		commRetryCount--;
+		if (commRetryCount == 0) {
+			MV_U32 regVal;
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_FATAL_ERROR,
+				 "%d %d: Failed OOB sequence 5 times !!!\n", pAdapter->adapterId, channelIndex);
+			if ((SStatus != 0x121) || (retryWithGen1 == 1)
+			    || (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)) {
+				break;
+			}
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_FATAL_ERROR,
+				 "%d %d: SStatus is 0x121, Retry OOB sequence with Gen1 \n",
+				 pAdapter->adapterId, channelIndex);
+			retryWithGen1 = 1;
+			commRetryCount = 5;
+			/* set the phy in offline mode */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset, 0x304);
+
+			/* force Sata speed to Gen1 */
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+			/* according to the spec, bits [31:12] must be set to 0x009B1 */
+			/* Fix for 88SX60x1 FEr SATA#8 */
+			regVal &= 0x00000FFF;
+			/* regVal |= MV_BIT12; */
+			regVal |= 0x009B1000;
+			regVal &= ~MV_BIT7;	/* Disable GEn II */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+
+			_channelHardReset(pAdapter, channelIndex);
+		}
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 "%d %d: Retrying OOB sequnce", pAdapter->adapterId, channelIndex);
+	}
+}
+
+static void _establishSataCommAll(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U8 channelIndex;
+	MV_U32 SControlOffset;
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) {
+			maskEdmaInterrupts(pAdapter, channelIndex);
+			SControlOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_CONTROL_REG_OFFSET;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset, 0x301);
+
+		}
+		/* Wait for 1mSecond for COMRESET for all drives */
+		mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_DELAY);
+		for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) {
+			SControlOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_CONTROL_REG_OFFSET;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset, 0x300);
+		}
+		mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_WAIT_DELAY);
+		for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++)
+			unmaskEdmaInterrupts(pAdapter, channelIndex);
+	}
+}
+
+void _setActivePMPort(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+	MV_U32 regVal;
+
+	if (pSataChannel->PMSupported == MV_FALSE)
+		return;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_PM, "%d %d: Set TX PM"
+		 " Port to %x\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, PMPort);
+
+	regVal = MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_SATA_II_IF_CONTROL_REG_OFFSET);
+
+	regVal &= ~MV_SATA_II_IF_CONTROL_PMTX_MASK;
+	regVal |= (PMPort << MV_SATA_II_IF_CONTROL_PMTX_OFFSET) & MV_SATA_II_IF_CONTROL_PMTX_MASK;
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_SATA_II_IF_CONTROL_REG_OFFSET, regVal);
+	MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_SATA_II_IF_CONTROL_REG_OFFSET);
+
+}
+
+static void revertSataHCRegs(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U8 channelIndex;
+	MV_U8 temp;
+	MV_U32 edmaRegsOffset;
+	MV_U32 sataHcRegsOffset;
+	MV_U32 regTemp;
+	MV_U8 sataUnit;
+
+	if ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) || (pAdapter->hostInterface == MV_HOST_IF_INTEGRATED)) {
+		for (sataUnit = 0; sataUnit < pAdapter->numberOfUnits; sataUnit++) {
+			for (temp = 0; temp < pAdapter->portsPerUnit; temp++) {
+				channelIndex = temp + sataUnit * pAdapter->portsPerUnit;
+				edmaRegsOffset = getEdmaRegOffset(channelIndex);
+
+				/* Disable EDMA */
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET,
+						   MV_EDMA_COMMAND_DISABLE_MASK);
+				MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						  edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET);
+
+				/* Reset SATA bridge */
+				_channelHardReset(pAdapter, channelIndex);
+
+				/* Zero EDMA registersr */
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET, 0);
+
+				if (pAdapter->hostInterface == MV_HOST_IF_INTEGRATED) {
+					MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+							   edmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET, 0x101f);
+				} else {
+					MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+							   edmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET, 0x11f);
+				}
+
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_TIMER_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_REQUEST_Q_BAH_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_REQUEST_Q_INP_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_TEST_CONTROL_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   edmaRegsOffset + MV_EDMA_IORDY_TIMEOUT_REG_OFFSET, 0x800);
+			}
+
+			/* Revert values of SATA HC regs (few registers are READ-ONLY ) */
+			if (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED) {
+				sataHcRegsOffset = MV_SATAHC_REGS_BASE_OFFSET(sataUnit);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   sataHcRegsOffset + MV_SATAHC_INT_COAL_THRE_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   sataHcRegsOffset + MV_SATAHC_INT_TIME_THRE_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   sataHcRegsOffset + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, 0);
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   sataHcRegsOffset + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET, 0);
+				regTemp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+							    sataHcRegsOffset +
+							    MV_SATA_I_HC_BRIDGES_PINS_CONFIG_REG_OFFSET);
+				/* Keep the SS during power on and the reference clock bits (reset sample ) */
+				regTemp &= 0x1c1c1c1c;
+				regTemp |= 0x03030303;
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   sataHcRegsOffset + MV_SATA_I_HC_BRIDGES_PINS_CONFIG_REG_OFFSET,
+						   regTemp);
+			}
+		}
+	}
+
+	if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) {
+		MV_U32 timeout;
+		/* Use global reset feature */
+		/* Empty PCI master */
+
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET, MV_PCI_MAIN_COMMAND_STOP_MASTER_MASK);
+		MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET);
+		timeout = 1000;
+		while (timeout) {
+			if (MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					      MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET) &
+			    MV_PCI_MAIN_COMMAND_MASTER_EMPTY_MASK) {
+				break;
+			}
+
+			mvMicroSecondsDelay(pAdapter, 1);
+			timeout--;
+		}
+		if (timeout == 0) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: Global reset timeout when"
+				 " trying to flush PCI master - discarding the master flush", pAdapter->adapterId);
+		}
+		/* Issue global reset - this will reset both SATAHC */
+		regTemp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET);
+		regTemp |= MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET, regTemp);
+		regTemp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET);
+		if (!(regTemp & MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: Global reset error while "
+				 "writing '1' to the global reset bit", pAdapter->adapterId);
+		}
+		mvMicroSecondsDelay(pAdapter, 5);
+		regTemp &= ~(MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK | MV_PCI_MAIN_COMMAND_STOP_MASTER_MASK);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET, regTemp);
+		regTemp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET);
+		if (regTemp & MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: Global reset error while "
+				 "writing '1' to the global reset bit", pAdapter->adapterId);
+		}
+		mvMicroSecondsDelay(pAdapter, 5);
+	}
+}
+
+static void revertFlashInterfaceRegs(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U32 regTemp;
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_PARAMS_REG_OFFSET, 0x0fcfffff);
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		regTemp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
+		regTemp &= 0x3;
+		regTemp |= (MV_BIT5 | MV_BIT6);
+
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET, regTemp);
+	}
+}
+
+static void revertPCIInterfaceRegs(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U32 regTemp;
+	if ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)) {
+		if (!((pAdapter->pciConfigDeviceId == MV_SATA_DEVICE_ID_5080) &&
+		      (pAdapter->pciConfigRevisionId == 0x0))) {
+			regTemp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						    MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
+			regTemp |= MV_BIT0;
+
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, regTemp);
+		}
+	}
+
+	regTemp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MODE_REG_OFFSET);
+	regTemp &= 0xff00ffff;
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MODE_REG_OFFSET, regTemp);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_DISCARD_TIMER_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_MSI_TRIGGER_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_XBAR_IF_TIMEOUT_REG_OFFSET, 0x000100ff);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_SERR_MASK_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_INTERRUPT_CAUSE_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_INTERRUPT_MASK_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_ERROR_LOW_ADDRESS_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_ERROR_HIGH_ADDRESS_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_ERROR_ATTRIBUTE_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_ERROR_COMMAND_REG_OFFSET, 0);
+}
+
+static void revertPEXInterfaceRegs(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_E_INTERRUPT_CAUSE_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_E_INTERRUPT_MASK_REG_OFFSET, 0);
+}
+
+static void commandsQueueAddTail(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry)
+{
+	pCommandEntry->next = NULL;
+	pCommandEntry->prev = pSataChannel->commandsQueueTail;
+	if (pSataChannel->commandsQueueTail != NULL)
+		pSataChannel->commandsQueueTail->next = pCommandEntry;
+
+	pSataChannel->commandsQueueTail = pCommandEntry;
+
+	if (pSataChannel->commandsQueueHead == NULL)
+		pSataChannel->commandsQueueHead = pCommandEntry;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: command queued. Head:%p Tail:%p "
+		 "command :%p\n", pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber, pSataChannel->commandsQueueHead,
+		 pSataChannel->commandsQueueTail, pCommandEntry);
+}
+
+static void commandsQueueAddHead(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry)
+{
+	pCommandEntry->next = pSataChannel->commandsQueueHead;
+	pCommandEntry->prev = NULL;
+	if (pSataChannel->commandsQueueHead != NULL)
+		pSataChannel->commandsQueueHead->prev = pCommandEntry;
+
+	pSataChannel->commandsQueueHead = pCommandEntry;
+
+	if (pSataChannel->commandsQueueTail == NULL)
+		pSataChannel->commandsQueueTail = pCommandEntry;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: command queued. Head:%p Tail:%p "
+		 "command :%p\n", pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber, pSataChannel->commandsQueueHead,
+		 pSataChannel->commandsQueueTail, pCommandEntry);
+}
+
+static void commandsQueueRemove(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry)
+{
+	if (pCommandEntry->next == NULL) {	/* last */
+		pSataChannel->commandsQueueTail = pCommandEntry->prev;
+		if (pSataChannel->commandsQueueTail != NULL)
+			pSataChannel->commandsQueueTail->next = NULL;
+	} else {
+		pCommandEntry->next->prev = pCommandEntry->prev;
+	}
+
+	if (pCommandEntry->prev == NULL) {	/* head */
+		pSataChannel->commandsQueueHead = pCommandEntry->next;
+		if (pSataChannel->commandsQueueHead != NULL)
+			pSataChannel->commandsQueueHead->prev = NULL;
+	} else {
+		pCommandEntry->prev->next = pCommandEntry->next;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: command removed. Head:%p Tail:%p "
+		 "command :%p\n", pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber, pSataChannel->commandsQueueHead,
+		 pSataChannel->commandsQueueTail, pCommandEntry);
+	pCommandEntry->next = NULL;
+	pCommandEntry->prev = NULL;
+}
+
+static void addCommand(MV_SATA_CHANNEL *pSataChannel,
+		       MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_QUEUE_COMMAND_INFO *pCommandInfo)
+{
+#ifndef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+	pCommandEntry->pCommandInfo = &pCommandEntry->commandInfo;
+	switch (pCommandInfo->type) {
+	case MV_QUEUED_COMMAND_TYPE_UDMA:
+		memcpy(&pCommandEntry->pCommandInfo->commandParams.udmaCommand,
+		       &pCommandInfo->commandParams.udmaCommand, sizeof(MV_UDMA_COMMAND_PARAMS));
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: queue Udma command.\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		break;
+	case MV_QUEUED_COMMAND_TYPE_NONE_UDMA:
+		memcpy(&pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand,
+		       &pCommandInfo->commandParams.NoneUdmaCommand, sizeof(MV_NONE_UDMA_COMMAND_PARAMS));
+		pSataChannel->noneUdmaOutstandingCommands++;
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: queue Non Udma command.[%d]\n",
+			 pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber, pSataChannel->noneUdmaOutstandingCommands);
+		break;
+#ifdef MV_SUPPORT_ATAPI
+	case MV_QUEUED_COMMAND_TYPE_PACKET:
+		memcpy(&pCommandEntry->pCommandInfo->commandParams.packetCommand,
+		       &pCommandInfo->commandParams.packetCommand, sizeof(MV_PACKET_COMMAND_PARAMS));
+		pSataChannel->packetOutstandingCommands++;
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: queue Packet command.[%d]\n",
+			 pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber, pSataChannel->packetOutstandingCommands);
+		break;
+#endif
+	default:
+		break;
+	}
+	pCommandEntry->pCommandInfo->type = pCommandInfo->type;
+	pCommandEntry->pCommandInfo->PMPort = pCommandInfo->PMPort;
+#else
+	if (pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA)
+		pSataChannel->noneUdmaOutstandingCommands++;
+	else if (pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET)
+		pSataChannel->packetOutstandingCommands++;
+
+	pCommandEntry->pCommandInfo = pCommandInfo;
+#endif
+	commandsQueueAddTail(pSataChannel, pCommandEntry);
+	/* pCommandEntry->commandTag = ? */
+	pCommandEntry->isFreeEntry = MV_FALSE;
+	pSataChannel->outstandingCommands++;
+	pSataChannel->portQueuedCommands[pCommandInfo->PMPort]++;
+}
+
+static void removeCommand(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry)
+{
+	if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_UDMA) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: remove Udma command.\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+	} else if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: remove Non Udma command.[%d]\n",
+			 pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber, pSataChannel->noneUdmaOutstandingCommands);
+
+		pSataChannel->noneUdmaOutstandingCommands--;
+	}
+#ifdef MV_SUPPORT_ATAPI
+	else {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: remove Packet command.[%d]\n",
+			 pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber, pSataChannel->packetOutstandingCommands);
+
+		pSataChannel->packetOutstandingCommands--;
+	}
+#endif
+	commandsQueueRemove(pSataChannel, pCommandEntry);
+	releaseTag(pSataChannel, pCommandEntry->pCommandInfo->PMPort, pCommandEntry->hostTag, pCommandEntry->deviceTag);
+	pCommandEntry->isFreeEntry = MV_TRUE;
+	pSataChannel->outstandingCommands--;
+	pSataChannel->portQueuedCommands[pCommandEntry->pCommandInfo->PMPort]--;
+}
+
+static MV_U32 SaDevInterrutpBit(MV_U8 channelIndex)
+{
+	MV_U32 maskBit = 0;
+
+	if (channelIndex >= MV_SATA_PORT_PER_UNIT)
+		maskBit = (1 << ((channelIndex << 1) + 2));
+	else
+		maskBit = (1 << ((channelIndex << 1) + 1));
+
+	return maskBit;
+}
+
+static void enableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 maskBit = 0;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: enable SaDevInterrupts.\n",
+		 pAdapter->adapterId, channelIndex);
+	maskBit = SaDevInterrutpBit(channelIndex);
+	mvOsSemTake(&pAdapter->interruptsMaskSem);
+
+	pAdapter->mainMask |= maskBit;
+
+	/*clear disk interrupt */
+	MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress,
+			 getEdmaRegOffset(channelIndex) + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+	/* clear DevInterrupt */
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+			   MV_SATAHC_REGS_BASE_OFFSET((channelIndex & MV_BIT2) >> 2) +
+			   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << (channelIndex & (MV_BIT0 | MV_BIT1))));
+
+	/* unmask */
+	if (pAdapter->interruptsAreMasked == MV_FALSE) {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, pAdapter->mainMask);
+
+		MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset);
+
+	}
+	mvOsSemRelease(&pAdapter->interruptsMaskSem);
+}
+
+void disableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 maskBit = 0;
+
+	maskBit = SaDevInterrutpBit(channelIndex);
+	mvOsSemTake(&pAdapter->interruptsMaskSem);
+	pAdapter->mainMask &= ~maskBit;
+	if (pAdapter->interruptsAreMasked == MV_FALSE) {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, pAdapter->mainMask);
+
+		MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset);
+
+	}
+	mvOsSemRelease(&pAdapter->interruptsMaskSem);
+}
+
+static void _checkATAStatus(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	MV_U8 ATAstatus = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress,
+					   pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		if ((ATAstatus & (MV_ATA_BUSY_STATUS | MV_ATA_DATA_REQUEST_STATUS |
+				  MV_ATA_READY_STATUS | MV_ATA_DEVICE_FAULT_STATUS |
+				  MV_ATA_ERROR_STATUS)) == MV_ATA_READY_STATUS) {
+			return;
+		}
+	} else {
+		if ((ATAstatus & (MV_ATA_BUSY_STATUS | MV_ATA_DATA_REQUEST_STATUS |
+				  MV_ATA_READY_STATUS)) == MV_ATA_READY_STATUS) {
+			return;
+		}
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: _checkATAStatus "
+		 "EDMA can't be enabled with ATA status (0x%02x), do SW reset\n",
+		 pAdapter->adapterId, channelIndex, ATAstatus);
+	if (pSataChannel->PMSupported == MV_TRUE)
+		_setActivePMPort(pSataChannel, MV_SATA_PM_CONTROL_PORT);
+
+	_doSoftReset(pSataChannel);
+}
+
+static void activateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 eDmaRegsOffset;
+	MV_U8 sataUnit;
+	MV_U8 port;
+
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: activateEdma\n", pAdapter->adapterId, channelIndex);
+	pSataChannel->EdmaActive = MV_TRUE;
+	sataUnit = (channelIndex & MV_BIT2) >> 2;
+	port = channelIndex & (MV_BIT0 | MV_BIT1);
+	/* clear Device interrupt */
+	MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+			   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~((MV_BIT8 | MV_BIT0) << port));
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		MV_REG_WRITE_DWORD(ioBaseAddr,
+				   pSataChannel->eDmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, 0);
+	} else {
+		MV_REG_WRITE_DWORD(ioBaseAddr,
+				   pSataChannel->eDmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, MV_BIT8);
+	}
+
+	if (pSataChannel->FBSEnabled == MV_TRUE)
+		_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET, MV_BIT16);
+
+	/* disable sata device interrupts */
+	disableSaDevInterrupts(pAdapter, channelIndex);
+
+	MV_CPU_WRITE_BUFFER_FLUSH();
+
+	_checkATAStatus(pAdapter, channelIndex);
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET, MV_EDMA_COMMAND_ENABLE_MASK);
+}
+
+static void deactivateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 eDmaRegsOffset;
+	MV_U32 counter = 0;
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: deactivateEdma\n", pAdapter->adapterId, channelIndex);
+	pSataChannel->EdmaActive = MV_FALSE;
+
+	MV_CPU_WRITE_BUFFER_FLUSH();
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET, MV_EDMA_COMMAND_DISABLE_MASK);
+	while (counter < 1000) {
+		if (MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET) & MV_BIT0) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: deactivateEdma: "
+				 "Edma still active. elapsed time %d us\n", pAdapter->adapterId,
+				 channelIndex, counter * 1000);
+			mvMicroSecondsDelay(pAdapter, 1000);
+		} else {
+			break;
+		}
+		counter++;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: deactivateEdma: "
+		 "Edma status reg 0x%08x\n", pAdapter->adapterId,
+		 channelIndex, MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_STATUS_REG_OFFSET));
+	if (counter >= 1000) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+			 " %d %d: deactivateEdma: Edma Failed (EDMA status = %x)\n",
+			 pAdapter->adapterId, channelIndex,
+			 MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_STATUS_REG_OFFSET));
+		pSataChannel->queueCommandsEnabled = MV_FALSE;
+		flushDmaQueue(pSataChannel, MV_FLUSH_TYPE_CALLBACK, MV_COMPLETION_TYPE_ABORT, 0);
+		resetEdmaChannel(pSataChannel);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR,
+					    MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR, channelIndex);
+		mvOsSemTake(&pSataChannel->semaphore);
+	}
+	if (pSataChannel->FBSEnabled == MV_TRUE)
+		_clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET, MV_BIT16);
+
+	/*_dumpSataRegs(pAdapter, channelIndex);*/
+	enableSaDevInterrupts(pAdapter, channelIndex);
+}
+
+static void EdmaReqQueueInsert(MV_SATA_CHANNEL *pSataChannel,
+			       MV_QUEUED_COMMAND_ENTRY *pCommandEntry, MV_UDMA_COMMAND_PARAMS *pUdmaParams)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND, " %d %d: Insert Edma "
+		 "Request. PMPort %x host tag = 0x%x device tag = 0x%x\n",
+		 pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber, pCommandEntry->pCommandInfo->PMPort,
+		 pCommandEntry->hostTag, pCommandEntry->deviceTag);
+
+	/* insert the last commmand into the Edma queue */
+	if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) {
+		writeGen2EEdmaRequestEntry(&pSataChannel->requestQueue[pSataChannel->reqInPtr],
+					   pSataChannel, pCommandEntry, pUdmaParams);
+	} else {
+		writeEdmaRequestEntry(&pSataChannel->requestQueue[pSataChannel->reqInPtr],
+				      pSataChannel, pCommandEntry, pUdmaParams);
+	}
+	pSataChannel->reqInPtr++;
+	pSataChannel->reqInPtr &= pSataChannel->EDMAQueuePtrMask;
+	pSataChannel->EdmaQueuedCommands++;
+	pCommandEntry->isCommandInEdma = MV_TRUE;
+	pCommandEntry->commandAborted = MV_FALSE;
+
+	MV_CPU_WRITE_BUFFER_FLUSH();
+	MV_REG_WRITE_DWORD(ioBaseAddr,
+			   pSataChannel->eDmaRegsOffset +
+			   MV_EDMA_REQUEST_Q_INP_REG_OFFSET,
+			   pSataChannel->requestQueuePciLowAddress |
+			   ((pSataChannel->reqInPtr << MV_EDMA_REQUEST_Q_INP_OFFSET)
+			    & pSataChannel->EDMARequestInpMask));
+}
+
+static MV_VOID _insertQCommandsIntoEdma(MV_SATA_CHANNEL *pSataChannel)
+{
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: _insert"
+		 "QCommandsIntoEdma\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+
+	if (pSataChannel->commandsQueueHead == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: Commands queue is empty\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		return;
+	}
+	if (pSataChannel->commandsQueueHead->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: Next Command is PIO\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		if (pSataChannel->PMSupported == MV_TRUE)
+			_setActivePMPort(pSataChannel, pSataChannel->commandsQueueHead->pCommandInfo->PMPort);
+
+		if (sendNoneUdmaCommand(pSataChannel, pSataChannel->commandsQueueHead) == MV_FALSE)
+			completePIOCommand(pSataChannel, pSataChannel->commandsQueueHead, MV_TRUE);
+	}
+#ifdef MV_SUPPORT_ATAPI
+
+	else if (pSataChannel->commandsQueueHead->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: Next Command is Packet\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		if (pSataChannel->PMSupported == MV_TRUE)
+			_setActivePMPort(pSataChannel, pSataChannel->commandsQueueHead->pCommandInfo->PMPort);
+
+		if (sendNoneUdmaCommand(pSataChannel, pSataChannel->commandsQueueHead) == MV_FALSE)
+			completePacketCommand(pSataChannel, pSataChannel->commandsQueueHead, MV_TRUE);
+	}
+#endif /* MV_SUPPORT_ATAPI */
+	else {
+		MV_QUEUED_COMMAND_ENTRY *pEntry;
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+			 "%d %d: Next Command is UDMA\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		activateEdma(pSataChannel->mvSataAdapter, pSataChannel->channelNumber);
+		pEntry = pSataChannel->commandsQueueHead;
+		while ((pEntry != NULL) && (pEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_UDMA)) {
+			EdmaReqQueueInsert(pSataChannel, pEntry, &pEntry->pCommandInfo->commandParams.udmaCommand);
+			pEntry = pEntry->next;
+		}
+
+	}
+
+}
+
+/* do device error recovery for PIO, DMA and QUEUED DMA commands (not NCQ)*/
+static MV_BOOLEAN _doDevErrorRecovery(MV_SATA_CHANNEL *pSataChannel)
+{
+	if ((pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I) ||
+	    (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED)) {
+		if (_doSoftReset(pSataChannel) == MV_FALSE)
+			return MV_FALSE;
+	}
+	pSataChannel->queueCommandsEnabled = MV_TRUE;
+	/* Enable the storage device interrupts */
+	enableSaDevInterrupts(pSataChannel->mvSataAdapter, pSataChannel->channelNumber);
+	_resetEdmaQPointers(pSataChannel);
+	_insertQCommandsIntoEdma(pSataChannel);
+	return MV_TRUE;
+}
+
+/* this function used for NCQ error handling or FBS mode, it cheks if further commands
+    expected to be completed successfully (from drives without errors in PM)*/
+static MV_BOOLEAN isGoodCompletionsExpected(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_QUEUED_COMMAND_ENTRY *pEntry;
+
+	pEntry = pSataChannel->commandsQueueHead;
+	while (pEntry != NULL) {
+		if (pEntry->isCommandInEdma == MV_TRUE) {
+			if (pEntry->commandAborted == MV_FALSE) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d %d: isGoodCompletionsExpected: command (host tag 0x%02x)"
+					 "(device tag 0x%02x) expected with good completion from port 0x%02x. "
+					 "PortsWithErros= 0x%04x \n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, pEntry->hostTag,
+					 pEntry->deviceTag,
+					 pEntry->pCommandInfo->PMPort, pSataChannel->ErrorHandlingInfo.PortsWithErrors);
+				return MV_TRUE;
+			}
+		} else {
+			/* stop once reached a command that has not been inserted into the
+			   EDMA since the next commands also must be outside the EDMA
+			 */
+			break;
+		}
+		pEntry = pEntry->next;
+	}
+
+	if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) {
+		if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) {
+			MV_U32 EDMAStatus = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+							      pSataChannel->eDmaRegsOffset + MV_EDMA_STATUS_REG_OFFSET);
+
+			/*wait for internal commands cache to be empty */
+			if ((EDMAStatus & MV_EDMA_STATUS_ECACHE_EMPTY_BIT) == 0) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d %d: isGoodCompletionsExpected: eCache not empty,"
+					 " wait for completions with errors\n",
+					 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+				return MV_TRUE;
+			}
+			if ((EDMAStatus & MV_EDMA_STATUS_EDMA_IDLE_BIT) == 0) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d %d: isGoodCompletionsExpected: EDMA is not Idle\n",
+					 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+				return MV_TRUE;
+			}
+		}
+	}
+	/* check for responses */
+	if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) {
+		MV_U32 rspInReg = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+						    pSataChannel->eDmaRegsOffset + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET);
+		MV_U32 rspInPtr = 0;
+		if (pSataChannel->use128Entries == MV_TRUE)
+			rspInPtr = getRegField(rspInReg, 3, 7);
+		else
+			rspInPtr = getRegField(rspInReg, 3, 5);
+
+		if (pSataChannel->rspOutPtr != rspInPtr) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d: isGoodCompletionsExpected: More responses need to be "
+				 "handled, Response In Ptr 0x%x, SW Response Out Ptr 0x%x\n",
+				 pSataChannel->mvSataAdapter->adapterId,
+				 pSataChannel->channelNumber, rspInPtr, pSataChannel->rspOutPtr);
+			return MV_TRUE;
+		}
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 " %d %d: isGoodCompletionsExpected: No commands expected to be "
+		 "completed. PortrNumDevError 0x%04x\n",
+		 pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber, pSataChannel->ErrorHandlingInfo.PortsWithErrors);
+	return MV_FALSE;
+}
+
+/* this function used for NCQ error handling, this function called wheb DevErr
+    interrupt receivedm it checks which PM ports repored device error and updates
+    PortsWithErrors varibles
+*/
+
+static MV_VOID updatePortsWithErrors(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_U32 testCtrlReg = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+					       pSataChannel->eDmaRegsOffset + MV_SATA_II_IF_TEST_CTRL_REG_OFFSET);
+	testCtrlReg &= 0xFFFF0000;
+	testCtrlReg = testCtrlReg >> 16;
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 " %d %d: updatePortsWithErrors: old val 0x%04x, new 0x%04x\n",
+		 pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber,
+		 pSataChannel->ErrorHandlingInfo.PortsWithErrors,
+		 pSataChannel->ErrorHandlingInfo.PortsWithErrors | testCtrlReg);
+
+	pSataChannel->ErrorHandlingInfo.PortsWithErrors |= (MV_U16) testCtrlReg;
+}
+
+/* this function called when Device Error occures in NCQ mode or FBS mode*/
+/* is detects which outstanding commands (command in the EDMA) are aborted by*/
+/* the drive due to the error, also it resumes the transport layer*/
+static MV_VOID setAbortedCommands(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_QUEUED_COMMAND_ENTRY *pEntry;
+	MV_U32 TCQOutStandingStatus[4] = { 0, 0, 0, 0 };
+	MV_U8 TCQPortWithError = 0;
+	/*sanity checks */
+	if ((pSataChannel == NULL) || (pSataChannel->EdmaActive == MV_FALSE)) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "setAbortedCommands called in wrong context\n");
+		return;
+	}
+	if (pSataChannel->FBSEnabled == MV_TRUE) {
+		MV_U32 TCQStatus = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+						     pSataChannel->eDmaRegsOffset + MV_EDMA_TCQ_STATUS_REG_OFFSET);
+
+		TCQOutStandingStatus[0] = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+							    pSataChannel->eDmaRegsOffset +
+							    MV_EDMA_NCQTCQ0_OUTSTANDING_REG_OFFSET);
+		TCQOutStandingStatus[1] = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+							    pSataChannel->eDmaRegsOffset +
+							    MV_EDMA_NCQTCQ1_OUTSTANDING_REG_OFFSET);
+		TCQOutStandingStatus[2] = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+							    pSataChannel->eDmaRegsOffset +
+							    MV_EDMA_NCQTCQ2_OUTSTANDING_REG_OFFSET);
+		TCQOutStandingStatus[3] = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+							    pSataChannel->eDmaRegsOffset +
+							    MV_EDMA_NCQTCQ3_OUTSTANDING_REG_OFFSET);
+
+		{
+			MV_U32 regVal = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+							  pSataChannel->eDmaRegsOffset +
+							  MV_SATA_II_IF_STATUS_REG_OFFSET);
+
+			TCQPortWithError = (MV_U8) getRegField(regVal, 8, 4);
+		}
+
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " %d %d: setAbortedCommands: \n"
+			 "TCQPortWithError = 0x%04x \n"
+			 "TCQStatus = 0x%04x \n"
+			 "TCQ0OutStandingStatus = 0x%04x \n"
+			 "TCQ1OutStandingStatus = 0x%04x \n"
+			 "TCQ2OutStandingStatus = 0x%04x \n"
+			 "TCQ3OutStandingStatus = 0x%04x \n",
+			 pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber,
+			 TCQPortWithError,
+			 TCQStatus,
+			 TCQOutStandingStatus[0],
+			 TCQOutStandingStatus[1], TCQOutStandingStatus[2], TCQOutStandingStatus[3]);
+		/* clear DRQ bit */
+		if (TCQStatus & (MV_BIT0 << TCQPortWithError)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d: setAbortedCommands Clear TCQ DRQ\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+			TCQStatus &= ~(MV_BIT0 << TCQPortWithError);
+			MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+					   pSataChannel->eDmaRegsOffset + MV_EDMA_TCQ_STATUS_REG_OFFSET, TCQStatus);
+		}
+		/* clear SERVICE bit */
+		if (TCQStatus & (MV_BIT16 << TCQPortWithError)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d: setAbortedCommands Clear TCQ Service\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+			TCQStatus &= ~(MV_BIT16 << TCQPortWithError);
+			MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+					   pSataChannel->eDmaRegsOffset + MV_EDMA_TCQ_STATUS_REG_OFFSET, TCQStatus);
+		}
+		/* clear Device errors in EDMA error cause register */
+		MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+				   pSataChannel->eDmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, ~MV_BIT2);
+
+		/*clear interrupt cause to resume the transport layer operation */
+		MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+				   pSataChannel->eDmaRegsOffset + MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET, ~MV_BIT8);
+	}
+	pEntry = pSataChannel->commandsQueueHead;
+	while (pEntry != NULL) {
+		if (pEntry->isCommandInEdma == MV_TRUE) {
+			if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) {
+				if ((((MV_U16) (1 << pEntry->pCommandInfo->PMPort)) &
+				     pSataChannel->ErrorHandlingInfo.PortsWithErrors) != 0) {
+					pEntry->commandAborted = MV_TRUE;
+				}
+			} else { /*FBS*/
+				if (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) {
+					if (pEntry->pCommandInfo->PMPort == TCQPortWithError) {
+						MV_U32 bitmap = (1 << ((MV_U32) pEntry->hostTag));
+						MV_U8 reg = (pEntry->hostTag >> 5) & 0x3;
+						if ((bitmap & TCQOutStandingStatus[reg]) != 0)
+							pEntry->commandAborted = MV_TRUE;
+					}
+				}
+			}
+			if (pEntry->commandAborted == MV_TRUE) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d %d: command (host tag 0x%02x)"
+					 "(device tag 0x%02x) not expected, port 0x%02x. \n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, pEntry->hostTag,
+					 pEntry->deviceTag, pEntry->pCommandInfo->PMPort);
+			}
+		} else {
+			/* stop once reached a command that has not been inserted into the
+			   EDMA since the next commands also must be outside the EDMA
+			 */
+			break;
+		}
+		pEntry = pEntry->next;
+	}
+}
+
+/* this function used for NCQ error handling, called when device error received
+   and no further good complitions expected. it stops the EDMA and starts the
+   process if sending ReadLogExt commands to the drives that reported device
+   errors
+*/
+static MV_VOID enterRequestSenseState(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_U8 ATAstatus;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 " %d %d: enterRequestSenseState: PortsWithErrors 0x%04x\n",
+		 pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber, pSataChannel->ErrorHandlingInfo.PortsWithErrors);
+	/* Fix for 88SX60x1 FEr SATA#25 */
+	{
+		pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA = MV_FALSE;
+		if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_II) {
+			MV_U32 EDMAStatus = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+							      pSataChannel->eDmaRegsOffset + MV_EDMA_STATUS_REG_OFFSET);
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d: EDMA state is %x\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, EDMAStatus);
+
+			if (getRegField(EDMAStatus, 8, 8) == 0x70) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d %d: EDMA state is 0x70 do WA\n",
+					 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+				pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA = MV_TRUE;
+			}
+		}
+	}
+	deactivateEdma(pSataChannel->mvSataAdapter, pSataChannel->channelNumber);
+	if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED) {
+		if (pSataChannel->FBSEnabled != MV_TRUE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+				 "enterRequestSenseState called in wrong context\n");
+			return;
+		}
+
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " %d %d: enterRequestSenseState: Finished All erring ports\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_IDLE;
+		pSataChannel->ErrorHandlingInfo.PortsWithErrors = 0;
+		_resetEdmaQPointers(pSataChannel);
+		_insertQCommandsIntoEdma(pSataChannel);
+		return;
+	}
+
+	/* clear Device errors in EDMA error cause register due to the aborted
+	   commands */
+	MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+			   pSataChannel->eDmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, ~MV_BIT2);
+	/* the EDMA may be disabled after FPDMA commands issued and before */
+	/* receiving response from the drive (D2H Fis), in this case the ATA  */
+	/* busy bit will be set, so we wait for this bit to be cleared by the */
+	/* drive when is sends D2H registers Fis and SaDevInterrupt will be issued */
+
+	/* clear SaDevInterrupt if already received */
+	{
+		MV_U8 port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1);
+		MV_U8 sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2;
+
+		MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port));
+	}
+
+	ATAstatus = MV_REG_READ_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+				     pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+
+	if (ATAstatus & MV_ATA_BUSY_STATUS) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: ATA Busy"
+			 "bit is set after disabling EDMA, wait for SaDevInterrupt\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_WAIT_FOR_BUSY;
+		return;
+	}
+	pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_REQUEST_SENSE;
+	pSataChannel->ErrorHandlingInfo.CurrPort = 0;
+	if (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED)
+		/*TCQ*/ {
+		softResetErringPorts(pSataChannel);
+	} else {
+		setReadLogExtCmndPointers(pSataChannel);
+		handlePortError(pSataChannel);
+	}
+}
+
+/* this function used for NCQ error handling, called from the ReadLogExt command
+    callback function, it makes sanity checks for the command output and
+    completes the erring command with the ATA registers values, finally it calls
+    handlePortError to handle NCQ errors from the next drive if any*/
+static MV_BOOLEAN parseReadLogExtOutPut(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_U32 count;
+	MV_U8 tag;
+	MV_STORAGE_DEVICE_REGISTERS registerStruct;
+	MV_QUEUED_COMMAND_ENTRY *pCommandEntry;
+
+	MV_U8_PTR ReadLogExtBuffer = (MV_U8_PTR) pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer;
+	/* chack CRC */
+	{
+		MV_U8 crc = 0;
+		for (count = 0; count < ATA_SECTOR_SIZE; count++)
+			crc += ReadLogExtBuffer[count];
+
+		if (crc != 0) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut "
+				 "ATA Command failed due to wrong CRC checksum (%02x)\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, crc);
+			return MV_FALSE;
+		}
+	}
+	/* Swap to little endianess */
+	for (count = 0; count < ATA_SECTOR_SIZE_IN_WORDS; count++) {
+		/* CPU to little */
+		pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer[count] =
+		    MV_LE16_TO_CPU(pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer[count]);
+	}
+
+	for (count = 0; count < 3; count++) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " ReadLogExt: 0x%02x  0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", ReadLogExtBuffer[(count * 6) + 0],
+			 ReadLogExtBuffer[(count * 6) + 1], ReadLogExtBuffer[(count * 6) + 2],
+			 ReadLogExtBuffer[(count * 6) + 3], ReadLogExtBuffer[(count * 6) + 4],
+			 ReadLogExtBuffer[(count * 6) + 5]);
+	}
+	/* check NQ bit */
+	if (ReadLogExtBuffer[0] & MV_BIT7) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut: "
+			 "Error - NQ is set\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		return MV_FALSE;
+	}
+
+	if (_getHostTagByDeviceTag(pSataChannel,
+				   0x1F & ReadLogExtBuffer[0],
+				   pSataChannel->ErrorHandlingInfo.CurrPort, &tag) == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d %d: "
+			 "parseReadLogExtOutPut: "
+			 "Error - None Valid device tag (0x%02x)\n",
+			 pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber,
+			 pSataChannel->ErrorHandlingInfo.CurrPort, 0x1F & ReadLogExtBuffer[0]);
+		return MV_FALSE;
+	}
+	pCommandEntry = &pSataChannel->commandsQueue[tag];
+	if (pCommandEntry->isFreeEntry == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut: "
+			 "Error - No command with tag (0x%02x) has been issued\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, tag);
+		return MV_FALSE;
+	}
+	if (pCommandEntry->pCommandInfo->PMPort != pSataChannel->ErrorHandlingInfo.CurrPort) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut: "
+			 "Error - command PM Port (0x%02x) and CurrPort (0x%02x) doesn't match\n",
+			 pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber, pCommandEntry->pCommandInfo->PMPort,
+			 pSataChannel->ErrorHandlingInfo.CurrPort);
+		return MV_FALSE;
+	}
+	if (pCommandEntry->pCommandInfo->type != MV_QUEUED_COMMAND_TYPE_UDMA) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut: "
+			 "Error - command with tag (0x%02x) isn't UDMA command\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, tag);
+		return MV_FALSE;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: parseReadLogExtOutPut: "
+		 " command tag (0x%02x)\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, tag);
+	registerStruct.statusRegister = ReadLogExtBuffer[2];
+	registerStruct.deviceRegister = ReadLogExtBuffer[7];
+	registerStruct.errorRegister = ReadLogExtBuffer[3];
+	registerStruct.lbaLowRegister = (ReadLogExtBuffer[8] << 8) | ReadLogExtBuffer[4];
+	registerStruct.lbaMidRegister = (ReadLogExtBuffer[9] << 8) | ReadLogExtBuffer[5];
+	registerStruct.lbaHighRegister = (ReadLogExtBuffer[10] << 8) | ReadLogExtBuffer[6];
+	registerStruct.sectorCountRegister = (ReadLogExtBuffer[13] << 8) | ReadLogExtBuffer[12];
+
+	_printATARegs(&registerStruct);
+
+	pSataChannel->EdmaQueuedCommands--;
+	pCommandEntry->pCommandInfo->commandParams.udmaCommand.callBack(pSataChannel->mvSataAdapter,
+									pSataChannel->channelNumber,
+									MV_COMPLETION_TYPE_ERROR,
+									pCommandEntry->pCommandInfo->commandParams.
+									udmaCommand.commandId, 0x04, 0,
+									&registerStruct);
+	removeCommand(pSataChannel, pCommandEntry);
+	return MV_TRUE;
+}
+
+static MV_BOOLEAN _getHostTagByDeviceTag(MV_SATA_CHANNEL *pSataChannel,
+					 MV_U8 deviceTag, MV_U8 PMPort, MV_U8 *pHostTag)
+{
+	MV_QUEUED_COMMAND_ENTRY *pEntry = pSataChannel->commandsQueueHead;
+	while (pEntry != NULL) {
+		if (pEntry->isCommandInEdma == MV_TRUE) {
+			if ((pEntry->deviceTag == deviceTag) && (pEntry->pCommandInfo->PMPort == PMPort)) {
+				*pHostTag = pEntry->hostTag;
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "%d %d %d: _getHostTagByDeviceTag, command entry found, "
+					 "host tag = 0x%02x,  deviceTag(0x%02x)\n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, PMPort, *pHostTag, deviceTag);
+				return MV_TRUE;
+			}
+		} else {
+			/* stop once reached a command that has not been inserted into the
+			   EDMA since the next commands also must be outside the EDMA
+			 */
+			break;
+		}
+		pEntry = pEntry->next;
+	}
+	return MV_FALSE;
+}
+
+/* this function used for NCQ error handling, it's the callback function of the
+    ReadLogExt command with issued by adding command entry to the channel's
+    commands queue */
+static MV_BOOLEAN
+ReadLogExtCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
+		       MV_U8 channelNum,
+		       MV_COMPLETION_TYPE comp_type,
+		       MV_VOID_PTR commandId,
+		       MV_U16 responseFlags, MV_U32 timeStamp, MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+	MV_SATA_CHANNEL *pSataChannel = pSataAdapter->sataChannel[channelNum];
+
+	switch (comp_type) {
+	case MV_COMPLETION_TYPE_NORMAL:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " %d %d: ReadLogExtCompletionCB: Normal completion. Port 0x%02x\n",
+			 pSataAdapter->adapterId, channelNum, pSataChannel->ErrorHandlingInfo.CurrPort);
+		if (parseReadLogExtOutPut(pSataChannel) == MV_TRUE) {
+			/* Fix for 88SX60x1 FEr SATA#25 */
+			{
+				if (pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA == MV_TRUE) {
+					MV_U32 i;
+					MV_U8 ATAstatus;
+					_doSoftReset(pSataChannel);
+					for (i = 0; i < 31000; i++) {
+						ATAstatus = MV_REG_READ_BYTE(pSataAdapter->adapterIoBaseAddress,
+									     pSataChannel->eDmaRegsOffset +
+									     MV_ATA_DEVICE_STATUS_REG_OFFSET);
+						if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0)
+							break;
+
+						mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 1000);
+					}
+				}
+			}
+			pSataChannel->ErrorHandlingInfo.CurrPort++;
+			handlePortError(pSataChannel);
+		}
+		break;
+	default:
+		/* when ReadLogExt fails or parseReaDLogExtOutPut fails do nothing */
+		/* the higher layers will not have the queued commands completed so it */
+		/* should recover this situation by it's timeout error recovery */
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " %d %d: ReadLogExtCompletionCB: Bad completion. Port 0x%02x\n",
+			 pSataAdapter->adapterId, channelNum, pSataChannel->ErrorHandlingInfo.CurrPort);
+		_printATARegs(registerStruct);
+		_dumpSataRegs(pSataAdapter, channelNum);
+		break;
+	}
+	return MV_TRUE;
+}
+
+/* this function used for NCQ error handling, it "allocates" command entry of the
+    ReadLogExt command and data buffer used for that command from the EDMA
+    requests queue which is not used meanwhile since the EDMA disabled*/
+static MV_VOID setReadLogExtCmndPointers(MV_SATA_CHANNEL *pSataChannel)
+{
+	struct ReadLogExtBuffers {
+		MV_QUEUED_COMMAND_ENTRY entry;
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+		MV_QUEUE_COMMAND_INFO commandInfo;
+#endif
+		MV_U16 pioBuffer[ATA_SECTOR_SIZE_IN_WORDS];
+	};
+	/* EDMA is not active, so we use the request queue buffer for Read Log Ext
+	   command data */
+	struct ReadLogExtBuffers *pReadLogExtBuffers = (struct ReadLogExtBuffers *)pSataChannel->requestQueue;
+	pSataChannel->ErrorHandlingInfo.pReadLogExtEntry = &pReadLogExtBuffers->entry;
+	pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer = pReadLogExtBuffers->pioBuffer;
+
+#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+	pSataChannel->ErrorHandlingInfo.pReadLogExtEntry->pCommandInfo = &pReadLogExtBuffers->commandInfo;
+#else
+	pSataChannel->ErrorHandlingInfo.pReadLogExtEntry->pCommandInfo = &pReadLogExtBuffers->entry.commandInfo;
+#endif
+}
+
+/* this function used for NCQ error handling, it sets the ReadLogExt command
+    entry, then issues the command to the CuttPort*/
+static MV_VOID insertReadLogExtCmnd(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_QUEUED_COMMAND_ENTRY *pEntry = pSataChannel->ErrorHandlingInfo.pReadLogExtEntry;
+	MV_NONE_UDMA_COMMAND_PARAMS *pReadLogExtPIOParams = &pEntry->pCommandInfo->commandParams.NoneUdmaCommand;
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 " %d %d: insertReadLogExtCmnd: Port 0x%02x\n",
+		 pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber, pSataChannel->ErrorHandlingInfo.CurrPort);
+
+	pReadLogExtPIOParams->bufPtr = pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer;
+	pReadLogExtPIOParams->callBack = ReadLogExtCompletionCB;
+	pReadLogExtPIOParams->command = MV_ATA_COMMAND_READ_LOG_EXT;
+	pReadLogExtPIOParams->commandId = NULL;
+	pReadLogExtPIOParams->count = ATA_SECTOR_SIZE_IN_WORDS;
+	pReadLogExtPIOParams->device = 0;
+	pReadLogExtPIOParams->features = 0;
+	pReadLogExtPIOParams->isEXT = MV_TRUE;
+	pReadLogExtPIOParams->lbaHigh = 0;
+	pReadLogExtPIOParams->lbaLow = 0x10;
+	pReadLogExtPIOParams->lbaMid = 0;
+	pReadLogExtPIOParams->protocolType = MV_NON_UDMA_PROTOCOL_PIO_DATA_IN;
+	pReadLogExtPIOParams->sectorCount = 1;
+	pEntry->pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
+	pEntry->pCommandInfo->PMPort = pSataChannel->ErrorHandlingInfo.CurrPort;
+	pEntry->isCommandInEdma = MV_FALSE;
+	pEntry->commandAborted = MV_FALSE;
+	pEntry->isFreeEntry = MV_FALSE;
+	pEntry->hostTag = 0xFF;
+	pEntry->deviceTag = 0xFF;
+	commandsQueueAddHead(pSataChannel, pEntry);
+	if (pSataChannel->PMSupported == MV_TRUE)
+		_setActivePMPort(pSataChannel, pEntry->pCommandInfo->PMPort);
+
+	/* Fix for 88SX60x1 FEr SATA#25 */
+	if (pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA == MV_TRUE) {
+		MV_U32 FISBuffer[5];
+		FISBuffer[0] = ((MV_ATA_COMMAND_READ_LOG_EXT << 16) & 0xFF0000) | MV_BIT15 | 0x27;
+		FISBuffer[1] = 0x10;
+		FISBuffer[2] = 0;
+		FISBuffer[3] = 1;
+		FISBuffer[4] = 0;
+
+		sendVendorUniqueFIS(pSataChannel->mvSataAdapter, pSataChannel->channelNumber, FISBuffer, 5);
+
+		return;
+	}
+
+	if (sendNoneUdmaCommand(pSataChannel, pEntry) == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: Failed to "
+			 "Issue ReadLogExt PIO command\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		completePIOCommand(pSataChannel, pSataChannel->commandsQueueHead, MV_TRUE);
+	}
+}
+
+/* this function used for NCQ error handling, it checks the comming port
+    that experienced NCQ device error starting from CurrPort, if no port found,
+    it sets the NCQ error handling state to the Idle state and re-queues the
+    outstanding commands*/
+static MV_VOID handlePortError(MV_SATA_CHANNEL *pSataChannel)
+{
+	while (pSataChannel->ErrorHandlingInfo.CurrPort <= MV_SATA_PM_MAX_PORTS) {
+		if (((MV_U16) (1 << pSataChannel->ErrorHandlingInfo.CurrPort)) & pSataChannel->ErrorHandlingInfo.
+		    PortsWithErrors) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d: handlePortError: Device Error found on Port " "0x%02x\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber,
+				 pSataChannel->ErrorHandlingInfo.CurrPort);
+			break;
+		}
+		pSataChannel->ErrorHandlingInfo.CurrPort++;
+	}
+	if (pSataChannel->ErrorHandlingInfo.CurrPort > MV_SATA_PM_MAX_PORTS) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " %d %d: handlePortError: Finished All erring ports\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_IDLE;
+		pSataChannel->ErrorHandlingInfo.PortsWithErrors = 0;
+		_resetEdmaQPointers(pSataChannel);
+		_insertQCommandsIntoEdma(pSataChannel);
+		return;
+	}
+	insertReadLogExtCmnd(pSataChannel);
+}
+
+static MV_VOID softResetErringPorts(MV_SATA_CHANNEL *pSataChannel)
+{
+	while (pSataChannel->ErrorHandlingInfo.CurrPort <= MV_SATA_PM_MAX_PORTS) {
+		if (((MV_U16) (1 << pSataChannel->ErrorHandlingInfo.CurrPort)) & pSataChannel->ErrorHandlingInfo.
+		    PortsWithErrors) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d: softResetErringPorts: Device Error found on Port " "0x%02x\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber,
+				 pSataChannel->ErrorHandlingInfo.CurrPort);
+			if (pSataChannel->PMSupported == MV_TRUE)
+				_setActivePMPort(pSataChannel, pSataChannel->ErrorHandlingInfo.CurrPort);
+			_doSoftReset(pSataChannel);
+		}
+		pSataChannel->ErrorHandlingInfo.CurrPort++;
+	}
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 " %d %d: softResetErringPorts: Finished All erring ports\n",
+		 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+	pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_IDLE;
+	pSataChannel->ErrorHandlingInfo.PortsWithErrors = 0;
+	_resetEdmaQPointers(pSataChannel);
+	_insertQCommandsIntoEdma(pSataChannel);
+	return;
+}
+
+static MV_BOOLEAN sendNoneUdmaCommand(MV_SATA_CHANNEL *pSataChannel, MV_QUEUED_COMMAND_ENTRY *pCommandEntry)
+{
+	MV_NONE_UDMA_COMMAND_PARAMS *pParams = &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand;
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset;
+	MV_U8 ATAstatus;
+	unsigned int i;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+		 " %d %d Issue NON UDMA command: protocol(%d) buff %p , words %x ,"
+		 " features %x , sector count %x , lba %x.%x.%x device %x "
+		 "command=%x\n", pSataChannel->mvSataAdapter->adapterId,
+		 pSataChannel->channelNumber, pParams->protocolType,
+		 pParams->bufPtr, pParams->count,
+		 pParams->features, pParams->sectorCount,
+		 pParams->lbaLow, pParams->lbaMid, pParams->lbaHigh, pParams->device, pParams->command);
+
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+	if ((ATAstatus & (MV_ATA_READY_STATUS | MV_ATA_BUSY_STATUS)) != MV_ATA_READY_STATUS) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: storage drive is not"
+			 " ready, ATA STATUS=0x%02x\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ATAstatus);
+		return MV_FALSE;
+	}
+
+	if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET) {
+		if (pParams->protocolType == MV_NON_UDMA_PROTOCOL_PACKET_DMA)
+			MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_FEATURES_REG_OFFSET, MV_BIT0);
+		else
+			MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_FEATURES_REG_OFFSET, 0);
+
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, 0);
+
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, 0);
+
+		/* set byte count limit to 8KB (0x2000) */
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, 0x00);
+
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, 0x20);
+
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_HEAD_REG_OFFSET, 0);
+		MV_CPU_WRITE_BUFFER_FLUSH();
+
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_COMMAND_REG_OFFSET, MV_ATA_COMMAND_PACKET);
+
+	} else {
+		if (pParams->isEXT == MV_TRUE) {
+			MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+					  MV_ATA_DEVICE_FEATURES_REG_OFFSET, (pParams->features & 0xff00) >> 8);
+			MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+					  MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, (pParams->sectorCount & 0xff00) >> 8);
+			MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+					  MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, (pParams->lbaLow & 0xff00) >> 8);
+			MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+					  MV_ATA_DEVICE_LBA_MID_REG_OFFSET, (pParams->lbaMid & 0xff00) >> 8);
+			MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+					  MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, (pParams->lbaHigh & 0xff00) >> 8);
+		} else {
+			if ((pParams->features & 0xff00) ||
+			    (pParams->sectorCount & 0xff00) ||
+			    (pParams->lbaLow & 0xff00) || (pParams->lbaMid & 0xff00) || (pParams->lbaHigh & 0xff00)) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_NON_UDMA_COMMAND,
+					 " %d %d :in Issue NON UDMA command:"
+					 " bits[15:8] of register values should be reserved"
+					 " Features 0x%02x, SectorCount 0x%02x, LBA Low 0x%02x,"
+					 " LBA Mid 0x%02x, LBA High 0x%02x\n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, pParams->features,
+					 pParams->sectorCount, pParams->lbaLow, pParams->lbaMid, pParams->lbaHigh);
+				return MV_FALSE;
+			}
+		}
+
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_FEATURES_REG_OFFSET, pParams->features & 0xff);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, pParams->sectorCount & 0xff);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, pParams->lbaLow & 0xff);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_LBA_MID_REG_OFFSET, pParams->lbaMid & 0xff);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, pParams->lbaHigh & 0xff);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_HEAD_REG_OFFSET, pParams->device);
+
+		MV_CPU_WRITE_BUFFER_FLUSH();
+
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_COMMAND_REG_OFFSET, pParams->command);
+	}
+	if ((pParams->protocolType == MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT) ||
+	    (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET)) {
+		MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_ALTERNATE_REG_OFFSET);
+
+		/* Wait for the command to complete */
+		if (waitWhileStorageDevIsBusy(pSataChannel->mvSataAdapter,
+					      ioBaseAddr, eDmaRegsOffset, 10000, 100) == MV_FALSE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: in Issue PIO "
+				 "DATA-OUT command: disk not ready.\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+			return MV_FALSE;
+		}
+
+		if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+
+			if (waitForDRQ(pSataChannel->mvSataAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000)
+			    == MV_FALSE) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: DRQ bit in ATA STATUS"
+					 " register is not set\n", pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber);
+				return MV_FALSE;
+			}
+		}
+		/* Check the status register on DATA request commands */
+		ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+		if ((ATAstatus & (MV_ATA_DATA_REQUEST_STATUS | MV_ATA_BUSY_STATUS | MV_ATA_ERROR_STATUS)) !=
+		    MV_ATA_DATA_REQUEST_STATUS) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: in Issue PIO "
+				 "DATA-OUT command: Bad ATA STATUS:0x%02x.\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ATAstatus);
+			return MV_FALSE;
+		}
+
+		if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+			/* Perform a dummy read */
+			MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+			mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 1);
+		}
+#ifdef MV_SUPPORT_ATAPI
+		if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET) {
+			MV_PACKET_COMMAND_PARAMS *pParams = &pCommandEntry->pCommandInfo->commandParams.packetCommand;
+			for (i = 0; i < pParams->cdb_len; i++) {
+				MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset +
+						  MV_ATA_DEVICE_PIO_DATA_REG_OFFSET,
+						  MV_CPU_TO_LE16(pParams->cdb_buffer[i]));
+			}
+			for (; i < 6; i++)
+				MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, 0);
+
+			MV_CPU_WRITE_BUFFER_FLUSH();
+			pSataChannel->waitForBMDMA = MV_FALSE;
+			if (pParams->protocolType == MV_NON_UDMA_PROTOCOL_PACKET_DMA) {
+				activateBMDmaMode(pSataChannel->mvSataAdapter,
+						  pSataChannel->channelNumber,
+						  pParams->prdHighAddr,
+						  pParams->prdLowAddr,
+						  (pParams->flags & MV_BIT0) ? MV_UDMA_TYPE_WRITE : MV_UDMA_TYPE_READ);
+
+			}
+			return MV_TRUE;
+		}
+#endif
+		for (i = 0; i < ATA_SECTOR_SIZE_IN_WORDS; i++) {
+			MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset +
+					  MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, *pParams->bufPtr++);
+			MV_CPU_WRITE_BUFFER_FLUSH();
+		}
+		pParams->count -= ATA_SECTOR_SIZE_IN_WORDS;
+#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG
+
+		/* for Write long only */
+		if (pParams->count == 4) {
+			if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+				/* Perform a dummy read */
+				MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+				mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 1);
+			}
+			if (waitWhileStorageDevIsBusy(pSataChannel->mvSataAdapter,
+						      ioBaseAddr, eDmaRegsOffset, 50000, 100) == MV_FALSE) {
+				return MV_FALSE;
+			}
+			if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+				if (waitForDRQ(pSataChannel->mvSataAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100)
+				    == MV_FALSE) {
+					return MV_FALSE;
+				}
+			}
+			for (i = 0; i < 4; i++) {
+				MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset +
+						  MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, *pParams->bufPtr++);
+				MV_CPU_WRITE_BUFFER_FLUSH();
+
+				ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
+							     MV_ATA_DEVICE_STATUS_REG_OFFSET);
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Write Long ECC data"
+					 " xfered. ATA STATUS:0x%02x.\n",
+					 pSataChannel->mvSataAdapter->adapterId,
+					 pSataChannel->channelNumber, ATAstatus);
+			}
+			pParams->count -= 4;
+		}
+#endif /*MV_SATA_SUPPORT_READ_WRITE_LONG */
+	}
+	return MV_TRUE;
+}
+
+/*   SATA Core API functions        */
+
+/*******************************************************************************
+* mvSataInitAdapter - initialize MV88SX50XX adapter
+*
+* DESCRIPTION:
+*   this function initializes glabal registers that concerns PCI access
+*   and Interrupts.
+*
+* INPUT:
+*   *pAdapter   - pointer to the adapter data structure.
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+*
+* COMMENTS:
+*   The adapter will not be able yet to generate interrupts
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataInitAdapter(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U8 sataUnit;
+	MV_U8 channelIndex;
+	MV_U32 regVal;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "    : mvSataInitAdapter"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+
+	if (mvOsSemInit(&pAdapter->semaphore) == MV_FALSE)
+		return MV_FALSE;
+
+	if (mvOsSemInit(&pAdapter->interruptsMaskSem) == MV_FALSE)
+		return MV_FALSE;
+
+#ifdef MV_SATA_IO_GRANULARITY
+	if (mvOsSemInit(&pAdapter->iogSemaphore) == MV_FALSE)
+		return MV_FALSE;
+#endif
+
+	if (pAdapter->mvSataEventNotify == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d  : Bad pointer for "
+			 "mvSataEventNotify function\n", pAdapter->adapterId);
+		return MV_FALSE;
+	}
+
+	/* Initialize the hardware workarounds to false, and to 8 channels */
+	pAdapter->chipIs50XXB0 = MV_FALSE;
+	pAdapter->chipIs50XXB2 = MV_FALSE;
+	pAdapter->chipIs60X1B2 = MV_FALSE;
+	pAdapter->chipIs60X1C0 = MV_FALSE;
+	pAdapter->chipIs62X1Z0 = MV_FALSE;
+	pAdapter->chipIs65XXZ0 = MV_FALSE;
+	pAdapter->numberOfChannels = MV_SATA_CHANNELS_NUM;
+	pAdapter->numberOfUnits = MV_SATA_UNITS_NUM;
+	pAdapter->portsPerUnit = MV_SATA_PORT_PER_UNIT;
+	pAdapter->hostInterface = MV_HOST_IF_PCI;
+	pAdapter->mainMaskOffset = MV_MAIN_INTERRUPT_MASK_REG_OFFSET;
+	pAdapter->mainCauseOffset = MV_MAIN_INTERRUPT_CAUSE_REG_OFFSET;
+	switch (pAdapter->pciConfigDeviceId) {
+	case MV_SATA_DEVICE_ID_5080:
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_I;
+		switch (pAdapter->pciConfigRevisionId) {
+		case 0x1:
+			pAdapter->chipIs50XXB0 = MV_TRUE;
+			break;
+		case 0x3:
+			pAdapter->chipIs50XXB2 = MV_TRUE;
+			break;
+		default:
+			if (pAdapter->pciConfigRevisionId > 0x3) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d : Warning: Future revision ID %02x for Device "
+					 "ID %02x. Implementing latest workarounds\n",
+					 pAdapter->adapterId, pAdapter->pciConfigRevisionId,
+					 pAdapter->pciConfigDeviceId);
+				pAdapter->chipIs50XXB2 = MV_TRUE;
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d : Bad revision ID %02x for Device ID %02x\n",
+					 pAdapter->adapterId, pAdapter->pciConfigRevisionId,
+					 pAdapter->pciConfigDeviceId);
+				return MV_FALSE;
+			}
+		}
+		break;
+	case MV_SATA_DEVICE_ID_5041:
+	case MV_SATA_DEVICE_ID_5040:
+		pAdapter->numberOfChannels = MV_SATA_PORT_PER_UNIT;
+		pAdapter->numberOfUnits = 1;
+	case MV_SATA_DEVICE_ID_5081:
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_I;
+		switch (pAdapter->pciConfigRevisionId) {
+		case 0x0:
+			pAdapter->chipIs50XXB0 = MV_TRUE;
+			break;
+		case 0x3:
+			pAdapter->chipIs50XXB2 = MV_TRUE;
+			break;
+		default:
+			if (pAdapter->pciConfigRevisionId > 0x3) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Warning: Future revis"
+					 "ion ID %02x. Implementing latest workarounds\n",
+					 pAdapter->adapterId, pAdapter->pciConfigRevisionId);
+				pAdapter->chipIs50XXB2 = MV_TRUE;
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Bad revisi"
+					 "on ID %02x\n", pAdapter->adapterId, pAdapter->pciConfigRevisionId);
+				return MV_FALSE;
+			}
+		}
+		break;
+	case MV_SATA_DEVICE_ID_6041:
+		pAdapter->numberOfChannels = MV_SATA_PORT_PER_UNIT;
+		pAdapter->numberOfUnits = 1;
+	case MV_SATA_DEVICE_ID_6081:
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_II;
+		switch (pAdapter->pciConfigRevisionId) {
+		case 0x7:	/*B2 */
+			pAdapter->chipIs60X1B2 = MV_TRUE;
+			break;
+		case 0x9:	/*C0 */
+			pAdapter->chipIs60X1C0 = MV_TRUE;
+			break;
+		default:
+			if (pAdapter->pciConfigRevisionId > 0x9) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Warning:"
+					 " Future revision ID %02x. Implementing latest "
+					 "workarounds\n", pAdapter->adapterId, pAdapter->pciConfigRevisionId);
+				pAdapter->chipIs60X1C0 = MV_TRUE;
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d : Device %02x Bad revision ID %02x\n",
+					 pAdapter->adapterId,
+					 pAdapter->pciConfigDeviceId, pAdapter->pciConfigRevisionId);
+				return MV_FALSE;
+			}
+		}
+		break;
+	case MV_SATA_DEVICE_ID_7042:
+		pAdapter->hostInterface = MV_HOST_IF_PEX;
+	case MV_SATA_DEVICE_ID_6042:
+		pAdapter->numberOfChannels = MV_SATA_PORT_PER_UNIT;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		switch (pAdapter->pciConfigRevisionId) {
+		case 0x2:	/*B0 */
+			pAdapter->chipIs60X1C0 = MV_TRUE;
+			break;
+		default:
+			if (pAdapter->pciConfigRevisionId > 0x2) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Warning:"
+					 " Future revision ID %02x for Device %02x."
+					 " Implementing latest workarounds\n",
+					 pAdapter->adapterId,
+					 pAdapter->pciConfigRevisionId, pAdapter->pciConfigDeviceId);
+				pAdapter->chipIs60X1C0 = MV_TRUE;
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 " %d : Device %02x Bad revision ID %02x\n",
+					 pAdapter->adapterId,
+					 pAdapter->pciConfigDeviceId, pAdapter->pciConfigRevisionId);
+				return MV_FALSE;
+			}
+		}
+		break;
+
+	case MV_SATA_DEVICE_ID_5182:
+		pAdapter->numberOfChannels = MV_SATA_5182_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_5182_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->chipIs60X1C0 = MV_TRUE;
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;	/*the iobaseaddress is 0x60000 */
+		pAdapter->mainCauseOffset = 0x20020;
+		break;
+
+	case MV_SATA_DEVICE_ID_5082:
+		pAdapter->numberOfChannels = MV_SATA_5082_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_5082_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->chipIs60X1C0 = MV_TRUE;
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;	/*the iobaseaddress is 0x60000 */
+		pAdapter->mainCauseOffset = 0x20020;
+		mvSataChannelPhyShutdown(pAdapter, 1);
+		break;
+
+	case MV_SATA_DEVICE_ID_6082:
+		pAdapter->numberOfChannels = MV_SATA_6082_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_6082_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->chipIs60X1C0 = MV_TRUE;
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;	/*the iobaseaddress is 0x40000 */
+		pAdapter->mainCauseOffset = 0x20020;
+		break;
+
+	case MV_SATA_DEVICE_ID_6490:
+		pAdapter->numberOfChannels = MV_SATA_6490_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_6490_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->chipIs60X1C0 = MV_TRUE;
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+
+		/* enable swap DMA Data, EDMA descriptors and PRD tables to keep the data layout
+		 * as in the PCI adapters
+		 */
+		_clearRegBits(pAdapter->adapterIoBaseAddress,
+			      MV_SATAHC_0_REGS_BASE_OFFSET, MV_BIT10 | MV_BIT9 | MV_BIT8);
+
+		break;
+	case MV_SATA_DEVICE_ID_78XX0:
+	case MV_SATA_DEVICE_ID_78100:
+	case MV_SATA_DEVICE_ID_78200:
+		pAdapter->numberOfChannels = MV_SATA_78XX0_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_78XX0_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs62X1Z0 = MV_TRUE;
+		break;
+	case MV_SATA_DEVICE_ID_76100:
+		pAdapter->numberOfChannels = MV_SATA_76100_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_76100_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs62X1Z0 = MV_TRUE;
+		break;
+	case MV_SATA_DEVICE_ID_6323:
+		pAdapter->numberOfChannels = MV_SATA_6323_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_6323_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs62X1Z0 = MV_TRUE;
+		break;
+
+	case MV_SATA_DEVICE_ID_6281:
+		pAdapter->numberOfChannels = MV_SATA_6281_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_6281_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs62X1Z0 = MV_TRUE;
+		break;
+
+	case MV_SATA_DEVICE_ID_6282:
+		pAdapter->numberOfChannels = MV_SATA_6282_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_6282_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs62X1Z0 = MV_TRUE;
+		break;
+
+	case MV_SATA_DEVICE_ID_6192:
+		pAdapter->numberOfChannels = MV_SATA_6192_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_6192_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs62X1Z0 = MV_TRUE;
+		break;
+
+	case MV_SATA_DEVICE_ID_6190:
+		pAdapter->numberOfChannels = MV_SATA_6190_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_6190_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs62X1Z0 = MV_TRUE;
+		break;
+
+	case MV_SATA_DEVICE_ID_6781:
+		pAdapter->numberOfChannels = MV_SATA_6781_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_6781_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs62X1Z0 = MV_TRUE;
+		break;
+
+	case MV_SATA_DEVICE_ID_6550:
+	case MV_SATA_DEVICE_ID_6560:
+		pAdapter->numberOfChannels = MV_SATA_6781_PORT_NUM;
+		pAdapter->numberOfUnits = 1;
+		pAdapter->portsPerUnit = MV_SATA_65XX_PORT_NUM;
+		pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE;
+		/*The integrated sata core chip based on 60x1 C0 */
+		pAdapter->hostInterface = MV_HOST_IF_INTEGRATED;
+		pAdapter->mainMaskOffset = 0x20024;
+		pAdapter->mainCauseOffset = 0x20020;
+		pAdapter->chipIs65XXZ0 = MV_TRUE;
+		break;
+
+	default:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Bad device ID"
+			 " 0x%04x\n", pAdapter->adapterId, pAdapter->pciConfigDeviceId);
+		return MV_FALSE;
+	}
+
+	/* Clear main mask register to prevent adapter from generating interrupts */
+	pAdapter->mainMask = 0;
+	pAdapter->interruptsAreMasked = MV_TRUE;
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, pAdapter->mainMask);
+
+	/*
+	 * Save the PRE and AMP in the adapter. Also set staggared spin up to be
+	 * disabled on default (60x1 only).
+	 */
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d : Saving PRE and AMP values\n", pAdapter->adapterId);
+	for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) {
+		MV_U32 PHYModeRegister;
+		pAdapter->staggaredSpinup[channelIndex] = MV_FALSE;
+		pAdapter->ifSpeed[channelIndex] = MV_SATA_IF_SPEED_NO_LIMIT;
+		pAdapter->ifPowerState[channelIndex] = MV_SATA_IF_POWER_PHY_READY;
+		pAdapter->limitInterfaceSpeed[channelIndex] = MV_FALSE;
+		if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+			PHYModeRegister = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+							    MV_SATAHC_REGS_BASE_OFFSET((channelIndex & MV_BIT2) >> 2) +
+							    MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(channelIndex &
+													 (MV_BIT0 |
+													  MV_BIT1)));
+			pAdapter->signalAmps[channelIndex] =
+			    (MV_U8) ((PHYModeRegister & MV_SATA_I_PHY_MODE_AMP_MASK) >> MV_SATA_I_PHY_MODE_AMP_OFFSET);
+			pAdapter->pre[channelIndex] =
+			    (MV_U8) ((PHYModeRegister & MV_SATA_I_PHY_MODE_PRE_MASK) >> MV_SATA_I_PHY_MODE_PRE_OFFSET);
+		}
+		if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+			/*
+			 * Check if TWSI serial ROM initialization was triggered.
+			 * If so, then PRE/AMP configuration probably are set after
+			 * reset by serial ROM. If not then override the PRE/AMP
+			 * values.
+			 */
+			if ((pAdapter->hostInterface != MV_HOST_IF_INTEGRATED) &&
+			    ((MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_RESET_CONFIG_REG_OFFSET))
+			     & MV_RESET_CONFIG_TWSI_INIT_MASK)) {
+
+				MV_U32 phyMode2Offset = getEdmaRegOffset(channelIndex) +
+				    MV_SATA_II_PHY_MODE_2_REG_OFFSET;
+				/* Make sure EDMA is off */
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   getEdmaRegOffset(channelIndex) +
+						   MV_EDMA_COMMAND_REG_OFFSET, MV_EDMA_COMMAND_DISABLE_MASK);
+				MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						  getEdmaRegOffset(channelIndex) + MV_EDMA_COMMAND_REG_OFFSET);
+				regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, phyMode2Offset);
+				pAdapter->signalAmps[channelIndex] =
+				    (MV_U8) ((regVal & MV_SATA_II_PHY_MODE_2_AMP_MASK) >>
+					     MV_SATA_II_PHY_MODE_2_AMP_OFFSET);
+				pAdapter->pre[channelIndex] =
+				    (MV_U8) ((regVal & MV_SATA_II_PHY_MODE_2_PRE_MASK) >>
+					     MV_SATA_II_PHY_MODE_2_PRE_OFFSET);
+			} else {
+				pAdapter->signalAmps[channelIndex] = 0x7;
+				pAdapter->pre[channelIndex] = 0x1;
+			}
+		}
+	}
+#ifndef MV_NO_SW_RESET_FOR_THE_ADAPTER
+	/* Revert the registers to it's default value (software reset) */
+	revertSataHCRegs(pAdapter);
+
+	if (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)
+		revertFlashInterfaceRegs(pAdapter);
+
+	if (pAdapter->hostInterface == MV_HOST_IF_PEX)
+		revertPEXInterfaceRegs(pAdapter);
+	else if (pAdapter->hostInterface == MV_HOST_IF_PCI)
+		revertPCIInterfaceRegs(pAdapter);
+#endif
+
+	/* Enable the SATA LEDs if the silicon revision is B0 */
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d : Enabling SATA LEDS\n", pAdapter->adapterId);
+		/* Enable the SATA leds */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET, 0x0);
+		if (pAdapter->chipIs50XXB2 == MV_TRUE) {
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
+			for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) {
+				if (mvSataIsStorageDeviceConnected(pAdapter, channelIndex, NULL) == MV_FALSE)
+					regVal |= (MV_BIT8 << channelIndex);
+			}
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET, regVal);
+		}
+		/* disable Flash controller clock */
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
+
+		regVal &= ~(MV_BIT0);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, regVal);
+	}
+
+	/* Enable the SATA LEDs for 88SX60X1 devices */
+	if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d : Enabling SATA LEDS\n", pAdapter->adapterId);
+		/* Enable the SATA leds */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_FLASH_GPIO_PORT_CONTROL_OFFSET, 0x00000060);
+
+	}
+
+	/* Check if working in PCI-X mode, then disable all conventional PCI */
+	/* features */
+	if (pAdapter->hostInterface == MV_HOST_IF_PCI) {
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, MV_PCI_REGS_OFFSET + MV_PCI_MODE_REG_OFFSET);
+		if (((regVal & MV_PCI_MODE_MASK) >> MV_PCI_MODE_OFFSET) != 0) {	/* PCI-X */
+			if (pAdapter->pciCommand & MV_PCI_COMMAND_PCI_CONVENTIONAL_ONLY) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : disable pci conventio"
+					 "nal features when working in PCI-X. pciCommand origin"
+					 "al value:0x%08x. new value: 0x%08x.\n",
+					 pAdapter->adapterId,
+					 pAdapter->pciCommand, pAdapter->pciCommand &
+					 (~MV_PCI_COMMAND_PCI_CONVENTIONAL_ONLY));
+				pAdapter->pciCommand &= ~MV_PCI_COMMAND_PCI_CONVENTIONAL_ONLY;
+			}
+			if ((pAdapter->chipIs50XXB0 == MV_TRUE) ||
+			    (pAdapter->chipIs50XXB2 == MV_TRUE) || (pAdapter->chipIs60X1B2 == MV_TRUE)) {
+				/* Fix for 88SX50xx FEr PCI#1 */
+				/* Fix for 88SX60x1 FEr PCI#7 */
+				if (pAdapter->pciCommand & MV_PCI_MWRITE_COMBINE_BIT) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d  : PCI-X Master"
+						 " Write combine enable rejected\n", pAdapter->adapterId);
+					pAdapter->pciCommand &= ~MV_PCI_MWRITE_COMBINE_BIT;
+				}
+			}
+		} else {
+			if ((pAdapter->chipIs50XXB0 == MV_TRUE) || (pAdapter->chipIs50XXB2 == MV_TRUE)) {
+				/* Fix for 88SX50xx FEr PCI#2 */
+				if (pAdapter->pciCommand & MV_PCI_MWRITE_COMBINE_BIT) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d  : PCI Master"
+						 " Write combine enable rejected\n", pAdapter->adapterId);
+					pAdapter->pciCommand &= ~MV_PCI_MWRITE_COMBINE_BIT;
+				}
+				if (pAdapter->pciCommand & MV_PCI_MREAD_COMBINE_BIT) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d  : PCI Master"
+						 " Read combine enable rejected\n", pAdapter->adapterId);
+					pAdapter->pciCommand &= ~MV_PCI_MREAD_COMBINE_BIT;
+				}
+			}
+		}
+	}
+#if 0
+	/* Fix for 88SX60x1 FEr SATA#8 */
+	for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) {
+		if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+			/* Fix for 88SX60x1 FEr SATA#8 */
+			/* according to the spec, bits [31:12] must be set to 0x009B1 */
+			regVal &= 0x00000FFF;
+			/* regVal |= MV_BIT12; */
+			regVal |= 0x009B1000;
+
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+			/* _channelHardReset(pAdapter, channelIndex); */
+		}
+
+		_fixPhyParams(pAdapter, channelIndex);
+	}
+#endif
+	if (pAdapter->hostInterface == MV_HOST_IF_PCI) {
+
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_COMMAND_REG_OFFSET, pAdapter->pciCommand);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_SERR_MASK_REG_OFFSET, pAdapter->pciSerrMask);
+
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_INTERRUPT_MASK_REG_OFFSET, pAdapter->pciInterruptMask);
+	} else if (pAdapter->hostInterface == MV_HOST_IF_PEX) {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_PCI_REGS_OFFSET + MV_PCI_E_INTERRUPT_MASK_REG_OFFSET, MV_PCI_E_ERROR_MASK_VALUE);
+	}
+	for (sataUnit = 0; sataUnit < pAdapter->numberOfUnits; sataUnit++) {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATAHC_INT_COAL_THRE_REG_OFFSET, pAdapter->intCoalThre[sataUnit]);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATAHC_INT_TIME_THRE_REG_OFFSET, pAdapter->intTimeThre[sataUnit]);
+
+	}
+	if (pAdapter->hostInterface == MV_HOST_IF_INTEGRATED)
+		pAdapter->mainMask = MV_BIT8 | MV_BIT2 | MV_BIT0;
+	else
+		pAdapter->mainMask = MV_MAIN_INTERRUPT_MASK_ENABLE_ALL;
+
+	pAdapter->interruptsScheme = MV_SATA_INTERRUPT_HANDLING_IN_ISR;
+
+	for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++)
+		unmaskEdmaInterrupts(pAdapter, channelIndex);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataShutDownAdapter - Shuts down adapter.
+*
+* DESCRIPTION: Shuts down a specific 88SX50xx adapter.
+*
+* INPUT:
+*   *pAdapter   - pointer to the adapter data structure.
+*
+* OUTPUT:
+*   None.
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE on failure
+*
+* COMMENTS:
+*   None.
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataShutdownAdapter(MV_SATA_ADAPTER *pAdapter)
+{
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataShutdownAdapter Failed, Bad adapter data structure " "pointer\n");
+		return MV_FALSE;
+	}
+	pAdapter->interruptsAreMasked = MV_TRUE;
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, 0);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataReadReg - return the value of register.
+*
+* DESCRIPTION:
+*   return the value of a register, which have the offset regOffset, in a
+*   MV88SX50XX adapter.
+*   Note that if reading from storage device's internal registers and EDMA
+*   is enabled, then the read transaction will never complete and possibly
+*   cause system hang.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*       regOffset   - offset of the register
+*
+* RETURN:
+*   the register value in 32 bit.
+* COMMENTS:
+*   NONE
+*
+*******************************************************************************/
+MV_U32 mvSataReadReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset)
+{
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataReadReg Failed,"
+			 " Bad adapter data structure pointer\n");
+		return 0;
+	}
+
+	return MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, regOffset);
+}
+
+/*******************************************************************************
+* mvSataWriteReg - return the value of register.
+*
+* DESCRIPTION:
+*   write the regValue to a register, which have the offset regOffset, in a
+*   MV88SX50XX adapter.
+*   Note that if writing to storage device's internal registers and EDMA
+*   is enabled, then the write transaction will never complete and possibly
+*   cause system hang.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*       regOffset   - offset of the register
+*   regValue    - the value to write to the register
+*
+* RETURN:
+*   None.
+* COMMENTS:
+*   for 8 or 16 bit registers the low bits of the regValue should hold the
+*   requested value to be written.
+*
+*******************************************************************************/
+MV_VOID mvSataWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset, MV_U32 regValue)
+{
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataWriteReg Failed,"
+			 " Bad adapter data structure pointer\n");
+		return;
+	}
+
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, regOffset, regValue);
+}
+
+/*******************************************************************************
+* mvSataConfigureChannel - configure Sata channel
+*
+*
+* DESCRIPTION:
+*   this function configures SATA channel by resetting the low level fields
+*   of the channel data structure and configures EDMA regs accourdingly
+*
+* INPUT:
+*   pAdapter   - pointer to the MV88SX50XX adapter data structure
+*   channelIndex    - the index of the channel where the response received
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+*
+* COMMENTS:
+*   None.
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataConfigureChannel(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BOOLEAN result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataConfigureChannel"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataConfigureChann"
+			 "el Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	if (pAdapter->numberOfChannels <= channelIndex) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataConfigureChann"
+			 "el Failed - requsted to configure a non-valid channel\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	pSataChannel->eDmaRegsOffset = getEdmaRegOffset(channelIndex);
+	pSataChannel->mvSataAdapter = pAdapter;
+
+	if (mvOsSemInit(&pSataChannel->semaphore) == MV_FALSE)
+		return MV_FALSE;
+
+	mvOsSemTake(&pSataChannel->semaphore);
+
+	/* Sets the request and response queues base addresses */
+	pSataChannel->queueCommandsEnabled = MV_FALSE;
+	pSataChannel->EdmaActive = MV_FALSE;
+	pSataChannel->deviceType = MV_SATA_DEVICE_TYPE_UNKNOWN;
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II)
+		pSataChannel->PMSupported = MV_TRUE;
+	else
+		pSataChannel->PMSupported = MV_FALSE;
+
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) {
+		pSataChannel->commandsQueue = pAdapter->adapterCommands + (MV_SATA_GEN2E_SW_QUEUE_SIZE * channelIndex);
+		pSataChannel->commandsQueueSize = MV_SATA_GEN2E_SW_QUEUE_SIZE;
+	} else {
+		pSataChannel->commandsQueue = pAdapter->adapterCommands + (MV_SATA_SW_QUEUE_SIZE * channelIndex);
+		pSataChannel->commandsQueueSize = MV_SATA_SW_QUEUE_SIZE;
+	}
+	pSataChannel->DRQDataBlockSize = 1;
+	pSataChannel->FBSEnabled = MV_FALSE;
+	pSataChannel->use128Entries = MV_FALSE;
+	pSataChannel->EDMAQueuePtrMask = MV_EDMA_QUEUE_MASK;
+	pSataChannel->EDMARequestInpMask = MV_EDMA_REQUEST_Q_INP_MASK;
+	result = resetEdmaChannel(pSataChannel);
+	disableSaDevInterrupts(pAdapter, channelIndex);
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return result;
+}
+
+/*******************************************************************************
+* mvSataRemoveChannel -
+*
+* DESCRIPTION:  Removes data structures and other parameters used for the
+*   specific SATA channel that is indicated by pAdapter and channelIndex.
+*
+* INPUT:
+*   pAdapter - A pointer to an MV_SATA_ADAPTER data structure that holds
+*                information to access the 88SX50xx device.
+*   channelIndex - An index to a specific 88SX50xx channel.
+* OUTPUT:
+*   None.
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataRemoveChannel(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataRemoveChannel"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pAdapter->semaphore);
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataRemoveChannel"
+			 " Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pAdapter->semaphore);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataRemoveChannel "
+			 "failed, DMA is enabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		mvOsSemRelease(&pAdapter->semaphore);
+		return MV_FALSE;
+	}
+	mvOsSemRelease(&pSataChannel->semaphore);
+	mvOsSemRelease(&pAdapter->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataIsStorageDeviceConnected - Check if storage device is connected to a
+*                                  SATA channel.
+*
+* DESCRIPTION:
+*       This function reads the DET field from the R00 status bridge register
+*       of the corresponding channel.
+*
+* INPUT:
+*       pAdapter     - Pointer to the device data structure.
+*       channelIndex - Index of the required channel
+* OUTPU:
+*	SStatus	     - Pointer to SATA status reg value
+*
+* RETURN:
+*       MV_TRUE when storage device is connected, MV_FALSE otherwise( also when
+*       loopback mode is used).
+*
+* COMMENTS:
+*       None
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataIsStorageDeviceConnected(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 *SStatus)
+{
+	MV_U32 SStatusOffset = 0;
+	MV_U32 det;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "    : "
+			 "mvSataIsStorageDeviceConnected Failed, Bad adapter data" " structure pointer\n");
+		return MV_FALSE;
+	}
+
+	if (pAdapter->numberOfChannels <= channelIndex) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+			 "mvSataIsStorageDeviceConnected Failed, Bad channelIndex "
+			 " input on a 0x%x adapterstructure pointer\n",
+			 pAdapter->adapterId, channelIndex, pAdapter->pciConfigDeviceId);
+		return MV_FALSE;
+	}
+
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
+		MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+		SStatusOffset = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATA_I_HC_R00_STATUS_BRIDGE_PORT_OFFSET(port);
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		SStatusOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET;
+		if (pAdapter->staggaredSpinup[channelIndex] == MV_FALSE)
+			return MV_FALSE;
+	}
+
+	det = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SStatusOffset) & 0xf;
+
+	switch (det) {
+	case MV_PHY_DET_STATE_NO_DEVICE:
+		break;
+	case MV_PHY_DET_STATE_DEVICE_NO_PHY_COM:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " %d %d: Detection value is 1\n", pAdapter->adapterId, channelIndex);
+
+		MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SStatusOffset);
+		mvMicroSecondsDelay(pAdapter, MV_PHY_COM_SETUP_WAIT);
+		det = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SStatusOffset) & 0xf;
+		if (det != MV_PHY_DET_STATE_DEVICE_AND_PHY_COM) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Failed to"
+				 " establish SATA PHY communication\n", pAdapter->adapterId, channelIndex);
+			break;
+		}
+	case MV_PHY_DET_STATE_DEVICE_AND_PHY_COM:
+		return MV_TRUE;
+	case MV_PHY_DET_STATE_PHY_OFFLINE:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: WARNING: SATA PHY is "
+			 "offline\n", pAdapter->adapterId, channelIndex);
+		break;
+	default:
+		return MV_FALSE;
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: unknow value for\
+				R00 Status Bridge reg bits[3:0] (0x%02x)\n", pAdapter->adapterId, channelIndex, det);
+	}
+	return MV_FALSE;
+}
+
+static MV_BOOLEAN _checkSStatusAfterHReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 SStatusOffset;
+	MV_U32 SStatus;
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		/*  Get DET field in SControl register to 1 */
+		MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+		MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
+		SStatusOffset = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATA_I_HC_R00_STATUS_BRIDGE_PORT_OFFSET(port);
+	} else {
+		if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II)
+			SStatusOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET;
+		else
+			return MV_TRUE;
+	}
+	SStatus = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SStatusOffset);
+	SStatus &= (MV_BIT0 | MV_BIT1);
+	if ((SStatus == (MV_BIT0 | MV_BIT1)) || (SStatus == 0)) {
+		return MV_TRUE;
+	} else {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard "
+			 "Reset SATA communication not established.\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+}
+
+/*******************************************************************************
+* mvSataChannelHardReset - issue channel SATA HARD reset.
+*
+* DESCRIPTION:
+*   perform HARDWARE RESET to the connected device by asserting the RESET
+*   signal, this is done by setting the hardware reset bit of the EDMA
+*   command register
+*
+* INPUT:
+*   pAdapter    - pointer to the device data structure.
+*   channelIndex    - index of the required channel
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*   NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataChannelHardReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 count = 0;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataChannelHardReset"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: "
+			 "mvSataChannelHardReset Failed, channel data structure not "
+			 "allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	if (pSataChannel)
+		mvOsSemTake(&pSataChannel->semaphore);
+
+	if (pSataChannel && pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: Error: "
+				"mvSataIChannelHardReset called while EDMA is active\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Issue HRST\n", pAdapter->adapterId, channelIndex);
+
+	_channelHardReset(pAdapter, channelIndex);
+	_resetBmDma(pAdapter, channelIndex);
+	if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) &&
+	    (pAdapter->staggaredSpinup[channelIndex] == MV_FALSE)) {
+		if (pSataChannel)
+			mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_TRUE;
+	}
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		while (1) {
+			_establishSataComm(pAdapter, channelIndex);
+
+			/* try the DET fix 3 times */
+			if (_checkSStatusAfterHReset(pAdapter, channelIndex) == MV_FALSE) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard "
+					 "Reset storage drive is not ready, try fix #%d\n",
+					 pAdapter->adapterId, channelIndex, count);
+
+				count++;
+				if (count == 3) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel H"
+						 "ard Reset storage drive is not ready after 3 tries\n",
+						 pAdapter->adapterId, channelIndex);
+					if (pSataChannel)
+						mvOsSemRelease(&pSataChannel->semaphore);
+					return MV_FALSE;
+				}
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK, " %d %d: Disk is Ready After"
+					 " Hard Reset\n", pAdapter->adapterId, channelIndex);
+				break;
+			}
+		}
+	}
+
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II)
+		_establishSataComm(pAdapter, channelIndex);
+
+	if (pSataChannel)
+		mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataSetFBSMode - set FIS based switching mode.
+*
+* DESCRIPTION:
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*   enableFBS    -  if true then enable FBS mode.
+*   useQueueLen128 - if true then enable the 128 EDMA queue length.
+*
+* RETURN:
+*   MV_FALSE if
+*   1. the FBS feature set to be enable for an adapter that doesn't support this
+*      feature, or:
+*   2. the function called while EDMA is enabled.
+*   3. useQueueLen128 is true and enableFBS is false.
+*
+* COMMENTS:
+*   This function only sets the sw configuration, the harware is configured
+*   accordingly by mvSataConfigEdmaMode()
+*******************************************************************************/
+MV_BOOLEAN mvSataSetFBSMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			    MV_BOOLEAN enableFBS, MV_BOOLEAN useQueueLen128)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataSetFBSMode"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataSetFBSMode"
+			 " Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	mvOsSemTake(&pSataChannel->semaphore);
+
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " %d %d: mvSataSetFBSMode failed, EDMA is enabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	if (enableFBS == MV_FALSE) {
+		pSataChannel->FBSEnabled = MV_FALSE;
+		pSataChannel->use128Entries = MV_FALSE;
+		mvOsSemRelease(&pSataChannel->semaphore);
+		if (useQueueLen128 == MV_TRUE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d: mvSataSetFBSMode failed, 128 entries queue len is set"
+				 "while FBS mode is disabled\n", pAdapter->adapterId, channelIndex);
+			return MV_FALSE;
+		}
+		return MV_TRUE;
+	}
+
+	if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_IIE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataSetFBSMode failed,"
+			 " Feature not supported by the adapter\n", pAdapter->adapterId, channelIndex);
+		pSataChannel->FBSEnabled = MV_FALSE;
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	pSataChannel->FBSEnabled = MV_TRUE;
+	pSataChannel->use128Entries = useQueueLen128;
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataConfigEdmaMode - set EDMA operating mode.
+*
+* DESCRIPTION:
+*   Set the EDMA operating mode - MV_EDMA_MODE_NOT_QUEUED,
+*   MV_EDMA_MODE_QUEUED or MV_EDMA_MODE_NATIVE_QUEUING.
+*   When set toe MV_EDMA_MODE_QUEUED or MV_EDMA_MODE_NATIVE_QUEUING then
+*   the maxQueueDepth should be valud.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*   eDmaMode    - the selected mode
+*   maxQueueDepth   - the maximum depth of the queue
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+*
+* COMMENTS:
+*   None.
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataConfigEdmaMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+				MV_EDMA_MODE eDmaMode, MV_U8 maxQueueDepth)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 eDmaRegsOffset;
+	MV_U32 val;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataConfigEdmaMode"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataConfigEdmaMode"
+			 " Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	mvOsSemTake(&pSataChannel->semaphore);
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataConfigEdmaMode failed,"
+			 " EDMA is enabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+
+	val = MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET);
+	if (eDmaMode == MV_EDMA_MODE_NATIVE_QUEUING) {
+		if ((maxQueueDepth > MV_EDMA_QUEUE_LENGTH) || (maxQueueDepth == 0)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataConfigEdmaMode "
+				 "failed, Bad queue depth(%d)\n", pAdapter->adapterId, channelIndex, maxQueueDepth);
+			mvOsSemRelease(&pSataChannel->semaphore);
+			return MV_FALSE;
+		}
+		if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_II) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: Trying to configure "
+				 "EDMA to NCQ on a non NCQ enabled EDMA\n", pAdapter->adapterId, channelIndex);
+			mvOsSemRelease(&pSataChannel->semaphore);
+			return MV_FALSE;
+		}
+		val &= ~MV_EDMA_CONFIG_Q_DEPTH_MASK;	/* clear queue depth */
+		/* set the NCQ enable mode bit, and the queue depth bits */
+		val |= MV_EDMA_CONFIG_NATIVE_QUEUING_MASK | (maxQueueDepth - 1);
+	}
+	if (eDmaMode == MV_EDMA_MODE_QUEUED) {
+		if ((maxQueueDepth > MV_EDMA_QUEUE_LENGTH) || (maxQueueDepth == 0)) {
+			mvOsSemRelease(&pSataChannel->semaphore);
+			return MV_FALSE;
+		}
+		val &= ~MV_EDMA_CONFIG_Q_DEPTH_MASK;	/* clear queue depth */
+		val &= ~MV_EDMA_CONFIG_NATIVE_QUEUING_MASK;	/* clear NCQ mode */
+		/* set the queue enable mode bit, and the queue depth bits */
+		val |= MV_EDMA_CONFIG_EQUEUE_ENABLED_MASK | (maxQueueDepth - 1);
+	}
+
+	if (eDmaMode == MV_EDMA_MODE_NOT_QUEUED) {
+		val &= ~MV_EDMA_CONFIG_Q_DEPTH_MASK;	/* clear queue depth */
+		val &= ~MV_EDMA_CONFIG_NATIVE_QUEUING_MASK;	/* clear NCQ mode */
+		val &= ~MV_EDMA_CONFIG_EQUEUE_ENABLED_MASK;
+	}
+	pSataChannel->queuedDMA = eDmaMode;
+
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
+		val |= MV_EDMA_CONFIG_BURST_SIZE_MASK;
+
+	if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II)
+	    && (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) {
+		val |= (MV_EDMA_CONFIG_BURST_SIZE_EXT_MASK | MV_BIT13);
+	}
+
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) {
+		/* disable RX PM port mask, required for PM */
+		val |= MV_BIT23;
+
+		if (pSataChannel->FBSEnabled == MV_TRUE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+				 " %d %d: Enable FBS feature\n", pAdapter->adapterId, channelIndex);
+/*            val |= MV_BIT16;*/
+			/* Set bit 16 at FISDMAActiveSyncResp */
+			_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				    MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT16);
+			/* Set bit 8 at SingleSync */
+			_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + 0x30C, MV_BIT8);
+		} else {
+			val &= ~MV_BIT16;
+		}
+
+		if (pSataChannel->use128Entries == MV_TRUE) {
+			val |= MV_BIT19;
+			pSataChannel->EDMAQueuePtrMask = MV_EDMA_GEN2E_QUEUE_MASK;
+			pSataChannel->EDMARequestInpMask = MV_EDMA_GEN2E_REQUEST_Q_INP_MASK;
+		} else {
+			val &= ~MV_BIT19;
+			pSataChannel->EDMAQueuePtrMask = MV_EDMA_QUEUE_MASK;
+			pSataChannel->EDMARequestInpMask = MV_EDMA_REQUEST_Q_INP_MASK;
+		}
+		if (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED) {
+			/*enable cutthrough */
+			val |= MV_BIT17;
+#ifdef MV_SUPPORT_ATAPI
+			/*enable early completion */
+			val |= MV_BIT18;
+#endif
+		}
+		/*enable host queue cache */
+		val |= MV_BIT22;
+
+		if (pAdapter->hostInterface == MV_HOST_IF_PCI) {
+			MV_U32 pciMode = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+							   MV_PCI_REGS_OFFSET + MV_PCI_MODE_REG_OFFSET);
+
+			if (getRegField(pciMode, MV_PCI_MODE_OFFSET, 2) == 0) {	/* PCI */
+				if (MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						      MV_PCI_REGS_OFFSET + MV_PCI_COMMAND_REG_OFFSET) & MV_BIT7) {
+					/*in this case disable cut through */
+					val &= ~MV_BIT17;
+				}
+			}
+		}
+	}
+	/* by defualt, the tags data srutcure initialized in mvSataConfigureChannel */
+	/* for 32 host commands, so we call it again since use128Entries could be */
+	/* changed */
+	initChannelTags(pSataChannel);
+	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET, val);
+	setupEdmaDeviceErrorHandlingConfiguration(pSataChannel);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Edma Configuration Reg Value: 0x%08x\n",
+		 pAdapter->adapterId, channelIndex,
+		 MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET));
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataEnableChannelDma - enable EDMA engine
+*
+* DESCRIPTION:
+*   enable the EDMA engine for the given channel
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*   NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataEnableChannelDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataEnableChannelDma"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataEnableChannelD"
+			 "ma Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataEnableChannelDma "
+			 "failed, DMA is enabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+#ifdef MV_SATA_C2C_COMM
+	/* C2C */
+	if (pSataChannel->C2CmodeEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataEnableChannelDma "
+			 "failed, C2C mode is enabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+#endif
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: mvSataEnableChannelDma\n",
+		 pAdapter->adapterId, channelIndex);
+	pSataChannel->queueCommandsEnabled = MV_TRUE;
+	activateEdma(pAdapter, channelIndex);
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataDisableChannelDma - disable EDMA engine
+*
+* DESCRIPTION:
+*   disable the EDMA engine for the given channel
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*   NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataDisableChannelDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_BUS_ADDR_T ioBaseAddr;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataDisableChannelDma"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	if (pAdapter->sataChannel[channelIndex] == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataDisableChannel"
+			 "Dma Failed, channel data structure is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: mvSataDisableChannel\n", pAdapter->adapterId, channelIndex);
+	/* if this function called while commands still not finished, then it's */
+	/* probably timeout */
+	if (pAdapter->sataChannel[channelIndex]->outstandingCommands) {
+		_dumpSataRegs(pAdapter, channelIndex);
+		_dumpEDMARegs(pAdapter, channelIndex);
+		_dumpChannelQueues(pAdapter, channelIndex);
+	}
+
+	mvOsSemTake(&pAdapter->sataChannel[channelIndex]->semaphore);
+	pAdapter->sataChannel[channelIndex]->queueCommandsEnabled = MV_FALSE;
+	deactivateEdma(pAdapter, channelIndex);
+	mvOsSemRelease(&pAdapter->sataChannel[channelIndex]->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataFlushDmaQueue - flush the outstanding UDMA commands
+*
+* DESCRIPTION:
+*   flush posted UDMA ATA commands on a certain MV88SX50XX SATA channel. if
+*   the flush type is MV_FLUSH_TYPE_CALLBACK then all call back functions of
+*   the UDMA commands are called with a flush indication.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*   flushType   - indicates wheather to call the callBack function or not.
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*   NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataFlushDmaQueue(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_FLUSH_TYPE flushType)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataFlushDmaQueue"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataFlushDmaQueue "
+			 "Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataFlushDmaQueue "
+			 "Failed, EDMA not disabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	flushDmaQueue(pSataChannel, flushType, MV_COMPLETION_TYPE_ABORT, 0);
+	resetEdmaChannel(pSataChannel);
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataNumOfDmaCommands - get the number of the outstanding commmands for the
+*                           given channel
+*
+* DESCRIPTION:
+*   return the number of posted ATA commands on an EDMA engine for a
+*   specific SATA channel.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*
+* RETURN:
+*   num of queue commands.
+* COMMENTS:
+*   NONE
+*
+*******************************************************************************/
+MV_U8 mvSataNumOfDmaCommands(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_U8 result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataNumOfDmaCommands"
+			 " Failed, Bad adapter data structure pointer\n");
+		return 0xFF;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataNumOfDmaComman"
+			 "ds Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return 0xFF;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+	result = pSataChannel->outstandingCommands;
+	mvOsSemRelease(&pSataChannel->semaphore);
+
+	return result;
+}
+
+/*******************************************************************************
+* mvSataGetNumOfPortQueuedCommands - get the number of the outstanding commmands for
+*                               the given port
+*
+* DESCRIPTION:
+*   return the number of posted ATA commands on an EDMA engine for a
+*   specific SATA port.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*   PMPort      - port number
+*   pCommandsPerChannel - if not null, gets the total number of outstanding
+*                   command for the given channel
+*
+* RETURN:
+*   num of queue commands, 0xFF if error detected.
+* COMMENTS:
+*
+*
+*******************************************************************************/
+MV_U8 mvSataGetNumOfPortQueuedCommands(MV_SATA_ADAPTER *pAdapter,
+				       MV_U8 channelIndex, MV_U8 PMPort, MV_U8 *pCommandsPerChannel)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_U8 result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataGetNumOfPortQueuedCommands"
+			 " Failed, Bad adapter data structure pointer\n");
+		return 0xFF;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d %d: mvSataGetNumOfPortQueuedCommands"
+			 "ds Failed, channel data structure not allocated\n",
+			 pAdapter->adapterId, channelIndex, PMPort);
+		return 0xFF;
+	}
+	if (PMPort > MV_SATA_PM_MAX_PORTS) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d %d: mvSataGetNumOfPortQueuedCommands"
+			 "ds Failed, non valid port\n", pAdapter->adapterId, channelIndex, PMPort);
+		return 0xFF;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+	result = pSataChannel->portQueuedCommands[PMPort];
+	if (pCommandsPerChannel)
+		*pCommandsPerChannel = pSataChannel->outstandingCommands;
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+
+	return result;
+}
+
+/*******************************************************************************
+* mvSataSetIntCoalParams - update the interrupt Coalescing registers
+*
+* DESCRIPTION:  Sets the interrupt coalescing for a specific SATA unit
+*               (each SATA unit contains quad SATA channels).
+*
+* INPUT:
+*   pAdapter - pointer to the adapter data structure.
+*   sataUnit - which SATA unit to be changed (0xff for all SATA ports)
+*   intCoalThre - the value to be written to the Coalescing threshold register
+*   intTimeThre - the value to be written to the Time threshold register
+*
+* OUTPUT:
+*   None.
+* RETURN:
+*   MV_TRUE
+* COMMENTS:
+*   None.
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataSetIntCoalParams(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, MV_U32 intCoalThre, MV_U32 intTimeThre)
+{
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataSetIntCoalParams"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+
+	if ((sataUnit != 0) && (sataUnit != 1) && (sataUnit != 0xff)) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d  : %d Bad"
+			 " unit number\n", pAdapter->adapterId, sataUnit);
+		return MV_FALSE;
+	}
+
+	mvOsSemTake(&pAdapter->semaphore);
+	if (sataUnit == 0xff) {
+		if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) &&
+		    (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) {
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_SATA_II_ALL_PORTS_INT_COAL_CMND_THR_REG_OFFSET, intCoalThre);
+
+			pAdapter->intCoalThre[0] = intCoalThre;
+			pAdapter->intCoalThre[1] = intCoalThre;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_SATA_II_ALL_PORTS_INT_COAL_TIME_THR_REG_OFFSET, intTimeThre);
+			pAdapter->intTimeThre[0] = intTimeThre;
+			pAdapter->intTimeThre[1] = intTimeThre;
+			pAdapter->mainMask |= MV_BIT21;
+			pAdapter->mainMask &= ~(MV_BIT17 | MV_BIT8);
+		} else {
+			MV_U8 count;
+			for (count = 0; count < pAdapter->numberOfUnits; count++) {
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   MV_SATAHC_REGS_BASE_OFFSET(count) +
+						   MV_SATAHC_INT_COAL_THRE_REG_OFFSET, intCoalThre);
+
+				pAdapter->intCoalThre[count] = intCoalThre;
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   MV_SATAHC_REGS_BASE_OFFSET(count) +
+						   MV_SATAHC_INT_TIME_THRE_REG_OFFSET, intTimeThre);
+				pAdapter->intTimeThre[count] = intTimeThre;
+			}
+		}
+	} else {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATAHC_INT_COAL_THRE_REG_OFFSET, intCoalThre);
+
+		pAdapter->intCoalThre[sataUnit] = intCoalThre;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATAHC_INT_TIME_THRE_REG_OFFSET, intTimeThre);
+		pAdapter->intTimeThre[sataUnit] = intTimeThre;
+		if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+			pAdapter->mainMask |= (MV_BIT17 | MV_BIT8);
+			pAdapter->mainMask &= ~MV_BIT21;
+		}
+	}
+	if (pAdapter->interruptsAreMasked == MV_FALSE) {
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, pAdapter->mainMask);
+
+		MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset);
+
+	}
+	mvOsSemRelease(&pAdapter->semaphore);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataSetChannelPhyParams - update the channel's Sata Phy params
+*
+* DESCRIPTION: This functoin changes the Sata Phy params such as the AMP and
+*       PRE by updating the PHY Mode register.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex- index of the Edma channel number.
+*   signalAmps  - three bits value to be written to the Phy Mode register at
+*                   bits[7:5]
+*   pre         - two bits value to be written to the Phy Mode register at
+*                   bits[12:11]
+*
+* OUTPUT:
+*   None.
+*
+* RETURN:
+*   MV_TRUE on success, MV_FASLE otherwisw
+*
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataSetChannelPhyParams(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 signalAmps, MV_U8 pre)
+{
+	MV_U32 regAddr;
+	MV_U32 val;
+	MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+	MV_U8 unit = (channelIndex & MV_BIT2) >> 2;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "  : mvSataSetChannelPhyParam"
+			 "s Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+
+	if ((pAdapter->chipIs62X1Z0 == MV_TRUE) || (pAdapter->chipIs65XXZ0 == MV_TRUE)) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d  : mvSataSetChannelPhyPara\
+m" "s Failed, This function not supported for this adapter\n", pAdapter->adapterId);
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		if ((signalAmps & 0xf8) || (pre & 0xfc)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+				 "mvSataSetChannelPhyParams Failed. Bad params\n", pAdapter->adapterId, channelIndex);
+			return MV_FALSE;
+		}
+
+		regAddr = MV_SATAHC_REGS_BASE_OFFSET(unit) + MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port);
+
+		val = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, regAddr);
+
+		val &= ~MV_SATA_I_PHY_MODE_AMP_MASK;
+		val |= (signalAmps << MV_SATA_I_PHY_MODE_AMP_OFFSET) & MV_SATA_I_PHY_MODE_AMP_MASK;
+
+		val &= ~MV_SATA_I_PHY_MODE_PRE_MASK;
+		val |= (pre << MV_SATA_I_PHY_MODE_PRE_OFFSET) & MV_SATA_I_PHY_MODE_PRE_MASK;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, regAddr, val);
+		pAdapter->pre[channelIndex] = pre;
+		pAdapter->signalAmps[channelIndex] = signalAmps;
+	}
+
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		if ((signalAmps & 0xf8) || (pre & 0xf8)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+				 "mvSataSetChannelPhyParams Failed. Bad params\n", pAdapter->adapterId, channelIndex);
+			return MV_FALSE;
+		}
+
+		pAdapter->pre[channelIndex] = pre;
+		pAdapter->signalAmps[channelIndex] = signalAmps;
+		regAddr = getEdmaRegOffset(channelIndex) + MV_SATA_II_PHY_MODE_2_REG_OFFSET;
+		val = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, regAddr);
+
+		val &= ~MV_SATA_II_PHY_MODE_2_AMP_MASK;
+		val |= (signalAmps << MV_SATA_II_PHY_MODE_2_AMP_OFFSET) & MV_SATA_II_PHY_MODE_2_AMP_MASK;
+		val &= ~MV_SATA_II_PHY_MODE_2_PRE_MASK;
+		val |= (pre << MV_SATA_II_PHY_MODE_2_PRE_OFFSET) & MV_SATA_II_PHY_MODE_2_PRE_MASK;
+		val &= ~MV_BIT16;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, regAddr, val);
+	}
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataChannelPhyShutdown -
+*
+* DESCRIPTION: Shutdown the sata Phy of the given channel.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise
+*
+* COMMENTS:
+*   After shutdown no connect / disconnect indication will be available.
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataChannelPhyShutdown(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 regVal;
+	MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+	MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "  : mvSataChannelPhyShutdown"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+		/* Fix for 88SX60x1 FEr SATA#8 */
+		/* according to the spec, bits [31:12] must be set to 0x009B1 */
+		regVal &= 0x00000FFF;
+		/* regVal |= MV_BIT12; */
+		regVal |= 0x009B1000;
+
+		regVal |= MV_BIT9;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+		return MV_TRUE;
+	}
+	regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET);
+	regVal |= MV_SATA_I_TEST_CONTROL_PHY_SHUTDOWN_MASK(port);
+
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+			   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET, regVal);
+	MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+			  MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataChannelPhyPowerOn -
+*
+* DESCRIPTION: power on the sata Phy of the given channel.
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise
+*
+* COMMENTS:
+*   None.
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataChannelPhyPowerOn(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 regVal;
+	MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+	MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "  : mvSataChannelPhyPowerOn"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+		/* Fix for 88SX60x1 FEr SATA#8 */
+		/* according to the spec, bits [31:12] must be set to 0x009B1 */
+		regVal &= 0x00000FFF;
+		/* regVal |= MV_BIT12; */
+		regVal |= 0x009B1000;
+
+		regVal &= ~(MV_BIT9);
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+		_channelHardReset(pAdapter, channelIndex);
+		return MV_TRUE;
+	}
+	_fixPhyParams(pAdapter, channelIndex);
+	regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "  : %d %d %d mvSataChannelPhyPowerOn"
+		 " reg[%x] = 0x%x -> 0x%x\n", pAdapter->adapterId, sataUnit, port,
+		 MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+		 MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET, regVal,
+		 regVal & ~(MV_SATA_I_TEST_CONTROL_PHY_SHUTDOWN_MASK(port)));
+	regVal &= ~(MV_SATA_I_TEST_CONTROL_PHY_SHUTDOWN_MASK(port));
+
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+			   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET, regVal);
+	MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+			  MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET); {
+		MV_U32 temp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+						MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port));
+		temp &= ~0xf;
+		temp |= MV_BIT0;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port), temp);
+	}
+	_fixPhyParams(pAdapter, channelIndex);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataChannelFarLoopbackDiagnostic - do far end loopback
+*
+* DESCRIPTION: operate the far-end LB mode on the bridge
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - index of the required channel
+*
+* OUTPUT:
+*   None.
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise
+* COMMENTS:
+*   None.
+*******************************************************************************/
+
+MV_BOOLEAN mvSataChannelFarLoopbackDiagnostic(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
+	MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+	MV_U32 regVal = 0, temp;
+	MV_U32 tryCount, pollCount;
+	MV_BOOLEAN result = MV_TRUE;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "  : mvSataChannelFarLoopback"
+			 "Diagnostic Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		/* TODO - Add support for far end loopback */
+		return MV_TRUE;
+	}
+
+	for (tryCount = 0; tryCount < 5; tryCount++) {
+
+		/* Set Far-end loopback */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATA_I_HC_R04_STATUS_BRIDGE_PORT_OFFSET(port), 0x00100000);
+		/* BIST pattern */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATA_I_HC_R05_STATUS_BRIDGE_PORT_OFFSET(port), 0xb5b5b5b5);
+		/* BIST pattern */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATA_I_HC_R06_STATUS_BRIDGE_PORT_OFFSET(port), 0xb5b5b5b5);
+		/* enable BIST */
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+				   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				   MV_SATA_I_HC_R0F_STATUS_BRIDGE_PORT_OFFSET(port), 0x00200000);
+
+		mvMicroSecondsDelay(pAdapter, MV_FAR_END_LOOPBACK_TEST_WAIT_TIME);
+
+		/* poll bit 20 of register 0F(bist finish) for 50 times */
+		for (pollCount = 0; pollCount < 50; pollCount++) {
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+						   MV_SATA_I_HC_R0F_STATUS_BRIDGE_PORT_OFFSET(port));
+
+			if (regVal & MV_BIT20)
+				break;
+		}
+
+		if (regVal & MV_BIT20) {
+			break;
+		} else {	/*if bit 20 still 0, then try the bist sequence again for 5 times */
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Warning: FarEnd LoopBack "
+				 "- bit 20 still not set try again, tryCount %d\n", pAdapter->adapterId,
+				 channelIndex, tryCount);
+			temp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						 MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+						 MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port));
+			temp &= 0xff0;
+			temp |= MV_BIT0;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+					   MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port), temp);
+
+			if (waitForBusyAfterHReset(pAdapter, channelIndex) == MV_FALSE) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard Rese"
+					 "t storage drive is not ready\n", pAdapter->adapterId, channelIndex);
+
+				result = MV_FALSE;
+			}
+			_fixPhyParams(pAdapter, channelIndex);
+
+		}
+	}
+	if (tryCount == 5) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: FarEnd LoopBack Failed"
+			 "- the test doesn't finish\n", pAdapter->adapterId, channelIndex);
+		result = MV_FALSE;
+	} else {
+		if (((regVal & MV_BIT20) == 0) && (regVal & MV_BIT19)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: FarEnd LoopBack"
+				 " finished with error, 0F regVal= %x\n", pAdapter->adapterId, channelIndex, regVal);
+			result = MV_FALSE;
+		} else {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: FarEnd LoopBack finished "
+				 "successfuly, 0F regVal= %x\n", pAdapter->adapterId, channelIndex, regVal);
+		}
+	}
+	/* disable BIST and start phy communication */
+	temp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+				 MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+				 MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port));
+	temp &= 0xff0;
+	temp |= MV_BIT0;
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+			   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+			   MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port), temp);
+
+	if (waitForBusyAfterHReset(pAdapter, channelIndex) == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard Rese"
+			 "t storage drive is not ready\n", pAdapter->adapterId, channelIndex);
+
+		result = MV_FALSE;
+	}
+	_fixPhyParams(pAdapter, channelIndex);
+
+	return result;
+}
+
+/*******************************************************************************
+* mvSataQueueCommand - Execute ATA command (PIO or UDMA)
+*
+* DESCRIPTION:
+*   adds ATA PIO or UDMA request to a MV88SX50XX specific sata channel
+*
+* INPUT:
+*   pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - the index of the specific EDMA channel
+*   pCommandInfo - Pointer to the PIO or UDMA command
+*
+* RETURN:
+*   MV_DMA_QUEUE_RESULT_OK - Command queuing is successfull
+*   MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED - when trying to add command
+*                            while command queuing is disabled
+*   MV_QUEUE_COMMAND_RESULT_FULL - Command queue is full
+*   MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS - when the connected device doesn't
+*          support 48 bit addressing but the new command need's to use 48bit
+*           addressing.
+*   MV_QUEUE_RESULT_BAD_PARAMS - When bad parameters are received
+*
+* COMMENTS:
+*   None.
+*
+*******************************************************************************/
+MV_QUEUE_COMMAND_RESULT mvSataQueueCommand(MV_SATA_ADAPTER *pAdapter,
+					   MV_U8 channelIndex, MV_QUEUE_COMMAND_INFO *pCommandInfo)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	MV_QUEUED_COMMAND_ENTRY *pCommandEntry;
+	MV_U32 eDmaRegsOffset;
+	MV_U8 hostTag;
+	MV_U8 deviceTag;
+
+#ifdef MV_SATA_IO_GRANULARITY
+	MV_U8 nextTransId;
+#endif
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "  : mvSataQueueCommand"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_QUEUE_COMMAND_RESULT_BAD_PARAMS;
+	}
+
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataQueueCommand"
+			 " Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_QUEUE_COMMAND_RESULT_BAD_PARAMS;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION
+	if ((pAdapter->sataAdapterGeneration < MV_SATA_GEN_IIE) &&
+	    (MV_QUEUED_COMMAND_TYPE_UDMA == pCommandInfo->type) &&
+	    (pCommandInfo->commandParams.udmaCommand.singleDataRegion == MV_TRUE)) {
+		mvOsSemRelease(&pSataChannel->semaphore);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: "
+			 "mvSataQueueCommand single Data region not supported\n", pAdapter->adapterId, channelIndex);
+		return MV_QUEUE_COMMAND_RESULT_BAD_PARAMS;
+	}
+#endif
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+	if (pSataChannel->queueCommandsEnabled == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: queued commands mode"
+			 " is disabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED;
+	}
+
+	if (getTag(pSataChannel, pCommandInfo->PMPort, &hostTag, &deviceTag) == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: queue is full\n",
+			 pAdapter->adapterId, channelIndex);
+
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_QUEUE_COMMAND_RESULT_FULL;
+	}
+#ifdef MV_SATA_IO_GRANULARITY
+	if ((MV_QUEUED_COMMAND_TYPE_UDMA == pCommandInfo->type) &&
+	    (MV_TRUE == pCommandInfo->commandParams.udmaCommand.ioGranularityEnabled)) {
+
+		if (MV_FALSE == pAdapter->iogEnabled) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: IO granularity is "
+				 "disabled for the adapter\n", pAdapter->adapterId, channelIndex);
+			mvOsSemRelease(&pSataChannel->semaphore);
+			return MV_QUEUE_COMMAND_RESULT_BAD_PARAMS;
+		} else {
+			if (pAdapter->iogFreeIdsNum <= 0) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: IO granularity "
+					 "queue is full\n", pAdapter->adapterId);
+				mvOsSemRelease(&pSataChannel->semaphore);
+				return MV_QUEUE_COMMAND_RESULT_FULL;
+			}
+		}
+	}
+#endif
+	pCommandEntry = &(pSataChannel->commandsQueue[hostTag]);
+	pCommandEntry->hostTag = hostTag;
+	pCommandEntry->deviceTag = deviceTag;
+	pCommandEntry->isCommandInEdma = MV_FALSE;
+	pCommandEntry->commandAborted = MV_FALSE;
+	if (pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_UDMA) {
+		MV_UDMA_COMMAND_PARAMS *pUdmaCommand = &pCommandInfo->commandParams.udmaCommand;
+		if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)
+			pUdmaCommand->isEXT = MV_TRUE;
+
+#ifdef MV_SATA_IO_GRANULARITY
+		pUdmaCommand->iogCurrentTransId = MV_IOG_INVALID_COMMAND_ID;
+		if ((MV_TRUE == pAdapter->iogEnabled) && (MV_TRUE == pUdmaCommand->ioGranularityEnabled)) {
+			if (pUdmaCommand->iogCommandType == MV_IOG_COMMAND_TYPE_FIRST) {
+				mvOsSemTake(&pAdapter->iogSemaphore);
+				nextTransId = pAdapter->iogFreeIdsStack[--(pAdapter->iogFreeIdsNum)];
+				setIoGranularityCount(pAdapter,
+						      nextTransId, pUdmaCommand->ioGranularityCommandParam.transCount);
+				mvOsSemRelease(&pAdapter->iogSemaphore);
+			} else {
+				nextTransId = pUdmaCommand->ioGranularityCommandParam.transId;
+			}
+			pUdmaCommand->iogCurrentTransId = nextTransId;
+		}
+#endif
+		if ((pSataChannel->noneUdmaOutstandingCommands == 0) &&
+#ifdef MV_SUPPORT_ATAPI
+		    (pSataChannel->packetOutstandingCommands == 0) &&
+#endif
+		    (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_IDLE)) {
+			if (pSataChannel->EdmaActive == MV_FALSE) {
+				disableSaDevInterrupts(pAdapter, channelIndex);
+				activateEdma(pAdapter, channelIndex);
+			}
+			addCommand(pSataChannel, pCommandEntry, pCommandInfo);
+			EdmaReqQueueInsert(pSataChannel, pCommandEntry, &pCommandInfo->commandParams.udmaCommand);
+		} else {
+			addCommand(pSataChannel, pCommandEntry, pCommandInfo);
+		}
+	} else {
+		addCommand(pSataChannel, pCommandEntry, pCommandInfo);
+		if (pSataChannel->outstandingCommands == 1) {
+			if (pSataChannel->EdmaActive == MV_TRUE)
+				deactivateEdma(pAdapter, channelIndex);
+
+			if (pSataChannel->PMSupported == MV_TRUE)
+				_setActivePMPort(pSataChannel, pCommandInfo->PMPort);
+
+			if (sendNoneUdmaCommand(pSataChannel, pCommandEntry) == MV_FALSE) {
+				removeCommand(pSataChannel, pCommandEntry);
+				_doSoftReset(pSataChannel);
+				mvOsSemRelease(&pSataChannel->semaphore);
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Failed to "
+					 "Issue PIO command\n", pAdapter->adapterId, channelIndex);
+				return MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED;
+			}
+		}
+	}
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_QUEUE_COMMAND_RESULT_OK;
+
+}
+
+/*******************************************************************************
+* mvSataSetInterruptsScheme - Modify interrupt scheme
+*
+* DESCRIPTION:
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*       interruptScheme =  A parameter containing the rquired interrupt scheme
+*
+* RETURN:
+*       MV_TRUE on success, otherwise MV_FALSE.
+* COMMENTS: This function doesn't modify the HW main mask register
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataSetInterruptsScheme(MV_SATA_ADAPTER *pAdapter, MV_SATA_INTERRUPT_SCHEME interruptScheme)
+{
+	mvOsSemTake(&pAdapter->semaphore);
+	switch (interruptScheme) {
+	case MV_SATA_INTERRUPT_HANDLING_IN_ISR:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, " %d  : Interrupts"
+			 " scheme set to Handling in ISR\n", pAdapter->adapterId);
+		break;
+	case MV_SATA_INTERRUPT_HANDLING_IN_TASK:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, " %d  : Interrupts"
+			 " scheme set to Handling in TASK\n", pAdapter->adapterId);
+		break;
+	case MV_SATA_INTERRUPTS_DISABLED:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, " %d  : Interrupts"
+			 " scheme set to interrupts Disabled\n", pAdapter->adapterId);
+		break;
+	default:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d  : in mvSataSet"
+			 "InterruptsScheme: Invalid Interrup scheme (%d)\n", pAdapter->adapterId, interruptScheme);
+		mvOsSemRelease(&pAdapter->semaphore);
+		return MV_FALSE;
+	}
+	pAdapter->interruptsScheme = interruptScheme;
+	mvOsSemRelease(&pAdapter->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataCheckPendingInterrupt - Check and mask interrupts
+*
+* DESCRIPTION:
+*       Check if an interrupt is pending, If there is  a pending interrupt then
+*   this function masks the adapter's interrupts and returns MV_TRUE
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*
+* RETURN:
+*       MV_TRUE if the interrupt issued by mv adapter, otherwise MV_FALSE.
+* COMMENTS:
+*       this function must be used only when interrupt scheme is set to
+*       MV_SATA_INTERRUPT_IN_TASK
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataCheckPendingInterrupt(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U32 mainMask;
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+
+	/*mvOsSemTake(&pAdapter->interruptsMaskSem); */
+	mainMask = pAdapter->mainMask;
+	/*mvOsSemRelease(&pAdapter->interruptsMaskSem); */
+	/* if the interrupt it ours */
+	if (MV_REG_READ_DWORD(ioBaseAddr, pAdapter->mainCauseOffset) & mainMask) {
+		/*clear mainMask, the ISR enables the interrupt once served */
+		MV_REG_WRITE_DWORD(ioBaseAddr, pAdapter->mainMaskOffset, 0);
+		return MV_TRUE;
+	}
+	/*bogus interrupt */
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvSataInterruptServiceRoutine - Interrupt service routine
+*
+* DESCRIPTION:
+*       this function is an interrupt service routine that is called upon
+*       reception of an interrupt from a MV88SX50XX adapter.
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*
+* RETURN:
+*       MV_TRUE if the interrupt issued by mv adapter, otherwise MV_FALSE.
+* COMMENTS:
+*       this function handles all the events that generate interrupts incuding
+*       calling the upper layer call back functions.
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataInterruptServiceRoutine(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U32 mainCause;
+	MV_U32 mainMask;
+	MV_U32 unitCause = 0;
+	MV_U32 responseDone;
+	MV_U32 edmaError;
+	MV_U32 deviceInterrupt;
+	MV_U8 sataUnit;
+	MV_U8 port;
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	mvOsSemTake(&pAdapter->semaphore);
+	mainCause = MV_REG_READ_DWORD(ioBaseAddr, pAdapter->mainCauseOffset);
+
+	/* Check if the interrupt is ours */
+	mvOsSemTake(&pAdapter->interruptsMaskSem);
+	mainMask = pAdapter->mainMask;
+	mvOsSemRelease(&pAdapter->interruptsMaskSem);
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_INTERRUPTS,
+		 " %d  : Interrupt. Cause = 0x%08x, mask 0x%08x\n", pAdapter->adapterId, mainCause, mainMask);
+
+	/*
+	 * Check if interrupt is our or interrupts are masked.
+	 * in interrupts disaled scheme, the main mask register is cleared but the
+	 * mainMask variable will hold the bits where interrupts expected, this why
+	 * the sheme is not checked
+	 */
+	if ((0 == (mainCause & mainMask)) ||
+	    ((pAdapter->interruptsAreMasked == MV_TRUE) &&
+	     (pAdapter->interruptsScheme != MV_SATA_INTERRUPTS_DISABLED))) {
+		/* when interrupts handled in task, we expect to find interrupts here */
+		if (pAdapter->interruptsScheme == MV_SATA_INTERRUPT_HANDLING_IN_TASK) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d  : ISR called "
+				 "but no interrutps are found in interrupts handle in task"
+				 "scheme!\n", pAdapter->adapterId);
+			/*anyway unmask interrupts */
+			mvOsSemTake(&pAdapter->interruptsMaskSem);
+			if (pAdapter->interruptsAreMasked == MV_FALSE) {
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   pAdapter->mainMaskOffset, pAdapter->mainMask);
+			}
+			mvOsSemRelease(&pAdapter->interruptsMaskSem);
+		}
+		mvOsSemRelease(&pAdapter->semaphore);
+		return MV_FALSE;
+	}
+
+	if (mainCause & MV_MAIN_INTERRUPT_MASK_REG_PCIERR_BIT)
+		handlePCIErrorInterrupt(pAdapter);
+
+#ifdef MV_SATA_IO_GRANULARITY
+	/*IO Granularity interrupt */
+	if (mainCause & MV_IOG_TRANS_INT_MASK) {
+		mvOsSemTake(&pAdapter->iogSemaphore);
+		iogInterrupt(pAdapter, ioBaseAddr, mainCause);
+		mvOsSemRelease(&pAdapter->iogSemaphore);
+	}
+#endif
+	for (sataUnit = 0; sataUnit < pAdapter->numberOfUnits; sataUnit++) {
+		if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) &&
+		    (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) {
+			/* Clear the all ports interrupt coalescing cause register */
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   MV_SATA_II_ALL_PORTS_INT_CAUSE_REG_OFFSET, 0);
+		}
+
+		if (mainCause & 0x1ff) {
+			MV_U32 unitCauseAddr = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+			    MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET;
+			MV_U32 unitRspInPtr;
+
+			/* clear the cause bit of the Coalescing interrupt */
+			MV_REG_WRITE_DWORD(ioBaseAddr, unitCauseAddr, ~MV_BIT4);
+			unitCause = MV_REG_READ_DWORD(ioBaseAddr, unitCauseAddr);
+			/* clear the cause register of the current unit */
+			MV_REG_WRITE_DWORD(ioBaseAddr, unitCauseAddr, ~unitCause | MV_BIT4);
+
+			unitRspInPtr = MV_REG_READ_DWORD(ioBaseAddr,
+							 MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+							 MV_SATAHC_RESPONSE_Q_IN_POINTER_OFFSET);
+
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d unit %d : unitCause = 0x%08x,"
+				 " unitRspInPtr 0x%08x\n", pAdapter->adapterId, sataUnit, unitCause, unitRspInPtr);
+
+			for (port = 0; port < pAdapter->portsPerUnit; port++) {
+				deviceInterrupt = unitCause & (MV_BIT8 << port);
+				responseDone = unitCause & (1 << port);
+				edmaError = (mainCause & MV_BIT0);
+
+				if (responseDone || edmaError) {
+					handleEdmaInterrupt(pAdapter, sataUnit, port,
+							    (MV_U8) (unitRspInPtr), responseDone, edmaError, unitCause);
+				}
+				if (deviceInterrupt &&
+				    (SaDevInterrutpBit((MV_U8) MV_CHANNEL_INDEX(sataUnit, port)) & mainMask)) {
+					handleDeviceInterrupt(pAdapter, sataUnit, port);
+				}
+
+				mainCause >>= 2;
+				unitRspInPtr >>= 8;
+			}
+		} else {
+			mainCause >>= 8;
+		}
+		mainCause >>= 1;	/* this is for the coalescing 0-3 bit */
+	}
+	if (pAdapter->interruptsScheme == MV_SATA_INTERRUPT_HANDLING_IN_TASK) {
+		if (pAdapter->interruptsAreMasked == MV_FALSE) {
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   pAdapter->mainMaskOffset, pAdapter->mainMask);
+		}
+	}
+	mvOsSemRelease(&pAdapter->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataMaskAdapterInterrupt - mask any interrupts can be generated from a
+*       MV88SX50XX adapter
+*
+* DESCRIPTION:
+*       mask all the interrupts that could occur from the adapter.
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       Before masking the interrupts, the value of the interrupt maks register
+*       will be stored in the adapter data structure.
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataMaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter)
+{
+	pAdapter->interruptsAreMasked = MV_TRUE;
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, 0);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataUnmaskAdapterInterrupt - unmask interrupts can be generated from a
+*       MV88SX50XX adapter
+*
+* DESCRIPTION:
+*       Restore a previous value in the MV88SX50XX interrupt maks register by
+*       writing the previously stored value in the interruptMaskRegister field
+*       in the adapter data structure to the MV88SX50XX adapter main interrupt
+*       mask register
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataUnmaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter)
+{
+	mvOsSemTake(&pAdapter->interruptsMaskSem);
+	pAdapter->interruptsAreMasked = MV_FALSE;
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, pAdapter->mainMask);
+	mvOsSemRelease(&pAdapter->interruptsMaskSem);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataEnableStaggeredSpinUpAll - Enables staggared spin-up of all SATA channels
+*
+* DESCRIPTION:
+*       Enables staggared spin-up of all SATA II chnannel. This function is not
+*       relevant for SATA I.
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataEnableStaggeredSpinUpAll(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U8 channelIndex;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataEnableStaggeredSpinUp Failed, Bad adapter data structure" " pointer\n");
+		return MV_FALSE;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d  : Staggered spin-up called for all "
+		 "SATA channels\n", pAdapter->adapterId);
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+
+		mvOsSemTake(&pAdapter->semaphore);
+		_establishSataCommAll(pAdapter);
+		for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) {
+			MV_U32 SStatusReg;
+			SStatusReg = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						       getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET);
+
+			/*
+			 * Fix for 88SX60X1 FEr #10
+			 */
+
+			if ((SStatusReg != 0x0) && (SStatusReg != 0x113) && (SStatusReg != 0x123)) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: SStatusRegs = %x ; "
+					 "retrying communication...", pAdapter->adapterId, channelIndex, SStatusReg);
+				_establishSataComm(pAdapter, channelIndex);
+				SStatusReg = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+							       getEdmaRegOffset(channelIndex) +
+							       MV_SATA_II_S_STATUS_REG_OFFSET);
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: New SStatus is %x\n",
+					 pAdapter->adapterId, channelIndex, SStatusReg);
+
+			}
+			if (((SStatusReg & 0xf) == MV_PHY_DET_STATE_DEVICE_NO_PHY_COM) ||
+			    ((SStatusReg & 0xf) == MV_PHY_DET_STATE_PHY_OFFLINE)) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+					 "Error - failed to establish SATA link after staggered "
+					 "spin up (S Status = %08x)\n", pAdapter->adapterId, channelIndex, SStatusReg);
+			}
+			pAdapter->staggaredSpinup[channelIndex] = MV_TRUE;
+		}
+		mvOsSemRelease(&pAdapter->semaphore);
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK | MV_DEBUG, " %d  : "
+		 "Finished staggered spin-up\n", pAdapter->adapterId);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataEnableStaggeredSpinUp - Enables staggared spin-up.
+*
+* DESCRIPTION:
+*       Enables staggared spin-up of SATA II chnannel. This function is not
+*       relevant for SATA I.
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - the index of the specific EDMA channel
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataEnableStaggeredSpinUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataEnableStaggeredSpinUp Failed, Bad adapter data structure" " pointer\n");
+		return MV_FALSE;
+	}
+	if (channelIndex >= pAdapter->numberOfChannels) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataEnableStaggeredSpinUp Failed, bad channel index\n");
+		return MV_FALSE;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Staggered spin-up called\n",
+		 pAdapter->adapterId, channelIndex);
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		MV_U32 SStatusReg;
+
+		mvOsSemTake(&pAdapter->semaphore);
+		_establishSataComm(pAdapter, channelIndex);
+		SStatusReg = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					       getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET);
+		if (((SStatusReg & 0xf) == MV_PHY_DET_STATE_DEVICE_NO_PHY_COM) ||
+		    ((SStatusReg & 0xf) == MV_PHY_DET_STATE_PHY_OFFLINE)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+				 "Error - failed to establish SATA link after staggered "
+				 "spin up (S Status = %08x)\n", pAdapter->adapterId, channelIndex, SStatusReg);
+		}
+		pAdapter->staggaredSpinup[channelIndex] = MV_TRUE;
+		mvOsSemRelease(&pAdapter->semaphore);
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK | MV_DEBUG, " %d %d: "
+		 "Finished staggered spin-up\n", pAdapter->adapterId, channelIndex);
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataDisableStaggeredSpinUpAll - Disables staggared spin-up on all channels
+*
+* DESCRIPTION:
+*       Disables staggared spin-up of all SATA II chnannel. This function is not
+*       relevant for SATA I.
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataDisableStaggeredSpinUpAll(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U8 channelIndex;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataDisableStaggeredSpinUp Failed, Bad adapter data structure" " pointer\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		/* OK to use mvSataDisableStaggeredSpinUp since it's fast enough */
+		for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++)
+			mvSataDisableStaggeredSpinUp(pAdapter, channelIndex);
+	}
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataDisableStaggeredSpinUp - Disables staggared spin-up.
+*
+* DESCRIPTION:
+*       Disables staggared spin-up of SATA II chnannel. This function is not
+*       relevant for SATA I.
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - the index of the specific EDMA channel
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataDisableStaggeredSpinUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 SControlOffset, regVal;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataDisableStaggeredSpinUp Failed, Bad adapter data structure" " pointer\n");
+		return MV_FALSE;
+	}
+	if (channelIndex >= pAdapter->numberOfChannels) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataDisableStaggeredSpinUp Failed, bad channel index\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		mvOsSemTake(&pAdapter->semaphore);
+		SControlOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_CONTROL_REG_OFFSET;
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset);
+		regVal &= ~0xf;
+		regVal |= MV_PHY_DET_CONTROL_SHUTDOWN;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset, regVal);
+		pAdapter->staggaredSpinup[channelIndex] = MV_FALSE;
+		mvOsSemRelease(&pAdapter->semaphore);
+	}
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataSetInterfaceSpeed - Sets the interface speed of a specific SATA channel
+*
+* DESCRIPTION:
+*       Sets the interface speed of a specific SATA channel (1.5/3 Gbps)
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - the index of the specific EDMA channel
+*
+* RETURN:
+*       MV_SATA_IF_SPEED_1_5 for 1.5 Gbps
+*       MV_SATA_IF_SPEED_3   for 3 Gbps
+*       MV_SATA_IF_SPEED_INVALID if no speed is negotiated
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataSetInterfaceSpeed(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_SATA_IF_SPEED ifSpeed)
+{
+	MV_U32 SStatusOffset;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataSetInterfaceSpeed Failed, Bad adapter data structure" " pointer\n");
+		return MV_FALSE;
+	}
+	if (channelIndex >= pAdapter->numberOfChannels) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataSetInterfaceSpeed Failed, bad channel index\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		MV_SATA_CHANNEL *pSataChannel;
+
+		pSataChannel = pAdapter->sataChannel[channelIndex];
+		if (pSataChannel != NULL) {
+			mvOsSemTake(&pSataChannel->semaphore);
+			if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Error:"
+					 "mvSataSetInterfaceSpeed called while EDMA is active\n",
+					 pAdapter->adapterId, channelIndex);
+				mvOsSemRelease(&pSataChannel->semaphore);
+				return MV_FALSE;
+			}
+			mvOsSemRelease(&pSataChannel->semaphore);
+		}
+
+		SStatusOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET;
+
+		if (ifSpeed == MV_SATA_IF_SPEED_1_5_GBPS) {
+			pAdapter->limitInterfaceSpeed[channelIndex] = MV_TRUE;
+			pAdapter->ifSpeed[channelIndex] = MV_SATA_IF_SPEED_1_5_GBPS;
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK, " %d %d: Set Sata speed to "
+				 "1.5Gbps\n", pAdapter->adapterId, channelIndex);
+		} else if (ifSpeed == MV_SATA_IF_SPEED_3_GBPS) {
+			pAdapter->limitInterfaceSpeed[channelIndex] = MV_TRUE;
+			pAdapter->ifSpeed[channelIndex] = MV_SATA_IF_SPEED_3_GBPS;
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK, " %d %d: Set Sata speed to "
+				 "3Gbps\n", pAdapter->adapterId, channelIndex);
+		} else if (ifSpeed == MV_SATA_IF_SPEED_NO_LIMIT) {
+			pAdapter->limitInterfaceSpeed[channelIndex] = MV_FALSE;
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK, " %d %d: don't limit Sata"
+				 " speed \n", pAdapter->adapterId, channelIndex);
+		} else {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+				 "mvSataSetInterfaceSpeed Failed, bad IF speed\n");
+			return MV_FALSE;
+		}
+
+		mvOsSemTake(&pAdapter->semaphore);
+		if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+			MV_U32 regVal, LPRegVal = 0;
+
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+			if (pAdapter->chipIs65XXZ0 == MV_TRUE) {
+				LPRegVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+							     getEdmaRegOffset(channelIndex) +
+							     MV_SATA_II_LP_EXT_CTRL_REG_OFFSET);
+				LPRegVal &= ~(0xFF << 5);
+			}
+
+			/* according to the spec, bits [31:12] must be set to 0x009B1 */
+			regVal &= 0x00000FFF;
+			/* regVal |= MV_BIT12; */
+			regVal |= 0x009B1000;
+
+			if ((pAdapter->limitInterfaceSpeed[channelIndex] == MV_TRUE) &&
+			    (pAdapter->ifSpeed[channelIndex] == MV_SATA_IF_SPEED_1_5_GBPS)) {
+				regVal &= ~MV_BIT7;	/* Disable GEn II */
+				if (pAdapter->chipIs65XXZ0 == MV_TRUE)
+					LPRegVal &= ~(0xFF << 5);
+			} else {
+				regVal |= MV_BIT7;	/* Enable GEn II */
+				if (pAdapter->chipIs65XXZ0 == MV_TRUE)
+					LPRegVal |= (0x11 << 5);
+			}
+			if (pAdapter->chipIs65XXZ0 == MV_TRUE) {
+				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+						   getEdmaRegOffset(channelIndex) +
+						   MV_SATA_II_LP_EXT_CTRL_REG_OFFSET, LPRegVal);
+			}
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   getEdmaRegOffset(channelIndex) + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+		}
+
+		_channelHardReset(pAdapter, channelIndex);
+		/* If interface is already active, then device detection is needed */
+		if (pAdapter->staggaredSpinup[channelIndex] == MV_TRUE)
+			_establishSataComm(pAdapter, channelIndex);
+
+		mvOsSemRelease(&pAdapter->semaphore);
+		return MV_TRUE;
+	}
+	if ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) &&
+	    ((ifSpeed == MV_SATA_IF_SPEED_NO_LIMIT) || (ifSpeed == MV_SATA_IF_SPEED_1_5_GBPS))) {
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvSataGetInterfaceSpeed - Gets the interface speed of a specific SATA channel
+*
+* DESCRIPTION:
+*       Gets the interface speed of a specific SATA channel (1.5/3 Gbps)
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - the index of the specific EDMA channel
+*
+* RETURN:
+*       MV_SATA_IF_SPEED_1_5 for 1.5 Gbps
+*       MV_SATA_IF_SPEED_3   for 3 Gbps
+*       MV_SATA_IF_SPEED_INVALID if no speed is negotiated
+*
+* COMMENTS:
+*
+*******************************************************************************/
+MV_SATA_IF_SPEED mvSataGetInterfaceSpeed(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 SStatusOffset, regVal;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataGetInterfaceSpeed Failed, Bad adapter data structure" " pointer\n");
+		return MV_SATA_IF_SPEED_INVALID;
+	}
+	if (channelIndex >= pAdapter->numberOfChannels) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataGetInterfaceSpeed Failed, bad channel index\n");
+		return MV_SATA_IF_SPEED_INVALID;
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		if (pAdapter->staggaredSpinup[channelIndex] == MV_TRUE) {
+			SStatusOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET;
+			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SStatusOffset);
+			if (regVal & MV_BIT4)
+				return MV_SATA_IF_SPEED_1_5_GBPS;
+
+			if (regVal & MV_BIT5)
+				return MV_SATA_IF_SPEED_3_GBPS;
+		}
+		return MV_SATA_IF_SPEED_INVALID;
+	}
+	return MV_SATA_IF_SPEED_1_5_GBPS;
+/*TBD*/}
+
+/*******************************************************************************
+* mvSataSetInterfacePowerState - Sets the sata interface power state of a
+* specific SATA channel
+*
+* DESCRIPTION:
+*       Sets the interface power state of a specific SATA channel
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - the index of the specific EDMA channel
+*   ifPowerState    - sata interface power state
+*
+* RETURN:
+*       MV_TRUE if the desired power state entered successfully.
+*       MV_FALSE otherwise
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataSetInterfacePowerState(MV_SATA_ADAPTER *pAdapter,
+					MV_U8 channelIndex, MV_SATA_IF_POWER_STATE ifPowerState)
+{
+	MV_U32 SControlOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_CONTROL_REG_OFFSET;
+	MV_U32 SStatusOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET;
+	MV_U32 SControl;
+	MV_U32 SStatus;
+	MV_U32 IPM;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataSetInterfacePowerState Failed, Bad adapter data structure" " pointer\n");
+		return MV_FALSE;
+	}
+	if (channelIndex >= pAdapter->numberOfChannels) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataSetInterfacePowerState Failed, bad channel index\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_II) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+			 "mvSataSetInterfacePowerState Failed, adapter not supported\n",
+			 pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	if (pAdapter->staggaredSpinup[channelIndex] == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+			 "mvSataSetInterfacePowerState Failed, sata link not established yet\n",
+			 pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	switch (ifPowerState) {
+	case MV_SATA_IF_POWER_PHY_READY:
+		SControl = 0x4300;
+		break;
+	case MV_SATA_IF_POWER_PARTIAL:
+		SControl = 0x1300;
+		break;
+	case MV_SATA_IF_POWER_SLUMBER:
+		SControl = 0x2300;
+		break;
+	default:
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: "
+			 "mvSataSetInterfacePowerState Failed, unkniwn state (0x%x)\n",
+			 pAdapter->adapterId, channelIndex, ifPowerState);
+		return MV_FALSE;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: "
+		 "mvSataSetInterfacePowerState: enter state 0x%x (prev 0x%x)\n",
+		 pAdapter->adapterId, channelIndex, ifPowerState, pAdapter->ifPowerState[channelIndex]);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset, SControl);
+	MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SControlOffset);
+	if (pAdapter->ifPowerState[channelIndex] == MV_SATA_IF_POWER_SLUMBER)
+		mvMicroSecondsDelay(pAdapter, 10000);
+	else
+		mvMicroSecondsDelay(pAdapter, 10);
+
+	SStatus = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SStatusOffset);
+	IPM = getRegField(SStatus, 8, 4);
+	if (IPM != ifPowerState) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: "
+			 "mvSataSetInterfacePowerState: IPM (0x%x) doesn't match the "
+			 "requested state 0x%x (prev 0x%x)\n",
+			 pAdapter->adapterId, channelIndex, IPM, ifPowerState, pAdapter->ifPowerState[channelIndex]);
+		pAdapter->ifPowerState[channelIndex] = MV_SATA_IF_POWER_SLUMBER;
+		return MV_FALSE;
+	}
+	pAdapter->ifPowerState[channelIndex] = ifPowerState;
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataGetInterfacePowerState - Gets the sata interface power state of a
+* specific SATA channel
+*
+* DESCRIPTION:
+*       Gets the interface power state of a specific SATA channel from the HW
+*       registers (SStatus)
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*   channelIndex    - the index of the specific EDMA channel
+*   ifPowerState    - sata interface power state
+*
+* RETURN:
+*       ifPowerState    - sata interface power state
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvSataGetInterfacePowerState(MV_SATA_ADAPTER *pAdapter,
+					MV_U8 channelIndex, MV_SATA_IF_POWER_STATE *ifPowerState)
+{
+	MV_U32 SStatusOffset = getEdmaRegOffset(channelIndex) + MV_SATA_II_S_STATUS_REG_OFFSET;
+
+	MV_U32 SStatus;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataGetInterfacePowerState Failed, Bad adapter data structure" " pointer\n");
+		return MV_FALSE;
+	}
+	if (channelIndex >= pAdapter->numberOfChannels) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : "
+			 "mvSataGetInterfacePowerState Failed, bad channel index\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_II) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+			 "mvSataGetInterfacePowerState Failed, adapter not supported\n",
+			 pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	if (pAdapter->staggaredSpinup[channelIndex] == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: "
+			 "mvSataGetInterfacePowerState Failed, sata link not established yet\n",
+			 pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	SStatus = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, SStatusOffset);
+	*ifPowerState = getRegField(SStatus, 8, 4);
+	return MV_TRUE;
+}
+
+#if defined(MV_SUPPORT_ATAPI) || defined(MV_SATA_C2C_COMM)
+static void activateBMDmaMode(MV_SATA_ADAPTER *pAdapter,
+			      MV_U8 channelIndex, MV_U32 prdTableHi, MV_U32 prdTableLow, MV_UDMA_TYPE dmaType)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+		 " activateBMDmaMode: BMDMA status(1) 0x%08x\n",
+		 MV_REG_READ_DWORD(ioBaseAddr, getEdmaRegOffset(pSataChannel->channelNumber) + MV_BMDMA_STATUS_OFFSET)
+	    );
+	if (pAdapter->hostInterface == MV_HOST_IF_INTEGRATED)
+		_setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + 0x6C, MV_BIT0);
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_BMDMA_COMMAND_OFFSET, 0);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+		 " activateBMDmaMode: BMDMA status(2) 0x%08x\n",
+		 MV_REG_READ_DWORD(ioBaseAddr, getEdmaRegOffset(pSataChannel->channelNumber) + MV_BMDMA_STATUS_OFFSET)
+	    );
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+			   MV_BMDMA_PRD_TABLE_LOW_ADDRESS_OFFSET, prdTableLow);
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+			   MV_BMDMA_PRD_TABLE_HIGH_ADDRESS_OFFSET, prdTableHi);
+
+	if (dmaType == MV_UDMA_TYPE_READ) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Activate BM-DMA in write Mode"
+			 " (Read from disk)\n", pAdapter->adapterId, channelIndex);
+		MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				   MV_BMDMA_COMMAND_OFFSET, MV_BIT3 | MV_BIT0);
+	} else {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Activate BM-DMA in read Mode"
+			 " (Writes to disk)\n", pAdapter->adapterId, channelIndex);
+		MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_BMDMA_COMMAND_OFFSET, MV_BIT0);
+	}
+}
+#endif
+/*================C2C functions==========================================*/
+#ifdef MV_SATA_C2C_COMM
+/*******************************************************************************
+* mvSataC2CInit - setup channel-to-channel communication mode on
+*                   specific SATA channel
+*
+* DESCRIPTION:
+*       Initializes channel for channel-to-channel communication mode
+*
+* INPUT:
+*       pAdapter        - pointer to the adapter data structure.
+*       channelIndex    - the index of the specific SATA channel
+*       mvSataC2CMode   - Comunication mode for the channel:
+*                           target or initiator
+*
+*       mvSataC2CCallBack - callback function called on channel 2 channel
+*                           communication event
+*
+* RETURN:
+*       MV_TRUE on success
+*       MV_FALSE on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataC2CInit(MV_SATA_ADAPTER *pAdapter,
+			 MV_U8 channelIndex, MV_SATA_C2C_MODE mvSataC2CMode, C2CCallBack_t mvSataC2CCallBack)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 regVal;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataC2CInit"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataC2CInit Failed"
+			 ", channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataC2CInit "
+			 "failed, DMA is enabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataC2CInit "
+			 "failed, Feature not supported by this HW\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+
+	regVal = MV_REG_READ_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+	/* Enable communication mode */
+	regVal |= MV_BIT11;
+	/* Fix for 88SX60xx FEr SATA#8 */
+	/* according to the spec, bits [31:12] must be set to 0x009B1 */
+	regVal &= 0x00000FFF;
+	/* regVal |= MV_BIT12; */
+	regVal |= 0x009B1000;
+
+	if (mvSataC2CMode == MV_SATA_C2C_MODE_INITIATOR)
+		regVal |= MV_BIT10;	/* Initiator */
+	else
+		regVal &= ~MV_BIT10;	/* Target */
+
+	maskEdmaInterrupts(pAdapter, channelIndex);
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+
+	_channelHardReset(pAdapter, channelIndex);
+
+	pSataChannel->C2CmodeEnabled = MV_TRUE;
+	pSataChannel->C2CMode = mvSataC2CMode;
+	pSataChannel->C2CCallback = mvSataC2CCallBack;
+
+	mvSataMaskAdapterInterrupt(pAdapter);
+	pAdapter->mainMask |= SaDevInterrutpBit(channelIndex);
+	mvSataUnmaskAdapterInterrupt(pAdapter);
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: mvSataC2CInit %s mode\n",
+		 pAdapter->adapterId, channelIndex,
+		 (mvSataC2CMode == MV_SATA_C2C_MODE_INITIATOR) ? "Initiator" : "Target");
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataC2CStop - Stop channel to channel communication mode
+*
+* DESCRIPTION:
+*       Stop channel to channel communication mode on
+*                   specific SATA channel
+*
+* INPUT:
+*       pAdapter        - pointer to the adapter data structure.
+*       channelIndex    - the index of the specific SATA channel
+*
+* RETURN:
+*       MV_TRUE on success
+*       MV_FALSE on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataC2CStop(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 regVal;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    : mvSataC2CStop"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataC2CStop Failed"
+			 ", channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataC2CStop "
+			 "failed, DMA is enabled\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+
+	regVal = MV_REG_READ_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+	regVal &= ~MV_BIT11;	/* Disable communication mode */
+	/* Fix for 88SX60xx FEr SATA#8 */
+	/* according to the spec, bits [31:12] must be set to 0x009B1 */
+	regVal &= 0x00000FFF;
+	/* regVal |= MV_BIT12; */
+	regVal |= 0x009B1000;
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+	MV_REG_READ_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+	mvSataMaskAdapterInterrupt(pAdapter);
+	pAdapter->mainMask &= ~SaDevInterrutpBit(channelIndex);
+	mvSataUnmaskAdapterInterrupt(pAdapter);
+
+	_channelHardReset(pAdapter, channelIndex);
+	pSataChannel->C2CmodeEnabled = MV_FALSE;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: mvSataC2CStop\n", pAdapter->adapterId, channelIndex);
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvSataC2CSendRegisterDeviceToHostFIS - sends Register device to host FIS
+*
+* DESCRIPTION:
+*                   Sends Register device to host FIS
+*                   used for channel-to-channel communication mode on
+*                   specific SATA channel
+* INPUT:
+*       pAdapter        - pointer to the adapter data structure.
+*       channelIndex    - the index of the specific SATA channel
+*       pmPort          - port multiplier port
+*       bInterrupt      - determine whether the interrupt is being generated on
+*                           the receiver side
+*       msg             - message containing 10 bytes of user data
+*
+* RETURN:
+*       MV_TRUE on success
+*       MV_FALSE on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataC2CSendRegisterDeviceToHostFIS(MV_SATA_ADAPTER *pAdapter,
+						MV_U8 channelIndex,
+						MV_U8 pmPort, MV_BOOLEAN bInterrupt, MV_U8 msg[MV_C2C_MESSAGE_SIZE])
+{
+
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 buffer[5];
+	MV_BOOLEAN res;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d "
+			 "mvSataC2CSendRegisterDeviceToHostFIS failed - "
+			 "Bad adapter data structure pointer.\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d "
+			 "mvSataC2CSendRegisterDeviceToHostFIS failed - "
+			 "channel data structure not allocated.\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+
+	if (pSataChannel->C2CmodeEnabled == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataC2CInitiator"
+			 "mvSataC2CSendRegisterDeviceToHostFIS failed - "
+			 "Bad C2C configuration.\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+
+	buffer[0] = MV_SATA_REGISTER_HOST_2_DEVICE_FIS;
+	buffer[0] |= ((MV_U32) (pmPort & 0xF)) << 8;
+	if (MV_TRUE == bInterrupt)
+		buffer[0] |= 1 << 14;
+
+	buffer[0] |= ((MV_U32) msg[0]) << 24;
+	buffer[1] = msg[1] | ((MV_U32) msg[2]) << 8 | ((MV_U32) msg[3]) << 16 | ((MV_U32) msg[4]) << 24;
+	buffer[2] = msg[5] | ((MV_U32) msg[6]) << 8 | ((MV_U32) msg[7]) << 16;
+	buffer[3] = msg[8] | ((MV_U32) msg[9]) << 8;
+	buffer[4] = 0;
+	res = sendVendorUniqueFIS(pAdapter, channelIndex, (MV_U32 *) buffer, 5);
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return res;
+}
+
+/*******************************************************************************
+* mvSataC2CActivateBmDma - activate B-M DMA
+*
+* DESCRIPTION:
+*       Activates Bus Master DMA for the specific SATA channel
+*
+* INPUT:
+*       pAdapter        - pointer to the adapter data structure.
+*       channelIndex    - the index of the specific EDMA channel
+*       pmPort          - port multiplier port
+*       prdTableHi      - upper 32 bits of PRD table address
+*       prdTableHi      - lower 32 bits of PRD table address
+*       dmaType         - DMA type (read o write) from the initiator point
+*			  of view
+*
+* RETURN:
+*       MV_TRUE on success
+*       MV_FALSE on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataC2CActivateBmDma(MV_SATA_ADAPTER *pAdapter,
+				  MV_U8 channelIndex,
+				  MV_U8 pmPort, MV_U32 prdTableHi, MV_U32 prdTableLow, MV_UDMA_TYPE dmaType)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_BOOLEAN res = MV_TRUE;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d "
+			 "mvSataC2CActivateBmDma failed - "
+			 "Bad adapter data structure pointer.\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d "
+			 "mvSataC2CActivateBmDma failed - "
+			 "channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+	if (pSataChannel->C2CmodeEnabled == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d "
+			 "mvSataC2CActivateBmDma failed - "
+			 "bad C2C configuration.\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	if (pSataChannel->C2CMode == MV_SATA_C2C_MODE_TARGET) {
+		activateBMDmaMode(pAdapter, channelIndex,
+				  prdTableHi, prdTableLow,
+				  (dmaType == MV_UDMA_TYPE_WRITE) ? MV_UDMA_TYPE_READ : MV_UDMA_TYPE_WRITE);
+		if (dmaType == MV_UDMA_TYPE_WRITE) {
+			MV_U32 buffer[1] = { MV_SATA_DMA_ACTIVATE_FIS };
+
+			buffer[0] |= ((MV_U32) (pmPort & 0xF)) << 8;
+			res = sendVendorUniqueFIS(pAdapter, channelIndex, (MV_U32 *) buffer, 1);
+		} else {
+			MV_U32 val = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+						       pAdapter->sataChannel[channelIndex]->eDmaRegsOffset +
+						       MV_SATA_II_IF_CONTROL_REG_OFFSET);
+			val |= MV_BIT16;
+			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+					   pAdapter->sataChannel[channelIndex]->eDmaRegsOffset +
+					   MV_SATA_II_IF_CONTROL_REG_OFFSET, val);
+		}
+	} else {
+		activateBMDmaMode(pAdapter, channelIndex, prdTableHi, prdTableLow, dmaType);
+	}
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return res;
+}
+
+/*******************************************************************************
+* mvSataC2CResetBmDma - reset B-M DMA
+*
+* DESCRIPTION:
+*       Reset Bus Master DMA for the specific SATA channel
+*
+* INPUT:
+*       pAdapter        - pointer to the adapter data structure.
+*       channelIndex    - the index of the specific EDMA channel
+*
+* RETURN:
+*       MV_TRUE on success
+*       MV_FALSE on error
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataC2CResetBmDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d "
+			 "mvSataC2CResetBmDma failed - "
+			 "Bad adapter data structure pointer.\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel)
+		mvOsSemTake(&pSataChannel->semaphore);
+
+	_resetBmDma(pAdapter, channelIndex);
+
+	if (pSataChannel)
+		mvOsSemRelease(&pSataChannel->semaphore);
+
+	return MV_TRUE;
+}
+#endif
+void _resetBmDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	MV_U32 val;
+	MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
+	MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
+	MV_U32 unitCauseAddr = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET;
+
+	/*Reset bm dma */
+	val = MV_REG_READ_DWORD(ioBaseAddr, getEdmaRegOffset(channelIndex) + MV_BMDMA_COMMAND_OFFSET);
+	/*The DMA direction must be preserved */
+	val &= ~MV_BIT0;
+	MV_REG_WRITE_DWORD(ioBaseAddr, getEdmaRegOffset(channelIndex) + MV_BMDMA_COMMAND_OFFSET, val);
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, getEdmaRegOffset(channelIndex) + MV_SATA_II_IF_CONTROL_REG_OFFSET, 0);
+	/*clear BM Done interrupt */
+	MV_REG_WRITE_DWORD(ioBaseAddr, unitCauseAddr, ~(1 << port));
+}
+
+/*******************************************************************************
+* sendVendorUniqueFIS - send vendor unique FIS
+*
+* DESCRIPTION:
+*       Performs vendor unique FIS transmission
+*
+* INPUT:
+*       pAdapter            - pointer to the adapter data structure.
+*       channelIndex        - the index of the specific SATA channel
+*       vendorUniqueBuffer  - data buffer to transmit
+*       numOfDWords         - number of double words in the buffer
+*
+* RETURN:
+*       MV_TRUE on success
+*       MV_FALSE on error
+*
+* COMMENTS:
+*
+*  1. Verify the Transport Layer is in idle, field TransFsmSts in
+*     Serial-ATA Interface Status Register is cleared.
+*  2. Set Vendor Unique Mode. Write 1 to bit VendorUqMd in register
+*     Serial-ATA Interface Control Register.
+*  3. Insert data into Vendor Unique Register.
+*  4. Repeat steps 3 until all data except last Dword in the vendor unique
+*     FIS is transferred. Note that according to Serial-ATA protocol the
+*     FIS length is limited to 8 KB.
+*  5. Write 1 to bit VendorUqSend in register Serial-ATA Interface Control
+*     Register.
+*  6. Write last Dword in the FIS to Complete FIS transmission.
+*  7. Wait for transmission completion. Bit VendorUqDn or bit VendorUqErr
+*     in Serial-ATA Interface Status Register is set to 1.
+*  8. Verify successful transmission of the FIS. Bit VendorUqErr in
+*     Serial-ATA Interface Status Register is cleared.
+*  9. Clear Vendor Unique Mode. Write 0 to bit VendorUqMd in register
+*     Serial-ATA Interface Control Register.
+*******************************************************************************/
+static MV_BOOLEAN sendVendorUniqueFIS(MV_SATA_ADAPTER *pAdapter,
+				      MV_U8 channelIndex, MV_U32 *vendorUniqueBuffer, MV_U8 numOfDWords)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	MV_U32 regVal;
+	MV_U8 i;
+	MV_BOOLEAN res = MV_FALSE;
+
+	regVal = MV_REG_READ_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_IF_STATUS_REG_OFFSET);
+
+	if (regVal & MV_SATA_II_IF_STATUS_FSM_STATUS_MASK) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: ERROR : sendVendorUniqueFIS"
+			 " Transport Layer is not in Idle status\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	/* Set Vendor Unique Mode */
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_IF_CONTROL_REG_OFFSET, MV_BIT8);
+
+	for (i = 1; i < numOfDWords; i++) {
+		MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+				   MV_SATA_II_VENDOR_UQ_REG_OFFSET, vendorUniqueBuffer[i - 1]);
+	}
+
+	/* Write 1 to bit VendorUqSend */
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+			   MV_SATA_II_IF_CONTROL_REG_OFFSET, MV_BIT9 | MV_BIT8);
+
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+			   MV_SATA_II_VENDOR_UQ_REG_OFFSET, vendorUniqueBuffer[i - 1]);
+
+	/* polling with timeout */
+	for (i = 0; i < 200; i++) {
+		regVal = MV_REG_READ_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_IF_STATUS_REG_OFFSET);
+
+		if (regVal & (MV_SATA_II_IF_STATUS_VUQ_DONE_MASK | MV_SATA_II_IF_STATUS_VUQ_ERR_MASK)) {
+			if (regVal & MV_SATA_II_IF_STATUS_VUQ_DONE_MASK) {
+				res = MV_TRUE;
+				break;
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: ERROR"
+					 "sendVendorUniqueFIS operation failed. "
+					 "regVal = 0x%08x\n", pAdapter->adapterId, channelIndex, regVal);
+				break;
+			}
+		}
+		mvMicroSecondsDelay(pAdapter, 1);
+	}
+	/* Clear Vendor Unique Mode */
+	MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_IF_CONTROL_REG_OFFSET, 0);
+
+	if (res != MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: ERROR in sendVendorUniqueFI"
+			 "S operation didn't finish. regVal = 0x%08x\n", pAdapter->adapterId, channelIndex, regVal);
+	}
+	return res;
+}
+
+/*******************************************************************************
+* mvSata60X1B2CheckDevError - check if device errors occurred
+*
+* DESCRIPTION:
+*      This function checks if the drive reported device errors, the 60X1 B2
+*      may not issue error interrupt when the device error reported after
+*      transferring part of the data, this function need to be called every
+*      period of time(e.g 0.5 seconds).
+*
+* INPUT:
+*       pAdapter            - pointer to the adapter data structure.
+*       channelIndex        - the index of the specific SATA channel
+*
+* RETURN:
+*       MV_TRUE if device error is reported
+*       MV_FALSE otherwise
+*
+* COMMENTS:
+*******************************************************************************/
+MV_BOOLEAN mvSata60X1B2CheckDevError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 testCtrlReg;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+			 "    : mvSata60X1B2CheckDevError Failed, Bad adapter " "data structure pointer\n");
+		return MV_FALSE;
+	}
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+			 " %d %d: mvSata60X1B2CheckDevError Failed, channel "
+			 "data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+
+	if ((pAdapter->chipIs60X1B2 == MV_FALSE) ||
+	    (pSataChannel->queueCommandsEnabled == MV_FALSE) ||
+	    (pSataChannel->EdmaActive == MV_FALSE) || (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED)) {
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	mvOsSemRelease(&pSataChannel->semaphore);
+
+	testCtrlReg = MV_REG_READ_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_SATA_II_IF_TEST_CTRL_REG_OFFSET);
+	if (testCtrlReg & 0xFFFF0000) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " %d %d: PortNumDevErr is set 0x%04x\n",
+			 pAdapter->adapterId, channelIndex, (testCtrlReg >> 16) & 0xFFFF);
+		MV_REG_WRITE_DWORD(ioBaseAddr,
+				   pSataChannel->eDmaRegsOffset +
+				   MV_EDMA_COMMAND_REG_OFFSET, MV_EDMA_COMMAND_DISABLE_MASK);
+		handleSelfDisable(pAdapter, channelIndex, MV_BIT7 | MV_BIT2);
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+MV_BOOLEAN mvSataIfD2HReceived(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 port)
+{
+	MV_U32 regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					  edmaRegOffst[channelIndex] + MV_SATA_II_IF_STATUS_REG_OFFSET);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+		 " %d %d: mvSataIfD2HReceived: if status reg %08x\n", pAdapter->adapterId, channelIndex, regVal);
+	if (((regVal & 0xFF) == 0x34) && (((regVal >> 8) & 0xF) == port))
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+#ifdef MV_SATA_IO_GRANULARITY
+
+/*Public functions*/
+
+/*******************************************************************************
+* mvSataEnableIoGranularity - Enable/disable I/O granularity for the specific
+*                             SATA adapter
+*
+* DESCRIPTION:
+*               Enable/disable I/O granularity for the specific
+*               SATA adapter. if IO/granularity is enabled, the function masks
+*               all channel's and channel coalescing interrupts and enables
+*               I/O granularity coalescing interupts
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*       enable    -  MV_TRUE to enable I/O granularity
+*                    MV_FALSE to disable I/O granularity
+*
+* RETURN:
+*       MV_TRUE if succeed
+*       MV_FALSE otherwise
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvSataEnableIoGranularity(MV_SATA_ADAPTER *pAdapter, MV_BOOLEAN enable)
+{
+	MV_U32 i;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d: "
+			 "mvSataEnableIoGranularity Failed, Bad adapter data structure"
+			 " pointer\n", pAdapter->adapterId);
+		return MV_FALSE;
+	}
+	if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_II) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: "
+			 "mvSataEnableIoGranularity Failed, Feature is not supported by HW\n", pAdapter->adapterId);
+		return MV_FALSE;
+	}
+	if (enable) {
+		if (MV_TRUE == pAdapter->iogEnabled)
+			return MV_TRUE;
+
+		mvOsSemTake(&pAdapter->iogSemaphore);
+		for (i = 0; i < MV_IOG_QUEUE_SIZE; i++)
+			pAdapter->iogFreeIdsStack[i] = i;
+
+		pAdapter->iogFreeIdsNum = MV_IOG_QUEUE_SIZE;
+		pAdapter->iogEnabled = MV_TRUE;
+		mvOsSemRelease(&pAdapter->iogSemaphore);
+
+		mvOsSemTake(&pAdapter->interruptsMaskSem);
+		pAdapter->mainMask &= ~(MV_BIT1 | MV_BIT3 | MV_BIT5 | MV_BIT7 |
+					MV_BIT10 | MV_BIT12 | MV_BIT14 | MV_BIT16 | MV_BIT17 | MV_BIT8);
+		pAdapter->mainMask |= MV_IOG_TRANS_INT_MASK;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, pAdapter->mainMask);
+		mvOsSemRelease(&pAdapter->interruptsMaskSem);
+
+	} else {
+		if (MV_FALSE == pAdapter->iogEnabled)
+			return MV_TRUE;
+
+		mvOsSemTake(&pAdapter->interruptsMaskSem);
+		pAdapter->mainMask &= ~MV_IOG_TRANS_INT_MASK;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset, pAdapter->mainMask);
+		mvOsSemRelease(&pAdapter->interruptsMaskSem);
+
+		mvOsSemTake(&pAdapter->iogSemaphore);
+		pAdapter->iogFreeIdsNum = 0;
+		pAdapter->iogEnabled = MV_FALSE;
+		mvOsSemRelease(&pAdapter->iogSemaphore);
+	}
+	return MV_TRUE;
+}
+
+/*Static functions*/
+
+/*******************************************************************************
+* setIoGranularityCount - Set I/O granularity transaction control register.
+*
+* DESCRIPTION:
+*       This function Sets I/O granularity transaction control register for
+*       specific transaction ID
+*
+* INPUT:
+*       pAdapter     - Pointer to the MV88SX60XX adapter data structure.
+*       transId     -  transaction ID
+*       counter     -  I/O granularity counter transaction for current
+*                       transaction Id
+*
+* RETURN:
+*       None
+*
+* COMMENTS:
+*       This function assumes that the channel semaphore is locked.
+*
+*******************************************************************************/
+
+static void setIoGranularityCount(MV_SATA_ADAPTER *pAdapter, MV_U8 transId, MV_U8 counter)
+{
+	MV_U32 offset = MV_IOG_TRANS_CTRL_REG_OFFSET + transId;
+	MV_U8 value = (counter & 0x1F);
+	MV_REG_WRITE_BYTE(pAdapter->adapterIoBaseAddress, offset, value);
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND,
+		 " %d : setIoGranularityCount "
+		 "writing 0x%X to 0x%X, transId = 0x%X\n", pAdapter->adapterId, value, offset, transId);
+}
+
+/*******************************************************************************
+* readIoGranularityCount - Read I/O granularity transaction control register.
+*
+* DESCRIPTION:
+*       This function reads I/O granularity transaction control register for
+*       specific transaction ID
+*
+* INPUT:
+*       pAdapter     - Pointer to the MV88SX60XX adapter data structure.
+*       transId     -  transaction ID
+*
+*
+* RETURN:
+*        I/O granularity counter for transaction Id
+*
+* COMMENTS:
+*       This function assumes that the channel semaphore is locked.
+*
+*******************************************************************************/
+static MV_U8 readIoGranularityCount(MV_SATA_ADAPTER *pAdapter, MV_U8 transId)
+{
+	MV_U32 offset = MV_IOG_TRANS_CTRL_REG_OFFSET + transId;
+	MV_U8 value = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress, offset);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, " %d : readIoGranularityCount "
+		 "reading 0x%X from 0x%X, transId = 0x%X\n", pAdapter->adapterId, value, offset, transId);
+	return value;
+}
+
+/*******************************************************************************
+* checkIogBit - Check bit of I/O granularity cause register.
+*
+* DESCRIPTION:
+*       Checks bits in I/O granularity cause register for completion
+*
+* INPUT:
+*       pAdapter     - Pointer to the MV88SX60XX adapter data structure.
+*       bitOffset    - bit offset in register for current transaction id
+*       value        - register value
+*
+* RETURN:
+*        None
+*
+* COMMENTS:
+*       Assume that is function is called while IO granularity semaphore is
+*       locked
+*******************************************************************************/
+
+static void checkIogBit(MV_SATA_ADAPTER *pAdapter, MV_U8 bitOffset, MV_U8 value)
+{
+	MV_U32 i;
+	MV_U8 id = 0x40;
+	for (i = 0; i < 8; i++) {
+		if ((value >> i) & 0x1) {
+			MV_U8 iogCount;
+			id = bitOffset + i;
+			iogCount = readIoGranularityCount(pAdapter, id);
+			if (iogCount > 0) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
+					 " %d: unexpected IO granularity "
+					 "transaction counter = %d > 0\n", pAdapter->adapterId, iogCount);
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
+					 " %d: IO granularity transaction Id 0x%X done.\n", pAdapter->adapterId, id);
+			}
+			pAdapter->iogFreeIdsStack[pAdapter->iogFreeIdsNum++] = id;
+		}
+	}
+}
+
+/*******************************************************************************
+* checkIogCompletion - Check bit of I/O granularity cause register.
+*
+* DESCRIPTION:
+*       Checks I/O granularity completion
+*
+* INPUT:
+*       pAdapter     - Pointer to the MV88SX60XX adapter data structure.
+*       iogCause     - I/O granularity cause register value
+*       Offset      -  0 if transaction Id is 0-31, 32 if transaction Id 32-63
+*
+* RETURN:
+*        None
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+static void checkIogCompletion(MV_SATA_ADAPTER *pAdapter, MV_U32 iogCause, MV_U8 offset)
+{
+	MV_U32 id;
+	MV_U8 byte;
+
+	if (iogCause & 0xFFFF0000) {
+		byte = (MV_U8) (iogCause >> 24);
+		if (byte)
+			checkIogBit(pAdapter, (offset) + 24, byte);
+
+		byte = (MV_U8) ((iogCause >> 16) & 0xFF);
+		if (byte)
+			checkIogBit(pAdapter, (offset) + 16, byte);
+	}
+	if (iogCause & 0x0000FFFF) {
+		byte = (MV_U8) (iogCause >> 8);
+		if (byte)
+			checkIogBit(pAdapter, (offset) + 8, byte);
+
+		byte = (MV_U8) (iogCause & 0xFF);
+		if (byte)
+			checkIogBit(pAdapter, (offset), byte);
+	}
+}
+
+/*******************************************************************************
+* iogInterrupt - I/O granularity ISR.
+*
+* DESCRIPTION:
+*       Checks bit of I/O granularity cause register for
+*       specific transaction ID
+*
+* INPUT:
+*       pAdapter     - Pointer to the MV88SX60XX adapter data structure.
+*       ioBaseAddr   - SATA Adapter base address
+*       mainCause   - interrupt cause register
+*
+* RETURN:
+*        None
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+static void iogInterrupt(MV_SATA_ADAPTER *pAdapter, MV_BUS_ADDR_T ioBaseAddr, MV_U32 mainCause)
+{
+	MV_U32 iogCauseRegister;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_INTERRUPTS,
+		 " %d: IO Granularity Interrupt." "Cause = 0x%08x", pAdapter->adapterId, mainCause);
+	if (mainCause & MV_IOG_TRANS_LOW_BIT) {
+
+		iogCauseRegister = MV_REG_READ_DWORD(ioBaseAddr, MV_IOG_TRANS_LOW_REG_OFFSET);
+		MV_REG_WRITE_DWORD(ioBaseAddr, MV_IOG_TRANS_LOW_REG_OFFSET, ~iogCauseRegister);
+		if (MV_TRUE == pAdapter->iogEnabled)
+			checkIogCompletion(pAdapter, iogCauseRegister, 0);
+	}
+	if (mainCause & MV_IOG_TRANS_HIGH_BIT) {
+		iogCauseRegister = MV_REG_READ_DWORD(ioBaseAddr, MV_IOG_TRANS_HIGH_REG_OFFSET);
+		MV_REG_WRITE_DWORD(ioBaseAddr, MV_IOG_TRANS_HIGH_REG_OFFSET, ~iogCauseRegister);
+		if (MV_TRUE == pAdapter->iogEnabled)
+			checkIogCompletion(pAdapter, iogCauseRegister, 32);
+	}
+}
+
+/*******************************************************************************
+* iogReset - reset all settings in HW related to I/O granularity.
+*
+* DESCRIPTION:
+*       The function is executed when the error is occured and IO granularity
+*       is enabled for the adapter. The function performs the following
+*       operations
+*       1. IO granularity interrupts are masked
+*       2. Clear IO granularity cause registers
+*       3. Reset all IO granularity transcation counters
+*
+* INPUT:
+*       pAdapter     - Pointer to the MV88SX60XX adapter data structure.
+*
+* RETURN:
+*        None
+*
+* COMMENTS:
+*
+*******************************************************************************/
+
+static MV_BOOLEAN iogReset(MV_SATA_ADAPTER *pAdapter)
+{
+	MV_U32 i;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 " %d: IO Granularity error handler is executed.\n.", pAdapter->adapterId);
+	/*Mask IO Granularity interrupt */
+	mvOsSemTake(&pAdapter->interruptsMaskSem);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
+			   pAdapter->mainMaskOffset, (pAdapter->mainMask & (~MV_IOG_TRANS_INT_MASK)));
+	mvOsSemRelease(&pAdapter->interruptsMaskSem);
+
+	mvOsSemTake(&pAdapter->iogSemaphore);
+	/*Clear IO Granularity cause registers */
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_IOG_TRANS_LOW_REG_OFFSET, 0);
+	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, MV_IOG_TRANS_HIGH_REG_OFFSET, 0);
+
+	/*Set all transaction counters to zero */
+	for (i = 0; i < MV_IOG_QUEUE_SIZE; i += 4) {
+		MV_U32 offset = MV_IOG_TRANS_CTRL_REG_OFFSET + i;
+		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, offset, 0);
+	}
+	mvOsSemRelease(&pAdapter->iogSemaphore);
+}
+
+#endif
+static MV_U32 getRegField(MV_U32 regVal, MV_U32 fieldOff, MV_U32 bitsNum)
+{
+	MV_U32 mask = ((1 << bitsNum) - 1);
+	return (regVal >> fieldOff) & mask;
+}
+
+#ifdef MV_LOGGER
+void _dumpPCIRegs(MV_SATA_ADAPTER *pAdapter)
+{
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d "
+			 "_dumpPCIRegs failed - " "Bad adapter data structure pointer.\n", pAdapter->adapterId);
+		return;
+	}
+	if (pAdapter->hostInterface == MV_HOST_IF_INTEGRATED) {
+		/* no pci interface */
+		return;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d :Dump PCI Regs\n", pAdapter->adapterId);
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "Main interrupt Cause", pAdapter->mainCauseOffset,
+		 MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainCauseOffset));
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "Main interrupt Mask", pAdapter->mainMaskOffset,
+		 MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, pAdapter->mainMaskOffset));
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "SErr Mask", 0xC28, MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0xc28));
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "Error Addr Low", 0x1d40, MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d40));
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "Error Addr High", 0x1d44, MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d44));
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "Error Attr", 0x1d48, MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d48));
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "Error Command", 0x1d50, MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d50));
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "Intr Cause", 0x1d58, MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d58));
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s  %04x %08x\n",
+		 "Intr Mask", 0x1d5c, MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d5c));
+}
+
+void _dumpEDMARegs(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelIndex)
+{
+	MV_U32 regVal, regOff;
+
+	if (pMvSataAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d "
+			 "_dumpEDMARegs failed - "
+			 "Bad adapter data structure pointer.\n", pMvSataAdapter->adapterId, channelIndex);
+		return;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d:Dump Edma HW Regs\n",
+		 pMvSataAdapter->adapterId, channelIndex);
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_CONFIG_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 " EMDA CFG   off 0x%08x val 0x%08x: depth 0x%x NCQ %x BURST SIZE %x "
+		 "eQueue %x Stop On Err %x BURST EXT %x WRITE BURST SIZE %x\n",
+		 regOff, regVal,
+		 getRegField(regVal, 0, 5),
+		 getRegField(regVal, 5, 1),
+		 getRegField(regVal, 8, 1),
+		 getRegField(regVal, 9, 1),
+		 getRegField(regVal, 10, 1), getRegField(regVal, 11, 1), getRegField(regVal, 13, 1));
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Intr Cause off 0x%08x val 0x%08x\n", regOff, regVal);
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Intr Mask  off 0x%08x val 0x%08x\n", regOff, regVal);
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_REQUEST_Q_BAH_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Req AddrHi off 0x%08x val 0x%08x\n", regOff, regVal);
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_REQUEST_Q_INP_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Req INP    off 0x%08x val 0x%08x: INP 0x%x BA 0x%x\n",
+		 regOff, regVal, getRegField(regVal, 5, 5), getRegField(regVal, 10, 22));
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Req OUTP   off 0x%08x val 0x%08x: OUT 0x%x\n",
+		 regOff, regVal, getRegField(regVal, 5, 5));
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Res AddrHi off 0x%08x val 0x%08x\n", regOff, regVal);
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Res INP    off 0x%08x val 0x%08x: INP 0x%x\n",
+		 regOff, regVal, getRegField(regVal, 3, 5));
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Res OUTP   off 0x%08x val 0x%08x: OUTP 0x%x BA 0x%x\n",
+		 regOff, regVal, getRegField(regVal, 3, 5), getRegField(regVal, 8, 24));
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_COMMAND_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Command    off 0x%08x val 0x%08x: EN %x DIS %x HW RESET %x\n",
+		 regOff, regVal, getRegField(regVal, 0, 1), getRegField(regVal, 1, 1), getRegField(regVal, 2, 1));
+
+	regOff = edmaRegOffst[channelIndex] + MV_EDMA_STATUS_REG_OFFSET;
+	regVal = mvSataReadReg(pMvSataAdapter, regOff);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " Status     off 0x%08x val 0x%08x: TAG 0x%x\n",
+		 regOff, regVal, getRegField(regVal, 0, 5));
+
+	if (pMvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) {
+#define PRINT_REG(name, offset)\
+	{\
+		regOff = edmaRegOffst[channelIndex] + (offset);\
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%s      off 0x%08x val 0x%08x\n",\
+				name, regOff, mvSataReadReg(pMvSataAdapter, regOff));\
+	}
+		PRINT_REG("EDMA Halt Conditions Register", 0x60);
+		PRINT_REG("EDMA FSM Debug Status Register", 0x084);
+		PRINT_REG("EDMA Busy Status Register", 0x88);
+		PRINT_REG("EDMA TCQ Status Register", 0x08c);
+		PRINT_REG("EDMA Rx FIS Parser Register", 0x090);
+		PRINT_REG("EDMA NCQ0 Done/TCQ0 Outstanding Status Register", 0x098);
+		PRINT_REG("EDMA NCQ1 Done/TCQ1 Outstanding Status Register", 0x09c);
+		PRINT_REG("EDMA NCQ2 Done/TCQ2 Outstanding Status Register", 0x0a0);
+		PRINT_REG("EDMA NCQ3 Done/TCQ3 Outstanding Status Register", 0x0a4);
+		PRINT_REG("EDMA Interrupt Error 2 Cause Register", 0x064);
+		PRINT_REG("FIS Interrupt Cause Register", 0x364);
+		PRINT_REG("FIS Interrupt Mask  Register", 0x368);
+		PRINT_REG("FIS DW0 Register", 0x370);
+		PRINT_REG("FIS DW1 Register", 0x374);
+		PRINT_REG("FIS DW2 Register", 0x378);
+		PRINT_REG("FIS DW3 Register", 0x37c);
+		PRINT_REG("FIS DW4 Register", 0x380);
+		PRINT_REG("FIS DW5 Register", 0x384);
+		PRINT_REG("FIS DW6 Register", 0x388);
+
+	}
+
+}
+
+void _dumpChannelQueues(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_U32 i;
+	MV_U32 entries = MV_EDMA_QUEUE_LENGTH;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d "
+			 "_dumpChannelQueues failed - "
+			 "Bad adapter data structure pointer.\n", pAdapter->adapterId, channelIndex);
+		return;
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d:Dump Channel Queues\n",
+		 pAdapter->adapterId, channelIndex);
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: _dumpChannelQueues"
+			 "el Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return;
+	}
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Request Qeueu Info:\n");
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " virt addr %p:\n", pSataChannel->requestQueue);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " phy low addr %08x:\n",
+		 pSataChannel->requestQueuePciLowAddress);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " phy high addr %08x:\n",
+		 pSataChannel->requestQueuePciHiAddress);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " SW IN pointer %x:\n", pSataChannel->reqInPtr);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Request Qeueu Entries:\n");
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Index [3:0]       [7:4]       [11:8]       [15:12]\n");
+	if (pSataChannel->use128Entries == MV_TRUE)
+		entries = MV_EDMA_GEN2E_QUEUE_LENGTH;
+
+	for (i = 0; i < entries; i++) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 "[%2d] 0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x  0x%08x\n", i,
+			 *((MV_U32 *) (pSataChannel->requestQueue + i)),
+			 *(((MV_U32 *) (pSataChannel->requestQueue + i)) + 1),
+			 *(((MV_U32 *) (pSataChannel->requestQueue + i)) + 2),
+			 *(((MV_U32 *) (pSataChannel->requestQueue + i)) + 3),
+			 *(((MV_U32 *) (pSataChannel->requestQueue + i)) + 4),
+			 *(((MV_U32 *) (pSataChannel->requestQueue + i)) + 5),
+			 *(((MV_U32 *) (pSataChannel->requestQueue + i)) + 6),
+			 *(((MV_U32 *) (pSataChannel->requestQueue + i)) + 7));
+	}
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Responset Qeueu Info:\n");
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " virt addr %p:\n", pSataChannel->responseQueue);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " phy low addr %08x:\n",
+		 pSataChannel->responseQueuePciLowAddress);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " phy high addr %08x:\n",
+		 pSataChannel->responseQueuePciHiAddress);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " SW OUT pointer %x:\n", pSataChannel->rspOutPtr);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Response Qeueu Entries:\n");
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Index [1:0]   [3:2]   [7:4]\n");
+	for (i = 0; i < entries; i++) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 "[%2d] 0x%04x  0x%04x  0x%08x\n", i,
+			 *((MV_U16 *) (pSataChannel->responseQueue + i)),
+			 *(((MV_U16 *) (pSataChannel->responseQueue + i)) + 1),
+			 *(((MV_U32 *) (pSataChannel->responseQueue + i)) + 1));
+	}
+}
+
+void _dumpSataRegs(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_U32 regVal;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d "
+			 "_dumpSataRegs failed - "
+			 "Bad adapter data structure pointer.\n", pAdapter->adapterId, channelIndex);
+		return;
+	}
+
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   edmaRegOffst[channelIndex] + MV_SATA_II_S_STATUS_REG_OFFSET);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " SStatus  0x%08x:\n", regVal);
+
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   edmaRegOffst[channelIndex] + MV_SATA_II_S_CONTROL_REG_OFFSET);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " SControl 0x%08x:\n", regVal);
+
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   edmaRegOffst[channelIndex] + MV_SATA_II_S_ERROR_REG_OFFSET);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " SError    0x%08x:\n", regVal);
+
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   edmaRegOffst[channelIndex] + MV_SATA_II_IF_CONTROL_REG_OFFSET);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " IF Ctrl  0x%08x: TXPort 0x%x\n", regVal, getRegField(regVal, 0, 4));
+		regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
+					   edmaRegOffst[channelIndex] + MV_SATA_II_IF_STATUS_REG_OFFSET);
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 " IF status 0x%08x: RXFIS 0x%x RXPort 0x%x\n", regVal,
+			 getRegField(regVal, 0, 8), getRegField(regVal, 8, 4));
+	}
+}
+
+void _printATARegs(MV_STORAGE_DEVICE_REGISTERS *pDeviceRegs)
+{
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " ATA Drive Registers:\n");
+	if (pDeviceRegs == NULL)
+		return;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n", "Error", pDeviceRegs->errorRegister);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+		 "%20s : %04x\n", "SectorCount", pDeviceRegs->sectorCountRegister);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n", "LBA Low", pDeviceRegs->lbaLowRegister);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n", "LBA Mid", pDeviceRegs->lbaMidRegister);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n", "LBA High", pDeviceRegs->lbaHighRegister);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n", "Device", pDeviceRegs->deviceRegister);
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%20s : %04x\n", "Status", pDeviceRegs->statusRegister);
+}
+
+#endif /*MV_LOGGER */
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSata.h b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSata.h
new file mode 100755
index 0000000..823684e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSata.h
@@ -0,0 +1,684 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvSata.h - Header File for mvSata.c.
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       mvOs.h
+*       ATA/ATAPI-6 standard
+*
+*******************************************************************************/
+#ifndef __INCmvSatah
+#define __INCmvSatah
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+/* Includes */
+#include "mvOsS.h"
+#include "mvRegs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+/* Definitions */
+#define MV_CORE_DRIVER_LOG_ID                   0
+/* MV88SX50XX specific defines */
+#define MV_SATA_VENDOR_ID                       0x11AB
+#define MV_SATA_DEVICE_ID_5080                  0x5080
+#define MV_SATA_DEVICE_ID_5081                  0x5081
+#define MV_SATA_DEVICE_ID_5040                  0x5040
+#define MV_SATA_DEVICE_ID_5041                  0x5041
+#define MV_SATA_DEVICE_ID_6041                  0x6041
+#define MV_SATA_DEVICE_ID_6081                  0x6081
+#define MV_SATA_DEVICE_ID_6042                  0x6042
+#define MV_SATA_DEVICE_ID_7042                  0x7042
+#define MV_SATA_DEVICE_ID_5182                  0x5182	/*88F5182 integrated sata */
+#define MV_SATA_DEVICE_ID_5082                  0x5082	/*88F5082 integrated sata */
+#define MV_SATA_DEVICE_ID_6082                  0x6082	/* Same device ID for 6082L */
+#define MV_SATA_DEVICE_ID_6490                  0x6490	/*64660 integrated sata */
+#define MV_SATA_DEVICE_ID_78XX0                 0x7800	/*78x00 Z0/Y0 integrated sata */
+#define MV_SATA_DEVICE_ID_78100                 0x7810	/*78100 integrated sata */
+#define MV_SATA_DEVICE_ID_78200                 0x7820	/*78200 integrated sata */
+#define MV_SATA_DEVICE_ID_76100                 0x7610	/*76100 integrated sata */
+#define MV_SATA_DEVICE_ID_6323                  0x6323	/*6323 integrated sata */
+#define MV_SATA_DEVICE_ID_6281                 0x6281	/*88f6281 integrated sata */
+#define MV_SATA_DEVICE_ID_6282                 0x1155	/*88f6282 integrated sata */
+#define MV_SATA_DEVICE_ID_6192                 0x6192	/*88f6192 integrated sata */
+#define MV_SATA_DEVICE_ID_6190                 0x6190	/*88f6190 integrated sata */
+#define MV_SATA_DEVICE_ID_6781                 0x6781	/*88f6781 integrated sata */
+#define MV_SATA_DEVICE_ID_6550		       0x6550	/*88f6550 integrated sata */
+#define MV_SATA_DEVICE_ID_6560		       0x6560	/*88f6560 integrated sata */
+#define MV_SATA_CHANNELS_NUM                    8
+#define MV_SATA_UNITS_NUM                       2
+#define MV_SATA_5082_PORT_NUM                   1
+#define MV_SATA_5182_PORT_NUM                   2
+#define MV_SATA_6082_PORT_NUM                   1
+#define MV_SATA_6490_PORT_NUM                   1
+#define MV_SATA_6281_PORT_NUM                   2
+#define MV_SATA_6282_PORT_NUM                   2
+#define MV_SATA_6192_PORT_NUM                   2
+#define MV_SATA_6190_PORT_NUM                   1
+#define MV_SATA_6781_PORT_NUM                   1
+#define MV_SATA_78XX0_PORT_NUM                  2
+#define MV_SATA_76100_PORT_NUM                  1
+#define MV_SATA_6323_PORT_NUM                   1
+#define MV_SATA_65XX_PORT_NUM			1
+#define MV_SATA_PM_MAX_PORTS                    15
+#define MV_SATA_PM_CONTROL_PORT                 15
+#define MV_EDMA_QUEUE_LENGTH                    32	/* Up to 32 outstanding  */
+#define MV_EDMA_GEN2E_QUEUE_LENGTH              128
+/* commands per SATA channel*/
+#ifndef MV_SATA_OVERRIDE_SW_QUEUE_SIZE
+#define MV_SATA_SW_QUEUE_SIZE                   (MV_EDMA_QUEUE_LENGTH - 1)
+#else
+#define MV_SATA_SW_QUEUE_SIZE                   MV_SATA_REQUESTED_SW_QUEUE_SIZE
+#endif
+#ifdef MV_SATA_SUPPORT_GEN2E_128_QUEUE_LEN
+#ifndef MV_SATA_OVERRIDE_GEN2E_SW_QUEUE_SIZE
+#define MV_SATA_GEN2E_SW_QUEUE_SIZE                   (MV_EDMA_GEN2E_QUEUE_LENGTH - 1)
+#else
+#define MV_SATA_GEN2E_SW_QUEUE_SIZE                   MV_SATA_REQUESTED_GEN2E_SW_QUEUE_SIZE
+#endif
+#else
+#define MV_SATA_GEN2E_SW_QUEUE_SIZE         (MV_SATA_SW_QUEUE_SIZE)
+#endif
+#if ((MV_SATA_SW_QUEUE_SIZE) >= (MV_EDMA_QUEUE_LENGTH))
+#error "FATAL ERROR: Bad Value for MV_SATA_SW_QUEUE_SIZE "
+#endif
+#if ((MV_SATA_GEN2E_SW_QUEUE_SIZE) >= (MV_EDMA_GEN2E_QUEUE_LENGTH))
+#error "FATAL ERROR: Bad Value for MV_EDMA_GEN2E_QUEUE_LENGTH "
+#endif
+#if ((MV_SATA_SW_QUEUE_SIZE) > (MV_SATA_GEN2E_SW_QUEUE_SIZE))
+#error "FATAL ERROR: MV_SATA_SW_QUEUE_SIZE bigger than MV_EDMA_GEN2E_QUEUE_LENGTH"
+#endif
+#if (((MV_SATA_GEN2E_SW_QUEUE_SIZE) * 4) > ((MV_SATA_SW_QUEUE_SIZE) * 8))
+#define _MV_SATA_COMMANDS_PER_ADAPTER ((MV_SATA_GEN2E_SW_QUEUE_SIZE) * 4)
+#else
+#define _MV_SATA_COMMANDS_PER_ADAPTER ((MV_SATA_SW_QUEUE_SIZE) * 8)
+#endif
+#define MV_EDMA_QUEUE_MASK                      0x1F
+#define MV_EDMA_REQUEST_ENTRY_SIZE              32
+#define MV_EDMA_RESPONSE_ENTRY_SIZE             8
+#define MV_EDMA_REQUEST_QUEUE_SIZE              1024	/* 32*32 = 1KBytes */
+#define MV_EDMA_RESPONSE_QUEUE_SIZE             256	/* 32*8 = 256 Bytes */
+#define MV_EDMA_GEN2E_QUEUE_MASK                      0x7F
+#define MV_EDMA_GEN2E_REQUEST_QUEUE_SIZE              4096	/* 128*32 = 4KBytes */
+#define MV_EDMA_GEN2E_RESPONSE_QUEUE_SIZE             1024	/* 128*8 = 1KBytes */
+#define MV_EDMA_PRD_ENTRY_SIZE                  16	/* 16Bytes */
+#define MV_EDMA_PRD_NO_SNOOP_FLAG               MV_BIT0
+#define MV_EDMA_PRD_EOT_FLAG                    MV_BIT15
+#define MV_ATA_IDENTIFY_DEV_DATA_LENGTH         256	/* number of words(2 byte) */
+#define MV_ATA_MODEL_NUMBER_LEN                 40
+#define ATA_SECTOR_SIZE                         512
+#define ATA_SECTOR_SIZE_IN_WORDS                256
+#define MV_SATA_COMM_INIT_DELAY                 1000	/*1000 us */
+#define MV_SATA_COMM_INIT_WAIT_DELAY            20000	/*20 ms */
+/*Channel to Channel*/
+#ifdef MV_SATA_C2C_COMM
+#define MV_SATA_REGISTER_HOST_2_DEVICE_FIS         0x00000034
+#define MV_SATA_DMA_ACTIVATE_FIS                   0x00000039
+#define MV_C2C_MESSAGE_SIZE                        10
+#endif
+#ifdef MV_SATA_IO_GRANULARITY
+#define MV_IOG_QUEUE_SIZE           0x40
+#define MV_IOG_INVALID_COMMAND_ID   MV_IOG_QUEUE_SIZE
+#endif
+/* Typedefs    */
+    typedef enum mvUdmaType {
+	MV_UDMA_TYPE_READ, MV_UDMA_TYPE_WRITE
+} MV_UDMA_TYPE;
+
+typedef enum mvFlushType {
+	MV_FLUSH_TYPE_CALLBACK, MV_FLUSH_TYPE_NONE
+} MV_FLUSH_TYPE;
+
+typedef enum mvCompletionType {
+	MV_COMPLETION_TYPE_NORMAL, MV_COMPLETION_TYPE_ERROR,
+	MV_COMPLETION_TYPE_ABORT
+} MV_COMPLETION_TYPE;
+
+typedef enum mvEventType {
+	MV_EVENT_TYPE_ADAPTER_ERROR, MV_EVENT_TYPE_SATA_CABLE,
+	MV_EVENT_TYPE_SATA_ERROR
+} MV_EVENT_TYPE;
+
+typedef enum mvSataCableEvent {
+	MV_SATA_CABLE_EVENT_DISCONNECT = 0,
+	MV_SATA_CABLE_EVENT_CONNECT,
+	MV_SATA_CABLE_EVENT_PM_HOT_PLUG
+} MV_SATA_CABLE_EVENT;
+
+typedef enum mvSataErrorEvent {
+	MV_SATA_RECOVERABLE_COMMUNICATION_ERROR = 0,
+	MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR,
+	MV_SATA_DEVICE_ERROR
+} MV_SATA_ERROR_EVENT;
+
+#ifdef MV_SATA_C2C_COMM
+typedef enum mvC2CEventType {
+	MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_DONE,
+	MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_ERROR,
+	MV_C2C_BM_DMA_DONE,
+	MV_C2C_BM_DMA_ERROR,
+} MV_C2C_EVENT_TYPE;
+#endif
+
+typedef enum mvEdmaMode {
+	MV_EDMA_MODE_QUEUED,
+	MV_EDMA_MODE_NOT_QUEUED,
+	MV_EDMA_MODE_NATIVE_QUEUING
+} MV_EDMA_MODE;
+
+typedef enum mvQueueCommandResult {
+	MV_QUEUE_COMMAND_RESULT_OK = 0,
+	MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED,
+	MV_QUEUE_COMMAND_RESULT_FULL,
+	MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS,
+	MV_QUEUE_COMMAND_RESULT_BAD_PARAMS
+} MV_QUEUE_COMMAND_RESULT;
+
+typedef enum mvNonUdmaProtocol {
+	MV_NON_UDMA_PROTOCOL_NON_DATA,
+	MV_NON_UDMA_PROTOCOL_PIO_DATA_IN,
+	MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT,
+	MV_NON_UDMA_PROTOCOL_PACKET_PIO_NON_DATA,
+	MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN,
+	MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT,
+	MV_NON_UDMA_PROTOCOL_PACKET_DMA,
+	MV_NON_UDMA_PROTOCOL_UNKNOWN
+} MV_NON_UDMA_PROTOCOL;
+
+typedef enum mvSataGeneration {
+	MV_SATA_GEN_I, MV_SATA_GEN_II, MV_SATA_GEN_IIE
+} MV_SATA_GEN;
+
+typedef enum mvSataInterfaceSpeed {
+	MV_SATA_IF_SPEED_1_5_GBPS, MV_SATA_IF_SPEED_3_GBPS,
+	MV_SATA_IF_SPEED_NO_LIMIT, MV_SATA_IF_SPEED_INVALID
+} MV_SATA_IF_SPEED;
+
+typedef enum mvSataInterfacePowerState {
+	MV_SATA_IF_POWER_PHY_READY = 1, MV_SATA_IF_POWER_PARTIAL = 2,
+	MV_SATA_IF_POWER_SLUMBER = 6
+} MV_SATA_IF_POWER_STATE;
+
+#ifdef MV_SATA_C2C_COMM
+typedef enum mvSataC2CMode {
+	MV_SATA_C2C_MODE_INITIATOR, MV_SATA_C2C_MODE_TARGET
+} MV_SATA_C2C_MODE;
+#endif
+
+typedef enum mvSataDeviceType {
+	MV_SATA_DEVICE_TYPE_UNKNOWN = 0,
+	MV_SATA_DEVICE_TYPE_ATA_DISK,
+	MV_SATA_DEVICE_TYPE_ATAPI_DEVICE,
+	MV_SATA_DEVICE_TYPE_PM
+} MV_SATA_DEVICE_TYPE;
+
+typedef enum mvPMSwitchingmode {
+	MV_SATA_SWITCHING_MODE_NONE = 0,
+	MV_SATA_SWITCHING_MODE_CBS,
+	MV_SATA_SWITCHING_MODE_QCBS,
+	MV_SATA_SWITCHING_MODE_FBS,
+} MV_SATA_SWITCHING_MODE;
+
+struct mvDmaRequestQueueEntry;
+struct mvDmaResponseQueueEntry;
+struct mvDmaCommandEntry;
+
+struct mvSataAdapter;
+struct mvStorageDevRegisters;
+struct mvSataChannel;
+
+typedef MV_BOOLEAN(*mvSataCommandCompletionCallBack_t) (struct mvSataAdapter *,
+							MV_U8,
+							MV_COMPLETION_TYPE,
+							MV_VOID_PTR, MV_U16, MV_U32, struct mvStorageDevRegisters *);
+#ifdef MV_SATA_C2C_COMM
+typedef MV_BOOLEAN(*C2CCallBack_t) (struct mvSataAdapter *,
+				    struct mvSataChannel *, MV_C2C_EVENT_TYPE event, MV_U32 msgSize, MV_U8 *msg);
+
+#endif
+
+typedef enum mvQueuedCommandType {
+	MV_QUEUED_COMMAND_TYPE_UDMA,
+	MV_QUEUED_COMMAND_TYPE_NONE_UDMA,
+	MV_QUEUED_COMMAND_TYPE_PACKET
+} MV_QUEUED_COMMAND_TYPE;
+
+#ifdef MV_SATA_IO_GRANULARITY
+typedef enum mvIogQueuedCommandType {
+	MV_IOG_COMMAND_TYPE_FIRST,
+	MV_IOG_COMMAND_TYPE_NEXT
+} MV_IOG_COMMAND_TYPE;
+#endif
+
+typedef enum mvSataInterruptScheme {
+	MV_SATA_INTERRUPT_HANDLING_IN_ISR,
+	MV_SATA_INTERRUPT_HANDLING_IN_TASK,
+	MV_SATA_INTERRUPTS_DISABLED
+} MV_SATA_INTERRUPT_SCHEME;
+
+typedef struct mvUdmaCommandParams {
+	MV_UDMA_TYPE readWrite;
+	MV_BOOLEAN isEXT;
+	MV_BOOLEAN FUA;
+	MV_U32 lowLBAAddress;
+	MV_U16 highLBAAddress;
+	MV_U16 numOfSectors;
+	MV_U32 prdLowAddr;
+	MV_U32 prdHighAddr;
+#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION
+	MV_BOOLEAN singleDataRegion;
+	MV_U16 byteCount;
+#endif
+	mvSataCommandCompletionCallBack_t callBack;
+	MV_VOID_PTR commandId;
+#ifdef MV_SATA_IO_GRANULARITY
+	MV_BOOLEAN ioGranularityEnabled;
+	MV_IOG_COMMAND_TYPE iogCommandType;
+	union {
+		MV_U8 transId;
+		MV_U8 transCount;
+	} ioGranularityCommandParam;
+	MV_U8 iogCurrentTransId;
+#endif
+} MV_UDMA_COMMAND_PARAMS;
+
+typedef struct mvNoneUdmaCommandParams {
+	MV_NON_UDMA_PROTOCOL protocolType;
+	MV_BOOLEAN isEXT;
+	MV_U16_PTR bufPtr;
+	MV_U32 count;
+	MV_U16 features;
+	MV_U16 sectorCount;
+	MV_U16 lbaLow;
+	MV_U16 lbaMid;
+	MV_U16 lbaHigh;
+	MV_U8 device;
+	MV_U8 command;
+	mvSataCommandCompletionCallBack_t callBack;
+	MV_VOID_PTR commandId;
+} MV_NONE_UDMA_COMMAND_PARAMS;
+
+typedef struct mvPacketCommandParams {
+	MV_NON_UDMA_PROTOCOL protocolType;
+	MV_U16_PTR bufPtr;
+	MV_U32 buffer_len;
+	MV_U32 transfered_data;
+	MV_U8 cdb_len;
+	MV_U16_PTR cdb_buffer;	/*SCSI command desciptor block */
+	MV_U8 flags;		/* bit 0:1-> DMA write */
+	/* bit 1:1-> single Data Region */
+	MV_U32 prdLowAddr;
+	MV_U32 prdHighAddr;
+	mvSataCommandCompletionCallBack_t callBack;
+	MV_VOID_PTR commandId;
+} MV_PACKET_COMMAND_PARAMS;
+
+typedef struct mvQueueCommandInfo {
+	MV_QUEUED_COMMAND_TYPE type;
+	MV_U8 PMPort;
+	union {
+		MV_UDMA_COMMAND_PARAMS udmaCommand;
+		MV_NONE_UDMA_COMMAND_PARAMS NoneUdmaCommand;
+		MV_PACKET_COMMAND_PARAMS packetCommand;
+	} commandParams;
+} MV_QUEUE_COMMAND_INFO;
+
+/* The following structure is for the Core Driver internal usage */
+typedef struct mvQueuedCommandEntry {
+	MV_BOOLEAN isFreeEntry;
+	/*MV_U8        commandTag; */
+	MV_U8 hostTag;
+	MV_U8 deviceTag;
+	MV_BOOLEAN isCommandInEdma:1;
+	MV_BOOLEAN commandAborted:1;
+	struct mvQueuedCommandEntry *next;
+	struct mvQueuedCommandEntry *prev;
+	MV_QUEUE_COMMAND_INFO *pCommandInfo;
+#ifndef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
+	MV_QUEUE_COMMAND_INFO commandInfo;
+#endif
+} MV_QUEUED_COMMAND_ENTRY;
+
+typedef enum mvErrorHandlingState {
+	MV_ERROR_HANDLING_STATE_IDLE,
+	MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS,
+	MV_ERROR_HANDLING_STATE_WAIT_FOR_BUSY,
+	MV_ERROR_HANDLING_STATE_REQUEST_SENSE
+} MV_ERROR_HANDLING_STATE;
+
+typedef struct {
+	MV_ERROR_HANDLING_STATE state;
+	MV_U16 PortsWithErrors;	/*which ports reported errors */
+	MV_U8 CurrPort;
+	MV_QUEUED_COMMAND_ENTRY *pReadLogExtEntry;
+	MV_U16_PTR ReadLogExtBuffer;
+	MV_BOOLEAN useVendorUniqGen2WA;
+} MV_ERROR_HANDLING_INFO;
+
+/*for internal usage*/
+#define MV_SATA_TAGS_PER_POOL                   32
+#ifdef MV_SATA_SUPPORT_GEN2E_128_QUEUE_LEN
+#define MV_SATA_GEN2E_TAG_POOLS_NUM         (MV_SATA_PM_MAX_PORTS + 1)
+#define MV_SATA_GEN2E_TAG_PMPORT_MASK       0x0F
+#else
+#define MV_SATA_GEN2E_TAG_POOLS_NUM         1
+#define MV_SATA_GEN2E_TAG_PMPORT_MASK       0x00
+#endif
+
+struct _mvTagsStack {
+	MV_U8 *pTagsArray;
+	MV_U8 top;
+};
+struct _mvChannelTags {
+	struct _mvTagsStack HostTagsPool;
+	struct _mvTagsStack DeviceTagsPool[MV_SATA_GEN2E_TAG_POOLS_NUM];
+	MV_U8 HostTags[MV_SATA_GEN2E_SW_QUEUE_SIZE];
+	MV_U8 DeviceTags[MV_SATA_GEN2E_TAG_POOLS_NUM][MV_SATA_TAGS_PER_POOL];
+};
+
+typedef enum mvHostInterfase {
+	MV_HOST_IF_INTEGRATED,	/*as in 5182 */
+	MV_HOST_IF_PEX,
+	MV_HOST_IF_PCI		/*PCI/PCI-X */
+} MV_HOST_IF;
+
+/* The following structures are part of the Core Driver API */
+typedef struct mvSataChannel {
+	/* Fields set by Intermediate Application Layer */
+	MV_U8 channelNumber;
+	struct mvDmaRequestQueueEntry *requestQueue;
+	struct mvDmaResponseQueueEntry *responseQueue;
+	MV_U32 requestQueuePciHiAddress;
+	MV_U32 requestQueuePciLowAddress;
+	MV_U32 responseQueuePciHiAddress;
+	MV_U32 responseQueuePciLowAddress;
+	/* DRQ Data Block size in sectors, Core Driver sets a default value of 1 */
+	/* sector in mvSataConfigureChannel */
+	MV_U8 DRQDataBlockSize;
+	/* Fields set by CORE driver */
+	struct mvSataAdapter *mvSataAdapter;
+	MV_OS_SEMAPHORE semaphore;
+	MV_U32 eDmaRegsOffset;
+	MV_BOOLEAN EdmaActive;
+	MV_EDMA_MODE queuedDMA;
+	MV_U8 outstandingCommands;
+	MV_U8 portQueuedCommands[MV_SATA_PM_MAX_PORTS + 1];
+	struct mvQueuedCommandEntry *commandsQueue;
+	struct mvQueuedCommandEntry *commandsQueueHead;
+	struct mvQueuedCommandEntry *commandsQueueTail;
+	MV_BOOLEAN queueCommandsEnabled;
+	MV_U8 noneUdmaOutstandingCommands;
+#ifdef MV_SUPPORT_ATAPI
+	MV_U8 packetOutstandingCommands;
+	MV_BOOLEAN waitForBMDMA;
+#endif
+	MV_U8 EdmaQueuedCommands;
+	MV_U8 commandsQueueSize;
+	struct _mvChannelTags Tags;
+	MV_U8 reqInPtr;
+	MV_U8 rspOutPtr;
+	MV_U8 EDMAQueuePtrMask;
+	MV_U32 EDMARequestInpMask;
+	/* Port Multiplier fiels */
+	MV_BOOLEAN PMSupported;
+	MV_SATA_DEVICE_TYPE deviceType;
+	MV_BOOLEAN FBSEnabled;
+	MV_BOOLEAN use128Entries;
+#ifdef MV_SATA_C2C_COMM
+
+	/* Channel 2 Channel */
+	MV_BOOLEAN C2CmodeEnabled;
+	MV_SATA_C2C_MODE C2CMode;
+	C2CCallBack_t C2CCallback;
+#endif
+	MV_U8 recoveredErrorsCounter;
+	/* NCQ error handling */
+	MV_ERROR_HANDLING_INFO ErrorHandlingInfo;
+} MV_SATA_CHANNEL;
+
+typedef struct mvSataAdapter {
+	/* Fields set by Intermediate Application Layer */
+	MV_U32 adapterId;
+	MV_VOID_PTR IALData;
+	MV_U8 pciConfigRevisionId;
+	MV_U16 pciConfigDeviceId;
+	MV_BUS_ADDR_T adapterIoBaseAddress;
+	MV_U32 intCoalThre[MV_SATA_UNITS_NUM];
+	MV_U32 intTimeThre[MV_SATA_UNITS_NUM];
+	MV_BOOLEAN (*mvSataEventNotify) (struct mvSataAdapter *, MV_EVENT_TYPE, MV_U32, MV_U32);
+	MV_SATA_CHANNEL *sataChannel[MV_SATA_CHANNELS_NUM];
+	MV_U32 pciCommand;
+	MV_U32 pciSerrMask;
+	MV_U32 pciInterruptMask;
+
+	/* Fields set by CORE driver */
+	MV_SATA_GEN sataAdapterGeneration;
+	MV_BOOLEAN staggaredSpinup[MV_SATA_CHANNELS_NUM];	/* For 60x1 only */
+	MV_BOOLEAN limitInterfaceSpeed[MV_SATA_CHANNELS_NUM];	/* For 60x1 only */
+	MV_SATA_IF_SPEED ifSpeed[MV_SATA_CHANNELS_NUM];	/* For 60x1 only */
+	MV_SATA_IF_POWER_STATE ifPowerState[MV_SATA_CHANNELS_NUM];
+	MV_U8 numberOfChannels;	/* 4 channels for 504x, 8 for 508x */
+	MV_U8 numberOfUnits;	/* 1 for 504x, 2 for 508x */
+	MV_U8 portsPerUnit;
+	MV_OS_SEMAPHORE semaphore;
+	MV_U32 mainMask;
+	MV_U32 mainMaskOffset;
+	MV_U32 mainCauseOffset;
+	MV_HOST_IF hostInterface;
+	MV_BOOLEAN interruptsAreMasked;
+	MV_SATA_INTERRUPT_SCHEME interruptsScheme;
+	MV_OS_SEMAPHORE interruptsMaskSem;
+	MV_BOOLEAN chipIs50XXB0;
+	MV_BOOLEAN chipIs50XXB2;
+	MV_BOOLEAN chipIs60X1B2;
+	MV_BOOLEAN chipIs60X1C0;
+	MV_BOOLEAN chipIs62X1Z0;
+	MV_BOOLEAN chipIs65XXZ0;
+	MV_U8 signalAmps[MV_SATA_CHANNELS_NUM];
+	MV_U8 pre[MV_SATA_CHANNELS_NUM];
+	struct mvQueuedCommandEntry adapterCommands[_MV_SATA_COMMANDS_PER_ADAPTER];
+#ifdef MV_SATA_IO_GRANULARITY
+	MV_BOOLEAN iogEnabled;
+	MV_U8 iogFreeIdsStack[MV_IOG_QUEUE_SIZE];
+	MV_U8 iogFreeIdsNum;
+	MV_OS_SEMAPHORE iogSemaphore;
+#endif
+} MV_SATA_ADAPTER;
+
+/* this structure used by the IAL defines the PRD entries used by the EDMA HW */
+typedef struct mvSataEdmaPRDEntry {
+	volatile MV_U32 lowBaseAddr;
+	volatile MV_U16 byteCount;
+	volatile MV_U16 flags;
+	volatile MV_U32 highBaseAddr;
+	volatile MV_U32 reserved;
+} MV_SATA_EDMA_PRD_ENTRY;
+
+/* API Functions */
+
+/* CORE driver Adapter Management */
+MV_BOOLEAN mvSataInitAdapter(MV_SATA_ADAPTER *pAdapter);
+
+MV_BOOLEAN mvSataShutdownAdapter(MV_SATA_ADAPTER *pAdapter);
+
+MV_U32 mvSataReadReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset);
+
+MV_VOID mvSataWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset, MV_U32 regValue);
+
+/* CORE driver SATA Channel Management */
+MV_BOOLEAN mvSataConfigureChannel(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataRemoveChannel(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataIsStorageDeviceConnected(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U32 *SStatus);
+
+MV_BOOLEAN mvSataIfD2HReceived(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 port);
+
+MV_BOOLEAN mvSataChannelHardReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataSetFBSMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			    MV_BOOLEAN enableFBS, MV_BOOLEAN useQueueLen128);
+
+MV_BOOLEAN mvSataConfigEdmaMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+				MV_EDMA_MODE eDmaMode, MV_U8 maxQueueDepth);
+
+MV_BOOLEAN mvSataEnableChannelDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataDisableChannelDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataFlushDmaQueue(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_FLUSH_TYPE flushType);
+
+MV_U8 mvSataNumOfDmaCommands(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_U8 mvSataGetNumOfPortQueuedCommands(MV_SATA_ADAPTER *pAdapter,
+				       MV_U8 channelIndex, MV_U8 PMPort, MV_U8 *pCommandsPerChannel);
+
+MV_BOOLEAN mvSataSetIntCoalParams(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, MV_U32 intCoalThre, MV_U32 intTimeThre);
+
+MV_BOOLEAN mvSataSetChannelPhyParams(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 signalAmps, MV_U8 pre);
+
+MV_BOOLEAN mvSataChannelPhyShutdown(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataChannelPhyPowerOn(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataChannelFarLoopbackDiagnostic(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+/* Queue ATA command */
+MV_QUEUE_COMMAND_RESULT mvSataQueueCommand(MV_SATA_ADAPTER *pAdapter,
+					   MV_U8 channelIndex, MV_QUEUE_COMMAND_INFO *pCommandParams);
+
+/* Interrupt Service Routine */
+MV_BOOLEAN mvSataInterruptServiceRoutine(MV_SATA_ADAPTER *pAdapter);
+
+MV_BOOLEAN mvSataMaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter);
+
+MV_BOOLEAN mvSataUnmaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter);
+
+MV_BOOLEAN mvSataCheckPendingInterrupt(MV_SATA_ADAPTER *pAdapter);
+
+MV_BOOLEAN mvSataSetInterruptsScheme(MV_SATA_ADAPTER *pAdapter, MV_SATA_INTERRUPT_SCHEME interruptScheme);
+
+/*
+ * Staggered spin-ip support and SATA interface speed control
+ * (relevant for 60x1 adapters)
+ */
+MV_BOOLEAN mvSataEnableStaggeredSpinUpAll(MV_SATA_ADAPTER *pAdapter);
+
+MV_BOOLEAN mvSataEnableStaggeredSpinUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataDisableStaggeredSpinUpAll(MV_SATA_ADAPTER *pAdapter);
+
+MV_BOOLEAN mvSataDisableStaggeredSpinUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataSetInterfaceSpeed(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_SATA_IF_SPEED ifSpeed);
+
+MV_SATA_IF_SPEED mvSataGetInterfaceSpeed(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataSetInterfacePowerState(MV_SATA_ADAPTER *pAdapter,
+					MV_U8 channelIndex, MV_SATA_IF_POWER_STATE ifPowerState);
+
+MV_BOOLEAN mvSataGetInterfacePowerState(MV_SATA_ADAPTER *pAdapter,
+					MV_U8 channelIndex, MV_SATA_IF_POWER_STATE *ifPowerState);
+
+/* Command Completion and Event Notification (user implemented) */
+MV_BOOLEAN mvSataEventNotify(MV_SATA_ADAPTER *, MV_EVENT_TYPE, MV_U32, MV_U32);
+#ifdef MV_SATA_C2C_COMM
+
+/* Channel 2 Channel communication */
+MV_BOOLEAN mvSataC2CInit(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			 MV_SATA_C2C_MODE mvSataC2CMode, C2CCallBack_t mvSataC2CCallBack);
+
+MV_BOOLEAN mvSataC2CStop(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN mvSataC2CSendRegisterDeviceToHostFIS(MV_SATA_ADAPTER *pAdapter,
+						MV_U8 channelIndex,
+						MV_U8 pmPort,
+						MV_BOOLEAN bInterrupt, MV_U8 message[MV_C2C_MESSAGE_SIZE]);
+
+MV_BOOLEAN mvSataC2CActivateBmDma(MV_SATA_ADAPTER *pAdapter,
+				  MV_U8 channelIndex,
+				  MV_U8 pmPort, MV_U32 prdTableHi, MV_U32 prdTableLow, MV_UDMA_TYPE dmaType);
+
+MV_BOOLEAN mvSataC2CResetBmDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+#endif
+
+#ifdef MV_SATA_IO_GRANULARITY
+
+MV_BOOLEAN mvSataEnableIoGranularity(MV_SATA_ADAPTER *pAdapter, MV_BOOLEAN enable);
+
+#endif
+MV_BOOLEAN mvSata60X1B2CheckDevError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_STATUS mvSataWinInit(MV_UNIT_WIN_INFO *addrWinMap);
+MV_STATUS mvSataWinRead(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+MV_STATUS mvSataWinWrite(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INCmvSatah */
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataAddrDec.c b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataAddrDec.c
new file mode 100755
index 0000000..9d530b7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataAddrDec.c
@@ -0,0 +1,379 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvRegs.h"
+#include "mvSata.h"
+#include "mvSysSataConfig.h"
+
+/* Address decoding regs.	*/
+
+#define MV_SATA_WIN_CTRL_REG(dev, win)        (MV_SATA_REGS_BASE + 0x30 + ((win)<<4))
+#define MV_SATA_WIN_BASE_REG(dev, win)        (MV_SATA_REGS_BASE + 0x34 + ((win)<<4))
+
+/* BITs in Bridge Interrupt Cause and Mask registers */
+#define MV_SATA_ADDR_DECODE_ERROR_BIT        0
+#define MV_SATA_ADDR_DECODE_ERROR_MASK       (1<<MV_SATA_ADDR_DECODE_ERROR_BIT)
+
+/* BITs in Windows 0-3 Control and Base Registers */
+#define MV_SATA_WIN_ENABLE_BIT               0
+#define MV_SATA_WIN_ENABLE_MASK              (1<<MV_SATA_WIN_ENABLE_BIT)
+
+#define MV_SATA_WIN_TARGET_OFFSET            4
+#define MV_SATA_WIN_TARGET_MASK              (0xF<<MV_SATA_WIN_TARGET_OFFSET)
+
+#define MV_SATA_WIN_ATTR_OFFSET              8
+#define MV_SATA_WIN_ATTR_MASK                (0xFF<<MV_SATA_WIN_ATTR_OFFSET)
+
+#define MV_SATA_WIN_SIZE_OFFSET              16
+#define MV_SATA_WIN_SIZE_MASK                (0xFFFF<<MV_SATA_WIN_SIZE_OFFSET)
+
+#define MV_SATA_WIN_BASE_OFFSET              16
+#define MV_SATA_WIN_BASE_MASK                (0xFFFF<<MV_SATA_WIN_BASE_OFFSET)
+
+#define MV_SATA_WIN_SIZE_ALIGN		    _64K
+
+MV_TARGET sataAddrDecPrioTab[] = {
+#if defined(MV_INCLUDE_SDRAM_CS0)
+	SDRAM_CS0,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS1)
+	SDRAM_CS1,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS2)
+	SDRAM_CS2,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS3)
+	SDRAM_CS3,
+#endif
+#if defined(MV_INCLUDE_PEX)
+	PEX0_MEM,
+#endif
+	TBL_TERM
+};
+
+/*******************************************************************************
+* sataWinOverlapDetect - Detect SATA address windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviur is expected in case SATA address decode
+*       windows overlapps.
+*       This function detects SATA address decode windows overlapping of a
+*       specified window. The function does not check the window itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS sataWinOverlapDetect(int dev, MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 winNumIndex;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	for (winNumIndex = 0; winNumIndex < MV_SATA_MAX_ADDR_DECODE_WIN; winNumIndex++) {
+		/* Do not check window itself       */
+		if (winNumIndex == winNum)
+			continue;
+
+		/* Get window parameters    */
+		if (MV_OK != mvSataWinRead(dev, winNumIndex, &addrDecWin)) {
+			mvOsPrintf("%s: ERR. mvSataWinGet failed\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled windows    */
+		if (addrDecWin.enable == MV_FALSE)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+			return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvSataWinWrite - Set SATA target address window
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0)
+*       address window, also known as address decode window.
+*       After setting this target window, the SATA will be able to access the
+*       target within the address window.
+*
+* INPUT:
+*       winNum      - SATA target address decode window number.
+*       pAddrDecWin - SATA target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if address window overlapps with other address decode windows.
+*       MV_BAD_PARAM if base address is invalid parameter or target is
+*       unknown.
+*
+*******************************************************************************/
+MV_STATUS mvSataWinWrite(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+
+	/* Parameter checking   */
+	if (winNum >= MV_SATA_MAX_ADDR_DECODE_WIN) {
+		mvOsPrintf("%s: ERR. Invalid win num %d\n", __func__, winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlapps with current windows         */
+	if (MV_TRUE == sataWinOverlapDetect(dev, winNum, &pAddrDecWin->addrWin)) {
+		mvOsPrintf("%s: ERR. Window %d overlap\n", __func__, winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) {
+		mvOsPrintf("mvSataWinSet:Error setting SATA window %d.\n"
+			   "Address 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	baseReg = pAddrDecWin->addrWin.baseLow & MV_SATA_WIN_BASE_MASK;
+	sizeReg = (pAddrDecWin->addrWin.size / MV_SATA_WIN_SIZE_ALIGN) - 1;
+	sizeReg = sizeReg << MV_SATA_WIN_SIZE_OFFSET;
+
+	/* set attributes */
+	sizeReg &= ~MV_SATA_WIN_ATTR_MASK;
+	sizeReg |= (pAddrDecWin->attrib << MV_SATA_WIN_ATTR_OFFSET);
+
+	/* set target ID */
+	sizeReg &= ~MV_SATA_WIN_TARGET_MASK;
+	sizeReg |= (pAddrDecWin->targetId << MV_SATA_WIN_TARGET_OFFSET);
+
+	if (pAddrDecWin->enable == MV_TRUE)
+		sizeReg |= MV_SATA_WIN_ENABLE_MASK;
+	else
+		sizeReg &= ~MV_SATA_WIN_ENABLE_MASK;
+
+	MV_REG_WRITE(MV_SATA_WIN_CTRL_REG(dev, winNum), sizeReg);
+	MV_REG_WRITE(MV_SATA_WIN_BASE_REG(dev, winNum), baseReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSataWinRead - Get SATA peripheral target address window.
+*
+* DESCRIPTION:
+*       Get SATA peripheral target address window.
+*
+* INPUT:
+*       winNum - SATA target address decode window number.
+*
+* OUTPUT:
+*       pAddrDecWin - SATA target window data structure.
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvSataWinRead(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+	MV_U32 sizeRegVal;
+
+	/* Parameter checking   */
+	if (winNum >= MV_SATA_MAX_ADDR_DECODE_WIN) {
+		mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", __func__, dev, winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	baseReg = MV_REG_READ(MV_SATA_WIN_BASE_REG(dev, winNum));
+	sizeReg = MV_REG_READ(MV_SATA_WIN_CTRL_REG(dev, winNum));
+
+	/* Extract base address and size    */
+	sizeRegVal = (sizeReg & MV_SATA_WIN_SIZE_MASK) >> MV_SATA_WIN_SIZE_OFFSET;
+	pAddrDecWin->addrWin.size = (sizeRegVal + 1) * MV_SATA_WIN_SIZE_ALIGN;
+	pAddrDecWin->addrWin.baseLow = baseReg & MV_SATA_WIN_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh = 0;
+
+	/* attrib and targetId              */
+	pAddrDecWin->attrib = (sizeReg & MV_SATA_WIN_ATTR_MASK) >> MV_SATA_WIN_ATTR_OFFSET;
+	pAddrDecWin->targetId = (sizeReg & MV_SATA_WIN_TARGET_MASK) >> MV_SATA_WIN_TARGET_OFFSET;
+
+	/* Check if window is enabled       */
+	if (sizeReg & MV_SATA_WIN_ENABLE_MASK)
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+	return MV_OK;
+}
+
+#if 0
+/*******************************************************************************
+* mvSataAddrDecShow - Print the SATA address decode map.
+*
+* DESCRIPTION:
+*		This function print the SATA address decode map.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+MV_VOID mvSataAddrDecShow(MV_VOID)
+{
+	MV_SATA_DEC_WIN win;
+	int i, j;
+
+	for (j = 0; j < MV_SATA_MAX_CHAN; j++) {
+		if (MV_FALSE == mvCtrlPwrClckGet(SATA_UNIT_ID, j))
+			return;
+
+		mvOsOutput("\n");
+		mvOsOutput("SATA %d:\n", j);
+		mvOsOutput("----\n");
+
+		for (i = 0; i < MV_SATA_MAX_ADDR_DECODE_WIN; i++) {
+			memset(&win, 0, sizeof(MV_SATA_DEC_WIN));
+
+			mvOsOutput("win%d - ", i);
+
+			if (mvSataWinGet(j, i, &win) == MV_OK) {
+				if (win.enable) {
+					mvOsOutput("%s base %08x, ",
+						   mvCtrlTargetNameGet(win.target), win.addrWin.baseLow);
+					mvOsOutput("....");
+
+					mvSizePrint(win.addrWin.size);
+
+					mvOsOutput("\n");
+				} else
+					mvOsOutput("disable\n");
+			}
+		}
+	}
+}
+#endif
+
+/*******************************************************************************
+* mvSataWinInit - Initialize the integrated SATA target address window.
+*
+* DESCRIPTION:
+*       Initialize the SATA peripheral target address window.
+*
+* INPUT:
+*
+*
+* OUTPUT:
+*
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvSataWinInit(MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 winNum;
+	MV_UNIT_WIN_INFO *addrDecWin;
+	MV_U32 winPrioIndex = 0;
+
+	/* Initiate Sata address decode */
+
+	/* First disable all address decode windows */
+	for (winNum = 0; winNum < MV_SATA_MAX_ADDR_DECODE_WIN; winNum++) {
+		MV_U32 regVal = MV_REG_READ(MV_SATA_WIN_CTRL_REG(0, winNum));
+		regVal &= ~MV_SATA_WIN_ENABLE_MASK;
+		MV_REG_WRITE(MV_SATA_WIN_CTRL_REG(0, winNum), regVal);
+	}
+
+	winNum = 0;
+	while ((sataAddrDecPrioTab[winPrioIndex] != TBL_TERM) && (winNum < MV_SATA_MAX_ADDR_DECODE_WIN)) {
+		addrDecWin = &addrWinMap[sataAddrDecPrioTab[winPrioIndex]];
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvSataWinWrite(0 /*dev */ , winNum, addrDecWin))
+				return MV_ERROR;
+
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataSoc.c b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataSoc.c
new file mode 100755
index 0000000..2668aca
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataSoc.c
@@ -0,0 +1,106 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvSataSoc.h"
+#include "mvRegs.h"
+
+/* Calculate the base address of the registers for a SATA channel */
+static MV_U32 edmaRegOffst[8] = { 0x22000, 0x24000, 0x26000, 0x28000,
+	0x32000, 0x34000, 0x36000, 0x38000
+};
+
+#define getEdmaRegOffset(x) edmaRegOffst[(x)]
+
+MV_BOOL mvSataPhyShutdown(MV_U8 port)
+{
+	MV_U32 regVal;
+	MV_U32 adapterIoBaseAddress = MV_SATA_REGS_OFFSET - 0x20000;
+
+	regVal = MV_REG_READ(adapterIoBaseAddress + getEdmaRegOffset(port) + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+	/* Fix for 88SX60x1 FEr SATA#8 */
+	/* according to the spec, bits [31:12] must be set to 0x009B1 */
+	regVal &= 0x00000FFF;
+	/* regVal |= MV_BIT12; */
+	regVal |= 0x009B1000;
+
+	regVal |= BIT9;
+	MV_REG_WRITE(adapterIoBaseAddress + getEdmaRegOffset(port) + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+	return MV_TRUE;
+}
+
+MV_BOOL mvSataPhyPowerOn(MV_U8 port)
+{
+	MV_U32 adapterIoBaseAddress = MV_SATA_REGS_OFFSET - 0x20000;
+
+	MV_U32 regVal = MV_REG_READ(adapterIoBaseAddress + getEdmaRegOffset(port) + MV_SATA_II_SATA_CONFIG_REG_OFFSET);
+	/* Fix for 88SX60x1 FEr SATA#8 */
+	/* according to the spec, bits [31:12] must be set to 0x009B1 */
+	regVal &= 0x00000FFF;
+	/* regVal |= MV_BIT12; */
+	regVal |= 0x009B1000;
+
+	regVal &= ~(BIT9);
+	MV_REG_WRITE(adapterIoBaseAddress + getEdmaRegOffset(port) + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal);
+	return MV_TRUE;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataSoc.h b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataSoc.h
new file mode 100755
index 0000000..aba2058
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvSataSoc.h
@@ -0,0 +1,83 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCmvSataSoch
+#define __INCmvSataSoch
+
+#ifdef __cplusplus
+extern "C"			/*{ */
+#endif				/* __cplusplus */
+#include "mvCommon.h"
+#include "mvRegs.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysSataConfig.h"
+ MV_BOOL mvSataPhyShutdown(MV_U8 port);
+MV_BOOL mvSataPhyPowerOn(MV_U8 port);
+
+#ifdef __cplusplus
+
+/*}*/
+#endif /* __cplusplus */
+
+#endif /* __INCmvSatah */
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvStorageDev.c b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvStorageDev.c
new file mode 100755
index 0000000..0655b81
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvStorageDev.c
@@ -0,0 +1,1835 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvStorageDev.c - C File for implementation of the core driver.
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*   mvOs.h
+*   mvSata.h.
+*   mvStorageDev.h
+*   mvRegs.h
+*
+*******************************************************************************/
+#include "mvSataSoc.h"
+#include "mvOsS.h"
+#include "mvSata.h"
+#include "mvStorageDev.h"
+#include "mvRegs.h"
+
+/* Defines */
+
+/* functions for internal driver use */
+MV_BOOLEAN waitWhileStorageDevIsBusy(MV_SATA_ADAPTER *pAdapter,
+				     MV_BUS_ADDR_T ioBaseAddr, MV_U32 eDmaRegsOffset, MV_U32 loops, MV_U32 delayParam);
+MV_BOOLEAN waitForDRQToClear(MV_SATA_ADAPTER *pAdapter,
+			     MV_BUS_ADDR_T ioBaseAddr, MV_U32 eDmaRegsOffset, MV_U32 loops, MV_U32 delayParam);
+
+void enableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel);
+void disableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel);
+static MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel);
+void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter,
+			    MV_U8 channelIndex, MV_BOOLEAN isEXT, MV_STORAGE_DEVICE_REGISTERS *pRegisters);
+MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel);
+extern void _setActivePMPort(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort);
+extern void disableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+MV_BOOLEAN _PMAccessReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue,
+			MV_STORAGE_DEVICE_REGISTERS *registerStruct, MV_BOOLEAN isRead);
+
+MV_BOOLEAN executeNonUDMACommand(MV_SATA_ADAPTER *pAdapter,
+				 MV_U8 channelIndex,
+				 MV_U8 PMPort,
+				 MV_NON_UDMA_PROTOCOL protocolType,
+				 MV_BOOLEAN isEXT,
+				 MV_U16_PTR bufPtr, MV_U32 count,
+				 MV_U16 features,
+				 MV_U16 sectorCount,
+				 MV_U16 lbaLow, MV_U16 lbaMid, MV_U16 lbaHigh, MV_U8 device, MV_U8 command);
+
+MV_BOOLEAN waitWhileStorageDevIsBusy_88SX60X1(MV_SATA_ADAPTER *pAdapter,
+					      MV_BUS_ADDR_T ioBaseAddr,
+					      MV_U32 eDmaRegsOffset, MV_U8 channelIndex,
+					      MV_U32 loops, MV_U32 delayParam);
+
+MV_BOOLEAN waitForDRQ(MV_SATA_ADAPTER *pAdapter,
+		      MV_BUS_ADDR_T ioBaseAddr, MV_U32 eDmaRegsOffset, MV_U32 loops, MV_U32 delayParam);
+
+void _startSoftResetDevice(MV_SATA_CHANNEL *pSataChannel);
+MV_BOOLEAN _isDeviceBsyBitOff(MV_SATA_CHANNEL *pSataChannel);
+/*******************************************************************************
+* waitWhileStorageDevIsBusy - Wait for the storage device to be released from
+*                             busy state.
+*
+* DESCRIPTION:
+*   The busy bit is set to one to indicate that the storage device is busy. The
+*   busy bit shall be set to one by the device only when one of the following
+*   events occurs:
+*
+*   1) after either the negation of RESET- or the setting of the SRST bit to one
+*      in the Device Control register.
+*   2) after writing the Command register if the DRQ bit is not set to one.
+*   3) between blocks of a data transfer during PIO data-in commands before the
+*      DRQ bit is cleared to zero.
+*   4) after the transfer of a data block during PIO data-out commands before
+*      the DRQ bit is cleared to zero.
+*   5) during the data transfer of DMA commands either the BSY bit, the DRQ bit,
+*      or both shall be set to one.
+*   6) after the command packet is received during the execution of a PACKET
+*      command.
+*
+* INPUT:
+*     ioBaseAddr     - The PCI I/O window base address of the adapter.
+*     eDmaRegsOffset - The EDMA register's offset of the relevant SATA channel.
+*     loops          - max number of times to pool the status register.
+*     delay          - number of u seconds to wait each loop.
+*
+* RETURN:
+*     MV_TRUE if the device is released from busy state, MV_FALSE otherwise.
+* COMMENTS:
+*     None.
+*
+*******************************************************************************/
+MV_BOOLEAN waitWhileStorageDevIsBusy(MV_SATA_ADAPTER *pAdapter,
+				     MV_BUS_ADDR_T ioBaseAddr, MV_U32 eDmaRegsOffset, MV_U32 loops, MV_U32 delayParam)
+{
+	MV_U8 ATAstatus = 0;
+	MV_U32 i;
+
+	for (i = 0; i < loops; i++) {
+		ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+		if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) {
+
+			if ((ATAstatus & MV_ATA_ERROR_STATUS) == 0) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *"
+					 "%d usecs\n", i, delayParam);
+				return MV_TRUE;
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "waitWhileStorageDevIsBusy<FAILED>: Device ERROR" " Status: 0x%02x\n",
+					 ATAstatus);
+				return MV_FALSE;
+			}
+		}
+		mvMicroSecondsDelay(pAdapter, delayParam);
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+		 "waitWhileStorageDevIsBusy<FAILED>: Time out - Device ERROR" " Status: 0x%02x. loops %d, delay %d\n",
+		 ATAstatus, loops, delayParam);
+
+	return MV_FALSE;
+}
+
+MV_BOOLEAN waitWhileStorageDevIsBusy_88SX60X1(MV_SATA_ADAPTER *pAdapter,
+					      MV_BUS_ADDR_T ioBaseAddr,
+					      MV_U32 eDmaRegsOffset, MV_U8 channelIndex,
+					      MV_U32 loops, MV_U32 delayParam)
+{
+	MV_U8 ATAstatus = 0;
+	MV_U32 i, intReg;
+	MV_U8 sataUnit = channelIndex >> 2, portNum = (channelIndex & 0x3);
+
+	for (i = 0; i < loops; i++) {
+		intReg = MV_REG_READ_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+					   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET);
+
+		if (intReg & (1 << (8 + portNum))) {
+			ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+			MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+					   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(1 << (8 + portNum)));
+			if ((ATAstatus & MV_ATA_ERROR_STATUS) == 0) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *"
+					 "%d usecs\n", i, delayParam);
+				return MV_TRUE;
+			} else {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "waitWhileStorageDevIsBusy<FAILED>: Device ERROR" " Status: 0x%02x\n",
+					 ATAstatus);
+				return MV_FALSE;
+			}
+		}
+		mvMicroSecondsDelay(pAdapter, delayParam);
+	}
+	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "waitWhileStorageDevIsBusy<FAILED>: Time out - Device ERROR"
+		 " Status: 0x%02x. loops %d, delay %d\n", ATAstatus, loops, delayParam);
+	return MV_FALSE;
+}
+
+MV_BOOLEAN waitForDRQ(MV_SATA_ADAPTER *pAdapter,
+		      MV_BUS_ADDR_T ioBaseAddr, MV_U32 eDmaRegsOffset, MV_U32 loops, MV_U32 delayParam)
+{
+	MV_U8 ATAstatus = 0;
+	MV_U32 i;
+
+	for (i = 0; i < loops; i++) {
+		ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+		if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) {
+			if (ATAstatus & MV_ATA_DATA_REQUEST_STATUS) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *"
+					 "%d usecs\n", i, delayParam);
+				return MV_TRUE;
+			}
+		}
+		mvMicroSecondsDelay(pAdapter, delayParam);
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+		 "waitWhileStorageDevIsBusy<FAILED>: Time out - Device ERROR" " Status: 0x%02x. loops %d, delay %d\n",
+		 ATAstatus, loops, delayParam);
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* enableStorageDevInterrupt - Enable the storage device to be able to issue
+*                       interrupt.
+*
+* DESCRIPTION:
+*   Enable the connected storage device to the given channel to assert INTRQ by
+*   clearing nIEN bit in the Device Control register.
+*
+* INPUT:
+*   pSataChannel - Pointer to the Sata channel data structure.
+*
+* RETURN:
+*   None.
+*
+* COMMENTS:
+*   this function also clears the SRST bit in the Device Control register.
+*
+*******************************************************************************/
+void enableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel)
+{
+
+	MV_REG_WRITE_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+			  pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET, 0);
+	MV_REG_READ_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+			 pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET);
+}
+
+/*******************************************************************************
+* disableStorageDevInterrupt - Disable the storage device to be able to issue
+*                              interrupt.
+*
+* DESCRIPTION:
+*   This function disable the connected storage device to the given channel to
+*   assert INTRQ by setting nIEN bit in the Device Control register.
+*
+* INPUT:
+*   pSataChannel - Pointer to the Sata channel data structure.
+*
+* RETURN:
+*   None.
+*
+* COMMENTS:
+*   this function also clears the SRST bit
+*
+*******************************************************************************/
+void disableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel)
+{
+
+	MV_REG_WRITE_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+			  pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT1);
+	MV_REG_READ_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
+			 pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+}
+
+/*******************************************************************************
+* isStorageDevReadyForPIO - Check that the storage device connected to the given
+*                           channel and the channel itself are ready to perform
+*                           PIO commands.
+*
+* DESCRIPTION:
+*   Check if the device connected to the given channel and the channel itself
+*   are ready for PIO commands.
+*
+* INPUT:
+*       pSataChannel - Pointer to the SATA channel data structure.
+*
+* RETURN:
+*       MV_TRUE if the channel and the connected device ready to do PIO,
+*       MV_FALSE otherwise.
+*
+* COMMENTS:
+*     If the adapter's eEnEDMA bit in the EDMA Command Register is set, PIO
+*     commands cannot be issued. The eEnEDMA bit cannot be reset by the CPU.
+*     Only the EDMA resets it, when bit eDsEDMA is set or when an error
+*     condition occurs.
+*
+*******************************************************************************/
+static MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+	MV_U8 ATAcontrolRegValue;
+
+	/* If the adapter's eEnEDMA bit in the EDMA Command Register is set  */
+	/* PIO commands cannot be issued.                                       */
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: PIO command failed:"
+			 "EDMA is active\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		return MV_FALSE;
+	}
+	/* Check if BUSY bit is '0' */
+
+	/* Reading the Control register actually gives us the Alternate Status  */
+	/* register content (ATA protocol). If the busy bit is set in the       */
+	/* Alternate Status register, we wait for 50 mili-sec and try again, if */
+	/* the busy bit is still set, we return false indicating that the       */
+	/* device is not ready for PIO commands.                                */
+	ATAcontrolRegValue = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET);
+	if ((ATAcontrolRegValue & MV_ATA_BUSY_STATUS) != 0) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  control regiser is "
+			 "0x%02x\n", pSataChannel->mvSataAdapter->adapterId,
+			 pSataChannel->channelNumber, ATAcontrolRegValue);
+		return MV_FALSE;
+	}
+	if ((pSataChannel->deviceType != MV_SATA_DEVICE_TYPE_ATAPI_DEVICE) &&
+	    ((ATAcontrolRegValue & MV_ATA_READY_STATUS) != MV_ATA_READY_STATUS)) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  storage drive is not"
+			 " ready, ATA STATUS=0x%02x\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ATAcontrolRegValue);
+		return MV_FALSE;
+	}
+	/* The device is ready for PIO commands */
+	return MV_TRUE;
+}
+
+MV_BOOLEAN mvStorageDevATAIdleImmediate(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 eDmaRegsOffset;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvStorageDevATAIdentif"
+			 "yDevice failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {	/* If the pointer do not exists, retrun false */
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  channel data "
+			 "structure is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+
+	mvOsSemTake(&pSataChannel->semaphore);
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  mvStorageDevATAIdle"
+			 "Immediate command failed: EDMA is active\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Issue IDLE IMMEDIATE COMMAND\n");
+	disableStorageDevInterrupt(pSataChannel);
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_COMMAND_REG_OFFSET, MV_ATA_COMMAND_IDLE_IMMEDIATE);
+
+	if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 10000, 100) == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  Idle Immediate failed\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+
+		enableStorageDevInterrupt(pSataChannel);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+
+	enableStorageDevInterrupt(pSataChannel);
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvStorageDevATAIdentifyDevice - Perform an ATA IDENTIFY device command.
+*
+* DESCRIPTION:
+*       This function issues an IDENTIFY command to the connected device, and
+*       stores all the information in the identifyDevice buffer of the channel.
+*
+* INPUT:
+*       pAdapter     - Pointer to the device data structure.
+*       channelIndex - The index of the channel where the storage device
+*                      connected to.
+*       PMPort       - index of the required destination port multipliers
+*                      device Port (0 if no PM available).
+*       identifyDeviceResult - a buffer that is allocated by IAL that will hold
+*                              the IDENTIFY DEIVICE command result.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE on failure.
+*
+* COMMENTS:
+*       None.
+*
+*******************************************************************************/
+MV_BOOLEAN mvStorageDevATAIdentifyDevice(MV_SATA_ADAPTER *pAdapter,
+					 MV_U8 channelIndex, MV_U8 PMPort, MV_U16_PTR identifyDeviceResult)
+{
+	MV_BOOLEAN result;
+	/* Get the pointer to the relevant channel. */
+	MV_SATA_CHANNEL *pSataChannel;
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvStorageDevATAIdentif"
+			 "yDevice failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {	/* If the pointer do not exists, retrun false */
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  channel data "
+			 "structure is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	if (identifyDeviceResult == NULL) {	/* If the pointer do not exists, retrun false */
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  identify data buffer"
+			 " is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	result = mvStorageDevATAExecuteNonUDMACommand(pAdapter, channelIndex,
+						      PMPort, MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, MV_FALSE,
+						      /* pBuffer */
+						      identifyDeviceResult, 256,	/* count       */
+						      0,	/* features    */
+						      0,	/* sectorCount */
+						      0,	/* lbaLow      */
+						      0,	/* lbaMid      */
+						      0,	/* lbaHigh     */
+						      0,	/* device      */
+						      /* The command */
+						      MV_ATA_COMMAND_IDENTIFY);
+	if (result == MV_FALSE)
+		return MV_FALSE;
+
+	if (identifyDeviceResult[IDEN_ATA_VERSION] & (MV_BIT7 | MV_BIT6 | MV_BIT5)) {
+		/* if ATA 5/6/7 then check CRC of Identify command result */
+		MV_U8 crc = 0;
+		MV_U16 count;
+		MV_U8_PTR pointer = (MV_U8_PTR) identifyDeviceResult;
+		/* If no 0xa5 signature valid, then don't check CRC */
+		if (pointer[510] != 0xa5)
+			return MV_TRUE;
+
+		for (count = 0; count < ATA_SECTOR_SIZE; count++)
+			crc += pointer[count];
+
+		if (crc != 0) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  IDENTIFY DEVICE "
+				 "ATA Command failed due to wrong CRC checksum (%02x)\n",
+				 pAdapter->adapterId, channelIndex, crc);
+			return MV_FALSE;
+		}
+
+	}
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvStorageDevATASoftResetDevice - Issue SATA SOFTWARE reset to device.
+*
+* DESCRIPTION:
+*       Perform SOFTWARE RESET to the connected storage device by setting the
+*       SRST bit of the ATA device COMMAND
+*
+* INPUT:
+*       pAdapter     - Pointer to the device data structure.
+*       channelIndex - Index of the required channel.
+*       PMPort       - index of the required destination port multipliers
+*                      device port (0 if no PM available).
+*       registerStruct - Pointer to ATA registers data structure
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+*
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvStorageDevATASoftResetDevice(MV_SATA_ADAPTER *pAdapter,
+					  MV_U8 channelIndex,
+					  MV_U8 PMPort, MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_U32 eDmaRegsOffset;
+	MV_BOOLEAN result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvStorageDevATASoftRes"
+			 "etDevice Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  channel data structu"
+			 "re is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	mvOsSemTake(&pSataChannel->semaphore);
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  mvStorageDevATASoft"
+			 "ResetDevice command failed: EDMA is active\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	_setActivePMPort(pSataChannel, PMPort);
+	result = _doSoftReset(pSataChannel);
+	if (registerStruct)
+		dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_FALSE, registerStruct);
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return result;
+}
+
+void _startSoftResetDevice(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_NON_UDMA_COMMAND | MV_DEBUG, "Issue SRST COMMAND\n");
+
+/* Write to the Device Control register, bits 1,2:                      */
+/* - bit 1 (nIEN): is the enable bit for the device assertion of INTRQ  */
+/*   to the host. When the nIEN bit is set to one, or the device is not */
+/*   selected, the device shall release the INTRQ signal.               */
+/* - bit 2 (SRST): is the host software reset bit.                      */
+	MV_REG_WRITE_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+			  MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT2 | MV_BIT1);
+	MV_REG_READ_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET);
+	mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 10);
+	/* enableStorageDevInterrupt will clear the SRST bit */
+	enableStorageDevInterrupt(pSataChannel);
+}
+
+MV_BOOLEAN _isDeviceBsyBitOff(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U8 ATAstatus;
+	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+	if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0)
+		return MV_TRUE;
+	else {
+#ifdef MV_LOGGER
+		if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+			MV_U32 ifStatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
+							   MV_SATA_II_IF_STATUS_REG_OFFSET);
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+				 "[%d %d] SATA interface status register = 0x%X\n",
+				 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ifStatus);
+		}
+#endif
+		return MV_FALSE;
+	}
+}
+
+/*******************************************************************************
+* mvStorageDevATAStartSoftResetDevice -
+*                   begins device software reset
+*
+* DESCRIPTION:
+*
+*   Submits SRST for channel connected device and exit. The IAL must call the
+*   mvStorageIsDeviceBsyBitOff later on to check whether the device is
+*   ready
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*       channelIndex - channel number
+*       PMPort      - port multiplier port
+*
+* OUTPUT:
+*       None
+* RETURN:
+*       MV_TRUE on success,
+*       MV_FALSE otherwise.
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvStorageDevATAStartSoftResetDevice(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvStorageDevATASoftRes"
+			 "etDevice Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  channel data structu"
+			 "re is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	mvOsSemTake(&pSataChannel->semaphore);
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  mvStorageDevATASoft"
+			 "ResetDevice command failed: EDMA is active\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	_setActivePMPort(pSataChannel, PMPort);
+	_startSoftResetDevice(pSataChannel);
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvStorageIsDeviceBsyBitOff -
+*                    check if device is BUSY bit cleared after SRST
+*
+* DESCRIPTION:
+*
+*   Checks the if BSY bit in ATA status is on/off
+*
+* INPUT:
+*       pAdapter    - pointer to the adapter data structure.
+*       channelIndex - channel number
+*       registerStruct - If non-zero then this function dumps ATA registers
+*                        to this data structure before exit.
+*
+* OUTPUT:
+*       None
+* RETURN:
+*       MV_TRUE if BSY bit is off
+*       MV_FALSE if BSY bit is on (or on failure)
+* COMMENTS:
+*
+*******************************************************************************/
+MV_BOOLEAN mvStorageIsDeviceBsyBitOff(MV_SATA_ADAPTER *pAdapter,
+				      MV_U8 channelIndex, MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BUS_ADDR_T ioBaseAddr;
+	MV_BOOLEAN result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvStorageDevATASoftRes"
+			 "etDevice Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  channel data structu"
+			 "re is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pSataChannel->semaphore);
+	result = _isDeviceBsyBitOff(pSataChannel);
+	if (registerStruct)
+		dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_FALSE, registerStruct);
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return result;
+}
+
+/*******************************************************************************
+* mvStorageDevATASetFeatures - Perform ATA SET FEATURES command.
+*
+* DESCRIPTION:
+*       Perform ATA SET FEATURES command to the ATA device connected to the
+*       given channel. This command is used by the host to establish parameters
+*       that affect the execution of certain device features (Table 44 in the
+*       ATA protocol document defines these features).
+*
+* INPUT:
+*       pAdapter            - Pointer to the device data structure.
+*       channelIndex        - Index of the required channel
+*       PMPort              - index of the required destination port multipliers
+*                             device Port (0 if no PM available).
+*       subCommand          - Sub command for the SET FEATURES ATA command
+*       subCommandSpecific1 - First parameter to the sub command.
+*       subCommandSpecific2 - Second parameter to the sub command.
+*       subCommandSpecific3 - Third parameter to the sub command.
+*       subCommandSpecific4 - Fourth parameter to the sub command.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvStorageDevATASetFeatures(MV_SATA_ADAPTER *pAdapter,
+				      MV_U8 channelIndex,
+				      MV_U8 PMPort,
+				      MV_U8 subCommand,
+				      MV_U8 subCommandSpecific1,
+				      MV_U8 subCommandSpecific2, MV_U8 subCommandSpecific3, MV_U8 subCommandSpecific4)
+{
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND,
+		 "ATA Set Features: %x , %x , %x , %x , %x\n", subCommand,
+		 subCommandSpecific1, subCommandSpecific2, subCommandSpecific3, subCommandSpecific4);
+	return mvStorageDevATAExecuteNonUDMACommand(pAdapter, channelIndex, PMPort, MV_NON_UDMA_PROTOCOL_NON_DATA,
+						    MV_FALSE, NULL,/* pBuffer */
+						    0,	/* count  */
+						    subCommand,	/*features */
+						    /* sectorCount */
+						    subCommandSpecific1, subCommandSpecific2,	/* lbaLow */
+						    subCommandSpecific3,	/* lbaMid */
+						    /* lbaHigh */
+						    subCommandSpecific4, 0,	/* device */
+						    /* command */
+						    MV_ATA_COMMAND_SET_FEATURES);
+}
+
+/*******************************************************************************
+* mvStorageDevATAExecuteNonUdmaCommand - perform ATA non udma command.
+*
+* DESCRIPTION:
+*       perform ATA non UDMA command to the ATA device connected to the given
+*       channel
+*
+* INPUT:
+*   pAdapter    - pointer to the device data structure.
+*   channelIndex    - index of the required channel
+*   PMPort          - index of the required destination port multipliers
+*                     device Port (0 if no PM available).
+*   protocolType    - protocol type of the command
+*   isEXT   - true when the given command is the EXTENDED
+*   bufPtr  - pointer to the buffer to write/read to/from
+*   count   - number of words to transfer
+*   features    - the value to be written to the FEATURES register
+*   sectorCount - the value to be written to the SECTOR COUNT register
+*   lbaLow  - the value to be written to the LBA LOW register
+*   lbaMid  - the value to be written to the LBA MID register
+*   lbaHigh - the value to be written to the LBA HIGH register
+*   device  - the value to be written to the DEVICE register
+*   command - the value to be written to the COMMAND register
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       when the command is EXTENDED, then the high 8 bits of the 16 bits values
+*   will be written first, so they should hold the previous value as defined in
+*   the ATA 6 standard
+*
+*******************************************************************************/
+MV_BOOLEAN mvStorageDevATAExecuteNonUDMACommand(MV_SATA_ADAPTER *pAdapter,
+						MV_U8 channelIndex,
+						MV_U8 PMPort,
+						MV_NON_UDMA_PROTOCOL protocolType,
+						MV_BOOLEAN isEXT,
+						MV_U16_PTR bufPtr, MV_U32 count,
+						MV_U16 features,
+						MV_U16 sectorCount,
+						MV_U16 lbaLow, MV_U16 lbaMid,
+						MV_U16 lbaHigh, MV_U8 device, MV_U8 command)
+{
+	MV_BOOLEAN result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvStorageDevATAExecute"
+			 "NonUDMACommand Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataChannel[channelIndex] == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  mvStorageDevATAExecu"
+			 "teNonUDMACommand Failed, channel data structure not allocated"
+			 "\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pAdapter->sataChannel[channelIndex]->semaphore);
+	result = executeNonUDMACommand(pAdapter, channelIndex, PMPort, protocolType,
+				       isEXT, bufPtr, count, features, sectorCount,
+				       lbaLow, lbaMid, lbaHigh, device, command);
+	mvOsSemRelease(&pAdapter->sataChannel[channelIndex]->semaphore);
+	return result;
+}
+
+#if 0
+MV_BOOLEAN executePacketCommand(MV_SATA_ADAPTER *pAdapter,
+				MV_U8 channelIndex,
+				MV_NON_UDMA_PROTOCOL protocolType,
+				MV_U8 PMPort, MV_U16_PTR cdb, MV_U8 cdb_len, MV_U16_PTR dataBufPtr)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset;
+	MV_U32 i;
+	MV_U32 count;
+	MV_U8 ATAstatus;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND, " %d %d send PACKET "
+		 " command: protocol(%d) cdb %p cdb len %p buffer %p \n", pAdapter->adapterId,
+		 channelIndex, protocolType, cdb, cdb_len, dataBufPtr);
+
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+	if ((PMPort) && ((pSataChannel->PMSupported == MV_FALSE) ||
+			 (pSataChannel->deviceType != MV_SATA_DEVICE_TYPE_PM))) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  executePacketCommand"
+			 " failed PM not supported for this channel\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	{
+		if (isStorageDevReadyForPIO(pSataChannel) == MV_FALSE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d : Error in Issue NON UDMA command:"
+				 " isStorageDevReadyForPIO failed\n", pAdapter->adapterId, channelIndex);
+
+			return MV_FALSE;
+		}
+	}
+	_setActivePMPort(pSataChannel, PMPort);
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  PIO command failed:"
+			 "EDMA is active\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		return MV_FALSE;
+	}
+
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
+		disableStorageDevInterrupt(pSataChannel);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_FEATURES_REG_OFFSET, 0);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, 0);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, 0);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, 0);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, 0x20);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_HEAD_REG_OFFSET, 0);
+	MV_CPU_WRITE_BUFFER_FLUSH();
+
+	/* 88SX60X1 FEr SATA #16 */
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II)
+		enableStorageDevInterrupt(pSataChannel);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_COMMAND_REG_OFFSET, MV_ATA_COMMAND_PACKET);
+
+	/* Wait for PIO Setup or completion */
+	if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 3100, 10000) == MV_FALSE) {
+		enableStorageDevInterrupt(pSataChannel);
+		return MV_FALSE;
+	}
+	if (protocolType == MV_NON_UDMA_PROTOCOL_PACKET_PIO_NON_DATA) {
+		enableStorageDevInterrupt(pSataChannel);
+		pSataChannel->recoveredErrorsCounter = 0;
+		return MV_TRUE;
+	}
+
+	/* Check the status register on DATA request commands */
+	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		if (!(ATAstatus & MV_ATA_DATA_REQUEST_STATUS)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS"
+				 " register is not set\n", pAdapter->adapterId, channelIndex);
+			enableStorageDevInterrupt(pSataChannel);
+			return MV_FALSE;
+		}
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+
+		if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000)
+		    == MV_FALSE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS"
+				 " register is not set\n", pAdapter->adapterId, channelIndex);
+			enableStorageDevInterrupt(pSataChannel);
+			return MV_FALSE;
+		}
+	}
+	for (i = 0; i < cdb_len; i++) {
+		MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, cdb[i]);
+		MV_CPU_WRITE_BUFFER_FLUSH();
+	}
+
+	if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000)
+	    == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS"
+			 " register is not set\n", pAdapter->adapterId, channelIndex);
+		enableStorageDevInterrupt(pSataChannel);
+		return MV_FALSE;
+	}
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " Status: %x\n",
+		 MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET));
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " Sector Count: %x\n",
+		 MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET));
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " LBA Mid: %x\n",
+		 MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET));
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " LBA High: %x\n",
+		 MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET));
+
+	count = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET) +
+	    (MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) << 8);
+	count >>= 1;
+	for (i = 0; i < count; i++) {
+		if (protocolType == MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN) {
+			dataBufPtr[i] = MV_REG_READ_WORD(ioBaseAddr, eDmaRegsOffset +
+							 MV_ATA_DEVICE_PIO_DATA_REG_OFFSET);
+		} else {
+			MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset +
+					  MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, dataBufPtr[i]);
+
+		}
+	}
+
+	/* Wait for the storage device to be available */
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: on non-UDMA sequence - checking if"
+		 " device is has finished the command\n", pAdapter->adapterId, channelIndex);
+
+	if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100) == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " Status: %x\n",
+			 MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET));
+
+		enableStorageDevInterrupt(pSataChannel);
+		return MV_FALSE;
+	}
+
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+
+		if (waitForDRQToClear(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100)
+		    == MV_FALSE) {
+			enableStorageDevInterrupt(pSataChannel);
+			return MV_FALSE;
+		}
+	}
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Finish NonUdma Command. Status=0x%02x"
+		 "\n", pAdapter->adapterId, channelIndex,
+		 MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET));
+	enableStorageDevInterrupt(pSataChannel);
+	pSataChannel->recoveredErrorsCounter = 0;
+	return MV_TRUE;
+}
+#endif /* 0 */
+MV_BOOLEAN executeNonUDMACommand(MV_SATA_ADAPTER *pAdapter,
+				 MV_U8 channelIndex,
+				 MV_U8 PMPort,
+				 MV_NON_UDMA_PROTOCOL protocolType,
+				 MV_BOOLEAN isEXT,
+				 MV_U16_PTR bufPtr, MV_U32 count,
+				 MV_U16 features,
+				 MV_U16 sectorCount,
+				 MV_U16 lbaLow, MV_U16 lbaMid, MV_U16 lbaHigh, MV_U8 device, MV_U8 command)
+{
+	MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex];
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset;
+	MV_U32 i;
+	MV_U8 ATAstatus;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_NON_UDMA_COMMAND, " %d %d Issue NON "
+		 "UDMA command: protocol(%d) %p , %x , %x , %x , %x.%x.%x %x "
+		 "command=%x\n", pAdapter->adapterId, channelIndex, protocolType,
+		 bufPtr, count, features, sectorCount, lbaLow, lbaMid, lbaHigh, device, command);
+
+	eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+	if ((PMPort) && ((pSataChannel->PMSupported == MV_FALSE) ||
+			 (pSataChannel->deviceType != MV_SATA_DEVICE_TYPE_PM))) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  executeNonUDMACommand"
+			 " failed PM not supported for this channel\n",
+			 pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	if (command != MV_ATA_COMMAND_PM_READ_REG && command != MV_ATA_COMMAND_PM_WRITE_REG) {
+		if (isStorageDevReadyForPIO(pSataChannel) == MV_FALSE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d : Error in Issue NON UDMA command:"
+				 " isStorageDevReadyForPIO failed\n", pAdapter->adapterId, channelIndex);
+
+			return MV_FALSE;
+		}
+	}
+	_setActivePMPort(pSataChannel, PMPort);
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  PIO command failed:"
+			 "EDMA is active\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber);
+		return MV_FALSE;
+	}
+
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
+		disableStorageDevInterrupt(pSataChannel);
+
+	if (isEXT == MV_TRUE) {
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_FEATURES_REG_OFFSET, (features & 0xff00) >> 8);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, (sectorCount & 0xff00) >> 8);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, (lbaLow & 0xff00) >> 8);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_LBA_MID_REG_OFFSET, (lbaMid & 0xff00) >> 8);
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
+				  MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, (lbaHigh & 0xff00) >> 8);
+	} else {
+		if ((features & 0xff00) || (sectorCount & 0xff00) || (lbaLow & 0xff00) ||
+		    (lbaMid & 0xff00) || (lbaHigh & 0xff00)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 " %d %d : Error in Issue NON UDMA command:"
+				 " bits[15:8] of register values should be reserved"
+				 " Features 0x%02x, SectorCount 0x%02x, LBA Low 0x%02x,"
+				 " LBA Mid 0x%02x, LBA High 0x%02x\n",
+				 pAdapter->adapterId, channelIndex, features, sectorCount, lbaLow, lbaMid, lbaHigh);
+			enableStorageDevInterrupt(pSataChannel);
+			return MV_FALSE;
+		}
+	}
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_FEATURES_REG_OFFSET, features & 0xff);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, sectorCount & 0xff);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, lbaLow & 0xff);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, lbaMid & 0xff);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, lbaHigh & 0xff);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_HEAD_REG_OFFSET, device);
+	MV_CPU_WRITE_BUFFER_FLUSH();
+
+	/* 88SX60X1 FEr SATA #16 */
+	/* 88SX6042/88SX7042 FEr SATA #16 */
+	/* 88F5182 FEr #SATA-S11 */
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II)
+		enableStorageDevInterrupt(pSataChannel);
+
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_COMMAND_REG_OFFSET, command);
+
+	if (protocolType == MV_NON_UDMA_PROTOCOL_NON_DATA) {
+		/* Wait for the command to complete */
+		if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 3100, 10000) == MV_FALSE) {
+			enableStorageDevInterrupt(pSataChannel);
+			return MV_FALSE;
+		}
+		enableStorageDevInterrupt(pSataChannel);
+		pSataChannel->recoveredErrorsCounter = 0;
+		return MV_TRUE;
+	}
+	/* Wait for the command to complete */
+	if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 3100, 10000) == MV_FALSE) {
+		enableStorageDevInterrupt(pSataChannel);
+		return MV_FALSE;
+	}
+	/* Check the status register on DATA request commands */
+	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+		if (!(ATAstatus & MV_ATA_DATA_REQUEST_STATUS)) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS"
+				 " register is not set\n", pAdapter->adapterId, channelIndex);
+			enableStorageDevInterrupt(pSataChannel);
+			return MV_FALSE;
+		}
+	}
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000)
+		    == MV_FALSE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS"
+				 " register is not set\n", pAdapter->adapterId, channelIndex);
+			enableStorageDevInterrupt(pSataChannel);
+			return MV_FALSE;
+		}
+	}
+	for (i = 0; i < count; i++) {
+		/* Every DRQ data block we have to check the BUSY bit to verify that
+		   the Disk is ready for next block transfer  */
+		if ((i & (((MV_U32) pSataChannel->DRQDataBlockSize * ATA_SECTOR_SIZE_IN_WORDS) - 1)) == 0) {
+			if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+				/* Perform a dummy read */
+				MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_ALTERNATE_REG_OFFSET);
+				/* 88SX60X1 FEr SATA #16 */
+				/* 88SX6042/88SX7042 FEr SATA #16 */
+				/* 88F5182 FEr #SATA-S11 */
+				if (i != 0) {
+					if (waitWhileStorageDevIsBusy_88SX60X1(pAdapter,
+									       ioBaseAddr, eDmaRegsOffset, channelIndex,
+									       50000, 100) == MV_FALSE) {
+						mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+							 "Sata device interrupt timeout...i = %d\n", i);
+						enableStorageDevInterrupt(pSataChannel);
+						return MV_FALSE;
+					}
+				} else {
+					MV_U8 sataUnit = channelIndex >> 2, portNum = channelIndex & 3;
+
+					if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr,
+								      eDmaRegsOffset, 50000, 100) == MV_FALSE) {
+						mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+							 "Busy bit timeout...i = %d\n", i);
+						enableStorageDevInterrupt(pSataChannel);
+						return MV_FALSE;
+					}
+					MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
+							   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(1 << (8 + portNum)));
+				}
+				if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100)
+				    == MV_FALSE) {
+					enableStorageDevInterrupt(pSataChannel);
+					return MV_FALSE;
+				}
+			} else if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) {
+				if (waitWhileStorageDevIsBusy(pAdapter,
+							      ioBaseAddr, eDmaRegsOffset, 50000, 100) == MV_FALSE) {
+					enableStorageDevInterrupt(pSataChannel);
+					return MV_FALSE;
+				}
+			}
+		}
+		if (protocolType == MV_NON_UDMA_PROTOCOL_PIO_DATA_IN) {
+			bufPtr[i] = MV_REG_READ_WORD(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET);
+		} else {
+			MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, bufPtr[i]);
+			MV_CPU_WRITE_BUFFER_FLUSH();
+		}
+	}
+
+	/* Wait for the storage device to be available */
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: on non-UDMA sequence - checking if"
+		 " device is has finished the command\n", pAdapter->adapterId, channelIndex);
+
+	if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100) == MV_FALSE) {
+		enableStorageDevInterrupt(pSataChannel);
+		return MV_FALSE;
+	}
+
+	if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) {
+		if (waitForDRQToClear(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100)
+		    == MV_FALSE) {
+			enableStorageDevInterrupt(pSataChannel);
+			return MV_FALSE;
+		}
+	}
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Finish NonUdma Command. Status=0x%02x"
+		 "\n", pAdapter->adapterId, channelIndex,
+		 MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET));
+	enableStorageDevInterrupt(pSataChannel);
+	pSataChannel->recoveredErrorsCounter = 0;
+	return MV_TRUE;
+}
+
+MV_BOOLEAN _PMAccessReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue,
+			MV_STORAGE_DEVICE_REGISTERS *registerStruct, MV_BOOLEAN isRead)
+{
+	MV_BOOLEAN result;
+
+	if (isRead == MV_TRUE) {
+		result = executeNonUDMACommand(pAdapter, channelIndex,
+					       MV_SATA_PM_CONTROL_PORT,
+					       MV_NON_UDMA_PROTOCOL_NON_DATA, MV_TRUE /*isEXT */ ,
+					       NULL /*bufPtr */ ,
+					       0 /*count */ ,
+					       PMReg /*features */ , 0 /*sectorCount */ ,
+					       0 /*lbaLow */ , 0 /*lbaMid */ , 0 /*lbaHigh */ ,
+					       PMPort /*device */ ,
+					       MV_ATA_COMMAND_PM_READ_REG /*command */);
+		if (result == MV_TRUE) {
+			MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+			MV_U32 eDmaRegsOffset = pAdapter->sataChannel[channelIndex]->eDmaRegsOffset;
+
+			*pValue = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET);
+			*pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) << 8;
+			*pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
+						    MV_ATA_DEVICE_LBA_MID_REG_OFFSET) << 16;
+			*pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
+						    MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) << 24;
+		}
+	} else {
+		result = executeNonUDMACommand(pAdapter, channelIndex,
+					       MV_SATA_PM_CONTROL_PORT,
+					       MV_NON_UDMA_PROTOCOL_NON_DATA, MV_TRUE /*isEXT */ ,
+					       NULL /*bufPtr */ ,
+					       0 /*count */ ,
+					       PMReg /*features */ ,
+					       (MV_U16) ((*pValue) & 0xff) /*sectorCount */ ,
+					       (MV_U16) (((*pValue) & 0xff00) >> 8) /*lbaLow */ ,
+					       (MV_U16) (((*pValue) & 0xff0000) >> 16) /*lbaMid */ ,
+					       (MV_U16) (((*pValue) & 0xff000000) >> 24) /*lbaHigh */ ,
+					       PMPort /*device */ ,
+					       MV_ATA_COMMAND_PM_WRITE_REG /*command */);
+	}
+	if (registerStruct)
+		dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_FALSE, registerStruct);
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_PM, " %d %d: %s PM Reg %s: PM Port %x"
+		 ", PM Reg %d, value %x\n", pAdapter->adapterId, channelIndex,
+		 (isRead == MV_TRUE) ? "Read" : "Write",
+		 (result == MV_TRUE) ? "Succeeded" : "Failed", PMPort, PMReg, *pValue);
+
+	return result;
+}
+
+MV_BOOLEAN waitForDRQToClear(MV_SATA_ADAPTER *pAdapter,
+			     MV_BUS_ADDR_T ioBaseAddr, MV_U32 eDmaRegsOffset, MV_U32 loops, MV_U32 delayParam)
+{
+	MV_U8 ATAstatus = 0;
+	MV_U32 i;
+
+	for (i = 0; i < loops; i++) {
+		ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+		if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) {
+			if (!(ATAstatus & MV_ATA_DATA_REQUEST_STATUS)) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *"
+					 "%d usecs\n", i, delayParam);
+				return MV_TRUE;
+			}
+		}
+		mvMicroSecondsDelay(pAdapter, delayParam);
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "waitWhileStorageDevIsBusy<FAILED>: Time out - Device ERROR"
+		 " Status: 0x%02x. loops %d, delay %d\n", ATAstatus, loops, delayParam);
+
+	return MV_FALSE;
+}
+
+void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter,
+			    MV_U8 channelIndex, MV_BOOLEAN isEXT, MV_STORAGE_DEVICE_REGISTERS *pRegisters)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
+	MV_U32 eDmaRegsOffset = pAdapter->sataChannel[channelIndex]->eDmaRegsOffset;
+
+	if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_IIE) {
+		if (MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET) & MV_BIT0) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR,
+				 " %d %d: dumpAtaDeviceRegisters: Edma is active!!!\n",
+				 pAdapter->adapterId, channelIndex);
+			return;
+		}
+	}
+	MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET, 0);
+
+	pRegisters->errorRegister = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_ERROR_REG_OFFSET);
+
+	pRegisters->sectorCountRegister =
+	    MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET) & 0x00ff;
+	pRegisters->lbaLowRegister =
+	    MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) & 0x00ff;
+
+	pRegisters->lbaMidRegister =
+	    MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET) & 0x00ff;
+
+	pRegisters->lbaHighRegister =
+	    MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) & 0x00ff;
+
+	if (isEXT == MV_TRUE) {
+		/*set the HOB bit of DEVICE CONTROL REGISTER */
+
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT7);
+
+		pRegisters->sectorCountRegister |= (MV_REG_READ_BYTE(ioBaseAddr,
+								     eDmaRegsOffset +
+								     MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET) << 8) &
+		    0xff00;
+
+		pRegisters->lbaLowRegister |= (MV_REG_READ_BYTE(ioBaseAddr,
+								eDmaRegsOffset + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) << 8)
+		    & 0xff00;
+
+		pRegisters->lbaMidRegister |= (MV_REG_READ_BYTE(ioBaseAddr,
+								eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET) << 8)
+		    & 0xff00;
+
+		pRegisters->lbaHighRegister |= (MV_REG_READ_BYTE(ioBaseAddr,
+								 eDmaRegsOffset +
+								 MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) << 8)
+		    & 0xff00;
+		MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET, 0);
+
+	}
+
+	pRegisters->deviceRegister = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_HEAD_REG_OFFSET);
+
+	pRegisters->statusRegister = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+
+}
+
+MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel)
+{
+	MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
+	MV_U32 i;
+	MV_U8 ATAstatus;
+	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_NON_UDMA_COMMAND | MV_DEBUG, "Issue SRST COMMAND\n");
+
+/* Write to the Device Control register, bits 1,2:                      */
+/* - bit 1 (nIEN): is the enable bit for the device assertion of INTRQ  */
+/*   to the host. When the nIEN bit is set to one, or the device is not */
+/*   selected, the device shall release the INTRQ signal.               */
+/* - bit 2 (SRST): is the host software reset bit.                      */
+	MV_REG_WRITE_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset +
+			  MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT2 | MV_BIT1);
+	MV_REG_READ_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset + MV_ATA_DEVICE_CONTROL_REG_OFFSET);
+	mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 10);
+
+/* enableStorageDevInterrupt will clear the SRST bit*/
+	enableStorageDevInterrupt(pSataChannel);
+
+	mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500);
+	mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500);
+	mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500);
+	mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500);
+
+	for (i = 0; i < 31000; i++) {
+		ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
+		if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0)
+			return MV_TRUE;
+
+		mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 1000);
+	}
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: Software reset failed "
+		 "Status=0x%02x\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber, ATAstatus);
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvPMDevReadReg - Reads port multiplier's internal register
+*
+*
+* DESCRIPTION:
+*       Performs PIO non-data command for reading port multiplier's internal
+*       register.
+*
+* INPUT:
+*       pAdapter            - Pointer to the device data structure.
+*       channelIndex        - Index of the required channel
+*       PMPort              - This should be port 0xf
+*       PMReg               - The required register to be read
+*       pValue              - A pointer to 32bit data container that holds
+*                             the result.
+*       registerStruct      - A pointer to ATA register data structure. This
+*                             holds the ATA registers dump after command
+*                             is executed.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvPMDevReadReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			  MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue, MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BOOLEAN result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvStorageDevPMReadReg"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  channel data structu"
+			 "re is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	mvOsSemTake(&pSataChannel->semaphore);
+	if (pSataChannel->PMSupported == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  mvStorageDevPMReadReg"
+			 " failed PM not supported for this channel\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  mvStorageDevPMReadReg"
+			 " command failed: EDMA is active\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+
+	result = _PMAccessReg(pAdapter, channelIndex, PMPort, PMReg, pValue, registerStruct, MV_TRUE);
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return result;
+}
+
+/*******************************************************************************
+* mvPMDevWriteReg - Writes to port multiplier's internal register
+*
+*
+* DESCRIPTION:
+*       Performs PIO non-data command for writing to port multiplier's internal
+*       register.
+*
+* INPUT:
+*       pAdapter            - Pointer to the device data structure.
+*       channelIndex        - Index of the required channel
+*       PMPort              - This should be port 0xf
+*       PMReg               - The required register to be read
+*       value               - Holds 32bit of the value to be written
+*       registerStruct      - A pointer to ATA register data structure. This
+*                             holds the ATA registers dump after command
+*                             is executed.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvPMDevWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+			   MV_U8 PMPort, MV_U8 PMReg, MV_U32 value, MV_STORAGE_DEVICE_REGISTERS *registerStruct)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+	MV_BOOLEAN result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvStorageDevPMWriteReg"
+			 " Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  channel data structu"
+			 "re is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	mvOsSemTake(&pSataChannel->semaphore);
+	if (pSataChannel->PMSupported == MV_FALSE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  mvStorageDevPMWriteReg"
+			 " failed PM not supported for this channel\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+	if (pSataChannel->queueCommandsEnabled == MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d:  mvStorageDevPMWriteReg"
+			 " command failed: EDMA is active\n", pAdapter->adapterId, channelIndex);
+		mvOsSemRelease(&pSataChannel->semaphore);
+		return MV_FALSE;
+	}
+
+	result = _PMAccessReg(pAdapter, channelIndex, PMPort, PMReg, &value, registerStruct, MV_FALSE);
+
+	mvOsSemRelease(&pSataChannel->semaphore);
+	return result;
+}
+
+static MV_BOOLEAN _checkPMPortSStatus(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort, MV_BOOLEAN *error)
+{
+	MV_BOOLEAN result;
+	MV_U32 SStatus;
+
+	result = mvPMDevReadReg(pAdapter, channelIndex, PMPort, MV_SATA_PSCR_SSTATUS_REG_NUM, &SStatus, NULL);
+
+	if (result == MV_FALSE) {
+		*error = MV_TRUE;
+		return result;
+	}
+	*error = MV_FALSE;
+	SStatus &= (MV_BIT0 | MV_BIT1 | MV_BIT2);
+	if ((SStatus == (MV_BIT0 | MV_BIT1)) || (SStatus == 0))
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+MV_BOOLEAN mvPMLinkUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort, MV_BOOLEAN force_gen1)
+{
+	MV_BOOLEAN result;
+	MV_U32 speed_force = 0;
+
+	if (force_gen1 == MV_TRUE)
+		speed_force = 0x10;
+
+	result = mvPMDevWriteReg(pAdapter, channelIndex, PMPort,
+				 MV_SATA_PSCR_SCONTROL_REG_NUM, 0x301 | speed_force, NULL);
+	if (result == MV_FALSE)
+		return result;
+
+	mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_DELAY);
+	result = mvPMDevWriteReg(pAdapter, channelIndex, PMPort,
+				 MV_SATA_PSCR_SCONTROL_REG_NUM, 0x300 | speed_force, NULL);
+	return result;
+}
+
+/*******************************************************************************
+* mvPMDevEnableStaggeredSpinUp -
+*
+*
+* DESCRIPTION:
+*       Enables commnucation on a port multiplier's device SATA channel
+*
+* INPUT:
+*       pAdapter            - Pointer to the device data structure.
+*       channelIndex        - Index of the required channel
+*       PMPort              - Required device SATA channel on port multiplier
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvPMDevEnableStaggeredSpinUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort)
+{
+	return mvPMLinkUp(pAdapter, channelIndex, PMPort, MV_FALSE);
+}
+
+/*******************************************************************************
+* mvPMDevEnableStaggeredSpinUpAll -
+*
+*
+* DESCRIPTION:
+*       Enables commnucation on all port multiplier's device SATA channels
+*
+* INPUT:
+*       pAdapter            - Pointer to the device data structure.
+*       channelIndex        - Index of the required channel
+*       PMNumOfPorts        - Number of device SATA channel the port multiplier
+*                             has.
+*       bitmask             - A pointer to 16bit data container that holds
+*                             a bitmask of '1' when the relevant port multiplier's
+*                             device port staggered spinup operation is success.
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+
+MV_BOOLEAN mvPMDevEnableStaggeredSpinUpAll(MV_SATA_ADAPTER *pSataAdapter,
+					   MV_U8 channelIndex, MV_U8 PMNumOfPorts, MV_U16 *bitmask)
+{
+	MV_U8 PMPort;
+	MV_U8 retryCount;
+	MV_U8 tmpBitmask = 1;
+
+	if (bitmask == NULL)
+		return MV_FALSE;
+
+	/*Do not issue staggered spinup for port 0 - already done because of
+	   legacy port mode */
+	*bitmask = 1;
+	for (PMPort = 0; PMPort < PMNumOfPorts; PMPort++) {
+		MV_BOOLEAN error;
+		/* if sata communication already done(No staggered spin-up) */
+		if (_checkPMPortSStatus(pSataAdapter, channelIndex, PMPort, &error) == MV_TRUE) {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+				 "[%d %d %d]: sata communication already established.\n",
+				 pSataAdapter->adapterId, channelIndex, PMPort);
+			tmpBitmask |= (1 << PMPort);
+			continue;
+		}
+		if (mvPMDevEnableStaggeredSpinUp(pSataAdapter, channelIndex, PMPort) == MV_TRUE) {
+			tmpBitmask |= (1 << PMPort);
+		} else {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+				 "Error [%d %d %d]: "
+				 "PM enable staggered spin-up failed.\n",
+				 pSataAdapter->adapterId, channelIndex, PMPort);
+			return MV_FALSE;
+		}
+	}
+	mvMicroSecondsDelay(pSataAdapter, MV_SATA_COMM_INIT_WAIT_DELAY);
+	for (retryCount = 0; retryCount < 200; retryCount++) {
+		for (PMPort = 0; PMPort < PMNumOfPorts; PMPort++) {
+			MV_BOOLEAN error;
+			if ((*bitmask) & (1 << PMPort))
+				continue;
+
+			if (_checkPMPortSStatus(pSataAdapter, channelIndex, PMPort, &error) == MV_FALSE) {
+				if (error == MV_TRUE) {
+					mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+						 "[%d %d %d]: "
+						 "Fatal error - cannot read PM port SStatus.\n",
+						 pSataAdapter->adapterId, channelIndex, PMPort);
+					break;
+				}
+				mvMicroSecondsDelay(pSataAdapter, 1000);
+			} else {
+				if (bitmask != NULL)
+					*bitmask |= (1 << PMPort);
+
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+					 "[%d %d %d] PM SATA PHY ready after %d msec\n",
+					 pSataAdapter->adapterId, channelIndex, PMPort, retryCount);
+			}
+		}
+		if (tmpBitmask == *bitmask)
+			break;
+	}
+	if (tmpBitmask != *bitmask) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 "[%d %d %d]: "
+			 "Some of PM ports PHY are not initialized.\n", pSataAdapter->adapterId, channelIndex, PMPort);
+
+	}
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvPMDevEnableStaggeredSpinUpPort -
+*
+*
+* DESCRIPTION:
+*       Enables commnucation on port multiplier's device SATA port
+*
+* INPUT:
+*       pAdapter            - Pointer to the device data structure.
+*       channelIndex        - Index of the required channel
+*       PMPort              - the port number
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvPMDevEnableStaggeredSpinUpPort(MV_SATA_ADAPTER *pSataAdapter,
+					    MV_U8 channelIndex, MV_U8 PMPort, MV_BOOLEAN force_speed_gen1)
+{
+	MV_U8 retryCount;
+
+	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+		 "[%d %d %d]: init sata communication.\n", pSataAdapter->adapterId, channelIndex, PMPort);
+
+	if (mvPMLinkUp(pSataAdapter, channelIndex, PMPort, force_speed_gen1) != MV_TRUE) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+			 "Error [%d %d %d]: "
+			 "PM enable staggered spin-up failed.\n", pSataAdapter->adapterId, channelIndex, PMPort);
+		return MV_FALSE;
+	}
+	mvMicroSecondsDelay(pSataAdapter, MV_SATA_COMM_INIT_WAIT_DELAY);
+	for (retryCount = 0; retryCount < 200; retryCount++) {
+		MV_BOOLEAN error;
+
+		if (_checkPMPortSStatus(pSataAdapter, channelIndex, PMPort, &error) == MV_FALSE) {
+			if (error == MV_TRUE) {
+				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,
+					 "[%d %d %d]: "
+					 "Fatal error - cannot read PM port SStatus.\n",
+					 pSataAdapter->adapterId, channelIndex, PMPort);
+				return MV_FALSE;
+			}
+			mvMicroSecondsDelay(pSataAdapter, 1000);
+		} else {
+			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG,
+				 "[%d %d %d] PM SATA PHY ready after %d msec\n",
+				 pSataAdapter->adapterId, channelIndex, PMPort, retryCount);
+			break;
+		}
+
+	}
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvStorageDevExecutePIO -
+*
+*
+* DESCRIPTION:
+*       Sends custom PIO command (polling driven)
+*
+* INPUT:
+*   pAdapter    - pointer to the device data structure.
+*   channelIndex    - index of the required channel
+*   PMPort          - index of the required destination port multipliers
+*                     device Port (0 if no PM available).
+*   protocolType    - protocol type of the command
+*   isEXT   - true when the given command is the EXTENDED
+*   bufPtr  - pointer to the buffer to write/read to/from
+*   pInATARegs  - Holds ATA registers for the command
+*   pOutATARegs - Holds ATA registers after the command completed
+*
+* RETURN:
+*   MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       when the command is EXTENDED, then the high 8 bits of the 16 bits values
+*   will be written first, so they should hold the previous value as defined in
+*   the ATA 6 standard
+*******************************************************************************/
+MV_BOOLEAN mvStorageDevExecutePIO(MV_SATA_ADAPTER *pAdapter,
+				  MV_U8 channelIndex,
+				  MV_U8 PMPort,
+				  MV_NON_UDMA_PROTOCOL protocolType,
+				  MV_BOOLEAN isEXT, MV_U16_PTR bufPtr,
+				  MV_U32 count,
+				  MV_STORAGE_DEVICE_REGISTERS *pInATARegs, MV_STORAGE_DEVICE_REGISTERS *pOutATARegs)
+{
+	MV_BOOLEAN result;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  mvPMDevExecutePIO"
+			 "Command Failed, Bad adapter data structure pointer\n");
+		return MV_FALSE;
+	}
+	if (pAdapter->sataChannel[channelIndex] == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  mvPMDevExecutePIO"
+			 "Command Failed, channel data structure not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+	mvOsSemTake(&pAdapter->sataChannel[channelIndex]->semaphore);
+	result = executeNonUDMACommand(pAdapter, channelIndex, PMPort,
+				       protocolType, isEXT,
+				       bufPtr, count, pInATARegs->featuresRegister,
+				       pInATARegs->sectorCountRegister,
+				       pInATARegs->lbaLowRegister,
+				       pInATARegs->lbaMidRegister,
+				       pInATARegs->lbaHighRegister,
+				       pInATARegs->deviceRegister, pInATARegs->commandRegister);
+	if (pOutATARegs)
+		dumpAtaDeviceRegisters(pAdapter, channelIndex, isEXT, pOutATARegs);
+
+	mvOsSemRelease(&pAdapter->sataChannel[channelIndex]->semaphore);
+	return result;
+}
+
+/*******************************************************************************
+* mvStorageDevSetDeviceType -
+*
+*
+* DESCRIPTION:
+*       Sets the device type connected directly to the specific adapter's
+*       SATA channel.
+*
+* INPUT:
+*       pAdapter            - Pointer to the device data structure.
+*       channelIndex        - Index of the required channel
+*       deviceType          - Type of device
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+MV_BOOLEAN mvStorageDevSetDeviceType(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_SATA_DEVICE_TYPE deviceType)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  "
+			 " mvStorageDevSetDeviceType Failed, Bad adapter data structure " "pointer\n");
+		return MV_SATA_DEVICE_TYPE_UNKNOWN;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  channel data structu"
+			 "re is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_FALSE;
+	}
+
+	pSataChannel->deviceType = deviceType;
+
+	return MV_TRUE;
+}
+
+/*******************************************************************************
+* mvStorageDevGetDeviceType -
+*
+*
+* DESCRIPTION:
+*       Gets the device type connected directly to the specific adapter's
+*       SATA channel.
+*
+* INPUT:
+*       pAdapter            - Pointer to the device data structure.
+*       channelIndex        - Index of the required channel
+*
+* RETURN:
+*       MV_TRUE on success, MV_FALSE otherwise.
+* COMMENTS:
+*       NONE
+*
+*******************************************************************************/
+MV_SATA_DEVICE_TYPE mvStorageDevGetDeviceType(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
+{
+	MV_SATA_CHANNEL *pSataChannel;
+
+	if (pAdapter == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "    :  "
+			 " mvStorageDevGetDeviceType Failed, Bad adapter data structure " "pointer\n");
+		return MV_SATA_DEVICE_TYPE_UNKNOWN;
+	}
+	pSataChannel = pAdapter->sataChannel[channelIndex];
+	if (pSataChannel == NULL) {
+		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d:  "
+			 "channel data structure is not allocated\n", pAdapter->adapterId, channelIndex);
+		return MV_SATA_DEVICE_TYPE_UNKNOWN;
+	}
+
+	return pSataChannel->deviceType;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvStorageDev.h b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvStorageDev.h
new file mode 100755
index 0000000..d703ac1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/CoreDriver/mvStorageDev.h
@@ -0,0 +1,327 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/*******************************************************************************
+* mvStorageDev.h - Header File for mvStorageDev.c.
+*
+* DESCRIPTION:
+*       None.
+*
+* DEPENDENCIES:
+*       mvSata.h.
+*       mvOs.h.
+*       ATA/ATAPI-6 standard
+*
+*******************************************************************************/
+#ifndef __INCmvStorageDevh
+#define __INCmvStorageDevh
+#ifdef __cplusplus
+
+extern "C" {
+#endif				/* __cplusplus */
+
+/* Includes */
+#include "mvOsS.h"
+#include "mvSata.h"
+#include "mvRegs.h"
+
+/* Definitions */
+
+/* ATA register on the ATA drive*/
+
+#define MV_EDMA_ATA_FEATURES_ADDR               0x11
+#define MV_EDMA_ATA_SECTOR_COUNT_ADDR           0x12
+#define MV_EDMA_ATA_LBA_LOW_ADDR                0x13
+#define MV_EDMA_ATA_LBA_MID_ADDR                0x14
+#define MV_EDMA_ATA_LBA_HIGH_ADDR               0x15
+#define MV_EDMA_ATA_DEVICE_ADDR                 0x16
+#define MV_EDMA_ATA_COMMAND_ADDR                0x17
+
+#define MV_ATA_ERROR_STATUS                     MV_BIT0
+#define MV_ATA_DATA_REQUEST_STATUS              MV_BIT3
+#define MV_ATA_SERVICE_STATUS                   MV_BIT4
+#define MV_ATA_DEVICE_FAULT_STATUS              MV_BIT5
+#define MV_ATA_READY_STATUS                     MV_BIT6
+#define MV_ATA_BUSY_STATUS                      MV_BIT7
+
+#define MV_ATA_COMMAND_READ_SECTORS             0x20
+#define MV_ATA_COMMAND_READ_SECTORS_EXT         0x24
+#define MV_ATA_COMMAND_READ_LOG_EXT		0x2F
+#define MV_ATA_COMMAND_READ_VERIFY_SECTORS      0x40
+#define MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT  0x42
+#define MV_ATA_COMMAND_READ_BUFFER              0xE4
+#define MV_ATA_COMMAND_WRITE_BUFFER             0xE8
+#define MV_ATA_COMMAND_WRITE_SECTORS            0x30
+#define MV_ATA_COMMAND_WRITE_SECTORS_EXT        0x34
+#define MV_ATA_COMMAND_DIAGNOSTIC               0x90
+#define MV_ATA_COMMAND_SMART                    0xb0
+#define MV_ATA_COMMAND_READ_MULTIPLE            0xc4
+#define MV_ATA_COMMAND_WRITE_MULTIPLE           0xc5
+#define MV_ATA_COMMAND_STANDBY_IMMEDIATE        0xe0
+#define MV_ATA_COMMAND_IDLE_IMMEDIATE           0xe1
+#define MV_ATA_COMMAND_STANDBY                  0xe2
+#define MV_ATA_COMMAND_IDLE                     0xe3
+#define MV_ATA_COMMAND_SLEEP                    0xe6
+#define MV_ATA_COMMAND_IDENTIFY                 0xec
+#define MV_ATA_COMMAND_ATAPI_IDENTIFY           0xa1
+#define MV_ATA_COMMAND_PACKET                   0xa0
+#define MV_ATA_COMMAND_DEVICE_CONFIG            0xb1
+#define MV_ATA_COMMAND_SET_FEATURES             0xef
+#define MV_ATA_COMMAND_WRITE_DMA                0xca
+#define MV_ATA_COMMAND_WRITE_DMA_EXT            0x35
+#define MV_ATA_COMMAND_WRITE_DMA_QUEUED         0xcc
+#define MV_ATA_COMMAND_WRITE_DMA_QUEUED_EXT     0x36
+#define MV_ATA_COMMAND_WRITE_FPDMA_QUEUED_EXT   0x61
+#define MV_ATA_COMMAND_READ_DMA                 0xc8
+#define MV_ATA_COMMAND_READ_DMA_EXT             0x25
+#define MV_ATA_COMMAND_READ_DMA_QUEUED          0xc7
+#define MV_ATA_COMMAND_READ_DMA_QUEUED_EXT      0x26
+#define MV_ATA_COMMAND_READ_FPDMA_QUEUED_EXT    0x60
+#define MV_ATA_COMMAND_FLUSH_CACHE              0xe7
+#define MV_ATA_COMMAND_FLUSH_CACHE_EXT          0xea
+
+#define MV_ATA_COMMAND_PM_READ_REG              0xe4
+#define MV_ATA_COMMAND_PM_WRITE_REG             0xe8
+
+#define MV_SATA_GSCR_ID_REG_NUM                 0
+#define MV_SATA_GSCR_REVISION_REG_NUM           1
+#define MV_SATA_GSCR_INFO_REG_NUM               2
+#define MV_SATA_GSCR_ERROR_REG_NUM              32
+#define MV_SATA_GSCR_ERROR_ENABLE_REG_NUM       33
+#define MV_SATA_GSCR_FEATURES_REG_NUM           64
+#define MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM    96
+
+#define MV_SATA_PSCR_SSTATUS_REG_NUM            0
+#define MV_SATA_PSCR_SERROR_REG_NUM             1
+#define MV_SATA_PSCR_SCONTROL_REG_NUM           2
+#define MV_SATA_PSCR_SACTIVE_REG_NUM            3
+
+#define MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO   0x01
+#define MV_ATA_SET_FEATURES_ENABLE_WCACHE       0x02	/* Enable write cache */
+#define MV_ATA_SET_FEATURES_TRANSFER            0x03	/* Set transfer mode  */
+#define MV_ATA_TRANSFER_UDMA_0                  0x40
+#define MV_ATA_TRANSFER_UDMA_1                  0x41
+#define MV_ATA_TRANSFER_UDMA_2                  0x42
+#define MV_ATA_TRANSFER_UDMA_3                  0x43
+#define MV_ATA_TRANSFER_UDMA_4                  0x44
+#define MV_ATA_TRANSFER_UDMA_5                  0x45
+#define MV_ATA_TRANSFER_UDMA_6                  0x46
+#define MV_ATA_TRANSFER_UDMA_7                  0x47
+#define MV_ATA_TRANSFER_PIO_SLOW                0x00
+#define MV_ATA_TRANSFER_PIO_0                   0x08
+#define MV_ATA_TRANSFER_PIO_1                   0x09
+#define MV_ATA_TRANSFER_PIO_2                   0x0A
+#define MV_ATA_TRANSFER_PIO_3                   0x0B
+#define MV_ATA_TRANSFER_PIO_4                   0x0C
+
+/* Enable advanced power management */
+#define MV_ATA_SET_FEATURES_ENABLE_APM          0x05
+
+/* Disable media status notification*/
+#define MV_ATA_SET_FEATURES_DISABLE_MSN         0x31
+
+/* Disable read look-ahead          */
+#define MV_ATA_SET_FEATURES_DISABLE_RLA         0x55
+
+/* Enable release interrupt         */
+#define MV_ATA_SET_FEATURES_ENABLE_RI           0x5D
+
+/* Enable SERVICE interrupt         */
+#define MV_ATA_SET_FEATURES_ENABLE_SI           0x5E
+
+/* Disable revert power-on defaults */
+#define MV_ATA_SET_FEATURES_DISABLE_RPOD        0x66
+
+/* Disable write cache              */
+#define MV_ATA_SET_FEATURES_DISABLE_WCACHE      0x82
+
+/* Disable advanced power management*/
+#define MV_ATA_SET_FEATURES_DISABLE_APM         0x85
+
+/* Enable media status notification */
+#define MV_ATA_SET_FEATURES_ENABLE_MSN          0x95
+
+/* Enable read look-ahead           */
+#define MV_ATA_SET_FEATURES_ENABLE_RLA          0xAA
+
+/* Enable revert power-on defaults  */
+#define MV_ATA_SET_FEATURES_ENABLE_RPOD         0xCC
+
+/* Disable release interrupt        */
+#define MV_ATA_SET_FEATURES_DISABLE_RI          0xDD
+
+/* Disable SERVICE interrupt        */
+#define MV_ATA_SET_FEATURES_DISABLE_SI          0xDE
+
+/* Defines for parsing the IDENTIFY command results*/
+#define IDEN_SERIAL_NUM_OFFSET                  10
+#define IDEN_SERIAL_NUM_SIZE                    (20 - 10)
+#define IDEN_FIRMWARE_OFFSET                    23
+#define IDEN_FIRMWARE_SIZE                      (27 - 23)
+#define IDEN_MODEL_OFFSET                       27
+#define IDEN_MODEL_SIZE                         (47 - 27)
+#define IDEN_CAPACITY_1_OFFSET                  49
+#define IDEN_VALID                              53
+#define IDEN_NUM_OF_ADDRESSABLE_SECTORS         60
+#define IDEN_PIO_MODE_SPPORTED                  64
+#define IDEN_QUEUE_DEPTH                        75
+#define IDEN_SATA_CAPABILITIES                  76
+#define IDEN_SATA_FEATURES_SUPPORTED            78
+#define IDEN_SATA_FEATURES_ENABLED              79
+#define IDEN_ATA_VERSION                        80
+#define IDEN_SUPPORTED_COMMANDS1                82
+#define IDEN_SUPPORTED_COMMANDS2                83
+#define IDEN_ENABLED_COMMANDS1                  85
+#define IDEN_ENABLED_COMMANDS2                  86
+#define IDEN_UDMA_MODE                          88
+
+/* Typedefs    */
+
+/* Structures  */
+
+	typedef struct mvStorageDevRegisters {
+/* Fields set by CORE driver */
+		MV_U8 errorRegister;
+		MV_U16 featuresRegister;	/*input only */
+		MV_U8 commandRegister;	/*input only */
+		MV_U16 sectorCountRegister;
+		MV_U16 lbaLowRegister;
+		MV_U16 lbaMidRegister;
+		MV_U16 lbaHighRegister;
+		MV_U8 deviceRegister;
+		MV_U8 statusRegister;
+	} MV_STORAGE_DEVICE_REGISTERS;
+
+/* Function */
+
+	MV_BOOLEAN mvStorageDevATAExecuteNonUDMACommand(MV_SATA_ADAPTER *pAdapter,
+							MV_U8 channelIndex,
+							MV_U8 PMPort,
+							MV_NON_UDMA_PROTOCOL protocolType,
+							MV_BOOLEAN isEXT,
+							MV_U16_PTR bufPtr, MV_U32 count,
+							MV_U16 features,
+							MV_U16 sectorCount,
+							MV_U16 lbaLow, MV_U16 lbaMid,
+							MV_U16 lbaHigh, MV_U8 device, MV_U8 command);
+
+	MV_BOOLEAN mvStorageDevATAIdentifyDevice(MV_SATA_ADAPTER *pAdapter,
+						 MV_U8 channelIndex, MV_U8 PMPort, MV_U16_PTR identifyDeviceResult);
+
+	MV_BOOLEAN mvStorageDevATASetFeatures(MV_SATA_ADAPTER *pAdapter,
+					      MV_U8 channelIndex,
+					      MV_U8 PMPort,
+					      MV_U8 subCommand,
+					      MV_U8 subCommandSpecific1,
+					      MV_U8 subCommandSpecific2,
+					      MV_U8 subCommandSpecific3, MV_U8 subCommandSpecific4);
+
+	MV_BOOLEAN mvStorageDevATAIdleImmediate(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+	MV_BOOLEAN mvStorageDevATASoftResetDevice(MV_SATA_ADAPTER *pAdapter,
+						  MV_U8 channelIndex,
+						  MV_U8 PMPort, MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+	 /*PM*/
+	MV_BOOLEAN mvPMDevReadReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+				      MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue,
+				      MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+	MV_BOOLEAN mvPMDevWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+				   MV_U8 PMPort, MV_U8 PMReg, MV_U32 value,
+				   MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+	MV_BOOLEAN mvPMDevEnableStaggeredSpinUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort);
+
+	MV_BOOLEAN mvPMDevEnableStaggeredSpinUpAll(MV_SATA_ADAPTER *pAdapter,
+						   MV_U8 channelIndex, MV_U8 PMNumOfPorts, MV_U16 *bitmask);
+
+	MV_BOOLEAN mvPMDevEnableStaggeredSpinUpPort(MV_SATA_ADAPTER *pSataAdapter,
+						    MV_U8 channelIndex, MV_U8 PMPort, MV_BOOLEAN force_gen1);
+
+	MV_BOOLEAN mvPMLinkUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort, MV_BOOLEAN force_gen1);
+
+	MV_BOOLEAN mvStorageDevExecutePIO(MV_SATA_ADAPTER *pAdapter,
+					  MV_U8 channelIndex,
+					  MV_U8 PMPort,
+					  MV_NON_UDMA_PROTOCOL protocolType,
+					  MV_BOOLEAN isEXT, MV_U16_PTR bufPtr,
+					  MV_U32 count,
+					  MV_STORAGE_DEVICE_REGISTERS *pInATARegs,
+					  MV_STORAGE_DEVICE_REGISTERS *pOutATARegs);
+
+	MV_BOOLEAN mvStorageDevATAStartSoftResetDevice(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort);
+
+	MV_BOOLEAN mvStorageIsDeviceBsyBitOff(MV_SATA_ADAPTER *pAdapter,
+					      MV_U8 channelIndex, MV_STORAGE_DEVICE_REGISTERS *registerStruct);
+
+	MV_BOOLEAN mvStorageDevSetDeviceType(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
+					     MV_SATA_DEVICE_TYPE deviceType);
+
+	MV_SATA_DEVICE_TYPE mvStorageDevGetDeviceType(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
+
+#ifdef __cplusplus
+
+}
+#endif				/* __cplusplus */
+#endif				/* __INCmvStorageDevh */
diff --git a/arch/arm/plat-feroceon/mv_hal/sata/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/sata/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sata/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/sdmmc/mvSdmmc.h b/arch/arm/plat-feroceon/mv_hal/sdmmc/mvSdmmc.h
new file mode 100755
index 0000000..164085f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sdmmc/mvSdmmc.h
@@ -0,0 +1,73 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCMVSdmmcH
+#define __INCMVSdmmcH
+
+#include "mvCommon.h"
+
+MV_STATUS mvSdmmcWinInit(MV_UNIT_WIN_INFO *addrWinMap);
+MV_STATUS mvSdmmcWinRead(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+MV_STATUS mvSdmmcWinWrite(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/sdmmc/mvSdmmcAddrDec.c b/arch/arm/plat-feroceon/mv_hal/sdmmc/mvSdmmcAddrDec.c
new file mode 100755
index 0000000..c58adce
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sdmmc/mvSdmmcAddrDec.c
@@ -0,0 +1,322 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysSdmmcConfig.h"
+#include "mvSdmmc.h"
+
+#define MV_SDMMC_MAX_ADDR_DECODE_WIN 4
+
+#define MV_SDMMC_WIN_CTRL_REG(dev, win)        (MV_SDMMC_REGS_BASE + 0x108 + ((win)<<3))
+#define MV_SDMMC_WIN_BASE_REG(dev, win)        (MV_SDMMC_REGS_BASE + 0x10c + ((win)<<3))
+
+/* BITs in Windows 0-3 Control and Base Registers */
+#define MV_SDMMC_WIN_ENABLE_BIT               0
+#define MV_SDMMC_WIN_ENABLE_MASK              (1<<MV_SDMMC_WIN_ENABLE_BIT)
+
+#define MV_SDMMC_WIN_TARGET_OFFSET            4
+#define MV_SDMMC_WIN_TARGET_MASK              (0xF<<MV_SDMMC_WIN_TARGET_OFFSET)
+
+#define MV_SDMMC_WIN_ATTR_OFFSET              8
+#define MV_SDMMC_WIN_ATTR_MASK                (0xFF<<MV_SDMMC_WIN_ATTR_OFFSET)
+
+#define MV_SDMMC_WIN_SIZE_OFFSET              16
+#define MV_SDMMC_WIN_SIZE_MASK                (0xFFFF<<MV_SDMMC_WIN_SIZE_OFFSET)
+
+#define MV_SDMMC_WIN_BASE_OFFSET              16
+#define MV_SDMMC_WIN_BASE_MASK                (0xFFFF<<MV_SDMMC_WIN_BASE_OFFSET)
+
+#define MV_SDMMC_WIN_SIZE_ALIGN		    _64K
+
+MV_TARGET sdmmcAddrDecPrioTab[] = {
+#if defined(MV_INCLUDE_SDRAM_CS0)
+	SDRAM_CS0,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS1)
+	SDRAM_CS1,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS2)
+	SDRAM_CS2,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS3)
+	SDRAM_CS3,
+#endif
+#if defined(MV_INCLUDE_PEX)
+	PEX0_MEM,
+#endif
+	TBL_TERM
+};
+
+/*******************************************************************************
+* sdmmcWinOverlapDetect - Detect SDMMC address windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviur is expected in case SDMMC address decode
+*       windows overlapps.
+*       This function detects SDMMC address decode windows overlapping of a
+*       specified window. The function does not check the window itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS sdmmcWinOverlapDetect(int dev, MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 winNumIndex;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	for (winNumIndex = 0; winNumIndex < MV_SDMMC_MAX_ADDR_DECODE_WIN; winNumIndex++) {
+		/* Do not check window itself       */
+		if (winNumIndex == winNum)
+			continue;
+
+		/* Get window parameters    */
+		if (MV_OK != mvSdmmcWinRead(dev, winNumIndex, &addrDecWin)) {
+			mvOsPrintf("%s: ERR. mvSdmmcWinRead failed\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled windows    */
+		if (addrDecWin.enable == MV_FALSE)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+			return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvSdmmcWinWrite - Set SDMMC target address window
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0)
+*       address window, also known as address decode window.
+*       After setting this target window, the SDMMC will be able to access the
+*       target within the address window.
+*
+* INPUT:
+*       winNum      - SDMMC target address decode window number.
+*       pAddrDecWin - SDMMC target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if address window overlapps with other address decode windows.
+*       MV_BAD_PARAM if base address is invalid parameter or target is
+*       unknown.
+*
+*******************************************************************************/
+MV_STATUS mvSdmmcWinWrite(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+
+	/* Parameter checking   */
+	if (winNum >= MV_SDMMC_MAX_ADDR_DECODE_WIN) {
+		mvOsPrintf("%s: ERR. Invalid win num %d\n", __func__, winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlapps with current windows         */
+	if (MV_TRUE == sdmmcWinOverlapDetect(dev, winNum, &pAddrDecWin->addrWin)) {
+		mvOsPrintf("%s: ERR. Window %d overlap\n", __func__, winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) {
+		mvOsPrintf("mvSdmmcWinWrite:Error setting SDMMC window %d.\n"
+			   "Address 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	baseReg = pAddrDecWin->addrWin.baseLow & MV_SDMMC_WIN_BASE_MASK;
+	sizeReg = (pAddrDecWin->addrWin.size / MV_SDMMC_WIN_SIZE_ALIGN) - 1;
+	sizeReg = sizeReg << MV_SDMMC_WIN_SIZE_OFFSET;
+
+	/* set attributes */
+	sizeReg &= ~MV_SDMMC_WIN_ATTR_MASK;
+	sizeReg |= (pAddrDecWin->attrib << MV_SDMMC_WIN_ATTR_OFFSET);
+
+	/* set target ID */
+	sizeReg &= ~MV_SDMMC_WIN_TARGET_MASK;
+	sizeReg |= (pAddrDecWin->targetId << MV_SDMMC_WIN_TARGET_OFFSET);
+
+	if (pAddrDecWin->enable == MV_TRUE)
+		sizeReg |= MV_SDMMC_WIN_ENABLE_MASK;
+	else
+		sizeReg &= ~MV_SDMMC_WIN_ENABLE_MASK;
+
+	MV_REG_WRITE(MV_SDMMC_WIN_CTRL_REG(dev, winNum), sizeReg);
+	MV_REG_WRITE(MV_SDMMC_WIN_BASE_REG(dev, winNum), baseReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSdmmcWinRead - Read SDMMC peripheral target address window.
+*
+* DESCRIPTION:
+*       Get SDMMC peripheral target address window.
+*
+* INPUT:
+*       winNum - SDMMC target address decode window number.
+*
+* OUTPUT:
+*       pAddrDecWin - SDMMC target window data structure.
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvSdmmcWinRead(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+	MV_U32 sizeRegVal;
+
+	/* Parameter checking   */
+	if (winNum >= MV_SDMMC_MAX_ADDR_DECODE_WIN) {
+		mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", __func__, dev, winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	baseReg = MV_REG_READ(MV_SDMMC_WIN_BASE_REG(dev, winNum));
+	sizeReg = MV_REG_READ(MV_SDMMC_WIN_CTRL_REG(dev, winNum));
+
+	/* Extract base address and size    */
+	sizeRegVal = (sizeReg & MV_SDMMC_WIN_SIZE_MASK) >> MV_SDMMC_WIN_SIZE_OFFSET;
+	pAddrDecWin->addrWin.size = (sizeRegVal + 1) * MV_SDMMC_WIN_SIZE_ALIGN;
+	pAddrDecWin->addrWin.baseLow = baseReg & MV_SDMMC_WIN_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh = 0;
+
+	/* attrib and targetId              */
+	pAddrDecWin->attrib = (sizeReg & MV_SDMMC_WIN_ATTR_MASK) >> MV_SDMMC_WIN_ATTR_OFFSET;
+	pAddrDecWin->targetId = (sizeReg & MV_SDMMC_WIN_TARGET_MASK) >> MV_SDMMC_WIN_TARGET_OFFSET;
+
+	/* Check if window is enabled       */
+	if (sizeReg & MV_SDMMC_WIN_ENABLE_MASK)
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSdmmcWinInit - Initialize the integrated SDMMC target address window.
+*
+* DESCRIPTION:
+*       Initialize the SDMMC peripheral target address window.
+*
+* INPUT:
+*
+*
+* OUTPUT:
+*
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvSdmmcWinInit(MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 winNum;
+	MV_UNIT_WIN_INFO *addrDecWin;
+	MV_U32 winPrioIndex = 0;
+
+	/* Initiate Sdmmc address decode */
+
+	/* First disable all address decode windows */
+	for (winNum = 0; winNum < MV_SDMMC_MAX_ADDR_DECODE_WIN; winNum++) {
+		MV_U32 regVal = MV_REG_READ(MV_SDMMC_WIN_CTRL_REG(0, winNum));
+		regVal &= ~MV_SDMMC_WIN_ENABLE_MASK;
+		MV_REG_WRITE(MV_SDMMC_WIN_CTRL_REG(0, winNum), regVal);
+	}
+
+	winNum = 0;
+	while ((sdmmcAddrDecPrioTab[winPrioIndex] != TBL_TERM) && (winNum < MV_SDMMC_MAX_ADDR_DECODE_WIN)) {
+		addrDecWin = &addrWinMap[sdmmcAddrDecPrioTab[winPrioIndex]];
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvSdmmcWinWrite(0, winNum, addrDecWin))
+				return MV_ERROR;
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/sflash/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/sflash/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sflash/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlash.c b/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlash.c
new file mode 100755
index 0000000..07fbd60
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlash.c
@@ -0,0 +1,1657 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSFlash.h"
+#include "mvSFlashSpec.h"
+#include "mvSysSFlash.h"
+
+
+/*#define MV_DEBUG*/
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+/* Globals */
+static MV_U32 flSize;
+static MV_U32 cmndLength;
+static MV_SFLASH_DEVICE_PARAMS sflash[] = {
+    /* ST M25P32 SPI flash, 4MB, 64 sectors of 64K each */
+    {
+     MV_M25P_WREN_CMND_OPCD,
+     MV_M25P_WRDI_CMND_OPCD,
+     MV_M25P_RDID_CMND_OPCD,
+     MV_M25P_RDSR_CMND_OPCD,
+     MV_M25P_WRSR_CMND_OPCD,
+     MV_M25P_READ_CMND_OPCD,
+     MV_M25P_FAST_RD_CMND_OPCD,
+     MV_M25P_PP_CMND_OPCD,
+     MV_M25P_SE_CMND_OPCD,
+     MV_M25P_BE_CMND_OPCD,
+     MV_M25P_RES_CMND_OPCD,
+     MV_SFLASH_NO_SPECIFIC_OPCD,    /* power save not supported */
+     MV_M25P32_SECTOR_SIZE,
+     MV_M25P32_SECTOR_NUMBER,
+     MV_M25P_PAGE_SIZE,
+     "ST M25P32",
+     MV_M25PXXX_ST_MANF_ID,
+     MV_M25P32_DEVICE_ID,
+     MV_M25P32_MAX_SPI_FREQ,
+     MV_M25P32_MAX_FAST_SPI_FREQ,
+     MV_M25P32_FAST_READ_DUMMY_BYTES
+    },
+    /* ST M25P64 SPI flash, 8MB, 128 sectors of 64K each */
+    {
+     MV_M25P_WREN_CMND_OPCD,
+     MV_M25P_WRDI_CMND_OPCD,
+     MV_M25P_RDID_CMND_OPCD,
+     MV_M25P_RDSR_CMND_OPCD,
+     MV_M25P_WRSR_CMND_OPCD,
+     MV_M25P_READ_CMND_OPCD,
+     MV_M25P_FAST_RD_CMND_OPCD,
+     MV_M25P_PP_CMND_OPCD,
+     MV_M25P_SE_CMND_OPCD,
+     MV_M25P_BE_CMND_OPCD,
+     MV_M25P_RES_CMND_OPCD,
+     MV_SFLASH_NO_SPECIFIC_OPCD,    /* power save not supported */
+     MV_M25P64_SECTOR_SIZE,
+     MV_M25P64_SECTOR_NUMBER,
+     MV_M25P_PAGE_SIZE,
+     "ST M25P64",
+     MV_M25PXXX_ST_MANF_ID,
+     MV_M25P64_DEVICE_ID,
+     MV_M25P64_MAX_SPI_FREQ,
+     MV_M25P64_MAX_FAST_SPI_FREQ,
+     MV_M25P64_FAST_READ_DUMMY_BYTES
+    },
+    /* ST M25P128 SPI flash, 16MB, 64 sectors of 256K each */
+    {
+     MV_M25P_WREN_CMND_OPCD,
+     MV_M25P_WRDI_CMND_OPCD,
+     MV_M25P_RDID_CMND_OPCD,
+     MV_M25P_RDSR_CMND_OPCD,
+     MV_M25P_WRSR_CMND_OPCD,
+     MV_M25P_READ_CMND_OPCD,
+     MV_M25P_FAST_RD_CMND_OPCD,
+     MV_M25P_PP_CMND_OPCD,
+     MV_M25P_SE_CMND_OPCD,
+     MV_M25P_BE_CMND_OPCD,
+     MV_M25P_RES_CMND_OPCD,
+     MV_SFLASH_NO_SPECIFIC_OPCD,    /* power save not supported */
+     MV_M25P128_SECTOR_SIZE,
+     MV_M25P128_SECTOR_NUMBER,
+     MV_M25P_PAGE_SIZE,
+     "ST M25P128",
+     MV_M25PXXX_ST_MANF_ID,
+     MV_M25P128_DEVICE_ID,
+     MV_M25P128_MAX_SPI_FREQ,
+     MV_M25P128_MAX_FAST_SPI_FREQ,
+     MV_M25P128_FAST_READ_DUMMY_BYTES
+    },
+/* ST M25Q128 SPI flash, 16MB, 256 sectors of 64K each */
+    {
+     MV_M25P_WREN_CMND_OPCD,
+     MV_M25P_WRDI_CMND_OPCD,
+     MV_M25P_RDID_CMND_OPCD,
+     MV_M25P_RDSR_CMND_OPCD,
+     MV_M25P_WRSR_CMND_OPCD,
+     MV_M25P_READ_CMND_OPCD,
+     MV_M25P_FAST_RD_CMND_OPCD,
+     MV_M25P_PP_CMND_OPCD,
+     MV_M25P_SE_CMND_OPCD,
+     MV_M25P_BE_CMND_OPCD,
+     MV_M25P_RES_CMND_OPCD,
+     MV_SFLASH_NO_SPECIFIC_OPCD,    /* power save not supported */
+     MV_SFLASH_NO_SPECIFIC_OPCD,
+     MV_M25Q128_SECTOR_SIZE,
+     MV_M25Q128_SECTOR_NUMBER,
+     MV_M25Q_PAGE_SIZE,
+     "ST M25Q128",
+     MV_M25PXXX_ST_MANF_ID,
+     MV_M25Q128_DEVICE_ID,
+     MV_M25Q128_MAX_SPI_FREQ,
+     MV_M25Q128_MAX_FAST_SPI_FREQ,
+     MV_M25Q128_FAST_READ_DUMMY_BYTES
+    },
+    /* Macronix MXIC MX25L6405 SPI flash, 8MB, 128 sectors of 64K each */
+    {
+     MV_MX25L_WREN_CMND_OPCD,
+     MV_MX25L_WRDI_CMND_OPCD,
+     MV_MX25L_RDID_CMND_OPCD,
+     MV_MX25L_RDSR_CMND_OPCD,
+     MV_MX25L_WRSR_CMND_OPCD,
+     MV_MX25L_READ_CMND_OPCD,
+     MV_MX25L_FAST_RD_CMND_OPCD,
+     MV_MX25L_PP_CMND_OPCD,
+     MV_MX25L_SE_CMND_OPCD,
+     MV_MX25L_BE_CMND_OPCD,
+     MV_MX25L_RES_CMND_OPCD,
+     MV_MX25L_DP_CMND_OPCD,
+     MV_SFLASH_NO_SPECIFIC_OPCD,
+     MV_MX25L1605_SECTOR_SIZE,
+     MV_MX25L1605_SECTOR_NUMBER,
+     MV_MXIC_PAGE_SIZE,
+     "MXIC MX25L1605",
+     MV_MXIC_MANF_ID,
+     MV_MX25L1605_DEVICE_ID,
+     MV_MX25L1605_MAX_SPI_FREQ,
+     MV_MX25L1605_MAX_FAST_SPI_FREQ,
+     MV_MX25L1605_FAST_READ_DUMMY_BYTES
+    },
+    /* Macronix MXIC MX25L3205 SPI flash, 4MB, 64 sectors of 64K each */
+    {
+     MV_MX25L_WREN_CMND_OPCD,
+     MV_MX25L_WRDI_CMND_OPCD,
+     MV_MX25L_RDID_CMND_OPCD,
+     MV_MX25L_RDSR_CMND_OPCD,
+     MV_MX25L_WRSR_CMND_OPCD,
+     MV_MX25L_READ_CMND_OPCD,
+     MV_MX25L_FAST_RD_CMND_OPCD,
+     MV_MX25L_PP_CMND_OPCD,
+     MV_MX25L_SE_CMND_OPCD,
+     MV_MX25L_BE_CMND_OPCD,
+     MV_MX25L_RES_CMND_OPCD,
+     MV_MX25L_DP_CMND_OPCD,
+     MV_SFLASH_NO_SPECIFIC_OPCD,
+     MV_MX25L3205_SECTOR_SIZE,
+     MV_MX25L3205_SECTOR_NUMBER,
+     MV_MXIC_PAGE_SIZE,
+     "MXIC MX25L3205",
+     MV_MXIC_MANF_ID,
+     MV_MX25L3205_DEVICE_ID,
+     MV_MX25L3205_MAX_SPI_FREQ,
+     MV_MX25L3205_MAX_FAST_SPI_FREQ,
+     MV_MX25L3205_FAST_READ_DUMMY_BYTES
+    },
+    /* Macronix MXIC MX25L6405 SPI flash, 8MB, 128 sectors of 64K each */
+    {
+     MV_MX25L_WREN_CMND_OPCD,
+     MV_MX25L_WRDI_CMND_OPCD,
+     MV_MX25L_RDID_CMND_OPCD,
+     MV_MX25L_RDSR_CMND_OPCD,
+     MV_MX25L_WRSR_CMND_OPCD,
+     MV_MX25L_READ_CMND_OPCD,
+     MV_MX25L_FAST_RD_CMND_OPCD,
+     MV_MX25L_PP_CMND_OPCD,
+     MV_MX25L_SE_CMND_OPCD,
+     MV_MX25L_BE_CMND_OPCD,
+     MV_MX25L_RES_CMND_OPCD,
+     MV_MX25L_DP_CMND_OPCD,
+     MV_SFLASH_NO_SPECIFIC_OPCD,
+     MV_MX25L6405_SECTOR_SIZE,
+     MV_MX25L6405_SECTOR_NUMBER,
+     MV_MXIC_PAGE_SIZE,
+     "MXIC MX25L6405",
+     MV_MXIC_MANF_ID,
+     MV_MX25L6405_DEVICE_ID,
+     MV_MX25L6405_MAX_SPI_FREQ,
+     MV_MX25L6405_MAX_FAST_SPI_FREQ,
+     MV_MX25L6405_FAST_READ_DUMMY_BYTES
+    },
+    /* Macronix MXIC MX25L25635E SPI flash, 32MB, 512 sectors of 64K each */
+    {
+     MV_MX25L_WREN_CMND_OPCD,
+     MV_MX25L_WRDI_CMND_OPCD,
+     MV_MX25L_RDID_CMND_OPCD,
+     MV_MX25L_RDSR_CMND_OPCD,
+     MV_MX25L_WRSR_CMND_OPCD,
+     MV_MX25L_READ_CMND_OPCD,
+     MV_MX25L_FAST_RD_CMND_OPCD,
+     MV_MX25L_PP_CMND_OPCD,
+     MV_MX25L_SE_CMND_OPCD,
+     MV_MX25L_BE_CMND_OPCD,
+     MV_MX25L_RES_CMND_OPCD,
+     MV_MX25L_DP_CMND_OPCD,
+     MV_MX25L_EN4B_CMND_OPCD,
+     MV_MX25L25635E_SECTOR_SIZE,
+     MV_MX25L25635E_SECTOR_NUMBER,
+     MV_MXIC_PAGE_SIZE,
+     "MXIC MX25L25635E",
+     MV_MXIC_MANF_ID,
+     MV_MX25L25635E_DEVICE_ID,
+     MV_MX25L25635E_MAX_SPI_FREQ,
+     MV_MX25L25635E_MAX_FAST_SPI_FREQ,
+     MV_MX25L25635E_FAST_READ_DUMMY_BYTES
+    },
+    /* SPANSION S25FL128P SPI flash, 16MB, 64 sectors of 256K each */
+    {
+     MV_S25FL_WREN_CMND_OPCD,
+     MV_S25FL_WRDI_CMND_OPCD,
+     MV_S25FL_RDID_CMND_OPCD,
+     MV_S25FL_RDSR_CMND_OPCD,
+     MV_S25FL_WRSR_CMND_OPCD,
+     MV_S25FL_READ_CMND_OPCD,
+     MV_S25FL_FAST_RD_CMND_OPCD,
+     MV_S25FL_PP_CMND_OPCD,
+     MV_S25FL_SE_CMND_OPCD,
+     MV_S25FL_BE_CMND_OPCD,
+     MV_S25FL_RES_CMND_OPCD,
+     MV_S25FL_DP_CMND_OPCD,
+     MV_SFLASH_NO_SPECIFIC_OPCD,
+     MV_S25FL128_SECTOR_SIZE,
+     MV_S25FL128_SECTOR_NUMBER,
+     MV_S25FL_PAGE_SIZE,
+     "SPANSION S25FL128",
+     MV_SPANSION_MANF_ID,
+     MV_S25FL128_DEVICE_ID,
+     MV_S25FL128_MAX_SPI_FREQ,
+     MV_M25P128_MAX_FAST_SPI_FREQ,
+     MV_M25P128_FAST_READ_DUMMY_BYTES
+    }
+};
+
+/* Static Functions */
+static MV_STATUS    mvWriteEnable(MV_SFLASH_INFO *pFlinfo);
+static MV_STATUS    mvStatusRegGet(MV_SFLASH_INFO *pFlinfo, MV_U8 *pStatReg);
+static MV_STATUS    mvStatusRegSet(MV_SFLASH_INFO *pFlinfo, MV_U8 sr);
+static MV_STATUS    mvWaitOnWipClear(MV_SFLASH_INFO *pFlinfo);
+static MV_STATUS    mvSFlashPageWr(MV_SFLASH_INFO *pFlinfo, MV_U32 offset, \
+					MV_U8 *pPageBuff, MV_U32 buffSize);
+static MV_STATUS    mvSFlashWithDefaultsIdGet(MV_SFLASH_INFO *pFlinfo, \
+						MV_U8 *manId, MV_U16 *devId);
+
+/*******************************************************************************
+* mvWriteEnable - serialize the write enable sequence
+*
+* DESCRIPTION:
+*       transmit the sequence for write enable
+*
+********************************************************************************/
+static MV_STATUS mvWriteEnable(MV_SFLASH_INFO *pFlinfo)
+{
+	MV_U8 cmd[MV_SFLASH_WREN_CMND_LENGTH];
+
+	cmd[0] = sflash[pFlinfo->index].opcdWREN;
+
+	/*  mvSpiWriteThenRead(MV_SFLASH_WREN_CMND_LENGTH); */
+	return mvSysSflashCommandSet(0, cmd, MV_SFLASH_WREN_CMND_LENGTH,
+			SYS_SFLASH_TRANS_ATOMIC);
+}
+
+/*******************************************************************************
+* mvStatusRegGet - Retrieve the value of the status register
+*
+* DESCRIPTION:
+*       perform the RDSR sequence to get the 8bit status register
+*
+********************************************************************************/
+static MV_STATUS mvStatusRegGet(MV_SFLASH_INFO *pFlinfo, MV_U8 *pStatReg)
+{
+    MV_STATUS ret;
+	MV_U8 cmd[MV_SFLASH_RDSR_CMND_LENGTH];
+	MV_U8 sr[MV_SFLASH_RDSR_REPLY_LENGTH];
+
+	cmd[0] = sflash[pFlinfo->index].opcdRDSR;
+
+	/*  mvSpiWriteThenRead(MV_SFLASH_RDSR_CMND_LENGTH, sr,MV_SFLASH_RDSR_REPLY_LENGTH) */
+	ret = mvSysSflashCommandSet(NULL,  cmd, MV_SFLASH_RDSR_CMND_LENGTH,
+			SYS_SFLASH_TRANS_START);
+	if (ret == MV_OK) {
+		ret = mvSysSflashDataRead(NULL, sr, MV_SFLASH_RDSR_REPLY_LENGTH, 0,
+				SYS_SFLASH_TRANS_END);
+	}
+	if (ret != MV_OK)
+		return ret;
+
+    *pStatReg = sr[0];
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvWaitOnWipClear - Block waiting for the WIP (write in progress) to be cleared
+*
+* DESCRIPTION:
+*       Block waiting for the WIP (write in progress) to be cleared
+*
+********************************************************************************/
+static MV_STATUS mvWaitOnWipClear(MV_SFLASH_INFO *pFlinfo)
+{
+    MV_STATUS ret;
+	MV_U32 i;
+    MV_U8 stat;
+
+	for (i = 0; i < MV_SFLASH_MAX_WAIT_LOOP; i++) {
+	ret = mvStatusRegGet(pFlinfo, &stat);
+	if (ret != MV_OK)
+		return ret;
+
+		if ((stat & MV_SFLASH_STATUS_REG_WIP_MASK) == 0)
+			return MV_OK;
+	}
+
+    DB(mvOsPrintf("%s WARNING: Write Timeout!\n", __func__);)
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+* mvWaitOnChipEraseDone - Block waiting for the WIP (write in progress) to be
+*                         cleared after a chip erase command which is supposed
+*                         to take about 2:30 minutes
+*
+* DESCRIPTION:
+*       Block waiting for the WIP (write in progress) to be cleared
+*
+********************************************************************************/
+static MV_STATUS mvWaitOnChipEraseDone(MV_SFLASH_INFO *pFlinfo)
+{
+    MV_STATUS ret;
+	MV_U32 i;
+    MV_U8 stat;
+
+	for (i = 0; i < MV_SFLASH_CHIP_ERASE_MAX_WAIT_LOOP; i++) {
+	ret = mvStatusRegGet(pFlinfo, &stat);
+	if (ret != MV_OK)
+		return ret;
+
+		if ((stat & MV_SFLASH_STATUS_REG_WIP_MASK) == 0)
+			return MV_OK;
+	}
+
+    DB(mvOsPrintf("%s WARNING: Write Timeout!\n", __func__);)
+	return MV_TIMEOUT;
+}
+
+/*******************************************************************************
+*  mvStatusRegSet - Set the value of the 8bit status register
+*
+* DESCRIPTION:
+*       Set the value of the 8bit status register
+*
+********************************************************************************/
+static MV_STATUS mvStatusRegSet(MV_SFLASH_INFO *pFlinfo, MV_U8 sr)
+{
+    MV_STATUS ret;
+	MV_U8 cmd[MV_SFLASH_WRSR_CMND_LENGTH];
+
+	/* Issue the Write enable command prior the WRSR command */
+	ret = mvWriteEnable(pFlinfo);
+	if (ret != MV_OK)
+		return ret;
+
+	/* Write the SR with the new values */
+	cmd[0] = sflash[pFlinfo->index].opcdWRSR;
+	cmd[1] = sr;
+
+	/*  mvSpiWriteThenRead(MV_SFLASH_WRSR_CMND_LENGTH) */
+	ret = mvSysSflashCommandSet(NULL,  cmd, MV_SFLASH_WRSR_CMND_LENGTH, SYS_SFLASH_TRANS_ATOMIC);
+	if (ret != MV_OK)
+		return ret;
+	ret = mvWaitOnWipClear(pFlinfo);
+	if (ret != MV_OK)
+		return ret;
+
+	mvOsDelay(1);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashPageWr - Write up to 256 Bytes in the same page
+*
+* DESCRIPTION:
+*       Write a buffer up to the page size in length provided that the whole address
+*		range is within the same page (alligned to page bounderies)
+*
+*******************************************************************************/
+static MV_STATUS mvSFlashPageWr(MV_SFLASH_INFO *pFlinfo, MV_U32 offset,
+							     MV_U8 *pPageBuff, MV_U32 buffSize)
+{
+    	MV_STATUS ret;
+	MV_U8 cmd[MV_SFLASH_MAX_CMND_LENGTH];
+
+	/* Protection - check if the model was detected */
+	if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+		DB(mvOsPrintf("%s WARNING: Invalid parameter device index!\n", __func__););
+		return MV_BAD_PARAM;
+	}
+
+	/* check that we do not cross the page bounderies */
+	if (((offset & (sflash[pFlinfo->index].pageSize - 1)) + buffSize) >
+			sflash[pFlinfo->index].pageSize) {
+		DB(mvOsPrintf("%s WARNING: Page allignment problem!\n", __func__););
+		return MV_OUT_OF_RANGE;
+	}
+
+	/* Issue the Write enable command prior the page program command */
+	ret = mvWriteEnable(pFlinfo);
+	if (ret != MV_OK)
+		return ret;
+
+    	cmd[0] = sflash[pFlinfo->index].opcdPP;
+	if (flSize <= _16M) {
+		cmd[1] = ((offset >> 16) & 0xFF);
+		cmd[2] = ((offset >> 8) & 0xFF);
+		cmd[3] = (offset & 0xFF);
+	} else {
+		cmd[1] = ((offset >> 24) & 0xFF);
+		cmd[2] = ((offset >> 16) & 0xFF);
+		cmd[3] = ((offset >> 8) & 0xFF);
+		cmd[4] = (offset & 0xFF);
+	}
+
+	/*  mvSpiWriteThenWrite(MV_SFLASH_PP_CMND_LENGTH, pPageBuff, buffSize) */
+	ret = mvSysSflashCommandSet(NULL, cmd, cmndLength, SYS_SFLASH_TRANS_START);
+	if (ret == MV_OK)
+		ret = mvSysSflashDataWrite(NULL, pPageBuff, buffSize, SYS_SFLASH_TRANS_END);
+	if (ret != MV_OK)
+		return ret;
+	ret = mvWaitOnWipClear(pFlinfo);
+	if (ret != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashWithDefaultsIdGet - Try to read the manufacturer and Device IDs from
+*       the device using the default RDID opcode and the default WREN opcode.
+*
+* DESCRIPTION:
+*       This is used to detect a generic device that uses the default opcodes
+*       for the WREN and RDID.
+*
+********************************************************************************/
+static MV_STATUS mvSFlashWithDefaultsIdGet(MV_SFLASH_INFO *pFlinfo, MV_U8 *manId, MV_U16 *devId)
+{
+    MV_STATUS ret;
+    MV_U8 cmdRDID[MV_SFLASH_RDID_CMND_LENGTH];
+	MV_U8 id[MV_SFLASH_RDID_REPLY_LENGTH] = {0};
+
+	/* Use the default RDID opcode to read the IDs */
+	cmdRDID[0] = MV_SFLASH_DEFAULT_RDID_OPCD;   /* unknown model try default */
+
+	/*  mvSpiWriteThenRead(MV_SFLASH_RDID_CMND_LENGTH, id,MV_SFLASH_RDID_REPLY_LENGTH) */
+	ret = mvSysSflashCommandSet(NULL,  cmdRDID, MV_SFLASH_RDID_CMND_LENGTH, SYS_SFLASH_TRANS_START);
+	if (ret == MV_OK)
+		ret = mvSysSflashDataRead(NULL, id, MV_SFLASH_RDID_REPLY_LENGTH, 0, SYS_SFLASH_TRANS_END);
+
+	*manId = id[0];
+	*devId = 0;
+	*devId |= (id[1] << 8);
+	*devId |= id[2];
+
+	return MV_OK;
+}
+
+/*
+#####################################################################################
+#####################################################################################
+*/
+
+/*******************************************************************************
+* mvSFlashInit - Initialize the serial flash device
+*
+* DESCRIPTION:
+*       Perform the neccessary initialization and configuration
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*           pFlinfo->baseAddr: base address in fast mode.
+*           pFlinfo->index: Index of the flash in the sflash tabel. If the SPI
+*                           flash device does not support read Id command with
+*                           the standard opcode, then the user should supply this
+*                           as an input to skip the autodetection process!!!!
+*
+* OUTPUT:
+*       pFlinfo: pointer to the Flash information structure after detection
+*           pFlinfo->manufacturerId: Manufacturer ID
+*           pFlinfo->deviceId: Device ID
+*           pFlinfo->sectorSize: size of the sector (all sectors are the same).
+*           pFlinfo->sectorNumber: number of sectors.
+*           pFlinfo->pageSize: size of the page.
+*           pFlinfo->index: Index of the detected flash in the sflash tabel
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashInit(MV_SFLASH_INFO *pFlinfo)
+{
+    MV_STATUS ret;
+    MV_U8 manf;
+    MV_U16 dev;
+    MV_U32 indx;
+    MV_U8 cmd;
+    MV_BOOL detectFlag = MV_FALSE;
+
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Initialize the SPI interface with low frequency to make sure that the read ID succeeds */
+    /*  mvSpiInit(0, MV_SFLASH_BASIC_SPI_FREQ); */
+    ret = mvSysSflashFreqSet(NULL, MV_SFLASH_BASIC_SPI_FREQ);
+    if (ret != MV_OK) {
+	mvOsPrintf("%s ERROR: Failed to set base SPI frequency!\n", __func__);
+	return ret;
+    }
+
+    /* First try to read the Manufacturer and Device IDs */
+    ret = mvSFlashIdGet(pFlinfo, &manf, &dev);
+    if (ret != MV_OK) {
+	mvOsPrintf("%s ERROR: Failed to get the SFlash ID!\n", __func__);
+	return ret;
+    }
+
+    /* loop over the whole table and look for the appropriate SFLASH */
+    for (indx = 0; indx < MV_ARRAY_SIZE(sflash); indx++) {
+	if ((manf == sflash[indx].manufacturerId) && (dev == sflash[indx].deviceId)) {
+		pFlinfo->manufacturerId = manf;
+		pFlinfo->deviceId = dev;
+		pFlinfo->index = indx;
+		detectFlag = MV_TRUE;
+	}
+    }
+
+    if (!detectFlag) {
+	mvOsPrintf("%s ERROR: Unknown SPI flash device!\n", __func__);
+	return MV_FAIL;
+    }
+
+    /* fill the info based on the model detected */
+    pFlinfo->sectorSize = sflash[pFlinfo->index].sectorSize;
+    pFlinfo->sectorNumber = sflash[pFlinfo->index].sectorNumber;
+    pFlinfo->pageSize = sflash[pFlinfo->index].pageSize;
+
+    /* Enable 4B address mode in case needed and supported */
+    flSize = (pFlinfo->sectorSize  * pFlinfo->sectorNumber);
+    if (flSize > _16M) {
+	cmndLength = 5;
+    	if (sflash[pFlinfo->index].opcdEn4B != MV_SFLASH_NO_SPECIFIC_OPCD) {
+		mvOsPrintf("%s: Enabling 4-Byte address mode\n", __func__);
+
+	 	cmd = sflash[pFlinfo->index].opcdEn4B;
+
+		/*  mvSpiWriteThenWrite(MV_SFLASH_RES_CMND_LENGTH) */
+		ret = mvSysSflashCommandSet(NULL, &cmd, 1, SYS_SFLASH_TRANS_ATOMIC);
+		
+		if (ret != MV_OK)
+			return ret;
+	}
+    } else
+	cmndLength = 4;
+
+    /* Set the SPI frequency to the MAX allowed for the device for best performance */
+    /*  mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFreq) */
+    ret = mvSysSflashFreqSet(NULL, sflash[pFlinfo->index].spiMaxFreq);
+    if (ret != MV_OK) {
+	 mvOsPrintf("%s ERROR: Failed to set the SPI frequency!\n", __func__);
+	return ret;
+    }
+
+    /* As default lock the SR */
+    ret = mvSFlashStatRegLock(pFlinfo, MV_TRUE);
+    if (ret != MV_OK)
+	return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashSectorErase - Erasse a single sector of the serial flash
+*
+* DESCRIPTION:
+*       Issue the erase sector command and address
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*		secNumber: sector Number to erase (0 -> (sectorNumber-1))
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashSectorErase(MV_SFLASH_INFO *pFlinfo, MV_U32 secNumber)
+{
+    MV_STATUS ret;
+    MV_U8 cmd[MV_SFLASH_MAX_CMND_LENGTH];
+    MV_U32 secAddr;
+#if 0
+    MV_U32 i;
+    MV_U32 *pW = (MV_U32 *) (secAddr + pFlinfo->baseAddr);
+    MV_U32 erasedWord = 0xFFFFFFFF;
+    MV_U32 wordsPerSector = (pFlinfo->sectorSize / sizeof(MV_U32));
+    MV_BOOL eraseNeeded = MV_FALSE;
+#endif
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+    secAddr = (secNumber * pFlinfo->sectorSize);
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+    /* check that the sector number is valid */
+    if (secNumber >= pFlinfo->sectorNumber) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter sector number!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+    /* we don't want to access SPI in direct mode from in-direct API,
+	becasue of timing issue between CS asserts. */
+#if 0
+    /* First compare to FF and check if erase is needed */
+    for (i = 0; i < wordsPerSector; i++)  {
+	if (memcmp(pW, &erasedWord, sizeof(MV_U32)) != 0) {
+		eraseNeeded = MV_TRUE;
+		break;
+	}
+
+	++pW;
+    }
+    if (!eraseNeeded)
+	return MV_OK;
+#endif
+
+    	cmd[0] = sflash[pFlinfo->index].opcdSE;
+	if (flSize <= _16M) {
+		cmd[1] = ((secAddr >> 16) & 0xFF);
+		cmd[2] = ((secAddr >> 8) & 0xFF);
+		cmd[3] = (secAddr & 0xFF);
+	} else {
+		cmd[1] = ((secAddr >> 24) & 0xFF);
+		cmd[2] = ((secAddr >> 16) & 0xFF);
+		cmd[3] = ((secAddr >> 8) & 0xFF);
+		cmd[4] = (secAddr & 0xFF);
+	}
+
+	/* Issue the Write enable command prior the sector erase command */
+	ret = mvWriteEnable(pFlinfo);
+	if (ret != MV_OK)
+		return ret;
+
+	/*  mvSpiWriteThenWrite(MV_SFLASH_SE_CMND_LENGTH) */
+	ret = mvSysSflashCommandSet(NULL, cmd, cmndLength, SYS_SFLASH_TRANS_ATOMIC);
+	if (ret != MV_OK)
+		return ret;
+	ret = mvWaitOnWipClear(pFlinfo);
+	if (ret != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashChipErase - Erasse the whole serial flash
+*
+* DESCRIPTION:
+*       Issue the bulk (chip) erase command
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashChipErase(MV_SFLASH_INFO *pFlinfo)
+{
+    MV_STATUS ret;
+	MV_U8 cmd[MV_SFLASH_BE_CMND_LENGTH];
+
+
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+    cmd[0] = sflash[pFlinfo->index].opcdBE;
+
+	/* Issue the Write enable command prior the Bulk erase command */
+	ret = mvWriteEnable(pFlinfo);
+	if (ret != MV_OK)
+		return ret;
+
+	/*  mvSpiWriteThenWrite(MV_SFLASH_BE_CMND_LENGTH) */
+	ret = mvSysSflashCommandSet(NULL, cmd, MV_SFLASH_BE_CMND_LENGTH, SYS_SFLASH_TRANS_ATOMIC);
+	if (ret != MV_OK)
+		return ret;
+	ret = mvWaitOnChipEraseDone(pFlinfo);
+	if (ret != MV_OK)
+		return ret;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashBlockRd - Read from the serial flash
+*
+* DESCRIPTION:
+*       Issue the read command and address then perfom the needed read
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*		offset: byte offset with the flash to start reading from
+*		pReadBuff: pointer to the buffer to read the data in
+*		buffSize: size of the buffer to read.
+*
+* OUTPUT:
+*       pReadBuff: pointer to the buffer containing the read data
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashBlockRd(MV_SFLASH_INFO *pFlinfo, MV_U32 offset,
+						   MV_U8 *pReadBuff, MV_U32 buffSize)
+{
+	MV_U8 cmd[MV_SFLASH_MAX_CMND_LENGTH];
+	MV_STATUS status;
+
+    /* check for NULL pointer */
+	if ((pFlinfo == NULL) || (pReadBuff == NULL)) {
+		mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+		return MV_BAD_PARAM;
+	}
+
+	/* Protection - check if the model was detected */
+	if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+		DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__));
+		return MV_BAD_PARAM;
+	}
+
+	cmd[0] = sflash[pFlinfo->index].opcdREAD;
+	if (flSize <= _16M) {
+		cmd[1] = ((offset >> 16) & 0xFF);
+		cmd[2] = ((offset >> 8) & 0xFF);
+		cmd[3] = (offset & 0xFF);
+	} else {
+		cmd[1] = ((offset >> 24) & 0xFF);
+		cmd[2] = ((offset >> 16) & 0xFF);
+		cmd[3] = ((offset >> 8) & 0xFF);
+		cmd[4] = (offset & 0xFF);
+	}
+
+	/*  mvSpiWriteThenRead(MV_SFLASH_READ_CMND_LENGTH, pReadBuff, buffSize) */
+	status = mvSysSflashCommandSet(NULL, cmd, cmndLength,
+			SYS_SFLASH_TRANS_START);
+	if (status == MV_OK)
+		status = mvSysSflashDataRead(NULL, pReadBuff, buffSize, 0,
+				SYS_SFLASH_TRANS_END);
+	return status;
+}
+
+/*******************************************************************************
+* mvSFlashFastBlockRd - Fast read from the serial flash
+*
+* DESCRIPTION:
+*       Issue the fast read command and address then perfom the needed read
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*		offset: byte offset with the flash to start reading from
+*		pReadBuff: pointer to the buffer to read the data in
+*		buffSize: size of the buffer to read.
+*
+* OUTPUT:
+*       pReadBuff: pointer to the buffer containing the read data
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashFastBlockRd(MV_SFLASH_INFO *pFlinfo, MV_U32 offset,
+						       MV_U8 *pReadBuff, MV_U32 buffSize)
+{
+    MV_U8 cmd[MV_SFLASH_MAX_CMND_LENGTH];
+    MV_STATUS ret, retCmd;
+
+    /* check for NULL pointer */
+    if ((pFlinfo == NULL) || (pReadBuff == NULL)) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+    cmd[0] = sflash[pFlinfo->index].opcdFSTRD;
+    if (flSize <= _16M) {
+	cmd[1] = ((offset >> 16) & 0xFF);
+	cmd[2] = ((offset >> 8) & 0xFF);
+	cmd[3] = (offset & 0xFF);
+    } else {
+	cmd[1] = ((offset >> 24) & 0xFF);
+	cmd[2] = ((offset >> 16) & 0xFF);
+	cmd[3] = ((offset >> 8) & 0xFF);
+	cmd[4] = (offset & 0xFF);
+    }
+
+    /*  mvSpiWriteThenRead(MV_SFLASH_READ_CMND_LENGTH, pReadBuff, buffSize,
+	sflash[pFlinfo->index].spiFastRdDummyBytes); */
+    retCmd = mvSysSflashCommandSet(NULL, cmd, cmndLength,
+		    SYS_SFLASH_TRANS_START);
+
+    /* Set the SPI frequency to the MAX allowed for fast-read operations */
+    mvOsPrintf("Setting freq to %d.\n", sflash[pFlinfo->index].spiMaxFastFreq);
+
+    /*  mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFastFreq) */
+    ret = mvSysSflashFreqSet(NULL, sflash[pFlinfo->index].spiMaxFastFreq);
+    if (ret != MV_OK) {
+	mvOsPrintf("%s ERROR: Failed to set the SPI fast frequency!\n", __func__);
+	return ret;
+    }
+
+    if (retCmd == MV_OK)
+	ret = mvSysSflashDataRead(NULL, pReadBuff, buffSize,
+			    sflash[pFlinfo->index].spiFastRdDummyBytes, SYS_SFLASH_TRANS_END);
+
+	/* Reset the SPI frequency to the MAX allowed for the device for best performance */
+    /*  mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFreq) */
+    ret = mvSysSflashFreqSet(NULL, sflash[pFlinfo->index].spiMaxFreq);
+    if (ret != MV_OK) {
+	mvOsPrintf("%s ERROR: Failed to set the SPI frequency!\n", __func__);
+	return ret;
+    }
+
+    return retCmd;
+}
+
+
+/*******************************************************************************
+* mvSFlashBlockWr - Write a buffer with any size
+*
+* DESCRIPTION:
+*       write regardless of the page boundaries and size limit per Page
+*		program command
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*		offset: byte offset within the flash region
+*		pWriteBuff: pointer to the buffer holding the data to program
+*		buffSize: size of the buffer to write
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashBlockWr(MV_SFLASH_INFO *pFlinfo, MV_U32 offset,
+						   MV_U8 *pWriteBuff, MV_U32 buffSize)
+{
+    MV_STATUS ret;
+	MV_U32 data2write	= buffSize;
+    MV_U32 preAllOffset = (offset & MV_SFLASH_PAGE_ALLIGN_MASK(MV_M25P_PAGE_SIZE));
+    MV_U32 preAllSz		= (preAllOffset ? (MV_M25P_PAGE_SIZE - preAllOffset) : 0);
+	MV_U32 writeOffset	= offset;
+
+    /* check for NULL pointer */
+#ifndef CONFIG_MARVELL
+    if (NULL == pWriteBuff) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+#endif
+
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+	/* check that the buffer size does not exceed the flash size */
+    if ((offset + buffSize) > mvSFlashSizeGet(pFlinfo)) {
+	DB(mvOsPrintf("%s WARNING: Write exceeds flash size!\n", __func__);)
+	return MV_OUT_OF_RANGE;
+    }
+
+	/* check if the total block size is less than the first chunk remainder */
+	if (data2write < preAllSz)
+		preAllSz = data2write;
+
+	/* check if programing does not start at a 64byte alligned offset */
+	if (preAllSz) {
+		ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, preAllSz);
+		if (ret != MV_OK)
+			return ret;
+
+		/* increment pointers and counters */
+		writeOffset += preAllSz;
+		data2write -= preAllSz;
+		pWriteBuff += preAllSz;
+	}
+
+	/* program the data that fits in complete page chunks */
+	while (data2write >= sflash[pFlinfo->index].pageSize) {
+		ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, sflash[pFlinfo->index].pageSize);
+		if (ret != MV_OK)
+			return ret;
+
+		/* increment pointers and counters */
+		writeOffset += sflash[pFlinfo->index].pageSize;
+		data2write -= sflash[pFlinfo->index].pageSize;
+		pWriteBuff += sflash[pFlinfo->index].pageSize;
+	}
+
+	/* program the last partial chunk */
+	if (data2write) {
+		ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, data2write);
+		if (ret != MV_OK)
+			return ret;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashIdGet - Get the manufacturer and device IDs.
+*
+* DESCRIPTION:
+*       Get the Manufacturer and device IDs from the serial flash through
+*		writing the RDID command then reading 3 bytes of data. In case that
+*       this command was called for the first time in order to detect the
+*       manufacturer and device IDs, then the default RDID opcode will be used
+*       unless the device index is indicated by the user (in case the SPI flash
+*       does not use the default RDID opcode).
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*		pManId: pointer to the 8bit variable to hold the manufacturing ID
+*		pDevId: pointer to the 16bit variable to hold the device ID
+*
+* OUTPUT:
+*		pManId: pointer to the 8bit variable holding the manufacturing ID
+*		pDevId: pointer to the 16bit variable holding the device ID
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashIdGet(MV_SFLASH_INFO *pFlinfo, MV_U8 *pManId, MV_U16 *pDevId)
+{
+    MV_STATUS ret;
+	MV_U8 cmd[MV_SFLASH_RDID_CMND_LENGTH];
+	MV_U8 id[MV_SFLASH_RDID_REPLY_LENGTH];
+
+
+
+    /* check for NULL pointer */
+    if ((pFlinfo == NULL) || (pManId == NULL) || (pDevId == NULL)) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash))
+	return mvSFlashWithDefaultsIdGet(pFlinfo, pManId, pDevId);
+    else
+	cmd[0] = sflash[pFlinfo->index].opcdRDID;
+
+	/*  mvSpiWriteThenRead(MV_SFLASH_RDID_CMND_LENGTH, id, MV_SFLASH_RDID_REPLY_LENGTH) */
+	ret = mvSysSflashCommandSet(NULL, cmd, MV_SFLASH_RDID_CMND_LENGTH,
+			SYS_SFLASH_TRANS_START);
+	if (ret == MV_OK)
+		ret = mvSysSflashDataRead(NULL, id, MV_SFLASH_RDID_REPLY_LENGTH, 0, SYS_SFLASH_TRANS_END);
+	if (ret != MV_OK)
+		return ret;
+
+	*pManId = id[0];
+	*pDevId = 0;
+	*pDevId |= (id[1] << 8);
+	*pDevId |= id[2];
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashWpRegionSet - Set the Write-Protected region
+*
+* DESCRIPTION:
+*       Set the Write-Protected region
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*		wpRegion: which region will be protected
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashWpRegionSet(MV_SFLASH_INFO *pFlinfo, MV_SFLASH_WP_REGION wpRegion)
+{
+    MV_U8 wpMask;
+
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+    /* Check if the chip is an ST flash; then WP supports only 3 bits */
+    if (pFlinfo->manufacturerId == MV_M25PXXX_ST_MANF_ID) {
+	switch (wpRegion) {
+	case MV_WP_NONE:
+	    wpMask = MV_M25P_STATUS_BP_NONE;
+	    break;
+
+	case MV_WP_UPR_1OF128:
+	    DB(mvOsPrintf("%s WARNING: Invaild option for this flash chip!\n", __func__);)
+	    return MV_NOT_SUPPORTED;
+
+	case MV_WP_UPR_1OF64:
+	    wpMask = MV_M25P_STATUS_BP_1_OF_64;
+	    break;
+
+	case MV_WP_UPR_1OF32:
+	    wpMask = MV_M25P_STATUS_BP_1_OF_32;
+	    break;
+
+	case MV_WP_UPR_1OF16:
+	    wpMask = MV_M25P_STATUS_BP_1_OF_16;
+	    break;
+
+	case MV_WP_UPR_1OF8:
+	    wpMask = MV_M25P_STATUS_BP_1_OF_8;
+	    break;
+
+	case MV_WP_UPR_1OF4:
+	    wpMask = MV_M25P_STATUS_BP_1_OF_4;
+	    break;
+
+	case MV_WP_UPR_1OF2:
+	    wpMask = MV_M25P_STATUS_BP_1_OF_2;
+	    break;
+
+	case MV_WP_ALL:
+	    wpMask = MV_M25P_STATUS_BP_ALL;
+	    break;
+
+	default:
+	    DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __func__);)
+	    return MV_BAD_PARAM;
+	}
+    } else if (pFlinfo->manufacturerId == MV_MXIC_MANF_ID) {
+	/* check if the manufacturer is MXIC then the WP is 4bits */
+
+	switch (wpRegion) {
+	case MV_WP_NONE:
+	    wpMask = MV_MX25L_STATUS_BP_NONE;
+	    break;
+
+	case MV_WP_UPR_1OF128:
+	    wpMask = MV_MX25L_STATUS_BP_1_OF_128;
+	    break;
+
+	case MV_WP_UPR_1OF64:
+	    wpMask = MV_MX25L_STATUS_BP_1_OF_64;
+	    break;
+
+	case MV_WP_UPR_1OF32:
+	    wpMask = MV_MX25L_STATUS_BP_1_OF_32;
+	    break;
+
+	case MV_WP_UPR_1OF16:
+	    wpMask = MV_MX25L_STATUS_BP_1_OF_16;
+	    break;
+
+	case MV_WP_UPR_1OF8:
+	    wpMask = MV_MX25L_STATUS_BP_1_OF_8;
+	    break;
+
+	case MV_WP_UPR_1OF4:
+	    wpMask = MV_MX25L_STATUS_BP_1_OF_4;
+	    break;
+
+	case MV_WP_UPR_1OF2:
+	    wpMask = MV_MX25L_STATUS_BP_1_OF_2;
+	    break;
+
+	case MV_WP_ALL:
+	    wpMask = MV_MX25L_STATUS_BP_ALL;
+	    break;
+
+	default:
+	    DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __func__);)
+	    return MV_BAD_PARAM;
+	}
+    } else if (pFlinfo->manufacturerId == MV_SPANSION_MANF_ID) {
+	/* check if the manufacturer is SPANSION then the WP is 4bits */
+	switch (wpRegion) {
+	case MV_WP_NONE:
+	    wpMask = MV_S25FL_STATUS_BP_NONE;
+	    break;
+
+	case MV_WP_UPR_1OF128:
+	    DB(mvOsPrintf("%s WARNING: Invaild option for this flash chip!\n", __func__);)
+	    return MV_NOT_SUPPORTED;
+
+	case MV_WP_UPR_1OF64:
+	    wpMask = MV_S25FL_STATUS_BP_1_OF_64;
+	    break;
+
+	case MV_WP_UPR_1OF32:
+	    wpMask = MV_S25FL_STATUS_BP_1_OF_32;
+	    break;
+
+	case MV_WP_UPR_1OF16:
+	    wpMask = MV_S25FL_STATUS_BP_1_OF_16;
+	    break;
+
+	case MV_WP_UPR_1OF8:
+	    wpMask = MV_S25FL_STATUS_BP_1_OF_8;
+	    break;
+
+	case MV_WP_UPR_1OF4:
+	    wpMask = MV_S25FL_STATUS_BP_1_OF_4;
+	    break;
+
+	case MV_WP_UPR_1OF2:
+	    wpMask = MV_S25FL_STATUS_BP_1_OF_2;
+	    break;
+
+	case MV_WP_ALL:
+	    wpMask = MV_S25FL_STATUS_BP_ALL;
+	    break;
+
+
+	default:
+	    DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __func__);)
+	    return MV_BAD_PARAM;
+	}
+    } else {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter Manufacturer ID!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+    /* Verify that the SRWD bit is always set - register is s/w locked */
+    wpMask |= MV_SFLASH_STATUS_REG_SRWD_MASK;
+
+	return mvStatusRegSet(pFlinfo, wpMask);
+}
+
+/*******************************************************************************
+* mvSFlashWpRegionGet - Get the Write-Protected region configured
+*
+* DESCRIPTION:
+*       Get from the chip the Write-Protected region configured
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*		pWpRegion: pointer to the variable to return the WP region in
+*
+* OUTPUT:
+*		wpRegion: pointer to the variable holding the WP region configured
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashWpRegionGet(MV_SFLASH_INFO *pFlinfo, MV_SFLASH_WP_REGION *pWpRegion)
+{
+	MV_STATUS ret;
+	MV_U8 reg;
+
+    /* check for NULL pointer */
+    if ((pFlinfo == NULL) || (pWpRegion == NULL)) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+    ret = mvStatusRegGet(pFlinfo, &reg);
+    if (ret != MV_OK)
+	return ret;
+
+    /* Check if the chip is an ST flash; then WP supports only 3 bits */
+    if (pFlinfo->manufacturerId == MV_M25PXXX_ST_MANF_ID) {
+	switch ((reg & MV_M25P_STATUS_REG_WP_MASK)) {
+	case MV_M25P_STATUS_BP_NONE:
+	    *pWpRegion = MV_WP_NONE;
+	    break;
+
+	case MV_M25P_STATUS_BP_1_OF_64:
+	    *pWpRegion = MV_WP_UPR_1OF64;
+	    break;
+
+	case MV_M25P_STATUS_BP_1_OF_32:
+	    *pWpRegion = MV_WP_UPR_1OF32;
+	    break;
+
+	case MV_M25P_STATUS_BP_1_OF_16:
+	    *pWpRegion = MV_WP_UPR_1OF16;
+	    break;
+
+	case MV_M25P_STATUS_BP_1_OF_8:
+	    *pWpRegion = MV_WP_UPR_1OF8;
+	    break;
+
+	case MV_M25P_STATUS_BP_1_OF_4:
+	    *pWpRegion = MV_WP_UPR_1OF4;
+	    break;
+
+	case MV_M25P_STATUS_BP_1_OF_2:
+	    *pWpRegion = MV_WP_UPR_1OF2;
+	    break;
+
+	case MV_M25P_STATUS_BP_ALL:
+	    *pWpRegion = MV_WP_ALL;
+	    break;
+
+	default:
+	    DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __func__);)
+	    return MV_BAD_VALUE;
+	}
+    } else if (pFlinfo->manufacturerId == MV_MXIC_MANF_ID) {
+	/* check if the manufacturer is MXIC then the WP is 4bits */
+	switch ((reg & MV_MX25L_STATUS_REG_WP_MASK))  {
+	case MV_MX25L_STATUS_BP_NONE:
+	    *pWpRegion = MV_WP_NONE;
+	    break;
+
+	case MV_MX25L_STATUS_BP_1_OF_128:
+	    *pWpRegion = MV_WP_UPR_1OF128;
+	    break;
+
+	case MV_MX25L_STATUS_BP_1_OF_64:
+	    *pWpRegion = MV_WP_UPR_1OF64;
+	    break;
+
+	case MV_MX25L_STATUS_BP_1_OF_32:
+	    *pWpRegion = MV_WP_UPR_1OF32;
+	    break;
+
+	case MV_MX25L_STATUS_BP_1_OF_16:
+	    *pWpRegion = MV_WP_UPR_1OF16;
+	    break;
+
+	case MV_MX25L_STATUS_BP_1_OF_8:
+	    *pWpRegion = MV_WP_UPR_1OF8;
+	    break;
+
+	case MV_MX25L_STATUS_BP_1_OF_4:
+	    *pWpRegion = MV_WP_UPR_1OF4;
+	    break;
+
+	case MV_MX25L_STATUS_BP_1_OF_2:
+	    *pWpRegion = MV_WP_UPR_1OF2;
+	    break;
+
+	case MV_MX25L_STATUS_BP_ALL:
+	    *pWpRegion = MV_WP_ALL;
+	    break;
+
+	default:
+	    DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __func__);)
+	    return MV_BAD_VALUE;
+	}
+    } else if (pFlinfo->manufacturerId == MV_SPANSION_MANF_ID) {
+	/* Check if the chip is an SPANSION flash; then WP supports only 3 bits */
+	switch ((reg & MV_S25FL_STATUS_REG_WP_MASK)) {
+	case MV_S25FL_STATUS_BP_NONE:
+	    *pWpRegion = MV_WP_NONE;
+	    break;
+
+	case MV_S25FL_STATUS_BP_1_OF_64:
+	    *pWpRegion = MV_WP_UPR_1OF64;
+	    break;
+
+	case MV_S25FL_STATUS_BP_1_OF_32:
+	    *pWpRegion = MV_WP_UPR_1OF32;
+	    break;
+
+	case MV_S25FL_STATUS_BP_1_OF_16:
+	    *pWpRegion = MV_WP_UPR_1OF16;
+	    break;
+
+	case MV_S25FL_STATUS_BP_1_OF_8:
+	    *pWpRegion = MV_WP_UPR_1OF8;
+	    break;
+
+	case MV_S25FL_STATUS_BP_1_OF_4:
+	    *pWpRegion = MV_WP_UPR_1OF4;
+	    break;
+
+	case MV_S25FL_STATUS_BP_1_OF_2:
+	    *pWpRegion = MV_WP_UPR_1OF2;
+	    break;
+
+	case MV_S25FL_STATUS_BP_ALL:
+	    *pWpRegion = MV_WP_ALL;
+	    break;
+
+	default:
+	    DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __func__);)
+	    return MV_BAD_VALUE;
+	}
+    } else {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter Manufacturer ID!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashStatRegLock - Lock the status register for writing - W/Vpp
+*		pin should be low to take effect
+*
+* DESCRIPTION:
+*       Lock the access to the Status Register for writing. This will
+*		cause the flash to enter the hardware protection mode if the W/Vpp
+*		is low. If the W/Vpp is hi, the chip will be in soft protection mode, but
+*		the register will continue to be writable if WREN sequence was used.
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*		srLock: enable/disable (MV_TRUE/MV_FALSE) status registor lock mechanism
+*
+* OUTPUT:
+*       None
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashStatRegLock(MV_SFLASH_INFO *pFlinfo, MV_BOOL srLock)
+{
+    MV_STATUS ret;
+	MV_U8 reg;
+
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+    ret = mvStatusRegGet(pFlinfo, &reg);
+    if (ret != MV_OK)
+	return ret;
+
+	if (srLock)
+		reg |= MV_SFLASH_STATUS_REG_SRWD_MASK;
+	else
+		reg &= ~MV_SFLASH_STATUS_REG_SRWD_MASK;
+
+	return mvStatusRegSet(pFlinfo, reg);
+}
+
+/*******************************************************************************
+* mvSFlashSizeGet - Get the size of the SPI flash
+*
+* DESCRIPTION:
+*       based on the sector number and size of each sector calculate the total
+*       size of the flash memory.
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Size of the flash in bytes.
+*
+*
+*******************************************************************************/
+MV_U32 mvSFlashSizeGet(MV_SFLASH_INFO *pFlinfo)
+{
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return 0;
+    }
+
+    return (pFlinfo->sectorSize * pFlinfo->sectorNumber);
+}
+
+/*******************************************************************************
+* mvSFlashPowerSaveEnter - Cause the falsh device to go into power save mode
+*
+* DESCRIPTION:
+*       Enter a special power save mode.
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Size of the flash in bytes.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashPowerSaveEnter(MV_SFLASH_INFO *pFlinfo)
+{
+    MV_STATUS ret;
+	MV_U8 cmd[MV_SFLASH_DP_CMND_LENGTH];
+
+
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return 0;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+    /* check that power save mode is supported in the specific device */
+    if (sflash[pFlinfo->index].opcdPwrSave == MV_SFLASH_NO_SPECIFIC_OPCD) {
+	DB(mvOsPrintf("%s WARNING: Power save not supported for this device!\n", __func__);)
+	return MV_NOT_SUPPORTED;
+    }
+
+    cmd[0] = sflash[pFlinfo->index].opcdPwrSave;
+
+	/*  mvSpiWriteThenWrite(MV_SFLASH_DP_CMND_LENGTH) */
+	ret = mvSysSflashCommandSet(NULL, cmd, MV_SFLASH_DP_CMND_LENGTH, SYS_SFLASH_TRANS_ATOMIC);
+	return ret;
+}
+
+/*******************************************************************************
+* mvSFlashPowerSaveExit - Cause the falsh device to exit the power save mode
+*
+* DESCRIPTION:
+*       Exit the deep power save mode.
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Size of the flash in bytes.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSFlashPowerSaveExit(MV_SFLASH_INFO *pFlinfo)
+{
+	MV_STATUS ret;
+	MV_U8 cmd[MV_SFLASH_RES_CMND_LENGTH];
+
+
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return 0;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return MV_BAD_PARAM;
+    }
+
+    /* check that power save mode is supported in the specific device */
+    if (sflash[pFlinfo->index].opcdRES == MV_SFLASH_NO_SPECIFIC_OPCD) {
+	DB(mvOsPrintf("%s WARNING: Read Electronic Signature not supported for this device!\n", __func__);)
+	return MV_NOT_SUPPORTED;
+    }
+
+    cmd[0] = sflash[pFlinfo->index].opcdRES;
+
+
+	/*  mvSpiWriteThenWrite(MV_SFLASH_RES_CMND_LENGTH) */
+	ret = mvSysSflashCommandSet(NULL, cmd, MV_SFLASH_RES_CMND_LENGTH, SYS_SFLASH_TRANS_ATOMIC);
+	if (ret != MV_OK)
+		return ret;
+
+    /* add the delay needed for the device to wake up */
+    mvOsDelay(MV_MXIC_DP_EXIT_DELAY);   /* 30 ms */
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvSFlashModelGet - Retreive the string with the device manufacturer and model
+*
+* DESCRIPTION:
+*       Retreive the string with the device manufacturer and model
+*
+* INPUT:
+*       pFlinfo: pointer to the Flash information structure
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       pointer to the string indicating the device manufacturer and model
+*
+*
+*******************************************************************************/
+const MV_8 *mvSFlashModelGet(MV_SFLASH_INFO *pFlinfo)
+{
+    static const MV_8 * unknModel = (const MV_8 *)"Unknown";
+
+    /* check for NULL pointer */
+    if (pFlinfo == NULL) {
+	 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return 0;
+    }
+
+    /* Protection - check if the model was detected */
+    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) {
+	DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __func__);)
+	return unknModel;
+    }
+
+    return sflash[pFlinfo->index].deviceModel;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlash.h b/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlash.h
new file mode 100755
index 0000000..f269e3d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlash.h
@@ -0,0 +1,172 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSFlashH
+#define __INCmvSFlashH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+/* MCAROS */
+#define MV_SFLASH_PAGE_ALLIGN_MASK(pgSz)    (pgSz-1)
+
+/* Constants */
+#define MV_INVALID_DEVICE_NUMBER            0xFFFFFFFF
+/* 10 MHz is the minimum possible SPI frequency when tclk is set 200MHz*/
+#define MV_SFLASH_BASIC_SPI_FREQ            10000000
+/* enumerations */
+typedef enum {
+	MV_WP_NONE,             /* Unprotect the whole chip */
+	MV_WP_UPR_1OF128,       /* Write protect the upper 1/128 part */
+	MV_WP_UPR_1OF64,        /* Write protect the upper 1/64 part */
+	MV_WP_UPR_1OF32,        /* Write protect the upper 1/32 part */
+	MV_WP_UPR_1OF16,        /* Write protect the upper 1/16 part */
+	MV_WP_UPR_1OF8,         /* Write protect the upper 1/8 part */
+	MV_WP_UPR_1OF4,         /* Write protect the upper 1/4 part */
+	MV_WP_UPR_1OF2,         /* Write protect the upper 1/2 part */
+	MV_WP_ALL               /* Write protect the whole chip */
+} MV_SFLASH_WP_REGION;
+
+/* Type Definitions */
+typedef struct {
+    MV_U8   opcdWREN;       /* Write enable opcode */
+    MV_U8   opcdWRDI;       /* Write disable opcode */
+    MV_U8   opcdRDID;       /* Read ID opcode */
+    MV_U8   opcdRDSR;       /* Read Status Register opcode */
+    MV_U8   opcdWRSR;       /* Write Status register opcode */
+    MV_U8   opcdREAD;       /* Read opcode */
+    MV_U8   opcdFSTRD;      /* Fast Read opcode */
+    MV_U8   opcdPP;         /* Page program opcode */
+    MV_U8   opcdSE;         /* Sector erase opcode */
+    MV_U8   opcdBE;         /* Bulk erase opcode */
+    MV_U8   opcdRES;        /* Read electronic signature */
+    MV_U8   opcdPwrSave;    /* Go into power save mode */
+    MV_U8   opcdEn4B;	    /* Enable 4-Byte mode */
+    MV_U32  sectorSize;     /* Size of each sector */
+    MV_U32  sectorNumber;   /* Number of sectors */
+    MV_U32  pageSize;       /* size of each page */
+    const char *deviceModel;    /* string with the device model */
+    MV_U32  manufacturerId; /* The manufacturer ID */
+    MV_U32  deviceId;       /* Device ID */
+    MV_U32  spiMaxFreq;     /* The MAX frequency that can be used with the device */
+    MV_U32  spiMaxFastFreq; /* The MAX frequency that can be used with the device for fast reads */
+    MV_U32  spiFastRdDummyBytes; /* Number of dumy bytes to read before real data when working in fast read mode. */
+} MV_SFLASH_DEVICE_PARAMS;
+
+typedef struct {
+	MV_U32					baseAddr;       /* Flash Base Address used in fast mode */
+	MV_U8	                manufacturerId;	/* Manufacturer ID */
+	MV_U16	                deviceId;	    /* Device ID */
+	MV_U32                  sectorSize;     /* Size of each sector - all the same */
+	MV_U32                  sectorNumber;   /* Number of sectors */
+	MV_U32                  pageSize;       /* Page size - affect allignment */
+	MV_U32                  index;          /* index of the device in the sflash table (internal parameter) */
+} MV_SFLASH_INFO;
+
+/* Function Prototypes */
+/* Init */
+MV_STATUS	mvSFlashInit(MV_SFLASH_INFO *pFlinfo);
+
+/* erase */
+MV_STATUS 	mvSFlashSectorErase(MV_SFLASH_INFO *pFlinfo, MV_U32 secNumber);
+MV_STATUS 	mvSFlashChipErase(MV_SFLASH_INFO *pFlinfo);
+
+/* Read */
+MV_STATUS	mvSFlashBlockRd(MV_SFLASH_INFO *pFlinfo, MV_U32 offset,
+						MV_U8 *pReadBuff, MV_U32 buffSize);
+MV_STATUS mvSFlashFastBlockRd(MV_SFLASH_INFO *pFlinfo, MV_U32 offset,
+							     MV_U8 *pReadBuff, MV_U32 buffSize);
+
+/* write regardless of the page boundaries and size limit per Page program command */
+MV_STATUS	mvSFlashBlockWr(MV_SFLASH_INFO *pFlinfo, MV_U32 offset,
+							     MV_U8 *pWriteBuff, MV_U32 buffSize);
+/* Get IDs */
+MV_STATUS 	mvSFlashIdGet(MV_SFLASH_INFO *pFlinfo, MV_U8 *pManId, MV_U16 *pDevId);
+
+/* Set and Get the Write Protection region - if the Status register is not locked */
+MV_STATUS   mvSFlashWpRegionSet(MV_SFLASH_INFO *pFlinfo, MV_SFLASH_WP_REGION wpRegion);
+MV_STATUS   mvSFlashWpRegionGet(MV_SFLASH_INFO *pFlinfo, MV_SFLASH_WP_REGION *pWpRegion);
+
+/* Lock the status register for writing - W/Vpp pin should be low to take effect */
+MV_STATUS   mvSFlashStatRegLock(MV_SFLASH_INFO *pFlinfo, MV_BOOL srLock);
+
+/* Get the regions sizes */
+MV_U32      mvSFlashSizeGet(MV_SFLASH_INFO *pFlinfo);
+
+/* Cause the falsh device to go into power save mode */
+MV_STATUS   mvSFlashPowerSaveEnter(MV_SFLASH_INFO *pFlinfo);
+MV_STATUS   mvSFlashPowerSaveExit(MV_SFLASH_INFO *pFlinfo);
+
+/* Retreive the string with the device manufacturer and model */
+const MV_8 *mvSFlashModelGet(MV_SFLASH_INFO *pFlinfo);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __INCmvSFlashH */
diff --git a/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlashSpec.h b/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlashSpec.h
new file mode 100755
index 0000000..6fb2428
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sflash/mvSFlashSpec.h
@@ -0,0 +1,276 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSFlashSpecH
+#define __INCmvSFlashSpecH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Constants */
+#define		MV_SFLASH_READ_CMND_LENGTH		    4		/* 1B opcode + 3B address */
+#define		MV_SFLASH_SE_CMND_LENGTH		    4		/* 1B opcode + 3B address */
+#define		MV_SFLASH_BE_CMND_LENGTH		    1		/* 1B opcode */
+#define		MV_SFLASH_PP_CMND_LENGTH		    4		/* 1B opcode + 3B address */
+#define		MV_SFLASH_WREN_CMND_LENGTH		    1		/* 1B opcode */
+#define		MV_SFLASH_WRDI_CMND_LENGTH		    1		/* 1B opcode */
+#define		MV_SFLASH_RDID_CMND_LENGTH		    1		/* 1B opcode */
+#define		MV_SFLASH_RDID_REPLY_LENGTH		    3		/* 1B manf ID and 2B device ID */
+#define		MV_SFLASH_RDSR_CMND_LENGTH		    1		/* 1B opcode */
+#define		MV_SFLASH_RDSR_REPLY_LENGTH		    1		/* 1B status */
+#define		MV_SFLASH_WRSR_CMND_LENGTH		    2		/* 1B opcode + 1B status value */
+#define		MV_SFLASH_DP_CMND_LENGTH		    1		/* 1B opcode */
+#define		MV_SFLASH_RES_CMND_LENGTH		    1		/* 1B opcode */
+#define		MV_SFLASH_MAX_CMND_LENGTH		    5		/* 1B opcode + 3B/4B address */
+
+/* Status Register Bit Masks */
+#define		MV_SFLASH_STATUS_REG_WIP_OFFSET	    0	    /* bit 0; write in progress */
+#define		MV_SFLASH_STATUS_REG_WP_OFFSET	    2       /* bit 2-4; write protect option */
+#define		MV_SFLASH_STATUS_REG_SRWD_OFFSET	7	    /* bit 7; lock status register write */
+#define		MV_SFLASH_STATUS_REG_WIP_MASK	    (0x1 << MV_SFLASH_STATUS_REG_WIP_OFFSET)
+#define		MV_SFLASH_STATUS_REG_SRWD_MASK	    (0x1 << MV_SFLASH_STATUS_REG_SRWD_OFFSET)
+
+#define		MV_SFLASH_MAX_WAIT_LOOP			    1000000
+#define     MV_SFLASH_CHIP_ERASE_MAX_WAIT_LOOP  0x50000000
+
+#define		MV_SFLASH_DEFAULT_RDID_OPCD		    0x9F	/* Default Read ID */
+#define     MV_SFLASH_DEFAULT_WREN_OPCD         0x06	/* Default Write Enable */
+#define     MV_SFLASH_NO_SPECIFIC_OPCD          0x00
+
+/********************************/
+/*  ST M25Pxxx Device Specific  */
+/********************************/
+
+/* Manufacturer IDs and Device IDs for SFLASHs supported by the driver */
+#define     MV_M25PXXX_ST_MANF_ID               0x20
+#define     MV_M25P32_DEVICE_ID                 0x2016
+#define     MV_M25P32_MAX_SPI_FREQ              20000000    /* 20MHz */
+#define     MV_M25P32_MAX_FAST_SPI_FREQ         50000000    /* 50MHz */
+#define     MV_M25P32_FAST_READ_DUMMY_BYTES     1
+#define     MV_M25P64_DEVICE_ID                 0x2017
+#define     MV_M25P64_MAX_SPI_FREQ              20000000    /* 20MHz */
+#define     MV_M25P64_MAX_FAST_SPI_FREQ         50000000    /* 50MHz */
+#define     MV_M25P64_FAST_READ_DUMMY_BYTES     1
+#define     MV_M25P128_DEVICE_ID                0x2018
+#define     MV_M25P128_MAX_SPI_FREQ             20000000    /* 20MHz */
+#define     MV_M25P128_MAX_FAST_SPI_FREQ        50000000    /* 50MHz */
+#define     MV_M25P128_FAST_READ_DUMMY_BYTES    1
+
+/********************************/
+/*  ST M25Qxxx Device Specific  */
+/********************************/
+
+/* Manufacturer IDs and Device IDs for SFLASHs supported by the driver */
+#define     MV_M25Q128_DEVICE_ID                0xBA18
+#define     MV_M25Q128_MAX_SPI_FREQ             20000000    /* 20MHz */
+#define     MV_M25Q128_MAX_FAST_SPI_FREQ        50000000    /* 50MHz */
+#define     MV_M25Q128_FAST_READ_DUMMY_BYTES    1
+
+
+/* Sector Sizes and population per device model*/
+#define     MV_M25P32_SECTOR_SIZE               0x10000 /* 64K */
+#define     MV_M25P64_SECTOR_SIZE               0x10000 /* 64K */
+#define     MV_M25P128_SECTOR_SIZE              0x40000 /* 256K */
+#define     MV_M25Q128_SECTOR_SIZE              0x10000 /* 64K */
+#define     MV_M25P32_SECTOR_NUMBER             64
+#define     MV_M25P64_SECTOR_NUMBER             128
+#define     MV_M25P128_SECTOR_NUMBER            64
+#define     MV_M25Q128_SECTOR_NUMBER            256
+#define	    MV_M25P_PAGE_SIZE			0x100   /* 256 byte */
+#define	    MV_M25Q_PAGE_SIZE			0x100   /* 256 byte */
+
+#define		MV_M25P_WREN_CMND_OPCD			    0x06	/* Write Enable */
+#define		MV_M25P_WRDI_CMND_OPCD			    0x04	/* Write Disable */
+#define		MV_M25P_RDID_CMND_OPCD			    0x9F	/* Read ID */
+#define		MV_M25P_RDSR_CMND_OPCD			    0x05	/* Read Status Register */
+#define		MV_M25P_WRSR_CMND_OPCD			    0x01	/* Write Status Register */
+#define		MV_M25P_READ_CMND_OPCD			    0x03	/* Sequential Read */
+#define		MV_M25P_FAST_RD_CMND_OPCD		    0x0B	/* Fast Read */
+#define		MV_M25P_PP_CMND_OPCD			    0x02	/* Page Program */
+#define		MV_M25P_SE_CMND_OPCD			    0xD8	/* Sector Erase */
+#define		MV_M25P_BE_CMND_OPCD			    0xC7	/* Bulk Erase */
+#define		MV_M25P_RES_CMND_OPCD			    0xAB	/* Read Electronic Signature */
+
+/* Status Register Write Protect Bit Masks - 3bits */
+#define		MV_M25P_STATUS_REG_WP_MASK	        (0x07 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_M25P_STATUS_BP_NONE              (0x00 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_M25P_STATUS_BP_1_OF_64           (0x01 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_M25P_STATUS_BP_1_OF_32           (0x02 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_M25P_STATUS_BP_1_OF_16           (0x03 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_M25P_STATUS_BP_1_OF_8            (0x04 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_M25P_STATUS_BP_1_OF_4            (0x05 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_M25P_STATUS_BP_1_OF_2            (0x06 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_M25P_STATUS_BP_ALL               (0x07 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+
+/************************************/
+/*  MXIC MX25L6405 Device Specific  */
+/************************************/
+
+/* Manufacturer IDs and Device IDs for SFLASHs supported by the driver */
+#define     MV_MXIC_MANF_ID                     0xC2
+#define     MV_MX25L1605_DEVICE_ID              0x2015
+#define     MV_MX25L1605_MAX_SPI_FREQ           20000000    /* 20MHz */
+#define     MV_MX25L1605_MAX_FAST_SPI_FREQ      50000000    /* 50MHz */
+#define     MV_MX25L1605_FAST_READ_DUMMY_BYTES  1
+#define     MV_MX25L3205_DEVICE_ID              0x2016
+#define     MV_MX25L3205_MAX_SPI_FREQ           20000000    /* 20MHz */
+#define     MV_MX25L3205_MAX_FAST_SPI_FREQ      50000000    /* 50MHz */
+#define     MV_MX25L3205_FAST_READ_DUMMY_BYTES  1
+#define     MV_MX25L6405_DEVICE_ID              0x2017
+#define     MV_MX25L6405_MAX_SPI_FREQ           20000000    /* 20MHz */
+#define     MV_MX25L6405_MAX_FAST_SPI_FREQ      50000000    /* 50MHz */
+#define     MV_MX25L6405_FAST_READ_DUMMY_BYTES   1
+#define     MV_MX25L25635E_DEVICE_ID             0x2019
+#define     MV_MX25L25635E_MAX_SPI_FREQ          20000000    /* 20MHz */
+#define     MV_MX25L25635E_MAX_FAST_SPI_FREQ     50000000    /* 50MHz */
+#define     MV_MX25L25635E_FAST_READ_DUMMY_BYTES 1
+#define     MV_MXIC_DP_EXIT_DELAY               30          /* 30 ms */
+
+/* Sector Sizes and population per device model*/
+#define     MV_MX25L1605_SECTOR_SIZE            0x10000 /* 64K */
+#define     MV_MX25L3205_SECTOR_SIZE            0x10000 /* 64K */
+#define     MV_MX25L6405_SECTOR_SIZE            0x10000 /* 64K */
+#define     MV_MX25L25635E_SECTOR_SIZE          0x10000 /* 64K */
+#define     MV_MX25L1605_SECTOR_NUMBER          32
+#define     MV_MX25L3205_SECTOR_NUMBER          64
+#define     MV_MX25L6405_SECTOR_NUMBER          128
+#define     MV_MX25L25635E_SECTOR_NUMBER        512
+
+#define		MV_MXIC_PAGE_SIZE			        0x100   /* 256 byte */
+
+#define		MV_MX25L_WREN_CMND_OPCD			    0x06	/* Write Enable */
+#define		MV_MX25L_WRDI_CMND_OPCD			    0x04	/* Write Disable */
+#define		MV_MX25L_RDID_CMND_OPCD			    0x9F	/* Read ID */
+#define		MV_MX25L_RDSR_CMND_OPCD			    0x05	/* Read Status Register */
+#define		MV_MX25L_WRSR_CMND_OPCD			    0x01	/* Write Status Register */
+#define		MV_MX25L_READ_CMND_OPCD			    0x03	/* Sequential Read */
+#define		MV_MX25L_FAST_RD_CMND_OPCD		    0x0B	/* Fast Read */
+#define		MV_MX25L_PP_CMND_OPCD			    0x02	/* Page Program */
+#define		MV_MX25L_SE_CMND_OPCD			    0xD8	/* Sector Erase */
+#define		MV_MX25L_BE_CMND_OPCD			    0xC7	/* Bulk Erase */
+#define     MV_MX25L_DP_CMND_OPCD               0xB9    /* Deep Power Down */
+#define		MV_MX25L_RES_CMND_OPCD			    0xAB	/* Read Electronic Signature */
+#define		MV_MX25L_EN4B_CMND_OPCD			    0xB7	/* Enable 4-byte mode */
+
+/* Status Register Write Protect Bit Masks - 4bits */
+#define		MV_MX25L_STATUS_REG_WP_MASK	        (0x0F << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_NONE             (0x00 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_1_OF_128         (0x01 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_1_OF_64          (0x02 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_1_OF_32          (0x03 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_1_OF_16          (0x04 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_1_OF_8           (0x05 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_1_OF_4           (0x06 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_1_OF_2           (0x07 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     MV_MX25L_STATUS_BP_ALL              (0x0F << MV_SFLASH_STATUS_REG_WP_OFFSET)
+
+/************************************/
+/*  SPANSION S25FL128P Device Specific  */
+/************************************/
+
+/* Manufacturer IDs and Device IDs for SFLASHs supported by the driver */
+#define     MV_SPANSION_MANF_ID                     	0x01
+#define     MV_S25FL128_DEVICE_ID              		0x2018
+#define     MV_S25FL128_MAX_SPI_FREQ           		33000000    /* 33MHz */
+#define     MV_S25FL128_MAX_FAST_SPI_FREQ        	104000000    /* 104MHz */
+#define     MV_S25FL128_FAST_READ_DUMMY_BYTES    	1
+
+/* Sector Sizes and population per device model*/
+#define     MV_S25FL128_SECTOR_SIZE            			0x40000 /* 256K */
+#define     MV_S25FL128_SECTOR_NUMBER          			64
+#define	    MV_S25FL_PAGE_SIZE			        	0x100   /* 256 byte */
+
+#define		MV_S25FL_WREN_CMND_OPCD			    0x06	/* Write Enable */
+#define		MV_S25FL_WRDI_CMND_OPCD			    0x04	/* Write Disable */
+#define		MV_S25FL_RDID_CMND_OPCD			    0x9F	/* Read ID */
+#define		MV_S25FL_RDSR_CMND_OPCD			    0x05	/* Read Status Register */
+#define		MV_S25FL_WRSR_CMND_OPCD			    0x01	/* Write Status Register */
+#define		MV_S25FL_READ_CMND_OPCD			    0x03	/* Sequential Read */
+#define		MV_S25FL_FAST_RD_CMND_OPCD		    0x0B	/* Fast Read */
+#define		MV_S25FL_PP_CMND_OPCD			    0x02	/* Page Program */
+#define		MV_S25FL_SE_CMND_OPCD			    0xD8	/* Sector Erase */
+#define		MV_S25FL_BE_CMND_OPCD			    0xC7	/* Bulk Erase */
+#define     	MV_S25FL_DP_CMND_OPCD               	    0xB9    	/* Deep Power Down */
+#define		MV_S25FL_RES_CMND_OPCD			    0xAB	/* Read Electronic Signature */
+
+/* Status Register Write Protect Bit Masks - 4bits */
+#define		MV_S25FL_STATUS_REG_WP_MASK	        (0x0F << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_NONE             	(0x00 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_1_OF_128         	(0x01 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_1_OF_64          	(0x02 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_1_OF_32          	(0x03 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_1_OF_16          	(0x04 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_1_OF_8           	(0x05 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_1_OF_4           	(0x06 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_1_OF_2           	(0x07 << MV_SFLASH_STATUS_REG_WP_OFFSET)
+#define     	MV_S25FL_STATUS_BP_ALL              	(0x0F << MV_SFLASH_STATUS_REG_WP_OFFSET)
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __INCmvSFlashSpecH */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/sflash/mvSysSFlash.h b/arch/arm/plat-feroceon/mv_hal/sflash/mvSysSFlash.h
new file mode 100755
index 0000000..fe5d99f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/sflash/mvSysSFlash.h
@@ -0,0 +1,194 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSysSFlashH
+#define __INCmvSysSFlashH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/*
+** The below macros define the type of the transaction performed by the SFlash
+** HAL.
+** SYS_SFLASH_TRANS_START: This identifies a start of a new transaction (CS
+** assertion).
+** SYS_SFLASH_TRANS_END: This identifies the end of a previously started
+** transaction (CS de-assertion).
+** These options can be OR'ed together to identify atomic operations (like
+** flash erase).
+*/
+#define SYS_SFLASH_TRANS_START		0x1
+#define SYS_SFLASH_TRANS_END		0x2
+#define SYS_SFLASH_TRANS_ATOMIC		0x3
+
+
+/*******************************************************************************
+* mvSysSflashCommandSet
+*
+* DESCRIPTION:
+*	System interface for sending a command to the SPI flash.
+*
+* INPUT:
+*       flashHandle: Handle passed by OS glue by which an SPI flash is
+*		     identified.
+*      	cmdBuff:     Command data to be written.
+*	cmdLen:	     Command length in bytes.
+*	transType:   Bitmask describing the transaction type, see
+*		     SYS_SFLASH_TRANS_XX for details.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSflashCommandSet(MV_VOID *flashHandle, MV_U8 *cmdBuff, MV_U32 cmdLen,
+		MV_U8 transType);
+
+
+/*******************************************************************************
+* mvSysSflashDataRead
+*
+* DESCRIPTION:
+*	System interface for reading SPI flash data.
+*
+* INPUT:
+*       flashHandle: Handle passed by OS glue by which an SPI flash is
+*		     identified.
+*	dataBuff:    Buffer to read the data into.
+*	dataLen:     Number of bytes to read.
+*	dummyBytes:  Number of dummy bytes to read before reading the real
+*		     data.
+*	transType:   Bitmask describing the transaction type, see
+*		     SYS_SFLASH_TRANS_XX for details.
+*
+* OUTPUT:
+*	dataBuff: The data as read from flash.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSflashDataRead(MV_VOID *flashHandle, MV_U8 *dataBuff, MV_U32 dataLen,
+		MV_U32 dummyBytes, MV_U8 transType);
+
+
+/*******************************************************************************
+* mvSysSflashDataWrite
+*
+* DESCRIPTION:
+*	System interface for writing SPI flash data.
+*
+* INPUT:
+*       flashHandle: Handle passed by OS glue by which an SPI flash is
+*		     identified.
+*	dataBuff:    Buffer holding the data to be written.
+*	dataLen:     Number of bytes to write.
+*	transType:   Bitmask describing the transaction type, see
+*		     SYS_SFLASH_TRANS_XX for details.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSflashDataWrite(MV_VOID *flashHandle, MV_U8 *dataBuff, MV_U32 dataLen,
+		MV_U8 transType);
+
+
+/*******************************************************************************
+* mvSysSflashFreqSet
+*
+* DESCRIPTION:
+*	System interface for controlling the SPI interface frequency.
+*
+* INPUT:
+*       flashHandle: Handle passed by OS glue by which an SPI flash is
+*		     identified.
+*	freq:	     The new frequency to be configured for the SPI IF.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSflashFreqSet(MV_VOID *flashHandle, MV_U32 freq);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/spi/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/spi/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/spi/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/spi/mvSpi.c b/arch/arm/plat-feroceon/mv_hal/spi/mvSpi.c
new file mode 100755
index 0000000..ccbbc91
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/spi/mvSpi.c
@@ -0,0 +1,822 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "mvSpiSpec.h"
+#include "mvSpi.h"
+#include "mvSysSpi.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+/* #define MV_DEBUG */
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+static MV_SPI_HAL_DATA	spiHalData;
+
+static MV_SPI_TYPE_INFO spiTypes[] = {
+	{
+		.en16Bit = MV_TRUE,
+		.byteCsAsrt = MV_FALSE,
+		.baudRate = (20 << 20), /*  20M */
+	},
+	{
+		.en16Bit = MV_FALSE,
+		.byteCsAsrt = MV_TRUE,
+		.baudRate = _8M,
+	}
+};
+
+MV_SPI_TYPE_INFO *currSpiInfo = NULL;
+
+/*******************************************************************************
+* mvSpiParamsSet
+*
+* DESCRIPTION:
+*	Set SPI driver parameters.
+*	This will affect the behaviour of the SPI APIs after this call.
+*
+* INPUT:
+*	spiId - Controller ID
+*	csId - chip select ID
+*	type - The type to set.
+*
+* OUTPUT:
+*	None.
+*
+* RETURNS:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+********************************************************************************/
+MV_STATUS mvSpiParamsSet(MV_U8 spiId, MV_U8 csId, MV_SPI_TYPE type)
+{
+	if (csId > (MV_SPI_MAX_CS - 1)) {
+		mvOsPrintf("Error, csId(%d) exceeded maximum(%d)\n", csId, (MV_SPI_MAX_CS - 1));
+		return MV_ERROR;
+	}
+
+#if (MV_SPI_VERSION > 1)
+	if (MV_OK != mvSpiCsSet(spiId, csId)) {
+		mvOsPrintf("Error, setting SPI CS failed\n");
+		return MV_ERROR;
+	}
+#endif
+
+	if (currSpiInfo != (&(spiTypes[type]))) {
+		currSpiInfo = &(spiTypes[type]);
+		mvSpiBaudRateSet(0, currSpiInfo->baudRate);
+	}
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvSpi16bitDataTxRx - Transmt and receive data
+*
+* DESCRIPTION:
+*       Tx data and block waiting for data to be transmitted
+*
+********************************************************************************/
+MV_STATUS mvSpi16bitDataTxRx(MV_U8 spiId, MV_U16 txData, MV_U16 *pRxData)
+{
+    MV_U32 i;
+    MV_BOOL ready = MV_FALSE;
+
+
+    /* First clear the bit in the interrupt cause register */
+    MV_REG_WRITE(MV_SPI_INT_CAUSE_REG(spiId), 0x0);
+
+    /* Transmit data */
+    MV_REG_WRITE(MV_SPI_DATA_OUT_REG(spiId), MV_16BIT_LE(txData));
+
+    /* wait with timeout for memory ready */
+    for (i = 0; i < MV_SPI_WAIT_RDY_MAX_LOOP; i++) {
+	if (MV_REG_READ(MV_SPI_INT_CAUSE_REG(spiId))) {
+		ready = MV_TRUE;
+		break;
+	}
+#ifdef MV_SPI_SLEEP_ON_WAIT
+	mvOsSleep(1);
+#endif /* MV_SPI_SLEEP_ON_WAIT */
+    }
+
+    if (!ready)
+	return MV_TIMEOUT;
+
+    /* check that the RX data is needed */
+    if (pRxData) {
+	if ((MV_U32)pRxData &  0x1) { /* check if address is not alligned to 16bit */
+#if defined(MV_CPU_LE)
+		/* perform the data write to the buffer in two stages with 8bit each */
+		MV_U8 *bptr = (MV_U8 *)pRxData;
+		MV_U16 data = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG(spiId)));
+		*bptr = (data & 0xFF);
+		++bptr;
+		*bptr = ((data >> 8) & 0xFF);
+
+#elif defined(MV_CPU_BE)
+
+		/* perform the data write to the buffer in two stages with 8bit each */
+		MV_U8 *bptr = (MV_U8 *)pRxData;
+		MV_U16 data = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG(spiId)));
+		*bptr = ((data >> 8) & 0xFF);
+		++bptr;
+		*bptr = (data & 0xFF);
+
+#else
+    #error "CPU endianess isn't defined!\n"
+#endif
+
+	} else
+		*pRxData = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG(spiId)));
+    }
+
+    return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvSpi8bitDataTxRx - Transmt and receive data (8bits)
+*
+* DESCRIPTION:
+*       Tx data and block waiting for data to be transmitted
+*
+********************************************************************************/
+MV_STATUS mvSpi8bitDataTxRx(MV_U8 spiId, MV_U8 txData, MV_U8 *pRxData)
+{
+	MV_U32 i;
+	MV_BOOL ready = MV_FALSE;
+
+	if (currSpiInfo->byteCsAsrt)
+		mvSpiCsAssert(spiId);
+
+	/* First clear the bit in the interrupt cause register */
+	MV_REG_WRITE(MV_SPI_INT_CAUSE_REG(spiId), 0x0);
+
+	/* Transmit data */
+	MV_REG_WRITE(MV_SPI_DATA_OUT_REG(spiId), txData);
+
+	/* wait with timeout for memory ready */
+	for (i = 0; i < MV_SPI_WAIT_RDY_MAX_LOOP; i++) {
+		if (MV_REG_READ(MV_SPI_INT_CAUSE_REG(spiId))) {
+			ready = MV_TRUE;
+			break;
+		}
+#ifdef MV_SPI_SLEEP_ON_WAIT
+		mvOsSleep(1);
+#endif /* MV_SPI_SLEEP_ON_WAIT */
+	}
+
+	if (!ready) {
+		if (currSpiInfo->byteCsAsrt) {
+			mvSpiCsDeassert(spiId);
+			/* WA to compansate Zarlink SLIC CS off time */
+			mvOsUDelay(4);
+		}
+		return MV_TIMEOUT;
+	}
+
+	/* check that the RX data is needed */
+	if (pRxData)
+		*pRxData = MV_REG_READ(MV_SPI_DATA_IN_REG(spiId));
+
+	if (currSpiInfo->byteCsAsrt) {
+		mvSpiCsDeassert(spiId);
+		/* WA to compansate Zarlink SLIC CS off time */
+		mvOsUDelay(4);
+	}
+
+	return MV_OK;
+}
+
+/*
+#####################################################################################
+#####################################################################################
+*/
+
+#if (MV_SPI_VERSION > 1)
+/*******************************************************************************
+* mvSpiCsSet -
+*
+* DESCRIPTION:
+*	Set the Chip-Select to which the next SPI transaction will be
+*	addressed to.
+*
+* INPUT:
+*       csId: The Chip-Select ID to set.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*******************************************************************************/
+MV_STATUS mvSpiCsSet(MV_U8 spiId, MV_U8 csId)
+{
+	MV_U32	ctrlReg;
+	static MV_U8 lastCsId = 0xFF;
+
+	if (csId > 7)
+		return MV_BAD_PARAM;
+
+	if (lastCsId == csId)
+		return MV_OK;
+
+	ctrlReg = MV_REG_READ(MV_SPI_IF_CTRL_REG(spiId));
+	ctrlReg &= ~MV_SPI_CS_NUM_MASK;
+	ctrlReg |= (csId << MV_SPI_CS_NUM_OFFSET);
+	MV_REG_WRITE(MV_SPI_IF_CTRL_REG(spiId), ctrlReg);
+
+	lastCsId = csId;
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvSpiIfConfigSet -
+*
+* DESCRIPTION:
+*	Set the SPI interface parameters.
+*
+* INPUT:
+*       spiId: The SPI controller ID to setup.
+*	ifParams: The interface parameters.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*******************************************************************************/
+MV_STATUS mvSpiIfConfigSet(MV_U8 spiId, MV_SPI_IF_PARAMS *ifParams)
+{
+	MV_U32	ctrlReg;
+
+	ctrlReg = MV_REG_READ(MV_SPI_IF_CONFIG_REG(spiId));
+
+	/* Set Clock Polarity */
+	ctrlReg &= ~(MV_SPI_CPOL_MASK | MV_SPI_CPHA_MASK |
+			MV_SPI_TXLSBF_MASK | MV_SPI_RXLSBF_MASK);
+	if (ifParams->clockPolLow)
+		ctrlReg |= MV_SPI_CPOL_MASK;
+
+	if (ifParams->clockPhase == SPI_CLK_BEGIN_CYC)
+		ctrlReg |= MV_SPI_CPHA_MASK;
+
+	if (ifParams->txMsbFirst)
+		ctrlReg |= MV_SPI_TXLSBF_MASK;
+
+	if (ifParams->rxMsbFirst)
+		ctrlReg |= MV_SPI_RXLSBF_MASK;
+
+	MV_REG_WRITE(MV_SPI_IF_CONFIG_REG(spiId), ctrlReg);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvSpiTimingParamsSet -
+*
+* DESCRIPTION:
+*	Set the SPI timing params.
+*
+* INPUT:
+*       spiId: The SPI controller ID to setup.
+*	tmngParams: The interface timing parameters to configure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*******************************************************************************/
+MV_STATUS mvSpiTimingParamsSet(MV_U8 spiId, MV_SPI_TIMING_PARAMS *tmngParams)
+{
+	MV_U32	ctrlReg;
+
+	ctrlReg = MV_REG_READ(MV_SPI_TMNG_PARAMS_REG(spiId));
+
+	/* Set Clock Polarity */
+	ctrlReg &= ~(MV_SPI_TCSH_MASK | MV_SPI_TMISO_SAMPLE_MASK | MV_SPI_TCS_SETUP_MASK
+			| MV_SPI_TCS_HOLD_MASK);
+	ctrlReg |= ((tmngParams->tcsh << MV_SPI_TCSH_OFFSET) |
+			(tmngParams->tmisoSample << MV_SPI_TMISO_SAMPLE_OFFSET) |
+			(tmngParams->tcsSetup << MV_SPI_TCS_SETUP_OFFSET) |
+			(tmngParams->tcsHold << MV_SPI_TCS_HOLD_OFFSET));
+
+	MV_REG_WRITE(MV_SPI_TMNG_PARAMS_REG(spiId), ctrlReg);
+
+	return MV_OK;
+}
+
+#endif /* (MV_SPI_VERSION > 1) */
+
+/*******************************************************************************
+* mvSpiInit - Initialize the SPI controller
+*
+* DESCRIPTION:
+*       Perform the neccessary initialization in order to be able to send an
+*		receive over the SPI interface.
+*
+* INPUT:
+*       serialBaudRate: Baud rate (SPI clock frequency)
+*		use16BitMode: Whether to use 2bytes (MV_TRUE) or 1bytes (MV_FALSE)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSpiInit(MV_U8 spiId, MV_U32 serialBaudRate, MV_SPI_HAL_DATA *halData)
+{
+    MV_STATUS ret;
+
+    mvOsMemcpy(&spiHalData, halData, sizeof(MV_SPI_HAL_DATA));
+
+    /* Set the serial clock */
+    ret = mvSpiBaudRateSet(spiId, serialBaudRate);
+    if (ret != MV_OK)
+	return ret;
+
+	/* Configure the default SPI mode to be 16bit */
+    MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG(spiId), MV_SPI_BYTE_LENGTH_MASK);
+
+	/* Fix ac timing on SPI in 6183, 6183L and 78x00 only */
+    if ((spiHalData.ctrlModel == MV_6183_DEV_ID) ||
+		(spiHalData.ctrlModel == MV_6183L_DEV_ID) ||
+		(spiHalData.ctrlModel == MV_78100_DEV_ID) ||
+		(spiHalData.ctrlModel == MV_78200_DEV_ID) ||
+		(spiHalData.ctrlModel == MV_76100_DEV_ID) ||
+		(spiHalData.ctrlModel == MV_6323_DEV_ID) ||
+		(spiHalData.ctrlModel == MV_6322_DEV_ID) ||
+		(spiHalData.ctrlModel == MV_6321_DEV_ID))
+			MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG(spiId), BIT14);
+
+    /* Verify that the CS is deasserted */
+    mvSpiCsDeassert(spiId);
+
+    mvSpiParamsSet(spiId, 0, SPI_TYPE_FLASH);
+
+    return MV_OK;
+}
+
+/*******************************************************************************
+* mvSpiBaudRateSet - Set the Frequency of the SPI clock
+*
+* DESCRIPTION:
+*       Set the Prescale bits to adapt to the requested baud rate (the clock
+*       used for thr SPI).
+*
+* INPUT:
+*       serialBaudRate: Baud rate (SPI clock frequency)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+#if (MV_SPI_VERSION == 1)
+MV_STATUS mvSpiBaudRateSet(MV_U8 spiId, MV_U32 serialBaudRate)
+{
+	MV_U8 i;
+	MV_U8 preScale[14] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
+	MV_U8 bestPrescaleIndx = 100;
+	MV_U32 minBaudOffset = 0xFFFFFFFF;
+	MV_U32 cpuClk = spiHalData.tclk; /*mvCpuPclkGet();*/
+	MV_U32 tempReg;
+
+	/* Find the best prescale configuration - less or equal */
+	for (i = 0; i < 14; i++) {
+		/* check for higher - irrelevent */
+		if ((cpuClk / preScale[i]) > serialBaudRate)
+			continue;
+
+		/* check for exact fit */
+		if ((cpuClk / preScale[i]) == serialBaudRate) {
+			bestPrescaleIndx = i;
+			break;
+		}
+
+		/* check if this is better than the previous one */
+		if ((serialBaudRate - (cpuClk / preScale[i])) < minBaudOffset) {
+			minBaudOffset = (serialBaudRate - (cpuClk / preScale[i]));
+			bestPrescaleIndx = i;
+		}
+	}
+
+	if (bestPrescaleIndx > 14) {
+		mvOsPrintf("%s ERROR: SPI baud rate prescale error!\n", __func__);
+		return MV_OUT_OF_RANGE;
+	}
+
+	/* configure the Prescale */
+	tempReg = MV_REG_READ(MV_SPI_IF_CONFIG_REG(spiId));
+	tempReg = ((tempReg & ~MV_SPI_CLK_PRESCALE_MASK) | (bestPrescaleIndx + 0x12));
+
+	if (bestPrescaleIndx == 0) /* if we're using the highest clock, enable fast read. */
+		tempReg |= MV_SPI_DIRECT_READ_MASK;
+
+	MV_REG_WRITE(MV_SPI_IF_CONFIG_REG(spiId), tempReg);
+
+	return MV_OK;
+}
+
+#elif (MV_SPI_VERSION == 2)
+
+MV_STATUS mvSpiBaudRateSet(MV_U8 spiId, MV_U32 serialBaudRate)
+{
+	MV_U32 spr, sppr;
+	MV_U32 divider;
+	MV_U32 bestSpr = 0, bestSppr = 0;
+	MV_U8 exactMatch = 0;
+	MV_U32 minBaudOffset = 0xFFFFFFFF;
+	MV_U32 cpuClk = spiHalData.tclk; /*mvCpuPclkGet();*/
+	MV_U32 tempReg;
+
+	/* Find the best prescale configuration - less or equal */
+	for (spr = 1; spr <= 15; spr++) {
+		for (sppr = 0; sppr <= 7; sppr++) {
+			divider = spr * (1 << sppr);
+			/* check for higher - irrelevent */
+			if ((cpuClk / divider) > serialBaudRate)
+				continue;
+
+			/* check for exact fit */
+			if ((cpuClk / divider) == serialBaudRate) {
+				bestSpr = spr;
+				bestSppr = sppr;
+				exactMatch = 1;
+				break;
+			}
+
+			/* check if this is better than the previous one */
+			if ((serialBaudRate - (cpuClk / divider)) < minBaudOffset) {
+				minBaudOffset = (serialBaudRate - (cpuClk / divider));
+				bestSpr = spr;
+				bestSppr = sppr;
+			}
+		}
+
+		if (exactMatch == 1)
+			break;
+	}
+
+	if (bestSpr == 0) {
+		mvOsPrintf("%s ERROR: SPI baud rate prescale error!\n", __func__);
+		return MV_OUT_OF_RANGE;
+	}
+
+	/* configure the Prescale */
+	tempReg = MV_REG_READ(MV_SPI_IF_CONFIG_REG(spiId)) & ~(MV_SPI_SPR_MASK | MV_SPI_SPPR_0_MASK |
+			MV_SPI_SPPR_HI_MASK);
+	tempReg |= ((bestSpr << MV_SPI_SPR_OFFSET) |
+			((bestSppr & 0x1) << MV_SPI_SPPR_0_OFFSET) |
+			((bestSppr >> 1) << MV_SPI_SPPR_HI_OFFSET));
+	MV_REG_WRITE(MV_SPI_IF_CONFIG_REG(spiId), tempReg);
+
+	return MV_OK;
+}
+
+#else
+
+#error "MV_SPI_VERSION is not defined."
+
+#endif
+
+/*******************************************************************************
+* mvSpiCsAssert - Assert the Chip Select pin indicating a new transfer
+*
+* DESCRIPTION:
+*       Assert The chip select - used to select an external SPI device
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+********************************************************************************/
+MV_VOID mvSpiCsAssert(MV_U8 spiId)
+{
+	/* For devices in which the SPI is muxed on the MPP with other interfaces*/
+	mvSysSpiMppConfig(SYS_SPI_MPP_ENABLE);
+	mvOsUDelay(1);
+	MV_REG_BIT_SET(MV_SPI_IF_CTRL_REG(spiId), MV_SPI_CS_ENABLE_MASK);
+}
+
+/*******************************************************************************
+* mvSpiCsDeassert - DeAssert the Chip Select pin indicating the end of a
+*				  SPI transfer sequence
+*
+* DESCRIPTION:
+*       DeAssert the chip select pin
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+********************************************************************************/
+MV_VOID mvSpiCsDeassert(MV_U8 spiId)
+{
+	MV_REG_BIT_RESET(MV_SPI_IF_CTRL_REG(spiId), MV_SPI_CS_ENABLE_MASK);
+
+	/* For devices in which the SPI is muxed on the MPP with other interfaces*/
+	mvSysSpiMppConfig(SYS_SPI_MPP_DEFAULT);
+}
+
+/*******************************************************************************
+* mvSpiRead - Read a buffer over the SPI interface
+*
+* DESCRIPTION:
+*       Receive (read) a buffer over the SPI interface in 16bit chunks. If the
+*		buffer size is odd, then the last chunk will be 8bits. Chip select is not
+*       handled at this level.
+*
+* INPUT:
+*		pRxBuff: Pointer to the buffer to hold the received data
+*		buffSize: length of the pRxBuff
+*
+* OUTPUT:
+*		pRxBuff: Pointer to the buffer with the received data
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSpiRead(MV_U8 spiId, MV_U8 *pRxBuff, MV_U32 buffSize)
+{
+    MV_STATUS ret;
+	MV_U32 bytesLeft = buffSize;
+	MV_U16 *rxPtr = (MV_U16 *)pRxBuff;
+
+    /* check for null parameters */
+    if (pRxBuff == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Check that the buffer pointer and the buffer size are 16bit aligned */
+    if ((currSpiInfo->en16Bit) && (((MV_U32)buffSize & 1) == 0) && (((MV_U32)pRxBuff & 1) == 0)) {
+	/* Verify that the SPI mode is in 16bit mode */
+	MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG(spiId), MV_SPI_BYTE_LENGTH_MASK);
+
+	/* TX/RX as long we have complete 16bit chunks */
+	while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE) {
+		/* Transmitted and wait for the transfer to be completed */
+		ret = mvSpi16bitDataTxRx(spiId, MV_SPI_DUMMY_WRITE_16BITS, rxPtr);
+		if (ret != MV_OK)
+			return ret;
+
+		/* increment the pointers */
+		rxPtr++;
+		bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
+	}
+
+    } else {
+	/* Verify that the SPI mode is in 8bit mode */
+	MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG(spiId), MV_SPI_BYTE_LENGTH_MASK);
+
+	/* TX/RX in 8bit chanks */
+	while (bytesLeft > 0) {
+		/* Transmitted and wait for the transfer to be completed */
+		ret = mvSpi8bitDataTxRx(spiId, MV_SPI_DUMMY_WRITE_8BITS, pRxBuff);
+		if (ret != MV_OK)
+			return ret;
+		/* increment the pointers */
+		pRxBuff++;
+		bytesLeft--;
+	}
+    }
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvSpiWrite - Transmit a buffer over the SPI interface
+*
+* DESCRIPTION:
+*       Transmit a buffer over the SPI interface in 16bit chunks. If the
+*		buffer size is odd, then the last chunk will be 8bits. No chip select
+*       action is taken.
+*
+* INPUT:
+*		pTxBuff: Pointer to the buffer holding the TX data
+*		buffSize: length of the pTxBuff
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSpiWrite(MV_U8 spiId, MV_U8 *pTxBuff, MV_U32 buffSize)
+{
+    MV_STATUS ret;
+	MV_U32 bytesLeft = buffSize;
+	MV_U16 *txPtr = (MV_U16 *)pTxBuff;
+
+    /* check for null parameters */
+    if (pTxBuff == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* Check that the buffer pointer and the buffer size are 16bit aligned */
+    if ((currSpiInfo->en16Bit)
+	&& (currSpiInfo->en16Bit)
+	&& (((MV_U32)buffSize & 1) == 0)
+	&& (((MV_U32)pTxBuff & 1) == 0)) {
+	/* Verify that the SPI mode is in 16bit mode */
+	MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG(spiId), MV_SPI_BYTE_LENGTH_MASK);
+
+	/* TX/RX as long we have complete 16bit chunks */
+	while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE) {
+	/* Transmitted and wait for the transfer to be completed */
+		ret = mvSpi16bitDataTxRx(spiId, *txPtr, NULL);
+		if (ret != MV_OK)
+			return ret;
+		/* increment the pointers */
+		txPtr++;
+		bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
+	}
+    } else {
+	/* Verify that the SPI mode is in 8bit mode */
+	MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG(spiId), MV_SPI_BYTE_LENGTH_MASK);
+
+	/* TX/RX in 8bit chanks */
+	while (bytesLeft > 0) {
+		/* Transmitted and wait for the transfer to be completed */
+		ret = mvSpi8bitDataTxRx(spiId, *pTxBuff, NULL);
+		if (ret != MV_OK)
+			return ret;
+
+		/* increment the pointers */
+		pTxBuff++;
+		bytesLeft--;
+	}
+    }
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvSpiReadWrite - Read and Write a buffer simultanuosely
+*
+* DESCRIPTION:
+*       Transmit and receive a buffer over the SPI in 16bit chunks. If the
+*		buffer size is odd, then the last chunk will be 8bits. The SPI chip
+*       select is not handled implicitely.
+*
+* INPUT:
+*       pRxBuff: Pointer to the buffer to write the RX info in
+*		pTxBuff: Pointer to the buffer holding the TX info
+*		buffSize: length of both the pTxBuff and pRxBuff
+*
+* OUTPUT:
+*       pRxBuff: Pointer of the buffer holding the RX data
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSpiReadWrite(MV_U8 spiId, MV_U8 *pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize)
+{
+    MV_STATUS ret;
+    MV_U32 bytesLeft = buffSize;
+    MV_U16 *txPtr = (MV_U16 *)pTxBuff;
+    MV_U16 *rxPtr = (MV_U16 *)pRxBuff;
+
+	/* check for null parameters */
+	if ((pRxBuff == NULL) || (pTxBuff == NULL)) {
+		mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+		return MV_BAD_PARAM;
+	}
+
+	 /* Check that the buffer pointer and the buffer size are 16bit aligned */
+	if ((currSpiInfo->en16Bit)
+		&& (((MV_U32)buffSize & 1) == 0)
+		&& (((MV_U32)pTxBuff & 1) == 0)
+		&& (((MV_U32)pRxBuff & 1) == 0)) {
+		/* Verify that the SPI mode is in 16bit mode */
+		MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG(spiId), MV_SPI_BYTE_LENGTH_MASK);
+
+		/* TX/RX as long we have complete 16bit chunks */
+		while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE) {
+		/* Transmitted and wait for the transfer to be completed */
+			ret = mvSpi16bitDataTxRx(spiId, *txPtr, rxPtr);
+			if (ret != MV_OK)
+				return ret;
+			/* increment the pointers */
+			txPtr++;
+			rxPtr++;
+			bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
+		}
+	} else {
+		/* Verify that the SPI mode is in 8bit mode */
+		MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG(spiId), MV_SPI_BYTE_LENGTH_MASK);
+
+		/* TX/RX in 8bit chanks */
+		while (bytesLeft > 0) {
+			/* Transmitted and wait for the transfer to be completed */
+			ret = mvSpi8bitDataTxRx(spiId, *pTxBuff, pRxBuff);
+			if (ret != MV_OK)
+				return ret;
+			pRxBuff++;
+			pTxBuff++;
+			bytesLeft--;
+		}
+	}
+
+	return MV_OK;
+}
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/spi/mvSpi.h b/arch/arm/plat-feroceon/mv_hal/spi/mvSpi.h
new file mode 100755
index 0000000..d9948e4
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/spi/mvSpi.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSpihH
+#define __INCmvSpihH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysSpiConfig.h"
+
+typedef struct {
+	MV_U16		ctrlModel;
+	MV_U32		tclk;
+} MV_SPI_HAL_DATA;
+
+#if (MV_SPI_VERSION > 1)
+
+typedef struct {
+	MV_BOOL		clockPolLow;
+	enum {
+		SPI_CLK_HALF_CYC,
+		SPI_CLK_BEGIN_CYC
+	}		clockPhase;
+	MV_BOOL		txMsbFirst;
+	MV_BOOL		rxMsbFirst;
+} MV_SPI_IF_PARAMS;
+
+
+typedef struct {
+	MV_U8	tcsh;
+	MV_U8	tmisoSample;
+	MV_U8	tcsSetup;
+	MV_U8	tcsHold;
+} MV_SPI_TIMING_PARAMS;
+
+#endif
+
+typedef struct {
+	/* Does this device support 16 bits access */
+	MV_BOOL	en16Bit;
+	/* should we assert / disassert CS for each byte we read / write */
+	MV_BOOL	byteCsAsrt;
+	MV_U32	baudRate;
+} MV_SPI_TYPE_INFO;
+
+typedef enum {
+	SPI_TYPE_FLASH = 0,
+	SPI_TYPE_SLIC
+} MV_SPI_TYPE;
+
+
+/* Function Prototypes */
+/* Init */
+MV_STATUS mvSpiInit(MV_U8 spiId, MV_U32 serialBaudRate, MV_SPI_HAL_DATA *halData);
+MV_STATUS mvSpi8bitDataTxRx(MV_U8 spiId, MV_U8 txData, MV_U8 *pRxData);
+MV_STATUS mvSpi16bitDataTxRx(MV_U8 spiId, MV_U16 txData, MV_U16 *pRxData);
+
+/* Set the Frequency of the Spi clock */
+MV_STATUS   mvSpiBaudRateSet(MV_U8 spiId, MV_U32 serialBaudRate);
+
+/* Assert the SPI chip select */
+MV_VOID     mvSpiCsAssert(MV_U8 spiId);
+
+/* De-assert the SPI chip select */
+MV_VOID     mvSpiCsDeassert(MV_U8 spiId);
+
+/* Simultanuous Read and write */
+MV_STATUS	mvSpiReadWrite(MV_U8 spiId, MV_U8 *pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize);
+
+/* serialize a buffer on the TX line - Rx is ignored */
+MV_STATUS	mvSpiWrite(MV_U8 spiId, MV_U8 *pTxBuff, MV_U32 buffSize);
+
+/* read from the RX line by writing dummy values to the TX line */
+MV_STATUS	mvSpiRead(MV_U8 spiId, MV_U8 *pRxBuff, MV_U32 buffSize);
+
+/* Set SPI parameters before any transaction is issued */
+MV_STATUS mvSpiParamsSet(MV_U8 spiId, MV_U8 csId, MV_SPI_TYPE type);
+
+#if (MV_SPI_VERSION > 1)
+
+MV_STATUS mvSpiCsSet(MV_U8 spiId, MV_U8 csId);
+MV_STATUS mvSpiIfConfigSet(MV_U8 spiId, MV_SPI_IF_PARAMS *ifParams);
+MV_STATUS mvSpiTimingParamsSet(MV_U8 spiId, MV_SPI_TIMING_PARAMS *tmngParams);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCmvSpihH */
diff --git a/arch/arm/plat-feroceon/mv_hal/spi/mvSpiCmnd.c b/arch/arm/plat-feroceon/mv_hal/spi/mvSpiCmnd.c
new file mode 100755
index 0000000..9887478
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/spi/mvSpiCmnd.c
@@ -0,0 +1,256 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysSpiConfig.h"
+#include "mvSpiSpec.h"
+#include "mvSpiCmnd.h"
+#include "mvSpi.h"
+
+
+/*#define MV_DEBUG*/
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+extern MV_SPI_TYPE_INFO *currSpiInfo;
+
+
+/*******************************************************************************
+* mvSpiReadAndWrite - Read and Write a buffer simultanuousely
+*
+* DESCRIPTION:
+*       Transmit and receive a buffer over the SPI in 16bit chunks. If the
+*		buffer size is odd, then the last chunk will be 8bits.
+*
+* INPUT:
+*       pRxBuff: Pointer to the buffer to write the RX info in
+*		pTxBuff: Pointer to the buffer holding the TX info
+*		buffSize: length of both the pTxBuff and pRxBuff
+*
+* OUTPUT:
+*       pRxBuff: Pointer of the buffer holding the RX data
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSpiReadAndWrite(MV_U8 spiId, MV_U8 *pRxBuff, MV_U8 *pTxBuff, MV_U32 buffSize)
+{
+    MV_STATUS ret;
+
+    /* check for null parameters */
+    if ((pRxBuff == NULL) || (pTxBuff == NULL) || (buffSize == 0)) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* First assert the chip select */
+    mvSpiCsAssert(spiId);
+
+    ret = mvSpiReadWrite(spiId, pRxBuff, pTxBuff, buffSize);
+
+    /* Finally deassert the chip select */
+    mvSpiCsDeassert(spiId);
+
+	return ret;
+}
+
+/*******************************************************************************
+* mvSpiWriteThenWrite - Serialize a command followed by the data over the TX line
+*
+* DESCRIPTION:
+*       Assert the chip select line. Transmit the command buffer followed by
+*       the data buffer. Then deassert the CS line.
+*
+* INPUT:
+*       pCmndBuff: Pointer to the command buffer to transmit
+*       cmndSize: length of the command size
+*		pTxDataBuff: Pointer to the data buffer to transmit
+*		txDataSize: length of the data buffer
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS	mvSpiWriteThenWrite(MV_U8 spiId, MV_U8 *pCmndBuff, MV_U32 cmndSize, MV_U8 *pTxDataBuff,
+				MV_U32 txDataSize)
+{
+    MV_STATUS ret = MV_OK, tempRet;
+
+    /* check for null parameters */
+#ifndef CONFIG_MARVELL
+    if (NULL == pTxDataBuff) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+    return MV_BAD_PARAM;
+    }
+#endif
+
+    if (pCmndBuff == NULL) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* First assert the chip select */
+    if (!currSpiInfo->byteCsAsrt)
+	mvSpiCsAssert(spiId);
+
+    /* first write the command */
+    if ((cmndSize) && (pCmndBuff != NULL)) {
+	tempRet = mvSpiWrite(spiId, pCmndBuff, cmndSize);
+	if (tempRet != MV_OK)
+		ret = tempRet;
+    }
+
+    /* Then write the data buffer */
+#ifndef CONFIG_MARVELL
+    if (txDataSize) {
+#else
+    if ((txDataSize) && (pTxDataBuff != NULL)) {
+#endif
+	tempRet = mvSpiWrite(spiId, pTxDataBuff, txDataSize);
+	if (tempRet != MV_OK)
+		ret = tempRet;
+    }
+
+    /* Finally deassert the chip select */
+    if (!currSpiInfo->byteCsAsrt)
+	mvSpiCsDeassert(spiId);
+
+    return ret;
+}
+
+/*******************************************************************************
+* mvSpiWriteThenRead - Serialize a command then read a data buffer
+*
+* DESCRIPTION:
+*       Assert the chip select line. Transmit the command buffer then read
+*       the data buffer. Then deassert the CS line.
+*
+* INPUT:
+*       pCmndBuff: Pointer to the command buffer to transmit
+*       cmndSize: length of the command size
+*		pRxDataBuff: Pointer to the buffer to read the data in
+*		txDataSize: length of the data buffer
+*
+* OUTPUT:
+*		pRxDataBuff: Pointer to the buffer holding the data
+*
+* RETURN:
+*       Success or Error code.
+*
+*
+*******************************************************************************/
+MV_STATUS mvSpiWriteThenRead(MV_U8 spiId, MV_U8 *pCmndBuff, MV_U32 cmndSize, MV_U8 *pRxDataBuff,
+				MV_U32 rxDataSize, MV_U32 dummyBytesToRead)
+{
+    MV_STATUS ret = MV_OK, tempRet;
+    MV_U8   dummyByte;
+
+    /* check for null parameters */
+    if ((pCmndBuff == NULL) && (pRxDataBuff == NULL)) {
+	mvOsPrintf("%s ERROR: Null pointer parameter!\n", __func__);
+	return MV_BAD_PARAM;
+    }
+
+    /* First assert the chip select */
+    if (!currSpiInfo->byteCsAsrt)
+	mvSpiCsAssert(spiId);
+
+    /* first write the command */
+    if ((cmndSize) && (pCmndBuff != NULL)) {
+	tempRet = mvSpiWrite(spiId, pCmndBuff, cmndSize);
+	if (tempRet != MV_OK)
+		ret = tempRet;
+    }
+
+    /* Read dummy bytes before real data.   */
+    while (dummyBytesToRead) {
+	mvSpiRead(spiId, &dummyByte, 1);
+	dummyBytesToRead--;
+    }
+
+    /* Then write the data buffer */
+    if ((rxDataSize) && (pRxDataBuff != NULL)) {
+	tempRet = mvSpiRead(spiId, pRxDataBuff, rxDataSize);
+	if (tempRet != MV_OK)
+	ret = tempRet;
+    }
+
+    /* Finally deassert the chip select */
+    if (!currSpiInfo->byteCsAsrt)
+	mvSpiCsDeassert(spiId);
+
+    return ret;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/spi/mvSpiCmnd.h b/arch/arm/plat-feroceon/mv_hal/spi/mvSpiCmnd.h
new file mode 100755
index 0000000..3bb0168
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/spi/mvSpiCmnd.h
@@ -0,0 +1,90 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSpiCmndhH
+#define __INCmvSpiCmndhH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvTypes.h"
+
+/* Function Prototypes */
+
+/* Simultanuous Read and write */
+MV_STATUS	mvSpiReadAndWrite(MV_U8 spiId, MV_U8 *pRxBuff, MV_U8 *pTxBuff, MV_U32 buffSize);
+
+/* write command - write a command and then write data */
+MV_STATUS	mvSpiWriteThenWrite(MV_U8 spiId, MV_U8 *pCmndBuff, MV_U32 cmndSize, MV_U8 *pTxDataBuff, MV_U32 txDataSize);
+
+/* read command - write a command and then read data by writing dummy data */
+MV_STATUS mvSpiWriteThenRead(MV_U8 spiId, MV_U8 *pCmndBuff, MV_U32 cmndSize, MV_U8 *pRxDataBuff,
+				MV_U32 rxDataSize, MV_U32 dummyBytesToRead);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCmvSpiCmndhH */
diff --git a/arch/arm/plat-feroceon/mv_hal/spi/mvSpiSpec.h b/arch/arm/plat-feroceon/mv_hal/spi/mvSpiSpec.h
new file mode 100755
index 0000000..6dca025
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/spi/mvSpiSpec.h
@@ -0,0 +1,139 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSpiSpecH
+#define __INCmvSpiSpecH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvSysSpiConfig.h"
+
+/* Constants */
+#define		MV_SPI_WAIT_RDY_MAX_LOOP			100000
+#define		MV_SPI_16_BIT_CHUNK_SIZE			2
+#define		MV_SPI_DUMMY_WRITE_16BITS			0xFFFF
+#define		MV_SPI_DUMMY_WRITE_8BITS			0xFF
+
+/* Marvell Flash Device Controller Registers */
+#define		MV_SPI_IF_CTRL_REG(spiId)			(MV_SPI_REGS_BASE(spiId) + 0x00)
+#define		MV_SPI_IF_CONFIG_REG(spiId)			(MV_SPI_REGS_BASE(spiId) + 0x04)
+#define		MV_SPI_DATA_OUT_REG(spiId)			(MV_SPI_REGS_BASE(spiId) + 0x08)
+#define		MV_SPI_DATA_IN_REG(spiId)			(MV_SPI_REGS_BASE(spiId) + 0x0c)
+#define		MV_SPI_INT_CAUSE_REG(spiId)			(MV_SPI_REGS_BASE(spiId) + 0x10)
+#define		MV_SPI_INT_CAUSE_MASK_REG(spiId)		(MV_SPI_REGS_BASE(spiId) + 0x14)
+#define		MV_SPI_TMNG_PARAMS_REG(spiId)			(MV_SPI_REGS_BASE(spiId) + 0x18)
+
+/* Serial Memory Interface Control Register Masks */
+#define		MV_SPI_CS_ENABLE_OFFSET				0		/* bit 0 */
+#define		MV_SPI_MEMORY_READY_OFFSET			1		/* bit 1 */
+#define		MV_SPI_CS_ENABLE_MASK				(0x1  << MV_SPI_CS_ENABLE_OFFSET)
+#define		MV_SPI_MEMORY_READY_MASK			(0x1  << MV_SPI_MEMORY_READY_OFFSET)
+#define		MV_SPI_CS_NUM_OFFSET				2
+#define		MV_SPI_CS_NUM_MASK				(0x7 << MV_SPI_CS_NUM_OFFSET)
+
+/* SPI Timing Parameters Register */
+#define		MV_SPI_TCSH_OFFSET				0
+#define		MV_SPI_TCSH_MASK				(0x7F << MV_SPI_TCSH_OFFSET)
+#define		MV_SPI_TMISO_SAMPLE_OFFSET			6
+#define		MV_SPI_TMISO_SAMPLE_MASK			(0x3 << MV_SPI_TMISO_SAMPLE_OFFSET)
+#define		MV_SPI_TCS_SETUP_OFFSET				8
+#define		MV_SPI_TCS_SETUP_MASK				(0xF << MV_SPI_TCS_SETUP_OFFSET)
+#define		MV_SPI_TCS_HOLD_OFFSET				12
+#define		MV_SPI_TCS_HOLD_MASK				(0xF << MV_SPI_TCS_HOLD_OFFSET)
+
+
+/* Serial Memory Interface Configuration Register Masks */
+#define		MV_SPI_CLK_PRESCALE_OFFSET			0	/* bit 0-4 */
+#define		MV_SPI_BYTE_LENGTH_OFFSET			5	/* bit 5 */
+#define		MV_SPI_ADDRESS_BURST_LENGTH_OFFSET		8	/* bit 8-9 */
+#define		MV_SPI_DIRECT_READ_OFFSET			10
+#define		MV_SPI_DIRECT_READ_MASK				(1 << MV_SPI_DIRECT_READ_OFFSET)
+#define		MV_SPI_CLK_PRESCALE_MASK			(0x1F << MV_SPI_CLK_PRESCALE_OFFSET)
+#define		MV_SPI_BYTE_LENGTH_MASK				(0x1  << MV_SPI_BYTE_LENGTH_OFFSET)
+#define		MV_SPI_ADDRESS_BURST_LENGTH_MASK		(0x3  << MV_SPI_ADDRESS_BURST_LENGTH_OFFSET)
+#define		MV_SPI_CPOL_OFFSET				11
+#define		MV_SPI_CPOL_MASK				(0x1 << MV_SPI_CPOL_OFFSET)
+#define		MV_SPI_CPHA_OFFSET				12
+#define		MV_SPI_CPHA_MASK				(0x1 << MV_SPI_CPHA_OFFSET)
+#define		MV_SPI_TXLSBF_OFFSET				13
+#define		MV_SPI_TXLSBF_MASK				(0x1 << MV_SPI_TXLSBF_OFFSET)
+#define		MV_SPI_RXLSBF_OFFSET				14
+#define		MV_SPI_RXLSBF_MASK				(0x1 << MV_SPI_RXLSBF_OFFSET)
+
+#define		MV_SPI_SPR_OFFSET				0
+#define		MV_SPI_SPR_MASK					(0xF << MV_SPI_SPR_OFFSET)
+#define		MV_SPI_SPPR_0_OFFSET				4
+#define		MV_SPI_SPPR_0_MASK				(0x1 << MV_SPI_SPPR_0_OFFSET)
+#define		MV_SPI_SPPR_HI_OFFSET				6
+#define		MV_SPI_SPPR_HI_MASK				(0x3 << MV_SPI_SPPR_HI_OFFSET)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCmvSpiSpecH */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/spi/mvSysSpi.h b/arch/arm/plat-feroceon/mv_hal/spi/mvSysSpi.h
new file mode 100755
index 0000000..dbb4bc9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/spi/mvSysSpi.h
@@ -0,0 +1,101 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvSysSpiH
+#define __INCmvSysSpiH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SYS_SPI_MPP_ENABLE		0x1
+#define SYS_SPI_MPP_DEFAULT		0x2
+
+
+/*******************************************************************************
+* mvSysSpiMppConfig
+*
+* DESCRIPTION:
+*	System interface for configuring the MPP's configuration to enable /
+*	disable SPI mode.
+*
+* INPUT:
+*      	mode:	The mode to be set into MPP unit.
+*
+* OUTPUT:
+*	None.
+*
+* RETURN:
+*	MV_OK on success,
+*	MV_ERROR otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvSysSpiMppConfig(MV_U8 mode);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/ts/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/ts/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ts/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/ts/mvTsu.c b/arch/arm/plat-feroceon/mv_hal/ts/mvTsu.c
new file mode 100755
index 0000000..17dc429
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ts/mvTsu.c
@@ -0,0 +1,1733 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysTsConfig.h"
+#include "mvTsuRegs.h"
+#include "mvTsu.h"
+
+/********************************/
+/* Local enums and structures	*/
+/********************************/
+#define TSU_MIN_PKT_SIZE		188
+#define TSU_MAX_PKT_SIZE		256
+#define TSU_NUM_CLOCK_DIVIDERS		6
+
+typedef struct
+{
+	MV_U32			aggrMode;
+	MV_U16			pktSize;
+	MV_TSU_PORT_DIRECTION	portDir;
+	MV_ULONG		descPhyAddr;
+	MV_U32			*descVirtAddr;
+	MV_U32			descMemHandle;
+	MV_U32			numTsDesc;
+	MV_U32			numDoneQEntry;
+	MV_U32			aggrNumPckts;
+	MV_U32			*tsDataBuff;
+	MV_U32			*tsDoneBuff;
+	MV_U32			dataBlockSize;
+	MV_U32			dataReadIdx;
+	MV_U32			statReadIdx;
+	MV_U32			cpuRollBit;
+	MV_U32			descSize;
+	MV_U32			queueMask;
+	MV_U32			queueDescSize;
+	MV_BOOL			enableTimer;
+}MV_TSU_PORT_CTRL;
+
+typedef struct
+{
+	MV_U32 			numActPorts;
+	MV_TSU_PORTS_MODE 	mode;
+	MV_TSU_CORE_CLOCK	coreClock;
+	void 			*osHandle;
+}MV_TSU_CTRL;
+
+/********************************/
+/* Local Macros			*/
+/********************************/
+#define TS_SIGNAL_PARAMS_CONFIG(cfg,usedMask,polMask,reg)		\
+	{								\
+		if(cfg != TSU_SIGNAL_KEEP_DEF)				\
+		{							\
+			reg &= ~(usedMask | polMask);			\
+			if(cfg != TSU_SIGNAL_DIS)			\
+			{						\
+				reg |= usedMask;			\
+				if(cfg == TSU_SIGNAL_EN_ACT_HIGH)	\
+					reg |= polMask;			\
+			}						\
+		}							\
+	}
+
+#define TS_SIGNAL_PARAMS_GET(cfg,usedMask,polMask,reg)			\
+	{								\
+		if(reg & usedMask)					\
+		{							\
+			if(reg & polMask)				\
+				cfg = TSU_SIGNAL_EN_ACT_HIGH;		\
+			else						\
+				cfg = TSU_SIGNAL_EN_ACT_LOW;		\
+		}							\
+		else							\
+		{							\
+			cfg = TSU_SIGNAL_DIS;				\
+		}							\
+	}
+
+
+
+#define TSU_SET_DESC_BUFF_PTR(desc,addr)	(*(MV_U32*)desc) = addr
+#define TSU_SET_OUT_DESC_TMSTMP(desc,tms,err)		\
+	(*((MV_U32*)desc + 1)) = (tms | (err << 28))
+
+#define TSU_BUFF_HNDL(d, s) (MV_U32) ((d & 0xFFFF) | ((s & 0xFFFF) << 16))
+#define TSU_BUFF_HNDL_2_DATA_IDX(h) (MV_U32)(h & 0xFFFF)
+#define TSU_BUFF_HNDL_2_STAT_IDX(h) (MV_U32)((h >> 16) & 0xFFFF)
+
+/********************************/
+/* Control variables.           */
+/********************************/
+MV_U32  mvTsuCoreClock2Val[] = {
+	83 * _1M,	/* TSU_CORE_CLK_83_MHZ 	*/
+	71 * _1M,	/* TSU_CORE_CLK_71_MHZ	*/
+	91 * _1M,	/* TSU_CORE_CLK_91_MHZ	*/
+	100 * _1M	/* TSU_CORE_CLK_100_MHZ	*/
+};
+MV_TSU_CTRL		mvTsuCtrl;
+MV_TSU_PORT_CTRL 	mvTsuPortCtrl[MV_TSU_NUM_PORTS];
+
+
+/********************************/
+/* Forward functions declaration*/
+/********************************/
+inline static MV_STATUS mvTsuOperationModeSet(MV_U8 port, MV_BOOL enable);
+static MV_STATUS mvTsuReadyBuffCountGet(MV_U8 port, MV_U32 *numBlocks,
+					MV_U32 *numBuffers);
+static MV_STATUS mvTsuPortEnable(MV_U8 port,MV_BOOL enable);
+
+/********************************/
+/* Functions Implementation	*/
+/********************************/
+
+
+/*******************************************************************************
+* mvTsuHalInit
+*
+* DESCRIPTION:
+* 	Initialize the TSU unit, and get unit out of reset.
+*
+* INPUT:
+*       coreClock	- The core clock at which the TSU should operate.
+*       mode		- The mode on configure the unit into (serial/parallel).
+* 	osHandle	- Memory handle used for memory allocations.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK	- on success,
+*
+*******************************************************************************/
+MV_STATUS mvTsuHalInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode,
+		       void *osHandle)
+{
+	MV_U32	reg;
+	MV_U32 port;
+
+	/* Setup the core clock.			*/
+	reg = MV_REG_READ(MV_TSU_MODES_REG);
+	reg &= TSU_MODES_TSCK_MASK;
+	reg |= (coreClock << TSU_MODES_TSCK_OFF);
+
+	/* Configure the mode				*/
+	reg &= ~TSU_MODES_PAR_MODE_MASK;
+	if(mode == TSU_MODE_SERIAL) {
+		reg |= TSU_MODES_PAR_MODE_SER;
+		mvTsuCtrl.numActPorts = 2;
+	} else {
+		reg |= TSU_MODES_PAR_MODE_PAR;
+		mvTsuCtrl.numActPorts = 1;
+	}
+	MV_REG_WRITE(MV_TSU_MODES_REG,reg);
+
+	/* Get ports out of reset.				*/
+	for(port = 0; port < MV_TSU_NUM_PORTS; port++)
+		mvTsuPortReset(port);
+
+	/* Setup control veraibles.			*/
+	mvTsuCtrl.coreClock = coreClock;
+	mvTsuCtrl.osHandle = osHandle;
+	mvTsuCtrl.mode = mode;
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuShutdown
+*
+* DESCRIPTION:
+* 	Shutdown the TS unit, and put into reset state.
+*
+* INPUT:
+*       None.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK	- on success,
+*
+*******************************************************************************/
+MV_STATUS mvTsuShutdown(void)
+{
+	//...
+	// Check if it's possible to put the module back into reset mode.
+	return MV_NOT_IMPLEMENTED;
+}
+
+
+/*******************************************************************************
+* mvTsuPortReset
+*
+* DESCRIPTION:
+* 	Perform a SW reset on a given port.
+*
+* INPUT:
+*	port	- The port number to reset.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_BAD_VALUE	- Bad port configuration option.
+*	MV_BAD_SIZE	- Illegal number of ports.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortReset(MV_U8 port)
+{
+	MV_U32 reg;
+
+	/* Check the correctness of parameters.		*/
+	if(port >= MV_TSU_NUM_PORTS)
+		return MV_BAD_SIZE;
+
+	/* First, set in reset mode, then get out of reset.	*/
+	reg = MV_REG_READ(MV_TSU_CONFIG_REG(port));
+	reg &= ~TSU_CFG_RESET_MASK;
+	reg |= TSU_CFG_RESET_SET;
+	MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg);
+	reg &= ~TSU_CFG_RESET_MASK;
+	reg |= TSU_CFG_RESET_CLEAR;
+	MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuPortInit
+*
+* DESCRIPTION:
+* 	Initialize the TSU ports.
+*
+* INPUT:
+*	port	- The port number to configure.
+*	portCfg	- Port configurations parameters.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_BAD_VALUE	- Bad port configuration option.
+*	MV_BAD_SIZE	- Illegal number of ports.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortInit(MV_U8 port, MV_TSU_PORT_CONFIG *portCfg)
+{
+	MV_U32	reg;
+
+	/* Check the correctness of parameters.		*/
+	if(((mvTsuCtrl.mode == TSU_MODE_SERIAL) && (port >= MV_TSU_NUM_PORTS))||
+	   ((mvTsuCtrl.mode == TSU_MODE_PARALLEL) && (port >= 1)))
+		return MV_BAD_SIZE;
+
+	if((portCfg->pktSize < TSU_MIN_PKT_SIZE) ||
+	   (portCfg->pktSize > TSU_MAX_PKT_SIZE))
+		return MV_BAD_VALUE;
+
+	/* configure the port parameters		*/
+	/* Disable operation mode.			*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+        reg = MV_REG_READ(MV_TSU_CONFIG_REG(port));
+
+	/* Setup packet size.			*/
+	reg &= ~TSU_CFG_PKT_SIZE_MASK;
+	reg |= (((portCfg->pktSize - 1) & 0xFF) << TSU_CFG_PKT_SIZE_OFFS);
+
+	/* Setup data direction.		*/
+	reg &= ~TSU_CFG_DATA_DIR_MASK;
+	if(portCfg->portDir == TSU_PORT_INPUT)
+		reg |= TSU_CFG_DATA_DIR_IN;
+	else
+		reg |= TSU_CFG_DATA_DIR_OUT;
+
+	/* Setup serial / parallel mode.	*/
+	reg &= ~TSU_CFG_DATA_MODE_MASK;
+	if(mvTsuCtrl.mode == TSU_MODE_SERIAL)
+		reg |= TSU_CFG_DATA_MODE_SER;
+	else
+		reg |= TSU_CFG_DATA_MODE_PAR;
+
+	MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg);
+
+	/* Setup DMA packet size.		*/
+	reg = MV_REG_READ(MV_TSU_DMA_PARAMS_REG(port));
+	reg &= ~TSU_DMAP_DMA_LEN_MASK;
+	reg |= portCfg->pktSize;
+	MV_REG_WRITE(MV_TSU_DMA_PARAMS_REG(port),reg);
+
+	/* Setup timestamp auto adjust.		*/
+	if(portCfg->portDir == TSU_PORT_OUTPUT)
+	{
+		reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port));
+		reg &= ~TSU_TMS_CTRL_AUTO_ADJ_MASK;
+		reg |= TSU_TMS_CTRL_AUTO_ADJ_ON;
+		MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg);
+	}
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+
+	/* Update global control vars.			*/
+	mvTsuPortCtrl[port].pktSize = portCfg->pktSize;
+	mvTsuPortCtrl[port].portDir = portCfg->portDir;
+
+	MV_REG_BIT_SET(MV_TSU_CONFIG_REG(port),(1 << 17));
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuPortSignalCfgSet
+*
+* DESCRIPTION:
+* 	Configure port signals parameters.
+*
+* INPUT:
+*       port 		- The port to configure.
+*	signalCfg	- Signal configuration options.
+*	serialflags	- Serial signal configuration options (valid only if the
+*			  port is working in serial mode).
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_BAD_VALUE	- Bad port configuration option.
+*	MV_BAD_SIZE	- Illegal number of ports.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortSignalCfgSet(MV_U8 port, MV_TSU_SIGNAL_CONFIG *signalCfg,
+				MV_U32 serialFlags)
+{
+	MV_U32	reg;
+
+	if(port >= MV_TSU_NUM_PORTS)
+		return MV_OUT_OF_RANGE;
+
+	/* Disable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	reg = MV_REG_READ(MV_TSU_CONFIG_REG(port));
+
+	/* Setup signal related options.	*/
+	TS_SIGNAL_PARAMS_CONFIG(signalCfg->tsSync,
+				TSU_CFG_SYNC_USED_MASK,
+				TSU_CFG_SYNC_POL_MASK,reg);
+	TS_SIGNAL_PARAMS_CONFIG(signalCfg->tsValid,
+				TSU_CFG_VAL_USED_MASK,
+				TSU_CFG_VAL_POL_MASK,reg);
+	TS_SIGNAL_PARAMS_CONFIG(signalCfg->tsError,
+				TSU_CFG_ERR_USED_MASK,
+				TSU_CFG_ERR_POL_MASK,reg);
+
+	if(signalCfg->tsDataEdge != TSU_SIGNAL_EDGE_KEEP_DEF)
+	{
+		if(signalCfg->tsDataEdge == TSU_SIGNAL_EDGE_FALL)
+			reg |= TSU_CFG_TX_EDGE_MASK;
+		else
+			reg &= ~TSU_CFG_TX_EDGE_MASK;
+	}
+
+	/* Setup serial mode related configurations.	*/
+	if(mvTsuCtrl.mode == TSU_MODE_SERIAL)
+	{
+		if(serialFlags & MV_TSU_SER_DATA_ORDER_MASK)
+		{
+			reg &= ~TSU_CFG_DATA_ORD_MASK;
+			if(serialFlags & MV_TSU_SER_DATA_ORDER_MSB)
+				reg |= TSU_CFG_DATA_ORD_MSB;
+			else if(serialFlags & MV_TSU_SER_DATA_ORDER_LSB)
+				reg |= TSU_CFG_DATA_ORD_LSB;
+		}
+
+		if(serialFlags & MV_TSU_SER_SYNC_ACT_LEN_MASK)
+		{
+			reg &= ~TSU_CFG_TS_SYNC_MASK;
+			if(serialFlags & MV_TSU_SER_SYNC_ACT_1_BIT)
+				reg |= TSU_CFG_TS_SYNC_1BIT;
+			else if(serialFlags & MV_TSU_SER_SYNC_ACT_8_BIT)
+				reg |= TSU_CFG_TS_SYNC_8BIT;
+		}
+
+		if(serialFlags & MV_TSU_SER_TX_CLK_MODE_MASK)
+		{
+			reg &= ~TSU_CFG_CLK_MODE_MASK;
+			if(serialFlags & MV_TSU_SER_TX_CLK_MODE_GAPPED)
+				reg |= TSU_CFG_CLK_MODE_GAPPED;
+			else if(serialFlags & MV_TSU_SER_TX_CLK_MODE_CONT)
+				reg |= TSU_CFG_CLK_MODE_CONT;
+		}
+	}
+
+	MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg);
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuPortSignalCfgGet
+*
+* DESCRIPTION:
+* 	Get port signals parameters.
+*
+* INPUT:
+*       port 		- The port to configure.
+* OUTPUT:
+*	signalCfg	- Signal configuration options.
+*	serialflags	- Serial signal configuration options (valid only if the
+*			  port is working in serial mode).
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Illegal port number.
+*	MV_BAD_PARAM	- Bad pointers.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortSignalCfgGet(MV_U8 port, MV_TSU_SIGNAL_CONFIG *signalCfg,
+				MV_U32* serialFlags)
+{
+	MV_U32	reg;
+
+	if(port >= MV_TSU_NUM_PORTS)
+		return MV_OUT_OF_RANGE;
+
+	if((signalCfg == NULL) ||
+	   ( (mvTsuCtrl.mode == TSU_MODE_SERIAL) && (serialFlags == NULL)))
+		return MV_BAD_PARAM;
+
+	reg = MV_REG_READ(MV_TSU_CONFIG_REG(port));
+
+	/* Setup signal related options.	*/
+	TS_SIGNAL_PARAMS_GET(signalCfg->tsSync,TSU_CFG_SYNC_USED_MASK,
+			     TSU_CFG_SYNC_POL_MASK,reg);
+	TS_SIGNAL_PARAMS_GET(signalCfg->tsValid,TSU_CFG_VAL_USED_MASK,
+			     TSU_CFG_VAL_POL_MASK,reg);
+	TS_SIGNAL_PARAMS_GET(signalCfg->tsError,TSU_CFG_ERR_USED_MASK,
+			     TSU_CFG_ERR_POL_MASK,reg);
+
+	if(reg & TSU_CFG_TX_EDGE_MASK)
+		signalCfg->tsDataEdge = TSU_SIGNAL_EDGE_FALL;
+	else
+		signalCfg->tsDataEdge = TSU_SIGNAL_EDGE_RISE;
+
+	/* Setup serial mode related configurations.	*/
+	if(mvTsuCtrl.mode == TSU_MODE_SERIAL)
+	{
+		*serialFlags = 0;
+
+		if((reg & TSU_CFG_DATA_ORD_MASK) == TSU_CFG_DATA_ORD_LSB)
+			*serialFlags |= MV_TSU_SER_DATA_ORDER_LSB;
+		else
+			*serialFlags |= MV_TSU_SER_DATA_ORDER_MSB;
+
+		if((reg & TSU_CFG_TS_SYNC_MASK) == TSU_CFG_TS_SYNC_1BIT)
+			*serialFlags |= MV_TSU_SER_SYNC_ACT_1_BIT;
+		else
+			*serialFlags |= MV_TSU_SER_SYNC_ACT_8_BIT;
+
+		if((reg & TSU_CFG_CLK_MODE_MASK) == MV_TSU_SER_TX_CLK_MODE_GAPPED)
+			*serialFlags |= TSU_CFG_CLK_MODE_GAPPED;
+		else
+			*serialFlags |= TSU_CFG_CLK_MODE_CONT;
+	}
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuStatusGet
+*
+* DESCRIPTION:
+* 	Get the TSU port status for a given port.
+*
+* INPUT:
+*	port	- The port number to configure.
+* OUTPUT:
+*	status	- Bitmask representing the TSU port status (a bitwise or
+*		between the MV_TSU_STATUS_* macros.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+MV_STATUS mvTsuStatusGet(MV_U8 port, MV_U32 *status)
+{
+	MV_U32	reg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+	{
+		return MV_OUT_OF_RANGE;
+	}
+
+	reg = MV_REG_READ(MV_TSU_STATUS_REG(port));
+	reg &= TSU_STATUS_MASK;
+
+	*status = 0;
+	if(reg & TSU_STATUS_IF_ERR)
+		*status |= MV_TSU_STATUS_TSIF_ERROR;
+	if(reg & TSU_STATUS_FIFO_OVFL_ERR)
+		*status |= MV_TSU_STATUS_OVFL_ERROR;
+	if(reg & TSU_STATUS_CONN_ERR)
+		*status |= MV_TSU_STATUS_CONN_ERROR;
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuBuffersInit
+*
+* DESCRIPTION:
+* 	Initialize the TSU unit buffers.
+*	This function is used to initialize both Rx or Tx buffers according to
+*	the port mode configured in mvTsuPortsInit().
+*
+* INPUT:
+*	port	- The port number to configure.
+*	buffInfo- TSU buffer information.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad buffer configuration options.
+*	MV_NOT_ALIGNED	- Bad data buffer alignemed.
+*
+*******************************************************************************/
+MV_STATUS mvTsuBuffersInit(MV_U8 port, MV_TSU_BUFF_INFO *buffInfo)
+{
+	MV_U32	reg;
+	MV_U32	descSize;
+	MV_U32	i;
+	MV_U8	*tsDataBuff;
+	MV_U32	*descEntry;
+	MV_U32	phyAddr;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+
+	if( ( (buffInfo->aggrMode != MV_TSU_AGGR_MODE_DISABLED) &&
+	      ( (buffInfo->aggrMode2TmstmpOff > 0xF ) ||
+		(buffInfo->aggrMode2TmstmpOff < 4 ) ||
+		(buffInfo->aggrNumPackets <= 1) ||
+		(buffInfo->numDoneQEntry < buffInfo->aggrNumPackets) ) ) ||
+	    (!MV_IS_POWER_OF_2(buffInfo->numTsDesc) ) ||
+	    (!MV_IS_POWER_OF_2(buffInfo->numDoneQEntry) ) ||
+	    (buffInfo->numTsDesc == 0) ||
+	    (buffInfo->numDoneQEntry == 0) ||
+	    (buffInfo->numDoneQEntry > MV_TSU_MAX_DONEQ_LEN) ||
+	    ( (mvTsuPortCtrl[port].portDir == TSU_PORT_INPUT) &&
+	      (buffInfo->numTsDesc > MV_TSU_MAX_IN_QUEUE_LEN) ) ||
+	    ( (mvTsuPortCtrl[port].portDir == TSU_PORT_OUTPUT) &&
+	      (buffInfo->numTsDesc > MV_TSU_MAX_OUT_QUEUE_LEN) ) )
+	{
+		return MV_BAD_PARAM;
+	}
+
+	/* Check buffer alignment.			*/
+	if( ( (buffInfo->aggrMode == MV_TSU_AGGR_MODE_2) &&
+	      (((buffInfo->tsDataBuffPhys + buffInfo->aggrMode2TmstmpOff) &
+		(TSU_DMA_ALIGN - 1)) != 0) ) ||
+	    ( (buffInfo->aggrMode == MV_TSU_AGGR_MODE_DISABLED) &&
+	      (buffInfo->tsDataBuffPhys & (TSU_DMA_ALIGN - 1)) != 0 ) )
+	{
+		return MV_NOT_ALIGNED;
+	}
+
+	/* Disable operation mode.			*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	/* Setup aggregation mode.			*/
+	reg = MV_REG_READ(MV_TSU_AGGREGATION_CTRL_REG(port));
+	reg &= ~TSU_AGGR_ENABLE_MASK;
+	if(buffInfo->aggrMode == MV_TSU_AGGR_MODE_DISABLED)
+	{
+		reg |= TSU_AGGR_DISABLE;
+		mvTsuPortCtrl[port].aggrNumPckts = 1;
+	}
+	else
+	{
+                reg |= TSU_AGGR_ENABLE;
+
+		reg &= ~TSU_AGGR_TMSTMP_OFF_MASK;
+		if(buffInfo->aggrMode == MV_TSU_AGGR_MODE_2)
+		{
+			reg |= (buffInfo->aggrMode2TmstmpOff <<
+				TSU_AGGR_TMSTMP_OFF_OFFS);
+			reg &= ~TSU_AGGR_TMSTMP_MODE_MASK;
+			reg |= TSU_AGGR_TMSTMP_TO_PCKT;
+		}
+
+		reg &= ~TSU_AGGR_PCKT_NUM_MASK;
+		reg |= (buffInfo->aggrNumPackets << TSU_AGGR_PCKT_NUM_OFFS);
+
+		MV_REG_WRITE(MV_TSU_AGGREGATION_CTRL_REG(port),reg);
+		mvTsuPortCtrl[port].aggrNumPckts = buffInfo->aggrNumPackets;
+	}
+
+	mvTsuPortCtrl[port].aggrMode = buffInfo->aggrMode;
+	if(mvTsuPortCtrl[port].portDir == TSU_PORT_INPUT) {
+		descSize = TSU_INPUT_DESC_ENTRY_SIZE;
+		mvTsuPortCtrl[port].queueDescSize = 4;
+	} else {
+		descSize = TSU_OUTPUT_DESC_ENTRY_SIZE(buffInfo->aggrMode);
+		mvTsuPortCtrl[port].queueDescSize = 8;
+	}
+
+	/* Initialize descriptor data.			*/
+	mvTsuPortCtrl[port].descVirtAddr = mvOsIoUncachedMalloc(
+		mvTsuCtrl.osHandle,descSize * buffInfo->numTsDesc,
+		&(mvTsuPortCtrl[port].descPhyAddr),
+		&(mvTsuPortCtrl[port].descMemHandle));
+
+	/* Initialize the descriptors list with buffer pointers.	*/
+	descEntry = (MV_U32*)mvTsuPortCtrl[port].descVirtAddr;
+	tsDataBuff = (MV_U8*)buffInfo->tsDataBuff;
+	phyAddr = buffInfo->tsDataBuffPhys;
+	for(i = 0; i < buffInfo->numTsDesc; i++)
+	{
+                TSU_SET_DESC_BUFF_PTR(descEntry,phyAddr);
+		descEntry += (descSize >> 2);
+		tsDataBuff += buffInfo->dataBlockSize;
+		phyAddr += buffInfo->dataBlockSize;
+	}
+
+	mvTsuPortCtrl[port].queueMask =
+		~(0xFFFFFFFF << mvLog2(buffInfo->numTsDesc * descSize));
+
+	if(mvTsuPortCtrl[port].portDir == TSU_PORT_INPUT)
+		mvTsuPortCtrl[port].cpuRollBit =
+			mvTsuPortCtrl[port].queueMask + 1;
+	else
+		mvTsuPortCtrl[port].cpuRollBit = 0;
+
+	/* Write the read / write pointers for data & status buffers.	*/
+
+	/* Desc start pointer.	*/
+	phyAddr = mvTsuPortCtrl[port].descPhyAddr;
+	MV_REG_WRITE(MV_TSU_DESC_QUEUE_BASE_REG(port),phyAddr);
+
+        /* Desc read pointer.	*/
+	MV_REG_WRITE(MV_TSU_DESC_QUEUE_READ_PTR_REG(port),
+		     0 << TSU_DESC_READ_PTR_OFFS);
+
+	/* Desc write pointer.	*/
+        MV_REG_WRITE(MV_TSU_DESC_QUEUE_WRITE_PTR_REG(port),
+		     mvTsuPortCtrl[port].cpuRollBit);
+
+	/* Done start pointer.	*/
+	phyAddr = buffInfo->tsDoneBuffPhys;
+	MV_REG_WRITE(MV_TSU_DONE_QUEUE_BASE_REG(port),phyAddr);
+
+	/* Done read pointer.	*/
+	MV_REG_WRITE(MV_TSU_DONE_QUEUE_READ_PTR_REG(port),
+		     0 << TSU_DONE_READ_PTR_OFFS);
+
+	/* Done write pointer.	*/
+	MV_REG_WRITE(MV_TSU_DONE_QUEUE_WRITE_PTR_REG(port),
+		     mvTsuPortCtrl[port].cpuRollBit);//0 << TSU_DONE_WRITE_PTR_OFFS);
+
+	/* Done & Data queues size.	*/
+	reg = MV_REG_READ(MV_TSU_DMA_PARAMS_REG(port));
+	reg &= ~(TSU_DMAP_DESC_Q_SIZE_MASK | TSU_DMAP_DONE_Q_SIZE_MASK);
+
+	i = mvLog2((buffInfo->numTsDesc * descSize) >> 2);
+	reg |= (i << TSU_DMAP_DESC_Q_SIZE_OFFS);
+
+	i = mvLog2((buffInfo->numDoneQEntry * TSU_DONE_STATUS_ENTRY_SIZE) >> 2);
+	reg |= (i << TSU_DMAP_DONE_Q_SIZE_OFFS);
+
+	MV_REG_WRITE(MV_TSU_DMA_PARAMS_REG(port),reg);
+
+	mvTsuPortCtrl[port].descSize = descSize;
+	mvTsuPortCtrl[port].numTsDesc = buffInfo->numTsDesc;
+	mvTsuPortCtrl[port].numDoneQEntry = buffInfo->numDoneQEntry;
+	mvTsuPortCtrl[port].tsDataBuff = buffInfo->tsDataBuff;
+	mvTsuPortCtrl[port].tsDoneBuff = buffInfo->tsDoneBuff;
+	mvTsuPortCtrl[port].dataBlockSize = buffInfo->dataBlockSize;
+	mvTsuPortCtrl[port].dataReadIdx = 0;
+	mvTsuPortCtrl[port].statReadIdx = 0;
+	mvTsuPortCtrl[port].enableTimer = MV_FALSE;
+
+	mvTsuPortEnable(port,MV_TRUE);
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuPortShutdown
+*
+* DESCRIPTION:
+* 	Shutdown the port, this will release any previously allocated port
+*	memory, and set the port to disable state.
+*
+* INPUT:
+*	port	- The port number to shutdown.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad buffer configuration options.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortShutdown(MV_U8 port)
+{
+	MV_TSU_PORT_CTRL *portCtrl;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+
+	/* Disable operation mode.	*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	/* Disable the port.		*/
+	mvTsuPortEnable(port,MV_FALSE);
+
+	/* Free descriptors buffer.	*/
+	portCtrl = &mvTsuPortCtrl[port];
+	mvOsIoUncachedFree(mvTsuCtrl.osHandle,
+			   portCtrl->descSize * portCtrl->numTsDesc,
+			   portCtrl->descPhyAddr,portCtrl->descVirtAddr,
+			   portCtrl->descMemHandle);
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuDmaWatermarkSet
+*
+* DESCRIPTION:
+*	Set the watermark for starting a DMA transfer from / to the TSU
+*	internal FIFO to the CPU memory.
+*
+* INPUT:
+*	port		- The port number to configure.
+*	watermark	- The watermark to configure (in DWORD units).
+*			For Rx: Number of data DWORDS in FIFO to start DMA.
+*			For Tx: Number of free DWORDS in FIFO to start DMA.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad watermark value..
+*
+*******************************************************************************/
+MV_STATUS mvTsuDmaWatermarkSet(MV_U8 port, MV_U32 watermark)
+{
+	MV_U32	reg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(watermark > TSU_DMAP_DATA_WTRMK_MAX)
+		return MV_BAD_PARAM;
+
+	/* Disable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	reg = MV_REG_READ(MV_TSU_DMA_PARAMS_REG(port));
+	reg &= ~TSU_DMAP_DATA_WTRMK_MASK;
+	reg |= (watermark << TSU_DMAP_DATA_WTRMK_OFFS);
+	MV_REG_WRITE(MV_TSU_DMA_PARAMS_REG(port),reg);
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuAggrMode1TmsOnPcktEn
+*
+* DESCRIPTION:
+*	Set the TSU unit to add the timestamp to the packet buffer when working
+*	in aggregation mode-1.
+*
+* INPUT:
+*	port	- The port number to configure.
+*	enable	- When True, enables the placement of timestamp data in the
+*		  packet buffer.
+*		  When False, the timestamp is placed in the Done-Queue.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+MV_STATUS mvTsuAggrMode1TmsOnPcktEn(MV_U8 port, MV_BOOL enable)
+{
+	MV_U32	reg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+
+	/* Disable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	reg = MV_REG_READ(MV_TSU_AGGREGATION_CTRL_REG(port));
+	reg &= ~TSU_AGGR_TMSTMP_MODE_MASK;
+	if(enable == MV_TRUE)
+		reg |= TSU_AGGR_TMSTMP_TO_PCKT;
+	else
+		reg |= TSU_AGGR_TMSTMP_TO_DONE_Q;
+	MV_REG_WRITE(MV_TSU_AGGREGATION_CTRL_REG(port),reg);
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+
+	return MV_OK;
+}
+
+
+/********************************/
+/* Rx related APIs		*/
+/********************************/
+
+
+/*******************************************************************************
+* mvTsuRxSyncDetectionSet
+*
+* DESCRIPTION:
+* 	Set TS synchronization parameters for Rx data.
+*
+* INPUT:
+*	port		- The port number to configure.
+*	syncDetect	- Number of TS sync matches to lock signal.
+*	syncLoss	- Number of TS sync losses to unlock signal.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad sync values configuration.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxSyncDetectionSet(MV_U8 port, MV_U8 syncDetect, MV_U8 syncLoss)
+{
+	MV_U32	reg;
+	MV_U8	maxVal;
+
+	if(port >= MV_TSU_NUM_PORTS)
+		return MV_OUT_OF_RANGE;
+
+	maxVal = TSU_SYNC_LOSS_CNT_MASK >> TSU_SYNC_LOSS_CNT_OFFS;
+	if((syncDetect > maxVal) || (syncLoss > maxVal))
+		return MV_BAD_PARAM;
+
+	/* Disable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	reg = MV_REG_READ(MV_TSU_SYNCBYTE_DETECT_REG(port));
+	reg &= ~(TSU_SYNC_LOSS_CNT_MASK | TSU_SYNC_DETECT_CNT_MASK);
+	reg |= ((syncDetect << TSU_SYNC_DETECT_CNT_OFFS) |
+		(syncLoss << TSU_SYNC_LOSS_CNT_OFFS));
+	MV_REG_WRITE(MV_TSU_SYNCBYTE_DETECT_REG(port),reg);
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuRxSyncDetectionGet
+*
+* DESCRIPTION:
+* 	Get TS synchronization parameters for Rx data.
+*
+* INPUT:
+*	port		- The port number.
+* OUTPUT:
+*	syncDetect	- Number of TS sync matches to lock signal.
+*	syncLoss	- Number of TS sync losses to unlock signal.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad pointers.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxSyncDetectionGet(MV_U8 port, MV_U8 *syncDetect, MV_U8 *syncLoss)
+{
+	MV_U32	reg;
+
+	if(port >= MV_TSU_NUM_PORTS)
+		return MV_OUT_OF_RANGE;
+
+	if((syncDetect == NULL) || (syncLoss == NULL))
+		return MV_BAD_PARAM;
+
+	reg = MV_REG_READ(MV_TSU_SYNCBYTE_DETECT_REG(port));
+
+	*syncDetect = (reg & TSU_SYNC_DETECT_CNT_MASK) >> TSU_SYNC_DETECT_CNT_OFFS;
+	*syncLoss = (reg & TSU_SYNC_LOSS_CNT_MASK) >> TSU_SYNC_LOSS_CNT_OFFS;
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuRxFullBuffCountGet
+*
+* DESCRIPTION:
+* 	Get number of Rx packets ready for CPU processing.
+*
+* INPUT:
+*	port		- TSU port number.
+* OUTPUT:
+*	numBlocks	- Number of data blocks ready for CPU processing
+*			 (already have data for processing).
+*	numBuffers	- Number of buffers ready for CPU processing (already
+*			have data for processing).
+*			In non-aggreagtion mode numBlocks == numBuffers.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NOT_SUPPORTED- If the port is not configured in input mode.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxFullBuffCountGet(MV_U8 port, MV_U32 *numBlocks,
+				  MV_U32 *numBuffers)
+{
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_INPUT)
+		return MV_NOT_SUPPORTED;
+	return mvTsuReadyBuffCountGet(port,numBlocks,numBuffers);
+}
+
+/*******************************************************************************
+* mvTsuRxNextBuffGet
+*
+* DESCRIPTION:
+* 	Get a pointer to the next available Rx data & status buffers from the Rx
+*	queue.
+*
+* INPUT:
+*	port		- TSU port number.
+*	dataBuff	- Pointer to return the address of the next data buffer.
+*	statBuff	- Pointer to return the address of the next status
+*			  buffer.
+* OUTPUT:
+*	buffsHandle	- A handle returned to the user to be used when freeing
+*			  the buffers in mvTsuRxBuffFree().
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad parameters.
+*	MV_NOT_SUPPORTED- Functionality not supported by the port configuration.
+*	MV_NO_MORE	- No Rx data is available for copy.
+* NOTE:
+*	When working in Aggregation mode, the buffer will point to the
+*	beggining of the aggregation buffer and not to a single packet inside
+*	the buffer.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxNextBuffGet(MV_U8 port,MV_U32 **dataBuff, MV_U32 **statBuff,
+			     MV_U32 *buffsHandle)
+{
+	MV_TSU_PORT_CTRL *portCtrl;
+	MV_U32	numBlocks;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_INPUT)
+		return MV_NOT_SUPPORTED;
+	if((dataBuff == NULL) || (statBuff == NULL) || (buffsHandle == NULL))
+		return MV_BAD_PARAM;
+
+	mvTsuReadyBuffCountGet(port,&numBlocks,NULL);
+	if(numBlocks <= 2)
+		return MV_NO_MORE;
+
+	portCtrl = &mvTsuPortCtrl[port];
+
+	/* Get read pointer.		*/
+	*dataBuff = (MV_U32*)(((MV_U32)portCtrl->tsDataBuff) +
+			      (portCtrl->dataBlockSize * portCtrl->dataReadIdx));
+        *statBuff =
+		(MV_U32*)(((MV_U32)portCtrl->tsDoneBuff) +
+			  (TSU_DONE_STATUS_ENTRY_SIZE * portCtrl->statReadIdx));
+	*buffsHandle = TSU_BUFF_HNDL(portCtrl->dataReadIdx,
+				     portCtrl->statReadIdx);
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuRxTimestampCntEn
+*
+* DESCRIPTION:
+* 	Enable / Disable the timestamp counter for Rx direction.
+*
+* INPUT:
+*	port		- TSU port number.
+*	enable		- MV_TRUE to enable the timestamp counter.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad parameters.
+* NOTE:
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxTimestampCntEn(MV_U8 port,MV_BOOL enable)
+{
+	MV_U32 reg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_INPUT)
+		return MV_NOT_SUPPORTED;
+
+	reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port));
+	reg &= ~TSU_TMS_CTRL_TIMER_MASK;
+
+	if(enable == MV_TRUE)
+		reg |= TSU_TMS_CTRL_TIMER_EN;
+	else
+		reg |= TSU_TMS_CTRL_TIMER_DIS;
+
+	MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuRxBuffFree
+*
+* DESCRIPTION:
+* 	Mark a given set of buffers to be free (ready for new data Rx).
+*
+* INPUT:
+*	port		- TSU port number.
+*	dataBuff	- Pointer to the start of data buffer to return.
+*	statBuff	- Pointer to the start of status buffer to return.
+*	buffsHandle	- The buffers handle as returned by mvTsuRxNextBuffGet()
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NO_MORE	- No Rx data is available for copy.
+*	MV_BAD_PARAM	- Bad parameters.
+*	MV_BAD_STATE	- Bad buffer free order, attempting to free a buffer
+*			  before all previous buffers where freed.
+* NOTE:
+*	When working in Aggregation mode, the buffer will point to the
+*	beggining of the aggregation buffer and not to a single packet inside
+*	the buffer.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxBuffFree(MV_U8 port,MV_U32 *dataBuff, MV_U32 *statBuff,
+			  MV_U32 buffsHandle)
+{
+	MV_TSU_PORT_CTRL *portCtrl;
+	MV_U32 ptr;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_INPUT)
+		return MV_NOT_SUPPORTED;
+	if((dataBuff == NULL) || (statBuff == NULL))
+		return MV_BAD_PARAM;
+
+	portCtrl = &mvTsuPortCtrl[port];
+
+	if(buffsHandle !=
+	   TSU_BUFF_HNDL(portCtrl->dataReadIdx,portCtrl->statReadIdx)){
+		mvOsPrintf("Bad state..........................\n");
+		return MV_BAD_STATE;
+	}
+
+	portCtrl->dataReadIdx =
+		(portCtrl->dataReadIdx + 1) & (portCtrl->numTsDesc - 1);
+	if(portCtrl->dataReadIdx == 0)
+		portCtrl->cpuRollBit ^= (portCtrl->queueMask + 1);
+
+	portCtrl->statReadIdx =
+		((portCtrl->statReadIdx + portCtrl->aggrNumPckts) &
+		 (portCtrl->numDoneQEntry - 1));
+
+	/* Update the desc queue write pointer.	*/
+	ptr = (portCtrl->dataReadIdx << 2) | portCtrl->cpuRollBit;
+
+	MV_REG_WRITE(MV_TSU_DESC_QUEUE_WRITE_PTR_REG(port),ptr);
+
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuRxFlushErrorPackets
+*
+* DESCRIPTION:
+* 	Enable / Disable flushing of received erroneous packets.
+*
+* INPUT:
+*	port		- TSU port number.
+*	enableFlush	- MV_TRUE to flush recieved erroneous packets.
+*			  MV_FALSE to copy erroneous packets to Rx buffers.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxFlushErrorPackets(MV_U8 port, MV_BOOL enableFlush)
+{
+	MV_U32	reg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+
+	/* Disable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	reg = MV_REG_READ(MV_TSU_AGGREGATION_CTRL_REG(port));
+	reg &= ~TSU_AGGR_FLUSH_ERR_MASK;
+	if(enableFlush == MV_TRUE)
+		reg |= TSU_AGGR_FLUSH_ERR_ENABLE;
+	else
+		reg |= TSU_AGGR_FLUSH_ERR_DISABLE;
+	MV_REG_WRITE(MV_TSU_AGGREGATION_CTRL_REG(port),reg);
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+	return MV_OK;
+}
+
+
+/********************************/
+/* Tx related APIs		*/
+/********************************/
+
+/*******************************************************************************
+* mvTsuTxClockFreqSet
+*
+* DESCRIPTION:
+* 	Configure the transmit clock frequency and parameters.
+*
+* INPUT:
+*	port		- TSU port number.
+*	freq		- The frequency to configure in Hz.
+*	autoAdjust	- Whether to adjust the Tx frequency according to the
+*			next packet timestamp.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_VALUE	- Bad Tx frequency value.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxClockFreqSet(MV_U8 port, MV_U32 freq, MV_BOOL autoAdjust)
+{
+	MV_U32	reg;
+	MV_U32	clockVal;
+	MV_U32	divider;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	clockVal = mvTsuCoreClock2Val[mvTsuCtrl.coreClock];
+	if(freq > clockVal)
+		return MV_BAD_VALUE;
+
+	/* Disable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	/* Find the correct divider that satisfies: freq <= (core_clock / div)*/
+	divider = TSU_NUM_CLOCK_DIVIDERS - 1;
+	while(divider != 0)
+	{
+		if(freq <= (clockVal >> divider))
+			break;
+		divider--;
+	}
+
+	/* Now, bestDev holds the best divider value.			*/
+	reg = MV_REG_READ(MV_TSU_CONFIG_REG(port));
+	reg &= ~(TSU_CFG_OUT_CLOCK_MASK | TSU_CFG_FREQ_MODE_MASK);
+	switch(divider)
+	{
+	case(0):	/* 1 */
+		reg |= (1 << TSU_CFG_FREQ_MODE_OFFS);
+		/* Fall through */
+	case(3):	/* 8 */
+        	reg |= TSU_CFG_OUT_CLOCK_1_8;
+		break;
+	case(1):	/* 2 */
+		reg |= (1 << TSU_CFG_FREQ_MODE_OFFS);
+		/* Fall through */
+	case(4):	/* 16 */
+        	reg |= TSU_CFG_OUT_CLOCK_2_16;
+		break;
+	case(2):	/* 4 */
+		reg |= (1 << TSU_CFG_FREQ_MODE_OFFS);
+		/* Fall through */
+	case(5):	/* 32 */
+        	reg |= TSU_CFG_OUT_CLOCK_4_32;
+		break;
+	default:
+		break;
+	}
+        MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg);
+
+	/* Setup auto adjust.				*/
+	reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port));
+	reg &= ~TSU_TMS_CTRL_AUTO_ADJ_MASK;
+	if(autoAdjust == MV_TRUE)
+		reg |= TSU_TMS_CTRL_AUTO_ADJ_ON;
+	else
+		reg |= TSU_TMS_CTRL_AUTO_ADJ_OFF;
+	MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg);
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuTxFreeBuffCountGet
+*
+* DESCRIPTION:
+* 	Get the number of free packets ready to be transmitted in the TX
+*	descriptor list.
+*
+* INPUT:
+*	port		- TSU port number.
+* OUTPUT:
+*	numBlocks	- Number of data blocks ready for CPU processing
+*			 (does not have data for transmit).
+*	numBuffers	- Number of buffers ready for CPU processing (does not
+*			  have data for transmit).
+*			In non-aggreagtion mode numBlocks == numBuffers.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NOT_SUPPORTED- If the port is not configured in output mode.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxFreeBuffCountGet(MV_U8 port, MV_U32 *numBlocks,
+				  MV_U32 *numBuffers)
+{
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT)
+		return MV_NOT_SUPPORTED;
+	return mvTsuReadyBuffCountGet(port,numBlocks,numBuffers);
+}
+
+
+/*******************************************************************************
+* mvTsuRxNextBuffGet
+*
+* DESCRIPTION:
+* 	Get a pointer to the next available Tx data & status buffers from the Tx
+*	queue.
+*
+* INPUT:
+*	port		- TSU port number.
+*	dataBuff	- Pointer to return the address of the next data buffer.
+*	statBuff	- Pointer to return the address of the next status
+*			  buffer.
+* OUTPUT:
+*	buffsHandle	- A handle returned to the user to be used when freeing
+*			  the buffers in mvTsuTxBuffPut().
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad parameters.
+*	MV_NOT_SUPPORTED- Functionality not supported by the port configuration.
+*	MV_NO_MORE	- No free Tx data is available.
+* NOTE:
+*	When working in Aggregation mode, the buffer will point to the
+*	beggining of the aggregation buffer and not to a single packet inside
+*	the buffer.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxNextBuffGet(MV_U8 port,MV_U32 **dataBuff,MV_U32 *buffsHandle)
+{
+	MV_TSU_PORT_CTRL *portCtrl;
+	MV_U32	numBlocks;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT)
+		return MV_NOT_SUPPORTED;
+	if((dataBuff == NULL) || (buffsHandle == NULL))
+		return MV_BAD_PARAM;
+
+	mvTsuTxFreeBuffCountGet(port,&numBlocks,NULL);
+	if(numBlocks <= 2)
+		return MV_NO_MORE;
+
+//	if(numBlocks == 0)
+//		return MV_NO_MORE;
+
+	portCtrl = &mvTsuPortCtrl[port];
+
+	if(dataBuff != NULL) {
+		*dataBuff = (MV_U32*)(((MV_U32)portCtrl->tsDataBuff) +
+				      (portCtrl->dataBlockSize * portCtrl->dataReadIdx));
+		*buffsHandle = TSU_BUFF_HNDL(portCtrl->dataReadIdx,portCtrl->statReadIdx);
+	}
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuTxBuffPut
+*
+* DESCRIPTION:
+* 	Mark a given set of buffers to be ready for transmission.
+*
+* INPUT:
+*	port		- TSU port number.
+*	dataBuff	- Pointer to the start of data buffer to put.
+*	tmsValue	- The timestamp to associate with the buffer.
+*		 	  This parameter is applicable only when working in
+*			  non-aggregation mode.
+*	tsErr		- Indicates if the TS packet should be sent as an
+*			  erroneous packet.
+*			  This parameter is applicable only when working in
+*			  non-aggregation mode.
+*	buffsHandle	- The buffer handle as returned by mvTsuTxNextBuffGet()
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad function parameters.
+* NOTE:
+*	When working in Aggregation mode, the buffer will point to the
+*	beggining of the aggregation buffer and not to a single packet inside
+*	the buffer.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxBuffPut(MV_U8 port, MV_U32 *dataBuff, MV_U32 tmsValue,
+			 MV_BOOL tsErr, MV_U32 buffsHandle)
+{
+	MV_TSU_PORT_CTRL *portCtrl;
+	MV_U32 *descEntry;
+	MV_U32 ptr;
+	MV_U32 reg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT)
+		return MV_NOT_SUPPORTED;
+	if(dataBuff == NULL)
+		return MV_BAD_PARAM;
+
+	portCtrl = &mvTsuPortCtrl[port];
+	if(TSU_BUFF_HNDL_2_DATA_IDX(buffsHandle) != portCtrl->dataReadIdx)
+		return MV_BAD_STATE;
+
+	if(portCtrl->aggrMode == MV_TSU_AGGR_MODE_DISABLED) {
+		/* Write the timestamp value.	*/
+		descEntry = (MV_U32*)(((MV_U32)portCtrl->descVirtAddr) +
+				      (portCtrl->dataReadIdx << 3));
+		TSU_SET_OUT_DESC_TMSTMP(descEntry,tmsValue,tsErr);
+	}
+
+	portCtrl->dataReadIdx =
+		(portCtrl->dataReadIdx + 1) & (portCtrl->numTsDesc - 1);
+	if(portCtrl->dataReadIdx == 0)
+		portCtrl->cpuRollBit ^= (portCtrl->queueMask + 1);
+
+	/* Update the desc queue write pointer.	*/
+	ptr = (portCtrl->dataReadIdx << 3) | portCtrl->cpuRollBit;
+	MV_REG_WRITE(MV_TSU_DESC_QUEUE_WRITE_PTR_REG(port),ptr);
+
+	if(portCtrl->enableTimer) {
+		/* Enable the timestamp counter.	*/
+		reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port));
+		reg &= ~TSU_TMS_CTRL_TIMER_MASK;
+		reg |= TSU_TMS_CTRL_TIMER_EN;
+		MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg);
+		portCtrl->enableTimer = MV_FALSE;
+	}
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuTxStatusGet
+*
+* DESCRIPTION:
+* 	Get the next TX done buffer from the TX done queue.
+*
+* INPUT:
+*	port		- TSU port number.
+*	doneBuff	- Pointer to return the address of the next done buffer.
+*	buffsHandle	- The buffer handle as returned by mvTsuTxNextBuffGet()
+* OUTPUT:
+*	numBuffs	- Number of returned buffers.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NO_MORE	- No free Tx buffers are avilable.
+* NOTE:
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxStatusGet(MV_U8 port, MV_U32 **doneBuff, MV_U32 buffsHandle)
+{
+	MV_TSU_PORT_CTRL *portCtrl;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT)
+		return MV_NOT_SUPPORTED;
+	if(doneBuff == NULL)
+		return MV_BAD_PARAM;
+
+	portCtrl = &mvTsuPortCtrl[port];
+	if(TSU_BUFF_HNDL_2_STAT_IDX(buffsHandle) != portCtrl->statReadIdx)
+		return MV_BAD_STATE;
+
+	*doneBuff = (MV_U32*)(portCtrl->tsDoneBuff + portCtrl->statReadIdx);
+
+	portCtrl->statReadIdx =
+		((portCtrl->statReadIdx + portCtrl->aggrNumPckts)&
+		 (portCtrl->numDoneQEntry - 1));
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuTxInitTimeStampSet
+*
+* DESCRIPTION:
+* 	Set the initial timestamp value for TX operations.
+*	This function must be called before each transmit session.
+*
+* INPUT:
+*	port		- TSU port number.
+*	enableTmstmp	- Enable the timestamp mechanism for packet transmit.
+*			  When false, the TSU will transmit packets back-to-back
+*	initTimestamp   - (Valid only if enableTs == MV_TRUE)
+*			  The initial timestamp to set.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad timestamp value.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxInitTimeStampSet(MV_U8 port, MV_BOOL enableTmstmp,
+				  MV_U32 initTimestamp)
+{
+	MV_U32	reg;
+	MV_U32	tsReg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT)
+		return MV_NOT_SUPPORTED;
+
+	/* Disable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port));
+	if(enableTmstmp == MV_TRUE)
+	{
+		/* Setup timestamp initial value.		*/
+		tsReg = MV_REG_READ(MV_TSU_TIMESTAMP_REG(port));
+		tsReg &= ~TSU_TMSTMP_TIMESTAMP_MASK;
+		tsReg |= (initTimestamp &
+			  (TSU_TMSTMP_TIMESTAMP_MASK >> TSU_TMSTMP_TIMESTAMP_OFFS));
+		MV_REG_WRITE(MV_TSU_TIMESTAMP_REG(port),tsReg);
+
+		/* Trigger the TSU to read the timestamp.	*/
+		reg |= (1 << TSU_TMS_CTRL_READ_TIMER_OFFS);
+	}
+
+	/* Disable the timestamp counter (Will be enabled on 	*/
+	/* the first packet Tx */
+	reg &= ~TSU_TMS_CTRL_TIMER_MASK;
+	reg |= TSU_TMS_CTRL_TIMER_DIS;
+	MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg);
+	mvTsuPortCtrl[port].enableTimer = enableTmstmp;
+
+	/* Enable operation mode.				*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuTxDone
+*
+* DESCRIPTION:
+* 	Inform the TS unit that the current transmission session is over.
+*	This will stop the internal timestamp counters held by the unit.
+*
+* INPUT:
+*	port		- TSU port number.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxDone(MV_U8 port)
+{
+	MV_U32	reg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+	if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT)
+		return MV_NOT_SUPPORTED;
+
+	/* Disable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_FALSE);
+
+	reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port));
+
+	/* Disable the timestamp counter.	*/
+	reg &= ~TSU_TMS_CTRL_TIMER_MASK;
+	reg |= TSU_TMS_CTRL_TIMER_DIS;
+	MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg);
+
+	/* Enable operation mode.		*/
+	mvTsuOperationModeSet(port,MV_TRUE);
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuOperationModeSet
+*
+* DESCRIPTION:
+* 	Set the given TS port into operaion mode.
+*
+* INPUT:
+*	port	- TSU port number.
+*	enable	- MV_TRUE: enable operation mode.
+*		  MV_FALSE: disable operation mode.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+inline static MV_STATUS mvTsuOperationModeSet(MV_U8 port, MV_BOOL enable)
+{
+	MV_U32	reg;
+
+	reg = MV_REG_READ(MV_TSU_CONFIG_REG(port));
+	reg &= ~TSU_CFG_OPER_MASK;
+	if(enable)
+		reg |= TSU_CFG_OPER_ENABLE;
+	else
+		reg |= TSU_CFG_OPER_DISABLE;
+	MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg);
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuReadyBuffCountGet
+*
+* DESCRIPTION:
+* 	Get number of packets ready for CPU processing.
+*	In Rx direction, this is the number of packets ready to be rpocessed by
+*	CPU. For Tx direction, this is the number of free buffers ready for data
+*	transmission.
+*
+* INPUT:
+*	port		- TSU port number.
+* OUTPUT:
+*	numBlocks	- Number of data blocks ready for CPU processing
+*			 (already have data for processing).
+*	numBuffers	- Number of buffers ready for CPU processing (already
+*			have data for processing).
+*			In non-aggreagtion mode numBlocks == numBuffers.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+static MV_STATUS mvTsuReadyBuffCountGet(MV_U8 port, MV_U32 *numBlocks,
+					MV_U32 *numBuffers)
+{
+	MV_U32 cpuPtr;
+	MV_U32 tsuPtr;
+	MV_U32 result = 0;
+	MV_U32 tsuRollBit;
+	MV_TSU_PORT_CTRL *portCtrl = &mvTsuPortCtrl[port];
+
+	/* Get CPU pointer.		*/
+	cpuPtr = portCtrl->dataReadIdx;
+
+	/* Get TSU pointer.		*/
+	tsuPtr = MV_REG_READ(MV_TSU_DESC_QUEUE_READ_PTR_REG(port));
+
+	tsuRollBit = tsuPtr & (portCtrl->queueMask + 1);
+	tsuPtr &= portCtrl->queueMask;
+	tsuPtr /= portCtrl->queueDescSize;
+
+	if(tsuPtr > cpuPtr) {
+		result = tsuPtr - cpuPtr;
+	} else if(tsuPtr < cpuPtr) {
+		result = tsuPtr + portCtrl->numTsDesc - cpuPtr;
+	} else if( (tsuPtr == cpuPtr) && (portCtrl->cpuRollBit == tsuRollBit) ) {
+		result = portCtrl->numTsDesc;
+	}
+
+	if(numBuffers)
+		*numBuffers = result * portCtrl->aggrNumPckts;
+	if(numBlocks)
+		*numBlocks = result;
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuPortEnable
+*
+* DESCRIPTION:
+* 	Enable port for receiving & transmitting data after it has been
+*	configured.
+*
+* INPUT:
+*	port	- The port number to configure.
+*	enable	- MV_TRUE to enable port.
+*		  MV_FALSE to disable it.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+static MV_STATUS mvTsuPortEnable(MV_U8 port,MV_BOOL enable)
+{
+	MV_U32	reg;
+
+	if(port >= mvTsuCtrl.numActPorts)
+		return MV_OUT_OF_RANGE;
+
+	if(enable == MV_TRUE)
+		reg = 0xFFFFFFFF;
+	else
+		reg = 0x04040404;
+
+	reg = MV_REG_WRITE(MV_TSU_ENABLE_ACCESS_REG(port),reg);
+	return MV_OK;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/ts/mvTsu.h b/arch/arm/plat-feroceon/mv_hal/ts/mvTsu.h
new file mode 100755
index 0000000..87320ed
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ts/mvTsu.h
@@ -0,0 +1,896 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INC_MV_TSU_H__
+#define __INC_MV_TSU_H__
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysTsConfig.h"
+
+/********************************/
+/* General enums and structures */
+/********************************/
+
+#define MV_TSU_NUM_PORTS			(2)
+
+#define MV_TSU_STATUS_CONN_ERROR		(0x1)
+#define MV_TSU_STATUS_OVFL_ERROR		(0x2)
+#define MV_TSU_STATUS_TSIF_ERROR		(0x4)
+
+#define TSU_DONE_STATUS_ENTRY_SIZE		(4)
+#define TSU_INPUT_DESC_ENTRY_SIZE		(4)
+#define TSU_OUTPUT_DESC_ENTRY_SIZE(agrMode)	((agrMode == MV_TSU_AGGR_MODE_DISABLED) ? (8) : (4))
+#define TSU_MODE1_OUT_TMS_SIZE			(8)
+#define MV_TSU_MAX_IN_QUEUE_LEN			(1024)
+#define MV_TSU_MAX_OUT_QUEUE_LEN		(512)
+#define MV_TSU_MAX_DONEQ_LEN			(1024)
+#define TSU_DMA_ALIGN				(32)
+
+#define MV_TSU_TX_CLOCK_EXTERNAL		(0xFFFFFFFF)
+
+typedef enum
+{
+	TSU_CORE_CLK_83_MHZ = 0,
+	TSU_CORE_CLK_71_MHZ,
+	TSU_CORE_CLK_91_MHZ,
+	TSU_CORE_CLK_100_MHZ
+}MV_TSU_CORE_CLOCK;
+
+typedef enum
+{
+	TSU_MODE_SERIAL,
+	TSU_MODE_PARALLEL
+}MV_TSU_PORTS_MODE;
+
+typedef enum
+{
+	TSU_SIGNAL_KEEP_DEF,		/* Keep default.	*/
+	TSU_SIGNAL_DIS,
+	TSU_SIGNAL_EN_ACT_LOW,
+	TSU_SIGNAL_EN_ACT_HIGH
+}MV_TSU_SIGNAL_MODE;
+
+
+typedef enum
+{
+	TSU_SIGNAL_EDGE_KEEP_DEF,	/* Keep default.	*/
+	TSU_SIGNAL_EDGE_FALL,
+	TSU_SIGNAL_EDGE_RISE
+}MV_TSU_SIGNAL_EDGE;
+
+
+typedef enum
+{
+	TSU_PORT_INPUT,
+	TSU_PORT_OUTPUT
+}MV_TSU_PORT_DIRECTION;
+
+
+typedef struct
+{
+	MV_TSU_SIGNAL_MODE	tsSync;
+	MV_TSU_SIGNAL_MODE	tsValid;
+	MV_TSU_SIGNAL_MODE	tsError;
+	MV_TSU_SIGNAL_EDGE	tsDataEdge;
+}MV_TSU_SIGNAL_CONFIG;
+
+
+/* Serial data bits order, only one option can be selected.	*/
+#define MV_TSU_SER_DATA_ORDER_MSB	(0x0001)
+#define MV_TSU_SER_DATA_ORDER_LSB	(0x0002)
+#define MV_TSU_SER_DATA_ORDER_MASK				\
+	(MV_TSU_SER_DATA_ORDER_MSB | MV_TSU_SER_DATA_ORDER_LSB)
+
+
+/* Serial sync signal active length in bits, only one option	*/
+/* can be selected.						*/
+#define MV_TSU_SER_SYNC_ACT_1_BIT	(0x0004)
+#define MV_TSU_SER_SYNC_ACT_8_BIT	(0x0008)
+#define MV_TSU_SER_SYNC_ACT_LEN_MASK				\
+		(MV_TSU_SER_SYNC_ACT_1_BIT | MV_TSU_SER_SYNC_ACT_8_BIT)
+
+/* Serial Tx signal mode, continuous or gapped, only one option	*/
+/* can be selected.						*/
+#define MV_TSU_SER_TX_CLK_MODE_CONT 	(0x0010)
+#define MV_TSU_SER_TX_CLK_MODE_GAPPED	(0x0020)
+#define MV_TSU_SER_TX_CLK_MODE_MASK			\
+	(MV_TSU_SER_TX_CLK_MODE_CONT | MV_TSU_SER_TX_CLK_MODE_GAPPED)
+
+
+typedef struct
+{
+	MV_TSU_PORT_DIRECTION	portDir;
+	MV_U16			pktSize;	/* 188 to 256 		   */
+}MV_TSU_PORT_CONFIG;
+
+
+#define MV_TSU_AGGR_MODE_DISABLED	(1)
+#define MV_TSU_AGGR_MODE_1		(2)
+#define MV_TSU_AGGR_MODE_2		(3)
+
+/*
+ * MV_TSU_BUFF_INFO:
+ *
+ * aggrMode:		Aggregation mode MV_TSU_AGGR_MODE_X
+ * aggrMode2TmstmpOff:	Timestamp offset in case of aggr mode 2.
+ * aggrNumPackets:	Number of packets in each aggregation.
+ * numTsDesc:		Number of descriptors (Power of 2).
+ * numDoneQEntry:	Number of done queue entries (Power of 2).
+ * tsDataBuff:		Pointer to the data buffers list, the user must ensure 
+ * 			DMA coherency for these buffers. The content of these
+ *			buffers is never accessed by the HAL.
+ * tsDoneBuff:		Pointer to the data status list, the user must ensure 
+ * 			DMA coherency for these buffers. The content of these
+ *			buffers is never accessed by the HAL.
+ * dataBlockSize:	the size of a single data block, this can be larger than
+ *			the amount of memory needed to hold TS packets in order
+ *			to insure a certain alignment of the buffers.
+ *
+ * Guidelines for calculating the data & status buffers length:
+ *
+ *  	data-buff-len = dataBlockSize * numTsDesc
+ *	In normal mode:
+ *		dataBlockSize = <packet-size> + alignment_space
+ *		done-buff-len= numDoneQEntry * TSU_DONE_STATUS_ENTRY_SIZE
+ *
+ *	In aggregation mode 1:
+ *		dataBlockSize = <packet-size> * aggrNumPackets + alignment_space
+ *		done-buff-len= numDoneQEntry * TSU_DONE_STATUS_ENTRY_SIZE
+ *
+ *	In aggregation mode 2: 
+ *		dataBlockSize = ((<packet-size> + aggrMode2TmstmpOff)* 
+ *			aggrNumPackets) + alignment_space
+ *		done-buff-len= numDoneQEntry * TSU_DONE_STATUS_ENTRY_SIZE
+ */
+typedef struct
+{
+	MV_U8		aggrMode;
+	MV_U8		aggrMode2TmstmpOff;
+	MV_U8		aggrNumPackets;
+
+	MV_U32		numTsDesc;
+	MV_U32		numDoneQEntry;
+	MV_U32		*tsDataBuff;
+	MV_U32		tsDataBuffPhys;
+	MV_U32		*tsDoneBuff;
+	MV_U32		tsDoneBuffPhys;
+	MV_U32		dataBlockSize;
+}MV_TSU_BUFF_INFO;
+
+
+/********************************/
+/* Macros 			*/
+/********************************/
+#define MV_TSU_STATUS_ENTRY_TMS_GET(stat)	(MV_U32)(stat & 0xFFFFFFF)
+
+
+/********************************/
+/* Functions API 		*/
+/********************************/
+
+/*******************************************************************************
+* mvTsuHalInit
+*
+* DESCRIPTION:
+* 	Initialize the TSU unit, and get unit out of reset.
+*
+* INPUT:
+*       coreClock	- The core clock at which the TSU should operate.
+*       mode		- The mode on configure the unit into (serial/parallel).
+* 	osHandle	- Memory handle used for memory allocations.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK	- on success,
+*
+*******************************************************************************/
+MV_STATUS mvTsuHalInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode,
+		       void *osHandle);
+
+
+/*******************************************************************************
+* mvTsuShutdown
+*
+* DESCRIPTION:
+* 	Shutdown the TS unit, and put into reset state.
+*
+* INPUT:
+*       None.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK	- on success,
+*
+*******************************************************************************/
+MV_STATUS mvTsuShutdown(void);
+
+
+/*******************************************************************************
+* mvTsuPortReset
+*
+* DESCRIPTION:
+* 	Perform a SW reset on a given port.
+*
+* INPUT:
+*	port	- The port number to reset.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_BAD_VALUE	- Bad port configuration option.
+*	MV_BAD_SIZE	- Illegal number of ports.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortReset(MV_U8 port);
+
+
+/*******************************************************************************
+* mvTsuPortInit
+*
+* DESCRIPTION:
+* 	Initialize the TSU ports.
+*
+* INPUT:
+*	port	- The port number to configure.
+*	portCfg	- Port configurations parameters.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_BAD_VALUE	- Bad port configuration option.
+*	MV_BAD_SIZE	- Illegal number of ports.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortInit(MV_U8 port, MV_TSU_PORT_CONFIG *portCfg);
+
+
+/*******************************************************************************
+* mvTsuPortSignalCfgSet
+*
+* DESCRIPTION:
+* 	Configure port signals parameters.
+*
+* INPUT:
+*       port 		- The port to configure.
+*	signalCfg	- Signal configuration options.
+*	serialflags	- Serial signal configuration options (valid only if the 
+*			  port is working in serial mode).
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_BAD_VALUE	- Bad port configuration option.
+*	MV_BAD_SIZE	- Illegal number of ports.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortSignalCfgSet(MV_U8 port, MV_TSU_SIGNAL_CONFIG *signalCfg,
+				MV_U32 serialFlags);
+
+
+/*******************************************************************************
+* mvTsuPortSignalCfgGet
+*
+* DESCRIPTION:
+* 	Get port signals parameters.
+*
+* INPUT:
+*       port 		- The port to configure.
+* OUTPUT:
+*	signalCfg	- Signal configuration options.
+*	serialflags	- Serial signal configuration options (valid only if the 
+*			  port is working in serial mode).
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Illegal port number.
+*	MV_BAD_PARAM	- Bad pointers.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortSignalCfgGet(MV_U8 port, MV_TSU_SIGNAL_CONFIG *signalCfg,
+				MV_U32* serialFlags);
+
+
+/*******************************************************************************
+* mvTsuStatusGet
+*
+* DESCRIPTION:
+* 	Get the TSU port status for a given port.
+*
+* INPUT:
+*	port	- The port number to configure.
+* OUTPUT:
+*	status	- Bitmask representing the TSU port status (a bitwise or
+*		between the MV_TSU_STATUS_* macros.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+MV_STATUS mvTsuStatusGet(MV_U8 port, MV_U32 *status);
+
+
+/*******************************************************************************
+* mvTsuBuffersInit
+*
+* DESCRIPTION:
+* 	Initialize the TSU unit buffers.
+*	This function is used to initialize both Rx or Tx buffers according to
+*	the port mode configured in mvTsuPortsInit().
+*
+* INPUT:
+*	port	- The port number to configure.
+*	buffInfo- TSU buffer information.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad buffer configuration options.
+*	MV_NOT_ALIGNED	- Bad data buffer alignemed.
+*
+*******************************************************************************/
+MV_STATUS mvTsuBuffersInit(MV_U8 port, MV_TSU_BUFF_INFO *buffInfo);
+
+
+/*******************************************************************************
+* mvTsuPortShutdown
+*
+* DESCRIPTION:
+* 	Shutdown the port, this will release any previously allocated port 
+*	memory, and set the port to disable state.
+*
+* INPUT:
+*	port	- The port number to shutdown.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad buffer configuration options.
+*
+*******************************************************************************/
+MV_STATUS mvTsuPortShutdown(MV_U8 port);
+
+
+/*******************************************************************************
+* mvTsuDmaWatermarkSet
+*
+* DESCRIPTION:
+*	Set the watermark for starting a DMA transfer from / to the TSU 
+*	internal FIFO to the CPU memory.
+*
+* INPUT:
+*	port		- The port number to configure.
+*	watermark	- The watermark to configure (in DWORD units).
+*			For Rx: Number of data DWORDS in FIFO to start DMA.
+*			For Tx: Number of free DWORDS in FIFO to start DMA.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad watermark value..
+*
+*******************************************************************************/
+MV_STATUS mvTsuDmaWatermarkSet(MV_U8 port, MV_U32 watermark);
+
+
+/*******************************************************************************
+* mvTsuAggrMode1TmsOnPcktEn
+*
+* DESCRIPTION:
+*	Set the TSU unit to add the timestamp to the packet buffer when working
+*	in aggregation mode-1.
+*
+* INPUT:
+*	port	- The port number to configure.
+*	enable	- When True, enables the placement of timestamp data in the 
+*		  packet buffer.
+*		  When False, the timestamp is placed in the Done-Queue.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+MV_STATUS mvTsuAggrMode1TmsOnPcktEn(MV_U8 port, MV_BOOL enable);
+
+
+/********************************/
+/* Rx related APIs		*/
+/********************************/
+
+
+/*******************************************************************************
+* mvTsuRxSyncDetectionSet
+*
+* DESCRIPTION:
+* 	Set TS synchronization parameters for Rx data.
+*
+* INPUT:
+*	port		- The port number to configure.
+*	syncDetect	- Number of TS sync matches to lock signal.
+*	syncLoss	- Number of TS sync losses to unlock signal.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad sync values configuration.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxSyncDetectionSet(MV_U8 port, MV_U8 syncDetect, MV_U8 syncLoss);
+
+
+/*******************************************************************************
+* mvTsuRxSyncDetectionGet
+*
+* DESCRIPTION:
+* 	Get TS synchronization parameters for Rx data.
+*
+* INPUT:
+*	port		- The port number.
+* OUTPUT:
+*	syncDetect	- Number of TS sync matches to lock signal.
+*	syncLoss	- Number of TS sync losses to unlock signal.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad pointers.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxSyncDetectionGet(MV_U8 port, MV_U8 *syncDetect, MV_U8 *syncLoss);
+
+
+/*******************************************************************************
+* mvTsuRxFullBuffCountGet
+*
+* DESCRIPTION:
+* 	Get number of Rx packets ready for CPU processing.
+*
+* INPUT:
+*	port		- TSU port number.
+* OUTPUT:
+*	numBlocks	- Number of data blocks ready for CPU processing 
+*			 (already have data for processing).
+*	numBuffers	- Number of buffers ready for CPU processing (already
+*			have data for processing).
+*			In non-aggreagtion mode numBlocks == numBuffers.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NOT_SUPPORTED- If the port is not configured in input mode.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxFullBuffCountGet(MV_U8 port, MV_U32 *numBlocks,
+				  MV_U32 *numBuffers);
+
+
+/*******************************************************************************
+* mvTsuRxNextBuffGet
+*
+* DESCRIPTION:
+* 	Get a pointer to the next available Rx data & status buffers from the Rx
+*	queue.
+*
+* INPUT:
+*	port		- TSU port number.
+*	dataBuff	- Pointer to return the address of the next data buffer.
+*	statBuff	- Pointer to return the address of the next status buffer.
+* OUTPUT:
+*	buffsHandle	- A handle returned to the user to be used when freeing 
+*			  the buffers in mvTsuRxBuffFree().
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad parameters.
+*	MV_NOT_SUPPORTED- Functionality not supported by the port configuration.
+*	MV_NO_MORE	- No Rx data is available for copy.
+* NOTE:
+*	When working in Aggregation mode, the buffer will point to the 
+*	beggining of the aggregation buffer and not to a single packet inside 
+*	the buffer.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxNextBuffGet(MV_U8 port,MV_U32 **dataBuff, MV_U32 **statBuff,
+			     MV_U32 *buffsHandle);
+
+
+/*******************************************************************************
+* mvTsuRxTimestampCntEn
+*
+* DESCRIPTION:
+* 	Enable / Disable the timestamp counter for Rx direction.
+*
+* INPUT:
+*	port		- TSU port number.
+*	enable		- MV_TRUE to enable the timestamp counter.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad parameters.
+* NOTE:
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxTimestampCntEn(MV_U8 port,MV_BOOL enable);
+
+
+/*******************************************************************************
+* mvTsuRxBuffFree
+*
+* DESCRIPTION:
+* 	Mark a given set of buffers to be free (ready for new data Rx).
+*
+* INPUT:
+*	port		- TSU port number.
+*	dataBuff	- Pointer to the start of data buffer to return.
+*	statBuff	- Pointer to the start of status buffer to return.
+*	buffsHandle	- The buffers handle as returned by mvTsuRxNextBuffGet()
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NO_MORE	- No Rx data is available for copy.
+*	MV_BAD_PARAM	- Bad parameters.
+*	MV_BAD_STATE	- Bad buffer free order, attempting to free a buffer 
+*			  before all previous buffers where freed.
+* NOTE:
+*	When working in Aggregation mode, the buffer will point to the 
+*	beggining of the aggregation buffer and not to a single packet inside 
+*	the buffer.
+*	The numBuffs represents the number of aggregation buffers and not to the
+*	number of packets.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxBuffFree(MV_U8 port,MV_U32 *dataBuff, MV_U32 *statBuff,
+			  MV_U32 buffsHandle);
+
+
+/*******************************************************************************
+* mvTsuRxFlushErrorPackets
+*
+* DESCRIPTION:
+* 	Enable / Disable flushing of received erroneous packets.
+*
+* INPUT:
+*	port		- TSU port number.
+*	enableFlush	- MV_TRUE to flush recieved erroneous packets.
+*			  MV_FALSE to copy erroneous packets to Rx buffers.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+MV_STATUS mvTsuRxFlushErrorPackets(MV_U8 port, MV_BOOL enableFlush);
+
+
+/********************************/
+/* Tx related APIs		*/
+/********************************/
+
+
+/*******************************************************************************
+* mvTsuTxClockFreqSet
+*
+* DESCRIPTION:
+* 	Configure the transmit clock frequency and parameters.
+*
+* INPUT:
+*	port		- TSU port number.
+*	freq		- The frequency to configure in Hz. 
+*			range is 2500000 (2.5MHz) to 80000000 (80MHz).
+*	autoAdjust	- Whether to adjust the Tx frequency according to the
+*			next packet timestamp.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_VALUE	- Bad Tx frequency value.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxClockFreqSet(MV_U8 port, MV_U32 freq, MV_BOOL autoAdjust);
+
+
+/*******************************************************************************
+* mvTsuTxFreeBuffCountGet
+*
+* DESCRIPTION:
+* 	Get the number of free packets ready to be transmitted in the TX
+*	descriptor list.
+*
+* INPUT:
+*	port		- TSU port number.
+* OUTPUT:
+*	numBlocks	- Number of data blocks ready for CPU processing 
+*			 (does not have data for transmit).
+*	numBuffers	- Number of buffers ready for CPU processing (does not 
+*			  have data for transmit).
+*			In non-aggreagtion mode numBlocks == numBuffers.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NOT_SUPPORTED- If the port is not configured in input mode.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxFreeBuffCountGet(MV_U8 port, MV_U32 *numBlocks,
+				  MV_U32 *numBuffers);
+
+
+/*******************************************************************************
+* mvTsuRxNextBuffGet
+*
+* DESCRIPTION:
+* 	Get a pointer to the next available Tx data & status buffers from the Tx
+*	queue.
+*
+* INPUT:
+*	port		- TSU port number.
+*	dataBuff	- Pointer to return the address of the next data buffer.
+*	numBuffs	- Pointer to the maximum number of buffers to return.
+* OUTPUT:
+*	numBuffs	- Number of data / status buffers that where returned.
+*	buffsHandle	- A handle returned to the user to be used when freeing 
+*			  the buffers in mvTsuRxBuffFree().
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NO_MORE	- No Rx data is available for copy.
+* NOTE:
+*	When working in Aggregation mode, the buffer will point to the 
+*	beggining of the aggregation buffer and not to a single packet inside 
+*	the buffer.
+*	The numBuffs represents the number of aggregation buffers and not to the
+*	number of packets.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxNextBuffGet(MV_U8 port,MV_U32 **dataBuff,MV_U32 *buffsHandle);
+
+
+/*******************************************************************************
+* mvTsuTxBuffPut
+*
+* DESCRIPTION:
+* 	Mark a given set of buffers to be ready for transmission.
+*
+* INPUT:
+*	port		- TSU port number.
+*	dataBuff	- Pointer to the start of data buffer to put.
+*	tmsValue	- The timestamp to associate with the buffer.
+*		 	  This parameter is applicable only when working in 
+*			  non-aggregation mode.
+*	tsErr		- Indicates if the TS packet should be sent as an 
+*			  erroneous packet.
+*	buffsHandle	- The buffer handle as returned by mvTsuTxNextBuffGet()
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad function parameters.
+* NOTE:
+*	When working in Aggregation mode, the buffer will point to the 
+*	beggining of the aggregation buffer and not to a single packet inside 
+*	the buffer.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxBuffPut(MV_U8 port, MV_U32 *dataBuff, MV_U32 tmsValue,
+			 MV_BOOL tsErr, MV_U32 buffsHandle);
+
+
+/*******************************************************************************
+* mvTsuTxStatusGet
+*
+* DESCRIPTION:
+* 	Get the next TX done buffer from the TX done queue.
+*
+* INPUT:
+*	port		- TSU port number.
+*	doneBuff	- Pointer to return the address of the next done buffer.
+*	buffsHandle	- The buffer handle as returned by mvTsuTxNextBuffGet()
+* OUTPUT:
+*	numBuffs	- Number of returned buffers.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_NO_MORE	- No free Tx buffers are avilable.
+* NOTE:
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxStatusGet(MV_U8 port, MV_U32 **doneBuff, MV_U32 buffsHandle);
+
+
+/*******************************************************************************
+* mvTsuTxInitTimeStampSet
+*
+* DESCRIPTION:
+* 	Set the initial timestamp value for TX operations.
+*	This function must be called before each transmit session.
+*
+* INPUT:
+*	port		- TSU port number.
+*	enableTmstmp	- Enable the timestamp mechanism for packet transmit.
+*			  When false, the TSU will transmit packets back-to-back
+*	initTimestamp   - (Valid only if enableTs == MV_TRUE)
+*			  The initial timestamp to set.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*	MV_BAD_PARAM	- Bad timestamp value.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxInitTimeStampSet(MV_U8 port, MV_BOOL enableTmstmp, 
+				  MV_U32 initTimestamp);
+
+
+/*******************************************************************************
+* mvTsuTxDone
+*
+* DESCRIPTION:
+* 	Inform the TS unit that the current transmission session is over.
+*	This will stop the internal timestamp counters held by the unit.
+*
+* INPUT:
+*	port		- TSU port number.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK		- On success,
+*	MV_OUT_OF_RANGE	- Unsupported port number.
+*
+*******************************************************************************/
+MV_STATUS mvTsuTxDone(MV_U8 port);
+
+
+/*******************************************************************************
+* mvTsuWinInit
+*
+* DESCRIPTION:
+* 	Initialize the TSU unit address decode windows.
+*
+* INPUT:
+*	addWinMap: An array holding the address decoding information for the
+*		    system.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK	- on success,
+*
+*******************************************************************************/
+MV_STATUS mvTsuWinInit(MV_UNIT_WIN_INFO *addrWinMap);
+
+
+/*******************************************************************************
+* mvTsuWinWrite
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0)
+*       address window, also known as address decode window.
+*       After setting this target window, the TSU will be able to access the
+*       target within the address window.
+*
+* INPUT:
+*	unit	    - The Unit ID.
+*       winNum      - TSU to target address decode window number.
+*       pAddrDecWin - TSU target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR	- if address window overlapps with other address decode 
+*			windows.
+*       MV_BAD_PARAM	- if base address is invalid parameter or target is
+*       		unknown.
+*
+*******************************************************************************/
+MV_STATUS mvTsuWinWrite(MV_U32 unit, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+
+
+/*******************************************************************************
+* mvTsuWinRead
+*
+* DESCRIPTION:
+*	Get TSU peripheral target address window.
+*
+* INPUT:
+*	unit - The Unit ID.
+*	winNum - TSU to target address decode window number.
+*
+* OUTPUT:
+*       pAddrDecWin - TSU target window data structure.
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvTsuWinRead(MV_U32 unit, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin);
+
+/*******************************************************************************
+* mvTsuWinEnable - Enable/disable a TS address decode window
+*
+* DESCRIPTION:
+*       This function enable/disable a TS address decode window.
+*
+* INPUT:
+*       winNum - Decode window number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvTsuWinEnable(MV_U32 winNum, MV_BOOL enable);
+
+#endif /* __INC_MV_TSU__H__ */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/ts/mvTsuAddrDec.c b/arch/arm/plat-feroceon/mv_hal/ts/mvTsuAddrDec.c
new file mode 100755
index 0000000..a2dbf82
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ts/mvTsuAddrDec.c
@@ -0,0 +1,388 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvTsuRegs.h"
+#include "mvTsu.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+	#define DB(x)	x
+#else
+	#define DB(x)
+#endif	
+
+
+static MV_STATUS tsuWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
+
+MV_TARGET tsuAddrDecPrioTap[] = 
+{
+#if defined(MV_INCLUDE_SDRAM_CS0)
+    SDRAM_CS0,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS1)
+    SDRAM_CS1,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS2)
+    SDRAM_CS2,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS3)
+    SDRAM_CS3,
+#endif
+    TBL_TERM
+};
+
+/*******************************************************************************
+* mvTsuWinInit
+*
+* DESCRIPTION:
+* 	Initialize the TSU unit address decode windows.
+*
+* INPUT:
+*	addWinMap: An array holding the address decoding information for the
+*		    system.
+* OUTPUT:
+*	None.
+* RETURN:
+*       MV_OK	- on success,
+*
+*******************************************************************************/
+MV_STATUS mvTsuWinInit(MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32		winNum;
+	MV_UNIT_WIN_INFO	*addrDecWin;
+	MV_U32		winPrioIndex=0;
+
+	/* First disable all address decode windows */
+	for(winNum = 0; winNum < TSU_MAX_DECODE_WIN; winNum++)
+	{
+		MV_REG_BIT_RESET(MV_TSU_WIN_CTRL_REG(winNum),
+				 TSU_WIN_CTRL_EN_MASK);
+	}
+
+	/* Go through all windows in user table until table terminator      */
+	for(winNum = 0; ((tsuAddrDecPrioTap[winPrioIndex] != TBL_TERM) &&
+			 (winNum < TSU_MAX_DECODE_WIN));)
+	{
+		addrDecWin = &addrWinMap[tsuAddrDecPrioTap[winPrioIndex]];
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvTsuWinWrite(0, winNum, addrDecWin)) {
+				DB(mvOsPrintf("mvTsuWinInit: ERR. mvTsuWinWrite failed\n"));
+				return MV_ERROR;
+			}
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuWinWrite
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0)
+*       address window, also known as address decode window.
+*       After setting this target window, the TSU will be able to access the
+*       target within the address window.
+*
+* INPUT:
+*	unit	    - The Unit ID.
+*       winNum      - TSU to target address decode window number.
+*       pAddrDecWin - TSU target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR	- if address window overlapps with other address decode 
+*			windows.
+*       MV_BAD_PARAM	- if base address is invalid parameter or target is
+*       		unknown.
+*
+*******************************************************************************/
+MV_STATUS mvTsuWinWrite(MV_U32 unit, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32  sizeReg, baseReg;
+
+	/* Parameter checking   */
+	if(winNum >= TSU_MAX_DECODE_WIN)
+	{
+		mvOsPrintf("mvTsuWinSet: ERR. Invalid win num %d\n",winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlapps with current windows     */
+	if(MV_TRUE == tsuWinOverlapDetect(winNum, &pAddrDecWin->addrWin))
+	{
+		mvOsPrintf("mvTsuWinSet: ERR. Window %d overlap\n", winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow,pAddrDecWin->addrWin.size))
+	{
+		mvOsPrintf("mvTsuWinSet: Error setting TSU window %d.\n"
+			   "Address 0x%08x is unaligned to size 0x%x.\n",
+			   winNum,
+			   pAddrDecWin->addrWin.baseLow,
+			   pAddrDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	baseReg = pAddrDecWin->addrWin.baseLow & TSU_WIN_BASE_MASK;
+	sizeReg = (pAddrDecWin->addrWin.size / TSU_WIN_SIZE_ALIGN) - 1;
+	sizeReg = (sizeReg << TSU_WIN_CTRL_SIZE_OFFS) & TSU_WIN_CTRL_SIZE_MASK;
+
+	/* set attributes */
+	baseReg &= ~TSU_WIN_CTRL_ATTR_MASK;
+	baseReg |= pAddrDecWin->attrib << TSU_WIN_CTRL_ATTR_OFFS;
+	/* set target ID */
+	baseReg &= ~TSU_WIN_CTRL_TARGET_MASK;
+	baseReg |= pAddrDecWin->targetId << TSU_WIN_CTRL_TARGET_OFFS;
+
+	/* for the safe side we disable the window before writing the new */
+	/* values */
+	mvTsuWinEnable(winNum, MV_FALSE);
+	MV_REG_WRITE(MV_TSU_WIN_CTRL_REG(winNum), sizeReg);
+
+	/* Write to address decode Size Register                            */
+	MV_REG_WRITE(MV_TSU_WIN_BASE_REG(winNum), baseReg);
+
+	/* Enable address decode target window                              */
+	if(pAddrDecWin->enable == MV_TRUE)
+	{
+		mvTsuWinEnable(winNum,MV_TRUE);
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvTsuWinRead
+*
+* DESCRIPTION:
+*	Get TSU peripheral target address window.
+*
+* INPUT:
+*	unit   - The Unit ID.
+*	winNum - TSU to target address decode window number.
+*
+* OUTPUT:
+*       pAddrDecWin - TSU target window data structure.
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvTsuWinRead(MV_U32 unit, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 baseReg, sizeReg;
+
+	/* Parameter checking   */
+	if(winNum >= TSU_MAX_DECODE_WIN)
+	{
+		mvOsPrintf("mvTsuWinGet: ERR. Invalid winNum %d\n", winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	baseReg = MV_REG_READ(MV_TSU_WIN_BASE_REG(winNum));                                                                           
+	sizeReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum));
+
+	pAddrDecWin->addrWin.size = (sizeReg & TSU_WIN_CTRL_SIZE_MASK) >> TSU_WIN_CTRL_SIZE_OFFS;
+	pAddrDecWin->addrWin.size = (pAddrDecWin->addrWin.size + 1) * TSU_WIN_SIZE_ALIGN;
+
+	pAddrDecWin->addrWin.baseLow = baseReg & TSU_WIN_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh =  0;
+
+	/* attrib and targetId */
+	pAddrDecWin->attrib = 
+		(sizeReg & TSU_WIN_CTRL_ATTR_MASK) >> TSU_WIN_CTRL_ATTR_OFFS;
+	pAddrDecWin->targetId = 
+		(sizeReg & TSU_WIN_CTRL_TARGET_MASK) >> TSU_WIN_CTRL_TARGET_OFFS;
+
+	/* Check if window is enabled   */
+	if((MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum)) & TSU_WIN_CTRL_EN_MASK))
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvTsuWinEnable - Enable/disable a TS address decode window
+*
+* DESCRIPTION:
+*       This function enable/disable a TS address decode window.
+*
+* INPUT:
+*       winNum - Decode window number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvTsuWinEnable(MV_U32 winNum, MV_BOOL enable)
+{
+    MV_UNIT_WIN_INFO	addrDecWin;
+
+    /* Parameter checking   */               
+    if (winNum >= TSU_MAX_DECODE_WIN) {
+        DB(mvOsPrintf("%s: ERR. Invalid winNum%d\n", __FUNCTION__, winNum));
+        return MV_ERROR;
+    }
+
+    if (enable == MV_TRUE) {
+	/* Get current window */
+	if (MV_OK != mvTsuWinRead(0, winNum, &addrDecWin)) {
+	    DB(mvOsPrintf("%s: ERR. targetWinGet fail\n", __FUNCTION__));
+	    return MV_ERROR;
+	}
+
+	/* Check for overlapping */
+	if (MV_TRUE == tsuWinOverlapDetect(winNum, &(addrDecWin.addrWin))) {
+	    /* Overlap detected	*/
+	    DB(mvOsPrintf("%s: ERR. Overlap detected\n", __FUNCTION__));
+	    return MV_ERROR;
+	}
+
+	/* No Overlap. Enable address decode target window */
+	MV_REG_BIT_SET(MV_TSU_WIN_CTRL_REG(winNum), TSU_WIN_CTRL_EN_MASK);
+    } else {
+	/* Disable address decode target window */
+	MV_REG_BIT_RESET(MV_TSU_WIN_CTRL_REG(winNum), TSU_WIN_CTRL_EN_MASK);
+    }
+
+    return MV_OK;                  
+}
+
+/*******************************************************************************
+* tsuWinOverlapDetect - Detect TS address windows overlaping
+*
+* DESCRIPTION:
+*       An unpredicted behaviour is expected in case TS address decode 
+*       windows overlaps.
+*       This function detects TS address decode windows overlaping of a 
+*       specified window. The function does not check the window itself for 
+*       overlaping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data 
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS tsuWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+    MV_U32		baseAddrEnableReg;
+    MV_U32		winNumIndex;
+    MV_UNIT_WIN_INFO	addrDecWin;
+
+    if (pAddrWin == NULL) {
+	DB(mvOsPrintf("%s: ERR. pAddrWin is NULL pointer\n", __FUNCTION__ ));
+	return MV_BAD_PTR;
+    }
+
+    for (winNumIndex = 0; winNumIndex < TSU_MAX_DECODE_WIN; winNumIndex++) {
+	/* Do not check window itself */
+	if (winNumIndex == winNum)
+	    continue;
+
+	/* Read base address enable register. Do not check disabled windows	*/
+	baseAddrEnableReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNumIndex));
+
+	/* Do not check disabled windows */
+	if ((baseAddrEnableReg & TSU_WIN_CTRL_EN_MASK) == 0)
+	    continue;
+
+	/* Get window parameters */
+	if (MV_OK != mvTsuWinRead(0, winNumIndex, &addrDecWin)) {
+	    DB(mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__ ));
+	    return MV_ERROR;
+	}
+
+	if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+	    return MV_TRUE;
+    }
+
+    return MV_FALSE;
+}
+
diff --git a/arch/arm/plat-feroceon/mv_hal/ts/mvTsuRegs.h b/arch/arm/plat-feroceon/mv_hal/ts/mvTsuRegs.h
new file mode 100755
index 0000000..5cbdf4c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/ts/mvTsuRegs.h
@@ -0,0 +1,285 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+        used to endorse or promote products derived from this software without
+        specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INC_MV_TSU_REGS_H__
+#define __INC_MV_TSU_REGS_H__
+
+#define TSU_MAX_DECODE_WIN		4
+
+#define MV_TSU_MODES_REG		(MV_TSU_GLOBAL_REGS_BASE + 0x00)
+
+
+#define MV_TSU_CONFIG_REG(port)			(MV_TSU_REGS_BASE(port) + 0x00)
+#define MV_TSU_DMA_PARAMS_REG(port)		(MV_TSU_REGS_BASE(port) + 0x04)
+#define MV_TSU_DONE_QUEUE_BASE_REG(port)	(MV_TSU_REGS_BASE(port) + 0x08)
+#define MV_TSU_DESC_QUEUE_BASE_REG(port)	(MV_TSU_REGS_BASE(port) + 0x0C)
+#define MV_TSU_DONE_QUEUE_WRITE_PTR_REG(port)	(MV_TSU_REGS_BASE(port) + 0x10)
+#define MV_TSU_DONE_QUEUE_READ_PTR_REG(port)	(MV_TSU_REGS_BASE(port) + 0x14)
+#define MV_TSU_DESC_QUEUE_WRITE_PTR_REG(port)	(MV_TSU_REGS_BASE(port) + 0x18)
+#define MV_TSU_DESC_QUEUE_READ_PTR_REG(port)	(MV_TSU_REGS_BASE(port) + 0x1C)
+#define MV_TSU_ENABLE_ACCESS_REG(port)		(MV_TSU_REGS_BASE(port) + 0x2C)
+#define MV_TSU_TIMESTAMP_REG(port)		(MV_TSU_REGS_BASE(port) + 0x30)
+#define MV_TSU_STATUS_REG(port)			(MV_TSU_REGS_BASE(port) + 0x34)
+#define MV_TSU_TIMESTAMP_CTRL_REG(port)		(MV_TSU_REGS_BASE(port) + 0x38)
+#define MV_TSU_TEST_REG(port)			(MV_TSU_REGS_BASE(port) + 0x3C)
+#define MV_TSU_INTERRUPT_SRC_REG(port)		(MV_TSU_REGS_BASE(port) + 0x40)
+#define MV_TSU_INTERRUPT_MASK_REG(port)		(MV_TSU_REGS_BASE(port) + 0x44)
+#define MV_TSU_IRQ_PARAM_REG(port)		(MV_TSU_REGS_BASE(port) + 0x48)
+#define MV_TSU_DEBUG_REG(port)			(MV_TSU_REGS_BASE(port) + 0x4C)
+#define MV_TSU_NEXT_DESC_1_REG(port)		(MV_TSU_REGS_BASE(port) + 0x50)
+#define MV_TSU_NEXT_DESC_2_REG(port)		(MV_TSU_REGS_BASE(port) + 0x54)
+#define MV_TSU_SYNCBYTE_DETECT_REG(port)	(MV_TSU_REGS_BASE(port) + 0x58)
+#define MV_TSU_AGGREGATION_CTRL_REG(port)	(MV_TSU_REGS_BASE(port) + 0x60)
+#define MV_TSU_TIMESTAMP_INTERVAL_REG(port)	(MV_TSU_REGS_BASE(port) + 0x64)
+#define MV_TSU_CONFIG_2_REG(port)		(MV_TSU_REGS_BASE(port) + 0x68)
+
+
+/* TSU Modes register.				*/
+#define TSU_MODES_PAR_MODE_OFFS		14
+#define TSU_MODES_PAR_MODE_MASK		(0x1 << TSU_MODES_PAR_MODE_OFFS)
+#define TSU_MODES_PAR_MODE_SER		(0x0 << TSU_MODES_PAR_MODE_OFFS)
+#define TSU_MODES_PAR_MODE_PAR		(0x1 << TSU_MODES_PAR_MODE_OFFS)
+#define TSU_MODES_TSCK_OFF		15
+#define TSU_MODES_TSCK_MASK		(0x3 << TSU_MODES_TSCK_OFF)
+
+
+/* TSU config register.				*/
+#define TSU_CFG_RESET_OFFS		0
+#define TSU_CFG_RESET_MASK		(0x3 << TSU_CFG_RESET_OFFS)
+#define TSU_CFG_RESET_SET		(0x1 << TSU_CFG_RESET_OFFS)
+#define TSU_CFG_RESET_CLEAR		(0x2 << TSU_CFG_RESET_OFFS)
+#define TSU_CFG_OPER_OFFS		2
+#define TSU_CFG_OPER_MASK		(0x3 << TSU_CFG_OPER_OFFS)
+#define TSU_CFG_OPER_DISABLE		(0x1 << TSU_CFG_OPER_OFFS)
+#define TSU_CFG_OPER_ENABLE		(0x2 << TSU_CFG_OPER_OFFS)
+#define TSU_CFG_DATA_DIR_OFFS		8
+#define TSU_CFG_DATA_DIR_MASK		(0x1 << TSU_CFG_DATA_DIR_OFFS)
+#define TSU_CFG_DATA_DIR_IN		(0x0 << TSU_CFG_DATA_DIR_OFFS)
+#define TSU_CFG_DATA_DIR_OUT		(0x1 << TSU_CFG_DATA_DIR_OFFS)
+#define TSU_CFG_DATA_MODE_OFFS		9
+#define TSU_CFG_DATA_MODE_MASK		(0x1 << TSU_CFG_DATA_MODE_OFFS)
+#define TSU_CFG_DATA_MODE_SER		(0x0 << TSU_CFG_DATA_MODE_OFFS)
+#define TSU_CFG_DATA_MODE_PAR		(0x1 << TSU_CFG_DATA_MODE_OFFS)
+#define TSU_CFG_OUT_CLOCK_OFFS		10
+#define TSU_CFG_OUT_CLOCK_MASK		(0x3 << TSU_CFG_OUT_CLOCK_OFFS)
+#define TSU_CFG_OUT_CLOCK_4_32		(0x0 << TSU_CFG_OUT_CLOCK_OFFS)
+#define TSU_CFG_OUT_CLOCK_2_16		(0x1 << TSU_CFG_OUT_CLOCK_OFFS)
+#define TSU_CFG_OUT_CLOCK_1_8		(0x2 << TSU_CFG_OUT_CLOCK_OFFS)
+#define TSU_CFG_OUT_CLOCK_EXT		(0x3 << TSU_CFG_OUT_CLOCK_OFFS)
+#define TSU_CFG_CLK_MODE_OFFS		12
+#define TSU_CFG_CLK_MODE_MASK		(0x1 << TSU_CFG_CLK_MODE_OFFS)
+#define TSU_CFG_CLK_MODE_CONT		(0x0 << TSU_CFG_CLK_MODE_OFFS)
+#define TSU_CFG_CLK_MODE_GAPPED		(0x1 << TSU_CFG_CLK_MODE_OFFS)
+#define TSU_CFG_TS_SYNC_OFFS		13
+#define TSU_CFG_TS_SYNC_MASK		(0x1 << TSU_CFG_TS_SYNC_OFFS)
+#define TSU_CFG_TS_SYNC_8BIT		(0x0 << TSU_CFG_TS_SYNC_OFFS)
+#define TSU_CFG_TS_SYNC_1BIT		(0x1 << TSU_CFG_TS_SYNC_OFFS)
+#define TSU_CFG_DATA_ORD_OFFS		14
+#define TSU_CFG_DATA_ORD_MASK		(0x1 << TSU_CFG_DATA_ORD_OFFS)
+#define TSU_CFG_DATA_ORD_MSB		(0x0 << TSU_CFG_DATA_ORD_OFFS)
+#define TSU_CFG_DATA_ORD_LSB		(0x1 << TSU_CFG_DATA_ORD_OFFS)
+#define TSU_CFG_TX_EDGE_OFFS		15
+#define TSU_CFG_TX_EDGE_MASK		(0x1 << TSU_CFG_TX_EDGE_OFFS)
+#define TSU_CFG_FREQ_MODE_OFFS		16
+#define TSU_CFG_FREQ_MODE_MASK		(0x1 << TSU_CFG_FREQ_MODE_OFFS)
+#define TSU_CFG_ERR_POL_OFFS		18
+#define TSU_CFG_ERR_POL_MASK		(0x1 << TSU_CFG_ERR_POL_OFFS)
+#define TSU_CFG_ERR_USED_OFFS		19
+#define TSU_CFG_ERR_USED_MASK		(0x1 << TSU_CFG_ERR_USED_OFFS)
+#define TSU_CFG_VAL_POL_OFFS		20
+#define TSU_CFG_VAL_POL_MASK		(0x1 << TSU_CFG_VAL_POL_OFFS)
+#define TSU_CFG_VAL_USED_OFFS		21
+#define TSU_CFG_VAL_USED_MASK		(0x1 << TSU_CFG_VAL_USED_OFFS)
+#define TSU_CFG_SYNC_POL_OFFS		22
+#define TSU_CFG_SYNC_POL_MASK		(0x1 << TSU_CFG_SYNC_POL_OFFS)
+#define TSU_CFG_SYNC_USED_OFFS		23
+#define TSU_CFG_SYNC_USED_MASK		(0x1 << TSU_CFG_SYNC_USED_OFFS)
+#define TSU_CFG_RESET_SET		(0x1 << TSU_CFG_RESET_OFFS)
+#define TSU_CFG_PKT_SIZE_OFFS		24
+#define TSU_CFG_PKT_SIZE_MASK		(0xFF << TSU_CFG_PKT_SIZE_OFFS)
+
+/* TSU DMA parameters register.			*/
+#define TSU_DMAP_DMA_LEN_OFFS		0
+#define TSU_DMAP_DMA_LEN_MASK		(0xFFFF << TSU_DMAP_DMA_LEN_OFFS)
+#define TSU_DMAP_DATA_WTRMK_OFFS	16
+#define TSU_DMAP_DATA_WTRMK_MASK	(0xFF << TSU_DMAP_DATA_WTRMK_OFFS)
+#define TSU_DMAP_DATA_WTRMK_MAX		0xFF
+#define TSU_DMAP_DESC_Q_SIZE_OFFS	24
+#define TSU_DMAP_DESC_Q_SIZE_MASK	(0xF << TSU_DMAP_DESC_Q_SIZE_OFFS)
+#define TSU_DMAP_DONE_Q_SIZE_OFFS	28
+#define TSU_DMAP_DONE_Q_SIZE_MASK	(0xF << TSU_DMAP_DONE_Q_SIZE_OFFS)
+
+/* TSU Done queue base register.		*/
+#define TSU_DONE_PTR_BASE_OFFS		2
+#define TSU_DONE_PTR_BASE_MASK		(0x3FFFFFFF << TSU_DONE_PTR_BASE_OFFS)
+
+/* TSU Desc queue base register.		*/
+#define TSU_DESC_PTR_BASE_OFFS		2
+#define TSU_DESC_PTR_BASE_MASK		(0x3FFFFFFF << TSU_DESC_PTR_BASE_OFFS)
+
+/* TSU Done queue write pointer register.	*/
+#define TSU_DONE_WRITE_PTR_OFFS		0
+#define TSU_DONE_WRITE_PTR_MASK		(0xFFF << TSU_DONE_WRITE_PTR_OFFS)
+
+/* TSU Done queue read pointer register.	*/
+#define TSU_DONE_READ_PTR_OFFS		0
+#define TSU_DONE_READ_PTR_MASK		(0xFFF << TSU_DONE_READ_PTR_OFFS)
+
+/* TSU Desc queue write pointer register.	*/
+#define TSU_DESC_WRITE_PTR_OFFS		0
+#define TSU_DESC_WRITE_PTR_MASK		(0xFFF << TSU_DESC_WRITE_PTR_OFFS)
+
+/* TSU Desc queue read pointer register.	*/
+#define TSU_DESC_READ_PTR_OFFS		0
+#define TSU_DESC_READ_PTR_MASK		(0xFFF << TSU_DESC_READ_PTR_OFFS)
+
+/* TSU access enable reg.			*/
+#define TSU_ENACC_TS_READ_OFFS		0
+#define TSU_ENACC_TS_WRITE_OFFS		8
+#define TSU_ENACC_DESC_WRITE_OFFS	16
+#define TSU_ENACC_DESC_READ_OFFS	24
+
+/* TSU Timestamp register.			*/
+#define TSU_TMSTMP_TIMESTAMP_OFFS	0
+#define TSU_TMSTMP_TIMESTAMP_MASK	(0xFFFFFFF << TSU_TMSTMP_TIMESTAMP_OFFS)
+
+/* TSU status register.				*/
+#define TSU_STATUS_OFFS			0
+#define TSU_STATUS_MASK			(0x7FF << TSU_STATUS_OFFS)
+#define TSU_STATUS_IF_ERR		(0x100 << TSU_STATUS_OFFS)
+#define TSU_STATUS_FIFO_OVFL_ERR	(0x200 << TSU_STATUS_OFFS)
+#define TSU_STATUS_CONN_ERR		(0x400 << TSU_STATUS_OFFS)
+
+/* TSU interrupt source register.		*/
+#define TSU_INT_TS_IF_ERROR		(1 << 3)
+#define TSU_INT_FIFO_OVFL_ERROR		(1 << 4)
+#define TSU_INT_TS_CONN_ERROR		(1 << 5)
+#define TSU_INT_CLOCK_SYNC_EXP		(1 << 6)
+
+/* TSU SyncByte detect register.		*/
+#define TSU_SYNC_DETECT_CNT_OFFS	0
+#define TSU_SYNC_DETECT_CNT_MASK	(0xF << TSU_SYNC_DETECT_CNT_OFFS)
+#define TSU_SYNC_LOSS_CNT_OFFS		4
+#define TSU_SYNC_LOSS_CNT_MASK		(0xF << TSU_SYNC_LOSS_CNT_OFFS)
+
+/* TSU Aggregation control register.		*/
+#define TSU_AGGR_PCKT_NUM_OFFS		0
+#define TSU_AGGR_PCKT_NUM_MASK		(0xFF << TSU_AGGR_PCKT_NUM_OFFS)
+#define TSU_AGGR_TMSTMP_OFF_OFFS	8
+#define TSU_AGGR_TMSTMP_OFF_MASK	(0xF << TSU_AGGR_TMSTMP_OFF_OFFS)
+#define TSU_AGGR_FLUSH_ERR_OFFS		26
+#define TSU_AGGR_FLUSH_ERR_MASK		(0x3 << TSU_AGGR_FLUSH_ERR_OFFS)
+#define TSU_AGGR_FLUSH_ERR_DISABLE	(0x1 << TSU_AGGR_FLUSH_ERR_OFFS)
+#define TSU_AGGR_FLUSH_ERR_ENABLE	(0x2 << TSU_AGGR_FLUSH_ERR_OFFS)
+#define TSU_AGGR_TMSTMP_MODE_OFFS	28
+#define TSU_AGGR_TMSTMP_MODE_MASK	(0x3 << TSU_AGGR_TMSTMP_MODE_OFFS)
+#define TSU_AGGR_TMSTMP_TO_DONE_Q	(0x1 << TSU_AGGR_TMSTMP_MODE_OFFS)
+#define TSU_AGGR_TMSTMP_TO_PCKT		(0x2 << TSU_AGGR_TMSTMP_MODE_OFFS)
+#define TSU_AGGR_ENABLE_OFFS		30
+#define TSU_AGGR_ENABLE_MASK		(0x3 << TSU_AGGR_ENABLE_OFFS)
+#define TSU_AGGR_DISABLE		(0x1 << TSU_AGGR_ENABLE_OFFS)
+#define TSU_AGGR_ENABLE			(0x2 << TSU_AGGR_ENABLE_OFFS)
+
+
+/* TSU timestamp interval register.		*/
+#define TSU_TMSTP_INTRVL_OFFS		0
+#define TSU_TMSTP_INTRVL_MASK		(0xFFFFFFF << TSU_TMSTP_INTRVL_OFFS)
+
+/* TSU timestamp control register.		*/
+#define TSU_TMS_CTRL_TIMER_OFFS		0
+#define TSU_TMS_CTRL_TIMER_MASK		(0x3 << TSU_TMS_CTRL_TIMER_OFFS)
+#define TSU_TMS_CTRL_TIMER_DIS		(0x1 << TSU_TMS_CTRL_TIMER_OFFS)
+#define TSU_TMS_CTRL_TIMER_EN		(0x2 << TSU_TMS_CTRL_TIMER_OFFS)
+#define TSU_TMS_CTRL_AUTO_ADJ_OFFS	2
+#define TSU_TMS_CTRL_AUTO_ADJ_MASK	(0x3 << TSU_TMS_CTRL_AUTO_ADJ_OFFS)
+#define TSU_TMS_CTRL_AUTO_ADJ_OFF	(0x1 << TSU_TMS_CTRL_AUTO_ADJ_OFFS)
+#define TSU_TMS_CTRL_AUTO_ADJ_ON	(0x2 << TSU_TMS_CTRL_AUTO_ADJ_OFFS)
+#define TSU_TMS_CTRL_READ_TIMER_OFFS	4
+#define TSU_TMS_CTRL_READ_TIMER_MASK	(0x1 << TSU_TMS_CTRL_READ_TIMER_OFFS)
+
+
+/*******************************************/
+/* TSU Windows Registers                   */
+/*******************************************/
+#define TSU_MAX_DECODE_WIN		4
+
+#define MV_TSU_WIN_CTRL_REG(win)	(MV_TSU_GLOBAL_REGS_BASE + 0x30 + 0x10 * win)
+#define MV_TSU_WIN_BASE_REG(win)	(MV_TSU_GLOBAL_REGS_BASE + 0x34 + 0x10 * win)
+
+/* TSU windows control register.		*/
+#define TSU_WIN_CTRL_EN_MASK		(0x1 << 0)
+#define TSU_WIN_CTRL_TARGET_OFFS	4
+#define TSU_WIN_CTRL_TARGET_MASK	(0xF << TSU_WIN_CTRL_TARGET_OFFS)
+#define TSU_WIN_CTRL_ATTR_OFFS		8
+#define TSU_WIN_CTRL_ATTR_MASK		(0xFF << TSU_WIN_CTRL_ATTR_OFFS)
+#define TSU_WIN_CTRL_SIZE_OFFS		16
+#define TSU_WIN_CTRL_SIZE_MASK		(0xFFFF << TSU_WIN_CTRL_SIZE_OFFS)
+#define TSU_WIN_SIZE_ALIGN		_64K
+
+/* TSU windows base register.			*/
+#define TSU_WIN_BASE_OFFS		16
+#define TSU_WIN_BASE_MASK		(0xFFFF << TSU_WIN_BASE_OFFS)
+
+
+#endif /* __INC_MV_TSU_REGS_H__ */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/twsi/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/twsi/mvCompVer.txt
new file mode 100755
index 0000000..40fea93
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/twsi/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.5
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsi.c b/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsi.c
new file mode 100755
index 0000000..37e4204
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsi.c
@@ -0,0 +1,987 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvTwsi.h"
+#include "mvTwsiSpec.h"
+
+/*#define MV_DEBUG*/
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+static MV_VOID twsiIntFlgClr(MV_U8 chanNum);
+static MV_BOOL twsiMainIntGet(MV_U8 chanNum);
+static MV_VOID twsiAckBitSet(MV_U8 chanNum);
+static MV_U32 twsiStsGet(MV_U8 chanNum);
+static MV_VOID twsiReset(MV_U8 chanNum);
+static MV_STATUS twsiAddr7BitSet(MV_U8 chanNum, MV_U32 deviceAddress, MV_TWSI_CMD command);
+static MV_STATUS twsiAddr10BitSet(MV_U8 chanNum, MV_U32 deviceAddress, MV_TWSI_CMD command);
+static MV_STATUS twsiDataTransmit(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize);
+static MV_STATUS twsiDataReceive(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize);
+static MV_STATUS twsiTargetOffsSet(MV_U8 chanNum, MV_U32 offset, MV_BOOL moreThen256);
+
+static MV_BOOL twsiTimeoutChk(MV_U32 timeout, const MV_8 *pString)
+{
+	if (timeout >= TWSI_TIMEOUT_VALUE) {
+		DB(mvOsPrintf("%s", pString));
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+
+}
+
+/*******************************************************************************
+* mvTwsiStartBitSet - Set start bit on the bus
+*
+* DESCRIPTION:
+*       This routine sets the start bit on the TWSI bus.
+*       The routine first checks for interrupt flag condition, then it sets
+*       the start bit  in the TWSI Control register.
+*       If the interrupt flag condition check previously was set, the function
+*       will clear it.
+*       The function then wait for the start bit to be cleared by the HW.
+*       Then it waits for the interrupt flag to be set and eventually, the
+*       TWSI status is checked to be 0x8 or 0x10(repeated start bit).
+*
+* INPUT:
+*       chanNum - TWSI channel.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK is start bit was set successfuly on the bus.
+*       MV_FAIL if interrupt flag was set before setting start bit.
+*
+*******************************************************************************/
+MV_STATUS mvTwsiStartBitSet(MV_U8 chanNum)
+{
+	MV_BOOL isIntFlag = MV_FALSE;
+	MV_U32 timeout, temp;
+
+	DB(mvOsPrintf("TWSI: mvTwsiStartBitSet \n"));
+	/* check Int flag */
+	if (twsiMainIntGet(chanNum))
+		isIntFlag = MV_TRUE;
+	/* set start Bit */
+	temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum));
+	MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_START_BIT);
+
+	/* in case that the int flag was set before i.e. repeated start bit */
+	if (isIntFlag) {
+		DB(mvOsPrintf("TWSI: mvTwsiStartBitSet repeated start Bit\n"));
+		twsiIntFlgClr(chanNum);
+	}
+
+	/* wait for interrupt */
+	timeout = 0;
+	while (!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE))
+		;
+
+	/* check for timeout */
+	if (MV_TRUE == twsiTimeoutChk(timeout,
+				      (const MV_8 *)"TWSI: mvTwsiStartBitSet ERROR - Start Clear bit TimeOut .\n"))
+		return MV_TIMEOUT;
+
+	/* check that start bit went down */
+	if ((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_START_BIT) != 0) {
+		mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - start bit didn't went down\n");
+		return MV_FAIL;
+	}
+
+	/* check the status */
+	temp = twsiStsGet(chanNum);
+	if ((temp != TWSI_START_CON_TRA) && (temp != TWSI_REPEATED_START_CON_TRA)) {
+		mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - status %x after Set Start Bit. \n", temp);
+		return MV_FAIL;
+	}
+
+	return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvTwsiStopBitSet - Set stop bit on the bus
+*
+* DESCRIPTION:
+*       This routine set the stop bit on the TWSI bus.
+*       The function then wait for the stop bit to be cleared by the HW.
+*       Finally the function checks for status of 0xF8.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE is stop bit was set successfuly on the bus.
+*
+*******************************************************************************/
+MV_STATUS mvTwsiStopBitSet(MV_U8 chanNum)
+{
+	MV_U32 timeout, temp;
+
+	/* Generate stop bit */
+	temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum));
+	MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_STOP_BIT);
+
+	twsiIntFlgClr(chanNum);
+
+	/* wait for stop bit to come down */
+	timeout = 0;
+	while (((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0)
+	       && (timeout++ < TWSI_TIMEOUT_VALUE))
+		;
+
+	/* check for timeout */
+	if (MV_TRUE == twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: mvTwsiStopBitSet ERROR - Stop bit TimeOut .\n"))
+		return MV_TIMEOUT;
+
+	/* check that the stop bit went down */
+	if ((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0) {
+		mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - stop bit didn't went down. \n");
+		return MV_FAIL;
+	}
+
+	/* check the status */
+	temp = twsiStsGet(chanNum);
+	if (temp != TWSI_NO_REL_STS_INT_FLAG_IS_KEPT_0) {
+		mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - status %x after Stop Bit. \n", temp);
+		return MV_FAIL;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* twsiMainIntGet - Get twsi bit from main Interrupt cause.
+*
+* DESCRIPTION:
+*       This routine returns the twsi interrupt flag value.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE is interrupt flag is set, MV_FALSE otherwise.
+*
+*******************************************************************************/
+static MV_BOOL twsiMainIntGet(MV_U8 chanNum)
+{
+	MV_U32 temp;
+
+	/* get the int flag bit */
+
+	temp = MV_REG_READ(MV_TWSI_CPU_MAIN_INT_CASUE(chanNum));
+	if (temp & (TWSI0_CPU_MAIN_INT_BIT(chanNum)))
+		return MV_TRUE;
+
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* twsiIntFlgClr - Clear Interrupt flag.
+*
+* DESCRIPTION:
+*       This routine clears the interrupt flag. It does NOT poll the interrupt
+*       to make sure the clear. After clearing the interrupt, it waits for at
+*       least 1 miliseconds.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID twsiIntFlgClr(MV_U8 chanNum)
+{
+	MV_U32 temp;
+
+	/* wait for 1 mili to prevent TWSI register write after write problems */
+	mvOsDelay(1);
+	/* clear the int flag bit */
+	temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum));
+	MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp & ~(TWSI_CONTROL_INT_FLAG_SET));
+
+	/* wait for 1 mili sec for the clear to take effect */
+	mvOsDelay(1);
+
+	return;
+}
+
+/*******************************************************************************
+* twsiAckBitSet - Set acknowledge bit on the bus
+*
+* DESCRIPTION:
+*       This routine set the acknowledge bit on the TWSI bus.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static MV_VOID twsiAckBitSet(MV_U8 chanNum)
+{
+	MV_U32 temp;
+
+	/*Set the Ack bit */
+	temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum));
+	MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_ACK);
+
+	/* Add delay of 1ms */
+	mvOsDelay(1);
+	return;
+}
+
+/*******************************************************************************
+* twsiInit - Initialize TWSI interface
+*
+* DESCRIPTION:
+*       This routine:
+*	-Reset the TWSI.
+*	-Initialize the TWSI clock baud rate according to given frequancy
+*	 parameter based on Tclk frequancy and enables TWSI slave.
+*       -Set the ack bit.
+*	-Assign the TWSI slave address according to the TWSI address Type.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*       frequancy - TWSI frequancy in KHz. (up to 100KHZ)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Actual frequancy.
+*
+*******************************************************************************/
+MV_U32 mvTwsiInit(MV_U8 chanNum, MV_HZ frequancy, MV_U32 Tclk, MV_TWSI_ADDR *pTwsiAddr, MV_BOOL generalCallEnable)
+{
+	MV_U32 n, m, freq, margin, minMargin = 0xffffffff;
+	MV_U32 power;
+	MV_U32 actualFreq = 0, actualN = 0, actualM = 0, val;
+
+	if (frequancy > 100000)
+		mvOsPrintf("Warning TWSI frequancy is too high, please use up tp 100Khz. \n");
+
+	DB(mvOsPrintf("TWSI: mvTwsiInit - Tclk = %d freq = %d\n", Tclk, frequancy));
+	/* Calucalte N and M for the TWSI clock baud rate */
+	for (n = 0; n < 8; n++) {
+		for (m = 0; m < 16; m++) {
+			power = 2 << n;	/* power = 2^(n+1) */
+			freq = Tclk / (10 * (m + 1) * power);
+			margin = MV_ABS(frequancy - freq);
+
+			if ((freq <= frequancy) && (margin < minMargin)) {
+				minMargin = margin;
+				actualFreq = freq;
+				actualN = n;
+				actualM = m;
+			}
+		}
+	}
+	DB(mvOsPrintf("TWSI: mvTwsiInit - actN %d actM %d actFreq %d\n", actualN, actualM, actualFreq));
+	/* Reset the TWSI logic */
+	twsiReset(chanNum);
+
+	/* Set the baud rate */
+	val = ((actualM << TWSI_BAUD_RATE_M_OFFS) | actualN << TWSI_BAUD_RATE_N_OFFS);
+	MV_REG_WRITE(TWSI_STATUS_BAUDE_RATE_REG(chanNum), val);
+
+	/* Enable the TWSI and slave */
+	MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), TWSI_CONTROL_ENA | TWSI_CONTROL_ACK);
+
+	/* set the TWSI slave address */
+	if (pTwsiAddr->type == ADDR10_BIT) {	/* 10 Bit deviceAddress */
+		/* writing the 2 most significant bits of the 10 bit address */
+		val = ((pTwsiAddr->address & TWSI_SLAVE_ADDR_10BIT_MASK) >> TWSI_SLAVE_ADDR_10BIT_OFFS);
+		/* bits 7:3 must be 0x11110 */
+		val |= TWSI_SLAVE_ADDR_10BIT_CONST;
+		/* set GCE bit */
+		if (generalCallEnable)
+			val |= TWSI_SLAVE_ADDR_GCE_ENA;
+		/* write slave address */
+		MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum), val);
+
+		/* writing the 8 least significant bits of the 10 bit address */
+		val = (pTwsiAddr->address << TWSI_EXTENDED_SLAVE_OFFS) & TWSI_EXTENDED_SLAVE_MASK;
+		MV_REG_WRITE(TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum), val);
+	} else {		/*7 bit address */
+
+		/* set the 7 Bits address */
+		MV_REG_WRITE(TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum), 0x0);
+		val = (pTwsiAddr->address << TWSI_SLAVE_ADDR_7BIT_OFFS) & TWSI_SLAVE_ADDR_7BIT_MASK;
+		MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum), val);
+	}
+
+	/* unmask twsi int */
+	val = MV_REG_READ(TWSI_CONTROL_REG(chanNum));
+	MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), val | TWSI_CONTROL_INT_ENA);
+	/* Add delay of 1ms */
+	mvOsDelay(1);
+
+	return actualFreq;
+}
+
+/*******************************************************************************
+* twsiStsGet - Get the TWSI status value.
+*
+* DESCRIPTION:
+*       This routine returns the TWSI status value.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_U32 - the TWSI status.
+*
+*******************************************************************************/
+static MV_U32 twsiStsGet(MV_U8 chanNum)
+{
+	return MV_REG_READ(TWSI_STATUS_BAUDE_RATE_REG(chanNum));
+
+}
+
+/*******************************************************************************
+* twsiReset - Reset the TWSI.
+*
+* DESCRIPTION:
+*       Resets the TWSI logic and sets all TWSI registers to their reset values.
+*
+* INPUT:
+*      chanNum - TWSI channel
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None
+*
+*******************************************************************************/
+static MV_VOID twsiReset(MV_U8 chanNum)
+{
+	/* Reset the TWSI logic */
+	MV_REG_WRITE(TWSI_SOFT_RESET_REG(chanNum), 0);
+
+	/* wait for 2 mili sec */
+	mvOsDelay(2);
+
+	return;
+}
+
+/******************************* POLICY ****************************************/
+
+/*******************************************************************************
+* mvTwsiAddrSet - Set address on TWSI bus.
+*
+* DESCRIPTION:
+*       This function Set address (7 or 10 Bit address) on the Twsi Bus.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*       pTwsiAddr - twsi address.
+*	command	 - read / write .
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK - if setting the address completed succesfully.
+*	MV_FAIL otherwmise.
+*
+*******************************************************************************/
+MV_STATUS mvTwsiAddrSet(MV_U8 chanNum, MV_TWSI_ADDR *pTwsiAddr, MV_TWSI_CMD command)
+{
+	DB(mvOsPrintf("TWSI: mvTwsiAddr7BitSet addr %x , type %d, cmd is %s\n", pTwsiAddr->address,
+		      pTwsiAddr->type, ((command == MV_TWSI_WRITE) ? "Write" : "Read")));
+	/* 10 Bit address */
+	if (pTwsiAddr->type == ADDR10_BIT)
+		return twsiAddr10BitSet(chanNum, pTwsiAddr->address, command);
+	/* 7 Bit address */
+	else
+		return twsiAddr7BitSet(chanNum, pTwsiAddr->address, command);
+}
+
+/*******************************************************************************
+* twsiAddr10BitSet - Set 10 Bit address on TWSI bus.
+*
+* DESCRIPTION:
+*       There are two address phases:
+*       1) Write '11110' to data register bits [7:3] and 10-bit address MSB
+*          (bits [9:8]) to data register bits [2:1] plus a write(0) or read(1) bit
+*          to the Data register. Then it clears interrupt flag which drive
+*          the address on the TWSI bus. The function then waits for interrupt
+*          flag to be active and status 0x18 (write) or 0x40 (read) to be set.
+*       2) write the rest of 10-bit address to data register and clears
+*          interrupt flag which drive the address on the TWSI bus. The
+*          function then waits for interrupt flag to be active and status
+*          0xD0 (write) or 0xE0 (read) to be set.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*       deviceAddress - twsi address.
+*	command	 - read / write .
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK - if setting the address completed succesfully.
+*	MV_FAIL otherwmise.
+*
+*******************************************************************************/
+static MV_STATUS twsiAddr10BitSet(MV_U8 chanNum, MV_U32 deviceAddress, MV_TWSI_CMD command)
+{
+	MV_U32 val, timeout;
+
+	/* writing the 2 most significant bits of the 10 bit address */
+	val = ((deviceAddress & TWSI_DATA_ADDR_10BIT_MASK) >> TWSI_DATA_ADDR_10BIT_OFFS);
+	/* bits 7:3 must be 0x11110 */
+	val |= TWSI_DATA_ADDR_10BIT_CONST;
+	/* set command */
+	val |= command;
+	MV_REG_WRITE(TWSI_DATA_REG(chanNum), val);
+	/* WA add a delay */
+	mvOsDelay(1);
+
+	/* clear Int flag */
+	twsiIntFlgClr(chanNum);
+
+	/* wait for Int to be Set */
+	timeout = 0;
+	while (!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE))
+		;
+
+	/* check for timeout */
+	if (MV_TRUE ==
+	    twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: twsiAddr10BitSet ERROR - 1st addr (10Bit) Int TimeOut.\n"))
+		return MV_TIMEOUT;
+
+	/* check the status */
+	val = twsiStsGet(chanNum);
+	if (((val != TWSI_AD_PLS_RD_BIT_TRA_ACK_REC) && (command == MV_TWSI_READ)) ||
+	    ((val != TWSI_AD_PLS_WR_BIT_TRA_ACK_REC) && (command == MV_TWSI_WRITE))) {
+		mvOsPrintf("TWSI: twsiAddr10BitSet ERROR - status %x 1st addr (10 Bit) in %s mode.\n", val,
+			   ((command == MV_TWSI_WRITE) ? "Write" : "Read"));
+		return MV_FAIL;
+	}
+
+	/* set  8 LSB of the address */
+	val = (deviceAddress << TWSI_DATA_ADDR_7BIT_OFFS) & TWSI_DATA_ADDR_7BIT_MASK;
+	MV_REG_WRITE(TWSI_DATA_REG(chanNum), val);
+
+	/* clear Int flag */
+	twsiIntFlgClr(chanNum);
+
+	/* wait for Int to be Set */
+	timeout = 0;
+	while (!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE))
+		;
+
+	/* check for timeout */
+	if (MV_TRUE ==
+	    twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: twsiAddr10BitSet ERROR - 2nd (10 Bit) Int TimOut.\n"))
+		return MV_TIMEOUT;
+
+	/* check the status */
+	val = twsiStsGet(chanNum);
+	if (((val != TWSI_SEC_AD_PLS_RD_BIT_TRA_ACK_REC) && (command == MV_TWSI_READ)) ||
+	    ((val != TWSI_SEC_AD_PLS_WR_BIT_TRA_ACK_REC) && (command == MV_TWSI_WRITE))) {
+		mvOsPrintf("TWSI: twsiAddr10BitSet ERROR - status %x 2nd addr(10 Bit) in %s mode.\n", val,
+			   ((command == MV_TWSI_WRITE) ? "Write" : "Read"));
+		return MV_FAIL;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* twsiAddr7BitSet - Set 7 Bit address on TWSI bus.
+*
+* DESCRIPTION:
+*       This function writes 7 bit address plus a write or read bit to the
+*       Data register. Then it clears interrupt flag which drive the address on
+*       the TWSI bus. The function then waits for interrupt flag to be active
+*       and status 0x18 (write) or 0x40 (read) to be set.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*       deviceAddress - twsi address.
+*	command	 - read / write .
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK - if setting the address completed succesfully.
+*	MV_FAIL otherwmise.
+*
+*******************************************************************************/
+static MV_STATUS twsiAddr7BitSet(MV_U8 chanNum, MV_U32 deviceAddress, MV_TWSI_CMD command)
+{
+	MV_U32 val, timeout;
+
+	/* set the address */
+	val = (deviceAddress << TWSI_DATA_ADDR_7BIT_OFFS) & TWSI_DATA_ADDR_7BIT_MASK;
+	/* set command */
+	val |= command;
+	MV_REG_WRITE(TWSI_DATA_REG(chanNum), val);
+	/* WA add a delay */
+	mvOsDelay(1);
+
+	/* clear Int flag */
+	twsiIntFlgClr(chanNum);
+
+	/* wait for Int to be Set */
+	timeout = 0;
+	while (!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE))
+		;
+
+	/* check for timeout */
+	if (MV_TRUE ==
+	    twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: twsiAddr7BitSet ERROR - Addr (7 Bit) int TimeOut.\n"))
+		return MV_TIMEOUT;
+
+	/* check the status */
+	val = twsiStsGet(chanNum);
+	if (((val != TWSI_AD_PLS_RD_BIT_TRA_ACK_REC) && (command == MV_TWSI_READ)) ||
+	    ((val != TWSI_AD_PLS_WR_BIT_TRA_ACK_REC) && (command == MV_TWSI_WRITE))) {
+		/* only in debug, since in boot we try to read the SPD of both DRAM, and we don't
+		   want error messeges in case DIMM doesn't exist. */
+		DB(mvOsPrintf
+		   ("TWSI: twsiAddr7BitSet ERROR - status %x addr (7 Bit) in %s mode.\n", val,
+		    ((command == MV_TWSI_WRITE) ? "Write" : "Read")));
+		return MV_FAIL;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* twsiDataWrite - Trnasmit a data block over TWSI bus.
+*
+* DESCRIPTION:
+*       This function writes a given data block to TWSI bus in 8 bit granularity.
+*	first The function waits for interrupt flag to be active then
+*       For each 8-bit data:
+*        The function writes data to data register. It then clears
+*        interrupt flag which drives the data on the TWSI bus.
+*        The function then waits for interrupt flag to be active and status
+*        0x28 to be set.
+*
+*
+* INPUT:
+*	chanNum - TWSI channel
+*       pBlock - Data block.
+*	blockSize - number of chars in pBlock.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK - if transmiting the block completed succesfully,
+*	MV_BAD_PARAM - if pBlock is NULL,
+*	MV_FAIL otherwmise.
+*
+*******************************************************************************/
+static MV_STATUS twsiDataTransmit(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize)
+{
+	MV_U32 timeout, temp, blockSizeWr = blockSize;
+
+	if (NULL == pBlock)
+		return MV_BAD_PARAM;
+
+	/* wait for Int to be Set */
+	timeout = 0;
+	while (!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE))
+		;
+
+	/* check for timeout */
+	if (MV_TRUE ==
+	    twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: twsiDataTransmit ERROR - Read Data Int TimeOut.\n"))
+		return MV_TIMEOUT;
+
+	while (blockSizeWr) {
+		/* write the data */
+		MV_REG_WRITE(TWSI_DATA_REG(chanNum), (MV_U32) *pBlock);
+		DB(mvOsPrintf("TWSI: twsiDataTransmit place = %d write %x \n", blockSize - blockSizeWr, *pBlock));
+		pBlock++;
+		blockSizeWr--;
+
+		twsiIntFlgClr(chanNum);
+
+		/* wait for Int to be Set */
+		timeout = 0;
+		while (!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE))
+			;
+
+		/* check for timeout */
+		if (MV_TRUE ==
+		    twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: twsiDataTransmit ERROR - Read Data Int TimeOut.\n"))
+			return MV_TIMEOUT;
+
+		/* check the status */
+		temp = twsiStsGet(chanNum);
+		if (temp != TWSI_M_TRAN_DATA_BYTE_ACK_REC) {
+			mvOsPrintf("TWSI: twsiDataTransmit ERROR - status %x in write trans\n", temp);
+			return MV_FAIL;
+		}
+
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* twsiDataReceive - Receive data block from TWSI bus.
+*
+* DESCRIPTION:
+*       This function receive data block from TWSI bus in 8bit granularity
+*       into pBlock buffer.
+*	first The function waits for interrupt flag to be active then
+*       For each 8-bit data:
+*        It clears the interrupt flag which allows the next data to be
+*        received from TWSI bus.
+*	 The function waits for interrupt flag to be active,
+*	 and status reg is 0x50.
+*	 Then the function reads data from data register, and copies it to
+*	 the given buffer.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*       blockSize - number of bytes to read.
+*
+* OUTPUT:
+*       pBlock - Data block.
+*
+* RETURN:
+*       MV_OK - if receive transaction completed succesfully,
+*	MV_BAD_PARAM - if pBlock is NULL,
+*	MV_FAIL otherwmise.
+*
+*******************************************************************************/
+static MV_STATUS twsiDataReceive(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize)
+{
+	MV_U32 timeout, temp, blockSizeRd = blockSize;
+
+	if (NULL == pBlock)
+		return MV_BAD_PARAM;
+
+	/* wait for Int to be Set */
+	timeout = 0;
+	while (!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE))
+		;
+
+	/* check for timeout */
+	if (MV_TRUE ==
+	    twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: twsiDataReceive ERROR - Read Data int Time out .\n"))
+		return MV_TIMEOUT;
+
+	while (blockSizeRd) {
+		if (blockSizeRd == 1) {
+			/* clear ack and Int flag */
+			temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum));
+			temp &= ~(TWSI_CONTROL_ACK);
+			MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp);
+		}
+		twsiIntFlgClr(chanNum);
+		/* wait for Int to be Set */
+		timeout = 0;
+		while ((!twsiMainIntGet(chanNum)) && (timeout++ < TWSI_TIMEOUT_VALUE))
+			;
+
+		/* check for timeout */
+		if (MV_TRUE ==
+		    twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: twsiDataReceive ERROR - Read Data Int Time out .\n"))
+			return MV_TIMEOUT;
+
+		/* check the status */
+		temp = twsiStsGet(chanNum);
+		if ((temp != TWSI_M_REC_RD_DATA_ACK_TRA) && (blockSizeRd != 1)) {
+			mvOsPrintf("TWSI: twsiDataReceive ERROR - status %x in read trans \n", temp);
+			return MV_FAIL;
+		} else if ((temp != TWSI_M_REC_RD_DATA_ACK_NOT_TRA) && (blockSizeRd == 1)) {
+			mvOsPrintf("TWSI: twsiDataReceive ERROR - status %x in Rd Terminate\n", temp);
+			return MV_FAIL;
+		}
+
+		/* read the data */
+		*pBlock = (MV_U8) MV_REG_READ(TWSI_DATA_REG(chanNum));
+		DB(mvOsPrintf("TWSI: twsiDataReceive  place %d read %x \n", blockSize - blockSizeRd, *pBlock));
+		pBlock++;
+		blockSizeRd--;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* twsiTargetOffsSet - Set TWST target offset on TWSI bus.
+*
+* DESCRIPTION:
+*       The function support TWSI targets that have inside address space (for
+*       example EEPROMs). The function:
+*       1) Convert the given offset into pBlock and size.
+*		in case the offset should be set to a TWSI slave which support
+*		more then 256 bytes offset, the offset setting will be done
+*		in 2 transactions.
+*       2) Use twsiDataTransmit to place those on the bus.
+*
+* INPUT:
+*	chanNum - TWSI channel
+*       offset - offset to be set on the EEPROM device.
+*	moreThen256 - whether the EEPROM device support more then 256 byte offset.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK - if setting the offset completed succesfully.
+*	MV_FAIL otherwmise.
+*
+*******************************************************************************/
+static MV_STATUS twsiTargetOffsSet(MV_U8 chanNum, MV_U32 offset, MV_BOOL moreThen256)
+{
+	MV_U8 offBlock[2];
+	MV_U32 offSize;
+
+	if (moreThen256 == MV_TRUE) {
+		offBlock[0] = (offset >> 8) & 0xff;
+		offBlock[1] = offset & 0xff;
+		offSize = 2;
+	} else {
+		offBlock[0] = offset & 0xff;
+		offSize = 1;
+	}
+	DB(mvOsPrintf("TWSI: twsiTargetOffsSet offSize = %x addr1 = %x addr2 = %x\n",
+		      offSize, offBlock[0], offBlock[1]));
+	return twsiDataTransmit(chanNum, offBlock, offSize);
+
+}
+
+/*******************************************************************************
+* mvTwsiRead - Read data block from a TWSI Slave.
+*
+* DESCRIPTION:
+*       The function calls the following functions:
+*       -) mvTwsiStartBitSet();
+*	if(EEPROM device)
+*       	-) mvTwsiAddrSet(w);
+*       	-) twsiTargetOffsSet();
+*       	-) mvTwsiStartBitSet();
+*       -) mvTwsiAddrSet(r);
+*       -) twsiDataReceive();
+*       -) mvTwsiStopBitSet();
+*
+* INPUT:
+*	chanNum - TWSI channel
+*      	pTwsiSlave - Twsi Slave structure.
+*       blockSize - number of bytes to read.
+*
+* OUTPUT:
+*      	pBlock - Data block.
+*
+* RETURN:
+*       MV_OK - if EEPROM read transaction completed succesfully,
+* 	MV_BAD_PARAM - if pBlock is NULL,
+*	MV_FAIL otherwmise.
+*
+*******************************************************************************/
+MV_STATUS mvTwsiRead(MV_U8 chanNum, MV_TWSI_SLAVE *pTwsiSlave, MV_U8 *pBlock, MV_U32 blockSize)
+{
+	if ((NULL == pBlock) || (NULL == pTwsiSlave))
+		return MV_BAD_PARAM;
+	if (MV_OK != mvTwsiStartBitSet(chanNum)) {
+		mvTwsiStopBitSet(chanNum);
+		return MV_FAIL;
+	}
+
+	DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStartBitSet\n"));
+
+	/* in case offset exsist (i.e. eeprom ) */
+	if (MV_TRUE == pTwsiSlave->validOffset) {
+		if (MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_WRITE)) {
+			mvTwsiStopBitSet(chanNum);
+			return MV_FAIL;
+		}
+		DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiAddrSet\n"));
+		if (MV_OK != twsiTargetOffsSet(chanNum, pTwsiSlave->offset, pTwsiSlave->moreThen256)) {
+			mvTwsiStopBitSet(chanNum);
+			return MV_FAIL;
+		}
+		DB(mvOsPrintf("TWSI: mvTwsiEepromRead after twsiTargetOffsSet\n"));
+		if (MV_OK != mvTwsiStartBitSet(chanNum)) {
+			mvTwsiStopBitSet(chanNum);
+			return MV_FAIL;
+		}
+		DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStartBitSet\n"));
+	}
+	if (MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_READ)) {
+		mvTwsiStopBitSet(chanNum);
+		return MV_FAIL;
+	}
+	DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiAddrSet\n"));
+	if (MV_OK != twsiDataReceive(chanNum, pBlock, blockSize)) {
+		mvTwsiStopBitSet(chanNum);
+		return MV_FAIL;
+	}
+	DB(mvOsPrintf("TWSI: mvTwsiEepromRead after twsiDataReceive\n"));
+
+	if (MV_OK != mvTwsiStopBitSet(chanNum))
+		return MV_FAIL;
+
+	twsiAckBitSet(chanNum);
+
+	DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStopBitSet\n"));
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvTwsiWrite - Write data block to a TWSI Slave.
+*
+* DESCRIPTION:
+*       The function calls the following functions:
+*       -) mvTwsiStartBitSet();
+*       -) mvTwsiAddrSet();
+*	-)if(EEPROM device)
+*       	-) twsiTargetOffsSet();
+*       -) twsiDataTransmit();
+*       -) mvTwsiStopBitSet();
+*
+* INPUT:
+*	chanNum - TWSI channel
+*      	eepromAddress - eeprom address.
+*       blockSize - number of bytes to write.
+*      	pBlock - Data block.
+*
+* OUTPUT:
+*	None
+*
+* RETURN:
+*       MV_OK - if EEPROM read transaction completed succesfully.
+*	MV_BAD_PARAM - if pBlock is NULL,
+*	MV_FAIL otherwmise.
+*
+* NOTE: Part of the EEPROM, required that the offset will be aligned to the
+*	max write burst supported.
+*******************************************************************************/
+MV_STATUS mvTwsiWrite(MV_U8 chanNum, MV_TWSI_SLAVE *pTwsiSlave, MV_U8 *pBlock, MV_U32 blockSize)
+{
+	if ((NULL == pBlock) || (NULL == pTwsiSlave))
+		return MV_BAD_PARAM;
+
+	if (MV_OK != mvTwsiStartBitSet(chanNum)) {
+		mvTwsiStopBitSet(chanNum);
+		return MV_FAIL;
+	}
+
+	DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after mvTwsiStartBitSet\n"));
+	if (MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_WRITE)) {
+		mvTwsiStopBitSet(chanNum);
+		return MV_FAIL;
+	}
+	DB(mvOsPrintf("TWSI :mvTwsiEepromWrite after mvTwsiAddrSet\n"));
+
+	/* in case offset exsist (i.e. eeprom ) */
+	if (MV_TRUE == pTwsiSlave->validOffset) {
+		if (MV_OK != twsiTargetOffsSet(chanNum, pTwsiSlave->offset, pTwsiSlave->moreThen256)) {
+			mvTwsiStopBitSet(chanNum);
+			return MV_FAIL;
+		}
+		DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after twsiTargetOffsSet\n"));
+	}
+	if (MV_OK != twsiDataTransmit(chanNum, pBlock, blockSize)) {
+		mvTwsiStopBitSet(chanNum);
+		return MV_FAIL;
+	}
+	DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after twsiDataTransmit\n"));
+	if (MV_OK != mvTwsiStopBitSet(chanNum))
+		return MV_FAIL;
+
+	DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after mvTwsiStopBitSet\n"));
+
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsi.h b/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsi.h
new file mode 100755
index 0000000..185eb58
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsi.h
@@ -0,0 +1,116 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __INCmvTwsiH
+#define __INCmvTwsiH
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysTwsiConfig.h"
+
+/* The TWSI interface supports both 7-bit and 10-bit addressing.            */
+/* This enumerator describes addressing type.                               */
+typedef enum _mvTwsiAddrType {
+    ADDR7_BIT,                      /* 7 bit address    */
+    ADDR10_BIT                      /* 10 bit address   */
+} MV_TWSI_ADDR_TYPE;
+
+/* This structure describes TWSI address.                                   */
+typedef struct _mvTwsiAddr {
+    MV_U32              address;    /* address          */
+    MV_TWSI_ADDR_TYPE   type;       /* Address type     */
+} MV_TWSI_ADDR;
+
+/* This structure describes a TWSI slave.                                   */
+typedef struct _mvTwsiSlave {
+    MV_TWSI_ADDR	slaveAddr;
+    MV_BOOL 		validOffset;		/* whether the slave has offset (i.e. Eeprom  etc.) 	*/
+    MV_U32		offset;		/* offset in the slave.					*/
+    MV_BOOL 		moreThen256;	/* whether the ofset is bigger then 256 		*/
+} MV_TWSI_SLAVE;
+
+/* This enumerator describes TWSI protocol commands.                        */
+typedef enum _mvTwsiCmd {
+    MV_TWSI_WRITE,   /* TWSI write command - 0 according to spec   */
+    MV_TWSI_READ   /* TWSI read command  - 1 according to spec */
+} MV_TWSI_CMD;
+
+MV_STATUS mvTwsiStartBitSet(MV_U8 chanNum);
+MV_STATUS mvTwsiStopBitSet(MV_U8 chanNum);
+MV_STATUS mvTwsiAddrSet(MV_U8 chanNum, MV_TWSI_ADDR *twsiAddr, MV_TWSI_CMD command);
+
+MV_U32 mvTwsiInit(MV_U8 chanNum, MV_KHZ frequency, MV_U32 Tclk, MV_TWSI_ADDR *twsiAddr, MV_BOOL generalCallEnable);
+MV_STATUS mvTwsiRead(MV_U8 chanNum, MV_TWSI_SLAVE *twsiSlave, MV_U8 *pBlock, MV_U32 blockSize);
+MV_STATUS mvTwsiWrite(MV_U8 chanNum, MV_TWSI_SLAVE *twsiSlave, MV_U8 *pBlock, MV_U32 blockSize);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INCmvTwsiH */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsiEeprom.S b/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsiEeprom.S
new file mode 100755
index 0000000..7b62838
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsiEeprom.S
@@ -0,0 +1,453 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+/* includes */
+#define MV_ASMLANGUAGE
+#include "mvCommon.h"
+#include "mvOsAsm.h"
+#include "mvCtrlEnvSpec.h"
+#include "mvSysTwsiConfig.h"
+#include "mvTwsiSpec.h"
+#include "boardEnv/mvBoardEnvSpec.h"
+
+#define I2C_CH MV_BOARD_DIMM_I2C_CHANNEL
+
+#define CPUIF_REGS_BASE		INTER_REGS_BASE + 0x20000
+#define CPU_MAIN_INT_CAUSE_REG  (CPUIF_REGS_BASE + 0x200)
+
+
+/* defines */
+/* defines  */
+
+
+        .data
+        .global _i2cInit
+        .global _i2cRead
+
+        .text
+
+/*******************************************************************************
+* _i2cInit - Initialize TWSI interface
+*
+* DESCRIPTION:
+*       The function performs TWSI interface initialization. It resets the
+*       TWSI state machine and initialize its clock to 100KHz assuming Tclock
+*       of 133MHz.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+_i2cInit:
+        mov     r9, LR     /* Save link register */
+        mov     r0, #0     /* Make sure r0 is zero */
+
+        /* Reset the i2c Mechanism first */
+        MV_REG_WRITE_ASM (r0, r1, TWSI_SOFT_RESET_REG(I2C_CH))
+
+        bl      _twsiDelay
+        bl      _twsiDelay
+
+        /* Initializing the I2C mechanism. Assuming Tclock frequency          */
+        /* of 166MHz. The I2C frequency in that case will be 100KHz.          */
+        /* For this settings, M = 9 and N = 3. Set the baud-rate with the     */
+        /* value of 0x2b (freq of ==> 100KHz                                  */
+        /* see spec for more details about the calculation of this value)     */
+        mov     r6, #(9 << 3 | 3)
+        MV_REG_WRITE_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
+
+        /* Enable the I2C master */
+	/* Enable TWSI interrupt in main mask reg */
+        mov     r6, #0xC4
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+
+        /* Let the slow TWSI machine get used to the idea that it is enabled  */
+        bl      _twsiDelay
+
+        mov     PC, r9         /* r9 is saved link register */
+
+/*******************************************************************************
+* _twsiDelay - Perform delay.
+*
+* DESCRIPTION:
+*       The function performs a delay to enable TWSI logic to stable.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+_twsiDelay:
+        mov     r10, #0x100000 /*was 0x400*/
+
+_twsiDelayLoop:
+        subs    r10, r10, #1
+        bne     _twsiDelayLoop
+
+        mov     PC, LR
+
+/*******************************************************************************
+* _i2cRead - Read byte from I2C EEPROM device.
+*
+* DESCRIPTION:
+*       The function returns a byte from I2C EEPROM device.
+*       The EEPROM device is 7-bit address type.
+*
+* INPUT:
+*       r4 has the DIMM0 base address with shift 1 bit to the left
+*       r7 has the EEPROM offset
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       r4 returns '0' if address can not be read.
+*       r7 has byte value in case read is successful.
+*
+*******************************************************************************/
+_i2cRead:
+        mov     r9, LR     /* Save link register */
+
+        /* Transmit the device address and desired offset within the EEPROM. */
+
+        /* Generate Start Bit */
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        orr     r6, r6, #TWSI_CONTROL_START_BIT
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+
+        /* Wait for the interrupt flag (bit3) to be set  */
+        mov     r10, #0x50000
+loop_1:
+        subs    r10, r10, #1
+        beq     loop_1_timeout
+#ifdef MV78XX0
+        MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
+        tst     r6, #BIT2
+#else
+        MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
+        tst     r6, #BIT5
+#endif
+        beq     loop_1
+
+loop_1_timeout:
+
+        /* Wait for the start bit to be reset by HW */
+        mov     r10, #0x50000
+loop_2:
+        subs    r10, r10, #1
+        beq     loop_2_timeout
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        tst     r6, #TWSI_CONTROL_START_BIT
+        bne     loop_2
+
+loop_2_timeout:
+
+        /* Wait for the status TWSI_START_CONDITION_TRA = 0x8 */
+        mov     r10, #0x50000
+loop_3:
+        subs    r10, r10, #1
+        beq     loop_3_timeout
+        MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
+        cmp     r6, #0x08
+        bne     loop_3
+
+loop_3_timeout:
+
+        /* writing the address of (DIMM0/1 << 1) with write indication */
+        mov     r6, r4, LSL #1 /* Write operation address bit 0 must be 0 */
+        MV_REG_WRITE_ASM (r6, r1, TWSI_DATA_REG(I2C_CH))
+
+        bl      _twsiDelay
+        /* Clear the interrupt flag */
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bl      _twsiDelay
+
+        /* Waiting for the interrupt flag to be set which means that the
+           address has been transmitted                                  */
+loop_4:
+#ifdef MV78XX0
+        MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
+        tst     r6, #BIT2
+#else
+        MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
+        tst     r6, #BIT5
+#endif
+        beq     loop_4       /* if tst = 0, then the bit is not set yet */
+
+        /* Wait for status TWSI_ADDR_PLUS_WRITE_BIT_TRA_ACK_REC = 0x18 */
+        mov     r10, #0x50000         /* Set r10 to 0x50000 =~ 328,000 */
+
+loop_5:
+        subs    r10, r10, #1          /* timeout count down         */
+        bne     testStatus
+        mov     r4, #0                /* r4 = 0 -> operation failed */
+        b       exit_i2cRead          /* Exit if timeout (No DIMM)  */
+
+testStatus:
+        MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
+        cmp     r6, #0x18
+        bne     loop_5
+
+        /* check if the offset is bigger than 256 byte*/
+        tst     r7, #0x80000000
+        bne     great_than_256
+
+        /* Write the offset to be read from the DIMM EEPROM */
+        MV_REG_WRITE_ASM (r7, r1, TWSI_DATA_REG(I2C_CH))
+
+        b after_offset
+
+great_than_256:
+        mov     r10, r7, LSR #8
+        and     r10, r10, #0xff
+        /* Write the offset0 to be read from the  EEPROM */
+        MV_REG_WRITE_ASM (r10, r1, TWSI_DATA_REG(I2C_CH))
+
+        /* Clear the interrupt flag ==> signaling that the address can now
+           be transmited                                                    */
+
+        bl      _twsiDelay
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bl      _twsiDelay
+
+        /* Wait for the interrupt to be set again ==> address has transmited */
+loop_6_1:
+#ifdef MV78XX0
+        MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
+        tst     r6, #BIT2
+#else
+        MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
+        tst     r6, #BIT5
+#endif
+        beq     loop_6_1
+
+        /* Wait for status TWSI_MAS_TRAN_DATA_BYTE_ACK_REC = 0x28 */
+loop_7_1:
+        MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
+        cmp     r6, #0x28
+        bne     loop_7_1
+
+        mov     r10, r7
+        and     r10, r10, #0xff
+        /* Write the offset1 to be read from the  EEPROM */
+        MV_REG_WRITE_ASM (r10, r1, TWSI_DATA_REG(I2C_CH))
+
+after_offset:
+
+        /* Clear the interrupt flag ==> signaling that the address can now
+           be transmited                                                    */
+
+        bl      _twsiDelay
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bl      _twsiDelay
+
+        /* Wait for the interrupt to be set again ==> address has transmited */
+loop_6:
+#ifdef MV78XX0
+        MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
+        tst     r6, #BIT2
+#else
+        MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
+        tst     r6, #BIT5
+#endif
+        beq     loop_6
+
+        /* Wait for status TWSI_MAS_TRAN_DATA_BYTE_ACK_REC = 0x28 */
+loop_7:
+        MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
+        cmp     r6, #0x28
+        bne     loop_7
+
+        /* Retransmit the device address with read indication to get the data */
+
+        /* generate a repeated start bit */
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        orr     r6, r6, #TWSI_CONTROL_START_BIT
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+
+        /* Clear the interrupt flag ==> the start bit will be transmitted. */
+        bl      _twsiDelay
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bl      _twsiDelay
+
+       /* Wait for the interrupt flag (bit3) to be set */
+loop_9:
+#ifdef MV78XX0
+        MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
+        tst     r6, #BIT2
+#else
+        MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
+        tst     r6, #BIT5
+#endif
+        beq     loop_9
+
+        /* Wait for the start bit to be reset by HW */
+loop_8:
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        tst     r6, #TWSI_CONTROL_START_BIT
+        bne     loop_8
+
+        /* Wait for status TWSI_REPEATED_START_CONDITION_TRA = 0x10 */
+loop_10:
+        MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
+        cmp     r6, #0x10
+        bne     loop_10
+
+        /* Writing the address of (DIMM0<<1) with read indication (bit0 is 1) */
+        mov     r6, r4, LSL #1
+        orr     r6, r6, #1     /* Read operation address bit 0 must be 1 */
+        MV_REG_WRITE_ASM (r6, r1, TWSI_DATA_REG(I2C_CH))
+
+        /* Clear the interrupt flag ==> the address will be transmitted */
+        bl      _twsiDelay
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bl      _twsiDelay
+
+        /* Wait for the interrupt flag (bit3) to be set as a result of
+           transmitting the address.                                     */
+loop_11:
+#ifdef MV78XX0
+        MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
+        tst     r6, #BIT2
+#else
+        MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
+        tst     r6, #BIT5
+#endif
+        beq     loop_11
+
+         /* Wait for status TWSI_ADDR_PLUS_READ_BIT_TRA_ACK_REC = 0x40 */
+loop_12:
+        MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
+        cmp     r6, #0x40
+        bne     loop_12
+
+        /* Clear the interrupt flag and the Acknoledge bit */
+        bl      _twsiDelay
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bic     r6, r6, #(TWSI_CONTROL_INT_FLAG_SET | TWSI_CONTROL_ACK)
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bl      _twsiDelay
+
+        /* Wait for the interrupt flag (bit3) to be set */
+loop_14:
+#ifdef MV78XX0
+        MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH))
+        tst     r6, #BIT2
+#else
+        MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG)
+        tst     r6, #BIT5
+#endif
+        beq     loop_14
+
+        /* Wait for status TWSI_MAS_REC_READ_DATA_ACK_NOT_TRA = 0x58 */
+loop_15:
+        MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH))
+        cmp     r6, #0x58
+        bne     loop_15
+
+        /* Store the data in r7. */
+        MV_REG_READ_ASM (r7, r1, TWSI_DATA_REG(I2C_CH))
+
+        /* Generate stop bit */
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        orr     r6, r6, #TWSI_CONTROL_STOP_BIT
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+
+        /* Clear the interrupt flag  */
+        bl      _twsiDelay
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bic     r6, r6, #TWSI_CONTROL_INT_FLAG_SET
+        MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        bl      _twsiDelay
+
+        /* Wait for the stop bit to be reset by HW */
+loop_16:
+        MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH))
+        tst     r6, #TWSI_CONTROL_INT_FLAG_SET
+        bne     loop_16
+
+exit_i2cRead:
+        mov     PC, r9         /* r9 is saved link register */
diff --git a/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsiSpec.h b/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsiSpec.h
new file mode 100755
index 0000000..d1481ed
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/twsi/mvTwsiSpec.h
@@ -0,0 +1,166 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+/****************************************/
+/* TWSI Registers                        */
+/****************************************/
+#ifndef __INCmvTwsiSpech
+#define __INCmvTwsiSpech
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysTwsiConfig.h"
+
+/* defines */
+#define CPU_LCD_TWSI_CONFIG_1_REG		(INTER_REGS_BASE + 0xE802C)
+#define CPU_LCD_TWSI_CONFIG_2_REG		(INTER_REGS_BASE + 0xE8030)
+
+#define TWSI_SLAVE_ADDR_REG(chanNum)	(MV_TWSI_SLAVE_REGS_BASE(chanNum) + 0x00)
+
+#define TWSI_SLAVE_ADDR_GCE_ENA		BIT0
+#define TWSI_SLAVE_ADDR_7BIT_OFFS	0x1
+#define TWSI_SLAVE_ADDR_7BIT_MASK 	(0xFF << TWSI_SLAVE_ADDR_7BIT_OFFS)
+#define TWSI_SLAVE_ADDR_10BIT_OFFS	0x7
+#define TWSI_SLAVE_ADDR_10BIT_MASK 	0x300
+#define	TWSI_SLAVE_ADDR_10BIT_CONST 	0xF0
+
+
+#define TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum)	(MV_TWSI_SLAVE_REGS_BASE(chanNum) + 0x10)
+#define TWSI_EXTENDED_SLAVE_OFFS 	0
+#define TWSI_EXTENDED_SLAVE_MASK	(0xFF << TWSI_EXTENDED_SLAVE_OFFS)
+
+
+#define TWSI_DATA_REG(chanNum)		(MV_TWSI_SLAVE_REGS_BASE(chanNum) + 0x04)
+#define TWSI_DATA_COMMAND_OFFS		0x0
+#define TWSI_DATA_COMMAND_MASK 		(0x1 << TWSI_DATA_COMMAND_OFFS)
+#define TWSI_DATA_COMMAND_WR		(0x1 << TWSI_DATA_COMMAND_OFFS)
+#define TWSI_DATA_COMMAND_RD		(0x0 << TWSI_DATA_COMMAND_OFFS)
+#define TWSI_DATA_ADDR_7BIT_OFFS	0x1
+#define TWSI_DATA_ADDR_7BIT_MASK 	(0xFF << TWSI_DATA_ADDR_7BIT_OFFS)
+#define TWSI_DATA_ADDR_10BIT_OFFS	0x7
+#define TWSI_DATA_ADDR_10BIT_MASK	0x300
+#define TWSI_DATA_ADDR_10BIT_CONST	0xF0
+
+
+#define TWSI_CONTROL_REG(chanNum)	(MV_TWSI_SLAVE_REGS_BASE(chanNum) + 0x08)
+#define TWSI_CONTROL_ACK            	BIT2
+#define TWSI_CONTROL_INT_FLAG_SET   	BIT3
+#define TWSI_CONTROL_STOP_BIT    	BIT4
+#define TWSI_CONTROL_START_BIT 		BIT5
+#define TWSI_CONTROL_ENA     		BIT6
+#define TWSI_CONTROL_INT_ENA    	BIT7
+
+
+#define TWSI_STATUS_BAUDE_RATE_REG(chanNum)	(MV_TWSI_SLAVE_REGS_BASE(chanNum) + 0x0c)
+#define TWSI_BAUD_RATE_N_OFFS		0
+#define TWSI_BAUD_RATE_N_MASK		(0x7 << TWSI_BAUD_RATE_N_OFFS)
+#define TWSI_BAUD_RATE_M_OFFS   	3
+#define TWSI_BAUD_RATE_M_MASK  		(0xF << TWSI_BAUD_RATE_M_OFFS)
+
+#define TWSI_SOFT_RESET_REG(chanNum)	(MV_TWSI_SLAVE_REGS_BASE(chanNum) + 0x1c)
+
+/* defines */
+#define TWSI_TIMEOUT_VALUE 		0x500
+
+/* TWSI status codes */
+#define TWSI_BUS_ERROR                                            0x00
+#define TWSI_START_CON_TRA                                        0x08
+#define TWSI_REPEATED_START_CON_TRA                               0x10
+#define TWSI_AD_PLS_WR_BIT_TRA_ACK_REC                            0x18
+#define TWSI_AD_PLS_WR_BIT_TRA_ACK_NOT_REC                        0x20
+#define TWSI_M_TRAN_DATA_BYTE_ACK_REC                             0x28
+#define TWSI_M_TRAN_DATA_BYTE_ACK_NOT_REC                         0x30
+#define TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA                        0x38
+#define TWSI_AD_PLS_RD_BIT_TRA_ACK_REC                            0x40
+#define TWSI_AD_PLS_RD_BIT_TRA_ACK_NOT_REC                        0x48
+#define TWSI_M_REC_RD_DATA_ACK_TRA                                0x50
+#define TWSI_M_REC_RD_DATA_ACK_NOT_TRA                            0x58
+#define TWSI_SLA_REC_AD_PLS_WR_BIT_ACK_TRA                        0x60
+#define TWSI_M_LOST_ARB_DUR_AD_TRA_AD_IS_TRGT_TO_SLA_ACK_TRA_W    0x68
+#define TWSI_GNL_CALL_REC_ACK_TRA                                 0x70
+#define TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA        0x78
+#define TWSI_SLA_REC_WR_DATA_AF_REC_SLA_AD_ACK_TRAN               0x80
+#define TWSI_SLA_REC_WR_DATA_AF_REC_SLA_AD_ACK_NOT_TRAN           0x88
+#define TWSI_SLA_REC_WR_DATA_AF_REC_GNL_CALL_ACK_TRAN             0x90
+#define TWSI_SLA_REC_WR_DATA_AF_REC_GNL_CALL_ACK_NOT_TRAN         0x98
+#define TWSI_SLA_REC_STOP_OR_REPEATED_STRT_CON                    0xA0
+#define TWSI_SLA_REC_AD_PLS_RD_BIT_ACK_TRA                        0xA8
+#define TWSI_M_LOST_ARB_DUR_AD_TRA_AD_IS_TRGT_TO_SLA_ACK_TRA_R    0xB0
+#define TWSI_SLA_TRA_RD_DATA_ACK_REC                              0xB8
+#define TWSI_SLA_TRA_RD_DATA_ACK_NOT_REC                          0xC0
+#define TWSI_SLA_TRA_LAST_RD_DATA_ACK_REC                         0xC8
+#define TWSI_SEC_AD_PLS_WR_BIT_TRA_ACK_REC                        0xD0
+#define TWSI_SEC_AD_PLS_WR_BIT_TRA_ACK_NOT_REC                    0xD8
+#define TWSI_SEC_AD_PLS_RD_BIT_TRA_ACK_REC                        0xE0
+#define TWSI_SEC_AD_PLS_RD_BIT_TRA_ACK_NOT_REC                    0xE8
+#define TWSI_NO_REL_STS_INT_FLAG_IS_KEPT_0                        0xF8
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INCmvTwsiSpech */
diff --git a/arch/arm/plat-feroceon/mv_hal/uart/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/uart/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/uart/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/uart/mvUart.c b/arch/arm/plat-feroceon/mv_hal/uart/mvUart.c
new file mode 100755
index 0000000..a2ad05b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/uart/mvUart.c
@@ -0,0 +1,305 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvUart.h"
+
+/* static variables */
+static volatile MV_UART_PORT *uartBase[MV_UART_MAX_CHAN];
+
+/*******************************************************************************
+* mvUartInit - Init a uart port.
+*
+* DESCRIPTION:
+*       This routine Initialize one of the uarts ports (channels).
+*	It initialize the baudrate, stop bit,parity bit etc.
+*
+* INPUT:
+*       port - uart port number.
+*	baudDivisor - baud divisior to use for the uart port.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvUartInit(MV_U32 port, MV_U32 baudDivisor, MV_UART_PORT *base)
+{
+	volatile MV_UART_PORT *pUartPort;
+
+#if defined(MV_UART_OVER_PEX_WA) || defined(MV_UART_OVER_PCI_WA)
+	uartBase[port] = pUartPort = (volatile MV_UART_PORT *)(base);
+	return;
+#else
+	uartBase[port] = pUartPort = (volatile MV_UART_PORT *)base;
+
+	pUartPort->ier = 0x00;
+	pUartPort->lcr = LCR_DIVL_EN;	/* Access baud rate */
+	pUartPort->dll = baudDivisor & 0xff;	/* 9600 baud */
+	pUartPort->dlm = (baudDivisor >> 8) & 0xff;
+	pUartPort->lcr = LCR_8N1;	/* 8 data, 1 stop, no parity */
+
+	/* Clear & enable FIFOs */
+	pUartPort->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR;
+	return;
+#endif
+}
+
+#ifdef MV78XX0
+#define UART_EXTERNAL_CONTROL_REG			0x10700
+/*******************************************************************************
+* mvUartDmaInit - Init a uart port in DMA mode.
+*
+* DESCRIPTION:
+*       This routine Initialize one of the uart ports (channels) to use DMA mode
+*	    for transmission. It initialize the baudrate, stop bit,parity bit etc.
+*       It also initializes IDMA channel 0 for UART transmission.
+*       Once DMA based UART is configured IDMA channel 0 must not be used elsewhere.
+*
+* INPUT:
+*       port - uart port number.
+*	    baudDivisor - baud divisior to use for the uart port.
+*       idmaWinNum - The IDMA BAR to use for UART transfer (must be 1-3)
+*       srcBurstSize - the IDMA source burst size (8,16,32,64,128)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvUartDmaInit(MV_U32 port, MV_U32 baudDivisor, MV_UART_PORT *base, MV_U32 idmaWinNum, MV_U32 srcBurstSize)
+{
+	volatile MV_UART_PORT *pUartPort;
+	MV_U32 srcBurstLim;
+
+	/*set the UART channel to use the IDMA */
+	MV_REG_BIT_SET(UART_EXTERNAL_CONTROL_REG, BIT0 | (BIT8 << port));
+
+	uartBase[port] = pUartPort = (volatile MV_UART_PORT *)base;
+	mvUartInit(port, baudDivisor, base);
+
+	pUartPort->mcr = MCR_AFCE;	/* Enable Auto flow control */
+	/* Set IDMA BAR target to UART */
+	MV_REG_BIT_RESET(IDMA_BASE_ADDR_REG(idmaWinNum), 0xffff);
+	MV_REG_BIT_SET(IDMA_BASE_ADDR_REG(idmaWinNum), 0x0101);	/*Set BAR to UART */
+
+	/* Set IDMA0 channel to UART mode */
+	switch (srcBurstSize) {
+	case 8:
+		srcBurstLim = ICCLR_SRC_BURST_LIM_8BYTE;
+		break;
+	case 16:
+		srcBurstLim = ICCLR_SRC_BURST_LIM_16BYTE;
+		break;
+	case 32:
+		srcBurstLim = ICCLR_SRC_BURST_LIM_32BYTE;
+		break;
+	case 64:
+		srcBurstLim = ICCLR_SRC_BURST_LIM_64BYTE;
+		break;
+	case 128:
+		srcBurstLim = ICCLR_SRC_BURST_LIM_128BYTE;
+		break;
+	default:
+		mvOsPrintf("mvUartDmaInit:ERR. Illegal source burst limit, \
+	setting to 128B default\n");
+		srcBurstLim = ICCLR_SRC_BURST_LIM_128BYTE;
+		break;
+	}
+	mvDmaCtrlLowSet(0, 0x18220 | srcBurstLim);	/*channel control low according FS */
+	mvDmaOverrideSet(0, idmaWinNum, DMA_DST_ADDR);
+	return;
+}
+
+/*******************************************************************************
+* mvUartDmaTransmit - Transmit a buffer over the UART using the IDMA.
+*
+* DESCRIPTION:
+*       This routine transmits a buffer over the UART port using IDMA0.
+*
+* INPUT:
+*       port - uart port number.
+*	    byteCount - The total number of bytes to be transferred to the UART.
+*       srcAddr - The source address of the buffer to be transferred.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	    MV_OK.
+*
+*******************************************************************************/
+MV_STATUS mvUartDmaTransmit(MV_U32 port, MV_U32 byteCount, MV_U32 srcAddr)
+{
+	MV_U32 dstAddr, tmp;
+
+	/* Verify IDMA 0 is not busy */
+	if (mvDmaStateGet(port) != MV_IDLE) {
+		mvOsPrintf("mvUartDmaTransmit: ERR. IDMA 0 busy.\n");
+		return MV_ERROR;
+	}
+
+	/* Verify byte count is legal, and choose either 64K mode or 16M mode */
+	if (byteCount >= 0x1000000) {
+		mvOsPrintf("mvUartDmaTransmit: ERR. Illegal Byte count.\n");
+		return MV_ERROR;
+	} else if (byteCount >= 0x10000) {
+		byteCount |= BIT31;
+		MV_REG_BIT_SET(IDMA_CTRL_LOW_REG(0), BIT31);
+	} else
+		MV_REG_BIT_RESET(IDMA_CTRL_LOW_REG(0), BIT31);
+
+	/* Calculate UART destination address from assigned BAR */
+	tmp = MV_REG_READ(IDMA_CTRL_LOW_REG(0));
+	tmp = (tmp >> 23) & 0x3;	/* Extract the destination override window number */
+
+	/* Check that destination BAR is configured and calculate destination address */
+	if ((MV_REG_READ(IDMA_BASE_ADDR_REG(tmp)) & 0xffff) != 0x0101) {
+		mvOsPrintf("mvUartDmaTransmit: ERR. IDMA UART BAR isn't configured.\n");
+		return MV_ERROR;
+	} else
+		dstAddr = (MV_REG_READ(IDMA_BASE_ADDR_REG(tmp)) & 0xffff0000) | (port << 8);
+
+	/* Start transfer */
+	if (mvDmaTransfer(0, srcAddr, dstAddr, byteCount, 0x0) == MV_OK)
+		return MV_OK;
+	else
+		return MV_ERROR;
+}
+#endif /* MV78XX0 */
+/*******************************************************************************
+* mvUartPutc - Send char to the uart port.
+*
+* DESCRIPTION:
+*       This routine puts one charachetr on one of the uart ports.
+*
+* INPUT:
+*       port - uart port number.
+*	c - character.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_VOID mvUartPutc(MV_U32 port, MV_U8 c)
+{
+	volatile MV_UART_PORT *pUartPort = uartBase[port];
+	while ((pUartPort->lsr & LSR_THRE) == 0)
+		;
+	pUartPort->thr = c;
+	return;
+}
+
+/*******************************************************************************
+* mvUartGetc - Get char from uart port.
+*
+* DESCRIPTION:
+*       This routine gets one charachetr from one of the uart ports.
+*
+* INPUT:
+*       port - uart port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	carachter from the uart port.
+*
+*******************************************************************************/
+MV_U8 mvUartGetc(MV_U32 port)
+{
+	volatile MV_UART_PORT *pUartPort = uartBase[port];
+	while ((pUartPort->lsr & LSR_DR) == 0)
+		;
+	return (pUartPort->rbr);
+}
+
+/*******************************************************************************
+* mvUartTstc - test for char in uart port.
+*
+* DESCRIPTION:
+*       This routine heck if a charachter is ready to be read from one of the
+*	the uart ports.
+*
+* INPUT:
+*       port - uart port number.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*	None.
+*
+*******************************************************************************/
+MV_BOOL mvUartTstc(MV_U32 port)
+{
+	volatile MV_UART_PORT *pUartPort = uartBase[port];
+	return ((pUartPort->lsr & LSR_DR) != 0);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/uart/mvUart.h b/arch/arm/plat-feroceon/mv_hal/uart/mvUart.h
new file mode 100755
index 0000000..a16c7a9
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/uart/mvUart.h
@@ -0,0 +1,164 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+
+#ifndef __NS16550_H__
+#define __NS16550_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+#ifdef MV78XX0
+#include "idma/mvIdma.h"
+#include "ctrlEnv/sys/mvSysIdma.h"
+#endif
+/* This structure describes the registers offsets for one UART port(channel) */
+	typedef struct mvUartPort {
+		MV_U8 rbr;	/* 0 = 0-3 */
+		MV_U8 pad1[3];
+
+		MV_U8 ier;	/* 1 = 4-7 */
+		MV_U8 pad2[3];
+
+		MV_U8 fcr;	/* 2 = 8-b */
+		MV_U8 pad3[3];
+
+		MV_U8 lcr;	/* 3 = c-f */
+		MV_U8 pad4[3];
+
+		MV_U8 mcr;	/* 4 = 10-13 */
+		MV_U8 pad5[3];
+
+		MV_U8 lsr;	/* 5 = 14-17 */
+		MV_U8 pad6[3];
+
+		MV_U8 msr;	/* 6 =18-1b */
+		MV_U8 pad7[3];
+
+		MV_U8 scr;	/* 7 =1c-1f */
+		MV_U8 pad8[3];
+	} MV_UART_PORT;
+
+#if defined(MV_UART_OVER_PEX_WA) || defined(MV_UART_OVER_PCI_WA)
+#define mvUartBase(port)  \
+		((MV_UART_PORT *)(0xF2000000 + MV_UART_REGS_OFFSET(port)))
+#else
+#define mvUartBase(port)  \
+		((MV_UART_PORT *)(INTER_REGS_BASE + MV_UART_REGS_OFFSET(port)))
+#endif
+
+/* aliases - for registers which has the same offsets */
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+
+/* registers feilds */
+#define FCR_FIFO_EN     	BIT0	/* fifo enable */
+#define FCR_RXSR        	BIT1	/* reciever soft reset */
+#define FCR_TXSR        	BIT2	/* transmitter soft reset */
+
+#define MCR_RTS         	BIT1	/* ready to send */
+#define MCR_AFCE         	BIT5	/* Auto Flow Control Enable */
+
+#define LCR_WLS_OFFS		0
+#define LCR_WLS_MASK 		(0x3 << LCR_WLS_OFFS)	/* character length mask  */
+#define LCR_WLS_5   		(0x0 << LCR_WLS_OFFS)	/* 5 bit character length */
+#define LCR_WLS_6   		(0x1 << LCR_WLS_OFFS)	/* 6 bit character length */
+#define LCR_WLS_7   		(0x2 << LCR_WLS_OFFS)	/* 7 bit character length */
+#define LCR_WLS_8   		(0x3 << LCR_WLS_OFFS)	/* 8 bit character length */
+#define LCR_STP_OFFS		2
+#define LCR_1_STB     		(0x0 << LCR_STP_OFFS)	/* Number of stop Bits */
+#define LCR_2_STB     		(0x1 << LCR_STP_OFFS)	/* Number of stop Bits */
+#define LCR_PEN     		0x8	/* Parity eneble */
+#define LCR_PS_OFFS		4
+#define LCR_EPS     		(0x1 << LCR_PS_OFFS)	/* Even Parity Select */
+#define LCR_OPS     		(0x0 << LCR_PS_OFFS)	/* Odd Parity Select */
+#define LCR_SBRK_OFFS		0x6
+#define LCR_SBRK    		(0x1 << LCR_SBRK_OFFS)	/* Set Break */
+#define LCR_DIVL_OFFS		7
+#define LCR_DIVL_EN    		(0x1 << LCR_DIVL_OFFS)	/* Divisior latch enable */
+
+#define LSR_DR      		BIT0	/* Data ready */
+#define LSR_OE      		BIT1	/* Overrun */
+#define LSR_PE      		BIT2	/* Parity error */
+#define LSR_FE      		BIT3	/* Framing error */
+#define LSR_BI      		BIT4	/* Break */
+#define LSR_THRE    		BIT5	/* Xmit holding register empty */
+#define LSR_TEMT    		BIT6	/* Xmitter empty */
+#define LSR_ERR     		BIT7	/* Error */
+
+/* useful defaults for LCR*/
+#define LCR_8N1     (LCR_WLS_8 | LCR_1_STB)
+
+/* APIs */
+	MV_VOID mvUartPutc(MV_U32 port, MV_U8 c);
+	MV_U8 mvUartGetc(MV_U32 port);
+	MV_BOOL mvUartTstc(MV_U32 port);
+	MV_VOID mvUartInit(MV_U32 port, MV_U32 baudDivisor, MV_UART_PORT *base);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbCh9.h b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbCh9.h
new file mode 100755
index 0000000..8d4d263
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbCh9.h
@@ -0,0 +1,124 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __mvUsbCh9_h__
+#define __mvUsbCh9_h__
+
+#include "usb/api/mvUsbTypes.h"
+/*----------------------------------------------------------------**
+** Chapter 9.4 Standard Device Requests -- all devices            **
+** See Table 9-3 p. 250 of USB 2.0 spec for combinations          **
+**   of request type bitfields with requests, WVALUE, WINDEX etc. **
+**----------------------------------------------------------------*/
+#define REQ_RECIP_MASK          0x1f
+#define REQ_RECIP_DEVICE        0x00
+#define REQ_RECIP_INTERFACE     0x01
+#define REQ_RECIP_ENDPOINT      0x02
+#define REQ_RECIP_OTHER         0x03
+
+/* Also for class requests set the following bit */
+#define REQ_TYPE_OFFSET         5
+#define REQ_TYPE_MASK			(0x03 << REQ_TYPE_OFFSET)
+#define REQ_TYPE_STANDARD		(0x00 << REQ_TYPE_OFFSET)
+#define REQ_TYPE_CLASS			(0x01 << REQ_TYPE_OFFSET)
+#define REQ_TYPE_VENDOR			(0x02 << REQ_TYPE_OFFSET)
+#define REQ_TYPE_RESERVED		(0x03 << REQ_TYPE_OFFSET)
+
+/* Combine one of the 3 above with one of the following 2 */
+#define REQ_DIR_OFFSET         7
+#define REQ_DIR_IN             (1 << REQ_DIR_OFFSET)
+#define REQ_DIR_OUT            (0 << REQ_DIR_OFFSET)
+
+/* Standard USB requests, see Chapter 9 */
+#define REQ_GET_STATUS          0
+#define REQ_CLEAR_FEATURE       1
+#define REQ_SET_FEATURE         3
+#define REQ_SET_ADDRESS         5
+#define REQ_GET_DESCRIPTOR      6
+#define REQ_SET_DESCRIPTOR      7
+#define REQ_GET_CONFIGURATION   8
+#define REQ_SET_CONFIGURATION   9
+#define REQ_GET_INTERFACE       10
+#define REQ_SET_INTERFACE       11
+#define REQ_SYNCH_FRAME         12
+
+#define DESC_TYPE_DEVICE         0x1
+#define DESC_TYPE_CONFIG         0x2
+#define DESC_TYPE_STRING         0x3
+#define DESC_TYPE_INTERFACE      0x4
+#define DESC_TYPE_ENDPOINT       0x5
+#define DESC_TYPE_QUALIFIER      0x6
+#define DESC_TYPE_OTHER_SPEED    0x7
+#define DESC_TYPE_INTF_POWER     0x8
+#define DESC_TYPE_OTG            0x9
+
+/*******************************************************************
+**
+** Values specific to CLEAR FEATURE commands (must go to common.h later)
+*/
+
+#define  ENDPOINT_HALT          0
+#define  DEVICE_SELF_POWERED    0
+#define  DEVICE_REMOTE_WAKEUP   1
+#define  DEVICE_TEST_MODE       2
+
+
+/* States of device instances on the device list */
+
+/* initial device state */
+#define  DEVSTATE_INITIAL        0x00
+
+/* device descriptor [0..7]*/
+#define  DEVSTATE_DEVDESC8       0x01
+
+/* address set */
+#define  DEVSTATE_ADDR_SET       0x02
+
+/* full device descriptor */
+#define  DEVSTATE_DEV_DESC       0x03
+
+/* config descriptor [0..7] */
+#define  DEVSTATE_GET_CFG9       0x04
+
+/* config set */
+#define  DEVSTATE_SET_CFG        0x05
+
+/* full config desc. read in */
+#define  DEVSTATE_CFG_READ       0x06
+
+/* application callbacks */
+#define  DEVSTATE_APP_CALL       0x07
+
+/* Select interface done */
+#define  DEVSTATE_SET_INTF       0x08
+
+#define  DEVSTATE_ENUM_OK        0x09
+
+#define  DEVSTATE_CHK_OTG        0x0A
+
+/* Event codes for attach/detach etc. callback */
+#define  USB_ATTACH_EVENT        1   /* device attach */
+#define  USB_DETACH_EVENT        2   /* device detach */
+#define  USB_CONFIG_EVENT        3   /* device reconfigured */
+#define  USB_INTF_EVENT          4   /* device interface selected */
+
+#endif /* __mvUsbCh9_h__ */
+
+/* EOF */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDebug.h b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDebug.h
new file mode 100755
index 0000000..e663b45
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDebug.h
@@ -0,0 +1,109 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __mvUsbDebug_h__
+#define __mvUsbDebug_h__
+
+#include "mvUsbTypes.h"
+
+#define MV_USB_RT_DEBUG
+
+/************************************************************
+The following array is used to make a run time trace route
+inside the USB stack.
+*************************************************************/
+
+#define ARC_DEBUG_FLAG_ANY      0x00000000
+
+#define ARC_DEBUG_FLAG_TRACE    0x00000001
+#define ARC_DEBUG_FLAG_CTRL     0x00000002
+#define ARC_DEBUG_FLAG_RX       0x00000004
+#define ARC_DEBUG_FLAG_TX       0x00000008
+#define ARC_DEBUG_FLAG_STALL    0x00000010
+#define ARC_DEBUG_FLAG_STATUS   0x00000020
+#define ARC_DEBUG_FLAG_TRANSFER 0x00000040
+#define ARC_DEBUG_FLAG_INIT     0x00000080
+#define ARC_DEBUG_FLAG_ISR      0x00000100
+#define ARC_DEBUG_FLAG_ERROR    0x00000200
+#define ARC_DEBUG_FLAG_ADDR     0x00000400
+#define ARC_DEBUG_FLAG_DUMP     0x00000800
+#define ARC_DEBUG_FLAG_SETUP    0x00001000
+#define ARC_DEBUG_FLAG_CLASS    0x00002000
+#define ARC_DEBUG_FLAG_SPEED    0x00004000
+#define ARC_DEBUG_FLAG_RESET    0x00008000
+#define ARC_DEBUG_FLAG_SUSPEND  0x00010000
+#define ARC_DEBUG_FLAG_RESUME   0x00020000
+#define ARC_DEBUG_FLAG_EP0      0x00040000
+#define ARC_DEBUG_FLAG_EP1      0x00080000
+#define ARC_DEBUG_FLAG_STATS    0x00100000
+
+
+#define ARC_DEBUG_FLAG_ALL      0xffffffff
+
+extern uint_32  usbDebugFlags;
+
+#ifdef MV_USB_RT_DEBUG
+#   define ARC_DEBUG_CODE(flags, code)    	        \
+        if( (usbDebugFlags & (flags)) == (flags) )  \
+            code
+#else
+#   define ARC_DEBUG_CODE(flags, code)
+#endif
+
+#if defined(MV_USB_TRACE_LOG)
+
+#define TRACE_ARRAY_SIZE 400
+#define MAX_STRING_SIZE  132
+
+extern uint_16 DEBUG_TRACE_ARRAY_COUNTER;
+extern char    DEBUG_TRACE_ARRAY[TRACE_ARRAY_SIZE][MAX_STRING_SIZE];
+
+#define ARC_DEBUG_TRACE(flags, format, x...)                                        \
+{                                                                                   \
+    if( (usbDebugFlags & (flags)) == (flags))                                   \
+    {                                                                               \
+        USB_sprintf(DEBUG_TRACE_ARRAY[DEBUG_TRACE_ARRAY_COUNTER], format, ##x);     \
+        DEBUG_TRACE_ARRAY_COUNTER++;                                                \
+        if(DEBUG_TRACE_ARRAY_COUNTER >= TRACE_ARRAY_SIZE)                           \
+            {DEBUG_TRACE_ARRAY_COUNTER = 0;}                                        \
+    }                                                                               \
+}
+                                                    
+#elif defined(MV_USB_TRACE_PRINT)
+
+#   define ARC_DEBUG_TRACE(flags, format, x...)           \
+        if((usbDebugFlags & (flags)) == (flags))      \
+            USB_printf(format, ##x)
+
+/*if trace switch is not enabled define debug log trace to empty*/
+#else
+#   define ARC_DEBUG_TRACE(flags, fromat, x...)
+#endif
+
+
+/************************************************************
+The following are global data structures that can be used
+to copy data from stack on run time. This structure can
+be analyzed at run time to see the state of various other
+data structures in the memory.
+*************************************************************/
+
+#endif /* __mvUsbDebug_h__ */
+/* EOF */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDefs.h b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDefs.h
new file mode 100755
index 0000000..66e2812
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDefs.h
@@ -0,0 +1,139 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __mvUsbDefs_h__
+#define __mvUsbDefs_h__
+
+#include "mvUsbTypes.h"
+
+/* Host specific */
+#define  USB_DEBOUNCE_DELAY                  (101)
+#define  USB_RESET_RECOVERY_DELAY            (11)
+#define  USB_RESET_DELAY                     (60)
+
+/* Error codes */
+#define  USB_OK                              (0x00)
+#define  USBERR_ALLOC                        (0x81)
+#define  USBERR_BAD_STATUS                   (0x82)
+#define  USBERR_CLOSED_SERVICE               (0x83)
+#define  USBERR_OPEN_SERVICE                 (0x84)
+#define  USBERR_TRANSFER_IN_PROGRESS         (0x85)
+#define  USBERR_ENDPOINT_STALLED             (0x86)
+#define  USBERR_ALLOC_STATE                  (0x87)
+#define  USBERR_DRIVER_INSTALL_FAILED        (0x88)
+#define  USBERR_DRIVER_NOT_INSTALLED         (0x89)
+#define  USBERR_INSTALL_ISR                  (0x8A)
+#define  USBERR_INVALID_DEVICE_NUM           (0x8B)
+#define  USBERR_ALLOC_SERVICE                (0x8C)
+#define  USBERR_INIT_FAILED                  (0x8D)
+#define  USBERR_SHUTDOWN                     (0x8E)
+#define  USBERR_INVALID_PIPE_HANDLE          (0x8F)
+#define  USBERR_OPEN_PIPE_FAILED             (0x90)
+#define  USBERR_INIT_DATA                    (0x91)
+#define  USBERR_SRP_REQ_INVALID_STATE        (0x92)
+#define  USBERR_TX_FAILED                    (0x93)
+#define  USBERR_RX_FAILED                    (0x94)
+#define  USBERR_EP_INIT_FAILED               (0x95)
+#define  USBERR_EP_DEINIT_FAILED             (0x96)
+#define  USBERR_TR_FAILED                    (0x97)
+#define  USBERR_BANDWIDTH_ALLOC_FAILED       (0x98)
+#define  USBERR_INVALID_NUM_OF_ENDPOINTS     (0x99)
+
+#define  USBERR_DEVICE_NOT_FOUND             (0xC0)
+#define  USBERR_DEVICE_BUSY                  (0xC1)
+#define  USBERR_NO_DEVICE_CLASS              (0xC3)
+#define  USBERR_UNKNOWN_ERROR                (0xC4)
+#define  USBERR_INVALID_BMREQ_TYPE           (0xC5)
+#define  USBERR_GET_MEMORY_FAILED            (0xC6)
+#define  USBERR_INVALID_MEM_TYPE             (0xC7)
+#define  USBERR_NO_DESCRIPTOR                (0xC8)
+#define  USBERR_NULL_CALLBACK                (0xC9)
+#define  USBERR_NO_INTERFACE                 (0xCA)
+#define  USBERR_INVALID_CFIG_NUM             (0xCB)
+#define  USBERR_INVALID_ANCHOR               (0xCC)
+#define  USBERR_INVALID_REQ_TYPE             (0xCD)
+
+/* Error Codes for lower-layer */
+#define  USBERR_ALLOC_EP_QUEUE_HEAD          (0xA8)
+#define  USBERR_ALLOC_TR                     (0xA9)
+#define  USBERR_ALLOC_DTD_BASE               (0xAA)
+#define  USBERR_CLASS_DRIVER_INSTALL         (0xAB)
+
+
+/* Pipe Types */
+#define  USB_ISOCHRONOUS_PIPE                (0x01)
+#define  USB_INTERRUPT_PIPE                  (0x02)
+#define  USB_CONTROL_PIPE                    (0x03)
+#define  USB_BULK_PIPE                       (0x04)
+
+#define  ARC_USB_STATE_UNKNOWN               (0xff)
+#define  ARC_USB_STATE_POWERED               (0x03)
+#define  ARC_USB_STATE_DEFAULT               (0x02)
+#define  ARC_USB_STATE_ADDRESS               (0x01)
+#define  ARC_USB_STATE_CONFIG                (0x00)
+#define  ARC_USB_STATE_SUSPEND               (0x80)
+
+#define  ARC_USB_SELF_POWERED                (0x01)
+#define  ARC_USB_REMOTE_WAKEUP               (0x02)
+
+/* Bus Control values */
+#define  ARC_USB_NO_OPERATION                (0x00)
+#define  ARC_USB_ASSERT_BUS_RESET            (0x01)
+#define  ARC_USB_DEASSERT_BUS_RESET          (0x02)
+#define  ARC_USB_ASSERT_RESUME               (0x03)
+#define  ARC_USB_DEASSERT_RESUME             (0x04)
+#define  ARC_USB_SUSPEND_SOF                 (0x05)
+#define  ARC_USB_RESUME_SOF                  (0x06)
+
+/* possible values of XD->bStatus */
+#define  ARC_USB_STATUS_IDLE                 (0)
+#define  ARC_USB_STATUS_TRANSFER_ACCEPTED    (1)
+#define  ARC_USB_STATUS_TRANSFER_PENDING     (2)
+#define  ARC_USB_STATUS_TRANSFER_IN_PROGRESS (3)
+#define  ARC_USB_STATUS_ERROR                (4)
+#define  ARC_USB_STATUS_DISABLED             (5)
+#define  ARC_USB_STATUS_STALLED              (6)
+#define  ARC_USB_STATUS_TRANSFER_QUEUED      (7)
+
+#define  ARC_USB_RECV                        (0)
+#define  ARC_USB_SEND                        (1)
+
+#define  ARC_USB_DEVICE_DONT_ZERO_TERMINATE  (0x1)
+
+#define  ARC_USB_SETUP_DATA_XFER_DIRECTION   (0x80)
+
+#define  ARC_USB_SPEED_FULL                  (0)
+#define  ARC_USB_SPEED_LOW                   (1)
+#define  ARC_USB_SPEED_HIGH                  (2)
+
+#define  ARC_USB_MAX_PKTS_PER_UFRAME         (0x6)
+
+/* USB 1.1 Setup Packet */
+typedef struct setup_struct {
+   uint_8      REQUESTTYPE;
+   uint_8      REQUEST;
+   uint_16     VALUE;
+   uint_16     INDEX;
+   uint_16     LENGTH;
+} SETUP_STRUCT, _PTR_ SETUP_STRUCT_PTR;
+
+#endif /* __mvUsbDefs_h__ */
+
+/* EOF */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDevApi.h b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDevApi.h
new file mode 100755
index 0000000..1db2369
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbDevApi.h
@@ -0,0 +1,159 @@
+/*******************************************************************************
+
+This software file (the "File") is distributed by Marvell International Ltd. 
+or its affiliate(s) under the terms of the GNU General Public License Version 2, 
+June 1991 (the "License").  You may use, redistribute and/or modify this File 
+in accordance with the terms and conditions of the License, a copy of which 
+is available along with the File in the license.txt file or by writing to the 
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 
+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+
+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.
+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.
+
+*******************************************************************************/
+
+#ifndef __mvUsbDevApi_h__
+#define __mvUsbDevApi_h__
+
+#include "mvUsbTypes.h"
+#include "mvUsbDebug.h"
+#include "mvUsbDefs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+
+
+#define ARC_USB_MAX_ENDPOINTS               (16)
+
+#define MAX_EP_TR_DESCRS                    (48)
+#define MAX_XDS_FOR_TR_CALLS                (32)
+#define MAX_USB_DEVICES                     MV_USB_MAX_PORTS
+
+/*Assumption here is that all control endpoints are sequential 0,1,..
+if they are not you need to modify the tr_complete routine to handle that */
+#define USB_MAX_CONTROL_ENDPOINTS           (1)
+
+#define USB_MAX_CTRL_PAYLOAD                (64)
+
+
+/* Endpoint types */
+#define  ARC_USB_CONTROL_ENDPOINT             (0)
+#define  ARC_USB_ISOCHRONOUS_ENDPOINT         (1)
+#define  ARC_USB_BULK_ENDPOINT                (2)
+#define  ARC_USB_INTERRUPT_ENDPOINT           (3)
+
+/* Informational Request/Set Types */
+#define  ARC_USB_STATUS_DEVICE_STATE          (0x01)
+#define  ARC_USB_STATUS_INTERFACE             (0x02)
+#define  ARC_USB_STATUS_ADDRESS               (0x03)
+#define  ARC_USB_STATUS_CURRENT_CONFIG        (0x04)
+#define  ARC_USB_STATUS_SOF_COUNT             (0x05)
+#define  ARC_USB_STATUS_DEVICE                (0x06)
+#define  ARC_USB_STATUS_TEST_MODE             (0x07)
+#define  ARC_USB_FORCE_FULL_SPEED             (0x08)
+#define  ARC_USB_PHY_LOW_POWER_SUSPEND        (0x09)
+
+#define  ARC_USB_STATUS_ENDPOINT_NUMBER_MASK  (0x000F)
+#define  ARC_USB_STATUS_ENDPOINT_DIR_MASK     (0x0080)
+
+#define  ARC_USB_TEST_MODE_TEST_PACKET        (0x0400)
+
+/* Available service types */
+/* Services 0 through 15 are reserved for endpoints */
+#define  ARC_USB_SERVICE_EP0                  (0x00)
+#define  ARC_USB_SERVICE_EP1                  (0x01)
+#define  ARC_USB_SERVICE_EP2                  (0x02)
+#define  ARC_USB_SERVICE_EP3                  (0x03)
+#define  ARC_USB_SERVICE_BUS_RESET            (0x10)
+#define  ARC_USB_SERVICE_SUSPEND              (0x11)
+#define  ARC_USB_SERVICE_SOF                  (0x12)
+#define  ARC_USB_SERVICE_RESUME               (0x13)
+#define  ARC_USB_SERVICE_SLEEP                (0x14)
+#define  ARC_USB_SERVICE_SPEED_DETECTION      (0x15)
+#define  ARC_USB_SERVICE_ERROR                (0x16)
+#define  ARC_USB_SERVICE_STALL                (0x17)
+
+typedef pointer _usb_device_handle;
+typedef void (*USB_SERVICE_FUNC)(void* handle, uint_8, boolean, uint_8, 
+                                                 uint_8_ptr, uint_32, uint_8);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void    _usb_dci_vusb20_isr(void* handle);
+
+void    _usb_device_set_bsp_funcs(USB_IMPORT_FUNCS* pBspFuncs);
+
+uint_8  _usb_device_init(uint_8 devNo, void** pHandle);
+
+uint_8  _usb_device_get_max_endpoint(void* handle);
+
+uint_8  _usb_device_get_dev_num(void* handle);
+
+void    _usb_device_shutdown(void* handle);
+
+void    _usb_device_stop(void* handle);
+void    _usb_device_start(void* handle);
+
+uint_8  _usb_device_init_endpoint(void* handle, uint_8 ep_num, uint_16 max_pkt_size, 
+                                  uint_8 direction, uint_8 type, uint_8 flag);
+uint_8  _usb_device_deinit_endpoint(void* handle, uint_8 ep_num, uint_8 direction);
+
+uint_8  _usb_device_recv_data(void* handle, uint_8 ep_num, uint_8* buf_ptr, uint_32 size);
+uint_8  _usb_device_send_data(void* handle, uint_8 ep_num, uint_8* buf_ptr, uint_32 size);
+uint_8  _usb_device_cancel_transfer(void* handle, uint_8 ep_num, uint_8 direction);
+uint_8  _usb_device_get_transfer_status(void* handle, uint_8 ep_num, uint_8 direction);
+void    _usb_device_stall_endpoint(void* handle, uint_8 ep_num, uint_8 direction);
+void    _usb_device_unstall_endpoint(void* handle, uint_8 ep_num, uint_8 direction);
+uint_8  _usb_device_is_endpoint_stalled(void* handle, uint_8 ep_num, uint_8 direction);
+void    _usb_device_assert_resume(void* handle);
+uint_8  _usb_device_get_status(void* handle, uint_8 component, uint_16* status_ptr);
+uint_8  _usb_device_set_status(void* handle, uint_8 component, uint_16 setting);
+void    _usb_device_read_setup_data(void* handle, uint_8 ep_num, uint_8* buf_ptr);
+
+uint_8  _usb_device_register_service(void* handle, uint_8 type, USB_SERVICE_FUNC serviceFunc);
+
+uint_8  _usb_device_unregister_service(void* handle, uint_8 type);
+
+
+
+/* These functions that implement USB 2.0 standard Chapter 9 Setup requests */
+void    mvUsbCh9GetStatus(void* handle, boolean setup, 
+                                  SETUP_STRUCT* ctrl_req);
+
+void    mvUsbCh9ClearFeature(void* handle, boolean setup, 
+                                   SETUP_STRUCT* setup_ptr);
+
+void    mvUsbCh9SetFeature(void* handle, boolean setup, 
+                                 SETUP_STRUCT* setup_ptr);
+
+void    mvUsbCh9SetAddress(void* handle, boolean setup, 
+                                   SETUP_STRUCT* setup_ptr);
+
+/* DEBUG Functions */
+void    _usb_dci_vusb20_set_test_mode(void* handle, uint_16 testMode);   
+
+void    _usb_debug_set_flags(uint_32 flags);     
+uint_32 _usb_debug_get_flags(void);
+     
+void    _usb_debug_init_trace_log(void);
+void    _usb_debug_print_trace_log(void);
+
+void    _usb_regs(void* usbHandle);
+void    _usb_status(void* usbHandle);
+void    _usb_stats(void* usbHandle);
+void    _usb_clear_stats(void* usbHandle);
+void    _usb_ep_status(void* usbHandle, int ep_num, int direction);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __mvUsbDevApi_h__ */
+/* EOF */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbTypes.h b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbTypes.h
new file mode 100755
index 0000000..e99a94d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/api/mvUsbTypes.h
@@ -0,0 +1,238 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __mvUsbTypes_h__
+#define __mvUsbTypes_h__
+
+#define _PTR_      *
+#define _CODE_PTR_ *
+
+typedef char _PTR_                    char_ptr;    /* signed character       */
+
+typedef signed   char  int_8, _PTR_   int_8_ptr;   /* 8-bit signed integer   */
+typedef unsigned char  uint_8, _PTR_   uint_8_ptr;  /* 8-bit signed integer   */
+
+typedef          short int_16, _PTR_   int_16_ptr;  /* 16-bit signed integer  */
+typedef unsigned short uint_16, _PTR_  uint_16_ptr; /* 16-bit unsigned integer*/
+
+typedef          int   int_32, _PTR_   int_32_ptr;  /* 32-bit signed integer  */
+typedef unsigned int   uint_32, _PTR_  uint_32_ptr; /* 32-bit unsigned integer*/
+
+typedef unsigned long  boolean;  /* Machine representation of a boolean */
+
+typedef void _PTR_     pointer;  /* Machine representation of a pointer */
+
+/*--------------------------------------------------------------------------*/
+/*
+**                          STANDARD CONSTANTS
+**
+**  Note that if standard 'C' library files are included after types.h,
+**  the defines of TRUE, FALSE and NULL may sometimes conflict, as most
+**  standard library files do not check for previous definitions.
+*/
+
+#ifndef  FALSE
+#   define FALSE ((boolean)0)   
+#endif
+
+#ifndef  TRUE
+#   define TRUE ((boolean)!FALSE) 
+#endif
+
+#ifndef  NULL
+#   ifdef __cplusplus
+#       define NULL (0)
+#   else
+#       define NULL ((pointer)0)
+#   endif
+#endif
+
+#ifndef _ASSERT_
+   #define ASSERT(X,Y)
+#else
+   #define ASSERT(X,Y) if(Y) { USB_printf(X); exit(1);}
+#endif
+
+#ifndef  MIN
+#   define MIN(a,b)   ((a) < (b) ? (a) : (b))      
+#endif
+
+#define USB_MEM_ALIGN(n, align)            ((n) + (-(n) & (align-1)))
+
+/* Macro for aligning the EP queue head to 32 byte boundary */
+#define USB_MEM32_ALIGN(n)                  USB_MEM_ALIGN(n, 32)
+
+/* Macro for aligning the EP queue head to 1024 byte boundary */
+#define USB_MEM1024_ALIGN(n)                USB_MEM_ALIGN(n, 1024)
+
+/* Macro for aligning the EP queue head to 1024 byte boundary */
+#define USB_MEM2048_ALIGN(n)                USB_MEM_ALIGN(n, 2048)
+
+#define PSP_CACHE_LINE_SIZE                 32
+
+#define USB_uint_16_low(x)                  ((x) & 0xFF)
+#define USB_uint_16_high(x)                 (((x) >> 8) & 0xFF)
+
+#define USB_CACHE_ALIGN(n)                  USB_MEM_ALIGN(n, PSP_CACHE_LINE_SIZE)       
+
+#ifndef INLINE
+#   if defined(MV_VXWORKS)
+#       define INLINE   __inline
+#   else
+#       define INLINE   inline
+#   endif /* MV_VXWORKS */
+#endif /* INLINE */
+
+/* 16bit byte swap. For example 0x1122 -> 0x2211                            */
+static INLINE uint_16 USB_BYTE_SWAP_16BIT(uint_16 value)
+{
+    return ( ((value & 0x00ff) << 8) | 
+             ((value & 0xff00) >> 8) );
+}
+
+/* 32bit byte swap. For example 0x11223344 -> 0x44332211                    */
+static INLINE uint_32 USB_BYTE_SWAP_32BIT(uint_32 value)
+{
+    return ( ((value & 0x000000ff) << 24) |                      
+             ((value & 0x0000ff00) << 8)  |                    
+             ((value & 0x00ff0000) >> 8)  |       
+             ((value & 0xff000000) >> 24));
+}
+
+    
+/* Endianess macros.                                                        */
+#if defined(MV_CPU_LE)
+#   define USB_16BIT_LE(X)  (X) 
+#   define USB_32BIT_LE(X)  (X)
+#   define USB_16BIT_BE(X)  USB_BYTE_SWAP_16BIT(X)
+#   define USB_32BIT_BE(X)  USB_BYTE_SWAP_32BIT(X)
+#elif defined(MV_CPU_BE)
+#   define USB_16BIT_LE(X)  USB_BYTE_SWAP_16BIT(X) 
+#   define USB_32BIT_LE(X)  USB_BYTE_SWAP_32BIT(X)
+#   define USB_16BIT_BE(X)  (X)
+#   define USB_32BIT_BE(X)  (X)
+#else
+    #error "CPU endianess isn't defined!\n"
+#endif 
+
+typedef struct
+{
+    void    (*bspPrintf)          (const char *  fmt, ...);
+    int     (*bspSprintf)         (char* buffer, const char *  fmt, ...);
+    void*   (*bspUncachedMalloc)  (void* pDev, uint_32 size, uint_32 align,
+                                   unsigned long* pPhyAddr);     
+    void    (*bspUncachedFree)    (void* pDev, uint_32 size, unsigned long phyAddr, 
+                                    void*  pVirtAddr);
+    void*   (*bspMalloc)          (unsigned int size);
+    void    (*bspFree)            (void* ptr);
+    void*   (*bspMemset)          (void* ptr, int val, unsigned int size);
+    void*   (*bspMemcpy)          (void* dst, const void* src, unsigned int size);
+    unsigned long (*bspCacheFlush)      (void* pDev, void* pVirtAddr, int size);
+    unsigned long (*bspCacheInv)        (void* pDev, void* pVirtAddr, int size);
+    unsigned long (*bspVirtToPhys)    (void* pDev, void* pVirtAddr);
+    int     (*bspLock)            (void);
+    void    (*bspUnlock)          (int lockKey);
+    uint_32 (*bspGetCapRegAddr)   (int devNo);
+    void    (*bspResetComplete)   (int devNo);
+
+} USB_IMPORT_FUNCS;
+
+extern USB_IMPORT_FUNCS*            global_import_funcs;
+
+#define USB_sprintf(frmt, x...)     if( (global_import_funcs != NULL) &&                \
+                                         global_import_funcs->bspSprintf != NULL)        \
+                                        global_import_funcs->bspSprintf(frmt, ##x)
+
+#define USB_printf(frmt, x...)      if( (global_import_funcs != NULL) &&                \
+                                        (global_import_funcs->bspPrintf != NULL) )        \
+                                        global_import_funcs->bspPrintf(frmt, ##x)
+
+
+#define USB_virt_to_phys(pVirt)     (global_import_funcs->bspVirtToPhys == NULL) ?      \
+                                        (uint_32)(pVirt) : global_import_funcs->bspVirtToPhys(NULL, pVirt)
+
+#define USB_get_cap_reg_addr(dev)   global_import_funcs->bspGetCapRegAddr(dev)
+
+static INLINE void* USB_uncached_memalloc(uint_32 size, uint_32 align, unsigned long* pPhyAddr) 
+{
+    /*USB_printf("**** USB_uncached_memalloc: size=%d\n", (size));       */
+    return global_import_funcs->bspUncachedMalloc(NULL, size, align, pPhyAddr); 
+}
+
+static INLINE void* USB_memalloc(uint_32 size)                                                                              
+{
+    /*USB_printf("**** USB_memalloc: size=%d\n", (size)); */
+    return global_import_funcs->bspMalloc(size);        
+}
+
+#define USB_uncached_memfree(pVirt, size, physAddr)                                 \
+                /*USB_printf("#### USB_uncached_memfree: pVirt=0x%x\n", (pVirt)); */\
+                global_import_funcs->bspUncachedFree(NULL, size, physAddr, pVirt);
+
+#define USB_memfree(ptr)                                                            \
+                /*USB_printf("#### USB_memfree: ptr=0x%x\n", (ptr));*/              \
+                global_import_funcs->bspFree(ptr);
+
+#define USB_memzero(ptr, n)         global_import_funcs->bspMemset(ptr, 0,  n)
+#define USB_memcopy(src, dst, n)    global_import_funcs->bspMemcpy(dst, src, n)
+
+#define USB_dcache_inv(ptr, size)   if(global_import_funcs->bspCacheInv != NULL)  \
+                                        global_import_funcs->bspCacheInv(NULL, ptr, size)     
+
+#define USB_dcache_flush(ptr, size) if(global_import_funcs->bspCacheFlush != NULL)  \
+                                        global_import_funcs->bspCacheFlush(NULL, ptr, size)     
+
+#define USB_lock()                  (global_import_funcs->bspLock == NULL) ?        \
+                                                    0 : global_import_funcs->bspLock()
+
+#define USB_unlock(key)             if(global_import_funcs->bspUnlock != NULL)  \
+                                        global_import_funcs->bspUnlock(key)     
+
+#define USB_reset_complete(dev)     if(global_import_funcs->bspResetComplete)       \
+                                        global_import_funcs->bspResetComplete(dev)
+
+
+#if defined(USB_UNDERRUN_WA)
+
+#define USB_SRAM_MAX_PARTS  16  
+
+typedef struct
+{
+    uint_32 (*bspGetSramAddr) (uint_32* pSize);
+    void    (*bspIdmaCopy) (void* dst, void* src, unsigned int size);
+
+} USB_WA_FUNCS;
+
+extern USB_WA_FUNCS*    global_wa_funcs;
+extern int              global_wa_sram_parts;
+extern int              global_wa_threshold; 
+
+#define USB_get_sram_addr(pSize)        global_wa_funcs->bspGetSramAddr(pSize)
+
+#define USB_idma_copy(dst, src, size)                                   \
+            if(global_wa_funcs->bspIdmaCopy != NULL)                    \
+                global_wa_funcs->bspIdmaCopy(dst, src, size)
+
+#endif /* USB_UNDERRUN_WA */
+
+#endif /* __mvUsbTypes_h__ */
+
+/* EOF */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/common/mvUsbCore.h b/arch/arm/plat-feroceon/mv_hal/usb/common/mvUsbCore.h
new file mode 100755
index 0000000..c6af8e8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/common/mvUsbCore.h
@@ -0,0 +1,720 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __mvUsbCore_h__

+#define __mvUsbCore_h__

+
+#include "usb/api/mvUsbTypes.h"
+
+/* VUSBHS specific defines */
+#define  VUSBHS_MAX_PORTS                          (8)
+#define  EHCI_CAP_LEN_MASK                         (0x000000FF)
+#define  EHCI_DATA_STRUCTURE_BASE_ADDRESS          (0)
+
+/* Command Register Bit Masks */
+#define  EHCI_CMD_RUN_STOP                         (0x00000001)
+#define  EHCI_CMD_CTRL_RESET                       (0x00000002)
+#define  EHCI_CMD_SETUP_TRIPWIRE_SET               (0x00002000)
+#define  EHCI_CMD_SETUP_TRIPWIRE_CLEAR             ~EHCI_CMD_SETUP_TRIPWIRE_SET
+
+#define  EHCI_CMD_ATDTW_TRIPWIRE_SET               (0x00004000)
+#define  EHCI_CMD_ATDTW_TRIPWIRE_CLEAR             ~EHCI_CMD_ATDTW_TRIPWIRE_SET
+
+/*bit 15,3,2 are for frame list size */
+#define  EHCI_CMD_FRAME_SIZE_1024                  (0x00000000) /* 000 */
+#define  EHCI_CMD_FRAME_SIZE_512                   (0x00000004) /* 001 */
+#define  EHCI_CMD_FRAME_SIZE_256                   (0x00000008) /* 010 */
+#define  EHCI_CMD_FRAME_SIZE_128                   (0x0000000C) /* 011 */
+#define  EHCI_CMD_FRAME_SIZE_64                    (0x00008000) /* 100 */
+#define  EHCI_CMD_FRAME_SIZE_32                    (0x00008004) /* 101 */
+#define  EHCI_CMD_FRAME_SIZE_16                    (0x00008008) /* 110 */
+#define  EHCI_CMD_FRAME_SIZE_8                     (0x0000800C) /* 111 */
+
+/* Hardware Rev 4.0 related change */                                             
+/* Mode Register Bit Masks */
+#define  VUSBHS_MODE_CTRL_MODE_IDLE                (0x00000000)
+#define  VUSBHS_MODE_CTRL_MODE_DEV                 (0x00000002)
+#define  VUSBHS_MODE_CTRL_MODE_HOST                (0x00000003)
+#define  VUSBHS_MODE_BIG_ENDIAN                    (0x00000004)
+#define  VUSBHS_MODE_SETUP_LOCK_DISABLE            (0x00000008)
+#define  VUSBHS_MODE_STREAM_DISABLE                (0x00000010)
+    
+/* Interrupt Enable Register Bit Masks */
+#define  EHCI_INTR_INT_EN                          (0x00000001)
+#define  EHCI_INTR_ERR_INT_EN                      (0x00000002)
+#define  EHCI_INTR_PORT_CHANGE_DETECT_EN           (0x00000004)
+
+#define  EHCI_INTR_ASYNC_ADV_AAE                   (0x00000020)
+#define  EHCI_INTR_ASYNC_ADV_AAE_ENABLE            (0x00000020) /* | with this to enable */
+#define  EHCI_INTR_ASYNC_ADV_AAE_DISABLE           (0xFFFFFFDF) /* & with this to disable */
+
+#define  EHCI_INTR_RESET_EN                        (0x00000040)
+#define  EHCI_INTR_SOF_UFRAME_EN                   (0x00000080)
+#define  EHCI_INTR_DEVICE_SUSPEND                  (0x00000100)
+
+/* Interrupt Status Register Masks */
+#define  EHCI_STS_SOF                              (0x00000080)
+#define  EHCI_STS_RESET                            (0x00000040)
+#define  EHCI_STS_PORT_CHANGE                      (0x00000004)
+#define  EHCI_STS_ERR                              (0x00000002)
+#define  EHCI_STS_INT                              (0x00000001)
+#define  EHCI_STS_SUSPEND                          (0x00000100)
+#define  EHCI_STS_HC_HALTED                        (0x00001000)
+
+/* Endpoint Queue Head Bit Masks */
+#define  VUSB_EP_QUEUE_HEAD_IOS                    (0x00008000)
+#define  VUSB_EP_QUEUE_HEAD_IOC                    (0x00008000)
+#define  VUSB_EP_QUEUE_HEAD_INT                    (0x00000100)
+#define  VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE         (0x00000001)
+#define  VUSB_EP_QUEUE_HEAD_MAX_PKT_LEN_POS        (16)
+#define  VUSB_EP_QUEUE_HEAD_ZERO_LEN_TER_SEL       (0x20000000)
+#define  VUSB_EP_QUEUE_HEAD_MULT_POS               (30)
+#define  VUSB_EP_MAX_LENGTH_TRANSFER               (0x4000)
+
+#define  VUSB_EP_QUEUE_HEAD_STATUS_ACTIVE          (0x00000080)
+
+#define  VUSBHS_TD_NEXT_TERMINATE                  (0x00000001)
+#define  VUSBHS_TD_IOC                             (0x00008000)
+#define  VUSBHS_TD_STATUS_ACTIVE                   (0x00000080)
+#define  VUSBHS_TD_STATUS_HALTED                   (0x00000040)
+#define  VUSBHS_TD_RESERVED_FIELDS                 (0x00007F00)
+#define  VUSBHS_TD_ERROR_MASK                      (0x68)
+#define  VUSBHS_TD_ADDR_MASK                       (0xFFFFFFE0)
+#define  VUSBHS_TD_LENGTH_BIT_POS                  (16)
+

+#define  EHCI_EPCTRL_TX_ALL_MASK                   (0xFFFF0000)

+#define  EHCI_EPCTRL_RX_ALL_MASK                   (0x0000FFFF)

+
+#define  EHCI_EPCTRL_TX_DATA_TOGGLE_RST            (0x00400000)
+#define  EHCI_EPCTRL_TX_EP_STALL                   (0x00010000)
+#define  EHCI_EPCTRL_RX_EP_STALL                   (0x00000001)
+#define  EHCI_EPCTRL_RX_DATA_TOGGLE_RST            (0x00000040)
+#define  EHCI_EPCTRL_RX_ENABLE                     (0x00000080)
+#define  EHCI_EPCTRL_TX_ENABLE                     (0x00800000)
+#define  EHCI_EPCTRL_CONTROL                       (0x00000000)
+#define  EHCI_EPCTRL_ISOCHRONOUS                   (0x00040000)
+#define  EHCI_EPCTRL_BULK                          (0x00080000)
+#define  EHCI_EPCTRL_INT                           (0x000C0000)
+#define  EHCI_EPCTRL_TX_TYPE                       (0x000C0000)
+#define  EHCI_EPCTRL_RX_TYPE                       (0x0000000C)
+#define  EHCI_EPCTRL_DATA_TOGGLE_INHIBIT           (0x00000020)
+#define  EHCI_EPCTRL_TX_EP_TYPE_SHIFT              (18)
+#define  EHCI_EPCTRL_RX_EP_TYPE_SHIFT              (2)
+
+/* set bit 24 (PFSC) in PORTSCX register */
+#define  EHCI_PORTSCX_FORCE_FULL_SPEED_CONNECT     (0x01000000) 
+/* set bit 23 (PHCD) in PORTSCX register */
+#define  EHCI_PORTSCX_PHY_CLOCK_DISABLE            (0x00800000) 
+
+#define  EHCI_PORTSCX_PORT_POWER                   (0x00001000)
+#define  EHCI_PORTSCX_LINE_STATUS_BITS             (0x00000C00)
+#define  EHCI_PORTSCX_LINE_STATUS_SE0              (0x00000000)
+#define  EHCI_PORTSCX_LINE_STATUS_KSTATE           (0x00000400)
+#define  EHCI_PORTSCX_LINE_STATUS_JSTATE           (0x00000800)
+#define  EHCI_PORTSCX_PORT_HIGH_SPEED              (0x00000200)
+#define  EHCI_PORTSCX_PORT_RESET                   (0x00000100)
+#define  EHCI_PORTSCX_PORT_SUSPEND                 (0x00000080)
+#define  EHCI_PORTSCX_PORT_FORCE_RESUME            (0x00000040)
+#define  EHCI_PORTSCX_PORT_EN_DIS_CHANGE           (0x00000008)
+#define  EHCI_PORTSCX_PORT_ENABLE                  (0x00000004)
+#define  EHCI_PORTSCX_CONNECT_STATUS_CHANGE        (0x00000002)
+#define  EHCI_PORTSCX_CURRENT_CONNECT_STATUS       (0x00000001)
+
+#define  VUSBHS_PORTSCX_PORT_SPEED_FULL            (0x00000000)
+#define  VUSBHS_PORTSCX_PORT_SPEED_LOW             (0x04000000)
+#define  VUSBHS_PORTSCX_PORT_SPEED_HIGH            (0x08000000)
+#define  VUSBHS_SPEED_MASK                         (0x0C000000)
+#define  VUSBHS_SPEED_BIT_POS                      (26)
+
+#define  EHCI_PORTSCX_W1C_BITS                     (0x2A)
+#define  VUSB_EP_QH_PACKET_SIZE                    (0x3FFF0000)
+#define  VUSB_EP_TR_PACKET_SIZE                    (0x7FFF0000)
+
+#define  VUSBHS_FRINDEX_MS_MASK                    (0xFFFFFFF8)
+#define  VUSBHS_ADDRESS_BIT_SHIFT                  (25)
+
+#define  VUSB20_DCC_MAX_ENDPTS_SUPPORTED           (0x1F)
+#define  VUSB20_DCC_HOST_MODE_MASK                 (1 << 8)               
+#define  VUSB20_DCC_DEVICE_MODE_MASK               (1 << 7)               
+
+#define  EHCI_HCC_PARAMS_64_BIT_ADDR_CAP           (0x01)
+#define  EHCI_HCC_PARAMS_PGM_FRM_LIST_FLAG         (0x02)
+#define  EHCI_HCC_PARAMS_ASYNC_PARK_CAP            (0x04)
+#define  EHCI_HCC_PARAMS_ISOCH_SCHED_THRESHOLD     (0xF0)
+#define  EHCI_HCC_PARAMS_ISOCH_FRAME_CACHED        (0x80)
+
+#define  VUSB20_HCS_PARAMS_PORT_POWER_CONTROL_FLAG (0x10)
+
+#define  VUSB20_HOST_INTR_EN_BITS                  (0x37)
+
+#define  VUSB20_DEFAULT_PERIODIC_FRAME_LIST_SIZE   (1024)
+#define  VUSB20_NEW_PERIODIC_FRAME_LIST_BITS       (2)
+#define  EHCI_FRAME_LIST_ELEMENT_POINTER_T_BIT     (0x01)
+#define  EHCI_ITD_T_BIT                            (0x01)
+#define  EHCI_SITD_T_BIT                           (0x01)
+#define  EHCI_QUEUE_HEAD_POINTER_T_BIT             (0x01)
+
+
+/************************************************************
+Split transatcions specific defines
+************************************************************/
+#define  EHCI_START_SPLIT_MAX_BUDGET               188
+
+#define  EHCI_ELEMENT_TYPE_ITD                     (0x00)
+#define  EHCI_ELEMENT_TYPE_QH                      (0x02)
+#define  EHCI_ELEMENT_TYPE_SITD                    (0x04)
+#define  EHCI_ELEMENT_TYPE_FSTN                    (0x06)
+#define  EHCI_ELEMENT_TYPE_MASK                    (0x06)
+
+#define  EHCI_FRAME_LIST_ELEMENT_TYPE_ITD          (0x00)
+#define  EHCI_FRAME_LIST_ELEMENT_TYPE_QH           (0x01)
+#define  EHCI_FRAME_LIST_ELEMENT_TYPE_SITD         (0x02)
+#define  EHCI_FRAME_LIST_ELEMENT_TYPE_FSTN         (0x03)
+#define  EHCI_FRAME_LIST_ELEMENT_TYPE_BIT_POS      (1)
+
+
+#define  EHCI_QH_ELEMENT_TYPE_ITD                  (0x00)
+#define  EHCI_QH_ELEMENT_TYPE_QH                   (0x01)
+#define  EHCI_QH_ELEMENT_TYPE_SITD                 (0x02)
+#define  EHCI_QH_ELEMENT_TYPE_FSTN                 (0x03)
+
+#define  EHCI_QH_ELEMENT_TYPE_BIT_POS              (1)
+
+#define  EHCI_QTD_PID_OUT_TOKEN                    (0x000)
+#define  EHCI_QTD_PID_IN_TOKEN                     (0x100)
+#define  EHCI_QTD_PID_SETUP_TOKEN                  (0x200)
+#define  EHCI_QTD_IOC                              (0x8000)
+#define  EHCI_QTD_STATUS_ACTIVE                    (0x0080)
+#define  EHCI_QTD_STATUS_HALTED                    (0x0040)
+#define  EHCI_QTD_PID_SETUP                        (0x0200)
+#define  EHCI_QTD_PID_IN                           (0x0100)
+#define  EHCI_QTD_PID_OUT                          (0x0000)
+#define  EHCI_QTD_LENGTH_BIT_POS                   (16)
+#define  EHCI_QTD_DATA_TOGGLE                      (0x80000000)
+#define  EHCI_QTD_DATA_TOGGLE_BIT_POS              (31)
+#define  EHCI_QTD_LENGTH_BIT_MASK                  (0x7FFF0000)
+#define  EHCI_QTD_ERROR_BITS_MASK                  (0x0000003E)
+#define  EHCI_QTD_DEFAULT_CERR_VALUE               (0xC00)
+
+#define  EHCI_SETUP_TOKEN                          (2)
+#define  EHCI_OUT_TOKEN                            (0)
+#define  EHCI_IN_TOKEN                             (1)
+
+#define  EHCI_QTD_T_BIT                            (0x01)
+
+#define  EHCI_QH_ENDPOINT_SPEED_FULL               (0x00)
+#define  EHCI_QH_ENDPOINT_SPEED_LOW                (0x01)
+#define  EHCI_QH_ENDPOINT_SPEED_HIGH               (0x02)
+#define  EHCI_QH_ENDPOINT_SPEED_RESERVED           (0x03)
+
+#define  EHCI_ITD_LENGTH_BIT_POS                   (16)
+#define  EHCI_ITD_IOC_BIT                          (0x00008000)
+#define  EHCI_ITD_ACTIVE_BIT                       (0x80000000)
+#define  EHCI_ITD_PG_SELECT_BIT_POS                (12)
+#define  EHCI_ITD_DIRECTION_BIT_POS                (11)
+#define  EHCI_ITD_EP_BIT_POS                       (8)
+#define  EHCI_ITD_STATUS                           (0xF0000000)
+#define  EHCI_ITD_STATUS_ACTIVE                    (0x80000000) /*bit 4 = 1000*/
+#define  EHCI_ITD_STATUS_DATA_BUFFER_ERR           (0x40000000) /*bit 3 = 0100*/
+#define  EHCI_ITD_STATUS_BABBLE_ERROR              (0x20000000) /*bit 2 = 0010*/
+#define  EHCI_ITD_STATUS_TRANSACTION_ERR           (0x10000000) /*bit 4 = 0001*/
+
+#define  EHCI_ITD_LENGTH_TRANSMITTED               (0x0FFF0000)
+#define  EHCI_ITD_BUFFER_OFFSET                    (0x00000FFF)
+#define  EHCI_ITD_PAGE_NUMBER                      (0x00007000)
+#define  EHCI_ITD_BUFFER_POINTER                   (0xFFFFF000)
+#define  EHCI_ITD_MULTI_TRANSACTION_BITS           (0x00000003)
+
+          
+
+/* SITD position bits */
+#define  EHCI_SITD_DIRECTION_BIT_POS                (31)
+#define  EHCI_SITD_PORT_NUMBER_BIT_POS              (24)
+#define  EHCI_SITD_HUB_ADDR_BIT_POS                 (16)
+#define  EHCI_SITD_EP_ADDR_BIT_POS                  (8)
+
+#define  EHCI_SITD_COMPLETE_SPLIT_MASK_BIT_POS      (8)
+
+#define  EHCI_SITD_IOC_BIT_SET                      (0x80000000)
+#define  EHCI_SITD_PAGE_SELECT_BIT_POS              (30)
+#define  EHCI_SITD_TRANSFER_LENGTH_BIT_POS          (16)
+#define  EHCI_SITD_STATUS_ACTIVE                    (0x80)
+
+#define  EHCI_SITD_STATUS                           (0xFF)
+#define  EHCI_SITD_LENGTH_TRANSMITTED               (0x03FF0000)
+#define  EHCI_SITD_BUFFER_OFFSET                    (0x00000FFF)
+#define  EHCI_SITD_PAGE_NUMBER                      (0x40000000)
+#define  EHCI_SITD_BUFFER_POINTER                   (0xFFFFF000)
+
+
+
+#define  EHCI_SITD_BUFFER_PTR_BIT_POS              (12)
+#define  EHCI_SITD_TP_BIT_POS                      (3)
+#define  EHCI_SITD_TP_ALL                          (0)
+#define  EHCI_SITD_TP_BEGIN                        (1)
+#define  EHCI_SITD_TP_MID                          (2)
+#define  EHCI_SITD_TP_END                          (3)
+
+
+
+/* Interrupt enable bit masks */
+#define  EHCI_IER_ASYNCH_ADVANCE                   (0x00000020)
+#define  EHCI_IER_HOST_SYS_ERROR                   (0x00000010)
+#define  EHCI_IER_FRAME_LIST_ROLLOVER              (0x00000008)
+#define  EHCI_IER_PORT_CHANGE                      (0x00000004)
+#define  EHCI_IER_USB_ERROR                        (0x00000002)
+#define  EHCI_IER_USB_INTERRUPT                    (0x00000001)
+
+/* Interrupt status bit masks */
+#define  EHCI_STS_RECLAIMATION                     (0x00002000)
+#define  EHCI_STS_SOF_COUNT                        (0x00000080)
+#define  EHCI_STS_ASYNCH_ADVANCE                   (0x00000020)
+#define  EHCI_STS_HOST_SYS_ERROR                   (0x00000010)
+#define  EHCI_STS_FRAME_LIST_ROLLOVER              (0x00000008)
+#define  EHCI_STS_PORT_CHANGE                      (0x00000004)
+#define  EHCI_STS_USB_ERROR                        (0x00000002)
+#define  EHCI_STS_USB_INTERRUPT                    (0x00000001)
+
+/* Status bit masks */
+#define  EHCI_STS_ASYNCH_SCHEDULE                  (0x00008000)
+#define  EHCI_STS_PERIODIC_SCHEDULE                (0x00004000)
+#define  EHCI_STS_RECLAMATION                      (0x00002000)
+#define  EHCI_STS_HC_HALTED                        (0x00001000)
+
+/* USB command bit masks */
+#define  EHCI_USBCMD_ASYNC_SCHED_ENABLE            (0x00000020)
+#define  EHCI_USBCMD_PERIODIC_SCHED_ENABLE         (0x00000010)
+
+#define  EHCI_HCS_PARAMS_N_PORTS                   (0x0F)
+
+#define  VUSB_HS_DELAY                             (3500)
+
+#define  EHCI_QH_EP_NUM_MASK                       (0x0F00)
+#define  EHCI_QH_EP_NUM_BITS_POS                   (8)
+#define  EHCI_QH_DEVICE_ADDRESS_MASK               (0x7F)
+#define  EHCI_QH_SPEED_BITS_POS                    (12)
+#define  EHCI_QH_MAX_PKT_SIZE_BITS_POS             (16)
+#define  EHCI_QH_NAK_COUNT_RL_BITS_POS             (28)
+#define  EHCI_QH_EP_CTRL_FLAG_BIT_POS              (27)
+#define  EHCI_QH_HEAD_RECLAMATION_BIT_POS          (15)
+#define  EHCI_QH_DTC_BIT_POS                       (14)
+#define  EHCI_QH_HIGH_BW_MULT_BIT_POS              (30)
+#define  EHCI_QH_HUB_PORT_NUM_BITS_POS             (23)
+#define  EHCI_QH_HUB_ADDR_BITS_POS                 (16)
+#define  EHCI_QH_SPLIT_COMPLETION_MASK_BITS_POS    (8)
+#define  EHCI_QH_SPLIT_COMPLETION_MASK             (0xFF00)
+#define  EHCI_QH_INTR_SCHED_MASK                   (0xFF)
+#define  EHCI_QH_INACTIVATE_NEXT_TR_BIT_POS        (7)
+#define  EHCI_QH_HORIZ_PHY_ADDRESS_MASK            (0xFFFFFFE0)
+#define  EHCI_QH_TR_OVERLAY_DT_BIT                 (0x80000000)
+
+#define  EHCI_SITD_SPLIT_COMPLETION_MASK_BITS_POS  (8)
+
+#define  EHCI_INTR_NO_THRESHOLD_IMMEDIATE          (0x00010000)
+#define  EHCI_NEW_PERIODIC_FRAME_LIST_SIZE         (1024)
+#define  EHCI_FRAME_LIST_SIZE_BITS_POS             (2)
+#define  EHCI_HORIZ_PHY_ADDRESS_MASK              (0xFFFFFFE0)
+
+#define  DEFAULT_MAX_NAK_COUNT                     (15)
+
+/* OTG Status and control register bit masks */
+
+/* OTG interrupt enable bit masks */
+#define  VUSBHS_OTGSC_INTERRUPT_ENABLE_BITS_MASK   (0x5F000000)
+#define  VUSBHS_OTGSC_DPIE                         (0x40000000)   /* Data-line pulsing IE */
+#define  VUSBHS_OTGSC_1MSIE                        (0x20000000)
+#define  VUSBHS_OTGSC_BSEIE                        (0x10000000)   /* B-session end IE */
+#define  VUSBHS_OTGSC_BSVIE                        (0x08000000)   /* B-session valid IE */
+#define  VUSBHS_OTGSC_ASVIE                        (0x04000000)   /* A-session valid IE */
+#define  VUSBHS_OTGSC_AVVIE                        (0x02000000)   /* A-V-bus valid IE */
+#define  VUSBHS_OTGSC_IDIE                         (0x01000000)   /* OTG ID IE */
+
+/* OTG interrupt status bit masks */
+#define  VUSBHS_OTGSC_INTERRUPT_STATUS_BITS_MASK   (0x005F0000)
+#define  VUSBHS_OTGSC_DPIS                         (0x00400000)   /* Data-line pulsing IS */
+#define  VUSBHS_OTGSC_1MSIS                        (0x00200000)
+#define  VUSBHS_OTGSC_BSEIS                        (0x00100000)   /* B-session end IS */
+#define  VUSBHS_OTGSC_BSVIS                        (0x00080000)   /* B-session valid IS */
+#define  VUSBHS_OTGSC_ASVIS                        (0x00040000)   /* A-session valid IS */
+#define  VUSBHS_OTGSC_AVVIS                        (0x00020000)   /* A-Vbus valid IS */
+#define  VUSBHS_OTGSC_IDIS                         (0x00010000)   /* OTG ID IS */
+
+/* OTG status bit masks */
+#define  VUSBHS_OTGSC_DPS                          (0x00004000)
+#define  VUSBHS_OTGSC_BSE                          (0x00001000)   /* B-session end */
+#define  VUSBHS_OTGSC_BSV                          (0x00000800)   /* B-session valid */
+#define  VUSBHS_OTGSC_ASV                          (0x00000400)   /* A-session valid */
+#define  VUSBHS_OTGSC_AVV                          (0x00000200)   /* A-Vbus Valid */
+#define  VUSBHS_OTGSC_ID                           (0x00000100)   /* OTG ID */
+
+/* OTG control bit masks */
+#define  VUSBHS_OTGSC_CTL_BITS                     (0x2F)
+#define  VUSBHS_OTGSC_HABA                         (0x00000080)   /* hardware assisted data pulse bits*/
+#define  VUSBHS_OTGSC_HADP                         (0x00000040)   /* hardware assisted data pulse bits*/
+
+#ifdef PATCH_3
+/* the following change is to be compatable with 4.0 revision of
+hardware. Enable the following switch in config.mk to enable the
+changes. */
+
+    /* WEB20040409 below line changed from VUSBHS_OTGSC_B_HOST_EN to VUSBHS_OTGSC_IDPU 
+       to reflect change in usbhs4.0  B_HOST_EN has not been used quite some time */
+    #define  VUSBHS_OTGSC_IDPU                         (0x00000020)   /* ID pull enable */
+#else
+    #define  VUSBHS_OTGSC_B_HOST_EN                    (0x00000020)   /* B_host_enable */
+#endif
+
+#define  VUSBHS_OTGSC_DP                           (0x00000010)   /* Data-pulsing */
+#define  VUSBHS_OTGSC_OT                           (0x00000008)   /* OTG termination */
+#if 0
+    #define  VUSBHS_OTGSC_VO                       (0x00000004)   /* Vbus on */
+#endif
+
+#define  VUSBHS_OTGSC_HAAR                         (0x00000004)   /* Auto reset bit*/
+
+#define  VUSBHS_OTGSC_VC                           (0x00000002)   /* Vbus charge */
+#define  VUSBHS_OTGSC_VD                           (0x00000001)   /* Vbus discharge */
+
+typedef  uint_32  USB_REGISTER, _PTR_ USB_REGISTER_PTR;
+
+/* The VUSB register structure */
+typedef struct {
+   union  {
+      struct  {
+         volatile USB_REGISTER   CAPLENGTH_HCIVER;
+         volatile USB_REGISTER   HCS_PARAMS;       /* HC structural parameters */
+         volatile USB_REGISTER   HCC_PARAMS;       /* HC Capability Parameters*/
+         volatile USB_REGISTER   RESERVED1[5];
+         volatile USB_REGISTER   DCI_VERSION;      /* DC version number and reserved 16 bits */
+         volatile USB_REGISTER   DCC_PARAMS;       /* DC Capability Parameters */
+      } CAPABILITY_REGISTERS;
+      
+      struct  {
+         volatile USB_REGISTER   USB_CMD;                   /* Command register */
+         volatile USB_REGISTER   USB_STS;                   /* Status register */
+         volatile USB_REGISTER   USB_INTR;                  /* Interrupt enable */
+         volatile USB_REGISTER   USB_FRINDEX;               /* Frame index */
+         volatile USB_REGISTER   CTRLDSSEGMENT;             /* 4G segment selector */
+         volatile USB_REGISTER   DEVICE_ADDR;               /* Device Address */
+         volatile USB_REGISTER   EP_LIST_ADDR;              /* Endpoint List Address */
+         volatile USB_REGISTER   RESERVED0[9];
+         volatile USB_REGISTER   CONFIG_FLAG;               /* Configured Flag register */
+         volatile USB_REGISTER   PORTSCX[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */
+         volatile USB_REGISTER   OTGSC;
+         volatile USB_REGISTER   USB_MODE;                  /* USB Host/Device mode */
+         volatile USB_REGISTER   ENDPT_SETUP_STAT;          /* Endpoint Setup Status */
+         volatile USB_REGISTER   ENDPTPRIME;                /* Endpoint Initialize */
+         volatile USB_REGISTER   ENDPTFLUSH;                /* Endpoint De-initialize */
+         volatile USB_REGISTER   ENDPTSTATUS;               /* Endpoint Status */
+         volatile USB_REGISTER   ENDPTCOMPLETE;             /* Endpoint Interrupt On Complete */
+         volatile USB_REGISTER   ENDPTCTRLX[16];            /* Endpoint Control, where x = 0.. 15 */
+      } OPERATIONAL_DEVICE_REGISTERS;
+      
+      struct  {
+         volatile USB_REGISTER   USB_CMD;                   /* Command register */
+         volatile USB_REGISTER   USB_STS;                   /* Status register */
+         volatile USB_REGISTER   USB_INTR;                  /* Interrupt enable */
+         volatile USB_REGISTER   USB_FRINDEX;               /* Frame index */
+         volatile USB_REGISTER   CTRLDSSEGMENT;             /* 4G segment selector */
+         volatile USB_REGISTER   PERIODIC_LIST_BASE_ADDR;   /* Periodic schedule list */
+         volatile USB_REGISTER   CURR_ASYNC_LIST_ADDR;      /* Current Asynch schedule list */
+         volatile USB_REGISTER   ASYNCTTSTS;                /* Async buffer in embedded TT control */
+         volatile USB_REGISTER   RESERVED0[8];
+         volatile USB_REGISTER   CONFIG_FLAG;               /* Configured Flag register */
+         volatile USB_REGISTER   PORTSCX[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */
+         volatile USB_REGISTER   OTGSC;                     /* OTG status and control register */
+         volatile USB_REGISTER   USB_MODE;                  /* USB Host/Device mode */
+      } OPERATIONAL_HOST_REGISTERS;
+   } REGISTERS;
+} VUSB20_REG_STRUCT, _PTR_ VUSB20_REG_STRUCT_PTR;
+
+typedef struct {
+   volatile uint_32   MAX_PKT_LENGTH;    /* Bits 16..26 Bit 15 is Interrupt 
+                                          ** On Setup 
+                                          */
+   volatile uint_32   CURR_DTD_PTR;        /* Current dTD Pointer */
+   volatile uint_32   NEXT_DTD_PTR;        /* Next dTD Pointer */
+   volatile uint_32   SIZE_IOC_INT_STS;    /* Total bytes (16..30), IOC (15), 
+                                          ** INT (8), STS (0-7) 
+                                          */
+   volatile uint_32   BUFF_PTR0;           /* Buffer pointer Page 0 (12-31) */
+   volatile uint_32   BUFF_PTR1;           /* Buffer pointer Page 1 (12-31) */
+   volatile uint_32   BUFF_PTR2;           /* Buffer pointer Page 2 (12-31) */
+   volatile uint_32   BUFF_PTR3;           /* Buffer pointer Page 3 (12-31) */
+   volatile uint_32   BUFF_PTR4;           /* Buffer pointer Page 4 (12-31) */
+   volatile uint_32   RESERVED1;
+   volatile uint_8    SETUP_BUFFER[8];     /* 8 bytes of setup data that follows 
+                                            ** the Setup PID 
+                                            */
+   volatile uint_32   RESERVED2[4];
+} VUSB20_EP_QUEUE_HEAD_STRUCT, _PTR_ VUSB20_EP_QUEUE_HEAD_STRUCT_PTR;
+
+typedef struct {
+   pointer              PRIVATE;
+   void (_CODE_PTR_     FREE)(pointer);
+   pointer              XD_FOR_THIS_DTD;
+} SCRATCH_STRUCT, _PTR_ SCRATCH_STRUCT_PTR;
+
+typedef struct ep_tr_struct {
+   volatile uint_32      NEXT_TR_ELEM_PTR; /* Memory address of next 
+                                          ** dTD to be processed (5-31)
+                                          ** and the T (bit 0) indicating 
+                                          ** pointer validity
+                                          */
+   volatile uint_32      SIZE_IOC_STS;     /* total bytes (16-30), 
+                                          ** IOC (15), Status (0-7) 
+                                          */
+   volatile uint_32      BUFF_PTR0;        /* Buffer pointer Page 0 */
+   volatile uint_32      BUFF_PTR1;        /* Buffer pointer Page 1 */
+   volatile uint_32      BUFF_PTR2;        /* Buffer pointer Page 2 */
+   volatile uint_32      BUFF_PTR3;        /* Buffer pointer Page 3 */
+   volatile uint_32      BUFF_PTR4;        /* Buffer pointer Page 4 */
+   volatile SCRATCH_STRUCT_PTR   SCRATCH_PTR;
+} VUSB20_EP_TR_STRUCT, _PTR_ VUSB20_EP_TR_STRUCT_PTR;
+
+typedef struct {
+   uint_32      NEXT_LINK_PTR;    /* (5-31) Memory address of 
+                                          ** next schedule data structure 
+                                          ** item Type (1..2 ) and the 
+                                          ** T (bit 0) indicating pointer 
+                                          ** validity
+                                          */
+   uint_32      TR_STATUS_CTL_LIST[8];  /* bits 31-28: Status,
+                                                ** bits 27-16: Tr X length
+                                                ** bit 15: Int on complete
+                                                ** bits 14-12: Page Select
+                                                ** bits 11-0: Tr X offset
+                                                */
+   uint_32      BUFFER_PAGE_PTR_LIST[7];  /* bits 31-12 4K aligned pointer 
+                                                ** to physical memory 
+                                                ** bits 11-8 endpoint no.
+                                                ** bit 7: reserved
+                                                ** bits 6-0 device address*/
+   SCRATCH_STRUCT_PTR   SCRATCH_PTR;
+   pointer      PIPE_DESCR_FOR_THIS_ITD;
+   pointer      PIPE_TR_DESCR_FOR_THIS_ITD;
+   uint_32_ptr  frame_list_ptr;
+   uint_32      number_of_transactions;
+   /* 32-byte aligned structures */
+   uint_32        RESERVED[11];
+} EHCI_ITD_STRUCT, _PTR_ EHCI_ITD_STRUCT_PTR;
+
+typedef struct {
+   uint_32      NEXT_LINK_PTR;    /* (5-31) Memory address of 
+                                          ** next schedule data structure 
+                                          ** item Type (1..2 ) and the 
+                                          ** T (bit 0) indicating pointer 
+                                          ** validity
+                                          */
+   uint_32      EP_CAPAB_CHARAC;  /* bits 31: Direction (I/O),
+                                          ** bits 30-24: Port number
+                                          ** bit 23: reserved
+                                          ** bits 22-16: Hub address
+                                          ** bits 15-12: Reserved
+                                          ** bits 11-8: Endpoint number
+                                          ** bit 7: reserved
+                                          ** bits 6-0: device address
+                                          */
+   uint_32      UFRAME_SCHED_CTL; /* bits 31-16: reserved 
+                                          ** bits 15-8: Split completion mask
+                                          ** bits 7-0: Split start mask
+                                          */
+   uint_32      TRANSFER_STATE;   /* bit 31: int on complete
+                                          ** bit 30: Page Select
+                                          ** bits 29-26: Reserved
+                                          ** bits 25-16: total bytes to 
+                                          ** transfer
+                                          ** bits 15-8: uframe 
+                                          ** complete-split progress mask
+                                          ** bits 7-0: status
+                                          */
+   uint_32      BUFFER_PTR_0;     /* bits 31-12: 4K aligned pointer 
+                                          ** to physical memory 
+                                          ** bits 11-0: Current offset
+                                          */
+   uint_32      BUFFER_PTR_1;     /* bits 31-12: 4K aligned pointer 
+                                          ** to physical memory 
+                                          ** bits 11-5 reserved
+                                          ** bits 4-3 tr position
+                                          ** bits 2-0 tr count
+                                          */
+   uint_32      BACK_LINK_PTR;    /* bits 31-5 back pointer points to sITD 
+                                          ** bits 4-1: reserved
+                                          ** bit 0: terminate
+                                          */
+   SCRATCH_STRUCT_PTR   SCRATCH_PTR;
+   pointer      PIPE_DESCR_FOR_THIS_SITD;
+   pointer      PIPE_TR_DESCR_FOR_THIS_SITD;
+   uint_32_ptr  frame_list_ptr;
+
+   /* align to 16 word boundry */
+   uint_32      RESERVED[5];
+
+} EHCI_SITD_STRUCT, _PTR_ EHCI_SITD_STRUCT_PTR;
+
+typedef struct {
+   uint_32      NEXT_QTD_PTR;     /* (5-31) Memory address of 
+                                          ** next qTD to be processed
+                                          ** (4..1) reserved 
+                                          ** T (bit 0) indicating pointer 
+                                          ** validity
+                                          */
+   uint_32      ALT_NEXT_QTD_PTR; /* bits 31-5: alternate next 
+                                          ** qTD if the above one encounters 
+                                          ** a short packet
+                                          ** (4..1) reserved 
+                                          ** T (bit 0) indicating pointer 
+                                          ** validity
+                                          */
+   uint_32      TOKEN;            /* bits 31: data toggle 
+                                          ** bits 30-16: Total bytes to transfer
+                                          ** bit 15: Interrupt on Complete
+                                          ** bits 14-12: Current page
+                                          ** bits 11-10: Error Counter
+                                          ** bits 9-8: PID code
+                                          ** bits 7-0: status
+                                          */
+   uint_32      BUFFER_PTR_0;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 11-0: Current Offset
+                                          */
+   uint_32      BUFFER_PTR_1;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 11-0: reserved
+                                          */
+   uint_32      BUFFER_PTR_2;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 11-0: reserved
+                                          */
+   uint_32      BUFFER_PTR_3;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 11-0: reserved
+                                          */
+   uint_32      BUFFER_PTR_4;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 11-0: reserved
+                                          */
+   SCRATCH_STRUCT_PTR   SCRATCH_PTR;
+   pointer     PIPE_DESCR_FOR_THIS_QTD;
+   pointer     TR_FOR_THIS_QTD;
+   uint_32     RESERVED[5];
+} EHCI_QTD_STRUCT, _PTR_ EHCI_QTD_STRUCT_PTR;
+
+typedef struct {
+   uint_32      HORIZ_LINK_PTR;   /* (5-31) Memory address of 
+                                          ** next data object to be processed
+                                          ** (4..3) reserved 
+                                          ** (2..1) type of the item
+                                          ** T (bit 0) indicating pointer 
+                                          ** validity
+                                          */
+   uint_32      EP_CAPAB_CHARAC1; /* bits 31-28: NAK count reload,
+                                          ** bit 27: Control endpoint flag
+                                          ** bit 26-16: Maximum packet length
+                                          ** bit 15: Head of reclamation 
+                                          ** list flag
+                                          ** bit 14: data toggle control
+                                          ** bits 13-12: endpoint speed
+                                          ** bit 11-8: endpoint number
+                                          ** bits 7: Inactivate on next tr
+                                          ** bits 6-0: Device address
+                                          */
+   uint_32      EP_CAPAB_CHARAC2; /* bits 31-30: High-BW pipe 
+                                          ** Multiplier, 
+                                          ** bit 29-23: Port number
+                                          ** bit 22-16: Hub address
+                                          ** bit 15-8: Split completion mask
+                                          ** bit 7-0: Interrupt schedule mask
+                                          */
+   uint_32      CURR_QTD_LINK_PTR;/* bits 31-5: physical memory address
+                                          ** of the current xaction processed
+                                          */
+   uint_32      NEXT_QTD_LINK_PTR;/* bits 31-5: physical memory address
+                                          ** of the current xaction processed
+                                          ** bit 0: Terminate bit
+                                          */
+   uint_32      ALT_NEXT_QTD_LINK_PTR;  /* bits 31-5: physical memory address
+                                                ** of the current xaction processed
+                                                ** bits 4-1: NAK counter
+                                                ** bit 0: Terminate bit
+                                                */
+   uint_32      STATUS;           /* bit 31: data-toggle
+                                          ** bits 30-16: total bytes to transfer
+                                          ** bit 15: Interrupt on complete
+                                          ** bits 11-10: Error counter
+                                          ** bit 0: Ping state/Err
+                                          ** physical memory address
+                                          ** bit 11-0: reserved
+                                          */
+   uint_32      BUFFER_PTR_0;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 11-0: reserved
+                                          */
+   uint_32      BUFFER_PTR_1;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 7-0: Split-transaction, 
+                                          ** complete-split progress
+                                          */
+   uint_32      BUFFER_PTR_2;     /* bits 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bits 11-5: S-bytes
+                                          ** bits 4-0: Split-transaction 
+                                          ** frame tag
+                                          */
+   uint_32      BUFFER_PTR_3;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 11-0: reserved
+                                          */
+   uint_32      BUFFER_PTR_4;     /* bit 31-12: 4K-page aligned 
+                                          ** physical memory address
+                                          ** bit 11-0: reserved
+                                          */
+   SCRATCH_STRUCT_PTR   SCRATCH_PTR;
+   pointer     PIPE_DESCR_FOR_THIS_QH;
+   uint_32     RESERVED[18];
+} EHCI_QH_STRUCT, _PTR_ EHCI_QH_STRUCT_PTR;
+
+typedef struct {
+   uint_32      NORMAL_PATH_LINK_PTR;   /* (5-31) Memory address of 
+                                                ** next data object to be processed
+                                                ** in the periodic list
+                                                ** bits 4-3: reserved 
+                                                ** (2..1) type of the item
+                                                ** T (bit 0) indicating pointer 
+                                                ** validity
+                                                */
+   uint_32      BACK_PATH_LINK_PTR;     /* bits 31-5: Memory address of 
+                                                ** the queue head,
+                                                ** bit 4-3: reserved
+                                                ** (2..1) type of the item
+                                                ** T (bit 0) indicating pointer 
+                                                ** validity
+                                                */
+   SCRATCH_STRUCT_PTR   SCRATCH_PTR;
+   /* 32-bytes aligned */
+   uint_32              RESERVED[6];
+} EHCI_FSTN_STRUCT, _PTR_ EHCI_FSTN_STRUCT_PTR;
+
+typedef uint_32   EHCI_FRAME_LIST_ELEMENT_POINTER;
+
+#endif /* __mvUsbCore_h__ */
+/* EOF */
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/common/mvUsbDesc.h b/arch/arm/plat-feroceon/mv_hal/usb/common/mvUsbDesc.h
new file mode 100755
index 0000000..1a95297
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/common/mvUsbDesc.h
@@ -0,0 +1,162 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __mvUsbDesc_h__
+#define __mvUsbDesc_h__
+
+#include "mvUsbTypes.h"
+
+typedef struct usb_device_descriptor
+{
+   uint_8   bLength;          /* Descriptor size in bytes = 18 */
+   uint_8   bDescriptorType;  /* DEVICE descriptor type = 1 */
+   uint_8   bcdUSD[2];        /* USB spec in BCD, e.g. 0x0200 */
+   uint_8   bDeviceClass;     /* Class code, if 0 see interface */
+   uint_8   bDeviceSubClass;  /* Sub-Class code, 0 if class = 0 */
+   uint_8   bDeviceProtocol;  /* Protocol, if 0 see interface */
+   uint_8   bMaxPacketSize;   /* Endpoint 0 max. size */
+   uint_8   idVendor[2];      /* Vendor ID per USB-IF */
+   uint_8   idProduct[2];     /* Product ID per manufacturer */
+   uint_8   bcdDevice[2];     /* Device release # in BCD */
+   uint_8   iManufacturer;    /* Index to manufacturer string */
+   uint_8   iProduct;         /* Index to product string */
+   uint_8   iSerialNumber;    /* Index to serial number string */
+   uint_8   bNumConfigurations; /* Number of possible configurations */ 
+} DEVICE_DESCRIPTOR, _PTR_ DEVICE_DESCRIPTOR_PTR;  
+
+typedef struct usb_configuration_descriptor
+{
+   uint_8   bLength;          /* Descriptor size in bytes = 9 */
+   uint_8   bDescriptorType;  /* CONFIGURATION type = 2 or 7 */
+   uint_8   wTotalLength[2];  /* Length of concatenated descriptors */
+   uint_8   bNumInterfaces;   /* Number of interfaces, this config. */
+   uint_8   bConfigurationValue;  /* Value to set this config. */ 
+   uint_8   iConfig;          /* Index to configuration string */
+   uint_8   bmAttributes;     /* Config. characteristics */
+   #define  CONFIG_RES7       (0x80)  /* Reserved, always = 1 */
+   #define  CONFIG_SELF_PWR   (0x40)  /* Self-powered device */
+   #define  CONFIG_WAKEUP     (0x20)  /* Remote wakeup */
+   uint_8   bMaxPower;        /* Max.power from bus, 2mA units */
+} CONFIGURATION_DESCRIPTOR, _PTR_ CONFIGURATION_DESCRIPTOR_PTR;  
+
+typedef struct usb_interface_descriptor
+{
+   uint_8   bLength;          /* Descriptor size in bytes = 9 */
+   uint_8   bDescriptorType;  /* INTERFACE descriptor type = 4 */
+   uint_8   bInterfaceNumber; /* Interface no.*/
+   uint_8   bAlternateSetting;  /* Value to select this IF */
+   uint_8   bNumEndpoints;    /* Number of endpoints excluding 0 */
+   uint_8   bInterfaceClass;  /* Class code, 0xFF = vendor */
+   uint_8   bInterfaceSubClass;  /* Sub-Class code, 0 if class = 0 */
+   uint_8   bInterfaceProtocol;  /* Protocol, 0xFF = vendor */
+   uint_8   iInterface;       /* Index to interface string */
+} INTERFACE_DESCRIPTOR, _PTR_ INTERFACE_DESCRIPTOR_PTR;  
+
+typedef struct usb_endpoint_descriptor
+{
+   uint_8   bLength;          /* Descriptor size in bytes = 7 */
+   uint_8   bDescriptorType;  /* ENDPOINT descriptor type = 5 */
+   uint_8   bEndpointAddress; /* Endpoint # 0 - 15 | IN/OUT */
+   #define  IN_ENDPOINT    (0x80)   /* IN endpoint, device to host */
+   #define  OUT_ENDPOINT   (0x00)   /* OUT endpoint, host to device */
+   #define  ENDPOINT_MASK  (0x0F)   /* Mask endpoint # */
+   uint_8   bmAttributes;     /* Transfer type */
+   #define  CONTROL_ENDPOINT  (0x00)   /* Control transfers */
+   #define  ISOCH_ENDPOINT    (0x01)   /* Isochronous transfers */
+   #define  BULK_ENDPOINT     (0x02)   /* Bulk transfers */
+   #define  IRRPT_ENDPOINT    (0x03)   /* Interrupt transfers */
+   #define  EP_TYPE_MASK      (0x03)   /* Mask type bits */
+   /* Following must be zero except for isochronous endpoints */
+   #define  ISOCH_NOSYNC      (0x00)   /* No synchronization */
+   #define  ISOCH_ASYNC       (0x04)   /* Asynchronous */
+   #define  ISOCH_ADAPT       (0x08)   /* Adaptive */
+   #define  ISOCH_SYNCH       (0x0C)   /* Synchrounous */
+   #define  ISOCH_DATA        (0x00)   /* Data endpoint */
+   #define  ISOCH_FEEDBACK    (0x10)   /* Feedback endpoint */
+   #define  ISOCH_IMPLICIT    (0x20)   /* Implicit feedback */
+   #define  ISOCH_RESERVED    (0x30)   /* Reserved */
+   uint_8   wMaxPacketSize[2];   /* Bits 10:0 = max. packet size */
+   /* For high-speed interrupt or isochronous only, additional
+   **   transaction opportunities per microframe follow.*/
+   #define  PACKET_SIZE_MASK     (0x7FF)  /* packet size bits */
+   #define  NO_ADDITONAL      (0x0000)   /* 1 / microframe */
+   #define  ONE_ADDITIONAL    (0x0800)   /* 2 / microframe */
+   #define  TWO_ADDITIONAL    (0x1000)   /* 3 / microframe */
+   #define  ADDITIONAL_MASK   (ONE_ADDITIONAL | TWO_ADDITIONAL)
+   uint_8   iInterval;        /* Polling interval in (micro) frames */
+} ENDPOINT_DESCRIPTOR, _PTR_ ENDPOINT_DESCRIPTOR_PTR;  
+
+typedef struct usb_qualifier_descriptor
+{
+   uint_8   bLength;          /* Descriptor size in bytes = 10 */
+   uint_8   bDescriptorType;  /* DEVICE QUALIFIER type = 6 */
+   uint_8   bcdUSD[2];        /* USB spec in BCD, e.g. 0x0200 */
+   uint_8   bDeviceClass;     /* Class code, if 0 see interface */
+   uint_8   bDeviceSubClass;  /* Sub-Class code, 0 if class = 0 */
+   uint_8   bDeviceProtocol;  /* Protocol, if 0 see interface */
+   uint_8   bMaxPacketSize;   /* Endpoint 0 max. size */
+   uint_8   bNumConfigurations; /* Number of possible configurations */
+   uint_8   bReserved;        /* Reserved = 0 */ 
+} QUALIFIER_DESCRIPTOR, _PTR_ QUALIFIER_DESCRIPTOR_PTR;  
+
+/* Other-Config type 7 fields are identical to type 2 above */
+
+/* Interface-Power descriptor  type 8 not used  in this version */
+
+typedef struct usb_otg_descriptor
+{
+   uint_8   bLength;          /* Descriptor size in bytes = 9 */
+   uint_8   bDescriptorType;  /* CONFIGURATION type = 2 or 7 */
+   uint_8   bmAttributes;     /* OTG characteristics */
+   #define  OTG_SRP_SUPPORT   (0x01)  /* Supports SRP */
+   #define  OTG_HNP_SUPPORT   (0x02)  /* Supports HNP */
+} OTG_DESCRIPTOR, _PTR_ OTG_DESCRIPTOR_PTR;  
+
+typedef union descriptor_union
+{
+   uint_32                       word;
+   uint_8_ptr                    bufr;
+   pointer                       pntr;
+   DEVICE_DESCRIPTOR_PTR         dvic;
+   CONFIGURATION_DESCRIPTOR_PTR  cfig;
+   INTERFACE_DESCRIPTOR_PTR      intf;
+   ENDPOINT_DESCRIPTOR_PTR       ndpt;
+   QUALIFIER_DESCRIPTOR_PTR      qual;
+   OTG_DESCRIPTOR_PTR            otg;
+}  DESCRIPTOR_UNION, _PTR_ DESCRIPTOR_UNION_PTR;
+                           
+/* Prototypes */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint_32 usb_host_init(uint_8, uint_32, 
+                  _usb_host_handle _PTR_);
+extern uint_32 _usb_host_open_pipe(_usb_host_handle, 
+                  PIPE_INIT_PARAM_STRUCT_PTR, _usb_pipe_handle _PTR_ );
+
+#ifdef __cplusplus
+}
+#endif                         
+
+#endif /* __mvUsbDesc_h__ */
+
+/* EOF */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevCh9.c b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevCh9.c
new file mode 100755
index 0000000..4e46477
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevCh9.c
@@ -0,0 +1,301 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+
+#include "usb/api/mvUsbDevApi.h"
+#include "usb/device/mvUsbDevPrv.h"
+#include "usb/api/mvUsbCh9.h"
+
+static volatile boolean  ENTER_TEST_MODE = FALSE; 
+static volatile uint_16  test_mode_index = 0;
+
+
+void    mvUsbCh9GetStatus(_usb_device_handle handle, boolean setup, 
+                         SETUP_STRUCT* ctrl_req)
+{ /* Body */
+    uint_8                  endpoint, direction;

+    uint_16                 usb_status;

+    USB_DEV_STATE_STRUCT*   usb_dev_ptr = (USB_DEV_STATE_STRUCT*)handle; 

+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup);
+
+    if(!setup)
+        return;
+
+    switch (ctrl_req->REQUESTTYPE) 
+    {
+       case (REQ_DIR_IN | REQ_RECIP_DEVICE):
+          /* Device request */
+          _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status);
+          break;
+
+       case (REQ_DIR_IN | REQ_RECIP_INTERFACE):
+          /* Interface request */
+          _usb_device_get_status(handle, ARC_USB_STATUS_INTERFACE, &usb_status);
+          break;
+    
+       case (REQ_DIR_IN | REQ_RECIP_ENDPOINT):
+          /* Endpoint request */
+          endpoint = ctrl_req->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK;

+          if( (ctrl_req->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN)

+            direction = ARC_USB_SEND;

+          else

+            direction = ARC_USB_RECV;
+
+          usb_status = _usb_device_is_endpoint_stalled(handle, endpoint, direction);

+          break;
+       
+       default:
+          /* Unknown request */
+           USB_printf("GetStatus: Unknown request type 0x%x\n", ctrl_req->REQUESTTYPE);
+          _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+          return;
+    } /* Endswitch */
+
+    /* Send the requested data */
+    *usb_dev_ptr->STATUS_PTR = USB_16BIT_LE(usb_status);
+    _usb_device_send_data(handle, 0, (uint_8_ptr)usb_dev_ptr->STATUS_PTR, sizeof(uint_16));
+    
+    /* status phase */
+    _usb_device_recv_data(handle, 0, NULL, 0);
+    
+    return;
+} /* Endbody */
+
+void    mvUsbCh9ClearFeature(_usb_device_handle handle, boolean setup, 
+                            SETUP_STRUCT* setup_ptr)
+{ /* Body */
+    uint_8   endpoint, direction;
+    uint_16  usb_status;
+     
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup);
+
+    _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_status);
+    if ((usb_status != ARC_USB_STATE_CONFIG) && (usb_status != ARC_USB_STATE_ADDRESS)) 
+    {
+        USB_printf("ClearFeature: Wrong USB state %d\n", usb_status);
+        _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+        return;
+    } /* Endif */
+
+    if(!setup)
+        return;
+
+    switch (setup_ptr->REQUESTTYPE) 
+    {
+        case (REQ_DIR_OUT | REQ_RECIP_DEVICE):
+            /* DEVICE */
+            switch(setup_ptr->VALUE)
+            {
+                case DEVICE_REMOTE_WAKEUP: 
+                    /* clear remote wakeup */
+                    _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status);
+                    usb_status &= ~ARC_USB_REMOTE_WAKEUP;
+                    _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, usb_status);
+                    USB_printf("Clear REMOTE_WAKEUP feature\n");
+                    break;
+
+                case DEVICE_TEST_MODE:
+                    /* Exit Test Mode */
+                    _usb_device_set_status(handle, ARC_USB_STATUS_TEST_MODE, 0);
+                    break;
+
+                default:
+                    USB_printf("ClearFeature: Unknown Device feature %d\n", 
+                                setup_ptr->VALUE);
+                    _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+                    return;
+            } /* Endif */
+            break;
+         
+        case (REQ_DIR_OUT | REQ_RECIP_ENDPOINT):
+            /* ENDPOINT */
+            if (setup_ptr->VALUE != ENDPOINT_HALT) 
+            {
+                USB_printf("ClearFeature: Wrong Endpoint feature %d\n", 
+                            setup_ptr->VALUE);
+                _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+                return;
+            } /* Endif */
+
+            endpoint = setup_ptr->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK;
+            if( (setup_ptr->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN)

+                direction = ARC_USB_SEND;

+            else

+                direction = ARC_USB_RECV;

+

+            _usb_device_unstall_endpoint(handle, endpoint, direction);

+            break;
+
+        default:
+            USB_printf("ClearFeature: Unknown REQUEST_TYPE %d\n", 
+                                setup_ptr->REQUESTTYPE);
+
+            _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+            return;
+    } /* Endswitch */
+      
+    /* status phase */
+    _usb_device_send_data(handle, 0, 0, 0);
+}
+
+void    mvUsbCh9SetFeature(_usb_device_handle handle, boolean setup, 
+                          SETUP_STRUCT* setup_ptr)
+{
+   uint_16                  usb_status;
+   uint_8                   endpoint, direction;
+   USB_DEV_STATE_STRUCT*    usb_dev_ptr = (USB_DEV_STATE_STRUCT*)handle; 
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup);
+
+   if (setup) 
+   {
+      switch (setup_ptr->REQUESTTYPE) 
+      {
+         case (REQ_DIR_OUT | REQ_RECIP_DEVICE):
+            /* DEVICE */
+            switch (setup_ptr->VALUE) 
+            {
+               case DEVICE_REMOTE_WAKEUP:
+                  /* set remote wakeup */
+                  _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status);
+                  usb_status |= ARC_USB_REMOTE_WAKEUP;
+                  _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, usb_status);
+                  USB_printf("Set REMOTE_WAKEUP feature\n");
+                  break;
+
+               case DEVICE_TEST_MODE:
+                  /* Test Mode */
+                  if( (setup_ptr->INDEX & 0x00FF) || (usb_dev_ptr->SPEED != ARC_USB_SPEED_HIGH) ) 
+                  {
+                     USB_printf("SetFeature: Wrong Test mode parameters: mode=%d, speed=%d\n", 
+                                (setup_ptr->INDEX & 0x00FF), usb_dev_ptr->SPEED);
+                     _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+                     return;
+                  } /* Endif */
+
+                  _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_status);
+                  if( (usb_status == ARC_USB_STATE_CONFIG)  || 
+                      (usb_status == ARC_USB_STATE_ADDRESS) || 
+                      (usb_status == ARC_USB_STATE_DEFAULT)) 
+                  {
+                      /* wait with Set Test mode */
+                      ENTER_TEST_MODE = TRUE;
+                      test_mode_index = (setup_ptr->INDEX & 0xFF00);
+                      USB_printf("SetFeature: Prepare for Test mode 0x%x\n", test_mode_index);
+                  } 
+                  else 
+                  {
+                     USB_printf("SetFeature: Wrong USB state for Test mode: state=%d\n", 
+                                usb_status);
+                     _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+                     return;
+                  } /* Endif */
+                  break;
+
+               default:
+                    USB_printf("SetFeature: Unknown Device feature %d\n", 
+                                setup_ptr->VALUE);
+                  _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+                  return;
+            } /* Endswitch */
+            break;
+            
+         case (REQ_DIR_OUT | REQ_RECIP_ENDPOINT):
+            /* ENDPOINT */
+            if (setup_ptr->VALUE != ENDPOINT_HALT) 
+            {
+                USB_printf("SetFeature: Unknown Endpoint feature %d\n", 
+                            setup_ptr->VALUE);
+                _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+                return;
+            } /* Endif */
+
+            endpoint = setup_ptr->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK;
+            if( (setup_ptr->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN)

+                direction = ARC_USB_SEND;

+            else

+                direction = ARC_USB_RECV;

+

+            _usb_device_stall_endpoint(handle, endpoint, direction);

+            break;
+
+         default:
+            USB_printf("SetFeature: Unknown REQUEST_TYPE %d\n", 
+                       setup_ptr->REQUESTTYPE);
+
+            _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+            return;
+      } /* Endswitch */
+      
+      /* status phase */
+      _usb_device_send_data(handle, 0, 0, 0);
+   } 
+   else 
+   {
+      if (ENTER_TEST_MODE) 
+      {
+         /* Enter Test Mode */
+          USB_printf("SetFeature: Activate Test mode 0x%x\n", test_mode_index);
+         _usb_device_set_status(handle, ARC_USB_STATUS_TEST_MODE, test_mode_index);
+      } /* Endif */
+   } /* Endif */
+}
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SetAddress
+* Returned Value : None
+* Comments       :
+*     Chapter 9 SetAddress command
+*     We setup a TX packet of 0 length ready for the IN token
+*     Once we get the TOK_DNE interrupt for the IN token, then
+*     we change the ADDR register and go to the ADDRESS state.
+* 
+*END*--------------------------------------------------------------------*/
+void    mvUsbCh9SetAddress(_usb_device_handle handle,
+                        boolean setup, SETUP_STRUCT* setup_ptr)
+{ /* Body */
+   static uint_8            new_address;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ADDR, "usbDisk %s: setup=%d, address=%d\n", 
+                                    __FUNCTION__, (int)setup, setup_ptr->VALUE);
+
+   if (setup) 
+   {
+      new_address = setup_ptr->VALUE;
+      /*******************************************************
+       * if hardware assitance is enabled for set_address (see
+       * hardware rev for details) we need to do the set_address
+       * before queuing the status phase.
+       *******************************************************/
+#ifdef SET_ADDRESS_HARDWARE_ASSISTANCE      
+       _usb_device_set_status(handle, ARC_USB_STATUS_ADDRESS, new_address);
+#endif
+      /* ack */
+      _usb_device_send_data(handle, 0, 0, 0);
+   } 
+   else 
+   {
+#ifndef SET_ADDRESS_HARDWARE_ASSISTANCE
+      _usb_device_set_status(handle, ARC_USB_STATUS_ADDRESS, new_address);
+#endif
+      _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, ARC_USB_STATE_ADDRESS);        
+   }
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevMain.c b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevMain.c
new file mode 100755
index 0000000..8ba6fdc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevMain.c
@@ -0,0 +1,773 @@
+/*******************************************************************************
+
+This software file (the "File") is distributed by Marvell International Ltd. 
+or its affiliate(s) under the terms of the GNU General Public License Version 2, 
+June 1991 (the "License").  You may use, redistribute and/or modify this File 
+in accordance with the terms and conditions of the License, a copy of which 
+is available along with the File in the license.txt file or by writing to the 
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 
+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+
+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.
+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.
+
+*******************************************************************************/
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#include "usb/api/mvUsbDevApi.h"
+#include "usb/device/mvUsbDevPrv.h"
+
+USB_IMPORT_FUNCS*           global_import_funcs = NULL;
+
+#ifdef USB_UNDERRUN_WA
+USB_WA_FUNCS*               global_wa_funcs = NULL;
+int                         global_wa_threshold = 64;
+int                         global_wa_sram_parts = 2;
+#endif /* USB_UNDERRUN_WA */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_cleanup
+*  Returned Value : void
+*  Comments       :
+*        Cleanup allocated structures.
+*
+*END*-----------------------------------------------------------------*/
+
+static void    _usb_device_cleanup(USB_DEV_STATE_STRUCT_PTR usb_dev_ptr)
+{
+    /* Free all internal transfer descriptors */
+    if(usb_dev_ptr->XD_BASE != NULL)
+    {
+        USB_memfree((pointer)usb_dev_ptr->XD_BASE);
+    }
+   
+    /* Free all XD scratch memory */
+    if(usb_dev_ptr->XD_SCRATCH_STRUCT_BASE != NULL)
+    {
+        USB_memfree((pointer)usb_dev_ptr->XD_SCRATCH_STRUCT_BASE);
+    }
+    /* Free the temp ep init XD */
+    if(usb_dev_ptr->TEMP_XD_PTR != NULL)
+    {
+        USB_memfree((pointer)usb_dev_ptr->TEMP_XD_PTR);
+    }
+
+    if(usb_dev_ptr->STATUS_UNAIGNED_PTR != NULL)
+        USB_memfree((pointer)usb_dev_ptr->STATUS_UNAIGNED_PTR);
+
+    if(usb_dev_ptr->TEST_PKT_UNAIGNED_PTR != NULL)
+        USB_memfree((pointer)usb_dev_ptr->TEST_PKT_UNAIGNED_PTR);
+
+    /* Free the USB state structure */
+    USB_memfree((pointer)usb_dev_ptr);
+}
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_free_XD
+*  Returned Value : void
+*  Comments       :
+*        Enqueues a XD onto the free XD ring.
+*
+*END*-----------------------------------------------------------------*/
+
+void _usb_device_free_XD
+   (
+      /* [IN] the dTD to enqueue */
+      pointer  xd_ptr
+   )
+{ /* Body */
+    int                         lockKey;
+    USB_DEV_STATE_STRUCT_PTR    usb_dev_ptr;
+  
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)(((XD_STRUCT_PTR)xd_ptr)->SCRATCH_PTR->PRIVATE);
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "free_XD: xd_ptr=0x%x\n", (unsigned)xd_ptr);
+
+    ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.free_XD_count++));
+
+   /*
+   ** This function can be called from any context, and it needs mutual
+   ** exclusion with itself.
+   */
+
+   lockKey = USB_lock();
+
+   /*
+   ** Add the XD to the free XD queue (linked via PRIVATE) and
+   ** increment the tail to the next descriptor
+   */
+   USB_XD_QADD(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, (XD_STRUCT_PTR)xd_ptr);
+   usb_dev_ptr->XD_ENTRIES++;
+
+   USB_unlock(lockKey);
+
+} /* Endbody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_set_bsp_funcs
+*  Returned Value : NONE
+*  Comments       :
+*        Set pointer to structure of imported BSP functions
+*
+*END*-----------------------------------------------------------------*/
+void _usb_device_set_bsp_funcs(USB_IMPORT_FUNCS* pBspFuncs)
+{
+    static  boolean isFirst = TRUE;
+    
+    if(isFirst)
+    {
+        global_import_funcs = pBspFuncs;
+       _usb_debug_init_trace_log();
+       isFirst = FALSE;
+    }
+}
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_get_max_endpoint
+*  Returned Value : handle or NULL
+*  Comments       :
+*        Return maximum number of endpoints supportedby USB device 
+*        (for DEBUG only)
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_device_get_max_endpoint(_usb_device_handle handle)
+{
+    USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    return usb_dev_ptr->MAX_ENDPOINTS;
+}
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_get_dev_num
+*  Returned Value : handle or NULL
+*  Comments       :
+*        Return unique USB device number
+*        (for DEBUG only)
+*
+*END*-----------------------------------------------------------------*/
+uint_8  _usb_device_get_dev_num(_usb_device_handle handle)
+{
+    USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    return usb_dev_ptr->DEV_NUM;
+}
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_init
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Initializes the USB device specific data structures and calls 
+*  the low-level device controller chip initialization routine.
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_device_init
+   (
+      /* [IN] the USB device controller to initialize */
+      uint_8                    devnum,
+
+      /* [OUT] the USB_USB_dev_initialize state structure */
+      _usb_device_handle*       handle
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR         usb_dev_ptr;
+   XD_STRUCT_PTR                    xd_ptr;
+   uint_8                           i, error;
+   SCRATCH_STRUCT_PTR               temp_scratch_ptr;
+
+   /* global_import_funcs must be initailized before */
+   if(global_import_funcs == NULL)
+       return USBERR_INIT_FAILED;
+
+   if (devnum > MAX_USB_DEVICES)
+   {
+        USB_printf("_usb_device_init, error invalid device number");
+        return USBERR_INVALID_DEVICE_NUM;
+   } /* Endif */
+   
+   /* Allocate memory for the state structure */
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)USB_memalloc(sizeof(USB_DEV_STATE_STRUCT));      
+   if (usb_dev_ptr == NULL) 
+   {
+        USB_printf("_usb_device_init, malloc of %d bytes for USB_DEV_STATE_STRUCT failed\n", 
+                    sizeof(USB_DEV_STATE_STRUCT));
+        return USBERR_ALLOC_STATE;
+   } /* Endif */
+   
+   /* Zero out the internal USB state structure */
+   USB_memzero(usb_dev_ptr, sizeof(USB_DEV_STATE_STRUCT));
+    
+   usb_dev_ptr->DEV_NUM = devnum;
+
+   /* Multiple devices will have different base addresses and 
+   ** interrupt vectors (For future)
+   */   
+   usb_dev_ptr->USB_STATE = ARC_USB_STATE_UNKNOWN;
+   
+   /* Allocate MAX_XDS_FOR_TR_CALLS */
+   xd_ptr = (XD_STRUCT_PTR)USB_memalloc(sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS);      
+   if (xd_ptr == NULL) 
+   {
+        _usb_device_cleanup(usb_dev_ptr);
+        USB_printf("_usb_device_init, malloc of %d bytes for %d XD_STRUCT failed\n", 
+                        sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS, MAX_XDS_FOR_TR_CALLS);
+        return USBERR_ALLOC_TR;
+   } /* Endif */
+   
+   usb_dev_ptr->XD_BASE = xd_ptr;
+
+   _usb_clear_stats(usb_dev_ptr);
+
+   USB_memzero(xd_ptr, sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS);
+
+   /* Allocate memory for internal scratch structure */   
+   usb_dev_ptr->XD_SCRATCH_STRUCT_BASE = (SCRATCH_STRUCT_PTR)
+                    USB_memalloc(sizeof(SCRATCH_STRUCT) * MAX_XDS_FOR_TR_CALLS);
+   if (usb_dev_ptr->XD_SCRATCH_STRUCT_BASE == NULL) 
+   {
+        _usb_device_cleanup(usb_dev_ptr);
+        USB_printf("_usb_device_init, malloc of %d bytes for %d XD_STRUCT failed\n", 
+                        sizeof(SCRATCH_STRUCT) * MAX_XDS_FOR_TR_CALLS, MAX_XDS_FOR_TR_CALLS);
+        return USBERR_ALLOC;
+   } /* Endif */
+
+   temp_scratch_ptr = usb_dev_ptr->XD_SCRATCH_STRUCT_BASE;
+   usb_dev_ptr->XD_HEAD = NULL;
+   usb_dev_ptr->XD_TAIL = NULL;
+   usb_dev_ptr->XD_ENTRIES = 0;
+
+   /* Enqueue all the XDs */   
+   for (i=0;i<MAX_XDS_FOR_TR_CALLS;i++) 
+   {
+      xd_ptr->SCRATCH_PTR = temp_scratch_ptr;
+      xd_ptr->SCRATCH_PTR->FREE = _usb_device_free_XD;
+      xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr;
+      _usb_device_free_XD((pointer)xd_ptr);
+      xd_ptr++;
+      temp_scratch_ptr++;
+   } /* Endfor */
+
+   usb_dev_ptr->TEMP_XD_PTR = (XD_STRUCT_PTR)USB_memalloc(sizeof(XD_STRUCT));
+   if(usb_dev_ptr->TEMP_XD_PTR == NULL)
+   {
+        USB_printf("_usb_device_init, malloc of %d bytes for TEMP_XD_STRUCT failed\n", 
+                        sizeof(XD_STRUCT));
+        _usb_device_cleanup(usb_dev_ptr);
+        return USBERR_ALLOC;
+   }
+   USB_memzero(usb_dev_ptr->TEMP_XD_PTR, sizeof(XD_STRUCT));
+
+   /* Allocate 2 bytes for USB_STATUS to be sent over USB, so Cache line aligned */
+   usb_dev_ptr->STATUS_UNAIGNED_PTR = (uint_8*)USB_memalloc(sizeof(uint_16) + PSP_CACHE_LINE_SIZE);
+   if(usb_dev_ptr->STATUS_UNAIGNED_PTR == NULL)
+   {
+        USB_printf("_usb_device_init, malloc of %d bytes for USB_STATUS failed\n", 
+                        sizeof(uint_16) + PSP_CACHE_LINE_SIZE);
+        _usb_device_cleanup(usb_dev_ptr);
+        return USBERR_ALLOC;
+   }
+   USB_memzero(usb_dev_ptr->STATUS_UNAIGNED_PTR, sizeof(uint_16) + PSP_CACHE_LINE_SIZE);
+   usb_dev_ptr->STATUS_PTR = (uint_16*)USB_CACHE_ALIGN((uint_32)usb_dev_ptr->STATUS_UNAIGNED_PTR);
+
+   /* Allocate 53 bytes for USB Test packet to be sent over USB, so Cache line aligned */
+   usb_dev_ptr->TEST_PKT_UNAIGNED_PTR = (uint_8*)USB_memalloc(USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE);
+   if(usb_dev_ptr->TEST_PKT_UNAIGNED_PTR == NULL)
+   {
+        USB_printf("_usb_device_init, malloc of %d bytes for USB Test packet failed\n", 
+                        USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE);
+        _usb_device_cleanup(usb_dev_ptr);
+        return USBERR_ALLOC;
+   }
+   USB_memzero(usb_dev_ptr->TEST_PKT_UNAIGNED_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE);
+   usb_dev_ptr->TEST_PKT_PTR = (uint_8*)USB_CACHE_ALIGN((uint_32)usb_dev_ptr->TEST_PKT_UNAIGNED_PTR);
+
+   /* Initialize the USB controller chip */
+   error = _usb_dci_vusb20_init(devnum, usb_dev_ptr);
+   if (error) 
+   {
+        _usb_device_cleanup(usb_dev_ptr);
+        USB_printf("_usb_device_init, init failed");
+        return USBERR_INIT_FAILED;
+   } /* Endif */
+
+   USB_printf("device_init: pDev=0x%x, pXD(%d)=0x%x, pSCRATCH(%d)=0x%x, pTempXD=0x%x\n",
+                (unsigned)usb_dev_ptr, MAX_XDS_FOR_TR_CALLS, (unsigned)usb_dev_ptr->XD_BASE,
+                MAX_XDS_FOR_TR_CALLS, (unsigned)usb_dev_ptr->XD_SCRATCH_STRUCT_BASE,
+                (unsigned)usb_dev_ptr->TEMP_XD_PTR);
+
+   *handle = usb_dev_ptr;
+   return USB_OK;   
+} /* EndBody */
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_shutdown
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Shutdown an initialized USB device
+*
+*END*-----------------------------------------------------------------*/
+void _usb_device_shutdown(_usb_device_handle handle)
+{ /* Body */
+    USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+    SERVICE_STRUCT_PTR           service_ptr;
+    int                          ep;
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_CTRL, "shutdown\n");
+   
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    for(ep=0; ep<(usb_dev_ptr->MAX_ENDPOINTS); ep++)
+    {
+        /* Cancel all transfers on all endpoints */
+        while(_usb_device_get_transfer_status(handle, ep, ARC_USB_RECV) != 
+                                                    ARC_USB_STATUS_IDLE)
+        {
+            _usb_device_cancel_transfer(handle, ep, ARC_USB_RECV);
+        }
+        while(_usb_device_get_transfer_status(handle, ep, ARC_USB_SEND) != 
+                                                    ARC_USB_STATUS_IDLE)
+        {
+            _usb_device_cancel_transfer(handle, ep, ARC_USB_SEND);
+        }
+    }
+    _usb_dci_vusb20_shutdown(usb_dev_ptr);
+   
+    /* Free all the Callback function structure memory */
+    for( service_ptr = usb_dev_ptr->SERVICE_HEAD_PTR; service_ptr;
+         service_ptr = service_ptr->NEXT) 
+    {
+        USB_printf("_usb_device_shutdown: free service_ptr = 0x%x\n", 
+                            service_ptr);
+        USB_memfree(service_ptr);
+    }
+    usb_dev_ptr->SERVICE_HEAD_PTR = NULL;
+
+    _usb_device_cleanup(usb_dev_ptr);
+} /* EndBody */
+
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _usb_device_register_service
+* Returned Value : USB_OK or error code
+* Comments       :
+*     Registers a callback routine for a specified event or endpoint.
+* 
+*END*--------------------------------------------------------------------*/
+uint_8 _usb_device_register_service
+   (
+      /* [IN] Handle to the USB device */
+      _usb_device_handle         handle,
+      
+      /* [IN] type of event or endpoint number to service */
+      uint_8                     type,
+      
+      /* [IN] Pointer to the service's callback function */
+      void(_CODE_PTR_ service)(pointer, uint_8, boolean, uint_8, uint_8_ptr, uint_32, uint_8)
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR   usb_dev_ptr;
+   SERVICE_STRUCT_PTR         service_ptr;
+   SERVICE_STRUCT_PTR _PTR_   search_ptr;
+   int                        lockKey;
+ 
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   /* Needs mutual exclusion */
+   lockKey = USB_lock();
+   
+   /* Search for an existing entry for type */
+   for (search_ptr = &usb_dev_ptr->SERVICE_HEAD_PTR;
+      *search_ptr;
+      search_ptr = &(*search_ptr)->NEXT) 
+   {
+      if ((*search_ptr)->TYPE == type) 
+      {
+         /* Found an existing entry */
+         USB_unlock(lockKey);
+         USB_printf("_usb_device_register_service, service %d already opened\n");
+         return USBERR_OPEN_SERVICE;
+      } /* Endif */
+   } /* Endfor */
+   
+   /* No existing entry found - create a new one */
+   service_ptr = (SERVICE_STRUCT_PTR)USB_memalloc(sizeof(SERVICE_STRUCT));
+   if (!service_ptr) 
+   {
+      USB_unlock(lockKey);
+      USB_printf("_usb_device_register_service, malloc for %d bytes failed\n", 
+                    sizeof(SERVICE_STRUCT));
+      return USBERR_ALLOC;
+   } /* Endif */
+
+   service_ptr->TYPE = type;
+   service_ptr->SERVICE = service;
+   service_ptr->NEXT = NULL;
+   *search_ptr = service_ptr;
+   
+   USB_unlock(lockKey);
+
+   return USB_OK;
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _usb_device_unregister_service
+* Returned Value : USB_OK or error code
+* Comments       :
+*     Unregisters a callback routine for a specified event or endpoint.
+* 
+*END*--------------------------------------------------------------------*/
+uint_8 _usb_device_unregister_service
+   (
+      /* [IN] Handle to the USB device */
+      _usb_device_handle         handle,
+
+      /* [IN] type of event or endpoint number to service */
+      uint_8                     type
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR   usb_dev_ptr;
+   SERVICE_STRUCT_PTR         service_ptr;
+   SERVICE_STRUCT_PTR _PTR_   search_ptr;
+   int                        lockKey;
+ 
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   /* Needs mutual exclusion */
+   lockKey = USB_lock();
+   
+   /* Search for an existing entry for type */
+   for (search_ptr = &usb_dev_ptr->SERVICE_HEAD_PTR;
+      *search_ptr;
+      search_ptr = &(*search_ptr)->NEXT) 
+   {
+      if ((*search_ptr)->TYPE == type) {
+         /* Found an existing entry - delete it */
+         break;
+      } /* Endif */
+   } /* Endfor */
+   
+   /* No existing entry found */
+   if (!*search_ptr) 
+   {
+      USB_unlock(lockKey);
+      USB_printf("_usb_device_unregister_service, no service found\n");
+      return USBERR_CLOSED_SERVICE;
+   } /* Endif */
+   
+   service_ptr = *search_ptr;
+   *search_ptr = service_ptr->NEXT;
+
+   USB_memfree((pointer)service_ptr);
+   
+   USB_unlock(lockKey);
+
+   return USB_OK;
+
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _usb_device_call_service
+* Returned Value : USB_OK or error code
+* Comments       :
+*     Calls the appropriate service for the specified type, if one is
+*     registered. Used internally only.
+* 
+*END*--------------------------------------------------------------------*/
+uint_8 _usb_device_call_service
+   (
+      /* [IN] Handle to the USB device */
+      _usb_device_handle   handle,
+
+      /* [OUT] Type of service or endpoint */
+      uint_8               type,
+      
+      /* [OUT] Is it a Setup transfer? */
+      boolean              setup,
+      
+      /* [OUT] Direction of transmission; is it a Transmit? */
+      boolean              direction,
+
+      /* [OUT] Pointer to the data */
+      uint_8_ptr           buffer_ptr,
+      
+      /* [OUT] Number of bytes in transmission */
+      uint_32              length,
+
+      /* [OUT] Any errors */
+      uint_8               errors
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   SERVICE_STRUCT _PTR_         service_ptr;
+   int                          lockKey;
+
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   /* Needs mutual exclusion */
+   lockKey = USB_lock();
+   
+   /* Search for an existing entry for type */
+   for (service_ptr = usb_dev_ptr->SERVICE_HEAD_PTR;
+        service_ptr;
+        service_ptr = service_ptr->NEXT) 
+   {
+      if (service_ptr->TYPE == type) 
+      {
+#ifdef CONFIG_MV_SP_I_FTCH_DB_INV
+        if( (direction == ARC_USB_RECV) && (buffer_ptr != NULL) && (length > 0) )
+            USB_dcache_inv( buffer_ptr, length);   
+#endif /* CONFIG_MV_SP_I_FTCH_DB_INV */
+
+         service_ptr->SERVICE(handle, type, setup, direction, buffer_ptr, length, errors);
+         USB_unlock(lockKey);
+
+         return USB_OK;
+      } /* Endif */
+      
+   } /* Endfor */
+
+   USB_unlock(lockKey);
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_CTRL, "_usb_device_call_service, service %d is closed\n", type);
+
+   return USBERR_CLOSED_SERVICE;
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_init_endpoint
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*     Initializes the endpoint and the data structures associated with the 
+*  endpoint
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_device_init_endpoint
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] MAX Packet size for this endpoint */
+      uint_16                    max_pkt_size,
+            
+      /* [IN] Direction */
+      uint_8                     direction,
+            
+      /* [IN] Type of Endpoint */
+      uint_8                     type,
+            
+      /* [IN] After all data is transfered, should we terminate the transfer 
+      ** with a zero length packet if the last packet size == MAX_PACKET_SIZE? 
+      */
+      uint_8                     flag   
+   )
+{ /* Body */
+
+    int                         lockKey;
+    uint_8                      error = 0;
+    USB_DEV_STATE_STRUCT_PTR    usb_dev_ptr;
+   
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    /* Initialize the transfer descriptor */
+    usb_dev_ptr->TEMP_XD_PTR->EP_NUM = ep_num;
+    usb_dev_ptr->TEMP_XD_PTR->BDIRECTION = direction;
+    usb_dev_ptr->TEMP_XD_PTR->WMAXPACKETSIZE = max_pkt_size;
+    usb_dev_ptr->TEMP_XD_PTR->EP_TYPE = type;
+    usb_dev_ptr->TEMP_XD_PTR->DONT_ZERO_TERMINATE = flag;
+    usb_dev_ptr->TEMP_XD_PTR->MAX_PKTS_PER_UFRAME = 
+                    ((flag & ARC_USB_MAX_PKTS_PER_UFRAME) >> 1);
+
+    lockKey = USB_lock();
+    error = _usb_dci_vusb20_init_endpoint(handle, usb_dev_ptr->TEMP_XD_PTR);
+    USB_unlock(lockKey);
+   
+   return error;
+
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_deinit_endpoint
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*  Disables the endpoint and the data structures associated with the 
+*  endpoint
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_device_deinit_endpoint
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                    ep_num,
+            
+      /* [IN] Direction */
+      uint_8                    direction
+   )
+{ /* Body */
+   int                          lockKey;
+   uint_8                       error = 0;
+   lockKey = USB_lock();
+
+   error = _usb_dci_vusb20_deinit_endpoint(handle, ep_num, direction);
+   
+   USB_unlock(lockKey);
+   
+   return error;
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_get_transfer_status
+*  Returned Value : Status of the transfer
+*  Comments       :
+*        returns the status of the transaction on the specified endpoint.
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_device_get_transfer_status
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   uint_8                       status;
+   int                          lockKey;
+
+   lockKey = USB_lock();
+
+   status = _usb_dci_vusb20_get_transfer_status(handle, ep_num, direction);
+
+   USB_unlock(lockKey);
+
+   /* Return the status of the last queued transfer */
+   return (status);
+
+} /* EndBody */
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_read_setup_data
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Reads the setup data from the hardware
+*
+*END*-----------------------------------------------------------------*/
+void _usb_device_read_setup_data
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] buffer for receiving Setup packet */
+      uint_8_ptr                  buff_ptr
+   )
+{ /* Body */
+   int                           lockKey;
+ 
+   lockKey = USB_lock();
+
+   _usb_dci_vusb20_get_setup_data(handle, ep_num, buff_ptr);
+
+   USB_unlock(lockKey);
+
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_cancel_transfer
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        returns the status of the transaction on the specified endpoint.
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_device_cancel_transfer
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   uint_8                        error = USB_OK;
+   int                           lockKey;
+   
+   lockKey = USB_lock();
+
+   /* Cancel transfer on the specified endpoint for the specified 
+   ** direction 
+   */
+   error = _usb_dci_vusb20_cancel_transfer(handle, ep_num, direction);
+
+   USB_unlock(lockKey);
+
+   return error;
+} /* EndBody */
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_stop
+*  Returned Value : None
+*  Comments       :
+*        Stop USB device
+*
+*END*-----------------------------------------------------------------*/
+void _usb_device_stop(_usb_device_handle handle)
+{
+    int         lockKey;
+
+    lockKey = USB_lock();
+    _usb_dci_vusb20_stop(handle);
+    USB_unlock(lockKey);
+}
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_start
+*  Returned Value : None
+*  Comments       :
+*        Start USB device
+*
+*END*-----------------------------------------------------------------*/
+void _usb_device_start(_usb_device_handle handle)
+{
+    int         lockKey;
+
+    lockKey = USB_lock();
+    _usb_dci_vusb20_start(handle);
+    USB_unlock(lockKey);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevPrv.h b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevPrv.h
new file mode 100755
index 0000000..597bdcf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevPrv.h
@@ -0,0 +1,267 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __mvUsbDevPrv_h__
+#define __mvUsbDevPrv_h__
+

+#include "usb/common/mvUsbCore.h"
+
+
+#define USB_TEST_MODE_TEST_PACKET_LENGTH   (53)
+
+ 
+#define USB_XD_QADD(head,tail,XD)      \
+   if ((head) == NULL) {         \
+      (head) = (XD);            \
+   } else {                      \
+      (tail)->SCRATCH_PTR->PRIVATE = (XD);   \
+   } /* Endif */                 \
+   (tail) = (XD);               \
+   (XD)->SCRATCH_PTR->PRIVATE = NULL
+   
+#define USB_XD_QGET(head,tail,XD)      \
+   (XD) = (head);               \
+   if (head) {                   \
+      (head) = (XD_STRUCT_PTR)((head)->SCRATCH_PTR->PRIVATE);  \
+      if ((head) == NULL) {      \
+         (tail) = NULL;          \
+      } /* Endif */              \
+   } /* Endif */
+
+#define EHCI_DTD_QADD(head,tail,dTD)      \
+   if ((head) == NULL) {         \
+      (head) = (dTD);            \
+   } else {                      \
+      (tail)->SCRATCH_PTR->PRIVATE = (void *) (dTD);   \
+   } /* Endif */                 \
+   (tail) = (dTD);               \
+   (dTD)->SCRATCH_PTR->PRIVATE = NULL
+   
+#define EHCI_DTD_QGET(head,tail,dTD)      \
+   (dTD) = (head);               \
+   if (head) {                   \
+      (head) = (head)->SCRATCH_PTR->PRIVATE;  \
+      if ((head) == NULL) {      \
+         (tail) = NULL;          \
+      } /* Endif */              \
+   } /* Endif */
+
+/***************************************
+**
+** Data structures
+**
+*/
+
+typedef struct
+{
+    uint_32     usb_isr_count;
+    uint_32     usb_reset_count;
+    uint_32     usb_send_count;
+    uint_32     usb_recv_count;
+    uint_32     usb_setup_count;
+    uint_32     free_XD_count;
+    uint_32     free_dTD_count;
+    uint_32     usb_cancel_count;
+    uint_32     usb_add_count;
+    uint_32     usb_add_not_empty_count;
+    uint_32     usb_empty_isr_count;
+    uint_32     usb_empty_complete_count;
+    uint_32     usb_read_setup_count;
+    uint_32     usb_complete_isr_count;
+    uint_32     usb_complete_count;
+    uint_32     usb_complete_max_count;
+    uint_32     usb_port_change_count; 
+    uint_32     usb_suspend_count;
+    uint_32     usb_complete_ep_count[ARC_USB_MAX_ENDPOINTS*2];
+
+} USB_STATS;
+
+
+
+/* Callback function storage structure */
+typedef struct service_struct 
+{
+    uint_8   TYPE;
+    void     (_CODE_PTR_ SERVICE)(pointer, uint_8, boolean, uint_8, uint_8_ptr, uint_32, uint_8);
+    struct service_struct _PTR_   NEXT;
+
+} SERVICE_STRUCT, _PTR_ SERVICE_STRUCT_PTR;
+
+typedef struct xd_struct 
+{
+    uint_8         EP_NUM;           /* Endpoint number */
+    uint_8         BDIRECTION;       /* Direction : Send/Receive */
+    uint_8         EP_TYPE;          /* Type of the endpoint: Ctrl, Isoch, Bulk, Int */
+    uint_8         BSTATUS;          /* Current transfer status */
+    uint_8_ptr     WSTARTADDRESS;    /* Address of first byte */
+    uint_32        WTOTALLENGTH;     /* Number of bytes to send/recv */
+    uint_32        WSOFAR;           /* Number of bytes recv'd so far */
+    uint_16        WMAXPACKETSIZE;   /* Max Packet size */
+    boolean        DONT_ZERO_TERMINATE;
+    uint_8         MAX_PKTS_PER_UFRAME;
+    SCRATCH_STRUCT *SCRATCH_PTR;
+} XD_STRUCT, _PTR_ XD_STRUCT_PTR;
+
+/* The USB Device State Structure */
+typedef struct 
+{
+    boolean                          BUS_RESETTING;       /* Device is 
+                                                         ** being reset */
+    volatile VUSB20_REG_STRUCT_PTR   CAP_REGS_PTR;        /* Capabilities registers */
+
+    volatile VUSB20_REG_STRUCT_PTR   DEV_PTR;            /* Device Controller 
+                                                         ** Register base 
+                                                         ** address */
+
+    SERVICE_STRUCT_PTR               SERVICE_HEAD_PTR;   /* Head struct 
+                                                         ** address of 
+                                                         ** registered services 
+                                                         */
+    XD_STRUCT_PTR                    TEMP_XD_PTR;         /* Temp xd for ep init */
+    XD_STRUCT_PTR                    XD_BASE;
+    XD_STRUCT_PTR                    XD_HEAD;             /* Head Transaction 
+                                                         ** descriptors 
+                                                         */
+    XD_STRUCT_PTR                    XD_TAIL;             /* Tail Transaction 
+                                                         ** descriptors 
+                                                         */
+    uint_32                          XD_ENTRIES;
+    uint_8*                          EP_QUEUE_HEAD_BASE;
+    uint_32                          EP_QUEUE_HEAD_PHYS;
+    uint_32                          EP_QUEUE_HEAD_SIZE;
+    VUSB20_EP_QUEUE_HEAD_STRUCT_PTR  EP_QUEUE_HEAD_PTR;   /* Endpoint Queue head */   
+
+    uint_8*                          DTD_BASE_PTR;        /* Device transfer descriptor pool address */
+    uint_32                          DTD_BASE_PHYS;
+    uint_32                          DTD_SIZE;
+    VUSB20_EP_TR_STRUCT_PTR          DTD_ALIGNED_BASE_PTR;/* Aligned transfer descriptor pool address */
+
+    VUSB20_EP_TR_STRUCT_PTR          DTD_HEAD;
+    VUSB20_EP_TR_STRUCT_PTR          DTD_TAIL;
+    VUSB20_EP_TR_STRUCT_PTR          EP_DTD_HEADS[ARC_USB_MAX_ENDPOINTS * 2];
+    VUSB20_EP_TR_STRUCT_PTR          EP_DTD_TAILS[ARC_USB_MAX_ENDPOINTS * 2];
+    SCRATCH_STRUCT_PTR               XD_SCRATCH_STRUCT_BASE;
+   
+   
+    SCRATCH_STRUCT_PTR               SCRATCH_STRUCT_BASE;
+   
+    uint_16                          USB_STATE;
+    uint_16                          USB_DEVICE_STATE;
+    uint_16                          USB_SOF_COUNT;
+    uint_16                          DTD_ENTRIES;
+    uint_16                          ERRORS;

+    uint_16                          ERROR_STATE;
+    uint_16                          USB_DEV_STATE_B4_SUSPEND;
+    uint_8                           DEV_NUM;             /* USB device number 
+                                                         ** on the board 
+                                                         */
+    uint_8                           SPEED;               /* Low Speed, 
+                                                         ** High Speed, 
+                                                         ** Full Speed 
+                                                         */
+    uint_8                           MAX_ENDPOINTS;       /* Max endpoints
+                                                         ** supported by this
+                                                         ** device
+                                                         */
+                                                         
+    uint_8                           USB_CURR_CONFIG;                                                         
+    uint_8                           DEVICE_ADDRESS;
+    uint_8                           FORCE_FS;
+    USB_STATS                        STATS;
+
+    uint_8*                          STATUS_UNAIGNED_PTR;
+    uint_16*                         STATUS_PTR;
+
+    uint_8*                          TEST_PKT_UNAIGNED_PTR;
+    uint_8*                          TEST_PKT_PTR;
+
+} USB_DEV_STATE_STRUCT, _PTR_ USB_DEV_STATE_STRUCT_PTR;
+
+/* ONLY For data bases allocated by the driver (when PHYS and VIRT bases are known) */
+#define USB_EP_QH_VIRT_TO_PHYS(handle, virtAddr)                                                    \
+    (((virtAddr) == NULL) ? 0 : ((handle)->EP_QUEUE_HEAD_PHYS +                                \
+                          ((uint_32)(virtAddr) - (uint_32)(handle)->EP_QUEUE_HEAD_BASE)))
+
+#define USB_DTD_VIRT_TO_PHYS(handle, virtAddr)                                                    \
+    (((virtAddr) == NULL) ? 0 : ((handle)->DTD_BASE_PHYS +                                \
+                          ((uint_32)(virtAddr) - (uint_32)(handle)->DTD_BASE_PTR)))
+
+#define USB_DTD_PHYS_TO_VIRT(handle, physAddr)                                                    \
+    (((physAddr) == 0) ? NULL : ((handle)->DTD_BASE_PTR +                             \
+                                ((physAddr) - (handle)->DTD_BASE_PHYS)))
+
+
+/***************************************
+**
+** Prototypes
+**
+*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint_8  _usb_device_call_service(void* handle, uint_8, boolean,
+                                 boolean, uint_8_ptr, uint_32, uint_8);
+
+extern uint_8   _usb_dci_vusb20_init(uint_8, _usb_device_handle);
+extern void     _usb_device_free_XD(pointer);
+extern void     _usb_dci_vusb20_free_dTD(pointer);
+extern uint_8   _usb_dci_vusb20_add_dTD(_usb_device_handle, XD_STRUCT_PTR);
+extern uint_8   _usb_dci_vusb20_cancel_transfer(_usb_device_handle, uint_8, uint_8);
+extern uint_8   _usb_dci_vusb20_get_transfer_status(_usb_device_handle, uint_8, uint_8);
+extern XD_STRUCT_PTR _usb_dci_vusb20_get_transfer_details(_usb_device_handle, uint_8, uint_8);
+extern void     _usb_dci_vusb20_process_tr_complete(_usb_device_handle);
+extern void     _usb_dci_vusb20_process_reset(_usb_device_handle);
+extern void     _usb_dci_vusb20_process_tr_complete(_usb_device_handle);
+extern void     _usb_dci_vusb20_process_suspend(_usb_device_handle);
+extern void     _usb_dci_vusb20_process_SOF(_usb_device_handle);
+extern void     _usb_dci_vusb20_process_port_change(_usb_device_handle);
+extern void     _usb_dci_vusb20_process_error(_usb_device_handle);
+extern void     _usb_dci_vusb20_shutdown(_usb_device_handle);
+extern void     _usb_dci_vusb20_set_speed_full(_usb_device_handle, uint_8);
+extern void     _usb_dci_vusb20_suspend_phy(_usb_device_handle, uint_8);
+extern void     _usb_dci_vusb20_hnp_shutdown(void);
+extern void     _usb_dci_vusb20_set_address(_usb_device_handle, uint_8);
+extern void     _usb_dci_vusb20_get_setup_data(_usb_device_handle, uint_8, uint_8_ptr);
+extern void     _usb_dci_vusb20_assert_resume(_usb_device_handle);
+extern uint_8   _usb_dci_vusb20_init_endpoint(_usb_device_handle, XD_STRUCT_PTR);
+extern void     _usb_dci_vusb20_stall_endpoint(_usb_device_handle, uint_8, uint_8);
+extern void     _usb_dci_vusb20_unstall_endpoint(_usb_device_handle, uint_8, uint_8);

+extern uint_8   _usb_dci_vusb20_is_endpoint_stalled(_usb_device_handle, uint_8, uint_8);
+extern uint_8   _usb_dci_vusb20_deinit_endpoint(_usb_device_handle, uint_8, uint_8);
+extern void     _usb_dci_vusb20_chip_initialize(_usb_device_handle);
+extern void     _usb_dci_vusb20_stop(_usb_device_handle handle);
+extern void     _usb_dci_vusb20_start(_usb_device_handle handle);
+
+#if defined(USB_UNDERRUN_WA)
+
+extern uint_8*  usbSramBase;
+extern int      usbSramSize;
+
+void    _usb_reset_send_queue(void);
+void    usbSendComplete(void* handle, uint_8 type, boolean setup, uint_8 dir, 
+                        uint_8_ptr buffer, uint_32 length, uint_8 error);
+#endif /* USB_UNDERRUN_WA */
+                         
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevRecv.c b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevRecv.c
new file mode 100755
index 0000000..15f8dac
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevRecv.c
@@ -0,0 +1,99 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#include "usb/api/mvUsbDevApi.h"
+#include "usb/device/mvUsbDevPrv.h"
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_recv_data
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Receives data on a specified endpoint.
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_device_recv_data
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] buffer to receive data */
+      uint_8_ptr                 buff_ptr,
+            
+      /* [IN] length of the transfer */
+      uint_32                    size
+   )
+{ /* Body */
+    int                              lockKey;
+    uint_8                           error = USB_OK;
+    XD_STRUCT_PTR                    xd_ptr;
+    USB_DEV_STATE_STRUCT_PTR         usb_dev_ptr;
+   
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_RX, "recv_data: ep=%d, buf_ptr=0x%x, size=%d\n",
+                                       ep_num, (unsigned)buff_ptr, (int)size);
+
+    ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_recv_count++));
+
+    if(buff_ptr != NULL)
+        USB_dcache_inv((pointer)buff_ptr,size);   
+    
+    lockKey = USB_lock();
+
+    if (!usb_dev_ptr->XD_ENTRIES) 
+    {
+        USB_unlock(lockKey);
+        USB_printf("_usb_device_recv_data, transfer in progress\n");
+        return ARC_USB_STATUS_TRANSFER_IN_PROGRESS;
+    } /* Endif */
+
+    /* Get a transfer descriptor for the specified endpoint 
+    ** and direction 
+    */
+    USB_XD_QGET(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, xd_ptr);
+   
+    usb_dev_ptr->XD_ENTRIES--;
+
+    /* Initialize the new transfer descriptor */      
+    xd_ptr->EP_NUM = ep_num;
+    xd_ptr->BDIRECTION = ARC_USB_RECV;
+    xd_ptr->WTOTALLENGTH = size;
+    xd_ptr->WSOFAR = 0;
+    xd_ptr->WSTARTADDRESS = buff_ptr;
+   
+    xd_ptr->BSTATUS = ARC_USB_STATUS_TRANSFER_ACCEPTED;
+
+    error = _usb_dci_vusb20_add_dTD(handle, xd_ptr);
+
+    USB_unlock(lockKey);
+   
+    if (error) 
+    {
+        USB_printf("_usb_device_recv_data, receive failed\n");
+        return USBERR_RX_FAILED;
+    } /* Endif */
+
+    return error;
+
+} /* EndBody */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevSend.c b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevSend.c
new file mode 100755
index 0000000..3481e30
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevSend.c
@@ -0,0 +1,373 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+
+#include "usb/api/mvUsbDevApi.h"
+#include "usb/device/mvUsbDevPrv.h"
+
+#if defined(USB_UNDERRUN_WA)
+
+typedef struct
+{
+    uint_8*     buff_ptr[MAX_XDS_FOR_TR_CALLS];
+    uint_32     size[MAX_XDS_FOR_TR_CALLS];
+    uint_8      ep_num[MAX_XDS_FOR_TR_CALLS];
+    int         head;
+    int         tail;
+    int         tail_dma;
+    int         num;
+    int         num_dma;
+
+} USB_SEND_QUEUE;
+
+uint_8*         usbSramBase;
+int             usbSramSize;
+int		        usbSramPartSize;
+USB_SEND_QUEUE  usbSendQueue;
+
+uint_32         usbSentSize = 0;
+uint_32         usbDmaSize = 0;
+
+#define S_FREE	    0
+#define S_BUSY	    1
+
+uint_32		    dma_index = 0;
+uint_32		    sent_index = 0;
+uint_32		    sram_parts[USB_SRAM_MAX_PARTS];
+
+
+void    _usb_reset_send_queue(void)
+{
+    int     i;
+
+    usbSendQueue.num = 0;
+	usbSendQueue.num_dma = 0;
+    usbSendQueue.head = 0;
+    usbSendQueue.tail = 0;
+	usbSendQueue.tail_dma = 0;
+    for(i=0; i<MAX_XDS_FOR_TR_CALLS; i++)
+    {
+        usbSendQueue.size[i] = 0;
+        usbSendQueue.buff_ptr[i] = NULL;
+        usbSendQueue.ep_num[i] = 0;
+    }        
+	usbSramPartSize = usbSramSize/global_wa_sram_parts;
+
+    for(i=0; i<global_wa_sram_parts; i++)
+    {
+		sram_parts[i] = S_FREE;
+    }
+}
+
+uint_8 _usb_prepare_to_send(void*   handle)
+{
+    XD_STRUCT_PTR               xd_ptr;
+    USB_DEV_STATE_STRUCT_PTR    usb_dev_ptr;
+    uint_8*                     buff_ptr;
+    uint_8*			            tmp_buff;
+    uint_32                     size;
+    int                         num_dma, tail_dma, i;
+    uint_8			            error = 0;
+
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    tail_dma = usbSendQueue.tail_dma;
+    num_dma = usbSendQueue.num_dma;
+    buff_ptr = usbSendQueue.buff_ptr[tail_dma];
+    size = usbSendQueue.size[tail_dma];
+
+    if(num_dma == 0)
+	    return 0;
+
+/*
+    USB_printf("_usb_prepare_to_send: num=%d, tail=%d, sentSize=%d, size=%d, buff=%p\n", 
+                num_dma, tail_dma, usbSentSize, size, buff_ptr);
+*/
+    for(i=0; i<global_wa_sram_parts; i++)
+    {
+	    if(sram_parts[dma_index] != S_FREE)
+	        break;
+	
+	    if(usbDmaSize >= usbSendQueue.size[tail_dma])
+	    {
+	        /* Remove from the usbSendQueues */
+	        num_dma--;
+            tail_dma++;
+            if(tail_dma == MAX_XDS_FOR_TR_CALLS)
+                tail_dma = 0;
+
+            usbSendQueue.tail_dma = tail_dma;
+            usbSendQueue.num_dma = num_dma;
+            usbDmaSize = 0;
+
+            if(num_dma == 0)
+                break;
+        }
+
+	    buff_ptr = usbSendQueue.buff_ptr[tail_dma] + usbDmaSize;
+	    size = MIN(usbSramPartSize, (usbSendQueue.size[tail_dma] - usbDmaSize) ); 
+
+	    usbDmaSize += size;
+
+	    if(size > global_wa_threshold)
+	    {
+	        tmp_buff = buff_ptr;
+	        buff_ptr = (uint_8*)((int)usbSramBase + (dma_index * usbSramPartSize));
+	        USB_idma_copy(buff_ptr, tmp_buff, size);
+
+	        sram_parts[dma_index] = S_BUSY;
+            dma_index++;
+            if(dma_index == global_wa_sram_parts)
+                dma_index = 0;
+	    }
+        
+
+	    /* Get a transfer descriptor */
+	    USB_XD_QGET(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, xd_ptr);
+
+	    usb_dev_ptr->XD_ENTRIES--;
+	    USB_dcache_flush((pointer)buff_ptr, size);   
+
+	    /* Initialize the new transfer descriptor */      
+	    xd_ptr->EP_NUM = usbSendQueue.ep_num[tail_dma];
+	    xd_ptr->BDIRECTION = ARC_USB_SEND;
+	    xd_ptr->WTOTALLENGTH = size;
+	    xd_ptr->WSOFAR = 0;
+	    xd_ptr->WSTARTADDRESS = buff_ptr;   
+	    xd_ptr->BSTATUS = ARC_USB_STATUS_TRANSFER_ACCEPTED;
+
+	    error = _usb_dci_vusb20_add_dTD(handle, xd_ptr);
+
+	    if(error)
+	        break;
+    }
+
+    return error;    
+}
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : usbSendComplete
+*  Returned Value : None
+*  Comments       :
+*        Callback for send transfer complete event.
+*
+*END*-----------------------------------------------------------------*/
+void    usbSendComplete(void* handle, uint_8 type, boolean setup, uint_8 dir, 
+                        uint_8_ptr buffer, uint_32 length, uint_8 error)
+{
+    /* Check if this complete is one from the sendQueue */
+    if( (usbSendQueue.ep_num[usbSendQueue.tail] == type) &&
+        (usbSendQueue.num > 0) )
+    {
+        USB_DEV_STATE_STRUCT_PTR    usb_dev_ptr;
+        uint_8*                     buff_ptr;
+        uint_32                     size;
+        int                         num, tail;
+
+        usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+        tail = usbSendQueue.tail;
+        num = usbSendQueue.num;
+        buff_ptr = usbSendQueue.buff_ptr[tail];
+        size = usbSendQueue.size[tail];
+/*
+        USB_printf("usbSendComplete: num=%d, tail=%d, usbSentSize=%d, type=%d, length=%d (%d), buff=%p (%p)\n", 
+                num, tail, usbSentSize, type, length, usbSendQueue.size[tail], 
+                buffer, usbSendQueue.buff_ptr[tail]);
+*/
+        usbSentSize += length;
+
+	    /* if the buffer was on the SRAM */
+	    if( ((unsigned)buffer >= (unsigned)usbSramBase) &&
+	    ((unsigned)buffer < ((unsigned)usbSramBase + (usbSramPartSize * global_wa_sram_parts))) )
+	    {
+	        sram_parts[sent_index] = S_FREE;
+            sent_index++;
+            if(sent_index == global_wa_sram_parts)
+                sent_index = 0;
+	    }
+
+        if(usbSentSize >= usbSendQueue.size[tail])
+        {
+            /* Remove from the usbSendQueues */
+            num--;
+            tail++;
+            if(tail == MAX_XDS_FOR_TR_CALLS)
+                tail = 0;
+
+            usbSendQueue.tail = tail;
+            usbSendQueue.num = num;
+            usbSentSize = 0;
+
+            /* Call complete callback */
+            _usb_device_call_service(handle, type, setup, dir, 
+                         buff_ptr, size, error);
+
+            if(num == 0)
+                return;
+        }
+
+	    error = _usb_prepare_to_send(handle);	
+        if (error) 
+        {
+            USB_printf("usbSendComplete, add_dTD failed\n");
+        }	
+
+    }
+    else
+    {
+        /* Call complete callback */
+        _usb_device_call_service(handle, type, setup, dir, 
+                        buffer, length, error);
+    }
+}
+#endif /* USB_UNDERRUN_WA */
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_send_data
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Sends data on a specified endpoint.
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_device_send_data
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] buffer to send */
+      uint_8_ptr                 buff_ptr,
+            
+      /* [IN] length of the transfer */
+      uint_32                    size
+   )
+{ /* Body */
+   int 	                        lockKey;
+   uint_8                       error = 0;
+   XD_STRUCT_PTR                xd_ptr;
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   boolean                      toSend = TRUE;
+
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TX,
+       "send_data: handle=%p, ep=%d, pBuf=0x%x, size=%d, EP_QH=%p\n", 
+       handle, ep_num, (unsigned)buff_ptr, (int)size, usb_dev_ptr->EP_QUEUE_HEAD_PTR);
+
+   ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_send_count++));
+      
+   lockKey = USB_lock();
+
+   if (!usb_dev_ptr->XD_ENTRIES) 
+   {
+      USB_unlock(lockKey);
+      USB_printf("_usb_device_send_data, transfer in progress\n");
+      return ARC_USB_STATUS_TRANSFER_IN_PROGRESS;
+   } /* Endif */
+
+#if defined(USB_UNDERRUN_WA)
+    {
+        int 			                head;
+       	VUSB20_EP_QUEUE_HEAD_STRUCT* 	ep_queue_head_ptr;
+
+		ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + 
+                       						                  2*ep_num + ARC_USB_SEND;
+
+        if( ((ep_queue_head_ptr->MAX_PKT_LENGTH >> 16) & 0x7FF) > global_wa_threshold) 
+        {
+            /* Only Endpoints with maxPktSize more than 128 bytes need special processing */
+            if( (size > global_wa_threshold) || 
+                (usbSendQueue.num != 0) )
+            {
+/*
+                USB_printf("_usb_device_send_data: ep_num=%d, maxPktSize=%d, size=%d\n",
+                        ep_num, (ep_queue_head_ptr->MAX_PKT_LENGTH >> 16) & 0x7FF, size);
+*/
+                /* Check if usbSendQueue is not Full */
+                if(usbSendQueue.num == MAX_XDS_FOR_TR_CALLS)
+                {
+                    USB_printf("ep=%d: usbSendQueue is FULL\n", ep_num);
+                    USB_unlock(lockKey);
+                    return USBERR_TX_FAILED;
+                }
+
+                /* Add to usbSendQueu */
+                head = usbSendQueue.head;
+
+                usbSendQueue.num++;
+		        usbSendQueue.num_dma++;
+                usbSendQueue.size[head] = size;
+                usbSendQueue.buff_ptr[head] = buff_ptr;
+                usbSendQueue.ep_num[head] = ep_num;
+
+                head++;
+                if(head == MAX_XDS_FOR_TR_CALLS)
+                    head = 0;
+
+                usbSendQueue.head = head;
+
+                /* Process first usbSendQueue element if possible */
+                if(usbSendQueue.num == 1)
+                {
+		            error = _usb_prepare_to_send(handle);
+		        }
+		        toSend = FALSE;
+            }
+        }
+    }
+#endif /* USB_UNDERRUN_WA */
+
+    if(toSend == TRUE)
+    {
+        /* Get a transfer descriptor */
+        USB_XD_QGET(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, xd_ptr);
+
+        usb_dev_ptr->XD_ENTRIES--;
+
+        if(buff_ptr != NULL)

+            USB_dcache_flush((pointer)buff_ptr, size);   
+
+        /* Initialize the new transfer descriptor */      
+        xd_ptr->EP_NUM = ep_num;
+        xd_ptr->BDIRECTION = ARC_USB_SEND;
+        xd_ptr->WTOTALLENGTH = size;
+        xd_ptr->WSOFAR = 0;
+        xd_ptr->WSTARTADDRESS = buff_ptr;   
+        xd_ptr->BSTATUS = ARC_USB_STATUS_TRANSFER_ACCEPTED;
+
+        error = _usb_dci_vusb20_add_dTD(handle, xd_ptr);
+    }
+    USB_unlock(lockKey);
+   
+    if (error) 
+    {
+        USB_printf("_usb_device_send_data, transfer failed\n");
+        return USBERR_TX_FAILED;
+    } /* Endif */
+    return error;
+
+} /* EndBody */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevUtl.c b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevUtl.c
new file mode 100755
index 0000000..7238d57
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbDevUtl.c
@@ -0,0 +1,635 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+
+#include "usb/api/mvUsbDevApi.h"
+#include "usb/device/mvUsbDevPrv.h"
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_unstall_endpoint
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*     Unstalls the endpoint in specified direction
+*
+*END*-----------------------------------------------------------------*/
+void _usb_device_unstall_endpoint
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR   	usb_dev_ptr;
+   int							lockKey;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+ 
+   lockKey = USB_lock();
+   
+   _usb_dci_vusb20_unstall_endpoint(handle, ep_num, direction);
+
+   USB_unlock(lockKey);
+  
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _usb_device_get_status
+* Returned Value : USB_OK or error code
+* Comments       :
+*     Provides API to access the USB internal state.
+* 
+*END*--------------------------------------------------------------------*/
+uint_8 _usb_device_get_status
+   (
+      /* [IN] Handle to the USB device */
+      _usb_device_handle   handle,
+      
+      /* [IN] What to get the status of */
+      uint_8               component,
+      
+      /* [OUT] The requested status */
+      uint_16_ptr          status
+   )
+{ /* Body */
+   	USB_DEV_STATE_STRUCT_PTR 	usb_dev_ptr;
+	int							lockKey;
+
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+  
+   lockKey = USB_lock();
+
+   switch (component) 
+   {
+      case ARC_USB_STATUS_DEVICE_STATE:
+         *status = usb_dev_ptr->USB_STATE;
+         break;
+
+      case ARC_USB_STATUS_DEVICE:
+         *status = usb_dev_ptr->USB_DEVICE_STATE;
+         break;
+
+      case ARC_USB_STATUS_INTERFACE:
+          *status = 0;
+         break;
+         
+      case ARC_USB_STATUS_ADDRESS:
+         *status = usb_dev_ptr->DEVICE_ADDRESS;
+         break;
+         
+      case ARC_USB_STATUS_CURRENT_CONFIG:
+         *status = usb_dev_ptr->USB_CURR_CONFIG;
+         break;
+
+      case ARC_USB_STATUS_SOF_COUNT:
+         *status = usb_dev_ptr->USB_SOF_COUNT;
+         break;
+   
+      default:
+            USB_unlock(lockKey);
+            USB_printf("_usb_device_get_status, bad status\n");
+            return USBERR_BAD_STATUS;
+  
+   } /* Endswitch */
+   USB_unlock(lockKey);
+  
+   return USB_OK;   
+} /* EndBody */  
+ 
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _usb_device_set_status
+* Returned Value : USB_OK or error code
+* Comments       :
+*     Provides API to set internal state
+* 
+*END*--------------------------------------------------------------------*/
+uint_8 _usb_device_set_status
+   (
+      /* [IN] Handle to the usb device */
+      _usb_device_handle   handle,
+      
+      /* [IN] What to set the status of */
+      uint_8               component,
+      
+      /* [IN] What to set the status to */
+      uint_16              setting
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR usb_dev_ptr;
+   int 					    lockKey;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_STATUS, 
+            "set_status: component=0x%x, value=0x%x\n", component, setting);
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   lockKey = USB_lock();
+
+   switch (component) 
+   {
+      case ARC_USB_STATUS_DEVICE_STATE:
+         usb_dev_ptr->USB_STATE = setting;
+         break;
+
+      case ARC_USB_STATUS_DEVICE:
+         usb_dev_ptr->USB_DEVICE_STATE = setting;
+         break;
+
+      case ARC_USB_STATUS_INTERFACE:
+         break;
+
+      case ARC_USB_STATUS_CURRENT_CONFIG:
+         usb_dev_ptr->USB_CURR_CONFIG = setting;
+         break;
+
+      case ARC_USB_STATUS_SOF_COUNT:
+         usb_dev_ptr->USB_SOF_COUNT = setting;
+         break;
+
+      case ARC_USB_FORCE_FULL_SPEED:
+         _usb_dci_vusb20_set_speed_full((pointer)usb_dev_ptr, setting);
+         break;
+
+      case ARC_USB_PHY_LOW_POWER_SUSPEND:
+         _usb_dci_vusb20_suspend_phy((pointer)usb_dev_ptr, setting);
+         break;
+
+      case ARC_USB_STATUS_ADDRESS:
+         usb_dev_ptr->DEVICE_ADDRESS = setting;
+
+         _usb_dci_vusb20_set_address((pointer)usb_dev_ptr, setting);
+         break;
+      
+      case ARC_USB_STATUS_TEST_MODE:
+         _usb_dci_vusb20_set_test_mode(handle, setting);
+         break;
+         
+      default:
+            USB_unlock(lockKey);
+            USB_printf("_usb_device_set_status, bad status\n");
+            return USBERR_BAD_STATUS;
+  
+   } /* Endswitch */
+
+   USB_unlock(lockKey);
+   
+   return USB_OK;   
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_stall_endpoint
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*     Stalls the endpoint.
+*
+*END*-----------------------------------------------------------------*/
+void _usb_device_stall_endpoint
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   int							lockKey;

+
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+   lockKey = USB_lock();

+

+   _usb_dci_vusb20_stall_endpoint(handle, ep_num, direction);

+

+   USB_unlock(lockKey);
+   
+} /* EndBody */
+

+/*FUNCTION*-------------------------------------------------------------

+*

+*  Function Name  : _usb_device_is_endpoint_stalled

+*  Returned Value : USB_OK or error code

+*  Comments       :

+*     Stalls the endpoint.

+*

+*END*-----------------------------------------------------------------*/

+uint_8 _usb_device_is_endpoint_stalled

+   (

+      /* [IN] the USB_USB_dev_initialize state structure */

+      _usb_device_handle         handle,

+            

+      /* [IN] the Endpoint number */

+      uint_8                     ep_num,

+            

+      /* [IN] direction */

+      uint_8                     direction

+   )

+{ /* Body */

+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;

+   uint_8                       val;

+   int							lockKey;

+

+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;

+

+   lockKey = USB_lock();

+

+   val = _usb_dci_vusb20_is_endpoint_stalled(handle, ep_num, direction);

+

+   USB_unlock(lockKey);

+

+   return val;

+   

+} /* EndBody */

+

+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_device_process_resume
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Process Resume event
+*
+*END*-----------------------------------------------------------------*/
+void _usb_device_assert_resume
+   (
+      /* [IN] the USB_USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR      usb_dev_ptr;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+   _usb_dci_vusb20_assert_resume(handle);
+
+} /* EndBody */
+
+
+/***************************/
+/* ARC USB Debug functions */
+/***************************/
+void _usb_status(void* usbHandle)
+{
+    USB_DEV_STATE_STRUCT*   pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle;
+
+    if(pUsbDev == NULL)
+    {
+        USB_printf("USB Device core is not initialized\n");
+        return;
+    }
+
+    USB_printf("\n\tUSB Status\n\n");
+
+    USB_printf("DEV_NUM=%d, DEV_ADDR=%d, CAP_REGS=0x%x, DEV_REGS=0x%x, MAX_EP=%d\n",
+                pUsbDev->DEV_NUM,
+                pUsbDev->DEVICE_ADDRESS,
+                (unsigned)pUsbDev->CAP_REGS_PTR, 
+                (unsigned)pUsbDev->DEV_PTR, 
+                pUsbDev->MAX_ENDPOINTS);
+
+    USB_printf("BUS_RESET=%s, STATE=0x%02x, DEV_STATE=0x%02x, SPEED=%d, ERRORS=%d, ERROR_STATE=0x%04x\n",
+                pUsbDev->BUS_RESETTING ? "Yes" : "No",
+                pUsbDev->USB_STATE,
+                pUsbDev->USB_DEVICE_STATE,
+                pUsbDev->SPEED, 
+                pUsbDev->ERRORS,
+                pUsbDev->ERROR_STATE);

+
+    USB_printf("EP_QUEUE_HEAD: SIZE=%d, BASE=%p (0x%08x), ALIGNED=%p, SERVICE_HEAD=%p\n",
+                pUsbDev->EP_QUEUE_HEAD_SIZE,
+                pUsbDev->EP_QUEUE_HEAD_BASE, 
+                pUsbDev->EP_QUEUE_HEAD_PHYS,
+                pUsbDev->EP_QUEUE_HEAD_PTR,
+                pUsbDev->SERVICE_HEAD_PTR);
+
+    USB_printf("XD: BASE=%p, HEAD=%p, TAIL=%p, ENTRIES=%d, SCRATCH=%p, TEMP=%p\n",
+                pUsbDev->XD_BASE,
+                pUsbDev->XD_HEAD,
+                pUsbDev->XD_TAIL,
+                pUsbDev->XD_ENTRIES,
+                pUsbDev->XD_SCRATCH_STRUCT_BASE,
+                pUsbDev->TEMP_XD_PTR);
+
+    USB_printf("DTD: SIZE=%d, BASE=%p (0x%08x), ALIGNED=%p, HEAD=0x%08x, TAIL=0x%08x, ENTRIES=%d, SCRATCH=%p\n",
+                pUsbDev->DTD_SIZE,
+                pUsbDev->DTD_BASE_PTR,
+                pUsbDev->DTD_BASE_PHYS,
+                pUsbDev->DTD_ALIGNED_BASE_PTR,
+                pUsbDev->DTD_HEAD,
+                pUsbDev->DTD_TAIL,
+                pUsbDev->DTD_ENTRIES,
+                pUsbDev->SCRATCH_STRUCT_BASE);
+}
+
+void _usb_stats(void* usbHandle)
+{
+    USB_DEV_STATE_STRUCT*   pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle;
+    USB_STATS*              pUsbStats = &pUsbDev->STATS;
+    int                     i;
+
+    USB_printf("\n\tUSB Statistics\n\n");
+
+    USB_printf("isr=%u, empty_isr=%u, reset=%u, setup=%u, read_setup=%u\n", 
+                    pUsbStats->usb_isr_count, pUsbStats->usb_empty_isr_count, 
+                    pUsbStats->usb_reset_count, pUsbStats->usb_setup_count, 
+                    pUsbStats->usb_read_setup_count);
+
+    USB_printf("recv=%u, send=%u, add=%u (%u), cancel=%u\n", 
+                pUsbStats->usb_recv_count, pUsbStats->usb_send_count, 
+                pUsbStats->usb_add_count, pUsbStats->usb_add_not_empty_count, 
+                pUsbStats->usb_cancel_count);
+
+    USB_printf("free_XD=%u, free_dTD=%u\n", 
+            pUsbStats->free_XD_count, pUsbStats->free_dTD_count);
+
+    USB_printf("complete_isr=%u, complete=%u, empty_complete=%u, max_complete=%u\n", 
+                pUsbStats->usb_complete_isr_count, pUsbStats->usb_complete_count, 
+                pUsbStats->usb_empty_complete_count, pUsbStats->usb_complete_max_count);
+
+    USB_printf("port_change=%u, suspend=%u\n", 
+                pUsbStats->usb_port_change_count, pUsbStats->usb_suspend_count);
+    for(i=0; i<(pUsbDev->MAX_ENDPOINTS); i++)
+    {
+        if( (pUsbStats->usb_complete_ep_count[i*2] == 0) && 
+            (pUsbStats->usb_complete_ep_count[i*2+1] == 0) )
+            continue;
+
+        USB_printf("EP #%d: RECV (OUT) = %3u, \tSEND (IN) = %u\n", i,
+                    pUsbStats->usb_complete_ep_count[i*2], 
+                    pUsbStats->usb_complete_ep_count[i*2+1]);
+    }
+    USB_printf("\n");
+}
+
+void _usb_clear_stats(void* usbHandle)
+{
+    USB_DEV_STATE_STRUCT*   pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle;
+
+    USB_memzero(&pUsbDev->STATS, sizeof(pUsbDev->STATS));
+}
+
+void _usb_regs(void* usbHandle)
+{
+    USB_DEV_STATE_STRUCT*   pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle;
+    VUSB20_REG_STRUCT*      cap_regs, *dev_regs;
+    int                     dev_num;
+
+    if(pUsbDev == NULL)
+    {
+        USB_printf("USB Device core is not initialized\n");
+        return;
+    }
+    USB_printf("\n\tUSB Capability Registers\n\n");
+
+    cap_regs = pUsbDev->CAP_REGS_PTR;
+    USB_printf("CAPLENGTH_HCIVER (0x%08x) = 0x%08x\n", 
+        (unsigned)&cap_regs->REGISTERS.CAPABILITY_REGISTERS.CAPLENGTH_HCIVER,
+        (unsigned)USB_32BIT_LE(cap_regs->REGISTERS.CAPABILITY_REGISTERS.CAPLENGTH_HCIVER));
+
+    USB_printf("DCI_VERSION      (0x%08x) = 0x%08x\n", 
+        (unsigned)&cap_regs->REGISTERS.CAPABILITY_REGISTERS.DCI_VERSION,
+        (unsigned)USB_32BIT_LE(cap_regs->REGISTERS.CAPABILITY_REGISTERS.DCI_VERSION));
+
+    USB_printf("DCC_PARAMS       (0x%08x) = 0x%08x\n", 
+        (unsigned)&cap_regs->REGISTERS.CAPABILITY_REGISTERS.DCC_PARAMS,
+        (unsigned)USB_32BIT_LE(cap_regs->REGISTERS.CAPABILITY_REGISTERS.DCC_PARAMS));
+
+    dev_regs = pUsbDev->DEV_PTR;
+    dev_num = pUsbDev->DEV_NUM;
+    USB_printf("\n\tUSB Device Operational Registers\n\n");
+
+    USB_printf("USB_CMD          (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD));
+
+    USB_printf("USB_STS          (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS));
+
+    USB_printf("USB_INTR         (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR));
+
+    USB_printf("USB_FRINDEX      (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX));
+
+    /* Skip CTRLDSSEGMENT register */
+    USB_printf("DEVICE_ADDR      (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR));
+
+    USB_printf("EP_LIST_ADDR     (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.EP_LIST_ADDR,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.EP_LIST_ADDR));
+
+    /* Skip CONFIG_FLAG register */
+
+    /* Skip PORTSCX[0..15] registers*/
+    USB_printf("PORTSCX[0]       (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0],
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]));
+
+    /* Skip OTGSC register */
+
+    USB_printf("USB_MODE         (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_MODE,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_MODE));
+
+    USB_printf("ENDPT_SETUP_STAT (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT));
+
+    USB_printf("ENDPTPRIME       (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME));
+
+    USB_printf("ENDPTFLUSH       (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH));
+
+    USB_printf("ENDPTSTATUS      (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS));
+
+    USB_printf("ENDPTCOMPLETE    (0x%08x) = 0x%08x\n", 
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE,
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE));
+}
+
+    
+void _usb_ep_status(void* usbHandle, int ep_num, int direction)
+{
+    USB_DEV_STATE_STRUCT*               pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle;
+    int                                 i, ep_idx;
+    VUSB20_EP_QUEUE_HEAD_STRUCT_PTR     ep_queue_head_ptr;
+    VUSB20_EP_TR_STRUCT_PTR             dTD_ptr, head_dTD_ptr, tail_dTD_ptr, next_dTD_ptr;
+    XD_STRUCT_PTR                       xd_ptr, next_xd_ptr;
+    VUSB20_REG_STRUCT_PTR               dev_regs;
+
+    if(pUsbDev == NULL)
+    {
+        USB_printf("USB Device core is not initialized\n");
+        return;
+    }
+
+    USB_printf("\n\tUSB Endpoint #%d - %s status\n\n", ep_num,
+        (direction == ARC_USB_SEND) ? "SEND (IN)" : "RECV (OUT)" );
+
+    ep_idx = ep_num*2 + direction;
+    dev_regs = pUsbDev->DEV_PTR;
+
+    USB_printf("ENDPTCTRLX[%d]    (0x%08x) = 0x%08x\n", ep_num,
+        (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num],
+        (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num]));
+
+    ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)pUsbDev->EP_QUEUE_HEAD_PTR + ep_idx;
+
+    head_dTD_ptr = pUsbDev->EP_DTD_HEADS[ep_idx];
+    tail_dTD_ptr = pUsbDev->EP_DTD_TAILS[ep_idx];
+
+    USB_printf("EP_QH=0x%08x: MAX_PKT=0x%x, SIZE_IOC_INT_STS=0x%x, CURR_DTD=0x%x, NEXT_DTD=0x%x\n", 
+                (unsigned)ep_queue_head_ptr, (unsigned)USB_32BIT_LE(ep_queue_head_ptr->MAX_PKT_LENGTH), 
+                (unsigned)USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS), 
+                (unsigned)USB_32BIT_LE(ep_queue_head_ptr->CURR_DTD_PTR), 
+                (unsigned)USB_32BIT_LE(ep_queue_head_ptr->NEXT_DTD_PTR));
+
+    USB_printf("\tBUF_0=0x%08x, BUF_1=0x%08x, BUF_2=0x%08x, BUF_3=0x%08x, BUF_4=0x%08x\n",
+                (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR0), 
+                (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR1), 
+                (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR2), 
+                (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR3), 
+                (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR4));
+    
+    USB_printf("\tSETUP_BUFFER (%p): ", ep_queue_head_ptr->SETUP_BUFFER);
+    for(i=0; i<sizeof(ep_queue_head_ptr->SETUP_BUFFER); i++)
+        USB_printf("%02x", ep_queue_head_ptr->SETUP_BUFFER[i] & 0xFF);
+    USB_printf("\n");
+
+    USB_printf("\ndTD_HEAD=0x%08x, dTD_TAIL=0x%08x\n", 
+                (unsigned)head_dTD_ptr, (unsigned)tail_dTD_ptr);
+
+    dTD_ptr = head_dTD_ptr;
+    i = 0;
+    while(dTD_ptr != NULL)
+    {
+        USB_printf("%d. dTD=0x%08x (0x%08x), SIZE_IOC_STS=0x%08x, BUF_0=0x%08x, NEXT=0x%08x\n", 
+                    i, (unsigned)dTD_ptr, USB_DTD_VIRT_TO_PHYS(pUsbDev, dTD_ptr),
+                    (unsigned)USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS), 
+                    (unsigned)USB_32BIT_LE(dTD_ptr->BUFF_PTR0), 
+                    (unsigned)USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR));
+
+        xd_ptr = dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD;
+
+        next_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(pUsbDev, 
+                           (uint_32)(USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK));
+        if(next_dTD_ptr != NULL) 
+            next_xd_ptr = next_dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD;
+        else
+            next_xd_ptr = NULL;
+
+        if(next_xd_ptr != xd_ptr)
+        {
+            USB_printf("\tXD=0x%08x, ADDR=0x%08x, SIZE=%u, STATUS=0x%02x\n",
+                (unsigned)xd_ptr, (unsigned)xd_ptr->WSTARTADDRESS, 
+                (unsigned)xd_ptr->WTOTALLENGTH, xd_ptr->BSTATUS);
+        }
+        i++;
+        dTD_ptr = next_dTD_ptr;
+    }
+}
+
+
+/* DEBUG */
+uint_32 usbDebugFlags = ARC_DEBUG_FLAG_STATS
+                      | ARC_DEBUG_FLAG_INIT 
+                      | ARC_DEBUG_FLAG_ERROR 
+                      | ARC_DEBUG_FLAG_STALL
+                      | ARC_DEBUG_FLAG_RESET;
+                      /*| ARC_DEBUG_FLAG_TRANSFER;*/
+
+void    _usb_debug_set_flags(uint_32 flags)     
+{
+    usbDebugFlags = (flags);                        
+}
+
+uint_32 _usb_debug_get_flags(void)     
+{
+    return usbDebugFlags;  
+}
+
+#if defined(MV_USB_TRACE_LOG)
+
+uint_16 DEBUG_TRACE_ARRAY_COUNTER = 0;
+char    DEBUG_TRACE_ARRAY[TRACE_ARRAY_SIZE][MAX_STRING_SIZE];
+
+void  _usb_debug_init_trace_log(void)                   
+{                                                  
+    USB_memzero(DEBUG_TRACE_ARRAY, TRACE_ARRAY_SIZE*MAX_STRING_SIZE);
+	DEBUG_TRACE_ARRAY_COUNTER =0;                  
+}                               
+
+void    _usb_debug_print_trace_log(void)                     
+{                                                       
+    int     i;                                          
+                                                        
+    USB_printf("USB Trace log: start=0x%x, end=0x%x, idx=%d, flags=0x%x\n\n", 
+               &DEBUG_TRACE_ARRAY[0][0], &DEBUG_TRACE_ARRAY[TRACE_ARRAY_SIZE-1][0], 
+               DEBUG_TRACE_ARRAY_COUNTER, usbDebugFlags);      
+
+    for(i=DEBUG_TRACE_ARRAY_COUNTER; i<TRACE_ARRAY_SIZE; i++)                      
+    {                                                 
+        if(DEBUG_TRACE_ARRAY[i][0] == '\0')              
+            continue;                     
+        
+        USB_printf("%3d. %s", i, DEBUG_TRACE_ARRAY[i]);
+    }                                                 
+    for(i=0; i<DEBUG_TRACE_ARRAY_COUNTER; i++)       
+    {                                                 
+        if(DEBUG_TRACE_ARRAY[i][0] == '\0')           
+            continue;                                 
+        USB_printf("%3d. %s", i, DEBUG_TRACE_ARRAY[i]);
+    }                          
+    _usb_debug_init_trace_log();
+}
+#else
+void  _usb_debug_init_trace_log(void)                   
+{
+}
+
+void    _usb_debug_print_trace_log(void)
+{
+    USB_printf("USB trace log is not supported\n");
+}
+#endif /* MV_USB_TRACE_LOG */
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevCncl.c b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevCncl.c
new file mode 100755
index 0000000..b3f91d8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevCncl.c
@@ -0,0 +1,222 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#include "usb/api/mvUsbDevApi.h"
+#include "usb/device/mvUsbDevPrv.h"
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_cancel_transfer
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Cancels a transfer
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_dci_vusb20_cancel_transfer
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+     
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR             usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR                dev_ptr;
+   VUSB20_EP_TR_STRUCT_PTR              dTD_ptr, check_dTD_ptr;
+   VUSB20_EP_QUEUE_HEAD_STRUCT_PTR      ep_queue_head_ptr;
+   XD_STRUCT_PTR                        xd_ptr;
+   uint_32                              temp, bit_pos;
+   volatile unsigned long               timeout, status_timeout;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   
+   bit_pos = (1 << (16 * direction + ep_num));
+   temp = (2*ep_num + direction);
+   
+   ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp;
+   
+   /* Unlink the dTD */
+   dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[temp];
+   
+   if (dTD_ptr) 
+   {
+      ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_cancel_count++));
+
+      check_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, 
+                            ((uint_32)USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK));
+
+      if (USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_STATUS_ACTIVE) 
+      {
+         /* Flushing will halt the pipe */
+         /* Write 1 to the Flush register */
+         dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH = USB_32BIT_LE(bit_pos);
+
+         /* Wait until flushing completed */
+         timeout = 0x1000000;
+         while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH) & bit_pos) 
+         {
+            /* ENDPTFLUSH bit should be cleared to indicate this operation is complete */
+            timeout--;
+            if(timeout == 0)
+            {
+                USB_printf("USB Cancel: - TIMEOUT for ENDPTFLUSH=0x%x, bit_pos=0x%x \n", 
+                      (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH), 
+                      (unsigned)bit_pos);
+                break;
+            }
+         } /* EndWhile */
+         status_timeout = 0x100000;
+         while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos) 
+         {
+            status_timeout--;
+            if(status_timeout == 0)
+            {
+                USB_printf("USB Cancel: - TIMEOUT for ENDPTSTATUS=0x%x, bit_pos=0x%x\n", 
+                      (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), 
+                      (unsigned)bit_pos);
+                break;
+            }
+
+            /* Write 1 to the Flush register */
+            dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH = USB_32BIT_LE(bit_pos);
+         
+            /* Wait until flushing completed */
+            timeout = 0x1000000;
+            while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH) & bit_pos) 
+            {
+               /* ENDPTFLUSH bit should be cleared to indicate this operation is complete */
+               timeout--;
+               if(timeout == 0)
+                {
+                    USB_printf("USB Cancel: - TIMEOUT for ENDPTFLUSH=0x%x, ENDPTSTATUS=0x%x, bit_pos=0x%x\n", 
+                            (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH), 
+                            (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS),
+                            (unsigned)bit_pos);
+                    break;
+                }
+            } /* EndWhile */
+         } /* EndWhile */
+      } /* Endif */
+      
+      /* Retire the current dTD */
+      dTD_ptr->SIZE_IOC_STS = 0;
+      dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(VUSBHS_TD_NEXT_TERMINATE);
+      
+      /* The transfer descriptor for this dTD */
+      xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD;
+      dTD_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr;
+
+      ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER,
+                      "cncl_%d: fri=0x%x, ep=%d%s, buf=%p, size=%d, xd=%p, dTD=%p %p, bit=0x%x\n",
+                       usb_dev_ptr->STATS.usb_cancel_count & 0xFFFF, 
+                       USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), 
+                       ep_num, direction ? "in" : "out", 
+                       xd_ptr->WSTARTADDRESS, xd_ptr->WTOTALLENGTH, xd_ptr, 
+                       dTD_ptr, check_dTD_ptr, bit_pos);
+       
+      /* Free the dTD */
+      _usb_dci_vusb20_free_dTD((pointer)dTD_ptr);
+      
+      /* Update the dTD head and tail for specific endpoint/direction */
+      if (!check_dTD_ptr) 
+      {
+         usb_dev_ptr->EP_DTD_HEADS[temp] = NULL;
+         usb_dev_ptr->EP_DTD_TAILS[temp] = NULL;
+         if (xd_ptr) 
+         {
+            xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr;
+            /* Free the transfer descriptor */
+            _usb_device_free_XD((pointer)xd_ptr);
+         } /* Endif */
+         /* No other transfers on the queue */
+         ep_queue_head_ptr->NEXT_DTD_PTR = USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE);
+         ep_queue_head_ptr->SIZE_IOC_INT_STS = 0;
+      } 
+      else 
+      {
+         usb_dev_ptr->EP_DTD_HEADS[temp] = check_dTD_ptr;
+            
+         if (xd_ptr) 
+         {
+            if ((uint_32)check_dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD != (uint_32)xd_ptr) 
+            {
+               xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr;
+               /* Free the transfer descriptor */
+               _usb_device_free_XD((pointer)xd_ptr);
+            } /* Endif */
+         } /* Endif */
+         
+         if (USB_32BIT_LE(check_dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_STATUS_ACTIVE) 
+         {         
+            /* Start CR 1015 */
+            /* Prime the Endpoint */
+            dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos);
+
+            if (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos)) 
+            {
+               timeout = 0x100000;
+               while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & bit_pos) 
+               {
+                  /* Wait for the ENDPTPRIME to go to zero */
+                  timeout--;
+                  if(timeout == 0)
+                  {
+                      USB_printf("USB Cancel: - TIMEOUT for ENDPTPRIME=0x%x, bit_pos=0x%x\n", 
+                                (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), 
+                                (unsigned)bit_pos);
+                      break;
+                  }
+               } /* EndWhile */
+
+               if (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos) 
+               {
+                  /* The endpoint was not not primed so no other transfers on 
+                  ** the queue 
+                  */
+                  goto done;
+               } /* Endif */
+            } 
+            else 
+            {
+               goto done;
+            } /* Endif */
+
+            /* No other transfers on the queue */
+            ep_queue_head_ptr->NEXT_DTD_PTR = (uint_32)USB_32BIT_LE((uint_32)check_dTD_ptr);
+            ep_queue_head_ptr->SIZE_IOC_INT_STS = 0;
+   
+            /* Prime the Endpoint */
+            dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos);
+         } /* Endif */
+      } /* Endif */
+   } /* Endif */
+   
+done:
+
+   /* End CR 1015 */  
+   return USB_OK;
+} /* EndBody */
+
+/* EOF */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevMain.c b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevMain.c
new file mode 100755
index 0000000..18cc3f7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevMain.c
@@ -0,0 +1,1868 @@
+/*******************************************************************************
+
+This software file (the "File") is distributed by Marvell International Ltd. 
+or its affiliate(s) under the terms of the GNU General Public License Version 2, 
+June 1991 (the "License").  You may use, redistribute and/or modify this File 
+in accordance with the terms and conditions of the License, a copy of which 
+is available along with the File in the license.txt file or by writing to the 
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 
+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+
+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.
+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.
+
+*******************************************************************************/
+
+#include "usb/api/mvUsbDevApi.h"
+#include "usb/device/mvUsbDevPrv.h"
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_init
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Initializes the USB device controller.
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_dci_vusb20_init
+   (
+      /* [IN] the USB device controller to initialize */
+      uint_8                     devnum,
+
+      /* [OUT] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+    USB_DEV_STATE_STRUCT_PTR    usb_dev_ptr;
+    uint_32                     temp;
+    uint_8*                     pBuf;
+    unsigned long               phyAddr;
+      
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    usb_dev_ptr->CAP_REGS_PTR = 
+       (VUSB20_REG_STRUCT_PTR)USB_get_cap_reg_addr(devnum);
+      
+    /* Get the base address of the VUSB_HS registers */
+    usb_dev_ptr->DEV_PTR = 
+      (VUSB20_REG_STRUCT_PTR)(((uint_32)usb_dev_ptr->CAP_REGS_PTR) + 
+       (USB_32BIT_LE(usb_dev_ptr->CAP_REGS_PTR->REGISTERS.CAPABILITY_REGISTERS.CAPLENGTH_HCIVER) & 
+                                                                EHCI_CAP_LEN_MASK));
+
+    /* Get the maximum number of endpoints supported by this USB controller */
+    usb_dev_ptr->MAX_ENDPOINTS = 
+      (USB_32BIT_LE(usb_dev_ptr->CAP_REGS_PTR->REGISTERS.CAPABILITY_REGISTERS.DCC_PARAMS) & 
+                                                VUSB20_DCC_MAX_ENDPTS_SUPPORTED);
+
+    USB_printf("USB init: CAP_REGS=0x%x, DEV_REGS=0x%x, MAX_EP=%d\n",
+                (unsigned)usb_dev_ptr->CAP_REGS_PTR, (unsigned)usb_dev_ptr->DEV_PTR, 
+                usb_dev_ptr->MAX_ENDPOINTS);
+
+    temp = (usb_dev_ptr->MAX_ENDPOINTS * 2);
+   
+    pBuf = (uint_8*)USB_uncached_memalloc(temp*sizeof(VUSB20_EP_QUEUE_HEAD_STRUCT), 
+                                          2048, &phyAddr);      
+    if (pBuf == NULL) 
+    {
+        USB_printf("_usb_dci_vusb20_init, malloc of %d bytes in Uncached area failed\n",
+                        temp*sizeof(VUSB20_EP_QUEUE_HEAD_STRUCT));
+        return USBERR_ALLOC;
+    }
+
+    /****************************************************************   
+      Assign QH base
+    ****************************************************************/   
+    usb_dev_ptr->EP_QUEUE_HEAD_BASE = pBuf;
+    usb_dev_ptr->EP_QUEUE_HEAD_PHYS = (uint_32)phyAddr;
+
+    /* Align the endpoint queue head to 2K boundary */   
+    usb_dev_ptr->EP_QUEUE_HEAD_PTR = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)
+                USB_MEM2048_ALIGN((uint_32)usb_dev_ptr->EP_QUEUE_HEAD_BASE);
+
+    usb_dev_ptr->EP_QUEUE_HEAD_SIZE = temp*sizeof(VUSB20_EP_QUEUE_HEAD_STRUCT) +
+                                      ((uint_32)usb_dev_ptr->EP_QUEUE_HEAD_PTR - 
+                                       (uint_32)usb_dev_ptr->EP_QUEUE_HEAD_BASE);
+
+    /****************************************************************   
+      Zero out the memory allocated
+    ****************************************************************/   
+    USB_memzero( (void*)usb_dev_ptr->EP_QUEUE_HEAD_PTR, 
+                 temp*sizeof(VUSB20_EP_QUEUE_HEAD_STRUCT));
+
+    USB_printf("USB EP_QH: Base=%p (0x%x), Aligned(%d)=%p, Size=%d\n",
+                usb_dev_ptr->EP_QUEUE_HEAD_BASE, usb_dev_ptr->EP_QUEUE_HEAD_PHYS,
+                2048, usb_dev_ptr->EP_QUEUE_HEAD_PTR, usb_dev_ptr->EP_QUEUE_HEAD_SIZE);
+
+    /****************************************************************   
+      Assign DTD base
+    ****************************************************************/   
+    pBuf = (uint_8*)USB_uncached_memalloc(MAX_EP_TR_DESCRS*sizeof(VUSB20_EP_TR_STRUCT), 
+                                          32, &phyAddr);      
+    if (pBuf == NULL) 
+    {
+        USB_printf("_usb_dci_vusb20_init, malloc of %d bytes in Uncached area failed\n",
+                        MAX_EP_TR_DESCRS*sizeof(VUSB20_EP_TR_STRUCT));
+        return USBERR_ALLOC;
+    }
+
+    usb_dev_ptr->DTD_BASE_PTR = pBuf;
+    usb_dev_ptr->DTD_BASE_PHYS = (uint_32)phyAddr;
+    
+    /* Align the dTD base to 32 byte boundary */   
+    usb_dev_ptr->DTD_ALIGNED_BASE_PTR = (VUSB20_EP_TR_STRUCT_PTR)
+                        USB_MEM32_ALIGN((uint_32)usb_dev_ptr->DTD_BASE_PTR);
+
+    usb_dev_ptr->DTD_SIZE = MAX_EP_TR_DESCRS*sizeof(VUSB20_EP_TR_STRUCT) +
+                                ((uint_32)usb_dev_ptr->EP_QUEUE_HEAD_PTR - 
+                                 (uint_32)usb_dev_ptr->EP_QUEUE_HEAD_BASE);
+
+    /****************************************************************   
+      Zero out the memory allocated
+    ****************************************************************/   
+    USB_memzero((void*)usb_dev_ptr->DTD_ALIGNED_BASE_PTR, 
+                MAX_EP_TR_DESCRS*sizeof(VUSB20_EP_TR_STRUCT));
+
+    /****************************************************************   
+      Assign SCRATCH Structure base
+    ****************************************************************/   
+    /* Allocate memory for internal scratch structure */   
+    pBuf = USB_memalloc(MAX_EP_TR_DESCRS*sizeof(SCRATCH_STRUCT));
+    if (pBuf == NULL) 
+    {
+        USB_printf("_usb_dci_vusb20_init, malloc of %d bytes failed\n",
+                        MAX_EP_TR_DESCRS*sizeof(SCRATCH_STRUCT));
+        return USBERR_ALLOC;
+    }
+    usb_dev_ptr->SCRATCH_STRUCT_BASE = (SCRATCH_STRUCT_PTR)pBuf;
+    USB_memzero(usb_dev_ptr->SCRATCH_STRUCT_BASE, 
+            MAX_EP_TR_DESCRS*sizeof(SCRATCH_STRUCT));
+
+    USB_printf("USB dTD(%d): Base=%p (0x%x), Aligned(%d)=%p, Size=%d, Scratch=%p\n",
+                MAX_EP_TR_DESCRS, usb_dev_ptr->DTD_BASE_PTR, usb_dev_ptr->DTD_BASE_PHYS,
+                32, usb_dev_ptr->DTD_ALIGNED_BASE_PTR, usb_dev_ptr->DTD_SIZE,
+                usb_dev_ptr->SCRATCH_STRUCT_BASE);
+
+#ifdef USB_UNDERRUN_WA
+    usbSramBase = (uint_8*)USB_get_sram_addr(&usbSramSize);
+    if (usbSramBase == NULL) 
+    {
+        USB_printf("_usb_dci_vusb20_init, SRAM is not available\n");                        
+        return USBERR_ALLOC;
+    }
+    USB_memzero(usbSramBase, usbSramSize);
+    USB_printf("USB WA_Queue: base=%p, size=%d, parts=%d\n", 
+                    usbSramBase, usbSramSize, global_wa_sram_parts);
+#endif /* USB_UNDERRUN_WA */
+
+    usb_dev_ptr->USB_STATE = ARC_USB_STATE_UNKNOWN;
+
+    /* Initialize the VUSB_HS controller */   
+    _usb_dci_vusb20_chip_initialize((pointer)usb_dev_ptr);
+
+    return USB_OK;   
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_chip_initialize
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Initializes the USB device controller.
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_chip_initialize
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+    USB_DEV_STATE_STRUCT_PTR         usb_dev_ptr;
+    VUSB20_REG_STRUCT_PTR            dev_ptr;
+    VUSB20_EP_QUEUE_HEAD_STRUCT_PTR  ep_queue_head_ptr;
+    VUSB20_EP_TR_STRUCT_PTR          dTD_ptr;
+    uint_32                          i, port_control;
+    SCRATCH_STRUCT_PTR               temp_scratch_ptr;
+    volatile unsigned long           delay;
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, "chip_initialize\n");
+   
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   
+    /* Stop the controller */
+    dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= ~(USB_32BIT_LE(EHCI_CMD_RUN_STOP));
+      
+    /* Reset the controller to get default values */
+    dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD = USB_32BIT_LE(EHCI_CMD_CTRL_RESET);
+
+    USB_printf("USB Init: Wait for RESET completed\n");
+   
+    delay = 0x100000;
+    while (dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD & 
+                                    (USB_32BIT_LE(EHCI_CMD_CTRL_RESET))) 
+    {
+        /* Wait for the controller reset to complete */
+        delay--;
+        if(delay == 0)
+            break;
+    } /* EndWhile */
+
+    if(delay == 0)
+    {
+        USB_printf("USB Init: Wait for RESET completed TIMEOUT\n");
+    }
+    else
+    {
+        USB_printf("USB Init: RESET completed\n");
+    }
+    /* Call BSP callback to complete reset process */
+    USB_reset_complete(usb_dev_ptr->DEV_NUM);
+
+    /* Initialize the internal dTD head and tail to NULL */   
+    usb_dev_ptr->DTD_HEAD = NULL;
+    usb_dev_ptr->DTD_TAIL = NULL;
+    usb_dev_ptr->DTD_ENTRIES = 0; 
+    usb_dev_ptr->ERROR_STATE = 0;
+
+   /* Make sure the 16 MSBs of this register are 0s */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT = USB_32BIT_LE(0);
+   
+   ep_queue_head_ptr = usb_dev_ptr->EP_QUEUE_HEAD_PTR;
+
+   /* Initialize all device queue heads */
+   for (i=0; i<(usb_dev_ptr->MAX_ENDPOINTS*2); i++) 
+   {
+      /* Interrupt on Setup packet */
+      (ep_queue_head_ptr + i)->MAX_PKT_LENGTH = (USB_32BIT_LE(
+          ((uint_32)USB_MAX_CTRL_PAYLOAD << VUSB_EP_QUEUE_HEAD_MAX_PKT_LEN_POS) | 
+            VUSB_EP_QUEUE_HEAD_IOS));
+
+      (ep_queue_head_ptr + i)->NEXT_DTD_PTR = (USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE));
+   } /* Endfor */
+
+   /* Configure the Endpoint List Address */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.EP_LIST_ADDR = 
+                            USB_32BIT_LE(USB_EP_QH_VIRT_TO_PHYS(usb_dev_ptr, ep_queue_head_ptr));
+      
+   port_control = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]);
+   if (usb_dev_ptr->CAP_REGS_PTR->REGISTERS.CAPABILITY_REGISTERS.HCS_PARAMS & 
+                                        USB_32BIT_LE(VUSB20_HCS_PARAMS_PORT_POWER_CONTROL_FLAG)) 
+   {
+      port_control &= (~EHCI_PORTSCX_W1C_BITS | ~EHCI_PORTSCX_PORT_POWER);
+   } /* Endif */
+   
+   if(usb_dev_ptr->FORCE_FS == TRUE)
+   {
+       port_control |= EHCI_PORTSCX_FORCE_FULL_SPEED_CONNECT;
+   }
+   else
+   {
+       port_control &= (~EHCI_PORTSCX_FORCE_FULL_SPEED_CONNECT);
+   }
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0] = USB_32BIT_LE(port_control);
+
+   dTD_ptr = usb_dev_ptr->DTD_ALIGNED_BASE_PTR;
+
+   temp_scratch_ptr = usb_dev_ptr->SCRATCH_STRUCT_BASE;
+
+   /* Enqueue all the dTDs */   
+   for (i=0; i<MAX_EP_TR_DESCRS; i++) 
+   {
+      dTD_ptr->SCRATCH_PTR = temp_scratch_ptr;
+      dTD_ptr->SCRATCH_PTR->FREE = _usb_dci_vusb20_free_dTD;
+      /* Set the dTD to be invalid */
+      dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(VUSBHS_TD_NEXT_TERMINATE);
+      /* Set the Reserved fields to 0 */
+      dTD_ptr->SIZE_IOC_STS &= ~(USB_32BIT_LE(VUSBHS_TD_RESERVED_FIELDS));
+      dTD_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr;
+      _usb_dci_vusb20_free_dTD((pointer)dTD_ptr);
+      dTD_ptr++;
+      temp_scratch_ptr++;
+   } /* Endfor */
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_free_dTD
+*  Returned Value : void
+*  Comments       :
+*        Enqueues a dTD onto the free DTD ring.
+*
+*END*-----------------------------------------------------------------*/
+
+void _usb_dci_vusb20_free_dTD
+   (
+      /* [IN] the dTD to enqueue */
+      pointer  dTD_ptr
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   int                          lockKey;
+
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)(((VUSB20_EP_TR_STRUCT_PTR)dTD_ptr)->SCRATCH_PTR->PRIVATE);
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "free_dTD: dTD_ptr=0x%x\n", (unsigned)dTD_ptr);
+
+   ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.free_dTD_count++));
+
+
+   /*
+   ** This function can be called from any context, and it needs mutual
+   ** exclusion with itself.
+   */
+   lockKey = USB_lock();
+
+   /*
+   ** Add the dTD to the free dTD queue (linked via PRIVATE) and
+   ** increment the tail to the next descriptor
+   */
+   EHCI_DTD_QADD(usb_dev_ptr->DTD_HEAD, usb_dev_ptr->DTD_TAIL, (VUSB20_EP_TR_STRUCT_PTR)dTD_ptr);
+   usb_dev_ptr->DTD_ENTRIES++;
+
+   USB_unlock(lockKey);
+
+} /* Endbody */
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_add_dTD
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Adds a device transfer desriptor(s) to the queue.
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_dci_vusb20_add_dTD
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+     
+      /* [IN] The transfer descriptor address */
+      XD_STRUCT_PTR              xd_ptr
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR         usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR            dev_ptr;
+   VUSB20_EP_TR_STRUCT_PTR          dTD_ptr, temp_dTD_ptr, first_dTD_ptr = NULL;
+   VUSB20_EP_QUEUE_HEAD_STRUCT_PTR  ep_queue_head_ptr;
+   uint_32                          curr_pkt_len, remaining_len; 
+   uint_32                          curr_offset, temp, bit_pos;
+   volatile unsigned long           timeout;
+   
+   /*********************************************************************
+   For a optimal implementation, we need to detect the fact that
+   we are adding DTD to an empty list. If list is empty, we can
+   actually skip several programming steps esp. those for ensuring
+   that there is no race condition.The following boolean will be useful
+   in skipping some code here.
+   *********************************************************************/
+   boolean           list_empty = FALSE;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   remaining_len = xd_ptr->WTOTALLENGTH;
+   
+   curr_offset = 0;
+   temp = (2*xd_ptr->EP_NUM + xd_ptr->BDIRECTION);
+   bit_pos = (1 << (16 * xd_ptr->BDIRECTION + xd_ptr->EP_NUM));
+   
+   ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp;
+
+   /*********************************************************************
+   This loops iterates through the length of the transfer and divides
+   the data in to DTDs each handling the a max of 0x4000 bytes of data.
+   The first DTD in the list is stored in a pointer called first_dTD_ptr.
+   This pointer is later linked in to QH for processing by the hardware.   
+   *********************************************************************/
+
+    do 
+    {
+        /* Check if we need to split the transfer into multiple dTDs */
+        if (remaining_len > VUSB_EP_MAX_LENGTH_TRANSFER) 
+        {
+            curr_pkt_len = VUSB_EP_MAX_LENGTH_TRANSFER;
+        } 
+        else 
+        {
+            curr_pkt_len = remaining_len;
+        } /* Endif */
+   
+        /* Get a dTD from the queue */   
+        EHCI_DTD_QGET(usb_dev_ptr->DTD_HEAD, usb_dev_ptr->DTD_TAIL, dTD_ptr);
+   
+        if (!dTD_ptr) 
+        {
+            USB_printf("Error: Can't get dTD\n");
+            return USBERR_TR_FAILED;
+        } /* Endif */
+
+        ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_add_count++));
+
+        remaining_len -= curr_pkt_len;
+
+        usb_dev_ptr->DTD_ENTRIES--;
+
+        if (curr_offset == 0) 
+        {
+            first_dTD_ptr = dTD_ptr;
+        } /* Endif */
+
+        /* Zero the dTD. Leave the last 4 bytes as that is the scratch pointer */
+        USB_memzero((void *) dTD_ptr,(sizeof(VUSB20_EP_TR_STRUCT) - 4));
+
+        /* Initialize the dTD */
+        dTD_ptr->SCRATCH_PTR->PRIVATE = handle;
+   
+        /* Set the Terminate bit */
+        dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE);
+
+        /*************************************************************
+        FIX ME: For hig-speed and high-bandwidth ISO IN endpoints,
+        we must initialize the multiplied field so that Host can issues
+        multiple IN transactions on the endpoint. See the DTD data
+        structure for MultiIO field.
+      
+        S Garg 11/06/2003
+        *************************************************************/
+      
+        /* Fill in the transfer size */
+        if (!remaining_len) 
+        {
+            dTD_ptr->SIZE_IOC_STS = USB_32BIT_LE((curr_pkt_len << 
+                    VUSBHS_TD_LENGTH_BIT_POS) | (VUSBHS_TD_IOC) | (VUSBHS_TD_STATUS_ACTIVE));
+        } 
+        else 
+        {
+            dTD_ptr->SIZE_IOC_STS = USB_32BIT_LE((curr_pkt_len << VUSBHS_TD_LENGTH_BIT_POS) 
+                                                   | VUSBHS_TD_STATUS_ACTIVE);
+        } /* Endif */
+   
+        /* Set the reserved field to 0 */
+        dTD_ptr->SIZE_IOC_STS &= ~USB_32BIT_LE(VUSBHS_TD_RESERVED_FIELDS);
+
+        /* 4K apart buffer page pointers */
+        if(xd_ptr->WSTARTADDRESS != NULL)
+        {
+            uint_32 physAddr = USB_virt_to_phys((uint_8*)xd_ptr->WSTARTADDRESS + curr_offset);
+
+            dTD_ptr->BUFF_PTR0 = USB_32BIT_LE(physAddr);
+            
+            physAddr += 4096;
+            dTD_ptr->BUFF_PTR1 = USB_32BIT_LE(physAddr);
+
+            physAddr += 4096;
+            dTD_ptr->BUFF_PTR2 = USB_32BIT_LE(physAddr);
+
+            physAddr += 4096;
+            dTD_ptr->BUFF_PTR3 = USB_32BIT_LE(physAddr);
+
+            physAddr += 4096;
+            dTD_ptr->BUFF_PTR4 = USB_32BIT_LE(physAddr);
+        }
+        else
+        {
+            dTD_ptr->BUFF_PTR0 = dTD_ptr->BUFF_PTR1 = dTD_ptr->BUFF_PTR2 = 0;
+            dTD_ptr->BUFF_PTR3 = dTD_ptr->BUFF_PTR4 = 0;
+        }
+        curr_offset += curr_pkt_len;
+
+      /* Maintain the first and last device transfer descriptor per 
+      ** endpoint and direction 
+      */
+      if (!usb_dev_ptr->EP_DTD_HEADS[temp]) 
+      {
+         usb_dev_ptr->EP_DTD_HEADS[temp] = dTD_ptr;
+         /***********************************************
+         If list does not have a head, it means that list
+         is empty. An empty condition is detected.
+         ***********************************************/
+         list_empty = TRUE;
+      } /* Endif */ 
+   
+      /* Check if the transfer is to be queued at the end or beginning */
+      temp_dTD_ptr = usb_dev_ptr->EP_DTD_TAILS[temp];
+      
+      /* Remember which XD to use for this dTD */
+      dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD = (pointer)xd_ptr;
+      
+      /* New tail */
+      usb_dev_ptr->EP_DTD_TAILS[temp] = dTD_ptr;
+      if (temp_dTD_ptr) 
+      {
+         /* Should not do |=. The Terminate bit should be zero */
+         temp_dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(USB_DTD_VIRT_TO_PHYS(usb_dev_ptr, dTD_ptr));
+      } /* Endif */
+   } while (remaining_len); /* EndWhile */
+
+
+   /**************************************************************
+   In the loop above DTD has already been added to the list
+   However endpoint has not been primed yet. If list is not empty 
+   we need safter ways to add DTD to the existing list. 
+   Else we just skip to adding DTD to QH safely.
+   **************************************************************/
+   
+    if(list_empty == FALSE)
+    {
+        volatile boolean    read_safe = FALSE;                      
+        uint_32             prime, temp_ep_stat=0;
+
+        /*********************************************************
+        Hardware v3.2+ require the use of semaphore to ensure that
+        QH is safely updated.
+        *********************************************************/
+        ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_add_not_empty_count++));
+
+        /*********************************************************
+        Check the prime bit. If set goto done
+        *********************************************************/
+        prime = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME);
+/*
+        USB_printf("%03d: Add not empty: bit_pos=%x, prime=0x%x, status=0x%x\n",
+                    usb_dev_ptr->STATS.usb_add_not_empty_count, prime, bit_pos,
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS),
+                    USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS) );
+*/
+        if(prime & bit_pos)
+        {
+            timeout = 0x1000;
+            while( dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME
+                    & USB_32BIT_LE(bit_pos) ) 
+            {
+               /* Wait for the ENDPTPRIME to go to zero */
+                timeout--;
+                if(timeout <= 0)
+                {
+                    USB_printf(
+                        "timeout: CTRL=%x, PRIME=%x, STAT=%x, INTR=%x, ADDR=%x, PORTSC=%x, dTD=%p, temp_dTD=%p\n",
+                        USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0]),
+                        USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), 
+                        USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), 
+                        USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS),
+                        USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR),
+                        USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]), 
+                        first_dTD_ptr, temp_dTD_ptr);
+
+                    _usb_ep_status(handle, xd_ptr->EP_NUM, xd_ptr->BDIRECTION);
+
+                    return USBERR_TR_FAILED;
+                }
+            } /* EndWhile */
+
+            /*ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER,*/
+            if(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS & USB_32BIT_LE(bit_pos))
+            {
+                goto done;
+            }
+        }
+
+        read_safe = FALSE;
+        timeout = 1000000;
+        while(read_safe == FALSE)
+        {
+            timeout--;
+            if(timeout <= 0)
+            {
+                USB_printf("%s: Timeout for ATDTW_TRIPWIRE reg = 0x%x\n", __FUNCTION__, 
+                    (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD));
+                return USBERR_TR_FAILED;
+            }
+
+           /*********************************************************
+           start with setting the semaphores
+           *********************************************************/
+           dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD |= 
+                                          USB_32BIT_LE(EHCI_CMD_ATDTW_TRIPWIRE_SET);
+               
+           /*********************************************************
+           Read the endpoint status
+           *********************************************************/
+           temp_ep_stat = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) 
+                                        & bit_pos; 
+
+           /*********************************************************
+           Reread the ATDTW semaphore bit to check if it is cleared.
+           When hardware see a hazard, it will clear the bit or
+           else we remain set to 1 and we can proceed with priming
+           of endpoint if not already primed.
+           *********************************************************/
+           if( dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD & 
+                                          USB_32BIT_LE(EHCI_CMD_ATDTW_TRIPWIRE_SET))
+           {
+               read_safe = TRUE;
+           }
+
+        }/*end while loop */
+
+        /*********************************************************
+        Clear the semaphore
+        *********************************************************/
+        dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= 
+                                       USB_32BIT_LE(EHCI_CMD_ATDTW_TRIPWIRE_CLEAR);
+
+        /*********************************************************
+         * If endpoint is not active, we activate it now.               
+         *********************************************************/
+         if(!temp_ep_stat)
+         {
+            /* No other transfers on the queue */
+            ep_queue_head_ptr->NEXT_DTD_PTR = USB_32BIT_LE(
+                        USB_DTD_VIRT_TO_PHYS(usb_dev_ptr, first_dTD_ptr));
+            ep_queue_head_ptr->SIZE_IOC_INT_STS = 0;
+
+            /* Prime the Endpoint */
+            dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos);
+         }
+    }
+    else
+    {
+         /* No other transfers on the queue */
+         ep_queue_head_ptr->NEXT_DTD_PTR = USB_32BIT_LE(
+                            USB_DTD_VIRT_TO_PHYS(usb_dev_ptr, first_dTD_ptr));
+         ep_queue_head_ptr->SIZE_IOC_INT_STS = 0;
+   
+         /* Prime the Endpoint */
+         dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos);
+         /* delay */
+         timeout = 0x100;
+         while(timeout > 0)
+             timeout--;
+
+         dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos);
+    }
+
+done:
+   if(first_dTD_ptr == NULL)
+       USB_printf("ERROR !!!! first_dTD_ptr=NULL\n");
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER,
+               " add_%d: fri=0x%x, ep=%d%s, buf=%p, size=%d, xd=%p, dTD=%p %p, empty=%d\n",
+               usb_dev_ptr->STATS.usb_add_count & 0xFFFF, 
+               USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), 
+               xd_ptr->EP_NUM, xd_ptr->BDIRECTION ? "in" : "out", 
+               xd_ptr->WSTARTADDRESS, (int)xd_ptr->WTOTALLENGTH, 
+               xd_ptr, (unsigned)first_dTD_ptr, 
+               usb_dev_ptr->EP_DTD_HEADS[temp], list_empty);
+
+
+   return USB_OK;
+   /* End CR 1015 */
+} /* EndBody */
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_process_tr_complete
+*  Returned Value : None
+*  Comments       :
+*        Services transaction complete interrupt
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_process_tr_complete
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   volatile VUSB20_REG_STRUCT_PTR               dev_ptr;
+   volatile VUSB20_EP_TR_STRUCT_PTR             dTD_ptr; 
+   VUSB20_EP_TR_STRUCT_PTR                      temp_dTD_ptr;
+   VUSB20_EP_QUEUE_HEAD_STRUCT_PTR              ep_queue_head_ptr;
+   uint_32                                      temp, i, ep_num = 0, direction = 0, bit_pos;
+   uint_32                                      remaining_length = 0;
+   uint_32                                      actual_transfer_length = 0;
+   uint_32                                      counter, errors = 0;
+   XD_STRUCT_PTR                                xd_ptr;
+   XD_STRUCT_PTR                                temp_xd_ptr = NULL;
+   uint_8_ptr                                   buff_start_address = NULL;
+   boolean                                      endpoint_detected = FALSE;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_complete_isr_count++));
+
+   /* We use separate loops for ENDPTSETUPSTAT and ENDPTCOMPLETE because the 
+   ** setup packets are to be read ASAP 
+   */
+   
+   /* Process all Setup packet received interrupts */
+   bit_pos = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT);
+   
+   if (bit_pos) 
+   {
+      ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "setup_isr: bit_pos=0x%x\n", (unsigned)bit_pos);
+      for(i=0; i<USB_MAX_CONTROL_ENDPOINTS; i++) 
+      {
+         if (bit_pos & (1 << i)) 
+         {
+            ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_setup_count++));
+            _usb_device_call_service(handle, i, TRUE, 0, 0, 8, 0);
+         } /* Endif */
+      } /* Endfor */
+   } /* Endif */
+   
+   /* Don't clear the endpoint setup status register here. It is cleared as a 
+   ** setup packet is read out of the buffer 
+   */
+
+   /* Process non-setup transaction complete interrupts */   
+   bit_pos = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE);
+
+   /* Clear the bits in the register */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE = USB_32BIT_LE(bit_pos);
+   
+   if (bit_pos) 
+   {
+        ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_complete_count++));
+
+        /* Get the endpoint number and the direction of transfer */
+        counter = 0;
+        for (i=0; i<(ARC_USB_MAX_ENDPOINTS*2); i++) 
+        {
+            endpoint_detected = FALSE;
+            if ((i < ARC_USB_MAX_ENDPOINTS) && (bit_pos & (1 << i)))
+            {
+                ep_num = i;
+                direction = ARC_USB_RECV;
+                endpoint_detected = TRUE;
+            }
+            else
+            {
+                if( (i >= ARC_USB_MAX_ENDPOINTS) && 
+                    (bit_pos & (1 << (i+16-ARC_USB_MAX_ENDPOINTS))))
+                {
+                    ep_num = (i - ARC_USB_MAX_ENDPOINTS);
+                    direction = ARC_USB_SEND;
+                    endpoint_detected = TRUE;
+                }            
+            }
+
+            if(endpoint_detected)
+            {
+                temp = (2*ep_num + direction);
+
+                /* Get the first dTD */      
+                dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[temp];
+            
+                ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp;
+
+                /* Process all the dTDs for respective transfers */
+                while (dTD_ptr) 
+                {            
+                    if (USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_STATUS_ACTIVE) 
+                    {
+                        /* No more dTDs to process. Next one is owned by VUSB */
+                        if(counter == 0)
+                        {
+                            ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "tr_complete - break: ep=%d %s, bit_pos=0x%x\n",
+                                    (unsigned)ep_num, direction ? "SEND" : "RECV", (unsigned)bit_pos);
+
+                            ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_empty_complete_count++));
+                        }
+                        break;
+                    } /* Endif */
+               
+                    /* Get the correct internal transfer descriptor */
+                    xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD;
+                    if (xd_ptr) 
+                    {
+                        buff_start_address = xd_ptr->WSTARTADDRESS;
+                        actual_transfer_length = xd_ptr->WTOTALLENGTH;
+                        temp_xd_ptr = xd_ptr;
+                    } /* Endif */
+               
+                    /* Get the address of the next dTD */
+                    temp_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, 
+                                (uint_32)(USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK) );
+                  
+                    /* Read the errors */
+                    errors = (USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_ERROR_MASK);                  
+                    if (!errors) 
+                    {
+                        /* No errors */
+                        /* Get the length of transfer from the current dTD */   
+                        remaining_length += ((USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSB_EP_TR_PACKET_SIZE) >> 16);
+                        actual_transfer_length -= remaining_length;
+                    } 
+                    else 
+                    {
+                        if (errors & VUSBHS_TD_STATUS_HALTED) 
+                        {
+                            /* Clear the errors and Halt condition */
+                            ep_queue_head_ptr->SIZE_IOC_INT_STS &= USB_32BIT_LE(~errors);
+                        } /* Endif */
+
+                        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ERROR, 
+                            "complete_tr ERROR: ep=%d %s: STS=0x%x, dTD=%p, dTD_next=%p, xd=%p, qh->sts=0x%x\n", 
+                                    (unsigned)ep_num, direction ? "SEND" : "RECV", 
+                                    (unsigned)dTD_ptr->SIZE_IOC_STS, dTD_ptr, temp_dTD_ptr, 
+                                    xd_ptr, ep_queue_head_ptr->SIZE_IOC_INT_STS);
+                    } /* Endif */
+               
+                    /* Retire the processed dTD */
+                    counter++;
+                    _usb_dci_vusb20_cancel_transfer(handle, ep_num, direction);
+                    if( (temp_dTD_ptr == NULL) || 
+                        (temp_dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD != temp_xd_ptr) ) 
+                    {
+                        /* Transfer complete. Call the register service function for the endpoint */
+                        ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_complete_ep_count[temp]++));
+
+#if defined(USB_UNDERRUN_WA)
+                        if( (direction == ARC_USB_SEND) && 
+                            (((ep_queue_head_ptr->MAX_PKT_LENGTH >> 16) & 0x7FF) > global_wa_threshold) )
+                            usbSendComplete(handle, ep_num, FALSE, direction, 
+                                   buff_start_address, actual_transfer_length, errors);
+                        else
+#endif /* USB_UNDERRUN_WA */
+                            _usb_device_call_service(handle, ep_num, FALSE, direction, 
+                                   buff_start_address, actual_transfer_length, errors);
+                        remaining_length = 0;
+
+                        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER,
+                            "comp_%d: fri=0x%x, ep=%d%s, buf=%p, size=%d, xd=%p, dTD=%p %p %p, COMP=0x%x\n", 
+                            usb_dev_ptr->STATS.usb_complete_count & 0xFFFF, 
+                            USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), 
+                            (unsigned)ep_num, direction ? "in" : "out", 
+                            buff_start_address, actual_transfer_length,
+                            temp_xd_ptr, dTD_ptr, temp_dTD_ptr, usb_dev_ptr->EP_DTD_HEADS[temp], (unsigned)bit_pos);
+
+                    } /* Endif */
+                    else
+                    {
+                        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER, "tr_complete not completed: ep=%d %s\n", 
+                                (unsigned)ep_num, direction ? "SEND" : "RECV");
+                    }
+                    if( (temp_dTD_ptr == NULL) && (usb_dev_ptr->EP_DTD_HEADS[temp] != NULL) )
+                    {
+/*
+                        USB_printf("tr_complete: ep=%d, temp_dTD=%p, dTD_ptr=%p (%p), DTD_HEADS=%p, remain=%d\n",
+                                    temp, temp_dTD_ptr, dTD_ptr, 
+                                    USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, (uint_32)(USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK) ),
+                                    usb_dev_ptr->EP_DTD_HEADS[temp], remaining_length);
+*/
+                        dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[temp];
+                    }
+                    else
+                    {
+                        dTD_ptr = temp_dTD_ptr;
+                    }
+                    errors = 0;
+                } /* Endwhile */
+            } /* Endif */
+        } /* Endfor */
+        ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, 
+               ( {if(usb_dev_ptr->STATS.usb_complete_max_count < counter) 
+                            usb_dev_ptr->STATS.usb_complete_max_count = counter;}));
+   } /* Endif */
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_isr
+*  Returned Value : None
+*  Comments       :
+*        Services all the VUSB_HS interrupt sources
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_isr
+   (
+      _usb_device_handle handle
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR        dev_ptr;
+   uint_32                      status;
+
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+   ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_isr_count++));
+
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   status = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS);
+   
+   status &= USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR);
+
+   if(status == 0) 
+   {
+       ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_empty_isr_count++));
+       return;
+   } /* Endif */
+/*
+    USB_printf("USB_ISR: FRINDEX=0x%x, status=0x%x, PORTSC=0x%x, EP_SETUP=0x%x, EP_COMPLETE=0x%x\n", 
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX),
+                    status, 
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]),
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT),
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE) );
+*/
+   /* Clear all the interrupts occured */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS = USB_32BIT_LE(status);
+   
+   if (status & EHCI_STS_ERR) 
+   {
+        usb_dev_ptr->ERROR_STATE = (status & 0xFFFF);
+
+      _usb_dci_vusb20_process_error((pointer)usb_dev_ptr);
+        /* do tr_complete if no STS_INT set */
+        if( (status & EHCI_STS_INT) == 0)
+            _usb_dci_vusb20_process_tr_complete((pointer)usb_dev_ptr);
+
+        /*USB_printf("USB process error: status=0x%x\n", status);*/
+   } /* Endif */
+
+   if (status & EHCI_STS_RESET) 
+   {
+       _usb_dci_vusb20_process_reset((pointer)usb_dev_ptr);
+   } /* Endif */
+   
+   if (status & EHCI_STS_PORT_CHANGE) 
+   {
+      _usb_dci_vusb20_process_port_change((pointer)usb_dev_ptr);
+   } /* Endif */
+      
+   if (status & EHCI_STS_SOF) 
+   {
+      _usb_dci_vusb20_process_SOF((pointer)usb_dev_ptr);
+   } /* Endif */
+   
+   if (status & EHCI_STS_INT) 
+   {
+      _usb_dci_vusb20_process_tr_complete((pointer)usb_dev_ptr);
+   } /* Endif */
+   
+    if (status & EHCI_STS_SUSPEND) 
+    {
+        _usb_dci_vusb20_process_suspend((pointer)usb_dev_ptr);
+    } /* Endif */
+
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_process_reset
+*  Returned Value : None
+*  Comments       :
+*        Services reset interrupt
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_process_reset
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR        dev_ptr;
+   uint_32                      temp;
+   volatile unsigned long       timeout;
+
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_reset\n");
+   ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_reset_count++));
+   
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   /* Inform the application so that it can cancel all previously queued transfers */
+   _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_BUS_RESET, 0, 0, 0, 0, 0);
+
+#if defined(USB_UNDERRUN_WA)
+    _usb_reset_send_queue();
+#endif /* USB_UNDERRUN_WA */
+   
+   /* The address bits are past bit 25-31. Set the address */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR &= ~USB_32BIT_LE(0xFE000000);
+   
+   /* Clear all the setup token semaphores */
+   temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT);
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT = USB_32BIT_LE(temp);
+
+   /* Clear all the endpoint complete status bits */   
+   temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE);
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE = USB_32BIT_LE(temp);
+   
+    timeout = 0x10000;
+    while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & 0xFFFFFFFF) 
+    {
+        timeout--;
+        if(timeout <= 0)
+        {
+            USB_printf("%s: Timeout for ENDPTPRIME = 0x%x\n", __FUNCTION__, 
+                (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME));
+            break;
+        }
+
+      /* Wait until all ENDPTPRIME bits cleared */
+    } /* Endif */
+   
+   /* Write 1s to the Flush register */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH = USB_32BIT_LE(0xFFFFFFFF);
+   
+    if( (usb_dev_ptr->ERROR_STATE == 0x0) &&
+        (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & 
+                                                EHCI_PORTSCX_PORT_RESET) )
+    {
+        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_RESET,
+                    "USB Bus Reset: fri=0x%x, dev_ptr=%p, STATE=%d, PORTSC=0x%x, CMD=0x%x, ENDPT[0]=0x%x\n", 
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), 
+                    usb_dev_ptr, usb_dev_ptr->USB_STATE,
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]),
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD),
+                    USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0]));
+
+        usb_dev_ptr->BUS_RESETTING = TRUE;
+        usb_dev_ptr->USB_STATE = ARC_USB_STATE_POWERED;
+    } 
+    else 
+    { 
+        USB_printf("USB Chip reinit: PORTSC=0x%x\n", 
+                USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]));
+
+        /* re-initialize */      
+        _usb_dci_vusb20_chip_initialize((pointer)usb_dev_ptr);
+        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, "process_reset, Chip reinit hw\n");
+    } /* Endif */
+   
+    _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_BUS_RESET, 1, 0, 0, 0, 0);
+
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_process_suspend
+*  Returned Value : None
+*  Comments       :
+*        Services suspend interrupt
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_process_suspend
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+    USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+    VUSB20_REG_STRUCT_PTR        dev_ptr;
+   
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_suspend\n");
+    ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_suspend_count++));
+   
+    usb_dev_ptr->USB_DEV_STATE_B4_SUSPEND = usb_dev_ptr->USB_STATE;
+   
+    usb_dev_ptr->USB_STATE = ARC_USB_STATE_SUSPEND;
+
+    /* Inform the upper layers */
+    _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_SLEEP, 0, 0, 0, 0, 0);
+   
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_process_SOF
+*  Returned Value : None
+*  Comments       :
+*        Services SOF interrupt
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_process_SOF
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR                        dev_ptr;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_SOF\n");
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   /* Inform the upper layer */   
+   _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_SOF, 0, 0, 0, 
+      USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), 0);
+
+} /* EndBody */
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_process_port_change
+*  Returned Value : None
+*  Comments       :
+*        Services port change detect interrupt
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_process_port_change
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+    USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+    VUSB20_REG_STRUCT_PTR                        dev_ptr;
+
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_port_change\n");
+    ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_port_change_count++));
+
+    dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+/*
+    USB_printf("port_change: PORTSC=0x%x, DTD_ENTRIES=%d, XD_ENTRIES=%d\n", 
+                USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]),
+                usb_dev_ptr->DTD_ENTRIES, usb_dev_ptr->XD_ENTRIES);
+*/
+    if (usb_dev_ptr->BUS_RESETTING) 
+    {
+        /* Bus reset operation complete */
+        usb_dev_ptr->BUS_RESETTING = FALSE;
+    } /* Endif */
+   
+    if (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & 
+                                                EHCI_PORTSCX_PORT_RESET)) 
+    {
+        /* Get the speed */
+        if (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & 
+                                            EHCI_PORTSCX_PORT_HIGH_SPEED) 
+        {
+            usb_dev_ptr->SPEED = ARC_USB_SPEED_HIGH;
+        } 
+        else 
+        {
+            usb_dev_ptr->SPEED = ARC_USB_SPEED_FULL;
+        } /* Endif */
+/*
+        USB_printf("USB %s speed device detected\n", 
+                (usb_dev_ptr->SPEED == ARC_USB_SPEED_HIGH) ? "High" : "Full");
+*/
+        /* Inform the upper layers of the speed of operation */      
+        _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_SPEED_DETECTION, 0, 0, 
+                                0, usb_dev_ptr->SPEED, 0);
+    } /* Endif */
+      
+    if (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & 
+                                                EHCI_PORTSCX_PORT_SUSPEND) 
+    {   
+        usb_dev_ptr->USB_DEV_STATE_B4_SUSPEND = usb_dev_ptr->USB_STATE;
+        usb_dev_ptr->USB_STATE = ARC_USB_STATE_SUSPEND;
+
+        /* Inform the upper layers */
+        USB_printf("USB suspend\n");
+        _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_SUSPEND, 0, 0, 0, 0, 0);
+    } /* Endif */
+   
+    if (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & EHCI_PORTSCX_PORT_SUSPEND) 
+                    && (usb_dev_ptr->USB_STATE == ARC_USB_STATE_SUSPEND)) 
+    {
+        USB_printf("USB resume\n");
+        usb_dev_ptr->USB_STATE = usb_dev_ptr->USB_DEV_STATE_B4_SUSPEND;
+        /* Inform the upper layers */
+        _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_RESUME, 0, 0, 0, 0, 0);
+
+        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SUSPEND, "process_port_change, SUCCESSFUL, resumed\n");
+        return;
+    } /* Endif */
+   
+    usb_dev_ptr->USB_STATE = ARC_USB_STATE_DEFAULT;
+      
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_process_error
+*  Returned Value : None
+*  Comments       :
+*        Services error interrupt
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_process_error
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR          usb_dev_ptr;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   
+   /* Increment the error count */
+   usb_dev_ptr->ERRORS++;
+   
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ERROR, 
+                "process_error_%d: state=0x%x\n", 
+                    usb_dev_ptr->ERRORS, usb_dev_ptr->ERROR_STATE); 
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_set_speed_full
+*  Returned Value : None
+*  Comments       :
+*        Force the controller port in full speed mode.
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_set_speed_full
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+     
+      /* The port number on the device */
+      uint_8                     port_number
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR                        dev_ptr;
+   uint_32                                      port_control;
+   
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ANY, "FORCE set_speed_full\n");
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   port_control = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[port_number]);   
+   port_control |= EHCI_PORTSCX_FORCE_FULL_SPEED_CONNECT;
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[port_number] = USB_32BIT_LE(port_control);
+  
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_suspend_phy
+*  Returned Value : None
+*  Comments       :
+*        Suspends the PHY in low power mode
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_suspend_phy
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+     
+      /* The port number on the device */
+      uint_8                     port_number
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR                        dev_ptr;
+   uint_32                                      port_control;
+      
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SUSPEND, "set_suspend_phy\n");
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   port_control = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[port_number]);   
+   port_control |= EHCI_PORTSCX_PHY_CLOCK_DISABLE;
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[port_number] = USB_32BIT_LE(port_control);
+   
+} /* EndBody */
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_set_address
+*  Returned Value : None
+*  Comments       :
+*        Sets the newly assigned device address
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_set_address
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+     
+      /* Address of the device assigned by the host */
+      uint_8                     address
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR          usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR             dev_ptr;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ADDR, "set_address: address=%d\n",address);
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   
+#ifdef SET_ADDRESS_HARDWARE_ASSISTANCE   
+   /***********************************************************
+   Hardware Rev 4.0 onwards have special assistance built in
+   for handling the set_address command. As per the USB specs
+   a device should be able to receive the response on a new
+   address, within 2 msecs after status phase of set_address is
+   completed. Since 2 mili second may be a very small time window
+   (on high interrupt latency systems) before software could 
+   come to the code below and write the device register,
+   this routine will be called in advance when status phase of
+   set_address is still not finished. The following line in the
+   code will set the bit 24 to '1' and hardware will take
+   the address and queue it in an internal buffer. From which
+   it will use it to decode the next USB token. Please look
+   at hardware rev details for the implementation of this
+   assistance.
+   
+   Also note that writing bit 24 to 0x01 will not break
+   any old hardware revs because it was an unused bit.
+   ***********************************************************/
+   /* The address bits are past bit 25-31. Set the address 
+   also set the bit 24 to 0x01 to start hardware assitance*/
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR = 
+      USB_32BIT_LE((uint_32)address << VUSBHS_ADDRESS_BIT_SHIFT) | 
+      (0x01 << (VUSBHS_ADDRESS_BIT_SHIFT -1)); 
+#else
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR = 
+      USB_32BIT_LE((uint_32)address << VUSBHS_ADDRESS_BIT_SHIFT); 
+#endif /* SET_ADDRESS_HARDWARE_ASSISTANCE */
+   
+   usb_dev_ptr->USB_STATE = ARC_USB_STATE_ADDRESS;
+      
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_get_setup_data
+*  Returned Value : None
+*  Comments       :
+*        Reads the Setup data from the 8-byte setup buffer
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_get_setup_data
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [OUT] address of the buffer to read the setup data into */
+      uint_8_ptr                  buffer_ptr
+   )
+{ /* Body */
+    USB_DEV_STATE_STRUCT_PTR                    usb_dev_ptr;
+    volatile VUSB20_REG_STRUCT_PTR              dev_ptr;
+    volatile VUSB20_EP_QUEUE_HEAD_STRUCT_PTR    ep_queue_head_ptr;
+    volatile boolean                            read_safe = FALSE;                      
+    volatile unsigned long                      timeout;
+
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   /* Get the endpoint queue head */
+   ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + 
+                                                                2*ep_num + ARC_USB_RECV;
+
+   /********************************************************************
+   CR 1219. Hardware versions 2.3+ have a implementation of tripwire 
+   semaphore mechanism that requires that we read the contents of 
+   QH safely by using the semaphore. Read the USBHS document to under
+   stand how the code uses the semaphore mechanism. The following are
+   the steps in brief
+   
+   1. USBCMD Write ‘1’ to Setup Tripwire in register.
+   2. Duplicate contents of dQH.StatusBuffer into local software byte
+      array.
+   3  Read Setup TripWire in register. (if set - continue; if
+      cleared goto 1.)
+   4. Write '0' to clear Setup Tripwire in register.
+   5. Process setup packet using local software byte array copy and
+      execute status/handshake phases.
+   
+           
+   ********************************************************************/
+    timeout = 0x100000;
+    while(!read_safe)
+    {
+        /*********************************************************
+        start with setting the semaphores
+        *********************************************************/
+
+        dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD |= 
+                                                USB_32BIT_LE(EHCI_CMD_SETUP_TRIPWIRE_SET);
+
+        /* Copy the setup packet to private buffer */
+        USB_memcopy((uint_8_ptr)ep_queue_head_ptr->SETUP_BUFFER, buffer_ptr, 8);
+
+        /*********************************************************
+        If setup tripwire semaphore is cleared by hardware it means
+        that we have a danger and we need to restart.
+        else we can exit out of loop safely.
+        *********************************************************/
+        if(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD) &
+                                                   EHCI_CMD_SETUP_TRIPWIRE_SET)
+        {
+            read_safe = TRUE; /* we can proceed exiting out of loop*/
+        }
+        if(timeout <= 0)
+        {
+            USB_printf("%s: Timeout for SETUP_TRIPWIRE = 0x%x\n", __FUNCTION__, 
+                        (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD));
+            break;
+        }
+    }
+    ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_read_setup_count++));
+  
+   /*********************************************************
+   Clear the semaphore bit now
+   *********************************************************/
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &=
+                                    USB_32BIT_LE(EHCI_CMD_SETUP_TRIPWIRE_CLEAR);                         
+   
+   /* Clear the bit in the ENDPTSETUPSTAT */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT = USB_32BIT_LE(1 << ep_num);
+   
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_init_endpoint
+*  Returned Value : None
+*  Comments       :
+*        Initializes the specified endpoint and the endpoint queue head
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_dci_vusb20_init_endpoint
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the transaction descriptor address */
+      XD_STRUCT_PTR              xd_ptr
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR                        dev_ptr;
+   VUSB20_EP_QUEUE_HEAD_STRUCT _PTR_            ep_queue_head_ptr;
+   uint_32                                      val, bit_pos;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   /* Get the endpoint queue head address */
+   ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + 
+                                                    2*xd_ptr->EP_NUM + xd_ptr->BDIRECTION;
+      
+   bit_pos = (1 << (16 * xd_ptr->BDIRECTION + xd_ptr->EP_NUM));
+
+   /* Check if the Endpoint is Primed */
+   if ((!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & bit_pos)) && 
+       (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos))) 
+   { 
+      /* Set the max packet length, interrupt on Setup and Mult fields */
+      if (xd_ptr->EP_TYPE == ARC_USB_ISOCHRONOUS_ENDPOINT) 
+      {
+         /* Mult bit should be set for isochronous endpoints */
+         ep_queue_head_ptr->MAX_PKT_LENGTH = USB_32BIT_LE((xd_ptr->WMAXPACKETSIZE << 16) | 
+            ((xd_ptr->MAX_PKTS_PER_UFRAME ?  xd_ptr->MAX_PKTS_PER_UFRAME : 1) << 
+            VUSB_EP_QUEUE_HEAD_MULT_POS));
+      } 
+      else 
+      {
+         if (xd_ptr->EP_TYPE != ARC_USB_CONTROL_ENDPOINT) 
+         {
+             /* BULK or INTERRUPT */
+            ep_queue_head_ptr->MAX_PKT_LENGTH = USB_32BIT_LE((xd_ptr->WMAXPACKETSIZE << 16) | 
+               (xd_ptr->DONT_ZERO_TERMINATE ? VUSB_EP_QUEUE_HEAD_ZERO_LEN_TER_SEL : 0));
+         } 
+         else 
+         {
+             /* CONTROL */
+            ep_queue_head_ptr->MAX_PKT_LENGTH = USB_32BIT_LE((xd_ptr->WMAXPACKETSIZE << 16) | 
+                                                    VUSB_EP_QUEUE_HEAD_IOS);
+         } /* Endif */
+      } /* Endif */
+      
+      /* Enable the endpoint for Rx or Tx and set the endpoint type */
+      val = dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM];
+      if(xd_ptr->BDIRECTION  == ARC_USB_SEND)
+      {
+          val &= ~(USB_32BIT_LE(EHCI_EPCTRL_TX_ALL_MASK));
+          val |= USB_32BIT_LE((EHCI_EPCTRL_TX_ENABLE | EHCI_EPCTRL_TX_DATA_TOGGLE_RST) | 
+                          (xd_ptr->EP_TYPE << EHCI_EPCTRL_TX_EP_TYPE_SHIFT));
+      }
+      else
+      {
+          val &= ~(USB_32BIT_LE(EHCI_EPCTRL_RX_ALL_MASK));
+          val |= USB_32BIT_LE((EHCI_EPCTRL_RX_ENABLE | EHCI_EPCTRL_RX_DATA_TOGGLE_RST) | 
+                          (xd_ptr->EP_TYPE << EHCI_EPCTRL_RX_EP_TYPE_SHIFT));
+      }
+      dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] = val;
+      
+      /* Implement Guideline (GL# USB-7) The unused endpoint type must  */
+      /* be programmed to bulk.                                         */
+      if( (dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] & 
+            USB_32BIT_LE(EHCI_EPCTRL_RX_ENABLE)) == 0)
+      {
+          dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] |= 
+              USB_32BIT_LE(ARC_USB_BULK_ENDPOINT << EHCI_EPCTRL_RX_EP_TYPE_SHIFT);
+      }
+
+      if( (dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] & 
+            USB_32BIT_LE(EHCI_EPCTRL_TX_ENABLE)) == 0)
+      {
+          dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] |= 
+              USB_32BIT_LE(ARC_USB_BULK_ENDPOINT << EHCI_EPCTRL_TX_EP_TYPE_SHIFT);
+      }
+
+      ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT,
+                    "init ep #%d %s: type=0x%x, EPCTRLX=0x%x, SETUP=0x%x, PRIME=0x%x, STATUS=0x%x, COMPL=0x%x\n", 
+                        xd_ptr->EP_NUM, xd_ptr->BDIRECTION ? "SEND" : "RECV", xd_ptr->EP_TYPE, 
+                        (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM]),
+                        (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT),
+                        (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME),
+                        (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS),
+                        (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE) );
+   } 
+   else 
+   { 
+      USB_printf("ep=%d %s: Init ERROR: ENDPTPRIME=0x%x, ENDPTSTATUS=0x%x, bit_pos=0x%x\n",
+                (unsigned)xd_ptr->EP_NUM, xd_ptr->BDIRECTION ? "SEND" : "RECV",
+                (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME),
+                (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), 
+                (unsigned)bit_pos);
+        return USBERR_EP_INIT_FAILED;
+   } /* Endif */
+      
+   return USB_OK;
+   
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_get_transfer_status
+*  Returned Value : USB_OK or error code
+*  Comments       :
+*        Gets the status of a transfer
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_dci_vusb20_get_transfer_status
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+     
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   VUSB20_EP_TR_STRUCT_PTR                      dTD_ptr;
+   XD_STRUCT_PTR                                xd_ptr;
+   uint_8                                       status;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+  
+   /* Unlink the dTD */
+   dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[2*ep_num + direction];
+
+   if (dTD_ptr) 
+   {
+      /* Get the transfer descriptor for the dTD */
+      xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD;
+      status = xd_ptr->BSTATUS;
+   } 
+   else 
+   {
+      status = ARC_USB_STATUS_IDLE;
+   } /* Endif */
+   
+   return (status);
+
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_get_transfer_details
+*  Returned Value : pointer to structure that has details for transfer
+*        Gets the status of a transfer
+*
+*END*-----------------------------------------------------------------*/
+XD_STRUCT_PTR  _usb_dci_vusb20_get_transfer_details
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+     
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR                        dev_ptr;
+   VUSB20_EP_TR_STRUCT_PTR                      dTD_ptr, temp_dTD_ptr;
+   XD_STRUCT_PTR                                xd_ptr;
+   uint_32                                      temp, remaining_bytes;
+   VUSB20_EP_QUEUE_HEAD_STRUCT_PTR              ep_queue_head_ptr;
+
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   temp = (2*ep_num + direction);
+
+   /* get a pointer to QH for this endpoint */   
+   ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "get_transfer_details\n");
+   
+   /* Unlink the dTD */
+   dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[2*ep_num + direction];
+
+   if (dTD_ptr) 
+   {      
+      /* Get the transfer descriptor for the dTD */
+      xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD;
+      if(!xd_ptr) return NULL;
+      
+      /* Initialize the transfer length field */
+      xd_ptr->WSOFAR =0;
+      remaining_bytes =0;
+      
+      /*if length of this transfer is greater than 20K
+      we have multiple DTDs to count */
+      if(xd_ptr->WTOTALLENGTH > VUSB_EP_MAX_LENGTH_TRANSFER)
+      {
+         /* it is a valid DTD. We should parse all DTDs for this XD
+         and find the total bytes used so far */
+         temp_dTD_ptr = dTD_ptr;
+      
+         /*loop through the list of DTDS until an active DTD is found
+         or list has finished */
+         while(!(USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_NEXT_TERMINATE))         
+         {
+            
+            /**********************************************************
+            If this DTD has been overlayed, we take the actual length 
+            from QH.
+            **********************************************************/
+
+            if ((uint_32)(USB_32BIT_LE(ep_queue_head_ptr->CURR_DTD_PTR) & VUSBHS_TD_ADDR_MASK) ==
+                                     USB_DTD_VIRT_TO_PHYS(usb_dev_ptr, temp_dTD_ptr) )
+            {
+                remaining_bytes += 
+                  ((USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS) & VUSB_EP_TR_PACKET_SIZE) >> 16);
+            }
+            else
+            {
+               /* take the length from DTD itself */
+                remaining_bytes += 
+                  ((USB_32BIT_LE(temp_dTD_ptr->SIZE_IOC_STS) & VUSB_EP_TR_PACKET_SIZE) >> 16);
+            }
+   
+            dTD_ptr = temp_dTD_ptr;
+             
+            /* Get the address of the next dTD */
+            temp_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, 
+                                (uint_32)(USB_32BIT_LE(temp_dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK) );
+         }
+         xd_ptr->WSOFAR = xd_ptr->WTOTALLENGTH - remaining_bytes;
+      }
+      else
+      {
+         /*look at actual length from QH*/
+         xd_ptr->WSOFAR = xd_ptr->WTOTALLENGTH - 
+            ((USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS) & VUSB_EP_TR_PACKET_SIZE) >> 16);         
+      }      
+   } 
+   else 
+   {
+      xd_ptr = NULL;
+   } /* Endif */
+   
+   return (xd_ptr);
+
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_deinit_endpoint
+*  Returned Value : None
+*  Comments       :
+*        Disables the specified endpoint and the endpoint queue head
+*
+*END*-----------------------------------------------------------------*/
+uint_8 _usb_dci_vusb20_deinit_endpoint
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+    USB_DEV_STATE_STRUCT_PTR        usb_dev_ptr;
+    VUSB20_REG_STRUCT_PTR           dev_ptr;
+    VUSB20_EP_QUEUE_HEAD_STRUCT*    ep_queue_head_ptr;
+    uint_32                         bit_pos;
+    uint_8                          status = USB_OK;
+   
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+    dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   
+    /* Get the endpoint queue head address */
+    ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR +
+                                                                    (2*ep_num + direction);
+      
+    bit_pos = (1 << (16 * direction + ep_num));
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT,
+               "deinit ep #%d-%s: bit_pos=0x%x, EPCTRLX=0x%x, SETUP=0x%x, PRIME=0x%x, STATUS=0x%x, COMPL=0x%x\n", 
+                   ep_num, direction ? "SEND" : "RECV", bit_pos,
+                   (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num]),
+                   (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT),
+                   (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME),
+                   (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS),
+                   (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE) );
+      
+    /* Check if the Endpoint is Primed */
+    if( ((USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & bit_pos)) || 
+        ((USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos)) ) 
+    { 
+        USB_printf("ep=%d %s: Deinit ERROR: ENDPTPRIME=0x%x, ENDPTSTATUS=0x%x, bit_pos=0x%x\n",
+                (unsigned)ep_num, direction ? "SEND" : "RECV",
+                (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME),
+                (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), 
+                (unsigned)bit_pos);
+        status = USBERR_EP_DEINIT_FAILED;
+    }
+
+    /* Reset the max packet length and the interrupt on Setup */
+    ep_queue_head_ptr->MAX_PKT_LENGTH = 0;
+      
+    /* Disable the endpoint for Rx or Tx and reset the endpoint type */
+    dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] &= 
+         USB_32BIT_LE( ~((direction ? EHCI_EPCTRL_TX_ENABLE : EHCI_EPCTRL_RX_ENABLE) | 
+                        (direction ? EHCI_EPCTRL_TX_TYPE : EHCI_EPCTRL_RX_TYPE)));
+      
+   return status;
+}
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_shutdown
+*  Returned Value : None
+*  Comments       :
+*        Shuts down the VUSB_HS Device
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_shutdown
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+    USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+    VUSB20_REG_STRUCT_PTR                        dev_ptr;
+   
+    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+    dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   
+    /* Disable interrupts */
+    dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR &= 
+      ~(USB_32BIT_LE(EHCI_INTR_INT_EN | EHCI_INTR_ERR_INT_EN |
+      EHCI_INTR_PORT_CHANGE_DETECT_EN | EHCI_INTR_RESET_EN));
+      
+    USB_uncached_memfree(usb_dev_ptr->EP_QUEUE_HEAD_BASE, 
+                        usb_dev_ptr->EP_QUEUE_HEAD_SIZE, 
+                        usb_dev_ptr->EP_QUEUE_HEAD_PHYS);
+
+    USB_uncached_memfree(usb_dev_ptr->DTD_BASE_PTR, 
+                        usb_dev_ptr->DTD_SIZE, 
+                        usb_dev_ptr->DTD_BASE_PHYS);
+
+    USB_memfree(usb_dev_ptr->SCRATCH_STRUCT_BASE);
+
+    USB_printf("USB shutdown: usb_dev_ptr=%p\n", usb_dev_ptr);
+
+   /* Reset the Run the bit in the command register to stop VUSB */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= ~USB_32BIT_LE(EHCI_CMD_RUN_STOP);
+   
+   /* Reset the controller to get default values */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD = USB_32BIT_LE(EHCI_CMD_CTRL_RESET);
+              
+} /* EndBody */
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_stop
+*  Returned Value : None
+*  Comments       :
+*        Stop USB device controller
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_stop(_usb_device_handle handle)
+{
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR        dev_ptr;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+    /* Disable interrupts */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR &= 
+            ~(USB_32BIT_LE(EHCI_INTR_INT_EN | EHCI_INTR_ERR_INT_EN |
+                           EHCI_INTR_PORT_CHANGE_DETECT_EN | EHCI_INTR_RESET_EN));
+
+   /* Reset the Run the bit in the command register to stop VUSB */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= ~USB_32BIT_LE(EHCI_CMD_RUN_STOP);
+}
+
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_start
+*  Returned Value : None
+*  Comments       :
+*        Start USB device controller
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_start(_usb_device_handle handle)
+{
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR        dev_ptr;
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+      /* Enable interrupts */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR = USB_32BIT_LE(
+                           EHCI_INTR_INT_EN
+                         | EHCI_INTR_ERR_INT_EN 
+                         | EHCI_INTR_PORT_CHANGE_DETECT_EN 
+                         | EHCI_INTR_RESET_EN 
+                         | EHCI_INTR_DEVICE_SUSPEND
+                       /*  
+                         | EHCI_INTR_SOF_UFRAME_EN 
+                        */
+                         );
+   
+   usb_dev_ptr->USB_STATE = ARC_USB_STATE_UNKNOWN;
+   
+   /* Set the Run bit in the command register */
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD = USB_32BIT_LE(EHCI_CMD_RUN_STOP);
+}
+
+/* EOF */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevUtl.c b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevUtl.c
new file mode 100755
index 0000000..3cfb91c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/device/mvUsbHsDevUtl.c
@@ -0,0 +1,271 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+
+#include "usb/api/mvUsbDevApi.h"
+#include "usb/device/mvUsbDevPrv.h"
+#include "usb/api/mvUsbDefs.h"
+
+/* Test packet for Test Mode : TEST_PACKET. USB 2.0 Specification section 7.1.20 */
+uint_8 test_packet[USB_TEST_MODE_TEST_PACKET_LENGTH] = 
+{
+   /* Synch */
+   /* DATA 0 PID */
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+   0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 
+   0xAA, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 
+   0xEE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xBF, 0xDF, 
+   0xEF, 0xF7, 0xFB, 0xFD, 0xFC, 0x7E, 0xBF, 0xDF, 
+   0xEF, 0xF7, 0xFB, 0xFD, 0x7E
+};
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_assert_resume
+*  Returned Value : None
+*  Comments       :
+*        Resume signalling for remote wakeup
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_assert_resume
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR             dev_ptr;
+   uint_32                                      temp;
+ 
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+
+   /* Assert the Resume signal */   
+   temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]);
+   temp &= ~EHCI_PORTSCX_W1C_BITS;
+   temp |= EHCI_PORTSCX_PORT_FORCE_RESUME;
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0] = USB_32BIT_LE(temp);
+   
+   /* Port change interrupt will be asserted at the end of resume 
+   ** operation 
+   */
+
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_stall_endpoint
+*  Returned Value : None
+*  Comments       :
+*        Stalls the specified endpoint
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_stall_endpoint
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR             usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR                dev_ptr;
+   VUSB20_EP_QUEUE_HEAD_STRUCT _PTR_    ep_queue_head_ptr;
+      
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   
+   /* Get the endpoint queue head address */
+   ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + 
+                                                                    2*ep_num + direction;
+   /* Stall the endpoint for Rx or Tx and set the endpoint type */
+   if (ep_queue_head_ptr->MAX_PKT_LENGTH & USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_IOS)) 
+   {
+      /* This is a control endpoint so STALL both directions */
+      dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= 
+         USB_32BIT_LE((EHCI_EPCTRL_TX_EP_STALL | EHCI_EPCTRL_RX_EP_STALL));
+   } 
+   else 
+   {   
+       if(direction) 
+       {
+            dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= 
+                        USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL);
+       }
+       else {
+            dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= 
+                        USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL);
+       }
+   } /* Endif */

+

+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_STALL, 

+                    "STALL ep=%d %s: EPCTRLX=0x%x, CURR_dTD=0x%x, NEXT_dTD=0x%x, SIZE=0x%x\n", 

+                    ep_num, direction ? "SEND" : "RECV",

+                    (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num]),

+                    (unsigned)USB_32BIT_LE(ep_queue_head_ptr->CURR_DTD_PTR), 

+                    (unsigned)USB_32BIT_LE(ep_queue_head_ptr->NEXT_DTD_PTR),

+                    (unsigned)USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS));

+      
+} /* EndBody */
+
+/*FUNCTION*-------------------------------------------------------------
+*
+*  Function Name  : _usb_dci_vusb20_unstall_endpoint
+*  Returned Value : None
+*  Comments       :
+*        Unstall the specified endpoint in the specified direction
+*
+*END*-----------------------------------------------------------------*/
+void _usb_dci_vusb20_unstall_endpoint
+   (
+      /* [IN] the USB_dev_initialize state structure */
+      _usb_device_handle         handle,
+            
+      /* [IN] the Endpoint number */
+      uint_8                     ep_num,
+            
+      /* [IN] direction */
+      uint_8                     direction
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR        dev_ptr;
+
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   
+   /* Enable the endpoint for Rx or Tx and set the endpoint type */
+   if(direction)
+   {

+        dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= 

+              USB_32BIT_LE(EHCI_EPCTRL_TX_DATA_TOGGLE_RST);

+
+        dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] &= 
+                ~(USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL));
+   }
+   else
+   {
+        dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= 

+              USB_32BIT_LE(EHCI_EPCTRL_RX_DATA_TOGGLE_RST);

+

+        dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] &= 
+                ~(USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL));
+   }     

+

+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_STALL, 

+                    "UNSTALL ep=%d %s: EPCTRLX=0x%x\n", 

+                    ep_num, direction ? "SEND" : "RECV",

+                    (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num]));

+

+
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _usb_dci_vusb20_is_endpoint_stalled
+* Returned Value : None
+* Comments       :
+*     Gets the endpoint status
+* 
+*END*--------------------------------------------------------------------*/
+uint_8 _usb_dci_vusb20_is_endpoint_stalled
+   (
+      /* [IN] Handle to the USB device */
+      _usb_device_handle   handle,
+      
+      /* [IN] Endpoint number */
+      uint_8               ep,

+

+      /* [IN] Endpoint direction */

+      uint_8               dir
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR        dev_ptr;

+   uint_32                      value;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "is_endpoint_stalled\n");
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+  

+   if(dir)

+   {
+        value = dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep] & 

+                                    (USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL));

+   }

+   else

+   {

+        value = dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep] & 

+                                    (USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL));

+   }

+   return (value) ? 1 : 0;
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _usb_dci_vusb20_set_test_mode
+* Returned Value : None
+* Comments       :
+*     sets/resets the test mode
+* 
+*END*--------------------------------------------------------------------*/
+void _usb_dci_vusb20_set_test_mode
+   (
+      /* [IN] Handle to the USB device */
+      _usb_device_handle handle,
+      
+      /* [IN] Test mode */
+      uint_16 test_mode
+   )
+{ /* Body */
+   USB_DEV_STATE_STRUCT_PTR                     usb_dev_ptr;
+   VUSB20_REG_STRUCT_PTR                        dev_ptr;
+   uint_32                                      temp;
+
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ANY, "set_test_mode\n");
+   
+   usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle;
+   dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR;
+   
+   temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0]);
+   
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0] = 
+                                USB_32BIT_LE((temp | EHCI_EPCTRL_TX_DATA_TOGGLE_RST));
+
+   if (test_mode == ARC_USB_TEST_MODE_TEST_PACKET) 
+   {
+       USB_memcopy(test_packet, usb_dev_ptr->TEST_PKT_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH); 
+      _usb_device_send_data(handle, 0, usb_dev_ptr->TEST_PKT_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH);
+
+   } /* Endif */
+   
+   temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]);
+   temp &= ~EHCI_PORTSCX_W1C_BITS;
+   
+   dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0] = 
+                                    USB_32BIT_LE(temp | ((uint_32)test_mode << 8));
+             
+} /* EndBody */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/examples/disk.c b/arch/arm/plat-feroceon/mv_hal/usb/examples/disk.c
new file mode 100755
index 0000000..6876c12
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/examples/disk.c
@@ -0,0 +1,2296 @@
+/*******************************************************************************
+
+This software file (the "File") is distributed by Marvell International Ltd. 
+or its affiliate(s) under the terms of the GNU General Public License Version 2, 
+June 1991 (the "License").  You may use, redistribute and/or modify this File 
+in accordance with the terms and conditions of the License, a copy of which 
+is available along with the File in the license.txt file or by writing to the 
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 
+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+
+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.
+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.
+
+*******************************************************************************/
+
+/**************************************************************************
+Include the USB stack and local header files.
+**************************************************************************/
+
+#include "usb/api/mvUsbDefs.h"
+#include "usb/api/mvUsbCh9.h"
+#include "usb/api/mvUsbDebug.h"
+#include "usb/api/mvUsbDevApi.h"
+#include "usb/examples/disk.h"
+
+/* MSB of debug flags for USB device usage */
+#define ARC_DEBUG_FLAG_DISK         0x01000000
+#define ARC_DEBUG_FLAG_DISK_READ    0x02000000
+#define ARC_DEBUG_FLAG_DISK_WRITE   0x04000000
+#define ARC_DEBUG_FLAG_DISK_CAP     0x08000000
+#define ARC_DEBUG_FLAG_DISK_DATA    0x10000000
+#define ARC_DEBUG_FLAG_DISK_DUMP    0x20000000
+
+
+/**************************************************************************
+Include the OS and BSP dependent files that define IO functions and
+basic types. You may like to change these files for your board and RTOS 
+**************************************************************************/
+   
+
+/**************************************************************************
+Global variables and some defines for device.
+**************************************************************************/
+
+#define BUFFERSIZE                      (2048)
+
+#define EP_TEMP_BUFFERSIZE              (32)
+#define MASS_STORAGE_INTERFACE          (0)
+
+#define APP_CONTROL_MAX_PKT_SIZE        (64)
+#define DEV_DESC_MAX_PACKET_SIZE        (7)
+#define DISK_FS_MAX_PACKET_SIZE         (64)
+#define DISK_HS_MAX_PACKET_SIZE         (512)
+
+#define CFG_DESC_EP_IN_TYPE_OFFSET              (21)
+#define CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET   (22)
+#define CFG_DESC_EP_OUT_TYPE_OFFSET             (28)
+#define CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET  (29)
+
+#define TOTAL_LOGICAL_ADDRESS_BLOCKS    (4096)
+#define LENGTH_OF_EACH_LAB              (512)
+
+#define DISK_IN_EP_NO       1
+#define DISK_OUT_EP_NO      2
+
+#define DISK_IN_EP_TYPE     2 /* Bulk */
+#define DISK_OUT_EP_TYPE    2 /* Bulk */
+
+typedef struct
+{
+    _usb_device_handle  usbDevHandle;     /* Must be first field */
+    uint_32             devNo;
+    uint_8_ptr          Send_Buffer_Unaligned;
+
+    uint_8_ptr          DevDesc;
+    uint_8_ptr          DevQualifierDesc;
+    uint_8_ptr          ConfigDesc;
+    uint_8_ptr          other_speed_config;
+    uint_8_ptr          ep1_buf;
+    uint_8_ptr          epTemp_buf;
+    DISK_READ_CAPACITY* pReadCapacity;
+    CSW_STRUCT*         pCSW;
+    uint_8_ptr          MASS_STORAGE_DISK;
+
+    SETUP_STRUCT        local_setup_packet;
+
+    volatile boolean    TEST_ENABLED;
+    volatile boolean    ENTER_TEST_MODE; 
+    volatile uint_16    test_mode_index;
+    volatile uint_8     speed;
+    uint_16             logicalBlocks;
+    uint_32             hsMaxPktSize;
+    uint_32             fsMaxPktSize;
+
+    uint_32             inEpType;
+    uint_32             outEpType;
+
+    uint_32             inEpNo;
+    uint_32             outEpNo;
+    boolean             CBW_PROCESSED;
+    boolean             ZERO_TERMINATE;
+
+} USB_DISK_STRUCT;
+
+uint_32             diskHsMaxPktSize = DISK_HS_MAX_PACKET_SIZE;
+uint_32             diskFsMaxPktSize = DISK_FS_MAX_PACKET_SIZE;
+
+uint_32             diskInEpType = DISK_IN_EP_TYPE;
+uint_32             diskOutEpType = DISK_OUT_EP_TYPE;
+
+uint_32             diskInEpNo = DISK_IN_EP_NO;
+uint_32             diskOutEpNo = DISK_OUT_EP_NO;
+
+static USB_DISK_STRUCT*  usbDisksPtr[MAX_USB_DEVICES] = { NULL, NULL };
+
+/**************************************************************************
+DESCRIPTORS DESCRIPTORS DESCRIPTORS DESCRIPTORS DESCRIPTORS DESCRIPTORS
+**************************************************************************/
+
+#define DEVICE_DESCRIPTOR_SIZE 18
+static const uint_8  DevDescData[DEVICE_DESCRIPTOR_SIZE] =
+{
+   /* Length of DevDesc */
+   DEVICE_DESCRIPTOR_SIZE,
+   /* "Device" Type of descriptor */
+   1,
+   /* BCD USB version */
+   0, 2,
+   /* Device Class is indicated in the interface descriptors */
+   0x00,
+   /* Device Subclass is indicated in the interface descriptors */
+   0x00,
+   /* Mass storage devices do not use class-specific protocols */
+   0x00,
+   /* Max packet size */
+   APP_CONTROL_MAX_PKT_SIZE,
+   /* Vendor ID */
+   USB_uint_16_low(0x1286), USB_uint_16_high(0x1286),
+   /* Product ID */
+   USB_uint_16_low(0x1), USB_uint_16_high(0x1),
+   /* BCD Device version */
+   USB_uint_16_low(0x0002), USB_uint_16_high(0x0002),
+   /* Manufacturer string index */
+   0x1,
+   /* Product string index */
+   0x2,
+   /* Serial number string index */
+   0x6,
+   /* Number of configurations available */
+   0x1
+};
+
+/* USB 2.0 specific descriptor */
+#define DEVICE_QUALIFIER_DESCRIPTOR_SIZE 10
+static const uint_8  DevQualifierDescData[DEVICE_QUALIFIER_DESCRIPTOR_SIZE] =
+{
+   DEVICE_QUALIFIER_DESCRIPTOR_SIZE,  /* bLength Length of this descriptor */
+   6,                         /* bDescType This is a DEVICE Qualifier descr */
+   0,2,                       /* bcdUSB USB revision 2.0 */
+   0,                         /* bDeviceClass */
+   0,                         /* bDeviceSubClass */
+   0,                         /* bDeviceProtocol */
+   APP_CONTROL_MAX_PKT_SIZE,  /* bMaxPacketSize0 */
+   0x01,                      /* bNumConfigurations */
+   0
+};
+
+#define CONFIG_DESC_NUM_INTERFACES  (4)
+/* This must be counted manually and updated with the descriptor */
+/* 1*Config(9) + 1*Interface(9) + 2*Endpoint(7) = 32 bytes */
+#define CONFIG_DESC_SIZE            (32)
+
+/**************************************************************
+we declare the config desc as USB_Uncached because this descriptor
+is updated on the fly for max packet size during enumeration. Making
+it uncached ensures that main memory is updated whenever this
+descriptor pointer is used.
+**************************************************************/
+static const uint_8 ConfigDescData[CONFIG_DESC_SIZE] =
+{
+   /* Configuration Descriptor - always 9 bytes */
+   9,
+   /* "Configuration" type of descriptor */
+   2,
+   /* Total length of the Configuration descriptor */
+   USB_uint_16_low(CONFIG_DESC_SIZE), 
+   USB_uint_16_high(CONFIG_DESC_SIZE),
+   /* NumInterfaces */
+   1,
+   /* Configuration Value */
+   1,
+   /* Configuration Description String Index*/
+   4,
+   /* Attributes.  Self-powered. */
+   0xc0,
+   /* Current draw from bus */
+   0,
+   /* Interface 0 Descriptor - always 9 bytes */
+   9,
+   /* "Interface" type of descriptor */
+   4,
+   /* Number of this interface */
+   MASS_STORAGE_INTERFACE,
+   /* Alternate Setting */
+   0,
+   /* Number of endpoints on this interface */
+   2,
+   /* Interface Class */
+   0x08,
+   /* Interface Subclass: SCSI transparent command set */
+   0x06,
+   /* Interface Protocol: Bulk only protocol */
+   0x50,
+   /* Interface Description String Index */
+   0,
+   /* Endpoint 1 (Bulk In Endpoint), Interface 0 Descriptor - always 7 bytes*/
+   7,
+   /* "Endpoint" type of descriptor */
+   5,
+   /*
+   ** Endpoint address.  The low nibble contains the endpoint number and the
+   ** high bit indicates TX(1) or RX(0).
+   */
+   ((ARC_USB_SEND<<7) | DISK_IN_EP_NO) /*0x81*/,
+   /* Attributes.  0=Control 1=Isochronous 2=Bulk 3=Interrupt */
+   DISK_IN_EP_TYPE,
+   /* Max Packet Size for this endpoint */
+   USB_uint_16_low(DISK_FS_MAX_PACKET_SIZE), 
+   USB_uint_16_high(DISK_FS_MAX_PACKET_SIZE),
+   /* Polling Interval (ms) */
+   0,
+   /* Endpoint 2 (Bulk Out Endpoint), Interface 0 Descriptor - always 7 bytes*/
+   7,
+   /* "Endpoint" type of descriptor */
+   5,
+   /*
+   ** Endpoint address.  The low nibble contains the endpoint number and the
+   ** high bit indicates TX(1) or RX(0).
+   */
+   ((ARC_USB_RECV<<7) | DISK_OUT_EP_NO), /*0x02*/
+   /* Attributes.  0=Control 1=Isochronous 2=Bulk 3=Interrupt */
+   DISK_OUT_EP_TYPE,
+   /* Max Packet Size for this endpoint */
+   USB_uint_16_low(DISK_FS_MAX_PACKET_SIZE), 
+   USB_uint_16_high(DISK_FS_MAX_PACKET_SIZE),
+   /* Polling Interval (ms) */
+   0
+};
+
+#define OTHER_SPEED_CONFIG_DESC_SIZE  CONFIG_DESC_SIZE
+static const uint_8  other_speed_config_data[CONFIG_DESC_SIZE] =
+{
+   9,                         /* bLength Length of this descriptor */
+   7,                         /* bDescType This is a Other speed config descr */
+   USB_uint_16_low(OTHER_SPEED_CONFIG_DESC_SIZE), 
+   USB_uint_16_high(OTHER_SPEED_CONFIG_DESC_SIZE),
+   1,
+   1,
+   4,
+   0xc0,
+   0,
+   /* Interface 0 Descriptor - always 9 bytes */
+   9,
+   /* "Interface" type of descriptor */
+   4,
+   /* Number of this interface */
+   MASS_STORAGE_INTERFACE,
+   /* Alternate Setting */
+   0,
+   /* Number of endpoints on this interface */
+   2,
+   /* Interface Class */
+   0x08,
+   /* Interface Subclass: SCSI transparent command set */
+   0x06,
+   /* Interface Protocol: Bulk only protocol */
+   0x50,
+   /* Interface Description String Index */
+   0,
+   /* Endpoint 1 (Bulk In Endpoint), Interface 0 Descriptor - always 7 bytes*/
+   7,
+   /* "Endpoint" type of descriptor */
+   5,
+   /*
+   ** Endpoint address.  The low nibble contains the endpoint number and the
+   ** high bit indicates TX(1) or RX(0).
+   */
+   ((ARC_USB_SEND<<7) | DISK_IN_EP_NO), /*0x81*/
+   /* Attributes.  0=Control 1=Isochronous 2=Bulk 3=Interrupt */
+   DISK_IN_EP_TYPE,
+   /* Max Packet Size for this endpoint */
+   USB_uint_16_low(DISK_HS_MAX_PACKET_SIZE), 
+   USB_uint_16_high(DISK_HS_MAX_PACKET_SIZE),
+   /* Polling Interval (ms) */
+   0,
+   /* Endpoint 2 (Bulk Out Endpoint), Interface 0 Descriptor - always 7 bytes*/
+   7,
+   /* "Endpoint" type of descriptor */
+   5,
+   /*
+   ** Endpoint address.  The low nibble contains the endpoint number and the
+   ** high bit indicates TX(1) or RX(0).
+   */
+   ((ARC_USB_RECV<<7) | DISK_OUT_EP_NO), /*0x02*/
+
+   /* Attributes.  0=Control 1=Isochronous 2=Bulk 3=Interrupt */
+   DISK_OUT_EP_TYPE,
+   /* Max Packet Size for this endpoint */
+   USB_uint_16_low(DISK_HS_MAX_PACKET_SIZE), 
+   USB_uint_16_high(DISK_HS_MAX_PACKET_SIZE),
+   /* Polling Interval (ms) */
+   0
+};
+
+static uint_8 USB_IF_ALT[4] = { 0, 0, 0, 0};
+
+/* number of strings in the table not including 0 or n. */
+static const uint_8 USB_STR_NUM = 7;
+
+/*
+** if the number of strings changes, look for USB_STR_0 everywhere and make 
+** the obvious changes.  It should be found in 3 places.
+*/
+
+static uint_16 USB_STR_0[ 2] = {(0x300 + sizeof(USB_STR_0)),(0x0409)};
+static uint_16 USB_STR_1[26] = {(0x300 + sizeof(USB_STR_1)),
+      'M','a','r','v','e','l','l',' ','S','e','m','i','c','o','n','d','u','c','t','o','r',' ','L','t','d'};       
+static uint_16 USB_STR_2[28] = {(0x300 + sizeof(USB_STR_2)),
+      'M','A','R','V','E','L','L',' ','M','a','s','s',' ','S','t','o','r','a','g','e',' ',\
+      'D','e','v','i','c','e'};
+static uint_16 USB_STR_3[ 5] = {(0x300 + sizeof(USB_STR_3)),
+      'B','E','T','A'};
+static uint_16 USB_STR_4[ 4] = {(0x300 + sizeof(USB_STR_4)),
+      '#','0','2'};
+static uint_16 USB_STR_5[ 4] = {(0x300 + sizeof(USB_STR_5)),
+      '_','A','1'};
+      /* Serial number has to be at least 12 bytes */
+static uint_16 USB_STR_6[ 13] = {(0x300 + sizeof(USB_STR_6)),
+      '0','0','0','0','0','0','0','0','0','0','0','1'};     
+static uint_16 USB_STR_7[15] = {(0x300 + sizeof(USB_STR_7)),
+      'Y','o','u','r',' ','n','a','m','e',' ','h','e','r','e'};
+static uint_16 USB_STR_n[17] = {(0x300 + sizeof(USB_STR_n)),
+      'B','A','D',' ','S','T','R','I','N','G',' ','I','n','d','e','x'};
+
+#define USB_STRING_ARRAY_SIZE  9
+static uint_8_ptr USB_STRING_DESC[USB_STRING_ARRAY_SIZE] =
+{
+   (uint_8_ptr)((pointer)USB_STR_0),
+   (uint_8_ptr)((pointer)USB_STR_1),
+   (uint_8_ptr)((pointer)USB_STR_2),
+   (uint_8_ptr)((pointer)USB_STR_3),
+   (uint_8_ptr)((pointer)USB_STR_4),
+   (uint_8_ptr)((pointer)USB_STR_5),
+   (uint_8_ptr)((pointer)USB_STR_6),
+   (uint_8_ptr)((pointer)USB_STR_7),
+   (uint_8_ptr)((pointer)USB_STR_n)
+};
+
+/*****************************************************************
+MASS STORAGE SPECIFIC GLOBALS
+*****************************************************************/
+
+static const DISK_DEVICE_INFO device_information_data = 
+{
+   0, 0x80, 0, 0x01, 0x1F, 
+   /* Reserved */
+   {0, 0, 0},
+   /* Vendor information: "MARVELL  " */
+   {0x4D, 0x41, 0x52, 0x56, 0x45, 0x4C, 0x4C, 0x20,},
+   /* Product information: "Disk            " */
+   {0x44, 0x69, 0x73, 0x6B, 0x20, 0x20, 0x20, 0x20,
+   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, 
+   /* Product Revision level: "Demo" */
+   {0x44, 0x65, 0x6D, 0x6F}
+}; 
+
+static const DISK_READ_CAPACITY read_capacity = 
+{
+   /* Data for the capacity */
+   {
+      0x00, 0x00, USB_uint_16_high(TOTAL_LOGICAL_ADDRESS_BLOCKS-14), 
+      USB_uint_16_low(TOTAL_LOGICAL_ADDRESS_BLOCKS-14)
+   }, 
+   {
+      0x00, 0x00, USB_uint_16_high(LENGTH_OF_EACH_LAB), 
+      USB_uint_16_low(LENGTH_OF_EACH_LAB)
+   }
+};
+
+static const uint_8 BOOT_SECTOR_AREA[512] = 
+{
+   /* Block 0 is the boot sector. Following is the data in the boot sector */
+   /* 80x86 "short: jump instruction, indicating that the disk is formatted */
+    0xEB, 
+    /* 8-bit displacement */
+    0x3C, 
+    /* NOP OPCode */
+    0x90, 
+    /* 8-bytes for OEM identification: "ARC 4.3 " */
+    0x41, 0x52, 0x43, 0x20, 0x34, 0x2E, 0x33, 0x20, 
+    /* bytes/sector: 512 bytes (0x0200) */
+    0x00, 0x02, 
+    /* Sectors/allocation unit */
+    0x01,
+    /* Reserved sectors: 0x0001 */
+    0x01, 0x00, 
+    /* Number of File Allocation Tables (FATs): 2 */
+    0x02,
+    /* Number of root directory entries */
+    0x00, 0x02, 
+    /* Total Small sectors in logical volume */
+    USB_uint_16_low(TOTAL_LOGICAL_ADDRESS_BLOCKS), 
+    USB_uint_16_high(TOTAL_LOGICAL_ADDRESS_BLOCKS),
+    /* Media descriptor byte: 0xF8: Fixed disk */
+    0xF8,
+    /* Sectors/FAT: 3 (Each FAT starts at a new sector) */
+    0x80, 0x00, 
+    /* Sectors/track: 9 */
+    0x09, 0x00, 
+    /* Number of heads */
+    0x02, 0x00, 
+    /* Number of hidden sectors: 0 */
+    0x00, 0x00, 0x00, 0x00, 
+    /* Total Large sectors in logical volume */
+    0x00, 0x00, 0x00, 0x00, 
+    /* Physical drive number */
+    0x00, 
+    /* Reserved */
+    0x00, 
+    /* Extended boot signature record: 0x29 */
+    0x29,
+    /* 32-bit binary volume ID */
+    0x01, 0x02, 0x03, 0x04, 
+    /* Volume label */
+    0x53, 0x54, 0x55, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    /* Reserved FAT-16*/
+    0x46, 0x41, 0x54, 0x31, 0x36, 0x00, 0x00, 0x00,
+    /* Bootstrap */
+    0x33, 0xC0, 0x8E, 0xD0, 0xBC, 0x00, 0x7C, 0xFC, 0xE8, 0x45, 0x00, 
+    /* String: \r\nNon-System disk\r\nPress any key to reboot\r\n" */
+    0x0D, 0x0A, 0x4E, 0x6F, 0x6E, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65,
+    0x6D, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x0D, 0x0A, 0x50, 0x72, 0x65, 
+    0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 
+    0x74, 0x6F, 0x20, 0x72, 0x65, 0x62, 0x6F, 0x6F, 0x74, 0x0D, 0x0A, 
+    0x5E, 0xEB, 0x02, 0xCD, 0x10, 0xB4, 0x0E, 0xBB, 0x07, 0x00, 0x2E, 
+    0xAC, 0x84, 0xC0, 0x75, 0xF3, 0x98, 0xCD, 0x16, 0xCD, 0x19, 0xEB, 
+    0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    /* Partition descriptors */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
+};
+
+
+static const uint_8 FAT16_SPECIAL_BYTES[3] = 
+{
+   /* FAT ID: Same as Media descriptor */
+   0xF8, 0xFF, 0xFF
+};
+
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9GetDescription
+* Returned Value : None
+* Comments       :
+*     Chapter 9 GetDescription command
+*     The Device Request can ask for Device/Config/string/interface/endpoint
+*     descriptors (via wValue). We then post an IN response to return the
+*     requested descriptor.
+*     And then wait for the OUT which terminates the control transfer.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9GetDescription
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+    uint_32             max_pkt_size;
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d, value=0x%x, length=%d\n", 
+                __FUNCTION__, (int)setup, setup_ptr->VALUE, setup_ptr->LENGTH);
+
+    if (setup) 
+    {
+        /* Load the appropriate string depending on the descriptor requested.*/
+        switch (setup_ptr->VALUE & 0xFF00) 
+        {
+            case 0x0100:
+                _usb_device_send_data(handle, 0, pDiskCtrl->DevDesc,
+                    MIN(setup_ptr->LENGTH, DEVICE_DESCRIPTOR_SIZE));
+                break;
+
+            case 0x0200:
+                /* Set the Max Packet Size in the config and other speed config */
+                if(pDiskCtrl->speed == ARC_USB_SPEED_HIGH) 
+                {
+                    max_pkt_size = pDiskCtrl->hsMaxPktSize;
+                } 
+                else 
+                {
+                    max_pkt_size = pDiskCtrl->fsMaxPktSize;
+                } /* Endif */
+        
+                *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_IN_TYPE_OFFSET) = (uint_8)pDiskCtrl->inEpType;
+
+                *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET) = 
+                                                USB_uint_16_low(max_pkt_size);
+                *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET+1) = 
+                                                USB_uint_16_high(max_pkt_size);
+
+                *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_OUT_TYPE_OFFSET) = (uint_8)pDiskCtrl->outEpType;
+
+                *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET) = 
+                                                USB_uint_16_low(max_pkt_size);
+                *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET+1) = 
+                                                USB_uint_16_high(max_pkt_size);
+
+                _usb_device_send_data(handle, 0, pDiskCtrl->ConfigDesc,
+                            MIN(setup_ptr->LENGTH, CONFIG_DESC_SIZE));
+                break;
+
+            case 0x0300:
+                if ((setup_ptr->VALUE & 0x00FF) > USB_STR_NUM) {
+                    _usb_device_send_data(handle, 0, USB_STRING_DESC[USB_STR_NUM+1],
+                            MIN(setup_ptr->LENGTH, USB_STRING_DESC[USB_STR_NUM+1][0]));
+                } 
+                else 
+                {
+                    _usb_device_send_data(handle, 0, USB_STRING_DESC[setup_ptr->VALUE & 0x00FF],
+                            MIN(setup_ptr->LENGTH, USB_STRING_DESC[setup_ptr->VALUE & 0x00FF][0]));
+                } /* Endif */      
+                break;
+            
+            case 0x600:
+                _usb_device_send_data(handle, 0, (uint_8_ptr)pDiskCtrl->DevQualifierDesc, 
+                        MIN(setup_ptr->LENGTH, DEVICE_QUALIFIER_DESCRIPTOR_SIZE));
+                break;
+            
+            case 0x700:
+                if(pDiskCtrl->speed == ARC_USB_SPEED_HIGH) 
+                {
+                    max_pkt_size = pDiskCtrl->fsMaxPktSize;
+                } 
+                else 
+                {
+                    max_pkt_size = pDiskCtrl->hsMaxPktSize;
+                } /* Endif */
+            
+                *(pDiskCtrl->other_speed_config + CFG_DESC_EP_IN_TYPE_OFFSET) = (uint_8)pDiskCtrl->inEpType;
+
+                *(pDiskCtrl->other_speed_config + CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET) = 
+                    USB_uint_16_low(max_pkt_size);
+                *(pDiskCtrl->other_speed_config + CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET+1) = 
+                    USB_uint_16_high(max_pkt_size);
+
+                *(pDiskCtrl->other_speed_config + CFG_DESC_EP_OUT_TYPE_OFFSET) = (uint_8)pDiskCtrl->outEpType;
+
+                *(pDiskCtrl->other_speed_config + CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET) = 
+                    USB_uint_16_low(max_pkt_size);
+                *(pDiskCtrl->other_speed_config + CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET+1) = 
+                    USB_uint_16_high(max_pkt_size);
+            
+                _usb_device_send_data(handle, 0, (uint_8_ptr)pDiskCtrl->other_speed_config, 
+                            MIN(setup_ptr->LENGTH, OTHER_SPEED_CONFIG_DESC_SIZE));
+               
+                break;
+
+            default:
+                USB_printf("usbDisk_%d, %s: Unexpected VALUE=0x%04x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE);
+                _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+                return;
+        } /* Endswitch */
+        /* status phase */
+        _usb_device_recv_data(handle, 0, NULL, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SetDescription
+* Returned Value : None
+* Comments       :
+*     Chapter 9 SetDescription command
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9SetDescription
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+   USB_printf("usbDisk_%d, %s: setup=%d\n", 
+        _usb_device_get_dev_num(handle), __FUNCTION__, (int)setup);
+   _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+
+   return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9GetConfig
+* Returned Value : None
+* Comments       :
+*     Chapter 9 GetConfig command
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9GetConfig
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    uint_16             current_config;
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d\n", __FUNCTION__, (int)setup);
+
+    /* Return the currently selected configuration */
+    if (setup)
+    { 
+        _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG,
+                                &current_config);
+        *pDiskCtrl->epTemp_buf = (current_config & 0xFF);      
+        _usb_device_send_data(handle, 0, pDiskCtrl->epTemp_buf, sizeof(uint_8));
+        /* status phase */
+        _usb_device_recv_data(handle, 0, NULL, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SetConfig
+* Returned Value : None
+* Comments       :
+*     Chapter 9 SetConfig command
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9SetConfig
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+    uint_16             usb_state;
+    uint_32             max_pkt_size;
+   
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d, value=0x%x\n", 
+                    __FUNCTION__, (int)setup, setup_ptr->VALUE);
+
+    if (setup) 
+    {
+        if ((setup_ptr->VALUE & 0x00FF) > 1) 
+        {
+            /* generate stall */
+            USB_printf("usbDisk_%d, %s: Wrong VALUE=0x%04x\n", 
+                    _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE);
+            _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+            return;
+        } /* Endif */
+
+        /* 0 indicates return to unconfigured state */
+        if ((setup_ptr->VALUE & 0x00FF) == 0) 
+        {
+            _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state);
+            if( (usb_state == ARC_USB_STATE_CONFIG) || 
+                (usb_state == ARC_USB_STATE_ADDRESS) ) 
+            {
+                /* clear the currently selected config value */
+                _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, 0);
+                _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE,
+                                                    ARC_USB_STATE_ADDRESS);
+                /* status phase */      
+                _usb_device_send_data(handle, 0, 0, 0);
+            } 
+            else 
+            {
+                USB_printf("usbDisk_%d, %s: Wrong usb_state=%d\n", 
+                    _usb_device_get_dev_num(handle), __FUNCTION__, usb_state);
+                _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+            } /* Endif */
+            return;
+        } /* Endif */
+
+        /*
+        ** If the configuration value (setup_ptr->VALUE & 0x00FF) differs
+        ** from the current configuration value, then endpoints must be
+        ** reconfigured to match the new device configuration
+        */
+        _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG,
+                                                        &usb_state);
+
+        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk: Set configuration: old=%d, new=%d\n", 
+                    usb_state, setup_ptr->VALUE & 0x00FF);
+
+        if (usb_state != (setup_ptr->VALUE & 0x00FF)) 
+        {
+            /* Reconfigure endpoints here */
+            switch (setup_ptr->VALUE & 0x00FF) 
+            {
+                default:
+                break;
+            } /* Endswitch */
+
+            _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG,
+                                    setup_ptr->VALUE & 0x00FF);
+        } /* Endif */
+
+        if (pDiskCtrl->speed == ARC_USB_SPEED_HIGH) 
+        {
+            max_pkt_size = pDiskCtrl->hsMaxPktSize;
+        } 
+        else 
+        {
+            max_pkt_size = pDiskCtrl->fsMaxPktSize;
+        } /* Endif */
+      
+        _usb_device_init_endpoint(handle, pDiskCtrl->outEpNo, max_pkt_size,
+                ARC_USB_RECV, ARC_USB_BULK_ENDPOINT, ARC_USB_DEVICE_DONT_ZERO_TERMINATE);
+        _usb_device_init_endpoint(handle, pDiskCtrl->inEpNo, max_pkt_size,
+                ARC_USB_SEND, ARC_USB_BULK_ENDPOINT, ARC_USB_DEVICE_DONT_ZERO_TERMINATE);
+    
+        if (_usb_device_get_transfer_status(handle, pDiskCtrl->outEpNo, ARC_USB_RECV) == USB_OK) 
+        {
+            _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+        } /* Endif */      
+      
+        pDiskCtrl->TEST_ENABLED = TRUE;
+
+        _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE,
+                                ARC_USB_STATE_CONFIG);
+        /* status phase */
+        _usb_device_send_data(handle, 0, 0, 0);
+
+        USB_printf("USB %s speed disk: config = %d\n", 
+            (pDiskCtrl->speed == ARC_USB_SPEED_HIGH) ? "High" : "Full", 
+            setup_ptr->VALUE & 0x00FF);
+
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9GetInterface
+* Returned Value : None
+* Comments       :
+*     Chapter 9 GetInterface command
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9GetInterface
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    uint_16 usb_state;
+   
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d\n", __FUNCTION__, (int)setup);
+
+    _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state);
+    if (usb_state != ARC_USB_STATE_CONFIG) 
+    {
+        USB_printf("usbDisk_%d, %s: Wrong usb_state=%d\n", 
+                    _usb_device_get_dev_num(handle), __FUNCTION__, usb_state);
+        _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+        return;
+    } /* Endif */
+
+    if (setup) 
+    {
+        _usb_device_send_data(handle, 0, &USB_IF_ALT[setup_ptr->INDEX & 0x00FF],
+                            MIN(setup_ptr->LENGTH, sizeof(uint_8)));
+        /* status phase */      
+        _usb_device_recv_data(handle, 0, NULL, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SetInterface
+* Returned Value : None
+* Comments       :
+*     Chapter 9 SetInterface command
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9SetInterface
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d\n", __FUNCTION__, (int)setup);
+
+    if (setup) 
+    {
+        if (setup_ptr->REQUESTTYPE != 0x01) 
+        {
+            USB_printf("usbDisk_%d, %s: Wrong REQUESTTYPE=0x%02x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, 
+                        setup_ptr->REQUESTTYPE);
+            _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+            return;
+        } /* Endif */
+
+        /*
+        ** If the alternate value (setup_ptr->VALUE & 0x00FF) differs
+        ** from the current alternate value for the specified interface,
+        ** then endpoints must be reconfigured to match the new alternate
+        */
+        if (USB_IF_ALT[setup_ptr->INDEX & 0x00FF]
+                        != (setup_ptr->VALUE & 0x00FF))
+        {
+            USB_IF_ALT[setup_ptr->INDEX & 0x00FF] = (setup_ptr->VALUE & 0x00FF);
+            /* Reconfigure endpoints here. */
+         
+        } /* Endif */
+
+        /* status phase */
+        _usb_device_send_data(handle, 0, 0, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SynchFrame
+* Returned Value : 
+* Comments       :
+*     Chapter 9 SynchFrame command
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9SynchFrame
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+
+    uint_16             usbStatus;
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d\n", 
+                                        __FUNCTION__, (int)setup);
+
+    if (setup) 
+    {
+        if (setup_ptr->REQUESTTYPE != (REQ_RECIP_ENDPOINT | REQ_TYPE_STANDARD | REQ_DIR_OUT) )
+        {
+            USB_printf("usbDisk_%d, %s: Wrong REQUESTTYPE=0x%02x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, 
+                        setup_ptr->REQUESTTYPE);
+            _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+            return;
+        } /* Endif */
+
+        if ((setup_ptr->INDEX & 0x00FF) >=
+            pDiskCtrl->ConfigDesc[CONFIG_DESC_NUM_INTERFACES])
+        {
+            USB_printf("usbDisk_%d, %s: Wrong INDEX=0x%02x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->INDEX);
+            _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV);
+            return;
+        } /* Endif */
+
+        _usb_device_get_status(handle, ARC_USB_STATUS_SOF_COUNT, &usbStatus);
+        pDiskCtrl->epTemp_buf[0] = USB_uint_16_low(usbStatus);
+        pDiskCtrl->epTemp_buf[1] = USB_uint_16_high(usbStatus);
+        _usb_device_send_data(handle, 0, pDiskCtrl->epTemp_buf, MIN(setup_ptr->LENGTH, sizeof(uint_16)));
+        /* status phase */      
+        _usb_device_recv_data(handle, 0, NULL, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9Class
+* Returned Value : 
+* Comments       :
+*     Chapter 9 Class specific request
+*     See section 9.4.11 (page 195) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9Class
+   (
+      _usb_device_handle handle,
+      boolean setup,
+      uint_8  direction,
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+   
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_CLASS, 
+                "usbDisk %s: setup=%d, request=0x%x, value=%d, index=%d, size=%d\n", 
+                __FUNCTION__, (int)setup, setup_ptr->REQUEST,
+                setup_ptr->VALUE, setup_ptr->INDEX, setup_ptr->LENGTH);
+
+    if (setup) 
+    {
+        switch (setup_ptr->REQUEST) 
+        {
+            case 0xFF:
+                /* Bulk-Only Mass Storage Reset: Ready the device for the next 
+                ** CBW from the host 
+                */
+                if ((setup_ptr->VALUE != 0) || 
+                    (setup_ptr->INDEX != MASS_STORAGE_INTERFACE) ||
+                    (setup_ptr->LENGTH != 0)) 
+                {
+                    USB_printf("usbDisk_%d, %s: Wrong Setup: VALUE=%d, INDEX=%d, LENGTH=%d\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE, 
+                        setup_ptr->INDEX, setup_ptr->LENGTH);
+
+                    _usb_device_stall_endpoint(handle, 0, 0);
+                } 
+                else 
+                { /* Body */
+                    pDiskCtrl->CBW_PROCESSED = FALSE;
+                    pDiskCtrl->ZERO_TERMINATE = FALSE;
+                    _usb_device_cancel_transfer(handle, pDiskCtrl->outEpNo, ARC_USB_RECV);
+                    _usb_device_cancel_transfer(handle, pDiskCtrl->inEpNo, ARC_USB_SEND);
+               
+                    /* unstall bulk endpoint */
+                    _usb_device_unstall_endpoint(handle, pDiskCtrl->outEpNo, ARC_USB_RECV);
+                    _usb_device_unstall_endpoint(handle, pDiskCtrl->inEpNo, ARC_USB_SEND);
+               
+                    _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+                    /* send zero packet to control pipe */
+                    _usb_device_send_data(handle, 0, NULL, 0);
+                } /* Endbody */
+                break;
+
+            case 0xFE:
+                /* For Get Max LUN use any of these responses*/
+                if (setup_ptr->LENGTH == 0) 
+                { /* Body */
+
+                    USB_printf("usbDisk_%d, %s: Wrong Length: LENGTH=%d\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->LENGTH);
+
+                    _usb_device_stall_endpoint(handle, 0, 0);
+                } 
+                else
+                {
+                    if ((setup_ptr->VALUE != 0) ||
+                        (setup_ptr->INDEX != MASS_STORAGE_INTERFACE) ||
+                        (setup_ptr->LENGTH != 1)) 
+                    { /* Body */
+                        USB_printf("usbDisk_%d, %s: Wrong Setup: VALUE=%d, INDEX=%d, LENGTH=%d\n", 
+                                    _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE, 
+                                    setup_ptr->INDEX, setup_ptr->LENGTH);
+                        _usb_device_stall_endpoint(handle, 0, 0);
+                    } 
+                    else 
+                    { /* Body */
+                        /* Send Max LUN = 0 to the the control pipe */
+                        *pDiskCtrl->epTemp_buf = 0;
+                        _usb_device_send_data(handle, 0, pDiskCtrl->epTemp_buf, 1);
+                        /* status phase */
+                        _usb_device_recv_data(handle, 0, 0, 0);
+                    } /* Endbody */     
+                }
+                break;
+
+            default :
+                USB_printf("usbDisk_%d, %s: Wrong REQUEST=0x%02x\n", 
+                    _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->REQUEST);
+                _usb_device_stall_endpoint(handle, 0, 0);
+                return;
+        } /* EndSwitch */
+    } 
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : service_ep0
+* Returned Value : None
+* Comments       :
+*     Called upon a completed endpoint 0 (USB 1.1 Chapter 9) transfer
+* 
+*END*--------------------------------------------------------------------*/
+static void service_ep0
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+
+      /* [IN] request type as registered */
+      uint_8               type,
+
+      /* [IN] Is it a setup packet? */
+      boolean              setup,
+      
+      /* [IN] Direction of the transfer.  Is it transmit? */
+      uint_8               direction,
+      
+      /* [IN] Pointer to the data buffer */
+      uint_8_ptr           buffer,
+      
+      /* [IN] Length of the transfer */
+      uint_32              length,
+      
+      /* [IN] Error, if any */
+      uint_8               error
+            
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+    SETUP_STRUCT*       pSetupPacket = &pDiskCtrl->local_setup_packet;
+
+   if (setup) 
+   {
+      _usb_device_read_setup_data(handle, 0, (uint_8_ptr)pSetupPacket);
+        pSetupPacket->VALUE = USB_16BIT_LE(pSetupPacket->VALUE);
+        pSetupPacket->INDEX = USB_16BIT_LE(pSetupPacket->INDEX);
+        pSetupPacket->LENGTH = USB_16BIT_LE(pSetupPacket->LENGTH);
+   }
+   
+   ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_EP0,
+              "disk %s: setup=%s, dir=%s, pBuf=0x%x, length=%d, reqType=0x%x, req=0x%x\n",
+                    __FUNCTION__, (setup ? "YES" : "NO"), 
+                    (direction == ARC_USB_RECV) ? "RECV" : "SEND", 
+                    (unsigned)buffer, (int)length, pSetupPacket->REQUESTTYPE, 
+                    pSetupPacket->REQUEST);
+
+   switch (pSetupPacket->REQUESTTYPE & REQ_TYPE_MASK) 
+   {
+      case REQ_TYPE_STANDARD:
+         switch (pSetupPacket->REQUEST) 
+         {
+            case REQ_GET_STATUS:
+               mvUsbCh9GetStatus(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_CLEAR_FEATURE:
+               mvUsbCh9ClearFeature(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_SET_FEATURE:
+               mvUsbCh9SetFeature(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_SET_ADDRESS:
+               mvUsbCh9SetAddress(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_GET_DESCRIPTOR:
+               ch9GetDescription(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_SET_DESCRIPTOR:
+               ch9SetDescription(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_GET_CONFIGURATION:
+               ch9GetConfig(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_SET_CONFIGURATION:
+               ch9SetConfig(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_GET_INTERFACE:
+               ch9GetInterface(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_SET_INTERFACE:
+               ch9SetInterface(handle, setup, pSetupPacket);
+               break;
+
+            case REQ_SYNCH_FRAME:
+               ch9SynchFrame(handle, setup, pSetupPacket);
+               break;
+
+            default:
+                USB_printf("usbDisk_%d, %s: Wrong REQUEST = 0x%02x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, pSetupPacket->REQUEST);
+               _usb_device_stall_endpoint(handle, 0, 0);
+               break;
+
+         } /* Endswitch */
+         
+         break;
+
+      case REQ_TYPE_CLASS:
+         /* class specific request */
+         ch9Class(handle, setup, direction, pSetupPacket);
+         return;
+
+      case REQ_TYPE_VENDOR:
+         /* vendor specific request can be handled here*/
+         USB_printf("usbDisk_%d, %s: Vendor REQUESTTYPE (%d) not supported\n", 
+               _usb_device_get_dev_num(handle), __FUNCTION__, REQ_TYPE_VENDOR);
+         
+         _usb_device_stall_endpoint(handle, 0, 0);
+         break;
+      
+      default:
+         USB_printf("usbDisk_%d, %s: Unexpected REQUESTTYPE = 0x%x\n", 
+                _usb_device_get_dev_num(handle), __FUNCTION__, 
+                pSetupPacket->REQUESTTYPE);
+         
+         _usb_device_stall_endpoint(handle, 0, 0);
+         break;
+         
+   } /* Endswitch */
+   
+   return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _process_inquiry_command
+* Returned Value : None
+* Comments       :
+*     Process a Mass storage class Inquiry command
+* 
+*END*--------------------------------------------------------------------*/
+void _process_inquiry_command
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+            
+      /* [IN] Endpoint number */
+      uint_8               ep_num,
+      
+      /* [IN] Pointer to the data buffer */
+      CBW_STRUCT_PTR       cbw_ptr
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+
+    if (cbw_ptr->DCBWDATALENGTH) 
+    {
+        if (cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) 
+        {      
+            /* Send the device information */
+            _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)&device_information_data, 36);
+        } /* Endif */
+    } /* Endif */
+   
+    /* The actual length will never exceed the DCBWDATALENGTH */            
+    pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH - 36);
+    pDiskCtrl->pCSW->BCSWSTATUS = 0;
+   
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _process_unsupported_command
+* Returned Value : None
+* Comments       :
+*     Responds appropriately to unsupported commands
+* 
+*END*--------------------------------------------------------------------*/
+void _process_unsupported_command
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+            
+      /* [IN] Endpoint number */
+      uint_8               ep_num,
+      
+      /* [IN] Pointer to the data buffer */
+      CBW_STRUCT_PTR       cbw_ptr
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+   
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK, 
+                    "disk unsupported command: BMCBWFLAGS = 0x%02x\n", cbw_ptr->BMCBWFLAGS);
+
+    /* The actual length will never exceed the DCBWDATALENGTH */
+    pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+    pDiskCtrl->pCSW->BCSWSTATUS = 0;
+
+    if (cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) 
+    {      
+        /* Send a zero-length packet */
+        _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)NULL, 0);
+    } 
+    else 
+    {
+        pDiskCtrl->CBW_PROCESSED = FALSE;
+        /* Send the command status information */
+        _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13);
+        _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+    } /* Endif */
+   
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _process_report_capacity
+* Returned Value : None
+* Comments       :
+*     Reports the media capacity as a response to READ CAPACITY Command.
+* 
+*END*--------------------------------------------------------------------*/
+void _process_report_capacity
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+            
+      /* [IN] Endpoint number */
+      uint_8               ep_num,
+      
+      /* [IN] Pointer to the data buffer */
+      CBW_STRUCT_PTR       cbw_ptr
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_CAP, 
+                    "disk read_capacity: BMCBWFLAGS = 0x%02x\n", cbw_ptr->BMCBWFLAGS);
+
+    if (cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) 
+    {      
+        /* Send a zero-length packet */
+        _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pReadCapacity, 8);
+      
+    } /* Endif */
+   
+    /* The actual length will never exceed the DCBWDATALENGTH */            
+    pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+    pDiskCtrl->pCSW->BCSWSTATUS = 0;
+   
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _process_read_command
+* Returned Value : None
+* Comments       :
+*     Sends data as a response to READ Command.
+* 
+*END*--------------------------------------------------------------------*/
+void _process_read_command
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+            
+      /* [IN] Endpoint number */
+      uint_8               ep_num,
+      
+      /* [IN] Pointer to the data buffer */
+      CBW_STRUCT_PTR       cbw_ptr
+   )
+{ /* Body */
+    uint_32             index1 = 0, index2 = 0;
+    uint_32             max_pkt_size, byteSize;
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+
+    if (cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) 
+    {                
+      /* Send a zero-length packet */
+      index1  = ((uint_32)cbw_ptr->CBWCB[4] << 8);
+      index1  |= cbw_ptr->CBWCB[5];
+      index2 = ((uint_32)cbw_ptr->CBWCB[7] << 8);
+      index2 |= (uint_32)cbw_ptr->CBWCB[8];
+
+      ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_READ, 
+                    "disk read: FLAGS=0x%02x, LENGTH=0x%x, index1=0x%x, index2=0x%x\n", 
+                    cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH, index1, index2);
+
+      if(cbw_ptr->CBWCB[0] != 0x3E)
+      {
+          byteSize = index2 * LENGTH_OF_EACH_LAB;
+      }
+      else
+      {
+          byteSize = index2;
+          index2 = (USB_MEM_ALIGN(byteSize, LENGTH_OF_EACH_LAB) / LENGTH_OF_EACH_LAB);
+      }
+
+      /* Check index validities */
+      if( (index1 + index2) >= pDiskCtrl->logicalBlocks)
+      {
+          USB_printf("USB disk read: invalid indexes - addr=%d, size=%d\n",
+                        index1, index2);
+          pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH);
+          pDiskCtrl->pCSW->BCSWSTATUS = 1;
+          /* Send zero size packet */
+          _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)NULL, 0);
+          return;
+      }
+ 
+      if (cbw_ptr->DCBWDATALENGTH == 0) 
+      { /* Body */
+         pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+         pDiskCtrl->pCSW->BCSWSTATUS = 2;
+         pDiskCtrl->CBW_PROCESSED = FALSE;
+         /* Send the command status information */
+         _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13);
+         _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+         return;
+      } 
+      else 
+      { /* Body */
+         pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+         pDiskCtrl->pCSW->BCSWSTATUS = 0;         
+         if (byteSize > cbw_ptr->DCBWDATALENGTH) 
+         { /* Body */
+            byteSize = cbw_ptr->DCBWDATALENGTH;
+            pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH);
+            pDiskCtrl->pCSW->BCSWSTATUS = 2;
+         } 
+         else 
+         {
+            if (byteSize < cbw_ptr->DCBWDATALENGTH) 
+            { /* Body */
+                pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH - index2);
+                if (byteSize > 0) 
+                { /* Body */
+                    if (pDiskCtrl->speed == ARC_USB_SPEED_HIGH) 
+                    {
+                        max_pkt_size = pDiskCtrl->hsMaxPktSize;
+                    } 
+                    else 
+                    {
+                        max_pkt_size = pDiskCtrl->fsMaxPktSize;
+                    }
+
+                    if( (byteSize % max_pkt_size) == 0) 
+                    { /* Body */
+                        /* Need send a zero terminate packet to host */
+                        pDiskCtrl->ZERO_TERMINATE = TRUE;
+                    } /* Endbody */
+                } /* Endbody */  
+            } /* Endbody */
+         }
+
+         _usb_device_send_data(handle, pDiskCtrl->inEpNo, 
+            pDiskCtrl->MASS_STORAGE_DISK + (index1*LENGTH_OF_EACH_LAB), byteSize);
+      } /* Endbody */
+   } 
+   else 
+   { /* Body */
+      USB_printf("disk read incorrect: FLAGS=0x%02x, LENGTH=0x%x\n", 
+                    cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH);
+
+      /* Incorrect but valid CBW */
+      if (cbw_ptr->DCBWDATALENGTH > BUFFERSIZE)
+         byteSize = BUFFERSIZE;
+      else
+         byteSize = cbw_ptr->DCBWDATALENGTH;
+
+      pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH);
+      pDiskCtrl->pCSW->BCSWSTATUS = 2;
+       _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, index2);   
+   } /* Endbody */     
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _process_write_command
+* Returned Value : None
+* Comments       :
+*     Sends data as a response to WRITE Command.
+* 
+*END*--------------------------------------------------------------------*/
+void _process_write_command
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+            
+      /* [IN] Endpoint number */
+      uint_8               ep_num,
+      
+      /* [IN] Pointer to the data buffer */
+      CBW_STRUCT_PTR       cbw_ptr
+   )
+{ /* Body */
+    uint_32             index1 = 0, index2 = 0;
+    uint_32             byteSize;
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+
+    if (!(cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT)) 
+    {
+        index1  = ((uint_32)cbw_ptr->CBWCB[4] << 8);
+        index1  |= cbw_ptr->CBWCB[5];
+        index2 = ((uint_32)cbw_ptr->CBWCB[7] << 8);
+        index2 |= (uint_32)cbw_ptr->CBWCB[8];
+        
+        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_WRITE, 
+                      "disk write: FLAGS=0x%02x, LENGTH=0x%x, index1=0x%x, index2=0x%x\n", 
+                      cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH, index1, index2);
+        
+        if(cbw_ptr->CBWCB[0] != 0x3F)
+        {
+            byteSize = index2 * LENGTH_OF_EACH_LAB;
+        }
+        else
+        {
+            byteSize = index2;
+            index2 = (USB_MEM_ALIGN(byteSize, LENGTH_OF_EACH_LAB) / LENGTH_OF_EACH_LAB);
+        }
+        
+        /* Check index validities */
+        if( (index1 + index2) >= pDiskCtrl->logicalBlocks)
+        {
+            USB_printf("USB disk write: invalid indexes - addr=%d, size=%d\n",
+                          index1, index2);
+            pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+            pDiskCtrl->pCSW->BCSWSTATUS = 1;
+            pDiskCtrl->CBW_PROCESSED = FALSE;
+            /* Send the command status information */
+            _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13);
+            _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+            return;
+        }
+
+        if (cbw_ptr->DCBWDATALENGTH == 0) 
+        { /* Body */
+            /* Zero transfer length */
+            pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+            pDiskCtrl->pCSW->BCSWSTATUS = 2;
+            pDiskCtrl->CBW_PROCESSED = FALSE;
+            
+            /* Send the command status information */
+            _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13);
+            
+            _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+            return;
+        } 
+        else 
+        { /* Body */
+            pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+            pDiskCtrl->pCSW->BCSWSTATUS = 0;
+         
+            if (byteSize < cbw_ptr->DCBWDATALENGTH) 
+            { /* Body */
+                /* The actual length will never exceed the DCBWDATALENGTH */
+                pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH - byteSize);
+                byteSize = cbw_ptr->DCBWDATALENGTH;
+            } 
+            else if (byteSize > cbw_ptr->DCBWDATALENGTH) 
+            { /* Body */
+                pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH);
+                pDiskCtrl->pCSW->BCSWSTATUS = 2;
+                byteSize = cbw_ptr->DCBWDATALENGTH;
+            } /* Endbody */
+            
+            if (_usb_device_get_transfer_status(handle, pDiskCtrl->outEpNo, ARC_USB_RECV) != USB_OK) 
+            {
+                _usb_device_cancel_transfer(handle, ep_num, ARC_USB_RECV);
+            } /* Endif */
+
+            _usb_device_recv_data(handle, pDiskCtrl->outEpNo, 
+                    pDiskCtrl->MASS_STORAGE_DISK + (index1*LENGTH_OF_EACH_LAB), byteSize);
+        }
+    } 
+    else 
+    { /* Body */
+        USB_printf("disk write incorrect: FLAGS=0x%02x, LENGTH=0x%x\n", 
+                    cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH);
+
+        /* Incorrect but valid CBW */
+        pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH);
+        pDiskCtrl->pCSW->BCSWSTATUS = 2;
+        _usb_device_send_data(handle, pDiskCtrl->inEpNo, 0, 0);
+        return;
+    } /* Endbody */
+   
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _process_test_unit_ready
+* Returned Value : None
+* Comments       :
+*     Responds appropriately to unit ready query
+* 
+*END*--------------------------------------------------------------------*/
+void _process_test_unit_ready
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+            
+      /* [IN] Endpoint number */
+      uint_8               ep_num,
+      
+      /* [IN] Pointer to the data buffer */
+      CBW_STRUCT_PTR       cbw_ptr
+   )
+{ /* Body */
+    uint_32             bufSize;
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+   
+    if ((cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) ||
+        (cbw_ptr->DCBWDATALENGTH == 0)) 
+    {
+        /* The actual length will never exceed the DCBWDATALENGTH */
+        pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+        pDiskCtrl->pCSW->BCSWSTATUS = 0;
+   
+        pDiskCtrl->CBW_PROCESSED = FALSE;
+
+        /* Send the command status information */
+        _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13);
+        _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+    } 
+    else 
+    { /* Body */
+      /* Incorrect but valid CBW */
+        if (cbw_ptr->DCBWDATALENGTH > BUFFERSIZE)
+            bufSize = BUFFERSIZE;
+        else
+            bufSize = cbw_ptr->DCBWDATALENGTH;
+
+        pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH);
+        pDiskCtrl->pCSW->BCSWSTATUS = 1;
+        _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, bufSize);
+    } /* Endbody */
+   
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _process_prevent_allow_medium_removal
+* Returned Value : None
+* Comments       :
+*     Responds appropriately to unit ready query
+* 
+*END*--------------------------------------------------------------------*/
+void _process_prevent_allow_medium_removal
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+            
+      /* [IN] Endpoint number */
+      uint_8               ep_num,
+      
+      /* [IN] Pointer to the data buffer */
+      CBW_STRUCT_PTR       cbw_ptr
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+
+    /* The actual length will never exceed the DCBWDATALENGTH */
+    pDiskCtrl->pCSW->DCSWDATARESIDUE = 0;
+    pDiskCtrl->pCSW->BCSWSTATUS = 0;
+   
+    pDiskCtrl->CBW_PROCESSED = FALSE;
+
+    /* Send the command status information */
+    _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13);
+    _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+   
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : _process_mass_storage_command
+* Returned Value : None
+* Comments       :
+*     Process a Mass storage class command
+* 
+*END*--------------------------------------------------------------------*/
+void _process_mass_storage_command
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+            
+      /* [IN] Endpoint number */
+      uint_8               ep_num,
+      
+      /* [IN] Pointer to the data buffer */
+      CBW_STRUCT_PTR       cbw_ptr
+   )
+{ /* Body */
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK, 
+                    "disk command: CBWCB[0]=0x%02x, FLAGS=0x%02x, LENGTH=0x%x\n", 
+                    cbw_ptr->CBWCB[0], cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH);
+
+   switch (cbw_ptr->CBWCB[0]) 
+   {
+      case 0x00: /* Request the device to report if it is ready */
+         _process_test_unit_ready(handle, ep_num, cbw_ptr);
+         break;
+
+      case 0x12: /* Inquity command. Get device information */
+         _process_inquiry_command(handle, ep_num, cbw_ptr);
+         break;
+
+      case 0x1A:
+         _process_unsupported_command(handle, ep_num, cbw_ptr);
+         break;
+
+      case 0x1E: /* Prevent or allow the removal of media from a removable media device */
+         _process_prevent_allow_medium_removal(handle, ep_num, cbw_ptr);
+         break;
+
+      case 0x23: /* Read Format Capacities. Report current media capacity and 
+                 ** formattable capacities supported by media 
+                  */
+         /* We bahave like already installed medium. No need to send any data */
+         _process_unsupported_command(handle, ep_num, cbw_ptr);
+         break;
+
+      case 0x25: /* Report current media capacity */
+         _process_report_capacity(handle, ep_num, cbw_ptr);
+         break;
+
+      case 0x28: /* Read (10) Transfer binary data from media to the host */
+      case 0x3E:
+          _process_read_command(handle, ep_num, cbw_ptr);
+         break;
+
+      case 0x2A: /* Write (10) Transfer binary data from the host to the media */
+      case 0x3F:
+         _process_write_command(handle, ep_num, cbw_ptr);
+         break;
+
+      case 0x01: /* Position a head of the drive to zero track */
+      case 0x03: /* Transfer status sense data to the host */
+      case 0x04: /* Format unformatted media */
+      case 0x1B: /* Request a request a removable-media device to load or 
+                 ** unload its media 
+                 */
+      case 0x1D: /* Perform a hard reset and execute diagnostics */
+      case 0x2B: /* Seek the device to a specified address */
+      case 0x2E: /* Transfer binary data from the host to the media and 
+                 ** verify data 
+                 */
+      case 0x2F: /* Verify data on the media */
+      case 0x55: /* Allow the host to set parameters in a peripheral */
+      case 0x5A: /* Report parameters to the host */
+      case 0xA8: /* Read (12) Transfer binary data from the media to the host */
+      case 0xAA: /* Write (12) Transfer binary data from the host to the 
+                 ** media 
+                 */
+      default:
+         _process_unsupported_command(handle, ep_num, cbw_ptr);
+         break;
+   } /* Endswitch */
+
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : service_ep1
+* Returned Value : None
+* Comments       :
+*     Called upon a completed endpoint 1 (USB 1.1 Chapter 9) transfer
+* 
+*END*--------------------------------------------------------------------*/
+static void service_ep1
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+
+      /* [IN] Service type as registered */
+      uint_8               type,
+      
+      /* [IN] Is it a setup packet? */
+      boolean              setup,
+      
+      /* [IN] Direction of the transfer.  Is it transmit? */
+      uint_8               direction,
+      
+      /* [IN] Pointer to the data buffer */
+      uint_8_ptr           buffer,
+      
+      /* [IN] Length of the transfer */
+      uint_32              length,
+
+      /* [IN] Error, if any */
+      uint_8               error
+            
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+    CBW_STRUCT_PTR cbw_ptr = (CBW_STRUCT_PTR)((pointer)buffer);      
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_EP1, 
+                    "disk %s: ep=%d, dir=%s, pBuf=0x%x, length=%d, error=0x%x\n",
+                    __FUNCTION__, type, (direction == ARC_USB_RECV) ? "RECV" : "SEND", 
+                    (unsigned)buffer, (int)length, error);
+
+    if ((!direction) && (!pDiskCtrl->CBW_PROCESSED) && (length == 31) && 
+        (cbw_ptr->DCBWSIGNATURE == USB_32BIT_LE(USB_DCBWSIGNATURE))) 
+    {
+        /* A valid CBW was received */
+        pDiskCtrl->pCSW->DCSWSIGNATURE = USB_32BIT_LE(USB_DCSWSIGNATURE);
+        pDiskCtrl->pCSW->DCSWTAG = cbw_ptr->DCBWTAG;
+        pDiskCtrl->CBW_PROCESSED = TRUE;
+
+        /* Swap 32 bit fields if neccessary */
+        cbw_ptr->DCBWDATALENGTH = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH);
+
+        /* Process the command */
+        _process_mass_storage_command(handle, type, cbw_ptr);
+    } 
+    else 
+    {
+        /* If a CBW was processed then send the status information and 
+        ** queue another cbw receive request, else just queue another CBW receive
+        ** request if we received an invalid CBW 
+        */
+        if (pDiskCtrl->CBW_PROCESSED) 
+        {
+            int     i;
+
+            ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_DATA, 
+                    "disk %s: ep=%d, dir=%s, pBuf=0x%x, length=%d, error=0x%x\n",
+                    __FUNCTION__, type, (direction == ARC_USB_RECV) ? "RECV" : "SEND", 
+                    (unsigned)buffer, (int)length, error);
+
+            for(i=0; i<64; i++)
+            {
+                if( (i % 16) == 0)
+                {
+                    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_DUMP, "\n0x%08x: ", &buffer[i]);
+                }
+                ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_DUMP, "%02x ", buffer[i]);
+                if( (i % 3) == 0)
+                    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_DUMP, " ");                
+            }
+
+            if (pDiskCtrl->ZERO_TERMINATE) 
+            { /* Body */
+                pDiskCtrl->ZERO_TERMINATE = FALSE;
+                _usb_device_send_data(handle, pDiskCtrl->inEpNo, 0, 0);
+            } 
+            else 
+            { /* Body */
+                pDiskCtrl->CBW_PROCESSED = FALSE;
+
+                /* Send the command status information */
+                _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13);        
+                _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);
+            }
+        } 
+        else
+        {
+            if (!direction) 
+            {
+                USB_printf("usbDisk_%d, %s: Wrong direction = %d\n", 
+                    _usb_device_get_dev_num(handle), __FUNCTION__, direction);
+                _usb_device_stall_endpoint(handle, pDiskCtrl->outEpNo, ARC_USB_RECV);
+                _usb_device_stall_endpoint(handle, pDiskCtrl->inEpNo, ARC_USB_SEND);
+
+                /* Invalid CBW received. Queue another receive buffer */
+                _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31);  
+            }
+        } /* Endif */
+    } /* Endif */
+   
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : service_speed
+* Returned Value : None
+* Comments       :
+*     Called upon a speed detection event.
+* 
+*END*--------------------------------------------------------------------*/
+static void service_speed
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+
+      /* [IN] request type as registered */
+      uint_8               type,
+
+      /* [IN] Unused */
+      boolean              setup,
+   
+      /* [IN] Unused */
+      uint_8               direction,
+   
+      /* [IN] Unused */
+      uint_8_ptr           buffer,
+   
+      /* [IN] Unused */
+      uint_32              length,
+
+      /* [IN] Error, if any */
+      uint_8               error
+            
+   )
+{ /* EndBody */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+    
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SPEED, "disk %s: speed = %d\n", __FUNCTION__, (unsigned)length);
+
+    pDiskCtrl->speed = length;
+    return;
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : reset_ep0
+* Returned Value : None
+* Comments       :
+*     Called upon a bus reset event.  Initialises the control endpoint.
+* 
+*END*--------------------------------------------------------------------*/
+static void reset_ep0
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+   
+      /* [IN] request type as registered */
+      uint_8               type,
+
+      /* [IN] Unused */
+      boolean              setup,
+   
+      /* [IN] Unused */
+      uint_8               direction,
+   
+      /* [IN] Unused */
+      uint_8_ptr           buffer,
+   
+      /* [IN] Unused */
+      uint_32              length,
+
+      /* [IN] Error, if any */
+      uint_8               error
+            
+   )
+{ /* Body */
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+    
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_RESET, "disk-%d %s: pDiskCtrl=%p, handle=%p\n", 
+                    devNo, __FUNCTION__, pDiskCtrl, handle);
+
+    /* on a reset always ensure all transfers are cancelled on control EP*/
+    _usb_device_cancel_transfer(handle, 0, ARC_USB_RECV);
+    _usb_device_cancel_transfer(handle, 0, ARC_USB_SEND);
+
+    _usb_device_start(handle);
+    /* Initialize the endpoint 0 in both directions */
+    _usb_device_init_endpoint(handle, 0, pDiskCtrl->DevDesc[DEV_DESC_MAX_PACKET_SIZE], 
+                                ARC_USB_RECV, ARC_USB_CONTROL_ENDPOINT, 0);
+    _usb_device_init_endpoint(handle, 0, pDiskCtrl->DevDesc[DEV_DESC_MAX_PACKET_SIZE], 
+                                ARC_USB_SEND, ARC_USB_CONTROL_ENDPOINT, 0);
+
+
+    if (pDiskCtrl->TEST_ENABLED) 
+    {
+        int out_ep_count=0, in_ep_count=0;
+
+        while(_usb_device_get_transfer_status(handle, pDiskCtrl->outEpNo, ARC_USB_RECV) != 
+                                                    ARC_USB_STATUS_IDLE)
+        {
+            out_ep_count++;
+            _usb_device_cancel_transfer(handle, pDiskCtrl->outEpNo, ARC_USB_RECV);
+        }
+        while(_usb_device_get_transfer_status(handle, pDiskCtrl->inEpNo, ARC_USB_SEND) != 
+                                                    ARC_USB_STATUS_IDLE)
+        {
+            in_ep_count++;
+            _usb_device_cancel_transfer(handle, pDiskCtrl->inEpNo, ARC_USB_SEND);
+        }
+        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_RESET, "disk %s: out_ep_count=%d, in_ep_count=%d\n", 
+                        __FUNCTION__, out_ep_count, in_ep_count);
+    } /* Endif */
+
+    pDiskCtrl->TEST_ENABLED = FALSE;
+
+    return;
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : usbDiskLoad - main task
+* Inputs:
+*   int diskSize  - size of created disk in KBytes    
+* Returned Value : None
+* Comments       :
+*     First function called.  Initialises the USB and registers Chapter 9
+*     callback functions.
+* 
+*END*--------------------------------------------------------------------*/
+_usb_device_handle  usbDiskLoad(int devNo, int diskSize)
+{ /* Body */
+    _usb_device_handle  handle;
+    USB_DISK_STRUCT*    pDiskCtrl;
+    uint_8_ptr          Send_Buffer_aligned;
+    uint_8              error;
+    uint_32             send_data_buffer_size=0;
+    uint_8_ptr          temp;
+    int                 lockKey, i, j;
+    static boolean      isFirst = TRUE;
+
+    ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, "%s: devNo=%d, diskSize=%d\n", 
+                        __FUNCTION__, devNo, diskSize);
+
+    if(devNo >= MAX_USB_DEVICES)
+    {
+        USB_printf("USB disk: devNo=%d too large\n", devNo);
+        return NULL;
+    }
+
+    /*lock interrupts */
+    lockKey = USB_lock();
+
+    if(isFirst)
+    {
+        for(i=0; i<MAX_USB_DEVICES; i++)
+        {
+            usbDisksPtr[i] = NULL;
+        }
+        /* Swap all USB_STRING_DESC */
+        for(i=0; i<(sizeof(USB_STRING_DESC)/sizeof(USB_STRING_DESC[0])); i++)
+        {
+            uint_16* usbStr = (uint_16*)(USB_STRING_DESC[i]);
+            uint_16 size = (usbStr[0]-0x300)/sizeof(uint_16);
+
+            for(j=0; j<size; j++)
+            {
+                usbStr[j] = USB_16BIT_LE(usbStr[j]);
+            }
+        }
+        isFirst = FALSE;
+    }
+
+    if(usbDisksPtr[devNo] != NULL)
+    {
+        USB_printf("USB disk: devNo=%d is busy\n", devNo);
+        USB_unlock(lockKey);
+        return NULL;
+    }
+
+    /* Allocate Disk control structure */
+    pDiskCtrl = USB_memalloc(sizeof(USB_DISK_STRUCT));
+    if(pDiskCtrl == NULL)
+    {
+        USB_printf("USB disk #%d: Can't allocate USB_DISK_STRUCT (%d bytes)\n", 
+                    devNo, sizeof(USB_DISK_STRUCT));
+        USB_unlock(lockKey);
+        return NULL;
+    }
+    USB_memzero(pDiskCtrl, sizeof(USB_DISK_STRUCT));
+
+    if(diskSize == 0)
+        pDiskCtrl->logicalBlocks = TOTAL_LOGICAL_ADDRESS_BLOCKS;
+    else
+        pDiskCtrl->logicalBlocks = (diskSize*1024)/LENGTH_OF_EACH_LAB;
+
+    if(pDiskCtrl->logicalBlocks < 16)
+    {
+        USB_printf("USB disk size (%d) is too small. Minimum is 8 Kbytes\n",
+                    diskSize);
+        USB_unlock(lockKey);
+        return NULL;
+    }
+    
+    pDiskCtrl->devNo = devNo;
+    pDiskCtrl->hsMaxPktSize = diskHsMaxPktSize;
+    pDiskCtrl->fsMaxPktSize = diskFsMaxPktSize;
+
+    pDiskCtrl->inEpType     = diskInEpType;
+    pDiskCtrl->outEpType    = diskOutEpType;
+
+    pDiskCtrl->inEpNo       = diskInEpNo;
+    pDiskCtrl->outEpNo      = diskOutEpNo;
+
+    /* Initialize the USB interface */
+    error = _usb_device_init(devNo, &handle);
+    if (error != USB_OK) 
+    {
+        USB_unlock(lockKey);
+        USB_printf("\nUSB Initialization failed. Error: %x", error);
+        return NULL;
+    } /* Endif */
+
+    /* Self Power, Remote wakeup disable */
+    _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, (1 << DEVICE_SELF_POWERED));    
+
+    error = _usb_device_register_service(handle, ARC_USB_SERVICE_EP0, service_ep0);   
+    if (error != USB_OK) 
+    {
+        USB_unlock(lockKey);
+        USB_printf("\nUSB Service Registration failed. Error: %x", error);
+        return NULL;
+    } /* Endif */
+   
+    error = _usb_device_register_service(handle, ARC_USB_SERVICE_BUS_RESET, reset_ep0);   
+    if (error != USB_OK) 
+    {
+        USB_unlock(lockKey);
+        USB_printf("\nUSB Service Registration failed. Error: %x", error);
+        return NULL;
+    } /* Endif */
+   
+    error = _usb_device_register_service(handle, ARC_USB_SERVICE_SPEED_DETECTION, 
+                                                        service_speed);
+    if (error != USB_OK) 
+    {
+        USB_unlock(lockKey);
+        USB_printf("\nUSB Service Registration failed. Error: %x", error);
+        return NULL;
+    } /* Endif */
+         
+    error = _usb_device_register_service(handle, pDiskCtrl->outEpNo, service_ep1);   
+    if (error != USB_OK) 
+    {
+        USB_unlock(lockKey);
+        USB_printf("\nUSB Service Registration failed. Error: %x", error);
+        return NULL;
+    } /* Endif */
+
+    if(pDiskCtrl->outEpNo != pDiskCtrl->inEpNo)
+    {
+        error = _usb_device_register_service(handle, pDiskCtrl->inEpNo, service_ep1);   
+        if (error != USB_OK) 
+        {
+            USB_unlock(lockKey);
+            USB_printf("\nUSB Service Registration failed. Error: %x", error);
+            return NULL;
+        } /* Endif */
+    }
+
+    /**************************************************************************
+    Best way to handle the Data cache is to allocate a large buffer that is
+    cache aligned and keep all data inside it. Flush the line of the cache
+    that you have changed. In this program, we have static data such as 
+    descriptors which never changes. Such data can be kept in this buffer
+    and flushed only once. Note that you can reduce the size of this buffer
+    by aligning the addresses in a different way.   
+    ***************************************************************************/
+    send_data_buffer_size =  (DEVICE_DESCRIPTOR_SIZE +  PSP_CACHE_LINE_SIZE) +
+                            (CONFIG_DESC_SIZE + PSP_CACHE_LINE_SIZE) +
+                            (DEVICE_QUALIFIER_DESCRIPTOR_SIZE + PSP_CACHE_LINE_SIZE) +
+                            (OTHER_SPEED_CONFIG_DESC_SIZE + PSP_CACHE_LINE_SIZE) +
+                            (BUFFERSIZE + PSP_CACHE_LINE_SIZE) +
+                            (EP_TEMP_BUFFERSIZE + PSP_CACHE_LINE_SIZE) + 
+                            (sizeof(DISK_READ_CAPACITY) + PSP_CACHE_LINE_SIZE) +
+                            (sizeof(CSW_STRUCT) + PSP_CACHE_LINE_SIZE) +
+                            (pDiskCtrl->logicalBlocks*LENGTH_OF_EACH_LAB + PSP_CACHE_LINE_SIZE);
+
+    pDiskCtrl->Send_Buffer_Unaligned   = (uint_8_ptr) USB_memalloc(send_data_buffer_size);
+    if (pDiskCtrl->Send_Buffer_Unaligned == NULL) 
+    {
+        USB_unlock(lockKey);
+        USB_printf("diskLoad: Buffer allocation of %d bytes is failed\n", 
+                    (unsigned)send_data_buffer_size);
+        return NULL;
+    }
+   
+    Send_Buffer_aligned = (uint_8_ptr) USB_CACHE_ALIGN((uint_32)pDiskCtrl->Send_Buffer_Unaligned);
+    /* keep a temporary copy of the aligned address */
+    temp = Send_Buffer_aligned;
+   
+    /**************************************************************************
+    Assign pointers to different buffers from it and copy data inside.
+    ***************************************************************************/
+    pDiskCtrl->DevDesc =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(DevDescData, pDiskCtrl->DevDesc, DEVICE_DESCRIPTOR_SIZE);
+    Send_Buffer_aligned += ((DEVICE_DESCRIPTOR_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; 
+   
+    pDiskCtrl->ConfigDesc =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(ConfigDescData, pDiskCtrl->ConfigDesc, CONFIG_DESC_SIZE);
+    Send_Buffer_aligned += ((CONFIG_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; 
+   
+    pDiskCtrl->DevQualifierDesc =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(DevQualifierDescData, pDiskCtrl->DevQualifierDesc, DEVICE_QUALIFIER_DESCRIPTOR_SIZE);
+    Send_Buffer_aligned += ((DEVICE_QUALIFIER_DESCRIPTOR_SIZE/PSP_CACHE_LINE_SIZE) + 1) * PSP_CACHE_LINE_SIZE;
+
+    pDiskCtrl->other_speed_config =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(other_speed_config_data, pDiskCtrl->other_speed_config, OTHER_SPEED_CONFIG_DESC_SIZE);
+    Send_Buffer_aligned += ((OTHER_SPEED_CONFIG_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; 
+
+    /*buffer to receive data from Bulk OUT */
+    pDiskCtrl->ep1_buf =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memzero(pDiskCtrl->ep1_buf, BUFFERSIZE);
+    Send_Buffer_aligned += ((BUFFERSIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE;
+   
+    /*buffer for control endpoint to send data */
+    pDiskCtrl->epTemp_buf =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memzero(pDiskCtrl->epTemp_buf, EP_TEMP_BUFFERSIZE);
+    
+    Send_Buffer_aligned += ((EP_TEMP_BUFFERSIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; 
+
+    /* Buffer for read Capacity message */
+    pDiskCtrl->pReadCapacity = (DISK_READ_CAPACITY*)Send_Buffer_aligned;
+    USB_memcopy((void*)&read_capacity, pDiskCtrl->pReadCapacity, sizeof(DISK_READ_CAPACITY));
+
+    /* Update read_capacity */
+    pDiskCtrl->pReadCapacity->LAST_LOGICAL_BLOCK_ADDRESS[2] = 
+                            USB_uint_16_high(pDiskCtrl->logicalBlocks-14);
+    pDiskCtrl->pReadCapacity->LAST_LOGICAL_BLOCK_ADDRESS[3] = 
+                            USB_uint_16_low(pDiskCtrl->logicalBlocks-14);
+
+    Send_Buffer_aligned += ((sizeof(DISK_READ_CAPACITY)/PSP_CACHE_LINE_SIZE) + 1) * PSP_CACHE_LINE_SIZE; 
+
+    /* Buffer for CSW message */
+    pDiskCtrl->pCSW = (CSW_STRUCT*)Send_Buffer_aligned;
+    USB_memzero(pDiskCtrl->pCSW , sizeof(CSW_STRUCT));
+    
+    Send_Buffer_aligned += ((sizeof(CSW_STRUCT)/PSP_CACHE_LINE_SIZE) + 1) * PSP_CACHE_LINE_SIZE; 
+
+    /*buffer for storage disk */
+    pDiskCtrl->MASS_STORAGE_DISK = (uint_8_ptr)Send_Buffer_aligned;
+    
+    USB_printf("usbDisk-%d: pDiskCtrl=%p, %d bytes allocated addr=0x%x\n", 
+                 devNo, pDiskCtrl, (unsigned)send_data_buffer_size, 
+                 (unsigned)pDiskCtrl->Send_Buffer_Unaligned);
+    USB_printf("usbDisk-%d: DevDesc=0x%x, ConfigDesc=0x%x, QualifierDesc=0x%x, otherSpeedDesc=0x%x\n",
+                 devNo, (unsigned)pDiskCtrl->DevDesc, (unsigned)pDiskCtrl->ConfigDesc, 
+                 (unsigned)pDiskCtrl->DevQualifierDesc, (unsigned)pDiskCtrl->other_speed_config);
+    USB_printf("usbDisk-%d: ep1_buf=0x%x, epTemp_buf=0x%x, MASS_STORAGE_DISK=0x%x\n",
+                 devNo, (unsigned)pDiskCtrl->ep1_buf, (unsigned)pDiskCtrl->epTemp_buf, 
+                 (unsigned)pDiskCtrl->MASS_STORAGE_DISK);
+    
+    USB_memzero(pDiskCtrl->MASS_STORAGE_DISK, (pDiskCtrl->logicalBlocks*LENGTH_OF_EACH_LAB));
+
+    /* Format the "disk" */      
+    USB_memcopy(BOOT_SECTOR_AREA, pDiskCtrl->MASS_STORAGE_DISK, 512);
+
+    /* Update BOOT Sector "Total Small sectors" field */
+    pDiskCtrl->MASS_STORAGE_DISK[19] = USB_uint_16_low(pDiskCtrl->logicalBlocks);
+    pDiskCtrl->MASS_STORAGE_DISK[20] = USB_uint_16_high(pDiskCtrl->logicalBlocks);
+
+    USB_memcopy((void *)FAT16_SPECIAL_BYTES, pDiskCtrl->MASS_STORAGE_DISK + 512, 3);
+    USB_memcopy((void *)FAT16_SPECIAL_BYTES, pDiskCtrl->MASS_STORAGE_DISK + 512*4, 3);
+                         
+    /**************************************************************************
+    Flush the cache to ensure main memory is updated.
+    ***************************************************************************/
+    USB_dcache_flush(temp, send_data_buffer_size);
+
+    pDiskCtrl->usbDevHandle = handle;
+    usbDisksPtr[devNo] = pDiskCtrl;
+
+    USB_unlock(lockKey);
+
+    USB_printf("USB Disk is READY: diskSize=%d KBytes, blockSize=%d Bytes, numBlocks=%d\n",
+                diskSize, LENGTH_OF_EACH_LAB, pDiskCtrl->logicalBlocks);
+
+    return pDiskCtrl->usbDevHandle;
+} /* Endbody */
+
+void    usbDiskUnload(_usb_device_handle handle)
+{
+    int                 lockKey;
+    int                 devNo = _usb_device_get_dev_num(handle);
+    USB_DISK_STRUCT*    pDiskCtrl = usbDisksPtr[devNo];
+
+    if(pDiskCtrl == NULL)
+    {
+        USB_printf("USB disk #%d: Disk is not loaded\n", pDiskCtrl->devNo);
+        return;
+    }
+    /*lock interrupts */
+    lockKey = USB_lock();
+    
+    /* ensure all transfers are cancelled */
+    _usb_device_cancel_transfer(handle, pDiskCtrl->outEpNo, ARC_USB_RECV);
+    _usb_device_cancel_transfer(handle, pDiskCtrl->inEpNo,  ARC_USB_SEND);
+
+    /* Stop Endpoints */
+    _usb_device_deinit_endpoint(handle, pDiskCtrl->outEpNo, ARC_USB_RECV);
+    _usb_device_deinit_endpoint(handle, pDiskCtrl->inEpNo, ARC_USB_SEND);
+
+    _usb_device_deinit_endpoint(handle, 0, ARC_USB_RECV);
+    _usb_device_deinit_endpoint(handle, 0, ARC_USB_SEND);
+
+    _usb_device_stop(handle);
+
+    /* Deregister all services */
+    _usb_device_unregister_service(handle, ARC_USB_SERVICE_EP0);   
+    _usb_device_unregister_service(handle, ARC_USB_SERVICE_BUS_RESET);   
+    _usb_device_unregister_service(handle, ARC_USB_SERVICE_SPEED_DETECTION);
+    _usb_device_unregister_service(handle, pDiskCtrl->outEpNo);   
+    if(pDiskCtrl->outEpNo != pDiskCtrl->inEpNo)
+    {
+        _usb_device_unregister_service(handle, pDiskCtrl->inEpNo);   
+    }
+
+    _usb_device_shutdown(handle);
+
+    /* Free memory allocated for Disk device */
+    if(pDiskCtrl->Send_Buffer_Unaligned != NULL)
+    {
+        USB_memfree(pDiskCtrl->Send_Buffer_Unaligned);
+    }
+
+    /* Free Control structure */
+    USB_memfree(pDiskCtrl);
+    usbDisksPtr[devNo] = NULL;
+
+    USB_unlock(lockKey);
+}
+
+/* EOF */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/examples/disk.h b/arch/arm/plat-feroceon/mv_hal/usb/examples/disk.h
new file mode 100755
index 0000000..d01dc4e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/examples/disk.h
@@ -0,0 +1,86 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __disk_h__
+#define __disk_h__
+
+#define  USB_DCBWSIGNATURE       (0x43425355)
+#define  USB_DCSWSIGNATURE       (0x53425355)
+#define  USB_CBW_DIRECTION_BIT   (0x80)
+
+/* USB Command Block Wrapper */
+typedef struct cbw_struct {
+   uint_32  DCBWSIGNATURE;
+   uint_32  DCBWTAG;
+   uint_32  DCBWDATALENGTH;
+   uint_8   BMCBWFLAGS;
+   /* 4 MSBs bits reserved */
+   uint_8   BCBWCBLUN;
+   /* 3 MSB reserved */
+   uint_8   BCBWCBLENGTH;
+   uint_8   CBWCB[16];
+} CBW_STRUCT, _PTR_ CBW_STRUCT_PTR;
+
+/* USB Command Status Wrapper */
+typedef struct csw_struct {
+   uint_32  DCSWSIGNATURE;
+   uint_32  DCSWTAG;
+   uint_32  DCSWDATARESIDUE;
+   uint_8   BCSWSTATUS;
+} CSW_STRUCT, _PTR_ CSW_STRUCT_PTR;
+
+/* USB Mass storage Inquiry Command */
+typedef struct mass_storage_inquiry {
+   uint_8   OPCODE;
+   uint_8   LUN;
+   uint_8   PAGE_CODE;
+   uint_8   RESERVED1;
+   uint_8   ALLOCATION_LENGTH;
+   uint_8   RESERVED2[7];
+} DISK_INQUIRY, _PTR_ DISK_INQUIRY_PTR;
+
+/* USB Mass storage READ CAPACITY Data */
+typedef struct mass_storage_read_capacity {
+   uint_8   LAST_LOGICAL_BLOCK_ADDRESS[4];
+   uint_8   BLOCK_LENGTH_IN_BYTES[4];
+} DISK_READ_CAPACITY, _PTR_ DISK_READ_CAPACITY_PTR;
+
+/* USB Mass storage Device information */
+typedef struct mass_storage_device_info {
+   uint_8   PERIPHERAL_DEVICE_TYPE;    /* Bits 0-4. All other bits reserved */
+   uint_8   RMB;                       /* Bit 7. All other bits reserved */
+   uint_8   ANSI_ECMA_ISO_VERSION;     /* ANSI: bits 0-2, ECMA: bits 3-5, 
+                                       ** ISO: bits 6-7 
+                                       */
+   uint_8   RESPONSE_DATA_FORMAT;      /* bits 0-3. All other bits reserved */
+   uint_8   ADDITIONAL_LENGTH;         /* For UFI device: always set to 0x1F */
+   uint_8   RESERVED1[3];
+   uint_8   VENDOR_INFORMATION[8];
+   uint_8   PRODUCT_ID[16];
+   uint_8   PRODUCT_REVISION_LEVEL[4];
+} DISK_DEVICE_INFO, _PTR_ DISK_DEVICE_INFO_PTR;
+
+
+extern _usb_device_handle  usbDiskLoad(int devNo, int diskSize);
+extern void                usbDiskUnload(_usb_device_handle  handle);
+
+#endif /* __disk_h__ */
+
+/* EOF */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/examples/mouse.c b/arch/arm/plat-feroceon/mv_hal/usb/examples/mouse.c
new file mode 100755
index 0000000..fdcdc42
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/examples/mouse.c
@@ -0,0 +1,1708 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+
+/**************************************************************************
+Include the USB stack header files.
+**************************************************************************/
+#include "usb/api/mvUsbDefs.h"
+#include "usb/api/mvUsbDebug.h"
+#include "usb/api/mvUsbCh9.h"
+#include "usb/api/mvUsbDevApi.h"
+
+#include "usb/examples/mouse.h"
+
+/**************************************************************************
+global variables and some defines for device.
+**************************************************************************/
+
+#define CONTROL_MAX_PACKET_SIZE         (64)
+#define INTERRUPT_MAX_PACKET_SIZE       (0x0008)
+#define DEV_DESC_MAX_PACKET_SIZE        (7)
+#define INTERRUPT_EP                    (1)
+#define FRAME_INTERVAL                  (15)
+
+/**************************************************************************
+Include the OS and BSP dependent files that define IO functions and
+basic types. You may like to change these files for your board and RTOS 
+**************************************************************************/
+
+int frame_interval = FRAME_INTERVAL;
+int mouseCntr = 0;
+int mouseDelay = 2;
+
+static volatile boolean TEST_ENABLED = FALSE;
+static volatile boolean USB_SUSPENDED = FALSE;
+
+#define EP1_RECV_BUFFER_SIZE 10
+static uint_8_ptr hid_test_rep_data;
+static uint_8_ptr hid_test_rep_data_unaligned;
+
+/********************************
+Buffers for sending data to stack
+********************************/
+#define EP0_SEND_BUFFER_SIZE 200
+static uint_8_ptr Send_Buffer_Unaligned;
+static uint_8_ptr Send_Buffer_aligned;
+
+static uint_8         data_to_send;
+static uint_16        sof_count;
+static SETUP_STRUCT   local_setup_packet;
+
+
+/*************************************************************************
+Device descriptors are always 18 bytes 
+
+Offset|       Field        | Value |  Description  
+------|--------------------|-------|--------------------
+  0   |      bLength       |  0x12 |The size of this 
+      |                    |       |descriptor is 18 bytes
+------|--------------------|-------|--------------------
+  1   |  bDescriptorType   |  0x01 |DEVICE Descriptor Type
+------|--------------------|-------|--------------------
+  2   |       bcdUSB       | 0x0100|Device compliant to 
+      |                    |       |the USB 
+      |                    |       |specification 
+      |                    |       |version 1.00   
+------|--------------------|-------|--------------------
+  4   |    bDeviceClass    |  0x00 |Each interface 
+      |                    |       |specifies its own 
+      |                    |       |class information
+------|--------------------|-------|--------------------
+  5   |  bDeviceSubClass   |  0x00 |Each interface 
+      |                    |       |specifies its own 
+      |                    |       |subclass information
+------|--------------------|-------|--------------------
+  6   |  bDeviceProtocol   |  0x00 |No protocols on the 
+      |                    |       |device basis
+------|--------------------|-------|--------------------
+  7   |  bMaxPacketSize0   |  0x08 |Maximum packet size 
+      |                    |       |for endpoint zero is 8
+------|--------------------|-------|--------------------
+  8   |      idVendor      | 0x0261|Vendor ID is 609: 
+      |                    |       
+------|--------------------|-------|--------------------
+  10  |     idProduct      | 0x4D03|The Product ID is 0x4D03
+------|--------------------|-------|--------------------
+  12  |     bcdDevice      | 0x0441|The device release 
+      |                    |       |number is 4.41
+------|--------------------|-------|--------------------
+  14  |   iManufacturer    |  0x00 |The device doesn't 
+      |                    |       |have the string 
+      |                    |       |descriptor 
+      |                    |       |describing the manufacturer
+------|--------------------|-------|--------------------
+  15  |      iProduct      |  0x00 |The device doesn't 
+      |                    |       |have the string 
+      |                    |       |descriptor 
+      |                    |       |describing the product
+------|--------------------|-------|--------------------
+  16  |   iSerialNumber    |  0x00 | 
+------|--------------------|-------|--------------------
+  17  | bNumConfigurations |  0x01 | 
+------|--------------------|-------|--------------------
+*************************************************************************/
+#define DEVICE_DESCRIPTOR_SIZE 18
+static uint_8_ptr DevDesc;
+static uint_8  DevDescData[DEVICE_DESCRIPTOR_SIZE] =
+{
+   DEVICE_DESCRIPTOR_SIZE,
+   0x01,
+   0x0,2,
+   
+   0x00,
+   0x00,
+   0x00,
+   CONTROL_MAX_PACKET_SIZE,
+   /* Vendor ID = MARVELL */
+   USB_uint_16_low(0x1286), USB_uint_16_high(0x1286),
+   /* Product ID */
+   USB_uint_16_low(0x1), USB_uint_16_high(0x1),
+   /* BCD Device version */
+   USB_uint_16_low(0x0002), USB_uint_16_high(0x0002),
+
+   0x01,                      /* iManufacturer */
+   0x02,                      /* iProduct */
+   0x00,                      /* iSerialNumber */
+   0x01                       /* bNumConfigurations */
+   
+};
+
+/* USB 2.0 specific descriptor */
+#define DEVICE_QUALIFIER_DESCRIPTOR_SIZE 10
+static uint_8_ptr DevQualifierDesc;
+static uint_8  DevQualifierDescData[DEVICE_QUALIFIER_DESCRIPTOR_SIZE] =
+{
+   DEVICE_QUALIFIER_DESCRIPTOR_SIZE,  /* bLength Length of this descriptor */
+   6,                         /* bDescType This is a DEVICE Qualifier descr */
+   0,2,                       /* bcdUSB USB revision 2.0 */
+   0,                         /* bDeviceClass */
+   0,                         /* bDeviceSubClass */
+   0,                         /* bDeviceProtocol */
+   CONTROL_MAX_PACKET_SIZE,  /* bMaxPacketSize0 */
+   0x01,                      /* bNumConfigurations */
+   0
+};
+
+
+/*******************************************************************
+   CONFIG DESCRIPTOR
+
+Data stage (34 bytes) :
+------------------------------------
+
+       CONFIGURATION Descriptor
+       ------------------------
+Offset|        Field        | Value |  Description  
+------|---------------------|-------|--------------------
+  0   |       bLength       |  0x09 |The size of this 
+      |                     |       |descriptor is 9 bytes
+------|---------------------|-------|--------------------
+  1   |   bDescriptorType   |  0x02 |CONFIGURATION 
+      |                     |       |Descriptor Type
+------|---------------------|-------|--------------------
+  2   |    wTotalLength     | 0x0022|The total length of 
+      |                     |       |data for this 
+      |                     |       |configuration is 34. 
+      |                     |       |This includes the 
+      |                     |       |combined length of 
+      |                     |       |all the descriptors returned
+------|---------------------|-------|--------------------
+  4   |   bNumInterfaces    |  0x01 |This configuration 
+      |                     |       |supports 1 interfaces
+------|---------------------|-------|--------------------
+  5   | bConfigurationValue |  0x01 |The value 1 should 
+      |                     |       |be used to select 
+      |                     |       |this configuration
+------|---------------------|-------|--------------------
+  6   |   iConfiguration    |  0x00 |The device doesn't 
+      |                     |       |have the string 
+      |                     |       |descriptor 
+      |                     |       |describing this configuration
+------|---------------------|-------|--------------------
+  7   |    bmAttributes     |  0x80 |Configuration characteristics :
+      |                     |       |Bit 7: Reserved (set to one) 1 
+      |                     |       |Bit 6: Self-powered          0 
+      |                     |       |Bit 5: Remote Wakeup         1 
+------|---------------------|-------|--------------------
+  8   |      MaxPower       |  0x32 |Maximum power 
+      |                     |       |consumption of the 
+      |                     |       |device in this 
+      |                     |       |configuration is 100 mA
+------|---------------------|-------|--------------------
+
+       INTERFACE Descriptor
+       --------------------
+Offset|       Field        | Value |  Description  
+------|--------------------|-------|--------------------
+  0   |      bLength       |  0x09 |The size of this 
+      |                    |       |descriptor is 9 bytes
+------|--------------------|-------|--------------------
+  1   |  bDescriptorType   |  0x04 |INTERFACE Descriptor Type
+------|--------------------|-------|--------------------
+  2   |  bInterfaceNumber  |  0x00 |The number of this 
+      |                    |       |interface is 0
+------|--------------------|-------|--------------------
+  3   | bAlternateSetting  |  0x00 |The value used to 
+      |                    |       |select alternate 
+      |                    |       |setting for this 
+      |                    |       |interface is 0
+------|--------------------|-------|--------------------
+  4   |   bNumEndpoints    |  0x01 |The number of 
+      |                    |       |endpoints used by 
+      |                    |       |this interface is 1 
+      |                    |       |(excluding endpoint zero)
+------|--------------------|-------|--------------------
+  5   |  bInterfaceClass   |  0x03 |The interface 
+      |                    |       |implements HID class
+------|--------------------|-------|--------------------
+  6   | bInterfaceSubClass |  0x01 |The subclass code is 0x01
+------|--------------------|-------|--------------------
+  7   | bInterfaceProtocol |  0x02 |The protocol code is 0x02
+------|--------------------|-------|--------------------
+  8   |     iInterface     |  0x00 |The device doesn't 
+      |                    |       |have the string 
+      |                    |       |descriptor 
+      |                    |       |describing this interface
+------|--------------------|-------|--------------------
+
+       HID Descriptor
+       --------------
+Offset|       Field       | Value |  Description  
+------|-------------------|-------|--------------------
+  0   |      bLength      |  0x09 |The size of this 
+      |                   |       |descriptor is 9 bytes
+------|-------------------|-------|--------------------
+  1   |  bDescriptorType  |  0x21 |HID Descriptor Type
+------|-------------------|-------|--------------------
+  2   |      bcdHID       | 0x0100|Device compliant to 
+      |                   |       |the HID 
+      |                   |       |specification 
+      |                   |       |version 1.00   
+------|-------------------|-------|--------------------
+  4   |   bCountryCode    |  0x00 |The country code is 0x00
+------|-------------------|-------|--------------------
+  5   |  bNumDescriptors  |  0x01 |The number of class 
+      |                   |       |descriptors is 1
+------|-------------------|-------|--------------------
+  6   |  bDescriptorType  |  0x22 |The class descriptor 
+      |                   |       |is Report descriptor
+------|-------------------|-------|--------------------
+  7   | wDescriptorlength | 0x0034|The total size of 
+      |                   |       |the class descriptor 
+      |                   |       |is 52
+------|-------------------|-------|--------------------
+
+       ENDPOINT Descriptor
+       -------------------
+Offset|      Field       | Value |  Description  
+------|------------------|-------|--------------------
+  0   |     bLength      |  0x07 |The size of this 
+      |                  |       |descriptor is 7 bytes
+------|------------------|-------|--------------------
+  1   | bDescriptorType  |  0x05 |ENDPOINT Descriptor Type
+------|------------------|-------|--------------------
+  2   | bEndpointAddress |  0x81 |This is an IN 
+      |                  |       |endpoint with 
+      |                  |       |address (endpoint 
+      |                  |       |number) 1
+------|------------------|-------|--------------------
+  3   |   bmAttributes   |  0x03 |Types - 
+      |                  |       |Transfer:INTERRUPT 
+      |                  |       |Sync:No Sync 
+      |                  |       |Usage:Data EP
+------|------------------|-------|--------------------
+  4   |  wMaxPacketSize  | 0x0004|Maximum packet size 
+      |                  |       |value for this 
+      |                  |       |endpoint is 0x4 
+      |                  |       |(Bits 12-11: Addtl. Transactions/frame)
+------|------------------|-------|--------------------
+  6   |    bInterval     |  0x0A |bInterval:10. The 
+      |                  |       |polling interval 
+      |                  |       |value is bInterval 
+      |                  |       |or 2**(bInterval-1)
+------|------------------|-------|--------------------
+
+*******************************************************************/
+
+
+#define CONFIG_DESC_NUM_INTERFACES  (4)
+
+/* This must be counted manually and updated with the descriptor */
+/* 1*Config(9) + 1*Interface(9) + 1*HID(9) + 1* Endpoint (7)= 34 bytes */
+#define CONFIG_DESC_SIZE            (34)
+
+static uint_8_ptr ConfigDesc;
+
+static uint_8 ConfigDescData[CONFIG_DESC_SIZE] =
+{
+   /*Config Descriptor */
+   0x09,
+   0x02,
+   USB_uint_16_low(CONFIG_DESC_SIZE),
+   USB_uint_16_high(CONFIG_DESC_SIZE),
+   0x01,
+   0x01,
+   0x00,
+   0xE0, /* 0x80, */
+   0x0,
+   /* Interface Descriptor */	
+   0x09,
+   0x04,
+   0x00,
+   0x00,
+   0x01,
+   0x03,
+   0x01,
+   0x02,
+   0x00,
+
+   /* HID descriptor */
+   0x09,
+   0x21,
+   USB_uint_16_low(0x0100),
+   USB_uint_16_high(0x0100),
+   0x00,
+   0x01,
+   0x22,
+   USB_uint_16_low(0x0034),
+   USB_uint_16_high(0x0034),
+ 
+   /*Endpoint descriptor */
+   0x07,
+   0x05,
+   (0x80+INTERRUPT_EP),
+   0x03,
+   USB_uint_16_low(INTERRUPT_MAX_PACKET_SIZE), 
+   USB_uint_16_high(INTERRUPT_MAX_PACKET_SIZE),
+   FRAME_INTERVAL
+};
+
+#define OTHER_SPEED_CONFIG_DESC_SIZE  CONFIG_DESC_SIZE
+static uint_8_ptr  other_speed_config;
+static uint_8  other_speed_config_data[CONFIG_DESC_SIZE] =
+{
+   /*Config Descriptor */
+   0x09,
+   0x07,
+   USB_uint_16_low(CONFIG_DESC_SIZE),
+   USB_uint_16_high(CONFIG_DESC_SIZE),
+   0x01,
+   0x01,
+   0x00,
+   0xE0, /* 0x80, */
+   0x0,
+   /* Interface Descriptor */	
+   0x09,
+   0x04,
+   0x00,
+   0x00,
+   0x01,
+   0x03,
+   0x01,
+   0x02,
+   0x00,
+
+   /* HID descriptor */
+   0x09,
+   0x21,
+   USB_uint_16_low(0x0100),
+   USB_uint_16_high(0x0100),
+   0x00,
+   0x01,
+   0x22,
+   USB_uint_16_low(0x0034),
+   USB_uint_16_high(0x0034),
+ 
+   /*Endpoint descriptor */
+   0x07,
+   0x05,
+   (0x80+INTERRUPT_EP),
+   0x03,
+   USB_uint_16_low(INTERRUPT_MAX_PACKET_SIZE), 
+   USB_uint_16_high(INTERRUPT_MAX_PACKET_SIZE),
+   FRAME_INTERVAL
+
+};
+/************************************************************************
+
+HID Class Report Descriptor :
+
+Item						Value(Hex)
+------------------------------------------------------------------------------------------------------------
+Usage Page (Generic Desktop Control)			05 01 
+Usage (Mouse)					09 02 
+Collection (Application)				A1 01 
+  Usage (Pointer)					09 01 
+  Collection (Physical)				A1 00 
+    Usage Page (Button)				05 09 
+    Usage Minimum (1)				19 01 
+    Usage Maximum (3)				29 03 
+    Logical Minimum (0)				15 00 
+    Logical Maximum (1)				25 01 
+    Report Count (3)					95 03 
+    Report Size (1)					75 01 
+    Input (Data, Variable, Absolute)			81 02 
+    Report Count (1)					95 01 
+    Report Size (5)					75 05 
+    Input (Constant)					81 01 
+    Usage Page (Generic Desktop Control)		05 01 
+    Usage (X)					09 30 
+    Usage (Y)					09 31 
+    Usage (Wheel)					09 38 
+    Logical Minimum (-127)				15 81 
+    Logical Maximum (127)				25 7F 
+    Report Size (8)					75 08 
+    Report Count (3)					95 03 
+    Input (Data, Variable, Relative)			81 06 
+  End Collection					C0 
+End Collection					C0 
+
+
+************************************************************************/
+
+#define REPORT_DESC_SIZE            (52)
+static uint_8_ptr ReportDesc;
+
+static uint_8 ReportDescData[REPORT_DESC_SIZE] =
+{
+   0x05,
+   0x01,
+   0x09,
+   0x02,
+   0xA1,
+   0x01,
+   0x09,
+   0x01,
+   
+   0xA1,
+   0x00,
+   0x05,
+   0x09,
+   0x19,
+   0x01,
+   0x29,
+   0x03,
+   
+   0x15,
+   0x00,
+   0x25,
+   0x01,
+   0x95,
+   0x03,
+   0x75,
+   0x01,
+   
+   0x81,
+   0x02,
+   0x95,
+   0x01,
+   0x75,
+   0x05,
+   0x81,
+   0x01,
+   
+   0x05,
+   0x01,
+   0x09,
+   0x30,
+   0x09,
+   0x31,
+   0x09,
+   0x38,
+   
+   0x15,
+   0x81,
+   0x25,
+   0x7F,
+   0x75,
+   0x08,
+   0x95,
+   0x03,
+   
+   0x81,
+   0x06,
+   0xC0,
+   0xC0   
+};
+
+/**************************************************************
+This report descriptor can be used to report the set_report
+and get_report capability to host. When this is used, modify
+the config descriptor to reflect the size of report descriptor.
+The following lines should be changed,
+
+USB_uint_16_low(0x0038),  //   Changed from USB_uint_16_low(0x0034),
+USB_uint_16_high(0x0038), //   Changed from USB_uint_16_high(0x0034),
+  
+
+
+
+uint_8  ReportDesc[56] = {
+    0x06, 0x00, 0xff,              		// USAGE_PAGE (Generic Desktop)
+    0x09, 0x01,                    		// USAGE (Vendor Usage 1)
+    0xa1, 0x01,                    		// COLLECTION (Application)
+
+    0x09, 0x02,                    		//   USAGE (Vendor Usage 2)
+    0x15, 0x80,                    		//   LOGICAL_MINIMUM (-128)																			
+    0x25, 0x7f,                    		//   LOGICAL_MAXIMUM (127) 																			
+    0x95, 0x01,                    		//   REPORT_COUNT (1)      																			
+    0x75, 0x08,                    		//   REPORT_SIZE (8)       																			
+    0xb1, 0x02,                    		//   FEATURE (Data,Var,Abs)																			
+
+    0x09, 0x03,                    		//   USAGE (Vendor Usage 3)																			
+    0x15, 0x80,                    		//   LOGICAL_MINIMUM (-128)																			
+    0x25, 0x7f,                    		//   LOGICAL_MAXIMUM (127) 																			
+    0x95, 0x01,                    		//   REPORT_COUNT (1)      																			
+    0x75, 0x08,                    		//   REPORT_SIZE (8)
+    0xb1, 0x02,                    		//   FEATURE (Data,Var,Abs)																			
+
+    0x09, 0x04,                    		//   USAGE (Vendor Usage 4)																			
+    0x15, 0x80,                    		//   LOGICAL_MINIMUM (-128)																			
+    0x25, 0x7f,                    		//   LOGICAL_MAXIMUM (127) 																			
+    0x95, 0x01,                    		//   REPORT_COUNT (1)      																			
+    0x75, 0x08,                    		//   REPORT_SIZE (8)
+    0xb1, 0x02,                    		//   FEATURE (Data,Var,Abs)																			
+
+    0x09, 0x05,                    		//   USAGE (Vendor Usage 5)																			
+    0x15, 0x80,                    		//   LOGICAL_MINIMUM (-128)																			
+    0x25, 0x7f,                    		//   LOGICAL_MAXIMUM (127) 																			
+    0x95, 0x01,                    		//   REPORT_COUNT (1)      																			
+    0x75, 0x08,                    		//   REPORT_SIZE (8)
+    0xb1, 0x02,                    		//   FEATURE (Data,Var,Abs)																			
+        
+    0xc0                           		// END_COLLECTION          																			
+};
+***************************************************************/
+
+/**********************************************************************
+Mouse data (this structure is used to send mouse movement information)
+**********************************************************************/
+typedef struct   _MOUSE_DATA {
+   char  a;
+   char  b;
+   char  c;
+   char  d;
+
+} MOUSE_DATA_STRUCT;
+
+static MOUSE_DATA_STRUCT mouse_data = {0,0,0,0};
+
+static uint_8 USB_IF_ALT[4] = { 0, 0, 0, 0};
+
+/* number of strings in the table not including 0 or n. */
+static const uint_8 USB_STR_NUM  = 6;
+
+/*
+** if the number of strings changes, look for USB_STR_0 everywhere and make 
+** the obvious changes.  It should be found in 3 places.
+*/
+
+static const uint_16 USB_STR_0[ 2] = {0x0300 + sizeof(USB_STR_0),0x0409};
+static const uint_16 USB_STR_1[26] = {0x0300 + sizeof(USB_STR_1),
+      'M','a','r','v','e','l','l',' ','S','e','m','i','c','o','n','d','u','c','t','o','r',' ','L','t','d'};       
+static const uint_16 USB_STR_2[28] = {0x0300 + sizeof(USB_STR_2),
+      'M','A','R','V','E','L','L',' ','U','S','B',' ','h','i','d','m','o','u','s','e',' ',\
+      'D','e','v','i','c','e'};
+static const uint_16 USB_STR_3[ 5] = {0x0300 + sizeof(USB_STR_3),
+      'B','E','T','A'};
+static const uint_16 USB_STR_4[ 4] = {0x0300 + sizeof(USB_STR_4),
+      '#','0','2'};
+static const uint_16 USB_STR_5[ 4] = {0x0300 + sizeof(USB_STR_5),
+      '_','A','1'};
+static const uint_16 USB_STR_6[15] = {0x0300 + sizeof(USB_STR_6),
+      'Y','o','u','r',' ','n','a','m','e',' ','h','e','r','e'};
+static const uint_16 USB_STR_n[17] = {0x0300 + sizeof(USB_STR_n),
+      'B','A','D',' ','S','T','R','I','N','G',' ','I','n','d','e','x'};
+
+#define USB_STRING_ARRAY_SIZE  8
+static const uint_8_ptr USB_STRING_DESC[USB_STRING_ARRAY_SIZE] =
+{
+   (uint_8_ptr)USB_STR_0,
+   (uint_8_ptr)USB_STR_1,
+   (uint_8_ptr)USB_STR_2,
+   (uint_8_ptr)USB_STR_3,
+   (uint_8_ptr)USB_STR_4,
+   (uint_8_ptr)USB_STR_5,
+   (uint_8_ptr)USB_STR_6,
+   (uint_8_ptr)USB_STR_n
+};
+
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9GetDescription
+* Returned Value : None
+* Comments       :
+*     Chapter 9 GetDescription command
+*     The Device Request can ask for Device/Config/string/interface/endpoint
+*     descriptors (via wValue). We then post an IN response to return the
+*     requested descriptor.
+*     And then wait for the OUT which terminates the control transfer.
+*     See section 9.4.3 (page 189) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9GetDescription
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+   if (setup) {
+      /* Load the appropriate string depending on the descriptor requested.*/
+      switch (setup_ptr->VALUE & 0xFF00) {
+
+         case 0x0100:
+            _usb_device_send_data(handle, 0, DevDesc,
+               MIN(setup_ptr->LENGTH, DEVICE_DESCRIPTOR_SIZE));
+
+            break;
+
+         case 0x0200:
+             *(ConfigDesc + 33) = frame_interval;
+            _usb_device_send_data(handle, 0, ConfigDesc,
+               MIN(setup_ptr->LENGTH, CONFIG_DESC_SIZE));
+                           
+            break;
+
+         case 0x2200:
+         _usb_device_send_data(handle, 0, ReportDesc,
+            MIN(setup_ptr->LENGTH, REPORT_DESC_SIZE));
+
+         /*send some data for the mouse in the interrupt pipe queue */
+         _usb_device_send_data(handle, INTERRUPT_EP, (uint_8_ptr)((pointer)&mouse_data),
+                                sizeof(MOUSE_DATA_STRUCT));
+               
+            break;      
+   
+         case 0x0300:
+            if ((setup_ptr->VALUE & 0x00FF) > USB_STR_NUM) {
+               _usb_device_send_data(handle, 0, USB_STRING_DESC[USB_STR_NUM+1],
+                  MIN(setup_ptr->LENGTH, USB_STRING_DESC[USB_STR_NUM+1][0]));
+            } else {
+               _usb_device_send_data(handle, 0,
+                  USB_STRING_DESC[setup_ptr->VALUE & 0x00FF],
+                  MIN(setup_ptr->LENGTH, USB_STRING_DESC[setup_ptr->VALUE & 0x00FF][0]));
+            } /* Endif */      
+            break;
+
+         case 0x600:
+            _usb_device_send_data(handle, 0, (uint_8_ptr)DevQualifierDesc, 
+               MIN(setup_ptr->LENGTH, DEVICE_QUALIFIER_DESCRIPTOR_SIZE));
+            break;
+            
+         case 0x700:      
+            *(other_speed_config + 33) = frame_interval;
+
+            _usb_device_send_data(handle, 0, (uint_8_ptr)other_speed_config, 
+               MIN(setup_ptr->LENGTH, OTHER_SPEED_CONFIG_DESC_SIZE));
+            break;
+        
+         default:
+            USB_printf("usbMouse_%d, %s: Unexpected VALUE=0x%04x\n", 
+                _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE);                
+            _usb_device_stall_endpoint(handle, 0, 0);
+            return;
+      } /* Endswitch */
+      /* status phase */
+      _usb_device_recv_data(handle, 0, 0, 0);
+   } /* Endif */
+   return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SetDescription
+* Returned Value : None
+* Comments       :
+*     Chapter 9 SetDescription command
+*     See section 9.4.8 (page 193) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9SetDescription
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    USB_printf("usbMouse_%d, %s: setup=%d\n", 
+            _usb_device_get_dev_num(handle), __FUNCTION__, (int)setup);
+   _usb_device_stall_endpoint(handle, 0, 0);
+   return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9GetConfig
+* Returned Value : None
+* Comments       :
+*     Chapter 9 GetConfig command
+*     See section 9.4.2 (page 189) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9GetConfig
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+   uint_16 current_config;
+   /* Return the currently selected configuration */
+   if (setup){ 
+      _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG,
+         &current_config);
+      data_to_send = (uint_8)current_config;      
+      _usb_device_send_data(handle, 0, (pointer) &data_to_send, sizeof(data_to_send));
+      /* status phase */
+      _usb_device_recv_data(handle, 0, 0, 0);
+   } /* Endif */
+   return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SetConfig
+* Returned Value : None
+* Comments       :
+*     Chapter 9 SetConfig command
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9SetConfig
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    uint_16 usb_state;
+   
+    if (setup) 
+    {
+        if ((setup_ptr->VALUE & 0x00FF) > 1) 
+        {
+            /* generate stall */
+            USB_printf("usbMouse_%d, %s: Wrong VALUE=0x%04x\n", 
+                    _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE);
+            _usb_device_stall_endpoint(handle, 0, 0);
+            return;
+        } /* Endif */
+
+        /* 0 indicates return to unconfigured state */
+        if ((setup_ptr->VALUE & 0x00FF) == 0) 
+        {
+            _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state);
+            if ((usb_state == ARC_USB_STATE_CONFIG) || 
+                (usb_state == ARC_USB_STATE_ADDRESS)) 
+            {
+                /* clear the currently selected config value */
+                _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, 0);
+                _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE,
+                                                        ARC_USB_STATE_ADDRESS);
+                /* status phase */      
+                _usb_device_send_data(handle, 0, 0, 0);
+            } 
+            else 
+            {
+                USB_printf("usbMouse_%d, %s: Wrong usb_state=%d\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, usb_state);
+
+                _usb_device_stall_endpoint(handle, 0, 0);
+            } /* Endif */
+            return;
+        } /* Endif */
+
+        /*
+        ** If the configuration value (setup_ptr->VALUE & 0x00FF) differs
+        ** from the current configuration value, then endpoints must be
+        ** reconfigured to match the new device configuration
+        */
+        _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, &usb_state);
+        ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, 
+                        "usbMouse: Set configuration: old=%d, new=%d\n", 
+                        usb_state, setup_ptr->VALUE & 0x00FF);
+
+        if (usb_state != (setup_ptr->VALUE & 0x00FF)) 
+        {
+            /* Reconfigure endpoints here */
+            switch (setup_ptr->VALUE & 0x00FF) 
+            {
+                default:
+                break;
+            } /* Endswitch */
+            _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG,
+                                setup_ptr->VALUE & 0x00FF);
+        } /* Endif */
+        /* Init Interrupt endpoint */
+        _usb_device_init_endpoint(handle,INTERRUPT_EP, INTERRUPT_MAX_PACKET_SIZE, 
+                                   ARC_USB_SEND, ARC_USB_INTERRUPT_ENDPOINT, 
+                                   ARC_USB_DEVICE_DONT_ZERO_TERMINATE);
+
+        TEST_ENABLED = TRUE;
+
+        _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE,
+                             ARC_USB_STATE_CONFIG);
+        /* status phase */
+        _usb_device_send_data(handle, 0, 0, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9GetInterface
+* Returned Value : None
+* Comments       :
+*     Chapter 9 GetInterface command
+*     See section 9.4.4 (page 190) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9GetInterface
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    uint_16 usb_state;
+   
+    _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state);
+    if (usb_state != ARC_USB_STATE_CONFIG) 
+    {
+        USB_printf("usbMouse_%d, %s: Wrong usb_state=%d\n", 
+                    _usb_device_get_dev_num(handle), __FUNCTION__, usb_state);
+        _usb_device_stall_endpoint(handle, 0, 0);
+        return;
+    } /* Endif */
+
+    if (setup) 
+    {
+        _usb_device_send_data(handle, 0, &USB_IF_ALT[setup_ptr->INDEX & 0x00FF],
+                                MIN(setup_ptr->LENGTH, sizeof(uint_8)));
+        /* status phase */      
+        _usb_device_recv_data(handle, 0, 0, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SetInterface
+* Returned Value : None
+* Comments       :
+*     Chapter 9 SetInterface command
+*     See section 9.4.10 (page 195) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9SetInterface
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+    if (setup) 
+    {
+        if (setup_ptr->REQUESTTYPE != 0x01) 
+        {
+            USB_printf("usbDisk_%d, %s: Wrong REQUESTTYPE=0x%02x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, 
+                        setup_ptr->REQUESTTYPE);
+
+            _usb_device_stall_endpoint(handle, 0, 0);
+            return;
+        } /* Endif */
+
+        /*
+        ** If the alternate value (setup_ptr->VALUE & 0x00FF) differs
+        ** from the current alternate value for the specified interface,
+        ** then endpoints must be reconfigured to match the new alternate
+        */
+        if (USB_IF_ALT[setup_ptr->INDEX & 0x00FF]
+                    != (setup_ptr->VALUE & 0x00FF))
+        {
+            USB_IF_ALT[setup_ptr->INDEX & 0x00FF] = (setup_ptr->VALUE & 0x00FF);
+            /* Reconfigure endpoints here. */
+         
+        } /* Endif */
+
+        /* status phase */
+        _usb_device_send_data(handle, 0, 0, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9SynchFrame
+* Returned Value : 
+* Comments       :
+*     Chapter 9 SynchFrame command
+*     See section 9.4.11 (page 195) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9SynchFrame
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+            
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+   
+    if (setup) 
+    {
+        if (setup_ptr->REQUESTTYPE != 0x02) 
+        {
+            USB_printf("usbMouse_%d, %s: Wrong REQUESTTYPE=0x%02x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, 
+                        setup_ptr->REQUESTTYPE);
+            _usb_device_stall_endpoint(handle, 0, 0);
+            return;
+        } /* Endif */
+
+        if ((setup_ptr->INDEX & 0x00FF) >=
+                ConfigDesc[CONFIG_DESC_NUM_INTERFACES])
+        {
+            USB_printf("usbMouse_%d, %s: Wrong INDEX=0x%04x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->INDEX);
+            _usb_device_stall_endpoint(handle, 0, 0);
+            return;
+        } /* Endif */
+
+        _usb_device_get_status(handle, ARC_USB_STATUS_SOF_COUNT, &sof_count);
+
+        sof_count = USB_16BIT_LE(sof_count);
+        _usb_device_send_data(handle, 0, (uint_8_ptr)&sof_count,
+                        MIN(setup_ptr->LENGTH, sizeof(sof_count)));
+        /* status phase */      
+        _usb_device_recv_data(handle, 0, 0, 0);
+    } /* Endif */
+    return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : get_report
+* Returned Value : 
+* Comments       :
+*     Chapter 9 Class specific request
+*     See section 9.4.11 (page 195) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+
+void get_report
+	(
+	/* USB handle */
+	_usb_device_handle handle,
+	
+	/* Is it a Setup phase? */
+	boolean     setup,
+   
+   /* [IN] Direction of the transfer. (1 for USB IN token)*/
+   uint_8      direction,
+	
+	/* The setup packet pointer */
+	SETUP_STRUCT_PTR setup_ptr
+
+	)
+{ 
+    int i;
+      
+   for(i=0;i<10;i++)	
+	{
+		hid_test_rep_data[i] = (uint_8) i;
+	}
+
+	if (setup)
+	{
+		_usb_device_send_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4));
+	}
+         
+   _usb_device_recv_data(handle, 0, 0, 0);
+         
+
+	return;
+} 
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : set_report
+* Returned Value : 
+* Comments       :
+*     Chapter 9 Class specific request
+*     See section 9.4.11 (page 195) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+
+void set_report
+	(
+	/* USB handle */
+	_usb_device_handle handle,
+	
+	/* Is it a Setup phase? */
+	boolean setup,
+   
+   /* [IN] Direction of the transfer. (1 for USB IN token)*/
+   uint_8               direction,
+
+	
+	/* The setup packet pointer */
+	SETUP_STRUCT_PTR setup_ptr
+	)
+{ 
+	if (setup)      /*on a SetUP packet*/
+   {
+	  _usb_device_recv_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4));
+ 
+	}
+   else if(direction == ARC_USB_RECV)   /*on a OUT packet*/
+   {
+	_usb_device_recv_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4));
+     _usb_device_send_data(handle, 0, 0, 0);
+   }
+
+	return;
+} 
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : set_idle
+* Returned Value : 
+* Comments       :
+*     Chapter 9 Class specific request
+*     See section 9.4.11 (page 195) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+
+void set_idle
+	(
+	/* USB handle */
+	_usb_device_handle handle,
+	
+	/* Is it a Setup phase? */
+	boolean setup,
+   
+   /* [IN] Direction of the transfer. (1 for USB IN token)*/
+   uint_8               direction,
+
+	
+	/* The setup packet pointer */
+	SETUP_STRUCT_PTR setup_ptr
+	)
+{ 
+   /* SET_IDLE is a No data phase transaction from HID class. All it needs
+   is a terminating IN token */
+	if (setup)      /*on a SetUP packet*/
+   {
+	  _usb_device_send_data(handle, 0, 0, 0);  
+	}
+	return;
+} 
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : ch9Class
+* Returned Value : 
+* Comments       :
+*     Chapter 9 Class specific request
+*     See section 9.4.11 (page 195) of the USB 1.1 Specification.
+* 
+*END*--------------------------------------------------------------------*/
+static void ch9Class
+   (
+      /* USB handle */
+      _usb_device_handle handle,
+      
+      /* Is it a Setup phase? */
+      boolean setup,
+      
+      /* [IN] Direction of the transfer. (1 for USB IN token)*/
+      uint_8               direction,
+
+      /* The setup packet pointer */
+      SETUP_STRUCT_PTR setup_ptr
+   )
+{ /* Body */
+   
+   switch (setup_ptr->REQUEST) 
+   {
+   
+      case 0x01:
+         get_report(handle, setup, direction, setup_ptr);
+         break;
+      
+      case 0x09:
+         set_report(handle, setup, direction, setup_ptr);
+         break;
+
+      case 0x0A:
+         set_idle(handle, setup, direction, setup_ptr);
+         break;
+     
+      default:
+        USB_printf("usbMouse_%d, %s: Wrong REQUEST=0x%02x\n", 
+              _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->REQUEST);
+
+         _usb_device_stall_endpoint(handle, 0, 0);
+         break;
+
+   } /* EndSwitch */
+
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : service_ep0
+* Returned Value : None
+* Comments       :
+*     Called upon a completed endpoint 0 (USB 1.1 Chapter 9) transfer
+* 
+*END*--------------------------------------------------------------------*/
+static void service_ep0
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+      
+      /* [IN] request type as registered */
+      uint_8               type,
+
+      /* [IN] Is it a setup packet? */
+      boolean              setup,
+      
+      /* [IN] Direction of the transfer.  Is it transmit? */
+      uint_8               direction,
+      
+      /* [IN] Pointer to the data buffer */
+      uint_8_ptr           buffer,
+      
+      /* [IN] Length of the transfer */
+      uint_32              length,
+      
+      /* [IN] Error, if any */
+      uint_8               error
+            
+            
+   )
+{ /* Body */
+   boolean  class_request = FALSE;
+   
+   if (setup) 
+   {
+      _usb_device_read_setup_data(handle, 0, (uint_8_ptr)&local_setup_packet);
+      local_setup_packet.VALUE = USB_16BIT_LE(local_setup_packet.VALUE);
+      local_setup_packet.INDEX = USB_16BIT_LE(local_setup_packet.INDEX);
+      local_setup_packet.LENGTH = USB_16BIT_LE(local_setup_packet.LENGTH);
+   } 
+   else if (class_request) {
+      class_request = FALSE;
+      /* Finish your class or vendor request here */
+      
+      return;
+   } /* Endif */
+   
+   switch (local_setup_packet.REQUESTTYPE & 0x60) {
+
+      case 0x00:
+         switch (local_setup_packet.REQUEST) {
+
+            case 0x0:
+               mvUsbCh9GetStatus(handle, setup, &local_setup_packet);
+               break;
+
+            case 0x1:
+               mvUsbCh9ClearFeature(handle, setup, &local_setup_packet);
+               break;
+
+            case 0x3:
+               mvUsbCh9SetFeature(handle, setup, &local_setup_packet);
+               break;
+
+            case 0x5:
+               mvUsbCh9SetAddress(handle, setup, &local_setup_packet);
+               break;
+
+            case 0x6:
+               ch9GetDescription(handle, setup, &local_setup_packet);
+               break;
+
+            case 0x7:
+               ch9SetDescription(handle, setup, &local_setup_packet);
+               break;
+
+            case 0x8:
+               ch9GetConfig(handle, setup, &local_setup_packet);
+               break;
+
+            case 0x9:
+               ch9SetConfig(handle, setup, &local_setup_packet);
+               break;
+
+            case 0xa:
+               ch9GetInterface(handle, setup, &local_setup_packet);
+               break;
+
+            case 0xb:
+               ch9SetInterface(handle, setup, &local_setup_packet);
+               break;
+
+            case 0xc:
+               ch9SynchFrame(handle, setup, &local_setup_packet);
+               break;
+
+            default:
+                USB_printf("usbMouse_%d, %s: Wrong REQUEST = 0x%02x\n", 
+                        _usb_device_get_dev_num(handle), __FUNCTION__, local_setup_packet.REQUEST);
+               _usb_device_stall_endpoint(handle, 0, 0);
+               break;
+
+         } /* Endswitch */
+         
+         break;
+
+      case 0x20:
+         ch9Class(handle, setup, direction, &local_setup_packet);
+
+         break;
+
+      case 0x40:
+         /* vendor specific request */
+         break;
+      
+      default:
+         USB_printf("usbMouse_%d, %s: Unexpected REQUESTTYPE = 0x%x\n", 
+                _usb_device_get_dev_num(handle), __FUNCTION__, 
+                local_setup_packet.REQUESTTYPE);
+
+         _usb_device_stall_endpoint(handle, 0, 0);
+         break;
+         
+   } /* Endswitch */
+   
+   return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : service_ep1
+* Returned Value : None
+* Comments       :
+*     Called upon a completed endpoint 1 (USB 1.1 Chapter 9) transfer
+* 
+*END*--------------------------------------------------------------------*/
+static void service_ep1
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+
+      /* [IN] request type as registered */
+      uint_8               type,
+      
+      /* [IN] Is it a setup packet? */
+      boolean              setup,
+      
+      /* [IN] Direction of the transfer.  Is it transmit? */
+      uint_8               direction,
+      
+      /* [IN] Pointer to the data buffer */
+      uint_8_ptr           buffer,
+      
+      /* [IN] Length of the transfer */
+      uint_32              length,
+
+      /* [IN] Error, if any */
+      uint_8               error
+            
+            
+   )
+{ /* Body */
+
+/********************************************************************
+   The following code will move the mouse right and left on the screen.
+   Comment this out if this behaviour is not desired.
+********************************************************************/
+
+    static int       x = 0;  
+    static boolean   right = FALSE;
+    static int       wait = 0;
+
+    mouseCntr++;
+    if(wait == 0)
+    {
+        if (right == FALSE)  
+        {
+            mouse_data.b = 1; 
+            x++;
+            right = (x > 200) ? TRUE : FALSE;     
+        }
+   
+        if (right == TRUE)  
+        {
+            mouse_data.b = -1; 
+            x--;
+            right = (x < 0) ? FALSE : TRUE;     
+        }
+        wait = mouseDelay;
+    }
+    else
+    {
+        wait--;
+        mouse_data.b = 0; 
+    }
+   
+   _usb_device_send_data(handle, INTERRUPT_EP, (uint_8_ptr)((pointer)&mouse_data),
+                            sizeof(MOUSE_DATA_STRUCT));
+ 
+   return;
+} /* Endbody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : reset_ep0
+* Returned Value : None
+* Comments       :
+*     Called upon a bus reset event.  Initialises the control endpoint.
+* 
+*END*--------------------------------------------------------------------*/
+static void reset_ep0
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+
+      /* [IN] request type as registered */
+      uint_8               type,
+      
+      /* [IN] Unused */
+      boolean              setup,
+   
+      /* [IN] Unused */
+      uint_8               direction,
+   
+      /* [IN] Unused */
+      uint_8_ptr           buffer,
+   
+      /* [IN] Unused */
+      uint_32              length,
+
+      /* [IN] Error, if any */
+      uint_8               error
+            
+            
+   )
+{ /* Body */
+
+   /*on a reset always cancel all transfers all EP 0 */
+   _usb_device_cancel_transfer(handle, 0, ARC_USB_RECV);
+   _usb_device_cancel_transfer(handle, 0, ARC_USB_SEND);
+

+   _usb_device_start(handle);

+
+   /* Initialize the endpoint 0 in both directions */
+   _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 0,
+      ARC_USB_CONTROL_ENDPOINT, 0);
+   _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 1,
+      ARC_USB_CONTROL_ENDPOINT, 0);
+
+   if (TEST_ENABLED) 
+   {
+      _usb_device_cancel_transfer(handle, INTERRUPT_EP, ARC_USB_SEND);
+   } /* Endif */
+   
+   TEST_ENABLED = FALSE;
+   mouseCntr = 0;
+         
+   return;
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : service_suspend
+* Returned Value : None
+* Comments       :
+*     Called when host suspend the USB port. Do remote wake up if desired.
+* 
+*END*--------------------------------------------------------------------*/
+static void service_suspend
+   (
+      /* [IN] Handle of the USB device */
+      _usb_device_handle   handle,
+   
+      /* [IN] request type as registered */
+      uint_8               type,
+
+      /* [IN] Unused */
+      boolean              setup,
+   
+      /* [IN] Unused */
+      uint_8               direction,
+   
+      /* [IN] Unused */
+      uint_8_ptr           buffer,
+   
+      /* [IN] Unused */
+      uint_32              length,
+
+      /* [IN] Error, if any */
+      uint_8               error                        
+   )
+{ /* Body */
+   uint_16      usb_status;
+   int          lockKey;            
+   
+   _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status);
+   if (usb_status & ARC_USB_REMOTE_WAKEUP) 
+   { 
+       lockKey = USB_lock();
+
+       USB_printf("Mouse Suspended: type=%d, usbStatus=0x%x\n", type, usb_status);
+       USB_SUSPENDED = TRUE;
+
+       USB_unlock(lockKey);
+   } 
+          
+   return;
+} /* EndBody */
+
+/*FUNCTION*----------------------------------------------------------------
+* 
+* Function Name  : usbMouseLoad
+* Returned Value : None
+* Comments       :
+*     First function called.  Initialises the USB and registers Chapter 9
+*     callback functions.
+* 
+*END*--------------------------------------------------------------------*/
+_usb_device_handle  usbMouseLoad(int devNo)
+{ /* Body */
+   _usb_device_handle   handle;
+   uint_8               error;
+   uint_32              send_data_buffer_size=0;
+   uint_8_ptr           temp;
+   int                  lockKey, i, j;
+   static boolean       isFirst = TRUE;
+
+    if(isFirst)
+    {
+        /* Swap all USB_STRING_DESC */
+        for(i=0; i<(sizeof(USB_STRING_DESC)/sizeof(USB_STRING_DESC[0])); i++)
+        {
+            uint_16* usbStr = (uint_16*)(USB_STRING_DESC[i]);
+            uint_16 size = (usbStr[0]-0x300)/sizeof(uint_16);
+
+            for(j=0; j<size; j++)
+            {
+                usbStr[j] = USB_16BIT_LE(usbStr[j]);
+            }
+        }
+        isFirst = FALSE;
+    }
+
+   lockKey = USB_lock();
+   
+    /* Initialize the USB interface */
+    error = _usb_device_init(devNo, &handle);   
+    if (error != USB_OK) 
+    {
+        USB_printf("\nUSB Initialization failed. Error: %x\n", error);
+        return NULL;
+    } /* Endif */
+   
+    /* Self Power, Remote wakeup disable */
+    _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, (1 << DEVICE_SELF_POWERED));    
+
+    error = _usb_device_register_service(handle, ARC_USB_SERVICE_EP0, service_ep0);
+    if (error != USB_OK) 
+    {
+        USB_printf("\nUSB EP0 Service Registration failed. Error: %x\n", error);
+        return NULL;
+    } /* Endif */
+   
+    error = _usb_device_register_service(handle, ARC_USB_SERVICE_BUS_RESET, reset_ep0);
+    if (error != USB_OK) 
+    {
+        USB_printf("\nUSB BUS_RESET Service Registration failed. Error: %x\n", error);
+        return NULL;
+    } /* Endif */
+   
+    error = _usb_device_register_service(handle, INTERRUPT_EP, service_ep1);   
+    if (error != USB_OK) 
+    {
+        USB_printf("\nUSB EP1 Service Registration failed. Error: %x\n", error);
+        return NULL;
+    } /* Endif */
+
+    error = _usb_device_register_service(handle, ARC_USB_SERVICE_SUSPEND, service_suspend);
+    if (error != USB_OK) 
+    {
+        USB_printf("\nUSB SUSPEND Service Registration failed. Error: %x\n", error);
+        return NULL;
+    } /* Endif */
+
+    error = _usb_device_register_service(handle, ARC_USB_SERVICE_SLEEP, service_suspend);
+    if (error != USB_OK) 
+    {
+        USB_printf("\nUSB SUSPEND Service Registration failed. Error: %x\n", error);
+        return NULL;
+    } /* Endif */
+
+    /***********************************************************************
+    Allocate memory to receive data at endpoint 0. Ensure that buffers are
+    cache aligned.
+    ***********************************************************************/
+    hid_test_rep_data_unaligned   = (uint_8_ptr) USB_memalloc((EP1_RECV_BUFFER_SIZE + PSP_CACHE_LINE_SIZE));
+    if(hid_test_rep_data_unaligned == NULL)
+    {
+        USB_printf("mouseLoad: Buffer allocation of %d bytes is failed\n", 
+                    (unsigned)EP1_RECV_BUFFER_SIZE + PSP_CACHE_LINE_SIZE);
+        return NULL;
+    }
+
+    hid_test_rep_data = (uint_8_ptr) USB_CACHE_ALIGN((uint_32) hid_test_rep_data_unaligned);
+    
+    /**************************************************************************
+    Best way to handle the Data cache is to allocate a large buffer that is
+    cache aligned and keep all data inside it. Flush the line of the cache
+    that you have changed. In this program, we have static data such as 
+    descriptors which never changes. Such data can be kept in this buffer
+    and flushed only once. Note that you can reduce the size of this buffer
+    by aligning the addresses in a different way.
+    ***************************************************************************/
+    send_data_buffer_size =  (DEVICE_DESCRIPTOR_SIZE +  PSP_CACHE_LINE_SIZE) +
+                             (CONFIG_DESC_SIZE + PSP_CACHE_LINE_SIZE) +
+                             (REPORT_DESC_SIZE + PSP_CACHE_LINE_SIZE) +
+                             (DEVICE_QUALIFIER_DESCRIPTOR_SIZE + PSP_CACHE_LINE_SIZE) +
+                             (OTHER_SPEED_CONFIG_DESC_SIZE + PSP_CACHE_LINE_SIZE);
+                               
+    Send_Buffer_Unaligned   = (uint_8_ptr) USB_memalloc(send_data_buffer_size);
+    if (Send_Buffer_Unaligned == NULL) 
+    {
+        USB_printf("\nMouse: %d bytes Buffer allocation failed\n", send_data_buffer_size);
+        return NULL;
+    }
+   
+    Send_Buffer_aligned = (uint_8_ptr) USB_CACHE_ALIGN((uint_32) Send_Buffer_Unaligned);
+    /* keep a temporary copy of the aligned address */
+    temp = Send_Buffer_aligned;
+   
+
+    /**************************************************************************
+    Assign pointers to different descriptors from it and copy descriptors inside.
+    ***************************************************************************/
+    DevDesc =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(DevDescData, DevDesc, DEVICE_DESCRIPTOR_SIZE);
+    Send_Buffer_aligned += ((DEVICE_DESCRIPTOR_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; 
+   
+    ConfigDesc =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(ConfigDescData, ConfigDesc, CONFIG_DESC_SIZE);
+
+    Send_Buffer_aligned += ((CONFIG_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; 
+
+    ReportDesc =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(ReportDescData, ReportDesc, REPORT_DESC_SIZE);
+    Send_Buffer_aligned += ((REPORT_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; 
+
+   
+    DevQualifierDesc =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(DevQualifierDescData, DevQualifierDesc, DEVICE_QUALIFIER_DESCRIPTOR_SIZE);
+    Send_Buffer_aligned += ((DEVICE_QUALIFIER_DESCRIPTOR_SIZE/PSP_CACHE_LINE_SIZE) + \
+                           1)* PSP_CACHE_LINE_SIZE;
+
+    other_speed_config =  (uint_8_ptr) Send_Buffer_aligned;
+    USB_memcopy(other_speed_config_data, other_speed_config, OTHER_SPEED_CONFIG_DESC_SIZE);
+    Send_Buffer_aligned += ((OTHER_SPEED_CONFIG_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; 
+                           
+    /**************************************************************************
+    Flush the cache to ensure main memory is updated.
+    ***************************************************************************/
+    USB_dcache_flush(temp,send_data_buffer_size);
+
+     /* Initialize the endpoint 0 in both directions */
+    _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 0,
+                            ARC_USB_CONTROL_ENDPOINT, 0);
+    _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 1,
+                            ARC_USB_CONTROL_ENDPOINT, 0);
+
+    USB_unlock(lockKey);
+
+    USB_printf("USB Mouse example is READY\n");
+   
+    return handle; 
+} /* Endbody */
+
+void    usbMouseUnload(_usb_device_handle handle)
+{
+    int     lockKey;
+
+    if(handle == NULL)
+        return;
+
+    /*lock interrupts */
+    lockKey = USB_lock();
+    
+    /* ensure all transfers are cancelled */
+    _usb_device_cancel_transfer(handle, INTERRUPT_EP,  ARC_USB_SEND);
+
+    /* Stop Endpoints */
+    _usb_device_deinit_endpoint(handle, INTERRUPT_EP, ARC_USB_SEND);
+
+    _usb_device_deinit_endpoint(handle, 0, ARC_USB_RECV);
+    _usb_device_deinit_endpoint(handle, 0, ARC_USB_SEND);
+

+    _usb_device_stop(handle);

+
+    /* Deregister all services */
+    _usb_device_unregister_service(handle, ARC_USB_SERVICE_EP0);   
+    _usb_device_unregister_service(handle, ARC_USB_SERVICE_BUS_RESET);   
+    _usb_device_unregister_service(handle, ARC_USB_SERVICE_SUSPEND);
+    _usb_device_unregister_service(handle, ARC_USB_SERVICE_SLEEP);
+    _usb_device_unregister_service(handle, INTERRUPT_EP);   
+
+    _usb_device_shutdown(handle);
+
+    /* Free memory allocated for Disk device */
+    if(Send_Buffer_Unaligned != NULL)
+    {
+        USB_memfree(Send_Buffer_Unaligned);
+        Send_Buffer_Unaligned = NULL;
+    }
+
+    if(hid_test_rep_data_unaligned != NULL)
+    {
+        USB_memfree(hid_test_rep_data_unaligned);
+        hid_test_rep_data_unaligned  = NULL;
+    }
+
+    /* Clear gloabal variables */
+    TEST_ENABLED = FALSE;
+    USB_SUSPENDED = FALSE;    
+    
+    USB_unlock(lockKey);
+}
+
+void    usbMousePeriodicResume(_usb_device_handle handle)
+{
+    if (USB_SUSPENDED) 
+    {
+       /*
+        * Send RESUME signal whenever host suspends the USB port. In real case, we should
+        *  send RESUME signal only when a mouse button being clicked.
+        */
+        USB_printf("Mouse Resumed\n");
+
+        _usb_device_assert_resume(handle);
+        USB_SUSPENDED = FALSE;     
+    } /* Endbody */
+}
+/* EOF */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/examples/mouse.h b/arch/arm/plat-feroceon/mv_hal/usb/examples/mouse.h
new file mode 100755
index 0000000..34b741b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/examples/mouse.h
@@ -0,0 +1,29 @@
+/*******************************************************************************

+

+This software file (the "File") is distributed by Marvell International Ltd. 

+or its affiliate(s) under the terms of the GNU General Public License Version 2, 

+June 1991 (the "License").  You may use, redistribute and/or modify this File 

+in accordance with the terms and conditions of the License, a copy of which 

+is available along with the File in the license.txt file or by writing to the 

+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 

+or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.

+

+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 

+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 

+DISCLAIMED.  The GPL License provides additional details about this warranty 

+disclaimer.

+

+(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.

+(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.

+

+*******************************************************************************/

+

+#ifndef __mouse_h__
+#define __mouse_h__
+
+extern _usb_device_handle   usbMouseLoad(int devNo);
+extern void                 usbMouseUnload(_usb_device_handle handle);
+extern void                 usbMousePeriodicResume(_usb_device_handle handle);
+
+#endif /* __mouse_h__ */
+/* EOF */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/usb/mvCompVer.txt
new file mode 100755
index 0000000..5f39390
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7
+Unit HAL Version: 3.1.4
+Description: This component includes an implementation of the unit HAL drivers
+
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/mvUsb.c b/arch/arm/plat-feroceon/mv_hal/usb/mvUsb.c
new file mode 100755
index 0000000..2a83e4c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/mvUsb.c
@@ -0,0 +1,1057 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysUsbConfig.h"
+#include "usb/mvUsbRegs.h"
+#include "usb/mvUsb.h"
+#ifdef MV_USB_VOLTAGE_FIX
+#include "boardEnv/mvBoardEnvLib.h"
+#include "gpp/mvGpp.h"
+#include "gpp/mvGppRegs.h"
+#endif
+static MV_USB_HAL_DATA usbHalData;
+
+MV_U32 mvUsbGetCapRegAddr(int devNo)
+{
+	return (INTER_REGS_BASE | MV_USB_CORE_CAP_LENGTH_REG(devNo));
+}
+
+#ifdef MV_USB_VOLTAGE_FIX
+
+/* GPIO Settings for Back voltage problem workaround */
+MV_U8 mvUsbGppInit(int dev)
+{
+	MV_U32 regVal;
+	MV_U8 gppNo = (MV_U8) mvBoardUSBVbusGpioPinGet(dev);
+	MV_U8 gppVbusEnNo = (MV_U8) mvBoardUSBVbusEnGpioPinGet(dev);
+
+	/* DDR1 => gpp5, DDR2 => gpp1 */
+	if (gppNo != (MV_U8) N_A) {
+		/*mvOsPrintf("mvUsbGppInit: gppNo=%d\n", gppNo); */
+
+		/* MPP Control Register - set to GPP */
+		regVal = MV_REG_READ(mvCtrlMppRegGet((unsigned int)(gppNo / 8)));
+		regVal &= ~(0xf << ((gppNo % 8) * 4));
+		MV_REG_WRITE(mvCtrlMppRegGet((unsigned int)(gppNo / 8)), regVal);
+
+		if (gppNo < 32) {
+			/* GPIO Data Out Enable Control Register - set to input */
+			mvGppTypeSet(0, (1 << gppNo), MV_GPP_IN & (1 << gppNo));
+			/* GPIO Data In Polarity Register */
+			mvGppPolaritySet(0, (1 << gppNo), (0 << gppNo));
+		} else {
+			/* GPIO Data Out Enable Control Register - set to input */
+			mvGppTypeSet(1, (1 << (gppNo - 32)), MV_GPP_IN & (1 << (gppNo - 32)));
+			/* GPIO Data In Polarity Register */
+			mvGppPolaritySet(1, (1 << (gppNo - 32)), (0 << (gppNo - 32)));
+		}
+
+		/* GPIO Data In Polarity Register */
+		/* mvGppPolaritySet(mppGrp, (1<<gppNo), (0<<gppNo) ); */
+
+		regVal = MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev));
+		regVal &= ~(7 << 24);
+		MV_REG_WRITE(MV_USB_PHY_POWER_CTRL_REG(dev), regVal);
+	}
+
+	/* for device - reset vbus enable gpp, for host - set by default */
+	if (gppVbusEnNo != (MV_U8) N_A) {
+		/*mvOsPrintf("mvUsbGppInit: gppVbusEnNo = %d \n", gppVbusEnNo); */
+
+		regVal = MV_REG_READ(GPP_DATA_OUT_REG((gppVbusEnNo / 32)));
+		if (gppVbusEnNo < 32)
+			MV_REG_WRITE(GPP_DATA_OUT_REG(0), (regVal & ~(1 << gppVbusEnNo)));
+		else
+			MV_REG_WRITE(GPP_DATA_OUT_REG(1), (regVal & ~(1 << (gppVbusEnNo - 32))));
+	}
+
+	return gppNo;
+}
+
+int mvUsbBackVoltageUpdate(int dev, MV_U8 gppNo)
+{
+	int vbusChange = 0;
+	MV_U32 gppData, regVal, gppInv;
+
+	if (gppNo < 32) {
+		gppInv = mvGppPolarityGet(0, (1 << gppNo));
+		gppData = mvGppValueGet(0, (1 << gppNo));
+	} else {
+		gppInv = mvGppPolarityGet(1, (1 << (gppNo - 32)));
+		gppData = mvGppValueGet(1, (1 << (gppNo - 32)));
+	}
+	regVal = MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev));
+
+	if ((gppInv == 0) && (gppData != 0)) {
+		/* VBUS appear */
+		regVal |= (7 << 24);
+
+		if (gppNo < 32)
+			gppInv |= (1 << gppNo);
+		else
+			gppInv |= (1 << (gppNo - 32));
+
+		/*mvOsPrintf("VBUS appear: dev=%d, gpp=%d\n", dev, gppNo); */
+		vbusChange = 1;
+	} else if ((gppInv != 0) && (gppData != 0)) {
+		/* VBUS disappear */
+		regVal &= ~(7 << 24);
+
+		if (gppNo < 32)
+			gppInv &= ~(1 << gppNo);
+		else
+			gppInv &= ~(1 << (gppNo - 32));
+
+		/*mvOsPrintf("VBUS disappear: dev=%d, gpp=%d\n", dev, gppNo); */
+		vbusChange = 2;
+	} else {
+		/* No changes */
+		return vbusChange;
+	}
+	MV_REG_WRITE(MV_USB_PHY_POWER_CTRL_REG(dev), regVal);
+
+	if (gppNo < 32)
+		mvGppPolaritySet(0, (1 << gppNo), gppInv);
+	else
+		mvGppPolaritySet(1, (1 << (gppNo - 32)), gppInv);
+
+	return vbusChange;
+}
+#endif /* MV_USB_VOLTAGE_FIX */
+
+/* USB Phy init (change from defaults) specific for 65nm (78100 78200 A0 and later) */
+static void mvUsbPhy65nmNewInit(int dev)
+{
+	MV_U32 regVal;
+
+	if ((usbHalData.ctrlModel == MV_6281_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6280_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6282_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6192_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6190_DEV_ID) || (usbHalData.ctrlModel == MV_6180_DEV_ID)) {
+	/******* USB PHY ANA Grp Config reg 0x1007c *******/
+		regVal = MV_REG_READ(0x1007c);
+		/* bit[4:3]     should be '01' */
+		regVal &= ~(0x3 << 3);
+		regVal |= (0x1 << 3);
+		MV_REG_WRITE(0x1007c, regVal);
+	}
+
+    /******* USB PHY PLL Control Register 0x410 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_PLL_CTRL_REG(dev));
+
+	/* bit[21]  (VCOCAL_ START) */
+	regVal |= (0x1 << 21);
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+
+	/* Wait 100 usec */
+	mvOsUDelay(100);
+
+	regVal &= ~(0x1 << 21);
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /******* USB PHY Tx Control Register Register 0x420 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_TX_CTRL_REG(dev));
+
+	/* Force impedance auto calibrate */
+	/* bit[12]      (REG_RCAL_START) = 1 */
+	regVal |= (0x1 << 12);
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+
+	/* Wait 100 usec */
+	mvOsUDelay(100);
+
+	/* bit[12]  (REG_RCAL_START) = 0 */
+	regVal &= ~(0x1 << 12);
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+
+	/* bit[16:14]       (IMPCAL_VTH) = 101 */
+	if (usbHalData.ctrlModel == MV_6280_DEV_ID) {
+		regVal &= ~(0x7 << 14);
+		regVal |= (0x5 << 14);
+	}
+
+	/* bits[2:0] (TX_AMP) = 0x4 */
+	regVal &= ~(0x7 << 0);
+	if ((usbHalData.ctrlModel == MV_78100_DEV_ID ||
+	     usbHalData.ctrlModel == MV_78200_DEV_ID ||
+	     usbHalData.ctrlModel == MV_76100_DEV_ID ||
+	     usbHalData.ctrlModel == MV_6321_DEV_ID ||
+	     usbHalData.ctrlModel == MV_6322_DEV_ID ||
+	     usbHalData.ctrlModel == MV_6323_DEV_ID) && usbHalData.ctrlRev == MV_78XX0_A0_REV)
+		regVal |= (0x4 << 0);
+	else
+		regVal |= (0x3 << 0);
+
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /******* USB PHY Rx Control Register 0x430 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_RX_CTRL_REG(dev));
+
+	/* bits[3:2]        LPF_COEF        = 0x1 */
+	regVal &= ~(0x3 << 2);
+	regVal |= (0x1 << 2);
+
+	/* bits[7:4]        SQ_THRESH       = 0x8 */
+	regVal &= ~(0xf << 4);
+
+	if (usbHalData.ctrlModel == MV_6282_DEV_ID)
+		regVal |= (0xc << 4);
+	else
+		regVal |= (0x8 << 4);
+
+	MV_REG_WRITE(MV_USB_PHY_RX_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /******* USB PHY IVREF Control Register 0x440 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_IVREF_CTRL_REG(dev));
+
+	/* bits[9:8]        TxVdd */
+	regVal &= ~(0x3 << 8);
+
+	if ((usbHalData.ctrlModel == MV_6281_DEV_ID) || (usbHalData.ctrlModel == MV_6280_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6282_DEV_ID) || (usbHalData.ctrlModel == MV_6192_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6190_DEV_ID) || (usbHalData.ctrlModel == MV_6180_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6510_DEV_ID) || (usbHalData.ctrlModel == MV_6530_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6550_DEV_ID) || (usbHalData.ctrlModel == MV_6560_DEV_ID))
+		regVal |= (0x3 << 8);
+	else
+		regVal |= (0x1 << 8);
+
+	MV_REG_WRITE(MV_USB_PHY_IVREF_CTRL_REG(dev), regVal);
+
+    /*-------------------------------------------------*/
+    /***** USB PHY TEST GROUP CONTROL Register: 0x450 *****/
+
+	/* Nothing to change */
+}
+
+/* USB Phy init (change from defaults) specific for 55nm (6500-Z1 device) */
+#if 0
+static void mvUsbPhyKW6500Init(int dev)
+{
+	MV_U32 regVal;
+	/******* USB PHY PLL Control Register 0x410 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_PLL_CTRL_REG(dev));
+
+	/* VCO recalibrate */
+	regVal |= (0x1 << 21);
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+	/* wait 500 usec */
+	mvOsUDelay(500);
+	regVal &= ~(0x1 << 21);
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+	/*-------------------------------------------------*/
+
+	/******* USB PHY Tx Control Register Register 0x420 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_TX_CTRL_REG(dev));
+
+	/* bit[11]      (LOWVDD_EN)     = 1 */
+	regVal |= (0x1 << 11);
+
+	/* bit[12]      (REG_RCAL_START) = 1 */
+	regVal |= (0x1 << 12);
+
+	/* bits[16:14]  (IMPCAL_VTH[2:0] = 101) */
+	regVal &= ~(0x7 << 14);
+	regVal |= (0x5 << 14);
+
+	/* bit[21]      (TX_BLOCK_EN)   = 0 */
+	regVal &= ~(0x1 << 21);
+
+	/* bit[31]  (HS_STRESS_CTRL) = 0 */
+	regVal &= ~(0x1 << 31);
+
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+
+	/* wait 500 usec */
+	mvOsUDelay(500);
+
+	/* Force impedance auto calibrate */
+	/* bit[12]      (REG_RCAL_START) = 0 */
+	regVal &= ~(0x1 << 12);
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+
+	/*-------------------------------------------------*/
+
+	/******* USB PHY Rx Control Register 0x430 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_RX_CTRL_REG(dev));
+
+	/* bits[3:2]    LPL_COEF        = 0x1 (1/8) */
+	regVal &= ~(0x3 << 2);
+	regVal |= (0x1 << 2);
+
+	/* bits[7:4]    SQ_THRESH       = 0xC */
+	regVal &= ~(0xf << 4);
+	regVal |= (0xC << 4);
+
+	/* bits[16:15]  REG_SQ_LENGTH   = 0x1 */
+	regVal &= ~(0x3 << 15);
+	regVal |= (0x1 << 15);
+
+	/* bit[21]      CDR_FASTLOCK_EN = 0x0 */
+	regVal &= ~(0x1 << 21);
+
+	/* bits[27:26]  EDGE_DET        = 0x0 (1 Tran) */
+	regVal &= ~(0x3 << 26);
+
+	MV_REG_WRITE(MV_USB_PHY_RX_CTRL_REG(dev), regVal);
+	/*-------------------------------------------------*/
+
+	/******* USB PHY IVREF Control Register 0x440 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_IVREF_CTRL_REG(dev));
+
+	/* bits[9:8]    TXVDD12 = 0x3 */
+	regVal &= ~(0x3 << 8);
+	regVal |= (0x3 << 8);
+
+	MV_REG_WRITE(MV_USB_PHY_IVREF_CTRL_REG(dev), regVal);
+	/*-------------------------------------------------*/
+
+	/***** USB PHY TEST GROUP CONTROL Register: 0x450 *****/
+	regVal = MV_REG_READ(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev));
+
+	/* bit[15]      REG_FIFO_SQ_RST = 0x0 */
+	regVal &= ~(0x1 << 15);
+
+	MV_REG_WRITE(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev), regVal);
+	/*-------------------------------------------------*/
+
+	return;
+}
+#endif
+
+/* USB Phy init (change from defaults) specific for 65nm (78XX0 and 6281) */
+static void mvUsbPhy65nmInit(int dev)
+{
+	MV_U32 regVal;
+
+    /******* USB PHY PLL Control Register 0x410 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_PLL_CTRL_REG(dev));
+
+	/* bit[14:12]       (ICP) = 6 */
+	regVal &= ~(0x7 << 12);
+	regVal |= (0x6 << 12);
+
+	/* bit[12]  (KVCO_EXT) = 1 */
+	regVal |= (0x1 << 22);
+
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /******* USB PHY Tx Control Register Register 0x420 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_TX_CTRL_REG(dev));
+
+	/* bit[11]  (LOWVDD_EN)     = 1 */
+	regVal |= (0x1 << 11);
+
+	/* bit[12]  (REG_RCAL_START) = 1 */
+	regVal |= (0x1 << 12);
+
+	/* bit[21]  (TX_BLOCK_EN)   = 0 */
+	regVal &= ~(0x1 << 21);
+
+	/* bit[31]  (HS_STRESS_CTRL) = 0 */
+	regVal &= ~(0x1 << 31);
+
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+	/* Force impedance auto calibrate */
+	/* bit[12]  (REG_RCAL_START) = 0 */
+	regVal &= ~(0x1 << 12);
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /******* USB PHY Rx Control Register 0x430 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_RX_CTRL_REG(dev));
+
+	/* bits[3:2]        LPL_COEF        = 0x0 (1/8) */
+	regVal &= ~(0x3 << 2);
+
+	/* bits[7:4]        SQ_THRESH       = 0x7 */
+	regVal &= ~(0xf << 4);
+	regVal |= (0x7 << 4);
+
+	/* bits[16:15]      REG_SQ_LENGTH   = 0x1 */
+	regVal &= ~(0x3 << 15);
+	regVal |= (0x1 << 15);
+
+	/* bit[21]  CDR_FASTLOCK_EN = 0x0 */
+	regVal &= ~(0x1 << 21);
+
+	/* bits[27:26]      EDGE_DET        = 0x0 (1 Tran) */
+	regVal &= ~(0x3 << 26);
+
+	MV_REG_WRITE(MV_USB_PHY_RX_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+	/******* USB PHY IVREF Control Register 0x440 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_IVREF_CTRL_REG(dev));
+
+	/* bits[9:8]    TXVDD12 = 0x3 */
+	regVal &= ~(0x3 << 8);
+	regVal |= (0x3 << 8);
+
+	MV_REG_WRITE(MV_USB_PHY_IVREF_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /***** USB PHY TEST GROUP CONTROL Register: 0x450 *****/
+	regVal = MV_REG_READ(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev));
+
+	/* bit[15]  REG_FIFO_SQ_RST = 0x0 */
+	regVal &= ~(0x1 << 15);
+
+	MV_REG_WRITE(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev), regVal);
+    /*-------------------------------------------------*/
+}
+
+/* USB Phy init (change from defaults) specific for 90nm (6183 and later) */
+static void mvUsbPhy90nmInit(int dev)
+{
+	MV_U32 regVal;
+
+    /******* USB 2.0 Power Control Register 0x400 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev));
+
+	/* Bits 7:6 (BG_VSEL) = 0x0 */
+	regVal &= ~(0x3 << 6);
+
+	MV_REG_WRITE(MV_USB_PHY_POWER_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /******* USB PHY PLL Control Register 0x410 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_PLL_CTRL_REG(dev));
+
+	/* bit[21]  (VCOCAL_ START) */
+	regVal |= (0x1 << 21);
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+
+	/* Wait 500 usec */
+	mvOsUDelay(500);
+
+	regVal &= ~(0x1 << 21);
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /******* USB PHY Tx Control Register Register 0x420 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_TX_CTRL_REG(dev));
+
+	/* bit[21]  (TX_BLK_EN) = 0 for B0 only */
+	if ((usbHalData.ctrlModel == MV_6183_DEV_ID))
+		regVal &= ~(0x1 << 21);
+
+	/* Force Auto calibration */
+	/* Bit[13] = 0x1, (REG_EXT_RCAL_EN = 0x1) */
+	regVal |= (0x1 << 13);
+
+	/* bit[11]  (LOWVDD_EN)     = 1 */
+	regVal |= (0x1 << 11);
+
+	/* Bit[6:3] (IMP_CAL) = 0x8 for A0 and B0 */
+	/* Bit[6:3] (IMP_CAL) = 0xf for A1 */
+	regVal &= ~(0xf << 3);
+	regVal |= (0x8 << 3);
+
+	if ((usbHalData.ctrlModel == MV_6183_DEV_ID)) {
+		regVal &= ~(0x7);
+		regVal |= (0x4);
+	}
+
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+	/* Wait 500 usec */
+	mvOsUDelay(500);
+    /*-------------------------------------------------*/
+
+    /******* USB PHY Rx Control Register 0x430 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_RX_CTRL_REG(dev));
+
+	/* bits[3:2]        LPF_COEF        = 0x0 */
+	regVal &= ~(0x3 << 2);
+
+	/* bits[7:4]        SQ_THRESH       = 0x0 */
+	/* bits[7:4]        SQ_THRESH = 0x3 for A1 and above */
+	regVal &= ~(0xf << 4);
+
+	/* bits[16:15]      REG_SQ_LENGTH   = 0x1 */
+	regVal &= ~(0x3 << 15);
+	regVal |= (0x1 << 15);
+
+	/* bit[21]  CDR_FASTLOCK_EN = 0x0 */
+	regVal &= ~(0x1 << 21);
+
+	/* bits[27:26]      EDGE_DET_SEL    = 0x0 */
+	regVal &= ~(0x3 << 26);
+
+	MV_REG_WRITE(MV_USB_PHY_RX_CTRL_REG(dev), regVal);
+	/*-------------------------------------------------*/
+
+    /******* USB PHY IVREF Control Register 0x440 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_IVREF_CTRL_REG(dev));
+
+	/* bits[7:6]        RXVDD18             = 0x0 */
+	regVal &= ~(0x3 << 6);
+
+	/* bits[11] SQ_CM_SEL = 0x1 for 6183 B0 only */
+	if ((usbHalData.ctrlModel == MV_6183_DEV_ID))
+		regVal |= (0x1 << 11);
+
+	/* bit[24]      REG_TEST_SUSPENDM   = 0x1 */
+	regVal |= (0x1 << 24);
+
+	MV_REG_WRITE(MV_USB_PHY_IVREF_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+    /***** USB PHY TEST GROUP CONTROL Register: 0x450 *****/
+	regVal = MV_REG_READ(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev));
+
+	/* bit[15]  REG_FIFO_SQ_RST = 0x0 */
+	regVal &= ~(0x1 << 15);
+
+	MV_REG_WRITE(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev), regVal);
+    /*-------------------------------------------------*/
+}
+
+/* USB Phy init (change from defaults) for 150nm chips:
+ *  - 645xx, 646xx
+ *  - 51xx, 52xx
+ *  - 6082
+ */
+static void mvUsbPhyInit(int dev)
+{
+	MV_U32 regVal;
+
+	/* GL# USB-9 */
+	/******* USB 2.0 Power Control Register 0x400 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev));
+
+	/* Bits 7:6 (BG_VSEL) = 0x1 */
+	regVal &= ~(0x3 << 6);
+	regVal |= (0x1 << 6);
+
+	MV_REG_WRITE(MV_USB_PHY_POWER_CTRL_REG(dev), regVal);
+
+	/******* USB PHY PLL Control Register 0x410 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_PLL_CTRL_REG(dev));
+
+	/* bit[21]  (VCOCAL_ START) */
+	regVal |= (0x1 << 21);
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+
+	/* Wait 500 usec */
+	mvOsUDelay(500);
+
+	regVal &= ~(0x1 << 21);
+	MV_REG_WRITE(MV_USB_PHY_PLL_CTRL_REG(dev), regVal);
+    /*-------------------------------------------------*/
+
+	/* GL# USB-1 */
+    /******* USB PHY Tx Control Register Register 0x420 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_TX_CTRL_REG(dev));
+
+	if ((usbHalData.ctrlModel == MV_5181_DEV_ID) && (usbHalData.ctrlRev <= MV_5181_A1_REV)) {
+		/* For OrionI A1/A0 rev:  Bit[21] = 0 (TXDATA_BLOCK_EN  = 0). */
+		regVal &= ~(1 << 21);
+	} else {
+		regVal |= (1 << 21);
+	}
+
+	/* Force Auto calibration */
+
+	/* Bit[13] = 0x1, (REG_EXT_RCAL_EN = 0x1) */
+	regVal |= (1 << 13);
+
+	/* Bits[2:0] (TxAmp)
+	 *      64560, 64660, 6082, 5181, 5182, etc = 0x4
+	 *      5281                                = 0x3
+	 */
+	if (usbHalData.ctrlModel == MV_5281_DEV_ID) {
+		regVal &= ~(0x7 << 0);
+		regVal |= (0x3 << 0);
+	} else {
+		regVal &= ~(0x7 << 0);
+		regVal |= (0x4 << 0);
+	}
+
+	/* Bit[6:3] (IMP_CAL)
+	 *      64560, 64660 = 0xA
+	 *      Others       = 0x8
+	 *
+	 */
+	regVal &= ~(0xf << 3);
+	if ((usbHalData.ctrlModel == MV64560_DEV_ID) || (usbHalData.ctrlModel == MV64660_DEV_ID))
+		regVal |= (0xA << 3);
+	else
+		regVal |= (0x8 << 3);
+
+	MV_REG_WRITE(MV_USB_PHY_TX_CTRL_REG(dev), regVal);
+	mvOsUDelay(500);
+
+	/* GL# USB-3 GL# USB-9 */
+	/******* USB PHY Rx Control Register 0x430 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_RX_CTRL_REG(dev));
+
+	/* bit[8:9] - (DISCON_THRESHOLD ). */
+	/* 88F5181-A0/A1/B0 = 11, 88F5281-A0 = 10, all other 00 */
+	/* 64660-A0 = 10 */
+	regVal &= ~(0x3 << 8);
+	if ((usbHalData.ctrlModel == MV_5181_DEV_ID) && (usbHalData.ctrlRev <= MV_5181_B0_REV))
+		regVal |= (0x3 << 8);
+	else if (usbHalData.ctrlModel == MV64660_DEV_ID)
+		regVal |= (0x2 << 8);
+
+	/* bit[21] = 0 (CDR_FASTLOCK_EN = 0). */
+	regVal &= ~(1 << 21);
+
+	/* bit[27:26] = 00 ( EDGE_DET_SEL = 00). */
+	regVal &= ~(0x3 << 26);
+
+	/* Bits[31:30] = RXDATA_BLOCK_LENGHT = 0x3 */
+	regVal |= (0x3 << 30);
+
+	/* Bits 7:4 (SQ_THRESH)
+	 *      64560, 64660                = 0x1
+	 *      5181, 5182, 5281, 6082, etc = 0x0
+	 */
+	regVal &= ~(0xf << 4);
+	if ((usbHalData.ctrlModel == MV64560_DEV_ID) || (usbHalData.ctrlModel == MV64660_DEV_ID))
+		regVal |= (0x1 << 4);
+	else
+		regVal |= (0x3 << 4);
+
+	MV_REG_WRITE(MV_USB_PHY_RX_CTRL_REG(dev), regVal);
+
+	/* GL# USB-3 GL# USB-9 */
+    /******* USB PHY IVREF Control Register 0x440 *******/
+	regVal = MV_REG_READ(MV_USB_PHY_IVREF_CTRL_REG(dev));
+
+	/*Bits[1:0] = 0x2 (PLLVDD12 = 0x2) */
+	regVal &= ~(0x3 << 0);
+	regVal |= (0x2 << 0);
+
+	/* Bits 5:4 (RXVDD) = 0x3; */
+	regVal &= ~(0x3 << 4);
+	regVal |= (0x3 << 4);
+
+	/* <VPLLCAL> bits[17:16] = 0x1 */
+	if ((usbHalData.ctrlModel == MV64560_DEV_ID) || (usbHalData.ctrlModel == MV64660_DEV_ID)) {
+		regVal &= ~(0x3 << 16);
+		regVal |= (0x1 << 16);
+	}
+
+	/* <ISAMPLE_SEL> bits[19:18] = 0x2 */
+	regVal &= ~(0x3 << 18);
+	regVal |= (0x2 << 18);
+
+	/* <SAMPLER_CTRL> bit[20] = 0x0 */
+	regVal &= ~(0x1 << 20);
+
+	/* <ICHGPBUF_SEL> bit[21] = 0x1 */
+	regVal |= (0x1 << 21);
+
+	MV_REG_WRITE(MV_USB_PHY_IVREF_CTRL_REG(dev), regVal);
+
+	/***** USB PHY TEST GROUP CONTROL Register: 0x450 *****/
+	regVal = MV_REG_READ(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev));
+
+	/* bit[15] = 0 (REG_FIFO_SQ_RST = 0). */
+	regVal &= ~(1 << 15);
+
+	/* <REG_FIFO_OVUF_SEL> bit[17] = 0x1 */
+	if ((usbHalData.ctrlModel == MV64560_DEV_ID) || (usbHalData.ctrlModel == MV64660_DEV_ID))
+		regVal |= (1 << 17);
+
+	MV_REG_WRITE(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev), regVal);
+}
+
+/*******************************************************************************
+* mvUsbHalInit - Initialize USB engine
+*
+* DESCRIPTION:
+*       This function initialize USB unit. It set the default address decode
+*       windows of the unit.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if setting fail.
+*******************************************************************************/
+MV_STATUS mvUsbHalInit(int dev, MV_BOOL isHost, MV_USB_HAL_DATA *halData)
+{
+	MV_U32 regVal;
+
+	mvOsMemcpy(&usbHalData, halData, sizeof(MV_USB_HAL_DATA));
+
+	/* Wait 100 usec */
+	mvOsUDelay(100);
+
+	/* Clear Interrupt Cause and Mask registers */
+	MV_REG_WRITE(MV_USB_BRIDGE_INTR_CAUSE_REG(dev), 0);
+	MV_REG_WRITE(MV_USB_BRIDGE_INTR_MASK_REG(dev), 0);
+
+	/* Reset controller */
+	regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev));
+	MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal | MV_USB_CORE_CMD_RESET_MASK);
+	while (MV_REG_READ(MV_USB_CORE_CMD_REG(dev)) & MV_USB_CORE_CMD_RESET_MASK)
+		;
+
+	/* Clear bit 4 in USB bridge control register for enableing core byte swap */
+	if ((usbHalData.ctrlModel == MV64560_DEV_ID) || (usbHalData.ctrlModel == MV64660_DEV_ID)) {
+		MV_REG_WRITE(MV_USB_BRIDGE_CTRL_REG(dev), (MV_REG_READ(MV_USB_BRIDGE_CTRL_REG(dev))
+							   & ~MV_USB_BRIDGE_CORE_BYTE_SWAP_MASK));
+	}
+
+	/* GL# USB-10 */
+	/* The new register 0x360 USB 2.0 IPG Metal Fix Register
+	 * dont' exists in the following chip revisions:
+	 * OrionN B1 (id=0x5180, rev 3)
+	 * Orion1 B1 (id=0x5181, rev=3) and before
+	 * Orion1-VoIP A0 (id=0x5181, rev=8)
+	 * Orion1-NAS A1 (id=0x5182, rev=1) and before
+	 * Orion2 B0 (id=0x5281, rev=1) and before
+	 */
+	if (((usbHalData.ctrlModel == MV_5181_DEV_ID) &&
+	     ((usbHalData.ctrlRev <= MV_5181_B1_REV) || (usbHalData.ctrlRev == MV_5181L_A0_REV))) ||
+	    ((usbHalData.ctrlModel == MV_5182_DEV_ID) &&
+	     (usbHalData.ctrlRev <= MV_5182_A1_REV)) ||
+	    ((usbHalData.ctrlModel == MV_5180_DEV_ID) && (usbHalData.ctrlRev <= MV_5180N_B1_REV))) {
+		/* Do nothing */
+	} else if ((usbHalData.ctrlModel == MV_6510_DEV_ID) ||
+		   (usbHalData.ctrlModel == MV_6530_DEV_ID) ||
+		   (usbHalData.ctrlModel == MV_6550_DEV_ID) || (usbHalData.ctrlModel == MV_6560_DEV_ID)) {
+		/* Change value of new register 0x360 */
+		regVal = MV_REG_READ(MV_USB_BRIDGE_IPG_REG(dev));
+#if 0
+		/*  Change bits31 & bit30 from 1 to 0 */
+		regVal &= ~(0x3 << 30);
+#endif
+		/*  Change bits[14:8] - IPG for non Start of Frame Packets
+		 *  from 0x9(default) to 0xD
+		 */
+		regVal &= ~(0x7F << 8);
+		regVal |= (0xD << 8);
+
+		MV_REG_WRITE(MV_USB_BRIDGE_IPG_REG(dev), regVal);
+	} else {
+		/* Change value of new register 0x360 */
+		regVal = MV_REG_READ(MV_USB_BRIDGE_IPG_REG(dev));
+
+		/*  Change bits[14:8] - IPG for non Start of Frame Packets
+		 *  from 0x9(default) to 0xD
+		 */
+		regVal &= ~(0x7F << 8);
+		regVal |= (0xD << 8);
+
+		MV_REG_WRITE(MV_USB_BRIDGE_IPG_REG(dev), regVal);
+	}
+#ifndef MV_USB_PHY_DONT_OVERRIDE
+
+    /********* Update USB PHY configuration **********/
+	if ((usbHalData.ctrlModel == MV_78100_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_78200_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_76100_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6281_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6282_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6280_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6192_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6190_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6180_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6321_DEV_ID) ||
+	    (usbHalData.ctrlModel == MV_6322_DEV_ID) || (usbHalData.ctrlModel == MV_6323_DEV_ID)) {
+		mvUsbPhy65nmNewInit(dev);
+	} else if ((usbHalData.ctrlModel == MV_78XX0_DEV_ID)) {
+		mvUsbPhy65nmInit(dev);
+	} else if (usbHalData.ctrlModel == MV_6183_DEV_ID) {
+		mvUsbPhy90nmInit(dev);
+	} else if ((usbHalData.ctrlModel == MV_6510_DEV_ID) ||
+		   (usbHalData.ctrlModel == MV_6530_DEV_ID) ||
+		   (usbHalData.ctrlModel == MV_6550_DEV_ID) || (usbHalData.ctrlModel == MV_6560_DEV_ID)) {
+		mvUsbPhy65nmNewInit(dev);
+/* 	mvUsbPhyKW6500Init(dev); */
+	} else {
+		mvUsbPhyInit(dev);
+	}
+#endif
+	/* Set Mode register (Stop and Reset USB Core before) */
+	/* Stop the controller */
+	regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev));
+	regVal &= ~MV_USB_CORE_CMD_RUN_MASK;
+	MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal);
+
+	/* Reset the controller to get default values */
+	regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev));
+	regVal |= MV_USB_CORE_CMD_RESET_MASK;
+	MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal);
+
+	/* Wait for the controller reset to complete */
+	do {
+		regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev));
+	} while (regVal & MV_USB_CORE_CMD_RESET_MASK);
+
+	/* Set USB_MODE register */
+	if (isHost)
+		regVal = MV_USB_CORE_MODE_HOST;
+	else
+		regVal = MV_USB_CORE_MODE_DEVICE | MV_USB_CORE_SETUP_LOCK_DISABLE_MASK;
+
+#if (MV_USB_VERSION == 0)
+	regVal |= MV_USB_CORE_STREAM_DISABLE_MASK;
+#endif
+
+	MV_REG_WRITE(MV_USB_CORE_MODE_REG(dev), regVal);
+
+	return MV_OK;
+}
+
+void mvUsbPowerDown(int dev)
+{
+	MV_U32 regVal;
+
+	/* Stop USB Controller core */
+	regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev));
+	if (regVal & MV_USB_CORE_CMD_RUN_MASK) {
+		mvOsPrintf("USB #%d:  Warning USB core was not disabled\n", dev);
+		regVal &= ~MV_USB_CORE_CMD_RUN_MASK;
+		MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal);
+	}
+
+	/* Power Down USB PHY */
+	regVal = MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev));
+	regVal &= ~(MV_USB_PHY_POWER_UP_MASK | MV_USB_PHY_PLL_POWER_UP_MASK);
+
+	MV_REG_WRITE(MV_USB_PHY_POWER_CTRL_REG(dev), regVal);
+}
+
+void mvUsbPowerUp(int dev)
+{
+	MV_U32 regVal;
+
+	/* Power Up USB PHY */
+	regVal = MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev));
+	regVal |= (MV_USB_PHY_POWER_UP_MASK | MV_USB_PHY_PLL_POWER_UP_MASK);
+
+	MV_REG_WRITE(MV_USB_PHY_POWER_CTRL_REG(dev), regVal);
+
+	/* Start USB core */
+	regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev));
+	if (regVal & MV_USB_CORE_CMD_RUN_MASK) {
+		mvOsPrintf("USB #%d:  Warning USB core is enabled\n", dev);
+	} else {
+		regVal |= MV_USB_CORE_CMD_RUN_MASK;
+		MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal);
+	}
+}
+
+void mvUsbRegs(int dev)
+{
+	mvOsPrintf("\n\tUSB-%d Bridge Registers\n\n", dev);
+
+	mvOsPrintf("MV_USB_BRIDGE_CTRL_REG          : 0x%X = 0x%08x\n",
+		   MV_USB_BRIDGE_CTRL_REG(dev), MV_REG_READ(MV_USB_BRIDGE_CTRL_REG(dev)));
+
+	mvOsPrintf("MV_USB_BRIDGE_INTR_MASK_REG     : 0x%X = 0x%08x\n",
+		   MV_USB_BRIDGE_INTR_MASK_REG(dev), MV_REG_READ(MV_USB_BRIDGE_INTR_MASK_REG(dev)));
+
+	mvOsPrintf("MV_USB_BRIDGE_INTR_CAUSE_REG    : 0x%X = 0x%08x\n",
+		   MV_USB_BRIDGE_INTR_CAUSE_REG(dev), MV_REG_READ(MV_USB_BRIDGE_INTR_CAUSE_REG(dev)));
+
+	mvOsPrintf("MV_USB_BRIDGE_ERROR_ADDR_REG    : 0x%X = 0x%08x\n",
+		   MV_USB_BRIDGE_ERROR_ADDR_REG(dev), MV_REG_READ(MV_USB_BRIDGE_ERROR_ADDR_REG(dev)));
+
+	mvOsPrintf("\n\tUSB-%d PHY Registers\n\n", dev);
+
+	mvOsPrintf("MV_USB_PHY_POWER_CTRL_REG       : 0x%X = 0x%08x\n",
+		   MV_USB_PHY_POWER_CTRL_REG(dev), MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev)));
+
+	mvOsPrintf("MV_USB_PHY_TX_CTRL_REG          : 0x%X = 0x%08x\n",
+		   MV_USB_PHY_TX_CTRL_REG(dev), MV_REG_READ(MV_USB_PHY_TX_CTRL_REG(dev)));
+	mvOsPrintf("MV_USB_PHY_RX_CTRL_REG          : 0x%X = 0x%08x\n",
+		   MV_USB_PHY_RX_CTRL_REG(dev), MV_REG_READ(MV_USB_PHY_RX_CTRL_REG(dev)));
+	mvOsPrintf("MV_USB_PHY_IVREF_CTRL_REG       : 0x%X = 0x%08x\n",
+		   MV_USB_PHY_IVREF_CTRL_REG(dev), MV_REG_READ(MV_USB_PHY_IVREF_CTRL_REG(dev)));
+
+	mvOsPrintf("\n");
+
+}
+
+void mvUsbCoreRegs(int dev, MV_BOOL isHost)
+{
+	mvOsPrintf("\n\t USB-%d Core %s Registers\n\n", dev, isHost ? "HOST" : "DEVICE");
+
+	mvOsPrintf("MV_USB_CORE_ID_REG                  : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_ID_REG(dev), MV_REG_READ(MV_USB_CORE_ID_REG(dev)));
+
+	mvOsPrintf("MV_USB_CORE_GENERAL_REG             : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_GENERAL_REG(dev), MV_REG_READ(MV_USB_CORE_GENERAL_REG(dev)));
+
+	if (isHost) {
+		mvOsPrintf("MV_USB_CORE_HOST_REG                : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_HOST_REG(dev), MV_REG_READ(MV_USB_CORE_HOST_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_TTTX_BUF_REG            : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_TTTX_BUF_REG(dev), MV_REG_READ(MV_USB_CORE_TTTX_BUF_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_TTRX_BUF_REG            : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_TTRX_BUF_REG(dev), MV_REG_READ(MV_USB_CORE_TTRX_BUF_REG(dev)));
+	} else {
+		mvOsPrintf("MV_USB_CORE_DEVICE_REG              : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_DEVICE_REG(dev), MV_REG_READ(MV_USB_CORE_DEVICE_REG(dev)));
+	}
+
+	mvOsPrintf("MV_USB_CORE_TX_BUF_REG              : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_TX_BUF_REG(dev), MV_REG_READ(MV_USB_CORE_TX_BUF_REG(dev)));
+
+	mvOsPrintf("MV_USB_CORE_RX_BUF_REG              : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_RX_BUF_REG(dev), MV_REG_READ(MV_USB_CORE_RX_BUF_REG(dev)));
+
+	mvOsPrintf("MV_USB_CORE_CAP_LENGTH_REG          : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_CAP_LENGTH_REG(dev), MV_REG_READ(MV_USB_CORE_CAP_LENGTH_REG(dev)));
+
+	if (isHost) {
+		mvOsPrintf("MV_USB_CORE_CAP_HCS_PARAMS_REG      : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_CAP_HCS_PARAMS_REG(dev), MV_REG_READ(MV_USB_CORE_CAP_HCS_PARAMS_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_CAP_HCC_PARAMS_REG      : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_CAP_HCC_PARAMS_REG(dev), MV_REG_READ(MV_USB_CORE_CAP_HCC_PARAMS_REG(dev)));
+	} else {
+		mvOsPrintf("MV_USB_CORE_CAP_DCI_VERSION_REG     : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_CAP_DCI_VERSION_REG(dev), MV_REG_READ(MV_USB_CORE_CAP_DCI_VERSION_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_CAP_DCC_PARAMS_REG      : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_CAP_DCC_PARAMS_REG(dev), MV_REG_READ(MV_USB_CORE_CAP_DCC_PARAMS_REG(dev)));
+	}
+
+	mvOsPrintf("MV_USB_CORE_CMD_REG                 : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_CMD_REG(dev), MV_REG_READ(MV_USB_CORE_CMD_REG(dev)));
+
+	mvOsPrintf("MV_USB_CORE_STATUS_REG              : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_STATUS_REG(dev), MV_REG_READ(MV_USB_CORE_STATUS_REG(dev)));
+
+	mvOsPrintf("MV_USB_CORE_INTR_REG                : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_INTR_REG(dev), MV_REG_READ(MV_USB_CORE_INTR_REG(dev)));
+
+	mvOsPrintf("MV_USB_CORE_FRAME_INDEX_REG         : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_FRAME_INDEX_REG(dev), MV_REG_READ(MV_USB_CORE_FRAME_INDEX_REG(dev)));
+
+	mvOsPrintf("MV_USB_CORE_MODE_REG                : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_MODE_REG(dev), MV_REG_READ(MV_USB_CORE_MODE_REG(dev)));
+
+	if (isHost) {
+		mvOsPrintf("MV_USB_CORE_PERIODIC_LIST_BASE_REG  : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_PERIODIC_LIST_BASE_REG(dev),
+			   MV_REG_READ(MV_USB_CORE_PERIODIC_LIST_BASE_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_ASYNC_LIST_ADDR_REG     : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_ASYNC_LIST_ADDR_REG(dev), MV_REG_READ(MV_USB_CORE_ASYNC_LIST_ADDR_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_CONFIG_FLAG_REG         : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_CONFIG_FLAG_REG(dev), MV_REG_READ(MV_USB_CORE_CONFIG_FLAG_REG(dev)));
+	} else {
+		int numEp, ep;
+		MV_U32 epCtrlVal;
+
+		mvOsPrintf("MV_USB_CORE_DEV_ADDR_REG            : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_DEV_ADDR_REG(dev), MV_REG_READ(MV_USB_CORE_DEV_ADDR_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_ENDPOINT_LIST_ADDR_REG  : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_ENDPOINT_LIST_ADDR_REG(dev),
+			   MV_REG_READ(MV_USB_CORE_ENDPOINT_LIST_ADDR_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_ENDPT_SETUP_STAT_REG    : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_ENDPT_SETUP_STAT_REG(dev), MV_REG_READ(MV_USB_CORE_ENDPT_SETUP_STAT_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_ENDPT_PRIME_REG         : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_ENDPT_PRIME_REG(dev), MV_REG_READ(MV_USB_CORE_ENDPT_PRIME_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_ENDPT_FLUSH_REG         : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_ENDPT_FLUSH_REG(dev), MV_REG_READ(MV_USB_CORE_ENDPT_FLUSH_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_ENDPT_STATUS_REG        : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_ENDPT_STATUS_REG(dev), MV_REG_READ(MV_USB_CORE_ENDPT_STATUS_REG(dev)));
+
+		mvOsPrintf("MV_USB_CORE_ENDPT_COMPLETE_REG      : 0x%X = 0x%08x\n",
+			   MV_USB_CORE_ENDPT_COMPLETE_REG(dev), MV_REG_READ(MV_USB_CORE_ENDPT_COMPLETE_REG(dev)));
+
+		numEp = MV_REG_READ(MV_USB_CORE_CAP_DCC_PARAMS_REG(dev)) & 0x1F;
+
+		for (ep = 0; ep < numEp; ep++) {
+			epCtrlVal = MV_REG_READ(MV_USB_CORE_ENDPT_CTRL_REG(dev, ep));
+			if (epCtrlVal == 0)
+				continue;
+
+			mvOsPrintf("MV_USB_CORE_ENDPT_CTRL_REG[%02d]      : 0x%X = 0x%08x\n",
+				   ep, MV_USB_CORE_ENDPT_CTRL_REG(dev, ep), epCtrlVal);
+		}
+	}
+
+	mvOsPrintf("MV_USB_CORE_PORTSC_REG              : 0x%X = 0x%08x\n",
+		   MV_USB_CORE_PORTSC_REG(dev), MV_REG_READ(MV_USB_CORE_PORTSC_REG(dev)));
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/mvUsb.h b/arch/arm/plat-feroceon/mv_hal/usb/mvUsb.h
new file mode 100755
index 0000000..f3c1b4a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/mvUsb.h
@@ -0,0 +1,105 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __mvUsb_h__
+#define __mvUsb_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysUsbConfig.h"
+
+typedef struct {
+	MV_U16		ctrlModel;
+	MV_U8		ctrlRev;
+} MV_USB_HAL_DATA;
+
+/* Functions */
+MV_STATUS   mvUsbHalInit(int dev, MV_BOOL isHost, MV_USB_HAL_DATA *halData);
+MV_U32      mvUsbGetCapRegAddr(int devNo);
+void        mvUsbDevResetComplete(int devNo);
+
+#ifdef MV_USB_VOLTAGE_FIX
+MV_U8       mvUsbGppInit(int dev);
+int         mvUsbBackVoltageUpdate(int dev, MV_U8 gppNo);
+#endif /* MV_USB_VOLTAGE_FIX */
+
+/* Power management routines */
+void        mvUsbPowerDown(int port);
+void        mvUsbPowerUp(int port);
+
+void        mvUsbRegs(int dev);
+void        mvUsbCoreRegs(int dev, MV_BOOL isHost);
+
+MV_STATUS   mvUsbWinInit(MV_U32 dev, MV_UNIT_WIN_INFO *addrWinMap);
+MV_STATUS   mvUsbWinRead(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin);
+MV_STATUS   mvUsbWinWrite(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __mvUsb_h__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/mvUsbAddrDec.c b/arch/arm/plat-feroceon/mv_hal/usb/mvUsbAddrDec.c
new file mode 100755
index 0000000..c1d3d0b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/mvUsbAddrDec.c
@@ -0,0 +1,315 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvUsbRegs.h"
+#include "mvUsb.h"
+
+MV_TARGET usbAddrDecPrioTab[] = {
+#if defined(MV_INCLUDE_SDRAM_CS0)
+	SDRAM_CS0,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS1)
+	SDRAM_CS1,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS2)
+	SDRAM_CS2,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS3)
+	SDRAM_CS3,
+#endif
+#if defined(MV_INCLUDE_CESA) && defined(USB_UNDERRUN_WA)
+	CRYPT_ENG,
+#endif
+#if defined(MV_INCLUDE_PEX)
+#if defined(MV_INCLUDE_PEX0)
+	PEX0_MEM,
+#endif
+#if defined(MV_INCLUDE_PEX1)
+	PEX1_MEM,
+#endif
+#endif
+	TBL_TERM
+};
+
+/*******************************************************************************
+* usbWinOverlapDetect - Detect USB address windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviur is expected in case USB address decode
+*       windows overlapps.
+*       This function detects USB address decode windows overlapping of a
+*       specified window. The function does not check the window itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS usbWinOverlapDetect(MV_U32 dev, MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 winNumIndex;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	for (winNumIndex = 0; winNumIndex < MV_USB_MAX_ADDR_DECODE_WIN; winNumIndex++) {
+		/* Do not check window itself       */
+		if (winNumIndex == winNum)
+			continue;
+
+		/* Get window parameters    */
+		if (MV_OK != mvUsbWinRead(dev, winNumIndex, &addrDecWin)) {
+			mvOsPrintf("%s: ERR. TargetWinGet failed\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled windows    */
+		if (addrDecWin.enable == MV_FALSE)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+			return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
+/*******************************************************************************
+* mvUsbWinWrite - Set USB target address window
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0)
+*       address window, also known as address decode window.
+*       After setting this target window, the USB will be able to access the
+*       target within the address window.
+*
+* INPUT:
+*       winNum      - USB target address decode window number.
+*       pAddrDecWin - USB target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if address window overlapps with other address decode windows.
+*       MV_BAD_PARAM if base address is invalid parameter or target is
+*       unknown.
+*
+*******************************************************************************/
+MV_STATUS mvUsbWinWrite(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+	MV_U32 size;
+
+	/* Parameter checking   */
+	if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN) {
+		mvOsPrintf("%s: ERR. Invalid win num %d\n", __func__, winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlapps with current windows         */
+	if (MV_TRUE == usbWinOverlapDetect(dev, winNum, &pDecWin->addrWin)) {
+		mvOsPrintf("%s: ERR. Window %d overlap\n", __func__, winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) {
+		mvOsPrintf("mvUsbWinWrite:Error setting USB window %d.\n"
+			   "Address 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pDecWin->addrWin.baseLow, pDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	if (!MV_IS_POWER_OF_2(pDecWin->addrWin.size)) {
+		mvOsPrintf("mvUsbWinWrite: Bad windows size.\n");
+		return MV_BAD_PARAM;
+	}
+
+	size = pDecWin->addrWin.size / MV_USB_WIN_SIZE_ALIGN - 1;
+
+	/* set Size, Attributes and TargetID */
+	sizeReg = (((pDecWin->targetId << MV_USB_WIN_TARGET_OFFSET) & MV_USB_WIN_TARGET_MASK) |
+		   ((pDecWin->attrib << MV_USB_WIN_ATTR_OFFSET) & MV_USB_WIN_ATTR_MASK) |
+		   ((size << MV_USB_WIN_SIZE_OFFSET) & MV_USB_WIN_SIZE_MASK));
+
+#if defined(MV645xx) || defined(MV646xx)
+	/* If window is DRAM with HW cache coherency, make sure bit2 is set */
+	sizeReg &= ~MV_USB_WIN_BURST_WR_LIMIT_MASK;
+
+	if ((MV_TARGET_IS_DRAM(pDecWin->target)) && (pDecWin->addrWinAttr.cachePolicy != NO_COHERENCY))
+		sizeReg |= MV_USB_WIN_BURST_WR_32BIT_LIMIT;
+	else
+		sizeReg |= MV_USB_WIN_BURST_WR_NO_LIMIT;
+
+#endif /* MV645xx || MV646xx */
+
+	if (pDecWin->enable == MV_TRUE)
+		sizeReg |= MV_USB_WIN_ENABLE_MASK;
+	else
+		sizeReg &= ~MV_USB_WIN_ENABLE_MASK;
+
+	/* Update Base value  */
+	baseReg = (pDecWin->addrWin.baseLow & MV_USB_WIN_BASE_MASK);
+
+	MV_REG_WRITE(MV_USB_WIN_CTRL_REG(dev, winNum), sizeReg);
+	MV_REG_WRITE(MV_USB_WIN_BASE_REG(dev, winNum), baseReg);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvUsbWinRead - Get USB peripheral target address window.
+*
+* DESCRIPTION:
+*       Get USB peripheral target address window.
+*
+* INPUT:
+*       winNum - USB target address decode window number.
+*
+* OUTPUT:
+*       pDecWin - USB target window data structure.
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvUsbWinRead(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+
+	/* Parameter checking   */
+	if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN) {
+		mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", __func__, dev, winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	baseReg = MV_REG_READ(MV_USB_WIN_BASE_REG(dev, winNum));
+	sizeReg = MV_REG_READ(MV_USB_WIN_CTRL_REG(dev, winNum));
+
+	/* Check if window is enabled   */
+	if (sizeReg & MV_USB_WIN_ENABLE_MASK) {
+		pDecWin->enable = MV_TRUE;
+
+		/* Extract window parameters from registers */
+		pDecWin->targetId = (sizeReg & MV_USB_WIN_TARGET_MASK) >> MV_USB_WIN_TARGET_OFFSET;
+		pDecWin->attrib = (sizeReg & MV_USB_WIN_ATTR_MASK) >> MV_USB_WIN_ATTR_OFFSET;
+		pDecWin->addrWin.size = (sizeReg & MV_USB_WIN_SIZE_MASK) >> MV_USB_WIN_SIZE_OFFSET;
+		pDecWin->addrWin.size = (pDecWin->addrWin.size + 1) * MV_USB_WIN_SIZE_ALIGN;
+		pDecWin->addrWin.baseLow = (baseReg & MV_USB_WIN_BASE_MASK);
+		pDecWin->addrWin.baseHigh = 0;
+	} else {
+		pDecWin->enable = MV_FALSE;
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvUsbWinInit -
+*
+* INPUT:
+*
+* OUTPUT:
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvUsbWinInit(MV_U32 dev, MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_UNIT_WIN_INFO *addrDecWin;
+	MV_U32 winNum;
+	MV_U32 winPrioIndex = 0;
+
+	/* First disable all address decode windows */
+	for (winNum = 0; winNum < MV_USB_MAX_ADDR_DECODE_WIN; winNum++)
+		MV_REG_BIT_RESET(MV_USB_WIN_CTRL_REG(dev, winNum), MV_USB_WIN_ENABLE_MASK);
+
+	/* Go through all windows in user table until table terminator          */
+	winNum = 0;
+	while ((usbAddrDecPrioTab[winPrioIndex] != TBL_TERM) && (winNum < MV_USB_MAX_ADDR_DECODE_WIN)) {
+		addrDecWin = &addrWinMap[usbAddrDecPrioTab[winPrioIndex]];
+		if (addrDecWin->enable == MV_TRUE) {
+#if defined(MV645xx) || defined(MV646xx)
+			/* Get the default attributes for that target window */
+			mvCtrlDefAttribGet(usbWin.target, &usbWin.addrWinAttr);
+#endif /* MV645xx || MV646xx */
+
+			if (MV_OK != mvUsbWinWrite(dev, winNum, addrDecWin))
+				return MV_ERROR;
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/usb/mvUsbRegs.h b/arch/arm/plat-feroceon/mv_hal/usb/mvUsbRegs.h
new file mode 100755
index 0000000..616d2db
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/usb/mvUsbRegs.h
@@ -0,0 +1,226 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvUsbRegsh
+#define __INCmvUsbRegsh
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "mvSysUsbConfig.h"
+
+/*******************************************/
+/* USB ARC Core Registers                  */
+/*******************************************/
+#define MV_USB_CORE_ID_REG(dev)                 (MV_USB_REGS_BASE(dev) + 0x00)
+#define MV_USB_CORE_GENERAL_REG(dev)            (MV_USB_REGS_BASE(dev) + 0x04)
+#define MV_USB_CORE_HOST_REG(dev)               (MV_USB_REGS_BASE(dev) + 0x08)
+#define MV_USB_CORE_DEVICE_REG(dev)             (MV_USB_REGS_BASE(dev) + 0x0C)
+#define MV_USB_CORE_TX_BUF_REG(dev)             (MV_USB_REGS_BASE(dev) + 0x10)
+#define MV_USB_CORE_RX_BUF_REG(dev)             (MV_USB_REGS_BASE(dev) + 0x14)
+#define MV_USB_CORE_TTTX_BUF_REG(dev)           (MV_USB_REGS_BASE(dev) + 0x18)
+#define MV_USB_CORE_TTRX_BUF_REG(dev)           (MV_USB_REGS_BASE(dev) + 0x1C)
+
+#define MV_USB_CORE_CAP_LENGTH_REG(dev)         (MV_USB_REGS_BASE(dev) + 0x100)
+#define MV_USB_CORE_CAP_HCS_PARAMS_REG(dev)     (MV_USB_REGS_BASE(dev) + 0x104)
+#define MV_USB_CORE_CAP_HCC_PARAMS_REG(dev)     (MV_USB_REGS_BASE(dev) + 0x108)
+
+#define MV_USB_CORE_CAP_DCI_VERSION_REG(dev)    (MV_USB_REGS_BASE(dev) + 0x120)
+#define MV_USB_CORE_CAP_DCC_PARAMS_REG(dev)     (MV_USB_REGS_BASE(dev) + 0x124)
+
+#define MV_USB_CORE_CMD_REG(dev)                (MV_USB_REGS_BASE(dev) + 0x140)
+
+#define MV_USB_CORE_CMD_RUN_BIT             0
+#define MV_USB_CORE_CMD_RUN_MASK            (1 << MV_USB_CORE_CMD_RUN_BIT)
+
+#define MV_USB_CORE_CMD_RESET_BIT           1
+#define MV_USB_CORE_CMD_RESET_MASK          (1 << MV_USB_CORE_CMD_RESET_BIT)
+
+#define MV_USB_CORE_STATUS_REG(dev)             (MV_USB_REGS_BASE(dev) + 0x144)
+#define MV_USB_CORE_INTR_REG(dev)               (MV_USB_REGS_BASE(dev) + 0x148)
+#define MV_USB_CORE_FRAME_INDEX_REG(dev)        (MV_USB_REGS_BASE(dev) + 0x14C)
+
+#define MV_USB_CORE_PERIODIC_LIST_BASE_REG(dev) (MV_USB_REGS_BASE(dev) + 0x154)
+#define MV_USB_CORE_DEV_ADDR_REG(dev)           (MV_USB_REGS_BASE(dev) + 0x154)
+
+#define MV_USB_CORE_ASYNC_LIST_ADDR_REG(dev)    (MV_USB_REGS_BASE(dev) + 0x158)
+#define MV_USB_CORE_ENDPOINT_LIST_ADDR_REG(dev) (MV_USB_REGS_BASE(dev) + 0x158)
+
+#define MV_USB_CORE_TT_CTRL_REG(dev)            (MV_USB_REGS_BASE(dev) + 0x15C)
+#define MV_USB_CORE_BURST_SIZE_REG(dev)         (MV_USB_REGS_BASE(dev) + 0x160)
+#define MV_USB_CORE_TX_FILL_TUNING_REG(dev)     (MV_USB_REGS_BASE(dev) + 0x164)
+#define MV_USB_CORE_TX_TT_FILL_TUNING_REG(dev)  (MV_USB_REGS_BASE(dev) + 0x168)
+#define MV_USB_CORE_CONFIG_FLAG_REG(dev)        (MV_USB_REGS_BASE(dev) + 0x180)
+#define MV_USB_CORE_PORTSC_REG(dev)             (MV_USB_REGS_BASE(dev) + 0x184)
+#define MV_USB_CORE_OTGSC_REG(dev)              (MV_USB_REGS_BASE(dev) + 0x1A4)
+
+#define MV_USB_CORE_MODE_REG(dev)               (MV_USB_REGS_BASE(dev) + 0x1A8)
+
+#define MV_USB_CORE_MODE_OFFSET                 0
+#define MV_USB_CORE_MODE_MASK                   (3 << MV_USB_CORE_MODE_OFFSET)
+#define MV_USB_CORE_MODE_HOST                   (3 << MV_USB_CORE_MODE_OFFSET)
+#define MV_USB_CORE_MODE_DEVICE                 (2 << MV_USB_CORE_MODE_OFFSET)
+
+/* Bit[2] (ES) - don't care */
+
+#define MV_USB_CORE_SETUP_LOCK_DISABLE_BIT      3
+#define MV_USB_CORE_SETUP_LOCK_DISABLE_MASK     (1 << MV_USB_CORE_SETUP_LOCK_DISABLE_BIT)
+
+#define MV_USB_CORE_STREAM_DISABLE_BIT          4
+#define MV_USB_CORE_STREAM_DISABLE_MASK         (1 << MV_USB_CORE_STREAM_DISABLE_BIT)
+
+
+#define MV_USB_CORE_ENDPT_SETUP_STAT_REG(dev)    (MV_USB_REGS_BASE(dev) + 0x1AC)
+#define MV_USB_CORE_ENDPT_PRIME_REG(dev)         (MV_USB_REGS_BASE(dev) + 0x1B0)
+#define MV_USB_CORE_ENDPT_FLUSH_REG(dev)         (MV_USB_REGS_BASE(dev) + 0x1B4)
+#define MV_USB_CORE_ENDPT_STATUS_REG(dev)        (MV_USB_REGS_BASE(dev) + 0x1B8)
+#define MV_USB_CORE_ENDPT_COMPLETE_REG(dev)      (MV_USB_REGS_BASE(dev) + 0x1BC)
+#define MV_USB_CORE_ENDPT_CTRL_REG(dev, ep)      (MV_USB_REGS_BASE(dev) + 0x1C0 + (ep*4))
+
+/*******************************************/
+/* Interrupt Controller Registers          */
+/*******************************************/
+#define USB_CAUSE_REG(dev)                  (MV_USB_REGS_BASE(dev) + 0x310)
+#define USB_MASK_REG(dev)                   (MV_USB_REGS_BASE(dev) + 0x314)
+#define USB_ERROR_ADDR_REG(dev)             (MV_USB_REGS_BASE(dev) + 0x31c)
+
+#define MV_USB_BRIDGE_INTR_CAUSE_REG(dev)        (MV_USB_REGS_BASE(dev) + 0x310)
+#define MV_USB_BRIDGE_INTR_MASK_REG(dev)         (MV_USB_REGS_BASE(dev) + 0x314)
+
+/*******************************************/
+/* USB Bridge Registers                    */
+/*******************************************/
+
+/* BITs in Bridge Interrupt Cause and Mask registers */
+#define MV_USB_ADDR_DECODE_ERROR_BIT        0
+#define MV_USB_ADDR_DECODE_ERROR_MASK       (1<<MV_USB_ADDR_DECODE_ERROR_BIT)
+
+#define MV_USB_BRIDGE_ERROR_ADDR_REG(dev)        (MV_USB_REGS_BASE(dev) + 0x31C)
+
+#define MV_USB_BRIDGE_CTRL_REG(dev)              (MV_USB_REGS_BASE(dev) + 0x300)
+#define MV_USB_BRIDGE_CORE_BYTE_SWAP_OFFSET 4
+#define MV_USB_BRIDGE_CORE_BYTE_SWAP_MASK   (1 << MV_USB_BRIDGE_CORE_BYTE_SWAP_OFFSET)
+#define MV_USB_BRIDGE_CORE_BYTE_SWAP_EN     (0 << MV_USB_BRIDGE_CORE_BYTE_SWAP_OFFSET)
+
+#define MV_USB_BRIDGE_IPG_REG(dev)          (MV_USB_REGS_BASE(dev) + 0x360)
+
+/*******************************************/
+/* USB PHY Registers                       */
+/*******************************************/
+
+#define MV_USB_PHY_POWER_CTRL_REG(dev)          (MV_USB_REGS_BASE(dev) + 0x400)
+
+#define MV_USB_PHY_POWER_UP_BIT                 0
+#define MV_USB_PHY_POWER_UP_MASK                (1<<MV_USB_PHY_POWER_UP_BIT)
+
+#define MV_USB_PHY_PLL_POWER_UP_BIT             1
+#define MV_USB_PHY_PLL_POWER_UP_MASK            (1<<MV_USB_PHY_PLL_POWER_UP_BIT)
+
+#define MV_USB_PHY_PLL_CTRL_REG(dev)            (MV_USB_REGS_BASE(dev) + 0x410)
+#define MV_USB_PHY_TX_CTRL_REG(dev)             (MV_USB_REGS_BASE(dev) + 0x420)
+#define MV_USB_PHY_RX_CTRL_REG(dev)             (MV_USB_REGS_BASE(dev) + 0x430)
+#define MV_USB_PHY_IVREF_CTRL_REG(dev)          (MV_USB_REGS_BASE(dev) + 0x440)
+#define MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev)   (MV_USB_REGS_BASE(dev) + 0x450)
+#define MV_USB_PHY_TEST_GROUP_CTRL_REG_1(dev)   (MV_USB_REGS_BASE(dev) + 0x454)
+
+
+
+
+/*******************************************/
+/* USB Windows Registers		   */
+/*******************************************/
+#define MV_USB_MAX_ADDR_DECODE_WIN  4
+
+#define MV_USB_WIN_CTRL_REG(dev, win)        (MV_USB_REGS_BASE(dev) + 0x320 + ((win)<<4))
+#define MV_USB_WIN_BASE_REG(dev, win)        (MV_USB_REGS_BASE(dev) + 0x324 + ((win)<<4))
+
+/* BITs in Windows 0-3 Control and Base Registers */
+#define MV_USB_WIN_ENABLE_BIT               0
+#define MV_USB_WIN_ENABLE_MASK              (1 << MV_USB_WIN_ENABLE_BIT)
+
+#define MV_USB_WIN_BURST_WR_LIMIT_BIT       1
+#define MV_USB_WIN_BURST_WR_LIMIT_MASK      (1 << MV_USB_WIN_BURST_WR_LIMIT_BIT)
+#define MV_USB_WIN_BURST_WR_NO_LIMIT        (0 << MV_USB_WIN_BURST_WR_LIMIT_BIT)
+#define MV_USB_WIN_BURST_WR_32BIT_LIMIT     (1 << MV_USB_WIN_BURST_WR_LIMIT_BIT)
+
+#define MV_USB_WIN_TARGET_OFFSET            4
+#define MV_USB_WIN_TARGET_MASK              (0xF << MV_USB_WIN_TARGET_OFFSET)
+
+#define MV_USB_WIN_ATTR_OFFSET              8
+#define MV_USB_WIN_ATTR_MASK                (0xFF << MV_USB_WIN_ATTR_OFFSET)
+
+#define MV_USB_WIN_SIZE_OFFSET              16
+#define MV_USB_WIN_SIZE_MASK                (0xFFFF << MV_USB_WIN_SIZE_OFFSET)
+
+#define MV_USB_WIN_BASE_OFFSET              16
+#define MV_USB_WIN_BASE_MASK                (0xFFFF << MV_USB_WIN_BASE_OFFSET)
+
+#define MV_USB_WIN_SIZE_ALIGN		    _64K
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INCmvUsbRegsh */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.c b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.c
new file mode 100755
index 0000000..8d382d0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.c
@@ -0,0 +1,1024 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "voiceband/commUnit/mvCommUnit.h"
+
+#undef	MV_COMM_UNIT_DEBUG
+#define	MV_COMM_UNIT_RPT_SUPPORT /* Repeat mode must be set */
+#undef	MV_COMM_UNIT_TEST_SUPPORT
+
+/* defines */
+#define TOTAL_CHAINS		2
+#define CONFIG_RBSZ		16
+#define NEXT_BUFF(buff)		((buff + 1) % TOTAL_CHAINS)
+#define PREV_BUFF(buff)		(buff == 0 ? (TOTAL_CHAINS-1) : (buff-1))
+#define MAX_POLL_USEC		100000	/* 100ms */
+#define IS_KW2_A0(model, rev)	((((model & 0xff00) == 0x6500) && (rev > 1)) ? 1 : 0)
+#define COMM_UNIT_SW_RST	(1 << 5)
+#define OLD_INT_WA_BIT		(1 << 15)
+
+/* globals */
+static MV_STATUS tdmEnable;
+static MV_STATUS pcmEnable;
+static MV_U8 spiMode;
+static MV_U8 maxCs;
+static MV_U8 sampleSize;
+static MV_U8 samplingCoeff;
+static MV_U16 totalChannels;
+static MV_U8 prevRxBuff, nextTxBuff;
+static MV_U8 *rxBuffVirt[TOTAL_CHAINS], *txBuffVirt[TOTAL_CHAINS];
+static MV_ULONG rxBuffPhys[TOTAL_CHAINS], txBuffPhys[TOTAL_CHAINS];
+static MV_TDM_MCDMA_RX_DESC *mcdmaRxDescPtr[TOTAL_CHAINS];
+static MV_TDM_MCDMA_TX_DESC *mcdmaTxDescPtr[TOTAL_CHAINS];
+static MV_ULONG mcdmaRxDescPhys[TOTAL_CHAINS], mcdmaTxDescPhys[TOTAL_CHAINS];
+static MV_TDM_DPRAM_ENTRY defDpramEntry = { 0, 0, 0x1, 0x1, 0, 0, 0x1, 0, 0, 0, 0 };
+static MV_U16 ctrlModel;
+static MV_U16 ctrlRev;
+
+/* Static APIs */
+static MV_VOID mvCommUnitDescChainBuild(MV_VOID);
+static MV_VOID mvCommUnitMcdmaMcscStart(MV_VOID);
+static MV_VOID mvCommUnitMcdmaStop(MV_VOID);
+static MV_VOID mvCommUnitMcdmaMcscAbort(MV_VOID);
+
+MV_STATUS mvCommUnitHalInit(MV_TDM_PARAMS *tdmParams, MV_TDM_HAL_DATA *halData)
+{
+	MV_U16 pcmSlot, index;
+	MV_U32 buffSize, chan;
+	MV_U32 totalRxDescSize, totalTxDescSize, chMask;
+	MV_U32 maxPoll, clkSyncCtrlReg;
+	MV_TDM_DPRAM_ENTRY actDpramEntry, *pActDpramEntry;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Initialize driver resources */
+	tdmEnable = MV_FALSE;
+	pcmEnable = MV_FALSE;
+	spiMode = halData->spiMode;
+	maxCs = halData->maxCs;
+	totalChannels = tdmParams->totalChannels;
+	prevRxBuff = 0;
+	nextTxBuff = 0;
+	ctrlModel = halData->model;
+	ctrlRev = halData->ctrlRev;
+
+	/* Check parameters */
+	if ((tdmParams->totalChannels > MV_TDM_TOTAL_CHANNELS) ||
+	    (tdmParams->samplingPeriod > MV_TDM_MAX_SAMPLING_PERIOD)) {
+		mvOsPrintf("%s: Error, bad parameters\n", __func__);
+		return MV_ERROR;
+	}
+
+	/* Extract sampling period coefficient */
+	samplingCoeff = (tdmParams->samplingPeriod / MV_TDM_BASE_SAMPLING_PERIOD);
+
+	sampleSize = tdmParams->pcmFormat;
+
+	/* Calculate single Rx/Tx buffer size */
+	buffSize = (sampleSize * MV_TDM_TOTAL_CH_SAMPLES * samplingCoeff);
+
+	/* Allocate cached data buffers for all channels */
+	TRC_REC("%s: allocate %dB for data buffers\n", __func__, (buffSize * totalChannels));
+	for (index = 0; index < TOTAL_CHAINS; index++) {
+		rxBuffVirt[index] =
+		    (MV_U8 *) mvOsIoCachedMalloc(NULL, ((buffSize * totalChannels) + CPU_D_CACHE_LINE_SIZE),
+						 &rxBuffPhys[index], NULL);
+		txBuffVirt[index] =
+		    (MV_U8 *) mvOsIoCachedMalloc(NULL, ((buffSize * totalChannels) + CPU_D_CACHE_LINE_SIZE),
+						 &txBuffPhys[index], NULL);
+
+		/* Check Rx buffer address & size alignment */
+		if (((MV_U32) rxBuffVirt[index] | buffSize) & (CONFIG_RBSZ - 1)) {
+			mvOsPrintf("%s: Error, unaligned Rx buffer address or size\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Clear buffers */
+		memset(rxBuffVirt[index], 0, (buffSize * totalChannels));
+		memset(txBuffVirt[index], 0, (buffSize * totalChannels));
+#ifdef MV_COMM_UNIT_TEST_SUPPORT
+	/* Fill Tx buffers with incremental pattern */
+		{
+			int i, j;
+			for (j = 0; j < totalChannels; j++) {
+				for (i = 0; i < buffSize; i++)
+					*(MV_U8 *) (txBuffVirt[index]+i+(j*buffSize)) = (MV_U8)(i+1);
+			}
+		}
+#endif
+
+		/* Flush+Inv buffers */
+		mvOsCacheFlushInv(NULL, rxBuffVirt[index], (buffSize * totalChannels));
+		mvOsCacheFlushInv(NULL, txBuffVirt[index], (buffSize * totalChannels));
+	}
+
+	/* Allocate non-cached MCDMA Rx/Tx descriptors */
+	totalRxDescSize = totalChannels * sizeof(MV_TDM_MCDMA_RX_DESC);
+	totalTxDescSize = totalChannels * sizeof(MV_TDM_MCDMA_TX_DESC);
+
+	TRC_REC("%s: allocate %dB for Rx/Tx descriptors\n", __func__, totalRxDescSize);
+	for (index = 0; index < TOTAL_CHAINS; index++) {
+		mcdmaRxDescPtr[index] = (MV_TDM_MCDMA_RX_DESC *) mvOsIoUncachedMalloc(NULL, totalRxDescSize,
+										      &mcdmaRxDescPhys[index], NULL);
+		mcdmaTxDescPtr[index] = (MV_TDM_MCDMA_TX_DESC *) mvOsIoUncachedMalloc(NULL, totalTxDescSize,
+										      &mcdmaTxDescPhys[index], NULL);
+
+		/* Check descriptors alignment */
+		if (((MV_U32) mcdmaRxDescPtr[index] | (MV_U32) mcdmaTxDescPtr[index]) &
+		    (sizeof(MV_TDM_MCDMA_RX_DESC) - 1)) {
+			mvOsPrintf("%s: Error, unaligned MCDMA Rx/Tx descriptors\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Clear descriptors */
+		memset(mcdmaRxDescPtr[index], 0, totalRxDescSize);
+		memset(mcdmaTxDescPtr[index], 0, totalTxDescSize);
+	}
+
+	/* Poll MCDMA for reset completion */
+	maxPoll = 0;
+	while ((maxPoll < MAX_POLL_USEC) && !(MV_REG_READ(MCDMA_GLOBAL_CONTROL_REG) & MCDMA_RID_MASK)) {
+		mvOsUDelay(1);
+		maxPoll++;
+	}
+
+	if (maxPoll >= MAX_POLL_USEC) {
+		mvOsPrintf("Error, MCDMA reset completion timout\n");
+		return MV_ERROR;
+	}
+
+	/* Poll MCSC for RAM initialization done */
+	if (!(MV_REG_READ(MCSC_GLOBAL_INT_CAUSE_REG) & MCSC_GLOBAL_INT_CAUSE_INIT_DONE_MASK)) {
+		maxPoll = 0;
+		while ((maxPoll < MAX_POLL_USEC) &&
+		       !(MV_REG_READ(MCSC_GLOBAL_INT_CAUSE_REG) & MCSC_GLOBAL_INT_CAUSE_INIT_DONE_MASK)) {
+			mvOsUDelay(1);
+			maxPoll++;
+		}
+
+		if (maxPoll >= MAX_POLL_USEC) {
+			mvOsPrintf("Error, MCDMA RAM initialization timout\n");
+			return MV_ERROR;
+		}
+	}
+
+	/***************************************************************/
+	/* MCDMA Configuration(use default MCDMA linked-list settings) */
+	/***************************************************************/
+	/* Set Rx Service Queue Arbiter Weight Register */
+	MV_REG_WRITE(RX_SERVICE_QUEUE_ARBITER_WEIGHT_REG,
+			(MV_REG_READ(RX_SERVICE_QUEUE_ARBITER_WEIGHT_REG) & ~(0x1f << 24))); /*| MCDMA_RSQW_MASK));*/
+
+	/* Set Tx Service Queue Arbiter Weight Register */
+	MV_REG_WRITE(TX_SERVICE_QUEUE_ARBITER_WEIGHT_REG,
+			(MV_REG_READ(TX_SERVICE_QUEUE_ARBITER_WEIGHT_REG) & ~(0x1f << 24)));	/*| MCDMA_TSQW_MASK));*/
+
+	for (chan = 0; chan < totalChannels; chan++) {
+		/* Set RMCCx */
+		MV_REG_WRITE(MCDMA_RECEIVE_CONTROL_REG(chan), CONFIG_RMCCx);
+
+		/* Set TMCCx */
+		MV_REG_WRITE(MCDMA_TRANSMIT_CONTROL_REG(chan), CONFIG_TMCCx);
+	}
+
+	/**********************/
+	/* MCSC Configuration */
+	/**********************/
+	if (IS_KW2_A0(ctrlModel, ctrlRev)) {
+		/* Disable Rx/Tx channel balancing & Linear mode fix */
+		MV_REG_BIT_SET(MCSC_GLOBAL_CONFIG_REG, MCSC_GLOBAL_CONFIG_TCBD_MASK);
+#if 0
+		/* Unmask Rx/Tx channel balancing */
+		chMask = (0xffffffff & ~((MV_U32)((1 << totalChannels) - 1)));
+		MV_REG_WRITE(MCSC_RX_CHANNEL_BALANCING_MASK_REG, chMask);
+		MV_REG_WRITE(MCSC_TX_CHANNEL_BALANCING_MASK_REG, chMask);
+#endif
+	}
+
+	for (chan = 0; chan < totalChannels; chan++) {
+		MV_REG_WRITE(MCSC_CHx_RECEIVE_CONFIG_REG(chan), CONFIG_MRCRx);
+		MV_REG_WRITE(MCSC_CHx_TRANSMIT_CONFIG_REG(chan), CONFIG_MTCRx);
+	}
+
+	/***********************************************/
+	/* Shared Bus to Crossbar Bridge Configuration */
+	/***********************************************/
+	/* Set Timeout Counter Register */
+	MV_REG_WRITE(TIME_OUT_COUNTER_REG, (MV_REG_READ(TIME_OUT_COUNTER_REG) | TIME_OUT_THRESHOLD_COUNT_MASK));
+
+	/*************************************************/
+	/* Time Division Multiplexing(TDM) Configuration */
+	/*************************************************/
+	pActDpramEntry = &actDpramEntry;
+	memcpy(&actDpramEntry, &defDpramEntry, sizeof(MV_TDM_DPRAM_ENTRY));
+	/* Set repeat mode bits for (sampleSize > 1) */
+	pActDpramEntry->rpt = ((sampleSize == MV_PCM_FORMAT_1BYTE) ? 0 : 1);
+
+	/* Reset all Rx/Tx DPRAM entries to default value */
+	for (index = 0; index < (2 * MV_TDM_MAX_HALF_DPRAM_ENTRIES); index++) {
+		MV_REG_WRITE(FLEX_TDM_RDPR_REG(index), *((MV_U32 *) pActDpramEntry));
+		MV_REG_WRITE(FLEX_TDM_TDPR_REG(index), *((MV_U32 *) pActDpramEntry));
+	}
+
+	/* Set active Rx/Tx DPRAM entries */
+	for (chan = 0; chan < totalChannels; chan++) {
+		/* Same time slot number for both Rx & Tx */
+		pcmSlot = tdmParams->pcmSlot[chan];
+
+		/* Verify time slot is within frame boundries */
+		if (pcmSlot >= halData->frameTs) {
+			mvOsPrintf("Error, time slot(%d) exceeded maximum(%d)\n", pcmSlot, halData->frameTs);
+			return MV_ERROR;
+		}
+
+		/* Verify time slot is aligned to sample size */
+		if ((sampleSize > MV_PCM_FORMAT_1BYTE) && (pcmSlot & 1)) {
+			mvOsPrintf("Error, time slot(%d) not aligned to Linear PCM sample size\n", pcmSlot);
+			return MV_ERROR;
+		}
+
+		/* Update relevant DPRAM fields */
+		pActDpramEntry->ch = chan;
+		pActDpramEntry->mask = 0xff;
+
+		/* Extract physical DPRAM entry id */
+		index = ((sampleSize == MV_PCM_FORMAT_1BYTE) ? pcmSlot : (pcmSlot / 2));
+		
+		/* DPRAM low half */
+		MV_REG_WRITE(FLEX_TDM_RDPR_REG(index), *((MV_U32 *) pActDpramEntry));
+		MV_REG_WRITE(FLEX_TDM_TDPR_REG(index), *((MV_U32 *) pActDpramEntry));
+
+		/* DPRAM high half(mirroring DPRAM low half) */
+		pActDpramEntry->mask = 0;
+		MV_REG_WRITE(FLEX_TDM_RDPR_REG((MV_TDM_MAX_HALF_DPRAM_ENTRIES + index)), *((MV_U32 *) pActDpramEntry));
+		MV_REG_WRITE(FLEX_TDM_TDPR_REG((MV_TDM_MAX_HALF_DPRAM_ENTRIES + index)), *((MV_U32 *) pActDpramEntry));
+
+		/* WideBand mode */
+		if (sampleSize == MV_PCM_FORMAT_4BYTES) {
+			index = (index + (halData->frameTs / sampleSize));
+			/* DPRAM low half */
+			pActDpramEntry->mask = 0xff;
+			MV_REG_WRITE(FLEX_TDM_RDPR_REG(index), *((MV_U32 *) pActDpramEntry));
+			MV_REG_WRITE(FLEX_TDM_TDPR_REG(index), *((MV_U32 *) pActDpramEntry));
+
+			/* DPRAM high half(mirroring DPRAM low half) */
+			pActDpramEntry->mask = 0;
+			MV_REG_WRITE(FLEX_TDM_RDPR_REG((MV_TDM_MAX_HALF_DPRAM_ENTRIES + index)), *((MV_U32 *) pActDpramEntry));
+			MV_REG_WRITE(FLEX_TDM_TDPR_REG((MV_TDM_MAX_HALF_DPRAM_ENTRIES + index)), *((MV_U32 *) pActDpramEntry));
+		}
+	}
+
+	/* Fill last Tx/Rx DPRAM entry('LAST'=1) */
+	pActDpramEntry->mask = 0;
+	pActDpramEntry->ch = 0;
+	pActDpramEntry->last = 1;
+
+	/* Index for last entry */
+	if (sampleSize == MV_PCM_FORMAT_1BYTE)
+		index = (halData->frameTs - 1);
+	else
+		index = ((halData->frameTs / 2) - 1);
+
+	/* Low half */
+	MV_REG_WRITE(FLEX_TDM_TDPR_REG(index), *((MV_U32 *) pActDpramEntry));
+	MV_REG_WRITE(FLEX_TDM_RDPR_REG(index), *((MV_U32 *) pActDpramEntry));
+	/* High half */
+	MV_REG_WRITE(FLEX_TDM_TDPR_REG((MV_TDM_MAX_HALF_DPRAM_ENTRIES + index)), *((MV_U32 *) pActDpramEntry));
+	MV_REG_WRITE(FLEX_TDM_RDPR_REG((MV_TDM_MAX_HALF_DPRAM_ENTRIES + index)), *((MV_U32 *) pActDpramEntry));
+
+	/* Set TDM_CLK_AND_SYNC_CONTROL register */
+	clkSyncCtrlReg = MV_REG_READ(TDM_CLK_AND_SYNC_CONTROL_REG);
+	clkSyncCtrlReg &= ~(TDM_TX_FSYNC_OUT_ENABLE_MASK | TDM_RX_FSYNC_OUT_ENABLE_MASK |
+			TDM_TX_CLK_OUT_ENABLE_MASK | TDM_RX_CLK_OUT_ENABLE_MASK);
+	clkSyncCtrlReg |= CONFIG_TDM_CLK_AND_SYNC_CONTROL;
+	MV_REG_WRITE(TDM_CLK_AND_SYNC_CONTROL_REG, clkSyncCtrlReg);
+
+	/* Set TDM TCR register */
+	MV_REG_WRITE(FLEX_TDM_CONFIG_REG, (MV_REG_READ(FLEX_TDM_CONFIG_REG) | CONFIG_FLEX_TDM_CONFIG));
+
+#if 0
+	/* Set TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_OUT register */
+	MV_REG_WRITE(TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_OUT_REG, CONFIG_TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_OUT);
+
+	/* Set TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_IN register */
+	MV_REG_WRITE(TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_IN_REG, CONFIG_TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_IN);
+
+	/* Restart calculation */
+	MV_REG_BIT_SET(TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_OUT_REG,
+				(TX_SYNC_DELAY_OUT_RESTART_CALC_MASK | RX_SYNC_DELAY_OUT_RESTART_CALC_MASK));
+	MV_REG_BIT_SET(TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_IN_REG,
+				(TX_SYNC_DELAY_IN_RESTART_CALC_MASK | RX_SYNC_DELAY_IN_RESTART_CALC_MASK));
+	mvOsDelay(1);
+	MV_REG_BIT_RESET(TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_OUT_REG,
+				(TX_SYNC_DELAY_OUT_RESTART_CALC_MASK | RX_SYNC_DELAY_OUT_RESTART_CALC_MASK));
+	MV_REG_BIT_RESET(TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_IN_REG,
+				(TX_SYNC_DELAY_IN_RESTART_CALC_MASK | RX_SYNC_DELAY_IN_RESTART_CALC_MASK));
+#endif
+
+	/* Set TDM_CLK_DIVIDER_CONTROL register */
+	/*MV_REG_WRITE(TDM_CLK_DIVIDER_CONTROL_REG, TDM_RX_FIXED_DIV_ENABLE_MASK); */
+
+	/* Enable SLIC/s interrupt detection(before Rx/Tx are active) */
+	/*MV_REG_WRITE(TDM_MASK_REG, TDM_SLIC_INT); */
+
+	/**********************************************************************/
+	/* Time Division Multiplexing(TDM) Interrupt Controller Configuration */
+	/**********************************************************************/
+	/* Clear TDM cause and mask registers */
+	MV_REG_WRITE(COMM_UNIT_TOP_MASK_REG, 0);
+	MV_REG_WRITE(TDM_MASK_REG, 0);
+	MV_REG_WRITE(COMM_UNIT_TOP_CAUSE_REG, 0);
+	MV_REG_WRITE(TDM_CAUSE_REG, 0);
+
+	/* Clear MCSC cause and mask registers(except InitDone bit) */
+	MV_REG_WRITE(MCSC_GLOBAL_INT_MASK_REG, 0);
+	MV_REG_WRITE(MCSC_EXTENDED_INT_MASK_REG, 0);
+	MV_REG_WRITE(MCSC_GLOBAL_INT_CAUSE_REG, MCSC_GLOBAL_INT_CAUSE_INIT_DONE_MASK);
+	MV_REG_WRITE(MCSC_EXTENDED_INT_CAUSE_REG, 0);
+
+#ifdef MV_COMM_UNIT_DEBUG
+	mvCommUnitShow();
+#endif
+
+	/* Enable PCM */
+	mvCommUnitPcmStart();
+
+	/* Mark TDM I/F as enabled */
+	tdmEnable = MV_TRUE;
+
+	/* Enable PCLK */
+	MV_REG_WRITE(TDM_DATA_DELAY_AND_CLK_CTRL_REG, (MV_REG_READ(TDM_DATA_DELAY_AND_CLK_CTRL_REG) |
+				CONFIG_TDM_DATA_DELAY_AND_CLK_CTRL));
+
+	/* Restore old periodic interrupt mechanism WA */
+	/* MV_REG_BIT_SET(TDM_DATA_DELAY_AND_CLK_CTRL_REG, OLD_INT_WA_BIT); */
+
+	/* Enable TDM */
+	MV_REG_BIT_SET(FLEX_TDM_CONFIG_REG, TDM_TEN_MASK);
+
+#if 0
+	/* Poll for Enter Hunt Execution Status */
+	for (chan = 0; chan < totalChannels; chan++) {
+		maxPoll = 0;
+		while ((maxPoll < MAX_POLL_USEC) &&
+			!(MV_REG_READ(MCSC_CHx_COMM_EXEC_STAT_REG(chan)) & MCSC_EH_E_STAT_MASK)) {
+			mvOsUDelay(1);
+			maxPoll++;
+		}
+
+		if (maxPoll >= MAX_POLL_USEC) {
+			mvOsPrintf("%s: Error, enter hunt execution timeout(ch%d)\n", __func__, chan);
+			return MV_ERROR;
+		}
+
+		MV_REG_BIT_RESET(MCSC_CHx_RECEIVE_CONFIG_REG(chan), MRCRx_ENTER_HUNT_MASK);
+	}
+#endif
+
+	MV_TRC_REC("<-%s\n", __func__);
+	return MV_OK;
+}
+
+MV_VOID mvCommUnitRelease(MV_VOID)
+{
+	MV_U32 buffSize, totalRxDescSize, totalTxDescSize, index;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	if (tdmEnable == MV_TRUE) {
+
+		/* Mark TDM I/F as disabled */
+		tdmEnable = MV_FALSE;
+
+		mvCommUnitPcmStop();
+
+		mvCommUnitMcdmaMcscAbort();
+
+		if (IS_KW2_A0(ctrlModel, ctrlRev)) {
+			mvOsUDelay(10);
+			MV_REG_BIT_RESET(MCSC_GLOBAL_CONFIG_REG, MCSC_GLOBAL_CONFIG_MAI_MASK);
+		}
+
+		/* Disable TDM */
+		MV_REG_BIT_RESET(FLEX_TDM_CONFIG_REG, TDM_TEN_MASK);
+
+		/* Disable PCLK */
+		MV_REG_BIT_RESET(TDM_DATA_DELAY_AND_CLK_CTRL_REG, (TX_CLK_OUT_ENABLE_MASK | RX_CLK_OUT_ENABLE_MASK));
+
+		/* Reset CommUnit blocks to default settings */
+		MV_REG_BIT_RESET(0x18220, COMM_UNIT_SW_RST);
+		mvOsUDelay(1);
+		MV_REG_BIT_SET(0x18220, COMM_UNIT_SW_RST);
+		mvOsDelay(10);
+
+		/* Calculate total Rx/Tx buffer size */
+		buffSize = (sampleSize * MV_TDM_TOTAL_CH_SAMPLES * samplingCoeff * totalChannels)
+	    			+ CPU_D_CACHE_LINE_SIZE;
+
+		/* Calculate total MCDMA Rx/Tx descriptors chain size */
+		totalRxDescSize = totalChannels * sizeof(MV_TDM_MCDMA_RX_DESC);
+		totalTxDescSize = totalChannels * sizeof(MV_TDM_MCDMA_TX_DESC);
+
+		for (index = 0; index < TOTAL_CHAINS; index++) {
+			/* Release Rx/Tx data buffers */
+			mvOsIoCachedFree(NULL, buffSize, rxBuffPhys[index], rxBuffVirt[index], 0);
+			mvOsIoCachedFree(NULL, buffSize, txBuffPhys[index], txBuffVirt[index], 0);
+
+			/* Release MCDMA Rx/Tx descriptors */
+			mvOsIoUncachedFree(NULL, totalRxDescSize, mcdmaRxDescPhys[index], mcdmaRxDescPtr[index], 0);
+			mvOsIoUncachedFree(NULL, totalTxDescSize, mcdmaTxDescPhys[index], mcdmaTxDescPtr[index], 0);
+		}
+	}
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+static MV_VOID mvCommUnitMcdmaMcscStart(MV_VOID)
+{
+	MV_U32 chan, rxDescPhysAddr, txDescPhysAddr;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	mvCommUnitDescChainBuild();
+
+	/* Set current Rx/Tx descriptors  */
+	for (chan = 0; chan < totalChannels; chan++) {
+		rxDescPhysAddr = mcdmaRxDescPhys[0] + (chan * sizeof(MV_TDM_MCDMA_RX_DESC));
+		txDescPhysAddr = mcdmaTxDescPhys[0] + (chan * sizeof(MV_TDM_MCDMA_TX_DESC));
+		MV_REG_WRITE(MCDMA_CURRENT_RECEIVE_DESC_PTR_REG(chan), rxDescPhysAddr);
+		MV_REG_WRITE(MCDMA_CURRENT_TRANSMIT_DESC_PTR_REG(chan), txDescPhysAddr);
+	}
+
+	/* Restore MCDMA Rx/Tx control registers */
+	for (chan = 0; chan < totalChannels; chan++) {
+		/* Set RMCCx */
+		MV_REG_WRITE(MCDMA_RECEIVE_CONTROL_REG(chan), CONFIG_RMCCx);
+
+		/* Set TMCCx */
+		MV_REG_WRITE(MCDMA_TRANSMIT_CONTROL_REG(chan), CONFIG_TMCCx);
+	}
+
+	/* Set Rx/Tx periodical interrupts */
+	MV_REG_WRITE(VOICE_PERIODICAL_INT_CONTROL_REG, CONFIG_VOICE_PERIODICAL_INT_CONTROL);
+
+	/* MCSC Global Tx Enable */
+	if (tdmEnable == MV_FALSE)
+		MV_REG_BIT_SET(MCSC_GLOBAL_CONFIG_REG, MCSC_GLOBAL_CONFIG_TXEN_MASK);
+
+	/* Enable MCSC-Tx & MCDMA-Rx */
+	for (chan = 0; chan < totalChannels; chan++) {
+		/* Enable Tx in TMCCx */
+		if (tdmEnable == MV_FALSE)
+			MV_REG_BIT_SET(MCSC_CHx_TRANSMIT_CONFIG_REG(chan), MTCRx_ET_MASK);
+
+		/* Enable Rx in: MCRDPx */
+		MV_REG_BIT_SET(MCDMA_RECEIVE_CONTROL_REG(chan), MCDMA_ERD_MASK);
+	}
+
+	/* MCSC Global Rx Enable */
+	if (tdmEnable == MV_FALSE)
+		MV_REG_BIT_SET(MCSC_GLOBAL_CONFIG_REG, MCSC_GLOBAL_CONFIG_RXEN_MASK);
+
+	/* Enable MCSC-Rx & MCDMA-Tx */
+	for (chan = 0; chan < totalChannels; chan++) {
+		/* Enable Rx in RMCCx */
+		if (tdmEnable == MV_FALSE)
+			MV_REG_BIT_SET(MCSC_CHx_RECEIVE_CONFIG_REG(chan), MRCRx_ER_MASK);
+
+		/* Enable Tx in MCTDPx */
+		MV_REG_BIT_SET(MCDMA_TRANSMIT_CONTROL_REG(chan), MCDMA_TXD_MASK);
+	}
+
+	/* Disable Rx/Tx return to half */
+	MV_REG_BIT_RESET(FLEX_TDM_CONFIG_REG, (TDM_RR2HALF_MASK | TDM_TR2HALF_MASK));
+	/* Wait at least 1 frame */
+	mvOsUDelay(200);
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+MV_VOID mvCommUnitPcmStart(MV_VOID)
+{
+	MV_U32 maskReg;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	if (pcmEnable == MV_FALSE) {
+
+		/* Mark PCM I/F as enabled  */
+		pcmEnable = MV_TRUE;
+
+		mvCommUnitMcdmaMcscStart();
+
+		/* Clear TDM cause and mask registers */
+		MV_REG_WRITE(COMM_UNIT_TOP_MASK_REG, 0);
+		MV_REG_WRITE(TDM_MASK_REG, 0);
+		MV_REG_WRITE(COMM_UNIT_TOP_CAUSE_REG, 0);
+		MV_REG_WRITE(TDM_CAUSE_REG, 0);
+
+		/* Clear MCSC cause and mask registers(except InitDone bit) */
+		MV_REG_WRITE(MCSC_GLOBAL_INT_MASK_REG, 0);
+		MV_REG_WRITE(MCSC_EXTENDED_INT_MASK_REG, 0);
+		MV_REG_WRITE(MCSC_GLOBAL_INT_CAUSE_REG, MCSC_GLOBAL_INT_CAUSE_INIT_DONE_MASK);
+		MV_REG_WRITE(MCSC_EXTENDED_INT_CAUSE_REG, 0);
+
+		/* Enable unit interrupts */
+		maskReg = MV_REG_READ(TDM_MASK_REG);
+		MV_REG_WRITE(TDM_MASK_REG, (maskReg | CONFIG_TDM_CAUSE));
+		MV_REG_WRITE(COMM_UNIT_TOP_MASK_REG, CONFIG_COMM_UNIT_TOP_MASK);
+	}
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+static MV_VOID mvCommUnitMcdmaMcscAbort(MV_VOID)
+{
+	MV_U32 chan, maxPoll;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Abort MCSC/MCDMA in case we got here from mvCommUnitRelease() */
+	if (tdmEnable == MV_FALSE) {
+
+#if 0
+		/* MCSC Rx Abort */
+		for (chan = 0; chan < totalChannels; chan++)
+			MV_REG_BIT_SET(MCSC_CHx_RECEIVE_CONFIG_REG(chan), MRCRx_ABORT_MASK);
+
+		for (chan = 0; chan < totalChannels; chan++) {
+			maxPoll = 0;
+			while ((maxPoll < MAX_POLL_USEC) &&
+				!(MV_REG_READ(MCSC_CHx_COMM_EXEC_STAT_REG(chan)) & MCSC_ABR_E_STAT_MASK)) {
+				mvOsUDelay(1);
+				maxPoll++;
+			}
+
+			if (maxPoll >= MAX_POLL_USEC) {
+				mvOsPrintf("%s: Error, MCSC Rx abort timeout(ch%d)\n", __func__, chan);
+				return;
+			}
+
+			MV_REG_BIT_RESET(MCSC_CHx_RECEIVE_CONFIG_REG(chan), MRCRx_ABORT_MASK);
+		}
+
+		/* MCDMA Tx Abort */
+		for (chan = 0; chan < totalChannels; chan++)
+			MV_REG_BIT_SET(MCDMA_TRANSMIT_CONTROL_REG(chan), MCDMA_AT_MASK);
+
+		for (chan = 0; chan < totalChannels; chan++) {
+			maxPoll = 0;
+			while ((maxPoll < MAX_POLL_USEC) &&
+				(MV_REG_READ(MCDMA_RECEIVE_CONTROL_REG(chan)) & MCDMA_ERD_MASK)) {
+				mvOsUDelay(1);
+				maxPoll++;
+			}
+
+			if (maxPoll >= MAX_POLL_USEC) {
+				mvOsPrintf("%s: Error, MCDMA Rx abort timeout(ch%d)\n", __func__, chan);
+				return;
+			}
+
+			maxPoll = 0;
+			while ((maxPoll < MAX_POLL_USEC) &&
+				(MV_REG_READ(MCDMA_TRANSMIT_CONTROL_REG(chan)) & MCDMA_AT_MASK)) {
+				mvOsUDelay(1);
+				maxPoll++;
+			}
+
+			if (maxPoll >= MAX_POLL_USEC) {
+				mvOsPrintf("%s: Error, MCDMA Tx abort timeout(ch%d)\n", __func__, chan);
+				return;
+			}
+		}
+#endif
+		/* Clear MCSC Rx/Tx channel enable */
+		for (chan = 0; chan < totalChannels; chan++) {
+			MV_REG_BIT_RESET(MCSC_CHx_RECEIVE_CONFIG_REG(chan), MRCRx_ER_MASK);
+			MV_REG_BIT_RESET(MCSC_CHx_TRANSMIT_CONFIG_REG(chan), MTCRx_ET_MASK);
+		}
+
+		/* MCSC Global Rx/Tx Disable */
+		MV_REG_BIT_RESET(MCSC_GLOBAL_CONFIG_REG, MCSC_GLOBAL_CONFIG_RXEN_MASK);
+		MV_REG_BIT_RESET(MCSC_GLOBAL_CONFIG_REG, MCSC_GLOBAL_CONFIG_TXEN_MASK);
+	}
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+static MV_VOID mvCommUnitMcdmaStop(MV_VOID)
+{
+	MV_U32 index, chan, maxPoll, currTxDesc;
+	MV_U32 currRxDesc, nextTxBuff = 0, nextRxBuff = 0;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/***************************/
+	/*    Stop MCDMA - Rx/Tx   */
+	/***************************/
+	for (chan = 0; chan < totalChannels; chan++) {
+		currRxDesc = MV_REG_READ(MCDMA_CURRENT_RECEIVE_DESC_PTR_REG(chan));
+		for (index = 0; index < TOTAL_CHAINS; index++) {
+			if (currRxDesc == (mcdmaRxDescPhys[index] + (chan*(sizeof(MV_TDM_MCDMA_RX_DESC))))) {
+				nextRxBuff = NEXT_BUFF(index);
+				break;
+			}
+		}
+
+		if(index == TOTAL_CHAINS) {
+			mvOsPrintf("%s: ERROR, couldn't Rx descriptor match for chan(%d)\n", __func__, chan);
+			break;
+		}
+
+		((MV_TDM_MCDMA_RX_DESC *) (mcdmaRxDescPtr[nextRxBuff] + chan))->physNextDescPtr = 0;
+		((MV_TDM_MCDMA_RX_DESC *) (mcdmaRxDescPtr[nextRxBuff] + chan))->cmdStatus = (LAST_BIT | OWNER);
+	}
+
+	for (chan = 0; chan < totalChannels; chan++) {
+		currTxDesc = MV_REG_READ(MCDMA_CURRENT_TRANSMIT_DESC_PTR_REG(chan));
+		for (index = 0; index < TOTAL_CHAINS; index++) {
+			if (currTxDesc == (mcdmaTxDescPhys[index] + (chan*(sizeof(MV_TDM_MCDMA_TX_DESC))))) {
+				nextTxBuff = NEXT_BUFF(index);
+				break;
+			}
+		}
+
+		if(index == TOTAL_CHAINS) {
+			printk("%s: ERROR, couldn't Tx descriptor match for chan(%d)\n", __func__, chan);
+			return;
+		}
+
+		((MV_TDM_MCDMA_TX_DESC *) (mcdmaTxDescPtr[nextTxBuff] + chan))->physNextDescPtr = 0;
+		((MV_TDM_MCDMA_TX_DESC *) (mcdmaTxDescPtr[nextTxBuff] + chan))->cmdStatus = (LAST_BIT | OWNER);
+	}
+
+	for (chan = 0; chan < totalChannels; chan++) {
+		maxPoll = 0;
+		while ((maxPoll < MAX_POLL_USEC) &&
+			(MV_REG_READ(MCDMA_TRANSMIT_CONTROL_REG(chan)) & MCDMA_TXD_MASK)) {
+			mvOsUDelay(1);
+			maxPoll++;
+		}
+
+		if (maxPoll >= MAX_POLL_USEC) {
+			mvOsPrintf("%s: Error, MCDMA TXD polling timeout(ch%d)\n", __func__, chan);
+			return;
+		}
+
+		maxPoll = 0;
+		while ((maxPoll < MAX_POLL_USEC) &&
+			(MV_REG_READ(MCDMA_RECEIVE_CONTROL_REG(chan)) & MCDMA_ERD_MASK)) {
+			mvOsUDelay(1);
+			maxPoll++;
+		}
+
+		if (maxPoll >= MAX_POLL_USEC) {
+			mvOsPrintf("%s: Error, MCDMA ERD polling timeout(ch%d)\n", __func__, chan);
+			return;
+		}
+	}
+
+	/* Disable Rx/Tx periodical interrupts */
+	MV_REG_WRITE(VOICE_PERIODICAL_INT_CONTROL_REG, 0xffffffff);
+
+	/* Enable Rx/Tx return to half */
+	MV_REG_BIT_SET(FLEX_TDM_CONFIG_REG, (TDM_RR2HALF_MASK | TDM_TR2HALF_MASK));
+	/* Wait at least 1 frame */
+	mvOsUDelay(200);
+
+	if (IS_KW2_A0(ctrlModel, ctrlRev)) {
+		/* Manual reset to channel-balancing mechanism */
+		MV_REG_BIT_SET(MCSC_GLOBAL_CONFIG_REG, MCSC_GLOBAL_CONFIG_MAI_MASK);
+		mvOsUDelay(1);
+	}
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+MV_VOID mvCommUnitPcmStop(MV_VOID)
+{
+	MV_U32 buffSize, index;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	if (pcmEnable == MV_TRUE) {
+		/* Mark PCM I/F as disabled  */
+		pcmEnable = MV_FALSE;
+
+		/* Clear TDM cause and mask registers */
+		MV_REG_WRITE(COMM_UNIT_TOP_MASK_REG, 0);
+		MV_REG_WRITE(TDM_MASK_REG, 0);
+		MV_REG_WRITE(COMM_UNIT_TOP_CAUSE_REG, 0);
+		MV_REG_WRITE(TDM_CAUSE_REG, 0);
+
+		/* Clear MCSC cause and mask registers(except InitDone bit) */
+		MV_REG_WRITE(MCSC_GLOBAL_INT_MASK_REG, 0);
+		MV_REG_WRITE(MCSC_EXTENDED_INT_MASK_REG, 0);
+		MV_REG_WRITE(MCSC_GLOBAL_INT_CAUSE_REG, MCSC_GLOBAL_INT_CAUSE_INIT_DONE_MASK);
+		MV_REG_WRITE(MCSC_EXTENDED_INT_CAUSE_REG, 0);
+
+		mvCommUnitMcdmaStop();
+
+		/* Calculate total Rx/Tx buffer size */
+		buffSize = (sampleSize * MV_TDM_TOTAL_CH_SAMPLES * samplingCoeff * totalChannels);
+
+		/* Clear Rx buffers */
+		for (index = 0; index < TOTAL_CHAINS; index++) {
+			memset(rxBuffVirt[index], 0, buffSize);
+
+			/* Flush+Inv buffers */
+			mvOsCacheFlushInv(NULL, txBuffVirt[index], buffSize);
+		}
+
+	}
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+MV_STATUS mvCommUnitTx(MV_U8 *pTdmTxBuff)
+{
+	MV_U32 buffSize, index;
+	MV_U8 tmp;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Calculate total Tx buffer size */
+	buffSize = (sampleSize * MV_TDM_TOTAL_CH_SAMPLES * samplingCoeff * totalChannels);
+
+	if (sampleSize > MV_PCM_FORMAT_1BYTE) {
+		TRC_REC("Linear mode(Tx): swapping bytes\n");
+			for (index = 0; index < buffSize; index += 2) {
+				tmp = pTdmTxBuff[index];
+				pTdmTxBuff[index] = pTdmTxBuff[index+1];
+				pTdmTxBuff[index+1] = tmp;
+			}
+		TRC_REC("Linear mode(Tx): swapping bytes...done.\n");
+	}
+
+	/* Flush+Invalidate the next Tx buffer */
+	mvOsCacheFlush(NULL, pTdmTxBuff, buffSize);
+	mvOsCacheInvalidate(NULL, pTdmTxBuff, buffSize);
+
+	MV_TRC_REC("<-%s\n", __func__);
+	return MV_OK;
+}
+
+MV_STATUS mvCommUnitRx(MV_U8 *pTdmRxBuff)
+{
+	MV_U32 buffSize, index;
+	MV_U8 tmp;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Calculate total Rx buffer size */
+	buffSize = (sampleSize * MV_TDM_TOTAL_CH_SAMPLES * samplingCoeff * totalChannels);
+
+	/* Invalidate current received buffer from cache */
+	mvOsCacheInvalidate(NULL, pTdmRxBuff, buffSize);
+
+	if (sampleSize > MV_PCM_FORMAT_1BYTE) {
+		TRC_REC("  -> Linear mode(Rx): swapping bytes\n");
+			for (index = 0; index < buffSize; index += 2) {
+				tmp = pTdmRxBuff[index];
+				pTdmRxBuff[index] = pTdmRxBuff[index+1];
+				pTdmRxBuff[index+1] = tmp;
+			}
+		TRC_REC("  <- Linear mode(Rx): swapping bytes...done.\n");
+	}
+
+	MV_TRC_REC("<-%s\n", __func__);
+	return MV_OK;
+}
+
+/* Low level TDM interrupt service routine */
+MV_VOID mvCommUnitIntLow(MV_TDM_INT_INFO *pTdmIntInfo)
+{
+	MV_U32 causeReg, maskReg, causeAndMask;
+	MV_U32 intAckBits = 0, currDesc;
+	MV_U8 index;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Read TDM cause & mask registers */
+	causeReg = MV_REG_READ(TDM_CAUSE_REG);
+	maskReg = MV_REG_READ(TDM_MASK_REG);
+
+	MV_TRC_REC("CAUSE(0x%x), MASK(0x%x)\n", causeReg, maskReg);
+
+	/* Refer only to unmasked bits */
+	causeAndMask = causeReg & maskReg;
+
+	/* Reset ISR params */
+	pTdmIntInfo->tdmRxBuff = NULL;
+	pTdmIntInfo->tdmTxBuff = NULL;
+	pTdmIntInfo->intType = MV_EMPTY_INT;
+
+#if 0
+	/* Handle SLIC interrupt */
+	slicInt = (causeAndMask & TDM_SLIC_INT);
+	if (slicInt) {
+		MV_TRC_REC("SLIC interrupt !!!\n");
+		pTdmIntInfo->intType |= MV_PHONE_INT;
+		for (cs = 0; cs < maxCs; cs++) {
+			if (slicInt & MV_BIT_MASK(cs + EXT_INT_SLIC0_OFFS)) {
+				pTdmIntInfo->cs = cs;
+				mvOsPrintf("");
+				intAckBits |= MV_BIT_MASK(cs + EXT_INT_SLIC0_OFFS);
+				break;
+			}
+
+		}
+		mvOsPrintf("pTdmIntInfo->cs = %d\n", pTdmIntInfo->cs);
+	}
+#endif
+	/* Return in case TDM is disabled */
+	if (tdmEnable == MV_FALSE) {
+		MV_TRC_REC("TDM is disabled - quit low level ISR\n");
+		MV_REG_WRITE(TDM_CAUSE_REG, ~intAckBits);
+		return;
+	}
+
+	/* Handle TDM Error/s */
+	if (causeAndMask & TDM_ERROR_INT) {
+		mvOsPrintf("TDM Error: TDM_CAUSE_REG = 0x%x\n", causeReg);
+		/*pTdmIntInfo->intType |= MV_ERROR_INT;*/
+		intAckBits |= (causeAndMask & TDM_ERROR_INT);
+	}
+
+	if (causeAndMask & (TDM_TX_INT | TDM_RX_INT)) {
+		/* MCDMA current Tx desc. pointer is unreliable, thus, checking Rx desc. pointer only */
+		currDesc = MV_REG_READ(MCDMA_CURRENT_RECEIVE_DESC_PTR_REG(0));
+		MV_TRC_REC("currDesc = 0x%x\n", currDesc);
+
+		/* Handle Tx */
+		if (causeAndMask & TDM_TX_INT) {
+			for (index = 0; index < TOTAL_CHAINS; index++) {
+				if (currDesc == mcdmaRxDescPhys[index]) {
+					nextTxBuff = NEXT_BUFF(index);
+					break;
+				}
+			}
+			MV_TRC_REC("Tx interrupt(nextTxBuff=%d)!!!\n", nextTxBuff);
+			pTdmIntInfo->tdmTxBuff = txBuffVirt[nextTxBuff];
+			pTdmIntInfo->intType |= MV_TX_INT;
+			intAckBits |= TDM_TX_INT;
+		}
+
+		/* Handle Rx */
+		if (causeAndMask & TDM_RX_INT) {
+			for (index = 0; index < TOTAL_CHAINS; index++) {
+				if (currDesc == mcdmaRxDescPhys[index]) {
+					prevRxBuff = PREV_BUFF(index);
+					break;
+				}
+			}
+			MV_TRC_REC("Rx interrupt(prevRxBuff=%d)!!!\n", prevRxBuff);
+			pTdmIntInfo->tdmRxBuff = rxBuffVirt[prevRxBuff];
+			pTdmIntInfo->intType |= MV_RX_INT;
+			intAckBits |= TDM_RX_INT;
+		}
+	}
+
+	/* Clear TDM interrupts */
+	MV_REG_WRITE(TDM_CAUSE_REG, ~intAckBits);
+
+	TRC_REC("<-%s\n", __func__);
+	return;
+}
+
+static MV_VOID mvCommUnitDescChainBuild(MV_VOID)
+{
+	MV_U32 chan, index, buffSize;
+
+	TRC_REC("->%s\n", __func__);
+
+	/* Calculate single Rx/Tx buffer size */
+	buffSize = (sampleSize * MV_TDM_TOTAL_CH_SAMPLES * samplingCoeff);
+
+	/* Initialize descriptors fields */
+	for (chan = 0; chan < totalChannels; chan++) {
+		for (index = 0; index < TOTAL_CHAINS; index++) {
+			/* Associate data buffers to descriptors physBuffPtr */
+			((MV_TDM_MCDMA_RX_DESC *) (mcdmaRxDescPtr[index] + chan))->physBuffPtr =
+			    (MV_U32) (rxBuffPhys[index] + (chan * buffSize));
+			((MV_TDM_MCDMA_TX_DESC *) (mcdmaTxDescPtr[index] + chan))->physBuffPtr =
+			    (MV_U32) (txBuffPhys[index] + (chan * buffSize));
+
+			/* Build cyclic descriptors chain for each channel */
+			((MV_TDM_MCDMA_RX_DESC *) (mcdmaRxDescPtr[index] + chan))->physNextDescPtr =
+			    (MV_U32) (mcdmaRxDescPhys[((index + 1) % TOTAL_CHAINS)] +
+				      (chan * sizeof(MV_TDM_MCDMA_RX_DESC)));
+
+			((MV_TDM_MCDMA_TX_DESC *) (mcdmaTxDescPtr[index] + chan))->physNextDescPtr =
+			    (MV_U32) (mcdmaTxDescPhys[((index + 1) % TOTAL_CHAINS)] +
+				      (chan * sizeof(MV_TDM_MCDMA_TX_DESC)));
+
+			/* Set Byte_Count/Buffer_Size Rx descriptor fields */
+			((MV_TDM_MCDMA_RX_DESC *) (mcdmaRxDescPtr[index] + chan))->byteCnt = 0;
+			((MV_TDM_MCDMA_RX_DESC *) (mcdmaRxDescPtr[index] + chan))->buffSize = buffSize;
+
+			/* Set Shadow_Byte_Count/Byte_Count Tx descriptor fields */
+			((MV_TDM_MCDMA_TX_DESC *) (mcdmaTxDescPtr[index] + chan))->shadowByteCnt = buffSize;
+			((MV_TDM_MCDMA_TX_DESC *) (mcdmaTxDescPtr[index] + chan))->byteCnt = buffSize;
+
+			/* Set Command/Status Rx/Tx descriptor fields */
+			((MV_TDM_MCDMA_RX_DESC *) (mcdmaRxDescPtr[index] + chan))->cmdStatus =
+			    (CONFIG_MCDMA_DESC_CMD_STATUS);
+			((MV_TDM_MCDMA_TX_DESC *) (mcdmaTxDescPtr[index] + chan))->cmdStatus =
+			    (CONFIG_MCDMA_DESC_CMD_STATUS);
+		}
+	}
+
+	TRC_REC("<-%s\n", __func__);
+	return;
+}
+
+MV_VOID mvCommUnitIntEnable(MV_U8 deviceId)
+{
+	/* MV_REG_BIT_SET(MV_GPP_IRQ_MASK_REG(0), BIT23); */
+}
+
+MV_VOID mvCommUnitIntDisable(MV_U8 deviceId)
+{
+	/* MV_REG_BIT_RESET(MV_GPP_IRQ_MASK_REG(0), BIT23); */
+}
+
+MV_VOID mvCommUnitShow(MV_VOID)
+{
+	MV_U32 index;
+
+	/* Dump data buffers & descriptors addresses */
+	for (index = 0; index < TOTAL_CHAINS; index++) {
+		mvOsPrintf("Rx Buff(%d): virt = 0x%x, phys = 0x%x\n", index, (MV_U32) rxBuffVirt[index],
+			   (MV_U32) rxBuffPhys[index]);
+		mvOsPrintf("Tx Buff(%d): virt = 0x%x, phys = 0x%x\n", index, (MV_U32) txBuffVirt[index],
+			   (MV_U32) txBuffPhys[index]);
+
+		mvOsPrintf("Rx Desc(%d): virt = 0x%x, phys = 0x%x\n", index,
+			   (MV_U32) mcdmaRxDescPtr[index], (MV_U32) mcdmaRxDescPhys[index]);
+
+		mvOsPrintf("Tx Desc(%d): virt = 0x%x, phys = 0x%x\n", index,
+			   (MV_U32) mcdmaTxDescPtr[index], (MV_U32) mcdmaTxDescPhys[index]);
+
+	}
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.h b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.h
new file mode 100755
index 0000000..620e458
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnit.h
@@ -0,0 +1,204 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCommUnith
+#define __INCmvCommUnith
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "voiceband/commUnit/mvCommUnitRegs.h"
+#include "voiceband/mvSysTdmSpi.h"
+#include "mvSysTdmConfig.h"
+
+/* Defines */
+#define MV_TDM_TOTAL_CHANNELS		32
+#define MV_TDM_MAX_HALF_DPRAM_ENTRIES	128
+#define MV_TDM_MAX_SAMPLING_PERIOD	30	/* ms */
+#define MV_TDM_BASE_SAMPLING_PERIOD	10	/* ms */
+#define MV_TDM_TOTAL_CH_SAMPLES		80	/* samples */
+
+/* IRQ types */
+#define MV_EMPTY_INT			0
+#define MV_RX_INT 			BIT0
+#define	MV_TX_INT 			BIT1
+#define	MV_PHONE_INT 			BIT2
+#define	MV_RX_ERROR_INT 		BIT3
+#define	MV_TX_ERROR_INT 		BIT4
+#define MV_DMA_ERROR_INT		BIT5
+#define MV_ERROR_INT			(MV_RX_ERROR_INT | MV_TX_ERROR_INT | MV_DMA_ERROR_INT)
+
+#define TDM_SLIC_INT		(EXT_INT_SLIC0_MASK | EXT_INT_SLIC1_MASK | EXT_INT_SLIC2_MASK | EXT_INT_SLIC3_MASK)
+#define TDM_TX_INT		 TX_VOICE_INT_PULSE_MASK
+#define TDM_RX_INT		 RX_VOICE_INT_PULSE_MASK
+#define TDM_ERROR_INT		(FLEX_TDM_RX_SYNC_LOSS_MASK | FLEX_TDM_TX_SYNC_LOSS_MASK | \
+				 COMM_UNIT_PAR_ERR_SUM_MASK | TDM_RX_PAR_ERR_SUM_MASK | TDM_TX_PAR_ERR_SUM_MASK | \
+				 MCSC_PAR_ERR_SUM_MASK | MCDMA_PAR_ERR_SUM_MASK)
+
+/* MCDMA Descriptor Command/Status Bits */
+#define	LAST_BIT	BIT16
+#define	FIRST_BIT	BIT17
+#define	EOPI		BIT21
+#define	ENABLE_INT	BIT23
+#define	AUTO_MODE	BIT30
+#define	OWNER		BIT31
+
+/* MCDMA */
+#define CONFIG_MCDMA_DESC_CMD_STATUS	(FIRST_BIT | AUTO_MODE | OWNER)
+#define CONFIG_RMCCx			(MCDMA_RBSZ_16BYTE | MCDMA_BLMR_MASK)
+#define CONFIG_TMCCx			(MCDMA_FSIZE_1BLK | MCDMA_TBSZ_16BYTE | MCDMA_BLMT_MASK)
+
+/* MCSC */
+#define CONFIG_MRCRx			(MRCRx_RRVD_MASK | MRCRx_MODE_MASK)
+#define CONFIG_MTCRx			(MTCRx_TRVD_MASK | MTCRx_MODE_MASK)
+
+/* TDM */
+#if defined(MV_TDM_USE_EXTERNAL_PCLK_SOURCE)
+#define CONFIG_TDM_CLK_AND_SYNC_CONTROL	(TDM_TX_CLK_OUT_ENABLE_MASK | TDM_RX_CLK_OUT_ENABLE_MASK | \
+					 TDM_REFCLK_DIVIDER_BYPASS_MASK)
+#else
+#define CONFIG_TDM_CLK_AND_SYNC_CONTROL	(TDM_REFCLK_DIVIDER_BYPASS_MASK | TDM_OUT_CLK_SRC_CTRL_AFTER_DIV)
+#endif				/* MV_TDM_USE_EXTERNAL_PCLK_SOURCE */
+
+#define CONFIG_VOICE_PERIODICAL_INT_CONTROL (((MV_TDM_TOTAL_CH_SAMPLES-1) << RX_VOICE_INT_CNT_REF_OFFS) | \
+					     ((MV_TDM_TOTAL_CH_SAMPLES-1) << TX_VOICE_INT_CNT_REF_OFFS) | \
+					     (1 << RX_FIRST_DELAY_REF_OFFS) | (4 << TX_FIRST_DELAY_REF_OFFS))
+#define CONFIG_TDM_CAUSE    		    (TDM_RX_INT | TDM_TX_INT /*| TDM_ERROR_INT*/)
+#define CONFIG_COMM_UNIT_TOP_MASK	    (TDM_SUM_INT_MASK | MCSC_SUM_INT_MASK)
+#define CONFIG_FLEX_TDM_CONFIG		    (TDM_SE_MASK | TDM_COMMON_RX_TX_MASK | TSD_NO_DELAY | RSD_NO_DELAY)
+#define	CONFIG_TDM_DATA_DELAY_AND_CLK_CTRL		(TX_CLK_OUT_ENABLE_MASK | RX_CLK_OUT_ENABLE_MASK)
+#define CONFIG_TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_OUT	(TX_SYNC_DELAY_OUT_MINUS | RX_SYNC_DELAY_OUT_MINUS)
+#define CONFIG_TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_IN	(TX_SYNC_DELAY_IN_MINUS | RX_SYNC_DELAY_IN_MINUS)
+
+/* Structures */
+	typedef struct {
+		MV_U8 *tdmRxBuff;
+		MV_U8 *tdmTxBuff;
+		MV_U32 intType;
+		MV_U8 cs;
+	} MV_TDM_INT_INFO;
+
+	typedef struct {
+		MV_PCM_FORMAT pcmFormat;
+		MV_U16 pcmSlot[MV_TDM_TOTAL_CHANNELS];
+		MV_U8 samplingPeriod;
+		MV_U16 totalChannels;
+	} MV_TDM_PARAMS;
+
+	typedef struct {
+		MV_U8 spiMode;
+		MV_U8 maxCs;
+		MV_U16 model;
+		MV_U16 ctrlRev;
+		MV_FRAME_TS frameTs;
+	} MV_TDM_HAL_DATA;
+
+	typedef struct {
+		MV_U32 cmdStatus;
+		MV_U16 byteCnt;
+		MV_U16 buffSize;
+		MV_U32 physBuffPtr;
+		MV_U32 physNextDescPtr;
+	} MV_TDM_MCDMA_RX_DESC;
+
+	typedef struct {
+		MV_U32 cmdStatus;
+		MV_U16 shadowByteCnt;
+		MV_U16 byteCnt;
+		MV_U32 physBuffPtr;
+		MV_U32 physNextDescPtr;
+	} MV_TDM_MCDMA_TX_DESC;
+
+	typedef struct {
+		MV_U32 mask:8;
+		MV_U32 ch:8;
+		MV_U32 mgs:2;
+		MV_U32 byte:1;
+		MV_U32 strb:2;
+		MV_U32 elpb:1;
+		MV_U32 tbs:1;
+		MV_U32 rpt:2;
+		MV_U32 last:1;
+		MV_U32 ftint:1;
+		MV_U32 reserved31_27:5;
+	} MV_TDM_DPRAM_ENTRY;
+
+/* CommUnit APIs */
+	MV_STATUS mvCommUnitHalInit(MV_TDM_PARAMS *pTdmParams, MV_TDM_HAL_DATA *halData);
+	MV_STATUS mvCommUnitWinInit(MV_UNIT_WIN_INFO *pAddrWinMap);
+	MV_VOID mvCommUnitIntLow(MV_TDM_INT_INFO *pTdmIntInfo);
+	MV_VOID mvCommUnitPcmStart(MV_VOID);
+	MV_VOID mvCommUnitPcmStop(MV_VOID);
+	MV_STATUS mvCommUnitTx(MV_U8 *pTdmTxBuff);
+	MV_STATUS mvCommUnitRx(MV_U8 *pTdmRxBuff);
+	MV_VOID mvCommUnitShow(MV_VOID);
+	MV_VOID mvCommUnitRelease(MV_VOID);
+	MV_VOID mvCommUnitIntEnable(MV_U8 deviceId);
+	MV_VOID mvCommUnitIntDisable(MV_U8 deviceId);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* __INCmvCommUnith */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnitAddrDec.c b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnitAddrDec.c
new file mode 100755
index 0000000..4604a50
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnitAddrDec.c
@@ -0,0 +1,339 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "voiceband/commUnit/mvCommUnitRegs.h"
+
+static MV_TARGET commUnitAddrDecPrioTable[] = {
+	SDRAM_CS0,
+	SDRAM_CS1,
+	SDRAM_CS2,
+	SDRAM_CS3,
+	PEX0_MEM,
+	PEX0_IO,
+	TBL_TERM
+};
+
+static MV_STATUS mvCommUnitWinRead(MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin);
+static MV_STATUS mvCommUnitWinWrite(MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin);
+static INLINE MV_VOID mvCommUnitWinEnable(MV_U32 winNum, MV_BOOL enable);
+static MV_STATUS commUnitWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
+
+/*******************************************************************************
+* mvCommUnitWinInit - Initialize CommUnit address decode windows
+*
+* DESCRIPTION:
+*               This function initialize CommUnit window decode unit. It set the
+*               default address decode
+*               windows of the unit.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if setting fail.
+*******************************************************************************/
+MV_STATUS mvCommUnitWinInit(MV_UNIT_WIN_INFO *pAddrWinMap)
+{
+	MV_U32 winNum;
+	MV_U32 winPrioIndex = 0;
+	MV_UNIT_WIN_INFO *addrDecWin;
+
+	/* Clear access for all windows */
+	MV_REG_WRITE(COMM_UNIT_WINDOWS_ACCESS_PROTECT_REG, 0);
+
+	/* Disable all windows */
+	for (winNum = 0; winNum < COMM_UNIT_MBUS_MAX_WIN; winNum++)
+		mvCommUnitWinEnable(winNum, MV_FALSE);
+
+	for (winNum = 0; ((commUnitAddrDecPrioTable[winPrioIndex] != TBL_TERM) && (winNum < COMM_UNIT_MBUS_MAX_WIN));) {
+		addrDecWin = &pAddrWinMap[commUnitAddrDecPrioTable[winPrioIndex]];
+
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvCommUnitWinWrite(winNum, addrDecWin)) {
+				mvOsPrintf("mvCommUnitWinInit: failed setting window(%d)\n", winNum);
+				return MV_ERROR;
+			}
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCommUnitWinWrite - Set CommUnit target address window
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0)
+*       address window, also known as address decode window.
+*       After setting this target window, the CommUnit will be able to access the
+*       target within the address window.
+*
+* INPUT:
+*       winNum      - CommUnit to target address decode window number.
+*       pDecWin     - CommUnit target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if address window overlaps with other address decode windows.
+*       MV_BAD_PARAM if base address is invalid parameter or target is
+*       unknown.
+*
+*******************************************************************************/
+static MV_STATUS mvCommUnitWinWrite(MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin)
+{
+	MV_U32 ctrlReg = 0, sizeReg = 0;
+	MV_U32 size;
+
+	/* Parameter checking   */
+	if (winNum >= COMM_UNIT_MBUS_MAX_WIN) {
+		mvOsPrintf("mvCommUnitWinWrite: ERR. Invalid win num %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlaps with current windows         */
+	if (MV_TRUE == commUnitWinOverlapDetect(winNum, &pDecWin->addrWin)) {
+		mvOsPrintf("mvCommUnitWinWrite: ERR. Window %d overlap\n", winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) {
+		mvOsPrintf("mvCommUnitWinWrite: Error setting CommUnit window %d"
+			   "\nAddress 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pDecWin->addrWin.baseLow, pDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	size = (pDecWin->addrWin.size / MV_COMM_UNIT_WIN_SIZE_ALIGN) - 1;
+
+	/* for the safe side we disable the window before writing the new
+	   values */
+	mvCommUnitWinEnable(winNum, MV_FALSE);
+
+	ctrlReg |= ((pDecWin->attrib << COMM_UNIT_WIN_ATTRIB_OFFS) & COMM_UNIT_WIN_ATTRIB_MASK);
+	ctrlReg |= ((pDecWin->targetId << COMM_UNIT_WIN_TARGET_OFFS) & COMM_UNIT_WIN_TARGET_MASK);
+	ctrlReg |= (pDecWin->addrWin.baseLow & COMM_UNIT_WIN_BASE_MASK);
+
+	/* Update Size value  */
+	sizeReg |= ((size << COMM_UNIT_WIN_SIZE_OFFS) & COMM_UNIT_WIN_SIZE_MASK);
+
+	/* Write to address size and control registers  */
+	MV_REG_WRITE(COMM_UNIT_WIN_SIZE_REG(winNum), sizeReg);
+	MV_REG_WRITE(COMM_UNIT_WIN_CTRL_REG(winNum), ctrlReg);
+
+	/* Enable address decode target window  */
+	if (pDecWin->enable == MV_TRUE)
+		mvCommUnitWinEnable(winNum, MV_TRUE);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCommUnitWinRead - Read peripheral target address window.
+*
+* DESCRIPTION:
+*               Read CommUnit peripheral target address window.
+*
+* INPUT:
+*       winNum - CommUnit to target address decode window number.
+*
+* OUTPUT:
+*       pDecWin - CommUnit target window data structure.
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+MV_STATUS mvCommUnitWinRead(MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin)
+{
+
+	MV_U32 ctrlReg, sizeReg, enReg;
+	MV_U32 size;
+
+	/* Parameter checking   */
+	if (winNum >= COMM_UNIT_MBUS_MAX_WIN) {
+		mvOsPrintf("mvCommUnitWinRead: ERR. Invalid winNum %d\n", winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	sizeReg = MV_REG_READ(COMM_UNIT_WIN_SIZE_REG(winNum));
+	ctrlReg = MV_REG_READ(COMM_UNIT_WIN_CTRL_REG(winNum));
+	enReg = MV_REG_READ(COMM_UNIT_WIN_ENABLE_REG(winNum));
+
+	/* Check if window is enabled   */
+	if (enReg & COMM_UNIT_WIN_ENABLE_MASK) {
+		pDecWin->enable = MV_TRUE;
+
+		/* Extract window parameters from registers */
+		pDecWin->targetId = (ctrlReg & COMM_UNIT_WIN_TARGET_MASK) >> COMM_UNIT_WIN_TARGET_OFFS;
+		pDecWin->attrib = (ctrlReg & COMM_UNIT_WIN_ATTRIB_MASK) >> COMM_UNIT_WIN_ATTRIB_OFFS;
+		pDecWin->addrWin.baseLow = (ctrlReg & COMM_UNIT_WIN_BASE_MASK);
+		pDecWin->addrWin.baseHigh = 0;
+
+		size = (sizeReg & COMM_UNIT_WIN_SIZE_MASK) >> COMM_UNIT_WIN_SIZE_OFFS;
+		pDecWin->addrWin.size = (size + 1) * MV_COMM_UNIT_WIN_SIZE_ALIGN;
+	} else {
+		pDecWin->enable = MV_FALSE;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvCommUnitWinEnable - Enable/disable a CommUnit to target address window
+*
+* DESCRIPTION:
+*       This function enable/disable a CommUnit to target address window.
+*       According to parameter 'enable' the routine will enable the
+*       window, thus enabling CommUnit accesses.
+*       Otherwise, the window will be disabled.
+*
+* INPUT:
+*       winNum - CommUnit to target address decode window number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_ERROR if decode window number was wrong or enabled window overlaps.
+*
+*******************************************************************************/
+static INLINE MV_VOID mvCommUnitWinEnable(MV_U32 winNum, MV_BOOL enable)
+{
+	MV_U32 enReg = 0, accProtWin = 0;
+
+	enReg = MV_REG_READ(COMM_UNIT_WIN_ENABLE_REG(winNum));
+	accProtWin = MV_REG_READ(COMM_UNIT_WINDOWS_ACCESS_PROTECT_REG);
+
+	if (enable == MV_TRUE) {
+		MV_REG_WRITE(COMM_UNIT_WIN_ENABLE_REG(winNum), (enReg | COMM_UNIT_WIN_ENABLE_MASK));
+		MV_REG_WRITE(COMM_UNIT_WINDOWS_ACCESS_PROTECT_REG, (accProtWin | COMM_UNIT_WIN_PROTECT_MASK(winNum)));
+
+	} else {
+		MV_REG_WRITE(COMM_UNIT_WIN_ENABLE_REG(winNum), 0 /*(enReg & ((MV_U32)~COMM_UNIT_WIN_ENABLE_MASK)) */);
+		MV_REG_WRITE(COMM_UNIT_WINDOWS_ACCESS_PROTECT_REG,
+			     (accProtWin & ((MV_U32) ~COMM_UNIT_WIN_PROTECT_MASK(winNum))));
+	}
+}
+
+/*******************************************************************************
+* commUnitWinOverlapDetect - Detect CommUnit address windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviour is expected in case CommUnit address decode
+*       windows overlaps.
+*       This function detects CommUnit address decode windows overlapping of a
+*       specified window. The function does not check the window itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pDecWin     - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS commUnitWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 winNumIndex;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	for (winNumIndex = 0; winNumIndex < COMM_UNIT_MBUS_MAX_WIN; winNumIndex++) {
+		/* Do not check window itself       */
+		if (winNumIndex == winNum)
+			continue;
+
+		/* Get window parameters    */
+		if (MV_OK != mvCommUnitWinRead(winNumIndex, &addrDecWin)) {
+			mvOsPrintf("%s: ERR. TargetWinGet failed\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled windows    */
+		if (addrDecWin.enable == MV_FALSE)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+			return MV_TRUE;
+	}
+
+	return MV_FALSE;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnitRegs.h b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnitRegs.h
new file mode 100755
index 0000000..f20b7ff
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/commUnit/mvCommUnitRegs.h
@@ -0,0 +1,448 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvCommUnitRegsh
+#define __INCmvCommUnitRegsh
+
+#include "mvSysTdmConfig.h"
+
+/****************************************************************/
+/*	Time Division Multiplexing Interrupt Controller		*/
+/****************************************************************/
+#define COMM_UNIT_TOP_CAUSE_REG			(MV_COMM_UNIT_REGS_BASE + 0x8C00)
+#define TDM_CAUSE_REG				(MV_COMM_UNIT_REGS_BASE + 0x8C40)
+#define COMM_UNIT_TOP_MASK_REG			(MV_COMM_UNIT_REGS_BASE + 0x8C80)
+#define VOICE_PERIODICAL_INT_CONTROL_REG	(MV_COMM_UNIT_REGS_BASE + 0x8C90)
+#define TDM_MASK_REG				(MV_COMM_UNIT_REGS_BASE + 0x8CC0)
+
+/* COMM_UNIT_TOP_CAUSE_REG bits */
+#define TDM_SUM_INT_OFFS			6
+#define TDM_SUM_INT_MASK			(1 << TDM_SUM_INT_OFFS)
+#define MCSC_SUM_INT_OFFS			28
+#define MCSC_SUM_INT_MASK			(1 << MCSC_SUM_INT_OFFS)
+
+/* TDM_CAUSE_REG bits */
+#define FLEX_TDM_RX_INT_OFFS			2
+#define FLEX_TDM_RX_INT_MASK			(1 << FLEXTDM_RX_INT_OFFS)
+#define FLEX_TDM_RX_SYNC_LOSS_OFFS		3
+#define FLEX_TDM_RX_SYNC_LOSS_MASK		(1 << FLEX_TDM_RX_SYNC_LOSS_OFFS)
+#define FLEX_TDM_TX_INT_OFFS			6
+#define FLEX_TDM_TX_INT_MASK			(1 << FLEXTDM_TX_INT_OFFS)
+#define FLEX_TDM_TX_SYNC_LOSS_OFFS		7
+#define FLEX_TDM_TX_SYNC_LOSS_MASK		(1 << FLEX_TDM_TX_SYNC_LOSS_OFFS)
+#define RX_VOICE_INT_PULSE_OFFS			8
+#define RX_VOICE_INT_PULSE_MASK			(1 << RX_VOICE_INT_PULSE_OFFS)
+#define TX_VOICE_INT_PULSE_OFFS			9
+#define TX_VOICE_INT_PULSE_MASK			(1 << TX_VOICE_INT_PULSE_OFFS)
+#define EXT_INT_SLIC0_OFFS			10
+#define EXT_INT_SLIC0_MASK			(1 << EXT_INT_SLIC0_OFFS)
+#define EXT_INT_SLIC1_OFFS			11
+#define EXT_INT_SLIC1_MASK			(1 << EXT_INT_SLIC1_OFFS)
+#define EXT_INT_SLIC2_OFFS			12
+#define EXT_INT_SLIC2_MASK			(1 << EXT_INT_SLIC2_OFFS)
+#define EXT_INT_SLIC3_OFFS			13
+#define EXT_INT_SLIC3_MASK			(1 << EXT_INT_SLIC3_OFFS)
+#define EXT_INT_SLIC4_OFFS			14
+#define EXT_INT_SLIC4_MASK			(1 << EXT_INT_SLIC4_OFFS)
+#define EXT_INT_SLIC5_OFFS			15
+#define EXT_INT_SLIC5_MASK			(1 << EXT_INT_SLIC5_OFFS)
+#define EXT_INT_SLIC6_OFFS			16
+#define EXT_INT_SLIC6_MASK			(1 << EXT_INT_SLIC6_OFFS)
+#define EXT_INT_SLIC7_OFFS			17
+#define EXT_INT_SLIC7_MASK			(1 << EXT_INT_SLIC7_OFFS)
+#define COMM_UNIT_PAR_ERR_SUM_OFFS		18
+#define COMM_UNIT_PAR_ERR_SUM_MASK		(1 << COMM_UNIT_PAR_ERR_SUM_OFFS)
+#define TDM_RX_PAR_ERR_SUM_OFFS			19
+#define TDM_RX_PAR_ERR_SUM_MASK			(1 << TDM_RX_PAR_ERR_SUM_OFFS)
+#define TDM_TX_PAR_ERR_SUM_OFFS			20
+#define TDM_TX_PAR_ERR_SUM_MASK			(1 << TDM_TX_PAR_ERR_SUM_OFFS)
+#define MCSC_PAR_ERR_SUM_OFFS			21
+#define MCSC_PAR_ERR_SUM_MASK			(1 << MCSC_PAR_ERR_SUM_OFFS)
+#define MCDMA_PAR_ERR_SUM_OFFS			22
+#define MCDMA_PAR_ERR_SUM_MASK			(1 << MCDMA_PAR_ERR_SUM_OFFS)
+
+/*  VOICE_PERIODICAL_INT_CONTROL_REG bits  */
+#define RX_VOICE_INT_CNT_REF_OFFS		0
+#define RX_VOICE_INT_CNT_REF_MASK		(0xff << RX_VOICE_INT_CNT_REF_OFFS)
+#define TX_VOICE_INT_CNT_REF_OFFS		8
+#define TX_VOICE_INT_CNT_REF_MASK		(0xff << TX_VOICE_INT_CNT_REF_OFFS)
+#define RX_FIRST_DELAY_REF_OFFS			16
+#define RX_FIRST_DELAY_REF_MASK			(0xff << RX_FIRST_DELAY_REF_OFFS)
+#define TX_FIRST_DELAY_REF_OFFS			24
+#define TX_FIRST_DELAY_REF_MASK			(0xff << TX_FIRST_DELAY_REF_OFFS)
+
+/************************************************/
+/*	Multi-Channel Serial Controller(MCSC)  	*/
+/************************************************/
+#define MCSC_CHx_COMM_EXEC_STAT_REG(ch)		(MV_COMM_UNIT_REGS_BASE + (ch<<2))
+#define MCSC_CHx_RECEIVE_CONFIG_REG(ch)		((MV_COMM_UNIT_REGS_BASE + 0x400) + (ch<<2))
+#define MCSC_CHx_TRANSMIT_CONFIG_REG(ch)	((MV_COMM_UNIT_REGS_BASE + 0x1800) + (ch<<2))
+#define MCSC_GLOBAL_CONFIG_REG			(MV_COMM_UNIT_REGS_BASE + 0x2800)
+#define MCSC_GLOBAL_INT_CAUSE_REG		(MV_COMM_UNIT_REGS_BASE + 0x2804)
+#define MCSC_EXTENDED_INT_CAUSE_REG		(MV_COMM_UNIT_REGS_BASE + 0x2808)
+#define MCSC_GLOBAL_INT_MASK_REG		(MV_COMM_UNIT_REGS_BASE + 0x280C)
+#define MCSC_EXTENDED_INT_MASK_REG		(MV_COMM_UNIT_REGS_BASE + 0x2810)
+#define MCSC_TX_CHANNEL_BALANCING_MASK_REG	(MV_COMM_UNIT_REGS_BASE + 0x284C)
+#define MCSC_RX_CHANNEL_BALANCING_MASK_REG	(MV_COMM_UNIT_REGS_BASE + 0x2850)
+
+/* MCSC_CHx_COMM_EXEC_STAT_REG bits */
+#define MCSC_ABR_E_STAT_OFFS			25
+#define MCSC_ABR_E_STAT_MASK			(1 << MCSC_ABR_E_STAT_OFFS)
+#define MCSC_EH_E_STAT_OFFS			26
+#define MCSC_EH_E_STAT_MASK			(1 << MCSC_EH_E_STAT_OFFS)
+
+/* MCSC_RECEIVE_CONFIG_REG(MRCRx) bits */
+#define MRCRx_ABORT_OFFS			21
+#define MRCRx_ABORT_MASK			(1 << MRCRx_ABORT_OFFS)
+#define MRCRx_ENTER_HUNT_OFFS			22
+#define MRCRx_ENTER_HUNT_MASK			(1 << MRCRx_ENTER_HUNT_OFFS)
+#define MRCRx_ER_OFFS				27
+#define MRCRx_ER_MASK				(1 << MRCRx_ER_OFFS)
+#define MRCRx_RRVD_OFFS				30
+#define MRCRx_RRVD_MASK				(1 << MRCRx_RRVD_OFFS)
+#define MRCRx_MODE_OFFS				31
+#define MRCRx_MODE_MASK				(1 << MRCRx_MODE_OFFS)
+
+/* MCSC_TRANSMIT_CONFIG_REG(MTCRx) bits */
+#define MTCRx_ET_OFFS				27
+#define MTCRx_ET_MASK				(1 << MTCRx_ET_OFFS)
+#define MTCRx_TRVD_OFFS				30
+#define MTCRx_TRVD_MASK				(1 << MTCRx_TRVD_OFFS)
+#define MTCRx_MODE_OFFS				31
+#define MTCRx_MODE_MASK				(1 << MTCRx_MODE_OFFS)
+
+/* MCSC_GLOBAL_CONFIG_REG bits */
+#define MCSC_GLOBAL_CONFIG_RCBD_OFFS		19
+#define MCSC_GLOBAL_CONFIG_RCBD_MASK		(1 << MCSC_GLOBAL_CONFIG_RCBD_OFFS)
+#define MCSC_GLOBAL_CONFIG_TCBD_OFFS		20
+#define MCSC_GLOBAL_CONFIG_TCBD_MASK		(1 << MCSC_GLOBAL_CONFIG_TCBD_OFFS)
+#define MCSC_GLOBAL_CONFIG_MAI_OFFS		21
+#define MCSC_GLOBAL_CONFIG_MAI_MASK		(1 << MCSC_GLOBAL_CONFIG_MAI_OFFS)
+#define MCSC_GLOBAL_CONFIG_LMD_OFFS		22
+#define MCSC_GLOBAL_CONFIG_LMD_MASK		(1 << MCSC_GLOBAL_CONFIG_LMD_OFFS)
+#define MCSC_GLOBAL_CONFIG_ARBM_OFFS		29
+#define MCSC_GLOBAL_CONFIG_ARBM_MASK		(1 << MCSC_GLOBAL_CONFIG_ARBM_OFFS)
+#define MCSC_GLOBAL_CONFIG_RXEN_OFFS		30
+#define MCSC_GLOBAL_CONFIG_RXEN_MASK		(1 << MCSC_GLOBAL_CONFIG_RXEN_OFFS)
+#define MCSC_GLOBAL_CONFIG_TXEN_OFFS		31
+#define MCSC_GLOBAL_CONFIG_TXEN_MASK		(1 << MCSC_GLOBAL_CONFIG_TXEN_OFFS)
+
+/* MCSC_GLOBAL_INT_CAUSE_REG */
+#define  MCSC_GLOBAL_INT_CAUSE_RXOR_OFFS	0
+#define  MCSC_GLOBAL_INT_CAUSE_RXOR_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_RXOR_OFFS)
+#define  MCSC_GLOBAL_INT_CAUSE_TXUR_OFFS	8
+#define  MCSC_GLOBAL_INT_CAUSE_TXUR_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_TXUR_OFFS)
+#define  MCSC_GLOBAL_INT_CAUSE_TXOR_OFFS	16
+#define  MCSC_GLOBAL_INT_CAUSE_TXOR_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_TXOR_OFFS)
+#define  MCSC_GLOBAL_INT_CAUSE_RXBOR_OFFS	24
+#define  MCSC_GLOBAL_INT_CAUSE_RXBOR_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_RXBOR_OFFS)
+#define  MCSC_GLOBAL_INT_CAUSE_INIT_DONE_OFFS	25
+#define  MCSC_GLOBAL_INT_CAUSE_INIT_DONE_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_INIT_DONE_OFFS)
+#define  MCSC_GLOBAL_INT_CAUSE_IQOR_OFFS	26
+#define  MCSC_GLOBAL_INT_CAUSE_IQOR_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_IQOR_OFFS)
+#define  MCSC_GLOBAL_INT_CAUSE_IQNE_OFFS	27
+#define  MCSC_GLOBAL_INT_CAUSE_IQNE_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_IQNE_OFFS)
+#define  MCSC_GLOBAL_INT_CAUSE_MDIL_OFFS	28
+#define  MCSC_GLOBAL_INT_CAUSE_MDIL_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_MDIL_OFFS)
+#define  MCSC_GLOBAL_INT_CAUSE_MGIS_OFFS	30
+#define  MCSC_GLOBAL_INT_CAUSE_MGIS_MASK	(1 << MCSC_GLOBAL_INT_CAUSE_MGIS_OFFS)
+
+/************************************************/
+/*	Multi-Channel DMA(MCDMA)       		*/
+/************************************************/
+#define MCDMA_RECEIVE_CONTROL_REG(ch)		((MV_COMM_UNIT_REGS_BASE + 0x3000) + (ch<<2))
+#define MCDMA_RECEIVE_FIFO_MGMT_LL_REG(ch)	((MV_COMM_UNIT_REGS_BASE + 0x3C00) + (ch<<2))
+#define MCDMA_CURRENT_RECEIVE_DESC_PTR_REG(ch)	((MV_COMM_UNIT_REGS_BASE + 0x4000) + (ch<<2))
+#define MCDMA_GLOBAL_CONTROL_REG		(MV_COMM_UNIT_REGS_BASE + 0x4400)
+#define RX_SERVICE_QUEUE_ARBITER_WEIGHT_REG	(MV_COMM_UNIT_REGS_BASE + 0x4408)
+#define MCDMA_TRANSMIT_CONTROL_REG(ch)		((MV_COMM_UNIT_REGS_BASE + 0x5000) + (ch<<2))
+#define MCDMA_TRANSMIT_FIFO_MGMT_LL_REG(ch)	((MV_COMM_UNIT_REGS_BASE + 0x5C00) + (ch<<2))
+#define MCDMA_CURRENT_TRANSMIT_DESC_PTR_REG(ch)	((MV_COMM_UNIT_REGS_BASE + 0x7000) + (ch<<2))
+#define TX_SERVICE_QUEUE_ARBITER_WEIGHT_REG	(MV_COMM_UNIT_REGS_BASE + 0x7408)
+
+/* MCDMA_RECEIVE_CONTROL_REG bits */
+#define MCDMA_RBSZ_OFFS				0
+#define MCDMA_RBSZ_MASK				(0x3 << MCDMA_RBSZ_OFFS)
+#define MCDMA_RBSZ_8BYTE			0
+#define MCDMA_RBSZ_16BYTE			0x1
+#define MCDMA_RBSZ_32BYTE			0x2
+#define MCDMA_RBSZ_64BYTE			0x3
+
+#define MCDMA_BLMR_OFFS				2
+#define MCDMA_BLMR_MASK				(1 << MCDMA_BLMR_OFFS)
+#define MCDMA_ERD_OFFS				6
+#define MCDMA_ERD_MASK				(1 << MCDMA_ERD_OFFS)
+
+/* MCDMA_GLOBAL_CONTROL_REG bits */
+#define MCDMA_RID_OFFS				1
+#define MCDMA_RID_MASK				(1 << MCDMA_RID_OFFS)
+
+/* RX_SERVICE_QUEUE_ARBITER_WEIGHT_REG bits */
+#define MCDMA_RSQW_OFFS				24
+#define MCDMA_RSQW_MASK				(0x1f << MCDMA_RSQW_OFFS)
+
+/* TX_SERVICE_QUEUE_ARBITER_WEIGHT_REG bits */
+#define MCDMA_TSQW_OFFS				24
+#define MCDMA_TSQW_MASK				(0x1f << MCDMA_TSQW_OFFS)
+
+/* MCDMA_TRANSMIT_CONTROL_REG bits */
+#define MCDMA_FSIZE_OFFS			0
+#define MCDMA_FSIZE_MASK			(0xff << MCDMA_FSIZE_OFFS)
+#define MCDMA_FSIZE_1BLK			0x1
+#define MCDMA_TBSZ_OFFS				8
+#define MCDMA_TBSZ_MASK				(0x3 << MCDMA_TBSZ_OFFS)
+#define MCDMA_TBSZ_8BYTE			(0x0 << MCDMA_TBSZ_OFFS)
+#define MCDMA_TBSZ_16BYTE			(0x1 << MCDMA_TBSZ_OFFS)
+#define MCDMA_TBSZ_32BYTE			(0x2 << MCDMA_TBSZ_OFFS)
+
+#define MCDMA_BLMT_OFFS				10
+#define MCDMA_BLMT_MASK				(1 << MCDMA_BLMT_OFFS)
+#define MCDMA_NDUR_OFFS				12
+#define MCDMA_NDUR_MASK				(1 << MCDMA_NDUR_OFFS)
+#define MCDMA_TPC_OFFS				13
+#define MCDMA_TPC_MASK				(1 << MCDMA_TPC_OFFS)
+#define MCDMA_URPM_OFFS				14
+#define MCDMA_URPM_MASK				(1 << MCDMA_URPM_OFFS)
+#define MCDMA_STD_OFFS				15
+#define MCDMA_STD_MASK				(1 << MCDMA_STD_OFFS)
+#define MCDMA_AT_OFFS				16
+#define MCDMA_AT_MASK				(1 << MCDMA_AT_OFFS)
+#define MCDMA_TXD_OFFS				17
+#define MCDMA_TXD_MASK				(1 << MCDMA_TXD_OFFS)
+
+/************************************************/
+/*	Time Division Multiplexing(TDM)	  	*/
+/************************************************/
+#define FLEX_TDM_TDPR_REG(entry)		((MV_COMM_UNIT_REGS_BASE + 0x8000) + (entry<<2))
+#define FLEX_TDM_RDPR_REG(entry)		((MV_COMM_UNIT_REGS_BASE + 0x8400) + (entry<<2))
+#define FLEX_TDM_TRANSMIT_READ_PTR_REG		(MV_COMM_UNIT_REGS_BASE + 0x8800)
+#define FLEX_TDM_RECEIVE_READ_PTR_REG		(MV_COMM_UNIT_REGS_BASE + 0x8804)
+#define FLEX_TDM_CONFIG_REG			(MV_COMM_UNIT_REGS_BASE + 0x8808)
+#define TDM_CLK_AND_SYNC_CONTROL_REG		(MV_COMM_UNIT_REGS_BASE + 0x881C)
+#define TDM_CLK_DIVIDER_CONTROL_REG		(MV_COMM_UNIT_REGS_BASE + 0x8820)
+#define TDM_RESV_CLK_DIVIDER_CONTROL_REG	(MV_COMM_UNIT_REGS_BASE + 0x8824)
+#define TDM_DATA_DELAY_AND_CLK_CTRL_REG		(MV_COMM_UNIT_REGS_BASE + 0x8CD0)
+#define TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_OUT_REG	(MV_COMM_UNIT_REGS_BASE + 0x8CD4)
+#define TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_IN_REG	(MV_COMM_UNIT_REGS_BASE + 0x8CD8)
+
+/* TDM_CLK_AND_SYNC_CONTROL_REG bits */
+#define TDM_TX_FSYNC_OUT_ENABLE_OFFS		0
+#define TDM_TX_FSYNC_OUT_ENABLE_MASK		(1 << TDM_TX_FSYNC_OUT_ENABLE_OFFS)
+#define TDM_RX_FSYNC_OUT_ENABLE_OFFS		1
+#define TDM_RX_FSYNC_OUT_ENABLE_MASK		(1 << TDM_RX_FSYNC_OUT_ENABLE_OFFS)
+#define TDM_TX_CLK_OUT_ENABLE_OFFS		2
+#define TDM_TX_CLK_OUT_ENABLE_MASK		(1 << TDM_TX_CLK_OUT_ENABLE_OFFS)
+#define TDM_RX_CLK_OUT_ENABLE_OFFS		3
+#define TDM_RX_CLK_OUT_ENABLE_MASK		(1 << TDM_RX_CLK_OUT_ENABLE_OFFS)
+#define TDM_TX_REFCLK_DIVIDER_OFFS		4
+#define TDM_TX_REFCLK_DIVIDER_MASK		(0xff << TDM_TX_REFCLK_DIVIDER_OFFS)
+#define TDM_TX_REFCLK_DIVIDER_2MHZ		BIT7
+#define TDM_TX_REFCLK_DIVIDER_4MHZ		BIT8
+#define TDM_TX_REFCLK_DIVIDER_8MHZ		BIT9
+#define TDM_RX_REFCLK_DIVIDER_OFFS		12
+#define TDM_RX_REFCLK_DIVIDER_MASK		(0xff << TDM_RX_REFCLK_DIVIDER_OFFS)
+#define TDM_RX_REFCLK_DIVIDER_2MHZ		BIT15
+#define TDM_RX_REFCLK_DIVIDER_4MHZ		BIT16
+#define TDM_RX_REFCLK_DIVIDER_8MHZ		BIT17
+#define TDM_FSYNC_INVERT_OFFS			19
+#define TDM_FSYNC_INVERT_DISABLE		(0 << TDM_FSYNC_INVERT_OFFS)
+#define TDM_FSYNC_INVERT_ENABLE			(1 << TDM_FSYNC_INVERT_OFFS)
+#define TDM_REFCLK_DIVIDER_BYPASS_OFFS		20
+#define TDM_REFCLK_DIVIDER_BYPASS_MASK		(3 << TDM_REFCLK_DIVIDER_BYPASS_OFFS)
+#define TDM_OUT_CLK_SRC_CTRL_OFFS		24
+#define TDM_OUT_CLK_SRC_CTRL_BEFORE_DIV		(0 << TDM_OUT_CLK_SRC_CTRL_OFFS)
+#define TDM_OUT_CLK_SRC_CTRL_AFTER_DIV		(1 << TDM_OUT_CLK_SRC_CTRL_OFFS)
+#define TDM_PROG_TDM_SLIC_RESET_OFFS		31
+#define TDM_PROG_TDM_SLIC_RESET_MASK		(1 << TDM_PROG_TDM_SLIC_RESET_OFFS)
+
+/* TDM_RX_CLK_DIVIDER_CONTROL_REG bits */
+#define TDM_RX_FIXED_DIV_ENABLE_OFFS		31
+#define TDM_RX_FIXED_DIV_ENABLE_MASK		(1 << TDM_RX_FIXED_DIV_ENABLE_OFFS)
+
+/* TDM_TX_CLK_DIVIDER_CONTROL_REG bits */
+#define TDM_TX_FIXED_DIV_ENABLE_OFFS		31
+#define TDM_TX_FIXED_DIV_ENABLE_MASK		(1 << TDM_TX_FIXED_DIV_ENABLE_OFFS)
+
+/* FLEX_TDM_CONFIG_REG bits */
+#define TDM_RR2HALF_OFFS			15
+#define TDM_RR2HALF_MASK			(1 << TDM_RR2HALF_OFFS)
+#define TDM_TR2HALF_OFFS			16
+#define TDM_TR2HALF_MASK			(1 << TDM_TR2HALF_OFFS)
+#define TDM_SE_OFFS				20
+#define TDM_SE_MASK				(1 << TDM_SE_OFFS)
+#define TDM_COMMON_RX_TX_OFFS			23
+#define TDM_COMMON_RX_TX_MASK			(1 << TDM_COMMON_RX_TX_OFFS)
+#define TSD_OFFS				25
+#define TSD_MASK				(0x3 << TSD_OFFS)
+#define TSD_NO_DELAY				(0 << TSD_OFFS)
+#define TSD_1BIT_DELAY				(1 << TSD_OFFS)
+#define TSD_2BIT_DELAY				(2 << TSD_OFFS)
+#define TSD_3BIT_DELAY				(3 << TSD_OFFS)
+#define RSD_OFFS				27
+#define RSD_MASK				(0x3 << RSD_OFFS)
+#define RSD_NO_DELAY				(0 << RSD_OFFS)
+#define RSD_1BIT_DELAY				(1 << RSD_OFFS)
+#define RSD_2BIT_DELAY				(2 << RSD_OFFS)
+#define RSD_3BIT_DELAY				(3 << RSD_OFFS)
+#define TDM_TEN_OFFS				31
+#define TDM_TEN_MASK				(1 << TDM_TEN_OFFS)
+
+/* TDM_DATA_DELAY_AND_CLK_CTRL_REG bits */
+#define TX_CLK_OUT_ENABLE_OFFS			0
+#define TX_CLK_OUT_ENABLE_MASK			(1 << TX_CLK_OUT_ENABLE_OFFS)
+#define RX_CLK_OUT_ENABLE_OFFS			1
+#define RX_CLK_OUT_ENABLE_MASK			(1 << RX_CLK_OUT_ENABLE_OFFS)
+#define FIXED_POINT_RX_SYNC_OFFS		2
+#define FIXED_POINT_RX_SYNC_MASK		(1 << FIXED_POINT_RX_SYNC_OFFS)
+#define TX_DELAY_HOTBIT_OFFS			4
+#define TX_NO_DELAY				(0 << TX_DELAY_HOTBIT_OFFS)
+#define TX_1BIT_DELAY				(1 << TX_DELAY_HOTBIT_OFFS)
+#define TX_2BIT_DELAY				(2 << TX_DELAY_HOTBIT_OFFS)
+#define TX_3BIT_DELAY				(4 << TX_DELAY_HOTBIT_OFFS)
+#define TX_4BIT_DELAY				(8 << TX_DELAY_HOTBIT_OFFS)
+#define RX_DELAY_HOTBIT_OFFS			8
+#define RX_NO_DELAY				(0 << RX_DELAY_HOTBIT_OFFS)
+#define RX_1BIT_DELAY				(1 << RX_DELAY_HOTBIT_OFFS)
+#define RX_2BIT_DELAY				(2 << RX_DELAY_HOTBIT_OFFS)
+#define RX_3BIT_DELAY				(4 << RX_DELAY_HOTBIT_OFFS)
+#define RX_4BIT_DELAY				(8 << RX_DELAY_HOTBIT_OFFS)
+
+/* TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_OUT_REG bits */
+#define TX_SYNC_DELAY_OUT_OFFS			0
+#define TX_SYNC_DELAY_OUT_PLUS_MINUS_OFFS	14
+#define TX_SYNC_DELAY_OUT_PLUS			(0 << TX_SYNC_DELAY_OUT_PLUS_MINUS_OFFS)
+#define TX_SYNC_DELAY_OUT_MINUS			(1 << TX_SYNC_DELAY_OUT_PLUS_MINUS_OFFS)
+#define TX_SYNC_DELAY_OUT_RESTART_CALC_OFFS	15
+#define TX_SYNC_DELAY_OUT_RESTART_CALC_MASK	(1 << TX_SYNC_DELAY_OUT_RESTART_CALC_OFFS)
+#define RX_SYNC_DELAY_OUT_OFFS			16
+#define RX_SYNC_DELAY_OUT_PLUS_MINUS_OFFS	30
+#define RX_SYNC_DELAY_OUT_PLUS			(0 << RX_SYNC_DELAY_OUT_PLUS_MINUS_OFFS)
+#define RX_SYNC_DELAY_OUT_MINUS			(1 << RX_SYNC_DELAY_OUT_PLUS_MINUS_OFFS)
+#define RX_SYNC_DELAY_OUT_RESTART_CALC_OFFS	31
+#define RX_SYNC_DELAY_OUT_RESTART_CALC_MASK	(1 << RX_SYNC_DELAY_OUT_RESTART_CALC_OFFS)
+
+/* TDM_PLUS_MINUS_DELAY_CTRL_FSYNC_IN_REG bits */
+#define TX_SYNC_DELAY_IN_OFFS			0
+#define TX_SYNC_DELAY_IN_PLUS_MINUS_OFFS	14
+#define TX_SYNC_DELAY_IN_PLUS			(0 << TX_SYNC_DELAY_IN_PLUS_MINUS_OFFS)
+#define TX_SYNC_DELAY_IN_MINUS			(1 << TX_SYNC_DELAY_IN_PLUS_MINUS_OFFS)
+#define TX_SYNC_DELAY_IN_RESTART_CALC_OFFS	15
+#define TX_SYNC_DELAY_IN_RESTART_CALC_MASK	(1 << TX_SYNC_DELAY_IN_RESTART_CALC_OFFS)
+#define RX_SYNC_DELAY_IN_OFFS			16
+#define RX_SYNC_DELAY_IN_PLUS_MINUS_OFFS	30
+#define RX_SYNC_DELAY_IN_PLUS			(0 << RX_SYNC_DELAY_IN_PLUS_MINUS_OFFS)
+#define RX_SYNC_DELAY_IN_MINUS			(1 << RX_SYNC_DELAY_IN_PLUS_MINUS_OFFS)
+#define RX_SYNC_DELAY_IN_RESTART_CALC_OFFS	31
+#define RX_SYNC_DELAY_IN_RESTART_CALC_MASK	(1 << RX_SYNC_DELAY_IN_RESTART_CALC_OFFS)
+
+/************************************************/
+/*	Shared Bus to Crossbar Bridge		*/
+/************************************************/
+#define COMM_UNIT_MBUS_MAX_WIN			12
+
+#define COMM_UNIT_WIN_CTRL_REG(win)		((MV_COMM_UNIT_REGS_BASE + 0x8A00) + (win<<3))
+#define COMM_UNIT_WIN_SIZE_REG(win)		((MV_COMM_UNIT_REGS_BASE + 0x8A04) + (win<<3))
+#define COMM_UNIT_WIN_ENABLE_REG(win)		((MV_COMM_UNIT_REGS_BASE + 0x8B04) + (win<<2))
+#define COMM_UNIT_OVERRIDE_WIN_CONTROL_REG	(MV_COMM_UNIT_REGS_BASE + 0x8A7C)
+#define TIME_OUT_COUNTER_REG			(MV_COMM_UNIT_REGS_BASE + 0x8ADC)
+#define COMM_UNIT_WINDOWS_ACCESS_PROTECT_REG	(MV_COMM_UNIT_REGS_BASE + 0x8B00)
+
+/* COMM_UNIT_WIN_CTRL_REG bits */
+#define COMM_UNIT_WIN_TARGET_OFFS		0
+#define COMM_UNIT_WIN_TARGET_MASK		(0xf << COMM_UNIT_WIN_TARGET_OFFS)
+#define COMM_UNIT_WIN_ATTRIB_OFFS		8
+#define COMM_UNIT_WIN_ATTRIB_MASK		(0xff << COMM_UNIT_WIN_ATTRIB_OFFS)
+#define COMM_UNIT_WIN_BASE_OFFS			16
+#define COMM_UNIT_WIN_BASE_MASK			(0xffff << COMM_UNIT_WIN_BASE_OFFS)
+
+/* COMM_UNIT_WIN_SIZE_REG bits */
+#define COMM_UNIT_WIN_SIZE_OFFS			16
+#define COMM_UNIT_WIN_SIZE_MASK			(0xffff << COMM_UNIT_WIN_SIZE_OFFS)
+
+/* COMM_UNIT_WIN_ENABLE_REG bits */
+#define COMM_UNIT_WIN_ENABLE_OFFS		0
+#define COMM_UNIT_WIN_ENABLE_MASK		(0xff << COMM_UNIT_WIN_CX_ENABLE_OFFS)
+#define COMM_UNIT_WIN_CX_ENABLE_OFFS		0
+#define COMM_UNIT_WIN_CX_ENABLE_MASK		(0x1 << COMM_UNIT_WIN_CX_ENABLE_OFFS)
+#define COMM_UNIT_WIN_MCDMA_ENABLE_OFFS		3
+#define COMM_UNIT_WIN_MCDMA_ENABLE_MASK		(0x1 << COMM_UNIT_WIN_MCDMA_ENABLE_OFFS)
+#define COMM_UNIT_WIN_MCSC_ENABLE_OFFS		4
+#define COMM_UNIT_WIN_MCSC_ENABLE_MASK		(0x1 << COMM_UNIT_WIN_MCSC_ENABLE_OFFS)
+#define COMM_UNIT_WIN_TDM_ENABLE_OFFS		5
+#define COMM_UNIT_WIN_TDM_ENABLE_MASK		(0x1 << COMM_UNIT_WIN_TDM_ENABLE_OFFS)
+#define COMM_UNIT_WIN_CX_REGFILE_ENABLE_OFFS	7
+#define COMM_UNIT_WIN_CX_REGFILE_ENABLE_MASK	(0x1 << COMM_UNIT_WIN_CX_REGFILE_ENABLE_OFFS)
+
+/* TIME_OUT_COUNTER_REG bits */
+#define	TIME_OUT_THRESHOLD_COUNT_OFFS		16
+#define	TIME_OUT_THRESHOLD_COUNT_MASK		(0xffff << TIME_OUT_THRESHOLD_COUNT_OFFS)
+
+/* COMM_UNIT_WINDOWS_ACCESS_PROTECT_REG bits */
+#define COMM_UNIT_WIN_PROTECT_OFFS(win)		(win << 1)
+#define COMM_UNIT_WIN_PROTECT_MASK(win)		(0x3 << COMM_UNIT_WIN_PROTECT_OFFS(win))
+
+#define MV_COMM_UNIT_WIN_SIZE_ALIGN	_64K
+
+#endif /*__INCmvCommUnitRegsh*/
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/voiceband/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/mvSysTdmSpi.h b/arch/arm/plat-feroceon/mv_hal/voiceband/mvSysTdmSpi.h
new file mode 100755
index 0000000..b0ffc6c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/mvSysTdmSpi.h
@@ -0,0 +1,93 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __MV_SYS_TDM_SPI_H__
+#define __MV_SYS_TDM_SPI_H__
+
+#include "mvOs.h"
+
+/* Enumerators */
+typedef enum {
+	MV_NARROW_BAND = 0,
+	MV_WIDE_BAND,
+} MV_BAND_MODE;
+
+typedef enum {
+	MV_PCM_FORMAT_1BYTE = 1,
+	MV_PCM_FORMAT_2BYTES = 2,
+	MV_PCM_FORMAT_4BYTES = 4
+} MV_PCM_FORMAT;
+
+typedef enum {
+	MV_FRAME_32TS = 32,
+	MV_FRAME_64TS = 64,
+	MV_FRAME_128TS = 128
+} MV_FRAME_TS;
+
+/* APIs */
+MV_VOID mvSysTdmSpiRead(MV_U16 lineId, MV_U8 *cmdBuff, MV_U8 cmdSize, MV_U8 *dataBuff, MV_U8 dataSize);
+MV_VOID mvSysTdmSpiWrite(MV_U16 lineId, MV_U8 *cmdBuff, MV_U8 cmdSize, MV_U8 *dataBuff, MV_U8 dataSize);
+MV_VOID mvSysTdmIntEnable(MV_U8 deviceId);
+MV_VOID mvSysTdmIntDisable(MV_U8 deviceId);
+
+#endif /* __MV_SYS_TDM_SPI_H__ */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/spi.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/spi.c
new file mode 100755
index 0000000..724377d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/spi.c
@@ -0,0 +1,323 @@
+/*

+** $Id: spi.c 109 2008-10-22 19:45:09Z lajordan@SILABS.COM $

+**

+** spi.h

+** SPI driver implementation file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** File Description:

+** This is the implementation file for the SPI driver used 

+** in the ProSLIC demonstration code. 

+**

+** Dependancies:

+** 

+**

+*/

+#include "spi.h"

+#include "voiceband/mvSysTdmSpi.h"

+#include "spi/mvSpi.h"

+#include "timer.h"

+

+/*

+** Function: SPI_Init

+**

+** Description: 

+** Initializes the SPI interface

+**

+** Input Parameters: 

+** none

+**

+** Return:

+** none

+*/

+int SPI_Init (ctrl_S * hSpiGci)

+{

+	uInt8 portId = hSpiGci->portID;

+	MV_SPI_IF_PARAMS ifParams;

+	MV_SPI_TIMING_PARAMS tmngParams;

+

+	ifParams.clockPolLow = TRUE;

+	ifParams.clockPhase = SPI_CLK_BEGIN_CYC;

+	ifParams.txMsbFirst = FALSE;

+	ifParams.rxMsbFirst = FALSE;

+	

+	tmngParams.tcsh = 0x3F;

+	tmngParams.tmisoSample = 0;

+	tmngParams.tcsSetup = 0x4;

+	tmngParams.tcsHold = 0x4;

+	

+	mvSpiIfConfigSet(portId, &ifParams);

+	mvSpiTimingParamsSet(portId, &tmngParams);

+

+	return 0;

+}

+

+#define CNUM_TO_CID_QUAD(channelNumber)   (((channelNumber<<4)&0x10)|((channelNumber<<2)&0x8)|((channelNumber>>2)&0x2)|((channelNumber>>4)&0x1)|(channelNumber&0x4))

+

+static uInt8 ReadRegister (ctrl_S * hSpiGci, uInt8 channel, uInt8 regAddr)

+{

+	uInt8 cmdBuff[2];

+	uInt8 dataBuff[5];

+	uInt8 portId = hSpiGci->portID;

+#ifdef PROFILE

+	profile.regAccess++;

+#endif

+	

+	if (channel == 0xFF)

+		cmdBuff[0] = 0x80 | 0x60;

+	else

+		cmdBuff[0] = CNUM_TO_CID_QUAD(channel) | 0x60;

+	

+	cmdBuff[1] = regAddr;

+

+	mvSysTdmSpiRead(portId, cmdBuff, 2, dataBuff, 1);

+

+	return dataBuff[0];

+}

+

+static void WriteRegister (ctrl_S * hSpiGci, uInt8 channel, uInt8 regAddr, uInt8 data)

+{

+	uInt8 cmdBuff[2];

+	uInt8 portId = hSpiGci->portID;

+

+#ifdef PROFILE

+	profile.regAccess++;

+#endif

+	if (channel == 0xFF)

+		cmdBuff[0] = 0x80 | 0x20;

+	else

+		cmdBuff[0] = CNUM_TO_CID_QUAD(channel) | 0x20;

+	

+	cmdBuff[0] &= 0xBF;

+	cmdBuff[1] = regAddr;

+	

+	mvSysTdmSpiWrite(portId, cmdBuff,2 , &data, 1);

+	

+	return;

+}

+

+#define DELAY_TEST 0

+/*

+** ReadRAM()

+**

+** Read from ProSLIC RAM space

+**

+*/

+static uInt32 ReadRAM(ctrl_S * hSpiGci, uInt8 channel, uInt16 address)

+{

+	uInt8 dataByte;

+	uInt8 addrByte;

+	uInt32 dataWord = 0L;

+	uInt32 userTimeout = 100000; //USER_TIMEOUT_VAL; /* user defined timeout counter */

+	

+	/* Wait for RAM to finish */

+	while ((ReadRegister(hSpiGci, channel, RAMSTAT) & 0x01) && (userTimeout > 0)) {

+		userTimeout--;

+	}

+	/*

+	while ((ReadRegister(hSpiGci, channel, RAMSTAT) & 0x01)) {

+		userTimeout--;

+	}*/

+	/* RAM_ADR_HI[7:5] = ramAddr[10:8] */

+	addrByte = (uInt8)((address >> 3) & 0x00E0);

+	WriteRegister(hSpiGci, channel, RAM_ADDR_HI, addrByte);

+	time_DelayWrapper (NULL, DELAY_TEST);

+	/* RAM_ADR_LO[7:0] = ramAddr[7:0] */

+	addrByte = (uInt8)((address & 0x00FF));

+	WriteRegister(hSpiGci, channel, RAM_ADDR_LO, addrByte);

+	time_DelayWrapper (NULL, DELAY_TEST);

+	/* Wait for RAM to finish */

+	while ((ReadRegister(hSpiGci, channel, RAMSTAT) & 0x01) && (userTimeout > 0)) {

+		userTimeout--;

+	}

+	/*

+	while ((ReadRegister(hSpiGci, channel, RAMSTAT) & 0x01)) {

+	userTimeout--;

+}*/

+	time_DelayWrapper (NULL, DELAY_TEST);

+	/* ramData[4:0] = RAM_DATA_B0[7:3] */

+	dataByte = ReadRegister(hSpiGci, channel, RAM_DATA_B0);

+	dataWord |= ((dataByte >> 3) & 0x0000001FL);

+	/* ramData[12:5] = RAM_DATA_B1[7:0] */

+	time_DelayWrapper (NULL, DELAY_TEST);

+	dataByte = ReadRegister(hSpiGci, channel, RAM_DATA_B1);

+	dataWord |= ((dataByte << 5) & 0x000001FE0L);

+	/* ramData[20:13] = RAM_DATA_B2[7:0] */

+	time_DelayWrapper (NULL, DELAY_TEST);

+	dataByte = ReadRegister(hSpiGci, channel, RAM_DATA_B2);

+	dataWord |= ((dataByte << 13) & 0x0001FE000L);

+	/* ramData[28:21] = RAM_DATA_B3[7:0] */

+	time_DelayWrapper (NULL, DELAY_TEST);

+	dataByte = ReadRegister(hSpiGci, channel, RAM_DATA_B3);

+	dataWord |= ((dataByte << 21) & 0x1FE00000L);

+	

+	return dataWord;

+}

+

+/*

+** WriteRAM()

+**

+** Write to ProSLIC RAM space

+**

+*/

+void WriteRAM(ctrl_S * hSpiGci, uInt8 channel, uInt16 address, uInt32 data)

+{

+	uInt8 dataByte;

+	uInt8 addrByte;

+	uInt32 userTimeout = 100000; //USER_TIMEOUT_VAL;

+

+	/* User defined timeout counter */

+	/* Wait for RAM to finish */

+	while ((ReadRegister(hSpiGci, channel, RAMSTAT) & 0x01) && (userTimeout > 0)) {

+		userTimeout--;

+	}

+	/*

+	while ((ReadRegister(hSpiGci, channel, RAMSTAT) & 0x01)) {

+	userTimeout--;

+}*/

+	time_DelayWrapper (NULL, DELAY_TEST);

+	

+	/* RAM_ADR_HI[7:5] = ramAddr[10:8] */

+	addrByte = (uInt8)((address >> 3) & 0x00E0);

+	WriteRegister(hSpiGci, channel, RAM_ADDR_HI, addrByte);

+	/* RAM_DATA_B0[7:3] = ramData[4:0] */

+	time_DelayWrapper (NULL, DELAY_TEST);

+	dataByte = (uInt8)((data << 3) & 0x000000F1L);

+	WriteRegister(hSpiGci, channel, RAM_DATA_B0, dataByte);

+	/* RAM_DATA_B1[7:0] = ramData[12:5] */

+	time_DelayWrapper (NULL, DELAY_TEST);

+	dataByte = (uInt8)((data >> 5) & 0x000000FFL);

+	WriteRegister(hSpiGci, channel, RAM_DATA_B1, dataByte);

+	/* RAM_DATA_B2[7:0] = ramData[20:13] */

+	time_DelayWrapper (NULL, DELAY_TEST);

+	dataByte = (uInt8)((data >> 13) & 0x000000FFL);

+	WriteRegister(hSpiGci, channel, RAM_DATA_B2, dataByte);

+	/* RAM_DATA_B3[7:0] = ramData[28:21] */

+	time_DelayWrapper (NULL, DELAY_TEST);

+	dataByte = (uInt8)((data >> 21) & 0x000000FFL);

+	WriteRegister(hSpiGci, channel, RAM_DATA_B3, dataByte);

+	/* RAM_ADR_LO[7:0] = ramAddr[7:0] */

+	time_DelayWrapper (NULL, DELAY_TEST);

+	addrByte = (uInt8)((address & 0x00FF));

+	WriteRegister(hSpiGci, channel, RAM_ADDR_LO, addrByte);

+}

+

+

+/*

+** Function: spiGci_ResetWrapper

+**

+** Description: 

+** Sets the reset pin of the ProSLIC

+*/

+int ctrl_ResetWrapper (void * hSpiGci, int status)

+{

+	/*if (status)

+		RSTNLow();

+	else

+		RSTNHigh();*/

+	return 0;

+}

+

+/*

+** SPI/GCI register read 

+**

+** Description: 

+** Reads a single ProSLIC register

+**

+** Input Parameters: 

+** channel: ProSLIC channel to read from

+** num: number of reads to perform

+** regAddr: Address of register to read

+** addr_inc: whether to increment address after each read

+** data: data to read from register

+**

+** Return:

+** none

+*/

+uInt8 ctrl_ReadRegisterWrapper (void * hSpiGci, uInt8 channel,uInt8 regAddr)

+{

+	

+	return ReadRegister(hSpiGci, channel, regAddr);

+}

+

+

+/*

+** Function: spiGci_WriteRegisterWrapper 

+**

+** Description: 

+** Writes a single ProSLIC register

+**

+** Input Parameters: 

+** channel: ProSLIC channel to write to

+** address: Address of register to write

+** data: data to write to register

+**

+** Return:

+** none

+*/

+int ctrl_WriteRegisterWrapper (void * hSpiGci, uInt8 channel,  uInt8 regAddr, uInt8 data)

+{

+	WriteRegister(hSpiGci, channel, regAddr, data);

+	return 0;

+}

+

+

+/*

+** Function: SPI_ReadRAMWrapper

+**

+** Description: 

+** Reads a single ProSLIC RAM location

+**

+** Input Parameters: 

+** channel: ProSLIC channel to read from

+** address: Address of RAM location to read

+** pData: data to read from RAM location

+**

+** Return:

+** none

+*/

+ramData ctrl_ReadRAMWrapper (void * hSpiGci, uInt8 channel, uInt16 ramAddr)

+{

+	return ReadRAM(hSpiGci, channel, ramAddr);;

+}

+

+

+/*

+** Function: SPI_WriteRAMWrapper

+**

+** Description: 

+** Writes a single ProSLIC RAM location

+**

+** Input Parameters: 

+** channel: ProSLIC channel to write to

+** address: Address of RAM location to write

+** data: data to write to RAM location

+**

+** Return:

+** none

+*/

+int ctrl_WriteRAMWrapper (void * hSpiGci, uInt8 channel, uInt16 ramAddr, ramData data)

+{

+	WriteRAM(hSpiGci, channel, ramAddr, data);

+	return 0;

+}

+

+

+/*

+** $Log: dummy_spi.c,v $

+** Revision 1.3  2008/07/24 21:06:16  lajordan

+** no message

+**

+** Revision 1.2  2007/10/22 21:38:10  lajordan

+** fixed some warnings

+**

+** Revision 1.1  2007/10/22 20:52:08  lajordan

+** no message

+**

+*/

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/spi.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/spi.h
new file mode 100755
index 0000000..b261228
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/spi.h
@@ -0,0 +1,93 @@
+/*

+** $Id: spi.h 109 2008-10-22 19:45:09Z lajordan@SILABS.COM $

+** 

+** This file is system specific and should be edited for your hardware platform

+**

+** This file is used by proslic_timer_intf.h and proslic_spiGci.h

+*/

+#ifndef SPI_TYPE_H

+#define SPI_TYPE_H

+

+#include "si_voice_datatypes.h"

+#include "proslic.h"

+#include "si3226x_registers.h"

+/*

+** SPI/GCI structure

+*/

+typedef struct{

+	int portID;

+} ctrl_S;

+

+/*

+** Function: SPI_Init

+**

+** Description: 

+** Initializes the SPI interface

+*/

+int SPI_Init (ctrl_S * hSpiGci);

+

+/*

+** Function: ctrl_ResetWrapper

+**

+** Description: 

+** Sets the reset pin of the ProSLIC

+*/

+int ctrl_ResetWrapper (void *hCtrl, int status);

+

+/*

+** register read 

+**

+** Description: 

+** Reads ProSLIC registers

+*/

+unsigned char ctrl_ReadRegisterWrapper (void *hCtrl, unsigned char channel, unsigned char regAddr);

+

+/*

+** Function: ctrl_WriteRegisterWrapper

+**

+** Description: 

+** Writes ProSLIC registers

+*/

+int ctrl_WriteRegisterWrapper (void *hSpiGci, unsigned char channel, unsigned char regAddr, unsigned char data);

+

+/*

+** Function: ctrl_WriteRAMWrapper

+**

+** Description: 

+** Writes ProSLIC RAM

+*/

+int ctrl_WriteRAMWrapper (void * hSpiGci, uInt8 channel, uInt16 ramAddr, ramData data);

+/*

+** Function: ctrl_ReadRAMWrapper

+**

+** Description: 

+** Reads ProSLIC RAM

+*/

+ramData ctrl_ReadRAMWrapper  (void *hSpiGci, unsigned char channel, unsigned short ramAddr);

+

+#endif

+/*

+** $Log: spi.h,v $

+** Revision 1.2  2007/10/22 21:38:10  lajordan

+** fixed some warnings

+**

+** Revision 1.1  2007/10/22 20:52:09  lajordan

+** no message

+**

+** Revision 1.1  2007/06/01 02:27:11  lajordan

+** no message

+**

+** Revision 1.2  2007/02/21 16:53:07  lajordan

+** no message

+**

+** Revision 1.1  2007/02/16 23:55:15  lajordan

+** no message

+**

+** Revision 1.2  2007/02/15 23:33:25  lajordan

+** no message

+**

+** Revision 1.1.1.1  2006/07/13 20:26:08  lajordan

+** no message

+**

+*/

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/timer.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/timer.c
new file mode 100755
index 0000000..20999fe
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/timer.c
@@ -0,0 +1,72 @@
+/*

+** $Id: dummy_timer.c 109 2008-10-22 19:45:09Z lajordan@SILABS.COM $

+**

+** system.c

+** System specific functions implementation file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** File Description:

+** This is the implementation file for the system specific functions like timer functions.

+**

+** Dependancies:

+** datatypes.h

+**

+*/

+

+#include "timer.h"

+

+/*

+** Function: SYSTEM_TimerInit

+*/

+void TimerInit (systemTimer_S *pTimerObj)

+{

+

+}

+

+

+/*

+** Function: SYSTEM_Delay

+*/

+int time_DelayWrapper (void *hTimer, int timeInMs)

+{

+	mvOsDelay(timeInMs);

+	return 0;

+}

+

+

+/*

+** Function: SYSTEM_TimeElapsed

+*/

+int time_TimeElapsedWrapper (void *hTimer, void *startTime, int *timeInMs)

+{

+	*timeInMs = 1000;

+	return 0;

+}

+

+/*

+** Function: SYSTEM_GetTime

+*/

+int time_GetTimeWrapper (void *hTimer, void *time)

+{

+//	time->timestamp=0;

+	return 0;

+}

+

+/*

+** $Log: dummy_timer.c,v $

+** Revision 1.3  2008/03/13 18:40:03  lajordan

+** fixed for si3226

+**

+** Revision 1.2  2007/10/22 21:38:31  lajordan

+** fixed some warnings

+**

+** Revision 1.1  2007/10/22 20:49:21  lajordan

+** no message

+**

+**

+*/

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/timer.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/timer.h
new file mode 100755
index 0000000..ab6f271
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/timer.h
@@ -0,0 +1,86 @@
+/*

+** $Id: dummy_timer.h 109 2008-10-22 19:45:09Z lajordan@SILABS.COM $

+** 

+** This file is system specific and should be edited for your hardware platform

+**

+** 

+*/

+#ifndef TIME_TYPE_H

+#define TIME_TYPE_H

+

+#include "si_voice_datatypes.h"

+#include "proslic.h"

+#include "mvOs.h"

+

+

+/*

+** System timer interface structure 

+*/

+typedef struct{

+	int timerInfo;

+} systemTimer_S;

+

+/*

+** System time stamp

+*/

+typedef struct{

+	int timestamp;

+} timeStamp;

+

+/*

+** Function: SYSTEM_TimerInit

+**

+** Description: 

+** Initializes the timer used in the delay and time measurement functions

+** by doing a long inaccurate sleep and counting the ticks

+**

+** Input Parameters: 

+**

+** Return:

+** none

+*/

+void TimerInit (systemTimer_S *pTimerObj);

+/*

+** Function: DelayWrapper

+**

+** Description: 

+** Waits the specified number of ms

+**

+** Input Parameters: 

+** hTimer: timer pointer

+** timeInMs: time in ms to wait

+**

+** Return:

+** none

+*/

+int time_DelayWrapper (void *hTimer, int timeInMs);

+

+

+/*

+** Function: TimeElapsedWrapper

+**

+** Description: 

+** Calculates number of ms that have elapsed

+**

+** Input Parameters: 

+** hTImer: pointer to timer object

+** startTime: timer value when function last called

+** timeInMs: pointer to time elapsed

+**

+** Return:

+** timeInMs: time elapsed since start time

+*/

+int time_TimeElapsedWrapper (void *hTimer, void *startTime, int *timeInMs);

+

+int time_GetTimeWrapper (void *hTimer, void *time);

+#endif

+/*

+** $Log: dummy_timer.h,v $

+** Revision 1.1  2007/10/22 21:38:32  lajordan

+** fixed some warnings

+**

+** Revision 1.1  2007/10/22 20:49:21  lajordan

+** no message

+**

+**

+*/

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_api_config.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_api_config.h
new file mode 100755
index 0000000..b69f038
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_api_config.h
@@ -0,0 +1,161 @@
+/*

+* Copyright 2007-2010 by Silicon Laboratories

+*

+* $Id: proslic_api_config.h 3073 2011-08-26 21:46:11Z cdp $

+*

+*

+* Author(s): 

+* laj

+*

+* Distributed by: 

+* Silicon Laboratories, Inc

+*

+* This file contains proprietary information.	 

+* No dissemination allowed without prior written permission from

+* Silicon Laboratories, Inc.

+*

+*

+*/

+#ifndef PROSLIC_API_CFG

+#define PROSLIC_API_CFG

+

+/** @defgroup PROSLIC_CFG ProSLIC Configuration Options

+ * @{

+ */

+

+/** @defgroup PROSLIC_DRIVER_SEL ProSLIC Driver Selection

+* Define device driver to be compliled

+* @{

+*/

+#define SI321X  /**< Define to support Si321X chipset family in the build */

+#undef SI321X 

+#define SI322X  /**< Define to support Si322x chipset family in the build */

+#undef SI322X

+#define SI3217X /**< Define to support Si3217x chipset family in the build */

+#undef SI3217X

+#define SI3226X /**< Define to support Si3226x chipset family in the build */

+#undef SI3226X

+#define SI324X /**< Define to support Si324x chipset family in the build */

+#undef SI324X

+

+#if defined(CONFIG_SILAB_SLIC_SI3226x)

+#define SI3226X

+#endif

+#if defined(CONFIG_SILAB_SLIC_SI3217x)

+#define SI3217X

+#endif

+

+

+/** @} PROSLIC_DRIVER_SEL*/

+

+/** @defgroup CODE_OPTS Code feature options 

+ * Select which options NOT to build - just uncomment out the undef to disable feature.

+ * @{

+ */

+#define DISABLE_VERIFY_PATCH      /**< Disable patch load verification */

+#undef DISABLE_VERIFY_PATCH 

+#define DISABLE_DTMF_SETUP        /**< Disable the DTMF API */

+/*#undef DISABLE_DTMF_SETUP */

+#define DISABLE_FSK_SETUP         /**< DIsable the FSK setup API */

+#undef DISABLE_FSK_SETUP 

+#define DISABLE_TONE_SETUP        /**< Disable Tone setup API */

+#undef DISABLE_TONE_SETUP 

+#define DISABLE_RING_SETUP        /**< Disable Ring setup API */

+#undef DISABLE_RING_SETUP  

+#define DISABLE_DCFEED_SETUP      /**< Disable DC FEED setup API */

+#undef DISABLE_DCFEED_SETUP 

+#define DISABLE_GPIO_SETUP        /**< Disable GPIO setup API */

+#undef DISABLE_GPIO_SETUP 

+#define DISABLE_PCM_SETUP         /**< Disable PCM setup API */

+#undef DISABLE_PCM_SETUP 

+#define ENABLE_DEBUG              /**< Enable debug messages - function entry, etc. */

+/* #undef ENABLE_DEBUG */

+#define DISABLE_CI_SETUP          /**< Disable CI Setup */

+#undef DISABLE_CI_SETUP 

+#define DISABLE_ZSYNTH_SETUP      /**< Disable Zsyth/impedance setup */

+#undef DISABLE_ZSYNTH_SETUP  

+#define DISABLE_MALLOC            /**< Don't use MALLOC/FREE, instead assume user will statically allocate */

+#undef DISABLE_MALLOC 

+/**@} */

+

+#define GCI_MODE  /**< Set if GCI vs. SPI/PCM mode is to be used */

+#undef GCI_MODE  

+

+#define PRINT_TO_STRING 0         /**< Set this to 1 if printing to a string buffer vs. console - you may change/remove this*/

+

+

+/** @defgroup MULTI_BOM Multiple Device/BOM Option Support

+ * Assign patch structure names to macros used in device drivers

+* @{ */

+#define SIVOICE_MULTI_BOM_SUPPORT /**< Enable Multiple General Configuration Support */

+#undef SIVOICE_MULTI_BOM_SUPPORT

+

+#ifdef SIVOICE_MULTI_BOM_SUPPORT

+#define SI3226_PATCH_C_QCUK		   si3226PatchRevCQcuk  /**< Si3226 RevC Quasi-Cuk DCDC Converter Patch */

+#define SI3226_PATCH_C_FLBK	       si3226PatchRevCFlbk  /**< Si3226 RevC Flyback DCDC Converter Patch */

+#define SI3226_PATCH_D_QCUK	       si3226PatchRevDQcuk  /**< Si3226 RevD Quasi-Cuk DCDC Converter Patch */

+#define SI3226_PATCH_D_FLBK	       si3226PatchRevDFlbk  /**< Si3226 RevD Flyback DCDC Converter Patch */

+#define SI3226_PATCH_E_FLBK	       si3226PatchRevEFlbk  /**< Si3226 RevE Flyback DCDC Converter Patch */

+

+#define SI3217X_PATCH_B_FLBK       si3217xPatchRevBFlbk  /**< Si3217x Flyback DCDC Converter patch */

+#define SI3217X_PATCH_B_BKBT       si3217xPatchRevBBkbt  /**< Si3217x Buck-boost DCDC Converter patch */

+#define SI3217X_PATCH_B_PBB5       si3217xPatchRevBBkbt  /**< Si3217x PMOS Buck-boost DCDC Converter patch */

+

+#define SI3226X_PATCH_B_FLBK       si3226xPatchRevBFlbk    /**< Si3226x RevB Flyback DCDC Converter Patch */

+#define SI3226X_PATCH_B_QCUK       si3226xPatchRevBFlbk    /**< Si3226x RevB Quasi-CUK DCDC Converter Patch */

+#define SI3226X_PATCH_B_FIXRL      si3226xPatchRevBFlbk    /**< Si3226x RevB Fixed Rail DCDC Converter Patch */

+#define SI3226X_PATCH_C_FLBK       si3226xPatchRevCFlbk    /**< Si3226x RevC Flyback DCDC Converter Patch */

+#define SI3226X_PATCH_C_QCUK       si3226xPatchRevCFlbk    /**< Si3226x RevC Quasi-CUK DCDC Converter Patch */

+#define SI3226X_PATCH_C_LCQCUK     si3226xPatchRevCFlbk    /**< Si3226x RevC Low-cost QCUK DCDC Converter Patch */

+#define SI3226X_PATCH_C_TSS        si3226xPatchRevCTss     /**< Si3226x RevC TSS DCDC Converter Patch */

+#define SI3226X_PATCH_C_TSS_ISO    si3226xPatchRevCTssIso  /**< Si3226x RevC TSS (isolated) DCDC Converter Patch */

+#define SI3226x_PATCH_C_FIXRL      SI3226X_PATCH_C_TSS

+#endif

+

+/* Default patch names for backwards compatibility */

+#define SI3226_PATCH_C_DEFAULT     RevCPatch

+#define SI3226_PATCH_D_DEFAULT     RevDPatch

+#define SI3226_PATCH_E_DEFAULT     RevEPatch

+#define SI3217X_PATCH_B_DEFAULT    RevBPatch

+#define SI3226X_PATCH_B_DEFAULT    RevBPatch

+#define SI3226X_PATCH_C_DEFAULT    RevCPatch

+

+

+/** @} MULTI_BOM */

+#include <linux/kernel.h>

+#if (PRINT_TO_STRING)  

+extern char outputBuffer[]; 

+#define LOGPRINT(...) sprintf(&(outputBuffer[strlen(outputBuffer)]),__VA_ARGS__) 

+#else 

+#define LOGPRINT printk

+#endif 

+

+/** @defgroup PSTN_CFG PSTN Detection Options

+* @{ */

+#define PSTN_DET_ENABLE                  /**< Define to include Differential PSTN detection code */

+#undef PSTN_DET_ENABLE

+

+#define PSTN_DET_OPEN_FEMF_SETTLE   1500     /**< OPEN foreign voltage measurement settle time */

+#define PSTN_DET_DIFF_SAMPLES       4        /**< Number of I/V samples averaged [1 to 16] */

+#define PSTN_DET_MIN_ILOOP          700      /**< Minimum acceptable loop current */

+#define PSTN_DET_MAX_FEMF           10000    /**< Maximum OPEN state foreign voltage */

+#define PSTN_DET_POLL_RATE          10       /**< Rate of re-entrant code in ms */

+#define PSTN_DET_DIFF_IV1_SETTLE    1000     /**< Settle time before first I/V measurment in ms */

+#define PSTN_DET_DIFF_IV2_SETTLE    1000     /**< Settle time before first I/V measurment in ms */

+

+/** @} PSTN_CFG */

+

+

+

+/** @defgroup SI321X_TONE Tone Generation Options 

+* @{ */

+#define SI3210_TONE

+#undef  SI3210_TONE

+#define SI3215_TONE

+/* #undef  SI3215_TONE */

+/** @} SI321X_TONE */

+

+#define SIVOICE_CFG_NEWTYPES_ONLY  1 /**< Set if not supporting Legacy types */

+

+/**@} */

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_tstin_limits.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_tstin_limits.c
new file mode 100755
index 0000000..d8bff00
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_tstin_limits.c
@@ -0,0 +1,79 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-09-08 08:51:02

+**

+**  ProSLIC API Configuration Tool Version 2.6.0

+**

+** Test-In Configuration Utility

+*/

+

+

+

+#include "proslic_tstin.h"

+

+proslicPcmLpbkTest ProSLIC_testIn_PcmLpbk_Test = {

+0,		/* Enable/Disable (read only) */

+0,		/* LPBK state (read only) */

+PCM_8BIT,   /* PCM Format */

+0,		/* PCM MODE (read only) */

+0 		/* Test Result (read only) */

+};

+

+proslicDcFeedTest ProSLIC_testIn_DcFeed_Test = {

+0,              /* Enable/Disable (read only) */

+TSTIN_RESULTS_INVALID,              /* Data Valid Status(read only) */

+ABORT_LIU_ENABLED,              /* Abort if Line-In-Use */

+LCR_CHECK_ENABLED,              /* LCR Check Enable/Disable */

+0x0048D595L,    /* Alt LCROFFHK for LCR Test */

+0x0036A030L,    /* Alt LCRONFHK for LCR Test */

+0,              /* LCR State(read only) */

+{  1000,    5000,  0,  0},	/* vtip onhook */

+{ 45000,   58000,  0,  0},	/* vring onhook */

+{ 43000,   52000,  0,  0},	/* vloop onhook */

+{ 43000,   62000,  0,  0},	/* vbat onhook */

+{ -2000,    2000,  0,  0},	/* itip onhook */

+{ -2000,    2000,  0,  0},	/* iring onhook */

+{ -1500,    1500,  0,  0},	/* iloop onhook */

+{ -2000,    2000,  0,  0},	/* ilong onhook */

+{  2000,   10000,  0,  0},	/* vtip offhook */

+{ 44000,   51000,  0,  0},	/* vring offhook */

+{ 34000,   46000,  0,  0},	/* vloop offhook */

+{ 36000,   60000,  0,  0},	/* vbat offhook */

+{  8000,   20000,  0,  0},	/* itip offhook */

+{-20000,   -8000,  0,  0},	/* iring offhook */

+{  8000,   20000,  0,  0},	/* iloop offhook */

+{ -2000,    2000,  0,  0},	/* ilong offhook */

+0              /* Cumulative Test Result(read only) */

+};

+

+proslicRingingTest ProSLIC_testIn_Ringing_Test = {

+0,              /* Enable/Disable (read only) */

+TSTIN_RESULTS_INVALID,       /* Data Valid Status(read only) */

+ABORT_LIU_ENABLED,       /* Abort if Line-In-Use */

+90,             /* Number of Samples */

+10,             /* Sample Interval (ms) */

+RTP_CHECK_ENABLED,      /* RTP Check Enable/Disable */

+0,              /* RTP State(read only) */

+{ 45000,   68000,  0,  0},	/* VAC */

+{ -2000,    2000,  0,  0},	/* VDC */

+0              /* Cumulative Test Result(read only) */

+};

+

+proslicBatteryTest ProSLIC_testIn_Battery_Test = {

+0,              /* Enable/Disable (read only) */

+TSTIN_RESULTS_INVALID,       /* Data Valid Status(read only) */

+{ 50000,   60000,  0,  0},	/* VBAT */

+0              /* Cumulative Test Result(read only) */

+};

+

+proslicAudioTest ProSLIC_testIn_Audio_Test = {

+0,              /* Enable/Disable (read only) */

+TSTIN_RESULTS_INVALID,       /* Data Valid Status(read only) */

+ABORT_LIU_ENABLED,              /* Abort if Line-In-Use */

+1095,              /* 0dBm Voltage (mvpk) */

+{-11000,    1000,  0,  0},	/* TX Path Gain */

+{-11000,    1000,  0,  0},	/* RX Path Gain */

+0              /* Cumulative Test Result(read only) */

+};

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_tstin_limits.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_tstin_limits.h
new file mode 100755
index 0000000..585b769
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/proslic_tstin_limits.h
@@ -0,0 +1,12 @@
+

+#ifndef PROSLIC_TSTIN_LIMITS_H

+#define PROSLIC_TSTIN_LIMITS_H

+

+

+extern proslicPcmLpbkTest ProSLIC_testIn_PcmLpbk_Test;

+extern proslicDcFeedTest ProSLIC_testIn_DcFeed_Test;

+extern proslicRingingTest ProSLIC_testIn_Ringing_Test;

+extern proslicBatteryTest ProSLIC_testIn_Battery_Test;

+extern proslicAudioTest ProSLIC_testIn_Audio_Test;

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_BKBT_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_BKBT_constants.c
new file mode 100755
index 0000000..8a12398
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_BKBT_constants.c
@@ -0,0 +1,575 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-02-09 18:02:16

+**

+** Si3217x ProSLIC API Configuration Tool Version 2.4.0

+*/

+

+

+#include "proslic.h"

+#include "si3217x.h"

+

+Si3217x_General_Cfg Si3217x_General_Configuration  = {

+BO_DCDC_BUCK_BOOST,    /* BOM_OPT */

+0x070A3D3AL,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x00000000L,    /* DCDC_FSW_VTHLO */

+0x00000000L,    /* DCDC_FSW_VHYST */

+0x00C00000L,    /* DCDC_VREF_MIN */

+0x01800000L,    /* DCDC_VREF_MIN_RNG */

+0x00200000L,    /* DCDC_FSW_NORM */

+0x00200000L,    /* DCDC_FSW_NORM_LO */

+0x00200000L,    /* DCDC_FSW_RING */

+0x00200000L,    /* DCDC_FSW_RING_LO */

+0x0D980000L,    /* DCDC_DIN_LIM */

+0x00C00000L,    /* DCDC_VOUT_LIM */

+0x10000000L,    /* DCDC_DCFF_ENABLE */

+0x00100000L,    /* DCDC_UVHYST */

+0x00400000L,    /* DCDC_UVTHRESH */

+0x00400000L,    /* DCDC_OVTHRESH */

+0x00200000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00300000L,    /* DCDC_SWFET */

+0x00600000L,    /* DCDC_VREF_CTRL */

+0x00000000L,    /* DCDC_RNGTYPE */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00600000L,    /* DCDC_ANA_TOFF */

+0x00300000L,    /* DCDC_ANA_TONMIN */

+0x00800000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x0048D15BL,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x01,     /* DAA_CNTL */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x30,     /* ENHANCE */

+1,       /* DAA_ENABLE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x0099999AL    /* AC_ADC_GAIN */

+};

+

+Si3217x_GPIO_Cfg Si3217x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3217x_CI_Cfg Si3217x_CI_Presets [] = {

+{0}

+};

+Si3217x_audioGain_Cfg Si3217x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3217x_Ring_Cfg Si3217x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 3, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x0025D5BFL,	/* RINGAMP (64.490 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x00608636L,	/* RTACTH (53.304 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x070A0AA8L,	/* VBATR_EXPECT (109.988 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x01,			/* USERSTAT */

+0x03850554L,	/* VCM_RING (51.994 v) */

+0x03850554L,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00000000L,	/* DCDC_RNGTYPE */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x01,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00000000L,	/* DCDC_RNGTYPE */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00000000L,	/* DCDC_RNGTYPE */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3217x_DCfeed_Cfg Si3217x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3217x_Impedance_Cfg Si3217x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3217x_FSK_Cfg Si3217x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3217x_PulseMeter_Cfg Si3217x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3217x_Tone_Cfg Si3217x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x00,			 /* O1TILO (4000 ms) */

+	0x7D			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3217x_PCM_Cfg Si3217x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_FLBK_BKBT_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_FLBK_BKBT_constants.c
new file mode 100755
index 0000000..0ff10fd
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_FLBK_BKBT_constants.c
@@ -0,0 +1,670 @@
+/*

+** Copyright (c) 2010 Silicon Laboratories, Inc.

+** 2010-06-25 15:51:02

+**

+** Si3217x ProSLIC API Configuration Tool Version 2.1L

+*/

+

+

+#include "proslic.h"

+#include "si3217x.h"

+

+Si3217x_General_Cfg Si3217x_General_Configuration  = {

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+0x070A3D3AL,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x00000000L,    /* DCDC_FSW_VTHLO */

+0x00000000L,    /* DCDC_FSW_VHYST */

+0x00C00000L,    /* DCDC_VREF_MIN */

+0x01800000L,    /* DCDC_VREF_MIN_RNG */

+0x00200000L,    /* DCDC_FSW_NORM */

+0x00200000L,    /* DCDC_FSW_NORM_LO */

+0x00200000L,    /* DCDC_FSW_RING */

+0x00200000L,    /* DCDC_FSW_RING_LO */

+0x0D980000L,    /* DCDC_DIN_LIM */

+0x00C00000L,    /* DCDC_VOUT_LIM */

+0x00000000L,    /* DCDC_DCFF_ENABLE */

+0x00100000L,    /* DCDC_UVHYST */

+0x00400000L,    /* DCDC_UVTHRESH */

+0x00B00000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00100000L,    /* DCDC_SWDRV_POL */

+0x00300000L,    /* DCDC_SWFET */

+0x00600000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x0048D15BL,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x01,     /* DAA_CNTL */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x30,     /* ENHANCE */

+1,       /* DAA_ENABLE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x0099999AL    /* AC_ADC_GAIN */

+};

+

+#ifdef SIVOICE_MULTI_BOM_SUPPORT

+

+int si3217x_genconf_multi_max_preset = 2;

+

+Si3217x_General_Cfg Si3217x_General_Configuration_MultiBOM[]  = {

+{

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+0x070A3D3AL,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x00000000L,    /* DCDC_FSW_VTHLO */

+0x00000000L,    /* DCDC_FSW_VHYST */

+0x00C00000L,    /* DCDC_VREF_MIN */

+0x01800000L,    /* DCDC_VREF_MIN_RNG */

+0x00200000L,    /* DCDC_FSW_NORM */

+0x00200000L,    /* DCDC_FSW_NORM_LO */

+0x00200000L,    /* DCDC_FSW_RING */

+0x00200000L,    /* DCDC_FSW_RING_LO */

+0x0D980000L,    /* DCDC_DIN_LIM */

+0x00C00000L,    /* DCDC_VOUT_LIM */

+0x00000000L,    /* DCDC_DCFF_ENABLE */

+0x00100000L,    /* DCDC_UVHYST */

+0x00400000L,    /* DCDC_UVTHRESH */

+0x00B00000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00100000L,    /* DCDC_SWDRV_POL */

+0x00300000L,    /* DCDC_SWFET */

+0x00600000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x0048D15BL,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x01,     /* DAA_CNTL */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x30,     /* ENHANCE */

+1,       /* DAA_ENABLE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x0099999AL    /* AC_ADC_GAIN */

+}, /* SI3217X_GEN_PARAM_FLBK */

+{

+BO_DCDC_BUCK_BOOST,    /* BOM_OPT */

+0x070A3D3AL,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x00000000L,    /* DCDC_FSW_VTHLO */

+0x00000000L,    /* DCDC_FSW_VHYST */

+0x00C00000L,    /* DCDC_VREF_MIN */

+0x01800000L,    /* DCDC_VREF_MIN_RNG */

+0x00200000L,    /* DCDC_FSW_NORM */

+0x00200000L,    /* DCDC_FSW_NORM_LO */

+0x00200000L,    /* DCDC_FSW_RING */

+0x00200000L,    /* DCDC_FSW_RING_LO */

+0x0D980000L,    /* DCDC_DIN_LIM */

+0x00C00000L,    /* DCDC_VOUT_LIM */

+0x10000000L,    /* DCDC_DCFF_ENABLE */

+0x00100000L,    /* DCDC_UVHYST */

+0x00400000L,    /* DCDC_UVTHRESH */

+0x00400000L,    /* DCDC_OVTHRESH */

+0x00200000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00300000L,    /* DCDC_SWFET */

+0x00600000L,    /* DCDC_VREF_CTRL */

+0x00000000L,    /* DCDC_RNGTYPE */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00600000L,    /* DCDC_ANA_TOFF */

+0x00300000L,    /* DCDC_ANA_TONMIN */

+0x00800000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x0048D15BL,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x01,     /* DAA_CNTL */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x30,     /* ENHANCE */

+1,       /* DAA_ENABLE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x0099999AL    /* AC_ADC_GAIN */

+}

+};

+

+#endif

+

+Si3217x_GPIO_Cfg Si3217x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3217x_CI_Cfg Si3217x_CI_Presets [] = {

+{0}

+};

+Si3217x_audioGain_Cfg Si3217x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3217x_Ring_Cfg Si3217x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 3, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x00262257L,	/* RINGAMP (65.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0061499FL,	/* RTACTH (53.725 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x070A3D3AL,	/* VBATR_EXPECT (110.000 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x03851E9DL,	/* VCM_RING (52.000 v) */

+0x03851E9DL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x01,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x01,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3217x_DCfeed_Cfg Si3217x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3217x_Impedance_Cfg Si3217x_Impedance_Presets[] ={

+/* Source: Database file: j:\proj\sandbox\config_tool\build\cwdb.db */

+/* Database information: version: 1.0.0 build date: 2010-01-06*/

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: j:\proj\sandbox\config_tool\build\cwdb.db */

+/* Database information: version: 1.0.0 build date: 2010-01-06*/

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x071F7A80L, 0x1FD01280L, 0x00132700L, 0x1FFEF980L,    /* TXACEQ */

+ 0x0A8AA300L, 0x1B9A5500L, 0x008E7F00L, 0x1FD7F300L},   /* RXACEQ */

+{0x0068CA00L, 0x1EAE1E00L, 0x0394FA00L, 0x1E94AE80L,    /* ECFIR/ECIIR */

+ 0x0356D800L, 0x0166CA80L, 0x1EC16380L, 0x01DE2780L,

+ 0x1F852300L, 0x0046BE80L, 0x02F17C80L, 0x1EBCD280L},

+{0x028A0C00L, 0x19EE4580L, 0x03876100L, 0x0A762700L,    /* ZSYNTH */

+ 0x1D87A380L, 0x93}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0109C280L,   /* RXACGAIN */

+ 0x07BC6F00L, 0x18439180L, 0x0778DE00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: j:\proj\sandbox\config_tool\build\cwdb.db */

+/* Database information: version: 1.0.0 build date: 2010-01-06*/

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: j:\proj\sandbox\config_tool\build\cwdb.db */

+/* Database information: version: 1.0.0 build date: 2010-01-06*/

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E38480L, 0x1FD33B00L, 0x00069780L, 0x1FFCAB80L,    /* TXACEQ */

+ 0x0A78F680L, 0x1BC5C880L, 0x009AEA00L, 0x1FD66D80L},   /* RXACEQ */

+{0x00378B00L, 0x1F3FCA00L, 0x02B5ED00L, 0x1F2B6200L,    /* ECFIR/ECIIR */

+ 0x04189080L, 0x1F8A4480L, 0x01113680L, 0x00373100L,

+ 0x001DAE80L, 0x1FE02F00L, 0x0C89C780L, 0x1B689680L},

+{0x02391100L, 0x1A886080L, 0x033E3B00L, 0x0A136200L,    /* ZSYNTH */

+ 0x1DEA4180L, 0x8C}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01019200L,   /* RXACGAIN */

+ 0x07BD1680L, 0x1842EA00L, 0x077A2D00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: j:\proj\sandbox\config_tool\build\cwdb.db */

+/* Database information: version: 1.0.0 build date: 2010-01-06*/

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: j:\proj\sandbox\config_tool\build\cwdb.db */

+/* Database information: version: 1.0.0 build date: 2010-01-06*/

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x073A7B00L, 0x1FCEB400L, 0x0002C680L, 0x1FFD0780L,    /* TXACEQ */

+ 0x09BA8580L, 0x1D2DF780L, 0x006F5000L, 0x1FDFE200L},   /* RXACEQ */

+{0x0004B700L, 0x000F9800L, 0x01201200L, 0x00E1D880L,    /* ECFIR/ECIIR */

+ 0x03314A00L, 0x1E84A580L, 0x029D2380L, 0x1E6F3400L,

+ 0x00E99200L, 0x1F121100L, 0x0588BC00L, 0x025CAE00L},

+{0x01415C00L, 0x1C98C180L, 0x0225A500L, 0x0A138200L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010DFD80L,   /* RXACGAIN */

+ 0x07BA2180L, 0x1845DF00L, 0x07744380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: j:\proj\sandbox\config_tool\build\cwdb.db */

+/* Database information: version: 1.0.0 build date: 2010-01-06*/

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56380L, 0x1FDF1900L, 0x00095A00L, 0x1FFDAA80L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00687000L, 0x1EAE1800L, 0x03983D80L, 0x1EB14B00L,    /* ECFIR/ECIIR */

+ 0x037B3E80L, 0x016FC900L, 0x1ED60100L, 0x01B17D80L,

+ 0x1FA20D00L, 0x001CE900L, 0x027D3380L, 0x1DBDBA80L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3217x_FSK_Cfg Si3217x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3217x_PulseMeter_Cfg Si3217x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3217x_Tone_Cfg Si3217x_Tone_Presets[] ={

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x80,			 /* O1TILO (2000 ms) */

+	0x3E			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3217x_PCM_Cfg Si3217x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_FLBK_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_FLBK_constants.c
new file mode 100755
index 0000000..497b0f0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_FLBK_constants.c
@@ -0,0 +1,575 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-02-09 18:53:30

+**

+** Si3217x ProSLIC API Configuration Tool Version 2.4.0

+*/

+

+

+#include "proslic.h"

+#include "si3217x.h"

+

+Si3217x_General_Cfg Si3217x_General_Configuration  = {

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+0x070A3D3AL,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x00000000L,    /* DCDC_FSW_VTHLO */

+0x00000000L,    /* DCDC_FSW_VHYST */

+0x00C00000L,    /* DCDC_VREF_MIN */

+0x01800000L,    /* DCDC_VREF_MIN_RNG */

+0x00200000L,    /* DCDC_FSW_NORM */

+0x00200000L,    /* DCDC_FSW_NORM_LO */

+0x00200000L,    /* DCDC_FSW_RING */

+0x00200000L,    /* DCDC_FSW_RING_LO */

+0x0D980000L,    /* DCDC_DIN_LIM */

+0x00C00000L,    /* DCDC_VOUT_LIM */

+0x00000000L,    /* DCDC_DCFF_ENABLE */

+0x00100000L,    /* DCDC_UVHYST */

+0x00400000L,    /* DCDC_UVTHRESH */

+0x00B00000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00100000L,    /* DCDC_SWDRV_POL */

+0x00300000L,    /* DCDC_SWFET */

+0x00600000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x0048D15BL,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x01,     /* DAA_CNTL */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x30,     /* ENHANCE */

+1,       /* DAA_ENABLE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x0099999AL    /* AC_ADC_GAIN */

+};

+

+Si3217x_GPIO_Cfg Si3217x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3217x_CI_Cfg Si3217x_CI_Presets [] = {

+{0}

+};

+Si3217x_audioGain_Cfg Si3217x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3217x_Ring_Cfg Si3217x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 3, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x0025D5BFL,	/* RINGAMP (64.490 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x00608636L,	/* RTACTH (53.304 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x070A0AA8L,	/* VBATR_EXPECT (109.988 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x01,			/* USERSTAT */

+0x03850554L,	/* VCM_RING (51.994 v) */

+0x03850554L,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x01,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3217x_DCfeed_Cfg Si3217x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3217x_Impedance_Cfg Si3217x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3217x_FSK_Cfg Si3217x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3217x_PulseMeter_Cfg Si3217x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3217x_Tone_Cfg Si3217x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x00,			 /* O1TILO (4000 ms) */

+	0x7D			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3217x_PCM_Cfg Si3217x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x01 	 /* A-LAW -  INVERT EVEN */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_PBB5_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_PBB5_constants.c
new file mode 100755
index 0000000..9737ca1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_PBB5_constants.c
@@ -0,0 +1,575 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-08-12 18:06:44

+**

+** Si3217x ProSLIC API Configuration Tool Version 2.5.2

+*/

+

+

+#include "proslic.h"

+#include "si3217x.h"

+

+Si3217x_General_Cfg Si3217x_General_Configuration  = {

+BO_DCDC_P_BUCK_BOOST_5V,    /* BOM_OPT */

+0x06666635L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x00000000L,    /* DCDC_FSW_VTHLO */

+0x00000000L,    /* DCDC_FSW_VHYST */

+0x00C00000L,    /* DCDC_VREF_MIN */

+0x01800000L,    /* DCDC_VREF_MIN_RNG */

+0x00200000L,    /* DCDC_FSW_NORM */

+0x00200000L,    /* DCDC_FSW_NORM_LO */

+0x00200000L,    /* DCDC_FSW_RING */

+0x00200000L,    /* DCDC_FSW_RING_LO */

+0x0D980000L,    /* DCDC_DIN_LIM */

+0x00C00000L,    /* DCDC_VOUT_LIM */

+0x10000000L,    /* DCDC_DCFF_ENABLE */

+0x00100000L,    /* DCDC_UVHYST */

+0x00400000L,    /* DCDC_UVTHRESH */

+0x00400000L,    /* DCDC_OVTHRESH */

+0x00200000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00300000L,    /* DCDC_SWFET */

+0x00600000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00400000L,    /* DCDC_ANA_TOFF */

+0x00200000L,    /* DCDC_ANA_TONMIN */

+0x01F00000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x0048D15BL,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x01,     /* DAA_CNTL */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x30,     /* ENHANCE */

+1,       /* DAA_ENABLE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x0099999AL    /* AC_ADC_GAIN */

+};

+

+Si3217x_GPIO_Cfg Si3217x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3217x_CI_Cfg Si3217x_CI_Presets [] = {

+{0}

+};

+Si3217x_audioGain_Cfg Si3217x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3217x_Ring_Cfg Si3217x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 3, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x0025D5BFL,	/* RINGAMP (64.490 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x00608636L,	/* RTACTH (53.304 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x06666635L,	/* VBATR_EXPECT (100.000 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x01,			/* USERSTAT */

+0x0333331AL,	/* VCM_RING (47.000 v) */

+0x0333331AL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x01,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* DCDC_VREF_MIN_RNG */

+0x40,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3217x_DCfeed_Cfg Si3217x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3217x_Impedance_Cfg Si3217x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3217x_FSK_Cfg Si3217x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3217x_PulseMeter_Cfg Si3217x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3217x_Tone_Cfg Si3217x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x00,			 /* O1TILO (4000 ms) */

+	0x7D			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3217x_PCM_Cfg Si3217x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_constants.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_constants.h
new file mode 100755
index 0000000..74a5142
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_constants.h
@@ -0,0 +1,74 @@
+/*

+** Copyright (c) 2010 Silicon Laboratories, Inc.

+** 2010-06-21 16:44:49

+**

+** Si3217x SiVoice API Configuration Tool Version 2.1L

+*/

+

+

+#ifndef SI3217X_CONSTANTS_H

+#define SI3217X_CONSTANTS_H

+

+/** Ringing Presets */

+enum {

+	RING_MAX_VBAT_PROVISIONING,

+	RING_F20_45VRMS_0VDC_LPR,

+	RING_F20_45VRMS_0VDC_BAL

+};

+

+/** DC_Feed Presets */

+enum {

+	DCFEED_48V_20MA,

+	DCFEED_48V_25MA,

+	DCFEED_PSTN_DET_1,

+	DCFEED_PSTN_DET_2

+};

+

+/** Impedance Presets */

+enum {

+	ZSYN_600_0_0_30_0,

+	ZSYN_270_750_150_30_0,

+	ZSYN_370_620_310_30_0,

+	ZSYN_220_820_120_30_0,

+	ZSYN_600_0_1000_30_0,

+	ZSYN_200_680_100_30_0,

+	ZSYN_220_820_115_30_0

+};

+

+/** FSK Presets */

+enum {

+	DEFAULT_FSK

+};

+

+/** Pulse_Metering Presets */

+enum {

+	DEFAULT_PULSE_METERING

+};

+

+/** Tone Presets */

+enum {

+	TONEGEN_FCC_DIAL,

+	TONEGEN_FCC_BUSY,

+	TONEGEN_FCC_RINGBACK,

+	TONEGEN_FCC_REORDER,

+	TONEGEN_FCC_CONGESTION

+};

+

+/** PCM Presets */

+enum {

+	PCM_8ULAW,

+	PCM_8ALAW,

+	PCM_16LIN,

+	PCM_16LIN_WB

+};

+

+/** Multiple BOM General Param */

+enum {

+	GEN_PARAM_FLYBACK,

+	GEN_PARAM_BUCK_BOOST

+};

+

+

+

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_patch_B_BB_2010DEC16.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_patch_B_BB_2010DEC16.c
new file mode 100755
index 0000000..8c18d5f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_patch_B_BB_2010DEC16.c
@@ -0,0 +1,999 @@
+/*
+** Generated from si3217x_patch_B_BB_2010DEC16.dsp_prom
+** on 12-17-2010 at 8:14:27
+*/
+#include "si_voice_datatypes.h"
+#include "si3217x.h"
+
+static const uInt32 patchData [] = {
+141029L,
+532675L,
+141029L,
+540867L,
+141029L,
+661699L,
+141029L,
+678083L,
+141029L,
+678595L,
+141029L,
+978627L,
+141029L,
+979139L,
+141029L,
+999107L,
+558181L,
+519586L,
+524309L,
+142565L,
+539331L,
+172645L,
+524197L,
+524296L,
+523269L,
+523365L,
+522864L,
+524291L,
+246789L,
+246885L,
+141029L,
+773313L,
+76005L,
+546499L,
+17637L,
+548547L,
+257125L,
+262242L,
+143587L,
+546499L,
+257029L,
+141029L,
+551107L,
+776293L,
+261762L,
+141045L,
+550595L,
+776293L,
+119426L,
+517750L,
+257093L,
+776197L,
+541925L,
+554179L,
+518245L,
+792133L,
+141029L,
+934081L,
+518757L,
+792133L,
+141029L,
+556227L,
+62688L,
+568003L,
+115205L,
+548069L,
+560835L,
+451685L,
+223301L,
+141029L,
+568003L,
+223333L,
+262242L,
+142563L,
+568003L,
+223237L,
+143077L,
+568003L,
+171525L,
+172037L,
+172549L,
+173061L,
+173573L,
+174085L,
+174597L,
+52448L,
+571587L,
+17632L,
+571587L,
+376741L,
+181761L,
+182277L,
+670213L,
+536293L,
+598723L,
+683525L,
+576741L,
+576707L,
+211557L,
+524290L,
+141541L,
+577731L,
+535269L,
+582339L,
+251013L,
+432737L,
+116229L,
+111680L,
+112197L,
+112645L,
+113157L,
+113669L,
+211461L,
+117893L,
+116321L,
+251011L,
+116229L,
+666341L,
+594115L,
+111713L,
+116224L,
+112227L,
+432291L,
+660064L,
+112234L,
+30213L,
+111716L,
+111616L,
+30307L,
+113251L,
+112128L,
+112228L,
+147077L,
+524298L,
+113672L,
+113157L,
+112741L,
+113762L,
+112227L,
+112645L,
+524294L,
+524294L,
+115205L,
+141029L,
+619203L,
+535781L,
+21698L,
+683525L,
+432736L,
+211556L,
+30213L,
+576741L,
+604355L,
+30306L,
+141538L,
+605379L,
+535269L,
+607939L,
+111616L,
+112133L,
+432293L,
+211457L,
+114181L,
+111717L,
+114274L,
+432739L,
+111620L,
+144099L,
+611523L,
+111685L,
+30307L,
+142053L,
+613571L,
+111685L,
+96901L,
+112225L,
+433251L,
+112132L,
+666341L,
+618179L,
+114272L,
+112132L,
+114181L,
+111717L,
+115269L,
+537829L,
+646851L,
+181349L,
+373858L,
+151173L,
+262250L,
+181253L,
+141541L,
+641731L,
+182370L,
+181859L,
+182277L,
+666853L,
+639683L,
+461410L,
+667L,
+670949L,
+628931L,
+377157L,
+181861L,
+374370L,
+667L,
+146661L,
+638147L,
+374885L,
+254107L,
+146661L,
+638147L,
+375397L,
+262299L,
+146661L,
+638147L,
+375909L,
+262811L,
+146661L,
+638147L,
+245893L,
+376933L,
+524296L,
+376837L,
+645L,
+524289L,
+181248L,
+181765L,
+5221L,
+374181L,
+524296L,
+660069L,
+181872L,
+377251L,
+181765L,
+115301L,
+524296L,
+115205L,
+549605L,
+649923L,
+115301L,
+245893L,
+524296L,
+115205L,
+115301L,
+431714L,
+524291L,
+115205L,
+393317L,
+522338L,
+524292L,
+660069L,
+263813L,
+115304L,
+660068L,
+141541L,
+657091L,
+115269L,
+524288L,
+115300L,
+660066L,
+524292L,
+141541L,
+660675L,
+115269L,
+141029L,
+1029825L,
+520290L,
+520197L,
+521636L,
+141541L,
+664771L,
+524288L,
+524294L,
+524294L,
+524294L,
+524294L,
+660069L,
+520808L,
+519779L,
+521732L,
+144101L,
+670403L,
+521797L,
+5733L,
+521840L,
+24293L,
+673475L,
+35429L,
+385136L,
+524295L,
+2147L,
+393315L,
+188420L,
+144101L,
+677059L,
+188485L,
+141029L,
+661185L,
+524293L,
+264322L,
+402037L,
+143076L,
+691907L,
+25829L,
+689859L,
+201312L,
+201218L,
+142565L,
+87747L,
+547941L,
+245890L,
+142560L,
+87747L,
+694789L,
+537605L,
+538437L,
+538629L,
+694785L,
+721925L,
+141029L,
+718531L,
+201280L,
+182789L,
+141029L,
+87747L,
+142564L,
+712387L,
+524292L,
+524292L,
+142564L,
+229570L,
+142564L,
+279746L,
+142564L,
+322754L,
+142564L,
+362178L,
+142564L,
+545474L,
+142564L,
+362178L,
+142564L,
+545474L,
+142564L,
+362178L,
+142564L,
+545474L,
+142564L,
+362178L,
+142564L,
+545474L,
+142564L,
+718531L,
+142564L,
+733891L,
+142564L,
+752835L,
+142564L,
+752835L,
+142564L,
+752835L,
+142560L,
+752835L,
+141029L,
+125122L,
+657125L,
+87747L,
+216165L,
+402018L,
+142564L,
+716483L,
+141029L,
+131778L,
+118405L,
+787781L,
+141029L,
+142530L,
+216165L,
+402018L,
+142564L,
+721603L,
+141029L,
+693442L,
+118405L,
+728389L,
+739141L,
+99973L,
+773957L,
+118917L,
+727365L,
+730949L,
+738629L,
+723776L,
+753157L,
+541285L,
+195141L,
+546405L,
+194629L,
+560741L,
+193605L,
+262277L,
+694784L,
+541509L,
+546309L,
+447909L,
+141029L,
+710850L,
+216165L,
+402018L,
+142564L,
+736963L,
+141029L,
+791234L,
+539749L,
+194629L,
+541285L,
+228933L,
+546917L,
+193605L,
+377957L,
+194117L,
+739941L,
+253509L,
+560741L,
+195141L,
+118917L,
+723781L,
+722757L,
+724805L,
+724293L,
+730949L,
+726853L,
+735557L,
+725317L,
+694784L,
+539653L,
+377858L,
+147094L,
+560641L,
+98437L,
+118422L,
+546838L,
+141029L,
+809666L,
+216165L,
+402018L,
+142564L,
+760003L,
+142564L,
+822467L,
+142564L,
+830147L,
+142564L,
+838339L,
+142560L,
+845507L,
+141029L,
+949955L,
+267909L,
+194373L,
+450661L,
+257605L,
+494693L,
+450629L,
+118917L,
+723781L,
+727365L,
+727877L,
+730949L,
+743237L,
+118405L,
+725317L,
+724293L,
+738629L,
+739141L,
+726853L,
+737605L,
+734021L,
+280197L,
+729413L,
+738117L,
+546917L,
+228933L,
+280706L,
+694806L,
+546821L,
+118917L,
+549184L,
+549381L,
+377957L,
+194629L,
+377861L,
+565349L,
+195141L,
+281221L,
+565573L,
+560741L,
+118914L,
+459894L,
+560645L,
+694789L,
+13381L,
+119429L,
+14144L,
+14341L,
+402021L,
+79074L,
+786115L,
+524288L,
+755200L,
+202245L,
+202757L,
+203269L,
+76517L,
+792259L,
+77029L,
+797379L,
+78053L,
+802499L,
+78565L,
+807619L,
+119429L,
+746817L,
+192837L,
+196613L,
+265349L,
+752448L,
+53477L,
+816323L,
+141029L,
+811715L,
+119429L,
+747329L,
+192837L,
+196613L,
+116869L,
+752453L,
+53477L,
+816323L,
+141029L,
+811715L,
+240773L,
+756033L,
+192837L,
+196613L,
+116869L,
+752453L,
+53477L,
+816323L,
+141029L,
+811715L,
+240773L,
+756545L,
+192837L,
+196613L,
+265349L,
+752448L,
+53477L,
+816323L,
+410213L,
+192069L,
+694789L,
+262277L,
+541504L,
+694801L,
+761861L,
+141029L,
+85699L,
+410725L,
+192069L,
+281733L,
+767301L,
+694789L,
+240773L,
+541509L,
+694789L,
+118917L,
+216389L,
+141029L,
+87747L,
+192101L,
+194146L,
+143588L,
+1005250L,
+192005L,
+141029L,
+87747L,
+410725L,
+192069L,
+694789L,
+240773L,
+541509L,
+694789L,
+141029L,
+85699L,
+119429L,
+694789L,
+549701L,
+694789L,
+192101L,
+194146L,
+143588L,
+1014978L,
+192005L,
+141029L,
+970435L,
+411237L,
+201797L,
+192069L,
+141029L,
+968387L,
+192101L,
+194146L,
+143588L,
+841923L,
+192005L,
+141029L,
+970435L,
+411744L,
+192069L,
+205317L,
+203781L,
+204293L,
+141029L,
+968387L,
+657637L,
+970435L,
+204901L,
+204386L,
+412580L,
+203877L,
+204362L,
+203781L,
+203877L,
+412581L,
+204712L,
+660064L,
+203884L,
+204197L,
+204394L,
+204709L,
+192106L,
+205314L,
+143589L,
+858307L,
+194149L,
+524292L,
+192005L,
+141541L,
+970435L,
+253541L,
+262242L,
+142563L,
+916163L,
+142563L,
+912579L,
+142565L,
+878275L,
+517221L,
+516706L,
+205435L,
+193122L,
+283268L,
+660069L,
+516720L,
+515589L,
+147173L,
+869059L,
+515169L,
+517220L,
+515077L,
+196162L,
+515685L,
+524292L,
+195589L,
+141029L,
+882371L,
+192677L,
+515168L,
+253448L,
+283270L,
+147173L,
+876227L,
+660065L,
+524292L,
+524311L,
+192517L,
+141029L,
+939715L,
+205413L,
+193122L,
+524292L,
+660069L,
+516720L,
+517125L,
+196163L,
+195589L,
+640L,
+253253L,
+192517L,
+196197L,
+195682L,
+192612L,
+144101L,
+888515L,
+196098L,
+253029L,
+524291L,
+192517L,
+195685L,
+282242L,
+79077L,
+891075L,
+129669L,
+253031L,
+195586L,
+138343L,
+252932L,
+144101L,
+895171L,
+141029L,
+883907L,
+192609L,
+524296L,
+79077L,
+903875L,
+517223L,
+192512L,
+253445L,
+516706L,
+96923L,
+147169L,
+901315L,
+524288L,
+192613L,
+283267L,
+192517L,
+141029L,
+876227L,
+192517L,
+114309L,
+253537L,
+517220L,
+143589L,
+872131L,
+516706L,
+516219L,
+192610L,
+145125L,
+910019L,
+524305L,
+524291L,
+192517L,
+515077L,
+141029L,
+923331L,
+205413L,
+193122L,
+282244L,
+516613L,
+192837L,
+141029L,
+923331L,
+205413L,
+193088L,
+192517L,
+79077L,
+923331L,
+281733L,
+752448L,
+202245L,
+202757L,
+203269L,
+410725L,
+118917L,
+141029L,
+924355L,
+201829L,
+118405L,
+192069L,
+216389L,
+253541L,
+262242L,
+192612L,
+253440L,
+755205L,
+283266L,
+524311L,
+192517L,
+192613L,
+283269L,
+77026L,
+935107L,
+76535L,
+936643L,
+78053L,
+938179L,
+756229L,
+141029L,
+970435L,
+747013L,
+141029L,
+970435L,
+746501L,
+141029L,
+970435L,
+755717L,
+141029L,
+970435L,
+77029L,
+945347L,
+76535L,
+946883L,
+78053L,
+948419L,
+232037L,
+524291L,
+756229L,
+141029L,
+949955L,
+747013L,
+141029L,
+949955L,
+746501L,
+141029L,
+949955L,
+231525L,
+524291L,
+755717L,
+756736L,
+752133L,
+727045L,
+727557L,
+730629L,
+729093L,
+723461L,
+726533L,
+737285L,
+738309L,
+738821L,
+216069L,
+766981L,
+761861L,
+742917L,
+724997L,
+723973L,
+733701L,
+257637L,
+450629L,
+560741L,
+284290L,
+694805L,
+560645L,
+228965L,
+546880L,
+541189L,
+548869L,
+549381L,
+194661L,
+377925L,
+195173L,
+565317L,
+694789L,
+141029L,
+87747L,
+216165L,
+402018L,
+524291L,
+216069L,
+127077L,
+413093L,
+202856L,
+414629L,
+203372L,
+415141L,
+414124L,
+202245L,
+202858L,
+413605L,
+203340L,
+202341L,
+202821L,
+204805L,
+141029L,
+87747L,
+524293L,
+82149L,
+984259L,
+514661L,
+118402L,
+142565L,
+985795L,
+771392L,
+514565L,
+141029L,
+985795L,
+524288L,
+524305L,
+514565L,
+191077L,
+549605L,
+989891L,
+4165L,
+191589L,
+4677L,
+141029L,
+145600L,
+391088L,
+660069L,
+234632L,
+524295L,
+660065L,
+191075L,
+191077L,
+17120L,
+995011L,
+524290L,
+4101L,
+191589L,
+19168L,
+997571L,
+524290L,
+4613L,
+141029L,
+145600L,
+736L,
+562880L,
+452200L,
+141029L,
+562368L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+3557,
+3861,
+3329,
+0,
+4275,
+0,
+193,
+1089
+};
+
+static const uInt16 patchSupportAddr [] = {
+1023,
+1021,
+1020,
+1019,
+1018,
+1017,
+1015,
+1014,
+1013,
+1012,
+1011,
+804,
+1008,
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0x1FFFFFFL,
+0x500000L,
+0x0L,
+0xA126E9L,
+0x7FFFFFFL,
+0xA18937L,
+0xC49BA5L,
+0x80000L,
+0x0L,
+0x400000L,
+0x800000L,
+0x4B00L,
+0x320000L,
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3217xPatchRevBBkbt = {
+#else
+const proslicPatch RevBPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x1010B001L,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_patch_B_FB_2010DEC16.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_patch_B_FB_2010DEC16.c
new file mode 100755
index 0000000..4892c22
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3217x_patch_B_FB_2010DEC16.c
@@ -0,0 +1,999 @@
+/*
+** Generated from si3217x_patch_B_FB_2010DEC16.dsp_prom
+** on 12-16-2010 at 16:16:45
+*/
+#include "si_voice_datatypes.h"
+#include "si3217x.h"
+
+static const uInt32 patchData [] = {
+141029L,
+532675L,
+141029L,
+540867L,
+141029L,
+661699L,
+141029L,
+678083L,
+141029L,
+678595L,
+141029L,
+978627L,
+141029L,
+979139L,
+141029L,
+999107L,
+558181L,
+519586L,
+524309L,
+142565L,
+539331L,
+172645L,
+524197L,
+524296L,
+523269L,
+523365L,
+522864L,
+524291L,
+246789L,
+246885L,
+141029L,
+773313L,
+76005L,
+546499L,
+17637L,
+548547L,
+257125L,
+262242L,
+143587L,
+546499L,
+257029L,
+141029L,
+551107L,
+776293L,
+261762L,
+141045L,
+550595L,
+776293L,
+119426L,
+517750L,
+257093L,
+776197L,
+541925L,
+554179L,
+518245L,
+792133L,
+141029L,
+934081L,
+518757L,
+792133L,
+141029L,
+556227L,
+62688L,
+568003L,
+115205L,
+548069L,
+560835L,
+451685L,
+223301L,
+141029L,
+568003L,
+223333L,
+262242L,
+142563L,
+568003L,
+223237L,
+143077L,
+568003L,
+171525L,
+172037L,
+172549L,
+173061L,
+173573L,
+174085L,
+174597L,
+52448L,
+571587L,
+17632L,
+571587L,
+376741L,
+181761L,
+182277L,
+670213L,
+536293L,
+598723L,
+683525L,
+576741L,
+576707L,
+211557L,
+524290L,
+141541L,
+577731L,
+535269L,
+582339L,
+251013L,
+432737L,
+116229L,
+111680L,
+112197L,
+112645L,
+113157L,
+113669L,
+211461L,
+117893L,
+116321L,
+251011L,
+116229L,
+666341L,
+594115L,
+111713L,
+116224L,
+112227L,
+432291L,
+660064L,
+112234L,
+30213L,
+111716L,
+111616L,
+30307L,
+113251L,
+112128L,
+112228L,
+147077L,
+524298L,
+113672L,
+113157L,
+112741L,
+113762L,
+112227L,
+112645L,
+524294L,
+524294L,
+115205L,
+141029L,
+619203L,
+535781L,
+21698L,
+683525L,
+432736L,
+211556L,
+30213L,
+576741L,
+604355L,
+30306L,
+141538L,
+605379L,
+535269L,
+607939L,
+111616L,
+112133L,
+432293L,
+211457L,
+114181L,
+111717L,
+114274L,
+432739L,
+111620L,
+144099L,
+611523L,
+111685L,
+30307L,
+142053L,
+613571L,
+111685L,
+96901L,
+112225L,
+433251L,
+112132L,
+666341L,
+618179L,
+114272L,
+112132L,
+114181L,
+111717L,
+115269L,
+537829L,
+646851L,
+181349L,
+373858L,
+151173L,
+262250L,
+181253L,
+141541L,
+641731L,
+182370L,
+181859L,
+182277L,
+666853L,
+639683L,
+461410L,
+667L,
+670949L,
+628931L,
+377157L,
+181861L,
+374370L,
+667L,
+146661L,
+638147L,
+374885L,
+254107L,
+146661L,
+638147L,
+375397L,
+262299L,
+146661L,
+638147L,
+375909L,
+262811L,
+146661L,
+638147L,
+245893L,
+376933L,
+524296L,
+376837L,
+645L,
+524289L,
+181248L,
+181765L,
+5221L,
+374181L,
+524296L,
+660069L,
+181872L,
+377251L,
+181765L,
+115301L,
+524296L,
+115205L,
+549605L,
+649923L,
+115301L,
+245893L,
+524296L,
+115205L,
+115301L,
+431714L,
+524291L,
+115205L,
+393317L,
+522338L,
+524292L,
+660069L,
+263813L,
+115304L,
+660068L,
+141541L,
+657091L,
+115269L,
+524288L,
+115300L,
+660066L,
+524292L,
+141541L,
+660675L,
+115269L,
+141029L,
+1029825L,
+520290L,
+520197L,
+521636L,
+141541L,
+664771L,
+524288L,
+524294L,
+524294L,
+524294L,
+524294L,
+660069L,
+520808L,
+519779L,
+521732L,
+144101L,
+670403L,
+521797L,
+5733L,
+521840L,
+24293L,
+673475L,
+35429L,
+385136L,
+524295L,
+2147L,
+393315L,
+188420L,
+144101L,
+677059L,
+188485L,
+141029L,
+661185L,
+524293L,
+264322L,
+402037L,
+143076L,
+691907L,
+25829L,
+689859L,
+201312L,
+201218L,
+142565L,
+87747L,
+547941L,
+245890L,
+142560L,
+87747L,
+694789L,
+537605L,
+538437L,
+538629L,
+694785L,
+721925L,
+141029L,
+718531L,
+201280L,
+182789L,
+141029L,
+87747L,
+142564L,
+712387L,
+524292L,
+524292L,
+142564L,
+229570L,
+142564L,
+279746L,
+142564L,
+322754L,
+142564L,
+362178L,
+142564L,
+545474L,
+142564L,
+362178L,
+142564L,
+545474L,
+142564L,
+362178L,
+142564L,
+545474L,
+142564L,
+362178L,
+142564L,
+545474L,
+142564L,
+718531L,
+142564L,
+733891L,
+142564L,
+752835L,
+142564L,
+752835L,
+142564L,
+752835L,
+142560L,
+752835L,
+141029L,
+125122L,
+657125L,
+87747L,
+216165L,
+402018L,
+142564L,
+716483L,
+141029L,
+131778L,
+118405L,
+787781L,
+141029L,
+142530L,
+216165L,
+402018L,
+142564L,
+721603L,
+141029L,
+693442L,
+118405L,
+728389L,
+739141L,
+99973L,
+773957L,
+118917L,
+727365L,
+730949L,
+738629L,
+723776L,
+753157L,
+541285L,
+195141L,
+546405L,
+194629L,
+560741L,
+193605L,
+262277L,
+694784L,
+541509L,
+546309L,
+447909L,
+141029L,
+710850L,
+216165L,
+402018L,
+142564L,
+736963L,
+141029L,
+791234L,
+539749L,
+194629L,
+541285L,
+228933L,
+546917L,
+193605L,
+377957L,
+194117L,
+739941L,
+253509L,
+560741L,
+195141L,
+118917L,
+723781L,
+722757L,
+724805L,
+724293L,
+730949L,
+726853L,
+735557L,
+725317L,
+694784L,
+539653L,
+377858L,
+147094L,
+560641L,
+98437L,
+118422L,
+546838L,
+141029L,
+809666L,
+216165L,
+402018L,
+142564L,
+760003L,
+142564L,
+822467L,
+142564L,
+830147L,
+142564L,
+838339L,
+142560L,
+845507L,
+141029L,
+949955L,
+267909L,
+194373L,
+450661L,
+257605L,
+494693L,
+450629L,
+118917L,
+723781L,
+727365L,
+727877L,
+730949L,
+743237L,
+118405L,
+725317L,
+724293L,
+738629L,
+739141L,
+726853L,
+737605L,
+734021L,
+280197L,
+729413L,
+738117L,
+546917L,
+228933L,
+280706L,
+694806L,
+546821L,
+118917L,
+549184L,
+549381L,
+377957L,
+194629L,
+377861L,
+565349L,
+195141L,
+281221L,
+565573L,
+560741L,
+118914L,
+459894L,
+560645L,
+694789L,
+13381L,
+119429L,
+14144L,
+14341L,
+402021L,
+79074L,
+786115L,
+524288L,
+755200L,
+202245L,
+202757L,
+203269L,
+76517L,
+792259L,
+77029L,
+797379L,
+78053L,
+802499L,
+78565L,
+807619L,
+119429L,
+746817L,
+192837L,
+196613L,
+265349L,
+752448L,
+53477L,
+816323L,
+141029L,
+811715L,
+119429L,
+747329L,
+192837L,
+196613L,
+116869L,
+752453L,
+53477L,
+816323L,
+141029L,
+811715L,
+240773L,
+756033L,
+192837L,
+196613L,
+116869L,
+752453L,
+53477L,
+816323L,
+141029L,
+811715L,
+240773L,
+756545L,
+192837L,
+196613L,
+265349L,
+752448L,
+53477L,
+816323L,
+410213L,
+192069L,
+694789L,
+262277L,
+541504L,
+694801L,
+761861L,
+141029L,
+85699L,
+410725L,
+192069L,
+281733L,
+767301L,
+694789L,
+240773L,
+541509L,
+694789L,
+118917L,
+216389L,
+141029L,
+87747L,
+192101L,
+194146L,
+143588L,
+1005250L,
+192005L,
+141029L,
+87747L,
+410725L,
+192069L,
+694789L,
+240773L,
+541509L,
+694789L,
+141029L,
+85699L,
+119429L,
+694789L,
+549701L,
+694789L,
+192101L,
+194146L,
+143588L,
+1014978L,
+192005L,
+141029L,
+970435L,
+411237L,
+201797L,
+192069L,
+141029L,
+968387L,
+192101L,
+194146L,
+143588L,
+841923L,
+192005L,
+141029L,
+970435L,
+411744L,
+192069L,
+205317L,
+203781L,
+204293L,
+141029L,
+968387L,
+657637L,
+970435L,
+204901L,
+204386L,
+412580L,
+203877L,
+204362L,
+203781L,
+203877L,
+412581L,
+204712L,
+660064L,
+203884L,
+204197L,
+204394L,
+204709L,
+192106L,
+205314L,
+143589L,
+858307L,
+194149L,
+524292L,
+192005L,
+141541L,
+970435L,
+253541L,
+262242L,
+142563L,
+916163L,
+142563L,
+912579L,
+142565L,
+878275L,
+517221L,
+516706L,
+205435L,
+193122L,
+283268L,
+660069L,
+516720L,
+515589L,
+147173L,
+869059L,
+515169L,
+517220L,
+515077L,
+196162L,
+515685L,
+524292L,
+195589L,
+141029L,
+882371L,
+192677L,
+515168L,
+253448L,
+283270L,
+147173L,
+876227L,
+660065L,
+524292L,
+524311L,
+192517L,
+141029L,
+939715L,
+205413L,
+193122L,
+524292L,
+660069L,
+516720L,
+517125L,
+196163L,
+195589L,
+640L,
+253253L,
+192517L,
+196197L,
+195682L,
+192612L,
+144101L,
+888515L,
+196098L,
+253029L,
+524291L,
+192517L,
+195685L,
+282242L,
+79077L,
+891075L,
+129669L,
+253031L,
+195586L,
+138343L,
+252932L,
+144101L,
+895171L,
+141029L,
+883907L,
+192609L,
+524296L,
+79077L,
+903875L,
+517223L,
+192512L,
+253445L,
+516706L,
+96923L,
+147169L,
+901315L,
+524288L,
+192613L,
+283267L,
+192517L,
+141029L,
+876227L,
+192517L,
+114309L,
+253537L,
+517220L,
+143589L,
+872131L,
+516706L,
+516219L,
+192610L,
+145125L,
+910019L,
+524305L,
+524291L,
+192517L,
+515077L,
+141029L,
+923331L,
+205413L,
+193122L,
+282244L,
+516613L,
+192837L,
+141029L,
+923331L,
+205413L,
+193088L,
+192517L,
+79077L,
+923331L,
+281733L,
+752448L,
+202245L,
+202757L,
+203269L,
+410725L,
+118917L,
+141029L,
+924355L,
+201829L,
+118405L,
+192069L,
+216389L,
+253541L,
+262242L,
+192612L,
+253440L,
+755205L,
+283266L,
+524311L,
+192517L,
+192613L,
+283269L,
+77026L,
+935107L,
+76535L,
+936643L,
+78053L,
+938179L,
+756229L,
+141029L,
+970435L,
+747013L,
+141029L,
+970435L,
+746501L,
+141029L,
+970435L,
+755717L,
+141029L,
+970435L,
+77029L,
+945347L,
+76535L,
+946883L,
+78053L,
+948419L,
+232037L,
+524291L,
+756229L,
+141029L,
+949955L,
+747013L,
+141029L,
+949955L,
+746501L,
+141029L,
+949955L,
+231525L,
+524291L,
+755717L,
+756736L,
+752133L,
+727045L,
+727557L,
+730629L,
+729093L,
+723461L,
+726533L,
+737285L,
+738309L,
+738821L,
+216069L,
+766981L,
+761861L,
+742917L,
+724997L,
+723973L,
+733701L,
+257637L,
+450629L,
+560741L,
+284290L,
+694805L,
+560645L,
+228965L,
+546880L,
+541189L,
+548869L,
+549381L,
+194661L,
+377925L,
+195173L,
+565317L,
+694789L,
+141029L,
+87747L,
+216165L,
+402018L,
+524291L,
+216069L,
+127077L,
+413093L,
+202856L,
+414629L,
+203372L,
+415141L,
+414124L,
+202245L,
+202858L,
+413605L,
+203340L,
+202341L,
+202821L,
+204805L,
+141029L,
+87747L,
+524293L,
+82149L,
+984259L,
+514661L,
+118402L,
+142565L,
+985795L,
+771392L,
+514565L,
+141029L,
+985795L,
+524288L,
+524305L,
+514565L,
+191077L,
+549605L,
+989891L,
+4165L,
+191589L,
+4677L,
+141029L,
+145600L,
+391088L,
+660069L,
+234632L,
+524295L,
+660065L,
+191075L,
+191077L,
+17120L,
+995011L,
+524290L,
+4101L,
+191589L,
+19168L,
+997571L,
+524290L,
+4613L,
+141029L,
+145600L,
+736L,
+562880L,
+452200L,
+141029L,
+562368L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+3557,
+3861,
+3329,
+0,
+4275,
+0,
+193,
+1089
+};
+
+static const uInt16 patchSupportAddr [] = {
+1023,
+1021,
+1020,
+1019,
+1018,
+1017,
+1015,
+1014,
+1013,
+1012,
+1011,
+804,
+1008,
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0x1FFFFFFL,
+0x500000L,
+0x0L,
+0xA126E9L,
+0x7FFFFFFL,
+0xA18937L,
+0xC49BA5L,
+0x80000L,
+0x0L,
+0xB00000L,
+0x800000L,
+0x4B00L,
+0x320000L,
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3217xPatchRevBFlbk = {
+#else
+const proslicPatch RevBPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x1010B000L,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si321x_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si321x_constants.c
new file mode 100755
index 0000000..5840e62
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si321x_constants.c
@@ -0,0 +1,93 @@
+/*

+Copyright (c) 2008 Silicon Laboratories, Inc.

+2008-04-03 17:59:58 */

+/*ProSLIC API Tool Rev0.31 Alpha*/

+

+

+#include "proslic.h"

+#include "si321x.h"

+

+Si321x_General_Cfg Si321x_General_Configuration = {

+	0xff,

+		0xff,

+		0xff

+};

+

+#define AUDIOGAIN_0DB	0

+

+Si321x_audioGain_Cfg Si321x_AudioGain_Presets [] = {

+	{AUDIOGAIN_0DB,0x4000}

+};

+Si321x_PulseMeter_Cfg Si321x_PulseMeter_Presets [] = {

+	{0,0,0,0,0}

+};

+

+Si321x_Ring_Cfg Si321x_Ring_Presets[] ={

+

+

+    /* inputs:  ringtrip ac thresh = 0.036, rt debounce = 0.075*/

+    { 0x155, 0x0, 0x0, 0x7EFD, 0x80, 0x3E, 0x0, 0x7D, 0x18, 0xA, 0x320 }

+};

+

+Si321x_DCfeed_Cfg Si321x_Dcfeed_Presets[] = {

+

+    /* inputs: voc=48.000, vcm=3.000, ilim=20.000*/

+    { 0x0, 0x20, 0x2 }

+};

+

+Si321x_Zsynth_Cfg Si321x_Zsynth_Presets [] ={

+

+{ 0x0, 0x0  },

+{ 0x0, 0x1  }

+};

+

+Si321x_FSK_Cfg Si321x_FSK_Presets[] ={

+

+    /* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000 */

+    { 0x1119L, 0x3BE1L, 0x1E0L, 0x100L, 0x35B0L, 0x3CE0L }

+};

+

+/*

+** Tone Generator configuration

+*/

+#define OSC_TOPHONE 0x2

+#define OSC_350HZ_MINUS18DBM_8KHZ	0x7b30,0x63,0

+#define OSC_350HZ_MINUS18DBM_16KHZ	0x7ed0,0x31,0

+#define OSC_NOTIME				0,0

+#define OSC_0_5SEC				0xa0,0xf

+#define OSC_0_3SEC				0x60,0x9

+#define OSC_0_2SEC				0x40,0x6

+#define OSC_4SEC				0x0,0x7d

+#define	OSC_2SEC				0x80,0x3e

+#define OSC_440HZ_MINUS18DBM_8KHZ	0x7870,0x7d,0 

+#define OSC_440HZ_MINUS18DBM_16KHZ	0x7e20,0x3d,0 

+#define OSC_480HZ_MINUS18DBM_8KHZ	0x7700,0x89,0

+#define OSC_480HZ_MINUS18DBM_16KHZ	0x7dc0,0x43,0

+#define OSC_620HZ_MINUS18DBM_8KHZ	0x7120,0xb2,0

+#define OSC_620HZ_MINUS18DBM_16KHZ	0x7c40,0x57,0

+

+/*Si3210 Tone generator (8kHz) */

+Si321x_Tone_Cfg Si321x_Tone_Presets [] = {

+{{OSC_350HZ_MINUS18DBM_8KHZ,OSC_NOTIME,OSC_NOTIME},{OSC_440HZ_MINUS18DBM_8KHZ,OSC_NOTIME,OSC_NOTIME},OSC_TOPHONE,OSC_TOPHONE},

+{{OSC_480HZ_MINUS18DBM_8KHZ,OSC_0_5SEC,OSC_0_5SEC},{OSC_620HZ_MINUS18DBM_8KHZ,OSC_0_5SEC,OSC_0_5SEC},OSC_TOPHONE,OSC_TOPHONE},

+{{OSC_480HZ_MINUS18DBM_8KHZ,OSC_0_2SEC,OSC_0_3SEC},{OSC_620HZ_MINUS18DBM_8KHZ,OSC_0_2SEC,OSC_0_3SEC},OSC_TOPHONE,OSC_TOPHONE},

+{{OSC_480HZ_MINUS18DBM_8KHZ,OSC_2SEC,OSC_4SEC},{OSC_440HZ_MINUS18DBM_8KHZ,OSC_2SEC,OSC_4SEC},OSC_TOPHONE,OSC_TOPHONE},

+{{OSC_480HZ_MINUS18DBM_8KHZ,OSC_0_3SEC,OSC_0_2SEC},{OSC_620HZ_MINUS18DBM_8KHZ,OSC_0_3SEC,OSC_0_2SEC},OSC_TOPHONE,OSC_TOPHONE}

+};

+

+Si321x_Tone_Cfg Si3215_Tone_Presets [] = {

+{{OSC_350HZ_MINUS18DBM_16KHZ,OSC_NOTIME,OSC_NOTIME},{OSC_440HZ_MINUS18DBM_16KHZ,OSC_NOTIME,OSC_NOTIME},OSC_TOPHONE,OSC_TOPHONE},

+{{OSC_480HZ_MINUS18DBM_16KHZ,OSC_0_5SEC,OSC_0_5SEC},{OSC_620HZ_MINUS18DBM_16KHZ,OSC_0_5SEC,OSC_0_5SEC},OSC_TOPHONE,OSC_TOPHONE},

+{{OSC_480HZ_MINUS18DBM_16KHZ,OSC_0_2SEC,OSC_0_3SEC},{OSC_620HZ_MINUS18DBM_16KHZ,OSC_0_2SEC,OSC_0_3SEC},OSC_TOPHONE,OSC_TOPHONE},

+{{OSC_480HZ_MINUS18DBM_16KHZ,OSC_2SEC,OSC_4SEC},{OSC_440HZ_MINUS18DBM_16KHZ,OSC_2SEC,OSC_4SEC},OSC_TOPHONE,OSC_TOPHONE},

+{{OSC_480HZ_MINUS18DBM_16KHZ,OSC_0_3SEC,OSC_0_2SEC},{OSC_620HZ_MINUS18DBM_16KHZ,OSC_0_3SEC,OSC_0_2SEC},OSC_TOPHONE,OSC_TOPHONE}

+};

+

+Si321x_PCM_Cfg Si321x_Pcm_Presets[] ={

+

+    /* inputs:  u-law narrowband positive  */

+    { 0x1, 0x0, 0x0 },

+    /* inputs:  16 bit wideband positive  */

+    { 0x3, 0x1, 0x0 }

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si321x_constants.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si321x_constants.h
new file mode 100755
index 0000000..920b300
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si321x_constants.h
@@ -0,0 +1,37 @@
+/*

+Copyright (c) 2008 Silicon Laboratories, Inc.

+2008-04-03 17:59:58 */

+/*ProSLIC API Tool Rev0.31 Alpha*/

+

+

+enum {

+	USA_DEFAULT_RING

+};

+

+enum {

+	DEFAULT_DCFEED

+};

+

+enum {

+	ZSYNTH_600,

+	ZSYNTH_900

+};

+

+enum {

+	USA_DEFAULT_FSK

+};

+

+enum {

+	USA_DIAL_TONE,

+	USA_BUSY_TONE,

+	USA_CONGESTION_TONE,

+	USA_RINGBACK_TONE,

+	USA_REORDER_TONE

+};

+

+enum {

+	DEFAULT_PCM,

+	WIDEBAND_PCM

+};

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_FLBK_QCUK_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_FLBK_QCUK_constants.c
new file mode 100755
index 0000000..c7796d7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_FLBK_QCUK_constants.c
@@ -0,0 +1,451 @@
+/*

+Copyright (c) 2008 Silicon Laboratories, Inc.

+2008-03-18 16:06:28 */

+

+#include "proslic.h"

+#include "si3226.h"

+Si3226_General_Cfg Si3226_General_Configuration  = {

+BO_DCDC_QCUK,	

+0x8720000L,	/* VBATR_EXPECT */

+0x3D70000L,	/* VBATH_EXPECT */

+0x0L,	    /* DCDC_FSW_VTHLO */

+0x0L,	    /* DCDC_FSW_VHYST */

+0x1300000L,	/* DCDC_VREF_MIN */

+0x5A00000L,	/* DCDC_VREF_MIN_RING */

+0x200000L,	/* DCDC_FSW_NORM */

+0x200000L,	/* DCDC_FSW_NORM_LO */

+0x200000L,	/* DCDC_FSW_RING */

+0x100000L,	/* DCDC_FSW_RING_LO */

+0xD980000L,	/* DCDC_DIN_LIM */

+0xC00000L,	/* DCDC_VOUT_LIM */

+0x0L,	    /* DCDC_DCFF_ENABLE */

+0x500000L,	/* DCDC_UVHYST */

+0x600000L,	/* DCDC_UVTHRESH */

+0xB00000L,	/* DCDC_OVTHRESH */

+0x1F00000L,	/* DCDC_OITHRESH */

+0x100000L,	/* DCDC_SWDRV_POL */

+0x300000L,	/* DCDC_SWFET */

+0x600000L,	/* DCDC_VREF_CTRL */

+0x200000L,	/* DCDC_RNGTYPE */

+0x0L,	    /* DCDC_ANA_GAIN */

+0x0L,	    /* DCDC_ANA_TOFF */

+0x0L,	    /* DCDC_ANA_TONMIN */

+0x0L,	    /* DCDC_ANA_TONMAX */

+0x0L,	    /* DCDC_ANA_DSHIFT */

+0x0L,	    /* DCDC_ANA_LPOLY */

+0x7FeF000L,	/* COEF_P_HVIC */

+0x68D000L,	/* P_TH_HVIC */

+0x0,	    /* CM_CLAMP */

+0x3F,	    /* AUTO */

+0x0,	    /* DAA_CNTL */

+0x7F,	    /* IRQEN1 */

+0xFF,	    /* IRQEN2 */

+0xFF,	    /* IRQEN3 */

+0xFF,	    /* IRQEN4 */

+0x0,	    /* ENHANCE */

+0,	        /* DAA_ENABLE */

+0x8000000L,	/* SCALE_KAUDIO */

+0x151EB80L,	/* AC_ADC_GAIN */

+};

+

+#ifdef SIVOICE_MULTI_BOM_SUPPORT

+

+int si3226_genconf_multi_max_preset = 2;

+

+Si3226_General_Cfg Si3226_General_Configuration_MultiBOM[]  = {

+{

+BO_DCDC_FLYBACK,	

+0x8720000L,	/* VBATR_EXPECT */

+0x3D70000L,	/* VBATH_EXPECT */

+0x0L,	    /* DCDC_FSW_VTHLO */

+0x0L,	    /* DCDC_FSW_VHYST */

+0x1300000L,	/* DCDC_VREF_MIN */

+0x5A00000L,	/* DCDC_VREF_MIN_RING */

+0x200000L,	/* DCDC_FSW_NORM */

+0x200000L,	/* DCDC_FSW_NORM_LO */

+0x200000L,	/* DCDC_FSW_RING */

+0x100000L,	/* DCDC_FSW_RING_LO */

+0xD980000L,	/* DCDC_DIN_LIM */

+0xC00000L,	/* DCDC_VOUT_LIM */

+0x0L,	    /* DCDC_DCFF_ENABLE */

+0x500000L,	/* DCDC_UVHYST */

+0x600000L,	/* DCDC_UVTHRESH */

+0xB00000L,	/* DCDC_OVTHRESH */

+0x1F00000L,	/* DCDC_OITHRESH */

+0x100000L,	/* DCDC_SWDRV_POL */

+0x300000L,	/* DCDC_SWFET */

+0x600000L,	/* DCDC_VREF_CTRL */

+0x200000L,	/* DCDC_RNGTYPE */

+0x0L,	    /* DCDC_ANA_GAIN */

+0x0L,	    /* DCDC_ANA_TOFF */

+0x0L,	    /* DCDC_ANA_TONMIN */

+0x0L,	    /* DCDC_ANA_TONMAX */

+0x0L,	    /* DCDC_ANA_DSHIFT */

+0x0L,	    /* DCDC_ANA_LPOLY */

+0x7FeF000L,	/* COEF_P_HVIC */

+0x68D000L,	/* P_TH_HVIC */

+0x0,	    /* CM_CLAMP */

+0x3F,	    /* AUTO */

+0x0,	    /* DAA_CNTL */

+0x7F,	    /* IRQEN1 */

+0xFF,	    /* IRQEN2 */

+0xFF,	    /* IRQEN3 */

+0xFF,	    /* IRQEN4 */

+0x0,	    /* ENHANCE */

+0,	        /* DAA_ENABLE */

+0x8000000L,	/* SCALE_KAUDIO */

+0x151EB80L	/* AC_ADC_GAIN */

+},

+{

+BO_DCDC_QCUK,	

+0x8720000L,	/* VBATR_EXPECT */

+0x3D70000L,	/* VBATH_EXPECT */

+0x0L,	    /* DCDC_FSW_VTHLO */

+0x0L,	    /* DCDC_FSW_VHYST */

+0x1300000L,	/* DCDC_VREF_MIN */

+0x5A00000L,	/* DCDC_VREF_MIN_RING */

+0x200000L,	/* DCDC_FSW_NORM */

+0x200000L,	/* DCDC_FSW_NORM_LO */

+0x200000L,	/* DCDC_FSW_RING */

+0x100000L,	/* DCDC_FSW_RING_LO */

+0xD980000L,	/* DCDC_DIN_LIM */

+0xC00000L,	/* DCDC_VOUT_LIM */

+0x0L,	    /* DCDC_DCFF_ENABLE */

+0x500000L,	/* DCDC_UVHYST */

+0x600000L,	/* DCDC_UVTHRESH */

+0xB00000L,	/* DCDC_OVTHRESH */

+0x1F00000L,	/* DCDC_OITHRESH */

+0x100000L,	/* DCDC_SWDRV_POL */

+0x300000L,	/* DCDC_SWFET */

+0x600000L,	/* DCDC_VREF_CTRL */

+0x200000L,	/* DCDC_RNGTYPE */

+0x0L,	    /* DCDC_ANA_GAIN */

+0x0L,	    /* DCDC_ANA_TOFF */

+0x0L,	    /* DCDC_ANA_TONMIN */

+0x0L,	    /* DCDC_ANA_TONMAX */

+0x0L,	    /* DCDC_ANA_DSHIFT */

+0x0L,	    /* DCDC_ANA_LPOLY */

+0x7FeF000L,	/* COEF_P_HVIC */

+0x68D000L,	/* P_TH_HVIC */

+0x0,	    /* CM_CLAMP */

+0x3F,	    /* AUTO */

+0x0,	    /* DAA_CNTL */

+0x7F,	    /* IRQEN1 */

+0xFF,	    /* IRQEN2 */

+0xFF,	    /* IRQEN3 */

+0xFF,	    /* IRQEN4 */

+0x0,	    /* ENHANCE */

+0,	        /* DAA_ENABLE */

+0x8000000L,	/* SCALE_KAUDIO */

+0x151EB80L 	/* AC_ADC_GAIN */

+}

+};

+#endif

+

+Si3226_DTMFDec_Cfg Si3226_DTMFDec_Presets[] = {

+	{0x2d40000L,0x1a660000L,0x2d40000L,0x6ba0000L,0x1dcc0000L,0x33f0000L,0xbd30000L,0x19d20000L,0x4150000L,0x188F0000L,0x4150000L,0xd970000L,0x18620000L,0xf1c0000L}

+};

+Si3226_GPIO_Cfg Si3226_GPIO_Configuration = {

+	0,0,0,0,0,0,0

+};

+

+Si3226_CI_Cfg Si3226_CI_Presets [] = {

+	{0}

+};

+Si3226_audioGain_Cfg Si3226_audioGain_Presets [] = {

+	{0x1377080L,0,0L,0L,0L,0L},

+	{0x80C3180L,0,0L,0L,0L,0L}

+};

+

+Si3226_Ring_Cfg Si3226_Ring_Presets[] ={

+{ /* RING_F20_45VRMS_0VDC_LPR */

+0x00050000L,		/* RTPER */

+0x07EFD9D5L,		/* RINGFR */

+0x001BD493L,		/* RINGAMP */

+0x00000000L,		/* RINGPHAS */

+0x00000000L,		/* RINGOF */

+0x15E5200EL,		/* SLOPE_RING */

+0x00D16348L,		/* IRING_LIM */

+0x0068C6BBL,		/* RTACTH */

+0x0FFFFFFFL,		/* RTDCTH */

+0x00006000L,		/* RTACDB */

+0x00006000L,		/* RTDCDB */

+0x0064874DL,		/* VOV_RING_BAT */

+0x0064874DL,		/* VOV_RING_GND */

+0x049CE106L,		/* VBATR_EXPECT */

+0x80,		/* RINGTALO */

+0x3E,		/* RINGTAHI */

+0x00,		/* RINGTILO */

+0x7D,		/* RINGTIHI */

+0x01000547L,		/* ADAP_RING_MIN_I */

+0x00003000L,		/* COUNTER_IRING_VAL */

+0x00051EB8L,		/* COUNTER_VTR_VAL */

+0x0163063FL,		/* CONST_028 */

+0x019E31F4L,		/* CONST_032 */

+0x01F108BEL,		/* CONST_036 */

+0x026D4AEEL,		/* CONST_046 */

+0x00370000L,		/* RRD_DELAY */

+0x00190000L,		/* RRD_DELAY2 */

+0x01893740L,		/* DCDC_VREF_MIN_RNG */

+0x58,		/* RINGCON */

+0x01,		/* USERSTAT */

+0x024E7083L,		/* VCM_RING */

+0x024E7083L,		/* VCM_RING_FIXED */

+0x003126E8L,		/* DELTA_VCM */

+0x200000L,		/* DCDC_RNGTYPE */

+},

+{ /* RING_F20_45VRMS_0VDC_BAL */

+0x00050000L,		/* RTPER */

+0x07EFD9D5L,		/* RINGFR */

+0x001BD493L,		/* RINGAMP */

+0x00000000L,		/* RINGPHAS */

+0x00000000L,		/* RINGOF */

+0x15E5200EL,		/* SLOPE_RING */

+0x00D16348L,		/* IRING_LIM */

+0x0068C6BBL,		/* RTACTH */

+0x0FFFFFFFL,		/* RTDCTH */

+0x00006000L,		/* RTACDB */

+0x00006000L,		/* RTDCDB */

+0x0064874DL,		/* VOV_RING_BAT */

+0x0064874DL,		/* VOV_RING_GND */

+0x0565EFA2L,		/* VBATR_EXPECT */

+0x80,		/* RINGTALO */

+0x3E,		/* RINGTAHI */

+0x00,		/* RINGTILO */

+0x7D,		/* RINGTIHI */

+0x01000547L,		/* ADAP_RING_MIN_I */

+0x00003000L,		/* COUNTER_IRING_VAL */

+0x00051EB8L,		/* COUNTER_VTR_VAL */

+0x0163063FL,		/* CONST_028 */

+0x019E31F4L,		/* CONST_032 */

+0x01F108BEL,		/* CONST_036 */

+0x026D4AEEL,		/* CONST_046 */

+0x00370000L,		/* RRD_DELAY */

+0x00190000L,		/* RRD_DELAY2 */

+0x01893740L,		/* DCDC_VREF_MIN_RNG */

+0x58,		/* RINGCON */

+0x00,		/* USERSTAT */

+0x02B2F7D1L,		/* VCM_RING */

+0x02B2F7D1L,		/* VCM_RING_FIXED */

+0x003126E8L,		/* DELTA_VCM */

+0x200000L,		/* DCDC_RNGTYPE */

+},

+{ /* RING_F20_55VRMS_48VDC_LPR */

+0x00050000L,		/* RTPER */

+0x07EFD9D5L,		/* RINGFR */

+0x002203D0L,		/* RINGAMP */

+0x00000000L,		/* RINGPHAS */

+0x049A5F69L,		/* RINGOF */

+0x15E5200EL,		/* SLOPE_RING */

+0x00D16348L,		/* IRING_LIM */

+0x032EDF91L,		/* RTACTH */

+0x0038E38EL,		/* RTDCTH */

+0x00006000L,		/* RTACDB */

+0x00006000L,		/* RTDCDB */

+0x007ADE42L,		/* VOV_RING_BAT */

+0x007ADE42L,		/* VOV_RING_GND */

+0x08B5BA6CL,		/* VBATR_EXPECT */

+0x80,		/* RINGTALO */

+0x3E,		/* RINGTAHI */

+0x00,		/* RINGTILO */

+0x7D,		/* RINGTIHI */

+0x0138EA01L,		/* ADAP_RING_MIN_I */

+0x00003000L,		/* COUNTER_IRING_VAL */

+0x00051EB8L,		/* COUNTER_VTR_VAL */

+0x01A40BA6L,		/* CONST_028 */

+0x01EA0D97L,		/* CONST_032 */

+0x024C104FL,		/* CONST_036 */

+0x02DF1463L,		/* CONST_046 */

+0x00370000L,		/* RRD_DELAY */

+0x00190000L,		/* RRD_DELAY2 */

+0x01893740L,		/* DCDC_VREF_MIN_RNG */

+0x58,		/* RINGCON */

+0x01,		/* USERSTAT */

+0x045ADD36L,		/* VCM_RING */

+0x045ADD36L,		/* VCM_FIXED_RING */

+0x003126E8L,		/* DELTA_VCM */

+0x200000L,		/* DCDC_RNGTYPE */

+}

+};

+

+Si3226_DCfeed_Cfg Si3226_DCfeed_Presets[] = {

+

+    /* inputs: v_vlim=48.000, i_vlim=0.000, v_rfeed=42.800, i_rfeed=10.000,v_ilim=33.200, i_ilim=20.000,

+ vcm_oh=27.000, vov_gnd=4.000, vov_bat=4.000, r_ring=320.000

+ lcronhk=10.000, lcroffhk=12.000, lcrdbi=5.000, longhith=8.000, longloth=7.000, longdbi=5.000

+ lcrmask=80.000, lcrmask_polrev=80.000, lcrmask_state=200.000, lcrmask_linecap=200.000 */

+{ /* DCFEED_48V_20MA */

+0x1DDF41C9L,    /* SLOPE_VLIM */

+0x1EF68D5EL,    /* SLOPE_RFEED */

+0x40A0E0L,      /* SLOPE_ILIM */

+0x18AAD168L,    /* SLOPE_DELTA1 */

+0x1CA39FFAL,    /* SLOPE_DELTA2 */

+0x5A38633L,     /* V_VLIM */

+0x5072476L,     /* V_RFEED */

+0x3E67006L,     /* V_ILIM */

+0xFDFAB5L,      /* CONST_RFEED */

+0x5D0FA6L,      /* CONST_ILIM */

+0x2D8D96L,      /* I_VLIM */

+0x5B0AFBL,      /* LCRONHK */

+0x6D4060L,      /* LCROFFHK */

+0x8000L,        /* LCRDBI */

+0x48D595L,      /* LONGHITH */

+0x3FBAE2L,      /* LONGLOTH */

+0x8000L,        /* LONGDBI */

+0x120000L,       /* LCRMASK */

+0x80000L,       /* LCRMASK_POLREV */

+0x140000L,      /* LCRMASK_STATE */

+0x140000L,      /* LCRMASK_LINECAP */

+0x1BA5E35L,     /* VCM_OH */

+0x418937L,      /* VOV_BAT */

+0x418937L       /* VOV_GND */

+},

+{ /* DCFEED_48V_25MA */

+0x1D46EA04L,    /* SLOPE_VLIM */

+0x1EA4087EL,    /* SLOPE_RFEED */

+0x40A0E0L,      /* SLOPE_ILIM */

+0x1A224120L,    /* SLOPE_DELTA1 */

+0x1D4FB32EL,    /* SLOPE_DELTA2 */

+0x5A38633L,     /* V_VLIM */ 

+0x5072476L,     /* V_RFEED */ 

+0x3E67006L,     /* V_ILIM */ 

+0x13D7962L,     /* CONST_RFEED */ 

+0x74538FL,      /* CONST_ILIM */ 

+0x2D8D96L,      /* I_VLIM */ 

+0x5B0AFBL,      /* LCRONHK */

+0x6D4060L,      /* LCROFFHK */

+0x8000L,        /* LCRDBI */

+0x48D595L,      /* LONGHITH */

+0x3FBAE2L,      /* LONGLOTH */

+0x8000L,        /* LONGDBI */

+0x120000L,       /* LCRMASK */

+0x80000L,       /* LCRMASK_POLREV */

+0x140000L,      /* LCRMASK_STATE */

+0x140000L,      /* LCRMASK_LINECAP */

+0x1BA5E35L,     /* VCM_OH */

+0x418937L,      /* VOV_BAT */

+0x418937L       /* VOV_GND */

+}

+};

+

+Si3226_Impedance_Cfg Si3226_Impedance_Presets[] ={

+{  /* Si3226_600_0_0_30_0.txt - ZSYN_600_0_0 */

+{0x08066500L, 0x1FF6FC80L, 0x00050B00L, 0x1FFE2680L,    /* TXACEQ */

+ 0x0800D000L, 0x1FF6C700L, 0x00025700L, 0x1FFB2300L},   /* RXACEQ */

+{0x00151F00L, 0x1FE4D400L, 0x01E78880L, 0x00573380L,    /* ECFIR/ECIIR */

+ 0x020AF880L, 0x1EF79A80L, 0x00B35800L, 0x1F955080L,

+ 0x003E6600L, 0x1FBC7880L, 0x01E9AA00L, 0x05F27E00L},

+{0x025AFA00L, 0x1C1FAD80L, 0x0185EC00L, 0x0A195E00L,    /* ZSYNTH */

+ 0x1DE3B180L, 0x31}, 

+ 0x08775F80L,   /* TXACGAIN */

+ 0x01450700L,   /* RXACGAIN */

+ 0x07B41580L, 0x184BEB00L, 0x07682B80L,    /* RXACHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_270_750_150_30_0.txt - ZSYN_270_750_150*/

+  {0x071F7A80L,0x1FD01280L,0x00132700L,0x1FFEF980L, /* TXACEQ */

+   0x0A8AA300L,0x1B9A5500L,0x008E7F00L,0x1FD7F300L}, /* RXACEQ */

+  {0x0068CA00L,0x1EAE1E00L,0x0394FA00L,0x1E94AE80L,  /* ECFIR/ECIIR */

+   0x0356D800L,0x0166CA80L,0x1EC16380L,0x01DE2780L,

+   0x1F852300L,0x0046BE80L,0x02F17C80L,0x1EBCD280L},  

+  {0x028A0C00L,0x19EE4580L,0x03876100L,0x0A762700L, /* ZSYNTH */

+   0x1D87A380L,0x93},  

+  0x08000000L, /* TXACGAIN */

+  0x0109C280L, /* RXACGAIN */

+   0x07BC6F00L,0x18439180L,0x0778DE00L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_370_620_310_30_0.txt - ZSYN_370_620_310 */

+  {0x07E59E80L,0x1FD33400L,0x1FFDF800L,0x1FFD8300L, /* TXACEQ */

+   0x09F38000L,0x1C1C5A00L,0x1F94D700L,0x1FDE5800L}, /* RXACEQ */

+  {0x00234480L,0x1F9CDD00L,0x01F5D580L,0x1FF39000L,  /* ECFIR/ECIIR */

+   0x02C17180L,0x1FBE2500L,0x00DFFE80L,0x00441A80L,

+   0x003BF800L,0x1FC42400L,0x0D9EB380L,0x1A514580L},  

+  {0x003ED200L,0x1F5D6B80L,0x0063B100L,0x0F12E200L, /* ZSYNTH */

+   0x18EC9380L,0x8B},  

+  0x08000000L, /* TXACGAIN */

+  0x0127C700L, /* RXACGAIN */

+   0x07B51200L,0x184AEE80L,0x076A2480L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_220_820_120_30_0.txt - ZSYN_220_820_120 */

+  {0x06E38480L,0x1FD33B00L,0x00069780L,0x1FFCAB80L, /* TXACEQ */

+   0x0A78F680L,0x1BC5C880L,0x009AEA00L,0x1FD66D80L}, /* RXACEQ */

+  {0x00378B00L,0x1F3FCA00L,0x02B5ED00L,0x1F2B6200L,  /* ECFIR/ECIIR */

+   0x04189080L,0x1F8A4480L,0x01113680L,0x00373100L,

+   0x001DAE80L,0x1FE02F00L,0x0C89C780L,0x1B689680L},  

+  {0x02391100L,0x1A886080L,0x033E3B00L,0x0A136200L, /* ZSYNTH */

+   0x1DEA4180L,0x8C},  

+  0x08000000L, /* TXACGAIN */

+  0x01019200L, /* RXACGAIN */

+   0x07BD1680L,0x1842EA00L,0x077A2D00L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_600_0_1000_30_0.txt - ZSYN_600_0_1000 */

+  {0x07F83980L,0x00056200L,0x1FFEE880L,0x1FFB1900L, /* TXACEQ */

+   0x08405000L,0x001DD200L,0x0003DB80L,0x00008700L}, /* RXACEQ */

+  {0x1FEE8700L,0x009B2B00L,0x000C9680L,0x03700100L,  /* ECFIR/ECIIR */

+   0x1F62E400L,0x01C77400L,0x1FBBCF80L,0x0089D500L,

+   0x005CFF80L,0x1FA96E80L,0x0F679480L,0x18962A80L},  

+  {0x00657C00L,0x1F2FA580L,0x006ADE00L,0x0FE12100L, /* ZSYNTH */

+   0x181ED080L,0x57},  

+  0x08618D80L, /* TXACGAIN */

+  0x013E3400L, /* RXACGAIN */

+   0x0717CE80L,0x18E83200L,0x062F9C80L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_200_680_100_30_0.txt - ZSYN_200_680_100 */

+  {0x073A7B00L,0x1FCEB400L,0x0002C680L,0x1FFD0780L, /* TXACEQ */

+   0x09BA8580L,0x1D2DF780L,0x006F5000L,0x1FDFE200L}, /* RXACEQ */

+  {0x0004B700L,0x000F9800L,0x01201200L,0x00E1D880L,  /* ECFIR/ECIIR */

+   0x03314A00L,0x1E84A580L,0x029D2380L,0x1E6F3400L,

+   0x00E99200L,0x1F121100L,0x0588BC00L,0x025CAE00L},  

+  {0x01415C00L,0x1C98C180L,0x0225A500L,0x0A138200L, /* ZSYNTH */

+   0x1DEA2280L,0x8E},  

+  0x08000000L, /* TXACGAIN */

+  0x010DFD80L, /* RXACGAIN */

+   0x07BA2180L,0x1845DF00L,0x07744380L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_220_820_115_30_0.txt - ZSYN_200_820_115 */

+  {0x06D56380L,0x1FDF1900L,0x00095A00L,0x1FFDAA80L, /* TXACEQ */

+   0x0A596300L,0x1C067880L,0x0095EF00L,0x1FD7AF00L}, /* RXACEQ */

+  {0x00687000L,0x1EAE1800L,0x03983D80L,0x1EB14B00L,  /* ECFIR/ECIIR */

+   0x037B3E80L,0x016FC900L,0x1ED60100L,0x01B17D80L,

+   0x1FA20D00L,0x001CE900L,0x027D3380L,0x1DBDBA80L},  

+  {0x00246300L,0x1E5E0580L,0x017D2300L,0x0A138100L, /* ZSYNTH */

+   0x1DEA2280L,0xA7},  

+  0x08000000L, /* TXACGAIN */

+  0x01009500L, /* RXACGAIN */

+   0x07BBEE80L,0x18441200L,0x0777DD80L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+}

+};

+

+Si3226_FSK_Cfg Si3226_FSK_Presets[] ={

+

+    /* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+    { 0x2232000L, 0x77C2000L, 0x3C0000L, 0x200000L, 0x6B60000L, 0x79C0000L,0, 0 }

+};

+

+Si3226_Tone_Cfg Si3226_Tone_Presets[] ={

+

+    /* inputs:  freq1 = 350.000, amp1 = -18.000, freq2 = 440.000, amp2 = -18.000, ta1 = 0.000, ti1 = 0.000, ta2 = 0.000, ti2 = 0.000*/

+    { {0x7B30000L, 0x3A000L, 0x0L, 0x0, 0x0, 0x0, 0x0}, {0x7870000L, 0x4A000L, 0x0L, 0x0, 0x0, 0x0, 0x0}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.500, ti1 = 0.500, ta2 = 0.500, ti2 = 0.500*/

+    { {0x7700000L, 0x52000L, 0x0L, 0xA0, 0xF, 0xA0, 0xF}, {0x7120000L, 0x6A000L, 0x0L, 0xA0, 0xF, 0xA0, 0xF}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 440.000, amp2 = -18.000, ta1 = 2.000, ti1 = 4.000, ta2 = 2.000, ti2 = 4.000*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x80, 0x3E, 0x0, 0x7D}, {0x7870000L, 0x4A000L, 0x0L, 0x80, 0x3E, 0x0, 0x7D}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.300, ti1 = 0.200, ta2 = 0.300, ti2 = 0.200*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x60, 0x9, 0x40, 0x6}, {0x7120000L, 0x6A000L, 0x0L, 0x60, 0x9, 0x40, 0x6}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.200, ti1 = 0.200, ta2 = 0.200, ti2 = 0.200*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x40, 0x6, 0x40, 0x6}, {0x7120000L, 0x6A000L, 0x0L, 0x40, 0x6, 0x40, 0x6}, 0x66 }

+};

+

+Si3226_PCM_Cfg Si3226_PCM_Presets[] ={

+

+    /* inputs:  u-law narrowband positive edge, dtx positive edge, both disabled, tx hwy = A, rx hwy = A */

+    { 0x1, 0x0, 0x0, 0x0, 0x0 }

+};

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_constants.c
new file mode 100755
index 0000000..39cccc1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_constants.c
@@ -0,0 +1,357 @@
+/*

+Copyright (c) 2008 Silicon Laboratories, Inc.

+2008-03-18 16:06:28 */

+

+#include "proslic.h"

+#include "si3226.h"

+Si3226_General_Cfg Si3226_General_Configuration  = {

+BO_DCDC_QCUK,	

+0x8720000L,	/* VBATR_EXPECT */

+0x3D70000L,	/* VBATH_EXPECT */

+0x0L,	    /* DCDC_FSW_VTHLO */

+0x0L,	    /* DCDC_FSW_VHYST */

+0x1300000L,	/* DCDC_VREF_MIN */

+0x5A00000L,	/* DCDC_VREF_MIN_RING */

+0x200000L,	/* DCDC_FSW_NORM */

+0x200000L,	/* DCDC_FSW_NORM_LO */

+0x200000L,	/* DCDC_FSW_RING */

+0x100000L,	/* DCDC_FSW_RING_LO */

+0xD980000L,	/* DCDC_DIN_LIM */

+0xC00000L,	/* DCDC_VOUT_LIM */

+0x0L,	    /* DCDC_DCFF_ENABLE */

+0x500000L,	/* DCDC_UVHYST */

+0x600000L,	/* DCDC_UVTHRESH */

+0xB00000L,	/* DCDC_OVTHRESH */

+0x1F00000L,	/* DCDC_OITHRESH */

+0x100000L,	/* DCDC_SWDRV_POL */

+0x300000L,	/* DCDC_SWFET */

+0x600000L,	/* DCDC_VREF_CTRL */

+0x200000L,	/* DCDC_RNGTYPE */

+0x0L,	    /* DCDC_ANA_GAIN */

+0x0L,	    /* DCDC_ANA_TOFF */

+0x0L,	    /* DCDC_ANA_TONMIN */

+0x0L,	    /* DCDC_ANA_TONMAX */

+0x0L,	    /* DCDC_ANA_DSHIFT */

+0x0L,	    /* DCDC_ANA_LPOLY */

+0x7FeF000L,	/* COEF_P_HVIC */

+0x68D000L,	/* P_TH_HVIC */

+0x0,	    /* CM_CLAMP */

+0x3F,	    /* AUTO */

+0x0,	    /* DAA_CNTL */

+0x7F,	    /* IRQEN1 */

+0xFF,	    /* IRQEN2 */

+0xFF,	    /* IRQEN3 */

+0xFF,	    /* IRQEN4 */

+0x0,	    /* ENHANCE */

+0,	        /* DAA_ENABLE */

+0x8000000L,	/* SCALE_KAUDIO */

+0x151EB80L,	/* AC_ADC_GAIN */

+};

+

+Si3226_DTMFDec_Cfg Si3226_DTMFDec_Presets[] = {

+	{0x2d40000L,0x1a660000L,0x2d40000L,0x6ba0000L,0x1dcc0000L,0x33f0000L,0xbd30000L,0x19d20000L,0x4150000L,0x188F0000L,0x4150000L,0xd970000L,0x18620000L,0xf1c0000L}

+};

+Si3226_GPIO_Cfg Si3226_GPIO_Configuration = {

+	0,0,0,0,0,0,0

+};

+

+Si3226_CI_Cfg Si3226_CI_Presets [] = {

+	{0}

+};

+Si3226_audioGain_Cfg Si3226_audioGain_Presets [] = {

+	{0x1377080L,0,0L,0L,0L,0L},

+	{0x80C3180L,0,0L,0L,0L,0L}

+};

+

+Si3226_Ring_Cfg Si3226_Ring_Presets[] ={

+{ /* RING_F20_45VRMS_0VDC_LPR */

+0x00050000L,		/* RTPER */

+0x07EFD9D5L,		/* RINGFR */

+0x001BD493L,		/* RINGAMP */

+0x00000000L,		/* RINGPHAS */

+0x00000000L,		/* RINGOF */

+0x15E5200EL,		/* SLOPE_RING */

+0x00D16348L,		/* IRING_LIM */

+0x0068C6BBL,		/* RTACTH */

+0x0FFFFFFFL,		/* RTDCTH */

+0x00006000L,		/* RTACDB */

+0x00006000L,		/* RTDCDB */

+0x0064874DL,		/* VOV_RING_BAT */

+0x0064874DL,		/* VOV_RING_GND */

+0x049CE106L,		/* VBATR_EXPECT */

+0x80,		/* RINGTALO */

+0x3E,		/* RINGTAHI */

+0x00,		/* RINGTILO */

+0x7D,		/* RINGTIHI */

+0x01000547L,		/* ADAP_RING_MIN_I */

+0x00003000L,		/* COUNTER_IRING_VAL */

+0x00051EB8L,		/* COUNTER_VTR_VAL */

+0x0163063FL,		/* CONST_028 */

+0x019E31F4L,		/* CONST_032 */

+0x01F108BEL,		/* CONST_036 */

+0x026D4AEEL,		/* CONST_046 */

+0x00370000L,		/* RRD_DELAY */

+0x00190000L,		/* RRD_DELAY2 */

+0x01893740L,		/* DCDC_VREF_MIN_RNG */

+0x58,		/* RINGCON */

+0x01,		/* USERSTAT */

+0x024E7083L,		/* VCM_RING */

+0x024E7083L,		/* VCM_RING_FIXED */

+0x003126E8L,		/* DELTA_VCM */

+0x200000L,		/* DCDC_RNGTYPE */

+},

+{ /* RING_F20_45VRMS_0VDC_BAL */

+0x00050000L,		/* RTPER */

+0x07EFD9D5L,		/* RINGFR */

+0x001BD493L,		/* RINGAMP */

+0x00000000L,		/* RINGPHAS */

+0x00000000L,		/* RINGOF */

+0x15E5200EL,		/* SLOPE_RING */

+0x00D16348L,		/* IRING_LIM */

+0x0068C6BBL,		/* RTACTH */

+0x0FFFFFFFL,		/* RTDCTH */

+0x00006000L,		/* RTACDB */

+0x00006000L,		/* RTDCDB */

+0x0064874DL,		/* VOV_RING_BAT */

+0x0064874DL,		/* VOV_RING_GND */

+0x0565EFA2L,		/* VBATR_EXPECT */

+0x80,		/* RINGTALO */

+0x3E,		/* RINGTAHI */

+0x00,		/* RINGTILO */

+0x7D,		/* RINGTIHI */

+0x01000547L,		/* ADAP_RING_MIN_I */

+0x00003000L,		/* COUNTER_IRING_VAL */

+0x00051EB8L,		/* COUNTER_VTR_VAL */

+0x0163063FL,		/* CONST_028 */

+0x019E31F4L,		/* CONST_032 */

+0x01F108BEL,		/* CONST_036 */

+0x026D4AEEL,		/* CONST_046 */

+0x00370000L,		/* RRD_DELAY */

+0x00190000L,		/* RRD_DELAY2 */

+0x01893740L,		/* DCDC_VREF_MIN_RNG */

+0x58,		/* RINGCON */

+0x00,		/* USERSTAT */

+0x02B2F7D1L,		/* VCM_RING */

+0x02B2F7D1L,		/* VCM_RING_FIXED */

+0x003126E8L,		/* DELTA_VCM */

+0x200000L,		/* DCDC_RNGTYPE */

+},

+{ /* RING_F20_55VRMS_48VDC_LPR */

+0x00050000L,		/* RTPER */

+0x07EFD9D5L,		/* RINGFR */

+0x002203D0L,		/* RINGAMP */

+0x00000000L,		/* RINGPHAS */

+0x049A5F69L,		/* RINGOF */

+0x15E5200EL,		/* SLOPE_RING */

+0x00D16348L,		/* IRING_LIM */

+0x032EDF91L,		/* RTACTH */

+0x0038E38EL,		/* RTDCTH */

+0x00006000L,		/* RTACDB */

+0x00006000L,		/* RTDCDB */

+0x007ADE42L,		/* VOV_RING_BAT */

+0x007ADE42L,		/* VOV_RING_GND */

+0x08B5BA6CL,		/* VBATR_EXPECT */

+0x80,		/* RINGTALO */

+0x3E,		/* RINGTAHI */

+0x00,		/* RINGTILO */

+0x7D,		/* RINGTIHI */

+0x0138EA01L,		/* ADAP_RING_MIN_I */

+0x00003000L,		/* COUNTER_IRING_VAL */

+0x00051EB8L,		/* COUNTER_VTR_VAL */

+0x01A40BA6L,		/* CONST_028 */

+0x01EA0D97L,		/* CONST_032 */

+0x024C104FL,		/* CONST_036 */

+0x02DF1463L,		/* CONST_046 */

+0x00370000L,		/* RRD_DELAY */

+0x00190000L,		/* RRD_DELAY2 */

+0x01893740L,		/* DCDC_VREF_MIN_RNG */

+0x58,		/* RINGCON */

+0x01,		/* USERSTAT */

+0x045ADD36L,		/* VCM_RING */

+0x045ADD36L,		/* VCM_FIXED_RING */

+0x003126E8L,		/* DELTA_VCM */

+0x200000L,		/* DCDC_RNGTYPE */

+}

+};

+

+Si3226_DCfeed_Cfg Si3226_DCfeed_Presets[] = {

+

+    /* inputs: v_vlim=48.000, i_vlim=0.000, v_rfeed=42.800, i_rfeed=10.000,v_ilim=33.200, i_ilim=20.000,

+ vcm_oh=27.000, vov_gnd=4.000, vov_bat=4.000, r_ring=320.000

+ lcronhk=10.000, lcroffhk=12.000, lcrdbi=5.000, longhith=8.000, longloth=7.000, longdbi=5.000

+ lcrmask=80.000, lcrmask_polrev=80.000, lcrmask_state=200.000, lcrmask_linecap=200.000 */

+{ /* DCFEED_48V_20MA */

+0x1DDF41C9L,    /* SLOPE_VLIM */

+0x1EF68D5EL,    /* SLOPE_RFEED */

+0x40A0E0L,      /* SLOPE_ILIM */

+0x18AAD168L,    /* SLOPE_DELTA1 */

+0x1CA39FFAL,    /* SLOPE_DELTA2 */

+0x5A38633L,     /* V_VLIM */

+0x5072476L,     /* V_RFEED */

+0x3E67006L,     /* V_ILIM */

+0xFDFAB5L,      /* CONST_RFEED */

+0x5D0FA6L,      /* CONST_ILIM */

+0x2D8D96L,      /* I_VLIM */

+0x5B0AFBL,      /* LCRONHK */

+0x6D4060L,      /* LCROFFHK */

+0x8000L,        /* LCRDBI */

+0x48D595L,      /* LONGHITH */

+0x3FBAE2L,      /* LONGLOTH */

+0x8000L,        /* LONGDBI */

+0x120000L,       /* LCRMASK */

+0x80000L,       /* LCRMASK_POLREV */

+0x140000L,      /* LCRMASK_STATE */

+0x140000L,      /* LCRMASK_LINECAP */

+0x1BA5E35L,     /* VCM_OH */

+0x418937L,      /* VOV_BAT */

+0x418937L       /* VOV_GND */

+},

+{ /* DCFEED_48V_25MA */

+0x1D46EA04L,    /* SLOPE_VLIM */

+0x1EA4087EL,    /* SLOPE_RFEED */

+0x40A0E0L,      /* SLOPE_ILIM */

+0x1A224120L,    /* SLOPE_DELTA1 */

+0x1D4FB32EL,    /* SLOPE_DELTA2 */

+0x5A38633L,     /* V_VLIM */ 

+0x5072476L,     /* V_RFEED */ 

+0x3E67006L,     /* V_ILIM */ 

+0x13D7962L,     /* CONST_RFEED */ 

+0x74538FL,      /* CONST_ILIM */ 

+0x2D8D96L,      /* I_VLIM */ 

+0x5B0AFBL,      /* LCRONHK */

+0x6D4060L,      /* LCROFFHK */

+0x8000L,        /* LCRDBI */

+0x48D595L,      /* LONGHITH */

+0x3FBAE2L,      /* LONGLOTH */

+0x8000L,        /* LONGDBI */

+0x120000L,       /* LCRMASK */

+0x80000L,       /* LCRMASK_POLREV */

+0x140000L,      /* LCRMASK_STATE */

+0x140000L,      /* LCRMASK_LINECAP */

+0x1BA5E35L,     /* VCM_OH */

+0x418937L,      /* VOV_BAT */

+0x418937L       /* VOV_GND */

+}

+};

+

+Si3226_Impedance_Cfg Si3226_Impedance_Presets[] ={

+{  /* Si3226_600_0_0_30_0.txt - ZSYN_600_0_0 */

+{0x08066500L, 0x1FF6FC80L, 0x00050B00L, 0x1FFE2680L,    /* TXACEQ */

+ 0x0800D000L, 0x1FF6C700L, 0x00025700L, 0x1FFB2300L},   /* RXACEQ */

+{0x00151F00L, 0x1FE4D400L, 0x01E78880L, 0x00573380L,    /* ECFIR/ECIIR */

+ 0x020AF880L, 0x1EF79A80L, 0x00B35800L, 0x1F955080L,

+ 0x003E6600L, 0x1FBC7880L, 0x01E9AA00L, 0x05F27E00L},

+{0x025AFA00L, 0x1C1FAD80L, 0x0185EC00L, 0x0A195E00L,    /* ZSYNTH */

+ 0x1DE3B180L, 0x31}, 

+ 0x08775F80L,   /* TXACGAIN */

+ 0x01450700L,   /* RXACGAIN */

+ 0x07B41580L, 0x184BEB00L, 0x07682B80L,    /* RXACHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_270_750_150_30_0.txt - ZSYN_270_750_150*/

+  {0x071F7A80L,0x1FD01280L,0x00132700L,0x1FFEF980L, /* TXACEQ */

+   0x0A8AA300L,0x1B9A5500L,0x008E7F00L,0x1FD7F300L}, /* RXACEQ */

+  {0x0068CA00L,0x1EAE1E00L,0x0394FA00L,0x1E94AE80L,  /* ECFIR/ECIIR */

+   0x0356D800L,0x0166CA80L,0x1EC16380L,0x01DE2780L,

+   0x1F852300L,0x0046BE80L,0x02F17C80L,0x1EBCD280L},  

+  {0x028A0C00L,0x19EE4580L,0x03876100L,0x0A762700L, /* ZSYNTH */

+   0x1D87A380L,0x93},  

+  0x08000000L, /* TXACGAIN */

+  0x0109C280L, /* RXACGAIN */

+   0x07BC6F00L,0x18439180L,0x0778DE00L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_370_620_310_30_0.txt - ZSYN_370_620_310 */

+  {0x07E59E80L,0x1FD33400L,0x1FFDF800L,0x1FFD8300L, /* TXACEQ */

+   0x09F38000L,0x1C1C5A00L,0x1F94D700L,0x1FDE5800L}, /* RXACEQ */

+  {0x00234480L,0x1F9CDD00L,0x01F5D580L,0x1FF39000L,  /* ECFIR/ECIIR */

+   0x02C17180L,0x1FBE2500L,0x00DFFE80L,0x00441A80L,

+   0x003BF800L,0x1FC42400L,0x0D9EB380L,0x1A514580L},  

+  {0x003ED200L,0x1F5D6B80L,0x0063B100L,0x0F12E200L, /* ZSYNTH */

+   0x18EC9380L,0x8B},  

+  0x08000000L, /* TXACGAIN */

+  0x0127C700L, /* RXACGAIN */

+   0x07B51200L,0x184AEE80L,0x076A2480L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_220_820_120_30_0.txt - ZSYN_220_820_120 */

+  {0x06E38480L,0x1FD33B00L,0x00069780L,0x1FFCAB80L, /* TXACEQ */

+   0x0A78F680L,0x1BC5C880L,0x009AEA00L,0x1FD66D80L}, /* RXACEQ */

+  {0x00378B00L,0x1F3FCA00L,0x02B5ED00L,0x1F2B6200L,  /* ECFIR/ECIIR */

+   0x04189080L,0x1F8A4480L,0x01113680L,0x00373100L,

+   0x001DAE80L,0x1FE02F00L,0x0C89C780L,0x1B689680L},  

+  {0x02391100L,0x1A886080L,0x033E3B00L,0x0A136200L, /* ZSYNTH */

+   0x1DEA4180L,0x8C},  

+  0x08000000L, /* TXACGAIN */

+  0x01019200L, /* RXACGAIN */

+   0x07BD1680L,0x1842EA00L,0x077A2D00L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_600_0_1000_30_0.txt - ZSYN_600_0_1000 */

+  {0x07F83980L,0x00056200L,0x1FFEE880L,0x1FFB1900L, /* TXACEQ */

+   0x08405000L,0x001DD200L,0x0003DB80L,0x00008700L}, /* RXACEQ */

+  {0x1FEE8700L,0x009B2B00L,0x000C9680L,0x03700100L,  /* ECFIR/ECIIR */

+   0x1F62E400L,0x01C77400L,0x1FBBCF80L,0x0089D500L,

+   0x005CFF80L,0x1FA96E80L,0x0F679480L,0x18962A80L},  

+  {0x00657C00L,0x1F2FA580L,0x006ADE00L,0x0FE12100L, /* ZSYNTH */

+   0x181ED080L,0x57},  

+  0x08618D80L, /* TXACGAIN */

+  0x013E3400L, /* RXACGAIN */

+   0x0717CE80L,0x18E83200L,0x062F9C80L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_200_680_100_30_0.txt - ZSYN_200_680_100 */

+  {0x073A7B00L,0x1FCEB400L,0x0002C680L,0x1FFD0780L, /* TXACEQ */

+   0x09BA8580L,0x1D2DF780L,0x006F5000L,0x1FDFE200L}, /* RXACEQ */

+  {0x0004B700L,0x000F9800L,0x01201200L,0x00E1D880L,  /* ECFIR/ECIIR */

+   0x03314A00L,0x1E84A580L,0x029D2380L,0x1E6F3400L,

+   0x00E99200L,0x1F121100L,0x0588BC00L,0x025CAE00L},  

+  {0x01415C00L,0x1C98C180L,0x0225A500L,0x0A138200L, /* ZSYNTH */

+   0x1DEA2280L,0x8E},  

+  0x08000000L, /* TXACGAIN */

+  0x010DFD80L, /* RXACGAIN */

+   0x07BA2180L,0x1845DF00L,0x07744380L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+},

+{  /* Si3226_220_820_115_30_0.txt - ZSYN_200_820_115 */

+  {0x06D56380L,0x1FDF1900L,0x00095A00L,0x1FFDAA80L, /* TXACEQ */

+   0x0A596300L,0x1C067880L,0x0095EF00L,0x1FD7AF00L}, /* RXACEQ */

+  {0x00687000L,0x1EAE1800L,0x03983D80L,0x1EB14B00L,  /* ECFIR/ECIIR */

+   0x037B3E80L,0x016FC900L,0x1ED60100L,0x01B17D80L,

+   0x1FA20D00L,0x001CE900L,0x027D3380L,0x1DBDBA80L},  

+  {0x00246300L,0x1E5E0580L,0x017D2300L,0x0A138100L, /* ZSYNTH */

+   0x1DEA2280L,0xA7},  

+  0x08000000L, /* TXACGAIN */

+  0x01009500L, /* RXACGAIN */

+   0x07BBEE80L,0x18441200L,0x0777DD80L,  /* RXHPF */

+  0, 0 /* 0dB TX, 0dB RX */

+}

+};

+

+Si3226_FSK_Cfg Si3226_FSK_Presets[] ={

+

+    /* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+    { 0x2232000L, 0x77C2000L, 0x3C0000L, 0x200000L, 0x6B60000L, 0x79C0000L,0, 0 }

+};

+

+Si3226_Tone_Cfg Si3226_Tone_Presets[] ={

+

+    /* inputs:  freq1 = 350.000, amp1 = -18.000, freq2 = 440.000, amp2 = -18.000, ta1 = 0.000, ti1 = 0.000, ta2 = 0.000, ti2 = 0.000*/

+    { {0x7B30000L, 0x3A000L, 0x0L, 0x0, 0x0, 0x0, 0x0}, {0x7870000L, 0x4A000L, 0x0L, 0x0, 0x0, 0x0, 0x0}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.500, ti1 = 0.500, ta2 = 0.500, ti2 = 0.500*/

+    { {0x7700000L, 0x52000L, 0x0L, 0xA0, 0xF, 0xA0, 0xF}, {0x7120000L, 0x6A000L, 0x0L, 0xA0, 0xF, 0xA0, 0xF}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 440.000, amp2 = -18.000, ta1 = 2.000, ti1 = 4.000, ta2 = 2.000, ti2 = 4.000*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x80, 0x3E, 0x0, 0x7D}, {0x7870000L, 0x4A000L, 0x0L, 0x80, 0x3E, 0x0, 0x7D}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.300, ti1 = 0.200, ta2 = 0.300, ti2 = 0.200*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x60, 0x9, 0x40, 0x6}, {0x7120000L, 0x6A000L, 0x0L, 0x60, 0x9, 0x40, 0x6}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.200, ti1 = 0.200, ta2 = 0.200, ti2 = 0.200*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x40, 0x6, 0x40, 0x6}, {0x7120000L, 0x6A000L, 0x0L, 0x40, 0x6, 0x40, 0x6}, 0x66 }

+};

+

+Si3226_PCM_Cfg Si3226_PCM_Presets[] ={

+

+    /* inputs:  u-law narrowband positive edge, dtx positive edge, both disabled, tx hwy = A, rx hwy = A */

+    { 0x1, 0x0, 0x0, 0x0, 0x0 }

+};

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_constants.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_constants.h
new file mode 100755
index 0000000..6d46990
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_constants.h
@@ -0,0 +1,50 @@
+/*

+Copyright (c) 2008 Silicon Laboratories, Inc.

+2008-03-12 17:24:23 */

+

+enum {

+    RING_F20_45VRMS_0VDC_LPR,

+    RING_F20_45VRMS_0VDC_BAL,

+    RING_F20_55VRMS_48VDC_LPR,

+    RING_F25_45VRMS_0VDC_LPR,

+    RING_F25_45VRMS_0VDC_BAL,

+    RING_F25_55VRMS_48VDC_LPR

+};

+

+enum {

+    DCFEED_48V_20MA,

+    DCFEED_48V_25MA

+};

+

+enum {

+    ZSYN_600_0_0,

+    ZSYN_270_750_150,

+    ZSYN_370_620_310,

+    ZSYN_220_820_120,

+    ZSYN_600_0_1000,

+    ZSYN_200_680_100,

+    ZSYN_220_820_115

+};

+

+enum {

+	FSK_DEFAULT_CONFIG

+};

+

+enum {

+	TONEGEN_FCC_DIAL,

+	TONEGEN_FCC_BUSY,

+	TONEGEN_FCC_RINGBACK,

+	TONEGEN_FCC_REORDER,

+	TONEGEN_FCC_CONGESTION

+};

+

+enum {

+	PCM_DEFAULT_CONFIG

+};

+

+enum {

+   GEN_PARAM_FLYBACK,

+   GEN_PARAM_QCUK

+};

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_C_FLBK_2010AUG10.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_C_FLBK_2010AUG10.c
new file mode 100755
index 0000000..5f5d009
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_C_FLBK_2010AUG10.c
@@ -0,0 +1,920 @@
+// Generated from si3226_patch_D_FB_2008NOV20.dsp_prom
+// on 03-20-2009 at 15:24:7
+//
+#include "si_voice_datatypes.h"
+#include "si3226.h"
+
+static const uInt32 patchData [] = {
+141541L,
+532675L,
+141541L,
+535235L,
+141541L,
+536259L,
+141541L,
+613059L,
+141541L,
+617667L,
+141541L,
+956099L,
+141541L,
+957123L,
+141541L,
+961219L,
+736L,
+513728L,
+452200L,
+141541L,
+513216L,
+141541L,
+842432L,
+143589L,
+553667L,
+474213L,
+468066L,
+516165L,
+800867L,
+515653L,
+514053L,
+473700L,
+144608L,
+553155L,
+799330L,
+119428L,
+142048L,
+553155L,
+515141L,
+514661L,
+262242L,
+143077L,
+550595L,
+517218L,
+524291L,
+517125L,
+142053L,
+553667L,
+787781L,
+141541L,
+553667L,
+516709L,
+514882L,
+517125L,
+141541L,
+553667L,
+514565L,
+250469L,
+3170L,
+251811L,
+144101L,
+556739L,
+111237L,
+250981L,
+472675L,
+144096L,
+559299L,
+524289L,
+251397L,
+143077L,
+561347L,
+473189L,
+17637L,
+564419L,
+471653L,
+143077L,
+564419L,
+472165L,
+794693L,
+5733L,
+183952L,
+237724L,
+147196L,
+573635L,
+145637L,
+575171L,
+238213L,
+660065L,
+524291L,
+524294L,
+524294L,
+230534L,
+660069L,
+524296L,
+141541L,
+576195L,
+524288L,
+141541L,
+576195L,
+231045L,
+524289L,
+783365L,
+541925L,
+593091L,
+522853L,
+801349L,
+522341L,
+792645L,
+520293L,
+524290L,
+667365L,
+586435L,
+520805L,
+471621L,
+472133L,
+472645L,
+473157L,
+262245L,
+520261L,
+141541L,
+599235L,
+5221L,
+461424L,
+521828L,
+144613L,
+599235L,
+471621L,
+472133L,
+472645L,
+473157L,
+118405L,
+790853L,
+141541L,
+599235L,
+523877L,
+801349L,
+523365L,
+792645L,
+521317L,
+471621L,
+472133L,
+472645L,
+473152L,
+520197L,
+118917L,
+790853L,
+619749L,
+607939L,
+25829L,
+602819L,
+469605L,
+141538L,
+606915L,
+246373L,
+262242L,
+144099L,
+606915L,
+246277L,
+785925L,
+141541L,
+607939L,
+246277L,
+786437L,
+776293L,
+24293L,
+611011L,
+98434L,
+141557L,
+888513L,
+119426L,
+524310L,
+141541L,
+888513L,
+330917L,
+660069L,
+474728L,
+404579L,
+78565L,
+616643L,
+660069L,
+141541L,
+654016L,
+24800L,
+620739L,
+5221L,
+69L,
+141541L,
+625347L,
+122373L,
+123397L,
+122885L,
+123909L,
+121861L,
+124933L,
+124421L,
+141541L,
+668867L,
+658661L,
+634563L,
+119429L,
+122469L,
+98L,
+122986L,
+122370L,
+101L,
+524298L,
+122896L,
+660069L,
+123496L,
+126469L,
+126563L,
+123394L,
+124005L,
+524291L,
+123909L,
+659173L,
+668867L,
+262240L,
+121956L,
+386659L,
+121860L,
+143077L,
+649923L,
+224384L,
+121964L,
+524291L,
+143077L,
+642243L,
+141541L,
+668867L,
+431717L,
+122466L,
+142562L,
+644803L,
+524305L,
+433765L,
+123492L,
+125957L,
+434274L,
+524292L,
+125440L,
+122373L,
+123397L,
+141541L,
+657091L,
+431717L,
+122978L,
+142562L,
+652483L,
+524305L,
+433765L,
+124004L,
+125957L,
+434274L,
+524292L,
+125440L,
+122885L,
+123909L,
+121861L,
+125541L,
+262242L,
+666848L,
+660163L,
+124516L,
+435299L,
+124421L,
+435301L,
+126052L,
+144613L,
+663235L,
+680965L,
+262242L,
+666848L,
+665795L,
+125028L,
+434787L,
+124933L,
+434789L,
+524292L,
+144613L,
+668867L,
+680965L,
+536800L,
+672963L,
+114789L,
+262242L,
+435812L,
+114692L,
+144608L,
+673475L,
+114693L,
+1125L,
+610L,
+524292L,
+256005L,
+539237L,
+240258L,
+402037L,
+143588L,
+688835L,
+25829L,
+687299L,
+201312L,
+201218L,
+143077L,
+1030338L,
+547941L,
+224386L,
+143072L,
+1030338L,
+694789L,
+537605L,
+538437L,
+538629L,
+694785L,
+721925L,
+141541L,
+791235L,
+201285L,
+141541L,
+1030338L,
+143076L,
+711875L,
+524292L,
+524292L,
+143076L,
+192706L,
+143076L,
+242882L,
+143076L,
+751299L,
+143076L,
+324802L,
+143076L,
+508098L,
+143076L,
+324802L,
+143076L,
+508098L,
+143076L,
+324802L,
+143076L,
+508098L,
+143076L,
+324802L,
+143076L,
+508098L,
+143076L,
+791235L,
+143076L,
+809667L,
+143076L,
+830146L,
+143076L,
+830146L,
+143076L,
+830146L,
+143072L,
+830146L,
+721925L,
+694789L,
+538629L,
+538117L,
+694789L,
+141541L,
+1030338L,
+658149L,
+1030338L,
+216165L,
+402018L,
+143076L,
+724163L,
+143076L,
+124098L,
+143076L,
+127682L,
+143076L,
+138946L,
+143076L,
+1028290L,
+143076L,
+164034L,
+143076L,
+726211L,
+143076L,
+170690L,
+143076L,
+730819L,
+141541L,
+734403L,
+739941L,
+194117L,
+141541L,
+100034L,
+720485L,
+248418L,
+241795L,
+694791L,
+248321L,
+561157L,
+694789L,
+141541L,
+1028290L,
+720485L,
+247906L,
+524291L,
+694791L,
+247808L,
+561157L,
+694789L,
+194661L,
+330816L,
+119429L,
+787781L,
+790021L,
+787973L,
+788485L,
+725509L,
+726021L,
+724997L,
+728581L,
+730629L,
+729093L,
+726533L,
+724485L,
+723973L,
+776709L,
+195173L,
+694789L,
+541253L,
+694789L,
+228965L,
+446533L,
+722437L,
+732165L,
+742917L,
+723461L,
+194149L,
+739909L,
+216069L,
+756741L,
+141541L,
+1030338L,
+658149L,
+1030338L,
+216165L,
+402018L,
+143076L,
+763587L,
+143076L,
+1028290L,
+143076L,
+772291L,
+143076L,
+1028290L,
+143076L,
+775363L,
+143076L,
+1028290L,
+143076L,
+772291L,
+143076L,
+1028290L,
+143076L,
+780995L,
+141536L,
+745155L,
+577765L,
+789187L,
+212101L,
+694785L,
+561157L,
+694789L,
+118917L,
+779077L,
+243845L,
+118401L,
+740881L,
+741893L,
+743237L,
+739941L,
+194117L,
+141541L,
+116418L,
+718949L,
+195141L,
+720485L,
+194629L,
+141541L,
+1028290L,
+720485L,
+194658L,
+524291L,
+195175L,
+249349L,
+718946L,
+118915L,
+743239L,
+398341L,
+141541L,
+1028290L,
+720485L,
+194658L,
+524291L,
+195175L,
+249861L,
+718946L,
+524291L,
+694791L,
+398848L,
+561157L,
+694789L,
+740869L,
+741893L,
+778757L,
+141541L,
+745155L,
+216069L,
+756741L,
+141541L,
+1030338L,
+216165L,
+402018L,
+143076L,
+798403L,
+143076L,
+211138L,
+143076L,
+802499L,
+143076L,
+211138L,
+143072L,
+806595L,
+141541L,
+732354L,
+99973L,
+773957L,
+403557L,
+194117L,
+416357L,
+192069L,
+141541L,
+661186L,
+152160L,
+403554L,
+416355L,
+403461L,
+192064L,
+773637L,
+141541L,
+1028290L,
+152165L,
+192064L,
+194149L,
+403525L,
+141541L,
+677570L,
+216165L,
+402018L,
+143076L,
+815811L,
+143076L,
+855235L,
+143076L,
+834755L,
+143072L,
+855235L,
+141541L,
+936131L,
+539749L,
+194629L,
+541285L,
+228933L,
+546917L,
+193605L,
+377957L,
+194117L,
+739941L,
+254021L,
+560741L,
+195141L,
+118917L,
+723781L,
+722757L,
+724805L,
+724293L,
+730949L,
+726853L,
+735557L,
+725317L,
+694784L,
+539653L,
+377858L,
+147094L,
+560641L,
+118405L,
+546838L,
+541189L,
+694784L,
+762885L,
+739141L,
+738629L,
+745797L,
+729413L,
+777029L,
+740165L,
+402016L,
+745986L,
+216165L,
+118403L,
+216066L,
+143077L,
+843459L,
+776005L,
+728389L,
+405093L,
+183938L,
+223047L,
+404485L,
+404069L,
+159877L,
+255041L,
+403973L,
+402021L,
+162946L,
+405095L,
+226306L,
+257095L,
+460389L,
+227330L,
+225864L,
+228421L,
+227845L,
+119429L,
+216161L,
+257124L,
+144101L,
+852675L,
+404549L,
+141541L,
+1030338L,
+159877L,
+524289L,
+403973L,
+141541L,
+1030338L,
+225893L,
+226402L,
+144100L,
+858819L,
+225797L,
+141541L,
+1030338L,
+757349L,
+257122L,
+142053L,
+862915L,
+227426L,
+253571L,
+141541L,
+863939L,
+227426L,
+253572L,
+257026L,
+119431L,
+227333L,
+216161L,
+257124L,
+142050L,
+872643L,
+118917L,
+54913L,
+660072L,
+524292L,
+524294L,
+524294L,
+524294L,
+403973L,
+141541L,
+873155L,
+404549L,
+227429L,
+253570L,
+405094L,
+228460L,
+144613L,
+881859L,
+227938L,
+216164L,
+225797L,
+119429L,
+228353L,
+524292L,
+142053L,
+1030338L,
+225861L,
+141541L,
+1030338L,
+746085L,
+257122L,
+667365L,
+887491L,
+192069L,
+719973L,
+218245L,
+192577L,
+745989L,
+141541L,
+843459L,
+257125L,
+218245L,
+192104L,
+140421L,
+660072L,
+524294L,
+257124L,
+256517L,
+192098L,
+524292L,
+524294L,
+254086L,
+524294L,
+524294L,
+524294L,
+524294L,
+660069L,
+254600L,
+660069L,
+524296L,
+255493L,
+119429L,
+216161L,
+255588L,
+142050L,
+907971L,
+113285L,
+524296L,
+182887L,
+447493L,
+222725L,
+445957L,
+196098L,
+143589L,
+912067L,
+694784L,
+547845L,
+694789L,
+141538L,
+912067L,
+330821L,
+256613L,
+474693L,
+719973L,
+253509L,
+192610L,
+255108L,
+196423L,
+143077L,
+932547L,
+195589L,
+640L,
+196933L,
+193029L,
+196197L,
+195682L,
+193124L,
+144613L,
+919747L,
+196098L,
+196709L,
+524291L,
+193029L,
+195685L,
+524290L,
+196711L,
+195586L,
+138343L,
+196612L,
+142565L,
+915139L,
+119429L,
+216161L,
+193124L,
+142053L,
+927939L,
+447557L,
+141541L,
+932547L,
+399941L,
+218245L,
+253541L,
+192616L,
+140421L,
+660072L,
+524294L,
+524292L,
+399365L,
+119429L,
+216161L,
+524292L,
+142053L,
+1028290L,
+255077L,
+404037L,
+756736L,
+745477L,
+745989L,
+216069L,
+722437L,
+724485L,
+723973L,
+730629L,
+726533L,
+735237L,
+724997L,
+729093L,
+723461L,
+728069L,
+775685L,
+694789L,
+194661L,
+539717L,
+228965L,
+541253L,
+195173L,
+560709L,
+193637L,
+546885L,
+194149L,
+377925L,
+694784L,
+254053L,
+739909L,
+738821L,
+738309L,
+182885L,
+776706L,
+143077L,
+1030338L,
+254528L,
+182789L,
+141541L,
+1030338L,
+141541L,
+988353L,
+549605L,
+74432L,
+191077L,
+4165L,
+191589L,
+4677L,
+141541L,
+117440L,
+513541L,
+86629L,
+524290L,
+513638L,
+660066L,
+141541L,
+224960L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+993,
+1643,
+3699,
+1270,
+4094,
+3963,
+144,
+437
+};
+
+static const uInt16 patchSupportAddr [] = {
+1023,
+1022,
+1021,
+1020,
+1019,
+1018,
+1017,
+1016,
+746,
+927,
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0x1F00000L,
+0xC00000L,
+0xA00000L,
+0x1F00000L,
+0x200000L,
+0x200000L,
+0x100000L,
+0x0L,
+0x8F00000L,
+0x1FFE0000L,
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3226PatchRevCFlbk = {
+#else
+	const proslicPatch RevCPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x08102010L,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_C_QCUK_2010AUG10.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_C_QCUK_2010AUG10.c
new file mode 100755
index 0000000..1dcd1a3
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_C_QCUK_2010AUG10.c
@@ -0,0 +1,921 @@
+/*
+** Generated from si3226_patch_C_QCUK_2008NOV20.dsp_prom
+** on 03-20-2009 at 15:18:26
+*/
+#include "si_voice_datatypes.h"
+#include "si3226.h"
+
+static const uInt32 patchData [] = {
+141541L,
+532675L,
+141541L,
+535235L,
+141541L,
+536259L,
+141541L,
+613059L,
+141541L,
+617667L,
+141541L,
+956099L,
+141541L,
+957123L,
+141541L,
+961219L,
+736L,
+513728L,
+452200L,
+141541L,
+513216L,
+141541L,
+842432L,
+143589L,
+553667L,
+474213L,
+468066L,
+516165L,
+800867L,
+515653L,
+514053L,
+473700L,
+144608L,
+553155L,
+799330L,
+119428L,
+142048L,
+553155L,
+515141L,
+514661L,
+262242L,
+143077L,
+550595L,
+517218L,
+524291L,
+517125L,
+142053L,
+553667L,
+787781L,
+141541L,
+553667L,
+516709L,
+514882L,
+517125L,
+141541L,
+553667L,
+514565L,
+250469L,
+3170L,
+251811L,
+144101L,
+556739L,
+111237L,
+250981L,
+472675L,
+144096L,
+559299L,
+524289L,
+251397L,
+143077L,
+561347L,
+473189L,
+17637L,
+564419L,
+471653L,
+143077L,
+564419L,
+472165L,
+794693L,
+5733L,
+183952L,
+237724L,
+147196L,
+573635L,
+145637L,
+575171L,
+238213L,
+660065L,
+524291L,
+524294L,
+524294L,
+230534L,
+660069L,
+524296L,
+141541L,
+576195L,
+524288L,
+141541L,
+576195L,
+231045L,
+524289L,
+783365L,
+541925L,
+593091L,
+522853L,
+801349L,
+522341L,
+792645L,
+520293L,
+524290L,
+667365L,
+586435L,
+520805L,
+471621L,
+472133L,
+472645L,
+473157L,
+262245L,
+520261L,
+141541L,
+599235L,
+5221L,
+461424L,
+521828L,
+144613L,
+599235L,
+471621L,
+472133L,
+472645L,
+473157L,
+118405L,
+790853L,
+141541L,
+599235L,
+523877L,
+801349L,
+523365L,
+792645L,
+521317L,
+471621L,
+472133L,
+472645L,
+473152L,
+520197L,
+118917L,
+790853L,
+619749L,
+607939L,
+25829L,
+602819L,
+469605L,
+141538L,
+606915L,
+246373L,
+262242L,
+144099L,
+606915L,
+246277L,
+785925L,
+141541L,
+607939L,
+246277L,
+786437L,
+776293L,
+24293L,
+611011L,
+98434L,
+141557L,
+888513L,
+119426L,
+524310L,
+141541L,
+888513L,
+330917L,
+660069L,
+474728L,
+404579L,
+78565L,
+616643L,
+660069L,
+141541L,
+654016L,
+24800L,
+620739L,
+5221L,
+69L,
+141541L,
+625347L,
+122373L,
+123397L,
+122885L,
+123909L,
+121861L,
+124933L,
+124421L,
+141541L,
+668867L,
+658661L,
+634563L,
+119429L,
+122469L,
+98L,
+122986L,
+122370L,
+101L,
+524298L,
+122896L,
+660069L,
+123496L,
+126469L,
+126563L,
+123394L,
+124005L,
+524291L,
+123909L,
+659173L,
+668867L,
+262240L,
+121956L,
+386659L,
+121860L,
+143077L,
+649923L,
+224384L,
+121964L,
+524291L,
+143077L,
+642243L,
+141541L,
+668867L,
+431717L,
+122466L,
+142562L,
+644803L,
+524305L,
+433765L,
+123492L,
+125957L,
+434274L,
+524292L,
+125440L,
+122373L,
+123397L,
+141541L,
+657091L,
+431717L,
+122978L,
+142562L,
+652483L,
+524305L,
+433765L,
+124004L,
+125957L,
+434274L,
+524292L,
+125440L,
+122885L,
+123909L,
+121861L,
+125541L,
+262242L,
+666848L,
+660163L,
+124516L,
+435299L,
+124421L,
+435301L,
+126052L,
+144613L,
+663235L,
+680965L,
+262242L,
+666848L,
+665795L,
+125028L,
+434787L,
+124933L,
+434789L,
+524292L,
+144613L,
+668867L,
+680965L,
+536800L,
+672963L,
+114789L,
+262242L,
+435812L,
+114692L,
+144608L,
+673475L,
+114693L,
+1125L,
+610L,
+524292L,
+256005L,
+539237L,
+240258L,
+402037L,
+143588L,
+688835L,
+25829L,
+687299L,
+201312L,
+201218L,
+143077L,
+1030338L,
+547941L,
+224386L,
+143072L,
+1030338L,
+694789L,
+537605L,
+538437L,
+538629L,
+694785L,
+721925L,
+141541L,
+791235L,
+201285L,
+141541L,
+1030338L,
+143076L,
+711875L,
+524292L,
+524292L,
+143076L,
+192706L,
+143076L,
+242882L,
+143076L,
+751299L,
+143076L,
+324802L,
+143076L,
+508098L,
+143076L,
+324802L,
+143076L,
+508098L,
+143076L,
+324802L,
+143076L,
+508098L,
+143076L,
+324802L,
+143076L,
+508098L,
+143076L,
+791235L,
+143076L,
+809667L,
+143076L,
+830146L,
+143076L,
+830146L,
+143076L,
+830146L,
+143072L,
+830146L,
+721925L,
+694789L,
+538629L,
+538117L,
+694789L,
+141541L,
+1030338L,
+658149L,
+1030338L,
+216165L,
+402018L,
+143076L,
+724163L,
+143076L,
+124098L,
+143076L,
+127682L,
+143076L,
+138946L,
+143076L,
+1028290L,
+143076L,
+164034L,
+143076L,
+726211L,
+143076L,
+170690L,
+143076L,
+730819L,
+141541L,
+734403L,
+739941L,
+194117L,
+141541L,
+100034L,
+720485L,
+248418L,
+241795L,
+694791L,
+248321L,
+561157L,
+694789L,
+141541L,
+1028290L,
+720485L,
+247906L,
+524291L,
+694791L,
+247808L,
+561157L,
+694789L,
+194661L,
+330816L,
+119429L,
+787781L,
+790021L,
+787973L,
+788485L,
+725509L,
+726021L,
+724997L,
+728581L,
+730629L,
+729093L,
+726533L,
+724485L,
+723973L,
+776709L,
+195173L,
+694789L,
+541253L,
+694789L,
+228965L,
+446533L,
+722437L,
+732165L,
+742917L,
+723461L,
+194149L,
+739909L,
+216069L,
+756741L,
+141541L,
+1030338L,
+658149L,
+1030338L,
+216165L,
+402018L,
+143076L,
+763587L,
+143076L,
+1028290L,
+143076L,
+772291L,
+143076L,
+1028290L,
+143076L,
+775363L,
+143076L,
+1028290L,
+143076L,
+772291L,
+143076L,
+1028290L,
+143076L,
+780995L,
+141536L,
+745155L,
+577765L,
+789187L,
+212101L,
+694785L,
+561157L,
+694789L,
+118917L,
+779077L,
+243845L,
+118401L,
+740881L,
+741893L,
+743237L,
+739941L,
+194117L,
+141541L,
+116418L,
+718949L,
+195141L,
+720485L,
+194629L,
+141541L,
+1028290L,
+720485L,
+194658L,
+524291L,
+195175L,
+249349L,
+718946L,
+118915L,
+743239L,
+398341L,
+141541L,
+1028290L,
+720485L,
+194658L,
+524291L,
+195175L,
+249861L,
+718946L,
+524291L,
+694791L,
+398848L,
+561157L,
+694789L,
+740869L,
+741893L,
+778757L,
+141541L,
+745155L,
+216069L,
+756741L,
+141541L,
+1030338L,
+216165L,
+402018L,
+143076L,
+798403L,
+143076L,
+211138L,
+143076L,
+802499L,
+143076L,
+211138L,
+143072L,
+806595L,
+141541L,
+732354L,
+99973L,
+773957L,
+403557L,
+194117L,
+416357L,
+192069L,
+141541L,
+661186L,
+152160L,
+403554L,
+416355L,
+403461L,
+192064L,
+773637L,
+141541L,
+1028290L,
+152165L,
+192064L,
+194149L,
+403525L,
+141541L,
+677570L,
+216165L,
+402018L,
+143076L,
+815811L,
+143076L,
+855235L,
+143076L,
+834755L,
+143072L,
+855235L,
+141541L,
+936131L,
+539749L,
+194629L,
+541285L,
+228933L,
+546917L,
+193605L,
+377957L,
+194117L,
+739941L,
+254021L,
+560741L,
+195141L,
+118917L,
+723781L,
+722757L,
+724805L,
+724293L,
+730949L,
+726853L,
+735557L,
+725317L,
+694784L,
+539653L,
+377858L,
+147094L,
+560641L,
+118405L,
+546838L,
+541189L,
+694784L,
+762885L,
+739141L,
+738629L,
+745797L,
+729413L,
+777029L,
+740165L,
+402016L,
+745986L,
+216165L,
+118403L,
+216066L,
+143077L,
+843459L,
+776005L,
+728389L,
+405093L,
+183938L,
+223047L,
+404485L,
+404069L,
+159877L,
+255041L,
+403973L,
+402021L,
+162946L,
+405095L,
+226306L,
+257095L,
+460389L,
+227330L,
+225864L,
+228421L,
+227845L,
+119429L,
+216161L,
+257124L,
+144101L,
+852675L,
+404549L,
+141541L,
+1030338L,
+159877L,
+524289L,
+403973L,
+141541L,
+1030338L,
+225893L,
+226402L,
+144100L,
+858819L,
+225797L,
+141541L,
+1030338L,
+757349L,
+257122L,
+142053L,
+862915L,
+227426L,
+253571L,
+141541L,
+863939L,
+227426L,
+253572L,
+257026L,
+119431L,
+227333L,
+216161L,
+257124L,
+142050L,
+872643L,
+118917L,
+54913L,
+660072L,
+524292L,
+524294L,
+524294L,
+524294L,
+403973L,
+141541L,
+873155L,
+404549L,
+227429L,
+253570L,
+405094L,
+228460L,
+144613L,
+881859L,
+227938L,
+216164L,
+225797L,
+119429L,
+228353L,
+524292L,
+142053L,
+1030338L,
+225861L,
+141541L,
+1030338L,
+746085L,
+257122L,
+667365L,
+887491L,
+192069L,
+719973L,
+218245L,
+192577L,
+745989L,
+141541L,
+843459L,
+257125L,
+218245L,
+192104L,
+140421L,
+660072L,
+524294L,
+257124L,
+256517L,
+192098L,
+524292L,
+524294L,
+254086L,
+524294L,
+524294L,
+524294L,
+524294L,
+660069L,
+254600L,
+660069L,
+524296L,
+255493L,
+119429L,
+216161L,
+255588L,
+142050L,
+907971L,
+113285L,
+524296L,
+182887L,
+447493L,
+222725L,
+445957L,
+196098L,
+143589L,
+912067L,
+694784L,
+547845L,
+694789L,
+141538L,
+912067L,
+330821L,
+256613L,
+474693L,
+719973L,
+253509L,
+192610L,
+255108L,
+196423L,
+143077L,
+932547L,
+195589L,
+640L,
+196933L,
+193029L,
+196197L,
+195682L,
+193124L,
+144613L,
+919747L,
+196098L,
+196709L,
+524291L,
+193029L,
+195685L,
+524290L,
+196711L,
+195586L,
+138343L,
+196612L,
+142565L,
+915139L,
+119429L,
+216161L,
+193124L,
+142053L,
+927939L,
+447557L,
+141541L,
+932547L,
+399941L,
+218245L,
+253541L,
+192616L,
+140421L,
+660072L,
+524294L,
+524292L,
+399365L,
+119429L,
+216161L,
+524292L,
+142053L,
+1028290L,
+255077L,
+404037L,
+756736L,
+745477L,
+745989L,
+216069L,
+722437L,
+724485L,
+723973L,
+730629L,
+726533L,
+735237L,
+724997L,
+729093L,
+723461L,
+728069L,
+775685L,
+694789L,
+194661L,
+539717L,
+228965L,
+541253L,
+195173L,
+560709L,
+193637L,
+546885L,
+194149L,
+377925L,
+694784L,
+254053L,
+739909L,
+738821L,
+738309L,
+182885L,
+776706L,
+143077L,
+1030338L,
+254528L,
+182789L,
+141541L,
+1030338L,
+141541L,
+988353L,
+549605L,
+74432L,
+191077L,
+4165L,
+191589L,
+4677L,
+141541L,
+117440L,
+513541L,
+86629L,
+524290L,
+513638L,
+660066L,
+141541L,
+224960L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+993,
+1643,
+3699,
+1270,
+4094,
+3963,
+144,
+437
+};
+
+static const uInt16 patchSupportAddr [] = {
+1023,
+1022,
+1021,
+1020,
+1019,
+1018,
+1017,
+1016,
+746,
+927,
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0x500000L,
+0xC00000L,
+0xA00000L,
+0x1F00000L,
+0x200000L,
+0x200000L,
+0x100000L,
+0x0L,
+0x8F00000L,
+0x1FFE0000L,
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3226PatchRevCQcuk = {
+#else
+const proslicPatch RevCPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x08102010L,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_D_FLBK_2010AUG10.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_D_FLBK_2010AUG10.c
new file mode 100755
index 0000000..d797141
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_D_FLBK_2010AUG10.c
@@ -0,0 +1,921 @@
+/*

+** Generated from si3226_patch_D_FB_2008NOV20.dsp_prom

+** on 03-20-2009 at 15:24:7

+*/

+#include "si_voice_datatypes.h"

+#include "si3226.h"

+

+static const uInt32 patchData [] = {

+141541L,

+532675L,

+141541L,

+535235L,

+141541L,

+536259L,

+141541L,

+613059L,

+141541L,

+617667L,

+141541L,

+956099L,

+141541L,

+957123L,

+141541L,

+961219L,

+736L,

+513728L,

+452200L,

+141541L,

+513216L,

+141541L,

+842432L,

+143589L,

+553667L,

+474213L,

+468066L,

+516165L,

+800867L,

+515653L,

+514053L,

+473700L,

+144608L,

+553155L,

+799330L,

+119428L,

+142048L,

+553155L,

+515141L,

+514661L,

+262242L,

+143077L,

+550595L,

+517218L,

+524291L,

+517125L,

+142053L,

+553667L,

+787781L,

+141541L,

+553667L,

+516709L,

+514882L,

+517125L,

+141541L,

+553667L,

+514565L,

+250469L,

+3170L,

+251811L,

+144101L,

+556739L,

+111237L,

+250981L,

+472675L,

+144096L,

+559299L,

+524289L,

+251397L,

+143077L,

+561347L,

+473189L,

+17637L,

+564419L,

+471653L,

+143077L,

+564419L,

+472165L,

+794693L,

+5733L,

+183952L,

+237724L,

+147196L,

+573635L,

+145637L,

+575171L,

+238213L,

+660065L,

+524291L,

+524294L,

+524294L,

+230534L,

+660069L,

+524296L,

+141541L,

+576195L,

+524288L,

+141541L,

+576195L,

+231045L,

+524289L,

+783365L,

+541925L,

+593091L,

+522853L,

+801349L,

+522341L,

+792645L,

+520293L,

+524290L,

+667365L,

+586435L,

+520805L,

+471621L,

+472133L,

+472645L,

+473157L,

+262245L,

+520261L,

+141541L,

+599235L,

+5221L,

+461424L,

+521828L,

+144613L,

+599235L,

+471621L,

+472133L,

+472645L,

+473157L,

+118405L,

+790853L,

+141541L,

+599235L,

+523877L,

+801349L,

+523365L,

+792645L,

+521317L,

+471621L,

+472133L,

+472645L,

+473152L,

+520197L,

+118917L,

+790853L,

+619749L,

+607939L,

+25829L,

+602819L,

+469605L,

+141538L,

+606915L,

+246373L,

+262242L,

+144099L,

+606915L,

+246277L,

+785925L,

+141541L,

+607939L,

+246277L,

+786437L,

+776293L,

+24293L,

+611011L,

+98434L,

+141557L,

+888513L,

+119426L,

+524310L,

+141541L,

+888513L,

+330917L,

+660069L,

+474728L,

+404579L,

+78565L,

+616643L,

+660069L,

+141541L,

+654016L,

+24800L,

+620739L,

+5221L,

+69L,

+141541L,

+625347L,

+122373L,

+123397L,

+122885L,

+123909L,

+121861L,

+124933L,

+124421L,

+141541L,

+668867L,

+658661L,

+634563L,

+119429L,

+122469L,

+98L,

+122986L,

+122370L,

+101L,

+524298L,

+122896L,

+660069L,

+123496L,

+126469L,

+126563L,

+123394L,

+124005L,

+524291L,

+123909L,

+659173L,

+668867L,

+262240L,

+121956L,

+386659L,

+121860L,

+143077L,

+649923L,

+224384L,

+121964L,

+524291L,

+143077L,

+642243L,

+141541L,

+668867L,

+431717L,

+122466L,

+142562L,

+644803L,

+524305L,

+433765L,

+123492L,

+125957L,

+434274L,

+524292L,

+125440L,

+122373L,

+123397L,

+141541L,

+657091L,

+431717L,

+122978L,

+142562L,

+652483L,

+524305L,

+433765L,

+124004L,

+125957L,

+434274L,

+524292L,

+125440L,

+122885L,

+123909L,

+121861L,

+125541L,

+262242L,

+666848L,

+660163L,

+124516L,

+435299L,

+124421L,

+435301L,

+126052L,

+144613L,

+663235L,

+680965L,

+262242L,

+666848L,

+665795L,

+125028L,

+434787L,

+124933L,

+434789L,

+524292L,

+144613L,

+668867L,

+680965L,

+536800L,

+672963L,

+114789L,

+262242L,

+435812L,

+114692L,

+144608L,

+673475L,

+114693L,

+1125L,

+610L,

+524292L,

+256005L,

+539237L,

+240258L,

+402037L,

+143588L,

+688835L,

+25829L,

+687299L,

+201312L,

+201218L,

+143077L,

+1030338L,

+547941L,

+224386L,

+143072L,

+1030338L,

+694789L,

+537605L,

+538437L,

+538629L,

+694785L,

+721925L,

+141541L,

+791235L,

+201285L,

+141541L,

+1030338L,

+143076L,

+711875L,

+524292L,

+524292L,

+143076L,

+192706L,

+143076L,

+242882L,

+143076L,

+751299L,

+143076L,

+324802L,

+143076L,

+508098L,

+143076L,

+324802L,

+143076L,

+508098L,

+143076L,

+324802L,

+143076L,

+508098L,

+143076L,

+324802L,

+143076L,

+508098L,

+143076L,

+791235L,

+143076L,

+809667L,

+143076L,

+830146L,

+143076L,

+830146L,

+143076L,

+830146L,

+143072L,

+830146L,

+721925L,

+694789L,

+538629L,

+538117L,

+694789L,

+141541L,

+1030338L,

+658149L,

+1030338L,

+216165L,

+402018L,

+143076L,

+724163L,

+143076L,

+124098L,

+143076L,

+127682L,

+143076L,

+138946L,

+143076L,

+1028290L,

+143076L,

+164034L,

+143076L,

+726211L,

+143076L,

+170690L,

+143076L,

+730819L,

+141541L,

+734403L,

+739941L,

+194117L,

+141541L,

+100034L,

+720485L,

+248418L,

+241795L,

+694791L,

+248321L,

+561157L,

+694789L,

+141541L,

+1028290L,

+720485L,

+247906L,

+524291L,

+694791L,

+247808L,

+561157L,

+694789L,

+194661L,

+330816L,

+119429L,

+787781L,

+790021L,

+787973L,

+788485L,

+725509L,

+726021L,

+724997L,

+728581L,

+730629L,

+729093L,

+726533L,

+724485L,

+723973L,

+776709L,

+195173L,

+694789L,

+541253L,

+694789L,

+228965L,

+446533L,

+722437L,

+732165L,

+742917L,

+723461L,

+194149L,

+739909L,

+216069L,

+756741L,

+141541L,

+1030338L,

+658149L,

+1030338L,

+216165L,

+402018L,

+143076L,

+763587L,

+143076L,

+1028290L,

+143076L,

+772291L,

+143076L,

+1028290L,

+143076L,

+775363L,

+143076L,

+1028290L,

+143076L,

+772291L,

+143076L,

+1028290L,

+143076L,

+780995L,

+141536L,

+745155L,

+577765L,

+789187L,

+212101L,

+694785L,

+561157L,

+694789L,

+118917L,

+779077L,

+243845L,

+118401L,

+740881L,

+741893L,

+743237L,

+739941L,

+194117L,

+141541L,

+116418L,

+718949L,

+195141L,

+720485L,

+194629L,

+141541L,

+1028290L,

+720485L,

+194658L,

+524291L,

+195175L,

+249349L,

+718946L,

+118915L,

+743239L,

+398341L,

+141541L,

+1028290L,

+720485L,

+194658L,

+524291L,

+195175L,

+249861L,

+718946L,

+524291L,

+694791L,

+398848L,

+561157L,

+694789L,

+740869L,

+741893L,

+778757L,

+141541L,

+745155L,

+216069L,

+756741L,

+141541L,

+1030338L,

+216165L,

+402018L,

+143076L,

+798403L,

+143076L,

+211138L,

+143076L,

+802499L,

+143076L,

+211138L,

+143072L,

+806595L,

+141541L,

+732354L,

+99973L,

+773957L,

+403557L,

+194117L,

+416357L,

+192069L,

+141541L,

+661186L,

+152160L,

+403554L,

+416355L,

+403461L,

+192064L,

+773637L,

+141541L,

+1028290L,

+152165L,

+192064L,

+194149L,

+403525L,

+141541L,

+677570L,

+216165L,

+402018L,

+143076L,

+815811L,

+143076L,

+855235L,

+143076L,

+834755L,

+143072L,

+855235L,

+141541L,

+936131L,

+539749L,

+194629L,

+541285L,

+228933L,

+546917L,

+193605L,

+377957L,

+194117L,

+739941L,

+254021L,

+560741L,

+195141L,

+118917L,

+723781L,

+722757L,

+724805L,

+724293L,

+730949L,

+726853L,

+735557L,

+725317L,

+694784L,

+539653L,

+377858L,

+147094L,

+560641L,

+118405L,

+546838L,

+541189L,

+694784L,

+762885L,

+739141L,

+738629L,

+745797L,

+729413L,

+777029L,

+740165L,

+402016L,

+745986L,

+216165L,

+118403L,

+216066L,

+143077L,

+843459L,

+776005L,

+728389L,

+405093L,

+183938L,

+223047L,

+404485L,

+404069L,

+159877L,

+255041L,

+403973L,

+402021L,

+162946L,

+405095L,

+226306L,

+257095L,

+460389L,

+227330L,

+225864L,

+228421L,

+227845L,

+119429L,

+216161L,

+257124L,

+144101L,

+852675L,

+404549L,

+141541L,

+1030338L,

+159877L,

+524289L,

+403973L,

+141541L,

+1030338L,

+225893L,

+226402L,

+144100L,

+858819L,

+225797L,

+141541L,

+1030338L,

+757349L,

+257122L,

+142053L,

+862915L,

+227426L,

+253571L,

+141541L,

+863939L,

+227426L,

+253572L,

+257026L,

+119431L,

+227333L,

+216161L,

+257124L,

+142050L,

+872643L,

+118917L,

+54913L,

+660072L,

+524292L,

+524294L,

+524294L,

+524294L,

+403973L,

+141541L,

+873155L,

+404549L,

+227429L,

+253570L,

+405094L,

+228460L,

+144613L,

+881859L,

+227938L,

+216164L,

+225797L,

+119429L,

+228353L,

+524292L,

+142053L,

+1030338L,

+225861L,

+141541L,

+1030338L,

+746085L,

+257122L,

+667365L,

+887491L,

+192069L,

+719973L,

+218245L,

+192577L,

+745989L,

+141541L,

+843459L,

+257125L,

+218245L,

+192104L,

+140421L,

+660072L,

+524294L,

+257124L,

+256517L,

+192098L,

+524292L,

+524294L,

+254086L,

+524294L,

+524294L,

+524294L,

+524294L,

+660069L,

+254600L,

+660069L,

+524296L,

+255493L,

+119429L,

+216161L,

+255588L,

+142050L,

+907971L,

+113285L,

+524296L,

+182887L,

+447493L,

+222725L,

+445957L,

+196098L,

+143589L,

+912067L,

+694784L,

+547845L,

+694789L,

+141538L,

+912067L,

+330821L,

+256613L,

+474693L,

+719973L,

+253509L,

+192610L,

+255108L,

+196423L,

+143077L,

+932547L,

+195589L,

+640L,

+196933L,

+193029L,

+196197L,

+195682L,

+193124L,

+144613L,

+919747L,

+196098L,

+196709L,

+524291L,

+193029L,

+195685L,

+524290L,

+196711L,

+195586L,

+138343L,

+196612L,

+142565L,

+915139L,

+119429L,

+216161L,

+193124L,

+142053L,

+927939L,

+447557L,

+141541L,

+932547L,

+399941L,

+218245L,

+253541L,

+192616L,

+140421L,

+660072L,

+524294L,

+524292L,

+399365L,

+119429L,

+216161L,

+524292L,

+142053L,

+1028290L,

+255077L,

+404037L,

+756736L,

+745477L,

+745989L,

+216069L,

+722437L,

+724485L,

+723973L,

+730629L,

+726533L,

+735237L,

+724997L,

+729093L,

+723461L,

+728069L,

+775685L,

+694789L,

+194661L,

+539717L,

+228965L,

+541253L,

+195173L,

+560709L,

+193637L,

+546885L,

+194149L,

+377925L,

+694784L,

+254053L,

+739909L,

+738821L,

+738309L,

+182885L,

+776706L,

+143077L,

+1030338L,

+254528L,

+182789L,

+141541L,

+1030338L,

+141541L,

+988353L,

+549605L,

+74432L,

+191077L,

+4165L,

+191589L,

+4677L,

+141541L,

+117440L,

+513541L,

+86629L,

+524290L,

+513638L,

+660066L,

+141541L,

+224960L,

+0L

+};

+

+static const uInt16 patchEntries [] = {

+993,

+1643,

+3699,

+1270,

+4094,

+3963,

+144,

+437

+};

+

+static const uInt16 patchSupportAddr [] = {

+1023,

+1022,

+1021,

+1020,

+1019,

+1018,

+1017,

+1016,

+746,

+927,

+0

+};

+

+static const uInt32 patchSupportData [] = {

+0x1F00000L,

+0xC00000L,

+0xA00000L,

+0x1F00000L,

+0x200000L,

+0x200000L,

+0x100000L,

+0x0L,

+0x8F00000L,

+0x1FFE0000L,

+0x0L

+};

+

+#ifdef SIVOICE_MULTI_BOM_SUPPORT

+const proslicPatch si3226PatchRevDFlbk = {

+#else

+const proslicPatch RevDPatch = {

+#endif

+    patchData,

+    patchEntries,

+    0x08102010L,

+    patchSupportAddr,

+    patchSupportData

+};

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_D_QCUK_2010AUG10.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_D_QCUK_2010AUG10.c
new file mode 100755
index 0000000..ee93d72
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_D_QCUK_2010AUG10.c
@@ -0,0 +1,921 @@
+/*

+** Generated from si3226_patch_D_QCUK_2008NOV20.dsp_prom

+** on 03-20-2009 at 15:18:26

+*/

+#include "si_voice_datatypes.h"

+#include "si3226.h"

+

+static const uInt32 patchData [] = {

+141541L,

+532675L,

+141541L,

+535235L,

+141541L,

+536259L,

+141541L,

+613059L,

+141541L,

+617667L,

+141541L,

+956099L,

+141541L,

+957123L,

+141541L,

+961219L,

+736L,

+513728L,

+452200L,

+141541L,

+513216L,

+141541L,

+842432L,

+143589L,

+553667L,

+474213L,

+468066L,

+516165L,

+800867L,

+515653L,

+514053L,

+473700L,

+144608L,

+553155L,

+799330L,

+119428L,

+142048L,

+553155L,

+515141L,

+514661L,

+262242L,

+143077L,

+550595L,

+517218L,

+524291L,

+517125L,

+142053L,

+553667L,

+787781L,

+141541L,

+553667L,

+516709L,

+514882L,

+517125L,

+141541L,

+553667L,

+514565L,

+250469L,

+3170L,

+251811L,

+144101L,

+556739L,

+111237L,

+250981L,

+472675L,

+144096L,

+559299L,

+524289L,

+251397L,

+143077L,

+561347L,

+473189L,

+17637L,

+564419L,

+471653L,

+143077L,

+564419L,

+472165L,

+794693L,

+5733L,

+183952L,

+237724L,

+147196L,

+573635L,

+145637L,

+575171L,

+238213L,

+660065L,

+524291L,

+524294L,

+524294L,

+230534L,

+660069L,

+524296L,

+141541L,

+576195L,

+524288L,

+141541L,

+576195L,

+231045L,

+524289L,

+783365L,

+541925L,

+593091L,

+522853L,

+801349L,

+522341L,

+792645L,

+520293L,

+524290L,

+667365L,

+586435L,

+520805L,

+471621L,

+472133L,

+472645L,

+473157L,

+262245L,

+520261L,

+141541L,

+599235L,

+5221L,

+461424L,

+521828L,

+144613L,

+599235L,

+471621L,

+472133L,

+472645L,

+473157L,

+118405L,

+790853L,

+141541L,

+599235L,

+523877L,

+801349L,

+523365L,

+792645L,

+521317L,

+471621L,

+472133L,

+472645L,

+473152L,

+520197L,

+118917L,

+790853L,

+619749L,

+607939L,

+25829L,

+602819L,

+469605L,

+141538L,

+606915L,

+246373L,

+262242L,

+144099L,

+606915L,

+246277L,

+785925L,

+141541L,

+607939L,

+246277L,

+786437L,

+776293L,

+24293L,

+611011L,

+98434L,

+141557L,

+888513L,

+119426L,

+524310L,

+141541L,

+888513L,

+330917L,

+660069L,

+474728L,

+404579L,

+78565L,

+616643L,

+660069L,

+141541L,

+654016L,

+24800L,

+620739L,

+5221L,

+69L,

+141541L,

+625347L,

+122373L,

+123397L,

+122885L,

+123909L,

+121861L,

+124933L,

+124421L,

+141541L,

+668867L,

+658661L,

+634563L,

+119429L,

+122469L,

+98L,

+122986L,

+122370L,

+101L,

+524298L,

+122896L,

+660069L,

+123496L,

+126469L,

+126563L,

+123394L,

+124005L,

+524291L,

+123909L,

+659173L,

+668867L,

+262240L,

+121956L,

+386659L,

+121860L,

+143077L,

+649923L,

+224384L,

+121964L,

+524291L,

+143077L,

+642243L,

+141541L,

+668867L,

+431717L,

+122466L,

+142562L,

+644803L,

+524305L,

+433765L,

+123492L,

+125957L,

+434274L,

+524292L,

+125440L,

+122373L,

+123397L,

+141541L,

+657091L,

+431717L,

+122978L,

+142562L,

+652483L,

+524305L,

+433765L,

+124004L,

+125957L,

+434274L,

+524292L,

+125440L,

+122885L,

+123909L,

+121861L,

+125541L,

+262242L,

+666848L,

+660163L,

+124516L,

+435299L,

+124421L,

+435301L,

+126052L,

+144613L,

+663235L,

+680965L,

+262242L,

+666848L,

+665795L,

+125028L,

+434787L,

+124933L,

+434789L,

+524292L,

+144613L,

+668867L,

+680965L,

+536800L,

+672963L,

+114789L,

+262242L,

+435812L,

+114692L,

+144608L,

+673475L,

+114693L,

+1125L,

+610L,

+524292L,

+256005L,

+539237L,

+240258L,

+402037L,

+143588L,

+688835L,

+25829L,

+687299L,

+201312L,

+201218L,

+143077L,

+1030338L,

+547941L,

+224386L,

+143072L,

+1030338L,

+694789L,

+537605L,

+538437L,

+538629L,

+694785L,

+721925L,

+141541L,

+791235L,

+201285L,

+141541L,

+1030338L,

+143076L,

+711875L,

+524292L,

+524292L,

+143076L,

+192706L,

+143076L,

+242882L,

+143076L,

+751299L,

+143076L,

+324802L,

+143076L,

+508098L,

+143076L,

+324802L,

+143076L,

+508098L,

+143076L,

+324802L,

+143076L,

+508098L,

+143076L,

+324802L,

+143076L,

+508098L,

+143076L,

+791235L,

+143076L,

+809667L,

+143076L,

+830146L,

+143076L,

+830146L,

+143076L,

+830146L,

+143072L,

+830146L,

+721925L,

+694789L,

+538629L,

+538117L,

+694789L,

+141541L,

+1030338L,

+658149L,

+1030338L,

+216165L,

+402018L,

+143076L,

+724163L,

+143076L,

+124098L,

+143076L,

+127682L,

+143076L,

+138946L,

+143076L,

+1028290L,

+143076L,

+164034L,

+143076L,

+726211L,

+143076L,

+170690L,

+143076L,

+730819L,

+141541L,

+734403L,

+739941L,

+194117L,

+141541L,

+100034L,

+720485L,

+248418L,

+241795L,

+694791L,

+248321L,

+561157L,

+694789L,

+141541L,

+1028290L,

+720485L,

+247906L,

+524291L,

+694791L,

+247808L,

+561157L,

+694789L,

+194661L,

+330816L,

+119429L,

+787781L,

+790021L,

+787973L,

+788485L,

+725509L,

+726021L,

+724997L,

+728581L,

+730629L,

+729093L,

+726533L,

+724485L,

+723973L,

+776709L,

+195173L,

+694789L,

+541253L,

+694789L,

+228965L,

+446533L,

+722437L,

+732165L,

+742917L,

+723461L,

+194149L,

+739909L,

+216069L,

+756741L,

+141541L,

+1030338L,

+658149L,

+1030338L,

+216165L,

+402018L,

+143076L,

+763587L,

+143076L,

+1028290L,

+143076L,

+772291L,

+143076L,

+1028290L,

+143076L,

+775363L,

+143076L,

+1028290L,

+143076L,

+772291L,

+143076L,

+1028290L,

+143076L,

+780995L,

+141536L,

+745155L,

+577765L,

+789187L,

+212101L,

+694785L,

+561157L,

+694789L,

+118917L,

+779077L,

+243845L,

+118401L,

+740881L,

+741893L,

+743237L,

+739941L,

+194117L,

+141541L,

+116418L,

+718949L,

+195141L,

+720485L,

+194629L,

+141541L,

+1028290L,

+720485L,

+194658L,

+524291L,

+195175L,

+249349L,

+718946L,

+118915L,

+743239L,

+398341L,

+141541L,

+1028290L,

+720485L,

+194658L,

+524291L,

+195175L,

+249861L,

+718946L,

+524291L,

+694791L,

+398848L,

+561157L,

+694789L,

+740869L,

+741893L,

+778757L,

+141541L,

+745155L,

+216069L,

+756741L,

+141541L,

+1030338L,

+216165L,

+402018L,

+143076L,

+798403L,

+143076L,

+211138L,

+143076L,

+802499L,

+143076L,

+211138L,

+143072L,

+806595L,

+141541L,

+732354L,

+99973L,

+773957L,

+403557L,

+194117L,

+416357L,

+192069L,

+141541L,

+661186L,

+152160L,

+403554L,

+416355L,

+403461L,

+192064L,

+773637L,

+141541L,

+1028290L,

+152165L,

+192064L,

+194149L,

+403525L,

+141541L,

+677570L,

+216165L,

+402018L,

+143076L,

+815811L,

+143076L,

+855235L,

+143076L,

+834755L,

+143072L,

+855235L,

+141541L,

+936131L,

+539749L,

+194629L,

+541285L,

+228933L,

+546917L,

+193605L,

+377957L,

+194117L,

+739941L,

+254021L,

+560741L,

+195141L,

+118917L,

+723781L,

+722757L,

+724805L,

+724293L,

+730949L,

+726853L,

+735557L,

+725317L,

+694784L,

+539653L,

+377858L,

+147094L,

+560641L,

+118405L,

+546838L,

+541189L,

+694784L,

+762885L,

+739141L,

+738629L,

+745797L,

+729413L,

+777029L,

+740165L,

+402016L,

+745986L,

+216165L,

+118403L,

+216066L,

+143077L,

+843459L,

+776005L,

+728389L,

+405093L,

+183938L,

+223047L,

+404485L,

+404069L,

+159877L,

+255041L,

+403973L,

+402021L,

+162946L,

+405095L,

+226306L,

+257095L,

+460389L,

+227330L,

+225864L,

+228421L,

+227845L,

+119429L,

+216161L,

+257124L,

+144101L,

+852675L,

+404549L,

+141541L,

+1030338L,

+159877L,

+524289L,

+403973L,

+141541L,

+1030338L,

+225893L,

+226402L,

+144100L,

+858819L,

+225797L,

+141541L,

+1030338L,

+757349L,

+257122L,

+142053L,

+862915L,

+227426L,

+253571L,

+141541L,

+863939L,

+227426L,

+253572L,

+257026L,

+119431L,

+227333L,

+216161L,

+257124L,

+142050L,

+872643L,

+118917L,

+54913L,

+660072L,

+524292L,

+524294L,

+524294L,

+524294L,

+403973L,

+141541L,

+873155L,

+404549L,

+227429L,

+253570L,

+405094L,

+228460L,

+144613L,

+881859L,

+227938L,

+216164L,

+225797L,

+119429L,

+228353L,

+524292L,

+142053L,

+1030338L,

+225861L,

+141541L,

+1030338L,

+746085L,

+257122L,

+667365L,

+887491L,

+192069L,

+719973L,

+218245L,

+192577L,

+745989L,

+141541L,

+843459L,

+257125L,

+218245L,

+192104L,

+140421L,

+660072L,

+524294L,

+257124L,

+256517L,

+192098L,

+524292L,

+524294L,

+254086L,

+524294L,

+524294L,

+524294L,

+524294L,

+660069L,

+254600L,

+660069L,

+524296L,

+255493L,

+119429L,

+216161L,

+255588L,

+142050L,

+907971L,

+113285L,

+524296L,

+182887L,

+447493L,

+222725L,

+445957L,

+196098L,

+143589L,

+912067L,

+694784L,

+547845L,

+694789L,

+141538L,

+912067L,

+330821L,

+256613L,

+474693L,

+719973L,

+253509L,

+192610L,

+255108L,

+196423L,

+143077L,

+932547L,

+195589L,

+640L,

+196933L,

+193029L,

+196197L,

+195682L,

+193124L,

+144613L,

+919747L,

+196098L,

+196709L,

+524291L,

+193029L,

+195685L,

+524290L,

+196711L,

+195586L,

+138343L,

+196612L,

+142565L,

+915139L,

+119429L,

+216161L,

+193124L,

+142053L,

+927939L,

+447557L,

+141541L,

+932547L,

+399941L,

+218245L,

+253541L,

+192616L,

+140421L,

+660072L,

+524294L,

+524292L,

+399365L,

+119429L,

+216161L,

+524292L,

+142053L,

+1028290L,

+255077L,

+404037L,

+756736L,

+745477L,

+745989L,

+216069L,

+722437L,

+724485L,

+723973L,

+730629L,

+726533L,

+735237L,

+724997L,

+729093L,

+723461L,

+728069L,

+775685L,

+694789L,

+194661L,

+539717L,

+228965L,

+541253L,

+195173L,

+560709L,

+193637L,

+546885L,

+194149L,

+377925L,

+694784L,

+254053L,

+739909L,

+738821L,

+738309L,

+182885L,

+776706L,

+143077L,

+1030338L,

+254528L,

+182789L,

+141541L,

+1030338L,

+141541L,

+988353L,

+549605L,

+74432L,

+191077L,

+4165L,

+191589L,

+4677L,

+141541L,

+117440L,

+513541L,

+86629L,

+524290L,

+513638L,

+660066L,

+141541L,

+224960L,

+0L

+};

+

+static const uInt16 patchEntries [] = {

+993,

+1643,

+3699,

+1270,

+4094,

+3963,

+144,

+437

+};

+

+static const uInt16 patchSupportAddr [] = {

+1023,

+1022,

+1021,

+1020,

+1019,

+1018,

+1017,

+1016,

+746,

+927,

+0

+};

+

+static const uInt32 patchSupportData [] = {

+0x500000L,

+0xC00000L,

+0xA00000L,

+0x1F00000L,

+0x200000L,

+0x200000L,

+0x100000L,

+0x0L,

+0x8F00000L,

+0x1FFE0000L,

+0x0L

+};

+

+#ifdef SIVOICE_MULTI_BOM_SUPPORT

+const proslicPatch si3226PatchRevDQcuk = {

+#else

+const proslicPatch RevDPatch = {

+#endif

+    patchData,

+    patchEntries,

+    0x08102010L,

+    patchSupportAddr,

+    patchSupportData

+};

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_E_FLBK_2010AUG10.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_E_FLBK_2010AUG10.c
new file mode 100755
index 0000000..159de44
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_E_FLBK_2010AUG10.c
@@ -0,0 +1,532 @@
+/*
+** Generated from si3226_patch_E_FLBK_2010JAN06.dsp_prom
+** on 01-07-2010 at 11:6:27
+*/
+#include "si_voice_datatypes.h"
+#include "si3226.h"
+
+static const uInt32 patchData [] = {
+141541L,
+532675L,
+141541L,
+757443L,
+141541L,
+763587L,
+141541L,
+765123L,
+141541L,
+769731L,
+141541L,
+770243L,
+141541L,
+770755L,
+141541L,
+771267L,
+216165L,
+402018L,
+143076L,
+539843L,
+143076L,
+601795L,
+143076L,
+609475L,
+143076L,
+617667L,
+143072L,
+624835L,
+141541L,
+729283L,
+223365L,
+194373L,
+450661L,
+253509L,
+519781L,
+450629L,
+118917L,
+723781L,
+727365L,
+727877L,
+730949L,
+743237L,
+118405L,
+725317L,
+724293L,
+738629L,
+739141L,
+726853L,
+734021L,
+260741L,
+729413L,
+738117L,
+546917L,
+228933L,
+69250L,
+694806L,
+546821L,
+118917L,
+549184L,
+549381L,
+377957L,
+194629L,
+377861L,
+565349L,
+195141L,
+206469L,
+565573L,
+560741L,
+118914L,
+459894L,
+560645L,
+694789L,
+13381L,
+119429L,
+14144L,
+14341L,
+402021L,
+77538L,
+565443L,
+524288L,
+755200L,
+202245L,
+202757L,
+203269L,
+74981L,
+571587L,
+75493L,
+576707L,
+76517L,
+581827L,
+77029L,
+586947L,
+119429L,
+746817L,
+192837L,
+196613L,
+225925L,
+752448L,
+53477L,
+595651L,
+141541L,
+591043L,
+119429L,
+747329L,
+192837L,
+196613L,
+116869L,
+752453L,
+53477L,
+595651L,
+141541L,
+591043L,
+249477L,
+756033L,
+192837L,
+196613L,
+116869L,
+752453L,
+53477L,
+595651L,
+141541L,
+591043L,
+249477L,
+756545L,
+192837L,
+196613L,
+225925L,
+752448L,
+53477L,
+595651L,
+410213L,
+192069L,
+694789L,
+228997L,
+541504L,
+694801L,
+761861L,
+141541L,
+978626L,
+410725L,
+192069L,
+256645L,
+767301L,
+694789L,
+249477L,
+541509L,
+694789L,
+118917L,
+216389L,
+141541L,
+980674L,
+192101L,
+194146L,
+144100L,
+605379L,
+192005L,
+141541L,
+980674L,
+410725L,
+192069L,
+694789L,
+249477L,
+541509L,
+694789L,
+141541L,
+978626L,
+119429L,
+694789L,
+549701L,
+694789L,
+192101L,
+194146L,
+144100L,
+615107L,
+192005L,
+141541L,
+749251L,
+411237L,
+201797L,
+192069L,
+141541L,
+747203L,
+192101L,
+194146L,
+144100L,
+621251L,
+192005L,
+141541L,
+749251L,
+411744L,
+192069L,
+205317L,
+203781L,
+204293L,
+141541L,
+747203L,
+658661L,
+749251L,
+204901L,
+204386L,
+412580L,
+203877L,
+204362L,
+203781L,
+203877L,
+412581L,
+204712L,
+660064L,
+203884L,
+204197L,
+204394L,
+204709L,
+192106L,
+205314L,
+144101L,
+637635L,
+194149L,
+524292L,
+192005L,
+142053L,
+749251L,
+253029L,
+262242L,
+143075L,
+695491L,
+143075L,
+691907L,
+143077L,
+657603L,
+259685L,
+259170L,
+205435L,
+193122L,
+256132L,
+660069L,
+259184L,
+260101L,
+147685L,
+648387L,
+261217L,
+259684L,
+261125L,
+196162L,
+260197L,
+524292L,
+195589L,
+141541L,
+661699L,
+192677L,
+261216L,
+252936L,
+256134L,
+147685L,
+655555L,
+660065L,
+524292L,
+524311L,
+192517L,
+141541L,
+719043L,
+205413L,
+193122L,
+524292L,
+660069L,
+259184L,
+259589L,
+196163L,
+195589L,
+640L,
+252741L,
+192517L,
+196197L,
+195682L,
+192612L,
+144613L,
+667843L,
+196098L,
+252517L,
+524291L,
+192517L,
+195685L,
+255618L,
+77541L,
+670403L,
+129669L,
+252519L,
+195586L,
+138343L,
+252420L,
+144613L,
+674499L,
+141541L,
+663235L,
+192609L,
+524296L,
+77541L,
+683203L,
+259687L,
+192512L,
+252933L,
+259170L,
+96923L,
+147681L,
+680643L,
+524288L,
+192613L,
+256131L,
+192517L,
+141541L,
+655555L,
+192517L,
+114309L,
+253025L,
+259684L,
+144101L,
+651459L,
+259170L,
+260731L,
+192610L,
+145637L,
+689347L,
+524305L,
+524291L,
+192517L,
+261125L,
+141541L,
+702659L,
+205413L,
+193122L,
+255620L,
+259077L,
+192837L,
+141541L,
+702659L,
+205413L,
+193088L,
+192517L,
+77541L,
+702659L,
+256645L,
+752448L,
+202245L,
+202757L,
+203269L,
+410725L,
+118917L,
+141541L,
+703683L,
+201829L,
+118405L,
+192069L,
+216389L,
+253029L,
+262242L,
+192612L,
+252928L,
+755205L,
+256130L,
+524311L,
+192517L,
+192613L,
+256133L,
+75490L,
+714435L,
+74999L,
+715971L,
+76517L,
+717507L,
+756229L,
+141541L,
+749251L,
+747013L,
+141541L,
+749251L,
+746501L,
+141541L,
+749251L,
+755717L,
+141541L,
+749251L,
+75493L,
+724675L,
+74999L,
+726211L,
+76517L,
+727747L,
+232037L,
+524291L,
+756229L,
+141541L,
+729283L,
+747013L,
+141541L,
+729283L,
+746501L,
+141541L,
+729283L,
+231525L,
+524291L,
+755717L,
+756736L,
+752133L,
+727045L,
+727557L,
+730629L,
+729093L,
+723461L,
+726533L,
+738309L,
+738821L,
+216069L,
+766981L,
+761861L,
+742917L,
+724997L,
+723973L,
+733701L,
+253541L,
+450629L,
+560741L,
+103554L,
+694805L,
+560645L,
+228965L,
+546880L,
+541189L,
+548869L,
+549381L,
+194661L,
+377925L,
+195173L,
+565317L,
+694789L,
+141541L,
+980674L,
+216165L,
+402018L,
+524291L,
+216069L,
+127077L,
+413093L,
+202856L,
+414629L,
+203372L,
+415141L,
+414124L,
+202245L,
+202858L,
+413605L,
+203340L,
+202341L,
+202821L,
+204805L,
+141541L,
+980674L,
+601829L,
+617152L,
+30725L,
+724069L,
+118914L,
+30837L,
+143074L,
+617152L,
+524288L,
+133637L,
+141541L,
+617152L,
+98437L,
+141558L,
+853698L,
+4837L,
+766659L,
+127077L,
+736L,
+521408L,
+452200L,
+524291L,
+141541L,
+521408L,
+524293L,
+524293L,
+524293L,
+524293L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+6004,
+1204,
+5762,
+1008,
+0,
+0,
+0,
+0
+};
+
+static const uInt16 patchSupportAddr [] = {
+1023,
+1022,
+804,
+509,
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0x1F00000L,
+0xC00000L,
+0x4B00L,
+0x320000L,
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3226PatchRevEFlbk = {
+#else
+const proslicPatch RevEPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x08102010L,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_E_FLBK_2010JAN06.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_E_FLBK_2010JAN06.c
new file mode 100755
index 0000000..54e2935
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226_patch_E_FLBK_2010JAN06.c
@@ -0,0 +1,528 @@
+/*
+** Generated from si3226_patch_E_FLBK_2010JAN06.dsp_prom
+** on 01-07-2010 at 11:6:27
+*/
+#include "si_voice_datatypes.h"
+#include "si3226.h"
+
+const uInt32 patchDataRevE [] = {
+141541L,
+532675L,
+141541L,
+757443L,
+141541L,
+763587L,
+141541L,
+765123L,
+141541L,
+769731L,
+141541L,
+770243L,
+141541L,
+770755L,
+141541L,
+771267L,
+216165L,
+402018L,
+143076L,
+539843L,
+143076L,
+601795L,
+143076L,
+609475L,
+143076L,
+617667L,
+143072L,
+624835L,
+141541L,
+729283L,
+223365L,
+194373L,
+450661L,
+253509L,
+519781L,
+450629L,
+118917L,
+723781L,
+727365L,
+727877L,
+730949L,
+743237L,
+118405L,
+725317L,
+724293L,
+738629L,
+739141L,
+726853L,
+734021L,
+260741L,
+729413L,
+738117L,
+546917L,
+228933L,
+69250L,
+694806L,
+546821L,
+118917L,
+549184L,
+549381L,
+377957L,
+194629L,
+377861L,
+565349L,
+195141L,
+206469L,
+565573L,
+560741L,
+118914L,
+459894L,
+560645L,
+694789L,
+13381L,
+119429L,
+14144L,
+14341L,
+402021L,
+77538L,
+565443L,
+524288L,
+755200L,
+202245L,
+202757L,
+203269L,
+74981L,
+571587L,
+75493L,
+576707L,
+76517L,
+581827L,
+77029L,
+586947L,
+119429L,
+746817L,
+192837L,
+196613L,
+225925L,
+752448L,
+53477L,
+595651L,
+141541L,
+591043L,
+119429L,
+747329L,
+192837L,
+196613L,
+116869L,
+752453L,
+53477L,
+595651L,
+141541L,
+591043L,
+249477L,
+756033L,
+192837L,
+196613L,
+116869L,
+752453L,
+53477L,
+595651L,
+141541L,
+591043L,
+249477L,
+756545L,
+192837L,
+196613L,
+225925L,
+752448L,
+53477L,
+595651L,
+410213L,
+192069L,
+694789L,
+228997L,
+541504L,
+694801L,
+761861L,
+141541L,
+978626L,
+410725L,
+192069L,
+256645L,
+767301L,
+694789L,
+249477L,
+541509L,
+694789L,
+118917L,
+216389L,
+141541L,
+980674L,
+192101L,
+194146L,
+144100L,
+605379L,
+192005L,
+141541L,
+980674L,
+410725L,
+192069L,
+694789L,
+249477L,
+541509L,
+694789L,
+141541L,
+978626L,
+119429L,
+694789L,
+549701L,
+694789L,
+192101L,
+194146L,
+144100L,
+615107L,
+192005L,
+141541L,
+749251L,
+411237L,
+201797L,
+192069L,
+141541L,
+747203L,
+192101L,
+194146L,
+144100L,
+621251L,
+192005L,
+141541L,
+749251L,
+411744L,
+192069L,
+205317L,
+203781L,
+204293L,
+141541L,
+747203L,
+658661L,
+749251L,
+204901L,
+204386L,
+412580L,
+203877L,
+204362L,
+203781L,
+203877L,
+412581L,
+204712L,
+660064L,
+203884L,
+204197L,
+204394L,
+204709L,
+192106L,
+205314L,
+144101L,
+637635L,
+194149L,
+524292L,
+192005L,
+142053L,
+749251L,
+253029L,
+262242L,
+143075L,
+695491L,
+143075L,
+691907L,
+143077L,
+657603L,
+259685L,
+259170L,
+205435L,
+193122L,
+256132L,
+660069L,
+259184L,
+260101L,
+147685L,
+648387L,
+261217L,
+259684L,
+261125L,
+196162L,
+260197L,
+524292L,
+195589L,
+141541L,
+661699L,
+192677L,
+261216L,
+252936L,
+256134L,
+147685L,
+655555L,
+660065L,
+524292L,
+524311L,
+192517L,
+141541L,
+719043L,
+205413L,
+193122L,
+524292L,
+660069L,
+259184L,
+259589L,
+196163L,
+195589L,
+640L,
+252741L,
+192517L,
+196197L,
+195682L,
+192612L,
+144613L,
+667843L,
+196098L,
+252517L,
+524291L,
+192517L,
+195685L,
+255618L,
+77541L,
+670403L,
+129669L,
+252519L,
+195586L,
+138343L,
+252420L,
+144613L,
+674499L,
+141541L,
+663235L,
+192609L,
+524296L,
+77541L,
+683203L,
+259687L,
+192512L,
+252933L,
+259170L,
+96923L,
+147681L,
+680643L,
+524288L,
+192613L,
+256131L,
+192517L,
+141541L,
+655555L,
+192517L,
+114309L,
+253025L,
+259684L,
+144101L,
+651459L,
+259170L,
+260731L,
+192610L,
+145637L,
+689347L,
+524305L,
+524291L,
+192517L,
+261125L,
+141541L,
+702659L,
+205413L,
+193122L,
+255620L,
+259077L,
+192837L,
+141541L,
+702659L,
+205413L,
+193088L,
+192517L,
+77541L,
+702659L,
+256645L,
+752448L,
+202245L,
+202757L,
+203269L,
+410725L,
+118917L,
+141541L,
+703683L,
+201829L,
+118405L,
+192069L,
+216389L,
+253029L,
+262242L,
+192612L,
+252928L,
+755205L,
+256130L,
+524311L,
+192517L,
+192613L,
+256133L,
+75490L,
+714435L,
+74999L,
+715971L,
+76517L,
+717507L,
+756229L,
+141541L,
+749251L,
+747013L,
+141541L,
+749251L,
+746501L,
+141541L,
+749251L,
+755717L,
+141541L,
+749251L,
+75493L,
+724675L,
+74999L,
+726211L,
+76517L,
+727747L,
+232037L,
+524291L,
+756229L,
+141541L,
+729283L,
+747013L,
+141541L,
+729283L,
+746501L,
+141541L,
+729283L,
+231525L,
+524291L,
+755717L,
+756736L,
+752133L,
+727045L,
+727557L,
+730629L,
+729093L,
+723461L,
+726533L,
+738309L,
+738821L,
+216069L,
+766981L,
+761861L,
+742917L,
+724997L,
+723973L,
+733701L,
+253541L,
+450629L,
+560741L,
+103554L,
+694805L,
+560645L,
+228965L,
+546880L,
+541189L,
+548869L,
+549381L,
+194661L,
+377925L,
+195173L,
+565317L,
+694789L,
+141541L,
+980674L,
+216165L,
+402018L,
+524291L,
+216069L,
+127077L,
+413093L,
+202856L,
+414629L,
+203372L,
+415141L,
+414124L,
+202245L,
+202858L,
+413605L,
+203340L,
+202341L,
+202821L,
+204805L,
+141541L,
+980674L,
+601829L,
+617152L,
+30725L,
+724069L,
+118914L,
+30837L,
+143074L,
+617152L,
+524288L,
+133637L,
+141541L,
+617152L,
+98437L,
+141558L,
+853698L,
+4837L,
+766659L,
+127077L,
+736L,
+521408L,
+452200L,
+524291L,
+141541L,
+521408L,
+524293L,
+524293L,
+524293L,
+524293L,
+0L
+};
+
+const uInt16 patchEntriesRevE [] = {
+6004,
+1204,
+5762,
+1008,
+0,
+0,
+0,
+0
+};
+
+const uInt16 patchSupportAddrRevE [] = {
+1023,
+1022,
+804,
+509,
+0
+};
+
+const uInt32 patchSupportDataRevE [] = {
+0x1F00000L,
+0xC00000L,
+0x4B00L,
+0x320000L,
+0x0L
+};
+
+const proslicPatch RevEPatch = {
+    patchDataRevE,
+    patchEntriesRevE,
+    0x01072010L,
+    patchSupportAddrRevE,
+    patchSupportDataRevE
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_FLBK_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_FLBK_constants.c
new file mode 100755
index 0000000..ae19904
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_FLBK_constants.c
@@ -0,0 +1,604 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-05-20 16:31:58

+**

+** Si3226x ProSLIC API Configuration Tool Version 2.5.0L

+*/

+

+

+#include "proslic.h"

+#include "si3226x.h"

+

+Si3226x_General_Cfg Si3226x_General_Configuration  = {

+0x65,     /* DEVICE_KEY */

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+BO_DCDC_TRACKING,    /* BAT_RAIL_TYPE */

+0x000AD000L,    /* bat_hyst */

+0x08A3D6C8L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x01999A00L,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x00F00000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x00809D80L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00400000L,    /* PD_UVLO */

+0x00400000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00500000L,    /* DCDC_UVHYST */

+0x00000000L,    /* DCDC_UVTHRESH */

+0x01700000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00000000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01000000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04B80200L,    /* UVTHRESH_SCALE */

+0x00823000L     /* UVTHRESH_BIAS */

+};

+

+Si3226x_GPIO_Cfg Si3226x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3226x_CI_Cfg Si3226x_CI_Presets [] = {

+{0}

+};

+Si3226x_audioGain_Cfg Si3226x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3226x_Ring_Cfg Si3226x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 3, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x002EEF31L,	/* RINGAMP (80.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0077BD13L,	/* RTACTH (66.124 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x088C26FDL,	/* VBATR_EXPECT (133.554 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x0446137EL,	/* VCM_RING (63.777 v) */

+0x0446137EL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x00,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3226x_DCfeed_Cfg Si3226x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3226x_Impedance_Cfg Si3226x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3226x_FSK_Cfg Si3226x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3226x_PulseMeter_Cfg Si3226x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3226x_Tone_Cfg Si3226x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x80,			 /* O1TILO (2000 ms) */

+	0x3E			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3226x_PCM_Cfg Si3226x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x01 	 /* A-LAW -  INVERT EVEN */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_LCQCUK_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_LCQCUK_constants.c
new file mode 100755
index 0000000..1b0960a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_LCQCUK_constants.c
@@ -0,0 +1,604 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-05-20 16:34:32

+**

+** Si3226x ProSLIC API Configuration Tool Version 2.5.0L

+*/

+

+

+#include "proslic.h"

+#include "si3226x.h"

+

+Si3226x_General_Cfg Si3226x_General_Configuration  = {

+0x65,     /* DEVICE_KEY */

+BO_DCDC_LCQCUK,    /* BOM_OPT */

+BO_DCDC_TRACKING,    /* BAT_RAIL_TYPE */

+0x0020C480L,    /* bat_hyst */

+0x051EB82AL,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x01999A00L,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x00F00000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x00809D80L,    /* DCDC_VERR_HYST */

+0x00000000L,    /* DCDC_OITHRESH_LO */

+0x01C00000L,    /* DCDC_OITHRESH_HI */

+0x00400000L,    /* PD_UVLO */

+0x00400000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00500000L,    /* DCDC_UVHYST */

+0x00000000L,    /* DCDC_UVTHRESH */

+0x00500000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00000000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01000000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04B80200L,    /* UVTHRESH_SCALE */

+0x00823000L     /* UVTHRESH_BIAS */

+};

+

+Si3226x_GPIO_Cfg Si3226x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3226x_CI_Cfg Si3226x_CI_Presets [] = {

+{0}

+};

+Si3226x_audioGain_Cfg Si3226x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3226x_Ring_Cfg Si3226x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 3, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001A668BL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x00435A5AL,	/* RTACTH (37.195 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x051EB82AL,	/* VBATR_EXPECT (80.000 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x028F5C15L,	/* VCM_RING (37.000 v) */

+0x028F5C15L,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x051EB82AL,	/* VBATR_EXPECT (80.000 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x028F5C15L,	/* VCM_RING (37.000 v) */

+0x028F5C15L,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x051EB82AL,	/* VBATR_EXPECT (80.000 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x00,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x028F5C15L,	/* VCM_RING (37.000 v) */

+0x028F5C15L,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3226x_DCfeed_Cfg Si3226x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3226x_Impedance_Cfg Si3226x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3226x_FSK_Cfg Si3226x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3226x_PulseMeter_Cfg Si3226x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3226x_Tone_Cfg Si3226x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x80,			 /* O1TILO (2000 ms) */

+	0x3E			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3226x_PCM_Cfg Si3226x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_MULTI_BOM_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_MULTI_BOM_constants.c
new file mode 100755
index 0000000..f4f78f6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_MULTI_BOM_constants.c
@@ -0,0 +1,927 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-05-20 16:31:58

+**

+** Si3226x ProSLIC API Configuration Tool Version 2.5.0L

+*/

+

+

+#include "proslic.h"

+#include "si3226x.h"

+

+Si3226x_General_Cfg Si3226x_General_Configuration  = {

+0x65,     /* DEVICE_KEY */

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+BO_DCDC_TRACKING,    /* BAT_RAIL_TYPE */

+0x000AD000L,    /* bat_hyst */

+0x08A3D6C8L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x01999A00L,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x00F00000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x00809D80L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00400000L,    /* PD_UVLO */

+0x00400000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00500000L,    /* DCDC_UVHYST */

+0x00000000L,    /* DCDC_UVTHRESH */

+0x01700000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00000000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01000000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04B80200L,    /* UVTHRESH_SCALE */

+0x00823000L     /* UVTHRESH_BIAS */

+};

+

+#ifdef SIVOICE_MULTI_BOM_SUPPORT

+

+int si3226x_genconf_multi_max_preset = 5;

+

+Si3226x_General_Cfg Si3226x_General_Configuration_MultiBOM[] = {

+{

+0x65,     /* DEVICE_KEY */

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+BO_DCDC_TRACKING,    /* BAT_RAIL_TYPE */

+0x000AD000L,    /* bat_hyst */

+0x08A3D6C8L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x01999A00L,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x00F00000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x00809D80L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00400000L,    /* PD_UVLO */

+0x00400000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00500000L,    /* DCDC_UVHYST */

+0x00000000L,    /* DCDC_UVTHRESH */

+0x01700000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00000000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01000000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04B80200L,    /* UVTHRESH_SCALE */

+0x00823000L     /* UVTHRESH_BIAS */

+},

+{

+0x64,     /* DEVICE_KEY */

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+BO_DCDC_TSS,    /* BAT_RAIL_TYPE */

+0x0050C480L,    /* bat_hyst */

+0x06666635L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x00F5C28FL,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x02000000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x0080C480L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00200000L,    /* PD_UVLO */

+0x00300000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00300000L,    /* DCDC_UVHYST */

+0x02100000L,    /* DCDC_UVTHRESH */

+0x00400000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x07700000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x2F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x02200000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04F80200L,    /* UVTHRESH_SCALE */

+0x00A23000L     /* UVTHRESH_BIAS */

+},

+{

+0x64,     /* DEVICE_KEY */

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+BO_DCDC_TSS_ISO,    /* BAT_RAIL_TYPE */

+0x0050C480L,    /* bat_hyst */

+0x06666635L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x00F5C28FL,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x03200000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x0080C480L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00200000L,    /* PD_UVLO */

+0x00300000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00100000L,    /* DCDC_UVHYST */

+0x02100000L,    /* DCDC_UVTHRESH */

+0x00400000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x06F00000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x2F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01B00000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04F80200L,    /* UVTHRESH_SCALE */

+0x00A23000L     /* UVTHRESH_BIAS */

+},

+{

+0x65,     /* DEVICE_KEY */

+BO_DCDC_QCUK,    /* BOM_OPT */

+BO_DCDC_TRACKING,    /* BAT_RAIL_TYPE */

+0x000AD000L,    /* bat_hyst */

+0x08A3D6C8L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x01999A00L,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x00F00000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x00809D80L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00400000L,    /* PD_UVLO */

+0x00400000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00500000L,    /* DCDC_UVHYST */

+0x00000000L,    /* DCDC_UVTHRESH */

+0x01700000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00000000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01000000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04B80200L,    /* UVTHRESH_SCALE */

+0x00823000L     /* UVTHRESH_BIAS */

+},

+{

+0x65,     /* DEVICE_KEY */

+BO_DCDC_LCQCUK,    /* BOM_OPT */

+BO_DCDC_TRACKING,    /* BAT_RAIL_TYPE */

+0x0020C480L,    /* bat_hyst */

+0x051EB82AL,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x01999A00L,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x00F00000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x00809D80L,    /* DCDC_VERR_HYST */

+0x00000000L,    /* DCDC_OITHRESH_LO */

+0x01C00000L,    /* DCDC_OITHRESH_HI */

+0x00400000L,    /* PD_UVLO */

+0x00400000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00500000L,    /* DCDC_UVHYST */

+0x00000000L,    /* DCDC_UVTHRESH */

+0x00500000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00000000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01000000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04B80200L,    /* UVTHRESH_SCALE */

+0x00823000L     /* UVTHRESH_BIAS */

+}

+};

+#endif

+

+Si3226x_GPIO_Cfg Si3226x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3226x_CI_Cfg Si3226x_CI_Presets [] = {

+{0}

+};

+Si3226x_audioGain_Cfg Si3226x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3226x_Ring_Cfg Si3226x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 3, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x002EEF31L,	/* RINGAMP (80.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0077BD13L,	/* RTACTH (66.124 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x088C26FDL,	/* VBATR_EXPECT (133.554 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x0446137EL,	/* VCM_RING (63.777 v) */

+0x0446137EL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x00,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3226x_DCfeed_Cfg Si3226x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3226x_Impedance_Cfg Si3226x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3226x_FSK_Cfg Si3226x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3226x_PulseMeter_Cfg Si3226x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3226x_Tone_Cfg Si3226x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x80,			 /* O1TILO (2000 ms) */

+	0x3E			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3226x_PCM_Cfg Si3226x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_QCUK_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_QCUK_constants.c
new file mode 100755
index 0000000..db72a13
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_QCUK_constants.c
@@ -0,0 +1,604 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-05-20 16:32:50

+**

+** Si3226x ProSLIC API Configuration Tool Version 2.5.0L

+*/

+

+

+#include "proslic.h"

+#include "si3226x.h"

+

+Si3226x_General_Cfg Si3226x_General_Configuration  = {

+0x65,     /* DEVICE_KEY */

+BO_DCDC_QCUK,    /* BOM_OPT */

+BO_DCDC_TRACKING,    /* BAT_RAIL_TYPE */

+0x000AD000L,    /* bat_hyst */

+0x08A3D6C8L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x01999A00L,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x00F00000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x00809D80L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00400000L,    /* PD_UVLO */

+0x00400000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00500000L,    /* DCDC_UVHYST */

+0x00000000L,    /* DCDC_UVTHRESH */

+0x01700000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x00000000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x3F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01000000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04B80200L,    /* UVTHRESH_SCALE */

+0x00823000L     /* UVTHRESH_BIAS */

+};

+

+Si3226x_GPIO_Cfg Si3226x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3226x_CI_Cfg Si3226x_CI_Presets [] = {

+{0}

+};

+Si3226x_audioGain_Cfg Si3226x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3226x_Ring_Cfg Si3226x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 3, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x002EEF31L,	/* RINGAMP (80.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0077BD13L,	/* RTACTH (66.124 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x088C26FDL,	/* VBATR_EXPECT (133.554 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x0446137EL,	/* VCM_RING (63.777 v) */

+0x0446137EL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x00,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3226x_DCfeed_Cfg Si3226x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x0051EB85L,	/* VOV_BAT (5.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3226x_Impedance_Cfg Si3226x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3226x_FSK_Cfg Si3226x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3226x_PulseMeter_Cfg Si3226x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3226x_Tone_Cfg Si3226x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x80,			 /* O1TILO (2000 ms) */

+	0x3E			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3226x_PCM_Cfg Si3226x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_TSS_ISO_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_TSS_ISO_constants.c
new file mode 100755
index 0000000..6bcb17e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_TSS_ISO_constants.c
@@ -0,0 +1,604 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-05-20 16:39:02

+**

+** Si3226x ProSLIC API Configuration Tool Version 2.5.0L

+*/

+

+

+#include "proslic.h"

+#include "si3226x.h"

+

+Si3226x_General_Cfg Si3226x_General_Configuration  = {

+0x64,     /* DEVICE_KEY */

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+BO_DCDC_TSS_ISO,    /* BAT_RAIL_TYPE */

+0x0050C480L,    /* bat_hyst */

+0x06666635L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x00F5C28FL,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x03200000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x0080C480L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00200000L,    /* PD_UVLO */

+0x00300000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00100000L,    /* DCDC_UVHYST */

+0x02100000L,    /* DCDC_UVTHRESH */

+0x00400000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x06F00000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x2F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x01B00000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04F80200L,    /* UVTHRESH_SCALE */

+0x00A23000L     /* UVTHRESH_BIAS */

+};

+

+Si3226x_GPIO_Cfg Si3226x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3226x_CI_Cfg Si3226x_CI_Presets [] = {

+{0}

+};

+Si3226x_audioGain_Cfg Si3226x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3226x_Ring_Cfg Si3226x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x0021C28EL,	/* RINGAMP (55.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x00803A14L,	/* RTACTH (70.811 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x065D2166L,	/* VBATR_EXPECT (99.434 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x032E90B3L,	/* VCM_RING (46.717 v) */

+0x032E90B3L,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x00,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3226x_DCfeed_Cfg Si3226x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x00624DD2L,	/* VOV_BAT (6.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x00624DD2L,	/* VOV_BAT (6.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x00624DD2L,	/* VOV_BAT (6.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x00624DD2L,	/* VOV_BAT (6.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3226x_Impedance_Cfg Si3226x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3226x_FSK_Cfg Si3226x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3226x_PulseMeter_Cfg Si3226x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3226x_Tone_Cfg Si3226x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x80,			 /* O1TILO (2000 ms) */

+	0x3E			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3226x_PCM_Cfg Si3226x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_TSS_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_TSS_constants.c
new file mode 100755
index 0000000..c214303
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_TSS_constants.c
@@ -0,0 +1,604 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-05-20 16:37:35

+**

+** Si3226x ProSLIC API Configuration Tool Version 2.5.0L

+*/

+

+

+#include "proslic.h"

+#include "si3226x.h"

+

+Si3226x_General_Cfg Si3226x_General_Configuration  = {

+0x64,     /* DEVICE_KEY */

+BO_DCDC_FLYBACK,    /* BOM_OPT */

+BO_DCDC_TSS,    /* BAT_RAIL_TYPE */

+0x0050C480L,    /* bat_hyst */

+0x06666635L,    /* VBATR_EXPECT */

+0x03D70A20L,    /* VBATH_EXPECT */

+0x0FFF0000L,    /* PWRSAVE_TIMER */

+0x00F5C28FL,    /* OFFHOOK_THRESH */

+0x00F00000L,    /* VBAT_TRACK_MIN */

+0x02000000L,    /* VBAT_TRACK_MIN_RNG */

+0x00014000L,    /* PWRSAVE_DBI */

+0x0ADD5500L,    /* DCDC_ANA_SCALE */

+0x00312700L,    /* VOV_BAT_PWRSAVE_MIN */

+0x00395800L,    /* VOV_BAT_PWRSAVE_MIN_RNG */

+0x00800000L,    /* THERM_DBI */

+0x00004000L,    /* CPUMP_DBI */

+0x00F18900L,    /* DCDC_VERR */

+0x0080C480L,    /* DCDC_VERR_HYST */

+0x00800000L,    /* DCDC_OITHRESH_LO */

+0x01F00000L,    /* DCDC_OITHRESH_HI */

+0x00200000L,    /* PD_UVLO */

+0x00300000L,    /* PD_OVLO */

+0x00200000L,    /* PD_OCLO */

+0x00400000L,    /* PD_SWDRV */

+0x00300000L,    /* DCDC_UVHYST */

+0x02100000L,    /* DCDC_UVTHRESH */

+0x00400000L,    /* DCDC_OVTHRESH */

+0x00800000L,    /* DCDC_OITHRESH */

+0x00000000L,    /* DCDC_SWDRV_POL */

+0x07700000L,    /* DCDC_UVPOL */

+0x00000000L,    /* DCDC_VREF_MAN */

+0x00000000L,    /* DCDC_VREF_CTRL */

+0x00200000L,    /* DCDC_RNGTYPE */

+0x05B00000L,    /* DCDC_ANA_VREF */

+0x00300000L,    /* DCDC_ANA_GAIN */

+0x00300000L,    /* DCDC_ANA_TOFF */

+0x00100000L,    /* DCDC_ANA_TONMIN */

+0x00FFC000L,    /* DCDC_ANA_TONMAX */

+0x00F00000L,    /* DCDC_ANA_DSHIFT */

+0x0FDA4000L,    /* DCDC_ANA_LPOLY */

+0x00000000L,    /* DCDC_AUX_INVERT */

+0x00400000L,    /* DCDC_CPUMP_LP */

+0x00000000L,    /* DCDC_CPUMP_PULLDOWN */

+0x00000000L,    /* DCDC_LIFT_EN */

+0x07FEB800L,    /* COEF_P_HVIC */

+0x005B05B2L,    /* P_TH_HVIC */

+0x00,     /* CM_CLAMP */

+0x2F,     /* AUTO */

+0x00,     /* IRQEN1 */

+0x00,     /* IRQEN2 */

+0x03,     /* IRQEN3 */

+0x00,     /* IRQEN4 */

+0x10,     /* ENHANCE */

+0x03A2E8BAL,    /* SCALE_KAUDIO */

+0x04,    /* ZCAL_EN */

+0x03000000L,    /* LKG_OFHK_OFFSET */

+0x05000000L,    /* LKG_LB_OFFSET */

+0x02200000L,    /* VBATH_DELTA */

+0x03700000L,    /* UVTHRESH_MAX */

+0x04F80200L,    /* UVTHRESH_SCALE */

+0x00A23000L     /* UVTHRESH_BIAS */

+};

+

+Si3226x_GPIO_Cfg Si3226x_GPIO_Configuration = {

+0x00,     /* GPIO_OE */

+0x06,     /* GPIO_ANA */

+0x00,     /* GPIO_DIR */

+0x00,     /* GPIO_MAN */

+0x00,     /* GPIO_POL */

+0x00,     /* GPIO_OD */

+0x00     /* BATSELMAP */

+};

+Si3226x_CI_Cfg Si3226x_CI_Presets [] = {

+{0}

+};

+Si3226x_audioGain_Cfg Si3226x_audioGain_Presets [] = {

+{0x1377080L,0, 0x0L, 0x0L, 0x0L, 0x0L},

+{0x80C3180L,0, 0x0L, 0x0L, 0x0L, 0x0L}

+};

+

+Si3226x_Ring_Cfg Si3226x_Ring_Presets[] ={

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x0021C28EL,	/* RINGAMP (55.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x00803A14L,	/* RTACTH (70.811 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x065D2166L,	/* VBATR_EXPECT (99.434 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x032E90B3L,	/* VCM_RING (46.717 v) */

+0x032E90B3L,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_MAX_VBAT_PROVISIONING */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = LPR, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x80,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+},  /* RING_F20_45VRMS_0VDC_LPR */

+{

+/*

+	Loop = 500 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms

+	Rprot = 30 ohms, Type = BALANCED, Waveform = SINE

+*/ 

+0x00050000L,	/* RTPER */

+0x07EFE000L,	/* RINGFR (20.000 Hz) */

+0x001B9F2EL,	/* RINGAMP (45.000 vrms)  */

+0x00000000L,	/* RINGPHAS */

+0x00000000L,	/* RINGOF (0.000 vdc) */

+0x15E5200EL,	/* SLOPE_RING (100.000 ohms) */

+0x00D16348L,	/* IRING_LIM (90.000 mA) */

+0x0068E9B4L,	/* RTACTH (57.936 mA) */

+0x0FFFFFFFL,	/* RTDCTH (450.000 mA) */

+0x00006000L,	/* RTACDB (75.000 ms) */

+0x00006000L,	/* RTDCDB (75.000 ms) */

+0x00C49BA0L,	/* VOV_RING_BAT (12.000 v) */

+0x00000000L,	/* VOV_RING_GND (0.000 v) */

+0x0558ABFCL,	/* VBATR_EXPECT (83.537 v) */

+0x80,			/* RINGTALO (2.000 s) */

+0x3E,			/* RINGTAHI */

+0x00,			/* RINGTILO (4.000 s) */

+0x7D,			/* RINGTIHI */

+0x00000000L,	/* ADAP_RING_MIN_I */

+0x00003000L,	/* COUNTER_IRING_VAL */

+0x00051EB8L,	/* COUNTER_VTR_VAL */

+0x00000000L,	/* CONST_028 */

+0x00000000L,	/* CONST_032 */

+0x00000000L,	/* CONST_038 */

+0x00000000L,	/* CONST_046 */

+0x00000000L,	/* RRD_DELAY */

+0x00000000L,	/* RRD_DELAY2 */

+0x01893740L,	/* VBAT_TRACK_MIN_RNG */

+0x00,			/* RINGCON */

+0x00,			/* USERSTAT */

+0x02AC55FEL,	/* VCM_RING (38.769 v) */

+0x02AC55FEL,	/* VCM_RING_FIXED */

+0x003126E8L,	/* DELTA_VCM */

+0x00200000L,	/* DCDC_RNGTYPE */

+0x00FFFFFFL,	/* VOV_DCDC_SLOPE */

+0x0083126AL,	/* VOV_DCDC_OS */

+0x009374B8L,	/* VOV_RING_BAT_MAX */

+}    /* RING_F20_45VRMS_0VDC_BAL */

+};

+

+Si3226x_DCfeed_Cfg Si3226x_DCfeed_Presets[] = {

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1F909679L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1D5B21A9L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x00B4F3C3L,	/* CONST_RFEED (15.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x00624DD2L,	/* VOV_BAT (6.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_20MA */

+{

+0x1C8A024CL,	/* SLOPE_VLIM */

+0x1EE08C11L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C940D71L,	/* SLOPE_DELTA1 */

+0x1DD87A3EL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x050D2839L,	/* V_RFEED (43.000 v) */

+0x03FE7F0FL,	/* V_ILIM  (34.000 v) */

+0x01241BC9L,	/* CONST_RFEED (15.000 mA) */

+0x0074538FL,	/* CONST_ILIM (25.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x00624DD2L,	/* VOV_BAT (6.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_48V_25MA */

+{

+0x1E655196L,	/* SLOPE_VLIM */

+0x001904EFL,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1B4CAD9EL,	/* SLOPE_DELTA1 */

+0x1BB0F47CL,	/* SLOPE_DELTA2 */

+0x05A38633L,	/* V_VLIM (48.000 v) */

+0x043AA4A6L,	/* V_RFEED (36.000 v) */

+0x025977EAL,	/* V_ILIM  (20.000 v) */

+0x0068B19AL,	/* CONST_RFEED (18.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x002D8D96L,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x00624DD2L,	/* VOV_BAT (6.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+},  /* DCFEED_PSTN_DET_1 */

+{

+0x1A10433FL,	/* SLOPE_VLIM */

+0x1C206275L,	/* SLOPE_RFEED */

+0x0040A0E0L,	/* SLOPE_ILIM */

+0x1C1F426FL,	/* SLOPE_DELTA1 */

+0x1EB51625L,	/* SLOPE_DELTA2 */

+0x041C91DBL,	/* V_VLIM (35.000 v) */

+0x03E06C43L,	/* V_RFEED (33.000 v) */

+0x038633E0L,	/* V_ILIM  (30.000 v) */

+0x022E5DE5L,	/* CONST_RFEED (10.000 mA) */

+0x005D0FA6L,	/* CONST_ILIM (20.000 mA) */

+0x0021373DL,	/* I_VLIM (0.000 mA) */

+0x005B0AFBL,	/* LCRONHK (10.000 mA) */

+0x006D4060L,	/* LCROFFHK (12.000 mA) */

+0x00008000L,	/* LCRDBI (5.000 ms) */

+0x0048D595L,	/* LONGHITH (8.000 mA) */

+0x003FBAE2L,	/* LONGLOTH (7.000 mA) */

+0x00008000L,	/* LONGDBI (5.000 ms) */

+0x000F0000L,	/* LCRMASK (150.000 ms) */

+0x00080000L,	/* LCRMASK_POLREV (80.000 ms) */

+0x00140000L,	/* LCRMASK_STATE (200.000 ms) */

+0x00140000L,	/* LCRMASK_LINECAP (200.000 ms) */

+0x01BA5E35L,	/* VCM_OH (27.000 v) */

+0x00624DD2L,	/* VOV_BAT (6.000 v) */

+0x00418937L,	/* VOV_GND (4.000 v) */

+}    /* DCFEED_PSTN_DET_2 */

+};

+

+Si3226x_Impedance_Cfg Si3226x_Impedance_Presets[] ={

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_0_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=270_750_150 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x0715CB80L, 0x1FD56880L, 0x000D4480L, 0x1FFEAE00L,    /* TXACEQ */

+ 0x0A834F80L, 0x1BA7E500L, 0x0080D300L, 0x1FDC1580L},   /* RXACEQ */

+{0x0017A080L, 0x1FDE3600L, 0x0129F900L, 0x01915280L,    /* ECFIR/ECIIR */

+ 0x01434280L, 0x018E9E00L, 0x1FFE1200L, 0x0085E000L,

+ 0x001ECE80L, 0x1FDF3C80L, 0x0CC9EA00L, 0x1B2E1180L},

+{0x00C66800L, 0x1DD9CB80L, 0x015F8F00L, 0x0CB97F00L,    /* ZSYNTH */

+ 0x1B44F480L, 0x94}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0108FB80L,   /* RXACGAIN */

+ 0x07BB6980L, 0x18449700L, 0x0776D380L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_270_750_150_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=370_620_310 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07E59E80L, 0x1FD33400L, 0x1FFDF800L, 0x1FFD8300L,    /* TXACEQ */

+ 0x09F38000L, 0x1C1C5A00L, 0x1F94D700L, 0x1FDE5800L},   /* RXACEQ */

+{0x00234480L, 0x1F9CDD00L, 0x01F5D580L, 0x1FF39000L,    /* ECFIR/ECIIR */

+ 0x02C17180L, 0x1FBE2500L, 0x00DFFE80L, 0x00441A80L,

+ 0x003BF800L, 0x1FC42400L, 0x0D9EB380L, 0x1A514580L},

+{0x003ED200L, 0x1F5D6B80L, 0x0063B100L, 0x0F12E200L,    /* ZSYNTH */

+ 0x18EC9380L, 0x8B}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x0127C700L,   /* RXACGAIN */

+ 0x07B51200L, 0x184AEE80L, 0x076A2480L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_370_620_310_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_120 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06E2A580L, 0x1FD1DF80L, 0x00068880L, 0x1FFCE200L,    /* TXACEQ */

+ 0x0A7AFB00L, 0x1BC11F80L, 0x009C4E80L, 0x1FD60300L},   /* RXACEQ */

+{0x002C9880L, 0x1F530400L, 0x02CF4D80L, 0x1E895880L,    /* ECFIR/ECIIR */

+ 0x055F7200L, 0x1E034600L, 0x023B9080L, 0x1FB01780L,

+ 0x00339380L, 0x1FC98F80L, 0x0B7EA900L, 0x1C760400L},

+{0x022C8200L, 0x1A9F3E80L, 0x03332100L, 0x0A0D4700L,    /* ZSYNTH */

+ 0x1DEBC480L, 0x8D}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01013A80L,   /* RXACGAIN */

+ 0x07BEF980L, 0x18410700L, 0x077DF280L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_220_820_120_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=600_0_0 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07F46C00L, 0x000E4600L, 0x00008580L, 0x1FFD6100L,    /* TXACEQ */

+ 0x07EF5000L, 0x0013F580L, 0x1FFDE000L, 0x1FFCB280L},   /* RXACEQ */

+{0x0027CB00L, 0x1F8A8880L, 0x02801180L, 0x1F625C80L,    /* ECFIR/ECIIR */

+ 0x0314FB00L, 0x1E6B8E80L, 0x00C5FF00L, 0x1FC96F00L,

+ 0x1FFD1200L, 0x00023C00L, 0x0ED29D00L, 0x192A9400L},

+{0x00810E00L, 0x1EFEBE80L, 0x00803500L, 0x0FF66D00L,    /* ZSYNTH */

+ 0x18099080L, 0x59}, 

+ 0x088E0D80L,   /* TXACGAIN */

+ 0x01456D80L,   /* RXACGAIN */

+ 0x07ABE580L, 0x18541B00L, 0x0757CB00L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_600_0_1000_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=200_680_100 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x07365D80L, 0x1FC64180L, 0x00022980L, 0x1FFCE300L,    /* TXACEQ */

+ 0x09C28580L, 0x1D1FD880L, 0x0071A280L, 0x1FDF7500L},   /* RXACEQ */

+{0x1FF15A00L, 0x005C0600L, 0x00828200L, 0x01B11D00L,    /* ECFIR/ECIIR */

+ 0x027BB800L, 0x1EE9F200L, 0x028BAB80L, 0x1E57BE80L,

+ 0x01007580L, 0x1EF8B780L, 0x0556EE80L, 0x028DFB80L},

+{0x014F2C00L, 0x1C7A1180L, 0x02369A00L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0x8E}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x010C7E80L,   /* RXACGAIN */

+ 0x07BB2500L, 0x1844DB80L, 0x07764980L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ },  /* ZSYN_200_680_100_30_0 */

+/* Source: Database file: cwdb.db */

+/* Database information: */

+/* parameters: zref=220_820_115 rprot=30 rfuse=0 emi_cap=10*/

+{

+{0x06D56400L, 0x1FDF1780L, 0x00095A80L, 0x1FFDA880L,    /* TXACEQ */

+ 0x0A596300L, 0x1C067880L, 0x0095EF00L, 0x1FD7AF00L},   /* RXACEQ */

+{0x00164300L, 0x1FD81880L, 0x0150CC80L, 0x0151BB80L,    /* ECFIR/ECIIR */

+ 0x01DA1A00L, 0x0142CB80L, 0x0027DE80L, 0x0076A180L,

+ 0x0012F980L, 0x1FEAE000L, 0x0CC70C80L, 0x1B2DF000L},

+{0x00246300L, 0x1E5E0580L, 0x017D2300L, 0x0A138100L,    /* ZSYNTH */

+ 0x1DEA2280L, 0xA7}, 

+ 0x08000000L,   /* TXACGAIN */

+ 0x01009500L,   /* RXACGAIN */

+ 0x07BBEE80L, 0x18441200L, 0x0777DD80L,    /* RXACHPF */

+ 0, 0  /* TXGAIN, RXGAIN */

+ }    /* ZSYN_220_820_115_30_0 */

+};

+

+Si3226x_FSK_Cfg Si3226x_FSK_Presets[] ={

+/* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+{

+0x02232000L,	 /* FSK01 */

+0x077C2000L,	 /* FSK10 */

+0x003C0000L,	 /* FSKAMP0 */

+0x00200000L,	 /* FSKAMP1 */

+0x06B60000L,	 /* FSKFREQ0 */

+0x079C0000L,	 /* FSKFREQ1 */

+0x00,			 /* FSK8 */

+0x00,			 /* FSKDEPTH */

+}    /* DEFAULT_FSK */

+};

+

+Si3226x_PulseMeter_Cfg Si3226x_PulseMeter_Presets[] ={

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }    /* DEFAULT_PULSE_METERING */

+};

+

+Si3226x_Tone_Cfg Si3226x_Tone_Presets[] = {

+{

+	{

+	0x07B30000L,	 /* OSC1FREQ (350.000 Hz) */

+	0x000C6000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x00,			 /* O1TALO (0 ms) */

+	0x00,			 /* O1TAHI */

+	0x00,			 /* O1TILO (0 ms) */

+	0x00			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x00,			 /* O2TALO (0 ms) */

+	0x00,			 /* O2TAHI */

+	0x00,			 /* O2TILO (0 ms) */

+	0x00 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_DIAL */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0xA0,			 /* O1TALO (500 ms) */

+	0x0F,			 /* O1TAHI */

+	0xA0,			 /* O1TILO (500 ms) */

+	0x0F			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0xA0,			 /* O2TALO (500 ms) */

+	0x0F,			 /* O2TAHI */

+	0xA0,			 /* O2TILO (500 ms) */

+	0x0F 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_BUSY */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x80,			 /* O1TALO (2000 ms) */

+	0x3E,			 /* O1TAHI */

+	0x80,			 /* O1TILO (2000 ms) */

+	0x3E			 /* O1TIHI */

+	},

+	{

+	0x07870000L,	 /* OSC2FREQ (440.000 Hz) */

+	0x000FA000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x80,			 /* O2TALO (2000 ms) */

+	0x3E,			 /* O2TAHI */

+	0x00,			 /* O2TILO (4000 ms) */

+	0x7D 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_RINGBACK */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x60,			 /* O1TALO (300 ms) */

+	0x09,			 /* O1TAHI */

+	0x60,			 /* O1TILO (300 ms) */

+	0x09			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x60,			 /* O2TALO (300 ms) */

+	0x09,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+},  /* TONEGEN_FCC_REORDER */

+{

+	{

+	0x07700000L,	 /* OSC1FREQ (480.000 Hz) */

+	0x00112000L,	 /* OSC1AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC1PHAS (0.000 rad) */

+	0x40,			 /* O1TALO (200 ms) */

+	0x06,			 /* O1TAHI */

+	0x40,			 /* O1TILO (200 ms) */

+	0x06			 /* O1TIHI */

+	},

+	{

+	0x07120000L,	 /* OSC2FREQ (620.000 Hz) */

+	0x00164000L,	 /* OSC2AMP (-18.000 dBm) */

+	0x00000000L,	 /* OSC2PHAS (0.000 rad) */

+	0x40,			 /* O2TALO (200 ms) */

+	0x06,			 /* O2TAHI */

+	0x40,			 /* O2TILO (200 ms) */

+	0x06 			 /* O2TIHI */

+	},

+	0x66 			 /* OMODE */

+}    /* TONEGEN_FCC_CONGESTION */

+};

+

+Si3226x_PCM_Cfg Si3226x_PCM_Presets[] ={

+	{

+	0x01, 	 /* PCM_FMT - u-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ULAW */

+	{

+	0x00, 	 /* PCM_FMT - A-Law */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_8ALAW */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x00, 	 /* WIDEBAND - DISABLED (3.4kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	},  /* PCM_16LIN */

+	{

+	0x03, 	 /* PCM_FMT - 16-bit Linear */

+	0x01, 	 /* WIDEBAND - ENABLED (7kHz BW) */

+	0x00, 	 /* PCM_TRI - PCLK RISING EDGE */

+	0x00, 	 /* TX_EDGE - PCLK RISING EDGE */

+	0x00 	 /* A-LAW -  INVERT NONE */

+	}    /* PCM_16LIN_WB */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_constants.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_constants.h
new file mode 100755
index 0000000..8f2bc1e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_constants.h
@@ -0,0 +1,74 @@
+/*

+** Copyright (c) 2010 Silicon Laboratories, Inc.

+** 2010-05-11 15:21:11

+**

+** Si3226x ProSLIC API Configuration Tool Version 1.10L

+*/

+

+

+#ifndef SI3226X_CONSTANTS_H

+#define SI3226X_CONSTANTS_H

+

+/** Ringing Presets */

+enum {

+	RING_MAX_VBAT_PROVISIONING,

+	RING_F20_45VRMS_0VDC_LPR,

+	RING_F20_45VRMS_0VDC_BAL

+};

+

+/** DC_Feed Presets */

+enum {

+	DCFEED_48V_20MA,

+	DCFEED_48V_25MA,

+	DCFEED_PSTN_DET_1,

+	DCFEED_PSTN_DET_2

+};

+

+/** Impedance Presets */

+enum {

+	ZSYN_600_0_0_30_0,

+	ZSYN_270_750_150_30_0,

+	ZSYN_370_620_310_30_0,

+	ZSYN_220_820_120_30_0,

+	ZSYN_600_0_1000_30_0,

+	ZSYN_200_680_100_30_0,

+	ZSYN_220_820_115_30_0

+};

+

+/** FSK Presets */

+enum {

+	DEFAULT_FSK

+};

+

+/** Pulse_Metering Presets */

+enum {

+	DEFAULT_PULSE_METERING

+};

+

+/** Tone Presets */

+enum {

+	TONEGEN_FCC_DIAL,

+	TONEGEN_FCC_BUSY,

+	TONEGEN_FCC_RINGBACK,

+	TONEGEN_FCC_REORDER,

+	TONEGEN_FCC_CONGESTION

+};

+

+/** PCM Presets */

+enum {

+	PCM_8ULAW,

+	PCM_8ALAW,

+	PCM_16LIN,

+	PCM_16LIN_WB

+};

+

+/** Multiple General Parameter Options */

+enum {

+      GEN_PARAM_FLYBACK,

+      GEN_PARAM_TSS,

+      GEN_PARAM_TSS_ISO

+};

+

+

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_B_FB_2010SEP22.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_B_FB_2010SEP22.c
new file mode 100755
index 0000000..14b4bc5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_B_FB_2010SEP22.c
@@ -0,0 +1,217 @@
+/*
+** Generated from si3226x_patch_B_FB_2010SEP22.dsp_prom
+** on 09-24-2010 at 8:12:53
+*/
+#include "si_voice_datatypes.h"
+#include "si3226x.h"
+
+static const uInt32 patchData [] = {
+141541L,
+540867L,
+141541L,
+543427L,
+141541L,
+544451L,
+141541L,
+545987L,
+141541L,
+553667L,
+141541L,
+561347L,
+141541L,
+569027L,
+141541L,
+576707L,
+141541L,
+601283L,
+141541L,
+606915L,
+141541L,
+607427L,
+141541L,
+607939L,
+141541L,
+608451L,
+141541L,
+608963L,
+141541L,
+609475L,
+141541L,
+609987L,
+736L,
+491712L,
+452200L,
+141541L,
+491200L,
+141541L,
+633536L,
+524305L,
+141541L,
+622785L,
+747621L,
+521314L,
+748131L,
+747522L,
+521317L,
+748643L,
+748034L,
+521317L,
+749155L,
+748546L,
+521317L,
+524291L,
+749061L,
+141541L,
+642754L,
+747621L,
+521314L,
+748132L,
+747522L,
+521317L,
+748644L,
+748034L,
+521317L,
+749156L,
+748546L,
+521317L,
+524292L,
+749061L,
+141541L,
+824002L,
+747621L,
+520802L,
+748132L,
+747522L,
+520805L,
+748644L,
+748034L,
+520805L,
+749156L,
+748546L,
+520805L,
+524292L,
+749061L,
+141541L,
+521921L,
+747621L,
+520802L,
+748131L,
+747522L,
+520805L,
+748643L,
+748034L,
+520805L,
+749155L,
+748546L,
+520805L,
+524291L,
+749061L,
+141541L,
+531649L,
+471138L,
+17637L,
+578755L,
+470629L,
+524292L,
+142565L,
+580803L,
+188485L,
+588005L,
+729793L,
+843365L,
+188002L,
+843355L,
+145125L,
+584899L,
+524290L,
+660069L,
+523685L,
+523880L,
+524292L,
+142565L,
+588483L,
+524288L,
+522341L,
+17637L,
+597187L,
+101093L,
+597187L,
+628453L,
+594627L,
+597733L,
+594627L,
+524291L,
+141541L,
+597187L,
+628965L,
+597187L,
+550117L,
+597187L,
+524291L,
+522853L,
+524315L,
+147173L,
+599747L,
+524290L,
+791557L,
+141541L,
+729793L,
+3682L,
+71909L,
+604867L,
+524292L,
+5L,
+141541L,
+134338L,
+524291L,
+5L,
+141541L,
+134338L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+950,
+1234,
+3263,
+5350,
+5704,
+3066,
+3085,
+3464,
+4345,
+0,
+0,
+0,
+0,
+0,
+0,
+0
+};
+
+static const uInt16 patchSupportAddr [] = {
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3226xPatchRevBFlbk = {
+#else
+const proslicPatch RevBPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x09242010L,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_FB_2011MAY19.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_FB_2011MAY19.c
new file mode 100755
index 0000000..6dca994
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_FB_2011MAY19.c
@@ -0,0 +1,185 @@
+/*
+** Generated from si3226x_patch_C_FB_2011MAY19.dsp_prom
+** Based on design file si32260C_firmware_1_0_0_4_20110517
+** on 05-19-2011 at 14:58:49
+** Patch ID = 0x1004C000
+*/
+#include "si_voice_datatypes.h"
+#include "si3226x.h"
+
+static const uInt32 patchData [] = {
+141541L,
+540867L,
+141541L,
+543427L,
+141541L,
+553155L,
+141541L,
+577731L,
+141541L,
+579779L,
+141541L,
+581315L,
+141541L,
+581827L,
+141541L,
+582339L,
+141541L,
+582851L,
+141541L,
+583363L,
+141541L,
+583875L,
+141541L,
+584387L,
+141541L,
+584899L,
+141541L,
+585411L,
+141541L,
+585923L,
+141541L,
+586435L,
+736L,
+491712L,
+452200L,
+141541L,
+491200L,
+5733L,
+524290L,
+142565L,
+550083L,
+3685L,
+519266L,
+5220L,
+144098L,
+550083L,
+3685L,
+524291L,
+141541L,
+551619L,
+5221L,
+3682L,
+524292L,
+5L,
+141541L,
+135362L,
+98021L,
+727745L,
+474213L,
+17637L,
+557251L,
+101093L,
+557251L,
+473701L,
+515653L,
+843365L,
+188002L,
+843355L,
+145125L,
+560835L,
+524290L,
+660069L,
+518053L,
+517224L,
+518244L,
+142565L,
+564419L,
+524288L,
+521733L,
+843365L,
+188002L,
+524315L,
+145125L,
+568003L,
+843365L,
+522850L,
+523387L,
+147685L,
+573123L,
+522363L,
+145125L,
+575171L,
+521826L,
+141541L,
+575683L,
+518757L,
+521826L,
+141541L,
+575683L,
+521824L,
+522245L,
+522338L,
+141541L,
+716481L,
+173669L,
+523845L,
+141541L,
+730304L,
+523877L,
+141541L,
+690368L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+950,
+4347,
+3431,
+1425,
+1347,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
+};
+
+static const uInt16 patchSupportAddr [] = {
+925,
+926,
+1014,
+1020,
+1021,
+1022,
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0xA00000L,
+0x1F00000L,
+0x2D8000L,
+0x0L,
+0x1A9FBDAL,
+0x1C28F4EL,
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3226xPatchRevCFlbk = {
+#else
+const proslicPatch RevCPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x1004C000,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_TSS_2011MAY19.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_TSS_2011MAY19.c
new file mode 100755
index 0000000..82944b5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_TSS_2011MAY19.c
@@ -0,0 +1,185 @@
+/*
+** Generated from si3226x_patch_C_TSS_2011MAY19.dsp_prom
+** Based on design file si32260C_firmware_1_0_0_4_20110517
+** on 05-19-2011 at 15:3:35
+** Patch ID = 0x1004C001
+*/
+#include "si_voice_datatypes.h"
+#include "si3226x.h"
+
+static const uInt32 patchData [] = {
+141541L,
+540867L,
+141541L,
+543427L,
+141541L,
+553155L,
+141541L,
+577731L,
+141541L,
+579779L,
+141541L,
+581315L,
+141541L,
+581827L,
+141541L,
+582339L,
+141541L,
+582851L,
+141541L,
+583363L,
+141541L,
+583875L,
+141541L,
+584387L,
+141541L,
+584899L,
+141541L,
+585411L,
+141541L,
+585923L,
+141541L,
+586435L,
+736L,
+491712L,
+452200L,
+141541L,
+491200L,
+5733L,
+524290L,
+142565L,
+550083L,
+3685L,
+519266L,
+5220L,
+144098L,
+550083L,
+3685L,
+524291L,
+141541L,
+551619L,
+5221L,
+3682L,
+524292L,
+5L,
+141541L,
+135362L,
+98021L,
+727745L,
+474213L,
+17637L,
+557251L,
+101093L,
+557251L,
+473701L,
+515653L,
+843365L,
+188002L,
+843355L,
+145125L,
+560835L,
+524290L,
+660069L,
+518053L,
+517224L,
+518244L,
+142565L,
+564419L,
+524288L,
+521733L,
+843365L,
+188002L,
+524315L,
+145125L,
+568003L,
+843365L,
+522850L,
+523387L,
+147685L,
+573123L,
+522363L,
+145125L,
+575171L,
+521826L,
+141541L,
+575683L,
+518757L,
+521826L,
+141541L,
+575683L,
+521824L,
+522245L,
+522338L,
+141541L,
+716481L,
+173669L,
+523845L,
+141541L,
+730304L,
+523877L,
+141541L,
+690368L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+950,
+4347,
+3431,
+1425,
+1347,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
+};
+
+static const uInt16 patchSupportAddr [] = {
+925,
+926,
+1014,
+1020,
+1021,
+1022,
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0xA00000L,
+0x1F00000L,
+0x2D8000L,
+0x0L,
+0x1A9FBDAL,
+0x1C28F4EL,
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3226xPatchRevCTss = {
+#else
+const proslicPatch RevCPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x1004C001,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_TSS_ISO_2011MAY19.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_TSS_ISO_2011MAY19.c
new file mode 100755
index 0000000..81ab27a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si3226x_patch_C_TSS_ISO_2011MAY19.c
@@ -0,0 +1,185 @@
+/*
+** Generated from si3226x_patch_C_TSS_ISO_2011MAY19.dsp_prom
+** Based on design file si32260C_firmware_1_0_0_4_20110517
+** on 05-19-2011 at 15:14:22
+** Patch ID = 0x1004C002
+*/
+#include "si_voice_datatypes.h"
+#include "si3226x.h"
+
+static const uInt32 patchData [] = {
+141541L,
+540867L,
+141541L,
+543427L,
+141541L,
+553155L,
+141541L,
+577731L,
+141541L,
+579779L,
+141541L,
+581315L,
+141541L,
+581827L,
+141541L,
+582339L,
+141541L,
+582851L,
+141541L,
+583363L,
+141541L,
+583875L,
+141541L,
+584387L,
+141541L,
+584899L,
+141541L,
+585411L,
+141541L,
+585923L,
+141541L,
+586435L,
+736L,
+491712L,
+452200L,
+141541L,
+491200L,
+5733L,
+524290L,
+142565L,
+550083L,
+3685L,
+519266L,
+5220L,
+144098L,
+550083L,
+3685L,
+524291L,
+141541L,
+551619L,
+5221L,
+3682L,
+524292L,
+5L,
+141541L,
+135362L,
+98021L,
+727745L,
+474213L,
+17637L,
+557251L,
+101093L,
+557251L,
+473701L,
+515653L,
+843365L,
+188002L,
+843355L,
+145125L,
+560835L,
+524290L,
+660069L,
+518053L,
+517224L,
+518244L,
+142565L,
+564419L,
+524288L,
+521733L,
+843365L,
+188002L,
+524315L,
+145125L,
+568003L,
+843365L,
+522850L,
+523387L,
+147685L,
+573123L,
+522363L,
+145125L,
+575171L,
+521826L,
+141541L,
+575683L,
+518757L,
+521826L,
+141541L,
+575683L,
+521824L,
+522245L,
+522338L,
+141541L,
+716481L,
+173669L,
+523845L,
+141541L,
+730304L,
+523877L,
+141541L,
+690368L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+524293L,
+0L
+};
+
+static const uInt16 patchEntries [] = {
+950,
+4347,
+3431,
+1425,
+1347,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
+};
+
+static const uInt16 patchSupportAddr [] = {
+925,
+926,
+1014,
+1020,
+1021,
+1022,
+0
+};
+
+static const uInt32 patchSupportData [] = {
+0xA00000L,
+0x1F00000L,
+0x2D8000L,
+0x0L,
+0x2075F60L,
+0x220335BL,
+0x0L
+};
+
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+const proslicPatch si3226xPatchRevCTssIso = {
+#else
+const proslicPatch RevCPatch = {
+#endif
+    patchData,
+    patchEntries,
+    0x1004C002,
+    patchSupportAddr,
+    patchSupportData
+};
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_constants.c
new file mode 100755
index 0000000..b56f5cb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_constants.c
@@ -0,0 +1,111 @@
+/*

+Copyright (c) 2008 Silicon Laboratories, Inc.

+2008-03-26 19:05:19 */

+/*ProSLIC API Tool Rev0.31 Beta*/

+

+

+#include "proslic.h"

+#include "si324x.h"

+Si324x_General_Cfg Si324x_General_Configuration  = {

+0x8F5C24AL, /*vbatr_expect - CUSTOM = 140.00, nom = 95.000*/

+0x7FD710CL, /*coeff_p_hvic = 1.000*/

+0x2468ADL, /*p_th_hvic = 1000.000*/

+0x353F7B5L, /*vbath_expect - CUSTOM = 52.00 , nom = 75.000*/

+0x0, /*cm_clamp = 0.000*/

+0x3F, /*auto = 0.000*/

+0x640000L, /*cm_dbi = 100.000*/

+0x3C0000L, /*bat_dbi = 60.000*/

+0x20C49AL, /*bat_hyst = 2.000*/

+0x10000L, /*bat_settle = 1.000*/

+0x42, /*batselmap - CUSTOM - nom 0x46 */

+0x7FD710CL, /*coef_p_offld = 1.000*/

+#ifdef NO_VBATL

+0x6, /*offld */

+#else

+0x7, /*offld*/

+#endif

+0x48D15BL, /*p_th_offld = 2000.000*/

+0x199998DL, /*vbatl_expect = 25.000*/

+0xff,     /* irqen1 */

+0xff,	  /* irqen2 */

+0xff,     /* irqen3 */

+0x00      /* irqen4 */

+};

+

+Si324x_DTMFDec_Cfg Si324x_DTMFDec_Presets[] = {

+	{0x2d40000L,0x1a660000L,0x2d40000L,0x6ba0000L,0x1dcc0000L,0x33f0000L,0xbd30000L,0x19d20000L,0x4150000L,0x188F0000L,0x4150000L,0xd970000L,0x18620000L,0xf1c0000L}

+};

+Si324x_GPIO_Cfg Si324x_GPIO_Configuration = {

+	0x0, 0x0, 0x0,0x0,0x0,0x0

+};

+Si324x_CI_Cfg Si324x_CI_Presets [] = {

+	{0}

+};

+Si324x_audioGain_Cfg Si324x_audioGain_Presets [] = {

+	{0x1377080L,0},

+	{0x80C3180L,0}

+};

+

+Si324x_Ring_Cfg Si324x_Ring_Presets[] ={

+

+

+    /* inputs:  ringtrip ac thresh = 450.000, dc_thresh = 10.000, rt debounce = 0.075, vov_ring_gnd = 7.000, vov_ring_bat = 10.000*/

+    { 0x7EFE000L, 0x1BA000L, 0x1EB3154L, 0x0L, 0x50000L, 0x80, 0x3E, 0x0, 0x7D, 0x58, 0x800000L, 0xC84B5BL, 0xF5E5200EL, 0x0L, 0x0L, 0x51EB8L, 0x6000L, 0x32EDF9EL, 0x6000L, 0x1C71ECL, 0xA3D70AL, 0x72B020L, 0x4CCCCCCL }

+};

+

+Si324x_DCfeed_Cfg Si324x_DCfeed_Presets[] = {

+

+    /* inputs: v_vlim=48.000, i_vlim=0.000, v_rfeed=42.800, i_rfeed=10.000,v_ilim=33.200, i_ilim=20.000,

+ vcm_oh=27.000, vov_gnd=4.000, vov_bat=4.000, r_ring=320.000

+ lcronhk=10.000, lcroffhk=12.000, lcrdbi=5.000, longhith=8.000, longloth=7.000, longdbi=5.000

+ lcrmask=80.000, lcrmask_polrev=80.000, lcrmask_state=200.000, lcrmask_linecap=200.000 */

+    { 0x1DDF41C9L, 0x1EF68D5EL, 0x40A0E0L, 0x18AAD168L, 0x1CA39FFAL, 0x5A38633L, 0x5072476L, 0x3E67006L, 0xFDFAB5L, 0x5D0FA6L, 0x2D8D96L, 0x5B0AFBL, 0x6D4060L, 0x8000L, 0x48D595L, 0x3FBAE2L, 0x8000L, 0x80000L, 0x80000L, 0x140000L, 0x140000L, 0x1BA5E35L, 0x418937L, 0x418937L  }

+};

+

+Si324x_Impedance_Cfg Si324x_Impedance_Presets[] = {   /* Default - 600ohms, 30ohm RPROT */

+{

+  {0x08044B00L,0x1FF9F000L,0x00052600L,0x1FFE2280L, /* TXACEQ */

+   0x07FECB00L,0x1FF9AC80L,0x00029900L,0x1FFB1100L}, /* RXACEQ */

+  {0x00209A80L,0x1FB0B880L,0x02090000L,0x001CE380L,  /* ECFIR/ECIIR */

+   0x0238AF80L,0x1F2E0E00L,0x005CC480L,0x1FED2680L,

+   0x1FF6DB00L,0x00035580L,0x0256D200L,0x05866B80L},  

+  {0x00207500L,0x1FD16580L,0x000E5C00L,0x0A138100L, /* ZSYNTH */

+   0x1DEA2280L,0x6E},  

+  {0x08769F00L,0x00}, /* TXACGAIN/MUTE */

+  {0x01454B00L,0x00}, /* RXACGAIN/MUTE */ 

+   0x07B3DA80L,0x184C2600L,0x0767B500L}  /* RXHPF */

+};

+

+

+Si324x_FSK_Cfg Si324x_FSK_Presets[] ={

+

+    /* inputs: mark freq=1200.000, space freq2200.000, amp=0.220, baud=1200.000, startStopDis=0, interrupt depth = 0 */

+    { 0x2232000L, 0x77C2000L, 0x3C0000L, 0x200000L, 0x6B60000L, 0x79C0000L,0, 0 }

+};

+

+Si324x_PulseMeter_Cfg Si324x_PulseMeter_Presets[] ={

+

+    /* inputs:  freq = 12kHz, amp = 1.000Vrms, cal = First, ramp = 24kHz, power = Normal */

+    { 0x7A2B6AL, 0x0, 0x0 }

+};

+

+Si324x_Tone_Cfg Si324x_Tone_Presets[] ={

+

+    /* inputs:  freq1 = 350.000, amp1 = -18.000, freq2 = 440.000, amp2 = -18.000, ta1 = 0.000, ti1 = 0.000, ta2 = 0.000, ti2 = 0.000*/

+    { {0x7B30000L, 0x3A000L, 0x0L, 0x0, 0x0, 0x0, 0x0}, {0x7870000L, 0x4A000L, 0x0L, 0x0, 0x0, 0x0, 0x0}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.500, ti1 = 0.500, ta2 = 0.500, ti2 = 0.500*/

+    { {0x7700000L, 0x52000L, 0x0L, 0xA0, 0xF, 0xA0, 0xF}, {0x7120000L, 0x6A000L, 0x0L, 0xA0, 0xF, 0xA0, 0xF}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 440.000, amp2 = -18.000, ta1 = 2.000, ti1 = 4.000, ta2 = 2.000, ti2 = 4.000*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x80, 0x3E, 0x0, 0x7D}, {0x7870000L, 0x4A000L, 0x0L, 0x80, 0x3E, 0x0, 0x7D}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.300, ti1 = 0.200, ta2 = 0.300, ti2 = 0.200*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x60, 0x9, 0x40, 0x6}, {0x7120000L, 0x6A000L, 0x0L, 0x60, 0x9, 0x40, 0x6}, 0x66 },

+    /* inputs:  freq1 = 480.000, amp1 = -18.000, freq2 = 620.000, amp2 = -18.000, ta1 = 0.200, ti1 = 0.200, ta2 = 0.200, ti2 = 0.200*/

+    { {0x7700000L, 0x52000L, 0x0L, 0x40, 0x6, 0x40, 0x6}, {0x7120000L, 0x6A000L, 0x0L, 0x40, 0x6, 0x40, 0x6}, 0x66 }

+};

+

+Si324x_PCM_Cfg Si324x_PCM_Presets[] ={

+

+    /* inputs:  u-law narrowband positive edge, dtx positive edge, both disabled, tx hwy = A, rx hwy = A */

+    { 0x1, 0x0, 0x0, 0x0 }

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_constants.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_constants.h
new file mode 100755
index 0000000..888157e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_constants.h
@@ -0,0 +1,42 @@
+/*

+Copyright (c) 2008 Silicon Laboratories, Inc.

+2008-03-26 19:05:19 */

+/*ProSLIC API Tool Rev0.31 Beta*/

+

+

+enum {

+	USA_DEFAULT_RING

+};

+

+enum {

+	DEFAULT_DC_FEED

+};

+

+enum {

+	DEFAULT_IMPEDANCE

+};

+

+enum {

+	DEFAULT_FSK

+};

+

+enum {

+	DEFAULT_PULSE_METERING

+};

+

+enum {

+	USA_DIAL_TONE,

+	USA_BUSY_TONE,

+	USA_RINGBACK_TONE,

+	USA_REORDER_TONE,

+	USA_CONGESTION_TONE

+};

+

+enum {

+	DEFAULT_PCM_CONFIG

+};

+

+enum {

+    DEFAULT_ZSYNTH

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_patch_D_2010AUG15.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_patch_D_2010AUG15.c
new file mode 100755
index 0000000..4204bf6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si324x_patch_D_2010AUG15.c
@@ -0,0 +1,992 @@
+//Generated on: Mon Aug 16 13:47:00 2010

+

+#include "si_voice_datatypes.h"

+#include "si324x.h"

+//Patch code file for Si324x

+const uInt32 patchDataRevD [] = {

+144101L,

+532675L,

+144101L,

+533699L,

+144101L,

+535747L,

+144101L,

+545987L,

+144101L,

+577219L,

+144101L,

+1014467L,

+144101L,

+1017539L,

+144101L,

+1019587L,

+144101L,

+464577L,

+257640L,

+404579L,

+144101L,

+617664L,

+222341L,

+143077L,

+537795L,

+697669L,

+659045L,

+658501L,

+674309L,

+133861L,

+535747L,

+608485L,

+542403L,

+144101L,

+5312L,

+149125L,

+262241L,

+524291L,

+144613L,

+543427L,

+144101L,

+47808L,

+18149L,

+560323L,

+767589L,

+524290L,

+145632L,

+553155L,

+759301L,

+759301L,

+759313L,

+759301L,

+758789L,

+758789L,

+758784L,

+758789L,

+136293L,

+231552L,

+258053L,

+219656L,

+660069L,

+174704L,

+212485L,

+23269L,

+558787L,

+144100L,

+971457L,

+258053L,

+144099L,

+971457L,

+12517L,

+562883L,

+673285L,

+144101L,

+955073L,

+258149L,

+174690L,

+146146L,

+568003L,

+82661L,

+568003L,

+146661L,

+974017L,

+144101L,

+569027L,

+145125L,

+974017L,

+212101L,

+377445L,

+212584L,

+174691L,

+82661L,

+970945L,

+258149L,

+660066L,

+146146L,

+575683L,

+174693L,

+144100L,

+971457L,

+174693L,

+144099L,

+971457L,

+13029L,

+581315L,

+25312L,

+583875L,

+5221L,

+69L,

+144101L,

+588483L,

+683525L,

+3173L,

+69L,

+144101L,

+588483L,

+122373L,

+123397L,

+122885L,

+123909L,

+121861L,

+124933L,

+124421L,

+144101L,

+632003L,

+660197L,

+597699L,

+119429L,

+122469L,

+98L,

+122986L,

+122370L,

+101L,

+524298L,

+122896L,

+660069L,

+123496L,

+126469L,

+126563L,

+123394L,

+124005L,

+524291L,

+123909L,

+660709L,

+632003L,

+262240L,

+121956L,

+386659L,

+121860L,

+145637L,

+613059L,

+214656L,

+121964L,

+524291L,

+145637L,

+605379L,

+144101L,

+632003L,

+431717L,

+122466L,

+145122L,

+607939L,

+524305L,

+433765L,

+123492L,

+125957L,

+434274L,

+524292L,

+125440L,

+122373L,

+123397L,

+144101L,

+620227L,

+431717L,

+122978L,

+145122L,

+615619L,

+524305L,

+433765L,

+124004L,

+125957L,

+434274L,

+524292L,

+125440L,

+122885L,

+123909L,

+121861L,

+125541L,

+262242L,

+669408L,

+623299L,

+124516L,

+435299L,

+124421L,

+435301L,

+126052L,

+147173L,

+626371L,

+680965L,

+262242L,

+669408L,

+628931L,

+125028L,

+434787L,

+124933L,

+434789L,

+524292L,

+147173L,

+632003L,

+680965L,

+537317L,

+665283L,

+645L,

+535265L,

+635587L,

+111621L,

+112133L,

+610021L,

+636611L,

+37477L,

+2658L,

+23269L,

+639683L,

+144100L,

+640195L,

+524291L,

+672261L,

+112229L,

+262242L,

+111716L,

+112130L,

+262245L,

+115300L,

+111618L,

+101L,

+145125L,

+649923L,

+433250L,

+524292L,

+147173L,

+652995L,

+115200L,

+112133L,

+144101L,

+652995L,

+433250L,

+524291L,

+145125L,

+652995L,

+115200L,

+111621L,

+111717L,

+216674L,

+217188L,

+146145L,

+656579L,

+115781L,

+672773L,

+112229L,

+216674L,

+217188L,

+146145L,

+660163L,

+115781L,

+672773L,

+115813L,

+262242L,

+145635L,

+665283L,

+115717L,

+146149L,

+665283L,

+437349L,

+673282L,

+29189L,

+536800L,

+670915L,

+114789L,

+262242L,

+435812L,

+114692L,

+147168L,

+671427L,

+672773L,

+217189L,

+115781L,

+114693L,

+24805L,

+678083L,

+253029L,

+262242L,

+146659L,

+676035L,

+252933L,

+144101L,

+680643L,

+776293L,

+98434L,

+144117L,

+680131L,

+776293L,

+119426L,

+517750L,

+252997L,

+776197L,

+579813L,

+686787L,

+26341L,

+686787L,

+611045L,

+686787L,

+188005L,

+392290L,

+524292L,

+146144L,

+686787L,

+8197L,

+1125L,

+610L,

+524292L,

+256005L,

+84192L,

+693443L,

+252517L,

+118402L,

+145637L,

+694467L,

+771392L,

+144101L,

+693955L,

+524305L,

+252421L,

+605408L,

+697027L,

+259077L,

+144101L,

+705731L,

+18661L,

+702147L,

+259173L,

+524290L,

+145637L,

+705731L,

+755776L,

+259077L,

+144101L,

+705731L,

+259173L,

+755810L,

+146149L,

+705731L,

+259141L,

+756325L,

+755781L,

+539237L,

+232578L,

+402037L,

+146148L,

+733379L,

+659173L,

+719043L,

+170629L,

+739937L,

+743012L,

+146149L,

+717507L,

+98434L,

+253557L,

+119451L,

+148709L,

+719043L,

+253445L,

+118934L,

+742917L,

+740165L,

+144101L,

+719043L,

+118405L,

+740160L,

+742917L,

+26336L,

+728259L,

+201317L,

+201218L,

+145637L,

+4291L,

+547941L,

+214658L,

+145632L,

+4291L,

+694789L,

+537605L,

+538437L,

+538629L,

+694785L,

+721925L,

+144101L,

+830147L,

+402021L,

+201285L,

+182885L,

+524290L,

+145632L,

+4291L,

+254533L,

+182789L,

+144101L,

+4291L,

+145636L,

+754883L,

+145636L,

+168130L,

+145636L,

+194754L,

+145636L,

+814275L,

+145636L,

+820419L,

+145636L,

+707L,

+145636L,

+338626L,

+145636L,

+525506L,

+145636L,

+338626L,

+145636L,

+525506L,

+145636L,

+338626L,

+145636L,

+525506L,

+145636L,

+338626L,

+145636L,

+525506L,

+145636L,

+830147L,

+145636L,

+859843L,

+145636L,

+1003203L,

+145636L,

+1003203L,

+145636L,

+1003203L,

+145632L,

+1003203L,

+144101L,

+86210L,

+659685L,

+4291L,

+216165L,

+402018L,

+145636L,

+771267L,

+145636L,

+120002L,

+145636L,

+774339L,

+145636L,

+776387L,

+145636L,

+2243L,

+145636L,

+779971L,

+145636L,

+783043L,

+145636L,

+791747L,

+145636L,

+793795L,

+145636L,

+799427L,

+145636L,

+801475L,

+145636L,

+807107L,

+145636L,

+809155L,

+144101L,

+153794L,

+240773L,

+694785L,

+561157L,

+694789L,

+144101L,

+100034L,

+720485L,

+249413L,

+144101L,

+123586L,

+720485L,

+249442L,

+524291L,

+524295L,

+249349L,

+144101L,

+131778L,

+720485L,

+249925L,

+718949L,

+398917L,

+144101L,

+2243L,

+720485L,

+249954L,

+524291L,

+718951L,

+249861L,

+398946L,

+524291L,

+524295L,

+398853L,

+162949L,

+118401L,

+98454L,

+694806L,

+561157L,

+694789L,

+144101L,

+2243L,

+720485L,

+248901L,

+144101L,

+2243L,

+720485L,

+248930L,

+524291L,

+98439L,

+248833L,

+162950L,

+694806L,

+561157L,

+694789L,

+144101L,

+2243L,

+720485L,

+248389L,

+144101L,

+2243L,

+720485L,

+248418L,

+524291L,

+98439L,

+248320L,

+162945L,

+694806L,

+561157L,

+694789L,

+144101L,

+2243L,

+720485L,

+247877L,

+144101L,

+2243L,

+720485L,

+247906L,

+524291L,

+524295L,

+247808L,

+694789L,

+561157L,

+694789L,

+144101L,

+153794L,

+216165L,

+402018L,

+145636L,

+817347L,

+144101L,

+248002L,

+118917L,

+723781L,

+727365L,

+728389L,

+144101L,

+257730L,

+216165L,

+402018L,

+145636L,

+823491L,

+144101L,

+299202L,

+118917L,

+723781L,

+727365L,

+727877L,

+728389L,

+729413L,

+222821L,

+446016L,

+738821L,

+220165L,

+220677L,

+144101L,

+309954L,

+216165L,

+402018L,

+145636L,

+837315L,

+145636L,

+264898L,

+145636L,

+855747L,

+145636L,

+264898L,

+145632L,

+699586L,

+144101L,

+756418L,

+118405L,

+728389L,

+739141L,

+99973L,

+773957L,

+118917L,

+727365L,

+730949L,

+738629L,

+723776L,

+753157L,

+541285L,

+195141L,

+546405L,

+194629L,

+560741L,

+193605L,

+231045L,

+694784L,

+541509L,

+546309L,

+118914L,

+447926L,

+560645L,

+694785L,

+445957L,

+242309L,

+402021L,

+754498L,

+754693L,

+403557L,

+194117L,

+416357L,

+192069L,

+144101L,

+2243L,

+152160L,

+403554L,

+416355L,

+403461L,

+192064L,

+773637L,

+144101L,

+2243L,

+216165L,

+402018L,

+145636L,

+865987L,

+145636L,

+905411L,

+145636L,

+884931L,

+145632L,

+905411L,

+144101L,

+985795L,

+539749L,

+194629L,

+541285L,

+228933L,

+546917L,

+193605L,

+377957L,

+194117L,

+560741L,

+195141L,

+739941L,

+254021L,

+118917L,

+723781L,

+722757L,

+724805L,

+724293L,

+730949L,

+726853L,

+735557L,

+725317L,

+694784L,

+539653L,

+377858L,

+147094L,

+560641L,

+118405L,

+546838L,

+541189L,

+694784L,

+762885L,

+739141L,

+738629L,

+745797L,

+729413L,

+777029L,

+740165L,

+402016L,

+745986L,

+216165L,

+118403L,

+216066L,

+145637L,

+893635L,

+776005L,

+728389L,

+405093L,

+183938L,

+223047L,

+404485L,

+404069L,

+159877L,

+255041L,

+403973L,

+402021L,

+162946L,

+405095L,

+226306L,

+257095L,

+460389L,

+227330L,

+225864L,

+228421L,

+227845L,

+119429L,

+216161L,

+257124L,

+146661L,

+902851L,

+404549L,

+144101L,

+4291L,

+159877L,

+524289L,

+403973L,

+144101L,

+4291L,

+225893L,

+226402L,

+146660L,

+908995L,

+225797L,

+144101L,

+4291L,

+757349L,

+257122L,

+144613L,

+913091L,

+227426L,

+93827L,

+144101L,

+914115L,

+227426L,

+93828L,

+257026L,

+119431L,

+227333L,

+216161L,

+257124L,

+144610L,

+922819L,

+118917L,

+54913L,

+660072L,

+524292L,

+524294L,

+524294L,

+524294L,

+403973L,

+144101L,

+923331L,

+404549L,

+227429L,

+93826L,

+405094L,

+228460L,

+147173L,

+932035L,

+227938L,

+216164L,

+225797L,

+119429L,

+228353L,

+524292L,

+144613L,

+4291L,

+225861L,

+144101L,

+4291L,

+746085L,

+257122L,

+669925L,

+937667L,

+192069L,

+719973L,

+210053L,

+192577L,

+745989L,

+144101L,

+893635L,

+257125L,

+210053L,

+192104L,

+140421L,

+660072L,

+524294L,

+257124L,

+256517L,

+192098L,

+524292L,

+524294L,

+246406L,

+524294L,

+524294L,

+524294L,

+524294L,

+660069L,

+246920L,

+660069L,

+524296L,

+255493L,

+119429L,

+216161L,

+255588L,

+144610L,

+958147L,

+113285L,

+524296L,

+182887L,

+447493L,

+222725L,

+445957L,

+196098L,

+146149L,

+961731L,

+694784L,

+547845L,

+694789L,

+144098L,

+961731L,

+330821L,

+256613L,

+257605L,

+719973L,

+192610L,

+174724L,

+196423L,

+145637L,

+982211L,

+195589L,

+640L,

+196933L,

+193029L,

+196197L,

+195682L,

+193124L,

+147173L,

+969411L,

+196098L,

+196709L,

+524291L,

+193029L,

+195685L,

+524290L,

+196711L,

+195586L,

+138343L,

+196612L,

+145125L,

+964803L,

+119429L,

+216161L,

+193124L,

+144613L,

+977603L,

+447557L,

+144101L,

+982211L,

+399941L,

+174725L,

+147073L,

+660069L,

+400296L,

+192613L,

+660072L,

+524292L,

+399365L,

+119429L,

+216161L,

+524292L,

+144613L,

+2243L,

+255077L,

+404037L,

+756736L,

+745477L,

+745989L,

+216069L,

+722437L,

+724485L,

+723973L,

+730629L,

+726533L,

+735237L,

+724997L,

+729093L,

+723461L,

+728069L,

+775685L,

+694789L,

+194661L,

+539717L,

+228965L,

+541253L,

+195173L,

+560709L,

+193637L,

+546885L,

+194149L,

+377925L,

+694784L,

+254053L,

+739909L,

+738821L,

+738309L,

+776709L,

+144101L,

+4291L,

+216165L,

+402018L,

+145636L,

+1010371L,

+145636L,

+919746L,

+145636L,

+927426L,

+145636L,

+935618L,

+145632L,

+942786L,

+144101L,

+1023682L,

+118917L,

+743237L,

+118405L,

+725317L,

+724293L,

+734021L,

+144101L,

+861378L,

+742917L,

+724997L,

+723973L,

+733701L,

+144101L,

+1030850L,

+118917L,

+743749L,

+144101L,

+510146L,

+144101L,

+837312L,

+0L

+};

+

+const uInt16 patchEntriesRevD [] =	{

+2938,

+1204,

+2,

+3896,

+3999,

+6108,

+5091,

+1633

+};

+

+const proslicPatch RevDPatch = {

+	patchDataRevD,

+	patchEntriesRevD};

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si32xxx_multibom_constants.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si32xxx_multibom_constants.h
new file mode 100755
index 0000000..8498cbe
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/si32xxx_multibom_constants.h
@@ -0,0 +1,90 @@
+/*

+** Copyright (c) 2010 Silicon Laboratories, Inc.

+** 2010-05-11 15:21:11

+**

+** Example use of multiple devices and/or device bom options in which

+** presets are generically selected, while the general configuration is

+** explicitly selected.

+*/

+

+

+#ifndef SI32XXX_CONSTANTS_H

+#define SI32XXX_CONSTANTS_H

+

+/** Ringing Presets */

+enum {

+	RING_MAX_VBAT_PROVISIONING,

+	RING_F20_45VRMS_0VDC_LPR,

+	RING_F20_45VRMS_0VDC_BAL

+};

+

+/** DC_Feed Presets */

+enum {

+	DCFEED_48V_20MA,

+	DCFEED_48V_25MA,

+	DCFEED_PSTN_DET_1,

+	DCFEED_PSTN_DET_2

+};

+

+/** Impedance Presets */

+enum {

+	ZSYN_600_0_0_30_0,

+	ZSYN_270_750_150_30_0,

+	ZSYN_370_620_310_30_0,

+	ZSYN_220_820_120_30_0,

+	ZSYN_600_0_1000_30_0,

+	ZSYN_200_680_100_30_0,

+	ZSYN_220_820_115_30_0

+};

+

+/** FSK Presets */

+enum {

+	DEFAULT_FSK

+};

+

+/** Pulse_Metering Presets */

+enum {

+	DEFAULT_PULSE_METERING

+};

+

+/** Tone Presets */

+enum {

+	TONEGEN_FCC_DIAL,

+	TONEGEN_FCC_BUSY,

+	TONEGEN_FCC_RINGBACK,

+	TONEGEN_FCC_REORDER,

+	TONEGEN_FCC_CONGESTION

+};

+

+/** PCM Presets */

+enum {

+	PCM_8ULAW,

+	PCM_8ALAW,

+	PCM_16LIN,

+	PCM_16LIN_WB

+};

+

+

+/** General Parameters */

+enum{

+  SI3217X_GEN_PARAM_FLYBACK,

+  SI3217X_GEN_PARAM_BUCK_BOOST,

+  SI3217X_GEN_PARAM_P_BUCK_BOOST_5V

+};

+

+enum {

+  SI3226_GEN_PARAM_FLYBACK,

+  SI3226_GEN_PARAM_QCUK

+};

+

+enum {

+  SI3226X_GEN_PARAM_FLYBACK,

+  SI3226X_GEN_PARAM_TSS,

+  SI3226X_GEN_PARAM_TSS_ISO,

+  SI3226X_GEN_PARAM_QCUK,

+  SI3226X_GEN_PARAM_LCQCUK

+};

+

+

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_api_config.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_api_config.h
new file mode 100755
index 0000000..d04b435
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_api_config.h
@@ -0,0 +1,44 @@
+/*

+** Copyright © 2008-2010 by Silicon Laboratories

+**

+** $Id: vdaa_api_config.h 1994 2010-06-01 23:48:45Z nizajerk $

+**

+** vdaa_api_config.h

+** VoiceDAA header config file

+**

+** Author(s): 

+** naqamar, laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This file is used 

+** in the VoiceDAA demonstration code. 

+**

+**

+*/

+

+#ifndef VDAA_API_CFG_H

+#define VDAA_API_CFG_H

+

+/* #define DISABLE_MALLOC */

+/* #define DISABLE_VDAA_RING_DETECT_SETUP */

+/* #define DISABLE_VDAA_AUDIO_GAIN_SETUP */

+/* #define DISABLE_VDAA_PCM_SETUP */

+/* #define DISABLE_VDAA_COUNTRY_SETUP */

+/* #define DISABLE_VDAA_HYBRID_SETUP */

+#define DISABLE_VDAA_LOOPBACK_SETUP

+#define DISABLE_VDAA_IMPEDANCE_SETUP

+

+#ifndef ENABLE_DEBUG

+#define ENABLE_DEBUG

+#endif

+#include "stdio.h"

+#define LOGPRINT printf

+

+#endif
\ No newline at end of file
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_constants.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_constants.c
new file mode 100755
index 0000000..b033542
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_constants.c
@@ -0,0 +1,201 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-02-09 18:53:30

+**

+** Si3217x ProSLIC API Configuration Tool Version 2.4.0

+*/

+

+

+

+#include "vdaa.h"

+

+vdaa_General_Cfg Vdaa_General_Configuration  = {

+    INTE_DISABLED,

+    INTE_ACTIVE_LOW,

+    RES_CAL_ENABLED,

+    FS_8KHZ,

+    FOH_128,

+    LVS_FORCE_ENABLED,

+    CVS_CURRENT,

+    CVP_ABOVE,

+    GCE_DISABLED,

+    IIR_DISABLED,

+    FULL_DISABLED,

+    FULL2_ENABLED,

+    FILT_HPF_200HZ,

+    RG1_DISABLED,

+    PWM_DELTA_SIGMA,

+    PWM_DISABLED,

+    SPIM_TRI_CS

+};

+

+vdaa_Country_Cfg Vdaa_Country_Presets[] ={

+    {

+    RZ_MAX,

+    DC_50,

+    AC_600,

+    DCV3_5,

+    MINI_10MA,

+    ILIM_DISABLED,

+    OHS_LESS_THAN_0_5MS,

+    HYBRID_ENABLED

+    },  /* COU_USA */

+    {

+    RZ_MAX,

+    DC_50,

+    AC_270__750_150,

+    DCV3_5,

+    MINI_10MA,

+    ILIM_ENABLED,

+    OHS_3MS,

+    HYBRID_ENABLED

+    },  /* COU_GERMANY */

+    {

+    RZ_MAX,

+    DC_50,

+    AC_200__680_100,

+    DCV3_5,

+    MINI_10MA,

+    ILIM_DISABLED,

+    OHS_LESS_THAN_0_5MS,

+    HYBRID_ENABLED

+    },  /* COU_CHINA */

+    {

+    RZ_MAX,

+    DC_50,

+    AC_220__820_120,

+    DCV3_2,

+    MINI_12MA,

+    ILIM_DISABLED,

+    OHS_26MS,

+    HYBRID_ENABLED

+    }   /* COU_AUSTRALIA */

+};

+

+vdaa_audioGain_Cfg Vdaa_audioGain_Presets[] ={

+    {

+    0,    /* mute */

+    XGA_GAIN,    /* xXGA2 */

+    0,    /* xXG2 */

+    XGA_GAIN,    /* xXGA3 */

+    0,    /* xXG3 */

+    64,    /* AxM */

+    0     /* cpEn */

+    },  /* AUDIO_GAIN_0DB */

+    {

+    0,    /* mute */

+    XGA_ATTEN,    /* xXGA2 */

+    4,    /* xXG2 */

+    XGA_GAIN,    /* xXGA3 */

+    0,    /* xXG3 */

+    64,    /* AxM */

+    0     /* cpEn */

+    },  /* AUDIO_ATTEN_4DB */

+    {

+    0,    /* mute */

+    XGA_ATTEN,    /* xXGA2 */

+    6,    /* xXG2 */

+    XGA_GAIN,    /* xXGA3 */

+    0,    /* xXG3 */

+    64,    /* AxM */

+    0     /* cpEn */

+    },  /* AUDIO_ATTEN_6DB */

+    {

+    0,    /* mute */

+    XGA_ATTEN,    /* xXGA2 */

+    11,    /* xXG2 */

+    XGA_GAIN,    /* xXGA3 */

+    0,    /* xXG3 */

+    64,    /* AxM */

+    0     /* cpEn */

+    }   /* AUDIO_ATTEN_11DB */

+};

+

+vdaa_Ring_Detect_Cfg Vdaa_Ring_Detect_Presets[] ={

+    {

+    RDLY_512MS,

+    RT__13_5VRMS_16_5VRMS,

+    12,    /* RMX */

+    RTO_1408MS,

+    RCC_640MS,

+    RNGV_DISABLED,

+    17,    /* RAS */

+    RFWE_HALF_WAVE,

+    RDI_BEG_END_BURST, 

+    RGDT_ACTIVE_LOW 

+    },  /* RING_DET_NOVAL_LOWV */

+    {

+    RDLY_512MS,

+    RT__40_5VRMS_49_5VRMS,

+    12,    /* RMX */

+    RTO_1408MS,

+    RCC_640MS,

+    RNGV_ENABLED,

+    17,    /* RAS */

+    RFWE_RNGV_RING_ENV,

+    RDI_BEG_END_BURST, 

+    RGDT_ACTIVE_LOW 

+    }   /* RING_DET_VAL_HIGHV */

+};

+

+vdaa_PCM_Cfg Vdaa_PCM_Presets[] ={

+    {

+    U_LAW,

+    PCLK_1_PER_BIT,

+    TRI_POS_EDGE

+    },  /* PCM_8ULAW */

+    {

+    A_LAW,

+    PCLK_1_PER_BIT,

+    TRI_POS_EDGE

+    },  /* PCM_8ALAW */

+    {

+    LINEAR_16_BIT,

+    PCLK_1_PER_BIT,

+    TRI_POS_EDGE

+    }   /* PCM_16LIN */

+};

+

+vdaa_Hybrid_Cfg Vdaa_Hybrid_Presets[] ={

+    {

+       0,    /* HYB1 */

+     254,    /* HYB2 */

+       0,    /* HYB3 */

+       1,    /* HYB4 */

+     255,    /* HYB5 */

+       1,    /* HYB6 */

+       0,    /* HYB7 */

+       0    /* HYB8 */

+    },  /* HYB_600_0_0_500FT_24AWG */

+    {

+       4,    /* HYB1 */

+     246,    /* HYB2 */

+     242,    /* HYB3 */

+       4,    /* HYB4 */

+     254,    /* HYB5 */

+     255,    /* HYB6 */

+       1,    /* HYB7 */

+     255    /* HYB8 */

+    },  /* HYB_270_750_150_500FT_24AWG */

+    {

+       4,    /* HYB1 */

+     245,    /* HYB2 */

+     243,    /* HYB3 */

+       7,    /* HYB4 */

+     253,    /* HYB5 */

+       0,    /* HYB6 */

+       1,    /* HYB7 */

+     255    /* HYB8 */

+    },  /* HYB_200_680_100_500FT_24AWG */

+    {

+       4,    /* HYB1 */

+     244,    /* HYB2 */

+     241,    /* HYB3 */

+       6,    /* HYB4 */

+     253,    /* HYB5 */

+     255,    /* HYB6 */

+       2,    /* HYB7 */

+     255    /* HYB8 */

+    }   /* HYB_220_820_120_500FT_24AWG */

+};

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_constants.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_constants.h
new file mode 100755
index 0000000..ec05e7c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/vdaa_constants.h
@@ -0,0 +1,50 @@
+/*

+** Copyright (c) 2011 Silicon Laboratories, Inc.

+** 2011-02-09 18:53:30

+**

+** Si3217x ProSLIC API Configuration Tool Version 2.4.0

+*/

+

+

+#ifndef VDAA_CONSTANTS_H

+#define VDAA_CONSTANTS_H

+

+/** Vdaa_Country Presets */

+enum {

+	COU_USA,

+	COU_GERMANY,

+	COU_CHINA,

+	COU_AUSTRALIA

+};

+

+/** Vdaa_Audio_Gain Presets */

+enum {

+	AUDIO_GAIN_0DB,

+	AUDIO_ATTEN_4DB,

+	AUDIO_ATTEN_6DB,

+	AUDIO_ATTEN_11DB

+};

+

+/** Vdaa_Ring_Validation Presets */

+enum {

+	RING_DET_NOVAL_LOWV,

+	RING_DET_VAL_HIGHV

+};

+

+/** Vdaa_PCM Presets */

+enum {

+	PCM_8ULAW,

+	PCM_8ALAW,

+	PCM_16LIN

+};

+

+/** Vdaa_Hybrid Presets */

+enum {

+	HYB_600_0_0_500FT_24AWG,

+	HYB_270_750_150_500FT_24AWG,

+	HYB_200_680_100_500FT_24AWG,

+	HYB_220_820_120_500FT_24AWG

+};

+

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/proslic.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/proslic.h
new file mode 100755
index 0000000..e8cd8f0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/proslic.h
@@ -0,0 +1,2480 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: proslic.h 3100 2011-09-15 14:04:54Z cdp $

+**

+** Proslic.h

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file for the ProSLIC driver.

+**

+** Dependancies:

+** proslic_datatypes.h

+**

+*/

+#ifndef PROSLIC_H

+#define PROSLIC_H

+

+/*include all the required headers*/

+#include "proslic_api_config.h"

+#include "si_voice_datatypes.h"

+#include "si_voice_ctrl.h"

+#include "si_voice_timer_intf.h"

+#include "si_voice.h"

+

+

+/* UNSORTED ADDITIONS - These common parameters have been moved from

+   the drivers to here to support simultaneous compile of multiple devices

+   */

+/* Patch Parameters */

+#define PATCH_JMPTBL_LOW_ADDR       82

+#define PATCH_NUM_LOW_ENTRIES       8

+#define PATCH_JMPTBL_HIGH_ADDR      1597

+#define PATCH_NUM_HIGH_ENTRIES      8

+#define PATCH_JMPTBL_START_ADDR     82

+#define PATCH_NUM_ENTRIES           8

+#define PATCH_MAX_SUPPORT_RAM       128

+#define PATCH_MAX_SIZE              1024

+

+/* BOM Constants */

+#define BOM_KAUDIO_PM               0x8000000L

+#define BOM_KAUDIO_NO_PM            0x3A2E8BAL

+#define BOM_AC_ADC_GAIN_PM          0x151EB80L

+#define BOM_AC_AC_GAIN_NO_PM        0x99999AL

+#define FIXRL_VDC_SCALE             0xAE924B9L  /** vdc sense scale when using fixed-rail */           

+

+/* Generic Constants */

+#define COMP_5V                     0x51EB82L 

+#define VBATL_13V                   0xF00000L 

+#define COMP_10V                    0xA3D705L 

+#define ZCAL_V_RASUM_IDEAL_VAL      0x8F00000L

+#define ZCAL_DC_DAC_OS_VAL          0x1FFE0000L  

+

+/* MADC Constants */

+#define SCALE_V_MADC                1074      /* 1/(1000*931.32e-9)  mV */

+#define SCALE_I_MADC                597       /* 1/(1e6*1.676e-9)    uA */

+

+/* Calibration Constants */

+#define CAL_LB_CMDAC                0x0C

+#define CAL_LB_TRNRD                0x03

+#define CAL_LB_ALL                  0x0F  

+#define TIMEOUT_MADC_CAL            100

+#define TIMEOUT_GEN_CAL             300

+#define TIMEOUT_LB_CAL              2410

+

+/* 

+

+/** @mainpage

+ * This document is a supplement to the ProSLIC API Specification.  It has most

+ * of the APIs documented and hyperlinked. 

+ *

+ * This document has the following tabs:

+ *

+ * - Main Page (this page) - introduction to the document.

+ * - Related pages - mainly the deprecated list is located here. 

+ *  Although these identifiers are present in the current release, they are 

+ *  targeted for deletion in a future release.  Any existing customer code 

+ *  using deprecated identifiers should be modified as indicated. 

+ * - Modules - this is the meat of the document - this has each functional group in outline format listed here.

+ * - Data Structures - This has every data structure listed in in the ProSLIC API in alphabetical order.

+ * - Files - this has the source files in hyperlink format.  @note In some cases the hyperlink generator will not properly 

+ *  generate the correct reference or not be able to find it.  In this case please use an alternative method.

+ *

+ */

+

+/** @defgroup PROSLIC_TYPES ProSLIC General Datatypes/Function Definitions

+ * This section documents functions and datastructures related to the 

+ * ProSLIC/FXS chipsets.

+ * @{

+ */

+

+/*

+* ----------------ProSLIC Generic DataTypes/Function Definitions----

+**********************************************************************

+*/

+

+#define MAX_PROSLIC_IRQS 32 /**< How many interrupts are supported in the ProSLIC */

+

+

+#define ON_HOOK_TIMEOUT 0x7f /**< Returned by @ref ProSLIC_DialPulseDetect() to 

+			          indicate a failure to detect a pulse digit */

+

+/**********************************************************************/

+/**

+ * @defgroup PROLSIC_BRD_DESIGN Board design settings 

+ * @{

+ */

+/**

+* Battery Rail option

+*/

+typedef enum 

+{

+    BO_DCDC_TSS,        /**< Used for Fixed Rail DC-DC supplies */

+    BO_DCDC_TRACKING,   /**< Used for Tracking DC-DC supplies */

+    BO_DCDC_EXTERNAL,   /**< Used for external fixed rail supplies */

+    BO_DCDC_TSS_ISO,    /**< Used for isolated TSS supplies */

+    BO_DCDC_FIXED_RAIL = BO_DCDC_TSS     /**< Fixed rail replaced by TSS */

+#ifndef SIVOICE_CFG_NEWTYPES_ONLY

+    ,FIXED = BO_DCDC_FIXED_RAIL /**< @deprecated use BO_DCDC_FIXED_RAIL */

+    ,TRACKING = BO_DCDC_TRACKING  /**< @deprecated use BO_DCDC_TRACKING */

+#endif

+} batRailType;

+

+/**

+* Linefeed part number options - which front end is used.

+*/

+typedef enum {

+	SI3208,

+	SI3209,

+	SI3203,

+	SI3206,

+	SI3205,

+	SI3201,

+	SI3210_DISCRETE

+} linefeed;

+/** @} PROSLIC_BRD_DESIGN */

+

+/**********************************************************************/

+/**

+* Map Proslic types to SiVoice types

+*/

+typedef SiVoiceControlInterfaceType controlInterfaceType; /**< Map ProSLIC to SiVoice type */

+typedef SiVoiceControlInterfaceType proslicControlInterfaceType; /**< Map ProSLIC to SiVoice type */

+typedef SiVoiceDeviceType ProslicDeviceType; /**< Map ProSLIC to SiVoice type */

+typedef SiVoiceChanType proslicChanType; /**< Map ProSLIC to SiVoice type */

+

+/**

+* Define channel and device type pointers

+*/

+typedef ProslicDeviceType* proslicDeviceType_ptr; /**< Shortcut for pointer to a ProSLIC device type */

+typedef proslicChanType *proslicChanType_ptr; /**< Shortcut for pointer to a ProSLIC channel type */

+

+/** @} PROSLIC_TYPES */

+

+/** @addtogroup PD_DETECT

+ * @{

+ */

+

+/**

+* This is structure used to store pulse dial information

+*/

+typedef struct {

+	uInt8 currentPulseDigit;

+	void *onHookTime; /**< Timestamp for when the onhook detection occured */

+	void *offHookTime; /**< Timestamp for when the offhook detection occured */

+} pulseDialType;

+

+/**

+* Defines structure for configuring pulse dial detection

+*/

+typedef struct {

+	uInt8 minOnHook; /**< Min mSec for onhook */

+	uInt8 maxOnHook; /**< Max mSec for onhook */

+	uInt8 minOffHook; /**< Min mSec for offhook */

+	uInt8 maxOffHook; /**< Max mSec for offhook */

+} pulseDial_Cfg;

+/** @} PD_DETECT */

+

+

+/** @addtogroup PROSLIC_INTERRUPTS

+ * @{

+ */

+/**

+* Interrupt tags

+*/

+

+typedef enum {

+IRQ_OSC1_T1,

+IRQ_OSC1_T2,

+IRQ_OSC2_T1,

+IRQ_OSC2_T2,

+IRQ_RING_T1,

+IRQ_RING_T2,

+IRQ_PM_T1,

+IRQ_PM_T2,

+IRQ_FSKBUF_AVAIL, /**< FSK FIFO depth reached */

+IRQ_VBAT, 

+IRQ_RING_TRIP, /**< Ring Trip detected */

+IRQ_LOOP_STATUS,  /**< Loop Current changed */

+IRQ_LONG_STAT,

+IRQ_VOC_TRACK,

+IRQ_DTMF,         /**< DTMF Detected - call @ref ProSLIC_DTMFReadDigit to decode the value */

+IRQ_INDIRECT,     /**< Indirect/RAM access completed */

+IRQ_TXMDM,

+IRQ_RXMDM,

+IRQ_PQ1,          /**< Power alarm 1 */

+IRQ_PQ2,          /**< Power alarm 2 */

+IRQ_PQ3,          /**< Power alarm 3 */

+IRQ_PQ4,          /**< Power alarm 4 */

+IRQ_PQ5,          /**< Power alarm 5 */

+IRQ_PQ6,          /**< Power alarm 6 */

+IRQ_RING_FAIL,

+IRQ_CM_BAL,

+IRQ_USER_0,

+IRQ_USER_1,

+IRQ_USER_2,

+IRQ_USER_3,

+IRQ_USER_4,

+IRQ_USER_5,

+IRQ_USER_6,

+IRQ_USER_7,

+IRQ_DSP,

+IRQ_MADC_FS,

+IRQ_P_HVIC,

+IRQ_P_THERM, /**< Thermal alarm */

+IRQ_P_OFFLD

+}ProslicInt;

+

+/**

+* Defines structure of interrupt data - used by @ref ProSLIC_GetInterrupts 

+*/

+typedef struct {

+	ProslicInt *irqs; /**< Pointer of an array of size MAX_PROSLIC_IRQS (this is to be allocated by the caller) */

+	uInt8 number; /**< Number of IRQs detected/pending */

+} proslicIntType;

+

+

+/** @} PROSLIC_INTERRUPTS */

+

+/** @addtogroup TONE_GEN

+ * @{

+ */

+/**

+* Defines structure for configuring 1 oscillator - see your datasheet for specifics or use the configuration

+* tool to have this filled in for you.

+*/

+typedef struct {

+	ramData freq;

+	ramData amp;

+	ramData phas;

+	uInt8 talo;

+	uInt8 tahi;

+	uInt8 tilo;

+	uInt8 tihi;

+} Oscillator_Cfg;

+

+/** @} TONE_GEN */

+

+/*****************************************************************************/

+/** @addtogroup SIGNALING 

+ * @{

+ */

+/** 

+* Hook states - retruned by @ref ProSLIC_ReadHookStatus()

+*/

+enum {

+	PROSLIC_ONHOOK, /**< Hook state is onhook */

+	PROSLIC_OFFHOOK /**< Hook state is offhook */

+};

+

+#ifndef SIVOICE_CFG_NEWTYPES_ONLY

+enum {

+ONHOOK = PROSLIC_ONHOOK, /**< @deprecated- Please use PROSLIC_ONHOOK and PROSLIC_OFFHOOK for future code development */

+OFFHOOK = PROSLIC_OFFHOOK

+};

+#endif

+

+/** @} SIGNALING */

+

+/*****************************************************************************/

+/** @addtogroup PCM_CONTROL

+ * @{

+* Loopback modes

+*/

+typedef enum {

+	PROSLIC_LOOPBACK_NONE, /**< Loopback disabled */

+	PROSLIC_LOOPBACK_DIG,  /**< Loopback is toward the PCM side */

+	PROSLIC_LOOPBACK_ANA   /**< Loopback is toward the analog side */

+} ProslicLoopbackModes;

+

+/**

+* Mute options - which direction to mute 

+*/

+typedef enum {

+	PROSLIC_MUTE_NONE = 0,  /**< Don't mute */

+	PROSLIC_MUTE_RX = 0x1,  /**< Mute toward the RX side */

+	PROSLIC_MUTE_TX = 0x2,  /**< Mute toward the TX side */

+	PROSLIC_MUTE_ALL = 0x3  /**< Mute both directions */

+} ProslicMuteModes;

+

+/** @} PCM_CONTROL */

+

+/*****************************************************************************/

+/** @addtogroup GAIN_CONTROL

+ * @{

+* Path Selector

+*/

+enum {

+    TXACGAIN_SEL = 0,

+    RXACGAIN_SEL = 1

+};

+

+

+/*

+** Defines structure for configuring audio gain on the fly

+*/

+typedef struct {

+	ramData acgain;

+	uInt8 mute;

+	ramData aceq_c0;

+	ramData aceq_c1;

+	ramData aceq_c2;

+	ramData aceq_c3;

+} ProSLIC_audioGain_Cfg;

+

+/** @} GAIN_CONTROL */

+

+/*****************************************************************************/

+/** @addtogroup LINESTATUS

+ * @{

+ */

+/**

+* enumeration of the Proslic polarity reversal states - used by ProSLIC_PolRev API

+*/

+enum {

+	POLREV_STOP, /**< Stop Polarity reversal */

+	POLREV_START, /**< Start Polarity reversal */

+	WINK_START, /**< Start Wink */

+	WINK_STOP /**< Stop Wink */

+};

+

+/**

+* Defines initialization data structures

+* Linefeed states - used in @ref ProSLIC_SetLinefeedStatus and @ref ProSLIC_SetLinefeedStatusBroadcast

+*/

+enum {

+LF_OPEN,          /**< Open circuit */

+LF_FWD_ACTIVE,    /**< Forward actvie */

+LF_FWD_OHT,       /**< Forward active, onhook transmission (used for CID/VMWI) */

+LF_TIP_OPEN,      /**< Tip open */

+LF_RINGING,       /**< Ringing */

+LF_REV_ACTIVE,    /**< Reverse battery/polarity reversed, active */

+LF_REV_OHT,       /**< Reverse battery/polarity reversed, active, onhook transmission (used for CID/VMWI) */

+LF_RING_OPEN      /**< Ring open */

+} ;

+/** @} LINESTATUS */

+

+

+

+

+/*****************************************************************************/

+/** @addtogroup GEN_CFG

+ * @{

+ */

+

+/**

+* Defines initialization data structures

+*/

+typedef struct {

+	uInt8 address;

+	uInt8 initValue;

+} ProslicRegInit;

+

+typedef struct {

+	uInt16 address;

+	ramData initValue;

+} ProslicRAMInit;

+

+/**

+* ProSLIC patch object

+*/

+typedef struct {

+	const ramData *patchData; /**< 1024 max*/

+	const uInt16 *patchEntries; /**< 8 max */

+	const uInt32 patchSerial;  

+    const uInt16 *psRamAddr;  /**< 128 max */

+    const ramData *psRamData; /**< 128 max */

+} proslicPatch;

+

+/** @} GEN_CFG */

+

+

+/*****************************************************************************/

+/** @addtogroup RING_CONTROL 

+ * @{

+ */

+/**

+* Ringing type options

+* Ringing type options - Trapezoidal w/ a Crest factor CF11= Crest factor 1.1 or sinusoidal.

+*/

+typedef enum

+{

+      ProSLIC_RING_TRAP_CF11,

+      ProSLIC_RING_TRAP_CF12,

+      ProSLIC_RING_TRAP_CF13,

+      ProSLIC_RING_TRAP_CF14,

+      ProSLIC_RING_TRAP_CF15,

+      ProSLIC_RING_TRAP_CF16,

+      ProSLIC_RING_SINE /***< Plain old sinusoidal ringing */

+} ProSLIC_RINGTYPE_T;

+

+/**

+* Ringing (provisioned) object

+*/

+typedef struct 

+{

+      ProSLIC_RINGTYPE_T ringtype;  /**< Is this a sinusoid or a trapezoidal ring shape? */

+      uInt8 freq;                   /**< In terms of Hz */

+      uInt8 amp;                    /**< in terms of 1 volt units */

+      uInt8 offset;                 /**< In terms of 1 volt units */

+} ProSLIC_dbgRingCfg;

+

+

+/** @} RING_CONTROL */

+

+/*****************************************************************************/

+/**

+* Line Monitor - returned by @ref ProSLIC_LineMonitor

+*/

+typedef struct 

+{

+    int32  vtr; /**< Voltage, tip-ring in mV */

+    int32  vtip;  /**< Voltage, tip-ground in mV */

+    int32  vring;  /**< Voltage, ring-ground in mV */

+    int32  vbat;  /**< Voltage, battery in mV */

+    int32  itr; /**< Loop current, in uA tip-ring */

+    int32  itip; /**< Loop current, in uA tip */

+    int32  iring; /**< Loop current, in uA ring */

+    int32  ilong; /**< Loop current, in uA longitudinal */

+} proslicMonitorType;

+

+/*****************************************************************************/

+/** @addtogroup PROSLIC_DCFEED

+ * @{

+ */

+/**

+* Powersave

+*/

+enum {

+    PWRSAVE_DISABLE = 0, /**< Disable power savings mode */

+    PWRSAVE_ENABLE = 1   /**< Enable power savings mode */

+};

+

+/**

+** DC Feed Preset

+*/

+typedef struct {

+	ramData slope_vlim;

+	ramData slope_rfeed;

+	ramData slope_ilim;

+	ramData delta1;

+	ramData delta2;

+	ramData v_vlim;

+	ramData v_rfeed;

+	ramData v_ilim;

+	ramData const_rfeed;

+	ramData const_ilim;

+	ramData i_vlim;

+	ramData lcronhk;

+	ramData lcroffhk;

+	ramData lcrdbi;

+	ramData longhith;

+	ramData longloth;

+	ramData longdbi;

+	ramData lcrmask;

+	ramData lcrmask_polrev;

+	ramData lcrmask_state;

+	ramData lcrmask_linecap;

+	ramData vcm_oh;

+	ramData vov_bat;

+	ramData vov_gnd;

+} ProSLIC_DCfeed_Cfg;

+

+/** @} PROSLIC_DCFEED */

+

+/*****************************************************************************/

+/** @defgroup ProSLIC_API ProSLIC API

+* proslic.c function declarations

+* @{

+*/

+

+/*****************************************************************************/

+/** @defgroup DIAGNOSTICS Diagnostics

+ * The functions in this group allow one to monitor the line state for abnormal

+ * situations. 

+ * @{

+ */

+

+/**

+* Test State - used in polled tests (such as PSTN Check)

+*/

+typedef struct 

+{

+    int32 stage;               /**< What state is the test in */

+    int32 waitIterations;      /**< How many iterations to stay in a particular state */

+    int32 sampleIterations;    /**< How many  samples have been collected */

+}proslicTestStateType;

+

+/**

+ * @brief

+ *  This function allows one to monitor the instanteous voltage and

+ *  loop current values seen on tip/ring.  

+ *

+ *  @param[in] pProslic - which channel should the data be collected from

+ *  @param[in,out] *monitor -  the data collected

+ *  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int ProSLIC_LineMonitor(proslicChanType_ptr pProslic, proslicMonitorType *monitor);

+

+int32 ProSLIC_ReadMADCScaled(proslicChanType_ptr pProslic, uInt16 addr, int32 scale);

+

+/** @defgroup PSTN_CHECK PSTN Check

+ * Monitor for excessive longitudinal current, which

+ * would be present if a live pstn line was connected

+ * to the port.  To operate these sets of functions:

+ *

+ * - Iniitalize the PSTN object by calling @ref ProSLIC_InitPSTNCheckObj

+ * - Poll at a constant rate and call @ref ProSLIC_PSTNCheck.  Check the return code of this function.

+ *

+ * Alternatively, you can call the DiffPSTNCheck versions of the above two functions.

+ *

+ * @note These functions may be disabled by doing a undef of @ref PSTN_DET_ENABLE in the configuration file.

+ * @{

+*/

+#define MAX_ILONG_SAMPLES 32 /**< How many samples to collect for PSTN check */

+#define MAX_PSTN_SAMPLES 16 /**< Used in the PSTN check status code to indicate the number of samples to collect */

+

+/**

+* FEMF OPEN voltage test enable

+*/

+enum {

+    FEMF_MEAS_DISABLE, /**< Do not measure FEMF as part of PSTN Check */

+    FEMF_MEAS_ENABLE   /**< Do measure FEMF as part of PSTN Check */

+};

+

+/** Standard line interfaces */

+typedef struct

+{

+    int32   avgThresh;

+    int32   singleThresh;

+    int32   ilong[MAX_ILONG_SAMPLES];

+    uInt8   count;

+    uInt8   samples;

+    int32   avgIlong;

+    BOOLEAN buffFull;

+} proslicPSTNCheckObjType;

+

+typedef proslicPSTNCheckObjType* proslicPSTNCheckObjType_ptr;

+

+

+/** Re-Injection line interfaces (differential) */

+typedef struct {

+    proslicTestStateType pState;

+    int dcfPreset1;

+    int dcfPreset2;

+    int entryDCFeedPreset;

+    uInt8 lfstate_entry;

+    uInt8 enhanceRegSave;

+    uInt8 samples;

+    int32 vdiff1[MAX_PSTN_SAMPLES];

+    int32 vdiff2[MAX_PSTN_SAMPLES];

+    int32 iloop1[MAX_PSTN_SAMPLES];

+    int32 iloop2[MAX_PSTN_SAMPLES];

+    int32 vdiff1_avg;

+    int32 vdiff2_avg;

+    int32 iloop1_avg;

+    int32 iloop2_avg;

+    int32 rl1;

+    int32 rl2;

+    int32 rl_ratio;

+    int femf_enable;

+    int32 vdiff_open;

+    int32 max_femf_vopen;

+    int return_status;

+}proslicDiffPSTNCheckObjType;

+

+typedef proslicDiffPSTNCheckObjType* proslicDiffPSTNCheckObjType_ptr;

+

+/** @}PSTN_CHECK */

+/** @}DIAGNOSTICS */

+/*****************************************************************************/

+/*

+** proslic.c function declarations

+*/

+

+/** @defgroup PROSLIC_IF_CFG ProSLIC System control interface functions

+ * This group of functions is called for allocating memory and configuring the ProSLIC API to call specific control interfaces that the user implemented.  

+ *

+ * @deprecated One should use the SiVoice equivalent functions. @ref SIVOICE_IF_CFG

+ * @{

+ */

+/*****************************************************************************/

+

+/** @defgroup PROSLIC_MEMORY_IF ProSLIC Memory allocation/deallocation 

+ * @deprecated One should use the SiVoice equivalent functions located: @ref SIVOICE_MEMORY_IF

+ * @{

+ */

+

+/**

+ * @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] **pCtrlIntf - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_createControlInterface

+ */

+

+int ProSLIC_createControlInterface (controlInterfaceType **pCtrlIntf);

+

+/**

+ * @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] **pDevice - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_createDevice

+ */

+

+int ProSLIC_createDevice (ProslicDeviceType **pDevice);

+

+/**

+ * @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] *hProslic - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_createChannel

+ */

+

+int ProSLIC_createChannel (proslicChanType_ptr *hProslic);

+

+/**

+ * @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] *hProslic - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_destroyChannel

+ */

+

+int ProSLIC_destroyChannel (proslicChanType_ptr *hProslic);

+

+/**

+ * @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] **pDevice - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_destroyDevice

+ */

+

+int ProSLIC_destroyDevice (ProslicDeviceType **pDevice);

+

+/**

+ * @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] **pCtrlIntf - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_destroyControlInterface

+ */

+

+int ProSLIC_destroyControlInterface (controlInterfaceType **pCtrlIntf);

+

+/** @} PROSLIC_MEMORY_IF */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_IO ProSLIC SPI/GCI access routines 

+ * This group of functions are used to associcate the transport mechanism (SPI, GCI) functions with the API.  The actual

+ * functions being references are normally implemented by the customer for their particualr OS and platform.

+ *

+ * @deprecated One should use the SiVoice equivalent functions located: @ref SIVOICE_IO

+ * @{

+ */

+

+/**

+ * @brief

+ *  Associate a interface object with a user supplied datastructure.  This 

+ *  structure is passed to all the I/O routines that the ProSLIC API calls.

+ *

+ * @param[in,out] *pCtrlIntf - which interface to associate 

+ *                the user supplied structure with.

+ * @param[in] hCtrl - the user supplied structure.

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setControlInterfaceCtrlObj

+ */

+

+int ProSLIC_setControlInterfaceCtrlObj (controlInterfaceType *pCtrlIntf, void *hCtrl);

+

+/**

+ * @brief

+ *  Associate a interface object with the reset function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] Reset_fptr - the reset function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use SiVoice_setControlInterfaceReset

+ */

+

+int ProSLIC_setControlInterfaceReset (controlInterfaceType *pCtrlIntf, ctrl_Reset_fptr Reset_fptr);

+

+/**

+ * @brief

+ *  Associate a interface object with the register write function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] WriteRegister_fptr - the register write function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use SiVoice_setControlInterfaceWriteRegister

+ */

+

+int ProSLIC_setControlInterfaceWriteRegister (controlInterfaceType *pCtrlIntf, ctrl_WriteRegister_fptr WriteRegister_fptr);

+

+/**

+ * @brief

+ *  Associate a interface object with the register read function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate the user supplied function with.

+ * @param[in] ReadRegister_fptr - the register read function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setControlInterfaceReadRegister

+ */

+

+int ProSLIC_setControlInterfaceReadRegister (controlInterfaceType *pCtrlIntf, ctrl_ReadRegister_fptr ReadRegister_fptr);

+

+/**

+ * @brief

+ *  Associate a interface object with the write RAM function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate the user supplied function with.

+ * @param[in] WriteRAM_fptr - the reset function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setControlInterfaceWriteRAM

+ */

+

+int ProSLIC_setControlInterfaceWriteRAM (controlInterfaceType *pCtrlIntf, ctrl_WriteRAM_fptr WriteRAM_fptr);

+

+/**

+ * @brief

+ *  Associate a interface object with the read RAM function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] ReadRAM_fptr - the read RAM function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setControlInterfaceReadRAM

+ */

+

+int ProSLIC_setControlInterfaceReadRAM (controlInterfaceType *pCtrlIntf, ctrl_ReadRAM_fptr ReadRAM_fptr);

+

+/** @} PROSLIC_IO */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_TIMER ProSLIC Timer functions

+ * This group of functions associates the customer supplied timer routines with the ProSLIC API.

+ * In most cases, only the delay function is needed.  The other functions which are related

+ * to elapsed time can be set to NULL under this situation.

+ *

+ * @deprecated One should use the SiVoice equivalent functions located: @ref SIVOICE_TIMER

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function associates a timer object - which is user defined, but it is 

+ *  used with ALL channels of the particular control interface.

+ *

+ * @param[in] pCtrlIntf - which control interface to associate the given timer object with.

+ * @param[in] hTimer  - the timer ojbect that is passed to all timer functions.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa SIVOICE_TIMER ProSLIC_setControlInterfaceDelay ProSLIC_setControlInterfaceTimeElapsed ProSLIC_setControlInterfaceGetTime

+ * @deprecated Use @ref SiVoice_setControlInterfaceTimerObj

+ */

+

+int ProSLIC_setControlInterfaceTimerObj (controlInterfaceType *pCtrlIntf, void *hTimer);

+

+/** 

+ * @brief

+ *  Associate a timer delay function with a given control interface.  The 

+ *  delay function takes in an argument of the timer object and the time in mSec

+ *  and delays the thread/task for at least the time requested.

+ *

+ *  @param[in] pCtrlIntf - which control interface to associate the function with.

+ *  @param[in] Delay_fptr - the pointer to the delay function.

+ *  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ *  @sa SIVOICE_TIMER ProSLIC_setControlInterfaceTimerObj ProSLIC_setControlInterfaceTimeElapsed ProSLIC_setControlInterfaceGetTime

+ * @deprecated Use @ref SiVoice_setControlInterfaceDelay

+ */

+

+int ProSLIC_setControlInterfaceDelay (controlInterfaceType *pCtrlIntf, system_delay_fptr Delay_fptr);

+

+/** 

+ *  @brief

+ *   Associate a time elapsed function with a given control interface.  The

+ *   time elapsed function uses the values from the function specified in

+ *   @ref SiVoice_setControlInterfaceGetTime and computes the delta time

+ *   in mSec.

+ *   @param[in] pCtrlIntf - which control interface to associate the function with.

+ *   @param[in] timeElapsed_fptr     - the pointer to the elapsed time function.

+ *   @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *   @sa SIVOICE_TIMER ProSLIC_setControlInterfaceTimerObj ProSLIC_setControlInterfaceDelay ProSLIC_setControlInterfaceGetTime

+ * @deprecated Use @ref SiVoice_setControlInterfaceTimeElapsed

+ */

+

+int ProSLIC_setControlInterfaceTimeElapsed (controlInterfaceType *pCtrlIntf, system_timeElapsed_fptr timeElapsed_fptr);

+

+/** 

+ *  @brief

+ *   Associate a time get function with a given control interface.  The

+ *   time get function returns a value in a form of a void pointer that 

+ *   is suitable to be used with the function specified in @ref SiVoice_setControlInterfaceTimeElapsed .

+ *   This is typically used as a timestamp of when an event started. The resolution needs to be in terms

+ *   of mSec.

+ *

+ *   @param[in] pCtrlIntf - which control interface to associate the function with.

+ *   @param[in] getTime_fptr -  the pointer to the get time function.

+ *   @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *   @sa SIVOICE_TIMER ProSLIC_setControlInterfaceTimerObj ProSLIC_setControlInterfaceDelay ProSLIC_setControlInterfaceTimeElapsed

+ * @deprecated Use @ref SiVoice_setControlInterfaceGetTime

+ */

+

+int ProSLIC_setControlInterfaceGetTime (controlInterfaceType *pCtrlIntf, system_getTime_fptr getTime_fptr);

+

+/** @} PROSLIC_TIMER */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_PROC_CONTROL ProSLIC Process control 

+ * @{*/

+

+/**

+ * @brief

+ *  This function assoicates a user defined semaphore/critical section

+ *  function with the given interface.

+ *

+ * @param[in,out] pCtrlIntf - the interface to associate the function with.

+ * @param[in] semaphore_fptr - the function pointer for semaphore control.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @deprecated Use @ref SiVoice_setControlInterfaceSemaphore

+ */

+

+int ProSLIC_setControlInterfaceSemaphore (controlInterfaceType *pCtrlIntf, ctrl_Semaphore_fptr semaphore_fptr);

+

+/** @} PROSLIC_PROC_CONTROL */

+/** @} PROSLIC_IF_CFG */

+

+/*****************************************************************************/

+/** @defgroup GEN_CFG General configuration

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function initializes the various channel structure elements.  

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ *  It is suggested to migrate to the @ref SiVoice_SWInitChan in new

+ *  implementations.

+ *

+ * @param[in,out] hProslic - which channel to initialize.

+ * @param[in] channel - Which channel index is this.  For example, for a 4 channel system, this would typically range from 0 to 3.

+ * @param[in] chipType - chipset family type for example @ref SI321X_TYPE or @ref SI3217X_TYPE

+ * @param[in] deviceObj - Device structure pointer associated with this channel

+ * @param[in] pCtrlIntf - Control interface associated with this channel

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_SWInitChan

+ */

+

+int ProSLIC_SWInitChan (proslicChanType_ptr hProslic,int channel,int chipType, ProslicDeviceType*deviceObj,controlInterfaceType *pCtrlIntf);

+

+

+/** 

+ *  

+ * @brief

+ *  Calibrates the ProSLIC (on some variants).  This typically only needs to be performed during 

+ *  initial setup and will itterate through all channels specified by the size parameter starting

+ *  from 0.

+ *

+ * @param[in] hProslic - array of channels

+ * @param[in] size - number of channels present/number to itterate through.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *  

+ * @sa PROSLIC_LB_CALIBRATION

+ * @deprecated This function does not need to be called externally since the normal initialization function will take care of this.

+ */

+

+int ProSLIC_Cal (proslicChanType_ptr *hProslic, int size);

+

+/**

+ * @brief

+ * This function calls the user supplied reset function to put and take out the channel from reset. This is

+ * typically done during initialization and may be assumed to be a "global" reset - that is 1 reset per

+ * daisychain vs. 1 per device.

+ *

+ * @note This function can take more than 500 mSec to complete.

+ *

+ * @param[in] hProslic - which channel to reset, if a "global reset", then any channel on the daisy chain is sufficient.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int ProSLIC_Reset (proslicChanType_ptr hProslic);

+

+/**

+ * @brief

+ *  Safely shutdown channel w/o interruptions to other active channels

+ *

+ * @param[in] hProslic - which channel to shut down

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_ShutdownChannel (proslicChanType_ptr hProslic);

+

+/**

+ * @brief

+ *  Loads patch and initializes all ProSLIC devices. Performs all calibrations except

+ *  longitudinal balance.

+ *

+ * @param[in] hProslic - which channel(s) to initialize, if size > 1, then the start of the array

+ * of channels to be initialized.

+ * @param[in] size - the number of channels to initialize.

+ * @param[in] preset - general configuration preset to apply

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa ProSLIC_Init

+ */

+

+int ProSLIC_Init_MultiBOM (proslicChanType_ptr *hProslic, int size, int preset);

+

+/**

+ * @brief

+ *  Loads patch and initializes all ProSLIC devices. Performs all calibrations except

+ *  longitudinal balance.

+ *

+ * @param[in] hProslic - which channel(s) to initialize, if size > 1, then the start of the array

+ * of channels to be initialized.

+ * @param[in] size - the number of channels to initialize.

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa ProSLIC_InitBroadcast

+ */

+

+int ProSLIC_Init (proslicChanType_ptr *hProslic, int size);

+

+/**

+ * @brief

+ *  Loads patch and initializes all ProSLIC devices on the same daisy chain including 

+ *  performing all calibrations and applying the patch (if necessary).

+ *

+ * @param[in] hProslic - which channel(s) to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @deprecated 

+ * Use the @ref ProSLIC_Init function

+ *

+ * @sa ProSLIC_Init

+ */

+

+int ProSLIC_InitBroadcast (proslicChanType_ptr *hProslic);

+

+/**

+ * @brief

+ *  Performs soft reset then calls ProSLIC_Init()

+ *

+ * @param[in] hProslic - which channel(s) to initialize, if size > 1, then the start of the array

+ * of channels to be initialized.

+ * @param[in] size - the number of channels to initialize.

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa ProSLIC_InitBroadcast

+ */

+

+int ProSLIC_Reinit (proslicChanType_ptr hProslic, int size);

+

+

+/**

+ * @brief 

+ * Loads registers and RAM in the ProSLICs specicified.

+ *

+ * @param[in] pProslic - array of channels

+ * @param[in] pRamTable - array of RAM locations and values to write

+ * @param[in] pRegTable - array of register locations and values to write

+ * @param[in] size - number of ProSLICS to write to.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @deprecated This function should NOT be used since it can bypass the standard initialization/operational state of the

+ * ProSLIC.

+ */

+

+int ProSLIC_LoadRegTables (proslicChanType_ptr *pProslic,ProslicRAMInit *pRamTable, ProslicRegInit *pRegTable, int size);

+

+/**

+ * @brief 

+ *  Configure impedence synthesis

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] preset - which impedence configuration to load from the constants file.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note This function can be disabled by @ref DISABLE_ZSYNTH_SETUP

+ */

+

+

+int ProSLIC_ZsynthSetup (proslicChanType_ptr hProslic,int preset);

+

+/**

+ * @brief

+ *  This function configures the CI bits (GCI mode)

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] preset - which GCI preset to use from the contstants file

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note This function can be disabled by @ref DISABLE_CI_SETUP

+ */

+

+int ProSLIC_GciCISetup (proslicChanType_ptr hProslic,int preset);

+

+/**

+ * @brief

+ *  This function sets the modem tone detection parameters for ProSLIC by loading a modem

+ *  tone detection preset

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] preset - which MODEM preset to use.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int ProSLIC_ModemDetSetup (proslicChanType_ptr hProslic,int preset);

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_ERROR_CONTROL Return code functions

+ * This group of functions are used for when the ProSLIC API function does

+ * not reutrn a standard error value and instead returns back some other value.

+ * You may call these functions to see if there was an error preset and to clear 

+ * the error state.

+ *

+ * @{

+ */

+

+/**

+ * @brief

+ * This function returns the error flag that may be set by some function in where

+ * @ref errorCodeType is not returned.  

+ *

+ * @note For functions that DO return errorCodeType, the return value here is undefined.

+ *

+ * @param[in] hProslic - which channel to clear the error flag

+ * @param[in,out] error - The current value of error flag.  

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_getErrorFlag

+ *

+ * @sa ProSLIC_clearErrorFlag

+ */

+

+int ProSLIC_getErrorFlag (proslicChanType_ptr hProslic, int *error);

+

+/**

+ * @brief

+ *  This function clears the error flag that may be set by some function in where

+ *  @ref errorCodeType is not returned.

+ *

+ * @param[in,out] hProslic - which channel to clear the error flag

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_clearErrorFlag

+ *

+ * @sa ProSLIC_getErrorFlag

+ */

+

+int ProSLIC_clearErrorFlag (proslicChanType_ptr hProslic);

+

+/** @} PROSLIC_ERROR_CONTROL */

+/*****************************************************************************/

+/** @defgroup PROSLIC_DEBUG Debug 

+ * This group of functions enables/disables debug messages as well as dump 

+ * register contents.

+ * @{

+ */

+

+/**

+ * @brief

+ * This function enables or disables the debug mode, assuming @ref ENABLE_DEBUG is set in the configuration file.

+ *

+ * @param[in] hProslic - which channel to set the debug flag.

+ * @param[in] debugEn - 0 = Not set, 1 = set.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setSWDebugMode

+ *

+ */

+

+int ProSLIC_setSWDebugMode (proslicChanType_ptr hProslic, int debugEn);

+

+/**

+ * @brief

+ * This function allows access to SPI read register function pointer from interface

+ *

+ * @param[in] hProslic - pointer to channel structure

+ * @param[in] addr - address to read

+ * @retval uInt8 - register contents

+ *

+ */

+uInt8 ProSLIC_ReadReg (proslicChanType_ptr hProslic, uInt8 addr);

+

+/**

+ * @brief

+ * This function allows access to SPI write register function pointer from interface

+ *

+ * @param[in] hProslic - pointer to channel structure

+ * @param[in] addr - address to write

+ * @param[in] data to be written

+ * @retval int - @ref RC_NONE

+ *

+ */

+int ProSLIC_WriteReg (proslicChanType *pProslic, uInt8 addr, uInt8 data);

+

+/**

+ * @brief

+ * This function allows access to SPI read RAM function pointer from interface

+ *

+ * @param[in] hProslic - pointer to channel structure

+ * @param[in] addr - address to read

+ * @retval ramData - RAM contents

+ *

+ */

+ramData ProSLIC_ReadRAM (proslicChanType *pProslic, uInt16 addr);

+

+/**

+ * @brief

+ * This function allows access to SPI write RAM function pointer from interface

+ *

+ * @param[in] hProslic - pointer to channel structure

+ * @param[in] addr - address to write

+ * @param[in] data to be written

+ * @retval int - @ref RC_NONE

+ *

+ */

+int ProSLIC_WriteRAM (proslicChanType *pProslic, uInt16 addr, ramData data);

+

+/**

+ * @brief

+ * This function dumps to console the register contents of several

+ * registers and RAM locations.

+ *

+ * @param[in] pProslic - which channel to dump the register contents of.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+int ProSLIC_PrintDebugData (proslicChanType *pProslic);

+

+/**

+ * @brief

+ * This function dumps the registers to the console using whatever

+ * I/O method is defined by LOGPRINT

+ *

+ * @param[in] pProslic - which channel to dump the register contents of.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+int ProSLIC_PrintDebugReg (proslicChanType *pProslic);

+

+/**

+ * @brief

+ * This function dumps the RAM to the console using whatever

+ * I/O method is defined by LOGPRINT

+ *

+ * @param[in] pProslic - which channel to dump the RAM contents of.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+int ProSLIC_PrintDebugRAM (proslicChanType *pProslic);

+

+/** @} PROSLIC_DEBUG */

+/*****************************************************************************/

+/** @defgroup PROSLIC_ENABLE Enable/disable channels (for init)

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function sets the channel enable status.  If NOT set, then when

+ *  the various initialization routines such as @ref ProSLIC_SWInitChan is called,

+ *  then this particular channel will NOT be initialized.

+ *

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ * @param[in,out] hProslic - which channel to return the status.

+ * @param[in] chanEn - The new value of the channel enable field. 0 = NOT enabled, 1 = enabled.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_getChannelEnable

+ */

+

+int ProSLIC_setChannelEnable (proslicChanType_ptr hProslic, int chanEn);

+

+/**

+ * @brief

+ *  This function returns back if the channel is enabled or not.

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ * @param[in] hProslic - which channel to return the status.

+ * @param[in,out] chanEn - The current value of if the channel is enabled. 0 = NOT enabled, 1 = enabled.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_setChannelEnable

+ */

+

+int ProSLIC_getChannelEnable (proslicChanType_ptr hProslic, int* chanEn);

+

+/**

+ * @brief

+ *  This function sets the channel enable status of the FXO channel on ProSLIC devices

+ *  with integrated FXO.  If NOT set, then when

+ *  the various initialization routines such as @ref ProSLIC_SWInitChan is called,

+ *  then this particular channel will NOT be initialized.

+ *

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ * @param[in,out] pProslic - which channel to return the status.

+ * @param[in] enable - The new value of the channel enable field. 0 = NOT enabled, 1 = enabled.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_getChannelEnable

+ */

+

+int ProSLIC_SetDAAEnable(proslicChanType *pProslic, int enable);

+

+/** @} PROSLIC_ENABLE */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_PATCH Patch management.

+ * This group of functions write and verify the patch data needed by the 

+ * ProSLIC chipset.

+ * @{

+ */

+

+/**

+ * @brief 

+ * Calls patch loading function for a particular channel/ProSLIC

+ *

+ * @param[in] hProslic - which channel/ProSLIC should be patched

+ * @param[in] pPatch - the patch data

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * 

+ * @note This function should not be called directly under normal circumstances since the initialization function should 

+ *       perform this operation.

+ *

+ * @sa ProSLIC_Init

+ */

+

+int ProSLIC_LoadPatch (proslicChanType_ptr hProslic,proslicPatch *pPatch);

+

+/**

+ * @brief 

+ *  Verifies patch loading function for a particular channel/ProSLIC

+ *

+ * @param[in] hProslic - which channel/ProSLIC should be patched

+ * @param[in] pPatch - the patch data to verify was written to.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * 

+ * @note This function should not be called directly under normal circumstances since the initialization function should 

+ *       perform this operation, unless @ref DISABLE_VERIFY_PATCH is defined.

+ *

+ * @sa ProSLIC_Init

+ */

+

+int ProSLIC_VerifyPatch (proslicChanType_ptr hProslic,proslicPatch *pPatch);

+

+/** @} PROSLIC_PATCH */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_GPIO GPIO Control

+ * This group of functions configure, read and write the GPIO status pins.

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function configures the ProSLIC GPIOs by loading a gpio preset that was

+ *  set in the configuration tool.

+ * @param[in] hProslic - which channel to configure the GPIO pins.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa ProSLIC_GPIOControl

+ */

+

+ int ProSLIC_GPIOSetup (proslicChanType_ptr hProslic);

+

+/**

+ * @brief

+ *  This function controls the GPIOs of the ProSLIC.

+ *

+ * @param[in] hProslic - which channel to modify

+ * @param[in,out] pGpioData  - pointer to GPIO status (typcially 1 byte)

+ * @param[in] read - 1 = Read the status, 0 = write the status

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa ProSLIC_GPIOSetup

+ */

+

+int ProSLIC_GPIOControl (proslicChanType_ptr hProslic,uInt8 *pGpioData, uInt8 read);

+

+/** @} PROSLIC_GPIO */

+/** @} GEN_CFG */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_PULSE_METER Pulse Metering

+ *

+ * This group contains functions related to pulse metering.

+ * @{

+ */

+

+ /**

+ * @brief

+ *  This function configures the ProSLIC pulse metering by loading a pulse metering preset.

+ *

+ * @param[in] hProslic - which channel should be configured

+ * @param[in] preset - which preset to load from the defined settings made in the configuration tool.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_PulseMeterStart ProSLIC_PulseMeterStop

+ */

+

+int ProSLIC_PulseMeterSetup (proslicChanType_ptr hProslic,int preset);

+

+/**

+ * @brief

+ *  This function starts the pulse metering tone.

+ *

+ * @param[in] hProslic - which channel should play the tone.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa ProSLIC_PulseMeterSetup ProSLIC_PulseMeterStop

+ *

+ */

+

+int ProSLIC_PulseMeterStart (proslicChanType_ptr hProslic);

+

+/**

+ * @brief

+ *  This function stops the pulse metering tone.

+ *

+ * @param[in] hProslic - which channel should play the tone.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa PProSLIC_PulseMeterStart ProSLIC_PulseMeterSetup

+ *

+ */

+

+int ProSLIC_PulseMeterStop (proslicChanType_ptr hProslic);

+

+/** @} PROSLIC_PULSE_METER */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_INTERRUPTS Interrupt control and decode

+ * @{

+ */

+

+/**

+ * @brief 

+ *  Enables interrupts configured in the general configuration data structure.

+ *

+ * @param[in]  hProslic - which channel to enable the interrupts.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * 

+ */

+

+int ProSLIC_EnableInterrupts (proslicChanType_ptr hProslic);

+

+/**

+ * @brief 

+ *  This function reads the interrupts from the ProSLIC and places them into 

+ *  a @ref proslicIntType structure which contains up to @ref MAX_PROSLIC_IRQS

+ *  interrupts. 

+ *

+ * @param[in] hProslic - which channel to enable the interrupts.

+ * @param[in,out] pIntData - this structure contains the interupts pending and the number of interrupts.

+ * @retval int - number of interrupts pending or RC_CHANNEL_TYPE_ERR if wrong chip type or 0 for no interrupts.

+ * 

+ */

+

+int ProSLIC_GetInterrupts (proslicChanType_ptr hProslic,proslicIntType *pIntData);

+

+/**

+ * @brief

+ *  This function disables and clears interrupts on the given channel.

+ *

+ *  @param[in] hProslic - which channel to disable

+ *  @retval int - error from @ref errorCodeType @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_DisableInterrupts (proslicChanType_ptr hProslic);

+

+/** @} PROSLIC_INTERRUPTS */

+

+/*****************************************************************************/

+/** @defgroup SIGNALING Signaling - ring & line state, and hook state

+ * @{

+ */

+

+/**

+* Function: PROSLIC_ReadHookStatus

+*

+* @brief 

+* Determine hook status

+* @param[in] hProslic - which channel to read from.

+* @param[out] *pHookStat - will contain either @ref PROSLIC_ONHOOK or @ref PROSLIC_OFFHOOK

+* 

+*/

+

+int ProSLIC_ReadHookStatus (proslicChanType_ptr hProslic,uInt8 *pHookStat);

+

+/*****************************************************************************/

+/** @defgroup LINESTATUS Line Feed status 

+ * @{

+ */

+

+/** 

+ * @brief

+ *  This function sets the linefeed state.

+ *

+ * @param[in] hProslic - which channel to modify

+ * @param[in] newLinefeed - new line feed state  - examples: LF_OPEN, LF_FWD_ACTIVE

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_SetLinefeedStatus (proslicChanType_ptr hProslic,uInt8 newLinefeed);

+

+/** 

+ * @brief

+ *  This function sets the linefeed state for all channels on the same daisychain.

+ *

+ * @param[in] hProslic - which channel to modify

+ * @param[in] newLinefeed - new line feed state  - examples: LF_OPEN, LF_FWD_ACTIVE

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_SetLinefeedStatusBroadcast (proslicChanType_ptr hProslic,uInt8 newLinefeed);

+

+/** 

+ * @brief

+ *  This function sets the polarity/wink state of the channel.

+ *

+ * @param[in] hProslic - which channel to modify

+ * @param[in] abrupt  - to change the state immeediately

+ * @param[in] newPolRevState - new polarity state  - examples: POLREV_STOP, POLREV_START and WINK_START

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_PolRev (proslicChanType_ptr hProslic,uInt8 abrupt,uInt8 newPolRevState);

+

+/** @} LINESTATUS */

+

+/*****************************************************************************/

+/** @defgroup RING_CONTROL Ring generation 

+ * @{

+ */

+

+/**

+ * @brief 

+ *  Configure the ringer to the given preset (see your constants header file for exact value to use).

+ *  This includes timing, cadence, OHT mode, voltage levels, etc.

+ *

+ * @param[in]  hProslic - which channel to configure

+ * @param[in]  preset - which of the xxxx_Ring_Cfg structures to use to configure the channel.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note This function can be compiled out by defining @ref DISABLE_RING_SETUP

+ *

+ * @sa ProSLIC_dbgSetRinging ProSLIC_RingStart ProSLIC_RingStop

+ */

+

+int ProSLIC_RingSetup (proslicChanType_ptr hProslic,int preset);

+

+/**

+ * @brief 

+ *  Starts the ringer as confgured by @ref ProSLIC_RingSetup .  If the active and inactive timers are enabled,

+ *  the ProSLIC will automatically turn on/off the ringer as programmed, else one will need to

+ *  manually implement the ring cadence.  In either case, one will need to call ProSLIC_RingStop to

+ *  stop the ringer or one may call @ref ProSLIC_SetLinefeedStatus to change the state directly.

+ *

+ * @param[in]  hProslic - which channel to enable ringing.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note This function can be compiled out by defining @ref DISABLE_RING_SETUP

+ *

+ * @sa ProSLIC_dbgSetRinging ProSLIC_RingStop ProSLIC_RingSetup

+ */

+

+int ProSLIC_RingStart (proslicChanType_ptr hProslic);

+

+/** 

+ * @brief

+ *  Stop the ringer on the given channel and set the line state to forward active.

+ *

+ * @param[in] hProslic - which channel to modify.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa ProSLIC_RingSetup ProSLIC_RingStart 

+ */

+

+int ProSLIC_RingStop (proslicChanType_ptr hProslic);

+

+/** 

+ * @brief

+ *  Provisionary function for setting up Ring type, frequency, amplitude and dc offset and

+ *  to store them in the given preset. 

+ *

+ * @note: This function calculates the values, it does not set them.

+ *

+ * @param[in] pProslic - which channel to modify

+ * @param[in] ringCfg - how to configure the channel's ringer

+ * @param[in] preset - where to store the new configuration.

+ * @sa ProSLIC_RingSetup ProSLIC_RingStart ProSLIC_RingStop

+ */

+

+int ProSLIC_dbgSetRinging (proslicChanType *pProslic, ProSLIC_dbgRingCfg *ringCfg, int preset);

+

+/** @} RING_CONTROL */

+/** @} SIGNALING */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_AUDIO Audio

+ * This group of functions contains routines to configure the PCM bus, to generate tones, and to send FSK data.

+ *

+ * In order to start using the PCM bus, you would typically initialize the PCM bus with code similar to

+ * the following:

+ *

+ * @code

+ * if( (ProSLIC_PCMSetup(myProSLIC, MY_COMPANDING) != RC_NONE) 

+ * 	|| (ProSLIC_PCMTimeSlotSetup(myProSLIC, pcm_ts, pcm_ts) != RC_NONE)

+ * 	|| (ProSLIC_PCMStart(myProSLIC) != RC_NONE))

+ * {

+ * 	return MY_PCM_INIT_ERROR;

+ * }

+ * @endcode

+ *

+ * @{ 

+ * @defgroup TONE_GEN Tone generation 

+ * This group of functions is related to playing out general tones - such as dial tone, busy tone, etc.  One would

+ * typically call @ref ProSLIC_ToneGenSetup first followed by @ref ProSLIC_ToneGenStart and after some time, a call to

+ * @ref ProSLIC_ToneGenStop to stop the tone.  The direction of the tone and cadence (if any) are configured using the 

+ * GUI configuration tool's TONE dialog box and then saved in the constants file.

+ *

+ * @{

+ */

+/**

+ * @brief 

+ *  Configure the tone generator to the given preset (see your constants header file for exact value to use).  It does NOT

+ *  play a particular tone out.

+ *

+ * @warning If @ref ProSLIC_FSKSetup was called earlier, this function will need to be called again.

+ *

+ * @param[in]  hProslic - which channel to configure

+ * @param[in]  preset - which of the xxxx_Tone_Cfg structures to use to configure the channel.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note This function can be compiled out by defining @ref DISABLE_TONE_SETUP.

+ *

+ * @note Typically, if one is using the ProSLIC for tone generation, you will be calling this function prior to each call

+ *       into @ref ProSLIC_ToneGenStart so that the correct tone is played out.

+ */

+

+int ProSLIC_ToneGenSetup (proslicChanType_ptr hProslic,int preset);

+

+/**

+ * @brief

+ *  This function starts the tone configured by @ref ProSLIC_ToneGenSetup.  

+ *  It is assumed that the @ref PROSLIC_AUDIO setup was performed

+ *  prior to calling this function.  Also, it is suggested that 

+ *  @ref ProSLIC_ToneGenSetup be called if @ref FSK_CONTROL

+ *  functions were used.

+ *

+ *  @param[in] hProslic - which channel should play the tone.

+ *  @param[in] timerEn - are the timers to be enabled?  1 = Yes, 0 = No. When in doubt, set to 1.

+ *  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_ToneGenSetup ProSLIC_ToneGenStop

+ */

+

+int ProSLIC_ToneGenStart (proslicChanType_ptr hProslic, uInt8 timerEn);

+

+/**

+ * @brief

+ *  This function turns off tone generation initiated by @ref ProSLIC_ToneGenStart.

+ *

+ * @param[in] hProslic - which channel should stop playing the tone.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_ToneGenStart ProSLIC_ToneGenSetup

+ */

+

+int ProSLIC_ToneGenStop (proslicChanType_ptr hProslic);

+

+/** @} TONE_GEN */

+

+/*****************************************************************************/

+/** @defgroup FSK_CONTROL FSK/Caller ID generation 

+ * This group of functions is related to FSK generation, typically used with Caller ID/Call Waiting 

+ * functionality. To set the frequencies, the data rate, and the FSK FIFO depth, please use the configuration

+ * GUI FSK dialog box.

+ *

+ * Here's a simple example code fragment to send data via FSK:

+ *

+ * @code

+ * if( ProSLIC_FSKSetup(myProSLICChan, PROSLIC_NORTH_AMERICA_FSK) == RC_NONE)

+ * {

+ * 	ProSLIC_EnableCID(myProSLICChan);

+ *

+ *	bytes_left_to_send = bufsz;

+ *

+ * 	do

+ * 	{

+ * 		if(bytes_left_to_send < FIFO_DEPTH)

+ * 		{

+ * 			bytes_to_send = bytes_left_to_send;

+ * 		}

+ * 		else

+ * 		{

+ * 			bytes_to_send = FIFO_DEPTH;

+ *		}

+ *

+ * 		if( ProSLIC_SendCID(myProSLICChan,buf,bytes_to_send) != RC_NONE)

+ * 		{

+ * 			ProSLIC_DisableCID(myProSLICChan);

+ * 			return MY_FSK_ERROR;

+ * 		}

+ *            

+ *		bytes_left_to_send -= bytes_to_send;

+ *		

+ *		if(bytes_left_to_send)

+ *		{

+ *			do

+ *			{

+ *				ProSLIC_CheckCIDBuffer(myProSLICChan, &is_fifo_empty);

+ *

+ *			} while( is_fifo_empty != 1 );

+ *		}	

+ *				

+ * 	}while( bytes_left_to_send > 0);

+ *

+ * 	ProSLIC_DisableCID(myProSLICChan);

+ * @endcode

+ *

+ * @note The above code fragment is sub-optimal since it does constantly poll the CID buffer

+ * state - one may want to implement the actual code using interrupts.

+ * @{

+ */

+

+/** 

+ * @brief

+ *  Configures the FSK generator from a configuration generated by the config tool.

+ *

+ * @warning If @ref ProSLIC_ToneGenSetup was called earlier, this function will need to be called again.

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] preset - which FSK configuration to use.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note This function can be compiled out by defining DISABLE_FSK_SETUP

+ */

+

+int ProSLIC_FSKSetup (proslicChanType_ptr hProslic,int preset);

+

+/**

+ * @brief 

+ *  This function enables FSK mode and clears the FSK FIFO.  It is assumed that PCM has been enabled and that @ref ProSLIC_FSKSetup

+ *  has been called at some point.  

+ *

+ * @warning If @ref ProSLIC_ToneGenSetup was called earlier, @ref ProSLIC_FSKSetup will need to be called again.

+ *

+ * @param[in] hProslic - which channel to check upon.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int ProSLIC_EnableCID (proslicChanType_ptr hProslic);

+

+/**

+ * @brief 

+ *  This function disables FSK mode.

+ *

+ * @param[in] hProslic - which channel to disable FSK mode.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int ProSLIC_DisableCID (proslicChanType_ptr hProslic);

+

+/**

+ * @brief 

+ *  Check if the FSK FIFO is empty or not.

+ *

+ * @param[in] hProslic - which channel to check upon.

+ * @param[out] fsk_buf_avail - is the buffer available? 1 = Yes, 0  = No.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note - This modifies the IRQ1 register contents, so some other interrupts may be lossed. An alternative is to enable the

+ *         FSK FIFO interrupt and trigger off of it when it does occur in your interrupt service routine.

+ */

+

+int ProSLIC_CheckCIDBuffer (proslicChanType_ptr hProslic, uInt8 *fsk_buf_avail);

+

+/**

+ * @brief 

+ *  Send numBytes as FSK encoded data.  It is assumed that numBytes <= FIFO Depth (typically 8) and that the FIFO

+ *  is free. It is also assumed that @ref ProSLIC_PCMStart has been called and that we're in 

+ *  @ref LF_FWD_OHT or @ref LF_REV_OHT mode for Type-1 or  @ref LF_REV_ACTIVE or @ref LF_FWD_ACTIVE

+ *  if we're in Type-2 caller ID.

+ *

+ * @param[in] hProslic - which channel to send the data through.

+ * @param[in] buffer - byte array of data to send.

+ * @param[in] numBytes - number of bytes to send. MUST be less than or equal to the FIFO size

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_CheckCIDBuffer ProSLIC_FSKSetup ProSLIC_EnableCID ProSLIC_DisableCID

+ */

+

+int ProSLIC_SendCID (proslicChanType_ptr hProslic, uInt8 *buffer, uInt8 numBytes);

+

+/** 

+ * @brief Control if the start/stop bits are enabled.

+ * 

+ * @param[in] hProslic - which channel to adjust

+ * @param[in] enable_startStop - TRUE - start/stop bits are enabled, FALSE - disabled

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * 

+ * @note: This does not replace @ref ProSLIC_FSKSetup, but is a suppliment that toggles

+ * one of the registers that the preset modifies.  It is assumed that @ref ProSLIC_FSKSetup

+ * was called at some point earlier in the code flow.

+ */

+

+int ProSLIC_ModifyCIDStartBits(proslicChanType_ptr hProslic, uInt8 enable_startStop);

+

+

+/** @} FSK_CONTROL */

+

+/*****************************************************************************/

+/** @defgroup AUDIO_CONTROL Audio control/configuration 

+ * @{

+ */

+/** @defgroup PCM_CONTROL PCM control 

+ * This group of functions is used to configure and control the PCM bus.  It is essential that @ref ProSLIC_PCMSetup,

+ * @ref ProSLIC_PCMTimeSlotSetup and @ref ProSLIC_PCMStart are called prior to any tone or FSK generation.

+ *

+ * See @ref PROSLIC_AUDIO code fragment on how the functions relate during initialization.

+ * 

+ * @{

+ */

+

+/** 

+ * @brief 

+ *  This configures the PCM bus with parameters such as companding and data latching timing.

+ *

+ * @param[in] hProslic - which channel should be configured

+ * @param[in] preset - which preset to use from the constants file (see configuration tool, PCM dialog box)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_PCMTimeSlotSetup ProSLIC_PCMStart

+ */

+

+int ProSLIC_PCMSetup (proslicChanType_ptr hProslic,int preset);

+

+/** 

+ * @brief 

+ *  This configures the ProSLIC to latch and send the PCM data at a particular timeslot in terms of PCM clocks (PCLK).

+ *

+ *  Typically, for aLaw and uLaw, one can use the following calculation to set the rxcount and txcount parameters:

+ *

+ *  rxcount = txcount = (channel_number)*8;

+ *

+ *  For 16 bit linear, one can do the following:

+ *

+ *  rxcount = txcount = (channel_number)*16;

+ *

+ * where channel_number = which ProSLIC channel on the PCM bus.  For example, if one were to have 2 dual channel

+ * ProSLIC's on the same PCM bus, this value would range from 0 to 3. 

+ *

+ * @param[in] hProslic - which channel should be configured

+ * @param[in] rxcount -  how many clocks until reading data from the PCM bus

+ * @param[in] txcount -  how many clocks until writing data to the PCM bus.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_PCMSetup ProSLIC_PCMStart

+ */

+

+int ProSLIC_PCMTimeSlotSetup (proslicChanType_ptr hProslic, uInt16 rxcount, uInt16 txcount);

+

+/**

+ * @brief

+ *  This enables PCM transfer on the given ProSLIC channel.

+ *

+ * @param[in] hProslic - - which channel should be enabled

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_PCMSetup ProSLIC_PCMTimeSlotSetup ProSLIC_PCMStop

+ */

+

+int ProSLIC_PCMStart (proslicChanType_ptr hProslic);

+

+/**

+ * @brief

+ *  This disables PCM transfer on the given ProSLIC channel. Typically, this is called for debugging

+ *  purposes only.

+ *

+ * @param[in] hProslic - - which channel should be disabled

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_PCMSetup ProSLIC_PCMTimeSlotSetup ProSLIC_PCMStart

+ */

+

+int ProSLIC_PCMStop (proslicChanType_ptr hProslic);

+

+/**

+ * @brief 

+ * Program desired loopback test mode for the given channel.

+ *

+ * @param[in] hProslic -  which channel should be modified 

+ * @param[in] newMode - what is the desired loopback mode.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int ProSLIC_SetLoopbackMode (proslicChanType_ptr hProslic, ProslicLoopbackModes newMode);

+

+/**

+ * @brief 

+ * Program desired mute test mode for the given channel.

+ *

+ * @param[in] hProslic - which channel should be modified 

+ * @param[in] muteEn - what is the desired mode.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int ProSLIC_SetMuteStatus (proslicChanType_ptr hProslic, ProslicMuteModes muteEn);

+

+/** @} PCM_CONTROL */

+

+/*****************************************************************************/

+/** @defgroup GAIN_CONTROL Gain control 

+ * @{

+ */

+

+/** 

+ * @brief

+ *  Sets the TX audio gain (toward the network). This funcion DOES NOT actually calculate the values for the preset.  

+ *  To dynamically calculate the values, you would need to call @ref ProSLIC_dbgSetTXGain .

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] preset - which preset to use (this may be from the constants file)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note One can use this in conjunction with @ref ProSLIC_dbgSetTXGain to dynamically 

+ * change the audio gain. It is important to have the presets of both routines match.

+ *

+ * The following code * fragment will set the TX audio gain to -5 dB:

+ *

+ * @code

+ * ProSLIC_dbgSetTXGain(myChannel, -5, MY_IMPEDENCE,0);

+ * ProSLIC_TXAudioGainSetup(myChannel,0);

+ * @endcode

+ *

+ * @sa ProSLIC_RXAudioGainSetup ProSLIC_dbgSetTXGain ProSLIC_AudioGainSetup

+ */

+

+int ProSLIC_TXAudioGainSetup (proslicChanType_ptr hProslic,int preset);

+

+/** 

+ * @brief

+ *  Configures the RX audio gain (toward the telephone). This funcion DOES NOT actually calculate the values for the preset. 

+ *  To dynamically calculate the values, you would need to call @ref ProSLIC_dbgSetRXGain .

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] preset - which preset to use (this may be from the constants file)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note One can use this in conjunction with @ref ProSLIC_dbgSetRXGain to dynamically 

+ * change the audio gain. It is important to have the presets of both routines match.

+ *

+ * The following code * fragment will set the RX audio gain to -1 dB:

+ *

+ * @code

+ * ProSLIC_dbgSetRXGain(myChannel, -1, MY_IMPEDENCE,0);

+ * ProSLIC_RXAudioGainSetup(myChannel,0);

+ * @endcode

+ *

+ * @sa ProSLIC_TXAudioGainSetup ProSLIC_dbgSetRXGain ProSLIC_AudioGainSetup

+ */

+

+int ProSLIC_RXAudioGainSetup (proslicChanType_ptr hProslic,int preset);

+

+/** 

+ * @brief

+ *  Configures and sets the audio gains - for both RX (toward the phone) and the TX (toward the network). Unlike

+ *  the @ref ProSLIC_RXAudioGainSetup and @ref ProSLIC_TXAudioGainSetup this does both the calculations and then

+ *  configures the given channel in one step.  It is assumed that the preset gain array is at least 2 elements in size.

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] rxgain - what is the gain/loss of the RX transmit path in 1 dB units (negative = attenuation)

+ * @param[in] txgain - what is the gain/loss of the TX transmit path in 1 dB units (negative = attenuation)

+ * @param[in] preset - what is the impedance preset value

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * The following code * fragment will set the RX audio gain to -1 dB snd TX audio gain to -5 dB:

+ *

+ * @code

+ * ProSLIC_AudioGain(myChannel, -1, -5,  MY_IMPEDENCE);

+ * @endcode

+ *

+ * @sa ProSLIC_TXAudioGainSetup ProSLIC_dbgSetRXGain ProSLIC_dbgSetRXGain ProSLIC_dbgSetTXGain

+ */

+

+int ProSLIC_AudioGainSetup (proslicChanType_ptr hProslic,int32 rxgain,int32 txgain,int preset);

+

+/**

+ * @brief

+ *  This function calculates the preset values for the RX audio (toward the telephone) - it does NOT set the 

+ *  actual register values.  For that, please use @ref ProSLIC_RXAudioGainSetup .

+ *

+ * @param[in] pProslic - which channel to configure

+ * @param[in] gain - gain to set the preset values to.

+ * @param[in] impedance_preset - impedence preset in the constants file.

+ * @param[in] audio_gain_preset - index to the audio gain preset to store the value.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_RXAudioGainSetup ProSLIC_AudioGainSetup ProSLIC_dbgSetTXGain

+ */

+

+int ProSLIC_dbgSetRXGain (proslicChanType *pProslic, int32 gain, int impedance_preset, int audio_gain_preset);

+

+/**

+ * @brief

+ *  This function calculates the preset values for the TX audio (toward the network) - it does NOT set the 

+ *  actual register values.  For that, please use @ref ProSLIC_TXAudioGainSetup .

+ *

+ * @param[in] pProslic - which channel to configure

+ * @param[in] gain - gain to set the preset values to.

+ * @param[in] impedance_preset - impedence preset in the constants file.

+ * @param[in] audio_gain_preset - index to the audio gain preset to store the value.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_TXAudioGainSetup ProSLIC_AudioGainSetup ProSLIC_dbgSetRXGain

+ */

+

+int ProSLIC_dbgSetTXGain (proslicChanType *pProslic, int32 gain, int impedance_preset, int audio_gain_preset);

+

+/** @} GAIN_CONTROL */

+/** @} AUDIO_CONTROL */

+/** @} PROSLIC_AUDIO */

+/*****************************************************************************/

+/** @defgroup PD_DETECT Pulse dial detection 

+ *

+ * This function group has routines used to implement a pulse dial detection

+ * mechanism.  The outline of how to use these functions is as follows:

+ *

+ * - Initialize the data structure w/ @ref ProSLIC_InitializeDialPulseDetect

+ * - When hook change is detected, call @ref ProSLIC_DialPulseDetect

+ * - After calling  @ref ProSLIC_DialPulseDetect and we're onhook, call

+ *   @ref ProSLIC_DialPulseDetectTimeout to see if we need to re-initialize

+ *   the state machine.

+ *

+ *   @note This set of functions require that the elapsed timer functions 

+ *   documented in @ref PROSLIC_CUSTOMER_TIMER are implemented.

+ * 

+ * @{

+ */

+

+/**

+ * @brief

+ *  Initialize pulse dial detection parameters.

+ *

+ * @param[in,out] pPulse - the structure that is to be initialized.

+ * @param[in] offHookTime - a timer object suitable to be passed to a function of type @ref system_timeElapsed_fptr

+ * @param[in] onHookTime - a timer object suitable to be passed to a function of type @ref system_timeElapsed_fptr

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_InitializeDialPulseDetect(pulseDialType *pPulse,void *offHookTime,void *onHookTime);

+

+/** 

+ * @brief

+ *  Implements pulse dial detection and should be called at every hook transistion.

+ *

+ * @param[in] pProslic - which channel had a hook transition.

+ * @param[in] pPulsedialCfg - what is the criteria to determine on/off hook states.

+ * @param[in,out] pPulseDialData - contians the timer information that was set in  

+ *                                  @ref ProSLIC_InitializeDialPulseDetect as well as the pulse digit detected

+ *

+ * @retval int - 0 = no pulse digit detected, 1 = we detected a pulse digit that met the timing criteria and that in @ref pulseDialType contains the digit detected.

+ */

+

+int ProSLIC_DialPulseDetect (proslicChanType *pProslic, pulseDial_Cfg *pPulsedialCfg, pulseDialType *pPulseDialData);

+

+/**

+ * @brief

+ *  This function implements pulse dial detection and should be called when a 

+ *  pulse dial timeout (e.g. max offhook or onhook time exceeded) is suspected.

+ *  

+ * @param[in] pProslic - which channel had a hook transition.

+ * @param[in] pPulsedialCfg - what is the criteria to determine on/off hook states.

+ * @param[in,out] pPulseDialData - contians the timer information that was set in  

+ *                                  @ref ProSLIC_InitializeDialPulseDetect as well as the pulse digit detected

+ * @retval @ref ON_HOOK_TIMEOUT - did not detect a digit, 0 = no digit detected, else the digit detected.

+ */

+

+int ProSLIC_DialPulseDetectTimeout (proslicChanType *pProslic, pulseDial_Cfg *pPulsedialCfg, pulseDialType *pPulseDialData);

+

+/** @} PD_DETECT */

+

+/*****************************************************************************/

+/**  @addtogroup PROSLIC_AUDIO

+ * @{

+ * @defgroup PROSLIC_DTMF_DECODE DTMF Decode

+ * This section covers DTMF decoding. 

+ *

+ * @note Not all chipsets support this capability.  Please review your chipset

+ * documentation to confirm this capability is supported.

+ * @{

+ */

+/**

+ * @brief

+ *  Configure the DTMF Decoder - assumes PCM setup procedure has been done.

+ *

+ *  @warning Not all ProSLIC chipsets have a DTMF decoder.  Please review your chipset to make

+ *  sure this capability exists.

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] preset - which DTMF preset to use.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note This function can be compiled out with @ref DISABLE_DTMF_SETUP being defined.

+ */

+

+int ProSLIC_DTMFDecodeSetup (proslicChanType_ptr hProslic,int preset);

+

+/**

+ * @brief 

+ *  Read/Decode DTMF digits.  The "raw" hexcode is returned in this function and would require

+ *  further processing.  For example, on the Si3217x chipset, the following mapping exists:

+ *

+ *  1-9 = no remapping required

+ *  0   = 0xA

+ *  *   = 0xB

+ *  #   = 0xC

+ *  A-C = 0xD-0xF

+ *  D   = 0

+ *

+ * @note This function is only valid after @ref IRQ_DTMF occurred and should be called shortly 

+ * thereafter.

+ *

+ * @warning Not all ProSLIC chipsets have a DTMF decoder.  Please review your chipset to make

+ * sure this capability exists.

+ *

+ * @param[in] hProslic - which channel is to be decoded.

+ * @param[out] pDigit - "raw" DTMF value (see comments in description)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ *

+ * @sa ProSLIC_DTMFDecodeSetup 

+ */

+

+int ProSLIC_DTMFReadDigit (proslicChanType_ptr hProslic,uInt8 *pDigit);

+

+/** @} PROSLIC_DTMF_DECODE */

+/** @} PROSLIC_AUDIO */

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_POWER_CONVERTER Power Converter control 

+ * @{

+ */

+/**

+* @brief 

+* Powers all DC/DC converters sequentially with delay to minimize peak power draw on VDC.

+* @param[in] hProslic - which channel to change state.

+* @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*

+* @sa ProSLIC_PowerDownConverter

+*

+*/

+

+int ProSLIC_PowerUpConverter(proslicChanType_ptr hProslic);

+

+/**

+* @brief 

+*  Safely powerdown dcdc converter after ensuring linefeed

+*  is in the open state.  Test powerdown by setting error

+*  flag if detected voltage does no fall below 5v.

+*

+* @param[in] hProslic - which channel to change state.

+* @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*

+* @sa ProSLIC_PowerUpConverter

+*

+*/

+

+int ProSLIC_PowerDownConverter(proslicChanType_ptr hProslic);

+

+/** @} PROSLIC_POWER_CONVERTER */

+/*****************************************************************************/

+/** @defgroup PROSLIC_LB_CALIBRATION LB Calibration

+ * @{

+ */

+

+/**

+ * @brief

+ *  Run canned longitudinal balance calibration.  

+ *  

+ * @param[in] pProslic - start channel to start from for calibration.

+ * @param[in] size - number of channels to calibrate

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @deprecated 

+ * Use the @ref ProSLIC_Init function to perform all calibrations except Longitudinal Balance (LB).

+ * Use the @ref ProSLIC_LBCal function to perform LB calibration.

+ *

+*  @sa ProSLIC_GetLBCalResult ProSLIC_LoadPreviousLBCal ProSLIC_LoadPreviousLBCalPacked ProSLIC_LBCal ProSLIC_GetLBCalResultPacked

+ */

+

+int ProSLIC_LBCal (proslicChanType_ptr *pProslic, int size);

+

+/**

+ * @brief

+ *  This function returns the coefficient results of the last LB calibration.

+ *

+ * @param[in] pProslic - which channel to retrieve the values from.

+ * @param[out] result1 - results read from the last calibration

+ * @param[out] result2 - results read from the last calibration

+ * @param[out] result3 - results read from the last calibration

+ * @param[out] result4 - results read from the last calibration

+*  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*

+*  @sa ProSLIC_LBCal ProSLIC_LoadPreviousLBCal ProSLIC_LoadPreviousLBCalPacked ProSLIC_LBCal ProSLIC_GetLBCalResultPacked

+*/

+

+int ProSLIC_GetLBCalResult (proslicChanType *pProslic,int32 *result1,int32 *result2,int32 *result3,int32 *result4);

+

+/**

+ * @brief

+ *  This function loads previously stored LB calibration results to the appropriate ProSLIC

+ *  RAM locations.

+ *

+ * @param[in] pProslic - which channel to program the values

+ * @param[in] result1 - values to be written

+ * @param[in] result2 - values to be written

+ * @param[in] result3 - values to be written

+ * @param[in] result4 - values to be written

+*  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*

+*  @sa ProSLIC_LBCal ProSLIC_LoadPreviousLBCalPacked ProSLIC_LBCal ProSLIC_GetLBCalResult ProSLIC_GetLBCalResultPacked

+*/

+

+int ProSLIC_LoadPreviousLBCal (proslicChanType *pProslic,int32 result1,int32 result2,int32 result3,int32 result4);

+

+/**

+ * @brief

+ *  This function returns the results of the last LB calibration packed into single int32.

+ *

+ * @param[in] pProslic - which channel to retrieve the values from.

+ * @param[out] result - results - where to store the value

+*  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*

+*  @sa ProSLIC_LBCal ProSLIC_LoadPreviousLBCal ProSLIC_LoadPreviousLBCalPacked ProSLIC_LBCal 

+*/

+

+int ProSLIC_GetLBCalResultPacked (proslicChanType *pProslic,int32 *result);

+

+/**

+ * @brief

+ *  This function loads previously stored LB calibration results that are in the packed format.

+ *

+ * @param[in] pProslic - which channel to retrieve the values from.

+ * @param[in] result - results read from @ref ProSLIC_GetLBCalResultPacked

+*  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*

+*  @sa ProSLIC_LBCal ProSLIC_LoadPreviousLBCal ProSLIC_LBCal ProSLIC_GetLBCalResultPacked

+*

+*/

+

+int ProSLIC_LoadPreviousLBCalPacked (proslicChanType *pProslic,int32 *result);

+

+/** @} PROSLIC_LB_CALIBRATION */

+

+

+/*****************************************************************************/

+/** @addtogroup DIAGNOSTICS 

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function can be used to verify that the SPI interface is functioning 

+ *  properly by performing a series of readback tests.  This test DOES modify 

+ *  certain registers, so a reinitialization will be required.  This test is 

+ *  recommended only for development use.

+ *

+ * @param[in] pProslic - This should point to the channel that is to be verified.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error amd will typically return back

+ * @ref RC_SPI_FAIL if a SPI failure occured.

+ */

+

+int ProSLIC_VerifyControlInterface (proslicChanType_ptr pProslic);

+

+/** @addtogroup PSTN_CHECK PSTN Check

+ * @{

+ */

+

+/**

+ * @brief

+ * Allocates memory for a PSTN check object. One channel object is needed per

+ * ProSLIC channel.

+ *

+ *  @param[in,out] pstnCheckObj - pointer to the object that is to be initialized.

+ *

+ *  @retval 0 = OK

+ */

+

+int ProSLIC_CreatePSTNCheckObj(proslicPSTNCheckObjType_ptr *pstnCheckObj);

+

+/** 

+ * @brief 

+ * Allocates memory for a differential PSTN check object. One channel object is needed per

+ * ProSLIC channel.

+ * 

+ *  @param[in,out] pstnCheckObj - pointer to the object that is to be initialized.

+ *

+ *  @retval 0 = OK

+ */

+

+int ProSLIC_CreateDiffPSTNCheckObj(proslicDiffPSTNCheckObjType_ptr *pstnCheckObj);

+

+/** 

+ * @brief 

+ * Destroys a PSTN check object and deallocates memory.

+ *

+ * @param[in] pstnCheckObj - object to deallocate.

+ *

+ * @retval 0 = OK

+ */

+

+int ProSLIC_DestroyPSTNCheckObj(proslicPSTNCheckObjType_ptr *pstnCheckObj);

+

+/**

+ * @brief

+ *  Destroys a differential PSTN check object and deallocates memory.

+ *

+ * @param[in] pstnCheckObj - object to deallocate.

+ *

+ * @retval 0 = OK

+ */

+

+int ProSLIC_DestroyDiffPSTNCheckObj(proslicDiffPSTNCheckObjType_ptr *pstnCheckObj);

+

+/**

+ * @brief

+ *  Initialize pstnCheckObj structure memebers

+ *

+ * @param[in] pstnCheckObj - which object to initialize

+ * @param[in] avgThresh - Average current threshold that indicates a PSTN is present (uA).

+ * @param[in] singleThresh - Single current threshold that indicates a PSTN is present (uA).

+ * @param[in] samples - number of samples to collect

+ * @retval 0 = OK

+ */

+

+int ProSLIC_InitPSTNCheckObj(proslicPSTNCheckObjType_ptr pstnCheckObj, int32 avgThresh, int32 singleThresh, uInt8 samples);

+

+/**

+ * @brief 

+ *  This function initializes a differential PSTN detection object.

+ *

+ *  @param[in,out] pstnDiffCheckObj - object to be initialized

+ *  @param[in] preset1 - DC Feed preset to be used for first loop I/V measurement

+ *  @param[in] preset2 - DC Feed preset to be used for second loop I/V measurement

+ *  @param[in] entry_preset - restore_preset DC Feed preset that is restored after PSTN check is complete.

+ *  @param[in] femf_enable - Flag to enable OPEN state hazardous voltage measurement (0 = disabled, 1 = enabled)

+ *  @retval 0 = OK

+ */

+

+int ProSLIC_InitDiffPSTNCheckObj(proslicDiffPSTNCheckObjType_ptr pstnDiffCheckObj, int preset1, int preset2, int entry_preset, int femf_enable);

+

+/**

+ * @brief 

+ * This function monitors longitudinal current (average and single sample) to quickly identify

+ * the presence of a live PSTN line. Sufficient polling needs to occur in order to quickly determine

+ * if a PSTN line is preset or not.

+ *  

+ *  @param[in] pProslic - which channel to run this test on. 

+ *  @param[in] pPSTNCheck - the initialized data structure that contains the intermediate results of this test.

+ *  @retval 0 = no PSTN detected/thresholds have not been exceeded, 1 = PSTN detected, state machine reset.

+ *

+ *  @note 

+ *   If wanting to restart the test, one will need to call @ref ProSLIC_InitPSTNCheckObj again. However, if the 

+ *   number of samples exceeds the buffer then the function will "wrap".

+ */

+

+int ProSLIC_PSTNCheck(proslicChanType *pProslic, proslicPSTNCheckObjType *pPSTNCheck);

+

+/**

+ * @brief

+ *  This function monitors for a foreign voltage (if enabled) and measures the differential I/V

+ *  characteristics of the loop at 2 unique settings to detect a foreign PSTN.  It is assumed that polling will

+ *  occur at the configured value found in @ref PSTN_DET_POLL_RATE.

+ *

+ *  @param[in] pProslic - channel to be monitored

+ *  @param[in,out] pPSTNCheck - pointer to an initialzed structure that is used by the function to

+ *  store state information.

+ *  @retval @ref RC_NONE - test is in progress, @ref RC_COMPLETE_NO_ERR - test complete, no errors, @ref RC_PSTN_OPEN_FEMF - detected foreign voltage, RC_CHANNEL_TYPE_ERR = a non-ProSLIC device was called to perform this function

+ */ 

+int ProSLIC_DiffPSTNCheck(proslicChanType *pProslic, proslicDiffPSTNCheckObjType *pPSTNCheck);

+

+/** @} PSTN_CHECK */

+/** @} DIAGNOSTICS*/

+

+/*****************************************************************************/

+/** @defgroup PROSLIC_DCFEED DC Feed Setup and control 

+ * @{

+ */

+

+/**

+ * @brief

+ *  Configures the DC feed from a preset.

+ *

+ * @param[in] hProslic - which channel to configure

+ * @param[in] preset - the preset to use

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @note This function can be disabled by @ref DISABLE_DCFEED_SETUP

+ */

+

+int ProSLIC_DCFeedSetup (proslicChanType_ptr hProslic,int preset);

+

+int ProSLIC_DCFeedSetupCfg (proslicChanType_ptr hProslic, ProSLIC_DCfeed_Cfg *cfg, int preset);

+

+/**

+ * @brief

+ *  This function allows one to adjust the DC open circuit voltage level dynamically. Boundary checking is done. 

+ *

+ * @note This function does NOT modify the register sets needed, it calculates the correct values and stores

+ * them in the correct preset.  Use @ref ProSLIC_DCFeedSetup to program the device with the new values.

+ *

+ * @param[in] pProslic - which channel to configure

+ * @param[in] v_vlim_val - absolute voltage level

+ * @param[in] preset - DC Feed preset to be modified.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_dbgSetDCFeedIloop ProSLIC_DCFeedSetup

+ */

+

+int ProSLIC_dbgSetDCFeedVopen (proslicChanType *pProslic, uInt32 v_vlim_val, int32 preset);

+

+/**

+ * @brief

+ *  This function allows one to adjust the loop current level dynamically. Boundary checking is done.

+ *

+ * @note This function does NOT modify the register sets needed, it calculates the correct values and stores

+ * them in the correct preset.  Use @ref ProSLIC_DCFeedSetup to program the device with the new values.

+ *

+ * @param[in] pProslic - which channel to configure

+ * @param[in] i_ilim_val - loop current level

+ * @param[in] preset - DC Feed preset to be modified.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_dbgSetDCFeedVopen ProSLIC_DCFeedSetup

+ */

+

+int ProSLIC_dbgSetDCFeedIloop (proslicChanType *pProslic, uInt32 i_ilim_val, int32 preset);

+

+/**

+ * @brief

+ *  This function allows one to enable/disable power savings mode found on some of the chipsets.  This allows one

+ *  to change the default value set in the GUI config tool.

+ *

+ * @param[in] pProslic - which channel to configure

+ * @param[in] pwrsave -  power savings mode enabled or disabled - value expected: @ref PWRSAVE_DISABLE or @ref PWRSAVE_ENABLE

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int ProSLIC_SetPowersaveMode(proslicChanType *pProslic, int pwrsave);

+

+/** @} PROSLIC_DCFEED */

+

+/*****************************************************************************/

+/** @defgroup MISC MISC. routines 

+ * @{

+ */

+

+/**

+ * @brief

+ *  Implements message waiting indicator

+ *

+ * @details

+ *  Message waiting (neon flashing) requires modifications to vbath_expect and slope_vlim.

+ *  The old values are restored to turn off the lamp. The function assumes the channels

+ *  are all configured the same. During off-hook event lamp must be disabled manually.

+ *

+ * @param[in] hProslic - channel to modify

+ * @param[in] lampOn - 0 = lamp is off, 1 = lamp is on.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_MWI (proslicChanType_ptr hProslic,uInt8 lampOn);

+

+/**

+ * @brief 

+ *  This function initiates PLL free run mode.

+ *

+ * @param[in] hProslic - which channel to modify

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_PLLFreeRunStart (proslicChanType_ptr hProslic);

+

+/**

+ * @brief 

+ *  This function terminates PLL free run mode.

+ *

+ * @param[in] hProslic - which channel to modify

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int ProSLIC_PLLFreeRunStop (proslicChanType_ptr hProslic);

+

+/**

+ * @brief

+ *  This function returns back a string with the current version of the 

+ *  ProSLIC API.

+ *

+ * @details

+ *  The string is in the following format MM.mm.vv[.rcX] format, where

+ *  MM is the major number, mm is the minor number and vv is the sub-minor number.

+ *  If this is a release candidate, a .RCx is tacked on - such as RC1 for release

+ *  candidate 1.

+ *

+ *  @retval char * - returns back a constant string.

+ */

+char *ProSLIC_Version(void);

+

+/** @} MISC */

+/** @} */

+#endif /*end ifdef PROSLIC_H*/

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/proslic_tstin.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/proslic_tstin.h
new file mode 100755
index 0000000..040d773
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/proslic_tstin.h
@@ -0,0 +1,379 @@
+/*

+** Copyright (c) 2011 by Silicon Laboratories

+**

+** proslic_tstin.h

+**

+** Author(s): 

+** cdp

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file for the inward test implementations.

+**

+** Dependancies:

+** si_voice_datatypes.h. proslic.h

+**

+*/

+#ifndef PROSLIC_TSTIN_H

+#define PROSLIC_TSTIN_H

+

+#include "si_voice_datatypes.h"

+#include "proslic.h"

+

+/** @addtogroup DIAGNOSTICS

+ * @{

+ */

+/** @defgroup PROSLIC_TSTIN ProSLIC Inward Tests (Test-In)

+ * This section documents functions and datastructures related to the 

+ * ProSLIC/FXS inward test implementations.

+ * @{

+ */

+

+#define MIN_RINGING_SAMPLES 16          /**< Minimum number of ringing samples for measuring ring amplitude */

+#define MAX_RINGING_SAMPLES 255         /**< Maximum number of ringing samples for measuring ring amplitude */

+#define MIN_RINGING_SAMPLE_INTERVAL 1   /**< Minimum sample interval for measuring ring amplitude */

+#define MAX_RINGING_SAMPLE_INTERVAL 10  /**< Maximum sample interval for measuring ring amplitude */

+ 

+/**

+* Test-In results status

+*/

+enum {

+    TSTIN_RESULTS_INVALID,

+    TSTIN_RESULTS_VALID

+};

+

+/**

+* PCM format options 

+*/

+enum {

+    PCM_8BIT,

+	PCM_16BIT

+};

+

+/**

+* Abort if Line-in-use option

+*/

+enum {

+	ABORT_LIU_DISABLED,

+	ABORT_LIU_ENABLED

+};

+

+/**

+* Check for loop closure option

+*/

+enum {

+	LCR_CHECK_DISABLED,

+	LCR_CHECK_ENABLED

+};

+

+/**

+* Check for ringtrip option

+*/

+enum {

+	RTP_CHECK_DISABLED,

+	RTP_CHECK_ENABLED

+};

+

+

+/**

+ * Defines generic test limit/value/status structure

+ */

+typedef struct {

+	int32			lowerLimit;     /**< Lower test limit */

+	int32			upperLimit;     /**< Upper test limit */

+	int32			value;          /**< Numeric test result */

+	uInt8			testResult;		/**< 0 - Fail, 1 - pass */

+}proslicTestObj;

+

+/** 

+ * Defines structure for PCM Loopback Test

+ */

+typedef struct {

+	BOOLEAN			testEnable;		/**< Gate execution/updating of results with this flag */

+	BOOLEAN			pcmLpbkEnabled;	/**< Indicates if test data is valid (1) or stale (0) */

+	BOOLEAN			pcm8BitLinear;  /**< Set to use 8 bit linear mode (used if normally using ulaw or alaw) */

+	uInt8           pcmModeSave;    /**< Store entry PCMMODE value  */

+	uInt8			testResult;		/**< OR of all test results in this structure */

+}proslicPcmLpbkTest;

+

+

+/** 

+ * Defines structure for DC Feed Test

+ */

+typedef struct {

+	BOOLEAN			testEnable;		    /**< Gate execution/updating of results with this flag */

+	BOOLEAN			testDataValid;	    /**< Indicates if test data is valid (1) or stale (0) */

+    BOOLEAN			abortIfLineInUse;   /**< Abort test if LCR set at the start of test. Leaves results invalid */

+	BOOLEAN			applyLcrThresh;     /**< Apply alternate LCR thresholds to ensure LCR event occurs */

+    uInt32          altLcrOffThresh;    /**< Optional LCROFFHK threshold to apply during test */

+	uInt32			altLcrOnThresh;     /**< Optional LCRONHK threshold to apply during test */

+	BOOLEAN			lcrStatus;		    /**< Indicates LCR status after applying test load */

+	proslicTestObj	dcfeedVtipOnhook;   /**< On-hook VTIP test results */

+	proslicTestObj	dcfeedVringOnhook;  /**< On-hook VRING test results */

+	proslicTestObj	dcfeedVloopOnhook;  /**< On-hook VLOOP test results */

+	proslicTestObj	dcfeedVbatOnhook;   /**< On-hook VBAT test results */

+	proslicTestObj	dcfeedItipOnhook;   /**< On-hook ITIP test results */

+	proslicTestObj	dcfeedIringOnhook;  /**< On-hook IRING test results */

+	proslicTestObj	dcfeedIloopOnhook;  /**< On-hook ILOOP test results */

+	proslicTestObj	dcfeedIlongOnhook;  /**< On-hook ILONG test results */

+	proslicTestObj	dcfeedVtipOffhook;  /**< Off-hook VTIP test results */

+	proslicTestObj	dcfeedVringOffhook; /**< Off-hook VRING test results */

+	proslicTestObj	dcfeedVloopOffhook; /**< Off-hook VLOOP test results */

+	proslicTestObj	dcfeedVbatOffhook;  /**< Off-hook VBAT test results */

+	proslicTestObj	dcfeedItipOffhook;  /**< Off-hook ITIP test results */

+	proslicTestObj	dcfeedIringOffhook; /**< Off-hook IRING test results */

+	proslicTestObj	dcfeedIloopOffhook; /**< Off-hook ILOOP test results */

+	proslicTestObj	dcfeedIlongOffhook; /**< Off-hook ILONG test results */

+	uInt8			testResult;		    /**< OR of all test results in this structure */

+}proslicDcFeedTest;  

+

+

+/** 

+ * Defines structure for Ringing Test

+ */

+typedef struct {

+	BOOLEAN			testEnable;		    /**< Gate execution/updating of results with this flag */

+	BOOLEAN			testDataValid;	    /**< Indicates if test data is valid (1) or stale (0) */

+	BOOLEAN			abortIfLineInUse;   /**< Abort test if LCR set at the start of test. Leaves results invalid */

+	uInt16			numSamples;         /**< Number of samples taken */

+	uInt8           sampleInterval;     /**< Sample interval (in ms - range 1 to 100) */

+	BOOLEAN			ringtripTestEnable; /**< Enable ringtrip test */

+	BOOLEAN			rtpStatus;          /**< RTP Bit */

+	proslicTestObj	ringingVac;         /**< Ringing AC Voltage test results */

+	proslicTestObj	ringingVdc;         /**< Ringing DC Voltage test results */

+	uInt8			testResult;		    /**< OR of all test results in this structure */

+}proslicRingingTest;

+

+/** 

+ * Defines structure for Battery Test

+ */

+typedef struct {

+	BOOLEAN			testEnable;		/**< Gate execution/updating of results with this flag */

+	BOOLEAN			testDataValid;	/**< Indicates if test data is valid (1) or stale (0) */

+	proslicTestObj	vbat;           /**< VBAT test results */

+	uInt8			testResult;		/**< OR of all test results in this structure */

+}proslicBatteryTest;

+

+/** 

+ * Defines structure for Audio Test

+ */

+typedef struct {

+	BOOLEAN			testEnable;		  /**< Gate execution/updating of results with this flag */

+	BOOLEAN			testDataValid;	  /**< Indicates if test data is valid (1) or stale (0) */

+	BOOLEAN			abortIfLineInUse; /**< Abort test if LCR set at the start of test. Leaves results invalid */

+	int32           zerodBm_mVpk;     /**< 0dBm voltage (in mVpk) of ref impedance */

+	proslicTestObj	txGain;		      /**< TX path gain test results */

+	proslicTestObj  rxGain;           /**< RX path gain test results */

+	uInt8			testResult;		  /**< OR of all test results in this structure */

+}proslicAudioTest;

+

+

+/** 

+ * Defines structure for all tests

+ */

+typedef struct {

+	proslicPcmLpbkTest	pcmLpbkTest;        

+	proslicDcFeedTest	dcFeedTest;

+	proslicRingingTest	ringingTest;

+	proslicBatteryTest	batteryTest;

+	proslicAudioTest	audioTest;

+}proslicTestInObjType;

+

+typedef proslicTestInObjType *proslicTestInObjType_ptr;

+

+

+/**

+ * @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] *pTstin - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_createTestInObj(proslicTestInObjType_ptr *pTstin);

+

+/**

+ * @brief

+ *  Free memory reserved by the given structure.

+ *

+ * @param[in,out] *pTstin - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_destroyTestInObj(proslicTestInObjType_ptr *pTstin);

+

+/**

+ * @brief

+ *  Enable PCM loopback.

+ *

+ * @param[in]      pProslic  -  channel data structure

+ * @param[in,out]  pTstin->pcmLpbkTest - all control, limits, and results

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_testInPCMLpbkEnable(proslicChanType_ptr pProslic, proslicTestInObjType_ptr pTstin);

+

+

+/**

+ * @brief

+ *  Disable PCM loopback.

+ *

+ * @param[in]      pProslic  -  channel data structure

+ * @param[in,out]  pTstin->pcmLpbkTest - all control, limits, and results

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_testInPCMLpbkDisable(proslicChanType_ptr pProslic, proslicTestInObjType_ptr pTstin);

+

+

+/**

+ * @brief

+ * DC Feed Test

+ *

+ * @param[in]      pProslic  -  channel data structure

+ * @param[in,out]  pTstin->dcFeedTest - all control, limits, and results

+ *

+ * @retval int - error from @ref errorCodeType  

+ * @retval RC_TEST_PASSED indicates test completed and passed

+ * @retval RC_TEST_FAILED indicates test completed and failed

+ * @retval RC_UNSUPPORTED_FEATURE indicates feature not supported on this device

+ * @retval RC_TEST_DISABLED indicates test has not been initialized/enabled

+ * @retval RC_LINE_IN_USE indicates LCS already set 

+ *

+ */

+int ProSLIC_testInDCFeed(proslicChanType_ptr pProslic, proslicTestInObjType_ptr pTstin);

+

+

+/**

+ * @brief

+ * Ringing and Ringtrip Test

+ *

+ * @param[in]      pProslic  -  channel data structure

+ * @param[in,out]  pTstin->ringingTest - all control, limits, and results

+ *

+ * @retval int - error from @ref errorCodeType 

+ * @retval RC_TEST_PASSED indicates test completed and passed

+ * @retval RC_TEST_FAILED indicates test completed and failed

+ * @retval RC_UNSUPPORTED_FEATURE indicates feature not supported on this device

+ * @retval RC_TEST_DISABLED indicates test has not been initialized/enabled

+ * @retval RC_LINE_IN_USE indicates LCS already set 

+ *

+ */

+int ProSLIC_testInRinging(proslicChanType_ptr pProslic, proslicTestInObjType_ptr pTstin);

+

+/**

+ * @brief

+ * Battery Test

+ *

+ * @param[in]  **pTstin                          - the structure to initialize

+ * @param[out] **pTstin->batteryTest.testResult  - Pass/Fail Result

+ *

+ * @retval int - error from @ref errorCodeType 

+ * @retval RC_TEST_PASSED indicates test completed and passed

+ * @retval RC_TEST_FAILED indicates test completed and failed

+ * @retval RC_UNSUPPORTED_FEATURE indicates feature not supported on this device

+ * @retval RC_TEST_DISABLED indicates test has not been initialized/enabled

+ *

+ */

+int ProSLIC_testInBattery(proslicChanType_ptr pProslic, proslicTestInObjType_ptr pTstin);

+

+/**

+ * @brief

+ * Audio level inward test.

+ *

+ * @param[in]      pProslic  -  channel data structure

+ * @param[in,out]  pTstin->audioTest - all control, limits, and results

+ *

+ * @retval int - error from @ref errorCodeType 

+ * @retval RC_TEST_PASSED indicates test completed and passed

+ * @retval RC_TEST_FAILED indicates test completed and failed

+ * @retval RC_UNSUPPORTED_FEATURE indicates feature not supported on this device

+ * @retval RC_TEST_DISABLED indicates test has not been initialized/enabled

+ * @retval RC_LINE_IN_USE indicates LCS already set 

+ *

+ */

+int ProSLIC_testInAudio(proslicChanType_ptr pProslic, proslicTestInObjType_ptr pTstin);

+

+/**

+ * @brief

+ *  Initialize/Enable PCM Loopback Test.  Links test config/limits

+ *  to inward test data structure.

+ *

+ * @param[in,out]  pTstin->pcmLpbkTest - all control, limits, and results

+ * @param[in]      pcmLpbkTest -  test config and limits to link to pTstin->pcmLpbkTest

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_testInPcmLpbkSetup(proslicTestInObjType *pTstin, proslicPcmLpbkTest *pcmLpbkTest);

+

+/**

+ * @brief

+ *  Initialize/Enable DC Feed Test.  Links test config/limits

+ *  to inward test data structure.

+ *

+ * @param[in,out]  pTstin->dcFeedTest - all control, limits, and results

+ * @param[in]      dcFeedTest -  test config and limits to link to pTstin->dcFeedTest

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_testInDcFeedSetup(proslicTestInObjType *pTstin,proslicDcFeedTest *dcFeedTest);

+

+/**

+ * @brief

+ *  Initialize/Enable Ringing Test.  Links test config/limits

+ *  to inward test data structure.

+ *

+ * @param[in,out]  pTstin->ringingTest - all control, limits, and results

+ * @param[in]      ringingTest -  test config and limits to link to pTstin->ringingTest

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_testInRingingSetup(proslicTestInObjType *pTstin, proslicRingingTest *ringingTest);

+

+/**

+ * @brief

+ *  Initialize/Enable Battery Test.  Links test config/limits

+ *  to inward test data structure.

+ *

+ * @param[in,out]  pTstin->batteryTest - all control, limits, and results

+ * @param[in]      batteryTest -  test config and limits to link to pTstin->batteryTest

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_testInBatterySetup(proslicTestInObjType *pTstin, proslicBatteryTest *batteryTest);

+

+/**

+ * @brief

+ *  Initialize/Enable Audio Test.  Links test config/limits

+ *  to inward test data structure.

+ *

+ * @param[in,out]  pTstin->audioTest - all control, limits, and results

+ * @param[in]      audioTest -  test config and limits to link to pTstin->audioTest

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+int ProSLIC_testInAudioSetup(proslicTestInObjType *pTstin, proslicAudioTest *audioTest);

+

+

+/**

+ * @brief

+ *  Debug utility to log presently loaded test limits

+ *

+ * @param[in]      pProslic  -  channel data structure

+ * @param[in]      pTstin - inward test data structure

+ *

+ * @retval int - error from @ref errorCodeType  

+ * @retval RC_NONE indicates no error.

+ * @retval RC_UNSUPPORTED_FEATURE indicates feature not supported on this device

+ */

+int ProSLIC_testInPrintLimits(proslicChanType *pProslic,proslicTestInObjType *pTstin);

+

+/** @} PROSLIC_TSTIN */

+/** @} DIAGNOSTICS */

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x.h
new file mode 100755
index 0000000..e7035b7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x.h
@@ -0,0 +1,327 @@
+/*

+** Copyright (c) 2007 by Silicon Laboratories

+**

+** $Id: si3217x.h 3100 2011-09-15 14:04:54Z cdp $

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+*/

+

+#ifndef SI3217XH_H

+#define SI3217XH_H

+

+#include "proslic.h"

+

+

+

+/*

+** SI3217X DataTypes/Function Definitions 

+*/

+

+#define NUMIRQ 4

+

+

+/*

+** Defines structure for configuring gpio

+*/

+typedef struct {

+	uInt8 outputEn;

+	uInt8 analog;

+	uInt8 direction;

+	uInt8 manual;

+	uInt8 polarity;

+	uInt8 openDrain;

+	uInt8 batselmap;

+} Si3217x_GPIO_Cfg;

+

+typedef ProSLIC_DCfeed_Cfg Si3217x_DCfeed_Cfg;

+

+/*

+** Defines structure for general configuration and the dcdc converter

+*/

+typedef struct {

+    bomOptionsType bomOpt;

+	ramData vbatr_expect; /* default - this is overwritten by ring preset */

+	ramData vbath_expect;  /* default - this is overwritten by dc feed preset */

+    ramData dcdc_fsw_vthlo; 

+    ramData dcdc_fsw_vhyst; 

+	ramData dcdc_vref_min; 

+    ramData dcdc_vref_min_ring; 

+	ramData dcdc_fsw_norm; 

+	ramData dcdc_fsw_norm_lo; 

+	ramData dcdc_fsw_ring; 

+	ramData dcdc_fsw_ring_lo; 

+	ramData dcdc_din_lim; 

+	ramData dcdc_vout_lim; 

+    ramData dcdc_dcff_enable;

+	ramData dcdc_uvhyst; 

+	ramData dcdc_uvthresh; 

+	ramData dcdc_ovthresh; 

+	ramData dcdc_oithresh; 

+    ramData dcdc_swdrv_pol; 

+    ramData dcdc_swfet; 

+    ramData dcdc_vref_ctrl; 

+    ramData dcdc_rngtype; 

+    ramData dcdc_ana_gain; 

+    ramData dcdc_ana_toff; 

+    ramData dcdc_ana_tonmin; 

+    ramData dcdc_ana_tonmax; 

+    ramData dcdc_ana_dshift; 

+    ramData dcdc_ana_lpoly; 

+	ramData coef_p_hvic;

+	ramData p_th_hvic;

+	uInt8	cm_clamp;

+	uInt8	autoRegister;

+	uInt8 daa_cntl;

+	uInt8 irqen1;

+	uInt8 irqen2;

+	uInt8 irqen3;

+	uInt8 irqen4;

+    uInt8 enhance;

+    uInt8 daa_enable;

+    ramData scale_kaudio;

+    ramData ac_adc_gain;

+} Si3217x_General_Cfg;

+

+

+/*

+** Defines structure for configuring pcm

+*/

+typedef struct {

+    uInt8 pcmFormat;

+    uInt8 widebandEn;

+    uInt8 pcm_tri;

+    uInt8 tx_edge;

+    uInt8 alaw_inv;

+} Si3217x_PCM_Cfg;

+

+/*

+** Defines structure for configuring pulse metering

+*/

+typedef struct {

+	ramData pm_amp_thresh;

+	uInt8 pmFreq;

+	uInt8 pmRampRate;

+} Si3217x_PulseMeter_Cfg;

+/*

+** Defines structure for configuring FSK generation

+*/

+typedef struct {

+	ramData fsk01;

+	ramData fsk10;

+	ramData fskamp0;

+	ramData fskamp1;

+	ramData fskfreq0;

+	ramData fskfreq1;

+	uInt8 eightBit;

+	uInt8 fskdepth;

+} Si3217x_FSK_Cfg;

+

+/*

+** Defines structure for configuring dtmf decode

+*/

+typedef struct {

+	ramData dtmfdtf_b0_1;

+	ramData dtmfdtf_b1_1;

+	ramData dtmfdtf_b2_1;

+	ramData dtmfdtf_a1_1;

+	ramData dtmfdtf_a2_1;

+	ramData dtmfdtf_b0_2;

+	ramData dtmfdtf_b1_2;

+	ramData dtmfdtf_b2_2;

+	ramData dtmfdtf_a1_2;

+	ramData dtmfdtf_a2_2;

+	ramData dtmfdtf_b0_3;

+	ramData dtmfdtf_b1_3;

+	ramData dtmfdtf_b2_3;

+	ramData dtmfdtf_a1_3;

+	ramData dtmfdtf_a2_3;

+} Si3217x_DTMFDec_Cfg;

+

+/*

+** Defines structure for configuring impedence synthesis

+*/

+typedef struct {

+	ramData zsynth_b0;

+	ramData zsynth_b1;

+	ramData zsynth_b2;

+	ramData zsynth_a1;

+	ramData zsynth_a2;

+	uInt8 ra;

+} Si3217x_Zsynth_Cfg;

+

+/*

+** Defines structure for configuring hybrid

+*/

+typedef struct {

+	ramData ecfir_c2;

+	ramData ecfir_c3;

+	ramData ecfir_c4;

+	ramData ecfir_c5;

+	ramData ecfir_c6;

+	ramData ecfir_c7;

+	ramData ecfir_c8;

+	ramData ecfir_c9;

+	ramData ecfir_b0;

+	ramData ecfir_b1;

+	ramData ecfir_a1;

+	ramData ecfir_a2;

+} Si3217x_hybrid_Cfg;

+

+/*

+** Defines structure for configuring GCI CI bits

+*/

+typedef struct {

+	uInt8 gci_ci;

+} Si3217x_CI_Cfg;

+

+/*

+** Defines structure for configuring modem tone detect

+*/

+typedef struct {

+	ramData rxmodpwr;

+	ramData rxpwr;

+	ramData modem_gain;

+	ramData txmodpwr;

+	ramData txpwr;

+} Si3217x_modemDet_Cfg;

+

+/*

+** Defines structure for configuring audio eq

+*/

+typedef struct {

+	ramData txaceq_c0;

+	ramData txaceq_c1;

+	ramData txaceq_c2;

+	ramData txaceq_c3;

+

+	ramData rxaceq_c0;

+	ramData rxaceq_c1;

+	ramData rxaceq_c2;

+	ramData rxaceq_c3;

+} Si3217x_audioEQ_Cfg;

+

+/*

+** Defines structure for configuring audio gain

+*/

+typedef ProSLIC_audioGain_Cfg Si3217x_audioGain_Cfg;

+

+

+

+typedef struct {

+	Si3217x_audioEQ_Cfg audioEQ;

+	Si3217x_hybrid_Cfg hybrid;

+    Si3217x_Zsynth_Cfg zsynth;

+	ramData txgain;

+	ramData rxgain;

+	ramData rxachpf_b0_1;

+	ramData  rxachpf_b1_1;

+	ramData  rxachpf_a1_1;

+	int16 txgain_db; /*overall gain associated with this configuration*/

+	int16 rxgain_db;

+} Si3217x_Impedance_Cfg;

+

+

+

+/*

+** Defines structure for configuring tone generator

+*/

+typedef struct {

+	Oscillator_Cfg osc1;

+	Oscillator_Cfg osc2;

+	uInt8 omode;

+} Si3217x_Tone_Cfg; 

+

+/*

+** Defines structure for configuring ring generator

+*/

+typedef struct {

+	ramData rtper;

+	ramData freq;

+	ramData amp;

+	ramData phas;

+	ramData offset;

+	ramData slope_ring;

+    ramData iring_lim;

+    ramData rtacth;

+	ramData rtdcth;

+	ramData rtacdb;

+	ramData rtdcdb;

+	ramData vov_ring_bat;

+	ramData vov_ring_gnd;

+    ramData vbatr_expect;

+	uInt8 talo;

+	uInt8 tahi;

+	uInt8 tilo;

+	uInt8 tihi;

+	ramData adap_ring_min_i;

+    ramData counter_iring_val;

+	ramData counter_vtr_val;

+    ramData ar_const28;

+    ramData ar_const32;

+    ramData ar_const38;

+    ramData ar_const46;

+	ramData rrd_delay;

+	ramData rrd_delay2;

+    ramData dcdc_vref_min_rng;

+	uInt8 ringcon;

+    uInt8 userstat;

+	ramData vcm_ring;

+    ramData vcm_ring_fixed;

+    ramData delta_vcm;

+    ramData dcdc_rngtype;

+} Si3217x_Ring_Cfg;

+

+

+

+/*

+** This defines names for the interrupts in the ProSLIC

+*/

+typedef enum {

+/* IRQ1 */

+IRQ_OSC1_T1_SI3217X = 0,   

+IRQ_OSC1_T2_SI3217X,

+IRQ_OSC2_T1_SI3217X,

+IRQ_OSC2_T2_SI3217X,

+IRQ_RING_T1_SI3217X,

+IRQ_RING_T2_SI3217X,

+IRQ_FSKBUF_AVAIL_SI3217X,

+IRQ_VBAT_SI3217X,

+/* IRQ2 */

+IRQ_RING_TRIP_SI3217X = 8,

+IRQ_LOOP_STAT_SI3217X,

+IRQ_LONG_STAT_SI3217X,

+IRQ_VOC_TRACK_SI3217X,

+IRQ_DTMF_SI3217X,

+IRQ_INDIRECT_SI3217X,

+IRQ_TXMDM_SI3217X,

+IRQ_RXMDM_SI3217X,

+/* IRQ3 */

+IRQ_P_HVIC_SI3217X = 16,  

+IRQ_P_THERM_SI3217X,

+IRQ_PQ3_SI3217X,

+IRQ_PQ4_SI3217X,

+IRQ_PQ5_SI3217X,

+IRQ_PQ6_SI3217X,

+IRQ_DSP_SI3217X,

+IRQ_MADC_FS_SI3217X,

+/* IRQ4 */

+IRQ_USER_0_SI3217X = 24, 

+IRQ_USER_1_SI3217X,

+IRQ_USER_2_SI3217X,

+IRQ_USER_3_SI3217X,

+IRQ_USER_4_SI3217X,

+IRQ_USER_5_SI3217X,

+IRQ_USER_6_SI3217X,

+IRQ_USER_7_SI3217X

+}Si3217xProslicInt;

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x_intf.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x_intf.h
new file mode 100755
index 0000000..8a0b36a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x_intf.h
@@ -0,0 +1,1052 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: si3217x_intf.h 3088 2011-09-13 15:12:43Z cdp $

+**

+** Si3217x_Intf.h

+** Si3217x ProSLIC interface header file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file for the ProSLIC driver.

+**

+** Dependancies:

+** proslic_datatypes.h, Si3217x_registers.h, ProSLIC.h

+**

+*/

+#ifndef SI3217X_INTF_H

+#define SI3217X_INTF_H

+

+/*

+**

+** Si3217x General Constants

+**

+*/

+#define SI3217X_REVA                0

+#define SI3217X_REVB                1

+               

+/*

+** Calibration Constants

+*/

+#define SI3217X_CAL_STD_CALR1       0xFF

+#define SI3217X_CAL_STD_CALR2       0xF8

+

+/* Timeouts in 10s of ms */

+#define SI3217X_TIMEOUT_DCDC_UP     200

+#define SI3217X_TIMEOUT_DCDC_DOWN   200

+

+/*

+**

+** PROSLIC INITIALIZATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_Reset

+**

+** Description: 

+** Resets the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_Reset (proslicChanType_ptr hProslic);

+

+/*

+** Function: PROSLIC_ShutdownChannel

+**

+** Description: 

+** Safely shutdown channel w/o interruption to 

+** other active channels

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_ShutdownChannel (proslicChanType_ptr hProslic);

+

+/*

+** Function: PROSLIC_Init_MultiBOM

+**

+** Description: 

+** Initializes the ProSLIC w/ selected general parameters

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** size:     number of channels

+** preset:   General configuratin preset

+**

+** Return:

+** none

+*/

+#ifdef SIVOICE_MULTI_BOM_SUPPORT

+int Si3217x_Init_MultiBOM (proslicChanType_ptr *hProslic,int size,int preset);

+#endif

+

+/*

+** Function: PROSLIC_Init

+**

+** Description: 

+** Initializes the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_Init (proslicChanType_ptr *hProslic,int size);

+

+/*

+** Function: PROSLIC_Reinit

+**

+** Description: 

+** Soft reset and initialization

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_Reinit (proslicChanType_ptr hProslic,int size);

+/*

+** Function: PROSLIC_VerifyControlInterface

+**

+** Description: 

+** Verify SPI port read capabilities

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_VerifyControlInterface (proslicChanType_ptr hProslic);

+

+uInt8 Si3217x_ReadReg (proslicChanType_ptr hProslic,uInt8 addr);

+int Si3217x_WriteReg (proslicChanType_ptr hProslic,uInt8 addr,uInt8 data);

+ramData Si3217x_ReadRAM (proslicChanType_ptr hProslic,uInt16 addr);

+int Si3217x_WriteRAM (proslicChanType_ptr hProslic,uInt16 addr, ramData data);

+

+/*

+** Function: ProSLIC_PrintDebugData

+**

+** Description: 

+** Register and RAM dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_PrintDebugData (proslicChanType_ptr hProslic);

+

+/*

+** Function: ProSLIC_PrintDebugReg

+**

+** Description: 

+** Register dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_PrintDebugReg (proslicChanType_ptr hProslic);

+

+/*

+** Function: ProSLIC_PrintDebugRAM

+**

+** Description: 

+** RAM dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_PrintDebugRAM (proslicChanType_ptr hProslic);

+

+/*

+** Function: Si3217x_PowerUpConverter

+**

+** Description: 

+** Powers all DC/DC converters sequentially with delay to minimize

+** peak power draw on VDC.

+**

+** Returns:

+** int (error)

+**

+*/

+int Si3217x_PowerUpConverter(proslicChanType_ptr hProslic);

+

+/*

+** Function: Si3217x_PowerDownConverter

+**

+** Description: 

+** Power down DCDC converter (selected channel only)

+**

+** Returns:

+** int (error)

+**

+*/

+int Si3217x_PowerDownConverter(proslicChanType_ptr hProslic);

+

+/*

+** Function: Si3217x_Calibrate

+**

+** Description: 

+** Generic calibration function for Si3217x

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object,

+** size:     maximum number of channels

+** calr:     array of CALRx register values

+** maxTime:  cal timeout (in ms) 

+**

+** Return:

+** int 

+*/

+int Si3217x_Calibrate (proslicChanType_ptr *hProslic, int size, uInt8 *calr, int maxTime);

+

+/*

+** Function: PROSLIC_Cal

+**

+** Description: 

+** Calibrates the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3217x_Cal (proslicChanType_ptr *hProslic, int size);

+

+/*

+** Function: PROSLIC_LoadRegTables

+**

+** Description: 

+** Loads registers and ram in the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pRamTable: pointer to ram values to load

+** pRegTable: pointer to register values to load

+** 

+**

+** Return:

+** none

+*/

+int Si3217x_LoadRegTables (proslicChanType_ptr *hProslic, ProslicRAMInit *pRamTable, ProslicRegInit *pRegTable,int size);

+

+/*

+** Function: PROSLIC_LoadPatch

+**

+** Description: 

+** Loads patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si3217x_LoadPatch (proslicChanType_ptr hProslic, const proslicPatch *pPatch);

+

+/*

+** Function: PROSLIC_VerifyPatch

+**

+** Description: 

+** Verifies patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si3217x_VerifyPatch (proslicChanType_ptr hProslic, const proslicPatch *pPatch);

+

+/*

+** Function: PROSLIC_EnableInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si3217x_EnableInterrupts (proslicChanType_ptr hProslic);

+int Si3217x_DisableInterrupts (proslicChanType_ptr hProslic);

+

+

+/*

+** Function: PROSLIC_SetLoopbackMode

+**

+** Description: 

+** Set loopback test mode

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si3217x_SetLoopbackMode (proslicChanType_ptr hProslic, ProslicLoopbackModes newMode);

+

+

+/*

+** Function: PROSLIC_SetMuteStatus

+**

+** Description: 

+** Set mute(s)

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si3217x_SetMuteStatus (proslicChanType_ptr hProslic, ProslicMuteModes muteEn);

+

+

+

+/*

+**

+** PROSLIC CONFIGURATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_RingSetup

+**

+** Description: 

+** configure ringing

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pRingSetup: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3217x_RingSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ToneGenSetup

+**

+** Description: 

+** configure tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pTone: pointer to tones config structure

+**

+** Return:

+** none

+*/

+int Si3217x_ToneGenSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_FSKSetup

+**

+** Description: 

+** configure fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pFsk: pointer to fsk config structure

+**

+** Return:

+** none

+*/

+int Si3217x_FSKSetup (proslicChanType *pProslic, int preset);

+

+/*

+ * Function: Si3217x_ModifyStartBits

+ * 

+ * Description: To change the FSK start/stop bits field.

+ * Returns RC_NONE if OK.

+ */

+

+int Si3217x_ModifyCIDStartBits(proslicChanType_ptr pProslic, uInt8 enable_startStop);

+

+/*

+** Function: PROSLIC_DTMFDecodeSetup

+**

+** Description: 

+** configure dtmf decode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDTMFDec: pointer to dtmf decoder config structure

+**

+** Return:

+** none

+*/

+int Si3217x_DTMFDecodeSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_SetProfile

+**

+** Description: 

+** set country profile of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCountryData: pointer to country config structure

+**

+** Return:

+** none

+*/

+int Si3217x_SetProfile (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ZsynthSetup

+**

+** Description: 

+** configure impedence synthesis

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pZynth: pointer to zsynth config structure

+**

+** Return:

+** none

+*/

+int Si3217x_ZsynthSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_GciCISetup

+**

+** Description: 

+** configure CI bits (GCI mode)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCI: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3217x_GciCISetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ModemDetSetup

+**

+** Description: 

+** configure modem detector

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pModemDet: pointer to modem det config structure

+**

+** Return:

+** none

+*/

+int Si3217x_ModemDetSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioGainSetup

+**

+** Description: 

+** configure audio gains

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudio: pointer to audio gains config structure

+**

+** Return:

+** none

+*/

+int Si3217x_TXAudioGainSetup (proslicChanType *pProslic, int preset);

+int Si3217x_RXAudioGainSetup (proslicChanType *pProslic, int preset);

+int Si3217x_AudioGainSetup (proslicChanType *pProslic,int32 rxgain,int32 txgain,int preset);

+

+/*

+** Function: PROSLIC_HybridSetup

+**

+** Description: 

+** configure Proslic hybrid

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHybridCfg: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3217x_HybridSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioEQSetup

+**

+** Description: 

+** configure audio equalizers

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudioEQ: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3217x_AudioEQSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_DCFeedSetup

+**

+** Description: 

+** configure dc feed

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDcFeed: pointer to dc feed config structure

+**

+** Return:

+** none

+*/

+int Si3217x_DCFeedSetup (proslicChanType *pProslic, int preset);

+int Si3217x_DCFeedSetupCfg (proslicChanType *pProslic, ProSLIC_DCfeed_Cfg *cfg, int preset);

+

+/*

+** Function: PROSLIC_GPIOSetup

+**

+** Description: 

+** configure gpio

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpio: pointer to gpio config structure

+**

+** Return:

+** none

+*/

+int Si3217x_GPIOSetup (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PCMSetup

+**

+** Description: 

+** configure pcm

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPcm: pointer to pcm config structure

+**

+** Return:

+** none

+*/

+int Si3217x_PCMSetup (proslicChanType *pProslic, int preset);

+int Si3217x_PCMTimeSlotSetup (proslicChanType *pProslic, uInt16 rxcount, uInt16 txcount);

+

+/*

+**

+** PROSLIC CONTROL FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_GetInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** pIntData: pointer to interrupt info retrieved

+** 

+** Return:

+** 

+*/

+int Si3217x_GetInterrupts (proslicChanType_ptr hProslic, proslicIntType *pIntData);

+

+/*

+** Function: PROSLIC_ReadHookStatus

+**

+** Description: 

+** Determine hook status

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHookStat: current hook status

+**

+** Return:

+** none

+*/

+int Si3217x_ReadHookStatus (proslicChanType *pProslic,uInt8 *pHookStat);

+

+/*

+** Function: PROSLIC_WriteLinefeed

+**

+** Description: 

+** Sets linefeed state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** newLinefeed: new linefeed state

+**

+** Return:

+** none

+*/

+int Si3217x_SetLinefeedStatus (proslicChanType *pProslic,uInt8 newLinefeed);

+

+/*

+** Function: PROSLIC_SetLinefeedBroadcast

+**

+** Description: 

+** Sets linefeed state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** newLinefeed: new linefeed state

+**

+** Return:

+** none

+*/

+int Si3217x_SetLinefeedStatusBroadcast (proslicChanType *pProslic, uInt8 newLinefeed);

+

+/*

+** Function: PROSLIC_PolRev

+**

+** Description: 

+** Sets polarity reversal state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** abrupt: set this to 1 for abrupt pol rev

+** newPolRevState: new pol rev state

+**

+** Return:

+** none

+*/

+int Si3217x_PolRev (proslicChanType *pProslic,uInt8 abrupt, uInt8 newPolRevState);

+

+/*

+** Function: PROSLIC_GPIOControl

+**

+** Description: 

+** Sets gpio of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpioData: pointer to gpio status

+** read: set to 1 to read status, 0 to write

+**

+** Return:

+** none

+*/

+int Si3217x_GPIOControl (proslicChanType *pProslic,uInt8 *pGpioData, uInt8 read);

+

+/*

+** Function: PROSLIC_MWI

+**

+** Description: 

+** implements message waiting indicator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** lampOn: 0 = turn lamp off, 1 = turn lamp on

+**

+** Return:

+** none

+*/

+int Si3217x_MWI (proslicChanType *pProslic,uInt8 lampOn);

+

+/*

+** Function: PROSLIC_StartGenericTone

+**

+** Description: 

+** Initializes and start tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** timerEn: specifies whether to enable the tone generator timers

+**

+** Return:

+** none

+*/

+int Si3217x_ToneGenStart (proslicChanType *pProslic, uInt8 timerEn);

+

+

+/*

+** Function: PROSLIC_StopTone

+**

+** Description: 

+** Stops tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_ToneGenStop (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StartRing

+**

+** Description: 

+** Initializes and start ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_RingStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopRing

+**

+** Description: 

+** Stops ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_RingStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_EnableCID

+**

+** Description: 

+** enable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_EnableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DisableCID

+**

+** Description: 

+** disable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_DisableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_SendCID

+**

+** Description: 

+** send fsk data

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** buffer: buffer to send

+** numBytes: num of bytes in the buffer

+**

+** Return:

+** none

+*/

+int Si3217x_SendCID (proslicChanType *pProslic, uInt8 *buffer, uInt8 numBytes);

+

+int Si3217x_CheckCIDBuffer (proslicChanType *pProslic, uInt8 *fsk_buf_avail);

+

+/*

+** Function: PROSLIC_StartPCM

+**

+** Description: 

+** Starts PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_PCMStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopPCM

+**

+** Description: 

+** Disables PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_PCMStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DialPulseDetect

+**

+** Description: 

+** implements pulse dial detection and should be called at every off/on hook transistion

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPulsedialCfg: pointer to pulse dial config

+** pPulseDialData: pointer to pulse dial state for current channel

+**

+** Return:

+** none

+*/

+int Si3217x_DialPulseDetect (proslicChanType *pProslic, pulseDial_Cfg *pPulsedialCfg, pulseDialType *pPulseDialData);

+

+/*

+** Function: PROSLIC_ReadDTMFDigit

+**

+** Description: 

+** Read DTMF digit (would be called after DTMF interrupt to collect digit)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDigit: digit read

+**

+** Return:

+** none

+*/

+int Si3217x_DTMFReadDigit (proslicChanType *pProslic,uInt8 *pDigit);

+

+/*

+** Function: PROSLIC_PLLFreeRunStart

+**

+** Description: 

+** initiates pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_PLLFreeRunStart (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PLLFreeRunStop

+**

+** Description: 

+** exit pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_PLLFreeRunStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterSetup

+**

+** Description: 

+** configure pulse metering

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPulseCfg: pointer to pulse metering config structure

+**

+** Return:

+** none

+*/

+int Si3217x_PulseMeterSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_PulseMeterStart

+**

+** Description: 

+** start pulse meter tone

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_PulseMeterStart (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterStop

+**

+** Description: 

+** stop pulse meter tone

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3217x_PulseMeterStop (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_LBCal

+**

+** Description: 

+** Execute longitudinal balance calibration

+**

+** Input Parameters: 

+** hProslic: pointer to array of Proslic objects

+** 

+** Return:

+** 

+*/

+int Si3217x_LBCal (proslicChanType_ptr *pProslic, int size);

+

+

+int Si3217x_GetLBCalResult (proslicChanType *pProslic,int32 *result1,int32 *result2,int32 *result3,int32 *result4);

+int Si3217x_GetLBCalResultPacked (proslicChanType *pProslic,int32 *result);

+int Si3217x_LoadPreviousLBCal (proslicChanType *pProslic,int32 result1,int32 result2,int32 result3,int32 result4);

+int Si3217x_LoadPreviousLBCalPacked (proslicChanType *pProslic,int32 *result);

+

+/*

+** Function: PROSLIC_dbgSetDCFeed

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3217x_dbgSetDCFeed (proslicChanType *pProslic, uInt32 v_vlim_val, uInt32 i_ilim_val, int32 preset);

+

+/*

+** Function: PROSLIC_dbgSetDCFeedVopen

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3217x_dbgSetDCFeedVopen (proslicChanType *pProslic, uInt32 v_vlim_val, int32 preset);

+

+

+/*

+** Function: PROSLIC_dbgSetDCFeedIloop

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3217x_dbgSetDCFeedIloop (proslicChanType *pProslic, uInt32 i_ilim_val, int32 preset);

+

+

+/*

+** Function: PROSLIC_dbgRingingSetup

+**

+** Description: 

+** Provisionary function for setting up

+** Ring type, frequency, amplitude and dc offset.

+** Main use will be by peek/poke applications.

+*/

+int Si3217x_dbgSetRinging (proslicChanType *pProslic, ProSLIC_dbgRingCfg *ringCfg, int preset);

+

+/*

+** Function: PROSLIC_dbgSetRXGain

+**

+** Description: 

+** Provisionary function for setting up

+** RX path gain.

+*/

+int Si3217x_dbgSetRXGain (proslicChanType *pProslic, int32 gain, int impedance_preset, int audio_gain_preset);

+

+/*

+** Function: PROSLIC_dbgSetTXGain

+**

+** Description: 

+** Provisionary function for setting up

+** TX path gain.

+*/

+int Si3217x_dbgSetTXGain (proslicChanType *pProslic, int32 gain, int impedance_preset, int audio_gain_preset);

+

+

+/*

+** Function: PROSLIC_LineMonitor

+**

+** Description: 

+** Monitor line voltages and currents

+*/

+int Si3217x_LineMonitor(proslicChanType *pProslic, proslicMonitorType *monitor);

+

+

+/*

+** Function: PROSLIC_PSTNCheck

+**

+** Description: 

+** Continuous monitor of ilong to detect hot pstn line 

+*/

+int Si3217x_PSTNCheck(proslicChanType *pProslic, proslicPSTNCheckObjType *pstnCheckObj);

+

+

+/*

+** Function: PROSLIC_PSTNCheck

+**

+** Description: 

+** Continuous monitor of ilong to detect hot pstn line 

+*/

+int Si3217x_DiffPSTNCheck(proslicChanType *pProslic, proslicDiffPSTNCheckObjType *pstnCheckObj);

+

+/*

+** Function: PROSLIC_SetPowersaveMode

+**

+** Description: 

+** Enable or disable powersave mode 

+*/

+int Si3217x_SetPowersaveMode(proslicChanType *pProslic, int pwrsave);

+

+/*

+** Function: PROSLIC_ReadMADCScaled

+**

+** Description: 

+** Read MADC (or other sensed voltages/currents) and

+** return scaled value in int32 format

+*/

+int32 Si3217x_ReadMADCScaled(proslicChanType_ptr pProslic, uInt16 addr, int32 scale);

+

+/*

+** Function: PROSLIC_SetDAAEnable

+**

+** Description: 

+** Enable FXO channel (Si32178 only)

+*/

+int Si3217x_SetDAAEnable(proslicChanType *pProslic, int enable);

+

+

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x_registers.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x_registers.h
new file mode 100755
index 0000000..09ad250
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3217x_registers.h
@@ -0,0 +1,1212 @@
+/*

+** Copyright (c) 2007 by Silicon Laboratories

+**

+** $Id: si3217x_registers.h 3044 2011-08-10 15:54:52Z cdp $

+**

+** Si3217x_Registers.h

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file that contains

+** register and RAM names definitions for 

+** the Si3217x ProSLIC.

+**

+** Dependancies:

+** 

+**

+*/

+#ifndef SI3217XREGS_H

+#define SI3217XREGS_H

+

+/*

+** This defines the neumomics for the SI3217X registers

+*/

+enum REGISTERS {

+ID,

+RESET,

+MSTREN,

+MSTRSTAT,

+RAMSTAT,

+RAM_ADDR_HI,

+RAM_DATA_B0,

+RAM_DATA_B1,

+RAM_DATA_B2,

+RAM_DATA_B3,

+RAM_ADDR_LO,

+PCMMODE,

+PCMTXLO,

+PCMTXHI,

+PCMRXLO,

+PCMRXHI,

+IRQ,

+IRQ0,

+IRQ1,

+IRQ2,

+IRQ3,

+IRQ4,

+IRQEN1,

+IRQEN2,

+IRQEN3,

+IRQEN4,

+CALR0,

+CALR1,

+CALR2,

+CALR3,

+LINEFEED,

+POLREV,

+SPEEDUP_DIS,

+SPEEDUP,

+LCRRTP,

+OFFLOAD,

+BATSELMAP,

+BATSEL,

+RINGCON,

+RINGTALO,

+RINGTAHI,

+RINGTILO,

+RINGTIHI,

+LOOPBACK,

+DIGCON,

+RA,

+ZCAL_EN,

+ENHANCE,

+OMODE,

+OCON,

+O1TALO,

+O1TAHI,

+O1TILO,

+O1TIHI,

+O2TALO,

+O2TAHI,

+O2TILO,

+O2TIHI,

+FSKDAT,

+FSKDEPTH,

+TONDTMF,

+TONDET,

+TONEN,

+GCI_CI,

+GLOBSTAT1,

+GLOBSTAT2,

+USERSTAT,

+GPIO,

+GPIO_CFG1,

+GPIO_CFG2,

+GPIO_CFG3,

+DIAG1,

+DIAG2,

+CM_CLAMP,

+DAA_CNTL,

+PMCON,

+REG76,

+REG77,

+REG78,

+REG79,

+AUTO,

+JMPEN,

+JMP0LO,

+JMP0HI,

+JMP1LO,

+JMP1HI,

+JMP2LO,

+JMP2HI,

+JMP3LO,

+JMP3HI,

+JMP4LO,

+JMP4HI,

+JMP5LO,

+JMP5HI,

+JMP6LO,

+JMP6HI,

+JMP7LO,

+JMP7HI,

+PDN,

+PDN_STAT,

+PDN2,

+PDN2_STAT,

+USERMODE_ENABLE = 126

+};

+

+

+/*

+** This defines the neumomics for the SI3217X RAM locations (revB)

+*/

+enum SRAM {

+IRNGNG_SENSE,

+MADC_VTIPC,

+MADC_VRINGC,

+MADC_VBAT,

+MADC_VLONG,

+UNUSED5,

+MADC_VDC,

+MADC_ILONG,

+MADC_ITIP,

+MADC_IRING,

+MADC_ILOOP,

+VDIFF_SENSE,

+VTIP,

+VRING,

+P_Q1_D,

+P_Q2_D,

+P_Q3_D,

+P_Q4_D,

+P_Q5_D,

+P_Q6_D,

+P_Q1,

+DIAG_EX1,

+DIAG_EX2,

+DIAG_LPF_MADC,

+DIAG_DMM_I,

+DIAG_DMM_V,

+OSC1FREQ,

+OSC1AMP,

+OSC1PHAS,

+OSC2FREQ,

+OSC2AMP,

+OSC2PHAS,

+TESTB0_1,

+TESTB1_1,

+TESTB2_1,

+TESTA1_1,

+TESTA2_1,

+TESTB0_2,

+TESTB1_2,

+TESTB2_2,

+TESTA1_2,

+TESTA2_2,

+TESTB0_3,

+TESTB1_3,

+TESTB2_3,

+TESTA1_3,

+TESTA2_3,

+TESTPKO,

+TESTAVO,

+TESTWLN,

+TESTAVBW,

+TESTPKFL,

+TESTAVFL,

+TESTPKTH,

+TESTAVTH,

+DAC_IN_SYNC1,

+BYPASS_REG,

+LCRMASK_CNT,

+DAC_IN_SYNC,

+TEMP,

+TEMP_ISR,

+P_Q2,

+P_Q3,

+P_Q4,

+P_Q5,

+P_Q6,

+ILOOP_FILT,

+ILONG_FILT,

+VBAT_FILT,

+VDIFF_FILT,

+VCM_FILT,

+VBAT_CNT,

+V_VLIM_SCALED,

+V_VLIM_TRACK,

+V_VLIM_MODFEED,

+DIAG_P_OUT,

+DIAG_COUNT,

+ROW0_MAG,

+ROW1_MAG,

+ROW2_MAG,

+ROW3_MAG,

+COL0_MAG,

+COL1_MAG,

+COL2_MAG,

+COL3_MAG,

+ROW0_2ND_Y1,

+ROW1_2ND_Y1,

+ROW2_2ND_Y1,

+ROW3_2ND_Y1,

+COL0_2ND_Y1,

+COL1_2ND_Y1,

+COL2_2ND_Y1,

+COL3_2ND_Y1,

+ROW0_2ND_Y2,

+ROW1_2ND_Y2,

+ROW2_2ND_Y2,

+ROW3_2ND_Y2,

+COL0_2ND_Y2,

+COL1_2ND_Y2,

+COL2_2ND_Y2,

+COL3_2ND_Y2,

+DTMF_IN,

+DTMFDTF_D2_1,

+DTMFDTF_D1_1,

+DTMFDTF_OUT_1,

+DTMFDTF_D2_2,

+DTMFDTF_D1_2,

+DTMFDTF_OUT_2,

+DTMFDTF_D2_3,

+DTMFDTF_D1_3,

+DTMFDTF_OUT_3,

+DTMFDTF_OUT,

+DTMFLPF_D2_1,

+DTMFLPF_D1_1,

+DTMFLPF_OUT_1,

+DTMFLPF_D2_2,

+DTMFLPF_D1_2,

+DTMFLPF_OUT_2,

+DTMF_ROW,

+DTMFHPF_D2_1,

+DTMFHPF_D1_1,

+DTMFHPF_OUT_1,

+DTMFHPF_D2_2,

+DTMFHPF_D1_2,

+DTMFHPF_OUT_2,

+DTMF_COL,

+ROW_POWER,

+COL_POWER,

+GP_TIMER,

+SPR_INTERP_DIF,

+SPR_INTERP_DIF_OUT,

+SPR_INTERP_INT,

+SPR_CNT,

+ROW0_Y1,

+ROW0_Y2,

+ROW1_Y1,

+ROW1_Y2,

+ROW2_Y1,

+ROW2_Y2,

+ROW3_Y1,

+ROW3_Y2,

+COL0_Y1,

+COL0_Y2,

+COL1_Y1,

+COL1_Y2,

+COL2_Y1,

+COL2_Y2,

+COL3_Y1,

+COL3_Y2,

+ROWMAX_MAG,

+COLMAX_MAG,

+ROW0_2ND_MAG,

+COL0_2ND_MAG,

+ROW_THR,

+COL_THR,

+OSC1_Y,

+OSC2_Y,

+OSC1_X,

+OSC1_COEFF,

+OSC2_X,

+OSC2_COEFF,

+RXACIIR_D2_1,

+RXACIIR_OUT_1,

+RXACIIR_D2_2,

+RXACIIR_D1_2,

+RXACIIR_OUT_2,

+RXACIIR_D2_3,

+RXACIIR_D1_3,

+RXACIIR_OUT,

+RXACIIR_OUT_3,

+TXACCOMB_D1,

+TXACCOMB_D2,

+TXACCOMB_D3,

+TXACSINC_OUT,

+TXACHPF_D1_2,

+TXACHPF_D2_1,

+TXACHPF_D2_2,

+TXACHPF_OUT,

+TXACHPF_OUT_1,

+TXACHPF_OUT_2,

+TXACIIR_D2_1,

+TXACIIR_OUT_1,

+TXACIIR_D2_2,

+TXACIIR_D1_2,

+TXACIIR_OUT_2,

+TXACIIR_D2_3,

+TXACIIR_D1_3,

+TXACIIR_OUT_3,

+TXACIIR_OUT,

+ECIIR_D1,

+ECIIR_D2,

+EC_DELAY1,

+EC_DELAY2,

+EC_DELAY3,

+EC_DELAY4,

+EC_DELAY5,

+EC_DELAY6,

+EC_DELAY7,

+EC_DELAY8,

+EC_DELAY9,

+EC_DELAY10,

+EC_DELAY11,

+ECHO_EST,

+EC_OUT,

+TESTFILT_OUT_1,

+TESTFILT_D1_1,

+TESTFILT_D2_1,

+TESTFILT_OUT_2,

+TESTFILT_D1_2,

+TESTFILT_D2_2,

+TESTFILT_OUT_3,

+TESTFILT_D1_3,

+TESTFILT_D2_3,

+TESTFILT_PEAK,

+TESTFILT_ABS,

+TESTFILT_MEANACC,

+TESTFILT_COUNT,

+TESTFILT_NO_OFFSET,

+RING_X,

+RING_Y,

+RING_INT,

+RING_Y_D1,

+RING_DIFF,

+RING_DELTA,

+WTCHDOG_CNT,

+RING_WAVE,

+UNUSED226,

+ONEKHZ_COUNT,

+TX2100_Y1,

+TX2100_Y2,

+TX2100_MAG,

+RX2100_Y1,

+RX2100_Y2,

+RX2100_MAG,

+TX2100_POWER,

+RX2100_POWER,

+TX2100_IN,

+RX2100_IN,

+RINGTRIP_COUNT,

+RINGTRIP_DC1,

+RINGTRIP_DC2,

+RINGTRIP_AC1,

+RINGTRIP_AC2,

+RINGTRIP_AC_COUNT,

+RINGTRIP_DC_COUNT,

+RINGTRIP_AC_RESULT,

+RINGTRIP_DC_RESULT,

+RINGTRIP_ABS,

+TXACEQ_OUT,

+LCR_DBI_CNT,

+BAT_DBI_CNT,

+LONG_DBI_CNT,

+TXACEQ_DELAY3,

+TXACEQ_DELAY2,

+TXACEQ_DELAY1,

+RXACEQ_DELAY3,

+RXACEQ_DELAY2,

+RXACEQ_DELAY1,

+RXACEQ_IN,

+TXDCCOMB_D1,

+TXDCCOMB_D2,

+TXDCSINC_OUT,

+RXACDIFF_D1,

+DC_NOTCH_1,

+DC_NOTCH_2,

+DC_NOTCH_OUT,

+DC_NOTCH_SCALED,

+V_FEED_IN,

+I_TAR,

+CONST_VLIM,

+UNITY,

+TXACNOTCH_1,

+TXACNOTCH_2,

+TXACNOTCH_OUT,

+ZSYNTH_1,

+ZSYNTH_2,

+ZSYNTH_OUT_1,

+TXACD2_1_0,

+TXACD2_1_1,

+TXACD2_1_2,

+TXACD2_1_3,

+TXACD2_1_4,

+TXACD2_1_5,

+TXACD2_1_OUT,

+TXACD2_2_0,

+TXACD2_2_1,

+TXACD2_2_2,

+TXACD2_2_3,

+TXACD2_2_4,

+TXACD2_2_5,

+TXACD2_2_OUT,

+TXACD2_3_0,

+TXACD2_3_1,

+TXACD2_3_2,

+TXACD2_3_3,

+TXACD2_3_4,

+TXACD2_3_5,

+TXACD2_3_OUT,

+RXACI2_1_1,

+RXACI2_1_2,

+RXACI2_1_3,

+RXACI2_1_4,

+RXACI2_1_OUT,

+RXACI2_2_1,

+RXACI2_2_2,

+RXACI2_2_3,

+RXACI2_2_4,

+RXACI2_2_OUT,

+RXACI2_3_1,

+RXACI2_3_2,

+RXACI2_3_3,

+RXACI2_3_4,

+RXACI2_3_OUT,

+TXACCOMP1,

+TXACCOMP_OUT,

+RXACCOMP1,

+RXACCOMP_OUT,

+RXACHPF_D1_2,

+RXACHPF_D2_1,

+RXACHPF_D2_2,

+RXACHPF_OUT,

+RXACHPF_OUT_1,

+RXACHPF_OUT_2,

+RXACEQ_OUT,

+METER_I_1,

+METER_I_OUT,

+METER_LPF_1,

+METER_LPF_2,

+METER_LPF_OUT_1,

+METER_BP_1,

+METER_BP_2,

+METER_BP_OUT,

+METER_SRC_OUT,

+PMDIFF_D1,

+PMDIFF_D2,

+RING_LPF_1,

+RING_LPF_2,

+RING_LPF_OUT,

+RING_INTERP_DIFF,

+RING_INTERP_DIFF_OUT,

+RING_INTERP_INT,

+RING_INTERP_INT_OUT,

+V_ILIM_TRACK,

+V_RFEED_TRACK,

+LF_SPEEDUP_CNT,

+DC_SPEEDUP_CNT,

+AC_SPEEDUP_CNT,

+LCR_SPEEDUP_CNT,

+CM_SPEEDUP_CNT,

+DC_SPEEDUP_MASK,

+ZSYNTH_IN,

+I_TAR_SAVE,

+UNUSED352,

+UNUSED353,

+COUNTER_VTR,

+I_RING_AVG,

+COUNTER_IRING,

+COMP_RATIO,

+MADC_VBAT_DIV2,

+VDIFF_PK_T,

+PEAK_CNT,

+CM_DBI_CNT,

+VCM_LAST,

+VBATL_SENSE,

+VBATH_SENSE,

+VBATR_SENSE,

+BAT_SETTLE_CNT,

+VBAT_TGT,

+VBAT_REQ,

+VCM_HIRES,

+VCM_LORES,

+ILOOP1,

+ILONG2,

+ITIP1,

+IRING1,

+CAL_TEMP1,

+CAL_TEMP2,

+CAL_TEMP3,

+CAL_TEMP4,

+CAL_TEMP5,

+CAL_TEMP6,

+CAL_TEMP7,

+CMRR_DIVISOR,

+CMRR_REMAINDER,

+CMRR_Q_PTR,

+CAL_LKG_DWN_C0,

+CAL_LKG_DWN_V0,

+CAL_LKG_DWN_CN,

+CAL_LKG_DWN_VN,

+CAL_LKG_DWN_VLSB,

+CAL_LKG_DWN_ILSB,

+CAL_LKG_DWN_DACCODE,

+CAL_LKG_DWN_ICALC,

+CAL_ONHK_Z,

+CAL_LB_SETTLE,

+CAL_DECLPF_V0,

+CAL_DECLPF_V1,

+CAL_DECLPF_V2,

+CAL_GOERTZEL_V0,

+CAL_GOERTZEL_V1,

+CAL_DECLPF_Y,

+CAL_GOERTZEL_Y,

+P_HVIC,

+VBATL_MIRROR,

+VBATH_MIRROR,

+VBATR_MIRROR,

+DIAG_EX1_OUT,

+DIAG_EX2_OUT,

+DIAG_DMM_V_OUT,

+DIAG_DMM_I_OUT,

+DIAG_P,

+DIAG_LPF_V,

+DIAG_LPF_I,

+DIAG_TONE_FLAG,

+ILOOP1_LAST,

+RING_ENTRY_VOC,

+MADC_VBAT_LAST,

+OSC1_X_SAVE,

+EZSYNTH_1,

+EZSYNTH_2,

+ZSYNTH_OUT,

+UNUSED421,

+CAL_SUBSTATE,

+DIAG_EX1_DC_OUT,

+DIAG_EX1_DC,

+EZSYNTH_B1,

+EZSYNTH_B2,

+EZSYNTH_A1,

+EZSYNTH_A2,

+ILOOP1_FILT,

+AC_PU_DELTA1_CNT,

+AC_PU_DELTA2_CNT,

+UNUSED432,

+UNUSED433,

+UNUSED434,

+AC_DAC_GAIN_SAVE,

+RING_FLUSH_CNT,

+UNUSED437,

+DIAG_VAR_OUT,

+I_VBAT,

+UNUSED440,

+CALTMP_LOOPCNT,

+CALTMP_LOOPINC,

+CALTMP_ILOOPX1,

+CALTMP_CODEINC,

+CALTMP_TAUINC,

+CALTMP_TAU,

+CAL_TEMP8,

+PATCH_ID,

+UNUSED449,

+UNUSED450,

+UNUSED451,

+CAL_LB_OFFSET_FWD,

+CAL_LB_OFFSET_RVS,

+COUNT_SPEEDUP,

+SWEEP_COUNT,

+AMP_RAMP,

+DIAG_LPF_MADC_D,

+DIAG_HPF_MADC,

+DIAG_V_TAR,

+TXDEC_OUT,

+TXDEC_D1,

+TXDEC_D2,

+RXDEC_D1,

+RXDEC_D2,

+OSCINT1_D2_1,

+OSCINT1_D1_1,

+OSCINT1_OUT_1,

+OSCINT1_D2_2,

+OSCINT1_D1_2,

+OSCINT1_OUT,

+OSCINT2_D2_1,

+OSCINT2_D1_1,

+OSCINT2_OUT_1,

+OSCINT2_D2_2,

+OSCINT2_D1_2,

+OSCINT2_OUT,

+OSC1_Y_SAVE,

+OSC2_Y_SAVE,

+PWRSAVE_CNT,

+VBATR_PK,

+SPEEDUP_MASK_CNT,

+VCM_RING_FIXED,

+DELTA_VCM,

+MADC_VTIPC_DIAG_OS,

+MADC_VRINGC_DIAG_OS,

+MADC_VLONG_DIAG_OS,

+MADC_ISNS_DIAG_STBY_OS,

+MADC_ISNS_DIAG_OS,

+DCDC_FSW_VTHLO,

+DCDC_FSW_VHYST,

+DCDC_FSW_STATE,

+PWRSAVE_DBI_CNT,

+COMP_RATIO_SAVE,

+CAL_TEMP9,

+CAL_TEMP10,

+DAC_OFFSET_TEMP,

+CAL_DAC_CODE,

+DCDAC_OFFSET,

+VDIFF_COARSE,

+RXACIIR_OUT_4,

+UNUSED501,

+UNUSED502,

+CAL_TEMP11,

+UNUSED504,

+UNUSED505,

+UNUSED506,

+UNUSED507,

+UNUSED508,

+UNUSED509,

+UNUSED510,

+UNUSED511,

+MINUS_ONE,

+ILOOPLPF,

+ILONGLPF,

+BATLPF,

+VDIFFLPF,

+VCMLPF,

+TXACIIR_B0_1,

+TXACIIR_B1_1,

+TXACIIR_A1_1,

+TXACIIR_B0_2,

+TXACIIR_B1_2,

+TXACIIR_B2_2,

+TXACIIR_A1_2,

+TXACIIR_A2_2,

+TXACIIR_B0_3,

+TXACIIR_B1_3,

+TXACIIR_B2_3,

+TXACIIR_A1_3,

+TXACIIR_A2_3,

+TXACHPF_B0_1,

+TXACHPF_B1_1,

+TXACHPF_A1_1,

+TXACHPF_B0_2,

+TXACHPF_B1_2,

+TXACHPF_B2_2,

+TXACHPF_A1_2,

+TXACHPF_A2_2,

+TXACHPF_GAIN,

+TXACEQ_C0,

+TXACEQ_C1,

+TXACEQ_C2,

+TXACEQ_C3,

+TXACGAIN,

+RXACGAIN,

+RXACEQ_C0,

+RXACEQ_C1,

+RXACEQ_C2,

+RXACEQ_C3,

+RXACIIR_B0_1,

+RXACIIR_B1_1,

+RXACIIR_A1_1,

+RXACIIR_B0_2,

+RXACIIR_B1_2,

+RXACIIR_B2_2,

+RXACIIR_A1_2,

+RXACIIR_A2_2,

+RXACIIR_B0_3,

+RXACIIR_B1_3,

+RXACIIR_B2_3,

+RXACIIR_A1_3,

+RXACIIR_A2_3,

+ECFIR_C2,

+ECFIR_C3,

+ECFIR_C4,

+ECFIR_C5,

+ECFIR_C6,

+ECFIR_C7,

+ECFIR_C8,

+ECFIR_C9,

+ECIIR_B0,

+ECIIR_B1,

+ECIIR_A1,

+ECIIR_A2,

+DTMFDTF_B0_1,

+DTMFDTF_B1_1,

+DTMFDTF_B2_1,

+DTMFDTF_A1_1,

+DTMFDTF_A2_1,

+DTMFDTF_B0_2,

+DTMFDTF_B1_2,

+DTMFDTF_B2_2,

+DTMFDTF_A1_2,

+DTMFDTF_A2_2,

+DTMFDTF_B0_3,

+DTMFDTF_B1_3,

+DTMFDTF_B2_3,

+DTMFDTF_A1_3,

+DTMFDTF_A2_3,

+DTMFDTF_GAIN,

+DTMFLPF_B0_1,

+DTMFLPF_B1_1,

+DTMFLPF_B2_1,

+DTMFLPF_A1_1,

+DTMFLPF_A2_1,

+DTMFLPF_B0_2,

+DTMFLPF_B1_2,

+DTMFLPF_B2_2,

+DTMFLPF_A1_2,

+DTMFLPF_A2_2,

+DTMFLPF_GAIN,

+DTMFHPF_B0_1,

+DTMFHPF_B1_1,

+DTMFHPF_B2_1,

+DTMFHPF_A1_1,

+DTMFHPF_A2_1,

+DTMFHPF_B0_2,

+DTMFHPF_B1_2,

+DTMFHPF_B2_2,

+DTMFHPF_A1_2,

+DTMFHPF_A2_2,

+DTMFHPF_GAIN,

+POWER_GAIN,

+GOERTZEL_GAIN,

+MODEM_GAIN,

+HOTBIT1,

+HOTBIT0,

+ROW0_C1,

+ROW1_C1,

+ROW2_C1,

+ROW3_C1,

+COL0_C1,

+COL1_C1,

+COL2_C1,

+COL3_C1,

+ROW0_C2,

+ROW1_C2,

+ROW2_C2,

+ROW3_C2,

+COL0_C2,

+COL1_C2,

+COL2_C2,

+COL3_C2,

+SLOPE_VLIM,

+SLOPE_RFEED,

+SLOPE_ILIM,

+SLOPE_RING,

+SLOPE_DELTA1,

+SLOPE_DELTA2,

+V_VLIM,

+V_RFEED,

+V_ILIM,

+CONST_RFEED,

+CONST_ILIM,

+I_VLIM,

+DC_DAC_GAIN,

+VDIFF_TH,

+TXDEC_B0,

+TXDEC_B1,

+TXDEC_B2,

+TXDEC_A1,

+TXDEC_A2,

+ZSYNTH_B0,

+ZSYNTH_B1,

+ZSYNTH_B2,

+ZSYNTH_A1,

+ZSYNTH_A2,

+RXACHPF_B0_1,

+RXACHPF_B1_1,

+RXACHPF_A1_1,

+RXACHPF_B0_2,

+RXACHPF_B1_2,

+RXACHPF_B2_2,

+RXACHPF_A1_2,

+RXACHPF_A2_2,

+RXACHPF_GAIN,

+MASK7LSB,

+RXDEC_B0,

+RXDEC_B1,

+RXDEC_B2,

+RXDEC_A1,

+RXDEC_A2,

+OSCINT1_B0_1,

+OSCINT1_B1_1,

+OSCINT1_B2_1,

+OSCINT1_A1_1,

+OSCINT1_A2_1,

+OSCINT1_B0_2,

+OSCINT1_B1_2,

+OSCINT1_B2_2,

+OSCINT1_A1_2,

+OSCINT1_A2_2,

+OSCINT2_B0_1,

+OSCINT2_B1_1,

+OSCINT2_B2_1,

+OSCINT2_A1_1,

+OSCINT2_A2_1,

+OSCINT2_B0_2,

+OSCINT2_B1_2,

+OSCINT2_B2_2,

+OSCINT2_A1_2,

+OSCINT2_A2_2,

+UNUSED693,

+UNUSED694,

+UNUSED695,

+RING_LPF_B0,

+RING_LPF_B1,

+RING_LPF_B2,

+RING_LPF_A1,

+RING_LPF_A2,

+LCRDBI,

+LONGDBI,

+VBAT_TIMER,

+LF_SPEEDUP_TIMER,

+DC_SPEEDUP_TIMER,

+AC_SPEEDUP_TIMER,

+LCR_SPEEDUP_TIMER,

+CM_SPEEDUP_TIMER,

+VCM_TH,

+AC_SPEEDUP_TH,

+SPR_SIG_0,

+SPR_SIG_1,

+SPR_SIG_2,

+SPR_SIG_3,

+SPR_SIG_4,

+SPR_SIG_5,

+SPR_SIG_6,

+SPR_SIG_7,

+SPR_SIG_8,

+SPR_SIG_9,

+SPR_SIG_10,

+SPR_SIG_11,

+SPR_SIG_12,

+SPR_SIG_13,

+SPR_SIG_14,

+SPR_SIG_15,

+SPR_SIG_16,

+SPR_SIG_17,

+SPR_SIG_18,

+COUNTER_VTR_VAL,

+CONST_028,

+CONST_032,

+CONST_038,

+CONST_046,

+COUNTER_IRING_VAL,

+GAIN_RING,

+RING_HYST,

+COMP_Z,

+CONST_115,

+CONST_110,

+CONST_105,

+CONST_100,

+CONST_095,

+CONST_090,

+CONST_085,

+V_RASUM_IDEAL,

+CONST_ONE,

+VCM_OH,

+VCM_RING,

+VCM_HYST,

+VOV_GND,

+VOV_BAT,

+VOV_RING_BAT,

+CM_DBI,

+RTPER,

+P_TH_HVIC,

+P_TH_Q1256,

+P_TH_Q34,

+COEF_P_HVIC,

+COEF_Q1256,

+COEF_Q34,

+R_OFFLOAD,

+R_63,

+BAT_HYST,

+BAT_DBI,

+VBATL_EXPECT,

+VBATH_EXPECT,

+VBATR_EXPECT,

+BAT_SETTLE,

+VBAT_IRQ_TH,

+MADC_VTIPC_OS,

+MADC_VRINGC_OS,

+MADC_VBAT_OS,

+MADC_VLONG_OS,

+UNUSED775,

+MADC_VDC_OS,

+MADC_ILONG_OS,

+MADC_ISNS_STDBY_OS,

+MADC_ISNS_OS,

+MADC_ILOOP_OS,

+MADC_ILOOP_SCALE,

+UNUSED782,

+UNUSED783,

+DC_ADC_OS,

+CAL_UNITY,

+UNUSED786,

+UNUSED787,

+ACADC_OFFSET,

+ACDAC_OFFSET,

+CAL_DCDAC_CODE,

+CAL_DCDAC_15MA,

+CAL_LKG_TSETTLE,

+CAL_LKG_IREF100,

+CAL_LKG_LIM100UA,

+CAL_LKG_VREF25,

+CAL_LKG_VLSB_0_INV,

+CAL_LKG_RDCSNS_EFF,

+CAL_LKG_RDCOFF_EFF,

+CAL_LKG_CODE_OS,

+CAL_LKG_VMAX_THR,

+CAL_LB_TSQUELCH,

+CAL_LB_TCHARGE,

+CAL_LB_TSETTLE0,

+CAL_GOERTZEL_DLY,

+CAL_GOERTZEL_ALPHA,

+CAL_DECLPF_K,

+CAL_DECLPF_B1,

+CAL_DECLPF_B2,

+CAL_DECLPF_A1,

+CAL_DECLPF_A2,

+CAL_ACADC_THRL,

+CAL_ACADC_THRH,

+CAL_ACADC_TSETTLE,

+DTROW0TH,

+DTROW1TH,

+DTROW2TH,

+DTROW3TH,

+DTCOL0TH,

+DTCOL1TH,

+DTCOL2TH,

+DTCOL3TH,

+DTFTWTH,

+DTRTWTH,

+DTROWRTH,

+DTCOLRTH,

+DTROW2HTH,

+DTCOL2HTH,

+DTMINPTH,

+DTHOTTH,

+RXPWR,

+TXPWR,

+RXMODPWR,

+TXMODPWR,

+FSKFREQ0,

+FSKFREQ1,

+FSKAMP0,

+FSKAMP1,

+FSK01,

+FSK10,

+VOCDELTA,

+VOCLTH,

+VOCHTH,

+RINGOF,

+RINGFR,

+RINGAMP,

+RINGPHAS,

+RTDCTH,

+RTACTH,

+RTDCDB,

+RTACDB,

+RTCOUNT,

+LCROFFHK,

+LCRONHK,

+LCRMASK,

+LCRMASK_POLREV,

+LCRMASK_STATE,

+LCRMASK_LINECAP,

+LONGHITH,

+LONGLOTH,

+IRING_LIM,

+AC_PU_DELTA1,

+AC_PU_DELTA2,

+DIAG_LPF_8K,

+DIAG_LPF_128K,

+DIAG_INV_N,

+DIAG_GAIN,

+DIAG_G_CAL,

+DIAG_OS_CAL,

+SPR_GAIN_TRIM,

+MADC_VBAT_HYST,

+AC_DAC_GAIN,

+STDBY_THRLO,

+STDBY_THRHI,

+AC_DAC_GAIN0,

+EZSYNTH_B0,

+UNUSED876,

+UNUSED877,

+UNUSED878,

+UNUSED879,

+AC_ADC_GAIN,

+ILOOP1LPF,

+RING_FLUSH_TIMER,

+ALAW_BIAS,

+MADC_VTRC_SCALE,

+MADC_VBAT_SCALE0,

+MADC_VBAT_SCALE1,

+MADC_VLONG_SCALE,

+MADC_VLONG_SCALE_RING,

+UNUSED889,

+MADC_VDC_SCALE,

+MADC_ILONG_SCALE,

+MADC_ITR_SCALE,

+UNUSED893,

+VDIFF_SENSE_SCALE,

+VDIFF_SENSE_SCALE_RING,

+VOV_RING_GND,

+DIAG_GAIN_DC,

+CAL_LB_OSC1_FREQ,

+CAL_DCDAC_9TAU,

+CAL_MADC_9TAU,

+ADAP_RING_MIN_I,

+SWEEP_STEP,

+SWEEP_STEP_SAVE,

+SWEEP_REF,

+AMP_STEP,

+RXACGAIN_SAVE,

+AMP_RAMP_INIT,

+DIAG_HPF_GAIN,

+DIAG_HPF_8K,

+DIAG_ADJ_STEP,

+CAL_LKG_CODE_OS_COMP,

+UNUSED912,

+MADC_SCALE_INV,

+UNUSED914,

+PWRSAVE_TIMER,

+OFFHOOK_THRESH,

+SPEEDUP_MASK_TIMER,

+UNUSED918,

+DCDC_VREF_MIN,

+DCDC_VREF_MIN_RNG,

+DCDC_FSW_NORM,

+DCDC_FSW_NORM_LO,

+DCDC_FSW_RING,

+DCDC_FSW_RING_LO,

+DCDC_DIN_LIM,

+DCDC_VOUT_LIM,

+DC_HOLD_DAC_OS,

+DAA_DTMF_IN_SCALE,

+NOTCH_B0,

+NOTCH_B1,

+NOTCH_B2,

+NOTCH_A1,

+NOTCH_A2,

+METER_LPF_B0,

+METER_LPF_B1,

+METER_LPF_B2,

+METER_LPF_A1,

+METER_LPF_A2,

+METER_SIG_0,

+METER_SIG_1,

+METER_SIG_2,

+METER_SIG_3,

+METER_SIG_4,

+METER_SIG_5,

+METER_SIG_6,

+METER_SIG_7,

+METER_SIG_8,

+METER_SIG_9,

+METER_SIG_10,

+METER_SIG_11,

+METER_SIG_12,

+METER_SIG_13,

+METER_SIG_14,

+METER_SIG_15,

+METER_BP_B0,

+METER_BP_B1,

+METER_BP_B2,

+METER_BP_A1,

+METER_BP_A2,

+PM_AMP_THRESH,

+PM_GAIN,

+PWRSAVE_DBI,

+DCDC_ANA_SCALE,

+VOV_BAT_PWRSAVE_LO,

+VOV_BAT_PWRSAVE_HI,

+AC_ADC_GAIN0,

+SCALE_KAUDIO,

+UNUSED968,

+UNUSED969,

+UNUSED970,

+UNUSED971,

+UNUSED972,

+UNUSED973,

+UNUSED974,

+UNUSED975,

+UNUSED976,

+UNUSED977,

+UNUSED978,

+UNUSED979,

+UNUSED980,

+UNUSED981,

+UNUSED982,

+UNUSED983,

+UNUSED984,

+UNUSED985,

+UNUSED986,

+UNUSED987,

+UNUSED988,

+UNUSED989,

+UNUSED990,

+UNUSED991,

+UNUSED992,

+UNUSED993,

+UNUSED994,

+UNUSED995,

+UNUSED996,

+UNUSED997,

+UNUSED998,

+UNUSED999,

+UNUSED1000,

+UNUSED1001,

+UNUSED1002,

+UNUSED1003,

+UNUSED1004,

+UNUSED1005,

+UNUSED1006,

+UNUSED1007,

+UNUSED1008,

+UNUSED1009,

+UNUSED1010,

+UNUSED1011,

+UNUSED1012,

+UNUSED1013,

+UNUSED1014,

+UNUSED1015,

+UNUSED1016,

+UNUSED1017,

+UNUSED1018,

+UNUSED1019,

+UNUSED1020,

+UNUSED1021,

+UNUSED1022,

+UNUSED1023

+};

+

+/*

+** This defines the neumomics for applicable SI3217X Memory-mapped register locations

+*/

+enum {

+    PD_BIAS = 1413,

+    PD_VBAT_SNS = 1418,

+    MADC_LOOP_MAN = 1445,

+    HVIC_CNTL_MAN = 1451,

+    CAL_TRNRD_DACT = 1458,

+    CAL_TRNRD_DACR,

+    CMDAC_FWD = 1476,

+    CMDAC_REV,

+	RDC_SUM = 1499,

+    DCDC_DCFF_ENABLE = 1522,

+    PD_DCDC = 1538,

+	DCDC_UVHYST = 1545,

+	DCDC_UVTHRESH,

+	DCDC_OVTHRESH = 1547,

+	DCDC_OITHRESH,

+	UNUSED1549,

+	DCDC_CCM_THRESH,

+	DCDC_STATUS,

+	DCDC_FSW,

+	DCDC_SWDRV_POL,

+	DCDC_UVPOL,

+	DCDC_SWFET,

+	UNUSED1556,

+	UNUSED1557,

+	DCDC_VREF_CTRL,

+	UNUSED1559,

+	DCDC_RNGTYPE,

+    PD_REF_OSC = 1571,

+    DCDC_ANA_GAIN = 1585,

+    DCDC_ANA_TOFF,

+    DCDC_ANA_TONMIN,

+    DCDC_ANA_TONMAX,

+    DCDC_ANA_DSHIFT,

+    DCDC_ANA_LPOLY

+};

+

+#endif

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x.h
new file mode 100755
index 0000000..5b24848
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x.h
@@ -0,0 +1,209 @@
+/*

+** Copyright (c) 2007-2009 by Silicon Laboratories

+**

+** $Id: si321x.h 933 2009-07-27 17:00:38Z nizajerk@SILABS.COM $

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+*/

+

+/*

+** Si321x Function Definitions/Datatypes

+*/

+#ifndef SI321XH_H

+#define SI321XH_H

+

+#include "proslic.h"

+

+

+#define SI321X_POWERUP_VOLT_THRESH 0x11

+

+/*

+** Defines structure for configuring dcdc converter

+*/

+typedef struct {

+	uInt8 irqen1;

+	uInt8 irqen2;

+	uInt8 irqen3;

+} Si321x_General_Cfg;

+

+typedef struct {

+	Oscillator_Cfg osc1;

+	Oscillator_Cfg osc2;

+	uInt8 omode1;

+	uInt8 omode2;

+} Si321x_Tone_Cfg; 

+

+

+/*

+** Defines structure for configuring ring generator

+*/

+typedef struct {

+	ramData rngx;

+	ramData rngy;

+	ramData roff;

+	ramData rco;

+	uInt8 talo;

+	uInt8 tahi;

+	uInt8 tilo;

+	uInt8 tihi;

+	uInt8 ringcon;

+	uInt8 rtdi;

+	uInt16 nrtp;

+} Si321x_Ring_Cfg;

+

+/*

+** Defines structure for configuring gpio

+*/

+typedef void Si321x_GPIO_Cfg;

+

+/*

+** Defines structure for configuring dc feed

+*/

+typedef struct {

+	uInt8 ilim;

+	uInt8 voc;

+	uInt8 vcm;

+} Si321x_DCfeed_Cfg;

+

+/*

+** Defines structure for configuring pcm

+*/

+typedef struct {

+	uInt8 pcmf;

+	uInt8 wbe;

+	uInt8 tri;

+} Si321x_PCM_Cfg;

+

+/*

+** Defines structure for configuring pulse metering

+*/

+typedef struct {

+	ramData plsco;

+	ramData plsx;

+	ramData plsd;

+	uInt16 pat;  /*Active Timer (Hi & Low byte)*/

+	uInt16 pit;  /*Inactive Timer (Hi & Low byte)*/

+} Si321x_PulseMeter_Cfg;

+

+

+/*

+** Defines structure for configuring FSK generation

+*/

+typedef struct {

+	ramData fsk01;

+	ramData fsk10;

+	ramData fsk0x; 

+	ramData fsk1x;	

+	ramData fsk0; 

+	ramData fsk1; 

+} Si321x_FSK_Cfg;

+

+/*

+** Defines structure for configuring dtmf decode

+*/

+typedef void Si321x_DTMFDec_Cfg;

+

+/*

+** Defines structure for configuring impedence synthesis

+*/

+typedef struct {

+	uInt8 clc;

+	uInt8 tiss;

+} Si321x_Zsynth_Cfg;

+

+/*

+** Defines structure for configuring hybrid

+*/

+typedef void Si321x_hybrid_Cfg;

+

+/*

+** Defines structure for configuring GCI CI bits

+*/

+typedef void Si321x_CI_Cfg;

+

+/*

+** Defines structure for configuring modem tone detect

+*/

+typedef void Si321x_modemDet_Cfg;

+

+/*

+** Defines structure for configuring audio eq

+*/

+typedef void Si321x_audioEQ_Cfg;

+

+/*

+** Defines structure for configuring audio gain

+*/

+typedef struct {

+	uInt8 gain;

+	uInt16 digGain;

+} Si321x_audioGain_Cfg;

+

+/*

+** Defines structure for configuring ring trip

+*/

+typedef struct {

+	uInt8 rtdi;

+	ramData rptp;

+	ramData nrtp;

+} Si321x_ringTrip_Cfg;

+

+/*

+** Defines country config structure

+*/

+typedef struct {

+	uInt16 countryCode;

+	ProslicRegInit *registers;

+	ProslicRAMInit *rams;

+	Si321x_FSK_Cfg fsk;

+	Si321x_Ring_Cfg ring;

+	Si321x_ringTrip_Cfg ringtrip;

+	Si321x_Zsynth_Cfg zsynth;

+	Si321x_DCfeed_Cfg dcfeed;

+} Si321x_country_Cfg;

+

+/*

+** This defines names for the interrupts in the ProSLIC

+*/

+

+#define OSC1_T1_SI321X 0 

+#define OSC1_T2_SI321X 1

+#define OSC2_T1_SI321X 2

+#define OSC2_T2_SI321X 3

+#define RING_T1_SI321X 4

+#define RING_T2_SI321X 5

+#define PM_T1_SI321X 6

+#define PM_T2_SI321X 7

+#define RING_TRIP_SI321X 8

+#define LOOP_STAT_SI321X 9

+#define PQ1_SI321X 10

+#define PQ2_SI321X 11

+#define PQ3_SI321X 12

+#define PQ4_SI321X 13

+#define PQ5_SI321X 14

+#define PQ6_SI321X 15

+#define DTMF_SI321X 16

+#define INDIRECT_SI321X 17

+#define CM_BAL_SI321X 18

+

+/* NOTE: these match the bit values of dr09 */

+typedef enum si321x_analog_gains

+{

+    SI321X_AG_0DB,

+    SI321X_AG_NEG35DB,

+    SI321X_AG_POS35DB,

+    SI321X_AG_LAST 

+} Si321x_AG_SETTING;

+

+#define SI321X_MIN_LOOP_CURRENT 20

+#define SI321X_MAX_LOOP_CURRENT 41

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x_intf.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x_intf.h
new file mode 100755
index 0000000..a7c3edd
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x_intf.h
@@ -0,0 +1,652 @@
+/*

+** Copyright (c) 2007-2009 by Silicon Laboratories

+**

+** $Id: si321x_intf.h 2395 2010-11-03 23:09:03Z nizajerk $

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+*/

+

+#ifndef SI321x_INTF_H

+#define SI321x_INTF_H

+

+#include "proslic.h"

+#include "si321x.h"

+

+int Si321x_Reset (proslicChanType_ptr hProslic);

+int Si321x_Init (proslicChanType_ptr *hProslic, int size);

+int Si321x_InitBroadcast (proslicChanType_ptr *hProslic);

+int Si321x_Cal (proslicChanType_ptr *hProslic, int size);

+int Si321x_SetLinefeedStatus (proslicChanType *pProslic,uInt8 newLinefeed);

+int Si321x_SetLinefeedStatusBroadcast (proslicChanType *pProslic,uInt8 newLinefeed);

+int Si321x_PrintDebugData(proslicChanType_ptr hProslic);

+int Si321x_VerifyControlInterface(proslicChanType_ptr hProslic);

+/*

+** Function: PROSLIC_LoadRegTables

+**

+** Description: 

+** Loads registers and ram in the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pRamTable: pointer to ram values to load

+** pRegTable: pointer to register values to load

+** 

+**

+** Return:

+** none

+*/

+int Si321x_LoadRegTables (proslicChanType_ptr *hProslic, ProslicRAMInit *pRamTable, ProslicRegInit *pRegTable, int size);

+

+/*

+** Function: PROSLIC_LoadPatch

+**

+** Description: 

+** Loads patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si321x_LoadPatch (proslicChanType_ptr hProslic, proslicPatch *pPatch);

+

+

+/*

+** Function: PROSLIC_EnableInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si321x_EnableInterrupts (proslicChanType_ptr hProslic);

+int Si321x_DisableInterrupts (proslicChanType_ptr hProslic);

+

+int Si321x_SetLoopbackMode (proslicChanType_ptr hProslic, ProslicLoopbackModes newMode);

+int Si321x_SetMuteStatus (proslicChanType_ptr hProslic, ProslicMuteModes muteEn);

+/*

+**

+** PROSLIC CONFIGURATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_RingSetup

+**

+** Description: 

+** configure ringing

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pRingSetup: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si321x_RingSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ToneGenSetup

+**

+** Description: 

+** configure tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pTone: pointer to tones config structure

+**

+** Return:

+** none

+*/

+int Si321x_ToneGenSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_FSKSetup

+**

+** Description: 

+** configure fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pFsk: pointer to fsk config structure

+**

+** Return:

+** none

+*/

+int Si321x_FSKSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_DTMFDecodeSetup

+**

+** Description: 

+** configure dtmf decode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDTMFDec: pointer to dtmf decoder config structure

+**

+** Return:

+** none

+*/

+int Si321x_DTMFDecodeSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_SetProfile

+**

+** Description: 

+** set country profile of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCountryData: pointer to country config structure

+**

+** Return:

+** none

+*/

+int Si321x_SetProfile (proslicChanType *pProslic, Si321x_country_Cfg *pCountryData);

+

+/*

+** Function: PROSLIC_ZsynthSetup

+**

+** Description: 

+** configure impedence synthesis

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pZynth: pointer to zsynth config structure

+**

+** Return:

+** none

+*/

+int Si321x_ZsynthSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_GciCISetup

+**

+** Description: 

+** configure CI bits (GCI mode)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCI: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si321x_GciCISetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ModemDetSetup

+**

+** Description: 

+** configure modem detector

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pModemDet: pointer to modem det config structure

+**

+** Return:

+** none

+*/

+int Si321x_ModemDetSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_TXAudioGainSetup

+**

+** Description: 

+** configure audio gains

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudio: pointer to audio gains config structure

+**

+** Return:

+** none

+*/

+int Si321x_TXAudioGainSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_RXAudioGainSetup

+**

+** Description: 

+** configure audio gains

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudio: pointer to audio gains config structure

+**

+** Return:

+** none

+*/

+int Si321x_RXAudioGainSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_HybridSetup

+**

+** Description: 

+** configure Proslic hybrid

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHybridCfg: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si321x_HybridSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioEQSetup

+**

+** Description: 

+** configure audio equalizers

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudioEQ: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si321x_AudioEQSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_DCFeedSetup

+**

+** Description: 

+** configure dc feed

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDcFeed: pointer to dc feed config structure

+**

+** Return:

+** none

+*/

+int Si321x_DCFeedSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_GPIOSetup

+**

+** Description: 

+** configure gpio

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpio: pointer to gpio config structure

+**

+** Return:

+** none

+*/

+int Si321x_GPIOSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_PulseMeterSetup

+**

+** Description: 

+** configure pulse metering

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPulseCfg: pointer to pulse metering config structure

+**

+** Return:

+** none

+*/

+int Si321x_PulseMeterSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_PCMSetup

+**

+** Description: 

+** configure pcm

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPcm: pointer to pcm config structure

+**

+** Return:

+** none

+*/

+int Si321x_PCMSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_PCMTimeSlotSetup

+**

+** Description: 

+** configure pcm

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** rxcount

+** txcount

+**

+** Return:

+** none

+*/

+int Si321x_PCMTimeSlotSetup (proslicChanType *pProslic, uInt16 rxcount, uInt16 txcount);

+

+/*

+**

+** PROSLIC CONTROL FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_GetInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** pIntData: pointer to interrupt info retrieved

+** 

+** Return:

+** 

+*/

+int Si321x_GetInterrupts (proslicChanType_ptr hProslic, proslicIntType *pIntData);

+

+/*

+** Function: PROSLIC_ReadHookStatus

+**

+** Description: 

+** Determine hook status

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHookStat: current hook status

+**

+** Return:

+** none

+*/

+int Si321x_ReadHookStatus (proslicChanType *pProslic,uInt8 *pHookStat);

+

+/*

+** Function: PROSLIC_PolRev

+**

+** Description: 

+** Sets polarity reversal state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** abrupt: set this to 1 for abrupt pol rev

+** newPolRevState: new pol rev state

+**

+** Return:

+** none

+*/

+int Si321x_PolRev (proslicChanType *pProslic,uInt8 abrupt, uInt8 newPolRevState);

+

+/*

+** Function: PROSLIC_GPIOControl

+**

+** Description: 

+** Sets gpio of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpioData: pointer to gpio status

+** read: set to 1 to read status, 0 to write

+**

+** Return:

+** none

+*/

+int Si321x_GPIOControl (proslicChanType *pProslic,uInt8 *pGpioData, uInt8 read);

+

+/*

+** Function: PROSLIC_MWI

+**

+** Description: 

+** implements message waiting indicator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** lampOn: 0 = turn lamp off, 1 = turn lamp on

+**

+** Return:

+** none

+*/

+int Si321x_MWI (proslicChanType *pProslic,uInt8 lampOn);

+

+/*

+** Function: PROSLIC_StartGenericTone

+**

+** Description: 

+** Initializes and start tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** timerEn: specifies whether to enable the tone generator timers

+**

+** Return:

+** none

+*/

+int Si321x_ToneGenStart (proslicChanType *pProslic, uInt8 timerEn);

+

+

+/*

+** Function: PROSLIC_StopTone

+**

+** Description: 

+** Stops tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_ToneGenStop (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StartRing

+**

+** Description: 

+** Initializes and start ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_RingStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopRing

+**

+** Description: 

+** Stops ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_RingStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_EnableCID

+**

+** Description: 

+** enable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_EnableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DisableCID

+**

+** Description: 

+** disable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_DisableCID (proslicChanType *pProslic);

+

+int Si321x_CheckCIDBuffer (proslicChanType *pProslic,uInt8 * fsk_buf_avail);

+

+/*

+** Function: PROSLIC_SendCID

+**

+** Description: 

+** send fsk data

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** buffer: buffer to send

+** numBytes: num of bytes in the buffer

+**

+** Return:

+** none

+*/

+int Si321x_SendCID (proslicChanType *pProslic, uInt8 *buffer, uInt8 numBytes);

+

+/*

+** Function: PROSLIC_StartPCM

+**

+** Description: 

+** Starts PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_PCMStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopPCM

+**

+** Description: 

+** Disables PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_PCMStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_ReadDTMFDigit

+**

+** Description: 

+** Read DTMF digit (would be called after DTMF interrupt to collect digit)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDigit: digit read

+**

+** Return:

+** none

+*/

+int Si321x_DTMFReadDigit (proslicChanType *pProslic,uInt8 *pDigit);

+

+/*

+** Function: PROSLIC_PLLFreeRunStart

+**

+** Description: 

+** initiates pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_PLLFreeRunStart (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PLLFreeRunStop

+**

+** Description: 

+** exit pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_PLLFreeRunStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterStart

+**

+** Description: 

+** start pulse meter tone

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_PulseMeterStart (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterStop

+**

+** Description: 

+** stop pulse meter tone

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si321x_PulseMeterStop (proslicChanType *pProslic);

+

+

+/*

+** Function: Si321x_SetAudioGain

+**

+** Description: 

+** Set audio gain of RX and TX paths

+** NOTE: preset at this time is not used.

+**

+*/

+

+int Si321x_AudioGainSetup(proslicChanType *pProslic, int rxgain, int txgain, int preset);

+

+

+int Si321x_dbgSetDCFeedVopen (proslicChanType *pProslic, uInt32 v_vlim_val, int32 preset);

+

+int Si321x_dbgSetDCFeedIloop (proslicChanType *pProslic, uInt32 i_ilim_val, int32 preset);

+

+int Si321x_dbgSetGain(proslicChanType *pProslic, int32 gain, int ag_value, int audio_gain_preset);

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x_registers.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x_registers.h
new file mode 100755
index 0000000..af020e4
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si321x_registers.h
@@ -0,0 +1,217 @@
+/* Copyright 2009, Silicon Laboratories */

+#ifndef SI321XREGS_H

+#define SI321XREGS_H

+

+

+

+

+#define IDA_LO  28

+#define IDA_HI	29

+

+#define IAA 30

+#define CLOCK_MASK 0x04

+#define ID_ACCES_STATUS 31

+#define IAS_BIT 1

+

+#define	I_STATUS	31

+

+#define	SPI_MODE	0

+#define	PCM_MODE	1

+#define	PCM_XMIT_START_COUNT_LSB	2

+#define	PCM_XMIT_START_COUNT_MSB	3

+#define	PCM_RCV_START_COUNT_LSB	4

+#define	PCM_RCV_START_COUNT_MSB	5

+#define	DIO	6

+

+#define	AUDIO_LOOPBACK	8

+#define	AUDIO_GAIN	9

+#define	LINE_IMPEDANCE	10

+#define	HYBRID	11

+#define	RESERVED12	12

+#define	RESERVED13	13

+#define	PWR_DOWN1	14

+#define	PWR_DOWN2	15

+#define	RESERVED16	16

+#define	RESERVED17	17

+#define	INTRPT_STATUS1	18

+#define	INTRPT_STATUS2	19

+#define	INTRPT_STATUS3	20

+#define	INTRPT_MASK1	21

+#define	INTRPT_MASK2	22

+#define	INTRPT_MASK3	23

+#define	DTMF_DIGIT	24

+#define	RESERVED25	25

+#define	RESERVED26	26

+#define	RESERVED27	27

+#define	I_DATA_LOW	28

+#define	I_DATA_HIGH	29

+#define	I_ADDRESS	30

+#define	I_STATUS	31

+#define	OSC1	32

+#define	OSC2	33

+#define	RING_OSC_CTL	34

+#define	PULSE_OSC	35

+#define	OSC1_ON__LO	36

+#define	OSC1_ON_HI	37

+#define	OSC1_OFF_LO	38

+#define	OSC1_OFF_HI	39

+#define	OSC2_ON__LO	40

+#define	OSC2_ON_HI	41

+#define	OSC2_OFF_LO	42

+#define	OSC2_OFF_HI	43

+#define	PULSE_ON__LO	44

+#define	PULSE_ON_HI	45

+#define	PULSE_OFF_LO	46

+#define	PULSE_OFF_HI	47

+#define	RING_ON__LO	48

+#define	RING_ON_HI	49

+#define	RING_OFF_LO	50

+#define	RING_OFF_HI	51

+#define	FSK_DATA	52	/*		0								fsk_data	*/

+#define	RESERVED53	53

+#define	RESERVED54	54

+#define	RESERVED55	55

+#define	RESERVED56	56

+#define	RESERVED57	57

+#define	RESERVED58	58

+#define	RESERVED59	59

+#define	RESERVED60	60

+#define	RESERVED61	61

+#define	RESERVED62	62

+#define	RESERVED63	63

+#define	LINE_STATE	64

+#define			ACTIVATE_LINE 0x11

+#define			RING_LINE     0x44

+#define	BIAS_SQUELCH	65

+#define	BAT_FEED	66

+#define	AUTO_STATE	67

+#define	LOOP_STAT	68

+#define	LOOP_DEBOUCE	69

+#define	RT_DEBOUCE	70

+#define	LOOP_I_LIMIT	71

+#define	ON_HOOK_V	72

+#define	COMMON_V	73

+#define	BAT_V_HI	74

+#define	BAT_V_LO	75

+#define	PWR_STAT_DEV	76

+#define	PWR_STAT	77

+#define	LOOP_V_SENSE	78

+#define	LOOP_I_SENSE	79

+#define	TIP_V_SENSE	80

+#define	RING_V_SENSE	81

+#define	BAT_V_HI_SENSE	82

+#define	BAT_V_LO_SENSE	83

+#define	IQ1	84

+#define	IQ2	85

+#define	IQ3	86

+#define	IQ4	87

+#define	IQ5	88

+#define	IQ6	89

+#define	RESERVED90	90

+#define	RESERVED91	91

+#define	DCDC_PWM_OFF	92

+#define	DCDC	93

+#define	DCDC_PW_OFF	94

+#define	RESERVED95	95

+#define	CALIBR1	96

+#define CALIBRATE_LINE 0x78

+#define NORMAL_CALIBRATION_COMPLETE 0x20

+#define	CALIBR2	97

+#define	RING_GAIN_CAL	98

+#define	TIP_GAIN_CAL	99

+#define	DIFF_I_CAL	100

+#define	COMMON_I_CAL	101

+#define	I_LIMIT_GAIN_CAL	102

+#define	ADC_OFFSET_CAL	103

+#define	DAC_ADC_OFFSET	104

+#define	DAC_OFFSET_CAL	105

+#define	COMMON_BAL_CAL	106

+#define	DC_PEAK_CAL	107

+

+/* Indirect Register (decimal) */

+#define	DTMF_ROW_0_PEAK	0

+#define	DTMF_ROW_1_PEAK	1

+#define	DTMF_ROW2_PEAK	2

+#define	DTMF_ROW3_PEAK	3

+#define	DTMF_COL1_PEAK	4

+#define	DTMF_FWD_TWIST	5

+#define	DTMF_RVS_TWIST	6

+#define	DTMF_ROW_RATIO_THRESH	7

+#define	DTMF_COL_RATIO_THRESH	8

+#define	DTMF_ROW_2ND_HARM	9

+#define	DTMF_COL_2ND_HARM	10

+#define	DTMF_PWR_MIN_THRESH	11

+#define	DTMF_HOT_LIM_THRESH	12

+#define	OSC1_COEF	13

+#define	OSC1X	14

+#define	OSC1Y	15

+#define	OSC2_COEF	16

+#define	OSC2X	17

+#define	OSC2Y	18

+#define	RING_V_OFF	19

+#define	RING_OSC_COEF	20

+#define	RING_X	21

+#define	RING_Y	22

+#define	PULSE_ENVEL	23

+#define	PULSE_X	24

+#define	PULSE_Y	25

+#define	RECV_DIGITAL_GAIN	26

+#define	XMIT_DIGITAL_GAIN	27

+#define	LOOP_CLOSE_THRESH	28

+#define	RING_TRIP_THRESH	29

+#define	COMMON_MIN_THRESH	30

+#define	COMMON_MAX_THRESH	31

+#define	PWR_ALARM_Q1Q2	32

+#define	PWR_ALARM_Q3Q4	33

+#define	PWR_ALARM_Q5Q6	34

+#define	LOOP_CLOSURE_FILTER	35

+#define	RING_TRIP_FILTER	36

+#define	THERM_LP_POLE_Q1Q2	37

+#define	THERM_LP_POLE_Q3Q4	38

+#define	THERM_LP_POLE_Q5Q6	39

+#define	CM_BIAS_RINGING	40

+#define	DCDC_MIN_V	41

+#define	DCDC_XTRA	42

+#define ALL_CHIPS 0x09

+#define NO_CHIPS 0

+#define	REVC	108	/*		0	ilim_max	fsk_revc	dc_err_en	zs_ext	batsel_pd	lcr_sense	en_subtr	hyst_en	*/

+#define	FSK_X_0		99	/*	x	sign				fsk_x_0[15:0]												*/

+#define	FSK_COEFF_0	100	/*	x	sign				fsk_coeff_0[15:0]												*/

+#define	FSK_X_1		101	/*	x	sign				fsk_x_1[15:0]												*/

+#define	FSK_COEFF_1	102	/*	x	sign				fsk_coeff_1[15:0]												*/

+#define	FSK_X_01	103	/*	x	sign				fsk_x_01[15:0]												*/

+#define	FSK_X_10	104	/*	x	sign				fsk_x_10[15:0]												*/

+

+				

+#define	BIT_CALM1_DR97	0x10	/*	CALM1 Monitor ADC Calibration 1. */

+#define	BIT_CALM2_DR97	0x08	/*	CALM2 Monitor ADC Calibration 2. */

+#define	BIT_CALDAC_DR97	0x04	/*	CALDAC DAC Calibration. */

+#define	BIT_ADC_DR97	0x02	/*	CALADC ADC Calibration. */

+#define	BIT_CALCM_DR97	0x01	/*	CALCM Common Mode Balance Calibration. */

+#define	STANDARD_CAL_DR97	0x18	/*	Calibrations without the ADC and DAC offset and without common mode calibration. */

+#define	MASK_CAL_DR96	0x40	/*	CAL Calibration Status Bit. */

+#define	BIT_CAL_DR96	0x40	/*	CAL Calibration Control */

+#define	BIT_CALR_DR96	0x10	/*	CALR RING Gain Mismatch Calibration. */

+#define	BIT_CALT_DR96	0x08	/*	CALT TIP Gain Mismatch Calibration. */

+#define	BIT_CALD_DR96	0x04	/*	CALD Differential DAC Gain Calibration. */

+#define	BIT_CALC_DR96	0x02	/*	CALC Common Mode DAC Gain Calibration. */

+#define	BIT_CALIL_DR96	0x01	/*	CALIL ILIM Calibration. */

+#define	STANDARD_CAL_DR96	0x47	/*	Calibrate common mode and differential DAC mode DAC + ILIM */

+#define	BIT_IRQE_CMCE	0x04	/*	Calibrate common mode and differential mode DAC + ILIM */

+#define CAL_COMPLETE_DR96 0     /*  Value in dr96 after calibration is completed */

+#define MAX_CAL_PERIOD 800		/* The longest period in ms. for a calibration to complete. */

+

+

+#define DISABLE_ALL_DR21 0

+#define DISABLE_ALL_DR22 0

+#define DISABLE_ALL_DR23 0

+

+#define ENB2_DR23  1<<2 /* enable interrupt for the balance Cal */

+

+#define	OPEN_DR64	0		

+

+

+#define SI321X_BROADCAST 0xff

+

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226.h
new file mode 100755
index 0000000..4cdc0cb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226.h
@@ -0,0 +1,355 @@
+/*

+** Copyright (c) 2007 by Silicon Laboratories

+**

+** $Id: si3226.h 1832 2010-04-19 21:39:12Z cdp $

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+*/

+#ifndef SI3226H_H

+#define SI3226H_H

+

+#include "proslic.h"

+

+/*

+** SI3226 DataTypes/Function Definitions 

+*/

+

+#define NUMIRQ 4

+

+

+/*

+** Defines structure for configuring gpio

+*/

+typedef struct {

+	uInt8 outputEn;

+	uInt8 analog;

+	uInt8 direction;

+	uInt8 manual;

+	uInt8 polarity;

+	uInt8 openDrain;

+	uInt8 batselmap;

+} Si3226_GPIO_Cfg;

+

+/*

+** Defines structure for configuring dc feed

+*/

+typedef struct {

+	ramData slope_vlim;

+	ramData slope_rfeed;

+	ramData slope_ilim;

+	ramData delta1;

+	ramData delta2;

+	ramData v_vlim;

+	ramData v_rfeed;

+	ramData v_ilim;

+	ramData const_rfeed;

+	ramData const_ilim;

+	ramData i_vlim;

+	ramData lcronhk;

+	ramData lcroffhk;

+	ramData lcrdbi;

+	ramData longhith;

+	ramData longloth;

+	ramData longdbi;

+	ramData lcrmask;

+	ramData lcrmask_polrev;

+	ramData lcrmask_state;

+	ramData lcrmask_linecap;

+	ramData vcm_oh;

+	ramData vov_bat;

+	ramData vov_gnd;

+} Si3226_DCfeed_Cfg;

+/*

+** Defines structure for configuring dcdc converter

+*/

+typedef struct {

+    bomOptionsType bomOpt;

+	ramData vbatr_expect; /* default - this is overwritten by ring preset */

+	ramData vbath_expect;  

+    ramData dcdc_fsw_vthlo; 

+    ramData dcdc_fsw_vhyst; 

+	ramData dcdc_vref_min; 

+    ramData dcdc_vref_min_ring; 

+	ramData dcdc_fsw_norm; 

+	ramData dcdc_fsw_norm_lo; 

+	ramData dcdc_fsw_ring; 

+	ramData dcdc_fsw_ring_lo; 

+	ramData dcdc_din_lim; 

+	ramData dcdc_vout_lim; 

+    ramData dcdc_dcff_enable;

+	ramData dcdc_uvhyst; 

+	ramData dcdc_uvthresh; 

+	ramData dcdc_ovthresh; 

+	ramData dcdc_oithresh; 

+    ramData dcdc_swdrv_pol; 

+    ramData dcdc_swfet; 

+    ramData dcdc_vref_ctrl; 

+    ramData dcdc_rngtype; 

+    ramData dcdc_ana_gain; 

+    ramData dcdc_ana_toff; 

+    ramData dcdc_ana_tonmin; 

+    ramData dcdc_ana_tonmax; 

+    ramData dcdc_ana_dshift; 

+    ramData dcdc_ana_lpoly; 

+	ramData coef_p_hvic;

+	ramData p_th_hvic;

+	uInt8	cm_clamp;

+	uInt8	autoRegister;

+	uInt8 daa_cntl;

+	uInt8 irqen1;

+	uInt8 irqen2;

+	uInt8 irqen3;

+	uInt8 irqen4;

+    uInt8 enhance;

+    uInt8 daa_enable;

+    ramData scale_kaudio;

+    ramData ac_adc_gain;

+} Si3226_General_Cfg;

+/*

+** Defines structure for configuring pcm

+*/

+typedef struct {

+    uInt8 pcmFormat;

+    uInt8 widebandEn;

+    uInt8 pcm_tri;

+    uInt8 tx_edge;

+    uInt8 alaw_inv;

+} Si3226_PCM_Cfg;

+

+/*

+** Currently unsupported.  For upgradability

+*/

+typedef void Si3226_PulseMeter_Cfg;

+

+/*

+** Defines structure for configuring FSK generation

+*/

+typedef struct {

+	ramData fsk01;

+	ramData fsk10;

+	ramData fskamp0;

+	ramData fskamp1;

+	ramData fskfreq0;

+	ramData fskfreq1;

+	uInt8 eightBit;

+	uInt8 fskdepth;

+} Si3226_FSK_Cfg;

+

+/*

+** Defines structure for configuring dtmf decode

+*/

+typedef struct {

+	ramData dtmfdtf_b0_1;

+	ramData dtmfdtf_b1_1;

+	ramData dtmfdtf_b2_1;

+	ramData dtmfdtf_a1_1;

+	ramData dtmfdtf_a2_1;

+	ramData dtmfdtf_b0_2;

+	ramData dtmfdtf_b1_2;

+	ramData dtmfdtf_b2_2;

+	ramData dtmfdtf_a1_2;

+	ramData dtmfdtf_a2_2;

+	ramData dtmfdtf_b0_3;

+	ramData dtmfdtf_b1_3;

+	ramData dtmfdtf_b2_3;

+	ramData dtmfdtf_a1_3;

+	ramData dtmfdtf_a2_3;

+} Si3226_DTMFDec_Cfg;

+

+/*

+** Defines structure for configuring impedence synthesis

+*/

+typedef struct {

+	ramData zsynth_b0;

+	ramData zsynth_b1;

+	ramData zsynth_b2;

+	ramData zsynth_a1;

+	ramData zsynth_a2;

+	uInt8 ra;

+} Si3226_Zsynth_Cfg;

+

+/*

+** Defines structure for configuring hybrid

+*/

+typedef struct {

+	ramData ecfir_c2;

+	ramData ecfir_c3;

+	ramData ecfir_c4;

+	ramData ecfir_c5;

+	ramData ecfir_c6;

+	ramData ecfir_c7;

+	ramData ecfir_c8;

+	ramData ecfir_c9;

+	ramData ecfir_b0;

+	ramData ecfir_b1;

+	ramData ecfir_a1;

+	ramData ecfir_a2;

+} Si3226_hybrid_Cfg;

+

+/*

+** Defines structure for configuring GCI CI bits

+*/

+typedef struct {

+	uInt8 gci_ci;

+} Si3226_CI_Cfg;

+

+/*

+** Defines structure for configuring modem tone detect

+*/

+typedef struct {

+	ramData rxmodpwr;

+	ramData rxpwr;

+	ramData modem_gain;

+	ramData txmodpwr;

+	ramData txpwr;

+} Si3226_modemDet_Cfg;

+

+/*

+** Defines structure for configuring audio eq

+*/

+typedef struct {

+	ramData txaceq_c0;

+	ramData txaceq_c1;

+	ramData txaceq_c2;

+	ramData txaceq_c3;

+

+	ramData rxaceq_c0;

+	ramData rxaceq_c1;

+	ramData rxaceq_c2;

+	ramData rxaceq_c3;

+} Si3226_audioEQ_Cfg;

+

+/*

+** Defines structure for configuring audio gain

+*/

+typedef struct {

+	ramData acgain;

+	uInt8 mute;

+	ramData aceq_c0; 

+	ramData aceq_c1;

+	ramData aceq_c2;

+	ramData aceq_c3;

+} Si3226_audioGain_Cfg;

+

+

+/*

+** Defines structure for configuring synthesized impedange

+*/

+typedef struct {

+	Si3226_audioEQ_Cfg audioEQ;

+	Si3226_hybrid_Cfg hybrid;

+    Si3226_Zsynth_Cfg zsynth;

+	ramData txgain;

+	ramData rxgain;

+	ramData rxachpf_b0_1;

+	ramData  rxachpf_b1_1;

+	ramData  rxachpf_a1_1;

+	int16 txgain_db; /*overall gain associated with this configuration*/

+	int16 rxgain_db;

+} Si3226_Impedance_Cfg;

+

+

+

+/*

+** Defines structure for configuring tone generator

+*/

+typedef struct {

+	Oscillator_Cfg osc1;

+	Oscillator_Cfg osc2;

+	uInt8 omode;

+} Si3226_Tone_Cfg; 

+

+/*

+** Defines structure for configuring ring generator

+*/

+typedef struct {

+	ramData rtper;

+	ramData freq;

+	ramData amp;

+	ramData phas;

+	ramData offset;

+	ramData slope_ring;

+    ramData iring_lim;

+    ramData rtacth;

+	ramData rtdcth;

+	ramData rtacdb;

+	ramData rtdcdb;

+	ramData vov_ring_bat;

+	ramData vov_ring_gnd;

+    ramData vbatr_expect;

+	uInt8 talo;

+	uInt8 tahi;

+	uInt8 tilo;

+	uInt8 tihi;

+	ramData adap_ring_min_i;

+    ramData counter_iring_val;

+	ramData counter_vtr_val;

+    ramData ar_const28;

+    ramData ar_const32;

+    ramData ar_const38;

+    ramData ar_const46;

+	ramData rrd_delay;

+	ramData rrd_delay2;

+    ramData dcdc_vref_min_rng;

+	uInt8 ringcon;

+    uInt8 userstat;

+	ramData vcm_ring;

+    ramData vcm_ring_fixed;

+    ramData delta_vcm;

+    ramData dcdc_rngtype;

+} Si3226_Ring_Cfg;

+

+

+

+/*

+** This defines names for the interrupts in the ProSLIC

+*/

+typedef enum {

+/* IRQ1 */

+IRQ_OSC1_T1_SI3226 = 0,   

+IRQ_OSC1_T2_SI3226,

+IRQ_OSC2_T1_SI3226,

+IRQ_OSC2_T2_SI3226,

+IRQ_RING_T1_SI3226,

+IRQ_RING_T2_SI3226,

+IRQ_FSKBUF_AVAIL_SI3226,

+IRQ_VBAT_SI3226,

+/* IRQ2 */

+IRQ_RING_TRIP_SI3226 = 8,

+IRQ_LOOP_STAT_SI3226,

+IRQ_LONG_STAT_SI3226,

+IRQ_VOC_TRACK_SI3226,

+IRQ_DTMF_SI3226,

+IRQ_INDIRECT_SI3226,

+IRQ_TXMDM_SI3226,

+IRQ_RXMDM_SI3226,

+/* IRQ3 */

+IRQ_P_HVIC_SI3226 = 16,  

+IRQ_P_THERM_SI3226,

+IRQ_PQ3_SI3226,

+IRQ_PQ4_SI3226,

+IRQ_PQ5_SI3226,

+IRQ_PQ6_SI3226,

+IRQ_DSP_SI3226,

+IRQ_MADC_FS_SI3226,

+/* IRQ4 */

+IRQ_USER_0_SI3226 = 24, 

+IRQ_USER_1_SI3226,

+IRQ_USER_2_SI3226,

+IRQ_USER_3_SI3226,

+IRQ_USER_4_SI3226,

+IRQ_USER_5_SI3226,

+IRQ_USER_6_SI3226,

+IRQ_USER_7_SI3226

+}Si3226ProslicInt;

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226_intf.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226_intf.h
new file mode 100755
index 0000000..adbd636
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226_intf.h
@@ -0,0 +1,860 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: si3226_intf.h 3100 2011-09-15 14:04:54Z cdp $

+**

+** Si3226_Intf.h

+** Si3226 ProSLIC interface header file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file for the ProSLIC driver.

+**

+** Dependancies:

+** proslic_datatypes.h, Si3226_registers.h, ProSLIC.h

+**

+*/

+#ifndef SI3226_INTF_H

+#define SI3226_INTF_H

+

+

+/*

+**

+** Si3226 General Constants

+**

+*/

+#define CHAN_PER_DEVICE             2

+  

+/* Timeouts in 10s of ms */

+#define SI3226_TIMEOUT_DCDC_UP             200

+#define SI3226_TIMEOUT_DCDC_DOWN           200

+ 

+

+#define SI3226_CAL_STD_CALR1               0xFF

+#define SI3226_CAL_STD_CALR2               0xF8

+

+

+/*

+**

+** PROSLIC INITIALIZATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_Reset

+**

+** Description: 

+** Resets the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_Reset (proslicChanType_ptr hProslic);

+

+/*

+** Function: PROSLIC_ShutdownChannel

+**

+** Description: 

+** Safely shutdown channel w/o interruption to 

+** other active channels

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_ShutdownChannel (proslicChanType_ptr hProslic);

+

+/*

+** Function: PROSLIC_Init

+**

+** Description: 

+** Initializes the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_Init (proslicChanType_ptr *hProslic,int size);

+

+/*

+** Function: PROSLIC_Reinit

+**

+** Description: 

+** Peforms Soft Reset and reinitializes the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_Reinit (proslicChanType_ptr hProslic,int size);

+

+/*

+** Function: PROSLIC_Init_MultiBOM

+**

+** Description: 

+** Initializes the ProSLIC with supplied general configuration preset

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_Init_MultiBOM (proslicChanType_ptr *hProslic,int size,int preset);

+

+

+int Si3226_VerifyControlInterface (proslicChanType_ptr hProslic);

+uInt8 Si3226_ReadReg (proslicChanType_ptr hProslic,uInt8 addr);

+int Si3226_WriteReg (proslicChanType_ptr hProslic,uInt8 addr,uInt8 data);

+ramData Si3226_ReadRAM (proslicChanType_ptr hProslic,uInt16 addr);

+int Si3226_WriteRAM (proslicChanType_ptr hProslic,uInt16 addr, ramData data);

+

+/*

+** Function: ProSLIC_PrintDebugData

+**

+** Description: 

+** Register and RAM dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_PrintDebugData (proslicChanType_ptr hProslic);

+

+/*

+** Function: ProSLIC_PrintDebugReg

+**

+** Description: 

+** Register dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_PrintDebugReg (proslicChanType_ptr hProslic);

+

+/*

+** Function: ProSLIC_PrintDebugRAM

+**

+** Description: 

+** RAM dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_PrintDebugRAM (proslicChanType_ptr hProslic);

+

+

+/*

+** Function: Si3226_PowerUpConverter

+**

+** Description: 

+** Powers all DC/DC converters sequentially with delay to minimize

+** peak power draw on VDC.

+**

+** Returns:

+** int (error)

+**

+*/

+int Si3226_PowerUpConverter(proslicChanType_ptr hProslic);

+

+/*

+** Function: Si3226_PowerDownConverter

+**

+** Description: 

+** Power down DCDC converter (selected channel only)

+**

+** Returns:

+** int (error)

+**

+*/

+int Si3226_PowerDownConverter(proslicChanType_ptr hProslic);

+

+

+/*

+** Function: PROSLIC_Calibrate

+**

+** Description: 

+** Calibrates the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_Calibrate (proslicChanType_ptr *hProslic, int size, uInt8 *calr, int maxTime);

+

+/*

+** Function: PROSLIC_Cal

+**

+** Description: 

+** Calibrates the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226_Cal (proslicChanType_ptr *hProslic, int size);

+

+/*

+** Function: PROSLIC_LoadRegTables

+**

+** Description: 

+** Loads registers and ram in the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pRamTable: pointer to ram values to load

+** pRegTable: pointer to register values to load

+** 

+**

+** Return:

+** none

+*/

+int Si3226_LoadRegTables (proslicChanType_ptr *hProslic, ProslicRAMInit *pRamTable, ProslicRegInit *pRegTable,int size);

+

+/*

+** Function: PROSLIC_LoadPatch

+**

+** Description: 

+** Loads patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si3226_LoadPatch (proslicChanType_ptr hProslic, const proslicPatch *pPatch);

+

+/*

+** Function: PROSLIC_VerifyPatch

+**

+** Description: 

+** Verifies patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si3226_VerifyPatch (proslicChanType_ptr hProslic, const proslicPatch *pPatch);

+

+/*

+** Function: PROSLIC_EnableInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si3226_EnableInterrupts (proslicChanType_ptr hProslic);

+int Si3226_DisableInterrupts (proslicChanType_ptr hProslic);

+

+int Si3226_SetLoopbackMode (proslicChanType_ptr hProslic, ProslicLoopbackModes newMode);

+

+int Si3226_SetMuteStatus (proslicChanType_ptr hProslic, ProslicMuteModes muteEn);

+/*

+**

+** PROSLIC CONFIGURATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_RingSetup

+**

+** Description: 

+** configure ringing

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pRingSetup: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3226_RingSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ToneGenSetup

+**

+** Description: 

+** configure tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pTone: pointer to tones config structure

+**

+** Return:

+** none

+*/

+int Si3226_ToneGenSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_FSKSetup

+**

+** Description: 

+** configure fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pFsk: pointer to fsk config structure

+**

+** Return:

+** none

+*/

+int Si3226_FSKSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_DTMFDecodeSetup

+**

+** Description: 

+** configure dtmf decode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDTMFDec: pointer to dtmf decoder config structure

+**

+** Return:

+** none

+*/

+int Si3226_DTMFDecodeSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_SetProfile

+**

+** Description: 

+** set country profile of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCountryData: pointer to country config structure

+**

+** Return:

+** none

+*/

+int Si3226_SetProfile (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ZsynthSetup

+**

+** Description: 

+** configure impedence synthesis

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pZynth: pointer to zsynth config structure

+**

+** Return:

+** none

+*/

+int Si3226_ZsynthSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_GciCISetup

+**

+** Description: 

+** configure CI bits (GCI mode)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCI: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3226_GciCISetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ModemDetSetup

+**

+** Description: 

+** configure modem detector

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pModemDet: pointer to modem det config structure

+**

+** Return:

+** none

+*/

+int Si3226_ModemDetSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioGainSetup

+**

+** Description: 

+** configure audio gains

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudio: pointer to audio gains config structure

+**

+** Return:

+** none

+*/

+int Si3226_TXAudioGainSetup (proslicChanType *pProslic, int preset);

+int Si3226_RXAudioGainSetup (proslicChanType *pProslic, int preset);

+int Si3226_AudioGainSetup (proslicChanType *pProslic, int32 rxgain, int32 txgain, int preset);

+

+/*

+** Function: PROSLIC_HybridSetup

+**

+** Description: 

+** configure Proslic hybrid

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHybridCfg: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3226_HybridSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioEQSetup

+**

+** Description: 

+** configure audio equalizers

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudioEQ: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3226_AudioEQSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_DCFeedSetup

+**

+** Description: 

+** configure dc feed

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDcFeed: pointer to dc feed config structure

+**

+** Return:

+** none

+*/

+int Si3226_DCFeedSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_GPIOSetup

+**

+** Description: 

+** configure gpio

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpio: pointer to gpio config structure

+**

+** Return:

+** none

+*/

+int Si3226_GPIOSetup (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PCMSetup

+**

+** Description: 

+** configure pcm

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPcm: pointer to pcm config structure

+**

+** Return:

+** none

+*/

+int Si3226_PCMSetup (proslicChanType *pProslic, int preset);

+int Si3226_PCMTimeSlotSetup (proslicChanType *pProslic, uInt16 rxcount, uInt16 txcount);

+

+/*

+**

+** PROSLIC CONTROL FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_GetInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** pIntData: pointer to interrupt info retrieved

+** 

+** Return:

+** 

+*/

+int Si3226_GetInterrupts (proslicChanType_ptr hProslic, proslicIntType *pIntData);

+

+/*

+** Function: PROSLIC_ReadHookStatus

+**

+** Description: 

+** Determine hook status

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHookStat: current hook status

+**

+** Return:

+** none

+*/

+int Si3226_ReadHookStatus (proslicChanType *pProslic,uInt8 *pHookStat);

+

+/*

+** Function: PROSLIC_WriteLinefeed

+**

+** Description: 

+** Sets linefeed state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** newLinefeed: new linefeed state

+**

+** Return:

+** none

+*/

+int Si3226_SetLinefeedStatus (proslicChanType *pProslic,uInt8 newLinefeed);

+

+/*

+** Function: PROSLIC_PolRev

+**

+** Description: 

+** Sets polarity reversal state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** abrupt: set this to 1 for abrupt pol rev

+** newPolRevState: new pol rev state

+**

+** Return:

+** none

+*/

+int Si3226_PolRev (proslicChanType *pProslic,uInt8 abrupt, uInt8 newPolRevState);

+

+/*

+** Function: PROSLIC_GPIOControl

+**

+** Description: 

+** Sets gpio of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpioData: pointer to gpio status

+** read: set to 1 to read status, 0 to write

+**

+** Return:

+** none

+*/

+int Si3226_GPIOControl (proslicChanType *pProslic,uInt8 *pGpioData, uInt8 read);

+

+/*

+** Function: PROSLIC_MWI

+**

+** Description: 

+** implements message waiting indicator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** lampOn: 0 = turn lamp off, 1 = turn lamp on

+**

+** Return:

+** none

+*/

+int Si3226_MWI (proslicChanType *pProslic,uInt8 lampOn);

+

+/*

+** Function: PROSLIC_StartGenericTone

+**

+** Description: 

+** Initializes and start tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** timerEn: specifies whether to enable the tone generator timers

+**

+** Return:

+** none

+*/

+int Si3226_ToneGenStart (proslicChanType *pProslic, uInt8 timerEn);

+

+

+/*

+** Function: PROSLIC_StopTone

+**

+** Description: 

+** Stops tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_ToneGenStop (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StartRing

+**

+** Description: 

+** Initializes and start ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_RingStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopRing

+**

+** Description: 

+** Stops ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_RingStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_EnableCID

+**

+** Description: 

+** enable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_EnableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DisableCID

+**

+** Description: 

+** disable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_DisableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_SendCID

+**

+** Description: 

+** send fsk data

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** buffer: buffer to send

+** numBytes: num of bytes in the buffer

+**

+** Return:

+** none

+*/

+int Si3226_SendCID (proslicChanType *pProslic, uInt8 *buffer, uInt8 numBytes);

+

+int Si3226_CheckCIDBuffer (proslicChanType *pProslic, uInt8 *fsk_buf_avail);

+

+/*

+** Function: PROSLIC_StartPCM

+**

+** Description: 

+** Starts PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_PCMStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopPCM

+**

+** Description: 

+** Disables PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_PCMStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DialPulseDetect

+**

+** Description: 

+** implements pulse dial detection and should be called at every off/on hook transistion

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPulsedialCfg: pointer to pulse dial config

+** pPulseDialData: pointer to pulse dial state for current channel

+**

+** Return:

+** none

+*/

+int Si3226_DialPulseDetect (proslicChanType *pProslic, pulseDial_Cfg *pPulsedialCfg, pulseDialType *pPulseDialData);

+

+/*

+** Function: PROSLIC_ReadDTMFDigit

+**

+** Description: 

+** Read DTMF digit (would be called after DTMF interrupt to collect digit)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDigit: digit read

+**

+** Return:

+** none

+*/

+int Si3226_DTMFReadDigit (proslicChanType *pProslic,uInt8 *pDigit);

+

+/*

+** Function: PROSLIC_PLLFreeRunStart

+**

+** Description: 

+** initiates pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_PLLFreeRunStart (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PLLFreeRunStop

+**

+** Description: 

+** exit pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226_PLLFreeRunStop (proslicChanType *pProslic);

+

+int Si3226_LBCal (proslicChanType_ptr *pProslic, int size);

+int Si3226_GetLBCalResult (proslicChanType *pProslic,int32*result1,int32*result2,int32 *result3,int32 *result4);

+int Si3226_GetLBCalResultPacked (proslicChanType *pProslic,int32 *result);

+int Si3226_LoadPreviousLBCal (proslicChanType *pProslic,int32 result1,int32 result2,int32 result3,int32 result4);

+int Si3226_LoadPreviousLBCalPacked (proslicChanType *pProslic,int32 *result);

+int Si3226_SetLinefeedStatusBroadcast (proslicChanType_ptr hProslic, uInt8 newLinefeed);

+

+/*

+** Function: PROSLIC_dbgSetDCFeed

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3226_dbgSetDCFeed (proslicChanType *pProslic, uInt32 v_vlim_val, uInt32 i_ilim_val, int32 preset);

+

+/*

+** Function: PROSLIC_dbgSetDCFeedVopen

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3226_dbgSetDCFeedVopen (proslicChanType *pProslic, uInt32 v_vlim_val, int32 preset);

+

+

+/*

+** Function: PROSLIC_dbgSetDCFeedIloop

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3226_dbgSetDCFeedIloop (proslicChanType *pProslic, uInt32 i_ilim_val, int32 preset);

+

+

+/*

+** Function: PROSLIC_dbgRingingSetup

+**

+** Description: 

+** Provisionary function for setting up

+** Ring type, frequency, amplitude and dc offset.

+** Main use will be by peek/poke applications.

+*/

+

+int Si3226_dbgSetRinging (proslicChanType *pProslic, ProSLIC_dbgRingCfg *ringCfg, int preset);

+

+int Si3226_dbgSetRXGain (proslicChanType *pProslic, int32 gain, int impedance_preset, int audio_gain_preset);

+int Si3226_dbgSetTXGain (proslicChanType *pProslic, int32 gain, int impedance_preset, int audio_gain_preset);

+

+int Si3226_LineMonitor (proslicChanType *pProslic, proslicMonitorType *monitor);

+int Si3226_PSTNCheck (proslicChanType *pProslic,proslicPSTNCheckObjType *pPSTNCheck);

+

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226_registers.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226_registers.h
new file mode 100755
index 0000000..9132fdf
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226_registers.h
@@ -0,0 +1,1201 @@
+/*

+** Copyright (c) 2007 by Silicon Laboratories

+**

+** $Id: si3226_registers.h 3044 2011-08-10 15:54:52Z cdp $

+**

+** Si3226_Registers.h

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file that contains

+** register and RAM names definitions for 

+** the Si3226 ProSLIC.

+**

+** Dependancies:

+** 

+**

+*/

+#ifndef SI3226REGS_H

+#define SI3226REGS_H

+

+/*

+** This defines the neumomics for the SI3226 registers

+*/

+enum REGISTERS {

+ID,

+RESET,

+MSTREN,

+MSTRSTAT,

+RAMSTAT,

+RAM_ADDR_HI,

+RAM_DATA_B0,

+RAM_DATA_B1,

+RAM_DATA_B2,

+RAM_DATA_B3,

+RAM_ADDR_LO,

+PCMMODE,

+PCMTXLO,

+PCMTXHI,

+PCMRXLO,

+PCMRXHI,

+IRQ,

+IRQ0,

+IRQ1,

+IRQ2,

+IRQ3,

+IRQ4,

+IRQEN1,

+IRQEN2,

+IRQEN3,

+IRQEN4,

+CALR0,

+CALR1,

+CALR2,

+CALR3,

+LINEFEED,

+POLREV,

+SPEEDUP_DIS,

+SPEEDUP,

+LCRRTP,

+OFFLOAD,

+BATSELMAP,

+BATSEL,

+RINGCON,

+RINGTALO,

+RINGTAHI,

+RINGTILO,

+RINGTIHI,

+LOOPBACK,

+DIGCON,

+RA,

+ZCAL_EN,

+ENHANCE,

+OMODE,

+OCON,

+O1TALO,

+O1TAHI,

+O1TILO,

+O1TIHI,

+O2TALO,

+O2TAHI,

+O2TILO,

+O2TIHI,

+FSKDAT,

+FSKDEPTH,

+TONDTMF,

+TONDET,

+TONEN,

+GCI_CI,

+GLOBSTAT1,

+GLOBSTAT2,

+USERSTAT,

+GPIO,

+GPIO_CFG1,

+GPIO_CFG2,

+GPIO_CFG3,

+DIAG1,

+DIAG2,

+CM_CLAMP,

+REG74,

+REG75,

+REG76,

+REG77,

+REG78,

+REG79,

+AUTO,

+JMPEN,

+JMP0LO,

+JMP0HI,

+JMP1LO,

+JMP1HI,

+JMP2LO,

+JMP2HI,

+JMP3LO,

+JMP3HI,

+JMP4LO,

+JMP4HI,

+JMP5LO,

+JMP5HI,

+JMP6LO,

+JMP6HI,

+JMP7LO,

+JMP7HI,

+PDN,

+PDN_STAT,

+USERMODE_ENABLE = 126

+};

+

+

+/*

+** This defines the neumomics for the SI3226 RAM locations (revB)

+*/

+enum SRAM {

+IRNGNG_SENSE,

+MADC_VTIPC,

+MADC_VRINGC,

+MADC_VBAT,

+MADC_VLONG,

+UNUSED5,

+MADC_VDC,

+MADC_ILONG,

+MADC_ITIP,

+MADC_IRING,

+MADC_ILOOP,

+VDIFF_SENSE,

+VTIP,

+VRING,

+P_Q1_D,

+P_Q2_D,

+P_Q3_D,

+P_Q4_D,

+P_Q5_D,

+P_Q6_D,

+P_Q1,

+DIAG_EX1,

+DIAG_EX2,

+DIAG_LPF_MADC,

+DIAG_DMM_I,

+DIAG_DMM_V,

+OSC1FREQ,

+OSC1AMP,

+OSC1PHAS,

+OSC2FREQ,

+OSC2AMP,

+OSC2PHAS,

+TESTB0_1,

+TESTB1_1,

+TESTB2_1,

+TESTA1_1,

+TESTA2_1,

+TESTB0_2,

+TESTB1_2,

+TESTB2_2,

+TESTA1_2,

+TESTA2_2,

+TESTB0_3,

+TESTB1_3,

+TESTB2_3,

+TESTA1_3,

+TESTA2_3,

+TESTPKO,

+TESTAVO,

+TESTWLN,

+TESTAVBW,

+TESTPKFL,

+TESTAVFL,

+TESTPKTH,

+TESTAVTH,

+DAC_IN_SYNC1,

+BYPASS_REG,

+LCRMASK_CNT,

+DAC_IN_SYNC,

+TEMP,

+TEMP_ISR,

+P_Q2,

+P_Q3,

+P_Q4,

+P_Q5,

+P_Q6,

+ILOOP_FILT,

+ILONG_FILT,

+VBAT_FILT,

+VDIFF_FILT,

+VCM_FILT,

+VBAT_CNT,

+V_VLIM_SCALED,

+V_VLIM_TRACK,

+V_VLIM_MODFEED,

+DIAG_P_OUT,

+DIAG_COUNT,

+ROW0_MAG,

+ROW1_MAG,

+ROW2_MAG,

+ROW3_MAG,

+COL0_MAG,

+COL1_MAG,

+COL2_MAG,

+COL3_MAG,

+ROW0_2ND_Y1,

+ROW1_2ND_Y1,

+ROW2_2ND_Y1,

+ROW3_2ND_Y1,

+COL0_2ND_Y1,

+COL1_2ND_Y1,

+COL2_2ND_Y1,

+COL3_2ND_Y1,

+ROW0_2ND_Y2,

+ROW1_2ND_Y2,

+ROW2_2ND_Y2,

+ROW3_2ND_Y2,

+COL0_2ND_Y2,

+COL1_2ND_Y2,

+COL2_2ND_Y2,

+COL3_2ND_Y2,

+DTMF_IN,

+DTMFDTF_D2_1,

+DTMFDTF_D1_1,

+DTMFDTF_OUT_1,

+DTMFDTF_D2_2,

+DTMFDTF_D1_2,

+DTMFDTF_OUT_2,

+DTMFDTF_D2_3,

+DTMFDTF_D1_3,

+DTMFDTF_OUT_3,

+DTMFDTF_OUT,

+DTMFLPF_D2_1,

+DTMFLPF_D1_1,

+DTMFLPF_OUT_1,

+DTMFLPF_D2_2,

+DTMFLPF_D1_2,

+DTMFLPF_OUT_2,

+DTMF_ROW,

+DTMFHPF_D2_1,

+DTMFHPF_D1_1,

+DTMFHPF_OUT_1,

+DTMFHPF_D2_2,

+DTMFHPF_D1_2,

+DTMFHPF_OUT_2,

+DTMF_COL,

+ROW_POWER,

+COL_POWER,

+GP_TIMER,

+SPR_INTERP_DIF,

+SPR_INTERP_DIF_OUT,

+SPR_INTERP_INT,

+SPR_CNT,

+ROW0_Y1,

+ROW0_Y2,

+ROW1_Y1,

+ROW1_Y2,

+ROW2_Y1,

+ROW2_Y2,

+ROW3_Y1,

+ROW3_Y2,

+COL0_Y1,

+COL0_Y2,

+COL1_Y1,

+COL1_Y2,

+COL2_Y1,

+COL2_Y2,

+COL3_Y1,

+COL3_Y2,

+ROWMAX_MAG,

+COLMAX_MAG,

+ROW0_2ND_MAG,

+COL0_2ND_MAG,

+ROW_THR,

+COL_THR,

+OSC1_Y,

+OSC2_Y,

+OSC1_X,

+OSC1_COEFF,

+OSC2_X,

+OSC2_COEFF,

+RXACIIR_D2_1,

+RXACIIR_OUT_1,

+RXACIIR_D2_2,

+RXACIIR_D1_2,

+RXACIIR_OUT_2,

+RXACIIR_D2_3,

+RXACIIR_D1_3,

+RXACIIR_OUT,

+RXACIIR_OUT_3,

+TXACCOMB_D1,

+TXACCOMB_D2,

+TXACCOMB_D3,

+TXACSINC_OUT,

+TXACHPF_D1_2,

+TXACHPF_D2_1,

+TXACHPF_D2_2,

+TXACHPF_OUT,

+TXACHPF_OUT_1,

+TXACHPF_OUT_2,

+TXACIIR_D2_1,

+TXACIIR_OUT_1,

+TXACIIR_D2_2,

+TXACIIR_D1_2,

+TXACIIR_OUT_2,

+TXACIIR_D2_3,

+TXACIIR_D1_3,

+TXACIIR_OUT_3,

+TXACIIR_OUT,

+ECIIR_D1,

+ECIIR_D2,

+EC_DELAY1,

+EC_DELAY2,

+EC_DELAY3,

+EC_DELAY4,

+EC_DELAY5,

+EC_DELAY6,

+EC_DELAY7,

+EC_DELAY8,

+EC_DELAY9,

+EC_DELAY10,

+EC_DELAY11,

+ECHO_EST,

+EC_OUT,

+TESTFILT_OUT_1,

+TESTFILT_D1_1,

+TESTFILT_D2_1,

+TESTFILT_OUT_2,

+TESTFILT_D1_2,

+TESTFILT_D2_2,

+TESTFILT_OUT_3,

+TESTFILT_D1_3,

+TESTFILT_D2_3,

+TESTFILT_PEAK,

+TESTFILT_ABS,

+TESTFILT_MEANACC,

+TESTFILT_COUNT,

+TESTFILT_NO_OFFSET,

+RING_X,

+RING_Y,

+RING_INT,

+RING_Y_D1,

+RING_DIFF,

+RING_DELTA,

+WTCHDOG_CNT,

+RING_WAVE,

+UNUSED226,

+ONEKHZ_COUNT,

+TX2100_Y1,

+TX2100_Y2,

+TX2100_MAG,

+RX2100_Y1,

+RX2100_Y2,

+RX2100_MAG,

+TX2100_POWER,

+RX2100_POWER,

+TX2100_IN,

+RX2100_IN,

+RINGTRIP_COUNT,

+RINGTRIP_DC1,

+RINGTRIP_DC2,

+RINGTRIP_AC1,

+RINGTRIP_AC2,

+RINGTRIP_AC_COUNT,

+RINGTRIP_DC_COUNT,

+RINGTRIP_AC_RESULT,

+RINGTRIP_DC_RESULT,

+RINGTRIP_ABS,

+TXACEQ_OUT,

+LCR_DBI_CNT,

+BAT_DBI_CNT,

+LONG_DBI_CNT,

+TXACEQ_DELAY3,

+TXACEQ_DELAY2,

+TXACEQ_DELAY1,

+RXACEQ_DELAY3,

+RXACEQ_DELAY2,

+RXACEQ_DELAY1,

+RXACEQ_IN,

+TXDCCOMB_D1,

+TXDCCOMB_D2,

+TXDCSINC_OUT,

+RXACDIFF_D1,

+UNUSED263,

+UNUSED264,

+UNUSED265,

+DC_NOTCH_SCALED,

+V_FEED_IN,

+I_TAR,

+CONST_VLIM,

+UNITY,

+UNUSED271,

+UNUSED272,

+UNUSED273,

+ZSYNTH_1,

+ZSYNTH_2,

+ZSYNTH_OUT_1,

+TXACD2_1_0,

+TXACD2_1_1,

+TXACD2_1_2,

+TXACD2_1_3,

+TXACD2_1_4,

+TXACD2_1_5,

+TXACD2_1_OUT,

+TXACD2_2_0,

+TXACD2_2_1,

+TXACD2_2_2,

+TXACD2_2_3,

+TXACD2_2_4,

+TXACD2_2_5,

+TXACD2_2_OUT,

+TXACD2_3_0,

+TXACD2_3_1,

+TXACD2_3_2,

+TXACD2_3_3,

+TXACD2_3_4,

+TXACD2_3_5,

+TXACD2_3_OUT,

+RXACI2_1_1,

+RXACI2_1_2,

+RXACI2_1_3,

+RXACI2_1_4,

+RXACI2_1_OUT,

+RXACI2_2_1,

+RXACI2_2_2,

+RXACI2_2_3,

+RXACI2_2_4,

+RXACI2_2_OUT,

+RXACI2_3_1,

+RXACI2_3_2,

+RXACI2_3_3,

+RXACI2_3_4,

+RXACI2_3_OUT,

+TXACCOMP1,

+TXACCOMP_OUT,

+RXACCOMP1,

+RXACCOMP_OUT,

+RXACHPF_D1_2,

+RXACHPF_D2_1,

+RXACHPF_D2_2,

+RXACHPF_OUT,

+RXACHPF_OUT_1,

+RXACHPF_OUT_2,

+RXACEQ_OUT,

+UNUSED324,

+UNUSED325,

+UNUSED326,

+UNUSED327,

+UNUSED328,

+UNUSED329,

+UNUSED330,

+UNUSED331,

+UNUSED332,

+UNUSED333,

+UNUSED334,

+RING_LPF_1,

+RING_LPF_2,

+RING_LPF_OUT,

+RING_INTERP_DIFF,

+RING_INTERP_DIFF_OUT,

+RING_INTERP_INT,

+RING_INTERP_INT_OUT,

+V_ILIM_TRACK,

+V_RFEED_TRACK,

+LF_SPEEDUP_CNT,

+DC_SPEEDUP_CNT,

+AC_SPEEDUP_CNT,

+LCR_SPEEDUP_CNT,

+CM_SPEEDUP_CNT,

+DC_SPEEDUP_MASK,

+ZSYNTH_IN,

+I_TAR_SAVE,

+V_TR_MAX,

+V_TR_MAX_TEMP,

+COUNTER_VTR,

+I_RING_AVG,

+COUNTER_IRING,

+COMP_RATIO,

+MADC_VBAT_DIV2,

+VDIFF_PK_T,

+PEAK_CNT,

+CM_DBI_CNT,

+VCM_LAST,

+VBATL_SENSE,

+VBATH_SENSE,

+VBATR_SENSE,

+BAT_SETTLE_CNT,

+VBAT_TGT,

+VBAT_REQ,

+VCM_HIRES,

+VCM_LORES,

+ILOOP1,

+ILONG2,

+ITIP1,

+IRING1,

+CAL_TEMP1,

+CAL_TEMP2,

+CAL_TEMP3,

+CAL_TEMP4,

+CAL_TEMP5,

+CAL_TEMP6,

+CAL_TEMP7,

+CMRR_DIVISOR,

+CMRR_REMAINDER,

+CMRR_Q_PTR,

+CAL_LKG_DWN_C0,

+CAL_LKG_DWN_V0,

+CAL_LKG_DWN_CN,

+CAL_LKG_DWN_VN,

+CAL_LKG_DWN_VLSB,

+CAL_LKG_DWN_ILSB,

+CAL_LKG_DWN_DACCODE,

+CAL_LKG_DWN_ICALC,

+CAL_ONHK_Z,

+CAL_LB_SETTLE,

+CAL_DECLPF_V0,

+CAL_DECLPF_V1,

+CAL_DECLPF_V2,

+CAL_GOERTZEL_V0,

+CAL_GOERTZEL_V1,

+CAL_DECLPF_Y,

+CAL_GOERTZEL_Y,

+P_HVIC,

+VBATL_MIRROR,

+VBATH_MIRROR,

+VBATR_MIRROR,

+DIAG_EX1_OUT,

+DIAG_EX2_OUT,

+DIAG_DMM_V_OUT,

+DIAG_DMM_I_OUT,

+DIAG_P,

+DIAG_LPF_V,

+DIAG_LPF_I,

+DIAG_TONE_FLAG,

+ILOOP1_LAST,

+RING_ENTRY_VOC,

+MADC_VBAT_LAST,

+OSC1_X_SAVE,

+EZSYNTH_1,

+EZSYNTH_2,

+ZSYNTH_OUT,

+CMRR,

+CAL_SUBSTATE,

+UNUSED423,

+UNUSED424,

+EZSYNTH_B1,

+EZSYNTH_B2,

+EZSYNTH_A1,

+EZSYNTH_A2,

+ILOOP1_FILT,

+AC_PU_DELTA1_CNT,

+AC_PU_DELTA2_CNT,

+UNUSED432,

+UNUSED433,

+UNUSED434,

+AC_DAC_GAIN_SAVE,

+RING_FLUSH_CNT,

+UNUSED437,

+DIAG_VAR_OUT,

+I_VBAT,

+P_OFFLOAD,

+CALTMP_LOOPCNT,

+CALTMP_LOOPINC,

+CALTMP_ILOOPX1,

+CALTMP_CODEINC,

+CALTMP_TAUINC,

+CALTMP_TAU,

+CAL_TEMP8,

+PATCH_ID,

+UNUSED449,

+UNUSED450,

+UNUSED451,

+CAL_LB_OFFSET_FWD,

+CAL_LB_OFFSET_RVS,

+COUNT_SPEEDUP,

+SWEEP_COUNT,

+AMP_RAMP,

+DIAG_LPF_MADC_D,

+DIAG_HPF_MADC,

+DIAG_V_TAR,

+TXDEC_OUT,

+TXDEC_D1,

+TXDEC_D2,

+RXDEC_D1,

+RXDEC_D2,

+OSCINT1_D2_1,

+OSCINT1_D1_1,

+OSCINT1_OUT_1,

+OSCINT1_D2_2,

+OSCINT1_D1_2,

+OSCINT1_OUT,

+OSCINT2_D2_1,

+OSCINT2_D1_1,

+OSCINT2_OUT_1,

+OSCINT2_D2_2,

+OSCINT2_D1_2,

+OSCINT2_OUT,

+OSC1_Y_SAVE,

+OSC2_Y_SAVE,

+PWRSAVE_CNT,

+VBATR_PK,

+SPEEDUP_MASK_CNT,

+VCM_RING_FIXED,

+DELTA_VCM,

+MADC_VTIPC_DIAG_OS,

+MADC_VRINGC_DIAG_OS,

+MADC_VLONG_DIAG_OS,

+MADC_ISNS_DIAG_STBY_OS,

+MADC_ISNS_DIAG_OS,

+DCDC_FSW_VTHLO,

+DCDC_FSW_VHYST,

+DCDC_FSW_STATE,

+UNUSED492,

+UNUSED493,

+UNUSED494,

+UNUSED495,

+UNUSED496,

+UNUSED497,

+UNUSED498,

+UNUSED499,

+UNUSED500,

+UNUSED501,

+UNUSED502,

+UNUSED503,

+UNUSED504,

+UNUSED505,

+UNUSED506,

+UNUSED507,

+UNUSED508,

+UNUSED509,

+UNUSED510,

+UNUSED511,

+MINUS_ONE,

+ILOOPLPF,

+ILONGLPF,

+BATLPF,

+VDIFFLPF,

+VCMLPF,

+TXACIIR_B0_1,

+TXACIIR_B1_1,

+TXACIIR_A1_1,

+TXACIIR_B0_2,

+TXACIIR_B1_2,

+TXACIIR_B2_2,

+TXACIIR_A1_2,

+TXACIIR_A2_2,

+TXACIIR_B0_3,

+TXACIIR_B1_3,

+TXACIIR_B2_3,

+TXACIIR_A1_3,

+TXACIIR_A2_3,

+TXACHPF_B0_1,

+TXACHPF_B1_1,

+TXACHPF_A1_1,

+TXACHPF_B0_2,

+TXACHPF_B1_2,

+TXACHPF_B2_2,

+TXACHPF_A1_2,

+TXACHPF_A2_2,

+TXACHPF_GAIN,

+TXACEQ_C0,

+TXACEQ_C1,

+TXACEQ_C2,

+TXACEQ_C3,

+TXACGAIN,

+RXACGAIN,

+RXACEQ_C0,

+RXACEQ_C1,

+RXACEQ_C2,

+RXACEQ_C3,

+RXACIIR_B0_1,

+RXACIIR_B1_1,

+RXACIIR_A1_1,

+RXACIIR_B0_2,

+RXACIIR_B1_2,

+RXACIIR_B2_2,

+RXACIIR_A1_2,

+RXACIIR_A2_2,

+RXACIIR_B0_3,

+RXACIIR_B1_3,

+RXACIIR_B2_3,

+RXACIIR_A1_3,

+RXACIIR_A2_3,

+ECFIR_C2,

+ECFIR_C3,

+ECFIR_C4,

+ECFIR_C5,

+ECFIR_C6,

+ECFIR_C7,

+ECFIR_C8,

+ECFIR_C9,

+ECIIR_B0,

+ECIIR_B1,

+ECIIR_A1,

+ECIIR_A2,

+DTMFDTF_B0_1,

+DTMFDTF_B1_1,

+DTMFDTF_B2_1,

+DTMFDTF_A1_1,

+DTMFDTF_A2_1,

+DTMFDTF_B0_2,

+DTMFDTF_B1_2,

+DTMFDTF_B2_2,

+DTMFDTF_A1_2,

+DTMFDTF_A2_2,

+DTMFDTF_B0_3,

+DTMFDTF_B1_3,

+DTMFDTF_B2_3,

+DTMFDTF_A1_3,

+DTMFDTF_A2_3,

+DTMFDTF_GAIN,

+DTMFLPF_B0_1,

+DTMFLPF_B1_1,

+DTMFLPF_B2_1,

+DTMFLPF_A1_1,

+DTMFLPF_A2_1,

+DTMFLPF_B0_2,

+DTMFLPF_B1_2,

+DTMFLPF_B2_2,

+DTMFLPF_A1_2,

+DTMFLPF_A2_2,

+DTMFLPF_GAIN,

+DTMFHPF_B0_1,

+DTMFHPF_B1_1,

+DTMFHPF_B2_1,

+DTMFHPF_A1_1,

+DTMFHPF_A2_1,

+DTMFHPF_B0_2,

+DTMFHPF_B1_2,

+DTMFHPF_B2_2,

+DTMFHPF_A1_2,

+DTMFHPF_A2_2,

+DTMFHPF_GAIN,

+POWER_GAIN,

+GOERTZEL_GAIN,

+MODEM_GAIN,

+HOTBIT1,

+HOTBIT0,

+ROW0_C1,

+ROW1_C1,

+ROW2_C1,

+ROW3_C1,

+COL0_C1,

+COL1_C1,

+COL2_C1,

+COL3_C1,

+ROW0_C2,

+ROW1_C2,

+ROW2_C2,

+ROW3_C2,

+COL0_C2,

+COL1_C2,

+COL2_C2,

+COL3_C2,

+SLOPE_VLIM,

+SLOPE_RFEED,

+SLOPE_ILIM,

+SLOPE_RING,

+SLOPE_DELTA1,

+SLOPE_DELTA2,

+V_VLIM,

+V_RFEED,

+V_ILIM,

+CONST_RFEED,

+CONST_ILIM,

+I_VLIM,

+DC_DAC_GAIN,

+VDIFF_TH,

+TXDEC_B0,

+TXDEC_B1,

+TXDEC_B2,

+TXDEC_A1,

+TXDEC_A2,

+ZSYNTH_B0,

+ZSYNTH_B1,

+ZSYNTH_B2,

+ZSYNTH_A1,

+ZSYNTH_A2,

+RXACHPF_B0_1,

+RXACHPF_B1_1,

+RXACHPF_A1_1,

+RXACHPF_B0_2,

+RXACHPF_B1_2,

+RXACHPF_B2_2,

+RXACHPF_A1_2,

+RXACHPF_A2_2,

+RXACHPF_GAIN,

+MASK7LSB,

+RXDEC_B0,

+RXDEC_B1,

+RXDEC_B2,

+RXDEC_A1,

+RXDEC_A2,

+OSCINT1_B0_1,

+OSCINT1_B1_1,

+OSCINT1_B2_1,

+OSCINT1_A1_1,

+OSCINT1_A2_1,

+OSCINT1_B0_2,

+OSCINT1_B1_2,

+OSCINT1_B2_2,

+OSCINT1_A1_2,

+OSCINT1_A2_2,

+OSCINT2_B0_1,

+OSCINT2_B1_1,

+OSCINT2_B2_1,

+OSCINT2_A1_1,

+OSCINT2_A2_1,

+OSCINT2_B0_2,

+OSCINT2_B1_2,

+OSCINT2_B2_2,

+OSCINT2_A1_2,

+OSCINT2_A2_2,

+UNUSED693,

+UNUSED694,

+UNUSED695,

+RING_LPF_B0,

+RING_LPF_B1,

+RING_LPF_B2,

+RING_LPF_A1,

+RING_LPF_A2,

+LCRDBI,

+LONGDBI,

+VBAT_TIMER,

+LF_SPEEDUP_TIMER,

+DC_SPEEDUP_TIMER,

+AC_SPEEDUP_TIMER,

+LCR_SPEEDUP_TIMER,

+CM_SPEEDUP_TIMER,

+VCM_TH,

+AC_SPEEDUP_TH,

+SPR_SIG_0,

+SPR_SIG_1,

+SPR_SIG_2,

+SPR_SIG_3,

+SPR_SIG_4,

+SPR_SIG_5,

+SPR_SIG_6,

+SPR_SIG_7,

+SPR_SIG_8,

+SPR_SIG_9,

+SPR_SIG_10,

+SPR_SIG_11,

+SPR_SIG_12,

+SPR_SIG_13,

+SPR_SIG_14,

+SPR_SIG_15,

+SPR_SIG_16,

+SPR_SIG_17,

+SPR_SIG_18,

+COUNTER_VTR_VAL,

+CONST_028,

+CONST_032,

+CONST_038,

+CONST_046,

+COUNTER_IRING_VAL,

+GAIN_RING,

+RING_HYST,

+COMP_Z,

+CONST_115,

+CONST_110,

+CONST_105,

+CONST_100,

+CONST_095,

+CONST_090,

+CONST_085,

+V_RASUM_IDEAL,

+CONST_ONE,

+VCM_OH,

+VCM_RING,

+VCM_HYST,

+VOV_GND,

+VOV_BAT,

+VOV_RING_BAT,

+CM_DBI,

+RTPER,

+P_TH_HVIC,

+P_TH_Q1256,

+P_TH_Q34,

+COEF_P_HVIC,

+COEF_Q1256,

+COEF_Q34,

+R_OFFLOAD,

+R_63,

+BAT_HYST,

+BAT_DBI,

+VBATL_EXPECT,

+VBATH_EXPECT,

+VBATR_EXPECT,

+BAT_SETTLE,

+VBAT_IRQ_TH,

+MADC_VTIPC_OS,

+MADC_VRINGC_OS,

+MADC_VBAT_OS,

+MADC_VLONG_OS,

+UNUSED775,

+MADC_VDC_OS,

+MADC_ILONG_OS,

+MADC_ISNS_STDBY_OS,

+MADC_ISNS_OS,

+MADC_ILOOP_OS,

+MADC_SCALE_ILOOP,

+UNUSED782,

+UNUSED783,

+DC_ADC_OS,

+CAL_UNITY,

+CAL_CMRR_N,

+CAL_CMRR_NINV,

+ACADC_OFFSET,

+ACDAC_OFFSET,

+CAL_DCDAC_CODE,

+CAL_DCDAC_15MA,

+CAL_LKG_TSETTLE,

+CAL_LKG_IREF100,

+CAL_LKG_LIM100UA,

+CAL_LKG_VREF25,

+CAL_LKG_VLSB_0_INV,

+CAL_LKG_RDCSNS_EFF,

+CAL_LKG_RDCOFF_EFF,

+CAL_LKG_CODE_OS,

+CAL_LKG_VMAX_THR,

+CAL_LB_TSQUELCH,

+CAL_LB_TCHARGE,

+CAL_LB_TSETTLE0,

+CAL_GOERTZEL_DLY,

+CAL_GOERTZEL_ALPHA,

+CAL_DECLPF_K,

+CAL_DECLPF_B1,

+CAL_DECLPF_B2,

+CAL_DECLPF_A1,

+CAL_DECLPF_A2,

+CAL_ACADC_THRL,

+CAL_ACADC_THRH,

+CAL_ACADC_TSETTLE,

+DTROW0TH,

+DTROW1TH,

+DTROW2TH,

+DTROW3TH,

+DTCOL0TH,

+DTCOL1TH,

+DTCOL2TH,

+DTCOL3TH,

+DTFTWTH,

+DTRTWTH,

+DTROWRTH,

+DTCOLRTH,

+DTROW2HTH,

+DTCOL2HTH,

+DTMINPTH,

+DTHOTTH,

+RXPWR,

+TXPWR,

+RXMODPWR,

+TXMODPWR,

+FSKFREQ0,

+FSKFREQ1,

+FSKAMP0,

+FSKAMP1,

+FSK01,

+FSK10,

+VOCDELTA,

+VOCLTH,

+VOCHTH,

+RINGOF,

+RINGFR,

+RINGAMP,

+RINGPHAS,

+RTDCTH,

+RTACTH,

+RTDCDB,

+RTACDB,

+RTCOUNT,

+LCROFFHK,

+LCRONHK,

+LCRMASK,

+LCRMASK_POLREV,

+LCRMASK_STATE,

+LCRMASK_LINECAP,

+LONGHITH,

+LONGLOTH,

+IRING_LIM,

+AC_PU_DELTA1,

+AC_PU_DELTA2,

+DIAG_LPF_8K,

+DIAG_LPF_128K,

+DIAG_INV_N,

+DIAG_GAIN,

+DIAG_G_CAL,

+DIAG_OS_CAL,

+SPR_GAIN_TRIM,

+MADC_VBAT_HYST,

+AC_DAC_GAIN,

+STDBY_THRLO,

+STDBY_THRHI,

+AC_DAC_GAIN0,

+EZSYNTH_B0,

+OFFLD_DAC_SCALE_LO,

+OFFLD_DAC_SCALE_HI,

+OFFLD_DAC_OS_LO,

+OFFLD_DAC_OS_HI,

+AC_ADC_GAIN,

+ILOOP1LPF,

+RING_FLUSH_TIMER,

+ALAW_BIAS,

+MADC_VTRC_SCALE,

+MADC_VBAT_SCALE0,

+MADC_VBAT_SCALE1,

+MADC_VLONG_SCALE,

+MADC_VLONG_SCALE_RING,

+UNUSED889,

+MADC_VDC_SCALE,

+MADC_ILONG_SCALE,

+MADC_ITR_SCALE,

+UNUSED893,

+VDIFF_SENSE_SCALE,

+VDIFF_SENSE_SCALE_RING,

+VOV_RING_GND,

+P_TH_OFFLOAD,

+CAL_LB_OSC1_FREQ,

+CAL_DCDAC_9TAU,

+CAL_MADC_9TAU,

+ADAP_RING_MIN_I,

+SWEEP_STEP,

+SWEEP_STEP_SAVE,

+SWEEP_REF,

+AMP_STEP,

+RXACGAIN_SAVE,

+AMP_RAMP_INIT,

+DIAG_HPF_GAIN,

+DIAG_HPF_8K,

+DIAG_ADJ_STEP,

+CAL_LKG_CODE_OS_COMP,

+CADC_SCALE,

+CADC_SCALE_INV,

+CADC_OS,

+PWRSAVE_TIMER,

+OFFHOOK_THRESH,

+SPEEDUP_MASK_TIMER,

+XTALK_TIMER,

+DCDC_VREF_MIN,

+DCDC_VREF_MIN_RNG,

+DCDC_FSW_NORM,

+DCDC_FSW_NORM_LO,

+DCDC_FSW_RING,

+DCDC_FSW_RING_LO,

+DCDC_DIN_LIM,

+DCDC_VOUT_LIM,

+DC_DAC_OS,

+UNUSED928,

+UNUSED929,

+UNUSED930,

+UNUSED931,

+UNUSED932,

+UNUSED933,

+UNUSED934,

+UNUSED935,

+UNUSED936,

+UNUSED937,

+UNUSED938,

+UNUSED939,

+UNUSED940,

+UNUSED941,

+UNUSED942,

+UNUSED943,

+UNUSED944,

+UNUSED945,

+UNUSED946,

+UNUSED947,

+UNUSED948,

+UNUSED949,

+UNUSED950,

+UNUSED951,

+UNUSED952,

+UNUSED953,

+UNUSED954,

+UNUSED955,

+UNUSED956,

+UNUSED957,

+UNUSED958,

+UNUSED959,

+UNUSED960,

+UNUSED961,

+UNUSED962,

+UNUSED963,

+UNUSED964,

+UNUSED965,

+UNUSED966,

+UNUSED967,

+UNUSED968,

+UNUSED969,

+UNUSED970,

+UNUSED971,

+UNUSED972,

+UNUSED973,

+UNUSED974,

+UNUSED975,

+UNUSED976,

+UNUSED977,

+UNUSED978,

+UNUSED979,

+UNUSED980,

+UNUSED981,

+UNUSED982,

+UNUSED983,

+UNUSED984,

+UNUSED985,

+UNUSED986,

+UNUSED987,

+UNUSED988,

+UNUSED989,

+UNUSED990,

+UNUSED991,

+UNUSED992,

+UNUSED993,

+UNUSED994,

+UNUSED995,

+UNUSED996,

+UNUSED997,

+UNUSED998,

+UNUSED999,

+UNUSED1000,

+UNUSED1001,

+UNUSED1002,

+UNUSED1003,

+UNUSED1004,

+UNUSED1005,

+UNUSED1006,

+UNUSED1007,

+UNUSED1008,

+UNUSED1009,

+UNUSED1010,

+UNUSED1011,

+UNUSED1012,

+UNUSED1013,

+UNUSED1014,

+UNUSED1015,

+UNUSED1016,

+UNUSED1017,

+UNUSED1018,

+UNUSED1019,

+UNUSED1020,

+UNUSED1021,

+UNUSED1022,

+UNUSED1023

+};

+

+enum {

+    PD_BIAS = 1413,

+    PD_VBAT_SNS = 1418,

+    MADC_LOOP_MAN = 1445,

+    HVIC_CNTL_MAN = 1451,

+    CAL_TRNRD_DACT = 1458,

+    CAL_TRNRD_DACR,

+    CMDAC_FWD = 1476,

+    CMDAC_REV,

+	RDC_SUM = 1499,

+    STBY_LEAKAGE_OS = 1537,

+    PD_DCDC = 1538,

+	DCDC_UVHYST = 1545,

+	DCDC_UVTHRESH,

+	DCDC_OVTHRESH = 1547,

+	DCDC_OITHRESH,

+	UNUSED1549,

+	DCDC_CCM_THRESH,

+	DCDC_STATUS,

+	DCDC_FSW,

+	DCDC_SWDRV_POL,

+	DCDC_UVPOL,

+	DCDC_SWFET,

+	UNUSED1556,

+	UNUSED1557,

+	DCDC_VREF_CTRL,

+	UNUSED1559,

+	DCDC_RNGTYPE,

+    PD_REF_OSC = 1571

+};

+

+#endif

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x.h
new file mode 100755
index 0000000..57f075f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x.h
@@ -0,0 +1,353 @@
+/*

+** Copyright (c) 2007 by Silicon Laboratories

+**

+** $Id: si3226x.h 458 2009-03-10 22:47:25Z cdp@SILABS.COM $

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+*/

+

+#ifndef SI3226XH_H

+#define SI3226XH_H

+

+#include "proslic.h"

+

+

+

+/*

+** SI3226X DataTypes/Function Definitions 

+*/

+

+#define NUMIRQ 4

+

+

+/*

+** Defines structure for configuring gpio

+*/

+typedef struct {

+	uInt8 outputEn;

+	uInt8 analog;

+	uInt8 direction;

+	uInt8 manual;

+	uInt8 polarity;

+	uInt8 openDrain;

+	uInt8 batselmap;

+} Si3226x_GPIO_Cfg;

+

+typedef ProSLIC_DCfeed_Cfg Si3226x_DCfeed_Cfg;

+typedef Si3226x_DCfeed_Cfg* Si3226x_DCfeed_Cfg_ptr;

+/*

+** Defines structure for general configuration and the dcdc converter

+*/

+typedef struct {

+    uInt8 device_key;    /* Used to prevent loaded coeffs for another device */

+    bomOptionsType bomOpt;

+    batRailType  batType;

+    ramData bat_hyst;

+    ramData vbatr_expect; /* default - this is overwritten by ring preset */

+    ramData vbath_expect;  /* default - this is overwritten by dc feed preset */

+    ramData pwrsave_timer;

+    ramData offhook_thresh; 

+    ramData vbat_track_min;

+    ramData vbat_track_min_rng;

+    ramData pwrsave_dbi;

+    ramData dcdc_ana_scale;

+    ramData vov_bat_pwrsave_min;

+    ramData vov_bat_pwrsave_min_rng;

+    ramData therm_dbi;

+    ramData cpump_dbi;

+    ramData dcdc_verr;

+    ramData dcdc_verr_hyst;

+    ramData dcdc_oithresh_lo;

+    ramData dcdc_oithresh_hi;

+    ramData pd_uvlo; 

+    ramData pd_ovlo;

+    ramData pd_oclo;

+    ramData pd_swdrv;

+    ramData dcdc_uvhyst; 

+    ramData dcdc_uvthresh; 

+    ramData dcdc_ovthresh; 

+    ramData dcdc_oithresh; 

+    ramData dcdc_swdrv_pol; 

+    ramData dcdc_uvpol;

+    ramData dcdc_vref_man;

+    ramData dcdc_vref_ctrl;

+    ramData dcdc_rngtype; 

+    ramData dcdc_ana_vref;

+    ramData dcdc_ana_gain; 

+    ramData dcdc_ana_toff; 

+    ramData dcdc_ana_tonmin; 

+    ramData dcdc_ana_tonmax; 

+    ramData dcdc_ana_dshift; 

+    ramData dcdc_ana_lpoly; 

+    ramData dcdc_aux_invert;

+    ramData dcdc_cpump_lp;

+    ramData dcdc_cpump_pulldown;

+    ramData dcdc_lift_en;

+    ramData coef_p_hvic;

+    ramData p_th_hvic;

+    uInt8 cm_clamp;

+    uInt8 autoRegister;

+    uInt8 irqen1;

+    uInt8 irqen2;

+    uInt8 irqen3;

+    uInt8 irqen4;

+    uInt8 enhance;

+    ramData scale_kaudio;

+    uInt8 zcal_en;

+    ramData lkg_ofhk_offset;

+    ramData lkg_lb_offset;

+    ramData vbath_delta;

+    ramData uvthresh_max;

+    ramData uvthresh_scale;

+    ramData uvthresh_bias;

+} Si3226x_General_Cfg;

+

+

+/*

+** Defines structure for configuring pcm

+*/

+typedef struct {

+    uInt8 pcmFormat;

+    uInt8 widebandEn;

+    uInt8 pcm_tri;

+    uInt8 tx_edge;

+    uInt8 alaw_inv;

+} Si3226x_PCM_Cfg;

+

+/*

+** Defines structure for configuring pulse metering

+*/

+typedef struct {

+	ramData pm_amp_thresh;

+	uInt8 pmFreq;

+	uInt8 pmRampRate;

+} Si3226x_PulseMeter_Cfg;

+/*

+** Defines structure for configuring FSK generation

+*/

+typedef struct {

+	ramData fsk01;

+	ramData fsk10;

+	ramData fskamp0;

+	ramData fskamp1;

+	ramData fskfreq0;

+	ramData fskfreq1;

+	uInt8 eightBit;

+	uInt8 fskdepth;

+} Si3226x_FSK_Cfg;

+

+/*

+** Defines structure for configuring dtmf decode

+*/

+typedef struct {

+	ramData dtmfdtf_b0_1;

+	ramData dtmfdtf_b1_1;

+	ramData dtmfdtf_b2_1;

+	ramData dtmfdtf_a1_1;

+	ramData dtmfdtf_a2_1;

+	ramData dtmfdtf_b0_2;

+	ramData dtmfdtf_b1_2;

+	ramData dtmfdtf_b2_2;

+	ramData dtmfdtf_a1_2;

+	ramData dtmfdtf_a2_2;

+	ramData dtmfdtf_b0_3;

+	ramData dtmfdtf_b1_3;

+	ramData dtmfdtf_b2_3;

+	ramData dtmfdtf_a1_3;

+	ramData dtmfdtf_a2_3;

+} Si3226x_DTMFDec_Cfg;

+

+/*

+** Defines structure for configuring impedence synthesis

+*/

+typedef struct {

+	ramData zsynth_b0;

+	ramData zsynth_b1;

+	ramData zsynth_b2;

+	ramData zsynth_a1;

+	ramData zsynth_a2;

+	uInt8 ra;

+} Si3226x_Zsynth_Cfg;

+

+/*

+** Defines structure for configuring hybrid

+*/

+typedef struct {

+	ramData ecfir_c2;

+	ramData ecfir_c3;

+	ramData ecfir_c4;

+	ramData ecfir_c5;

+	ramData ecfir_c6;

+	ramData ecfir_c7;

+	ramData ecfir_c8;

+	ramData ecfir_c9;

+	ramData ecfir_b0;

+	ramData ecfir_b1;

+	ramData ecfir_a1;

+	ramData ecfir_a2;

+} Si3226x_hybrid_Cfg;

+

+/*

+** Defines structure for configuring GCI CI bits

+*/

+typedef struct {

+	uInt8 gci_ci;

+} Si3226x_CI_Cfg;

+

+/*

+** Defines structure for configuring modem tone detect

+*/

+typedef struct {

+	ramData rxmodpwr;

+	ramData rxpwr;

+	ramData modem_gain;

+	ramData txmodpwr;

+	ramData txpwr;

+} Si3226x_modemDet_Cfg;

+

+/*

+** Defines structure for configuring audio eq

+*/

+

+typedef struct {

+	ramData txaceq_c0;

+	ramData txaceq_c1;

+	ramData txaceq_c2;

+	ramData txaceq_c3;

+

+	ramData rxaceq_c0;

+	ramData rxaceq_c1;

+	ramData rxaceq_c2;

+	ramData rxaceq_c3;

+} Si3226x_audioEQ_Cfg;

+

+

+

+/*

+** Defines structure for configuring audio gain

+*/

+

+typedef ProSLIC_audioGain_Cfg Si3226x_audioGain_Cfg;

+

+

+typedef struct {

+	Si3226x_audioEQ_Cfg audioEQ;

+	Si3226x_hybrid_Cfg hybrid;

+    Si3226x_Zsynth_Cfg zsynth;

+	ramData txgain;

+	ramData rxgain;

+	ramData rxachpf_b0_1;

+	ramData  rxachpf_b1_1;

+	ramData  rxachpf_a1_1;

+	int16 txgain_db; /*overall gain associated with this configuration*/

+	int16 rxgain_db;

+} Si3226x_Impedance_Cfg;

+

+

+

+/*

+** Defines structure for configuring tone generator

+*/

+typedef struct {

+	Oscillator_Cfg osc1;

+	Oscillator_Cfg osc2;

+	uInt8 omode;

+} Si3226x_Tone_Cfg; 

+

+/*

+** Defines structure for configuring ring generator

+*/

+typedef struct {

+	ramData rtper;

+	ramData freq;

+	ramData amp;

+	ramData phas;

+	ramData offset;

+	ramData slope_ring;

+    ramData iring_lim;

+    ramData rtacth;

+	ramData rtdcth;

+	ramData rtacdb;

+	ramData rtdcdb;

+	ramData vov_ring_bat;

+	ramData vov_ring_gnd;

+    ramData vbatr_expect;

+	uInt8 talo;

+	uInt8 tahi;

+	uInt8 tilo;

+	uInt8 tihi;

+	ramData adap_ring_min_i;

+    ramData counter_iring_val;

+	ramData counter_vtr_val;

+    ramData ar_const28;

+    ramData ar_const32;

+    ramData ar_const38;

+    ramData ar_const46;

+	ramData rrd_delay;

+	ramData rrd_delay2;

+    ramData vbat_track_min_rng;

+	uInt8 ringcon;

+    uInt8 userstat;

+	ramData vcm_ring;

+    ramData vcm_ring_fixed;

+    ramData delta_vcm;

+    ramData dcdc_rngtype;

+    ramData vov_dcdc_slope;

+    ramData vov_dcdc_os;

+    ramData vov_ring_bat_max;

+} Si3226x_Ring_Cfg;

+

+

+

+/*

+** This defines names for the interrupts in the ProSLIC

+*/

+typedef enum {

+/* IRQ1 */

+IRQ_OSC1_T1_SI3226X = 0,   

+IRQ_OSC1_T2_SI3226X,

+IRQ_OSC2_T1_SI3226X,

+IRQ_OSC2_T2_SI3226X,

+IRQ_RING_T1_SI3226X,

+IRQ_RING_T2_SI3226X,

+IRQ_FSKBUF_AVAIL_SI3226X,

+IRQ_VBAT_SI3226X,

+/* IRQ2 */

+IRQ_RING_TRIP_SI3226X = 8,

+IRQ_LOOP_STAT_SI3226X,

+IRQ_LONG_STAT_SI3226X,

+IRQ_VOC_TRACK_SI3226X,

+IRQ_DTMF_SI3226X,

+IRQ_INDIRECT_SI3226X,

+IRQ_TXMDM_SI3226X,

+IRQ_RXMDM_SI3226X,

+/* IRQ3 */

+IRQ_P_HVIC_SI3226X = 16,  

+IRQ_P_THERM_SI3226X,

+IRQ_PQ3_SI3226X,

+IRQ_PQ4_SI3226X,

+IRQ_PQ5_SI3226X,

+IRQ_PQ6_SI3226X,

+IRQ_DSP_SI3226X,

+IRQ_MADC_FS_SI3226X,

+/* IRQ4 */

+IRQ_USER_0_SI3226X = 24, 

+IRQ_USER_1_SI3226X,

+IRQ_USER_2_SI3226X,

+IRQ_USER_3_SI3226X,

+IRQ_USER_4_SI3226X,

+IRQ_USER_5_SI3226X,

+IRQ_USER_6_SI3226X,

+IRQ_USER_7_SI3226X

+}Si3226xProslicInt;

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x_intf.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x_intf.h
new file mode 100755
index 0000000..647da62
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x_intf.h
@@ -0,0 +1,1045 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: si3226x_intf.h 1028 2009-09-01 20:07:43Z cdp@SILABS.COM $

+**

+** Si3226x_Intf.h

+** Si3226x ProSLIC interface header file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file for the ProSLIC driver.

+**

+** Dependancies:

+** proslic_datatypes.h, Si3226x_registers.h, ProSLIC.h

+**

+*/

+#ifndef SI3226X_INTF_H

+#define SI3226X_INTF_H

+

+/*

+**

+** Si3226x General Constants

+**

+*/

+#define SI3226X_REVA                0

+#define SI3226X_REVB                1

+#define SI3226X_REVC                3    /* This is revC bug - shows revD revision code */

+#define DEVICE_KEY_MIN              0x64

+#define DEVICE_KEY_MAX              0x6D

+

+/*

+** Calibration Constants

+*/

+#define SI3226X_CAL_STD_CALR1               0xC0    /* FF */

+#define SI3226X_CAL_STD_CALR2               0x18    /* F8 */

+

+/* Timeouts in 10s of ms */

+#define SI3226X_TIMEOUT_DCDC_UP             200

+#define SI3226X_TIMEOUT_DCDC_DOWN           200

+

+/*

+**

+** PROSLIC INITIALIZATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_Reset

+**

+** Description: 

+** Resets the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_Reset (proslicChanType_ptr hProslic);

+

+/*

+** Function: PROSLIC_ShutdownChannel

+**

+** Description: 

+** Safely shutdown channel w/o interruption to 

+** other active channels

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_ShutdownChannel (proslicChanType_ptr hProslic);

+

+/*

+** Function: PROSLIC_Init_MultiBOM

+**

+** Description: 

+** Initializes the ProSLIC w/ selected general parameters

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** size:     number of channels

+** preset:   general configuration preset

+**

+** Return:

+** none

+*/

+int Si3226x_Init_MultiBOM (proslicChanType_ptr *hProslic,int size,int preset);

+

+/*

+** Function: PROSLIC_Init

+**

+** Description: 

+** Initializes the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_Init (proslicChanType_ptr *hProslic,int size);

+

+/*

+** Function: PROSLIC_Reinit

+**

+** Description: 

+** Soft reset and initialization

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_Reinit (proslicChanType_ptr hProslic,int size);

+

+/*

+** Function: PROSLIC_VerifyControlInterface

+**

+** Description: 

+** Verify SPI port read capabilities

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_VerifyControlInterface (proslicChanType_ptr hProslic);

+

+uInt8 Si3226x_ReadReg (proslicChanType_ptr hProslic,uInt8 addr);

+int Si3226x_WriteReg (proslicChanType_ptr hProslic,uInt8 addr,uInt8 data);

+ramData Si3226x_ReadRAM (proslicChanType_ptr hProslic,uInt16 addr);

+int Si3226x_WriteRAM (proslicChanType_ptr hProslic,uInt16 addr, ramData data);

+

+/*

+** Function: ProSLIC_PrintDebugData

+**

+** Description: 

+** Register and RAM dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_PrintDebugData (proslicChanType_ptr hProslic);

+

+/*

+** Function: ProSLIC_PrintDebugReg

+**

+** Description: 

+** Register dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_PrintDebugReg (proslicChanType_ptr hProslic);

+

+/*

+** Function: ProSLIC_PrintDebugRAM

+**

+** Description: 

+** RAM dump utility

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_PrintDebugRAM (proslicChanType_ptr hProslic);

+

+

+/*

+** Function: Si3226x_PowerUpConverter

+**

+** Description: 

+** Powers all DC/DC converters sequentially with delay to minimize

+** peak power draw on VDC.

+**

+** Returns:

+** int (error)

+**

+*/

+int Si3226x_PowerUpConverter(proslicChanType_ptr hProslic);

+

+/*

+** Function: Si3226x_PowerDownConverter

+**

+** Description: 

+** Power down DCDC converter (selected channel only)

+**

+** Returns:

+** int (error)

+**

+*/

+int Si3226x_PowerDownConverter(proslicChanType_ptr hProslic);

+

+/*

+** Function: Si3226x_Calibrate

+**

+** Description: 

+** Generic calibration function for Si3226x

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object,

+** size:     maximum number of channels

+** calr:     array of CALRx register values

+** maxTime:  cal timeout (in ms) 

+**

+** Return:

+** int 

+*/

+int Si3226x_Calibrate (proslicChanType_ptr *hProslic, int size, uInt8 *calr, int maxTime);

+

+/*

+** Function: PROSLIC_Cal

+**

+** Description: 

+** Calibrates the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si3226x_Cal (proslicChanType_ptr *hProslic, int size);

+

+/*

+** Function: PROSLIC_LoadRegTables

+**

+** Description: 

+** Loads registers and ram in the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pRamTable: pointer to ram values to load

+** pRegTable: pointer to register values to load

+** 

+**

+** Return:

+** none

+*/

+int Si3226x_LoadRegTables (proslicChanType_ptr *hProslic, ProslicRAMInit *pRamTable, ProslicRegInit *pRegTable,int size);

+

+/*

+** Function: PROSLIC_LoadPatch

+**

+** Description: 

+** Loads patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si3226x_LoadPatch (proslicChanType_ptr hProslic, const proslicPatch *pPatch);

+

+/*

+** Function: PROSLIC_VerifyPatch

+**

+** Description: 

+** Verifies patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si3226x_VerifyPatch (proslicChanType_ptr hProslic, const proslicPatch *pPatch);

+

+/*

+** Function: PROSLIC_EnableInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si3226x_EnableInterrupts (proslicChanType_ptr hProslic);

+int Si3226x_DisableInterrupts (proslicChanType_ptr hProslic);

+

+

+/*

+** Function: PROSLIC_SetLoopbackMode

+**

+** Description: 

+** Set loopback test mode

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si3226x_SetLoopbackMode (proslicChanType_ptr hProslic, ProslicLoopbackModes newMode);

+

+

+/*

+** Function: PROSLIC_SetMuteStatus

+**

+** Description: 

+** Set mute(s)

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si3226x_SetMuteStatus (proslicChanType_ptr hProslic, ProslicMuteModes muteEn);

+

+

+

+/*

+**

+** PROSLIC CONFIGURATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_RingSetup

+**

+** Description: 

+** configure ringing

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pRingSetup: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3226x_RingSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ToneGenSetup

+**

+** Description: 

+** configure tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pTone: pointer to tones config structure

+**

+** Return:

+** none

+*/

+int Si3226x_ToneGenSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_FSKSetup

+**

+** Description: 

+** configure fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pFsk: pointer to fsk config structure

+**

+** Return:

+** none

+*/

+int Si3226x_FSKSetup (proslicChanType *pProslic, int preset);

+

+/*

+ * Function: Si3226x_ModifyStartBits

+ * 

+ * Description: To change the FSK start/stop bits field.

+ * Returns RC_NONE if OK.

+ */

+

+int Si3226x_ModifyCIDStartBits(proslicChanType_ptr pProslic, uInt8 enable_startStop);

+

+/*

+** Function: PROSLIC_DTMFDecodeSetup

+**

+** Description: 

+** configure dtmf decode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDTMFDec: pointer to dtmf decoder config structure

+**

+** Return:

+** none

+*/

+int Si3226x_DTMFDecodeSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_SetProfile

+**

+** Description: 

+** set country profile of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCountryData: pointer to country config structure

+**

+** Return:

+** none

+*/

+int Si3226x_SetProfile (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ZsynthSetup

+**

+** Description: 

+** configure impedence synthesis

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pZynth: pointer to zsynth config structure

+**

+** Return:

+** none

+*/

+int Si3226x_ZsynthSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_GciCISetup

+**

+** Description: 

+** configure CI bits (GCI mode)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCI: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3226x_GciCISetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ModemDetSetup

+**

+** Description: 

+** configure modem detector

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pModemDet: pointer to modem det config structure

+**

+** Return:

+** none

+*/

+int Si3226x_ModemDetSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioGainSetup

+**

+** Description: 

+** configure audio gains

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudio: pointer to audio gains config structure

+**

+** Return:

+** none

+*/

+int Si3226x_TXAudioGainSetup (proslicChanType *pProslic, int preset);

+int Si3226x_RXAudioGainSetup (proslicChanType *pProslic, int preset);

+int Si3226x_AudioGainSetup (proslicChanType *pProslic,int32 rxgain,int32 txgain,int preset);

+

+/*

+** Function: PROSLIC_HybridSetup

+**

+** Description: 

+** configure Proslic hybrid

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHybridCfg: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3226x_HybridSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioEQSetup

+**

+** Description: 

+** configure audio equalizers

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudioEQ: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si3226x_AudioEQSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_DCFeedSetup

+**

+** Description: 

+** configure dc feed

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDcFeed: pointer to dc feed config structure

+**

+** Return:

+** none

+*/

+int Si3226x_DCFeedSetup (proslicChanType *pProslic,int preset);

+int Si3226x_DCFeedSetupCfg (proslicChanType *pProslic,ProSLIC_DCfeed_Cfg *cfg,int preset);

+

+/*

+** Function: PROSLIC_GPIOSetup

+**

+** Description: 

+** configure gpio

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpio: pointer to gpio config structure

+**

+** Return:

+** none

+*/

+int Si3226x_GPIOSetup (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PCMSetup

+**

+** Description: 

+** configure pcm

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPcm: pointer to pcm config structure

+**

+** Return:

+** none

+*/

+int Si3226x_PCMSetup (proslicChanType *pProslic, int preset);

+int Si3226x_PCMTimeSlotSetup (proslicChanType *pProslic, uInt16 rxcount, uInt16 txcount);

+

+/*

+**

+** PROSLIC CONTROL FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_GetInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** pIntData: pointer to interrupt info retrieved

+** 

+** Return:

+** 

+*/

+int Si3226x_GetInterrupts (proslicChanType_ptr hProslic, proslicIntType *pIntData);

+

+/*

+** Function: PROSLIC_ReadHookStatus

+**

+** Description: 

+** Determine hook status

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHookStat: current hook status

+**

+** Return:

+** none

+*/

+int Si3226x_ReadHookStatus (proslicChanType *pProslic,uInt8 *pHookStat);

+

+/*

+** Function: PROSLIC_WriteLinefeed

+**

+** Description: 

+** Sets linefeed state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** newLinefeed: new linefeed state

+**

+** Return:

+** none

+*/

+int Si3226x_SetLinefeedStatus (proslicChanType *pProslic,uInt8 newLinefeed);

+

+/*

+** Function: PROSLIC_SetLinefeedBroadcast

+**

+** Description: 

+** Sets linefeed state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** newLinefeed: new linefeed state

+**

+** Return:

+** none

+*/

+int Si3226x_SetLinefeedStatusBroadcast (proslicChanType *pProslic, uInt8 newLinefeed);

+

+/*

+** Function: PROSLIC_PolRev

+**

+** Description: 

+** Sets polarity reversal state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** abrupt: set this to 1 for abrupt pol rev

+** newPolRevState: new pol rev state

+**

+** Return:

+** none

+*/

+int Si3226x_PolRev (proslicChanType *pProslic,uInt8 abrupt, uInt8 newPolRevState);

+

+/*

+** Function: PROSLIC_GPIOControl

+**

+** Description: 

+** Sets gpio of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpioData: pointer to gpio status

+** read: set to 1 to read status, 0 to write

+**

+** Return:

+** none

+*/

+int Si3226x_GPIOControl (proslicChanType *pProslic,uInt8 *pGpioData, uInt8 read);

+

+/*

+** Function: PROSLIC_MWI

+**

+** Description: 

+** implements message waiting indicator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** lampOn: 0 = turn lamp off, 1 = turn lamp on

+**

+** Return:

+** none

+*/

+int Si3226x_MWI (proslicChanType *pProslic,uInt8 lampOn);

+

+/*

+** Function: PROSLIC_StartGenericTone

+**

+** Description: 

+** Initializes and start tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** timerEn: specifies whether to enable the tone generator timers

+**

+** Return:

+** none

+*/

+int Si3226x_ToneGenStart (proslicChanType *pProslic, uInt8 timerEn);

+

+

+/*

+** Function: PROSLIC_StopTone

+**

+** Description: 

+** Stops tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_ToneGenStop (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StartRing

+**

+** Description: 

+** Initializes and start ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_RingStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopRing

+**

+** Description: 

+** Stops ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_RingStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_EnableCID

+**

+** Description: 

+** enable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_EnableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DisableCID

+**

+** Description: 

+** disable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_DisableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_SendCID

+**

+** Description: 

+** send fsk data

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** buffer: buffer to send

+** numBytes: num of bytes in the buffer

+**

+** Return:

+** none

+*/

+int Si3226x_SendCID (proslicChanType *pProslic, uInt8 *buffer, uInt8 numBytes);

+

+int Si3226x_CheckCIDBuffer (proslicChanType *pProslic, uInt8 *fsk_buf_avail);

+

+/*

+** Function: PROSLIC_StartPCM

+**

+** Description: 

+** Starts PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_PCMStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopPCM

+**

+** Description: 

+** Disables PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_PCMStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DialPulseDetect

+**

+** Description: 

+** implements pulse dial detection and should be called at every off/on hook transistion

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPulsedialCfg: pointer to pulse dial config

+** pPulseDialData: pointer to pulse dial state for current channel

+**

+** Return:

+** none

+*/

+int Si3226x_DialPulseDetect (proslicChanType *pProslic, pulseDial_Cfg *pPulsedialCfg, pulseDialType *pPulseDialData);

+

+/*

+** Function: PROSLIC_ReadDTMFDigit

+**

+** Description: 

+** Read DTMF digit (would be called after DTMF interrupt to collect digit)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDigit: digit read

+**

+** Return:

+** none

+*/

+int Si3226x_DTMFReadDigit (proslicChanType *pProslic,uInt8 *pDigit);

+

+/*

+** Function: PROSLIC_PLLFreeRunStart

+**

+** Description: 

+** initiates pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_PLLFreeRunStart (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PLLFreeRunStop

+**

+** Description: 

+** exit pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_PLLFreeRunStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterSetup

+**

+** Description: 

+** configure pulse metering

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPulseCfg: pointer to pulse metering config structure

+**

+** Return:

+** none

+*/

+int Si3226x_PulseMeterSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_PulseMeterStart

+**

+** Description: 

+** start pulse meter tone

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_PulseMeterStart (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterStop

+**

+** Description: 

+** stop pulse meter tone

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si3226x_PulseMeterStop (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_LBCal

+**

+** Description: 

+** Execute longitudinal balance calibration

+**

+** Input Parameters: 

+** hProslic: pointer to array of Proslic objects

+** 

+** Return:

+** 

+*/

+int Si3226x_LBCal (proslicChanType_ptr *pProslic, int size);

+

+int Si3226x_GetLBCalResult (proslicChanType *pProslic,int32 *result1,int32 *result2,int32 *result3,int32 *result4);

+int Si3226x_GetLBCalResultPacked (proslicChanType *pProslic,int32 *result);

+int Si3226x_LoadPreviousLBCal (proslicChanType *pProslic,int32 result1,int32 result2,int32 result3,int32 result4);

+int Si3226x_LoadPreviousLBCalPacked (proslicChanType *pProslic,int32 *result);

+

+/*

+** Function: PROSLIC_dbgSetDCFeed

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3226x_dbgSetDCFeed (proslicChanType *pProslic, uInt32 v_vlim_val, uInt32 i_ilim_val, int32 preset);

+

+/*

+** Function: PROSLIC_dbgSetDCFeedVopen

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3226x_dbgSetDCFeedVopen (proslicChanType *pProslic, uInt32 v_vlim_val, int32 preset);

+

+

+/*

+** Function: PROSLIC_dbgSetDCFeedIloop

+**

+** Description: 

+** provisionary function for setting up

+** dcfeed given desired open circuit voltage 

+** and loop current.

+*/

+int Si3226x_dbgSetDCFeedIloop (proslicChanType *pProslic, uInt32 i_ilim_val, int32 preset);

+

+

+/*

+** Function: PROSLIC_dbgRingingSetup

+**

+** Description: 

+** Provisionary function for setting up

+** Ring type, frequency, amplitude and dc offset.

+** Main use will be by peek/poke applications.

+*/

+int Si3226x_dbgSetRinging (proslicChanType *pProslic, ProSLIC_dbgRingCfg *ringCfg, int preset);

+

+/*

+** Function: PROSLIC_dbgSetRXGain

+**

+** Description: 

+** Provisionary function for setting up

+** RX path gain.

+*/

+int Si3226x_dbgSetRXGain (proslicChanType *pProslic, int32 gain, int impedance_preset, int audio_gain_preset);

+

+/*

+** Function: PROSLIC_dbgSetTXGain

+**

+** Description: 

+** Provisionary function for setting up

+** TX path gain.

+*/

+int Si3226x_dbgSetTXGain (proslicChanType *pProslic, int32 gain, int impedance_preset, int audio_gain_preset);

+

+

+/*

+** Function: PROSLIC_LineMonitor

+**

+** Description: 

+** Monitor line voltages and currents

+*/

+int Si3226x_LineMonitor(proslicChanType *pProslic, proslicMonitorType *monitor);

+

+

+/*

+** Function: PROSLIC_PSTNCheck

+**

+** Description: 

+** Continuous monitor of ilong to detect hot pstn line 

+*/

+int Si3226x_PSTNCheck(proslicChanType *pProslic, proslicPSTNCheckObjType *pstnCheckObj);

+

+/*

+** Function: PROSLIC_DiffPSTNCheck

+**

+** Description: 

+** Detection of foreign PSTN 

+*/

+int Si3226x_DiffPSTNCheck (proslicChanType *pProslic, proslicDiffPSTNCheckObjType *pPSTNCheck);

+

+/*

+** Function: PROSLIC_SetPowersaveMode

+**

+** Description: 

+** Enable or Disable powersave mode 

+*/

+int Si3226x_SetPowersaveMode(proslicChanType *pProslic, int pwrsave);

+

+/*

+** Function: PROSLIC_ReadMADCScaled

+**

+** Description: 

+** ReadMADC (or other sensed voltage/currents) and

+** return scaled value in int32 format 

+*/

+int32 Si3226x_ReadMADCScaled(proslicChanType *pProslic, uInt16 addr, int32 scale);

+

+

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x_registers.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x_registers.h
new file mode 100755
index 0000000..4191f76
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si3226x_registers.h
@@ -0,0 +1,1259 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: si3226_registers.h 515 2009-03-20 15:22:33Z cdp@SILABS.COM $

+**

+** Si3226_Registers.h

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file that contains

+** register and RAM names definitions for 

+** the Si3226 ProSLIC.

+**

+** Dependancies:

+** 

+**

+*/

+#ifndef SI3226REGS_H

+#define SI3226REGS_H

+

+/*

+** This defines the neumomics for the SI3226 registers

+*/

+enum REGISTERS {

+ID  =  0,

+RESET  =  1,

+MSTREN  =  2,

+MSTRSTAT  =  3,

+RAMSTAT  =  4,

+RAM_ADDR_HI  =  5,

+RAM_DATA_B0  =  6,

+RAM_DATA_B1  =  7,

+RAM_DATA_B2  =  8,

+RAM_DATA_B3  =  9,

+RAM_ADDR_LO  =  10,

+PCMMODE  =  11,

+PCMTXLO  =  12,

+PCMTXHI  =  13,

+PCMRXLO  =  14,

+PCMRXHI  =  15,

+IRQ  =  16,

+IRQ0  =  17,

+IRQ1  =  18,

+IRQ2  =  19,

+IRQ3  =  20,

+IRQ4  =  21,

+IRQEN1  =  22,

+IRQEN2  =  23,

+IRQEN3  =  24,

+IRQEN4  =  25,

+CALR0  =  26,

+CALR1  =  27,

+CALR2  =  28,

+CALR3  =  29,

+LINEFEED  =  30,

+POLREV  =  31,

+SPEEDUP_DIS  =  32,

+SPEEDUP  =  33,

+LCRRTP  =  34,

+OFFLOAD  =  35,

+BATSELMAP  =  36,

+BATSEL  =  37,

+RINGCON  =  38,

+RINGTALO  =  39,

+RINGTAHI  =  40,

+RINGTILO  =  41,

+RINGTIHI  =  42,

+LOOPBACK  =  43,

+DIGCON  =  44,

+RA  =  45,

+ZCAL_EN  =  46,

+ENHANCE  =  47,

+OMODE  =  48,

+OCON  =  49,

+O1TALO  =  50,

+O1TAHI  =  51,

+O1TILO  =  52,

+O1TIHI  =  53,

+O2TALO  =  54,

+O2TAHI  =  55,

+O2TILO  =  56,

+O2TIHI  =  57,

+FSKDAT  =  58,

+FSKDEPTH  =  59,

+TONDTMF  =  60,

+TONDET  =  61,

+TONEN  =  62,

+GCI_CI  =  63,

+GLOBSTAT1  =  64,

+GLOBSTAT2  =  65,

+USERSTAT  =  66,

+GPIO  =  67,

+GPIO_CFG1  =  68,

+GPIO_CFG2  =  69,

+GPIO_CFG3  =  70,

+DIAG1  =  71,

+DIAG2  =  72,

+CM_CLAMP  =  73,

+DIAG3  =  74,

+PMCON  =  75,

+PCLK_FAULT_CNTL  =  76,

+REG77  =  77,

+REG78  =  78,

+REG79  =  79,

+AUTO  =  80,

+JMPEN  =  81,

+JMP0LO  =  82,

+JMP0HI  =  83,

+JMP1LO  =  84,

+JMP1HI  =  85,

+JMP2LO  =  86,

+JMP2HI  =  87,

+JMP3LO  =  88,

+JMP3HI  =  89,

+JMP4LO  =  90,

+JMP4HI  =  91,

+JMP5LO  =  92,

+JMP5HI  =  93,

+JMP6LO  =  94,

+JMP6HI  =  95,

+JMP7LO  =  96,

+JMP7HI  =  97,

+PDN  =  98,

+PDN_STAT  =  99,

+USERMODE_ENABLE = 126

+};

+

+

+/*

+** This defines the neumomics for the SI3226 RAM locations (revB)

+*/

+enum SRAM {

+IRNGNG_SENSE  =  0,

+MADC_VTIPC  =  1,

+MADC_VRINGC  =  2,

+MADC_VBAT  =  3,

+MADC_VLONG  =  4,

+UNUSED5  =  5,

+MADC_VDC  =  6,

+MADC_ILONG  =  7,

+MADC_ITIP  =  8,

+MADC_IRING  =  9,

+MADC_ILOOP  =  10,

+VDIFF_SENSE  =  11,

+VTIP  =  12,

+VRING  =  13,

+P_Q1_D  =  14,

+P_Q2_D  =  15,

+P_Q3_D  =  16,

+P_Q4_D  =  17,

+P_Q5_D  =  18,

+P_Q6_D  =  19,

+P_Q1  =  20,

+DIAG_EX1  =  21,

+DIAG_EX2  =  22,

+DIAG_LPF_MADC  =  23,

+DIAG_DMM_I  =  24,

+DIAG_DMM_V  =  25,

+OSC1FREQ  =  26,

+OSC1AMP  =  27,

+OSC1PHAS  =  28,

+OSC2FREQ  =  29,

+OSC2AMP  =  30,

+OSC2PHAS  =  31,

+TESTB0_1  =  32,

+TESTB1_1  =  33,

+TESTB2_1  =  34,

+TESTA1_1  =  35,

+TESTA2_1  =  36,

+TESTB0_2  =  37,

+TESTB1_2  =  38,

+TESTB2_2  =  39,

+TESTA1_2  =  40,

+TESTA2_2  =  41,

+TESTB0_3  =  42,

+TESTB1_3  =  43,

+TESTB2_3  =  44,

+TESTA1_3  =  45,

+TESTA2_3  =  46,

+TESTPKO  =  47,

+TESTAVO  =  48,

+TESTWLN  =  49,

+TESTAVBW  =  50,

+TESTPKFL  =  51,

+TESTAVFL  =  52,

+TESTPKTH  =  53,

+TESTAVTH  =  54,

+DAC_IN_SYNC1  =  55,

+BYPASS_REG  =  56,

+LCRMASK_CNT  =  57,

+DAC_IN_SYNC  =  58,

+TEMP  =  59,

+TEMP_ISR  =  60,

+P_Q2  =  61,

+P_Q3  =  62,

+P_Q4  =  63,

+P_Q5  =  64,

+P_Q6  =  65,

+ILOOP_FILT  =  66,

+ILONG_FILT  =  67,

+VBAT_FILT  =  68,

+VDIFF_FILT  =  69,

+VCM_FILT  =  70,

+VBAT_CNT  =  71,

+V_VLIM_SCALED  =  72,

+V_VLIM_TRACK  =  73,

+V_VLIM_MODFEED  =  74,

+DIAG_P_OUT  =  75,

+DIAG_COUNT  =  76,

+ROW0_MAG  =  77,

+ROW1_MAG  =  78,

+ROW2_MAG  =  79,

+ROW3_MAG  =  80,

+COL0_MAG  =  81,

+COL1_MAG  =  82,

+COL2_MAG  =  83,

+COL3_MAG  =  84,

+ROW0_2ND_Y1  =  85,

+ROW1_2ND_Y1  =  86,

+ROW2_2ND_Y1  =  87,

+ROW3_2ND_Y1  =  88,

+COL0_2ND_Y1  =  89,

+COL1_2ND_Y1  =  90,

+COL2_2ND_Y1  =  91,

+COL3_2ND_Y1  =  92,

+ROW0_2ND_Y2  =  93,

+ROW1_2ND_Y2  =  94,

+ROW2_2ND_Y2  =  95,

+ROW3_2ND_Y2  =  96,

+COL0_2ND_Y2  =  97,

+COL1_2ND_Y2  =  98,

+COL2_2ND_Y2  =  99,

+COL3_2ND_Y2  =  100,

+DTMF_IN  =  101,

+DTMFDTF_D2_1  =  102,

+DTMFDTF_D1_1  =  103,

+DTMFDTF_OUT_1  =  104,

+DTMFDTF_D2_2  =  105,

+DTMFDTF_D1_2  =  106,

+DTMFDTF_OUT_2  =  107,

+DTMFDTF_D2_3  =  108,

+DTMFDTF_D1_3  =  109,

+DTMFDTF_OUT_3  =  110,

+DTMFDTF_OUT  =  111,

+DTMFLPF_D2_1  =  112,

+DTMFLPF_D1_1  =  113,

+DTMFLPF_OUT_1  =  114,

+DTMFLPF_D2_2  =  115,

+DTMFLPF_D1_2  =  116,

+DTMFLPF_OUT_2  =  117,

+DTMF_ROW  =  118,

+DTMFHPF_D2_1  =  119,

+DTMFHPF_D1_1  =  120,

+DTMFHPF_OUT_1  =  121,

+DTMFHPF_D2_2  =  122,

+DTMFHPF_D1_2  =  123,

+DTMFHPF_OUT_2  =  124,

+DTMF_COL  =  125,

+ROW_POWER  =  126,

+COL_POWER  =  127,

+GP_TIMER  =  128,

+SPR_INTERP_DIF  =  129,

+SPR_INTERP_DIF_OUT  =  130,

+SPR_INTERP_INT  =  131,

+SPR_CNT  =  132,

+ROW0_Y1  =  133,

+ROW0_Y2  =  134,

+ROW1_Y1  =  135,

+ROW1_Y2  =  136,

+ROW2_Y1  =  137,

+ROW2_Y2  =  138,

+ROW3_Y1  =  139,

+ROW3_Y2  =  140,

+COL0_Y1  =  141,

+COL0_Y2  =  142,

+COL1_Y1  =  143,

+COL1_Y2  =  144,

+COL2_Y1  =  145,

+COL2_Y2  =  146,

+COL3_Y1  =  147,

+COL3_Y2  =  148,

+ROWMAX_MAG  =  149,

+COLMAX_MAG  =  150,

+ROW0_2ND_MAG  =  151,

+COL0_2ND_MAG  =  152,

+ROW_THR  =  153,

+COL_THR  =  154,

+OSC1_Y  =  155,

+OSC2_Y  =  156,

+OSC1_X  =  157,

+OSC1_COEFF  =  158,

+OSC2_X  =  159,

+OSC2_COEFF  =  160,

+RXACIIR_D2_1  =  161,

+RXACIIR_OUT_1  =  162,

+RXACIIR_D2_2  =  163,

+RXACIIR_D1_2  =  164,

+RXACIIR_OUT_2  =  165,

+RXACIIR_D2_3  =  166,

+RXACIIR_D1_3  =  167,

+RXACIIR_OUT  =  168,

+RXACIIR_OUT_3  =  169,

+TXACCOMB_D1  =  170,

+TXACCOMB_D2  =  171,

+TXACCOMB_D3  =  172,

+TXACSINC_OUT  =  173,

+TXACHPF_D1_2  =  174,

+TXACHPF_D2_1  =  175,

+TXACHPF_D2_2  =  176,

+TXACHPF_OUT  =  177,

+TXACHPF_OUT_1  =  178,

+TXACHPF_OUT_2  =  179,

+TXACIIR_D2_1  =  180,

+TXACIIR_OUT_1  =  181,

+TXACIIR_D2_2  =  182,

+TXACIIR_D1_2  =  183,

+TXACIIR_OUT_2  =  184,

+TXACIIR_D2_3  =  185,

+TXACIIR_D1_3  =  186,

+TXACIIR_OUT_3  =  187,

+TXACIIR_OUT  =  188,

+ECIIR_D1  =  189,

+ECIIR_D2  =  190,

+EC_DELAY1  =  191,

+EC_DELAY2  =  192,

+EC_DELAY3  =  193,

+EC_DELAY4  =  194,

+EC_DELAY5  =  195,

+EC_DELAY6  =  196,

+EC_DELAY7  =  197,

+EC_DELAY8  =  198,

+EC_DELAY9  =  199,

+EC_DELAY10  =  200,

+EC_DELAY11  =  201,

+ECHO_EST  =  202,

+EC_OUT  =  203,

+TESTFILT_OUT_1  =  204,

+TESTFILT_D1_1  =  205,

+TESTFILT_D2_1  =  206,

+TESTFILT_OUT_2  =  207,

+TESTFILT_D1_2  =  208,

+TESTFILT_D2_2  =  209,

+TESTFILT_OUT_3  =  210,

+TESTFILT_D1_3  =  211,

+TESTFILT_D2_3  =  212,

+TESTFILT_PEAK  =  213,

+TESTFILT_ABS  =  214,

+TESTFILT_MEANACC  =  215,

+TESTFILT_COUNT  =  216,

+TESTFILT_NO_OFFSET  =  217,

+RING_X  =  218,

+RING_Y  =  219,

+RING_INT  =  220,

+RING_Y_D1  =  221,

+RING_DIFF  =  222,

+RING_DELTA  =  223,

+WTCHDOG_CNT  =  224,

+RING_WAVE  =  225,

+UNUSED226  =  226,

+ONEKHZ_COUNT  =  227,

+TX2100_Y1  =  228,

+TX2100_Y2  =  229,

+TX2100_MAG  =  230,

+RX2100_Y1  =  231,

+RX2100_Y2  =  232,

+RX2100_MAG  =  233,

+TX2100_POWER  =  234,

+RX2100_POWER  =  235,

+TX2100_IN  =  236,

+RX2100_IN  =  237,

+RINGTRIP_COUNT  =  238,

+RINGTRIP_DC1  =  239,

+RINGTRIP_DC2  =  240,

+RINGTRIP_AC1  =  241,

+RINGTRIP_AC2  =  242,

+RINGTRIP_AC_COUNT  =  243,

+RINGTRIP_DC_COUNT  =  244,

+RINGTRIP_AC_RESULT  =  245,

+RINGTRIP_DC_RESULT  =  246,

+RINGTRIP_ABS  =  247,

+TXACEQ_OUT  =  248,

+LCR_DBI_CNT  =  249,

+BAT_DBI_CNT  =  250,

+LONG_DBI_CNT  =  251,

+TXACEQ_DELAY3  =  252,

+TXACEQ_DELAY2  =  253,

+TXACEQ_DELAY1  =  254,

+RXACEQ_DELAY3  =  255,

+RXACEQ_DELAY2  =  256,

+RXACEQ_DELAY1  =  257,

+RXACEQ_IN  =  258,

+TXDCCOMB_D1  =  259,

+TXDCCOMB_D2  =  260,

+TXDCSINC_OUT  =  261,

+RXACDIFF_D1  =  262,

+DC_NOTCH_1  =  263,

+DC_NOTCH_2  =  264,

+DC_NOTCH_OUT  =  265,

+DC_NOTCH_SCALED  =  266,

+V_FEED_IN  =  267,

+I_TAR  =  268,

+CONST_VLIM  =  269,

+UNITY  =  270,

+TXACNOTCH_1  =  271,

+TXACNOTCH_2  =  272,

+TXACNOTCH_OUT  =  273,

+ZSYNTH_1  =  274,

+ZSYNTH_2  =  275,

+ZSYNTH_OUT_1  =  276,

+TXACD2_1_0  =  277,

+TXACD2_1_1  =  278,

+TXACD2_1_2  =  279,

+TXACD2_1_3  =  280,

+TXACD2_1_4  =  281,

+TXACD2_1_5  =  282,

+TXACD2_1_OUT  =  283,

+TXACD2_2_0  =  284,

+TXACD2_2_1  =  285,

+TXACD2_2_2  =  286,

+TXACD2_2_3  =  287,

+TXACD2_2_4  =  288,

+TXACD2_2_5  =  289,

+TXACD2_2_OUT  =  290,

+TXACD2_3_0  =  291,

+TXACD2_3_1  =  292,

+TXACD2_3_2  =  293,

+TXACD2_3_3  =  294,

+TXACD2_3_4  =  295,

+TXACD2_3_5  =  296,

+TXACD2_3_OUT  =  297,

+RXACI2_1_1  =  298,

+RXACI2_1_2  =  299,

+RXACI2_1_3  =  300,

+RXACI2_1_4  =  301,

+RXACI2_1_OUT  =  302,

+RXACI2_2_1  =  303,

+RXACI2_2_2  =  304,

+RXACI2_2_3  =  305,

+RXACI2_2_4  =  306,

+RXACI2_2_OUT  =  307,

+RXACI2_3_1  =  308,

+RXACI2_3_2  =  309,

+RXACI2_3_3  =  310,

+RXACI2_3_4  =  311,

+RXACI2_3_OUT  =  312,

+TXACCOMP1  =  313,

+TXACCOMP_OUT  =  314,

+RXACCOMP1  =  315,

+RXACCOMP_OUT  =  316,

+RXACHPF_D1_2  =  317,

+RXACHPF_D2_1  =  318,

+RXACHPF_D2_2  =  319,

+RXACHPF_OUT  =  320,

+RXACHPF_OUT_1  =  321,

+RXACHPF_OUT_2  =  322,

+RXACEQ_OUT  =  323,

+METER_I_1  =  324,

+METER_I_OUT  =  325,

+METER_LPF_1  =  326,

+METER_LPF_2  =  327,

+METER_LPF_OUT_1  =  328,

+METER_BP_1  =  329,

+METER_BP_2  =  330,

+METER_BP_OUT  =  331,

+METER_SRC_OUT  =  332,

+UNUSED333  =  333,

+UNUSED334  =  334,

+RING_LPF_1  =  335,

+RING_LPF_2  =  336,

+RING_LPF_OUT  =  337,

+RING_INTERP_DIFF  =  338,

+RING_INTERP_DIFF_OUT  =  339,

+RING_INTERP_INT  =  340,

+RING_INTERP_INT_OUT  =  341,

+V_ILIM_TRACK  =  342,

+V_RFEED_TRACK  =  343,

+LF_SPEEDUP_CNT  =  344,

+DC_SPEEDUP_CNT  =  345,

+AC_SPEEDUP_CNT  =  346,

+LCR_SPEEDUP_CNT  =  347,

+CM_SPEEDUP_CNT  =  348,

+DC_SPEEDUP_MASK  =  349,

+ZSYNTH_IN  =  350,

+I_TAR_SAVE  =  351,

+UNUSED352  =  352,

+UNUSED353  =  353,

+COUNTER_VTR  =  354,

+I_RING_AVG  =  355,

+COUNTER_IRING  =  356,

+COMP_RATIO  =  357,

+MADC_VBAT_DIV2  =  358,

+VDIFF_PK_T  =  359,

+PEAK_CNT  =  360,

+CM_DBI_CNT  =  361,

+VCM_LAST  =  362,

+VBATL_SENSE  =  363,

+VBATH_SENSE  =  364,

+VBATR_SENSE  =  365,

+BAT_SETTLE_CNT  =  366,

+VBAT_TGT  =  367,

+VBAT_REQ  =  368,

+VCM_HIRES  =  369,

+VCM_LORES  =  370,

+ILOOP1  =  371,

+ILONG2  =  372,

+ITIP1  =  373,

+IRING1  =  374,

+CAL_TEMP1  =  375,

+CAL_TEMP2  =  376,

+CAL_TEMP3  =  377,

+CAL_TEMP4  =  378,

+CAL_TEMP5  =  379,

+CAL_TEMP6  =  380,

+CAL_TEMP7  =  381,

+CMRR_DIVISOR  =  382,

+CMRR_REMAINDER  =  383,

+CMRR_Q_PTR  =  384,

+I_SOURCE1  =  385,

+I_SOURCE2  =  386,

+VTR1  =  387,

+VTR2 =  388,

+STOP_TIMER1  =  389,

+STOP_TIMER2  =  390,

+UNUSED391  =  391,

+UNUSED392  =  392,

+CAL_ONHK_Z  =  393,

+CAL_LB_SETTLE  =  394,

+CAL_DECLPF_V0  =  395,

+CAL_DECLPF_V1  =  396,

+CAL_DECLPF_V2  =  397,

+CAL_GOERTZEL_V0  =  398,

+CAL_GOERTZEL_V1  =  399,

+CAL_DECLPF_Y  =  400,

+CAL_GOERTZEL_Y  =  401,

+P_HVIC  =  402,

+VBATL_MIRROR  =  403,

+VBATH_MIRROR  =  404,

+VBATR_MIRROR  =  405,

+DIAG_EX1_OUT  =  406,

+DIAG_EX2_OUT  =  407,

+DIAG_DMM_V_OUT  =  408,

+DIAG_DMM_I_OUT  =  409,

+DIAG_P  =  410,

+DIAG_LPF_V  =  411,

+DIAG_LPF_I  =  412,

+DIAG_TONE_FLAG  =  413,

+ILOOP1_LAST  =  414,

+RING_ENTRY_VOC  =  415,

+UNUSED416  =  416,

+OSC1_X_SAVE  =  417,

+EZSYNTH_1  =  418,

+EZSYNTH_2  =  419,

+ZSYNTH_OUT  =  420,

+UNUSED421  =  421,

+CAL_SUBSTATE  =  422,

+DIAG_EX1_DC_OUT  =  423,

+DIAG_EX1_DC  =  424,

+EZSYNTH_B1  =  425,

+EZSYNTH_B2  =  426,

+EZSYNTH_A1  =  427,

+EZSYNTH_A2  =  428,

+ILOOP1_FILT  =  429,

+AC_PU_DELTA1_CNT  =  430,

+AC_PU_DELTA2_CNT  =  431,

+UNUSED432  =  432,

+UNUSED433  =  433,

+UNUSED434  =  434,

+AC_DAC_GAIN_SAVE  =  435,

+RING_FLUSH_CNT  =  436,

+UNUSED437  =  437,

+DIAG_VAR_OUT  =  438,

+I_VBAT  =  439,

+P_OFFLOAD  =  440,

+CALTMP_LOOPCNT  =  441,

+CALTMP_LOOPINC  =  442,

+UNUSED443  =  443,

+CALTMP_CODEINC  =  444,

+CALTMP_TAUINC  =  445,

+CALTMP_TAU  =  446,

+CAL_TEMP8  =  447,

+PATCH_ID  =  448,

+UNUSED449  =  449,

+UNUSED450  =  450,

+UNUSED451  =  451,

+CAL_LB_OFFSET_FWD  =  452,

+CAL_LB_OFFSET_RVS  =  453,

+COUNT_SPEEDUP  =  454,

+SWEEP_COUNT  =  455,

+AMP_RAMP  =  456,

+DIAG_LPF_MADC_D  =  457,

+DIAG_HPF_MADC  =  458,

+UNUSED459  =  459,

+TXDEC_OUT  =  460,

+TXDEC_D1  =  461,

+TXDEC_D2  =  462,

+RXDEC_D1  =  463,

+RXDEC_D2  =  464,

+OSCINT1_D2_1  =  465,

+OSCINT1_D1_1  =  466,

+OSCINT1_OUT_1  =  467,

+OSCINT1_D2_2  =  468,

+OSCINT1_D1_2  =  469,

+OSCINT1_OUT  =  470,

+OSCINT2_D2_1  =  471,

+OSCINT2_D1_1  =  472,

+OSCINT2_OUT_1  =  473,

+OSCINT2_D2_2  =  474,

+OSCINT2_D1_2  =  475,

+OSCINT2_OUT  =  476,

+OSC1_Y_SAVE  =  477,

+OSC2_Y_SAVE  =  478,

+PWRSAVE_CNT  =  479,

+VBATR_PK  =  480,

+SPEEDUP_MASK_CNT  =  481,

+VCM_RING_FIXED  =  482,

+DELTA_VCM  =  483,

+MADC_VTIPC_DIAG_OS  =  484,

+MADC_VRINGC_DIAG_OS  =  485,

+MADC_VLONG_DIAG_OS  =  486,

+INIT_GUESS  =  487,

+Y1  =  488,

+Y2  =  489,

+Y3  =  490,

+UNUSED491  =  491,

+PWRSAVE_DBI_CNT  =  492,

+COMP_RATIO_SAVE  =  493,

+CAL_TEMP9  =  494,

+CAL_TEMP10  =  495,

+DAC_OFFSET_TEMP =  496,

+CAL_DAC_CODE  =  497,

+DCDAC_OFFSET  =  498,

+VDIFF_COARSE  =  499,

+RXACIIR_OUT_4  =  500,

+CAL_TEMP11  =  501,

+METER_RAMP =  502,

+METER_RAMP_DIR  =  503,

+METER_ON_T  =  504,

+METER_PK_DET  =  505,

+METER_PK_DET_T =  506,

+THERM_CNT  =  507,

+VDIFF_SENSE_DELAY  =  508,

+UNUSED509 =  509,

+CPUMP_DEB_CNT  =  510,

+UNUSED511  =  511,

+MINUS_ONE  =  512,

+ILOOPLPF  =  513,

+ILONGLPF  =  514,

+BATLPF  =  515,

+VDIFFLPF  =  516,

+VCMLPF  =  517,

+TXACIIR_B0_1  =  518,

+TXACIIR_B1_1  =  519,

+TXACIIR_A1_1  =  520,

+TXACIIR_B0_2  =  521,

+TXACIIR_B1_2  =  522,

+TXACIIR_B2_2  =  523,

+TXACIIR_A1_2  =  524,

+TXACIIR_A2_2  =  525,

+TXACIIR_B0_3  =  526,

+TXACIIR_B1_3  =  527,

+TXACIIR_B2_3  =  528,

+TXACIIR_A1_3  =  529,

+TXACIIR_A2_3  =  530,

+TXACHPF_B0_1  =  531,

+TXACHPF_B1_1  =  532,

+TXACHPF_A1_1  =  533,

+TXACHPF_B0_2  =  534,

+TXACHPF_B1_2  =  535,

+TXACHPF_B2_2  =  536,

+TXACHPF_A1_2  =  537,

+TXACHPF_A2_2  =  538,

+TXACHPF_GAIN  =  539,

+TXACEQ_C0  =  540,

+TXACEQ_C1  =  541,

+TXACEQ_C2  =  542,

+TXACEQ_C3  =  543,

+TXACGAIN  =  544,

+RXACGAIN  =  545,

+RXACEQ_C0  =  546,

+RXACEQ_C1  =  547,

+RXACEQ_C2  =  548,

+RXACEQ_C3  =  549,

+RXACIIR_B0_1  =  550,

+RXACIIR_B1_1  =  551,

+RXACIIR_A1_1  =  552,

+RXACIIR_B0_2  =  553,

+RXACIIR_B1_2  =  554,

+RXACIIR_B2_2  =  555,

+RXACIIR_A1_2  =  556,

+RXACIIR_A2_2  =  557,

+RXACIIR_B0_3  =  558,

+RXACIIR_B1_3  =  559,

+RXACIIR_B2_3  =  560,

+RXACIIR_A1_3  =  561,

+RXACIIR_A2_3  =  562,

+ECFIR_C2  =  563,

+ECFIR_C3  =  564,

+ECFIR_C4  =  565,

+ECFIR_C5  =  566,

+ECFIR_C6  =  567,

+ECFIR_C7  =  568,

+ECFIR_C8  =  569,

+ECFIR_C9  =  570,

+ECIIR_B0  =  571,

+ECIIR_B1  =  572,

+ECIIR_A1  =  573,

+ECIIR_A2  =  574,

+DTMFDTF_B0_1  =  575,

+DTMFDTF_B1_1  =  576,

+DTMFDTF_B2_1  =  577,

+DTMFDTF_A1_1  =  578,

+DTMFDTF_A2_1  =  579,

+DTMFDTF_B0_2  =  580,

+DTMFDTF_B1_2  =  581,

+DTMFDTF_B2_2  =  582,

+DTMFDTF_A1_2  =  583,

+DTMFDTF_A2_2  =  584,

+DTMFDTF_B0_3  =  585,

+DTMFDTF_B1_3  =  586,

+DTMFDTF_B2_3  =  587,

+DTMFDTF_A1_3  =  588,

+DTMFDTF_A2_3  =  589,

+DTMFDTF_GAIN  =  590,

+DTMFLPF_B0_1  =  591,

+DTMFLPF_B1_1  =  592,

+DTMFLPF_B2_1  =  593,

+DTMFLPF_A1_1  =  594,

+DTMFLPF_A2_1  =  595,

+DTMFLPF_B0_2  =  596,

+DTMFLPF_B1_2  =  597,

+DTMFLPF_B2_2  =  598,

+DTMFLPF_A1_2  =  599,

+DTMFLPF_A2_2  =  600,

+DTMFLPF_GAIN  =  601,

+DTMFHPF_B0_1  =  602,

+DTMFHPF_B1_1  =  603,

+DTMFHPF_B2_1  =  604,

+DTMFHPF_A1_1  =  605,

+DTMFHPF_A2_1  =  606,

+DTMFHPF_B0_2  =  607,

+DTMFHPF_B1_2  =  608,

+DTMFHPF_B2_2  =  609,

+DTMFHPF_A1_2  =  610,

+DTMFHPF_A2_2  =  611,

+DTMFHPF_GAIN  =  612,

+POWER_GAIN  =  613,

+GOERTZEL_GAIN  =  614,

+MODEM_GAIN  =  615,

+HOTBIT1  =  616,

+HOTBIT0  =  617,

+ROW0_C1  =  618,

+ROW1_C1  =  619,

+ROW2_C1  =  620,

+ROW3_C1  =  621,

+COL0_C1  =  622,

+COL1_C1  =  623,

+COL2_C1  =  624,

+COL3_C1  =  625,

+ROW0_C2  =  626,

+ROW1_C2  =  627,

+ROW2_C2  =  628,

+ROW3_C2  =  629,

+COL0_C2  =  630,

+COL1_C2  =  631,

+COL2_C2  =  632,

+COL3_C2  =  633,

+SLOPE_VLIM  =  634,

+SLOPE_RFEED  =  635,

+SLOPE_ILIM  =  636,

+SLOPE_RING  =  637,

+SLOPE_DELTA1  =  638,

+SLOPE_DELTA2  =  639,

+V_VLIM  =  640,

+V_RFEED  =  641,

+V_ILIM  =  642,

+CONST_RFEED  =  643,

+CONST_ILIM  =  644,

+I_VLIM  =  645,

+DC_DAC_GAIN  =  646,

+VDIFF_TH  =  647,

+TXDEC_B0  =  648,

+TXDEC_B1  =  649,

+TXDEC_B2  =  650,

+TXDEC_A1  =  651,

+TXDEC_A2  =  652,

+ZSYNTH_B0  =  653,

+ZSYNTH_B1  =  654,

+ZSYNTH_B2  =  655,

+ZSYNTH_A1  =  656,

+ZSYNTH_A2  =  657,

+RXACHPF_B0_1  =  658,

+RXACHPF_B1_1  =  659,

+RXACHPF_A1_1  =  660,

+RXACHPF_B0_2  =  661,

+RXACHPF_B1_2  =  662,

+RXACHPF_B2_2  =  663,

+RXACHPF_A1_2  =  664,

+RXACHPF_A2_2  =  665,

+RXACHPF_GAIN  =  666,

+MASK7LSB  =  667,

+RXDEC_B0  =  668,

+RXDEC_B1  =  669,

+RXDEC_B2  =  670,

+RXDEC_A1  =  671,

+RXDEC_A2  =  672,

+OSCINT1_B0_1  =  673,

+OSCINT1_B1_1  =  674,

+OSCINT1_B2_1  =  675,

+OSCINT1_A1_1  =  676,

+OSCINT1_A2_1  =  677,

+OSCINT1_B0_2  =  678,

+OSCINT1_B1_2  =  679,

+OSCINT1_B2_2  =  680,

+OSCINT1_A1_2  =  681,

+OSCINT1_A2_2  =  682,

+OSCINT2_B0_1  =  683,

+OSCINT2_B1_1  =  684,

+OSCINT2_B2_1  =  685,

+OSCINT2_A1_1  =  686,

+OSCINT2_A2_1  =  687,

+OSCINT2_B0_2  =  688,

+OSCINT2_B1_2  =  689,

+OSCINT2_B2_2  =  690,

+OSCINT2_A1_2  =  691,

+OSCINT2_A2_2  =  692,

+UNUSED693  =  693,

+UNUSED694  =  694,

+UNUSED695  =  695,

+RING_LPF_B0  =  696,

+RING_LPF_B1  =  697,

+RING_LPF_B2  =  698,

+RING_LPF_A1  =  699,

+RING_LPF_A2  =  700,

+LCRDBI  =  701,

+LONGDBI  =  702,

+VBAT_TIMER  =  703,

+LF_SPEEDUP_TIMER  =  704,

+DC_SPEEDUP_TIMER  =  705,

+AC_SPEEDUP_TIMER  =  706,

+LCR_SPEEDUP_TIMER  =  707,

+CM_SPEEDUP_TIMER  =  708,

+VCM_TH  =  709,

+AC_SPEEDUP_TH  =  710,

+SPR_SIG_0  =  711,

+SPR_SIG_1  =  712,

+SPR_SIG_2  =  713,

+SPR_SIG_3  =  714,

+SPR_SIG_4  =  715,

+SPR_SIG_5  =  716,

+SPR_SIG_6  =  717,

+SPR_SIG_7  =  718,

+SPR_SIG_8  =  719,

+SPR_SIG_9  =  720,

+SPR_SIG_10  =  721,

+SPR_SIG_11  =  722,

+SPR_SIG_12  =  723,

+SPR_SIG_13  =  724,

+SPR_SIG_14  =  725,

+SPR_SIG_15  =  726,

+SPR_SIG_16  =  727,

+SPR_SIG_17  =  728,

+SPR_SIG_18  =  729,

+COUNTER_VTR_VAL  =  730,

+CONST_028  =  731,

+CONST_032  =  732,

+CONST_038  =  733,

+CONST_046  =  734,

+COUNTER_IRING_VAL  =  735,

+GAIN_RING  =  736,

+RING_HYST  =  737,

+COMP_Z  =  738,

+CONST_115  =  739,

+CONST_110  =  740,

+CONST_105  =  741,

+CONST_100  =  742,

+CONST_095  =  743,

+CONST_090  =  744,

+CONST_085  =  745,

+V_RASUM_IDEAL  =  746,

+CONST_ONE  =  747,

+VCM_OH  =  748,

+VCM_RING  =  749,

+VCM_HYST  =  750,

+VOV_GND  =  751,

+VOV_BAT  =  752,

+VOV_RING_BAT  =  753,

+CM_DBI  =  754,

+RTPER  =  755,

+P_TH_HVIC  =  756,

+UNUSED757  =  757,

+UNUSED758  =  758,

+COEF_P_HVIC  =  759,

+COEF_Q1256  =  760,

+UNUSED761  =  761,

+UNUSED762  =  762,

+UNUSED763  =  763,

+BAT_HYST  =  764,

+BAT_DBI  =  765,

+VBATL_EXPECT  =  766,

+VBATH_EXPECT  =  767,

+VBATR_EXPECT  =  768,

+BAT_SETTLE  =  769,

+VBAT_IRQ_TH  =  770,

+MADC_VTIPC_OS  =  771,

+MADC_VRINGC_OS  =  772,

+MADC_VBAT_OS  =  773,

+MADC_VLONG_OS  =  774,

+UNUSED775  =  775,

+MADC_VDC_OS  =  776,

+MADC_ILONG_OS  =  777,

+UNUSED778  =  778,

+UNUSED779  =  779,

+MADC_ILOOP_OS  =  780,

+MADC_SCALE_ILOOP  =  781,

+UNUSED782  =  782,

+UNUSED783  =  783,

+DC_ADC_OS  =  784,

+CAL_UNITY  =  785,

+UNUSED786  =  786,

+UNUSED787  =  787,

+ACADC_OFFSET  =  788,

+ACDAC_OFFSET  =  789,

+CAL_DCDAC_CODE  =  790,

+CAL_DCDAC_15MA  =  791,

+UNUSED792  =  792,

+UNUSED793  =  793,

+UNUSED794  =  794,

+UNUSED795  =  795,

+UNUSED796  =  796,

+UNUSED797  =  797,

+UNUSED798  =  798,

+UNUSED799  =  799,

+UNUSED800  =  800,

+CAL_LB_TSQUELCH  =  801,

+CAL_LB_TCHARGE  =  802,

+CAL_LB_TSETTLE0  =  803,

+CAL_GOERTZEL_DLY  =  804,

+CAL_GOERTZEL_ALPHA  =  805,

+CAL_DECLPF_K  =  806,

+CAL_DECLPF_B1  =  807,

+CAL_DECLPF_B2  =  808,

+CAL_DECLPF_A1  =  809,

+CAL_DECLPF_A2  =  810,

+CAL_ACADC_THRL  =  811,

+CAL_ACADC_THRH  =  812,

+CAL_ACADC_TSETTLE  =  813,

+DTROW0TH  =  814,

+DTROW1TH  =  815,

+DTROW2TH  =  816,

+DTROW3TH  =  817,

+DTCOL0TH  =  818,

+DTCOL1TH  =  819,

+DTCOL2TH  =  820,

+DTCOL3TH  =  821,

+DTFTWTH  =  822,

+DTRTWTH  =  823,

+DTROWRTH  =  824,

+DTCOLRTH  =  825,

+DTROW2HTH  =  826,

+DTCOL2HTH  =  827,

+DTMINPTH  =  828,

+DTHOTTH  =  829,

+RXPWR  =  830,

+TXPWR  =  831,

+RXMODPWR  =  832,

+TXMODPWR  =  833,

+FSKFREQ0  =  834,

+FSKFREQ1  =  835,

+FSKAMP0  =  836,

+FSKAMP1  =  837,

+FSK01  =  838,

+FSK10  =  839,

+VOCDELTA  =  840,

+VOCLTH  =  841,

+VOCHTH  =  842,

+RINGOF  =  843,

+RINGFR  =  844,

+RINGAMP  =  845,

+RINGPHAS  =  846,

+RTDCTH  =  847,

+RTACTH  =  848,

+RTDCDB  =  849,

+RTACDB  =  850,

+RTCOUNT  =  851,

+LCROFFHK  =  852,

+LCRONHK  =  853,

+LCRMASK  =  854,

+LCRMASK_POLREV  =  855,

+LCRMASK_STATE  =  856,

+LCRMASK_LINECAP  =  857,

+LONGHITH  =  858,

+LONGLOTH  =  859,

+IRING_LIM  =  860,

+AC_PU_DELTA1  =  861,

+AC_PU_DELTA2  =  862,

+DIAG_LPF_8K  =  863,

+DIAG_LPF_128K  =  864,

+DIAG_INV_N  =  865,

+DIAG_GAIN  =  866,

+DIAG_G_CAL  =  867,

+DIAG_OS_CAL  =  868,

+SPR_GAIN_TRIM  =  869,

+UNUSED870  =  870,

+AC_DAC_GAIN  =  871,

+UNUSED872  =  872,

+UNUSED873  =  873,

+AC_DAC_GAIN0  =  874,

+EZSYNTH_B0  =  875,

+OFFLD_DAC_SCALE  =  876,

+UNUSED877  =  877,

+OFFLD_DAC_OS  =  878,

+UNUSED879  =  879,

+AC_ADC_GAIN  =  880,

+ILOOP1LPF  =  881,

+RING_FLUSH_TIMER  =  882,

+ALAW_BIAS  =  883,

+MADC_VTRC_SCALE  =  884,

+MADC_VBAT_SCALE  =  885,

+UNUSED886  =  886,

+MADC_VLONG_SCALE  =  887,

+MADC_VLONG_SCALE_RING  =  888,

+UNUSED889  =  889,

+MADC_VDC_SCALE  =  890,

+MADC_ILONG_SCALE  =  891,

+UNUSED892  =  892,

+UNUSED893  =  893,

+VDIFF_SENSE_SCALE  =  894,

+VDIFF_SENSE_SCALE_RING  =  895,

+VOV_RING_GND  =  896,

+P_TH_OFFLOAD  =  897,

+CAL_LB_OSC1_FREQ  =  898,

+CAL_DCDAC_9TAU  =  899,

+CAL_MADC_9TAU  =  900,

+ADAP_RING_MIN_I  =  901,

+SWEEP_STEP  =  902,

+SWEEP_STEP_SAVE  =  903,

+SWEEP_REF  =  904,

+AMP_STEP  =  905,

+RXACGAIN_SAVE  =  906,

+AMP_RAMP_INIT  =  907,

+DIAG_HPF_GAIN  =  908,

+DIAG_HPF_8K  =  909,

+DIAG_ADJ_STEP  =  910,

+UNUSED911  =  911,

+UNUSED912  =  912,

+MADC_SCALE_INV  =  913,

+UNUSED914  =  914,

+PWRSAVE_TIMER  =  915,

+OFFHOOK_THRESH  =  916,

+SPEEDUP_MASK_TIMER  =  917,

+XTALK_TIMER  =  918,

+VBAT_TRACK_MIN  =  919,

+VBAT_TRACK_MIN_RNG  =  920,

+UNUSED921  =  921,

+UNUSED922  =  922,

+UNUSED923  =  923,

+UNUSED924  =  924,

+UNUSED925 =  925,

+UNUSED926  =  926,

+DC_HOLD_DAC_OS  =  927,

+DAA_DTMF_IN_SCALE  =  928,

+NOTCH_B0  =  929,

+NOTCH_B1  =  930,

+NOTCH_B2  =  931,

+NOTCH_A1  =  932,

+NOTCH_A2  =  933,

+METER_LPF_B0  =  934,

+METER_LPF_B1  =  935,

+METER_LPF_B2  =  936,

+METER_LPF_A1  =  937,

+METER_LPF_A2  =  938,

+METER_SIG_0  =  939,

+METER_SIG_1  =  940,

+METER_SIG_2  =  941,

+METER_SIG_3  =  942,

+METER_SIG_4  =  943,

+METER_SIG_5  =  944,

+METER_SIG_6  =  945,

+METER_SIG_7  =  946,

+METER_SIG_8  =  947,

+METER_SIG_9  =  948,

+METER_SIG_10  =  949,

+METER_SIG_11  =  950,

+METER_SIG_12  =  951,

+METER_SIG_13  =  952,

+METER_SIG_14  =  953,

+METER_SIG_15  =  954,

+METER_BP_B0  =  955,

+METER_BP_B1  =  956,

+METER_BP_B2  =  957,

+METER_BP_A1  =  958,

+METER_BP_A2  =  959,

+PM_AMP_THRESH  =  960,

+PM_GAIN  =  961,

+PWRSAVE_DBI  =  962,

+DCDC_ANA_SCALE  =  963,

+VOV_BAT_PWRSAVE_LO  =  964,

+VOV_BAT_PWRSAVE_HI  =  965,

+AC_ADC_GAIN0  =  966,

+SCALE_KAUDIO  =  967,

+METER_GAIN_TEMP  =  968,

+METER_RAMP_STEP  =  969,

+THERM_DBI  =  970,

+LPR_SCALE =  971,

+LPR_CM_OS =  972,

+VOV_DCDC_SLOPE  =  973,

+VOV_DCDC_OS  =  974,

+VOV_RING_BAT_MAX  =  975,

+SLOPE_VLIM1 =  976,

+SLOPE_RFEED1  =  977,

+SLOPE_ILIM1  =  978,

+V_VLIM1  =  979,

+V_RFEED1  =  980,

+V_ILIM1  =  981,

+CONST_RFEED1 =  982,

+CONST_ILIM1 =  983,

+I_VLIM1  =  984,

+SLOPE_VLIM2 =  985,

+SLOPE_RFEED2  =  986,

+SLOPE_ILIM2  =  987,

+V_VLIM2  =  988,

+V_RFEED2  =  989,

+V_ILIM2 =  990,

+CONST_RFEED2  =  991,

+CONST_ILIM2  =  992,

+I_VLIM2  =  993,

+DIAG_V_TAR  =  994,

+DIAG_V_TAR2  =  995,

+STOP_TIMER1_VAL =  996,

+STOP_TIMER2_VAL =  997,

+DIAG_VCM1_TAR  =  998,

+DIAG_VCM_STEP  =  999,

+LKG_DNT_HIRES  =  1000,

+LKG_DNR_HIRES  =  1001,

+LINEAR_OS  =  1002,

+CPUMP_DEB =  1003,

+DCDC_VERR  =  1004,

+DCDC_VERR_HYST  =  1005,

+DCDC_OITHRESH_LO  =  1006,

+DCDC_OITHRESH_HI =  1007,

+HV_BIAS_ONHK  =  1008,

+HV_BIAS_OFFHK  =  1009,

+#ifdef USE_SI3226X_REVB_DEFINES

+RING_ENTRY_DLY  =  1010,

+RING_EXIT_DLY  =  1011,

+VBAT_FIXRL_RING  =  1012,

+VBAT_FIXRL_ACT  =  1013,

+VBAT_FIXRL_LP  =  1014,

+VOV_RING_BAT_DCDC  =  1015,

+P_OFFLOAD_VBAT_HYST  =  1016,

+LKG_OFHK_OFFSET  =  1017,

+LKG_LB_OFFSET  =  1018,

+UNUSED1019  =  1019,

+VBATH_DELTA  =  1020,

+UVTHRESH_MAX  =  1021,

+UVTHRESH_SCALE  =  1022,

+UVTHRESH_BIAS  =  1023

+#else

+UVTHRESH_BIAS = 1010,

+UVTHRESH_SCALE = 1011,

+UVTHRESH_MAX = 1012,

+VBATH_DELTA = 1013,

+UNUSED1014 = 1014,

+VOV_RING_BAT_DCDC = 1015,

+P_OFFLOAD_VBAT_HYST = 1016,

+LKG_LB_OFFSET = 1017,

+LKG_OFHK_OFFSET = 1018

+#endif

+};

+

+/*

+** This defines the neumomics for applicable SI3226X Memory-mapped register locations

+*/

+enum {

+    PD_BIAS = 1413,

+    PD_VBAT_SNS = 1418,

+    PD_HVIC = 1430,

+    MADC_LOOP_MAN = 1445,

+    HVIC_CNTL_MAN = 1451,

+    CAL_TRNRD_DACT = 1458,

+    CAL_TRNRD_DACR,

+    CMDAC_FWD = 1476,

+    CMDAC_REV,

+	RDC_SUM = 1499,

+    PD_OFFLD_DAC = 1512,

+    PD_OFFLD_GM = 1513,

+    DCDC_DCFF_ENABLE = 1522,

+    PD_DCDC = 1538,

+    PD_UVLO = 1540,

+    PD_OVLO,

+    PD_OCLO,

+	DCDC_UVHYST = 1545,

+	DCDC_UVTHRESH,

+	DCDC_OVTHRESH = 1547,

+	DCDC_OITHRESH,

+	UNUSED1549,

+	DCDC_CCM_THRESH,

+	DCDC_STATUS,

+	DCDC_FSW,

+	DCDC_SWDRV_POL,

+	DCDC_UVPOL,

+	DCDC_CPUMP,

+	UNUSED1556,

+	UNUSED1557,

+	DCDC_VREF_CTRL,

+	UNUSED1559,

+	DCDC_RNGTYPE,

+    DCDC_OIMASK = 1565,

+    PD_REF_OSC = 1571,

+    DCDC_ANA_GAIN = 1585,

+    DCDC_ANA_TOFF,

+    DCDC_ANA_TONMIN,

+    DCDC_ANA_TONMAX,

+    DCDC_ANA_DSHIFT,

+    DCDC_ANA_LPOLY,

+    DCDC_PD_ANA = 1592,

+    PATCH_JMP8 = 1597,

+    DCDC_CPUMP_LP_MASK = 1616,

+    DCDC_UV_MAN = 1640,

+    DCDC_UV_DEBOUNCE = 1641,

+    DCDC_OV_MAN = 1642, 

+    DCDC_OV_DEBOUNCE = 1643,

+    OFFLD_DAC_MAN = 1646

+};

+

+/* Temporary Rev B Support During Rev C Adoption */

+#define LKG_OFHK_OFFSET_REVB 1017

+#define LKG_LB_OFFSET_REVB   1018

+#define VBATH_DELTA_REVB     1020

+#define UVTHRESH_MAX_REVB    1021

+#define UVTHRESH_SCALE_REVB  1022

+#define UVTHRESH_BIAS_REVB   1023

+

+/* Temporarily map obsolete ram locations for debug purposes */

+#define DCDC_FSW_NORM       UNUSED921

+#define DCDC_FSW_NORM_LO    UNUSED922

+#define DCDC_DIN_LIM        UNUSED925

+#define DCDC_FSW_RING       UNUSED923

+#define DCDC_FSW_RING_LO    UNUSED924

+#define DCDC_VOUT_LIM       UNUSED926

+#define DCDC_FSW_VHYST      Y3

+#define DCDC_FSW_VTHLO      Y2

+#define DAA_CNTL            74

+#define DCDC_VREF_MIN       VBAT_TRACK_MIN

+#define DCDC_VREF_MIN_RNG   VBAT_TRACK_MIN_RNG

+

+

+#endif

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x.h
new file mode 100755
index 0000000..c080a8b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x.h
@@ -0,0 +1,314 @@
+/*

+** Copyright (c) 2007 by Silicon Laboratories

+**

+** $Id: si324x.h 1832 2010-04-19 21:39:12Z cdp $

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+*/

+

+#ifndef SI324XH_H

+#define SI324XH_H

+

+#include "proslic.h"

+

+/*

+** Si324x DataTypes/Function Definitions 

+*/

+

+#define NUMIRQ 4

+

+

+/*

+** Defines structure for configuring gpio

+*/

+typedef struct {

+	uInt8 outputEn;

+	uInt8 analog;

+	uInt8 direction;

+	uInt8 manual;

+	uInt8 polarity;

+	uInt8 openDrain;

+} Si324x_GPIO_Cfg;

+

+/*

+** Defines structure for configuring dc feed

+*/

+typedef struct {

+	ramData slope_vlim;

+	ramData slope_rfeed;

+	ramData slope_ilim;

+	ramData delta1;

+	ramData delta2;

+	ramData v_vlim;

+	ramData v_rfeed;

+	ramData v_ilim;

+	ramData const_rfeed;

+	ramData const_ilim;

+	ramData i_vlim;

+	ramData lcronhk;

+	ramData lcroffhk;

+	ramData lcrdbi;

+	ramData longhith;

+	ramData longloth;

+	ramData longdbi;

+	ramData lcrmask;

+	ramData lcrmask_polrev;

+	ramData lcrmask_state;

+	ramData lcrmask_linecap;

+	ramData vcm_oh;

+	ramData vov_bat;

+	ramData vov_gnd;

+} Si324x_DCfeed_Cfg;

+

+/*

+** Defines structure for configuring general parameters

+*/

+typedef struct {

+	ramData vbatr_expect;

+	ramData coef_p_hvic;

+	ramData p_th_hvic;

+	ramData vbath_expect;

+	uInt8	cm_clamp;

+	uInt8	autoRegister;

+	ramData cm_dbi;

+	ramData bat_dbi;

+	ramData bat_hyst;

+	ramData bat_settle;

+	uInt8 batselmap;

+	ramData coef_p_offld;

+	uInt8 offld;

+	ramData p_th_offld;

+	ramData vbatl_expect;

+	uInt8 irqen1;

+	uInt8 irqen2;

+	uInt8 irqen3;

+	uInt8 irqen4;

+} Si324x_General_Cfg;

+/*

+** Defines structure for configuring pcm

+*/

+typedef struct {

+	uInt8 pcmFormat;

+	uInt8 widebandEn;

+	uInt8 pcm_tri;

+	uInt8 tx_edge;

+	uInt8 tx_both;

+	uInt8 tx_hwy;

+	uInt8 rx_hwy;

+	uInt8 alaw_inv;

+} Si324x_PCM_Cfg;

+

+/*

+** Defines structure for configuring pulse metering

+*/

+typedef struct {

+	ramData pm_amp_thresh;

+	uInt8 pmFreq;

+	uInt8 pmRampRate;

+} Si324x_PulseMeter_Cfg;

+

+/*

+** Defines structure for configuring FSK generation

+*/

+typedef struct {

+	ramData fsk01;

+	ramData fsk10;

+	ramData fskamp0;

+	ramData fskamp1;

+	ramData fskfreq0;

+	ramData fskfreq1;

+	uInt8 eightBit;

+	uInt8 fskdepth;

+} Si324x_FSK_Cfg;

+

+/*

+** Defines structure for configuring dtmf decode

+*/

+typedef struct {

+	ramData dtmfdtf_b0_1;

+	ramData dtmfdtf_b1_1;

+	ramData dtmfdtf_b2_1;

+	ramData dtmfdtf_a1_1;

+	ramData dtmfdtf_a2_1;

+	ramData dtmfdtf_b0_2;

+	ramData dtmfdtf_b1_2;

+	ramData dtmfdtf_b2_2;

+	ramData dtmfdtf_a1_2;

+	ramData dtmfdtf_a2_2;

+	ramData dtmfdtf_b0_3;

+	ramData dtmfdtf_b1_3;

+	ramData dtmfdtf_b2_3;

+	ramData dtmfdtf_a1_3;

+	ramData dtmfdtf_a2_3;

+} Si324x_DTMFDec_Cfg;

+

+/*

+** Defines structure for configuring impedence synthesis

+*/

+typedef struct {

+	ramData zsynth_b0;

+	ramData zsynth_b1;

+	ramData zsynth_b2;

+	ramData zsynth_a1;

+	ramData zsynth_a2;

+	uInt8 ra;

+} Si324x_Zsynth_Cfg;

+

+/*

+** Defines structure for configuring hybrid

+*/

+typedef struct {

+	ramData ecfir_c2;

+	ramData ecfir_c3;

+	ramData ecfir_c4;

+	ramData ecfir_c5;

+	ramData ecfir_c6;

+	ramData ecfir_c7;

+	ramData ecfir_c8;

+	ramData ecfir_c9;

+	ramData eciir_b0;

+	ramData eciir_b1;

+	ramData eciir_a1;

+	ramData eciir_a2;

+} Si324x_hybrid_Cfg;

+

+/*

+** Defines structure for configuring GCI CI bits

+*/

+typedef struct {

+	uInt8 gci_ci;

+} Si324x_CI_Cfg;

+

+/*

+** Defines structure for configuring modem tone detect

+*/

+typedef struct {

+	ramData rxmodpwr;

+	ramData rxpwr;

+	ramData modem_gain;

+	ramData txmodpwr;

+	ramData txpwr;

+} Si324x_modemDet_Cfg;

+

+/*

+** Defines structure for configuring audio eq

+*/

+typedef struct {

+	ramData txaceq_c0;

+	ramData txaceq_c1;

+	ramData txaceq_c2;

+	ramData txaceq_c3;

+

+	ramData rxaceq_c0;

+	ramData rxaceq_c1;

+	ramData rxaceq_c2;

+	ramData rxaceq_c3;

+} Si324x_audioEQ_Cfg;

+

+/*

+** Defines structure for configuring audio gain

+*/

+typedef struct {

+	ramData acgain;

+	uInt8 mute;

+} Si324x_audioGain_Cfg;

+

+typedef struct {

+	Si324x_audioEQ_Cfg audioEQ;

+	Si324x_hybrid_Cfg hybrid;

+    Si324x_Zsynth_Cfg zsynth;

+	Si324x_audioGain_Cfg txgain;

+	Si324x_audioGain_Cfg rxgain;

+	ramData rxachpf_b0_1;

+	ramData  rxachpf_b1_1;

+	ramData  rxachpf_a1_1;

+} Si324x_Impedance_Cfg;

+

+/*

+** Defines structure for configuring tone generator

+*/

+typedef struct {

+	Oscillator_Cfg osc1;

+	Oscillator_Cfg osc2;

+	uInt8 omode;

+} Si324x_Tone_Cfg; 

+

+/*

+** Defines structure for configuring ring generator

+*/

+typedef struct {

+	ramData freq;

+	ramData amp;

+	ramData offset;

+	ramData phas;

+	ramData rtper;

+	uInt8 talo;

+	uInt8 tahi;

+	uInt8 tilo;

+	uInt8 tihi;

+	uInt8 ringcon;

+	ramData rtcount;

+	ramData adap_ring_min_i;

+	ramData slope_ring;

+	ramData rrd_delay;

+	ramData rrd_delay2;

+	ramData counter_vtr_val;

+	ramData rtacdb;

+    ramData rtacth;

+	ramData rtdcdb;

+	ramData rtdcth;

+	ramData vov_ring_bat;

+	ramData vov_ring_gnd;

+	ramData vcm_ring;

+} Si324x_Ring_Cfg;

+

+

+

+/*

+** This defines names for the interrupts in the ProSLIC

+*/

+typedef enum {

+OSC1_T1_SI324X,

+OSC1_T2_SI324X,

+OSC2_T1_SI324X,

+OSC2_T2_SI324X,

+RING_T1_SI324X,

+RING_T2_SI324X,

+FSKBUF_AVAIL_SI324X,

+VBAT_SI324X,

+RING_TRIP_SI324X,

+LOOP_STAT_SI324X,

+LONG_STAT_SI324X,

+VOC_TRACK_SI324X,

+DTMF_SI324X,

+INDIRECT_SI324X,

+TXMDM_SI324X,

+RXMDM_SI324X,

+PQ1_SI324X,

+PQ2_SI324X,

+PQ3_SI324X,

+PQ4_SI324X,

+PQ5_SI324X,

+PQ6_SI324X,

+RING_FAIL_SI324X,

+CM_BAL_SI324X,

+USER_IRQ0_SI324X,

+USER_IRQ1_SI324X,

+USER_IRQ2_SI324X,

+USER_IRQ3_SI324X,

+USER_IRQ4_SI324X,

+USER_IRQ5_SI324X,

+USER_IRQ6_SI324X,

+USER_IRQ7_SI324X

+}Si324xProslicInt;

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x_intf.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x_intf.h
new file mode 100755
index 0000000..60c39ad
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x_intf.h
@@ -0,0 +1,779 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: si324x_intf.h 2395 2010-11-03 23:09:03Z nizajerk $

+**

+** Si324x_Intf.h

+** Si324x ProSLIC interface header file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file for the ProSLIC driver.

+**

+** Dependancies:

+** proslic_datatypes.h, Si324x_registers.h, ProSLIC.h

+**

+*/

+#ifndef SI324X_INTF_H

+#define SI324X_INTF_H

+

+/*

+**

+** Si324x General Constants 

+**

+*/

+#define SCALE_V_MADC        1074    /* 1/(100*931.32e-9) mV */

+#define SCALE_I_MADC        597     /* 1/(1e6*1.676e-9) uA */

+

+/*

+**

+** PROSLIC INITIALIZATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_Reset

+**

+** Description: 

+** Resets the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si324x_Reset (proslicChanType_ptr hProslic);

+

+

+/*

+** Function: PROSLIC_Init

+**

+** Description: 

+** Initializes the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si324x_Init (proslicChanType_ptr *hProslic,int size);

+

+/*

+** Function: PROSLIC_Init

+**

+** Description: 

+** Initializes the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si324x_InitBroadcast (proslicChanType_ptr *hProslic);

+

+/*

+** Function: PROSLIC_Cal

+**

+** Description: 

+** Calibrates the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+**

+** Return:

+** none

+*/

+int Si324x_Cal (proslicChanType_ptr *hProslic, int size);

+

+/*

+** Function: PROSLIC_LoadRegTables

+**

+** Description: 

+** Loads registers and ram in the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pRamTable: pointer to ram values to load

+** pRegTable: pointer to register values to load

+** 

+**

+** Return:

+** none

+*/

+int Si324x_LoadRegTables (proslicChanType_ptr *hProslic, ProslicRAMInit *pRamTable, ProslicRegInit *pRegTable,int size);

+

+/*

+** Function: PROSLIC_LoadPatch

+**

+** Description: 

+** Loads patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si324x_LoadPatch (proslicChanType_ptr hProslic, const proslicPatch *pPatch);

+

+/*

+** Function: PROSLIC_VerifyPatch

+**

+** Description: 

+** Verifies patch to the ProSLIC

+**

+** Input Parameters: 

+** pProslic: pointer to PROSLIC object

+** pPatch: pointer to patch data

+**

+** Return:

+** none

+*/

+int Si324x_VerifyPatch (proslicChanType_ptr hProslic, const proslicPatch *pPatch);

+

+/*

+** Function: PROSLIC_EnableInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** 

+** Return:

+** 

+*/

+int Si324x_EnableInterrupts (proslicChanType_ptr hProslic);

+int Si324x_DisableInterrupts (proslicChanType_ptr hProslic);

+

+

+int Si324x_SetLoopbackMode (proslicChanType_ptr hProslic, ProslicLoopbackModes newMode);

+

+int Si324x_SetMuteStatus (proslicChanType_ptr hProslic, ProslicMuteModes muteEn);

+

+/*

+**

+** PROSLIC CONFIGURATION FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_RingSetup

+**

+** Description: 

+** configure ringing

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pRingSetup: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si324x_RingSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ToneGenSetup

+**

+** Description: 

+** configure tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pTone: pointer to tones config structure

+**

+** Return:

+** none

+*/

+int Si324x_ToneGenSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_FSKSetup

+**

+** Description: 

+** configure fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pFsk: pointer to fsk config structure

+**

+** Return:

+** none

+*/

+int Si324x_FSKSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_DTMFDecodeSetup

+**

+** Description: 

+** configure dtmf decode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDTMFDec: pointer to dtmf decoder config structure

+**

+** Return:

+** none

+*/

+int Si324x_DTMFDecodeSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_SetProfile

+**

+** Description: 

+** set country profile of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCountryData: pointer to country config structure

+**

+** Return:

+** none

+*/

+int Si324x_SetProfile (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ZsynthSetup

+**

+** Description: 

+** configure impedence synthesis

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pZynth: pointer to zsynth config structure

+**

+** Return:

+** none

+*/

+int Si324x_ZsynthSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_GciCISetup

+**

+** Description: 

+** configure CI bits (GCI mode)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pCI: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si324x_GciCISetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_ModemDetSetup

+**

+** Description: 

+** configure modem detector

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pModemDet: pointer to modem det config structure

+**

+** Return:

+** none

+*/

+int Si324x_ModemDetSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioGainSetup

+**

+** Description: 

+** configure audio gains

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudio: pointer to audio gains config structure

+**

+** Return:

+** none

+*/

+int Si324x_TXAudioGainSetup (proslicChanType *pProslic, int preset);

+int Si324x_RXAudioGainSetup (proslicChanType *pProslic, int preset);

+int Si324x_AudioGainSetup (proslicChanType *pProslic, int32 rxgain, int32 txgain,int preset);

+

+/*

+** Function: PROSLIC_HybridSetup

+**

+** Description: 

+** configure Proslic hybrid

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHybridCfg: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si324x_HybridSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_AudioEQSetup

+**

+** Description: 

+** configure audio equalizers

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pAudioEQ: pointer to ringing config structure

+**

+** Return:

+** none

+*/

+int Si324x_AudioEQSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_DCFeedSetup

+**

+** Description: 

+** configure dc feed

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDcFeed: pointer to dc feed config structure

+**

+** Return:

+** none

+*/

+int Si324x_DCFeedSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_GPIOSetup

+**

+** Description: 

+** configure gpio

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpio: pointer to gpio config structure

+**

+** Return:

+** none

+*/

+int Si324x_GPIOSetup (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterSetup

+**

+** Description: 

+** configure pulse metering

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPulseCfg: pointer to pulse metering config structure

+**

+** Return:

+** none

+*/

+int Si324x_PulseMeterSetup (proslicChanType *pProslic, int preset);

+

+/*

+** Function: PROSLIC_PCMSetup

+**

+** Description: 

+** configure pcm

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPcm: pointer to pcm config structure

+**

+** Return:

+** none

+*/

+int Si324x_PCMSetup (proslicChanType *pProslic, int preset);

+int Si324x_PCMTimeSlotSetup (proslicChanType *pProslic, uInt16 rxcount, uInt16 txcount);

+

+/*

+**

+** PROSLIC CONTROL FUNCTIONS

+**

+*/

+

+/*

+** Function: PROSLIC_GetInterrupts

+**

+** Description: 

+** Enables interrupts

+**

+** Input Parameters: 

+** hProslic: pointer to Proslic object

+** pIntData: pointer to interrupt info retrieved

+** 

+** Return:

+** 

+*/

+int Si324x_GetInterrupts (proslicChanType_ptr hProslic, proslicIntType *pIntData);

+

+/*

+** Function: PROSLIC_ReadHookStatus

+**

+** Description: 

+** Determine hook status

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pHookStat: current hook status

+**

+** Return:

+** none

+*/

+int Si324x_ReadHookStatus (proslicChanType *pProslic,uInt8 *pHookStat);

+

+/*

+** Function: PROSLIC_WriteLinefeed

+**

+** Description: 

+** Sets linefeed state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** newLinefeed: new linefeed state

+**

+** Return:

+** none

+*/

+int Si324x_SetLinefeedStatus (proslicChanType *pProslic, uInt8 newLinefeed);

+

+/*

+** Function: PROSLIC_WriteLinefeed

+**

+** Description: 

+** Sets linefeed state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** newLinefeed: new linefeed state

+**

+** Return:

+** none

+*/

+int Si324x_SetLinefeedStatusBroadcast (proslicChanType *pProslic, uInt8 newLinefeed);

+

+/*

+** Function: PROSLIC_PolRev

+**

+** Description: 

+** Sets polarity reversal state

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** abrupt: set this to 1 for abrupt pol rev

+** newPolRevState: new pol rev state

+**

+** Return:

+** none

+*/

+int Si324x_PolRev (proslicChanType *pProslic,uInt8 abrupt, uInt8 newPolRevState);

+

+/*

+** Function: PROSLIC_GPIOControl

+**

+** Description: 

+** Sets gpio of the proslic

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pGpioData: pointer to gpio status

+** read: set to 1 to read status, 0 to write

+**

+** Return:

+** none

+*/

+int Si324x_GPIOControl (proslicChanType *pProslic,uInt8 *pGpioData, uInt8 read);

+

+/*

+** Function: PROSLIC_MWI

+**

+** Description: 

+** implements message waiting indicator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** lampOn: 0 = turn lamp off, 1 = turn lamp on

+**

+** Return:

+** none

+*/

+int Si324x_MWI (proslicChanType *pProslic,uInt8 lampOn);

+

+/*

+** Function: PROSLIC_StartGenericTone

+**

+** Description: 

+** Initializes and start tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** timerEn: specifies whether to enable the tone generator timers

+**

+** Return:

+** none

+*/

+int Si324x_ToneGenStart (proslicChanType *pProslic, uInt8 timerEn);

+

+

+/*

+** Function: PROSLIC_StopTone

+**

+** Description: 

+** Stops tone generators

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_ToneGenStop (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StartRing

+**

+** Description: 

+** Initializes and start ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_RingStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopRing

+**

+** Description: 

+** Stops ring generator

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_RingStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_EnableCID

+**

+** Description: 

+** enable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_EnableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DisableCID

+**

+** Description: 

+** disable fsk

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_DisableCID (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_SendCID

+**

+** Description: 

+** send fsk data

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** buffer: buffer to send

+** numBytes: num of bytes in the buffer

+**

+** Return:

+** none

+*/

+int Si324x_SendCID (proslicChanType *pProslic, uInt8 *buffer, uInt8 numBytes);

+

+int Si324x_CheckCIDBuffer (proslicChanType *pProslic, uInt8 *fsk_buf_avail);

+

+/*

+** Function: PROSLIC_StartPCM

+**

+** Description: 

+** Starts PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_PCMStart (proslicChanType *pProslic);

+

+

+/*

+** Function: PROSLIC_StopPCM

+**

+** Description: 

+** Disables PCM

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_PCMStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_DialPulseDetect

+**

+** Description: 

+** implements pulse dial detection and should be called at every off/on hook transistion

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pPulsedialCfg: pointer to pulse dial config

+** pPulseDialData: pointer to pulse dial state for current channel

+**

+** Return:

+** none

+*/

+int Si324x_DialPulseDetect (proslicChanType *pProslic, pulseDial_Cfg *pPulsedialCfg, pulseDialType *pPulseDialData);

+

+/*

+** Function: PROSLIC_ReadDTMFDigit

+**

+** Description: 

+** Read DTMF digit (would be called after DTMF interrupt to collect digit)

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+** pDigit: digit read

+**

+** Return:

+** none

+*/

+int Si324x_DTMFReadDigit (proslicChanType *pProslic,uInt8 *pDigit);

+

+/*

+** Function: PROSLIC_PLLFreeRunStart

+**

+** Description: 

+** initiates pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_PLLFreeRunStart (proslicChanType *pProslic);

+

+int Si324x_VerifyControlInterface (proslicChanType_ptr pProslic);

+int Si324x_PrintDebugData (proslicChanType *pProslic);

+/*

+** Function: PROSLIC_PLLFreeRunStop

+**

+** Description: 

+** exit pll free run mode

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_PLLFreeRunStop (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterStart

+**

+** Description: 

+** start pulse meter tone

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_PulseMeterStart (proslicChanType *pProslic);

+

+/*

+** Function: PROSLIC_PulseMeterStop

+**

+** Description: 

+** stop pulse meter tone

+**

+** Input Parameters: 

+** pProslic: pointer to Proslic object

+**

+** Return:

+** none

+*/

+int Si324x_PulseMeterStop (proslicChanType *pProslic);

+

+int Si324x_LBCal (proslicChanType_ptr *pProslic, int size);

+int Si324x_LBCalBroadcast (proslicChanType *pProslic);

+int Si324x_GetLBCalResult (proslicChanType *pProslic,int32*result1,int32*result2,int32 *result3,int32 *result4);

+int Si324x_GetLBCalResultPacked (proslicChanType *pProslic,int32 *result);

+int Si324x_LoadPreviousLBCal (proslicChanType *pProslic,int32 result1,int32 result2,int32 result3,int32 result4);

+int Si324x_LoadPreviousLBCalPacked (proslicChanType *pProslic,int32 *result);

+

+

+/*

+** Function: Si3224_dbgSetTXGain

+**

+** Description: 

+** Provisionary function for setting up

+** TX gain

+*/

+int Si324x_dbgSetTXGain (proslicChanType *pProslic, int32 gain, 

+    int impedance_preset, int audio_gain_preset);

+

+/*

+** Function: Si3224_dbgSetRXGain

+**

+** Description: 

+** Provisionary function for setting up

+** RX gain

+*/

+int Si324x_dbgSetRXGain(proslicChanType *pProslic, int32 gain, 

+    int impedance_preset, int audio_gain_preset);

+

+/*

+** Function: Si3224_LineMonitor

+**

+** Description: 

+** Monitor line voltages and current

+*/

+int Si324x_LineMonitor(proslicChanType *pProslic, proslicMonitorType *monitor);

+

+

+

+#endif

+

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x_registers.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x_registers.h
new file mode 100755
index 0000000..e348cf6
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si324x_registers.h
@@ -0,0 +1,1179 @@
+/*

+** Copyright (c) 2007 by Silicon Laboratories

+**

+** $Id: si324x_registers.h 544 2009-03-23 20:07:28Z cdp@SILABS.COM $

+**

+** Si324x_Registers.h

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file that contains

+** register and RAM names definitions for 

+** the Si324x ProSLIC.

+**

+** Dependancies:

+** 

+**

+*/

+#ifndef SI324XREGS_H

+#define SI324XREGS_H

+

+/*

+** This defines the neumomics for the Si324x registers

+*/

+enum REGISTERS {

+ID,

+RESET,

+MSTREN,

+MSTRSTAT,

+RAMSTAT,

+RAM_ADDR_HI,

+RAM_DATA_B0,

+RAM_DATA_B1,

+RAM_DATA_B2,

+RAM_DATA_B3,

+RAM_ADDR_LO,

+PCMMODE,

+PCMTXLO,

+PCMTXHI,

+PCMRXLO,

+PCMRXHI,

+IRQ,

+IRQ0,

+IRQ1,

+IRQ2,

+IRQ3,

+IRQ4,

+IRQEN1,

+IRQEN2,

+IRQEN3,

+IRQEN4,

+CALR0,

+CALR1,

+CALR2,

+CALR3,

+LINEFEED,

+POLREV,

+SPEEDUP_DIS,

+SPEEDUP,

+LCRRTP,

+OFFLOAD,

+BATSELMAP,

+BATSEL,

+RINGCON,

+RINGTALO,

+RINGTAHI,

+RINGTILO,

+RINGTIHI,

+LOOPBACK,

+DIGCON,

+RA,

+ZCAL_EN,

+PMCON,

+OMODE,

+OCON,

+O1TALO,

+O1TAHI,

+O1TILO,

+O1TIHI,

+O2TALO,

+O2TAHI,

+O2TILO,

+O2TIHI,

+FSKDAT,

+FSKDEPTH,

+TONDTMF,

+TONDET,

+TONEN,

+GCI_CI,

+GLOBSTAT1,

+GLOBSTAT2,

+USERSTAT,

+GPIO,

+GPIO_CFG1,

+GPIO_CFG2,

+GPIO_CFG3,

+DIAG1,

+DIAG2,

+CM_CLAMP,

+REG74,

+REG75,

+REG76,

+REG77,

+REG78,

+REG79,

+AUTO,

+JMPEN,

+JMP0LO,

+JMP0HI,

+JMP1LO,

+JMP1HI,

+JMP2LO,

+JMP2HI,

+JMP3LO,

+JMP3HI,

+JMP4LO,

+JMP4HI,

+JMP5LO,

+JMP5HI,

+JMP6LO,

+JMP6HI,

+JMP7LO,

+JMP7HI,

+PDN,

+PDN_STAT

+};

+

+

+/*

+** This defines the neumomics for the Si324x RAM locations (revB)

+*/

+enum SRAM {

+IRNGNG_SENSE,

+MADC_VTIPC,

+MADC_VRINGC,

+MADC_VBAT,

+MADC_VLONG,

+MADC_VBLKRNG,

+MADC_IBLKRNG,

+MADC_ILONG,

+MADC_ITIP,

+MADC_IRING,

+MADC_ILOOP,

+VDIFF_SENSE,

+VTIP,

+VRING,

+P_Q1_D,

+P_Q2_D,

+P_Q3_D,

+P_Q4_D,

+P_Q5_D,

+P_Q6_D,

+P_Q1,

+DIAG_EX1,

+DIAG_EX2,

+DIAG_LPF_MADC,

+DIAG_DMM_I,

+DIAG_DMM_V,

+OSC1FREQ,

+OSC1AMP,

+OSC1PHAS,

+OSC2FREQ,

+OSC2AMP,

+OSC2PHAS,

+TESTB0_1,

+TESTB1_1,

+TESTB2_1,

+TESTA1_1,

+TESTA2_1,

+TESTB0_2,

+TESTB1_2,

+TESTB2_2,

+TESTA1_2,

+TESTA2_2,

+TESTB0_3,

+TESTB1_3,

+TESTB2_3,

+TESTA1_3,

+TESTA2_3,

+TESTPKO,

+TESTAVO,

+TESTWLN,

+TESTAVBW,

+TESTPKFL,

+TESTAVFL,

+TESTPKTH,

+TESTAVTH,

+DAC_IN_SYNC1,

+BYPASS_REG,

+LCRMASK_CNT,

+DAC_IN_SYNC,

+TEMP,

+TEMP_ISR,

+P_Q2,

+P_Q3,

+P_Q4,

+P_Q5,

+P_Q6,

+ILOOP_FILT,

+ILONG_FILT,

+VBAT_FILT,

+VDIFF_FILT,

+VCM_FILT,

+VBAT_CNT,

+V_VLIM_SCALED,

+V_VLIM_TRACK,

+V_VLIM_MODFEED,

+DIAG_P_OUT,

+DIAG_COUNT,

+ROW0_MAG,

+ROW1_MAG,

+ROW2_MAG,

+ROW3_MAG,

+COL0_MAG,

+COL1_MAG,

+COL2_MAG,

+COL3_MAG,

+ROW0_2ND_Y1,

+ROW1_2ND_Y1,

+ROW2_2ND_Y1,

+ROW3_2ND_Y1,

+COL0_2ND_Y1,

+COL1_2ND_Y1,

+COL2_2ND_Y1,

+COL3_2ND_Y1,

+ROW0_2ND_Y2,

+ROW1_2ND_Y2,

+ROW2_2ND_Y2,

+ROW3_2ND_Y2,

+COL0_2ND_Y2,

+COL1_2ND_Y2,

+COL2_2ND_Y2,

+COL3_2ND_Y2,

+DTMF_IN,

+DTMFDTF_D2_1,

+DTMFDTF_D1_1,

+DTMFDTF_OUT_1,

+DTMFDTF_D2_2,

+DTMFDTF_D1_2,

+DTMFDTF_OUT_2,

+DTMFDTF_D2_3,

+DTMFDTF_D1_3,

+DTMFDTF_OUT_3,

+DTMFDTF_OUT,

+DTMFLPF_D2_1,

+DTMFLPF_D1_1,

+DTMFLPF_OUT_1,

+DTMFLPF_D2_2,

+DTMFLPF_D1_2,

+DTMFLPF_OUT_2,

+DTMF_ROW,

+DTMFHPF_D2_1,

+DTMFHPF_D1_1,

+DTMFHPF_OUT_1,

+DTMFHPF_D2_2,

+DTMFHPF_D1_2,

+DTMFHPF_OUT_2,

+DTMF_COL,

+ROW_POWER,

+COL_POWER,

+GP_TIMER,

+SPR_INTERP_DIF,

+SPR_INTERP_DIF_OUT,

+SPR_INTERP_INT,

+SPR_CNT,

+ROW0_Y1,

+ROW0_Y2,

+ROW1_Y1,

+ROW1_Y2,

+ROW2_Y1,

+ROW2_Y2,

+ROW3_Y1,

+ROW3_Y2,

+COL0_Y1,

+COL0_Y2,

+COL1_Y1,

+COL1_Y2,

+COL2_Y1,

+COL2_Y2,

+COL3_Y1,

+COL3_Y2,

+ROWMAX_MAG,

+COLMAX_MAG,

+ROW0_2ND_MAG,

+COL0_2ND_MAG,

+ROW_THR,

+COL_THR,

+OSC1_Y,

+OSC2_Y,

+OSC1_X,

+OSC1_COEFF,

+OSC2_X,

+OSC2_COEFF,

+RXACIIR_D2_1,

+RXACIIR_OUT_1,

+RXACIIR_D2_2,

+RXACIIR_D1_2,

+RXACIIR_OUT_2,

+RXACIIR_D2_3,

+RXACIIR_D1_3,

+RXACIIR_OUT,

+RXACIIR_OUT_3,

+TXACCOMB_D1,

+TXACCOMB_D2,

+TXACCOMB_D3,

+TXACSINC_OUT,

+TXACHPF_D1_2,

+TXACHPF_D2_1,

+TXACHPF_D2_2,

+TXACHPF_OUT,

+TXACHPF_OUT_1,

+TXACHPF_OUT_2,

+TXACIIR_D2_1,

+TXACIIR_OUT_1,

+TXACIIR_D2_2,

+TXACIIR_D1_2,

+TXACIIR_OUT_2,

+TXACIIR_D2_3,

+TXACIIR_D1_3,

+TXACIIR_OUT_3,

+TXACIIR_OUT,

+ECIIR_D1,

+ECIIR_D2,

+EC_DELAY1,

+EC_DELAY2,

+EC_DELAY3,

+EC_DELAY4,

+EC_DELAY5,

+EC_DELAY6,

+EC_DELAY7,

+EC_DELAY8,

+EC_DELAY9,

+EC_DELAY10,

+EC_DELAY11,

+ECHO_EST,

+EC_OUT,

+TESTFILT_OUT_1,

+TESTFILT_D1_1,

+TESTFILT_D2_1,

+TESTFILT_OUT_2,

+TESTFILT_D1_2,

+TESTFILT_D2_2,

+TESTFILT_OUT_3,

+TESTFILT_D1_3,

+TESTFILT_D2_3,

+TESTFILT_PEAK,

+TESTFILT_ABS,

+TESTFILT_MEANACC,

+TESTFILT_COUNT,

+TESTFILT_NO_OFFSET,

+RING_X,

+RING_Y,

+RING_INT,

+RING_Y_D1,

+RING_DIFF,

+RING_DELTA,

+WTCHDOG_CNT,

+RING_WAVE,

+RRD2LINEFEED_CNT,

+ONEKHZ_COUNT,

+TX2100_Y1,

+TX2100_Y2,

+TX2100_MAG,

+RX2100_Y1,

+RX2100_Y2,

+RX2100_MAG,

+TX2100_POWER,

+RX2100_POWER,

+TX2100_IN,

+RX2100_IN,

+RINGTRIP_COUNT,

+RINGTRIP_DC1,

+RINGTRIP_DC2,

+RINGTRIP_AC1,

+RINGTRIP_AC2,

+RINGTRIP_AC_COUNT,

+RINGTRIP_DC_COUNT,

+RINGTRIP_AC_RESULT,

+RINGTRIP_DC_RESULT,

+RINGTRIP_ABS,

+TXACEQ_OUT,

+LCR_DBI_CNT,

+BAT_DBI_CNT,

+LONG_DBI_CNT,

+TXACEQ_DELAY3,

+TXACEQ_DELAY2,

+TXACEQ_DELAY1,

+RXACEQ_DELAY3,

+RXACEQ_DELAY2,

+RXACEQ_DELAY1,

+RXACEQ_IN,

+TXDCCOMB_D1,

+TXDCCOMB_D2,

+TXDCSINC_OUT,

+RXACDIFF_D1,

+DC_NOTCH_1,

+DC_NOTCH_2,

+DC_NOTCH_OUT,

+DC_NOTCH_SCALED,

+V_FEED_IN,

+I_TAR,

+CONST_VLIM,

+UNITY,

+TXACNOTCH_1,

+TXACNOTCH_2,

+TXACNOTCH_OUT,

+ZSYNTH_1,

+ZSYNTH_2,

+ZSYNTH_OUT_1,

+TXACD2_1_0,

+TXACD2_1_1,

+TXACD2_1_2,

+TXACD2_1_3,

+TXACD2_1_4,

+TXACD2_1_5,

+TXACD2_1_OUT,

+TXACD2_2_0,

+TXACD2_2_1,

+TXACD2_2_2,

+TXACD2_2_3,

+TXACD2_2_4,

+TXACD2_2_5,

+TXACD2_2_OUT,

+TXACD2_3_0,

+TXACD2_3_1,

+TXACD2_3_2,

+TXACD2_3_3,

+TXACD2_3_4,

+TXACD2_3_5,

+TXACD2_3_OUT,

+RXACI2_1_1,

+RXACI2_1_2,

+RXACI2_1_3,

+RXACI2_1_4,

+RXACI2_1_OUT,

+RXACI2_2_1,

+RXACI2_2_2,

+RXACI2_2_3,

+RXACI2_2_4,

+RXACI2_2_OUT,

+RXACI2_3_1,

+RXACI2_3_2,

+RXACI2_3_3,

+RXACI2_3_4,

+RXACI2_3_OUT,

+TXACCOMP1,

+TXACCOMP_OUT,

+RXACCOMP1,

+RXACCOMP_OUT,

+RXACHPF_D1_2,

+RXACHPF_D2_1,

+RXACHPF_D2_2,

+RXACHPF_OUT,

+RXACHPF_OUT_1,

+RXACHPF_OUT_2,

+RXACEQ_OUT,

+METER_I_1,

+METER_I_OUT,

+METER_LPF_1,

+METER_LPF_2,

+METER_LPF_OUT_1,

+METER_BP_1,

+METER_BP_2,

+METER_BP_OUT,

+METER_SRC_OUT,

+PMDIFF_D1,

+PMDIFF_D2,

+RING_LPF_1,

+RING_LPF_2,

+RING_LPF_OUT,

+RING_INTERP_DIFF,

+RING_INTERP_DIFF_OUT,

+RING_INTERP_INT,

+RING_INTERP_INT_OUT,

+V_ILIM_TRACK,

+V_RFEED_TRACK,

+LF_SPEEDUP_CNT,

+DC_SPEEDUP_CNT,

+AC_SPEEDUP_CNT,

+LCR_SPEEDUP_CNT,

+CM_SPEEDUP_CNT,

+DC_SPEEDUP_MASK,

+ZSYNTH_IN,

+I_TAR_SAVE,

+V_TR_MAX,

+V_TR_MAX_TEMP,

+COUNTER_VTR,

+I_RING_AVG,

+COUNTER_IRING,

+COMP_RATIO,

+MADC_VBAT_DIV2,

+VDIFF_PK_T,

+PEAK_CNT,

+CM_DBI_CNT,

+VCM_LAST,

+VBATL_SENSE,

+VBATH_SENSE,

+VBATR_SENSE,

+BAT_SETTLE_CNT,

+VBAT_TGT,

+VBAT_REQ,

+VCM_HIRES,

+VCM_LORES,

+ILOOP1,

+ILONG2,

+ITIP1,

+IRING1,

+CAL_TEMP1,

+CAL_TEMP2,

+CAL_TEMP3,

+CAL_TEMP4,

+CAL_TEMP5,

+CAL_TEMP6,

+CAL_TEMP7,

+CMRR_DIVISOR,

+CMRR_REMAINDER,

+CMRR_Q_PTR,

+CAL_LKG_DWN_C0,

+CAL_LKG_DWN_V0,

+CAL_LKG_DWN_CN,

+CAL_LKG_DWN_VN,

+CAL_LKG_DWN_VLSB,

+CAL_LKG_DWN_ILSB,

+CAL_LKG_DWN_DACCODE,

+CAL_LKG_DWN_ICALC,

+CAL_ONHK_Z,

+CAL_LB_SETTLE,

+CAL_DECLPF_V0,

+CAL_DECLPF_V1,

+CAL_DECLPF_V2,

+CAL_GOERTZEL_V0,

+CAL_GOERTZEL_V1,

+CAL_DECLPF_Y,

+CAL_GOERTZEL_Y,

+P_HVIC,

+VBATL_MIRROR,

+VBATH_MIRROR,

+VBATR_MIRROR,

+DIAG_EX1_OUT,

+DIAG_EX2_OUT,

+DIAG_DMM_V_OUT,

+DIAG_DMM_I_OUT,

+DIAG_P,

+DIAG_LPF_V,

+DIAG_LPF_I,

+DIAG_TONE_FLAG,

+ILOOP1_LAST,

+RING_ENTRY_VOC,

+MADC_VBAT_LAST,

+DC_NOTCH_LAST,

+EZSYNTH_1,

+EZSYNTH_2,

+ZSYNTH_OUT,

+CMRR,

+CAL_SUBSTATE,

+CAL_STATE_DCDAC,

+UNUSED424,

+UNUSED425,

+UNUSED426,

+UNUSED427,

+UNUSED428,

+UNUSED429,

+UNUSED430,

+UNUSED431,

+UNUSED432,

+UNUSED433,

+UNUSED434,

+UNUSED435,

+UNUSED436,

+UNUSED437,

+UNUSED438,

+UNUSED439,

+UNUSED440,

+UNUSED441,

+UNUSED442,

+UNUSED443,

+UNUSED444,

+UNUSED445,

+UNUSED446,

+UNUSED447,

+UNUSED448,

+UNUSED449,

+UNUSED450,

+UNUSED451,

+UNUSED452,

+UNUSED453,

+UNUSED454,

+UNUSED455,

+UNUSED456,

+UNUSED457,

+UNUSED458,

+UNUSED459,

+UNUSED460,

+UNUSED461,

+UNUSED462,

+UNUSED463,

+UNUSED464,

+UNUSED465,

+UNUSED466,

+UNUSED467,

+UNUSED468,

+UNUSED469,

+UNUSED470,

+UNUSED471,

+UNUSED472,

+UNUSED473,

+UNUSED474,

+UNUSED475,

+UNUSED476,

+UNUSED477,

+UNUSED478,

+UNUSED479,

+UNUSED480,

+UNUSED481,

+UNUSED482,

+UNUSED483,

+UNUSED484,

+UNUSED485,

+UNUSED486,

+UNUSED487,

+UNUSED488,

+UNUSED489,

+UNUSED490,

+UNUSED491,

+UNUSED492,

+UNUSED493,

+UNUSED494,

+UNUSED495,

+UNUSED496,

+UNUSED497,

+UNUSED498,

+UNUSED499,

+UNUSED500,

+UNUSED501,

+UNUSED502,

+UNUSED503,

+UNUSED504,

+UNUSED505,

+UNUSED506,

+UNUSED507,

+UNUSED508,

+UNUSED509,

+UNUSED510,

+UNUSED511,

+MINUS_ONE,

+ILOOPLPF,

+ILONGLPF,

+BATLPF,

+VDIFFLPF,

+VCMLPF,

+TXACIIR_B0_1,

+TXACIIR_B1_1,

+TXACIIR_A1_1,

+TXACIIR_B0_2,

+TXACIIR_B1_2,

+TXACIIR_B2_2,

+TXACIIR_A1_2,

+TXACIIR_A2_2,

+TXACIIR_B0_3,

+TXACIIR_B1_3,

+TXACIIR_B2_3,

+TXACIIR_A1_3,

+TXACIIR_A2_3,

+TXACHPF_B0_1,

+TXACHPF_B1_1,

+TXACHPF_A1_1,

+TXACHPF_B0_2,

+TXACHPF_B1_2,

+TXACHPF_B2_2,

+TXACHPF_A1_2,

+TXACHPF_A2_2,

+TXACHPF_GAIN,

+TXACEQ_C0,

+TXACEQ_C1,

+TXACEQ_C2,

+TXACEQ_C3,

+TXACGAIN,

+RXACGAIN,

+RXACEQ_C0,

+RXACEQ_C1,

+RXACEQ_C2,

+RXACEQ_C3,

+RXACIIR_B0_1,

+RXACIIR_B1_1,

+RXACIIR_A1_1,

+RXACIIR_B0_2,

+RXACIIR_B1_2,

+RXACIIR_B2_2,

+RXACIIR_A1_2,

+RXACIIR_A2_2,

+RXACIIR_B0_3,

+RXACIIR_B1_3,

+RXACIIR_B2_3,

+RXACIIR_A1_3,

+RXACIIR_A2_3,

+ECFIR_C2,

+ECFIR_C3,

+ECFIR_C4,

+ECFIR_C5,

+ECFIR_C6,

+ECFIR_C7,

+ECFIR_C8,

+ECFIR_C9,

+ECIIR_B0,

+ECIIR_B1,

+ECIIR_A1,

+ECIIR_A2,

+DTMFDTF_B0_1,

+DTMFDTF_B1_1,

+DTMFDTF_B2_1,

+DTMFDTF_A1_1,

+DTMFDTF_A2_1,

+DTMFDTF_B0_2,

+DTMFDTF_B1_2,

+DTMFDTF_B2_2,

+DTMFDTF_A1_2,

+DTMFDTF_A2_2,

+DTMFDTF_B0_3,

+DTMFDTF_B1_3,

+DTMFDTF_B2_3,

+DTMFDTF_A1_3,

+DTMFDTF_A2_3,

+DTMFDTF_GAIN,

+DTMFLPF_B0_1,

+DTMFLPF_B1_1,

+DTMFLPF_B2_1,

+DTMFLPF_A1_1,

+DTMFLPF_A2_1,

+DTMFLPF_B0_2,

+DTMFLPF_B1_2,

+DTMFLPF_B2_2,

+DTMFLPF_A1_2,

+DTMFLPF_A2_2,

+DTMFLPF_GAIN,

+DTMFHPF_B0_1,

+DTMFHPF_B1_1,

+DTMFHPF_B2_1,

+DTMFHPF_A1_1,

+DTMFHPF_A2_1,

+DTMFHPF_B0_2,

+DTMFHPF_B1_2,

+DTMFHPF_B2_2,

+DTMFHPF_A1_2,

+DTMFHPF_A2_2,

+DTMFHPF_GAIN,

+POWER_GAIN,

+GOERTZEL_GAIN,

+MODEM_GAIN,

+HOTBIT1,

+HOTBIT0,

+ROW0_C1,

+ROW1_C1,

+ROW2_C1,

+ROW3_C1,

+COL0_C1,

+COL1_C1,

+COL2_C1,

+COL3_C1,

+ROW0_C2,

+ROW1_C2,

+ROW2_C2,

+ROW3_C2,

+COL0_C2,

+COL1_C2,

+COL2_C2,

+COL3_C2,

+SLOPE_VLIM,

+SLOPE_RFEED,

+SLOPE_ILIM,

+SLOPE_RING,

+SLOPE_DELTA1,

+SLOPE_DELTA2,

+V_VLIM,

+V_RFEED,

+V_ILIM,

+CONST_RFEED,

+CONST_ILIM,

+I_VLIM,

+DC_DAC_GAIN,

+VDIFF_TH,

+NOTCH_B0,

+NOTCH_B1,

+NOTCH_B2,

+NOTCH_A1,

+NOTCH_A2,

+ZSYNTH_B0,

+ZSYNTH_B1,

+ZSYNTH_B2,

+ZSYNTH_A1,

+ZSYNTH_A2,

+RXACHPF_B0_1,

+RXACHPF_B1_1,

+RXACHPF_A1_1,

+RXACHPF_B0_2,

+RXACHPF_B1_2,

+RXACHPF_B2_2,

+RXACHPF_A1_2,

+RXACHPF_A2_2,

+RXACHPF_GAIN,

+MASK7LSB,

+METER_LPF_B0,

+METER_LPF_B1,

+METER_LPF_B2,

+METER_LPF_A1,

+METER_LPF_A2,

+METER_SIG_0,

+METER_SIG_1,

+METER_SIG_2,

+METER_SIG_3,

+METER_SIG_4,

+METER_SIG_5,

+METER_SIG_6,

+METER_SIG_7,

+METER_SIG_8,

+METER_SIG_9,

+METER_SIG_10,

+METER_SIG_11,

+METER_SIG_12,

+METER_SIG_13,

+METER_SIG_14,

+METER_SIG_15,

+METER_BP_B0,

+METER_BP_B1,

+METER_BP_B2,

+METER_BP_A1,

+METER_BP_A2,

+PM_AMP_THRESH,

+PM_GAIN,

+RING_LPF_B0,

+RING_LPF_B1,

+RING_LPF_B2,

+RING_LPF_A1,

+RING_LPF_A2,

+LCRDBI,

+LONGDBI,

+VBAT_TIMER,

+LF_SPEEDUP_TIMER,

+DC_SPEEDUP_TIMER,

+AC_SPEEDUP_TIMER,

+LCR_SPEEDUP_TIMER,

+CM_SPEEDUP_TIMER,

+VCM_TH,

+AC_SPEEDUP_TH,

+SPR_SIG_0,

+SPR_SIG_1,

+SPR_SIG_2,

+SPR_SIG_3,

+SPR_SIG_4,

+SPR_SIG_5,

+SPR_SIG_6,

+SPR_SIG_7,

+SPR_SIG_8,

+SPR_SIG_9,

+SPR_SIG_10,

+SPR_SIG_11,

+SPR_SIG_12,

+SPR_SIG_13,

+SPR_SIG_14,

+SPR_SIG_15,

+SPR_SIG_16,

+SPR_SIG_17,

+SPR_SIG_18,

+COUNTER_VTR_VAL,

+CONST_028,

+CONST_032,

+CONST_038,

+CONST_046,

+COUNTER_IRING_VAL,

+GAIN_RING,

+RING_HYST,

+COMP_Z,

+CONST_115,

+CONST_110,

+CONST_105,

+CONST_100,

+CONST_095,

+CONST_090,

+CONST_085,

+V_RASUM_IDEAL,

+CONST_ONE,

+VCM_OH,

+VCM_RING,

+VCM_HYST,

+VOV_GND,

+VOV_BAT,

+VOV_RING_BAT,

+CM_DBI,

+RTPER,

+P_TH_HVIC,

+P_TH_Q1256,

+P_TH_Q34,

+COEF_P_HVIC,

+COEF_P_OFFLD,

+COEF_Q34,

+R_OFFLOAD,

+R_63,

+BAT_HYST,

+BAT_DBI,

+VBATL_EXPECT,

+VBATH_EXPECT,

+VBATR_EXPECT,

+BAT_SETTLE,

+VBAT_IRQ_TH,

+MADC_VTIPC_OS,

+MADC_VRINGC_OS,

+MADC_VBAT_OS,

+MADC_VLONG_OS,

+MADC_VBLKRNG_OS,

+MADC_IBLKRNG_OS,

+MADC_ILONG_OS,

+MADC_ISNS_STDBY_OS,

+MADC_ISNS_OS,

+MADC_ILOOP_OS,

+MADC_SCALE_ILOOP,

+MADC_VBLKRNG_DC,

+MADC_IBLKRNG_DC,

+DC_ADC_OS,

+CAL_UNITY,

+CAL_CMRR_N,

+CAL_CMRR_NINV,

+ACADC_OFFSET,

+ACDAC_OFFSET,

+CAL_DCDAC_CODE,

+CAL_DCDAC_15MA,

+CAL_LKG_TSETTLE,

+CAL_LKG_IREF100,

+CAL_LKG_LIM100UA,

+CAL_LKG_VREF25,

+CAL_LKG_VLSB_0_INV,

+CAL_LKG_RDCSNS_EFF,

+CAL_LKG_RDCOFF_EFF,

+CAL_LKG_CODE_OS,

+CAL_LKG_VMAX_THR,

+CAL_LB_TSQUELCH,

+CAL_LB_TCHARGE,

+CAL_LB_TSETTLE0,

+CAL_GOERTZEL_DLY,

+CAL_GOERTZEL_ALPHA,

+CAL_DECLPF_K,

+CAL_DECLPF_B1,

+CAL_DECLPF_B2,

+CAL_DECLPF_A1,

+CAL_DECLPF_A2,

+CAL_ACADC_THRL,

+CAL_ACADC_THRH,

+CAL_ACADC_TSETTLE,

+DTROW0TH,

+DTROW1TH,

+DTROW2TH,

+DTROW3TH,

+DTCOL0TH,

+DTCOL1TH,

+DTCOL2TH,

+DTCOL3TH,

+DTFTWTH,

+DTRTWTH,

+DTROWRTH,

+DTCOLRTH,

+DTROW2HTH,

+DTCOL2HTH,

+DTMINPTH,

+DTHOTTH,

+RXPWR,

+TXPWR,

+RXMODPWR,

+TXMODPWR,

+FSKFREQ0,

+FSKFREQ1,

+FSKAMP0,

+FSKAMP1,

+FSK01,

+FSK10,

+VOCDELTA,

+VOCLTH,

+VOCHTH,

+RINGOF,

+RINGFR,

+RINGAMP,

+RINGPHAS,

+RTDCTH,

+RTACTH,

+RTDCDB,

+RTACDB,

+RTCOUNT,

+LCROFFHK,

+LCRONHK,

+LCRMASK,

+LCRMASK_POLREV,

+LCRMASK_STATE,

+LCRMASK_LINECAP,

+LONGHITH,

+LONGLOTH,

+IRING_LIM,

+RRD_DELAY,

+RRD_DELAY2,

+DIAG_LPF_8K,

+DIAG_LPF_128K,

+DIAG_INV_N,

+DIAG_GAIN,

+DIAG_G_CAL,

+DIAG_OS_CAL,

+SPR_GAIN_TRIM,

+MADC_VBAT_HYST,

+AC_DAC_GAIN,

+STDBY_THRLO,

+STDBY_THRHI,

+AC_DAC_GAIN0,

+EZSYNTH_B0,

+EZSYNTH_B1,

+EZSYNTH_B2,

+EZSYNTH_A1,

+EZSYNTH_A2,

+AC_ADC_GAIN,

+UNUSED881,

+UNUSED882,

+UNUSED883,

+UNUSED884,

+UNUSED885,

+UNUSED886,

+UNUSED887,

+UNUSED888,

+UNUSED889,

+UNUSED890,

+UNUSED891,

+UNUSED892,

+UNUSED893,

+UNUSED894,

+UNUSED895,

+VOV_RING_GND,

+P_TH_OFFLD,

+UNUSED898,

+UNUSED899,

+UNUSED900,

+ADAP_RING_MIN_I,

+UNUSED902,

+UNUSED903,

+UNUSED904,

+UNUSED905,

+RXACGAIN_SAVE,

+UNUSED907,

+UNUSED908,

+UNUSED909,

+UNUSED910,

+UNUSED911,

+UNUSED912,

+UNUSED913,

+UNUSED914,

+UNUSED915,

+UNUSED916,

+UNUSED917,

+UNUSED918,

+UNUSED919,

+UNUSED920,

+UNUSED921,

+UNUSED922,

+UNUSED923,

+UNUSED924,

+UNUSED925,

+UNUSED926,

+UNUSED927,

+UNUSED928,

+UNUSED929,

+UNUSED930,

+UNUSED931,

+UNUSED932,

+UNUSED933,

+UNUSED934,

+UNUSED935,

+UNUSED936,

+UNUSED937,

+UNUSED938,

+UNUSED939,

+UNUSED940,

+UNUSED941,

+UNUSED942,

+UNUSED943,

+UNUSED944,

+UNUSED945,

+UNUSED946,

+UNUSED947,

+UNUSED948,

+UNUSED949,

+UNUSED950,

+UNUSED951,

+UNUSED952,

+UNUSED953,

+UNUSED954,

+UNUSED955,

+UNUSED956,

+UNUSED957,

+UNUSED958,

+UNUSED959,

+UNUSED960,

+UNUSED961,

+UNUSED962,

+UNUSED963,

+UNUSED964,

+UNUSED965,

+UNUSED966,

+UNUSED967,

+UNUSED968,

+UNUSED969,

+UNUSED970,

+UNUSED971,

+UNUSED972,

+UNUSED973,

+UNUSED974,

+UNUSED975,

+UNUSED976,

+UNUSED977,

+UNUSED978,

+UNUSED979,

+UNUSED980,

+UNUSED981,

+UNUSED982,

+UNUSED983,

+UNUSED984,

+UNUSED985,

+UNUSED986,

+UNUSED987,

+UNUSED988,

+UNUSED989,

+UNUSED990,

+UNUSED991,

+UNUSED992,

+UNUSED993,

+UNUSED994,

+UNUSED995,

+UNUSED996,

+UNUSED997,

+UNUSED998,

+UNUSED999,

+UNUSED1000,

+UNUSED1001,

+UNUSED1002,

+UNUSED1003,

+UNUSED1004,

+UNUSED1005,

+UNUSED1006,

+UNUSED1007,

+UNUSED1008,

+UNUSED1009,

+UNUSED1010,

+UNUSED1011,

+UNUSED1012,

+UNUSED1013,

+UNUSED1014,

+UNUSED1015,

+UNUSED1016,

+UNUSED1017,

+UNUSED1018,

+UNUSED1019,

+UNUSED1020,

+UNUSED1021,

+UNUSED1022,

+UNUSED1023

+};

+

+enum {

+    PD_BIAS = 1413,

+    PD_VBAT_SNS = 1418,

+    MADC_LOOP_MAN = 1445,

+    HVIC_CNTL_MAN = 1451,

+    CAL_TRNRD_DACT = 1458,

+    CAL_TRNRD_DACR,

+    CMDAC_FWD = 1476,

+    CMDAC_REV

+};

+

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice.h
new file mode 100755
index 0000000..535c883
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice.h
@@ -0,0 +1,663 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: si_voice.h 3088 2011-09-13 15:12:43Z cdp $

+**

+** si_voice.h

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file for the ProSLIC driver.

+**

+** Dependancies:

+** si_voice_datatypes.h

+**

+*/

+

+#ifndef SI_VOICE_H

+#define SI_VOICE_H

+

+#include "proslic_api_config.h"

+#include "si_voice_ctrl.h"

+#include "si_voice_timer_intf.h"

+

+

+

+/** @defgroup SIVOICE SiVoice definitions

+

+ * @{

+ */

+/*****************************************************************************/

+/** @defgroup CHIPFAM Chip family definitions 

+ * @{

+ */

+#define SI321X_TYPE 0    /**< Single channel legacy chipsets - SI3210, SI3215, SI3216 */

+#define SI324X_TYPE 1    /**< Quad channel chipset */

+#define SI3220_TYPE 2    /**< Dual Channel chipset */

+#define SI3226_TYPE 3    /**< Dual channel chipset */

+#define SI3217X_TYPE 4   /**< Single channel chipset*/

+#define SI3226X_TYPE 5   /**< Dual channel chipset */

+#define SI3050_TYPE 20   /**< Single channel FXO chipset */

+

+/** @} CHIPFAM */

+/*****************************************************************************/

+

+

+/* 

+* Workaroud for building on windows systems

+*/

+

+#ifdef RC_NONE

+#undef RC_NONE

+#endif

+

+#define SIVOICE_RC_NONE RC_NONE

+

+/**

+* This is the main Silicon Labs control interface object. do not access directly!

+*/

+typedef struct	{

+		void *hCtrl;                                /**< user provided SPI/GCI structure */

+		ctrl_Reset_fptr Reset_fptr;                 /**< user provided reset function */

+		ctrl_WriteRegister_fptr WriteRegister_fptr; /**< user provided SPI/GCI write register function */

+		ctrl_ReadRegister_fptr ReadRegister_fptr;   /**< user provided SPI/GI read register function */

+		ctrl_WriteRAM_fptr WriteRAM_fptr;           /**< ProSLIC only - user provided SPI/GCI read RAM/Indirect register function */

+		ctrl_ReadRAM_fptr ReadRAM_fptr; /**< ProSLIC only*/

+		ctrl_Semaphore_fptr Semaphore_fptr; /**< ProSLIC only*/

+		void *hTimer;/**< user provided Timer data structure */

+		system_delay_fptr Delay_fptr; /**< user supplied mSec delay function */

+		system_timeElapsed_fptr timeElapsed_fptr; /**< user provided mSec time elapsed function */

+		system_getTime_fptr getTime_fptr; /**< user provided timestamp function */

+		int usermodeStatus; /**< ProSLIC only*/

+} SiVoiceControlInterfaceType;

+

+

+typedef enum {

+	SI3210, 

+	SI3215,

+	SI3216,

+	SI3211, 	

+	SI3212,

+ 	SI3210M,

+ 	SI3215M,

+ 	SI3216M,

+	SI3240,

+	SI3241,

+	SI3242,

+	SI3243,

+	SI3245,

+	SI3244,

+	SI3246,

+	SI3247,

+	SI3220,

+	SI3225,

+	SI3226,

+	SI3227,

+	SI32171,

+	SI32172,

+	SI32174,

+	SI32175,

+	SI32176,

+	SI32177,

+	SI32178,

+	SI32179,

+    SI32260,

+    SI32261,

+    SI32262,

+    SI32263,

+    SI32264,

+    SI32265,

+    SI32266,

+    SI32267,

+    SI32268,

+    SI32269,

+    SI32360,

+    SI32361,

+    SI3050 = 100,

+	UNSUPPORTED_PART_NUM = 255

+}partNumberType;

+

+/**

+* Chip revision definition for easier readability in the source code

+*/

+typedef enum {

+	A,

+	B,

+	C,

+	D,

+	E,

+	F,

+	G

+}revisionType ;

+

+

+typedef enum {

+    UNKNOWN, /**< Channel type has not been initalized or is still unknown */

+	PROSLIC, /**< Channel type is a ProSLIC/FXS */

+	DAA      /**< Channel type is a DAA/FXO */

+} channelTypeType;

+

+/**

+* These are the error codes for ProSLIC failures

+*/

+typedef enum {

+    RC_IGNORE = 0,         

+    RC_NONE= 0,           /**< Means the function did not encounter an error */

+	RC_TEST_PASSED = 0,

+	RC_TEST_FAILED = 1,

+    RC_COMPLETE_NO_ERR = 1,   /**< A test completed, no error detected */

+    RC_POWER_ALARM_Q1,

+    RC_POWER_ALARM_Q2,

+    RC_POWER_ALARM_Q3,

+    RC_POWER_ALARM_Q4,

+    RC_POWER_ALARM_Q5,

+    RC_POWER_ALARM_Q6,

+    RC_SPI_FAIL,         /**< SPI Communications failure */

+    RC_POWER_LEAK,

+    RC_VBAT_UP_TIMEOUT,

+    RC_VBAT_OUT_OF_RANGE,

+    RC_VBAT_DOWN_TIMEOUT,

+    RC_TG_RG_SHORT,

+    RC_CM_CAL_ERR,

+    RC_RING_FAIL_INT,

+    RC_CAL_TIMEOUT,

+    RC_PATCH_ERR,

+    RC_BROADCAST_FAIL,           /**< Broadcast unavailable for requested operation */

+    RC_UNSUPPORTED_FEATURE,      /**< Feature is not supported by the chipset*/

+    RC_CHANNEL_TYPE_ERR,         /**< Channel type does not support called function */

+    RC_GAIN_DELTA_TOO_LARGE,     /**< Requested gain delta too large */

+    RC_GAIN_OUT_OF_RANGE,        /**< Gain requested exceeds range */

+    RC_POWER_ALARM_HVIC,         /**< Power alarm on HVIC */

+    RC_POWER_ALARM_OFFLD,        /**< Power alarm on offload transistor */

+    RC_THERMAL_ALARM_HVIC,       /**< Thermal alarm detected */

+    RC_NO_MEM,                   /**< Out of memory */

+    RC_INVALID_GEN_PARAM,        /**< Invalid general parameter */

+    RC_LINE_IN_USE,              /**< Line is in use (LCS detected) */

+    RC_RING_V_LIMITED,           /**< Ringer voltage limited - signal may be clipped */

+    RC_PSTN_CHECK_SINGLE_FAIL,   /**< PSTN detect single current exceeds limit */

+    RC_PSTN_CHECK_AVG_FAIL,      /**< PSTN detect average current exceeds limit */

+    RC_VDAA_ILOOP_OVLD,          /**< Overload detected */

+    RC_UNSUPPORTED_OPTION,       /**< Function parameter is not supported at this time */

+    RC_FDT_TIMEOUT,              /**< Timeout waiting for valid frame detect */

+    RC_PSTN_OPEN_FEMF,           /**< Detected FEMF, device left in open state */

+    RC_VDAA_PAR_HANDSET_DET,     /**< Parallel handset detected */

+    RC_VDAA_PAR_HANDSET_NOT_DET,/**< Parallel handset not detected */

+    RC_PATCH_RAM_VERIFY_FAIL,  /**< Patch RAM verification failure */

+    RC_PATCH_ENTRY_VERIFY_FAIL,/**< Patch entry table verification failure */ 

+    RC_UNSUPPORTED_DEVICE_REV, /**< Device revision not supported */

+	RC_INVALID_PATCH,          /**< No patch for selected options */

+	RC_INVALID_PRESET,         /**< Invalid Preset value */

+	RC_TEST_DISABLED,          /**< Test Not enabled */

+	RC_RING_START_FAIL,        /**< Ringing failed to start */

+    RC_REINIT_REQUIRED = 255   /**< Soft Reset Required */

+} errorCodeType;

+

+

+/**

+* Generic BOM option tags - please refer to your PCB design

+* for which design you're using.

+*/

+typedef enum {

+	DEFAULT,                /**< Default design */

+	SI321X_HV,              /**< SI321x High voltage */

+    BO_DCDC_FLYBACK,        /**< DC power supply: flyback design */

+    BO_DCDC_QCUK,           /**< DC power supply: quasi-cuk design */

+    BO_DCDC_BUCK_BOOST,     /**< DC power supply: buck boost design */

+    BO_DCDC_LCQCUK,         /**< DC power supply: low-cost quasi-cuk design */

+	BO_DCDC_P_BUCK_BOOST_5V /**< DC power supply:  pmos buck-boost 5v design */

+} bomOptionsType;

+

+/**

+* Initialization options to allow init flow and/or content to be

+* altered at runtime

+*/

+typedef enum {

+	INIT_NO_OPT,	     /**<  No initialization option */

+	INIT_REINIT,         /**<  Reinitialization option */

+	INIT_NO_CAL,         /**<  Skip calibration only */

+	INIT_NO_PATCH_LOAD   /**<  Skip patch load */

+} initOptionsType;

+

+/**

+** This is the main Voice device object

+*/

+typedef struct	{

+		SiVoiceControlInterfaceType *ctrlInterface; /**< How do we talk to the system? User supplied functions are connected here */

+		revisionType chipRev; /**< What revision is the chip? */

+		partNumberType chipType; /**< What member of the particular family is this chip? */

+		uInt8 lsRev; /**< DAA: what rev is the line side chip? */

+		uInt8 lsType; /**< DAA: what type is the line side chip */

+		int usermodeStatus; /**< Used for patch code */

+} SiVoiceDeviceType;

+

+typedef SiVoiceDeviceType *SiVoiceDeviceType_ptr; /**< Shortcut typedef */

+

+

+/**

+** This is the main ProSLIC channel object

+*/

+typedef struct	{

+		SiVoiceDeviceType_ptr deviceId; /**< Information about the device associated with this channel */

+		uInt8 channel; /**< Which channel is this device? This is a system parameter meaning if you have 2 dual channel devices in your system, this number would then typically go from 0-3 */

+		channelTypeType channelType; /**< Is this a ProSLIC or a DAA */

+		errorCodeType error;  /**< Storage for the current error state - used only for APIs that don't return back an error */

+		int debugMode; /**< Are we debugging on this channel? */

+		int channelEnable; /**<  is the channel enabled or not? If not, this channel is not initialized */

+		bomOptionsType bomOption; /**< Device/PCB specific */

+} SiVoiceChanType;

+

+

+typedef SiVoiceChanType *SiVoiceChanType_ptr;

+

+/*****************************************************************************/

+/** @defgroup SIVOICE_IF_CFG  SiVoice System control interface functions

+ *

+ * These functions are used by the ProSLIC API to access system resources

+ * such as SPI/GCI access, memory allocation/deallocation and timers.

+ *

+ * @{

+ */

+/*****************************************************************************/

+/** @defgroup SIVOICE_MEMORY_IF SiVoice Memory allocation/deallocation 

+ *

+ * These functions dynamically allocate and deallocate memory for the given

+ * structures. malloc() and memset() are called for allocation and free() is

+ * called for deallocation.  These functions are typically called during 

+ * initialization of the API and at the tear down of the API.  If customers

+ * prefer to use statically allocated structures, then they must ensure that

+ * the strucutre elements are zero'ed out.

+ * 

+ * @{

+ */

+

+/**

+ @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] pCtrlIntf - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_createControlInterface (SiVoiceControlInterfaceType **pCtrlIntf);

+

+/**

+ @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] pCtrlIntf  - the structure to destroy/deallocate

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_destroyControlInterface (SiVoiceControlInterfaceType **pCtrlIntf);

+

+/**

+ @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] pDev - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_createDevice (SiVoiceDeviceType **pDev);

+

+/**

+ @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] pDev - the structure to destroy/deallocate

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_destroyDevice (SiVoiceDeviceType **pDev);

+

+/**

+ @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] pChan - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_createChannel (SiVoiceChanType_ptr *pChan);

+

+/**

+ @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] pChan - the structure to destroy/deallocate

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_destroyChannel (SiVoiceChanType_ptr *pChan);

+/** @} SIVOICE_MEMORY_IF */

+

+/*****************************************************************************/

+/** @defgroup SIVOICE_IO SiVoice SPI/GCI access routines

+ * This group of functions are used to associcate the transport mechanism (SPI, GCI) functions with the API.  The actual

+ * functions being references are normally implemented by the customer for their particualr OS and platform.

+ *

+ * @{

+ */

+

+/**

+ @brief

+ *  Associate a interface object with a user supplied datastructure.  This 

+ *  structure is passed to all the I/O routines that the ProSLIC API calls.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied structure with.

+ * @param[in] *hCtrl - the user supplied structure that is passed to the IO functions.

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_setControlInterfaceCtrlObj (SiVoiceControlInterfaceType *pCtrlIntf, void *hCtrl);

+

+/**

+ @brief

+ *  Associate a interface object with the reset function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] Reset_fptr - the reset function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_setControlInterfaceReset (SiVoiceControlInterfaceType *pCtrlIntf, ctrl_Reset_fptr Reset_fptr);

+

+/**

+ @brief

+ *  Associate a interface object with the register write function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] WriteRegister_fptr - the register write function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_setControlInterfaceWriteRegister (SiVoiceControlInterfaceType *pCtrlIntf, ctrl_WriteRegister_fptr WriteRegister_fptr);

+

+/**

+ @brief

+ *  Associate a interface object with the register read function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] ReadRegister_fptr- the register read function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_setControlInterfaceReadRegister (SiVoiceControlInterfaceType *pCtrlIntf, ctrl_ReadRegister_fptr ReadRegister_fptr);

+

+/**

+ @brief

+ *  Associate a interface object with the write RAM function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] WriteRAM_fptr - the reset function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_setControlInterfaceWriteRAM (SiVoiceControlInterfaceType *pCtrlIntf, ctrl_WriteRAM_fptr WriteRAM_fptr);

+

+/**

+ @brief

+ *  Associate a interface object with the read RAM function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in]  ReadRAM_fptr - the read RAM function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_setControlInterfaceReadRAM (SiVoiceControlInterfaceType *pCtrlIntf, ctrl_ReadRAM_fptr ReadRAM_fptr);

+/** @} SIVOICE_IO */

+

+/*****************************************************************************/

+/** @defgroup SIVOICE_TIMER SiVoice Timer functions 

+ *

+ * This group of functions associates the customer supplied timer routines with 

+ * the ProSLIC API. Please note, for most applications, only the delay routine 

+ * is required.  The other routines are needed for the pulse digit API.

+ * @{

+ */

+

+/**

+ @brief

+ *  This function associates a timer object - which is user defined, but it is 

+ *  used with ALL channels of the particular control interface.

+ *

+ *  @param[in] pCtrlIntf which control interface to associate the given timer object with.

+ *  @param[in] *hTimer - the timer ojbect that is passed to all timer functions.

+ *  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ *  @sa SiVoice_setControlInterfaceDelay SiVoice_setControlInterfaceTimeElapsed SiVoice_setControlInterfaceGetTime PROSLIC_TIMER

+ */

+

+int SiVoice_setControlInterfaceTimerObj (SiVoiceControlInterfaceType *pCtrlIntf, void *hTimer);

+

+/** 

+ @brief

+ *  Associate a timer delay function with a given control interface.  The 

+ *  delay function takes in an argument of the timer object and the time in mSec

+ *  and delays the thread/task for at least the time requested.

+ *

+ * @param[in] pCtrlIntf - which control interface to associate the function with.

+ * @param[in] Delay_fptr - the pointer to the delay function.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ *  @sa SiVoice_setControlInterfaceTimerObj SiVoice_setControlInterfaceTimeElapsed SiVoice_setControlInterfaceGetTime PROSLIC_TIMER

+ */

+

+int SiVoice_setControlInterfaceDelay (SiVoiceControlInterfaceType *pCtrlIntf, system_delay_fptr Delay_fptr);

+

+/** 

+ *  Description:

+ *   Associate a time elapsed function with a given control interface.  The

+ *   time elapsed function uses the values from the function specified in

+ *   @ref SiVoice_setControlInterfaceGetTime and computes the delta time

+ *   in mSec.

+ *  @param[in] pCtrlIntf - which control interface to associate the function with.

+ *  @param[in] timeElapsed_fptr - the pointer to the elapsed time function.

+ *  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *  @sa SiVoice_setControlInterfaceTimerObj SiVoice_setControlInterfaceGetTime SiVoice_setControlInterfaceDelay PROSLIC_TIMER

+ */

+

+int SiVoice_setControlInterfaceTimeElapsed (SiVoiceControlInterfaceType *pCtrlIntf, system_timeElapsed_fptr timeElapsed_fptr);

+

+/** 

+ *  Description:

+ *   Associate a time get function with a given control interface.  The

+ *   time get function returns a value in a form of a void pointer that 

+ *   is suitable to be used with the function specified in @ref SiVoice_setControlInterfaceTimeElapsed .

+ *   This is typically used as a timestamp of when an event started. The resolution needs to be in terms

+ *   of mSec.

+ *

+ *  @param[in] pCtrlIntf - which control interface to associate the function with.

+ *  @param[in] getTime_fptr -  the pointer to the get time function.

+ *  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *  @sa SiVoice_setControlInterfaceTimerObj SiVoice_setControlInterfaceTimeElapsed SiVoice_setControlInterfaceDelay PROSLIC_TIMER

+ */

+

+int SiVoice_setControlInterfaceGetTime (SiVoiceControlInterfaceType *pCtrlIntf, system_getTime_fptr getTime_fptr);

+

+/** @} SIVOICE_TIMER */

+

+/*****************************************************************************/

+/** @defgroup SIVOICE_PROC_CONTROL SiVoice Process control

+ * @{

+ */

+

+/**

+ @brief

+ *  This function assoicates a user defined semaphore/critical section

+ *  function with the given interface.

+ *

+ * @param[in,out] pCtrlIntf the interface to assoicate the function with.

+ * @param[in] semaphore_fptr - the function pointer for semaphore control.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int SiVoice_setControlInterfaceSemaphore (SiVoiceControlInterfaceType *pCtrlIntf, ctrl_Semaphore_fptr semaphore_fptr);

+

+/** @} SIVOICE_PROC_CONTROL */

+/*****************************************************************************/

+/** @} SIVOICE_IF_CFG*/

+/*****************************************************************************/

+/** @defgroup SIVOICE_INIT Initialization routines

+ * @{

+ */

+

+/**

+ @brief

+ *  This function initializes the various channel structure elements.  

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ * @param[in,out] hProslic - which channel to initialize.

+ * @param[in] channel - Which channel index is this.  For example, for a 4 channel system, this would typically range from 0 to 3.

+ * @param[in] chipType - chipset family type for example @ref SI321X_TYPE or @ref SI3217X_TYPE

+ * @param[in] pDeviceObj - Device structure pointer associated with this channel

+ * @param[in] pCtrlIntf - Control interface associated with this channel

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_SWInitChan

+ */

+

+int SiVoice_SWInitChan (SiVoiceChanType_ptr hProslic,int channel,int chipType, SiVoiceDeviceType *pDeviceObj, SiVoiceControlInterfaceType *pCtrlIntf);

+

+/**

+ @brief

+ * This function calls the user supplied reset function to put and take out the channel from reset. This is

+ * typically done during initialization and may be assumed to be a "global" reset - that is 1 reset per

+ * daisychain vs. 1 per device.

+ *

+ * @note This function can take more than 500 mSec to complete.

+ *

+ * @param[in] pChan - which channel to reset, if a "global reset", then any channel on the daisy chain is sufficient.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int SiVoice_Reset (SiVoiceChanType_ptr pChan);

+

+/** @} SIVOICE_INIT */

+

+/*****************************************************************************/

+/** @defgroup SIVOICE_DEBUG Debug

+ * @{

+ */

+

+/**

+ @brief

+ * This function enables or disables the debug mode, assuming @ref ENABLE_DEBUG is set in the configuration file.

+ *

+ * @param[in] pChan - which channel to set the debug flag.

+ * @param[in] debugEn - 0 = Not set, 1 = set.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int SiVoice_setSWDebugMode (SiVoiceChanType_ptr pChan, int debugEn);

+

+/** @} SIVOICE_DEBUG */

+

+/*****************************************************************************/

+/** @defgroup SIVOICE_ERROR Return code functions

+ * @{

+ */

+

+/** 

+ @brief

+ * This function returns the error flag that may be set by some function in where

+ * @ref errorCodeType is not returned.  

+ *

+ * @note For functions that DO return errorCodeType, the return value here is undefined.

+ *

+ * @param[in] pChan - which channel to clear the error flag

+ * @param[in,out] *error - The current value of error flag.  

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa SiVoice_clearErrorFlag

+ */

+

+int SiVoice_getErrorFlag (SiVoiceChanType_ptr pChan, int *error);

+

+/**

+ @brief

+ *  This function clears the error flag that may be set by some function in where

+ *  @ref errorCodeType is not returned.

+ *

+ * @param[in,out] pChan - which channel to clear the error flag

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa SiVoice_getErrorFlag

+ */

+

+int SiVoice_clearErrorFlag (SiVoiceChanType_ptr pChan);

+

+/** @} SIVOICE_ERROR */

+

+/*****************************************************************************/

+/** @defgroup SIVOICE_ENABLE Enable/disable channels (for init)

+ * @{

+ */

+/**

+ @brief

+ *  This function sets the channel enable status.  If NOT set, then when

+ *  the various initialization routines such as @ref SiVoice_SWInitChan is called,

+ *  then this particular channel will NOT be initialized.

+ *

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ * @param[in,out] pChan - which channel to return the status.

+ * @param[in] chanEn - The new value of the channel enable field. 0 = NOT enabled, 1 = enabled.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa SiVoice_getChannelEnable

+ */

+

+int SiVoice_setChannelEnable (SiVoiceChanType_ptr pChan, int chanEn);

+

+/**

+ @brief

+ *  This function returns back if the channel is enabled or not.

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ * @param[in] pChan - which channel to return the status.

+ * @param[in,out] chanEn* - The current value of if the channel is enabled. 0 = NOT enabled, 1 = enabled.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa SiVoice_setChannelEnable

+ */

+

+int SiVoice_getChannelEnable (SiVoiceChanType_ptr pChan, int* chanEn);

+

+/** @} SIVOICE_ENABLE */

+/*****************************************************************************/

+/** @} SIVOICE */

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_ctrl.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_ctrl.h
new file mode 100755
index 0000000..ef6437e
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_ctrl.h
@@ -0,0 +1,122 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: si_voice_ctrl.h 2009 2010-06-11 21:26:54Z nizajerk $

+**

+** si_voice_ctrl.h

+** SPI driver header file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** File Description:

+** This is the header file for the control driver used 

+** in the ProSLIC demonstration code.

+**

+** Dependancies:

+** si_voice_datatypes.h 

+**

+*/

+#ifndef CTRL_H

+#define CTRL_H

+

+/** @defgroup PROSLIC_CUSTOMER_APIS Customer implemented functions

+ * This section has documentation related to APIs that the customer

+ * needs to implement to allow the ProSLIC API to function correctly.

+ *

+ * @note Please note, in addition to the functions mentioned here, the

+ * customer will need to review/modify si_voice_datatypes.h to match

+ * the native datatypes of their system.

+ *

+ * @{

+ */

+/*****************************************************************************/

+/** @defgroup PROSLIC_CUSTOMER_CONTROL Customer implemented control functions

+ * This group of function pointer prototypes need to be implemented by the 

+ * customer in order for the ProSLIC API to function correctly.  These functions

+ * need to be associated with the API by the functions documented in @ref SIVOICE_IO

+ * @{

+ */

+

+/**

+* @brief

+* Sets/clears the reset pin of all the ProSLICs/VDAAs 

+*

+* @param[in] *hCtrl - which interface to reset (this is a customer supplied structure)

+* @param[in] in_reset -  0 = Take the device out of reset, 1 = place the device(s) in reset

+* @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*/

+

+typedef int (*ctrl_Reset_fptr) (void *hCtrl, int in_reset);

+

+/**

+* @brief 

+* Register write function pointer

+*

+* @param[in] *hCtrl - which interface to communicate through (this is a customer supplied structure)

+* @param[in] channel - ProSLIC channel to write to (this is the value passed is the same as found in @ref SiVoice_SWInitChan)

+* @param[in] regAddr -  Address of register to write

+* @param[in] data - data to write to register

+* @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*

+*/

+

+typedef int (*ctrl_WriteRegister_fptr) (void *hCtrl, uInt8 channel, uInt8 regAddr, uInt8 data);

+

+/**

+* @brief 

+* RAM write function pointer

+*

+* @param[in] *hCtrl - which interface to communicate through (this is a customer supplied structure)

+* @param[in] channel - ProSLIC channel to write to (this is the value passed is the same as found in @ref SiVoice_SWInitChan)

+* @param[in] ramAddr - Address of the RAM location to write

+* @param[in] ramData - data to write to the RAM location

+* @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*

+*/

+

+typedef int (*ctrl_WriteRAM_fptr) (void *hCtrl, uInt8 channel, uInt16 ramAddr, ramData data);

+

+/**

+* @brief 

+* Register read function pointer

+*

+* @param[in] *hCtrl - which interface to communicate through (this is a customer supplied structure)

+* @param[in] channel - ProSLIC channel to read from (this is the value passed is the same as found in @ref SiVoice_SWInitChan)

+* @param[in] regAddr -  Address of register to read from

+* @retval uInt8 - the value read. If an error occurs, this value is undefined.

+*/

+

+typedef uInt8 (*ctrl_ReadRegister_fptr) (void *hCtrl, uInt8 channel, uInt8 regAddr);

+

+/**

+* @brief 

+* RAM read function pointer

+*

+* @param[in] *hCtrl - which interface to communicate through (this is a customer supplied structure)

+* @param[in] channel - ProSLIC channel to read from (this is the value passed is the same as found in @ref SiVoice_SWInitChan)

+* @param[in] ramAddr - Address of the RAM location to read from

+* @retval ramData - the value read. If an error occurs, this value is undefined.

+*/

+

+typedef ramData (*ctrl_ReadRAM_fptr) (void *hCtrl, uInt8 channel, uInt16 ramAddr);

+

+/**

+ * @brief

+ *  Critical Section/Semaphore function pointer

+ *

+* @param[in] *hCtrl - which interface to communicate through (this is a customer supplied structure)

+* @param[in] in_critical_section - request to lock the critical section 1 = lock, 0 = unlock

+* @retval 1 = success, 0 = failed

+*/

+

+typedef int (*ctrl_Semaphore_fptr) (void *hCtrl, int in_critical_section);

+

+/** @} PROSLIC_CUSTOMER_CONTROL */

+/** @} */

+#endif

+

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_datatypes.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_datatypes.h
new file mode 100755
index 0000000..ce6a9a2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_datatypes.h
@@ -0,0 +1,78 @@
+/*

+** Copyright (c) 2007-2010 by Silicon Laboratories

+**

+** $Id: si_voice_datatypes_example.h 425 2009-02-20 21:14:41Z cdp@SILABS.COM $

+**

+** si_voice_datatypes.h

+** ProSLIC datatypes file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file that contains

+** type definitions for the data types

+** used in the demonstration code.

+**

+** Dependancies:

+** 

+**

+*/

+#ifndef DATATYPES_H

+#define DATATYPES_H

+

+#ifndef TRUE

+#define TRUE (1)

+#endif

+#ifndef FALSE

+#define FALSE (0)

+#endif

+

+#ifndef NULL

+#define NULL ((void *) 0)

+#endif

+

+#if defined(__linux__) && defined(__KERNEL__)

+#include <linux/types.h>

+typedef u_int8_t           BOOLEAN;

+typedef int8_t			    int8;

+typedef u_int8_t            uInt8;

+typedef uInt8				uChar;

+typedef int16_t  			int16;

+typedef u_int16_t           uInt16;

+typedef int32_t             int32;

+typedef u_int32_t   		uInt32;

+#elif defined(WIN32)

+#include <wtypes.h>

+typedef char				int8;

+typedef unsigned char		uInt8;

+typedef uInt8				uChar;

+typedef short int			int16;

+typedef unsigned short int	uInt16;

+typedef long				int32;

+typedef unsigned long		uInt32;

+#else

+#include <stdint.h>

+typedef uint8_t           BOOLEAN;

+typedef int8_t			    int8;

+typedef uint8_t            uInt8;

+typedef uint8_t				uChar;

+typedef int16_t  			int16;

+typedef uint16_t           uInt16;

+typedef int32_t             int32;

+typedef uint32_t   		uInt32;

+#endif

+/*

+** RAM data 

+*/

+

+#define ramData uInt32

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_timer_intf.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_timer_intf.h
new file mode 100755
index 0000000..85682fb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/si_voice_timer_intf.h
@@ -0,0 +1,106 @@
+/*

+** Copyright (c) 2007 by Silicon Laboratories

+**

+** $Id: si_voice_timer_intf.h 2005 2010-06-03 21:01:04Z nizajerk $

+**

+** si_voice_timer_intf.h

+** System specific functions header file

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** File Description:

+** This is the header file for the system specific functions like timer functions.

+**

+**

+*/

+

+

+#ifndef TIMER_INTF_H

+#define TIMER_INTF_H

+

+/** @addtogroup PROSLIC_CUSTOMER_APIS

+ * @{

+ * @defgroup PROSLIC_CUSTOMER_TIMER Customer implemented timer functions

+ * This section has documentation related to timers: delays and timestamps.  The void * is a customer

+ * supplied timer data structure that the user specifies in @ref SiVoice_setControlInterfaceTimerObj. 

+ * These functions need to be associated with the functions documented in @ref SIVOICE_TIMER

+ *

+ * @note For the majority of implementations, the only function that is required is the delay function.

+ *

+ * @{

+ */

+

+/** 

+ * @brief

+ * System time delay function pointer 

+ * 

+ * @param[in] hTimer - the system timer object

+ * @param[in] timeInMS - number of mSec to suspend the task/thread executing.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+*/

+

+typedef int (*system_delay_fptr) (void *hTimer, int timeInMs);

+

+/**

+ * @brief

+ * System time elapsed function pointer

+ *

+ * @details

+ * This function combined with @ref system_getTime_fptr function allow one to determine

+ * the time elapsed between the two event times.

+ *

+ * The example psuedo code below shows how one may see this function used in conjunction with

+ * the function pointed by @ref system_getTime_fptr to do some processing while waiting

+ * for a time to expire.

+ *

+ * @code

+ * my_timer_obj time_now;

+ *

+ * getTime(my_prosclic_obj->timer_obj_ptr, (void *)(&time_now));

+ * 

+ *  Some events occur here...

+ * 

+ * do

+ * {

+ *     time_elapsed(my_proslic_obj->timer_obj_ptr,(void *)(&time_now), &elapsed_time_mSec);

+ *     

+ *     Do something here...

+ *

+ *  }while(elapsed_time_mSec < Desired delay);

+ *

+ * Change state...

+ *

+ * @endcode

+ *

+ * @param[in] *hTimer - the system timer object

+ * @param[in] *startTime - the time object returned by @ref system_getTime_fptr - the "start time" of the event.

+ * @param[out] *timeInMs - the time in mSec between the "start time" and the current time.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa system_getTime_fptr

+*/

+

+typedef int (*system_timeElapsed_fptr) (void *hTimer, void *startTime, int *timeInMs);

+

+/**

+ * @brief

+ * Retrieve system time in mSec resolution.

+ *

+ * @details

+ * This function combined with @ref system_timeElapsed_fptr function allow one to determine

+ * the time elapsed between the two event times.

+ *

+ * @param[in] *hTimer - the system timer object

+ * @param[in] *time - the timestamp object needed by @ref system_timeElapsed_fptr

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa system_timeElapsed_fptr 

+*/

+

+typedef int (*system_getTime_fptr) (void *hTimer, void *time);

+

+/** @} 

+ * @} */

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/vdaa.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/vdaa.h
new file mode 100755
index 0000000..4110212
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/vdaa.h
@@ -0,0 +1,1576 @@
+/*

+** Copyright (c) 2008-2010 by Silicon Laboratories

+**

+** $Id: vdaa.h 2357 2010-10-20 18:16:55Z cdp $

+**

+** Vdaa.h

+** Vdaa  VoiceDAA interface header file

+**

+** Author(s): 

+** naqamar, laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+** File Description:

+** This is the header file for the main  VoiceDAA API and is used 

+** in the  VoiceDAA demonstration code. 

+**

+** Dependancies:

+** Customer Drivers

+**

+*/

+#ifndef VDAA_INTF_H

+#define VDAA_INTF_H

+

+#include "si_voice_datatypes.h"

+#include "si_voice.h"

+/*****************************************************************************/

+/** @defgroup VDAA_API VDAA API

+ * This section covers APIs and definitions related to the VDAA/FXO.

+ * @{

+ */

+

+/*

+** Constants

+*/

+#define BROADCAST 0xff

+#define LCS_SCALE_NUM 33		/* Line Current Status Scale */

+#define LCS_SCALE_DEN 10		/* Line Current Status Scale */

+

+

+/*

+**

+** VDAA Initialization/Configuration Parameter Options

+**

+*/

+/*

+** This defines names for the PCM Data Format

+*/

+ typedef enum {

+	A_LAW = 0,	/**< 00 = A-Law. Signed magnitude data format */

+	U_LAW = 1,	/**< 01 = u-Law. Signed magnitude data format */

+	LINEAR_16_BIT = 3 /**< 11 = 16-bit linear (2s complement data format) */

+}tPcmFormat;

+

+/*

+** This defines names for the phcf bits

+*/

+ typedef enum {

+	PCLK_1_PER_BIT = 0,

+	PCLK_2_PER_BIT = 1

+}tPHCF;

+

+

+/*

+** This defines names for the tri bit

+*/

+ typedef enum {

+	TRI_POS_EDGE = 0,

+	TRI_NEG_EDGE = 1

+}tTRI;

+

+

+/**

+** This defines names for the AC impedance range

+*/

+ typedef enum {

+	AC_600,				/**< 600 Ohms */

+	AC_900,				/**< 900 O */

+	AC_270__750_150,		/**< 270 O + (750 O || 150 nF) and 275 O + (780 O || 150 nF) */

+	AC_220__820_120,		/**< 220 O + (820 O || 120 nF) and 220 O + (820 O || 115 nF) */

+	AC_370__620_310,		/**< 370 O + (620 O || 310 nF) */

+	AC_320__1050_230,		/**< 320 O + (1050 O || 230 nF) */

+	AC_370__820_110,		/**< 370 O + (820 O || 110 nF) */

+	AC_275__780_115,		/**< 275 O + (780 O || 115 nF) */

+	AC_120__820_110,		/**< 120 O + (820 O || 110 nF) */

+	AC_350__1000_210,		/**< 350 O + (1000 O || 210 nF) */

+	AC_200__680_100,		/**< 200 O + (680 O || 100 nF) */

+	AC_600__2160,			/**< 600 O + 2.16 uF */

+	AC_900__1000,			/**< 900 O + 1 uF */

+	AC_900__2160,			/**< 900 O + 2.16 uF */

+	AC_600__1000,			/**< 600 O + 1 uF */

+	AC_Global_impedance		/**< Global impedance */

+}tAC_Z;

+

+/**

+** This defines names for the DC impedance range

+*/

+ typedef enum {

+	 DC_50,					/**< 50 Ohms dc termination is selected */

+	 DC_800					/**< 800 Ohms dc termination is selected */

+

+ }tDC_Z;

+

+/**

+** This defines names for the ringer impedance range

+*/

+ typedef enum {

+	 RZ_MAX = 0,					

+	 RZ_SYNTH = 1					

+ }tRZ;

+

+/**

+** This defines names for the dc voltage adjust

+*/

+ typedef enum {

+	 DCV3_1 = 0,

+	 DCV3_2 = 1,

+	 DCV3_35 = 2,

+	 DCV3_5 = 3

+ }tDCV;

+

+/**

+** This defines names for the minimum loop current

+*/

+ typedef enum {

+	 MINI_10MA = 0,

+	 MINI_12MA = 1,

+	 MINI_14MA = 2,

+	 MINI_16MA = 3

+ }tMINI;

+

+/**

+** This defines names for the current limiting enable bit

+*/

+ typedef enum {

+	 ILIM_DISABLED = 0,

+	 ILIM_ENABLED = 1

+ }tILIM;

+

+/**

+** This defines names for the ring detect interupt mode

+*/

+ typedef enum {

+	 RDI_BEG_BURST = 0,

+	 RDI_BEG_END_BURST = 1

+ }tRDI;

+

+/**

+** This defines names for the on hook speed / spark quenching

+*/

+ typedef enum {

+	 OHS_LESS_THAN_0_5MS = 0,

+	 OHS_3MS = 1,

+	 OHS_26MS = 0xE

+ }tOHS;

+

+ /**

+** This defines names for the hbe bit

+*/

+ typedef enum {

+	HYBRID_DISABLED = 0,

+	HYBRID_ENABLED  = 1

+ }tHBE;

+

+

+/**

+** Gain/Attenuation Select

+*/

+typedef enum {

+    XGA_GAIN,

+    XGA_ATTEN

+}tXGA;

+

+/**

+** MUTE Control Options

+*/

+typedef enum {

+    MUTE_DISABLE_ALL,

+    MUTE_DISABLE_RX,

+    MUTE_DISABLE_TX,

+    MUTE_ENABLE_RX,

+    MUTE_ENABLE_TX,

+    MUTE_ENABLE_ALL

+}tMUTE;

+

+/**

+** This defines names for the ring delay setting

+*/

+ typedef enum {

+	 RDLY_0MS = 0,

+	 RDLY_256MS = 1,

+	 RDLY_512MS = 2,

+	 RDLY_768MS = 3,

+	 RDLY_1024MS = 4,

+	 RDLY_1280MS = 5,

+	 RDLY_1536MS = 6,

+	 RDLY_1792MS = 7

+ }tRDLY;

+

+/**

+** This defines names for the ring timeouts

+*/

+ typedef enum {

+	 RTO_128MS = 1,

+	 RTO_256MS = 2,

+	 RTO_384MS = 3,

+	 RTO_512MS = 4,

+	 RTO_640MS = 5,

+	 RTO_768MS = 6,

+	 RTO_896MS = 7,

+	 RTO_1024MS = 8,

+	 RTO_1152MS = 9,

+	 RTO_1280MS = 10,

+	 RTO_1408MS = 11,

+	 RTO_1536MS = 12,

+	 RTO_1664MS = 13,

+	 RTO_1792MS = 14,

+	 RTO_1920MS = 15

+ }tRTO;

+

+ /**

+** This defines names for the ring timeouts

+*/

+ typedef enum {

+	 RCC_100MS = 0,

+	 RCC_150MS = 1,

+	 RCC_200MS = 2,

+	 RCC_256MS = 3,

+	 RCC_384MS = 4,

+	 RCC_512MS = 5,

+	 RCC_640MS = 6,

+	 RCC_1024MS = 7

+ }tRCC;

+

+/**

+** This defines names for the ring validation modes

+*/

+ typedef enum {

+	 RNGV_DISABLED = 0,

+	 RNGV_ENABLED = 1

+ }tRNGV;

+

+/**

+** This defines names for the rfwe bit

+*/

+ typedef enum {

+	 RFWE_HALF_WAVE = 0,

+	 RFWE_FULL_WAVE = 1,

+	 RFWE_RNGV_RING_ENV = 0,

+	 RFWE_RNGV_THRESH_CROSS = 1

+ }tRFWE;

+

+ /**

+** This defines names for the rt and rt2 bit

+*/

+ typedef enum {

+	 RT__13_5VRMS_16_5VRMS = 0,

+	 RT__19_35VRMS_23_65VRMS = 1,

+	 RT__40_5VRMS_49_5VRMS = 3

+ }tRT;

+

+/**

+** This defines names for the rt and rt2 bit

+*/

+ typedef enum {

+	 RGDT_ACTIVE_LOW = 0,

+	 RGDT_ACTIVE_HI = 1

+ }tRPOL;

+

+

+/**

+** This defines names for the interrupts

+*/

+ typedef enum {

+	POLI,

+	TGDI,

+	LCSOI,

+	DODI,

+	BTDI,

+	FTDI,

+	ROVI,

+	RDTI,

+	CVI		/**< Current/Voltage Interrupt REGISTER#44 */

+}vdaaInt;

+

+/**

+** Interrupt Bitmask Fields

+*/

+typedef enum {

+    POLM = 1,

+    TGDM = 2,   /**< Si3050  Only */

+    LCSOM = 4,

+    DODM = 8,

+    BTDM = 16,

+    FDTM = 32,

+    ROVM = 64,

+    RDTM = 128

+}vdaaIntMask;

+

+

+/**

+** This defines names for the idl bit (obsolete)

+*/

+ typedef enum {

+	 IDL_DISABLED = 0,

+	 IDL_ENABLED = 1

+ }tIDL;

+

+/**

+** This defines names for the ddl bit (obsolete)

+*/

+ typedef enum {

+	 DDL_NORMAL_OPERATION = 0,

+	 DDL_PCM_LOOPBACK = 1

+ }tDDL;

+

+/**

+** Loopback Modes

+*/

+typedef enum {

+    LPBK_NONE = 0,

+    LPBK_IDL = 1,

+    LPBK_DDL = 2,

+    LPBK_PCML = 3

+}tLpbkMode;

+

+/**

+** Loopback Status

+*/

+typedef enum {

+    LPBK_DISABLED = 0,

+    LPBK_ENABLED = 1

+}tLpbkStatus;

+

+/**

+** This defines names for the interrupt pin modes

+*/

+ typedef enum {

+	 INTE_DISABLED = 0,

+	 INTE_ENABLED = 1

+ }tInte;

+

+/**

+** This defines names for the interrupt pin polarities

+*/

+ typedef enum {

+	 INTE_ACTIVE_LOW = 0,

+	 INTE_ACTIVE_HIGH = 1

+ }tIntePol;

+

+/**

+** This defines names for the pwm settings

+*/

+ typedef enum {

+	PWM_DELTA_SIGMA = 0,

+	PWM_CONVENTIONAL_16KHZ = 1,

+	PWM_CONVENTIONAL_32KHZ = 2

+ }tPwmMode;

+

+/**

+** PWME

+*/

+typedef enum {

+    PWM_DISABLED = 0,

+    PWM_ENABLED

+}tPWME;

+

+/**

+** RCALD control

+*/

+typedef enum {

+    RES_CAL_ENABLED = 0,

+    RES_CAL_DISABLED

+}tRCALD;

+

+/**

+** Voice DAA Hook states 

+*/

+enum {

+VDAA_DIG_LOOPBACK = 1,

+VDAA_ONHOOK = 2,

+VDAA_OFFHOOK = 3,

+VDAA_ONHOOK_MONITOR = 4

+};

+

+/**

+** FDT Monitoring Options

+*/

+enum {

+    FDT_MONITOR_OFF = 0,

+    FDT_MONITOR_ON

+};

+    

+

+/**

+** Offhook Speed Select

+*/

+typedef enum {

+    FOH_512,

+    FOH_128,

+    FOH_64,

+    FOH_8

+}tFOH;

+

+/**

+** Sample Rate Control

+*/

+typedef enum {

+    FS_8KHZ,

+    FS_16KHZ

+}tHSSM;

+

+/**

+** Line Voltage Force Disable

+*/

+typedef enum {

+    LVS_FORCE_ENABLED = 0,

+    LVS_FORCE_DISABLED

+}tLVFD;

+

+/**

+** Current/Voltage Monitor Select

+*/

+typedef enum {

+    CVS_CURRENT,

+    CVS_VOLTAGE

+}tCVS;

+

+/**

+** Current/Voltage Interrupt Polarity

+*/

+typedef enum {

+    CVP_BELOW,

+    CVP_ABOVE

+}tCVP;

+

+/**

+** Guarded Clear 

+*/

+typedef enum {

+    GCE_DISABLED = 0,

+    GCE_ENABLED

+}tGCE;

+

+/**

+** SPI Mode (Si3050 Only)

+*/

+typedef enum {

+    SPIM_TRI_CS,

+    SPIM_TRI_SCLK

+}tSPIM;

+

+/**

+**  FILT

+*/

+typedef enum {

+    FILT_HPF_5HZ,

+    FILT_HPF_200HZ

+}tFILT;

+

+/**

+** IIRE

+*/

+typedef enum {

+    IIR_DISABLED = 0,

+    IIR_ENABLED

+}tIIRE;

+

+/**

+** FULL2

+*/

+typedef enum {

+    FULL2_DISABLED = 0,

+    FULL2_ENABLED

+}tFULL2;

+

+/**

+** FULL

+*/

+typedef enum {

+    FULL_DISABLED = 0,

+    FULL_ENABLED

+}tFULL;

+

+/**

+** RG1

+*/

+typedef enum {

+    RG1_DISABLED = 0,

+    RG1_ENABLED

+}tRG1;

+

+

+/**

+** -----------------------------

+** CONFIGURATION DATA STRUCTURES

+** -----------------------------

+*/

+

+/**

+** (Updated) Structure for General Parameters

+*/

+typedef struct {

+    tInte inte;             /* INTE */

+    tIntePol intp;          /* INTP */

+    tRCALD rcald;           /* RCALD */

+    tHSSM hssm;             /* HSSM */

+    tFOH foh;               /* FOH */

+    tLVFD lvfd;             /* LVFD */

+    tCVS cvs;               /* CVS */

+    tCVP cvp;               /* CVP */

+    tGCE gce;               /* GCE */

+    tIIRE iire;             /* IIRE */

+    tFULL2 full2;           /* FULL2 */

+    tFULL full;             /* FULL */

+    tFILT filt;             /* FILT */

+    tRG1 rg1;               /* RG1 */

+    tPwmMode pwmm;          /* PWMM Si3050 Only */

+    tPWME pwmEnable;        /* PWME Si3050 Only */

+    tSPIM spim;             /* SPIM Si3050 Only */

+} vdaa_General_Cfg;

+

+

+/**

+** (NEW) Structure for Country Presets

+*/

+typedef struct {

+    tRZ rz;

+	tDC_Z dcr; 

+	tAC_Z acim;

+	tDCV dcv;

+	tMINI mini;

+	tILIM ilim;

+	tOHS ohs_sq;

+	tHBE hbe;

+} vdaa_Country_Cfg;

+

+/**

+** (NEW) Structure for Hybrid Presets

+*/

+typedef struct {

+	uInt8 hyb1;

+	uInt8 hyb2;

+	uInt8 hyb3;

+	uInt8 hyb4;

+	uInt8 hyb5;

+	uInt8 hyb6;

+	uInt8 hyb7;

+	uInt8 hyb8;

+} vdaa_Hybrid_Cfg;

+

+/**

+** Structure for PCM configuration presets

+*/

+ typedef struct {

+	tPcmFormat pcmFormat;

+	tPHCF pcmHwy;	

+	tTRI pcm_tri;

+} vdaa_PCM_Cfg;

+

+/**

+** Defines structure for configuring impedence 

+** @deprecated:  Replace with separate vdaa_Country_Cfg preset

+**            for country-specific settings and vdaa_Hybrid_Cfg

+**            presets for hybrid coefficients since it is likely

+**            that multiple hybrid coefficient sets will be used

+**            tried during echo training.

+*/

+ typedef struct {

+	tRZ rz;

+	tDC_Z dcr; 

+	tAC_Z acim;

+	uInt8 hyb1;

+	uInt8 hyb2;

+	uInt8 hyb3;

+	uInt8 hyb4;

+	uInt8 hyb5;

+	uInt8 hyb6;

+	uInt8 hyb7;

+	uInt8 hyb8;

+	tDCV dcv;

+	tMINI mini;

+	tILIM ilim;

+	tOHS ohs_sq;

+	tHBE hbe;

+} vdaa_Impedance_Cfg;

+

+/** @addtogroup VDAA_AUDIO 

+ * @{

+ */

+/** @addtogroup VDAA_GAIN_CONTROL

+ * @{

+ */

+/*

+** (Updated) Structure for Audio path gain preset

+*/

+ typedef struct {

+	uInt8		mute;

+	tXGA		xga2;

+	uInt8   	acgain2;

+	tXGA		xga3;

+	uInt8   	acgain3;

+	uInt8		callProgress;

+    BOOLEAN     cpEn;

+} vdaa_audioGain_Cfg;

+

+/** @} VDAA_GAIN_CONTROL*/

+/** @} */

+/*

+** Structure for configuring ring detect config

+*/

+

+typedef struct {

+	tRDLY rdly;

+	tRT rt;

+	uInt8 rmx;

+	tRTO rto;

+	tRCC rcc;

+	tRNGV rngv;

+	uInt8 ras;

+	tRFWE rfwe;

+	tRDI rdi;

+	tRPOL rpol;

+} vdaa_Ring_Detect_Cfg;

+

+

+/*

+** Defines structure of interrupt data

+*/

+typedef struct {

+	vdaaInt *irqs;

+	uInt8 number;

+} vdaaIntType;

+

+/*

+** Defines structure for configuring Loop Back

+*/

+typedef struct {

+	tIDL isoDigLB;

+	tDDL digDataLB;

+} vdaa_Loopback_Cfg;

+

+

+/*

+** Generic Flag

+*/

+typedef enum {

+	VDAA_BIT_SET = 1,

+	VDAA_BIT_CLEAR = 0

+} tVdaaBit;

+

+/*

+** Defines structure for daa current status (ring detect/hook stat)

+*/

+typedef struct {

+	tVdaaBit ringDetectedNeg;

+	tVdaaBit ringDetectedPos;

+	tVdaaBit ringDetected;

+	tVdaaBit offhook;

+	tVdaaBit onhookLineMonitor;

+} vdaaRingDetectStatusType;

+

+

+typedef SiVoiceControlInterfaceType vdaaControlInterfaceType;

+typedef SiVoiceDeviceType vdaaDeviceType;

+typedef SiVoiceChanType vdaaChanType;

+

+/*

+** This is the main  VoiceDAA interface object pointer

+*/

+typedef vdaaChanType *vdaaChanType_ptr;

+

+/*

+** Defines initialization data structures

+*/

+typedef struct {

+	uInt8 address;

+	uInt8 initValue;

+} vdaaRegInit;

+

+

+typedef enum {

+   PAR_HANDSET_NOT_DETECTED = 0,

+   PAR_HANDSET_DETECTED = 1

+}vdaaPHDStatus;

+

+/*

+** Line In Use Configuration Structure

+*/

+typedef struct {

+    vdaaPHDStatus status;

+    int8 min_onhook_vloop;       

+    int8 min_offhook_vloop;

+    int16 min_offhook_iloop;

+    int8 measured_vloop;

+    int16 measured_iloop;

+}vdaa_LIU_Config;

+

+/*

+** Function Declarations

+*/

+

+/*****************************************************************************/

+/** @defgroup VDAA_IF_CONFIG VDAA System control interface functions

+ * This group of functions is called for allocating memory and configuring 

+ * the ProSLIC API to call specific control interfaces that the user implemented.

+ * @deprecated One should use the SiVoice equivalent functions. @ref SIVOICE_IF_CFG

+ * @{

+ */

+

+/*****************************************************************************/

+/** @defgroup VDAA_MEM Memory allocation/deallocation 

+ * @deprecated One should use the SiVoice equivalent functions located: @ref SIVOICE_MEMORY_IF

+ * @{

+ */

+

+/**

+ @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] pCtrlIntf - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_createControlInterface

+ * 

+ */

+

+int Vdaa_createControlInterface (vdaaControlInterfaceType **pCtrlIntf);

+

+/**

+ @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] pCtrlIntf  - the structure to destroy/deallocate

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_destroyControlInterface

+* 

+*/

+

+int Vdaa_destroyControlInterface (vdaaControlInterfaceType **pCtrlIntf);

+

+/**

+ * @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] **pDev - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_createDevice

+ */

+

+int Vdaa_createDevice (vdaaDeviceType **pDev);

+

+/**

+ * @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] **pDev - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_destroyDevice

+ */

+

+int Vdaa_destroyDevice (vdaaDeviceType **pDev);

+

+/**

+ * @brief

+ *  Allocate memory and initialize the given structure.

+ *

+ * @param[in,out] pVdaa - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_createChannel

+ */

+

+int Vdaa_createChannel (vdaaChanType **pVdaa);

+

+/**

+ * @brief

+ *  Destroys the given structure and deallocates memory.

+ *

+ * @param[in,out] pVdaa - the structure to initialize

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref Vdaa_destroyChannel

+ */

+

+int Vdaa_destroyChannel (vdaaChanType **pVdaa);

+

+/** @} */

+

+/*****************************************************************************/

+/** @defgroup VDAA_IO SPI/GCI access routines

+ * This group of functions are used to associcate the transport mechanism (SPI, GCI) functions with the API.  The actual

+ * functions being references are normally implemented by the customer for their particualr OS and platform.

+ *

+ * @deprecated One should use the SiVoice equivalent functions located: @ref SIVOICE_IO

+ * @{

+ */

+

+/**

+ * @brief

+ *  Associate a interface object with a user supplied datastructure.  This 

+ *  structure is passed to all the I/O routines that the ProSLIC API calls.

+ *

+ * @param[in,out] *pCtrlIntf - which interface to associate 

+ *                the user supplied structure with.

+ * @param[in] hCtrl - the user supplied structure.

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use SiVoice_setControlInterfaceCtrlObj

+ */

+

+int Vdaa_setControlInterfaceCtrlObj (vdaaControlInterfaceType *pCtrlIntf, void *hCtrl);

+

+/**

+ * @brief

+ *  Associate a interface object with the reset function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] Reset_fptr - the reset function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setControlInterfaceReset

+ */

+

+int Vdaa_setControlInterfaceReset (vdaaControlInterfaceType *pCtrlIntf, ctrl_Reset_fptr Reset_fptr);

+

+/**

+ * @brief

+ *  Associate a interface object with the register write function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] WriteRegister_fptr - the register write function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setControlInterfaceWriteRegister

+ */

+

+int Vdaa_setControlInterfaceWriteRegister (vdaaControlInterfaceType *pCtrlIntf, ctrl_WriteRegister_fptr WriteRegister_fptr);

+

+/**

+ * @brief

+ *  Associate a interface object with the register read function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] ReadRegister_fptr- the register read function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setControlInterfaceReadRegister

+ */

+

+int Vdaa_setControlInterfaceReadRegister (vdaaControlInterfaceType *pCtrlIntf, ctrl_ReadRegister_fptr ReadRegister_fptr);

+

+/**

+ * @brief

+ *  Associate a interface object with the write RAM function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] WriteRAM_fptr - the reset function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setControlInterfaceWriteRAM

+ */

+

+int Vdaa_setControlInterfaceWriteRAM (vdaaControlInterfaceType *pCtrlIntf, ctrl_WriteRAM_fptr WriteRAM_fptr);

+

+/**

+ * @brief

+ *  Associate a interface object with the read RAM function.

+ *

+ * @param[in,out] pCtrlIntf - which interface to associate 

+ *                the user supplied function with.

+ * @param[in] ReadRAM_fptr - the read RAM function pointer

+ *

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use SiVoice_setControlInterfaceReadRAM

+ */

+

+int Vdaa_setControlInterfaceReadRAM (vdaaControlInterfaceType *pCtrlIntf, ctrl_ReadRAM_fptr ReadRAM_fptr);

+

+/** @} VDAA_IO */

+

+/*****************************************************************************/

+/** @defgroup VDAA_TIMER Timer functions

+ *

+ * This group of functions associates the customer supplied timer routines with the ProSLIC API.

+ *

+ * @deprecated One should use the SiVoice equivalent functions located: @ref SIVOICE_TIMER

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function associates a timer object - which is user defined, but it is 

+ *  used with ALL channels of the particular control interface.

+ *

+ * @param[in] pCtrlIntf - which control interface to associate the given timer object with.

+ * @param[in] hTimer  - the timer ojbect that is passed to all timer functions.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa SIVOICE_TIMER Vdaa_setControlInterfaceDelay Vdaa_setControlInterfaceTimeElapsed Vdaa_setControlInterfaceGetTime

+ * @deprecated Use SiVoice_setControlInterfaceTimerObj

+ */

+

+int Vdaa_setControlInterfaceTimerObj (vdaaControlInterfaceType *pCtrlIntf, void *hTimer);

+

+/** 

+ * @brief

+ *  Associate a timer delay function with a given control interface.  The 

+ *  delay function takes in an argument of the timer object and the time in mSec

+ *  and delays the thread/task for at least the time requested.

+ *

+ *  @param[in] pCtrlIntf - which control interface to associate the function with.

+ *  @param[in] Delay_fptr - the pointer to the delay function.

+ *  @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ *  @sa SIVOICE_TIMER Vdaa_setControlInterfaceTimerObj Vdaa_setControlInterfaceTimeElapsed Vdaa_setControlInterfaceGetTime

+ * @deprecated Use @ref SiVoice_setControlInterfaceDelay

+ */

+

+int Vdaa_setControlInterfaceDelay (vdaaControlInterfaceType *pCtrlIntf, system_delay_fptr Delay_fptr);

+

+/** 

+ *  @brief

+ *   Associate a time elapsed function with a given control interface.  The

+ *   time elapsed function uses the values from the function specified in

+ *   @ref SiVoice_setControlInterfaceGetTime and computes the delta time

+ *   in mSec.

+ *   @param[in] pCtrlIntf - which control interface to associate the function with.

+ *   @param[in] timeElapsed_fptr     - the pointer to the elapsed time function.

+ *   @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *   @sa SIVOICE_TIMER Vdaa_setControlInterfaceTimerObj Vdaa_setControlInterfaceDelay Vdaa_setControlInterfaceGetTime

+ * @deprecated Use @ref SiVoice_setControlInterfaceTimeElapsed

+ */

+

+int Vdaa_setControlInterfaceTimeElapsed (vdaaControlInterfaceType *pCtrlIntf, system_timeElapsed_fptr timeElapsed_fptr);

+

+/** 

+ *  @brief

+ *   Associate a time get function with a given control interface.  The

+ *   time get function returns a value in a form of a void pointer that 

+ *   is suitable to be used with the function specified in @ref SiVoice_setControlInterfaceTimeElapsed .

+ *   This is typically used as a timestamp of when an event started. The resolution needs to be in terms

+ *   of mSec.

+ *

+ *   @param[in] pCtrlIntf - which control interface to associate the function with.

+ *   @param[in] getTime_fptr -  the pointer to the get time function.

+ *   @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *   @sa SIVOICE_TIMER Vdaa_setControlInterfaceTimerObj Vdaa_setControlInterfaceDelay Vdaa_setControlInterfaceTimeElapsed

+ * @deprecated Use @ref SiVoice_setControlInterfaceGetTime

+ */

+

+int Vdaa_setControlInterfaceGetTime (vdaaControlInterfaceType *pCtrlIntf, system_getTime_fptr getTime_fptr);

+

+/** @} VDAA_TIMER */

+

+/*****************************************************************************/

+/** @defgroup VDAA_PROCESS VDAA Process control

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function assoicates a user defined semaphore/critical section

+ *  function with the given interface.

+ *

+ * @param[in,out] pCtrlIntf - the interface to associate the function with.

+ * @param[in] semaphore_fptr - the function pointer for semaphore control.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @deprecated Use @ref SiVoice_setControlInterfaceSemaphore

+ */

+

+int Vdaa_setControlInterfaceSemaphore (vdaaControlInterfaceType *pCtrlIntf, ctrl_Semaphore_fptr semaphore_fptr);

+

+/** @} */

+/** @} VDAA_IF_CONFIG */

+

+/*****************************************************************************/

+/** @defgroup VDAA_DEBUG Debug

+ * * This group of functions enables/disables debug messages as well as dump 

+ * register contents.

+ * @{

+ */

+/**

+ * @brief

+ * This function enables or disables the debug mode, assuming @ref ENABLE_DEBUG is set in the configuration file.

+ *

+ * @param[in] pVdaa - which channel to set the debug flag.

+ * @param[in] debugEn - 0 = Not set, 1 = set.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_setSWDebugMode

+ *

+ */

+

+int Vdaa_setSWDebugMode (vdaaChanType_ptr pVdaa, int32 debugEn);

+

+/**

+ * @brief

+ * This function dumps to console the register contents of several

+ * registers and RAM locations.

+ *

+ * @param[in] pVdaa - which channel to dump the register contents of.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_PrintDebugData (vdaaChanType *pVdaa);

+

+/** @} VDAA_DEBUG */

+

+/*****************************************************************************/

+/** @defgroup VDAA_ERROR Return code functions

+ * This group of functions are used for when the ProSLIC API function does

+ * not reutrn a standard error value and instead returns back some other value.

+ * You may call these functions to see if there was an error preset and to clear 

+ * the error state.

+ * @{

+ */

+/**

+ * @brief

+ * This function returns the error flag that may be set by some function in where

+ * @ref errorCodeType is not returned.  

+ *

+ * @note For functions that DO return errorCodeType, the return value here is undefined.

+ *

+ * @param[in] pVdaa - which channel to clear the error flag

+ * @param[in,out] error - The current value of error flag.  

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_getErrorFlag

+ *

+ * @sa ProSLIC_clearErrorFlag

+ */

+

+int Vdaa_getErrorFlag (vdaaChanType_ptr pVdaa, int *error);

+

+/**

+ * @brief

+ *  This function clears the error flag that may be set by some function in where

+ *  @ref errorCodeType is not returned.

+ *

+ * @param[in,out] pVdaa - which channel to clear the error flag

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_clearErrorFlag

+ *

+ * @sa ProSLIC_getErrorFlag

+ */

+

+int Vdaa_clearErrorFlag (vdaaChanType_ptr pVdaa);

+

+/** @} VDAA_ERROR */

+

+/*****************************************************************************/

+/** @defgroup VDAA_AUDIO Audio

+ * @{

+ */

+/** @defgroup VDAA_GAIN_CONTROL Gain Control

+ * This section covers functions that allow one to adjust the audio

+ * gains - with TX toward the network/SOC/DSP and RX toward the tip/ring.

+ *

+ * @{

+ */

+

+/** 

+ * @brief

+ *  Sets the TX audio gain (toward the network). 

+ *

+ * @param[in] pVdaa - which channel to configure

+ * @param[in] preset - which preset to use (this may be from the constants file)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_TXAudioGainSetup (vdaaChanType *pVdaa,int32 preset);

+

+/** 

+ * @brief

+ *  Sets the RX audio gain (toward the tip/ring). 

+ *

+ * @param[in] pVdaa - which channel to configure

+ * @param[in] preset - which preset to use (this may be from the constants file)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_RXAudioGainSetup (vdaaChanType *pVdaa,int32 preset);

+

+/** @} VDAA_GAIN_CONTROL */

+

+/*****************************************************************************/

+/** @defgroup VDAA_AUDIO_CONTROL Audio control/configuration

+ * This group of functions is used to configure and control the PCM bus.  It is essential that @ref Vdaa_PCMSetup,

+ * @ref Vdaa_PCMTimeSlotSetup and @ref Vdaa_PCMStart are called prior to any audio processing.

+ * @{

+ */

+

+/** 

+ * @brief 

+ *  This configures the PCM bus with parameters such as companding and data latching timing.

+ *

+ * @param[in] pVdaa - which channel should be configured

+ * @param[in] preset - which preset to use from the constants file (see configuration tool, PCM dialog box)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa Vdaa_PCMTimeSlotSetup ProSLIC_PCMStart

+ */

+

+int Vdaa_PCMSetup (vdaaChanType *pVdaa,int32 preset);

+

+/** 

+ * @brief 

+ *  This configures the ProSLIC to latch and send the PCM data at a particular timeslot in terms of PCM clocks (PCLK).

+ *

+ *  Typically, for aLaw and uLaw, one can use the following calculation to set the rxcount and txcount parameters:

+ *

+ *  rxcount = txcount = (channel_number)*8;

+ *

+ *  For 16 bit linear, one can do the following:

+ *

+ *  rxcount = txcount = (channel_number)*16;

+ *

+ * where channel_number = which ProSLIC channel on the PCM bus.  For example, if one were to have 2 dual channel

+ * VDAA's on the same PCM bus, this value would range from 0 to 3. 

+ *

+ * @param[in] pVdaa - which channel should be configured

+ * @param[in] rxcount -  how many clocks until reading data from the PCM bus

+ * @param[in] txcount -  how many clocks until writing data to the PCM bus.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa Vdaa_PCMSetup Vdaa_PCMStart

+ */

+

+int Vdaa_PCMTimeSlotSetup (vdaaChanType *pVdaa, uInt16 rxcount, uInt16 txcount);

+

+/**

+ * @brief

+ *  This enables PCM transfer on the given ProSLIC channel.

+ *

+ * @param[in] pVdaa - - which channel should be enabled

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa ProSLIC_PCMSetup ProSLIC_PCMTimeSlotSetup ProSLIC_PCMStop

+ */

+

+int Vdaa_PCMStart (vdaaChanType *pVdaa);

+

+/**

+ * @brief

+ *  This disables PCM transfer on the given VDAA channel. Typically, this is called for debugging

+ *  purposes only.

+ *

+ * @param[in] pVdaa - - which channel should be disabled

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa Vdaa_PCMSetup Vdaa_PCMTimeSlotSetup Vdaa_PCMStart

+ */

+

+int Vdaa_PCMStop (vdaaChanType *pVdaa);

+

+/**

+ * @brief 

+ * Program desired mute mode for the given channel.

+ *

+ * @param[in] pVdaa - which channel should be modified 

+ * @param[in] mute - what is the desired mode.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_SetAudioMute(vdaaChanType *pVdaa, tMUTE mute);

+

+/**

+ * @brief 

+ * Program desired loopback test mode for the given channel.

+ *

+ * @param[in] pVdaa -  which channel should be modified 

+ * @param[in] lpbk_mode - what is the desired loopback mode.

+ * @param[in] lpbk_status - is this to enable or disable the loopback mode.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated This API is depricated as of 5.2.0

+ * @sa Vdaa_LoopbackSetup

+ *

+ */

+

+int Vdaa_SetLoopbackMode(vdaaChanType_ptr pVdaa, tLpbkMode lpbk_mode, tLpbkStatus lpbk_status);

+

+/**

+ * @brief 

+ * Program desired loopback test mode for the given channel.

+ *

+ * @param[in] pVdaa -  which channel should be modified 

+ * @param[in] preset - which of the API configuration tool's preset to use.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_LoopbackSetup (vdaaChanType *pVdaa, int32 preset);

+

+/*****************************************************************************/

+/** @} VDAA_AUDIO */

+/** @} */

+/** @defgroup VDAA_RING Ring detection

+ * @{

+ */

+

+/**

+ * @brief This function configures ringing detect for the Vdaa.

+ * @param[in] pVdaa - which channel to program

+ * @param[in] preset - Index of predefined ring detect setup configuration

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_RingDetectSetup (vdaaChanType *pVdaa,int32 preset);

+

+

+/** 

+ * @brief This function reads ring detect/hook status and populates the structure passed via pStatus.

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @param[out] pStatus - updated ring status.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_ReadRingDetectStatus (vdaaChanType *pVdaa,vdaaRingDetectStatusType *pStatus);

+

+/** @} VDAA_RING */

+

+/*****************************************************************************/

+/** @defgroup VDAA_LINE_STATE Line state 

+ * @{

+ */

+

+

+/** 

+ * @brief This function sets the Voice DAA hook status

+ * @param[in]  pVdaa - Pointer to Voice DAA channel structure

+ * @param[in]  newHookStatus - new hook state (VDAA_ONHOOK, VDAA_OFFHOOK, VDAA_DIG_LOOPBACK or VDAA_ONHOOK_MONITOR)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_SetHookStatus (vdaaChanType *pVdaa,uInt8 newHookStatus);

+

+/** 

+ * @brief This function powers up the Voice DAA lineside device.

+ * @param[in]  pVdaa - Pointer to Voice DAA channel structure

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_PowerupLineside(vdaaChanType_ptr pVdaa);

+

+/** 

+ * @brief This function powers down the Voice DAA lineside device.

+ * @param[in]  pVdaa - Pointer to Voice DAA channel structure

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_PowerdownLineside(vdaaChanType_ptr pVdaa);

+

+/**

+ * @brief Read VDAA Hook Status

+ * @param[in] pVdaa - which channel to return the hook status.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+uInt8 Vdaa_GetHookStatus (vdaaChanType *pVdaa);

+

+/** @} VDAA_LINE_STATE */

+

+/*****************************************************************************/

+/** @defgroup VDAA_DIAG Diagnostics 

+ * @{

+ */

+

+/** 

+ * @brief This function returns the Voice DAA linefeed status.

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @param[in,out] vloop - Pointer to loop voltage variable (set by this function) - in mV

+ * @param[in,out] iloop - Pointer to loop current variable (set by this function) - in uA

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_ReadLinefeedStatus (vdaaChanType *pVdaa,int8 *vloop, int16 *iloop);

+

+/** 

+ * @brief This function initializes the vdaa_LIU_Config datastructure for line in use feature

+ * @param[in,out] liuCfg - Pointer to vdaa_LIU_Config structure (user allocates)

+ * @param[in] minOnV - minimum onhook loop voltage that indicates no parallel handset is present (mV)

+ * @param[in] minOffV - minimum offhook loop voltage that indicates no parallel handset is present (mV)

+ * @param[in] minOffI - minimum offhook loop current that indicates no parallel handset is preset (uA)

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa Vdaa_CheckForLineInUse

+ */

+

+int Vdaa_InitLineInUseCheck(vdaa_LIU_Config *liuCfg,int8 minOnV,int8 minOffV,int16 minOffI );

+

+/** 

+ * @brief Monitor LVCS to detect intrusion or parallel handset

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @param[in,out] liuCfg - Pointer to vdaa_LIU_Config structure 

+ * @retval VDAA_ONHOOK or VDAA_OFFHOOK (in use)

+ * @sa Vdaa_InitLineInUseCheck

+ */

+

+uInt8 Vdaa_CheckForLineInUse(vdaaChanType *pVdaa, vdaa_LIU_Config *liuCfg);

+

+/** 

+ * @brief This function can be used to verify that the SPI interface is functioning properly.

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Deprecated in 5.2.0

+ */

+

+int Vdaa_VerifyControlInterface (vdaaChanType *pVdaa);

+

+/** 

+ * @brief This function returns the status of the Frame Detect (FDT) bit.

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @retval int - 0 - Frame NOT detected, 1 = Frame detected

+ */

+

+int Vdaa_ReadFDTStatus(vdaaChanType_ptr pVdaa);

+

+/** @} VDAA_DIAG */

+

+/*****************************************************************************/

+/** @defgroup VDAA_INTERRUPTS Interrupts

+ * @{

+ */

+

+/** 

+ * @brief Enables ALL interrupts

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Replaced by @ref Vdaa_SetInterruptMask

+ */

+

+int Vdaa_EnableInterrupts (vdaaChanType *pVdaa);

+

+/** 

+ * @brief Enables interrupts based on passed 9-bit bitmask.  Bit values defined by vdaaIntMask enum.

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @param[in] bitmask - a logical or of @ref vdaaIntMask enum

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_SetInterruptMask(vdaaChanType *pVdaa, vdaaIntMask bitmask);

+

+/** 

+ * @brief Returns the current interrupt status.

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @param[out]  pIntData - interrupt mask showing which interrupts are set.

+ * @retval int - the number of interrupts set or RC_IGNORE

+ */

+

+int Vdaa_GetInterrupts (vdaaChanType *pVdaa,vdaaIntType *pIntData);

+

+/** 

+ * @brief Clears ALL interrupts

+ * @param[in] pVdaa - Pointer to Voice DAA channel structure

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_ClearInterrupts (vdaaChanType *pVdaa);

+

+/** @} VDAA_INTERRUPTS */

+

+/*****************************************************************************/

+/** @defgroup VDAA_INIT Initialization

+ * @{

+ *

+ * @defgroup VDAA_SOFT_INIT Software initialization 

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function initializes the various channel structure elements.  

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ *  It is suggested to migrate to the @ref SiVoice_SWInitChan in new

+ *  implementations.

+ *

+ * @param[in,out] pVdaa - which channel to initialize.

+ * @param[in] channel - Which channel index is this.  For example, for a 4 channel system, this would typically range from 0 to 3.

+ * @param[in] chipType - chipset family type for example @ref SI321X_TYPE or @ref SI3217X_TYPE

+ * @param[in] deviceObj - Device structure pointer associated with this channel

+ * @param[in] pCtrlIntf - Control interface associated with this channel

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_SWInitChan

+ */

+

+int Vdaa_SWInitChan (vdaaChanType_ptr pVdaa,int32 channel,int chipType, SiVoiceDeviceType*deviceObj,SiVoiceControlInterfaceType *pCtrlIntf);

+

+/**

+ * @brief

+ *  This function sets the channel enable status.  If NOT set, then when

+ *  the various initialization routines such as @ref Vdaa_SWInitChan is called,

+ *  then this particular channel will NOT be initialized.

+ *

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ * @param[in,out] pVdaa - which channel to return the status.

+ * @param[in] chanEn - The new value of the channel enable field. 0 = NOT enabled, 1 = enabled.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa Vdaa_getChannelEnable SiVoice_SWInitChan

+ */

+

+int Vdaa_setChannelEnable (vdaaChanType_ptr pVdaa, int chanEn);

+

+

+/**

+ * @brief

+ *  This function returns back if the channel is enabled or not.

+ *  This function does not access the chipset directly, so SPI/GCI

+ *  does not need to be up during this function call.

+ *

+ * @param[in] pVdaa - which channel to return the status.

+ * @param[in,out] chanEn - The current value of if the channel is enabled. 0 = NOT enabled, 1 = enabled.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ * @sa Vdaa_setChannelEnable SiVoice_SWInitChan

+ */

+

+int Vdaa_getChannelEnable (vdaaChanType_ptr pVdaa, int* chanEn);

+

+/** @} VDAA_SOFT_INIT */

+

+/*****************************************************************************/

+/** @defgroup VDAA_HW_INIT Hardware/line initialization

+ * @{

+ */

+

+/**

+ * @brief

+ *  This function configures the Voice DAA with a predefined country configuration preset.

+ *

+ * @param[in] pVdaa - which channel to initialize

+ * @param[in] preset - The preset to use to configure the VDAA with.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_CountrySetup (vdaaChanType *pVdaa,int32 preset);

+

+/**

+ * @brief

+ *  This function configures the Voice DAA digital hybrid with a predefined preset.

+ *

+ * @param[in] pVdaa - which channel to initialize

+ * @param[in] preset - Index of predefined digital hybrid preset

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @sa Vdaa_SetHybridEnable

+ */

+

+int Vdaa_HybridSetup (vdaaChanType *pVdaa,int32 preset);

+

+/**

+ * @brief

+ *  This function sets the impedance coefficients of the Vdaa.

+ *

+ * @param[in] pVdaa - which channel to initialize

+ * @param[in] preset - Index of predefined digital hybrid preset

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_ImpedanceSetup (vdaaChanType *pVdaa,int32 preset);

+

+/**

+ * @brief

+ *  This function fully initializes and loads the general config parameters to all Vdaa devices 

+ *  a given daisychain up to a given number.

+ *

+ * @param[in] pVdaa - which channel to initialize or start from if size>1

+ * @param[in] size - the number of channels to initialize, should be at least 1

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_Init (vdaaChanType_ptr *pVdaa,int size);

+

+/**

+ * @brief

+ *  This function fully initializes and loads the general config parameters to all Vdaa devices on

+ *  a given daisychain.

+ *

+ * @param[in] pVdaa - Vdaa channel

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_InitBroadcast (vdaaChanType_ptr pVdaa);

+

+/**

+ * @brief

+ *  This function calibrates the ADC (analog to digital converter) of the Vdaa device(s).

+ *

+ * @param[in] pVdaa - which channel to calibrate or starting channel if size>1

+ * @param[in] size - the number of channels to calibrate.

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_ADCCal (vdaaChanType_ptr pVdaa, int32 size);

+

+/**

+ * @brief

+ *  This function controls the Voice DAA digital hybrid.

+ *

+ * @param[in] pVdaa - which channel to set/unset

+ * @param[in] enable - TRUE: enable digital hybrid, FALSE: disable digital hybrid

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ *

+ */

+

+int Vdaa_SetHybridEnable(vdaaChanType_ptr pVdaa, int enable);

+

+/** @} VDAA_HW_INIT */

+/*****************************************************************************/

+

+/**

+ * @brief Execute a reset on a given channel/daisychain.

+ * @param[in] pVdaa - the channel to reset

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ * @deprecated Use @ref SiVoice_Reset

+ */

+

+int Vdaa_Reset (vdaaChanType *pVdaa);

+

+/**

+ * @brief  Enables watchdog timer

+ * @param[in] pVdaa - the channel to enable the watchdog

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_EnableWatchdog(vdaaChanType_ptr pVdaa);

+

+/**

+ * @brief Execute a soft reset on a given channel.

+ * @param[in] pVdaa - the channel to reset

+ * @retval int - error from @ref errorCodeType  @ref RC_NONE indicates no error.

+ */

+

+int Vdaa_SoftReset(vdaaChanType_ptr pVdaa);/** @} VDAA_INIT */

+

+/**

+ * @brief

+ *  This function returns back a string with the current version of the 

+ *  ProSLIC API.

+ *

+ * @details

+ *  The string is in the following format MM.mm.vv[.rcX] format, where

+ *  MM is the major number, mm is the minor number and vv is the sub-minor number.

+ *  If this is a release candidate, a .RCx is tacked on - such as RC1 for release

+ *  candidate 1.

+ *

+ *  @retval char * - returns back a constant string.

+ */

+char *Vdaa_Version(void);

+

+/** @} MISC */

+

+/** @} VDAA_API */

+#endif

+

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/vdaa_registers.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/vdaa_registers.h
new file mode 100755
index 0000000..b421999
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc/vdaa_registers.h
@@ -0,0 +1,86 @@
+/*

+** Copyright (c) 2008 by Silicon Laboratories

+**

+** $Id: vdaa_registers.h 554 2009-03-25 23:11:55Z cdp@SILABS.COM $

+**

+** Author(s): 

+** laj

+**

+** Distributed by: 

+** Silicon Laboratories, Inc

+**

+** This file contains proprietary information.	 

+** No dissemination allowed without prior written permission from

+** Silicon Laboratories, Inc.

+**

+*/

+#ifndef SI3050REGS_H

+

+#define SI3050REGS_H

+

+

+enum REGISTERS {

+CTRL1						=	1	,	/*	Control    */

+CTRL2						=	2	,	/*	Control  */

+INTE_MSK					=	3	,	/*	Interrupt Mask  */

+INTE_SRC					=	4	,	/*	Interrupt Source  */

+DAA_CTRL1					=	5	,	/*	DAA Control 1   */

+DAA_CTRL2					=	6	,	/*	DAA Control 2   */

+SMPL_CTRL					=	7	,	/*	Sample Rate Control  */ 

+RESVD8 						=	8	,	/*	Reserved  */

+RESVD9 						=	9	,	/*	Reserved  */

+DAA_CTRL3					=	10	,	/*	DAA Control 3  */ 

+SYS_LINE_DEV_REV			=	11	,	/*	System- and Line-Side Device Revision  */ 

+LSIDE_STAT				 	=	12	,	/*	Line-Side Device Status   */

+LSIDE_REV					=	13	,	/*	Line-Side Device Revision   */

+DAA_CTRL4				=	14	,	/*	DAA Control 4 RPOL  */

+TXRX_GN_CTRL			 	=	15	,	/*	TX/RX Gain Control 1  */ 

+INTL_CTRL1				 	=	16	,	/*	International Control 1   */

+INTL_CTRL2				 	=	17	,	/*	International Control 2   */

+INTL_CTRL3				 	=	18	,	/*	International Control 3   */

+INTL_CTRL4				 	=	19	,	/*	International Control 4   */

+RXCALL_PROG_ATTEN			=	20	,	/*	Call Progress RX Attenuation  */

+TXCALL_PROG_ATTEN			=	21	,	/*	Call Progress TX Attenuation   */

+RNG_VLD_CTRL1			 	=	22	,	/*	Ring Validation Control 1   */

+RNG_VLD_CTRL2			 	=	23	,	/*	Ring Validation Control 2   */

+RNG_VLD_CTRL3			 	=	24	,	/*	ing Validation Control 3   */

+RES_CALIB					=	25	,	/*	Resistor Calibration   */

+DC_TERM_CTRL			 	=	26	,	/*	DC Termination Control   */

+RESVD27						=	27	,	/*	Reserved  */

+LP_CRNT_STAT			 	=	28	,	/*	Loop Current Status  */ 

+LINE_VOLT_STAT			 	=	29	,	/*	Line Voltage Status   */

+AC_TERM_CTRL				=	30	,	/*	AC Termination Control   */

+DAA_CTRL5					=	31	,	/*	DAA Control 5   */

+GND_STRT_CTRL				=	32	,	/*	Ground Start Control  */ 

+PCM_SPI_CTRL			 	=	33	,	/*	PCM/SPI Mode Select   */

+PCMTX_CNT_LO			 	=	34	,	/*	PCM Transmit Start Count - Low Byte  */ 

+PCMTX_CNT_HI			 	=	35	,	/*	PCM Transmit Start Count - High Byte   */

+PCMRX_CNT_LO			 	=	36	,	/*	PCM Receive Start Count - Low Byte   */

+PCMRX_CNT_HI			 	=	37	,	/*	PCM Receive Start Count - High Byte   */

+TX_GN_CTRL2					=	38	,	/*	TX Gain Control 2   */

+RX_GN_CTRL2					=	39	,	/*	RX Gain Control 2   */

+TX_GN_CTRL3					=	40	,	/*	TX Gain Control 3   */

+RX_GN_CTRL3					=	41	,	/*	RX Gain Control 3   */

+GCI_CTRL					=	42	,	/*	GCI Control   */

+LN_VI_THRESH_INTE		 	=	43	,	/*	Line Current/Voltage Threshold Interrupt  */ 

+LN_VI_THRESH_INTE_CTRL	 	=	44	,	/*	Line Current/Voltage Threshold Interrupt Control  */

+HYB1					 	=	45	,	/*	Programmable Hybrid Register 1  */

+HYB2					 	=	46	,	/*	Programmable Hybrid Register 2  */

+HYB3					 	=	47	,	/*	Programmable Hybrid Register 3  */

+HYB4					 	=	48	,	/*	Programmable Hybrid Register 4  */

+HYB5					 	=	49	,	/*	Programmable Hybrid Register 5  */

+HYB6					 	=	50	,	/*	Programmable Hybrid Register 6  */

+HYB7						=	51	,	/*	Programmable Hybrid Register 7  */

+HYB8					 	=	52	,	/*	Programmable Hybrid Register 8  */

+RESVD53					 	=	53	,	/*	Reserved 53  */

+RESVD54						=	54	,	/*	Reserved 54  */

+RESVD55					 	=	55	,	/*	Reserved 55  */

+RESVD56					 	=	56	,	/*	Reserved 56  */

+RESVD57					 	=	57	,	/*	Reserved 57  */

+RESVD58					 	=	58	,	/*	Reserved 58  */

+SPRK_QNCH_CTRL				=	59		/*	Spark Quenching Control  */ 

+

+};

+

+

+#endif

diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp580_api.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp580_api.h
new file mode 100755
index 0000000..249da75
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp580_api.h
@@ -0,0 +1,231 @@
+/** \file vp580_api.h
+ * vp580_api.h
+ *
+ *  Header file that define the Vp580 Device and Line Objects
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9084 $
+ * $LastChangedDate: 2011-11-09 16:54:12 -0600 (Wed, 09 Nov 2011) $
+ */
+
+#ifndef VP580_API_H
+#define VP580_API_H
+
+#include "vp_hal.h"
+#include "vp_CSLAC_types.h"
+
+#define VP580_MAX_MPI_DATA  15   /* Max data from any MPI read command */
+
+#ifndef VP580_UL_SIGREG_LEN
+#define VP580_UL_SIGREG_LEN         0x01
+#endif
+
+#define VP580_INT_SEQ_LEN       22
+#define VP580_MAX_NUM_STATES  10
+
+/**< Required Vp580 Device and Line Objects for user instantiation if a Vp580
+ * device is used
+ */
+
+/**< Structure that defines the Vp580 Device Profile. Current as of the first
+ * Device Profile version (ver 0).
+ */
+typedef struct Vp580DeviceProfileType {
+    uint8  maxNumInterrupts;
+    uint16 pcmClkRate;      /**< Used to verify valid TX/RX Timeslot setting */
+    uint8  mClkMask;
+    uint16 tickRate;        /**< Primary API-II tick for this device */
+    uint8  devCfg1;
+    uint8  debounceReg;
+    uint8  clockSlot;
+} Vp580DeviceProfileType;
+
+/**< Line Status types to minimize code space in line object, compared to each status being
+ * maintined by a uint8 type). These values are used by the line object "status" member.
+ */
+#define VP580_INIT_STATUS       (0x00)
+#define VP580_IS_FXO            (0x01)  /**< Set if the line is configured for FXO */
+
+#define VP580_SLS_CALL_FROM_API (0x02)    /**< Set if Set Line State is called from an intenral
+                                             * API function (e.g., cadence). Used to bypass the
+                                             * "same line state" test (i.e., always make the state
+                                             * change requested, even if it's the same as the
+                                             * current state).
+                                             */
+
+#define VP580_INIT_COMPLETE     (0x04)    /**< Set when InitLine has been completed */
+
+typedef struct Vp580LineObjectType {
+    uint8 channelId;    /**< Channel # for "this" line on the device.  Indexed
+                         * starting at 0, should not exceed the max number of
+                         * lines supported by the device - 1 (max = 2, then
+                         * channelId = {0, 1}
+                         */
+
+    VpTermType termType;    /**< Termination type */
+
+    uint8 status;       /**< Keeps track of several line state/config */
+
+    VpSeqDataType cadence;      /**< Sequencer related information */
+
+    VpDialPulseDetectType dpStruct; /**< Used on FXS lines for detecting pulse
+                                     * digits
+                                     */
+
+    VpDigitGenerationDataType digitGenStruct;   /**< Used on FXO lines for
+                                                 * generating pulse digits
+                                                 */
+
+    VpOptionCodecType codec;    /**< Codec mode used on this line. Maintained in
+                                 * the API-II to reduce MPI activity which is a
+                                 * shared resource and requires CRITICAL code
+                                 * section handling.
+                                 */
+
+    VpOptionEventMaskType lineEventsMask;
+    VpOptionEventMaskType lineEvents;
+
+    VpOptionPulseModeType pulseMode;
+
+    uint8 signalingData;    /**< Holds data for Signaling events on this line */
+    uint16 processData;      /**< Holds data for Process events on this line */
+    uint16 fxoData;         /**< Timestamp of event */
+
+    VpCslacTimerStruct lineTimers; /**< Timers for "this" line */
+
+    VpApiIntLineStateType lineState;    /**< Line state info used for state
+                                         * transition handling and recall
+                                         */
+#ifdef VP_CSLAC_SEQ_EN
+    /**< Array to control internally run sequences */
+    VpProfileDataType intSequence[VP580_INT_SEQ_LEN];
+#endif
+
+    /* Items saved from the Ring Profile: */
+    struct ringParams {
+        int method;
+        uint16 timerMs;
+        int state;
+    } ringParams;
+
+    VpProfilePtrType pRingingCadence;   /**< Currently used ringing cadence on
+                                         * this line
+                                         */
+
+    uint16 lineEventHandle; /**< Line specific event handle information */
+
+    VpOptionRingControlType ringCtrl;
+
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;   /* Defines how the PCM highway is
+                                             * set for "talk" linestates
+                                             */
+
+    /*
+     * NOTE: Do not move the location or name of these members. These may be
+     * used by applications to determine the gain of the GX/GR blocks in the
+     * AC profile. Using return from VpSetRelGain() is not usefull because that
+     * is the register setting. The customer would have to know how to convert
+     * that to linear values, which is not generally documented.
+     */
+    struct Vp580RelGainValues {
+        uint16 gxInt;       /**< Cached GX register, in 2.14 int format */
+        uint16 grInt;       /**< Cached GR register, in 2.14 int format */
+    } gain;
+
+    uint8 lineStateBytes[VP580_MAX_NUM_STATES]; /**< I/O Data bytes to set a
+                                                 * line state
+                                                 */
+    uint16 lineStateExist;  /* Bit map of the line states that are defined */
+
+    bool lineStateInit;         /**< TRUE if line state map is required and
+                                 * initialized for this line
+                                 */
+
+    uint8 detMap;               /**< Map in I/O data for detect bit */
+    uint8 bitMask;      /**< Bits that are used by termination type */
+
+    /* This registers may be used for detector status */
+    uint8 ioDataReg;    /* I/O Data Register for this channel */
+    uint8 ioDirReg;     /* I/O Direction Register for this channel */
+    bool ringingDet;    /**< TRUE when ringing is detected on FXO line */
+
+    uint8 ringDetMin;   /**< Minimum ringing detect period (FXO line) in 500uS
+                         * increments
+                         */
+
+    uint8 ringDetMax;   /**< Maximum ringing detect period (FXO line) in 500uS
+                         * increments
+                         */
+
+    VpLineIdType lineId;	/**< Application provided value for mapping a line to
+                             * a line context
+                             */
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+} Vp580LineObjectType;
+
+/*
+ * IMPORTANT: Make sure to update the "stateInt" member of the device object if
+ * the size of this type changes. There is no instance of this type itself.
+ */
+typedef enum Vp580DeviceStateIntType {
+    VP580_RSVD = 0x0001,            /* Not Used */
+    VP580_FORCE_SIG_READ = 0x0002   /* Set to force a signaling register read */
+} Vp580DeviceStateIntType;
+
+typedef struct Vp580DeviceObjectType {
+    VpDeviceIdType deviceId;    /**< Device chip select ID defined by user */
+    VpDeviceStaticInfoType staticInfo;  /**< Info that will not change during
+                                         * runtime
+                                         */
+    VpDeviceDynamicInfoType dynamicInfo;    /**< Info that will change during
+                                             * runtime
+                                             */
+
+    /**< State of signaling interrupt register */
+    uint8 intReg[VP580_UL_SIGREG_LEN];
+
+    VpCSLACDeviceStatusType status;
+
+    /* stateInt is a bit-mask of Vp580DeviceStateIntType values */
+    uint16 stateInt;
+
+    VpOptionEventMaskType deviceEventsMask;
+    VpOptionEventMaskType deviceEvents;
+
+    VpOptionPulseType pulseSpecs;
+
+    uint16 devTimer[VP_DEV_TIMER_LAST];
+    Vp580DeviceProfileType devProfileData;
+    VpCSLACDeviceProfileTableType devProfileTable;
+    VpCSLACProfileTableEntryType profEntry;
+
+#if !defined(VP_REDUCED_API_IF) || defined(ZARLINK_CFG_INTERNAL)
+    uint8 mpiData[VP580_MAX_MPI_DATA];  /**< Buffer for MPI Low level reads to
+                                         * hold maximum amount of MPI data that
+                                         * is possible
+                                         */
+
+    uint8 mpiLen;       /**< Length of data to be copied into mpiData buffer */
+#endif
+
+    uint16 eventHandle;  /** Application defined event handle */
+    uint16 timeStamp;   /**< Used to track event timing. Increment by ticks */
+    int16 timeRemainder;
+
+    VpGetResultsOptionsType getResultsOption;
+    VpRelGainResultsType relGainResults;
+
+    uint8 rtdReg;       /* Real-Time Data Register for this device */
+    uint8 clkFailReg;   /* Register containing clock fault status */
+
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+} Vp580DeviceObjectType;
+
+#endif  /**< vp580_api.h */
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp790_api.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp790_api.h
new file mode 100755
index 0000000..0c40ed0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp790_api.h
@@ -0,0 +1,174 @@
+/** \file vp790_api.h
+ * vp790_api.h
+ *
+ *  Header file that defines the Vp790 Device and Line Objects
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9084 $
+ * $LastChangedDate: 2011-11-09 16:54:12 -0600 (Wed, 09 Nov 2011) $
+ */
+
+#ifndef VP790_API_H
+#define VP790_API_H
+
+#include "vp_hal.h"
+#include "vp_CSLAC_types.h"
+
+#define VP790_MAX_MPI_DATA  0x0E    /**< Max data from any MPI read command */
+#define VP790_INT_SEQ_LEN   22
+/*
+ * Required Vp790_ Device and Line Objects for user instantiation if a Vp790
+ * device is used
+ */
+typedef struct Vp790DeviceProfileType {
+    uint8  maxNumInterrupts;
+    uint16 pcmClkRate;
+    uint8  mClkMask;
+    uint8  mClkCorrection;
+    uint16 tickRate;
+    uint8  devCfg1;
+    uint8  clockSlot;
+    uint8  calibrationTime;
+} Vp790DeviceProfileType;
+
+typedef struct Vp790LineObjectType {
+    uint8 channelId;    /**< Channel # associated with "this" line on the
+                         * device
+                         */
+
+    VpTermType termType;    /**< Termination type of this line */
+
+    VpOptionCodecType codec;    /**< Maintains the currently used code mode to
+                                 * reduce MPI activity
+                                 */
+
+    VpOptionLineStateType lineStateBatOption;
+
+#ifdef VP_CSLAC_SEQ_EN
+    uint8 cidEncodeBuff[6]; /**< Encoded CID data from user data */
+    uint8 cidEncodeIndex;   /**< current index into encoded buffer */
+    uint8 cidEncodeSize;    /**< Size of valid CID encoded data */
+
+    VpCallerIdType callerId;    /**< Caller ID related information */
+    VpSeqDataType cadence;      /**< Sequencer related information */
+    VpCidSeqDataType cidSeq;    /**< CID Sequencer related information */
+
+    /**< Array to control internally run sequences */
+    VpProfileDataType intSequence[VP790_INT_SEQ_LEN];
+
+    bool thisFskCid;   /**< TRUE if device tick has not changed since last call
+                        * to FSK CID Generator Function call. Used to prevent
+                        * CID lockup with while() loop to load CID data in the
+                        * device.
+                        */
+#endif
+
+    bool slsCalledFromApi;  /**< TRUE if SetLineState is called by the API */
+
+    VpDialPulseDetectType dpStruct; /**< Dial Pulse Parameters for detecting
+                                     * digits on FXS lines
+                                     */
+
+    VpOptionEventMaskType lineEventsMask;
+    VpOptionEventMaskType lineEvents;
+
+    VpOptionPulseModeType pulseMode;
+
+    uint8 signalingData;    /**< Holds data for Signaling events on this line */
+    uint16 processData;     /**< Holds data for Process events on this line */
+
+    VpCslacTimerStruct lineTimers; /**< Timers for "this" line */
+
+    VpApiIntLineStateType lineState;    /**< Line state info, used for state
+                                         * transition handling.
+                                         */
+
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;   /* Defines how the PCM highway is
+                                             * set for "talk" linestates
+                                             */
+    VpOptionRingControlType ringCtrl;
+
+    VpOptionZeroCrossType zeroCross;    /**< Defines how zero crossing is
+                                         * implemented. The device doesn't really
+                                         * support zero crossing "methods", but
+                                         * storing what the user selected is
+                                         * necessary for Get Option (so the
+                                         * operations of Set/Get can be
+                                         * orthogonal)
+                                         */
+
+    VpVirtualDeviceReg virtualDeviceReg;    /**< Virtual device register to
+                                             * minimize device access
+                                             */
+
+    VpProfilePtrType pRingingCadence;   /**< Currently used ringing cadence on
+                                         * this line
+                                         */
+
+    VpProfilePtrType pCidProfileType1;  /**< Currently used caller ID profile
+                                         * on this line for sequenced cid
+                                         */
+
+    VpProfilePtrType pCidProfileType2;  /**< Currently used caller ID profile
+                                         * on this line for non-sequenced cid
+                                         */
+
+    uint16 lineEventHandle; /**< Line specific event handle information */
+
+    uint16 dtmfDigitSense;          /**< Used to hold the DTMF digit reported
+                                     * with VpDtmfDigitDetected() until the
+                                     * VP_LINE_EVID_DTMF_DIG is generated.
+                                     */
+
+    VpLineIdType lineId;	/**< Application provided value for mapping a line to
+                             * a line context
+                             */
+} Vp790LineObjectType;
+
+typedef struct Vp790DeviceObjectType {
+    VpDeviceIdType deviceId;    /**< Device chip select ID or type defined by
+                                 * user
+                                 */
+
+    VpDeviceStaticInfoType staticInfo;      /**< Info that will not change
+                                             * during runtime
+                                             */
+    VpDeviceDynamicInfoType dynamicInfo;    /**< Info that will change during
+                                             * runtime
+                                             */
+    VpCSLACDeviceStatusType status;
+
+    VpOptionEventMaskType deviceEventsMask;
+    VpOptionEventMaskType deviceEvents;
+
+    VpOptionPulseType pulseSpecs;
+
+    VpOptionCriticalFltType criticalFault;
+
+    uint16 devTimer[VP_DEV_TIMER_LAST];
+    Vp790DeviceProfileType devProfileData;
+    VpCSLACDeviceProfileTableType devProfileTable;
+    VpCSLACProfileTableEntryType profEntry;
+
+#if !defined(VP_REDUCED_API_IF) || defined(ZARLINK_CFG_INTERNAL)
+    uint8 mpiData[VP790_MAX_MPI_DATA];  /**< Buffer for MPI Low level reads to
+                                         * hold maximum amount of MPI data that
+                                         * is possible
+                                         */
+
+    uint8 mpiLen;       /**< Length of data to be copied into mpiData buffer */
+#endif
+
+    uint16 eventHandle; /**< Device level event handle information */
+    uint16 timeStamp;
+    int16 timeRemainder;
+
+    VpGetResultsOptionsType getResultsOption;
+} Vp790DeviceObjectType;
+
+#endif  /* vp790_api.h */
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp880_api.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp880_api.h
new file mode 100755
index 0000000..2d5109b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp880_api.h
@@ -0,0 +1,1127 @@
+/** \file vp880_api.h
+ * vp880_api.h
+ *
+ *  Header file that define all the commands for the Vp880 device.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9253 $
+ * $LastChangedDate: 2011-12-14 11:08:16 -0600 (Wed, 14 Dec 2011) $
+ */
+
+#ifndef VP880_API_H
+#define VP880_API_H
+
+#include "vp_hal.h"
+#include "vp_CSLAC_types.h"
+#include "vp_api_common.h"
+
+#define VP880_MAX_NUM_CHANNELS   2
+
+#ifdef VP880_INCLUDE_TESTLINE_CODE
+#include "vp_api_test.h"
+  #ifdef VP880_EZ_MPI_PCM_COLLECT
+  #include  "vp_pcm_compute.h"
+  #endif
+#endif
+
+#define VP880_MAX_MPI_DATA  15   /* Max data from any MPI read command */
+#define VP880_INT_SEQ_LEN       22
+
+#ifndef VP880_DC_FEED_LEN
+#define VP880_DC_FEED_LEN    0x02
+#endif
+
+#ifndef VP880_REGULATOR_PARAM_LEN
+#define VP880_REGULATOR_PARAM_LEN   0x03
+#endif
+
+#ifndef VP880_LOOP_SUP_LEN
+#define VP880_LOOP_SUP_LEN      0x04
+#endif
+
+#ifndef VP880_SIGA_PARAMS_LEN
+#define VP880_SIGA_PARAMS_LEN   0x0B
+#endif
+
+#ifndef VP880_UL_SIGREG_LEN
+#define VP880_UL_SIGREG_LEN     0x02
+#endif
+
+#ifndef VP880_B1_FILTER_LEN
+#define VP880_B1_FILTER_LEN     0x0E
+#endif
+
+#ifndef VP880_B2_FILTER_LEN
+#define VP880_B2_FILTER_LEN     0x02
+#endif
+
+#ifndef VP880_ICR1_LEN
+#define VP880_ICR1_LEN      0x04
+#endif
+
+#ifndef VP880_ICR2_LEN
+#define VP880_ICR2_LEN      0x04
+#endif
+
+#ifndef VP880_ICR3_LEN
+#define VP880_ICR3_LEN      0x04
+#endif
+
+#ifndef VP880_ICR4_LEN
+#define VP880_ICR4_LEN      0x04
+#endif
+
+#ifndef VP880_ICR5_LEN
+#define VP880_ICR5_LEN      0x02
+#endif
+
+#ifndef VP880_ICR6_LEN
+#define VP880_ICR6_LEN      0x02
+#endif
+
+#ifndef VP880_ICR6_LEN
+#define VP880_ICR6_LEN      0x02
+#endif
+
+#ifndef VP880_BAT_CALIBRATION_LEN
+#define VP880_BAT_CALIBRATION_LEN 0x02
+#endif
+
+#ifndef VP880_REGULATOR_CTRL_LEN
+#define VP880_REGULATOR_CTRL_LEN    0x01
+#endif
+
+#ifndef VP880_TX_PCM_BUFF_LEN
+#define VP880_TX_PCM_BUFF_LEN 0x0E
+#endif
+
+#ifndef VP880_INT_SWREG_PARAM_LEN
+#define VP880_INT_SWREG_PARAM_LEN   0x06
+#endif
+
+#ifndef VP880_DISN_LEN
+#define VP880_DISN_LEN              0x01
+#endif
+
+#ifndef VP880_VP_GAIN_LEN
+#define VP880_VP_GAIN_LEN           0x01
+#endif
+
+#ifndef VP880_SYS_STATE_LEN
+#define VP880_SYS_STATE_LEN     0x01
+#endif
+
+#ifndef VP880_OP_FUNC_LEN
+#define VP880_OP_FUNC_LEN         0x01
+#endif
+
+#ifndef VP880_OP_COND_LEN
+#define VP880_OP_COND_LEN         0x01
+#endif
+
+#ifndef VP880_CONV_CFG_LEN
+#define VP880_CONV_CFG_LEN      0x01
+#endif
+
+#ifndef VP880_DEV_MODE_LEN
+#define VP880_DEV_MODE_LEN  0x01
+#endif
+
+#ifndef VP880_GEN_CTRL_LEN
+#define VP880_GEN_CTRL_LEN  0x01
+#endif
+
+#ifndef VP880_CID_PARAM_LEN
+#define VP880_CID_PARAM_LEN 0x01
+#endif
+
+
+/**< Required Vp880 Device and Line Objects for user instantiation if a Vp880 device is used */
+
+/**< Structure that defines the Vp880 Device Profile. Current as of the first
+ * Device Profile version (ver 0).
+ */
+typedef struct Vp880DeviceProfileType {
+    uint8   profVersion;
+    uint16  pcmClkRate;      /**< Used to verify valid TX/RX Timeslot setting */
+    uint16  tickRate;        /**< Primary API-II tick for this device */
+    uint8   devCfg1;
+    uint8   clockSlot;
+    uint8   systemConfig;   /**< Used to indicate system supply configuration */
+
+#ifdef VP880_FXS_SUPPORT
+    bool    peakManagement;
+    bool    lowVoltOverride;
+#endif
+} Vp880DeviceProfileType;
+
+/* Byte/Bit definitions from the device profile */
+#define VP880_DEV_PROFILE_OPERATIONAL_CFG   (2u)
+#define VP880_DEV_PROFILE_PK_PWR_MGMT       0x01
+#define VP880_DEV_PROFILE_LOW_VOLT_OVERRIDE 0x02
+
+#define VP880_DEV_PROFILE_PCLK_MSB          (6u)
+#define VP880_DEV_PROFILE_PCLK_LSB          (7u)
+#define VP880_DEV_PROFILE_DEVCFG1           (8u)
+
+#define VP880_DEV_PROFILE_SYSTEM_CFG        (9u)
+#define VP880_ABS_CFG_SINGLE                0x00
+#define VP880_ABS_CFG_SLAVE                 0x01
+#define VP880_ABS_CFG_MASTER                0x02
+#define VP880_ABS_CFG_MASK                  0x03
+
+#define VP880_DEV_PROFILE_CLOCK_SLOT        (10u)
+#define VP880_DEV_PROFILE_MAX_EVENTS        (11u)
+#define VP880_DEV_PROFILE_TICKRATE_MSB      (12u)
+#define VP880_DEV_PROFILE_TICKRATE_LSB      (13u)
+#define VP880_DEV_PROFILE_SWITCHER_CMD      (14u)
+#define VP880_DEV_PROFILE_SWITCHER_DATA0    (15u)
+#define VP880_DEV_PROFILE_SWITCHER_DATA1    (16u)
+#define VP880_DEV_PROFILE_SWITCHER_DATA2    (17u)
+
+#define VP880_ABS_DEV_PROFILE_YVOLT         (18u)
+#define VP880_ABS_DEV_PROFILE_ZVOLT         (19u)
+
+#define VP880_DEV_PROFILE_TRACKER_INT_SW_REG    (18u)
+
+#define VP880_DEV_PROFILE_ABS_INT_SW_REG    (24u)
+
+
+/**< Line Status types to minimize code space in line object (compared to each
+ * status being maintined by a uint8 type)
+ */
+typedef enum Vp880LineStatusType {
+    VP880_INIT_STATUS = 0x0000,
+
+    VP880_IS_FXO = 0x0001,  /**< Set if the line is configured for FXO */
+
+    VP880_SLS_CALL_FROM_API = 0x0002,   /**< Set if Set Line State is called
+                                         * from an API function (e.g., cadence).
+                                         */
+
+    VP880_BAD_LOOP_SUP = 0x0004,    /**< Set when the Loop Supervision has been
+                                     * changed in such a way inconsistent with
+                                     * the user's specifications. This is done
+                                     * in internal to the API to make some
+                                     * functions work (e.g., Msg Wait Pulse).
+                                     */
+
+    VP880_UNBAL_RINGING = 0x0008,   /**< Set if this line uses unbal ringing */
+
+    VP880_DP_SET1_DONE = 0x0010,    /**< Set when Dial Pulse detection machine
+                                     * is "done" on the current dial pulse using
+                                     * the "first" set of DP parameters
+                                     */
+
+    VP880_DP_SET2_DONE = 0x0020,    /**< Set when Dial Pulse detection machine
+                                     * is "done" on the current dial pulse using
+                                     * the 2nd set of DP parameters
+                                     */
+
+    VP880_LINE_IN_CAL = 0x0040,    /**< Set when line is calibrating */
+
+    VP880_LOW_POWER_EN = 0x0080,    /**< Set when line is operating in low power
+                                     * mode
+                                     */
+
+    VP880_LINE_LEAK = 0x0100,      /**< Set when leakage is detected on the line
+                                    * such that low power mode is prevented.
+                                    */
+
+    VP880_INIT_COMPLETE = 0x0800,  /**< Set when InitLine has been completed
+                                    * on this line.
+                                    */
+    VP880_PREVIOUS_HOOK = 0x1000,  /**< Set if Last Hook Event reported was
+                                    * off-hook, cleared if last event was
+                                    * on-hook.
+                                    */
+
+    VP880_RING_GEN_NORM = 0x2000,  /**< Set when the Generators are known last
+                                    * to be programmed to the application
+                                    * specified ringing profile. Cleared
+                                    * when line tests are run because the same
+                                    * generator is used for non-ringing.
+                                    */
+    VP880_RING_GEN_REV = 0x4000    /**< Set when the Generators are known last
+                                    * to be programmed to the application
+                                    * specified ringing profile. Cleared
+                                    * when line tests are run because the same
+                                    * generator is used for non-ringing.
+                                    */
+} Vp880LineStatusType;
+
+#if defined (VP880_INCLUDE_TESTLINE_CODE)
+/* Definitions for Test arguments */
+typedef union Vp880TestArgsType {
+    VpTestPrepareType           prepare;
+    VpTestConcludeType          conclude;
+    VpTestOpenVType             openV;
+    VpTestDcRLoopType           dcRloop;
+    VpTestAcRLoopType           acRloop;
+    VpTest3EleResAltResType     resFltAlt;
+    VpTestMSocketType           mSocket;
+    VpTestXConnectType          xConnect;
+    VpTest3EleCapAltResType     capAlt;
+    VpTestLoopCondType          loopCond;
+    VpTestLoopbackType          loopback;
+    VpTestRampType              ramp;
+    VpTestRampInitType          rampInit;
+} Vp880TestArgsType;
+
+typedef struct Vp880LineTestCalType {
+    uint8 slacState;
+    uint8 vpGain;
+    uint8 opCond;
+    uint8 opFunction;
+    uint8 icr2[VP880_ICR2_LEN];
+    uint8 icr3[VP880_ICR3_LEN];
+    uint8 icr4[VP880_ICR4_LEN];
+    uint8 icr6[VP880_ICR6_LEN];
+} Vp880LineTestCalType;
+
+typedef struct Vp880TestHeapType {
+    uint8 adcState;
+    int16 nextState; /**< Used when a pcm collection routine is started */
+
+    Vp880TestArgsType testArgs; /**< Saved test input arguments of current test */
+
+    uint8 opCond;                           /**< Saved Operation Condition */
+    uint8 opFunction;                       /**< Saved Operation Functions */
+    uint8 sigCtrl;                          /**< Signal Generator Control */
+    uint8 slacState;                        /**< Saved Slac State */
+    uint8 sysConfig;                        /** Saved System Configurations */
+    uint8 vpGain;                           /**< Voice Path Gain */
+    uint8 switchReg[VP880_REGULATOR_PARAM_LEN]; /**< Switching Reg Parameters */
+    uint8 dcFeed[VP880_DC_FEED_LEN];        /**< Saved DC Feed Parameters */
+    uint8 disn;                             /**< Digital Imped. Scaling Network */
+    uint8 SwRegCtrl;                        /**< Switching Regulator Control */
+
+    uint8 icr1[VP880_ICR1_LEN];
+    uint8 icr2[VP880_ICR2_LEN];
+    uint8 icr3[VP880_ICR3_LEN];
+    uint8 icr4[VP880_ICR4_LEN];
+    uint8 icr6[VP880_ICR6_LEN];
+    uint8 lpSuper[VP880_LOOP_SUP_LEN];      /**< Saved Loop Sup. Parameters */
+    uint8 sigGenAB[VP880_SIGA_PARAMS_LEN];  /**< Saved Signal Generator A & B */
+    uint8 b1Filter[VP880_B1_FILTER_LEN];    /**< Saved B1 filter coefficients */
+    uint8 b2Filter[VP880_B2_FILTER_LEN];    /**< Saved B2 filter coefficients */
+
+    /* lg res flt uses this to bump up the battery */
+    uint8 batCal[VP880_BAT_CALIBRATION_LEN];
+
+    /* used for collecting PCM data */
+    bool pcmRequest;        /** < indication that pcm data was requested */
+    VpPcmOperationMaskType operationMask;
+
+    VpPcmOperationResultsType pcmResults; /** < stores the pcm operation results */
+
+    /* Used for common setup functions */
+    uint16 commonSetupState;
+
+    /* Used for storing line event mask data */
+    VpOptionEventMaskType preTestEventMask;
+
+    /* Used for saving and restoring registers during calibration */
+    Vp880LineTestCalType calRegs;
+
+    /* Used for resflt lg speed up*/
+    uint16 speedupTime;
+    int16 previousAvg;
+    int16 vabComputed;
+    uint8 loopCnt;
+    bool compensate;
+    bool lowGain;
+
+    /* Used in the capacitance test */
+    int16 adcSampleBuffer[52];
+    uint8 requestedSamples;
+    uint8 saveConvConfig[VP880_CONV_CFG_LEN];
+    bool xtraBuffer;
+
+    /* The following members are for EZ mode calculations only*/
+#ifdef VP880_EZ_MPI_PCM_COLLECT
+    VpPcmComputeTempType ezPcmTemp;
+
+    /* Used to debug under and overflow pcm collect conditions */
+#ifdef VP_DEBUG
+    int8 underFlowValue;
+    uint32 overCnt;
+    uint32 underCnt;
+#endif
+#endif
+
+} Vp880TestHeapType;
+
+typedef struct Vp880CurrentTestType {
+    Vp880TestHeapType *pTestHeap;
+    uint8 testHeapId;
+
+    uint8 channelId;    /**< Channel # for "this" line on the device.  Indexed
+                         * starting at 0, should not exceed the max number of
+                         * lines supported by the device - 1 (max = 2, then
+                         * channelId = {0, 1}
+                         */
+
+    bool prepared;          /**< indicates if the current test is prepared */
+    bool preparing;         /**< indicates if the test prepare is complete */
+    bool concluding;        /**< indicates that the device is concluding a test */
+    bool nonIntrusiveTest;  /**< indicates a "stealth" test */
+    VpTestIdType testId;    /** < indicates the test currently running */
+
+    int16 testState;        /**< maintains the currnt state of the current TestId */
+    uint16 handle;
+
+} Vp880CurrentTestType;
+
+typedef struct Vp880CalOffCoeffs {
+    int16 nullOffset;
+    int16 vabOffset;
+    int16 vahOffset;
+    int16 valOffset;
+    int16 vbhOffset;
+    int16 vblOffset;
+    int16 imtOffset;
+    int16 ilgOffset;
+} Vp880CalOffCoeffs;
+
+#endif /*VP880_INCLUDE_TESTLINE_CODE*/
+
+typedef struct Vp880AbvCalData {
+    uint8 passCnt;
+    bool initChange;    /**< As needed, set to TRUE when a state is changed in
+                         * the calibration state machine.
+                         */
+
+    int16 swyVolt[2]; /**< One per channel used to measure SWY Voltage */
+    int16 swzVolt[2]; /**< One per channel used to measure SWZ Voltage */
+
+    uint8 isrpData[VP880_INT_SWREG_PARAM_LEN];
+    uint8 icr1[2][VP880_ICR1_LEN];
+    uint8 icr2[2][VP880_ICR2_LEN];
+    uint8 icr3[2][VP880_ICR3_LEN];
+    uint8 icr4[2][VP880_ICR4_LEN];
+    uint8 disnVal[2][VP880_DISN_LEN];
+    uint8 vpGain[2][VP880_VP_GAIN_LEN];
+    uint8 sysState[2][VP880_SYS_STATE_LEN];
+    uint8 opFunc[2][VP880_OP_FUNC_LEN];
+    uint8 opCond[2][VP880_OP_COND_LEN];
+    uint8 converterCfg[2][VP880_CONV_CFG_LEN];
+
+    /*
+     * This the switcher adjustments as determined by battery and VAS calibration
+     * procedures.
+     */
+    uint8 switcherAdjust[2][VP880_BAT_CALIBRATION_LEN];
+
+    /* This is to be compatible with VVA P1.3.0 */
+    int16 swyOffset[2];
+    int16 swzOffset[2];
+
+    /* This is to be compatible with VVA P1.3.0 but not currently measured. */
+    int16 swxbOffset[2];
+} Vp880AbvCalData;
+
+typedef struct Vp880CalLoopData {
+    int16 prevVal;
+    uint8 loopNum;
+    uint8 adcLoopMax;
+    uint8 adcRoute;
+} Vp880CalLoopData;
+
+typedef struct Vp880VocCalData {
+    int16 vocNorm;
+    int16 vocRev;
+} Vp880VocCalData;
+
+typedef struct Vp880CalTypeData {
+    int16 swyVolt;
+    Vp880CalLoopData loopData;
+    Vp880VocCalData vocData;
+} Vp880CalTypeData;
+
+
+#define VP880_AC_PROFILE_SIZE   (80)    /* 80 Bytes is fixed size known for 880
+                                         * AC Profiles up to PW 2.0.0
+                                         */
+#define VP880_DC_PROFILE_SIZE   (20)    /* 16 bytes should be enough, but this
+                                         * profile size has changed over time.
+                                         * Safe value with a few more bytes.
+                                         */
+
+#define VP880_RINGING_PROFILE_SIZE  (22)    /* 22 byte Ringing Profile size is
+                                             * the only size ever created for
+                                             * VE880 API. This should be enough.
+                                             */
+
+/*
+ * Bit-Masks for calibration update required if line configuration change
+ * attempted during calibration. Note that this only needs to flag/update the
+ * line configuration that may affect calibration.
+ */
+#define AC_PROFILE_UPDATE_REQ       0x1
+#define DC_PROFILE_UPDATE_REQ       0x2
+#define RINGING_PROFILE_UPDATE_REQ  0x4
+#define CODEC_UPDATE_REQ            0x8
+
+/*  these are in order of execution ALWAYS do not reorder them !!!! */
+typedef enum Vp880CalLineState {
+    VP880_CAL_SETUP                 =   0,
+    VP880_CAL_SETUP_RELEASE_CLAMPS,
+    VP880_RAMP_TO_POLREV_SETUP,
+    VP880_RAMP_TO_POLREV_RAMP1,
+    VP880_RAMP_TO_POLREV_SWAP_POLARITY,
+    VP880_RAMP_TO_POLREV_RAMP2,
+    VP880_RAMP_TO_POLREV_GOACTIVE,
+    VP880_RAMP_TO_POLREV_COMPLETE,
+
+    VP880_IMT_PR_SETUP              =   20,
+    VP880_IMT_PR_SET_ADC,
+    VP880_IMT_PR_MEASURE,
+
+#ifdef VP880_TRACKER_SUPPORT
+    VP880_VAS_PR_SETUP              =   30,
+    VP880_VAS_PR_STEP,
+    VP880_VAS_PR_SET_ADC,
+    VP880_VAS_PR_MEASURE,
+    VP880_VAS_PR_STORE,
+#endif
+
+    VP880_VAB_PR_SETUP              =   40,
+    VP880_VAB_PR_MEASURE,
+
+    VP880_VAB_PR_ADC_OFFSET_SETUP   =   50,
+    VP880_VAB_PR_ADC_OFFSET_MEASURE,
+
+    VP880_VA_PR_ADC_OFFSET_SETUP    =   60,
+    VP880_VA_PR_ADC_OFFSET_MEASURE,
+
+    VP880_VB_PR_ADC_OFFSET_SETUP    =   70,
+    VP880_VB_PR_ADC_OFFSET_MEASURE,
+
+    VP880_COLLAPSE_FEED             =   80,
+
+    VP880_GENA_NP_OFFSET_SETUP      =   90,
+    VP880_GENA_NP_OFFSET_SET_ADC,
+    VP880_GENA_NP_OFFSET_MEASURE,
+    VP880_GENA_NP_OFFSET_RESTORE,
+
+    VP880_ILG_OFFSET_SETUP          =   100,
+    VP880_ILG_OFFSET_MEASURE,
+
+    VP880_ILA_OFFSET_SETUP          =   110,
+    VP880_ILA_OFFSET_MEASURE,
+
+
+    VP880_RESTORE_DAC               =   120,
+
+    VP880_VAB_NP_ADC_OFFSET_SETUP   =   130,
+    VP880_VAB_NP_ADC_OFFSET_MEASURE,
+
+    VP880_VA_NP_ADC_OFFSET_SETUP    =   140,
+    VP880_VA_NP_ADC_OFFSET_MEASURE,
+
+    VP880_VB_NP_ADC_OFFSET_SETUP    =   150,
+    VP880_VB_NP_ADC_OFFSET_MEASURE,
+
+    VP880_ILA_SETUP                 =   160,
+    VP880_ILA_ADJUST,
+    VP880_ILA_SET_ADC,
+    VP880_ILA_MEASURE,
+    VP880_ILA_MEASURE_TRACKER,
+    VP880_ILA_MEASURE_ABS,
+
+    VP880_RESTORE_FEED              =   170,
+
+    VP880_IMT_NP_SETUP              =   180,
+    VP880_IMT_NP_SET_ADC,
+    VP880_IMT_NP_MEASURE,
+
+#ifdef VP880_TRACKER_SUPPORT
+    VP880_VAS_NP_SETUP              =   190,
+    VP880_VAS_NP_STEP,
+    VP880_VAS_NP_SET_ADC,
+    VP880_VAS_NP_MEASURE,
+    VP880_VAS_NP_STORE,
+#endif
+
+    VP880_VAB_NP_SETUP              =   200,
+    VP880_VAB_NP_MEASURE,
+
+    VP880_CAL_ADJUST                =   210,
+
+    VP880_CAL_RESTORE               =   254,
+
+    /**< Used in API to force valid/unused initial value */
+    VP880_CAL_ENUM_SIZE             = (VP880_CAL_RESTORE + 1)
+
+} Vp880CalLineState;
+
+typedef struct Vp880CalLineData {
+    bool calDone;           /**< TRUE when calibration has been performed on
+                             * this line
+                             */
+    bool reversePol;        /**< TRUE when line is in reverse polarity */
+
+    Vp880CalTypeData typeData;
+
+    uint8 codecReg;
+
+    uint8 dcFeedRef[VP880_DC_FEED_LEN]; /**< Customer settings per profile */
+    uint8 dcFeed[VP880_DC_FEED_LEN];    /**< Normal polarity calibrated values */
+    uint8 dcFeedPr[VP880_DC_FEED_LEN];  /**< Reverse polarity calibrated values */
+
+    Vp880CalLineState calLineState;
+    uint8 sysState;
+
+    uint8 icr2[VP880_ICR2_LEN];
+    uint8 icr3[VP880_ICR3_LEN];
+
+    uint8 disnVal[VP880_DISN_LEN];
+    uint8 vpGain[VP880_VP_GAIN_LEN];
+    uint8 loopSup[VP880_LOOP_SUP_LEN];
+
+    bool forceCalDataWrite;
+
+    /* Signal generator calibration temporary backup */
+    uint8 sigGenA[VP880_SIGA_PARAMS_LEN];
+    uint8 calReg[VP880_ICR6_LEN];
+    uint8 asscReg;
+
+    /**< Battery Calibration values used to compute final VAS values */
+    uint8 swCal[VP880_BAT_CALIBRATION_LEN];
+
+    uint16 minVas;  /**< Minimum VAS value determined during IMT calibration.
+                     * This is stored in the same format used to compute the VAS
+                     * value rather than the device format. This increases the
+                     * data memory space requirements slightly, but reduces the
+                     * size for code space and simplifies the logic when applied.
+                     */
+
+    uint16 vasStart;    /**< Starting point for VAS to reduce calibration time.
+                         * This value is based on battery adjustment and the
+                         * minimum vas allowed ("minVas" above).
+                         */
+
+    /*
+     * Cached user data applied after calibration in case line configuration is
+     * changed during calibration.
+     */
+    uint8 updateFlags;  /*
+                         * Bit-Mask to mark the information that needs to be
+                         * updated when calibration is complete. Note that some
+                         * information is automatically updated when calibration
+                         * is complete simply as part of the restore process.
+                         */
+    uint8 acProfile[VP880_AC_PROFILE_SIZE];
+    uint8 dcProfile[VP880_DC_PROFILE_SIZE];
+    uint8 ringingProfile[VP880_RINGING_PROFILE_SIZE];
+
+    VpLineStateType usrState;
+
+} Vp880CalLineData;
+
+typedef enum Vp880CalDeviceState {
+    VP880_CAL_INIT                  =   0,
+    VP880_CAL_ERROR,
+    VP880_CAL_MEASURE,
+    VP880_CAL_OFFSET,
+    VP880_CAL_ADC,
+    VP880_CAL_STATE_CHANGE,
+    VP880_CAL_INVERT_POL,
+    VP880_CONVERTER_CHECK,
+    VP880_CAL_DONE,
+    VP880_CAL_CLEANUP,
+    VP880_CAL_EXIT
+} Vp880CalDeviceState;
+
+typedef struct Vp880CalDeviceData {
+    Vp880AbvCalData abvData;
+    Vp880CalDeviceState calDeviceState;
+    int16 calSet;   /* Target values for calibration */
+    uint8 iteration;    /**< Used as fail-safe to prevent infinte retries */
+} Vp880CalDeviceData;
+
+typedef struct Vp880RingParams {
+    bool channelArray[VP880_MAX_NUM_CHANNELS];
+    uint8 stage[VP880_MAX_NUM_CHANNELS];
+    uint8 swRegParam[VP880_REGULATOR_PARAM_LEN];
+} Vp880RingParams;
+
+typedef struct Vp880LineObjectType {
+    uint8 channelId;    /**< Channel # for "this" line on the device.  Indexed
+                         * starting at 0, should not exceed the max number of
+                         * lines supported by the device - 1 (max = 2, then
+                         * channelId = {0, 1}
+                         */
+
+    uint8 ecVal;
+
+    VpTermType termType;    /**< Termination type */
+
+    uint16 status;  /**< Bit-mask of Vp880LineStatusType Keeps track of line state/config info*/
+
+#ifdef VP_CSLAC_SEQ_EN
+    VpSeqDataType cadence;      /**< Sequencer related information */
+
+    /**< Array to control internally run sequences */
+    VpProfileDataType intSequence[VP880_INT_SEQ_LEN];
+
+#ifdef VP880_FXS_SUPPORT
+    VpCallerIdType callerId;    /**< Caller ID related information */
+    VpCidSeqDataType cidSeq;    /**< CID Sequencer related information */
+    uint8 tickBeginState[VP880_CID_PARAM_LEN];
+    uint8 cidBytesRemain;
+    bool delayConsumed; /**< Set to TRUE when Polling Mode CID uses the loop
+                         * read/delay method and has started it.
+                         */
+
+    bool suspendCid;
+
+    VpProfilePtrType pRingingCadence;   /**< Currently used ringing cadence on
+                                         * this line
+                                         */
+
+    VpProfilePtrType pMeterProfile;     /**< Currently used metering profile on
+                                         * this line
+                                         */
+
+    VpProfilePtrType pCidProfileType1;  /**< Currently used caller ID profile
+                                         * on this line for sequenced cid
+                                         */
+#endif  /* VP880_FXS_SUPPORT */
+
+#ifdef VP880_FXO_SUPPORT
+    VpDigitGenerationDataType digitGenStruct;   /**< Used on FXO lines for
+                                                 * generating pulse digits
+                                                 */
+#endif  /* VP880_FXO_SUPPORT */
+#endif  /* VP_CSLAC_SEQ_EN */
+
+#ifdef VP880_FXS_SUPPORT
+    VpDialPulseDetectType dpStruct; /**< Used on FXS lines for detecting pulse
+                                     * digits
+                                     */
+
+    VpDialPulseDetectType dpStruct2;/**< Used on FXS lines for detecting pulse
+                                     * digits using 2nd set of dp specs.
+                                     */
+
+    VpOptionPulseModeType pulseMode;
+
+    /*
+     * Array to hold ringing parameters used in the Signal Generator.  This is
+     * needed when signal generator A is set to a tone, then set back to ringing
+     * without the user re-specifying the ringing profile
+     */
+    uint8 ringingParams[VP880_SIGA_PARAMS_LEN];
+
+    uint8 leakyLineCnt; /*
+                         * Keeps track of # of times off-hook was detected (LP Mode)
+                         * that was not further verified after exiting LP Mode. Reset
+                         * when off-hook is verified.
+                         */
+    /* Loop supervision parameters */
+    uint8 hookHysteresis;
+
+    bool internalTestTermApplied;
+
+    VpOptionRingControlType ringCtrl;
+
+    /*
+     * Used to track states for Ground Start Exit Timer Management. Use two steps - first step
+     * completes final state control, the second step is for final hook and ground key debounce.
+     */
+    uint8 gsTimerExitState;
+
+    /*
+     * Used to track states for Disconnect Exit Timer Management. Use two steps - first step
+     * completes final state control, the second step is for final hook and ground key debounce.
+     */
+    uint8 discTimerExitState;
+
+    VpRelayControlType relayState;   /**< Used to hold current line relay state */
+
+#endif
+
+    VpOptionEventMaskType lineEventsMask;
+    VpOptionEventMaskType lineEvents;
+
+    uint16 signaling1;
+    uint16 signaling2;
+    uint8 signalingData;    /**< Holds data for Signaling events on this line */
+
+
+#ifdef VP880_FXO_SUPPORT
+    uint8 fxoData;          /**< Holds data for FXO events on this line */
+    uint8 preRingPolRev;    /**< The polarity detected prior to ring detect */
+    VpCslacLineCondType preDisconnect;    /**< The disconnect state prior to timer start */
+
+    uint8 ringDetMax;   /**< Stores the user specified maximum ringing detect
+                         * period for FXO lines. This value may be outside the
+                         * device range, in which case the SW will implement
+                         * upper period detection
+                         */
+    uint8 ringDetMin;   /**< Stores the user specified maximum ringing detect
+                         * period for FXO lines that is within the device range.
+                         * This value is used as "minimum" that is detected by
+                         * SW. Actual minimum period is supported by the device
+                         * period detector itself.
+                         */
+#endif
+
+    uint16 processData;     /**< Holds data for Process events on this line */
+
+    uint8 responseData;     /**< Holds data for Response events on this line */
+
+    VpCslacTimerStruct lineTimers; /**< Timers for "this" line */
+    VpApiIntLineStateType lineState;    /**< Line state info used for state
+                                         * transition handling and recall
+                                         */
+    uint8 nextSlicValue;
+    uint8 slicValueCache;   /**< Used to reduce MPI reads. */
+
+    /*
+     * Holds user definition for Loop Supervision configuration when
+     * "badLoopSup" is TRUE
+     */
+    uint8 loopSup[VP880_LOOP_SUP_LEN];
+
+    uint16 lineEventHandle; /**< Line specific event handle information */
+
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;   /* Defines how the PCM highway is
+                                             * set for "talk" linestates
+                                             */
+
+    uint16 dtmfDigitSense;          /**< Used to hold the DTMF digit reported
+                                     * with VpDtmfDigitDetected() until the
+                                     * VP_LINE_EVID_DTMF_DIG is generated.
+                                     */
+
+    VpLineIdType lineId;    /**< Application provided value for mapping a line to
+                             * a line context
+                             */
+    /*
+     * NOTE: Do not move the location or name of these members. These may be
+     * used by applications to determine the gain of the GX/GR blocks in the
+     * AC profile. Using return from VpSetRelGain() is not usefull because that
+     * is the register setting. The customer would have to know how to convert
+     * that to linear values, which is not generally documented.
+     */
+    struct Vp880RelGainValues {
+        uint16 gxInt;       /**< Cached GX register, in 2.14 int format */
+        uint16 grInt;       /**< Cached GR register, in 2.14 int format */
+        int16 absGxGain;    /**< Cached ABS A-to-D Gain, simplifies code. */
+        int16 absGrGain;    /**< Cached ABS D-to-A Gain, simplifies code. */
+    } gain;
+
+    Vp880CalLineData calLineData;
+
+    VpOptionCodecType codec;
+
+#ifdef VP880_FXS_SUPPORT
+    VpHowlerModeCachedValues howlerModeCache;
+
+    uint8 icr1Values[VP880_ICR1_LEN];   /**< Cached to minimize device access */
+    uint8 icr2Values[VP880_ICR2_LEN];   /**< Cached to minimize device access */
+    uint8 icr3Values[VP880_ICR3_LEN];   /**< Cached to minimize device access */
+    uint8 icr4Values[VP880_ICR4_LEN];   /**< Cached to minimize device access */
+    uint8 icr6Values[VP880_ICR6_LEN];   /**< Cached to minimize device access */
+#endif
+
+    uint8 opCond[VP880_OP_COND_LEN];    /**< Cached to minimize device access */
+    uint8 sigGenCtrl[VP880_GEN_CTRL_LEN];   /**< Cached to minimize device access */
+
+#ifdef VP_DEBUG
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+#endif
+
+} Vp880LineObjectType;
+
+/*
+ * IMPORTANT: Make sure to update the "stateInt" member of the device object if
+ * the size of this type changes. There is no instance of this type itself.
+ */
+typedef uint32 Vp880DeviceStateIntType;
+#define VP880_IS_ABS                (0x0001)    /**< Set when the device is ABS type */
+#define VP880_RLY_PROT_REQ          (0x0002)    /**< Set when the device requires relay protction on I/O 1 */
+#define VP880_HAS_TEST_LOAD_SWITCH  (0x0004)    /**< Set when test load swith is available */
+#define VP880_HAS_CALIBRATE_CIRCUIT (0x0008)    /**< Set when test cal circuit is available */
+
+#define VP880_IS_HIGH_VOLTAGE       (0x0010)    /**< Set when device is a high voltage device */
+#define VP880_IS_SINGLE_CHANNEL     (0x0020)    /**< Set when a single channel device is found*/
+#define VP880_SYS_CAL_RESET         (0x0040)    /**< Set when Apply Cal is passed NULL to reset calibration values */
+#define VP880_LINE0_IS_FXO          (0x0080)    /**< Set if device detection indicates line0 as FXO */
+
+#define VP880_LINE1_IS_FXO          (0x0100)    /**< Set if device detection indicates line1 as FXO */
+#define VP880_WIDEBAND              (0x0200)    /**< Set if device supports Wideband mode */
+#define VP880_LINE0_LP              (0x0400)    /**< Set if line 0 allows low power mode */
+#define VP880_LINE1_LP              (0x0800)    /**< Set if line 1 allows low power mode */
+
+#define VP880_IS_FXO_ONLY           (0x1000)    /**< Set when the device contains only FXO lines */
+#define VP880_SYS_CAL_COMPLETE      (0x2000)    /**< Set when the system calibration structure has been initialied */
+#define VP880_CAL_RELOAD_REQ        (0x4000)    /**< Set when the line calibration values need to be reloaded. */
+#define VP880_FORCE_FREE_RUN        (0x8000)    /**< Set when app calls VpFreeRun() (start), cleared when called with stop.
+                                                 * This prevents the VP-API-II from automatically exiting free run mode
+                                                 * upon PCLK recovery.
+                                                 */
+
+#define VP880_SWY_DECAY_CMP         (0x10000)
+#define VP880_SWZ_DECAY_CMP         (0x20000)
+
+#define VP880_IS_TEST_CAPABLE       (0x40000)   /**< Set for devices that support Line Test */
+
+/*
+ * This value is set when either Device Calibration (VpInitDevice()/VpCalCodec()
+ * completes successfully, or when loaded values by Apply System Coeff. After
+ * VpInitDevice() this should only be NOT SET if device calibration failed or
+ * if null was passed to Apply System Coeff.
+ */
+#define VP880_DEVICE_CAL_COMPLETE   (0x80000)
+
+
+#define VP880_SYS_CAL_POLARITY_LENGTH  2
+#define VP880_SYS_CAL_CHANNEL_LENGTH   2
+
+/* Contains calibration error values -- in +/-10mv LSB */
+typedef struct Vp880SysCalResultsType {
+    int16 abvError[2];
+
+    int16 vocOffset[VP880_SYS_CAL_CHANNEL_LENGTH][VP880_SYS_CAL_POLARITY_LENGTH];
+    int16 vocError[VP880_SYS_CAL_CHANNEL_LENGTH][VP880_SYS_CAL_POLARITY_LENGTH];
+
+    int16 sigGenAError[VP880_SYS_CAL_CHANNEL_LENGTH][VP880_SYS_CAL_POLARITY_LENGTH];
+
+    int16 ila20[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila25[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila32[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila40[VP880_SYS_CAL_CHANNEL_LENGTH];
+
+    int16 ilaOffsetNorm[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 ilgOffsetNorm[VP880_SYS_CAL_CHANNEL_LENGTH];
+
+    /* Used for Tracker only */
+    uint8 vas[VP880_SYS_CAL_CHANNEL_LENGTH][VP880_SYS_CAL_POLARITY_LENGTH];
+
+    int16 vagOffsetNorm[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 vagOffsetRev[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 vbgOffsetNorm[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 vbgOffsetRev[VP880_SYS_CAL_CHANNEL_LENGTH];
+
+    /* Used for ABS only */
+    uint8 absNormCal[VP880_SYS_CAL_CHANNEL_LENGTH];
+    uint8 absPolRevCal[VP880_SYS_CAL_CHANNEL_LENGTH];
+
+    int16 swyOffset[VP880_SYS_CAL_CHANNEL_LENGTH];     /**< Used to hold SWY Offset */
+    int16 swzOffset[VP880_SYS_CAL_CHANNEL_LENGTH];     /**< Used to hold SWZ Offset */
+    int16 swxbOffset[VP880_SYS_CAL_CHANNEL_LENGTH];    /**< Used to hold SWXB Offset */
+
+    /* Used for capacitance line test only */
+    int32 tipCapCal[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int32 ringCapCal[VP880_SYS_CAL_CHANNEL_LENGTH];
+} Vp880SysCalResultsType;
+
+#define VP880_CAL_STRUCT_SIZE   (40*sizeof(int16) + 8*sizeof(uint8) + 4*sizeof(int32))
+
+typedef struct Vp880DeviceObjectType {
+    /* Device identifier set by the application -- passed to the HAL */
+    VpDeviceIdType deviceId;
+
+    /* Silicon RCN/PCN and number of channels supported */
+    VpDeviceStaticInfoType staticInfo;
+
+    /*
+     * Weak attempt to put everything that changes during run-time into a
+     * single structure. Good idea in principle, but in practice the devices
+     * are too dis-similar to share many common structures.
+     *
+     * This holds the "last channel checked" event information, clock fault,
+     * and battery fault.
+    */
+    VpDeviceDynamicInfoType dynamicInfo;
+
+    /*
+     * Variety of common device level status such as init/not init, init in
+     * progress, test buffer read y/n?, etc.. Internally used by the VP-API-II
+     * to communicate device state.
+     *
+     * This is a bit-mask of VpDeviceStateType values
+     */
+    uint16 state;
+
+    /*
+     * Similar to common device level status, this is for 880 specific type of
+     * device level information. Such as ABS/Tracker, LPM lines, etc..
+     *
+     * This is a bit-mask of Vp880DeviceStateIntType values
+     */
+    uint32 stateInt;
+
+    /*-----------------3/18/2010 3:51PM-----------------
+     * Device Level OPTION Values
+     * --------------------------------------------------*/
+    /* OPTION_ID_EVENT_MASK for device level events */
+    VpOptionEventMaskType deviceEventsMask;
+
+    /* OPTION_ID_PULSE */
+    VpOptionPulseType pulseSpecs;
+
+    /* OPTION_ID_PULSE2 */
+    VpOptionPulseType pulseSpecs2;
+
+    /* OPTION_ID_CRITICAL_FLT */
+    VpOptionCriticalFltType criticalFault;
+
+    /*
+     * Stored device level events. Note that this is an alternative method to
+     * an event queue. So if an event queue is later used, this value could be
+     * removed and all it's uses replaced.
+     */
+    VpOptionEventMaskType deviceEvents;
+
+    /*
+     * Device level timers such as clock fault, LPM Enter/Exit, VpCalCodec()
+     * steps, etc..
+     */
+    uint16 devTimer[VP_DEV_TIMER_LAST];
+
+    /*
+     * Soft values from the device profile that are used throughout the VP-API-II
+     * (not only in Init). Note that other values may be provided by the device
+     * profile, but are stored in other ways generally because they also may NOT
+     * be provided in the device profile (i.e., API has default values).
+     */
+    Vp880DeviceProfileType devProfileData;
+
+    /* This is the profile pointer table per the VP-API-II User's Guide. */
+    VpCSLACDeviceProfileTableType devProfileTable;
+
+    /*
+     * This is the structure indicating which profile table entries have been
+     * initialized. If profile tables are disabled, this and the device profile
+     * table (devProfileTable) can be removed.
+     */
+    VpCSLACProfileTableEntryType profEntry;
+
+    /*
+     * Raw information from the device signaling register last read. This
+     * information is internally converted into useable VP-API-II information.
+     */
+    uint8 intReg[VP880_UL_SIGREG_LEN];
+    uint8 intReg2[VP880_UL_SIGREG_LEN];
+
+    /* Buffer to support VpLowLevelCmd() only. */
+#if !defined(VP_REDUCED_API_IF) || defined(ZARLINK_CFG_INTERNAL)
+    uint8 mpiData[VP880_MAX_MPI_DATA];
+#endif
+
+    /*
+     * Data length copied into mpiData buffer -- used for VpLowLevelCmd() and
+     * Apply/Get System Calibration
+     */
+    uint8 mpiLen;
+
+    /* Handle to return with events as applicable */
+    uint16 eventHandle;
+
+    /*
+     * VP-API-II timing in 500us increments (per the VP-API-II User's Guide).
+     * Generally incremented at the tick rate.
+     */
+    uint16 timeStamp;
+    int16 timeRemainder;    /**< leftover of tick time for tickrates not divisible by 0.5ms */
+
+    /* Data returned with response events as applicable */
+    uint8 responseData;
+
+    /* Data returned with "Get Option" events */
+    VpGetResultsOptionsType getResultsOption;
+
+    /* Data returned with VpSetRelGain() function call/event. */
+    VpRelGainResultsType relGainResults;
+
+#if defined (VP880_INCLUDE_TESTLINE_CODE)
+    /* Testing structure */
+    VpTestResultType testResults;
+
+    Vp880CurrentTestType currentTest;
+
+    /**< Used to hold calibration offset coeffs. One per channel */
+    Vp880CalOffCoeffs calOffsets[VP880_MAX_NUM_CHANNELS];
+
+#endif /* VP880_INCLUDE_TESTLINE_CODE */
+
+
+    /*
+     * Used to hold battery switch calibration offset. One per channel, per
+     * polarity
+     */
+    uint8 calState;
+    Vp880CalDeviceData calData;
+
+    /*
+     * Used to get better hook granularity and pcm buffered data.
+     */
+    uint8 txBuffer[VP880_TX_PCM_BUFF_LEN];
+    uint8 txBufferDataRate;
+
+    /*
+     * These switcher paramaters are from the user setting in the
+     * device profile. They should never be changed except in Init (in case
+     * the values provided are illegal).
+     */
+    uint8 swParams[VP880_REGULATOR_PARAM_LEN];
+
+    /*
+     * These switcher paramaters should always be a SW representation of the
+     * silicon used to reduce device level access. The driver MUST change this
+     * setting if the device itself is changed.
+     */
+    uint8 swParamsCache[VP880_REGULATOR_PARAM_LEN];
+
+    /*
+     * These internal switcher paramaters are from the user setting in the
+     * device profile. They should never be changed except in Init (in case
+     * the values provided are illegal).
+     */
+    uint8 intSwParams[VP880_INT_SWREG_PARAM_LEN];
+
+    /*
+     * These internal switcher paramaters are for Free Run mode only and should
+     * only be set during Init Device (in case a set was not provided or if the
+     * provided set is illegal).
+     */
+    uint8 intSwParamsFR[VP880_INT_SWREG_PARAM_LEN];
+
+    uint8 yVolt;    /* Y-Switcher Target in 1V step */
+    uint8 zVolt;    /* Z-Switcher Target in 1V step */
+
+#if defined (VP_CC_880_SERIES) || defined (VP_CC_KWRAP)
+    Vp880SysCalResultsType vp880SysCalData;
+#endif
+
+    /* used to store the in-rush current function data */
+    Vp880RingParams ringParams;
+
+#ifdef VP_DEBUG
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+#endif
+
+    /* Used to hold the device level ecVal (to keep track of WB mode). */
+    uint8 ecVal;
+
+    /*
+     * Holds the last channel information changed to/from Wideband mode since
+     * the last tick. If = 0, no change has been made. If = 1, ch0 if = 2, ch1.
+     * This is a handshake with the tick which detects it is not 0, makes the
+     * appropriate change and sets it back to 0.
+     */
+    uint8 lastCodecChange;
+
+    /* Device Mode Register (0x5E/5F) cached to minimize MPI traffic */
+    uint8 devMode[VP880_DEV_MODE_LEN];
+} Vp880DeviceObjectType;
+
+#endif  /**< vp880_api.h */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp890_api.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp890_api.h
new file mode 100755
index 0000000..1bef289
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp890_api.h
@@ -0,0 +1,851 @@
+/** \file vp890_api.h
+ * vp890_api.h
+ *
+ *  Header file that define all the commands for the Vp890 device.
+ *
+ * $Revision: 9253 $
+ * $LastChangedDate: 2011-12-14 11:08:16 -0600 (Wed, 14 Dec 2011) $
+ */
+
+#ifndef VP890_API_H
+#define VP890_API_H
+
+#include "vp_hal.h"
+#include "vp_CSLAC_types.h"
+#include "vp_api_common.h"
+
+#ifdef VP890_INCLUDE_TESTLINE_CODE
+#include "vp_api_test.h"
+  #ifdef VP890_EZ_MPI_PCM_COLLECT
+  #include  "vp_pcm_compute.h"
+  #endif
+#endif
+
+/*
+ * Note that this value must be >=2 even when only using the single FXO device.
+ * That's because this is often used in looping through the line context pointers
+ * in the device context indexed by "channelId". The FXO channelId = 1 so the
+ * loop operations must be allowed to index into the second element.
+ */
+#define VP890_MAX_NUM_CHANNELS   2
+
+#define VP890_MAX_MPI_DATA      15   /* Max data from any MPI read command */
+#define VP890_INT_SEQ_LEN       22
+
+#ifndef VP890_UL_SIGREG_LEN
+#define VP890_UL_SIGREG_LEN         0x02
+#endif
+
+#ifndef VP890_B1_FILTER_LEN
+#define VP890_B1_FILTER_LEN         0x0E
+#endif
+
+#ifndef VP890_B2_FILTER_LEN
+#define VP890_B2_FILTER_LEN         0x02
+#endif
+
+#ifndef VP890_SIGA_PARAMS_LEN
+#define VP890_SIGA_PARAMS_LEN       0x0B
+#endif
+
+#ifndef VP890_DC_FEED_LEN
+#define VP890_DC_FEED_LEN           0x02
+#endif
+
+
+#ifndef VP890_ICR1_LEN
+#define VP890_ICR1_LEN              0x04
+#endif
+
+#ifndef VP890_ICR2_LEN
+#define VP890_ICR2_LEN              0x04
+#endif
+
+#ifndef VP890_ICR3_LEN
+#define VP890_ICR3_LEN              0x04
+#endif
+
+#ifndef VP890_ICR4_LEN
+#define VP890_ICR4_LEN              0x04
+#endif
+
+#ifndef VP890_DC_CAL_REG_LEN
+#define VP890_DC_CAL_REG_LEN        0x02
+#endif
+
+#ifndef VP890_LOOP_SUP_LEN
+#define VP890_LOOP_SUP_LEN          0x04
+#endif
+
+#ifndef VP890_TEST_DATA_LEN
+#define VP890_TEST_DATA_LEN         0x0E
+#endif
+
+#ifndef VP890_REGULATOR_PARAM_LEN
+#define VP890_REGULATOR_PARAM_LEN   0x03
+#endif
+
+#ifndef VP890_REGULATOR_TIMING_LEN
+#define VP890_REGULATOR_TIMING_LEN  0x06
+#endif
+
+#ifndef VP890_REGULATOR_CTRL_LEN
+#define VP890_REGULATOR_CTRL_LEN    0x01
+#endif
+
+#ifndef VP890_CONV_CFG_LEN
+#define VP890_CONV_CFG_LEN      0x01
+#endif
+
+/**< Required Vp890 Device and Line Objects for user instantiation if a Vp890
+ * device is used
+ */
+
+/**< Structure that defines the Vp890 Device Profile. Current as of the first
+ * Device Profile version (ver 0).
+ */
+typedef struct Vp890DeviceProfileType {
+    uint8   profVersion;
+    uint16  pcmClkRate;      /**< Used to verify valid TX/RX Timeslot setting */
+    uint8   mClkMask;
+    uint16  tickRate;        /**< Primary API-II tick for this device */
+    uint8   devCfg1;
+    uint8   clockSlot;
+
+#ifdef VP890_FXS_SUPPORT
+    uint8   swParams[VP890_REGULATOR_PARAM_LEN];
+    uint8   timingParams[VP890_REGULATOR_TIMING_LEN];
+    uint8   timingParamsFR[VP890_REGULATOR_TIMING_LEN];
+
+    bool    peakManagement;
+    bool    lowVoltOverride;
+#endif
+} Vp890DeviceProfileType;
+
+#if defined (VP890_INCLUDE_TESTLINE_CODE)
+
+/* Definitions for Test arguments */
+typedef union Vp890TestArgsType {
+    VpTestPrepareType           prepare;
+    VpTestConcludeType          conclude;
+    VpTestOpenVType             openV;
+    VpTestDcRLoopType           dcRloop;
+    VpTestAcRLoopType           acRloop;
+    VpTest3EleResAltResType     resFltAlt;
+    VpTestMSocketType           mSocket;
+    VpTestXConnectType          xConnect;
+    VpTest3EleCapAltResType     capAlt;
+    VpTestLoopCondType          loopCond;
+    VpTestLoopbackType          loopback;
+    VpTestRampType              ramp;
+    VpTestRampInitType          rampInit;
+} Vp890TestArgsType;
+
+typedef struct Vp890LineTestCalType {
+    uint8 slacState;
+    uint8 vpGain;
+    uint8 opCond;
+    uint8 opFunction;
+    uint8 switchTimes[VP890_REGULATOR_TIMING_LEN];
+    uint8 icr2[VP890_ICR2_LEN];
+    uint8 icr3[VP890_ICR3_LEN];
+    uint8 icr4[VP890_ICR4_LEN];
+    uint8 icr6[VP890_DC_CAL_REG_LEN];
+} Vp890LineTestCalType;
+
+typedef struct Vp890TestHeapType {
+    uint8 adcState;
+    int16 nextState; /**< Used when a pcm collection routine is started */
+
+    Vp890TestArgsType testArgs; /**< Saved test input arguments of current test */
+
+    uint8 opCond;                           /**< Saved Operation Condition */
+    uint8 opFunction;                       /**< Saved Operation Functions */
+    uint8 opMode;                           /**< Saved Operating Mode */
+    uint8 sysConfig;                        /** Saved System Configurations */
+    uint8 sigCtrl;                          /**< Signal Generator Control */
+    uint8 convCfg;                          /**< Saved Converter Config */
+    uint8 slacState;                        /**< Saved Slac State */
+    uint8 vpGain;                           /**< Voice Path Gain */
+    uint8 disn;                             /**< Digital Imped. Scaling Network */
+    uint8 lpSuper[VP890_LOOP_SUP_LEN];      /**< Saved Loop Sup. Parameters */
+    uint8 dcFeed[VP890_DC_FEED_LEN];        /**< Saved DC Feed Parameters */
+    uint8 switchReg[VP890_REGULATOR_PARAM_LEN]; /**< Switching Reg Parameters */
+    uint8 switchTimes[VP890_REGULATOR_TIMING_LEN]; /**< Switching Reg Timing */
+
+    uint8 icr1[VP890_ICR1_LEN];
+    uint8 icr2[VP890_ICR2_LEN];
+    uint8 icr3[VP890_ICR3_LEN];
+    uint8 icr4[VP890_ICR4_LEN];
+    uint8 icr6[VP890_DC_CAL_REG_LEN];
+    uint8 sigGenAB[VP890_SIGA_PARAMS_LEN]; /**< Saved Signal Generator A & B*/
+    uint8 b1Filter[VP890_B1_FILTER_LEN];   /**< Saved B1 filter coefficients */
+    uint8 b2Filter[VP890_B2_FILTER_LEN];   /**< Saved B2 filter coefficients */
+
+    /* used for collecting PCM data */
+    bool pcmRequest;        /** < indication that pcm data was requested */
+    VpPcmOperationMaskType operationMask;
+
+    VpPcmOperationResultsType pcmResults; /** < stores the pcm operation results */
+
+    /* Used for common setup functions */
+    uint16 commonSetupState;
+
+    /* Used for storing line event mask data */
+    VpOptionEventMaskType preTestEventMask;
+
+    /* Used for saving and restoring slac state after calibration */
+    uint8 calSlacState;
+
+     /* Used for saving and restoring registers during calibration */
+    Vp890LineTestCalType calRegs;
+
+    /* Used for resflt lg speed up*/
+    uint16 speedupTime;
+    int16 previousAvg;
+    int16 vabComputed;
+    uint8 loopCnt;
+    bool compensate;
+    bool lowGain;
+
+    /* Used in the capacitance test */
+    int16 adcSampleBuffer[52];
+    uint8 requestedSamples;
+    uint8 saveConvConfig[VP890_CONV_CFG_LEN];
+    bool xtraBuffer;
+
+    /* The following members are for EZ mode calculations only*/
+#ifdef VP890_EZ_MPI_PCM_COLLECT
+    VpPcmComputeTempType ezPcmTemp;
+
+    /* Used to debug under and overflow pcm collect conditions */
+#ifdef VP_DEBUG
+    int8 underFlowValue;
+    uint32 overCnt;
+    uint32 underCnt;
+#endif
+
+#endif
+
+} Vp890TestHeapType;
+
+typedef struct Vp890CurrentTestType {
+    Vp890TestHeapType *pTestHeap;
+    uint8 testHeapId;
+
+    uint8 channelId;    /**< Channel # for "this" line on the device.  Indexed
+                         * starting at 0, should not exceed the max number of
+                         * lines supported by the device - 1 (max = 2, then
+                         * channelId = {0, 1}
+                         */
+
+    bool prepared;          /**< indicates if the current test is prepared */
+    bool preparing;         /**< indicates if the test prepare is complete */
+    bool concluding;        /**< indicates that the device is concluding a test */
+    bool nonIntrusiveTest;  /**< indicates a "stealth" test */
+    VpTestIdType testId;    /** < indicates the test currently running */
+
+    int16 testState;        /**< maintains the currnt state of the current TestId */
+    uint16 handle;
+
+} Vp890CurrentTestType;
+
+typedef struct Vp890CalOffCoeffs {
+    int16 nullOffset;
+    int16 vabOffset;
+    int16 vahOffset;
+    int16 valOffset;
+    int16 vbhOffset;
+    int16 vblOffset;
+    int16 batOffset;
+    int16 imtOffset;
+    int16 ilgOffset;
+} Vp890CalOffCoeffs;
+
+#endif /*VP890_INCLUDE_TESTLINE_CODE*/
+
+typedef enum Vp890BFiltCalStates {
+    VP890_BFILT_MEASURE,
+    VP890_BFILT_END
+} Vp890BFiltCalStates;
+
+#ifndef VP890_B1_FILTER_LEN
+#define VP890_B1_FILTER_LEN         0x0E
+#endif
+
+#ifndef VP890_B2_FILTER_LEN
+#define VP890_B2_FILTER_LEN         0x02
+#endif
+
+#ifndef VP890_OP_FUNC_LEN
+#define VP890_OP_FUNC_LEN           0x01
+#endif
+
+#ifndef VP890_OP_COND_LEN
+#define VP890_OP_COND_LEN           0x01
+#endif
+
+#ifndef VP890_CONV_CFG_LEN
+#define VP890_CONV_CFG_LEN          0x01
+#endif
+
+#ifndef VP890_VP_GAIN_LEN
+#define VP890_VP_GAIN_LEN           0x01
+#endif
+
+#ifndef VP890_DISN_LEN
+#define VP890_DISN_LEN              0x01
+#endif
+
+#ifndef VP890_SYS_STATE_LEN
+#define VP890_SYS_STATE_LEN         0x01
+#endif
+
+#ifndef VP890_GEN_CTRL_LEN
+#define VP890_GEN_CTRL_LEN          0x01
+#endif
+
+#ifndef VP890_DEV_MODE_LEN
+#define VP890_DEV_MODE_LEN          0x01
+#endif
+
+#ifndef VP890_CID_PARAM_LEN
+#define VP890_CID_PARAM_LEN         0x01
+#endif
+
+#ifndef VP890_BAT_CALIBRATION_LEN
+#define VP890_BAT_CALIBRATION_LEN   0x02
+#endif
+
+typedef struct Vp890CalBFilterData {
+    VpCalBFilterType inputData;
+    uint8 b1FiltData[VP890_B1_FILTER_LEN];
+    uint8 b2FiltData[VP890_B2_FILTER_LEN];
+    uint8 opFunct[VP890_OP_FUNC_LEN];
+    uint8 opCond[VP890_OP_COND_LEN];
+    uint8 convCfg[VP890_CONV_CFG_LEN];
+    uint8 vpGain[VP890_VP_GAIN_LEN];
+    uint16 vRms;
+    uint8 listLength;   /* In number of B-Filter coefficient sets */
+    int8 currentSet;    /* Number of currently running B-Filter set */
+    int8 bestSet;       /* Number of the best set so far */
+} Vp890CalBFilterData;
+
+#define VP890_BFILT_SAMPLE_TIME     (70)
+
+/*
+ * IMPORTANT: Make sure to update the "stateInt" member of the device object if
+ * the size of this type changes. There is no instance of this type itself.
+ */
+#define VP890_RESET             (0x0000)    /**< Set at the begining of init device */
+#define VP890_IS_HIGH_VOLTAGE   (0x0010)    /**< Set when device is high voltage device */
+#define VP890_IS_SINGLE_CHANNEL (0x0020)    /**< Set when a single channel device is found*/
+#define VP890_LINE1_IS_FXO      (0x0100)    /**< Set if device detection indicates line1 as FXO */
+#define VP890_WIDEBAND          (0x0200)    /**< Set if device supports Wideband mode */
+#define VP890_LINE0_LP          (0x0400)    /**< Set if line 0 allows low power mode */
+#define VP890_LINE1_LP          (0x0800)    /**< Set if line 1 allows low power mode */
+#define VP890_IS_FXO_ONLY       (0x1000)    /**< Set when the device contains only FXO lines */
+#define VP890_SYS_CAL_COMPLETE  (0x2000)    /**< Set when the system calibration structure has been initialied */
+#define VP890_CAL_RELOAD_REQ    (0x4000)    /**< Set when the line calibration values need to be reloaded. */
+#define VP890_FORCE_FREE_RUN    (0x8000)    /**< Set when app calls VpFreeRun() (start), cleared when called with stop.
+                                             * This prevents the VP-API-II from automatically exiting free run mode
+                                             * upon PCLK recovery.
+                                             */
+
+/**< Line Status types to minimize code space in line object (compared to each
+ * status being maintined by a uint8 type)
+ */
+typedef enum Vp890LineStatusType {
+    VP890_INIT_STATUS   = 0x0000,
+
+    VP890_IS_FXO        = 0x0001,   /**< Set if the line is configured for FXO */
+
+    VP890_BAD_LOOP_SUP  = 0x0002,   /**< Set when the Loop Supervision has been
+                                     * changed in such a way inconsistent with
+                                     * the user's specifications. This is done
+                                     * in internal to the API to make some
+                                     * functions work (e.g., Msg Wait Pulse).
+                                     */
+
+    VP890_DP_SET1_DONE  = 0x0004,   /**< Set when Dial Pulse detection machine
+                                     * is "done" on the current dial pulse using
+                                     * the "first" set of DP parameters
+                                     */
+
+    VP890_DP_SET2_DONE  = 0x0008,   /**< Set when Dial Pulse detection machine
+                                     * is "done" on the current dial pulse using
+                                     * the 2nd set of DP parameters
+                                     */
+
+    VP890_SLS_CALL_FROM_API = 0x0010,   /**< Set if Set Line State is called
+                                         * from an API function (e.g., cadence).
+                                         */
+
+    VP890_LINE_IN_CAL = 0x0020,     /**< Set while line running cal routine */
+
+    VP890_LOW_POWER_EN = 0x0080,    /**< Set when line is operating in low power
+                                     * mode
+                                     */
+
+    VP890_LINE_LEAK = 0x0100,      /**< Set when leakage is detected on the line
+                                    * such that low power mode is prevented.
+                                    */
+    VP890_CHECK_LEAK = 0x0200,     /**< Set when API-II is testing for leakage
+                                    * on the line
+                                    */
+    VP890_INIT_COMPLETE = 0x0800,  /**< Set when InitLine has been completed
+                                    * on this line.
+                                    */
+    VP890_PREVIOUS_HOOK = 0x1000,  /**< Set if Last Hook Event reported was
+                                    * off-hook, cleared if last event was
+                                    * on-hook.
+                                    */
+    VP890_RING_GEN_NORM = 0x2000,  /**< Set when the Generators are known last
+                                    * to be programmed to the application
+                                    * specified ringing profile. Cleared
+                                    * when line tests are run because the same
+                                    * generator is used for non-ringing.
+                                    */
+    VP890_RING_GEN_REV = 0x4000    /**< Set when the Generators are known last
+                                    * to be programmed to the application
+                                    * specified ringing profile. Cleared
+                                    * when line tests are run because the same
+                                    * generator is used for non-ringing.
+                                    */
+} Vp890LineStatusType;
+
+typedef struct Vp890CidCorrectionPair {
+    uint16  volts;
+    uint16  gain;
+} Vp890CidCorrectionPair;
+
+typedef enum Vp890PllRecoveryStateType {
+    VP890_PLL_RECOVERY_ST_RESET,
+    VP890_PLL_RECOVERY_ST_DISABLE,
+    VP890_PLL_RECOVERY_ST_ENABLE_1,
+    VP890_PLL_RECOVERY_ST_ENABLE_2,
+    VP890_PLL_RECOVERY_ST_MEASURE,
+    VP890_PLL_RECOVERY_ST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req*/
+} Vp890PllRecoveryStateType;
+
+typedef struct Vp890CalLoopData {
+    int16 prevVal;
+    uint8 loopNum;
+    uint8 adcLoopMax;
+    uint8 adcRoute;
+} Vp890CalLoopData;
+
+typedef struct Vp890IlaCalData {
+    int16 ilaNorm;
+    int16 ilgNorm;
+} Vp890IlaCalData;
+
+typedef struct Vp890VocCalData {
+    int16 vocNorm;
+    int16 vocRev;
+} Vp890VocCalData;
+
+
+typedef struct Vp890CalTypeData {
+    int16 swyVolt;
+    Vp890CalLoopData loopData;
+    Vp890IlaCalData ilaData;
+    Vp890VocCalData vocData;
+    Vp890CalBFilterData bFilterData;
+} Vp890CalTypeData;
+
+typedef struct Vp890CalLineData {
+    bool calDone;           /**< TRUE when calibration has been performed on
+                             * this line
+                             */
+    bool reversePol;        /**< TRUE if CAL starts in polrev */
+
+    Vp890CalTypeData typeData;
+
+    uint8 codecReg;
+
+    uint8 dcFeedRef[VP890_DC_FEED_LEN];         /* Copied from dc profile */
+    uint8 dcFeed[VP890_DC_FEED_LEN];            /* use for VAS and VOC */
+    uint8 dcFeedPr[VP890_DC_FEED_LEN];          /* use for VAS and VOC */
+
+    uint16 calState;
+    uint8 sysState;
+
+    uint8 icr2[VP890_ICR2_LEN];
+    uint8 icr3[VP890_ICR3_LEN];
+
+    uint8 disnVal[VP890_DISN_LEN];
+    uint8 vpGain[VP890_VP_GAIN_LEN];
+    uint8 loopSup[VP890_LOOP_SUP_LEN];
+
+    bool forceCalDataWrite;
+
+    /* Signal generator calibration temporary backup */
+    uint8 sigGenA[VP890_SIGA_PARAMS_LEN];
+    uint8 calReg[VP890_DC_CAL_REG_LEN];
+    uint8 asscReg;
+
+    /**< Battery Calibration values used to compute final VAS values */
+    uint8 swCal[VP890_BAT_CALIBRATION_LEN];
+
+    uint16 minVas;  /**< Minimum VAS value determined during IMT calibration.
+                     * This is stored in the same format used to compute the VAS
+                     * value rather than the device format. This increases the
+                     * data memory space requirements slightly, but reduces the
+                     * size for code space and simplifies the logic when applied.
+                     */
+    uint16 vasStart;    /**< Used to speedup VAS calibration by providing the
+                         * minimum starting VAS. This value is computed from the
+                         * battery adjustment and minVas (above).
+                         */
+} Vp890CalLineData;
+
+typedef enum Vp890FxoCurrentMonitorStates {
+    VP890_CURRENT_MONITOR_DISABLED,
+    VP890_CURRENT_MONITOR_OFFSET,
+    VP890_CURRENT_MONITOR_BUFFER0,
+    VP890_CURRENT_MONITOR_BUFFER1,
+    VP890_CURRENT_MONITOR_BUFFER2,
+    VP890_CURRENT_MONITOR_BUFFER3,
+    VP890_CURRENT_MONITOR_BUFFER4,
+    VP890_CURRENT_MONITOR_NORMAL
+} Vp890FxoCurrentMonitorStates;
+
+#define VP890_PCM_BUF_SIZE    5
+typedef struct Vp890FxoCurrentMonitorType {
+    Vp890FxoCurrentMonitorStates    stateValue;
+    int16                           currentBuffer[VP890_PCM_BUF_SIZE];
+    int16                           currentOffset;
+
+    uint8                           offsetMeasurements;
+
+    /* This is updated when delta across all data is minimal */
+    int32                           steadyStateAverage;
+
+    /* Set TRUE when last set of data experienced a line transient */
+    bool                            invalidData;
+} Vp890FxoCurrentMonitorType;
+
+typedef struct Vp890FxoLowVoltageMonitorType {
+    bool enabled;
+    uint8 numDisc;
+    uint8 numNotDisc;
+} Vp890FxoLowVoltageMonitorType;
+
+#define VP890_SYS_CAL_POLARITY_LENGTH  2
+#define VP890_SYS_CAL_CHANNEL_LENGTH   1
+
+/* Contains calibration error values -- in +/-10mv LSB */
+typedef struct Vp890SysCalResultsType {
+    int16 abvError[1];
+
+    int16 vocOffset[VP890_SYS_CAL_CHANNEL_LENGTH][VP890_SYS_CAL_POLARITY_LENGTH];
+    int16 vocError[VP890_SYS_CAL_CHANNEL_LENGTH][VP890_SYS_CAL_POLARITY_LENGTH];
+
+    int16 sigGenAError[VP890_SYS_CAL_CHANNEL_LENGTH][VP890_SYS_CAL_POLARITY_LENGTH];
+
+    int16 ila20[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila25[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila32[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila40[VP890_SYS_CAL_CHANNEL_LENGTH];
+
+    int16 ilaOffsetNorm[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 ilgOffsetNorm[VP890_SYS_CAL_CHANNEL_LENGTH];
+
+    uint8 vas[VP890_SYS_CAL_CHANNEL_LENGTH][VP890_SYS_CAL_POLARITY_LENGTH];
+
+    int16 vagOffsetNorm[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 vagOffsetRev[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 vbgOffsetNorm[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 vbgOffsetRev[VP890_SYS_CAL_CHANNEL_LENGTH];
+
+    int16 swyOffset[VP890_SYS_CAL_CHANNEL_LENGTH];     /**< Used to hold SWY Offset */
+
+    /* Used for capacitance line test only */
+    int32 tipCapCal[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int32 ringCapCal[VP890_SYS_CAL_CHANNEL_LENGTH];
+} Vp890SysCalResultsType;
+
+#define VP890_CAL_STRUCT_SIZE   (18*sizeof(int16) + 2*sizeof(uint8) + 2*sizeof(int32))
+
+/* Vp890 specific Device Object */
+typedef struct Vp890DeviceObjectType {
+    VpDeviceIdType                  deviceId;           /* Device Id indication */
+
+    VpDeviceStaticInfoType          staticInfo;         /**< Info that will not change during runtime. */
+    VpDeviceDynamicInfoType         dynamicInfo;        /**< Info that will change during runtime */
+
+    /* state is a bit-mask of VpDeviceStateType values */
+    uint16                          state;
+
+    /* stateInt is a bit-mask of values */
+    uint16                          stateInt;
+
+    VpOptionEventMaskType           deviceEventsMask;
+    VpOptionEventMaskType           deviceEvents;
+    uint16                          eventHandle;        /** Application defined event handle */
+    uint16                          timeStamp;          /**< Used to track event timing. Increment by ticks */
+    int16                           timeRemainder;
+    VpGetResultsOptionsType         getResultsOption;
+    VpOptionCriticalFltType         criticalFault;
+
+    VpRelGainResultsType            relGainResults;
+
+    /* Used only to reduce MPI traffic (avoid read/modify/write */
+#ifdef VP890_FXS_SUPPORT
+    uint8                           swParamsCache[VP890_REGULATOR_PARAM_LEN];
+    uint8                           switchCtrl[VP890_REGULATOR_CTRL_LEN];
+#endif
+
+    uint8                           devMode[VP890_DEV_MODE_LEN];
+
+    uint16                          devTimer[VP_DEV_TIMER_LAST];
+
+    Vp890DeviceProfileType          devProfileData;
+    VpCSLACDeviceProfileTableType   devProfileTable;
+    VpCSLACProfileTableEntryType    profEntry;
+
+#ifdef VP890_INCLUDE_TESTLINE_CODE
+    VpTestResultType                testResults;
+#endif
+
+    uint8                           intReg[VP890_UL_SIGREG_LEN];  /**< Holds signaling data info for the device */
+    uint8                           intReg2[VP890_UL_SIGREG_LEN];
+
+    uint8                           responseData;   /**< Holds data for Response events on the device */
+
+    uint8                           txBufferDataRate;
+
+#if !defined(VP_REDUCED_API_IF) || defined(ZARLINK_CFG_INTERNAL)
+    uint8                           mpiData[VP890_MAX_MPI_DATA];  /**< Buffer for MPI Low level reads to
+                                                                   * hold maximum amount of MPI data that
+                                                                   * is possible
+                                                                   */
+#endif
+
+    uint8                           mpiLen;       /**< Length of data to be copied into mpiData buffer */
+
+#ifdef VP890_FXS_SUPPORT
+    /*  Two sets of dial pulse specifications are provide to support NTT dial
+     * pulse detection windows of 10pps and 20pps while excluding 15pps */
+    VpOptionPulseType pulseSpecs;
+    VpOptionPulseType pulseSpecs2;
+#endif
+
+    uint8 testDataBuffer[VP890_TEST_DATA_LEN];
+
+#if defined (VP890_INCLUDE_TESTLINE_CODE)
+    Vp890CurrentTestType currentTest;
+    Vp890CalOffCoeffs calOffsets[VP890_MAX_NUM_CHANNELS];
+#endif /* VP890_INCLUDE_TESTLINE_CODE */
+
+#if defined (VP_CC_890_SERIES) || defined (VP_CC_KWRAP)
+    Vp890SysCalResultsType vp890SysCalData;
+#endif
+
+#ifdef VP_DEBUG
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+#endif
+
+    /* Used to hold the device level ecVal (to keep track of WB mode). */
+    uint8 ecVal;
+
+    /*
+     * Holds the last channel information changed to/from Wideband mode since
+     * the last tick. If = 0, no change has been made. If = 1, ch0 if = 2, ch1.
+     * This is a handshake with the tick which detects it is not 0, makes the
+     * appropriate change and sets it back to 0.
+     */
+    uint8 lastCodecChange;
+} Vp890DeviceObjectType;
+
+/* 890 specific Line Object */
+typedef struct Vp890LineObjectType {
+    uint8                           channelId;
+    uint8                           ecVal;
+
+    VpTermType                      termType;
+
+    VpLineIdType                    lineId;             /**< Application provided value for mapping
+                                                         * a user defined type to a line context
+                                                         */
+
+    VpApiIntLineStateType           lineState;          /**< Line state info used for state
+                                                         * transition handling and recall */
+    uint16                          status;             /**< Bit-mask of Vp890LineStatusType */
+
+    VpOptionCodecType               codec;
+
+    /**< Used to delay slic write for LPM or Disconnect handling. */
+    uint8                           nextSlicValue;
+
+   /**< Used to reduce MPI reads. */
+    uint8                           slicValueCache;
+    uint8                           opCond[VP890_OP_COND_LEN];
+
+    VpCslacTimerStruct              lineTimers;         /**< Timers for "this" line */
+    VpOptionEventMaskType           lineEvents;
+    VpOptionEventMaskType           lineEventsMask;
+    uint16                          lineEventHandle;    /**< Line specific event handle information */
+    uint16                          signaling1;
+    uint16                          signaling2;
+
+    uint16                          dtmfDigitSense;     /**< Used to hold the DTMF digit reported
+                                                         * with VpDtmfDigitDetected() until the
+                                                         * VP_LINE_EVID_DTMF_DIG is generated. */
+    uint8                           signalingData;      /**< Holds data for Signaling events on this line */
+    uint16                          processData;        /**< Holds data for Process events on this line */
+    uint16                          responseData;       /**< Holds data for Response events on this line */
+
+#ifdef VP890_FXO_SUPPORT
+    uint8                           fxoData;            /**< Holds data for FXO events on this line */
+    uint8                           fxoRingStateFlag;   /**< Indicates a state change request during ringing,
+                                                             to be serviced when ringing is over */
+    VpLineStateType                 fxoRingState;       /**< State to change to when ringing is over */
+
+    VpCslacLineCondType             preDisconnect;      /**< The disconnect state prior to timer start */
+
+    VpDigitGenerationDataType       digitGenStruct;     /**< Used on FXO lines for
+                                                         * generating pulse digits */
+
+    uint8                           ringDetMax;         /**< Stores the user specified maximum
+                                                         * ringing detect period for FXO lines. This
+                                                         * value may be outside the device range, in
+                                                         * which case the SW will implement upper
+                                                         * period detection */
+
+    uint8                           ringDetMin;         /**< Stores the user specified maximum
+                                                         * ringing detect period for FXO lines that
+                                                         * is within the device range. This value is
+                                                         * used as "minimum" that is detected by SW.
+                                                         * Actual minimum period is supported by the
+                                                         * device period detector itself. */
+
+    uint8                           dPoh;               /**< Stores the user specified parallel
+                                                         * offhook integration time for use
+                                                         * in timing for the POH event */
+
+    uint8                           userDtg;             /* User-configured DTG setting */
+    uint8                           cidDtg;              /* DTG register setting for CID
+                                                          * correction */
+    int8                            cidCorrectionSample; /* Last line voltage sample for CID
+                                                          * correction */
+    uint8                           cidCorrectionCtr;    /* Counter for CID correction line
+                                                          * voltage samples */
+    Vp890PllRecoveryStateType       pllRecoveryState;    /* State for the pll issue fix */
+    uint8                           pllRecoverAttempts;    /* Number if pll recovery retries */
+
+    Vp890FxoCurrentMonitorType      currentMonitor;
+    Vp890FxoLowVoltageMonitorType   lowVoltageDetection;
+#endif
+
+#ifdef VP890_FXS_SUPPORT
+    /*
+     * Array to hold ringing parameters used in the Signal Generator.  This is
+     * needed when signal generator A is set to a tone, then set back to ringing
+     * without the user re-specifying the ringing profile
+     */
+    uint8                           ringingParams[VP890_SIGA_PARAMS_LEN];
+
+    VpProfilePtrType                pRingingCadence;    /**< Currently used ringing cadence on
+                                                         * this line */
+
+    VpOptionRingControlType         ringCtrl;
+
+    VpProfilePtrType                pCidProfileType1;   /**< Currently used caller ID profile
+                                                         * on this line for sequenced cid */
+
+    VpDialPulseDetectType           dpStruct;           /**< Used on FXS lines for detecting pulse
+                                                         * digits*/
+
+    VpDialPulseDetectType           dpStruct2;          /**< Used on FXS lines for detecting pulse
+                                                         * digits using 2nd set of dp specs. */
+
+    VpOptionPulseModeType           pulseMode;
+
+    VpRelayControlType              relayState;    /* Used to hold current line
+                                                    * relay state */
+
+    uint8 dcCalValues[VP890_DC_CAL_REG_LEN];
+
+    /* Loop supervision parameters */
+    uint8 hookHysteresis;
+
+    bool internalTestTermApplied;
+#endif
+
+    Vp890CalLineData                calLineData;    /* Data used during VpCalLine() */
+
+    /* Holds user definition for Loop Supervision configuration when
+     * "badLoopSup" is TRUE */
+    uint8                           loopSup[VP890_LOOP_SUP_LEN];
+
+    VpOptionPcmTxRxCntrlType        pcmTxRxCtrl;   /* Defines how the PCM highway is
+                                                    * set for "talk" linestates */
+
+    /*
+     * NOTE: Do not move the location or name of gx/grBase members. These may be
+     * used by applications to determine the gain of the GX/GR blocks in the
+     * AC profile. Using return from VpSetRelGain() is not usefull because that
+     * is the register setting. The customer would have to know how to convert
+     * that to linear values, which is not generally documented.
+     */
+    uint16                          gxBase;       /**< Cached GX register, in 2.14 int format */
+    uint16                          gxCidLevel;   /**< GX Caller ID correction factor (2.14) */
+    uint16                          gxUserLevel;  /**< User specified relative GX level (2.14) */
+    uint16                          grBase;       /**< Cached GR register, in 2.14 int format */
+    uint16                          grUserLevel;  /**< User specified relative GR level (2.14) */
+
+    int16 absGxGain; /**< Cached ABS A-to-D Gain, simplifies code. */
+    int16 absGrGain; /**< Cached ABS D-to-A Gain, simplifies code. */
+
+#ifdef VP_CSLAC_SEQ_EN
+#ifdef VP890_FXS_SUPPORT
+    VpCallerIdType                  callerId; /**< Caller ID related information */
+    VpCidSeqDataType                cidSeq;   /**< CID Sequencer related information */
+
+    bool                            suspendCid;
+    uint8                           tickBeginState[VP890_CID_PARAM_LEN];
+    uint8                           cidBytesRemain;
+    bool                            delayConsumed; /**< Set to TRUE when Polling Mode CID uses the
+                                                    * loop read/delay method and has started it.
+                                                    */
+#endif
+
+    VpSeqDataType                   cadence;  /**< Sequencer related information */
+
+    /**< Array to control internally run sequences */
+    VpProfileDataType               intSequence[VP890_INT_SEQ_LEN];
+#endif
+
+#ifdef VP890_LP_SUPPORT
+    uint8 leakyLineCnt; /*
+                         * Keeps track of # of times off-hook was detected (LP Mode)
+                         * that was not further verified after exiting LP Mode. Reset
+                         * when off-hook is verified.
+                         */
+#endif
+
+#ifdef VP890_FXS_SUPPORT
+    VpHowlerModeCachedValues howlerModeCache;
+
+    uint8 icr2Values[VP890_ICR2_LEN];   /**< Cached to minimize device access */
+    uint8 icr3Values[VP890_ICR3_LEN];   /**< Cached to minimize device access */
+    uint8 icr4Values[VP890_ICR4_LEN];   /**< Cached to minimize device access */
+#endif
+
+    /* Used in FXO PLL Recovery, FXS Line Test,  and FXS Generic and Low Power Mode Control */
+    uint8 icr1Values[VP890_ICR1_LEN];   /**< Cached to minimize device access */
+
+    uint8 sigGenCtrl[VP890_GEN_CTRL_LEN];   /**< Cached to minimize device access */
+
+#ifdef VP_DEBUG
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+#endif
+
+} Vp890LineObjectType;
+
+#endif /* VP890_API_H */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_CSLAC_types.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_CSLAC_types.h
new file mode 100755
index 0000000..23c7247
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_CSLAC_types.h
@@ -0,0 +1,620 @@
+/** \file vp_CSLAC_types.h
+ * vp_CSLAC_types.h
+ *
+ * Header file for internal variables used in CSLAC type API.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9103 $
+ * $LastChangedDate: 2011-11-14 11:15:45 -0600 (Mon, 14 Nov 2011) $
+ */
+
+#ifndef VP_CSLAC_TYPES_H
+#define VP_CSLAC_TYPES_H
+
+#include "vp_api_fxo_params.h"
+#include "vp_api_timer.h"
+
+#define VP_CSLAC_DEV_PROFILE_VERSION_INT_SW_CONFIG_FR   5
+#define VP_CSLAC_DEV_PROFILE_VERSION_INT_SW_CONFIG      4
+#define VP_CSLAC_DEV_PROFILE_VERSION_LINECARD_PARAM     3
+#define VP_CSLAC_DEV_PROFILE_VERSION_VBH_REG            2
+#define VP_CSLAC_DEV_PROFILE_VERSION_SW_CONFIG          1
+
+#define VP_CSLAC_FXO_VERSION_DTMF_LEVEL                 1
+#define VP_CSLAC_FXO_VERSION_POH                        2
+
+#define VP_CSLAC_DC_PROFILE_VERSION_890                 1
+
+#define VP_CSLAC_RING_PROFILE_VERSION_890               1
+
+#define VP_CSLAC_TICKSTEP_0_5MS     (0x80)      /**< CSLAC Tickrate for 0.5mS */
+#define VP_CSLAC_TICKSTEP_1MS       (0x100)     /**< CSLAC Tickrate for 1mS */
+
+#define VP_CID_TIMESCALE    1   /**< Timescale in mS for CID time data */
+
+#define VP_CSLAC_DEV_PROF_TABLE_SIZE            1
+#define VP_CSLAC_AC_PROF_TABLE_SIZE             2
+#define VP_CSLAC_DC_PROF_TABLE_SIZE             2
+#define VP_CSLAC_RINGING_PROF_TABLE_SIZE        2
+#define VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE   11
+#define VP_CSLAC_TONE_PROF_TABLE_SIZE           10
+#define VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE   4
+#define VP_CSLAC_METERING_PROF_TABLE_SIZE       2
+#define VP_CSLAC_CALLERID_PROF_TABLE_SIZE       2
+#define VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE     1
+#define VP_CSLAC_CUSTOM_TERM_PROF_TABLE_SIZE    4
+
+/* Special Howler Bit-Mask 'xxxx 11xx' */
+#define VP_CSLAC_SPECIAL_TONE_MASK  (0x0C)
+#define VP_CSLAC_STD_TONE           (0x00)
+#define VP_CSLAC_HOWLER_TONE        (0x04)  /* UK BTNR 1080 Specification */
+#define VP_CSLAC_AUS_HOWLER_TONE    (0x08)
+#define VP_CSLAC_NTT_HOWLER_TONE    (0x0C)
+
+#define VP_CSLAC_TONE_TYPE         5
+
+#define VP_CSLAC_READ_RESPONSE_MASK (VP_LINE_EVID_LLCMD_RX_CMP \
+                                   | VP_LINE_EVID_RD_OPTION \
+                                   | VP_LINE_EVID_GAIN_CMP)
+
+typedef struct VpCSLACDeviceProfileTableType {
+    VpProfilePtrType pDevProfileTable[VP_CSLAC_DEV_PROF_TABLE_SIZE];
+    VpProfilePtrType pAcProfileTable[VP_CSLAC_AC_PROF_TABLE_SIZE];
+    VpProfilePtrType pDcProfileTable[VP_CSLAC_DC_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingingProfileTable[VP_CSLAC_RINGING_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneCadProfileTable[VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneProfileTable[VP_CSLAC_TONE_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingingCadProfileTable[VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pMeteringProfileTable[VP_CSLAC_METERING_PROF_TABLE_SIZE];
+    VpProfilePtrType pCallerIdProfileTable[VP_CSLAC_CALLERID_PROF_TABLE_SIZE];
+    VpProfilePtrType pFxoConfigProfileTable[VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE];
+    VpProfilePtrType pCustomTermProfileTable[VP_CSLAC_CUSTOM_TERM_PROF_TABLE_SIZE];
+} VpCSLACDeviceProfileTableType;
+
+/**
+ * The following structure is used by the device as a bitmask indicating
+ * whether or not a given profile table entry is valid. In the bit location a
+ * value '1' = profile is current, '0' = profile is not current.
+ */
+typedef struct VpCSLACProfileTableEntryType {
+    uint16 devProfEntry;
+    uint16 acProfEntry;
+    uint16 dcProfEntry;
+    uint16 ringingProfEntry;
+    uint16 toneCadProfEntry;
+    uint16 toneProfEntry;
+    uint16 ringCadProfEntry;
+    uint16 meterProfEntry;
+    uint16 cidCadProfEntry;
+    uint16 fxoConfigProfEntry;
+    uint16 customTermProfEntry;
+} VpCSLACProfileTableEntryType;
+
+#define VP_PROF_ENTRY_INVALID   0
+#define VP_PROF_ENTRY_VALID     1
+
+typedef union VpGetResultsOptionsDataType {
+    VpOptionCriticalFltType criticalFaultOption;
+    VpOptionEventMaskType eventMaskOption;
+    VpOptionPulseModeType pulseModeOption;
+    VpOptionPulseType pulseTypeOption;
+    VpOptionRingControlType ringControlOption;
+    VpOptionZeroCrossType zeroCross;
+    VpOptionTimeslotType timeSlotOption;
+    VpOptionCodecType codecOption;
+    VpOptionPcmHwyType pcmHwyOption;
+    VpOptionLoopbackType loopBackOption;
+    VpOptionLineStateType lineStateOption;
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;
+    VpDeviceIoAccessDataType deviceIoData;
+    VpOptionDeviceIoType deviceIo;
+    VpLoopCondResultsType loopCond;
+    bool autoShutdownEn;
+    VpOptionAbsGainType absGain;
+} VpGetResultsOptionsDataType;
+
+typedef struct VpGetResultsOptionsType {
+    VpGetResultsOptionsDataType optionData;
+    uint8 chanId;
+    VpOptionIdType optionType;
+} VpGetResultsOptionsType;
+
+#define VP_CID_DTMF_ON_TIME    70   /**< Nominal 70mS +/- 5mS */
+#define VP_CID_DTMF_OFF_TIME   70   /**< Minimum 65mS */
+
+typedef enum VpCidGeneratorControlType {
+    VP_CID_GENERATOR_DATA,
+    VP_CID_GENERATOR_KEYED_CHAR,
+    VP_CID_SIGGEN_EOT,
+    VP_CID_NO_CHANGE,           /**< Load tones only, do not change generator
+                                 * state
+                                 */
+    VP_CID_GENERATOR_MARKOUT,
+    VP_CID_CTRL_TYPE_CNT,
+
+    VP_CID_GENC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCidGeneratorControlType;
+
+/* Previously VpCidStatusFlagType values */
+#define VP_CID_RESET_VALUE  (0x0000)
+
+#define VP_CID_IS_DEBOUNCE  (0x0001)    /**< Set when debounce has expired */
+#define VP_CID_CLIAWAITTONE (0x0002)
+#define VP_CID_REPEAT_MSG   (0x0004)
+#define VP_CID_AWAIT_TONE   (0x0008)    /**< Set if waiting for CPE ACK Tone */
+
+#define VP_CID_TERM_FSK     (0x0010)    /**< Set if stopping FSK generator */
+#define VP_CID_END_OF_MSG   (0x0020)    /**< Set if API detects an end of
+                                         * message in the buffered data
+                                         */
+
+#define VP_CID_FSK_GEN_VALID    (0x0040)    /**< Set if FSK Generator is programmed
+                                             * for Caller ID signals.
+                                             */
+
+#define VP_CID_IN_PROGRESS      (0x0080)    /**< Set if Caller ID is in progress */
+#define VP_CID_ACTIVE_RING_SEQ  (0x0100)    /**< Set if active CID Ring sequence */
+
+#define VP_CID_PRIMARY_FULL     (0x0200)    /**< Set when primary buffer contains
+                                             * CID data
+                                             */
+#define VP_CID_SECONDARY_FULL   (0x0400)    /**< Set when secondary buffer contains
+                                             * CID data
+                                             */
+#define VP_CID_PRIMARY_IN_USE   (0x0800)    /**< Set when primary buffer in use */
+#define VP_CID_SECONDARY_IN_USE (0x1000)    /**< Set when secondary buffer in use */
+#define VP_CID_WAIT_ON_ACTIVE   (0x2000)    /**< Set when a "wait on" mode is
+                                             * active. Should only be cleared in
+                                             * the timer function (since currently
+                                             * support only for Wait on CID or time
+                                             */
+#define VP_CID_MID_CHECKSUM     (0x4000)    /**< Set when a checksum value is being
+                                             * sent.
+                                             */
+#define VP_CID_MUTE_ON      (0x8000)    /**< Set when a "Mute On" CID operator
+                                         * is active.
+                                         */
+#define VP_CID_FSK_ACTIVE   (0x10000)   /**< Set while the FSK Generator is needed */
+
+
+typedef enum VpCidDtmfStatusType {
+    VP_CID_DTMF_RESET_VALUE = 0,
+    VP_CID_ACTIVE_ON_TIME = 1,
+    VP_CID_ACTIVE_OFF_TIME = 2
+} VpCidDtmfStatusType;
+
+/** Caller ID variables used by the line */
+typedef struct VpCallerIdType {
+    uint32 status;  /**< 'OR'ed combination of VpCidStatusFlagType */
+
+    VpCidDtmfStatusType dtmfStatus; /**< Used only for DTMF CID Message Data */
+
+    uint16 cliTimer;        /**< Time in increments of device ticks */
+    uint8 currentData;      /**< Data to repeat on the line */
+    uint16 cidCheckSum;     /**< Checksum to append to message data */
+
+    uint8 cliDebounceTime;  /**< Hook debouce specified in device ticks */
+    VpProfilePtrType pCliProfile;   /**< Currently running CID Profile */
+
+    VpDigitType cliDetectTone1;
+    VpDigitType cliDetectTone2;
+
+    uint8 cliMPIndex;       /**< Current Index into primary message buffer */
+    uint8 cliMSIndex;       /**< Current Index into secondary message buffer */
+
+    uint8 cliIndex;         /**< Current Index into profile data */
+
+    uint8 primaryBuffer[VP_SIZEOF_CID_MSG_BUFFER];
+    uint8 secondaryBuffer[VP_SIZEOF_CID_MSG_BUFFER];
+
+    uint8 primaryMsgLen;    /**< Length of data in the primary buffer */
+    uint8 secondaryMsgLen;  /**< Length of data in the secondary buffer */
+    VpDigitType digitDet;   /**< Stores the last DTMF digit detected during
+                             * Caller ID (if enabled via tone detection).
+                             */
+    uint8 messageDataRemain;    /**< Tracks the total number of message bytes remaining */
+
+    /*
+     * At the end of FSK Message Data, some systems require a mark-out time. As
+     * specified in the Profile Wizard, this is defined in # of bytes with each
+     * byte corresponding to 8.33ms (1200 baud with 1 start + 1 stop + 8 data
+     * bits = 10/1200 = 8.33ms).
+     */
+    uint8 markOutByteCount;     /* Retains the value specified in the profile */
+    uint8 markOutByteRemain;    /* Current value remaining. Clean up when = 0 */
+} VpCallerIdType;
+
+typedef enum VpCadenceStatusType {
+    VP_CADENCE_RESET_VALUE = 0x0,
+    VP_CADENCE_STATUS_ACTIVE = 0x1,
+    VP_CADENCE_STATUS_BRANCHING  = 0x2,
+    VP_CADENCE_STATUS_MID_TIMER  = 0x4,
+    VP_CADENCE_STATUS_SENDSIG  = 0x8,
+    VP_CADENCE_STATUS_METERING = 0x10,
+    VP_CADENCE_STATUS_BRANCHING_LVL2  = 0x20,
+    VP_CADENCE_STATUS_IGNORE_POLARITY = 0x40
+} VpCadenceStatusType;
+
+/** Variables to control the cadence on the line using the Sequencer */
+#define VP_CSLAC_MAX_BRANCH_DEPTH   2
+#define VP_CSLAC_BRANCH_LVL_0       0
+#define VP_CSLAC_BRANCH_LVL_1       1
+
+typedef struct VpSeqDataType {
+    VpProfilePtrType pActiveCadence;    /**< Currently Active Cadence */
+    VpProfilePtrType pCurrentPos;       /**< Current position in profile */
+
+    VpCadenceStatusType status;
+
+    uint8 index;        /**< Index in the the cadence table   */
+    uint8 length;       /**< Length of executable cadence instructions */
+
+    /**< Remaining number of repeats to perform for each branch depth */
+    uint8 count[VP_CSLAC_MAX_BRANCH_DEPTH];
+
+    uint16 timeRemain;
+    uint8 branchAt;     /**< Outermost step we're branching */
+    uint16 meteringBurst;   /**< Tracks the number of metering pulses sent */
+    bool meterPendingAbort; /**< Indicates that metering should abort after the
+                             * current pulse ends */
+    VpLineStateType meterAbortLineState; /**< The line state that should be set
+                                          * when metering aborts */
+
+    /* The following variables are for controlling signal generator ramp */
+#define VPCSLAC_MAX_GENERATOR_DATA 11
+    uint8 regData[VPCSLAC_MAX_GENERATOR_DATA];  /**< Scratchpad to reduce MPI
+                                                 * traffic.
+                                                 */
+    /*
+     * These values should correspond to device specific values for the
+     * freqency/level being set -- not a generic value.
+     */
+    uint16 startFreq;
+    bool isFreqIncrease;
+    uint16 stopFreq;
+    uint16 freqStep;
+
+    uint16 startLevel;
+    uint16 stopLevel;
+    uint16 levelStep;
+    uint8  toneType;
+} VpSeqDataType;
+/*
+ * Used to save values of registers that will be modified for Special Howler Tones. These
+ * tones require very high amplitude which can be done on VE880/890 using some back-door
+ * controls. Note that VE880/890 have the same command set in the case of these registers
+ */
+#define VP_CSLAC_ICR1_LEN       (4)
+#define VP_CSLAC_ICR2_LEN       (4)
+#define VP_CSLAC_ICR3_LEN       (4)
+#define VP_CSLAC_ICR4_LEN       (4)
+#define VP_CSLAC_DC_FEED_LEN    (2)
+#define VP_CSLAC_VP_GAIN_LEN    (1)
+#define VP_CSLAC_GR_LEN         (2)
+#define VP_CSLAC_R_LEN          (14)
+#define VP_CSLAC_DISN_LEN       (1)
+#define VP_CSLAC_OP_FUNC_LEN    (1)
+#define VP_CSLAC_SW_REG_LEN     (3)
+
+typedef struct VpHowlerModeCachedValues {
+    bool isInHowlerMode;    /**< Set to TRUE when in Howler Mode and values below are good */
+
+    uint8 icr1Reg[VP_CSLAC_ICR1_LEN];   /**< ICR1 = 0xEC/ED */
+    uint8 icr2Reg[VP_CSLAC_ICR2_LEN];   /**< ICR2 = 0xEE/EF */
+    uint8 icr3Reg[VP_CSLAC_ICR3_LEN];   /**< ICR3 = 0xF2/F3 */
+    uint8 icr4Reg[VP_CSLAC_ICR4_LEN];   /**< ICR4 = 0xEC/ED */
+    uint8 dcFeed[VP_CSLAC_DC_FEED_LEN];
+
+    uint8 digitalRxLoss[VP_CSLAC_VP_GAIN_LEN];  /**< VP Gain Reg - only changing Digital RX Loss */
+    uint8 grValue[VP_CSLAC_GR_LEN];
+    uint8 rValue[VP_CSLAC_R_LEN];
+
+    uint8 disn[VP_CSLAC_DISN_LEN];
+
+    /*
+     * Z and B will be disabled using the Operating Function Register instead of writing
+     * "disable" coefficients. Obviously - less MPI traffic by at least 33 bytes
+     */
+    uint8 opFunc[VP_CSLAC_OP_FUNC_LEN]; /**< Only disabling Z and B Filters */
+
+    uint8 swReg[VP_CSLAC_SW_REG_LEN];   /**< Used to change Tracking floor voltge to -30V */
+} VpHowlerModeCachedValues;
+
+/** Variables to control the CID sequence on the line using the CID Sequencer */
+typedef struct VpCidSeqDataType {
+    VpProfilePtrType pActiveCadence;    /**< Currently Active Cadence */
+    VpProfilePtrType pCurrentPos;       /**< Current position in profile */
+
+    uint8 index;        /**< Index in the the cadence table   */
+    uint16 timeRemain;
+} VpCidSeqDataType;
+
+typedef VpStatusType
+(*VpSeqInstructionFuncPtrType) (
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSequenceData);
+
+#define VP_SEQ_OPERATOR_MASK 0xE0
+#define VP_SEQ_SUBTYPE_MASK  0x1F
+#define VP_SEQUENCER_TICKRATE   0x0500  /* 5mS - Used with MS_TO_TICKRATE */
+
+/**< The super commands are the upper 3 bits of the command byte and therefore should never be
+ * used with types exceeding 8-bit
+ */
+#define VP_SEQ_SPRCMD_COMMAND_INSTRUCTION   (0x00)
+#define VP_SEQ_SPRCMD_TIME_INSTRUCTION      (0x20)
+#define VP_SEQ_SPRCMD_BRANCH_INSTRUCTION    (0x40)
+
+/**< The sub commands are the lower 5 bits of the command byte */
+#define VP_SEQ_SUBCMD_SIGGEN            (0x00)
+#define VP_SEQ_SUBCMD_LINE_STATE        (0x01)
+#define VP_SEQ_SUBCMD_START_CID         (0x02)
+#define VP_SEQ_SUBCMD_WAIT_ON           (0x07)  /**< Wait for CID or time to continue */
+
+#define VP_SEQ_SUBCMD_RAMP_GENERATORS   (0x08)  /**< Forces frequency/amplitude change of the tone
+                                                 * generator. Tone Cadence associated with this
+                                                 * command must be specified as "ramp" type.
+                                                 */
+
+    /**< API Internal Use only operators */
+#define VP_SEQ_SUBCMD_METERING      (0x10)  /**< Cadence Metering */
+
+    /**< Bit-Fields for Tone Generator Control (see Profile Wizard Spec). */
+#define VP_SEQ_SIGGEN_ALL_DISABLED  (0x00)
+#define VP_SEQ_SIGGEN_A_EN          (0x01)
+#define VP_SEQ_SIGGEN_B_EN          (0x02)
+#define VP_SEQ_SIGGEN_C_EN          (0x04)
+#define VP_SEQ_SIGGEN_D_EN          (0x08)
+
+/**< Definition for the states in the Profile Wizard output. These must always be used/accessed
+ * as uint8 types. Do everything possible to create compiler errors if they're used any differently
+ */
+typedef uint8 VpProfileCadencerStateTypes;
+#define VP_PROFILE_CADENCE_STATE_STANDBY            ((VpProfileCadencerStateTypes)0)
+#define VP_PROFILE_CADENCE_STATE_TIP_OPEN           ((VpProfileCadencerStateTypes)1)
+#define VP_PROFILE_CADENCE_STATE_TALK               ((VpProfileCadencerStateTypes)2)
+#define VP_PROFILE_CADENCE_STATE_ACTIVE             ((VpProfileCadencerStateTypes)3)
+#define VP_PROFILE_CADENCE_STATE_RSVD               ((VpProfileCadencerStateTypes)4)
+#define VP_PROFILE_CADENCE_STATE_OHT                ((VpProfileCadencerStateTypes)5)
+#define VP_PROFILE_CADENCE_STATE_DISCONNECT         ((VpProfileCadencerStateTypes)6)
+#define VP_PROFILE_CADENCE_STATE_RINGING            ((VpProfileCadencerStateTypes)7)
+#define VP_PROFILE_CADENCE_STATE_POLREV_STANDBY     ((VpProfileCadencerStateTypes)8)
+#define VP_PROFILE_CADENCE_STATE_POLREV_TIP_OPEN    ((VpProfileCadencerStateTypes)9)
+#define VP_PROFILE_CADENCE_STATE_POLREV_TALK        ((VpProfileCadencerStateTypes)10)
+#define VP_PROFILE_CADENCE_STATE_POLREV_ACTIVE      ((VpProfileCadencerStateTypes)11)
+#define VP_PROFILE_CADENCE_STATE_POLREV_RSVD        ((VpProfileCadencerStateTypes)12)
+#define VP_PROFILE_CADENCE_STATE_POLREV_OHT         ((VpProfileCadencerStateTypes)13)
+#define VP_PROFILE_CADENCE_STATE_POLREV_DISCONNECT  ((VpProfileCadencerStateTypes)14)
+#define VP_PROFILE_CADENCE_STATE_POLREV_RINGING     ((VpProfileCadencerStateTypes)15)
+#define VP_PROFILE_CADENCE_STATE_FXO_OHT            ((VpProfileCadencerStateTypes)16)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_OPEN      ((VpProfileCadencerStateTypes)17)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_CLOSE     ((VpProfileCadencerStateTypes)18)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_TALK      ((VpProfileCadencerStateTypes)19)
+#define VP_PROFILE_CADENCE_STATE_MSG_WAIT_NORM      ((VpProfileCadencerStateTypes)20)
+#define VP_PROFILE_CADENCE_STATE_MSG_WAIT_POLREV    ((VpProfileCadencerStateTypes)21)
+#define VP_PROFILE_CADENCE_STATE_UNKNOWN            ((VpProfileCadencerStateTypes)255)
+
+/* struct VpDialPulseDetectType is for FXS lines when detecting digits */
+typedef enum VpDialPulseDetectStatesType {
+    VP_DP_DETECT_STATE_LOOP_OPEN = 0,
+    VP_DP_DETECT_STATE_LOOP_CLOSE = 1,
+    VP_DP_DETECT_STATE_IDLE = 2
+} VpDialPulseDetectStatesType;
+
+typedef struct VpDialPulseDetectType {
+    int digits;
+    uint16 lo_time;
+    uint16 lc_time;
+    VpDialPulseDetectStatesType state;   /**< Dial Pulse State Machine state */
+    bool hookSt;
+    uint8 signalingData;
+} VpDialPulseDetectType;
+
+/* struct VpDigitGenerationDataType is for FXO lines when generating digits */
+typedef struct VpDigitGenerationDataType {
+    uint16 dtmfOnTime;
+    uint16 dtmfOffTime;
+    uint8 breakTime;
+    uint8 makeTime;
+    uint16 flashTime;
+    uint16 dpInterDigitTime;
+    uint8 dtmfHighFreqLevel[2];
+    uint8 dtmfLowFreqLevel[2];
+} VpDigitGenerationDataType;
+
+/** Virtual Device Registers - Used to reduce MPI accesses to the Device */
+typedef struct VpVirtualDeviceReg {
+    uint8 sigRegMSB;    /**< Signaling Register's Most Significant byte */
+    uint8 sigRegLSB;    /**< Signaling Register's Least Significant byte */
+    uint8 iMaskMSB;     /**< Interrupt mask for the current line */
+    uint8 iMaskLSB;     /**< Interrupt mask for the current line */
+    uint8 iMaskMSBSP;   /**< Interrupt mask for the current line */
+    uint8 iMaskLSBSP;   /**< Interrupt mask for the current line */
+    uint8 ccR1SP;
+    uint8 ccR5SP;       /**< Scratchpad for CCR5 used during metering */
+    uint8 ccR8SP;       /**< Scratchpad for CCR8 used during calibration */
+    uint8 ioReg;        /**< IO Register for QSLAC SLIC states */
+} VpVirtualDeviceReg;
+
+/**<
+ * IMPORTANT: Make sure to update the type used for "state" member inside
+ * objects, structs, and passed to functions where the comment states the value
+ * is a bit-mask of "VpDeviceStateType". Seach by "VpDeviceStateType".
+ * There are no instance of this type itself.
+ */
+typedef enum VpDeviceStateType {
+    /**< Indicates if function is running from InitDevice. Not the same as in
+     * the middle of an initialization process (including calibration). Used to
+     * allow InitDevice function calling other functions to be enabled. Otherwise,
+     * some functions will return "Device Not Initialized" error.
+     */
+    VP_DEV_INIT_IN_PROGRESS = 0x0001,
+
+    VP_DEV_INIT_CMP = 0x0002,    /**< Set if device has been initialized */
+    VP_DEV_IN_CAL = 0x0004,      /**< Set if device is busy calibrating */
+    VP_DEV_PENDING_INT = 0x0008, /**< Set if there is a pending interrupt */
+
+    VP_DEV_ABS_BAT_CAL = 0x0010, /**< Set when running ABS (batt switch) Cal */
+    VP_DEV_ABV_CAL = 0x0020,     /**< Set when running ABV Calibration on Tracker */
+    VP_DEV_ABV_CAL_ABS = 0x0040, /**< Set when running ABV Calibration on ABS */
+    VP_DEV_DISC_PENDING = 0x0080, /**< Set when a Disconnect Timer was suspsended */
+
+    VP_DEV_TEST_BUFFER_READ = 0x0100, /**< Set if test buffer was read this tick */
+
+     /**< Set if device in process of warm reboot. Note that warm reboot
+      * detection alone only helps skipping of VpCalCodec() because it is run
+      * with VpInitDevice(). But it does not ensure that VpCalLine() was
+      * previously run.
+      */
+    VP_DEV_WARM_REBOOT = 0x0200
+
+} VpDeviceStateType;
+
+typedef struct VpCSLACDeviceStatusType {
+    uint16 state;           /**< This is a bit-mask of VpDeviceStateType values */
+    uint8 globStatReg;      /**< Holds state of the device stat reg */
+    uint8 calibrating;      /**< Calibration timer */
+    uint8 numIntServiced;   /**< Max interrupts to be serviced during tick */
+} VpCSLACDeviceStatusType;
+
+#define VP_CSLAC_MAX_RCN_PCN_SIZE   2
+typedef struct VpDeviceStaticInfoType {
+    uint8 rcnPcn[VP_CSLAC_MAX_RCN_PCN_SIZE];    /**< Revision Code Number and
+                                                 * Product Code Number as
+                                                 * applicable
+                                                 */
+    uint8 maxChannels;  /**< How many lines supported by this device */
+} VpDeviceStaticInfoType;
+
+typedef struct VpDeviceDynamicInfoType {
+    uint8 lastChan;     /**< The last line checked */
+    bool clkFault;      /** TRUE if a clock fault is active */
+    bool bat1Fault;     /** TRUE if a bat1 fault is active and device level */
+    bool bat2Fault;     /** TRUE if a bat2 fault is active and device level */
+    bool bat3Fault;     /** TRUE if a bat3 fault is active and device level */
+} VpDeviceDynamicInfoType;
+
+/** Line state variables used by the line (api internal) */
+#ifdef STRICT_SIGNED_ENUM_VALUES
+typedef uint16 VpCslacLineCondType;
+
+#define VP_CSLAC_STATUS_INVALID     (0x0000)
+
+/* FXS Type Status */
+#define VP_CSLAC_HOOK   (0x0001)
+#define VP_CSLAC_GKEY   (0x0002)
+
+/* FXO Type Status */
+#define VP_CSLAC_RAW_DISC   (0x0001)
+#define VP_CSLAC_RINGING    (0x0004)
+#define VP_CSLAC_DISC       (0x0008)
+
+#define VP_CSLAC_AC_FLT     (0x0010)
+#define VP_CSLAC_DC_FLT     (0x0020)
+#define VP_CSLAC_THERM_FLT  (0x0040)
+#define VP_CSLAC_CAL_ENABLE (0x0080)
+
+#define VP_CSLAC_CAL_FAIL           (0x0100)
+#define VP_CSLAC_POLREV             (0x0200)
+#define VP_CSLAC_POLREV_REPORTED    (0x0400)
+#define VP_CSLAC_LIU                (0x0800)
+
+#define VP_CSLAC_LINE_LEAK_TEST (0x1000)
+#define VP_CSLAC_RING_AMP_DET   (0x2000)
+#define VP_CSLAC_RINGING_EXIT   (0x4000)
+#define VP_CSLAC_STATUS_VALID   (0x8000)
+#else
+typedef enum VpCslacLineCondType {
+    VP_CSLAC_STATUS_INVALID = 0x0000,
+
+    /* FXS Type Status */
+    VP_CSLAC_HOOK = 0x0001,
+    VP_CSLAC_GKEY = 0x0002,
+
+    /* FXO Type Status */
+    VP_CSLAC_RAW_DISC = 0x0001,     /*
+                                     * Set on 890 when device level disconnect
+                                     * status is set. Cleared otherwise.
+                                     */
+
+    VP_CSLAC_RINGING = 0x0004,      /**< Set when Ringing detected on Line */
+    VP_CSLAC_DISC = 0x0008,         /**< Set when Disconnect detected on Line */
+
+    VP_CSLAC_AC_FLT = 0x0010,
+    VP_CSLAC_DC_FLT = 0x0020,
+    VP_CSLAC_THERM_FLT = 0x0040,
+    VP_CSLAC_CAL_ENABLE = 0x0080,   /**< Set when the line is in a state that
+                                     * will allow device calibration
+                                     */
+
+    VP_CSLAC_CAL_FAIL = 0x0100,
+    VP_CSLAC_POLREV = 0x0200,
+    VP_CSLAC_POLREV_REPORTED = 0x0400,
+    VP_CSLAC_LIU = 0x0800,
+
+    VP_CSLAC_LINE_LEAK_TEST = 0x1000,   /**< Set when line is being tested for
+                                         * resistive leak. Clear when test is
+                                         * complete.
+                                         */
+    VP_CSLAC_RING_AMP_DET = 0x2000,
+    VP_CSLAC_RINGING_EXIT = 0x4000,     /**< Set when FXS line is exiting Ringing */
+    VP_CSLAC_STATUS_VALID = 0x8000
+} VpCslacLineCondType;
+#endif
+
+typedef enum VpCslacCalType {
+    VP_CSLAC_CAL_NONE = 0x0,
+    VP_CSLAC_CAL_VOC,
+    VP_CSLAC_CAL_ABV
+} VpCslacCalType;
+
+typedef struct VpApiIntLineStateType {
+    VpLineStateType currentState;   /**< Current state of the line */
+    VpLineStateType previous;       /**< Previous sate of the line */
+    VpLineStateType usrCurrent;     /**< Current user set state of the line */
+
+    /**< Differences between the usrCurrent state and currentState occur during most API internal
+     * line state control operations. E.g., Ringing Cadence and Calibration. When performing line
+     * state control functions on behalf of the Application (e.g., VpSendSignal()), these should
+     * be the same. For ex: if running a Forrward Disconnect Send Signal operation, for the duration
+     * the line is in VP_LINE_DISCONNECT the reported state using VpGetLineState() should be
+     * VP_LINE_DISCONNECT - not the state the line was in prior to performing VpSendSignal().
+     */
+
+    uint16 condition;   /**< 'OR' Combination of VpCslacLineCondType */
+    VpCslacCalType calType;
+} VpApiIntLineStateType;
+
+    /**< Indexes into the Custome Term Profile Type. #define instead of enums becuase the values
+     * must never be negative (many compilers treat enum = int type) and types larger than 8-bit is
+     * a waste.
+     */
+#define VP_CUSTOM_TERM_SLIC_TYPE    (6)
+#define VP_CUSTOM_TERM_NUM_STATES   (7)
+
+    /**< Indexes into the FXO/Dialing Profile Type. #define instead of enums becuase the values
+     * must never be negative (many compilers treat enum = int type) and types larger than 8-bit is
+     * a waste.
+     */
+#define VP_FXO_DIAL_PRFL_DTMF_ON_MSB    (6)
+#define VP_FXO_DIAL_PRFL_DTMF_ON_LSB    (7)
+#define VP_FXO_DIAL_PRFL_DTMF_OFF_MSB   (8)
+#define VP_FXO_DIAL_PRFL_DTMF_OFF_LSB   (9)
+#define VP_FXO_DIAL_PRFL_FLASH_HOOK_MSB (10)
+#define VP_FXO_DIAL_PRFL_FLASH_HOOK_LSB (11)
+#define VP_FXO_DIAL_PRFL_PULSE_BREAK    (12)
+#define VP_FXO_DIAL_PRFL_PULSE_MAKE     (13)
+#define VP_FXO_DIAL_PRFL_INTERDIG_MSB   (14)
+#define VP_FXO_DIAL_PRFL_INTERDIG_LSB   (15)
+#define VP_FXO_DIAL_PRFL_RING_PRD_MAX   (16)
+#define VP_FXO_DIAL_PRFL_RING_PRD_MIN   (17)
+#define VP_FXO_DIAL_PRFL_RING_VOLT_MIN  (18)
+#define VP_FXO_DIAL_PRFL_DISC_VOLT_MIN  (19)
+#define VP_FXO_DIAL_PRFL_LIU_THRESH_MIN (20)
+#define VP_FXO_DIAL_PRFL_RSVD           (21)
+#endif
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api.h
new file mode 100755
index 0000000..8b6a185
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api.h
@@ -0,0 +1,147 @@
+/** \file vp_api.h
+ * vp_api.h
+ *
+ * Header file for the API-II c files.
+ *
+ * This file contains the all of the VoicePath API-II function prototypes. This
+ * file should be used to bring in the VP-API-II library modules that are
+ * necessary for a given application.
+ *
+ *****************************************************************************
+ * NOTE: Inclusion of only this file is sufficient to bring in the all the   *
+ * necessary aspects of VP_API.                                              *
+ *****************************************************************************
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+
+#ifndef VP_API_H
+#define VP_API_H
+
+/******************************************************************************
+ * VP-API Version                                                             *
+ *****************************************************************************/
+/*
+ * The following version number tag is updated at every release of the VP-API.
+ * Since the VP-API is a common interface that supports more than one device,
+ * version number change might occur when any aspect of the VP-API gets
+ * released.
+ */
+#define VP_API_VERSION_TAG (0x021300)
+
+#define VP_API_VERSION_MAJOR_NUM ((VP_API_VERSION_TAG) >> 16)
+#define VP_API_VERSION_MINOR_NUM (((VP_API_VERSION_TAG) & 0x00FF00) >> 8)
+#define VP_API_VERSION_MINI_NUM (((VP_API_VERSION_TAG) & 0x0FF))
+
+/* First include various basic data types used in the API */
+#include "vp_api_types.h"
+
+/******************************************************************************
+ * Defines the configuration of VP-API library that needs to be built.        *
+ * Please modify the following include file as per your VP-API library        *
+ * requirement(s).                                                            *
+ ******************************************************************************/
+#include "vp_api_cfg.h"
+
+/******************************************************************************
+ *                  PLEASE DO NOT MODIFY BELOW THIS LINE                      *
+ ******************************************************************************/
+/* Include the main VP-API-Common file */
+#include "vp_api_common.h"
+
+/* Include the VP-API-Header file required for the CSLAC sequencer */
+#if defined (VP_CSLAC_SEQ_EN)
+#include "vp_api_cslac_seq.h"
+#endif
+
+/* Include the necessary files depending on the requirement of the project */
+#if defined (VP_CC_790_SERIES)
+#include "vp790_api.h"    /* Vp790 device specific API functions and typedefs */
+#endif
+
+/* Include the necessary files depending on the requirement of the project */
+#if defined (VP_CC_792_SERIES)
+#include "vp792_api.h"    /* Vp790 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_880_SERIES)
+#include "vp880_api.h"    /* Vp880 device specific API functions and typedefs */
+
+/*
+ * For 0823 LM, the FXO CID line is controlled by I/O3. For 0803 LM, it's
+ * controlled by I/O2. Control with I/O3 is better since I/O2 has more features
+ *
+ *  #define VP880_FXO_CID_LINE      VP880_IODATA_IO2    Use with 0803 ref
+ *  #define VP880_FXO_CID_LINE      VP880_IODATA_IO3    Use with 0823 ref
+ */
+#define VP880_FXO_CID_LINE      VP880_IODATA_IO3
+#endif
+
+#if defined (VP_CC_890_SERIES)
+#include "vp890_api.h"    /* Vp890 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_580_SERIES)
+#include "vp580_api.h"    /* Vp580 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_VCP_SERIES)
+#include "dvp_api.h"     /* VCP device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_VCP2_SERIES)
+#include "vcp2_api.h"     /* VCP2 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_MELT_SERIES)
+#include "melt_api.h"     /* VCP2 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_KWRAP)
+#include "vp_kernel.h"    /* KWRAP device specific API functions and typedefs */
+#endif
+
+/* Macros for calling a device-specific API function using the pointer in the
+   Device Context: */
+typedef void (*VpTempFuncPtrType) (void);
+
+#define VP_CALL_DEV_FUNC(func, args) \
+    (((pDevCtx->funPtrsToApiFuncs.func) == VP_NULL) ? VP_STATUS_FUNC_NOT_SUPPORTED : (pDevCtx->funPtrsToApiFuncs.func) args )
+
+/*
+ * Based on the existing structure of the include files the following def
+ * have been moved here.
+ */
+
+#if defined(VP_CC_880_SERIES) || defined(VP_CC_790_SERIES) || defined(VP_CC_890_SERIES)
+
+typedef union VpTestHeapType {
+      uint8 dummy; /* preventing an empty union */
+  #if defined(VP_CC_880_SERIES) && defined(VP880_INCLUDE_TESTLINE_CODE)
+    Vp880TestHeapType vpTestHeap880;
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+
+  #if defined(VP_CC_890_SERIES) && defined(VP890_INCLUDE_TESTLINE_CODE)
+    Vp890TestHeapType vpTestHeap890;
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+
+  #if defined(VP_CC_790_SERIES) && defined(VP790_INCLUDE_TESTLINE_CODE)
+    /* Vp790TestHeapType vpTestHeap790; */
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+} VpTestHeapType;
+#else
+typedef char VpTestHeapType;
+#endif
+
+#endif /* VP_API_H */
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cfg.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cfg.h
new file mode 100755
index 0000000..ebe1109
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cfg.h
@@ -0,0 +1,451 @@
+/** \file vp_api_cfg.h
+ * vp_api_cfg.h
+ *
+ * This file contains the configuration and compile time settings for
+ * building appropriate VP-API library modules needed for any application.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9058 $
+ * $LastChangedDate: 2011-11-07 14:21:29 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_CFG_H
+#define VP_API_CFG_H
+
+#ifdef MV_KERNEL_SLIC_SUPPORT
+#include "mvOs.h"
+#include "mvSysTdmConfig.h"
+#endif
+
+#include "vp_debug_masks.h"
+
+/**< NOTE Regarding compile-time settings to reduce code size. The values
+ * provided in these comments is for approximation and comparison purposes
+ * only. Specific savings will vary depending on the compiler and target
+ * processor.
+ */
+
+/**< VP_REDUCED_API_IF
+ * Define this to remove the I/F for unsupported functions. This reduces
+ * code size with the only limitation that the application cannot call
+ * functions that would return "Unsupported" for all devices used in the
+ * application. The specific functions removed will depend on the device and
+ * test packages compiled in.
+ */
+#define VP_REDUCED_API_IF
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: API DEBUG OUTPUT SELECTIONS                         *
+ *****************************************************************************/
+
+/**< VP_DEBUG
+ * If VP_DEBUG is undefined, then ALL debug messages will be compiled out. In
+ * this case, the code size will be smaller, but debug output CANNOT be enabled
+ * at runtime.
+ */
+#undef  VP_DEBUG
+
+/**< VP_CC_DEBUG_SELECT
+ * Choose which types of debug messages to be compiled in.  Only these message
+ * types can be enabled at runtime. See vp_debug_masks.h for a list of debug
+ * message types.
+ */
+#define VP_CC_DEBUG_SELECT (VP_DBG_ALL)
+
+/**< VP_OPTION_DEFAULT_DEBUG_SELECT
+ * The VP_OPTION_ID_DEBUG_SELECT option enables/disables debug output at
+ * runtime.  Define the default value of this option here.  The option will be
+ * automatically set to the default value at device initialization.  See
+ * vp_debug_masks.h for a list of debug message types.
+ *
+ * Note: The VP_OPTION_ID_DEBUG_SELECT option can be changed with VpSetOption()
+ *       only AFTER device initialization (VpInitDevice()).  If you wish to
+ *       see debug output messages during device initialization, you must set
+ *       the default VP_OPTION_ID_DEBUG_SELECT value accordingly.
+ */
+#define VP_OPTION_DEFAULT_DEBUG_SELECT  0
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: Conditionally-Compiled API Libraries                *
+ *****************************************************************************/
+
+/*
+ * Define (or undefine) the appropriate compile time switches based on your
+ * application needs.
+ *
+ * NOTE: Such library selection compile time option(s) MUST be defined before
+ * including any other file from VoicePath library.
+ *
+ * NOTE: More than one Library modules can be built simultaneosuly (if needed).
+ */
+#ifndef ZARLINK_CFG_INTERNAL
+
+  /*
+   * Define the API libraries that will be included in this build
+   * only if the kernel wrapper library is not supported.
+   */
+
+  #undef  VP_CC_790_SERIES   /**< define to build 790 specific API library;
+                              *   undef to exclude this library. */
+
+#if defined(ZARLINK_SLIC_VE792)
+  #define  VP_CC_792_SERIES    /**< define to build 792 specific API library;
+                             *   undef to exclude this library. */
+#endif
+
+#if defined(ZARLINK_SLIC_VE880)
+  #define  VP_CC_880_SERIES   /**< define to build 880 specific API library;
+                             *   undef to exclude this library. */
+#endif
+
+#if defined(ZARLINK_SLIC_VE890)
+  #define  VP_CC_890_SERIES   /**< define to build 890 specific API library;
+                              *   undef to exclude this library. */
+#endif
+
+  #undef  VP_CC_580_SERIES   /**< define to build 580 specific API library;
+                              *   undef to exclude this library. */
+
+  /* VCP (VCP) library */
+  #undef  VP_CC_VCP_SERIES   /**< define to build VCP specific API library;
+                              *   undef to exclude this library. */
+  /* VCP2 library */
+  #undef  VP_CC_VCP2_SERIES  /**< define to build VCP2 specific API library;
+                              *   undef to exclude this library. */
+
+  #undef  VP_CC_MELT_SERIES  /**< define to build Melt specific API library;
+                              *   undef to exclude this library. */
+
+  #undef VP_CC_KWRAP
+
+  #if defined(VP_CC_KWRAP) && defined(__KWRAP__)
+    #error "VP_CC_KWWAP is only applicable to user space builds"
+  #endif
+
+#endif
+
+/******************************************************************************
+ * Include Files for the API                                                  *
+ *****************************************************************************/
+/* Include the API types for this architecture */
+#include "vp_api_types.h"
+
+/*
+ * Undef the following to remove the code necessary to run the API-II sequencer
+ * for CSLAC devices and to enable compile of API-II Lite. This is useful to
+ * reduce code space if the host is not using API-II "advanced" features.
+ */
+#if defined(VP_CC_790_SERIES) || defined(VP_CC_880_SERIES) || \
+    defined(VP_CC_890_SERIES) || defined(VP_CC_580_SERIES)
+    /**< VP_CSLAC_SEQ_EN
+     * This is used to support all cadencing type operations on both FXO and
+     * FXS line types. This includes Ringing and Tone Cadencing, Metering
+     * Pulse, and VpSendSignal(). When set to #undef the VE890 code reduces by
+     * ~17K, the VE880 code reduces by ~20K.
+     */
+#define VP_CSLAC_SEQ_EN
+#endif
+
+#if defined(VP_CC_880_SERIES) || defined(VP_CC_890_SERIES)
+    /**< VP_CSLAC_RUNTIME_CAL_ENABLED
+     * This is used to support run-time calibration via VpInitDevice() and
+     * VpCalLine(). With this #undef, System Coefficients can still be applied
+     * using VpCal(). Set to #undef saves VE880 code size by ~19K bytes (if
+     * both Tracker and ABS are supported) and VE890 by ~10K bytes.
+     */
+    #define VP_CSLAC_RUNTIME_CAL_ENABLED
+
+    /**< VP_HIGH_GAIN_MODE_SUPPORTED
+     * This is used to support High Gain States VP_LINE_HOWLER and
+     * VP_LINE_HOWLER_POLREV. Set to #undef saves code size for both VE880 and
+     * VE890 by ~2K bytes.
+     */
+    #define VP_HIGH_GAIN_MODE_SUPPORTED
+
+    /**< UK Howler Tone Specifications
+     * VE880 and VE890 Applications only. The values below affect how UK Howler
+     * Tone will be provided on the line. To send UK Howler Tone the
+     * application must do the following:
+     *
+     *      - Have the full version of VP_API-II (i.e., Le71SK0002)
+     *      - Set VP_CLSAC_SEQ_EN to #define. Note: if setting VP_CLSAC_SEQ_EN
+     *        to #define causes compiler errors, the Make process may either
+     *        not be including the required *.c and *.h files or may be using
+     *        the "Lite" version of the API (i.e., Le71SDKAPIL).
+     *      - Create a Tone Cadence Profile with UK Howler Tone.
+     *      - Provide this tone cadence to VpSetLineTone()
+     *
+     * There are two types of UK Howler Tones supported in the API:
+     *
+     *      - VP_UK_HOWLER_BTNR_VER15
+     *          The BTNR Version 15 Howler Tone will perform a frequency sweep
+     *          between [800Hz to 3200Hz] at a 500ms period. Total sweep from
+     *          [800-3200-800] will be nominal 1 second +/-166ms. At each 1
+     *          second interval over a total duration of 12 seconds the tone
+     *          level will increase by 3dB for total level increase of 36dB.
+     *          The final level will be a nominal +14.5dBm @ 600ohm on T/R
+     *          when also used with VP_LINE_HOWLER or VP_LINE_HOWLER_POLREV
+     *          line states (see VpSetLineState() in API Reference Guide).
+     *
+     *      - VP_UK_HOWLER_BTNR_DRAFT_G
+     *          Draft 960-G Howler Tone is very similar to Version 15 with
+     *          only a few differences. The frequency sweep is between [800Hz
+     *          to 2500Hz] and the level varies by 3dB during the sweep
+     *          interval such that the level at 2500Hz is ~3dB higher than the
+     *          level at 800Hz. The total sweep time of 12 seconds is the same
+     *          as well as the final output level of +14.5dBm @ 600ohm on T/R
+     *          when also used with VP_LINE_HOWLER or VP_LINE_HOWLER_POLREV
+     *          line states (see VpSetLineState() in API Reference Guide).
+     *
+     * The Application may choose which BTNR Specification to use when
+     * generating the UK Howler Tone by setting VP_UK_HOWLER_IN_USE value as
+     * follows:
+     *
+     *      To use BTNR Version 15:
+     *          #define VP_UK_HOWLER_IN_USE VP_UK_HOWLER_BTNR_VER15
+     *
+     *      To use BTNR Draft-960 G:
+     *          #define VP_UK_HOWLER_IN_USE VP_UK_HOWLER_BTNR_DRAFT_G
+     *
+     *      Previous releases (P2.18.0 and earlier) provided UK Howler Tone
+     *      per VP_UK_HOWLER_BTNR_VER15.
+     */
+    #define VP_UK_HOWLER_BTNR_VER15     0
+    #define VP_UK_HOWLER_BTNR_DRAFT_G   1
+    #define VP_UK_HOWLER_IN_USE         VP_UK_HOWLER_BTNR_VER15
+
+#endif  /* defined(VP_CC_880_SERIES) || defined(VP_CC_890_SERIES) */
+
+/**< EXTENDED_FLASH_HOOK
+ * Define the following to include the onHookMin member in the
+ * VpOptionPulseType struct.
+ */
+#undef  EXTENDED_FLASH_HOOK
+
+/******************************************************************************
+ * Library Specific COMPILE-TIME OPTIONS and defines                          *
+ *****************************************************************************/
+#ifdef VP_CC_790_SERIES
+/* VE790 library can be configured to handle the interrupt in four different
+ * configurations. Choose (only) one of the mechanisms by defining one of the
+ * following. */
+#define VP790_SIMPLE_POLLED_MODE        /* Define to use simple polled interrupt
+                                         * handling mode */
+#undef VP790_EFFICIENT_POLLED_MODE      /* Define to use efficient polled
+                                         * interrupt handling mode */
+#undef VP790_INTERRUPT_LEVTRIG_MODE     /* Define to use level triggered
+                                         * interrupt handling mode */
+#undef VP790_INTERRUPT_EDGETRIG_MODE    /* Define to use edge triggered
+                                         * interrupt handling mode */
+#endif /* VP_CC_790_SERIES */
+
+#ifdef VP_CC_880_SERIES
+
+/*******************************************************************************
+ * Applications can reduce VP-API-II driver size by changing the following for
+ * only the required silicon and termination types needed
+ *
+ * See VP-API-II User's Guide for Details.
+ ******************************************************************************/
+/**< Device Type Support.
+ * One of these MUST be defined if FXS Support is enabled. If you're not sure
+ * whether the silicon used in your application is ABS or Tracker, contact
+ * Microsemi customer support.
+ *
+ * Note that disabling either ABS or Tracker removes the associated calibration
+ * and line specific support (e.g., if disabling Tracker, then LPM also must be
+ * disabled).
+ */
+#define VP880_ABS_SUPPORT   /**< VP880_ABS_SUPPORT
+                             *  #define this to support VE880 ABS type silicon.
+                             * This includes but not limited to Le88266/86 and
+                             * Le8822x/24x. When set to #undef reduces code
+                             * size by ~9K bytes.
+                             */
+
+#define VP880_TRACKER_SUPPORT   /**< VP880_TRACKER_SUPPORT
+                                 * #define this to support VE880 Tracker type
+                                 * silicon. This includes but not limited to
+                                 * VE8820 Chipset and Le88276.
+                                 */
+
+/**< VE880 Termination Type Support.
+ *
+ * Note: Both ABS and Tracker can be #undef while FXO defined. This results in
+ * support for FXO only silicon, and FXO/FXS silicon support for the FXO
+ * termination type only. FXS support requires either ABS or Tracker support.
+ */
+#define VP880_FXO_SUPPORT
+#define VP880_FXS_SUPPORT
+
+/**< VP880_LP_SUPPORT
+ * When set to #undef, all of the code in the VE880 API that supports
+ * termination types VP_TERM_FXS_LOW_PWR, VP_TERM_FXS_SPLITTER_LP, and
+ * VP_TERM_FXS_ISOLATE_LP will be removed. When disabled, the VE880 code
+ * size is reduced by ~7K bytes.
+ */
+#define VP880_LP_SUPPORT
+
+/**< Specific FXO Algorithm support.
+ *
+ * The VP880_CLARE Ringing Detect algorithm uses features of the Clare and VE880
+ * silicon to provide maximum performance of signal detection on FXO lines.
+ * Alternative methods (with VP880_CLARE_RINGING_DETECT set to #undef) do not
+ * require connection of I/O4 to Clare device, but have the following drawbacks:
+ *
+ *    1. Ringing Signals MUST contain polarity reversal to be detected AND
+ *       must exceed ~70V peak.
+ *    2. Line-In-Use is disabled.
+ *    3. Frequency Discriminaation is poor (limited to tickrate).
+ *
+ * It is recommended that all designs connect the CLARE Ringing output to IO4
+ * of the silicon. In that case, this value should be #define.
+ *
+ * Note: If FXO Support is disabled, this setting has no affect.
+ */
+#define VP880_CLARE_RINGING_DETECT
+
+/**< VP880_FXO_FULL_WAVE_RINGING
+ * Selects whether the Ringing input is 1/2-wave of full-wave. This must be
+ * set to #undef when using CPC5621 since this device provides only 1/2-wave
+ * ringing. For all other Clare devices, set to #define.
+ */
+#define VP880_FXO_FULL_WAVE_RINGING
+
+/**< VP880_ALWAYS_USE_INTERNAL_TEST_TERMINATION
+ * Define this option to always use the internal test termination for relay
+ * state VP_RELAY_BRIDGED_TEST, even for devices that have the test load
+ * switch. This is Microsemi's recommendation since the Internal Test
+ * Termination provides better isolation from the customer load and loop
+ * conditions when compared to the external test load.
+ */
+#undef  VP880_ALWAYS_USE_INTERNAL_TEST_TERMINATION
+
+/* VE880 library can be configured to handle the interrupt in four different
+ * configurations. Choose (only) one of the mechanisms by defining one of the
+ * following. */
+#define VP880_SIMPLE_POLLED_MODE        /* Define to use simple polled interrupt
+                                         * handling mode */
+#undef  VP880_EFFICIENT_POLLED_MODE     /* Define to use efficient polled
+                                         * interrupt handling mode */
+#undef  VP880_INTERRUPT_LEVTRIG_MODE    /* Define to use level triggered
+                                         * interrupt handling mode */
+#undef  VP880_INTERRUPT_EDGETRIG_MODE   /* Define to use edge triggered
+                                         * interrupt handling mode */
+#undef  VP880_INCLUDE_TESTLINE_CODE     /* Defines whether or not to enable
+                                         * 880 line test capabilities */
+
+/**< VE880 Line Test Package Defines
+ * Defines all possible VE880 test line packages. There should be no reason to
+ * change these values. But if they are changed, they must be different from
+ * each other.
+ */
+#define VP880_LINE_TEST_AUDITOR 1
+#define VP880_LINE_TEST_PROFESSIONAL 2
+
+#ifdef VP880_INCLUDE_TESTLINE_CODE
+
+/**< VP880_INCLUDE_LINE_TEST_PACKAGE
+ * Selects the VE880 Line Test Package to include. Note that both Auditor and
+ * Professional cannot be included in the same build.
+ */
+#define VP880_INCLUDE_LINE_TEST_PACKAGE VP880_LINE_TEST_PROFESSIONAL
+
+/**< VP880_EZ_MPI_PCM_COLLECT
+ * #define this to have the api collect PCM samples via the MPI bus.
+ * If #undef, the Line Test code will expect the PCM samples from an
+ * external process (DSP or uProcessor) connected to the PCM BUS
+ */
+#define  VP880_EZ_MPI_PCM_COLLECT
+
+/**< VP880_PCM_CALCULATION_TIME
+ * Define the maximum expected computation time to arrive at results for
+ * VpTestLineCallback() after having collected the necessary PCM samples.
+ */
+#define VP880_PCM_CALCULATION_TIME 1000     /* time is in ms */
+
+#endif /* VP880_INCLUDE_TESTLINE_CODE */
+
+#endif /* VP_CC_880_SERIES */
+
+#ifdef VP_CC_580_SERIES
+/* VE580 library can be configured to handle the interrupt in four different
+ * configurations. Choose (only) one of the mechanisms by defining one of the
+ * following. */
+#define VP580_SIMPLE_POLLED_MODE        /* Define to use simple polled interrupt
+                                         * handling mode */
+#undef VP580_EFFICIENT_POLLED_MODE      /* Define to use efficient polled
+                                         * interrupt handling mode */
+#undef VP580_INTERRUPT_LEVTRIG_MODE     /* Define to use level triggered
+                                         * interrupt handling mode */
+#undef VP580_INTERRUPT_EDGETRIG_MODE    /* Define to use edge triggered
+                                         * interrupt handling mode */
+#endif
+
+#ifdef VP_CC_890_SERIES
+
+/**< VE890 Generic Termination Type Support */
+#define VP890_FXO_SUPPORT
+#define VP890_FXS_SUPPORT
+
+/**< VP890_LP_SUPPORT
+ * When set to #undef, all of the code in the VE890 API that supports
+ * termination types VP_TERM_FXS_LOW_PWR, VP_TERM_FXS_SPLITTER_LP, and
+ * VP_TERM_FXS_ISOLATE_LP will be removed. When disabled, the VE890 code
+ * size is reduced by ~5K bytes.
+ */
+#define VP890_LP_SUPPORT
+
+#undef  VP890_INCLUDE_TESTLINE_CODE     /* Defines whether or not to enable
+                                         * 890 line test capabilities */
+#ifdef VP890_INCLUDE_TESTLINE_CODE
+
+/**< VE890 Line Test Package Defines
+ * Defines all possible VE890 test line packages. There should be no reason to
+ * change these values. But if they are changed, they must be different from
+ * each other.
+ */
+#define VP890_LINE_TEST_AUDITOR 1
+#define VP890_LINE_TEST_PROFESSIONAL 2
+
+/**< VP890_INCLUDE_LINE_TEST_PACKAGE
+ * Selects the VE890 Line Test Package to include. Note that both Auditor and
+ * Professional cannot be included in the same build.
+ */
+#define VP890_INCLUDE_LINE_TEST_PACKAGE VP890_LINE_TEST_PROFESSIONAL
+
+/**< VP890_EZ_MPI_PCM_COLLECT
+ * #define this to have the api collect PCM samples via the MPI bus.
+ * If #undef, the Line Test code will expect the PCM samples from an
+ * external process (DSP or uProcessor) connected to the PCM BUS
+ */
+#define VP890_EZ_MPI_PCM_COLLECT
+
+/**< VP890_PCM_CALCULATION_TIME
+ * Define the maximum expected computation time to arrive at results for
+ * Vp890TestLineCallback() after having collected the necessary PCM samples.
+ */
+#define VP890_PCM_CALCULATION_TIME 1000     /* time is in ms */
+
+#endif /* VP890_INCLUDE_TESTLINE_CODE */
+
+/* VE890 library can be configured to handle the interrupt in four different
+ * configurations. Choose (only) one of the mechanisms by defining one of the
+ * following. */
+#define VP890_SIMPLE_POLLED_MODE        /* Define to use simple polled interrupt
+                                         * handling mode */
+#undef  VP890_EFFICIENT_POLLED_MODE     /* Define to use efficient polled
+                                         * interrupt handling mode */
+#undef  VP890_INTERRUPT_LEVTRIG_MODE    /* Define to use Level Triggered
+                                         * interrupt handling mode */
+#undef  VP890_INTERRUPT_EDGETRIG_MODE   /* Define to use edge triggered
+                                         * interrupt handling mode */
+#endif /* VP_CC_890_SERIES*/
+
+typedef uint8 VpScratchMemType;
+
+/* Include internal options required to build the VP-API-II library */
+#include "vp_api_cfg_int.h"
+
+#endif /* VP_API_CFG_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cfg_int.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cfg_int.h
new file mode 100755
index 0000000..a8ce23c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cfg_int.h
@@ -0,0 +1,400 @@
+/** \file vp_api_cfg_int.h
+ * vp_api_cfg_int.h
+ *
+ * This file contains internal configuration and compile time settings for
+ * building appropriate VP-API library modules needed for any application.
+
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 6419 $
+ * $LastChangedDate: 2010-02-12 16:40:10 -0600 (Fri, 12 Feb 2010) $
+ */
+
+#ifndef VP_API_CFG_INT_H
+#define VP_API_CFG_INT_H
+
+/**< STRICT_SIGNED_ENUM_VALUES
+ * Define this to avoid using enumerations with negative values (e.g., 0x8000). It should not be
+ * needed in compilers compliant with ANSII C89 or later. Setting it to #define also removes strict
+ * type checking in the API which is generally not preferred.
+ */
+#undef STRICT_SIGNED_ENUM_VALUES
+
+/******************************************************************************
+ * Device Context Size                                                        *
+ *****************************************************************************/
+/*
+ * Define the maximum number of lines per device in your system. Note that a
+ * system (i.e., all devices controlled by one instance of VP-API) could have
+ * more than one type of device, each of those devices may support different
+ * number of lines. For example in a system, device A might support 2 lines
+ * and device B might support 4 lines, in such a scenario, the following macro
+ * should be defined as 4. */
+#if defined(VP_CC_790_SERIES) || defined(VP_CC_580_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (4)
+#else /* VP_CC_880_SERIES + VP_CC_890_SERIES */
+    /*
+     * Note that for VE890 this value must be >=2 even when using the single
+     * FXO device. That's because the line context pointer in the device
+     * context is assigned to the "channelId" element of the line context
+     * pointer array. The FXO channelId = 1 so the array must be size >= 2.
+     */
+    #define VP_MAX_LINES_PER_DEVICE     (2)
+#endif
+
+/**< Special Case for Kernel Wrapper: DO NOT TOUCH THESE VALUES */
+#if defined(VP_CC_KWRAP)
+  #undef VP_MAX_LINES_PER_DEVICE
+  #define VP_MAX_LINES_PER_DEVICE (128)
+#endif
+
+/**< CSLAC_GAIN_RELATIVE
+ * VE880 and VE890 applications only. This value affects whether or not the VE880/VE890 API will
+ * support VpSetRelGain() function. Setting to #undef reduces the API library size for each device
+ * by ~1K. Applications may choose to compile out VpSetRelGain() functionality and instead use
+ * the VP_OPTION_ID_ABS_GAIN feature (see CSLAC_GAIN_ABS).
+ *
+ * NOTE: The API has not been tested with this string set to #undef.
+ */
+#define CSLAC_GAIN_RELATIVE
+
+/**< CSLAC_GAIN_ABS
+ * VE880 and VE890 applications only. This value affects whether or not the VE880/VE890 API will
+ * support the VP_OPTION_ID_ABS_GAIN feature of the API. Setting to #undef reduces the API library
+ * size by ~1K independent of whether compiling only for VE880 or VE890, or compiling for both. The
+ * majority of the code used to support VP_OPTION_ID_ABS_GAIN is common for these devices.
+ * Applications are not likely to use both VP_OPTION_ID_ABS_GAIN and VpSetRelGain() features of the
+ * API (see CSLAC_GAIN_RELATIVE for VpSetRelGain() compile option).
+ *
+ * NOTE: The API has not been tested with this string set to #undef.
+ */
+#define CSLAC_GAIN_ABS
+
+/**< VP_ENABLE_PROD_TEST
+ * This value exists for test purposes only. DO NOT change to #define in production code.
+ * Unexpected or damaging behavior may occur.
+ */
+#undef  VP_ENABLE_PROD_TEST
+
+/**< VP_CID_POLLING_ENABLED
+ * This value should only be defined for applications with <= 4 lines on the same MPI BUS and
+ * with 8.33ms tickrate. With VP_CID_POLLING_ENABLED set to #define, the API will consume an
+ * additional >= 500us per line for each tick (additional 1ms per tick for a 2-FXS device).
+ *
+ * For systems with tickrates = 8.33ms and using FSK CID with standard baud rate = 1200, for a
+ * per-byte line update rate of 8.33ms (same as the tickrate) it is possible on the VE880 and
+ * VE890 silicon that without this set to #define the CID message data on the line may
+ * corrupt. The error occurs when the API writes to the silicon at "exactly" the same time as
+ * the CID message on the line is changing from one byte to the next ("exact" in this context
+ * specifically refers to a window of 80ns). Repeated bulk call testing of 100,000 calls
+ * indicates that this error can occur in the range of [< 0.001% (>99.999% success) to 4%
+ * (96% success)]. Note however these numbers are application and system specific. The problem
+ * will occur 100% of the time IF the API write occurs within the 80ns window where the
+ * device/line CID message data byte is being updated, and will occur 0% of the time IF this
+ * precise timing is avoided.
+ *
+ * When this is set to #define the exact tick consumption to avoid this error is defined by
+ * VP_CID_NORMAL_MPI_CNT described below.
+ */
+#undef  VP_CID_POLLING_ENABLED
+
+/**< VP_CID_NORMAL_INIT_CNT
+ * This count value is used at the start of sending FSK data in a CID sequence.
+ *
+ * The VE880 and VE890 silicon CID message buffer is 2+ bytes deep. That means the API can at a
+ * given time provide a little less than 3 bytes to the silicon. When CID FSK Data is initialized,
+ * the API writes one byte to the silicon. It takes the silicon 18us to update it's CID buffer
+ * management such that it will then accept another 2 bytes before indicating "Full". When "Full"
+ * the silicon will tolerate the maximum amount of VpApiTick() jitter without underrun of the CID
+ * message buffer.
+ *
+ * The exact value of VP_CID_NORMAL_INIT_CNT depends on the DCLK rate and CS-Off time assumed to be
+ * 8.192MHz and 2.5us respectively. The delay is implemented in the API by reading the CID State
+ * machine buffer where each call to VpMpiCmd() requires 4 bytes of MPI traffic. Therefore, one
+ * read will take a minimum of (4 * (2.5us + 8/8.192MHz)) = 13.90625us. In order to meet the minimum
+ * time of 18us then requires at least 2 reads. In systems with much longer CS Off times or slower
+ * DCLK rates, this count value could be reduced.
+ *
+ * NOTE: This value is used by the API independant of VP_CID_POLLING_ENABLED setting.
+ */
+#define VP_CID_NORMAL_INIT_CNT  (2)
+
+/** VP_CID_NORMAL_MPI_CNT
+ * This count value is used by the API during normal CID FSK Data transmission (all FSK conditions
+ * except for the very first 3 bytes of initialization controlled by VP_CID_NORMAL_INIT_CNT). This
+ * value is set to provide a minimum 500us window where the API will monitor the silicon for a
+ * Caller ID Buffer update.
+ *
+ * When running a 8.33ms tickrate and 1200baud FSK, the silicon buffer should update very nearly
+ * when VpApiTick() is called. As mentioned above, if the API updates the silicon at almost exactly
+ * the same time as the silicon buffer update occurs, Caller ID on the line will be corrupted. The
+ * API avoids this by checking for the silicon buffer update before writing to the silicon. With
+ * a tickrate of 8.33ms + jitter, the siliocn update should occur either just before VpApiTick() is
+ * called or very nearly when VpApiTick() starts.
+ *
+ * The precise value (36) assumes DCLK = 8.192MHz and CS Off-Time of 2.5us. Each read of the CID
+ * state machine requires 4 bytes for total duration of (4 * (2.5us + 8/8.192MHz)) = 13.90625us.
+ * To meet the 500us minimum time requires (500 / 13.90625) ~ 36 reads. In systems with much longer
+ * CS Off times or slower DCLK rates, this count value could be reduced.
+ *
+ * NOTE: This value is used by the API ONLY if VP_CID_POLLING_ENABLED is set to #define.
+ */
+#define VP_CID_NORMAL_MPI_CNT   (36)
+
+/**< VE8XX_LPM_LEAKY_LINE_CNT
+ * This count is for the numner of times during a Low Power Mode leaky line test the VP-API-II
+ * will retry using LPM state before "giving up".
+ */
+#define VE8XX_LPM_LEAKY_LINE_CNT    (3)
+
+#ifdef VP_CC_880_SERIES
+
+/*
+ * Modifications to previous settings to correct for potential inconsistencies.
+ * DO NOT CHANGE anything below this line. All corrections should be made above
+ */
+#if !defined (VP880_TRACKER_SUPPORT) && defined (VP880_LP_SUPPORT)
+    #error "Invalid 880 Compiler Combination: Low Power Mode Requires Tracker defined"
+#endif
+
+#if defined (VP880_FXS_SUPPORT) && (!defined (VP880_ABS_SUPPORT) && !defined (VP880_TRACKER_SUPPORT))
+    #error "Invalid 880 Compiler Combination: FXS requires either ABS or Tracker defined"
+#endif
+
+#ifndef VP880_FXS_SUPPORT
+    #undef VP880_ABS_SUPPORT
+    #undef VP880_INCLUDE_TESTLINE_CODE
+    #undef VP880_LP_SUPPORT
+#endif
+
+#if !defined (VP880_FXS_SUPPORT) && !defined (VP880_FXO_SUPPORT)
+    #error "Invalid 880 Compiler Combination: Either FXS or FXO must be defined if using VE880 device"
+#endif
+
+/*
+ * Current Limiting option in the VP880 library limits the peak switcher current
+ * such that a 3REN load can be supported at 90V peak. Disable this option if
+ * 5REN is required.
+ */
+#undef  VP880_CURRENT_LIMIT
+
+#endif /* VP_CC_880_SERIES */
+
+#if (defined (VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) || defined(VP_CC_KWRAP)
+    /*
+     * #defines used in unit conversion function
+     * All units are based on the following calculations
+     *      Internal voltage unit   = 480.0  / 2^31 Volts
+     *      Internal current unit   = 240e-3 / 2^31 Amps
+     *      Internal freq uint      = 12e3   / 2^31 Hz
+     */
+    #define VP880_UNIT_MV                          4474L    /* mV unit */
+    #define VP880_UNIT_MVRMS                       6327L    /* mVrms unit */
+    #define VP880_UNIT_ADC_VAB                     -32768L  /* vab step from ADC */
+    #define VP880_UNIT_ADC_VAB_RMS                 46341L   /* vab step from ADC rms*/
+    #define VP880_UNIT_ADC_AC_VAB_RMS                664L   /* vab step from ADC Metallic Vrms*/
+    #define VP880_UNIT_DAC_RING                    21076L   /* step due to DAC in ringing*/
+    #define VP880_UNIT_TRACK_SWZ                23091612L   /* step used for tracking switching regulator Z */
+    #define VP880_UNIT_UA                          8948L    /* uA unit */
+    #define VP880_UNIT_ADC_IMET_NOR                16384L   /* met I from ADC in normal VC */
+    #define VP880_UNIT_ADC_IMET_NOR_JA             15756L   /* met I from ADC in normal JA*/
+    #define VP880_UNIT_ADC_IMET_RING               32768L   /* met I from ADC in ringing*/
+    #define VP880_UNIT_ADC_ILG                     11469L   /* long current from ADC*/
+    #define VP880_UNIT_DECHZ                       17896L   /* Deci Hz*/
+    #define VP880_UNIT_MHZ                         179L     /* mHz */
+    #define VP880_UNIT_FREQ                        65536L   /* siggen freq step */
+    #define VP880_UNIT_RAMP_TIME                   1365L    /* Ramp time (-1/3) in ms*/
+
+    #define VP880_UNIT_CONVERT(DATA, I_UNIT, O_UNIT)    (int32)(((int32)DATA * I_UNIT) / O_UNIT)
+
+    /* converts requested slope into SigGen Freq */
+    #define VP880_SLOPE_TO_FREQ(AMP,SLOPE)  (int16)(((int32)SLOPE * (int32)VP880_UNIT_RAMP_TIME) / (int32)AMP)
+
+    #define VP880_AC_RLOOP_MAX_BAT_LVL              75000L /* mV */
+    #define VP880_AC_RLOOP_MAX_TEST_LVL         ((VP880_AC_RLOOP_MAX_BAT_LVL - 5000) / 2)
+
+#endif /*VP880_INCLUDE_TESTLINE_CODE*/
+
+#ifdef VP_CC_890_SERIES
+
+#define VP890_REL_GAIN_GX_LOW_LIMIT     (0x500)
+#define VP890_REL_GAIN_GR_LOW_LIMIT     (0x1000)
+
+#ifndef VP890_FXS_SUPPORT
+    /*
+     * Tests (using testline) is supported only for FXS termination types. If
+     * line tests are required, make sure FXS support is enabled.
+     */
+    #undef VP890_INCLUDE_TESTLINE_CODE
+
+    /* LPM is an FXS termination type. FXS must be supported to support LPM. */
+    #undef  VP890_LP_SUPPORT
+#endif
+
+/* Define this to attempt to reduce the level of the noise signal generated for
+ * adaptive balance B-Filter calibration.  Reducing the level will increase the
+ * negative effect of outside noise on the line and can reduce performance */
+#undef VP890_REDUCE_BFILTER_CAL_SIGNAL_LEVEL
+
+#endif /* VP_CC_890_SERIES*/
+
+#if (defined (VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE)) || defined(VP_CC_KWRAP)
+    /*
+     * #defines used in unit conversion function
+     * All units are based on the following calculations
+     *      Internal voltage unit   = 480.0  / 2^31 Volts
+     *      Internal current unit   = 240e-3 / 2^31 Amps
+     *      Internal freq uint      = 12e3   / 2^31 Hz
+     */
+    #define VP890_UNIT_MV                          4474L    /* mV unit */
+    #define VP890_UNIT_MVRMS                       6327L    /* mVrms unit */
+    #define VP890_UNIT_ADC_VAB                     -32768L  /* vab step from ADC */
+    #define VP890_UNIT_ADC_VAB_RMS                 46341L   /* vab step from ADC rms*/
+    #define VP890_UNIT_ADC_AC_VAB_RMS              664L     /* vab step from ADC Metallic Vrms*/
+    #define VP890_UNIT_DAC_RING                    21076L   /* step due to DAC in ringing*/
+    #define VP890_UNIT_TRACK_SWZ                23091612L   /* step used for tracking switching regulator Z */
+    #define VP890_UNIT_UA                          8948L    /* uA unit */
+    #define VP890_UNIT_ADC_IMET_NOR                15756L   /* met I from ADC in normal*/
+    #define VP890_UNIT_ADC_IMET_RING               32768L   /* met I from ADC in ringing*/
+    #define VP890_UNIT_ADC_ILG                     11469L   /* long current from ADC*/
+    #define VP890_UNIT_DECHZ                       17896L   /* Deci Hz*/
+    #define VP890_UNIT_MHZ                         179L     /* mHz */
+    #define VP890_UNIT_FREQ                        65536L   /* siggen freq step */
+    #define VP890_UNIT_RAMP_TIME                   1365L    /* Ramp time (-1/3) in ms*/
+
+    #define VP890_UNIT_CONVERT(DATA, I_UNIT, O_UNIT) (int32)( ((int32)DATA * I_UNIT) / O_UNIT)
+
+    /* converts requested slope into SigGen Freq */
+    #define VP890_SLOPE_TO_FREQ(AMP,SLOPE) (int16) ( ((int32)SLOPE * (int32)VP890_UNIT_RAMP_TIME) / (int32)AMP)
+
+    #define VP890_AC_RLOOP_MAX_BAT_LVL              75000L /* mV */
+    #define VP890_AC_RLOOP_MAX_TEST_LVL             ((VP890_AC_RLOOP_MAX_BAT_LVL - 5000) / 2)
+
+#endif /* VP890_INCLUDE_TESTLINE_CODE */
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: Top level VP-API Default Device and Line Options    *
+ *****************************************************************************/
+/*
+ *  The following defines specify the default settings of the device and line
+ * options used in the API. The VP-API-II should generally take on the default
+ * settings set here at VpInitDevice()/VpInitLine() but is not guaranteed (i.e.,
+ * the combinations are not tested - VpInitDevice()/InitLine() could fail as a
+ * result of setting to unexpected values).
+ *
+ * Please consult Field or Applications support before changing any of
+ * these settings.
+ */
+#include "vp_api_option.h"
+#include "vp_api_event.h"
+
+/* Default Dial Pulse Options specified in units of 125micro sec  */
+#define VP_OPTION_DEFAULT_DP_BREAK_MIN          (33 * 8)    /* == 33 ms */
+#define VP_OPTION_DEFAULT_DP_BREAK_MAX          (100 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MIN           (17 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MAX           (75 * 8)
+#define VP_OPTION_DEFAULT_DP_INTER_DIG_MIN      (250 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MIN          (250 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MAX          (1300 * 8)
+#define VP_OPTION_DEFAULT_DP_ON_HOOK_MIN        VP_OPTION_DEFAULT_DP_FLASH_MAX
+#define VP_OPTION_DEFAULT_DP_OFF_HOOK_MIN       0
+
+/*
+ * Specification 2 is usefull if you need to detect between two non-overlapping
+ * dial pulse specifications.
+ */
+#define VP_OPTION_DEFAULT_DP_BREAK_MIN2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_BREAK_MAX2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MIN2          (0 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MAX2          (0 * 8)
+#define VP_OPTION_DEFAULT_DP_INTER_DIG_MIN2     (0 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MIN2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MAX2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_ON_HOOK_MIN2       (0 * 8)
+
+/* Default setting for Critical fault option */
+#define VP_OPTION_DEFAULT_CF_AC_DIS_EN          TRUE
+#define VP_OPTION_DEFAULT_CF_DC_DIS_EN          TRUE
+#define VP_OPTION_DEFAULT_CF_THERMAL_DIS_EN     TRUE
+/* CSLAC-880 and VCP-880 do not support the detection of AC, DC critical faults.
+ * So, The VP-API uses the following default values for those devices.
+ * Note that changing the following values will result in VpInitDevice()
+ * failure. */
+#define VP_OPTION_DEFAULT_CF_AC_DIS_EN_880      FALSE
+#define VP_OPTION_DEFAULT_CF_DC_DIS_EN_880      FALSE
+
+/* Default setting for Zero cross option */
+#define VP_OPTION_DEFAULT_ZERO_CROSS            VP_OPTION_ZC_M4B
+
+/* Default setting for Ramp to standby option */
+#define VP_OPTION_DEFAULT_RAMP2STBY             0
+
+/* Default setting for Pulse mode option */
+#define VP_OPTION_DEFAULT_PULSE_MODE            VP_OPTION_PULSE_DECODE_OFF
+
+/* Default CODEC Mode */
+#define VP_OPTION_DEFAULT_CODEC_MODE            VP_OPTION_ALAW
+
+/* Default setting for PCM Highway option */
+#define VP_OPTION_DEFAULT_PCM_HWY               VP_OPTION_HWY_A
+
+/* Default setting for Loop back option */
+#define VP_OPTION_DEFAULT_LOOP_BACK             VP_OPTION_LB_OFF
+
+/* Default setting for Line state option */
+#define VP_OPTION_DEFAULT_LS_BAT_REV            FALSE
+#define VP_OPTION_DEFAULT_LS_BAT                VP_OPTION_BAT_AUTO
+
+/*
+ * Default Event Masks (VP_OPTION_ID_EVENT_MASK)
+ * The user can arbitrarily set the mask bits here as needed.  A mask bit set to
+ * '0' means the event is not masked.  Some events are non-maskable.
+ */
+#define VP_OPTION_DEFAULT_FAULT_EVENT_MASK      (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_FAULT_EVENTS)
+#define VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK  (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_SIGNALING_EVENTS)
+#define VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK   (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_RESPONSE_EVENTS)
+#define VP_OPTION_DEFAULT_TEST_EVENT_MASK       (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_TEST_EVENTS)
+#define VP_OPTION_DEFAULT_PROCESS_EVENT_MASK    (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_PROCESS_EVENTS)
+#define VP_OPTION_DEFAULT_FXO_EVENT_MASK        (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_FXO_EVENTS)
+#define VP_OPTION_DEFAULT_PACKET_EVENT_MASK     (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_PACKET_EVENTS)
+
+/* Default setting for Ring Control option */
+#define VP_OPTION_DEFAULT_RC_ZERO_CROSS         VP_OPTION_ZC_M4B
+#define VP_OPTION_DEFAULT_RC_RING_EXIT_DBNC_VAL (100 * 8) /* 100ms */
+#define VP_OPTION_DEFAULT_RC_RING_EXIT_STATE    VP_LINE_TALK
+
+/* Default setting for DTMF Mode option */
+#define VP_OPTION_DEFAULT_DM_DTMF_CONTROL_MODE  VP_OPTION_DTMF_DECODE_OFF
+#define VP_OPTION_DEFAULT_DM_DIRECTION          VP_DIRECTION_US
+
+/* Default setting for PCM TX/RX path control */
+#define VP_OPTION_DEFAULT_PCM_TXRX_CNTRL        VP_OPTION_PCM_BOTH
+
+/* Default setting for DTMF Spec option */
+#define VP_OPTION_DEFAULT_DTMF_SPEC             VP_OPTION_DTMF_SPEC_ATT
+
+/* Default setting for Park Mode option */
+#define VP_OPTION_DEFAULT_PARK_MODE_DISC        4   /* 2 seconds */
+#define VP_OPTION_DEFAULT_PARK_MODE_STANDBY     3   /* 300 ms */
+
+/* Default setting for DC Feed Slope option */
+#define VP_OPTION_DEFAULT_DCFEED_SLOPE          109 /* 4 V/ms */
+
+/* Default setting for hook detection mode option */
+#define VP_OPTION_DEFAULT_HOOK_DETECT_MODE      VP_OPTION_HOOKDET_NORMAL
+
+/* Default settings for PCM highway signaling and control */
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_ENABLE    FALSE
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_CTLTS     0
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_SIGTS     0
+
+/* Default setting for PCM highway lien state control mode */
+#define VP_OPTION_DEFAULT_LINESTATE_CTL_MODE    VP_OPTION_LINESTATE_CTL_NORMAL
+
+/* Default settings for Auto Loop Conditions option */
+#define VP_OPTION_DEFAULT_AUTO_LOOP_COND_SELECT 0
+#define VP_OPTION_DEFAULT_AUTO_LOOP_COND_DELAY  0
+
+#define VP_SIZEOF_CID_MSG_BUFFER 16
+
+#endif /* VP_API_CFG_INT_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_common.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_common.h
new file mode 100755
index 0000000..a96a324
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_common.h
@@ -0,0 +1,1884 @@
+/** \file vp_api_common.h
+ * vp_api_common.h
+ *
+ * Header file for the VP-API-II c files.
+ *
+ * This file contains all of the VP-API-II declarations that are Voice
+ * Termination Device (VTD) family independent.
+ *
+ * $Revision: 8867 $
+ * $LastChangedDate: 2011-09-22 14:13:03 -0500 (Thu, 22 Sep 2011) $
+ */
+
+#ifndef VP_API_COMMON_H
+#define VP_API_COMMON_H
+
+#include "vp_api_types.h"
+#include "vp_api_dev_term.h"
+#include "vp_api_event.h"
+#include "vp_api_option.h"
+#include "vp_api_test.h"
+
+
+/******************************************************************************
+ *                                DEFINES                                     *
+ ******************************************************************************/
+
+/*
+ * Profile Table Indexes
+ */
+#define VP_PTABLE_NULL      (VpProfilePtrType)0
+#define VP_PTABLE_INDEX1    (VpProfilePtrType)1
+#define VP_PTABLE_INDEX2    (VpProfilePtrType)2
+#define VP_PTABLE_INDEX3    (VpProfilePtrType)3
+#define VP_PTABLE_INDEX4    (VpProfilePtrType)4
+#define VP_PTABLE_INDEX5    (VpProfilePtrType)5
+#define VP_PTABLE_INDEX6    (VpProfilePtrType)6
+#define VP_PTABLE_INDEX7    (VpProfilePtrType)7
+#define VP_PTABLE_INDEX8    (VpProfilePtrType)8
+#define VP_PTABLE_INDEX9    (VpProfilePtrType)9
+#define VP_PTABLE_INDEX10   (VpProfilePtrType)10
+#define VP_PTABLE_INDEX11   (VpProfilePtrType)11
+#define VP_PTABLE_INDEX12   (VpProfilePtrType)12
+#define VP_PTABLE_INDEX13   (VpProfilePtrType)13
+#define VP_PTABLE_INDEX14   (VpProfilePtrType)14
+#define VP_PTABLE_INDEX15   (VpProfilePtrType)15
+#define VP_PTABLE_NO_INDEX   (VpProfilePtrType)99
+#define VP_PTABLE_MAX_INDEX VP_PTABLE_INDEX15
+#define VP_PTABLE_INDEX(n)  (VpProfilePtrType)(n)
+
+
+/*
+ *Utility macros:
+ */
+#ifndef ABS
+  #define ABS(arg) ((arg) < 0 ? -(arg) : (arg))
+#endif
+
+#ifndef MAX
+  #define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+  #define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX4
+  #define MAX4(a, b, c, d) MAX(MAX(a, b), MAX(c, d))
+#endif
+
+#ifndef MAX12
+  #define MAX12(a, b, c, d, e, f, g, h, i, j, k, l) \
+    MAX(MAX(MAX4(a, b, c, d), MAX4(e, f, g, h)), MAX4(i, j, k, l))
+#endif
+
+
+/******************************************************************************
+ *                    ENUMERATIONS AND NEW DATA TYPES                         *
+ ******************************************************************************/
+/** Standard return value for most API library functions.  See the VP-API-II
+    Reference Guide for descriptions. */
+typedef enum VpStatusType {
+    VP_STATUS_SUCCESS              = 0,
+    VP_STATUS_FAILURE              = 1,
+    VP_STATUS_FUNC_NOT_SUPPORTED   = 2,
+    VP_STATUS_INVALID_ARG          = 3,
+    VP_STATUS_MAILBOX_BUSY         = 4,
+    VP_STATUS_ERR_VTD_CODE         = 5,
+    VP_STATUS_OPTION_NOT_SUPPORTED = 6,
+    VP_STATUS_ERR_VERIFY           = 7,
+    VP_STATUS_DEVICE_BUSY          = 8,
+    VP_STATUS_MAILBOX_EMPTY        = 9,
+    VP_STATUS_ERR_MAILBOX_DATA     = 10,
+    VP_STATUS_ERR_HBI              = 11,
+    VP_STATUS_ERR_IMAGE            = 12,
+    VP_STATUS_IN_CRTCL_SECTN       = 13,
+    VP_STATUS_DEV_NOT_INITIALIZED  = 14,
+    VP_STATUS_ERR_PROFILE          = 15,
+    VP_STATUS_CUSTOM_TERM_NOT_CFG  = 17,
+    VP_STATUS_DEDICATED_PINS       = 18,
+    VP_STATUS_INVALID_LINE         = 19,
+    VP_STATUS_LINE_NOT_CONFIG      = 20,
+    VP_STATUS_INPUT_PARAM_OOR,  /* This enum value does not yet require to be a set value */
+    VP_STATUS_NUM_TYPES,
+    VP_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpStatusType;
+
+/* Enumeration for Boot load Function */
+typedef enum VpBootStateType {
+    VP_BOOT_STATE_FIRST,        /* First block to download */
+    VP_BOOT_STATE_CONTINUE,     /* Additional block to download */
+    VP_BOOT_STATE_LAST,         /* Last block to download */
+    VP_BOOT_STATE_FIRSTLAST,    /* First and only block to download */
+    VP_NUM_BOOT_STATES,
+    VP_BOOT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBootStateType;
+
+/* Enumeration for Boot load Function */
+typedef enum VpBootModeType {
+    VP_BOOT_MODE_NO_VERIFY,     /* No write verification is performed */
+    VP_BOOT_MODE_VERIFY,        /* Verify Load Image Checksum */
+    VP_NUM_BOOT_MODES,
+    VP_BOOT_MODE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBootModeType;
+
+/* Version and checksum information for VCP */
+typedef struct VpVersionInfoType {
+    uint16 vtdRevCode;          /* Silicon Revision for VTD */
+    uint8 swProductId;          /* VTD Firmware ID */
+    uint8 swVerMajor;           /* Major Revision for VTD Firmware */
+    uint8 swVerMinor;           /* Minor Revision for VTD Firmware */
+} VpVersionInfoType;
+
+typedef struct VpChkSumType {
+    uint32 loadChecksum;        /* Calculated Checksum for Code Image */
+    VpVersionInfoType vInfo;    /* Version Information for VTD HW/SW */
+} VpChkSumType;
+
+typedef enum VpProfileType {
+    VP_PROFILE_DEVICE      = 0, /* Device profile */
+    VP_PROFILE_AC          = 1, /* AC profile */
+    VP_PROFILE_DC          = 2, /* DC profile */
+    VP_PROFILE_RING        = 3, /* Ring profile */
+    VP_PROFILE_RINGCAD     = 4, /* Ringing cadence profile */
+    VP_PROFILE_TONE        = 5, /* Tone profile */
+    VP_PROFILE_METER       = 6, /* Metering profile */
+    VP_PROFILE_CID         = 7, /* Caller ID profile */
+    VP_PROFILE_TONECAD     = 8, /* Tone cadence profile */
+    VP_PROFILE_FXO_CONFIG,      /* FXO configuration profile */
+    VP_PROFILE_CUSTOM_TERM,     /* Custom Termination Type profile */
+    VP_PROFILE_CAL,             /* Used for VpCal when passing calibration coefficients */
+    VP_NUM_PROFILE_TYPES,
+    VP_PROFILE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProfileType;
+
+/**< typedef for VpCalCodec() function */
+typedef enum VpDeviceCalType {
+    VP_DEV_CAL_NOW   = 0, /* Calibrate immediately */
+    VP_DEV_CAL_NBUSY = 1, /* Calibrate if all lines are "on-hook" */
+    VP_NUM_DEV_CAL_TYPES,
+    VP_DEV_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceCalType;
+
+/* Valid line states for VpSetLineState() */
+/* Defined else where */
+
+/**< The following types are for VpSetLineTone() function */
+typedef struct VpDtmfToneGenType {
+    VpDigitType toneId;  /* Identifies the DTMF tone to generated */
+    VpDirectionType dir; /* Direction in which DTMF tone needs to be
+                          * generated */
+} VpDtmfToneGenType;
+
+typedef enum VpDigitGenerationType {
+  VP_DIGIT_GENERATION_DTMF,             /* Generate DTMF digit */
+  VP_DIGIT_GENERATION_DIAL_PULSE,       /* Generate pulse digit */
+  VP_DIGIT_GENERATION_DIAL_HOOK_FLASH,   /* Generate hook flash */
+  VP_DIGIT_GEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitGenerationType;
+
+typedef enum VpBFilterModeType {
+  VP_BFILT_DIS = 0,
+  VP_BFILT_EN  = 1,
+  VP_BFILT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBFilterModeType;
+
+typedef enum VpBatteryModeType {
+  VP_BATT_MODE_DIS = 0,
+  VP_BATT_MODE_EN  = 1,
+  VP_BATT_MODE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatteryModeType;
+
+typedef struct VpBatteryValuesType {
+    int16 batt1;
+    int16 batt2;
+    int16 batt3;
+} VpBatteryValuesType;
+
+/**< The following types are for VpSetRelayState() and VpGetRelayState() functions */
+typedef enum VpRelayControlType {
+    VP_RELAY_NORMAL         = 0,  /* No test access, ringing controlled
+                                   * by line state */
+    VP_RELAY_RESET          = 1,  /* LCAS all-off state, test-out released */
+    VP_RELAY_TESTOUT        = 2,  /* LCAS all-off state, test-out active */
+    VP_RELAY_TALK           = 3,  /* LCAS talk state, test-out released */
+    VP_RELAY_RINGING        = 4,  /* LCAS ringing state, test-out released */
+    VP_RELAY_TEST           = 5,  /* LCAS test state, test-out released */
+    VP_RELAY_BRIDGED_TEST   = 6,  /* LCAS test/monitor state,
+                                   * test-out released */
+    VP_RELAY_SPLIT_TEST     = 7,  /* LCAS test/monitor state,
+                                   * test-out active */
+    VP_RELAY_DISCONNECT     = 8,  /* LCAS talk state, test-out active */
+    VP_RELAY_RINGING_NOLOAD = 9,  /* LCAS ringing state, test-out active */
+    VP_RELAY_RINGING_TEST   = 10, /* LCAS test ringing state,
+                                   * test-out active */
+    VP_RELAY_LAMP_ON        = 11, /* VCP2-790 FXS_TL_MW only */
+    VP_RELAY_IDLE           = 12, /* All switches open, test switch off */
+    VP_NUM_RELAY_STATES,
+    VP_RELAY_ENUM_RSVD  = FORCE_SIGNED_ENUM,
+    VP_RELAY_ENUM_SIZE  = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpRelayControlType;
+
+/**< The following types are for VpSetCalRelayState() function */
+typedef enum VpCalRelayControlType {
+    VP_CAL_RELAY_OPEN,                /* Open circuit                      */
+    VP_CAL_RELAY_R_DIFF_LOW_TIP_RING, /* Res Tip-to-Ring: R_DIFF_LOW Ohms  */
+    VP_CAL_RELAY_R_CM_REF_TIP_GND,    /* Res Tip-to-Gnd:  R_CM_REF Ohms    */
+    VP_CAL_RELAY_V_CAL_REF_TIP_GND,   /* Volt Tip:        V_CAL_REF Volts  */
+    VP_CAL_RELAY_SHORT_TIP_RING,      /* Res Tip-to-Ring: short (0 Ohms)   */
+    VP_CAL_RELAY_R_DIFF_HIGH_TIP_RING,/* Res Tip-to-Ring: R_DIFF_HIGH Ohms */
+    VP_CAL_RELAY_R_CM_REF_RING_GND,   /* Res Ring-to-Gnd: R_CM_REF Ohms    */
+    VP_CAL_RELAY_V_CAL_REF_RING_GND,  /* Volt Ring:       V_CAL_REF Volts  */
+    VP_CAL_RELAY_NUM_STATES,
+    VP_CAL_RELAY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCalRelayControlType;
+
+/**< The following types are for VpSetRelGain() function */
+typedef enum VpGainResultType {
+    VP_GAIN_SUCCESS  = 0, /* Gain setting adjusted successfully */
+    VP_GAIN_GR_OOR   = 1, /* GR Gain setting overflowed (reset to default) */
+    VP_GAIN_GX_OOR   = 2, /* GX Gain setting overflowed (reset to default) */
+    VP_GAIN_BOTH_OOR = 3, /* Both GR & GX overflowed (and reset to default) */
+    VP_GAIN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGainResultType;
+
+typedef struct VpRelGainResultsType {
+    VpGainResultType gResult; /* Success / Failure status return */
+    uint16 gxValue;           /* new GX register abs value */
+    uint16 grValue;           /* new GR register abs value */
+} VpRelGainResultsType;
+
+/* The number of 16 bits words used to define whether seal current
+ * should be applied to lines 0-127 */
+#define VP_SEAL_CURRENT_ARRAY_SIZE 8
+
+typedef struct VpSealCurType {
+    uint16 sealApplyTime;
+    uint16 sealCycleTime;
+    uint16 maxCurrent;
+    uint16 minCurrent;
+    uint16 sealMaskArray[VP_SEAL_CURRENT_ARRAY_SIZE];
+} VpSealCurType;
+
+/**< The following types are for the VpQuery() function */
+typedef enum VpQueryIdType {
+    VP_QUERY_ID_TEMPERATURE = 0,
+    VP_QUERY_ID_METER_COUNT = 1,
+    VP_QUERY_ID_LOOP_RES    = 2,
+    VP_QUERY_ID_SEAL_CUR    = 3,
+    VP_NUM_QUERY_IDS,
+    VP_QUERY_ID_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpQueryIdType;
+
+typedef union VpQueryResultsType {
+    int16 temp;
+    uint16 meterCount;
+    uint16 rloop;
+    VpSealCurType sealCur;
+} VpQueryResultsType;
+
+/**< The following types are for VpLineIoAccess() function */
+typedef enum VpIoDirectionType {
+    VP_IO_WRITE = 0,
+    VP_IO_READ  = 1,
+    VP_IO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpIoDirectionType;
+
+typedef struct VpLineIoBitsType {
+    uint8 mask;
+    uint8 data;
+} VpLineIoBitsType;
+
+typedef struct VpLineIoAccessType {
+    VpIoDirectionType direction;
+    VpLineIoBitsType ioBits;
+} VpLineIoAccessType;
+
+/**< The following types are for VpDeviceIoAccess() function */
+typedef enum VpDeviceIoAccessType {
+    VP_DEVICE_IO_WRITE = 0, /* Perform device specific IO write access */
+    VP_DEVICE_IO_READ  = 1, /* Perform device specific IO read access */
+    VP_DEVICE_IO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceIoAccessType;
+
+typedef enum VpDeviceIoAccessMask {
+    VP_DEVICE_IO_IGNORE = 0, /* Ignore I/O access */
+    VP_DEVICE_IO_ACCESS = 1, /* Perform I/O access */
+    VP_DEVUCE_IOA_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceIoAccessMask;
+
+typedef struct VpDeviceIoAccessDataType {
+    VpDeviceIoAccessType accessType;/* Device I/O access type */
+    uint32 accessMask_31_0;         /* I/O access mask (Pins 0 - 31) */
+    uint32 accessMask_63_32;        /* I/O access mask (Pins 32 - 63) */
+    uint32 deviceIOData_31_0;   /* Output pin data (Pins 0 - 31) */
+    uint32 deviceIOData_63_32;  /* Output pin data (Pins 32 - 63) */
+} VpDeviceIoAccessDataType;
+
+/**< The following types are for VpDeviceIoAccessExt() function */
+
+typedef struct VpDeviceIoAccessExtType {
+    VpIoDirectionType direction;
+    VpLineIoBitsType lineIoBits[VP_MAX_LINES_PER_DEVICE];
+} VpDeviceIoAccessExtType;
+
+/**< The following types are for VpGetLineStatus() function */
+typedef enum VpInputType {
+    VP_INPUT_HOOK      = 0, /* Hook Status (ignoring pulse & flash) */
+    VP_INPUT_RAW_HOOK  = 1, /* Hook Status (include pulse & flash) */
+    VP_INPUT_GKEY      = 2, /* Ground-Key/Fault Status */
+    VP_INPUT_THERM_FLT = 3, /* Thermal Fault Status */
+    VP_INPUT_CLK_FLT   = 4, /* Clock Fault Status */
+    VP_INPUT_AC_FLT    = 5, /* AC Fault Status */
+    VP_INPUT_DC_FLT    = 6, /* DC Fault Status */
+    VP_INPUT_BAT1_FLT  = 7, /* Battery 1 Fault Status */
+    VP_INPUT_BAT2_FLT  = 8, /* Battery 2 Fault Status */
+    VP_INPUT_BAT3_FLT  = 9, /* Battery 3 Fault Status */
+
+    VP_INPUT_RINGING,    /* Ringing Status */
+    VP_INPUT_LIU,        /* Line In Use Status */
+    VP_INPUT_FEED_DIS,   /* Feed Disable Status */
+    VP_INPUT_FEED_EN,    /* Feed Enable Status */
+    VP_INPUT_DISCONNECT, /* Feed Disconnect Status */
+    VP_INPUT_CONNECT,    /* Feed Connect Status */
+    VP_INPUT_POLREV,     /* Reverse Polarity if TRUE, Normal if FALSE */
+    VP_INPUT_RES_LEAK,   /* Resistive Leakage on line if TRUE */
+
+    VP_NUM_INPUT_TYPES,
+    VP_INPUT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpInputType;
+
+/**< The following type is for the VpGetDeviceStatusExt() function: */
+typedef struct VpDeviceStatusType {
+    VpInputType input;
+    uint8 status[VP_LINE_FLAG_BYTES];
+} VpDeviceStatusType;
+
+/**< The following types are for VpGetLoopCond() function (return via
+ * VpGetResults())
+ */
+typedef enum VpBatteryType {
+    VP_BATTERY_UNDEFINED = 0, /* Battery being used is not known or feature
+                               * not supported */
+    VP_BATTERY_1         = 1, /* Battery 1 */
+    VP_BATTERY_2         = 2, /* Battery 2 */
+    VP_BATTERY_3         = 3, /* Battery 3 */
+    VP_NUM_BATTERY_TYPES,
+    VP_BATTERY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatteryType;
+
+typedef enum VpDcFeedRegionType {
+    VP_DF_UNDEFINED    = 0, /* DC feed region not known or feature not
+                             * supported */
+    VP_DF_ANTI_SAT_REG = 1, /* DC feed is in anti saturation region */
+    VP_DF_CNST_CUR_REG = 2, /* DC feed is in constant current region */
+    VP_DF_RES_FEED_REG = 3, /* DC feed is in resistive feed region */
+    VP_NUM_DC_FEED_TYPES,
+    VP_DC_FEED_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDcFeedRegionType;
+
+typedef struct VpLoopCondResultsType {
+    int16 rloop;                    /**< The loop resistance */
+    int16 ilg;                      /**< The longitudinal loop current */
+    int16 imt;                      /**< The metallic loop current */
+    int16 vsab;                     /**< The tip/ring voltage */
+    int16 vbat1;                    /**< The Battery 1 voltage */
+    int16 vbat2;                    /**< The Battery 2 voltage */
+    int16 vbat3;                    /**< The Battery 3 voltage */
+    int16 mspl;                     /**< Metering signal peak level */
+    VpBatteryType selectedBat;      /**< Battery that is presently used for
+                                     *   the DC feed */
+    VpDcFeedRegionType dcFeedReg;   /**< DC feed region presently selected */
+} VpLoopCondResultsType;
+
+/**< The following types are used for the function VpSendSignal() */
+typedef enum VpSendSignalType {
+    VP_SENDSIG_MSG_WAIT_PULSE      = 0,
+    VP_SENDSIG_DTMF_DIGIT          = 1,
+    VP_SENDSIG_PULSE_DIGIT         = 2,
+    VP_SENDSIG_HOOK_FLASH          = 3,
+    VP_SENDSIG_FWD_DISCONNECT      = 4,
+    VP_SENDSIG_POLREV_PULSE        = 5,
+    VP_SENDSIG_MOMENTARY_LOOP_OPEN = 6,
+    VP_SENDSIG_TIP_OPEN_PULSE      = 7,
+    VP_SENDSIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSendSignalType;
+
+typedef struct VpSendMsgWaitType {
+    int8 voltage;   /**< Voltage in Volts to apply to the line. A negative
+                     * value means Tip is more Negative than Ring, a positive
+                     * value means Ring is more Negative than Tip.
+                     */
+    uint16 onTime;  /**< Duration of pulse on-time in mS */
+    uint16 offTime; /**< Duration of pulse off-tim in mS. If the off-time is
+                     * set to 0, the voltage is applied to the line continuously
+                     */
+    uint8 cycles;   /**< Number of pulses to send on the line. If set to 0, will
+                     * repeat forever
+                     */
+} VpSendMsgWaitType;
+
+/**< The following type is used for the function VpGenTimerCtrl() */
+typedef enum VpGenTimerCtrlType {
+    VP_GEN_TIMER_START  = 0,
+    VP_GEN_TIMER_CANCEL = 1,
+    VP_GEN_TIMER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGenTimerCtrlType;
+
+/**< The enum is used by the system service layer pcmCollect() function */
+typedef enum VpPcmOperationBitType {
+    VP_PCM_OPERATION_AVERAGE      = 0x0001, /* average PCM samples */
+    VP_PCM_OPERATION_RANGE        = 0x0002, /* find pk to pk pcm sample data. */
+    VP_PCM_OPERATION_RMS          = 0x0004, /* find rms value of pcm samples */
+    VP_PCM_OPERATION_MIN          = 0x0008, /* find min pcm value of pcm samples */
+    VP_PCM_OPERATION_MAX          = 0x0010, /* find max pcm value of pcm samples */
+    VP_PCM_OPERATION_APP_SPECIFIC = 0x0020, /* generic operation */
+    VP_PCM_OPERATION_FREQ         = 0x0040, /* Measure frequency */
+    VP_PCM_OPERATION_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPcmOperationBitType;
+
+typedef uint16 VpPcmOperationMaskType;
+
+typedef struct VpPcmOperationResultsType {
+    int16 average;  /* Average value of all collected PCM samples */
+    int16 range;    /* Maximum - minimum PCM value during operation time */
+    int16 rms;      /* RMS result of all collected pcm samples */
+    int16 min;      /* Maximum pcm value found */
+    int16 max;      /* Minimum pcm value found */
+    void *pApplicationInfo; /* Any results that the implementation chooses to
+                             * pass. This data is not interpreted neither
+                             * by the VP-API nor the LT-API. LT-API passes
+                             * this pointer back to the application as part
+                             * of the test result
+                             */
+    int32 freq;     /* Measured average frequenny */
+
+    bool error;     /* indication of PCM operation process (1 = failure) */
+} VpPcmOperationResultsType;
+
+/**< The enum is used by the cal function */
+typedef enum VpCalType {
+    VP_CAL_BFILTER              = 1,
+    VP_CAL_APPLY_BFILTER        = 2,
+    VP_CAL_MEASURE_BFILTER      = 3,
+    VP_CAL_GET_SYSTEM_COEFF     = 4,
+    VP_CAL_APPLY_SYSTEM_COEFF   = 5,
+    VP_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCalType;
+
+typedef struct VpCalBFilterType {
+    uint16 vRms;    /**< Customer Target Value in approximate vRms */
+    VpProfilePtrType pAcProfile;
+} VpCalBFilterType;
+
+typedef struct VpCalApplyBFilterType {
+    VpProfilePtrType pAcProfile;
+    uint16 index;
+} VpCalApplyBFilterType;
+
+typedef enum VpCalStatusType {
+    VP_CAL_SUCCESS,
+    VP_CAL_FAILURE,
+    VP_CAL_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCalStatusType;
+
+typedef enum VpLowLevelCmdType {
+    VP_LOWLEV_PAGE_WR = 0,
+    VP_LOWLEV_PAGE_RD = 1,
+    VP_LOWLEV_MBOX_WR = 2,
+    VP_LOWLEV_MBOX_RD = 3,
+    VP_LOWLEV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpLowLevelCmdType;
+
+typedef enum VpProfileFieldIdType {
+
+    /* Device parameters */
+
+    /* DC parameters */
+    VP_PROF_FIELD_ILA
+
+} VpProfileFieldIdType;
+
+typedef struct VpProfileFieldType {
+    VpProfileFieldIdType fieldId;
+
+    union data {
+        uint16 ila;
+    } data;
+
+} VpProfileFieldType;
+
+/* The following struct can be passed to VpGetResults() if the event ID is not
+   known at compile time, to ensure that the buffer is large enough regardless
+   of the result type. */
+typedef union VpResultsType {
+    VpChkSumType codeChecksum;                  /* VP_DEV_EVID_BOOT_CMP or
+                                                   VP_DEV_EVID_CHKSUM          */
+    VpRelGainResultsType setRelGain;            /* VP_LINE_EVID_GAIN_CMP       */
+    uint8 lowLevelCmd[256];                     /* VP_LINE_EVID_LLCMD_RX_CMP   */
+    VpLoopCondResultsType getLoopCond;          /* VP_LINE_EVID_RD_LOOP        */
+    VpOptionValueType getOption;                /* VP_LINE_EVID_RD_OPTION      */
+    VpTestResultType testLine;                  /* VP_LINE_EVID_TEST_CMP       */
+    VpDeviceIoAccessDataType deviceIoAccess;    /* VP_DEV_EVID_IO_ACCESS_CMP   */
+    VpDeviceIoAccessExtType deviceIoAccessExt;  /* VP_DEV_EVID_IO_ACCESS_CMP   */
+    VpLineIoAccessType lineIoAccess;            /* VP_LINE_EVID_LINE_IO_RD_CMP */
+    VpQueryResultsType query;                   /* VP_LINE_EVID_QUERY_CMP      */
+} VpResultsType;
+
+typedef enum VpFreeRunModeType {
+    VP_FREE_RUN_START,
+    VP_FREE_RUN_STOP
+} VpFreeRunModeType;
+
+/******************************************************************************
+ *                 DEVICE/LINE CONTEXT (SUPPORT) DEFINITION                   *
+ ******************************************************************************/
+/* The following function pointers are required to get around problem of
+ * what comes first? chicken or the egg? when dealing with declaration of
+ * device context, function pointer table and hence the following declarations.
+ */
+struct VpDevCtxType;    /**< forward declaration */
+struct VpLineCtxType;   /**< forward declaration */
+struct VpEventType;     /**< forward declaration */
+
+/*
+ * System Configuration functions
+ */
+typedef VpStatusType
+(*VpMakeLineObjectFuncPtrType) (
+    VpTermType termType,
+    uint8 channelId,
+    struct VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    struct VpDevCtxType *pDevCtx);
+
+/*
+ * Initialization functions
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpBootLoadFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+typedef VpStatusType
+(*VpBootSlacFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize);
+#endif  /* !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * | defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpInitDeviceFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile,
+    VpProfilePtrType pFxoAcProfile,
+    VpProfilePtrType pFxoCfgProfile);
+
+typedef VpStatusType
+(*VpFreeRunFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpFreeRunModeType freeRunMode);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpInitSlacFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpInitLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+typedef VpStatusType
+(*VpConfigLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+typedef VpStatusType
+(*VpSetBFilterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpBFilterModeType bFiltMode,
+    VpProfilePtrType pAcProfile);
+
+typedef VpStatusType
+(*VpSetBatteriesFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpBatteryModeType battMode,
+    VpBatteryValuesType *pBatt);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+                                || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+typedef VpStatusType
+(*VpCalCodecFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpDeviceCalType mode);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+         * || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+         */
+
+typedef VpStatusType
+(*VpCalLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx);
+
+typedef VpStatusType
+(*VpCalFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpCalType calType,
+    void *inputArgs);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+typedef VpStatusType
+(*VpInitRingFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCadProfile,
+    VpProfilePtrType pCidProfile);
+
+typedef VpStatusType
+(*VpInitCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpInitMeterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+typedef VpStatusType
+(*VpInitCustomTermTypeFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCustomTermProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+typedef VpStatusType
+(*VpInitProfileFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpProfileType type,
+    VpProfilePtrType pProfileIndex,
+    VpProfilePtrType pProfile);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpSoftResetFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Control functions
+ */
+typedef VpStatusType
+(*VpSetLineStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+typedef VpStatusType
+(*VpSetLineToneFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+typedef VpStatusType
+(*VpSetRelayStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpRelayControlType rState);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+typedef VpStatusType
+(*VpSetCalRelayStateFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpCalRelayControlType rState);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+typedef VpStatusType
+(*VpSetRelGainFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 txLevel,
+    uint16 rxLevel,
+    uint16 handle);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+typedef VpStatusType
+(*VpSendSignalFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpSendSignalType signalType,
+    void *pSignalData);
+
+typedef VpStatusType
+(*VpSendCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    VpProfilePtrType pCidProfile,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpContinueCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpStartMeterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpStartMeter32QFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint32 minDelay,
+    uint32 onTime,
+    uint32 offTime,
+    uint16 numMeters,
+    uint16 eventRate);
+
+typedef VpStatusType
+(*VpGenTimerCtrlFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpGenTimerCtrlType timerCtrl,
+    uint32 duration,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpAssocDslLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    bool connect,
+    uint8 line);
+
+typedef VpStatusType
+(*VpSetSealCurFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    uint16 sealApplyTime,
+    uint16 sealCycleTime,
+    uint16 maxCurrent,
+    uint16 minCurrent,
+    uint16 *pSealArray,
+    VpProfilePtrType pDcProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpSetOptionFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    void *pValue);
+
+typedef VpStatusType
+(*VpDeviceIoAccessFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessDataType *pDeviceIoData);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpDeviceIoAccessExtFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessExtType *pDeviceIoAccess);
+
+typedef VpStatusType
+(*VpLineIoAccessFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineIoAccessType *pLineIoAccess,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpVirtualISRFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpApiTickFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    bool *pEventStatus);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(ZARLINK_CFG_INTERNAL)
+typedef VpStatusType
+(*VpLowLevelCmdFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 *pCmdData,
+    uint8 len,
+    uint16 handle);
+#endif
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpLowLevelCmd16FuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLowLevelCmdType cmdType,
+    uint16 *writeWords,
+    uint8 numWriteWords,
+    uint8 numReadWords,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Status and query functions
+ */
+
+typedef bool
+(*VpGetEventFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    struct VpEventType *pEvent);
+
+typedef VpStatusType
+(*VpGetLineStatusFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+typedef VpStatusType
+(*VpGetDeviceStatusFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpInputType input,
+    uint32 *pDeviceStatus);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpGetDeviceStatusExtFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceStatusType *pDeviceStatus);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+typedef VpStatusType
+(*VpGetLoopCondFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+typedef VpStatusType
+(*VpGetOptionFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpGetLineStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineStateType *pCurrentState);
+
+typedef VpStatusType
+(*VpFlushEventsFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpGetResultsFuncPtrType) (
+    struct VpEventType *pEvent,
+    void *pResults);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpClearResultsFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+                                || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+typedef VpStatusType
+(*VpGetRelayStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpRelayControlType *pRstate);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+         * || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+         */
+
+typedef VpStatusType
+(*VpObjectDumpFuncPtrType)(
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpRegisterDumpFuncPtrType)(
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpDtmfDigitDetectedFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+
+typedef VpStatusType
+(*VpQueryFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpQueryIdType queryId,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Test Functions
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+                                || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+typedef VpStatusType
+(*VpTestLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpTestLineIntFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle,
+    bool callback);
+
+typedef VpStatusType
+(*VpTestLineCallbackType) (
+    struct VpLineCtxType *pLineCtx,
+    VpPcmOperationResultsType *pResults);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpCodeCheckSumFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpSelfTestFuncPtrType) (
+    struct VpLineCtxType *pLineCtx);
+
+typedef VpStatusType
+(*VpFillTestBufFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+typedef VpStatusType
+(*VpReadTestBufFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+         * || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+         */
+
+/** ApiFunctionPointer Table to be used by Device Context */
+typedef struct ApiFunctions {
+    /* System Configuration Functions */
+    VpMakeLineObjectFuncPtrType MakeLineObject;
+
+    /* Initialization Functions */
+    /*   -- Init Functions common to all devices and VP-API-II configuration modes */
+    VpInitDeviceFuncPtrType InitDevice;
+    VpFreeRunFuncPtrType FreeRun;
+
+    VpInitLineFuncPtrType InitLine;
+    VpConfigLineFuncPtrType ConfigLine;
+
+    VpCalLineFuncPtrType CalLine;
+    VpCalFuncPtrType Cal;
+    VpInitProfileFuncPtrType InitProfile;
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+    VpBootLoadFuncPtrType BootLoad;
+    VpBootSlacFuncPtrType BootSlac;
+    VpInitSlacFuncPtrType InitSlac;
+    VpSoftResetFuncPtrType SoftReset;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpSetBFilterFuncPtrType SetBFilter;
+    VpSetBatteriesFuncPtrType SetBatteries;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+                                || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+    VpCalCodecFuncPtrType CalCodec;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II except VE580 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+    VpInitCustomTermTypeFuncPtrType InitCustomTerm;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II Lite Version */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+    VpInitRingFuncPtrType InitRing;
+    VpInitCidFuncPtrType InitCid;
+    VpInitMeterFuncPtrType InitMeter;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+         */
+
+    /* Control Functions */
+    /*   -- Control Functions common to all devices and VP-API-II configuration modes */
+    VpSetLineStateFuncPtrType SetLineState;
+    VpSetLineToneFuncPtrType SetLineTone;
+    VpSetRelayStateFuncPtrType SetRelayState;
+    VpSetRelGainFuncPtrType SetRelGain;
+
+    VpSetOptionFuncPtrType SetOption;
+    VpDeviceIoAccessFuncPtrType DeviceIoAccess;
+    VpVirtualISRFuncPtrType VirtualISR;
+    VpApiTickFuncPtrType ApiTick;
+
+    /*   -- Control Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+    VpSetCalRelayStateFuncPtrType SetCalRelayState;
+
+    VpStartMeter32QFuncPtrType StartMeter32Q;
+    VpGenTimerCtrlFuncPtrType GenTimerCtrl;
+    VpAssocDslLineFuncPtrType AssocDslLine;
+    VpSetSealCurFuncPtrType SetSealCur;
+
+    VpDeviceIoAccessExtFuncPtrType DeviceIoAccessExt;
+    VpLineIoAccessFuncPtrType LineIoAccess;
+
+    VpLowLevelCmd16FuncPtrType LowLevelCmd16;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(ZARLINK_CFG_INTERNAL)
+    VpLowLevelCmdFuncPtrType LowLevelCmd;
+#endif
+
+    /*   -- Control Functions NOT provided in CSLAC VP-API-II Lite Version */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+    VpSendSignalFuncPtrType SendSignal;
+    VpSendCidFuncPtrType SendCid;
+    VpContinueCidFuncPtrType ContinueCid;
+    VpStartMeterFuncPtrType StartMeter;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+         */
+
+    /* Status and Query Functions */
+    /*   -- Status and Query Functions common to all devices and VP-API-II configuration modes */
+    VpGetEventFuncPtrType GetEvent;
+    VpGetLineStatusFuncPtrType GetLineStatus;
+    VpGetDeviceStatusFuncPtrType GetDeviceStatus;
+
+    VpGetOptionFuncPtrType GetOption;
+    VpGetLineStateFuncPtrType GetLineState;
+    VpFlushEventsFuncPtrType FlushEvents;
+    VpGetResultsFuncPtrType GetResults;
+
+    VpObjectDumpFuncPtrType ObjectDump;
+    VpRegisterDumpFuncPtrType RegisterDump;
+    VpDtmfDigitDetectedFuncPtrType DtmfDigitDetected;
+
+    /*   -- Status and Query Functions used only for CSLAC Line Testing */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+                                || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+    VpGetRelayStateFuncPtrType GetRelayState;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+         * || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+         */
+
+    /*   -- Status and Query Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+    VpGetDeviceStatusExtFuncPtrType GetDeviceStatusExt;
+    VpClearResultsFuncPtrType ClearResults;
+    VpQueryFuncPtrType Query;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Status and Query Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpGetLoopCondFuncPtrType GetLoopCond;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+    /* Test Functions */
+    /*   -- All test functions removed for CSLAC VP-API-II unless Line Test is included */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+                                || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+    /*   -- Test Functions common to all devices and VP-API-II configuration modes */
+    VpTestLineFuncPtrType TestLine;
+    VpTestLineIntFuncPtrType TestLineInt;
+    VpTestLineCallbackType TestLineCallback;
+
+    /*   -- Test Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+    VpCodeCheckSumFuncPtrType CodeCheckSum;
+    VpFillTestBufFuncPtrType FillTestBuf;
+    VpReadTestBufFuncPtrType ReadTestBuf;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Test Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+            || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpSelfTestFuncPtrType SelfTest;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         *  || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+         * || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+         */
+} ApiFunctions;
+
+/******************************************************************************
+ *                       DEVICE/LINE CONTEXT DEFINITION                       *
+ ******************************************************************************/
+/** Voice Path Line Context type */
+typedef struct VpLineCtxType {
+    struct VpDevCtxType *pDevCtx;   /**< Pointer back Device Context */
+
+    void *pLineObj;                 /**< Pointer (forward) to Line Object */
+} VpLineCtxType;
+
+/** Voice Path Device Context type */
+typedef struct VpDevCtxType {
+    VpDeviceType deviceType;    /**< What type is the device context (enum) */
+    void *pDevObj;              /**< Pointer to device object */
+
+    ApiFunctions funPtrsToApiFuncs; /**< Pointers to API functions */
+
+    /**< Pointers to each line context associated with this device.  Set size
+     * to max allowable per device in system
+     */
+    VpLineCtxType *pLineCtx[VP_MAX_LINES_PER_DEVICE];
+} VpDevCtxType;
+
+/******************************************************************************
+ *                        VP-API-II Definitions that use context              *
+ ******************************************************************************/
+/** Event struct: Type reported by VpGetEvent(). */
+typedef struct VpEventType {
+    VpStatusType status;        /**< Function return status */
+
+    uint8 channelId;            /**< Channel that caused the event */
+
+    VpLineCtxType *pLineCtx;    /**< Pointer to the line context (corresponding
+                                 *   to the channel that caused the event) */
+
+    VpDeviceIdType deviceId;    /**< device chip select ID corresponding to the
+                                 *   device that caused the event */
+
+    VpDevCtxType *pDevCtx;      /**< Pointer to the device context
+                                 *   (corresponding to the device that caused
+                                 *   the event) */
+
+    VpEventCategoryType eventCategory; /**< Event category.  The event catagory
+                                        *   is necessary because there are more
+                                        *   events than can be specified by the
+                                        *   size of "eventId  */
+
+    uint16 eventId;     /**< The event that occurred.  Requires that the event
+                         *   catagory be known to interpret */
+
+    uint16 parmHandle;  /**< EventÂ’s Parameter or Host Handle.  This value is
+                         *   specified by the application only, not used by the
+                         *   API */
+
+    uint16 eventData;   /**< Data associated with the event. Event Id specific*/
+
+    bool hasResults;    /**< If TRUE indicates this event has results associated
+                         *   with it */
+
+    VpLineIdType lineId;    /**< Application provide line Id to ease mapping of
+                             * lines to specific line contexts.
+                             */
+} VpEventType;
+
+/**< The following types are for VpGetDeviceInfo() and VpGetLineInfo()
+ * functions */
+
+typedef enum VpFeatureType {
+    VP_UNKNOWN,
+    VP_AVAILABLE,
+    VP_NOT_AVAILABLE
+} VpFeatureType;
+
+typedef struct VpFeatureListType {
+    VpFeatureType testLoadSwitch;
+    VpFeatureType internalTestTermination;
+} VpFeatureListType;
+
+typedef struct VpDeviceInfoType {
+    VpLineCtxType *pLineCtx;            /* Pointer to Line Context */
+    VpDeviceIdType deviceId;            /* Device identity */
+    VpDevCtxType *pDevCtx;              /* Pointer to device Context */
+    VpDeviceType deviceType;            /* Device Type */
+    VpFeatureListType featureList;      /* Store the device features */
+    uint8 numLines;                     /* Number of lines */
+    uint8 revCode;                      /* Revision Code Number */
+    uint8 slacId;                       /* Unique ID associated with Device identity */
+    uint16 productCode;                 /* Number indicating features of the device.*/
+} VpDeviceInfoType;
+
+typedef struct VpLineInfoType {
+    VpDevCtxType *pDevCtx;       /* Pointer to device Context */
+    uint8 channelId;             /* Channel identity */
+    VpLineCtxType *pLineCtx;     /* Pointer to Line Context */
+    VpTermType termType;         /* Termination Type */
+    VpLineIdType lineId;         /* Application system wide line identifier */
+} VpLineInfoType;
+
+/******************************************************************************
+ *                        VP-API-II FUNCTION PROTOTYPES                       *
+ ******************************************************************************/
+/*
+ * System configuration functions
+ */
+EXTERN VpStatusType
+VpMakeDeviceObject(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    VpDevCtxType *pDevCtx,
+    void *pDevObj);
+
+EXTERN VpStatusType
+VpMakeDeviceCtx(
+    VpDeviceType deviceType,
+    VpDevCtxType *pDevCtx,
+    void *pDevObj);
+
+EXTERN VpStatusType
+VpMakeLineObject(
+    VpTermType termType,
+    uint8 channelId,
+    VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpMakeLineCtx(
+    VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpFreeLineCtx(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpGetDeviceInfo(
+    VpDeviceInfoType *pDeviceInfo);
+
+EXTERN VpStatusType
+VpGetLineInfo(
+    VpLineInfoType *pLineInfo);
+
+/*
+ * Initialization functions
+ */
+EXTERN VpStatusType
+VpBootLoad(
+    VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+EXTERN VpStatusType
+VpBootSlac(
+    VpLineCtxType *pLineCtx,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize);
+
+EXTERN VpStatusType
+VpInitDevice(
+    VpDevCtxType *pDevCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile,
+    VpProfilePtrType pFxoAcProfile,
+    VpProfilePtrType pFxoCfgProfile);
+
+EXTERN VpStatusType
+VpFreeRun(
+    VpDevCtxType *pDevCtx,
+    VpFreeRunModeType freeRunMode);
+
+EXTERN VpStatusType
+VpInitSlac(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpInitLine(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpConfigLine(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpCalCodec(
+    VpLineCtxType *pLineCtx,
+    VpDeviceCalType mode);
+
+EXTERN VpStatusType
+VpCalLine(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpCal(
+    VpLineCtxType *pLineCtx,
+    VpCalType calType,
+    void *inputArgs);
+
+EXTERN VpStatusType
+VpInitRing(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCadProfile,
+    VpProfilePtrType pCidProfile);
+
+EXTERN VpStatusType
+VpInitCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpInitMeter(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+
+EXTERN VpStatusType
+VpInitCustomTermType (
+    VpDevCtxType *pDevCtx,
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCustomTermProfile);
+
+EXTERN VpStatusType
+VpInitProfile(
+    VpDevCtxType *pDevCtx,
+    VpProfileType type,
+    VpProfilePtrType pProfileIndex,
+    VpProfilePtrType pProfile);
+
+EXTERN VpStatusType
+VpSoftReset(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpSetBatteries(
+    VpLineCtxType *pLineCtx,
+    VpBatteryModeType battMode,
+    VpBatteryValuesType *pBatt);
+
+EXTERN VpStatusType
+VpSetBFilter(
+    VpLineCtxType *pLineCtx,
+    VpBFilterModeType bFiltMode,
+    VpProfilePtrType pAcProfile);
+
+/*
+ * Control functions
+ */
+EXTERN VpStatusType
+VpSetLineState(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+EXTERN VpStatusType
+VpSetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+EXTERN VpStatusType
+VpSetRelayState(
+    VpLineCtxType *pLineCtx,
+    VpRelayControlType rState);
+
+EXTERN VpStatusType
+VpSetCalRelayState(
+    VpDevCtxType *pDevCtx,
+    VpCalRelayControlType rState);
+
+EXTERN VpStatusType
+VpSetRelGain(
+    VpLineCtxType *pLineCtx,
+    uint16 txLevel,
+    uint16 rxLevel,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpSendSignal(
+    VpLineCtxType *pLineCtx,
+    VpSendSignalType signalType,
+    void *pSignalData);
+
+EXTERN VpStatusType
+VpSendCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    VpProfilePtrType pCidProfile,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpContinueCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpStartMeter(
+    VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+
+EXTERN VpStatusType
+VpStartMeter32Q(
+    VpLineCtxType *pLineCtx,
+    uint32 minDelay,
+    uint32 onTime,
+    uint32 offTime,
+    uint16 numMeters,
+    uint16 eventRate);
+
+EXTERN VpStatusType
+VpAssocDslLine(
+    VpLineCtxType *pLineCtx,
+    bool connect,
+    uint8 line);
+
+EXTERN VpStatusType
+VpSetSealCur(
+    VpDevCtxType *pDevCtx,
+    uint16 sealApplyTime,
+    uint16 sealCycleTime,
+    uint16 maxCurrent,
+    uint16 minCurrent,
+    uint16 *pSealArray,
+    VpProfilePtrType pDcProfile);
+
+
+#define VpStartMeter32(pLineCtx, minDelay, onTime, offTime, numMeters) \
+    VpStartMeter32Q(pLineCtx, minDelay, onTime, offTime, numMeters, 1)
+
+EXTERN VpStatusType
+VpSetOption(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    void *pValue);
+
+EXTERN VpStatusType
+VpDeviceIoAccess(
+    VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessDataType *pDeviceIoData);
+
+VpStatusType
+VpDeviceIoAccessExt(
+    VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessExtType *pDeviceIoAccess);
+
+EXTERN VpStatusType
+VpLineIoAccess(
+    VpLineCtxType *pLineCtx,
+    VpLineIoAccessType *pLineIoAccess,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpVirtualISR(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpApiTick(
+    VpDevCtxType *pDevCtx,
+    bool *pEventStatus);
+
+EXTERN VpStatusType
+VpLowLevelCmd(
+    VpLineCtxType *pLineCtx,
+    uint8 *pCmdData,
+    uint8 len,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpLowLevelCmd16(
+    VpLineCtxType *pLineCtx,
+    VpLowLevelCmdType cmdType,
+    uint16 *writeWords,
+    uint8 numWriteWords,
+    uint8 numReadWords,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGenTimerCtrl(
+    VpLineCtxType *pLineCtx,
+    VpGenTimerCtrlType timerCtrl,
+    uint32 duration,
+    uint16 handle);
+
+/*
+ * Status and query functions
+ */
+EXTERN bool
+VpGetEvent(
+    VpDevCtxType *pDevCtx,
+    VpEventType *pEvent);
+
+EXTERN VpStatusType
+VpGetLineStatus(
+    VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+EXTERN VpStatusType
+VpGetDeviceStatus(
+    VpDevCtxType *pDevCtx,
+    VpInputType input,
+    uint32 *pDeviceStatus);
+
+EXTERN VpStatusType
+VpGetDeviceStatusExt(
+    VpDevCtxType *pDevCtx,
+    VpDeviceStatusType *pDeviceStatus);
+
+EXTERN VpStatusType
+VpGetLoopCond(
+    VpLineCtxType *pLineCtx,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetOption(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetLineState(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType *pCurrentState);
+
+EXTERN VpStatusType
+VpFlushEvents(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpGetResults(
+    VpEventType *pEvent,
+    void *pResults);
+
+EXTERN VpStatusType
+VpClearResults(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpObjectDump(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpRegisterDump(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpDtmfDigitDetected(
+    VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+EXTERN VpStatusType
+VpQuery(
+    VpLineCtxType *pLineCtx,
+    VpQueryIdType queryId,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetRelayState(
+    VpLineCtxType *pLineCtx,
+    VpRelayControlType *pRstate);
+
+/*
+ * Test Functions
+ */
+EXTERN VpStatusType
+VpTestLine(
+    VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpTestLineCallback(
+    VpLineCtxType *pLineCtx,
+    VpPcmOperationResultsType *pResults);
+
+EXTERN VpStatusType
+VpCodeCheckSum(
+    VpDevCtxType *pDevCtx,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpSelfTest(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpFillTestBuf(
+    VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+EXTERN VpStatusType
+VpReadTestBuf(
+    VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+
+EXTERN VpStatusType
+VpMapLineId(
+    VpLineCtxType *pLineCtx,
+    VpLineIdType lineId);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+EXTERN VpStatusType
+VpMapSlacId(
+    VpDevCtxType *pDevCtx,
+    uint8 slacId);
+#endif
+
+EXTERN bool
+VpMemCpyCheck(
+    uint8 *dest,
+    uint8 *src,
+    uint16 count);
+
+EXTERN void *
+VpMemCpy(
+    void *dest,
+    const void *src,
+    uint16 count);
+
+EXTERN void *
+VpMemSet(
+    void * s,
+    int c,
+    uint16 count);
+
+
+/*
+ * Undocumented external functions:
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+EXTERN void
+VpSetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+EXTERN bool
+VpReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+Vcp2HbiCheck(
+    VpDevCtxType *pDevCtx);
+#endif
+
+EXTERN void
+VpMpiCmdWrapper(
+    VpDeviceIdType deviceId,
+    uint8 ecVal,
+    uint8 mpiCmd,
+    uint8 mpiCmdLen,
+    uint8 *dataBuffer);
+
+EXTERN uint8
+VpCSLACBuildMpiBuffer(
+    uint8 index,
+    uint8 *mpiBuffer,
+    uint8 mpiCmd,
+    uint8 mpiCmdLen,
+    uint8 *mpiData);
+#endif /* VP_API_COMMON_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cslac_seq.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cslac_seq.h
new file mode 100755
index 0000000..a1baeaa
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_cslac_seq.h
@@ -0,0 +1,125 @@
+/** \file vp_api_cslac_seq.h
+ * vp_api_cslac_seq.h
+ *
+ * Header file for the API-II c files.
+ *
+ * This file contains the all of the VoicePath API-II function prototypes
+ * required to run the CSLAC sequencer.
+ *
+ * $Revision: 8873 $
+ * $LastChangedDate: 2011-09-23 12:00:01 -0500 (Fri, 23 Sep 2011) $
+ */
+
+#ifndef VP_API_CSLAC_SEQ_H
+#define VP_API_CSLAC_SEQ_H
+
+#include "vp_CSLAC_types.h"
+
+#ifdef VP_CSLAC_SEQ_EN
+
+/*
+ * Converting from bool to enumeration. So make sure there exists a string that
+ * maps directly to previous "FALSE" value. Other strings can take on any valid
+ * enumeration value.
+ */
+typedef enum VpCliEncodedDataType {
+    VP_CLI_ENCODE_END = 0,
+    VP_CLI_ENCODE_DATA = 1,
+    VP_CLI_ENCODE_MARKOUT = 2
+} VpCliEncodedDataType;
+
+VpStatusType
+VpSeq(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pProfile);
+
+VpStatusType
+VpBranchInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+
+VpStatusType
+VpTimeInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+
+#if (defined (VP_CC_890_SERIES) && defined (VP890_FXS_SUPPORT)) || \
+    (defined (VP_CC_880_SERIES) && defined (VP880_FXS_SUPPORT))
+bool
+VpCSLACHowlerInit(
+    VpSeqDataType *cadence,
+    uint16 tickRate);
+
+uint16
+VpDecimalMultiply(
+    uint16 value,
+    uint16 byteMask);
+
+bool
+VpCSLACProcessRampGenerators(
+    VpSeqDataType *cadence);
+#endif
+
+bool
+VpServiceSeq(
+    VpDevCtxType *pDevCtx);
+
+void
+VpCSLACInitCidStruct(
+    VpCallerIdType *pCidStruct,
+    uint8 sequenceData);
+
+VpStatusType
+VpCidSeq(
+    VpLineCtxType *pLineCtx);
+
+void
+VpCliStopCli(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+VpCSLACCliGetEncodedByte(
+    uint8 *pByte,
+    VpCallerIdType *pCidStruct,
+    uint16 *pProcessData,
+    VpOptionEventMaskType *pLineEvents,
+    uint8 checkSumIndex);
+
+VpStatusType
+VpCSLACInitMeter(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+
+VpStatusType
+VpCSLACStartMeter(
+    VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+
+#if defined (VP_CC_790_SERIES)
+VpStatusType
+Vp790CommandInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+#endif
+
+#if defined (VP_CC_880_SERIES)
+VpStatusType
+Vp880CommandInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+#endif
+
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+Vp580CommandInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+#endif
+
+#endif
+
+#endif
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_dev_term.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_dev_term.h
new file mode 100755
index 0000000..0baa9c1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_dev_term.h
@@ -0,0 +1,82 @@
+/** \file vp_api_dev_term.h
+ * vp_api_dev_term.h
+ *
+ * This file contains declaration for VP-API Device and termination types.
+ *
+ * $Revision: 8873 $
+ * $LastChangedDate: 2011-09-23 12:00:01 -0500 (Fri, 23 Sep 2011) $
+ */
+
+#ifndef VP_API_DEV_TERM_H
+#define VP_API_DEV_TERM_H
+
+/******************************************************************************
+ *                                ENUMERATIONS                                *
+ ******************************************************************************/
+/* Valid Device Types supported by VP-API-II. For the corresponding part numbers
+ * supported by each device type please see VP-API-II documentation.
+ */
+typedef enum VpDeviceType {
+    VP_DEV_RSRVD1 = 0,
+    VP_DEV_580_SERIES,
+    VP_DEV_790_SERIES,
+    VP_DEV_VCP_SERIES,
+    VP_DEV_880_SERIES = 4,  /* Fixed value to match calibration profile */
+    VP_DEV_RSVD_SERIES,
+    VP_DEV_VCP2_SERIES,
+    VP_DEV_KWRAP,
+    VP_DEV_890_SERIES = 8,  /* Fixed value to match calibration profile */
+    VP_DEV_792_SERIES,
+    VP_DEV_MELT_SERIES,
+    VP_DEV_792_GROUP,
+    VP_NUM_DEV_TYPES,
+    VP_DEV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceType;
+
+/**
+ * Deprecated name (VCP) based on older name for VCP. All new applications
+ * should use VCP instead
+ */
+#define VP_DEV_DVP_SERIES  VP_DEV_VCP_SERIES
+
+/** Valid Termination Types (per line) supported by API-II.  See the VP-API-II
+    Reference Guide for descriptions. */
+typedef enum VpTermType {
+    /* FXS */
+    VP_TERM_FXS_GENERIC            = 0x00, VP_TERM_FXS_FIRST = VP_TERM_FXS_GENERIC,
+    VP_TERM_FXS_ISOLATE            = 0x01,
+    VP_TERM_FXS_TITO_TL_R          = 0x02,
+    VP_TERM_FXS_CO_TL              = 0x03,
+    VP_TERM_FXS_75181              = 0x04,
+    VP_TERM_FXS_75282              = 0x05,
+    VP_TERM_FXS_RDT                = 0x06,
+    VP_TERM_FXS_RR                 = 0x07,
+    VP_TERM_FXS_SPLITTER           = 0x08,
+    VP_TERM_FXS_TO_TL              = 0x09,
+    VP_TERM_FXS_LOW_PWR            = 0x0A,
+    VP_TERM_FXS_TI                 = 0x0B,
+    VP_TERM_FXS_SPLITTER_LP        = 0x0C,
+    VP_TERM_FXS_ISOLATE_LP         = 0x0D,
+    VP_TERM_FXS_LCAS               = 0x0E,
+    VP_TERM_FXS_RR_TI              = 0x0F,
+    VP_TERM_FXS_CUSTOM             = 0x10,
+    VP_TERM_FXS_TL_MW              = 0x11, VP_TERM_FXS_LAST = VP_TERM_FXS_TL_MW,
+
+    /* MeLT */
+    VP_TERM_MELT_RELAY_CAL_CT      = 0x40, VP_TERM_MELT_FIRST = VP_TERM_MELT_RELAY_CAL_CT,
+    VP_TERM_MELT_RELAY_CAL_SPLIT   = 0x41,
+    VP_TERM_MELT_RELAY_CAL_BRIDGED = 0x42,
+    VP_TERM_MELT_LTAS_CT           = 0x43,
+    VP_TERM_MELT_RELAY_CT          = 0x44,
+    VP_TERM_MELT_RELAY_SPLIT       = 0x45,
+    VP_TERM_MELT_RELAY_BRIDGED     = 0x46, VP_TERM_MELT_LAST = VP_TERM_MELT_RELAY_BRIDGED,
+
+    /* FXO */
+    VP_TERM_FXO_GENERIC            = 0x80, VP_TERM_FXO_FIRST = VP_TERM_FXO_GENERIC,
+    VP_TERM_FXO_DISC               = 0x81,
+    VP_TERM_FXO_CUSTOM             = 0x82, VP_TERM_FXO_LAST = VP_TERM_FXO_CUSTOM,
+
+    VP_TERM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpTermType;
+
+#endif /* VP_API_DEV_TERM_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_event.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_event.h
new file mode 100755
index 0000000..7714232
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_event.h
@@ -0,0 +1,599 @@
+/** \file vp_api_event.h
+ * vp_api_event.h
+ *
+ * This file contains declaration associated with VP-API events.
+ *
+ * $Revision: 8929 $
+ * $LastChangedDate: 2011-10-07 15:22:45 -0500 (Fri, 07 Oct 2011) $
+ */
+
+#ifndef VP_API_EVENT_H
+#define VP_API_EVENT_H
+
+#include "vp_api_types.h"
+
+#define VP_EVENT_MASK_ALL       0xFFFF
+
+/* Event category type */
+typedef enum VpEventCategoryType {
+    VP_EVCAT_FAULT     = 0,
+    VP_EVCAT_SIGNALING = 1,
+    VP_EVCAT_RESPONSE  = 2,
+    VP_EVCAT_TEST      = 3,
+    VP_EVCAT_PROCESS   = 4,
+    VP_EVCAT_FXO       = 5,
+    VP_EVCAT_PACKET    = 6,
+    VP_NUM_EVCATS,
+    VP_EVCAT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpEventCategoryType;
+
+typedef struct VpOptionEventMaskType {
+    uint16 faults;      /**< Fault event mask */
+    uint16 signaling;   /**< Signaling event mask */
+    uint16 response;    /**< Mailbox response event mask */
+    uint16 test;        /**< Test events */
+    uint16 process;     /**< Call process related events */
+    uint16 fxo;         /**< FXO events mask */
+    uint16 packet;      /**< Packet events mask - no longer used */
+} VpOptionEventMaskType;
+
+#ifdef STRICT_SIGNED_ENUM_VALUES
+typedef uint16 VpFaultEventType;
+#define VP_DEV_EVID_BAT_FLT         (0x0001)
+#define VP_DEV_EVID_CLK_FLT         (0x0002)
+#define VP_LINE_EVID_THERM_FLT      (0x0004)
+#define VP_LINE_EVID_DC_FLT         (0x0008)
+#define VP_LINE_EVID_AC_FLT         (0x0010)
+#define VP_LINE_EVID_SYNC_FLT       (0x0020)
+#define VP_LINE_EVID_RES_LEAK_FLT   (0x0040)
+#define VP_LINE_EVID_SEAL_CUR_FLT   (0x0080)
+#define VP_DEV_EVID_WDT_FLT         (0x2000)
+#define VP_DEV_EVID_EVQ_OFL_FLT     (0x4000)
+#define VP_DEV_EVID_SYSTEM_FLT      (0x8000)
+
+/* The following fault events are device-specific, not line-specific */
+#define VP_EVCAT_FAULT_DEV_EVENTS   (VP_DEV_EVID_BAT_FLT     | \
+                                     VP_DEV_EVID_CLK_FLT     | \
+                                     VP_DEV_EVID_EVQ_OFL_FLT | \
+                                     VP_DEV_EVID_WDT_FLT     | \
+                                     VP_DEV_EVID_SYSTEM_FLT)
+
+/* Remaining undefined events should be masked to protect against future changes */
+#define VP_EVCAT_FAULT_UNDEFINED    (~(VP_DEV_EVID_BAT_FLT     | \
+                                       VP_DEV_EVID_CLK_FLT     | \
+                                       VP_LINE_EVID_THERM_FLT  | \
+                                       VP_LINE_EVID_DC_FLT     | \
+                                       VP_LINE_EVID_AC_FLT     | \
+                                       VP_LINE_EVID_SYNC_FLT   | \
+                                       VP_LINE_EVID_RES_LEAK_FLT | \
+                                       VP_LINE_EVID_SEAL_CUR_FLT | \
+                                       VP_DEV_EVID_WDT_FLT     | \
+                                       VP_DEV_EVID_EVQ_OFL_FLT | \
+                                       VP_DEV_EVID_SYSTEM_FLT))
+
+#define VP_EVCAT_FAULT_UNMASK_ALL   (VP_EVENT_MASK_ALL & VP_EVCAT_FAULT_UNDEFINED)
+#define VP_EVCAT_FAULT_MASK_ALL     (~VP_EVCAT_FAULT_UNDEFINED)
+#else
+typedef enum VpFaultEventType {
+    VP_DEV_EVID_BAT_FLT         = 0x0001, /**< Device detected battery fault */
+    VP_DEV_EVID_CLK_FLT         = 0x0002, /**< Device detected clock fault */
+    VP_LINE_EVID_THERM_FLT      = 0x0004, /**< Thermal Overload condition */
+    VP_LINE_EVID_DC_FLT         = 0x0008, /**< DC Fault detected on line */
+    VP_LINE_EVID_AC_FLT         = 0x0010, /**< AC Fault detected on line */
+    VP_LINE_EVID_SYNC_FLT       = 0x0020, /**< SLAC Synchronization fault */
+    VP_LINE_EVID_RES_LEAK_FLT   = 0x0040, /**< Low loop resistance while on-hook */
+    VP_LINE_EVID_SEAL_CUR_FLT   = 0x0080, /**< Sealing current error */
+    VP_DEV_EVID_WDT_FLT         = 0x2000, /**< Watchdog timer fault */
+    VP_DEV_EVID_EVQ_OFL_FLT     = 0x4000, /**< event queue overflow fault */
+    VP_DEV_EVID_SYSTEM_FLT      = 0x8000, /**< VCP2 system fault */
+    /* The following fault events are device-specific, not line-specific */
+    VP_EVCAT_FAULT_DEV_EVENTS   = (int)(VP_DEV_EVID_BAT_FLT     |
+                                        VP_DEV_EVID_CLK_FLT     |
+                                        VP_DEV_EVID_EVQ_OFL_FLT |
+                                        VP_DEV_EVID_WDT_FLT     |
+                                        VP_DEV_EVID_SYSTEM_FLT),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_FAULT_UNDEFINED    = (int)(~(VP_DEV_EVID_BAT_FLT     |
+                                          VP_DEV_EVID_CLK_FLT     |
+                                          VP_LINE_EVID_THERM_FLT  |
+                                          VP_LINE_EVID_DC_FLT     |
+                                          VP_LINE_EVID_AC_FLT     |
+                                          VP_LINE_EVID_SYNC_FLT   |
+                                          VP_LINE_EVID_RES_LEAK_FLT |
+                                          VP_LINE_EVID_SEAL_CUR_FLT |
+                                          VP_DEV_EVID_WDT_FLT     |
+                                          VP_DEV_EVID_EVQ_OFL_FLT |
+                                          VP_DEV_EVID_SYSTEM_FLT)), /* NOTES:
+    * The typecasting (int) is necessary in some compilers that have
+    * sizeof(enum)  == sizeof(int) == 2bytes and also because of 'C' rules for
+    * hexadecimal constants. Hexadecimal constants are treated as unsigned and
+    * enum variables are of type signed int. Thus compilers generate warning
+    * when code attempts to assign number that is bigger than what a signed enum
+    * can hold */
+
+    VP_EVCAT_FAULT_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                         VP_EVCAT_FAULT_UNDEFINED),
+    VP_EVCAT_FAULT_MASK_ALL     = (int)(~VP_EVCAT_FAULT_UNDEFINED),
+    VP_EVCAT_FAULT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpFaultEventType;
+#endif
+
+#ifdef STRICT_SIGNED_ENUM_VALUES
+typedef uint16 VpSignalingEventType;
+#define VP_LINE_EVID_HOOK_OFF       (0x0001)
+#define VP_LINE_EVID_HOOK_ON        (0x0002)
+#define VP_LINE_EVID_GKEY_DET       (0x0004)
+#define VP_LINE_EVID_GKEY_REL       (0x0008)
+#define VP_LINE_EVID_FLASH          (0x0010)
+#define VP_LINE_EVID_STARTPULSE     (0x0020)
+#define VP_LINE_EVID_DTMF_DIG       (0x0040)
+#define VP_LINE_EVID_PULSE_DIG      (0x0080)
+#define VP_LINE_EVID_MTONE          (0x0100)
+#define VP_DEV_EVID_TS_ROLLOVER     (0x0200)
+
+#define VP_LINE_EVID_US_TONE_DETECT (0x0400)
+#define VP_LINE_EVID_DS_TONE_DETECT (0x0800)
+#define VP_DEV_EVID_SEQUENCER       (0x1000)
+#define VP_LINE_EVID_BREAK_MAX      (0x2000)
+#define VP_LINE_EVID_EXTD_FLASH     (0x4000)
+#define VP_LINE_EVID_HOOK_PREQUAL   (0x8000)
+
+/* The following signaling events are device-specific, not line-specific */
+#define VP_EVCAT_SIGNALING_DEV_EVENTS   (VP_DEV_EVID_TS_ROLLOVER | VP_DEV_EVID_SEQUENCER)
+
+/* Remaining undefined events should be masked to protect againstfuture changes */
+#define VP_EVCAT_SIGNALING_UNDEFINED    (~(VP_LINE_EVID_HOOK_OFF        | \
+                                           VP_LINE_EVID_HOOK_ON         | \
+                                           VP_LINE_EVID_GKEY_DET        | \
+                                           VP_LINE_EVID_GKEY_REL        | \
+                                           VP_LINE_EVID_FLASH           | \
+                                           VP_LINE_EVID_STARTPULSE      | \
+                                           VP_LINE_EVID_DTMF_DIG        | \
+                                           VP_LINE_EVID_PULSE_DIG       | \
+                                           VP_LINE_EVID_MTONE           | \
+                                           VP_DEV_EVID_TS_ROLLOVER      | \
+                                           VP_LINE_EVID_US_TONE_DETECT  | \
+                                           VP_LINE_EVID_DS_TONE_DETECT  | \
+                                           VP_DEV_EVID_SEQUENCER        | \
+                                           VP_LINE_EVID_BREAK_MAX       | \
+                                           VP_LINE_EVID_EXTD_FLASH      | \
+                                           VP_LINE_EVID_HOOK_PREQUAL))
+
+#define VP_EVCAT_SIGNALING_UNMASK_ALL   (VP_EVENT_MASK_ALL & VP_EVCAT_SIGNALING_UNDEFINED)
+#define VP_EVCAT_SIGNALING_MASK_ALL     (~VP_EVCAT_SIGNALING_UNDEFINED)
+#else
+typedef enum VpSignalingEventType {
+    VP_LINE_EVID_HOOK_OFF       = 0x0001, /**< Off-Hook detected */
+    VP_LINE_EVID_HOOK_ON        = 0x0002, /**< On-Hook detected */
+    VP_LINE_EVID_GKEY_DET       = 0x0004, /**< Ground Key detected */
+    VP_LINE_EVID_GKEY_REL       = 0x0008, /**< Ground Key release detected */
+    VP_LINE_EVID_FLASH          = 0x0010, /**< Hook switch flash detected */
+    VP_LINE_EVID_STARTPULSE     = 0x0020, /**< Start of a dial pulse detected */
+    VP_LINE_EVID_DTMF_DIG       = 0x0040, /**< New DTMF digit detected */
+    VP_LINE_EVID_PULSE_DIG      = 0x0080, /**< New pulse digit detected */
+    VP_LINE_EVID_MTONE          = 0x0100, /**< Modem tone detected */
+    VP_DEV_EVID_TS_ROLLOVER     = 0x0200, /**< Timestamp rollover */
+
+    VP_LINE_EVID_US_TONE_DETECT = 0x0400, /**< Upstream tone detection event */
+    VP_LINE_EVID_DS_TONE_DETECT = 0x0800, /**< Downstream tone detection event*/
+    VP_DEV_EVID_SEQUENCER       = 0x1000, /**< Sequencer Event */
+    VP_LINE_EVID_BREAK_MAX      = 0x2000, /**< Break Max time has been exceeded */
+    VP_LINE_EVID_EXTD_FLASH     = 0x4000, /**< Flash Hook between flash max and on-hook min */
+    VP_LINE_EVID_HOOK_PREQUAL   = 0x8000, /**< debounced off/on hook detected, but < offHookMin */
+
+    /* The following signaling events are device-specific, not line-specific */
+    VP_EVCAT_SIGNALING_DEV_EVENTS  = (int)(VP_DEV_EVID_TS_ROLLOVER |
+                                            VP_DEV_EVID_SEQUENCER),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_SIGNALING_UNDEFINED   = (int)(~(VP_LINE_EVID_HOOK_OFF          |
+                                             VP_LINE_EVID_HOOK_ON           |
+                                             VP_LINE_EVID_GKEY_DET          |
+                                             VP_LINE_EVID_GKEY_REL          |
+                                             VP_LINE_EVID_FLASH             |
+                                             VP_LINE_EVID_STARTPULSE        |
+                                             VP_LINE_EVID_DTMF_DIG          |
+                                             VP_LINE_EVID_PULSE_DIG         |
+                                             VP_LINE_EVID_MTONE             |
+                                             VP_DEV_EVID_TS_ROLLOVER        |
+                                             VP_LINE_EVID_US_TONE_DETECT    |
+                                             VP_LINE_EVID_DS_TONE_DETECT    |
+                                             VP_DEV_EVID_SEQUENCER          |
+                                             VP_LINE_EVID_BREAK_MAX         |
+                                             VP_LINE_EVID_EXTD_FLASH        |
+                                             VP_LINE_EVID_HOOK_PREQUAL)),
+
+    VP_EVCAT_SIGNALING_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                             VP_EVCAT_SIGNALING_UNDEFINED),
+    VP_EVCAT_SIGNALING_MASK_ALL     = (int)(~VP_EVCAT_SIGNALING_UNDEFINED),
+    VP_EVCAT_SIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSignalingEventType;
+#endif
+
+#ifdef STRICT_SIGNED_ENUM_VALUES
+typedef uint16 VpResponseEventType;
+#define VP_DEV_EVID_BOOT_CMP        (0x0001)
+
+#define VP_LINE_EVID_LLCMD_TX_CMP   (0x0002)
+#define VP_LINE_EVID_LLCMD_RX_CMP   (0x0004)
+
+#define VP_DEV_EVID_DNSTR_MBOX      (0x0008)
+#define VP_LINE_EVID_RD_OPTION      (0x0010)
+#define VP_LINE_EVID_RD_LOOP        (0x0020)
+
+#define VP_EVID_CAL_CMP             (0x0040)
+#define VP_EVID_CAL_BUSY            (0x0080)
+#define VP_LINE_EVID_GAIN_CMP       (0x0100)
+#define VP_LINE_EVID_QUERY_CMP      (0x0200)
+#define VP_DEV_EVID_DEV_INIT_CMP    (0x0400)
+#define VP_LINE_EVID_LINE_INIT_CMP  (0x0800)
+#define VP_DEV_EVID_IO_ACCESS_CMP   (0x1000)
+#define VP_LINE_EVID_LINE_IO_RD_CMP (0x2000)
+#define VP_LINE_EVID_LINE_IO_WR_CMP (0x4000)
+#define VP_LINE_EVID_SLAC_INIT_CMP  (0x8000)
+
+/* The following response events are device-specific, not line-specific */
+#define VP_EVCAT_RESPONSE_DEV_EVENTS    (VP_DEV_EVID_BOOT_CMP       | \
+                                         VP_DEV_EVID_DNSTR_MBOX     | \
+                                         VP_DEV_EVID_DEV_INIT_CMP   | \
+                                         VP_DEV_EVID_IO_ACCESS_CMP)
+
+/* Remaining undefined events should be masked to protect against future changes */
+#define VP_EVCAT_RESPONSE_UNDEFINED     (~(VP_DEV_EVID_BOOT_CMP         | \
+                                           VP_LINE_EVID_LLCMD_TX_CMP    | \
+                                           VP_LINE_EVID_LLCMD_RX_CMP    | \
+                                           VP_DEV_EVID_DNSTR_MBOX       | \
+                                           VP_LINE_EVID_RD_OPTION       | \
+                                           VP_LINE_EVID_RD_LOOP         | \
+                                           VP_EVID_CAL_CMP              | \
+                                           VP_EVID_CAL_BUSY             | \
+                                           VP_LINE_EVID_GAIN_CMP        | \
+                                           VP_LINE_EVID_QUERY_CMP       | \
+                                           VP_DEV_EVID_DEV_INIT_CMP     | \
+                                           VP_LINE_EVID_LINE_INIT_CMP   | \
+                                           VP_DEV_EVID_IO_ACCESS_CMP    | \
+                                           VP_LINE_EVID_LINE_IO_RD_CMP  | \
+                                           VP_LINE_EVID_LINE_IO_WR_CMP  | \
+                                           VP_LINE_EVID_SLAC_INIT_CMP))
+
+#define VP_EVCAT_RESPONSE_UNMASK_ALL    (VP_EVENT_MASK_ALL & VP_EVCAT_RESPONSE_UNDEFINED)
+#define VP_EVCAT_RESPONSE_MASK_ALL      (~VP_EVCAT_RESPONSE_UNDEFINED)
+#else
+typedef enum VpResponseEventType {
+    VP_DEV_EVID_BOOT_CMP        = 0x0001, /**< VCP Startup sequence has
+                                           * completed; Non-maskable
+                                           */
+    VP_LINE_EVID_LLCMD_TX_CMP   = 0x0002, /**< Low level write transaction has
+                                           * completed
+                                           */
+    VP_LINE_EVID_LLCMD_RX_CMP   = 0x0004, /**< Low Level read transaction has
+                                           * completed
+                                           */
+    VP_DEV_EVID_DNSTR_MBOX      = 0x0008, /**< Dowstream Mailbox event ready */
+    VP_LINE_EVID_RD_OPTION      = 0x0010, /**< Read Option request complete */
+    VP_LINE_EVID_RD_LOOP        = 0x0020, /**< Read Loop Conditions is complete
+                                           */
+    VP_EVID_CAL_CMP             = 0x0040, /**< Device or Line Calibration is
+                                           * complete
+                                           */
+    VP_EVID_CAL_BUSY            = 0x0080, /**< Calibration not performed, line
+                                           * busy
+                                           */
+    VP_LINE_EVID_GAIN_CMP       = 0x0100, /**< Gain Adjustment complete */
+    VP_LINE_EVID_QUERY_CMP      = 0x0200, /**< Query complete */
+    VP_DEV_EVID_DEV_INIT_CMP    = 0x0400, /**< Device Init complete */
+    VP_LINE_EVID_LINE_INIT_CMP  = 0x0800, /**< Line Init complete */
+    VP_DEV_EVID_IO_ACCESS_CMP   = 0x1000, /**< Device Access complete */
+    VP_LINE_EVID_LINE_IO_RD_CMP = 0x2000, /**< Line GPIO read complete */
+    VP_LINE_EVID_LINE_IO_WR_CMP = 0x4000, /**< Line GPIO write complete */
+    VP_LINE_EVID_SLAC_INIT_CMP  = 0x8000, /**< SLAC Init complete */
+    /* The following response events are device-specific, not line-specific */
+    VP_EVCAT_RESPONSE_DEV_EVENTS = (int)(VP_DEV_EVID_BOOT_CMP       |
+                                        VP_DEV_EVID_DNSTR_MBOX      |
+                                        VP_DEV_EVID_DEV_INIT_CMP    |
+                                        VP_DEV_EVID_IO_ACCESS_CMP),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_RESPONSE_UNDEFINED = (int)(~(VP_DEV_EVID_BOOT_CMP          |
+                                          VP_LINE_EVID_LLCMD_TX_CMP     |
+                                          VP_LINE_EVID_LLCMD_RX_CMP     |
+                                          VP_DEV_EVID_DNSTR_MBOX        |
+                                          VP_LINE_EVID_RD_OPTION        |
+                                          VP_LINE_EVID_RD_LOOP          |
+                                          VP_EVID_CAL_CMP               |
+                                          VP_EVID_CAL_BUSY              |
+                                          VP_LINE_EVID_GAIN_CMP         |
+                                          VP_LINE_EVID_QUERY_CMP        |
+                                          VP_DEV_EVID_DEV_INIT_CMP      |
+                                          VP_LINE_EVID_LINE_INIT_CMP    |
+                                          VP_DEV_EVID_IO_ACCESS_CMP     |
+                                          VP_LINE_EVID_LINE_IO_RD_CMP   |
+                                          VP_LINE_EVID_LINE_IO_WR_CMP   |
+                                          VP_LINE_EVID_SLAC_INIT_CMP)),
+
+    VP_EVCAT_RESPONSE_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                            VP_EVCAT_RESPONSE_UNDEFINED),
+    VP_EVCAT_RESPONSE_MASK_ALL     = (int)(~VP_EVCAT_RESPONSE_UNDEFINED),
+    VP_EVCAT_RES_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpResponseEventType;
+#endif
+
+typedef enum VpTestEventType {
+    VP_LINE_EVID_TEST_CMP   = 0x0001, /**< A requested test has been completed*/
+    VP_LINE_EVID_TEST_RSVD1 = 0x0002, /**< Reserved event */
+    VP_LINE_EVID_DTONE_DET  = 0x0004, /**< Dial-Tone Test - Dialtone Detected */
+    VP_LINE_EVID_DTONE_LOSS = 0x0008, /**< Dial-Tone Test - Dialtone Lost */
+    VP_DEV_EVID_STEST_CMP   = 0x0010, /**< Self Test Function complete */
+    VP_DEV_EVID_CHKSUM      = 0x0020, /**< Code-space checksum is complete */
+    VP_LINE_EVID_ABORT      = 0x0040, /**< Event requesting abort test */
+    /* The following test events are device-specific, not line-specific */
+    VP_EVCAT_TEST_DEV_EVENTS = (int)(VP_DEV_EVID_CHKSUM),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_TEST_UNDEFINED =    (int)(~(VP_LINE_EVID_TEST_CMP       |
+                                         VP_LINE_EVID_DTONE_DET      |
+                                         VP_LINE_EVID_DTONE_LOSS     |
+                                         VP_DEV_EVID_STEST_CMP       |
+                                         VP_DEV_EVID_CHKSUM)),
+
+    VP_EVCAT_TEST_UNMASK_ALL    =  (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_TEST_UNDEFINED),
+    VP_EVCAT_TEST_MASK_ALL      =  (int)(~VP_EVCAT_TEST_UNDEFINED),
+    VP_EVCAT_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpTestEventType;
+
+typedef enum VpProcessEventType {
+    VP_LINE_EVID_MTR_CMP        = 0x0001, /**< Metering Signal complete */
+    VP_LINE_EVID_MTR_ABORT      = 0x0002, /**< Metering Signal aborted */
+    VP_LINE_EVID_CID_DATA       = 0x0004, /**< Caller ID Transmission buffer is
+                                           * empty
+                                           */
+    VP_LINE_EVID_RING_CAD       = 0x0008, /**< Ring Cadence State change
+                                           * information
+                                           */
+    VP_LINE_EVID_SIGNAL_CMP     = 0x0010, /**< Signal Generation complete */
+    VP_LINE_EVID_MTR_CAD        = 0x0020, /**< Metering cadence */
+
+    VP_LINE_EVID_TONE_CAD       = 0x0040, /**< Tone Cadence complete */
+
+    VP_LINE_EVID_MTR_ROLLOVER   = 0x0080, /**< Metering count rollover */
+    VP_LINE_EVID_GEN_TIMER      = 0x0100, /**< Timer complete / canceled / error */
+    VP_LINE_EVID_USER           = 0x0200, /**< User-defined event */
+    VP_LINE_EVID_AUTO_LOOP_COND = 0x0400, /**< VP_OPTION_ID_AUTO_LOOP_COND event */
+
+    /* There are no device-specific process events */
+    VP_EVCAT_PROCESS_DEV_EVENTS = 0,
+
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_PROCESS_UNDEFINED =  (int)(~(VP_LINE_EVID_MTR_CMP        |
+                                          VP_LINE_EVID_MTR_ABORT      |
+                                          VP_LINE_EVID_CID_DATA       |
+                                          VP_LINE_EVID_RING_CAD       |
+                                          VP_LINE_EVID_SIGNAL_CMP     |
+                                          VP_LINE_EVID_MTR_CAD        |
+                                          VP_LINE_EVID_TONE_CAD       |
+                                          VP_LINE_EVID_MTR_ROLLOVER   |
+                                          VP_LINE_EVID_GEN_TIMER      |
+                                          VP_LINE_EVID_USER)),
+
+    VP_EVCAT_PROCESS_UNMASK_ALL =  (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_PROCESS_UNDEFINED),
+    VP_EVCAT_PROCESS_MASK_ALL   =  (int)(~VP_EVCAT_PROCESS_UNDEFINED),
+    VP_EVCAT_PRO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProcessEventType;
+
+typedef enum VpFxoEventType {
+    /* FXO API Event Types */
+    VP_LINE_EVID_RING_ON    = 0x0001, /**< Ringing detected on line */
+    VP_LINE_EVID_RING_OFF   = 0x0002, /**< Ringing previously detected has
+                                       * stopped
+                                       */
+    VP_LINE_EVID_LIU        = 0x0004, /**< Line In Use by adjacent line off
+                                       * hook
+                                       */
+    VP_LINE_EVID_LNIU       = 0x0008, /**< Line In Use by adjacent line on
+                                       * hook */
+    VP_LINE_EVID_FEED_DIS   = 0x0010, /**< Line feed disabled (or too low) */
+    VP_LINE_EVID_FEED_EN    = 0x0020, /**< Line feed enabled */
+    VP_LINE_EVID_DISCONNECT = 0x0040, /**< Line feed removed while loop close */
+    VP_LINE_EVID_RECONNECT  = 0x0080, /**< Line feed connected while loop
+                                       * close
+                                       */
+    VP_LINE_EVID_POLREV     = 0x0100, /**< Line polarity reversal has occurred*/
+    VP_LINE_EVID_POH        = 0x0200, /**< Parallel line off-hook */
+    VP_LINE_EVID_PNOH       = 0x0400, /**< Parallel line on-hook */
+
+    /* There are no device-specific FXO events */
+    VP_EVCAT_FXO_DEV_EVENTS = 0,
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_FXO_UNDEFINED =     (int)(~(VP_LINE_EVID_RING_ON        |
+                                         VP_LINE_EVID_RING_OFF       |
+                                         VP_LINE_EVID_LIU            |
+                                         VP_LINE_EVID_LNIU           |
+                                         VP_LINE_EVID_FEED_DIS       |
+                                         VP_LINE_EVID_FEED_EN        |
+                                         VP_LINE_EVID_DISCONNECT     |
+                                         VP_LINE_EVID_RECONNECT      |
+                                         VP_LINE_EVID_POLREV         |
+                                         VP_LINE_EVID_POH            |
+                                         VP_LINE_EVID_PNOH)),
+
+    VP_EVCAT_FXO_UNMASK_ALL =      (int)(VP_EVENT_MASK_ALL &
+                                     VP_EVCAT_FXO_UNDEFINED),
+    VP_EVCAT_FXO_MASK_ALL   =      (int)(~VP_EVCAT_FXO_UNDEFINED),
+    VP_EVCAT_FXO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpFxoEventType;
+
+typedef enum VpPacketEventType {
+    VP_LINE_EVID_US_PKT_RDY     = 0x0001, /**< Upstream Packet ready event */
+    VP_LINE_EVID_NEED_DS_PKT    = 0x0002, /**< Need Downstream Packet event */
+    VP_LINE_EVID_PKT_ERROR      = 0x0004, /**< Packet type error event */
+    VP_LINE_EVID_PKT_LOST       = 0x0008, /**< Packet loss event */
+    VP_LINE_EVID_RD_PKT_STATS   = 0x0010, /**< Read packet statistics complete*/
+    /* There are no device-specific packet events */
+    VP_EVCAT_PACKET_DEV_EVENTS  = 0,
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_PACKET_UNDEFINED =   (int)(~(VP_LINE_EVID_US_PKT_RDY       |
+                                          VP_LINE_EVID_NEED_DS_PKT      |
+                                          VP_LINE_EVID_PKT_ERROR        |
+                                          VP_LINE_EVID_PKT_LOST         |
+                                          VP_LINE_EVID_RD_PKT_STATS)),
+
+    VP_EVCAT_PACKET_UNMASK_ALL  =   (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_PACKET_UNDEFINED),
+    VP_EVCAT_PACKET_MASK_ALL    =  (int)(~VP_EVCAT_PACKET_UNDEFINED),
+    VP_EVCAT_PKT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPacketEventType;
+
+/* Enumerations for interpreting event data in the VpGetEvent() field */
+typedef enum VpBatFltEventDataType {
+    VP_BAT_FLT_NONE = 0x0,
+    VP_BAT_FLT_BAT2 = 0x1,
+    VP_BAT_FLT_BAT1 = 0x2,
+    VP_BAT_FLT_BAT3 = 0x4,
+    VP_BAT_FLT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatFltEventDataType;
+
+typedef enum VpRingCadEventDataType {
+    VP_RING_CAD_BREAK = 0,
+    VP_RING_CAD_MAKE  = 1,
+    VP_RING_CAD_DONE  = 2,
+    VP_RING_CAD_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpRingCadEventDataType;
+
+typedef enum VpCidDataEventDataType {
+    VP_CID_DATA_NEED_MORE_DATA = 0,
+    VP_CID_DATA_TX_DONE        = 1,
+    VP_CID_DATA_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCidDataEventDataType;
+
+typedef enum VpDigitType {
+    VP_DIG_1         = 0x01,
+    VP_DIG_2         = 0x02,
+    VP_DIG_3         = 0x03,
+    VP_DIG_4         = 0x04,
+    VP_DIG_5         = 0x05,
+    VP_DIG_6         = 0x06,
+    VP_DIG_7         = 0x07,
+    VP_DIG_8         = 0x08,
+    VP_DIG_9         = 0x09,
+    VP_DIG_10        = 0x0A,    /* pulse only */
+    VP_DIG_11        = 0x0B,    /* pulse only */
+    VP_DIG_12        = 0x0C,    /* pulse only */
+    VP_DIG_13        = 0x0D,    /* pulse only */
+    VP_DIG_14        = 0x0E,    /* pulse only */
+    VP_DIG_15        = 0x0F,    /* pulse only */
+    VP_DIG_ZERO      = 0x0A,    /* DTMF only */
+    VP_DIG_ASTER     = 0x0B,    /* DTMF only */
+    VP_DIG_POUND     = 0x0C,    /* DTMF only */
+    VP_DIG_A         = 0x0D,    /* DTMF only */
+    VP_DIG_B         = 0x0E,    /* DTMF only */
+    VP_DIG_C         = 0x0F,    /* DTMF only */
+    VP_DIG_D         = 0x00,    /* DTMF only */
+    VP_DIG_NONE      = 0xFF,
+    VP_DIG_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_DIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitType;
+
+/*
+ * Indicates which set of Dial Pulse Specifications were met that is generating
+ * the dial pulse event.
+ */
+typedef enum VpDialPulseParamType {
+    VP_DP_PARAM1 = 0,
+    VP_DP_PARAM2 = 1,
+    VP_DP_PARAM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDialPulseParamType;
+
+typedef enum VpDigitSenseType {
+    VP_DIG_SENSE_BREAK = 0x0000,
+    VP_DIG_SENSE_MAKE  = 0x0010,
+    VP_DIG_SENSE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitSenseType;
+
+typedef enum VpPolRevEventDataType {
+    VP_POLREV_NORMAL  = 0, /* Line detected Reverse-to-Normal Transition */
+    VP_POLREV_REVERSE = 1, /* Line detected Normal-to-Reverse Transition */
+    VP_POLREV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPolRevEventDataType;
+
+typedef enum VpSyncFltEventDataType {
+    VP_SYNC_MB_ERR        = 0x00,
+    VP_SYNC_SEQ_BAD_INST  = 0x81, /* Unknown instruction in sequence */
+    VP_SYNC_SEQ_BAD_BR    = 0x82, /* Sequencer encountered bad branch (either
+                                   * a forward branch or too many nesting levels */
+    VP_SYNC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSyncFltEventDataType;
+
+typedef enum VpGenTimerStatusType {
+    VP_GEN_TIMER_STATUS_CMP      = 0,
+    VP_GEN_TIMER_STATUS_CANCELED = 1,
+    VP_GEN_TIMER_STATUS_RESRC_NA = 2,
+    VP_GEN_TIMER_STATUS_UNKNOWN  = 3,
+    VP_GEN_TIMER_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGenTimerStatusType;
+
+typedef enum VpFlashEventDataType {
+    VP_FLASH_ONLY = 0,
+    VP_FLASH_AND_DIGIT1 = 1
+} VpFlashEventDataType;
+
+typedef uint16 VpHookPrequalEventDataType;
+#define VP_HOOK_PREQUAL_START   (0) /* Debounced off-hook detected, but offHookMin > 0 */
+#define VP_HOOK_PREQUAL_ABORT   (1) /* Debounced on-hook detected, but duration < offHookMin */
+
+
+/**
+ * Non-maskable events are (with reasons):
+ *
+ *   Boot Complete -- Cannot mask.  Masking events requires that the boot has
+ *                   been completed.
+ *   Read Option -- To modify mask interrupts requires that the current mask
+ *                  options can be read.  The only way to know the read option
+ *                  is ready is via an unmasked Read Option Complete event.
+ *   Device Init -- Fundamental event to know when device is initialized and
+ *                  remaining options/line configurations can be set.  There
+ *                  is no other standard "timeout" mechanism to know when the
+ *                  device has been initialized properly.
+ *   Line Init -- Fundamental event to know when a line is initialized and ready
+ *                to be setup with remaining user defined options.  There is no
+ *                other standard "timeout" mechanism to know when the line has
+ *                been initialized properly.
+ *   Events that have responses -- These events are non-maskable. If an event
+ *                that has a response is masked, and if the response is not
+ *                read, in case of CSLAC devices, it blocks response buffer.
+ *                In case of VCP class of devices, response mailbox is
+ *                locked up. If this is followed by another command that
+ *                requires the response mailbox, that command can't complete
+ *                execution since the response mailbox is busy. Now no more
+ *                commands can be issued because the previous command can't
+ *                complete.
+ */
+
+#define VP_API_NONMASK_FAULT_EVENTS         0x0000
+#define VP_API_NONMASK_SIGNALING_EVENTS     0x0000
+
+#define VP_API_NONMASK_RESPONSE_EVENTS      (VP_DEV_EVID_BOOT_CMP \
+                                           | VP_LINE_EVID_LLCMD_RX_CMP \
+                                           | VP_LINE_EVID_RD_OPTION \
+                                           | VP_LINE_EVID_RD_LOOP \
+                                           | VP_LINE_EVID_GAIN_CMP \
+                                           | VP_LINE_EVID_QUERY_CMP \
+                                           | VP_DEV_EVID_DEV_INIT_CMP \
+                                           | VP_LINE_EVID_LINE_INIT_CMP \
+                                           | VP_DEV_EVID_IO_ACCESS_CMP \
+                                           | VP_LINE_EVID_LINE_IO_RD_CMP \
+                                           | VP_LINE_EVID_SLAC_INIT_CMP)
+
+#define VP_API_NONMASK_TEST_EVENTS          (VP_LINE_EVID_TEST_CMP \
+                                           | VP_DEV_EVID_CHKSUM)
+
+#define VP_API_NONMASK_PROCESS_EVENTS       VP_LINE_EVID_GEN_TIMER
+#define VP_API_NONMASK_FXO_EVENTS           0x0000
+#define VP_API_NONMASK_PACKET_EVENTS        0x0000
+
+#endif /* VP_API_EVENT_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_fxo_params.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_fxo_params.h
new file mode 100755
index 0000000..40212eb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_fxo_params.h
@@ -0,0 +1,68 @@
+/** \file vp_api_fxo_params.h
+ * vp_api_fxo_params.h
+ *
+ * This file contains the approved system parameters for proper
+ * FXO operation on the reference designs
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_FXO_PARAMS_H
+#define VP_API_FXO_PARAMS_H
+
+#define VP_FXO_DTMF_ON_DEFAULT          0x0027  /* DTMF On = 195mS */
+#define VP_FXO_DTMF_OFF_DEFAULT         0x0028  /* DTMF Off = 200mS */
+#define VP_FXO_FLASH_HOOK_DEFAULT       0x0078  /* Flash Hook = 600mS */
+#define VP_FXO_PULSE_BREAK_DEFAULT      0x0C    /* Pulse Break = 60mS */
+#define VP_FXO_PULSE_MAKE_DEFAULT       0x08    /* Pulse Make = 40mS */
+#define VP_FXO_INTERDIG_DEFAULT         0x0028  /* Interdigit Period = 200mS */
+#define VP_FXO_RING_DET_MAX_DEFAULT     0xEB    /* Ring Period Max = 58.75mS */
+#define VP_FXO_RING_DET_MIN_DEFAULT     0x79    /* Ring Period Min = 30.25mS */
+#define VP_FXO_RING_DET_VOLT_DEFAULT    0x02    /* Ring Voltage Min = 38V */
+#define VP_FXO_DISC_DET_MIN_DEFAULT     0x03    /* Disconnect Det Min = 4.2V */
+#define VP_FXO_LIU_DET_THRESH_DEFAULT   0x26    /* Line-In-Use Det Threshold = 38V */
+
+/* In ms, time that FXO detector activity is ignored after a state change */
+#define VP_FXO_STATE_CHANGE_DEBOUNCE    (50)
+
+/* In ms, time that FXO detector activity is ignored after a ring trip */
+#define VP_FXO_RING_TRIP_DEBOUNCE       (200)
+
+/* In ms, time that FXO disconnect detector is debounced */
+#define VP_FXO_DISCONNECT_DEBOUNCE      (300)
+
+/* In ms, time that FXO will change to loop open if detecting disconnect */
+#define VP_FXO_DISC_TO_LOOP_OPEN        (5000)
+
+typedef enum vp_fxo_dialingProfileParams {
+    VP_FXO_DIALING_PROFILE_DTMF_ON_MSB = 6,
+    VP_FXO_DIALING_PROFILE_DTMF_ON_LSB = 7,
+    VP_FXO_DIALING_PROFILE_DTMF_OFF_MSB = 8,
+    VP_FXO_DIALING_PROFILE_DTMF_OFF_LSB = 9,
+    VP_FXO_DIALING_PROFILE_FLASH_HOOK_MSB = 10,
+    VP_FXO_DIALING_PROFILE_FLASH_HOOK_LSB = 11,
+    VP_FXO_DIALING_PROFILE_PULSE_BREAK = 12,
+    VP_FXO_DIALING_PROFILE_PULSE_MAKE = 13,
+    VP_FXO_DIALING_PROFILE_INTERDIGIT_MSB = 14,
+    VP_FXO_DIALING_PROFILE_INTERDIGIT_LSB = 15,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MAX = 16,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MIN = 17,
+    VP_FXO_DIALING_PROFILE_RING_VOLTAGE_MIN = 18,
+    VP_FXO_DIALING_PROFILE_DISC_VOLTAGE_MIN = 19,
+    VP_FXO_DIALING_PROFILE_LIU_THRESHOLD_MIN = 20,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MAX_ACT = 21,
+    VP_FXO_DIALING_PROFILE_DTMF_HIGH_LVL_MSB = 22,
+    VP_FXO_DIALING_PROFILE_DTMF_HIGH_LVL_LSB = 23,
+    VP_FXO_DIALING_PROFILE_DTMF_LOW_LVL_MSB = 24,
+    VP_FXO_DIALING_PROFILE_DTMF_LOW_LVL_LSB = 25,
+    VP_FXO_DIALING_PROFILE_POH_INT_TIME = 26,
+    VP_FXO_DIALING_PROFILE_POH_THRESHOLD = 27,
+    VP_FXO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} vp_fxo_dialingProfileParams;
+#endif
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_int.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_int.h
new file mode 100755
index 0000000..ef94233
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_int.h
@@ -0,0 +1,652 @@
+/** \file vp_api_int.h
+ * vp_api_int.h
+ *
+ * Header file for the API-II c files. This file contains the declarations
+ * and defintions required to implement the VTD specific VP-API. This file
+ * is used by VP-API internally. This file should not be included by the
+ * application.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_INT_H
+#define VP_API_INT_H
+
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "vp_api.h"
+#include "vp_api_option.h"
+
+#include "vp_debug.h"
+
+/******************************************************************************
+ *                              VP-API Defines                                *
+ ******************************************************************************/
+#define VP_ALL_LINES            0xFF  /**< Internal constant used to identify
+                                       * all lines
+                                       */
+#define VP_ALL_SLACS          0xFFFF  /**< Internal constant used to identify
+                                       * all SLACs
+                                       */
+
+/**< Profile types as defined by Profile Wizard */
+typedef enum VpProfileWizProfileType {
+    VP_PRFWZ_PROFILE_AC = 0x00,
+    VP_PRFWZ_PROFILE_DC = 0x01,
+    VP_PRFWZ_PROFILE_TONE = 0x02,
+    VP_PRFWZ_PROFILE_TONECAD = 0x03,
+    VP_PRFWZ_PROFILE_RING = 0x04,
+    VP_PRFWZ_PROFILE_CID_TYPE1 = 0x05,
+    VP_PRFWZ_PROFILE_CID_TYPE2 = 0x06,
+    VP_PRFWZ_PROFILE_METER = 0x07,
+    VP_PRFWZ_PROFILE_RINGCAD = 0x08,
+    VP_PRFWZ_PROFILE_TEST_CRITERIA = 0x09,
+    VP_PRFWZ_PROFILE_TEST_TOPOLOGY = 0x0A,
+    VP_PRFWZ_PROFILE_FXS_CTRL = 0x0B,
+    VP_PRFWZ_PROFILE_CAL = 0x0C,
+    VP_PRFWZ_PROFILE_METERING_GEN,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_HOOK_FLASH_DIG_GEN,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_DIAL_PULSE_DIG_GEN,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_DTMF_DIG_GEN,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_MSG_WAIT_PULSE_INT,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_LINE_CAL_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_FWD_DISC_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_POLREV_PULSE_INT,      /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_MOMENTARY_LOOP_OPEN_INT,   /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_TIP_OPEN_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_NONE,                  /**< Indicates that internal
+                                                 profile data is not valid */
+    VP_PRFWZ_PROFILE_880_CAL_DATA = 0xFC,
+    VP_PRFWZ_PROFILE_890_CAL_DATA = 0xFD,
+
+    VP_PRFWZ_PROFILE_FXO_CONFIG = 0xFE,
+    VP_PRFWZ_PROFILE_DEVICE = 0xFF,
+    VP_PRFWZ_PROFILE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req.*/
+} VpProfileWizProfileType;
+
+typedef enum VpProfileWizCustomStateType {
+    VP_PRFWZ_CUSTOM_ST_STANDBY = 0x00,
+    VP_PRFWZ_CUSTOM_ST_ACTIVE = 0x02,
+    VP_PRFWZ_CUSTOM_ST_ACTIVE_PR = 0x03,
+    VP_PRFWZ_CUSTOM_ST_TIP_OPEN = 0x04,
+    VP_PRFWZ_CUSTOM_ST_OHT = 0x06,
+    VP_PRFWZ_CUSTOM_ST_OHT_PR = 0x07,
+    VP_PRFWZ_CUSTOM_ST_DISCONNECT = 0x08,
+    VP_PRFWZ_CUSTOM_ST_RINGING = 0x09,
+    VP_PRFWZ_CUSTOM_ST_DET_MAP = 0xFF,
+    VP_PRFWZ_CUSTOM_ST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req.*/
+} VpProfileWizCustomStateType;
+
+/** These locations are common to all profiles used in the API */
+typedef enum VpProfileHeaderFieldType {
+    VP_PROFILE_TYPE_MSB = 0,
+    VP_PROFILE_TYPE_LSB = 1,
+    VP_PROFILE_INDEX = 2,
+    VP_PROFILE_LENGTH = 3,
+    VP_PROFILE_VERSION = 4,
+    VP_PROFILE_MPI_LEN = 5,
+    VP_PROFILE_DATA_START = 6,
+    VP_PROFILE_HDR_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProfileHeaderFieldType;
+
+/* Define the Ringing Type (balanced/unbalanced) offset from end of MPI data */
+#define VP_PROFILE_RING_TYPE_OFFSET     1
+
+/** These are the locations of parameters in version 01 ringing profiles */
+typedef enum VpRingProfileFieldType {
+    VP_RING_PROFILE_RING_TRIP   = 18,
+    VP_RING_PROFILE_CURRENT_LIM = 19,
+    VP_RING_PROFILE_MAX_RING_V  = 20,
+    VP_RING_PROFILE_TRACK_MODE  = 21,
+    VP_RING_PROFILE_ENUM_SIZE  =  FORCE_STANDARD_C_ENUM_SIZE /* Portability Req */
+} VpRingProfileFieldType;
+
+/** These are the locations of parameters in version 01 DC profiles */
+typedef enum VpDcProfileFieldType {
+    VP_DC_PROFILE_THRESHOLDS =  9,
+    VP_DC_PROFILE_DEBOUNCES  =  10,
+    VP_DC_PROFILE_FLOOR_V    =  11,
+    VP_DC_PROFILE_HOOK_HYST  =  12,
+    VP_DC_PROFILE_ENUM_SIZE  =  FORCE_STANDARD_C_ENUM_SIZE /* Portability Req */
+} VpDcProfileFieldType;
+
+typedef enum VpCidProfileFieldType {
+    /*
+     * These parameters are the absolute locations of the specified value in
+     * the CID profile
+     */
+    VP_CID_PROFILE_FSK_PARAM_LEN = 6,
+    VP_CID_PROFILE_FSK_PARAM_CMD = 7,
+    VP_CID_PRFT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCidProfileFieldType;
+
+/*
+ * These parameters are offset from the end of the FSK data to the value
+ * specified
+ */
+#define VP_CID_PROFILE_CHECKSUM_OFFSET_MSB      (1)
+#define VP_CID_PROFILE_CHECKSUM_OFFSET_LSB      (2)
+#define VP_CID_PROFILE_LENGTH_OF_ELEMENTS_MSB   (3)
+#define VP_CID_PROFILE_LENGTH_OF_ELEMENTS_LSB   (4)
+#define VP_CID_PROFILE_START_OF_ELEMENTS_MSB    (5)
+#define VP_CID_PROFILE_START_OF_ELEMENTS_LSB    (6)
+
+/** These locations are for Tone and Ringing Cadence (Sequencer) profiles */
+#define VP_PROFILE_TYPE_SEQUENCER_COUNT_MSB (6)
+#define VP_PROFILE_TYPE_SEQUENCER_COUNT_LSB (7)
+#define VP_PROFILE_TYPE_SEQUENCER_START     (8)
+
+/** These locations are for Calibration profiles */
+#define VP_CAL_PROFILE_NUM_ENTRIES  (6)
+#define VP_CAL_PROFILE_FIRST_ENTRY  (8)
+
+/******************************************************************************
+ *                        API Specific common FUNCTION PROTOTYPES             *
+ ******************************************************************************/
+void
+VpImplementNonMaskEvents(
+    VpOptionEventMaskType *pLineEventsMask,
+    VpOptionEventMaskType *pDevEventsMask);
+
+VpStatusType
+VpImplementDefaultSettings(
+    VpDevCtxType *pDevCtx,
+    VpLineCtxType *pLineCtx);
+
+EXTERN int
+VpGetProfileIndex (
+    const VpProfilePtrType pProfile);
+
+EXTERN bool
+VpVerifyProfileType(
+    VpProfileType type,
+    VpProfilePtrType pProfile);
+
+EXTERN bool
+VpIsDigit(
+    VpDigitType digit);
+
+#if (defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES))
+EXTERN VpStatusType
+VpCSLACSetDTMFGenValues(
+    uint8 *sigGenABParams,
+    VpDigitType digit);
+
+EXTERN bool
+VpCSLACHookMaskEnabled(
+    uint16 fxsTimers[VP_LINE_TIMER_LAST]);
+#endif
+
+/******************************************************************************
+ *                        VCP Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_VCP_SERIES)
+VpStatusType
+VpMakeVcpDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpVcpDeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVcpDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpVcpDeviceObjectType *pDevObj);
+
+#endif /* VP_CC_VCP_SERIES */
+
+/******************************************************************************
+ *                        VCP2 Specific FUNCTION PROTOTYPES                   *
+ ******************************************************************************/
+#if defined (VP_CC_VCP2_SERIES)
+VpStatusType
+Vcp2MakeDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpVcp2DeviceObjectType *pDevObj);
+
+VpStatusType
+Vcp2MakeDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpVcp2DeviceObjectType *pDevObj);
+
+EXTERN bool
+Vcp2ReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN void
+Vcp2SetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+#endif /* VP_CC_VCP2_SERIES */
+/******************************************************************************
+ *                        MELT Specific FUNCTION PROTOTYPES                   *
+ ******************************************************************************/
+#if defined (VP_CC_MELT_SERIES)
+
+VpStatusType
+MeltMakeDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpMeltDeviceObjectType *pDevObj);
+
+VpStatusType
+MeltMakeDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpMeltDeviceObjectType *pDevObj);
+
+EXTERN bool
+MeltReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN void
+MeltSetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+#endif /* VP_CC_MELT_SERIES */
+
+/******************************************************************************
+ *                        Kernel Specific FUNCTION PROTOTYPES                 *
+ ******************************************************************************/
+#if defined (VP_CC_KWRAP)
+  #include "vp_kernel.h"
+#endif /* VP_CC_KWRAP */
+
+
+/******************************************************************************
+ *                        790 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_790_SERIES)
+
+#ifndef VP790_EC_CH1
+  #define VP790_EC_CH1    0x01
+  #define VP790_EC_CH2    0x02
+  #define VP790_EC_CH3    0x04
+  #define VP790_EC_CH4    0x08
+#endif
+
+VpStatusType
+VpMakeVp790DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp790DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp790DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp790DeviceObjectType *pDevObj);
+
+void
+Vp790MuteChannel(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+bool
+Vp790FSKGeneratorReady(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+Vp790CliGetEncodedByte(
+    VpLineCtxType *pLineCtx,
+    uint8 *pByte);
+
+VpStatusType
+Vp790CtrlSetCliTone(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+void
+Vp790CtrlSetFSKGen(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    uint8 data);
+#endif /* VP_CC_790_SERIES */
+
+/******************************************************************************
+ *                        792 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+
+#if defined (VP_CC_792_SERIES)
+VpStatusType
+Vp792MakeDeviceObject(
+    VpDevCtxType            *pDevCtx,
+    Vp792DeviceObjectType   *pDevObj);
+
+VpStatusType
+Vp792MakeDeviceCtx(
+    VpDevCtxType            *pDevCtx,
+    Vp792DeviceObjectType   *pDevObj);
+
+#ifdef VP_CC_792_GROUP
+bool
+Vp792GroupGetEvent(
+    VpDevCtxType *pDevCtx,
+    VpEventType *pEvent);
+#endif
+#endif /* VP_CC_792_SERIES */
+
+/******************************************************************************
+ *                        880 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_880_SERIES)
+
+#ifndef VP880_EC_CH1
+  #define VP880_EC_CH1                0x01
+  #define VP880_EC_CH2                0x02
+#endif
+
+#ifndef VP880_WIDEBAND_MODE
+  #define VP880_WIDEBAND_MODE         0x20
+#endif
+
+VpStatusType
+VpMakeVp880DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp880DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp880DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp880DeviceObjectType *pDevObj);
+
+void
+Vp880MuteChannel(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+#if defined (VP_CSLAC_SEQ_EN) && defined (VP880_FXS_SUPPORT)
+bool
+Vp880FSKGeneratorReady(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+Vp880CliGetEncodedByte(
+    VpLineCtxType *pLineCtx,
+    uint8 *pByte);
+
+VpStatusType
+Vp880CtrlSetCliTone(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+bool
+Vp880CtrlSetFSKGen(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    uint8 data);
+#endif
+
+VpStatusType
+Vp880SetDTMFGenerators(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    VpDigitType digit);
+
+VpStatusType
+Vp880SetLineStateInt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp880SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+void
+Vp880LLSetSysState(
+    VpDeviceIdType deviceId,
+    VpLineCtxType *pLineCtx,
+    uint8 lineState,
+    bool writeToDevice);
+#endif /* VP_CC_880_SERIES */
+
+
+/******************************************************************************
+ *                        890 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_890_SERIES)
+  #include "vp890_api_int.h"
+#endif /* VP_CC_890_SERIES */
+
+
+/******************************************************************************
+ *                        580 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+VpMakeVp580DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp580DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp580DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp580DeviceObjectType *pDevObj);
+
+#endif /* VP_CC_580_SERIES */
+
+/* Functions used internal to the API -- device dependant */
+#if defined (VP_CC_790_SERIES) || defined (VP_CC_880_SERIES) \
+ || defined (VP_CC_580_SERIES) || defined (VP_CC_890_SERIES)
+
+/* Converts ms to units of API_TICKRATE */
+#define MS_TO_TICKRATE(MS, API_TICKRATE)  \
+    ((uint16)(((((uint32)MS*256*2)/API_TICKRATE)+1)/2))
+#define TICKS_TO_MS(TICKS, API_TICKRATE)  \
+    (uint16) (((uint32)API_TICKRATE * (uint32)TICKS) / 256)
+#define MS_TO_TICKS_ROUND_UP(MS, API_TICKRATE)  \
+    ((uint16)(((((uint32)MS*256*2 + API_TICKRATE - 1)/API_TICKRATE)+1)/2))
+/* Gives frequency in units of 0.3662109375 Hz for signal generators */
+#define TICKRATE_TO_HZ(API_TICKRATE)  \
+    ((uint16)((uint32)(0x80000000 / API_TICKRATE) / 0x0C00))
+
+#define NO_DATA     0x00
+#define NOOP_CMD    0x06  /**< Standard No operation comnmand for all devices */
+
+#define MAX_CFAIL_TEST      10
+#define CFAIL_TEST_INTERVAL 10
+
+/**< CallerID Profile Data structure definitions */
+#define VP_FSK_MARK_SIGNAL     0xFF
+#define VP_FSK_CHAN_SEIZURE    0x55
+#define VP_FSK_DATA            0x11 /* Anything NOT Mark or C.S is ok */
+#define VP_FSK_NONE            0x00 /* When FSK Generator is not being used */
+
+typedef enum VpApiElementsType {
+    VP_CLI_NULL = 0,
+    VP_CLI_POLREV = 0x01,           /**< No Parameters */
+    VP_CLI_MUTEON = 0x02,           /**< No Parameters */
+    VP_CLI_MUTEOFF = 0x03,          /**< No Parameters */
+    VP_CLI_ALERTTONE = 0x04,        /**< Duration/Tone definition parameters */
+    VP_CLI_ALERTTONE2 = 0x05,       /**< Internal Alert Tone indicator */
+    VP_CLI_SILENCE = 0x06,          /**< Duration Parameter */
+    VP_CLI_SILENCE_MASKHOOK = 0x07, /**< Duration/Masked-hook length parameters */
+    VP_CLI_DETECT = 0x08,           /**< Tone and Timeout parameters */
+    VP_CLI_CHANSEIZURE = 0x09,      /**< Duration Parameter */
+    VP_CLI_MARKSIGNAL = 0x0A,       /**< Duration Parameter */
+    VP_CLI_MESSAGE = 0x0B,          /**< No Parameters */
+    VP_CLI_USER_DEFINED = 0x0C,     /**< Not supported in API-II */
+    VP_CLI_EOT = 0x0D,              /**< No Parameters */
+    VP_CLI_DTMF_MESSAGE = 0x0E,     /**< Message data to be sent in DTMF format */
+    VP_CLI_ELM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpApiElementsType;
+
+/* VP API Function Prototypes - Not associated with a function pointer */
+#if defined(VP_CC_790_SERIES) || defined(VP_CC_880_SERIES) \
+ || defined(VP_CC_890_SERIES) || defined(VP_CC_580_SERIES)
+
+#ifdef VP_CC_890_SERIES
+VpStatusType
+Vp890InitDevicePcnRcn(
+    Vp890DeviceObjectType   *pDevObj,
+    VpDeviceIdType          deviceId);
+#endif
+
+#ifdef VP_CC_880_SERIES
+VpStatusType
+Vp880InitDevicePcnRcn(
+    Vp880DeviceObjectType   *pDevObj,
+    VpDeviceIdType          deviceId);
+#endif
+
+bool
+VpIsLowPowerTermType(
+    VpTermType termType);
+
+void
+VpCSLACClearMPIBuffer(
+    VpDeviceIdType deviceId);
+
+bool
+VpCSLACIsProfileValid(
+    VpProfileType       profType,
+    int16               tableSize,
+    uint16              profEntry,
+    VpProfilePtrType    *pProfTable,
+    VpProfilePtrType    pProfileInput,
+    VpProfilePtrType    *pProfileRslt);
+
+bool
+VpCSLACSetTimer(
+    uint16 *pTimer,
+    uint16 newValue);
+
+#endif
+
+int16
+VpConvertToInt16(
+    uint8 *dataPtr);
+
+int32
+VpConvertToInt32(
+    uint8 *dataPtr);
+
+#if defined(VP_CC_880_SERIES) || defined(VP_CC_890_SERIES)
+VpStatusType
+VpCSLACSetAbsGain(
+    VpLineCtxType *pLineCtx,
+    VpOptionAbsGainType *gains);
+
+#if defined(VP880_FXS_SUPPORT) || defined(VP890_FXS_SUPPORT)
+/* Function only used for VP_LINE_HOWLER and VP_LINE_HOWLER_POLREV states */
+#ifdef VP_HIGH_GAIN_MODE_SUPPORTED
+void
+VpCLSACHighGainMode(
+    VpLineCtxType *pLineCtx,
+    bool highGainMode);
+
+VpStatusType
+VpCSLACHowlerStateMgmt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType fromState,
+    VpLineStateType toState,
+    VpLineStateType statePriorToHowler);    /**< Used only when exiting Howler State */
+#endif
+
+bool
+VpCSLACIsSupportedFxsState(
+    VpDeviceType deviceType,
+    VpLineStateType state);
+#endif  /* defined(VP880_FXS_SUPPORT) || defined(VP890_FXS_SUPPORT) */
+#endif  /* defined(VP_CC_880_SERIES) || defined(VP_CC_890_SERIES)   */
+
+VpProfileCadencerStateTypes
+ConvertApiState2PrfWizState(
+    const VpLineStateType state);
+
+VpLineStateType
+ConvertPrfWizState2ApiState(
+    uint8 state);
+
+void
+InitTimerVars(
+    VpLineCtxType *pLineCtx);
+
+bool
+VpUpdateDP(
+    uint16 tickRate,
+    VpOptionPulseType *pPulseSpecs,
+    VpDialPulseDetectType *pDpStruct,
+    VpOptionEventMaskType *pLineEvents);
+
+void
+VpInitDP(
+    VpDialPulseDetectType *pDpStruct);
+
+VpStatusType
+VpCSLACGetLineStatus(
+    VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+#if !defined(VP_REDUCED_API_IF)
+VpStatusType
+VpCSLACClearResults(
+    VpDevCtxType *pDevCtx);
+#endif
+
+VpStatusType
+VpCSLACDtmfDigitDetected(
+    VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+VpLineStateType
+VpGetReverseState(
+    VpLineStateType currentState);
+
+void
+VpCSLACSetVas(
+    uint8 *dcFeed,
+    uint16 vasValue);
+
+#ifdef CSLAC_GAIN_RELATIVE
+void
+VpConvertFixed2Csd(
+    uint16 fixed,
+    uint8 *csdBuf);
+
+uint16
+VpConvertCsd2Fixed(
+    uint8 *csdBuf);
+#endif
+#endif
+
+#if defined (VP_CC_790_SERIES)
+VpStatusType
+Vp790SetLineStateInt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp790SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+#endif
+
+
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+Vp580SetLineStateInt(
+
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp580SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+#endif
+
+uint16
+VpComputeSquareRoot(
+    uint32 number);
+
+#endif /* VP_API_INT_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_option.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_option.h
new file mode 100755
index 0000000..a24502b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_option.h
@@ -0,0 +1,399 @@
+/** \file vp_api_option.h
+ * vp_api_option.h
+ *
+ * This file contains declaration associated with VP-API Options.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_OPTION
+#define VP_API_OPTION
+
+#include "vp_api_types.h"
+#include "vp_api_cfg.h"
+#include "vp_api_event.h"
+
+/* Option IDs.  (See Options chapter in VP-API-2 Reference Guide.)
+ * Line-specific option IDs begin with "VP_OPTION_ID_".  Device-specific
+ * option IDs begin with "VP_DEVICE_OPTION_ID_".  When new option IDs are added,
+ * the VpOptionValueType struct (below) must be updated accordingly.
+ */
+typedef enum VpOptionIdType {
+    VP_DEVICE_OPTION_ID_PULSE            = 0x00,
+    VP_DEVICE_OPTION_ID_CRITICAL_FLT     = 0x01,
+    VP_OPTION_ID_ZERO_CROSS              = 0x02,
+    VP_DEVICE_OPTION_ID_RAMP2STBY        = 0x03,
+    VP_OPTION_ID_PULSE_MODE              = 0x04,
+    VP_OPTION_ID_TIMESLOT                = 0x05,
+    VP_OPTION_ID_CODEC                   = 0x06,
+    VP_OPTION_ID_PCM_HWY                 = 0x07,
+    VP_OPTION_ID_LOOPBACK                = 0x08,
+    VP_OPTION_ID_LINE_STATE              = 0x09,
+    VP_OPTION_ID_EVENT_MASK              = 0x0A,
+    VP_OPTION_ID_RESERVED_1              = 0x0B,
+    VP_OPTION_ID_RING_CNTRL              = 0x0C,
+    VP_OPTION_ID_RESERVED_2              = 0x0D,
+    VP_OPTION_ID_DTMF_MODE               = 0x0E,
+    VP_DEVICE_OPTION_ID_DEVICE_IO        = 0x0F,
+    VP_OPTION_ID_RESERVED_EVENT_MASK_VCP = 0x10,
+    VP_OPTION_ID_PCM_TXRX_CNTRL          = 0x11,
+    VP_DEVICE_OPTION_ID_PULSE2           = 0x12,
+    VP_OPTION_ID_LINE_IO_CFG             = 0x13,
+    VP_DEVICE_OPTION_ID_DEV_IO_CFG       = 0x14,
+    VP_OPTION_ID_DTMF_SPEC               = 0x15,
+    VP_DEVICE_OPTION_ID_PARK_MODE        = 0x16,
+    VP_OPTION_ID_DCFEED_SLOPE            = 0x17,
+    VP_OPTION_ID_SWITCHER_CTRL           = 0x18,
+    VP_OPTION_ID_HOOK_DETECT_MODE        = 0x19,
+    VP_OPTION_ID_AUTO_LOOP_COND          = 0x1A,
+
+    /* New option values may be added in this gap in the future. */
+    VP_OPTION_ID_PULSE                   = 0x24,
+    VP_OPTION_ID_DEBUG_SELECT            = 0x25,
+    VP_OPTION_ID_ABS_GAIN                = 0x26,
+    VP_DEVICE_OPTION_ID_PCM_SIG_CTL      = 0x27,
+    VP_OPTION_ID_LINESTATE_CTL_MODE      = 0x28,
+
+    VP_NUM_OPTION_IDS
+} VpOptionIdType;
+
+/** Parameters for dial pulse, flash, and on-hook */
+typedef struct VpOptionPulseType {
+    uint16 breakMin;        /**< Minimum pulse break time (in 125uS) */
+    uint16 breakMax;        /**< Maximum pulse break time (in 125uS) */
+    uint16 makeMin;         /**< Minimum pulse make time (in 125uS) */
+    uint16 makeMax;         /**< Maximum pulse make time (in 125uS) */
+    uint16 interDigitMin;   /**< Minimum pulse interdigit time (in 125uS) */
+    uint16 flashMin;        /**< Minimum flash break time (in 125uS) */
+    uint16 flashMax;        /**< Maximum flash break time (in 125uS) */
+#ifdef EXTENDED_FLASH_HOOK
+    uint16 onHookMin;       /**< Minimum on-hook time (in 125uS) */
+#endif
+} VpOptionPulseType;
+
+typedef struct VpOptionLinePulseType {
+    uint16 breakMin;        /**< Minimum pulse break time (in 125uS) */
+    uint16 breakMax;        /**< Maximum pulse break time (in 125uS) */
+    uint16 makeMin;         /**< Minimum pulse make time (in 125uS) */
+    uint16 makeMax;         /**< Maximum pulse make time (in 125uS) */
+    uint16 interDigitMin;   /**< Minimum pulse interdigit time (in 125uS) */
+    uint16 flashMin;        /**< Minimum flash break time (in 125uS) */
+    uint16 flashMax;        /**< Maximum flash break time (in 125uS) */
+    uint16 onHookMin;       /**< Minimum on-hook time (in 125uS) */
+    uint16 offHookMin;      /**< Minimum off-hook time (in 125uS) */
+} VpOptionLinePulseType;
+
+/** Method for line control when critical faults are detected */
+typedef struct VpOptionCriticalFltType {
+    /**< The line is set to disconnect when the specified fault is active and
+     * the "En" bit is set TRUE
+     */
+    bool acFltDiscEn;           /**< AC fault detected */
+    bool dcFltDiscEn;           /**< DC fault detected */
+    bool thermFltDiscEn;        /**< Thermal fault detected */
+} VpOptionCriticalFltType;
+
+/** Method for zero-cross control */
+typedef enum VpOptionZeroCrossType {
+    VP_OPTION_ZC_M4B  = 0, /**< Zero-Cross On - Make before break */
+    VP_OPTION_ZC_B4M  = 1, /**< Zero-Cross On - Break before make */
+    VP_OPTION_ZC_NONE = 2, /**< Turn Zero-Cross control off */
+    VP_OPTION_ZC_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_OPTION_ZC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpOptionZeroCrossType;
+
+/** Dial Pulse decode enable/disable */
+typedef enum VpOptionPulseModeType {
+    VP_OPTION_PULSE_DECODE_OFF      = 0, /**< Disable Pulse Decode */
+    VP_OPTION_PULSE_DECODE_ON       = 1, /**< Enable Pulse Decode */
+    VP_OPTION_PULSE_DECODE_BRIDGING = 2, /**< Enable Pulse Decode (With Bridging) */
+    VP_OPTION_PULSE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPulseModeType;
+
+/** Transmit/Receive Timeslot setting (timeslot and control) */
+typedef struct VpOptionTimeslotType {
+    uint8 tx;   /**< 8-bit TX timeslot */
+    uint8 rx;   /**< 8-bit RX timeslot */
+} VpOptionTimeslotType;
+
+typedef enum VpOptionCodecType {
+    VP_OPTION_ALAW     = 0, /**< Select G.711 A-Law PCM encoding */
+    VP_OPTION_MLAW     = 1, /**< Select G.711 Mu-Law PCM encoding */
+    VP_OPTION_LINEAR   = 2, /**< Select Linear PCM encoding */
+    VP_OPTION_WIDEBAND = 3, /**< Select Wideband PCM encoding */
+    VP_NUM_OPTION_CODEC_TYPE_IDS,
+    VP_OPTION_CODEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionCodecType;
+
+/** PCM Highway Selection (B valid on select devices only) */
+typedef enum VpOptionPcmHwyType {
+    VP_OPTION_HWY_A          = 0, /**< Select the 'A' PCM Highway */
+    VP_OPTION_HWY_B          = 1, /**< Select the 'B' PCM Highway */
+    VP_OPTION_HWY_TX_A_RX_B  = 2, /**< Transmit on Highway A, receive on B */
+    VP_OPTION_HWY_TX_B_RX_A  = 3, /**< Transmit on Highway A, receive on A */
+    VP_OPTION_HWY_TX_AB_RX_A = 4, /**< Transmit on Highway A and B, receive on A */
+    VP_OPTION_HWY_TX_AB_RX_B = 5, /**< Transmit on Highway A and B, receive on B */
+    VP_OPTION_HWY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPcmHwyType;
+
+/** Loopback option selection */
+typedef enum VpOptionLoopbackType {
+    VP_OPTION_LB_OFF      = 0, /**< All loopbacks off */
+
+    /* Following loopback options are supported for CSLAC and VCP only */
+    VP_OPTION_LB_TIMESLOT = 1, /**< Perform a timeslot loopback */
+    VP_OPTION_LB_DIGITAL  = 2, /**< Perform a full-digital loopback */
+    VP_OPTION_LB_CHANNELS = 3, /**< Connects FXO to FXS line on same device */
+
+    VP_NUM_LB_OPTIONS,
+    VP_OPTION_LB_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionLoopbackType;
+
+/** Active Line State battery supply selection */
+typedef enum VpOptionBatType {
+    VP_OPTION_BAT_AUTO  = 0, /**< Automatic Batery selection */
+    VP_OPTION_BAT_HIGH  = 1, /**< Use High Batery */
+    VP_OPTION_BAT_LOW   = 2, /**< Use Low Batery */
+    VP_OPTION_BAT_BOOST = 3, /**< Include Positive Batery */
+    VP_NUM_OPTION_BAT_IDS,
+    VP_OPTION_BAT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionBatType;
+
+/** Active Line State battery supply selection */
+typedef struct VpOptionLineStateType {
+    bool battRev;       /**< Smooth/Abrupt Battery Reversal (TRUE = abrupt) */
+
+    VpOptionBatType bat;    /**< Battery selection for Active line state */
+} VpOptionLineStateType;
+
+/** Ring control option */
+typedef enum VpLineStateType {
+
+    /* FXS */
+    VP_LINE_STANDBY         = 0x00, /**< Low power line feed state */
+    VP_LINE_TIP_OPEN        = 0x01, /**< Tip open circuit state */
+    VP_LINE_ACTIVE          = 0x02, /**< Line Feed w/out VF */
+    VP_LINE_ACTIVE_POLREV   = 0x03, /**< Polarity Reversal Line Feed w/out VF */
+    VP_LINE_TALK            = 0x04, /**< Normal off-hook Active State; Voice Enabled */
+    VP_LINE_TALK_POLREV     = 0x05, /**< Normal Active with reverse polarity; Voice Enabled */
+    VP_LINE_OHT             = 0x06, /**< On-Hook tranmission state */
+    VP_LINE_OHT_POLREV      = 0x07, /**< Polarity Reversal On-Hook tranmission state */
+    VP_LINE_DISCONNECT      = 0x08, /**< Denial of service */
+    VP_LINE_RINGING         = 0x09, /**< Ringing state */
+    VP_LINE_RINGING_POLREV  = 0x0A, /**< Ringing w/Polarity Reversal */
+    VP_LINE_STANDBY_POLREV  = 0x10, /**< Low power polrev line feed state */
+    VP_LINE_PARK            = 0x11, /**< Park mode */
+    VP_LINE_RING_OPEN       = 0x12, /**< Ring open */
+    VP_LINE_HOWLER          = 0x13, /**< Howler */
+    VP_LINE_TESTING         = 0x14, /**< Testing */
+    VP_LINE_DISABLED        = 0x15, /**< Disabled */
+    VP_LINE_NULLFEED        = 0x16, /**< Null-feed */
+    VP_LINE_HOWLER_PCM      = 0x17, /**< Howler with PCM highway enabled */
+    VP_LINE_HOWLER_POLREV   = 0x18, /**< Howler with Polarity Reversal */
+
+    /* FXO */
+    VP_LINE_FXO_OHT,        /**< FXO Line providing Loop Open w/VF */
+    VP_LINE_FXO_LOOP_OPEN,  /**< FXO Line providing Loop Open w/out VF */
+    VP_LINE_FXO_LOOP_CLOSE, /**< FXO Line providing Loop Close w/out VF */
+    VP_LINE_FXO_TALK,       /**< FXO Line providing Loop Close w/VF */
+    VP_LINE_FXO_RING_GND,   /**< FXO Line providing Ring Ground (GS only)*/
+
+    VP_NUM_LINE_STATES,
+    VP_LINE_STATE_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_LINE_STATE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLineStateType;
+
+typedef struct VpOptionRingControlType {
+    VpOptionZeroCrossType zeroCross;    /**< LCAS zero cross control */
+
+    uint16 ringExitDbncDur; /**< Ringing Exit Debounce Duration; Used during end
+                             * of ON periods of ringing cadences; 125uS
+                             * resolution
+                             */
+
+    VpLineStateType ringTripExitSt; /**< State to automatically switch to upon
+                                     * ring trip
+                                     */
+}  VpOptionRingControlType;
+
+/** DTMF detection option */
+typedef enum VpOptionDtmfModeControlType {
+    VP_OPTION_DTMF_DECODE_OFF = 0, /**< Disable DTMF Digit Decode */
+    VP_OPTION_DTMF_DECODE_ON  = 1, /**< Enable DTMF Digit  Decode */
+    VP_OPTION_DTMF_GET_STATUS = 2, /**< Do not change anything; Just get the DTMF status  */
+    VP_NUM_OPTION_DTMF_IDS,
+    VP_OPTION_DTMF_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionDtmfModeControlType;
+
+/* Device I/O Option related definitions */
+typedef enum VpDeviceIoDirectionType {
+    VP_IO_INPUT_PIN  = 0, /* Configure GPIO pin as input pin */
+    VP_IO_OUTPUT_PIN = 1, /* Configure GPIO pin as output pin */
+    VP_IO_DIR_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDeviceIoDirectionType;
+
+typedef enum VpDeviceOutputPinType {
+    VP_OUTPUT_DRIVEN_PIN = 0, /* Configure as TTL/CMOS output pin */
+    VP_OUTPUT_OPEN_PIN   = 1, /* Configure as open collector/drain output pin */
+    VP_OUTPUT_TYPE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDeviceOutputPinType;
+
+typedef struct VpOptionDeviceIoType {
+    uint32 directionPins_31_0;      /* Device specific IO pin direction
+                                     * (Pins 0 - 31) */
+    uint32 directionPins_63_32;     /* Device specific IO pin direction
+                                     * (Pins 32 - 63) */
+    uint32 outputTypePins_31_0;     /* Output pin type (Pins 0 - 31) */
+    uint32 outputTypePins_63_32;    /* Output pin type (Pins 32 - 63) */
+} VpOptionDeviceIoType;
+
+/* Definition for line I/O config option */
+typedef struct VpOptionLineIoConfigType {
+    uint8 direction;
+    uint8 outputType;
+} VpOptionLineIoConfigType;
+
+/* Definition for device I/O config option */
+typedef struct VpOptionDeviceIoConfigType {
+    VpOptionLineIoConfigType lineIoConfig[VP_MAX_LINES_PER_DEVICE];
+} VpOptionDeviceIoConfigType;
+
+typedef enum VpOptionPcmTxRxCntrlType {
+    VP_OPTION_PCM_BOTH      = 0, /* Enable both PCM transmit and receive paths */
+    VP_OPTION_PCM_RX_ONLY   = 1, /* Enable PCM receive path only */
+    VP_OPTION_PCM_TX_ONLY   = 2, /* Enable PCM transmit path only */
+    VP_OPTION_PCM_ALWAYS_ON = 3, /* Prevents disabling of PCM path */
+    VP_PCM_TXRX_CNTRL_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_PCM_TXRX_CNTRL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPcmTxRxCntrlType;
+
+/** Direction Specification */
+typedef enum VpDirectionType {
+    VP_DIRECTION_DS,
+    VP_DIRECTION_US,
+    VP_DIRECTION_INVALID,   /**< Used by the API to determine if the direction
+                             * field is valid */
+    VP_DIRECTION_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDirectionType;
+
+#define VP_LINE_FLAG_BYTES ((VP_MAX_LINES_PER_DEVICE + 7) / 8)
+
+/** DTMF detection option control */
+typedef struct VpOptionDtmfModeType {
+    VpOptionDtmfModeControlType dtmfControlMode; /**< DTMF detection
+                                                  * Enable/Disable */
+    VpDirectionType direction;                  /**< Detection direction */
+    uint32 dtmfDetectionSetting;                /**< Indicates the DTMF
+                                                 *   detection setting for first
+                                                 *    32 lines */
+    uint8 dtmfResourcesRemaining;               /**< DTMF decoder resources
+                                                 *   remaining */
+    uint8 dtmfDetectionEnabled[VP_LINE_FLAG_BYTES];
+                                                /**< DTMF detection setting for
+                                                 *   lines 7-0, 15-8, etc. */
+} VpOptionDtmfModeType;
+
+/** Regional DTMF Specs */
+typedef enum VpOptionDtmfSpecType {
+    VP_OPTION_DTMF_SPEC_ATT  = 0, /* Q.24 AT&T */
+    VP_OPTION_DTMF_SPEC_NTT  = 1, /* Q.24 NTT */
+    VP_OPTION_DTMF_SPEC_AUS  = 2, /* Q.24 Australian */
+    VP_OPTION_DTMF_SPEC_BRZL = 3, /* Q.24 Brazilian */
+    VP_OPTION_DTMF_SPEC_ETSI = 4, /* ETSI ES 201 235-3 v1.3.1 */
+    VP_OPTION_DTMF_SPEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionDtmfSpecType;
+
+/**< The following types are for Park Mode options */
+typedef struct VpOptionParkModeType {
+    uint16 discTime;    /**< Specified in 500ms increments, up to 8 seconds */
+    uint16 standbyTime; /**< Specified in 100ms increments, up to 8 seconds */
+} VpOptionParkModeType;
+
+/** Hook detection modes  */
+typedef enum VpOptionHookDetectModeType {
+    VP_OPTION_HOOKDET_NORMAL         = 0,  /* normal hook detection behavior */
+    VP_OPTION_HOOKDET_DISC_IS_ONHOOK = 1,  /* in the VP_LINE_DISCONNECT or VP_LINE_DISABLED
+                                              state, the hook status is always considered
+                                              to be on-hook */
+    VP_OPTION_HOOKDET_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionHookDetectModeType;
+
+/* Option value struct for VP_OPTION_ID_AUTO_LOOP_COND: */
+typedef enum VpLoopCondSelectType {
+    VP_LOOP_COND_NONE  = 0x0000,    /* feature disabled */
+    VP_LOOP_COND_RLOOP = 0x0001,    /* read loop resistance */
+    VP_LOOP_COND_ILG   = 0x0002,    /* read longitudinal (common mode) current */
+    VP_LOOP_COND_IMT   = 0x0004,    /* read metallic (differential) current */
+    VP_LOOP_COND_VSAB  = 0x0008,    /* read metallic (differential) voltage */
+    VP_LOOP_COND_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopCondSelectType;
+
+typedef struct VpOptionAutoLoopCondType {
+    uint16 select;  /* bitmask (multiple VpLoopCondSelectType values can be ORed
+                       together */
+    uint16 delay;   /* amount of time (in ms) after HOOK_OFF before
+                       measurement(s) */
+} VpOptionAutoLoopCondType;
+
+/* Definition for Absolute Level option */
+typedef struct VpOptionAbsGainType {
+    int16 gain_AToD;
+    int16 gain_DToA;
+} VpOptionAbsGainType;
+
+#define VP_OPTION_ABS_GAIN_QUIET        (-32767)
+#define VP_OPTION_ABS_GAIN_NO_CHANGE    (+32767)
+#define VP_ABS_GAIN_UNKNOWN             (VP_OPTION_ABS_GAIN_NO_CHANGE - 1)
+
+/* Option value struct for VP_DEVICE_OPTION_ID_PCM_SIG_CTL: */
+typedef struct VpOptionPcmSigCtlType {
+    bool enable;
+    uint8 ctlTimeslot;
+    uint8 sigTimeslot;
+} VpOptionPcmSigCtlType;
+
+/* Option value struct for VP_OPTION_ID_LINESTATE_CTL_MODE: */
+typedef enum VpOptionLinestateCtlModeType {
+    VP_OPTION_LINESTATE_CTL_NORMAL     = 0x0000,
+    VP_OPTION_LINESTATE_CTL_PCM        = 0x0080
+} VpOptionLinestateCtlModeType;
+
+/* The following struct can be passed to VpGetResults() if the option ID is not
+   known at compile time, to ensure that the buffer is large enough regardless
+   of the option type. */
+typedef union VpOptionValueType {
+    VpOptionPulseType pulse;                       /* VP_DEVICE_OPTION_ID_PULSE        */
+                                                   /* VP_DEVICE_OPTION_ID_PULSE2       */
+    VpOptionCriticalFltType criticalFlt;           /* VP_DEVICE_OPTION_ID_CRITICAL_FLT */
+    VpOptionZeroCrossType zeroCross;               /* VP_OPTION_ID_ZERO_CROSS          */
+    uint16 ramp2stby;                              /* VP_DEVICE_OPTION_ID_RAMP2STBY    */
+    VpOptionPulseModeType pulseMode;               /* VP_OPTION_ID_PULSE_MODE          */
+    VpOptionTimeslotType timeslot;                 /* VP_OPTION_ID_TIMESLOT            */
+    VpOptionCodecType codec;                       /* VP_OPTION_ID_CODEC               */
+    VpOptionPcmHwyType pcmHwy;                     /* VP_OPTION_ID_PCM_HWY             */
+    VpOptionLoopbackType loopback;                 /* VP_OPTION_ID_LOOPBACK            */
+    VpOptionLineStateType lineState;               /* VP_OPTION_ID_LINE_STATE          */
+    VpOptionEventMaskType eventMask;               /* VP_OPTION_ID_EVENT_MASK          */
+    VpOptionRingControlType ringControl;           /* VP_OPTION_ID_RING_CNTRL          */
+    VpOptionDtmfModeType dtmfMode;                 /* VP_OPTION_ID_DTMF_MODE           */
+    VpOptionDeviceIoType deviceIo;                 /* VP_DEVICE_OPTION_ID_DEVICE_IO    */
+    VpOptionPcmTxRxCntrlType pcmTxRxCntrl;         /* VP_OPTION_ID_PCM_TXRX_CNTRL      */
+    VpOptionDeviceIoConfigType deviceIoConfig;     /* VP_DEVICE_OPTION_ID_DEV_IO_CFG   */
+    VpOptionLineIoConfigType lineIoConfig;         /* VP_OPTION_ID_LINE_IO_CFG         */
+    VpOptionDtmfSpecType dtmfSpec;                 /* VP_OPTION_ID_DTMF_SPEC           */
+    VpOptionParkModeType parkMode;                 /* VP_DEVICE_OPTION_ID_PARK_MODE    */
+    VpOptionLinePulseType linePulse;               /* VP_OPTION_ID_PULSE               */
+    uint16 dcFeedSlope;                            /* VP_OPTION_ID_DCFEED_SLOPE        */
+    bool switcherCtrl;                             /* VP_OPTION_ID_SWITCHER_CTRL       */
+    uint32 debugSelect;                            /* VP_OPTION_ID_DEBUG_SELECT        */
+    VpOptionAbsGainType absGain;                   /* VP_OPTION_ID_ABS_GAIN            */
+    VpOptionHookDetectModeType hookDetectMode;     /* VP_OPTION_ID_HOOK_DETECT_MODE    */
+    VpOptionPcmSigCtlType pcmSigCtl;               /* VP_DEVICE_OPTION_ID_PCM_SIG_CTL  */
+    VpOptionLinestateCtlModeType linestateCtlMode; /* VP_OPTION_ID_LINESTATE_CTL_MODE  */
+    VpOptionAutoLoopCondType autoLoopCond;         /* VP_OPTION_ID_AUTO_LOOP_COND      */
+} VpOptionValueType;
+
+#endif /* VP_API_OPTION */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_test.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_test.h
new file mode 100755
index 0000000..143f444
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_test.h
@@ -0,0 +1,950 @@
+/** \file vp_api_test.h
+ * file vp_api_test.h
+ *
+ * This file contains declaration associated with VP-API Test features.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_TEST_H
+#define VP_API_TEST_H
+
+#include "vp_api_types.h"
+#include "vp_api_option.h"
+#include "vp_api_event.h"   /* For VpDigitType */
+
+#define VP_TEST_NOT_MEASURED            0x8000    /* a value of -1 to indicate not measured */
+                                        /* chosen because it is an impermissible value in those tests where used */
+
+/** Tests supported by VpTestLine function */
+typedef enum VpTestIdType {
+    VP_TEST_ID_PREPARE        = 0x00, /* Prepare for a test sequence */
+    VP_TEST_ID_CONCLUDE       = 0x01, /* Conclude a test sequence */
+    VP_TEST_ID_SET_SENSE_GAIN = 0x02, /* Set ILG and IMT gains high or low */
+    VP_TEST_ID_OPEN_VDC       = 0x03, /* Measure open DC voltage */
+    VP_TEST_ID_OPEN_VAC       = 0x04, /* Measure open AC voltage */
+    VP_TEST_ID_DIFF_VAC       = 0x05, /* Measure differential AC voltage */
+    VP_TEST_ID_DC_RLOOP       = 0x06, /* Measure DC loop resistance */
+    VP_TEST_ID_AC_RLOOP       = 0x07, /* Measure AC loop impedance */
+    VP_TEST_ID_NULL_IGND      = 0x08, /* Null ground current */
+    VP_TEST_ID_3ELE_RES       = 0x09, /* Measure 3-element insulation resistance */
+    VP_TEST_ID_3ELE_CAP       = 0x0A, /* Measure 3-element capacitance */
+    VP_TEST_ID_IDC            = 0x0B, /* Measure DC currents */
+    VP_TEST_ID_IAC            = 0x0C, /* Measure AC currents */
+    VP_TEST_ID_KEYPAD         = 0x0D, /* Keypad DTMF and Pulse dial test */
+    VP_TEST_ID_NOISE          = 0x0E, /* Measure Active or Passive Noise 3, 3.4 & 15KhZ */
+    VP_TEST_ID_SNR_QDIST      = 0x0F, /* Measure SNR and quantization distortion */
+    VP_TEST_ID_ARB_1TONE      = 0x10, /* Measure arbitrary single tone */
+    VP_TEST_ID_TONE_GEN       = 0x11, /* Generate a single/dual/quad-tone */
+    VP_TEST_ID_DIALTONE       = 0x12, /* Detect and measure dial tone (Inward test) */
+    VP_TEST_ID_HYBRID_LOSS    = 0x13, /* Measure trans-hybrid loss */
+    VP_TEST_ID_ALT_REN        = 0x14, /* Alternative method used to measure REN */
+    VP_TEST_ID_HOOK_STATUS    = 0x15, /* Check Hook Status (while in test mode) */
+    VP_TEST_ID_PCM_COLLECT    = 0x16, /* Collect PCM samples */
+    VP_TEST_ID_AC_RLOOP_PHASE = 0x17, /* Rloop with Phase information */
+    VP_TEST_ID_SET_BATTERIES  = 0x18, /* Select batteries for line testing */
+    VP_TEST_ID_MONITOR_IV     = 0x19, /* Non-Intrusive Monitoring Test */
+    VP_TEST_ID_UNBAL_TONE     = 0x1A, /* Generates an unbalanced tracing tone */
+    VP_TEST_ID_3ELE_RES_VMID  = 0x1B, /* Measure 3-element insulation resistance with a specified vMid */
+    VP_TEST_ID_AC_TRANS       = 0x1C, /* Measures digital-digital transmission characteristics */
+    VP_TEST_ID_GEN_TEST       = 0x1D, /* Multi-functional primitive */
+    VP_TEST_ID_SLOPE_REN      = 0x1E, /* REN test with a ramp instead of step */
+    /* Test IDs above this line are supported by one or more VCP devices.
+       Their values must not change.  More VCP tests might be added above this
+       line in the future. */
+
+    VP_TEST_ID_RSVD_MIN       = 0x23, /* Custom VCP tests (not currently used) */
+    VP_TEST_ID_RSVD_MAX       = 0x23,
+
+    /* The values of the constants below this line can change from time. */
+
+    VP_TEST_ID_3ELE_RES_HG,     /* Alternative 3-element resistance high gain */
+    VP_TEST_ID_3ELE_RES_LG,     /* Alternative 3-element resistance low gain */
+    VP_TEST_ID_3ELE_CAP_CSLAC,  /* CSLAC 3-element capacitance test */
+    VP_TEST_ID_MSOCKET_TYPE2,   /* Master Socket test for UK termination */
+    VP_TEST_ID_XCONNECT,        /* Cross Connect detection test */
+    VP_TEST_ID_LOOP_CONDITIONS, /* Measure current loop conditions */
+    VP_TEST_ID_LOOPBACK,        /* Setup loopback conditions */
+    VP_TEST_ID_LINE_IMPD,       /* Measure impedance at a frequency */
+    VP_TEST_ID_RING_TRIP,       /* Test ability to detect ring trip */
+    VP_TEST_ID_LOOP_DETECT,     /* Test ability to source current and detect
+                                 * off-hook */
+    VP_TEST_ID_CALIBRATE,       /* Perform line calibration */
+    VP_TEST_ID_USE_LINE_CAL,    /* Copy dev cal factors from lineObj to devObj */
+    VP_TEST_ID_OPEN_VXC,        /* Measure both DC and AC voltages */
+
+    VP_TEST_ID_GR909_HEMF,      /* Hazardous Potential Voltage Test for AC/DC
+                                 * Tip and Ring */
+    VP_TEST_ID_GR909_EMF,       /* FEMF test for AC/DC Tip and Ring */
+    VP_TEST_ID_GR909_RES_FLT,   /* Resistive Faults (T/R, T-Gnd, R-Gnd) */
+    VP_TEST_ID_GR909_OFF_HOOK,  /* Receiver Off-Hook */
+    VP_TEST_ID_GR909_RINGERS,   /* REN per FCC part 68 (1REN = 7Kohm) */
+    VP_TEST_ID_GR909_ALL,       /* Run all GR909 tests */
+    VP_TEST_ID_DELAY,           /* Implements non-blocking delay */
+    VP_TEST_ID_RAMP_INIT,       /* Implements a ramp to voltage test init */
+    VP_TEST_ID_RAMP,            /* Implements a ramp to voltage test */
+    VP_TEST_ID_FLT_DSCRM,       /* Implements the Fault discrimination test (880 890 only)*/
+    VP_TEST_ID_PREPARE_EXT,     /* Prepare for a test sequence without modifying the low power state  */
+
+    VP_TEST_ID_SET_SENSE_GAIN_792, /* Set Low/Normal/High sense gain for VCP792.
+                                    * The API translates this to the value of
+                                    * VP_TEST_ID_SET_SENSE_GAIN before sending
+                                    * it down to the VCP. */
+
+    VP_NUM_TEST_IDS,
+
+    VP_TEST_ID_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestIdType;
+
+/**< The following are test line error codes */
+typedef enum VpTestStatusType {
+    VP_TEST_STATUS_SUCCESS            = 0,  /**< Test Completed Successfully */
+    VP_TEST_STATUS_LINE_NOT_READY     = 1,  /**< Line Not in Test-mode (no VP_TEST_ID_PREPARE) */
+    VP_TEST_STATUS_RESOURCE_NA        = 2,  /**< Line Not available for Test (already in Test) */
+    VP_TEST_STATUS_TESTING            = 3,  /**< Test underway - not aborted */
+    VP_TEST_STATUS_VOUT_OOR           = 4,  /**< Voltage Out-of-range */
+    VP_TEST_STATUS_VAB_OOR            = 5,  /**< A-B Voltage is out-of-range */
+    VP_TEST_STATUS_ILG_OOR            = 6,  /**< Measured IILG is out-of-range */
+    VP_TEST_STATUS_VCM_OOR            = 7,  /**< Measured VCM is out-of-range */
+    VP_TEST_STATUS_IAHL_OOR           = 8,  /**< Measured current or voltage is out-of-range in Res or Cap test */
+    VP_TEST_STATUS_IBHL_OOR           = 9,  /**< " " */
+    VP_TEST_STATUS_IAHH_OOR           = 10, /**< " " */
+    VP_TEST_STATUS_IBHH_OOR           = 11, /**< " " */
+    VP_TEST_STATUS_VABHL_OOR          = 12, /**< " " */
+    VP_TEST_STATUS_IALL_OOR           = 13, /**< " " */
+    VP_TEST_STATUS_IBLL_OOR           = 14, /**< " " */
+    VP_TEST_STATUS_IA_OOR             = 15, /**< Measured Current is out-of-range */
+    VP_TEST_STATUS_IB_OOR             = 16, /**< " " */
+    VP_TEST_STATUS_IMT_OOR            = 17, /**< Measured IMT is out-of-range */
+    VP_TEST_STATUS_IMT_DC_OOR         = 18, /**< " " */
+    VP_TEST_STATUS_15KHZ_ERROR        = 19, /**< More than 1 15Khz Test requested */
+    VP_TEST_STATUS_TIMEOUT            = 20, /**< Failed to complete in specified time */
+    VP_TEST_STATUS_ABORTED            = 21, /**< Test aborted */
+    VP_TEST_STATUS_INTERNAL_ERROR     = 22, /**< Internal error (SLAC integrator) */
+    VP_TEST_STATUS_NO_CONVERGENCE     = 23, /**< NULL_IGND test failed to converge */
+    VP_TEST_STATUS_TEST_NOT_SUPPORTED = 24, /**< Requested test is not supported (due to device configuration) */
+    VP_TEST_STATUS_VTIPBIAS_OOR       = 25, /**< Tip Bias Voltage Out of Range */
+    VP_TEST_STATUS_VRINGBIAS_OOR      = 26, /**< Ring Bias Voltage Out of Range */
+    VP_TEST_STATUS_VMID_OOR           = 27, /**< User specified vMid voltage is out of range */
+    VP_TEST_STATUS_GAIN_OOR           = 28, /**< User specified gain is out of range */
+    VP_TEST_STATUS_VA_OOR             = 29, /**< Measured Voltage is out-of-range */
+    VP_TEST_STATUS_VB_OOR             = 30, /**< " " */
+    VP_TEST_STATUS_IMTOFFSET_OOR      = 31,
+    VP_TEST_STATUS_BUF_OVERFLOW       = 32, /* test would exceed the buffer storage available */
+    VP_TEST_STATUS_NUM_TYPES,               /**< NOT an ERROR, Just used for coding purposes */
+    VP_TEST_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestStatusType;
+
+typedef struct VpTestCalibrationDataType {
+    uint16 gMvErr;
+    int16 gMvOff;
+    uint16 gLvErr;
+    int16 gLvOff;
+    uint16 gMiErr;
+    int16 gMiOff;
+    uint16 gLiErr;
+    int16 gLiOff;
+    uint16 sAvErr;
+    int16 sAvOff;
+    uint16 sAiErr;
+    int16 sAiOff;
+    uint16 sBvErr;
+    int16 sBvOff;
+    uint16 sBiErr;
+    int16 sBiOff;
+
+    uint16 sABMvErr;
+    int16 sABMvOff;
+    uint16 sABMiErr;
+    int16 sABMiOff;
+
+    uint16 sABLvErr;
+    int16 sABLvOff;
+    uint16 sABLiErr;
+    int16 sABLiOff;
+
+    uint16 sABMHiErr;
+    int16 sABMHiOff;
+    uint16 sABLHiErr;
+    int16 sABLHiOff;
+} VpTestCalibrationDataType;
+
+/* Definitions used for VP_TEST_ID_DELAY */
+typedef struct VpTestTimerType {
+    uint16 timerVal;    /* Value in 125uS steps */
+} VpTestTimerType;
+
+/* Definitions used for VP_TEST_ID_PREPARE */
+typedef struct VpTestPrepareType {
+    bool intrusive;
+} VpTestPrepareType;
+
+/* Definitions used for VP_TEST_ID_CONCLUDE */
+typedef struct VpTestConcludeType {
+    bool abortTest;
+} VpTestConcludeType;
+
+/* Definitions used for VP_TEST_ID_SET_SENSE_GAIN */
+typedef enum VpSenseGainType {
+    VP_SENSE_GAIN_HIGH = 0,
+    VP_SENSE_GAIN_LOW  = 1,
+    VP_SENSE_GAIN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSenseGainType;
+
+typedef struct VpTestSetSenseGainType {
+    VpSenseGainType imt;
+    VpSenseGainType ilg;
+} VpTestSetSenseGainType;
+
+/* 792-specific definitions for VP_TEST_ID_SET_SENSE_GAIN_VP792 */
+typedef enum Vp792SenseGainType {
+    VP792_SENSE_GAIN_0dB_GAIN   = 0x0000, /* absolute gain = 1 */
+    VP792_SENSE_GAIN_28dB_GAIN  = 0x0010, /* absolute gain = 25 */
+    VP792_SENSE_GAIN_10dB_LOSS  = 0x0020, /* absolute gain = 1/3 */
+    VP792_SENSE_GAIN_RSVD       = 0x0030,
+    VP792_SENSE_GAIN_ENUM_SIZE  = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} Vp792SenseGainType;
+
+typedef struct VpTestSet792SenseGainType {
+    Vp792SenseGainType senseGain;
+} VpTestSet792SenseGainType;
+
+/* Definitions used for VP_TEST_ID_SET_BATTERIES */
+typedef enum VpSetBatteriesType {
+    VP_BS_LOW  = 0,
+    VP_BS_HIGH = 1,
+    VP_BS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSetBatteriesType;
+
+typedef struct VpTestSetBatteriesType {
+    VpSetBatteriesType bs1;
+    VpSetBatteriesType bs0;
+} VpTestSetBatteriesType;
+
+/* Definitions used for VP_TEST_ID_OPEN_VDC, VP_TEST_ID_OPEN_VAC */
+typedef enum VpTestTipSelectType {
+    VP_TEST_RING     = 0,
+    VP_TEST_TIP      = 1,
+    VP_TEST_TIP_RING = 2,
+    VP_TEST_TIP_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestTipSelectType;
+
+typedef struct VpTestOpenVType {
+    bool calMode;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestTipSelectType tip;
+} VpTestOpenVType;
+
+/* Definitions used for VP_TEST_ID_DIFF_VAC */
+typedef struct VpTestDiffVacType {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    int16 gvsaCal;
+    int16 gvsbCal;
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestDiffVacType;
+
+/* Definitions used for VP_TEST_IDC, VP_TEST_IAC */
+typedef struct VpTestIdcType {
+    bool calMode;
+    int16 vCm;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestIdcType;
+
+typedef struct VpTestIacType {
+    int16 gimtCal;
+    int16 gilgCal;
+    int16 vCm;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestIacType;
+
+typedef struct VpTestResultVixType {
+    int16 ia;
+    int16 ib;
+} VpTestResultVixType;
+
+/* Definitions used for VP_TEST_ID_DC_RLOOP */
+typedef struct VpTestDcRLoopType {
+    bool calMode;
+    int16 iTestLevel;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestDcRLoopType;
+
+typedef struct VpTestResultDcRlType {
+    int16 vab;
+    int16 ilg;
+    bool currentSaturation;
+} VpTestResultDcRlType;
+
+/* Definitions used for VP_TEST_ID_AC_RLOOP */
+typedef struct VpTestAcRLoopType {
+    bool calMode;
+    uint16 freq;
+    int16 vTestLevel;
+    int16 vBias;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestTipSelectType tip; /* Used by VE880 only */
+} VpTestAcRLoopType;
+
+typedef struct VpTestResultAcRlType {
+    int16 imt;
+    int16 ilg;
+    int16 vab;
+    int32 freq;
+} VpTestResultAcRlType;
+
+/* Definition used for VP_TEST_ID_AC_RLOOP_PHASE (in addition to VpTestAcRLoopType) */
+typedef struct VpTestResultAcRlPhaseType {
+    int16 imt;
+    int16 ilg;
+    int16 phase;
+} VpTestResultAcRlPhaseType;
+
+/* Definitions used for VP_TEST_ID_LOOP_COND */
+typedef enum VpLoopCondTestType {
+    VP_LOOP_COND_TEST_VSAB  = 1,
+    VP_LOOP_COND_TEST_VSAG  = 2,
+    VP_LOOP_COND_TEST_VSBG  = 3,
+    VP_LOOP_COND_TEST_RLOOP = 4,
+    VP_LOOP_COND_TEST_ILG   = 5,
+    VP_LOOP_COND_TEST_IMT   = 6,
+    VP_LOOP_COND_TEST_BAT1  = 7,
+    VP_LOOP_COND_TEST_BAT2  = 8,
+    VP_LOOP_COND_TEST_BAT3  = 9,
+    VP_LOOP_COND_TEST_METER = 10,
+    VP_LOOP_COND_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopCondTestType;
+
+typedef struct VpTestLoopCondType {
+    bool calMode;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpLoopCondTestType loopCond; /* Indicates which condition to measure */
+} VpTestLoopCondType;
+
+typedef struct VpTestResultLoopCondType {
+    VpLoopCondTestType condition;
+    int16 data;
+    bool calibrated;
+    int16 limit;            /* Limit or target value */
+} VpTestResultLoopCondType;
+
+/* Definitions used for VP_TEST_ID_XCONNECT */
+typedef enum VpXConnectType {
+    VP_XCONNECT_DISC_V    = 0,
+    VP_XCONNECT_12VVOC_I  = 1,
+    VP_XCONNECT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpXConnectType;
+
+typedef struct VpTestXConnectType {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpXConnectType measReq; /* Indicates which measurement sequence to run */
+    bool isFeedPositive;    /* VP_XCONNECT_12VVOC_I feed sign depends on measured EMF */
+    uint8 phase;            /* Test phase number */
+} VpTestXConnectType;
+
+typedef struct VpTestResultXConnectType {
+    VpXConnectType condition;
+    int16 data;
+} VpTestResultXConnectType;
+
+/* Definitions used for VP_TEST_ID_LOOPBACK */
+typedef enum VpLoopbackTestType {
+    VP_LOOPBACK_TEST_CODEC  = 1,
+    VP_LOOPBACK_TEST_ANALOG = 2,
+    VP_LOOPBACK_TEST_BFILTER = 3,
+    VP_LOOPBACK_TEST_TIMESLOT = 4,
+    VP_LOOPBACK_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopbackTestType;
+
+typedef struct VpTestLoopbackType {
+    uint16 waitTime;            /* Indicates how long before collecting samples */
+    uint16 loopbackTime;        /* Indicates Loopback duration in units of 125us */
+    VpLoopbackTestType loopback;/* Indicates which condition to setup */
+} VpTestLoopbackType;
+
+typedef struct VPTestResultLoopbackType {
+    VpLoopbackTestType  loopback; /* Indicates which condition was setup*/
+    void *pApplicationInfo;
+} VPTestResultLoopbackType;
+
+/* Definitions used for VP_TEST_LINE_IMPD */
+typedef struct VpTestLineImpdType {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    bool filterMode;
+    int16 vcm;              /* Common mode voltage for measurement */
+    int16 vDiff;            /* Differential voltage for measurement */
+    uint16 freq;
+    int16 amp;
+} VpTestLineImpdType;
+
+typedef struct VpTestResultLineImpdType {
+    bool iaOor;         /* If set IA out of range */
+    bool ibOor;         /* If set IB out of range */
+    uint16 iDiff;           /* RMS differential current */
+} VpTestResultLineImpdType;
+
+/**< Typedefs for Advanced Tests */
+/* Definitions used for VP_TEST_TONE_GEN */
+typedef struct VpTestToneGenType {
+    uint16 duration;
+    uint16 freq1;
+    int16 amp1;
+    uint16 freq2;
+    int16 amp2;
+    uint16 freq3;
+    int16 amp3;
+    uint16 freq4;
+    int16 amp4;
+} VpTestToneGenType;
+
+/* Definitions used for VP_TEST_ALT_REN */
+typedef struct VpTestRenType {
+    uint16 integrateTime;
+    int16 vDiff;
+} VpTestRenType;
+
+typedef struct VpTestResultRenType {
+    int16 imt;
+    int16 imtDc;
+} VpTestResultRenType;
+
+/* Definitions used for VP_TEST_ID_SLOPE_REN */
+typedef enum VpTestMathType {
+    VP_TEST_TYPE_UNDEFINED = 0,
+    VP_TEST_TYPE_AVG       = 1,
+    VP_TEST_TYPE_RMS       = 2,
+    VP_TEST_TYPE_DFT       = 3,
+    VP_TEST_TYPE_RAW       = 4,
+    VP_TEST_TYPE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestMathType;
+
+typedef enum VpTestDcbwSpeedType {
+    VP_TEST_SPEED_UNDEFINED = 0,
+    VP_TEST_SPEED_LOW       = 1,
+    VP_TEST_SPEED_MED       = 2,
+    VP_TEST_SPEED_HIGH      = 3,
+    VP_TEST_SPEED_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestDcbwSpeedType;
+
+typedef struct VpTestSRenType {
+    uint16 slopeTime;
+    uint16 integrateTime;
+    uint16 settlingTime;
+    int16 vDiff;
+    VpTestMathType type;
+    VpTestDcbwSpeedType speed;
+} VpTestSRenType;
+
+typedef struct VpTestResultSRenType {
+    int16 imtOffset;
+    int16 imt;
+    int16 imtDc;
+} VpTestResultSRenType;
+
+/* Definitions used for VP_TEST_ID_3ELE_RES*/
+typedef struct VpTestResType {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestResType;
+
+typedef struct VpTestResultResType {
+    int16 iahl;
+    int16 ibhl;
+    int16 iahh;
+    int16 ibhh;
+    int16 iall;
+    int16 ibll;
+    int16 vabhl;
+} VpTestResultResType;
+
+/* Definition used for VP_TEST_ID_3ELE_HG and LG */
+typedef struct VpTest3EleResAltResType {
+    int16 feedBias;
+    bool shiftZeroFeed;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTest3EleResAltResType;
+
+typedef struct VpTestResultAltResType {
+    bool highGain;
+    int16 vanf;
+    int16 vbnf;
+    int16 imnf;
+    int16 ilnf;
+    int16 varf;
+    int16 vbrf;
+    int16 imrf;
+    int16 ilrf;
+    int16 vazf;
+    int16 vbzf;
+    int16 imzf;
+    int16 ilzf;
+} VpTestResultAltResType;
+
+/* Definition used for VP_TEST_ID_MSOCKET_TYPE2 */
+typedef struct VpTestMSocketType {
+    uint8 dummy;
+} VpTestMSocketType;
+
+typedef struct VpTestResultMSockType {
+    int16 vanf;
+    int16 vbnf;
+    int16 imnf;
+    int16 varf1;
+    int16 vbrf1;
+    int16 imrf1;
+    int16 varf2;
+    int16 vbrf2;
+    int16 imrf2;
+    int16 varf3;
+    int16 vbrf3;
+    int16 imrf3;
+} VpTestResultMSockType;
+
+/* Definition used for VP_TEST_ID_3ELE_CAP_CSLAC */
+typedef struct VpTest3EleCapAltResType {
+    bool calMode;       /* Enable calibration */
+    uint16 testAmp;     /* Test signal amplitude (mV RMS) */
+    uint8 testFreq;     /* Test signal frequency [0,4], 0=2666.016Hz -> 4=280.151Hz */
+    int16 bias;         /* Signal generator bias (V) */
+} VpTest3EleCapAltResType;
+
+typedef struct VpTestResultAltCapType {
+    bool accuracyFlag;
+    uint8 freq;
+    int16 va;
+    int16 vb;
+    int16 im;
+    int16 il;
+    int32 tipCapCal;
+    int32 ringCapCal;
+} VpTestResultAltCapType;
+
+/* Definition used for VP_TEST_ID_3ELE_RES_VMID */
+typedef struct VpTestResVmidType {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    int16 vMid;
+} VpTestResVmidType;
+
+typedef struct VpTestResultVxcType {
+    int16 vdc;
+    int16 vac;
+} VpTestResultVxcType;
+
+/* Definitions used for VP_TEST_3ELE_CAP */
+typedef struct VpTestCapType {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 freq;
+    int16 gimtCal;
+    int16 gilgCal;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestCapType;
+
+typedef struct VpTestResultCapType {
+    int16 iahl;
+    int16 iahh;
+    int16 ibhh;
+    int16 iall;
+    int16 ibll;
+    int16 vabhl;
+} VpTestResultCapType;
+
+/* Definitions used for VP_TEST_NOISE */
+typedef enum VpTestFilterType {
+    VP_FILTER_NONE   = 0,
+    VP_FILTER_3KHZ   = 1,
+    VP_FILTER_CMSG   = 2,
+    VP_FILTER_15KHZ  = 3,
+    VP_FILTER_3_4KHZ = 4,
+    VP_FILTER_D      = 5,
+    VP_FILTER_PSOPH  = 6,
+    VP_NUM_TEST_FILTER_TYPES,
+    VP_FILTER_ENUM_RSVD    = FORCE_SIGNED_ENUM,
+    VP_FILTER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestFilterType;
+
+typedef struct VpTestNoiseType {
+    uint16 integrateTime;
+    VpTestFilterType filter;
+    int16 amp;
+    bool useBuffer;
+} VpTestNoiseType;
+
+/* Definitions used for VP_TEST_HYBRID_LOSS */
+typedef struct VpTestTransHybridLossType {
+    uint16 integrateTime;
+    uint16 freq;
+    int16 amp;
+    bool useBuffer;
+} VpTestTransHybridLossType;
+
+/* Definitions used for VP_TEST_ID_NULL_IGND */
+typedef struct VpTestNullIGndType {
+    int16 vTestLevel;
+    int16 iTarget;
+    VpTestTipSelectType tip;
+    uint16 settlingTime;
+} VpTestNullIGndType;
+
+/* Definitions used for VP_TEST_KEYPAD */
+typedef enum VpKeyTestType {
+    VP_KEY_TEST_DTMF  = 0,
+    VP_KEY_TEST_PULSE = 1,
+    VP_KEY_TEST_BOTH  = 2,
+    VP_NUM_KEY_TEST_TYPES,
+    VP_KEY_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpKeyTestType;
+
+typedef struct VpTestKeypadType {
+    VpKeyTestType kTest;
+    uint16 timeout;
+    uint16 freq;
+    int16 amp;
+    uint16 fftSize;
+    uint16 threshold;
+    VpOptionPulseType pulseOpt;
+    bool useBuffer;
+} VpTestKeypadType;
+
+typedef enum VpKeyTestResultType {
+    VP_KT_DTMF_DET   = 0,
+    VP_KT_DTMF_MES   = 1,
+    VP_KT_PULSE      = 2,
+    VP_KT_THRESH_DET = 3,
+    VP_NUM_KT_TYPES,
+    VP_KT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpKeyTestResultType;
+
+typedef struct VpTestResultKeyType {
+    VpKeyTestResultType kTestResult;
+    VpDigitType digit;
+    uint16 lowFreq;
+    uint16 lowAmp;
+    uint16 highFreq;
+    uint16 highAmp;
+    uint16 fftSize;
+    uint16 minBreak;
+    uint16 maxBreak;
+    uint16 aveBreak;
+    uint16 pulsePerSec;
+    bool hookFlashDet;
+    uint16 hookFlashDuration;
+    bool disconnectDet;
+} VpTestResultKeyType;
+
+/* Definitions used for VP_TEST_SNR_QDIST */
+typedef struct VpTestSnrQDistorType {
+    uint16 integrateTime;          /* Integration time in units of 125us */
+    int16 amp;
+    bool useBuffer;
+} VpTestSnrQDistorType;
+
+typedef struct VpTestResultSnrQDistorType {
+    uint16 vrmsNoise;
+    uint16 vrmsSignal;
+} VpTestResultSnrQDistorType;
+
+/* Definitions used for VP_TEST_ARB_1TONE */
+typedef struct VpTestArb1ToneType {
+    uint16 timeout;
+    uint16 fftSize;
+    uint16 threshold;
+    bool useBuffer;
+} VpTestArb1ToneType;
+
+/* Definitions used for VP_TEST_DIALTONE */
+typedef struct VpTestDialToneType {
+    bool inward;
+    uint16 timeout;
+    uint16 detectGran;
+    uint16 threshold;
+    uint16 fftSize;
+    uint16 duration;
+    bool useBuffer;
+} VpTestDialToneType;
+
+typedef struct VpTestResultToneType {
+    uint16 rmsPwr;
+    uint16 highFreq;
+    uint16 highAmp;
+    uint16 secFreq;
+    uint16 secAmp;
+    uint16 thdFreq;
+    uint16 thdAmp;
+} VpTestResultToneType;
+
+/**< The following types are for GR909 tests */
+/* Definitions used for  */
+typedef struct VpTestResultGR909EmfType {
+    bool testFail;
+    bool acFault;
+    bool dcFault;
+    uint16 acVolt;
+    int16 dcVolt;
+} VpTestResultGR909EmfType;
+
+/* Definitions used for VP_TEST_ID_GR909_RES_FLT */
+typedef struct VpTestResultGR909ResFltType {
+    bool testFail;
+    bool rtrFlt;
+    bool rtgFlt;
+    bool rrgFlt;
+    uint16 rtr;
+    uint16 rtg;
+    uint16 rrg;
+} VpTestResultGR909ResFltType;
+
+/* Definitions used for VP_TEST_ID_GR909_OFF_HOOK */
+typedef struct VpTestResultGR909OffHookType {
+    bool offHook;
+} VpTestResultGR909OffHookType;
+
+/* Definitions used for VP_TEST_ID_GR909_RINGERS */
+typedef struct VpTestResultGR909RenType {
+    bool testFailed;
+    bool renHigh;
+    bool renLow;
+    uint16 ren;
+} VpTestResultGR909RenType;
+
+/* Definitions used for VP_TEST_ID_GR909_ALL */
+typedef struct VpTestResultGR909AllType {
+    bool testFailed;
+    bool hvFailed;
+    bool emfFailed;
+    bool resFailed;
+    bool offHook;
+    bool ringersFailed;
+} VpTestResultGR909AllType;
+
+/* Definitions used for VP_TEST_ID_RAMP_INIT */
+typedef struct VpTestRampInitType {
+    int16 dcVstart;
+    int16 dcVend;
+    int16 vRate;
+    int16 bias;
+    VpTestTipSelectType tip;
+} VpTestRampInitType;
+
+/* Definitions used for VP_TEST_ID_RAMP */
+typedef struct VpTestRampType {
+    int16 dcVoltage;
+    int16 vRate;
+    int16 bias;
+    VpTestTipSelectType tip;
+} VpTestRampType;
+
+typedef struct VpTestResultRampType {
+    int16 imt;
+    int16 vRate;
+} VpTestResultRampType;
+
+/* Definitions used for VP_TEST_ID_MONITOR_IV */
+typedef enum VpMonitorIvFilterType {
+    VP_TEST_TYPE_DC = 0,
+    VP_TEST_TYPE_AC = 1,
+    VP_TEST_TYPE_ACDC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpMonitorIvFilterType;
+
+typedef enum VpMonitorIvTestMeasurementType {
+    VP_TEST_MEAS_VA  = 0,
+    VP_TEST_MEAS_VB  = 1,
+    VP_TEST_MEAS_VAB = 2,
+    VP_TEST_MEAS_IMT = 3,
+    VP_TEST_MEAS_ILG = 4,
+    VP_TEST_MEAS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpMonitorIvTestMeasurementType;
+
+typedef struct VpTestMonitorIvType {
+    bool calMode;
+    uint16 integrateTime;               /* Integration time in units of 125us */
+    uint16 settlingTime;                /* Filter settling time in units of 125us */
+    VpMonitorIvFilterType filterType;   /* Measurement Type (AC/DC) */
+    VpMonitorIvTestMeasurementType measurement; /* measurement source */
+} VpTestMonitorIvType;
+
+/* Definitions used for VP_TEST_ID_UNBAL_TONE */
+typedef struct VpTestUnbalToneType {
+    uint16 freq;
+    int16 vTestlevel;
+    int16 vTipBias;
+    int16 vRingBias;
+    uint16 duration;
+    VpTestTipSelectType tip;
+} VpTestUnbalToneType;
+
+/* Definitions used for VP_TEST_ID_PCM_COLLECT */
+typedef struct VpTestPcmCollectType {
+    uint16 sampleTime;
+} VpTestPcmCollectType;
+
+typedef struct VpTestResultPcmCollectType {
+    uint16 resultsSize;
+    uint16 samples;
+    VpOptionCodecType codec;
+    uint16 reserved;
+    uint32 address;
+} VpTestResultPcmCollectType;
+
+/* Definitions used for VP_FLT_DSCRM */
+typedef struct VpTestResultFltDscrmType {
+    int16 vtgFeed;
+    int16 vrgFeed;
+    int16 vtrFeed;
+    int16 vtrAC;
+    int16 vtoAC;
+    int16 vroAC;
+    int16 vtuBalAC;
+    int16 vruBalAC;
+    bool hookDet;
+    bool gnkDet;
+} VpTestResultFltDscrmType;
+
+/* Definitions for VP_TEST_ID_GEN_TEST */
+/* Generic Test Defines */
+typedef enum VpTestGenFilterType {
+    VP_TEST_FILTER_UNDEFINED = 0,
+    VP_TEST_FILTER_LPF       = 1,
+    VP_TEST_FILTER_HPF       = 2,
+    VP_TEST_FILTER_NONE      = 3,
+    VP_TEST_FILTER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenFilterType;
+
+typedef enum VpTestGenDriveType {
+    VP_TEST_DRIVE_UNDEFINED = 0,
+    VP_TEST_DRIVE_NONE      = 1,
+    VP_TEST_DRIVE_A         = 2,
+    VP_TEST_DRIVE_B         = 3,
+    VP_TEST_DRIVE_BOTH      = 4,
+    VP_TEST_DRIVE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenDriveType;
+
+typedef enum VpTestGenSignalType {
+    VP_TEST_SIGNAL_UNDEFINED = 0,
+    VP_TEST_SIGNAL_A         = 1,
+    VP_TEST_SIGNAL_B         = 2,
+    VP_TEST_SIGNAL_CM        = 3,
+    VP_TEST_SIGNAL_DIFF      = 4,
+    VP_TEST_SIGNAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenSignalType;
+
+typedef enum VpTestGenGainType {
+    VP_TEST_MEAS_UNDEFINED     = 0,
+    VP_TEST_MEAS_LOW_GAIN      = 1,
+    VP_TEST_MEAS_NORM_GAIN     = 2,
+    VP_TEST_MEAS_HIGH_GAIN     = 3,
+    VP_TEST_MEAS_SKIP          = 4,
+    VP_TEST_MEAS_IMT_NORM_GAIN = 5,
+    VP_TEST_MEAS_IMT_HIGH_GAIN = 6,
+    VP_TEST_MEAS_VAB_LOW_GAIN  = 7,
+    VP_TEST_MEAS_VAB_NORM_GAIN = 8,
+    VP_TEST_MEAS_VAB_HIGH_GAIN = 9,
+    VP_TEST_MEAS_ILG_NORM_GAIN = 10,
+    VP_TEST_MEAS_ILG_HIGH_GAIN = 11,
+    VP_TEST_MEAS_GEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenGainType;
+
+typedef struct VpTestGenTestType {
+    VpTestGenFilterType filter;
+    VpTestMathType type;
+    VpTestGenDriveType  driveMode;
+    VpTestGenSignalType  signalMode;
+    int16 vTestLevel;
+    uint16 freq;
+    int16 vTipBias;
+    int16 vRingBias;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestGenGainType iaMeas;
+    VpTestGenGainType vaMeas;
+    VpTestGenGainType ibMeas;
+    VpTestGenGainType vbMeas;
+} VpTestGenTestType;
+
+typedef struct VpTestResultGenTestType {
+    int16 iaReal;
+    int16 iaImag;
+    int16 vaReal;
+    int16 vaImag;
+    int16 ibReal;
+    int16 ibImag;
+    int16 vbReal;
+    int16 vbImag;
+} VpTestResultGenTestType;
+
+/* Definitions for Test results */
+typedef union VpTestResultsUnionType {
+    bool                          hstatus;
+    int16                         sVout;
+    uint16                        uVout;
+    int16                         vcm;
+    uint16                        vrms;
+    VpTestResultVxcType           vxc;
+    VpTestResultDcRlType          dcvab;
+    VpTestResultAcRlType          acimt;
+    VpTestResultAcRlPhaseType     acimtp;
+    VpTestResultVixType           vix;
+    VpTestResultResType           res;
+    VpTestResultAltResType        resAlt;
+    VpTestResultMSockType         mSock;
+    VpTestResultXConnectType      xConnect;
+    VpTestResultAltCapType        capAlt;
+    VpTestResultCapType           cap;
+    VpTestResultKeyType           keypad;
+    VpTestResultSnrQDistorType    snrqd;
+    VpTestResultToneType          tone;
+    VpTestResultRenType           ren;
+    VpTestResultLoopCondType      loopCond;
+    VPTestResultLoopbackType      loopback;
+
+    bool                          calFailed;
+    bool                          ringTripFail;
+    bool                          loopFnd;
+    bool                          loopBackTestFail;
+    VpTestResultLineImpdType      lineImpedance;
+    VpTestResultGR909EmfType      emf;
+    VpTestResultGR909ResFltType   resFault;
+    VpTestResultGR909OffHookType  offHookFault;
+    VpTestResultGR909RenType      ringers;
+    VpTestResultGR909AllType      gr909All;
+    VpTestResultRampType          ramp;
+    VpTestResultPcmCollectType    pcmCollect;
+    VpTestResultFltDscrmType      fltDscrm;
+    VpTestResultGenTestType       gen;
+    VpTestResultSRenType          sren;
+} VpTestResultsUnionType;
+
+typedef struct VpTestResultType {
+    VpTestIdType testId;            /* Test identifier */
+    VpTestStatusType errorCode;     /* Error code if Test Failed */
+    VpTestResultsUnionType result;  /* Return Results Union */
+} VpTestResultType;
+
+/* The following enum is used for event associated with VpSelfTest() */
+typedef enum VpSelfTestResultIdType {
+    VP_STEST_SUCCESS = 0,
+    VP_STEST_FAIL    = 1,
+    VP_STEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSelfTestResultIdType;
+
+#endif /* VP_API_TEST_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_timer.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_timer.h
new file mode 100755
index 0000000..32bf176
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_api_timer.h
@@ -0,0 +1,210 @@
+/** \file vp_api_timer.h
+ * vp_api_timer.h
+ *
+ * Header file for all timer typedefs used in API-II (internal).
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_TIMER_H
+#define VP_API_TIMER_H
+
+/* IMT average for Voltage to Frequency (FXO) smoothing */
+#define VP_IMT_AVG_LENGTH 2  /* FXO variable, but need this to compile */
+
+#define VP_ACTIVATE_TIMER       0x8000
+#define VP_TIMER_TIME_MASK      0x7FFF
+
+/**************************************************************************************************
+ * Common Timer Values - all times in ms                                                          *
+ **************************************************************************************************/
+/**< VP_DEV_TIMER_EXIT_RINGING_SAMPLE
+ * Used on VE880 ABS only at the moment. This is the initial time to delay switching from High Power
+ * to medium Power when exiting Ringing. It should be longer than the longest silent interval in any
+ * Ringing Cadence ideally. If not, it just means the supply would be switched to Medium Power and
+ * then quickly set back to High Power. No big deal, but not preferred.
+ */
+#define VP_DEV_TIMER_EXIT_RINGING_SAMPLE    (5000)
+
+/**< VP_DEV_TIMER_EXIT_RINGING_UPDATE
+ * Used on VE880 ABS only at the moment. This is the interval used to recheck for Ringing Exit after
+ * waiting the time specified by VP_DEV_TIMER_EXIT_RINGING_SAMPLE.
+ */
+#define VP_DEV_TIMER_EXIT_RINGING_UPDATE    (1000)
+
+/**< VP_WB_CHANGE_MASK_TIME
+ * The time used to mask Clock Fault after changing to or from Wideband mode on VE880 or VE890
+ */
+#define VP_WB_CHANGE_MASK_TIME              (20)
+
+/**< VP_DISCONNECT_RECOVERY_TIME
+ * Hook debounce time when exiting disconnect. This is to allow hook stability in case of high
+ * REN load conditions. Time of 100ms is sufficient for all normal field conditions, but if testing
+ * with 5REN per GR57 (40uF + 1386ohm) this time needs to be 120-130ms.
+ */
+#define VP_DISCONNECT_RECOVERY_TIME         (100)
+
+/**< VP_POLREV_DEBOUNCE_TIME
+ * Debounce time to mask hook activity when reversing polarity on the FXS line. The value (120ms)
+ * is designed to prevent false off-hook from being reported when changing line polarity under
+ * load conditions of 5REN FCC Part 68 load with 16ms Switch Hook Debounce in the DC Feed Profile.
+ * Applications that require detection of hook changes after polarity reversal in less than 120ms
+ * will have to change this value. Applications that need to prevent spurious hook events for load
+ * conditions of GR57 5REN (see "Ringing Capability) using 40uf + 1386ohm may need to increase this
+ * value. Note however that 40uf + 1386ohm condition is for test purposes only, not representative
+ * of real-world conditions.
+ */
+#define VP_POLREV_DEBOUNCE_TIME     (120)
+
+/**< Line Timer Definitions/Indexes
+ * Note that since the timer indexes themselves are generally used in incrememtal loops through
+ * the line timer array, these values must be sequential, unsigned type
+ */
+/**< VP_LINE_CID_DEBOUNCE: Hook debounce timer for conditions determined by the CID State Machine */
+#define VP_LINE_CID_DEBOUNCE            0
+
+/**< VP_LINE_TIMER_CID_DTMF: Timer for DTMF generation in CID */
+#define VP_LINE_TIMER_CID_DTMF          (VP_LINE_CID_DEBOUNCE + 1)
+
+/**< VP_LINE_TIMER_FAULT: VE790 only fault management timer */
+#define VP_LINE_TIMER_FAULT             (VP_LINE_TIMER_CID_DTMF + 1)
+
+/**< VP_LINE_RING_EXIT_PROCESS: Timer used for Ringing Exit handing */
+#define VP_LINE_RING_EXIT_PROCESS      (VP_LINE_TIMER_FAULT + 1)
+
+    /**< VP_CSLAC_RINGING_EXIT_MAX
+     * This value sets the maximum time the API will wait for the sillicon to exit it's own internal
+     * Ringing Exit state (used for certain conditions) before forcing the line to a know value and
+     * giving up on the timer. This value is monitored in the VE880/890 VP_LINE_RING_EXIT_PROCESS
+     * timer management functions. The time specified is in mSec.
+     */
+    #define VP_CSLAC_RINGING_EXIT_MAX       (100)
+
+/**< VP_LINE_HOOK_FREEZE:
+ * Hook Mask when making any line change that could cause spurious hook activity. This time should
+ * be used ONLY to mask hook activity, not as part of a control sequence. When it expires, the only
+ * action remaining should be to read the signaling register and process hook activity.
+ */
+#define VP_LINE_HOOK_FREEZE         (VP_LINE_RING_EXIT_PROCESS + 1)
+
+/**< VP_LINE_DISCONNECT_EXIT: Line Debounce for Disconnect Recovery */
+#define VP_LINE_DISCONNECT_EXIT         (VP_LINE_HOOK_FREEZE + 1)
+
+/**< VP_LINE_GND_START_TIMER: Timer for Recovery from Tip-Open */
+#define VP_LINE_GND_START_TIMER         (VP_LINE_DISCONNECT_EXIT + 1)
+
+/**< VP_LINE_CAL_LINE_TIMER: Timer used to sequence the CID state machine */
+#define VP_LINE_CAL_LINE_TIMER          (VP_LINE_GND_START_TIMER + 1)
+
+/**< VP_LINE_PING_TIMER: VE880 Rev VC only used to prevent phone "ping" when exiting disconnect */
+#define VP_LINE_PING_TIMER              (VP_LINE_CAL_LINE_TIMER + 1)
+
+/**< VP_LINE_TRACKER_DISABLE: Used to disable switcher with low power termination type. */
+#define VP_LINE_TRACKER_DISABLE         (VP_LINE_PING_TIMER + 1)
+
+/**< VP_LINE_GPIO_CLKOUT_TIMER: VE580 only time used to slow ringing signal clock output */
+#define VP_LINE_GPIO_CLKOUT_TIMER       (VP_LINE_TRACKER_DISABLE + 1)
+
+/**< VP_LINE_INTERNAL_TESTTERM_TIMER: Timer for the internal test termination */
+#define VP_LINE_INTERNAL_TESTTERM_TIMER (VP_LINE_GPIO_CLKOUT_TIMER + 1)
+
+/**< VP_LINE_SPEEDUP_RECOVERY_TIMER: Time used to manage the mettalic and battery speedup when
+ * making certain state transitions for VE880 and VE890
+ */
+#define VP_LINE_SPEEDUP_RECOVERY_TIMER  (VP_LINE_INTERNAL_TESTTERM_TIMER + 1)
+
+/**< VP_LINE_TIMER_LAST: Place holder to indicate number of line timers */
+#define VP_LINE_TIMER_LAST              (VP_LINE_SPEEDUP_RECOVERY_TIMER + 1)
+
+/**< Device Timer Definitions */
+/* Test line timer to ensure a more consistant MPI PCM collect routine, leave
+ * this timer as the first timer. */
+#define VP_DEV_TIMER_TESTLINE   0
+
+/* Clock fail interrupt timer - used only in 790 API */
+#define VP_DEV_TIMER_CLKFAIL            (VP_DEV_TIMER_TESTLINE + 1)
+
+/* ABS Calibration timer */
+#define VP_DEV_TIMER_ABSCAL             (VP_DEV_TIMER_CLKFAIL + 1)
+
+/* Lower Power Mode Switcher Changes */
+#define VP_DEV_TIMER_LP_CHANGE          (VP_DEV_TIMER_ABSCAL + 1)
+
+/* ABV Caibration  device timers */
+#define VP_DEV_TIMER_ABV_CAL            (VP_DEV_TIMER_LP_CHANGE + 1)
+
+/* In-rush limiting enter ringing device timers */
+#define VP_DEV_TIMER_ENTER_RINGING      (VP_DEV_TIMER_ABV_CAL + 1)
+
+/* Used on VE880-ABS only to time switching of the Supply Mode from HP (in Ringing) to MP */
+#define VP_DEV_TIMER_EXIT_RINGING       (VP_DEV_TIMER_ENTER_RINGING + 1)
+
+/* Used to mask clock faults */
+#define VP_DEV_TIMER_WB_MODE_CHANGE     (VP_DEV_TIMER_EXIT_RINGING + 1)
+
+/* Place holder to indicate number of device timers */
+#define VP_DEV_TIMER_LAST               (VP_DEV_TIMER_WB_MODE_CHANGE + 1)
+
+/** FXO specific timer variables to be used for FXO type lines only */
+typedef enum VpCslacTimerType {
+    VP_CSLAC_FXS_TIMER,
+    VP_CSLAC_FXO_TIMER,
+    VP_CSLAC_TIMER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCslacTimerType;
+
+
+#if (defined (VP_CC_880_SERIES) && defined (VP880_FXO_SUPPORT)) || \
+    (defined (VP_CC_890_SERIES) && defined (VP890_FXO_SUPPORT)) || \
+     defined (VP_CC_580_SERIES) || defined (VP_CC_KWRAP)
+typedef struct VpFXOTimerType {
+    uint16  highToLowTime;      /**< Device timestamp of last high to low change */
+    uint16  prevHighToLowTime;
+    bool    noCount;            /**< TRUE when not counting - lack of activity */
+    bool    lastState;          /**< TRUE if last known high, FALSE if low */
+    uint16  timeLastPolRev;     /**< Time in 0.25ms since polrev detected */
+    uint16  timePrevPolRev;     /**< Time in 0.25ms since prev polrev detected */
+    uint8   maxPeriod;          /**< Time in 0.25ms that ringing is detected */
+    uint16  lastStateChange;    /**< Time in 1mS since last state change */
+    uint16  lastNotLiu;         /**< Time in 1mS since last Not LIU detected */
+    uint16  disconnectDebounce; /**< Time in 1mS to debounce disconnect events */
+    uint16  disconnectDuration; /**< Time in ticks that disconnect is detected */
+    uint8   liuDebounce;        /**< Time in 1mS to debounce LIU detection that
+                                     accompanies some kinds of ringing */
+    uint8   ringOffDebounce;    /**< Time in 1mS to ignore disconnect after ring_off */
+    uint8   ringTimer;          /**< When this timer expires, ringing is off */
+    uint8   cidCorrectionTimer; /**< 1mS increments for CID correction timing */
+    uint8   bCalTimer;          /**< 1mS increments for BFilter sampling time */
+    uint16  fxoDiscIO2Change;   /**< Countdown in 1ms since IO2 changed for FXO_DISC termType */
+    uint16  pllRecovery;        /**< Timer in ticks to recover PLL when FXO Disconnect to OHT */
+    uint16  currentMonitorTimer;/**< Used to provide FXO line current buffer */
+    uint16  measureBFilterTimer;/**< 1mS increments for BFilter sampling time */
+    uint8   lowVoltageTimer;    /**< Timer in ticks for the low voltage
+                                     disconnect/LIU distinction workaround */
+} VpFXOTimerType;
+#endif
+
+/** Union of FXO and FXS timers since only one type can exist for each line */
+typedef union VpCslacTimers {
+#if (defined (VP_CC_880_SERIES) && defined (VP880_FXO_SUPPORT)) || \
+    (defined (VP_CC_890_SERIES) && defined (VP890_FXO_SUPPORT)) || \
+     defined (VP_CC_580_SERIES) || defined (VP_CC_KWRAP)
+    VpFXOTimerType fxoTimer;
+#endif
+    uint16 timer[VP_LINE_TIMER_LAST]; /**< FXS Array of timers */
+    uint16 trackingTime;    /**< Used in VE880/VE890 to track the total time the Ring Exit Timer
+                             * has been running. The Ring Exit Timer is restarted while waiting for
+                             * the silicon to make it's internal SLIC state change (i.e., get out of
+                             * the Ring Exit State). But in case the SLIC never makes the expected
+                             * state change, we want to force the final change and terminate the
+                             * timer.
+                             */
+} VpCslacTimers;
+
+typedef struct VpCslacTimerStruct {
+    VpCslacTimerType type;
+    VpCslacTimers timers;
+} VpCslacTimerStruct;
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug.h
new file mode 100755
index 0000000..f0e20a1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug.h
@@ -0,0 +1,475 @@
+/** \file vp_debug.h
+ * vp_debug.h
+ *
+ * This file contains the configuration and compile time settings for
+ * the VoicePath API debug statements.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ *
+ * As of svn 5835, no part of the VP-API-II uses the old VP_DOUT method.
+ */
+
+#ifndef VP_DEBUG_H
+#define VP_DEBUG_H
+
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "sys_service.h"
+
+/*
+ * These are not documented in the API-II and should be used for internal
+ * purposes only. Reserved range (0x00010000 to 0x80000000)
+ */
+#define DBG_EVENT_VERBOSE   0x00010000 /* Verbose event debug (792) */
+#define DBG_BOOT_WRITE      0x00020000 /* Displays all boot blocks */
+
+/* Define VP_DEBUG_COLOR to display ANSI X3.64 color codes in debug output. */
+#define VP_DEBUG_COLOR
+#include "vp_debug_colors.h"
+
+/* Colors for debug messages (if VP_DEBUG_COLOR is defined): */
+#define VP_DBG_ERROR_COLOR          bright_red
+#define VP_DBG_WARNING_COLOR        dark_yellow
+#define VP_DBG_INFO_COLOR           dark_blue
+#define VP_DBG_API_FUNC_COLOR       bright_cyan
+#define VP_DBG_API_FUNC_INT_COLOR   dark_cyan
+#define VP_DBG_HAL_COLOR            bright_white
+#define VP_DBG_SSL_COLOR            dark_green
+#define VP_DBG_EVENT_COLOR          bright_blue
+#define VP_DBG_CALIBRATION_COLOR    bright_white
+#define VP_DBG_LINE_STATE_COLOR     dark_yellow
+#define VP_DBG_HOOK_COLOR           bright_cyan
+#define VP_DBG_TEST_COLOR           bright_blue
+#define VP_DBG_TEST_FUNC_COLOR      bright_yellow
+#define VP_DBG_FXO_FUNC_COLOR       dark_green
+#define VP_DBG_SEQUENCER_COLOR      dark_blue
+#define VP_DBG_CID_COLOR            bright_white
+#define VP_DBG_TEST_PCM_COLOR       bright_cyan
+#define VP_DBG_GAIN_COLOR           dark_yellow
+
+/* Define VP_DEBUG_LOC to include the location (file and line) in each debug message. */
+#undef VP_DEBUG_LOC
+
+#ifdef VP_DEBUG_LOC
+#define VP_SHOW_LOC() VpSysDebugPrintf(" (" __FILE__ ":%d)", __LINE__)
+#else
+#define VP_SHOW_LOC()
+#endif
+
+/* Basic debug output macro: */
+#define VP_DOUT_(msgType, msgColor, objType, pObj, printf_args) \
+    if (VpDebugEnabled_ ## objType (VP_DBG_ ## msgType, color_fg(msgColor) #msgType, pObj)) { \
+        VpSysDebugPrintf printf_args; \
+        VP_SHOW_LOC(); \
+        VpSysDebugPrintf(color_reset "\n"); \
+    }
+
+/* Conditionally compile in various types of debug messages: */
+#if !defined(VP_DEBUG) && defined(VP_CC_DEBUG_SELECT)
+#undef VP_CC_DEBUG_SELECT
+#endif
+#ifndef VP_CC_DEBUG_SELECT
+#define VP_CC_DEBUG_SELECT 0
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_ERROR)
+#define VP_ERROR(objType, pObj, printf_args) VP_DOUT_(ERROR, VP_DBG_ERROR_COLOR, objType, pObj, printf_args)
+#else
+#define VP_ERROR(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_WARNING)
+#define VP_WARNING(objType, pObj, printf_args) VP_DOUT_(WARNING, VP_DBG_WARNING_COLOR, objType, pObj, printf_args)
+#else
+#define VP_WARNING(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_INFO)
+#define VP_INFO(objType, pObj, printf_args) VP_DOUT_(INFO, VP_DBG_INFO_COLOR, objType, pObj, printf_args)
+#else
+#define VP_INFO(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_API_FUNC)
+#define VP_API_FUNC(objType, pObj, printf_args) VP_DOUT_(API_FUNC, VP_DBG_API_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_API_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_API_FUNC_INT)
+#define VP_API_FUNC_INT(objType, pObj, printf_args) VP_DOUT_(API_FUNC_INT, VP_DBG_API_FUNC_INT_COLOR, objType, pObj, printf_args)
+#else
+#define VP_API_FUNC_INT(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_CALIBRATION)
+#define VP_CALIBRATION(objType, pObj, printf_args) VP_DOUT_(CALIBRATION, VP_DBG_CALIBRATION_COLOR, objType, pObj, printf_args)
+#else
+#define VP_CALIBRATION(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_LINE_STATE)
+#define VP_LINE_STATE(objType, pObj, printf_args) VP_DOUT_(LINE_STATE, VP_DBG_LINE_STATE_COLOR, objType, pObj, printf_args)
+#else
+#define VP_LINE_STATE(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_HOOK)
+#define VP_HOOK(objType, pObj, printf_args) VP_DOUT_(HOOK, VP_DBG_HOOK_COLOR, objType, pObj, printf_args)
+#else
+#define VP_HOOK(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST)
+#define VP_TEST(objType, pObj, printf_args) VP_DOUT_(TEST, VP_DBG_TEST_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST_FUNC)
+#define VP_TEST_FUNC(objType, pObj, printf_args) VP_DOUT_(TEST_FUNC, VP_DBG_TEST_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_FXO_FUNC)
+#define VP_FXO_FUNC(objType, pObj, printf_args) VP_DOUT_(FXO_FUNC, VP_DBG_FXO_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_FXO_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SEQUENCER)
+#define VP_SEQUENCER(objType, pObj, printf_args) VP_DOUT_(SEQUENCER, VP_DBG_SEQUENCER_COLOR, objType, pObj, printf_args)
+#else
+#define VP_SEQUENCER(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_CID)
+#define VP_CID(objType, pObj, printf_args) VP_DOUT_(CID, VP_DBG_CID_COLOR, objType, pObj, printf_args)
+#else
+#define VP_CID(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST_PCM)
+#define VP_TEST_PCM(objType, pObj, printf_args) VP_DOUT_(TEST_PCM, VP_DBG_TEST_PCM_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST_PCM(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_GAIN)
+#define VP_GAIN(objType, pObj, printf_args) VP_DOUT_(GAIN, VP_DBG_GAIN_COLOR, objType, pObj, printf_args)
+#else
+#define VP_GAIN(objType, pObj, printf_args)
+#endif
+
+
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SSL)
+#define VP_SSL(objType, pObj, printf_args) VP_DOUT_(SSL, VP_DBG_SSL_COLOR, objType, pObj, printf_args)
+#define VP_SYS_ENTER_CRITICAL(deviceId, criticalSecType) VpSysEnterCriticalWrapper(deviceId, criticalSecType)
+#define VP_SYS_EXIT_CRITICAL(deviceId, criticalSecType) VpSysExitCriticalWrapper(deviceId, criticalSecType)
+#define VP_SYS_WAIT(time) \
+    (VP_SSL(None, VP_NULL, ("VpSysWait(%u frames = %u ms)", (time), ((time) + 7 / 8))), VpSysWait(time))
+#else
+#define VP_SSL(objType, pObj, printf_args)
+#define VP_SYS_ENTER_CRITICAL(deviceId, criticalSecType) VpSysEnterCritical(deviceId, criticalSecType)
+#define VP_SYS_EXIT_CRITICAL(deviceId, criticalSecType) VpSysExitCritical(deviceId, criticalSecType)
+#define VP_SYS_WAIT(time) VpSysWait(time)
+#endif
+
+#ifndef VP_HAL_DEVICE_TYPE
+#define VP_HAL_DEVICE_TYPE VP_DEV_VCP_SERIES
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_HAL)
+#define VP_HAL(objType, pObj, printf_args) VP_DOUT_(HAL, VP_DBG_HAL_COLOR, objType, pObj, printf_args)
+#define VP_HAL_HBI_CMD(deviceId, cmd) \
+    (VpDisplayHbiCmd(VP_HAL_DEVICE_TYPE, deviceId, cmd), \
+    VpHalHbiCmd(deviceId, cmd))
+#define VP_HAL_HBI_WRITE(deviceId, cmd, numwords, data) \
+    (VpDisplayHbiCmd(VP_HAL_DEVICE_TYPE, deviceId, cmd), \
+    VpDisplayHbiData(deviceId, numwords + 1, data), \
+    VpHalHbiWrite(deviceId, cmd, numwords, data))
+#define VP_HAL_HBI_READ(deviceId, cmd, numwords, data) \
+    VpHalHbiReadWrapper(VP_HAL_DEVICE_TYPE, deviceId, cmd, numwords, data)
+#if (VP_CC_DEBUG_SELECT & DBG_BOOT_WRITE)
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    (VpDisplayHbiAccess(VP_HAL_DEVICE_TYPE, deviceId, numWords + 1, (uint16p)(data)), \
+    VpHalHbiBootWr(deviceId, numWords, data))
+#else
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    VpHalHbiBootWr(deviceId, numWords, data)
+#endif
+#else
+#define VP_HAL_HBI_CMD(deviceId, cmd) \
+    VpHalHbiCmd(deviceId, cmd)
+#define VP_HAL_HBI_WRITE(deviceId, cmd, numwords, data) \
+    VpHalHbiWrite(deviceId, cmd, numwords, data)
+#define VP_HAL_HBI_READ(deviceId, cmd, numwords, data) \
+    VpHalHbiRead(deviceId, cmd, numwords, data)
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    VpHalHbiBootWr(deviceId, numWords, data)
+#endif
+
+/* Basic assert macro: */
+#define VP_ASSERT(condition) \
+    if (!(condition)) { \
+        VP_ERROR(None, VP_NULL, ("Assertion failed: %s\n", #condition)); \
+        /* exit(-1); */ \
+    }
+
+#define VP_DOUT(msgType, printf_args)
+
+/* Global debug select mask (for messages that are not specific to a particular
+   line or device): */
+EXTERN uint32 vpDebugSelectMask;
+
+#ifdef VP_CC_VCP2_SERIES
+EXTERN bool
+VpDebugEnabled_VpVcp2DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpVcp2DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_VpVcp2LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpVcp2LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_MELT_SERIES
+EXTERN bool
+VpDebugEnabled_VpMeltDeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpMeltDeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_VpMeltLineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpMeltLineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_890_SERIES
+EXTERN bool
+VpDebugEnabled_Vp890DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp890DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp890LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp890LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_880_SERIES
+EXTERN bool
+VpDebugEnabled_Vp880DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp880DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp880LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp880LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_580_SERIES
+EXTERN bool
+VpDebugEnabled_Vp580DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp580DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp580LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp580LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_790_SERIES
+EXTERN bool
+VpDebugEnabled_Vp790DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp790DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp790LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp790LineObjectType *pLineObj);
+#endif
+
+EXTERN bool
+VpDebugEnabled_VpDeviceIdType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpDeviceIdType *pDeviceId);
+
+EXTERN bool
+VpDebugEnabled_VpLineIdType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpLineIdType *pLineId);
+
+EXTERN bool
+VpDebugEnabled_VpDevCtxType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpDevCtxType *pDevCtx);
+
+EXTERN bool
+VpDebugEnabled_VpLineCtxType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpLineCtxType *pLineCtx);
+
+EXTERN bool
+VpDebugEnabled_None(
+    uint32 msgType,
+    char *msgTypeStr,
+    void *nothing);
+
+EXTERN const char *
+VpGetString_VpStatusType(
+    VpStatusType status);
+
+EXTERN const char *
+    VpGetString_VpOptionIdType(
+    VpOptionIdType status);
+
+EXTERN const char *
+VpGetString_VpProfileType(
+    VpProfileType profType);
+
+EXTERN void
+VpDisplayEvent(
+    VpEventType *pEvent);
+
+EXTERN void
+VpDisplayResults(
+    VpEventType *pEvent,
+    void *pResult);
+
+EXTERN void
+VpDisplayHbiAccess(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    unsigned bufLen,
+    uint16 *buf);
+
+EXTERN unsigned
+VpDisplayHbiCmd(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    uint16 cmd);
+
+EXTERN void
+VpDisplayHbiData(
+    VpDeviceIdType deviceId,
+    unsigned bufLen,
+    uint16 *buf);
+
+EXTERN bool
+VpHalHbiReadWrapper(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    uint16 cmd,
+    uint8 numwords,
+    uint16 *data);
+
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SSL)
+EXTERN const char *
+VpGetString_VpCriticalSecType(
+    VpCriticalSecType criticalSecType);
+
+EXTERN uint8
+VpSysEnterCriticalWrapper(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+
+EXTERN uint8
+VpSysExitCriticalWrapper(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+#endif
+
+/* Derivative debug macros: */
+#define VP_API_ENTER(objType, pObj, funcName) \
+    VP_API_FUNC(objType, pObj, ("Vp%s():", funcName))
+#define VP_API_EXIT(objType, pObj, funcName, status) \
+    VP_API_FUNC(objType, pObj, ("Vp%s() = %s", funcName, VpGetString_VpStatusType(status)))
+#define VP_API_INT_ENTER(objType, pObj, funcName) \
+    VP_API_FUNC_INT(objType, pObj, ("%s():", funcName))
+#define VP_API_INT_EXIT(objType, pObj, funcName, status) \
+    VP_API_FUNC_INT(objType, pObj, ("%s() = %s", funcName, VpGetString_VpStatusType(status)))
+
+#if defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES)
+#if (VP_CC_DEBUG_SELECT & VP_DBG_ERROR)
+void VpPrintTermType(VpTermType termType);
+void VpPrintLineStateType(VpLineStateType lineState, char *strLineState);
+void VpPrintOptionRingControlType(VpOptionRingControlType *ringCtrl);
+void VpPrintOptionZeroCrossType(VpOptionZeroCrossType zeroCross);
+void VpPrintRelayControlType(VpRelayControlType relayState);
+void VpPrintOptionCodecType(VpOptionCodecType codec);
+void VpPrintOptionPcmTxRxCntrlType(VpOptionPcmTxRxCntrlType pcmTxRxCtrl);
+void VpPrintCallerIdType(VpCallerIdType *callerId);
+void VpPrintCidSeqDataType(VpCidSeqDataType *cidSeq);
+void VpPrintSeqDataType(VpSeqDataType *cadence);
+void VpPrintVpCslacTimerStruct(VpCslacTimerStruct *lineTimers);
+
+
+void VpPrintApiIntLineState(VpApiIntLineStateType *lineState);
+void VpPrintDigitGenDataType(VpDigitGenerationDataType *digitGenStruct);
+
+
+void VpPrintDynamicInfoStruct(VpDeviceDynamicInfoType *dynamicInfo);
+void VpPrintStaticInfoStruct(VpDeviceStaticInfoType *staticInfo);
+
+/* Bit-wise values from VpDeviceStateType */
+void VpPrintStateInformation(uint16 state);
+void
+VpPrintDeviceProfileStruct(
+    VpDeviceType deviceType,
+    void *devProfileData);
+
+void
+VpPrintEventMaskStruct(
+    bool isDeviceInfo,
+    bool isMask,
+    VpOptionEventMaskType *eventMask);
+
+void VpPrintCriticalFltStruct(VpOptionCriticalFltType *criticalFault);
+void VpPrintGetResultsOptionStruct(VpGetResultsOptionsType *resultsOption);
+void VpPrintRelGainResultsStruct(VpRelGainResultsType *relGainResults);
+
+#define VpPrintEventHandle(eventHandle)     VpSysDebugPrintf("\n\n\rpDevObj->eventHandle = 0x%04X", eventHandle)
+#define VpPrintTimeStamp(timeStamp)         VpSysDebugPrintf("\n\n\rpDevObj->timeStamp = 0x%04X", timeStamp)
+
+void VpPrintDeviceProfileTable(VpCSLACDeviceProfileTableType *devProfileTable);
+void VpPrintProfileTableEntry(VpCSLACProfileTableEntryType *profEntry);
+
+#if defined (VP890_FXS_SUPPORT) || defined (VP880_FXS_SUPPORT)
+void
+VpPrintPulseSpecs(
+    uint8 specNumber,
+    VpOptionPulseType *pulseSpecs);
+void
+VpPrintDPStateMachine(
+    uint8 stateMachineNum,
+    VpDialPulseDetectType  *dpStruct);
+#endif
+
+void
+VpPrintDeviceTimers(
+    uint16 devTimer[VP_DEV_TIMER_LAST]);
+
+#define VpPrintResponseData(responseData)       VpSysDebugPrintf("\n\n\rpDevObj->responseData = 0x%04X", responseData)
+#define VpPrintTxBufferRate(txBufferDataRate)   VpSysDebugPrintf("\n\n\rpDevObj->txBufferDataRate = %d", txBufferDataRate)
+
+
+#endif  /* VP_CC_DEBUG_SELECT & VP_DBG_ERROR */
+#endif  /* defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES) */
+
+
+
+
+
+
+
+#endif /* VP_DEBUG_H */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug_colors.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug_colors.h
new file mode 100755
index 0000000..6a51bf8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug_colors.h
@@ -0,0 +1,81 @@
+/* \file vp_debug_colors.h
+ * vp_debug_colors.h
+ *
+ * This file contains ANSI X3.64 codes for displaying colors.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 5264 $
+ * $LastChangedDate: 2009-07-06 10:22:54 -0500 (Mon, 06 Jul 2009) $
+ */
+
+#ifndef VP_DEBUG_COLORS_H
+#define VP_DEBUG_COLORS_H
+
+#include "vp_api_cfg.h"
+
+#ifdef VP_DEBUG_COLOR
+
+#define COLORS_begin    "\x1b["
+#define COLORS_delim    ";"
+#define COLORS_end      "m"
+#define COLORS_reset    "0"
+#define COLORS_bold     "1"
+#define COLORS_nonbold  "22"
+#define COLORS_fore     "3"
+#define COLORS_back     "4"
+
+#define COLORS_black    "0"
+#define COLORS_red      "1"
+#define COLORS_green    "2"
+#define COLORS_yellow   "3"
+#define COLORS_blue     "4"
+#define COLORS_magenta  "5"
+#define COLORS_cyan     "6"
+#define COLORS_white    "7"
+
+#define COLORS_bright_black     COLORS_black    COLORS_delim COLORS_bold
+#define COLORS_bright_red       COLORS_red      COLORS_delim COLORS_bold
+#define COLORS_bright_green     COLORS_green    COLORS_delim COLORS_bold
+#define COLORS_bright_yellow    COLORS_yellow   COLORS_delim COLORS_bold
+#define COLORS_bright_blue      COLORS_blue     COLORS_delim COLORS_bold
+#define COLORS_bright_magenta   COLORS_magenta  COLORS_delim COLORS_bold
+#define COLORS_bright_cyan      COLORS_cyan     COLORS_delim COLORS_bold
+#define COLORS_bright_white     COLORS_white    COLORS_delim COLORS_bold
+
+#define COLORS_dark_black       COLORS_black    COLORS_delim COLORS_nonbold
+#define COLORS_dark_red         COLORS_red      COLORS_delim COLORS_nonbold
+#define COLORS_dark_green       COLORS_green    COLORS_delim COLORS_nonbold
+#define COLORS_dark_yellow      COLORS_yellow   COLORS_delim COLORS_nonbold
+#define COLORS_dark_blue        COLORS_blue     COLORS_delim COLORS_nonbold
+#define COLORS_dark_magenta     COLORS_magenta  COLORS_delim COLORS_nonbold
+#define COLORS_dark_cyan        COLORS_cyan     COLORS_delim COLORS_nonbold
+#define COLORS_dark_white       COLORS_white    COLORS_delim COLORS_nonbold
+
+/*
+ * Usage example:
+ * printf( color_reset             "this is white-on-black text"
+ *         color(red, blue)        "this is red-on-blue text"
+ *         color_fg(green)         "this is green-on-blue text"
+ *         color_fg(bright_white)  "this is bright-white-on-blue text"
+ *         color_bg(black)         "this is bright-white-on-black text"
+ *         color_reset             "this is white on black\n"
+ * );
+ * Note: Bright colors are only allowed in the foreground.
+ */
+
+#define color_fg(c)             COLORS_begin COLORS_fore COLORS_ ## c COLORS_end
+#define color_bg(c)             COLORS_begin COLORS_back COLORS_ ## c COLORS_end
+#define color(fore_c, back_c)   COLORS_begin COLORS_fore COLORS_ ## fore_c COLORS_delim COLORS_back COLORS_ ## back_c COLORS_end
+#define color_reset             COLORS_begin COLORS_reset COLORS_end
+
+#else /* !defined(VP_DEBUG_COLOR) */
+
+#define color_fg(c)             ""
+#define color_bg(c)             ""
+#define color(fore_c, back_c)   ""
+#define color_reset             ""
+
+#endif
+
+#endif /* VP_DEBUG_COLORS_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug_masks.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug_masks.h
new file mode 100755
index 0000000..4a4af3c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/vp_debug_masks.h
@@ -0,0 +1,41 @@
+/** \file vp_debug_masks.h
+ * vp_debug_masks.h
+ *
+ * This file contains the debug masks for the VP-APi_II
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 7140 $
+ * $LastChangedDate: 2010-05-12 09:50:40 -0500 (Wed, 12 May 2010) $
+ */
+
+#ifndef VP_DEBUG_MASKS_H
+#define VP_DEBUG_MASKS_H
+
+/* VP-API debug message types: */
+#define VP_DBG_ERROR        0x00000001 /* Any error condition */
+#define VP_DBG_WARNING      0x00000002 /* Any warning condition */
+#define VP_DBG_INFO         0x00000004 /* Un-categorized information */
+#define VP_DBG_API_FUNC     0x00000008 /* API function entry/exit (except tick) */
+
+#define VP_DBG_API_FUNC_INT 0x00000010 /* Internal API function entry/exit */
+#define VP_DBG_HAL          0x00000020 /* HAL traffic */
+#define VP_DBG_SSL          0x00000040 /* SSL function entry/exit */
+#define VP_DBG_EVENT        0x00000080 /* Events/results from VpGetEvent()/VpGetResults() */
+
+#define VP_DBG_HOOK         0x00000100 /* Hook Based Code */
+#define VP_DBG_LINE_STATE   0x00000200 /* Set Line State Based Code */
+#define VP_DBG_CALIBRATION  0x00000400 /* VpCalCodec(), VpCalLine(), VpCal() */
+#define VP_DBG_TEST         0x00000800 /* Verbose test debug */
+
+#define VP_DBG_TEST_FUNC    0x00001000 /* Test I/F function enter and exit */
+#define VP_DBG_FXO_FUNC     0x00002000 /* FXO Detection Code */
+#define VP_DBG_SEQUENCER    0x00004000 /* Sequencer Based Code */
+#define VP_DBG_CID          0x00008000 /* Caller ID funcitons */
+
+#define VP_DBG_TEST_PCM     0x00010000 /* Verbose test pcm collection */
+#define VP_DBG_GAIN         0x00020000 /* VpSetRelGain() and VP_OPTION_ID_ABS_GAIN */
+
+#define VP_DBG_ALL          0xFFFFFFFF
+
+#endif /* VP_DEBUG_MASKS_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/Le71HP0410G_init.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/Le71HP0410G_init.c
new file mode 100755
index 0000000..1b549b0
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/Le71HP0410G_init.c
@@ -0,0 +1,576 @@
+#include "vp880_api_int.h"
+#include "vp_api_int.h"
+
+#undef BATT_DEBUG
+
+#ifdef BATT_DEBUG
+#define DBG(args...) mvOsPrintf(args)
+#else
+#define DBG(args...)
+#endif
+
+#define EC_1    VP880_EC_CH1
+#define EC_2    VP880_EC_CH2
+#define EC_BOTH (EC_1 | EC_2)
+
+/* Set device IDs according to the implementation of VpMpiCmd.
+ * Chip selects used:
+ *  CS0 - empty
+ *  CS1 - First device (gDev1Id) (VBH, VBL)
+ *  CS2 - Second device (gDev2Id) (VBP)
+ */
+VpDeviceIdType gDev1Id = 4;
+VpDeviceIdType gDev2Id = 5;
+
+
+/* Calibration arrays initially filled with median values from testing boards
+ * 022 and up as of April 5, 2010 */
+unsigned short gVbhCalAry[30] = {
+	420, 908, 1407, 1901, 2387, 2886, 3387, 3885, 4372, 4872,
+	5365, 5863, 6355, 6858, 7353, 7859, 8328, 8817, 9322, 9819,
+	10325, 10824, 11319, 11820, 12318, 12814, 13314, 13808, 14320, 14759
+};
+unsigned short gVblCalAry[30] = {
+	406, 898, 1396, 1891, 2378, 2879, 3372, 3879, 4377, 4865,
+	5360, 5861, 6360, 6859, 7358, 7856, 8340, 8839, 9335, 9837,
+	10334, 10839, 11332, 11837, 12322, 12828, 13322, 13823, 14322, 14685
+};
+unsigned short gVbpCalAry[30] = {
+	635, 1136, 1640, 2135, 2642, 3146, 3647, 4151, 4649, 5151,
+	5641, 6143, 6650, 7151, 7650, 8148, 8652, 9156, 9659, 10161,
+	10651, 11149, 11654, 12160, 12659, 13158, 13659, 14162, 14672, 15086
+};
+
+extern int BattOn(int vbhSetting, int vblSetting, int vbpSetting);
+
+extern int BattOff(void);
+
+static void CalculateRegisters(uint16 target, uint16 *pCalAry, uint8 *pSwReg, uint8 *pCalReg);
+
+static int MpiTest(VpDeviceIdType devId);
+
+int BattOn(int vbhIn, int vblIn, int vbpIn)
+{
+	uint8 data[20] = { 0 };
+	int i;
+	uint16 vbhTarget;
+	uint16 vblTarget;
+	uint16 vbpTarget;
+	uint8 vbhHex;
+	uint8 vblHex;
+	uint8 vbpHex;
+	uint8 calVbhHex;
+	uint8 calVblHex;
+	uint8 calVbpHex;
+
+	/* Argument checking */
+	if (vblIn > 0) {
+		mvOsPrintf("  VBL must be negative or zero\n");
+		return -1;
+	}
+	if (vbhIn > 0) {
+		mvOsPrintf("  VBH must be negative or zero\n");
+		return -1;
+	}
+	if (vbpIn < 0) {
+		mvOsPrintf("  VBP must be positive or zero\n");
+		return -1;
+	}
+	if (vblIn - vbhIn < 5 && vblIn != 0) {
+		mvOsPrintf("  VBH must be at least 5V more negative than VBL\n");
+		return -1;
+	}
+
+	/* 16 no-ops to clear MPI buffer */
+	for (i = 0; i < 16; i++)
+		data[i] = VP880_NO_OP;
+
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_NO_OP, 16, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_NO_OP, 16, data);
+
+	/* Read RCN/PCN and check that the devices are what we expect */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_DEVTYPE_CMD, VP880_DEVTYPE_LEN, data);
+	if (data[0] != VP880_REV_JE || data[1] != VP880_DEV_PCN_88506) {
+		mvOsPrintf("Invalid device 1, RCN/PCN 0x%02X%02X\n", data[0], data[1]);
+		return -1;
+	}
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_DEVTYPE_CMD, VP880_DEVTYPE_LEN, data);
+	if (data[0] != VP880_REV_JE || data[1] != VP880_DEV_PCN_88506) {
+		mvOsPrintf("Invalid device 2, RCN/PCN 0x%02X%02X\n", data[0], data[1]);
+		return -1;
+	}
+
+	/* Run MPI checks on both devices to make sure that it's safe to start
+	 * programming the devices.  If the signal integrity is bad, it could be
+	 * dangerous to continue. */
+	if (MpiTest(gDev1Id) < 0 || MpiTest(gDev2Id) < 0)
+		return -1;
+
+	/* HW reset */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_HW_RESET_CMD, 0, NULL);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_HW_RESET_CMD, 0, NULL);
+
+	/* Configure 8.192MHz mclk */
+	data[0] = 0x8A;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_MCLK_CNT_WRT, VP880_MCLK_CNT_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_MCLK_CNT_WRT, VP880_MCLK_CNT_LEN, data);
+
+	/* Unmask CFAIL */
+	data[0] = 0xFF & ~(VP880_CFAIL_MASK);
+	data[1] = 0xFF;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_INT_MASK_WRT, VP880_INT_MASK_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_INT_MASK_WRT, VP880_INT_MASK_LEN, data);
+
+	/* Make sure CFAIL clears on both devices */
+	for (i = 0; i < 11; i++) {
+		VpMpiCmd(gDev1Id, EC_BOTH, VP880_UL_SIGREG_RD, VP880_UL_SIGREG_LEN, data);
+		if ((data[0] & VP880_CFAIL_MASK) == 0)
+			break;
+
+		if (i == 10) {
+			mvOsPrintf("Couldn't clear CFAIL on dev 1");
+			return -1;
+		}
+		mvOsDelay(10);
+	}
+	for (i = 0; i < 11; i++) {
+		VpMpiCmd(gDev2Id, EC_BOTH, VP880_UL_SIGREG_RD, VP880_UL_SIGREG_LEN, data);
+		if ((data[0] & VP880_CFAIL_MASK) == 0)
+			break;
+
+		if (i == 10) {
+			mvOsPrintf("Couldn't clear CFAIL on dev 2");
+			return -1;
+		}
+		mvOsDelay(10);
+	}
+
+	/* Set the switcher timings */
+	data[0] = 0xB2;		/* Device defaults */
+	data[1] = 0x00;
+	data[2] = 0xB1;
+	data[3] = 0x00;
+	data[4] = 0xB0;
+	data[5] = 0x40;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_INT_SWREG_PARAM_WRT, VP880_INT_SWREG_PARAM_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_INT_SWREG_PARAM_WRT, VP880_INT_SWREG_PARAM_LEN, data);
+
+	/* ICR2 settings: c_tip_on and c_ring_on for measuring in disconnect,
+	 * 150V battery limit */
+	data[0] = VP880_ICR2_TIP_SENSE | VP880_ICR2_RING_SENSE;
+	data[1] = VP880_ICR2_TIP_SENSE | VP880_ICR2_RING_SENSE;
+	data[2] = VP880_ICR2_SWY_LIM_CTRL | VP880_ICR2_SWY_LIM_CTRL1;
+	data[3] = VP880_ICR2_SWY_LIM_CTRL | VP880_ICR2_SWY_LIM_CTRL1;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_ICR2_WRT, VP880_ICR2_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_ICR2_WRT, VP880_ICR2_LEN, data);
+
+	/* ICR3 settings: VREF ctrl, "line block control circuitry override" for
+	 * measuring in disconnect */
+	data[0] = VP880_ICR3_VREF_CTRL | VP880_ICR3_LINE_CTRL;
+	data[1] = VP880_ICR3_VREF_CTRL | VP880_ICR3_LINE_CTRL;
+	data[2] = 0;
+	data[3] = 0;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_ICR3_WRT, VP880_ICR3_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_ICR3_WRT, VP880_ICR3_LEN, data);
+
+	/* ICR4 settings: voice ADC override for measuring in disconnect */
+	data[0] = VP880_ICR4_VOICE_ADC_CTRL;
+	data[1] = VP880_ICR4_VOICE_ADC_CTRL;
+	data[2] = 0;
+	data[3] = 0;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_ICR4_WRT, VP880_ICR4_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_ICR4_WRT, VP880_ICR4_LEN, data);
+
+	/* Wait for VREF to stabilize */
+	mvOsDelay(20);
+
+	/* Disable auto system state ctrl, zero cross ringing, auto clock fail
+	 * switching, and thermal fault switching.  Enable auto battery shutdown */
+	data[0] = VP880_ACFS_DIS | VP880_ATFS_DIS | VP880_ZXR_DIS | VP880_AUTO_SSC_DIS | VP880_AUTO_BAT_SHUTDOWN_EN;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_SS_CONFIG_WRT, VP880_SS_CONFIG_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_SS_CONFIG_WRT, VP880_SS_CONFIG_LEN, data);
+
+	/* Zero out signal generator params for the channel (ch2 on dev1) that will
+	 * be in ringing */
+	for (i = 0; i < VP880_SIGA_PARAMS_LEN; i++)
+		data[i] = 0;
+
+	VpMpiCmd(gDev1Id, EC_2, VP880_SIGA_PARAMS_WRT, VP880_SIGA_PARAMS_LEN, data);
+
+	/* Calculate the register settings.  Calculations are performed  based on
+	 * units of cV and unsigned, for example -65.3 V == 6530 */
+	vbhTarget = (ABS(vbhIn) * 100);
+	vblTarget = (ABS(vblIn) * 100);
+	vbpTarget = (ABS(vbpIn) * 100);
+
+	DBG("VBH Calibration:\n");
+	CalculateRegisters(vbhTarget, gVbhCalAry, &vbhHex, &calVbhHex);
+	DBG("VBH results, vbhHex %02X, calVbhHex %02X\n\n", vbhHex, calVbhHex);
+
+	DBG("VBL Calibration:\n");
+	CalculateRegisters(vblTarget, gVblCalAry, &vblHex, &calVblHex);
+	DBG("VBL results, vblHex %02X, calVblHex %02X\n\n", vblHex, calVblHex);
+
+	DBG("VBP Calibration:\n");
+	CalculateRegisters(vbpTarget, gVbpCalAry, &vbpHex, &calVbpHex);
+	DBG("VBP results, vbpHex %02X, calVbpHex %02X\n\n", vbpHex, calVbpHex);
+
+	/* Set up switching regulator params - fixed, programmable */
+	data[0] = VP880_FLYBACK_MODE | VP880_ZRING_TRACK_DIS | VP880_YRING_TRACK_DIS;
+	data[1] = VP880_SWY_AUTOPOWER_DIS | vbhHex;
+	data[2] = VP880_SWZ_AUTOPOWER_DIS | vblHex;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_PARAM_WRT, VP880_REGULATOR_PARAM_LEN, data);
+
+	data[0] = VP880_FLYBACK_MODE | VP880_ZRING_TRACK_DIS | VP880_YRING_TRACK_DIS;
+	data[1] = VP880_SWY_AUTOPOWER_DIS | vbpHex;
+	data[2] = VP880_SWZ_AUTOPOWER_DIS;
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_REGULATOR_PARAM_WRT, VP880_REGULATOR_PARAM_LEN, data);
+
+	/* Set battery calibration registers */
+	data[1] = 0;
+	data[0] = calVbhHex << 3;
+	VpMpiCmd(gDev1Id, EC_1, VP880_BAT_CALIBRATION_WRT, VP880_BAT_CALIBRATION_LEN, data);
+	data[0] = calVblHex << 3;
+	VpMpiCmd(gDev1Id, EC_2, VP880_BAT_CALIBRATION_WRT, VP880_BAT_CALIBRATION_LEN, data);
+	data[0] = calVbpHex << 3;
+	VpMpiCmd(gDev2Id, EC_1, VP880_BAT_CALIBRATION_WRT, VP880_BAT_CALIBRATION_LEN, data);
+
+	/* Disable high-pass filter, cut off TX/RX */
+	data[0] = VP880_HIGH_PASS_DIS | VP880_CUT_TXPATH | VP880_CUT_RXPATH;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_OP_COND_WRT, VP880_OP_COND_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_OP_COND_WRT, VP880_OP_COND_LEN, data);
+
+	/* Set to linear mode, use default filters */
+	data[0] = VP880_LINEAR_CODEC | VP880_DEFAULT_OP_FUNC_MODE;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_OP_FUNC_WRT, VP880_OP_FUNC_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_OP_FUNC_WRT, VP880_OP_FUNC_LEN, data);
+
+	/* Set default DISN (00) */
+	data[0] = VP880_DEFAULT_DISN_GAIN;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_DISN_WRT, VP880_DISN_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_DISN_WRT, VP880_DISN_LEN, data);
+
+	mvOsDelay(50);
+
+    /*** Bring up HBAT ***/
+	/* Set HBAT switcher to low power. */
+	data[0] = 0;
+	if (vbhTarget != 0)
+		data[0] |= VP880_SWY_LP;
+
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+
+	mvOsDelay(10);
+
+	/* Set the line state:
+	 *  Dev 1 ch 1: disconnect (switcher Y)
+	 * Disconnect is needed so that the voltages don't track to VOC */
+	data[0] = VP880_SS_DISCONNECT | VP880_SS_ACTIVATE_MASK;
+	VpMpiCmd(gDev1Id, EC_1, VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, data);
+
+	mvOsDelay(100);
+
+    /*** Bring up LBAT ***/
+	/* Do a read/modify/write of ICR2 to override the LBAT switcher (Z) to off
+	 * so that we can set the line state to ringing before turning it on */
+	VpMpiCmd(gDev1Id, EC_2, VP880_ICR2_RD, VP880_ICR2_LEN, data);
+	data[2] |= VP880_ICR2_SWY_CTRL_EN;
+	data[3] &= ~VP880_ICR2_SWY_CTRL_EN;
+	VpMpiCmd(gDev1Id, EC_2, VP880_ICR2_WRT, VP880_ICR2_LEN, data);
+
+	/* Set the switcher control to low power.  It won't actually turn on yet
+	 * because of the ICR2 command above, but setting the register will allow
+	 * the line state to be set to ringing. */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_RD, VP880_REGULATOR_CTRL_LEN, data);
+	data[0] = 0;
+	if (vblTarget != 0)
+		data[0] |= VP880_SWZ_LP;
+
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+
+	mvOsDelay(10);
+
+	/* Set the line state:
+	 *  Dev 1 ch 2: ringing (switcher Z) */
+	data[0] = VP880_SS_BALANCED_RINGING;
+	VpMpiCmd(gDev1Id, EC_2, VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, data);
+
+	mvOsDelay(10);
+
+	/* Turn the switcher on */
+	VpMpiCmd(gDev1Id, EC_2, VP880_ICR2_RD, VP880_ICR2_LEN, data);
+	data[2] |= VP880_ICR2_SWY_CTRL_EN;
+	data[3] |= VP880_ICR2_SWY_CTRL_EN;
+	VpMpiCmd(gDev1Id, EC_2, VP880_ICR2_WRT, VP880_ICR2_LEN, data);
+
+	mvOsDelay(100);
+
+    /*** Bring up PBAT ***/
+	/* Set PBAT switcher to low power. */
+	data[0] = 0;
+	if (vbpTarget != 0)
+		data[0] |= VP880_SWY_LP;
+
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+
+	mvOsDelay(10);
+
+	/* Set the line states:
+	 *  Dev 2 ch 1: disconnect (switcher Y)
+	 * Disconnect is needed so that the voltages don't track to VOC */
+	data[0] = VP880_SS_DISCONNECT | VP880_SS_ACTIVATE_MASK;
+	VpMpiCmd(gDev2Id, EC_1, VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, data);
+
+	mvOsDelay(100);
+
+	/* Set switchers to high power for non-zero batteries, one at a time */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_RD, VP880_REGULATOR_CTRL_LEN, data);
+
+	if (vbhTarget != 0) {
+		data[0] &= ~VP880_SWY_MODE_MASK;
+		data[0] |= VP880_SWY_HP;
+		VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+	}
+
+	mvOsDelay(20);
+
+	if (vblTarget != 0) {
+		data[0] &= ~VP880_SWZ_MODE_MASK;
+		data[0] |= VP880_SWZ_HP;
+		VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+	}
+
+	mvOsDelay(20);
+
+	data[0] = 0;
+	if (vbpTarget != 0) {
+		data[0] |= VP880_SWY_HP;
+		VpMpiCmd(gDev2Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+	}
+
+	/* Set IOs to outputs to control the module LEDs */
+	data[0] = VP880_IODIR_IO1_OUTPUT | VP880_IODIR_IO2_OUTPUT;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_IODIR_REG_WRT, VP880_IODIR_REG_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_IODIR_REG_WRT, VP880_IODIR_REG_LEN, data);
+
+	/* Turn on the LEDs for non-zero batteries. */
+	data[0] = 0;
+	if (vbhTarget != 0) {
+		/* gDev1Id IO1 controls the VBH (v1) LED */
+		data[0] |= VP880_IODATA_IO1;
+	}
+	if (vblTarget != 0) {
+		/* gDev1Id IO2 controls the VBL (v2) LED */
+		data[0] |= VP880_IODATA_IO2;
+	}
+	VpMpiCmd(gDev1Id, EC_1, VP880_IODATA_REG_WRT, VP880_IODATA_REG_LEN, data);
+
+	data[0] = 0;
+	if (vbpTarget != 0) {
+		/* gDev2Id IO1 controls the VBP (v3) LED */
+		data[0] |= VP880_IODATA_IO1;
+	}
+	VpMpiCmd(gDev2Id, EC_1, VP880_IODATA_REG_WRT, VP880_IODATA_REG_LEN, data);
+
+	mvOsPrintf("Power supply initialized successfully\n");
+
+	return 0;
+}
+
+int BattOff(void)
+{
+	uint8 data[20];
+	int i;
+
+	/* 16 no-ops to clear MPI buffer */
+	for (i = 0; i < 16; i++)
+		data[i] = VP880_NO_OP;
+
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_NO_OP, 16, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_NO_OP, 16, data);
+
+	/* Read RCN/PCN and check that the devices are what we expect */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_DEVTYPE_CMD, VP880_DEVTYPE_LEN, data);
+	if (data[0] != VP880_REV_JE || data[1] != VP880_DEV_PCN_88506) {
+		mvOsPrintf("Invalid device 1, RCN/PCN 0x%02X%02X", data[0], data[1]);
+		return -1;
+	}
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_DEVTYPE_CMD, VP880_DEVTYPE_LEN, data);
+	if (data[0] != VP880_REV_JE || data[1] != VP880_DEV_PCN_88506) {
+		mvOsPrintf("Invalid device 2, RCN/PCN 0x%02X%02X", data[0], data[1]);
+		return -1;
+	}
+
+	/* Run MPI checks on both devices to make sure that it's safe to start
+	 * programming the devices.  If the signal integrity is bad, it could be
+	 * dangerous to continue. */
+	if (MpiTest(gDev1Id) < 0 || MpiTest(gDev2Id) < 0)
+		return -1;
+
+	/* Turn switchers off */
+	data[0] = VP880_SWY_OFF | VP880_SWZ_OFF;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+
+	/* Doubly make sure the switchers are off by setting ontimes to 0 */
+	data[0] = 0x00;
+	data[1] = 0x40;
+	data[2] = 0x00;
+	data[3] = 0x40;
+	data[4] = 0x00;
+	data[5] = 0x40;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_INT_SWREG_PARAM_WRT, VP880_INT_SWREG_PARAM_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_INT_SWREG_PARAM_WRT, VP880_INT_SWREG_PARAM_LEN, data);
+
+	/* Turn off the LEDs */
+	data[0] = 0;
+	VpMpiCmd(gDev1Id, EC_1, VP880_IODATA_REG_WRT, VP880_IODATA_REG_LEN, data);
+	VpMpiCmd(gDev2Id, EC_1, VP880_IODATA_REG_WRT, VP880_IODATA_REG_LEN, data);
+
+	return 0;
+}
+
+/*
+ * This function uses the calibration data at pCalAry to calculate the switching
+ * regulator and battery calibration register settings needed to produce a
+ * voltage as close as possible to the given target (in |cV|).  The register
+ * values are returned in the data pointed to by pSwReg and pCalReg.
+ */
+static void CalculateRegisters(uint16 target, uint16 *pCalAry, uint8 *pSwReg, uint8 *pCalReg)
+{
+	int16 minError;
+	uint8 minIndex;
+	uint8 index;
+	int16 error;
+	int8 cal;
+
+	DBG("Target = %d\n", target);
+
+	if (target == 0) {
+		*pSwReg = 0;
+		*pCalReg = 0;
+		return;
+	}
+
+	minIndex = 0;
+	minError = 32768;
+
+	/* The calibration data contains measured voltage values at each 5V
+	 * switching regulator step.  Find the 5V step measured value that is closest
+	 * to the target voltage. */
+	for (index = 0; index < 30; index++) {
+		error = target - pCalAry[index];
+		if (ABS(error) < ABS(minError)) {
+			minIndex = index;
+			minError = error;
+		}
+	}
+	DBG("Closest is %d (%d), %d.  Error %d (%d)\n",
+	    minIndex, (minIndex + 1) * 5, pCalAry[minIndex], minError, (int)minError / 125);
+
+	/* The battery calibration register allows adjustment in steps of.25V.
+	 * Calculate how many 1.25V steps are necessary to adjust for the difference
+	 * between the target voltage and the closest measured 5V step. */
+	if (minError > 0)
+		cal = (minError + (125 / 2)) / 125;
+	else
+		cal = (minError - (125 / 2)) / 125;
+
+	DBG("Cal offset %d\n", cal);
+
+	DBG("Actual output should be %d\n", pCalAry[minIndex] + (cal * 125));
+
+	/* The battery calibration register can only adjust 3 steps in either
+	 * direction (3.75V).  If we need more than that (meaning an error of at
+	 * least 4.375), print a warning.
+	 * Since we have measurements at every 5V step, errors should never be much
+	 * worse than 2.5V.  This would only reasonably happen if the target voltage
+	 * is above or below the ranged of measured voltages (such as 0.5 or 155) */
+	if (cal < -3) {
+		mvOsPrintf("Output error may be large.  cal=%d, limited to -3", cal);
+		cal = -3;
+	}
+	if (cal > 3) {
+		mvOsPrintf("Output error may be large.  cal=%d, limited to 3", cal);
+		cal = 3;
+	}
+
+	/* The hex value for the switching regulator params register is the same as
+	 * the index into the calibration array. */
+	*pSwReg = minIndex;
+
+	switch (cal) {
+	case -3:
+		*pCalReg = 0x7;
+		break;
+	case -2:
+		*pCalReg = 0x6;
+		break;
+	case -1:
+		*pCalReg = 0x5;
+		break;
+	case 0:
+		*pCalReg = 0x0;
+		break;
+	case 1:
+		*pCalReg = 0x1;
+		break;
+	case 2:
+		*pCalReg = 0x2;
+		break;
+	case 3:
+		*pCalReg = 0x3;
+		break;
+	default:
+		*pCalReg = 0;
+		mvOsPrintf("This shouldn't be possible, cal=%d", cal);
+		break;
+	}
+}
+
+/*
+ * This function performs a series of writes and reads to verify the signal
+ * integrity of the MPI interface.
+ */
+static int MpiTest(VpDeviceIdType devId)
+{
+	uint8 writeData[20] = { 0 };
+	uint8 readData[20] = { 0 };
+	int x;
+	int y;
+	int i;
+
+	for (x = 0; x <= 0xFF; x++) {
+		for (i = 0; i < VP880_R_FILTER_LEN; i++)
+			writeData[i] = x;
+
+		VpMpiCmd(devId, EC_1, VP880_R_FILTER_WRT, VP880_R_FILTER_LEN, writeData);
+		VpMpiCmd(devId, EC_1, VP880_R_FILTER_RD, VP880_R_FILTER_LEN, readData);
+		for (i = 0; i < VP880_R_FILTER_LEN; i++) {
+			if (writeData[i] != readData[i]) {
+				mvOsPrintf("Failed MPI test 1-%d on devId 0x%X", x, devId);
+				return -1;
+			}
+		}
+	}
+
+	for (x = 0; x <= 0xFF; x++) {
+		y = x % 0x10;
+		for (i = 0; i < VP880_R_FILTER_LEN; i++) {
+			writeData[i] = y << 4;
+			y = (y + 1) % 0x10;
+			writeData[i] |= y;
+			y = (y + 1) % 0x10;
+		}
+		VpMpiCmd(devId, EC_1, VP880_R_FILTER_WRT, VP880_R_FILTER_LEN, writeData);
+		VpMpiCmd(devId, EC_1, VP880_R_FILTER_RD, VP880_R_FILTER_LEN, readData);
+		for (i = 0; i < VP880_R_FILTER_LEN; i++) {
+			if (writeData[i] != readData[i]) {
+				mvOsPrintf("Failed MPI test 2-%d on devId 0x%X", x, devId);
+				return -1;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/hbi_hal.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/hbi_hal.h
new file mode 100755
index 0000000..57cc87d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/hbi_hal.h
@@ -0,0 +1,45 @@
+/* hbi_hal.h
+ *
+ * This file defines the interface between the VoicePath API and the Hardware
+ * Abstraction Layer (HAL).  The types and functions declared in this file are
+ * platform-dependent. Porting the VoicePath API to a new host processor
+ * consists of modifying the typedefs in this file, setting the HBI_PINCONFIG
+ * define below, and modifying the function implementations in vp_hal.c.
+ *
+ * Copyright (c) 2008, Zarlink Semiconductor, Inc.
+ */
+#ifndef HBI_HAL_H
+#define HBI_HAL_H
+#include "vp_api_types.h"
+/* Define the EXTERN macro, if necessary */
+#ifndef EXTERN
+  #ifdef __cplusplus
+    #define EXTERN extern "C"
+  #else
+    #define EXTERN extern
+  #endif /* __cplusplus */
+#endif /* EXTERN */
+/******************************************************************************
+ *                          PLATFORM-SPECIFIC OPTIONS                         *
+ ******************************************************************************/
+/* HBI configuration register */
+#define HBI_CFG_ENDLITTLE       0    /* 1=byte swapping for data words only */
+#define HBI_CFG_PWAIT_POLHI     0    /* 0=PWAIT pin active low, 1=PWAIT pin active high */
+#define HBI_CFG_PWAIT_EN        0    /* 0=PWAIT pin disabled, 1=PWAIT pin enabled */
+#define HBI_CFG_PWAIT_MODEOSD   0    /* 0=PWAIT pin TTL, 1=PWAIT pin open source/drain */
+#define HBI_CFG_INT_MODETTL     1    /* 0=INT pin open drain, 1=INT pin TTL */
+#define HBI_CFG_PINEA           0    /* 0=IO[2:0], 1=EA[10:8] */
+#define HBI_PINCONFIG   (HBI_CFG_ENDLITTLE | (HBI_CFG_PWAIT_POLHI << 1) | (HBI_CFG_PWAIT_EN << 2) | \
+			 (HBI_CFG_PWAIT_MODEOSD << 3) | (HBI_CFG_INT_MODETTL << 4) | (HBI_CFG_PINEA << 5))
+#define HBI_CMD_CONFIGURE_INT	0xFD00
+#define DEFAULT_DEVICE_ID	0
+/******************************************************************************
+ *                         PLATFORM-SPECIFIC FUNCTIONS                        *
+ ******************************************************************************/
+/* See vp_hal.c for descriptions. */
+EXTERN uint8 VpHalHbiInit(VpDeviceIdType deviceId);
+EXTERN uint8 VpHalHbiCmd(VpDeviceIdType deviceId, uint16 cmd);
+EXTERN uint8 VpHalHbiWrite(VpDeviceIdType deviceId, uint16 cmd, uint8 numwords, uint16p data);
+EXTERN uint8 VpHalHbiRead(VpDeviceIdType deviceId, uint16 cmd, uint8 numwords, uint16p data);
+#endif /* HBI_HAL_H */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/mpi_hal.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/mpi_hal.h
new file mode 100755
index 0000000..f84c44b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/mpi_hal.h
@@ -0,0 +1,20 @@
+/** \file mpi_hal.h
+ * mpi_hal.h
+ *
+ * Header file for the VP-API-II c files requiring MPI interface.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ */
+#ifndef MPI_UVB_HAL_H
+#define MPI_UVB_HAL_H
+#include "vp_api_types.h"
+
+EXTERN void
+VpMpiCmd(
+    VpDeviceIdType deviceId,
+    uint8 ecVal,
+    uint8 cmd,
+    uint8 cmdLen,
+    uint8 *dataPtr);
+#endif
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/sys_service.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/sys_service.c
new file mode 100755
index 0000000..a45d28b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/sys_service.c
@@ -0,0 +1,216 @@
+/** \file sys_service.c
+ * sys_service.c
+ *
+ *  This file implements the required system services for the API-II using a
+ * Linux OS running on the UVB.  The user should replace the functions provided
+ * here with the equivalent based on their OS and hardware.
+ *
+ * Copyright (c) 2008, Zarlink Semiconductor, Inc.
+ */
+#include "vp_api_types.h"
+#include "sys_service.h"
+/*
+ * VpSysWait() function implementation is needed only for CSLAC devices
+ * (880, 790). For other devices this function could be commented.
+ */
+void
+VpSysWait(
+    uint8 time)  /* Time specified in increments of 125uS (e.g. 4 = 500uS) */
+{
+	mvOsUDelay(125 * time);
+}
+void VpSysSemaphoreInit(int semaphoreId)
+{
+}
+
+/*
+ * VpSysEnterCritical(), VpSysExitCritical():
+ *
+ *  These functions allow for disabling interrupts while executing nonreentrant
+ * portions of VoicePath API code. Note that the following implementations of
+ * enter/exit critical section functions are simple implementations. These
+ * functions could be expanded (if required) to handle different critical
+ * section types differently.
+ *
+ * Params:
+ *  VpDeviceIdType deviceId: Device Id (chip select ID)
+ *  VpCriticalSecType: Critical section type
+ *
+ * Return:
+ *  Number of critical sections currently entered for the device.
+ */
+uint8
+VpSysEnterCritical(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType)
+{
+    /*
+     * Code to check if semaphore can be taken, and if so increment. Block if
+     * semaphore cannot be taken for this process ID.
+     */
+    /*
+     * criticalDepth++;
+     * return criticalDepth;
+     */
+    /* Prevent compiler from generating error */
+    return 1;
+} /* VpSysEnterCritical() */
+uint8
+VpSysExitCritical(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType)
+{
+    /* Code to decrement semaphore */
+    /*
+     * criticalDepth--;
+     * return criticalDepth;
+     */
+    /* Prevent compiler from generating error */
+    return 0;
+} /* VpSysExitCritical() */
+/**
+ * VpSysDisableInt(), VpSysEnableInt(), and VpSysTestInt()
+ *
+ *  These functions are used by the CSLAC device family for interrupt driven
+ * polling modes. These are called by the API to detect when a non-masked
+ * device status has changed.  If using SIMPLE_POLL mode, these functions do not
+ * require implementation.
+ *
+ * Preconditions:
+ *  None. The implementation of these functions is architecture dependent.
+ *
+ * Postconditions:
+ *  VpSysDisableInt() - The interrupt associated with the deviceId passed is
+ * disabled.
+ *
+ * VpSysEnableInt() - The interrupt associated with the deviceId passed is
+ * enabled.
+ *
+ * VpSysTestInt() - The return value is TRUE if an interrupt occurred, otherwise
+ * return FALSE.
+ *
+ * These functions are needed only for CSLAC devices
+ * (880, 790). For other devices these functions could be commented.
+ *
+ */
+void
+VpSysDisableInt(
+    VpDeviceIdType deviceId)
+{
+    mvSysTdmIntDisable((unsigned char)deviceId);
+}
+void
+VpSysEnableInt(
+    VpDeviceIdType deviceId)
+{
+    mvSysTdmIntEnable((unsigned char)deviceId);
+}
+bool
+VpSysTestInt(
+    VpDeviceIdType deviceId)
+{
+    return FALSE;
+}
+/**
+ * VpSysDtmfDetEnable(), VpSysDtmfDetDisable()
+ *
+ *  These functions are used by the CSLAC device family for devices that do not
+ * internally detect DTMF. It is used for Caller ID type-II and is provided to
+ * enable external DTMF detection.
+ *
+ * Preconditions:
+ *  None. The implementation of these functions is application dependent.
+ *
+ * Postconditions:
+ *  VpSysDtmfDetEnable() - The device/channel resource for DTMF detection is
+ * enabled.
+ *
+ *  VpSysDtmfDetDisable() - The device/channel resource for DTMF detection is
+ * disabled.
+ *
+ * These functions are needed only for CSLAC devices
+ * (880, 790). For other devices these functions could be commented.
+ *
+ */
+void
+VpSysDtmfDetEnable(
+    VpDeviceIdType deviceId,
+    uint8 channelId)
+{
+}
+void
+VpSysDtmfDetDisable(
+    VpDeviceIdType deviceId,
+    uint8 channelId)
+{
+}
+/*
+ * The following functions VpSysTestHeapAcquire(),  VpSysTestHeapRelease()
+ * VpSysPcmCollectAndProcess() and are needed only for CSLAC devices
+ * (880). For other devices these functions could be commented. Please see
+ * the LineTest API documentation for function requirements.
+ */
+void *
+VpSysTestHeapAcquire(
+    uint8 *pHeapId)
+{
+    return VP_NULL;
+} /* VpSysTestHeapAcquire() */
+bool
+VpSysTestHeapRelease(
+    uint8 heapId)
+{
+    return TRUE;
+} /* VpSysTestHeapRelease() */
+void
+VpSysPcmCollectAndProcess(
+    void *pLineCtx,
+    VpDeviceIdType deviceId,
+    uint8 channelId,
+    uint8 startTimeslot,
+    uint16 operationTime,
+    uint16 settlingTime,
+    uint16 operationMask)
+{
+} /* VpSysPcmCollectAndProcess() */
+
+#ifdef ENABLE_DBG_TAG
+int
+VpSysDebugPrintf(
+    const char *format, ...)
+{
+    va_list ap;
+    static char buf[1024];
+    static uint16 indexBuf;
+    static bool beginLine = TRUE;
+    uint16 bufLen;
+    int retval;
+
+    if (beginLine == TRUE) {
+	mvOsPrintf("<DBG> ");
+	beginLine = FALSE;
+    }
+    /* print in a string to check if there's a \n */
+    va_start(ap, format);
+    retval = vsprintf(&buf[indexBuf], format, ap);
+    va_end(ap);
+
+    bufLen = strlen(&buf[indexBuf]);
+    if (buf[indexBuf + bufLen - 1] == '\n') {
+		buf[indexBuf + bufLen - 1] = ' ';
+		retval = mvOsPrintf("%s</DBG>\n", buf);
+		indexBuf = 0;
+		beginLine = TRUE;
+    } else {
+		indexBuf += bufLen;
+
+		/* Just in case of a buffer overflow, not suppose to append */
+		if (indexBuf > 800) {
+			retval = mvOsPrintf("%s</DBG>\n", buf);
+			indexBuf = 0;
+			beginLine = TRUE;
+		}
+      }
+    return retval;
+}
+#endif /* ENABLE_DBG_TAG */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/sys_service.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/sys_service.h
new file mode 100755
index 0000000..42fd5dc
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/sys_service.h
@@ -0,0 +1,84 @@
+/*
+ * sys_service.h
+ *
+ *  This file is the header for all standard types used in the API code.
+ *
+ * Copyright (c) 2008, Zarlink Semiconductor, Inc.
+ */
+
+#ifdef MV_KERNEL_SLIC_SUPPORT
+
+#ifndef SYS_SERVICE_H
+#define SYS_SERVICE_H
+#include "vp_api_types.h"
+#include "vp_api_cfg.h"
+#include "voiceband/mvSysTdmSpi.h"
+
+/* Critical section types */
+typedef enum {
+	VP_MPI_CRITICAL_SEC, 	/* MPI access critical code section */
+	VP_HBI_CRITICAL_SEC, 	/* HBI access critical code section */
+	VP_CODE_CRITICAL_SEC, 	/* Critical code section */
+	VP_NUM_CRITICAL_SEC_TYPES, /* The number of critical section types */
+    VP_CRITICAL_SEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCriticalSecType;
+EXTERN uint8
+VpSysEnterCritical(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+EXTERN uint8
+VpSysExitCritical(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+EXTERN void
+VpSysWait(
+    uint8 time);
+EXTERN void
+VpSysDisableInt(
+    VpDeviceIdType deviceId);
+EXTERN void
+VpSysEnableInt(
+    VpDeviceIdType deviceId);
+EXTERN bool
+VpSysTestInt(
+    VpDeviceIdType deviceId);
+EXTERN void
+VpSysDtmfDetEnable(
+    VpDeviceIdType deviceId,
+    uint8 channelId);
+EXTERN void
+VpSysDtmfDetDisable(
+    VpDeviceIdType deviceId,
+    uint8 channelId);
+
+EXTERN void *
+VpSysTestHeapAcquire(
+    uint8 *pHeapId);
+EXTERN bool
+VpSysTestHeapRelease(
+    uint8 heapId);
+EXTERN void
+VpSysPcmCollectAndProcess(
+    void *pLineCtx,
+    VpDeviceIdType deviceId,
+    uint8 channelId,
+    uint8 startTimeslot,
+    uint16 operationTime,
+    uint16 settlingTime,
+    uint16 operationMask);
+
+/* Enable the XML tag <DBG> debug output </DBG>  */
+/* #define ENABLE_DBG_TAG */
+
+#ifdef ENABLE_DBG_TAG
+    EXTERN int
+    VpSysDebugPrintf(
+		const char *format, ...);
+#else
+    #define VpSysDebugPrintf mvOsPrintf
+#endif /* ENABLE_DBG_TAG */
+
+#endif /* SYS_SERVICE_H */
+
+#endif /* MV_KERNEL_SLIC_SUPPORT */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_api_profile_type.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_api_profile_type.h
new file mode 100755
index 0000000..63a8563
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_api_profile_type.h
@@ -0,0 +1,14 @@
+/** \file vp_api_profile_type.h
+ * vp_api_profile_type.h
+ *
+ * Header file for the VpProfileDataType typedef.  If using the API "apitypes",
+ * this file is automatically included.  Otherwise, this type is defined in the
+ * header file output from the Profile Wizard (app should include).
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ */
+#ifndef API_PROFILE_TYPE_H
+#define API_PROFILE_TYPE_H
+typedef unsigned char VpProfileDataType;
+#endif
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_api_types.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_api_types.h
new file mode 100755
index 0000000..a8ff1c5
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_api_types.h
@@ -0,0 +1,99 @@
+/** \file vp_api_types.h
+ * vp_api_types.h
+ *
+ *  This file is the header for all standard types used in the API code.
+ *
+ * Copyright (c) 2008, Zarlink Semiconductor, Inc.
+ */
+#ifndef VP_API_TYPES_H
+#define VP_API_TYPES_H
+#include "vp_api_profile_type.h"
+
+/* For maximum that can be stored in an int - if file exists in library */
+//#include "limits.h"
+/* VpDeviceIdType defines the type for the deviceId in the VpDevCtxType type.
+ * This information is passed through the API to the HAL to communicate
+ * with a specific device.  The values assigned via VpMakeDeviceObject()
+ * are user defined and may be simple device indexing (0, 1, .. (n-1)):
+ * where n = device number in system
+ */
+typedef unsigned char VpDeviceIdType;
+/*
+ * The 'VpLineIdType'  defines a system wide Line identification that the system
+ * could use to identify a line. This type can be defined to contain anything
+ * that the customer chooses. It could be defined to contain just an index or
+ * a pointer. The system wide line identity could be set using the
+ * VpMapLineId() function for a given line. The VP-API returns this line id
+ * information when line specific events occur (along with the event).
+ */
+typedef unsigned char VpLineIdType;
+#ifndef NULL
+    #define NULL (0)
+#endif
+#define VP_NULL NULL
+#ifdef EXTERN
+  #undef EXTERN
+  #error EXTERN was redefined!
+#endif /* undef EXTERN */
+#ifdef __cplusplus
+  #define EXTERN extern "C"
+#else
+  #define EXTERN extern
+#endif /* __cplusplus */
+/********************* DECLARATIONS ***************************/
+/* Constants */
+#ifndef FALSE
+#define FALSE   (0)     /* Boolean constant */
+#define TRUE    (1)     /* Boolean constant */
+#endif
+#ifndef __cplusplus
+/* C++ language provides a boolean data type; So no need to define
+ * one more data type; Make use of it
+ * NOTE: The 'C' potions of the VP-API assume C++ "bool" to be of the
+ * same size as that of "char". Please make sure this assumption is correct.
+ */
+//typedef unsigned char bool;
+#endif /* __cplusplus */
+/****************** typedefs ***********************************/
+/* These are the basic number types used */
+/* for uint8, uint16, uint32, int8, int16, int32, bool */
+typedef unsigned char   uchar;
+typedef unsigned char   uint8;
+typedef unsigned short  uint16;
+typedef unsigned long   uint32;
+typedef signed char    int8;
+typedef signed short int int16;
+typedef signed long  int32;
+typedef   uint8*  uint8p;
+typedef   uint16* uint16p;
+typedef   uint32* uint32p;
+typedef   int8*   int8p;
+typedef   int16*  int16p;
+typedef   int32*  int32p;
+typedef const VpProfileDataType * VpProfilePtrType;
+typedef uint8p VpImagePtrType;
+typedef uint16p VpVectorPtrType;
+typedef uint8 VpPktDataType;
+typedef VpPktDataType* VpPktDataPtrType;
+/* Some compilers optimize the size of enumeration data types based on
+ * the maximum data value assigned to the members of that data type.
+ * 'Standard C' requires enumeration data types to be of the same size
+ * as that of native 'int' implementation.
+ * The VP-API from a portability persepective adds a 'dummy' member to
+ * all enumeration data types that force the compilers to allocate the size
+ * of enumeration data types to be equal to that of native 'int'
+ * implementation */
+#define FORCE_STANDARD_C_ENUM_SIZE  ((int)(~0U>>1))
+
+/* Eliminate error messages that occur when comparing an enumeration constant
+   < 0 */
+#define FORCE_SIGNED_ENUM  (-FORCE_STANDARD_C_ENUM_SIZE - 1)
+
+
+/* Define any API specific basic data type ranges (that are necessary) */
+#define VP_INT16_MAX    ((short)(~0U>>1))
+#define VP_INT16_MIN    (-VP_INT16_MAX - 1)
+#define VP_INT32_MAX    ((long)(~0UL>>1))
+#define VP_INT32_MIN    (-VP_INT32_MAX - 1)
+#endif /* VP_API_TYPES_H */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_hal.c b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_hal.c
new file mode 100755
index 0000000..abf9b5a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_hal.c
@@ -0,0 +1,249 @@
+/** \file vp_hal.c
+ * vp_hal.c
+ *
+ * This file contains the platform dependent code for the Hardware Abstraction
+ * Layer (HAL). This is example code only to be used by the customer to help
+ * clarify HAL requirements.
+ *
+ * Copyright (c) 2008, Zarlink Semiconductor, Inc.
+ */
+
+#include "mpi_hal.h"
+#include "hbi_hal.h"
+#include "voiceband/mvSysTdmSpi.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt, arg...)	mvOsPrintf(KERN_INFO fmt, ##arg)
+#else
+#define DBG(fmt, arg...)
+#endif
+
+/* MPI */
+#define READ_COMMAND			1
+#define CSLAC_EC_REG_RD			0x4B   /* Same for all CSLAC devices */
+#define CSLAC_EC_REG_WRT		0x4A   /* Same for all CSLAC devices */
+#define MPI_MAX_CMD_LEN			255
+
+/* HBI */
+#define HBI_CMD_BYTES			2
+#define HBI_DATA_BYTES(numWords)	((numWords + 1) * 2)
+#define HBI_MAX_DATA_LEN		256
+
+uint16 readBuff[HBI_MAX_DATA_LEN];
+uint16 writeBuff[HBI_MAX_DATA_LEN];
+
+/**
+ * VpHalHbiInit(): Configures the HBI bus and glue logic (if any)
+ *
+ * This function performs any tasks necessary to prepare the system for
+ * communicating through the HBI, including writing the HBI configuration
+ * register.  The HBI read and write functions should work after HbiHalInit()
+ * is successfully executed. HbiHalInit() should be well-behaved even if called
+ * more than once between system resets. HbiHalInit() is called from
+ * VpBootLoad() since VpBootLoad() is normally the first VoicePath function
+ * that the host application will call.
+ *
+ * This function is called by VpBootLoad() before sending the VCP firmware
+ * image through the HBI.
+ *
+ * Params:
+ *  uint8 deviceId: Device Id (chip select ID)
+ *
+ * Returns:
+ *  This function returns FALSE if some error occurred during HBI initialization
+ *  or TRUE otherwise.
+ */
+uint8 VpHalHbiInit(
+    VpDeviceIdType deviceId)
+{
+	return TRUE;
+} /* VpHalHbiInit() */
+
+/**
+ * VpHalHbiCmd(): Sends a command word over the HBI, with no data words.
+ *
+ *  Accepts a uint16 HBI command which is little-endian or big-endian,
+ * depending on the host architecture.  Command words on the HBI bus are always
+ * big-endian. This function is responsible for byte-swapping if required.
+ *
+ * Params:
+ * uint8 deviceId: Device Id (chip select ID)
+ * uint16 cmd: the command word to send
+ *
+ * Returns:
+ *   TRUE on success, FALSE on failure
+ */
+uint8 VpHalHbiCmd(
+    VpDeviceIdType deviceId,
+    uint16 cmd)
+{
+	uint16 cmdSwapped = MV_16BIT_BE(cmd);
+
+	DBG("%s: WRITE(cmd-0x%x)\n", __func__, cmd);
+	mvSysTdmSpiWrite(deviceId, (uint8p)&cmdSwapped, HBI_CMD_BYTES, NULL, 0);
+
+	return TRUE;
+} /* VpHalHbiCmd() */
+
+/**
+ * VpHalHbiWrite(): Sends a command word and up to 256 data words over the HBI.
+ *
+ *  Accepts a uint16 HBI command which is little-endian or big-endian, depending
+ * on the host architecture.  Command words on the HBI bus are always big-
+ * endian.  This function is responsible for byte-swapping the command word, if
+ * required.
+ *
+ *  Accepts an array of uint16 data words.  No byte-swapping is necessary on
+ * data words in this function.  Instead, the HBI bus can be configured in
+ * VpHalHbiInit() to match the endianness of the host platform.
+ *
+ * Params:
+ *   uint8 deviceId: Device Id (chip select ID)
+ *   uint16 cmd: the command word to send
+ *   uint8 numwords: the number of data words to send, minus 1
+ *   uint16p data: the data itself; use data = (uint16p)0 to send
+ *      zeroes for all data words
+ *
+ * Returns:
+ *   TRUE on success, FALSE on failure
+ */
+uint8 VpHalHbiWrite(
+    VpDeviceIdType deviceId,
+    uint16 cmd,
+    uint8 numwords,
+    uint16p data)
+{
+	uint8 i;
+	uint16 cmdSwapped = MV_16BIT_BE(cmd);
+	uint16p pWriteBuff = &writeBuff[0];
+
+	if ((numwords + 1) > HBI_MAX_DATA_LEN) {
+		mvOsPrintf("%s: Error, HBI data length too big(%u)\n", __func__, (numwords + 1));
+		return FALSE;
+	}
+
+	for (i = 0; i < (numwords + 1); i++)
+		pWriteBuff[i] = MV_16BIT_BE(data[i]);
+
+	DBG("%s: WRITE(cmd-0x%x), (size-%d bytes)\n", __func__, cmd, HBI_DATA_BYTES(numwords));
+	mvSysTdmSpiWrite(deviceId, (uint8p)&cmdSwapped, HBI_CMD_BYTES, (uint8p)pWriteBuff, HBI_DATA_BYTES(numwords));
+
+	return TRUE;
+} /* VpHalHbiWrite() */
+
+/**
+ * VpHalHbiRead(): Sends a command, and receives up to 256 data words over the
+ * HBI.
+ *
+ *  Accepts a uint16 HBI command which is little-endian or big-endian, depending
+ * on the host architecture.  Command words on the HBI bus are always big-
+ * endian.  This function is responsible for byte-swapping the command word, if
+ * required.
+ *
+ * Retrieves an array of uint16 data words.  No byte-swapping is necessary on
+ * data words in this function.  Instead, the HBI bus can be configured in
+ * VpHalHbiInit() to match the endianness of the host platform.
+ *
+ * Params:
+ *   uint8 deviceId: Device Id (chip select ID)
+ *   uint8 numwords: the number of words to receive, minus 1
+ *   uint16p data: where to put them
+ *
+ * Returns:
+ *   TRUE on success, FALSE on failure
+ */
+uint8 VpHalHbiRead(
+    VpDeviceIdType deviceId,
+    uint16 cmd,
+    uint8 numwords,
+    uint16p data)
+{
+	uint8 i;
+	uint16 cmdSwapped = MV_16BIT_BE(cmd);
+	uint16p pReadBuff = &readBuff[0];
+
+	if ((numwords + 1) > HBI_MAX_DATA_LEN) {
+		mvOsPrintf("%s: Error, HBI data length too big(%u)\n", __func__, (numwords + 1));
+		return FALSE;
+	}
+
+	DBG("%s: READ(cmd-0x%x), (size-%d bytes)\n", __func__, cmd, HBI_DATA_BYTES(numwords));
+	mvSysTdmSpiRead(deviceId, (uint8p)&cmdSwapped, HBI_CMD_BYTES, (uint8p)pReadBuff, HBI_DATA_BYTES(numwords));
+
+	for (i = 0; i < (numwords + 1); i++)
+		data[i] = MV_16BIT_BE(pReadBuff[i]);
+
+	return TRUE;
+
+} /* VpHalHbiRead() */
+
+
+/*****************************************************************************
+ * HAL functions for CSLAC devices. Not necessary for VCP
+ ****************************************************************************/
+/**
+ * VpMpiCmd()
+ *  This function executes a Device MPI command through the MPI port. It
+ * executes both read and write commands. The read or write operation is
+ * determined by the "cmd" argument (odd = read, even = write). The caller must
+ * ensure that the data array is large enough to hold the data being collected.
+ * Because this command used hardware resources, this procedure is not
+ * re-entrant.
+ *
+ * Note: For API-II to support multi-threading, this function has to write to
+ * the EC register of the device to set the line being controlled, in addition
+ * to the command being passed. The EC register write/read command is the same
+ * for every CSLAC device and added to this function. The only exception is
+ * if the calling function is accessing the EC register (read), in which case
+ * the EC write cannot occur.
+ *
+ * This example assumes the implementation of two byte level commands:
+ *
+ *    MpiReadByte(VpDeviceIdType deviceId, uint8 *data);
+ *    MpiWriteByte(VpDeviceIdType deviceId, uint8 data);
+ *
+ * Preconditions:
+ *  The device must be initialized.
+ *
+ * Postconditions:
+ *   The data pointed to by dataPtr, using the command "cmd", with length
+ * "cmdLen" has been sent to the MPI bus via the chip select associated with
+ * deviceId.
+ */
+void
+VpMpiCmd(
+    VpDeviceIdType deviceId,    /* Chip select */
+    uint8 ecVal,        	/* Value to write to the EC register */
+    uint8 cmd,          	/* Command number */
+    uint8 cmdLen,       	/* Number of bytes used by command (cmd) */
+    uint8 *dataPtr)     	/* Pointer to the data location */
+{
+
+    uint8 cmdBuff[4];
+    uint8 cmdSize = 0;
+    uint8 isRead = (cmd & READ_COMMAND);
+
+     if (cmdLen > MPI_MAX_CMD_LEN)
+	mvOsPrintf("Error, MPI data length too big(%u)\n", cmdLen);
+
+    /* If a EC read is being preformed don't set the EC register */
+    if (CSLAC_EC_REG_RD != cmd) {
+	/* Write the EC register value passed to the device */
+	cmdBuff[cmdSize++] = CSLAC_EC_REG_WRT;
+	cmdBuff[cmdSize++] = ecVal;
+    }
+
+    /* Write the command byte to MPI. */
+    cmdBuff[cmdSize++] = cmd;
+
+    if (isRead) {
+	DBG("%s: READ - cmdSize=%d, dataSize=%d\n", __func__, cmdSize, cmdLen);
+	mvSysTdmSpiRead(deviceId, cmdBuff, cmdSize, dataPtr, cmdLen);
+    } else {
+	DBG("%s: WRITE - cmdSize=%d, dataSize=%d\n", __func__, cmdSize, cmdLen);
+	mvSysTdmSpiWrite(deviceId, cmdBuff, cmdSize, dataPtr, cmdLen);
+    }
+
+    return;
+} /* End VpMpiCmd */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_hal.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_hal.h
new file mode 100755
index 0000000..3e8f510
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/vp_hal.h
@@ -0,0 +1,19 @@
+/* vp_hal.h
+ *
+ * This file defines the interface between the VoicePath API and the Hardware
+ * Abstraction Layer (HAL).  The types and functions declared in this file are
+ * platform-dependent.  The functions are defined in ve_hal.c.  Porting the
+ * VoicePath API to a new host processor consists of modifying the typedefs
+ * in this file, setting the HBI_PINCONFIG define below, and modifying the
+ * function implementations in vp_hal.c.
+ *
+ * Copyright (c) 2008, Zarlink Semiconductor, Inc.
+ */
+#ifndef _VP_HAL_H
+#define _VP_HAL_H
+#include "vp_api_types.h"
+#include "mpi_hal.h"
+#include "hbi_hal.h"
+#include "sys_service.h"
+#endif /* _VP_HAL_H */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/boot_common.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/boot_common.h
new file mode 100755
index 0000000..e6ad378
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/boot_common.h
@@ -0,0 +1,59 @@
+/** \file boot_common.h
+ * boot_common.h
+ *
+ * Header file for the VP-API-II c files.
+ *
+ * This file contains all of the VP-API-II declarations that are Voice
+ * Termination Device (VTD) family independent.	The implementation in this file
+ * is applicable to VCP classes of devices.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 6419 $
+ * $LastChangedDate: 2010-02-12 16:40:10 -0600 (Fri, 12 Feb 2010) $
+ */
+
+#ifndef BOOT_COMMON_H
+#define BOOT_COMMON_H
+
+#include "vp_api_types.h"
+#include "hbi_common.h"
+
+/******************************************************************************
+ *                              TYPE DEFINITIONS                              *
+ ******************************************************************************/
+
+typedef bool (*VpBootSupportFuncPtrType) (VpDeviceIdType deviceId);
+
+
+/******************************************************************************
+ *                             FUNCTION PROTOTYPES                            *
+ ******************************************************************************/
+/*
+ * Initialization functions
+ */
+EXTERN VpStatusType
+VpVcpVppBootLoad(
+	VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+EXTERN VpStatusType
+VpBootLoadInternal(
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation,
+    VpDeviceIdType deviceId,
+    uint16p pRecCnt,
+    VpBootSupportFuncPtrType haltFunc,
+    VpBootSupportFuncPtrType validateFunc);
+
+#endif /* BOOT_COMMON_H */
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/hbi_common.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/hbi_common.h
new file mode 100755
index 0000000..ec07b27
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/hbi_common.h
@@ -0,0 +1,90 @@
+/** \file hbi_common.h
+ * hbi_common.h
+ *
+ * This file declares the VCP Host Bus Interface layer register/mail box
+ * mapping.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 6419 $
+ * $LastChangedDate: 2010-02-12 16:40:10 -0600 (Fri, 12 Feb 2010) $
+ */
+
+#ifndef _HBI_COMMON_H
+#define _HBI_COMMON_H
+
+#include "vp_hal.h"
+
+/******************************************************************************
+ *                        	LOW_LEVEL HBI DEFINES		                      *
+ ******************************************************************************/
+#define VP_HBI_PAGE_SIZE            0x80
+
+#define VP_DP 254    /* magic page number indicating direct page */
+
+/* HBI commands: */
+#define HBI_CMD_PAGED_READ(offset, length)   (0x0000 + ((uint16)offset << 8) + \
+                                                length)
+#define HBI_CMD_PAGED_WRITE(offset, length)  (0x0080 + ((uint16)offset << 8) + \
+                                                length)
+#define HBI_CMD_DIRECT_READ(offset, length)  (0x8000 + ((uint16)offset << 8) + \
+                                                length)
+#define HBI_CMD_DIRECT_WRITE(offset, length) (0x8080 + ((uint16)offset << 8) + \
+                                                length)
+#define HBI_CMD_START_MBOX_RD(length)        (0xF800 + length)
+#define HBI_CMD_START_MBOX_WR(length)        (0xF900 + length)
+#define HBI_CMD_CONT_MBOX_RD(length)         (0xFA00 + length)
+#define HBI_CMD_CONT_MBOX_WR(length)         (0xFB00 + length)
+#define HBI_CMD_CONFIGURE(options)           (0xFD00 + options)
+#define HBI_CMD_SELECT_PAGE(page)            (0xFE00 + page)
+#define HBI_CMD_NOP                          0xFFFF
+
+/******************************************************************************
+ *                 REGISTERS SHARED BY VCP DEVICES                            *
+ ******************************************************************************/
+#define HW_Reg_INTIND           VP_DP,  0x00,   0
+#define HW_Reg_INTPARAM         VP_DP,  0x01,   0
+#define HW_Reg_INTIND_AND_INTPARAM         VP_DP,  0x00,   1
+#define HW_Reg_MBOXFLAG         VP_DP,  0x02,   0
+#define HW_Reg_CRC255           VP_DP,  0x03,   0
+#define HW_Reg_BASE255          VP_DP,  0x04,   0
+#define HW_Reg_MBOFFSET         VP_DP,  0x05,   0
+#define HW_Reg_HWRES            VP_DP,  0x06,   0
+#define HW_Reg_PCLKSEL          VP_DP,  0x07,   0
+#define HW_Reg_PCMCLKSLOT       VP_DP,  0x08,   0
+#define HW_Reg_SYSINTSTAT       VP_DP,  0x09,   0
+#define HW_Reg_SYSINTMASK       VP_DP,  0x0A,   0
+
+/******************************************************************************
+ *                        FUNCTION PROTOTYPES			                      *
+ ******************************************************************************/
+EXTERN bool VpHbiRd8(VpDeviceIdType deviceId, uint8 page, uint8 offset,
+                        uint8 words, uint8p pDest);
+EXTERN bool VpHbiWr8(VpDeviceIdType deviceId, uint8 page, uint8 offset,
+                        uint8 words, uint8p pSrc);
+EXTERN bool VpHbiRd(VpDeviceIdType deviceId, uint8 page, uint8 offset,
+                        uint8 words, uint16p pDest);
+EXTERN bool VpHbiWr(VpDeviceIdType deviceId, uint8 page, uint8 offset,
+                        uint8 words, uint16p pSrc);
+EXTERN bool VpHbiXfer(bool readWrite, VpDeviceIdType deviceId,
+                        uint32 ambaAddr, uint32 length, uint16p data,
+                        uint8 byteAddressable,
+                        bool (*SetCodeLoadBase)(VpDeviceIdType deviceId, uint32 amba_addr));
+
+EXTERN bool VpHbiVcpVppValidate(VpDeviceIdType deviceId);
+EXTERN bool VpHbiVcpVppReset(VpDeviceIdType deviceId);
+EXTERN bool VpHbiVcpVppClearCodeMem(VpDeviceIdType deviceId);
+EXTERN bool VpHbiVcpVppHalt(VpDeviceIdType deviceId);
+EXTERN bool VpHbiVcpVppSetBase255(VpDeviceIdType deviceId, uint32 amba_addr);
+EXTERN bool VpHbiVcpVppAmbaRdWr(bool readWrite, VpDeviceIdType deviceId,
+                        uint32 amba_addr, uint32 numwords, uint16p data);
+EXTERN bool VpHbiSetBase255(VpDeviceIdType deviceId, uint32 amba_addr, uint16p base255reg);
+#define VpHbiAmbaRdWr(readWrite, deviceId, amba_addr, numwords, pData) \
+    VpHbiVcpVppAmbaRdWr(readWrite, deviceId, amba_addr, numwords, pData)
+#define VpHbiAmbaWrite(deviceId, amba_addr, numwords, pData) \
+    VpHbiVcpVppAmbaRdWr(TRUE, deviceId, amba_addr, numwords, pData)
+#define VpHbiAmbaRead(deviceId, amba_addr, numwords, pData) \
+    VpHbiVcpVppAmbaRdWr(FALSE, deviceId, amba_addr, numwords, pData)
+
+#endif /* _HBI_COMMON_H */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp792_api.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp792_api.h
new file mode 100755
index 0000000..2d36a83
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp792_api.h
@@ -0,0 +1,472 @@
+/** \file vp792_api.h
+ * vp792_api.h
+ *
+ *  Header file that define all the commands for the Vp792 device.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8475 $
+ * $LastChangedDate: 2011-04-05 11:30:04 -0500 (Tue, 05 Apr 2011) $
+ */
+
+#ifndef VP792_API_H
+#define VP792_API_H
+
+#define VP792_MIN_SLAC_ID       0
+#define VP792_MAX_SLAC_ID       7
+
+#define VP792_MAX_OUTSTANDING_RESPONSES         10
+
+/* Maximum number of profiles of each type in the Profile Table: */
+#define VP_792_DEV_PROF_TABLE_SIZE              1
+#define VP_792_AC_PROF_TABLE_SIZE               2
+#define VP_792_DC_PROF_TABLE_SIZE               2
+#define VP_792_RINGING_PROF_TABLE_SIZE          2
+#define VP_792_TONE_CADENCE_PROF_TABLE_SIZE     11
+#define VP_792_TONE_PROF_TABLE_SIZE             10
+#define VP_792_RING_CADENCE_PROF_TABLE_SIZE     4
+#define VP_792_METERING_PROF_TABLE_SIZE         2
+#define VP_792_CALLERID_PROF_TABLE_SIZE         2
+
+/* Maximum length of each type of profile (bytes): */
+#define VP792_DEV_PROFILE_LEN               45
+#define VP792_DC_PROFILE_LEN                44
+#define VP792_AC_PROFILE_LEN                128
+#define VP792_CID_PROFILE_LEN               200
+#define VP792_MTR_PROFILE_LEN               22
+#define VP792_TONE_PROFILE_LEN              32
+#define VP792_RINGCAD_PROFILE_LEN           72
+#define VP792_TONECAD_PROFILE_LEN           72
+#define VP792_RING_PROFILE_LEN              38
+
+/* Lengths of profile sections that need to be stored or otherwise handled
+ * separately from the whole. (words) */
+#define VP792_AC_PROFILE_REGDATA_LEN        1
+#define VP792_DC_PROFILE_REGDATA_LEN        22
+#define VP792_RING_PROFILE_REGDATA_LEN      34
+
+typedef enum
+{
+  VP_792_SEQ_OFF,
+  VP_792_SEQ_RING,
+  VP_792_SEQ_TONE,
+  VP_792_SEQ_OTHER
+} Vp792SequencerUseType;
+
+#include "vp_hal.h"
+
+/* Struct for the Profile Table: */
+typedef struct {
+#define VP792_NUM_PROFILE_TYPES 9
+    uint16 valid[VP792_NUM_PROFILE_TYPES];
+
+#ifdef VP_COMMON_ADDRESS_SPACE
+    /* We only need to save profile pointers in the device object. */
+    VpProfilePtrType pDevice[VP_792_DEV_PROF_TABLE_SIZE];
+    VpProfilePtrType pAc[VP_792_AC_PROF_TABLE_SIZE];
+    VpProfilePtrType pDc[VP_792_DC_PROF_TABLE_SIZE];
+    VpProfilePtrType pRinging[VP_792_RINGING_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingCad[VP_792_RING_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pTone[VP_792_TONE_PROF_TABLE_SIZE];
+    VpProfilePtrType pMetering[VP_792_METERING_PROF_TABLE_SIZE];
+    VpProfilePtrType pCallerId[VP_792_CALLERID_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneCad[VP_792_TONE_CADENCE_PROF_TABLE_SIZE];
+#else
+    /* Profiles must be copied into the device object. */
+    VpProfileDataType device[VP_792_DEV_PROF_TABLE_SIZE][VP792_DEV_PROFILE_LEN];
+    VpProfileDataType ac[VP_792_AC_PROF_TABLE_SIZE][VP792_AC_PROFILE_LEN];
+    VpProfileDataType dc[VP_792_DC_PROF_TABLE_SIZE][VP792_DC_PROFILE_LEN];
+    VpProfileDataType ringing[VP_792_RINGING_PROF_TABLE_SIZE][VP792_RING_PROFILE_LEN];
+    VpProfileDataType ringCad[VP_792_RING_CADENCE_PROF_TABLE_SIZE][VP792_RINGCAD_PROFILE_LEN];
+    VpProfileDataType tone[VP_792_TONE_PROF_TABLE_SIZE][VP792_TONE_PROFILE_LEN];
+    VpProfileDataType metering[VP_792_METERING_PROF_TABLE_SIZE][VP792_MTR_PROFILE_LEN];
+    VpProfileDataType callerId[VP_792_CALLERID_PROF_TABLE_SIZE][VP792_CID_PROFILE_LEN];
+    VpProfileDataType toneCad[VP_792_TONE_CADENCE_PROF_TABLE_SIZE][VP792_TONECAD_PROFILE_LEN];
+#endif
+
+} Vp792ProfileTableType;
+
+typedef enum
+{
+  VP792_REQUEST_SET_REL_GAIN,
+  VP792_REQUEST_GET_LOOP_COND,
+  VP792_REQUEST_GET_OPTION,
+  VP792_REQUEST_DEVICE_IO_ACCESS_EXT,
+  VP792_REQUEST_LINE_IO_ACCESS,
+  VP792_REQUEST_QUERY,
+  VP792_REQUEST_LOW_LEVEL_CMD_16,
+  VP792_REQUEST_SENDSIG_MSGWAIT,
+  VP792_REQUEST_TEST_INTERNAL,
+  VP792_REQUEST_TEST_CMP,
+  VP792_REQUEST_TIMER_CMP,
+  VP792_REQUEST_REGISTER_DUMP
+} Vp792RequestTagType;
+
+/* Struct for information about pending responses (used in
+VpGetResults()): */
+typedef struct {
+    bool outstanding;
+
+    Vp792RequestTagType requestType;
+
+    union {
+        struct {
+            uint16 handle;
+            uint8 channelId;
+        } setRelGain;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+        } getLoopCond;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+            VpOptionIdType optionId;
+        } getOption;
+
+        struct {
+            VpDeviceIoAccessExtType deviceIoAccess;
+        } deviceIoAccessExt;
+
+        struct {
+            uint16 handle;
+            VpLineIoAccessType lineIoAccess;
+        } lineIoAccess;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+            VpQueryIdType queryId;
+        } query;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+            VpLowLevelCmdType cmdType;
+            uint16 writeWords[2];
+            uint8 numWriteWords;
+            uint8 numReadWords;
+        } lowLevelCmd16;
+
+        struct {
+            uint16 eventId;
+            uint16 handle;
+            uint8 channelId;
+            uint16 respSize;
+            uint16 cmdId;
+        } testLine;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+            bool internal;
+        } genTimer;
+
+        struct {
+            uint8 channelId;
+            uint8 commandId;
+            uint8 numReadWords;
+        } registerDump;
+    } args;
+} Vp792ResponseRequestType;
+
+typedef struct {
+    uint32 opaqueData[2400];
+} Vp792OpaquePmDevObjType;
+
+/* Vp792-specific Device Object */
+typedef struct {
+    /* Customer-defined device identifier struct, passed to HAL functions: */
+    VpDeviceIdType deviceId;
+
+    /* Slac identifier mapped with VpMapSlacId().  This member allows for
+       multiple device objects to share a common deviceId (which is the case
+       when they share a chip-select on the SPI bus). */
+    uint8 slacId;
+
+    /* Total number of channels controlled by this device: */
+    uint8 maxChannels;
+
+    /* SLAC revision info */
+    struct {
+        uint16 device;
+        uint16 product;
+        uint16 version;
+        uint32 patchAddress;
+    } rev;
+
+    /* A flag indicating whether VpInitDevice() has completed: */
+    bool devInit;
+
+    /* The Profile Table: */
+    Vp792ProfileTableType profTable;
+
+    /* PCM Clock Rate in units of 1KHz */
+    uint16 pcmClockRate;
+
+    /* High bits of the VP-API-II timestamp.  We maintain the high bits here
+     because the SLAC's timestamp has finer granularity. */
+    uint16 timeStampHiBits;
+
+    /* Struct for locally-maintained device-specific options: */
+    struct {
+        VpOptionCriticalFltType criticalFlt;
+        VpOptionEventMaskType eventMask;
+        uint16 pulseEnabled;
+        uint16 dtmfEnabled;
+        VpOptionParkModeType parkMode;
+        uint32 debugSelect;
+    } options;
+
+    /* Temporary storage for interrupt indication, while command mailbox is busy. */
+    uint16 intInd[2];
+
+    /* Array for keeping track of outstanding response requests: */
+    Vp792ResponseRequestType responseRequest[VP792_MAX_OUTSTANDING_RESPONSES];
+
+    /* Index (in the above array) of the next result to be returned by
+       VpGetResults(): */
+    uint16 requestIdx;
+
+    /* SLAC response mailbox cache (temporary storage used in cases of mailbox
+       congestion, where we need to empty the response mailbox before we can
+       issue another command in the command mailbox): */
+    struct {
+        uint8 count;            /* When the cache is nonempty, count > 0. */
+#define VP792_MAX_RSPSIZE 42
+        uint16 data[2][VP792_MAX_RSPSIZE];
+    } respMboxCache;
+
+    /* Bitmask indicating which device-specific event handlers are running. */
+    uint16 eventHandlers;
+
+    /* State variables for EhInitDevice() event handler: */
+    struct {
+
+#ifdef VP_COMMON_ADDRESS_SPACE
+        /* We only need to save profile pointers in the line object. */
+        VpProfilePtrType pDevProfile;
+        VpProfilePtrType pAcProfile;
+        VpProfilePtrType pDcProfile;
+        VpProfilePtrType pRingProfile;
+#else
+        /* Profiles must be copied into the line object. */
+        uint16 profilesValid;
+        VpProfileDataType devProfile[VP792_DEV_PROFILE_LEN];
+        VpProfileDataType acProfile[VP792_AC_PROFILE_LEN];
+        VpProfileDataType dcProfile[VP792_DC_PROFILE_LEN];
+        VpProfileDataType ringProfile[VP792_RING_PROFILE_LEN];
+#endif
+
+    } ehInitDevice;
+
+#ifdef VP792_INCLUDE_TESTLINE_CODE
+    Vp792OpaquePmDevObjType opaquePmDevObj;
+#endif
+
+} Vp792DeviceObjectType;
+
+/* Vp792-specific Line Object */
+typedef struct
+{
+
+    /* Number used by the Vp792 to uniquely identify this line: */
+    uint8 channelId;
+
+    /* Line termination type: */
+    VpTermType termType;
+
+    /* Customer-defined line identifier struct, returned in the event
+    * structure by VpGetEvent() when an event occurs on this line: */
+    VpLineIdType lineId;
+
+    /* A flag indicating whether VpInitLine() has completed: */
+    bool lineInit;
+
+    /* Struct for locally-maintained line-specific options: */
+    struct {
+        VpOptionDtmfModeControlType dtmfControlMode;
+        VpOptionZeroCrossType zeroCross;
+        VpOptionPulseModeType pulseMode;
+        VpOptionEventMaskType eventMask;
+        VpOptionRingControlType ringControl;
+        VpOptionPcmTxRxCntrlType pcmTxRxCntrl;
+        VpOptionLoopbackType loopback;
+        uint16 afeConfig; /* cached AFE_CONFIG value for loopback option */
+        uint32 debugSelect;
+    } options;
+
+    struct {
+#ifdef VP_COMMON_ADDRESS_SPACE
+        /* We only need to save profile pointers in the line object. */
+        VpProfilePtrType pAc;
+        VpProfilePtrType pDc;
+        VpProfilePtrType pRinging;
+        VpProfilePtrType pRingCad;
+        VpProfilePtrType pTone;
+        VpProfilePtrType pMetering;
+        VpProfilePtrType pCallerId;
+        VpProfilePtrType pToneCad;
+#else
+        /* Profiles must be copied into the line object. */
+        uint16 valid;
+        VpProfileDataType ac[VP792_AC_PROFILE_LEN];
+        VpProfileDataType dc[VP792_DC_PROFILE_LEN];
+        VpProfileDataType ringing[VP792_RING_PROFILE_LEN];
+        VpProfileDataType ringCad[VP792_RINGCAD_PROFILE_LEN];
+        VpProfileDataType tone[VP792_TONE_PROFILE_LEN];
+        VpProfileDataType metering[VP792_MTR_PROFILE_LEN];
+        VpProfileDataType callerId[VP792_CID_PROFILE_LEN];
+        VpProfileDataType toneCad[VP792_TONECAD_PROFILE_LEN];
+#endif
+
+    } profiles;
+
+    /* Bitmask indicating which line-specific event handlers are running. */
+    uint16 eventHandlers;
+
+    /* State variables for EhSetLineState() event handler: */
+    struct {
+        bool waitForMeterAbort;
+        bool waitForSequencerReady;
+        VpLineStateType newState;
+    } ehSetLineState;
+
+    /* Current API line state */
+    VpLineStateType currentState;
+
+    /* Currently-detected ongoing DTMF digit (if any): */
+    uint16 dtmfDigitDetected;
+
+    /* Sequencer state variables: */
+    struct {
+
+        /* If a sequencer-abort command has been sent to the SLAC, but the
+           VP792_EVID_SEQ event has not yet arrived, this is TRUE. */
+        bool aborting;
+
+        /* Event handlers which will be started only after the current
+           sequence is aborted: */
+        uint16 deferredHandlers;
+
+        /* Keeps track of what, if anything, is using the sequencer. */
+        Vp792SequencerUseType activeSequence;
+
+        /* Buffer for holding a new sequencer program while we wait for the
+           old sequence to be aborted: */
+#define _VP792_CMDSIZE_WR_SEQ_CTL 35
+        uint16 program[_VP792_CMDSIZE_WR_SEQ_CTL];
+
+        /* Register values are cached here during hook mask and RX-disable
+           intervals: */
+        uint16 lastDsh;
+        uint16 lastVpCfg2;
+
+        bool hookMaskInterval;
+    } sequencer;
+
+    /* State variables for VpSendSignal(): */
+    struct {
+
+        /* Stores the ongoing send signal type (if any), and the one that will
+           be applied when the sequencer becomes available. */
+        VpSendSignalType currentSignal;
+        VpSendSignalType newSignal;
+
+        /* Stores the value that was in the DRIVE_ST variable before the signal
+           started. */
+        uint16 driveSt;
+
+        /* State variables for Vp792SendSignal(VP_SENDSIG_MSG_WAIT_PULSE): */
+        struct {
+            int16 voltage;
+
+            struct {
+                struct {
+                    uint16 v1;
+                    uint16 vas;
+                    uint16 ila;
+                } on;
+                struct {
+                    uint16 v1;
+                    uint16 vas;
+                    uint16 ila;
+                } off;
+
+                uint16 vasOffset;
+                uint16 rfd;
+                uint16 rptc;
+            } dcParams;
+
+            bool readingDcParams;
+            bool aborting;
+
+            uint16 requestIdx;  /* for RD_DC_PARAMS request */
+        } msgWait;
+    } sendSig;
+
+    /* Caller ID state variables */
+    struct {
+
+        /* Currently active Caller ID profile.  This will be the same as
+           profiles.pCidProfile if VpInitRing() was called, but it will be
+           different if VpSendCid() was called. */
+#ifdef VP_COMMON_ADDRESS_SPACE
+        VpProfilePtrType pCidProfile;
+#else
+        uint16 cidProfileValid;
+        VpProfileDataType cidProfile[VP792_CID_PROFILE_LEN];
+#endif
+
+        /* Sending data using FSK or DTMF? */
+        bool isFsk;
+
+        /* FSK data state */
+        struct {
+            /* Whether the API should compute the checksum */
+            bool autoChecksum;
+
+            /* SLAC device buffer status bits */
+            uint8 bufStatus;
+
+            /* Preamble */
+            uint16 seizureBits;
+            uint16 markBits;
+
+            uint8 checksum;
+        } fsk;
+
+        struct {
+            /* Message data buffer */
+            bool nonempty;
+            uint8 buf[VP_SIZEOF_CID_MSG_BUFFER * 2];
+            uint8 head;
+            uint8 tail;
+        } data;
+
+        bool dtmfDetectInterval;
+        uint8 dtmfTones[2];
+    } callerId;
+
+    /* Metering state variables */
+    struct {
+        bool active;
+        uint16 eventRate;
+    } metering;
+} Vp792LineObjectType;
+
+/* Vp792 Group Device Object */
+
+typedef struct
+{
+
+  VpDeviceIdType deviceId;
+
+  /* Temporary storage for interrupt indication, while mailbox is busy. */
+  uint16 intInd[2];
+
+} Vp792GroupDeviceObjectType;
+
+#endif /* VP792_API_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp880_api_int.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp880_api_int.h
new file mode 100755
index 0000000..e1f6a2f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp880_api_int.h
@@ -0,0 +1,1286 @@
+/** \file vp880_api_int.h
+ * vp880_api_int.h
+ *
+ * Header file for the vp880 series API-II c files.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 6680 $
+ * $LastChangedDate: 2010-03-15 16:01:52 -0500 (Mon, 15 Mar 2010) $
+ */
+
+#ifndef VP880_API_INT_H
+#define VP880_API_INT_H
+
+/**< Define the initial hook value to use when determining if the line status
+ * has been changed from initialization. This must be an invalid value to force
+ * a signaling register read for simple polled mode.
+ */
+#define VP880_HOOK_INIT_VAL 0xFF
+
+#define VP880_MAX_RING_DET_PERIOD   (0x3F)
+
+#define VP880_RING_TRIP_DEBOUNCE    (100)
+
+#define VP880_LP_POLREV_DEBOUNCE_TIME     (200)
+
+/**< Use the legacy ringing detection (bypassing the CLARE device) */
+#undef  LEGACY_RINGING_DETECTION
+
+/**< Define the number of charge iterations for the ringing transition */
+#define IN_RUSH_CYCLE_TOTAL 5   /* 5 = normal, 0 to disable the feature */
+#define IN_RUSH_CYCLE_END   1
+
+/**< Define the mask that will report device busy if there is a currently active
+ * event when the user is attempting to perform another "read" transaction.
+ */
+#define VP880_NO_MASK   0x0000
+
+/* Defines for API */
+
+/*
+ * This timer is used by the API Tick counter to prevent Active State
+ * for 100ms after an on-hook transition.
+ */
+#define ON_HOOK_TIMER    20
+#define ON_HOOK_ABS_CLARE_DELAY 2
+
+/**< Revision and Product Code Command info */
+#define VP880_DEVTYPE_RD        0x73
+#define VP880_DEVTYPE_CMD       VP880_DEVTYPE_RD
+#define VP880_DEVTYPE_LEN       0x02    /**< RCN = 1st Byte, PCN = 2nd Byte */
+
+#define VP880_NO_OP_WRT         0x06
+#define VP880_NO_OP             VP880_NO_OP_WRT
+
+#define VP880_REV_VA            0x01
+#define VP880_REV_VC            0x02
+#define VP880_REV_JE            0x04
+
+/**< GLOBAL REGISTERS (Effects all SLAC device channels) */
+#define VP880_HW_RESET_WRT      0x04    /**< Hardware Reset */
+#define VP880_HW_RESET_CMD      VP880_HW_RESET_WRT
+#define VP880_HW_RESET_LEN      0x00
+
+#define VP880_TEST_REG1_WRT     0x30
+#define VP880_TEST_REG1_RD      0x31
+#define VP880_TEST_REG1_LEN     0x01
+#define VP880_TREG1_PLLBYP_MASK 0x80
+#define VP880_TREG1_CSEL_MASK   0x40
+#define VP880_TREG1_TMODE_MASK  0x0F
+
+#define VP880_TEST_REG2_WRT     0x32
+#define VP880_TEST_REG2_RD      0x33
+#define VP880_TEST_REG2_LEN     0x01
+
+/**< Transmit/Receive Clock Slot Command info */
+#define VP880_XR_CS_WRT         0x44    /**< Tx/Rx clock slot register write */
+#define VP880_XR_CS_RD          0x45    /**< Tx/Rx clock slot register read */
+#define VP880_XR_CS_LEN         0x01
+
+#define VP880_TX_CSLOT_WRT      0x44    /**< Tx clock slot register write */
+#define VP880_TX_CSLOT_RD       0x45    /**< Tx clock slot register read */
+#define VP880_TX_CSLOT_LEN      0x01
+
+#define VP880_RX_CSLOT_WRT      0x44    /**< Rx clock slot register write */
+#define VP880_RX_CSLOT_RD       0x45    /**< Rx clock slot register read */
+#define VP880_RX_CSLOT_LEN      0x01
+
+/**< Bit definitions for Transmit/Receive Clock Slot Register */
+#define VP880_TX_SLOT_MASK      0x07
+#define VP880_RX_SLOT_MASK      0x38
+
+/**< Transmit Edge Command info */
+#define VP880_TX_EDGE_WRT       0x44    /**< Tx clock slot register write */
+#define VP880_TX_EDGE_RD        0x45    /**< Tx clock slot register read */
+#define VP880_TX_EDGE_LEN       0x01
+
+/**< Bit definitions for Transmit Edge Register */
+#define VP880_TX_EDGE_MASK      0x40
+
+/**< Device Configuration Command info */
+#define VP880_DCR_WRT           0x46
+#define VP880_DCR_RD            0x47
+#define VP880_DCR_LEN           0x01
+
+/**< Bit definitions for Device Configuration */
+#define VP880_DCR_INTMODE_MASK      0x80
+#define VP880_DCR_DPCLK_MASK        0x40
+#define VP880_DCR_PCM_SMODE_MASK    0x20
+
+/**< Master Clock Command info */
+#define VP880_MCLK_CNT_WRT          0x46
+#define VP880_MCLK_CNT_RD           0x47
+#define VP880_MCLK_CNT_LEN          0x01
+
+/**< Bit definitions for Master Clock Command */
+#define VP880_MCLK_CLKSEL_MASK      0x0F
+
+/**< Operating Mode Command info */
+#define VP880_OP_MODE_WRT           0x4A
+#define VP880_OP_MODE_RD            0x4B
+#define VP880_OP_MODE_LEN           0x01
+
+/**< Bit definitions for Operating Mode Command */
+#define VP880_TEST_MODE_MASK        0x80
+#define VP880_RBE_MODE_MASK         0x40
+#define VP880_WBAND_MODE_MASK       0x20
+#define VP880_DSPBYP_MODE_MASK      0x10
+
+/**< Signaling Register Command info */
+#define VP880_NO_UL_SIGREG_RD       0x4D    /**< Read w/o unlock signaling reg */
+#define VP880_NO_UL_SIGREG_LEN      0x02
+
+#define VP880_UL_SIGREG_RD          0x4F    /**< Read w/unlock signaling reg */
+
+#ifndef VP880_UL_SIGREG_LEN
+#define VP880_UL_SIGREG_LEN         0x02
+#endif
+
+/**< Interrupt Mask Register info */
+#define VP880_INT_MASK_WRT      0x6C
+#define VP880_INT_MASK_RD       0x6D
+#define VP880_INT_MASK_LEN      0x02
+
+/**< Bit definitions for Signaling Register Commands */
+        /**< Byte 1 */
+#define VP880_CFAIL_MASK        0x80
+
+#define VP880_POL1_MASK         0x40
+#define VP880_OCALMY_MASK       0x40
+
+#define VP880_POH1_MASK         0x20
+#define VP880_TEMPA1_MASK       0x20
+
+#define VP880_IO2_1_MASK        0x10
+#define VP880_CAD1_INT_MASK     0x08
+#define VP880_DISC1_MASK        0x04
+#define VP880_CID1_RDY_MASK     0x04
+#define VP880_RING1_DET_MASK    0x02
+#define VP880_GNK1_MASK         0x02
+#define VP880_LIU1_MASK         0x01
+#define VP880_HOOK1_MASK        0x01
+
+        /**< Byte 2 */
+#define VP880_CDAT_MASK         0x80
+#define VP880_POL2_MASK         0x40
+#define VP880_OCALMZ_MASK       0x40
+
+#define VP880_POH2_MASK         0x20
+#define VP880_TEMPA2_MASK       0x20
+
+#define VP880_IO2_2_MASK        0x10
+#define VP880_CAD2_INT_MASK     0x08
+#define VP880_DISC2_MASK        0x04
+#define VP880_CID2_RDY_MASK     0x04
+#define VP880_RING2_DET_MASK    0x02
+#define VP880_GNK2_MASK         0x02
+#define VP880_LIU2_MASK         0x01
+#define VP880_HOOK2_MASK        0x01
+
+/**< Revision and Product Code Command info */
+#define VP880_RCN_PCN_RD        0x73
+#define VP880_RCN_PCN_LEN       0x02    /**< RCN = 1st Byte, PCN = 2nd Byte */
+#define VP880_RCN_LOCATION      0x00
+#define VP880_PCN_LOCATION      0x01
+
+#define VP880_WIDEBAND_MASK     0x01    /**< Wideband if set in PCN */
+#define VP880_CODEC_MASK        0x02    /**< CODEC exists if set in PCN */
+#define VP880_HV_MASK           0x04    /**< HV device if set in PCN */
+#define VP880_TWO_CHAN_MASK     0x80
+
+#define VP880_SLIC_MASK         0x38    /**< Indicates if, and type of SLIC */
+#define VP880_2CH_TRACKER       0x38
+#define VP880_2CH_ABS           0x30
+#define VP880_TRACK_FXS_FXO     0x28
+#define VP880_2CH_FXO           0x20
+#define VP880_ABS_FXS_FXO       0x00
+
+/*
+ * PCN Interpretation:
+ *     SLIC2    = xxx1 xxxx
+ *     SLIC1    = xxxx 1xxx
+ *     HV       = xxxx x1xx
+ *     CODEC    = xxxx xx1x
+ *     WideBand = xxxx xxx1
+ */
+
+#define VP880_IS_IT_WB  (VP880_CODEC_MASK | VP880_WB_MASK)
+
+/**< One Channel Devices */
+#define VP880_FIRST_OF_ONE_CHANNEL_DEVICES  (0x05)
+
+#define VP880_DEV_PCN_88010  (0x06)     /**< FXO */
+#define VP880_DEV_PCN_88111  (0x0A)     /* FXS-Tracker */
+#define VP880_DEV_PCN_88116  (0x0B)     /* FXS-Tracker - Wideband */
+#define VP880_DEV_PCN_88131  (0x0E)     /* FXS-Tracker */
+#define VP880_DEV_PCN_88136  (0x0F)     /* FXS-Tracker - Wideband */
+
+#define VP880_LAST_OF_ONE_CHANNEL_DEVICES  (0x10)
+
+#define VP880_TWO_CHANNNEL_MASK       (0x80)
+#define VP880_TRACKER_MASK            (0x08)
+
+/** Two Channel Devices */
+#define VP880_DEV_PCN_88211     (0xBA)     /* 2FXS-Tracker */
+#define VP880_DEV_PCN_88216     (0xBB)     /* 2FXS-Tracker - Wideband */
+#define VP880_DEV_PCN_88221     (0xB2)     /* 2FXS-ABS */
+#define VP880_DEV_PCN_88226     (0xB3)     /* 2FXS-ABS - Wideband */
+#define VP880_DEV_PCN_88231     (0xBE)     /* 2FXS-Tracker */
+#define VP880_DEV_PCN_88236     (0xBF)     /* 2FXS-Tracker - Wideband */
+
+#define VP880_DEV_PCN_88241     (0xB6)     /* 2FXS-ABS */
+#define VP880_DEV_PCN_88246     (0xB7)     /* 2FXS-ABS - Wideband */
+
+#define VP880_DEV_PCN_88311     (0xAA)     /* FXO/FXS-Tracker */
+#define VP880_DEV_PCN_88331     (0xAE)     /* FXO/FXS-Tracker */
+
+#define VP880_DEV_PCN_88506     (0xBC)     /* 2FXS-Tracker - Wideband Split Package*/
+#define VP880_DEV_PCN_88536     (0xFF)     /* 2FXS-Tracker - Wideband, IP Block */
+
+/**< Internal Revision Command info */
+#define VP880_REV_INFO_RD       0xB9
+#define VP880_REV_INFO_LEN      0x01
+
+/**< Switching Regulator Parameters */
+#define VP880_REGULATOR_PARAM_WRT   0xE4
+#define VP880_REGULATOR_PARAM_RD    0xE5
+
+#ifndef VP880_REGULATOR_PARAM_LEN
+#define VP880_REGULATOR_PARAM_LEN   0x03
+#endif
+
+#define VP880_REGULATOR_TRACK_INDEX     0x00
+#define VP880_REGULATOR_FIXED_RING      0x08
+#define VP880_REGULATOR_INVERT_BOOST    0x20
+
+#define VP880_FLOOR_VOLTAGE_BYTE    0x01
+#define VP880_FLOOR_VOLTAGE_MASK    0x1F
+
+#define VP880_BAT_CALIBRATION_WRT   0xE8
+#define VP880_BAT_CALIBRATION_RD    0xE9
+#define VP880_BAT_CALIBRATION_LEN   0x02
+#define VP880_BAT_CAL_SWCAL_MASK    0x38
+#define VP880_BAT_CAL_SWCAL_SIGN    0x20
+
+#define VP880_CONVERTER_MODE_WRT    0xE4
+#define VP880_CONVERTER_MODE_RD     0xE5
+#define VP880_CONVERTER_MODE_LEN    0x03
+
+/**< Switching Regulator Parameters bit definitions */
+#define VP880_MODE_MASK             0x20
+#define VP880_FLYBACK_MODE          0x00
+#define VP880_BUCKBOOST_MODE        0x20
+
+#define VP880_BSI_MASK              0xC0
+#define VP880_BSI_LY_MX_HZ          0x00
+#define VP880_BSI_LY_MZ_HX          0x40
+#define VP880_BSI_LX_MY_HZ          0x80
+#define VP880_BSI_DEFAULT           VP880_BSI_LY_MX_HZ
+
+#define VP880_ZRING_TRACK_MASK      0x08
+#define VP880_ZRING_TRACK_EN        0x00
+#define VP880_ZRING_TRACK_DIS       0x08
+
+#define VP880_YRING_TRACK_MASK      0x02
+#define VP880_YRING_TRACK_EN        0x00
+#define VP880_YRING_TRACK_DIS       0x02
+
+#define VP880_SWY_AUTOPOWER_INDEX   0x01
+#define VP880_SWY_AUTOPOWER_MASK    0x80
+#define VP880_SWY_AUTOPOWER_EN      0x00
+#define VP880_SWY_AUTOPOWER_DIS     0x80
+
+#define VP880_SWY_V_DIVISOR         1000ul
+#define VP880_SWY_V_STEPSIZE        5025ul  /**< 5.025V/step */
+
+#define VP880_SWZ_AUTOPOWER_INDEX   0x02
+#define VP880_SWZ_AUTOPOWER_MASK    0x80
+#define VP880_SWZ_AUTOPOWER_EN      0x00
+#define VP880_SWZ_AUTOPOWER_DIS     0x80
+
+#define VP880_SWZ_V_DIVISOR         1000ul
+#define VP880_SWZ_V_STEPSIZE        5025ul  /**< 5.025V/step */
+
+#define VP880_VOLTAGE_MASK          0x1F
+#define VP880_SWY_LOCATION          1
+#define VP880_SWZ_LOCATION          2
+#define VP880_VOLTAGE_60V           0x0B
+
+/**< Internal Switching Regulator Parameters Command info */
+#define VP880_INT_SWREG_PARAM_WRT   0xF6
+#define VP880_INT_SWREG_PARAM_RD    0xF7
+
+#ifndef VP880_INT_SWREG_PARAM_LEN
+#define VP880_INT_SWREG_PARAM_LEN   0x06
+#endif
+
+#define VP880_SWREG_RING_V_BYTE     2
+#define VP880_SWREG_FLOOR_V_BYTE    1
+
+/**< Switching Regulator Control Command info */
+#define VP880_REGULATOR_CTRL_WRT    0xE6
+#define VP880_REGULATOR_CTRL_RD     0xE7
+
+#ifndef VP880_REGULATOR_CTRL_LEN
+#define VP880_REGULATOR_CTRL_LEN    0x01
+#endif
+
+/*  Calibration  */
+typedef enum {
+    VP880_NORM_POLARITY,
+    VP880_REV_POLARITY,
+    NUM_POLARITY
+} Vp880CalPolarityType;
+
+#define VP880_VOC_SHIFT_MASK        0x40
+#define VP880_ILA_MASK              0x1F
+#define VP880_ILA_INDEX             0x01
+
+#define VP880_ABV_MASK              0x1F
+#define VP880_VAS_MASK_LO           0x03
+#define VP880_VAS_MASK_HI           0xC0
+
+/**< Switching Regulator Control bit definitions */
+#define VP880_SWY_MODE_MASK         0x03
+#define VP880_SWY_OFF               0x00
+#define VP880_SWY_LP                0x01
+#define VP880_SWY_MP                0x02
+#define VP880_SWY_HP                0x03
+#define VP880_SWYZ_LP               0x05
+
+#define VP880_SWZ_MODE_MASK         0x0C
+#define VP880_SWZ_OFF               0x00
+#define VP880_SWZ_LP                0x04
+#define VP880_SWZ_MP                0x08
+#define VP880_SWZ_HP                0x0C
+
+#define VP880_PWR_SWITCH_DEBOUNCE   (70)
+
+/**< CHANNEL REGISTERS (must set EC register first) */
+
+/**< Channel Enable Command info */
+#define VP880_EC_WRT                0x4A
+#define VP880_EC_RD                 0x4B
+#define VP880_EC_LEN                0x01
+
+#ifndef VP880_EC_CH1
+#define VP880_EC_CH1                0x01
+#define VP880_EC_CH2                0x02
+#endif
+
+#define VP880_EC_STATE_AT_RESET     0x03
+
+/**< Bit definitions for Channel Enable Command */
+#define VP880_EC_BITS_MASK          0x03
+
+#define VP880_DSP_BYPASS            0x10
+#define VP880_WIDEBAND_MODE         0x20
+#define VP880_TEST_MODE_ENABLE      0x80
+
+/**< Voice Path Gain Command info */
+#define VP880_VP_GAIN_WRT           0x50
+#define VP880_VP_GAIN_RD            0x51
+#define VP880_VP_GAIN_LEN           0x01
+#define VP880_DEFAULT_VP_GAIN       0x00
+
+/**< Bit definitions for Voice Path Gain Commands */
+#define VP880_AX_MASK           0x40
+#define VP880_AR_MASK           0x30
+#define VP880_AR_0DB_LOSS       0x00
+#define VP880_AR_6DB_LOSS       0x10
+#define VP880_AR_6DB_GAIN       0x20
+#define VP880_AR_RSVD1          0x30
+#define VP880_DR_LOSS_MASK      0x08    /**< Digital Receive Loss = 0dB (0) or
+                                         * 6.02dB (1)
+                                         */
+
+/**< IO Data Command info */
+#define VP880_IODATA_REG_WRT    0x52    /**< I/O register write */
+#define VP880_IODATA_REG_RD     0x53    /**< I/O register read */
+#define VP880_IODATA_REG_LEN    0x01
+#define VP880_IODATA_IO6        0x20
+#define VP880_IODATA_IO5        0x10
+#define VP880_IODATA_IO4        0x08
+#define VP880_IODATA_IO3        0x04
+#define VP880_IODATA_IO2        0x02
+#define VP880_IODATA_IO1        0x01
+
+/**< Bit definitions for IO Data Command */
+#define VP880_IODATA_BITS_MASK  0x3F    /**< Lowest two bits always available */
+
+/**< IO Direction Command info */
+#define VP880_IODIR_REG_WRT     0x54    /**< I/O direction register write */
+#define VP880_IODIR_REG_RD      0x55    /**< I/O direction register read */
+#define VP880_IODIR_REG_LEN     0x01
+
+/**< Bit definitions for IO Direction Command */
+#define VP880_MAX_PINS_PER_LINE (6)
+
+#define VP880_IODIR_IO11_MASK   0x01
+#define VP880_IODIR_IO12_MASK   0x02
+#define VP880_IODIR_IO1_MASK    0x03
+#define VP880_IODIR_IO2_MASK    0x04
+#define VP880_IODIR_IO3_MASK    0x08
+#define VP880_IODIR_IO4_MASK    0x10
+#define VP880_IODIR_IO5_MASK    0x20
+#define VP880_IODIR_IO6_MASK    0x40
+#define VP880_IODIR_EXPDT_MASK  0x80    /**< External Period detector connected
+                                         * to IO4
+                                         */
+
+#define VP880_IODIR_IO1_INPUT       0x00
+#define VP880_IODIR_IO1_OUTPUT      0x01
+#define VP880_IODIR_IO1_OPEN_DRAIN  0x02
+
+#define VP880_IODIR_IO2_OUTPUT      0x04
+#define VP880_IODIR_IO3_OUTPUT      0x08
+#define VP880_IODIR_IO4_OUTPUT      0x10
+#define VP880_IODIR_IO5_OUTPUT      0x20
+#define VP880_IODIR_IO6_OUTPUT      0x40
+
+/**< System State Command info */
+#define VP880_SYS_STATE_WRT     0x56
+#define VP880_SYS_STATE_RD      0x57
+#define VP880_SYS_STATE_LEN     0x01
+
+#define VP880_SLIC_STATE_WRT    VP880_SYS_STATE_WRT
+#define VP880_SLIC_STATE_RD     VP880_SYS_STATE_RD
+#define VP880_SLIC_STATE_LEN    VP880_SYS_STATE_LEN
+
+/**< Command (bit) definitions for FXS System State */
+#define VP880_SS_RING_EXIT_MASK     0x80
+#define VP880_SS_METERING_MASK      0x40
+#define VP880_SS_ACTIVATE_MASK      0x20    /**< (1) = CODEC Active, (0) =
+                                             * Deactive
+                                             */
+
+#define VP880_SS_POLARITY_MASK      0x10    /**< (0) = Normal, (1) = Reverse */
+#define VP880_SS_STATE_MASK         0x3F
+#define VP880_SS_LINE_FEED_MASK     0x0F
+
+#define VP880_SS_DISCONNECT         0x00
+#define VP880_SS_TIP_OPEN           0x01
+#define VP880_SS_RING_OPEN          0x02
+#define VP880_SS_ACTIVE             (0x03 | VP880_SS_ACTIVATE_MASK)
+
+#define VP880_SS_ACTIVE_POLREV      (0x03 | VP880_SS_ACTIVATE_MASK \
+                                          | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_IDLE               0x04
+#define VP880_SS_IDLE_POLREV        (0x04 | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_FEED_BALANCED_RINGING      0x07
+#define VP880_SS_FEED_UNBALANCED_RINGING    0x0A
+
+#define VP880_SS_LONGITUDINAL_TEST  (0x05 | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_METALLIC_TEST      (0x06 | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_BALANCED_RINGING   (VP880_SS_FEED_BALANCED_RINGING | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_LOW_GAIN           (0x08 | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_RSVD_0             (0x09 | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_UNBALANCED_RINGING (VP880_SS_FEED_UNBALANCED_RINGING | VP880_SS_ACTIVATE_MASK)
+
+#define VP880_SS_BALANCED_RINGING_PR    (VP880_SS_BALANCED_RINGING \
+                                       | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_UNBALANCED_RINGING_PR  (VP880_SS_UNBALANCED_RINGING \
+                                       | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_ACTIVE_MID_BAT     (0x0B | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_ACTIVE_MID_BAT_PR  (VP880_SS_ACTIVE_MID_BAT \
+                                    | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_SHUTDOWN        0x0F
+
+#define VP880_SS_RSVD_1             (0x0C | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_RSVD_2             (0x0D | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_RSVD_3             (0x0E | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_RSVD_4             (0x0F | VP880_SS_ACTIVATE_MASK)
+
+/**< FXO State controlled by General Purpose I/O */
+#define VP880_FXO_STATE_WRT    0x52
+#define VP880_FXO_STATE_RD     0x53
+#define VP880_FXO_STATE_LEN    0x01
+
+#define VP880_FXO_ACTIVATE_CODEC  0x20
+#define VP880_FXO_SUPERVISION_EN  0x09
+
+#define VP880_SS_FXO_OHT             0x00  /**< I/O-1 = Low, I/O-2 = Low */
+#define VP880_SS_FXO_LOOP_CLOSED     0x01  /**< I/O-1 = High, I/O-2 = Low */
+#define VP880_SS_FXO_LOOP_OPEN       0x02  /**< I/O-1 = Low, I/O-2 = High */
+
+/**< Command (bit) definitions for FX0 System State */
+#define VP880_SS_SHUTDOWN_MASK      0x00
+#define VP880_SS_DEACTIVATED_MASK   0x09
+#define VP880_SS_ACTIVATED_MASK     0x29
+
+/**< Operating Functions Command info */
+#define VP880_OP_FUNC_WRT       0x60
+#define VP880_OP_FUNC_RD        0x61
+
+#ifndef VP880_OP_FUNC_LEN
+#define VP880_OP_FUNC_LEN       0x01
+#endif
+
+/**< Bit definitions for Operating Functions Command */
+#define VP880_ENABLE_GR     0x20
+#define VP880_ENABLE_GX     0x10
+#define VP880_ENABLE_X      0x08
+#define VP880_ENABLE_R      0x04
+#define VP880_ENABLE_Z      0x02
+#define VP880_ENABLE_B      0x01
+#define VP880_ENABLE_LOADED_COEFFICIENTS 0x3F
+
+#define VP880_DEFAULT_OP_FUNC_MODE 0x00
+
+/**< Codec Compression Command info (Operating Functions) */
+#define VP880_CODEC_REG_WRT     0x60
+#define VP880_CODEC_REG_RD      0x61
+#define VP880_CODEC_REG_LEN     0x01
+
+/**< Bit definitions for Codec Compression Command */
+
+/* Note:  If Linear Mode is selected, u-Law/A-Law selection is ignored */
+#define VP880_CODEC_COMPRESSION_MASK    0xC0
+#define VP880_ALAW_CODEC        0x00    /**< a-Law compression is used */
+#define VP880_ULAW_CODEC        0x40    /**< u-law compression is used */
+#define VP880_LINEAR_CODEC      0x80    /**< Linear mode is used */
+
+/**< System State Configuration Command info */
+#define VP880_SS_CONFIG_WRT     0x68
+#define VP880_SS_CONFIG_RD      0x69
+#define VP880_SS_CONFIG_LEN     0x01
+
+/*< Automatic Clock Fault Switching */
+#define VP880_ACFS_MASK     0x20
+#define VP880_ACFS_EN       0x20
+#define VP880_ACFS_DIS      0x00
+
+/**< Bit definitions for System State Configuration Command */
+/**< Auto Thermal Fault Switching */
+#define VP880_ATFS_MASK     0x10
+#define VP880_ATFS_EN       0x10
+#define VP880_ATFS_DIS      0x00
+
+/**< Zero Cross Ring Entry/Exit */
+#define VP880_ZXR_MASK      0x08
+#define VP880_ZXR_EN        0x00
+#define VP880_ZXR_DIS       0x08
+
+/**< Smooth Polarity Reversal */
+#define VP880_SMOOTH_PR_MASK    0x04
+#define VP880_SMOOTH_PR_EN      0x04
+#define VP880_SMOOTH_PR_DIS     0x00
+
+/**< Automatic System State Control */
+#define VP880_AUTO_SSC      0x02
+#define VP880_AUTO_SSC_EN   0x00
+#define VP880_AUTO_SSC_DIS  0x02
+
+/**< Automatic Battery Switch Control for ABS */
+#define VP880_ABS                       0x01
+#define VP880_AUTO_BAT_SWITCH_DIS       0x01
+#define VP880_AUTO_BAT_SWITCH_EN        0x00
+
+/**< Automatic Battery Shutdown for Tracker */
+#define VP880_AUTO_BAT_SHUTDOWN_EN      0x01
+#define VP880_AUTO_BAT_SHUTDOWN_DIS     0x00
+
+/**< Operating Conditions Command info */
+#define VP880_OP_COND_WRT         0x70
+#define VP880_OP_COND_RD          0x71
+
+#ifndef VP880_OP_COND_LEN
+#define VP880_OP_COND_LEN         0x01
+#endif
+
+/**< Map the loop back register to operating conditions register */
+#define VP880_LOOPBACK_WRT        VP880_OP_COND_WRT
+#define VP880_LOOPBACK_RD         VP880_OP_COND_RD
+#define VP880_LOOPBACK_LEN        VP880_OP_COND_LEN
+
+/**< Bit definitions for Operating Conditions Command */
+#define VP880_TX_PATH_MASK      0x80
+#define VP880_CUT_TXPATH        0x80
+#define VP880_TXPATH_EN         0x00
+#define VP880_TXPATH_DIS        0x80
+
+#define VP880_RX_PATH_MASK      0x40
+#define VP880_CUT_RXPATH        0x40
+#define VP880_RXPATH_EN         0x00
+#define VP880_RXPATH_DIS        0x40
+
+#define VP880_HIGH_PASS_MASK    0x20
+#define VP880_HIGH_PASS_EN      0x00
+#define VP880_HIGH_PASS_DIS     0x20
+
+#define VP880_LOWER_RX_GAIN_MASK    0x10
+#define VP880_RX_GAIN_6DB_LOSS      0x10
+#define VP880_RX_GAIN_0DB_LOSS      0x00
+
+#define VP880_INTERFACE_LOOPBACK_EN 0x04
+#define VP880_1KHZ_TONE_ON          0x01
+
+#define VP880_OPCOND_RSVD_MASK      (0x0A | VP880_1KHZ_TONE_ON)
+#define VP880_NORMAL_OP_COND_MODE   0x00
+
+/**< GX Filter Command info */
+#define VP880_GX_GAIN_WRT       0x80
+#define VP880_GX_GAIN_RD        0x81
+#define VP880_GX_GAIN_LEN       0x02
+
+/**< GR Filter Command info */
+#define VP880_GR_GAIN_WRT       0x82
+#define VP880_GR_GAIN_RD        0x83
+#define VP880_GR_GAIN_LEN       0x02
+
+/**< B Filter (FIR) Coefficients */
+#define VP880_B1_FILTER_WRT     0x86
+#define VP880_B1_FILTER_RD      0x87
+#define VP880_B1_FILTER_LEN     0x0E
+
+/**< B Filter (IIR) Coefficients */
+#define VP880_B2_FILTER_WRT     0x96
+#define VP880_B2_FILTER_RD      0x97
+#define VP880_B2_FILTER_LEN     0x02
+
+/**< X Filter Coefficients */
+#define VP880_X_FILTER_WRT      0x88
+#define VP880_X_FILTER_RD       0x89
+#define VP880_X_FILTER_LEN      0x0C
+
+/**< R Filter Coefficients */
+#define VP880_R_FILTER_WRT      0x8A
+#define VP880_R_FILTER_RD       0x8B
+#define VP880_R_FILTER_LEN      0x0E
+
+/**< Z Filter (FIR) Coefficients */
+#define VP880_Z1_FILTER_WRT     0x98
+#define VP880_Z1_FILTER_RD      0x99
+#define VP880_Z1_FILTER_LEN     0x0A
+
+/**< Z Filter (IIR) Coefficients */
+#define VP880_Z2_FILTER_WRT     0x9A
+#define VP880_Z2_FILTER_RD      0x9B
+#define VP880_Z2_FILTER_LEN     0x05
+
+/**< Converter Configuration */
+#define VP880_CONV_CFG_WRT      0xA6
+#define VP880_CONV_CFG_RD       0xA7
+
+#ifndef VP880_CONV_CFG_LEN
+#define VP880_CONV_CFG_LEN      0x01
+#endif
+
+/**< Converter Configuration bit definitions */
+#define VP880_CONV_CONNECT_BITS 0x0F
+#define VP880_METALLIC_AC_V     0x00
+#define VP880_SWITCHER_Y        0x01
+#define VP880_SWITCHER_Z        0x02
+#define VP880_XBR               0x03
+#define VP880_TIP_TO_GND_V      0x04
+#define VP880_RING_TO_GND_V     0x05
+#define VP880_METALLIC_DC_V     0x06
+#define VP880_METALLIC_DC_I     0x07
+#define VP880_LONGITUDINAL_DC_I 0x08
+#define VP880_CALIBRATION_I     0x09
+#define VP880_VOICE_DAC         0x0A
+#define VP880_NO_CONNECT        0x0B
+#define VP880_CC_RSVD1          0x0C
+#define VP880_LOW_TIP_TO_GND_V  0x0D
+#define VP880_LOW_RING_TO_GND_V 0x0E
+#define VP880_CC_RSVD2          0x0F
+#define VP880_CC_RATE_MASK      0x70
+#define VP880_CC_500HZ_RATE     0x40
+#define VP880_CC_1KHZ_RATE      0x30
+#define VP880_CC_2KHZ_RATE      0x20
+#define VP880_CC_4KHZ_RATE      0x10
+#define VP880_CC_8KHZ_RATE      0x00
+#define VP880_CC_RATE_BITS      0x70
+
+#define VP880_ILA_SCALE_1MA     (568)
+#define VP880_ILA_SCALE_2MA     (2 * VP880_ILA_SCALE_1MA)
+#define VP880_ILA_SCALE_18MA    (9 * VP880_ILA_SCALE_2MA)
+
+/**< Loop Supervision Command info */
+#define VP880_LOOP_SUP_WRT      0xC2
+#define VP880_LOOP_SUP_RD       0xC3
+
+#ifndef VP880_LOOP_SUP_LEN
+#define VP880_LOOP_SUP_LEN      0x04
+#endif
+
+#define VP880_LIU_DBNC_INDEX    0x01
+#define VP880_LIU_DBNC_MASK     0x1F
+
+#define VP880_RING_PERIOD_MIN_INDEX     0x02
+#define VP880_RING_PERIOD_1MS           0x04
+
+#define VP880_LOOP_SUP_RT_MODE_BYTE 0x02
+
+#define VP880_LOOP_SUP_LIU_THRESH_BYTE  0x00
+#define VP880_LOOP_SUP_LIU_THRESH_BITS  0x07
+#define VP880_LOOP_SUP_LIU_16V          0x00
+
+/**< Usefull variables and bit definitions for Loop Supervision */
+#define VP880_LOOPSUP_CUR_DIVISOR     1ul
+#define VP880_LOOPSUP_CUR_STEPSIZE    1ul
+
+#define VP880_LOOPSUP_TSH_DIVISOR     VP880_LOOPSUP_CUR_DIVISOR
+#define VP880_LOOPSUP_TSH_STEPSIZE    VP880_LOOPSUP_CUR_STEPSIZE
+
+#define VP880_LOOPSUP_TGK_DIVISOR     1ul
+#define VP880_LOOPSUP_TGK_STEPSIZE    3ul
+
+#define VP880_LOOPSUP_DGK_DIVISOR     1ul
+#define VP880_LOOPSUP_DGK_STEPSIZE    4ul
+
+#define VP880_LOOPSUP_DSH_DIVISOR     1ul
+#define VP880_LOOPSUP_DSH_STEPSIZE    2ul
+
+#define VP880_LOOPSUP_RTTH_DIVISOR    10ul
+#define VP880_LOOPSUP_RTTH_STEPSIZE   5ul
+
+#define VP880_LOOPSUP_IRL_DIVISOR     1ul
+#define VP880_LOOPSUP_IRL_STEPSIZE    2ul
+
+#define VP880_LOOPSUP_TDIS_DIVISOR    10ul
+#define VP880_LOOPSUP_TDIS_STEPSIZE   14ul
+
+#define VP880_LOOPSUP_TLIU_DIVISOR    1ul
+#define VP880_LOOPSUP_TLIU_STEPSIZE   11ul
+
+#define VP880_LOOPSUP_DDIS_DIVISOR    1ul
+#define VP880_LOOPSUP_DDIS_STEPSIZE   4ul
+
+#define VP880_LOOPSUP_DLIU_DIVISOR    1ul
+#define VP880_LOOPSUP_DLIU_STEPSIZE   2ul
+
+#define VP880_LOOPSUP_TMIN_DIVISOR    100ul
+#define VP880_LOOPSUP_TMIN_STEPSIZE   25ul
+
+#define VP880_LOOPSUP_TMAX_DIVISOR    100ul
+#define VP880_LOOPSUP_TMAX_STEPSIZE   25ul
+
+/**< Command to control how Ring Trip will work */
+#define VP880_RINGTRIP_MODE_WRT     0xC2
+#define VP880_RINGTRIP_MODE_RD      0xC3
+#define VP880_RINGTRIP_MODE_LEN     0x04
+
+/**< Bit definitions for Ring Trip Control (AC or DC) */
+#define VP880_RING_TRIP_DC      0x00
+#define VP880_RING_TRIP_AC      0x80
+
+#define VP880_RING_DETECT_PERIOD_ONLY   0x80
+
+/**< DC Feed Command info */
+#define VP880_DC_FEED_WRT    0xC6
+#define VP880_DC_FEED_RD     0xC7
+
+#ifndef VP880_DC_FEED_LEN
+#define VP880_DC_FEED_LEN    0x02
+#endif
+#define VP880_DC_CAL_VOC_DIS        0x10
+
+/* Position in DC Profile specifying VOC and ILA */
+#define VP880_VOC_PROFILE_POSITION 12
+#define VP880_ILA_PROFILE_POSITION 13
+#define VP880_HOOK_HYST_POSITION   14
+
+/**< Usefull variables and bit definitions for DC Feed */
+#define VP880_LONG_IMP_MASK     0x20
+#define VP880_LONG_IMP_50       0x20
+#define VP880_LONG_IMP_100      0x00
+
+/* First Byte */
+#define VP880_VOC_LOW_RANGE     0x40
+#define VP880_VOC_MASK          0x1C    /* 0x40 is Range (36-57, 12-33) bit */
+#define VP880_VOC_VALUE_MASK    (VP880_VOC_MASK | VP880_VOC_LOW_RANGE)
+#define VP880_VOC_57V           0x1C
+#define VP880_VOC_54V           0x18
+#define VP880_VOC_51V           0x14
+#define VP880_VOC_48V           0x10
+#define VP880_VOC_45V           0x0C
+#define VP880_VOC_42V           0x08
+#define VP880_VOC_39V           0x04
+#define VP880_VOC_36V           0x00
+
+#define VP880_VAS_MSB_LOC       0x00
+#define VP880_VAS_MSB_MASK      0x03
+
+#define VP880_VAS_LSB_LOC       0x01
+#define VP880_VAS_LSB_MASK      0xC0
+
+#define VP880_VAS_CONVERSION(msb, lsb)  (750*(((msb << 2) & 0xC) | ((lsb >> 6) & 0x3))+3000)
+
+/**< Digital Impedance Scaling Command info */
+#define VP880_DISN_WRT  0xCA
+#define VP880_DISN_RD   0xCB
+#define VP880_DISN_LEN  0x01
+
+#define VP880_DEFAULT_DISN_GAIN 0x00
+
+/**< Usefull variables and bit definitions for DISN */
+#define VP880_DISN_DIVISOR      10000ul
+#define VP880_DISN_STEPSIZE     78ul
+
+/**< Read Transmit PCM/Test Data Command info */
+#define VP880_TX_PCM_DATA_RD        0xCD
+#define VP880_TX_PCM_DATA_LEN       0x02
+
+/**< Read Transmit PCM/Test Buffer Command info */
+#define VP880_TX_PCM_BUFF_RD        0xCF
+#define VP880_TX_PCM_BUFF_LEN       0x0E
+
+#define VP880_TX_BUF_LEN_MASK           0x70
+#define VP880_TX_BUF_LEN_INDEX          0
+#define VP880_TX_BUF_HOOK_MSB_MASK      0x0F
+#define VP880_TX_BUF_HOOK_MSB_INDEX     0
+#define VP880_TX_BUF_HOOK_LSB_MASK      0xFF
+#define VP880_TX_BUF_HOOK_LSB_INDEX     1
+#define VP880_TX_BUF_HOOK_CHAN1_MASK    0x3F
+#define VP880_TX_BUF_HOOK_CHAN2_MASK    0xC0
+
+/**< Device Mode Command info */
+#define VP880_DEV_MODE_WRT          0x5E
+#define VP880_DEV_MODE_RD           0x5F
+#define VP880_DEV_MODE_LEN          0x01
+
+#define VP880_DEV_MODE_TEST_DATA    0x01
+#define VP880_DEV_MODE_CHAN_MASK    0x02
+#define VP880_DEV_MODE_CHAN0_SEL    0x00
+#define VP880_DEV_MODE_CHAN1_SEL    0x02
+
+/**< Metering Parameters Command info */
+#define VP880_METERING_PARAM_WRT    0xD0
+#define VP880_METERING_PARAM_RD     0xD1
+#define VP880_METERING_PARAM_LEN    0x04
+
+/**< Metering Parameters bit definitions */
+#define VP880_METERING_FREQ_MASK    0x80
+#define VP880_METERING_FREQ_12K     0x00
+#define VP880_METERING_FREQ_16K     0x80
+
+#define VP880_METERING_LIM_MASK     0x7F
+#define VP880_METER_LIM_DIVISOR     1000ul
+#define VP880_METER_LIM_STEPSIZE    15ul    /**< 15mV @ 12Khz, 18mV @ 16KHz */
+
+#define VP880_METERING_RAMP_MASK    0x80
+#define VP880_METERING_RAMP_SMOOTH  0x00
+#define VP880_METERING_RAMP_ABRUPT  0x80
+
+#define VP880_METERING_SLOPE_MASK       0x7F
+#define VP880_METERING_SLOPE_DIVISOR    1000ul
+#define VP880_METERING_SLOPE_STEPSIZE   68ul    /**< 68uA/step */
+
+#define VP880_METERING_TIME_DIVISOR     10000ul
+#define VP880_METERING_TIME_STEPSIZE    25ul    /**< 2.5mS/step */
+
+#define VP880_METERING_PEAK_DIVISOR     100000ul
+#define VP880_METERING_PEAK_STEPSIZE    78125ul /**< 7.8125mV/step */
+
+/**< Signal Generator A, B, and Bias Command info */
+#define VP880_SIGA_PARAMS_WRT       0xD2
+#define VP880_SIGA_PARAMS_RD        0xD3
+
+#ifndef VP880_SIGA_PARAMS_LEN
+#define VP880_SIGA_PARAMS_LEN       0x0B
+#endif
+
+#define VP880_SIGB_PARAMS_WRT       VP880_SIGA_PARAMS_WRT
+#define VP880_SIGB_PARAMS_RD        VP880_SIGA_PARAMS_RD
+#define VP880_SIGB_PARAMS_LEN       VP880_SIGA_PARAMS_LEN
+
+#define VP880_SIGAB_PARAMS_WRT      VP880_SIGA_PARAMS_WRT
+#define VP880_SIGAB_PARAMS_RD       VP880_SIGA_PARAMS_RD
+#define VP880_SIGAB_PARAMS_LEN      VP880_SIGA_PARAMS_LEN
+
+#define VP880_RINGER_PARAMS_WRT     VP880_SIGA_PARAMS_WRT
+#define VP880_RINGER_PARAMS_RD      VP880_SIGA_PARAMS_RD
+#define VP880_RINGER_PARAMS_LEN     VP880_SIGA_PARAMS_LEN
+
+/* Map of the Signal Generator A/B Byte Locations */
+#define VP880_SIGA_BIAS_MSB         0x01
+#define VP880_SIGA_BIAS_LSB         0x02
+#define VP880_SIGA_FREQ_MSB         0x03
+#define VP880_SIGA_FREQ_LSB         0x04
+#define VP880_SIGA_AMP_MSB          0x05
+#define VP880_SIGA_AMP_LSB          0x06
+#define VP880_SIGB_FREQ_MSB         0x07
+#define VP880_SIGB_FREQ_LSB         0x08
+#define VP880_SIGB_AMP_MSB          0x09
+#define VP880_SIGB_AMP_LSB          0x0A
+
+#define VP880_RINGING_AMP_SCALE     473
+#define VP880_RINGING_AMP_FACTOR    100000
+
+#define VP880_RINGING_BIAS_SCALE    473
+#define VP880_RINGING_BIAS_FACTOR   100000
+
+
+/**< Signal Generator bit definitions */
+#define VP880_RAMP_SLOPE_MASK   0x04
+#define VP880_RAMP_POSITIVE     0x00
+#define VP880_RAMP_NEGATIVE     0x04
+
+#define VP880_SIGGEN1_OP_MASK   0x02
+#define VP880_SIGGEN1_OUT_RAMP  0x02
+#define VP880_SIGGEN1_OUT_CONT  0x00
+
+#define VP880_SIGGEN1_SINTRAP_MASK  0x01
+#define VP880_SIGGEN1_SIN           0x00
+#define VP880_SIGGEN1_TRAP          0x01
+
+#define VP880_GENA_FREQ_DIVISOR     1000ul
+#define VP880_GENA_FREQ_STEPSIZE    366ul   /**< 0.366Hz/step */
+
+#define VP880_GENA_AMP_DIVISOR      100ul
+#define VP880_GENA_AMP_STEPSIZE     471ul   /**< 4.71mV/step in Ringing Mode */
+
+#define VP880_GENB_FREQ_DIVISOR     1000ul
+#define VP880_GENB_FREQ_STEPSIZE    366ul   /**< 0.366Hz/step */
+
+/**< Signal Generator C and D Command info */
+#define VP880_SIGC_PARAMS_WRT       0xD4
+#define VP880_SIGC_PARAMS_RD        0xD5
+#define VP880_SIGC_PARAMS_LEN       0x08
+
+#define VP880_SIGD_PARAMS_WRT       0xD4
+#define VP880_SIGD_PARAMS_RD        0xD5
+#define VP880_SIGD_PARAMS_LEN       0x08
+
+#define VP880_SIGCD_PARAMS_WRT      0xD4
+#define VP880_SIGCD_PARAMS_RD       0xD5
+#define VP880_SIGCD_PARAMS_LEN      0x08
+
+/**< Signal Generator C/D bit definitions */
+#define VP880_GENC_FREQ_DIVISOR     1000ul
+#define VP880_GENC_FREQ_STEPSIZE    366ul   /**< 0.366Hz/step */
+
+#define VP880_GEND_FREQ_DIVISOR     1000ul
+#define VP880_GEND_FREQ_STEPSIZE    366ul   /**< 0.366Hz/step */
+
+/**< Signal Generator Control Command */
+#define VP880_GEN_CTRL_WRT      0xDE
+#define VP880_GEN_CTRL_RD       0xDF
+#define VP880_GEN_CTRL_LEN      0x01
+
+#define VP880_GEND_EN           0x08
+#define VP880_GENC_EN           0x04
+#define VP880_GENB_EN           0x02
+#define VP880_GENA_EN           0x01
+
+#define VP880_GEN_ALLOFF        0x00
+#define VP880_GEN_ALLON         0x0F
+
+/**< Signal Generator Control bit definitions */
+#define VP880_GEN_CAD_EN        0x80
+#define VP880_GEN_CAD_DIS       0x00
+
+#define VP880_GEN_CTRL_CONT     0x00
+#define VP880_GEN_CTRL_OS       0x40
+
+#define VP880_GEN_CTRL_DPGEN_EN     0x20
+#define VP880_GEN_CTRL_DPGEN_DIS    0x00
+
+#define VP880_GEN_CTRL_EN_BIAS  0x10
+#define VP880_GEN_CTRL_DIS_BIAS 0x00
+
+#define VP880_GEN_CTRL_EN_D     0x08
+#define VP880_GEN_CTRL_DIS_D    0x00
+
+#define VP880_GEN_CTRL_EN_C     0x04
+#define VP880_GEN_CTRL_DIS_C    0x00
+
+#define VP880_GEN_CTRL_EN_B     0x02
+#define VP880_GEN_CTRL_DIS_B    0x00
+
+#define VP880_GEN_CTRL_EN_A     0x01
+#define VP880_GEN_CTRL_DIS_A    0x00
+
+/**< Cadence Timer Command */
+#define VP880_CADENCE_TIMER_WRT     0xE0
+#define VP880_CADENCE_TIMER_RD      0xE1
+#define VP880_CADENCE_TIMER_LEN     0x04
+
+/**< Cadence Timer bit definitions */
+#define VP880_CADENCE_ON_DIVISOR    1ul
+#define VP880_CADENCE_ON_STEPSIZE   5ul /**< 5mS/step */
+
+#define VP880_CADENCE_OFF_DIVISOR   1ul
+#define VP880_CADENCE_OFF_STEPSIZE  5ul /**< 5mS/step */
+
+/**< Caller ID Data Command info */
+#define VP880_CID_DATA_WRT      0xE2
+#define VP880_CID_DATA_RD       0xE3
+#define VP880_CID_DATA_LEN      0x01
+
+/**< Caller ID Parameters Command info */
+#define VP880_CID_PARAM_WRT     0xEA
+#define VP880_CID_PARAM_RD      0xEB
+#define VP880_CID_PARAM_LEN     0x01
+
+/**< Caller ID Parameters bit definitions */
+#define VP880_CID_STATE_MASK    0xE0
+#define VP880_CID_STATE_IDLE    0x00
+#define VP880_CID_STATE_RDY     0x20
+#define VP880_CID_STATE_FULL    0x40
+#define VP880_CID_STATE_LBYTE   0x60
+#define VP880_CID_STATE_L2BYTE  0x80
+#define VP880_CID_STATE_URUN    0xA0
+
+/* New CID States for Rev D Silicon */
+#define VP880_CID_STATE_EMPTY_D     0x20
+#define VP880_CID_STATE_HALF_FULL_D 0x40
+#define VP880_CID_STATE_LBYTE_D     0x60
+#define VP880_CID_STATE_L2BYTE_D    0x80
+#define VP880_CID_STATE_FULL_D      0xC0
+#define VP880_CID_STATE_L3BYTE_D    0xE0
+
+#define VP880_CID_EOM_MASK      0x10
+#define VP880_CID_EOM           0x10
+#define VP880_CID_NEOM          0x00
+
+#define VP880_CID_FBDIS_MASK    0x08
+#define VP880_CID_FBIT_DIS      0x08
+#define VP880_CID_FBIT_EN       0x00
+
+#define VP880_CID_FB_START_MASK 0x04
+#define VP880_CID_FB_START_0    0x00
+#define VP880_CID_FB_START_1    0x04
+
+#define VP880_CID_FB_STOP_MASK  0x02
+#define VP880_CID_FB_STOP_0     0x00
+#define VP880_CID_FB_STOP_1     0x02
+
+#define VP880_CID_FRAME_BITS    0x06
+
+#define VP880_CID_CTRL_MASK     0x01
+#define VP880_CID_EN            0x00
+#define VP880_CID_DIS           0x01
+
+/**< Software Reset Command info */
+#define VP880_SW_RESET_WRT      0x02    /**< Software reset */
+#define VP880_SW_RESET_LEN      0x00
+
+/**< Pulse Period Detector Command info */
+#define VP880_PERIOD_DET_RD     0x1F
+#define VP880_PERIOD_DET_LEN    0x01    /**< Time between successive pulses */
+
+/**< Pulse Period Detector bit definitions */
+#define VP880_PULSE_PERIOD_DIVISOR      100ul
+#define VP880_PULSE_PERIOD_STEPSIZE     25ul    /**< 0.25mS/step */
+
+/**< Transmit and Receiver Timeslot Command info */
+#define VP880_TX_TS_WRT         0x40    /**< Transmit time slot write */
+#define VP880_TX_TS_RD          0x41    /**< Transmit time slot read */
+#define VP880_TX_TS_LEN         0x01
+#define VP880_TX_TS_MASK        0x7F
+
+#define VP880_RX_TS_WRT         0x42    /**< Receive time slot write */
+#define VP880_RX_TS_RD          0x43    /**< Receive time slot read */
+#define VP880_RX_TS_LEN         0x01
+#define VP880_RX_TS_MASK        0x7F
+
+/**< Internal Configuration Register 1 */
+#define VP880_ICR1_WRT      0xEC
+#define VP880_ICR1_RD       0xED
+
+#ifndef VP880_ICR1_LEN
+#define VP880_ICR1_LEN      0x04
+#endif
+
+#define VP880_ICR1_BIAS_OVERRIDE_LOCATION   0x00
+#define VP880_ICR1_TIP_BIAS_OVERRIDE        0xF0
+#define VP880_ICR1_LINE_BIAS_OVERRIDE       0x0F
+#define VP880_ICR1_LINE_BIAS_OVERRIDE_NORM  0x08
+
+#define VP880_ICR1_LINE_BIAS_LOCATION       0x01
+#define VP880_ICR1_LINE_BIAS                0x0F
+#define VP880_ICR1_TIP_BIAS_LOCATION        0x01
+#define VP880_ICR1_TIP_BIAS                 0xF0
+
+#define VP880_ICR1_RING_BIAS_OVERRIDE_LOCATION  0x02
+#define VP880_ICR1_RING_BIAS_OVERRIDE           0x0F
+
+#define VP880_ICR1_RING_AND_DAC_LOCATION    0x02
+#define VP880_ICR1_RING_AND_DAC_B2_3        0x06
+#define VP880_ICR1_RING_BIAS_DAC_MASK       0x0C
+
+#define VP880_ICR1_RING_BIAS_LOCATION       0x03
+#define VP880_ICR1_RING_BIAS                0x0F
+
+#define VP880_ICR1_TEST_LOAD_LOCATION       0x03
+#define VP880_ICR1_TEST_LOAD_MASK           0xC0
+#define VP880_ICR1_TEST_LOAD_NONE           0x00
+#define VP880_ICR1_TEST_LOAD_METALLIC       0x40
+#define VP880_ICR1_TEST_LOAD_LONGITUDINAL   0x80
+
+/**< Internal Configuration Register 2 */
+#define VP880_ICR2_WRT      0xEE
+#define VP880_ICR2_RD       0xEF
+
+#ifndef VP880_ICR2_LEN
+#define VP880_ICR2_LEN      0x04
+#endif
+
+#define VP880_ICR2_SENSE_INDEX      0x00
+#define VP880_ICR2_DAC_SENSE        0x80
+#define VP880_ICR2_ILA_DAC          0x80
+#define VP880_ICR2_FEED_SENSE       0x40
+#define VP880_ICR2_VOC_DAC_SENSE    0x20
+#define VP880_ICR2_ILA_FDRING_SENSE 0x10
+
+#define VP880_ICR2_TIP_SENSE        0x08
+#define VP880_ICR2_RING_SENSE       0x04
+#define VP880_ICR2_VOC_DAC_INDEX    0x00
+
+#define VP880_ICR2_MET_SPEED_INDEX  0x02
+#define VP880_ICR2_SWY_LIM_INDEX    0x02
+#define VP880_ICR2_FEED_CTRL_INDEX  0x02
+
+#define VP880_ICR2_SWY_CTRL_INDEX   0x02
+#define VP880_ICR2_SWY_CTRL_EN      0x20
+
+#define VP880_ICR2_MET_SPEED_CTRL   0x80
+#define VP880_ICR2_FEED_CTRL        0x40
+#define VP880_ICR2_SWY_LIM_CTRL1    0x08
+#define VP880_ICR2_SWY_LIM_CTRL     0x04
+
+#define VP880_ICR2_STATE_CTRL_INDEX 0x02
+#define VP880_ICR2_STATE_CTRL       0x20
+
+/**< Internal Configuration Register 3 */
+#define VP880_ICR3_WRT      0xF2
+#define VP880_ICR3_RD       0xF3
+
+#ifndef VP880_ICR3_LEN
+#define VP880_ICR3_LEN      0x04
+#endif
+
+#define VP880_ICR3_LINE_CTRL_INDEX      0x00
+#define VP880_ICR3_LINE_CTRL            0x20
+#define VP880_ICR3_SAT_LIM_25_CTRL      0x10
+#define VP880_ICR3_VREF_CTRL            0x01
+
+
+#define VP880_ICR3_LONG_UNCLAMP         0x40
+#define VP880_ICR3_LONG_UNCLAMP_INDEX   0x02
+#define VP880_ICR3_LONG_FIXED           0x10
+#define VP880_ICR3_LONG_FIXED_INDEX     0x00
+
+#define VP880_ICR3_LONG_LOOP_CTRL_LOCATION  0x02
+#define VP880_ICR3_LONG_LOOP_CONTROL        0x80
+#define VP880_ICR3_SE_RINGING_CONTROL       0x01
+
+/**< Internal Configuration Register 4 */
+#define VP880_ICR4_WRT      0xF4
+#define VP880_ICR4_RD       0xF5
+
+#ifndef VP880_ICR4_LEN
+#define VP880_ICR4_LEN      0x04
+#endif
+
+#define VP880_ICR4_VOICE_ADC_INDEX      0x00
+#define VP880_ICR4_VOICE_ADC_CTRL       0x01
+
+#define VP880_ICR4_SUP_INDEX            0x02
+#define VP880_ICR4_SUP_DAC_CTRL         0x08
+#define VP880_ICR4_SUP_DET_CTRL         0x04
+#define VP880_ICR4_SUP_POL_CTRL         0x02
+
+#define VP880_ICR4_GKEY_DET_LOCATION    0x02
+#define VP880_ICR4_GKEY_POL             0x10
+#define VP880_ICR4_GKEY_DET             0x01
+
+#define VP880_ICR5_WRT              0xFA
+#define VP880_ICR5_RD               0xFB
+#define VP880_ICR5_LEN              0x02
+
+#define VP880_ICR5_FEED_HOLD_INDEX  0x00
+
+#define VP880_ICR5_FEED_HOLD_MASK   0xF0
+#define VP880_ICR5_BAT_HOLD_MASK    0x0F
+#define VP880_ICR5_H2MS_BYTE        1
+#define VP880_ICR5_H2MS_MASK        0xF0
+#define VP880_ICR5_SUBST_MASK       0x0F
+
+/**< Internal Configuration Register 6 */
+#define VP880_ICR6_WRT      0xFC
+#define VP880_ICR6_RD       0xFD
+
+#ifndef VP880_ICR6_LEN
+#define VP880_ICR6_LEN      0x02
+#endif
+
+#define VP880_DC_CAL_REG_WRT    0xFC
+#define VP880_DC_CAL_REG_RD     0xFD
+#define VP880_DC_CAL_REG_LEN    0x02
+
+/* Upper Byte Bits */
+#define VP880_DC_CAL_ABS_INDEX          0
+#define VP880_DC_CAL_ABS_MASK           0xF0
+#define VP880_DC_CAL_BAT_SW_OVRD        0x08
+#define VP880_DC_CAL_OFFSET_OVRD        0x04
+#define VP880_DC_CAL_RSVD               0x03
+
+/* Lower Byte Bits */
+#define VP880_DC_CAL_CUT_INDEX          1
+#define VP880_EN_XB_SENSE               0x80
+#define VP880_C_RING_SNS_CUT            0x40
+#define VP880_C_TIP_SNS_CUT             0x20
+#define VP880_VOC_DC_CTRL               0x10
+#define VP880_DC_CAL_BAT_SW_MID         0x08
+#define VP880_DC_CAL_DIS_INPUT_OFFSET   0x04
+
+#define VP880_DCCAL_BAT_SW_HYST_MASK    0x03
+#define VP880_DCCAL_BAT_SW_HYST_1V      0x00
+#define VP880_DCCAL_BAT_SW_HYST_3V      0x01
+#define VP880_DCCAL_BAT_SW_HYST_5V      0x02
+#define VP880_DCCAL_BAT_SW_HYST_7V      0x03
+
+#define VP880_DC_CAL_BLIM_INDEX 1
+#define VP880_DC_CAL_BLIM       0x08
+
+
+/*
+ * In ms, before bias is removed in ground start workaround when the line has
+ * been set from Tip Open to any other state.
+ */
+#define VP880_GND_START_TIME        (210)
+#define VP880_LPM_GND_START_TIME    (30)
+
+/*
+ * The initial settings of the fake test load state take a while to settle the
+ * DC values of the battery.  Wait this time before disabling tip and ring bias
+ * to make tip and ring outputs high impedance, and tend to pull to battery.
+ * The SHORT time is used for ABS and non-fixed tracking devices.
+ * The LONG time is used for fixed trackers.
+ */
+#define VP880_INTERNAL_TESTTERM_SETTLING_TIME_SHORT (50)    /* ms */
+#define VP880_INTERNAL_TESTTERM_SETTLING_TIME_LONG  (200)   /* ms */
+
+/*
+ * In ms, before transitioning from Disconnect to feed state to prevent ping
+ * on the phone. This exists because the device does a short pol rev on the
+ * line when transitioning from Disconnect to a Feed state.
+ */
+#define VP880_PING_TIME         (30)
+
+
+/* 2ms To adjust for slow onhook detection.  125us increments */
+#define VP880_PULSE_DETECT_ADJUSTMENT   (16)
+
+
+#define VP880_TRACKER_DISABLE_TIME      (70)
+#define VP880_INVERT_BOOST_DISABLE_TIME (150)
+#define VP880_FIXED_TRACK_DISABLE_TIME  (400)
+
+
+#endif  /* Vp880_API_INT_H */
+
+
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_CSLAC_types.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_CSLAC_types.h
new file mode 100755
index 0000000..c5688e8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_CSLAC_types.h
@@ -0,0 +1,557 @@
+/** \file vp_CSLAC_types.h
+ * vp_CSLAC_types.h
+ *
+ * Header file for internal variables used in CSLAC type API.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8533 $
+ * $LastChangedDate: 2011-04-21 11:11:31 -0500 (Thu, 21 Apr 2011) $
+ */
+
+#ifndef VP_CSLAC_TYPES_H
+#define VP_CSLAC_TYPES_H
+
+#include "vp_api_fxo_params.h"
+#include "vp_api_timer.h"
+
+#define VP_CSLAC_DEV_PROFILE_VERSION_INT_SW_CONFIG_FR   5
+#define VP_CSLAC_DEV_PROFILE_VERSION_INT_SW_CONFIG      4
+#define VP_CSLAC_DEV_PROFILE_VERSION_LINECARD_PARAM     3
+#define VP_CSLAC_DEV_PROFILE_VERSION_VBH_REG            2
+#define VP_CSLAC_DEV_PROFILE_VERSION_SW_CONFIG          1
+
+#define VP_CSLAC_FXO_VERSION_DTMF_LEVEL                 1
+#define VP_CSLAC_FXO_VERSION_POH                        2
+
+#define VP_CSLAC_DC_PROFILE_VERSION_890                 1
+
+#define VP_CSLAC_RING_PROFILE_VERSION_890               1
+
+#define VP_CSLAC_TICKSTEP_0_5MS     0x80    /**< CSLAC Tickrate for 0.5mS */
+
+#define VP_CID_TIMESCALE    1   /**< Timescale in mS for CID time data */
+
+#define VP_CSLAC_DEV_PROF_TABLE_SIZE            1
+#define VP_CSLAC_AC_PROF_TABLE_SIZE             2
+#define VP_CSLAC_DC_PROF_TABLE_SIZE             2
+#define VP_CSLAC_RINGING_PROF_TABLE_SIZE        2
+#define VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE   11
+#define VP_CSLAC_TONE_PROF_TABLE_SIZE           10
+#define VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE   4
+#define VP_CSLAC_METERING_PROF_TABLE_SIZE       2
+#define VP_CSLAC_CALLERID_PROF_TABLE_SIZE       2
+#define VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE     1
+#define VP_CSLAC_CUSTOM_TERM_PROF_TABLE_SIZE    4
+
+#define VP_CSLAC_STD_TONE          0
+#define VP_CSLAC_HOWLER_TONE       4
+#define VP_CSLAC_AUS_HOWLER_TONE   8
+#define VP_CSLAC_NTT_HOWLER_TONE   12
+#define VP_CSLAC_TONE_TYPE         5
+
+#define VP_CSLAC_READ_RESPONSE_MASK (VP_LINE_EVID_LLCMD_RX_CMP \
+                                   | VP_LINE_EVID_RD_OPTION \
+                                   | VP_LINE_EVID_GAIN_CMP)
+
+typedef struct {
+    VpProfilePtrType pDevProfileTable[VP_CSLAC_DEV_PROF_TABLE_SIZE];
+    VpProfilePtrType pAcProfileTable[VP_CSLAC_AC_PROF_TABLE_SIZE];
+    VpProfilePtrType pDcProfileTable[VP_CSLAC_DC_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingingProfileTable[VP_CSLAC_RINGING_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneCadProfileTable[VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneProfileTable[VP_CSLAC_TONE_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingingCadProfileTable[VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pMeteringProfileTable[VP_CSLAC_METERING_PROF_TABLE_SIZE];
+    VpProfilePtrType pCallerIdProfileTable[VP_CSLAC_CALLERID_PROF_TABLE_SIZE];
+    VpProfilePtrType pFxoConfigProfileTable[VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE];
+    VpProfilePtrType pCustomTermProfileTable[VP_CSLAC_CUSTOM_TERM_PROF_TABLE_SIZE];
+} VpCSLACDeviceProfileTableType;
+
+/**
+ * The following structure is used by the device as a bitmask indicating
+ * whether or not a given profile table entry is valid. In the bit location a
+ * value '1' = profile is current, '0' = profile is not current.
+ */
+typedef struct {
+    uint16 devProfEntry;
+    uint16 acProfEntry;
+    uint16 dcProfEntry;
+    uint16 ringingProfEntry;
+    uint16 toneCadProfEntry;
+    uint16 toneProfEntry;
+    uint16 ringCadProfEntry;
+    uint16 meterProfEntry;
+    uint16 cidCadProfEntry;
+    uint16 fxoConfigProfEntry;
+    uint16 customTermProfEntry;
+} VpCSLACProfileTableEntryType;
+
+#define VP_PROF_ENTRY_INVALID   0
+#define VP_PROF_ENTRY_VALID     1
+
+typedef union {
+    VpOptionCriticalFltType criticalFaultOption;
+    VpOptionEventMaskType eventMaskOption;
+    VpOptionPulseModeType pulseModeOption;
+    VpOptionPulseType pulseTypeOption;
+    VpOptionRingControlType ringControlOption;
+    VpOptionZeroCrossType zeroCross;
+    VpOptionTimeslotType timeSlotOption;
+    VpOptionCodecType codecOption;
+    VpOptionPcmHwyType pcmHwyOption;
+    VpOptionLoopbackType loopBackOption;
+    VpOptionLineStateType lineStateOption;
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;
+    VpDeviceIoAccessDataType deviceIoData;
+    VpOptionDeviceIoType deviceIo;
+    VpLoopCondResultsType loopCond;
+    bool autoShutdownEn;
+    VpOptionAbsGainType absGain;
+} VpGetResultsOptionsDataType;
+
+typedef struct {
+    VpGetResultsOptionsDataType optionData;
+    uint8 chanId;
+    VpOptionIdType optionType;
+} VpGetResultsOptionsType;
+
+#define VP_CID_DTMF_ON_TIME    70   /**< Nominal 70mS +/- 5mS */
+#define VP_CID_DTMF_OFF_TIME   70   /**< Minimum 65mS */
+
+typedef enum {
+    VP_CID_GENERATOR_DATA,
+    VP_CID_GENERATOR_KEYED_CHAR,
+    VP_CID_SIGGEN_EOT,
+    VP_CID_NO_CHANGE,           /**< Load tones only, do not change generator
+                                 * state
+                                 */
+    VP_CID_GENERATOR_MARKOUT,
+    VP_CID_CTRL_TYPE_CNT,
+
+    VP_CID_GENC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCidGeneratorControlType;
+
+typedef enum {
+    VP_CID_RESET_VALUE = 0x0000,
+
+    VP_CID_IS_DEBOUNCE = 0x0001,        /**< Set when debounce has expired */
+    VP_CID_CLIAWAITTONE = 0x0002,
+    VP_CID_REPEAT_MSG = 0x0004,
+    VP_CID_AWAIT_TONE = 0x0008,         /**< Set if waiting for CPE ACK Tone */
+
+    VP_CID_TERM_FSK = 0x0010,           /**< Set if stopping FSK generator */
+    VP_CID_END_OF_MSG = 0x0020,         /**< Set if API detects an end of
+                                         * message in the buffered data
+                                         */
+    VP_CID_FSK_GEN_VALID = 0x0040,      /**< Set if FSK Generator is programmed
+                                         * for Caller ID signals.
+                                         */
+    VP_CID_IN_PROGRESS = 0x0080,        /**< Set if Caller ID is in progress */
+
+    VP_CID_ACTIVE_RING_SEQ = 0x0100,    /**< Set if active CID Ring sequence */
+    VP_CID_PRIMARY_FULL = 0x0200,       /**< Set when primary buffer contains
+                                         * CID data
+                                         */
+    VP_CID_SECONDARY_FULL = 0x0400,     /**< Set when secondary buffer contains
+                                         * CID data
+                                         */
+    VP_CID_PRIMARY_IN_USE = 0x0800,     /**< Set when primary buffer in use */
+    VP_CID_SECONDARY_IN_USE = 0x1000,   /**< Set when secondary buffer in use */
+    VP_CID_WAIT_ON_ACTIVE = 0x2000,     /**< Set when a "wait on" mode is
+                                         * active. Should only be cleared in
+                                         * the timer function (since currently
+                                         * support only for Wait on CID or time
+                                         */
+    VP_CID_MID_CHECKSUM = 0x4000,       /**< Set when a checksum value is being
+                                         * sent.
+                                         */
+    VP_CID_MUTE_ON = 0x8000,            /**< Set when a "Mute On" CID operator
+                                         * is active.
+                                         */
+    VP_CID_FSK_ACTIVE = 0x10000 /**< Set while the FSK Generator is needed */
+
+} VpCidStatusFlagType;  /* Update "status" if this size increases */
+
+typedef enum {
+    VP_CID_DTMF_RESET_VALUE = 0x0000,
+    VP_CID_ACTIVE_ON_TIME = 0x0001,
+    VP_CID_ACTIVE_OFF_TIME = 0x0002,
+    VP_CID_DTMFS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCidDtmfStatusType;
+
+/** Caller ID variables used by the line */
+typedef struct {
+    uint32 status;  /**< 'OR'ed combination of VpCidStatusFlagType */
+
+    VpCidDtmfStatusType dtmfStatus; /**< Used only for DTMF CID Message Data */
+
+    uint16 cliTimer;        /**< Time in increments of device ticks */
+    uint8 currentData;      /**< Data to repeat on the line */
+    uint16 cidCheckSum;     /**< Checksum to append to message data */
+
+    uint8 cliDebounceTime;  /**< Hook debouce specified in device ticks */
+    VpProfilePtrType pCliProfile;   /**< Currently running CID Profile */
+
+    VpDigitType cliDetectTone1;
+    VpDigitType cliDetectTone2;
+
+    uint8 cliMPIndex;       /**< Current Index into primary message buffer */
+    uint8 cliMSIndex;       /**< Current Index into secondary message buffer */
+
+    uint8 cliIndex;         /**< Current Index into profile data */
+
+    uint8 primaryBuffer[VP_SIZEOF_CID_MSG_BUFFER];
+    uint8 secondaryBuffer[VP_SIZEOF_CID_MSG_BUFFER];
+
+    uint8 primaryMsgLen;    /**< Length of data in the primary buffer */
+    uint8 secondaryMsgLen;  /**< Length of data in the secondary buffer */
+    VpDigitType digitDet;   /**< Stores the last DTMF digit detected during
+                             * Caller ID (if enabled via tone detection).
+                             */
+    /*
+     * At the end of FSK Message Data, some systems require a mark-out time. As
+     * specified in the Profile Wizard, this is defined in # of bytes with each
+     * byte corresponding to 8.33ms (1200 baud with 1 start + 1 stop + 8 data
+     * bits = 10/1200 = 8.33ms).
+     */
+    uint8 markOutByteCount;     /* Retains the value specified in the profile */
+    uint8 markOutByteRemain;    /* Current value remaining. Clean up when = 0 */
+} VpCallerIdType;
+
+typedef enum {
+    VP_CADENCE_RESET_VALUE = 0x0000,
+    VP_CADENCE_STATUS_ACTIVE = 0x0001,
+    VP_CADENCE_STATUS_BRANCHING  = 0x0002,
+    VP_CADENCE_STATUS_MID_TIMER  = 0x0004,
+    VP_CADENCE_STATUS_SENDSIG  = 0x0008,
+    VP_CADENCE_STATUS_METERING = 0x0010,
+    VP_CADENCE_STATUS_BRANCHING_LVL2  = 0x0020,
+    VP_CADENCE_STATUS_IGNORE_POLARITY = 0x0040,
+    VP_CADENCE_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCadenceStatusType;
+
+/** Variables to control the cadence on the line using the Sequencer */
+#define VP_CSLAC_MAX_BRANCH_DEPTH   2
+#define VP_CSLAC_BRANCH_LVL_0       0
+#define VP_CSLAC_BRANCH_LVL_1       1
+
+typedef struct {
+    VpProfilePtrType pActiveCadence;    /**< Currently Active Cadence */
+    VpProfilePtrType pCurrentPos;       /**< Current position in profile */
+
+    VpCadenceStatusType status;
+
+    uint8 index;        /**< Index in the the cadence table   */
+    uint8 length;       /**< Length of executable cadence instructions */
+
+    /**< Remaining number of repeats to perform for each branch depth */
+    uint8 count[VP_CSLAC_MAX_BRANCH_DEPTH];
+
+    uint16 timeRemain;
+    uint8 branchAt;     /**< Outermost step we're branching */
+    uint16 meteringBurst;   /**< Tracks the number of metering pulses sent */
+    bool meterPendingAbort; /**< Indicates that metering should abort after the
+                             * current pulse ends */
+    VpLineStateType meterAbortLineState; /**< The line state that should be set
+                                          * when metering aborts */
+
+    /* The following variables are for controlling signal generator ramp */
+#define VPCSLAC_MAX_GENERATOR_DATA 11
+    uint8 regData[VPCSLAC_MAX_GENERATOR_DATA];  /**< Scratchpad to reduce MPI
+                                                 * traffic.
+                                                 */
+    /*
+     * These values should correspond to device specific values for the
+     * freqency/level being set -- not a generic value.
+     */
+    uint16 startFreq;
+    bool isFreqIncrease;
+    uint16 stopFreq;
+    uint16 freqStep;    /**< Step size assumes a 50mS interval. */
+
+    uint16 startLevel;
+    uint16 stopLevel;
+    uint16 levelStep;  /**< Step size assumes a 50mS interval. Note: It is
+                        * possible to support a negative step, but the first
+                        * use of this function is UK type howler tone which only
+                        * increases in level.
+                        */
+} VpSeqDataType;
+
+/** Variables to control the CID sequence on the line using the CID Sequencer */
+typedef struct {
+    VpProfilePtrType pActiveCadence;    /**< Currently Active Cadence */
+    VpProfilePtrType pCurrentPos;       /**< Current position in profile */
+
+    uint8 index;        /**< Index in the the cadence table   */
+    uint16 timeRemain;
+} VpCidSeqDataType;
+
+typedef VpStatusType
+(*VpSeqInstructionFuncPtrType) (
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSequenceData);
+
+#define VP_SEQ_OPERATOR_MASK 0xE0
+#define VP_SEQ_SUBTYPE_MASK  0x1F
+#define VP_SEQUENCER_TICKRATE   0x0500  /* 5mS - Used with MS_TO_TICKRATE */
+
+/**< The super commands are the upper 3 bits of the command byte */
+typedef enum {
+    VP_SEQ_SPRCMD_COMMAND_INSTRUCTION = 0x00,
+    VP_SEQ_SPRCMD_TIME_INSTRUCTION = 0x20,
+    VP_SEQ_SPRCMD_BRANCH_INSTRUCTION = 0x40,
+    VP_SEQ_SPRCMD_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSeqSuperCommandsType;
+
+/**< The sub commands are the lower 5 bits of the command byte */
+typedef enum {
+    VP_SEQ_SUBCMD_SIGGEN = 0x00,
+    VP_SEQ_SUBCMD_LINE_STATE = 0x01,
+    VP_SEQ_SUBCMD_START_CID = 0x02,
+    VP_SEQ_SUBCMD_WAIT_ON = 0x07,   /**< Wait for CID or time to continue */
+
+    VP_SEQ_SUBCMD_RAMP_GENERATORS = 0x08,   /**< Forces frequency/amplitude
+                                             * change of the tone generator.
+                                             * Tone Cadence associated with this
+                                             * command must be specified as
+                                             * "ramp" type. The period between
+                                             * adjustments is fixed 50mS.
+                                             */
+
+    /**< API Internal Use only operators */
+    VP_SEQ_SUBCMD_METERING = 0x10,  /**< Cadence Metering */
+
+    VP_SEQ_SUBCMD_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSeqSubCommandsType;
+
+typedef enum {
+    VP_SEQ_SIGGEN_ALL_DISABLED = 0x00,
+    VP_SEQ_SIGGEN_A_EN = 0x01,
+    VP_SEQ_SIGGEN_B_EN = 0x02,
+    VP_SEQ_SIGGEN_C_EN = 0x04,
+    VP_SEQ_SIGGEN_D_EN = 0x08,
+    VP_SEQ_SIGGEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSeqSigGenCtrlType;
+
+typedef uint8 VpProfileCadencerStateTypes;
+#define VP_PROFILE_CADENCE_STATE_STANDBY            (0)
+#define VP_PROFILE_CADENCE_STATE_TIP_OPEN           (1)
+#define VP_PROFILE_CADENCE_STATE_TALK               (2)
+#define VP_PROFILE_CADENCE_STATE_ACTIVE             (3)
+#define VP_PROFILE_CADENCE_STATE_RSVD               (4)
+#define VP_PROFILE_CADENCE_STATE_OHT                (5)
+#define VP_PROFILE_CADENCE_STATE_DISCONNECT         (6)
+#define VP_PROFILE_CADENCE_STATE_RINGING            (7)
+#define VP_PROFILE_CADENCE_STATE_POLREV_STANDBY     (8)
+#define VP_PROFILE_CADENCE_STATE_POLREV_TIP_OPEN    (9)
+#define VP_PROFILE_CADENCE_STATE_POLREV_TALK        (10)
+#define VP_PROFILE_CADENCE_STATE_POLREV_ACTIVE      (11)
+#define VP_PROFILE_CADENCE_STATE_POLREV_RSVD        (12)
+#define VP_PROFILE_CADENCE_STATE_POLREV_OHT         (13)
+#define VP_PROFILE_CADENCE_STATE_POLREV_DISCONNECT  (14)
+#define VP_PROFILE_CADENCE_STATE_POLREV_RINGING     (15)
+#define VP_PROFILE_CADENCE_STATE_FXO_OHT            (16)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_OPEN      (17)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_CLOSE     (18)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_TALK      (19)
+#define VP_PROFILE_CADENCE_STATE_MSG_WAIT_NORM      (20)
+#define VP_PROFILE_CADENCE_STATE_MSG_WAIT_POLREV    (21)
+
+/* struct VpDialPulseDetectType is for FXS lines when detecting digits */
+typedef enum {
+    VP_DP_DETECT_STATE_LOOP_OPEN = 0,
+    VP_DP_DETECT_STATE_LOOP_CLOSE = 1,
+    VP_DP_DETECT_STATE_IDLE = 2
+} VpDialPulseDetectStatesType;
+
+typedef struct {
+    int digits;
+    uint16 lo_time;
+    uint16 lc_time;
+    VpDialPulseDetectStatesType state;   /**< Dial Pulse State Machine state */
+    bool hookSt;
+    uint8 signalingData;
+} VpDialPulseDetectType;
+
+/* struct VpDigitGenerationDataType is for FXO lines when generating digits */
+typedef struct {
+    uint16 dtmfOnTime;
+    uint16 dtmfOffTime;
+    uint8 breakTime;
+    uint8 makeTime;
+    uint16 flashTime;
+    uint16 dpInterDigitTime;
+    uint8 dtmfHighFreqLevel[2];
+    uint8 dtmfLowFreqLevel[2];
+} VpDigitGenerationDataType;
+
+/** Virtual Device Registers - Used to reduce MPI accesses to the Device */
+typedef struct {
+    uint8 sigRegMSB;    /**< Signaling Register's Most Significant byte */
+    uint8 sigRegLSB;    /**< Signaling Register's Least Significant byte */
+    uint8 iMaskMSB;     /**< Interrupt mask for the current line */
+    uint8 iMaskLSB;     /**< Interrupt mask for the current line */
+    uint8 iMaskMSBSP;   /**< Interrupt mask for the current line */
+    uint8 iMaskLSBSP;   /**< Interrupt mask for the current line */
+    uint8 ccR1SP;
+    uint8 ccR5SP;       /**< Scratchpad for CCR5 used during metering */
+    uint8 ccR8SP;       /**< Scratchpad for CCR8 used during calibration */
+    uint8 ioReg;        /**< IO Register for QSLAC SLIC states */
+} VpVirtualDeviceReg;
+
+/*
+ * IMPORTANT: Make sure to update the type used for "state" member inside
+ * objects, structs, and passed to functions where the comment states the value
+ * is a bit-mask of "VpDeviceStateType". Seach by "VpDeviceStateType".
+ * There are no instance of this type itself.
+ */
+typedef enum {
+    /**< Indicates if function is running from InitDevice. Not the same as in
+     * the middle of an initialization process (including calibration). Used to
+     * allow InitDevice function calling other functions to be enabled. Otherwise,
+     * some functions will return "Device Not Initialized" error.
+     */
+    VP_DEV_INIT_IN_PROGRESS = 0x0001,
+
+    VP_DEV_INIT_CMP = 0x0002,    /**< Set if device has been initialized */
+    VP_DEV_IN_CAL = 0x0004,      /**< Set if device is busy calibrating */
+    VP_DEV_PENDING_INT = 0x0008, /**< Set if there is a pending interrupt */
+
+    VP_DEV_ABS_BAT_CAL = 0x0010, /**< Set when running ABS (batt switch) Cal */
+    VP_DEV_ABV_CAL = 0x0020,     /**< Set when running ABV Calibration on Tracker */
+    VP_DEV_ABV_CAL_ABS = 0x0040, /**< Set when running ABV Calibration on ABS */
+    VP_DEV_DISC_PENDING = 0x0080, /**< Set when a Disconnect Timer was suspsended */
+
+    VP_DEV_TEST_BUFFER_READ = 0x0100, /**< Set if test buffer was read this tick */
+
+     /**< Set if device in process of warm reboot. Note that warm reboot
+      * detection alone only helps skipping of VpCalCodec() because it is run
+      * with VpInitDevice(). But it does not ensure that VpCalLine() was
+      * previously run.
+      */
+    VP_DEV_WARM_REBOOT = 0x0200
+
+} VpDeviceStateType;
+
+typedef struct {
+    uint16 state;           /**< This is a bit-mask of VpDeviceStateType values */
+    uint8 globStatReg;      /**< Holds state of the device stat reg */
+    uint8 calibrating;      /**< Calibration timer */
+    uint8 numIntServiced;   /**< Max interrupts to be serviced during tick */
+} VpCSLACDeviceStatusType;
+
+#define VP_CSLAC_MAX_RCN_PCN_SIZE   2
+typedef struct {
+    uint8 rcnPcn[VP_CSLAC_MAX_RCN_PCN_SIZE];    /**< Revision Code Number and
+                                                 * Product Code Number as
+                                                 * applicable
+                                                 */
+    uint8 maxChannels;  /**< How many lines supported by this device */
+} VpDeviceStaticInfoType;
+
+typedef struct {
+    uint8 lastChan;     /**< The last line checked */
+    bool clkFault;      /** TRUE if a clock fault is active */
+    bool bat1Fault;     /** TRUE if a bat1 fault is active and device level */
+    bool bat2Fault;     /** TRUE if a bat2 fault is active and device level */
+    bool bat3Fault;     /** TRUE if a bat3 fault is active and device level */
+} VpDeviceDynamicInfoType;
+
+/** Line state variables used by the line (api internal) */
+typedef enum {
+    VP_CSLAC_STATUS_INVALID = 0x0000,
+
+    /* FXS Type Status */
+    VP_CSLAC_HOOK = 0x0001,
+    VP_CSLAC_GKEY = 0x0002,
+
+    /* FXO Type Status */
+    VP_CSLAC_RAW_DISC = 0x0001,     /*
+                                     * Set on 890 when device level disconnect
+                                     * status is set. Cleared otherwise.
+                                     */
+
+    VP_CSLAC_RINGING = 0x0004,      /**< Set when Ringing detected on Line */
+    VP_CSLAC_DISC = 0x0008,         /**< Set when Disconnect detected on Line */
+
+    VP_CSLAC_AC_FLT = 0x0010,
+    VP_CSLAC_DC_FLT = 0x0020,
+    VP_CSLAC_THERM_FLT = 0x0040,
+    VP_CSLAC_CAL_ENABLE = 0x0080,   /**< Set when the line is in a state that
+                                     * will allow device calibration
+                                     */
+
+    VP_CSLAC_CAL_FAIL = 0x0100,
+    VP_CSLAC_POLREV = 0x0200,
+    VP_CSLAC_POLREV_REPORTED = 0x0400,
+    VP_CSLAC_LIU = 0x0800,
+
+    VP_CSLAC_LINE_LEAK_TEST = 0x1000,   /**< Set when line is being tested for
+                                         * resistive leak. Clear when test is
+                                         * complete.
+                                         */
+    VP_CSLAC_RING_AMP_DET = 0x2000,
+    VP_CSLAC_RINGING_EXIT = 0x4000, /**< Set when FXS line is exiting Ringing */
+
+    VP_CSLAC_STATUS_VALID = 0x8000
+} VpCslacLineCondType;
+
+typedef enum {
+    VP_CSLAC_CAL_NONE = 0x0000,
+    VP_CSLAC_CAL_VOC,
+    VP_CSLAC_CAL_VAG,
+    VP_CSLAC_CAL_VBG,
+    VP_CSLAC_CAL_ILA,
+#ifdef VP880_TRACKER_SUPPORT
+    VP_CSLAC_CAL_VAS,
+#endif
+    VP_CSLAC_CAL_ABV,
+    VP_CSLAC_CAL_CLEANUP,
+    VP_CSLAC_CAL_TYPE_SIZE,
+    VP_CSLAC_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCslacCalType;
+
+typedef struct {
+    VpLineStateType currentState;   /**< Current state of the line */
+    VpLineStateType previous;   /**< Previous sate of the line */
+
+    VpLineStateType usrCurrent; /**< Current user set state of the line */
+
+    VpCslacLineCondType condition;
+    VpCslacCalType calType;
+} VpApiIntLineStateType;
+
+typedef enum
+{
+    VP_CUSTOM_TERM_SLIC_TYPE = 6,
+    VP_CUSTOM_TERM_NUM_STATES = 7,
+    VP_CUSTOM_TERM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} vpCustomTermProfileParams;
+
+typedef enum
+{
+    VP_FXO_DIAL_PRFL_DTMF_ON_MSB = 6,
+    VP_FXO_DIAL_PRFL_DTMF_ON_LSB = 7,
+    VP_FXO_DIAL_PRFL_DTMF_OFF_MSB = 8,
+    VP_FXO_DIAL_PRFL_DTMF_OFF_LSB = 9,
+    VP_FXO_DIAL_PRFL_FLASH_HOOK_MSB = 10,
+    VP_FXO_DIAL_PRFL_FLASH_HOOK_LSB = 11,
+    VP_FXO_DIAL_PRFL_PULSE_BREAK = 12,
+    VP_FXO_DIAL_PRFL_PULSE_MAKE = 13,
+    VP_FXO_DIAL_PRFL_INTERDIG_MSB = 14,
+    VP_FXO_DIAL_PRFL_INTERDIG_LSB = 15,
+    VP_FXO_DIAL_PRFL_RING_PRD_MAX = 16,
+    VP_FXO_DIAL_PRFL_RING_PRD_MIN = 17,
+    VP_FXO_DIAL_PRFL_RING_VOLT_MIN = 18,
+    VP_FXO_DIAL_PRFL_DISC_VOLT_MIN = 19,
+    VP_FXO_DIAL_PRFL_LIU_THRESH_MIN = 20,
+    VP_FXO_DIAL_PRFL_RSVD = 21,
+    VP_FXO_DIAL_PRFL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} vpCslac_fxo_dialPrflParams;
+#endif
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api.h
new file mode 100755
index 0000000..0a28172
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api.h
@@ -0,0 +1,147 @@
+/** \file vp_api.h
+ * vp_api.h
+ *
+ * Header file for the API-II c files.
+ *
+ * This file contains the all of the VoicePath API-II function prototypes. This
+ * file should be used to bring in the VP-API-II library modules that are
+ * necessary for a given application.
+ *
+ *****************************************************************************
+ * NOTE: Inclusion of only this file is sufficient to bring in the all the   *
+ * necessary aspects of VP_API.                                              *
+ *****************************************************************************
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8620 $
+ * $LastChangedDate: 2011-06-02 13:27:26 -0500 (Thu, 02 Jun 2011) $
+ */
+
+
+#ifndef VP_API_H
+#define VP_API_H
+
+/******************************************************************************
+ * VP-API Version                                                             *
+ *****************************************************************************/
+/*
+ * The following version number tag is updated at every release of the VP-API.
+ * Since the VP-API is a common interface that supports more than one device,
+ * version number change might occur when any aspect of the VP-API gets
+ * released.
+ */
+#define VP_API_VERSION_TAG (0x021201)
+
+#define VP_API_VERSION_MAJOR_NUM ((VP_API_VERSION_TAG) >> 16)
+#define VP_API_VERSION_MINOR_NUM (((VP_API_VERSION_TAG) & 0x00FF00) >> 8)
+#define VP_API_VERSION_MINI_NUM (((VP_API_VERSION_TAG) & 0x0FF))
+
+/* First include various basic data types used in the API */
+#include "vp_api_types.h"
+
+/******************************************************************************
+ * Defines the configuration of VP-API library that needs to be built.        *
+ * Please modify the following include file as per your VP-API library        *
+ * requirement(s).                                                            *
+ ******************************************************************************/
+#include "vp_api_cfg.h"
+
+/******************************************************************************
+ *                  PLEASE DO NOT MODIFY BELOW THIS LINE                      *
+ ******************************************************************************/
+/* Include the main VP-API-Common file */
+#include "vp_api_common.h"
+
+/* Include the VP-API-Header file required for the CSLAC sequencer */
+#if defined (VP_CSLAC_SEQ_EN)
+#include "vp_api_cslac_seq.h"
+#endif
+
+/* Include the necessary files depending on the requirement of the project */
+#if defined (VP_CC_790_SERIES)
+#include "vp790_api.h"    /* Vp790 device specific API functions and typedefs */
+#endif
+
+/* Include the necessary files depending on the requirement of the project */
+#if defined (VP_CC_792_SERIES)
+#include "vp792_api.h"    /* Vp790 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_880_SERIES)
+#include "vp880_api.h"    /* Vp880 device specific API functions and typedefs */
+
+/*
+ * For 0823 LM, the FXO CID line is controlled by I/O3. For 0803 LM, it's
+ * controlled by I/O2. Control with I/O3 is better since I/O2 has more features
+ *
+ *  #define VP880_FXO_CID_LINE      VP880_IODATA_IO2    Use with 0803 ref
+ *  #define VP880_FXO_CID_LINE      VP880_IODATA_IO3    Use with 0823 ref
+ */
+#define VP880_FXO_CID_LINE      VP880_IODATA_IO3
+#endif
+
+#if defined (VP_CC_890_SERIES)
+#include "vp890_api.h"    /* Vp890 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_580_SERIES)
+#include "vp580_api.h"    /* Vp580 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_VCP_SERIES)
+#include "dvp_api.h"     /* VCP device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_VCP2_SERIES)
+#include "vcp2_api.h"     /* VCP2 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_MELT_SERIES)
+#include "melt_api.h"     /* VCP2 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_KWRAP)
+#include "vp_kernel.h"    /* KWRAP device specific API functions and typedefs */
+#endif
+
+/* Macros for calling a device-specific API function using the pointer in the
+   Device Context: */
+typedef void (*VpTempFuncPtrType) (void);
+
+#define VP_CALL_DEV_FUNC(func, args) \
+    (((pDevCtx->funPtrsToApiFuncs.func) == VP_NULL) ? VP_STATUS_FUNC_NOT_SUPPORTED : (pDevCtx->funPtrsToApiFuncs.func) args )
+
+/*
+ * Based on the existing structure of the include files the following def
+ * have been moved here.
+ */
+
+#if defined(VP_CC_880_SERIES) || defined(VP_CC_790_SERIES) || defined(VP_CC_890_SERIES)
+
+  typedef union {
+      uint8 dummy; /* preventing an empty union */
+  #if defined(VP_CC_880_SERIES) && defined(VP880_INCLUDE_TESTLINE_CODE)
+    Vp880TestHeapType vpTestHeap880;
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+
+  #if defined(VP_CC_890_SERIES) && defined(VP890_INCLUDE_TESTLINE_CODE)
+    Vp890TestHeapType vpTestHeap890;
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+
+  #if defined(VP_CC_790_SERIES) && defined(VP790_INCLUDE_TESTLINE_CODE)
+    /* Vp790TestHeapType vpTestHeap790; */
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+} VpTestHeapType;
+#else
+typedef char VpTestHeapType;
+#endif
+
+#endif /* VP_API_H */
+
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_cfg.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_cfg.h
new file mode 100755
index 0000000..eaf509f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_cfg.h
@@ -0,0 +1,117 @@
+/** \file vp_api_cfg.h
+ * vp_api_cfg.h
+ *
+ * This file contains the configuration and compile time settings for
+ * building appropriate VP-API library modules needed for any application.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8674 $
+ * $LastChangedDate: 2011-06-22 10:13:07 -0500 (Wed, 22 Jun 2011) $
+ */
+
+#ifndef VP_API_CFG_H
+#define VP_API_CFG_H
+
+#ifdef MV_KERNEL_SLIC_SUPPORT
+#include "mvOs.h"
+#include "mvSysTdmConfig.h"
+#endif
+
+#include "vp_debug_masks.h"
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: API DEBUG OUTPUT SELECTIONS                         *
+ *****************************************************************************/
+
+/*
+ * If VP_DEBUG is undefined, then ALL debug messages will be compiled out.
+ * In this case, the code size will be smaller, but debug output CANNOT be
+ * enabled at runtime.
+ */
+#define VP_DEBUG
+
+/*
+ * Choose which types of debug messages to be compiled in.  Only these message
+ * types can be enabled at runtime.  See vp_debug_masks.h for a list of debug
+ * message types.
+ */
+#define VP_CC_DEBUG_SELECT (VP_DBG_ALL)
+
+/*
+ * The VP_OPTION_ID_DEBUG_SELECT option enables/disables debug output at
+ * runtime.  Define the default value of this option here.  The option will be
+ * automatically set to the default value at device initialization.  See
+ * vp_debug_masks.h for a list of debug message types.
+ *
+ * Note: The VP_OPTION_ID_DEBUG_SELECT option can be changed with VpSetOption()
+ *       only AFTER device initialization (VpInitDevice()).  If you wish to
+ *       see debug output messages during device initialization, you must set
+ *       the default VP_OPTION_ID_DEBUG_SELECT value accordingly.
+ */
+#define VP_OPTION_DEFAULT_DEBUG_SELECT  0
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: Conditionally-Compiled API Libraries                *
+ *****************************************************************************/
+
+/*
+ * Define (or undefine) the appropriate compile time switches based on your
+ * application needs.
+ *
+ * NOTE: Such library selection compile time option(s) MUST be defined before
+ * including any other file from VoicePath library.
+ *
+ * NOTE: More than one Library modules can be built simultaneosuly (if needed).
+ */
+
+#define VP_CC_792_SERIES    /**< define to build 792 specific API library;
+                             *   undef to exclude this library. */
+ 
+
+/******************************************************************************
+ * Include Files for the API                                                  *
+ *****************************************************************************/
+/* Include the API types for this architecture */
+#include "vp_api_types.h"
+
+/******************************************************************************
+ * Library Specific COMPILE-TIME OPTIONS and defines                          *
+ *****************************************************************************/
+#ifdef VP_CC_792_SERIES
+
+#undef VP_COMMON_ADDRESS_SPACE         /* Define if all VP-API-II data
+                                           structures (Line Objects, Line Contexts,
+                                           Device Objects, Device Contexts, Profiles)
+                                           are accessible at the same address in
+                                           all processes (tasks) which call VP-API-II
+                                           functions. */
+
+#define VP_CC_792_GROUP                 /* Define to include support for sharing
+                                         * an interrupt pin between multiple
+                                         * VP792 devices. */
+
+#define VP792_MAILBOX_SPINWAIT 50000    /* Number of times to poll the device's
+                                           command mailbox before returning
+                                           VP_STATUS_MAILBOX_BUSY. */
+
+#define VP792_SUPPORT_792388_REV_F_SILICON /* Define this if you want to support
+                                              Revision F of the Le792388 silicon. An
+                                              appropriate SLAC firmware patch will
+                                              be compiled in. */
+#define VP792_SUPPORT_792588_REV_B_SILICON /* Define this if you want to support
+                                              Revision B of the Le792588 silicon. An
+                                              appropriate SLAC firmware patch will
+                                              be compiled in. */
+#define EXTENDED_FLASH_HOOK
+
+#endif /* VP_CC_792_SERIES */
+
+typedef uint8 VpScratchMemType;
+
+/* Include internal options required to build the VP-API-II library */
+#include "vp_api_cfg_int.h"
+
+#endif /* VP_API_CFG_H */
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_cfg_int.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_cfg_int.h
new file mode 100755
index 0000000..e42cda2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_cfg_int.h
@@ -0,0 +1,412 @@
+/** \file vp_api_cfg_int.h
+ * vp_api_cfg_int.h
+ *
+ * This file contains internal configuration and compile time settings for
+ * building appropriate VP-API library modules needed for any application.
+
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 6419 $
+ * $LastChangedDate: 2010-02-12 16:40:10 -0600 (Fri, 12 Feb 2010) $
+ */
+
+#ifndef VP_API_CFG_INT_H
+#define VP_API_CFG_INT_H
+
+/******************************************************************************
+ * Device Context Size                                                        *
+ *****************************************************************************/
+/*
+ * Define the maximum number of lines per device in your system. Note that a
+ * system (i.e., all devices controlled by one instance of VP-API) could have
+ * more than one type of device, each of those devices may support different
+ * number of lines. For example in a system, device A might support 4 lines
+ * and device B might support 32 lines, in such a scenario, the following macro
+ * should be defined as 32. */
+#if defined(VP_CC_VCP2_SERIES) || defined(VP_CC_KERNEL_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (128)
+#elif defined(VP_CC_VCP_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (32)
+#elif defined(VP_CC_792_SERIES) || defined(VP_CC_MELT_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (8)
+#elif defined(VP_CC_790_SERIES) || defined(VP_CC_580_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (4)
+#else /* VP_CC_880_SERIES + VP_CC_890_SERIES */
+    /*
+     * Note that for VE890 this value must be >=2 even when using the single
+     * FXO device. That's because the line context pointer in the device
+     * context is assigned to the "channelId" element of the line context
+     * pointer array. The FXO channelId = 1 so the array must be size >= 2.
+     */
+    #define VP_MAX_LINES_PER_DEVICE     (2)
+#endif
+
+/* Special Case for Kernel Wrapper */
+#if defined(VP_CC_KWRAP)
+  #undef VP_MAX_LINES_PER_DEVICE
+  #define VP_MAX_LINES_PER_DEVICE (128)
+#endif
+
+/******************************************************************************
+ * Library Specific COMPILE-TIME OPTIONS and defines                          *
+ *****************************************************************************/
+/* #if defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES) */
+    #define CSLAC_GAIN_RELATIVE
+    #define CSLAC_GAIN_ABS
+/* #endif */
+
+/*
+ * The following values exist for Zarlink test purposes only. DO NOT
+ * change to #define in production code. Unexpected or damaging behavior may
+ * occur.
+ */
+#define VP_ENABLE_PROD_TEST
+
+#ifdef VP_CC_880_SERIES
+
+/*
+ * DO NOT CHANGE the following to #define. This enables experimental code that
+ * is not provided with the VP-API-II installation.
+ */
+#undef  VP880_AUTO_BAT_DETECT
+
+/*
+ * Modifications to previous settings to correct for potential inconsistencies.
+ * DO NOT CHANGE anything below this line. All corrections should be made above
+ */
+#if !defined (VP880_TRACKER_SUPPORT) && defined (VP880_LP_SUPPORT)
+    #error "Invalid 880 Compiler Combination: Low Power Mode Requires Tracker defined"
+#endif
+
+#if defined (VP880_FXS_SUPPORT) && (!defined (VP880_ABS_SUPPORT) && !defined (VP880_TRACKER_SUPPORT))
+    #error "Invalid 880 Compiler Combination: FXS requires either ABS or Tracker defined"
+#endif
+
+#ifndef VP880_FXS_SUPPORT
+    #undef VP880_ABS_SUPPORT
+    #undef VP880_INCLUDE_TESTLINE_CODE
+    #undef VP880_LP_SUPPORT
+#endif
+
+#if !defined (VP880_FXS_SUPPORT) && !defined (VP880_FXO_SUPPORT)
+    #error "Invalid 880 Compiler Combination: Either FXS or FXO must be defined if using VE880 device"
+#endif
+
+/*
+ * Current Limiting option in the VP880 library limits the peak switcher current
+ * such that a 3REN load can be supported at 90V peak. Disable this option if
+ * 5REN is required.
+ */
+#undef  VP880_CURRENT_LIMIT
+
+#endif /* VP_CC_880_SERIES */
+
+#if (defined (VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) || defined(VP_CC_KWRAP)
+    /*
+     * #defines used in unit conversion function
+     * All units are based on the following calculations
+     *      Internal voltage unit   = 480.0  / 2^31 Volts
+     *      Internal current unit   = 240e-3 / 2^31 Amps
+     *      Internal freq uint      = 12e3   / 2^31 Hz
+     */
+    #define VP880_UNIT_MV                          4474L    /* mV unit */
+    #define VP880_UNIT_MVRMS                       6327L    /* mVrms unit */
+    #define VP880_UNIT_ADC_VAB                     -32768L  /* vab step from ADC */
+    #define VP880_UNIT_ADC_VAB_RMS                 46341L   /* vab step from ADC rms*/
+    #define VP880_UNIT_ADC_AC_VAB_RMS                664L   /* vab step from ADC Metallic Vrms*/
+    #define VP880_UNIT_DAC_RING                    21076L   /* step due to DAC in ringing*/
+    #define VP880_UNIT_TRACK_SWZ                23091612L   /* step used for tracking switching regulator Z */
+    #define VP880_UNIT_UA                          8948L    /* uA unit */
+    #define VP880_UNIT_ADC_IMET_NOR                16384L   /* met I from ADC in normal VC */
+    #define VP880_UNIT_ADC_IMET_NOR_JA             15756L   /* met I from ADC in normal JA*/
+    #define VP880_UNIT_ADC_IMET_RING               32768L   /* met I from ADC in ringing*/
+    #define VP880_UNIT_ADC_ILG                     11469L   /* long current from ADC*/
+    #define VP880_UNIT_DECHZ                       17896L   /* Deci Hz*/
+    #define VP880_UNIT_MHZ                         179L     /* mHz */
+    #define VP880_UNIT_FREQ                        65536L   /* siggen freq step */
+    #define VP880_UNIT_RAMP_TIME                   1365L    /* Ramp time (-1/3) in ms*/
+
+    #define VP880_UNIT_CONVERT(DATA, I_UNIT, O_UNIT)    (int32)(((int32)DATA * I_UNIT) / O_UNIT)
+
+    /* converts requested slope into SigGen Freq */
+    #define VP880_SLOPE_TO_FREQ(AMP,SLOPE)  (int16)(((int32)SLOPE * (int32)VP880_UNIT_RAMP_TIME) / (int32)AMP)
+
+    #define VP880_AC_RLOOP_MAX_BAT_LVL              75000L /* mV */
+    #define VP880_AC_RLOOP_MAX_TEST_LVL         ((VP880_AC_RLOOP_MAX_BAT_LVL - 5000) / 2)
+
+#endif /*VP880_INCLUDE_TESTLINE_CODE*/
+
+
+#ifdef VP_CC_890_SERIES
+
+#define VP890_REL_GAIN_GX_LOW_LIMIT     (0x500)
+#define VP890_REL_GAIN_GR_LOW_LIMIT     (0x1000)
+
+#ifndef VP890_FXS_SUPPORT
+    /*
+     * Tests (using testline) is supported only for FXS termination types. If
+     * line tests are required, make sure FXS support is enabled.
+     */
+    #undef VP890_INCLUDE_TESTLINE_CODE
+
+    /* LPM is an FXS termination type. FXS must be supported to support LPM. */
+    #undef  VP890_LP_SUPPORT
+#endif
+
+/* Define this to attempt to reduce the level of the noise signal generated for
+ * adaptive balance B-Filter calibration.  Reducing the level will increase the
+ * negative effect of outside noise on the line and can reduce performance */
+#undef VP890_REDUCE_BFILTER_CAL_SIGNAL_LEVEL
+
+#endif /* VP_CC_890_SERIES*/
+
+#if (defined (VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE)) || defined(VP_CC_KWRAP)
+    /*
+     * #defines used in unit conversion function
+     * All units are based on the following calculations
+     *      Internal voltage unit   = 480.0  / 2^31 Volts
+     *      Internal current unit   = 240e-3 / 2^31 Amps
+     *      Internal freq uint      = 12e3   / 2^31 Hz
+     */
+    #define VP890_UNIT_MV                          4474L    /* mV unit */
+    #define VP890_UNIT_MVRMS                       6327L    /* mVrms unit */
+    #define VP890_UNIT_ADC_VAB                     -32768L  /* vab step from ADC */
+    #define VP890_UNIT_ADC_VAB_RMS                 46341L   /* vab step from ADC rms*/
+    #define VP890_UNIT_ADC_AC_VAB_RMS              664L     /* vab step from ADC Metallic Vrms*/
+    #define VP890_UNIT_DAC_RING                    21076L   /* step due to DAC in ringing*/
+    #define VP890_UNIT_TRACK_SWZ                23091612L   /* step used for tracking switching regulator Z */
+    #define VP890_UNIT_UA                          8948L    /* uA unit */
+    #define VP890_UNIT_ADC_IMET_NOR                15756L   /* met I from ADC in normal*/
+    #define VP890_UNIT_ADC_IMET_RING               32768L   /* met I from ADC in ringing*/
+    #define VP890_UNIT_ADC_ILG                     11469L   /* long current from ADC*/
+    #define VP890_UNIT_DECHZ                       17896L   /* Deci Hz*/
+    #define VP890_UNIT_MHZ                         179L     /* mHz */
+    #define VP890_UNIT_FREQ                        65536L   /* siggen freq step */
+    #define VP890_UNIT_RAMP_TIME                   1365L    /* Ramp time (-1/3) in ms*/
+
+    #define VP890_UNIT_CONVERT(DATA, I_UNIT, O_UNIT) (int32)( ((int32)DATA * I_UNIT) / O_UNIT)
+
+    /* converts requested slope into SigGen Freq */
+    #define VP890_SLOPE_TO_FREQ(AMP,SLOPE) (int16) ( ((int32)SLOPE * (int32)VP890_UNIT_RAMP_TIME) / (int32)AMP)
+
+    #define VP890_AC_RLOOP_MAX_BAT_LVL              75000L /* mV */
+    #define VP890_AC_RLOOP_MAX_TEST_LVL             ((VP890_AC_RLOOP_MAX_BAT_LVL - 5000) / 2)
+
+#endif /* VP890_INCLUDE_TESTLINE_CODE */
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: Top level VP-API Default Device and Line Options    *
+ *****************************************************************************/
+
+/* Debounce time to mask hook activity when a pol rev is generated */
+/*
+ * This duration covers conditions of 5REN FCC Part 68 load with 16ms Switch
+ * Hook Debounce. Applications are not expected to have much higher REN or longer
+ * Switch Hook Debounce times. If needed, this value can be changed but note
+ * that it affects all CSLAC devices.
+ */
+#define VP_POLREV_DEBOUNCE_TIME     (120)
+
+/*
+ *  The following defines specify the default settings of the device and line
+ * options used in the API. The VP-API-II should generally take on the default
+ * settings set here at VpInitDevice()/VpInitLine() but is not guaranteed (i.e.,
+ * the combinations are not tested - VpInitDevice()/InitLine() could fail as a
+ * result of setting to unexpected values).
+ *
+ * Please consult Zarlink Field or Applications support before changing any of
+ * these settings.
+ */
+#include "vp_api_option.h"
+#include "vp_api_event.h"
+
+/* Default Dial Pulse Options specified in units of 125micro sec  */
+#define VP_OPTION_DEFAULT_DP_BREAK_MIN          (33 * 8)    /* == 33 ms */
+#define VP_OPTION_DEFAULT_DP_BREAK_MAX          (100 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MIN           (17 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MAX           (75 * 8)
+#define VP_OPTION_DEFAULT_DP_INTER_DIG_MIN      (250 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MIN          (250 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MAX          (1300 * 8)
+#define VP_OPTION_DEFAULT_DP_ON_HOOK_MIN        VP_OPTION_DEFAULT_DP_FLASH_MAX
+#define VP_OPTION_DEFAULT_DP_OFF_HOOK_MIN       0
+
+/*
+ * Specification 2 is usefull if you need to detect between two non-overlapping
+ * dial pulse specifications.
+ */
+#define VP_OPTION_DEFAULT_DP_BREAK_MIN2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_BREAK_MAX2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MIN2          (0 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MAX2          (0 * 8)
+#define VP_OPTION_DEFAULT_DP_INTER_DIG_MIN2     (0 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MIN2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MAX2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_ON_HOOK_MIN2       (0 * 8)
+
+/* Default setting for Critical fault option */
+#define VP_OPTION_DEFAULT_CF_AC_DIS_EN          TRUE
+#define VP_OPTION_DEFAULT_CF_DC_DIS_EN          TRUE
+#define VP_OPTION_DEFAULT_CF_THERMAL_DIS_EN     TRUE
+/* CSLAC-880 and VCP-880 do not support the detection of AC, DC critical faults.
+ * So, The VP-API uses the following default values for those devices.
+ * Note that changing the following values will result in VpInitDevice()
+ * failure. */
+#define VP_OPTION_DEFAULT_CF_AC_DIS_EN_880      FALSE
+#define VP_OPTION_DEFAULT_CF_DC_DIS_EN_880      FALSE
+
+/* Default setting for Zero cross option */
+#define VP_OPTION_DEFAULT_ZERO_CROSS            VP_OPTION_ZC_M4B
+
+/* Default setting for Ramp to standby option */
+#define VP_OPTION_DEFAULT_RAMP2STBY             0
+
+/* Default setting for Pulse mode option */
+#define VP_OPTION_DEFAULT_PULSE_MODE            VP_OPTION_PULSE_DECODE_OFF
+
+/* Default CODEC Mode */
+#define VP_OPTION_DEFAULT_CODEC_MODE            VP_OPTION_ALAW
+
+/* Default setting for PCM Highway option */
+#define VP_OPTION_DEFAULT_PCM_HWY               VP_OPTION_HWY_A
+
+/* Default setting for Loop back option */
+#define VP_OPTION_DEFAULT_LOOP_BACK             VP_OPTION_LB_OFF
+
+/* Default setting for Line state option */
+#define VP_OPTION_DEFAULT_LS_BAT_REV            FALSE
+#define VP_OPTION_DEFAULT_LS_BAT                VP_OPTION_BAT_AUTO
+
+/*
+ * Default Event Masks (VP_OPTION_ID_EVENT_MASK)
+ * The user can arbitrarily set the mask bits here as needed.  A mask bit set to
+ * '0' means the event is not masked.  Some events are non-maskable.
+ */
+#define VP_OPTION_DEFAULT_FAULT_EVENT_MASK      (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_FAULT_EVENTS)
+#define VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK  (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_SIGNALING_EVENTS)
+#define VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK   (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_RESPONSE_EVENTS)
+#define VP_OPTION_DEFAULT_TEST_EVENT_MASK       (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_TEST_EVENTS)
+#define VP_OPTION_DEFAULT_PROCESS_EVENT_MASK    (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_PROCESS_EVENTS)
+#define VP_OPTION_DEFAULT_FXO_EVENT_MASK        (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_FXO_EVENTS)
+#define VP_OPTION_DEFAULT_PACKET_EVENT_MASK     (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_PACKET_EVENTS)
+
+/* Default setting for Ring Control option */
+#define VP_OPTION_DEFAULT_RC_ZERO_CROSS         VP_OPTION_ZC_M4B
+#define VP_OPTION_DEFAULT_RC_RING_EXIT_DBNC_VAL (100 * 8) /* 100ms */
+#define VP_OPTION_DEFAULT_RC_RING_EXIT_STATE    VP_LINE_TALK
+
+/* Default setting for DTMF Mode option */
+#define VP_OPTION_DEFAULT_DM_DTMF_CONTROL_MODE  VP_OPTION_DTMF_DECODE_OFF
+#define VP_OPTION_DEFAULT_DM_DIRECTION          VP_DIRECTION_US
+
+/* Default setting for PCM TX/RX path control */
+#define VP_OPTION_DEFAULT_PCM_TXRX_CNTRL        VP_OPTION_PCM_BOTH
+
+/* Default setting for DTMF Spec option */
+#define VP_OPTION_DEFAULT_DTMF_SPEC             VP_OPTION_DTMF_SPEC_ATT
+
+/* Default setting for Park Mode option */
+#define VP_OPTION_DEFAULT_PARK_MODE_DISC        4   /* 2 seconds */
+#define VP_OPTION_DEFAULT_PARK_MODE_STANDBY     3   /* 300 ms */
+
+/* Default setting for DC Feed Slope option */
+#define VP_OPTION_DEFAULT_DCFEED_SLOPE          109 /* 4 V/ms */
+
+/* Default setting for hook detection mode option */
+#define VP_OPTION_DEFAULT_HOOK_DETECT_MODE      VP_OPTION_HOOKDET_NORMAL
+
+/* Default settings for PCM highway signaling and control */
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_ENABLE    FALSE
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_CTLTS     0
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_SIGTS     0
+
+/* Default setting for PCM highway lien state control mode */
+#define VP_OPTION_DEFAULT_LINESTATE_CTL_MODE    VP_OPTION_LINESTATE_CTL_NORMAL
+
+/* Default settings for Auto Loop Conditions option */
+#define VP_OPTION_DEFAULT_AUTO_LOOP_COND_SELECT 0
+#define VP_OPTION_DEFAULT_AUTO_LOOP_COND_DELAY  0
+
+
+/******************************************************************************
+ *    VCP2 library specific other defines and conditional compile flags       *
+ ******************************************************************************/
+
+/* Specify the maximum number of SLACs which will be controlled by the VCP2 on
+ * each SPI bus.
+ *
+ * For VCP2-790, there are up to 8 SLACs (32 channels) on each SPI bus.
+ *
+ * For VCP2-792, with the Le79124 chipset, normally there are up to 4 SLACs (32
+ * channels) on the first SPI bus and up to 5 SLACs (40 channels) on the second
+ * SPI bus.
+ *
+ * For VCP2-792, with the Le79128 chipset, there are up to 8 SLACs on each SPI
+ * bus.
+ */
+#define VP_VCP2_MAX_NUM_SLACS_BUS0 8
+#define VP_VCP2_MAX_NUM_SLACS_BUS1 8
+
+/* Specify the maximum number of channels controlled by any individual SLAC.
+ * If you are controlling a VCP2-792 device, this should be 8.  If you are
+ * controlling a VCP2-790 device, you can reduce this value to 4 to save
+ * memory.  If you are controlling a VCP2-880 device, you can reduce this value
+ * to 2 to save memory.  If you are controlling a combination of
+ * SLACs (unlikely), use the number corresponding to the SLAC with the most
+ * channels. */
+#define VP_VCP2_MAX_NUM_CHANS  8
+
+/* Set this option to support the VCP2 emulator. */
+#define VP_VCP2_EMU_SUPPORT
+
+/* Do not define this unless you know what you're doing. */
+#undef VP_VCP2_SUPPORT_UNDOCUMENTED_TESTS
+
+#define VP_SIZEOF_CID_MSG_BUFFER 16
+
+/******************************************************************************
+ *    MELT library specific other defines and conditional compile flags       *
+ ******************************************************************************/
+#define VP_MELT_MAX_NUM_SLACS 1
+#define VP_MELT_MAX_NUM_CHANS 8
+/******************************************************************************
+ *     VCP library specific other defines and conditional compile flags       *
+ ******************************************************************************/
+
+/* Define the following to enable debug print statements from the VCP API */
+#undef DEBUG_VCP_API
+
+#ifdef DEBUG_VCP_API
+#include <stdio.h>
+/* Define the following as necessary to redirect the debug output */
+#define term_printf printf
+
+/* Further classification enabling/disabling debug output */
+#define DEBUG_BOOTLOAD              /* Debug bootload function */
+#define DEBUG_VCP_API_MB            /* MailBox related debug output */
+#define DEBUG_VCP_API_EVENT         /* Event masking related debug output */
+#define DEBUG_VCP_API_DEFLT_OPTN    /* Default option debugging */
+#endif /* DEBUG_VCP_API */
+
+/******************************************************************************
+ *                      API Debug output redirection                          *
+ ******************************************************************************/
+#if defined(DEBUG_VCP_API)
+#ifndef term_printf
+#include <stdio.h>
+/* Define the following as necessary to redirect the debug output */
+#define term_printf printf
+#endif /* term_printf */
+#endif /* DEBUG_VCP_API  */
+
+#if defined (VP_CC_VCP_SERIES) || defined (VP_CC_VCP2_SERIES)
+/******************************************************************************
+ * Library Specific default options                                           *
+ *****************************************************************************/
+/* VoicePath API provides a mechanism where individual library's default
+ * options could be different compared to top level API default options.
+ * If you need such a change please review the file included below.
+ */
+#include "vp_api_lib_cfg.h"
+#endif
+#endif /* VP_API_CFG_INT_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_common.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_common.h
new file mode 100755
index 0000000..04bd265
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_common.h
@@ -0,0 +1,1891 @@
+/** \file vp_api_common.h
+ * vp_api_common.h
+ *
+ * Header file for the VP-API-II c files.
+ *
+ * This file contains all of the VP-API-II declarations that are Voice
+ * Termination Device (VTD) family independent.
+ *
+ * $Revision: 8620 $
+ * $LastChangedDate: 2011-06-02 13:27:26 -0500 (Thu, 02 Jun 2011) $
+ */
+
+#ifndef VP_API_COMMON_H
+#define VP_API_COMMON_H
+
+#include "vp_api_types.h"
+#include "vp_api_dev_term.h"
+#include "vp_api_event.h"
+#include "vp_api_option.h"
+#include "vp_api_test.h"
+
+
+/******************************************************************************
+ *                                DEFINES                                     *
+ ******************************************************************************/
+
+/*
+ * Profile Table Indexes
+ */
+#define VP_PTABLE_NULL      (VpProfilePtrType)0
+#define VP_PTABLE_INDEX1    (VpProfilePtrType)1
+#define VP_PTABLE_INDEX2    (VpProfilePtrType)2
+#define VP_PTABLE_INDEX3    (VpProfilePtrType)3
+#define VP_PTABLE_INDEX4    (VpProfilePtrType)4
+#define VP_PTABLE_INDEX5    (VpProfilePtrType)5
+#define VP_PTABLE_INDEX6    (VpProfilePtrType)6
+#define VP_PTABLE_INDEX7    (VpProfilePtrType)7
+#define VP_PTABLE_INDEX8    (VpProfilePtrType)8
+#define VP_PTABLE_INDEX9    (VpProfilePtrType)9
+#define VP_PTABLE_INDEX10   (VpProfilePtrType)10
+#define VP_PTABLE_INDEX11   (VpProfilePtrType)11
+#define VP_PTABLE_INDEX12   (VpProfilePtrType)12
+#define VP_PTABLE_INDEX13   (VpProfilePtrType)13
+#define VP_PTABLE_INDEX14   (VpProfilePtrType)14
+#define VP_PTABLE_INDEX15   (VpProfilePtrType)15
+#define VP_PTABLE_NO_INDEX   (VpProfilePtrType)99
+#define VP_PTABLE_MAX_INDEX VP_PTABLE_INDEX15
+#define VP_PTABLE_INDEX(n)  (VpProfilePtrType)(n)
+
+
+/*
+ *Utility macros:
+ */
+#ifndef ABS
+  #define ABS(arg) ((arg) < 0 ? -(arg) : (arg))
+#endif
+
+#ifndef MAX
+  #define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+  #define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX4
+  #define MAX4(a, b, c, d) MAX(MAX(a, b), MAX(c, d))
+#endif
+
+#ifndef MAX12
+  #define MAX12(a, b, c, d, e, f, g, h, i, j, k, l) \
+    MAX(MAX(MAX4(a, b, c, d), MAX4(e, f, g, h)), MAX4(i, j, k, l))
+#endif
+
+
+/******************************************************************************
+ *                    ENUMERATIONS AND NEW DATA TYPES                         *
+ ******************************************************************************/
+/** Standard return value for most API library functions.  See the VP-API-II
+    Reference Guide for descriptions. */
+typedef enum
+{
+    VP_STATUS_SUCCESS              = 0,
+    VP_STATUS_FAILURE              = 1,
+    VP_STATUS_FUNC_NOT_SUPPORTED   = 2,
+    VP_STATUS_INVALID_ARG          = 3,
+    VP_STATUS_MAILBOX_BUSY         = 4,
+    VP_STATUS_ERR_VTD_CODE         = 5,
+    VP_STATUS_OPTION_NOT_SUPPORTED = 6,
+    VP_STATUS_ERR_VERIFY           = 7,
+    VP_STATUS_DEVICE_BUSY          = 8,
+    VP_STATUS_MAILBOX_EMPTY        = 9,
+    VP_STATUS_ERR_MAILBOX_DATA     = 10,
+    VP_STATUS_ERR_HBI              = 11,
+    VP_STATUS_ERR_IMAGE            = 12,
+    VP_STATUS_IN_CRTCL_SECTN       = 13,
+    VP_STATUS_DEV_NOT_INITIALIZED  = 14,
+    VP_STATUS_ERR_PROFILE          = 15,
+    VP_STATUS_CUSTOM_TERM_NOT_CFG  = 17,
+    VP_STATUS_DEDICATED_PINS       = 18,
+    VP_STATUS_INVALID_LINE         = 19,
+    VP_STATUS_LINE_NOT_CONFIG      = 20,
+    VP_STATUS_INPUT_PARAM_OOR,  /* This enum value does not yet require to be a set value */
+    VP_STATUS_NUM_TYPES,
+    VP_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpStatusType;
+
+/* Enumeration for Boot load Function */
+typedef enum
+{
+    VP_BOOT_STATE_FIRST,        /* First block to download */
+    VP_BOOT_STATE_CONTINUE,     /* Additional block to download */
+    VP_BOOT_STATE_LAST,         /* Last block to download */
+    VP_BOOT_STATE_FIRSTLAST,    /* First and only block to download */
+    VP_NUM_BOOT_STATES,
+    VP_BOOT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBootStateType;
+
+/* Enumeration for Boot load Function */
+typedef enum
+{
+    VP_BOOT_MODE_NO_VERIFY,     /* No write verification is performed */
+    VP_BOOT_MODE_VERIFY,        /* Verify Load Image Checksum */
+    VP_NUM_BOOT_MODES,
+    VP_BOOT_MODE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBootModeType;
+
+/* Version and checksum information for VCP */
+typedef struct
+{
+    uint16 vtdRevCode;          /* Silicon Revision for VTD */
+    uint8 swProductId;          /* VTD Firmware ID */
+    uint8 swVerMajor;           /* Major Revision for VTD Firmware */
+    uint8 swVerMinor;           /* Minor Revision for VTD Firmware */
+} VpVersionInfoType;
+
+typedef struct
+{
+    uint32 loadChecksum;        /* Calculated Checksum for Code Image */
+    VpVersionInfoType vInfo;    /* Version Information for VTD HW/SW */
+} VpChkSumType;
+
+typedef enum
+{
+    VP_PROFILE_DEVICE      = 0, /* Device profile */
+    VP_PROFILE_AC          = 1, /* AC profile */
+    VP_PROFILE_DC          = 2, /* DC profile */
+    VP_PROFILE_RING        = 3, /* Ring profile */
+    VP_PROFILE_RINGCAD     = 4, /* Ringing cadence profile */
+    VP_PROFILE_TONE        = 5, /* Tone profile */
+    VP_PROFILE_METER       = 6, /* Metering profile */
+    VP_PROFILE_CID         = 7, /* Caller ID profile */
+    VP_PROFILE_TONECAD     = 8, /* Tone cadence profile */
+    VP_PROFILE_FXO_CONFIG,      /* FXO configuration profile */
+    VP_PROFILE_CUSTOM_TERM,     /* Custom Termination Type profile */
+    VP_PROFILE_CAL,             /* Used for VpCal when passing calibration coefficients */
+    VP_NUM_PROFILE_TYPES,
+    VP_PROFILE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProfileType;
+
+/**< typedef for VpCalCodec() function */
+typedef enum {
+    VP_DEV_CAL_NOW   = 0, /* Calibrate immediately */
+    VP_DEV_CAL_NBUSY = 1, /* Calibrate if all lines are "on-hook" */
+    VP_NUM_DEV_CAL_TYPES,
+    VP_DEV_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceCalType;
+
+/* Valid line states for VpSetLineState() */
+/* Defined else where */
+
+/**< The following types are for VpSetLineTone() function */
+typedef struct {
+    VpDigitType toneId;  /* Identifies the DTMF tone to generated */
+    VpDirectionType dir; /* Direction in which DTMF tone needs to be
+                          * generated */
+} VpDtmfToneGenType;
+
+typedef enum {
+  VP_DIGIT_GENERATION_DTMF,             /* Generate DTMF digit */
+  VP_DIGIT_GENERATION_DIAL_PULSE,       /* Generate pulse digit */
+  VP_DIGIT_GENERATION_DIAL_HOOK_FLASH,   /* Generate hook flash */
+  VP_DIGIT_GEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitGenerationType;
+
+typedef enum {
+  VP_BFILT_DIS = 0,
+  VP_BFILT_EN  = 1,
+  VP_BFILT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBFilterModeType;
+
+typedef enum {
+  VP_BATT_MODE_DIS = 0,
+  VP_BATT_MODE_EN  = 1,
+  VP_BATT_MODE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatteryModeType;
+
+typedef struct {
+    int16 batt1;
+    int16 batt2;
+    int16 batt3;
+} VpBatteryValuesType;
+
+/**< The following types are for VpSetRelayState() and VpGetRelayState() functions */
+typedef enum {
+    VP_RELAY_NORMAL         = 0,  /* No test access, ringing controlled
+                                   * by line state */
+    VP_RELAY_RESET          = 1,  /* LCAS all-off state, test-out released */
+    VP_RELAY_TESTOUT        = 2,  /* LCAS all-off state, test-out active */
+    VP_RELAY_TALK           = 3,  /* LCAS talk state, test-out released */
+    VP_RELAY_RINGING        = 4,  /* LCAS ringing state, test-out released */
+    VP_RELAY_TEST           = 5,  /* LCAS test state, test-out released */
+    VP_RELAY_BRIDGED_TEST   = 6,  /* LCAS test/monitor state,
+                                   * test-out released */
+    VP_RELAY_SPLIT_TEST     = 7,  /* LCAS test/monitor state,
+                                   * test-out active */
+    VP_RELAY_DISCONNECT     = 8,  /* LCAS talk state, test-out active */
+    VP_RELAY_RINGING_NOLOAD = 9,  /* LCAS ringing state, test-out active */
+    VP_RELAY_RINGING_TEST   = 10, /* LCAS test ringing state,
+                                   * test-out active */
+    VP_RELAY_LAMP_ON        = 11, /* VCP2-790 FXS_TL_MW only */
+    VP_RELAY_IDLE           = 12, /* All switches open, test switch off */
+    VP_NUM_RELAY_STATES,
+    VP_RELAY_ENUM_RSVD  = FORCE_SIGNED_ENUM,
+    VP_RELAY_ENUM_SIZE  = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpRelayControlType;
+
+/**< The following types are for VpSetCalRelayState() function */
+typedef enum {
+    VP_CAL_RELAY_OPEN,                /* Open circuit                      */
+    VP_CAL_RELAY_R_DIFF_LOW_TIP_RING, /* Res Tip-to-Ring: R_DIFF_LOW Ohms  */
+    VP_CAL_RELAY_R_CM_REF_TIP_GND,    /* Res Tip-to-Gnd:  R_CM_REF Ohms    */
+    VP_CAL_RELAY_V_CAL_REF_TIP_GND,   /* Volt Tip:        V_CAL_REF Volts  */
+    VP_CAL_RELAY_SHORT_TIP_RING,      /* Res Tip-to-Ring: short (0 Ohms)   */
+    VP_CAL_RELAY_R_DIFF_HIGH_TIP_RING,/* Res Tip-to-Ring: R_DIFF_HIGH Ohms */
+    VP_CAL_RELAY_R_CM_REF_RING_GND,   /* Res Ring-to-Gnd: R_CM_REF Ohms    */
+    VP_CAL_RELAY_V_CAL_REF_RING_GND,  /* Volt Ring:       V_CAL_REF Volts  */
+    VP_CAL_RELAY_NUM_STATES,
+    VP_CAL_RELAY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCalRelayControlType;
+
+/**< The following types are for VpSetRelGain() function */
+typedef enum {
+    VP_GAIN_SUCCESS  = 0, /* Gain setting adjusted successfully */
+    VP_GAIN_GR_OOR   = 1, /* GR Gain setting overflowed (reset to default) */
+    VP_GAIN_GX_OOR   = 2, /* GX Gain setting overflowed (reset to default) */
+    VP_GAIN_BOTH_OOR = 3, /* Both GR & GX overflowed (and reset to default) */
+    VP_GAIN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGainResultType;
+
+typedef struct {
+    VpGainResultType gResult; /* Success / Failure status return */
+    uint16 gxValue;           /* new GX register abs value */
+    uint16 grValue;           /* new GR register abs value */
+} VpRelGainResultsType;
+
+/* The number of 16 bits words used to define whether seal current
+ * should be applied to lines 0-127 */
+#define VP_SEAL_CURRENT_ARRAY_SIZE 8
+
+typedef struct {
+    uint16 sealApplyTime;
+    uint16 sealCycleTime;
+    uint16 maxCurrent;
+    uint16 minCurrent;
+    uint16 sealMaskArray[VP_SEAL_CURRENT_ARRAY_SIZE];
+} VpSealCurType;
+
+/**< The following types are for the VpQuery() function */
+typedef enum {
+    VP_QUERY_ID_TEMPERATURE = 0,
+    VP_QUERY_ID_METER_COUNT = 1,
+    VP_QUERY_ID_LOOP_RES    = 2,
+    VP_QUERY_ID_SEAL_CUR    = 3,
+    VP_NUM_QUERY_IDS,
+    VP_QUERY_ID_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpQueryIdType;
+
+typedef union {
+    int16 temp;
+    uint16 meterCount;
+    uint16 rloop;
+    VpSealCurType sealCur;
+} VpQueryResultsType;
+
+/**< The following types are for VpLineIoAccess() function */
+typedef enum {
+    VP_IO_WRITE = 0,
+    VP_IO_READ  = 1,
+    VP_IO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpIoDirectionType;
+
+typedef struct {
+    uint8 mask;
+    uint8 data;
+} VpLineIoBitsType;
+
+typedef struct {
+    VpIoDirectionType direction;
+    VpLineIoBitsType ioBits;
+} VpLineIoAccessType;
+
+/**< The following types are for VpDeviceIoAccess() function */
+typedef enum {
+    VP_DEVICE_IO_WRITE = 0, /* Perform device specific IO write access */
+    VP_DEVICE_IO_READ  = 1, /* Perform device specific IO read access */
+    VP_DEVICE_IO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceIoAccessType;
+
+typedef enum {
+    VP_DEVICE_IO_IGNORE = 0, /* Ignore I/O access */
+    VP_DEVICE_IO_ACCESS = 1, /* Perform I/O access */
+    VP_DEVUCE_IOA_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceIoAccessMask;
+
+typedef struct {
+    VpDeviceIoAccessType accessType;/* Device I/O access type */
+    uint32 accessMask_31_0;         /* I/O access mask (Pins 0 - 31) */
+    uint32 accessMask_63_32;        /* I/O access mask (Pins 32 - 63) */
+    uint32 deviceIOData_31_0;   /* Output pin data (Pins 0 - 31) */
+    uint32 deviceIOData_63_32;  /* Output pin data (Pins 32 - 63) */
+} VpDeviceIoAccessDataType;
+
+/**< The following types are for VpDeviceIoAccessExt() function */
+
+typedef struct {
+    VpIoDirectionType direction;
+    VpLineIoBitsType lineIoBits[VP_MAX_LINES_PER_DEVICE];
+} VpDeviceIoAccessExtType;
+
+/**< The following types are for VpGetLineStatus() function */
+typedef enum {
+    VP_INPUT_HOOK      = 0, /* Hook Status (ignoring pulse & flash) */
+    VP_INPUT_RAW_HOOK  = 1, /* Hook Status (include pulse & flash) */
+    VP_INPUT_GKEY      = 2, /* Ground-Key/Fault Status */
+    VP_INPUT_THERM_FLT = 3, /* Thermal Fault Status */
+    VP_INPUT_CLK_FLT   = 4, /* Clock Fault Status */
+    VP_INPUT_AC_FLT    = 5, /* AC Fault Status */
+    VP_INPUT_DC_FLT    = 6, /* DC Fault Status */
+    VP_INPUT_BAT1_FLT  = 7, /* Battery 1 Fault Status */
+    VP_INPUT_BAT2_FLT  = 8, /* Battery 2 Fault Status */
+    VP_INPUT_BAT3_FLT  = 9, /* Battery 3 Fault Status */
+
+    VP_INPUT_RINGING,    /* Ringing Status */
+    VP_INPUT_LIU,        /* Line In Use Status */
+    VP_INPUT_FEED_DIS,   /* Feed Disable Status */
+    VP_INPUT_FEED_EN,    /* Feed Enable Status */
+    VP_INPUT_DISCONNECT, /* Feed Disconnect Status */
+    VP_INPUT_CONNECT,    /* Feed Connect Status */
+    VP_INPUT_POLREV,     /* Reverse Polarity if TRUE, Normal if FALSE */
+    VP_INPUT_RES_LEAK,   /* Resistive Leakage on line if TRUE */
+
+    VP_NUM_INPUT_TYPES,
+    VP_INPUT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpInputType;
+
+/**< The following type is for the VpGetDeviceStatusExt() function: */
+typedef struct {
+    VpInputType input;
+    uint8 status[VP_LINE_FLAG_BYTES];
+} VpDeviceStatusType;
+
+/**< The following types are for VpGetLoopCond() function (return via
+ * VpGetResults())
+ */
+typedef enum {
+    VP_BATTERY_UNDEFINED = 0, /* Battery being used is not known or feature
+                               * not supported */
+    VP_BATTERY_1         = 1, /* Battery 1 */
+    VP_BATTERY_2         = 2, /* Battery 2 */
+    VP_BATTERY_3         = 3, /* Battery 3 */
+    VP_NUM_BATTERY_TYPES,
+    VP_BATTERY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatteryType;
+
+typedef enum {
+    VP_DF_UNDEFINED    = 0, /* DC feed region not known or feature not
+                             * supported */
+    VP_DF_ANTI_SAT_REG = 1, /* DC feed is in anti saturation region */
+    VP_DF_CNST_CUR_REG = 2, /* DC feed is in constant current region */
+    VP_DF_RES_FEED_REG = 3, /* DC feed is in resistive feed region */
+    VP_NUM_DC_FEED_TYPES,
+    VP_DC_FEED_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDcFeedRegionType;
+
+typedef struct {
+    int16 rloop;                    /**< The loop resistance */
+    int16 ilg;                      /**< The longitudinal loop current */
+    int16 imt;                      /**< The metallic loop current */
+    int16 vsab;                     /**< The tip/ring voltage */
+    int16 vbat1;                    /**< The Battery 1 voltage */
+    int16 vbat2;                    /**< The Battery 2 voltage */
+    int16 vbat3;                    /**< The Battery 3 voltage */
+    int16 mspl;                     /**< Metering signal peak level */
+    VpBatteryType selectedBat;      /**< Battery that is presently used for
+                                     *   the DC feed */
+    VpDcFeedRegionType dcFeedReg;   /**< DC feed region presently selected */
+} VpLoopCondResultsType;
+
+/**< The following types are used for the function VpSendSignal() */
+typedef enum {
+    VP_SENDSIG_MSG_WAIT_PULSE      = 0,
+    VP_SENDSIG_DTMF_DIGIT          = 1,
+    VP_SENDSIG_PULSE_DIGIT         = 2,
+    VP_SENDSIG_HOOK_FLASH          = 3,
+    VP_SENDSIG_FWD_DISCONNECT      = 4,
+    VP_SENDSIG_POLREV_PULSE        = 5,
+    VP_SENDSIG_MOMENTARY_LOOP_OPEN = 6,
+    VP_SENDSIG_TIP_OPEN_PULSE      = 7,
+    VP_SENDSIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSendSignalType;
+
+typedef struct {
+    int8 voltage;   /**< Voltage in Volts to apply to the line. A negative
+                     * value means Tip is more Negative than Ring, a positive
+                     * value means Ring is more Negative than Tip.
+                     */
+    uint16 onTime;  /**< Duration of pulse on-time in mS */
+    uint16 offTime; /**< Duration of pulse off-tim in mS. If the off-time is
+                     * set to 0, the voltage is applied to the line continuously
+                     */
+    uint8 cycles;   /**< Number of pulses to send on the line. If set to 0, will
+                     * repeat forever
+                     */
+} VpSendMsgWaitType;
+
+/**< The following type is used for the function VpGenTimerCtrl() */
+typedef enum {
+    VP_GEN_TIMER_START  = 0,
+    VP_GEN_TIMER_CANCEL = 1,
+    VP_GEN_TIMER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGenTimerCtrlType;
+
+/**< The enum is used by the system service layer pcmCollect() function */
+typedef enum {
+    VP_PCM_OPERATION_AVERAGE      = 0x0001, /* average PCM samples */
+    VP_PCM_OPERATION_RANGE        = 0x0002, /* find pk to pk pcm sample data. */
+    VP_PCM_OPERATION_RMS          = 0x0004, /* find rms value of pcm samples */
+    VP_PCM_OPERATION_MIN          = 0x0008, /* find min pcm value of pcm samples */
+    VP_PCM_OPERATION_MAX          = 0x0010, /* find max pcm value of pcm samples */
+    VP_PCM_OPERATION_APP_SPECIFIC = 0x0020, /* generic operation */
+    VP_PCM_OPERATION_FREQ         = 0x0040, /* Measure frequency */
+    VP_PCM_OPERATION_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPcmOperationBitType;
+
+typedef uint16 VpPcmOperationMaskType;
+
+typedef struct {
+    int16 average;  /* Average value of all collected PCM samples */
+    int16 range;    /* Maximum - minimum PCM value during operation time */
+    int16 rms;      /* RMS result of all collected pcm samples */
+    int16 min;      /* Maximum pcm value found */
+    int16 max;      /* Minimum pcm value found */
+    void *pApplicationInfo; /* Any results that the implementation chooses to
+                             * pass. This data is not interpreted neither
+                             * by the VP-API nor the LT-API. LT-API passes
+                             * this pointer back to the application as part
+                             * of the test result
+                             */
+    int32 freq;     /* Measured average frequenny */
+
+    bool error;     /* indication of PCM operation process (1 = failure) */
+} VpPcmOperationResultsType;
+
+/**< The enum is used by the cal function */
+typedef enum {
+    VP_CAL_BFILTER              = 1,
+    VP_CAL_APPLY_BFILTER        = 2,
+    VP_CAL_MEASURE_BFILTER      = 3,
+    VP_CAL_GET_SYSTEM_COEFF     = 4,
+    VP_CAL_APPLY_SYSTEM_COEFF   = 5,
+    VP_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCalType;
+
+typedef struct {
+    uint16 vRms;    /**< Customer Target Value in approximate vRms */
+    VpProfilePtrType pAcProfile;
+} VpCalBFilterType;
+
+typedef struct {
+    VpProfilePtrType pAcProfile;
+    uint16 index;
+} VpCalApplyBFilterType;
+
+typedef enum {
+    VP_CAL_SUCCESS,
+    VP_CAL_FAILURE,
+    VP_CAL_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCalStatusType;
+
+typedef enum {
+    VP_LOWLEV_PAGE_WR = 0,
+    VP_LOWLEV_PAGE_RD = 1,
+    VP_LOWLEV_MBOX_WR = 2,
+    VP_LOWLEV_MBOX_RD = 3,
+    VP_LOWLEV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpLowLevelCmdType;
+
+typedef enum {
+
+    /* Device parameters */
+
+    /* DC parameters */
+    VP_PROF_FIELD_ILA
+
+} VpProfileFieldIdType;
+
+typedef struct {
+    VpProfileFieldIdType fieldId;
+
+    union {
+        uint16 ila;
+    } data;
+
+} VpProfileFieldType;
+
+/* The following struct can be passed to VpGetResults() if the event ID is not
+   known at compile time, to ensure that the buffer is large enough regardless
+   of the result type. */
+typedef union {
+    VpChkSumType codeChecksum;                  /* VP_DEV_EVID_BOOT_CMP or
+                                                   VP_DEV_EVID_CHKSUM          */
+    VpRelGainResultsType setRelGain;            /* VP_LINE_EVID_GAIN_CMP       */
+    uint8 lowLevelCmd[256];                     /* VP_LINE_EVID_LLCMD_RX_CMP   */
+    VpLoopCondResultsType getLoopCond;          /* VP_LINE_EVID_RD_LOOP        */
+    VpOptionValueType getOption;                /* VP_LINE_EVID_RD_OPTION      */
+    VpTestResultType testLine;                  /* VP_LINE_EVID_TEST_CMP       */
+    VpDeviceIoAccessDataType deviceIoAccess;    /* VP_DEV_EVID_IO_ACCESS_CMP   */
+    VpDeviceIoAccessExtType deviceIoAccessExt;  /* VP_DEV_EVID_IO_ACCESS_CMP   */
+    VpLineIoAccessType lineIoAccess;            /* VP_LINE_EVID_LINE_IO_RD_CMP */
+    VpQueryResultsType query;                   /* VP_LINE_EVID_QUERY_CMP      */
+} VpResultsType;
+
+typedef enum {
+    VP_FREE_RUN_START,
+    VP_FREE_RUN_STOP
+} VpFreeRunModeType;
+
+/******************************************************************************
+ *                 DEVICE/LINE CONTEXT (SUPPORT) DEFINITION                   *
+ ******************************************************************************/
+/* The following function pointers are required to get around problem of
+ * what comes first? chicken or the egg? when dealing with declaration of
+ * device context, function pointer table and hence the following declarations.
+ */
+struct VpDevCtxType;    /**< forward declaration */
+struct VpLineCtxType;   /**< forward declaration */
+struct VpEventType;     /**< forward declaration */
+
+/*
+ * System Configuration functions
+ */
+typedef VpStatusType
+(*VpMakeLineObjectFuncPtrType) (
+    VpTermType termType,
+    uint8 channelId,
+    struct VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    struct VpDevCtxType *pDevCtx);
+
+/*
+ * Initialization functions
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpBootLoadFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+typedef VpStatusType
+(*VpBootSlacFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize);
+#endif  /* !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * | defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpInitDeviceFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile,
+    VpProfilePtrType pFxoAcProfile,
+    VpProfilePtrType pFxoCfgProfile);
+
+typedef VpStatusType
+(*VpFreeRunFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpFreeRunModeType freeRunMode);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpInitSlacFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpInitLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+typedef VpStatusType
+(*VpConfigLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+typedef VpStatusType
+(*VpSetBFilterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpBFilterModeType bFiltMode,
+    VpProfilePtrType pAcProfile);
+
+typedef VpStatusType
+(*VpSetBatteriesFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpBatteryModeType battMode,
+    VpBatteryValuesType *pBatt);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+                                || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+typedef VpStatusType
+(*VpCalCodecFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpDeviceCalType mode);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+         * || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+         */
+
+typedef VpStatusType
+(*VpCalLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx);
+
+typedef VpStatusType
+(*VpCalFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpCalType calType,
+    void *inputArgs);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+typedef VpStatusType
+(*VpInitRingFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCadProfile,
+    VpProfilePtrType pCidProfile);
+
+typedef VpStatusType
+(*VpInitCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpInitMeterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+typedef VpStatusType
+(*VpInitCustomTermTypeFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCustomTermProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+typedef VpStatusType
+(*VpInitProfileFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpProfileType type,
+    VpProfilePtrType pProfileIndex,
+    VpProfilePtrType pProfile);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpSoftResetFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Control functions
+ */
+typedef VpStatusType
+(*VpSetLineStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+typedef VpStatusType
+(*VpSetLineToneFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+typedef VpStatusType
+(*VpSetRelayStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpRelayControlType rState);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+typedef VpStatusType
+(*VpSetCalRelayStateFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpCalRelayControlType rState);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+typedef VpStatusType
+(*VpSetRelGainFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 txLevel,
+    uint16 rxLevel,
+    uint16 handle);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+typedef VpStatusType
+(*VpSendSignalFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpSendSignalType signalType,
+    void *pSignalData);
+
+typedef VpStatusType
+(*VpSendCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    VpProfilePtrType pCidProfile,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpContinueCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpStartMeterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpStartMeter32QFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint32 minDelay,
+    uint32 onTime,
+    uint32 offTime,
+    uint16 numMeters,
+    uint16 eventRate);
+
+typedef VpStatusType
+(*VpGenTimerCtrlFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpGenTimerCtrlType timerCtrl,
+    uint32 duration,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpAssocDslLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    bool connect,
+    uint8 line);
+
+typedef VpStatusType
+(*VpSetSealCurFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    uint16 sealApplyTime,
+    uint16 sealCycleTime,
+    uint16 maxCurrent,
+    uint16 minCurrent,
+    uint16 *pSealArray,
+    VpProfilePtrType pDcProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpSetOptionFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    void *pValue);
+
+typedef VpStatusType
+(*VpDeviceIoAccessFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessDataType *pDeviceIoData);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpDeviceIoAccessExtFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessExtType *pDeviceIoAccess);
+
+typedef VpStatusType
+(*VpLineIoAccessFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineIoAccessType *pLineIoAccess,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpVirtualISRFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpApiTickFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    bool *pEventStatus);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(ZARLINK_CFG_INTERNAL)
+typedef VpStatusType
+(*VpLowLevelCmdFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 *pCmdData,
+    uint8 len,
+    uint16 handle);
+#endif
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpLowLevelCmd16FuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLowLevelCmdType cmdType,
+    uint16 *writeWords,
+    uint8 numWriteWords,
+    uint8 numReadWords,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Status and query functions
+ */
+
+typedef bool
+(*VpGetEventFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    struct VpEventType *pEvent);
+
+typedef VpStatusType
+(*VpGetLineStatusFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+typedef VpStatusType
+(*VpGetDeviceStatusFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpInputType input,
+    uint32 *pDeviceStatus);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpGetDeviceStatusExtFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceStatusType *pDeviceStatus);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+typedef VpStatusType
+(*VpGetLoopCondFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+typedef VpStatusType
+(*VpGetOptionFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpGetLineStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineStateType *pCurrentState);
+
+typedef VpStatusType
+(*VpFlushEventsFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpGetResultsFuncPtrType) (
+    struct VpEventType *pEvent,
+    void *pResults);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpClearResultsFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+                                || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+typedef VpStatusType
+(*VpGetRelayStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpRelayControlType *pRstate);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+         * || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+         */
+
+typedef VpStatusType
+(*VpObjectDumpFuncPtrType)(
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpRegisterDumpFuncPtrType)(
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpDtmfDigitDetectedFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+
+typedef VpStatusType
+(*VpQueryFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpQueryIdType queryId,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Test Functions
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+                                || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+typedef VpStatusType
+(*VpTestLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpTestLineIntFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle,
+    bool callback);
+
+typedef VpStatusType
+(*VpTestLineCallbackType) (
+    struct VpLineCtxType *pLineCtx,
+    VpPcmOperationResultsType *pResults);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpCodeCheckSumFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpSelfTestFuncPtrType) (
+    struct VpLineCtxType *pLineCtx);
+
+typedef VpStatusType
+(*VpFillTestBufFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+typedef VpStatusType
+(*VpReadTestBufFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+         * || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+         */
+
+/** ApiFunctionPointer Table to be used by Device Context */
+typedef struct {
+    /* System Configuration Functions */
+    VpMakeLineObjectFuncPtrType MakeLineObject;
+
+    /* Initialization Functions */
+    /*   -- Init Functions common to all devices and VP-API-II configuration modes */
+    VpInitDeviceFuncPtrType InitDevice;
+    VpFreeRunFuncPtrType FreeRun;
+
+    VpInitLineFuncPtrType InitLine;
+    VpConfigLineFuncPtrType ConfigLine;
+
+    VpCalLineFuncPtrType CalLine;
+    VpCalFuncPtrType Cal;
+    VpInitProfileFuncPtrType InitProfile;
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+    VpBootLoadFuncPtrType BootLoad;
+    VpBootSlacFuncPtrType BootSlac;
+    VpInitSlacFuncPtrType InitSlac;
+    VpSoftResetFuncPtrType SoftReset;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpSetBFilterFuncPtrType SetBFilter;
+    VpSetBatteriesFuncPtrType SetBatteries;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+                                || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+    VpCalCodecFuncPtrType CalCodec;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II except VE580 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+    VpInitCustomTermTypeFuncPtrType InitCustomTerm;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II Lite Version */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+    VpInitRingFuncPtrType InitRing;
+    VpInitCidFuncPtrType InitCid;
+    VpInitMeterFuncPtrType InitMeter;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+         */
+
+    /* Control Functions */
+    /*   -- Control Functions common to all devices and VP-API-II configuration modes */
+    VpSetLineStateFuncPtrType SetLineState;
+    VpSetLineToneFuncPtrType SetLineTone;
+    VpSetRelayStateFuncPtrType SetRelayState;
+    VpSetRelGainFuncPtrType SetRelGain;
+
+    VpSetOptionFuncPtrType SetOption;
+    VpDeviceIoAccessFuncPtrType DeviceIoAccess;
+    VpVirtualISRFuncPtrType VirtualISR;
+    VpApiTickFuncPtrType ApiTick;
+
+    /*   -- Control Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+    VpSetCalRelayStateFuncPtrType SetCalRelayState;
+
+    VpStartMeter32QFuncPtrType StartMeter32Q;
+    VpGenTimerCtrlFuncPtrType GenTimerCtrl;
+    VpAssocDslLineFuncPtrType AssocDslLine;
+    VpSetSealCurFuncPtrType SetSealCur;
+
+    VpDeviceIoAccessExtFuncPtrType DeviceIoAccessExt;
+    VpLineIoAccessFuncPtrType LineIoAccess;
+
+    VpLowLevelCmd16FuncPtrType LowLevelCmd16;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(ZARLINK_CFG_INTERNAL)
+    VpLowLevelCmdFuncPtrType LowLevelCmd;
+#endif
+
+    /*   -- Control Functions NOT provided in CSLAC VP-API-II Lite Version */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+    VpSendSignalFuncPtrType SendSignal;
+    VpSendCidFuncPtrType SendCid;
+    VpContinueCidFuncPtrType ContinueCid;
+    VpStartMeterFuncPtrType StartMeter;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+         */
+
+    /* Status and Query Functions */
+    /*   -- Status and Query Functions common to all devices and VP-API-II configuration modes */
+    VpGetEventFuncPtrType GetEvent;
+    VpGetLineStatusFuncPtrType GetLineStatus;
+    VpGetDeviceStatusFuncPtrType GetDeviceStatus;
+
+    VpGetOptionFuncPtrType GetOption;
+    VpGetLineStateFuncPtrType GetLineState;
+    VpFlushEventsFuncPtrType FlushEvents;
+    VpGetResultsFuncPtrType GetResults;
+
+    VpObjectDumpFuncPtrType ObjectDump;
+    VpRegisterDumpFuncPtrType RegisterDump;
+    VpDtmfDigitDetectedFuncPtrType DtmfDigitDetected;
+
+    /*   -- Status and Query Functions used only for CSLAC Line Testing */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+                                || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+    VpGetRelayStateFuncPtrType GetRelayState;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+         * || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+         */
+
+    /*   -- Status and Query Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+    VpGetDeviceStatusExtFuncPtrType GetDeviceStatusExt;
+    VpClearResultsFuncPtrType ClearResults;
+    VpQueryFuncPtrType Query;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Status and Query Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpGetLoopCondFuncPtrType GetLoopCond;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+    /* Test Functions */
+    /*   -- All test functions removed for CSLAC VP-API-II unless Line Test is included */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+                                || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+    /*   -- Test Functions common to all devices and VP-API-II configuration modes */
+    VpTestLineFuncPtrType TestLine;
+    VpTestLineIntFuncPtrType TestLineInt;
+    VpTestLineCallbackType TestLineCallback;
+
+    /*   -- Test Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+    VpCodeCheckSumFuncPtrType CodeCheckSum;
+    VpFillTestBufFuncPtrType FillTestBuf;
+    VpReadTestBufFuncPtrType ReadTestBuf;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Test Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+            || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpSelfTestFuncPtrType SelfTest;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         *  || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+         * || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+         */
+} ApiFunctions;
+
+/******************************************************************************
+ *                       DEVICE/LINE CONTEXT DEFINITION                       *
+ ******************************************************************************/
+/** Voice Path Line Context type */
+typedef struct VpLineCtxType {
+    struct VpDevCtxType *pDevCtx;   /**< Pointer back Device Context */
+
+    void *pLineObj;                 /**< Pointer (forward) to Line Object */
+} VpLineCtxType;
+
+/** Voice Path Device Context type */
+typedef struct VpDevCtxType {
+    VpDeviceType deviceType;    /**< What type is the device context (enum) */
+    void *pDevObj;              /**< Pointer to device object */
+
+    ApiFunctions funPtrsToApiFuncs; /**< Pointers to API functions */
+
+    /**< Pointers to each line context associated with this device.  Set size
+     * to max allowable per device in system
+     */
+    VpLineCtxType *pLineCtx[VP_MAX_LINES_PER_DEVICE];
+} VpDevCtxType;
+
+/******************************************************************************
+ *                        VP-API-II Definitions that use context              *
+ ******************************************************************************/
+/** Event struct: Type reported by VpGetEvent(). */
+typedef struct VpEventType {
+    VpStatusType status;        /**< Function return status */
+
+    uint8 channelId;            /**< Channel that caused the event */
+
+    VpLineCtxType *pLineCtx;    /**< Pointer to the line context (corresponding
+                                 *   to the channel that caused the event) */
+
+    VpDeviceIdType deviceId;    /**< device chip select ID corresponding to the
+                                 *   device that caused the event */
+
+    VpDevCtxType *pDevCtx;      /**< Pointer to the device context
+                                 *   (corresponding to the device that caused
+                                 *   the event) */
+
+    VpEventCategoryType eventCategory; /**< Event category.  The event catagory
+                                        *   is necessary because there are more
+                                        *   events than can be specified by the
+                                        *   size of "eventId  */
+
+    uint16 eventId;     /**< The event that occurred.  Requires that the event
+                         *   catagory be known to interpret */
+
+    uint16 parmHandle;  /**< EventÂ’s Parameter or Host Handle.  This value is
+                         *   specified by the application only, not used by the
+                         *   API */
+
+    uint16 eventData;   /**< Data associated with the event. Event Id specific*/
+
+    bool hasResults;    /**< If TRUE indicates this event has results associated
+                         *   with it */
+
+    VpLineIdType lineId;    /**< Application provide line Id to ease mapping of
+                             * lines to specific line contexts.
+                             */
+} VpEventType;
+
+/**< The following types are for VpGetDeviceInfo() and VpGetLineInfo()
+ * functions */
+
+typedef enum {
+    VP_UNKNOWN,
+    VP_AVAILABLE,
+    VP_NOT_AVAILABLE
+} VpFeatureType;
+
+typedef struct {
+    VpFeatureType testLoadSwitch;
+    VpFeatureType internalTestTermination;
+} VpFeatureListType;
+
+typedef struct {
+    VpLineCtxType *pLineCtx;            /* Pointer to Line Context */
+    VpDeviceIdType deviceId;            /* Device identity */
+    VpDevCtxType *pDevCtx;              /* Pointer to device Context */
+    VpDeviceType deviceType;            /* Device Type */
+    VpFeatureListType featureList;      /* Store the device features */
+    uint8 numLines;                     /* Number of lines */
+    uint8 revCode;                      /* Revision Code Number */
+    uint8 slacId;                       /* Unique ID associated with Device identity */
+    uint16 productCode;                 /* Number indicating features of the device.*/
+} VpDeviceInfoType;
+
+typedef struct {
+    VpDevCtxType *pDevCtx;       /* Pointer to device Context */
+    uint8 channelId;             /* Channel identity */
+    VpLineCtxType *pLineCtx;     /* Pointer to Line Context */
+    VpTermType termType;         /* Termination Type */
+    VpLineIdType lineId;         /* Application system wide line identifier */
+} VpLineInfoType;
+
+/******************************************************************************
+ *                        VP-API-II FUNCTION PROTOTYPES                       *
+ ******************************************************************************/
+/*
+ * System configuration functions
+ */
+EXTERN VpStatusType
+VpMakeDeviceObject(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    VpDevCtxType *pDevCtx,
+    void *pDevObj);
+
+EXTERN VpStatusType
+VpMakeDeviceCtx(
+    VpDeviceType deviceType,
+    VpDevCtxType *pDevCtx,
+    void *pDevObj);
+
+EXTERN VpStatusType
+VpMakeLineObject(
+    VpTermType termType,
+    uint8 channelId,
+    VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpMakeLineCtx(
+    VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpFreeLineCtx(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpGetDeviceInfo(
+    VpDeviceInfoType *pDeviceInfo);
+
+EXTERN VpStatusType
+VpGetLineInfo(
+    VpLineInfoType *pLineInfo);
+
+/*
+ * Initialization functions
+ */
+EXTERN VpStatusType
+VpBootLoad(
+    VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+EXTERN VpStatusType
+VpBootSlac(
+    VpLineCtxType *pLineCtx,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize);
+
+EXTERN VpStatusType
+VpInitDevice(
+    VpDevCtxType *pDevCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile,
+    VpProfilePtrType pFxoAcProfile,
+    VpProfilePtrType pFxoCfgProfile);
+
+EXTERN VpStatusType
+VpFreeRun(
+    VpDevCtxType *pDevCtx,
+    VpFreeRunModeType freeRunMode);
+
+EXTERN VpStatusType
+VpInitSlac(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpInitLine(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpConfigLine(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpCalCodec(
+    VpLineCtxType *pLineCtx,
+    VpDeviceCalType mode);
+
+EXTERN VpStatusType
+VpCalLine(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpCal(
+    VpLineCtxType *pLineCtx,
+    VpCalType calType,
+    void *inputArgs);
+
+EXTERN VpStatusType
+VpInitRing(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCadProfile,
+    VpProfilePtrType pCidProfile);
+
+EXTERN VpStatusType
+VpInitCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpInitMeter(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+
+EXTERN VpStatusType
+VpInitCustomTermType (
+    VpDevCtxType *pDevCtx,
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCustomTermProfile);
+
+EXTERN VpStatusType
+VpInitProfile(
+    VpDevCtxType *pDevCtx,
+    VpProfileType type,
+    VpProfilePtrType pProfileIndex,
+    VpProfilePtrType pProfile);
+
+EXTERN VpStatusType
+VpSoftReset(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpSetBatteries(
+    VpLineCtxType *pLineCtx,
+    VpBatteryModeType battMode,
+    VpBatteryValuesType *pBatt);
+
+EXTERN VpStatusType
+VpSetBFilter(
+    VpLineCtxType *pLineCtx,
+    VpBFilterModeType bFiltMode,
+    VpProfilePtrType pAcProfile);
+
+/*
+ * Control functions
+ */
+EXTERN VpStatusType
+VpSetLineState(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+EXTERN VpStatusType
+VpSetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+EXTERN VpStatusType
+VpSetRelayState(
+    VpLineCtxType *pLineCtx,
+    VpRelayControlType rState);
+
+EXTERN VpStatusType
+VpSetCalRelayState(
+    VpDevCtxType *pDevCtx,
+    VpCalRelayControlType rState);
+
+EXTERN VpStatusType
+VpSetRelGain(
+    VpLineCtxType *pLineCtx,
+    uint16 txLevel,
+    uint16 rxLevel,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpSendSignal(
+    VpLineCtxType *pLineCtx,
+    VpSendSignalType signalType,
+    void *pSignalData);
+
+EXTERN VpStatusType
+VpSendCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    VpProfilePtrType pCidProfile,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpContinueCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpStartMeter(
+    VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+
+EXTERN VpStatusType
+VpStartMeter32Q(
+    VpLineCtxType *pLineCtx,
+    uint32 minDelay,
+    uint32 onTime,
+    uint32 offTime,
+    uint16 numMeters,
+    uint16 eventRate);
+
+EXTERN VpStatusType
+VpAssocDslLine(
+    VpLineCtxType *pLineCtx,
+    bool connect,
+    uint8 line);
+
+EXTERN VpStatusType
+VpSetSealCur(
+    VpDevCtxType *pDevCtx,
+    uint16 sealApplyTime,
+    uint16 sealCycleTime,
+    uint16 maxCurrent,
+    uint16 minCurrent,
+    uint16 *pSealArray,
+    VpProfilePtrType pDcProfile);
+
+
+#define VpStartMeter32(pLineCtx, minDelay, onTime, offTime, numMeters) \
+    VpStartMeter32Q(pLineCtx, minDelay, onTime, offTime, numMeters, 1)
+
+EXTERN VpStatusType
+VpSetOption(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    void *pValue);
+
+EXTERN VpStatusType
+VpDeviceIoAccess(
+    VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessDataType *pDeviceIoData);
+
+VpStatusType
+VpDeviceIoAccessExt(
+    VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessExtType *pDeviceIoAccess);
+
+EXTERN VpStatusType
+VpLineIoAccess(
+    VpLineCtxType *pLineCtx,
+    VpLineIoAccessType *pLineIoAccess,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpVirtualISR(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpApiTick(
+    VpDevCtxType *pDevCtx,
+    bool *pEventStatus);
+
+EXTERN VpStatusType
+VpLowLevelCmd(
+    VpLineCtxType *pLineCtx,
+    uint8 *pCmdData,
+    uint8 len,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpLowLevelCmd16(
+    VpLineCtxType *pLineCtx,
+    VpLowLevelCmdType cmdType,
+    uint16 *writeWords,
+    uint8 numWriteWords,
+    uint8 numReadWords,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGenTimerCtrl(
+    VpLineCtxType *pLineCtx,
+    VpGenTimerCtrlType timerCtrl,
+    uint32 duration,
+    uint16 handle);
+
+/*
+ * Status and query functions
+ */
+EXTERN bool
+VpGetEvent(
+    VpDevCtxType *pDevCtx,
+    VpEventType *pEvent);
+
+EXTERN VpStatusType
+VpGetLineStatus(
+    VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+EXTERN VpStatusType
+VpGetDeviceStatus(
+    VpDevCtxType *pDevCtx,
+    VpInputType input,
+    uint32 *pDeviceStatus);
+
+EXTERN VpStatusType
+VpGetDeviceStatusExt(
+    VpDevCtxType *pDevCtx,
+    VpDeviceStatusType *pDeviceStatus);
+
+EXTERN VpStatusType
+VpGetLoopCond(
+    VpLineCtxType *pLineCtx,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetOption(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetLineState(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType *pCurrentState);
+
+EXTERN VpStatusType
+VpFlushEvents(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpGetResults(
+    VpEventType *pEvent,
+    void *pResults);
+
+EXTERN VpStatusType
+VpClearResults(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpObjectDump(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpRegisterDump(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpDtmfDigitDetected(
+    VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+EXTERN VpStatusType
+VpQuery(
+    VpLineCtxType *pLineCtx,
+    VpQueryIdType queryId,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetRelayState(
+    VpLineCtxType *pLineCtx,
+    VpRelayControlType *pRstate);
+
+/*
+ * Test Functions
+ */
+EXTERN VpStatusType
+VpTestLine(
+    VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpTestLineCallback(
+    VpLineCtxType *pLineCtx,
+    VpPcmOperationResultsType *pResults);
+
+EXTERN VpStatusType
+VpCodeCheckSum(
+    VpDevCtxType *pDevCtx,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpSelfTest(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpFillTestBuf(
+    VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+EXTERN VpStatusType
+VpReadTestBuf(
+    VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+
+EXTERN VpStatusType
+VpMapLineId(
+    VpLineCtxType *pLineCtx,
+    VpLineIdType lineId);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+EXTERN VpStatusType
+VpMapSlacId(
+    VpDevCtxType *pDevCtx,
+    uint8 slacId);
+#endif
+
+EXTERN bool
+VpMemCpyCheck(
+    uint8 *dest,
+    uint8 *src,
+    uint16 count);
+
+EXTERN void *
+VpMemCpy(
+    void *dest,
+    const void *src,
+    uint16 count);
+
+EXTERN void *
+VpMemSet(
+    void * s,
+    int c,
+    uint16 count);
+
+
+/*
+ * Undocumented external functions:
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+EXTERN void
+VpSetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+EXTERN bool
+VpReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+Vcp2HbiCheck(
+    VpDevCtxType *pDevCtx);
+#endif
+
+EXTERN void
+VpMpiCmdWrapper(
+    VpDeviceIdType deviceId,
+    uint8 ecVal,
+    uint8 mpiCmd,
+    uint8 mpiCmdLen,
+    uint8 *dataBuffer);
+
+EXTERN uint8
+VpCSLACBuildMpiBuffer(
+    uint8 index,
+    uint8 *mpiBuffer,
+    uint8 mpiCmd,
+    uint8 mpiCmdLen,
+    uint8 *mpiData);
+
+#endif /* VP_API_COMMON_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_dev_term.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_dev_term.h
new file mode 100755
index 0000000..b53d4af
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_dev_term.h
@@ -0,0 +1,84 @@
+/** \file vp_api_dev_term.h
+ * vp_api_dev_term.h
+ *
+ * This file contains declaration for VP-API Device and termination types.
+ *
+ * $Revision: 7591 $
+ * $LastChangedDate: 2010-08-16 09:33:04 -0500 (Mon, 16 Aug 2010) $
+ */
+
+#ifndef VP_API_DEV_TERM_H
+#define VP_API_DEV_TERM_H
+
+/******************************************************************************
+ *                                ENUMERATIONS                                *
+ ******************************************************************************/
+/* Valid Device Types supported by VP-API-II. For the corresponding part numbers
+ * supported by each device type please see VP-API-II documentation.
+ */
+typedef enum
+{
+    VP_DEV_RSRVD1 = 0,
+    VP_DEV_580_SERIES,
+    VP_DEV_790_SERIES,
+    VP_DEV_VCP_SERIES,
+    VP_DEV_880_SERIES = 4,  /* Fixed value to match calibration profile */
+    VP_DEV_RSVD_SERIES,
+    VP_DEV_VCP2_SERIES,
+    VP_DEV_KWRAP,
+    VP_DEV_890_SERIES = 8,  /* Fixed value to match calibration profile */
+    VP_DEV_792_SERIES,
+    VP_DEV_MELT_SERIES,
+    VP_DEV_792_GROUP,
+    VP_NUM_DEV_TYPES,
+    VP_DEV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceType;
+
+/**
+ * Deprecated name (VCP) based on older name for VCP. All new applications
+ * should use VCP instead
+ */
+#define VP_DEV_DVP_SERIES  VP_DEV_VCP_SERIES
+
+/** Valid Termination Types (per line) supported by API-II.  See the VP-API-II
+    Reference Guide for descriptions. */
+typedef enum
+{
+    /* FXS */
+    VP_TERM_FXS_GENERIC            = 0x00, VP_TERM_FXS_FIRST = VP_TERM_FXS_GENERIC,
+    VP_TERM_FXS_ISOLATE            = 0x01,
+    VP_TERM_FXS_TITO_TL_R          = 0x02,
+    VP_TERM_FXS_CO_TL              = 0x03,
+    VP_TERM_FXS_75181              = 0x04,
+    VP_TERM_FXS_75282              = 0x05,
+    VP_TERM_FXS_RDT                = 0x06,
+    VP_TERM_FXS_RR                 = 0x07,
+    VP_TERM_FXS_SPLITTER           = 0x08,
+    VP_TERM_FXS_TO_TL              = 0x09,
+    VP_TERM_FXS_LOW_PWR            = 0x0A,
+    VP_TERM_FXS_TI                 = 0x0B,
+    VP_TERM_FXS_SPLITTER_LP        = 0x0C,
+    VP_TERM_FXS_ISOLATE_LP         = 0x0D,
+    VP_TERM_FXS_LCAS               = 0x0E,
+    VP_TERM_FXS_RR_TI              = 0x0F,
+    VP_TERM_FXS_CUSTOM             = 0x10,
+    VP_TERM_FXS_TL_MW              = 0x11, VP_TERM_FXS_LAST = VP_TERM_FXS_TL_MW,
+
+    /* MeLT */
+    VP_TERM_MELT_RELAY_CAL_CT      = 0x40, VP_TERM_MELT_FIRST = VP_TERM_MELT_RELAY_CAL_CT,
+    VP_TERM_MELT_RELAY_CAL_SPLIT   = 0x41,
+    VP_TERM_MELT_RELAY_CAL_BRIDGED = 0x42,
+    VP_TERM_MELT_LTAS_CT           = 0x43,
+    VP_TERM_MELT_RELAY_CT          = 0x44,
+    VP_TERM_MELT_RELAY_SPLIT       = 0x45,
+    VP_TERM_MELT_RELAY_BRIDGED     = 0x46, VP_TERM_MELT_LAST = VP_TERM_MELT_RELAY_BRIDGED,
+
+    /* FXO */
+    VP_TERM_FXO_GENERIC            = 0x80, VP_TERM_FXO_FIRST = VP_TERM_FXO_GENERIC,
+    VP_TERM_FXO_DISC               = 0x81,
+    VP_TERM_FXO_CUSTOM             = 0x82, VP_TERM_FXO_LAST = VP_TERM_FXO_CUSTOM,
+
+    VP_TERM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpTermType;
+
+#endif /* VP_API_DEV_TERM_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_event.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_event.h
new file mode 100755
index 0000000..5055ad8
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_event.h
@@ -0,0 +1,468 @@
+/** \file vp_api_event.h
+ * vp_api_event.h
+ *
+ * This file contains declaration associated with VP-API events.
+ *
+ * $Revision: 8609 $
+ * $LastChangedDate: 2011-05-27 14:55:29 -0500 (Fri, 27 May 2011) $
+ */
+
+#ifndef VP_API_EVENT_H
+#define VP_API_EVENT_H
+
+#include "vp_api_types.h"
+
+#define VP_EVENT_MASK_ALL       0xFFFF
+
+/* Event category type */
+typedef enum {
+    VP_EVCAT_FAULT     = 0,
+    VP_EVCAT_SIGNALING = 1,
+    VP_EVCAT_RESPONSE  = 2,
+    VP_EVCAT_TEST      = 3,
+    VP_EVCAT_PROCESS   = 4,
+    VP_EVCAT_FXO       = 5,
+    VP_EVCAT_PACKET    = 6,
+    VP_NUM_EVCATS,
+    VP_EVCAT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpEventCategoryType;
+
+typedef struct {
+    uint16 faults;      /**< Fault event mask */
+    uint16 signaling;   /**< Signaling event mask */
+    uint16 response;    /**< Mailbox response event mask */
+    uint16 test;        /**< Test events */
+    uint16 process;     /**< Call process related events */
+    uint16 fxo;         /**< FXO events mask */
+    uint16 packet;      /**< Packet events mask - no longer used */
+} VpOptionEventMaskType;
+
+typedef enum {
+    VP_DEV_EVID_BAT_FLT         = 0x0001, /**< Device detected battery fault */
+    VP_DEV_EVID_CLK_FLT         = 0x0002, /**< Device detected clock fault */
+    VP_LINE_EVID_THERM_FLT      = 0x0004, /**< Thermal Overload condition */
+    VP_LINE_EVID_DC_FLT         = 0x0008, /**< DC Fault detected on line */
+    VP_LINE_EVID_AC_FLT         = 0x0010, /**< AC Fault detected on line */
+    VP_LINE_EVID_SYNC_FLT       = 0x0020, /**< SLAC Synchronization fault */
+    VP_LINE_EVID_RES_LEAK_FLT   = 0x0040, /**< Low loop resistance while on-hook */
+    VP_LINE_EVID_SEAL_CUR_FLT   = 0x0080, /**< Sealing current error */
+    VP_DEV_EVID_WDT_FLT         = 0x2000, /**< Watchdog timer fault */
+    VP_DEV_EVID_EVQ_OFL_FLT     = 0x4000, /**< event queue overflow fault */
+    VP_DEV_EVID_SYSTEM_FLT      = 0x8000, /**< VCP2 system fault */
+    /* The following fault events are device-specific, not line-specific */
+    VP_EVCAT_FAULT_DEV_EVENTS   = (int)(VP_DEV_EVID_BAT_FLT     |
+                                        VP_DEV_EVID_CLK_FLT     |
+                                        VP_DEV_EVID_EVQ_OFL_FLT |
+                                        VP_DEV_EVID_WDT_FLT     |
+                                        VP_DEV_EVID_SYSTEM_FLT),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_FAULT_UNDEFINED    = (int)(~(VP_DEV_EVID_BAT_FLT     |
+                                          VP_DEV_EVID_CLK_FLT     |
+                                          VP_LINE_EVID_THERM_FLT  |
+                                          VP_LINE_EVID_DC_FLT     |
+                                          VP_LINE_EVID_AC_FLT     |
+                                          VP_LINE_EVID_SYNC_FLT   |
+                                          VP_LINE_EVID_RES_LEAK_FLT |
+                                          VP_LINE_EVID_SEAL_CUR_FLT |
+                                          VP_DEV_EVID_WDT_FLT     |
+                                          VP_DEV_EVID_EVQ_OFL_FLT |
+                                          VP_DEV_EVID_SYSTEM_FLT)), /* NOTES:
+    * The typecasting (int) is necessary in some compilers that have
+    * sizeof(enum)  == sizeof(int) == 2bytes and also because of 'C' rules for
+    * hexadecimal constants. Hexadecimal constants are treated as unsigned and
+    * enum variables are of type signed int. Thus compilers generate warning
+    * when code attempts to assign number that is bigger than what a signed enum
+    * can hold */
+
+    VP_EVCAT_FAULT_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                         VP_EVCAT_FAULT_UNDEFINED),
+    VP_EVCAT_FAULT_MASK_ALL     = (int)(~VP_EVCAT_FAULT_UNDEFINED),
+    VP_EVCAT_FAULT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpFaultEventType;
+
+typedef enum {
+    VP_LINE_EVID_HOOK_OFF       = 0x0001, /**< Off-Hook detected */
+    VP_LINE_EVID_HOOK_ON        = 0x0002, /**< On-Hook detected */
+    VP_LINE_EVID_GKEY_DET       = 0x0004, /**< Ground Key detected */
+    VP_LINE_EVID_GKEY_REL       = 0x0008, /**< Ground Key release detected */
+    VP_LINE_EVID_FLASH          = 0x0010, /**< Hook switch flash detected */
+    VP_LINE_EVID_STARTPULSE     = 0x0020, /**< Start of a dial pulse detected */
+    VP_LINE_EVID_DTMF_DIG       = 0x0040, /**< New DTMF digit detected */
+    VP_LINE_EVID_PULSE_DIG      = 0x0080, /**< New pulse digit detected */
+    VP_LINE_EVID_MTONE          = 0x0100, /**< Modem tone detected */
+    VP_DEV_EVID_TS_ROLLOVER     = 0x0200, /**< Timestamp rollover */
+
+    VP_LINE_EVID_US_TONE_DETECT = 0x0400, /**< Upstream tone detection event */
+    VP_LINE_EVID_DS_TONE_DETECT = 0x0800, /**< Downstream tone detection event*/
+    VP_DEV_EVID_SEQUENCER       = 0x1000, /**< Sequencer Event */
+    VP_LINE_EVID_BREAK_MAX      = 0x2000, /**< Break Max time has been exceeded */
+    VP_LINE_EVID_EXTD_FLASH     = 0x4000, /**< Flash Hook between flash max and on-hook min */
+    VP_LINE_EVID_HOOK_PREQUAL   = 0x8000, /**< debounced off/on hook detected, but < offHookMin */
+
+    /* The following signaling events are device-specific, not line-specific */
+    VP_EVCAT_SIGNALING_DEV_EVENTS  = (int)(VP_DEV_EVID_TS_ROLLOVER |
+                                            VP_DEV_EVID_SEQUENCER),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_SIGNALING_UNDEFINED   = (int)(~(VP_LINE_EVID_HOOK_OFF          |
+                                             VP_LINE_EVID_HOOK_ON           |
+                                             VP_LINE_EVID_GKEY_DET          |
+                                             VP_LINE_EVID_GKEY_REL          |
+                                             VP_LINE_EVID_FLASH             |
+                                             VP_LINE_EVID_STARTPULSE        |
+                                             VP_LINE_EVID_DTMF_DIG          |
+                                             VP_LINE_EVID_PULSE_DIG         |
+                                             VP_LINE_EVID_MTONE             |
+                                             VP_DEV_EVID_TS_ROLLOVER        |
+                                             VP_LINE_EVID_US_TONE_DETECT    |
+                                             VP_LINE_EVID_DS_TONE_DETECT    |
+                                             VP_DEV_EVID_SEQUENCER          |
+                                             VP_LINE_EVID_BREAK_MAX         |
+                                             VP_LINE_EVID_EXTD_FLASH        |
+                                             VP_LINE_EVID_HOOK_PREQUAL)),
+
+    VP_EVCAT_SIGNALING_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                             VP_EVCAT_SIGNALING_UNDEFINED),
+    VP_EVCAT_SIGNALING_MASK_ALL     = (int)(~VP_EVCAT_SIGNALING_UNDEFINED),
+    VP_EVCAT_SIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSignalingEventType;
+
+typedef enum {
+    VP_DEV_EVID_BOOT_CMP        = 0x0001, /**< VCP Startup sequence has
+                                           * completed; Non-maskable
+                                           */
+    VP_LINE_EVID_LLCMD_TX_CMP   = 0x0002, /**< Low level write transaction has
+                                           * completed
+                                           */
+    VP_LINE_EVID_LLCMD_RX_CMP   = 0x0004, /**< Low Level read transaction has
+                                           * completed
+                                           */
+    VP_DEV_EVID_DNSTR_MBOX      = 0x0008, /**< Dowstream Mailbox event ready */
+    VP_LINE_EVID_RD_OPTION      = 0x0010, /**< Read Option request complete */
+    VP_LINE_EVID_RD_LOOP        = 0x0020, /**< Read Loop Conditions is complete
+                                           */
+    VP_EVID_CAL_CMP             = 0x0040, /**< Device or Line Calibration is
+                                           * complete
+                                           */
+    VP_EVID_CAL_BUSY            = 0x0080, /**< Calibration not performed, line
+                                           * busy
+                                           */
+    VP_LINE_EVID_GAIN_CMP       = 0x0100, /**< Gain Adjustment complete */
+    VP_LINE_EVID_QUERY_CMP      = 0x0200, /**< Query complete */
+    VP_DEV_EVID_DEV_INIT_CMP    = 0x0400, /**< Device Init complete */
+    VP_LINE_EVID_LINE_INIT_CMP  = 0x0800, /**< Line Init complete */
+    VP_DEV_EVID_IO_ACCESS_CMP   = 0x1000, /**< Device Access complete */
+    VP_LINE_EVID_LINE_IO_RD_CMP = 0x2000, /**< Line GPIO read complete */
+    VP_LINE_EVID_LINE_IO_WR_CMP = 0x4000, /**< Line GPIO write complete */
+    VP_LINE_EVID_SLAC_INIT_CMP  = 0x8000, /**< SLAC Init complete */
+    /* The following response events are device-specific, not line-specific */
+    VP_EVCAT_RESPONSE_DEV_EVENTS = (int)(VP_DEV_EVID_BOOT_CMP       |
+                                        VP_DEV_EVID_DNSTR_MBOX      |
+                                        VP_DEV_EVID_DEV_INIT_CMP    |
+                                        VP_DEV_EVID_IO_ACCESS_CMP),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_RESPONSE_UNDEFINED = (int)(~(VP_DEV_EVID_BOOT_CMP          |
+                                          VP_LINE_EVID_LLCMD_TX_CMP     |
+                                          VP_LINE_EVID_LLCMD_RX_CMP     |
+                                          VP_DEV_EVID_DNSTR_MBOX        |
+                                          VP_LINE_EVID_RD_OPTION        |
+                                          VP_LINE_EVID_RD_LOOP          |
+                                          VP_EVID_CAL_CMP               |
+                                          VP_EVID_CAL_BUSY              |
+                                          VP_LINE_EVID_GAIN_CMP         |
+                                          VP_LINE_EVID_QUERY_CMP        |
+                                          VP_DEV_EVID_DEV_INIT_CMP      |
+                                          VP_LINE_EVID_LINE_INIT_CMP    |
+                                          VP_DEV_EVID_IO_ACCESS_CMP     |
+                                          VP_LINE_EVID_LINE_IO_RD_CMP   |
+                                          VP_LINE_EVID_LINE_IO_WR_CMP   |
+                                          VP_LINE_EVID_SLAC_INIT_CMP)),
+
+    VP_EVCAT_RESPONSE_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                            VP_EVCAT_RESPONSE_UNDEFINED),
+    VP_EVCAT_RESPONSE_MASK_ALL     = (int)(~VP_EVCAT_RESPONSE_UNDEFINED),
+    VP_EVCAT_RES_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpResponseEventType;
+
+typedef enum
+{
+    VP_LINE_EVID_TEST_CMP   = 0x0001, /**< A requested test has been completed*/
+    VP_LINE_EVID_TEST_RSVD1 = 0x0002, /**< Reserved event */
+    VP_LINE_EVID_DTONE_DET  = 0x0004, /**< Dial-Tone Test - Dialtone Detected */
+    VP_LINE_EVID_DTONE_LOSS = 0x0008, /**< Dial-Tone Test - Dialtone Lost */
+    VP_DEV_EVID_STEST_CMP   = 0x0010, /**< Self Test Function complete */
+    VP_DEV_EVID_CHKSUM      = 0x0020, /**< Code-space checksum is complete */
+    VP_LINE_EVID_ABORT      = 0x0040, /**< Event requesting abort test */
+    /* The following test events are device-specific, not line-specific */
+    VP_EVCAT_TEST_DEV_EVENTS = (int)(VP_DEV_EVID_CHKSUM),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_TEST_UNDEFINED =    (int)(~(VP_LINE_EVID_TEST_CMP       |
+                                         VP_LINE_EVID_DTONE_DET      |
+                                         VP_LINE_EVID_DTONE_LOSS     |
+                                         VP_DEV_EVID_STEST_CMP       |
+                                         VP_DEV_EVID_CHKSUM)),
+
+    VP_EVCAT_TEST_UNMASK_ALL    =  (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_TEST_UNDEFINED),
+    VP_EVCAT_TEST_MASK_ALL      =  (int)(~VP_EVCAT_TEST_UNDEFINED),
+    VP_EVCAT_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpTestEventType;
+
+typedef enum
+{                               
+    VP_LINE_EVID_MTR_CMP        = 0x0001, /**< Metering Signal complete */
+    VP_LINE_EVID_MTR_ABORT      = 0x0002, /**< Metering Signal aborted */
+    VP_LINE_EVID_CID_DATA       = 0x0004, /**< Caller ID Transmission buffer is
+                                           * empty
+                                           */
+    VP_LINE_EVID_RING_CAD       = 0x0008, /**< Ring Cadence State change
+                                           * information
+                                           */
+    VP_LINE_EVID_SIGNAL_CMP     = 0x0010, /**< Signal Generation complete */
+    VP_LINE_EVID_MTR_CAD        = 0x0020, /**< Metering cadence */
+                                
+    VP_LINE_EVID_TONE_CAD       = 0x0040, /**< Tone Cadence complete */
+
+    VP_LINE_EVID_MTR_ROLLOVER   = 0x0080, /**< Metering count rollover */
+    VP_LINE_EVID_GEN_TIMER      = 0x0100, /**< Timer complete / canceled / error */
+    VP_LINE_EVID_USER           = 0x0200, /**< User-defined event */
+    VP_LINE_EVID_AUTO_LOOP_COND = 0x0400, /**< VP_OPTION_ID_AUTO_LOOP_COND event */
+
+    /* There are no device-specific process events */
+    VP_EVCAT_PROCESS_DEV_EVENTS = 0,
+
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_PROCESS_UNDEFINED =  (int)(~(VP_LINE_EVID_MTR_CMP        |
+                                          VP_LINE_EVID_MTR_ABORT      |
+                                          VP_LINE_EVID_CID_DATA       |
+                                          VP_LINE_EVID_RING_CAD       |
+                                          VP_LINE_EVID_SIGNAL_CMP     |
+                                          VP_LINE_EVID_MTR_CAD        |
+                                          VP_LINE_EVID_TONE_CAD       |
+                                          VP_LINE_EVID_MTR_ROLLOVER   |
+                                          VP_LINE_EVID_GEN_TIMER      |
+                                          VP_LINE_EVID_USER)),
+
+    VP_EVCAT_PROCESS_UNMASK_ALL =  (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_PROCESS_UNDEFINED),
+    VP_EVCAT_PROCESS_MASK_ALL   =  (int)(~VP_EVCAT_PROCESS_UNDEFINED),
+    VP_EVCAT_PRO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProcessEventType;
+
+typedef enum {
+    /* FXO API Event Types */
+    VP_LINE_EVID_RING_ON    = 0x0001, /**< Ringing detected on line */
+    VP_LINE_EVID_RING_OFF   = 0x0002, /**< Ringing previously detected has
+                                       * stopped
+                                       */
+    VP_LINE_EVID_LIU        = 0x0004, /**< Line In Use by adjacent line off
+                                       * hook
+                                       */
+    VP_LINE_EVID_LNIU       = 0x0008, /**< Line In Use by adjacent line on
+                                       * hook */
+    VP_LINE_EVID_FEED_DIS   = 0x0010, /**< Line feed disabled (or too low) */
+    VP_LINE_EVID_FEED_EN    = 0x0020, /**< Line feed enabled */
+    VP_LINE_EVID_DISCONNECT = 0x0040, /**< Line feed removed while loop close */
+    VP_LINE_EVID_RECONNECT  = 0x0080, /**< Line feed connected while loop
+                                       * close
+                                       */
+    VP_LINE_EVID_POLREV     = 0x0100, /**< Line polarity reversal has occurred*/
+    VP_LINE_EVID_POH        = 0x0200, /**< Parallel line off-hook */
+    VP_LINE_EVID_PNOH       = 0x0400, /**< Parallel line on-hook */
+
+    /* There are no device-specific FXO events */
+    VP_EVCAT_FXO_DEV_EVENTS = 0,
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_FXO_UNDEFINED =     (int)(~(VP_LINE_EVID_RING_ON        |
+                                         VP_LINE_EVID_RING_OFF       |
+                                         VP_LINE_EVID_LIU            |
+                                         VP_LINE_EVID_LNIU           |
+                                         VP_LINE_EVID_FEED_DIS       |
+                                         VP_LINE_EVID_FEED_EN        |
+                                         VP_LINE_EVID_DISCONNECT     |
+                                         VP_LINE_EVID_RECONNECT      |
+                                         VP_LINE_EVID_POLREV         |
+                                         VP_LINE_EVID_POH            |
+                                         VP_LINE_EVID_PNOH)),
+
+    VP_EVCAT_FXO_UNMASK_ALL =      (int)(VP_EVENT_MASK_ALL &
+                                     VP_EVCAT_FXO_UNDEFINED),
+    VP_EVCAT_FXO_MASK_ALL   =      (int)(~VP_EVCAT_FXO_UNDEFINED),
+    VP_EVCAT_FXO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpFxoEventType;
+
+typedef enum {
+    VP_LINE_EVID_US_PKT_RDY     = 0x0001, /**< Upstream Packet ready event */
+    VP_LINE_EVID_NEED_DS_PKT    = 0x0002, /**< Need Downstream Packet event */
+    VP_LINE_EVID_PKT_ERROR      = 0x0004, /**< Packet type error event */
+    VP_LINE_EVID_PKT_LOST       = 0x0008, /**< Packet loss event */
+    VP_LINE_EVID_RD_PKT_STATS   = 0x0010, /**< Read packet statistics complete*/
+    /* There are no device-specific packet events */
+    VP_EVCAT_PACKET_DEV_EVENTS  = 0,
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_PACKET_UNDEFINED =   (int)(~(VP_LINE_EVID_US_PKT_RDY       |
+                                          VP_LINE_EVID_NEED_DS_PKT      |
+                                          VP_LINE_EVID_PKT_ERROR        |
+                                          VP_LINE_EVID_PKT_LOST         |
+                                          VP_LINE_EVID_RD_PKT_STATS)),
+
+    VP_EVCAT_PACKET_UNMASK_ALL  =   (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_PACKET_UNDEFINED),
+    VP_EVCAT_PACKET_MASK_ALL    =  (int)(~VP_EVCAT_PACKET_UNDEFINED),
+    VP_EVCAT_PKT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPacketEventType;
+
+/* Enumerations for interpreting event data in the VpGetEvent() field */
+typedef enum {
+    VP_BAT_FLT_NONE = 0x0,
+    VP_BAT_FLT_BAT2 = 0x1,
+    VP_BAT_FLT_BAT1 = 0x2,
+    VP_BAT_FLT_BAT3 = 0x4,
+    VP_BAT_FLT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatFltEventDataType;
+
+typedef enum {
+    VP_RING_CAD_BREAK = 0,
+    VP_RING_CAD_MAKE  = 1,
+    VP_RING_CAD_DONE  = 2,
+    VP_RING_CAD_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpRingCadEventDataType;
+
+typedef enum {
+    VP_CID_DATA_NEED_MORE_DATA = 0,
+    VP_CID_DATA_TX_DONE        = 1,
+    VP_CID_DATA_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCidDataEventDataType;
+
+typedef enum {
+    VP_DIG_1         = 0x01,
+    VP_DIG_2         = 0x02,
+    VP_DIG_3         = 0x03,
+    VP_DIG_4         = 0x04,
+    VP_DIG_5         = 0x05,
+    VP_DIG_6         = 0x06,
+    VP_DIG_7         = 0x07,
+    VP_DIG_8         = 0x08,
+    VP_DIG_9         = 0x09,
+    VP_DIG_10        = 0x0A,    /* pulse only */
+    VP_DIG_11        = 0x0B,    /* pulse only */
+    VP_DIG_12        = 0x0C,    /* pulse only */
+    VP_DIG_13        = 0x0D,    /* pulse only */
+    VP_DIG_14        = 0x0E,    /* pulse only */
+    VP_DIG_15        = 0x0F,    /* pulse only */
+    VP_DIG_ZERO      = 0x0A,    /* DTMF only */
+    VP_DIG_ASTER     = 0x0B,    /* DTMF only */
+    VP_DIG_POUND     = 0x0C,    /* DTMF only */
+    VP_DIG_A         = 0x0D,    /* DTMF only */
+    VP_DIG_B         = 0x0E,    /* DTMF only */
+    VP_DIG_C         = 0x0F,    /* DTMF only */
+    VP_DIG_D         = 0x00,    /* DTMF only */
+    VP_DIG_NONE      = 0xFF,
+    VP_DIG_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_DIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitType;
+
+/*
+ * Indicates which set of Dial Pulse Specifications were met that is generating
+ * the dial pulse event.
+ */
+typedef enum {
+    VP_DP_PARAM1 = 0,
+    VP_DP_PARAM2 = 1,
+    VP_DP_PARAM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDialPulseParamType;
+
+typedef enum {
+    VP_DIG_SENSE_BREAK = 0x0000,
+    VP_DIG_SENSE_MAKE  = 0x0010,
+    VP_DIG_SENSE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitSenseType;
+
+typedef enum {
+    VP_POLREV_NORMAL  = 0, /* Line detected Reverse-to-Normal Transition */
+    VP_POLREV_REVERSE = 1, /* Line detected Normal-to-Reverse Transition */
+    VP_POLREV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPolRevEventDataType;
+
+typedef enum {
+    VP_SYNC_MB_ERR        = 0x00,
+    VP_SYNC_SEQ_BAD_INST  = 0x81, /* Unknown instruction in sequence */
+    VP_SYNC_SEQ_BAD_BR    = 0x82, /* Sequencer encountered bad branch (either
+                                   * a forward branch or too many nesting levels */
+    VP_SYNC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSyncFltEventDataType;
+
+typedef enum {
+    VP_GEN_TIMER_STATUS_CMP      = 0,
+    VP_GEN_TIMER_STATUS_CANCELED = 1,
+    VP_GEN_TIMER_STATUS_RESRC_NA = 2,
+    VP_GEN_TIMER_STATUS_UNKNOWN  = 3,
+    VP_GEN_TIMER_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGenTimerStatusType;
+
+typedef enum {
+    VP_FLASH_ONLY = 0,
+    VP_FLASH_AND_DIGIT1 = 1
+} VpFlashEventDataType;
+
+typedef uint16 VpHookPrequalEventDataType;
+#define VP_HOOK_PREQUAL_START   (0) /* Debounced off-hook detected, but offHookMin > 0 */
+#define VP_HOOK_PREQUAL_ABORT   (1) /* Debounced on-hook detected, but duration < offHookMin */
+
+
+/**
+ * Non-maskable events are (with reasons):
+ *
+ *   Boot Complete -- Cannot mask.  Masking events requires that the boot has
+ *                   been completed.
+ *   Read Option -- To modify mask interrupts requires that the current mask
+ *                  options can be read.  The only way to know the read option
+ *                  is ready is via an unmasked Read Option Complete event.
+ *   Device Init -- Fundamental event to know when device is initialized and
+ *                  remaining options/line configurations can be set.  There
+ *                  is no other standard "timeout" mechanism to know when the
+ *                  device has been initialized properly.
+ *   Line Init -- Fundamental event to know when a line is initialized and ready
+ *                to be setup with remaining user defined options.  There is no
+ *                other standard "timeout" mechanism to know when the line has
+ *                been initialized properly.
+ *   Events that have responses -- These events are non-maskable. If an event
+ *                that has a response is masked, and if the response is not
+ *                read, in case of CSLAC devices, it blocks response buffer.
+ *                In case of VCP class of devices, response mailbox is
+ *                locked up. If this is followed by another command that
+ *                requires the response mailbox, that command can't complete
+ *                execution since the response mailbox is busy. Now no more
+ *                commands can be issued because the previous command can't
+ *                complete.
+ */
+
+#define VP_API_NONMASK_FAULT_EVENTS         0x0000
+#define VP_API_NONMASK_SIGNALING_EVENTS     0x0000
+
+#define VP_API_NONMASK_RESPONSE_EVENTS      (VP_DEV_EVID_BOOT_CMP \
+                                           | VP_LINE_EVID_LLCMD_RX_CMP \
+                                           | VP_LINE_EVID_RD_OPTION \
+                                           | VP_LINE_EVID_RD_LOOP \
+                                           | VP_LINE_EVID_GAIN_CMP \
+                                           | VP_LINE_EVID_QUERY_CMP \
+                                           | VP_DEV_EVID_DEV_INIT_CMP \
+                                           | VP_LINE_EVID_LINE_INIT_CMP \
+                                           | VP_DEV_EVID_IO_ACCESS_CMP \
+                                           | VP_LINE_EVID_LINE_IO_RD_CMP \
+                                           | VP_LINE_EVID_SLAC_INIT_CMP)
+
+#define VP_API_NONMASK_TEST_EVENTS          (VP_LINE_EVID_TEST_CMP \
+                                           | VP_DEV_EVID_CHKSUM)
+
+#define VP_API_NONMASK_PROCESS_EVENTS       VP_LINE_EVID_GEN_TIMER
+#define VP_API_NONMASK_FXO_EVENTS           0x0000
+#define VP_API_NONMASK_PACKET_EVENTS        0x0000
+
+#endif /* VP_API_EVENT_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_fxo_params.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_fxo_params.h
new file mode 100755
index 0000000..15f1dae
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_fxo_params.h
@@ -0,0 +1,67 @@
+/** \file vp_api_fxo_params.h
+ * vp_api_fxo_params.h
+ *
+ * This file contains the Zarlink Semiconductor approved system parameters for proper
+ * FXO operation on the reference designs
+ *
+ * $Revision: 5442 $
+ * $LastChangedDate: 2009-08-17 12:13:24 -0500 (Mon, 17 Aug 2009) $
+ */
+
+#ifndef VP_API_FXO_PARAMS_H
+#define VP_API_FXO_PARAMS_H
+
+#define VP_FXO_DTMF_ON_DEFAULT          0x0027  /* DTMF On = 195mS */
+#define VP_FXO_DTMF_OFF_DEFAULT         0x0028  /* DTMF Off = 200mS */
+#define VP_FXO_FLASH_HOOK_DEFAULT       0x0078  /* Flash Hook = 600mS */
+#define VP_FXO_PULSE_BREAK_DEFAULT      0x0C    /* Pulse Break = 60mS */
+#define VP_FXO_PULSE_MAKE_DEFAULT       0x08    /* Pulse Make = 40mS */
+#define VP_FXO_INTERDIG_DEFAULT         0x0028  /* Interdigit Period = 200mS */
+#define VP_FXO_RING_DET_MAX_DEFAULT     0xEB    /* Ring Period Max = 58.75mS */
+#define VP_FXO_RING_DET_MIN_DEFAULT     0x79    /* Ring Period Min = 30.25mS */
+#define VP_FXO_RING_DET_VOLT_DEFAULT    0x02    /* Ring Voltage Min = 38V */
+#define VP_FXO_DISC_DET_MIN_DEFAULT     0x03    /* Disconnect Det Min = 4.2V */
+#define VP_FXO_LIU_DET_THRESH_DEFAULT   0x26    /* Line-In-Use Det Threshold = 38V */
+
+/* In ms, time that FXO detector activity is ignored after a state change */
+#define VP_FXO_STATE_CHANGE_DEBOUNCE    (50)
+
+/* In ms, time that FXO detector activity is ignored after a ring trip */
+#define VP_FXO_RING_TRIP_DEBOUNCE       (200)
+
+/* In ms, time that FXO disconnect detector is debounced */
+#define VP_FXO_DISCONNECT_DEBOUNCE      (300)
+
+/* In ms, time that FXO will change to loop open if detecting disconnect */
+#define VP_FXO_DISC_TO_LOOP_OPEN        (5000)
+
+typedef enum
+{
+    VP_FXO_DIALING_PROFILE_DTMF_ON_MSB = 6,
+    VP_FXO_DIALING_PROFILE_DTMF_ON_LSB = 7,
+    VP_FXO_DIALING_PROFILE_DTMF_OFF_MSB = 8,
+    VP_FXO_DIALING_PROFILE_DTMF_OFF_LSB = 9,
+    VP_FXO_DIALING_PROFILE_FLASH_HOOK_MSB = 10,
+    VP_FXO_DIALING_PROFILE_FLASH_HOOK_LSB = 11,
+    VP_FXO_DIALING_PROFILE_PULSE_BREAK = 12,
+    VP_FXO_DIALING_PROFILE_PULSE_MAKE = 13,
+    VP_FXO_DIALING_PROFILE_INTERDIGIT_MSB = 14,
+    VP_FXO_DIALING_PROFILE_INTERDIGIT_LSB = 15,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MAX = 16,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MIN = 17,
+    VP_FXO_DIALING_PROFILE_RING_VOLTAGE_MIN = 18,
+    VP_FXO_DIALING_PROFILE_DISC_VOLTAGE_MIN = 19,
+    VP_FXO_DIALING_PROFILE_LIU_THRESHOLD_MIN = 20,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MAX_ACT = 21,
+    VP_FXO_DIALING_PROFILE_DTMF_HIGH_LVL_MSB = 22,
+    VP_FXO_DIALING_PROFILE_DTMF_HIGH_LVL_LSB = 23,
+    VP_FXO_DIALING_PROFILE_DTMF_LOW_LVL_MSB = 24,
+    VP_FXO_DIALING_PROFILE_DTMF_LOW_LVL_LSB = 25,
+    VP_FXO_DIALING_PROFILE_POH_INT_TIME = 26,
+    VP_FXO_DIALING_PROFILE_POH_THRESHOLD = 27,
+    VP_FXO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} vp_fxo_dialingProfileParams;
+#endif
+
+
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_int.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_int.h
new file mode 100755
index 0000000..3968c3b
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_int.h
@@ -0,0 +1,622 @@
+/** \file vp_api_int.h
+ * vp_api_int.h
+ *
+ * Header file for the API-II c files. This file contains the declarations
+ * and defintions required to implement the VTD specific VP-API. This file
+ * is used by VP-API internally. This file should not be included by the
+ * application.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8620 $
+ * $LastChangedDate: 2011-06-02 13:27:26 -0500 (Thu, 02 Jun 2011) $
+ */
+
+#ifndef VP_API_INT_H
+#define VP_API_INT_H
+
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "vp_api.h"
+#include "vp_api_option.h"
+
+#include "vp_debug.h"
+
+/******************************************************************************
+ *                              VP-API Defines                                *
+ ******************************************************************************/
+#define VP_ALL_LINES            0xFF  /**< Internal constant used to identify
+                                       * all lines
+                                       */
+#define VP_ALL_SLACS          0xFFFF  /**< Internal constant used to identify
+                                       * all SLACs
+                                       */
+
+/**< Profile types as defined by Profile Wizard */
+typedef enum {
+    VP_PRFWZ_PROFILE_AC = 0x00,
+    VP_PRFWZ_PROFILE_DC = 0x01,
+    VP_PRFWZ_PROFILE_TONE = 0x02,
+    VP_PRFWZ_PROFILE_TONECAD = 0x03,
+    VP_PRFWZ_PROFILE_RING = 0x04,
+    VP_PRFWZ_PROFILE_CID_TYPE1 = 0x05,
+    VP_PRFWZ_PROFILE_CID_TYPE2 = 0x06,
+    VP_PRFWZ_PROFILE_METER = 0x07,
+    VP_PRFWZ_PROFILE_RINGCAD = 0x08,
+    VP_PRFWZ_PROFILE_TEST_CRITERIA = 0x09,
+    VP_PRFWZ_PROFILE_TEST_TOPOLOGY = 0x0A,
+    VP_PRFWZ_PROFILE_FXS_CTRL = 0x0B,
+    VP_PRFWZ_PROFILE_CAL = 0x0C,
+    VP_PRFWZ_PROFILE_METERING_GEN,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_HOOK_FLASH_DIG_GEN,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_DIAL_PULSE_DIG_GEN,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_DTMF_DIG_GEN,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_MSG_WAIT_PULSE_INT,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_LINE_CAL_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_FWD_DISC_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_POLREV_PULSE_INT,      /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_MOMENTARY_LOOP_OPEN_INT,   /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_TIP_OPEN_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_NONE,                  /**< Indicates that internal
+                                                 profile data is not valid */
+    VP_PRFWZ_PROFILE_880_CAL_DATA = 0xFC,
+    VP_PRFWZ_PROFILE_890_CAL_DATA = 0xFD,
+
+    VP_PRFWZ_PROFILE_FXO_CONFIG = 0xFE,
+    VP_PRFWZ_PROFILE_DEVICE = 0xFF,
+    VP_PRFWZ_PROFILE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req.*/
+} VpProfileWizProfileType;
+
+typedef enum {
+    VP_PRFWZ_CUSTOM_ST_STANDBY = 0x00,
+    VP_PRFWZ_CUSTOM_ST_ACTIVE = 0x02,
+    VP_PRFWZ_CUSTOM_ST_ACTIVE_PR = 0x03,
+    VP_PRFWZ_CUSTOM_ST_TIP_OPEN = 0x04,
+    VP_PRFWZ_CUSTOM_ST_OHT = 0x06,
+    VP_PRFWZ_CUSTOM_ST_OHT_PR = 0x07,
+    VP_PRFWZ_CUSTOM_ST_DISCONNECT = 0x08,
+    VP_PRFWZ_CUSTOM_ST_RINGING = 0x09,
+    VP_PRFWZ_CUSTOM_ST_DET_MAP = 0xFF,
+    VP_PRFWZ_CUSTOM_ST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req.*/
+} VpProfileWizCustomStateType;
+
+/** These locations are common to all profiles used in the API */
+typedef enum
+{
+    VP_PROFILE_TYPE_MSB = 0,
+    VP_PROFILE_TYPE_LSB = 1,
+    VP_PROFILE_INDEX = 2,
+    VP_PROFILE_LENGTH = 3,
+    VP_PROFILE_VERSION = 4,
+    VP_PROFILE_MPI_LEN = 5,
+    VP_PROFILE_DATA_START = 6,
+    VP_PROFILE_HDR_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProfileHeaderFieldType;
+
+/* Define the Ringing Type (balanced/unbalanced) offset from end of MPI data */
+#define VP_PROFILE_RING_TYPE_OFFSET     1
+
+/** These are the locations of parameters in version 01 ringing profiles */
+typedef enum
+{
+    VP_RING_PROFILE_RING_TRIP   = 18,
+    VP_RING_PROFILE_CURRENT_LIM = 19,
+    VP_RING_PROFILE_MAX_RING_V  = 20,
+    VP_RING_PROFILE_TRACK_MODE  = 21,
+    VP_RING_PROFILE_ENUM_SIZE  =  FORCE_STANDARD_C_ENUM_SIZE /* Portability Req */
+} VpRingProfileFieldType;
+
+/** These are the locations of parameters in version 01 DC profiles */
+typedef enum
+{
+    VP_DC_PROFILE_THRESHOLDS =  9,
+    VP_DC_PROFILE_DEBOUNCES  =  10,
+    VP_DC_PROFILE_FLOOR_V    =  11,
+    VP_DC_PROFILE_HOOK_HYST  =  12,
+    VP_DC_PROFILE_ENUM_SIZE  =  FORCE_STANDARD_C_ENUM_SIZE /* Portability Req */
+} VpDcProfileFieldType;
+
+typedef enum
+{
+    /*
+     * These parameters are the absolute locations of the specified value in
+     * the CID profile
+     */
+    VP_CID_PROFILE_FSK_PARAM_LEN = 6,
+    VP_CID_PROFILE_FSK_PARAM_CMD = 7,
+    VP_CID_PRFT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCidProfileFieldType;
+
+/*
+ * These parameters are offset from the end of the FSK data to the value
+ * specified
+ */
+#define VP_CID_PROFILE_CHECKSUM_OFFSET_MSB      (1)
+#define VP_CID_PROFILE_CHECKSUM_OFFSET_LSB      (2)
+#define VP_CID_PROFILE_LENGTH_OF_ELEMENTS_MSB   (3)
+#define VP_CID_PROFILE_LENGTH_OF_ELEMENTS_LSB   (4)
+#define VP_CID_PROFILE_START_OF_ELEMENTS_MSB    (5)
+#define VP_CID_PROFILE_START_OF_ELEMENTS_LSB    (6)
+
+/** These locations are for Tone and Ringing Cadence (Sequencer) profiles */
+#define VP_PROFILE_TYPE_SEQUENCER_COUNT_MSB (6)
+#define VP_PROFILE_TYPE_SEQUENCER_COUNT_LSB (7)
+#define VP_PROFILE_TYPE_SEQUENCER_START     (8)
+
+/** These locations are for Calibration profiles */
+#define VP_CAL_PROFILE_NUM_ENTRIES  (6)
+#define VP_CAL_PROFILE_FIRST_ENTRY  (8)
+
+/******************************************************************************
+ *                        API Specific common FUNCTION PROTOTYPES             *
+ ******************************************************************************/
+void
+VpImplementNonMaskEvents(
+    VpOptionEventMaskType *pLineEventsMask,
+    VpOptionEventMaskType *pDevEventsMask);
+
+VpStatusType
+VpImplementDefaultSettings(
+    VpDevCtxType *pDevCtx,
+    VpLineCtxType *pLineCtx);
+
+EXTERN int
+VpGetProfileIndex (
+    const VpProfilePtrType pProfile);
+
+EXTERN bool
+VpVerifyProfileType(
+    VpProfileType type,
+    VpProfilePtrType pProfile);
+
+EXTERN bool
+VpIsDigit(
+    VpDigitType digit);
+
+/******************************************************************************
+ *                        VCP Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_VCP_SERIES)
+VpStatusType
+VpMakeVcpDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpVcpDeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVcpDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpVcpDeviceObjectType *pDevObj);
+
+#endif /* VP_CC_VCP_SERIES */
+
+/******************************************************************************
+ *                        VCP2 Specific FUNCTION PROTOTYPES                   *
+ ******************************************************************************/
+#if defined (VP_CC_VCP2_SERIES)
+VpStatusType
+Vcp2MakeDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpVcp2DeviceObjectType *pDevObj);
+
+VpStatusType
+Vcp2MakeDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpVcp2DeviceObjectType *pDevObj);
+
+EXTERN bool
+Vcp2ReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN void
+Vcp2SetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+#endif /* VP_CC_VCP2_SERIES */
+/******************************************************************************
+ *                        MELT Specific FUNCTION PROTOTYPES                   *
+ ******************************************************************************/
+#if defined (VP_CC_MELT_SERIES)
+
+VpStatusType
+MeltMakeDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpMeltDeviceObjectType *pDevObj);
+
+VpStatusType
+MeltMakeDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpMeltDeviceObjectType *pDevObj);
+
+EXTERN bool
+MeltReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN void
+MeltSetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+#endif /* VP_CC_MELT_SERIES */
+
+/******************************************************************************
+ *                        Kernel Specific FUNCTION PROTOTYPES                 *
+ ******************************************************************************/
+#if defined (VP_CC_KWRAP)
+  #include "vp_kernel.h"
+#endif /* VP_CC_KWRAP */
+
+
+/******************************************************************************
+ *                        790 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_790_SERIES)
+
+#ifndef VP790_EC_CH1
+  #define VP790_EC_CH1    0x01
+  #define VP790_EC_CH2    0x02
+  #define VP790_EC_CH3    0x04
+  #define VP790_EC_CH4    0x08
+#endif
+
+VpStatusType
+VpMakeVp790DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp790DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp790DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp790DeviceObjectType *pDevObj);
+
+void
+Vp790MuteChannel(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+bool
+Vp790FSKGeneratorReady(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+Vp790CliGetEncodedByte(
+    VpLineCtxType *pLineCtx,
+    uint8 *pByte);
+
+VpStatusType
+Vp790CtrlSetCliTone(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+void
+Vp790CtrlSetFSKGen(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    uint8 data);
+#endif /* VP_CC_790_SERIES */
+
+/******************************************************************************
+ *                        792 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+
+#if defined (VP_CC_792_SERIES)
+VpStatusType
+Vp792MakeDeviceObject(
+    VpDevCtxType            *pDevCtx,
+    Vp792DeviceObjectType   *pDevObj);
+
+VpStatusType
+Vp792MakeDeviceCtx(
+    VpDevCtxType            *pDevCtx,
+    Vp792DeviceObjectType   *pDevObj);
+
+#ifdef VP_CC_792_GROUP
+bool
+Vp792GroupGetEvent(
+    VpDevCtxType *pDevCtx,
+    VpEventType *pEvent);
+#endif
+#endif /* VP_CC_792_SERIES */
+
+/******************************************************************************
+ *                        880 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_880_SERIES)
+
+#ifndef VP880_EC_CH1
+  #define VP880_EC_CH1                0x01
+  #define VP880_EC_CH2                0x02
+#endif
+
+#ifndef VP880_WIDEBAND_MODE
+  #define VP880_WIDEBAND_MODE         0x20
+#endif
+
+VpStatusType
+VpMakeVp880DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp880DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp880DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp880DeviceObjectType *pDevObj);
+
+void
+Vp880MuteChannel(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+#if defined (VP_CSLAC_SEQ_EN) && defined (VP880_FXS_SUPPORT)
+bool
+Vp880FSKGeneratorReady(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+Vp880CliGetEncodedByte(
+    VpLineCtxType *pLineCtx,
+    uint8 *pByte);
+
+VpStatusType
+Vp880CtrlSetCliTone(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+void
+Vp880CtrlSetFSKGen(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    uint8 data);
+#endif
+
+VpStatusType
+Vp880SetDTMFGenerators(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    VpDigitType digit);
+
+VpStatusType
+Vp880SetLineStateInt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp880SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+void
+Vp880LLSetSysState(
+    VpDeviceIdType deviceId,
+    VpLineCtxType *pLineCtx,
+    uint8 lineState,
+    bool writeToDevice);
+#endif /* VP_CC_880_SERIES */
+
+
+/******************************************************************************
+ *                        890 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_890_SERIES)
+  #include "vp890_api_int.h"
+#endif /* VP_CC_890_SERIES */
+
+
+/******************************************************************************
+ *                        580 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+VpMakeVp580DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp580DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp580DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp580DeviceObjectType *pDevObj);
+
+#endif /* VP_CC_580_SERIES */
+
+/* Functions used internal to the API -- device dependant */
+#if defined (VP_CC_790_SERIES) || defined (VP_CC_880_SERIES) \
+ || defined (VP_CC_580_SERIES) || defined (VP_CC_890_SERIES)
+
+/* Converts ms to units of API_TICKRATE */
+#define MS_TO_TICKRATE(MS, API_TICKRATE)  \
+    ((uint16)(((((uint32)MS*256*2)/API_TICKRATE)+1)/2))
+#define TICKS_TO_MS(TICKS, API_TICKRATE)  \
+    (uint16) (((uint32)API_TICKRATE * (uint32)TICKS) / 256)
+#define MS_TO_TICKS_ROUND_UP(MS, API_TICKRATE)  \
+    ((uint16)(((((uint32)MS*256*2 + API_TICKRATE - 1)/API_TICKRATE)+1)/2))
+/* Gives frequency in units of 0.3662109375 Hz for signal generators */
+#define TICKRATE_TO_HZ(API_TICKRATE)  \
+    ((uint16)((uint32)(0x80000000 / API_TICKRATE) / 0x0C00))
+
+#define NO_DATA     0x00
+#define NOOP_CMD    0x06  /**< Standard No operation comnmand for all devices */
+
+#define MAX_CFAIL_TEST      10
+#define CFAIL_TEST_INTERVAL 10
+
+/**< CallerID Profile Data structure definitions */
+#define VP_FSK_MARK_SIGNAL     0xFF
+#define VP_FSK_CHAN_SEIZURE    0x55
+#define VP_FSK_DATA            0x11 /* Anything NOT Mark or C.S is ok */
+#define VP_FSK_NONE            0x00 /* When FSK Generator is not being used */
+
+typedef enum
+{
+    VP_CLI_NULL = 0,
+    VP_CLI_POLREV,              /**< No Parameters */
+    VP_CLI_MUTEON,              /**< No Parameters */
+    VP_CLI_MUTEOFF,             /**< No Parameters */
+    VP_CLI_ALERTTONE,           /**< Duration/Tone definition parameters */
+    VP_CLI_ALERTTONE2,          /**< Internal Alert Tone indicator */
+    VP_CLI_SILENCE,             /**< Duration Parameter */
+    VP_CLI_SILENCE_MASKHOOK,    /**< Duration/Masked-hook length parameters */
+    VP_CLI_DETECT,              /**< Tone and Timeout parameters */
+    VP_CLI_CHANSEIZURE,         /**< Duration Parameter */
+    VP_CLI_MARKSIGNAL,          /**< Duration Parameter */
+    VP_CLI_MESSAGE,             /**< No Parameters */
+    VP_CLI_USER_DEFINED,        /**< Not supported in API-II */
+    VP_CLI_EOT = 0x0D,          /**< No Parameters */
+    VP_CLI_DTMF_MESSAGE = 0x0E, /**< Message data to be sent in DTMF format */
+    VP_CLI_ELM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpApiElementsType;
+
+/* VP API Function Prototypes - Not associated with a function pointer */
+#if defined(VP_CC_790_SERIES) || defined(VP_CC_880_SERIES) \
+ || defined(VP_CC_890_SERIES) || defined(VP_CC_580_SERIES)
+
+#ifdef VP_CC_890_SERIES
+VpStatusType
+Vp890InitDevicePcnRcn(
+    Vp890DeviceObjectType   *pDevObj,
+    VpDeviceIdType          deviceId);
+#endif
+
+#ifdef VP_CC_880_SERIES
+VpStatusType
+Vp880InitDevicePcnRcn(
+    Vp880DeviceObjectType   *pDevObj,
+    VpDeviceIdType          deviceId);
+#endif
+
+bool
+VpIsLowPowerTermType(
+    VpTermType termType);
+
+void
+VpCSLACClearMPIBuffer(
+    VpDeviceIdType deviceId);
+
+bool
+VpCSLACIsProfileValid(
+    VpProfileType       profType,
+    int16               tableSize,
+    uint16              profEntry,
+    VpProfilePtrType    *pProfTable,
+    VpProfilePtrType    pProfileInput,
+    VpProfilePtrType    *pProfileRslt);
+
+bool
+VpCSLACSetTimer(
+    uint16 *pTimer,
+    uint16 newValue);
+
+#endif
+
+int16
+VpConvertToInt16(
+    uint8 *dataPtr);
+
+int32
+VpConvertToInt32(
+    uint8 *dataPtr);
+
+VpStatusType
+VpCSLACSetAbsGain(
+    VpLineCtxType *pLineCtx,
+    VpOptionAbsGainType *gains);
+
+uint8
+ConvertApiState2PrfWizState(
+    const VpLineStateType state);
+
+VpLineStateType
+ConvertPrfWizState2ApiState(
+    uint8 state);
+
+void
+InitTimerVars(
+    VpLineCtxType *pLineCtx);
+
+bool
+VpUpdateDP(
+    uint16 tickRate,
+    VpOptionPulseType *pPulseSpecs,
+    VpDialPulseDetectType *pDpStruct,
+    VpOptionEventMaskType *pLineEvents);
+
+void
+VpInitDP(
+    VpDialPulseDetectType *pDpStruct);
+
+VpStatusType
+VpCSLACGetLineStatus(
+    VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+#if !defined(VP_REDUCED_API_IF)
+VpStatusType
+VpCSLACClearResults(
+    VpDevCtxType *pDevCtx);
+#endif
+
+VpStatusType
+VpCSLACDtmfDigitDetected(
+    VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+VpLineStateType
+VpGetReverseState(
+    VpLineStateType currentState);
+
+void
+VpCSLACSetVas(
+    uint8 *dcFeed,
+    uint16 vasValue);
+
+#ifdef CSLAC_GAIN_RELATIVE
+void
+VpConvertFixed2Csd(
+    uint16 fixed,
+    uint8 *csdBuf);
+
+uint16
+VpConvertCsd2Fixed(
+    uint8 *csdBuf);
+#endif
+#endif
+
+#if defined (VP_CC_790_SERIES)
+VpStatusType
+Vp790SetLineStateInt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp790SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+#endif
+
+
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+Vp580SetLineStateInt(
+
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp580SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+#endif
+
+uint16
+VpComputeSquareRoot(
+    uint32 number);
+
+#endif /* VP_API_INT_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_lib_cfg.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_lib_cfg.h
new file mode 100755
index 0000000..1a0828d
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_lib_cfg.h
@@ -0,0 +1,106 @@
+/** \file vp_api_lib_cfg.h
+ * vp_api_lib_cfg.h
+ *
+ * This file contains the default options for various libraries. In general
+ * the default options are same as top level API default options. However
+ * VP-API provides a mechanism to define default options that is different
+ * compared to top level default options. This file provides such a mechanism.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 7591 $
+ * $LastChangedDate: 2010-08-16 09:33:04 -0500 (Mon, 16 Aug 2010) $
+ */
+
+#ifndef VP_API_LIB_CFG_H
+#define VP_API_LIB_CFG_H
+
+/******************************************************************************
+ * Library Specific default options                                           *
+ *****************************************************************************/
+/* The following section provides mechanisms to define default options for
+ * individual VTD families that is different compared to VP-API top level
+ * default settins.
+ *
+ * NOTE: Users are free to change individual library's default settings as long
+ * as it is not needed by the API and the VTD understands it.
+ */
+
+#ifdef VP_CC_VCP_SERIES
+
+/* Default Event Masks for VCP */
+/* First, define the events that VCP does not understand or not needed */
+#define VCP_EVCAT_FAULT_NOT_NEEDED \
+        (VP_DEV_EVID_EVQ_OFL_FLT    | /* VCP does not understand */ \
+         VP_DEV_EVID_WDT_FLT)        /* VCP does not understand */
+/* Second, define the events that are specially needed for the VCP API */
+#define VCP_EVCAT_FAULT_NEEDED (~0x0000)
+
+/* Third, Define the composite events */
+#define VCP_OPTION_DEFAULT_FAULT_EVENT_MASK  \
+    ((VP_OPTION_DEFAULT_FAULT_EVENT_MASK  |  /* Top level API default */ \
+     VCP_EVCAT_FAULT_NOT_NEEDED) &         /* Events not needed for VCP*/ \
+     VCP_EVCAT_FAULT_NEEDED)                /* Events needed for VCP */
+
+/* First, define the events that VCP does not understand or not needed */
+#define VCP_EVCAT_SIGNALLING_NOT_NEEDED \
+        (VP_LINE_EVID_US_TONE_DETECT | /* VCP does not understand */  \
+         VP_LINE_EVID_DS_TONE_DETECT | /* VCP does not understand */  \
+         VP_DEV_EVID_SEQUENCER)       /* VCP does not understand */
+/* Second, define the events that are specially needed for the VCP API */
+#define VCP_EVCAT_SIGNALLING_NEEDED (~0x0000)
+
+/* Third, Define the composite events */
+#define VCP_OPTION_DEFAULT_SIGNALING_EVENT_MASK  \
+    ((VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK  |  /* Top level API default */ \
+     VCP_EVCAT_SIGNALLING_NOT_NEEDED) &         /* Events not needed for VCP*/ \
+     VCP_EVCAT_SIGNALLING_NEEDED)                /* Events needed for VCP */
+
+/* First, define the events that VCP does not understand or not needed */
+#define VCP_EVCAT_RESPONSE_NOT_NEEDED \
+        (VP_DEV_EVID_DEV_INIT_CMP ) /* VCP does not understand */
+/* Second, define the events that are specially needed for the VCP API */
+#define VCP_EVCAT_RESPONSE_NEEDED (~0x0000)
+
+/* Third, Define the composite events */
+#define VCP_OPTION_DEFAULT_RESPONSE_EVENT_MASK  \
+    ((VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK  |  /* Top level API default */ \
+     VCP_EVCAT_RESPONSE_NOT_NEEDED) &         /* Events not needed for VCP*/ \
+     VCP_EVCAT_RESPONSE_NEEDED)                /* Events needed for VCP */
+
+#define VCP_OPTION_DEFAULT_FXO_EVENT_MASK    (0xffff)/* VCP does not understand */
+
+#define VCP_OPTION_DEFAULT_PACKET_EVENT_MASK (0xffff)/* VCP does not understand */
+#endif /* VP_CC_VCP_SERIES */
+
+
+#ifdef VP_CC_VCP2_SERIES
+/* Default option settings for VCP2:  These are the default values applied at
+ * VpInitDevice() and/or VpInitLine().  If your application uses more than one
+ * type of device (VTD) and you with to specify VCP2-specific defaults that
+ * differ from the defaults specified in vp_api_cfg.h, do so here. */
+
+#include "vcp2_api.h"
+
+/* VCP2-specific default event masks: */
+#define VCP2_DEFAULT_MASK_FAULT     (VP_OPTION_DEFAULT_FAULT_EVENT_MASK     | VCP2_INVALID_FAULT_EVENTS)
+#define VCP2_DEFAULT_MASK_SIGNALING (VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK | VCP2_INVALID_SIGNALING_EVENTS)
+#define VCP2_DEFAULT_MASK_RESPONSE  (VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK  | VCP2_INVALID_RESPONSE_EVENTS)
+#define VCP2_DEFAULT_MASK_TEST      (VP_OPTION_DEFAULT_TEST_EVENT_MASK      | VCP2_INVALID_TEST_EVENTS)
+#define VCP2_DEFAULT_MASK_PROCESS   (VP_OPTION_DEFAULT_PROCESS_EVENT_MASK   | VCP2_INVALID_PROCESS_EVENTS)
+#define VCP2_DEFAULT_MASK_FXO       (VP_OPTION_DEFAULT_FXO_EVENT_MASK       | VCP2_INVALID_FXO_EVENTS)
+#define VCP2_DEFAULT_MASK_PACKET    (VP_OPTION_DEFAULT_PACKET_EVENT_MASK    | VCP2_INVALID_PACKET_EVENTS)
+
+#endif
+#ifdef VP_CC_MELT_SERIES
+
+#define MELT_DEFAULT_MASK_FAULT     (VP_OPTION_DEFAULT_FAULT_EVENT_MASK     | MELT_INVALID_FAULT_EVENTS)
+#define MELT_DEFAULT_MASK_SIGNALING (VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK | MELT_INVALID_SIGNALING_EVENTS)
+#define MELT_DEFAULT_MASK_RESPONSE  (VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK  | MELT_INVALID_RESPONSE_EVENTS)
+#define MELT_DEFAULT_MASK_TEST      (VP_OPTION_DEFAULT_TEST_EVENT_MASK      | MELT_INVALID_TEST_EVENTS)
+#define MELT_DEFAULT_MASK_PROCESS   (VP_OPTION_DEFAULT_PROCESS_EVENT_MASK   | MELT_INVALID_PROCESS_EVENTS)
+#define MELT_DEFAULT_MASK_FXO       (VP_OPTION_DEFAULT_FXO_EVENT_MASK       | MELT_INVALID_FXO_EVENTS)
+#define MELT_DEFAULT_MASK_PACKET    (VP_OPTION_DEFAULT_PACKET_EVENT_MASK    | MELT_INVALID_PACKET_EVENTS)
+#endif
+#endif /* VP_API_LIB_CFG_H */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_option.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_option.h
new file mode 100755
index 0000000..c935820
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_option.h
@@ -0,0 +1,398 @@
+/** \file vp_api_option.h
+ * vp_api_option.h
+ *
+ * This file contains declaration associated with VP-API Options.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8467 $
+ * $LastChangedDate: 2011-04-01 10:24:49 -0500 (Fri, 01 Apr 2011) $
+ */
+
+#ifndef VP_API_OPTION
+#define VP_API_OPTION
+
+#include "vp_api_types.h"
+#include "vp_api_cfg.h"
+#include "vp_api_event.h"
+
+/* Option IDs.  (See Options chapter in VP-API-2 Reference Guide.)
+ * Line-specific option IDs begin with "VP_OPTION_ID_".  Device-specific
+ * option IDs begin with "VP_DEVICE_OPTION_ID_".  When new option IDs are added,
+ * the VpOptionValueType struct (below) must be updated accordingly.
+ */
+typedef enum {
+    VP_DEVICE_OPTION_ID_PULSE            = 0x00,
+    VP_DEVICE_OPTION_ID_CRITICAL_FLT     = 0x01,
+    VP_OPTION_ID_ZERO_CROSS              = 0x02,
+    VP_DEVICE_OPTION_ID_RAMP2STBY        = 0x03,
+    VP_OPTION_ID_PULSE_MODE              = 0x04,
+    VP_OPTION_ID_TIMESLOT                = 0x05,
+    VP_OPTION_ID_CODEC                   = 0x06,
+    VP_OPTION_ID_PCM_HWY                 = 0x07,
+    VP_OPTION_ID_LOOPBACK                = 0x08,
+    VP_OPTION_ID_LINE_STATE              = 0x09,
+    VP_OPTION_ID_EVENT_MASK              = 0x0A,
+    VP_OPTION_ID_RESERVED_1              = 0x0B,
+    VP_OPTION_ID_RING_CNTRL              = 0x0C,
+    VP_OPTION_ID_RESERVED_2              = 0x0D,
+    VP_OPTION_ID_DTMF_MODE               = 0x0E,
+    VP_DEVICE_OPTION_ID_DEVICE_IO        = 0x0F,
+    VP_OPTION_ID_RESERVED_EVENT_MASK_VCP = 0x10,
+    VP_OPTION_ID_PCM_TXRX_CNTRL          = 0x11,
+    VP_DEVICE_OPTION_ID_PULSE2           = 0x12,
+    VP_OPTION_ID_LINE_IO_CFG             = 0x13,
+    VP_DEVICE_OPTION_ID_DEV_IO_CFG       = 0x14,
+    VP_OPTION_ID_DTMF_SPEC               = 0x15,
+    VP_DEVICE_OPTION_ID_PARK_MODE        = 0x16,
+    VP_OPTION_ID_DCFEED_SLOPE            = 0x17,
+    VP_OPTION_ID_SWITCHER_CTRL           = 0x18,
+    VP_OPTION_ID_HOOK_DETECT_MODE        = 0x19,
+    VP_OPTION_ID_AUTO_LOOP_COND          = 0x1A,
+
+    /* New option values may be added in this gap in the future. */
+    VP_OPTION_ID_PULSE                   = 0x24,
+    VP_OPTION_ID_DEBUG_SELECT            = 0x25,
+    VP_OPTION_ID_ABS_GAIN                = 0x26,
+    VP_DEVICE_OPTION_ID_PCM_SIG_CTL      = 0x27,
+    VP_OPTION_ID_LINESTATE_CTL_MODE      = 0x28,
+
+    VP_NUM_OPTION_IDS
+} VpOptionIdType;
+
+/** Parameters for dial pulse, flash, and on-hook */
+typedef struct {
+    uint16 breakMin;        /**< Minimum pulse break time (in 125uS) */
+    uint16 breakMax;        /**< Maximum pulse break time (in 125uS) */
+    uint16 makeMin;         /**< Minimum pulse make time (in 125uS) */
+    uint16 makeMax;         /**< Maximum pulse make time (in 125uS) */
+    uint16 interDigitMin;   /**< Minimum pulse interdigit time (in 125uS) */
+    uint16 flashMin;        /**< Minimum flash break time (in 125uS) */
+    uint16 flashMax;        /**< Maximum flash break time (in 125uS) */
+#ifdef EXTENDED_FLASH_HOOK
+    uint16 onHookMin;       /**< Minimum on-hook time (in 125uS) */
+#endif
+} VpOptionPulseType;
+
+typedef struct {
+    uint16 breakMin;        /**< Minimum pulse break time (in 125uS) */
+    uint16 breakMax;        /**< Maximum pulse break time (in 125uS) */
+    uint16 makeMin;         /**< Minimum pulse make time (in 125uS) */
+    uint16 makeMax;         /**< Maximum pulse make time (in 125uS) */
+    uint16 interDigitMin;   /**< Minimum pulse interdigit time (in 125uS) */
+    uint16 flashMin;        /**< Minimum flash break time (in 125uS) */
+    uint16 flashMax;        /**< Maximum flash break time (in 125uS) */
+    uint16 onHookMin;       /**< Minimum on-hook time (in 125uS) */
+    uint16 offHookMin;      /**< Minimum off-hook time (in 125uS) */
+} VpOptionLinePulseType;
+
+/** Method for line control when critical faults are detected */
+typedef struct {
+    /**< The line is set to disconnect when the specified fault is active and
+     * the "En" bit is set TRUE
+     */
+    bool acFltDiscEn;           /**< AC fault detected */
+    bool dcFltDiscEn;           /**< DC fault detected */
+    bool thermFltDiscEn;        /**< Thermal fault detected */
+} VpOptionCriticalFltType;
+
+/** Method for zero-cross control */
+typedef enum {
+    VP_OPTION_ZC_M4B  = 0, /**< Zero-Cross On - Make before break */
+    VP_OPTION_ZC_B4M  = 1, /**< Zero-Cross On - Break before make */
+    VP_OPTION_ZC_NONE = 2, /**< Turn Zero-Cross control off */
+    VP_OPTION_ZC_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_OPTION_ZC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpOptionZeroCrossType;
+
+/** Dial Pulse decode enable/disable */
+typedef enum {
+    VP_OPTION_PULSE_DECODE_OFF      = 0, /**< Disable Pulse Decode */
+    VP_OPTION_PULSE_DECODE_ON       = 1, /**< Enable Pulse Decode */
+    VP_OPTION_PULSE_DECODE_BRIDGING = 2, /**< Enable Pulse Decode (With Bridging) */
+    VP_OPTION_PULSE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPulseModeType;
+
+/** Transmit/Receive Timeslot setting (timeslot and control) */
+typedef struct {
+    uint8 tx;   /**< 8-bit TX timeslot */
+    uint8 rx;   /**< 8-bit RX timeslot */
+} VpOptionTimeslotType;
+
+typedef enum {
+    VP_OPTION_ALAW     = 0, /**< Select G.711 A-Law PCM encoding */
+    VP_OPTION_MLAW     = 1, /**< Select G.711 Mu-Law PCM encoding */
+    VP_OPTION_LINEAR   = 2, /**< Select Linear PCM encoding */
+    VP_OPTION_WIDEBAND = 3, /**< Select Wideband PCM encoding */
+    VP_NUM_OPTION_CODEC_TYPE_IDS,
+    VP_OPTION_CODEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionCodecType;
+
+/** PCM Highway Selection (B valid on select devices only) */
+typedef enum {
+    VP_OPTION_HWY_A          = 0, /**< Select the 'A' PCM Highway */
+    VP_OPTION_HWY_B          = 1, /**< Select the 'B' PCM Highway */
+    VP_OPTION_HWY_TX_A_RX_B  = 2, /**< Transmit on Highway A, receive on B */
+    VP_OPTION_HWY_TX_B_RX_A  = 3, /**< Transmit on Highway A, receive on A */
+    VP_OPTION_HWY_TX_AB_RX_A = 4, /**< Transmit on Highway A and B, receive on A */
+    VP_OPTION_HWY_TX_AB_RX_B = 5, /**< Transmit on Highway A and B, receive on B */
+    VP_OPTION_HWY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPcmHwyType;
+
+/** Loopback option selection */
+typedef enum {
+    VP_OPTION_LB_OFF      = 0, /**< All loopbacks off */
+
+    /* Following loopback options are supported for CSLAC and VCP only */
+    VP_OPTION_LB_TIMESLOT = 1, /**< Perform a timeslot loopback */
+    VP_OPTION_LB_DIGITAL  = 2, /**< Perform a full-digital loopback */
+    VP_OPTION_LB_CHANNELS = 3, /**< Connects FXO to FXS line on same device */
+
+    VP_NUM_LB_OPTIONS,
+    VP_OPTION_LB_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionLoopbackType;
+
+/** Active Line State battery supply selection */
+typedef enum {
+    VP_OPTION_BAT_AUTO  = 0, /**< Automatic Batery selection */
+    VP_OPTION_BAT_HIGH  = 1, /**< Use High Batery */
+    VP_OPTION_BAT_LOW   = 2, /**< Use Low Batery */
+    VP_OPTION_BAT_BOOST = 3, /**< Include Positive Batery */
+    VP_NUM_OPTION_BAT_IDS,
+    VP_OPTION_BAT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionBatType;
+
+/** Active Line State battery supply selection */
+typedef struct {
+    bool battRev;       /**< Smooth/Abrupt Battery Reversal (TRUE = abrupt) */
+
+    VpOptionBatType bat;    /**< Battery selection for Active line state */
+} VpOptionLineStateType;
+
+/** Ring control option */
+typedef enum {
+
+    /* FXS */
+    VP_LINE_STANDBY         = 0x00, /**< Low power line feed state */
+    VP_LINE_TIP_OPEN        = 0x01, /**< Tip open circuit state */
+    VP_LINE_ACTIVE          = 0x02, /**< Line Feed w/out VF */
+    VP_LINE_ACTIVE_POLREV   = 0x03, /**< Polarity Reversal Line Feed w/out VF */
+    VP_LINE_TALK            = 0x04, /**< Normal off-hook Active State; Voice Enabled */
+    VP_LINE_TALK_POLREV     = 0x05, /**< Normal Active with reverse polarity; Voice Enabled */
+    VP_LINE_OHT             = 0x06, /**< On-Hook tranmission state */
+    VP_LINE_OHT_POLREV      = 0x07, /**< Polarity Reversal On-Hook tranmission state */
+    VP_LINE_DISCONNECT      = 0x08, /**< Denial of service */
+    VP_LINE_RINGING         = 0x09, /**< Ringing state */
+    VP_LINE_RINGING_POLREV  = 0x0A, /**< Ringing w/Polarity Reversal */
+    VP_LINE_STANDBY_POLREV  = 0x10, /**< Low power polrev line feed state */
+    VP_LINE_PARK            = 0x11, /**< Park mode */
+    VP_LINE_RING_OPEN       = 0x12, /**< Ring open */
+    VP_LINE_HOWLER          = 0x13, /**< Howler */
+    VP_LINE_TESTING         = 0x14, /**< Testing */
+    VP_LINE_DISABLED        = 0x15, /**< Disabled */
+    VP_LINE_NULLFEED        = 0x16, /**< Null-feed */
+    VP_LINE_HOWLER_PCM      = 0x17, /**< Howler with PCM highway enabled */
+
+    /* FXO */
+    VP_LINE_FXO_OHT,        /**< FXO Line providing Loop Open w/VF */
+    VP_LINE_FXO_LOOP_OPEN,  /**< FXO Line providing Loop Open w/out VF */
+    VP_LINE_FXO_LOOP_CLOSE, /**< FXO Line providing Loop Close w/out VF */
+    VP_LINE_FXO_TALK,       /**< FXO Line providing Loop Close w/VF */
+    VP_LINE_FXO_RING_GND,   /**< FXO Line providing Ring Ground (GS only)*/
+
+    VP_NUM_LINE_STATES,
+    VP_LINE_STATE_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_LINE_STATE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLineStateType;
+
+typedef struct {
+    VpOptionZeroCrossType zeroCross;    /**< LCAS zero cross control */
+
+    uint16 ringExitDbncDur; /**< Ringing Exit Debounce Duration; Used during end
+                             * of ON periods of ringing cadences; 125uS
+                             * resolution
+                             */
+
+    VpLineStateType ringTripExitSt; /**< State to automatically switch to upon
+                                     * ring trip
+                                     */
+}  VpOptionRingControlType;
+
+/** DTMF detection option */
+typedef enum {
+    VP_OPTION_DTMF_DECODE_OFF = 0, /**< Disable DTMF Digit Decode */
+    VP_OPTION_DTMF_DECODE_ON  = 1, /**< Enable DTMF Digit  Decode */
+    VP_OPTION_DTMF_GET_STATUS = 2, /**< Do not change anything; Just get the DTMF status  */
+    VP_NUM_OPTION_DTMF_IDS,
+    VP_OPTION_DTMF_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionDtmfModeControlType;
+
+/* Device I/O Option related definitions */
+typedef enum {
+    VP_IO_INPUT_PIN  = 0, /* Configure GPIO pin as input pin */
+    VP_IO_OUTPUT_PIN = 1, /* Configure GPIO pin as output pin */
+    VP_IO_DIR_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDeviceIoDirectionType;
+
+typedef enum {
+    VP_OUTPUT_DRIVEN_PIN = 0, /* Configure as TTL/CMOS output pin */
+    VP_OUTPUT_OPEN_PIN   = 1, /* Configure as open collector/drain output pin */
+    VP_OUTPUT_TYPE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDeviceOutputPinType;
+
+typedef struct {
+    uint32 directionPins_31_0;      /* Device specific IO pin direction
+                                     * (Pins 0 - 31) */
+    uint32 directionPins_63_32;     /* Device specific IO pin direction
+                                     * (Pins 32 - 63) */
+    uint32 outputTypePins_31_0;     /* Output pin type (Pins 0 - 31) */
+    uint32 outputTypePins_63_32;    /* Output pin type (Pins 32 - 63) */
+} VpOptionDeviceIoType;
+
+/* Definition for line I/O config option */
+typedef struct {
+    uint8 direction;
+    uint8 outputType;
+} VpOptionLineIoConfigType;
+
+/* Definition for device I/O config option */
+typedef struct {
+    VpOptionLineIoConfigType lineIoConfig[VP_MAX_LINES_PER_DEVICE];
+} VpOptionDeviceIoConfigType;
+
+typedef enum {
+    VP_OPTION_PCM_BOTH      = 0, /* Enable both PCM transmit and receive paths */
+    VP_OPTION_PCM_RX_ONLY   = 1, /* Enable PCM receive path only */
+    VP_OPTION_PCM_TX_ONLY   = 2, /* Enable PCM transmit path only */
+    VP_OPTION_PCM_ALWAYS_ON = 3, /* Prevents disabling of PCM path */
+    VP_PCM_TXRX_CNTRL_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_PCM_TXRX_CNTRL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPcmTxRxCntrlType;
+
+/** Direction Specification */
+typedef enum {
+    VP_DIRECTION_DS,
+    VP_DIRECTION_US,
+    VP_DIRECTION_INVALID,   /**< Used by the API to determine if the direction
+                             * field is valid */
+    VP_DIRECTION_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDirectionType;
+
+#define VP_LINE_FLAG_BYTES ((VP_MAX_LINES_PER_DEVICE + 7) / 8)
+
+/** DTMF detection option control */
+typedef struct {
+    VpOptionDtmfModeControlType dtmfControlMode; /**< DTMF detection
+                                                  * Enable/Disable */
+    VpDirectionType direction;                  /**< Detection direction */
+    uint32 dtmfDetectionSetting;                /**< Indicates the DTMF
+                                                 *   detection setting for first
+                                                 *    32 lines */
+    uint8 dtmfResourcesRemaining;               /**< DTMF decoder resources
+                                                 *   remaining */
+    uint8 dtmfDetectionEnabled[VP_LINE_FLAG_BYTES];
+                                                /**< DTMF detection setting for
+                                                 *   lines 7-0, 15-8, etc. */
+} VpOptionDtmfModeType;
+
+/** Regional DTMF Specs */
+typedef enum {
+    VP_OPTION_DTMF_SPEC_ATT  = 0, /* Q.24 AT&T */
+    VP_OPTION_DTMF_SPEC_NTT  = 1, /* Q.24 NTT */
+    VP_OPTION_DTMF_SPEC_AUS  = 2, /* Q.24 Australian */
+    VP_OPTION_DTMF_SPEC_BRZL = 3, /* Q.24 Brazilian */
+    VP_OPTION_DTMF_SPEC_ETSI = 4, /* ETSI ES 201 235-3 v1.3.1 */
+    VP_OPTION_DTMF_SPEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionDtmfSpecType;
+
+/**< The following types are for Park Mode options */
+typedef struct {
+    uint16 discTime;    /**< Specified in 500ms increments, up to 8 seconds */
+    uint16 standbyTime; /**< Specified in 100ms increments, up to 8 seconds */
+} VpOptionParkModeType;
+
+/** Hook detection modes  */
+typedef enum {
+    VP_OPTION_HOOKDET_NORMAL         = 0,  /* normal hook detection behavior */
+    VP_OPTION_HOOKDET_DISC_IS_ONHOOK = 1,  /* in the VP_LINE_DISCONNECT or VP_LINE_DISABLED
+                                              state, the hook status is always considered
+                                              to be on-hook */
+    VP_OPTION_HOOKDET_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionHookDetectModeType;
+
+/* Option value struct for VP_OPTION_ID_AUTO_LOOP_COND: */
+typedef enum {
+    VP_LOOP_COND_NONE  = 0x0000,    /* feature disabled */
+    VP_LOOP_COND_RLOOP = 0x0001,    /* read loop resistance */
+    VP_LOOP_COND_ILG   = 0x0002,    /* read longitudinal (common mode) current */
+    VP_LOOP_COND_IMT   = 0x0004,    /* read metallic (differential) current */
+    VP_LOOP_COND_VSAB  = 0x0008,    /* read metallic (differential) voltage */
+    VP_LOOP_COND_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopCondSelectType;
+
+typedef struct {
+    uint16 select;  /* bitmask (multiple VpLoopCondSelectType values can be ORed
+                       together */
+    uint16 delay;   /* amount of time (in ms) after HOOK_OFF before
+                       measurement(s) */
+} VpOptionAutoLoopCondType;
+
+/* Definition for Absolute Level option */
+typedef struct {
+    int16 gain_AToD;
+    int16 gain_DToA;
+} VpOptionAbsGainType;
+
+#define VP_OPTION_ABS_GAIN_QUIET        (-32767)
+#define VP_OPTION_ABS_GAIN_NO_CHANGE    (+32767)
+#define VP_ABS_GAIN_UNKNOWN             (VP_OPTION_ABS_GAIN_NO_CHANGE - 1)
+
+/* Option value struct for VP_DEVICE_OPTION_ID_PCM_SIG_CTL: */
+typedef struct {
+    bool enable;
+    uint8 ctlTimeslot;
+    uint8 sigTimeslot;
+} VpOptionPcmSigCtlType;
+
+/* Option value struct for VP_OPTION_ID_LINESTATE_CTL_MODE: */
+typedef enum {
+    VP_OPTION_LINESTATE_CTL_NORMAL     = 0x0000,
+    VP_OPTION_LINESTATE_CTL_PCM        = 0x0080
+} VpOptionLinestateCtlModeType;
+
+/* The following struct can be passed to VpGetResults() if the option ID is not
+   known at compile time, to ensure that the buffer is large enough regardless
+   of the option type. */
+typedef union {
+    VpOptionPulseType pulse;                       /* VP_DEVICE_OPTION_ID_PULSE        */
+                                                   /* VP_DEVICE_OPTION_ID_PULSE2       */
+    VpOptionCriticalFltType criticalFlt;           /* VP_DEVICE_OPTION_ID_CRITICAL_FLT */
+    VpOptionZeroCrossType zeroCross;               /* VP_OPTION_ID_ZERO_CROSS          */
+    uint16 ramp2stby;                              /* VP_DEVICE_OPTION_ID_RAMP2STBY    */
+    VpOptionPulseModeType pulseMode;               /* VP_OPTION_ID_PULSE_MODE          */
+    VpOptionTimeslotType timeslot;                 /* VP_OPTION_ID_TIMESLOT            */
+    VpOptionCodecType codec;                       /* VP_OPTION_ID_CODEC               */
+    VpOptionPcmHwyType pcmHwy;                     /* VP_OPTION_ID_PCM_HWY             */
+    VpOptionLoopbackType loopback;                 /* VP_OPTION_ID_LOOPBACK            */
+    VpOptionLineStateType lineState;               /* VP_OPTION_ID_LINE_STATE          */
+    VpOptionEventMaskType eventMask;               /* VP_OPTION_ID_EVENT_MASK          */
+    VpOptionRingControlType ringControl;           /* VP_OPTION_ID_RING_CNTRL          */
+    VpOptionDtmfModeType dtmfMode;                 /* VP_OPTION_ID_DTMF_MODE           */
+    VpOptionDeviceIoType deviceIo;                 /* VP_DEVICE_OPTION_ID_DEVICE_IO    */
+    VpOptionPcmTxRxCntrlType pcmTxRxCntrl;         /* VP_OPTION_ID_PCM_TXRX_CNTRL      */
+    VpOptionDeviceIoConfigType deviceIoConfig;     /* VP_DEVICE_OPTION_ID_DEV_IO_CFG   */
+    VpOptionLineIoConfigType lineIoConfig;         /* VP_OPTION_ID_LINE_IO_CFG         */
+    VpOptionDtmfSpecType dtmfSpec;                 /* VP_OPTION_ID_DTMF_SPEC           */
+    VpOptionParkModeType parkMode;                 /* VP_DEVICE_OPTION_ID_PARK_MODE    */
+    VpOptionLinePulseType linePulse;               /* VP_OPTION_ID_PULSE               */
+    uint16 dcFeedSlope;                            /* VP_OPTION_ID_DCFEED_SLOPE        */
+    bool switcherCtrl;                             /* VP_OPTION_ID_SWITCHER_CTRL       */
+    uint32 debugSelect;                            /* VP_OPTION_ID_DEBUG_SELECT        */
+    VpOptionAbsGainType absGain;                   /* VP_OPTION_ID_ABS_GAIN            */
+    VpOptionHookDetectModeType hookDetectMode;     /* VP_OPTION_ID_HOOK_DETECT_MODE    */
+    VpOptionPcmSigCtlType pcmSigCtl;               /* VP_DEVICE_OPTION_ID_PCM_SIG_CTL  */
+    VpOptionLinestateCtlModeType linestateCtlMode; /* VP_OPTION_ID_LINESTATE_CTL_MODE  */
+    VpOptionAutoLoopCondType autoLoopCond;         /* VP_OPTION_ID_AUTO_LOOP_COND      */
+} VpOptionValueType;
+
+#endif /* VP_API_OPTION */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_test.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_test.h
new file mode 100755
index 0000000..11d5bc7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_test.h
@@ -0,0 +1,948 @@
+/** \file vp_api_test.h
+ * file vp_api_test.h
+ *
+ * This file contains declaration associated with VP-API Test features.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 7301 $
+ * $LastChangedDate: 2010-06-08 14:43:02 -0500 (Tue, 08 Jun 2010) $
+ */
+
+#ifndef VP_API_TEST_H
+#define VP_API_TEST_H
+
+#include "vp_api_types.h"
+#include "vp_api_option.h"
+#include "vp_api_event.h"   /* For VpDigitType */
+
+#define VP_TEST_NOT_MEASURED            0x8000    /* a value of -1 to indicate not measured */
+                                        /* chosen because it is an impermissible value in those tests where used */
+
+/** Tests supported by VpTestLine function */
+typedef enum
+{
+    VP_TEST_ID_PREPARE        = 0x00, /* Prepare for a test sequence */
+    VP_TEST_ID_CONCLUDE       = 0x01, /* Conclude a test sequence */
+    VP_TEST_ID_SET_SENSE_GAIN = 0x02, /* Set ILG and IMT gains high or low */
+    VP_TEST_ID_OPEN_VDC       = 0x03, /* Measure open DC voltage */
+    VP_TEST_ID_OPEN_VAC       = 0x04, /* Measure open AC voltage */
+    VP_TEST_ID_DIFF_VAC       = 0x05, /* Measure differential AC voltage */
+    VP_TEST_ID_DC_RLOOP       = 0x06, /* Measure DC loop resistance */
+    VP_TEST_ID_AC_RLOOP       = 0x07, /* Measure AC loop impedance */
+    VP_TEST_ID_NULL_IGND      = 0x08, /* Null ground current */
+    VP_TEST_ID_3ELE_RES       = 0x09, /* Measure 3-element insulation resistance */
+    VP_TEST_ID_3ELE_CAP       = 0x0A, /* Measure 3-element capacitance */
+    VP_TEST_ID_IDC            = 0x0B, /* Measure DC currents */
+    VP_TEST_ID_IAC            = 0x0C, /* Measure AC currents */
+    VP_TEST_ID_KEYPAD         = 0x0D, /* Keypad DTMF and Pulse dial test */
+    VP_TEST_ID_NOISE          = 0x0E, /* Measure Active or Passive Noise 3, 3.4 & 15KhZ */
+    VP_TEST_ID_SNR_QDIST      = 0x0F, /* Measure SNR and quantization distortion */
+    VP_TEST_ID_ARB_1TONE      = 0x10, /* Measure arbitrary single tone */
+    VP_TEST_ID_TONE_GEN       = 0x11, /* Generate a single/dual/quad-tone */
+    VP_TEST_ID_DIALTONE       = 0x12, /* Detect and measure dial tone (Inward test) */
+    VP_TEST_ID_HYBRID_LOSS    = 0x13, /* Measure trans-hybrid loss */
+    VP_TEST_ID_ALT_REN        = 0x14, /* Alternative method used to measure REN */
+    VP_TEST_ID_HOOK_STATUS    = 0x15, /* Check Hook Status (while in test mode) */
+    VP_TEST_ID_PCM_COLLECT    = 0x16, /* Collect PCM samples */
+    VP_TEST_ID_AC_RLOOP_PHASE = 0x17, /* Rloop with Phase information */
+    VP_TEST_ID_SET_BATTERIES  = 0x18, /* Select batteries for line testing */
+    VP_TEST_ID_MONITOR_IV     = 0x19, /* Non-Intrusive Monitoring Test */
+    VP_TEST_ID_UNBAL_TONE     = 0x1A, /* Generates an unbalanced tracing tone */
+    VP_TEST_ID_3ELE_RES_VMID  = 0x1B, /* Measure 3-element insulation resistance with a specified vMid */
+    VP_TEST_ID_AC_TRANS       = 0x1C, /* Measures digital-digital transmission characteristics */
+    VP_TEST_ID_GEN_TEST       = 0x1D, /* Multi-functional primitive */
+    VP_TEST_ID_SLOPE_REN      = 0x1E, /* REN test with a ramp instead of step */
+    /* Test IDs above this line are supported by one or more VCP devices.
+       Their values must not change.  More VCP tests might be added above this
+       line in the future. */
+
+    VP_TEST_ID_RSVD_MIN       = 0x23, /* Custom VCP tests (not currently used) */
+    VP_TEST_ID_RSVD_MAX       = 0x23,
+
+    /* The values of the constants below this line can change from time. */
+
+    VP_TEST_ID_3ELE_RES_HG,     /* Alternative 3-element resistance high gain */
+    VP_TEST_ID_3ELE_RES_LG,     /* Alternative 3-element resistance low gain */
+    VP_TEST_ID_3ELE_CAP_CSLAC,  /* CSLAC 3-element capacitance test */
+    VP_TEST_ID_MSOCKET_TYPE2,   /* Master Socket test for UK termination */
+    VP_TEST_ID_XCONNECT,        /* Cross Connect detection test */
+    VP_TEST_ID_LOOP_CONDITIONS, /* Measure current loop conditions */
+    VP_TEST_ID_LOOPBACK,        /* Setup loopback conditions */
+    VP_TEST_ID_LINE_IMPD,       /* Measure impedance at a frequency */
+    VP_TEST_ID_RING_TRIP,       /* Test ability to detect ring trip */
+    VP_TEST_ID_LOOP_DETECT,     /* Test ability to source current and detect
+                                 * off-hook */
+    VP_TEST_ID_CALIBRATE,       /* Perform line calibration */
+    VP_TEST_ID_USE_LINE_CAL,    /* Copy dev cal factors from lineObj to devObj */
+    VP_TEST_ID_OPEN_VXC,        /* Measure both DC and AC voltages */
+
+    VP_TEST_ID_GR909_HEMF,      /* Hazardous Potential Voltage Test for AC/DC
+                                 * Tip and Ring */
+    VP_TEST_ID_GR909_EMF,       /* FEMF test for AC/DC Tip and Ring */
+    VP_TEST_ID_GR909_RES_FLT,   /* Resistive Faults (T/R, T-Gnd, R-Gnd) */
+    VP_TEST_ID_GR909_OFF_HOOK,  /* Receiver Off-Hook */
+    VP_TEST_ID_GR909_RINGERS,   /* REN per FCC part 68 (1REN = 7Kohm) */
+    VP_TEST_ID_GR909_ALL,       /* Run all GR909 tests */
+    VP_TEST_ID_DELAY,           /* Implements non-blocking delay */
+    VP_TEST_ID_RAMP_INIT,       /* Implements a ramp to voltage test init */
+    VP_TEST_ID_RAMP,            /* Implements a ramp to voltage test */
+    VP_TEST_ID_FLT_DSCRM,       /* Implements the Fault discrimination test (880 890 only)*/
+    VP_TEST_ID_PREPARE_EXT,     /* Prepare for a test sequence without modifying the low power state  */
+
+    VP_TEST_ID_SET_SENSE_GAIN_792, /* Set Low/Normal/High sense gain for VCP792.
+                                    * The API translates this to the value of
+                                    * VP_TEST_ID_SET_SENSE_GAIN before sending
+                                    * it down to the VCP. */
+
+    VP_NUM_TEST_IDS,
+
+    VP_TEST_ID_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestIdType;
+
+/**< The following are test line error codes */
+typedef enum {
+    VP_TEST_STATUS_SUCCESS            = 0,  /**< Test Completed Successfully */
+    VP_TEST_STATUS_LINE_NOT_READY     = 1,  /**< Line Not in Test-mode (no VP_TEST_ID_PREPARE) */
+    VP_TEST_STATUS_RESOURCE_NA        = 2,  /**< Line Not available for Test (already in Test) */
+    VP_TEST_STATUS_TESTING            = 3,  /**< Test underway - not aborted */
+    VP_TEST_STATUS_VOUT_OOR           = 4,  /**< Voltage Out-of-range */
+    VP_TEST_STATUS_VAB_OOR            = 5,  /**< A-B Voltage is out-of-range */
+    VP_TEST_STATUS_ILG_OOR            = 6,  /**< Measured IILG is out-of-range */
+    VP_TEST_STATUS_VCM_OOR            = 7,  /**< Measured VCM is out-of-range */
+    VP_TEST_STATUS_IAHL_OOR           = 8,  /**< Measured current or voltage is out-of-range in Res or Cap test */
+    VP_TEST_STATUS_IBHL_OOR           = 9,  /**< " " */
+    VP_TEST_STATUS_IAHH_OOR           = 10, /**< " " */
+    VP_TEST_STATUS_IBHH_OOR           = 11, /**< " " */
+    VP_TEST_STATUS_VABHL_OOR          = 12, /**< " " */
+    VP_TEST_STATUS_IALL_OOR           = 13, /**< " " */
+    VP_TEST_STATUS_IBLL_OOR           = 14, /**< " " */
+    VP_TEST_STATUS_IA_OOR             = 15, /**< Measured Current is out-of-range */
+    VP_TEST_STATUS_IB_OOR             = 16, /**< " " */
+    VP_TEST_STATUS_IMT_OOR            = 17, /**< Measured IMT is out-of-range */
+    VP_TEST_STATUS_IMT_DC_OOR         = 18, /**< " " */
+    VP_TEST_STATUS_15KHZ_ERROR        = 19, /**< More than 1 15Khz Test requested */
+    VP_TEST_STATUS_TIMEOUT            = 20, /**< Failed to complete in specified time */
+    VP_TEST_STATUS_ABORTED            = 21, /**< Test aborted */
+    VP_TEST_STATUS_INTERNAL_ERROR     = 22, /**< Internal error (SLAC integrator) */
+    VP_TEST_STATUS_NO_CONVERGENCE     = 23, /**< NULL_IGND test failed to converge */
+    VP_TEST_STATUS_TEST_NOT_SUPPORTED = 24, /**< Requested test is not supported (due to device configuration) */
+    VP_TEST_STATUS_VTIPBIAS_OOR       = 25, /**< Tip Bias Voltage Out of Range */
+    VP_TEST_STATUS_VRINGBIAS_OOR      = 26, /**< Ring Bias Voltage Out of Range */
+    VP_TEST_STATUS_VMID_OOR           = 27, /**< User specified vMid voltage is out of range */
+    VP_TEST_STATUS_GAIN_OOR           = 28, /**< User specified gain is out of range */
+    VP_TEST_STATUS_VA_OOR             = 29, /**< Measured Voltage is out-of-range */
+    VP_TEST_STATUS_VB_OOR             = 30, /**< " " */
+    VP_TEST_STATUS_IMTOFFSET_OOR      = 31, 
+    VP_TEST_STATUS_BUF_OVERFLOW       = 32, /* test would exceed the buffer storage available */
+    VP_TEST_STATUS_NUM_TYPES,               /**< NOT an ERROR, Just used for coding purposes */
+    VP_TEST_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestStatusType;
+
+typedef struct {
+    uint16 gMvErr;
+    int16 gMvOff;
+    uint16 gLvErr;
+    int16 gLvOff;
+    uint16 gMiErr;
+    int16 gMiOff;
+    uint16 gLiErr;
+    int16 gLiOff;
+    uint16 sAvErr;
+    int16 sAvOff;
+    uint16 sAiErr;
+    int16 sAiOff;
+    uint16 sBvErr;
+    int16 sBvOff;
+    uint16 sBiErr;
+    int16 sBiOff;
+
+    uint16 sABMvErr;
+    int16 sABMvOff;
+    uint16 sABMiErr;
+    int16 sABMiOff;
+
+    uint16 sABLvErr;
+    int16 sABLvOff;
+    uint16 sABLiErr;
+    int16 sABLiOff;
+
+    uint16 sABMHiErr;
+    int16 sABMHiOff;
+    uint16 sABLHiErr;
+    int16 sABLHiOff;
+} VpTestCalibrationDataType;
+
+/* Definitions used for VP_TEST_ID_DELAY */
+typedef struct {
+    uint16 timerVal;    /* Value in 125uS steps */
+} VpTestTimerType;
+
+/* Definitions used for VP_TEST_ID_CONCLUDE */
+typedef struct {
+    bool abortTest;
+} VpTestConcludeType;
+
+/* Definitions used for VP_TEST_ID_SET_SENSE_GAIN */
+typedef enum {
+    VP_SENSE_GAIN_HIGH = 0,
+    VP_SENSE_GAIN_LOW  = 1,
+    VP_SENSE_GAIN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSenseGainType;
+
+typedef struct {
+    VpSenseGainType imt;
+    VpSenseGainType ilg;
+} VpTestSetSenseGainType;
+
+/* 792-specific definitions for VP_TEST_ID_SET_SENSE_GAIN_VP792 */
+typedef enum {
+    VP792_SENSE_GAIN_0dB_GAIN   = 0x0000, /* absolute gain = 1 */
+    VP792_SENSE_GAIN_28dB_GAIN  = 0x0010, /* absolute gain = 25 */
+    VP792_SENSE_GAIN_10dB_LOSS  = 0x0020, /* absolute gain = 1/3 */
+    VP792_SENSE_GAIN_RSVD       = 0x0030,
+    VP792_SENSE_GAIN_ENUM_SIZE  = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} Vp792SenseGainType;
+
+typedef struct {
+    Vp792SenseGainType senseGain;
+} VpTestSet792SenseGainType;
+
+/* Definitions used for VP_TEST_ID_SET_BATTERIES */
+typedef enum {
+    VP_BS_LOW  = 0,
+    VP_BS_HIGH = 1,
+    VP_BS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSetBatteriesType;
+
+typedef struct {
+    VpSetBatteriesType bs1;
+    VpSetBatteriesType bs0;
+} VpTestSetBatteriesType;
+
+/* Definitions used for VP_TEST_ID_OPEN_VDC, VP_TEST_ID_OPEN_VAC */
+typedef enum {
+    VP_TEST_RING     = 0,
+    VP_TEST_TIP      = 1,
+    VP_TEST_TIP_RING = 2,
+    VP_TEST_TIP_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestTipSelectType;
+
+typedef struct {
+    bool calMode;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestTipSelectType tip;
+} VpTestOpenVType;
+
+/* Definitions used for VP_TEST_ID_DIFF_VAC */
+typedef struct {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    int16 gvsaCal;
+    int16 gvsbCal;
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestDiffVacType;
+
+/* Definitions used for VP_TEST_IDC, VP_TEST_IAC */
+typedef struct {
+    bool calMode;
+    int16 vCm;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestIdcType;
+
+typedef struct {
+    int16 gimtCal;
+    int16 gilgCal;
+    int16 vCm;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestIacType;
+
+typedef struct {
+    int16 ia;
+    int16 ib;
+} VpTestResultVixType;
+
+/* Definitions used for VP_TEST_ID_DC_RLOOP */
+typedef struct {
+    bool calMode;
+    int16 iTestLevel;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestDcRLoopType;
+
+typedef struct {
+    int16 vab;
+    int16 ilg;
+    bool currentSaturation;
+} VpTestResultDcRlType;
+
+/* Definitions used for VP_TEST_ID_AC_RLOOP */
+typedef struct {
+    bool calMode;
+    uint16 freq;
+    int16 vTestLevel;
+    int16 vBias;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestTipSelectType tip; /* Used by VE880 only */
+} VpTestAcRLoopType;
+
+typedef struct {
+    int16 imt;
+    int16 ilg;
+    int16 vab;
+    int32 freq;
+} VpTestResultAcRlType;
+
+/* Definition used for VP_TEST_ID_AC_RLOOP_PHASE (in addition to VpTestAcRLoopType) */
+typedef struct {
+    int16 imt;
+    int16 ilg;
+    int16 phase;
+} VpTestResultAcRlPhaseType;
+
+/* Definitions used for VP_TEST_ID_LOOP_COND */
+typedef enum {
+    VP_LOOP_COND_TEST_VSAB  = 1,
+    VP_LOOP_COND_TEST_VSAG  = 2,
+    VP_LOOP_COND_TEST_VSBG  = 3,
+    VP_LOOP_COND_TEST_RLOOP = 4,
+    VP_LOOP_COND_TEST_ILG   = 5,
+    VP_LOOP_COND_TEST_IMT   = 6,
+    VP_LOOP_COND_TEST_BAT1  = 7,
+    VP_LOOP_COND_TEST_BAT2  = 8,
+    VP_LOOP_COND_TEST_BAT3  = 9,
+    VP_LOOP_COND_TEST_METER = 10,
+    VP_LOOP_COND_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopCondTestType;
+
+typedef struct {
+    bool calMode;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpLoopCondTestType loopCond; /* Indicates which condition to measure */
+} VpTestLoopCondType;
+
+typedef struct {
+    VpLoopCondTestType condition;
+    int16 data;
+    bool calibrated;
+    int16 limit;            /* Limit or target value */
+} VpTestResultLoopCondType;
+
+/* Definitions used for VP_TEST_ID_XCONNECT */
+typedef enum {
+    VP_XCONNECT_DISC_V    = 0,
+    VP_XCONNECT_12VVOC_I  = 1,
+    VP_XCONNECT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpXConnectType;
+
+typedef struct {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpXConnectType measReq; /* Indicates which measurement sequence to run */
+    bool isFeedPositive;    /* VP_XCONNECT_12VVOC_I feed sign depends on measured EMF */
+    uint8 phase;            /* Test phase number */
+} VpTestXConnectType;
+
+typedef struct {
+    VpXConnectType condition;
+    int16 data;
+} VpTestResultXConnectType;
+
+/* Definitions used for VP_TEST_ID_LOOPBACK */
+typedef enum {
+    VP_LOOPBACK_TEST_CODEC  = 1,
+    VP_LOOPBACK_TEST_ANALOG = 2,
+    VP_LOOPBACK_TEST_BFILTER = 3,
+    VP_LOOPBACK_TEST_TIMESLOT = 4,
+    VP_LOOPBACK_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopbackTestType;
+
+typedef struct {
+    uint16 waitTime;            /* Indicates how long before collecting samples */
+    uint16 loopbackTime;        /* Indicates Loopback duration in units of 125us */
+    VpLoopbackTestType loopback;/* Indicates which condition to setup */
+} VpTestLoopbackType;
+
+typedef struct {
+    VpLoopbackTestType  loopback; /* Indicates which condition was setup*/
+    void *pApplicationInfo;
+} VPTestResultLoopbackType;
+
+/* Definitions used for VP_TEST_LINE_IMPD */
+typedef struct {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    bool filterMode;
+    int16 vcm;              /* Common mode voltage for measurement */
+    int16 vDiff;            /* Differential voltage for measurement */
+    uint16 freq;
+    int16 amp;
+} VpTestLineImpdType;
+
+typedef struct {
+    bool iaOor;         /* If set IA out of range */
+    bool ibOor;         /* If set IB out of range */
+    uint16 iDiff;           /* RMS differential current */
+} VpTestResultLineImpdType;
+
+/**< Typedefs for Advanced Tests */
+/* Definitions used for VP_TEST_TONE_GEN */
+typedef struct {
+    uint16 duration;
+    uint16 freq1;
+    int16 amp1;
+    uint16 freq2;
+    int16 amp2;
+    uint16 freq3;
+    int16 amp3;
+    uint16 freq4;
+    int16 amp4;
+} VpTestToneGenType;
+
+/* Definitions used for VP_TEST_ALT_REN */
+typedef struct {
+    uint16 integrateTime;
+    int16 vDiff;
+} VpTestRenType;
+
+typedef struct {
+    int16 imt;
+    int16 imtDc;
+} VpTestResultRenType;
+
+/* Definitions used for VP_TEST_ID_SLOPE_REN */
+typedef enum {
+    VP_TEST_TYPE_UNDEFINED = 0,
+    VP_TEST_TYPE_AVG       = 1,
+    VP_TEST_TYPE_RMS       = 2,
+    VP_TEST_TYPE_DFT       = 3,
+    VP_TEST_TYPE_RAW       = 4,
+    VP_TEST_TYPE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestMathType;
+
+typedef enum {
+    VP_TEST_SPEED_UNDEFINED = 0,
+    VP_TEST_SPEED_LOW       = 1,
+    VP_TEST_SPEED_MED       = 2,
+    VP_TEST_SPEED_HIGH      = 3,
+    VP_TEST_SPEED_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestDcbwSpeedType;
+
+typedef struct {
+    uint16 slopeTime;
+    uint16 integrateTime;
+    uint16 settlingTime;
+    int16 vDiff;
+    VpTestMathType type;
+    VpTestDcbwSpeedType speed;
+} VpTestSRenType;
+
+typedef struct {
+    int16 imtOffset;
+    int16 imt;
+    int16 imtDc;
+} VpTestResultSRenType;
+
+/* Definitions used for VP_TEST_ID_3ELE_RES*/
+typedef struct {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestResType;
+
+typedef struct {
+    int16 iahl;
+    int16 ibhl;
+    int16 iahh;
+    int16 ibhh;
+    int16 iall;
+    int16 ibll;
+    int16 vabhl;
+} VpTestResultResType;
+
+/* Definition used for VP_TEST_ID_3ELE_HG and LG */
+typedef struct {
+    int16 feedBias;
+    bool shiftZeroFeed;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTest3EleResAltResType;
+
+typedef struct {
+    bool highGain;
+    int16 vanf;
+    int16 vbnf;
+    int16 imnf;
+    int16 ilnf;
+    int16 varf;
+    int16 vbrf;
+    int16 imrf;
+    int16 ilrf;
+    int16 vazf;
+    int16 vbzf;
+    int16 imzf;
+    int16 ilzf;
+} VpTestResultAltResType;
+
+/* Definition used for VP_TEST_ID_MSOCKET_TYPE2 */
+typedef struct {
+    uint8 dummy;
+} VpTestMSocketType;
+
+typedef struct {
+    int16 vanf;
+    int16 vbnf;
+    int16 imnf;
+    int16 varf1;
+    int16 vbrf1;
+    int16 imrf1;
+    int16 varf2;
+    int16 vbrf2;
+    int16 imrf2;
+    int16 varf3;
+    int16 vbrf3;
+    int16 imrf3;
+} VpTestResultMSockType;
+
+/* Definition used for VP_TEST_ID_3ELE_CAP_CSLAC */
+typedef struct {
+    bool calMode;       /* Enable calibration */
+    uint16 testAmp;     /* Test signal amplitude (mV RMS) */
+    uint8 testFreq;     /* Test signal frequency [0,4], 0=2666.016Hz -> 4=280.151Hz */
+    int16 bias;         /* Signal generator bias (V) */
+} VpTest3EleCapAltResType;
+
+typedef struct {
+    bool accuracyFlag;
+    uint8 freq;
+    int16 va;
+    int16 vb;
+    int16 im;
+    int16 il;
+    int32 tipCapCal;
+    int32 ringCapCal;
+} VpTestResultAltCapType;
+
+/* Definition used for VP_TEST_ID_3ELE_RES_VMID */
+typedef struct {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    int16 vMid;
+} VpTestResVmidType;
+
+typedef struct {
+    int16 vdc;
+    int16 vac;
+} VpTestResultVxcType;
+
+/* Definitions used for VP_TEST_3ELE_CAP */
+typedef struct {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 freq;
+    int16 gimtCal;
+    int16 gilgCal;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestCapType;
+
+typedef struct {
+    int16 iahl;
+    int16 iahh;
+    int16 ibhh;
+    int16 iall;
+    int16 ibll;
+    int16 vabhl;
+} VpTestResultCapType;
+
+/* Definitions used for VP_TEST_NOISE */
+typedef enum {
+    VP_FILTER_NONE   = 0,
+    VP_FILTER_3KHZ   = 1,
+    VP_FILTER_CMSG   = 2,
+    VP_FILTER_15KHZ  = 3,
+    VP_FILTER_3_4KHZ = 4,
+    VP_FILTER_D      = 5,
+    VP_FILTER_PSOPH  = 6,
+    VP_NUM_TEST_FILTER_TYPES,
+    VP_FILTER_ENUM_RSVD    = FORCE_SIGNED_ENUM,
+    VP_FILTER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestFilterType;
+
+typedef struct {
+    uint16 integrateTime;
+    VpTestFilterType filter;
+    int16 amp;
+    bool useBuffer;
+} VpTestNoiseType;
+
+/* Definitions used for VP_TEST_HYBRID_LOSS */
+typedef struct {
+    uint16 integrateTime;
+    uint16 freq;
+    int16 amp;
+    bool useBuffer;
+} VpTestTransHybridLossType;
+
+/* Definitions used for VP_TEST_ID_NULL_IGND */
+typedef struct {
+    int16 vTestLevel;
+    int16 iTarget;
+    VpTestTipSelectType tip;
+    uint16 settlingTime;
+} VpTestNullIGndType;
+
+/* Definitions used for VP_TEST_KEYPAD */
+typedef enum {
+    VP_KEY_TEST_DTMF  = 0,
+    VP_KEY_TEST_PULSE = 1,
+    VP_KEY_TEST_BOTH  = 2,
+    VP_NUM_KEY_TEST_TYPES,
+    VP_KEY_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpKeyTestType;
+
+typedef struct {
+    VpKeyTestType kTest;
+    uint16 timeout;
+    uint16 freq;
+    int16 amp;
+    uint16 fftSize;
+    uint16 threshold;
+    VpOptionPulseType pulseOpt;
+    bool useBuffer;
+} VpTestKeypadType;
+
+typedef enum {
+    VP_KT_DTMF_DET   = 0,
+    VP_KT_DTMF_MES   = 1,
+    VP_KT_PULSE      = 2,
+    VP_KT_THRESH_DET = 3,
+    VP_NUM_KT_TYPES,
+    VP_KT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpKeyTestResultType;
+
+typedef struct {
+    VpKeyTestResultType kTestResult;
+    VpDigitType digit;
+    uint16 lowFreq;
+    uint16 lowAmp;
+    uint16 highFreq;
+    uint16 highAmp;
+    uint16 fftSize;
+    uint16 minBreak;
+    uint16 maxBreak;
+    uint16 aveBreak;
+    uint16 pulsePerSec;
+    bool hookFlashDet;
+    uint16 hookFlashDuration;
+    bool disconnectDet;
+} VpTestResultKeyType;
+
+/* Definitions used for VP_TEST_SNR_QDIST */
+typedef struct {
+    uint16 integrateTime;          /* Integration time in units of 125us */
+    int16 amp;
+    bool useBuffer;
+} VpTestSnrQDistorType;
+
+typedef struct {
+    uint16 vrmsNoise;
+    uint16 vrmsSignal;
+} VpTestResultSnrQDistorType;
+
+/* Definitions used for VP_TEST_ARB_1TONE */
+typedef struct {
+    uint16 timeout;
+    uint16 fftSize;
+    uint16 threshold;
+    bool useBuffer;
+} VpTestArb1ToneType;
+
+/* Definitions used for VP_TEST_DIALTONE */
+typedef struct {
+    bool inward;
+    uint16 timeout;
+    uint16 detectGran;
+    uint16 threshold;
+    uint16 fftSize;
+    uint16 duration;
+    bool useBuffer;
+} VpTestDialToneType;
+
+typedef struct {
+    uint16 rmsPwr;
+    uint16 highFreq;
+    uint16 highAmp;
+    uint16 secFreq;
+    uint16 secAmp;
+    uint16 thdFreq;
+    uint16 thdAmp;
+} VpTestResultToneType;
+
+/**< The following types are for GR909 tests */
+/* Definitions used for  */
+typedef struct {
+    bool testFail;
+    bool acFault;
+    bool dcFault;
+    uint16 acVolt;
+    int16 dcVolt;
+} VpTestResultGR909EmfType;
+
+/* Definitions used for VP_TEST_ID_GR909_RES_FLT */
+typedef struct {
+    bool testFail;
+    bool rtrFlt;
+    bool rtgFlt;
+    bool rrgFlt;
+    uint16 rtr;
+    uint16 rtg;
+    uint16 rrg;
+} VpTestResultGR909ResFltType;
+
+/* Definitions used for VP_TEST_ID_GR909_OFF_HOOK */
+typedef struct {
+    bool offHook;
+} VpTestResultGR909OffHookType;
+
+/* Definitions used for VP_TEST_ID_GR909_RINGERS */
+typedef struct {
+    bool testFailed;
+    bool renHigh;
+    bool renLow;
+    uint16 ren;
+} VpTestResultGR909RenType;
+
+/* Definitions used for VP_TEST_ID_GR909_ALL */
+typedef struct {
+    bool testFailed;
+    bool hvFailed;
+    bool emfFailed;
+    bool resFailed;
+    bool offHook;
+    bool ringersFailed;
+} VpTestResultGR909AllType;
+
+/* Definitions used for VP_TEST_ID_RAMP_INIT */
+typedef struct {
+    int16 dcVstart;
+    int16 dcVend;
+    int16 vRate;
+    int16 bias;
+    VpTestTipSelectType tip;
+} VpTestRampInitType;
+
+/* Definitions used for VP_TEST_ID_RAMP */
+typedef struct {
+    int16 dcVoltage;
+    int16 vRate;
+    int16 bias;
+    VpTestTipSelectType tip;
+} VpTestRampType;
+
+typedef struct {
+    int16 imt;
+    int16 vRate;
+} VpTestResultRampType;
+
+/* Definitions used for VP_TEST_ID_MONITOR_IV */
+typedef enum {
+    VP_TEST_TYPE_DC = 0,
+    VP_TEST_TYPE_AC = 1,
+    VP_TEST_TYPE_ACDC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpMonitorIvFilterType;
+
+typedef enum {
+    VP_TEST_MEAS_VA  = 0,
+    VP_TEST_MEAS_VB  = 1,
+    VP_TEST_MEAS_VAB = 2,
+    VP_TEST_MEAS_IMT = 3,
+    VP_TEST_MEAS_ILG = 4,
+    VP_TEST_MEAS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpMonitorIvTestMeasurementType;
+
+typedef struct {
+    bool calMode;
+    uint16 integrateTime;               /* Integration time in units of 125us */
+    uint16 settlingTime;                /* Filter settling time in units of 125us */
+    VpMonitorIvFilterType filterType;   /* Measurement Type (AC/DC) */
+    VpMonitorIvTestMeasurementType measurement; /* measurement source */
+} VpTestMonitorIvType;
+
+/* Definitions used for VP_TEST_ID_UNBAL_TONE */
+typedef struct {
+    uint16 freq;
+    int16 vTestlevel;
+    int16 vTipBias;
+    int16 vRingBias;
+    uint16 duration;
+    VpTestTipSelectType tip;
+} VpTestUnbalToneType;
+
+/* Definitions used for VP_TEST_ID_PCM_COLLECT */
+typedef struct {
+    uint16 sampleTime;
+} VpTestPcmCollectType;
+
+typedef struct {
+    uint16 resultsSize;
+    uint16 samples;
+    VpOptionCodecType codec;
+    uint16 reserved;
+    uint32 address;
+} VpTestResultPcmCollectType;
+
+/* Definitions used for VP_FLT_DSCRM */
+typedef struct {
+    int16 vtgFeed;
+    int16 vrgFeed;
+    int16 vtrFeed;
+    int16 vtrAC;
+    int16 vtoAC;
+    int16 vroAC;
+    int16 vtuBalAC;
+    int16 vruBalAC;
+    bool hookDet;
+    bool gnkDet;
+} VpTestResultFltDscrmType;
+
+/* Definitions for VP_TEST_ID_GEN_TEST */
+/* Generic Test Defines */
+typedef enum {
+    VP_TEST_FILTER_UNDEFINED = 0,
+    VP_TEST_FILTER_LPF       = 1,
+    VP_TEST_FILTER_HPF       = 2,
+    VP_TEST_FILTER_NONE      = 3,
+    VP_TEST_FILTER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenFilterType;
+
+typedef enum {
+    VP_TEST_DRIVE_UNDEFINED = 0,
+    VP_TEST_DRIVE_NONE      = 1,
+    VP_TEST_DRIVE_A         = 2,
+    VP_TEST_DRIVE_B         = 3,
+    VP_TEST_DRIVE_BOTH      = 4,
+    VP_TEST_DRIVE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenDriveType;
+
+typedef enum {
+    VP_TEST_SIGNAL_UNDEFINED = 0,
+    VP_TEST_SIGNAL_A         = 1,
+    VP_TEST_SIGNAL_B         = 2,
+    VP_TEST_SIGNAL_CM        = 3,
+    VP_TEST_SIGNAL_DIFF      = 4,
+    VP_TEST_SIGNAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenSignalType;
+
+typedef enum {
+    VP_TEST_MEAS_UNDEFINED     = 0,
+    VP_TEST_MEAS_LOW_GAIN      = 1,
+    VP_TEST_MEAS_NORM_GAIN     = 2,
+    VP_TEST_MEAS_HIGH_GAIN     = 3,
+    VP_TEST_MEAS_SKIP          = 4,
+    VP_TEST_MEAS_IMT_NORM_GAIN = 5,
+    VP_TEST_MEAS_IMT_HIGH_GAIN = 6,
+    VP_TEST_MEAS_VAB_LOW_GAIN  = 7,
+    VP_TEST_MEAS_VAB_NORM_GAIN = 8,
+    VP_TEST_MEAS_VAB_HIGH_GAIN = 9,
+    VP_TEST_MEAS_ILG_NORM_GAIN = 10,
+    VP_TEST_MEAS_ILG_HIGH_GAIN = 11,
+    VP_TEST_MEAS_GEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenGainType;
+
+typedef struct {
+    VpTestGenFilterType filter;
+    VpTestMathType type;
+    VpTestGenDriveType  driveMode;
+    VpTestGenSignalType  signalMode;
+    int16 vTestLevel;
+    uint16 freq;
+    int16 vTipBias;
+    int16 vRingBias;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestGenGainType iaMeas;
+    VpTestGenGainType vaMeas;
+    VpTestGenGainType ibMeas;
+    VpTestGenGainType vbMeas;
+} VpTestGenTestType;
+
+typedef struct
+{
+    int16 iaReal;
+    int16 iaImag;
+    int16 vaReal;
+    int16 vaImag;
+    int16 ibReal;
+    int16 ibImag;
+    int16 vbReal;
+    int16 vbImag;
+} VpTestResultGenTestType;
+
+/* Definitions for Test results */
+typedef union {
+    bool                          hstatus;
+    int16                         sVout;
+    uint16                        uVout;
+    int16                         vcm;
+    uint16                        vrms;
+    VpTestResultVxcType           vxc;
+    VpTestResultDcRlType          dcvab;
+    VpTestResultAcRlType          acimt;
+    VpTestResultAcRlPhaseType     acimtp;
+    VpTestResultVixType           vix;
+    VpTestResultResType           res;
+    VpTestResultAltResType        resAlt;
+    VpTestResultMSockType         mSock;
+    VpTestResultXConnectType      xConnect;
+    VpTestResultAltCapType        capAlt;
+    VpTestResultCapType           cap;
+    VpTestResultKeyType           keypad;
+    VpTestResultSnrQDistorType    snrqd;
+    VpTestResultToneType          tone;
+    VpTestResultRenType           ren;
+    VpTestResultLoopCondType      loopCond;
+    VPTestResultLoopbackType      loopback;
+
+    bool                          calFailed;
+    bool                          ringTripFail;
+    bool                          loopFnd;
+    bool                          loopBackTestFail;
+    VpTestResultLineImpdType      lineImpedance;
+    VpTestResultGR909EmfType      emf;
+    VpTestResultGR909ResFltType   resFault;
+    VpTestResultGR909OffHookType  offHookFault;
+    VpTestResultGR909RenType      ringers;
+    VpTestResultGR909AllType      gr909All;
+    VpTestResultRampType          ramp;
+    VpTestResultPcmCollectType    pcmCollect;
+    VpTestResultFltDscrmType      fltDscrm;
+    VpTestResultGenTestType       gen;
+    VpTestResultSRenType          sren;
+} VpTestResultsUnionType;
+
+typedef struct {
+    VpTestIdType testId;            /* Test identifier */
+    VpTestStatusType errorCode;     /* Error code if Test Failed */
+    VpTestResultsUnionType result;  /* Return Results Union */
+} VpTestResultType;
+
+/* The following enum is used for event associated with VpSelfTest() */
+typedef enum
+{
+    VP_STEST_SUCCESS = 0,
+    VP_STEST_FAIL    = 1,
+    VP_STEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSelfTestResultIdType;
+
+#endif /* VP_API_TEST_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_timer.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_timer.h
new file mode 100755
index 0000000..4982d5c
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_api_timer.h
@@ -0,0 +1,163 @@
+/** \file vp_api_timer.h
+ * vp_api_timer.h
+ *
+ * Header file for all timer typedefs used in API-II (internal).
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8481 $
+ * $LastChangedDate: 2011-04-07 09:43:23 -0500 (Thu, 07 Apr 2011) $
+ */
+
+#ifndef VP_API_TIMER_H
+#define VP_API_TIMER_H
+
+/* IMT average for Voltage to Frequency (FXO) smoothing */
+#define VP_IMT_AVG_LENGTH 2  /* FXO variable, but need this to compile */
+
+#define VP_ACTIVATE_TIMER       0x8000
+#define VP_TIMER_TIME_MASK      0x7FFF
+
+/*
+ * The timer types are generally evaluated in an incremental loop, so must use
+ * only sequential values.
+ */
+/**< Line Timer Definitions */
+
+/**< Debounce for known CID state changes */
+#define VP_LINE_CID_DEBOUNCE            0
+
+/**< Timer for DTMF generation in CID */
+#define VP_LINE_TIMER_CID_DTMF          (VP_LINE_CID_DEBOUNCE + 1)
+
+/**< The fault timer */
+#define VP_LINE_TIMER_FAULT             (VP_LINE_TIMER_CID_DTMF + 1)
+
+/**< Line Debounce specifically for Ring Exit */
+#define VP_LINE_RING_EXIT_DEBOUNCE      (VP_LINE_TIMER_FAULT + 1)
+
+/**< Hook Mask on Polarity Reversals */
+#define VP_LINE_POLREV_DEBOUNCE         (VP_LINE_RING_EXIT_DEBOUNCE + 1)
+
+/**< Line Debounce for Disconnect Recovery */
+#define VP_LINE_DISCONNECT_EXIT         (VP_LINE_POLREV_DEBOUNCE + 1)
+
+/**< Timer for Recovery from Tip-Open */
+#define VP_LINE_GND_START_TIMER         (VP_LINE_DISCONNECT_EXIT + 1)
+
+/**< Timer for CalLine operations */
+#define VP_LINE_CAL_LINE_TIMER          (VP_LINE_GND_START_TIMER + 1)
+
+/**< Timer to prevent phone "ping" */
+#define VP_LINE_PING_TIMER              (VP_LINE_CAL_LINE_TIMER + 1)
+
+/**< Offhook report delay when not pulse detecting */
+#define VP_LINE_OFFHOOK_DELAY           (VP_LINE_PING_TIMER + 1)
+
+/**< Timer used to disable switcher with low power termination type. */
+#define VP_LINE_TRACKER_DISABLE         (VP_LINE_OFFHOOK_DELAY + 1)
+
+/**< Timer for Cal operations */
+#define VP_LINE_CAL_TIMER               (VP_LINE_TRACKER_DISABLE + 1)
+
+/**< Timer to use a GPIO as a slow clock output */
+#define VP_LINE_GPIO_CLKOUT_TIMER       (VP_LINE_CAL_TIMER + 1)
+
+/**< Timer for the internal test termination */
+#define VP_LINE_INTERNAL_TESTTERM_TIMER (VP_LINE_GPIO_CLKOUT_TIMER + 1)
+
+/**< Timer to restore speedup recovery */
+#define VP_LINE_SPEEDUP_RECOVERY_TIMER  (VP_LINE_INTERNAL_TESTTERM_TIMER + 1)
+
+/**< Place holder to indicate number of line timers */
+#define VP_LINE_TIMER_LAST              (VP_LINE_SPEEDUP_RECOVERY_TIMER + 1)
+
+
+/**< Time after disconnect recovery for Hook mask */
+#define VP_DISCONNECT_RECOVERY_TIME     100
+
+/**< Device Timer Definitions */
+/* Test line timer to ensure a more consistant MPI PCM collect routine, leave
+ * this timer as the first timer. */
+#define VP_DEV_TIMER_TESTLINE   0
+
+/* Clock fail interrupt timer - used only in 790 API */
+#define VP_DEV_TIMER_CLKFAIL            (VP_DEV_TIMER_TESTLINE + 1)
+
+/* ABS Calibration timer */
+#define VP_DEV_TIMER_ABSCAL             (VP_DEV_TIMER_CLKFAIL + 1)
+
+/* Lower Power Mode Switcher Changes */
+#define VP_DEV_TIMER_LP_CHANGE          (VP_DEV_TIMER_ABSCAL + 1)
+
+/* ABV Caibration  device timers */
+#define VP_DEV_TIMER_ABV_CAL            (VP_DEV_TIMER_LP_CHANGE + 1)
+
+/* In-rush limiting enter ringing device timers */
+#define VP_DEV_TIMER_ENTER_RINGING      (VP_DEV_TIMER_ABV_CAL + 1)
+
+/* Used to enable Low Power Switching */
+#define VP_DEV_TIMER_EXIT_RINGING       (VP_DEV_TIMER_ENTER_RINGING + 1)
+
+/* Used to mask clock faults */
+#define VP_DEV_TIMER_WB_MODE_CHANGE     (VP_DEV_TIMER_EXIT_RINGING + 1)
+
+/* Place holder to indicate number of device timers */
+#define VP_DEV_TIMER_LAST               (VP_DEV_TIMER_WB_MODE_CHANGE + 1)
+
+#define VP_DEV_TIMER_EXIT_RINGING_SAMPLE    (5000)
+#define VP_WB_CHANGE_MASK_TIME  (20)
+
+/** FXO specific timer variables to be used for FXO type lines only */
+typedef enum {
+    VP_CSLAC_FXS_TIMER,
+    VP_CSLAC_FXO_TIMER,
+    VP_CSLAC_TIMER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCslacTimerType;
+
+
+#if (defined (VP_CC_880_SERIES) && defined (VP880_FXO_SUPPORT)) || \
+    (defined (VP_CC_890_SERIES) && defined (VP890_FXO_SUPPORT)) || \
+     defined (VP_CC_580_SERIES) || defined (VP_CC_KWRAP)
+typedef struct {
+    uint16  highToLowTime;      /**< Device timestamp of last high to low change */
+    uint16  prevHighToLowTime;
+    bool    noCount;            /**< TRUE when not counting - lack of activity */
+    bool    lastState;          /**< TRUE if last known high, FALSE if low */
+    uint16  timeLastPolRev;     /**< Time in 0.25ms since polrev detected */
+    uint16  timePrevPolRev;     /**< Time in 0.25ms since prev polrev detected */
+    uint8   maxPeriod;          /**< Time in 0.25ms that ringing is detected */
+    uint16  lastStateChange;    /**< Time in 1mS since last state change */
+    uint16  lastNotLiu;         /**< Time in 1mS since last Not LIU detected */
+    uint16  disconnectDebounce; /**< Time in 1mS to debounce disconnect events */
+    uint16  disconnectDuration; /**< Time in ticks that disconnect is detected */
+    uint8   liuDebounce;        /**< Time in 1mS to debounce LIU detection that
+                                     accompanies some kinds of ringing */
+    uint8   ringOffDebounce;    /**< Time in 1mS to ignore disconnect after ring_off */
+    uint8   ringTimer;          /**< When this timer expires, ringing is off */
+    uint8   cidCorrectionTimer; /**< 1mS increments for CID correction timing */
+    uint8   bCalTimer;          /**< 1mS increments for BFilter sampling time */
+    uint16  fxoDiscIO2Change;   /**< Countdown in 1ms since IO2 changed for FXO_DISC termType */
+    uint16  pllRecovery;        /**< Timer in ticks to recover PLL when FXO Disconnect to OHT */
+    uint16  currentMonitorTimer;/**< Used to provide FXO line current buffer */
+    uint16  measureBFilterTimer;/**< 1mS increments for BFilter sampling time */
+    uint8   lowVoltageTimer;    /**< Timer in ticks for the low voltage
+                                     disconnect/LIU distinction workaround */
+} VpFXOTimerType;
+#endif
+
+/** Union of FXO and FXS timers since only one type can exist for each line */
+typedef union {
+#if (defined (VP_CC_880_SERIES) && defined (VP880_FXO_SUPPORT)) || \
+    (defined (VP_CC_890_SERIES) && defined (VP890_FXO_SUPPORT)) || \
+     defined (VP_CC_580_SERIES) || defined (VP_CC_KWRAP)
+    VpFXOTimerType fxoTimer;
+#endif
+    uint16 timer[VP_LINE_TIMER_LAST]; /**< FXS Array of timers */
+} VpCslacTimers;
+
+typedef struct {
+    VpCslacTimerType type;
+    VpCslacTimers timers;
+} VpCslacTimerStruct;
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug.h
new file mode 100755
index 0000000..a0df5aa
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug.h
@@ -0,0 +1,481 @@
+/** \file vp_debug.h
+ * vp_debug.h
+ *
+ * This file contains the configuration and compile time settings for
+ * the VoicePath API debug statements.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8548 $
+ * $LastChangedDate: 2011-04-27 13:53:28 -0500 (Wed, 27 Apr 2011) $
+ *
+ * As of svn 5835, no part of the VP-API-II uses the old VP_DOUT method.
+ */
+
+#ifndef VP_DEBUG_H
+#define VP_DEBUG_H
+
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "sys_service.h"
+
+/*
+ * These are not documented in the API-II and should be used for internal
+ * purposes only. Reserved range (0x00010000 to 0x80000000)
+ */
+#define DBG_EVENT_VERBOSE   0x00010000 /* Verbose event debug (792) */
+#define DBG_BOOT_WRITE      0x00020000 /* Displays all boot blocks */
+
+/* Define VP_DEBUG_COLOR to display ANSI X3.64 color codes in debug output. */
+#define VP_DEBUG_COLOR
+#include "vp_debug_colors.h"
+
+/* Colors for debug messages (if VP_DEBUG_COLOR is defined): */
+#define VP_DBG_ERROR_COLOR          bright_red
+#define VP_DBG_WARNING_COLOR        dark_yellow
+#define VP_DBG_INFO_COLOR           dark_blue
+#define VP_DBG_API_FUNC_COLOR       bright_cyan
+#define VP_DBG_API_FUNC_INT_COLOR   dark_cyan
+#define VP_DBG_HAL_COLOR            bright_white
+#define VP_DBG_SSL_COLOR            dark_green
+#define VP_DBG_EVENT_COLOR          bright_blue
+#define VP_DBG_CALIBRATION_COLOR    bright_white
+#define VP_DBG_LINE_STATE_COLOR     dark_yellow
+#define VP_DBG_HOOK_COLOR           bright_cyan
+#define VP_DBG_TEST_COLOR           bright_blue
+#define VP_DBG_TEST_FUNC_COLOR      bright_yellow
+#define VP_DBG_FXO_FUNC_COLOR       dark_green
+#define VP_DBG_SEQUENCER_COLOR      dark_blue
+#define VP_DBG_CID_COLOR            bright_white
+#define VP_DBG_TEST_PCM_COLOR       bright_cyan
+#define VP_DBG_GAIN_COLOR           dark_yellow
+
+/* Macros for displaying VpDeviceIdType and VpLineIdType values.  If you have
+   defined these (in vp_api_types.h) as something other than simple integers,
+   you should modify the printf format strings as needed: */
+#define VP_PRINT_DEVICE_ID(deviceId)  VpSysDebugPrintf(" (dev 0x%2.2X)", (int)deviceId)
+#define VP_PRINT_LINE_ID(lineId)      VpSysDebugPrintf(" (line %d)", (int)lineId)
+
+/* Define VP_DEBUG_LOC to include the location (file and line) in each debug message. */
+#undef VP_DEBUG_LOC
+
+#ifdef VP_DEBUG_LOC
+#define VP_SHOW_LOC() VpSysDebugPrintf(" (" __FILE__ ":%d)", __LINE__)
+#else
+#define VP_SHOW_LOC()
+#endif
+
+/* Basic debug output macro: */
+#define VP_DOUT_(msgType, msgColor, objType, pObj, printf_args) \
+    if (VpDebugEnabled_ ## objType (VP_DBG_ ## msgType, color_fg(msgColor) #msgType, pObj)) { \
+        VpSysDebugPrintf printf_args; \
+        VP_SHOW_LOC(); \
+        VpSysDebugPrintf(color_reset "\n"); \
+    }
+
+/* Conditionally compile in various types of debug messages: */
+#if !defined(VP_DEBUG) && defined(VP_CC_DEBUG_SELECT)
+#undef VP_CC_DEBUG_SELECT
+#endif
+#ifndef VP_CC_DEBUG_SELECT
+#define VP_CC_DEBUG_SELECT 0
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_ERROR)
+#define VP_ERROR(objType, pObj, printf_args) VP_DOUT_(ERROR, VP_DBG_ERROR_COLOR, objType, pObj, printf_args)
+#else
+#define VP_ERROR(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_WARNING)
+#define VP_WARNING(objType, pObj, printf_args) VP_DOUT_(WARNING, VP_DBG_WARNING_COLOR, objType, pObj, printf_args)
+#else
+#define VP_WARNING(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_INFO)
+#define VP_INFO(objType, pObj, printf_args) VP_DOUT_(INFO, VP_DBG_INFO_COLOR, objType, pObj, printf_args)
+#else
+#define VP_INFO(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_API_FUNC)
+#define VP_API_FUNC(objType, pObj, printf_args) VP_DOUT_(API_FUNC, VP_DBG_API_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_API_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_API_FUNC_INT)
+#define VP_API_FUNC_INT(objType, pObj, printf_args) VP_DOUT_(API_FUNC_INT, VP_DBG_API_FUNC_INT_COLOR, objType, pObj, printf_args)
+#else
+#define VP_API_FUNC_INT(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_CALIBRATION)
+#define VP_CALIBRATION(objType, pObj, printf_args) VP_DOUT_(CALIBRATION, VP_DBG_CALIBRATION_COLOR, objType, pObj, printf_args)
+#else
+#define VP_CALIBRATION(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_LINE_STATE)
+#define VP_LINE_STATE(objType, pObj, printf_args) VP_DOUT_(LINE_STATE, VP_DBG_LINE_STATE_COLOR, objType, pObj, printf_args)
+#else
+#define VP_LINE_STATE(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_HOOK)
+#define VP_HOOK(objType, pObj, printf_args) VP_DOUT_(HOOK, VP_DBG_HOOK_COLOR, objType, pObj, printf_args)
+#else
+#define VP_HOOK(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST)
+#define VP_TEST(objType, pObj, printf_args) VP_DOUT_(TEST, VP_DBG_TEST_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST_FUNC)
+#define VP_TEST_FUNC(objType, pObj, printf_args) VP_DOUT_(TEST_FUNC, VP_DBG_TEST_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_FXO_FUNC)
+#define VP_FXO_FUNC(objType, pObj, printf_args) VP_DOUT_(FXO_FUNC, VP_DBG_FXO_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_FXO_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SEQUENCER)
+#define VP_SEQUENCER(objType, pObj, printf_args) VP_DOUT_(SEQUENCER, VP_DBG_SEQUENCER_COLOR, objType, pObj, printf_args)
+#else
+#define VP_SEQUENCER(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_CID)
+#define VP_CID(objType, pObj, printf_args) VP_DOUT_(CID, VP_DBG_CID_COLOR, objType, pObj, printf_args)
+#else
+#define VP_CID(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST_PCM)
+#define VP_TEST_PCM(objType, pObj, printf_args) VP_DOUT_(TEST_PCM, VP_DBG_TEST_PCM_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST_PCM(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_GAIN)
+#define VP_GAIN(objType, pObj, printf_args) VP_DOUT_(GAIN, VP_DBG_GAIN_COLOR, objType, pObj, printf_args)
+#else
+#define VP_GAIN(objType, pObj, printf_args)
+#endif
+
+
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SSL)
+#define VP_SSL(objType, pObj, printf_args) VP_DOUT_(SSL, VP_DBG_SSL_COLOR, objType, pObj, printf_args)
+#define VP_SYS_ENTER_CRITICAL(deviceId, criticalSecType) VpSysEnterCriticalWrapper(deviceId, criticalSecType)
+#define VP_SYS_EXIT_CRITICAL(deviceId, criticalSecType) VpSysExitCriticalWrapper(deviceId, criticalSecType)
+#define VP_SYS_WAIT(time) \
+    (VP_SSL(None, VP_NULL, ("VpSysWait(%u frames = %u ms)", (time), ((time) + 7 / 8))), VpSysWait(time))
+#else
+#define VP_SSL(objType, pObj, printf_args)
+#define VP_SYS_ENTER_CRITICAL(deviceId, criticalSecType) VpSysEnterCritical(deviceId, criticalSecType)
+#define VP_SYS_EXIT_CRITICAL(deviceId, criticalSecType) VpSysExitCritical(deviceId, criticalSecType)
+#define VP_SYS_WAIT(time) VpSysWait(time)
+#endif
+
+#ifndef VP_HAL_DEVICE_TYPE
+#define VP_HAL_DEVICE_TYPE VP_DEV_VCP_SERIES
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_HAL)
+#define VP_HAL(objType, pObj, printf_args) VP_DOUT_(HAL, VP_DBG_HAL_COLOR, objType, pObj, printf_args)
+#define VP_HAL_HBI_CMD(deviceId, cmd) \
+    (VpDisplayHbiCmd(VP_HAL_DEVICE_TYPE, deviceId, cmd), \
+    VpHalHbiCmd(deviceId, cmd))
+#define VP_HAL_HBI_WRITE(deviceId, cmd, numwords, data) \
+    (VpDisplayHbiCmd(VP_HAL_DEVICE_TYPE, deviceId, cmd), \
+    VpDisplayHbiData(deviceId, numwords + 1, data), \
+    VpHalHbiWrite(deviceId, cmd, numwords, data))
+#define VP_HAL_HBI_READ(deviceId, cmd, numwords, data) \
+    VpHalHbiReadWrapper(VP_HAL_DEVICE_TYPE, deviceId, cmd, numwords, data)
+#if (VP_CC_DEBUG_SELECT & DBG_BOOT_WRITE)
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    (VpDisplayHbiAccess(VP_HAL_DEVICE_TYPE, deviceId, numWords + 1, (uint16p)(data)), \
+    VpHalHbiBootWr(deviceId, numWords, data))
+#else
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    VpHalHbiBootWr(deviceId, numWords, data)
+#endif
+#else
+#define VP_HAL_HBI_CMD(deviceId, cmd) \
+    VpHalHbiCmd(deviceId, cmd)
+#define VP_HAL_HBI_WRITE(deviceId, cmd, numwords, data) \
+    VpHalHbiWrite(deviceId, cmd, numwords, data)
+#define VP_HAL_HBI_READ(deviceId, cmd, numwords, data) \
+    VpHalHbiRead(deviceId, cmd, numwords, data)
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    VpHalHbiBootWr(deviceId, numWords, data)
+#endif
+
+/* Basic assert macro: */
+#define VP_ASSERT(condition) \
+    if (!(condition)) { \
+        VP_ERROR(None, VP_NULL, ("Assertion failed: %s\n", #condition)); \
+        /* exit(-1); */ \
+    }
+
+#define VP_DOUT(msgType, printf_args)
+
+/* Global debug select mask (for messages that are not specific to a particular
+   line or device): */
+EXTERN uint32 vpDebugSelectMask;
+
+#ifdef VP_CC_VCP2_SERIES
+EXTERN bool
+VpDebugEnabled_VpVcp2DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpVcp2DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_VpVcp2LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpVcp2LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_MELT_SERIES
+EXTERN bool
+VpDebugEnabled_VpMeltDeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpMeltDeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_VpMeltLineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpMeltLineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_890_SERIES
+EXTERN bool
+VpDebugEnabled_Vp890DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp890DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp890LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp890LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_880_SERIES
+EXTERN bool
+VpDebugEnabled_Vp880DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp880DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp880LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp880LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_580_SERIES
+EXTERN bool
+VpDebugEnabled_Vp580DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp580DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp580LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp580LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_790_SERIES
+EXTERN bool
+VpDebugEnabled_Vp790DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp790DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp790LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp790LineObjectType *pLineObj);
+#endif
+
+EXTERN bool
+VpDebugEnabled_VpDeviceIdType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpDeviceIdType *pDeviceId);
+
+EXTERN bool
+VpDebugEnabled_VpLineIdType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpLineIdType *pLineId);
+
+EXTERN bool
+VpDebugEnabled_VpDevCtxType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpDevCtxType *pDevCtx);
+
+EXTERN bool
+VpDebugEnabled_VpLineCtxType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpLineCtxType *pLineCtx);
+
+EXTERN bool
+VpDebugEnabled_None(
+    uint32 msgType,
+    char *msgTypeStr,
+    void *nothing);
+
+EXTERN const char *
+VpGetString_VpStatusType(
+    VpStatusType status);
+
+EXTERN const char *
+    VpGetString_VpOptionIdType(
+    VpOptionIdType status);
+
+EXTERN const char *
+VpGetString_VpProfileType(
+    VpProfileType profType);
+
+EXTERN void
+VpDisplayEvent(
+    VpEventType *pEvent);
+
+EXTERN void
+VpDisplayResults(
+    VpEventType *pEvent,
+    void *pResult);
+
+EXTERN void
+VpDisplayHbiAccess(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    unsigned bufLen,
+    uint16 *buf);
+
+EXTERN unsigned
+VpDisplayHbiCmd(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    uint16 cmd);
+
+EXTERN void
+VpDisplayHbiData(
+    VpDeviceIdType deviceId,
+    unsigned bufLen,
+    uint16 *buf);
+
+EXTERN bool
+VpHalHbiReadWrapper(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    uint16 cmd,
+    uint8 numwords,
+    uint16 *data);
+
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SSL)
+EXTERN const char *
+VpGetString_VpCriticalSecType(
+    VpCriticalSecType criticalSecType);
+
+EXTERN uint8
+VpSysEnterCriticalWrapper(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+
+EXTERN uint8
+VpSysExitCriticalWrapper(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+#endif
+
+/* Derivative debug macros: */
+#define VP_API_ENTER(objType, pObj, funcName) \
+    VP_API_FUNC(objType, pObj, ("Vp%s():", funcName))
+#define VP_API_EXIT(objType, pObj, funcName, status) \
+    VP_API_FUNC(objType, pObj, ("Vp%s() = %s", funcName, VpGetString_VpStatusType(status)))
+#define VP_API_INT_ENTER(objType, pObj, funcName) \
+    VP_API_FUNC_INT(objType, pObj, ("%s():", funcName))
+#define VP_API_INT_EXIT(objType, pObj, funcName, status) \
+    VP_API_FUNC_INT(objType, pObj, ("%s() = %s", funcName, VpGetString_VpStatusType(status)))
+
+#if defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES)
+#if (VP_CC_DEBUG_SELECT & VP_DBG_ERROR)
+void VpPrintTermType(VpTermType termType);
+void VpPrintLineStateType(VpLineStateType lineState, char *strLineState);
+void VpPrintOptionRingControlType(VpOptionRingControlType *ringCtrl);
+void VpPrintOptionZeroCrossType(VpOptionZeroCrossType zeroCross);
+void VpPrintRelayControlType(VpRelayControlType relayState);
+void VpPrintOptionCodecType(VpOptionCodecType codec);
+void VpPrintOptionPcmTxRxCntrlType(VpOptionPcmTxRxCntrlType pcmTxRxCtrl);
+void VpPrintCallerIdType(VpCallerIdType *callerId);
+void VpPrintCidSeqDataType(VpCidSeqDataType *cidSeq);
+void VpPrintSeqDataType(VpSeqDataType *cadence);
+void VpPrintVpCslacTimerStruct(VpCslacTimerStruct *lineTimers);
+
+
+void VpPrintApiIntLineState(VpApiIntLineStateType *lineState);
+void VpPrintDigitGenDataType(VpDigitGenerationDataType *digitGenStruct);
+
+
+void VpPrintDynamicInfoStruct(VpDeviceDynamicInfoType *dynamicInfo);
+void VpPrintStaticInfoStruct(VpDeviceStaticInfoType *staticInfo);
+
+/* Bit-wise values from VpDeviceStateType */
+void VpPrintStateInformation(uint16 state);
+void
+VpPrintDeviceProfileStruct(
+    VpDeviceType deviceType,
+    void *devProfileData);
+
+void
+VpPrintEventMaskStruct(
+    bool isDeviceInfo,
+    bool isMask,
+    VpOptionEventMaskType *eventMask);
+
+void VpPrintCriticalFltStruct(VpOptionCriticalFltType *criticalFault);
+void VpPrintGetResultsOptionStruct(VpGetResultsOptionsType *resultsOption);
+void VpPrintRelGainResultsStruct(VpRelGainResultsType *relGainResults);
+
+#define VpPrintEventHandle(eventHandle)     VpSysDebugPrintf("\n\n\rpDevObj->eventHandle = 0x%04X", eventHandle)
+#define VpPrintTimeStamp(timeStamp)         VpSysDebugPrintf("\n\n\rpDevObj->timeStamp = 0x%04X", timeStamp)
+
+void VpPrintDeviceProfileTable(VpCSLACDeviceProfileTableType *devProfileTable);
+void VpPrintProfileTableEntry(VpCSLACProfileTableEntryType *profEntry);
+
+#if defined (VP890_FXS_SUPPORT) || defined (VP880_FXS_SUPPORT)
+void
+VpPrintPulseSpecs(
+    uint8 specNumber,
+    VpOptionPulseType *pulseSpecs);
+void
+VpPrintDPStateMachine(
+    uint8 stateMachineNum,
+    VpDialPulseDetectType  *dpStruct);
+#endif
+
+void
+VpPrintDeviceTimers(
+    uint16 devTimer[VP_DEV_TIMER_LAST]);
+
+#define VpPrintResponseData(responseData)       VpSysDebugPrintf("\n\n\rpDevObj->responseData = 0x%04X", responseData)
+#define VpPrintTxBufferRate(txBufferDataRate)   VpSysDebugPrintf("\n\n\rpDevObj->txBufferDataRate = %d", txBufferDataRate)
+
+
+#endif  /* VP_CC_DEBUG_SELECT & VP_DBG_ERROR */
+#endif  /* defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES) */
+
+
+
+
+
+
+
+#endif /* VP_DEBUG_H */
+
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug_colors.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug_colors.h
new file mode 100755
index 0000000..6081e66
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug_colors.h
@@ -0,0 +1,81 @@
+/* \file vp_debug_colors.h
+ * vp_debug_colors.h
+ *
+ * This file contains ANSI X3.64 codes for displaying colors.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 5264 $
+ * $LastChangedDate: 2009-07-06 10:22:54 -0500 (Mon, 06 Jul 2009) $
+ */
+
+#ifndef VP_DEBUG_COLORS_H
+#define VP_DEBUG_COLORS_H
+
+#include "vp_api_cfg.h"
+
+#ifdef VP_DEBUG_COLOR
+
+#define COLORS_begin    "\x1b["
+#define COLORS_delim    ";"
+#define COLORS_end      "m"
+#define COLORS_reset    "0"
+#define COLORS_bold     "1"
+#define COLORS_nonbold  "22"
+#define COLORS_fore     "3"
+#define COLORS_back     "4"
+
+#define COLORS_black    "0"
+#define COLORS_red      "1"
+#define COLORS_green    "2"
+#define COLORS_yellow   "3"
+#define COLORS_blue     "4"
+#define COLORS_magenta  "5"
+#define COLORS_cyan     "6"
+#define COLORS_white    "7"
+
+#define COLORS_bright_black     COLORS_black    COLORS_delim COLORS_bold
+#define COLORS_bright_red       COLORS_red      COLORS_delim COLORS_bold
+#define COLORS_bright_green     COLORS_green    COLORS_delim COLORS_bold
+#define COLORS_bright_yellow    COLORS_yellow   COLORS_delim COLORS_bold
+#define COLORS_bright_blue      COLORS_blue     COLORS_delim COLORS_bold
+#define COLORS_bright_magenta   COLORS_magenta  COLORS_delim COLORS_bold
+#define COLORS_bright_cyan      COLORS_cyan     COLORS_delim COLORS_bold
+#define COLORS_bright_white     COLORS_white    COLORS_delim COLORS_bold
+
+#define COLORS_dark_black       COLORS_black    COLORS_delim COLORS_nonbold
+#define COLORS_dark_red         COLORS_red      COLORS_delim COLORS_nonbold
+#define COLORS_dark_green       COLORS_green    COLORS_delim COLORS_nonbold
+#define COLORS_dark_yellow      COLORS_yellow   COLORS_delim COLORS_nonbold
+#define COLORS_dark_blue        COLORS_blue     COLORS_delim COLORS_nonbold
+#define COLORS_dark_magenta     COLORS_magenta  COLORS_delim COLORS_nonbold
+#define COLORS_dark_cyan        COLORS_cyan     COLORS_delim COLORS_nonbold
+#define COLORS_dark_white       COLORS_white    COLORS_delim COLORS_nonbold
+
+/*
+ * Usage example:
+ * printf( color_reset             "this is white-on-black text"
+ *         color(red, blue)        "this is red-on-blue text"
+ *         color_fg(green)         "this is green-on-blue text"
+ *         color_fg(bright_white)  "this is bright-white-on-blue text"
+ *         color_bg(black)         "this is bright-white-on-black text"
+ *         color_reset             "this is white on black\n"
+ * );
+ * Note: Bright colors are only allowed in the foreground.
+ */
+
+#define color_fg(c)             COLORS_begin COLORS_fore COLORS_ ## c COLORS_end
+#define color_bg(c)             COLORS_begin COLORS_back COLORS_ ## c COLORS_end
+#define color(fore_c, back_c)   COLORS_begin COLORS_fore COLORS_ ## fore_c COLORS_delim COLORS_back COLORS_ ## back_c COLORS_end
+#define color_reset             COLORS_begin COLORS_reset COLORS_end
+
+#else /* !defined(VP_DEBUG_COLOR) */
+
+#define color_fg(c)             ""
+#define color_bg(c)             ""
+#define color(fore_c, back_c)   ""
+#define color_reset             ""
+
+#endif
+
+#endif /* VP_DEBUG_COLORS_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug_masks.h b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug_masks.h
new file mode 100755
index 0000000..73afc89
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/vp_debug_masks.h
@@ -0,0 +1,41 @@
+/** \file vp_debug_masks.h
+ * vp_debug_masks.h
+ *
+ * This file contains the debug masks for the VP-APi_II
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 7140 $
+ * $LastChangedDate: 2010-05-12 09:50:40 -0500 (Wed, 12 May 2010) $
+ */
+
+#ifndef VP_DEBUG_MASKS_H
+#define VP_DEBUG_MASKS_H
+
+/* VP-API debug message types: */
+#define VP_DBG_ERROR        0x00000001 /* Any error condition */
+#define VP_DBG_WARNING      0x00000002 /* Any warning condition */
+#define VP_DBG_INFO         0x00000004 /* Un-categorized information */
+#define VP_DBG_API_FUNC     0x00000008 /* API function entry/exit (except tick) */
+
+#define VP_DBG_API_FUNC_INT 0x00000010 /* Internal API function entry/exit */
+#define VP_DBG_HAL          0x00000020 /* HAL traffic */
+#define VP_DBG_SSL          0x00000040 /* SSL function entry/exit */
+#define VP_DBG_EVENT        0x00000080 /* Events/results from VpGetEvent()/VpGetResults() */
+
+#define VP_DBG_HOOK         0x00000100 /* Hook Based Code */
+#define VP_DBG_LINE_STATE   0x00000200 /* Set Line State Based Code */
+#define VP_DBG_CALIBRATION  0x00000400 /* VpCalCodec(), VpCalLine(), VpCal() */
+#define VP_DBG_TEST         0x00000800 /* Verbose test debug */
+
+#define VP_DBG_TEST_FUNC    0x00001000 /* Test I/F function enter and exit */
+#define VP_DBG_FXO_FUNC     0x00002000 /* FXO Detection Code */
+#define VP_DBG_SEQUENCER    0x00004000 /* Sequencer Based Code */
+#define VP_DBG_CID          0x00008000 /* Caller ID funcitons */
+
+#define VP_DBG_TEST_PCM     0x00010000 /* Verbose test pcm collection */
+#define VP_DBG_GAIN         0x00020000 /* VpSetRelGain() and VP_OPTION_ID_ABS_GAIN */
+
+#define VP_DBG_ALL          0xFFFFFFFF
+
+#endif /* VP_DEBUG_MASKS_H */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.c b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.c
new file mode 100755
index 0000000..eb76460
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.c
@@ -0,0 +1,935 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include "voiceband/tdm/mvTdm.h"
+
+/* defines */
+#define INT_SAMPLE			2
+#define BUFF_IS_FULL			1
+#define BUFF_IS_EMPTY			0
+#define FIRST_INT			1
+#define TOTAL_BUFFERS			2
+#define MV_TDM_NEXT_BUFFER(buf)		((buf + 1) % TOTAL_BUFFERS)
+#define MV_TDM_PREV_BUFFER(buf, step) 	((TOTAL_BUFFERS + buf - step) % TOTAL_BUFFERS)
+#define MV_TDM_CS			0
+#define BUFF_INVALID			-1
+
+/* static APIs */
+static MV_STATUS mvTdmChInit(MV_U8 ch);
+static MV_STATUS mvTdmChRemove(MV_U8 ch);
+static MV_VOID mvTdmReset(MV_VOID);
+static MV_VOID mvTdmDaisyChainModeSet(MV_VOID);
+static MV_VOID mvTdmShowProperties(MV_VOID);
+/* Tx */
+static INLINE MV_STATUS mvTdmChTxLow(MV_U8 ch);
+/* Rx */
+static INLINE MV_STATUS mvTdmChRxLow(MV_U8 ch);
+
+/* TDM channel info structure */
+typedef struct _mv_tdm_ch_info {
+	MV_U8 ch;
+	MV_U8 *rxBuffVirt[TOTAL_BUFFERS], *txBuffVirt[TOTAL_BUFFERS];
+	MV_ULONG rxBuffPhys[TOTAL_BUFFERS], txBuffPhys[TOTAL_BUFFERS];
+	MV_U8 rxBuffFull[TOTAL_BUFFERS], txBuffFull[TOTAL_BUFFERS];
+	MV_U8 rxCurrBuff, txCurrBuff;
+	MV_U8 rxFirst;
+} MV_TDM_CH_INFO;
+
+/* globals */
+static MV_U8 *rxAggrBuffVirt, *txAggrBuffVirt;
+static MV_ULONG rxAggrBuffPhys, txAggrBuffPhys;
+static MV_U8 rxInt, txInt;
+static MV_16 rxFull, txEmpty;
+static MV_U8 tdmEnable;
+static MV_U8 spiMode;
+static MV_U8 factor;
+static MV_PCM_FORMAT pcmFormat;
+static MV_BAND_MODE tdmBandMode;
+static MV_TDM_CH_INFO *tdmChInfo[MV_TDM_TOTAL_CHANNELS] = { NULL, NULL };
+
+MV_STATUS mvTdmHalInit(MV_TDM_PARAMS *tdmParams, MV_TDM_HAL_DATA *halData)
+{
+	MV_U8 ch;
+	MV_U32 pcmCtrlReg, nbDelay = 0, wbDelay = 0;
+	MV_U32 chDelay[4] = { 0, 0, 0, 0 };
+
+	MV_TRC_REC("->%s\n", __func__);
+	mvTdmShowProperties();
+
+	/* Init globals */
+	rxInt = txInt = 0;
+	rxFull = txEmpty = BUFF_INVALID;
+	tdmEnable = 0;
+	spiMode = halData->spiMode;
+	pcmFormat = tdmParams->pcmFormat;
+
+	if (tdmParams->samplingPeriod > MV_TDM_MAX_SAMPLING_PERIOD)
+		factor = 1;	/* use base sample period(10ms) */
+	else
+		factor = (tdmParams->samplingPeriod / MV_TDM_BASE_SAMPLING_PERIOD);
+
+	/* Extract pcm format & band mode */
+	if (pcmFormat == MV_PCM_FORMAT_4BYTES) {
+		pcmFormat = MV_PCM_FORMAT_2BYTES;
+		tdmBandMode = MV_WIDE_BAND;
+	} else {
+		tdmBandMode = MV_NARROW_BAND;
+	}
+
+	/* Allocate aggregated buffers for data transport */
+	MV_TRC_REC("allocate %d bytes for aggregated buffer\n", MV_TDM_AGGR_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+	rxAggrBuffVirt = (MV_U8 *) mvOsIoCachedMalloc(NULL, MV_TDM_AGGR_BUFF_SIZE(pcmFormat, tdmBandMode, factor),
+						      &rxAggrBuffPhys, NULL);
+	txAggrBuffVirt = (MV_U8 *) mvOsIoCachedMalloc(NULL, MV_TDM_AGGR_BUFF_SIZE(pcmFormat, tdmBandMode, factor),
+						      &txAggrBuffPhys, NULL);
+	if (!rxAggrBuffVirt || !txAggrBuffVirt) {
+		mvOsPrintf("%s: Error malloc failed\n", __func__);
+		return MV_NO_RESOURCE;
+	}
+
+	/* Clear buffers */
+	memset(rxAggrBuffVirt, 0, MV_TDM_AGGR_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+	memset(txAggrBuffVirt, 0, MV_TDM_AGGR_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+
+	/* Calculate CH(0/1) Delay Control for narrow/wideband modes */
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+		nbDelay = ((tdmParams->pcmSlot[ch] * PCM_SLOT_PCLK) + 1);
+		wbDelay = (nbDelay + ((halData->frameTs / 2) * PCM_SLOT_PCLK)); /* Offset required by ZARLINK VE880 SLIC */
+		chDelay[ch] = ((nbDelay << CH_RX_DELAY_OFFS) | (nbDelay << CH_TX_DELAY_OFFS));
+		chDelay[(ch + 2)] = ((wbDelay << CH_RX_DELAY_OFFS) | (wbDelay << CH_TX_DELAY_OFFS));
+	}
+
+	/* Config TDM */
+	MV_REG_BIT_RESET(TDM_SPI_MUX_REG, 1);	/* enable TDM/SPI interface */
+	MV_REG_BIT_SET(TDM_MISC_REG, BIT0);	/* sw reset to TDM for 5181L-A1 & up */
+	MV_REG_WRITE(INT_RESET_SELECT_REG, CLEAR_ON_ZERO);	/* int cause is not clear on read */
+	MV_REG_WRITE(INT_EVENT_MASK_REG, 0x3ffff);	/* all interrupt bits latched in status */
+	MV_REG_WRITE(INT_STATUS_MASK_REG, 0);	/* disable interrupts */
+	MV_REG_WRITE(INT_STATUS_REG, 0);	/* clear int status register */
+
+	/* Bypass clock divider */
+	MV_REG_WRITE(PCM_CLK_RATE_DIV_REG, PCM_DIV_PASS);	/* PCM PCLK freq */
+
+	MV_REG_WRITE(DUMMY_RX_WRITE_DATA_REG, 0);	/* Padding on Rx completion */
+	MV_REG_BYTE_WRITE(SPI_GLOBAL_CTRL_REG, MV_REG_READ(SPI_GLOBAL_CTRL_REG) | SPI_GLOBAL_ENABLE);
+	MV_REG_BYTE_WRITE(SPI_CLK_PRESCALAR_REG, SPI_CLK_2MHZ);	/* SPI SCLK freq */
+	MV_REG_WRITE(FRAME_TIMESLOT_REG, (MV_U32)halData->frameTs); /* Number of timeslots (PCLK) */
+
+	if (tdmBandMode == MV_NARROW_BAND) {
+		pcmCtrlReg = (CONFIG_PCM_CRTL | (((MV_U8)pcmFormat - 1) << PCM_SAMPLE_SIZE_OFFS));
+		MV_REG_WRITE(PCM_CTRL_REG, pcmCtrlReg);	/* PCM configuration */
+		MV_REG_WRITE(CH_DELAY_CTRL_REG(0), chDelay[0]);	/* CH0 delay control register */
+		MV_REG_WRITE(CH_DELAY_CTRL_REG(1), chDelay[1]);	/* CH1 delay control register */
+	} else {		/* MV_WIDE_BAND */
+
+		pcmCtrlReg = (CONFIG_WB_PCM_CRTL | (((MV_U8)pcmFormat - 1) << PCM_SAMPLE_SIZE_OFFS));
+		MV_REG_WRITE(PCM_CTRL_REG, pcmCtrlReg);	/* PCM configuration - WB support */
+		MV_REG_WRITE(CH_DELAY_CTRL_REG(0), chDelay[0]);	/* CH0 delay control register */
+		MV_REG_WRITE(CH_DELAY_CTRL_REG(1), chDelay[1]);	/* CH1 delay control register */
+		MV_REG_WRITE(CH_WB_DELAY_CTRL_REG(0), chDelay[2]);	/* CH0 WB delay control register */
+		MV_REG_WRITE(CH_WB_DELAY_CTRL_REG(1), chDelay[3]);	/* CH1 WB delay control register */
+	}
+
+	/* Issue reset to codec(s) */
+	MV_TRC_REC("reseting voice unit(s)\n");
+	MV_REG_WRITE(MISC_CTRL_REG, 0);
+	mvOsDelay(1);
+	MV_REG_WRITE(MISC_CTRL_REG, 1);
+
+	if (spiMode) {
+		/* Configure TDM to work in daisy chain mode */
+		mvTdmDaisyChainModeSet();
+	}
+
+	/* Initialize all HW units */
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+		if (mvTdmChInit(ch) != MV_OK) {
+			mvOsPrintf("mvTdmChInit(%d) failed !\n", ch);
+			return MV_ERROR;
+		}
+	}
+
+	/* Enable SLIC/DAA interrupt detection(before pcm is active) */
+	MV_REG_WRITE(INT_STATUS_MASK_REG, (MV_REG_READ(INT_STATUS_MASK_REG) | TDM_INT_SLIC));
+
+	MV_TRC_REC("<-%s\n", __func__);
+	return MV_OK;
+}
+
+static MV_STATUS mvTdmChInit(MV_U8 ch)
+{
+	MV_TDM_CH_INFO *chInfo;
+	MV_U32 buff;
+
+	MV_TRC_REC("->%s ch%d\n", __func__, ch);
+
+	if (ch >= MV_TDM_TOTAL_CHANNELS) {
+		mvOsPrintf("%s: error, channel(%d) exceeds maximum(%d)\n", __func__, ch, MV_TDM_TOTAL_CHANNELS);
+		return MV_BAD_PARAM;
+	}
+
+	tdmChInfo[ch] = chInfo = (MV_TDM_CH_INFO *) mvOsMalloc(sizeof(MV_TDM_CH_INFO));
+	if (!chInfo) {
+		mvOsPrintf("%s: error malloc failed\n", __func__);
+		return MV_NO_RESOURCE;
+	}
+
+	chInfo->ch = ch;
+
+	/* Per channel TDM init */
+	MV_REG_WRITE(CH_ENABLE_REG(ch), CH_DISABLE);	/* disable channel (enable in pcm start) */
+	MV_REG_WRITE(CH_SAMPLE_REG(ch), CONFIG_CH_SAMPLE(tdmBandMode, factor));	/* set total samples and int sample */
+
+	for (buff = 0; buff < TOTAL_BUFFERS; buff++) {
+		/* Buffers must be 32B aligned */
+		chInfo->rxBuffVirt[buff] =
+		    (MV_U8 *) mvOsIoUncachedMalloc(NULL, MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor),
+						   &(chInfo->rxBuffPhys[buff]), NULL);
+		chInfo->rxBuffFull[buff] = BUFF_IS_EMPTY;
+
+		chInfo->txBuffVirt[buff] =
+		    (MV_U8 *) mvOsIoUncachedMalloc(NULL, MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor),
+						   &(chInfo->txBuffPhys[buff]), NULL);
+		chInfo->txBuffFull[buff] = BUFF_IS_FULL;
+
+		memset(chInfo->txBuffVirt[buff], 0, MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+
+		if (((MV_ULONG) chInfo->rxBuffVirt[buff] | chInfo->rxBuffPhys[buff] |
+		     (MV_ULONG) chInfo->txBuffVirt[buff] | chInfo->txBuffPhys[buff]) & 0x1f) {
+			mvOsPrintf("%s: error, unaligned buffer allocation\n", __func__);
+		}
+	}
+
+	MV_TRC_REC("<-%s\n", __func__);
+	return MV_OK;
+}
+
+MV_VOID mvTdmRelease(MV_VOID)
+{
+	MV_U8 ch;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Free Rx/Tx aggregated buffers */
+	mvOsIoCachedFree(NULL, MV_TDM_AGGR_BUFF_SIZE(pcmFormat, tdmBandMode, factor), rxAggrBuffPhys,
+			 rxAggrBuffVirt, 0);
+	mvOsIoCachedFree(NULL, MV_TDM_AGGR_BUFF_SIZE(pcmFormat, tdmBandMode, factor), txAggrBuffPhys,
+			 txAggrBuffVirt, 0);
+
+	/* Release HW channel resources */
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++)
+		mvTdmChRemove(ch);
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+static MV_STATUS mvTdmChRemove(MV_U8 ch)
+{
+	MV_TDM_CH_INFO *chInfo;
+	MV_U8 buff;
+
+	MV_TRC_REC("->%s ch%d\n", __func__, ch);
+
+	if (ch >= MV_TDM_TOTAL_CHANNELS) {
+		mvOsPrintf("%s: error, channel(%d) exceeds maximum(%d)\n", __func__, ch, MV_TDM_TOTAL_CHANNELS);
+		return MV_BAD_PARAM;
+	}
+
+	chInfo = tdmChInfo[ch];
+
+	for (buff = 0; buff < TOTAL_BUFFERS; buff++) {
+		mvOsIoUncachedFree(NULL, MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor), chInfo->rxBuffPhys[buff],
+				   chInfo->rxBuffVirt[buff], 0);
+		mvOsIoUncachedFree(NULL, MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor), chInfo->txBuffPhys[buff],
+				   chInfo->txBuffVirt[buff], 0);
+	}
+
+	mvOsFree(chInfo);
+
+	MV_TRC_REC("<-%s ch%d\n", __func__, ch);
+	return MV_OK;
+}
+
+static MV_VOID mvTdmReset(MV_VOID)
+{
+	MV_TDM_CH_INFO *chInfo;
+	MV_U8 buff, ch;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Reset globals */
+	rxInt = txInt = 0;
+	rxFull = txEmpty = BUFF_INVALID;
+
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+		chInfo = tdmChInfo[ch];
+		chInfo->rxFirst = FIRST_INT;
+		chInfo->txCurrBuff = chInfo->rxCurrBuff = 0;
+		for (buff = 0; buff < TOTAL_BUFFERS; buff++) {
+			chInfo->rxBuffFull[buff] = BUFF_IS_EMPTY;
+			chInfo->txBuffFull[buff] = BUFF_IS_FULL;
+
+		}
+	}
+
+	MV_TRC_REC("<-%s\n", __func__);
+	return;
+}
+
+MV_VOID mvTdmPcmStart(MV_VOID)
+{
+	MV_TDM_CH_INFO *chInfo;
+	MV_U8 ch;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	tdmEnable = 1;		/* TDM is enabled  */
+	mvTdmReset();
+
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+		chInfo = tdmChInfo[ch];
+
+		/* Set Tx buff */
+		MV_REG_WRITE(CH_TX_ADDR_REG(ch), chInfo->txBuffPhys[chInfo->txCurrBuff]);
+		MV_REG_BYTE_WRITE(CH_BUFF_OWN_REG(ch) + TX_OWN_BYTE_OFFS, OWN_BY_HW);
+
+		/* Set Rx buff */
+		MV_REG_WRITE(CH_RX_ADDR_REG(ch), chInfo->rxBuffPhys[chInfo->rxCurrBuff]);
+		MV_REG_BYTE_WRITE(CH_BUFF_OWN_REG(ch) + RX_OWN_BYTE_OFFS, OWN_BY_HW);
+
+	}
+
+	/* Enable Tx */
+	MV_REG_BYTE_WRITE(CH_ENABLE_REG(0) + TX_ENABLE_BYTE_OFFS, CH_ENABLE);
+	MV_REG_BYTE_WRITE(CH_ENABLE_REG(1) + TX_ENABLE_BYTE_OFFS, CH_ENABLE);
+
+	/* Enable Rx */
+	MV_REG_BYTE_WRITE(CH_ENABLE_REG(0) + RX_ENABLE_BYTE_OFFS, CH_ENABLE);
+	MV_REG_BYTE_WRITE(CH_ENABLE_REG(1) + RX_ENABLE_BYTE_OFFS, CH_ENABLE);
+
+	/* Enable Tx interrupts */
+	MV_REG_WRITE(INT_STATUS_REG, MV_REG_READ(INT_STATUS_REG) & (~(TDM_INT_TX(0) | TDM_INT_TX(1))));
+	MV_REG_WRITE(INT_STATUS_MASK_REG, (MV_REG_READ(INT_STATUS_MASK_REG) | TDM_INT_TX(0) | TDM_INT_TX(1)));
+
+	/* Enable Rx interrupts */
+	MV_REG_WRITE(INT_STATUS_REG, (MV_REG_READ(INT_STATUS_REG) & (~(TDM_INT_RX(0) | TDM_INT_RX(1)))));
+	MV_REG_WRITE(INT_STATUS_MASK_REG, (MV_REG_READ(INT_STATUS_MASK_REG) | TDM_INT_RX(0) | TDM_INT_RX(1)));
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+MV_VOID mvTdmPcmStop(MV_VOID)
+{
+	MV_TRC_REC("->%s\n", __func__);
+
+	tdmEnable = 0;
+	mvTdmReset();
+
+	/* Mask all interrpts except SLIC/DAA */
+	/*MV_REG_WRITE(INT_STATUS_MASK_REG, (MV_U32)TDM_INT_SLIC);*/
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
+
+MV_STATUS mvTdmTx(MV_U8 *tdmTxBuff)
+{
+	MV_TDM_CH_INFO *chInfo;
+	MV_U8 ch;
+	MV_U8 *pTdmTxBuff;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Sanity check */
+	if (tdmTxBuff != txAggrBuffVirt) {
+		mvOsPrintf("%s: Error, invalid Tx buffer !!!\n", __func__);
+		return MV_ERROR;
+	}
+
+	if (!tdmEnable) {
+		mvOsPrintf("%s: Error, no active Tx channels are available\n", __func__);
+		return MV_ERROR;
+	}
+
+	if (txEmpty == BUFF_INVALID) {
+		MV_TRC_REC("%s: Tx not ready\n", __func__);
+		return MV_NOT_READY;
+	}
+
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+		chInfo = tdmChInfo[ch];
+		MV_TRC_REC("ch%d: fill buf %d with %d bytes\n", ch, txEmpty,
+			   MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+		chInfo->txBuffFull[txEmpty] = BUFF_IS_FULL;
+		pTdmTxBuff = tdmTxBuff + (ch * MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+		/* Copy data from voice engine buffer to DMA */
+		mvOsMemcpy(chInfo->txBuffVirt[txEmpty], pTdmTxBuff,
+			   MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+	}
+
+	txEmpty = BUFF_INVALID;
+
+	MV_TRC_REC("<-%s\n", __func__);
+	return MV_OK;
+}
+
+MV_STATUS mvTdmRx(MV_U8 *tdmRxBuff)
+{
+	MV_TDM_CH_INFO *chInfo;
+	MV_U8 ch;
+	MV_U8 *pTdmRxBuff;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Sanity check */
+	if (tdmRxBuff != rxAggrBuffVirt) {
+		mvOsPrintf("%s: invalid Rx buffer !!!\n", __func__);
+		return MV_ERROR;
+	}
+
+	if (!tdmEnable) {
+		mvOsPrintf("%s: Error, no active Rx channels are available\n", __func__);
+		return MV_ERROR;
+	}
+
+	if (rxFull == BUFF_INVALID) {
+		MV_TRC_REC("%s: Rx not ready\n", __func__);
+		return MV_NOT_READY;
+	}
+
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+		chInfo = tdmChInfo[ch];
+		chInfo->rxBuffFull[rxFull] = BUFF_IS_EMPTY;
+		MV_TRC_REC("%s get Rx buffer(%d) for channel(%d)\n", __func__, rxFull, ch);
+		pTdmRxBuff = tdmRxBuff + (ch * MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+		/* Copy data from DMA to voice engine buffer */
+		mvOsMemcpy(pTdmRxBuff, chInfo->rxBuffVirt[rxFull], MV_TDM_CH_BUFF_SIZE(pcmFormat, tdmBandMode, factor));
+	}
+
+	rxFull = BUFF_INVALID;
+	MV_TRC_REC("<-%s\n", __func__);
+	return MV_OK;
+}
+
+/* Low level TDM interrupt service routine */
+MV_VOID mvTdmIntLow(MV_TDM_INT_INFO *tdmIntInfo)
+{
+	MV_U32 statusReg, maskReg, statusAndMask;
+	MV_U8 ch;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	/* Read Status & mask registers */
+	statusReg = MV_REG_READ(INT_STATUS_REG);
+	maskReg = MV_REG_READ(INT_STATUS_MASK_REG);
+	MV_TRC_REC("CAUSE(0x%x), MASK(0x%x)\n", statusReg, maskReg);
+
+	/* Refer only to unmasked bits */
+	statusAndMask = statusReg & maskReg;
+
+	/* Reset params */
+	tdmIntInfo->tdmRxBuff = NULL;
+	tdmIntInfo->tdmTxBuff = NULL;
+	tdmIntInfo->intType = MV_EMPTY_INT;
+	tdmIntInfo->cs = MV_TDM_CS;
+
+	/* Handle SLIC/DAA int */
+	if (statusAndMask & SLIC_INT_BIT) {
+		MV_TRC_REC("Phone interrupt !!!\n");
+		tdmIntInfo->intType |= MV_PHONE_INT;
+	}
+#if 0
+	/* Return in case TDM is disabled */
+	if (!tdmEnable) {
+		MV_TRC_REC("TDM is disabled - quit low level ISR\n");
+		MV_REG_WRITE(INT_STATUS_REG, ~statusReg);
+		return;
+	}
+#endif
+	if (statusAndMask & DMA_ABORT_BIT) {
+		mvOsPrintf("DMA data abort. Address: 0x%08x, Info: 0x%08x\n",
+			   MV_REG_READ(DMA_ABORT_ADDR_REG), MV_REG_READ(DMA_ABORT_INFO_REG));
+		tdmIntInfo->intType |= MV_DMA_ERROR_INT;
+	}
+
+	for (ch = 0; ch < MV_TDM_TOTAL_CHANNELS; ch++) {
+		if (statusAndMask & TDM_INT_TX(ch)) {
+			/* Give next buff to TDM and set curr buff as empty */
+			if ((statusAndMask & TX_BIT(ch)) && tdmEnable) {
+				MV_TRC_REC("Tx interrupt(ch%d) !!!\n", ch);
+
+				/* MV_OK -> Tx is done for both channels */
+				if (mvTdmChTxLow(ch) == MV_OK) {
+					MV_TRC_REC("Assign Tx aggregate buffer for further processing\n");
+					tdmIntInfo->tdmTxBuff = txAggrBuffVirt;
+					tdmIntInfo->intType |= MV_TX_INT;
+				}
+			}
+
+			if (statusAndMask & TX_UNDERFLOW_BIT(ch)) {
+				MV_TRC_REC("Tx underflow(ch%d) - checking for root cause...\n", ch);
+				if (tdmEnable) {
+					MV_TRC_REC("Tx underflow ERROR\n");
+					tdmIntInfo->intType |= MV_TX_ERROR_INT;
+					if (!(statusAndMask & TX_BIT(ch))) {
+						MV_TRC_REC("Trying to recover for ch(%d)\n", ch);
+						/* Set HW ownership */
+						MV_REG_BYTE_WRITE(CH_BUFF_OWN_REG(ch) + TX_OWN_BYTE_OFFS, OWN_BY_HW);
+						/* Enable Tx */
+						MV_REG_BYTE_WRITE(CH_ENABLE_REG(ch) + TX_ENABLE_BYTE_OFFS, CH_ENABLE);
+					}
+				} else {
+					MV_TRC_REC("Expected Tx underflow(not an error)\n");
+					MV_REG_WRITE(INT_STATUS_MASK_REG,
+						     MV_REG_READ(INT_STATUS_MASK_REG) & (~(TDM_INT_TX(ch))));
+				}
+			}
+		}
+
+		if (statusAndMask & TDM_INT_RX(ch)) {
+			if ((statusAndMask & RX_BIT(ch)) && tdmEnable) {
+				MV_TRC_REC("Rx interrupt(ch%d) !!!\n", ch);
+
+				/* MV_OK -> Rx is done for both channels */
+				if (mvTdmChRxLow(ch) == MV_OK) {
+					MV_TRC_REC("Assign Rx aggregate buffer for further processing\n");
+					tdmIntInfo->tdmRxBuff = rxAggrBuffVirt;
+					tdmIntInfo->intType |= MV_RX_INT;
+				}
+			}
+
+			if (statusAndMask & RX_OVERFLOW_BIT(ch)) {
+				MV_TRC_REC("Rx overflow(ch%d) - checking for root cause...\n", ch);
+				if (tdmEnable) {
+					MV_TRC_REC("Rx overflow ERROR\n");
+					tdmIntInfo->intType |= MV_RX_ERROR_INT;
+					if (!(statusAndMask & RX_BIT(ch))) {
+						MV_TRC_REC("Trying to recover for ch(%d)\n", ch);
+						/* Set HW ownership */
+						MV_REG_BYTE_WRITE(CH_BUFF_OWN_REG(ch) + RX_OWN_BYTE_OFFS, OWN_BY_HW);
+						/* Enable Rx */
+						MV_REG_BYTE_WRITE(CH_ENABLE_REG(ch) + RX_ENABLE_BYTE_OFFS, CH_ENABLE);
+					}
+				} else {
+					MV_TRC_REC("Expected Rx overflow(not an error)\n");
+					MV_REG_WRITE(INT_STATUS_MASK_REG,
+						     MV_REG_READ(INT_STATUS_MASK_REG) & (~(TDM_INT_RX(ch))));
+				}
+			}
+		}
+	}
+
+	/* clear TDM interrupts */
+	MV_REG_WRITE(INT_STATUS_REG, ~statusReg);
+
+	MV_TRC_REC("<-%s\n", __func__);
+	return;
+}
+
+static INLINE MV_STATUS mvTdmChTxLow(MV_U8 ch)
+{
+	MV_U32 max_poll = 0;
+	MV_TDM_CH_INFO *chInfo = tdmChInfo[ch];
+
+	MV_TRC_REC("->%s ch%d\n", __func__, ch);
+
+	/* count tx interrupts */
+	txInt++;
+	MV_TRC_REC("txInt(%d)\n", txInt);
+
+	if (chInfo->txBuffFull[chInfo->txCurrBuff] == BUFF_IS_FULL)
+		MV_TRC_REC("curr buff full for hw [MMP ok]\n");
+	else
+		MV_TRC_REC("curr buf is empty [MMP miss write]\n");
+
+	/* Change buffers */
+	chInfo->txCurrBuff = MV_TDM_NEXT_BUFFER(chInfo->txCurrBuff);
+
+	/* Mark next buff to be transmitted by HW as empty. Give it to the HW
+	   for next frame. The app need to write the data before HW takes it.  */
+	chInfo->txBuffFull[chInfo->txCurrBuff] = BUFF_IS_EMPTY;
+	MV_TRC_REC("->%s clear buf(%d) for channel(%d)\n", __func__, chInfo->txCurrBuff, ch);
+
+	/* Poll on SW ownership (single check) */
+	MV_TRC_REC("start poll for SW ownership\n");
+	while (((MV_REG_BYTE_READ(CH_BUFF_OWN_REG(chInfo->ch) + TX_OWN_BYTE_OFFS) & OWNER_MASK) == OWN_BY_HW)
+	       && (max_poll < 2000)) {
+		mvOsUDelay(1);
+		max_poll++;
+	}
+	if (max_poll == 2000) {
+		MV_TRC_REC("poll timeout (~2ms)\n");
+		return MV_TIMEOUT;
+	} else {
+		MV_TRC_REC("tx-low poll stop ok\n");
+	}
+	MV_TRC_REC("ch%d, start tx buff %d\n", ch, chInfo->txCurrBuff);
+
+	/*Set TX buff address (must be 32 byte aligned) */
+	MV_REG_WRITE(CH_TX_ADDR_REG(chInfo->ch), chInfo->txBuffPhys[chInfo->txCurrBuff]);
+
+	/* Set HW ownership */
+	MV_REG_BYTE_WRITE(CH_BUFF_OWN_REG(chInfo->ch) + TX_OWN_BYTE_OFFS, OWN_BY_HW);
+
+	/* Enable Tx */
+	MV_REG_BYTE_WRITE(CH_ENABLE_REG(chInfo->ch) + TX_ENABLE_BYTE_OFFS, CH_ENABLE);
+
+	MV_TRC_REC("<-%s\n", __func__);
+
+	/* Did we get the required amount of irqs for Tx wakeup ? */
+	if (txInt < MV_TDM_INT_COUNTER) {
+		return MV_NOT_READY;
+	} else {
+		txInt = 0;
+		txEmpty = chInfo->txCurrBuff;
+		return MV_OK;
+	}
+}
+
+static INLINE MV_STATUS mvTdmChRxLow(MV_U8 ch)
+{
+	MV_U32 max_poll = 0;
+	MV_TDM_CH_INFO *chInfo = tdmChInfo[ch];
+
+	MV_TRC_REC("->%s ch%d\n", __func__, ch);
+
+	if (chInfo->rxFirst)
+		chInfo->rxFirst = !FIRST_INT;
+	else
+		rxInt++;
+
+	MV_TRC_REC("rxInt(%d)\n", rxInt);
+
+	if (chInfo->rxBuffFull[chInfo->rxCurrBuff] == BUFF_IS_EMPTY)
+		MV_TRC_REC("curr buff empty for hw [MMP ok]\n");
+	else
+		MV_TRC_REC("curr buf is full [MMP miss read]\n");
+
+	/* Mark last buff that was received by HW as full. Give next buff to HW for */
+	/* next frame. The app need to read the data before next irq */
+	chInfo->rxBuffFull[chInfo->rxCurrBuff] = BUFF_IS_FULL;
+
+	/* Change buffers */
+	chInfo->rxCurrBuff = MV_TDM_NEXT_BUFFER(chInfo->rxCurrBuff);
+
+	/* Poll on SW ownership (single check) */
+	MV_TRC_REC("start poll for ownership\n");
+	while (((MV_REG_BYTE_READ(CH_BUFF_OWN_REG(chInfo->ch) + RX_OWN_BYTE_OFFS) & OWNER_MASK) == OWN_BY_HW)
+	       && (max_poll < 2000)) {
+		mvOsUDelay(1);
+		max_poll++;
+	}
+	if (max_poll == 2000) {
+		MV_TRC_REC("poll timeout (~2ms)\n");
+		return MV_TIMEOUT;
+	} else {
+		MV_TRC_REC("poll stop ok\n");
+	}
+	MV_TRC_REC("%s ch%d, start rx buff %d\n", __func__, ch, chInfo->rxCurrBuff);
+
+	/* Set RX buff address (must be 32 byte aligned) */
+	MV_REG_WRITE(CH_RX_ADDR_REG(chInfo->ch), chInfo->rxBuffPhys[chInfo->rxCurrBuff]);
+
+	/* Set HW ownership */
+	MV_REG_BYTE_WRITE(CH_BUFF_OWN_REG(chInfo->ch) + RX_OWN_BYTE_OFFS, OWN_BY_HW);
+
+	/* Enable Rx */
+	MV_REG_BYTE_WRITE(CH_ENABLE_REG(chInfo->ch) + RX_ENABLE_BYTE_OFFS, CH_ENABLE);
+
+	MV_TRC_REC("<-%s\n", __func__);
+
+	/* Did we get the required amount of irqs for Rx wakeup ? */
+	if (rxInt < MV_TDM_INT_COUNTER) {
+		return MV_NOT_READY;
+	} else {
+		rxInt = 0;
+		rxFull = MV_TDM_PREV_BUFFER(chInfo->rxCurrBuff, 2);
+		MV_TRC_REC("buff %d is FULL for ch0\n", rxFull);
+		MV_TRC_REC("buff %d is FULL for ch1\n", rxFull);
+		return MV_OK;
+	}
+}
+
+/****************************
+**        SPI Stuff        **
+****************************/
+
+static MV_VOID mvTdmSetCurrentUnit(MV_32 cs)
+{
+	if (!spiMode) {
+		if (!cs)
+			MV_REG_WRITE(PCM_CTRL_REG, (MV_REG_READ(PCM_CTRL_REG) & ~CS_CTRL));
+		else
+			MV_REG_WRITE(PCM_CTRL_REG, (MV_REG_READ(PCM_CTRL_REG) | CS_CTRL));
+	} else
+		MV_REG_WRITE(PCM_CTRL_REG, (MV_REG_READ(PCM_CTRL_REG) & ~CS_CTRL));
+}
+
+static MV_VOID mvTdmDaisyChainModeSet(MV_VOID)
+{
+	mvOsPrintf("Setting Daisy Chain Mode\n");
+	while ((MV_REG_READ(SPI_CTRL_REG) & SPI_STAT_MASK) == SPI_ACTIVE)
+		continue;
+	MV_REG_WRITE(SPI_CODEC_CMD_LO_REG, (0x80 << 8) | 0);
+	MV_REG_WRITE(SPI_CODEC_CTRL_REG, TRANSFER_BYTES(2) | ENDIANESS_MSB_MODE | WR_MODE | CLK_SPEED_LO_DIV);
+	MV_REG_WRITE(SPI_CTRL_REG, MV_REG_READ(SPI_CTRL_REG) | SPI_ACTIVE);
+	/* Poll for ready indication */
+	while ((MV_REG_READ(SPI_CTRL_REG) & SPI_STAT_MASK) == SPI_ACTIVE)
+		continue;
+}
+
+MV_STATUS mvTdmSpiWrite(MV_U8 *cmdBuff, MV_U8 cmdSize, MV_U8 *dataBuff, MV_U8 dataSize, MV_U8 cs)
+{
+	MV_U32 i, val1 = 0, val2 = 0, cmd;
+
+	/*MV_TRC_REC("%s: cs = %d val1 = 0x%x val2 = 0x%x\n",__func__,cs, val1, val2); */
+
+	/* Poll for ready indication */
+	while ((MV_REG_READ(SPI_CTRL_REG) & SPI_STAT_MASK) == SPI_ACTIVE)
+		continue;
+
+	if (cmdSize > 0)
+		val1 = (MV_U32) (cmdBuff[0] & 0xff);
+
+	if (cmdSize > 1)
+		val1 |= (MV_U32) (cmdBuff[1] << 8);
+
+	if (cmdSize > 2)
+		val2 = (MV_U32) (cmdBuff[2] & 0xff);
+
+	mvTdmSetCurrentUnit(cs);
+
+	/* Prepare codec control parameters for command transmission */
+	cmd = TRANSFER_BYTES(cmdSize) | ENDIANESS_MSB_MODE | WR_MODE | CLK_SPEED_LO_DIV;
+
+	MV_REG_WRITE(SPI_CODEC_CMD_LO_REG, val1);
+	MV_REG_WRITE(SPI_CODEC_CMD_HI_REG, val2);
+	MV_REG_WRITE(SPI_CODEC_CTRL_REG, cmd);
+
+	/* Activate */
+	MV_REG_WRITE(SPI_CTRL_REG, MV_REG_READ(SPI_CTRL_REG) | SPI_ACTIVE);
+
+	/* Poll for ready indication */
+	while ((MV_REG_READ(SPI_CTRL_REG) & SPI_STAT_MASK) == SPI_ACTIVE)
+		continue;
+
+	/* Update the command to 1 data byte transfer */
+	cmd = TRANSFER_BYTES(1) | ENDIANESS_MSB_MODE | WR_MODE | CLK_SPEED_LO_DIV;
+
+	for (i = 0; i < dataSize; i++) {
+		val1 = dataBuff[i];
+
+		mvTdmSetCurrentUnit(cs);
+
+		MV_REG_WRITE(SPI_CODEC_CMD_LO_REG, val1);
+		MV_REG_WRITE(SPI_CODEC_CTRL_REG, cmd);
+
+		/* Activate */
+		MV_REG_WRITE(SPI_CTRL_REG, MV_REG_READ(SPI_CTRL_REG) | SPI_ACTIVE);
+
+		/* Poll for ready indication */
+		while ((MV_REG_READ(SPI_CTRL_REG) & SPI_STAT_MASK) == SPI_ACTIVE)
+			continue;
+	}
+
+	return MV_OK;
+}
+
+MV_STATUS mvTdmSpiRead(MV_U8 *cmdBuff, MV_U8 cmdSize, MV_U8 *dataBuff, MV_U8 dataSize, MV_U8 cs)
+{
+	MV_U32 val1 = 0, val2 = 0, cmd;
+	MV_U32 data;
+
+	/*MV_TRC_REC("%s: cs = %d val1 = 0x%x val2 = 0x%x\n",__func__,cs, val1, val2); */
+
+	if (dataSize > 2) {
+		mvOsPrintf("%s: Error, exceeded max read size(%d)\n", __func__, dataSize);
+		return MV_ERROR;
+	}
+
+	/* Poll for ready indication */
+	while ((MV_REG_READ(SPI_CTRL_REG) & SPI_STAT_MASK) == SPI_ACTIVE)
+		continue;
+
+	val1 = (MV_U32) (cmdBuff[0] & 0xff);
+
+	if (cmdSize > 1)
+		val1 |= (MV_U32) (cmdBuff[1] << 8);
+
+	if (cmdSize > 2)
+		val2 = (MV_U32) (cmdBuff[2] & 0xff);
+
+	if (cmdSize > 3)
+		val2 = (MV_U32) (cmdBuff[3] << 8);
+
+	mvTdmSetCurrentUnit(cs);
+
+	/* Prepare codec control parameters for command transmission */
+	if (dataSize == 1)
+		cmd = TRANSFER_BYTES(cmdSize) | ENDIANESS_MSB_MODE | RD_MODE | READ_1_BYTE | CLK_SPEED_LO_DIV;
+	else
+		cmd = TRANSFER_BYTES(cmdSize) | ENDIANESS_MSB_MODE | RD_MODE | READ_2_BYTE | CLK_SPEED_LO_DIV;
+
+	MV_REG_WRITE(SPI_CODEC_CMD_LO_REG, val1);
+	MV_REG_WRITE(SPI_CODEC_CMD_HI_REG, val2);
+	MV_REG_WRITE(SPI_CODEC_CTRL_REG, cmd);
+
+	/* Activate */
+	MV_REG_WRITE(SPI_CTRL_REG, MV_REG_READ(SPI_CTRL_REG) | SPI_ACTIVE);
+
+	/* Poll for ready indication */
+	while ((MV_REG_READ(SPI_CTRL_REG) & SPI_STAT_MASK) == SPI_ACTIVE)
+		continue;
+
+	/* Read the data received from codec */
+	data = MV_REG_READ(SPI_CODEC_READ_DATA_REG);
+	dataBuff[dataSize - 1] = (data & 0xff);
+
+	if (dataSize == 2)
+		dataBuff[0] = ((data & 0xff00) >> 8);
+
+	return MV_OK;
+}
+
+/******************
+** Debug Display **
+******************/
+MV_VOID mvOsRegDump(MV_U32 reg)
+{
+	mvOsPrintf("0x%05x: %08x\n", reg, MV_REG_READ(reg));
+}
+
+MV_VOID mvTdmRegsDump(MV_VOID)
+{
+	MV_U8 i;
+	MV_TDM_CH_INFO *chInfo;
+
+	mvOsPrintf("TDM Control:\n");
+	mvOsRegDump(TDM_SPI_MUX_REG);
+	mvOsRegDump(INT_RESET_SELECT_REG);
+	mvOsRegDump(INT_STATUS_MASK_REG);
+	mvOsRegDump(INT_STATUS_REG);
+	mvOsRegDump(INT_EVENT_MASK_REG);
+	mvOsRegDump(PCM_CTRL_REG);
+	mvOsRegDump(TIMESLOT_CTRL_REG);
+	mvOsRegDump(PCM_CLK_RATE_DIV_REG);
+	mvOsRegDump(FRAME_TIMESLOT_REG);
+	mvOsRegDump(DUMMY_RX_WRITE_DATA_REG);
+	mvOsRegDump(MISC_CTRL_REG);
+	mvOsPrintf("TDM Channel Control:\n");
+	for (i = 0; i < MV_TDM_TOTAL_CHANNELS; i++) {
+		mvOsRegDump(CH_DELAY_CTRL_REG(i));
+		mvOsRegDump(CH_SAMPLE_REG(i));
+		mvOsRegDump(CH_DBG_REG(i));
+		mvOsRegDump(CH_TX_CUR_ADDR_REG(i));
+		mvOsRegDump(CH_RX_CUR_ADDR_REG(i));
+		mvOsRegDump(CH_ENABLE_REG(i));
+		mvOsRegDump(CH_BUFF_OWN_REG(i));
+		mvOsRegDump(CH_TX_ADDR_REG(i));
+		mvOsRegDump(CH_RX_ADDR_REG(i));
+	}
+	mvOsPrintf("TDM interrupts:\n");
+	mvOsRegDump(INT_EVENT_MASK_REG);
+	mvOsRegDump(INT_STATUS_MASK_REG);
+	mvOsRegDump(INT_STATUS_REG);
+	for (i = 0; i < MV_TDM_TOTAL_CHANNELS; i++) {
+		mvOsPrintf("ch%d info:\n", i);
+		chInfo = tdmChInfo[i];
+		mvOsPrintf("RX buffs:\n");
+		mvOsPrintf("buff0: virt=%p phys=%p\n", chInfo->rxBuffVirt[0], (MV_U32 *) (chInfo->rxBuffPhys[0]));
+		mvOsPrintf("buff1: virt=%p phys=%p\n", chInfo->rxBuffVirt[1], (MV_U32 *) (chInfo->rxBuffPhys[1]));
+		mvOsPrintf("TX buffs:\n");
+		mvOsPrintf("buff0: virt=%p phys=%p\n", chInfo->txBuffVirt[0], (MV_U32 *) (chInfo->txBuffPhys[0]));
+		mvOsPrintf("buff1: virt=%p phys=%p\n", chInfo->txBuffVirt[1], (MV_U32 *) (chInfo->txBuffPhys[1]));
+	}
+}
+
+static MV_VOID mvTdmShowProperties(MV_VOID)
+{
+	mvOsPrintf("TDM dual channel device rev 0x%x\n", MV_REG_READ(TDM_REV_REG));
+}
+
+MV_U8 currRxSampleGet(MV_U8 ch)
+{
+	return (MV_REG_BYTE_READ(CH_DBG_REG(ch) + 1));
+}
+
+MV_U8 currTxSampleGet(MV_U8 ch)
+{
+	return (MV_REG_BYTE_READ(CH_DBG_REG(ch) + 3));
+}
+
+MV_VOID mvTdmIntEnable(MV_VOID)
+{
+	MV_REG_WRITE(INT_STATUS_MASK_REG, (MV_REG_READ(INT_STATUS_MASK_REG) | TDM_INT_SLIC));
+}
+
+MV_VOID mvTdmIntDisable(MV_VOID)
+{
+	MV_U32 val = ~TDM_INT_SLIC;
+
+	MV_TRC_REC("->%s\n", __func__);
+
+	MV_REG_WRITE(INT_STATUS_MASK_REG, (MV_REG_READ(INT_STATUS_MASK_REG) & val));
+
+	MV_TRC_REC("<-%s\n", __func__);
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.h b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.h
new file mode 100755
index 0000000..3909a7f
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdm.h
@@ -0,0 +1,183 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvTdmh
+#define __INCmvTdmh
+
+#include "voiceband/tdm/mvTdmRegs.h"
+#include "voiceband/mvSysTdmSpi.h"
+#include "mvSysTdmConfig.h"
+
+/* Defines */
+#define SAMPLES_BUFF_SIZE(bandMode, factor)  \
+	 ((bandMode == MV_NARROW_BAND) ? (factor * 80) : (factor * 160))
+
+#define MV_TDM_CH_BUFF_SIZE(pcmFormat, bandMode, factor) \
+	(pcmFormat == MV_PCM_FORMAT_2BYTES ? (2 * SAMPLES_BUFF_SIZE(bandMode, factor)) : \
+						  SAMPLES_BUFF_SIZE(bandMode, factor))
+
+#define MV_TDM_AGGR_BUFF_SIZE(pcmFormat, bandMode, factor)	(2 * MV_TDM_CH_BUFF_SIZE(pcmFormat, bandMode, factor))
+#define MV_TDM_TOTAL_CHANNELS					2
+#define MV_TDM_INT_COUNTER					2
+#define MV_TDM_MAX_SAMPLING_PERIOD				30	/* ms */
+#define MV_TDM_BASE_SAMPLING_PERIOD				10	/* ms */
+#define MV_TDM_TOTAL_CH_SAMPLES					80	/* samples */
+
+/* TDM IRQ types */
+#define MV_EMPTY_INT		0
+#define MV_RX_INT 		BIT0
+#define	MV_TX_INT 		BIT1
+#define	MV_PHONE_INT 		BIT2
+#define	MV_RX_ERROR_INT 	BIT3
+#define	MV_TX_ERROR_INT 	BIT4
+#define MV_DMA_ERROR_INT	BIT5
+#define MV_ERROR_INT		(MV_RX_ERROR_INT | MV_TX_ERROR_INT | MV_DMA_ERROR_INT)
+
+/* PCM SLOT configuration */
+
+#define PCM_SLOT_PCLK	8
+
+#define TDM_INT_SLIC	(DMA_ABORT_BIT|SLIC_INT_BIT)
+#define TDM_INT_TX(ch)	(TX_UNDERFLOW_BIT(ch)|TX_BIT(ch)|TX_IDLE_BIT(ch))
+#define TDM_INT_RX(ch)	(RX_OVERFLOW_BIT(ch)|RX_BIT(ch)|RX_IDLE_BIT(ch))
+
+/* TDM Registers Configuration */
+#if defined(MV_TDM_USE_EXTERNAL_PCLK_SOURCE)
+#define CONFIG_PCM_CRTL (MASTER_PCLK_EXTERNAL | MASTER_FS_TDM | DATA_POLAR_NEG | \
+			 FS_POLAR_NEG | INVERT_FS_HI | FS_TYPE_SHORT	 | \
+			 CH_DELAY_ENABLE 		 		 | \
+			 CH_QUALITY_DISABLE | QUALITY_POLARITY_NEG	 | \
+			 QUALITY_TYPE_TIME_SLOT | CS_CTRL_DONT_CARE 	 | \
+			 WIDEBAND_OFF | PERF_GBUS_TWO_ACCESS)
+
+#else
+#define CONFIG_PCM_CRTL (MASTER_PCLK_TDM | MASTER_FS_TDM | DATA_POLAR_NEG | \
+			 FS_POLAR_NEG | INVERT_FS_HI | FS_TYPE_SHORT	 | \
+			 CH_DELAY_ENABLE 				 | \
+			 CH_QUALITY_DISABLE | QUALITY_POLARITY_NEG	 | \
+			 QUALITY_TYPE_TIME_SLOT | CS_CTRL_DONT_CARE 	 | \
+			 WIDEBAND_OFF | PERF_GBUS_TWO_ACCESS)
+#endif
+
+#if defined(MV_TDM_USE_EXTERNAL_PCLK_SOURCE)
+#define CONFIG_WB_PCM_CRTL (MASTER_PCLK_EXTERNAL | MASTER_FS_TDM | DATA_POLAR_NEG | \
+			    FS_POLAR_NEG | INVERT_FS_HI | FS_TYPE_SHORT	 | \
+			    CH_DELAY_ENABLE 				 | \
+			    CH_QUALITY_DISABLE | QUALITY_POLARITY_NEG	 | \
+			    QUALITY_TYPE_TIME_SLOT | CS_CTRL_DONT_CARE 	 | \
+			    WIDEBAND_ON | PERF_GBUS_TWO_ACCESS)
+#else
+#define CONFIG_WB_PCM_CRTL (MASTER_PCLK_TDM | MASTER_FS_TDM | DATA_POLAR_NEG | \
+			    FS_POLAR_NEG | INVERT_FS_HI | FS_TYPE_SHORT	 | \
+			    CH_DELAY_ENABLE 				 | \
+			    CH_QUALITY_DISABLE | QUALITY_POLARITY_NEG	 | \
+			    QUALITY_TYPE_TIME_SLOT | CS_CTRL_DONT_CARE 	 | \
+			    WIDEBAND_ON | PERF_GBUS_TWO_ACCESS)
+#endif
+
+#define CONFIG_CH_SAMPLE(bandMode, factor) ((SAMPLES_BUFF_SIZE(bandMode, factor)<<TOTAL_CNT_OFFS) |\
+									 (INT_SAMPLE<<INT_CNT_OFFS))
+
+/* Enumerators */
+
+/* Structures */
+typedef struct {
+	MV_U8 *tdmRxBuff;
+	MV_U8 *tdmTxBuff;
+	MV_U32 intType;
+	MV_U8 cs;
+} MV_TDM_INT_INFO;
+
+typedef struct {
+	MV_PCM_FORMAT pcmFormat;
+	MV_U16 pcmSlot[32];
+	MV_U8 samplingPeriod;
+	MV_U16 totalChannels;
+} MV_TDM_PARAMS;
+
+typedef struct {
+	MV_U8 spiMode;
+	MV_U8 maxCs;
+	MV_U16 model;
+	MV_U16 ctrlRev;
+	MV_FRAME_TS frameTs;
+} MV_TDM_HAL_DATA;
+
+/* APIs */
+MV_STATUS mvTdmHalInit(MV_TDM_PARAMS *tdmParams, MV_TDM_HAL_DATA *halData);
+MV_STATUS mvTdmWinInit(MV_UNIT_WIN_INFO *addrWinMap);
+MV_VOID mvTdmRelease(MV_VOID);
+MV_VOID mvTdmIntLow(MV_TDM_INT_INFO *tdmIntInfo);
+MV_VOID mvTdmPcmStart(MV_VOID);
+MV_VOID mvTdmPcmStop(MV_VOID);
+MV_STATUS mvTdmTx(MV_U8 *tdmTxBuff);
+MV_STATUS mvTdmRx(MV_U8 *tdmRxBuff);
+MV_VOID mvTdmRegsDump(MV_VOID);
+MV_STATUS mvTdmSpiRead(MV_U8 *cmdBuff, MV_U8 cmdSize, MV_U8 *dataBuff, MV_U8 dataSize, MV_U8 cs);
+MV_STATUS mvTdmSpiWrite(MV_U8 *cmdBuff, MV_U8 cmdSize, MV_U8 *dataBuff, MV_U8 dataSize, MV_U8 cs);
+MV_U8 currRxSampleGet(MV_U8 ch);
+MV_U8 currTxSampleGet(MV_U8 ch);
+MV_VOID mvTdmIntEnable(MV_VOID);
+MV_VOID mvTdmIntDisable(MV_VOID);
+#endif /* __INCmvTdmh */
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdmAddrDec.c b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdmAddrDec.c
new file mode 100755
index 0000000..8e63395
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdmAddrDec.c
@@ -0,0 +1,331 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "voiceband/tdm/mvTdmRegs.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+static MV_TARGET tdmAddrDecPrioTable[] = {
+	SDRAM_CS0,
+	SDRAM_CS1,
+	SDRAM_CS2,
+	SDRAM_CS3,
+	PEX0_MEM,
+	PEX0_IO,
+	TBL_TERM
+};
+
+static MV_STATUS mvTdmWinRead(MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin);
+static MV_STATUS mvTdmWinWrite(MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin);
+static INLINE MV_VOID mvTdmWinEnable(int winNum, MV_BOOL enable);
+static MV_STATUS tdmWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
+
+/*******************************************************************************
+* mvTdmWinInit - Initialize TDM address decode windows
+*
+* DESCRIPTION:
+*               This function initialize TDM window decode unit. It set the
+*               default address decode
+*               windows of the unit.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if setting fail.
+*******************************************************************************/
+MV_STATUS mvTdmWinInit(MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 winNum;
+	MV_U32 winPrioIndex = 0;
+	MV_UNIT_WIN_INFO *addrDecWin;
+
+	/*Disable all windows */
+	for (winNum = 0; winNum < TDM_MBUS_MAX_WIN; winNum++)
+		mvTdmWinEnable(winNum, MV_FALSE);
+
+	for (winNum = 0; ((tdmAddrDecPrioTable[winPrioIndex] != TBL_TERM) && (winNum < TDM_MBUS_MAX_WIN));) {
+		addrDecWin = &addrWinMap[tdmAddrDecPrioTable[winPrioIndex]];
+
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvTdmWinWrite(winNum, addrDecWin)) {
+				mvOsPrintf("mvTdmWinWrite: failed setting window(%d)\n", winNum);
+				return MV_ERROR;
+			}
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvTdmWinWrite - Set TDM target address window
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0)
+*       address window, also known as address decode window.
+*       After setting this target window, the TDM will be able to access the
+*       target within the address window.
+*
+* INPUT:
+*       winNum      - TDM to target address decode window number.
+*       pDecWin     - TDM target window data structure.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_ERROR if address window overlapps with other address decode windows.
+*       MV_BAD_PARAM if base address is invalid parameter or target is
+*       unknown.
+*
+*******************************************************************************/
+static MV_STATUS mvTdmWinWrite(MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin)
+{
+	MV_U32 ctrlReg = 0, baseReg = 0;
+	MV_U32 size;
+
+	/* Parameter checking   */
+	if (winNum >= TDM_MBUS_MAX_WIN) {
+		mvOsPrintf("mvTdmWinWrite: ERR. Invalid win num %d\n", winNum);
+		return MV_BAD_PARAM;
+	}
+
+	/* Check if the requested window overlapps with current windows         */
+	if (MV_TRUE == tdmWinOverlapDetect(winNum, &pDecWin->addrWin)) {
+		mvOsPrintf("mvTdmWinWrite: ERR. Window %d overlap\n", winNum);
+		return MV_ERROR;
+	}
+
+	/* check if address is aligned to the size */
+	if (MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) {
+		mvOsPrintf("mvTdmWinWrite: Error setting TDM window %d"
+			   "\nAddress 0x%08x is unaligned to size 0x%x.\n",
+			   winNum, pDecWin->addrWin.baseLow, pDecWin->addrWin.size);
+		return MV_ERROR;
+	}
+
+	size = (pDecWin->addrWin.size / MV_TDM_WIN_SIZE_ALIGN) - 1;
+
+	/* for the safe side we disable the window before writing the new
+	   values */
+	mvTdmWinEnable(winNum, MV_FALSE);
+
+	ctrlReg |= ((pDecWin->attrib << TDM_WIN_ATTRIB_OFFS) & TDM_WIN_ATTRIB_MASK);
+	ctrlReg |= ((pDecWin->targetId << TDM_WIN_TARGET_OFFS) & TDM_WIN_TARGET_MASK);
+	ctrlReg |= ((size << TDM_WIN_SIZE_OFFS) & TDM_WIN_SIZE_MASK);
+
+	/* Update Base value  */
+	baseReg = (pDecWin->addrWin.baseLow & TDM_BASE_MASK);
+
+	/* Write to address base and control registers  */
+	MV_REG_WRITE(TDM_WIN_BASE_REG(winNum), baseReg);
+	MV_REG_WRITE(TDM_WIN_CTRL_REG(winNum), ctrlReg);
+
+	/* Enable address decode target window  */
+	if (pDecWin->enable == MV_TRUE)
+		mvTdmWinEnable(winNum, MV_TRUE);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvTdmWinRead - Read peripheral target address window.
+*
+* DESCRIPTION:
+*               Read TDM peripheral target address window.
+*
+* INPUT:
+*       winNum - TDM to target address decode window number.
+*
+* OUTPUT:
+*       pDecWin - TDM target window data structure.
+*
+* RETURN:
+*       MV_ERROR if register parameters are invalid.
+*
+*******************************************************************************/
+static MV_STATUS mvTdmWinRead(MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin)
+{
+
+	MV_U32 ctrlReg, baseReg;
+	MV_U32 size;
+
+	/* Parameter checking   */
+	if (winNum >= TDM_MBUS_MAX_WIN) {
+		mvOsPrintf("mvTdmWinRead: ERR. Invalid winNum %d\n", winNum);
+		return MV_NOT_SUPPORTED;
+	}
+
+	baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum));
+	ctrlReg = MV_REG_READ(TDM_WIN_CTRL_REG(winNum));
+
+	/* Check if window is enabled   */
+	if (ctrlReg & TDM_WIN_ENABLE_MASK) {
+		pDecWin->enable = MV_TRUE;
+
+		/* Extract window parameters from registers */
+		pDecWin->targetId = (ctrlReg & TDM_WIN_TARGET_MASK) >> TDM_WIN_TARGET_OFFS;
+		pDecWin->attrib = (ctrlReg & TDM_WIN_ATTRIB_MASK) >> TDM_WIN_ATTRIB_OFFS;
+
+		size = (ctrlReg & TDM_WIN_SIZE_MASK) >> TDM_WIN_SIZE_OFFS;
+		pDecWin->addrWin.size = (size + 1) * MV_TDM_WIN_SIZE_ALIGN;
+		pDecWin->addrWin.baseLow = (baseReg & TDM_BASE_MASK);
+		pDecWin->addrWin.baseHigh = 0;
+	} else {
+		pDecWin->enable = MV_FALSE;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvTdmWinEnable - Enable/disable a TDM to target address window
+*
+* DESCRIPTION:
+*       This function enable/disable a TDM to target address window.
+*       According to parameter 'enable' the routine will enable the
+*       window, thus enabling TDM accesses.
+*       Otherwise, the window will be disabled.
+*
+* INPUT:
+*       winNum - TDM to target address decode window number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       N/A
+*
+* RETURN:
+*       MV_ERROR if decode window number was wrong or enabled window overlapps.
+*
+*******************************************************************************/
+static INLINE MV_VOID mvTdmWinEnable(int winNum, MV_BOOL enable)
+{
+	if (enable == MV_TRUE)
+		MV_REG_BIT_SET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK);
+	else
+		MV_REG_BIT_RESET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK);
+}
+
+/*******************************************************************************
+* tdmWinOverlapDetect - Detect TDM address windows overlapping
+*
+* DESCRIPTION:
+*       An unpredicted behaviour is expected in case TDM address decode
+*       windows overlapps.
+*       This function detects TDM address decode windows overlapping of a
+*       specified window. The function does not check the window itself for
+*       overlapping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pDecWin     - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS tdmWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 winNumIndex;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	for (winNumIndex = 0; winNumIndex < TDM_MBUS_MAX_WIN; winNumIndex++) {
+		/* Do not check window itself       */
+		if (winNumIndex == winNum)
+			continue;
+
+		/* Get window parameters    */
+		if (MV_OK != mvTdmWinRead(winNumIndex, &addrDecWin)) {
+			mvOsPrintf("%s: ERR. TargetWinGet failed\n", __func__);
+			return MV_ERROR;
+		}
+
+		/* Do not check disabled windows    */
+		if (addrDecWin.enable == MV_FALSE)
+			continue;
+
+		if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+			return MV_TRUE;
+	}
+
+	return MV_FALSE;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdmRegs.h b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdmRegs.h
new file mode 100755
index 0000000..f8ade9a
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/voiceband/tdm/mvTdmRegs.h
@@ -0,0 +1,300 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef __INCmvTdmRegsh
+#define __INCmvTdmRegsh
+
+#include "mvSysTdmConfig.h"
+
+/************************************************/
+/*        TDM to Mbus Bridge Register Map       */
+/************************************************/
+#define TDM_SPI_MUX_REG		(MV_TDM_REGS_BASE + 0x4000)
+#define TDM_MBUS_CONFIG_REG	(MV_TDM_REGS_BASE + 0x4010)
+#define TDM_MISC_REG		(MV_TDM_REGS_BASE + 0x4070)
+#define TDM_CLK_DIV_REG		(MV_TDM_REGS_BASE + 0x4074)
+
+/*****************************************/
+/*        TDM Control Register Map       */
+/*****************************************/
+#define PCM_CTRL_REG		 MV_TDM_REGS_BASE
+#define TIMESLOT_CTRL_REG	(MV_TDM_REGS_BASE + 0x4)
+#define FRAME_TIMESLOT_REG	(MV_TDM_REGS_BASE + 0x38)
+#define PCM_CLK_RATE_DIV_REG	(MV_TDM_REGS_BASE + 0x3c)
+#define INT_EVENT_MASK_REG	(MV_TDM_REGS_BASE + 0x40)
+/*#define INT_EVENT_REG         0xb0044*/
+#define INT_STATUS_MASK_REG	(MV_TDM_REGS_BASE + 0x48)
+#define INT_RESET_SELECT_REG	(MV_TDM_REGS_BASE + 0x4c)
+#define INT_STATUS_REG		(MV_TDM_REGS_BASE + 0x50)
+#define DUMMY_RX_WRITE_DATA_REG (MV_TDM_REGS_BASE + 0x54)
+#define MISC_CTRL_REG		(MV_TDM_REGS_BASE + 0x58)
+#define TESTBUS_MUX_SELECT_REG	(MV_TDM_REGS_BASE + 0x5c)
+#define CUR_TIMESLOT_REG	(MV_TDM_REGS_BASE + 0x70)
+#define TDM_REV_REG		(MV_TDM_REGS_BASE + 0x74)
+#define DMA_ABORT_ADDR_REG	(MV_TDM_REGS_BASE + 0x80)
+#define DMA_ABORT_INFO_REG	(MV_TDM_REGS_BASE + 0x84)
+
+#define CH_WB_DELAY_CTRL_REG(ch) ((MV_TDM_REGS_BASE + 0x88) | ((ch)<<2))
+#define CH_DELAY_CTRL_REG(ch)	((MV_TDM_REGS_BASE + 0x8) | ((ch)<<2))
+#define CH_SAMPLE_REG(ch)	((MV_TDM_REGS_BASE + 0x30) | ((ch)<<2))
+#define CH_DBG_REG(ch)		((MV_TDM_REGS_BASE + 0x78) | ((ch)<<2))
+#define CH_TX_CUR_ADDR_REG(ch)	((MV_TDM_REGS_BASE + 0x60) | ((ch)<<3))
+#define CH_RX_CUR_ADDR_REG(ch)	((MV_TDM_REGS_BASE + 0x64) | ((ch)<<3))
+#define CH_ENABLE_REG(ch)	((MV_TDM_REGS_BASE) | (((ch)+1)<<4))
+#define CH_BUFF_OWN_REG(ch)	((MV_TDM_REGS_BASE + 0x4) | (((ch)+1)<<4))
+#define CH_TX_ADDR_REG(ch)	((MV_TDM_REGS_BASE + 0x8) | (((ch)+1)<<4))
+#define CH_RX_ADDR_REG(ch)	((MV_TDM_REGS_BASE + 0xc) | (((ch)+1)<<4))
+
+/* PCM_CLK_RATE_DIV_REG bits */
+#define PCM_256KHZ	1
+#define PCM_512KHZ	(1<<1)
+#define PCM_1024KHZ	(1<<2)
+#define PCM_2048KHZ	(1<<3)
+#define PCM_4096KHZ	(1<<4)
+#define PCM_8192KHZ	(1<<5)
+#define PCM_DIV_PASS	(1<<6)
+
+/* FRAME_TIMESLOT_REG bits */
+#define TIMESLOTS4_256KHZ	(1<<2)
+#define TIMESLOTS8_512KHZ	(1<<3)
+#define TIMESLOTS16_1024KHZ	(1<<4)
+#define TIMESLOTS32_2048KHZ	(1<<5)
+#define TIMESLOTS64_4096KHZ	(1<<6)
+#define TIMESLOTS128_8192KHZ	(1<<7)
+
+/* PCM_CTRL_REG bits */
+#define MASTER_PCLK_OFFS	0
+#define MASTER_PCLK_TDM		(0<<MASTER_PCLK_OFFS)
+#define MASTER_PCLK_EXTERNAL	(1<<MASTER_PCLK_OFFS)
+#define MASTER_FS_OFFS		1
+#define MASTER_FS_TDM		(0<<MASTER_FS_OFFS)
+#define MASTER_FS_EXTERNAL	(1<<MASTER_FS_OFFS)
+#define DATA_POLAR_OFFS		2
+#define DATA_POLAR_NEG		(0<<DATA_POLAR_OFFS)
+#define DATA_POLAR_POS		(1<<DATA_POLAR_OFFS)
+#define FS_POLAR_OFFS		3
+#define FS_POLAR_NEG		(0<<FS_POLAR_OFFS)
+#define FS_POLAR_POS		(1<<FS_POLAR_OFFS)
+#define INVERT_FS_OFFS		4
+#define INVERT_FS_HI		(0<<INVERT_FS_OFFS)
+#define INVERT_FS_LO		(1<<INVERT_FS_OFFS)
+#define FS_TYPE_OFFS		5
+#define FS_TYPE_SHORT		(0<<FS_TYPE_OFFS)
+#define FS_TYPE_LONG		(1<<FS_TYPE_OFFS)
+#define PCM_SAMPLE_SIZE_OFFS	6
+#define PCM_SAMPLE_SIZE_1	(0<<PCM_SAMPLE_SIZE_OFFS)
+#define PCM_SAMPLE_SIZE_2	(1<<PCM_SAMPLE_SIZE_OFFS)
+#define CH_DELAY_OFFS		8
+#define CH_DELAY_DISABLE	(0<<CH_DELAY_OFFS)
+#define CH_DELAY_ENABLE		(3<<CH_DELAY_OFFS)
+#define CH_QUALITY_OFFS		10
+#define CH_QUALITY_DISABLE	(0<<CH_QUALITY_OFFS)
+#define CH_QUALITY_ENABLE	(3<<CH_QUALITY_OFFS)
+#define QUALITY_POLARITY_OFFS	12
+#define QUALITY_POLARITY_NEG	(0<<QUALITY_POLARITY_OFFS)
+#define QUALITY_POLARITY_POS	(1<<QUALITY_POLARITY_OFFS)
+#define QUALITY_TYPE_OFFS	13
+#define QUALITY_TYPE_TIME_SLOT	(0<<QUALITY_TYPE_OFFS)
+#define QUALITY_TYPE_MSB	(3<<QUALITY_TYPE_OFFS)
+#define CS_CTRL_OFFS		15
+#define CS_CTRL_DONT_CARE	(0<<CS_CTRL_OFFS)
+#define CS_CTRL			(1<<CS_CTRL_OFFS)
+#define CS_CTRL_0		(0<<CS_CTRL_OFFS)
+#define CS_CTRL_1		(1<<CS_CTRL_OFFS)
+#define WIDEBAND_OFFS		16
+#define WIDEBAND_OFF		(0<<WIDEBAND_OFFS)
+#define WIDEBAND_ON		(3<<WIDEBAND_OFFS)
+#define PERF_GBUS_OFFS		31
+#define PERF_GBUS_ONE_ACCESS	(0<<PERF_GBUS_OFFS)
+#define PERF_GBUS_TWO_ACCESS	(1<<PERF_GBUS_OFFS)
+
+/* TIMESLOT_CTRL_REG bits */
+#define CH0_RX_SLOT_OFFS	0
+#define CH0_TX_SLOT_OFFS	8
+#define CH1_RX_SLOT_OFFS	16
+#define CH1_TX_SLOT_OFFS	24
+
+/* CH_SAMPLE_REG bits */
+#define TOTAL_CNT_OFFS		0
+#define TOTAL_CNT_MASK		(0xff<<TOTAL_CNT_OFFS)
+#define INT_CNT_OFFS		8
+#define INT_CNT_MASK		(0xff<<INT_CNT_OFFS)
+
+/* CH_BUFF_OWN_REG bits */
+#define RX_OWN_BYTE_OFFS	0
+#define TX_OWN_BYTE_OFFS	1
+#define OWNER_MASK		1
+#define OWN_BY_SW		0
+#define OWN_BY_HW		1
+
+/* CH_ENABLE_REG bits */
+#define RX_ENABLE_BYTE_OFFS	0
+#define TX_ENABLE_BYTE_OFFS	1
+#define CH_ENABLE		1
+#define CH_DISABLE		0
+
+/* INT_STATUS_REG bits */
+#define RX_OVERFLOW_BIT(ch)	(1<<(0+(ch)*2))
+#define TX_UNDERFLOW_BIT(ch)	(1<<(1+((ch)*2)))
+#define RX_BIT(ch)		(1<<(4+((ch)*2)))
+#define TX_BIT(ch)		(1<<(5+((ch)*2)))
+#define RX_IDLE_BIT(ch)		(1<<(8+((ch)*2)))
+#define TX_IDLE_BIT(ch)		(1<<(9+((ch)*2)))
+#define RX_FIFO_FULL(ch)	(1<<(12+((ch)*2)))
+#define TX_FIFO_EMPTY(ch)	(1<<(13+((ch)*2)))
+#define DMA_ABORT_BIT		(1<<16)
+#define SLIC_INT_BIT		(1<<17)
+
+/* TDU_INTR_SET_RESET bits */
+#define CLEAR_MODE_OFFS		0
+#define CLEAR_ON_READ		(1<<CLEAR_MODE_OFFS)
+#define CLEAR_ON_ZERO		(0<<CLEAR_MODE_OFFS)
+
+/* CH_DELAY_CTRL_REG bits */
+#define CH_RX_DELAY_OFFS	0
+#define CH_RX_DELAY_MASK	(0x3ff<<CH_RX_DELAY_OFFS)
+#define CH_TX_DELAY_OFFS	16
+#define CH_TX_DELAY_MASK	(0x3ff<<CH_RX_DELAY_OFFS)
+
+
+/*********************************/
+/*        SPI Register Map       */
+/*********************************/
+#define SPI_CLK_PRESCALAR_REG	(MV_TDM_REGS_BASE + 0x3100)
+#define SPI_GLOBAL_CTRL_REG	(MV_TDM_REGS_BASE + 0x3104)
+#define SPI_CTRL_REG		(MV_TDM_REGS_BASE + 0x3108)
+#define SPI_MICRO_WIRE_CTRL_REG	(MV_TDM_REGS_BASE + 0x310c)
+#define SPI_TWSI_CTRL_REG	(MV_TDM_REGS_BASE + 0x3110)
+#define SPI_MV_STATUS_REG	(MV_TDM_REGS_BASE + 0x311c)
+#define SPI_INT_MASK_REG	(MV_TDM_REGS_BASE + 0x3120)
+#define SPI_DATA_REG		(MV_TDM_REGS_BASE + 0x3124)
+#define SPI_ADDR_REG		(MV_TDM_REGS_BASE + 0x3128)
+#define SPI_CODEC_CMD_LO_REG	(MV_TDM_REGS_BASE + 0x3130)
+#define SPI_CODEC_CMD_HI_REG	(MV_TDM_REGS_BASE + 0x3134)
+#define SPI_CODEC_CTRL_REG	(MV_TDM_REGS_BASE + 0x3138)
+#define SPI_CODEC_READ_DATA_REG	(MV_TDM_REGS_BASE + 0x313c)
+
+/* SPI CLK_PRESCALAR_REG bits */
+#define SPI_CLK_2MHZ	0x2A64  /* refers to tclk = 200MHz */
+#define SPI_CLK_4MHZ	0x2A32  /* refers to tclk = 200MHz */
+#define SPI_CLK_8MHZ	0x2A19  /* refers to tclk = 200MHz */
+
+/* SPI_CTRL_REG bits */
+#define SPI_STAT_OFFS	10
+#define SPI_STAT_MASK	(1<<SPI_STAT_OFFS)
+#define SPI_READY	(0<<SPI_STAT_OFFS)
+#define SPI_ACTIVE	(1<<SPI_STAT_OFFS)
+
+/* SPI_GLOBAL_CTRL_REG bits */
+#define SPI_GLOBAL_ENABLE_OFFS	0
+#define SPI_GLOBAL_ENABLE_MASK	(1<<SPI_GLOBAL_ENABLE_OFFS)
+#define SPI_GLOBAL_DISABLE	(0<<SPI_GLOBAL_ENABLE_OFFS)
+#define SPI_GLOBAL_ENABLE	(1<<SPI_GLOBAL_ENABLE_OFFS)
+
+/* SPI_CODEC_CTRL_REG bits */
+#define TRANSFER_BYTES_OFFS	0
+#define TRANSFER_BYTES(count)	((count-1)<<TRANSFER_BYTES_OFFS)
+#define ENDIANESS_MODE_OFFS	2
+#define ENDIANESS_MSB_MODE	(0<<ENDIANESS_MODE_OFFS)
+#define ENDIANESS_LSB_MODE	(1<<ENDIANESS_MODE_OFFS)
+#define RD_WR_MODE_OFFS		3
+#define WR_MODE			(0<<RD_WR_MODE_OFFS)
+#define RD_MODE			(1<<RD_WR_MODE_OFFS)
+#define READ_BYTES_OFFS		4
+#define READ_1_BYTE		(0<<READ_BYTES_OFFS)
+#define READ_2_BYTE		(1<<READ_BYTES_OFFS)
+#define CLK_SPEED_OFFS		5
+#define CLK_SPEED_LO_DIV	(0<<CLK_SPEED_OFFS)
+#define CLK_SPEED_HI_DIV	(1<<CLK_SPEED_OFFS)
+#define CS_HI_CNT_VAL_RD_OFFS	6
+#define CS_HI_CNT_VAL_RD_MASK	(0xff3<<CS_HI_CNT_VAL_RD_OFFS)
+
+/*********************************/
+/*        TDM Address Decoding   */
+/*********************************/
+
+#define TDM_MBUS_MAX_WIN	4
+#define TDM_WIN_CTRL_REG(win)	((MV_TDM_REGS_BASE + 0x4030) + (win<<4))
+#define TDM_WIN_BASE_REG(win)	((MV_TDM_REGS_BASE + 0x4034) + (win<<4))
+
+/* TDM_WIN_CTRL_REG bits */
+#define TDM_WIN_ENABLE_OFFS	0
+#define TDM_WIN_ENABLE_MASK	(1<<TDM_WIN_ENABLE_OFFS)
+#define TDM_WIN_ENABLE		1
+#define TDM_WIN_TARGET_OFFS	4
+#define TDM_WIN_TARGET_MASK	(0xf<<TDM_WIN_TARGET_OFFS)
+#define TDM_WIN_ATTRIB_OFFS	8
+#define TDM_WIN_ATTRIB_MASK	(0xff<<TDM_WIN_ATTRIB_OFFS)
+#define TDM_WIN_SIZE_OFFS	16
+#define TDM_WIN_SIZE_MASK	(0xffff<<TDM_WIN_SIZE_OFFS)
+
+/* TDM_WIN_BASE_REG bits */
+#define TDM_BASE_OFFS		16
+#define TDM_BASE_MASK		(0xffff<<TDM_BASE_OFFS)
+
+#define MV_TDM_WIN_SIZE_ALIGN	_64K
+
+
+#endif /*__INCmvTdmRegsh*/
+
diff --git a/arch/arm/plat-feroceon/mv_hal/xor/mvCompVer.txt b/arch/arm/plat-feroceon/mv_hal/xor/mvCompVer.txt
new file mode 100755
index 0000000..85bfa61
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/xor/mvCompVer.txt
@@ -0,0 +1,4 @@
+Global HAL Version: FEROCEON_HAL_3_1_7

+Unit HAL Version: 3.1.3

+Description: This component includes an implementation of the unit HAL drivers

+

diff --git a/arch/arm/plat-feroceon/mv_hal/xor/mvXor.c b/arch/arm/plat-feroceon/mv_hal/xor/mvXor.c
new file mode 100755
index 0000000..d1e6cf2
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/xor/mvXor.c
@@ -0,0 +1,586 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysXorConfig.h"
+#include "mvXorRegs.h"
+#include "mvXor.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+/*******************************************************************************
+* mvXorHalInit - Initialize XOR engine
+*
+* DESCRIPTION:
+*               This function initialize XOR unit.
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*******************************************************************************/
+MV_VOID mvXorHalInit(MV_U32 xorChanNum)
+{
+	MV_U32 i;
+	/* Abort any XOR activity & set default configuration */
+	for (i = 0; i < xorChanNum; i++) {
+		mvXorCommandSet(i, MV_STOP);
+		mvXorCtrlSet(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
+			     (4 << XEXCR_DST_BURST_LIMIT_OFFS) | (4 << XEXCR_SRC_BURST_LIMIT_OFFS)
+#if defined(MV_CPU_BE)
+/*				| (1 << XEXCR_DRD_RES_SWP_OFFS)
+				| (1 << XEXCR_DWR_REQ_SWP_OFFS)
+*/
+			     | (1 << XEXCR_DES_SWP_OFFS)
+#endif
+		    );
+	}
+
+}
+
+/*******************************************************************************
+* mvXorCtrlSet - Set XOR channel control registers
+*
+* DESCRIPTION:
+*
+* INPUT:
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+* NOTE:
+*    This function does not modify the OperationMode field of control register.
+*
+*******************************************************************************/
+MV_STATUS mvXorCtrlSet(MV_U32 chan, MV_U32 xorCtrl)
+{
+	MV_U32 oldValue;
+
+	/* update the XOR Engine [0..1] Configuration Registers (XExCR) */
+	oldValue = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)))
+	    & XEXCR_OPERATION_MODE_MASK;
+	xorCtrl &= ~XEXCR_OPERATION_MODE_MASK;
+	xorCtrl |= oldValue;
+	MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xorCtrl);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorEccClean - .
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       destPtr -
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*
+*******************************************************************************/
+MV_STATUS mvXorEccClean(MV_U32 chan, MV_XOR_ECC *pXorEccConfig)
+{
+	MV_U32 tClkCycles;
+	MV_U32 temp;
+
+	/* Parameter checking   */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+		return MV_BAD_PARAM;
+	}
+	if (NULL == pXorEccConfig) {
+		DB(mvOsPrintf("%s: ERR. pXorEccConfig is NULL pointer\n", __func__));
+		return MV_BAD_PTR;
+	}
+	if (MV_ACTIVE == mvXorStateGet(chan)) {
+		DB(mvOsPrintf("%s: ERR. Channel is already active\n", __func__));
+		return MV_BUSY;
+	}
+	if ((pXorEccConfig->sectorSize < XETMCR_SECTION_SIZE_MIN_VALUE) ||
+	    (pXorEccConfig->sectorSize > XETMCR_SECTION_SIZE_MAX_VALUE)) {
+		DB(mvOsPrintf("%s: ERR. sectorSize must be between %d to %d\n",
+			      __func__, XETMCR_SECTION_SIZE_MIN_VALUE, XETMCR_SECTION_SIZE_MAX_VALUE));
+		return MV_BAD_PARAM;
+	}
+	if ((pXorEccConfig->blockSize < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
+	    (pXorEccConfig->blockSize > XEXBSR_BLOCK_SIZE_MAX_VALUE)) {
+		DB(mvOsPrintf("%s: ERR. Block size must be between %d to %ul\n",
+			      __func__, XEXBSR_BLOCK_SIZE_MIN_VALUE, XEXBSR_BLOCK_SIZE_MAX_VALUE));
+		return MV_BAD_PARAM;
+	}
+	if (0x0 == pXorEccConfig->destPtr) {
+		DB(mvOsPrintf("%s: ERR. destPtr is NULL pointer\n", __func__));
+		return MV_BAD_PARAM;
+	}
+
+	/* set the operation mode to ECC */
+	temp = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+	temp &= ~XEXCR_OPERATION_MODE_MASK;
+	temp |= XEXCR_OPERATION_MODE_ECC;
+	MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
+
+	/* update the TimerEn bit in the XOR Engine Timer Mode
+	   Control Register (XETMCR) */
+	if (pXorEccConfig->periodicEnable)
+		MV_REG_BIT_SET(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)), XETMCR_TIMER_EN_MASK);
+	else
+		MV_REG_BIT_RESET(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)), XETMCR_TIMER_EN_MASK);
+
+	/* update the SectionSizeCtrl bit in the XOR Engine Timer Mode Control
+	   Register (XETMCR) */
+	temp = MV_REG_READ(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)));
+	temp &= ~XETMCR_SECTION_SIZE_CTRL_MASK;
+	temp |= (pXorEccConfig->sectorSize << XETMCR_SECTION_SIZE_CTRL_OFFS);
+	MV_REG_WRITE(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)), temp);
+
+	/* update the DstPtr field in the XOR Engine [0..1] Destination Pointer
+	   Register (XExDPR0) */
+	MV_REG_WRITE(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), pXorEccConfig->destPtr);
+
+	/* update the BlockSize field in the XOR Engine[0..1] Block Size
+	   Registers (XExBSR) */
+	MV_REG_WRITE(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)), pXorEccConfig->blockSize);
+
+	/* update the XOR Engine Timer Mode Initial Value Register (XETMIVR) */
+	tClkCycles = pXorEccConfig->tClkTicks;
+	MV_REG_WRITE(XOR_TIMER_MODE_INIT_VAL_REG(XOR_UNIT(chan)), tClkCycles);
+
+	/* start transfer */
+	MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), XEXACTR_XESTART_MASK);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorEccCurrTimerGet - Return ECC timer current value.
+*
+* DESCRIPTION:
+*       Return the ECC timer mode Current value.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       Timer ticks (in Tclk frequancy).
+*
+*******************************************************************************/
+MV_U32 mvXorEccCurrTimerGet(MV_U32 chan, MV_U32 tClk)
+{
+	/* read the current Tclk */
+	return (MV_REG_READ(XOR_TIMER_MODE_CURR_VAL_REG(XOR_UNIT(chan))));
+}
+
+/*******************************************************************************
+* mvXorMemInit -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*
+*
+*******************************************************************************/
+MV_STATUS mvXorMemInit(MV_U32 chan, MV_U32 startPtr, MV_U32 blockSize, MV_U32 initValHigh, MV_U32 initValLow)
+{
+	MV_U32 temp;
+
+	/* Parameter checking   */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		mvOsPrintf("%s: ERR. Invalid chan num %d\n", __func__, chan);
+		return MV_BAD_PARAM;
+	}
+	if (MV_ACTIVE == mvXorStateGet(chan)) {
+		mvOsPrintf("%s: ERR. Channel is already active\n", __func__);
+		return MV_BUSY;
+	}
+	if ((blockSize < XEXBSR_BLOCK_SIZE_MIN_VALUE) || (blockSize > XEXBSR_BLOCK_SIZE_MAX_VALUE)) {
+		mvOsPrintf("%s: ERR. Block size must be between %d to %ul\n",
+			   __func__, XEXBSR_BLOCK_SIZE_MIN_VALUE, XEXBSR_BLOCK_SIZE_MAX_VALUE);
+		return MV_BAD_PARAM;
+	}
+#if 0
+/* tzachi - this is done purposely by u-boot */
+	if (0x0 == startPtr) {
+		mvOsPrintf("%s: ERR. startPtr is NULL pointer\n", __func__);
+		return MV_BAD_PARAM;
+	}
+#endif
+
+	/* set the operation mode to Memory Init */
+	temp = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+	temp &= ~XEXCR_OPERATION_MODE_MASK;
+	temp |= XEXCR_OPERATION_MODE_MEM_INIT;
+	MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
+
+	/* update the startPtr field in XOR Engine [0..1] Destination Pointer
+	   Register (XExDPR0) */
+	MV_REG_WRITE(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), startPtr);
+
+	/* update the BlockSize field in the XOR Engine[0..1] Block Size
+	   Registers (XExBSR) */
+	MV_REG_WRITE(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)), blockSize);
+
+	/* update the field InitValL in the XOR Engine Initial Value Register
+	   Low (XEIVRL) */
+	MV_REG_WRITE(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), initValLow);
+
+	/* update the field InitValH in the XOR Engine Initial Value Register
+	   High (XEIVRH) */
+	MV_REG_WRITE(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), initValHigh);
+
+	/* start transfer */
+	MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), XEXACTR_XESTART_MASK);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorTransfer - Transfer data from source to destination on one of
+*                 three modes (XOR,CRC32,DMA)
+*
+* DESCRIPTION:
+*       This function initiates XOR channel, according to function parameters,
+*       in order to perform XOR or CRC32 or DMA transaction.
+*       To gain maximum performance the user is asked to keep the following
+*       restrictions:
+*       1) Selected engine is available (not busy).
+*       1) This module does not take into consideration CPU MMU issues.
+*          In order for the XOR engine to access the appropreate source
+*          and destination, address parameters must be given in system
+*          physical mode.
+*       2) This API does not take care of cache coherency issues. The source,
+*          destination and in case of chain the descriptor list are assumed
+*          to be cache coherent.
+*       4) Parameters validity. For example, does size parameter exceeds
+*          maximum byte count of descriptor mode (16M or 64K).
+*
+* INPUT:
+*       chan          - XOR channel number. See MV_XOR_CHANNEL enumerator.
+*       xorType       - One of three: XOR, CRC32 and DMA operations.
+*       xorChainPtr   - address of chain pointer
+*
+* OUTPUT:
+*       None.
+*
+* RETURS:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvXorTransfer(MV_U32 chan, MV_XOR_TYPE xorType, MV_U32 xorChainPtr)
+{
+	MV_U32 temp;
+
+	/* Parameter checking */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+		return MV_BAD_PARAM;
+	}
+	if (MV_ACTIVE == mvXorStateGet(chan)) {
+		DB(mvOsPrintf("%s: ERR. Channel is already active\n", __func__));
+		return MV_BUSY;
+	}
+	if (0x0 == xorChainPtr) {
+		DB(mvOsPrintf("%s: ERR. xorChainPtr is NULL pointer\n", __func__));
+		return MV_BAD_PARAM;
+	}
+
+	/* read configuration register and mask the operation mode field */
+	temp = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+	temp &= ~XEXCR_OPERATION_MODE_MASK;
+
+	switch (xorType) {
+	case MV_XOR:
+		if (0 != (xorChainPtr & XEXDPR_DST_PTR_XOR_MASK)) {
+			DB(mvOsPrintf("%s: ERR. Invalid chain pointer (bits [5:0] must "
+				      "be cleared)\n", __func__));
+			return MV_BAD_PARAM;
+		}
+		/* set the operation mode to XOR */
+		temp |= XEXCR_OPERATION_MODE_XOR;
+		break;
+
+	case MV_DMA:
+		if (0 != (xorChainPtr & XEXDPR_DST_PTR_DMA_MASK)) {
+			DB(mvOsPrintf("%s: ERR. Invalid chain pointer (bits [4:0] must "
+				      "be cleared)\n", __func__));
+			return MV_BAD_PARAM;
+		}
+		/* set the operation mode to DMA */
+		temp |= XEXCR_OPERATION_MODE_DMA;
+		break;
+
+	case MV_CRC32:
+		if (0 != (xorChainPtr & XEXDPR_DST_PTR_CRC_MASK)) {
+			DB(mvOsPrintf("%s: ERR. Invalid chain pointer (bits [4:0] must "
+				      "be cleared)\n", __func__));
+			return MV_BAD_PARAM;
+		}
+		/* set the operation mode to CRC32 */
+		temp |= XEXCR_OPERATION_MODE_CRC;
+		break;
+
+	default:
+		return MV_BAD_PARAM;
+	}
+
+	/* write the operation mode to the register */
+	MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
+	/* update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor
+	   Pointer Register (XExNDPR) */
+	MV_REG_WRITE(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xorChainPtr);
+
+	/* start transfer */
+	MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), XEXACTR_XESTART_MASK);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorStateGet - Get XOR channel state.
+*
+* DESCRIPTION:
+*       XOR channel activity state can be active, idle, paused.
+*       This function retrunes the channel activity state.
+*
+* INPUT:
+*       chan     - the channel number
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       XOR_CHANNEL_IDLE    - If the engine is idle.
+*       XOR_CHANNEL_ACTIVE  - If the engine is busy.
+*       XOR_CHANNEL_PAUSED  - If the engine is paused.
+*       MV_UNDEFINED_STATE  - If the engine state is undefind or there is no
+*                             such engine
+*
+*******************************************************************************/
+MV_STATE mvXorStateGet(MV_U32 chan)
+{
+	MV_U32 state;
+
+	/* Parameter checking   */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+		return MV_UNDEFINED_STATE;
+	}
+
+	/* read the current state */
+	state = MV_REG_READ(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+	state &= XEXACTR_XESTATUS_MASK;
+
+	/* return the state */
+	switch (state) {
+	case XEXACTR_XESTATUS_IDLE:
+		return MV_IDLE;
+	case XEXACTR_XESTATUS_ACTIVE:
+		return MV_ACTIVE;
+	case XEXACTR_XESTATUS_PAUSED:
+		return MV_PAUSED;
+	}
+	return MV_UNDEFINED_STATE;
+}
+
+/*******************************************************************************
+* mvXorCommandSet - Set command of XOR channel
+*
+* DESCRIPTION:
+*       XOR channel can be started, idle, paused and restarted.
+*       Paused can be set only if channel is active.
+*       Start can be set only if channel is idle or paused.
+*       Restart can be set only if channel is paused.
+*       Stop can be set only if channel is active.
+*
+* INPUT:
+*       chan     - The channel number
+*       command  - The command type (start, stop, restart, pause)
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
+*       undefind XOR engine mode
+*
+*******************************************************************************/
+MV_STATUS mvXorCommandSet(MV_U32 chan, MV_COMMAND command)
+{
+	MV_STATE state;
+
+	/* Parameter checking */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+		return MV_BAD_PARAM;
+	}
+
+	/* get the current state */
+	state = mvXorStateGet(chan);
+
+	/* command is start and current state is idle */
+	if ((command == MV_START) && (state == MV_IDLE)) {
+		MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), XEXACTR_XESTART_MASK);
+		return MV_OK;
+	}
+	/* command is stop and current state is active */
+	else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
+		MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), XEXACTR_XESTOP_MASK);
+		return MV_OK;
+	}
+	/* command is paused and current state is active */
+	else if ((command == MV_PAUSED) && (state == MV_ACTIVE)) {
+		MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), XEXACTR_XEPAUSE_MASK);
+		return MV_OK;
+	}
+	/* command is restart and current state is paused */
+	else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
+		MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), XEXACTR_XERESTART_MASK);
+		return MV_OK;
+	}
+
+	/* command is stop and current state is active */
+	else if ((command == MV_STOP) && (state == MV_IDLE))
+		return MV_OK;
+
+	/* illegal command */
+	DB(mvOsPrintf("%s: ERR. Illegal command\n", __func__));
+
+	return MV_BAD_PARAM;
+}
+
+/*******************************************************************************
+* mvXorOverrideSet - Set XOR target window override
+*
+* DESCRIPTION:
+*       The address override feature enables additional address decoupling.
+*       For example, it allows the use of the same source and destination
+*       addresses while the source is targeted to one interface and
+*       destination to a second interface.
+*       XOR source/destination/next descriptor addresses can be override per
+*       address decode windows 0,1,2 and 3 only.
+*       This function set override parameters per XOR channel. It access
+*       XOR control register low.
+*
+* INPUT:
+*       chan        - XOR channel number. See MV_XOR_CHANNEL enumerator.
+*       winNum      - Override window number.
+*                       Note: Not all windows can override.
+*       override    - Type of override. See MV_XOR_OVERRIDE enumerator.
+*       enable      - Window override is enabled or disabled
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+
+MV_STATUS mvXorOverrideSet(MV_U32 chan, MV_XOR_OVERRIDE_TARGET target, MV_U32 winNum, MV_BOOL enable)
+{
+	MV_U32 temp;
+
+	/* Parameter checking   */
+	if (chan >= MV_XOR_MAX_CHAN) {
+
+		DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+		return MV_BAD_PARAM;
+	}
+	if (winNum >= XOR_MAX_OVERRIDE_WIN) {
+		DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __func__, winNum));
+		return MV_BAD_PARAM;
+	}
+
+	/* set the enable bit */
+	if (enable)
+		MV_REG_BIT_SET(XOR_OVERRIDE_CTRL_REG(chan), XEXAOCR_OVR_EN_MASK(target));
+	 else
+		MV_REG_BIT_RESET(XOR_OVERRIDE_CTRL_REG(chan), XEXAOCR_OVR_EN_MASK(target));
+
+	/* read the override control register */
+	temp = MV_REG_READ(XOR_OVERRIDE_CTRL_REG(chan));
+	temp &= ~XEXAOCR_OVR_PTR_MASK(target);
+	temp |= (winNum << XEXAOCR_OVR_PTR_OFFS(target));
+	MV_REG_WRITE(XOR_OVERRIDE_CTRL_REG(chan), temp);
+	return MV_OK;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/xor/mvXor.h b/arch/arm/plat-feroceon/mv_hal/xor/mvXor.h
new file mode 100755
index 0000000..75e1fdb
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/xor/mvXor.h
@@ -0,0 +1,207 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*******************************************************************************
+* mvXor.h - Header File for :
+*
+* DESCRIPTION:
+*       This file contains Marvell Controller XOR HW library API.
+*       NOTE: This HW library API assumes XOR source, destination and
+*       descriptors are cache coherent.
+*
+* DEPENDENCIES:
+*       None.
+*
+*******************************************************************************/
+
+#ifndef __INCMVxorh
+#define __INCMVxorh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvCommon.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvSysXorConfig.h"
+
+/* typedefs */
+
+/* This enumerator describes the type of functionality the XOR channel      */
+/* can have while using the same data structures.                           */
+	typedef enum _mvXorType {
+		MV_XOR,		/* XOR channel functions as XOR accelerator     */
+		MV_DMA,		/* XOR channel functions as IDMA channel        */
+		MV_CRC32	/* XOR channel functions as CRC 32 calculator   */
+	} MV_XOR_TYPE;
+
+#if defined(MV_CPU_LE)
+	/* This structure describes XOR descriptor size 64bytes                     */
+	typedef struct _mvXorDesc {
+		MV_U32 status;	/* Successful descriptor execution indication */
+		MV_U32 crc32Result;	/* Result of CRC-32 calculation */
+		MV_U32 descCommand;	/* type of operation to be carried out on the data */
+		MV_U32 phyNextDescPtr;	/* Next descriptor address pointer */
+		MV_U32 byteCnt;	/* Size of source and destination blocks in bytes */
+		MV_U32 phyDestAdd;	/* Destination Block address pointer */
+		MV_U32 srcAdd0;	/* source block #0 address pointer */
+		MV_U32 srcAdd1;	/* source block #1 address pointer */
+		MV_U32 srcAdd2;	/* source block #2 address pointer */
+		MV_U32 srcAdd3;	/* source block #3 address pointer */
+		MV_U32 srcAdd4;	/* source block #4 address pointer */
+		MV_U32 srcAdd5;	/* source block #6 address pointer */
+		MV_U32 srcAdd6;	/* source block #6 address pointer */
+		MV_U32 srcAdd7;	/* source block #7 address pointer */
+		MV_U32 reserved0;
+		MV_U32 reserved1;
+	} MV_XOR_DESC;
+
+/* XOR descriptor structure for CRC and DMA descriptor */
+	typedef struct _mvCrcDmaDesc {
+		MV_U32 status;	/* Successful descriptor execution indication */
+		MV_U32 crc32Result;	/* Result of CRC-32 calculation */
+		MV_U32 descCommand;	/* type of operation to be carried out on the data */
+		MV_U32 nextDescPtr;	/* Next descriptor address pointer */
+		MV_U32 byteCnt;	/* Size of source block part represented by the descriptor */
+		MV_U32 destAdd;	/* Destination Block address pointer (not used in CRC32 */
+		MV_U32 srcAdd0;	/* Mode: Source Block address pointer */
+		MV_U32 srcAdd1;	/* Mode: Source Block address pointer */
+	} MV_CRC_DMA_DESC;
+
+#elif defined(MV_CPU_BE)
+/* This structure describes XOR descriptor size 64bytes                     */
+	typedef struct _mvXorDesc {
+		MV_U32 crc32Result;	/* Result of CRC-32 calculation */
+		MV_U32 status;	/* Successful descriptor execution indication */
+		MV_U32 phyNextDescPtr;	/* Next descriptor address pointer */
+		MV_U32 descCommand;	/* type of operation to be carried out on the data */
+		MV_U32 phyDestAdd;	/* Destination Block address pointer */
+		MV_U32 byteCnt;	/* Size of source and destination blocks in bytes */
+		MV_U32 srcAdd1;	/* source block #1 address pointer */
+		MV_U32 srcAdd0;	/* source block #0 address pointer */
+		MV_U32 srcAdd3;	/* source block #3 address pointer */
+		MV_U32 srcAdd2;	/* source block #2 address pointer */
+		MV_U32 srcAdd5;	/* source block #5 address pointer */
+		MV_U32 srcAdd4;	/* source block #4 address pointer */
+		MV_U32 srcAdd7;	/* source block #7 address pointer */
+		MV_U32 srcAdd6;	/* source block #6 address pointer */
+		MV_U32 reserved0;
+		MV_U32 reserved1;
+	} MV_XOR_DESC;
+
+/* XOR descriptor structure for CRC and DMA descriptor */
+	typedef struct _mvCrcDmaDesc {
+		MV_U32 crc32Result;	/* Result of CRC-32 calculation */
+		MV_U32 status;	/* Successful descriptor execution indication */
+		MV_U32 nextDescPtr;	/* Next descriptor address pointer */
+		MV_U32 descCommand;	/* type of operation to be carried out on the data */
+		MV_U32 destAdd;	/* Destination Block address pointer (not used in CRC32 */
+		MV_U32 byteCnt;	/* Size of source block part represented by the descriptor */
+		MV_U32 srcAdd1;	/* Mode: Source Block address pointer */
+		MV_U32 srcAdd0;	/* Mode: Source Block address pointer */
+	} MV_CRC_DMA_DESC;
+
+#endif
+
+	typedef struct _mvXorEcc {
+		MV_U32 destPtr;	/* Target block pointer to ECC/MemInit operation */
+		MV_U32 blockSize;	/* Block size in bytes for ECC/MemInit operation */
+		MV_BOOL periodicEnable;	/* Enable Timer Mode                                                         */
+		MV_U32 tClkTicks;	/* ECC timer mode initial count - down value     */
+		MV_U32 sectorSize;	/* section size for ECC timer mode operation     */
+	} MV_XOR_ECC;
+
+	typedef enum _mvXorOverrideTarget {
+		SRC_ADDR0,	/* Source Address #0 Control */
+		SRC_ADDR1,	/* Source Address #1 Control */
+		SRC_ADDR2,	/* Source Address #2 Control */
+		SRC_ADDR3,	/* Source Address #3 Control */
+		SRC_ADDR4,	/* Source Address #4 Control */
+		SRC_ADDR5,	/* Source Address #5 Control */
+		SRC_ADDR6,	/* Source Address #6 Control */
+		SRC_ADDR7,	/* Source Address #7 Control */
+		XOR_DST_ADDR,	/* Destination Address Control */
+		XOR_NEXT_DESC	/* Next Descriptor Address Control */
+	} MV_XOR_OVERRIDE_TARGET;
+
+	MV_VOID mvXorHalInit(MV_U32 xorChanNum);
+	MV_STATUS mvXorCtrlSet(MV_U32 chan, MV_U32 xorCtrl);
+	MV_STATUS mvXorEccClean(MV_U32 chan, MV_XOR_ECC *pXorEccConfig);
+	MV_U32 mvXorEccCurrTimerGet(MV_U32 chan, MV_U32 tClk);
+	MV_STATUS mvXorMemInit(MV_U32 chan, MV_U32 startPtr, MV_U32 blockSize, MV_U32 initValHigh, MV_U32 initValLow);
+	MV_STATUS mvXorTransfer(MV_U32 chan, MV_XOR_TYPE xorType, MV_U32 xorChainPtr);
+	MV_STATE mvXorStateGet(MV_U32 chan);
+	MV_STATUS mvXorCommandSet(MV_U32 chan, MV_COMMAND command);
+	MV_STATUS mvXorOverrideSet(MV_U32 chan, MV_XOR_OVERRIDE_TARGET target, MV_U32 winNum, MV_BOOL enable);
+
+	MV_STATUS mvXorWinInit(MV_UNIT_WIN_INFO *addrWinMap);
+	MV_STATUS mvXorTargetWinWrite(MV_U32 unit, MV_U32 winNum,
+					MV_UNIT_WIN_INFO *pAddrDecWin);
+	MV_STATUS mvXorTargetWinRead(MV_U32 unit, MV_U32 winNum,
+					MV_UNIT_WIN_INFO *pAddrDecWin);
+	MV_STATUS mvXorTargetWinEnable(MV_U32 unit, MV_U32 winNum, MV_BOOL enable);
+	MV_STATUS mvXorProtWinSet(MV_U32 unit, MV_U32 chan, MV_U32 winNum, MV_BOOL access, MV_BOOL write);
+	MV_STATUS mvXorPciRemap(MV_U32 unit, MV_U32 winNum, MV_U32 addrHigh);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/arm/plat-feroceon/mv_hal/xor/mvXorAddrDec.c b/arch/arm/plat-feroceon/mv_hal/xor/mvXorAddrDec.c
new file mode 100755
index 0000000..3cf9da7
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/xor/mvXorAddrDec.c
@@ -0,0 +1,518 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+#include "mvCommon.h"
+#include "mvOs.h"
+#include "ctrlEnv/mvCtrlEnvSpec.h"
+#include "mvXorRegs.h"
+#include "mvXor.h"
+
+/* defines  */
+#ifdef MV_DEBUG
+#define DB(x)	x
+#else
+#define DB(x)
+#endif
+
+static MV_STATUS xorWinOverlapDetect(MV_U32 unit, MV_U32 winNum,
+	MV_ADDR_WIN *pAddrWin);
+
+MV_TARGET xorAddrDecPrioTap[] = {
+#if defined(MV_INCLUDE_SDRAM_CS0)
+	SDRAM_CS0,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS1)
+	SDRAM_CS1,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS2)
+	SDRAM_CS2,
+#endif
+#if defined(MV_INCLUDE_SDRAM_CS3)
+	SDRAM_CS3,
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS0)
+	DEVICE_CS0,
+#endif
+#if defined(MV_INCLUDE_PEX)
+#ifdef MV_INCLUDE_PEX0
+	PEX0_MEM,
+#endif
+#ifdef MV_INCLUDE_PEX1
+	PEX1_MEM,
+#endif
+#endif
+#if defined(MV_INCLUDE_DEVICE_CS1)
+	DEV_CS1,
+#endif
+#if defined(MV_INCLUDE_CESA)
+	CRYPT1_ENG,
+#endif
+	TBL_TERM
+};
+
+static MV_STATUS mvXorInitWinsUnit(MV_U32 unit, MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 winNum;
+	MV_UNIT_WIN_INFO *addrDecWin;
+	MV_U32 winPrioIndex = 0;
+
+	/* Initiate XOR address decode */
+
+	/* First disable all address decode windows */
+	for (winNum = 0; winNum < XOR_MAX_ADDR_DEC_WIN; winNum++)
+		mvXorTargetWinEnable(unit, winNum, MV_FALSE);
+
+	/* Go through all windows in user table until table terminator                      */
+	for (winNum = 0; ((xorAddrDecPrioTap[winPrioIndex] != TBL_TERM) && (winNum < XOR_MAX_ADDR_DEC_WIN));) {
+		addrDecWin = &addrWinMap[xorAddrDecPrioTap[winPrioIndex]];
+		if (addrDecWin->enable == MV_TRUE) {
+			if (MV_OK != mvXorTargetWinWrite(unit, winNum, addrDecWin)) {
+				DB(mvOsPrintf("mvXorInit: ERR. mvDmaTargetWinSet failed\n"));
+				return MV_ERROR;
+			}
+			winNum++;
+		}
+		winPrioIndex++;
+	}
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorWinInit
+*
+* DESCRIPTION:
+*   This function sets the default address decode windows of the unit.
+*   Note that if the address window is disabled in xorAddrDecMap, the
+*   window parameters will be set but the window will remain disabled.
+*
+* INPUT:
+*       None.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*******************************************************************************/
+MV_STATUS mvXorWinInit(MV_UNIT_WIN_INFO *addrWinMap)
+{
+	MV_U32 i;
+
+	/* Initiate XOR address decode */
+	for (i = 0; i < MV_XOR_MAX_UNIT; i++)
+		mvXorInitWinsUnit(i, addrWinMap);
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorTargetWinWrite - Set XOR target address window
+*
+* DESCRIPTION:
+*       This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0)
+*       address window. After setting this target window, the XOR will be
+*       able to access the target within the address window.
+*
+* INPUT:
+*	    winNum - One of the possible XOR memory decode windows.
+*       target - Peripheral target enumerator.
+*       base   - Window base address.
+*       size   - Window size.
+*       enable - Window enable/disable.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvXorTargetWinWrite(MV_U32 unit, MV_U32 winNum,
+				MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+	MV_U32 chan;
+
+	/* Parameter checking */
+	if (winNum >= XOR_MAX_ADDR_DEC_WIN) {
+		DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",  __func__, winNum));
+		return MV_BAD_PARAM;
+	}
+
+	if (pAddrDecWin == NULL) {
+		DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n",  __func__));
+		return MV_BAD_PTR;
+	}
+
+	/* Check if the requested window overlaps with current windows */
+	if (MV_TRUE == xorWinOverlapDetect(unit, winNum, &pAddrDecWin->addrWin)) {
+		DB(mvOsPrintf("%s: ERR. Window %d overlap\n",  __func__, winNum));
+		return MV_ERROR;
+	}
+
+	if (!MV_IS_POWER_OF_2(pAddrDecWin->addrWin.size)) {
+		mvOsPrintf("%s: ERR. Illegal window size.\n",  __func__);
+		return MV_BAD_PARAM;
+	}
+
+	baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit, winNum));
+	sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit, winNum));
+
+	baseReg = pAddrDecWin->addrWin.baseLow & XEBARX_BASE_MASK;
+	sizeReg = (pAddrDecWin->addrWin.size / XOR_WIN_SIZE_ALIGN) - 1;
+	sizeReg = (sizeReg << XESMRX_SIZE_MASK_OFFS) & XESMRX_SIZE_MASK_MASK;
+
+	/* set attributes */
+	baseReg &= ~XEBARX_ATTR_MASK;
+	baseReg |= pAddrDecWin->attrib << XEBARX_ATTR_OFFS;
+	/* set target ID */
+	baseReg &= ~XEBARX_TARGET_MASK;
+	baseReg |= pAddrDecWin->targetId << XEBARX_TARGET_OFFS;
+
+	/* Write to address decode Base Address Register */
+	MV_REG_WRITE(XOR_BASE_ADDR_REG(unit, winNum), baseReg);
+
+	/* Write to Size Register */
+	MV_REG_WRITE(XOR_SIZE_MASK_REG(unit, winNum), sizeReg);
+
+	for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) {
+		if (pAddrDecWin->enable)
+			MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit, chan), XEXWCR_WIN_EN_MASK(winNum));
+		 else
+			MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit, chan), XEXWCR_WIN_EN_MASK(winNum));
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorTargetWinRead - Get xor peripheral target address window.
+*
+* DESCRIPTION:
+*		Get xor peripheral target address window.
+*
+* INPUT:
+*	  winNum - One of the possible XOR memory decode windows.
+*
+* OUTPUT:
+*       base   - Window base address.
+*       size   - Window size.
+*       enable - window enable/disable.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvXorTargetWinRead(MV_U32 unit, MV_U32 winNum,
+	MV_UNIT_WIN_INFO *pAddrDecWin)
+{
+	MV_U32 sizeReg, baseReg;
+	MV_U32 chan = 0, chanWinEn;
+
+	/* Parameter checking */
+	if (winNum >= XOR_MAX_ADDR_DEC_WIN) {
+		DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",  __func__, winNum));
+		return MV_ERROR;
+	}
+
+	if (NULL == pAddrDecWin) {
+		DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n",  __func__));
+		return MV_BAD_PTR;
+	}
+
+	chanWinEn = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit, 0)) & XEXWCR_WIN_EN_MASK(winNum);
+
+	for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) {	/* we should scan here all channels per unit */
+		/* Check if enable bit is equal for all channels */
+		if ((MV_REG_READ(XOR_WINDOW_CTRL_REG(unit, chan)) & XEXWCR_WIN_EN_MASK(winNum)) != chanWinEn) {
+			mvOsPrintf("%s: ERR. Window enable field must be equal in "
+				   "all channels(chan=%d)\n",  __func__, chan);
+			return MV_ERROR;
+		}
+	}
+
+	baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit, winNum));
+	sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit, winNum));
+
+	pAddrDecWin->addrWin.size = (sizeReg & XESMRX_SIZE_MASK_MASK) >> XESMRX_SIZE_MASK_OFFS;
+	pAddrDecWin->addrWin.size = (pAddrDecWin->addrWin.size + 1) * XOR_WIN_SIZE_ALIGN;
+
+	pAddrDecWin->addrWin.baseLow = baseReg & XEBARX_BASE_MASK;
+	pAddrDecWin->addrWin.baseHigh = 0;
+
+	/* attrib and targetId */
+	pAddrDecWin->attrib = (baseReg & XEBARX_ATTR_MASK) >> XEBARX_ATTR_OFFS;
+	pAddrDecWin->targetId = (baseReg & XEBARX_TARGET_MASK) >> XEBARX_TARGET_OFFS;
+
+	if (chanWinEn)
+		pAddrDecWin->enable = MV_TRUE;
+	else
+		pAddrDecWin->enable = MV_FALSE;
+
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorTargetWinEnable - Enable/disable a Xor address decode window
+*
+* DESCRIPTION:
+*       This function enable/disable a XOR address decode window.
+*       if parameter 'enable' == MV_TRUE the routine will enable the
+*       window, thus enabling XOR accesses (before enabling the window it is
+*       tested for overlapping). Otherwise, the window will be disabled.
+*
+* INPUT:
+*       winNum - Decode window number.
+*       enable - Enable/disable parameter.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvXorTargetWinEnable(MV_U32 unit, MV_U32 winNum, MV_BOOL enable)
+{
+	MV_UNIT_WIN_INFO addrDecWin;
+	MV_U32 chan;
+
+	/* Parameter checking   */
+	if (winNum >= XOR_MAX_ADDR_DEC_WIN) {
+		DB(mvOsPrintf("%s: ERR. Invalid winNum%d\n",  __func__, winNum));
+		return MV_ERROR;
+	}
+
+	if (enable == MV_TRUE) {
+		/* Get current window */
+		if (MV_OK != mvXorTargetWinRead(unit, winNum, &addrDecWin)) {
+			DB(mvOsPrintf("%s: ERR. targetWinGet fail\n",  __func__));
+			return MV_ERROR;
+		}
+
+		/* Check for overlapping */
+		if (MV_TRUE == xorWinOverlapDetect(unit, winNum, &(addrDecWin.addrWin))) {
+			/* Overlap detected */
+			DB(mvOsPrintf("%s: ERR. Overlap detected\n",  __func__));
+			return MV_ERROR;
+		}
+
+		/* No Overlap. Enable address decode target window */
+		for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++)
+			MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit, chan), XEXWCR_WIN_EN_MASK(winNum));
+	} else {
+		/* Disable address decode target window */
+		for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++)
+			MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit, chan), XEXWCR_WIN_EN_MASK(winNum));
+	}
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorSetProtWinSet - Configure access attributes of a XOR engine
+*                               to one of the XOR memory windows.
+*
+* DESCRIPTION:
+*       Each engine can be configured with access attributes for each of the
+*       memory spaces. This function sets access attributes
+*       to a given window for the given engine
+*
+* INPUTS:
+*       chan    - One of the possible engines.
+*       winNum  - One of the possible XOR memory spaces.
+*       access  - Protection access rights.
+*       write   - Write rights.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvXorProtWinSet(MV_U32 unit, MV_U32 chan, MV_U32 winNum, MV_BOOL access, MV_BOOL write)
+{
+	MV_U32 temp;
+
+	/* Parameter checking   */
+	if (chan >= MV_XOR_MAX_CHAN_PER_UNIT) {
+		DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n",  __func__, chan));
+		return MV_BAD_PARAM;
+	}
+	if (winNum >= XOR_MAX_ADDR_DEC_WIN) {
+		DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",  __func__, winNum));
+		return MV_BAD_PARAM;
+	}
+
+	temp = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit, chan)) & (~XEXWCR_WIN_ACC_MASK(winNum));
+
+	/* if access is disable */
+	if (!access) {
+		/* disable access */
+		temp |= XEXWCR_WIN_ACC_NO_ACC(winNum);
+	}
+	/* if access is enable */
+	else {
+		/* if write is enable */
+		if (write) {
+			/* enable write */
+			temp |= XEXWCR_WIN_ACC_RW(winNum);
+		}
+		/* if write is disable */
+		else {
+			/* disable write */
+			temp |= XEXWCR_WIN_ACC_RO(winNum);
+		}
+	}
+	MV_REG_WRITE(XOR_WINDOW_CTRL_REG(unit, chan), temp);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* mvXorPciRemap - Set XOR remap register for PCI address windows.
+*
+* DESCRIPTION:
+*       only Windows 0-3 can be remapped.
+*
+* INPUT:
+*       winNum      - window number
+*       pAddrDecWin  - pointer to address space window structure
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+MV_STATUS mvXorPciRemap(MV_U32 unit, MV_U32 winNum, MV_U32 addrHigh)
+{
+	/* Parameter checking   */
+	if (winNum >= XOR_MAX_REMAP_WIN) {
+		DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",  __func__, winNum));
+		return MV_BAD_PARAM;
+	}
+
+	MV_REG_WRITE(XOR_HIGH_ADDR_REMAP_REG(unit, winNum), addrHigh);
+	return MV_OK;
+}
+
+/*******************************************************************************
+* xorWinOverlapDetect - Detect XOR address windows overlaping
+*
+* DESCRIPTION:
+*       An unpredicted behaviour is expected in case XOR address decode
+*       windows overlaps.
+*       This function detects XOR address decode windows overlaping of a
+*       specified window. The function does not check the window itself for
+*       overlaping. The function also skipps disabled address decode windows.
+*
+* INPUT:
+*       winNum      - address decode window number.
+*       pAddrDecWin - An address decode window struct.
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*       MV_TRUE if the given address window overlap current address
+*       decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data
+*       from registers.
+*
+*******************************************************************************/
+static MV_STATUS xorWinOverlapDetect(MV_U32 unit, MV_U32 winNum,
+	MV_ADDR_WIN *pAddrWin)
+{
+	MV_U32 baseAddrEnableReg;
+	MV_U32 winNumIndex, chan;
+	MV_UNIT_WIN_INFO addrDecWin;
+
+	if (pAddrWin == NULL) {
+		DB(mvOsPrintf("%s: ERR. pAddrWin is NULL pointer\n",  __func__));
+		return MV_BAD_PTR;
+	}
+
+	for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) {
+		/* Read base address enable register. Do not check disabled windows     */
+		baseAddrEnableReg = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit, chan));
+
+		for (winNumIndex = 0; winNumIndex < XOR_MAX_ADDR_DEC_WIN; winNumIndex++) {
+			/* Do not check window itself */
+			if (winNumIndex == winNum)
+				continue;
+
+			/* Do not check disabled windows */
+			if ((baseAddrEnableReg & XEXWCR_WIN_EN_MASK(winNumIndex)) == 0)
+				continue;
+
+			/* Get window parameters */
+			if (MV_OK != mvXorTargetWinRead(unit, winNumIndex, &addrDecWin)) {
+				DB(mvOsPrintf("%s: ERR. TargetWinGet failed\n",  __func__));
+				return MV_ERROR;
+			}
+
+			if (MV_TRUE == mvWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
+				return MV_TRUE;
+		}
+	}
+
+	return MV_FALSE;
+}
diff --git a/arch/arm/plat-feroceon/mv_hal/xor/mvXorRegs.h b/arch/arm/plat-feroceon/mv_hal/xor/mvXorRegs.h
new file mode 100755
index 0000000..71e64a1
--- /dev/null
+++ b/arch/arm/plat-feroceon/mv_hal/xor/mvXorRegs.h
@@ -0,0 +1,281 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef __INCmvXorSpech
+#define __INCmvXorSpech
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mvSysXorConfig.h"
+/* defines */
+
+/* for controllers that have two XOR units, then chans 2 & 3 will be mapped*/
+/* to channels 0 & 1 of unit 1 */
+#define XOR_UNIT(chan)	((chan) >> 1)
+#define XOR_CHAN(chan)  ((chan) & 1)
+
+/* XOR Engine Control Register Map */
+#define XOR_CHANNEL_ARBITER_REG(unit)       (MV_XOR_REGS_BASE(unit))
+#define XOR_CONFIG_REG(unit, chan)           (MV_XOR_REGS_BASE(unit)+(0x10 + ((chan) * 4)))
+#define XOR_ACTIVATION_REG(unit, chan)       (MV_XOR_REGS_BASE(unit)+(0x20 + ((chan) * 4)))
+
+/* XOR Engine Interrupt Register Map */
+#define XOR_CAUSE_REG(unit)         (MV_XOR_REGS_BASE(unit)+(0x30))
+#define XOR_MASK_REG(unit)   	    (MV_XOR_REGS_BASE(unit)+(0x40))
+#define XOR_ERROR_CAUSE_REG(unit)   (MV_XOR_REGS_BASE(unit)+(0x50))
+#define XOR_ERROR_ADDR_REG(unit)    (MV_XOR_REGS_BASE(unit)+(0x60))
+
+/* XOR Engine Descriptor Register Map */
+#define XOR_NEXT_DESC_PTR_REG(unit, chan) (MV_XOR_REGS_BASE(unit)+(0x200 + ((chan) * 4)))
+#define XOR_CURR_DESC_PTR_REG(unit, chan) (MV_XOR_REGS_BASE(unit)+(0x210 + ((chan) * 4)))
+#define XOR_BYTE_COUNT_REG(unit, chan)    (MV_XOR_REGS_BASE(unit)+(0x220 + ((chan) * 4)))
+
+/* XOR Engine ECC/MemInit Register Map */
+#define XOR_DST_PTR_REG(unit, chan)          (MV_XOR_REGS_BASE(unit)+(0x2B0 + ((chan) * 4)))
+#define XOR_BLOCK_SIZE_REG(unit, chan)       (MV_XOR_REGS_BASE(unit)+(0x2C0 + ((chan) * 4)))
+#define XOR_TIMER_MODE_CTRL_REG(unit)       (MV_XOR_REGS_BASE(unit)+(0x2D0))
+#define XOR_TIMER_MODE_INIT_VAL_REG(unit)   (MV_XOR_REGS_BASE(unit)+(0x2D4))
+#define XOR_TIMER_MODE_CURR_VAL_REG(unit)   (MV_XOR_REGS_BASE(unit)+(0x2D8))
+#define XOR_INIT_VAL_LOW_REG(unit)          (MV_XOR_REGS_BASE(unit)+(0x2E0))
+#define XOR_INIT_VAL_HIGH_REG(unit)         (MV_XOR_REGS_BASE(unit)+(0x2E4))
+
+/* XOR Engine Debug Register Map */
+#define XOR_DEBUG_REG(unit)                 (MV_XOR_REGS_BASE(unit)+(0x70))
+
+
+/* XOR register fileds */
+
+
+/* XOR Engine Channel Arbiter Register */
+#define XECAR_SLICE_OFFS(sliceNum)          (sliceNum)
+#define XECAR_SLICE_MASK(sliceNum)          (1 << (XECAR_SLICE_OFFS(sliceNum)))
+
+/* XOR Engine [0..1] Configuration Registers (XExCR) */
+#define XEXCR_OPERATION_MODE_OFFS           (0)
+#define XEXCR_OPERATION_MODE_MASK           (7 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_XOR            (0 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_CRC            (1 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_DMA            (2 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_ECC            (3 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_MEM_INIT       (4 << XEXCR_OPERATION_MODE_OFFS)
+
+#define XEXCR_SRC_BURST_LIMIT_OFFS          (4)
+#define XEXCR_SRC_BURST_LIMIT_MASK          (7 << XEXCR_SRC_BURST_LIMIT_OFFS)
+#define XEXCR_DST_BURST_LIMIT_OFFS          (8)
+#define XEXCR_DST_BURST_LIMIT_MASK          (7 << XEXCR_DST_BURST_LIMIT_OFFS)
+#define XEXCR_DRD_RES_SWP_OFFS              (12)
+#define XEXCR_DRD_RES_SWP_MASK              (1 << XEXCR_DRD_RES_SWP_OFFS)
+#define XEXCR_DWR_REQ_SWP_OFFS              (13)
+#define XEXCR_DWR_REQ_SWP_MASK              (1 << XEXCR_DWR_REQ_SWP_OFFS)
+#define XEXCR_DES_SWP_OFFS                  (14)
+#define XEXCR_DES_SWP_MASK                  (1 << XEXCR_DES_SWP_OFFS)
+#define XEXCR_REG_ACC_PROTECT_OFFS          (15)
+#define XEXCR_REG_ACC_PROTECT_MASK          (1 << XEXCR_REG_ACC_PROTECT_OFFS)
+
+
+/* XOR Engine [0..1] Activation Registers (XExACTR) */
+#define XEXACTR_XESTART_OFFS                (0)
+#define XEXACTR_XESTART_MASK                (1 << XEXACTR_XESTART_OFFS)
+#define XEXACTR_XESTOP_OFFS                 (1)
+#define XEXACTR_XESTOP_MASK                 (1 << XEXACTR_XESTOP_OFFS)
+#define XEXACTR_XEPAUSE_OFFS                (2)
+#define XEXACTR_XEPAUSE_MASK                (1 << XEXACTR_XEPAUSE_OFFS)
+#define XEXACTR_XERESTART_OFFS              (3)
+#define XEXACTR_XERESTART_MASK              (1 << XEXACTR_XERESTART_OFFS)
+#define XEXACTR_XESTATUS_OFFS               (4)
+#define XEXACTR_XESTATUS_MASK               (3 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_IDLE               (0 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_ACTIVE             (1 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_PAUSED             (2 << XEXACTR_XESTATUS_OFFS)
+
+/* XOR Engine Interrupt Cause Register (XEICR) */
+#define XEICR_CHAN_OFFS					16
+#define XEICR_CAUSE_OFFS(chan)   		(chan * XEICR_CHAN_OFFS)
+#define XEICR_CAUSE_MASK(chan, cause)   (1 << (cause + XEICR_CAUSE_OFFS(chan)))
+#define XEICR_COMP_MASK_ALL				0x000f000f
+#define XEICR_COMP_MASK(chan)			(0x000f << XEICR_CAUSE_OFFS(chan))
+#define XEICR_ERR_MASK					0x03800380
+
+/* XOR Engine Error Cause Register (XEECR) */
+#define XEECR_ERR_TYPE_OFFS				0
+#define XEECR_ERR_TYPE_MASK				(0x1f << XEECR_ERR_TYPE_OFFS)
+
+/* XOR Engine Error Address Register (XEEAR) */
+#define XEEAR_ERR_ADDR_OFFS                 (0)
+#define XEEAR_ERR_ADDR_MASK                 (0xFFFFFFFF << XEEAR_ERR_ADDR_OFFS)
+
+/* XOR Engine [0..1] Next Descriptor Pointer Register (XExNDPR) */
+#define XEXNDPR_NEXT_DESC_PTR_OFFS          (0)
+#define XEXNDPR_NEXT_DESC_PTR_MASK          (0xFFFFFFFF << XEXNDPR_NEXT_DESC_PTR_OFFS)
+
+/* XOR Engine [0..1] Current Descriptor Pointer Register (XExCDPR) */
+#define XEXCDPR_CURRENT_DESC_PTR_OFFS       (0)
+#define XEXCDPR_CURRENT_DESC_PTR_MASK       (0xFFFFFFFF << XEXCDPR_CURRENT_DESC_PTR_OFFS)
+
+/* XOR Engine [0..1] Byte Count Register (XExBCR) */
+#define XEXBCR_BYTE_CNT_OFFS                (0)
+#define XEXBCR_BYTE_CNT_MASK                (0xFFFFFFFF << XEXBCR_BYTE_CNT_OFFS)
+
+/* XOR Engine [0..1] Destination Pointer Register (XExDPR0) */
+#define XEXDPR_DST_PTR_OFFS                 (0)
+#define XEXDPR_DST_PTR_MASK                 (0xFFFFFFFF << XEXDPR_DST_PTR_OFFS)
+#define XEXDPR_DST_PTR_XOR_MASK             (0x3F)
+#define XEXDPR_DST_PTR_DMA_MASK             (0x1F)
+#define XEXDPR_DST_PTR_CRC_MASK             (0x1F)
+
+/* XOR Engine[0..1] Block Size Registers (XExBSR) */
+#define XEXBSR_BLOCK_SIZE_OFFS              (0)
+#define XEXBSR_BLOCK_SIZE_MASK              (0xFFFFFFFF << XEXBSR_BLOCK_SIZE_OFFS)
+#define XEXBSR_BLOCK_SIZE_MIN_VALUE         (128)
+#define XEXBSR_BLOCK_SIZE_MAX_VALUE         (0xFFFFFFFF)
+
+/* XOR Engine Timer Mode Control Register (XETMCR) */
+#define XETMCR_TIMER_EN_OFFS                (0)
+#define XETMCR_TIMER_EN_MASK                (1 << XETMCR_TIMER_EN_OFFS)
+#define XETMCR_TIMER_EN_ENABLE              (1 << XETMCR_TIMER_EN_OFFS)
+#define XETMCR_TIMER_EN_DISABLE             (0 << XETMCR_TIMER_EN_OFFS)
+#define XETMCR_SECTION_SIZE_CTRL_OFFS       (8)
+#define XETMCR_SECTION_SIZE_CTRL_MASK       (0x1F << XETMCR_SECTION_SIZE_CTRL_OFFS)
+#define XETMCR_SECTION_SIZE_MIN_VALUE       (7)
+#define XETMCR_SECTION_SIZE_MAX_VALUE       (31)
+
+/* XOR Engine Timer Mode Initial Value Register (XETMIVR) */
+#define XETMIVR_TIMER_INIT_VAL_OFFS         (0)
+#define XETMIVR_TIMER_INIT_VAL_MASK         (0xFFFFFFFF << XETMIVR_TIMER_INIT_VAL_OFFS)
+
+/* XOR Engine Timer Mode Current Value Register (XETMCVR) */
+#define XETMCVR_TIMER_CRNT_VAL_OFFS         (0)
+#define XETMCVR_TIMER_CRNT_VAL_MASK         (0xFFFFFFFF << XETMCVR_TIMER_CRNT_VAL_OFFS)
+
+/* XOR Engine Initial Value Register Low (XEIVRL) */
+#define XEIVRL_INIT_VAL_L_OFFS              (0)
+#define XEIVRL_INIT_VAL_L_MASK              (0xFFFFFFFF << XEIVRL_INIT_VAL_L_OFFS)
+
+/* XOR Engine Initial Value Register High (XEIVRH) */
+#define XEIVRH_INIT_VAL_H_OFFS              (0)
+#define XEIVRH_INIT_VAL_H_MASK              (0xFFFFFFFF << XEIVRH_INIT_VAL_H_OFFS)
+
+/* XOR Engine Debug Register (XEDBR) */
+#define XEDBR_PARITY_ERR_INSR_OFFS          (0)
+#define XEDBR_PARITY_ERR_INSR_MASK          (1 << XEDBR_PARITY_ERR_INSR_OFFS)
+#define XEDBR_XBAR_ERR_INSR_OFFS            (1)
+#define XEDBR_XBAR_ERR_INSR_MASK            (1 << XEDBR_XBAR_ERR_INSR_OFFS)
+
+
+/* XOR Engine address decode registers.	*/
+
+#define XOR_MAX_ADDR_DEC_WIN	8	/* Maximum address decode windows		*/
+#define XOR_MAX_REMAP_WIN       4	/* Maximum address arbiter windows		*/
+
+/* XOR Engine Address Decoding Register Map */
+#define XOR_WINDOW_CTRL_REG(unit, chan)     (MV_XOR_REGS_BASE(unit)+(0x240 + ((chan) * 4)))
+#define XOR_BASE_ADDR_REG(unit, winNum)     (MV_XOR_REGS_BASE(unit)+(0x250 + ((winNum) * 4)))
+#define XOR_SIZE_MASK_REG(unit, winNum)     (MV_XOR_REGS_BASE(unit)+(0x270 + ((winNum) * 4)))
+#define XOR_HIGH_ADDR_REMAP_REG(unit, winNum) (MV_XOR_REGS_BASE(unit)+(0x290 + ((winNum) * 4)))
+
+/* XOR Engine [0..1] Window Control Registers (XExWCR) */
+#define XEXWCR_WIN_EN_OFFS(winNum)          (winNum)
+#define XEXWCR_WIN_EN_MASK(winNum)          (1 << (XEXWCR_WIN_EN_OFFS(winNum)))
+#define XEXWCR_WIN_EN_ENABLE(winNum)        (1 << (XEXWCR_WIN_EN_OFFS(winNum)))
+#define XEXWCR_WIN_EN_DISABLE(winNum)       (0 << (XEXWCR_WIN_EN_OFFS(winNum)))
+
+#define XEXWCR_WIN_ACC_OFFS(winNum)         ((2 * winNum) + 16)
+#define XEXWCR_WIN_ACC_MASK(winNum)         (3 << (XEXWCR_WIN_ACC_OFFS(winNum)))
+#define XEXWCR_WIN_ACC_NO_ACC(winNum)       (0 << (XEXWCR_WIN_ACC_OFFS(winNum)))
+#define XEXWCR_WIN_ACC_RO(winNum)           (1 << (XEXWCR_WIN_ACC_OFFS(winNum)))
+#define XEXWCR_WIN_ACC_RW(winNum)           (3 << (XEXWCR_WIN_ACC_OFFS(winNum)))
+
+/* XOR Engine Base Address Registers (XEBARx) */
+#define XEBARX_TARGET_OFFS                  (0)
+#define XEBARX_TARGET_MASK                  (0xF << XEBARX_TARGET_OFFS)
+#define XEBARX_ATTR_OFFS                    (8)
+#define XEBARX_ATTR_MASK                    (0xFF << XEBARX_ATTR_OFFS)
+#define XEBARX_BASE_OFFS                    (16)
+#define XEBARX_BASE_MASK                    (0xFFFF << XEBARX_BASE_OFFS)
+
+
+/* XOR Engine Size Mask Registers (XESMRx) */
+#define XESMRX_SIZE_MASK_OFFS               (16)
+#define XESMRX_SIZE_MASK_MASK               (0xFFFF << XESMRX_SIZE_MASK_OFFS)
+#define XOR_WIN_SIZE_ALIGN		    _64K
+
+/* XOR Engine High Address Remap Register (XEHARRx1) */
+#define XEHARRX_REMAP_OFFS                  (0)
+#define XEHARRX_REMAP_MASK                  (0xFFFFFFFF << XEHARRX_REMAP_OFFS)
+
+
+#define XOR_OVERRIDE_CTRL_REG(chan)   (MV_XOR_REGS_BASE(XOR_UNIT(chan))+(0x2A0 + ((XOR_CHAN(chan)) * 4)))
+/* XOR Engine [0..1] Address Override Control Register (XExAOCR) */
+#define XEXAOCR_OVR_EN_OFFS(target)         (3 * target)
+#define XEXAOCR_OVR_EN_MASK(target)         (1 << (XEXAOCR_OVR_EN_OFFS(target)))
+#define XEXAOCR_OVR_PTR_OFFS(target)        ((3 * target) + 1)
+#define XEXAOCR_OVR_PTR_MASK(target)        (3 << (XEXAOCR_OVR_PTR_OFFS(target)))
+#define XEXAOCR_OVR_BAR(winNum, target)      (winNum << (XEXAOCR_OVR_PTR_OFFS(target)))
+
+#define XOR_MAX_OVERRIDE_WIN	4	/* Maximum address override windows		*/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* __INCmvXorSpech */
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
old mode 100644
new mode 100755
index 07b976d..7b83d31
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -539,10 +539,10 @@
 tidsc25			MACH_TIDSC25		TIDSC25			523
 akcpmxl			MACH_AKCPMXL		AKCPMXL			524
 av3xx			MACH_AV3XX		AV3XX			525
-avila			MACH_AVILA		AVILA			526
-pxa_mpm10		MACH_PXA_MPM10		PXA_MPM10		527
-pxa_kyanite		MACH_PXA_KYANITE	PXA_KYANITE		528
-sgold			MACH_SGOLD		SGOLD			529
+feroceon_orion		ARCH_FEROCEON_ORION	FEROCEON_ORION		526
+feroceon_kw		ARCH_FEROCEON_KW	FEROCEON_KW		527
+feroceon_mv78xx0	ARCH_FEROCEON_MV78XX0	FEROCEON_MV78XX0	528
+feroceon_kw2		ARCH_FEROCEON_KW2	FEROCEON_KW2		529
 oscar			MACH_OSCAR		OSCAR			530
 epxa4usb2		MACH_EPXA4USB2		EPXA4USB2		531
 xsengine		MACH_XSENGINE		XSENGINE		532
diff --git a/cesa/openssl/README b/cesa/openssl/README
new file mode 100755
index 0000000..9e5ab40
--- /dev/null
+++ b/cesa/openssl/README
@@ -0,0 +1,26 @@
+OpenSSL
+===========
+ In order to explore the CESA unit through the OpenSSL, you have to use the 
+ OpenSSL OCF cryptodev engine.By default the cryptodev engine will use the CESA 
+ accelerator.
+
+ o Create a crypto device: mknod /dev/crypto c 10 70
+ o download openssl-0.9.8l (http://www.openssl.org/), then untar+unzip it.
+ o apply the patches (in the following order):
+ 	- openssl_ocf.patch: a patch from OCF for the OpenSSL cryptodev.
+ o copy from kernel crypto/ocf/cryptodev.h to FS /usr/include/crypto .
+ o Run: `./config --with-cryptodev shared `
+ o and compile ...('make' and 'make install')
+ o When the compilation is finished, copy the following files(from openssl root directory) to /lib:
+	- libcrypto.so
+	- libcrypto.so.0.9.8
+	- libssl.so
+	- libssl.so.0.9.8
+
+ you can run a speed test to make sure everything is working:
+	openssl speed -evp des3 -elapsed 
+ Modify /dev/crypto to /dev/crypto_tmp so that the speed test will use
+ now software encryption.
+ Run again:
+        openssl speed -evp des3 -elapsed
+ Compare results.
diff --git a/cesa/openswan/README b/cesa/openswan/README
new file mode 100755
index 0000000..680c615
--- /dev/null
+++ b/cesa/openswan/README
@@ -0,0 +1,68 @@
+OpenSWAN
+=========
+ In order to explore the CESA through the OpenSWAN, 1 patch should be applied to the OpenSWAN.
+
+ download openswan-2.6.29 (http://www.openswan.org/), then untar+unzip it.
+ apply the patch:
+
+ - mv_openswan_2_6_29.patch - 
+	change default configs to remove DEBUG and to include OCF.
+	Fixes:
+		- fix icmp_send failure caused by IFF_XMIT_DST_RELEASE flag set on the net dev.
+		- fix rmmod BUG by removing duplicated free_netdev call.
+		- include patch from openswan git that make sure we have the skb->dst in place before we call
+		  ip_select_ident otherwise we get kernel warn: "rt_bind_peer(0) .. "
+
+and compile:
+
+ + ipsec module (cross compilation) :
+  'make KERNELSRC=<path to this release, after config> module ARCH=arm CC=<path_to_cross_compile> LD=<path_to_cross_loader>'
+  then copy the module to the host FS: /lib/modules/<kernel_name>/kernel/net/ipsec/
+
+ + ipsec user (native) :
+  make sure that you have the kernel source on the FS.
+  'make KERNELSRC=<path to this release, after config> programs'
+  'make install'
+
+Note: before tunnel is enabled on target, reverse path filtering(rp_filter) must be disabled under sysfs, using
+      the following commands:
+      - echo 0  > /proc/sys/net/ipv4/conf/eth<x>/rp_filter
+      - echo 0  > /proc/sys/net/ipv4/conf/all/rp_filter
+
+Reverse Path Filtering(rp_filter): it is a technology that is used on IP routers to try and prevent source address spoofing,
+which is often used for DenialOfService attacks. RPF works by checking the source IP of each packet received on an interface
+against the routing table. If the best route for the source IP address does not use the same interface that the packet was received
+on the packet is dropped. 
+
+IPSec routing using encryption/authentication only
+
+  basic vpn connection:
+  +++++++++++++++++++++
+ - platform: conncted with egiga.
+ - make sure you have 'ip' (part of the iproute package) installed.
+ - edit /etc/ipsec.conf (on both sides) ,check the "man ipsec.conf" :
+
+config setup
+        interfaces="ipsec0=eth0"    # Virtual/physical interfaces
+        klipsdebug="none"             # Debug KLIPS
+        plutodebug="none"             # Debug PLUTO
+
+conn dove_psk_vpn
+    type=tunnel                    # type of the connection: tunnel(default),passthrough,transport,reject,drop
+    authby=secret
+    left=192.168.1.1
+    leftsubnet=192.168.1.0/16
+    right=192.168.0.1              # Remote information
+    rightsubnet=192.168.0.0/16
+    auto=start                     # start this connection at startup
+
+
+ - edit /etc/ipsec.secrets (on both sides) to have shared secret.
+192.168.1.1 192.168.0.1 : PSK "123456"
+
+ - side1: 'ifconfig eth0 192.168.0.1 netmask 255.255.0.0'
+ - side2: 'ifconfig eth0 192.168.1.1 netmask 255.255.0.0'
+ - check connectivity: ping from side1 to 192.168.1.1
+ - '/etc/init.d/ipsec start' (on both sides), create new interface ipsec0.
+ - check connectivity: ping from side1 to 192.168.1.1 --> VPN is working (make sure by sniffing)
+
diff --git a/cesa/openswan/ipsec_setup_kw2.sh b/cesa/openswan/ipsec_setup_kw2.sh
new file mode 100755
index 0000000..28fe3a2
--- /dev/null
+++ b/cesa/openswan/ipsec_setup_kw2.sh
@@ -0,0 +1,36 @@
+# This is an example how to setup the network interfaces in order to run IPSec routing
+
+ifconfig eth0 192.168.0.1 hw ether 00:00:00:00:61:92 netmask 255.255.0.0
+ifconfig eth1 192.167.0.1 hw ether 00:00:00:00:62:81 netmask 255.255.0.0
+echo 1 > /proc/sys/net/ipv4/ip_forward
+arp -s 192.167.0.250 00:00:00:00:00:12
+arp -s 192.168.1.1 00:00:00:00:00:11
+#IPSec Configuration
+insmod /ipsec.ko
+
+#SmartBit Configuration
+#eth0 - 192.168.1.1 --> 192.167.0.250
+#         00:00:00:00:00:12 --> 00:00:00:00:61:92
+#eth1   - 192.167.0.250 --> 192.168.1.1
+#         00:00:00:00:00:11 -> 00:00:00:00:62:81
+
+
+# unmark this to disble flow control for Yukon/E1000 NICs
+#ethtool -A eth0 tx off
+#ethtool -A eth0 rx off
+#ethtool -A eth2 tx off
+#ethtool -A eth2 rx off
+
+# Here we build static SA database since it is not supported anymore from OpenSWAN 2.6.18 and on
+# This is example setup for ESP 3DES/SHA1
+ipsec spi --clear
+ipsec eroute --clear
+enckey=0x0123456789abcdef02468ace13579bdf123456789abcdef0
+authkey=0x0123456789abcdef02468ace13579bdf12345678
+ipsec spi --af inet --edst 192.168.1.1 --spi 0x12345678 --proto esp --src 192.168.0.1 --esp 3des-sha1 --enckey $enckey --authkey $authkey
+ipsec spi --af inet --edst 192.168.1.1 --spi 0x12345678 --proto tun --src 192.168.0.1 --dst 192.168.1.1 --ip4
+ipsec spigrp inet 192.168.1.1 0x12345678 tun inet 192.168.1.1 0x12345678 esp
+ipsec eroute --add --eraf inet --src 192.167.0.0/16 --dst 192.168.1.0/24 --said tun0x12345678@192.168.1.1
+ipsec tncfg --attach --virtual ipsec0 --physical eth0
+ifconfig ipsec0 inet 192.168.0.1 netmask 255.255.0.0 broadcast 192.168.255.255 up
+route add -host 192.168.1.1 gw 192.168.0.1 dev ipsec0
diff --git a/crypto/Kconfig b/crypto/Kconfig
old mode 100644
new mode 100755
index 26b5dd0..cf9f4d5
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -812,4 +812,5 @@
 
 source "drivers/crypto/Kconfig"
 
+source "crypto/ocf/Kconfig"
 endif	# if CRYPTO
diff --git a/crypto/Makefile b/crypto/Makefile
old mode 100644
new mode 100755
index 9e8f619..e2135fc
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -83,7 +83,7 @@
 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
 obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
-obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
+obj-$(CONFIG_OCF_OCF) += ocf/
 
 #
 # generic algorithms and the async_tx api
diff --git a/crypto/ocf/ChangeLog b/crypto/ocf/ChangeLog
new file mode 100755
index 0000000..e913ef2
--- /dev/null
+++ b/crypto/ocf/ChangeLog
@@ -0,0 +1,1960 @@
+2008-09-18 01:27  davidm
+
+	* Makefile, README, README.sglinux,
+	patches/linux-2.6.26-natt.patch, patches/linux-2.6.26-ocf.patch,
+	patches/openssl-0.9.8g.patch, patches/openssl-0.9.8i.patch: 
+	
+	Updates for a new OCF release with openssl-0.9.8i and linux-2.6.26
+	support.
+
+2008-09-18 00:19  davidm
+
+	* Config.in, Kconfig, Makefile, ep80579/Makefile,
+	ep80579/environment.mk, ep80579/icp_asym.c, ep80579/icp_common.c,
+	ep80579/icp_ocf.h, ep80579/icp_sym.c,
+	ep80579/linux_2.6_kernel_space.mk: 
+	
+	A new driver from Intel for their Intel QuickAssist enabled EP80579
+	Integrated Processor Product Line.
+	
+	Adrian Hoban  Brad Vrabete
+	
+
+2008-07-25 01:01  gerg
+
+	* ocf-compat.h: 
+	
+	From linux-2.6.26 onwards there is now a linux/fdtable.h include
+	that contains the file_fdtable() definition.
+
+2008-07-05 01:20  davidm
+
+	* Makefile, patches/linux-2.6.25-natt.patch,
+	patches/linux-2.6.25-ocf.patch: 
+	
+	A new ocf-linux release and some patches to send to the OS guys.
+
+2008-07-03 21:21  davidm
+
+	* crypto.c: 
+	
+	Clean up a some possible deadlock/busy wait issues with
+	locking/sleeping.  This has greatly improved openswan 2.6.14
+	reliability ;-)
+	
+	Make more of our state available in /sys for debugging.
+
+2008-06-23 20:38  davidm
+
+	* Config.in, Kconfig: 
+	
+	Some settings should be bool's John Gumb 
+
+2008-05-28 03:43  philipc
+
+	* ixp4xx/ixp4xx.c:  Revert previous checkin since the
+	callbacks are meant to complete the crypto request.  Before
+	reverting this, CONFIG_DEBUG_SLAB gives: slab error in
+	verify_redzone_free(): cache `ixp4xx_q': double free detected when
+	trying to ssh to the device.
+
+2008-04-27 19:31  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	We were not completing a crypto request under some error
+	conditions.
+
+2008-04-02 01:51  davidm
+
+	* talitos/talitos.c: 
+	
+	This patch is for crypto/ocf/talitos for use on linux 2.6.23.  It
+	is applied to the ocf-linux-20071215 release.
+	
+	Signed-off-by: Lee Nipper 
+
+2008-02-29 00:43  davidm
+
+	* crypto.c, ocf-compat.h, ixp4xx/ixp4xx.c: 
+	
+	freshen  up the 2.4 support,  some recent OCF changes and openswan
+	changes are not that old-os friendly.
+	
+	Force OCF to select HW/SW,  otherwise it may get stuck on the first
+	device.  This change means we will favour HW over SW,  but we will
+	use both as required.  Passing in a crid of 0 to crypto_newsession
+	effectively meant we were stuck on the first device registered with
+	OCF,  not good.  This only applied to ipsec,  cryptodev already did
+	the right thing.
+
+2008-01-31 07:37  gerg
+
+	* hifn/hifn7751.c: 
+	
+	The linux-2.6.24 modules build fails if the pci ID table doesn't
+	have a NULL entry at the end. So add one.
+
+2008-01-29 09:16  gerg
+
+	* cryptosoft.c, ocf-compat.h: 
+	
+	Added some compatability macros for scatterlist changes from 2.6.24
+	onwards.
+
+2007-12-16 07:31  davidm
+
+	* Makefile: 
+	
+	missed an openssl patch name change
+
+2007-12-16 07:27  davidm
+
+	* Makefile, README, README.sglinux, patches/linux-2.6.23-ocf.patch,
+	patches/openssl-0.9.8e.patch, patches/openssl-0.9.8g.patch,
+	patches/ssl.patch: 
+	
+	updates for a new ocf release and associated bits
+
+2007-12-16 06:36  davidm
+
+	* crypto.c: 
+	
+	Be very careful what you do while potentially in an driver unload
+	state or we will call through NULL pointers.
+	
+	Reported by Nawang Chhetan .
+
+2007-12-14 22:32  davidm
+
+	* cryptodev.c: 
+	
+	Add in an unlock_ioctl when available to help SMP systems a lot. 
+	Otherwise all ioctls get a BKL :-(
+	
+	Problem found by Egor N. Martovetsky 
+
+2007-12-14 18:29  davidm
+
+	* cryptosoft.c: 
+	
+	reformat the alg table to make it easier to read.
+
+2007-12-14 18:29  davidm
+
+	* crypto.c: 
+	
+	Fix more driver locking/sleeping bugs report by Nawang Chhetan
+	
+
+2007-12-12 21:36  davidm
+
+	* Config.in, Kconfig, Makefile, pasemi/Makefile, pasemi/pasemi.c,
+	pasemi/pasemi_fnu.h: 
+	
+	Here I'm including my PA Semi driver patch to OCF.  Please consider
+	it for inclusion into next OCF release.
+	
+	Egor N. Martovetsky 
+
+2007-12-05 00:37  davidm
+
+	* patches/: linux-2.4.35-ocf.patch, linux-2.6.22-ocf.patch: 
+	
+	More correct count setting if we get a signal
+	
+	Adrian Hoban 
+
+2007-12-05 00:02  davidm
+
+	* random.c: 
+	
+	OCF has a static array for holding random data. The random number
+	generator I have can write directly into physically contiguous
+	memory. Static memory comes from the heap and isn't physically
+	contiguous. I could use kmalloc'd memory and then copy into the OCF
+	static buf but I'd like to avoid a memory copy. The following patch
+	(Physically_Contig_Rand.patch) allows me to avoid a memory copy and
+	should not impact the other OCF drivers:
+	
+	Adrian Hoban 
+
+2007-12-05 00:01  davidm
+
+	* Kconfig: 
+	
+	Fix a typo in the Kconfig
+
+2007-11-23 19:15  davidm
+
+	* talitos/talitos_dev.h: 
+	
+	fix the DPRINTF macro so that it actually compiles.
+
+2007-11-22 19:41  davidm
+
+	* ocf-compat.h, talitos/talitos.c, talitos/talitos_dev.h: 
+	
+	Various updates to get talitos compiling and work on real-world (ie
+	ubuntu) kernels.
+
+2007-11-08 02:21  davidm
+
+	* crypto.c: 
+	
+	keep and eye on us being completely blocked.  If we have Q's to
+	process, but all the requests are blocked,  sleep.  We do not want
+	to busy loop until a driver unblocks as it uses valuable CPU
+	resources that could be doing something much more important ;-)
+
+2007-11-07 19:04  davidm
+
+	* hifn/hifn7751.c: 
+	
+	hifn driver was failing to unblock itself under some "out of
+	resources" conditions.	It would return ERESTART to signal it was
+	full but never call crypto_unblock to start things moving again.
+
+2007-11-06 02:09  davidm
+
+	* hifn/hifn7751.c: 
+	
+	Remove some bogus trace left in the driver for the overflow (too
+	busy) case.
+
+2007-10-12 21:10  gerg
+
+	* crypto.c, ixp4xx/ixp4xx.c: 
+	
+	Fix up use of kmem_cache_create() - it takes one less argument in
+	2.6.23 onwards.
+
+2007-10-03 02:41  gerg
+
+	* ixp4xx/Makefile: 
+	
+	The directory locations for includes in CSR-2.4 is different.  Need
+	to modify the CFLAGS accordingly if using CSR-2.4.
+
+2007-09-22 00:39  philipc
+
+	* ixp4xx/Makefile:  linux 2.4 make dep was failing.  This is
+	a quick fix to get it building, need to double check this.
+
+2007-09-19 00:13  mmccreat
+
+	* Config.in:  Add config option CONFIG_OCF_IXP4XX_SHA1_MD5,
+	that enables SHA1 and MD5 hashing to be done by the IXP4xx crypto
+	accelerator (although it is much slower than using cryptosoft).
+
+2007-09-18 21:45  mmccreat
+
+	* Makefile, random.c:  - Force the inclusion of autoconf.h,
+	which contains #defines for CONFIG_xxx	 options for OCF.  -
+	Removing additional -D option, now that we are including the
+	CONFIG_xxx   #defines.
+
+2007-09-18 21:44  mmccreat
+
+	* Kconfig:  Add config option CONFIG_OCF_IXP4XX_SHA1_MD5,
+	that enables SHA1 and MD5 hashing to be done by the IXP4xx crypto
+	accelerator (although it is much slower than using cryptosoft).
+
+2007-09-18 21:37  mmccreat
+
+	* cryptodev.h:  The CRYPTO_MAX_DATA_LEN limit should be
+	0xFFFF ie 64K - 1.
+
+2007-09-18 21:19  mmccreat
+
+	* ixp4xx/ixp4xx.c:  - Rework the code so that the correct IXP
+	function, ixCryptoAccHashPerform(), is	 used to calculate SHA1 and
+	MD5 hashes.    NB: The performance of using the IXP4xx hardware is
+	really, really poor    compared to using cryptosoft (and the kernel
+	crypto).  - Only support SHA1 and MD5 hashing if the
+	CONFIG_OCF_IXP4XX_SHA1_MD5 is	enabled.
+
+2007-08-30 21:42  davidm
+
+	* Makefile: 
+	
+	do not archive build files in the crypto-tools archive
+
+2007-08-22 19:19  mmccreat
+
+	* cryptodev.c:  Fix up the checking for key lengths, when the
+	key can be of unlimited size.
+
+2007-08-16 01:50  davidm
+
+	* Makefile: 
+	
+	Better 2.4 compat for "make dep" now working with fastdep.
+
+2007-07-28 08:25  davidm
+
+	* Makefile, README, README.sglinux, patches/crypto-tools.patch,
+	patches/linux-2.4.29-ocf.patch, patches/linux-2.4.35-ocf.patch,
+	patches/linux-2.6.11-ocf.patch, patches/linux-2.6.22-ocf.patch,
+	patches/ssl.patch: 
+	
+	Update all the patches and put the patch making target back into
+	the Makefile.
+
+2007-07-28 08:25  davidm
+
+	* hifn/hifn7751.c: 
+	
+	fix an unused variable warning when HARVESTING is disabled
+
+2007-07-27 21:33  davidm
+
+	* hifn/hifn7751.c, ixp4xx/ixp4xx.c, safe/safe.c, talitos/talitos.c:
+	
+	
+	Remove all the random code if OCF does not have radom harvesting
+	enabled.
+
+2007-07-26 00:36  davidm
+
+	* Kconfig, hifn/hifnHIPP.c, hifn/hifnHIPPvar.h: 
+	
+	Changes to get the hifn HIPP stub driver to build.
+
+2007-07-25 21:25  davidm
+
+	* Makefile, hifn/Makefile, hifn/hifnHIPP.c, hifn/hifnHIPPreg.h,
+	hifn/hifnHIPPvar.h, ixp4xx/Makefile, ocfnull/Makefile,
+	safe/Makefile, talitos/Makefile: 
+	
+	Bring in the hifnHIPP driver written by Xelerance.  This is the
+	super hifn chip with full protocol offload.
+	
+	Switch to much more traditional Makefile/subdir building.  The
+	Makefiles are nicer now,  but still not beautiful,  2.6 and 2.4
+	capable builds result in a certain amount of uglyiness.
+
+2007-07-24 21:46  davidm
+
+	* cryptodev.c: 
+	
+	Clean up all the driver id checking and session management so
+	adding/removing drivers all continues to run cleanly.
+
+2007-07-24 20:14  davidm
+
+	* talitos/talitos.c: 
+	
+	From: Ahsan Kabir 
+	
+	less than .1% packet corruption was detected using the talitos
+	driver. It turns out we don't need the cipher iv out len/ptr field
+	to do ESP IPsec. Therefore we set the len field as 0, which tells
+	the SEC not to do anything with this len/ptr field.
+	
+	Signed-off-by: Ahsan Kabir 
+	Signed-off-by: Kim Phillips 
+
+2007-07-24 08:25  davidm
+
+	* cryptosoft.c, ocf-bench.c, hifn/hifn7751.c, ixp4xx/ixp4xx.c,
+	safe/safe.c, talitos/talitos.c: 
+	
+	Switch the remaining GFP_ATOMIC to the newer and not deprecated
+	SLAB_ATOMIC
+
+2007-07-23 22:16  mmccreat
+
+	* ixp4xx/ixp4xx.c:  Add missing ";" from end of dprintk()
+	call!
+
+2007-07-21 01:16  davidm
+
+	* ocf-compat.h, rndtest.c, hifn/hifn7751.c, safe/safe.c: 
+	
+	pci_register_driver is nothing like it is depending on the kernel,
+	so we need a compat function to fix it up for all kernels before
+	2.6.10, and in different ways for older and not so older versions.
+
+2007-07-20 21:54  davidm
+
+	* safe/safe.c: 
+	
+	Make the debug macro ';' safe so you do not get compiler warnings
+
+2007-07-20 21:53  davidm
+
+	* talitos/: talitos.c, talitos_dev.h, talitos_soft.h: 
+	
+	update to the latest FreeBSD driver structure and fix up the code
+	as required.
+
+2007-07-20 03:07  davidm
+
+	* rndtest.c: 
+	
+	more headers needed to compile on 2.4
+
+2007-07-20 03:00  davidm
+
+	* cryptosoft.c: 
+	
+	Put in the 2.4 stubs to support compression
+
+2007-07-20 02:53  davidm
+
+	* crypto.c, ocf-compat.h: 
+	
+	move some more compat stuff into the compat header.
+
+2007-07-20 02:47  davidm
+
+	* talitos/talitos.c: 
+	
+	support of_platform_driver for newer, ARCH=powerpc based kernels. 
+	Signed-off-by: Kim Phillips 
+
+2007-07-20 02:46  davidm
+
+	* talitos/talitos.c: 
+	
+	From: Ahsan Kabir 
+	
+	When Talitos completes job both the channel and execution unit are
+	capable of generating interrupts.  Talitos used to take two
+	interrupts per request - one for channel completion and the other
+	for execution unit completion. This patch ensures that Talitos
+	takes interrupt only for channel completion. Execution unit will
+	generate interrupt only when there is error and the error
+	interrupts for execution units are not masked.
+	
+	Signed-off-by: Ahsan Kabir 
+	Signed-off-by: Kim Phillips 
+
+2007-07-20 02:37  davidm
+
+	* cryptodev.c: 
+	
+	Unless the user specifies,  select from both HW and SW.
+	
+	Clean up some debug to report the actual ioctl name.
+	
+	Compiler warning on newer compilers.
+
+2007-07-20 02:35  davidm
+
+	* cryptodev.h: 
+	
+	moved dprintk to the compat code,  seemed nicer in there.
+
+2007-07-20 02:35  davidm
+
+	* rndtest.c: 
+	
+	Need to clean up some warnings etc,  more includes
+
+2007-07-20 02:34  davidm
+
+	* ocf-compat.h, hifn/hifn7751.c, safe/safe.c: 
+	
+	new shared IRQ flags for 2.6.22 and a safer version of the debug
+	macro
+
+2007-07-20 00:52  davidm
+
+	* cryptosoft.c: 
+	
+	Implement compression based on the code from the openswan guys.
+
+2007-07-20 00:52  davidm
+
+	* criov.c: 
+	
+	Fix compiler warning on non-value returning void func.
+
+2007-07-18 22:55  davidm
+
+	* hifn/hifn7751.c, safe/safe.c: 
+	
+	Use pci_register_driver rather than pci_module_init. 
+	pci_module_init has been dropped in 2.6.22 yet pci_register_driver
+	has always existed and used to do some crazy hotplug junk.
+
+2007-07-18 21:55  gerg
+
+	* ixp4xx/ixp4xx.c: 
+	
+	Added a missing ";" at the end of the ixp_kproces() prototype.	It
+	is IXP465 specific, only showed up when generateing for SG720.
+
+2007-07-17 00:37  davidm
+
+	* Makefile, cryptodev.c, random.c, rndtest.c, hifn/hifn7751.c,
+	ocfnull/ocfnull.c, safe/safe.c: 
+	
+	Fixup all the debug support for 2.4 kernels,  clean up the entropy
+	harvester to be far more robust.
+
+2007-07-14 02:19  davidm
+
+	* talitos/talitos.c: 
+	
+	Old patch that had not been applied Kim Phillips
+	
+
+2007-07-14 01:12  davidm
+
+	* Config.in, Kconfig, Makefile, cryptodev.c, cryptodev.h, random.c,
+	syscall.h: 
+	
+	Finally ditched all the syscall stuff.	You can now enable/disable
+	the random harvestor.  Pulled in most of random.c from openswan
+	project and fixed some obvious bugs (that were always there).
+
+2007-07-13 21:59  davidm
+
+	* ocf-compat.h: 
+	
+	Better error printing and checking for drivers
+
+2007-07-13 21:56  davidm
+
+	* cryptosoft.c: 
+	
+	Fix some incorrect debug (reporting wrong error type)
+
+2007-07-13 21:55  davidm
+
+	* hifn/hifn7751.c, safe/safe.c: 
+	
+	Make the code more similar to Free-BSD by reverting to the same
+	debug macros
+
+2007-07-13 21:53  davidm
+
+	* ocfnull/ocfnull.c: 
+	
+	Fix up the null driver to work again in the new framework.
+
+2007-07-06 23:54  mmccreat
+
+	* cryptodev.c, cryptodev.h, cryptosoft.c:  - Update OCF to
+	work with new Crypto API introduced in 2.6.19 kerneli, and add
+	macros so it work with older kernels.  - Add support for SHA256,
+	SHA384 and SHA512 HASH and HMAC algorithms.  - Cryptosoft: Only
+	register algorithms that the kernel has implementations for.
+
+2007-07-03 19:52  davidm
+
+	* Kconfig, README, README.sglinux, criov.c, crypto.c, cryptodev.c,
+	cryptodev.h, cryptosoft.c, ocf-bench.c, ocf-compat.h, random.c,
+	rndtest.c, uio.h, hifn/hifn7751.c, hifn/hifn7751reg.h,
+	hifn/hifn7751var.h, ixp4xx/ixp4xx.c, ocfnull/ocfnull.c,
+	safe/safe.c, safe/safevar.h, talitos/talitos.c: 
+	
+	Updated OCF to the lastest FreeBSD version.
+	
+	There was a lot of change in here,  some of which will help FIP's,
+	some which won't.
+	
+	Did lots of cleaning and diff reduction against the freebsd code. 
+	Still more cleaning to do.
+
+2007-06-01 21:58  gerg
+
+	* Config.in: 
+	
+	Put the regular old Config.in back, needed for puclic releases.
+
+2007-06-01 21:58  gerg
+
+	* Kconfig: 
+	
+	Change the CONFIG_OCF_IXP400 dependencies to be the same as they
+	where in the Config.in file.
+
+2007-05-28 21:40  gerg
+
+	* Config.in, Kconfig: 
+	
+	Switch all module configuration over to new style Kconfigs.
+
+2007-05-24 18:49  davidm
+
+	* cryptodev.c, random.c: 
+	
+	Work around some problems on redhat systems with errno redefinition
+
+2007-04-30 21:09  gerg
+
+	* cryptosoft.c: 
+	
+	The CRYPTO_TFM_MODE_ family of defines no longer exists from 2.6.21
+	onwards. As far as I can tell you don't need to pass it to the
+	crypto_alloc_tfm() function anymore.
+	
+	So define it to be 0 if it doesn't exist.
+
+2007-04-03 02:13  gerg
+
+	* syscall.h: 
+	
+	Added syscall macros for SH architecture. Just temporary, 'till
+	Dave fixes the OCF code to not use syscalls from the modules :-)
+
+2007-02-16 23:10  davidm
+
+	* syscall.h: 
+	
+	ensure the temprary 2.6 fix doesn't break 2.4
+
+2007-02-07 22:23  gerg
+
+	* cryptodev.c, random.c, syscall.h: 
+	
+	Temporary fix for new 2.6 kernels no longer defining in-kernel
+	system call functions. Define them locally for now until we fix
+	properly.
+
+2007-02-07 03:10  gerg
+
+	* ixp4xx/ixp4xx.c: 
+	
+	Changes to support the different INIT_WORK() mechanism from kernels
+	2.6.20 onwards.
+
+2007-02-06 02:38  gerg
+
+	* crypto.c: 
+	
+	Cleaned up use of kmem_cache_t and use of SLAB_ATOMIC.
+
+2006-12-05 20:50  cpascoe
+
+	* hifn/hifn7751.c, safe/safe.c, talitos/talitos.c: 
+	
+	Remove pt_regs from OCF interrupt handlers for 2.6.19+
+
+2006-12-02 03:36  gerg
+
+	* criov.c, crypto.c, cryptodev.c, cryptosoft.c, ocf-bench.c,
+	random.c, rndtest.c, hifn/hifn7751.c, ixp4xx/ixp4xx.c,
+	ocfnull/ocfnull.c, safe/safe.c, talitos/talitos.c: 
+	
+	Can no longer include linux/config.h as of 2.6.19 kernels.  Need to
+	conditionally include it based on AUTOCONF_INCLUDED not being
+	defined.
+
+2006-10-13 21:52  cpascoe
+
+	* random.c: 
+	
+	Remove another race condition that may result in us running more
+	than one random thread if modules are reloaded during heavy system
+	load.
+
+2006-10-13 21:18  cpascoe
+
+	* random.c: 
+	
+	- Permit delivery of SIGKILL to the random thread.  - Do not exit
+	prematurely if poll() is interrupted.  - Improve exit conditions so
+	that we quit immediately, rather than loop   infinitely, if the
+	last RNG source is removed while we are trying to   fill our
+	buffer.
+
+2006-10-03 20:28  cpascoe
+
+	* crypto.c, crypto.c:  AutoMerged
+	>
+	> Zero the empty half of "new driver" buffer, and not past the end
+	of the old
+	> buffer that we are about to free.
+
+2006-10-03 20:28  cpascoe
+
+	* crypto.c: 
+	
+	Zero the empty half of "new driver" buffer, and not past the end of
+	the old buffer that we are about to free.
+
+2006-08-25 23:57  davidm
+
+	* cryptosoft.c: 
+	
+	Do not print errors for failed ALG requests unless debugging
+
+2006-07-14 21:44  davidm
+
+	* cryptodev.h: 
+	
+	2.6.11 and earlier did not have the files_fdtable macro.
+
+2006-06-21 21:26  gerg
+
+	* cryptodev.h, hifn/hifn7751.c, ocfnull/ocfnull.c, safe/safe.c,
+	talitos/talitos.c: 
+	
+	Fixed up more occurrances of MODULE_PARM() needing to be converted
+	to module_param() (as of 2.6.17 and onwards).
+
+2006-06-21 00:28  gerg
+
+	* cryptosoft.c: 
+	
+	Change use of MODULE_PARM to module_param() for 2.6.17+ kernels.
+
+2006-06-20 22:13  gerg
+
+	* crypto.c, cryptodev.c, cryptodev.h, ocf-bench.c, ixp4xx/ixp4xx.c:
+	
+	
+	As of 2.6.17 and onwards module_param is used in place of
+	MODULE_PARM.
+
+2006-06-06 00:31  gerg
+
+	* Makefile: 
+	
+	Fix Makefile to find includes is using CSR-2.1.
+
+2006-05-31 01:44  gerg
+
+	* cryptodev.h: 
+	
+	The vars "crypto_usercrypto", "crypto_userasymcrypto" are declared
+	as extern in the header file, but static in the c file. I guessed
+	that they should probably be truely static, so removed the extern
+	declarations from the header.
+
+2006-05-25 21:06  davidm
+
+	* talitos/talitos.c: 
+	
+	This fixes a situation that I never provably experienced, where a
+	descriptor in memory may be reserved within the proper lock, and
+	freed immediately after, only for a few cycles, right outside the
+	lock.  Kim Phillips 
+
+2006-05-15 19:49  davidm
+
+	* criov.c, crypto.c, cryptodev.c, cryptodev.h, cryptosoft.c,
+	ocf-bench.c, random.c, rndtest.c, uio.h, ixp4xx/ixp4xx.c: 
+	
+	Remove the "all rights reserved" from the Intel copyrights.
+
+2006-05-12 21:19  davidm
+
+	* Config.in, Kconfig, Makefile, cryptodev.c, ocf-bench.c,
+	ocfnull/ocfnull.c: 
+	
+	Add in a null OCF driver that does nothing at all,  useful for
+	measuring the cost of various parts of the ipsec stack.
+
+2006-05-12 21:17  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	make sure we do not overwrite a correctly set error type.
+
+2006-05-12 06:52  davidm
+
+	* crypto.c: 
+	
+	Fix a problem where a driver would return ERESTART (full) but then
+	unblock itself before the upper layer had marked it as blocked. 
+	This caused the code to get stuck in crypto_proc and process no
+	more requests.
+
+2006-05-12 06:47  davidm
+
+	* cryptosoft.c: 
+	
+	Implement CRD_F_KEY_EXPLICIT for cryptosoft so keys can be changed
+	on an active session.
+
+2006-05-10 20:09  davidm
+
+	* README, criov.c, crypto.c, cryptodev.h, cryptosoft.c,
+	ocf-bench.c, random.c, rndtest.c, uio.h, hifn/hifn7751.c,
+	ixp4xx/ixp4xx.c, safe/safe.c, safe/safevar.h: 
+	
+	update email addresses and other house cleaning
+
+2006-05-10 20:08  davidm
+
+	* cryptodev.c: 
+	
+	pull in better error checking from openswan modifications
+
+2006-05-10 19:11  davidm
+
+	* cryptosoft.c: 
+	
+	Fix an unused variable warning when various options are disabled.
+
+2006-05-10 19:10  davidm
+
+	* cryptodev.h: 
+	
+	Add support for 2.4 kernels for the new FD cloning operation
+
+2006-05-09 19:48  davidm
+
+	* hifn/hifn7751.c: 
+	
+	remove the hifn 7855 support,  this driver will never work with
+	that chip.
+
+2006-05-08 23:34  davidm
+
+	* hifn/hifn7751var.h: 
+	
+	Contiguous buffer support so that ocf-bench can run properly.
+
+2006-05-05 23:21  davidm
+
+	* hifn/hifn7751.c: 
+	
+	Add in contiguous buffer support so that ocf-bench and run on the
+	driver.
+
+2006-05-05 23:14  davidm
+
+	* ocf-bench.c: 
+	
+	Our requests were out of order,  need to do crypto then auth on
+	encrypt requests.  Some drivers enforce this.
+
+2006-05-04 23:21  davidm
+
+	* crypto.c: 
+	
+	Do not run "newsession" with lock,  since newsession may sleep on
+	some targets.  Handle the accounting so that things are not pulled
+	from underneath us.
+
+2006-05-04 23:20  davidm
+
+	* cryptodev.c: 
+	
+	Switch to a less optimal (marginally) solution for creating a new
+	fd that appears to work in far more versions of the kernel
+	including 64bit versions.
+
+2006-05-04 18:54  davidm
+
+	* ocf-bench.c: 
+	
+	Turn off the IXP access lib benchmarking by default as most people
+	don't have it.
+	
+	Paul Wouters 
+
+2006-04-01 08:23  davidm
+
+	* Makefile: 
+	
+	Remove more temp files when cleaning
+
+2006-04-01 08:12  davidm
+
+	* hifn/hifn7751reg.h: 
+	
+	7855 PCI id's as yet untested
+
+2006-04-01 08:08  davidm
+
+	* hifn/hifn7751.c: 
+	
+	add PCI id's for the 7855 and AES support,  card is untested still
+	as it requires 128MB of PCI memory !
+
+2006-03-31 08:38  davidm
+
+	* README.sglinux: 
+	
+	small update to instructions with corrected patch name
+
+2006-03-31 00:23  davidm
+
+	* Config.in: 
+	
+	Add the Talitos driver to the 2.4 config,  even though it probably
+	won't compile.
+
+2006-03-30 07:48  davidm
+
+	* Kconfig, Makefile, talitos/talitos.c, talitos/talitos_dev.h,
+	talitos/talitos_soft.h: 
+	
+	Please find attached the freescale SEC driver for OCF.	It's been
+	(most recently) tested on an SEC2.0 based MPC8541E
+	(cryptographically identical to the MPC8555E) under 2.6.15.2, with
+	openssl-0.9.8a and openswan-2.4.3 (2.4.5rc5 won't keep the security
+	association up for me for some reason).
+	
+	Please feel free to add it to your next release of OCF-Linux :-)
+	
+	Kim Phillips 
+
+2006-03-20 19:34  davidm
+
+	* safe/: safe.c, safevar.h: 
+	
+	Safenet 1141 v1.0 chips have a DMA lockup error if you access the
+	chip while DMA'ing.  As a work around you need to limit your DMA to
+	256 byte chunks using scatter/gather descriptors.  All the SG/SME
+	products have v1.0 chips and would lockup with more than two
+	outstanding packets at one time.
+	
+	Fix the KASSERT macro
+	
+	Add some more exhaustive initialisation.
+
+2006-03-15 21:58  davidm
+
+	* cryptodev.h, random.c: 
+	
+	Switch random support to "ints" since that is what the kernel uses
+	and not using the same thing is 64bit wise a bad idea.
+	
+	Fix FIP's code to ensure correct amount of data is passed in.
+	
+	Add work around for broken 64bit OS RNG support (disable it)
+	
+	General code cleanups.
+
+2006-03-15 21:55  davidm
+
+	* hifn/hifn7751.c: 
+	
+	Fixes for 64bit OS's,  make sure PCI address are within bus space,
+	make sure we order writes to the bus so that chip functions
+	correctly.  Some small cleanups.
+
+2006-03-15 21:48  davidm
+
+	* hifn/hifn7751var.h: 
+	
+	Remove unused field from structure
+
+2006-03-15 21:47  davidm
+
+	* safe/safe.c: 
+	
+	Make the code more 64bit OS compatible,  force PCI address space
+	and so on.
+
+2006-03-09 20:42  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	If we call ixpCryptoAccInit() and it fails,  just assume that it
+	has already been called.  This allows our "rc" scripts to be
+	openswan and freeswan compatible ore easily.
+
+2006-02-28 23:21  davidm
+
+	* README: 
+	
+	generalise it a bit so rel-dates don't get in the way
+
+2006-02-28 01:52  davidm
+
+	* README, patches/ssh.patch, patches/ssl.patch: 
+	
+	Updated the README and patches for a release
+
+2006-02-25 09:21  davidm
+
+	* README, README.sglinux: 
+	
+	updates for a new release of OCF,  ssl patches and so on.
+
+2006-02-25 08:44  davidm
+
+	* crypto.c: 
+	
+	We were calling the "process"routines with interrupts disabled.  I
+	can see no good reason for this and it provokes badness warnings in
+	2.6 under some conditions.
+	
+	I am going to run with the Q's unlocked for processing,  and
+	hopefully it will allow the system to be more responsive.  It
+	hasn't affected ipsec throughput in any way.  Userland throughput
+	(multi threaded) may have improved significantly though,  but it
+	needs more testing.
+
+2006-02-24 23:32  davidm
+
+	* cryptodev.c: 
+	
+	Whoa,  set the segments with uninitted values can't be good.  Clean
+	out the rest of the old code that was accidently left in.
+
+2006-02-22 01:02  davidm
+
+	* cryptodev.c: 
+	
+	Still not sure about this one,	but this is working for all the
+	cases I can see so far.  If it gets weird,  I am going to switch to
+	a simple clone and chain the sessions rather than a new fcr per fd.
+
+2006-02-20 22:12  davidm
+
+	* cryptodev.c: 
+	
+	Error handling case could free data that was not allocated
+	
+	Ronen Shitrit  Marvell Semiconductor Israel
+	Ltd
+
+2006-02-20 21:57  davidm
+
+	* cryptosoft.c: 
+	
+	Proper SHA/MD5 (non hmac) implementation,  remove some retrictions
+	for hashes (which only applied to crypto) and fix over zealous
+	error checking.
+	
+	Ronen Shitrit  Marvell Semiconductor Israel
+	Ltd
+
+2006-02-09 21:15  davidm
+
+	* cryptodev.c: 
+	
+	The code wasn't quite right and needed some fixing for proper file
+	accounting.
+
+2006-01-24 20:08  davidm
+
+	* crypto.c, cryptodev.c, hifn/hifn7751.c: 
+	
+	We implement our own open in the CRIOGET ioctl now which does
+	pretty much the same thing as the BSD version,	rather than use an
+	open system call which gets caught out by chroot.
+
+2006-01-06 00:42  gerg
+
+	* cryptosoft.c: 
+	
+	Moved "{" block marker inside the set of
+	"defined(CONFIG_CRYPTO_HMAC) || defined(CONFIG_CRYPTO_HMAC_MODULE)"
+	code (in function swcr_process) so that it compiled if these where
+	not defined.
+
+2005-11-11 01:44  davidm
+
+	* Makefile, README: 
+	
+	cleanups for a general release of OCF
+
+2005-11-11 01:18  davidm
+
+	* patches/ssl.patch: 
+	
+	Updated the ssl patch to the latest and greatest changed we have
+	made.
+
+2005-11-10 21:41  davidm
+
+	* Makefile, ixp4xx/ixp4xx.c: 
+	
+	Better debug for bad input.
+	
+	Have make clean do more cleaning and less talking.
+
+2005-11-03 20:53  davidm
+
+	* cryptosoft.c: 
+	
+	clean up some compilation errors with various options on/off
+
+2005-10-25 00:25  davidm
+
+	* Makefile: 
+	
+	Add a patch target that generates full kernel patches to add OCF
+	into either a 2.4 or 2.6 kernel as a single patch.
+
+2005-10-25 00:24  davidm
+
+	* Kconfig: 
+	
+	Make sure all OCF settings depend on OCF_OCF
+
+2005-09-23 02:45  davidm
+
+	* README, README.sglinux: 
+	
+	new crypto-tools archive to keep the tools up to date
+
+2005-09-23 02:08  davidm
+
+	* Makefile, README, README.sglinux: 
+	
+	updates for doing OCF releases
+
+2005-09-23 01:59  davidm
+
+	* patches/: ssh.patch, ssl.patch: 
+	
+	updated the patches for the latest in fixes etc to ssh/ssl for a
+	new OCF release before the openswan 2.4.1 merge.
+
+2005-09-21 00:57  davidm
+
+	* Makefile, cryptosoft.c, hifn/hifn7751.c, ixp4xx/ixp4xx.c: 
+	
+	Fixes for building cleanly under 2.6
+
+2005-09-13 23:11  davidm
+
+	* ocf-bench.c: 
+	
+	Add an exit function for cleaner 2.6 support.  Patch from Ronen
+	Shitrit 
+
+2005-07-30 00:23  davidm
+
+	* cryptosoft.c: 
+	
+	Add proper hooks for MD5/SHA and their HMAC countrparts processing
+	from cryptodev.
+
+2005-07-29 01:50  davidm
+
+	* cryptodev.c: 
+	
+	cryptodev did not support MD5 and SHA1,  only the HMAC versions
+
+2005-07-29 01:05  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	register for MD5,  return 16 bytes for MD5 and 12 for MD5_HMAC, 
+	likewise for SHA1 (only 20 is not HMAC).
+
+2005-07-28 21:52  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	First pass fix of userland MD5 processing.  We now do as well as
+	the safenet does,  I think.
+
+2005-07-27 06:23  davidm
+
+	* cryptodev.c: 
+	
+	udelay doesn't give up the current thread, thus the kernel will get
+	locked if a process is killed but the hardware never completes the
+	crypto request.
+
+2005-07-22 02:07  davidm
+
+	* crypto.c, cryptodev.h: 
+	
+	Implement queuing limits for input/output and OCF requests.
+	
+	Implement 2.6 style work queues instead of the 2.4 task_queues.
+
+2005-07-21 20:42  davidm
+
+	* cryptodev.h, ocf-bench.c, ixp4xx/ixp4xx.c: 
+	
+	Fix OCF to use work queues,  add 2.4 version of work queues to
+	cryptodev.h for use in ipsec and elsewhere.
+	
+	Problem and initial patch provided by David Vrabel
+	.  Cleaned up and 2.4 support added by me.
+
+2005-07-21 19:08  davidm
+
+	* random.c: 
+	
+	Fix spinlock initialisation, problem reported by Andy @
+	windsorcarclub.co.uk.
+
+2005-07-20 20:24  davidm
+
+	* cryptodev.c: 
+	
+	fix a silly spelling mistake
+
+2005-07-08 00:56  gerg
+
+	* Makefile: 
+	
+	Only build ocf-bench when CONFIG_OCF_BENCH is acrually enabled.
+
+2005-06-27 20:29  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	Ok,  we need a simple implentation here or we go too slow for UDP
+	tests.	For now,  if the Q is full just ditch the packet,  someone
+	has to do it.
+
+2005-06-25 01:13  davidm
+
+	* safe/safe.c: 
+	
+	bytes swapping etc all seems wrong for safenet on BE,  these fixes
+	see both MD5 and SHA1 working with OpenSwan.
+
+2005-06-22 23:10  davidm
+
+	* random.c: 
+	
+	clean up some ifdef code a little
+
+2005-06-22 21:28  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	Make sure we do not call blocking functions from ISR callable
+	routines.  In this case we were calling ixCryptoAccCtxUnregister.
+	
+	Run all the random numbers through SHA1 process to ensure more
+	uniform distribution of bits (NOTE:  it is not more random in any
+	way)
+
+2005-06-21 00:11  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	do not process requests from the register callback, gets the AES
+	code all messed up.
+	
+	Align caches on HW cache boundaries ot improve speed.
+	
+	More tracking or potential errors.
+
+2005-06-15 01:55  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	technically ixCryptoAccCtxRegister cannot be called from IRQ
+	context, so run it from the immediate BH.
+
+2005-06-14 23:13  davidm
+
+	* ocf-bench.c: 
+	
+	Fix some compile warnings/errors
+
+2005-06-14 20:52  davidm
+
+	* Config.in, Kconfig, Makefile, ocf-bench.c: 
+	
+	Add in kernel benchmark driver
+	
+	Support for building under CSR 1.4 and 2.0 is now complete
+
+2005-06-14 20:51  davidm
+
+	* crypto.c: 
+	
+	Do not use immediate processing for SW drivers otherwise we hold a
+	lock for too long.  Instead force BATCH processing.
+	
+	Problem found by David Vrabel 
+
+2005-06-14 20:46  davidm
+
+	* cryptodev.c: 
+	
+	Fix up AES minimum key size
+	
+	Make some more variables static
+
+2005-06-14 20:36  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	Use kernel caches as they are more efficient and faster to obtain.
+	
+	Fix some spelling
+	
+	Tune PKE to only use the space required.  Turn off go fast options
+	to reduce any speed-related cracking.
+	
+	Only zero data that needs to be zeroed (save some cycles)
+
+2005-06-02 21:42  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	Added optimisations ideas from Intel the improve the PKE
+	performance for 512 and 1024 bits operations.
+
+2005-06-01 02:13  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	Looks like I found the ixp bug.  Using OSAL buffer routines on
+	non-OSAL buffers is a very very bad thing to do.  Must double check
+	all the API's I am using (ie., PKE) just to be sure.
+
+2005-05-31 21:38  davidm
+
+	* Config.in, Kconfig: 
+	
+	Updated/Added the menu wrapper for the config options
+
+2005-05-31 21:18  gerg
+
+	* Config.in: 
+	
+	Reworked the config.in so that each sub-module has its own
+	Config.in.  That way it is easier to make release trees with some
+	modules left in.
+
+2005-05-30 19:46  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	Not all the Pke code was appropriately ifdef'd
+
+2005-05-28 01:49  davidm
+
+	* cryptosoft.c: 
+	
+	We were not injecting data in the right places nor calling the
+	cipher code the best was under all situations.	We are now good
+	enought to do ESP/AH processing with 3DES and SHA1-HMAC.
+
+2005-05-28 01:42  davidm
+
+	* hifn/hifn7751.c: 
+	
+	Non atomic kmallocs at IRQ time are bad and cause lockups
+
+2005-05-21 08:31  davidm
+
+	* README, README.sglinux: 
+	
+	Some small updates to email and patches that no longer exist
+
+2005-05-21 08:25  davidm
+
+	* cryptosoft.c: 
+	
+	better error message on failure,  a lot of the error check we do
+	sems to break apps like cryptotest, not sure who is right yet.
+
+2005-05-21 00:55  davidm
+
+	* criov.c, crypto.c, cryptodev.c, cryptodev.h, cryptosoft.c,
+	random.c, rndtest.c, uio.h, hifn/hifn7751.c, ixp4xx/ixp4xx.c,
+	safe/safe.c, safe/safevar.h: 
+	
+	Convert to CyberGuard email addresses for OCF files.
+
+2005-05-21 00:28  davidm
+
+	* crypto.c, cryptodev.c, cryptosoft.c, hifn/hifn7751.c,
+	ixp4xx/ixp4xx.c, safe/safe.c: 
+	
+	final round of naming changes,	hifn driver also confirmed working
+	in SG710
+
+2005-05-20 23:50  davidm
+
+	* cryptosoft.c, random.c, uio.h, ixp4xx/ixp4xx.c: 
+	
+	more copyright/author updates etc for Intel
+
+2005-05-20 23:48  davidm
+
+	* criov.c, crypto.c, cryptodev.c, cryptodev.h, cryptosoft.c,
+	random.c, rndtest.c, uio.h, ixp4xx/ixp4xx.c, safe/safe.c,
+	safe/safevar.h: 
+	
+	updated copyrights to reflect Intels interest/investment in the
+	project
+
+2005-05-20 20:31  davidm
+
+	* hifn/: hifn7751.c, hifn7751var.h: 
+	
+	Most of a working SKB implementation now
+
+2005-05-20 20:30  davidm
+
+	* safe/: md5.c, md5.h, safe.c, sha1.c, sha1.h: 
+	
+	Full AH/ESP processing now working,  just added BSD sha/md5
+	routines as needed for now.
+
+2005-05-20 20:30  davidm
+
+	* random.c: 
+	
+	use the new BSD rndtest code rather than the old GPL fips code
+
+2005-05-20 20:28  davidm
+
+	* Makefile, fips.c, fips.h, rndtest.c, rndtest.h: 
+	
+	Get rid of the GPL version of the fips test and use a BSD licensed
+	version so no one can get upset and cry derivative :-)
+
+2005-05-20 08:19  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	High throughput improvements. Can now handle multiple simultaneous
+	requests.
+
+2005-05-20 00:55  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	
+	works with openswan/OCF for ipsec receive.
+	
+	fixes ESP/AUTH processing (esp. HMAC)
+	
+	This driver needs a rework for kernel IPSEC as it's current packet
+	at a time processing is not up to the task.
+
+2005-05-20 00:53  davidm
+
+	* cryptosoft.c: 
+	
+	working ESP/AUTH code now impleneted.  Can do RX processing for
+	openswan KLIPS.
+	
+	Fixes numerous problems in skb processing
+	
+	Fixes broken HMAC code and IV processing
+
+2005-05-14 01:44  davidm
+
+	* cryptodev.c, ixp4xx/ixp4xx.c: 
+	
+	Cleanup IXP key processing to guarantee only a single outstanding
+	request rather than relying on the intel driver to get it right. 
+	Stops us losing requests.
+	
+	Tighten up the cryptodev response to "no answer" so that we don't
+	take all the CPU.  Only happens if there is a driver bug.
+
+2005-05-14 00:07  davidm
+
+	* Config.in, Kconfig, Makefile, crypto.c, fips.c, fips.h, random.c,
+	ixp4xx/ixp4xx.c, tools/bench-ocf: 
+	
+	PKE and RNG support running on the ixp driver,	added PKE bench
+	marking to script.  Still some multi-thread problems in the PKE
+	code.
+	
+	Added FIP RNG checking option to config and code.
+
+2005-05-10 19:18  davidm
+
+	* Makefile, ixp4xx/ixp4xx.c: 
+	
+	Get the OCF stuff building for the 465 and CSR-2.0
+
+2005-04-27 19:18  davidm
+
+	* cryptodev.h, random.c, hifn/hifn7751.c, safe/safe.c: 
+	cleanup the random number interface some more
+
+2005-04-27 00:57  davidm
+
+	* cryptodev.h, cryptosoft.c, random.c, hifn/hifn7751.c,
+	ixp4xx/ixp4xx.c, patches/linux-2.4.29-add_true_randomness.patch,
+	patches/linux-2.6.11-add_true_randomness.patch, safe/safe.c,
+	safe/safevar.h: 
+	
+	Switch to a more "user" like random number handling.  Drivers no
+	longer poll for RNG data,  we pull it as needed to fill
+	/dev/random's entropy.
+	
+	Implement sk_buff handling within the OCF framework.
+	
+	fixup IV handling in cryptosoft.
+
+2005-04-27 00:41  davidm
+
+	* crypto.c: 
+	
+	Fix a race condition with the starting of kernel threads.  The
+	threads were running before the pid assignment in the parent.
+
+2005-03-24 23:57  davidm
+
+	* Makefile: 
+	include crypto-tools.patch in the release file
+	
+	
+
+2005-03-24 20:14  davidm
+
+	* safe/safe.c: 
+	Fixup compile time warnings due to some left over BSDisms
+	
+
+2005-03-24 00:53  davidm
+
+	* Makefile, README, README.sglinux, patches/linux-2.4.29-ocf.patch,
+	patches/linux-2.6.11-ocf.patch, patches/ocf-linux-2.4.29.patch,
+	patches/ocf-linux-2.6.11.patch: 
+	added cleaner patch names and a tarball target to aid releases
+	
+
+2005-03-24 00:28  davidm
+
+	* patches/crypto-tools.patch,
+	patches/linux-2.4.29-add_true_randomness.patch,
+	patches/linux-2.6.11-add_true_randomness.patch,
+	patches/ocf-linux-2.4.29.patch, patches/ocf-linux-2.6.11.patch,
+	patches/ssh.patch, patches/ssl.patch, tools/bench-ocf: 
+	move all the release file patches into CVS for simplicity
+	
+
+2005-03-23 20:37  davidm
+
+	* safe/safe.c: 
+	remove excessive debug from RNG routines so that you can turn on
+	debug and live through it
+	
+	
+
+2005-03-23 02:23  davidm
+
+	* safe/safe.c: 
+	fix memory corruption for mod_exp and the safenet,  we were copying
+	back more than the space available.
+	
+	
+
+2005-03-22 21:45  davidm
+
+	* crypto.c, cryptodev.c, cryptodev.h, safe/safe.c: 
+	fixup a major sync issues with key processing (callback called
+	before sleeping).  Improve its performance while we are there with
+	a CBIMM (callback immediate) option.
+	
+	
+
+2005-03-19 00:33  davidm
+
+	* random.c: 
+	A new randomness function for both 2.4 and 2.6 that replaces out
+	previous old solution for the hifn driver with more generic code
+	that works on both kernels.
+	
+		add_true_randomness(u_int32_t *buf, int nwords);
+	
+	
+
+2005-03-18 21:01  davidm
+
+	* Makefile, cryptodev.h, random.c, hifn/hifn7751.c, safe/safe.c: 
+	RNG support in both the safenet and the hifn plus the required
+	kernel support.
+	
+	"hd /dev/random" runs much much faster now :-)
+	
+	
+
+2005-03-17 23:29  toby
+
+	* cryptodev.c:  Make sure the CIOCASYMFEAT ioctl on
+	/dev/crypto copies out the capable features.
+
+2005-03-17 01:19  davidm
+
+	* safe/: safe.c, safereg.h, safevar.h: 
+	hardware PK acceleration on the safenet (CRK_MOD_EXP only)
+	
+
+2005-03-16 04:28  davidm
+
+	* criov.c, crypto.c, cryptodev.c, safe/safe.c: 
+	fixup the FBSD id stuff to compile :-) 
+
+2005-03-16 04:02  davidm
+
+	* README, README.sglinux, TODO: 
+	Updated with versions,	removed tabs,  new kernel versions, web
+	site etc 
+
+2005-03-16 03:45  davidm
+
+	* criov.c, crypto.c, cryptodev.c, cryptodev.h: 
+	more license formatting and version id's to help keep in touch with
+	FreeBSD 
+
+2005-03-16 03:16  davidm
+
+	* safe/safe.c: 
+	up to date with FreeBSD versioning, no changes to merge 
+
+2005-03-16 03:15  davidm
+
+	* safe/safe.c: 
+	include FreeBSD version info so I can track changes better
+	
+
+2005-03-16 03:11  davidm
+
+	* hifn/: hifn7751.c, hifn7751reg.h, hifn7751var.h: 
+	incorporate latest updates from FreeBSD:
+	
+	| Update support for 795x parts: | o rework pll setup code to
+	follow h/w specification | o add hint.hifn.X.pllconfig to specify
+	reference clock setup |   requirements; default is pci66 which
+	means the clock is |   derived from the PCI bus clock and the card
+	resides in a |	 66MHz slot | | Tested on 7955 and 7956 cards;
+	support for 7954 cards not enabled | since we have no cards to test
+	against.
+	
+	
+
+2005-03-16 02:50  davidm
+
+	* Config.in, Kconfig, README, crypto.c, cryptodev.c, cryptodev.h,
+	hifn/hifn7751.c, hifn/hifn7751var.h, safe/safe.c, safe/safevar.h: 
+	cleanups to build and run on 2.6.11 and 2.4.29 for a public release
+	
+	included configs locally to reduce patch to kernel and required
+	user effort.
+	
+	pci_dma_sync_single fix from Michele Baldessari
+	,	with modifications by me to work on all
+	kernels.
+	
+	
+
+2005-03-11 23:30  davidm
+
+	* Makefile: 
+	fix up the compiling again, I had outstanding commits for this one
+	:-) 
+
+2005-03-11 21:56  danield
+
+	* Makefile: Get ocf modules building again.  
+
+2004-12-25 07:12  davidm
+
+	* TODO: 
+	safenet is all good now AKAIK 
+
+2004-12-25 07:02  davidm
+
+	* Makefile, crypto.c, cryptodev.c, cryptosoft.c, uio.h: 
+	2.6 port of the OCF framework,	tested on Xscale and compiled for
+	x86
+	
+	
+
+2004-12-10 02:41  davidm
+
+	* hifn/hifn7751.c: 
+	Fix compilation as l_flags was not defined for LOCK in pci_remove
+	
+
+2004-12-06 19:15  davidm
+
+	* hifn/hifn7751.c, safe/safe.c: 
+	* Put locking into hifn_remove to ensure interrupts are not running
+	while we   remove the driver
+	
+	  Use del_timer_sync (need to ensure timer is not running on
+	another CPU
+	* when we delete it).
+	
+	Improvements suggested by Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+	
+
+2004-12-02 09:16  davidm
+
+	* README, README.sglinux: 
+	* Fix up all tabs to be spaces * explain how to update the ocf
+	support in the patch to the current version.
+	
+	
+
+2004-12-02 09:11  davidm
+
+	* README: 
+	* fix some spelling/grammar * add more info on the ssl.patch file
+	and what it contains 
+
+2004-12-02 09:08  davidm
+
+	* README.sglinux: 
+	give some more instructions on the shar archive and extracting the
+	release.  
+
+2004-12-02 09:03  davidm
+
+	* README.sglinux: 
+	how to include crypto-tools into 3.1.6
+	
+	
+
+2004-12-02 08:48  davidm
+
+	* README.sglinux: 
+	updated for a new crypto patch for openssl-0.9.7e 
+
+2004-12-02 08:04  davidm
+
+	* README, README.sglinux: 
+	Clean up the README's to use the new SG Linux alpha and a specific
+	2.4.28 patch.
+	
+	
+
+2004-12-01 23:11  davidm
+
+	* Makefile, criov.c, crypto.c, cryptodev.c, cryptosoft.c,
+	hifn/Makefile, hifn/hifn7751.c, ixp4xx/Makefile, ixp4xx/ixp4xx.c,
+	safe/Makefile, safe/safe.c: 
+	Re-worked the Makefiles so that including the code into a standard
+	non-SG kernel is really easy.
+	
+	Fixed a non-initialised bug that was introduce into cryptosoft.c
+	with the additional error checking.
+	
+	
+
+2004-12-01 01:54  davidm
+
+	* TODO: 
+	updates based on things that have been fixed.  
+
+2004-12-01 01:53  davidm
+
+	* safe/: safe.c, safevar.h: 
+	Cleanup some old hacks based on the much cleaner port of the hifn
+	driver.  
+
+2004-12-01 01:53  davidm
+
+	* cryptosoft.c: 
+	fix some crashes due to bad buffer sizes etc.  
+
+2004-11-27 09:16  davidm
+
+	* crypto.c, cryptodev.c, ixp4xx/ixp4xx.c: 
+	Fixed some nasty problems that were stopping reliable behaviour:
+	
+	1) we were not initialising some of our lists/wait queues,  which  
+	 meant they appears to have things in them when in fact they did
+	not.	 This actually didn't seems to cause any problems but is
+	extremely bogus.
+	
+	2) While a process was waiting for the crypto engine,  if
+	itreceived a	signal we would lose sync with the engine and end
+	up allowing out-of-band    actions that were invalid (ie.,
+	unregistering a context that was still	  active in a crypto
+	operation).
+	
+	   Of source the CryptACC should probably deal with this as well
+	;-)
+	
+	
+
+2004-11-26 01:33  davidm
+
+	* TODO: 
+	We should also hook in the random number generators to linux
+	
+
+2004-11-26 01:33  davidm
+
+	* hifn/hifn7751.c: 
+	Changed all the accesses to DMS descriptors to not set the valid
+	bit until after everything else was set.  This got the driver
+	running smoothly, along with a fixup to the pci_map_uio which
+	wasn't settings lengths correctly.
+	
+	
+
+2004-11-25 21:15  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	document why using a new context for each packet is actually a
+	better idea than allocating one (actually two) per session.
+	
+	
+
+2004-11-25 08:48  davidm
+
+	* README, README.sglinux: 
+	updates from email with Intel to fix a few little things
+	
+
+2004-11-25 00:02  davidm
+
+	* README, README.sglinux, safe/safe.c: 
+	Some cleanups of doc and so on for Intel/General use 
+
+2004-11-23 07:58  davidm
+
+	* TODO: 
+	safenet is working on big endian machines now
+	
+	
+
+2004-11-23 07:56  davidm
+
+	* ixp4xx/: Makefile, ixp4xx.c: 
+	Reference the Intel library,  cleanup the IV sizes and turn on AES.
+	 Fix Makefile for new config options.
+	
+	
+
+2004-11-23 07:52  davidm
+
+	* Makefile: 
+	Complete the changes of ixp to ixp4xx (IXP4xx) as appropriate
+	
+
+2004-11-23 00:33  davidm
+
+	* Makefile, README, ixp4xx/Makefile: 
+	Changes all references to ixp to be ixp4xx at Intels request
+	
+
+2004-11-20 01:07  davidm
+
+	* safe/: safe.c, safereg.h: 
+	fully working safenet on BE machines 
+
+2004-11-19 01:03  davidm
+
+	* Makefile, hifn/Makefile, hifn/hifn7751.c, hifn/hifn7751reg.h,
+	hifn/hifn7751var.h: 
+	hifn driver code complete and compiling,  needs a test now ;-)
+	
+
+2004-11-18 21:45  davidm
+
+	* hifn/: Makefile, hifn7751.c, hifn7751var.h: 
+	Makefile for building the hifn driver 
+
+2004-11-18 21:44  davidm
+
+	* hifn/: hifn7751.c, hifn7751reg.h, hifn7751var.h: 
+	Checkin the orginal freebsd source for the hifn driver as a
+	reference in the future.
+	
+	
+
+2004-11-18 10:05  davidm
+
+	* Makefile, README, TODO, criov.c, crypto.c, cryptodev.c,
+	cryptodev.h, cryptosoft.c, uio.h, ixp4xx/Makefile, ixp4xx/ixp4xx.c,
+	safe/Makefile, safe/safe.c, safe/safevar.h: 
+	Clean up license and copyright info to be more acceptable (and
+	present) Clean up debug and trace Fixup memory freeing etc on
+	safenet Fix compiler warnings (some were bugs)
+	
+	
+
+2004-11-17 02:23  davidm
+
+	* safe/safe.c: 
+	working on Xscale (big endian) now but packet data is getting
+	stuffed up due to endian problems (at least now we are talking to
+	the chip correctly for BE).  Good enough to test packet throughput,
+	 no good for testing scp.
+	
+	
+
+2004-11-17 02:21  davidm
+
+	* criov.c: 
+	Make sure public symbols are exported by including the correct
+	header files 
+
+2004-11-17 02:15  davidm
+
+	* crypto.c: 
+	even better cleanup of kernel threads on exit 
+
+2004-11-17 02:15  davidm
+
+	* cryptosoft.c: 
+	return some trace to debug so it doesn't appear 
+
+2004-11-17 02:14  davidm
+
+	* Makefile: 
+	Make sure all drivers get built, not just IXP 
+
+2004-11-16 21:31  davidm
+
+	* crypto.c: 
+	Fix problem with reboots and driver not unloading cleanly,  we were
+	not handling signals correctly in the kernel threads, 
+
+2004-11-10 10:46  davidm
+
+	* ixp4xx/ixp4xx.c: 
+	fix serious context leak,  itturns out the context is still
+	considered busy while it is calling the perform callback,  so we
+	cleanup on closing the session and on allocating the next context
+	to work around this.
+	
+	
+
+2004-11-10 05:26  davidm
+
+	* crypto.c, cryptodev.c, ixp4xx/ixp4xx.c, safe/safe.c: 
+	cleaned out some debug,  found MAX tunnels bug,  traced it various
+	other cleanups.
+	
+	
+
+2004-11-10 04:02  davidm
+
+	* cryptodev.c, cryptosoft.c, ixp4xx/ixp4xx.c, safe/Makefile,
+	safe/safe.c: 
+	Fix up kmalloc usage to always zero resulting buffer everywhere   
+	(stops crashes in ixp)
+	
+	Add some function debug to ixp so you can see it working
+	
+	Fix safe driver to build and install in a real tree.
+	
+	
+
+2004-11-10 02:27  davidm
+
+	* Makefile, criov.c, crypto.c, cryptosoft.c, ixp4xx/Makefile,
+	ixp4xx/ixp4xx.c: 
+	Compiling OCF modules for the IXP crypto, needs testing now
+	
+
+2004-11-09 19:16  davidm
+
+	* criov.c, crypto.c, cryptodev.c, cryptodev.h, cryptosoft.c,
+	cryptosoft.h, uio.h, safe/safe.c, safe/safevar.h: 
+	The linux port of OCF with working safenet and software modules. 
+	Still some bugs with mutiple crypto threads using the safenet
+	driver.
+	
+	
+
+2004-11-09 18:49  davidm
+
+	* Makefile, criov.c, crypto.c, cryptodev.c, cryptodev.h,
+	cryptosoft.c, cryptosoft.h, uio.h, safe/Makefile, safe/safe.c,
+	safe/safereg.h, safe/safevar.h: 
+	Check in the orginal free-bsd sources for the OCF support.  This
+	allows us to diff against it later to see if we botched anything
+	major league.
+	
+	
+
diff --git a/crypto/ocf/Config.in b/crypto/ocf/Config.in
new file mode 100755
index 0000000..cb01ea9
--- /dev/null
+++ b/crypto/ocf/Config.in
@@ -0,0 +1,34 @@
+#############################################################################
+
+mainmenu_option next_comment
+comment 'OCF Configuration'
+tristate 'OCF (Open Cryptograhic Framework)' CONFIG_OCF_OCF
+dep_mbool '  enable fips RNG checks (fips check on RNG data before use)' \
+				CONFIG_OCF_FIPS $CONFIG_OCF_OCF
+dep_mbool '  enable harvesting entropy for /dev/random' \
+				CONFIG_OCF_RANDOMHARVEST $CONFIG_OCF_OCF
+dep_tristate '  cryptodev (user space support)' \
+				CONFIG_OCF_CRYPTODEV $CONFIG_OCF_OCF
+dep_tristate '  cryptosoft (software crypto engine)' \
+				CONFIG_OCF_CRYPTOSOFT $CONFIG_OCF_OCF
+dep_tristate '  safenet (HW crypto engine)' \
+				CONFIG_OCF_SAFE $CONFIG_OCF_OCF
+dep_tristate '  IXP4xx (HW crypto engine)' \
+				CONFIG_OCF_IXP4XX $CONFIG_OCF_OCF
+dep_mbool    '  Enable IXP4xx HW to perform SHA1 and MD5 hashing (very slow)' \
+				CONFIG_OCF_IXP4XX_SHA1_MD5 $CONFIG_OCF_IXP4XX
+dep_tristate '  hifn (HW crypto engine)' \
+				CONFIG_OCF_HIFN $CONFIG_OCF_OCF
+dep_tristate '  talitos (HW crypto engine)' \
+				CONFIG_OCF_TALITOS $CONFIG_OCF_OCF
+dep_tristate '  pasemi (HW crypto engine)' \
+				CONFIG_OCF_PASEMI $CONFIG_OCF_OCF
+dep_tristate '  ep80579 (HW crypto engine)' \
+				CONFIG_OCF_EP80579 $CONFIG_OCF_OCF
+dep_tristate '  ocfnull (does no crypto)' \
+				CONFIG_OCF_OCFNULL $CONFIG_OCF_OCF
+dep_tristate '  ocf-bench (HW crypto in-kernel benchmark)' \
+				CONFIG_OCF_BENCH $CONFIG_OCF_OCF
+endmenu
+
+#############################################################################
diff --git a/crypto/ocf/Kconfig b/crypto/ocf/Kconfig
new file mode 100755
index 0000000..74b98b2
--- /dev/null
+++ b/crypto/ocf/Kconfig
@@ -0,0 +1,101 @@
+menu "OCF Configuration"
+
+config OCF_OCF
+	tristate "OCF (Open Cryptograhic Framework)"
+	help
+	  A linux port of the OpenBSD/FreeBSD crypto framework.
+
+config OCF_RANDOMHARVEST
+	bool "crypto random --- harvest entropy for /dev/random"
+	depends on OCF_OCF
+	help
+	  Includes code to harvest random numbers from devices that support it.
+
+config OCF_FIPS
+	bool "enable fips RNG checks"
+	depends on OCF_OCF && OCF_RANDOMHARVEST
+	help
+	  Run all RNG provided data through a fips check before
+	  adding it /dev/random's entropy pool.
+
+config OCF_CRYPTODEV
+	tristate "cryptodev (user space support)"
+	depends on OCF_OCF
+	help
+	  The user space API to access crypto hardware.
+
+config OCF_CRYPTOSOFT
+	tristate "cryptosoft (software crypto engine)"
+	depends on OCF_OCF
+	help
+	  A software driver for the OCF framework that uses
+	  the kernel CryptoAPI.
+
+config OCF_SAFE
+	tristate "safenet (HW crypto engine)"
+	depends on OCF_OCF
+	help
+	  A driver for a number of the safenet Excel crypto accelerators.
+	  Currently tested and working on the 1141 and 1741.
+
+config OCF_IXP4XX
+	tristate "IXP4xx (HW crypto engine)"
+	depends on OCF_OCF
+	help
+	  XScale IXP4xx crypto accelerator driver.  Requires the
+	  Intel Access library.
+
+config OCF_IXP4XX_SHA1_MD5
+	bool "IXP4xx SHA1 and MD5 Hashing"
+	depends on OCF_IXP4XX
+	help
+	  Allows the IXP4xx crypto accelerator to perform SHA1 and MD5 hashing.
+	  Note: this is MUCH slower than using cryptosoft (software crypto engine).
+
+config OCF_HIFN
+	tristate "hifn (HW crypto engine)"
+	depends on OCF_OCF
+	help
+	  OCF driver for various HIFN based crypto accelerators.
+	  (7951, 7955, 7956, 7751, 7811)
+
+config OCF_HIFNHIPP
+	tristate "Hifn HIPP (HW packet crypto engine)"
+	depends on OCF_OCF
+	help
+	  OCF driver for various HIFN (HIPP) based crypto accelerators
+	  (7855)
+
+config OCF_TALITOS
+	tristate "talitos (HW crypto engine)"
+	depends on OCF_OCF
+	help
+	  OCF driver for Freescale's security engine (SEC/talitos).
+
+config OCF_PASEMI
+	tristate "pasemi (HW crypto engine)"
+	depends on OCF_OCF && PPC_PASEMI
+	help
+	  OCF driver for the PA Semi PWRficient DMA Engine
+
+config OCF_EP80579
+	tristate "ep80579 (HW crypto engine)"
+	depends on OCF_OCF
+	help
+	  OCF driver for the Intel EP80579 Integrated Processor Product Line.
+
+config OCF_OCFNULL
+	tristate "ocfnull (fake crypto engine)"
+	depends on OCF_OCF
+	help
+	  OCF driver for measuring ipsec overheads (does no crypto)
+
+config OCF_BENCH
+	tristate "ocf-bench (HW crypto in-kernel benchmark)"
+	depends on OCF_OCF
+	help
+	  A very simple encryption test for the in-kernel interface
+	  of OCF.  Also includes code to benchmark the IXP Access library
+	  for comparison.
+
+endmenu
diff --git a/crypto/ocf/Makefile b/crypto/ocf/Makefile
new file mode 100755
index 0000000..cae4b25
--- /dev/null
+++ b/crypto/ocf/Makefile
@@ -0,0 +1,121 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+OCF_OBJS = crypto.o criov.o
+
+ifdef CONFIG_OCF_RANDOMHARVEST
+	OCF_OBJS += random.o
+endif
+
+ifdef CONFIG_OCF_FIPS
+	OCF_OBJS += rndtest.o
+endif
+
+# Add in autoconf.h to get #defines for CONFIG_xxx
+AUTOCONF_H=$(ROOTDIR)/modules/autoconf.h
+ifeq ($(AUTOCONF_H), $(wildcard $(AUTOCONF_H)))
+	EXTRA_CFLAGS += -include $(AUTOCONF_H)
+	export EXTRA_CFLAGS
+endif
+
+ifndef obj
+	obj ?= .
+	_obj = subdir
+	mod-subdirs := safe hifn ixp4xx talitos ocfnull
+	export-objs += crypto.o criov.o random.o
+	list-multi += ocf.o
+	_slash :=
+else
+	_obj = obj
+	_slash := /
+endif
+
+EXTRA_CFLAGS += -I$(obj)/.
+
+obj-$(CONFIG_OCF_OCF)         += ocf.o
+obj-$(CONFIG_OCF_CRYPTODEV)   += cryptodev.o
+obj-$(CONFIG_OCF_CRYPTOSOFT)  += cryptosoft.o
+obj-$(CONFIG_OCF_BENCH)       += ocf-bench.o
+
+$(_obj)-$(CONFIG_OCF_SAFE)    += safe$(_slash)
+$(_obj)-$(CONFIG_OCF_HIFN)    += hifn$(_slash)
+$(_obj)-$(CONFIG_OCF_IXP4XX)  += ixp4xx$(_slash)
+$(_obj)-$(CONFIG_OCF_TALITOS) += talitos$(_slash)
+$(_obj)-$(CONFIG_OCF_PASEMI)  += pasemi$(_slash)
+#$(_obj)-$(CONFIG_OCF_EP80579) += ep80579$(_slash)
+$(_obj)-$(CONFIG_OCF_OCFNULL) += ocfnull$(_slash)
+
+ocf-objs := $(OCF_OBJS)
+
+$(list-multi) dummy1: $(ocf-objs)
+	$(LD) -r -o $@ $(ocf-objs)
+
+.PHONY:
+clean:
+	rm -f *.o *.ko .*.o.flags .*.ko.cmd .*.o.cmd .*.mod.o.cmd *.mod.c
+	rm -f */*.o */*.ko */.*.o.cmd */.*.ko.cmd */.*.mod.o.cmd */*.mod.c */.*.o.flags
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
+#
+# release gen targets
+#
+
+.PHONY: patch
+patch:
+	REL=`date +%Y%m%d`; \
+		patch=ocf-linux-$$REL.patch; \
+		patch24=ocf-linux-24-$$REL.patch; \
+		patch26=ocf-linux-26-$$REL.patch; \
+		( \
+			find . -name Makefile; \
+			find . -name Config.in; \
+			find . -name Kconfig; \
+			find . -name README; \
+			find . -name '*.[ch]' | grep -v '.mod.c'; \
+		) | while read t; do \
+			diff -Nau /dev/null $$t | sed 's?^+++ \./?+++ linux/crypto/ocf/?'; \
+		done > $$patch; \
+		cat patches/linux-2.4.35-ocf.patch $$patch > $$patch24; \
+		cat patches/linux-2.6.26-ocf.patch $$patch > $$patch26
+
+.PHONY: tarball
+tarball:
+	REL=`date +%Y%m%d`; RELDIR=/tmp/ocf-linux-$$REL; \
+		CURDIR=`pwd`; \
+		rm -rf /tmp/ocf-linux-$$REL*; \
+		mkdir -p $$RELDIR/tools; \
+		cp README* $$RELDIR; \
+		cp patches/openss*.patch $$RELDIR; \
+		cp patches/crypto-tools.patch $$RELDIR; \
+		cp tools/[!C]* $$RELDIR/tools; \
+		cd ..; \
+		tar cvf $$RELDIR/ocf-linux.tar \
+					--exclude=CVS \
+					--exclude=.* \
+					--exclude=*.o \
+					--exclude=*.ko \
+					--exclude=*.mod.* \
+					--exclude=README* \
+					--exclude=ocf-*.patch \
+					--exclude=ocf/patches/openss*.patch \
+					--exclude=ocf/patches/crypto-tools.patch \
+					--exclude=ocf/tools \
+					ocf; \
+		gzip -9 $$RELDIR/ocf-linux.tar; \
+		cd /tmp; \
+		tar cvf ocf-linux-$$REL.tar ocf-linux-$$REL; \
+		gzip -9 ocf-linux-$$REL.tar; \
+		cd $$CURDIR/../../user; \
+		rm -rf /tmp/crypto-tools-$$REL*; \
+		tar cvf /tmp/crypto-tools-$$REL.tar \
+					--exclude=CVS \
+					--exclude=.* \
+					--exclude=*.o \
+					--exclude=cryptotest \
+					--exclude=cryptokeytest \
+					crypto-tools; \
+		gzip -9 /tmp/crypto-tools-$$REL.tar
+
diff --git a/crypto/ocf/criov.c b/crypto/ocf/criov.c
new file mode 100755
index 0000000..3bf7c32
--- /dev/null
+++ b/crypto/ocf/criov.c
@@ -0,0 +1,215 @@
+/*      $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $	*/
+
+/*
+ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ * The license and original author are listed below.
+ *
+ * Copyright (c) 1999 Theo de Raadt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+__FBSDID("$FreeBSD: src/sys/opencrypto/criov.c,v 1.5 2006/06/04 22:15:13 pjd Exp $");
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/uio.h>
+#include <linux/skbuff.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+
+#include <uio.h>
+#include <cryptodev.h>
+
+/*
+ * This macro is only for avoiding code duplication, as we need to skip
+ * given number of bytes in the same way in three functions below.
+ */
+#define	CUIO_SKIP()	do {						\
+	KASSERT(off >= 0, ("%s: off %d < 0", __func__, off));		\
+	KASSERT(len >= 0, ("%s: len %d < 0", __func__, len));		\
+	while (off > 0) {						\
+		KASSERT(iol >= 0, ("%s: empty in skip", __func__));	\
+		if (off < iov->iov_len)					\
+			break;						\
+		off -= iov->iov_len;					\
+		iol--;							\
+		iov++;							\
+	}								\
+} while (0)
+
+void
+cuio_copydata(struct uio* uio, int off, int len, caddr_t cp)
+{
+	struct iovec *iov = uio->uio_iov;
+	int iol = uio->uio_iovcnt;
+	unsigned count;
+
+	CUIO_SKIP();
+	while (len > 0) {
+		KASSERT(iol >= 0, ("%s: empty", __func__));
+		count = min((int)(iov->iov_len - off), len);
+		memcpy(cp, ((caddr_t)iov->iov_base) + off, count);
+		len -= count;
+		cp += count;
+		off = 0;
+		iol--;
+		iov++;
+	}
+}
+
+void
+cuio_copyback(struct uio* uio, int off, int len, caddr_t cp)
+{
+	struct iovec *iov = uio->uio_iov;
+	int iol = uio->uio_iovcnt;
+	unsigned count;
+
+	CUIO_SKIP();
+	while (len > 0) {
+		KASSERT(iol >= 0, ("%s: empty", __func__));
+		count = min((int)(iov->iov_len - off), len);
+		memcpy(((caddr_t)iov->iov_base) + off, cp, count);
+		len -= count;
+		cp += count;
+		off = 0;
+		iol--;
+		iov++;
+	}
+}
+
+/*
+ * Return a pointer to iov/offset of location in iovec list.
+ */
+struct iovec *
+cuio_getptr(struct uio *uio, int loc, int *off)
+{
+	struct iovec *iov = uio->uio_iov;
+	int iol = uio->uio_iovcnt;
+
+	while (loc >= 0) {
+		/* Normal end of search */
+		if (loc < iov->iov_len) {
+	    		*off = loc;
+	    		return (iov);
+		}
+
+		loc -= iov->iov_len;
+		if (iol == 0) {
+			if (loc == 0) {
+				/* Point at the end of valid data */
+				*off = iov->iov_len;
+				return (iov);
+			} else
+				return (NULL);
+		} else {
+			iov++, iol--;
+		}
+    	}
+
+	return (NULL);
+}
+
+EXPORT_SYMBOL(cuio_copyback);
+EXPORT_SYMBOL(cuio_copydata);
+EXPORT_SYMBOL(cuio_getptr);
+
+
+static void
+skb_copy_bits_back(struct sk_buff *skb, int offset, caddr_t cp, int len)
+{
+	int i;
+	if (offset < skb_headlen(skb)) {
+		memcpy(skb->data + offset, cp, min_t(int, skb_headlen(skb), len));
+		len -= skb_headlen(skb);
+		cp += skb_headlen(skb);
+	}
+	offset -= skb_headlen(skb);
+	for (i = 0; len > 0 && i < skb_shinfo(skb)->nr_frags; i++) {
+		if (offset < skb_shinfo(skb)->frags[i].size) {
+			memcpy(page_address(skb_shinfo(skb)->frags[i].page) +
+					skb_shinfo(skb)->frags[i].page_offset,
+					cp, min_t(int, skb_shinfo(skb)->frags[i].size, len));
+			len -= skb_shinfo(skb)->frags[i].size;
+			cp += skb_shinfo(skb)->frags[i].size;
+		}
+		offset -= skb_shinfo(skb)->frags[i].size;
+	}
+}
+
+void
+crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in)
+{
+
+	if ((flags & CRYPTO_F_SKBUF) != 0)
+		skb_copy_bits_back((struct sk_buff *)buf, off, in, size);
+	else if ((flags & CRYPTO_F_IOV) != 0)
+		cuio_copyback((struct uio *)buf, off, size, in);
+	else
+		bcopy(in, buf + off, size);
+}
+
+void
+crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out)
+{
+
+	if ((flags & CRYPTO_F_SKBUF) != 0)
+		skb_copy_bits((struct sk_buff *)buf, off, out, size);
+	else if ((flags & CRYPTO_F_IOV) != 0)
+		cuio_copydata((struct uio *)buf, off, size, out);
+	else
+		bcopy(buf + off, out, size);
+}
+
+int
+crypto_apply(int flags, caddr_t buf, int off, int len,
+    int (*f)(void *, void *, u_int), void *arg)
+{
+#if 0
+	int error;
+
+	if ((flags & CRYPTO_F_SKBUF) != 0)
+		error = XXXXXX((struct mbuf *)buf, off, len, f, arg);
+	else if ((flags & CRYPTO_F_IOV) != 0)
+		error = cuio_apply((struct uio *)buf, off, len, f, arg);
+	else
+		error = (*f)(arg, buf + off, len);
+	return (error);
+#else
+	KASSERT(0, ("crypto_apply not implemented!\n"));
+#endif
+	return 0;
+}
+
+EXPORT_SYMBOL(crypto_copyback);
+EXPORT_SYMBOL(crypto_copydata);
+EXPORT_SYMBOL(crypto_apply);
+
diff --git a/crypto/ocf/crypto.c b/crypto/ocf/crypto.c
new file mode 100755
index 0000000..1775324
--- /dev/null
+++ b/crypto/ocf/crypto.c
@@ -0,0 +1,1729 @@
+/*-
+ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ * The license and original author are listed below.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * Copyright (c) 2002-2006 Sam Leffler.  All rights reserved.
+ *
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/opencrypto/crypto.c,v 1.27 2007/03/21 03:42:51 sam Exp $");
+#endif
+
+/*
+ * Cryptographic Subsystem.
+ *
+ * This code is derived from the Openbsd Cryptographic Framework (OCF)
+ * that has the copyright shown below.  Very little of the original
+ * code remains.
+ */
+/*-
+ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
+ *
+ * This code was written by Angelos D. Keromytis in Athens, Greece, in
+ * February 2000. Network Security Technologies Inc. (NSTI) kindly
+ * supported the development of this code.
+ *
+ * Copyright (c) 2000, 2001 Angelos D. Keromytis
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all source code copies of any software which is or includes a copy or
+ * modification of this software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+__FBSDID("$FreeBSD: src/sys/opencrypto/crypto.c,v 1.16 2005/01/07 02:29:16 imp Exp $");
+ */
+
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/version.h>
+#include <cryptodev.h>
+
+/*
+ * keep track of whether or not we have been initialised, a big
+ * issue if we are linked into the kernel and a driver gets started before
+ * us
+ */
+int crypto_initted = 0;
+
+/*
+ * Crypto drivers register themselves by allocating a slot in the
+ * crypto_drivers table with crypto_get_driverid() and then registering
+ * each algorithm they support with crypto_register() and crypto_kregister().
+ */
+
+/*
+ * lock on driver table
+ * we track its state as spin_is_locked does not do anything on non-SMP boxes
+ */
+static spinlock_t	crypto_drivers_lock;
+static int			crypto_drivers_locked;		/* for non-SMP boxes */
+
+#define	CRYPTO_DRIVER_LOCK() \
+			({ \
+				spin_lock_irqsave(&crypto_drivers_lock, d_flags); \
+			 	crypto_drivers_locked = 1; \
+				dprintk("%s,%d: DRIVER_LOCK()\n", __FILE__, __LINE__); \
+			 })
+#define	CRYPTO_DRIVER_UNLOCK() \
+			({ \
+			 	dprintk("%s,%d: DRIVER_UNLOCK()\n", __FILE__, __LINE__); \
+			 	crypto_drivers_locked = 0; \
+				spin_unlock_irqrestore(&crypto_drivers_lock, d_flags); \
+			 })
+#define	CRYPTO_DRIVER_ASSERT() \
+			({ \
+			 	if (!crypto_drivers_locked) { \
+					dprintk("%s,%d: DRIVER_ASSERT!\n", __FILE__, __LINE__); \
+			 	} \
+			 })
+
+/*
+ * Crypto device/driver capabilities structure.
+ *
+ * Synchronization:
+ * (d) - protected by CRYPTO_DRIVER_LOCK()
+ * (q) - protected by CRYPTO_Q_LOCK()
+ * Not tagged fields are read-only.
+ */
+struct cryptocap {
+	device_t	cc_dev;			/* (d) device/driver */
+	u_int32_t	cc_sessions;		/* (d) # of sessions */
+	u_int32_t	cc_koperations;		/* (d) # os asym operations */
+	/*
+	 * Largest possible operator length (in bits) for each type of
+	 * encryption algorithm. XXX not used
+	 */
+	u_int16_t	cc_max_op_len[CRYPTO_ALGORITHM_MAX + 1];
+	u_int8_t	cc_alg[CRYPTO_ALGORITHM_MAX + 1];
+	u_int8_t	cc_kalg[CRK_ALGORITHM_MAX + 1];
+
+	int		cc_flags;		/* (d) flags */
+#define CRYPTOCAP_F_CLEANUP	0x80000000	/* needs resource cleanup */
+	int		cc_qblocked;		/* (q) symmetric q blocked */
+	int		cc_kqblocked;		/* (q) asymmetric q blocked */
+};
+static struct cryptocap *crypto_drivers = NULL;
+static int crypto_drivers_num = 0;
+
+/*
+ * There are two queues for crypto requests; one for symmetric (e.g.
+ * cipher) operations and one for asymmetric (e.g. MOD)operations.
+ * A single mutex is used to lock access to both queues.  We could
+ * have one per-queue but having one simplifies handling of block/unblock
+ * operations.
+ */
+static	int crp_sleep = 0;
+static LIST_HEAD(crp_q);		/* request queues */
+static LIST_HEAD(crp_kq);
+
+static spinlock_t crypto_q_lock;
+
+int crypto_all_qblocked = 0;  /* protect with Q_LOCK */
+module_param(crypto_all_qblocked, int, 0444);
+MODULE_PARM_DESC(crypto_all_qblocked, "Are all crypto queues blocked");
+
+int crypto_all_kqblocked = 0; /* protect with Q_LOCK */
+module_param(crypto_all_kqblocked, int, 0444);
+MODULE_PARM_DESC(crypto_all_kqblocked, "Are all asym crypto queues blocked");
+
+#define	CRYPTO_Q_LOCK() \
+			({ \
+				spin_lock_irqsave(&crypto_q_lock, q_flags); \
+			 	dprintk("%s,%d: Q_LOCK()\n", __FILE__, __LINE__); \
+			 })
+#define	CRYPTO_Q_UNLOCK() \
+			({ \
+			 	dprintk("%s,%d: Q_UNLOCK()\n", __FILE__, __LINE__); \
+				spin_unlock_irqrestore(&crypto_q_lock, q_flags); \
+			 })
+
+/*
+ * There are two queues for processing completed crypto requests; one
+ * for the symmetric and one for the asymmetric ops.  We only need one
+ * but have two to avoid type futzing (cryptop vs. cryptkop).  A single
+ * mutex is used to lock access to both queues.  Note that this lock
+ * must be separate from the lock on request queues to insure driver
+ * callbacks don't generate lock order reversals.
+ */
+static LIST_HEAD(crp_ret_q);		/* callback queues */
+static LIST_HEAD(crp_ret_kq);
+
+static spinlock_t crypto_ret_q_lock;
+#define	CRYPTO_RETQ_LOCK() \
+			({ \
+				spin_lock_irqsave(&crypto_ret_q_lock, r_flags); \
+				dprintk("%s,%d: RETQ_LOCK\n", __FILE__, __LINE__); \
+			 })
+#define	CRYPTO_RETQ_UNLOCK() \
+			({ \
+			 	dprintk("%s,%d: RETQ_UNLOCK\n", __FILE__, __LINE__); \
+				spin_unlock_irqrestore(&crypto_ret_q_lock, r_flags); \
+			 })
+#define	CRYPTO_RETQ_EMPTY()	(list_empty(&crp_ret_q) && list_empty(&crp_ret_kq))
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static kmem_cache_t *cryptop_zone;
+static kmem_cache_t *cryptodesc_zone;
+#else
+static struct kmem_cache *cryptop_zone;
+static struct kmem_cache *cryptodesc_zone;
+#endif
+
+#define debug crypto_debug
+int crypto_debug = 0;
+module_param(crypto_debug, int, 0644);
+MODULE_PARM_DESC(crypto_debug, "Enable debug");
+EXPORT_SYMBOL(crypto_debug);
+
+/*
+ * Maximum number of outstanding crypto requests before we start
+ * failing requests.  We need this to prevent DOS when too many
+ * requests are arriving for us to keep up.  Otherwise we will
+ * run the system out of memory.  Since crypto is slow,  we are
+ * usually the bottleneck that needs to say, enough is enough.
+ *
+ * We cannot print errors when this condition occurs,  we are already too
+ * slow,  printing anything will just kill us
+ */
+
+static int crypto_q_cnt = 0;
+module_param(crypto_q_cnt, int, 0444);
+MODULE_PARM_DESC(crypto_q_cnt,
+		"Current number of outstanding crypto requests");
+
+static int crypto_q_max = 1000;
+module_param(crypto_q_max, int, 0644);
+MODULE_PARM_DESC(crypto_q_max,
+		"Maximum number of outstanding crypto requests");
+
+#define bootverbose crypto_verbose
+static int crypto_verbose = 0;
+module_param(crypto_verbose, int, 0644);
+MODULE_PARM_DESC(crypto_verbose,
+		"Enable verbose crypto startup");
+
+int	crypto_usercrypto = 1;	/* userland may do crypto reqs */
+module_param(crypto_usercrypto, int, 0644);
+MODULE_PARM_DESC(crypto_usercrypto,
+	   "Enable/disable user-mode access to crypto support");
+
+int	crypto_userasymcrypto = 1;	/* userland may do asym crypto reqs */
+module_param(crypto_userasymcrypto, int, 0644);
+MODULE_PARM_DESC(crypto_userasymcrypto,
+	   "Enable/disable user-mode access to asymmetric crypto support");
+
+int	crypto_devallowsoft = 0;	/* only use hardware crypto */
+module_param(crypto_devallowsoft, int, 0644);
+MODULE_PARM_DESC(crypto_devallowsoft,
+	   "Enable/disable use of software crypto support");
+
+static pid_t	cryptoproc = (pid_t) -1;
+static struct	completion cryptoproc_exited;
+static DECLARE_WAIT_QUEUE_HEAD(cryptoproc_wait);
+static pid_t	cryptoretproc = (pid_t) -1;
+static struct	completion cryptoretproc_exited;
+static DECLARE_WAIT_QUEUE_HEAD(cryptoretproc_wait);
+
+static	int crypto_proc(void *arg);
+static	int crypto_ret_proc(void *arg);
+static	int crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint);
+static	int crypto_kinvoke(struct cryptkop *krp, int flags);
+static	void crypto_exit(void);
+int crypto_init(void);
+
+static	struct cryptostats cryptostats;
+
+static struct cryptocap *
+crypto_checkdriver(u_int32_t hid)
+{
+	if (crypto_drivers == NULL)
+		return NULL;
+	return (hid >= crypto_drivers_num ? NULL : &crypto_drivers[hid]);
+}
+
+/*
+ * Compare a driver's list of supported algorithms against another
+ * list; return non-zero if all algorithms are supported.
+ */
+static int
+driver_suitable(const struct cryptocap *cap, const struct cryptoini *cri)
+{
+	const struct cryptoini *cr;
+
+	/* See if all the algorithms are supported. */
+	for (cr = cri; cr; cr = cr->cri_next)
+		if (cap->cc_alg[cr->cri_alg] == 0)
+			return 0;
+	return 1;
+}
+
+/*
+ * Select a driver for a new session that supports the specified
+ * algorithms and, optionally, is constrained according to the flags.
+ * The algorithm we use here is pretty stupid; just use the
+ * first driver that supports all the algorithms we need. If there
+ * are multiple drivers we choose the driver with the fewest active
+ * sessions.  We prefer hardware-backed drivers to software ones.
+ *
+ * XXX We need more smarts here (in real life too, but that's
+ * XXX another story altogether).
+ */
+static struct cryptocap *
+crypto_select_driver(const struct cryptoini *cri, int flags)
+{
+	struct cryptocap *cap, *best;
+	int match, hid;
+
+	CRYPTO_DRIVER_ASSERT();
+
+	/*
+	 * Look first for hardware crypto devices if permitted.
+	 */
+	if (flags & CRYPTOCAP_F_HARDWARE)
+		match = CRYPTOCAP_F_HARDWARE;
+	else
+		match = CRYPTOCAP_F_SOFTWARE;
+	best = NULL;
+again:
+	for (hid = 0; hid < crypto_drivers_num; hid++) {
+		cap = &crypto_drivers[hid];
+		/*
+		 * If it's not initialized, is in the process of
+		 * going away, or is not appropriate (hardware
+		 * or software based on match), then skip.
+		 */
+		if (cap->cc_dev == NULL ||
+		    (cap->cc_flags & CRYPTOCAP_F_CLEANUP) ||
+		    (cap->cc_flags & match) == 0)
+			continue;
+
+		/* verify all the algorithms are supported. */
+		if (driver_suitable(cap, cri)) {
+			if (best == NULL ||
+			    cap->cc_sessions < best->cc_sessions)
+				best = cap;
+		}
+	}
+	if (best != NULL)
+		return best;
+	if (match == CRYPTOCAP_F_HARDWARE && (flags & CRYPTOCAP_F_SOFTWARE)) {
+		/* sort of an Algol 68-style for loop */
+		match = CRYPTOCAP_F_SOFTWARE;
+		goto again;
+	}
+	return best;
+}
+
+/*
+ * Create a new session.  The crid argument specifies a crypto
+ * driver to use or constraints on a driver to select (hardware
+ * only, software only, either).  Whatever driver is selected
+ * must be capable of the requested crypto algorithms.
+ */
+int
+crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int crid)
+{
+	struct cryptocap *cap;
+	u_int32_t hid, lid;
+	int err;
+	unsigned long d_flags;
+
+	CRYPTO_DRIVER_LOCK();
+	if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
+		/*
+		 * Use specified driver; verify it is capable.
+		 */
+		cap = crypto_checkdriver(crid);
+		if (cap != NULL && !driver_suitable(cap, cri))
+			cap = NULL;
+	} else {
+		/*
+		 * No requested driver; select based on crid flags.
+		 */
+		cap = crypto_select_driver(cri, crid);
+		/*
+		 * if NULL then can't do everything in one session.
+		 * XXX Fix this. We need to inject a "virtual" session
+		 * XXX layer right about here.
+		 */
+	}
+	if (cap != NULL) {
+		/* Call the driver initialization routine. */
+		hid = cap - crypto_drivers;
+		lid = hid;		/* Pass the driver ID. */
+		cap->cc_sessions++;
+		CRYPTO_DRIVER_UNLOCK();
+		err = CRYPTODEV_NEWSESSION(cap->cc_dev, &lid, cri);
+		CRYPTO_DRIVER_LOCK();
+		if (err == 0) {
+			(*sid) = (cap->cc_flags & 0xff000000)
+			       | (hid & 0x00ffffff);
+			(*sid) <<= 32;
+			(*sid) |= (lid & 0xffffffff);
+		} else
+			cap->cc_sessions--;
+	} else
+		err = EINVAL;
+	CRYPTO_DRIVER_UNLOCK();
+	return err;
+}
+
+static void
+crypto_remove(struct cryptocap *cap)
+{
+	CRYPTO_DRIVER_ASSERT();
+	if (cap->cc_sessions == 0 && cap->cc_koperations == 0)
+		bzero(cap, sizeof(*cap));
+}
+
+/*
+ * Delete an existing session (or a reserved session on an unregistered
+ * driver).
+ */
+int
+crypto_freesession(u_int64_t sid)
+{
+	struct cryptocap *cap;
+	u_int32_t hid;
+	int err = 0;
+	unsigned long d_flags;
+
+	dprintk("%s()\n", __FUNCTION__);
+	CRYPTO_DRIVER_LOCK();
+
+	if (crypto_drivers == NULL) {
+		err = EINVAL;
+		goto done;
+	}
+
+	/* Determine two IDs. */
+	hid = CRYPTO_SESID2HID(sid);
+
+	if (hid >= crypto_drivers_num) {
+		dprintk("%s - INVALID DRIVER NUM %d\n", __FUNCTION__, hid);
+		err = ENOENT;
+		goto done;
+	}
+	cap = &crypto_drivers[hid];
+
+	if (cap->cc_dev) {
+		CRYPTO_DRIVER_UNLOCK();
+		/* Call the driver cleanup routine, if available, unlocked. */
+		err = CRYPTODEV_FREESESSION(cap->cc_dev, sid);
+		CRYPTO_DRIVER_LOCK();
+	}
+
+	if (cap->cc_sessions)
+		cap->cc_sessions--;
+
+	if (cap->cc_flags & CRYPTOCAP_F_CLEANUP)
+		crypto_remove(cap);
+
+done:
+	CRYPTO_DRIVER_UNLOCK();
+	return err;
+}
+
+/*
+ * Return an unused driver id.  Used by drivers prior to registering
+ * support for the algorithms they handle.
+ */
+int32_t
+crypto_get_driverid(device_t dev, int flags)
+{
+	struct cryptocap *newdrv;
+	int i;
+	unsigned long d_flags;
+
+	if ((flags & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
+		printf("%s: no flags specified when registering driver\n",
+		    device_get_nameunit(dev));
+		return -1;
+	}
+
+	CRYPTO_DRIVER_LOCK();
+
+	for (i = 0; i < crypto_drivers_num; i++) {
+		if (crypto_drivers[i].cc_dev == NULL &&
+		    (crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP) == 0) {
+			break;
+		}
+	}
+
+	/* Out of entries, allocate some more. */
+	if (i == crypto_drivers_num) {
+		/* Be careful about wrap-around. */
+		if (2 * crypto_drivers_num <= crypto_drivers_num) {
+			CRYPTO_DRIVER_UNLOCK();
+			printk("crypto: driver count wraparound!\n");
+			return -1;
+		}
+
+		newdrv = kmalloc(2 * crypto_drivers_num * sizeof(struct cryptocap),
+				GFP_KERNEL);
+		if (newdrv == NULL) {
+			CRYPTO_DRIVER_UNLOCK();
+			printk("crypto: no space to expand driver table!\n");
+			return -1;
+		}
+
+		memcpy(newdrv, crypto_drivers,
+				crypto_drivers_num * sizeof(struct cryptocap));
+		memset(&newdrv[crypto_drivers_num], 0,
+				crypto_drivers_num * sizeof(struct cryptocap));
+
+		crypto_drivers_num *= 2;
+
+		kfree(crypto_drivers);
+		crypto_drivers = newdrv;
+	}
+
+	/* NB: state is zero'd on free */
+	crypto_drivers[i].cc_sessions = 1;	/* Mark */
+	crypto_drivers[i].cc_dev = dev;
+	crypto_drivers[i].cc_flags = flags;
+	if (bootverbose)
+		printf("crypto: assign %s driver id %u, flags %u\n",
+		    device_get_nameunit(dev), i, flags);
+
+	CRYPTO_DRIVER_UNLOCK();
+
+	return i;
+}
+
+/*
+ * Lookup a driver by name.  We match against the full device
+ * name and unit, and against just the name.  The latter gives
+ * us a simple widlcarding by device name.  On success return the
+ * driver/hardware identifier; otherwise return -1.
+ */
+int
+crypto_find_driver(const char *match)
+{
+	int i, len = strlen(match);
+	unsigned long d_flags;
+
+	CRYPTO_DRIVER_LOCK();
+	for (i = 0; i < crypto_drivers_num; i++) {
+		device_t dev = crypto_drivers[i].cc_dev;
+		if (dev == NULL ||
+		    (crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP))
+			continue;
+		if (strncmp(match, device_get_nameunit(dev), len) == 0 ||
+		    strncmp(match, device_get_name(dev), len) == 0)
+			break;
+	}
+	CRYPTO_DRIVER_UNLOCK();
+	return i < crypto_drivers_num ? i : -1;
+}
+
+/*
+ * Return the device_t for the specified driver or NULL
+ * if the driver identifier is invalid.
+ */
+device_t
+crypto_find_device_byhid(int hid)
+{
+	struct cryptocap *cap = crypto_checkdriver(hid);
+	return cap != NULL ? cap->cc_dev : NULL;
+}
+
+/*
+ * Return the device/driver capabilities.
+ */
+int
+crypto_getcaps(int hid)
+{
+	struct cryptocap *cap = crypto_checkdriver(hid);
+	return cap != NULL ? cap->cc_flags : 0;
+}
+
+/*
+ * Register support for a key-related algorithm.  This routine
+ * is called once for each algorithm supported a driver.
+ */
+int
+crypto_kregister(u_int32_t driverid, int kalg, u_int32_t flags)
+{
+	struct cryptocap *cap;
+	int err;
+	unsigned long d_flags;
+
+	dprintk("%s()\n", __FUNCTION__);
+	CRYPTO_DRIVER_LOCK();
+
+	cap = crypto_checkdriver(driverid);
+	if (cap != NULL &&
+	    (CRK_ALGORITM_MIN <= kalg && kalg <= CRK_ALGORITHM_MAX)) {
+		/*
+		 * XXX Do some performance testing to determine placing.
+		 * XXX We probably need an auxiliary data structure that
+		 * XXX describes relative performances.
+		 */
+
+		cap->cc_kalg[kalg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
+		if (bootverbose)
+			printf("crypto: %s registers key alg %u flags %u\n"
+				, device_get_nameunit(cap->cc_dev)
+				, kalg
+				, flags
+			);
+		err = 0;
+	} else
+		err = EINVAL;
+
+	CRYPTO_DRIVER_UNLOCK();
+	return err;
+}
+
+/*
+ * Register support for a non-key-related algorithm.  This routine
+ * is called once for each such algorithm supported by a driver.
+ */
+int
+crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
+    u_int32_t flags)
+{
+	struct cryptocap *cap;
+	int err;
+	unsigned long d_flags;
+
+	dprintk("%s(id=0x%x, alg=%d, maxoplen=%d, flags=0x%x)\n", __FUNCTION__,
+			driverid, alg, maxoplen, flags);
+
+	CRYPTO_DRIVER_LOCK();
+
+	cap = crypto_checkdriver(driverid);
+	/* NB: algorithms are in the range [1..max] */
+	if (cap != NULL &&
+	    (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX)) {
+		/*
+		 * XXX Do some performance testing to determine placing.
+		 * XXX We probably need an auxiliary data structure that
+		 * XXX describes relative performances.
+		 */
+
+		cap->cc_alg[alg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
+		cap->cc_max_op_len[alg] = maxoplen;
+		if (bootverbose)
+			printf("crypto: %s registers alg %u flags %u maxoplen %u\n"
+				, device_get_nameunit(cap->cc_dev)
+				, alg
+				, flags
+				, maxoplen
+			);
+		cap->cc_sessions = 0;		/* Unmark */
+		err = 0;
+	} else
+		err = EINVAL;
+
+	CRYPTO_DRIVER_UNLOCK();
+	return err;
+}
+
+static void
+driver_finis(struct cryptocap *cap)
+{
+	u_int32_t ses, kops;
+
+	CRYPTO_DRIVER_ASSERT();
+
+	ses = cap->cc_sessions;
+	kops = cap->cc_koperations;
+	bzero(cap, sizeof(*cap));
+	if (ses != 0 || kops != 0) {
+		/*
+		 * If there are pending sessions,
+		 * just mark as invalid.
+		 */
+		cap->cc_flags |= CRYPTOCAP_F_CLEANUP;
+		cap->cc_sessions = ses;
+		cap->cc_koperations = kops;
+	}
+}
+
+/*
+ * Unregister a crypto driver. If there are pending sessions using it,
+ * leave enough information around so that subsequent calls using those
+ * sessions will correctly detect the driver has been unregistered and
+ * reroute requests.
+ */
+int
+crypto_unregister(u_int32_t driverid, int alg)
+{
+	struct cryptocap *cap;
+	int i, err;
+	unsigned long d_flags;
+
+	dprintk("%s()\n", __FUNCTION__);
+	CRYPTO_DRIVER_LOCK();
+
+	cap = crypto_checkdriver(driverid);
+	if (cap != NULL &&
+	    (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX) &&
+	    cap->cc_alg[alg] != 0) {
+		cap->cc_alg[alg] = 0;
+		cap->cc_max_op_len[alg] = 0;
+
+		/* Was this the last algorithm ? */
+		for (i = 1; i <= CRYPTO_ALGORITHM_MAX; i++)
+			if (cap->cc_alg[i] != 0)
+				break;
+
+		if (i == CRYPTO_ALGORITHM_MAX + 1)
+			driver_finis(cap);
+		err = 0;
+	} else
+		err = EINVAL;
+	CRYPTO_DRIVER_UNLOCK();
+	return err;
+}
+
+/*
+ * Unregister all algorithms associated with a crypto driver.
+ * If there are pending sessions using it, leave enough information
+ * around so that subsequent calls using those sessions will
+ * correctly detect the driver has been unregistered and reroute
+ * requests.
+ */
+int
+crypto_unregister_all(u_int32_t driverid)
+{
+	struct cryptocap *cap;
+	int err;
+	unsigned long d_flags;
+
+	dprintk("%s()\n", __FUNCTION__);
+	CRYPTO_DRIVER_LOCK();
+	cap = crypto_checkdriver(driverid);
+	if (cap != NULL) {
+		driver_finis(cap);
+		err = 0;
+	} else
+		err = EINVAL;
+	CRYPTO_DRIVER_UNLOCK();
+
+	return err;
+}
+
+/*
+ * Clear blockage on a driver.  The what parameter indicates whether
+ * the driver is now ready for cryptop's and/or cryptokop's.
+ */
+int
+crypto_unblock(u_int32_t driverid, int what)
+{
+	struct cryptocap *cap;
+	int err;
+	unsigned long q_flags;
+
+	CRYPTO_Q_LOCK();
+	cap = crypto_checkdriver(driverid);
+	if (cap != NULL) {
+		if (what & CRYPTO_SYMQ) {
+			cap->cc_qblocked = 0;
+			crypto_all_qblocked = 0;
+		}
+		if (what & CRYPTO_ASYMQ) {
+			cap->cc_kqblocked = 0;
+			crypto_all_kqblocked = 0;
+		}
+		if (crp_sleep)
+			wake_up_interruptible(&cryptoproc_wait);
+		err = 0;
+	} else
+		err = EINVAL;
+	CRYPTO_Q_UNLOCK(); //DAVIDM should this be a driver lock
+
+	return err;
+}
+
+/*
+ * Add a crypto request to a queue, to be processed by the kernel thread.
+ */
+int
+crypto_dispatch(struct cryptop *crp)
+{
+	struct cryptocap *cap;
+	u_int32_t hid;
+	int result = 0;
+	unsigned long q_flags;
+
+	dprintk("%s()\n", __FUNCTION__);
+	cryptostats.cs_ops++;
+
+	CRYPTO_Q_LOCK();
+	if (crypto_q_cnt >= crypto_q_max) {
+		CRYPTO_Q_UNLOCK();
+		cryptostats.cs_drops++;
+		return ENOMEM;
+	}
+	crypto_q_cnt++;
+	CRYPTO_Q_UNLOCK();
+
+	hid = CRYPTO_SESID2HID(crp->crp_sid);
+	cap = crypto_checkdriver(hid);
+	/* warning: We are using the CRYPTO_F_BATCH to mark processing by HW,
+ 	   it should be disabled for software encryption */
+	if ((crp->crp_flags & CRYPTO_F_BATCH)) {
+        /* If should be done by HW - skip OCF queue */
+		result = crypto_invoke(cap, crp, 0);
+		if (result != 0) {
+            	    cryptostats.cs_drops++;
+		} 
+	} else {
+		/*
+		 * Caller marked the request as ``ok to delay'';
+		 * queue it for the dispatch thread.  This is desirable
+		 * when the operation is low priority and/or suitable
+		 * for batching.
+		 */
+      		CRYPTO_Q_LOCK();
+		TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
+		if (crp_sleep)
+			wake_up_interruptible(&cryptoproc_wait);
+		CRYPTO_Q_UNLOCK();
+	}
+	
+	return result;
+}
+
+/*
+ * Add an asymetric crypto request to a queue,
+ * to be processed by the kernel thread.
+ */
+int
+crypto_kdispatch(struct cryptkop *krp)
+{
+	int error;
+	unsigned long q_flags;
+
+	cryptostats.cs_kops++;
+
+	error = crypto_kinvoke(krp, krp->krp_crid);
+	if (error == ERESTART) {
+		CRYPTO_Q_LOCK();
+		TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
+		if (crp_sleep)
+			wake_up_interruptible(&cryptoproc_wait);
+		CRYPTO_Q_UNLOCK();
+		error = 0;
+	}
+	return error;
+}
+
+/*
+ * Verify a driver is suitable for the specified operation.
+ */
+static __inline int
+kdriver_suitable(const struct cryptocap *cap, const struct cryptkop *krp)
+{
+	return (cap->cc_kalg[krp->krp_op] & CRYPTO_ALG_FLAG_SUPPORTED) != 0;
+}
+
+/*
+ * Select a driver for an asym operation.  The driver must
+ * support the necessary algorithm.  The caller can constrain
+ * which device is selected with the flags parameter.  The
+ * algorithm we use here is pretty stupid; just use the first
+ * driver that supports the algorithms we need. If there are
+ * multiple suitable drivers we choose the driver with the
+ * fewest active operations.  We prefer hardware-backed
+ * drivers to software ones when either may be used.
+ */
+static struct cryptocap *
+crypto_select_kdriver(const struct cryptkop *krp, int flags)
+{
+	struct cryptocap *cap, *best, *blocked;
+	int match, hid;
+
+	CRYPTO_DRIVER_ASSERT();
+
+	/*
+	 * Look first for hardware crypto devices if permitted.
+	 */
+	if (flags & CRYPTOCAP_F_HARDWARE)
+		match = CRYPTOCAP_F_HARDWARE;
+	else
+		match = CRYPTOCAP_F_SOFTWARE;
+	best = NULL;
+	blocked = NULL;
+again:
+	for (hid = 0; hid < crypto_drivers_num; hid++) {
+		cap = &crypto_drivers[hid];
+		/*
+		 * If it's not initialized, is in the process of
+		 * going away, or is not appropriate (hardware
+		 * or software based on match), then skip.
+		 */
+		if (cap->cc_dev == NULL ||
+		    (cap->cc_flags & CRYPTOCAP_F_CLEANUP) ||
+		    (cap->cc_flags & match) == 0)
+			continue;
+
+		/* verify all the algorithms are supported. */
+		if (kdriver_suitable(cap, krp)) {
+			if (best == NULL ||
+			    cap->cc_koperations < best->cc_koperations)
+				best = cap;
+		}
+	}
+	if (best != NULL)
+		return best;
+	if (match == CRYPTOCAP_F_HARDWARE && (flags & CRYPTOCAP_F_SOFTWARE)) {
+		/* sort of an Algol 68-style for loop */
+		match = CRYPTOCAP_F_SOFTWARE;
+		goto again;
+	}
+	return best;
+}
+
+/*
+ * Dispatch an assymetric crypto request.
+ */
+static int
+crypto_kinvoke(struct cryptkop *krp, int crid)
+{
+	struct cryptocap *cap = NULL;
+	int error;
+	unsigned long d_flags;
+
+	KASSERT(krp != NULL, ("%s: krp == NULL", __func__));
+	KASSERT(krp->krp_callback != NULL,
+	    ("%s: krp->crp_callback == NULL", __func__));
+
+	CRYPTO_DRIVER_LOCK();
+	if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
+		cap = crypto_checkdriver(crid);
+		if (cap != NULL) {
+			/*
+			 * Driver present, it must support the necessary
+			 * algorithm and, if s/w drivers are excluded,
+			 * it must be registered as hardware-backed.
+			 */
+			if (!kdriver_suitable(cap, krp) ||
+			    (!crypto_devallowsoft &&
+			     (cap->cc_flags & CRYPTOCAP_F_HARDWARE) == 0))
+				cap = NULL;
+		}
+	} else {
+		/*
+		 * No requested driver; select based on crid flags.
+		 */
+		if (!crypto_devallowsoft)	/* NB: disallow s/w drivers */
+			crid &= ~CRYPTOCAP_F_SOFTWARE;
+		cap = crypto_select_kdriver(krp, crid);
+	}
+	if (cap != NULL && !cap->cc_kqblocked) {
+		krp->krp_hid = cap - crypto_drivers;
+		cap->cc_koperations++;
+		CRYPTO_DRIVER_UNLOCK();
+		error = CRYPTODEV_KPROCESS(cap->cc_dev, krp, 0);
+		CRYPTO_DRIVER_LOCK();
+		if (error == ERESTART) {
+			cap->cc_koperations--;
+			CRYPTO_DRIVER_UNLOCK();
+			return (error);
+		}
+		/* return the actual device used */
+		krp->krp_crid = krp->krp_hid;
+	} else {
+		/*
+		 * NB: cap is !NULL if device is blocked; in
+		 *     that case return ERESTART so the operation
+		 *     is resubmitted if possible.
+		 */
+		error = (cap == NULL) ? ENODEV : ERESTART;
+	}
+	CRYPTO_DRIVER_UNLOCK();
+
+	if (error) {
+		krp->krp_status = error;
+		crypto_kdone(krp);
+	}
+	return 0;
+}
+
+
+/*
+ * Dispatch a crypto request to the appropriate crypto devices.
+ */
+static int
+crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint)
+{
+	KASSERT(crp != NULL, ("%s: crp == NULL", __func__));
+	KASSERT(crp->crp_callback != NULL,
+	    ("%s: crp->crp_callback == NULL", __func__));
+	KASSERT(crp->crp_desc != NULL, ("%s: crp->crp_desc == NULL", __func__));
+
+	dprintk("%s()\n", __FUNCTION__);
+
+#ifdef CRYPTO_TIMING
+	if (crypto_timing)
+		crypto_tstat(&cryptostats.cs_invoke, &crp->crp_tstamp);
+#endif
+	if (cap->cc_flags & CRYPTOCAP_F_CLEANUP) {
+		struct cryptodesc *crd;
+		u_int64_t nid;
+
+		/*
+		 * Driver has unregistered; migrate the session and return
+		 * an error to the caller so they'll resubmit the op.
+		 *
+		 * XXX: What if there are more already queued requests for this
+		 *      session?
+		 */
+		crypto_freesession(crp->crp_sid);
+
+		for (crd = crp->crp_desc; crd->crd_next; crd = crd->crd_next)
+			crd->CRD_INI.cri_next = &(crd->crd_next->CRD_INI);
+
+		/* XXX propagate flags from initial session? */
+		if (crypto_newsession(&nid, &(crp->crp_desc->CRD_INI),
+		    CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE) == 0)
+			crp->crp_sid = nid;
+
+		crp->crp_etype = EAGAIN;
+		crypto_done(crp);
+		return 0;
+	} else {
+		/*
+		 * Invoke the driver to process the request.
+		 */
+		return CRYPTODEV_PROCESS(cap->cc_dev, crp, hint);
+	}
+}
+
+/*
+ * Release a set of crypto descriptors.
+ */
+void
+crypto_freereq(struct cryptop *crp)
+{
+	struct cryptodesc *crd;
+
+	if (crp == NULL)
+		return;
+
+#ifdef DIAGNOSTIC
+	{
+		struct cryptop *crp2;
+		unsigned long q_flags;
+
+		CRYPTO_Q_LOCK();
+		TAILQ_FOREACH(crp2, &crp_q, crp_next) {
+			KASSERT(crp2 != crp,
+			    ("Freeing cryptop from the crypto queue (%p).",
+			    crp));
+		}
+		CRYPTO_Q_UNLOCK();
+		CRYPTO_RETQ_LOCK();
+		TAILQ_FOREACH(crp2, &crp_ret_q, crp_next) {
+			KASSERT(crp2 != crp,
+			    ("Freeing cryptop from the return queue (%p).",
+			    crp));
+		}
+		CRYPTO_RETQ_UNLOCK();
+	}
+#endif
+
+	while ((crd = crp->crp_desc) != NULL) {
+		crp->crp_desc = crd->crd_next;
+		kmem_cache_free(cryptodesc_zone, crd);
+	}
+	kmem_cache_free(cryptop_zone, crp);
+}
+
+/*
+ * Acquire a set of crypto descriptors.
+ */
+struct cryptop *
+crypto_getreq(int num)
+{
+	struct cryptodesc *crd;
+	struct cryptop *crp;
+
+	crp = kmem_cache_alloc(cryptop_zone, SLAB_ATOMIC);
+	if (crp != NULL) {
+		memset(crp, 0, sizeof(*crp));
+		INIT_LIST_HEAD(&crp->crp_next);
+		init_waitqueue_head(&crp->crp_waitq);
+		while (num--) {
+			crd = kmem_cache_alloc(cryptodesc_zone, SLAB_ATOMIC);
+			if (crd == NULL) {
+				crypto_freereq(crp);
+				return NULL;
+			}
+			memset(crd, 0, sizeof(*crd));
+			crd->crd_next = crp->crp_desc;
+			crp->crp_desc = crd;
+		}
+	}
+	return crp;
+}
+
+/*
+ * Invoke the callback on behalf of the driver.
+ */
+void
+crypto_done(struct cryptop *crp)
+{
+	unsigned long q_flags;
+
+	dprintk("%s()\n", __FUNCTION__);
+	if ((crp->crp_flags & CRYPTO_F_DONE) == 0) {
+		crp->crp_flags |= CRYPTO_F_DONE;
+		CRYPTO_Q_LOCK();
+		crypto_q_cnt--;
+		CRYPTO_Q_UNLOCK();
+	} else
+		printk("crypto: crypto_done op already done, flags 0x%x",
+				crp->crp_flags);
+	if (crp->crp_etype != 0)
+		cryptostats.cs_errs++;
+	/*
+	 * CBIMM means unconditionally do the callback immediately;
+	 * CBIFSYNC means do the callback immediately only if the
+	 * operation was done synchronously.  Both are used to avoid
+	 * doing extraneous context switches; the latter is mostly
+	 * used with the software crypto driver.
+	 */
+	if ((crp->crp_flags & CRYPTO_F_CBIMM) ||
+	    ((crp->crp_flags & CRYPTO_F_CBIFSYNC) &&
+	     (CRYPTO_SESID2CAPS(crp->crp_sid) & CRYPTOCAP_F_SYNC))) {
+		/*
+		 * Do the callback directly.  This is ok when the
+		 * callback routine does very little (e.g. the
+		 * /dev/crypto callback method just does a wakeup).
+		 */
+		crp->crp_callback(crp);
+	} else {
+		unsigned long r_flags;
+		/*
+		 * Normal case; queue the callback for the thread.
+		 */
+		CRYPTO_RETQ_LOCK();
+		if (CRYPTO_RETQ_EMPTY())
+			wake_up_interruptible(&cryptoretproc_wait);/* shared wait channel */
+		TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
+		CRYPTO_RETQ_UNLOCK();
+	}
+}
+
+/*
+ * Invoke the callback on behalf of the driver.
+ */
+void
+crypto_kdone(struct cryptkop *krp)
+{
+	struct cryptocap *cap;
+	unsigned long d_flags;
+
+	if ((krp->krp_flags & CRYPTO_KF_DONE) != 0)
+		printk("crypto: crypto_kdone op already done, flags 0x%x",
+				krp->krp_flags);
+	krp->krp_flags |= CRYPTO_KF_DONE;
+	if (krp->krp_status != 0)
+		cryptostats.cs_kerrs++;
+
+	CRYPTO_DRIVER_LOCK();
+	/* XXX: What if driver is loaded in the meantime? */
+	if (krp->krp_hid < crypto_drivers_num) {
+		cap = &crypto_drivers[krp->krp_hid];
+		cap->cc_koperations--;
+		KASSERT(cap->cc_koperations >= 0, ("cc_koperations < 0"));
+		if (cap->cc_flags & CRYPTOCAP_F_CLEANUP)
+			crypto_remove(cap);
+	}
+	CRYPTO_DRIVER_UNLOCK();
+
+	/*
+	 * CBIMM means unconditionally do the callback immediately;
+	 * This is used to avoid doing extraneous context switches
+	 */
+	if ((krp->krp_flags & CRYPTO_KF_CBIMM)) {
+		/*
+		 * Do the callback directly.  This is ok when the
+		 * callback routine does very little (e.g. the
+		 * /dev/crypto callback method just does a wakeup).
+		 */
+		krp->krp_callback(krp);
+	} else {
+		unsigned long r_flags;
+		/*
+		 * Normal case; queue the callback for the thread.
+		 */
+		CRYPTO_RETQ_LOCK();
+		if (CRYPTO_RETQ_EMPTY())
+			wake_up_interruptible(&cryptoretproc_wait);/* shared wait channel */
+		TAILQ_INSERT_TAIL(&crp_ret_kq, krp, krp_next);
+		CRYPTO_RETQ_UNLOCK();
+	}
+}
+
+int
+crypto_getfeat(int *featp)
+{
+	int hid, kalg, feat = 0;
+	unsigned long d_flags;
+
+	CRYPTO_DRIVER_LOCK();
+	for (hid = 0; hid < crypto_drivers_num; hid++) {
+		const struct cryptocap *cap = &crypto_drivers[hid];
+
+		if ((cap->cc_flags & CRYPTOCAP_F_SOFTWARE) &&
+		    !crypto_devallowsoft) {
+			continue;
+		}
+		for (kalg = 0; kalg < CRK_ALGORITHM_MAX; kalg++)
+			if (cap->cc_kalg[kalg] & CRYPTO_ALG_FLAG_SUPPORTED)
+				feat |=  1 << kalg;
+	}
+	CRYPTO_DRIVER_UNLOCK();
+	*featp = feat;
+	return (0);
+}
+
+/*
+ * Crypto thread, dispatches crypto requests.
+ */
+static int
+crypto_proc(void *arg)
+{
+	struct cryptop *crp, *submit;
+	struct cryptkop *krp, *krpp;
+	struct cryptocap *cap;
+	u_int32_t hid;
+	int result, hint;
+	unsigned long q_flags;
+
+	ocf_daemonize("crypto");
+
+	CRYPTO_Q_LOCK();
+	for (;;) {
+		/*
+		 * we need to make sure we don't get into a busy loop with nothing
+		 * to do,  the two crypto_all_*blocked vars help us find out when
+		 * we are all full and can do nothing on any driver or Q.  If so we
+		 * wait for an unblock.
+		 */
+		crypto_all_qblocked  = !list_empty(&crp_q);
+
+		/*
+		 * Find the first element in the queue that can be
+		 * processed and look-ahead to see if multiple ops
+		 * are ready for the same driver.
+		 */
+		submit = NULL;
+		hint = 0;
+		list_for_each_entry(crp, &crp_q, crp_next) {
+			hid = CRYPTO_SESID2HID(crp->crp_sid);
+			cap = crypto_checkdriver(hid);
+			/*
+			 * Driver cannot disappear when there is an active
+			 * session.
+			 */
+			KASSERT(cap != NULL, ("%s:%u Driver disappeared.",
+			    __func__, __LINE__));
+			if (cap == NULL || cap->cc_dev == NULL) {
+				/* Op needs to be migrated, process it. */
+				if (submit == NULL)
+					submit = crp;
+				break;
+			}
+			if (!cap->cc_qblocked) {
+				if (submit != NULL) {
+					/*
+					 * We stop on finding another op,
+					 * regardless whether its for the same
+					 * driver or not.  We could keep
+					 * searching the queue but it might be
+					 * better to just use a per-driver
+					 * queue instead.
+					 */
+					if (CRYPTO_SESID2HID(submit->crp_sid) == hid)
+						hint = CRYPTO_HINT_MORE;
+					break;
+				} else {
+					submit = crp;
+					if ((submit->crp_flags & CRYPTO_F_BATCH) == 0)
+						break;
+					/* keep scanning for more are q'd */
+				}
+			}
+		}
+		if (submit != NULL) {
+			hid = CRYPTO_SESID2HID(submit->crp_sid);
+			crypto_all_qblocked = 0;
+			list_del(&submit->crp_next);
+			crypto_drivers[hid].cc_qblocked = 1;
+			cap = crypto_checkdriver(hid);
+			CRYPTO_Q_UNLOCK();
+			KASSERT(cap != NULL, ("%s:%u Driver disappeared.",
+			    __func__, __LINE__));
+			result = crypto_invoke(cap, submit, hint);
+			CRYPTO_Q_LOCK();
+			if (result == ERESTART) {
+				/*
+				 * The driver ran out of resources, mark the
+				 * driver ``blocked'' for cryptop's and put
+				 * the request back in the queue.  It would
+				 * best to put the request back where we got
+				 * it but that's hard so for now we put it
+				 * at the front.  This should be ok; putting
+				 * it at the end does not work.
+				 */
+				/* XXX validate sid again? */
+				list_add(&submit->crp_next, &crp_q);
+				cryptostats.cs_blocks++;
+			} else
+				crypto_drivers[hid].cc_qblocked=0;
+		}
+
+		crypto_all_kqblocked = !list_empty(&crp_kq);
+
+		/* As above, but for key ops */
+		krp = NULL;
+		list_for_each_entry(krpp, &crp_kq, krp_next) {
+			cap = crypto_checkdriver(krpp->krp_hid);
+			if (cap == NULL || cap->cc_dev == NULL) {
+				/*
+				 * Operation needs to be migrated, invalidate
+				 * the assigned device so it will reselect a
+				 * new one below.  Propagate the original
+				 * crid selection flags if supplied.
+				 */
+				krp->krp_hid = krp->krp_crid &
+				    (CRYPTOCAP_F_SOFTWARE|CRYPTOCAP_F_HARDWARE);
+				if (krp->krp_hid == 0)
+					krp->krp_hid =
+				    CRYPTOCAP_F_SOFTWARE|CRYPTOCAP_F_HARDWARE;
+				break;
+			}
+			if (!cap->cc_kqblocked) {
+				krp = krpp;
+				break;
+			}
+		}
+		if (krp != NULL) {
+			crypto_all_kqblocked = 0;
+			list_del(&krp->krp_next);
+			crypto_drivers[krp->krp_hid].cc_kqblocked = 1;
+			CRYPTO_Q_UNLOCK();
+			result = crypto_kinvoke(krp, krp->krp_hid);
+			CRYPTO_Q_LOCK();
+			if (result == ERESTART) {
+				/*
+				 * The driver ran out of resources, mark the
+				 * driver ``blocked'' for cryptkop's and put
+				 * the request back in the queue.  It would
+				 * best to put the request back where we got
+				 * it but that's hard so for now we put it
+				 * at the front.  This should be ok; putting
+				 * it at the end does not work.
+				 */
+				/* XXX validate sid again? */
+				list_add(&krp->krp_next, &crp_kq);
+				cryptostats.cs_kblocks++;
+			} else
+				crypto_drivers[krp->krp_hid].cc_kqblocked = 0;
+		}
+
+		if (submit == NULL && krp == NULL) {
+			/*
+			 * Nothing more to be processed.  Sleep until we're
+			 * woken because there are more ops to process.
+			 * This happens either by submission or by a driver
+			 * becoming unblocked and notifying us through
+			 * crypto_unblock.  Note that when we wakeup we
+			 * start processing each queue again from the
+			 * front. It's not clear that it's important to
+			 * preserve this ordering since ops may finish
+			 * out of order if dispatched to different devices
+			 * and some become blocked while others do not.
+			 */
+			dprintk("%s - sleeping (qe=%d qb=%d kqe=%d kqb=%d)\n",
+					__FUNCTION__,
+					list_empty(&crp_q), crypto_all_qblocked,
+					list_empty(&crp_kq), crypto_all_kqblocked);
+			CRYPTO_Q_UNLOCK();
+			crp_sleep = 1;
+			wait_event_interruptible(cryptoproc_wait,
+					!(list_empty(&crp_q) || crypto_all_qblocked) ||
+					!(list_empty(&crp_kq) || crypto_all_kqblocked) ||
+					cryptoproc == (pid_t) -1);
+			crp_sleep = 0;
+			if (signal_pending (current)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+				spin_lock_irq(&current->sigmask_lock);
+#endif
+				flush_signals(current);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+				spin_unlock_irq(&current->sigmask_lock);
+#endif
+			}
+			CRYPTO_Q_LOCK();
+			dprintk("%s - awake\n", __FUNCTION__);
+			if (cryptoproc == (pid_t) -1)
+				break;
+			cryptostats.cs_intrs++;
+		}
+	}
+	CRYPTO_Q_UNLOCK();
+	complete_and_exit(&cryptoproc_exited, 0);
+}
+
+/*
+ * Crypto returns thread, does callbacks for processed crypto requests.
+ * Callbacks are done here, rather than in the crypto drivers, because
+ * callbacks typically are expensive and would slow interrupt handling.
+ */
+static int
+crypto_ret_proc(void *arg)
+{
+	struct cryptop *crpt;
+	struct cryptkop *krpt;
+	unsigned long  r_flags;
+
+	ocf_daemonize("crypto_ret");
+
+	CRYPTO_RETQ_LOCK();
+	for (;;) {
+		/* Harvest return q's for completed ops */
+		crpt = NULL;
+		if (!list_empty(&crp_ret_q))
+			crpt = list_entry(crp_ret_q.next, typeof(*crpt), crp_next);
+		if (crpt != NULL)
+			list_del(&crpt->crp_next);
+
+		krpt = NULL;
+		if (!list_empty(&crp_ret_kq))
+			krpt = list_entry(crp_ret_kq.next, typeof(*krpt), krp_next);
+		if (krpt != NULL)
+			list_del(&krpt->krp_next);
+
+		if (crpt != NULL || krpt != NULL) {
+			CRYPTO_RETQ_UNLOCK();
+			/*
+			 * Run callbacks unlocked.
+			 */
+			if (crpt != NULL)
+				crpt->crp_callback(crpt);
+			if (krpt != NULL)
+				krpt->krp_callback(krpt);
+			CRYPTO_RETQ_LOCK();
+		} else {
+			/*
+			 * Nothing more to be processed.  Sleep until we're
+			 * woken because there are more returns to process.
+			 */
+			dprintk("%s - sleeping\n", __FUNCTION__);
+			CRYPTO_RETQ_UNLOCK();
+			wait_event_interruptible(cryptoretproc_wait,
+					cryptoretproc == (pid_t) -1 ||
+					!list_empty(&crp_ret_q) ||
+					!list_empty(&crp_ret_kq));
+			if (signal_pending (current)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+				spin_lock_irq(&current->sigmask_lock);
+#endif
+				flush_signals(current);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+				spin_unlock_irq(&current->sigmask_lock);
+#endif
+			}
+			CRYPTO_RETQ_LOCK();
+			dprintk("%s - awake\n", __FUNCTION__);
+			if (cryptoretproc == (pid_t) -1) {
+				dprintk("%s - EXITING!\n", __FUNCTION__);
+				break;
+			}
+			cryptostats.cs_rets++;
+		}
+	}
+	CRYPTO_RETQ_UNLOCK();
+	complete_and_exit(&cryptoretproc_exited, 0);
+}
+
+
+#if 0 /* should put this into /proc or something */
+static void
+db_show_drivers(void)
+{
+	int hid;
+
+	db_printf("%12s %4s %4s %8s %2s %2s\n"
+		, "Device"
+		, "Ses"
+		, "Kops"
+		, "Flags"
+		, "QB"
+		, "KB"
+	);
+	for (hid = 0; hid < crypto_drivers_num; hid++) {
+		const struct cryptocap *cap = &crypto_drivers[hid];
+		if (cap->cc_dev == NULL)
+			continue;
+		db_printf("%-12s %4u %4u %08x %2u %2u\n"
+		    , device_get_nameunit(cap->cc_dev)
+		    , cap->cc_sessions
+		    , cap->cc_koperations
+		    , cap->cc_flags
+		    , cap->cc_qblocked
+		    , cap->cc_kqblocked
+		);
+	}
+}
+
+DB_SHOW_COMMAND(crypto, db_show_crypto)
+{
+	struct cryptop *crp;
+
+	db_show_drivers();
+	db_printf("\n");
+
+	db_printf("%4s %8s %4s %4s %4s %4s %8s %8s\n",
+	    "HID", "Caps", "Ilen", "Olen", "Etype", "Flags",
+	    "Desc", "Callback");
+	TAILQ_FOREACH(crp, &crp_q, crp_next) {
+		db_printf("%4u %08x %4u %4u %4u %04x %8p %8p\n"
+		    , (int) CRYPTO_SESID2HID(crp->crp_sid)
+		    , (int) CRYPTO_SESID2CAPS(crp->crp_sid)
+		    , crp->crp_ilen, crp->crp_olen
+		    , crp->crp_etype
+		    , crp->crp_flags
+		    , crp->crp_desc
+		    , crp->crp_callback
+		);
+	}
+	if (!TAILQ_EMPTY(&crp_ret_q)) {
+		db_printf("\n%4s %4s %4s %8s\n",
+		    "HID", "Etype", "Flags", "Callback");
+		TAILQ_FOREACH(crp, &crp_ret_q, crp_next) {
+			db_printf("%4u %4u %04x %8p\n"
+			    , (int) CRYPTO_SESID2HID(crp->crp_sid)
+			    , crp->crp_etype
+			    , crp->crp_flags
+			    , crp->crp_callback
+			);
+		}
+	}
+}
+
+DB_SHOW_COMMAND(kcrypto, db_show_kcrypto)
+{
+	struct cryptkop *krp;
+
+	db_show_drivers();
+	db_printf("\n");
+
+	db_printf("%4s %5s %4s %4s %8s %4s %8s\n",
+	    "Op", "Status", "#IP", "#OP", "CRID", "HID", "Callback");
+	TAILQ_FOREACH(krp, &crp_kq, krp_next) {
+		db_printf("%4u %5u %4u %4u %08x %4u %8p\n"
+		    , krp->krp_op
+		    , krp->krp_status
+		    , krp->krp_iparams, krp->krp_oparams
+		    , krp->krp_crid, krp->krp_hid
+		    , krp->krp_callback
+		);
+	}
+	if (!TAILQ_EMPTY(&crp_ret_q)) {
+		db_printf("%4s %5s %8s %4s %8s\n",
+		    "Op", "Status", "CRID", "HID", "Callback");
+		TAILQ_FOREACH(krp, &crp_ret_kq, krp_next) {
+			db_printf("%4u %5u %08x %4u %8p\n"
+			    , krp->krp_op
+			    , krp->krp_status
+			    , krp->krp_crid, krp->krp_hid
+			    , krp->krp_callback
+			);
+		}
+	}
+}
+#endif
+
+
+int
+crypto_init(void)
+{
+	int error;
+
+	dprintk("%s(0x%x)\n", __FUNCTION__, (int) crypto_init);
+
+	if (crypto_initted)
+		return 0;
+	crypto_initted = 1;
+
+	spin_lock_init(&crypto_drivers_lock);
+	spin_lock_init(&crypto_q_lock);
+	spin_lock_init(&crypto_ret_q_lock);
+
+	cryptop_zone = kmem_cache_create("cryptop", sizeof(struct cryptop),
+				       0, SLAB_HWCACHE_ALIGN, NULL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+				       , NULL
+#endif
+					);
+
+	cryptodesc_zone = kmem_cache_create("cryptodesc", sizeof(struct cryptodesc),
+				       0, SLAB_HWCACHE_ALIGN, NULL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+				       , NULL
+#endif
+					);
+
+	if (cryptodesc_zone == NULL || cryptop_zone == NULL) {
+		printk("crypto: crypto_init cannot setup crypto zones\n");
+		error = ENOMEM;
+		goto bad;
+	}
+
+	crypto_drivers_num = CRYPTO_DRIVERS_INITIAL;
+	crypto_drivers = kmalloc(crypto_drivers_num * sizeof(struct cryptocap),
+			GFP_KERNEL);
+	if (crypto_drivers == NULL) {
+		printk("crypto: crypto_init cannot setup crypto drivers\n");
+		error = ENOMEM;
+		goto bad;
+	}
+
+	memset(crypto_drivers, 0, crypto_drivers_num * sizeof(struct cryptocap));
+
+	init_completion(&cryptoproc_exited);
+	init_completion(&cryptoretproc_exited);
+
+	cryptoproc = 0; /* to avoid race condition where proc runs first */
+	cryptoproc = kernel_thread(crypto_proc, NULL, CLONE_FS|CLONE_FILES);
+	if (cryptoproc < 0) {
+		error = cryptoproc;
+		printk("crypto: crypto_init cannot start crypto thread; error %d",
+			error);
+		goto bad;
+	}
+
+	cryptoretproc = 0; /* to avoid race condition where proc runs first */
+	cryptoretproc = kernel_thread(crypto_ret_proc, NULL, CLONE_FS|CLONE_FILES);
+	if (cryptoretproc < 0) {
+		error = cryptoretproc;
+		printk("crypto: crypto_init cannot start cryptoret thread; error %d",
+				error);
+		goto bad;
+	}
+
+	return 0;
+bad:
+	crypto_exit();
+	return error;
+}
+
+
+static void
+crypto_exit(void)
+{
+	pid_t p;
+	unsigned long d_flags;
+
+	dprintk("%s()\n", __FUNCTION__);
+
+	/*
+	 * Terminate any crypto threads.
+	 */
+
+	CRYPTO_DRIVER_LOCK();
+	p = cryptoproc;
+	cryptoproc = (pid_t) -1;
+	kill_proc_info(SIGTERM, SEND_SIG_PRIV, p);
+	wake_up_interruptible(&cryptoproc_wait);
+	CRYPTO_DRIVER_UNLOCK();
+
+	wait_for_completion(&cryptoproc_exited);
+
+	CRYPTO_DRIVER_LOCK();
+	p = cryptoretproc;
+	cryptoretproc = (pid_t) -1;
+	kill_proc_info(SIGTERM, SEND_SIG_PRIV, p);
+	wake_up_interruptible(&cryptoretproc_wait);
+	CRYPTO_DRIVER_UNLOCK();
+
+	wait_for_completion(&cryptoretproc_exited);
+
+	/* XXX flush queues??? */
+
+	/* 
+	 * Reclaim dynamically allocated resources.
+	 */
+	if (crypto_drivers != NULL)
+		kfree(crypto_drivers);
+
+	if (cryptodesc_zone != NULL)
+		kmem_cache_destroy(cryptodesc_zone);
+	if (cryptop_zone != NULL)
+		kmem_cache_destroy(cryptop_zone);
+}
+
+
+EXPORT_SYMBOL(crypto_newsession);
+EXPORT_SYMBOL(crypto_freesession);
+EXPORT_SYMBOL(crypto_get_driverid);
+EXPORT_SYMBOL(crypto_kregister);
+EXPORT_SYMBOL(crypto_register);
+EXPORT_SYMBOL(crypto_unregister);
+EXPORT_SYMBOL(crypto_unregister_all);
+EXPORT_SYMBOL(crypto_unblock);
+EXPORT_SYMBOL(crypto_dispatch);
+EXPORT_SYMBOL(crypto_kdispatch);
+EXPORT_SYMBOL(crypto_freereq);
+EXPORT_SYMBOL(crypto_getreq);
+EXPORT_SYMBOL(crypto_done);
+EXPORT_SYMBOL(crypto_kdone);
+EXPORT_SYMBOL(crypto_getfeat);
+EXPORT_SYMBOL(crypto_userasymcrypto);
+EXPORT_SYMBOL(crypto_getcaps);
+EXPORT_SYMBOL(crypto_find_driver);
+EXPORT_SYMBOL(crypto_find_device_byhid);
+
+module_init(crypto_init);
+module_exit(crypto_exit);
+
+MODULE_LICENSE("BSD");
+MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_DESCRIPTION("OCF (OpenBSD Cryptographic Framework)");
diff --git a/crypto/ocf/cryptodev.c b/crypto/ocf/cryptodev.c
new file mode 100755
index 0000000..13d57a1
--- /dev/null
+++ b/crypto/ocf/cryptodev.c
@@ -0,0 +1,1048 @@
+/*	$OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $	*/
+
+/*-
+ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ * The license and original author are listed below.
+ *
+ * Copyright (c) 2001 Theo de Raadt
+ * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+__FBSDID("$FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.34 2007/05/09 19:37:02 gnn Exp $");
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/unistd.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/dcache.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/miscdevice.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+
+#include <cryptodev.h>
+#include <uio.h>
+
+extern asmlinkage long sys_dup(unsigned int fildes);
+
+#define debug cryptodev_debug
+int cryptodev_debug = 0;
+module_param(cryptodev_debug, int, 0644);
+MODULE_PARM_DESC(cryptodev_debug, "Enable cryptodev debug");
+
+struct csession_info {
+	u_int16_t	blocksize;
+	u_int16_t	minkey, maxkey;
+
+	u_int16_t	keysize;
+	/* u_int16_t	hashsize;  */
+	u_int16_t	authsize;
+	/* u_int16_t	ctxsize; */
+};
+
+struct csession {
+	struct list_head	list;
+	u_int64_t	sid;
+	u_int32_t	ses;
+
+	wait_queue_head_t waitq;
+
+	u_int32_t	cipher;
+
+	u_int32_t	mac;
+
+	caddr_t		key;
+	int		keylen;
+	u_char		tmp_iv[EALG_MAX_BLOCK_LEN];
+
+	caddr_t		mackey;
+	int		mackeylen;
+
+	struct csession_info info;
+
+	struct iovec	iovec;
+	struct uio	uio;
+	int		error;
+};
+
+struct fcrypt {
+	struct list_head	csessions;
+	int		sesn;
+};
+
+static struct csession *csefind(struct fcrypt *, u_int);
+static int csedelete(struct fcrypt *, struct csession *);
+static struct csession *cseadd(struct fcrypt *, struct csession *);
+static struct csession *csecreate(struct fcrypt *, u_int64_t,
+		struct cryptoini *crie, struct cryptoini *cria, struct csession_info *);
+static int csefree(struct csession *);
+
+static	int cryptodev_op(struct csession *, struct crypt_op *);
+static	int cryptodev_key(struct crypt_kop *);
+static	int cryptodev_find(struct crypt_find_op *);
+
+static int cryptodev_cb(void *);
+static int cryptodev_open(struct inode *inode, struct file *filp);
+
+/*
+ * Check a crypto identifier to see if it requested
+ * a valid crid and it's capabilities match.
+ */
+static int
+checkcrid(int crid)
+{
+	int hid = crid & ~(CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
+	int typ = crid & (CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
+	int caps = 0;
+	
+	/* if the user hasn't selected a driver, then just call newsession */
+	if (hid == 0 && typ != 0)
+		return 0;
+
+	caps = crypto_getcaps(hid);
+
+	/* didn't find anything with capabilities */
+	if (caps == 0) {
+		dprintk("%s: hid=%x typ=%x not matched\n", __FUNCTION__, hid, typ);
+		return EINVAL;
+	}
+	
+	/* the user didn't specify SW or HW, so the driver is ok */
+	if (typ == 0)
+		return 0;
+
+	/* if the type specified didn't match */
+	if (typ != (caps & (CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE))) {
+		dprintk("%s: hid=%x typ=%x caps=%x not matched\n", __FUNCTION__,
+				hid, typ, caps);
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+cryptodev_op(struct csession *cse, struct crypt_op *cop)
+{
+	struct cryptop *crp = NULL;
+	struct cryptodesc *crde = NULL, *crda = NULL;
+	int error = 0;
+
+	dprintk("%s()\n", __FUNCTION__);
+	if (cop->len > CRYPTO_MAX_DATA_LEN) {
+		dprintk("%s: %d > %d\n", __FUNCTION__, cop->len, CRYPTO_MAX_DATA_LEN);
+		return (E2BIG);
+	}
+
+	if (cse->info.blocksize && (cop->len % cse->info.blocksize) != 0) {
+		dprintk("%s: blocksize=%d len=%d\n", __FUNCTION__, cse->info.blocksize,
+				cop->len);
+		return (EINVAL);
+	}
+
+	cse->uio.uio_iov = &cse->iovec;
+	cse->uio.uio_iovcnt = 1;
+	cse->uio.uio_offset = 0;
+#if 0
+	cse->uio.uio_resid = cop->len;
+	cse->uio.uio_segflg = UIO_SYSSPACE;
+	cse->uio.uio_rw = UIO_WRITE;
+	cse->uio.uio_td = td;
+#endif
+	cse->uio.uio_iov[0].iov_len = cop->len;
+	if (cse->info.authsize)
+		cse->uio.uio_iov[0].iov_len += cse->info.authsize;
+	cse->uio.uio_iov[0].iov_base = kmalloc(cse->uio.uio_iov[0].iov_len,
+			GFP_KERNEL);
+
+	if (cse->uio.uio_iov[0].iov_base == NULL) {
+		dprintk("%s: iov_base kmalloc(%d) failed\n", __FUNCTION__,
+				cse->uio.uio_iov[0].iov_len);
+		return (ENOMEM);
+	}
+
+	crp = crypto_getreq((cse->info.blocksize != 0) + (cse->info.authsize != 0));
+	if (crp == NULL) {
+		dprintk("%s: ENOMEM\n", __FUNCTION__);
+		error = ENOMEM;
+		goto bail;
+	}
+
+	if (cse->info.authsize) {
+		crda = crp->crp_desc;
+		if (cse->info.blocksize)
+			crde = crda->crd_next;
+	} else {
+		if (cse->info.blocksize)
+			crde = crp->crp_desc;
+		else {
+			dprintk("%s: bad request\n", __FUNCTION__);
+			error = EINVAL;
+			goto bail;
+		}
+	}
+
+	if ((error = copy_from_user(cse->uio.uio_iov[0].iov_base, cop->src,
+					cop->len))) {
+		dprintk("%s: bad copy\n", __FUNCTION__);
+		goto bail;
+	}
+
+	if (crda) {
+		crda->crd_skip = 0;
+		crda->crd_len = cop->len;
+		crda->crd_inject = cop->len;
+
+		crda->crd_alg = cse->mac;
+		crda->crd_key = cse->mackey;
+		crda->crd_klen = cse->mackeylen * 8;
+	}
+
+	if (crde) {
+		if (cop->op == COP_ENCRYPT)
+			crde->crd_flags |= CRD_F_ENCRYPT;
+		else
+			crde->crd_flags &= ~CRD_F_ENCRYPT;
+		crde->crd_len = cop->len;
+		crde->crd_inject = 0;
+
+		crde->crd_alg = cse->cipher;
+		crde->crd_key = cse->key;
+		crde->crd_klen = cse->keylen * 8;
+	}
+
+	crp->crp_ilen = cse->uio.uio_iov[0].iov_len;
+	crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
+		       | (cop->flags & COP_F_BATCH);
+	crp->crp_buf = (caddr_t)&cse->uio;
+	crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
+	crp->crp_sid = cse->sid;
+	crp->crp_opaque = (void *)cse;
+
+	if (cop->iv) {
+		if (crde == NULL) {
+			error = EINVAL;
+			dprintk("%s no crde\n", __FUNCTION__);
+			goto bail;
+		}
+		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
+			error = EINVAL;
+			dprintk("%s arc4 with IV\n", __FUNCTION__);
+			goto bail;
+		}
+		if ((error = copy_from_user(cse->tmp_iv, cop->iv,
+						cse->info.blocksize))) {
+			dprintk("%s bad iv copy\n", __FUNCTION__);
+			goto bail;
+		}
+		memcpy(crde->crd_iv, cse->tmp_iv, cse->info.blocksize);
+		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
+		crde->crd_skip = 0;
+	} else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
+		crde->crd_skip = 0;
+	} else if (crde) {
+		crde->crd_flags |= CRD_F_IV_PRESENT;
+		crde->crd_skip = cse->info.blocksize;
+		crde->crd_len -= cse->info.blocksize;
+	}
+
+	if (cop->mac && crda == NULL) {
+		error = EINVAL;
+		dprintk("%s no crda\n", __FUNCTION__);
+		goto bail;
+	}
+
+	/*
+	 * Let the dispatch run unlocked, then, interlock against the
+	 * callback before checking if the operation completed and going
+	 * to sleep.  This insures drivers don't inherit our lock which
+	 * results in a lock order reversal between crypto_dispatch forced
+	 * entry and the crypto_done callback into us.
+	 */
+	error = crypto_dispatch(crp);
+	if (error == 0) {
+		dprintk("%s about to WAIT\n", __FUNCTION__);
+		/*
+		 * we really need to wait for driver to complete to maintain
+		 * state,  luckily interrupts will be remembered
+		 */
+		do {
+			error = wait_event_interruptible(crp->crp_waitq,
+					((crp->crp_flags & CRYPTO_F_DONE) != 0));
+			/*
+			 * we can't break out of this loop or we will leave behind
+			 * a huge mess,  however,  staying here means if your driver
+			 * is broken user applications can hang and not be killed.
+			 * The solution,  fix your driver :-)
+			 */
+			if (error) {
+				schedule();
+				error = 0;
+			}
+		} while ((crp->crp_flags & CRYPTO_F_DONE) == 0);
+		dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
+	}
+
+	if (crp->crp_etype != 0) {
+		error = crp->crp_etype;
+		dprintk("%s error in crp processing\n", __FUNCTION__);
+		goto bail;
+	}
+
+	if (cse->error) {
+		error = cse->error;
+		dprintk("%s error in cse processing\n", __FUNCTION__);
+		goto bail;
+	}
+
+	if (cop->dst && (error = copy_to_user(cop->dst,
+					cse->uio.uio_iov[0].iov_base, cop->len))) {
+		dprintk("%s bad dst copy\n", __FUNCTION__);
+		goto bail;
+	}
+
+	if (cop->mac &&
+			(error=copy_to_user(cop->mac,
+				(caddr_t)cse->uio.uio_iov[0].iov_base + cop->len,
+				cse->info.authsize))) {
+		dprintk("%s bad mac copy\n", __FUNCTION__);
+		goto bail;
+	}
+
+bail:
+	if (crp)
+		crypto_freereq(crp);
+	if (cse->uio.uio_iov[0].iov_base)
+		kfree(cse->uio.uio_iov[0].iov_base);
+
+	return (error);
+}
+
+static int
+cryptodev_cb(void *op)
+{
+	struct cryptop *crp = (struct cryptop *) op;
+	struct csession *cse = (struct csession *)crp->crp_opaque;
+	int error;
+
+	dprintk("%s()\n", __FUNCTION__);
+	error = crp->crp_etype;
+	if (error == EAGAIN) {
+		crp->crp_flags &= ~CRYPTO_F_DONE;
+#ifdef NOTYET
+		/*
+		 * DAVIDM I am fairly sure that we should turn this into a batch
+		 * request to stop bad karma/lockup, revisit
+		 */
+		crp->crp_flags |= CRYPTO_F_BATCH;
+#endif
+		return crypto_dispatch(crp);
+	}
+	if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
+		cse->error = error;
+		wake_up_interruptible(&crp->crp_waitq);
+	}
+	return (0);
+}
+
+static int
+cryptodevkey_cb(void *op)
+{
+	struct cryptkop *krp = (struct cryptkop *) op;
+	dprintk("%s()\n", __FUNCTION__);
+	wake_up_interruptible(&krp->krp_waitq);
+	return (0);
+}
+
+static int
+cryptodev_key(struct crypt_kop *kop)
+{
+	struct cryptkop *krp = NULL;
+	int error = EINVAL;
+	int in, out, size, i;
+
+	dprintk("%s()\n", __FUNCTION__);
+	if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
+		dprintk("%s params too big\n", __FUNCTION__);
+		return (EFBIG);
+	}
+
+	in = kop->crk_iparams;
+	out = kop->crk_oparams;
+	switch (kop->crk_op) {
+	case CRK_MOD_EXP:
+		if (in == 3 && out == 1)
+			break;
+		return (EINVAL);
+	case CRK_MOD_EXP_CRT:
+		if (in == 6 && out == 1)
+			break;
+		return (EINVAL);
+	case CRK_DSA_SIGN:
+		if (in == 5 && out == 2)
+			break;
+		return (EINVAL);
+	case CRK_DSA_VERIFY:
+		if (in == 7 && out == 0)
+			break;
+		return (EINVAL);
+	case CRK_DH_COMPUTE_KEY:
+		if (in == 3 && out == 1)
+			break;
+		return (EINVAL);
+	default:
+		return (EINVAL);
+	}
+
+	krp = (struct cryptkop *)kmalloc(sizeof *krp, GFP_KERNEL);
+	if (!krp)
+		return (ENOMEM);
+	bzero(krp, sizeof *krp);
+	krp->krp_op = kop->crk_op;
+	krp->krp_status = kop->crk_status;
+	krp->krp_iparams = kop->crk_iparams;
+	krp->krp_oparams = kop->crk_oparams;
+	krp->krp_crid = kop->crk_crid;
+	krp->krp_status = 0;
+	krp->krp_flags = CRYPTO_KF_CBIMM;
+	krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
+	init_waitqueue_head(&krp->krp_waitq);
+
+	for (i = 0; i < CRK_MAXPARAM; i++)
+		krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
+	for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
+		size = (krp->krp_param[i].crp_nbits + 7) / 8;
+		if (size == 0)
+			continue;
+		krp->krp_param[i].crp_p = (caddr_t) kmalloc(size, GFP_KERNEL);
+		if (i >= krp->krp_iparams)
+			continue;
+		error = copy_from_user(krp->krp_param[i].crp_p,
+				kop->crk_param[i].crp_p, size);
+		if (error)
+			goto fail;
+	}
+
+	error = crypto_kdispatch(krp);
+	if (error)
+		goto fail;
+
+	do {
+		error = wait_event_interruptible(krp->krp_waitq,
+				((krp->krp_flags & CRYPTO_KF_DONE) != 0));
+		/*
+		 * we can't break out of this loop or we will leave behind
+		 * a huge mess,  however,  staying here means if your driver
+		 * is broken user applications can hang and not be killed.
+		 * The solution,  fix your driver :-)
+		 */
+		if (error) {
+			schedule();
+			error = 0;
+		}
+	} while ((krp->krp_flags & CRYPTO_KF_DONE) == 0);
+
+	dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
+	
+	kop->crk_crid = krp->krp_crid;		/* device that did the work */
+	if (krp->krp_status != 0) {
+		error = krp->krp_status;
+		goto fail;
+	}
+
+	for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
+		size = (krp->krp_param[i].crp_nbits + 7) / 8;
+		if (size == 0)
+			continue;
+		error = copy_to_user(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p,
+				size);
+		if (error)
+			goto fail;
+	}
+
+fail:
+	if (krp) {
+		kop->crk_status = krp->krp_status;
+		for (i = 0; i < CRK_MAXPARAM; i++) {
+			if (krp->krp_param[i].crp_p)
+				kfree(krp->krp_param[i].crp_p);
+		}
+		kfree(krp);
+	}
+	return (error);
+}
+
+static int
+cryptodev_find(struct crypt_find_op *find)
+{
+	device_t dev;
+
+	if (find->crid != -1) {
+		dev = crypto_find_device_byhid(find->crid);
+		if (dev == NULL)
+			return (ENOENT);
+		strlcpy(find->name, device_get_nameunit(dev),
+		    sizeof(find->name));
+	} else {
+		find->crid = crypto_find_driver(find->name);
+		if (find->crid == -1)
+			return (ENOENT);
+	}
+	return (0);
+}
+
+static struct csession *
+csefind(struct fcrypt *fcr, u_int ses)
+{
+	struct csession *cse;
+
+	dprintk("%s()\n", __FUNCTION__);
+	list_for_each_entry(cse, &fcr->csessions, list)
+		if (cse->ses == ses)
+			return (cse);
+	return (NULL);
+}
+
+static int
+csedelete(struct fcrypt *fcr, struct csession *cse_del)
+{
+	struct csession *cse;
+
+	dprintk("%s()\n", __FUNCTION__);
+	list_for_each_entry(cse, &fcr->csessions, list) {
+		if (cse == cse_del) {
+			list_del(&cse->list);
+			return (1);
+		}
+	}
+	return (0);
+}
+	
+static struct csession *
+cseadd(struct fcrypt *fcr, struct csession *cse)
+{
+	dprintk("%s()\n", __FUNCTION__);
+	list_add_tail(&cse->list, &fcr->csessions);
+	cse->ses = fcr->sesn++;
+	return (cse);
+}
+
+static struct csession *
+csecreate(struct fcrypt *fcr, u_int64_t sid, struct cryptoini *crie,
+	struct cryptoini *cria, struct csession_info *info)
+{
+	struct csession *cse;
+
+	dprintk("%s()\n", __FUNCTION__);
+	cse = (struct csession *) kmalloc(sizeof(struct csession), GFP_KERNEL);
+	if (cse == NULL)
+		return NULL;
+	memset(cse, 0, sizeof(struct csession));
+
+	INIT_LIST_HEAD(&cse->list);
+	init_waitqueue_head(&cse->waitq);
+
+	cse->key = crie->cri_key;
+	cse->keylen = crie->cri_klen/8;
+	cse->mackey = cria->cri_key;
+	cse->mackeylen = cria->cri_klen/8;
+	cse->sid = sid;
+	cse->cipher = crie->cri_alg;
+	cse->mac = cria->cri_alg;
+	cse->info = *info;
+	cseadd(fcr, cse);
+	return (cse);
+}
+
+static int
+csefree(struct csession *cse)
+{
+	int error;
+
+	dprintk("%s()\n", __FUNCTION__);
+	error = crypto_freesession(cse->sid);
+	if (cse->key)
+		kfree(cse->key);
+	if (cse->mackey)
+		kfree(cse->mackey);
+	kfree(cse);
+	return(error);
+}
+
+static int
+cryptodev_ioctl(
+	struct inode *inode,
+	struct file *filp,
+	unsigned int cmd,
+	unsigned long arg)
+{
+	struct cryptoini cria, crie;
+	struct fcrypt *fcr = filp->private_data;
+	struct csession *cse;
+	struct csession_info info;
+	struct session2_op sop;
+	struct crypt_op cop;
+	struct crypt_kop kop;
+	struct crypt_find_op fop;
+	u_int64_t sid;
+	u_int32_t ses;
+	int feat, fd, error = 0, crid;
+	mm_segment_t fs;
+
+	dprintk("%s(cmd=%x arg=%lx)\n", __FUNCTION__, cmd, arg);
+
+	switch (cmd) {
+
+	case CRIOGET: {
+		dprintk("%s(CRIOGET)\n", __FUNCTION__);
+		fs = get_fs();
+		set_fs(get_ds());
+		for (fd = 0; fd < files_fdtable(current->files)->max_fds; fd++)
+			if (files_fdtable(current->files)->fd[fd] == filp)
+				break;
+		fd = sys_dup(fd);
+		set_fs(fs);
+		put_user(fd, (int *) arg);
+		return IS_ERR_VALUE(fd) ? fd : 0;
+		}
+
+#define	CIOCGSESSSTR	(cmd == CIOCGSESSION ? "CIOCGSESSION" : "CIOCGSESSION2")
+	case CIOCGSESSION:
+	case CIOCGSESSION2:
+		dprintk("%s(%s)\n", __FUNCTION__, CIOCGSESSSTR);
+		memset(&crie, 0, sizeof(crie));
+		memset(&cria, 0, sizeof(cria));
+		memset(&info, 0, sizeof(info));
+		memset(&sop, 0, sizeof(sop));
+
+		if (copy_from_user(&sop, (void*)arg, (cmd == CIOCGSESSION) ?
+					sizeof(struct session_op) : sizeof(sop))) {
+			dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
+			error = EFAULT;
+			goto bail;
+		}
+
+		switch (sop.cipher) {
+		case 0:
+			dprintk("%s(%s) - no cipher\n", __FUNCTION__, CIOCGSESSSTR);
+			break;
+		case CRYPTO_NULL_CBC:
+			info.blocksize = NULL_BLOCK_LEN;
+			info.minkey = NULL_MIN_KEY_LEN;
+			info.maxkey = NULL_MAX_KEY_LEN;
+			break;
+		case CRYPTO_DES_CBC:
+			info.blocksize = DES_BLOCK_LEN;
+			info.minkey = DES_MIN_KEY_LEN;
+			info.maxkey = DES_MAX_KEY_LEN;
+			break;
+		case CRYPTO_3DES_CBC:
+			info.blocksize = DES3_BLOCK_LEN;
+			info.minkey = DES3_MIN_KEY_LEN;
+			info.maxkey = DES3_MAX_KEY_LEN;
+			break;
+		case CRYPTO_BLF_CBC:
+			info.blocksize = BLOWFISH_BLOCK_LEN;
+			info.minkey = BLOWFISH_MIN_KEY_LEN;
+			info.maxkey = BLOWFISH_MAX_KEY_LEN;
+			break;
+		case CRYPTO_CAST_CBC:
+			info.blocksize = CAST128_BLOCK_LEN;
+			info.minkey = CAST128_MIN_KEY_LEN;
+			info.maxkey = CAST128_MAX_KEY_LEN;
+			break;
+		case CRYPTO_SKIPJACK_CBC:
+			info.blocksize = SKIPJACK_BLOCK_LEN;
+			info.minkey = SKIPJACK_MIN_KEY_LEN;
+			info.maxkey = SKIPJACK_MAX_KEY_LEN;
+			break;
+		case CRYPTO_AES_CBC:
+			info.blocksize = AES_BLOCK_LEN;
+			info.minkey = AES_MIN_KEY_LEN;
+			info.maxkey = AES_MAX_KEY_LEN;
+			break;
+		case CRYPTO_ARC4:
+			info.blocksize = ARC4_BLOCK_LEN;
+			info.minkey = ARC4_MIN_KEY_LEN;
+			info.maxkey = ARC4_MAX_KEY_LEN;
+			break;
+		case CRYPTO_CAMELLIA_CBC:
+			info.blocksize = CAMELLIA_BLOCK_LEN;
+			info.minkey = CAMELLIA_MIN_KEY_LEN;
+			info.maxkey = CAMELLIA_MAX_KEY_LEN;
+			break;
+		default:
+			dprintk("%s(%s) - bad cipher\n", __FUNCTION__, CIOCGSESSSTR);
+			error = EINVAL;
+			goto bail;
+		}
+
+		switch (sop.mac) {
+		case 0:
+			dprintk("%s(%s) - no mac\n", __FUNCTION__, CIOCGSESSSTR);
+			break;
+		case CRYPTO_NULL_HMAC:
+			info.authsize = NULL_HASH_LEN;
+			break;
+		case CRYPTO_MD5:
+			info.authsize = MD5_HASH_LEN;
+			break;
+		case CRYPTO_SHA1:
+			info.authsize = SHA1_HASH_LEN;
+			break;
+		case CRYPTO_SHA2_256:
+			info.authsize = SHA2_256_HASH_LEN;
+			break;
+		case CRYPTO_SHA2_384:
+			info.authsize = SHA2_384_HASH_LEN;
+  			break;
+		case CRYPTO_SHA2_512:
+			info.authsize = SHA2_512_HASH_LEN;
+			break;
+		case CRYPTO_RIPEMD160:
+			info.authsize = RIPEMD160_HASH_LEN;
+			break;
+		case CRYPTO_MD5_HMAC:
+			info.authsize = MD5_HASH_LEN;
+			break;
+		case CRYPTO_SHA1_HMAC:
+			info.authsize = SHA1_HASH_LEN;
+			break;
+		case CRYPTO_SHA2_256_HMAC:
+			info.authsize = SHA2_256_HASH_LEN;
+			break;
+		case CRYPTO_SHA2_384_HMAC:
+			info.authsize = SHA2_384_HASH_LEN;
+  			break;
+		case CRYPTO_SHA2_512_HMAC:
+			info.authsize = SHA2_512_HASH_LEN;
+			break;
+		case CRYPTO_RIPEMD160_HMAC:
+			info.authsize = RIPEMD160_HASH_LEN;
+			break;
+		default:
+			dprintk("%s(%s) - bad mac\n", __FUNCTION__, CIOCGSESSSTR);
+			error = EINVAL;
+			goto bail;
+		}
+
+		if (info.blocksize) {
+			crie.cri_alg = sop.cipher;
+			crie.cri_klen = sop.keylen * 8;
+			if ((info.maxkey && sop.keylen > info.maxkey) ||
+				   	sop.keylen < info.minkey) {
+				dprintk("%s(%s) - bad key\n", __FUNCTION__, CIOCGSESSSTR);
+				error = EINVAL;
+				goto bail;
+			}
+
+			crie.cri_key = (u_int8_t *) kmalloc(crie.cri_klen/8+1, GFP_KERNEL);
+			if (copy_from_user(crie.cri_key, sop.key,
+							crie.cri_klen/8)) {
+				dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
+				error = EFAULT;
+				goto bail;
+			}
+			if (info.authsize)
+				crie.cri_next = &cria;
+		}
+
+		if (info.authsize) {
+			cria.cri_alg = sop.mac;
+			cria.cri_klen = sop.mackeylen * 8;
+			if ((info.maxkey && sop.mackeylen > info.maxkey) ||
+					sop.keylen < info.minkey) {
+				dprintk("%s(%s) - mackeylen %d\n", __FUNCTION__, CIOCGSESSSTR,
+						sop.mackeylen);
+				error = EINVAL;
+				goto bail;
+			}
+
+			if (cria.cri_klen) {
+				cria.cri_key = (u_int8_t *) kmalloc(cria.cri_klen/8,GFP_KERNEL);
+				if (copy_from_user(cria.cri_key, sop.mackey,
+								cria.cri_klen / 8)) {
+					dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
+					error = EFAULT;
+					goto bail;
+				}
+			}
+		}
+
+		/* NB: CIOGSESSION2 has the crid */
+		if (cmd == CIOCGSESSION2) {
+			crid = sop.crid;
+			error = checkcrid(crid);
+			if (error) {
+				dprintk("%s(%s) - checkcrid %x\n", __FUNCTION__,
+						CIOCGSESSSTR, error);
+				goto bail;
+			}
+		} else {
+			/* allow either HW or SW to be used */
+			crid = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
+		}
+		error = crypto_newsession(&sid, (info.blocksize ? &crie : &cria), crid);
+		if (error) {
+			dprintk("%s(%s) - newsession %d\n",__FUNCTION__,CIOCGSESSSTR,error);
+			goto bail;
+		}
+
+		cse = csecreate(fcr, sid, &crie, &cria, &info);
+		if (cse == NULL) {
+			crypto_freesession(sid);
+			error = EINVAL;
+			dprintk("%s(%s) - csecreate failed\n", __FUNCTION__, CIOCGSESSSTR);
+			goto bail;
+		}
+		sop.ses = cse->ses;
+
+		if (cmd == CIOCGSESSION2) {
+			/* return hardware/driver id */
+			sop.crid = CRYPTO_SESID2HID(cse->sid);
+		}
+
+		if (copy_to_user((void*)arg, &sop, (cmd == CIOCGSESSION) ?
+					sizeof(struct session_op) : sizeof(sop))) {
+			dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
+			error = EFAULT;
+		}
+bail:
+		if (error) {
+			dprintk("%s(%s) - bail %d\n", __FUNCTION__, CIOCGSESSSTR, error);
+			if (crie.cri_key)
+				kfree(crie.cri_key);
+			if (cria.cri_key)
+				kfree(cria.cri_key);
+		}
+		break;
+	case CIOCFSESSION:
+		dprintk("%s(CIOCFSESSION)\n", __FUNCTION__);
+		get_user(ses, (uint32_t*)arg);
+		cse = csefind(fcr, ses);
+		if (cse == NULL) {
+			error = EINVAL;
+			dprintk("%s(CIOCFSESSION) - Fail %d\n", __FUNCTION__, error);
+			break;
+		}
+		csedelete(fcr, cse);
+		error = csefree(cse);
+		break;
+	case CIOCCRYPT:
+		dprintk("%s(CIOCCRYPT)\n", __FUNCTION__);
+		if(copy_from_user(&cop, (void*)arg, sizeof(cop))) {
+			dprintk("%s(CIOCCRYPT) - bad copy\n", __FUNCTION__);
+			error = EFAULT;
+			goto bail;
+		}
+		cse = csefind(fcr, cop.ses);
+		if (cse == NULL) {
+			error = EINVAL;
+			dprintk("%s(CIOCCRYPT) - Fail %d\n", __FUNCTION__, error);
+			break;
+		}
+		error = cryptodev_op(cse, &cop);
+		if(copy_to_user((void*)arg, &cop, sizeof(cop))) {
+			dprintk("%s(CIOCCRYPT) - bad return copy\n", __FUNCTION__);
+			error = EFAULT;
+			goto bail;
+		}
+		break;
+	case CIOCKEY:
+	case CIOCKEY2:
+		dprintk("%s(CIOCKEY)\n", __FUNCTION__);
+		if (!crypto_userasymcrypto)
+			return (EPERM);		/* XXX compat? */
+		if(copy_from_user(&kop, (void*)arg, sizeof(kop))) {
+			dprintk("%s(CIOCKEY) - bad copy\n", __FUNCTION__);
+			error = EFAULT;
+			goto bail;
+		}
+		if (cmd == CIOCKEY) {
+			/* NB: crypto core enforces s/w driver use */
+			kop.crk_crid =
+			    CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
+		}
+		error = cryptodev_key(&kop);
+		if(copy_to_user((void*)arg, &kop, sizeof(kop))) {
+			dprintk("%s(CIOCGKEY) - bad return copy\n", __FUNCTION__);
+			error = EFAULT;
+			goto bail;
+		}
+		break;
+	case CIOCASYMFEAT:
+		dprintk("%s(CIOCASYMFEAT)\n", __FUNCTION__);
+		if (!crypto_userasymcrypto) {
+			/*
+			 * NB: if user asym crypto operations are
+			 * not permitted return "no algorithms"
+			 * so well-behaved applications will just
+			 * fallback to doing them in software.
+			 */
+			feat = 0;
+		} else
+			error = crypto_getfeat(&feat);
+		if (!error) {
+		  error = copy_to_user((void*)arg, &feat, sizeof(feat));
+		}
+		break;
+	case CIOCFINDDEV:
+		if (copy_from_user(&fop, (void*)arg, sizeof(fop))) {
+			dprintk("%s(CIOCFINDDEV) - bad copy\n", __FUNCTION__);
+			error = EFAULT;
+			goto bail;
+		}
+		error = cryptodev_find(&fop);
+		if (copy_to_user((void*)arg, &fop, sizeof(fop))) {
+			dprintk("%s(CIOCFINDDEV) - bad return copy\n", __FUNCTION__);
+			error = EFAULT;
+			goto bail;
+		}
+		break;
+	default:
+		dprintk("%s(unknown ioctl 0x%x)\n", __FUNCTION__, cmd);
+		error = EINVAL;
+		break;
+	}
+	return(-error);
+}
+
+#ifdef HAVE_UNLOCKED_IOCTL
+static long
+cryptodev_unlocked_ioctl(
+	struct file *filp,
+	unsigned int cmd,
+	unsigned long arg)
+{
+	return cryptodev_ioctl(NULL, filp, cmd, arg);
+}
+#endif
+
+static int
+cryptodev_open(struct inode *inode, struct file *filp)
+{
+	struct fcrypt *fcr;
+
+	dprintk("%s()\n", __FUNCTION__);
+	if (filp->private_data) {
+		printk("cryptodev: Private data already exists !\n");
+		return(0);
+	}
+
+	fcr = kmalloc(sizeof(*fcr), GFP_KERNEL);
+	if (!fcr) {
+		dprintk("%s() - malloc failed\n", __FUNCTION__);
+		return(-ENOMEM);
+	}
+	memset(fcr, 0, sizeof(*fcr));
+
+	INIT_LIST_HEAD(&fcr->csessions);
+	filp->private_data = fcr;
+	return(0);
+}
+
+static int
+cryptodev_release(struct inode *inode, struct file *filp)
+{
+	struct fcrypt *fcr = filp->private_data;
+	struct csession *cse, *tmp;
+
+	dprintk("%s()\n", __FUNCTION__);
+	if (!filp) {
+		printk("cryptodev: No private data on release\n");
+		return(0);
+	}
+
+	list_for_each_entry_safe(cse, tmp, &fcr->csessions, list) {
+		list_del(&cse->list);
+		(void)csefree(cse);
+	}
+	filp->private_data = NULL;
+	kfree(fcr);
+	return(0);
+}
+
+static struct file_operations cryptodev_fops = {
+	.owner = THIS_MODULE,
+	.open = cryptodev_open,
+	.release = cryptodev_release,
+	.ioctl = cryptodev_ioctl,
+#ifdef HAVE_UNLOCKED_IOCTL
+	.unlocked_ioctl = cryptodev_unlocked_ioctl,
+#endif
+};
+
+static struct miscdevice cryptodev = {
+	.minor = CRYPTODEV_MINOR,
+	.name = "crypto",
+	.fops = &cryptodev_fops,
+};
+
+static int __init
+cryptodev_init(void)
+{
+	int rc;
+
+	dprintk("%s(%p)\n", __FUNCTION__, cryptodev_init);
+	rc = misc_register(&cryptodev);
+	if (rc) {
+		printk(KERN_ERR "cryptodev: registration of /dev/crypto failed\n");
+		return(rc);
+	}
+
+	return(0);
+}
+
+static void __exit
+cryptodev_exit(void)
+{
+	dprintk("%s()\n", __FUNCTION__);
+	misc_deregister(&cryptodev);
+}
+
+module_init(cryptodev_init);
+module_exit(cryptodev_exit);
+
+MODULE_LICENSE("BSD");
+MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_DESCRIPTION("Cryptodev (user interface to OCF)");
diff --git a/crypto/ocf/cryptodev.h b/crypto/ocf/cryptodev.h
new file mode 100755
index 0000000..3ec926d
--- /dev/null
+++ b/crypto/ocf/cryptodev.h
@@ -0,0 +1,479 @@
+/*	$FreeBSD: src/sys/opencrypto/cryptodev.h,v 1.25 2007/05/09 19:37:02 gnn Exp $	*/
+/*	$OpenBSD: cryptodev.h,v 1.31 2002/06/11 11:14:29 beck Exp $	*/
+
+/*-
+ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ * The license and original author are listed below.
+ *
+ * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
+ * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
+ *
+ * This code was written by Angelos D. Keromytis in Athens, Greece, in
+ * February 2000. Network Security Technologies Inc. (NSTI) kindly
+ * supported the development of this code.
+ *
+ * Copyright (c) 2000 Angelos D. Keromytis
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all source code copies of any software which is or includes a copy or
+ * modification of this software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ *
+ * Copyright (c) 2001 Theo de Raadt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#ifndef _CRYPTO_CRYPTO_H_
+#define _CRYPTO_CRYPTO_H_
+
+/* Some initial values */
+#define CRYPTO_DRIVERS_INITIAL	4
+#define CRYPTO_SW_SESSIONS	32
+
+/* Hash values */
+#define NULL_HASH_LEN		0
+#define MD5_HASH_LEN		16
+#define SHA1_HASH_LEN		20
+#define RIPEMD160_HASH_LEN	20
+#define SHA2_256_HASH_LEN	32
+#define SHA2_384_HASH_LEN	48
+#define SHA2_512_HASH_LEN	64
+#define MD5_KPDK_HASH_LEN	16
+#define SHA1_KPDK_HASH_LEN	20
+/* Maximum hash algorithm result length */
+#define HASH_MAX_LEN		SHA2_512_HASH_LEN /* Keep this updated */
+
+/* HMAC values */
+#define NULL_HMAC_BLOCK_LEN			1
+#define MD5_HMAC_BLOCK_LEN			64
+#define SHA1_HMAC_BLOCK_LEN			64
+#define RIPEMD160_HMAC_BLOCK_LEN	64
+#define SHA2_256_HMAC_BLOCK_LEN		64
+#define SHA2_384_HMAC_BLOCK_LEN		128
+#define SHA2_512_HMAC_BLOCK_LEN		128
+/* Maximum HMAC block length */
+#define HMAC_MAX_BLOCK_LEN		SHA2_512_HMAC_BLOCK_LEN /* Keep this updated */
+#define HMAC_IPAD_VAL			0x36
+#define HMAC_OPAD_VAL			0x5C
+
+/* Encryption algorithm block sizes */
+#define NULL_BLOCK_LEN			1
+#define DES_BLOCK_LEN			8
+#define DES3_BLOCK_LEN			8
+#define BLOWFISH_BLOCK_LEN		8
+#define SKIPJACK_BLOCK_LEN		8
+#define CAST128_BLOCK_LEN		8
+#define RIJNDAEL128_BLOCK_LEN	16
+#define AES_BLOCK_LEN			RIJNDAEL128_BLOCK_LEN
+#define CAMELLIA_BLOCK_LEN		16
+#define ARC4_BLOCK_LEN			1
+#define EALG_MAX_BLOCK_LEN		AES_BLOCK_LEN /* Keep this updated */
+
+/* Encryption algorithm min and max key sizes */
+#define NULL_MIN_KEY_LEN		0
+#define NULL_MAX_KEY_LEN		0
+#define DES_MIN_KEY_LEN			8
+#define DES_MAX_KEY_LEN			8
+#define DES3_MIN_KEY_LEN		24
+#define DES3_MAX_KEY_LEN		24
+#define BLOWFISH_MIN_KEY_LEN	4
+#define BLOWFISH_MAX_KEY_LEN	56
+#define SKIPJACK_MIN_KEY_LEN	10
+#define SKIPJACK_MAX_KEY_LEN	10
+#define CAST128_MIN_KEY_LEN		5
+#define CAST128_MAX_KEY_LEN		16
+#define RIJNDAEL128_MIN_KEY_LEN	16
+#define RIJNDAEL128_MAX_KEY_LEN	32
+#define AES_MIN_KEY_LEN			RIJNDAEL128_MIN_KEY_LEN
+#define AES_MAX_KEY_LEN			RIJNDAEL128_MAX_KEY_LEN
+#define CAMELLIA_MIN_KEY_LEN	16
+#define CAMELLIA_MAX_KEY_LEN	32
+#define ARC4_MIN_KEY_LEN		1
+#define ARC4_MAX_KEY_LEN		256
+
+/* Max size of data that can be processed */
+#define CRYPTO_MAX_DATA_LEN		64*1024 - 1
+
+#define CRYPTO_ALGORITHM_MIN	1
+#define CRYPTO_DES_CBC			1
+#define CRYPTO_3DES_CBC			2
+#define CRYPTO_BLF_CBC			3
+#define CRYPTO_CAST_CBC			4
+#define CRYPTO_SKIPJACK_CBC		5
+#define CRYPTO_MD5_HMAC			6
+#define CRYPTO_SHA1_HMAC		7
+#define CRYPTO_RIPEMD160_HMAC	8
+#define CRYPTO_MD5_KPDK			9
+#define CRYPTO_SHA1_KPDK		10
+#define CRYPTO_RIJNDAEL128_CBC	11 /* 128 bit blocksize */
+#define CRYPTO_AES_CBC			11 /* 128 bit blocksize -- the same as above */
+#define CRYPTO_ARC4				12
+#define CRYPTO_MD5				13
+#define CRYPTO_SHA1				14
+#define CRYPTO_NULL_HMAC		15
+#define CRYPTO_NULL_CBC			16
+#define CRYPTO_DEFLATE_COMP		17 /* Deflate compression algorithm */
+#define CRYPTO_SHA2_256_HMAC	18
+#define CRYPTO_SHA2_384_HMAC	19
+#define CRYPTO_SHA2_512_HMAC	20
+#define CRYPTO_CAMELLIA_CBC		21
+#define CRYPTO_SHA2_256			22
+#define CRYPTO_SHA2_384			23
+#define CRYPTO_SHA2_512			24
+#define CRYPTO_RIPEMD160		25
+#define CRYPTO_ALGORITHM_MAX	25 /* Keep updated - see below */
+
+/* Algorithm flags */
+#define CRYPTO_ALG_FLAG_SUPPORTED	0x01 /* Algorithm is supported */
+#define CRYPTO_ALG_FLAG_RNG_ENABLE	0x02 /* Has HW RNG for DH/DSA */
+#define CRYPTO_ALG_FLAG_DSA_SHA		0x04 /* Can do SHA on msg */
+
+/*
+ * Crypto driver/device flags.  They can set in the crid
+ * parameter when creating a session or submitting a key
+ * op to affect the device/driver assigned.  If neither
+ * of these are specified then the crid is assumed to hold
+ * the driver id of an existing (and suitable) device that
+ * must be used to satisfy the request.
+ */
+#define CRYPTO_FLAG_HARDWARE	0x01000000	/* hardware accelerated */
+#define CRYPTO_FLAG_SOFTWARE	0x02000000	/* software implementation */
+
+/* NB: deprecated */
+struct session_op {
+	u_int32_t	cipher;		/* ie. CRYPTO_DES_CBC */
+	u_int32_t	mac;		/* ie. CRYPTO_MD5_HMAC */
+
+	u_int32_t	keylen;		/* cipher key */
+	caddr_t		key;
+	int		mackeylen;	/* mac key */
+	caddr_t		mackey;
+
+  	u_int32_t	ses;		/* returns: session # */ 
+};
+
+struct session2_op {
+	u_int32_t	cipher;		/* ie. CRYPTO_DES_CBC */
+	u_int32_t	mac;		/* ie. CRYPTO_MD5_HMAC */
+
+	u_int32_t	keylen;		/* cipher key */
+	caddr_t		key;
+	int		mackeylen;	/* mac key */
+	caddr_t		mackey;
+
+  	u_int32_t	ses;		/* returns: session # */ 
+	int		crid;		/* driver id + flags (rw) */
+	int		pad[4];		/* for future expansion */
+};
+
+struct crypt_op {
+	u_int32_t	ses;
+	u_int16_t	op;		/* i.e. COP_ENCRYPT */
+#define COP_NONE	0
+#define COP_ENCRYPT	1
+#define COP_DECRYPT	2
+	u_int16_t	flags;
+#define	COP_F_BATCH	0x0008		/* Batch op if possible */
+	u_int		len;
+	caddr_t		src, dst;	/* become iov[] inside kernel */
+	caddr_t		mac;		/* must be big enough for chosen MAC */
+	caddr_t		iv;
+};
+
+/*
+ * Parameters for looking up a crypto driver/device by
+ * device name or by id.  The latter are returned for
+ * created sessions (crid) and completed key operations.
+ */
+struct crypt_find_op {
+	int		crid;		/* driver id + flags */
+	char		name[32];	/* device/driver name */
+};
+
+/* bignum parameter, in packed bytes, ... */
+struct crparam {
+	caddr_t		crp_p;
+	u_int		crp_nbits;
+};
+
+#define CRK_MAXPARAM	8
+
+struct crypt_kop {
+	u_int		crk_op;		/* ie. CRK_MOD_EXP or other */
+	u_int		crk_status;	/* return status */
+	u_short		crk_iparams;	/* # of input parameters */
+	u_short		crk_oparams;	/* # of output parameters */
+	u_int		crk_crid;	/* NB: only used by CIOCKEY2 (rw) */
+	struct crparam	crk_param[CRK_MAXPARAM];
+};
+#define CRK_ALGORITM_MIN	0
+#define CRK_MOD_EXP		0
+#define CRK_MOD_EXP_CRT		1
+#define CRK_DSA_SIGN		2
+#define CRK_DSA_VERIFY		3
+#define CRK_DH_COMPUTE_KEY	4
+#define CRK_ALGORITHM_MAX	4 /* Keep updated - see below */
+
+#define CRF_MOD_EXP		(1 << CRK_MOD_EXP)
+#define CRF_MOD_EXP_CRT		(1 << CRK_MOD_EXP_CRT)
+#define CRF_DSA_SIGN		(1 << CRK_DSA_SIGN)
+#define CRF_DSA_VERIFY		(1 << CRK_DSA_VERIFY)
+#define CRF_DH_COMPUTE_KEY	(1 << CRK_DH_COMPUTE_KEY)
+
+/*
+ * done against open of /dev/crypto, to get a cloned descriptor.
+ * Please use F_SETFD against the cloned descriptor.
+ */
+#define CRIOGET		_IOWR('c', 100, u_int32_t)
+#define CRIOASYMFEAT	CIOCASYMFEAT
+#define CRIOFINDDEV	CIOCFINDDEV
+
+/* the following are done against the cloned descriptor */
+#define CIOCGSESSION	_IOWR('c', 101, struct session_op)
+#define CIOCFSESSION	_IOW('c', 102, u_int32_t)
+#define CIOCCRYPT	_IOWR('c', 103, struct crypt_op)
+#define CIOCKEY		_IOWR('c', 104, struct crypt_kop)
+#define CIOCASYMFEAT	_IOR('c', 105, u_int32_t)
+#define CIOCGSESSION2	_IOWR('c', 106, struct session2_op)
+#define CIOCKEY2	_IOWR('c', 107, struct crypt_kop)
+#define CIOCFINDDEV	_IOWR('c', 108, struct crypt_find_op)
+
+struct cryptotstat {
+	struct timespec	acc;		/* total accumulated time */
+	struct timespec	min;		/* min time */
+	struct timespec	max;		/* max time */
+	u_int32_t	count;		/* number of observations */
+};
+
+struct cryptostats {
+	u_int32_t	cs_ops;		/* symmetric crypto ops submitted */
+	u_int32_t	cs_errs;	/* symmetric crypto ops that failed */
+	u_int32_t	cs_kops;	/* asymetric/key ops submitted */
+	u_int32_t	cs_kerrs;	/* asymetric/key ops that failed */
+	u_int32_t	cs_intrs;	/* crypto swi thread activations */
+	u_int32_t	cs_rets;	/* crypto return thread activations */
+	u_int32_t	cs_blocks;	/* symmetric op driver block */
+	u_int32_t	cs_kblocks;	/* symmetric op driver block */
+	/*
+	 * When CRYPTO_TIMING is defined at compile time and the
+	 * sysctl debug.crypto is set to 1, the crypto system will
+	 * accumulate statistics about how long it takes to process
+	 * crypto requests at various points during processing.
+	 */
+	struct cryptotstat cs_invoke;	/* crypto_dipsatch -> crypto_invoke */
+	struct cryptotstat cs_done;	/* crypto_invoke -> crypto_done */
+	struct cryptotstat cs_cb;	/* crypto_done -> callback */
+	struct cryptotstat cs_finis;	/* callback -> callback return */
+
+	u_int32_t	cs_drops;		/* crypto ops dropped due to congestion */
+};
+
+#ifdef __KERNEL__
+
+/* Standard initialization structure beginning */
+struct cryptoini {
+	int		cri_alg;	/* Algorithm to use */
+	int		cri_klen;	/* Key length, in bits */
+	int		cri_mlen;	/* Number of bytes we want from the
+					   entire hash. 0 means all. */
+	caddr_t		cri_key;	/* key to use */
+	u_int8_t	cri_iv[EALG_MAX_BLOCK_LEN];	/* IV to use */
+	struct cryptoini *cri_next;
+};
+
+/* Describe boundaries of a single crypto operation */
+struct cryptodesc {
+	int		crd_skip;	/* How many bytes to ignore from start */
+	int		crd_len;	/* How many bytes to process */
+	int		crd_inject;	/* Where to inject results, if applicable */
+	int		crd_flags;
+
+#define CRD_F_ENCRYPT		0x01	/* Set when doing encryption */
+#define CRD_F_IV_PRESENT	0x02	/* When encrypting, IV is already in
+					   place, so don't copy. */
+#define CRD_F_IV_EXPLICIT	0x04	/* IV explicitly provided */
+#define CRD_F_DSA_SHA_NEEDED	0x08	/* Compute SHA-1 of buffer for DSA */
+#define CRD_F_KEY_EXPLICIT	0x10	/* Key explicitly provided */
+#define CRD_F_COMP		0x0f    /* Set when doing compression */
+
+	struct cryptoini	CRD_INI; /* Initialization/context data */
+#define crd_iv		CRD_INI.cri_iv
+#define crd_key		CRD_INI.cri_key
+#define crd_alg		CRD_INI.cri_alg
+#define crd_klen	CRD_INI.cri_klen
+#define crd_mlen	CRD_INI.cri_mlen
+
+	struct cryptodesc *crd_next;
+};
+
+/* Structure describing complete operation */
+struct cryptop {
+	struct list_head crp_next;
+	wait_queue_head_t crp_waitq;
+
+	u_int64_t	crp_sid;	/* Session ID */
+	int		crp_ilen;	/* Input data total length */
+	int		crp_olen;	/* Result total length */
+
+	int		crp_etype;	/*
+					 * Error type (zero means no error).
+					 * All error codes except EAGAIN
+					 * indicate possible data corruption (as in,
+					 * the data have been touched). On all
+					 * errors, the crp_sid may have changed
+					 * (reset to a new one), so the caller
+					 * should always check and use the new
+					 * value on future requests.
+					 */
+	int		crp_flags;
+
+#define CRYPTO_F_SKBUF		0x0001	/* Input/output are skbuf chains */
+#define CRYPTO_F_IOV		0x0002	/* Input/output are uio */
+#define CRYPTO_F_REL		0x0004	/* Must return data in same place */
+#define CRYPTO_F_BATCH		0x0008	/* Batch op if possible */
+#define CRYPTO_F_CBIMM		0x0010	/* Do callback immediately */
+#define CRYPTO_F_DONE		0x0020	/* Operation completed */
+#define CRYPTO_F_CBIFSYNC	0x0040	/* Do CBIMM if op is synchronous */
+
+	caddr_t		crp_buf;	/* Data to be processed */
+	caddr_t		crp_opaque;	/* Opaque pointer, passed along */
+	struct cryptodesc *crp_desc;	/* Linked list of processing descriptors */
+
+	int (*crp_callback)(struct cryptop *); /* Callback function */
+};
+
+#define CRYPTO_BUF_CONTIG	0x0
+#define CRYPTO_BUF_IOV		0x1
+#define CRYPTO_BUF_SKBUF		0x2
+
+#define CRYPTO_OP_DECRYPT	0x0
+#define CRYPTO_OP_ENCRYPT	0x1
+
+/*
+ * Hints passed to process methods.
+ */
+#define CRYPTO_HINT_MORE	0x1	/* more ops coming shortly */
+
+struct cryptkop {
+	struct list_head krp_next;
+	wait_queue_head_t krp_waitq;
+
+	int		krp_flags;
+#define CRYPTO_KF_DONE		0x0001	/* Operation completed */
+#define CRYPTO_KF_CBIMM		0x0002	/* Do callback immediately */
+
+	u_int		krp_op;		/* ie. CRK_MOD_EXP or other */
+	u_int		krp_status;	/* return status */
+	u_short		krp_iparams;	/* # of input parameters */
+	u_short		krp_oparams;	/* # of output parameters */
+	u_int		krp_crid;	/* desired device, etc. */
+	u_int32_t	krp_hid;
+	struct crparam	krp_param[CRK_MAXPARAM];	/* kvm */
+	int		(*krp_callback)(struct cryptkop *);
+};
+
+#include <ocf-compat.h>
+
+/*
+ * Session ids are 64 bits.  The lower 32 bits contain a "local id" which
+ * is a driver-private session identifier.  The upper 32 bits contain a
+ * "hardware id" used by the core crypto code to identify the driver and
+ * a copy of the driver's capabilities that can be used by client code to
+ * optimize operation.
+ */
+#define CRYPTO_SESID2HID(_sid)	(((_sid) >> 32) & 0x00ffffff)
+#define CRYPTO_SESID2CAPS(_sid)	(((_sid) >> 32) & 0xff000000)
+#define CRYPTO_SESID2LID(_sid)	(((u_int32_t) (_sid)) & 0xffffffff)
+
+extern	int crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard);
+extern	int crypto_freesession(u_int64_t sid);
+#define CRYPTOCAP_F_HARDWARE	CRYPTO_FLAG_HARDWARE
+#define CRYPTOCAP_F_SOFTWARE	CRYPTO_FLAG_SOFTWARE
+#define CRYPTOCAP_F_SYNC	0x04000000	/* operates synchronously */
+extern	int32_t crypto_get_driverid(device_t dev, int flags);
+extern	int crypto_find_driver(const char *);
+extern	device_t crypto_find_device_byhid(int hid);
+extern	int crypto_getcaps(int hid);
+extern	int crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
+	    u_int32_t flags);
+extern	int crypto_kregister(u_int32_t, int, u_int32_t);
+extern	int crypto_unregister(u_int32_t driverid, int alg);
+extern	int crypto_unregister_all(u_int32_t driverid);
+extern	int crypto_dispatch(struct cryptop *crp);
+extern	int crypto_kdispatch(struct cryptkop *);
+#define CRYPTO_SYMQ	0x1
+#define CRYPTO_ASYMQ	0x2
+extern	int crypto_unblock(u_int32_t, int);
+extern	void crypto_done(struct cryptop *crp);
+extern	void crypto_kdone(struct cryptkop *);
+extern	int crypto_getfeat(int *);
+
+extern	void crypto_freereq(struct cryptop *crp);
+extern	struct cryptop *crypto_getreq(int num);
+
+extern  int crypto_usercrypto;      /* userland may do crypto requests */
+extern  int crypto_userasymcrypto;  /* userland may do asym crypto reqs */
+extern  int crypto_devallowsoft;    /* only use hardware crypto */
+
+/*
+ * random number support,  crypto_unregister_all will unregister
+ */
+extern int crypto_rregister(u_int32_t driverid,
+		int (*read_random)(void *arg, u_int32_t *buf, int len), void *arg);
+extern int crypto_runregister_all(u_int32_t driverid);
+
+/*
+ * Crypto-related utility routines used mainly by drivers.
+ *
+ * XXX these don't really belong here; but for now they're
+ *     kept apart from the rest of the system.
+ */
+struct uio;
+extern	void cuio_copydata(struct uio* uio, int off, int len, caddr_t cp);
+extern	void cuio_copyback(struct uio* uio, int off, int len, caddr_t cp);
+extern	struct iovec *cuio_getptr(struct uio *uio, int loc, int *off);
+
+extern	void crypto_copyback(int flags, caddr_t buf, int off, int size,
+	    caddr_t in);
+extern	void crypto_copydata(int flags, caddr_t buf, int off, int size,
+	    caddr_t out);
+extern	int crypto_apply(int flags, caddr_t buf, int off, int len,
+	    int (*f)(void *, void *, u_int), void *arg);
+
+#endif /* __KERNEL__ */
+#endif /* _CRYPTO_CRYPTO_H_ */
diff --git a/crypto/ocf/cryptosoft.c b/crypto/ocf/cryptosoft.c
new file mode 100755
index 0000000..1486889
--- /dev/null
+++ b/crypto/ocf/cryptosoft.c
@@ -0,0 +1,898 @@
+/*
+ * An OCF module that uses the linux kernel cryptoapi, based on the
+ * original cryptosoft for BSD by Angelos D. Keromytis (angelos@cis.upenn.edu)
+ * but is mostly unrecognisable,
+ *
+ * Written by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2004-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ * ---------------------------------------------------------------------------
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <asm/scatterlist.h>
+
+#include <cryptodev.h>
+#include <uio.h>
+
+struct {
+	softc_device_decl	sc_dev;
+} swcr_softc;
+
+#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
+
+/* Software session entry */
+
+#define SW_TYPE_CIPHER		0
+#define SW_TYPE_HMAC		1
+#define SW_TYPE_AUTH2		2
+#define SW_TYPE_HASH		3
+#define SW_TYPE_COMP		4
+#define SW_TYPE_BLKCIPHER	5
+
+struct swcr_data {
+	int					sw_type;
+	int					sw_alg;
+	struct crypto_tfm	*sw_tfm;
+	union {
+		struct {
+			char *sw_key;
+			int  sw_klen;
+			int  sw_mlen;
+		} hmac;
+		void *sw_comp_buf;
+	} u;
+	struct swcr_data	*sw_next;
+};
+
+#ifndef CRYPTO_TFM_MODE_CBC
+/*
+ * As of linux-2.6.21 this is no longer defined, and presumably no longer
+ * needed to be passed into the crypto core code.
+ */
+#define	CRYPTO_TFM_MODE_CBC	0
+#define	CRYPTO_TFM_MODE_ECB	0
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+	/*
+	 * Linux 2.6.19 introduced a new Crypto API, setup macro's to convert new
+	 * API into old API.
+	 */
+
+	/* Symmetric/Block Cipher */
+	struct blkcipher_desc
+	{
+		struct crypto_tfm *tfm;
+		void *info;
+	};
+	#define ecb(X)								#X
+	#define cbc(X)								#X
+	#define crypto_has_blkcipher(X, Y, Z)		crypto_alg_available(X, 0)
+	#define crypto_blkcipher_cast(X)			X
+	#define crypto_blkcipher_tfm(X)				X
+	#define crypto_alloc_blkcipher(X, Y, Z)		crypto_alloc_tfm(X, mode)
+	#define crypto_blkcipher_ivsize(X)			crypto_tfm_alg_ivsize(X)
+	#define crypto_blkcipher_blocksize(X)		crypto_tfm_alg_blocksize(X)
+	#define crypto_blkcipher_setkey(X, Y, Z)	crypto_cipher_setkey(X, Y, Z)
+	#define crypto_blkcipher_encrypt_iv(W, X, Y, Z)	\
+				crypto_cipher_encrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info))
+	#define crypto_blkcipher_decrypt_iv(W, X, Y, Z)	\
+				crypto_cipher_decrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info))
+
+	/* Hash/HMAC/Digest */
+	struct hash_desc
+	{
+		struct crypto_tfm *tfm;
+	};
+	#define hmac(X)							#X
+	#define crypto_has_hash(X, Y, Z)		crypto_alg_available(X, 0)
+	#define crypto_hash_cast(X)				X
+	#define crypto_hash_tfm(X)				X
+	#define crypto_alloc_hash(X, Y, Z)		crypto_alloc_tfm(X, mode)
+	#define crypto_hash_digestsize(X)		crypto_tfm_alg_digestsize(X)
+	#define crypto_hash_digest(W, X, Y, Z)	\
+				crypto_digest_digest((W)->tfm, X, sg_num, Z)
+
+	/* Asymmetric Cipher */
+	#define crypto_has_cipher(X, Y, Z)		crypto_alg_available(X, 0)
+
+	/* Compression */
+	#define crypto_has_comp(X, Y, Z)		crypto_alg_available(X, 0)
+	#define crypto_comp_tfm(X)				X
+	#define crypto_comp_cast(X)				X
+	#define crypto_alloc_comp(X, Y, Z)		crypto_alloc_tfm(X, mode)
+#else
+	#define ecb(X)	"ecb(" #X ")"
+	#define cbc(X)	"cbc(" #X ")"
+	#define hmac(X)	"hmac(" #X ")"
+#endif /* if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
+
+struct crypto_details
+{
+	char *alg_name;
+	int mode;
+	int sw_type;
+};
+
+/*
+ * This needs to be kept updated with CRYPTO_xxx list (cryptodev.h).
+ * If the Algorithm is not supported, then insert a {NULL, 0, 0} entry.
+ *
+ * IMPORTANT: The index to the array IS CRYPTO_xxx.
+ */
+static struct crypto_details crypto_details[CRYPTO_ALGORITHM_MAX + 1] = {
+	{ NULL,              0,                   0 },
+	/* CRYPTO_xxx index starts at 1 */
+	{ cbc(des),          CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
+	{ cbc(des3_ede),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
+	{ cbc(blowfish),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
+	{ cbc(cast5),        CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
+	{ cbc(skipjack),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
+	{ hmac(md5),         0,                   SW_TYPE_HMAC },
+	{ hmac(sha1),        0,                   SW_TYPE_HMAC },
+	{ hmac(ripemd160),   0,                   SW_TYPE_HMAC },
+	{ "md5-kpdk??",      0,                   SW_TYPE_HASH },
+	{ "sha1-kpdk??",     0,                   SW_TYPE_HASH },
+	{ cbc(aes),          CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
+	{ ecb(arc4),         CRYPTO_TFM_MODE_ECB, SW_TYPE_BLKCIPHER },
+	{ "md5",             0,                   SW_TYPE_HASH },
+	{ "sha1",            0,                   SW_TYPE_HASH },
+	{ hmac(digest_null), 0,                   SW_TYPE_HMAC },
+	{ cbc(cipher_null),  CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
+	{ "deflate",         0,                   SW_TYPE_COMP },
+	{ hmac(sha256),      0,                   SW_TYPE_HMAC },
+	{ hmac(sha384),      0,                   SW_TYPE_HMAC },
+	{ hmac(sha512),      0,                   SW_TYPE_HMAC },
+	{ cbc(camellia),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
+	{ "sha256",          0,                   SW_TYPE_HASH },
+	{ "sha384",          0,                   SW_TYPE_HASH },
+	{ "sha512",          0,                   SW_TYPE_HASH },
+	{ "ripemd160",       0,                   SW_TYPE_HASH },
+};
+
+int32_t swcr_id = -1;
+module_param(swcr_id, int, 0444);
+MODULE_PARM_DESC(swcr_id, "Read-Only OCF ID for cryptosoft driver");
+
+int swcr_fail_if_compression_grows = 1;
+module_param(swcr_fail_if_compression_grows, int, 0644);
+MODULE_PARM_DESC(swcr_fail_if_compression_grows,
+                "Treat compression that results in more data as a failure");
+
+static struct swcr_data **swcr_sessions = NULL;
+static u_int32_t swcr_sesnum = 0;
+
+static	int swcr_process(device_t, struct cryptop *, int);
+static	int swcr_newsession(device_t, u_int32_t *, struct cryptoini *);
+static	int swcr_freesession(device_t, u_int64_t);
+
+static device_method_t swcr_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,	swcr_newsession),
+	DEVMETHOD(cryptodev_freesession,swcr_freesession),
+	DEVMETHOD(cryptodev_process,	swcr_process),
+};
+
+#define debug swcr_debug
+int swcr_debug = 0;
+module_param(swcr_debug, int, 0644);
+MODULE_PARM_DESC(swcr_debug, "Enable debug");
+
+/*
+ * Generate a new software session.
+ */
+static int
+swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
+{
+	struct swcr_data **swd;
+	u_int32_t i;
+	int error;
+	char *algo;
+	int mode, sw_type;
+
+	dprintk("%s()\n", __FUNCTION__);
+	if (sid == NULL || cri == NULL) {
+		dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	if (swcr_sessions) {
+		for (i = 1; i < swcr_sesnum; i++)
+			if (swcr_sessions[i] == NULL)
+				break;
+	} else
+		i = 1;		/* NB: to silence compiler warning */
+
+	if (swcr_sessions == NULL || i == swcr_sesnum) {
+		if (swcr_sessions == NULL) {
+			i = 1; /* We leave swcr_sessions[0] empty */
+			swcr_sesnum = CRYPTO_SW_SESSIONS;
+		} else
+			swcr_sesnum *= 2;
+
+		swd = kmalloc(swcr_sesnum * sizeof(struct swcr_data *), SLAB_ATOMIC);
+		if (swd == NULL) {
+			/* Reset session number */
+			if (swcr_sesnum == CRYPTO_SW_SESSIONS)
+				swcr_sesnum = 0;
+			else
+				swcr_sesnum /= 2;
+			dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+			return ENOBUFS;
+		}
+		memset(swd, 0, swcr_sesnum * sizeof(struct swcr_data *));
+
+		/* Copy existing sessions */
+		if (swcr_sessions) {
+			memcpy(swd, swcr_sessions,
+			    (swcr_sesnum / 2) * sizeof(struct swcr_data *));
+			kfree(swcr_sessions);
+		}
+
+		swcr_sessions = swd;
+	}
+
+	swd = &swcr_sessions[i];
+	*sid = i;
+
+	while (cri) {
+		*swd = (struct swcr_data *) kmalloc(sizeof(struct swcr_data),
+				SLAB_ATOMIC);
+		if (*swd == NULL) {
+			swcr_freesession(NULL, i);
+			dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+			return ENOBUFS;
+		}
+		memset(*swd, 0, sizeof(struct swcr_data));
+
+		if (cri->cri_alg > CRYPTO_ALGORITHM_MAX) {
+			printk("cryptosoft: Unknown algorithm 0x%x\n", cri->cri_alg);
+			swcr_freesession(NULL, i);
+			return EINVAL;
+		}
+
+		algo = crypto_details[cri->cri_alg].alg_name;
+		if (!algo || !*algo) {
+			printk("cryptosoft: Unsupported algorithm 0x%x\n", cri->cri_alg);
+			swcr_freesession(NULL, i);
+			return EINVAL;
+		}
+
+		mode = crypto_details[cri->cri_alg].mode;
+		sw_type = crypto_details[cri->cri_alg].sw_type;
+
+		/* Algorithm specific configuration */
+		switch (cri->cri_alg) {
+		case CRYPTO_NULL_CBC:
+			cri->cri_klen = 0; /* make it work with crypto API */
+			break;
+		default:
+			break;
+		}
+
+		if (sw_type == SW_TYPE_BLKCIPHER) {
+			dprintk("%s crypto_alloc_blkcipher(%s, 0x%x)\n", __FUNCTION__,
+					algo, mode);
+
+			(*swd)->sw_tfm = crypto_blkcipher_tfm(
+								crypto_alloc_blkcipher(algo, 0,
+									CRYPTO_ALG_ASYNC));
+			if (!(*swd)->sw_tfm) {
+				dprintk("cryptosoft: crypto_alloc_blkcipher failed(%s,0x%x)\n",
+						algo,mode);
+				swcr_freesession(NULL, i);
+				return EINVAL;
+			}
+
+			if (debug) {
+				dprintk("%s key:cri->cri_klen=%d,(cri->cri_klen + 7)/8=%d",
+						__FUNCTION__,cri->cri_klen,(cri->cri_klen + 7)/8);
+				for (i = 0; i < (cri->cri_klen + 7) / 8; i++)
+				{
+					dprintk("%s0x%x", (i % 8) ? " " : "\n    ",cri->cri_key[i]);
+				}
+				dprintk("\n");
+			}
+			error = crypto_blkcipher_setkey(
+						crypto_blkcipher_cast((*swd)->sw_tfm), cri->cri_key,
+							(cri->cri_klen + 7) / 8);
+			if (error) {
+				printk("cryptosoft: setkey failed %d (crt_flags=0x%x)\n", error,
+						(*swd)->sw_tfm->crt_flags);
+				swcr_freesession(NULL, i);
+				return error;
+			}
+		} else if (sw_type == SW_TYPE_HMAC || sw_type == SW_TYPE_HASH) {
+			dprintk("%s crypto_alloc_hash(%s, 0x%x)\n", __FUNCTION__,
+					algo, mode);
+
+			(*swd)->sw_tfm = crypto_hash_tfm(
+								crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC));
+
+			if (!(*swd)->sw_tfm) {
+				dprintk("cryptosoft: crypto_alloc_hash failed(%s,0x%x)\n",
+						algo, mode);
+				swcr_freesession(NULL, i);
+				return EINVAL;
+			}
+
+			(*swd)->u.hmac.sw_klen = (cri->cri_klen + 7) / 8;
+			(*swd)->u.hmac.sw_key = (char *)kmalloc((*swd)->u.hmac.sw_klen,
+				SLAB_ATOMIC);
+			if ((*swd)->u.hmac.sw_key == NULL) {
+				swcr_freesession(NULL, i);
+				dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+				return ENOBUFS;
+			}
+			memcpy((*swd)->u.hmac.sw_key, cri->cri_key, (*swd)->u.hmac.sw_klen);
+			if (cri->cri_mlen) {
+				(*swd)->u.hmac.sw_mlen = cri->cri_mlen;
+			} else {
+				(*swd)->u.hmac.sw_mlen =
+						crypto_hash_digestsize(
+								crypto_hash_cast((*swd)->sw_tfm));
+			}
+		} else if (sw_type == SW_TYPE_COMP) {
+			(*swd)->sw_tfm = crypto_comp_tfm(
+					crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC));
+			if (!(*swd)->sw_tfm) {
+				dprintk("cryptosoft: crypto_alloc_comp failed(%s,0x%x)\n",
+						algo, mode);
+				swcr_freesession(NULL, i);
+				return EINVAL;
+			}
+			(*swd)->u.sw_comp_buf = kmalloc(CRYPTO_MAX_DATA_LEN, SLAB_ATOMIC);
+			if ((*swd)->u.sw_comp_buf == NULL) {
+				swcr_freesession(NULL, i);
+				dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+				return ENOBUFS;
+			}
+		} else {
+			printk("cryptosoft: Unhandled sw_type %d\n", sw_type);
+			swcr_freesession(NULL, i);
+			return EINVAL;
+		}
+
+		(*swd)->sw_alg = cri->cri_alg;
+		(*swd)->sw_type = sw_type;
+
+		cri = cri->cri_next;
+		swd = &((*swd)->sw_next);
+	}
+	return 0;
+}
+
+/*
+ * Free a session.
+ */
+static int
+swcr_freesession(device_t dev, u_int64_t tid)
+{
+	struct swcr_data *swd;
+	u_int32_t sid = CRYPTO_SESID2LID(tid);
+
+	dprintk("%s()\n", __FUNCTION__);
+	if (sid > swcr_sesnum || swcr_sessions == NULL ||
+			swcr_sessions[sid] == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return(EINVAL);
+	}
+
+	/* Silently accept and return */
+	if (sid == 0)
+		return(0);
+
+	while ((swd = swcr_sessions[sid]) != NULL) {
+		swcr_sessions[sid] = swd->sw_next;
+		if (swd->sw_tfm)
+			crypto_free_tfm(swd->sw_tfm);
+		if (swd->sw_type == SW_TYPE_COMP) {
+			if (swd->u.sw_comp_buf)
+				kfree(swd->u.sw_comp_buf);
+		} else {
+			if (swd->u.hmac.sw_key)
+				kfree(swd->u.hmac.sw_key);
+		}
+		kfree(swd);
+	}
+	return 0;
+}
+
+/*
+ * Process a software request.
+ */
+static int
+swcr_process(device_t dev, struct cryptop *crp, int hint)
+{
+	struct cryptodesc *crd;
+	struct swcr_data *sw;
+	u_int32_t lid;
+#define SCATTERLIST_MAX 16
+	struct scatterlist sg[SCATTERLIST_MAX];
+	int sg_num, sg_len, skip;
+	struct sk_buff *skb = NULL;
+	struct uio *uiop = NULL;
+
+	dprintk("%s()\n", __FUNCTION__);
+	/* Sanity check */
+	if (crp == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	crp->crp_etype = 0;
+
+	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		crp->crp_etype = EINVAL;
+		goto done;
+	}
+
+	lid = crp->crp_sid & 0xffffffff;
+	if (lid >= swcr_sesnum || lid == 0 || swcr_sessions == NULL ||
+			swcr_sessions[lid] == NULL) {
+		crp->crp_etype = ENOENT;
+		dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
+		goto done;
+	}
+
+	/*
+	 * do some error checking outside of the loop for SKB and IOV processing
+	 * this leaves us with valid skb or uiop pointers for later
+	 */
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		skb = (struct sk_buff *) crp->crp_buf;
+		if (skb_shinfo(skb)->nr_frags >= SCATTERLIST_MAX) {
+			printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__, __LINE__,
+					skb_shinfo(skb)->nr_frags);
+			goto done;
+		}
+	} else if (crp->crp_flags & CRYPTO_F_IOV) {
+		uiop = (struct uio *) crp->crp_buf;
+		if (uiop->uio_iovcnt > SCATTERLIST_MAX) {
+			printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__, __LINE__,
+					uiop->uio_iovcnt);
+			goto done;
+		}
+	}
+
+	/* Go through crypto descriptors, processing as we go */
+	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+		/*
+		 * Find the crypto context.
+		 *
+		 * XXX Note that the logic here prevents us from having
+		 * XXX the same algorithm multiple times in a session
+		 * XXX (or rather, we can but it won't give us the right
+		 * XXX results). To do that, we'd need some way of differentiating
+		 * XXX between the various instances of an algorithm (so we can
+		 * XXX locate the correct crypto context).
+		 */
+		for (sw = swcr_sessions[lid]; sw && sw->sw_alg != crd->crd_alg;
+				sw = sw->sw_next)
+			;
+
+		/* No such context ? */
+		if (sw == NULL) {
+			crp->crp_etype = EINVAL;
+			dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+			goto done;
+		}
+
+		skip = crd->crd_skip;
+
+		/*
+		 * setup the SG list skip from the start of the buffer
+		 */
+		memset(sg, 0, sizeof(sg));
+		if (crp->crp_flags & CRYPTO_F_SKBUF) {
+			int i, len;
+
+			sg_num = 0;
+			sg_len = 0;
+
+			if (skip < skb_headlen(skb)) {
+				len = skb_headlen(skb) - skip;
+				if (len + sg_len > crd->crd_len)
+					len = crd->crd_len - sg_len;
+				sg_set_page(&sg[sg_num],
+					virt_to_page(skb->data + skip), len,
+					offset_in_page(skb->data + skip));
+				sg_len += len;
+				sg_num++;
+				skip = 0;
+			} else
+				skip -= skb_headlen(skb);
+
+			for (i = 0; sg_len < crd->crd_len &&
+						i < skb_shinfo(skb)->nr_frags &&
+						sg_num < SCATTERLIST_MAX; i++) {
+				if (skip < skb_shinfo(skb)->frags[i].size) {
+					len = skb_shinfo(skb)->frags[i].size - skip;
+					if (len + sg_len > crd->crd_len)
+						len = crd->crd_len - sg_len;
+					sg_set_page(&sg[sg_num],
+						skb_shinfo(skb)->frags[i].page,
+						len,
+						skb_shinfo(skb)->frags[i].page_offset + skip);
+					sg_len += len;
+					sg_num++;
+					skip = 0;
+				} else
+					skip -= skb_shinfo(skb)->frags[i].size;
+			}
+		} else if (crp->crp_flags & CRYPTO_F_IOV) {
+			int len;
+
+			sg_len = 0;
+			for (sg_num = 0; sg_len <= crd->crd_len &&
+					sg_num < uiop->uio_iovcnt &&
+					sg_num < SCATTERLIST_MAX; sg_num++) {
+				if (skip <= uiop->uio_iov[sg_num].iov_len) {
+					len = uiop->uio_iov[sg_num].iov_len - skip;
+					if (len + sg_len > crd->crd_len)
+						len = crd->crd_len - sg_len;
+					sg_set_page(&sg[sg_num],
+						virt_to_page(uiop->uio_iov[sg_num].iov_base+skip),
+						len,
+						offset_in_page(uiop->uio_iov[sg_num].iov_base+skip));
+					sg_len += len;
+					skip = 0;
+				} else 
+					skip -= uiop->uio_iov[sg_num].iov_len;
+			}
+		} else {
+			sg_len = (crp->crp_ilen - skip);
+			if (sg_len > crd->crd_len)
+				sg_len = crd->crd_len;
+			sg_set_page(&sg[0], virt_to_page(crp->crp_buf + skip),
+				sg_len, offset_in_page(crp->crp_buf + skip));
+			sg_num = 1;
+		}
+
+
+		switch (sw->sw_type) {
+		case SW_TYPE_BLKCIPHER: {
+			unsigned char iv[EALG_MAX_BLOCK_LEN];
+			unsigned char *ivp = iv;
+			int ivsize = 
+				crypto_blkcipher_ivsize(crypto_blkcipher_cast(sw->sw_tfm));
+			struct blkcipher_desc desc;
+
+			if (sg_len < crypto_blkcipher_blocksize(
+					crypto_blkcipher_cast(sw->sw_tfm))) {
+				crp->crp_etype = EINVAL;
+				dprintk("%s,%d: EINVAL len %d < %d\n", __FILE__, __LINE__,
+						sg_len, crypto_blkcipher_blocksize(
+							crypto_blkcipher_cast(sw->sw_tfm)));
+				goto done;
+			}
+
+			if (ivsize > sizeof(iv)) {
+				crp->crp_etype = EINVAL;
+				dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+				goto done;
+			}
+
+			if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
+				int i, error;
+
+				if (debug) {
+					dprintk("%s key:", __FUNCTION__);
+					for (i = 0; i < (crd->crd_klen + 7) / 8; i++)
+						dprintk("%s0x%x", (i % 8) ? " " : "\n    ",
+								crd->crd_key[i]);
+					dprintk("\n");
+				}
+				error = crypto_blkcipher_setkey(
+							crypto_blkcipher_cast(sw->sw_tfm), crd->crd_key,
+							(crd->crd_klen + 7) / 8);
+				if (error) {
+					dprintk("cryptosoft: setkey failed %d (crt_flags=0x%x)\n",
+							error, sw->sw_tfm->crt_flags);
+					crp->crp_etype = -error;
+				}
+			}
+
+			memset(&desc, 0, sizeof(desc));
+			desc.tfm = crypto_blkcipher_cast(sw->sw_tfm);
+
+			if (crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
+
+				if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
+					ivp = crd->crd_iv;
+				} else {
+					get_random_bytes(ivp, ivsize);
+				}
+				/*
+				 * do we have to copy the IV back to the buffer ?
+				 */
+				if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
+					crypto_copyback(crp->crp_flags, crp->crp_buf,
+							crd->crd_inject, ivsize, (caddr_t)ivp);
+				}
+				desc.info = ivp;
+				crypto_blkcipher_encrypt_iv(&desc, sg, sg, sg_len);
+
+			} else { /*decrypt */
+
+				if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
+					ivp = crd->crd_iv;
+				} else {
+					crypto_copydata(crp->crp_flags, crp->crp_buf,
+							crd->crd_inject, ivsize, (caddr_t)ivp);
+				}
+				desc.info = ivp;
+				crypto_blkcipher_decrypt_iv(&desc, sg, sg, sg_len);
+			}
+			} break;
+		case SW_TYPE_HMAC:
+		case SW_TYPE_HASH:
+			{
+			char result[HASH_MAX_LEN];
+			struct hash_desc desc;
+
+			/* check we have room for the result */
+			if (crp->crp_ilen - crd->crd_inject < sw->u.hmac.sw_mlen) {
+				dprintk(
+			"cryptosoft: EINVAL crp_ilen=%d, len=%d, inject=%d digestsize=%d\n",
+						crp->crp_ilen, crd->crd_skip + sg_len, crd->crd_inject,
+						sw->u.hmac.sw_mlen);
+				crp->crp_etype = EINVAL;
+				goto done;
+			}
+
+			memset(&desc, 0, sizeof(desc));
+			desc.tfm = crypto_hash_cast(sw->sw_tfm);
+
+			memset(result, 0, sizeof(result));
+
+			if (sw->sw_type == SW_TYPE_HMAC) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+				crypto_hmac(sw->sw_tfm, sw->u.hmac.sw_key, &sw->u.hmac.sw_klen,
+						sg, sg_num, result);
+#else
+				crypto_hash_setkey(desc.tfm, sw->u.hmac.sw_key,
+						sw->u.hmac.sw_klen);
+				crypto_hash_digest(&desc, sg, sg_len, result);
+#endif /* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
+				
+			} else { /* SW_TYPE_HASH */
+				crypto_hash_digest(&desc, sg, sg_len, result);
+			}
+
+			crypto_copyback(crp->crp_flags, crp->crp_buf,
+					crd->crd_inject, sw->u.hmac.sw_mlen, result);
+			}
+			break;
+
+		case SW_TYPE_COMP: {
+			void *ibuf = NULL;
+			void *obuf = sw->u.sw_comp_buf;
+			int ilen = sg_len, olen = CRYPTO_MAX_DATA_LEN;
+			int ret = 0;
+
+			/*
+			 * we need to use an additional copy if there is more than one
+			 * input chunk since the kernel comp routines do not handle
+			 * SG yet.  Otherwise we just use the input buffer as is.
+			 * Rather than allocate another buffer we just split the tmp
+			 * buffer we already have.
+			 * Perhaps we should just use zlib directly ?
+			 */
+			if (sg_num > 1) {
+				int blk;
+
+				ibuf = obuf;
+				for (blk = 0; blk < sg_num; blk++) {
+					memcpy(obuf, sg_virt(&sg[blk]),
+							sg[blk].length);
+					obuf += sg[blk].length;
+				}
+				olen -= sg_len;
+			} else
+				ibuf = sg_virt(&sg[0]);
+
+			if (crd->crd_flags & CRD_F_ENCRYPT) { /* compress */
+				ret = crypto_comp_compress(crypto_comp_cast(sw->sw_tfm),
+						ibuf, ilen, obuf, &olen);
+				if (!ret && olen > crd->crd_len) {
+					dprintk("cryptosoft: ERANGE compress %d into %d\n",
+							crd->crd_len, olen);
+					if (swcr_fail_if_compression_grows)
+						ret = ERANGE;
+				}
+			} else { /* decompress */
+				ret = crypto_comp_decompress(crypto_comp_cast(sw->sw_tfm),
+						ibuf, ilen, obuf, &olen);
+				if (!ret && (olen + crd->crd_inject) > crp->crp_olen) {
+					dprintk("cryptosoft: ETOOSMALL decompress %d into %d, "
+							"space for %d,at offset %d\n",
+							crd->crd_len, olen, crp->crp_olen, crd->crd_inject);
+					ret = ETOOSMALL;
+				}
+			}
+			if (ret)
+				dprintk("%s,%d: ret = %d\n", __FILE__, __LINE__, ret);
+
+			/*
+			 * on success copy result back,
+			 * linux crpyto API returns -errno,  we need to fix that
+			 */
+			crp->crp_etype = ret < 0 ? -ret : ret;
+			if (ret == 0) {
+				/* copy back the result and return it's size */
+				crypto_copyback(crp->crp_flags, crp->crp_buf,
+						crd->crd_inject, olen, obuf);
+				crp->crp_olen = olen;
+			}
+
+
+			} break;
+
+		default:
+			/* Unknown/unsupported algorithm */
+			dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+			crp->crp_etype = EINVAL;
+			goto done;
+		}
+	}
+
+done:
+	crypto_done(crp);
+	return 0;
+}
+
+static int
+cryptosoft_init(void)
+{
+	int i, sw_type, mode;
+	char *algo;
+
+	dprintk("%s(%p)\n", __FUNCTION__, cryptosoft_init);
+
+	softc_device_init(&swcr_softc, "cryptosoft", 0, swcr_methods);
+
+	swcr_id = crypto_get_driverid(softc_get_device(&swcr_softc),
+			CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
+	if (swcr_id < 0) {
+		printk("Software crypto device cannot initialize!");
+		return -ENODEV;
+	}
+
+#define	REGISTER(alg) \
+		crypto_register(swcr_id, alg, 0,0);
+
+	for (i = CRYPTO_ALGORITHM_MIN; i <= CRYPTO_ALGORITHM_MAX; ++i)
+	{
+		
+		algo = crypto_details[i].alg_name;
+		if (!algo || !*algo)
+		{
+			dprintk("%s:Algorithm %d not supported\n", __FUNCTION__, i);
+			continue;
+		}
+
+		mode = crypto_details[i].mode;
+		sw_type = crypto_details[i].sw_type;
+
+		switch (sw_type)
+		{
+			case SW_TYPE_CIPHER:
+				if (crypto_has_cipher(algo, 0, CRYPTO_ALG_ASYNC))
+				{
+					REGISTER(i);
+				}
+				else
+				{
+					dprintk("%s:CIPHER algorithm %d:'%s' not supported\n",
+								__FUNCTION__, i, algo);
+				}
+				break;
+			case SW_TYPE_HMAC:
+				if (crypto_has_hash(algo, 0, CRYPTO_ALG_ASYNC))
+				{
+					REGISTER(i);
+				}
+				else
+				{
+					dprintk("%s:HMAC algorithm %d:'%s' not supported\n",
+								__FUNCTION__, i, algo);
+				}
+				break;
+			case SW_TYPE_HASH:
+				if (crypto_has_hash(algo, 0, CRYPTO_ALG_ASYNC))
+				{
+					REGISTER(i);
+				}
+				else
+				{
+					dprintk("%s:HASH algorithm %d:'%s' not supported\n",
+								__FUNCTION__, i, algo);
+				}
+				break;
+			case SW_TYPE_COMP:
+				if (crypto_has_comp(algo, 0, CRYPTO_ALG_ASYNC))
+				{
+					REGISTER(i);
+				}
+				else
+				{
+					dprintk("%s:COMP algorithm %d:'%s' not supported\n",
+								__FUNCTION__, i, algo);
+				}
+				break;
+			case SW_TYPE_BLKCIPHER:
+				if (crypto_has_blkcipher(algo, 0, CRYPTO_ALG_ASYNC))
+				{
+					REGISTER(i);
+				}
+				else
+				{
+					dprintk("%s:BLKCIPHER algorithm %d:'%s' not supported\n",
+								__FUNCTION__, i, algo);
+				}
+				break;
+			default:
+				dprintk(
+				"%s:Algorithm Type %d not supported (algorithm %d:'%s')\n",
+					__FUNCTION__, sw_type, i, algo);
+				break;
+		}
+	}
+
+	return(0);
+}
+
+static void
+cryptosoft_exit(void)
+{
+	dprintk("%s()\n", __FUNCTION__);
+	crypto_unregister_all(swcr_id);
+	swcr_id = -1;
+}
+
+module_init(cryptosoft_init);
+module_exit(cryptosoft_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_DESCRIPTION("Cryptosoft (OCF module for kernel crypto)");
diff --git a/crypto/ocf/ep80579/Makefile b/crypto/ocf/ep80579/Makefile
new file mode 100755
index 0000000..19ff6eb
--- /dev/null
+++ b/crypto/ocf/ep80579/Makefile
@@ -0,0 +1,107 @@
+#########################################################################
+#
+#  Targets supported
+#  all     - builds everything and installs
+#  install - identical to all
+#  depend  - build dependencies
+#  clean   - clears derived objects except the .depend files
+#  distclean- clears all derived objects and the .depend file
+#  
+# @par
+# This file is provided under a dual BSD/GPLv2 license.  When using or 
+#   redistributing this file, you may do so under either license.
+# 
+#   GPL LICENSE SUMMARY
+# 
+#   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+# 
+#   This program is free software; you can redistribute it and/or modify 
+#   it under the terms of version 2 of the GNU General Public License as
+#   published by the Free Software Foundation.
+# 
+#   This program is distributed in the hope that it will be useful, but 
+#   WITHOUT ANY WARRANTY; without even the implied warranty of 
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#   General Public License for more details.
+# 
+#   You should have received a copy of the GNU General Public License 
+#   along with this program; if not, write to the Free Software 
+#   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+#   The full GNU General Public License is included in this distribution 
+#   in the file called LICENSE.GPL.
+# 
+#   Contact Information:
+#   Intel Corporation
+# 
+#   BSD LICENSE 
+# 
+#   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+#   All rights reserved.
+# 
+#   Redistribution and use in source and binary forms, with or without 
+#   modification, are permitted provided that the following conditions 
+#   are met:
+# 
+#     * Redistributions of source code must retain the above copyright 
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright 
+#       notice, this list of conditions and the following disclaimer in 
+#       the documentation and/or other materials provided with the 
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its 
+#       contributors may be used to endorse or promote products derived 
+#       from this software without specific prior written permission.
+# 
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# 
+# 
+#  version: Security.L.1.0.130
+############################################################################
+
+
+####################Common variables and definitions########################
+
+# Ensure The ENV_DIR environmental var is defined.
+ifndef ICP_ENV_DIR
+$(error ICP_ENV_DIR is undefined. Please set the path to your environment makefile \
+        "-> setenv ICP_ENV_DIR <path>")
+endif
+
+#Add your project environment Makefile
+include $(ICP_ENV_DIR)/environment.mk
+
+#include the makefile with all the default and common Make variable definitions
+include $(ICP_BUILDSYSTEM_PATH)/build_files/common.mk
+
+#Add the name for the executable, Library or Module output definitions
+OUTPUT_NAME= icp_ocf
+
+# List of Source Files to be compiled 
+SOURCES= icp_common.c icp_sym.c icp_asym.c
+
+#common includes between all supported OSes
+INCLUDES= -I $(ICP_API_DIR) -I$(ICP_LAC_API) \
+-I$(ICP_OCF_SRC_DIR)
+
+# The location of the os level makefile needs to be changed.
+include $(ICP_ENV_DIR)/$(ICP_OS)_$(ICP_OS_LEVEL).mk
+
+# On the line directly below list the outputs you wish to build for,
+# e.g "lib_static lib_shared exe module" as show below
+install: module
+
+###################Include rules makefiles########################
+include $(ICP_BUILDSYSTEM_PATH)/build_files/rules.mk
+###################End of Rules inclusion#########################
+
+
diff --git a/crypto/ocf/ep80579/environment.mk b/crypto/ocf/ep80579/environment.mk
new file mode 100755
index 0000000..a674b45
--- /dev/null
+++ b/crypto/ocf/ep80579/environment.mk
@@ -0,0 +1,75 @@
+ ###########################################################################
+ #
+# This file is provided under a dual BSD/GPLv2 license.  When using or 
+#   redistributing this file, you may do so under either license.
+# 
+#   GPL LICENSE SUMMARY
+# 
+#   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+# 
+#   This program is free software; you can redistribute it and/or modify 
+#   it under the terms of version 2 of the GNU General Public License as
+#   published by the Free Software Foundation.
+# 
+#   This program is distributed in the hope that it will be useful, but 
+#   WITHOUT ANY WARRANTY; without even the implied warranty of 
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#   General Public License for more details.
+# 
+#   You should have received a copy of the GNU General Public License 
+#   along with this program; if not, write to the Free Software 
+#   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+#   The full GNU General Public License is included in this distribution 
+#   in the file called LICENSE.GPL.
+# 
+#   Contact Information:
+#   Intel Corporation
+# 
+#   BSD LICENSE 
+# 
+#   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+#   All rights reserved.
+# 
+#   Redistribution and use in source and binary forms, with or without 
+#   modification, are permitted provided that the following conditions 
+#   are met:
+# 
+#     * Redistributions of source code must retain the above copyright 
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright 
+#       notice, this list of conditions and the following disclaimer in 
+#       the documentation and/or other materials provided with the 
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its 
+#       contributors may be used to endorse or promote products derived 
+#       from this software without specific prior written permission.
+# 
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# 
+# 
+#  version: Security.L.1.0.130
+ #
+ ###########################################################################
+
+
+ICP_LAC_API=$(ICP_ROOT)/Acceleration/include/lac
+ICP_BTR_API=$(ICP_ROOT)/Acceleration/include/btr
+ICP_API_DIR=$(ICP_ROOT)/Acceleration/include
+ICP_OCF_SHIM_DIR?=$(KERNEL_SOURCE_ROOT)/crypto/ocf/
+
+ICP_OS_LEVEL?=kernel_space
+
+ICP_OS?=linux_2.6
+
+ICP_CORE?=ia
+
diff --git a/crypto/ocf/ep80579/icp_asym.c b/crypto/ocf/ep80579/icp_asym.c
new file mode 100755
index 0000000..1a9bd28
--- /dev/null
+++ b/crypto/ocf/ep80579/icp_asym.c
@@ -0,0 +1,1375 @@
+/***************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or 
+ *   redistributing this file, you may do so under either license.
+ * 
+ *   GPL LICENSE SUMMARY
+ * 
+ *   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+ * 
+ *   This program is free software; you can redistribute it and/or modify 
+ *   it under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ * 
+ *   This program is distributed in the hope that it will be useful, but 
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+ *   General Public License for more details.
+ * 
+ *   You should have received a copy of the GNU General Public License 
+ *   along with this program; if not, write to the Free Software 
+ *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *   The full GNU General Public License is included in this distribution 
+ *   in the file called LICENSE.GPL.
+ * 
+ *   Contact Information:
+ *   Intel Corporation
+ * 
+ *   BSD LICENSE 
+ * 
+ *   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without 
+ *   modification, are permitted provided that the following conditions 
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright 
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright 
+ *       notice, this list of conditions and the following disclaimer in 
+ *       the documentation and/or other materials provided with the 
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its 
+ *       contributors may be used to endorse or promote products derived 
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ *  version: Security.L.1.0.130
+ *
+ ***************************************************************************/
+
+#include "icp_ocf.h"
+
+/*The following define values (containing the word 'INDEX') are used to find
+the index of each input buffer of the crypto_kop struct (see OCF cryptodev.h).
+These values were found through analysis of the OCF OpenSSL patch. If the
+calling program uses different input buffer positions, these defines will have
+to be changed.*/
+
+/*DIFFIE HELLMAN buffer index values*/
+#define ICP_DH_KRP_PARAM_PRIME_INDEX				(0)
+#define ICP_DH_KRP_PARAM_BASE_INDEX				(1)
+#define ICP_DH_KRP_PARAM_PRIVATE_VALUE_INDEX			(2)
+#define ICP_DH_KRP_PARAM_RESULT_INDEX				(3)
+
+/*MOD EXP buffer index values*/
+#define ICP_MOD_EXP_KRP_PARAM_BASE_INDEX			(0)
+#define ICP_MOD_EXP_KRP_PARAM_EXPONENT_INDEX			(1)
+#define ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX			(2)
+#define ICP_MOD_EXP_KRP_PARAM_RESULT_INDEX			(3)
+
+#define SINGLE_BYTE_VALUE					(4)
+
+/*MOD EXP CRT buffer index values*/
+#define ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_P_INDEX			(0)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_Q_INDEX			(1)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_I_INDEX			(2)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DP_INDEX		(3)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DQ_INDEX		(4)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_COEFF_QINV_INDEX		(5)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_RESULT_INDEX			(6)
+
+/*DSA sign buffer index values*/
+#define ICP_DSA_SIGN_KRP_PARAM_DGST_INDEX			(0)
+#define ICP_DSA_SIGN_KRP_PARAM_PRIME_P_INDEX			(1)
+#define ICP_DSA_SIGN_KRP_PARAM_PRIME_Q_INDEX			(2)
+#define ICP_DSA_SIGN_KRP_PARAM_G_INDEX				(3)
+#define ICP_DSA_SIGN_KRP_PARAM_X_INDEX				(4)
+#define ICP_DSA_SIGN_KRP_PARAM_R_RESULT_INDEX			(5)
+#define ICP_DSA_SIGN_KRP_PARAM_S_RESULT_INDEX			(6)
+
+/*DSA verify buffer index values*/
+#define ICP_DSA_VERIFY_KRP_PARAM_DGST_INDEX			(0)
+#define ICP_DSA_VERIFY_KRP_PARAM_PRIME_P_INDEX			(1)
+#define ICP_DSA_VERIFY_KRP_PARAM_PRIME_Q_INDEX			(2)
+#define ICP_DSA_VERIFY_KRP_PARAM_G_INDEX			(3)
+#define ICP_DSA_VERIFY_KRP_PARAM_PUBKEY_INDEX			(4)
+#define ICP_DSA_VERIFY_KRP_PARAM_SIG_R_INDEX			(5)
+#define ICP_DSA_VERIFY_KRP_PARAM_SIG_S_INDEX			(6)
+
+/*DSA sign prime Q vs random number K size check values*/
+#define DONT_RUN_LESS_THAN_CHECK				(0)
+#define FAIL_A_IS_GREATER_THAN_B				(1)
+#define FAIL_A_IS_EQUAL_TO_B					(1)
+#define SUCCESS_A_IS_LESS_THAN_B				(0)
+#define DSA_SIGN_RAND_GEN_VAL_CHECK_MAX_ITERATIONS		(500)
+
+/* We need to set a cryptokp success value just in case it is set or allocated
+   and not set to zero outside of this module */
+#define CRYPTO_OP_SUCCESS					(0)
+
+static int icp_ocfDrvDHComputeKey(struct cryptkop *krp);
+
+static int icp_ocfDrvModExp(struct cryptkop *krp);
+
+static int icp_ocfDrvModExpCRT(struct cryptkop *krp);
+
+static int
+icp_ocfDrvCheckALessThanB(CpaFlatBuffer * pK, CpaFlatBuffer * pQ, int *doCheck);
+
+static int icp_ocfDrvDsaSign(struct cryptkop *krp);
+
+static int icp_ocfDrvDsaVerify(struct cryptkop *krp);
+
+static void
+icp_ocfDrvDhP1CallBack(void *callbackTag,
+		       CpaStatus status,
+		       void *pOpData, CpaFlatBuffer * pLocalOctetStringPV);
+
+static void
+icp_ocfDrvModExpCallBack(void *callbackTag,
+			 CpaStatus status,
+			 void *pOpData, CpaFlatBuffer * pResult);
+
+static void
+icp_ocfDrvModExpCRTCallBack(void *callbackTag,
+			    CpaStatus status,
+			    void *pOpData, CpaFlatBuffer * pOutputData);
+
+static void
+icp_ocfDrvDsaVerifyCallBack(void *callbackTag,
+			    CpaStatus status,
+			    void *pOpData, CpaBoolean verifyStatus);
+
+static void
+icp_ocfDrvDsaRSSignCallBack(void *callbackTag,
+			    CpaStatus status,
+			    void *pOpData,
+			    CpaBoolean protocolStatus,
+			    CpaFlatBuffer * pR, CpaFlatBuffer * pS);
+
+/* Name        : icp_ocfDrvPkeProcess
+ *
+ * Description : This function will choose which PKE process to follow
+ * based on the input arguments
+ */
+int icp_ocfDrvPkeProcess(device_t dev, struct cryptkop *krp, int hint)
+{
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+
+	if (NULL == krp) {
+		DPRINTK("%s(): Invalid input parameters, cryptkop = %p\n",
+			__FUNCTION__, krp);
+		return EINVAL;
+	}
+
+	if (CPA_TRUE == atomic_read(&icp_ocfDrvIsExiting)) {
+		krp->krp_status = ECANCELED;
+		return ECANCELED;
+	}
+
+	switch (krp->krp_op) {
+	case CRK_DH_COMPUTE_KEY:
+		DPRINTK("%s() doing DH_COMPUTE_KEY\n", __FUNCTION__);
+		lacStatus = icp_ocfDrvDHComputeKey(krp);
+		if (CPA_STATUS_SUCCESS != lacStatus) {
+			EPRINTK("%s(): icp_ocfDrvDHComputeKey failed "
+				"(%d).\n", __FUNCTION__, lacStatus);
+			krp->krp_status = ECANCELED;
+			return ECANCELED;
+		}
+
+		break;
+
+	case CRK_MOD_EXP:
+		DPRINTK("%s() doing MOD_EXP \n", __FUNCTION__);
+		lacStatus = icp_ocfDrvModExp(krp);
+		if (CPA_STATUS_SUCCESS != lacStatus) {
+			EPRINTK("%s(): icp_ocfDrvModExp failed (%d).\n",
+				__FUNCTION__, lacStatus);
+			krp->krp_status = ECANCELED;
+			return ECANCELED;
+		}
+
+		break;
+
+	case CRK_MOD_EXP_CRT:
+		DPRINTK("%s() doing MOD_EXP_CRT \n", __FUNCTION__);
+		lacStatus = icp_ocfDrvModExpCRT(krp);
+		if (CPA_STATUS_SUCCESS != lacStatus) {
+			EPRINTK("%s(): icp_ocfDrvModExpCRT "
+				"failed (%d).\n", __FUNCTION__, lacStatus);
+			krp->krp_status = ECANCELED;
+			return ECANCELED;
+		}
+
+		break;
+
+	case CRK_DSA_SIGN:
+		DPRINTK("%s() doing DSA_SIGN \n", __FUNCTION__);
+		lacStatus = icp_ocfDrvDsaSign(krp);
+		if (CPA_STATUS_SUCCESS != lacStatus) {
+			EPRINTK("%s(): icp_ocfDrvDsaSign "
+				"failed (%d).\n", __FUNCTION__, lacStatus);
+			krp->krp_status = ECANCELED;
+			return ECANCELED;
+		}
+
+		break;
+
+	case CRK_DSA_VERIFY:
+		DPRINTK("%s() doing DSA_VERIFY \n", __FUNCTION__);
+		lacStatus = icp_ocfDrvDsaVerify(krp);
+		if (CPA_STATUS_SUCCESS != lacStatus) {
+			EPRINTK("%s(): icp_ocfDrvDsaVerify "
+				"failed (%d).\n", __FUNCTION__, lacStatus);
+			krp->krp_status = ECANCELED;
+			return ECANCELED;
+		}
+
+		break;
+
+	default:
+		EPRINTK("%s(): Asymettric function not "
+			"supported (%d).\n", __FUNCTION__, krp->krp_op);
+		krp->krp_status = EOPNOTSUPP;
+		return EOPNOTSUPP;
+	}
+
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvSwapBytes
+ *
+ * Description : This function is used to swap the byte order of a buffer.
+ * It has been seen that in general we are passed little endian byte order
+ * buffers, but LAC only accepts big endian byte order buffers.
+ */
+static void inline
+icp_ocfDrvSwapBytes(u_int8_t * num, u_int32_t buff_len_bytes)
+{
+
+	int i;
+	u_int8_t *end_ptr;
+	u_int8_t hold_val;
+
+	end_ptr = num + (buff_len_bytes - 1);
+	buff_len_bytes = buff_len_bytes >> 1;
+	for (i = 0; i < buff_len_bytes; i++) {
+		hold_val = *num;
+		*num = *end_ptr;
+		num++;
+		*end_ptr = hold_val;
+		end_ptr--;
+	}
+}
+
+/* Name        : icp_ocfDrvDHComputeKey
+ *
+ * Description : This function will map Diffie Hellman calls from OCF
+ * to the LAC API. OCF uses this function for Diffie Hellman Phase1 and
+ * Phase2. LAC has a separate Diffie Hellman Phase2 call, however both phases
+ * break down to a modular exponentiation.
+ */
+static int icp_ocfDrvDHComputeKey(struct cryptkop *krp)
+{
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	void *callbackTag = NULL;
+	CpaCyDhPhase1KeyGenOpData *pPhase1OpData = NULL;
+	CpaFlatBuffer *pLocalOctetStringPV = NULL;
+	uint32_t dh_prime_len_bytes = 0, dh_prime_len_bits = 0;
+
+	/* Input checks - check prime is a multiple of 8 bits to allow for
+	   allocation later */
+	dh_prime_len_bits =
+	    (krp->krp_param[ICP_DH_KRP_PARAM_PRIME_INDEX].crp_nbits);
+
+	/* LAC can reject prime lengths based on prime key sizes, we just
+	   need to make sure we can allocate space for the base and
+	   exponent buffers correctly */
+	if ((dh_prime_len_bits % NUM_BITS_IN_BYTE) != 0) {
+		APRINTK("%s(): Warning Prime number buffer size is not a "
+			"multiple of 8 bits\n", __FUNCTION__);
+	}
+
+	/* Result storage space should be the same size as the prime as this
+	   value can take up the same amount of storage space */
+	if (dh_prime_len_bits !=
+	    krp->krp_param[ICP_DH_KRP_PARAM_RESULT_INDEX].crp_nbits) {
+		DPRINTK("%s(): Return Buffer must be the same size "
+			"as the Prime buffer\n", __FUNCTION__);
+		krp->krp_status = EINVAL;
+		return EINVAL;
+	}
+	/* Switch to size in bytes */
+	BITS_TO_BYTES(dh_prime_len_bytes, dh_prime_len_bits);
+
+	callbackTag = krp;
+
+	pPhase1OpData = kmem_cache_zalloc(drvDH_zone, GFP_KERNEL);
+	if (NULL == pPhase1OpData) {
+		APRINTK("%s():Failed to get memory for key gen data\n",
+			__FUNCTION__);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	pLocalOctetStringPV = kmem_cache_zalloc(drvFlatBuffer_zone, GFP_KERNEL);
+	if (NULL == pLocalOctetStringPV) {
+		APRINTK("%s():Failed to get memory for pLocalOctetStringPV\n",
+			__FUNCTION__);
+		kmem_cache_free(drvDH_zone, pPhase1OpData);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	/* Link parameters */
+	pPhase1OpData->primeP.pData =
+	    krp->krp_param[ICP_DH_KRP_PARAM_PRIME_INDEX].crp_p;
+
+	pPhase1OpData->primeP.dataLenInBytes = dh_prime_len_bytes;
+
+	icp_ocfDrvSwapBytes(pPhase1OpData->primeP.pData, dh_prime_len_bytes);
+
+	pPhase1OpData->baseG.pData =
+	    krp->krp_param[ICP_DH_KRP_PARAM_BASE_INDEX].crp_p;
+
+	BITS_TO_BYTES(pPhase1OpData->baseG.dataLenInBytes,
+		      krp->krp_param[ICP_DH_KRP_PARAM_BASE_INDEX].crp_nbits);
+
+	icp_ocfDrvSwapBytes(pPhase1OpData->baseG.pData,
+			    pPhase1OpData->baseG.dataLenInBytes);
+
+	pPhase1OpData->privateValueX.pData =
+	    krp->krp_param[ICP_DH_KRP_PARAM_PRIVATE_VALUE_INDEX].crp_p;
+
+	BITS_TO_BYTES(pPhase1OpData->privateValueX.dataLenInBytes,
+		      krp->krp_param[ICP_DH_KRP_PARAM_PRIVATE_VALUE_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(pPhase1OpData->privateValueX.pData,
+			    pPhase1OpData->privateValueX.dataLenInBytes);
+
+	/* Output parameters */
+	pLocalOctetStringPV->pData =
+	    krp->krp_param[ICP_DH_KRP_PARAM_RESULT_INDEX].crp_p;
+
+	BITS_TO_BYTES(pLocalOctetStringPV->dataLenInBytes,
+		      krp->krp_param[ICP_DH_KRP_PARAM_RESULT_INDEX].crp_nbits);
+
+	lacStatus = cpaCyDhKeyGenPhase1(CPA_INSTANCE_HANDLE_SINGLE,
+					icp_ocfDrvDhP1CallBack,
+					callbackTag, pPhase1OpData,
+					pLocalOctetStringPV);
+
+	if (CPA_STATUS_SUCCESS != lacStatus) {
+		EPRINTK("%s(): DH Phase 1 Key Gen failed (%d).\n",
+			__FUNCTION__, lacStatus);
+		icp_ocfDrvFreeFlatBuffer(pLocalOctetStringPV);
+		kmem_cache_free(drvDH_zone, pPhase1OpData);
+	}
+
+	return lacStatus;
+}
+
+/* Name        : icp_ocfDrvModExp
+ *
+ * Description : This function will map ordinary Modular Exponentiation calls
+ * from OCF to the LAC API.
+ *
+ */
+static int icp_ocfDrvModExp(struct cryptkop *krp)
+{
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	void *callbackTag = NULL;
+	CpaCyLnModExpOpData *pModExpOpData = NULL;
+	CpaFlatBuffer *pResult = NULL;
+
+	if ((krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].crp_nbits %
+	     NUM_BITS_IN_BYTE) != 0) {
+		DPRINTK("%s(): Warning - modulus buffer size (%d) is not a "
+			"multiple of 8 bits\n", __FUNCTION__,
+			krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].
+			crp_nbits);
+	}
+
+	/* Result storage space should be the same size as the prime as this
+	   value can take up the same amount of storage space */
+	if (krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].crp_nbits >
+	    krp->krp_param[ICP_MOD_EXP_KRP_PARAM_RESULT_INDEX].crp_nbits) {
+		APRINTK("%s(): Return Buffer size must be the same or"
+			" greater than the Modulus buffer\n", __FUNCTION__);
+		krp->krp_status = EINVAL;
+		return EINVAL;
+	}
+
+	callbackTag = krp;
+
+	pModExpOpData = kmem_cache_zalloc(drvLnModExp_zone, GFP_KERNEL);
+	if (NULL == pModExpOpData) {
+		APRINTK("%s():Failed to get memory for key gen data\n",
+			__FUNCTION__);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	pResult = kmem_cache_zalloc(drvFlatBuffer_zone, GFP_KERNEL);
+	if (NULL == pResult) {
+		APRINTK("%s():Failed to get memory for ModExp result\n",
+			__FUNCTION__);
+		kmem_cache_free(drvLnModExp_zone, pModExpOpData);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	/* Link parameters */
+	pModExpOpData->modulus.pData =
+	    krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].crp_p;
+	BITS_TO_BYTES(pModExpOpData->modulus.dataLenInBytes,
+		      krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(pModExpOpData->modulus.pData,
+			    pModExpOpData->modulus.dataLenInBytes);
+
+	/*OCF patch to Openswan Pluto regularly sends the base value as 2
+	   bits in size. In this case, it has been found it is better to
+	   use the base size memory space as the input buffer (if the number
+	   is in bits is less than a byte, the number of bits is the input
+	   value) */
+	if (krp->krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].crp_nbits <
+	    NUM_BITS_IN_BYTE) {
+		DPRINTK("%s : base is small (%d)\n", __FUNCTION__, krp->
+			krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].crp_nbits);
+		pModExpOpData->base.dataLenInBytes = SINGLE_BYTE_VALUE;
+		pModExpOpData->base.pData =
+		    (uint8_t *) & (krp->
+				   krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].
+				   crp_nbits);
+		*((uint32_t *) pModExpOpData->base.pData) =
+		    htonl(*((uint32_t *) pModExpOpData->base.pData));
+
+	} else {
+
+		DPRINTK("%s : base is big (%d)\n", __FUNCTION__, krp->
+			krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].crp_nbits);
+		pModExpOpData->base.pData =
+		    krp->krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].crp_p;
+		BITS_TO_BYTES(pModExpOpData->base.dataLenInBytes,
+			      krp->krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].
+			      crp_nbits);
+		icp_ocfDrvSwapBytes(pModExpOpData->base.pData,
+				    pModExpOpData->base.dataLenInBytes);
+	}
+
+	pModExpOpData->exponent.pData =
+	    krp->krp_param[ICP_MOD_EXP_KRP_PARAM_EXPONENT_INDEX].crp_p;
+	BITS_TO_BYTES(pModExpOpData->exponent.dataLenInBytes,
+		      krp->krp_param[ICP_MOD_EXP_KRP_PARAM_EXPONENT_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(pModExpOpData->exponent.pData,
+			    pModExpOpData->exponent.dataLenInBytes);
+	/* Output parameters */
+	pResult->pData =
+	    krp->krp_param[ICP_MOD_EXP_KRP_PARAM_RESULT_INDEX].crp_p,
+	    BITS_TO_BYTES(pResult->dataLenInBytes,
+			  krp->krp_param[ICP_MOD_EXP_KRP_PARAM_RESULT_INDEX].
+			  crp_nbits);
+
+	lacStatus = cpaCyLnModExp(CPA_INSTANCE_HANDLE_SINGLE,
+				  icp_ocfDrvModExpCallBack,
+				  callbackTag, pModExpOpData, pResult);
+
+	if (CPA_STATUS_SUCCESS != lacStatus) {
+		EPRINTK("%s(): Mod Exp Operation failed (%d).\n",
+			__FUNCTION__, lacStatus);
+		krp->krp_status = ECANCELED;
+		icp_ocfDrvFreeFlatBuffer(pResult);
+		kmem_cache_free(drvLnModExp_zone, pModExpOpData);
+	}
+
+	return lacStatus;
+}
+
+/* Name        : icp_ocfDrvModExpCRT
+ *
+ * Description : This function will map ordinary Modular Exponentiation Chinese
+ * Remainder Theorem implementaion calls from OCF to the LAC API.
+ *
+ * Note : Mod Exp CRT for this driver is accelerated through LAC RSA type 2
+ * decrypt operation. Therefore P and Q input values must always be prime
+ * numbers. Although basic primality checks are done in LAC, it is up to the
+ * user to do any correct prime number checking before passing the inputs.
+ */
+
+static int icp_ocfDrvModExpCRT(struct cryptkop *krp)
+{
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	CpaCyRsaDecryptOpData *rsaDecryptOpData = NULL;
+	void *callbackTag = NULL;
+	CpaFlatBuffer *pOutputData = NULL;
+
+	/*Parameter input checks are all done by LAC, no need to repeat
+	   them here. */
+	callbackTag = krp;
+
+	rsaDecryptOpData = kmem_cache_zalloc(drvRSADecrypt_zone, GFP_KERNEL);
+	if (NULL == rsaDecryptOpData) {
+		APRINTK("%s():Failed to get memory"
+			" for MOD EXP CRT Op data struct\n", __FUNCTION__);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	rsaDecryptOpData->pRecipientPrivateKey
+	    = kmem_cache_zalloc(drvRSAPrivateKey_zone, GFP_KERNEL);
+	if (NULL == rsaDecryptOpData->pRecipientPrivateKey) {
+		APRINTK("%s():Failed to get memory for MOD EXP CRT"
+			" private key values struct\n", __FUNCTION__);
+		kmem_cache_free(drvRSADecrypt_zone, rsaDecryptOpData);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	rsaDecryptOpData->pRecipientPrivateKey->
+	    version = CPA_CY_RSA_VERSION_TWO_PRIME;
+	rsaDecryptOpData->pRecipientPrivateKey->
+	    privateKeyRepType = CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2;
+
+	pOutputData = kmem_cache_zalloc(drvFlatBuffer_zone, GFP_KERNEL);
+	if (NULL == pOutputData) {
+		APRINTK("%s():Failed to get memory"
+			" for MOD EXP CRT output data\n", __FUNCTION__);
+		kmem_cache_free(drvRSAPrivateKey_zone,
+				rsaDecryptOpData->pRecipientPrivateKey);
+		kmem_cache_free(drvRSADecrypt_zone, rsaDecryptOpData);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	rsaDecryptOpData->pRecipientPrivateKey->
+	    version = CPA_CY_RSA_VERSION_TWO_PRIME;
+	rsaDecryptOpData->pRecipientPrivateKey->
+	    privateKeyRepType = CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2;
+
+	/* Link parameters */
+	rsaDecryptOpData->inputData.pData =
+	    krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_I_INDEX].crp_p;
+	BITS_TO_BYTES(rsaDecryptOpData->inputData.dataLenInBytes,
+		      krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_I_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(rsaDecryptOpData->inputData.pData,
+			    rsaDecryptOpData->inputData.dataLenInBytes);
+
+	rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P.pData =
+	    krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_P_INDEX].crp_p;
+	BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.
+		      prime1P.dataLenInBytes,
+		      krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_P_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.prime1P.pData,
+			    rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.prime1P.dataLenInBytes);
+
+	rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q.pData =
+	    krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_Q_INDEX].crp_p;
+	BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.
+		      prime2Q.dataLenInBytes,
+		      krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_Q_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.prime2Q.pData,
+			    rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.prime2Q.dataLenInBytes);
+
+	rsaDecryptOpData->pRecipientPrivateKey->
+	    privateKeyRep2.exponent1Dp.pData =
+	    krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DP_INDEX].crp_p;
+	BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.
+		      exponent1Dp.dataLenInBytes,
+		      krp->
+		      krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DP_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.exponent1Dp.pData,
+			    rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.exponent1Dp.dataLenInBytes);
+
+	rsaDecryptOpData->pRecipientPrivateKey->
+	    privateKeyRep2.exponent2Dq.pData =
+	    krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DQ_INDEX].crp_p;
+	BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->
+		      privateKeyRep2.exponent2Dq.dataLenInBytes,
+		      krp->
+		      krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DQ_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.exponent2Dq.pData,
+			    rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.exponent2Dq.dataLenInBytes);
+
+	rsaDecryptOpData->pRecipientPrivateKey->
+	    privateKeyRep2.coefficientQInv.pData =
+	    krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_COEFF_QINV_INDEX].crp_p;
+	BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->
+		      privateKeyRep2.coefficientQInv.dataLenInBytes,
+		      krp->
+		      krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_COEFF_QINV_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.coefficientQInv.pData,
+			    rsaDecryptOpData->pRecipientPrivateKey->
+			    privateKeyRep2.coefficientQInv.dataLenInBytes);
+
+	/* Output Parameter */
+	pOutputData->pData =
+	    krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_RESULT_INDEX].crp_p;
+	BITS_TO_BYTES(pOutputData->dataLenInBytes,
+		      krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_RESULT_INDEX].
+		      crp_nbits);
+
+	lacStatus = cpaCyRsaDecrypt(CPA_INSTANCE_HANDLE_SINGLE,
+				    icp_ocfDrvModExpCRTCallBack,
+				    callbackTag, rsaDecryptOpData, pOutputData);
+
+	if (CPA_STATUS_SUCCESS != lacStatus) {
+		EPRINTK("%s(): Mod Exp CRT Operation failed (%d).\n",
+			__FUNCTION__, lacStatus);
+		krp->krp_status = ECANCELED;
+		icp_ocfDrvFreeFlatBuffer(pOutputData);
+		kmem_cache_free(drvRSAPrivateKey_zone,
+				rsaDecryptOpData->pRecipientPrivateKey);
+		kmem_cache_free(drvRSADecrypt_zone, rsaDecryptOpData);
+	}
+
+	return lacStatus;
+}
+
+/* Name        : icp_ocfDrvCheckALessThanB
+ *
+ * Description : This function will check whether the first argument is less
+ * than the second. It is used to check whether the DSA RS sign Random K
+ * value is less than the Prime Q value (as defined in the specification)
+ *
+ */
+static int
+icp_ocfDrvCheckALessThanB(CpaFlatBuffer * pK, CpaFlatBuffer * pQ, int *doCheck)
+{
+
+	uint8_t *MSB_K = pK->pData;
+	uint8_t *MSB_Q = pQ->pData;
+	uint32_t buffer_lengths_in_bytes = pQ->dataLenInBytes;
+
+	if (DONT_RUN_LESS_THAN_CHECK == *doCheck) {
+		return FAIL_A_IS_GREATER_THAN_B;
+	}
+
+/*Check MSBs
+if A == B, check next MSB
+if A > B, return A_IS_GREATER_THAN_B
+if A < B, return A_IS_LESS_THAN_B (success)
+*/
+	while (*MSB_K == *MSB_Q) {
+		MSB_K++;
+		MSB_Q++;
+
+		buffer_lengths_in_bytes--;
+		if (0 == buffer_lengths_in_bytes) {
+			DPRINTK("%s() Buffers have equal value!!\n",
+				__FUNCTION__);
+			return FAIL_A_IS_EQUAL_TO_B;
+		}
+
+	}
+
+	if (*MSB_K < *MSB_Q) {
+		return SUCCESS_A_IS_LESS_THAN_B;
+	} else {
+		return FAIL_A_IS_GREATER_THAN_B;
+	}
+
+}
+
+/* Name        : icp_ocfDrvDsaSign
+ *
+ * Description : This function will map DSA RS Sign from OCF to the LAC API.
+ *
+ * NOTE: From looking at OCF patch to OpenSSL and even the number of input
+ * parameters, OCF expects us to generate the random seed value. This value
+ * is generated and passed to LAC, however the number is discared in the
+ * callback and not returned to the user.
+ */
+static int icp_ocfDrvDsaSign(struct cryptkop *krp)
+{
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	CpaCyDsaRSSignOpData *dsaRsSignOpData = NULL;
+	void *callbackTag = NULL;
+	CpaCyRandGenOpData randGenOpData;
+	int primeQSizeInBytes = 0;
+	int doCheck = 0;
+	CpaFlatBuffer randData;
+	CpaBoolean protocolStatus = CPA_FALSE;
+	CpaFlatBuffer *pR = NULL;
+	CpaFlatBuffer *pS = NULL;
+
+	callbackTag = krp;
+
+	BITS_TO_BYTES(primeQSizeInBytes,
+		      krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_Q_INDEX].
+		      crp_nbits);
+
+	if (DSA_RS_SIGN_PRIMEQ_SIZE_IN_BYTES != primeQSizeInBytes) {
+		APRINTK("%s(): DSA PRIME Q size not equal to the "
+			"FIPS defined 20bytes, = %d\n",
+			__FUNCTION__, primeQSizeInBytes);
+		krp->krp_status = EDOM;
+		return EDOM;
+	}
+
+	dsaRsSignOpData = kmem_cache_zalloc(drvDSARSSign_zone, GFP_KERNEL);
+	if (NULL == dsaRsSignOpData) {
+		APRINTK("%s():Failed to get memory"
+			" for DSA RS Sign Op data struct\n", __FUNCTION__);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	dsaRsSignOpData->K.pData =
+	    kmem_cache_alloc(drvDSARSSignKValue_zone, GFP_ATOMIC);
+
+	if (NULL == dsaRsSignOpData->K.pData) {
+		APRINTK("%s():Failed to get memory"
+			" for DSA RS Sign Op Random value\n", __FUNCTION__);
+		kmem_cache_free(drvDSARSSign_zone, dsaRsSignOpData);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	pR = kmem_cache_zalloc(drvFlatBuffer_zone, GFP_KERNEL);
+	if (NULL == pR) {
+		APRINTK("%s():Failed to get memory"
+			" for DSA signature R\n", __FUNCTION__);
+		kmem_cache_free(drvDSARSSignKValue_zone,
+				dsaRsSignOpData->K.pData);
+		kmem_cache_free(drvDSARSSign_zone, dsaRsSignOpData);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	pS = kmem_cache_zalloc(drvFlatBuffer_zone, GFP_KERNEL);
+	if (NULL == pS) {
+		APRINTK("%s():Failed to get memory"
+			" for DSA signature S\n", __FUNCTION__);
+		icp_ocfDrvFreeFlatBuffer(pR);
+		kmem_cache_free(drvDSARSSignKValue_zone,
+				dsaRsSignOpData->K.pData);
+		kmem_cache_free(drvDSARSSign_zone, dsaRsSignOpData);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	/*link prime number parameter for ease of processing */
+	dsaRsSignOpData->P.pData =
+	    krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_P_INDEX].crp_p;
+	BITS_TO_BYTES(dsaRsSignOpData->P.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_P_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(dsaRsSignOpData->P.pData,
+			    dsaRsSignOpData->P.dataLenInBytes);
+
+	dsaRsSignOpData->Q.pData =
+	    krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_Q_INDEX].crp_p;
+	BITS_TO_BYTES(dsaRsSignOpData->Q.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_Q_INDEX].
+		      crp_nbits);
+
+	icp_ocfDrvSwapBytes(dsaRsSignOpData->Q.pData,
+			    dsaRsSignOpData->Q.dataLenInBytes);
+
+	/*generate random number with equal buffer size to Prime value Q,
+	   but value less than Q */
+	dsaRsSignOpData->K.dataLenInBytes = dsaRsSignOpData->Q.dataLenInBytes;
+
+	randGenOpData.generateBits = CPA_TRUE;
+	randGenOpData.lenInBytes = dsaRsSignOpData->K.dataLenInBytes;
+
+	icp_ocfDrvPtrAndLenToFlatBuffer(dsaRsSignOpData->K.pData,
+					dsaRsSignOpData->K.dataLenInBytes,
+					&randData);
+
+	doCheck = 0;
+	while (icp_ocfDrvCheckALessThanB(&(dsaRsSignOpData->K),
+					 &(dsaRsSignOpData->Q), &doCheck)) {
+
+		if (CPA_STATUS_SUCCESS
+		    != cpaCyRandGen(CPA_INSTANCE_HANDLE_SINGLE,
+				    NULL, NULL, &randGenOpData, &randData)) {
+			APRINTK("%s(): ERROR - Failed to generate DSA RS Sign K"
+				"value\n", __FUNCTION__);
+			icp_ocfDrvFreeFlatBuffer(pS);
+			icp_ocfDrvFreeFlatBuffer(pR);
+			kmem_cache_free(drvDSARSSignKValue_zone,
+					dsaRsSignOpData->K.pData);
+			kmem_cache_free(drvDSARSSign_zone, dsaRsSignOpData);
+			krp->krp_status = EAGAIN;
+			return EAGAIN;
+		}
+
+		doCheck++;
+		if (DSA_SIGN_RAND_GEN_VAL_CHECK_MAX_ITERATIONS == doCheck) {
+			APRINTK("%s(): ERROR - Failed to find DSA RS Sign K "
+				"value less than Q value\n", __FUNCTION__);
+			icp_ocfDrvFreeFlatBuffer(pS);
+			icp_ocfDrvFreeFlatBuffer(pR);
+			kmem_cache_free(drvDSARSSignKValue_zone,
+					dsaRsSignOpData->K.pData);
+			kmem_cache_free(drvDSARSSign_zone, dsaRsSignOpData);
+			krp->krp_status = EAGAIN;
+			return EAGAIN;
+		}
+
+	}
+	/*Rand Data - no need to swap bytes for pK */
+
+	/* Link parameters */
+	dsaRsSignOpData->G.pData =
+	    krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_G_INDEX].crp_p;
+	BITS_TO_BYTES(dsaRsSignOpData->G.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_G_INDEX].crp_nbits);
+
+	icp_ocfDrvSwapBytes(dsaRsSignOpData->G.pData,
+			    dsaRsSignOpData->G.dataLenInBytes);
+
+	dsaRsSignOpData->X.pData =
+	    krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_X_INDEX].crp_p;
+	BITS_TO_BYTES(dsaRsSignOpData->X.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_X_INDEX].crp_nbits);
+	icp_ocfDrvSwapBytes(dsaRsSignOpData->X.pData,
+			    dsaRsSignOpData->X.dataLenInBytes);
+
+	dsaRsSignOpData->M.pData =
+	    krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_DGST_INDEX].crp_p;
+	BITS_TO_BYTES(dsaRsSignOpData->M.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_DGST_INDEX].
+		      crp_nbits);
+	icp_ocfDrvSwapBytes(dsaRsSignOpData->M.pData,
+			    dsaRsSignOpData->M.dataLenInBytes);
+
+	/* Output Parameters */
+	pS->pData = krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_S_RESULT_INDEX].crp_p;
+	BITS_TO_BYTES(pS->dataLenInBytes,
+		      krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_S_RESULT_INDEX].
+		      crp_nbits);
+
+	pR->pData = krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_R_RESULT_INDEX].crp_p;
+	BITS_TO_BYTES(pR->dataLenInBytes,
+		      krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_R_RESULT_INDEX].
+		      crp_nbits);
+
+	lacStatus = cpaCyDsaSignRS(CPA_INSTANCE_HANDLE_SINGLE,
+				   icp_ocfDrvDsaRSSignCallBack,
+				   callbackTag, dsaRsSignOpData,
+				   &protocolStatus, pR, pS);
+
+	if (CPA_STATUS_SUCCESS != lacStatus) {
+		EPRINTK("%s(): DSA RS Sign Operation failed (%d).\n",
+			__FUNCTION__, lacStatus);
+		krp->krp_status = ECANCELED;
+		icp_ocfDrvFreeFlatBuffer(pS);
+		icp_ocfDrvFreeFlatBuffer(pR);
+		kmem_cache_free(drvDSARSSignKValue_zone,
+				dsaRsSignOpData->K.pData);
+		kmem_cache_free(drvDSARSSign_zone, dsaRsSignOpData);
+	}
+
+	return lacStatus;
+}
+
+/* Name        : icp_ocfDrvDsaVerify
+ *
+ * Description : This function will map DSA RS Verify from OCF to the LAC API.
+ *
+ */
+static int icp_ocfDrvDsaVerify(struct cryptkop *krp)
+{
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	CpaCyDsaVerifyOpData *dsaVerifyOpData = NULL;
+	void *callbackTag = NULL;
+	CpaBoolean verifyStatus = CPA_FALSE;
+
+	callbackTag = krp;
+
+	dsaVerifyOpData = kmem_cache_zalloc(drvDSAVerify_zone, GFP_KERNEL);
+	if (NULL == dsaVerifyOpData) {
+		APRINTK("%s():Failed to get memory"
+			" for DSA Verify Op data struct\n", __FUNCTION__);
+		krp->krp_status = ENOMEM;
+		return ENOMEM;
+	}
+
+	/* Link parameters */
+	dsaVerifyOpData->P.pData =
+	    krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PRIME_P_INDEX].crp_p;
+	BITS_TO_BYTES(dsaVerifyOpData->P.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PRIME_P_INDEX].
+		      crp_nbits);
+	icp_ocfDrvSwapBytes(dsaVerifyOpData->P.pData,
+			    dsaVerifyOpData->P.dataLenInBytes);
+
+	dsaVerifyOpData->Q.pData =
+	    krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PRIME_Q_INDEX].crp_p;
+	BITS_TO_BYTES(dsaVerifyOpData->Q.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PRIME_Q_INDEX].
+		      crp_nbits);
+	icp_ocfDrvSwapBytes(dsaVerifyOpData->Q.pData,
+			    dsaVerifyOpData->Q.dataLenInBytes);
+
+	dsaVerifyOpData->G.pData =
+	    krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_G_INDEX].crp_p;
+	BITS_TO_BYTES(dsaVerifyOpData->G.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_G_INDEX].
+		      crp_nbits);
+	icp_ocfDrvSwapBytes(dsaVerifyOpData->G.pData,
+			    dsaVerifyOpData->G.dataLenInBytes);
+
+	dsaVerifyOpData->Y.pData =
+	    krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PUBKEY_INDEX].crp_p;
+	BITS_TO_BYTES(dsaVerifyOpData->Y.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PUBKEY_INDEX].
+		      crp_nbits);
+	icp_ocfDrvSwapBytes(dsaVerifyOpData->Y.pData,
+			    dsaVerifyOpData->Y.dataLenInBytes);
+
+	dsaVerifyOpData->M.pData =
+	    krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_DGST_INDEX].crp_p;
+	BITS_TO_BYTES(dsaVerifyOpData->M.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_DGST_INDEX].
+		      crp_nbits);
+	icp_ocfDrvSwapBytes(dsaVerifyOpData->M.pData,
+			    dsaVerifyOpData->M.dataLenInBytes);
+
+	dsaVerifyOpData->R.pData =
+	    krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_SIG_R_INDEX].crp_p;
+	BITS_TO_BYTES(dsaVerifyOpData->R.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_SIG_R_INDEX].
+		      crp_nbits);
+	icp_ocfDrvSwapBytes(dsaVerifyOpData->R.pData,
+			    dsaVerifyOpData->R.dataLenInBytes);
+
+	dsaVerifyOpData->S.pData =
+	    krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_SIG_S_INDEX].crp_p;
+	BITS_TO_BYTES(dsaVerifyOpData->S.dataLenInBytes,
+		      krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_SIG_S_INDEX].
+		      crp_nbits);
+	icp_ocfDrvSwapBytes(dsaVerifyOpData->S.pData,
+			    dsaVerifyOpData->S.dataLenInBytes);
+
+	lacStatus = cpaCyDsaVerify(CPA_INSTANCE_HANDLE_SINGLE,
+				   icp_ocfDrvDsaVerifyCallBack,
+				   callbackTag, dsaVerifyOpData, &verifyStatus);
+
+	if (CPA_STATUS_SUCCESS != lacStatus) {
+		EPRINTK("%s(): DSA Verify Operation failed (%d).\n",
+			__FUNCTION__, lacStatus);
+		kmem_cache_free(drvDSAVerify_zone, dsaVerifyOpData);
+		krp->krp_status = ECANCELED;
+	}
+
+	return lacStatus;
+}
+
+/* Name        : icp_ocfDrvReadRandom
+ *
+ * Description : This function will map RNG functionality calls from OCF
+ * to the LAC API.
+ */
+int icp_ocfDrvReadRandom(void *arg, uint32_t * buf, int maxwords)
+{
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	CpaCyRandGenOpData randGenOpData;
+	CpaFlatBuffer randData;
+
+	if (NULL == buf) {
+		APRINTK("%s(): Invalid input parameters\n", __FUNCTION__);
+		return EINVAL;
+	}
+
+	/* maxwords here is number of integers to generate data for */
+	randGenOpData.generateBits = CPA_TRUE;
+
+	randGenOpData.lenInBytes = maxwords * sizeof(uint32_t);
+
+	icp_ocfDrvPtrAndLenToFlatBuffer((Cpa8U *) buf,
+					randGenOpData.lenInBytes, &randData);
+
+	lacStatus = cpaCyRandGen(CPA_INSTANCE_HANDLE_SINGLE,
+				 NULL, NULL, &randGenOpData, &randData);
+	if (CPA_STATUS_SUCCESS != lacStatus) {
+		EPRINTK("%s(): icp_LacSymRandGen failed (%d). \n",
+			__FUNCTION__, lacStatus);
+		return RETURN_RAND_NUM_GEN_FAILED;
+	}
+
+	return randGenOpData.lenInBytes / sizeof(uint32_t);
+}
+
+/* Name        : icp_ocfDrvDhP1Callback
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the DH operation.
+ */
+static void
+icp_ocfDrvDhP1CallBack(void *callbackTag,
+		       CpaStatus status,
+		       void *pOpData, CpaFlatBuffer * pLocalOctetStringPV)
+{
+	struct cryptkop *krp = NULL;
+	CpaCyDhPhase1KeyGenOpData *pPhase1OpData = NULL;
+
+	if (NULL == callbackTag) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"callbackTag data is NULL\n", __FUNCTION__);
+		return;
+	}
+	krp = (struct cryptkop *)callbackTag;
+
+	if (NULL == pOpData) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"Operation Data is NULL\n", __FUNCTION__);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+	pPhase1OpData = (CpaCyDhPhase1KeyGenOpData *) pOpData;
+
+	if (NULL == pLocalOctetStringPV) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"pLocalOctetStringPV Data is NULL\n", __FUNCTION__);
+		memset(pPhase1OpData, 0, sizeof(CpaCyDhPhase1KeyGenOpData));
+		kmem_cache_free(drvDH_zone, pPhase1OpData);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+
+	if (CPA_STATUS_SUCCESS == status) {
+		krp->krp_status = CRYPTO_OP_SUCCESS;
+	} else {
+		APRINTK("%s(): Diffie Hellman Phase1 Key Gen failed - "
+			"Operation Status = %d\n", __FUNCTION__, status);
+		krp->krp_status = ECANCELED;
+	}
+
+	icp_ocfDrvSwapBytes(pLocalOctetStringPV->pData,
+			    pLocalOctetStringPV->dataLenInBytes);
+
+	icp_ocfDrvFreeFlatBuffer(pLocalOctetStringPV);
+	memset(pPhase1OpData, 0, sizeof(CpaCyDhPhase1KeyGenOpData));
+	kmem_cache_free(drvDH_zone, pPhase1OpData);
+
+	crypto_kdone(krp);
+
+	return;
+}
+
+/* Name        : icp_ocfDrvModExpCallBack
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the Mod Exp operation.
+ */
+static void
+icp_ocfDrvModExpCallBack(void *callbackTag,
+			 CpaStatus status,
+			 void *pOpdata, CpaFlatBuffer * pResult)
+{
+	struct cryptkop *krp = NULL;
+	CpaCyLnModExpOpData *pLnModExpOpData = NULL;
+
+	if (NULL == callbackTag) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"callbackTag data is NULL\n", __FUNCTION__);
+		return;
+	}
+	krp = (struct cryptkop *)callbackTag;
+
+	if (NULL == pOpdata) {
+		DPRINTK("%s(): Invalid Mod Exp input parameters - "
+			"Operation Data is NULL\n", __FUNCTION__);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+	pLnModExpOpData = (CpaCyLnModExpOpData *) pOpdata;
+
+	if (NULL == pResult) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"pResult data is NULL\n", __FUNCTION__);
+		krp->krp_status = ECANCELED;
+		memset(pLnModExpOpData, 0, sizeof(CpaCyLnModExpOpData));
+		kmem_cache_free(drvLnModExp_zone, pLnModExpOpData);
+		crypto_kdone(krp);
+		return;
+	}
+
+	if (CPA_STATUS_SUCCESS == status) {
+		krp->krp_status = CRYPTO_OP_SUCCESS;
+	} else {
+		APRINTK("%s(): LAC Mod Exp Operation failed - "
+			"Operation Status = %d\n", __FUNCTION__, status);
+		krp->krp_status = ECANCELED;
+	}
+
+	icp_ocfDrvSwapBytes(pResult->pData, pResult->dataLenInBytes);
+
+	/*switch base size value back to original */
+	if (pLnModExpOpData->base.pData ==
+	    (uint8_t *) & (krp->
+			   krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].
+			   crp_nbits)) {
+		*((uint32_t *) pLnModExpOpData->base.pData) =
+		    ntohl(*((uint32_t *) pLnModExpOpData->base.pData));
+	}
+	icp_ocfDrvFreeFlatBuffer(pResult);
+	memset(pLnModExpOpData, 0, sizeof(CpaCyLnModExpOpData));
+	kmem_cache_free(drvLnModExp_zone, pLnModExpOpData);
+
+	crypto_kdone(krp);
+
+	return;
+
+}
+
+/* Name        : icp_ocfDrvModExpCRTCallBack
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the Mod Exp CRT operation.
+ */
+static void
+icp_ocfDrvModExpCRTCallBack(void *callbackTag,
+			    CpaStatus status,
+			    void *pOpData, CpaFlatBuffer * pOutputData)
+{
+	struct cryptkop *krp = NULL;
+	CpaCyRsaDecryptOpData *pDecryptData = NULL;
+
+	if (NULL == callbackTag) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"callbackTag data is NULL\n", __FUNCTION__);
+		return;
+	}
+
+	krp = (struct cryptkop *)callbackTag;
+
+	if (NULL == pOpData) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"Operation Data is NULL\n", __FUNCTION__);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+	pDecryptData = (CpaCyRsaDecryptOpData *) pOpData;
+
+	if (NULL == pOutputData) {
+		DPRINTK("%s(): Invalid input parameter - "
+			"pOutputData is NULL\n", __FUNCTION__);
+		memset(pDecryptData->pRecipientPrivateKey, 0,
+		       sizeof(CpaCyRsaPrivateKey));
+		kmem_cache_free(drvRSAPrivateKey_zone,
+				pDecryptData->pRecipientPrivateKey);
+		memset(pDecryptData, 0, sizeof(CpaCyRsaDecryptOpData));
+		kmem_cache_free(drvRSADecrypt_zone, pDecryptData);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+
+	if (CPA_STATUS_SUCCESS == status) {
+		krp->krp_status = CRYPTO_OP_SUCCESS;
+	} else {
+		APRINTK("%s(): LAC Mod Exp CRT operation failed - "
+			"Operation Status = %d\n", __FUNCTION__, status);
+		krp->krp_status = ECANCELED;
+	}
+
+	icp_ocfDrvSwapBytes(pOutputData->pData, pOutputData->dataLenInBytes);
+
+	icp_ocfDrvFreeFlatBuffer(pOutputData);
+	memset(pDecryptData->pRecipientPrivateKey, 0,
+	       sizeof(CpaCyRsaPrivateKey));
+	kmem_cache_free(drvRSAPrivateKey_zone,
+			pDecryptData->pRecipientPrivateKey);
+	memset(pDecryptData, 0, sizeof(CpaCyRsaDecryptOpData));
+	kmem_cache_free(drvRSADecrypt_zone, pDecryptData);
+
+	crypto_kdone(krp);
+
+	return;
+}
+
+/* Name        : icp_ocfDrvDsaRSSignCallBack
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the DSA RS sign operation.
+ */
+static void
+icp_ocfDrvDsaRSSignCallBack(void *callbackTag,
+			    CpaStatus status,
+			    void *pOpData,
+			    CpaBoolean protocolStatus,
+			    CpaFlatBuffer * pR, CpaFlatBuffer * pS)
+{
+	struct cryptkop *krp = NULL;
+	CpaCyDsaRSSignOpData *pSignData = NULL;
+
+	if (NULL == callbackTag) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"callbackTag data is NULL\n", __FUNCTION__);
+		return;
+	}
+
+	krp = (struct cryptkop *)callbackTag;
+
+	if (NULL == pOpData) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"Operation Data is NULL\n", __FUNCTION__);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+	pSignData = (CpaCyDsaRSSignOpData *) pOpData;
+
+	if (NULL == pR) {
+		DPRINTK("%s(): Invalid input parameter - "
+			"pR sign is NULL\n", __FUNCTION__);
+		icp_ocfDrvFreeFlatBuffer(pS);
+		kmem_cache_free(drvDSARSSign_zone, pSignData);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+
+	if (NULL == pS) {
+		DPRINTK("%s(): Invalid input parameter - "
+			"pS sign is NULL\n", __FUNCTION__);
+		icp_ocfDrvFreeFlatBuffer(pR);
+		kmem_cache_free(drvDSARSSign_zone, pSignData);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+
+	if (CPA_STATUS_SUCCESS != status) {
+		APRINTK("%s(): LAC DSA RS Sign operation failed - "
+			"Operation Status = %d\n", __FUNCTION__, status);
+		krp->krp_status = ECANCELED;
+	} else {
+		krp->krp_status = CRYPTO_OP_SUCCESS;
+
+		if (CPA_TRUE != protocolStatus) {
+			DPRINTK("%s(): LAC DSA RS Sign operation failed due "
+				"to protocol error\n", __FUNCTION__);
+			krp->krp_status = EIO;
+		}
+	}
+
+	/* Swap bytes only when the callback status is successful and
+	   protocolStatus is set to true */
+	if (CPA_STATUS_SUCCESS == status && CPA_TRUE == protocolStatus) {
+		icp_ocfDrvSwapBytes(pR->pData, pR->dataLenInBytes);
+		icp_ocfDrvSwapBytes(pS->pData, pS->dataLenInBytes);
+	}
+
+	icp_ocfDrvFreeFlatBuffer(pR);
+	icp_ocfDrvFreeFlatBuffer(pS);
+	memset(pSignData->K.pData, 0, pSignData->K.dataLenInBytes);
+	kmem_cache_free(drvDSARSSignKValue_zone, pSignData->K.pData);
+	memset(pSignData, 0, sizeof(CpaCyDsaRSSignOpData));
+	kmem_cache_free(drvDSARSSign_zone, pSignData);
+	crypto_kdone(krp);
+
+	return;
+}
+
+/* Name        : icp_ocfDrvDsaVerifyCallback
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the DSA Verify operation.
+ */
+static void
+icp_ocfDrvDsaVerifyCallBack(void *callbackTag,
+			    CpaStatus status,
+			    void *pOpData, CpaBoolean verifyStatus)
+{
+
+	struct cryptkop *krp = NULL;
+	CpaCyDsaVerifyOpData *pVerData = NULL;
+
+	if (NULL == callbackTag) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"callbackTag data is NULL\n", __FUNCTION__);
+		return;
+	}
+
+	krp = (struct cryptkop *)callbackTag;
+
+	if (NULL == pOpData) {
+		DPRINTK("%s(): Invalid input parameters - "
+			"Operation Data is NULL\n", __FUNCTION__);
+		krp->krp_status = ECANCELED;
+		crypto_kdone(krp);
+		return;
+	}
+	pVerData = (CpaCyDsaVerifyOpData *) pOpData;
+
+	if (CPA_STATUS_SUCCESS != status) {
+		APRINTK("%s(): LAC DSA Verify operation failed - "
+			"Operation Status = %d\n", __FUNCTION__, status);
+		krp->krp_status = ECANCELED;
+	} else {
+		krp->krp_status = CRYPTO_OP_SUCCESS;
+
+		if (CPA_TRUE != verifyStatus) {
+			DPRINTK("%s(): DSA signature invalid\n", __FUNCTION__);
+			krp->krp_status = EIO;
+		}
+	}
+
+	/* Swap bytes only when the callback status is successful and
+	   verifyStatus is set to true */
+	/*Just swapping back the key values for now. Possibly all
+	   swapped buffers need to be reverted */
+	if (CPA_STATUS_SUCCESS == status && CPA_TRUE == verifyStatus) {
+		icp_ocfDrvSwapBytes(pVerData->R.pData,
+				    pVerData->R.dataLenInBytes);
+		icp_ocfDrvSwapBytes(pVerData->S.pData,
+				    pVerData->S.dataLenInBytes);
+	}
+
+	memset(pVerData, 0, sizeof(CpaCyDsaVerifyOpData));
+	kmem_cache_free(drvDSAVerify_zone, pVerData);
+	crypto_kdone(krp);
+
+	return;
+}
diff --git a/crypto/ocf/ep80579/icp_common.c b/crypto/ocf/ep80579/icp_common.c
new file mode 100755
index 0000000..461370c
--- /dev/null
+++ b/crypto/ocf/ep80579/icp_common.c
@@ -0,0 +1,891 @@
+/***************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or 
+ *   redistributing this file, you may do so under either license.
+ * 
+ *   GPL LICENSE SUMMARY
+ * 
+ *   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+ * 
+ *   This program is free software; you can redistribute it and/or modify 
+ *   it under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ * 
+ *   This program is distributed in the hope that it will be useful, but 
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+ *   General Public License for more details.
+ * 
+ *   You should have received a copy of the GNU General Public License 
+ *   along with this program; if not, write to the Free Software 
+ *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *   The full GNU General Public License is included in this distribution 
+ *   in the file called LICENSE.GPL.
+ * 
+ *   Contact Information:
+ *   Intel Corporation
+ * 
+ *   BSD LICENSE 
+ * 
+ *   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without 
+ *   modification, are permitted provided that the following conditions 
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright 
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright 
+ *       notice, this list of conditions and the following disclaimer in 
+ *       the documentation and/or other materials provided with the 
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its 
+ *       contributors may be used to endorse or promote products derived 
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ *  version: Security.L.1.0.130
+ *
+ ***************************************************************************/
+
+/*
+ * An OCF module that uses Intel® QuickAssist Integrated Accelerator to do the 
+ * crypto.
+ *
+ * This driver requires the ICP Access Library that is available from Intel in
+ * order to operate.
+ */
+
+#include "icp_ocf.h"
+
+#define ICP_OCF_COMP_NAME 			"ICP_OCF"
+#define ICP_OCF_VER_MAIN			(2)
+#define ICP_OCF_VER_MJR				(0)
+#define ICP_OCF_VER_MNR 			(0)
+
+#define MAX_DEREG_RETRIES 			(100)
+#define DEFAULT_DEREG_RETRIES 			(10)
+#define DEFAULT_DEREG_DELAY_IN_JIFFIES		(10)
+
+/* This defines the maximum number of sessions possible between OCF
+   and the OCF Tolapai Driver. If set to zero, there is no limit. */
+#define DEFAULT_OCF_TO_DRV_MAX_SESSION_COUNT	(0)
+#define NUM_SUPPORTED_CAPABILITIES		(21)
+
+/*Slabs zones*/
+struct kmem_cache *drvSessionData_zone = NULL;
+struct kmem_cache *drvOpData_zone = NULL;
+struct kmem_cache *drvDH_zone = NULL;
+struct kmem_cache *drvLnModExp_zone = NULL;
+struct kmem_cache *drvRSADecrypt_zone = NULL;
+struct kmem_cache *drvRSAPrivateKey_zone = NULL;
+struct kmem_cache *drvDSARSSign_zone = NULL;
+struct kmem_cache *drvDSARSSignKValue_zone = NULL;
+struct kmem_cache *drvDSAVerify_zone = NULL;
+
+/*Slab zones for flatbuffers and bufferlist*/
+struct kmem_cache *drvFlatBuffer_zone = NULL;
+
+static int icp_ocfDrvInit(void);
+static void icp_ocfDrvExit(void);
+static void icp_ocfDrvFreeCaches(void);
+static void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg);
+
+int32_t icp_ocfDrvDriverId = INVALID_DRIVER_ID;
+
+/* Module parameter - gives the number of times LAC deregistration shall be
+   re-tried */
+int num_dereg_retries = DEFAULT_DEREG_RETRIES;
+
+/* Module parameter - gives the delay time in jiffies before a LAC session 
+   shall be attempted to be deregistered again */
+int dereg_retry_delay_in_jiffies = DEFAULT_DEREG_DELAY_IN_JIFFIES;
+
+/* Module parameter - gives the maximum number of sessions possible between
+   OCF and the OCF Tolapai Driver. If set to zero, there is no limit.*/
+int max_sessions = DEFAULT_OCF_TO_DRV_MAX_SESSION_COUNT;
+
+/* This is set when the module is removed from the system, no further
+   processing can take place if this is set */
+atomic_t icp_ocfDrvIsExiting = ATOMIC_INIT(0);
+
+/* This is used to show how many lac sessions were not deregistered*/
+atomic_t lac_session_failed_dereg_count = ATOMIC_INIT(0);
+
+/* This is used to track the number of registered sessions between OCF and
+ * and the OCF Tolapai driver, when max_session is set to value other than
+ * zero. This ensures that the max_session set for the OCF and the driver
+ * is equal to the LAC registered sessions */
+atomic_t num_ocf_to_drv_registered_sessions = ATOMIC_INIT(0);
+
+/* Head of linked list used to store session data */
+struct list_head icp_ocfDrvGlobalSymListHead;
+struct list_head icp_ocfDrvGlobalSymListHead_FreeMemList;
+
+spinlock_t icp_ocfDrvSymSessInfoListSpinlock = SPIN_LOCK_UNLOCKED;
+rwlock_t icp_kmem_cache_destroy_alloc_lock = RW_LOCK_UNLOCKED;
+
+struct workqueue_struct *icp_ocfDrvFreeLacSessionWorkQ;
+
+struct icp_drvBuffListInfo defBuffListInfo;
+
+static struct {
+	softc_device_decl sc_dev;
+} icpDev;
+
+static device_method_t icp_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession, icp_ocfDrvNewSession),
+	DEVMETHOD(cryptodev_freesession, icp_ocfDrvFreeLACSession),
+	DEVMETHOD(cryptodev_process, icp_ocfDrvSymProcess),
+	DEVMETHOD(cryptodev_kprocess, icp_ocfDrvPkeProcess),
+};
+
+module_param(num_dereg_retries, int, S_IRUGO);
+module_param(dereg_retry_delay_in_jiffies, int, S_IRUGO);
+module_param(max_sessions, int, S_IRUGO);
+
+MODULE_PARM_DESC(num_dereg_retries,
+		 "Number of times to retry LAC Sym Session Deregistration. "
+		 "Default 10, Max 100");
+MODULE_PARM_DESC(dereg_retry_delay_in_jiffies, "Delay in jiffies "
+		 "(added to a schedule() function call) before a LAC Sym "
+		 "Session Dereg is retried. Default 10");
+MODULE_PARM_DESC(max_sessions, "This sets the maximum number of sessions "
+		 "between OCF and this driver. If this value is set to zero, "
+		 "max session count checking is disabled. Default is zero(0)");
+
+/* Name        : icp_ocfDrvInit
+ *
+ * Description : This function will register all the symmetric and asymmetric
+ * functionality that will be accelerated by the hardware. It will also
+ * get a unique driver ID from the OCF and initialise all slab caches
+ */
+static int __init icp_ocfDrvInit(void)
+{
+	int ocfStatus = 0;
+
+	IPRINTK("=== %s ver %d.%d.%d ===\n", ICP_OCF_COMP_NAME,
+		ICP_OCF_VER_MAIN, ICP_OCF_VER_MJR, ICP_OCF_VER_MNR);
+
+	if (MAX_DEREG_RETRIES < num_dereg_retries) {
+		EPRINTK("Session deregistration retry count set to greater "
+			"than %d", MAX_DEREG_RETRIES);
+		return -1;
+	}
+
+	/* Initialize and Start the Cryptographic component */
+	if (CPA_STATUS_SUCCESS !=
+	    cpaCyStartInstance(CPA_INSTANCE_HANDLE_SINGLE)) {
+		EPRINTK("Failed to initialize and start the instance "
+			"of the Cryptographic component.\n");
+		return -1;
+	}
+
+	/* Set the default size of BufferList to allocate */
+	memset(&defBuffListInfo, 0, sizeof(struct icp_drvBuffListInfo));
+	if (ICP_OCF_DRV_STATUS_SUCCESS !=
+	    icp_ocfDrvBufferListMemInfo(ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS,
+					&defBuffListInfo)) {
+		EPRINTK("Failed to get bufferlist memory info.\n");
+		return -1;
+	}
+
+	/*Register OCF Tolapai Driver with OCF */
+	memset(&icpDev, 0, sizeof(icpDev));
+	softc_device_init(&icpDev, "icp", 0, icp_methods);
+
+	icp_ocfDrvDriverId = crypto_get_driverid(softc_get_device(&icpDev),
+						 CRYPTOCAP_F_HARDWARE);
+
+	if (icp_ocfDrvDriverId < 0) {
+		EPRINTK("%s : ICP driver failed to register with OCF!\n",
+			__FUNCTION__);
+		return -ENODEV;
+	}
+
+	/*Create all the slab caches used by the OCF Tolapai Driver */
+	drvSessionData_zone =
+	    ICP_CACHE_CREATE("ICP Session Data", struct icp_drvSessionData);
+	ICP_CACHE_NULL_CHECK(drvSessionData_zone);
+
+	/* 
+	 * Allocation of the OpData includes the allocation space for meta data.
+	 * The memory after the opData structure is reserved for this meta data.
+	 */
+	drvOpData_zone =
+	    kmem_cache_create("ICP Op Data", sizeof(struct icp_drvOpData) +
+	            defBuffListInfo.metaSize ,0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+
+	ICP_CACHE_NULL_CHECK(drvOpData_zone);
+
+	drvDH_zone = ICP_CACHE_CREATE("ICP DH data", CpaCyDhPhase1KeyGenOpData);
+	ICP_CACHE_NULL_CHECK(drvDH_zone);
+
+	drvLnModExp_zone =
+	    ICP_CACHE_CREATE("ICP ModExp data", CpaCyLnModExpOpData);
+	ICP_CACHE_NULL_CHECK(drvLnModExp_zone);
+
+	drvRSADecrypt_zone =
+	    ICP_CACHE_CREATE("ICP RSA decrypt data", CpaCyRsaDecryptOpData);
+	ICP_CACHE_NULL_CHECK(drvRSADecrypt_zone);
+
+	drvRSAPrivateKey_zone =
+	    ICP_CACHE_CREATE("ICP RSA private key data", CpaCyRsaPrivateKey);
+	ICP_CACHE_NULL_CHECK(drvRSAPrivateKey_zone);
+
+	drvDSARSSign_zone =
+	    ICP_CACHE_CREATE("ICP DSA Sign", CpaCyDsaRSSignOpData);
+	ICP_CACHE_NULL_CHECK(drvDSARSSign_zone);
+
+	/*too awkward to use a macro here */
+	drvDSARSSignKValue_zone =
+	    kmem_cache_create("ICP DSA Sign Rand Val",
+			      DSA_RS_SIGN_PRIMEQ_SIZE_IN_BYTES, 0,
+			      SLAB_HWCACHE_ALIGN, NULL, NULL);
+	ICP_CACHE_NULL_CHECK(drvDSARSSignKValue_zone);
+
+	drvDSAVerify_zone =
+	    ICP_CACHE_CREATE("ICP DSA Verify", CpaCyDsaVerifyOpData);
+	ICP_CACHE_NULL_CHECK(drvDSAVerify_zone);
+
+	drvFlatBuffer_zone =
+	    ICP_CACHE_CREATE("ICP Flat Buffers", CpaFlatBuffer);
+	ICP_CACHE_NULL_CHECK(drvFlatBuffer_zone);
+
+	/* Register the ICP symmetric crypto support. */
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_NULL_CBC);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_DES_CBC);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_3DES_CBC);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_AES_CBC);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_ARC4);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_MD5);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_MD5_HMAC);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA1);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA1_HMAC);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_256);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_256_HMAC);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_384);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_384_HMAC);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_512);
+	ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_512_HMAC);
+
+	/* Register the ICP asymmetric algorithm support */
+	ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_DH_COMPUTE_KEY);
+	ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_MOD_EXP);
+	ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_MOD_EXP_CRT);
+	ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_DSA_SIGN);
+	ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_DSA_VERIFY);
+
+	/* Register the ICP random number generator support */
+	if (OCF_REGISTRATION_STATUS_SUCCESS ==
+	    crypto_rregister(icp_ocfDrvDriverId, icp_ocfDrvReadRandom, NULL)) {
+		ocfStatus++;
+	}
+
+	if (OCF_ZERO_FUNCTIONALITY_REGISTERED == ocfStatus) {
+		DPRINTK("%s: Failed to register any device capabilities\n",
+			__FUNCTION__);
+		icp_ocfDrvFreeCaches();
+		icp_ocfDrvDriverId = INVALID_DRIVER_ID;
+		return -ECANCELED;
+	}
+
+	DPRINTK("%s: Registered %d of %d device capabilities\n",
+		__FUNCTION__, ocfStatus, NUM_SUPPORTED_CAPABILITIES);
+
+/*Session data linked list used during module exit*/
+	INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead);
+	INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead_FreeMemList);
+
+	icp_ocfDrvFreeLacSessionWorkQ =
+	    create_singlethread_workqueue("ocfLacDeregWorkQueue");
+
+	return 0;
+}
+
+/* Name        : icp_ocfDrvExit
+ *
+ * Description : This function will deregister all the symmetric sessions
+ * registered with the LAC component. It will also deregister all symmetric
+ * and asymmetric functionality that can be accelerated by the hardware via OCF
+ * and random number generation if it is enabled.
+ */
+static void icp_ocfDrvExit(void)
+{
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	struct icp_drvSessionData *sessionData = NULL;
+	struct icp_drvSessionData *tempSessionData = NULL;
+	int i, remaining_delay_time_in_jiffies = 0;
+	/* There is a possibility of a process or new session command being   */
+	/* sent before this variable is incremented. The aim of this variable */
+	/* is to stop a loop of calls creating a deadlock situation which     */
+	/* would prevent the driver from exiting.                             */
+
+	atomic_inc(&icp_ocfDrvIsExiting);
+
+	/*Existing sessions will be routed to another driver after these calls */
+	crypto_unregister_all(icp_ocfDrvDriverId);
+	crypto_runregister_all(icp_ocfDrvDriverId);
+
+	/*If any sessions are waiting to be deregistered, do that. This also 
+	   flushes the work queue */
+	destroy_workqueue(icp_ocfDrvFreeLacSessionWorkQ);
+
+	/*ENTER CRITICAL SECTION */
+	spin_lock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
+	list_for_each_entry_safe(tempSessionData, sessionData,
+				 &icp_ocfDrvGlobalSymListHead, listNode) {
+		for (i = 0; i < num_dereg_retries; i++) {
+			/*No harm if bad input - LAC will handle error cases */
+			if (ICP_SESSION_RUNNING == tempSessionData->inUse) {
+				lacStatus =
+				    cpaCySymRemoveSession
+				    (CPA_INSTANCE_HANDLE_SINGLE,
+				     tempSessionData->sessHandle);
+				if (CPA_STATUS_SUCCESS == lacStatus) {
+					/* Succesfully deregistered */
+					break;
+				} else if (CPA_STATUS_RETRY != lacStatus) {
+					atomic_inc
+					    (&lac_session_failed_dereg_count);
+					break;
+				}
+
+				/*schedule_timout returns the time left for completion if 
+				 * this task is set to TASK_INTERRUPTIBLE */
+				remaining_delay_time_in_jiffies =
+				    dereg_retry_delay_in_jiffies;
+				while (0 > remaining_delay_time_in_jiffies) {
+					remaining_delay_time_in_jiffies =
+					    schedule_timeout
+					    (remaining_delay_time_in_jiffies);
+				}
+
+				DPRINTK
+				    ("%s(): Retry %d to deregistrate the session\n",
+				     __FUNCTION__, i);
+			}
+		}
+
+		/*remove from current list */
+		list_del(&(tempSessionData->listNode));
+		/*add to free mem linked list */
+		list_add(&(tempSessionData->listNode),
+			 &icp_ocfDrvGlobalSymListHead_FreeMemList);
+
+	}
+
+	/*EXIT CRITICAL SECTION */
+	spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
+
+	/*set back to initial values */
+	sessionData = NULL;
+	/*still have a reference in our list! */
+	tempSessionData = NULL;
+	/*free memory */
+	list_for_each_entry_safe(tempSessionData, sessionData,
+				 &icp_ocfDrvGlobalSymListHead_FreeMemList,
+				 listNode) {
+
+		list_del(&(tempSessionData->listNode));
+		/* Free allocated CpaCySymSessionCtx */
+		if (NULL != tempSessionData->sessHandle) {
+			kfree(tempSessionData->sessHandle);
+		}
+		memset(tempSessionData, 0, sizeof(struct icp_drvSessionData));
+		kmem_cache_free(drvSessionData_zone, tempSessionData);
+	}
+
+	if (0 != atomic_read(&lac_session_failed_dereg_count)) {
+		DPRINTK("%s(): %d LAC sessions were not deregistered "
+			"correctly. This is not a clean exit! \n",
+			__FUNCTION__,
+			atomic_read(&lac_session_failed_dereg_count));
+	}
+
+	icp_ocfDrvFreeCaches();
+	icp_ocfDrvDriverId = INVALID_DRIVER_ID;
+
+	/* Shutdown the Cryptographic component */
+	lacStatus = cpaCyStopInstance(CPA_INSTANCE_HANDLE_SINGLE);
+	if (CPA_STATUS_SUCCESS != lacStatus) {
+		DPRINTK("%s(): Failed to stop instance of the "
+			"Cryptographic component.(status == %d)\n",
+			__FUNCTION__, lacStatus);
+	}
+
+}
+
+/* Name        : icp_ocfDrvFreeCaches
+ *
+ * Description : This function deregisters all slab caches
+ */
+static void icp_ocfDrvFreeCaches(void)
+{
+	if (atomic_read(&icp_ocfDrvIsExiting) != CPA_TRUE) {
+		atomic_set(&icp_ocfDrvIsExiting, 1);
+	}
+
+	/*Sym Zones */
+	ICP_CACHE_DESTROY(drvSessionData_zone);
+	ICP_CACHE_DESTROY(drvOpData_zone);
+
+	/*Asym zones */
+	ICP_CACHE_DESTROY(drvDH_zone);
+	ICP_CACHE_DESTROY(drvLnModExp_zone);
+	ICP_CACHE_DESTROY(drvRSADecrypt_zone);
+	ICP_CACHE_DESTROY(drvRSAPrivateKey_zone);
+	ICP_CACHE_DESTROY(drvDSARSSignKValue_zone);
+	ICP_CACHE_DESTROY(drvDSARSSign_zone);
+	ICP_CACHE_DESTROY(drvDSAVerify_zone);
+
+	/*FlatBuffer and BufferList Zones */
+	ICP_CACHE_DESTROY(drvFlatBuffer_zone);
+
+}
+
+/* Name        : icp_ocfDrvDeregRetry
+ *
+ * Description : This function will try to farm the session deregistration
+ * off to a work queue. If it fails, nothing more can be done and it
+ * returns an error
+ */
+
+int icp_ocfDrvDeregRetry(CpaCySymSessionCtx sessionToDeregister)
+{
+	struct icp_ocfDrvFreeLacSession *workstore = NULL;
+
+	DPRINTK("%s(): Retry - Deregistering session (%p)\n",
+		__FUNCTION__, sessionToDeregister);
+
+	/*make sure the session is not available to be allocated during this
+	   process */
+	atomic_inc(&lac_session_failed_dereg_count);
+
+	/*Farm off to work queue */
+	workstore =
+	    kmalloc(sizeof(struct icp_ocfDrvFreeLacSession), GFP_ATOMIC);
+	if (NULL == workstore) {
+		DPRINTK("%s(): unable to free session - no memory available "
+			"for work queue\n", __FUNCTION__);
+		return ENOMEM;
+	}
+
+	workstore->sessionToDeregister = sessionToDeregister;
+
+	INIT_WORK(&(workstore->work), icp_ocfDrvDeferedFreeLacSessionProcess,
+		  workstore);
+	queue_work(icp_ocfDrvFreeLacSessionWorkQ, &(workstore->work));
+
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+
+}
+
+/* Name        : icp_ocfDrvDeferedFreeLacSessionProcess
+ *
+ * Description : This function will retry (module input parameter)
+ * 'num_dereg_retries' times to deregister any symmetric session that recieves a
+ * CPA_STATUS_RETRY message from the LAC component. This function is run in
+ * Thread context because it is called from a worker thread
+ */
+static void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg)
+{
+	struct icp_ocfDrvFreeLacSession *workstore = NULL;
+	CpaCySymSessionCtx sessionToDeregister = NULL;
+	int i = 0;
+	int remaining_delay_time_in_jiffies = 0;
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+
+	workstore = (struct icp_ocfDrvFreeLacSession *)arg;
+	if (NULL == workstore) {
+		DPRINTK("%s() function called with null parameter \n",
+			__FUNCTION__);
+		return;
+	}
+
+	sessionToDeregister = workstore->sessionToDeregister;
+	kfree(workstore);
+
+	/*if exiting, give deregistration one more blast only */
+	if (atomic_read(&icp_ocfDrvIsExiting) == CPA_TRUE) {
+		lacStatus = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE,
+						  sessionToDeregister);
+
+		if (lacStatus != CPA_STATUS_SUCCESS) {
+			DPRINTK("%s() Failed to Dereg LAC session %p "
+				"during module exit\n", __FUNCTION__,
+				sessionToDeregister);
+			return;
+		}
+
+		atomic_dec(&lac_session_failed_dereg_count);
+		return;
+	}
+
+	for (i = 0; i <= num_dereg_retries; i++) {
+		lacStatus = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE,
+						  sessionToDeregister);
+
+		if (lacStatus == CPA_STATUS_SUCCESS) {
+			atomic_dec(&lac_session_failed_dereg_count);
+			return;
+		}
+		if (lacStatus != CPA_STATUS_RETRY) {
+			DPRINTK("%s() Failed to deregister session - lacStatus "
+				" = %d", __FUNCTION__, lacStatus);
+			break;
+		}
+
+		/*schedule_timout returns the time left for completion if this
+		   task is set to TASK_INTERRUPTIBLE */
+		remaining_delay_time_in_jiffies = dereg_retry_delay_in_jiffies;
+		while (0 > remaining_delay_time_in_jiffies) {
+			remaining_delay_time_in_jiffies =
+			    schedule_timeout(remaining_delay_time_in_jiffies);
+		}
+
+	}
+
+	DPRINTK("%s(): Unable to deregister session\n", __FUNCTION__);
+	DPRINTK("%s(): Number of unavailable LAC sessions = %d\n", __FUNCTION__,
+		atomic_read(&lac_session_failed_dereg_count));
+}
+
+/* Name        : icp_ocfDrvPtrAndLenToFlatBuffer 
+ *
+ * Description : This function converts a "pointer and length" buffer 
+ * structure to Fredericksburg Flat Buffer (CpaFlatBuffer) format.
+ *
+ * This function assumes that the data passed in are valid.
+ */
+inline void
+icp_ocfDrvPtrAndLenToFlatBuffer(void *pData, uint32_t len,
+				CpaFlatBuffer * pFlatBuffer)
+{
+	pFlatBuffer->pData = pData;
+	pFlatBuffer->dataLenInBytes = len;
+}
+
+/* Name        : icp_ocfDrvSingleSkBuffToFlatBuffer 
+ *
+ * Description : This function converts a single socket buffer (sk_buff)
+ * structure to a Fredericksburg Flat Buffer (CpaFlatBuffer) format.
+ *
+ * This function assumes that the data passed in are valid.
+ */
+static inline void
+icp_ocfDrvSingleSkBuffToFlatBuffer(struct sk_buff *pSkb,
+				   CpaFlatBuffer * pFlatBuffer)
+{
+	pFlatBuffer->pData = pSkb->data;
+	pFlatBuffer->dataLenInBytes = skb_headlen(pSkb);
+}
+
+/* Name        : icp_ocfDrvSkBuffToBufferList 
+ *
+ * Description : This function converts a socket buffer (sk_buff) structure to
+ * Fredericksburg Scatter/Gather (CpaBufferList) buffer format.
+ *
+ * This function assumes that the bufferlist has been allocated with the correct
+ * number of buffer arrays.
+ * 
+ */
+inline int
+icp_ocfDrvSkBuffToBufferList(struct sk_buff *pSkb, CpaBufferList * bufferList)
+{
+	CpaFlatBuffer *curFlatBuffer = NULL;
+	char *skbuffPageAddr = NULL;
+	struct sk_buff *pCurFrag = NULL;
+	struct skb_shared_info *pShInfo = NULL;
+	uint32_t page_offset = 0, i = 0;
+
+	DPRINTK("%s(): Entry Point\n", __FUNCTION__);
+
+	/*
+	 * In all cases, the first skb needs to be translated to FlatBuffer.
+	 * Perform a buffer translation for the first skbuff
+	 */
+	curFlatBuffer = bufferList->pBuffers;
+	icp_ocfDrvSingleSkBuffToFlatBuffer(pSkb, curFlatBuffer);
+
+	/* Set the userData to point to the original sk_buff */
+	bufferList->pUserData = (void *)pSkb;
+
+	/* We now know we'll have at least one element in the SGL */
+	bufferList->numBuffers = 1;
+
+	if (0 == skb_is_nonlinear(pSkb)) {
+		/* Is a linear buffer - therefore it's a single skbuff */
+		DPRINTK("%s(): Exit Point\n", __FUNCTION__);
+		return ICP_OCF_DRV_STATUS_SUCCESS;
+	}
+
+	curFlatBuffer++;
+	pShInfo = skb_shinfo(pSkb);
+	if (pShInfo->frag_list != NULL && pShInfo->nr_frags != 0) {
+		EPRINTK("%s():"
+			"Translation for a combination of frag_list "
+			"and frags[] array not supported!\n", __FUNCTION__);
+		return ICP_OCF_DRV_STATUS_FAIL;
+	} else if (pShInfo->frag_list != NULL) {
+		/*
+		 * Non linear skbuff supported through frag_list 
+		 * Perform translation for each fragment (sk_buff)
+		 * in the frag_list of the first sk_buff.
+		 */
+		for (pCurFrag = pShInfo->frag_list;
+		     pCurFrag != NULL; pCurFrag = pCurFrag->next) {
+			icp_ocfDrvSingleSkBuffToFlatBuffer(pCurFrag,
+							   curFlatBuffer);
+			curFlatBuffer++;
+			bufferList->numBuffers++;
+		}
+	} else if (pShInfo->nr_frags != 0) {
+		/*
+		 * Perform translation for each fragment in frags array
+		 * and add to the BufferList
+		 */
+		for (i = 0; i < pShInfo->nr_frags; i++) {
+			/* Get the page address and offset of this frag */
+			skbuffPageAddr = (char *)pShInfo->frags[i].page;
+			page_offset = pShInfo->frags[i].page_offset;
+
+			/* Convert a pointer and length to a flat buffer */
+			icp_ocfDrvPtrAndLenToFlatBuffer(skbuffPageAddr +
+							page_offset,
+							pShInfo->frags[i].size,
+							curFlatBuffer);
+			curFlatBuffer++;
+			bufferList->numBuffers++;
+		}
+	} else {
+		EPRINTK("%s():" "Could not recognize skbuff fragments!\n",
+			__FUNCTION__);
+		return ICP_OCF_DRV_STATUS_FAIL;
+	}
+
+	DPRINTK("%s(): Exit Point\n", __FUNCTION__);
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvBufferListToSkBuff 
+ *
+ * Description : This function converts a Fredericksburg Scatter/Gather 
+ * (CpaBufferList) buffer format to socket buffer structure.
+ */
+inline int
+icp_ocfDrvBufferListToSkBuff(CpaBufferList * bufferList, struct sk_buff **skb)
+{
+	DPRINTK("%s(): Entry Point\n", __FUNCTION__);
+
+	/* Retrieve the orignal skbuff */
+	*skb = (struct sk_buff *)bufferList->pUserData;
+	if (NULL == *skb) {
+		EPRINTK("%s():"
+			"Error on converting from a BufferList. "
+			"The BufferList does not contain an sk_buff.\n",
+			__FUNCTION__);
+		return ICP_OCF_DRV_STATUS_FAIL;
+	}
+	DPRINTK("%s(): Exit Point\n", __FUNCTION__);
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvPtrAndLenToBufferList
+ *
+ * Description : This function converts a "pointer and length" buffer
+ * structure to Fredericksburg Scatter/Gather Buffer (CpaBufferList) format.
+ *
+ * This function assumes that the data passed in are valid.
+ */
+inline void
+icp_ocfDrvPtrAndLenToBufferList(void *pDataIn, uint32_t length,
+				CpaBufferList * pBufferList)
+{
+	pBufferList->numBuffers = 1;
+	pBufferList->pBuffers->pData = pDataIn;
+	pBufferList->pBuffers->dataLenInBytes = length;
+}
+
+/* Name        : icp_ocfDrvBufferListToPtrAndLen
+ *
+ * Description : This function converts Fredericksburg Scatter/Gather Buffer
+ * (CpaBufferList) format to a "pointer and length" buffer structure.
+ *
+ * This function assumes that the data passed in are valid.
+ */
+inline void
+icp_ocfDrvBufferListToPtrAndLen(CpaBufferList * pBufferList,
+				void **ppDataOut, uint32_t * pLength)
+{
+	*ppDataOut = pBufferList->pBuffers->pData;
+	*pLength = pBufferList->pBuffers->dataLenInBytes;
+}
+
+/* Name        : icp_ocfDrvBufferListMemInfo
+ *
+ * Description : This function will set the number of flat buffers in 
+ * bufferlist, the size of memory to allocate for the pPrivateMetaData 
+ * member of the CpaBufferList.
+ */
+int
+icp_ocfDrvBufferListMemInfo(uint16_t numBuffers,
+			    struct icp_drvBuffListInfo *buffListInfo)
+{
+	buffListInfo->numBuffers = numBuffers;
+
+	if (CPA_STATUS_SUCCESS !=
+	    cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE,
+				       buffListInfo->numBuffers,
+				       &(buffListInfo->metaSize))) {
+		EPRINTK("%s() Failed to get buffer list meta size.\n",
+			__FUNCTION__);
+		return ICP_OCF_DRV_STATUS_FAIL;
+	}
+
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvGetSkBuffFrags
+ *
+ * Description : This function will determine the number of 
+ * fragments in a socket buffer(sk_buff).
+ */
+inline uint16_t icp_ocfDrvGetSkBuffFrags(struct sk_buff * pSkb)
+{
+	uint16_t numFrags = 0;
+	struct sk_buff *pCurFrag = NULL;
+	struct skb_shared_info *pShInfo = NULL;
+
+	if (NULL == pSkb)
+		return 0;
+
+	numFrags = 1;
+	if (0 == skb_is_nonlinear(pSkb)) {
+		/* Linear buffer - it's a single skbuff */
+		return numFrags;
+	}
+
+	pShInfo = skb_shinfo(pSkb);
+	if (NULL != pShInfo->frag_list && 0 != pShInfo->nr_frags) {
+		EPRINTK("%s(): Combination of frag_list "
+			"and frags[] array not supported!\n", __FUNCTION__);
+		return 0;
+	} else if (0 != pShInfo->nr_frags) {
+		numFrags += pShInfo->nr_frags;
+		return numFrags;
+	} else if (NULL != pShInfo->frag_list) {
+		for (pCurFrag = pShInfo->frag_list;
+		     pCurFrag != NULL; pCurFrag = pCurFrag->next) {
+			numFrags++;
+		}
+		return numFrags;
+	} else {
+		return 0;
+	}
+}
+
+/* Name        : icp_ocfDrvFreeFlatBuffer
+ *
+ * Description : This function will deallocate flat buffer.
+ */
+inline void icp_ocfDrvFreeFlatBuffer(CpaFlatBuffer * pFlatBuffer)
+{
+	if (pFlatBuffer != NULL) {
+		memset(pFlatBuffer, 0, sizeof(CpaFlatBuffer));
+		kmem_cache_free(drvFlatBuffer_zone, pFlatBuffer);
+	}
+}
+
+/* Name        : icp_ocfDrvAllocMetaData
+ *
+ * Description : This function will allocate memory for the
+ * pPrivateMetaData member of CpaBufferList.
+ */
+inline int
+icp_ocfDrvAllocMetaData(CpaBufferList * pBufferList,
+        const struct icp_drvOpData *pOpData)
+{
+	Cpa32U metaSize = 0;
+
+	if (pBufferList->numBuffers <= ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS){
+	    void *pOpDataStartAddr = (void *)pOpData;
+
+	    if (0 == defBuffListInfo.metaSize) {
+			pBufferList->pPrivateMetaData = NULL;
+			return ICP_OCF_DRV_STATUS_SUCCESS;
+		}
+		/*
+		 * The meta data allocation has been included as part of the 
+		 * op data.  It has been pre-allocated in memory just after the
+		 * icp_drvOpData structure.
+		 */
+		pBufferList->pPrivateMetaData = pOpDataStartAddr +
+		        sizeof(struct icp_drvOpData);
+	} else {
+		if (CPA_STATUS_SUCCESS !=
+		    cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE,
+					       pBufferList->numBuffers,
+					       &metaSize)) {
+			EPRINTK("%s() Failed to get buffer list meta size.\n",
+				__FUNCTION__);
+			return ICP_OCF_DRV_STATUS_FAIL;
+		}
+
+		if (0 == metaSize) {
+			pBufferList->pPrivateMetaData = NULL;
+			return ICP_OCF_DRV_STATUS_SUCCESS;
+		}
+
+		pBufferList->pPrivateMetaData = kmalloc(metaSize, GFP_ATOMIC);
+	}
+	if (NULL == pBufferList->pPrivateMetaData) {
+		EPRINTK("%s() Failed to allocate pPrivateMetaData.\n",
+			__FUNCTION__);
+		return ICP_OCF_DRV_STATUS_FAIL;
+	}
+
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvFreeMetaData
+ *
+ * Description : This function will deallocate pPrivateMetaData memory.
+ */
+inline void icp_ocfDrvFreeMetaData(CpaBufferList * pBufferList)
+{
+	if (NULL == pBufferList->pPrivateMetaData) {
+		return;
+	}
+
+	/*
+	 * Only free the meta data if the BufferList has more than 
+	 * ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS number of buffers.
+	 * Otherwise, the meta data shall be freed when the icp_drvOpData is
+	 * freed.
+	 */
+	if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS < pBufferList->numBuffers){
+		kfree(pBufferList->pPrivateMetaData);
+	}
+}
+
+module_init(icp_ocfDrvInit);
+module_exit(icp_ocfDrvExit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Intel");
+MODULE_DESCRIPTION("OCF Driver for Intel Quick Assist crypto acceleration");
diff --git a/crypto/ocf/ep80579/icp_ocf.h b/crypto/ocf/ep80579/icp_ocf.h
new file mode 100755
index 0000000..dff0a8b
--- /dev/null
+++ b/crypto/ocf/ep80579/icp_ocf.h
@@ -0,0 +1,363 @@
+/***************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or 
+ *   redistributing this file, you may do so under either license.
+ * 
+ *   GPL LICENSE SUMMARY
+ * 
+ *   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+ * 
+ *   This program is free software; you can redistribute it and/or modify 
+ *   it under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ * 
+ *   This program is distributed in the hope that it will be useful, but 
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+ *   General Public License for more details.
+ * 
+ *   You should have received a copy of the GNU General Public License 
+ *   along with this program; if not, write to the Free Software 
+ *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *   The full GNU General Public License is included in this distribution 
+ *   in the file called LICENSE.GPL.
+ * 
+ *   Contact Information:
+ *   Intel Corporation
+ * 
+ *   BSD LICENSE 
+ * 
+ *   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without 
+ *   modification, are permitted provided that the following conditions 
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright 
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright 
+ *       notice, this list of conditions and the following disclaimer in 
+ *       the documentation and/or other materials provided with the 
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its 
+ *       contributors may be used to endorse or promote products derived 
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ *  version: Security.L.1.0.130
+ *
+ ***************************************************************************/
+
+/*
+ * OCF drv driver header file for the Intel ICP processor.
+ */
+
+#ifndef ICP_OCF_H
+#define ICP_OCF_H
+
+#include <linux/crypto.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+
+#include "cryptodev.h"
+#include "uio.h"
+
+#include "cpa.h"
+#include "cpa_cy_im.h"
+#include "cpa_cy_sym.h"
+#include "cpa_cy_rand.h"
+#include "cpa_cy_dh.h"
+#include "cpa_cy_rsa.h"
+#include "cpa_cy_ln.h"
+#include "cpa_cy_common.h"
+#include "cpa_cy_dsa.h"
+
+#define NUM_BITS_IN_BYTE (8)
+#define NUM_BITS_IN_BYTE_MINUS_ONE (NUM_BITS_IN_BYTE -1)
+#define INVALID_DRIVER_ID (-1)
+#define RETURN_RAND_NUM_GEN_FAILED (-1)
+
+/*This is define means only one operation can be chained to another
+(resulting in one chain of two operations)*/
+#define MAX_NUM_OF_CHAINED_OPS (1)
+/*This is the max block cipher initialisation vector*/
+#define MAX_IV_LEN_IN_BYTES (20)
+/*This is used to check whether the OCF to this driver session limit has
+  been disabled*/
+#define NO_OCF_TO_DRV_MAX_SESSIONS		(0)
+
+/*OCF values mapped here*/
+#define ICP_SHA1_DIGEST_SIZE_IN_BYTES 		(SHA1_HASH_LEN)
+#define ICP_SHA256_DIGEST_SIZE_IN_BYTES 	(SHA2_256_HASH_LEN)
+#define ICP_SHA384_DIGEST_SIZE_IN_BYTES 	(SHA2_384_HASH_LEN)
+#define ICP_SHA512_DIGEST_SIZE_IN_BYTES 	(SHA2_512_HASH_LEN)
+#define ICP_MD5_DIGEST_SIZE_IN_BYTES 		(MD5_HASH_LEN)
+#define ARC4_COUNTER_LEN 			(ARC4_BLOCK_LEN)
+
+#define OCF_REGISTRATION_STATUS_SUCCESS 	(0)
+#define OCF_ZERO_FUNCTIONALITY_REGISTERED 	(0)
+#define ICP_OCF_DRV_NO_CRYPTO_PROCESS_ERROR 	(0)
+#define ICP_OCF_DRV_STATUS_SUCCESS 		(0)
+#define ICP_OCF_DRV_STATUS_FAIL 		(1)
+
+/*Turn on/off debug options*/
+#define ICP_OCF_PRINT_DEBUG_MESSAGES		(0)
+#define ICP_OCF_PRINT_KERN_ALERT		(1)
+#define ICP_OCF_PRINT_KERN_ERRS			(1)
+
+/*DSA Prime Q size in bytes (as defined in the standard) */
+#define DSA_RS_SIGN_PRIMEQ_SIZE_IN_BYTES	(20)
+
+/*MACRO DEFINITIONS*/
+
+#define BITS_TO_BYTES(bytes, bits) 					\
+	bytes = (bits + NUM_BITS_IN_BYTE_MINUS_ONE) / NUM_BITS_IN_BYTE
+
+#define ICP_CACHE_CREATE(cache_ID, cache_name) 				\
+	kmem_cache_create(cache_ID, sizeof(cache_name),0, 		\
+		SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+#define ICP_CACHE_NULL_CHECK(slab_zone)					\
+{									\
+	if(NULL == slab_zone){ 						\
+		icp_ocfDrvFreeCaches(); 				\
+		EPRINTK("%s() line %d: Not enough memory!\n", 		\
+			__FUNCTION__, __LINE__); 			\
+		return ENOMEM; 						\
+	}								\
+}
+
+#define ICP_CACHE_DESTROY(slab_zone) 	                                \
+{                                                                       \
+        if(NULL != slab_zone){						\
+                kmem_cache_destroy(slab_zone);				\
+                slab_zone = NULL;					\
+        }								\
+}
+
+#define ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(alg)			\
+{									\
+	if(OCF_REGISTRATION_STATUS_SUCCESS ==				\
+		crypto_register(icp_ocfDrvDriverId,			\
+				    alg,				\
+				    0,					\
+				    0)) {				\
+		ocfStatus++;						\
+	}								\
+}
+
+#define ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(alg)			\
+{									\
+	if(OCF_REGISTRATION_STATUS_SUCCESS ==				\
+		crypto_kregister(icp_ocfDrvDriverId,			\
+				      alg,				\
+				      0)){				\
+		ocfStatus++;						\
+	}								\
+}
+
+#if ICP_OCF_PRINT_DEBUG_MESSAGES == 1
+#define DPRINTK(args...)      \
+{			      \
+                printk(args); \
+}
+
+#else				//ICP_OCF_PRINT_DEBUG_MESSAGES == 1
+
+#define DPRINTK(args...)
+
+#endif				//ICP_OCF_PRINT_DEBUG_MESSAGES == 1
+
+#if ICP_OCF_PRINT_KERN_ALERT == 1
+#define APRINTK(args...)      						\
+{			      						\
+       printk(KERN_ALERT args);						\
+}
+
+#else				//ICP_OCF_PRINT_KERN_ALERT == 1
+
+#define APRINTK(args...)
+
+#endif				//ICP_OCF_PRINT_KERN_ALERT == 1
+
+#if ICP_OCF_PRINT_KERN_ERRS == 1
+#define EPRINTK(args...)      \
+{			      \
+       printk(KERN_ERR args); \
+}
+
+#else				//ICP_OCF_PRINT_KERN_ERRS == 1
+
+#define EPRINTK(args...)
+
+#endif				//ICP_OCF_PRINT_KERN_ERRS == 1
+
+#define IPRINTK(args...)      \
+{			      \
+      printk(KERN_INFO args); \
+}
+
+/*END OF MACRO DEFINITIONS*/
+
+typedef enum {
+	ICP_OCF_DRV_ALG_CIPHER = 0,
+	ICP_OCF_DRV_ALG_HASH
+} icp_ocf_drv_alg_type_t;
+
+/* These are all defined in icp_common.c */
+extern atomic_t lac_session_failed_dereg_count;
+extern atomic_t icp_ocfDrvIsExiting;
+extern atomic_t num_ocf_to_drv_registered_sessions;
+
+/*These are use inputs used in icp_sym.c and icp_common.c
+  They are instantiated in icp_common.c*/
+extern int max_sessions;
+
+extern int32_t icp_ocfDrvDriverId;
+extern struct list_head icp_ocfDrvGlobalSymListHead;
+extern struct list_head icp_ocfDrvGlobalSymListHead_FreeMemList;
+extern struct workqueue_struct *icp_ocfDrvFreeLacSessionWorkQ;
+extern spinlock_t icp_ocfDrvSymSessInfoListSpinlock;
+extern rwlock_t icp_kmem_cache_destroy_alloc_lock;
+
+/*Slab zones for symettric functionality, instantiated in icp_common.c*/
+extern struct kmem_cache *drvSessionData_zone;
+extern struct kmem_cache *drvOpData_zone;
+
+/*Slabs zones for asymettric functionality, instantiated in icp_common.c*/
+extern struct kmem_cache *drvDH_zone;
+extern struct kmem_cache *drvLnModExp_zone;
+extern struct kmem_cache *drvRSADecrypt_zone;
+extern struct kmem_cache *drvRSAPrivateKey_zone;
+extern struct kmem_cache *drvDSARSSign_zone;
+extern struct kmem_cache *drvDSARSSignKValue_zone;
+extern struct kmem_cache *drvDSAVerify_zone;
+
+/*Slab zones for flatbuffers and bufferlist*/
+extern struct kmem_cache *drvFlatBuffer_zone;
+
+#define ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS     (16)
+
+struct icp_drvBuffListInfo {
+	Cpa16U numBuffers;
+	Cpa32U metaSize;
+	Cpa32U metaOffset;
+	Cpa32U buffListSize;
+};
+extern struct icp_drvBuffListInfo defBuffListInfo;
+
+/*
+* This struct is used to keep a reference to the relevant node in the list
+* of sessionData structs, to the buffer type required by OCF and to the OCF
+* provided crp struct that needs to be returned. All this info is needed in
+* the callback function.
+*
+* IV can sometimes be stored in non-contiguous memory (e.g. skbuff
+* linked/frag list, therefore a contiguous memory space for the IV data must be
+* created and passed to LAC
+*
+*/
+struct icp_drvOpData {
+	CpaCySymOpData lacOpData;
+	uint32_t digestSizeInBytes;
+	struct cryptop *crp;
+	uint8_t bufferType;
+	uint8_t ivData[MAX_IV_LEN_IN_BYTES];
+	uint16_t numBufferListArray;
+	CpaBufferList srcBuffer;
+	CpaFlatBuffer bufferListArray[ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS];
+	CpaBoolean verifyResult;
+};
+/*Values used to derisk chances of performs being called against
+deregistered sessions (for which the slab page has been reclaimed)
+This is not a fix - since page frames are reclaimed from a slab, one cannot
+rely on that memory not being re-used by another app.*/
+typedef enum {
+	ICP_SESSION_INITIALISED = 0x5C5C5C,
+	ICP_SESSION_RUNNING = 0x005C00,
+	ICP_SESSION_DEREGISTERED = 0xC5C5C5
+} usage_derisk;
+
+/*
+This is the OCF<->OCF_DRV session object:
+
+1.The first member is a listNode. These session objects are added to a linked
+  list in order to make it easier to remove them all at session exit time.
+2.The second member is used to give the session object state and derisk the
+  possibility of OCF batch calls executing against a deregistered session (as
+  described above).
+3.The third member is a LAC<->OCF_DRV session handle (initialised with the first
+  perform request for that session).
+4.The fourth is the LAC session context. All the parameters for this structure
+  are only known when the first perform request for this session occurs. That is
+  why the OCF Tolapai Driver only registers a new LAC session at perform time
+*/
+struct icp_drvSessionData {
+	struct list_head listNode;
+	usage_derisk inUse;
+	CpaCySymSessionCtx sessHandle;
+	CpaCySymSessionSetupData lacSessCtx;
+};
+
+/* This struct is required for deferred session
+ deregistration as a work queue function can
+ only have one argument*/
+struct icp_ocfDrvFreeLacSession {
+	CpaCySymSessionCtx sessionToDeregister;
+	struct work_struct work;
+};
+
+int icp_ocfDrvNewSession(device_t dev, uint32_t * sild, struct cryptoini *cri);
+
+int icp_ocfDrvFreeLACSession(device_t dev, uint64_t sid);
+
+int icp_ocfDrvSymProcess(device_t dev, struct cryptop *crp, int hint);
+
+int icp_ocfDrvPkeProcess(device_t dev, struct cryptkop *krp, int hint);
+
+int icp_ocfDrvReadRandom(void *arg, uint32_t * buf, int maxwords);
+
+int icp_ocfDrvDeregRetry(CpaCySymSessionCtx sessionToDeregister);
+
+int icp_ocfDrvSkBuffToBufferList(struct sk_buff *skb,
+				 CpaBufferList * bufferList);
+
+int icp_ocfDrvBufferListToSkBuff(CpaBufferList * bufferList,
+				 struct sk_buff **skb);
+
+void icp_ocfDrvPtrAndLenToFlatBuffer(void *pData, uint32_t len,
+				     CpaFlatBuffer * pFlatBuffer);
+
+void icp_ocfDrvPtrAndLenToBufferList(void *pDataIn, uint32_t length,
+				     CpaBufferList * pBufferList);
+
+void icp_ocfDrvBufferListToPtrAndLen(CpaBufferList * pBufferList,
+				     void **ppDataOut, uint32_t * pLength);
+
+int icp_ocfDrvBufferListMemInfo(uint16_t numBuffers,
+				struct icp_drvBuffListInfo *buffListInfo);
+
+uint16_t icp_ocfDrvGetSkBuffFrags(struct sk_buff *pSkb);
+
+void icp_ocfDrvFreeFlatBuffer(CpaFlatBuffer * pFlatBuffer);
+
+int icp_ocfDrvAllocMetaData(CpaBufferList * pBufferList, 
+                const struct icp_drvOpData *pOpData);
+
+void icp_ocfDrvFreeMetaData(CpaBufferList * pBufferList);
+
+#endif
+/* ICP_OCF_H */
diff --git a/crypto/ocf/ep80579/icp_sym.c b/crypto/ocf/ep80579/icp_sym.c
new file mode 100755
index 0000000..d632970
--- /dev/null
+++ b/crypto/ocf/ep80579/icp_sym.c
@@ -0,0 +1,1382 @@
+/***************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or 
+ *   redistributing this file, you may do so under either license.
+ * 
+ *   GPL LICENSE SUMMARY
+ * 
+ *   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+ * 
+ *   This program is free software; you can redistribute it and/or modify 
+ *   it under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ * 
+ *   This program is distributed in the hope that it will be useful, but 
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+ *   General Public License for more details.
+ * 
+ *   You should have received a copy of the GNU General Public License 
+ *   along with this program; if not, write to the Free Software 
+ *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *   The full GNU General Public License is included in this distribution 
+ *   in the file called LICENSE.GPL.
+ * 
+ *   Contact Information:
+ *   Intel Corporation
+ * 
+ *   BSD LICENSE 
+ * 
+ *   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without 
+ *   modification, are permitted provided that the following conditions 
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright 
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright 
+ *       notice, this list of conditions and the following disclaimer in 
+ *       the documentation and/or other materials provided with the 
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its 
+ *       contributors may be used to endorse or promote products derived 
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ *  version: Security.L.1.0.130
+ *
+ ***************************************************************************/
+/*
+ * An OCF module that uses the API for Intel® QuickAssist Technology to do the
+ * cryptography.
+ *
+ * This driver requires the ICP Access Library that is available from Intel in
+ * order to operate.
+ */
+
+#include "icp_ocf.h"
+
+/*This is the call back function for all symmetric cryptographic processes.
+  Its main functionality is to free driver crypto operation structure and to 
+  call back to OCF*/
+static void
+icp_ocfDrvSymCallBack(void *callbackTag,
+		      CpaStatus status,
+		      const CpaCySymOp operationType,
+		      void *pOpData,
+		      CpaBufferList * pDstBuffer, CpaBoolean verifyResult);
+
+/*This function is used to extract crypto processing information from the OCF
+  inputs, so as that it may be passed onto LAC*/
+static int
+icp_ocfDrvProcessDataSetup(struct icp_drvOpData *drvOpData,
+			   struct cryptodesc *crp_desc);
+
+/*This function checks whether the crp_desc argument pertains to a digest or a
+  cipher operation*/
+static int icp_ocfDrvAlgCheck(struct cryptodesc *crp_desc);
+
+/*This function copies all the passed in session context information and stores
+  it in a LAC context structure*/
+static int
+icp_ocfDrvAlgorithmSetup(struct cryptoini *cri,
+			 CpaCySymSessionSetupData * lacSessCtx);
+
+/*This top level function is used to find a pointer to where a digest is 
+  stored/needs to be inserted. */
+static uint8_t *icp_ocfDrvDigestPointerFind(struct icp_drvOpData *drvOpData,
+					    struct cryptodesc *crp_desc);
+
+/*This function is called when a digest pointer has to be found within a
+  SKBUFF.*/
+static inline uint8_t *icp_ocfDrvSkbuffDigestPointerFind(struct icp_drvOpData
+							 *drvOpData,
+							 int offsetInBytes,
+							 uint32_t
+							 digestSizeInBytes);
+
+/*The following two functions are called if the SKBUFF digest pointer is not 
+  positioned in the linear portion of the buffer (i.e. it is in a linked SKBUFF
+   or page fragment).*/
+/*This function takes care of the page fragment case.*/
+static inline uint8_t *icp_ocfDrvDigestSkbNRFragsCheck(struct sk_buff *skb,
+						       struct skb_shared_info
+						       *skb_shared,
+						       int offsetInBytes,
+						       uint32_t
+						       digestSizeInBytes);
+
+/*This function takes care of the linked list case.*/
+static inline uint8_t *icp_ocfDrvDigestSkbFragListCheck(struct sk_buff *skb,
+							struct skb_shared_info
+							*skb_shared,
+							int offsetInBytes,
+							uint32_t
+							digestSizeInBytes);
+
+/*This function is used to free an OCF->OCF_DRV session object*/
+static void icp_ocfDrvFreeOCFSession(struct icp_drvSessionData *sessionData);
+
+/*max IOV buffs supported in a UIO structure*/
+#define NUM_IOV_SUPPORTED		(1)
+
+/* Name        : icp_ocfDrvSymCallBack
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the relevant symmetric operation. 
+ *
+ * Notes : The callbackTag is a pointer to an icp_drvOpData. This memory
+ * object was passed to LAC for the cryptographic processing and contains all
+ * the relevant information for cleaning up buffer handles etc. so that the
+ * OCF Tolapai Driver portion of this crypto operation can be fully completed.
+ */
+static void
+icp_ocfDrvSymCallBack(void *callbackTag,
+		      CpaStatus status,
+		      const CpaCySymOp operationType,
+		      void *pOpData,
+		      CpaBufferList * pDstBuffer, CpaBoolean verifyResult)
+{
+	struct cryptop *crp = NULL;
+	struct icp_drvOpData *temp_drvOpData =
+	    (struct icp_drvOpData *)callbackTag;
+	uint64_t *tempBasePtr = NULL;
+	uint32_t tempLen = 0;
+
+	if (NULL == temp_drvOpData) {
+		DPRINTK("%s(): The callback from the LAC component"
+			" has failed due to Null userOpaque data"
+			"(status == %d).\n", __FUNCTION__, status);
+		DPRINTK("%s(): Unable to call OCF back! \n", __FUNCTION__);
+		return;
+	}
+
+	crp = temp_drvOpData->crp;
+	crp->crp_etype = ICP_OCF_DRV_NO_CRYPTO_PROCESS_ERROR;
+
+	if (NULL == pOpData) {
+		DPRINTK("%s(): The callback from the LAC component"
+			" has failed due to Null Symmetric Op data"
+			"(status == %d).\n", __FUNCTION__, status);
+		crp->crp_etype = ECANCELED;
+		crypto_done(crp);
+		return;
+	}
+
+	if (NULL == pDstBuffer) {
+		DPRINTK("%s(): The callback from the LAC component"
+			" has failed due to Null Dst Bufferlist data"
+			"(status == %d).\n", __FUNCTION__, status);
+		crp->crp_etype = ECANCELED;
+		crypto_done(crp);
+		return;
+	}
+
+	if (CPA_STATUS_SUCCESS == status) {
+
+		if (temp_drvOpData->bufferType == CRYPTO_F_SKBUF) {
+			if (ICP_OCF_DRV_STATUS_SUCCESS !=
+			    icp_ocfDrvBufferListToSkBuff(pDstBuffer,
+							 (struct sk_buff **)
+							 &(crp->crp_buf))) {
+				EPRINTK("%s(): BufferList to SkBuff "
+					"conversion error.\n", __FUNCTION__);
+				crp->crp_etype = EPERM;
+			}
+		} else {
+			icp_ocfDrvBufferListToPtrAndLen(pDstBuffer,
+							(void **)&tempBasePtr,
+							&tempLen);
+			crp->crp_olen = (int)tempLen;
+		}
+
+	} else {
+		DPRINTK("%s(): The callback from the LAC component has failed"
+			"(status == %d).\n", __FUNCTION__, status);
+
+		crp->crp_etype = ECANCELED;
+	}
+
+	if (temp_drvOpData->numBufferListArray >
+	    ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) {
+		kfree(pDstBuffer->pBuffers);
+	}
+	icp_ocfDrvFreeMetaData(pDstBuffer);
+	kmem_cache_free(drvOpData_zone, temp_drvOpData);
+
+	/* Invoke the OCF callback function */
+	crypto_done(crp);
+
+	return;
+}
+
+/* Name        : icp_ocfDrvNewSession 
+ *
+ * Description : This function will create a new Driver<->OCF session
+ *
+ * Notes : LAC session registration happens during the first perform call.
+ * That is the first time we know all information about a given session.
+ */
+int icp_ocfDrvNewSession(device_t dev, uint32_t * sid, struct cryptoini *cri)
+{
+	struct icp_drvSessionData *sessionData = NULL;
+	uint32_t delete_session = 0;
+
+	/* The SID passed in should be our driver ID. We can return the     */
+	/* local ID (LID) which is a unique identifier which we can use     */
+	/* to differentiate between the encrypt/decrypt LAC session handles */
+	if (NULL == sid) {
+		EPRINTK("%s(): Invalid input parameters - NULL sid.\n",
+			__FUNCTION__);
+		return EINVAL;
+	}
+
+	if (NULL == cri) {
+		EPRINTK("%s(): Invalid input parameters - NULL cryptoini.\n",
+			__FUNCTION__);
+		return EINVAL;
+	}
+
+	if (icp_ocfDrvDriverId != *sid) {
+		EPRINTK("%s(): Invalid input parameters - bad driver ID\n",
+			__FUNCTION__);
+		EPRINTK("\t sid = 0x08%p \n \t cri = 0x08%p \n", sid, cri);
+		return EINVAL;
+	}
+
+	sessionData = kmem_cache_zalloc(drvSessionData_zone, GFP_ATOMIC);
+	if (NULL == sessionData) {
+		DPRINTK("%s():No memory for Session Data\n", __FUNCTION__);
+		return ENOMEM;
+	}
+
+	/*ENTER CRITICAL SECTION */
+	spin_lock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
+	/*put this check in the spinlock so no new sessions can be added to the
+	   linked list when we are exiting */
+	if (CPA_TRUE == atomic_read(&icp_ocfDrvIsExiting)) {
+		delete_session++;
+
+	} else if (NO_OCF_TO_DRV_MAX_SESSIONS != max_sessions) {
+		if (atomic_read(&num_ocf_to_drv_registered_sessions) >=
+		    (max_sessions -
+		     atomic_read(&lac_session_failed_dereg_count))) {
+			delete_session++;
+		} else {
+			atomic_inc(&num_ocf_to_drv_registered_sessions);
+			/* Add to session data linked list */
+			list_add(&(sessionData->listNode),
+				 &icp_ocfDrvGlobalSymListHead);
+		}
+
+	} else if (NO_OCF_TO_DRV_MAX_SESSIONS == max_sessions) {
+		list_add(&(sessionData->listNode),
+			 &icp_ocfDrvGlobalSymListHead);
+	}
+
+	sessionData->inUse = ICP_SESSION_INITIALISED;
+
+	/*EXIT CRITICAL SECTION */
+	spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
+
+	if (delete_session) {
+		DPRINTK("%s():No Session handles available\n", __FUNCTION__);
+		kmem_cache_free(drvSessionData_zone, sessionData);
+		return EPERM;
+	}
+
+	if (ICP_OCF_DRV_STATUS_SUCCESS !=
+	    icp_ocfDrvAlgorithmSetup(cri, &(sessionData->lacSessCtx))) {
+		DPRINTK("%s():algorithm not supported\n", __FUNCTION__);
+		icp_ocfDrvFreeOCFSession(sessionData);
+		return EINVAL;
+	}
+
+	if (cri->cri_next) {
+		if (cri->cri_next->cri_next != NULL) {
+			DPRINTK("%s():only two chained algorithms supported\n",
+				__FUNCTION__);
+			icp_ocfDrvFreeOCFSession(sessionData);
+			return EPERM;
+		}
+
+		if (ICP_OCF_DRV_STATUS_SUCCESS !=
+		    icp_ocfDrvAlgorithmSetup(cri->cri_next,
+					     &(sessionData->lacSessCtx))) {
+			DPRINTK("%s():second algorithm not supported\n",
+				__FUNCTION__);
+			icp_ocfDrvFreeOCFSession(sessionData);
+			return EINVAL;
+		}
+
+		sessionData->lacSessCtx.symOperation =
+		    CPA_CY_SYM_OP_ALGORITHM_CHAINING;
+	}
+
+	*sid = (uint32_t) sessionData;
+
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvAlgorithmSetup
+ *
+ * Description : This function builds the session context data from the
+ * information supplied through OCF. Algorithm chain order and whether the
+ * session is Encrypt/Decrypt can only be found out at perform time however, so
+ * the session is registered with LAC at that time.
+ */
+static int
+icp_ocfDrvAlgorithmSetup(struct cryptoini *cri,
+			 CpaCySymSessionSetupData * lacSessCtx)
+{
+
+	lacSessCtx->sessionPriority = CPA_CY_PRIORITY_NORMAL;
+
+	switch (cri->cri_alg) {
+
+	case CRYPTO_NULL_CBC:
+		DPRINTK("%s(): NULL CBC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
+		lacSessCtx->cipherSetupData.cipherAlgorithm =
+		    CPA_CY_SYM_CIPHER_NULL;
+		lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
+		break;
+
+	case CRYPTO_DES_CBC:
+		DPRINTK("%s(): DES CBC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
+		lacSessCtx->cipherSetupData.cipherAlgorithm =
+		    CPA_CY_SYM_CIPHER_DES_CBC;
+		lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
+		break;
+
+	case CRYPTO_3DES_CBC:
+		DPRINTK("%s(): 3DES CBC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
+		lacSessCtx->cipherSetupData.cipherAlgorithm =
+		    CPA_CY_SYM_CIPHER_3DES_CBC;
+		lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
+		break;
+
+	case CRYPTO_AES_CBC:
+		DPRINTK("%s(): AES CBC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
+		lacSessCtx->cipherSetupData.cipherAlgorithm =
+		    CPA_CY_SYM_CIPHER_AES_CBC;
+		lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
+		break;
+
+	case CRYPTO_ARC4:
+		DPRINTK("%s(): ARC4\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
+		lacSessCtx->cipherSetupData.cipherAlgorithm =
+		    CPA_CY_SYM_CIPHER_ARC4;
+		lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
+		break;
+
+	case CRYPTO_SHA1:
+		DPRINTK("%s(): SHA1\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_SHA1_DIGEST_SIZE_IN_BYTES);
+
+		break;
+
+	case CRYPTO_SHA1_HMAC:
+		DPRINTK("%s(): SHA1_HMAC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_SHA1_DIGEST_SIZE_IN_BYTES);
+		lacSessCtx->hashSetupData.authModeSetupData.authKey =
+		    cri->cri_key;
+		lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
+
+		break;
+
+	case CRYPTO_SHA2_256:
+		DPRINTK("%s(): SHA256\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm =
+		    CPA_CY_SYM_HASH_SHA256;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_SHA256_DIGEST_SIZE_IN_BYTES);
+
+		break;
+
+	case CRYPTO_SHA2_256_HMAC:
+		DPRINTK("%s(): SHA256_HMAC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm =
+		    CPA_CY_SYM_HASH_SHA256;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_SHA256_DIGEST_SIZE_IN_BYTES);
+		lacSessCtx->hashSetupData.authModeSetupData.authKey =
+		    cri->cri_key;
+		lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
+
+		break;
+
+	case CRYPTO_SHA2_384:
+		DPRINTK("%s(): SHA384\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm =
+		    CPA_CY_SYM_HASH_SHA384;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_SHA384_DIGEST_SIZE_IN_BYTES);
+
+		break;
+
+	case CRYPTO_SHA2_384_HMAC:
+		DPRINTK("%s(): SHA384_HMAC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm =
+		    CPA_CY_SYM_HASH_SHA384;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_SHA384_DIGEST_SIZE_IN_BYTES);
+		lacSessCtx->hashSetupData.authModeSetupData.authKey =
+		    cri->cri_key;
+		lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
+
+		break;
+
+	case CRYPTO_SHA2_512:
+		DPRINTK("%s(): SHA512\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm =
+		    CPA_CY_SYM_HASH_SHA512;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_SHA512_DIGEST_SIZE_IN_BYTES);
+
+		break;
+
+	case CRYPTO_SHA2_512_HMAC:
+		DPRINTK("%s(): SHA512_HMAC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm =
+		    CPA_CY_SYM_HASH_SHA512;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_SHA512_DIGEST_SIZE_IN_BYTES);
+		lacSessCtx->hashSetupData.authModeSetupData.authKey =
+		    cri->cri_key;
+		lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
+
+		break;
+
+	case CRYPTO_MD5:
+		DPRINTK("%s(): MD5\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_MD5;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_MD5_DIGEST_SIZE_IN_BYTES);
+
+		break;
+
+	case CRYPTO_MD5_HMAC:
+		DPRINTK("%s(): MD5_HMAC\n", __FUNCTION__);
+		lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
+		lacSessCtx->hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_MD5;
+		lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
+		lacSessCtx->hashSetupData.digestResultLenInBytes =
+		    (cri->cri_mlen ?
+		     cri->cri_mlen : ICP_MD5_DIGEST_SIZE_IN_BYTES);
+		lacSessCtx->hashSetupData.authModeSetupData.authKey =
+		    cri->cri_key;
+		lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
+		    cri->cri_klen / NUM_BITS_IN_BYTE;
+		lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
+
+		break;
+
+	default:
+		DPRINTK("%s(): ALG Setup FAIL\n", __FUNCTION__);
+		return ICP_OCF_DRV_STATUS_FAIL;
+	}
+
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvFreeOCFSession
+ *
+ * Description : This function deletes all existing Session data representing
+ * the Cryptographic session established between OCF and this driver. This
+ * also includes freeing the memory allocated for the session context. The
+ * session object is also removed from the session linked list.
+ */
+static void icp_ocfDrvFreeOCFSession(struct icp_drvSessionData *sessionData)
+{
+
+	sessionData->inUse = ICP_SESSION_DEREGISTERED;
+
+	/*ENTER CRITICAL SECTION */
+	spin_lock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
+
+	if (CPA_TRUE == atomic_read(&icp_ocfDrvIsExiting)) {
+		/*If the Driver is exiting, allow that process to
+		   handle any deletions */
+		/*EXIT CRITICAL SECTION */
+		spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
+		return;
+	}
+
+	atomic_dec(&num_ocf_to_drv_registered_sessions);
+
+	list_del(&(sessionData->listNode));
+
+	/*EXIT CRITICAL SECTION */
+	spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
+
+	if (NULL != sessionData->sessHandle) {
+		kfree(sessionData->sessHandle);
+	}
+	kmem_cache_free(drvSessionData_zone, sessionData);
+}
+
+/* Name        : icp_ocfDrvFreeLACSession
+ *
+ * Description : This attempts to deregister a LAC session. If it fails, the
+ * deregistation retry function is called.
+ */
+int icp_ocfDrvFreeLACSession(device_t dev, uint64_t sid)
+{
+	CpaCySymSessionCtx sessionToDeregister = NULL;
+	struct icp_drvSessionData *sessionData = NULL;
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	int retval = 0;
+
+	sessionData = (struct icp_drvSessionData *)CRYPTO_SESID2LID(sid);
+	if (NULL == sessionData) {
+		EPRINTK("%s(): OCF Free session called with Null Session ID.\n",
+			__FUNCTION__);
+		return EINVAL;
+	}
+
+	sessionToDeregister = sessionData->sessHandle;
+
+	if (ICP_SESSION_INITIALISED == sessionData->inUse) {
+		DPRINTK("%s() Session not registered with LAC\n", __FUNCTION__);
+	} else if (NULL == sessionData->sessHandle) {
+		EPRINTK
+		    ("%s(): OCF Free session called with Null Session Handle.\n",
+		     __FUNCTION__);
+		return EINVAL;
+	} else {
+		lacStatus = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE,
+						  sessionToDeregister);
+		if (CPA_STATUS_RETRY == lacStatus) {
+			if (ICP_OCF_DRV_STATUS_SUCCESS !=
+			    icp_ocfDrvDeregRetry(&sessionToDeregister)) {
+				/* the retry function increments the 
+				   dereg failed count */
+				DPRINTK("%s(): LAC failed to deregister the "
+					"session. (localSessionId= %p)\n",
+					__FUNCTION__, sessionToDeregister);
+				retval = EPERM;
+			}
+
+		} else if (CPA_STATUS_SUCCESS != lacStatus) {
+			DPRINTK("%s(): LAC failed to deregister the session. "
+				"localSessionId= %p, lacStatus = %d\n",
+				__FUNCTION__, sessionToDeregister, lacStatus);
+			atomic_inc(&lac_session_failed_dereg_count);
+			retval = EPERM;
+		}
+	}
+
+	icp_ocfDrvFreeOCFSession(sessionData);
+	return retval;
+
+}
+
+/* Name        : icp_ocfDrvAlgCheck 
+ *
+ * Description : This function checks whether the cryptodesc argument pertains
+ * to a sym or hash function
+ */
+static int icp_ocfDrvAlgCheck(struct cryptodesc *crp_desc)
+{
+
+	if (crp_desc->crd_alg == CRYPTO_3DES_CBC ||
+	    crp_desc->crd_alg == CRYPTO_AES_CBC ||
+	    crp_desc->crd_alg == CRYPTO_DES_CBC ||
+	    crp_desc->crd_alg == CRYPTO_NULL_CBC ||
+	    crp_desc->crd_alg == CRYPTO_ARC4) {
+		return ICP_OCF_DRV_ALG_CIPHER;
+	}
+
+	return ICP_OCF_DRV_ALG_HASH;
+}
+
+/* Name        : icp_ocfDrvSymProcess 
+ *
+ * Description : This function will map symmetric functionality calls from OCF
+ * to the LAC API. It will also allocate memory to store the session context.
+ * 
+ * Notes: If it is the first perform call for a given session, then a LAC
+ * session is registered. After the session is registered, no checks as
+ * to whether session paramaters have changed (e.g. alg chain order) are
+ * done.
+ */
+int icp_ocfDrvSymProcess(device_t dev, struct cryptop *crp, int hint)
+{
+	struct icp_drvSessionData *sessionData = NULL;
+	struct icp_drvOpData *drvOpData = NULL;
+	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+	Cpa32U sessionCtxSizeInBytes = 0;
+	uint16_t numBufferListArray = 0;
+
+	if (NULL == crp) {
+		DPRINTK("%s(): Invalid input parameters, cryptop is NULL\n",
+			__FUNCTION__);
+		return EINVAL;
+	}
+
+	if (NULL == crp->crp_desc) {
+		DPRINTK("%s(): Invalid input parameters, no crp_desc attached "
+			"to crp\n", __FUNCTION__);
+		crp->crp_etype = EINVAL;
+		return EINVAL;
+	}
+
+	if (NULL == crp->crp_buf) {
+		DPRINTK("%s(): Invalid input parameters, no buffer attached "
+			"to crp\n", __FUNCTION__);
+		crp->crp_etype = EINVAL;
+		return EINVAL;
+	}
+
+	if (CPA_TRUE == atomic_read(&icp_ocfDrvIsExiting)) {
+		crp->crp_etype = EFAULT;
+		return EFAULT;
+	}
+
+	sessionData = (struct icp_drvSessionData *)
+	    (CRYPTO_SESID2LID(crp->crp_sid));
+	if (NULL == sessionData) {
+		DPRINTK("%s(): Invalid input parameters, Null Session ID \n",
+			__FUNCTION__);
+		crp->crp_etype = EINVAL;
+		return EINVAL;
+	}
+
+/*If we get a request against a deregisted session, cancel operation*/
+	if (ICP_SESSION_DEREGISTERED == sessionData->inUse) {
+		DPRINTK("%s(): Session ID %d was deregistered \n",
+			__FUNCTION__, (int)(CRYPTO_SESID2LID(crp->crp_sid)));
+		crp->crp_etype = EFAULT;
+		return EFAULT;
+	}
+
+/*If none of the session states are set, then the session structure was either
+  not initialised properly or we are reading from a freed memory area (possible
+  due to OCF batch mode not removing queued requests against deregistered 
+  sessions*/
+	if (ICP_SESSION_INITIALISED != sessionData->inUse &&
+	    ICP_SESSION_RUNNING != sessionData->inUse) {
+		DPRINTK("%s(): Session - ID %d - not properly initialised or "
+			"memory freed back to the kernel \n",
+			__FUNCTION__, (int)(CRYPTO_SESID2LID(crp->crp_sid)));
+		crp->crp_etype = EINVAL;
+		return EINVAL;
+	}
+
+	/*For the below checks, remember error checking is already done in LAC.
+	   We're not validating inputs subsequent to registration */
+	if (sessionData->inUse == ICP_SESSION_INITIALISED) {
+		DPRINTK("%s(): Initialising session\n", __FUNCTION__);
+
+		if (NULL != crp->crp_desc->crd_next) {
+			if (ICP_OCF_DRV_ALG_CIPHER ==
+			    icp_ocfDrvAlgCheck(crp->crp_desc)) {
+
+				sessionData->lacSessCtx.algChainOrder =
+				    CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH;
+
+				if (crp->crp_desc->crd_flags & CRD_F_ENCRYPT) {
+					sessionData->lacSessCtx.cipherSetupData.
+					    cipherDirection =
+					    CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT;
+				} else {
+					sessionData->lacSessCtx.cipherSetupData.
+					    cipherDirection =
+					    CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT;
+				}
+			} else {
+				sessionData->lacSessCtx.algChainOrder =
+				    CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER;
+
+				if (crp->crp_desc->crd_next->crd_flags &
+				    CRD_F_ENCRYPT) {
+					sessionData->lacSessCtx.cipherSetupData.
+					    cipherDirection =
+					    CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT;
+				} else {
+					sessionData->lacSessCtx.cipherSetupData.
+					    cipherDirection =
+					    CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT;
+				}
+
+			}
+
+		} else if (ICP_OCF_DRV_ALG_CIPHER ==
+			   icp_ocfDrvAlgCheck(crp->crp_desc)) {
+			if (crp->crp_desc->crd_flags & CRD_F_ENCRYPT) {
+				sessionData->lacSessCtx.cipherSetupData.
+				    cipherDirection =
+				    CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT;
+			} else {
+				sessionData->lacSessCtx.cipherSetupData.
+				    cipherDirection =
+				    CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT;
+			}
+
+		}
+
+		/*No action required for standalone Auth here */
+
+		/* Allocate memory for SymSessionCtx before the Session Registration */
+		lacStatus =
+		    cpaCySymSessionCtxGetSize(CPA_INSTANCE_HANDLE_SINGLE,
+					      &(sessionData->lacSessCtx),
+					      &sessionCtxSizeInBytes);
+		if (CPA_STATUS_SUCCESS != lacStatus) {
+			EPRINTK("%s(): cpaCySymSessionCtxGetSize failed - %d\n",
+				__FUNCTION__, lacStatus);
+			return EINVAL;
+		}
+		sessionData->sessHandle =
+		    kmalloc(sessionCtxSizeInBytes, GFP_ATOMIC);
+		if (NULL == sessionData->sessHandle) {
+			EPRINTK
+			    ("%s(): Failed to get memory for SymSessionCtx\n",
+			     __FUNCTION__);
+			return ENOMEM;
+		}
+
+		lacStatus = cpaCySymInitSession(CPA_INSTANCE_HANDLE_SINGLE,
+						icp_ocfDrvSymCallBack,
+						&(sessionData->lacSessCtx),
+						sessionData->sessHandle);
+
+		if (CPA_STATUS_SUCCESS != lacStatus) {
+			EPRINTK("%s(): cpaCySymInitSession failed -%d \n",
+				__FUNCTION__, lacStatus);
+			return EFAULT;
+		}
+
+		sessionData->inUse = ICP_SESSION_RUNNING;
+	}
+
+	drvOpData = kmem_cache_zalloc(drvOpData_zone, GFP_ATOMIC);
+	if (NULL == drvOpData) {
+		EPRINTK("%s():Failed to get memory for drvOpData\n",
+			__FUNCTION__);
+		crp->crp_etype = ENOMEM;
+		return ENOMEM;
+	}
+
+	drvOpData->lacOpData.pSessionCtx = sessionData->sessHandle;
+	drvOpData->digestSizeInBytes = sessionData->lacSessCtx.hashSetupData.
+	    digestResultLenInBytes;
+	drvOpData->crp = crp;
+
+	/* Set the default buffer list array memory allocation */
+	drvOpData->srcBuffer.pBuffers = drvOpData->bufferListArray;
+	drvOpData->numBufferListArray = ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS;
+
+	/* 
+	 * Allocate buffer list array memory allocation if the
+	 * data fragment is more than the default allocation
+	 */
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		numBufferListArray = icp_ocfDrvGetSkBuffFrags((struct sk_buff *)
+							      crp->crp_buf);
+		if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS < numBufferListArray) {
+			DPRINTK("%s() numBufferListArray more than default\n",
+				__FUNCTION__);
+			drvOpData->srcBuffer.pBuffers = NULL;
+			drvOpData->srcBuffer.pBuffers =
+			    kmalloc(numBufferListArray *
+				    sizeof(CpaFlatBuffer), GFP_ATOMIC);
+			if (NULL == drvOpData->srcBuffer.pBuffers) {
+				EPRINTK("%s() Failed to get memory for "
+					"pBuffers\n", __FUNCTION__);
+				kmem_cache_free(drvOpData_zone, drvOpData);
+				crp->crp_etype = ENOMEM;
+				return ENOMEM;
+			}
+			drvOpData->numBufferListArray = numBufferListArray;
+		}
+	}
+
+	/*
+	 * Check the type of buffer structure we got and convert it into
+	 * CpaBufferList format.
+	 */
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		if (ICP_OCF_DRV_STATUS_SUCCESS !=
+		    icp_ocfDrvSkBuffToBufferList((struct sk_buff *)crp->crp_buf,
+						 &(drvOpData->srcBuffer))) {
+			EPRINTK("%s():Failed to translate from SK_BUF "
+				"to bufferlist\n", __FUNCTION__);
+			crp->crp_etype = EINVAL;
+			goto err;
+		}
+
+		drvOpData->bufferType = CRYPTO_F_SKBUF;
+	} else if (crp->crp_flags & CRYPTO_F_IOV) {
+		/* OCF only supports IOV of one entry. */
+		if (NUM_IOV_SUPPORTED ==
+		    ((struct uio *)(crp->crp_buf))->uio_iovcnt) {
+
+			icp_ocfDrvPtrAndLenToBufferList(((struct uio *)(crp->
+									crp_buf))->
+							uio_iov[0].iov_base,
+							((struct uio *)(crp->
+									crp_buf))->
+							uio_iov[0].iov_len,
+							&(drvOpData->
+							  srcBuffer));
+
+			drvOpData->bufferType = CRYPTO_F_IOV;
+
+		} else {
+			DPRINTK("%s():Unable to handle IOVs with lengths of "
+				"greater than one!\n", __FUNCTION__);
+			crp->crp_etype = EINVAL;
+			goto err;
+		}
+
+	} else {
+		icp_ocfDrvPtrAndLenToBufferList(crp->crp_buf,
+						crp->crp_ilen,
+						&(drvOpData->srcBuffer));
+
+		drvOpData->bufferType = CRYPTO_BUF_CONTIG;
+	}
+
+	if (ICP_OCF_DRV_STATUS_SUCCESS !=
+	    icp_ocfDrvProcessDataSetup(drvOpData, drvOpData->crp->crp_desc)) {
+		crp->crp_etype = EINVAL;
+		goto err;
+	}
+
+	if (drvOpData->crp->crp_desc->crd_next != NULL) {
+		if (icp_ocfDrvProcessDataSetup(drvOpData, drvOpData->crp->
+					       crp_desc->crd_next)) {
+			crp->crp_etype = EINVAL;
+			goto err;
+		}
+
+	}
+
+	/* Allocate srcBuffer's private meta data */
+	if (ICP_OCF_DRV_STATUS_SUCCESS !=
+	    icp_ocfDrvAllocMetaData(&(drvOpData->srcBuffer), drvOpData)) {
+		EPRINTK("%s() icp_ocfDrvAllocMetaData failed\n", __FUNCTION__);
+		memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData));
+		crp->crp_etype = EINVAL;
+		goto err;
+	}
+
+	/* Perform "in-place" crypto operation */
+	lacStatus = cpaCySymPerformOp(CPA_INSTANCE_HANDLE_SINGLE,
+				      (void *)drvOpData,
+				      &(drvOpData->lacOpData),
+				      &(drvOpData->srcBuffer),
+				      &(drvOpData->srcBuffer),
+				      &(drvOpData->verifyResult));
+	if (CPA_STATUS_RETRY == lacStatus) {
+		DPRINTK("%s(): cpaCySymPerformOp retry, lacStatus = %d\n",
+			__FUNCTION__, lacStatus);
+		memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData));
+		crp->crp_etype = EINVAL;
+		goto err;
+	}
+	if (CPA_STATUS_SUCCESS != lacStatus) {
+		EPRINTK("%s(): cpaCySymPerformOp failed, lacStatus = %d\n",
+			__FUNCTION__, lacStatus);
+		memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData));
+		crp->crp_etype = EINVAL;
+		goto err;
+	}
+
+	return 0;		//OCF success status value
+
+      err:
+	if (drvOpData->numBufferListArray > ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) {
+		kfree(drvOpData->srcBuffer.pBuffers);
+	}
+	icp_ocfDrvFreeMetaData(&(drvOpData->srcBuffer));
+	kmem_cache_free(drvOpData_zone, drvOpData);
+
+	return crp->crp_etype;
+}
+
+/* Name        : icp_ocfDrvProcessDataSetup
+ *
+ * Description : This function will setup all the cryptographic operation data
+ *               that is required by LAC to execute the operation.
+ */
+static int icp_ocfDrvProcessDataSetup(struct icp_drvOpData *drvOpData,
+				      struct cryptodesc *crp_desc)
+{
+	CpaCyRandGenOpData randGenOpData;
+	CpaFlatBuffer randData;
+
+	drvOpData->lacOpData.packetType = CPA_CY_SYM_PACKET_TYPE_FULL;
+
+	/* Convert from the cryptop to the ICP LAC crypto parameters */
+	switch (crp_desc->crd_alg) {
+	case CRYPTO_NULL_CBC:
+		drvOpData->lacOpData.
+		    cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
+		drvOpData->lacOpData.
+		    messageLenToCipherInBytes = crp_desc->crd_len;
+		drvOpData->verifyResult = CPA_FALSE;
+		drvOpData->lacOpData.ivLenInBytes = NULL_BLOCK_LEN;
+		break;
+	case CRYPTO_DES_CBC:
+		drvOpData->lacOpData.
+		    cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
+		drvOpData->lacOpData.
+		    messageLenToCipherInBytes = crp_desc->crd_len;
+		drvOpData->verifyResult = CPA_FALSE;
+		drvOpData->lacOpData.ivLenInBytes = DES_BLOCK_LEN;
+		break;
+	case CRYPTO_3DES_CBC:
+		drvOpData->lacOpData.
+		    cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
+		drvOpData->lacOpData.
+		    messageLenToCipherInBytes = crp_desc->crd_len;
+		drvOpData->verifyResult = CPA_FALSE;
+		drvOpData->lacOpData.ivLenInBytes = DES3_BLOCK_LEN;
+		break;
+	case CRYPTO_ARC4:
+		drvOpData->lacOpData.
+		    cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
+		drvOpData->lacOpData.
+		    messageLenToCipherInBytes = crp_desc->crd_len;
+		drvOpData->verifyResult = CPA_FALSE;
+		drvOpData->lacOpData.ivLenInBytes = ARC4_COUNTER_LEN;
+		break;
+	case CRYPTO_AES_CBC:
+		drvOpData->lacOpData.
+		    cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
+		drvOpData->lacOpData.
+		    messageLenToCipherInBytes = crp_desc->crd_len;
+		drvOpData->verifyResult = CPA_FALSE;
+		drvOpData->lacOpData.ivLenInBytes = RIJNDAEL128_BLOCK_LEN;
+		break;
+	case CRYPTO_SHA1:
+	case CRYPTO_SHA1_HMAC:
+	case CRYPTO_SHA2_256:
+	case CRYPTO_SHA2_256_HMAC:
+	case CRYPTO_SHA2_384:
+	case CRYPTO_SHA2_384_HMAC:
+	case CRYPTO_SHA2_512:
+	case CRYPTO_SHA2_512_HMAC:
+	case CRYPTO_MD5:
+	case CRYPTO_MD5_HMAC:
+		drvOpData->lacOpData.
+		    hashStartSrcOffsetInBytes = crp_desc->crd_skip;
+		drvOpData->lacOpData.
+		    messageLenToHashInBytes = crp_desc->crd_len;
+		drvOpData->lacOpData.
+		    pDigestResult =
+		    icp_ocfDrvDigestPointerFind(drvOpData, crp_desc);
+
+		if (NULL == drvOpData->lacOpData.pDigestResult) {
+			DPRINTK("%s(): ERROR - could not calculate "
+				"Digest Result memory address\n", __FUNCTION__);
+			return ICP_OCF_DRV_STATUS_FAIL;
+		}
+
+		drvOpData->lacOpData.digestVerify = CPA_FALSE;
+		break;
+	default:
+		DPRINTK("%s(): Crypto process error - algorithm not "
+			"found \n", __FUNCTION__);
+		return ICP_OCF_DRV_STATUS_FAIL;
+	}
+
+	/* Figure out what the IV is supposed to be */
+	if ((crp_desc->crd_alg == CRYPTO_DES_CBC) ||
+	    (crp_desc->crd_alg == CRYPTO_3DES_CBC) ||
+	    (crp_desc->crd_alg == CRYPTO_AES_CBC)) {
+		/*ARC4 doesn't use an IV */
+		if (crp_desc->crd_flags & CRD_F_IV_EXPLICIT) {
+			/* Explicit IV provided to OCF */
+			drvOpData->lacOpData.pIv = crp_desc->crd_iv;
+		} else {
+			/* IV is not explicitly provided to OCF */
+
+			/* Point the LAC OP Data IV pointer to our allocated
+			   storage location for this session. */
+			drvOpData->lacOpData.pIv = drvOpData->ivData;
+
+			if ((crp_desc->crd_flags & CRD_F_ENCRYPT) &&
+			    ((crp_desc->crd_flags & CRD_F_IV_PRESENT) == 0)) {
+
+				/* Encrypting - need to create IV */
+				randGenOpData.generateBits = CPA_TRUE;
+				randGenOpData.lenInBytes = MAX_IV_LEN_IN_BYTES;
+
+				icp_ocfDrvPtrAndLenToFlatBuffer((Cpa8U *)
+								drvOpData->
+								ivData,
+								MAX_IV_LEN_IN_BYTES,
+								&randData);
+
+				if (CPA_STATUS_SUCCESS !=
+				    cpaCyRandGen(CPA_INSTANCE_HANDLE_SINGLE,
+						 NULL, NULL,
+						 &randGenOpData, &randData)) {
+					DPRINTK("%s(): ERROR - Failed to"
+						" generate"
+						" Initialisation Vector\n",
+						__FUNCTION__);
+					return ICP_OCF_DRV_STATUS_FAIL;
+				}
+
+				crypto_copyback(drvOpData->crp->
+						crp_flags,
+						drvOpData->crp->crp_buf,
+						crp_desc->crd_inject,
+						drvOpData->lacOpData.
+						ivLenInBytes,
+						(caddr_t) (drvOpData->lacOpData.
+							   pIv));
+			} else {
+				/* Reading IV from buffer */
+				crypto_copydata(drvOpData->crp->
+						crp_flags,
+						drvOpData->crp->crp_buf,
+						crp_desc->crd_inject,
+						drvOpData->lacOpData.
+						ivLenInBytes,
+						(caddr_t) (drvOpData->lacOpData.
+							   pIv));
+			}
+
+		}
+
+	}
+
+	return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvDigestPointerFind
+ *
+ * Description : This function is used to find the memory address of where the
+ * digest information shall be stored in. Input buffer types are an skbuff, iov
+ * or flat buffer. The address is found using the buffer data start address and
+ * an offset.
+ *
+ * Note: In the case of a linux skbuff, the digest address may exist within
+ * a memory space linked to from the start buffer. These linked memory spaces
+ * must be traversed by the data length offset in order to find the digest start
+ * address. Whether there is enough space for the digest must also be checked.
+ */
+
+static uint8_t *icp_ocfDrvDigestPointerFind(struct icp_drvOpData *drvOpData,
+					    struct cryptodesc *crp_desc)
+{
+
+	int offsetInBytes = crp_desc->crd_inject;
+	uint32_t digestSizeInBytes = drvOpData->digestSizeInBytes;
+	uint8_t *flat_buffer_base = NULL;
+	int flat_buffer_length = 0;
+	struct sk_buff *skb;
+
+	if (drvOpData->crp->crp_flags & CRYPTO_F_SKBUF) {
+		/*check if enough overall space to store hash */
+		skb = (struct sk_buff *)(drvOpData->crp->crp_buf);
+
+		if (skb->len < (offsetInBytes + digestSizeInBytes)) {
+			DPRINTK("%s() Not enough space for Digest"
+				" payload after the offset (%d), "
+				"digest size (%d) \n", __FUNCTION__,
+				offsetInBytes, digestSizeInBytes);
+			return NULL;
+		}
+
+		return icp_ocfDrvSkbuffDigestPointerFind(drvOpData,
+							 offsetInBytes,
+							 digestSizeInBytes);
+
+	} else {
+		/* IOV or flat buffer */
+		if (drvOpData->crp->crp_flags & CRYPTO_F_IOV) {
+			/*single IOV check has already been done */
+			flat_buffer_base = ((struct uio *)
+					    (drvOpData->crp->crp_buf))->
+			    uio_iov[0].iov_base;
+			flat_buffer_length = ((struct uio *)
+					      (drvOpData->crp->crp_buf))->
+			    uio_iov[0].iov_len;
+		} else {
+			flat_buffer_base = (uint8_t *) drvOpData->crp->crp_buf;
+			flat_buffer_length = drvOpData->crp->crp_ilen;
+		}
+
+		if (flat_buffer_length < (offsetInBytes + digestSizeInBytes)) {
+			DPRINTK("%s() Not enough space for Digest "
+				"(IOV/Flat Buffer) \n", __FUNCTION__);
+			return NULL;
+		} else {
+			return (uint8_t *) (flat_buffer_base + offsetInBytes);
+		}
+	}
+	DPRINTK("%s() Should not reach this point\n", __FUNCTION__);
+	return NULL;
+}
+
+/* Name        : icp_ocfDrvSkbuffDigestPointerFind
+ *
+ * Description : This function is used by icp_ocfDrvDigestPointerFind to process
+ * the non-linear portion of the skbuff if the fragmentation type is a linked
+ * list (frag_list is not NULL in the skb_shared_info structure)
+ */
+static inline uint8_t *icp_ocfDrvSkbuffDigestPointerFind(struct icp_drvOpData
+							 *drvOpData,
+							 int offsetInBytes,
+							 uint32_t
+							 digestSizeInBytes)
+{
+
+	struct sk_buff *skb = NULL;
+	struct skb_shared_info *skb_shared = NULL;
+
+	uint32_t skbuffisnonlinear = 0;
+
+	uint32_t skbheadlen = 0;
+
+	skb = (struct sk_buff *)(drvOpData->crp->crp_buf);
+	skbuffisnonlinear = skb_is_nonlinear(skb);
+
+	skbheadlen = skb_headlen(skb);
+
+	/*Linear skb checks */
+	if (skbheadlen > offsetInBytes) {
+
+		if (skbheadlen >= (offsetInBytes + digestSizeInBytes)) {
+			return (uint8_t *) (skb->data + offsetInBytes);
+		} else {
+			DPRINTK("%s() Auth payload stretches "
+				"accross contiguous memory\n", __FUNCTION__);
+			return NULL;
+		}
+	} else {
+		if (skbuffisnonlinear) {
+			offsetInBytes -= skbheadlen;
+		} else {
+			DPRINTK("%s() Offset outside of buffer boundaries\n",
+				__FUNCTION__);
+			return NULL;
+		}
+	}
+
+	/*Non Linear checks */
+	skb_shared = (struct skb_shared_info *)(skb->end);
+	if (unlikely(NULL == skb_shared)) {
+		DPRINTK("%s() skbuff shared info stucture is NULL! \n",
+			__FUNCTION__);
+		return NULL;
+	} else if ((0 != skb_shared->nr_frags) &&
+		   (skb_shared->frag_list != NULL)) {
+		DPRINTK("%s() skbuff nr_frags AND "
+			"frag_list not supported \n", __FUNCTION__);
+		return NULL;
+	}
+
+	/*TCP segmentation more likely than IP fragmentation */
+	if (likely(0 != skb_shared->nr_frags)) {
+		return icp_ocfDrvDigestSkbNRFragsCheck(skb, skb_shared,
+						       offsetInBytes,
+						       digestSizeInBytes);
+	} else if (skb_shared->frag_list != NULL) {
+		return icp_ocfDrvDigestSkbFragListCheck(skb, skb_shared,
+							offsetInBytes,
+							digestSizeInBytes);
+	} else {
+		DPRINTK("%s() skbuff is non-linear but does not show any "
+			"linked data\n", __FUNCTION__);
+		return NULL;
+	}
+
+}
+
+/* Name        : icp_ocfDrvDigestSkbNRFragsCheck
+ *
+ * Description : This function is used by icp_ocfDrvSkbuffDigestPointerFind to
+ * process the non-linear portion of the skbuff, if the fragmentation type is
+ * page fragments
+ */
+static inline uint8_t *icp_ocfDrvDigestSkbNRFragsCheck(struct sk_buff *skb,
+						       struct skb_shared_info
+						       *skb_shared,
+						       int offsetInBytes,
+						       uint32_t
+						       digestSizeInBytes)
+{
+	int i = 0;
+	/*nr_frags starts from 1 */
+	if (MAX_SKB_FRAGS < skb_shared->nr_frags) {
+		DPRINTK("%s error processing skbuff "
+			"page frame -- MAX FRAGS exceeded \n", __FUNCTION__);
+		return NULL;
+	}
+
+	for (i = 0; i < skb_shared->nr_frags; i++) {
+
+		if (offsetInBytes >= skb_shared->frags[i].size) {
+			/*offset still greater than data position */
+			offsetInBytes -= skb_shared->frags[i].size;
+		} else {
+			/* found the page containing start of hash */
+
+			if (NULL == skb_shared->frags[i].page) {
+				DPRINTK("%s() Linked page is NULL!\n",
+					__FUNCTION__);
+				return NULL;
+			}
+
+			if (offsetInBytes + digestSizeInBytes >
+			    skb_shared->frags[i].size) {
+				DPRINTK("%s() Auth payload stretches accross "
+					"contiguous memory\n", __FUNCTION__);
+				return NULL;
+			} else {
+				return (uint8_t *) (skb_shared->frags[i].page +
+						    skb_shared->frags[i].
+						    page_offset +
+						    offsetInBytes);
+			}
+		}
+		/*only possible if internal page sizes are set wrong */
+		if (offsetInBytes < 0) {
+			DPRINTK("%s error processing skbuff page frame "
+				"-- offset calculation \n", __FUNCTION__);
+			return NULL;
+		}
+	}
+	/*only possible if internal page sizes are set wrong */
+	DPRINTK("%s error processing skbuff page frame "
+		"-- ran out of page fragments, remaining offset = %d \n",
+		__FUNCTION__, offsetInBytes);
+	return NULL;
+
+}
+
+/* Name        : icp_ocfDrvDigestSkbFragListCheck
+ *
+ * Description : This function is used by icp_ocfDrvSkbuffDigestPointerFind to 
+ * process the non-linear portion of the skbuff, if the fragmentation type is 
+ * a linked list
+ * 
+ */
+static inline uint8_t *icp_ocfDrvDigestSkbFragListCheck(struct sk_buff *skb,
+							struct skb_shared_info
+							*skb_shared,
+							int offsetInBytes,
+							uint32_t
+							digestSizeInBytes)
+{
+
+	struct sk_buff *skb_list = skb_shared->frag_list;
+	/*check added for readability */
+	if (NULL == skb_list) {
+		DPRINTK("%s error processing skbuff "
+			"-- no more list! \n", __FUNCTION__);
+		return NULL;
+	}
+
+	for (; skb_list; skb_list = skb_list->next) {
+		if (NULL == skb_list) {
+			DPRINTK("%s error processing skbuff "
+				"-- no more list! \n", __FUNCTION__);
+			return NULL;
+		}
+
+		if (offsetInBytes >= skb_list->len) {
+			offsetInBytes -= skb_list->len;
+
+		} else {
+			if (offsetInBytes + digestSizeInBytes > skb_list->len) {
+				DPRINTK("%s() Auth payload stretches accross "
+					"contiguous memory\n", __FUNCTION__);
+				return NULL;
+			} else {
+				return (uint8_t *)
+				    (skb_list->data + offsetInBytes);
+			}
+
+		}
+
+		/*This check is only needed if internal skb_list length values
+		   are set wrong. */
+		if (0 > offsetInBytes) {
+			DPRINTK("%s() error processing skbuff object -- offset "
+				"calculation \n", __FUNCTION__);
+			return NULL;
+		}
+
+	}
+
+	/*catch all for unusual for-loop exit. 
+	   This code should never be reached */
+	DPRINTK("%s() Catch-All hit! Process error.\n", __FUNCTION__);
+	return NULL;
+}
diff --git a/crypto/ocf/ep80579/linux_2.6_kernel_space.mk b/crypto/ocf/ep80579/linux_2.6_kernel_space.mk
new file mode 100755
index 0000000..96afa9a
--- /dev/null
+++ b/crypto/ocf/ep80579/linux_2.6_kernel_space.mk
@@ -0,0 +1,69 @@
+###################
+# @par
+# This file is provided under a dual BSD/GPLv2 license.  When using or 
+#   redistributing this file, you may do so under either license.
+# 
+#   GPL LICENSE SUMMARY
+# 
+#   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+# 
+#   This program is free software; you can redistribute it and/or modify 
+#   it under the terms of version 2 of the GNU General Public License as
+#   published by the Free Software Foundation.
+# 
+#   This program is distributed in the hope that it will be useful, but 
+#   WITHOUT ANY WARRANTY; without even the implied warranty of 
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#   General Public License for more details.
+# 
+#   You should have received a copy of the GNU General Public License 
+#   along with this program; if not, write to the Free Software 
+#   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+#   The full GNU General Public License is included in this distribution 
+#   in the file called LICENSE.GPL.
+# 
+#   Contact Information:
+#   Intel Corporation
+# 
+#   BSD LICENSE 
+# 
+#   Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
+#   All rights reserved.
+# 
+#   Redistribution and use in source and binary forms, with or without 
+#   modification, are permitted provided that the following conditions 
+#   are met:
+# 
+#     * Redistributions of source code must retain the above copyright 
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright 
+#       notice, this list of conditions and the following disclaimer in 
+#       the documentation and/or other materials provided with the 
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its 
+#       contributors may be used to endorse or promote products derived 
+#       from this software without specific prior written permission.
+# 
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# 
+# 
+#  version: Security.L.1.0.130
+###################
+
+#specific include directories in kernel space
+INCLUDES+=#e.g. -I$(OSAL_DIR)/include \
+
+#Extra Flags Specific in kernel space e.g. include path or debug flags etc. e.g to add an include path EXTRA_CFLAGS += -I$(src)/../include
+EXTRA_CFLAGS += $(INCLUDES) -O2 -Wall
+EXTRA_LDFLAGS +=-whole-archive
+
diff --git a/crypto/ocf/hifn/Makefile b/crypto/ocf/hifn/Makefile
new file mode 100755
index 0000000..163fed0
--- /dev/null
+++ b/crypto/ocf/hifn/Makefile
@@ -0,0 +1,13 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+obj-$(CONFIG_OCF_HIFN)     += hifn7751.o
+obj-$(CONFIG_OCF_HIFNHIPP) += hifnHIPP.o
+
+obj ?= .
+EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/crypto/ocf/hifn/hifn7751.c b/crypto/ocf/hifn/hifn7751.c
new file mode 100755
index 0000000..6459f35
--- /dev/null
+++ b/crypto/ocf/hifn/hifn7751.c
@@ -0,0 +1,2970 @@
+/*	$OpenBSD: hifn7751.c,v 1.120 2002/05/17 00:33:34 deraadt Exp $	*/
+
+/*-
+ * Invertex AEON / Hifn 7751 driver
+ * Copyright (c) 1999 Invertex Inc. All rights reserved.
+ * Copyright (c) 1999 Theo de Raadt
+ * Copyright (c) 2000-2001 Network Security Technologies, Inc.
+ *			http://www.netsec.net
+ * Copyright (c) 2003 Hifn Inc.
+ *
+ * This driver is based on a previous driver by Invertex, for which they
+ * requested:  Please send any comments, feedback, bug-fixes, or feature
+ * requests to software@invertex.com.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ *
+__FBSDID("$FreeBSD: src/sys/dev/hifn/hifn7751.c,v 1.40 2007/03/21 03:42:49 sam Exp $");
+ */
+
+/*
+ * Driver for various Hifn encryption processors.
+ */
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/version.h>
+#include <linux/skbuff.h>
+#include <asm/io.h>
+
+#include <cryptodev.h>
+#include <uio.h>
+#include <hifn/hifn7751reg.h>
+#include <hifn/hifn7751var.h>
+
+#if 1
+#define	DPRINTF(a...)	if (hifn_debug) { \
+							printk("%s: ", sc ? \
+								device_get_nameunit(sc->sc_dev) : "hifn"); \
+							printk(a); \
+						} else
+#else
+#define	DPRINTF(a...)
+#endif
+
+static inline int
+pci_get_revid(struct pci_dev *dev)
+{
+	u8 rid = 0;
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
+	return rid;
+}
+
+static	struct hifn_stats hifnstats;
+
+#define	debug hifn_debug
+int hifn_debug = 0;
+module_param(hifn_debug, int, 0644);
+MODULE_PARM_DESC(hifn_debug, "Enable debug");
+
+int hifn_maxbatch = 1;
+module_param(hifn_maxbatch, int, 0644);
+MODULE_PARM_DESC(hifn_maxbatch, "max ops to batch w/o interrupt");
+
+#ifdef MODULE_PARM
+char *hifn_pllconfig = NULL;
+MODULE_PARM(hifn_pllconfig, "s");
+#else
+char hifn_pllconfig[32]; /* This setting is RO after loading */
+module_param_string(hifn_pllconfig, hifn_pllconfig, 32, 0444);
+#endif
+MODULE_PARM_DESC(hifn_pllconfig, "PLL config, ie., pci66, ext33, ...");
+
+#ifdef HIFN_VULCANDEV
+#include <sys/conf.h>
+#include <sys/uio.h>
+
+static struct cdevsw vulcanpk_cdevsw; /* forward declaration */
+#endif
+
+/*
+ * Prototypes and count for the pci_device structure
+ */
+static	int  hifn_probe(struct pci_dev *dev, const struct pci_device_id *ent);
+static	void hifn_remove(struct pci_dev *dev);
+
+static	int hifn_newsession(device_t, u_int32_t *, struct cryptoini *);
+static	int hifn_freesession(device_t, u_int64_t);
+static	int hifn_process(device_t, struct cryptop *, int);
+
+static device_method_t hifn_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,	hifn_newsession),
+	DEVMETHOD(cryptodev_freesession,hifn_freesession),
+	DEVMETHOD(cryptodev_process,	hifn_process),
+};
+
+static	void hifn_reset_board(struct hifn_softc *, int);
+static	void hifn_reset_puc(struct hifn_softc *);
+static	void hifn_puc_wait(struct hifn_softc *);
+static	int hifn_enable_crypto(struct hifn_softc *);
+static	void hifn_set_retry(struct hifn_softc *sc);
+static	void hifn_init_dma(struct hifn_softc *);
+static	void hifn_init_pci_registers(struct hifn_softc *);
+static	int hifn_sramsize(struct hifn_softc *);
+static	int hifn_dramsize(struct hifn_softc *);
+static	int hifn_ramtype(struct hifn_softc *);
+static	void hifn_sessions(struct hifn_softc *);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+static irqreturn_t hifn_intr(int irq, void *arg);
+#else
+static irqreturn_t hifn_intr(int irq, void *arg, struct pt_regs *regs);
+#endif
+static	u_int hifn_write_command(struct hifn_command *, u_int8_t *);
+static	u_int32_t hifn_next_signature(u_int32_t a, u_int cnt);
+static	void hifn_callback(struct hifn_softc *, struct hifn_command *, u_int8_t *);
+static	int hifn_crypto(struct hifn_softc *, struct hifn_command *, struct cryptop *, int);
+static	int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *);
+static	int hifn_writeramaddr(struct hifn_softc *, int, u_int8_t *);
+static	int hifn_dmamap_load_src(struct hifn_softc *, struct hifn_command *);
+static	int hifn_dmamap_load_dst(struct hifn_softc *, struct hifn_command *);
+static	int hifn_init_pubrng(struct hifn_softc *);
+static	void hifn_tick(unsigned long arg);
+static	void hifn_abort(struct hifn_softc *);
+static	void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, int *);
+
+static	void hifn_write_reg_0(struct hifn_softc *, bus_size_t, u_int32_t);
+static	void hifn_write_reg_1(struct hifn_softc *, bus_size_t, u_int32_t);
+
+#ifdef CONFIG_OCF_RANDOMHARVEST
+static	int hifn_read_random(void *arg, u_int32_t *buf, int len);
+#endif
+
+#define HIFN_MAX_CHIPS	8
+static struct hifn_softc *hifn_chip_idx[HIFN_MAX_CHIPS];
+
+static __inline u_int32_t
+READ_REG_0(struct hifn_softc *sc, bus_size_t reg)
+{
+	u_int32_t v = readl(sc->sc_bar0 + reg);
+	sc->sc_bar0_lastreg = (bus_size_t) -1;
+	return (v);
+}
+#define	WRITE_REG_0(sc, reg, val)	hifn_write_reg_0(sc, reg, val)
+
+static __inline u_int32_t
+READ_REG_1(struct hifn_softc *sc, bus_size_t reg)
+{
+	u_int32_t v = readl(sc->sc_bar1 + reg);
+	sc->sc_bar1_lastreg = (bus_size_t) -1;
+	return (v);
+}
+#define	WRITE_REG_1(sc, reg, val)	hifn_write_reg_1(sc, reg, val)
+
+/*
+ * map in a given buffer (great on some arches :-)
+ */
+
+static int
+pci_map_uio(struct hifn_softc *sc, struct hifn_operand *buf, struct uio *uio)
+{
+	struct iovec *iov = uio->uio_iov;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	buf->mapsize = 0;
+	for (buf->nsegs = 0; buf->nsegs < uio->uio_iovcnt; ) {
+		buf->segs[buf->nsegs].ds_addr = pci_map_single(sc->sc_pcidev,
+				iov->iov_base, iov->iov_len,
+				PCI_DMA_BIDIRECTIONAL);
+		buf->segs[buf->nsegs].ds_len = iov->iov_len;
+		buf->mapsize += iov->iov_len;
+		iov++;
+		buf->nsegs++;
+	}
+	/* identify this buffer by the first segment */
+	buf->map = (void *) buf->segs[0].ds_addr;
+	return(0);
+}
+
+/*
+ * map in a given sk_buff
+ */
+
+static int
+pci_map_skb(struct hifn_softc *sc,struct hifn_operand *buf,struct sk_buff *skb)
+{
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	buf->mapsize = 0;
+
+	buf->segs[0].ds_addr = pci_map_single(sc->sc_pcidev,
+			skb->data, skb_headlen(skb), PCI_DMA_BIDIRECTIONAL);
+	buf->segs[0].ds_len = skb_headlen(skb);
+	buf->mapsize += buf->segs[0].ds_len;
+
+	buf->nsegs = 1;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; ) {
+		buf->segs[buf->nsegs].ds_len = skb_shinfo(skb)->frags[i].size;
+		buf->segs[buf->nsegs].ds_addr = pci_map_single(sc->sc_pcidev,
+				page_address(skb_shinfo(skb)->frags[i].page) +
+					skb_shinfo(skb)->frags[i].page_offset,
+				buf->segs[buf->nsegs].ds_len, PCI_DMA_BIDIRECTIONAL);
+		buf->mapsize += buf->segs[buf->nsegs].ds_len;
+		buf->nsegs++;
+	}
+
+	/* identify this buffer by the first segment */
+	buf->map = (void *) buf->segs[0].ds_addr;
+	return(0);
+}
+
+/*
+ * map in a given contiguous buffer
+ */
+
+static int
+pci_map_buf(struct hifn_softc *sc,struct hifn_operand *buf, void *b, int len)
+{
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	buf->mapsize = 0;
+	buf->segs[0].ds_addr = pci_map_single(sc->sc_pcidev,
+			b, len, PCI_DMA_BIDIRECTIONAL);
+	buf->segs[0].ds_len = len;
+	buf->mapsize += buf->segs[0].ds_len;
+	buf->nsegs = 1;
+
+	/* identify this buffer by the first segment */
+	buf->map = (void *) buf->segs[0].ds_addr;
+	return(0);
+}
+
+#if 0 /* not needed at this time */
+static void
+pci_sync_iov(struct hifn_softc *sc, struct hifn_operand *buf)
+{
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+	for (i = 0; i < buf->nsegs; i++)
+		pci_dma_sync_single_for_cpu(sc->sc_pcidev, buf->segs[i].ds_addr,
+				buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
+}
+#endif
+
+static void
+pci_unmap_buf(struct hifn_softc *sc, struct hifn_operand *buf)
+{
+	int i;
+	DPRINTF("%s()\n", __FUNCTION__);
+	for (i = 0; i < buf->nsegs; i++) {
+		pci_unmap_single(sc->sc_pcidev, buf->segs[i].ds_addr,
+				buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
+		buf->segs[i].ds_addr = 0;
+		buf->segs[i].ds_len = 0;
+	}
+	buf->nsegs = 0;
+	buf->mapsize = 0;
+	buf->map = 0;
+}
+
+static const char*
+hifn_partname(struct hifn_softc *sc)
+{
+	/* XXX sprintf numbers when not decoded */
+	switch (pci_get_vendor(sc->sc_pcidev)) {
+	case PCI_VENDOR_HIFN:
+		switch (pci_get_device(sc->sc_pcidev)) {
+		case PCI_PRODUCT_HIFN_6500:	return "Hifn 6500";
+		case PCI_PRODUCT_HIFN_7751:	return "Hifn 7751";
+		case PCI_PRODUCT_HIFN_7811:	return "Hifn 7811";
+		case PCI_PRODUCT_HIFN_7951:	return "Hifn 7951";
+		case PCI_PRODUCT_HIFN_7955:	return "Hifn 7955";
+		case PCI_PRODUCT_HIFN_7956:	return "Hifn 7956";
+		}
+		return "Hifn unknown-part";
+	case PCI_VENDOR_INVERTEX:
+		switch (pci_get_device(sc->sc_pcidev)) {
+		case PCI_PRODUCT_INVERTEX_AEON:	return "Invertex AEON";
+		}
+		return "Invertex unknown-part";
+	case PCI_VENDOR_NETSEC:
+		switch (pci_get_device(sc->sc_pcidev)) {
+		case PCI_PRODUCT_NETSEC_7751:	return "NetSec 7751";
+		}
+		return "NetSec unknown-part";
+	}
+	return "Unknown-vendor unknown-part";
+}
+
+static u_int
+checkmaxmin(struct pci_dev *dev, const char *what, u_int v, u_int min, u_int max)
+{
+	struct hifn_softc *sc = pci_get_drvdata(dev);
+	if (v > max) {
+		device_printf(sc->sc_dev, "Warning, %s %u out of range, "
+			"using max %u\n", what, v, max);
+		v = max;
+	} else if (v < min) {
+		device_printf(sc->sc_dev, "Warning, %s %u out of range, "
+			"using min %u\n", what, v, min);
+		v = min;
+	}
+	return v;
+}
+
+/*
+ * Select PLL configuration for 795x parts.  This is complicated in
+ * that we cannot determine the optimal parameters without user input.
+ * The reference clock is derived from an external clock through a
+ * multiplier.  The external clock is either the host bus (i.e. PCI)
+ * or an external clock generator.  When using the PCI bus we assume
+ * the clock is either 33 or 66 MHz; for an external source we cannot
+ * tell the speed.
+ *
+ * PLL configuration is done with a string: "pci" for PCI bus, or "ext"
+ * for an external source, followed by the frequency.  We calculate
+ * the appropriate multiplier and PLL register contents accordingly.
+ * When no configuration is given we default to "pci66" since that
+ * always will allow the card to work.  If a card is using the PCI
+ * bus clock and in a 33MHz slot then it will be operating at half
+ * speed until the correct information is provided.
+ *
+ * We use a default setting of "ext66" because according to Mike Ham
+ * of HiFn, almost every board in existence has an external crystal
+ * populated at 66Mhz. Using PCI can be a problem on modern motherboards,
+ * because PCI33 can have clocks from 0 to 33Mhz, and some have
+ * non-PCI-compliant spread-spectrum clocks, which can confuse the pll.
+ */
+static void
+hifn_getpllconfig(struct pci_dev *dev, u_int *pll)
+{
+	const char *pllspec = hifn_pllconfig;
+	u_int freq, mul, fl, fh;
+	u_int32_t pllconfig;
+	char *nxt;
+
+	if (pllspec == NULL)
+		pllspec = "ext66";
+	fl = 33, fh = 66;
+	pllconfig = 0;
+	if (strncmp(pllspec, "ext", 3) == 0) {
+		pllspec += 3;
+		pllconfig |= HIFN_PLL_REF_SEL;
+		switch (pci_get_device(dev)) {
+		case PCI_PRODUCT_HIFN_7955:
+		case PCI_PRODUCT_HIFN_7956:
+			fl = 20, fh = 100;
+			break;
+#ifdef notyet
+		case PCI_PRODUCT_HIFN_7954:
+			fl = 20, fh = 66;
+			break;
+#endif
+		}
+	} else if (strncmp(pllspec, "pci", 3) == 0)
+		pllspec += 3;
+	freq = strtoul(pllspec, &nxt, 10);
+	if (nxt == pllspec)
+		freq = 66;
+	else
+		freq = checkmaxmin(dev, "frequency", freq, fl, fh);
+	/*
+	 * Calculate multiplier.  We target a Fck of 266 MHz,
+	 * allowing only even values, possibly rounded down.
+	 * Multipliers > 8 must set the charge pump current.
+	 */
+	mul = checkmaxmin(dev, "PLL divisor", (266 / freq) &~ 1, 2, 12);
+	pllconfig |= (mul / 2 - 1) << HIFN_PLL_ND_SHIFT;
+	if (mul > 8)
+		pllconfig |= HIFN_PLL_IS;
+	*pll = pllconfig;
+}
+
+/*
+ * Attach an interface that successfully probed.
+ */
+static int
+hifn_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+	struct hifn_softc *sc = NULL;
+	char rbase;
+	u_int16_t ena, rev;
+	int rseg, rc;
+	unsigned long mem_start, mem_len;
+	static int num_chips = 0;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (pci_enable_device(dev) < 0)
+		return(-ENODEV);
+
+	if (pci_set_mwi(dev))
+		return(-ENODEV);
+
+	if (!dev->irq) {
+		printk("hifn: found device with no IRQ assigned. check BIOS settings!");
+		pci_disable_device(dev);
+		return(-ENODEV);
+	}
+
+	sc = (struct hifn_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
+	if (!sc)
+		return(-ENOMEM);
+	memset(sc, 0, sizeof(*sc));
+
+	softc_device_init(sc, "hifn", num_chips, hifn_methods);
+
+	sc->sc_pcidev = dev;
+	sc->sc_irq = -1;
+	sc->sc_cid = -1;
+	sc->sc_num = num_chips++;
+	if (sc->sc_num < HIFN_MAX_CHIPS)
+		hifn_chip_idx[sc->sc_num] = sc;
+
+	pci_set_drvdata(sc->sc_pcidev, sc);
+
+	spin_lock_init(&sc->sc_mtx);
+
+	/* XXX handle power management */
+
+	/*
+	 * The 7951 and 795x have a random number generator and
+	 * public key support; note this.
+	 */
+	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
+	    (pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
+	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
+	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))
+		sc->sc_flags = HIFN_HAS_RNG | HIFN_HAS_PUBLIC;
+	/*
+	 * The 7811 has a random number generator and
+	 * we also note it's identity 'cuz of some quirks.
+	 */
+	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
+	    pci_get_device(dev) == PCI_PRODUCT_HIFN_7811)
+		sc->sc_flags |= HIFN_IS_7811 | HIFN_HAS_RNG;
+
+	/*
+	 * The 795x parts support AES.
+	 */
+	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
+	    (pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
+	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7956)) {
+		sc->sc_flags |= HIFN_IS_7956 | HIFN_HAS_AES;
+		/*
+		 * Select PLL configuration.  This depends on the
+		 * bus and board design and must be manually configured
+		 * if the default setting is unacceptable.
+		 */
+		hifn_getpllconfig(dev, &sc->sc_pllconfig);
+	}
+
+	/*
+	 * Setup PCI resources. Note that we record the bus
+	 * tag and handle for each register mapping, this is
+	 * used by the READ_REG_0, WRITE_REG_0, READ_REG_1,
+	 * and WRITE_REG_1 macros throughout the driver.
+	 */
+	mem_start = pci_resource_start(sc->sc_pcidev, 0);
+	mem_len   = pci_resource_len(sc->sc_pcidev, 0);
+	sc->sc_bar0 = (ocf_iomem_t) ioremap(mem_start, mem_len);
+	if (!sc->sc_bar0) {
+		device_printf(sc->sc_dev, "cannot map bar%d register space\n", 0);
+		goto fail;
+	}
+	sc->sc_bar0_lastreg = (bus_size_t) -1;
+
+	mem_start = pci_resource_start(sc->sc_pcidev, 1);
+	mem_len   = pci_resource_len(sc->sc_pcidev, 1);
+	sc->sc_bar1 = (ocf_iomem_t) ioremap(mem_start, mem_len);
+	if (!sc->sc_bar1) {
+		device_printf(sc->sc_dev, "cannot map bar%d register space\n", 1);
+		goto fail;
+	}
+	sc->sc_bar1_lastreg = (bus_size_t) -1;
+
+	/* fix up the bus size */
+	if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
+		device_printf(sc->sc_dev, "No usable DMA configuration, aborting.\n");
+		goto fail;
+	}
+	if (pci_set_consistent_dma_mask(dev, DMA_32BIT_MASK)) {
+		device_printf(sc->sc_dev,
+				"No usable consistent DMA configuration, aborting.\n");
+		goto fail;
+	}
+
+	hifn_set_retry(sc);
+
+	/*
+	 * Setup the area where the Hifn DMA's descriptors
+	 * and associated data structures.
+	 */
+	sc->sc_dma = (struct hifn_dma *) pci_alloc_consistent(dev,
+			sizeof(*sc->sc_dma),
+			&sc->sc_dma_physaddr);
+	if (!sc->sc_dma) {
+		device_printf(sc->sc_dev, "cannot alloc sc_dma\n");
+		goto fail;
+	}
+	bzero(sc->sc_dma, sizeof(*sc->sc_dma));
+
+	/*
+	 * Reset the board and do the ``secret handshake''
+	 * to enable the crypto support.  Then complete the
+	 * initialization procedure by setting up the interrupt
+	 * and hooking in to the system crypto support so we'll
+	 * get used for system services like the crypto device,
+	 * IPsec, RNG device, etc.
+	 */
+	hifn_reset_board(sc, 0);
+
+	if (hifn_enable_crypto(sc) != 0) {
+		device_printf(sc->sc_dev, "crypto enabling failed\n");
+		goto fail;
+	}
+	hifn_reset_puc(sc);
+
+	hifn_init_dma(sc);
+	hifn_init_pci_registers(sc);
+
+	pci_set_master(sc->sc_pcidev);
+
+	/* XXX can't dynamically determine ram type for 795x; force dram */
+	if (sc->sc_flags & HIFN_IS_7956)
+		sc->sc_drammodel = 1;
+	else if (hifn_ramtype(sc))
+		goto fail;
+
+	if (sc->sc_drammodel == 0)
+		hifn_sramsize(sc);
+	else
+		hifn_dramsize(sc);
+
+	/*
+	 * Workaround for NetSec 7751 rev A: half ram size because two
+	 * of the address lines were left floating
+	 */
+	if (pci_get_vendor(dev) == PCI_VENDOR_NETSEC &&
+	    pci_get_device(dev) == PCI_PRODUCT_NETSEC_7751 &&
+	    pci_get_revid(dev) == 0x61)	/*XXX???*/
+		sc->sc_ramsize >>= 1;
+
+	/*
+	 * Arrange the interrupt line.
+	 */
+	rc = request_irq(dev->irq, hifn_intr, IRQF_SHARED, "hifn", sc);
+	if (rc) {
+		device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
+		goto fail;
+	}
+	sc->sc_irq = dev->irq;
+
+	hifn_sessions(sc);
+
+	/*
+	 * NB: Keep only the low 16 bits; this masks the chip id
+	 *     from the 7951.
+	 */
+	rev = READ_REG_1(sc, HIFN_1_REVID) & 0xffff;
+
+	rseg = sc->sc_ramsize / 1024;
+	rbase = 'K';
+	if (sc->sc_ramsize >= (1024 * 1024)) {
+		rbase = 'M';
+		rseg /= 1024;
+	}
+	device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram",
+		hifn_partname(sc), rev,
+		rseg, rbase, sc->sc_drammodel ? 'd' : 's');
+	if (sc->sc_flags & HIFN_IS_7956)
+		printf(", pll=0x%x<%s clk, %ux mult>",
+			sc->sc_pllconfig,
+			sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
+			2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
+	printf("\n");
+
+	sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
+	if (sc->sc_cid < 0) {
+		device_printf(sc->sc_dev, "could not get crypto driver id\n");
+		goto fail;
+	}
+
+	WRITE_REG_0(sc, HIFN_0_PUCNFG,
+	    READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID);
+	ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
+
+	switch (ena) {
+	case HIFN_PUSTAT_ENA_2:
+		crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
+		crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0);
+		if (sc->sc_flags & HIFN_HAS_AES)
+			crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
+		/*FALLTHROUGH*/
+	case HIFN_PUSTAT_ENA_1:
+		crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
+		crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
+		crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
+		crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
+		crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
+		break;
+	}
+
+	if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG))
+		hifn_init_pubrng(sc);
+
+	init_timer(&sc->sc_tickto);
+	sc->sc_tickto.function = hifn_tick;
+	sc->sc_tickto.data = (unsigned long) sc->sc_num;
+	mod_timer(&sc->sc_tickto, jiffies + HZ);
+
+	return (0);
+
+fail:
+    if (sc->sc_cid >= 0)
+        crypto_unregister_all(sc->sc_cid);
+    if (sc->sc_irq != -1)
+        free_irq(sc->sc_irq, sc);
+    if (sc->sc_dma) {
+		/* Turn off DMA polling */
+		WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+
+        pci_free_consistent(sc->sc_pcidev,
+				sizeof(*sc->sc_dma),
+                sc->sc_dma, sc->sc_dma_physaddr);
+	}
+    kfree(sc);
+	return (-ENXIO);
+}
+
+/*
+ * Detach an interface that successfully probed.
+ */
+static void
+hifn_remove(struct pci_dev *dev)
+{
+	struct hifn_softc *sc = pci_get_drvdata(dev);
+	unsigned long l_flags;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	KASSERT(sc != NULL, ("hifn_detach: null software carrier!"));
+
+	/* disable interrupts */
+	HIFN_LOCK(sc);
+	WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
+	HIFN_UNLOCK(sc);
+
+	/*XXX other resources */
+	del_timer_sync(&sc->sc_tickto);
+
+	/* Turn off DMA polling */
+	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+
+	crypto_unregister_all(sc->sc_cid);
+
+	free_irq(sc->sc_irq, sc);
+
+	pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
+                sc->sc_dma, sc->sc_dma_physaddr);
+}
+
+
+static int
+hifn_init_pubrng(struct hifn_softc *sc)
+{
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if ((sc->sc_flags & HIFN_IS_7811) == 0) {
+		/* Reset 7951 public key/rng engine */
+		WRITE_REG_1(sc, HIFN_1_PUB_RESET,
+		    READ_REG_1(sc, HIFN_1_PUB_RESET) | HIFN_PUBRST_RESET);
+
+		for (i = 0; i < 100; i++) {
+			DELAY(1000);
+			if ((READ_REG_1(sc, HIFN_1_PUB_RESET) &
+			    HIFN_PUBRST_RESET) == 0)
+				break;
+		}
+
+		if (i == 100) {
+			device_printf(sc->sc_dev, "public key init failed\n");
+			return (1);
+		}
+	}
+
+	/* Enable the rng, if available */
+#ifdef CONFIG_OCF_RANDOMHARVEST
+	if (sc->sc_flags & HIFN_HAS_RNG) {
+		if (sc->sc_flags & HIFN_IS_7811) {
+			u_int32_t r;
+			r = READ_REG_1(sc, HIFN_1_7811_RNGENA);
+			if (r & HIFN_7811_RNGENA_ENA) {
+				r &= ~HIFN_7811_RNGENA_ENA;
+				WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r);
+			}
+			WRITE_REG_1(sc, HIFN_1_7811_RNGCFG,
+			    HIFN_7811_RNGCFG_DEFL);
+			r |= HIFN_7811_RNGENA_ENA;
+			WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r);
+		} else
+			WRITE_REG_1(sc, HIFN_1_RNG_CONFIG,
+			    READ_REG_1(sc, HIFN_1_RNG_CONFIG) |
+			    HIFN_RNGCFG_ENA);
+
+		sc->sc_rngfirst = 1;
+		crypto_rregister(sc->sc_cid, hifn_read_random, sc);
+	}
+#endif
+
+	/* Enable public key engine, if available */
+	if (sc->sc_flags & HIFN_HAS_PUBLIC) {
+		WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
+		sc->sc_dmaier |= HIFN_DMAIER_PUBDONE;
+		WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
+#ifdef HIFN_VULCANDEV
+		sc->sc_pkdev = make_dev(&vulcanpk_cdevsw, 0, 
+					UID_ROOT, GID_WHEEL, 0666,
+					"vulcanpk");
+		sc->sc_pkdev->si_drv1 = sc;
+#endif
+	}
+
+	return (0);
+}
+
+#ifdef CONFIG_OCF_RANDOMHARVEST
+static int
+hifn_read_random(void *arg, u_int32_t *buf, int len)
+{
+	struct hifn_softc *sc = (struct hifn_softc *) arg;
+	u_int32_t sts;
+	int i, rc = 0;
+
+	if (len <= 0)
+		return rc;
+
+	if (sc->sc_flags & HIFN_IS_7811) {
+		/* ONLY VALID ON 7811!!!! */
+		for (i = 0; i < 5; i++) {
+			sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS);
+			if (sts & HIFN_7811_RNGSTS_UFL) {
+				device_printf(sc->sc_dev,
+					      "RNG underflow: disabling\n");
+				/* DAVIDM perhaps return -1 */
+				break;
+			}
+			if ((sts & HIFN_7811_RNGSTS_RDY) == 0)
+				break;
+
+			/*
+			 * There are at least two words in the RNG FIFO
+			 * at this point.
+			 */
+			if (rc < len)
+				buf[rc++] = READ_REG_1(sc, HIFN_1_7811_RNGDAT);
+			if (rc < len)
+				buf[rc++] = READ_REG_1(sc, HIFN_1_7811_RNGDAT);
+		}
+	} else
+		buf[rc++] = READ_REG_1(sc, HIFN_1_RNG_DATA);
+
+	/* NB: discard first data read */
+	if (sc->sc_rngfirst) {
+		sc->sc_rngfirst = 0;
+		rc = 0;
+	}
+
+	return(rc);
+}
+#endif /* CONFIG_OCF_RANDOMHARVEST */
+
+static void
+hifn_puc_wait(struct hifn_softc *sc)
+{
+	int i;
+	int reg = HIFN_0_PUCTRL;
+
+	if (sc->sc_flags & HIFN_IS_7956) {
+		reg = HIFN_0_PUCTRL2;
+	}
+
+	for (i = 5000; i > 0; i--) {
+		DELAY(1);
+		if (!(READ_REG_0(sc, reg) & HIFN_PUCTRL_RESET))
+			break;
+	}
+	if (!i)
+		device_printf(sc->sc_dev, "proc unit did not reset(0x%x)\n",
+				READ_REG_0(sc, HIFN_0_PUCTRL));
+}
+
+/*
+ * Reset the processing unit.
+ */
+static void
+hifn_reset_puc(struct hifn_softc *sc)
+{
+	/* Reset processing unit */
+	int reg = HIFN_0_PUCTRL;
+
+	if (sc->sc_flags & HIFN_IS_7956) {
+		reg = HIFN_0_PUCTRL2;
+	}
+	WRITE_REG_0(sc, reg, HIFN_PUCTRL_DMAENA);
+
+	hifn_puc_wait(sc);
+}
+
+/*
+ * Set the Retry and TRDY registers; note that we set them to
+ * zero because the 7811 locks up when forced to retry (section
+ * 3.6 of "Specification Update SU-0014-04".  Not clear if we
+ * should do this for all Hifn parts, but it doesn't seem to hurt.
+ */
+static void
+hifn_set_retry(struct hifn_softc *sc)
+{
+	DPRINTF("%s()\n", __FUNCTION__);
+	/* NB: RETRY only responds to 8-bit reads/writes */
+	pci_write_config_byte(sc->sc_pcidev, HIFN_RETRY_TIMEOUT, 0);
+	pci_write_config_dword(sc->sc_pcidev, HIFN_TRDY_TIMEOUT, 0);
+}
+
+/*
+ * Resets the board.  Values in the regesters are left as is
+ * from the reset (i.e. initial values are assigned elsewhere).
+ */
+static void
+hifn_reset_board(struct hifn_softc *sc, int full)
+{
+	u_int32_t reg;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+	/*
+	 * Set polling in the DMA configuration register to zero.  0x7 avoids
+	 * resetting the board and zeros out the other fields.
+	 */
+	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+
+	/*
+	 * Now that polling has been disabled, we have to wait 1 ms
+	 * before resetting the board.
+	 */
+	DELAY(1000);
+
+	/* Reset the DMA unit */
+	if (full) {
+		WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE);
+		DELAY(1000);
+	} else {
+		WRITE_REG_1(sc, HIFN_1_DMA_CNFG,
+		    HIFN_DMACNFG_MODE | HIFN_DMACNFG_MSTRESET);
+		hifn_reset_puc(sc);
+	}
+
+	KASSERT(sc->sc_dma != NULL, ("hifn_reset_board: null DMA tag!"));
+	bzero(sc->sc_dma, sizeof(*sc->sc_dma));
+
+	/* Bring dma unit out of reset */
+	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+
+	hifn_puc_wait(sc);
+	hifn_set_retry(sc);
+
+	if (sc->sc_flags & HIFN_IS_7811) {
+		for (reg = 0; reg < 1000; reg++) {
+			if (READ_REG_1(sc, HIFN_1_7811_MIPSRST) &
+			    HIFN_MIPSRST_CRAMINIT)
+				break;
+			DELAY(1000);
+		}
+		if (reg == 1000)
+			device_printf(sc->sc_dev, ": cram init timeout\n");
+	} else {
+	  /* set up DMA configuration register #2 */
+	  /* turn off all PK and BAR0 swaps */
+	  WRITE_REG_1(sc, HIFN_1_DMA_CNFG2,
+		      (3 << HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT)|
+		      (3 << HIFN_DMACNFG2_INIT_READ_BURST_SHIFT)|
+		      (2 << HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT)|
+		      (2 << HIFN_DMACNFG2_TGT_READ_BURST_SHIFT));
+	}
+}
+
+static u_int32_t
+hifn_next_signature(u_int32_t a, u_int cnt)
+{
+	int i;
+	u_int32_t v;
+
+	for (i = 0; i < cnt; i++) {
+
+		/* get the parity */
+		v = a & 0x80080125;
+		v ^= v >> 16;
+		v ^= v >> 8;
+		v ^= v >> 4;
+		v ^= v >> 2;
+		v ^= v >> 1;
+
+		a = (v & 1) ^ (a << 1);
+	}
+
+	return a;
+}
+
+
+/*
+ * Checks to see if crypto is already enabled.  If crypto isn't enable,
+ * "hifn_enable_crypto" is called to enable it.  The check is important,
+ * as enabling crypto twice will lock the board.
+ */
+static int 
+hifn_enable_crypto(struct hifn_softc *sc)
+{
+	u_int32_t dmacfg, ramcfg, encl, addr, i;
+	char offtbl[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					  0x00, 0x00, 0x00, 0x00 };
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	ramcfg = READ_REG_0(sc, HIFN_0_PUCNFG);
+	dmacfg = READ_REG_1(sc, HIFN_1_DMA_CNFG);
+
+	/*
+	 * The RAM config register's encrypt level bit needs to be set before
+	 * every read performed on the encryption level register.
+	 */
+	WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
+
+	encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
+
+	/*
+	 * Make sure we don't re-unlock.  Two unlocks kills chip until the
+	 * next reboot.
+	 */
+	if (encl == HIFN_PUSTAT_ENA_1 || encl == HIFN_PUSTAT_ENA_2) {
+#ifdef HIFN_DEBUG
+		if (hifn_debug)
+			device_printf(sc->sc_dev,
+			    "Strong crypto already enabled!\n");
+#endif
+		goto report;
+	}
+
+	if (encl != 0 && encl != HIFN_PUSTAT_ENA_0) {
+#ifdef HIFN_DEBUG
+		if (hifn_debug)
+			device_printf(sc->sc_dev,
+			      "Unknown encryption level 0x%x\n", encl);
+#endif
+		return 1;
+	}
+
+	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_UNLOCK |
+	    HIFN_DMACNFG_MSTRESET | HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+	DELAY(1000);
+	addr = READ_REG_1(sc, HIFN_UNLOCK_SECRET1);
+	DELAY(1000);
+	WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, 0);
+	DELAY(1000);
+
+	for (i = 0; i <= 12; i++) {
+		addr = hifn_next_signature(addr, offtbl[i] + 0x101);
+		WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, addr);
+
+		DELAY(1000);
+	}
+
+	WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
+	encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
+
+#ifdef HIFN_DEBUG
+	if (hifn_debug) {
+		if (encl != HIFN_PUSTAT_ENA_1 && encl != HIFN_PUSTAT_ENA_2)
+			device_printf(sc->sc_dev, "Engine is permanently "
+				"locked until next system reset!\n");
+		else
+			device_printf(sc->sc_dev, "Engine enabled "
+				"successfully!\n");
+	}
+#endif
+
+report:
+	WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg);
+	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, dmacfg);
+
+	switch (encl) {
+	case HIFN_PUSTAT_ENA_1:
+	case HIFN_PUSTAT_ENA_2:
+		break;
+	case HIFN_PUSTAT_ENA_0:
+	default:
+		device_printf(sc->sc_dev, "disabled\n");
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * Give initial values to the registers listed in the "Register Space"
+ * section of the HIFN Software Development reference manual.
+ */
+static void 
+hifn_init_pci_registers(struct hifn_softc *sc)
+{
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	/* write fixed values needed by the Initialization registers */
+	WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
+	WRITE_REG_0(sc, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD);
+	WRITE_REG_0(sc, HIFN_0_PUIER, HIFN_PUIER_DSTOVER);
+
+	/* write all 4 ring address registers */
+	WRITE_REG_1(sc, HIFN_1_DMA_CRAR, sc->sc_dma_physaddr +
+	    offsetof(struct hifn_dma, cmdr[0]));
+	WRITE_REG_1(sc, HIFN_1_DMA_SRAR, sc->sc_dma_physaddr +
+	    offsetof(struct hifn_dma, srcr[0]));
+	WRITE_REG_1(sc, HIFN_1_DMA_DRAR, sc->sc_dma_physaddr +
+	    offsetof(struct hifn_dma, dstr[0]));
+	WRITE_REG_1(sc, HIFN_1_DMA_RRAR, sc->sc_dma_physaddr +
+	    offsetof(struct hifn_dma, resr[0]));
+
+	DELAY(2000);
+
+	/* write status register */
+	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
+	    HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
+	    HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS |
+	    HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
+	    HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
+	    HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
+	    HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
+	    HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
+	    HIFN_DMACSR_S_WAIT |
+	    HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
+	    HIFN_DMACSR_C_WAIT |
+	    HIFN_DMACSR_ENGINE |
+	    ((sc->sc_flags & HIFN_HAS_PUBLIC) ?
+		HIFN_DMACSR_PUBDONE : 0) |
+	    ((sc->sc_flags & HIFN_IS_7811) ?
+		HIFN_DMACSR_ILLW | HIFN_DMACSR_ILLR : 0));
+
+	sc->sc_d_busy = sc->sc_r_busy = sc->sc_s_busy = sc->sc_c_busy = 0;
+	sc->sc_dmaier |= HIFN_DMAIER_R_DONE | HIFN_DMAIER_C_ABORT |
+	    HIFN_DMAIER_D_OVER | HIFN_DMAIER_R_OVER |
+	    HIFN_DMAIER_S_ABORT | HIFN_DMAIER_D_ABORT | HIFN_DMAIER_R_ABORT |
+	    ((sc->sc_flags & HIFN_IS_7811) ?
+		HIFN_DMAIER_ILLW | HIFN_DMAIER_ILLR : 0);
+	sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
+	WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
+
+
+	if (sc->sc_flags & HIFN_IS_7956) {
+		u_int32_t pll;
+
+		WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
+		    HIFN_PUCNFG_TCALLPHASES |
+		    HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32);
+
+		/* turn off the clocks and insure bypass is set */
+		pll = READ_REG_1(sc, HIFN_1_PLL);
+		pll = (pll &~ (HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL))
+		  | HIFN_PLL_BP | HIFN_PLL_MBSET;
+		WRITE_REG_1(sc, HIFN_1_PLL, pll);
+		DELAY(10*1000);		/* 10ms */
+
+		/* change configuration */
+		pll = (pll &~ HIFN_PLL_CONFIG) | sc->sc_pllconfig;
+		WRITE_REG_1(sc, HIFN_1_PLL, pll);
+		DELAY(10*1000);		/* 10ms */
+
+		/* disable bypass */
+		pll &= ~HIFN_PLL_BP;
+		WRITE_REG_1(sc, HIFN_1_PLL, pll);
+		/* enable clocks with new configuration */
+		pll |= HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL;
+		WRITE_REG_1(sc, HIFN_1_PLL, pll);
+	} else {
+		WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
+		    HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
+		    HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
+		    (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
+	}
+
+	WRITE_REG_0(sc, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
+	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST |
+	    ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) |
+	    ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL));
+}
+
+/*
+ * The maximum number of sessions supported by the card
+ * is dependent on the amount of context ram, which
+ * encryption algorithms are enabled, and how compression
+ * is configured.  This should be configured before this
+ * routine is called.
+ */
+static void
+hifn_sessions(struct hifn_softc *sc)
+{
+	u_int32_t pucnfg;
+	int ctxsize;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	pucnfg = READ_REG_0(sc, HIFN_0_PUCNFG);
+
+	if (pucnfg & HIFN_PUCNFG_COMPSING) {
+		if (pucnfg & HIFN_PUCNFG_ENCCNFG)
+			ctxsize = 128;
+		else
+			ctxsize = 512;
+		/*
+		 * 7955/7956 has internal context memory of 32K
+		 */
+		if (sc->sc_flags & HIFN_IS_7956)
+			sc->sc_maxses = 32768 / ctxsize;
+		else
+			sc->sc_maxses = 1 +
+			    ((sc->sc_ramsize - 32768) / ctxsize);
+	} else
+		sc->sc_maxses = sc->sc_ramsize / 16384;
+
+	if (sc->sc_maxses > 2048)
+		sc->sc_maxses = 2048;
+}
+
+/*
+ * Determine ram type (sram or dram).  Board should be just out of a reset
+ * state when this is called.
+ */
+static int
+hifn_ramtype(struct hifn_softc *sc)
+{
+	u_int8_t data[8], dataexpect[8];
+	int i;
+
+	for (i = 0; i < sizeof(data); i++)
+		data[i] = dataexpect[i] = 0x55;
+	if (hifn_writeramaddr(sc, 0, data))
+		return (-1);
+	if (hifn_readramaddr(sc, 0, data))
+		return (-1);
+	if (bcmp(data, dataexpect, sizeof(data)) != 0) {
+		sc->sc_drammodel = 1;
+		return (0);
+	}
+
+	for (i = 0; i < sizeof(data); i++)
+		data[i] = dataexpect[i] = 0xaa;
+	if (hifn_writeramaddr(sc, 0, data))
+		return (-1);
+	if (hifn_readramaddr(sc, 0, data))
+		return (-1);
+	if (bcmp(data, dataexpect, sizeof(data)) != 0) {
+		sc->sc_drammodel = 1;
+		return (0);
+	}
+
+	return (0);
+}
+
+#define	HIFN_SRAM_MAX		(32 << 20)
+#define	HIFN_SRAM_STEP_SIZE	16384
+#define	HIFN_SRAM_GRANULARITY	(HIFN_SRAM_MAX / HIFN_SRAM_STEP_SIZE)
+
+static int
+hifn_sramsize(struct hifn_softc *sc)
+{
+	u_int32_t a;
+	u_int8_t data[8];
+	u_int8_t dataexpect[sizeof(data)];
+	int32_t i;
+
+	for (i = 0; i < sizeof(data); i++)
+		data[i] = dataexpect[i] = i ^ 0x5a;
+
+	for (i = HIFN_SRAM_GRANULARITY - 1; i >= 0; i--) {
+		a = i * HIFN_SRAM_STEP_SIZE;
+		bcopy(&i, data, sizeof(i));
+		hifn_writeramaddr(sc, a, data);
+	}
+
+	for (i = 0; i < HIFN_SRAM_GRANULARITY; i++) {
+		a = i * HIFN_SRAM_STEP_SIZE;
+		bcopy(&i, dataexpect, sizeof(i));
+		if (hifn_readramaddr(sc, a, data) < 0)
+			return (0);
+		if (bcmp(data, dataexpect, sizeof(data)) != 0)
+			return (0);
+		sc->sc_ramsize = a + HIFN_SRAM_STEP_SIZE;
+	}
+
+	return (0);
+}
+
+/*
+ * XXX For dram boards, one should really try all of the
+ * HIFN_PUCNFG_DSZ_*'s.  This just assumes that PUCNFG
+ * is already set up correctly.
+ */
+static int
+hifn_dramsize(struct hifn_softc *sc)
+{
+	u_int32_t cnfg;
+
+	if (sc->sc_flags & HIFN_IS_7956) {
+		/*
+		 * 7955/7956 have a fixed internal ram of only 32K.
+		 */
+		sc->sc_ramsize = 32768;
+	} else {
+		cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
+		    HIFN_PUCNFG_DRAMMASK;
+		sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
+	}
+	return (0);
+}
+
+static void
+hifn_alloc_slot(struct hifn_softc *sc, int *cmdp, int *srcp, int *dstp, int *resp)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (dma->cmdi == HIFN_D_CMD_RSIZE) {
+		dma->cmdi = 0;
+		dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
+		wmb();
+		dma->cmdr[HIFN_D_CMD_RSIZE].l |= htole32(HIFN_D_VALID);
+		HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE,
+		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+	}
+	*cmdp = dma->cmdi++;
+	dma->cmdk = dma->cmdi;
+
+	if (dma->srci == HIFN_D_SRC_RSIZE) {
+		dma->srci = 0;
+		dma->srcr[HIFN_D_SRC_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
+		wmb();
+		dma->srcr[HIFN_D_SRC_RSIZE].l |= htole32(HIFN_D_VALID);
+		HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
+		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+	}
+	*srcp = dma->srci++;
+	dma->srck = dma->srci;
+
+	if (dma->dsti == HIFN_D_DST_RSIZE) {
+		dma->dsti = 0;
+		dma->dstr[HIFN_D_DST_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
+		wmb();
+		dma->dstr[HIFN_D_DST_RSIZE].l |= htole32(HIFN_D_VALID);
+		HIFN_DSTR_SYNC(sc, HIFN_D_DST_RSIZE,
+		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+	}
+	*dstp = dma->dsti++;
+	dma->dstk = dma->dsti;
+
+	if (dma->resi == HIFN_D_RES_RSIZE) {
+		dma->resi = 0;
+		dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
+		wmb();
+		dma->resr[HIFN_D_RES_RSIZE].l |= htole32(HIFN_D_VALID);
+		HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE,
+		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+	}
+	*resp = dma->resi++;
+	dma->resk = dma->resi;
+}
+
+static int
+hifn_writeramaddr(struct hifn_softc *sc, int addr, u_int8_t *data)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+	hifn_base_command_t wc;
+	const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
+	int r, cmdi, resi, srci, dsti;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	wc.masks = htole16(3 << 13);
+	wc.session_num = htole16(addr >> 14);
+	wc.total_source_count = htole16(8);
+	wc.total_dest_count = htole16(addr & 0x3fff);
+
+	hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi);
+
+	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
+	    HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
+	    HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA);
+
+	/* build write command */
+	bzero(dma->command_bufs[cmdi], HIFN_MAX_COMMAND);
+	*(hifn_base_command_t *)dma->command_bufs[cmdi] = wc;
+	bcopy(data, &dma->test_src, sizeof(dma->test_src));
+
+	dma->srcr[srci].p = htole32(sc->sc_dma_physaddr
+	    + offsetof(struct hifn_dma, test_src));
+	dma->dstr[dsti].p = htole32(sc->sc_dma_physaddr
+	    + offsetof(struct hifn_dma, test_dst));
+
+	dma->cmdr[cmdi].l = htole32(16 | masks);
+	dma->srcr[srci].l = htole32(8 | masks);
+	dma->dstr[dsti].l = htole32(4 | masks);
+	dma->resr[resi].l = htole32(4 | masks);
+
+	for (r = 10000; r >= 0; r--) {
+		DELAY(10);
+		if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0)
+			break;
+	}
+	if (r == 0) {
+		device_printf(sc->sc_dev, "writeramaddr -- "
+		    "result[%d](addr %d) still valid\n", resi, addr);
+		r = -1;
+		return (-1);
+	} else
+		r = 0;
+
+	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
+	    HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS |
+	    HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS);
+
+	return (r);
+}
+
+static int
+hifn_readramaddr(struct hifn_softc *sc, int addr, u_int8_t *data)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+	hifn_base_command_t rc;
+	const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
+	int r, cmdi, srci, dsti, resi;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	rc.masks = htole16(2 << 13);
+	rc.session_num = htole16(addr >> 14);
+	rc.total_source_count = htole16(addr & 0x3fff);
+	rc.total_dest_count = htole16(8);
+
+	hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi);
+
+	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
+	    HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
+	    HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA);
+
+	bzero(dma->command_bufs[cmdi], HIFN_MAX_COMMAND);
+	*(hifn_base_command_t *)dma->command_bufs[cmdi] = rc;
+
+	dma->srcr[srci].p = htole32(sc->sc_dma_physaddr +
+	    offsetof(struct hifn_dma, test_src));
+	dma->test_src = 0;
+	dma->dstr[dsti].p =  htole32(sc->sc_dma_physaddr +
+	    offsetof(struct hifn_dma, test_dst));
+	dma->test_dst = 0;
+	dma->cmdr[cmdi].l = htole32(8 | masks);
+	dma->srcr[srci].l = htole32(8 | masks);
+	dma->dstr[dsti].l = htole32(8 | masks);
+	dma->resr[resi].l = htole32(HIFN_MAX_RESULT | masks);
+
+	for (r = 10000; r >= 0; r--) {
+		DELAY(10);
+		if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0)
+			break;
+	}
+	if (r == 0) {
+		device_printf(sc->sc_dev, "readramaddr -- "
+		    "result[%d](addr %d) still valid\n", resi, addr);
+		r = -1;
+	} else {
+		r = 0;
+		bcopy(&dma->test_dst, data, sizeof(dma->test_dst));
+	}
+
+	WRITE_REG_1(sc, HIFN_1_DMA_CSR,
+	    HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS |
+	    HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS);
+
+	return (r);
+}
+
+/*
+ * Initialize the descriptor rings.
+ */
+static void 
+hifn_init_dma(struct hifn_softc *sc)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	hifn_set_retry(sc);
+
+	/* initialize static pointer values */
+	for (i = 0; i < HIFN_D_CMD_RSIZE; i++)
+		dma->cmdr[i].p = htole32(sc->sc_dma_physaddr +
+		    offsetof(struct hifn_dma, command_bufs[i][0]));
+	for (i = 0; i < HIFN_D_RES_RSIZE; i++)
+		dma->resr[i].p = htole32(sc->sc_dma_physaddr +
+		    offsetof(struct hifn_dma, result_bufs[i][0]));
+
+	dma->cmdr[HIFN_D_CMD_RSIZE].p =
+	    htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, cmdr[0]));
+	dma->srcr[HIFN_D_SRC_RSIZE].p =
+	    htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, srcr[0]));
+	dma->dstr[HIFN_D_DST_RSIZE].p =
+	    htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, dstr[0]));
+	dma->resr[HIFN_D_RES_RSIZE].p =
+	    htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, resr[0]));
+
+	dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0;
+	dma->cmdi = dma->srci = dma->dsti = dma->resi = 0;
+	dma->cmdk = dma->srck = dma->dstk = dma->resk = 0;
+}
+
+/*
+ * Writes out the raw command buffer space.  Returns the
+ * command buffer size.
+ */
+static u_int
+hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
+{
+	struct hifn_softc *sc = NULL;
+	u_int8_t *buf_pos;
+	hifn_base_command_t *base_cmd;
+	hifn_mac_command_t *mac_cmd;
+	hifn_crypt_command_t *cry_cmd;
+	int using_mac, using_crypt, len, ivlen;
+	u_int32_t dlen, slen;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	buf_pos = buf;
+	using_mac = cmd->base_masks & HIFN_BASE_CMD_MAC;
+	using_crypt = cmd->base_masks & HIFN_BASE_CMD_CRYPT;
+
+	base_cmd = (hifn_base_command_t *)buf_pos;
+	base_cmd->masks = htole16(cmd->base_masks);
+	slen = cmd->src_mapsize;
+	if (cmd->sloplen)
+		dlen = cmd->dst_mapsize - cmd->sloplen + sizeof(u_int32_t);
+	else
+		dlen = cmd->dst_mapsize;
+	base_cmd->total_source_count = htole16(slen & HIFN_BASE_CMD_LENMASK_LO);
+	base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO);
+	dlen >>= 16;
+	slen >>= 16;
+	base_cmd->session_num = htole16(
+	    ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
+	    ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
+	buf_pos += sizeof(hifn_base_command_t);
+
+	if (using_mac) {
+		mac_cmd = (hifn_mac_command_t *)buf_pos;
+		dlen = cmd->maccrd->crd_len;
+		mac_cmd->source_count = htole16(dlen & 0xffff);
+		dlen >>= 16;
+		mac_cmd->masks = htole16(cmd->mac_masks |
+		    ((dlen << HIFN_MAC_CMD_SRCLEN_S) & HIFN_MAC_CMD_SRCLEN_M));
+		mac_cmd->header_skip = htole16(cmd->maccrd->crd_skip);
+		mac_cmd->reserved = 0;
+		buf_pos += sizeof(hifn_mac_command_t);
+	}
+
+	if (using_crypt) {
+		cry_cmd = (hifn_crypt_command_t *)buf_pos;
+		dlen = cmd->enccrd->crd_len;
+		cry_cmd->source_count = htole16(dlen & 0xffff);
+		dlen >>= 16;
+		cry_cmd->masks = htole16(cmd->cry_masks |
+		    ((dlen << HIFN_CRYPT_CMD_SRCLEN_S) & HIFN_CRYPT_CMD_SRCLEN_M));
+		cry_cmd->header_skip = htole16(cmd->enccrd->crd_skip);
+		cry_cmd->reserved = 0;
+		buf_pos += sizeof(hifn_crypt_command_t);
+	}
+
+	if (using_mac && cmd->mac_masks & HIFN_MAC_CMD_NEW_KEY) {
+		bcopy(cmd->mac, buf_pos, HIFN_MAC_KEY_LENGTH);
+		buf_pos += HIFN_MAC_KEY_LENGTH;
+	}
+
+	if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_KEY) {
+		switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
+		case HIFN_CRYPT_CMD_ALG_3DES:
+			bcopy(cmd->ck, buf_pos, HIFN_3DES_KEY_LENGTH);
+			buf_pos += HIFN_3DES_KEY_LENGTH;
+			break;
+		case HIFN_CRYPT_CMD_ALG_DES:
+			bcopy(cmd->ck, buf_pos, HIFN_DES_KEY_LENGTH);
+			buf_pos += HIFN_DES_KEY_LENGTH;
+			break;
+		case HIFN_CRYPT_CMD_ALG_RC4:
+			len = 256;
+			do {
+				int clen;
+
+				clen = MIN(cmd->cklen, len);
+				bcopy(cmd->ck, buf_pos, clen);
+				len -= clen;
+				buf_pos += clen;
+			} while (len > 0);
+			bzero(buf_pos, 4);
+			buf_pos += 4;
+			break;
+		case HIFN_CRYPT_CMD_ALG_AES:
+			/*
+			 * AES keys are variable 128, 192 and
+			 * 256 bits (16, 24 and 32 bytes).
+			 */
+			bcopy(cmd->ck, buf_pos, cmd->cklen);
+			buf_pos += cmd->cklen;
+			break;
+		}
+	}
+
+	if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_IV) {
+		switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
+		case HIFN_CRYPT_CMD_ALG_AES:
+			ivlen = HIFN_AES_IV_LENGTH;
+			break;
+		default:
+			ivlen = HIFN_IV_LENGTH;
+			break;
+		}
+		bcopy(cmd->iv, buf_pos, ivlen);
+		buf_pos += ivlen;
+	}
+
+	if ((cmd->base_masks & (HIFN_BASE_CMD_MAC|HIFN_BASE_CMD_CRYPT)) == 0) {
+		bzero(buf_pos, 8);
+		buf_pos += 8;
+	}
+
+	return (buf_pos - buf);
+}
+
+static int
+hifn_dmamap_aligned(struct hifn_operand *op)
+{
+	struct hifn_softc *sc = NULL;
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	for (i = 0; i < op->nsegs; i++) {
+		if (op->segs[i].ds_addr & 3)
+			return (0);
+		if ((i != (op->nsegs - 1)) && (op->segs[i].ds_len & 3))
+			return (0);
+	}
+	return (1);
+}
+
+static __inline int
+hifn_dmamap_dstwrap(struct hifn_softc *sc, int idx)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+
+	if (++idx == HIFN_D_DST_RSIZE) {
+		dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP |
+		    HIFN_D_MASKDONEIRQ);
+		HIFN_DSTR_SYNC(sc, idx,
+		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+		idx = 0;
+	}
+	return (idx);
+}
+
+static int
+hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+	struct hifn_operand *dst = &cmd->dst;
+	u_int32_t p, l;
+	int idx, used = 0, i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	idx = dma->dsti;
+	for (i = 0; i < dst->nsegs - 1; i++) {
+		dma->dstr[idx].p = htole32(dst->segs[i].ds_addr);
+		dma->dstr[idx].l = htole32(HIFN_D_MASKDONEIRQ | dst->segs[i].ds_len);
+		wmb();
+		dma->dstr[idx].l |= htole32(HIFN_D_VALID);
+		HIFN_DSTR_SYNC(sc, idx,
+		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+		used++;
+
+		idx = hifn_dmamap_dstwrap(sc, idx);
+	}
+
+	if (cmd->sloplen == 0) {
+		p = dst->segs[i].ds_addr;
+		l = HIFN_D_MASKDONEIRQ | HIFN_D_LAST |
+		    dst->segs[i].ds_len;
+	} else {
+		p = sc->sc_dma_physaddr +
+		    offsetof(struct hifn_dma, slop[cmd->slopidx]);
+		l = HIFN_D_MASKDONEIRQ | HIFN_D_LAST |
+		    sizeof(u_int32_t);
+
+		if ((dst->segs[i].ds_len - cmd->sloplen) != 0) {
+			dma->dstr[idx].p = htole32(dst->segs[i].ds_addr);
+			dma->dstr[idx].l = htole32(HIFN_D_MASKDONEIRQ |
+			    (dst->segs[i].ds_len - cmd->sloplen));
+			wmb();
+			dma->dstr[idx].l |= htole32(HIFN_D_VALID);
+			HIFN_DSTR_SYNC(sc, idx,
+			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+			used++;
+
+			idx = hifn_dmamap_dstwrap(sc, idx);
+		}
+	}
+	dma->dstr[idx].p = htole32(p);
+	dma->dstr[idx].l = htole32(l);
+	wmb();
+	dma->dstr[idx].l |= htole32(HIFN_D_VALID);
+	HIFN_DSTR_SYNC(sc, idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+	used++;
+
+	idx = hifn_dmamap_dstwrap(sc, idx);
+
+	dma->dsti = idx;
+	dma->dstu += used;
+	return (idx);
+}
+
+static __inline int
+hifn_dmamap_srcwrap(struct hifn_softc *sc, int idx)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+
+	if (++idx == HIFN_D_SRC_RSIZE) {
+		dma->srcr[idx].l = htole32(HIFN_D_VALID |
+		    HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
+		HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
+		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+		idx = 0;
+	}
+	return (idx);
+}
+
+static int
+hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+	struct hifn_operand *src = &cmd->src;
+	int idx, i;
+	u_int32_t last = 0;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	idx = dma->srci;
+	for (i = 0; i < src->nsegs; i++) {
+		if (i == src->nsegs - 1)
+			last = HIFN_D_LAST;
+
+		dma->srcr[idx].p = htole32(src->segs[i].ds_addr);
+		dma->srcr[idx].l = htole32(src->segs[i].ds_len |
+		    HIFN_D_MASKDONEIRQ | last);
+		wmb();
+		dma->srcr[idx].l |= htole32(HIFN_D_VALID);
+		HIFN_SRCR_SYNC(sc, idx,
+		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+
+		idx = hifn_dmamap_srcwrap(sc, idx);
+	}
+	dma->srci = idx;
+	dma->srcu += src->nsegs;
+	return (idx);
+} 
+
+
+static int 
+hifn_crypto(
+	struct hifn_softc *sc,
+	struct hifn_command *cmd,
+	struct cryptop *crp,
+	int hint)
+{
+	struct	hifn_dma *dma = sc->sc_dma;
+	u_int32_t cmdlen, csr;
+	int cmdi, resi, err = 0;
+	unsigned long l_flags;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	/*
+	 * need 1 cmd, and 1 res
+	 *
+	 * NB: check this first since it's easy.
+	 */
+	HIFN_LOCK(sc);
+	if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE ||
+	    (dma->resu + 1) > HIFN_D_RES_RSIZE) {
+#ifdef HIFN_DEBUG
+		if (hifn_debug) {
+			device_printf(sc->sc_dev,
+				"cmd/result exhaustion, cmdu %u resu %u\n",
+				dma->cmdu, dma->resu);
+		}
+#endif
+		hifnstats.hst_nomem_cr++;
+		sc->sc_needwakeup |= CRYPTO_SYMQ;
+		HIFN_UNLOCK(sc);
+		return (ERESTART);
+	}
+
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		if (pci_map_skb(sc, &cmd->src, cmd->src_skb)) {
+			hifnstats.hst_nomem_load++;
+			err = ENOMEM;
+			goto err_srcmap1;
+		}
+	} else if (crp->crp_flags & CRYPTO_F_IOV) {
+		if (pci_map_uio(sc, &cmd->src, cmd->src_io)) {
+			hifnstats.hst_nomem_load++;
+			err = ENOMEM;
+			goto err_srcmap1;
+		}
+	} else {
+		if (pci_map_buf(sc, &cmd->src, cmd->src_buf, crp->crp_ilen)) {
+			hifnstats.hst_nomem_load++;
+			err = ENOMEM;
+			goto err_srcmap1;
+		}
+	}
+
+	if (hifn_dmamap_aligned(&cmd->src)) {
+		cmd->sloplen = cmd->src_mapsize & 3;
+		cmd->dst = cmd->src;
+	} else {
+		if (crp->crp_flags & CRYPTO_F_IOV) {
+			DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+			err = EINVAL;
+			goto err_srcmap;
+		} else if (crp->crp_flags & CRYPTO_F_SKBUF) {
+#ifdef NOTYET
+			int totlen, len;
+			struct mbuf *m, *m0, *mlast;
+
+			KASSERT(cmd->dst_m == cmd->src_m,
+				("hifn_crypto: dst_m initialized improperly"));
+			hifnstats.hst_unaligned++;
+			/*
+			 * Source is not aligned on a longword boundary.
+			 * Copy the data to insure alignment.  If we fail
+			 * to allocate mbufs or clusters while doing this
+			 * we return ERESTART so the operation is requeued
+			 * at the crypto later, but only if there are
+			 * ops already posted to the hardware; otherwise we
+			 * have no guarantee that we'll be re-entered.
+			 */
+			totlen = cmd->src_mapsize;
+			if (cmd->src_m->m_flags & M_PKTHDR) {
+				len = MHLEN;
+				MGETHDR(m0, M_DONTWAIT, MT_DATA);
+				if (m0 && !m_dup_pkthdr(m0, cmd->src_m, M_DONTWAIT)) {
+					m_free(m0);
+					m0 = NULL;
+				}
+			} else {
+				len = MLEN;
+				MGET(m0, M_DONTWAIT, MT_DATA);
+			}
+			if (m0 == NULL) {
+				hifnstats.hst_nomem_mbuf++;
+				err = dma->cmdu ? ERESTART : ENOMEM;
+				goto err_srcmap;
+			}
+			if (totlen >= MINCLSIZE) {
+				MCLGET(m0, M_DONTWAIT);
+				if ((m0->m_flags & M_EXT) == 0) {
+					hifnstats.hst_nomem_mcl++;
+					err = dma->cmdu ? ERESTART : ENOMEM;
+					m_freem(m0);
+					goto err_srcmap;
+				}
+				len = MCLBYTES;
+			}
+			totlen -= len;
+			m0->m_pkthdr.len = m0->m_len = len;
+			mlast = m0;
+
+			while (totlen > 0) {
+				MGET(m, M_DONTWAIT, MT_DATA);
+				if (m == NULL) {
+					hifnstats.hst_nomem_mbuf++;
+					err = dma->cmdu ? ERESTART : ENOMEM;
+					m_freem(m0);
+					goto err_srcmap;
+				}
+				len = MLEN;
+				if (totlen >= MINCLSIZE) {
+					MCLGET(m, M_DONTWAIT);
+					if ((m->m_flags & M_EXT) == 0) {
+						hifnstats.hst_nomem_mcl++;
+						err = dma->cmdu ? ERESTART : ENOMEM;
+						mlast->m_next = m;
+						m_freem(m0);
+						goto err_srcmap;
+					}
+					len = MCLBYTES;
+				}
+
+				m->m_len = len;
+				m0->m_pkthdr.len += len;
+				totlen -= len;
+
+				mlast->m_next = m;
+				mlast = m;
+			}
+			cmd->dst_m = m0;
+#else
+			device_printf(sc->sc_dev,
+					"%s,%d: CRYPTO_F_SKBUF unaligned not implemented\n",
+					__FILE__, __LINE__);
+			err = EINVAL;
+			goto err_srcmap;
+#endif
+		} else {
+			device_printf(sc->sc_dev,
+					"%s,%d: unaligned contig buffers not implemented\n",
+					__FILE__, __LINE__);
+			err = EINVAL;
+			goto err_srcmap;
+		}
+	}
+
+	if (cmd->dst_map == NULL) {
+		if (crp->crp_flags & CRYPTO_F_SKBUF) {
+			if (pci_map_skb(sc, &cmd->dst, cmd->dst_skb)) {
+				hifnstats.hst_nomem_map++;
+				err = ENOMEM;
+				goto err_dstmap1;
+			}
+		} else if (crp->crp_flags & CRYPTO_F_IOV) {
+			if (pci_map_uio(sc, &cmd->dst, cmd->dst_io)) {
+				hifnstats.hst_nomem_load++;
+				err = ENOMEM;
+				goto err_dstmap1;
+			}
+		} else {
+			if (pci_map_buf(sc, &cmd->dst, cmd->dst_buf, crp->crp_ilen)) {
+				hifnstats.hst_nomem_load++;
+				err = ENOMEM;
+				goto err_dstmap1;
+			}
+		}
+	}
+
+#ifdef HIFN_DEBUG
+	if (hifn_debug) {
+		device_printf(sc->sc_dev,
+		    "Entering cmd: stat %8x ien %8x u %d/%d/%d/%d n %d/%d\n",
+		    READ_REG_1(sc, HIFN_1_DMA_CSR),
+		    READ_REG_1(sc, HIFN_1_DMA_IER),
+		    dma->cmdu, dma->srcu, dma->dstu, dma->resu,
+		    cmd->src_nsegs, cmd->dst_nsegs);
+	}
+#endif
+
+#if 0
+	if (cmd->src_map == cmd->dst_map) {
+		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
+		    BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
+	} else {
+		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
+		    BUS_DMASYNC_PREWRITE);
+		bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
+		    BUS_DMASYNC_PREREAD);
+	}
+#endif
+
+	/*
+	 * need N src, and N dst
+	 */
+	if ((dma->srcu + cmd->src_nsegs) > HIFN_D_SRC_RSIZE ||
+	    (dma->dstu + cmd->dst_nsegs + 1) > HIFN_D_DST_RSIZE) {
+#ifdef HIFN_DEBUG
+		if (hifn_debug) {
+			device_printf(sc->sc_dev,
+				"src/dst exhaustion, srcu %u+%u dstu %u+%u\n",
+				dma->srcu, cmd->src_nsegs,
+				dma->dstu, cmd->dst_nsegs);
+		}
+#endif
+		hifnstats.hst_nomem_sd++;
+		err = ERESTART;
+		goto err_dstmap;
+	}
+
+	if (dma->cmdi == HIFN_D_CMD_RSIZE) {
+		dma->cmdi = 0;
+		dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
+		wmb();
+		dma->cmdr[HIFN_D_CMD_RSIZE].l |= htole32(HIFN_D_VALID);
+		HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE,
+		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+	}
+	cmdi = dma->cmdi++;
+	cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]);
+	HIFN_CMD_SYNC(sc, cmdi, BUS_DMASYNC_PREWRITE);
+
+	/* .p for command/result already set */
+	dma->cmdr[cmdi].l = htole32(cmdlen | HIFN_D_LAST |
+	    HIFN_D_MASKDONEIRQ);
+	wmb();
+	dma->cmdr[cmdi].l |= htole32(HIFN_D_VALID);
+	HIFN_CMDR_SYNC(sc, cmdi,
+	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+	dma->cmdu++;
+
+	/*
+	 * We don't worry about missing an interrupt (which a "command wait"
+	 * interrupt salvages us from), unless there is more than one command
+	 * in the queue.
+	 */
+	if (dma->cmdu > 1) {
+		sc->sc_dmaier |= HIFN_DMAIER_C_WAIT;
+		WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
+	}
+
+	hifnstats.hst_ipackets++;
+	hifnstats.hst_ibytes += cmd->src_mapsize;
+
+	hifn_dmamap_load_src(sc, cmd);
+
+	/*
+	 * Unlike other descriptors, we don't mask done interrupt from
+	 * result descriptor.
+	 */
+#ifdef HIFN_DEBUG
+	if (hifn_debug)
+		device_printf(sc->sc_dev, "load res\n");
+#endif
+	if (dma->resi == HIFN_D_RES_RSIZE) {
+		dma->resi = 0;
+		dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
+		wmb();
+		dma->resr[HIFN_D_RES_RSIZE].l |= htole32(HIFN_D_VALID);
+		HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE,
+		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+	}
+	resi = dma->resi++;
+	KASSERT(dma->hifn_commands[resi] == NULL,
+		("hifn_crypto: command slot %u busy", resi));
+	dma->hifn_commands[resi] = cmd;
+	HIFN_RES_SYNC(sc, resi, BUS_DMASYNC_PREREAD);
+	if ((hint & CRYPTO_HINT_MORE) && sc->sc_curbatch < hifn_maxbatch) {
+		dma->resr[resi].l = htole32(HIFN_MAX_RESULT |
+		    HIFN_D_LAST | HIFN_D_MASKDONEIRQ);
+		wmb();
+		dma->resr[resi].l |= htole32(HIFN_D_VALID);
+		sc->sc_curbatch++;
+		if (sc->sc_curbatch > hifnstats.hst_maxbatch)
+			hifnstats.hst_maxbatch = sc->sc_curbatch;
+		hifnstats.hst_totbatch++;
+	} else {
+		dma->resr[resi].l = htole32(HIFN_MAX_RESULT | HIFN_D_LAST);
+		wmb();
+		dma->resr[resi].l |= htole32(HIFN_D_VALID);
+		sc->sc_curbatch = 0;
+	}
+	HIFN_RESR_SYNC(sc, resi,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+	dma->resu++;
+
+	if (cmd->sloplen)
+		cmd->slopidx = resi;
+
+	hifn_dmamap_load_dst(sc, cmd);
+
+	csr = 0;
+	if (sc->sc_c_busy == 0) {
+		csr |= HIFN_DMACSR_C_CTRL_ENA;
+		sc->sc_c_busy = 1;
+	}
+	if (sc->sc_s_busy == 0) {
+		csr |= HIFN_DMACSR_S_CTRL_ENA;
+		sc->sc_s_busy = 1;
+	}
+	if (sc->sc_r_busy == 0) {
+		csr |= HIFN_DMACSR_R_CTRL_ENA;
+		sc->sc_r_busy = 1;
+	}
+	if (sc->sc_d_busy == 0) {
+		csr |= HIFN_DMACSR_D_CTRL_ENA;
+		sc->sc_d_busy = 1;
+	}
+	if (csr)
+		WRITE_REG_1(sc, HIFN_1_DMA_CSR, csr);
+
+#ifdef HIFN_DEBUG
+	if (hifn_debug) {
+		device_printf(sc->sc_dev, "command: stat %8x ier %8x\n",
+		    READ_REG_1(sc, HIFN_1_DMA_CSR),
+		    READ_REG_1(sc, HIFN_1_DMA_IER));
+	}
+#endif
+
+	sc->sc_active = 5;
+	HIFN_UNLOCK(sc);
+	KASSERT(err == 0, ("hifn_crypto: success with error %u", err));
+	return (err);		/* success */
+
+err_dstmap:
+	if (cmd->src_map != cmd->dst_map)
+		pci_unmap_buf(sc, &cmd->dst);
+err_dstmap1:
+err_srcmap:
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		if (cmd->src_skb != cmd->dst_skb)
+#ifdef NOTYET
+			m_freem(cmd->dst_m);
+#else
+			device_printf(sc->sc_dev,
+					"%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
+					__FILE__, __LINE__);
+#endif
+	}
+	pci_unmap_buf(sc, &cmd->src);
+err_srcmap1:
+	HIFN_UNLOCK(sc);
+	return (err);
+}
+
+static void
+hifn_tick(unsigned long arg)
+{
+	struct hifn_softc *sc;
+	unsigned long l_flags;
+
+	if (arg >= HIFN_MAX_CHIPS)
+		return;
+	sc = hifn_chip_idx[arg];
+	if (!sc)
+		return;
+
+	HIFN_LOCK(sc);
+	if (sc->sc_active == 0) {
+		struct hifn_dma *dma = sc->sc_dma;
+		u_int32_t r = 0;
+
+		if (dma->cmdu == 0 && sc->sc_c_busy) {
+			sc->sc_c_busy = 0;
+			r |= HIFN_DMACSR_C_CTRL_DIS;
+		}
+		if (dma->srcu == 0 && sc->sc_s_busy) {
+			sc->sc_s_busy = 0;
+			r |= HIFN_DMACSR_S_CTRL_DIS;
+		}
+		if (dma->dstu == 0 && sc->sc_d_busy) {
+			sc->sc_d_busy = 0;
+			r |= HIFN_DMACSR_D_CTRL_DIS;
+		}
+		if (dma->resu == 0 && sc->sc_r_busy) {
+			sc->sc_r_busy = 0;
+			r |= HIFN_DMACSR_R_CTRL_DIS;
+		}
+		if (r)
+			WRITE_REG_1(sc, HIFN_1_DMA_CSR, r);
+	} else
+		sc->sc_active--;
+	HIFN_UNLOCK(sc);
+	mod_timer(&sc->sc_tickto, jiffies + HZ);
+}
+
+static irqreturn_t
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+hifn_intr(int irq, void *arg)
+#else
+hifn_intr(int irq, void *arg, struct pt_regs *regs)
+#endif
+{
+	struct hifn_softc *sc = arg;
+	struct hifn_dma *dma;
+	u_int32_t dmacsr, restart;
+	int i, u;
+	unsigned long l_flags;
+
+	dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR);
+
+	/* Nothing in the DMA unit interrupted */
+	if ((dmacsr & sc->sc_dmaier) == 0)
+		return IRQ_NONE;
+
+	HIFN_LOCK(sc);
+
+	dma = sc->sc_dma;
+
+#ifdef HIFN_DEBUG
+	if (hifn_debug) {
+		device_printf(sc->sc_dev,
+		    "irq: stat %08x ien %08x damier %08x i %d/%d/%d/%d k %d/%d/%d/%d u %d/%d/%d/%d\n",
+		    dmacsr, READ_REG_1(sc, HIFN_1_DMA_IER), sc->sc_dmaier,
+		    dma->cmdi, dma->srci, dma->dsti, dma->resi,
+		    dma->cmdk, dma->srck, dma->dstk, dma->resk,
+		    dma->cmdu, dma->srcu, dma->dstu, dma->resu);
+	}
+#endif
+
+	WRITE_REG_1(sc, HIFN_1_DMA_CSR, dmacsr & sc->sc_dmaier);
+
+	if ((sc->sc_flags & HIFN_HAS_PUBLIC) &&
+	    (dmacsr & HIFN_DMACSR_PUBDONE))
+		WRITE_REG_1(sc, HIFN_1_PUB_STATUS,
+		    READ_REG_1(sc, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE);
+
+	restart = dmacsr & (HIFN_DMACSR_D_OVER | HIFN_DMACSR_R_OVER);
+	if (restart)
+		device_printf(sc->sc_dev, "overrun %x\n", dmacsr);
+
+	if (sc->sc_flags & HIFN_IS_7811) {
+		if (dmacsr & HIFN_DMACSR_ILLR)
+			device_printf(sc->sc_dev, "illegal read\n");
+		if (dmacsr & HIFN_DMACSR_ILLW)
+			device_printf(sc->sc_dev, "illegal write\n");
+	}
+
+	restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT |
+	    HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT);
+	if (restart) {
+		device_printf(sc->sc_dev, "abort, resetting.\n");
+		hifnstats.hst_abort++;
+		hifn_abort(sc);
+		HIFN_UNLOCK(sc);
+		return IRQ_HANDLED;
+	}
+
+	if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
+		/*
+		 * If no slots to process and we receive a "waiting on
+		 * command" interrupt, we disable the "waiting on command"
+		 * (by clearing it).
+		 */
+		sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
+		WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
+	}
+
+	/* clear the rings */
+	i = dma->resk; u = dma->resu;
+	while (u != 0) {
+		HIFN_RESR_SYNC(sc, i,
+		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+		if (dma->resr[i].l & htole32(HIFN_D_VALID)) {
+			HIFN_RESR_SYNC(sc, i,
+			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+			break;
+		}
+
+		if (i != HIFN_D_RES_RSIZE) {
+			struct hifn_command *cmd;
+			u_int8_t *macbuf = NULL;
+
+			HIFN_RES_SYNC(sc, i, BUS_DMASYNC_POSTREAD);
+			cmd = dma->hifn_commands[i];
+			KASSERT(cmd != NULL,
+				("hifn_intr: null command slot %u", i));
+			dma->hifn_commands[i] = NULL;
+
+			if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
+				macbuf = dma->result_bufs[i];
+				macbuf += 12;
+			}
+
+			hifn_callback(sc, cmd, macbuf);
+			hifnstats.hst_opackets++;
+			u--;
+		}
+
+		if (++i == (HIFN_D_RES_RSIZE + 1))
+			i = 0;
+	}
+	dma->resk = i; dma->resu = u;
+
+	i = dma->srck; u = dma->srcu;
+	while (u != 0) {
+		if (i == HIFN_D_SRC_RSIZE)
+			i = 0;
+		HIFN_SRCR_SYNC(sc, i,
+		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+		if (dma->srcr[i].l & htole32(HIFN_D_VALID)) {
+			HIFN_SRCR_SYNC(sc, i,
+			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+			break;
+		}
+		i++, u--;
+	}
+	dma->srck = i; dma->srcu = u;
+
+	i = dma->cmdk; u = dma->cmdu;
+	while (u != 0) {
+		HIFN_CMDR_SYNC(sc, i,
+		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+		if (dma->cmdr[i].l & htole32(HIFN_D_VALID)) {
+			HIFN_CMDR_SYNC(sc, i,
+			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+			break;
+		}
+		if (i != HIFN_D_CMD_RSIZE) {
+			u--;
+			HIFN_CMD_SYNC(sc, i, BUS_DMASYNC_POSTWRITE);
+		}
+		if (++i == (HIFN_D_CMD_RSIZE + 1))
+			i = 0;
+	}
+	dma->cmdk = i; dma->cmdu = u;
+
+	HIFN_UNLOCK(sc);
+
+	if (sc->sc_needwakeup) {		/* XXX check high watermark */
+		int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
+#ifdef HIFN_DEBUG
+		if (hifn_debug)
+			device_printf(sc->sc_dev,
+				"wakeup crypto (%x) u %d/%d/%d/%d\n",
+				sc->sc_needwakeup,
+				dma->cmdu, dma->srcu, dma->dstu, dma->resu);
+#endif
+		sc->sc_needwakeup &= ~wakeup;
+		crypto_unblock(sc->sc_cid, wakeup);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Allocate a new 'session' and return an encoded session id.  'sidp'
+ * contains our registration id, and should contain an encoded session
+ * id on successful allocation.
+ */
+static int
+hifn_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
+{
+	struct hifn_softc *sc = device_get_softc(dev);
+	struct cryptoini *c;
+	int mac = 0, cry = 0, sesn;
+	struct hifn_session *ses = NULL;
+	unsigned long l_flags;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	KASSERT(sc != NULL, ("hifn_newsession: null softc"));
+	if (sidp == NULL || cri == NULL || sc == NULL) {
+		DPRINTF("%s,%d: %s - EINVAL\n", __FILE__, __LINE__, __FUNCTION__);
+		return (EINVAL);
+	}
+
+	HIFN_LOCK(sc);
+	if (sc->sc_sessions == NULL) {
+		ses = sc->sc_sessions = (struct hifn_session *)kmalloc(sizeof(*ses),
+				SLAB_ATOMIC);
+		if (ses == NULL) {
+			HIFN_UNLOCK(sc);
+			return (ENOMEM);
+		}
+		sesn = 0;
+		sc->sc_nsessions = 1;
+	} else {
+		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
+			if (!sc->sc_sessions[sesn].hs_used) {
+				ses = &sc->sc_sessions[sesn];
+				break;
+			}
+		}
+
+		if (ses == NULL) {
+			sesn = sc->sc_nsessions;
+			ses = (struct hifn_session *)kmalloc((sesn + 1) * sizeof(*ses),
+					SLAB_ATOMIC);
+			if (ses == NULL) {
+				HIFN_UNLOCK(sc);
+				return (ENOMEM);
+			}
+			bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
+			bzero(sc->sc_sessions, sesn * sizeof(*ses));
+			kfree(sc->sc_sessions);
+			sc->sc_sessions = ses;
+			ses = &sc->sc_sessions[sesn];
+			sc->sc_nsessions++;
+		}
+	}
+	HIFN_UNLOCK(sc);
+
+	bzero(ses, sizeof(*ses));
+	ses->hs_used = 1;
+
+	for (c = cri; c != NULL; c = c->cri_next) {
+		switch (c->cri_alg) {
+		case CRYPTO_MD5:
+		case CRYPTO_SHA1:
+		case CRYPTO_MD5_HMAC:
+		case CRYPTO_SHA1_HMAC:
+			if (mac) {
+				DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+				return (EINVAL);
+			}
+			mac = 1;
+			ses->hs_mlen = c->cri_mlen;
+			if (ses->hs_mlen == 0) {
+				switch (c->cri_alg) {
+				case CRYPTO_MD5:
+				case CRYPTO_MD5_HMAC:
+					ses->hs_mlen = 16;
+					break;
+				case CRYPTO_SHA1:
+				case CRYPTO_SHA1_HMAC:
+					ses->hs_mlen = 20;
+					break;
+				}
+			}
+			break;
+		case CRYPTO_DES_CBC:
+		case CRYPTO_3DES_CBC:
+		case CRYPTO_AES_CBC:
+			/* XXX this may read fewer, does it matter? */
+			read_random(ses->hs_iv,
+				c->cri_alg == CRYPTO_AES_CBC ?
+					HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
+			/*FALLTHROUGH*/
+		case CRYPTO_ARC4:
+			if (cry) {
+				DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+				return (EINVAL);
+			}
+			cry = 1;
+			break;
+		default:
+			DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+			return (EINVAL);
+		}
+	}
+	if (mac == 0 && cry == 0) {
+		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+		return (EINVAL);
+	}
+
+	*sidp = HIFN_SID(device_get_unit(sc->sc_dev), sesn);
+
+	return (0);
+}
+
+/*
+ * Deallocate a session.
+ * XXX this routine should run a zero'd mac/encrypt key into context ram.
+ * XXX to blow away any keys already stored there.
+ */
+static int
+hifn_freesession(device_t dev, u_int64_t tid)
+{
+	struct hifn_softc *sc = device_get_softc(dev);
+	int session, error;
+	u_int32_t sid = CRYPTO_SESID2LID(tid);
+	unsigned long l_flags;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	KASSERT(sc != NULL, ("hifn_freesession: null softc"));
+	if (sc == NULL) {
+		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+		return (EINVAL);
+	}
+
+	HIFN_LOCK(sc);
+	session = HIFN_SESSION(sid);
+	if (session < sc->sc_nsessions) {
+		bzero(&sc->sc_sessions[session], sizeof(struct hifn_session));
+		error = 0;
+	} else {
+		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+		error = EINVAL;
+	}
+	HIFN_UNLOCK(sc);
+
+	return (error);
+}
+
+static int
+hifn_process(device_t dev, struct cryptop *crp, int hint)
+{
+	struct hifn_softc *sc = device_get_softc(dev);
+	struct hifn_command *cmd = NULL;
+	int session, err, ivlen;
+	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (crp == NULL || crp->crp_callback == NULL) {
+		hifnstats.hst_invalid++;
+		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+		return (EINVAL);
+	}
+	session = HIFN_SESSION(crp->crp_sid);
+
+	if (sc == NULL || session >= sc->sc_nsessions) {
+		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+		err = EINVAL;
+		goto errout;
+	}
+
+	cmd = kmalloc(sizeof(struct hifn_command), SLAB_ATOMIC);
+	if (cmd == NULL) {
+		hifnstats.hst_nomem++;
+		err = ENOMEM;
+		goto errout;
+	}
+	memset(cmd, 0, sizeof(*cmd));
+
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		cmd->src_skb = (struct sk_buff *)crp->crp_buf;
+		cmd->dst_skb = (struct sk_buff *)crp->crp_buf;
+	} else if (crp->crp_flags & CRYPTO_F_IOV) {
+		cmd->src_io = (struct uio *)crp->crp_buf;
+		cmd->dst_io = (struct uio *)crp->crp_buf;
+	} else {
+		cmd->src_buf = crp->crp_buf;
+		cmd->dst_buf = crp->crp_buf;
+	}
+
+	crd1 = crp->crp_desc;
+	if (crd1 == NULL) {
+		DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+		err = EINVAL;
+		goto errout;
+	}
+	crd2 = crd1->crd_next;
+
+	if (crd2 == NULL) {
+		if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
+		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
+		    crd1->crd_alg == CRYPTO_SHA1 ||
+		    crd1->crd_alg == CRYPTO_MD5) {
+			maccrd = crd1;
+			enccrd = NULL;
+		} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
+		    crd1->crd_alg == CRYPTO_3DES_CBC ||
+		    crd1->crd_alg == CRYPTO_AES_CBC ||
+		    crd1->crd_alg == CRYPTO_ARC4) {
+			if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0)
+				cmd->base_masks |= HIFN_BASE_CMD_DECODE;
+			maccrd = NULL;
+			enccrd = crd1;
+		} else {
+			DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+			err = EINVAL;
+			goto errout;
+		}
+	} else {
+		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
+                     crd1->crd_alg == CRYPTO_SHA1_HMAC ||
+                     crd1->crd_alg == CRYPTO_MD5 ||
+                     crd1->crd_alg == CRYPTO_SHA1) &&
+		    (crd2->crd_alg == CRYPTO_DES_CBC ||
+		     crd2->crd_alg == CRYPTO_3DES_CBC ||
+		     crd2->crd_alg == CRYPTO_AES_CBC ||
+		     crd2->crd_alg == CRYPTO_ARC4) &&
+		    ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
+			cmd->base_masks = HIFN_BASE_CMD_DECODE;
+			maccrd = crd1;
+			enccrd = crd2;
+		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
+		     crd1->crd_alg == CRYPTO_ARC4 ||
+		     crd1->crd_alg == CRYPTO_3DES_CBC ||
+		     crd1->crd_alg == CRYPTO_AES_CBC) &&
+		    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
+                     crd2->crd_alg == CRYPTO_SHA1_HMAC ||
+                     crd2->crd_alg == CRYPTO_MD5 ||
+                     crd2->crd_alg == CRYPTO_SHA1) &&
+		    (crd1->crd_flags & CRD_F_ENCRYPT)) {
+			enccrd = crd1;
+			maccrd = crd2;
+		} else {
+			/*
+			 * We cannot order the 7751 as requested
+			 */
+			DPRINTF("%s,%d: %s %d,%d,%d - EINVAL\n",__FILE__,__LINE__,__FUNCTION__, crd1->crd_alg, crd2->crd_alg, crd1->crd_flags & CRD_F_ENCRYPT);
+			err = EINVAL;
+			goto errout;
+		}
+	}
+
+	if (enccrd) {
+		cmd->enccrd = enccrd;
+		cmd->base_masks |= HIFN_BASE_CMD_CRYPT;
+		switch (enccrd->crd_alg) {
+		case CRYPTO_ARC4:
+			cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4;
+			break;
+		case CRYPTO_DES_CBC:
+			cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES |
+			    HIFN_CRYPT_CMD_MODE_CBC |
+			    HIFN_CRYPT_CMD_NEW_IV;
+			break;
+		case CRYPTO_3DES_CBC:
+			cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_3DES |
+			    HIFN_CRYPT_CMD_MODE_CBC |
+			    HIFN_CRYPT_CMD_NEW_IV;
+			break;
+		case CRYPTO_AES_CBC:
+			cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_AES |
+			    HIFN_CRYPT_CMD_MODE_CBC |
+			    HIFN_CRYPT_CMD_NEW_IV;
+			break;
+		default:
+			DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+			err = EINVAL;
+			goto errout;
+		}
+		if (enccrd->crd_alg != CRYPTO_ARC4) {
+			ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ?
+				HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
+			if (enccrd->crd_flags & CRD_F_ENCRYPT) {
+				if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+					bcopy(enccrd->crd_iv, cmd->iv, ivlen);
+				else
+					bcopy(sc->sc_sessions[session].hs_iv,
+					    cmd->iv, ivlen);
+
+				if ((enccrd->crd_flags & CRD_F_IV_PRESENT)
+				    == 0) {
+					crypto_copyback(crp->crp_flags,
+					    crp->crp_buf, enccrd->crd_inject,
+					    ivlen, cmd->iv);
+				}
+			} else {
+				if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+					bcopy(enccrd->crd_iv, cmd->iv, ivlen);
+				else {
+					crypto_copydata(crp->crp_flags,
+					    crp->crp_buf, enccrd->crd_inject,
+					    ivlen, cmd->iv);
+				}
+			}
+		}
+
+		if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
+			cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
+		cmd->ck = enccrd->crd_key;
+		cmd->cklen = enccrd->crd_klen >> 3;
+		cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
+
+		/* 
+		 * Need to specify the size for the AES key in the masks.
+		 */
+		if ((cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) ==
+		    HIFN_CRYPT_CMD_ALG_AES) {
+			switch (cmd->cklen) {
+			case 16:
+				cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_128;
+				break;
+			case 24:
+				cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_192;
+				break;
+			case 32:
+				cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_256;
+				break;
+			default:
+				DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
+				err = EINVAL;
+				goto errout;
+			}
+		}
+	}
+
+	if (maccrd) {
+		cmd->maccrd = maccrd;
+		cmd->base_masks |= HIFN_BASE_CMD_MAC;
+
+		switch (maccrd->crd_alg) {
+		case CRYPTO_MD5:
+			cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 |
+			    HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH |
+			    HIFN_MAC_CMD_POS_IPSEC;
+                       break;
+		case CRYPTO_MD5_HMAC:
+			cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 |
+			    HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC |
+			    HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
+			break;
+		case CRYPTO_SHA1:
+			cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 |
+			    HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH |
+			    HIFN_MAC_CMD_POS_IPSEC;
+			break;
+		case CRYPTO_SHA1_HMAC:
+			cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 |
+			    HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC |
+			    HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
+			break;
+		}
+
+		if (maccrd->crd_alg == CRYPTO_SHA1_HMAC ||
+		     maccrd->crd_alg == CRYPTO_MD5_HMAC) {
+			cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY;
+			bcopy(maccrd->crd_key, cmd->mac, maccrd->crd_klen >> 3);
+			bzero(cmd->mac + (maccrd->crd_klen >> 3),
+			    HIFN_MAC_KEY_LENGTH - (maccrd->crd_klen >> 3));
+		}
+	}
+
+	cmd->crp = crp;
+	cmd->session_num = session;
+	cmd->softc = sc;
+
+	err = hifn_crypto(sc, cmd, crp, hint);
+	if (!err) {
+		return 0;
+	} else if (err == ERESTART) {
+		/*
+		 * There weren't enough resources to dispatch the request
+		 * to the part.  Notify the caller so they'll requeue this
+		 * request and resubmit it again soon.
+		 */
+#ifdef HIFN_DEBUG
+		if (hifn_debug)
+			device_printf(sc->sc_dev, "requeue request\n");
+#endif
+		kfree(cmd);
+		sc->sc_needwakeup |= CRYPTO_SYMQ;
+		return (err);
+	}
+
+errout:
+	if (cmd != NULL)
+		kfree(cmd);
+	if (err == EINVAL)
+		hifnstats.hst_invalid++;
+	else
+		hifnstats.hst_nomem++;
+	crp->crp_etype = err;
+	crypto_done(crp);
+	return (err);
+}
+
+static void
+hifn_abort(struct hifn_softc *sc)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+	struct hifn_command *cmd;
+	struct cryptop *crp;
+	int i, u;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	i = dma->resk; u = dma->resu;
+	while (u != 0) {
+		cmd = dma->hifn_commands[i];
+		KASSERT(cmd != NULL, ("hifn_abort: null command slot %u", i));
+		dma->hifn_commands[i] = NULL;
+		crp = cmd->crp;
+
+		if ((dma->resr[i].l & htole32(HIFN_D_VALID)) == 0) {
+			/* Salvage what we can. */
+			u_int8_t *macbuf;
+
+			if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
+				macbuf = dma->result_bufs[i];
+				macbuf += 12;
+			} else
+				macbuf = NULL;
+			hifnstats.hst_opackets++;
+			hifn_callback(sc, cmd, macbuf);
+		} else {
+#if 0
+			if (cmd->src_map == cmd->dst_map) {
+				bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
+				    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+			} else {
+				bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
+				    BUS_DMASYNC_POSTWRITE);
+				bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
+				    BUS_DMASYNC_POSTREAD);
+			}
+#endif
+
+			if (cmd->src_skb != cmd->dst_skb) {
+#ifdef NOTYET
+				m_freem(cmd->src_m);
+				crp->crp_buf = (caddr_t)cmd->dst_m;
+#else
+				device_printf(sc->sc_dev,
+						"%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
+						__FILE__, __LINE__);
+#endif
+			}
+
+			/* non-shared buffers cannot be restarted */
+			if (cmd->src_map != cmd->dst_map) {
+				/*
+				 * XXX should be EAGAIN, delayed until
+				 * after the reset.
+				 */
+				crp->crp_etype = ENOMEM;
+				pci_unmap_buf(sc, &cmd->dst);
+			} else
+				crp->crp_etype = ENOMEM;
+
+			pci_unmap_buf(sc, &cmd->src);
+
+			kfree(cmd);
+			if (crp->crp_etype != EAGAIN)
+				crypto_done(crp);
+		}
+
+		if (++i == HIFN_D_RES_RSIZE)
+			i = 0;
+		u--;
+	}
+	dma->resk = i; dma->resu = u;
+
+	hifn_reset_board(sc, 1);
+	hifn_init_dma(sc);
+	hifn_init_pci_registers(sc);
+}
+
+static void
+hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf)
+{
+	struct hifn_dma *dma = sc->sc_dma;
+	struct cryptop *crp = cmd->crp;
+	struct cryptodesc *crd;
+	int i, u, ivlen;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+#if 0
+	if (cmd->src_map == cmd->dst_map) {
+		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
+		    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+	} else {
+		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
+		    BUS_DMASYNC_POSTWRITE);
+		bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
+		    BUS_DMASYNC_POSTREAD);
+	}
+#endif
+
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		if (cmd->src_skb != cmd->dst_skb) {
+#ifdef NOTYET
+			crp->crp_buf = (caddr_t)cmd->dst_m;
+			totlen = cmd->src_mapsize;
+			for (m = cmd->dst_m; m != NULL; m = m->m_next) {
+				if (totlen < m->m_len) {
+					m->m_len = totlen;
+					totlen = 0;
+				} else
+					totlen -= m->m_len;
+			}
+			cmd->dst_m->m_pkthdr.len = cmd->src_m->m_pkthdr.len;
+			m_freem(cmd->src_m);
+#else
+			device_printf(sc->sc_dev,
+					"%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
+					__FILE__, __LINE__);
+#endif
+		}
+	}
+
+	if (cmd->sloplen != 0) {
+		crypto_copyback(crp->crp_flags, crp->crp_buf,
+		    cmd->src_mapsize - cmd->sloplen, cmd->sloplen,
+		    (caddr_t)&dma->slop[cmd->slopidx]);
+	}
+
+	i = dma->dstk; u = dma->dstu;
+	while (u != 0) {
+		if (i == HIFN_D_DST_RSIZE)
+			i = 0;
+#if 0
+		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
+		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+#endif
+		if (dma->dstr[i].l & htole32(HIFN_D_VALID)) {
+#if 0
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
+			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+#endif
+			break;
+		}
+		i++, u--;
+	}
+	dma->dstk = i; dma->dstu = u;
+
+	hifnstats.hst_obytes += cmd->dst_mapsize;
+
+	if ((cmd->base_masks & (HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE)) ==
+	    HIFN_BASE_CMD_CRYPT) {
+		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+			if (crd->crd_alg != CRYPTO_DES_CBC &&
+			    crd->crd_alg != CRYPTO_3DES_CBC &&
+			    crd->crd_alg != CRYPTO_AES_CBC)
+				continue;
+			ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
+				HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
+			crypto_copydata(crp->crp_flags, crp->crp_buf,
+			    crd->crd_skip + crd->crd_len - ivlen, ivlen,
+			    cmd->softc->sc_sessions[cmd->session_num].hs_iv);
+			break;
+		}
+	}
+
+	if (macbuf != NULL) {
+		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+                        int len;
+
+			if (crd->crd_alg != CRYPTO_MD5 &&
+			    crd->crd_alg != CRYPTO_SHA1 &&
+			    crd->crd_alg != CRYPTO_MD5_HMAC &&
+			    crd->crd_alg != CRYPTO_SHA1_HMAC) {
+				continue;
+			}
+			len = cmd->softc->sc_sessions[cmd->session_num].hs_mlen;
+			crypto_copyback(crp->crp_flags, crp->crp_buf,
+			    crd->crd_inject, len, macbuf);
+			break;
+		}
+	}
+
+	if (cmd->src_map != cmd->dst_map)
+		pci_unmap_buf(sc, &cmd->dst);
+	pci_unmap_buf(sc, &cmd->src);
+	kfree(cmd);
+	crypto_done(crp);
+}
+
+/*
+ * 7811 PB3 rev/2 parts lock-up on burst writes to Group 0
+ * and Group 1 registers; avoid conditions that could create
+ * burst writes by doing a read in between the writes.
+ *
+ * NB: The read we interpose is always to the same register;
+ *     we do this because reading from an arbitrary (e.g. last)
+ *     register may not always work.
+ */
+static void
+hifn_write_reg_0(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
+{
+	if (sc->sc_flags & HIFN_IS_7811) {
+		if (sc->sc_bar0_lastreg == reg - 4)
+			readl(sc->sc_bar0 + HIFN_0_PUCNFG);
+		sc->sc_bar0_lastreg = reg;
+	}
+	writel(val, sc->sc_bar0 + reg);
+}
+
+static void
+hifn_write_reg_1(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
+{
+	if (sc->sc_flags & HIFN_IS_7811) {
+		if (sc->sc_bar1_lastreg == reg - 4)
+			readl(sc->sc_bar1 + HIFN_1_REVID);
+		sc->sc_bar1_lastreg = reg;
+	}
+	writel(val, sc->sc_bar1 + reg);
+}
+
+
+static struct pci_device_id hifn_pci_tbl[] = {
+	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7951,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7955,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7956,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_VENDOR_NETSEC, PCI_PRODUCT_NETSEC_7751,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_VENDOR_INVERTEX, PCI_PRODUCT_INVERTEX_AEON,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7811,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	/*
+	 * Other vendors share this PCI ID as well, such as
+	 * http://www.powercrypt.com, and obviously they also
+	 * use the same key.
+	 */
+	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7751,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ 0, 0, 0, 0, 0, 0, }
+};
+MODULE_DEVICE_TABLE(pci, hifn_pci_tbl);
+
+static struct pci_driver hifn_driver = {
+	.name         = "hifn",
+	.id_table     = hifn_pci_tbl,
+	.probe        =	hifn_probe,
+	.remove       = hifn_remove,
+	/* add PM stuff here one day */
+};
+
+static int __init hifn_init (void)
+{
+	struct hifn_softc *sc = NULL;
+	int rc;
+
+	DPRINTF("%s(%p)\n", __FUNCTION__, hifn_init);
+
+	rc = pci_register_driver(&hifn_driver);
+	pci_register_driver_compat(&hifn_driver, rc);
+
+	return rc;
+}
+
+static void __exit hifn_exit (void)
+{
+	pci_unregister_driver(&hifn_driver);
+}
+
+module_init(hifn_init);
+module_exit(hifn_exit);
+
+MODULE_LICENSE("BSD");
+MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_DESCRIPTION("OCF driver for hifn PCI crypto devices");
diff --git a/crypto/ocf/hifn/hifn7751reg.h b/crypto/ocf/hifn/hifn7751reg.h
new file mode 100755
index 0000000..ccf54f9
--- /dev/null
+++ b/crypto/ocf/hifn/hifn7751reg.h
@@ -0,0 +1,540 @@
+/* $FreeBSD: src/sys/dev/hifn/hifn7751reg.h,v 1.7 2007/03/21 03:42:49 sam Exp $ */
+/*	$OpenBSD: hifn7751reg.h,v 1.35 2002/04/08 17:49:42 jason Exp $	*/
+
+/*-
+ * Invertex AEON / Hifn 7751 driver
+ * Copyright (c) 1999 Invertex Inc. All rights reserved.
+ * Copyright (c) 1999 Theo de Raadt
+ * Copyright (c) 2000-2001 Network Security Technologies, Inc.
+ *			http://www.netsec.net
+ *
+ * Please send any comments, feedback, bug-fixes, or feature requests to
+ * software@invertex.com.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+#ifndef __HIFN_H__
+#define	__HIFN_H__
+
+/*
+ * Some PCI configuration space offset defines.  The names were made
+ * identical to the names used by the Linux kernel.
+ */
+#define	HIFN_BAR0		PCIR_BAR(0)	/* PUC register map */
+#define	HIFN_BAR1		PCIR_BAR(1)	/* DMA register map */
+#define	HIFN_TRDY_TIMEOUT	0x40
+#define	HIFN_RETRY_TIMEOUT	0x41
+
+/*
+ * PCI vendor and device identifiers
+ * (the names are preserved from their OpenBSD source).
+ */
+#define	PCI_VENDOR_HIFN		0x13a3		/* Hifn */
+#define	PCI_PRODUCT_HIFN_7751	0x0005		/* 7751 */
+#define	PCI_PRODUCT_HIFN_6500	0x0006		/* 6500 */
+#define	PCI_PRODUCT_HIFN_7811	0x0007		/* 7811 */
+#define	PCI_PRODUCT_HIFN_7855	0x001f		/* 7855 */
+#define	PCI_PRODUCT_HIFN_7951	0x0012		/* 7951 */
+#define	PCI_PRODUCT_HIFN_7955	0x0020		/* 7954/7955 */
+#define	PCI_PRODUCT_HIFN_7956	0x001d		/* 7956 */
+
+#define	PCI_VENDOR_INVERTEX	0x14e1		/* Invertex */
+#define	PCI_PRODUCT_INVERTEX_AEON 0x0005	/* AEON */
+
+#define	PCI_VENDOR_NETSEC	0x1660		/* NetSec */
+#define	PCI_PRODUCT_NETSEC_7751	0x7751		/* 7751 */
+
+/*
+ * The values below should multiple of 4 -- and be large enough to handle
+ * any command the driver implements.
+ *
+ * MAX_COMMAND = base command + mac command + encrypt command +
+ *			mac-key + rc4-key
+ * MAX_RESULT  = base result + mac result + mac + encrypt result
+ *			
+ *
+ */
+#define	HIFN_MAX_COMMAND	(8 + 8 + 8 + 64 + 260)
+#define	HIFN_MAX_RESULT		(8 + 4 + 20 + 4)
+
+/*
+ * hifn_desc_t
+ *
+ * Holds an individual descriptor for any of the rings.
+ */
+typedef struct hifn_desc {
+	volatile u_int32_t l;		/* length and status bits */
+	volatile u_int32_t p;
+} hifn_desc_t;
+
+/*
+ * Masks for the "length" field of struct hifn_desc.
+ */
+#define	HIFN_D_LENGTH		0x0000ffff	/* length bit mask */
+#define	HIFN_D_MASKDONEIRQ	0x02000000	/* mask the done interrupt */
+#define	HIFN_D_DESTOVER		0x04000000	/* destination overflow */
+#define	HIFN_D_OVER		0x08000000	/* overflow */
+#define	HIFN_D_LAST		0x20000000	/* last descriptor in chain */
+#define	HIFN_D_JUMP		0x40000000	/* jump descriptor */
+#define	HIFN_D_VALID		0x80000000	/* valid bit */
+
+
+/*
+ * Processing Unit Registers (offset from BASEREG0)
+ */
+#define	HIFN_0_PUDATA		0x00	/* Processing Unit Data */
+#define	HIFN_0_PUCTRL		0x04	/* Processing Unit Control */
+#define	HIFN_0_PUISR		0x08	/* Processing Unit Interrupt Status */
+#define	HIFN_0_PUCNFG		0x0c	/* Processing Unit Configuration */
+#define	HIFN_0_PUIER		0x10	/* Processing Unit Interrupt Enable */
+#define	HIFN_0_PUSTAT		0x14	/* Processing Unit Status/Chip ID */
+#define	HIFN_0_FIFOSTAT		0x18	/* FIFO Status */
+#define	HIFN_0_FIFOCNFG		0x1c	/* FIFO Configuration */
+#define	HIFN_0_PUCTRL2		0x28	/* Processing Unit Control (2nd map) */
+#define	HIFN_0_MUTE1		0x80
+#define	HIFN_0_MUTE2		0x90
+#define	HIFN_0_SPACESIZE	0x100	/* Register space size */
+
+/* Processing Unit Control Register (HIFN_0_PUCTRL) */
+#define	HIFN_PUCTRL_CLRSRCFIFO	0x0010	/* clear source fifo */
+#define	HIFN_PUCTRL_STOP	0x0008	/* stop pu */
+#define	HIFN_PUCTRL_LOCKRAM	0x0004	/* lock ram */
+#define	HIFN_PUCTRL_DMAENA	0x0002	/* enable dma */
+#define	HIFN_PUCTRL_RESET	0x0001	/* Reset processing unit */
+
+/* Processing Unit Interrupt Status Register (HIFN_0_PUISR) */
+#define	HIFN_PUISR_CMDINVAL	0x8000	/* Invalid command interrupt */
+#define	HIFN_PUISR_DATAERR	0x4000	/* Data error interrupt */
+#define	HIFN_PUISR_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
+#define	HIFN_PUISR_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
+#define	HIFN_PUISR_DSTOVER	0x0200	/* Destination overrun interrupt */
+#define	HIFN_PUISR_SRCCMD	0x0080	/* Source command interrupt */
+#define	HIFN_PUISR_SRCCTX	0x0040	/* Source context interrupt */
+#define	HIFN_PUISR_SRCDATA	0x0020	/* Source data interrupt */
+#define	HIFN_PUISR_DSTDATA	0x0010	/* Destination data interrupt */
+#define	HIFN_PUISR_DSTRESULT	0x0004	/* Destination result interrupt */
+
+/* Processing Unit Configuration Register (HIFN_0_PUCNFG) */
+#define	HIFN_PUCNFG_DRAMMASK	0xe000	/* DRAM size mask */
+#define	HIFN_PUCNFG_DSZ_256K	0x0000	/* 256k dram */
+#define	HIFN_PUCNFG_DSZ_512K	0x2000	/* 512k dram */
+#define	HIFN_PUCNFG_DSZ_1M	0x4000	/* 1m dram */
+#define	HIFN_PUCNFG_DSZ_2M	0x6000	/* 2m dram */
+#define	HIFN_PUCNFG_DSZ_4M	0x8000	/* 4m dram */
+#define	HIFN_PUCNFG_DSZ_8M	0xa000	/* 8m dram */
+#define	HIFN_PUNCFG_DSZ_16M	0xc000	/* 16m dram */
+#define	HIFN_PUCNFG_DSZ_32M	0xe000	/* 32m dram */
+#define	HIFN_PUCNFG_DRAMREFRESH	0x1800	/* DRAM refresh rate mask */
+#define	HIFN_PUCNFG_DRFR_512	0x0000	/* 512 divisor of ECLK */
+#define	HIFN_PUCNFG_DRFR_256	0x0800	/* 256 divisor of ECLK */
+#define	HIFN_PUCNFG_DRFR_128	0x1000	/* 128 divisor of ECLK */
+#define	HIFN_PUCNFG_TCALLPHASES	0x0200	/* your guess is as good as mine... */
+#define	HIFN_PUCNFG_TCDRVTOTEM	0x0100	/* your guess is as good as mine... */
+#define	HIFN_PUCNFG_BIGENDIAN	0x0080	/* DMA big endian mode */
+#define	HIFN_PUCNFG_BUS32	0x0040	/* Bus width 32bits */
+#define	HIFN_PUCNFG_BUS16	0x0000	/* Bus width 16 bits */
+#define	HIFN_PUCNFG_CHIPID	0x0020	/* Allow chipid from PUSTAT */
+#define	HIFN_PUCNFG_DRAM	0x0010	/* Context RAM is DRAM */
+#define	HIFN_PUCNFG_SRAM	0x0000	/* Context RAM is SRAM */
+#define	HIFN_PUCNFG_COMPSING	0x0004	/* Enable single compression context */
+#define	HIFN_PUCNFG_ENCCNFG	0x0002	/* Encryption configuration */
+
+/* Processing Unit Interrupt Enable Register (HIFN_0_PUIER) */
+#define	HIFN_PUIER_CMDINVAL	0x8000	/* Invalid command interrupt */
+#define	HIFN_PUIER_DATAERR	0x4000	/* Data error interrupt */
+#define	HIFN_PUIER_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
+#define	HIFN_PUIER_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
+#define	HIFN_PUIER_DSTOVER	0x0200	/* Destination overrun interrupt */
+#define	HIFN_PUIER_SRCCMD	0x0080	/* Source command interrupt */
+#define	HIFN_PUIER_SRCCTX	0x0040	/* Source context interrupt */
+#define	HIFN_PUIER_SRCDATA	0x0020	/* Source data interrupt */
+#define	HIFN_PUIER_DSTDATA	0x0010	/* Destination data interrupt */
+#define	HIFN_PUIER_DSTRESULT	0x0004	/* Destination result interrupt */
+
+/* Processing Unit Status Register/Chip ID (HIFN_0_PUSTAT) */
+#define	HIFN_PUSTAT_CMDINVAL	0x8000	/* Invalid command interrupt */
+#define	HIFN_PUSTAT_DATAERR	0x4000	/* Data error interrupt */
+#define	HIFN_PUSTAT_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
+#define	HIFN_PUSTAT_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
+#define	HIFN_PUSTAT_DSTOVER	0x0200	/* Destination overrun interrupt */
+#define	HIFN_PUSTAT_SRCCMD	0x0080	/* Source command interrupt */
+#define	HIFN_PUSTAT_SRCCTX	0x0040	/* Source context interrupt */
+#define	HIFN_PUSTAT_SRCDATA	0x0020	/* Source data interrupt */
+#define	HIFN_PUSTAT_DSTDATA	0x0010	/* Destination data interrupt */
+#define	HIFN_PUSTAT_DSTRESULT	0x0004	/* Destination result interrupt */
+#define	HIFN_PUSTAT_CHIPREV	0x00ff	/* Chip revision mask */
+#define	HIFN_PUSTAT_CHIPENA	0xff00	/* Chip enabled mask */
+#define	HIFN_PUSTAT_ENA_2	0x1100	/* Level 2 enabled */
+#define	HIFN_PUSTAT_ENA_1	0x1000	/* Level 1 enabled */
+#define	HIFN_PUSTAT_ENA_0	0x3000	/* Level 0 enabled */
+#define	HIFN_PUSTAT_REV_2	0x0020	/* 7751 PT6/2 */
+#define	HIFN_PUSTAT_REV_3	0x0030	/* 7751 PT6/3 */
+
+/* FIFO Status Register (HIFN_0_FIFOSTAT) */
+#define	HIFN_FIFOSTAT_SRC	0x7f00	/* Source FIFO available */
+#define	HIFN_FIFOSTAT_DST	0x007f	/* Destination FIFO available */
+
+/* FIFO Configuration Register (HIFN_0_FIFOCNFG) */
+#define	HIFN_FIFOCNFG_THRESHOLD	0x0400	/* must be written as this value */
+
+/*
+ * DMA Interface Registers (offset from BASEREG1)
+ */
+#define	HIFN_1_DMA_CRAR		0x0c	/* DMA Command Ring Address */
+#define	HIFN_1_DMA_SRAR		0x1c	/* DMA Source Ring Address */
+#define	HIFN_1_DMA_RRAR		0x2c	/* DMA Result Ring Address */
+#define	HIFN_1_DMA_DRAR		0x3c	/* DMA Destination Ring Address */
+#define	HIFN_1_DMA_CSR		0x40	/* DMA Status and Control */
+#define	HIFN_1_DMA_IER		0x44	/* DMA Interrupt Enable */
+#define	HIFN_1_DMA_CNFG		0x48	/* DMA Configuration */
+#define	HIFN_1_PLL		0x4c	/* 7955/7956: PLL config */
+#define	HIFN_1_7811_RNGENA	0x60	/* 7811: rng enable */
+#define	HIFN_1_7811_RNGCFG	0x64	/* 7811: rng config */
+#define	HIFN_1_7811_RNGDAT	0x68	/* 7811: rng data */
+#define	HIFN_1_7811_RNGSTS	0x6c	/* 7811: rng status */
+#define	HIFN_1_DMA_CNFG2	0x6c	/* 7955/7956: dma config #2 */
+#define	HIFN_1_7811_MIPSRST	0x94	/* 7811: MIPS reset */
+#define	HIFN_1_REVID		0x98	/* Revision ID */
+
+#define	HIFN_1_PUB_RESET	0x204	/* Public/RNG Reset */
+#define	HIFN_1_PUB_BASE		0x300	/* Public Base Address */
+#define	HIFN_1_PUB_OPLEN	0x304	/* 7951-compat Public Operand Length */
+#define	HIFN_1_PUB_OP		0x308	/* 7951-compat Public Operand */
+#define	HIFN_1_PUB_STATUS	0x30c	/* 7951-compat Public Status */
+#define	HIFN_1_PUB_IEN		0x310	/* Public Interrupt enable */
+#define	HIFN_1_RNG_CONFIG	0x314	/* RNG config */
+#define	HIFN_1_RNG_DATA		0x318	/* RNG data */
+#define	HIFN_1_PUB_MODE		0x320	/* PK mode */
+#define	HIFN_1_PUB_FIFO_OPLEN	0x380	/* first element of oplen fifo */
+#define	HIFN_1_PUB_FIFO_OP	0x384	/* first element of op fifo */
+#define	HIFN_1_PUB_MEM		0x400	/* start of Public key memory */
+#define	HIFN_1_PUB_MEMEND	0xbff	/* end of Public key memory */
+
+/* DMA Status and Control Register (HIFN_1_DMA_CSR) */
+#define	HIFN_DMACSR_D_CTRLMASK	0xc0000000	/* Destinition Ring Control */
+#define	HIFN_DMACSR_D_CTRL_NOP	0x00000000	/* Dest. Control: no-op */
+#define	HIFN_DMACSR_D_CTRL_DIS	0x40000000	/* Dest. Control: disable */
+#define	HIFN_DMACSR_D_CTRL_ENA	0x80000000	/* Dest. Control: enable */
+#define	HIFN_DMACSR_D_ABORT	0x20000000	/* Destinition Ring PCIAbort */
+#define	HIFN_DMACSR_D_DONE	0x10000000	/* Destinition Ring Done */
+#define	HIFN_DMACSR_D_LAST	0x08000000	/* Destinition Ring Last */
+#define	HIFN_DMACSR_D_WAIT	0x04000000	/* Destinition Ring Waiting */
+#define	HIFN_DMACSR_D_OVER	0x02000000	/* Destinition Ring Overflow */
+#define	HIFN_DMACSR_R_CTRL	0x00c00000	/* Result Ring Control */
+#define	HIFN_DMACSR_R_CTRL_NOP	0x00000000	/* Result Control: no-op */
+#define	HIFN_DMACSR_R_CTRL_DIS	0x00400000	/* Result Control: disable */
+#define	HIFN_DMACSR_R_CTRL_ENA	0x00800000	/* Result Control: enable */
+#define	HIFN_DMACSR_R_ABORT	0x00200000	/* Result Ring PCI Abort */
+#define	HIFN_DMACSR_R_DONE	0x00100000	/* Result Ring Done */
+#define	HIFN_DMACSR_R_LAST	0x00080000	/* Result Ring Last */
+#define	HIFN_DMACSR_R_WAIT	0x00040000	/* Result Ring Waiting */
+#define	HIFN_DMACSR_R_OVER	0x00020000	/* Result Ring Overflow */
+#define	HIFN_DMACSR_S_CTRL	0x0000c000	/* Source Ring Control */
+#define	HIFN_DMACSR_S_CTRL_NOP	0x00000000	/* Source Control: no-op */
+#define	HIFN_DMACSR_S_CTRL_DIS	0x00004000	/* Source Control: disable */
+#define	HIFN_DMACSR_S_CTRL_ENA	0x00008000	/* Source Control: enable */
+#define	HIFN_DMACSR_S_ABORT	0x00002000	/* Source Ring PCI Abort */
+#define	HIFN_DMACSR_S_DONE	0x00001000	/* Source Ring Done */
+#define	HIFN_DMACSR_S_LAST	0x00000800	/* Source Ring Last */
+#define	HIFN_DMACSR_S_WAIT	0x00000400	/* Source Ring Waiting */
+#define	HIFN_DMACSR_ILLW	0x00000200	/* Illegal write (7811 only) */
+#define	HIFN_DMACSR_ILLR	0x00000100	/* Illegal read (7811 only) */
+#define	HIFN_DMACSR_C_CTRL	0x000000c0	/* Command Ring Control */
+#define	HIFN_DMACSR_C_CTRL_NOP	0x00000000	/* Command Control: no-op */
+#define	HIFN_DMACSR_C_CTRL_DIS	0x00000040	/* Command Control: disable */
+#define	HIFN_DMACSR_C_CTRL_ENA	0x00000080	/* Command Control: enable */
+#define	HIFN_DMACSR_C_ABORT	0x00000020	/* Command Ring PCI Abort */
+#define	HIFN_DMACSR_C_DONE	0x00000010	/* Command Ring Done */
+#define	HIFN_DMACSR_C_LAST	0x00000008	/* Command Ring Last */
+#define	HIFN_DMACSR_C_WAIT	0x00000004	/* Command Ring Waiting */
+#define	HIFN_DMACSR_PUBDONE	0x00000002	/* Public op done (7951 only) */
+#define	HIFN_DMACSR_ENGINE	0x00000001	/* Command Ring Engine IRQ */
+
+/* DMA Interrupt Enable Register (HIFN_1_DMA_IER) */
+#define	HIFN_DMAIER_D_ABORT	0x20000000	/* Destination Ring PCIAbort */
+#define	HIFN_DMAIER_D_DONE	0x10000000	/* Destination Ring Done */
+#define	HIFN_DMAIER_D_LAST	0x08000000	/* Destination Ring Last */
+#define	HIFN_DMAIER_D_WAIT	0x04000000	/* Destination Ring Waiting */
+#define	HIFN_DMAIER_D_OVER	0x02000000	/* Destination Ring Overflow */
+#define	HIFN_DMAIER_R_ABORT	0x00200000	/* Result Ring PCI Abort */
+#define	HIFN_DMAIER_R_DONE	0x00100000	/* Result Ring Done */
+#define	HIFN_DMAIER_R_LAST	0x00080000	/* Result Ring Last */
+#define	HIFN_DMAIER_R_WAIT	0x00040000	/* Result Ring Waiting */
+#define	HIFN_DMAIER_R_OVER	0x00020000	/* Result Ring Overflow */
+#define	HIFN_DMAIER_S_ABORT	0x00002000	/* Source Ring PCI Abort */
+#define	HIFN_DMAIER_S_DONE	0x00001000	/* Source Ring Done */
+#define	HIFN_DMAIER_S_LAST	0x00000800	/* Source Ring Last */
+#define	HIFN_DMAIER_S_WAIT	0x00000400	/* Source Ring Waiting */
+#define	HIFN_DMAIER_ILLW	0x00000200	/* Illegal write (7811 only) */
+#define	HIFN_DMAIER_ILLR	0x00000100	/* Illegal read (7811 only) */
+#define	HIFN_DMAIER_C_ABORT	0x00000020	/* Command Ring PCI Abort */
+#define	HIFN_DMAIER_C_DONE	0x00000010	/* Command Ring Done */
+#define	HIFN_DMAIER_C_LAST	0x00000008	/* Command Ring Last */
+#define	HIFN_DMAIER_C_WAIT	0x00000004	/* Command Ring Waiting */
+#define	HIFN_DMAIER_PUBDONE	0x00000002	/* public op done (7951 only) */
+#define	HIFN_DMAIER_ENGINE	0x00000001	/* Engine IRQ */
+
+/* DMA Configuration Register (HIFN_1_DMA_CNFG) */
+#define	HIFN_DMACNFG_BIGENDIAN	0x10000000	/* big endian mode */
+#define	HIFN_DMACNFG_POLLFREQ	0x00ff0000	/* Poll frequency mask */
+#define	HIFN_DMACNFG_UNLOCK	0x00000800
+#define	HIFN_DMACNFG_POLLINVAL	0x00000700	/* Invalid Poll Scalar */
+#define	HIFN_DMACNFG_LAST	0x00000010	/* Host control LAST bit */
+#define	HIFN_DMACNFG_MODE	0x00000004	/* DMA mode */
+#define	HIFN_DMACNFG_DMARESET	0x00000002	/* DMA Reset # */
+#define	HIFN_DMACNFG_MSTRESET	0x00000001	/* Master Reset # */
+
+/* DMA Configuration Register (HIFN_1_DMA_CNFG2) */
+#define	HIFN_DMACNFG2_PKSWAP32	(1 << 19)	/* swap the OPLEN/OP reg */
+#define	HIFN_DMACNFG2_PKSWAP8	(1 << 18)	/* swap the bits of OPLEN/OP */
+#define	HIFN_DMACNFG2_BAR0_SWAP32 (1<<17)	/* swap the bytes of BAR0 */
+#define	HIFN_DMACNFG2_BAR1_SWAP8 (1<<16)	/* swap the bits  of BAR0 */
+#define	HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT 12
+#define	HIFN_DMACNFG2_INIT_READ_BURST_SHIFT 8
+#define	HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT 4
+#define	HIFN_DMACNFG2_TGT_READ_BURST_SHIFT  0
+
+/* 7811 RNG Enable Register (HIFN_1_7811_RNGENA) */
+#define	HIFN_7811_RNGENA_ENA	0x00000001	/* enable RNG */
+
+/* 7811 RNG Config Register (HIFN_1_7811_RNGCFG) */
+#define	HIFN_7811_RNGCFG_PRE1	0x00000f00	/* first prescalar */
+#define	HIFN_7811_RNGCFG_OPRE	0x00000080	/* output prescalar */
+#define	HIFN_7811_RNGCFG_DEFL	0x00000f80	/* 2 words/ 1/100 sec */
+
+/* 7811 RNG Status Register (HIFN_1_7811_RNGSTS) */
+#define	HIFN_7811_RNGSTS_RDY	0x00004000	/* two numbers in FIFO */
+#define	HIFN_7811_RNGSTS_UFL	0x00001000	/* rng underflow */
+
+/* 7811 MIPS Reset Register (HIFN_1_7811_MIPSRST) */
+#define	HIFN_MIPSRST_BAR2SIZE	0xffff0000	/* sdram size */
+#define	HIFN_MIPSRST_GPRAMINIT	0x00008000	/* gpram can be accessed */
+#define	HIFN_MIPSRST_CRAMINIT	0x00004000	/* ctxram can be accessed */
+#define	HIFN_MIPSRST_LED2	0x00000400	/* external LED2 */
+#define	HIFN_MIPSRST_LED1	0x00000200	/* external LED1 */
+#define	HIFN_MIPSRST_LED0	0x00000100	/* external LED0 */
+#define	HIFN_MIPSRST_MIPSDIS	0x00000004	/* disable MIPS */
+#define	HIFN_MIPSRST_MIPSRST	0x00000002	/* warm reset MIPS */
+#define	HIFN_MIPSRST_MIPSCOLD	0x00000001	/* cold reset MIPS */
+
+/* Public key reset register (HIFN_1_PUB_RESET) */
+#define	HIFN_PUBRST_RESET	0x00000001	/* reset public/rng unit */
+
+/* Public operation register (HIFN_1_PUB_OP) */
+#define	HIFN_PUBOP_AOFFSET	0x0000003e	/* A offset */
+#define	HIFN_PUBOP_BOFFSET	0x00000fc0	/* B offset */
+#define	HIFN_PUBOP_MOFFSET	0x0003f000	/* M offset */
+#define	HIFN_PUBOP_OP_MASK	0x003c0000	/* Opcode: */
+#define	HIFN_PUBOP_OP_NOP	0x00000000	/*  NOP */
+#define	HIFN_PUBOP_OP_ADD	0x00040000	/*  ADD */
+#define	HIFN_PUBOP_OP_ADDC	0x00080000	/*  ADD w/carry */
+#define	HIFN_PUBOP_OP_SUB	0x000c0000	/*  SUB */
+#define	HIFN_PUBOP_OP_SUBC	0x00100000	/*  SUB w/carry */
+#define	HIFN_PUBOP_OP_MODADD	0x00140000	/*  Modular ADD */
+#define	HIFN_PUBOP_OP_MODSUB	0x00180000	/*  Modular SUB */
+#define	HIFN_PUBOP_OP_INCA	0x001c0000	/*  INC A */
+#define	HIFN_PUBOP_OP_DECA	0x00200000	/*  DEC A */
+#define	HIFN_PUBOP_OP_MULT	0x00240000	/*  MULT */
+#define	HIFN_PUBOP_OP_MODMULT	0x00280000	/*  Modular MULT */
+#define	HIFN_PUBOP_OP_MODRED	0x002c0000	/*  Modular Red */
+#define	HIFN_PUBOP_OP_MODEXP	0x00300000	/*  Modular Exp */
+
+/* Public operand length register (HIFN_1_PUB_OPLEN) */
+#define	HIFN_PUBOPLEN_MODLEN	0x0000007f
+#define	HIFN_PUBOPLEN_EXPLEN	0x0003ff80
+#define	HIFN_PUBOPLEN_REDLEN	0x003c0000
+
+/* Public status register (HIFN_1_PUB_STATUS) */
+#define	HIFN_PUBSTS_DONE	0x00000001	/* operation done */
+#define	HIFN_PUBSTS_CARRY	0x00000002	/* carry */
+#define	HIFN_PUBSTS_FIFO_EMPTY	0x00000100	/* fifo empty */
+#define	HIFN_PUBSTS_FIFO_FULL	0x00000200	/* fifo full */
+#define	HIFN_PUBSTS_FIFO_OVFL	0x00000400	/* fifo overflow */
+#define	HIFN_PUBSTS_FIFO_WRITE	0x000f0000	/* fifo write */
+#define	HIFN_PUBSTS_FIFO_READ	0x0f000000	/* fifo read */
+
+/* Public interrupt enable register (HIFN_1_PUB_IEN) */
+#define	HIFN_PUBIEN_DONE	0x00000001	/* operation done interrupt */
+
+/* Random number generator config register (HIFN_1_RNG_CONFIG) */
+#define	HIFN_RNGCFG_ENA		0x00000001	/* enable rng */
+
+/*
+ * Register offsets in register set 1
+ */
+
+#define	HIFN_UNLOCK_SECRET1	0xf4
+#define	HIFN_UNLOCK_SECRET2	0xfc
+
+/*
+ * PLL config register
+ *
+ * This register is present only on 7954/7955/7956 parts. It must be
+ * programmed according to the bus interface method used by the h/w.
+ * Note that the parts require a stable clock.  Since the PCI clock
+ * may vary the reference clock must usually be used.  To avoid
+ * overclocking the core logic, setup must be done carefully, refer
+ * to the driver for details.  The exact multiplier required varies
+ * by part and system configuration; refer to the Hifn documentation.
+ */
+#define	HIFN_PLL_REF_SEL	0x00000001	/* REF/HBI clk selection */
+#define	HIFN_PLL_BP		0x00000002	/* bypass (used during setup) */
+/* bit 2 reserved */
+#define	HIFN_PLL_PK_CLK_SEL	0x00000008	/* public key clk select */
+#define	HIFN_PLL_PE_CLK_SEL	0x00000010	/* packet engine clk select */
+/* bits 5-9 reserved */
+#define	HIFN_PLL_MBSET		0x00000400	/* must be set to 1 */
+#define	HIFN_PLL_ND		0x00003800	/* Fpll_ref multiplier select */
+#define	HIFN_PLL_ND_SHIFT	11
+#define	HIFN_PLL_ND_2		0x00000000	/* 2x */
+#define	HIFN_PLL_ND_4		0x00000800	/* 4x */
+#define	HIFN_PLL_ND_6		0x00001000	/* 6x */
+#define	HIFN_PLL_ND_8		0x00001800	/* 8x */
+#define	HIFN_PLL_ND_10		0x00002000	/* 10x */
+#define	HIFN_PLL_ND_12		0x00002800	/* 12x */
+/* bits 14-15 reserved */
+#define	HIFN_PLL_IS		0x00010000	/* charge pump current select */
+/* bits 17-31 reserved */
+
+/*
+ * Board configuration specifies only these bits.
+ */
+#define	HIFN_PLL_CONFIG		(HIFN_PLL_IS|HIFN_PLL_ND|HIFN_PLL_REF_SEL)
+
+/*
+ * Public Key Engine Mode Register
+ */
+#define	HIFN_PKMODE_HOSTINVERT	(1 << 0)	/* HOST INVERT */
+#define	HIFN_PKMODE_ENHANCED	(1 << 1)	/* Enable enhanced mode */
+
+
+/*********************************************************************
+ * Structs for board commands 
+ *
+ *********************************************************************/
+
+/*
+ * Structure to help build up the command data structure.
+ */
+typedef struct hifn_base_command {
+	volatile u_int16_t masks;
+	volatile u_int16_t session_num;
+	volatile u_int16_t total_source_count;
+	volatile u_int16_t total_dest_count;
+} hifn_base_command_t;
+
+#define	HIFN_BASE_CMD_MAC		0x0400
+#define	HIFN_BASE_CMD_CRYPT		0x0800
+#define	HIFN_BASE_CMD_DECODE		0x2000
+#define	HIFN_BASE_CMD_SRCLEN_M		0xc000
+#define	HIFN_BASE_CMD_SRCLEN_S		14
+#define	HIFN_BASE_CMD_DSTLEN_M		0x3000
+#define	HIFN_BASE_CMD_DSTLEN_S		12
+#define	HIFN_BASE_CMD_LENMASK_HI	0x30000
+#define	HIFN_BASE_CMD_LENMASK_LO	0x0ffff
+
+/*
+ * Structure to help build up the command data structure.
+ */
+typedef struct hifn_crypt_command {
+	volatile u_int16_t masks;
+	volatile u_int16_t header_skip;
+	volatile u_int16_t source_count;
+	volatile u_int16_t reserved;
+} hifn_crypt_command_t;
+
+#define	HIFN_CRYPT_CMD_ALG_MASK		0x0003		/* algorithm: */
+#define	HIFN_CRYPT_CMD_ALG_DES		0x0000		/*   DES */
+#define	HIFN_CRYPT_CMD_ALG_3DES		0x0001		/*   3DES */
+#define	HIFN_CRYPT_CMD_ALG_RC4		0x0002		/*   RC4 */
+#define	HIFN_CRYPT_CMD_ALG_AES		0x0003		/*   AES */
+#define	HIFN_CRYPT_CMD_MODE_MASK	0x0018		/* Encrypt mode: */
+#define	HIFN_CRYPT_CMD_MODE_ECB		0x0000		/*   ECB */
+#define	HIFN_CRYPT_CMD_MODE_CBC		0x0008		/*   CBC */
+#define	HIFN_CRYPT_CMD_MODE_CFB		0x0010		/*   CFB */
+#define	HIFN_CRYPT_CMD_MODE_OFB		0x0018		/*   OFB */
+#define	HIFN_CRYPT_CMD_CLR_CTX		0x0040		/* clear context */
+#define	HIFN_CRYPT_CMD_NEW_KEY		0x0800		/* expect new key */
+#define	HIFN_CRYPT_CMD_NEW_IV		0x1000		/* expect new iv */
+
+#define	HIFN_CRYPT_CMD_SRCLEN_M		0xc000
+#define	HIFN_CRYPT_CMD_SRCLEN_S		14
+
+#define	HIFN_CRYPT_CMD_KSZ_MASK		0x0600		/* AES key size: */
+#define	HIFN_CRYPT_CMD_KSZ_128		0x0000		/*   128 bit */
+#define	HIFN_CRYPT_CMD_KSZ_192		0x0200		/*   192 bit */
+#define	HIFN_CRYPT_CMD_KSZ_256		0x0400		/*   256 bit */
+
+/*
+ * Structure to help build up the command data structure.
+ */
+typedef struct hifn_mac_command {
+	volatile u_int16_t masks;
+	volatile u_int16_t header_skip;
+	volatile u_int16_t source_count;
+	volatile u_int16_t reserved;
+} hifn_mac_command_t;
+
+#define	HIFN_MAC_CMD_ALG_MASK		0x0001
+#define	HIFN_MAC_CMD_ALG_SHA1		0x0000
+#define	HIFN_MAC_CMD_ALG_MD5		0x0001
+#define	HIFN_MAC_CMD_MODE_MASK		0x000c
+#define	HIFN_MAC_CMD_MODE_HMAC		0x0000
+#define	HIFN_MAC_CMD_MODE_SSL_MAC	0x0004
+#define	HIFN_MAC_CMD_MODE_HASH		0x0008
+#define	HIFN_MAC_CMD_MODE_FULL		0x0004
+#define	HIFN_MAC_CMD_TRUNC		0x0010
+#define	HIFN_MAC_CMD_RESULT		0x0020
+#define	HIFN_MAC_CMD_APPEND		0x0040
+#define	HIFN_MAC_CMD_SRCLEN_M		0xc000
+#define	HIFN_MAC_CMD_SRCLEN_S		14
+
+/*
+ * MAC POS IPsec initiates authentication after encryption on encodes
+ * and before decryption on decodes.
+ */
+#define	HIFN_MAC_CMD_POS_IPSEC		0x0200
+#define	HIFN_MAC_CMD_NEW_KEY		0x0800
+
+/*
+ * The poll frequency and poll scalar defines are unshifted values used
+ * to set fields in the DMA Configuration Register.
+ */
+#ifndef HIFN_POLL_FREQUENCY
+#define	HIFN_POLL_FREQUENCY	0x1
+#endif
+
+#ifndef HIFN_POLL_SCALAR
+#define	HIFN_POLL_SCALAR	0x0
+#endif
+
+#define	HIFN_MAX_SEGLEN 	0xffff		/* maximum dma segment len */
+#define	HIFN_MAX_DMALEN		0x3ffff		/* maximum dma length */
+#endif /* __HIFN_H__ */
diff --git a/crypto/ocf/hifn/hifn7751var.h b/crypto/ocf/hifn/hifn7751var.h
new file mode 100755
index 0000000..9a5f231
--- /dev/null
+++ b/crypto/ocf/hifn/hifn7751var.h
@@ -0,0 +1,369 @@
+/* $FreeBSD: src/sys/dev/hifn/hifn7751var.h,v 1.9 2007/03/21 03:42:49 sam Exp $ */
+/*	$OpenBSD: hifn7751var.h,v 1.42 2002/04/08 17:49:42 jason Exp $	*/
+
+/*-
+ * Invertex AEON / Hifn 7751 driver
+ * Copyright (c) 1999 Invertex Inc. All rights reserved.
+ * Copyright (c) 1999 Theo de Raadt
+ * Copyright (c) 2000-2001 Network Security Technologies, Inc.
+ *			http://www.netsec.net
+ *
+ * Please send any comments, feedback, bug-fixes, or feature requests to
+ * software@invertex.com.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#ifndef __HIFN7751VAR_H__
+#define __HIFN7751VAR_H__
+
+#ifdef __KERNEL__
+
+/*
+ * Some configurable values for the driver.  By default command+result
+ * descriptor rings are the same size.  The src+dst descriptor rings
+ * are sized at 3.5x the number of potential commands.  Slower parts
+ * (e.g. 7951) tend to run out of src descriptors; faster parts (7811)
+ * src+cmd/result descriptors.  It's not clear that increasing the size
+ * of the descriptor rings helps performance significantly as other
+ * factors tend to come into play (e.g. copying misaligned packets).
+ */
+#define	HIFN_D_CMD_RSIZE	24	/* command descriptors */
+#define	HIFN_D_SRC_RSIZE	((HIFN_D_CMD_RSIZE * 7) / 2)	/* source descriptors */
+#define	HIFN_D_RES_RSIZE	HIFN_D_CMD_RSIZE	/* result descriptors */
+#define	HIFN_D_DST_RSIZE	HIFN_D_SRC_RSIZE	/* destination descriptors */
+
+/*
+ *  Length values for cryptography
+ */
+#define HIFN_DES_KEY_LENGTH		8
+#define HIFN_3DES_KEY_LENGTH		24
+#define HIFN_MAX_CRYPT_KEY_LENGTH	HIFN_3DES_KEY_LENGTH
+#define HIFN_IV_LENGTH			8
+#define	HIFN_AES_IV_LENGTH		16
+#define HIFN_MAX_IV_LENGTH		HIFN_AES_IV_LENGTH
+
+/*
+ *  Length values for authentication
+ */
+#define HIFN_MAC_KEY_LENGTH		64
+#define HIFN_MD5_LENGTH			16
+#define HIFN_SHA1_LENGTH		20
+#define HIFN_MAC_TRUNC_LENGTH		12
+
+#define MAX_SCATTER 64
+
+/*
+ * Data structure to hold all 4 rings and any other ring related data.
+ */
+struct hifn_dma {
+	/*
+	 *  Descriptor rings.  We add +1 to the size to accomidate the
+	 *  jump descriptor.
+	 */
+	struct hifn_desc	cmdr[HIFN_D_CMD_RSIZE+1];
+	struct hifn_desc	srcr[HIFN_D_SRC_RSIZE+1];
+	struct hifn_desc	dstr[HIFN_D_DST_RSIZE+1];
+	struct hifn_desc	resr[HIFN_D_RES_RSIZE+1];
+
+	struct hifn_command	*hifn_commands[HIFN_D_RES_RSIZE];
+
+	u_char			command_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_COMMAND];
+	u_char			result_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_RESULT];
+	u_int32_t		slop[HIFN_D_CMD_RSIZE];
+
+	u_int64_t		test_src, test_dst;
+
+	/*
+	 *  Our current positions for insertion and removal from the desriptor
+	 *  rings. 
+	 */
+	int			cmdi, srci, dsti, resi;
+	volatile int		cmdu, srcu, dstu, resu;
+	int			cmdk, srck, dstk, resk;
+};
+
+struct hifn_session {
+	int hs_used;
+	int hs_mlen;
+	u_int8_t hs_iv[HIFN_MAX_IV_LENGTH];
+};
+
+#define	HIFN_RING_SYNC(sc, r, i, f)					\
+	/* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
+
+#define	HIFN_CMDR_SYNC(sc, i, f)	HIFN_RING_SYNC((sc), cmdr, (i), (f))
+#define	HIFN_RESR_SYNC(sc, i, f)	HIFN_RING_SYNC((sc), resr, (i), (f))
+#define	HIFN_SRCR_SYNC(sc, i, f)	HIFN_RING_SYNC((sc), srcr, (i), (f))
+#define	HIFN_DSTR_SYNC(sc, i, f)	HIFN_RING_SYNC((sc), dstr, (i), (f))
+
+#define	HIFN_CMD_SYNC(sc, i, f)						\
+	/* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
+
+#define	HIFN_RES_SYNC(sc, i, f)						\
+	/* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
+
+typedef int bus_size_t;
+
+/*
+ * Holds data specific to a single HIFN board.
+ */
+struct hifn_softc {
+	softc_device_decl		 sc_dev;
+
+	struct pci_dev		*sc_pcidev;	/* PCI device pointer */
+	spinlock_t		sc_mtx;		/* per-instance lock */
+
+	int			sc_num;		/* for multiple devs */
+
+	ocf_iomem_t		sc_bar0;
+	bus_size_t		sc_bar0_lastreg;/* bar0 last reg written */
+	ocf_iomem_t		sc_bar1;
+	bus_size_t		sc_bar1_lastreg;/* bar1 last reg written */
+
+	int			sc_irq;
+
+	u_int32_t		sc_dmaier;
+	u_int32_t		sc_drammodel;	/* 1=dram, 0=sram */
+	u_int32_t		sc_pllconfig;	/* 7954/7955/7956 PLL config */
+
+	struct hifn_dma		*sc_dma;
+	dma_addr_t		sc_dma_physaddr;/* physical address of sc_dma */
+
+	int			sc_dmansegs;
+	int32_t			sc_cid;
+	int			sc_maxses;
+	int			sc_nsessions;
+	struct hifn_session	*sc_sessions;
+	int			sc_ramsize;
+	int			sc_flags;
+#define	HIFN_HAS_RNG		0x1	/* includes random number generator */
+#define	HIFN_HAS_PUBLIC		0x2	/* includes public key support */
+#define	HIFN_HAS_AES		0x4	/* includes AES support */
+#define	HIFN_IS_7811		0x8	/* Hifn 7811 part */
+#define	HIFN_IS_7956		0x10	/* Hifn 7956/7955 don't have SDRAM */
+
+	struct timer_list	sc_tickto;	/* for managing DMA */
+
+	int			sc_rngfirst;
+	int			sc_rnghz;	/* RNG polling frequency */
+
+	int			sc_c_busy;	/* command ring busy */
+	int			sc_s_busy;	/* source data ring busy */
+	int			sc_d_busy;	/* destination data ring busy */
+	int			sc_r_busy;	/* result ring busy */
+	int			sc_active;	/* for initial countdown */
+	int			sc_needwakeup;	/* ops q'd wating on resources */
+	int			sc_curbatch;	/* # ops submitted w/o int */
+	int			sc_suspended;
+#ifdef HIFN_VULCANDEV
+	struct cdev            *sc_pkdev;
+#endif
+};
+
+#define	HIFN_LOCK(_sc)		spin_lock_irqsave(&(_sc)->sc_mtx, l_flags)
+#define	HIFN_UNLOCK(_sc)	spin_unlock_irqrestore(&(_sc)->sc_mtx, l_flags)
+
+/*
+ *  hifn_command_t
+ *
+ *  This is the control structure used to pass commands to hifn_encrypt().
+ *
+ *  flags
+ *  -----
+ *  Flags is the bitwise "or" values for command configuration.  A single
+ *  encrypt direction needs to be set:
+ *
+ *	HIFN_ENCODE or HIFN_DECODE
+ *
+ *  To use cryptography, a single crypto algorithm must be included:
+ *
+ *	HIFN_CRYPT_3DES or HIFN_CRYPT_DES
+ *
+ *  To use authentication is used, a single MAC algorithm must be included:
+ *
+ *	HIFN_MAC_MD5 or HIFN_MAC_SHA1
+ *
+ *  By default MD5 uses a 16 byte hash and SHA-1 uses a 20 byte hash.
+ *  If the value below is set, hash values are truncated or assumed
+ *  truncated to 12 bytes:
+ *
+ *	HIFN_MAC_TRUNC
+ *
+ *  Keys for encryption and authentication can be sent as part of a command,
+ *  or the last key value used with a particular session can be retrieved
+ *  and used again if either of these flags are not specified.
+ *
+ *	HIFN_CRYPT_NEW_KEY, HIFN_MAC_NEW_KEY
+ *
+ *  session_num
+ *  -----------
+ *  A number between 0 and 2048 (for DRAM models) or a number between 
+ *  0 and 768 (for SRAM models).  Those who don't want to use session
+ *  numbers should leave value at zero and send a new crypt key and/or
+ *  new MAC key on every command.  If you use session numbers and
+ *  don't send a key with a command, the last key sent for that same
+ *  session number will be used.
+ *
+ *  Warning:  Using session numbers and multiboard at the same time
+ *            is currently broken.
+ *
+ *  mbuf
+ *  ----
+ *  Either fill in the mbuf pointer and npa=0 or
+ *	 fill packp[] and packl[] and set npa to > 0
+ * 
+ *  mac_header_skip
+ *  ---------------
+ *  The number of bytes of the source_buf that are skipped over before
+ *  authentication begins.  This must be a number between 0 and 2^16-1
+ *  and can be used by IPsec implementers to skip over IP headers.
+ *  *** Value ignored if authentication not used ***
+ *
+ *  crypt_header_skip
+ *  -----------------
+ *  The number of bytes of the source_buf that are skipped over before
+ *  the cryptographic operation begins.  This must be a number between 0
+ *  and 2^16-1.  For IPsec, this number will always be 8 bytes larger
+ *  than the auth_header_skip (to skip over the ESP header).
+ *  *** Value ignored if cryptography not used ***
+ *
+ */
+struct hifn_operand {
+	union {
+		struct sk_buff *skb;
+		struct uio *io;
+		unsigned char *buf;
+	} u;
+	void		*map;
+	bus_size_t	mapsize;
+	int		nsegs;
+	struct {
+	    dma_addr_t  ds_addr;
+	    int         ds_len;
+	} segs[MAX_SCATTER];
+};
+
+struct hifn_command {
+	u_int16_t session_num;
+	u_int16_t base_masks, cry_masks, mac_masks;
+	u_int8_t iv[HIFN_MAX_IV_LENGTH], *ck, mac[HIFN_MAC_KEY_LENGTH];
+	int cklen;
+	int sloplen, slopidx;
+
+	struct hifn_operand src;
+	struct hifn_operand dst;
+
+	struct hifn_softc *softc;
+	struct cryptop *crp;
+	struct cryptodesc *enccrd, *maccrd;
+};
+
+#define	src_skb		src.u.skb
+#define	src_io		src.u.io
+#define	src_map		src.map
+#define	src_mapsize	src.mapsize
+#define	src_segs	src.segs
+#define	src_nsegs	src.nsegs
+#define	src_buf		src.u.buf
+
+#define	dst_skb		dst.u.skb
+#define	dst_io		dst.u.io
+#define	dst_map		dst.map
+#define	dst_mapsize	dst.mapsize
+#define	dst_segs	dst.segs
+#define	dst_nsegs	dst.nsegs
+#define	dst_buf		dst.u.buf
+
+/*
+ *  Return values for hifn_crypto()
+ */
+#define HIFN_CRYPTO_SUCCESS	0
+#define HIFN_CRYPTO_BAD_INPUT	(-1)
+#define HIFN_CRYPTO_RINGS_FULL	(-2)
+
+/**************************************************************************
+ *
+ *  Function:  hifn_crypto
+ *
+ *  Purpose:   Called by external drivers to begin an encryption on the
+ *             HIFN board.
+ *
+ *  Blocking/Non-blocking Issues
+ *  ============================
+ *  The driver cannot block in hifn_crypto (no calls to tsleep) currently.
+ *  hifn_crypto() returns HIFN_CRYPTO_RINGS_FULL if there is not enough
+ *  room in any of the rings for the request to proceed.
+ *
+ *  Return Values
+ *  =============
+ *  0 for success, negative values on error
+ *
+ *  Defines for negative error codes are:
+ *  
+ *    HIFN_CRYPTO_BAD_INPUT  :  The passed in command had invalid settings.
+ *    HIFN_CRYPTO_RINGS_FULL :  All DMA rings were full and non-blocking
+ *                              behaviour was requested.
+ *
+ *************************************************************************/
+
+/*
+ * Convert back and forth from 'sid' to 'card' and 'session'
+ */
+#define HIFN_CARD(sid)		(((sid) & 0xf0000000) >> 28)
+#define HIFN_SESSION(sid)	((sid) & 0x000007ff)
+#define HIFN_SID(crd,ses)	(((crd) << 28) | ((ses) & 0x7ff))
+
+#endif /* _KERNEL */
+
+struct hifn_stats {
+	u_int64_t hst_ibytes;
+	u_int64_t hst_obytes;
+	u_int32_t hst_ipackets;
+	u_int32_t hst_opackets;
+	u_int32_t hst_invalid;
+	u_int32_t hst_nomem;		/* malloc or one of hst_nomem_* */
+	u_int32_t hst_abort;
+	u_int32_t hst_noirq;		/* IRQ for no reason */
+	u_int32_t hst_totbatch;		/* ops submitted w/o interrupt */
+	u_int32_t hst_maxbatch;		/* max ops submitted together */
+	u_int32_t hst_unaligned;	/* unaligned src caused copy */
+	/*
+	 * The following divides hst_nomem into more specific buckets.
+	 */
+	u_int32_t hst_nomem_map;	/* bus_dmamap_create failed */
+	u_int32_t hst_nomem_load;	/* bus_dmamap_load_* failed */
+	u_int32_t hst_nomem_mbuf;	/* MGET* failed */
+	u_int32_t hst_nomem_mcl;	/* MCLGET* failed */
+	u_int32_t hst_nomem_cr;		/* out of command/result descriptor */
+	u_int32_t hst_nomem_sd;		/* out of src/dst descriptors */
+};
+
+#endif /* __HIFN7751VAR_H__ */
diff --git a/crypto/ocf/hifn/hifnHIPP.c b/crypto/ocf/hifn/hifnHIPP.c
new file mode 100755
index 0000000..45ad7ba
--- /dev/null
+++ b/crypto/ocf/hifn/hifnHIPP.c
@@ -0,0 +1,420 @@
+/*-
+ * Driver for Hifn HIPP-I/II chipset
+ * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored by Hifn Inc.
+ *
+ */
+
+/*
+ * Driver for various Hifn encryption processors.
+ */
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/version.h>
+#include <linux/skbuff.h>
+#include <linux/uio.h>
+#include <linux/sysfs.h>
+#include <linux/miscdevice.h>
+#include <asm/io.h>
+
+#include <cryptodev.h>
+
+#include "hifnHIPPreg.h"
+#include "hifnHIPPvar.h"
+
+#if 1
+#define	DPRINTF(a...)	if (hipp_debug) { \
+							printk("%s: ", sc ? \
+								device_get_nameunit(sc->sc_dev) : "hifn"); \
+							printk(a); \
+						} else
+#else
+#define	DPRINTF(a...)
+#endif
+
+typedef int bus_size_t;
+
+static inline int
+pci_get_revid(struct pci_dev *dev)
+{
+	u8 rid = 0;
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
+	return rid;
+}
+
+#define debug hipp_debug
+int hipp_debug = 0;
+module_param(hipp_debug, int, 0644);
+MODULE_PARM_DESC(hipp_debug, "Enable debug");
+
+int hipp_maxbatch = 1;
+module_param(hipp_maxbatch, int, 0644);
+MODULE_PARM_DESC(hipp_maxbatch, "max ops to batch w/o interrupt");
+
+static	int  hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent);
+static	void hipp_remove(struct pci_dev *dev);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+static irqreturn_t hipp_intr(int irq, void *arg);
+#else
+static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs);
+#endif
+
+static int hipp_num_chips = 0;
+static struct hipp_softc *hipp_chip_idx[HIPP_MAX_CHIPS];
+
+static	int hipp_newsession(device_t, u_int32_t *, struct cryptoini *);
+static	int hipp_freesession(device_t, u_int64_t);
+static	int hipp_process(device_t, struct cryptop *, int);
+
+static device_method_t hipp_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,	hipp_newsession),
+	DEVMETHOD(cryptodev_freesession,hipp_freesession),
+	DEVMETHOD(cryptodev_process,	hipp_process),
+};
+
+static __inline u_int32_t
+READ_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg)
+{
+	u_int32_t v = readl(sc->sc_bar[barno] + reg);
+	//sc->sc_bar0_lastreg = (bus_size_t) -1;
+	return (v);
+}
+static __inline void
+WRITE_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg, u_int32_t val)
+{
+	writel(val, sc->sc_bar[barno] + reg);
+}
+
+#define READ_REG_0(sc, reg)         READ_REG(sc, 0, reg)
+#define WRITE_REG_0(sc, reg, val)   WRITE_REG(sc,0, reg, val)
+#define READ_REG_1(sc, reg)         READ_REG(sc, 1, reg)
+#define WRITE_REG_1(sc, reg, val)   WRITE_REG(sc,1, reg, val)
+
+static int
+hipp_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
+{
+	return EINVAL;
+}
+
+static int
+hipp_freesession(device_t dev, u_int64_t tid)
+{
+	return EINVAL;
+}
+
+static int
+hipp_process(device_t dev, struct cryptop *crp, int hint)
+{
+	return EINVAL;
+}
+
+static const char*
+hipp_partname(struct hipp_softc *sc, char buf[128], size_t blen)
+{
+	char *n = NULL;
+
+	switch (pci_get_vendor(sc->sc_pcidev)) {
+	case PCI_VENDOR_HIFN:
+		switch (pci_get_device(sc->sc_pcidev)) {
+		case PCI_PRODUCT_HIFN_7855:	n = "Hifn 7855";
+		case PCI_PRODUCT_HIFN_8155:	n = "Hifn 8155";
+		case PCI_PRODUCT_HIFN_6500:	n = "Hifn 6500";
+		}
+	}
+
+	if(n==NULL) {
+		snprintf(buf, blen, "VID=%02x,PID=%02x",
+			 pci_get_vendor(sc->sc_pcidev),
+			 pci_get_device(sc->sc_pcidev));
+	} else {
+		buf[0]='\0';
+		strncat(buf, n, blen);
+	}
+	return buf;
+}
+
+struct hipp_fs_entry {
+	struct attribute attr;
+	/* other stuff */
+};
+
+
+static ssize_t
+cryptoid_show(struct device *dev,
+	      struct device_attribute *attr,
+	      char *buf)						
+{								
+	struct hipp_softc *sc;					
+
+	sc = pci_get_drvdata(to_pci_dev (dev));
+	return sprintf (buf, "%d\n", sc->sc_cid);
+}
+
+struct device_attribute hipp_dev_cryptoid = __ATTR_RO(cryptoid);
+
+/*
+ * Attach an interface that successfully probed.
+ */
+static int
+hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+	struct hipp_softc *sc = NULL;
+	int i;
+	//char rbase;
+	//u_int16_t ena;
+	int rev;
+	//int rseg;
+	int rc;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (pci_enable_device(dev) < 0)
+		return(-ENODEV);
+
+	if (pci_set_mwi(dev))
+		return(-ENODEV);
+
+	if (!dev->irq) {
+		printk("hifn: found device with no IRQ assigned. check BIOS settings!");
+		pci_disable_device(dev);
+		return(-ENODEV);
+	}
+
+	sc = (struct hipp_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
+	if (!sc)
+		return(-ENOMEM);
+	memset(sc, 0, sizeof(*sc));
+
+	softc_device_init(sc, "hifn-hipp", hipp_num_chips, hipp_methods);
+
+	sc->sc_pcidev = dev;
+	sc->sc_irq = -1;
+	sc->sc_cid = -1;
+	sc->sc_num = hipp_num_chips++;
+
+	if (sc->sc_num < HIPP_MAX_CHIPS)
+		hipp_chip_idx[sc->sc_num] = sc;
+
+	pci_set_drvdata(sc->sc_pcidev, sc);
+
+	spin_lock_init(&sc->sc_mtx);
+
+	/*
+	 * Setup PCI resources.
+	 * The READ_REG_0, WRITE_REG_0, READ_REG_1,
+	 * and WRITE_REG_1 macros throughout the driver are used
+	 * to permit better debugging.
+	 */
+	for(i=0; i<4; i++) {
+		unsigned long mem_start, mem_len;
+		mem_start = pci_resource_start(sc->sc_pcidev, i);
+		mem_len   = pci_resource_len(sc->sc_pcidev, i);
+		sc->sc_barphy[i] = (caddr_t)mem_start;
+		sc->sc_bar[i] = (ocf_iomem_t) ioremap(mem_start, mem_len);
+		if (!sc->sc_bar[i]) {
+			device_printf(sc->sc_dev, "cannot map bar%d register space\n", i);
+			goto fail;
+		}
+	}
+
+	//hipp_reset_board(sc, 0);
+	pci_set_master(sc->sc_pcidev);
+
+	/*
+	 * Arrange the interrupt line.
+	 */
+	rc = request_irq(dev->irq, hipp_intr, IRQF_SHARED, "hifn", sc);
+	if (rc) {
+		device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
+		goto fail;
+	}
+	sc->sc_irq = dev->irq;
+
+	rev = READ_REG_1(sc, HIPP_1_REVID) & 0xffff;
+
+	{
+		char b[32];
+		device_printf(sc->sc_dev, "%s, rev %u",
+			      hipp_partname(sc, b, sizeof(b)), rev);
+	}
+
+#if 0
+	if (sc->sc_flags & HIFN_IS_7956)
+		printf(", pll=0x%x<%s clk, %ux mult>",
+			sc->sc_pllconfig,
+			sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
+			2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
+#endif
+	printf("\n");
+
+	sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
+	if (sc->sc_cid < 0) {
+		device_printf(sc->sc_dev, "could not get crypto driver id\n");
+		goto fail;
+	}
+
+#if 0 /* cannot work with a non-GPL module */
+	/* make a sysfs entry to let the world know what entry we got */
+	sysfs_create_file(&sc->sc_pcidev->dev.kobj, &hipp_dev_cryptoid.attr);
+#endif
+
+#if 0
+	init_timer(&sc->sc_tickto);
+	sc->sc_tickto.function = hifn_tick;
+	sc->sc_tickto.data = (unsigned long) sc->sc_num;
+	mod_timer(&sc->sc_tickto, jiffies + HZ);
+#endif
+
+#if 0 /* no code here yet ?? */
+	crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
+#endif
+
+	return (0);
+
+fail:
+	if (sc->sc_cid >= 0)
+		crypto_unregister_all(sc->sc_cid);
+	if (sc->sc_irq != -1)
+		free_irq(sc->sc_irq, sc);
+	
+#if 0
+	if (sc->sc_dma) {
+		/* Turn off DMA polling */
+		WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+			    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+		
+		pci_free_consistent(sc->sc_pcidev,
+				    sizeof(*sc->sc_dma),
+				    sc->sc_dma, sc->sc_dma_physaddr);
+	}
+#endif
+	kfree(sc);
+	return (-ENXIO);
+}
+
+/*
+ * Detach an interface that successfully probed.
+ */
+static void
+hipp_remove(struct pci_dev *dev)
+{
+	struct hipp_softc *sc = pci_get_drvdata(dev);
+	unsigned long l_flags;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	/* disable interrupts */
+	HIPP_LOCK(sc);
+
+#if 0
+	WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
+	HIFN_UNLOCK(sc);
+
+	/*XXX other resources */
+	del_timer_sync(&sc->sc_tickto);
+
+	/* Turn off DMA polling */
+	WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+#endif
+
+	crypto_unregister_all(sc->sc_cid);
+
+	free_irq(sc->sc_irq, sc);
+
+#if 0
+	pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
+                sc->sc_dma, sc->sc_dma_physaddr);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+static irqreturn_t hipp_intr(int irq, void *arg)
+#else
+static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs)
+#endif
+{
+	struct hipp_softc *sc = arg;
+
+	sc = sc; /* shut up compiler */
+
+	return IRQ_HANDLED;
+}
+
+static struct pci_device_id hipp_pci_tbl[] = {
+	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7855,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_8155,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+};
+MODULE_DEVICE_TABLE(pci, hipp_pci_tbl);
+
+static struct pci_driver hipp_driver = {
+	.name         = "hipp",
+	.id_table     = hipp_pci_tbl,
+	.probe        =	hipp_probe,
+	.remove       = hipp_remove,
+	/* add PM stuff here one day */
+};
+
+static int __init hipp_init (void)
+{
+	struct hipp_softc *sc = NULL;
+	int rc;
+
+	DPRINTF("%s(%p)\n", __FUNCTION__, hipp_init);
+
+	rc = pci_register_driver(&hipp_driver);
+	pci_register_driver_compat(&hipp_driver, rc);
+
+	return rc;
+}
+
+static void __exit hipp_exit (void)
+{
+	pci_unregister_driver(&hipp_driver);
+}
+
+module_init(hipp_init);
+module_exit(hipp_exit);
+
+MODULE_LICENSE("BSD");
+MODULE_AUTHOR("Michael Richardson <mcr@xelerance.com>");
+MODULE_DESCRIPTION("OCF driver for hifn HIPP-I/II PCI crypto devices");
diff --git a/crypto/ocf/hifn/hifnHIPPreg.h b/crypto/ocf/hifn/hifnHIPPreg.h
new file mode 100755
index 0000000..8c0e720
--- /dev/null
+++ b/crypto/ocf/hifn/hifnHIPPreg.h
@@ -0,0 +1,46 @@
+/*-
+ * Hifn HIPP-I/HIPP-II (7855/8155) driver.
+ * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored by Hifn inc.
+ *
+ */
+
+#ifndef __HIFNHIPP_H__
+#define	__HIFNHIPP_H__
+
+/*
+ * PCI vendor and device identifiers
+ */
+#define	PCI_VENDOR_HIFN		0x13a3		/* Hifn */
+#define	PCI_PRODUCT_HIFN_6500	0x0006		/* 6500 */
+#define	PCI_PRODUCT_HIFN_7855	0x001f		/* 7855 */
+#define	PCI_PRODUCT_HIFN_8155	0x999		/* XXX 8155 */
+
+#define HIPP_1_REVID            0x01 /* BOGUS */
+
+#endif /* __HIPP_H__ */
diff --git a/crypto/ocf/hifn/hifnHIPPvar.h b/crypto/ocf/hifn/hifnHIPPvar.h
new file mode 100755
index 0000000..61d292f
--- /dev/null
+++ b/crypto/ocf/hifn/hifnHIPPvar.h
@@ -0,0 +1,93 @@
+/*
+ * Hifn HIPP-I/HIPP-II (7855/8155) driver.
+ * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com> * 
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored by Hifn inc.
+ *
+ */
+
+#ifndef __HIFNHIPPVAR_H__
+#define __HIFNHIPPVAR_H__
+
+#define HIPP_MAX_CHIPS 8
+
+/*
+ * Holds data specific to a single Hifn HIPP-I board.
+ */
+struct hipp_softc {
+	softc_device_decl		 sc_dev;
+
+	struct pci_dev		*sc_pcidev;	/* device backpointer */
+	ocf_iomem_t             sc_bar[5];
+	caddr_t		        sc_barphy[5];   /* physical address */
+	int			sc_num;		/* for multiple devs */
+	spinlock_t		sc_mtx;		/* per-instance lock */
+	int32_t			sc_cid;
+	int			sc_irq;
+
+#if 0
+
+	u_int32_t		sc_dmaier;
+	u_int32_t		sc_drammodel;	/* 1=dram, 0=sram */
+	u_int32_t		sc_pllconfig;	/* 7954/7955/7956 PLL config */
+
+	struct hifn_dma		*sc_dma;
+	dma_addr_t		sc_dma_physaddr;/* physical address of sc_dma */
+
+	int			sc_dmansegs;
+	int			sc_maxses;
+	int			sc_nsessions;
+	struct hifn_session	*sc_sessions;
+	int			sc_ramsize;
+	int			sc_flags;
+#define	HIFN_HAS_RNG		0x1	/* includes random number generator */
+#define	HIFN_HAS_PUBLIC		0x2	/* includes public key support */
+#define	HIFN_HAS_AES		0x4	/* includes AES support */
+#define	HIFN_IS_7811		0x8	/* Hifn 7811 part */
+#define	HIFN_IS_7956		0x10	/* Hifn 7956/7955 don't have SDRAM */
+
+	struct timer_list	sc_tickto;	/* for managing DMA */
+
+	int			sc_rngfirst;
+	int			sc_rnghz;	/* RNG polling frequency */
+
+	int			sc_c_busy;	/* command ring busy */
+	int			sc_s_busy;	/* source data ring busy */
+	int			sc_d_busy;	/* destination data ring busy */
+	int			sc_r_busy;	/* result ring busy */
+	int			sc_active;	/* for initial countdown */
+	int			sc_needwakeup;	/* ops q'd wating on resources */
+	int			sc_curbatch;	/* # ops submitted w/o int */
+	int			sc_suspended;
+	struct miscdevice       sc_miscdev;
+#endif
+};
+
+#define	HIPP_LOCK(_sc)		spin_lock_irqsave(&(_sc)->sc_mtx, l_flags)
+#define	HIPP_UNLOCK(_sc)	spin_unlock_irqrestore(&(_sc)->sc_mtx, l_flags)
+
+#endif /* __HIFNHIPPVAR_H__ */
diff --git a/crypto/ocf/ixp4xx/Makefile b/crypto/ocf/ixp4xx/Makefile
new file mode 100755
index 0000000..d94a3b7
--- /dev/null
+++ b/crypto/ocf/ixp4xx/Makefile
@@ -0,0 +1,104 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+#
+# You will need to point this at your Intel ixp425 includes,  this portion
+# of the Makefile only really works under SGLinux with the appropriate libs
+# installed.  They can be downloaded from http://www.snapgear.org/
+#
+ifeq ($(CONFIG_CPU_IXP46X),y)
+IXPLATFORM = ixp46X
+else
+ifeq ($(CONFIG_CPU_IXP43X),y)
+IXPLATFORM = ixp43X
+else
+IXPLATFORM = ixp42X
+endif
+endif
+
+ifdef CONFIG_IXP400_LIB_2_4
+IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.4/ixp400_xscale_sw
+OSAL_DIR     = $(ROOTDIR)/modules/ixp425/ixp400-2.4/ixp_osal
+endif
+ifdef CONFIG_IXP400_LIB_2_1
+IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.1/ixp400_xscale_sw
+OSAL_DIR     = $(ROOTDIR)/modules/ixp425/ixp400-2.1/ixp_osal
+endif
+ifdef CONFIG_IXP400_LIB_2_0
+IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.0/ixp400_xscale_sw
+OSAL_DIR     = $(ROOTDIR)/modules/ixp425/ixp400-2.0/ixp_osal
+endif
+ifdef IX_XSCALE_SW
+ifdef CONFIG_IXP400_LIB_2_4
+IXP_CFLAGS = \
+	-I$(ROOTDIR)/. \
+	-I$(IX_XSCALE_SW)/src/include \
+	-I$(OSAL_DIR)/common/include/ \
+	-I$(OSAL_DIR)/common/include/modules/ \
+	-I$(OSAL_DIR)/common/include/modules/ddk/ \
+	-I$(OSAL_DIR)/common/include/modules/bufferMgt/ \
+	-I$(OSAL_DIR)/common/include/modules/ioMem/ \
+	-I$(OSAL_DIR)/common/os/linux/include/ \
+	-I$(OSAL_DIR)/common/os/linux/include/core/  \
+	-I$(OSAL_DIR)/common/os/linux/include/modules/ \
+	-I$(OSAL_DIR)/common/os/linux/include/modules/ddk/ \
+	-I$(OSAL_DIR)/common/os/linux/include/modules/bufferMgt/ \
+	-I$(OSAL_DIR)/common/os/linux/include/modules/ioMem/ \
+	-I$(OSAL_DIR)/platforms/$(IXPLATFORM)/include/ \
+	-I$(OSAL_DIR)/platforms/$(IXPLATFORM)/os/linux/include/ \
+	-DENABLE_IOMEM -DENABLE_BUFFERMGT -DENABLE_DDK \
+	-DUSE_IXP4XX_CRYPTO
+else
+IXP_CFLAGS = \
+	-I$(ROOTDIR)/. \
+	-I$(IX_XSCALE_SW)/src/include \
+	-I$(OSAL_DIR)/ \
+	-I$(OSAL_DIR)/os/linux/include/ \
+	-I$(OSAL_DIR)/os/linux/include/modules/ \
+	-I$(OSAL_DIR)/os/linux/include/modules/ioMem/ \
+	-I$(OSAL_DIR)/os/linux/include/modules/bufferMgt/ \
+	-I$(OSAL_DIR)/os/linux/include/core/  \
+	-I$(OSAL_DIR)/os/linux/include/platforms/ \
+	-I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ \
+	-I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp425 \
+	-I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp465 \
+	-I$(OSAL_DIR)/os/linux/include/core/ \
+	-I$(OSAL_DIR)/include/ \
+	-I$(OSAL_DIR)/include/modules/ \
+	-I$(OSAL_DIR)/include/modules/bufferMgt/ \
+	-I$(OSAL_DIR)/include/modules/ioMem/ \
+	-I$(OSAL_DIR)/include/platforms/ \
+	-I$(OSAL_DIR)/include/platforms/ixp400/ \
+	-DUSE_IXP4XX_CRYPTO
+endif
+endif
+ifdef CONFIG_IXP400_LIB_1_4
+IXP_CFLAGS   = \
+	-I$(ROOTDIR)/. \
+	-I$(ROOTDIR)/modules/ixp425/ixp400-1.4/ixp400_xscale_sw/src/include \
+	-I$(ROOTDIR)/modules/ixp425/ixp400-1.4/ixp400_xscale_sw/src/linux \
+	-DUSE_IXP4XX_CRYPTO
+endif
+ifndef IXPDIR
+IXPDIR = ixp-version-is-not-supported
+endif
+
+ifeq ($(CONFIG_CPU_IXP46X),y)
+IXP_CFLAGS += -D__ixp46X
+else
+ifeq ($(CONFIG_CPU_IXP43X),y)
+IXP_CFLAGS += -D__ixp43X
+else
+IXP_CFLAGS += -D__ixp42X
+endif
+endif
+
+obj-$(CONFIG_OCF_IXP4XX) += ixp4xx.o
+
+obj ?= .
+EXTRA_CFLAGS += $(IXP_CFLAGS) -I$(obj)/.. -I$(obj)/.
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/crypto/ocf/ixp4xx/ixp4xx.c b/crypto/ocf/ixp4xx/ixp4xx.c
new file mode 100755
index 0000000..fba31b0
--- /dev/null
+++ b/crypto/ocf/ixp4xx/ixp4xx.c
@@ -0,0 +1,1328 @@
+/*
+ * An OCF module that uses Intels IXP CryptACC API to do the crypto.
+ * This driver requires the IXP400 Access Library that is available
+ * from Intel in order to operate (or compile).
+ *
+ * Written by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/crypto.h>
+#include <linux/interrupt.h>
+#include <asm/scatterlist.h>
+
+#include <IxTypes.h>
+#include <IxOsBuffMgt.h>
+#include <IxNpeDl.h>
+#include <IxCryptoAcc.h>
+#include <IxQMgr.h>
+#include <IxOsServices.h>
+#include <IxOsCacheMMU.h>
+
+#include <cryptodev.h>
+#include <uio.h>
+
+#ifndef IX_MBUF_PRIV
+#define IX_MBUF_PRIV(x) ((x)->priv)
+#endif
+
+struct ixp_data;
+
+struct ixp_q {
+	struct list_head	 ixp_q_list;
+	struct ixp_data		*ixp_q_data;
+	struct cryptop		*ixp_q_crp;
+	struct cryptodesc	*ixp_q_ccrd;
+	struct cryptodesc	*ixp_q_acrd;
+	IX_MBUF				 ixp_q_mbuf;
+	UINT8				*ixp_hash_dest; /* Location for hash in client buffer */
+	UINT8				*ixp_hash_src; /* Location of hash in internal buffer */
+	unsigned char		 ixp_q_iv_data[IX_CRYPTO_ACC_MAX_CIPHER_IV_LENGTH];
+	unsigned char		*ixp_q_iv;
+};
+
+struct ixp_data {
+	int					 ixp_registered;	/* is the context registered */
+	int					 ixp_crd_flags;		/* detect direction changes */
+
+	int					 ixp_cipher_alg;
+	int					 ixp_auth_alg;
+
+	UINT32				 ixp_ctx_id;
+	UINT32				 ixp_hash_key_id;	/* used when hashing */
+	IxCryptoAccCtx		 ixp_ctx;
+	IX_MBUF				 ixp_pri_mbuf;
+	IX_MBUF				 ixp_sec_mbuf;
+
+	struct work_struct   ixp_pending_work;
+	struct work_struct   ixp_registration_work;
+	struct list_head	 ixp_q;				/* unprocessed requests */
+};
+
+#ifdef __ixp46X
+
+#define	MAX_IOP_SIZE	64	/* words */
+#define	MAX_OOP_SIZE	128
+
+#define	MAX_PARAMS		3
+
+struct ixp_pkq {
+	struct list_head			 pkq_list;
+	struct cryptkop				*pkq_krp;
+
+	IxCryptoAccPkeEauInOperands	 pkq_op;
+	IxCryptoAccPkeEauOpResult	 pkq_result;
+
+	UINT32						 pkq_ibuf0[MAX_IOP_SIZE];
+	UINT32						 pkq_ibuf1[MAX_IOP_SIZE];
+	UINT32						 pkq_ibuf2[MAX_IOP_SIZE];
+	UINT32						 pkq_obuf[MAX_OOP_SIZE];
+};
+
+static LIST_HEAD(ixp_pkq); /* current PK wait list */
+static struct ixp_pkq *ixp_pk_cur;
+static spinlock_t ixp_pkq_lock;
+
+#endif /* __ixp46X */
+
+static int ixp_blocked = 0;
+
+static int32_t			 ixp_id = -1;
+static struct ixp_data **ixp_sessions = NULL;
+static u_int32_t		 ixp_sesnum = 0;
+
+static int ixp_process(device_t, struct cryptop *, int);
+static int ixp_newsession(device_t, u_int32_t *, struct cryptoini *);
+static int ixp_freesession(device_t, u_int64_t);
+#ifdef __ixp46X
+static int ixp_kprocess(device_t, struct cryptkop *krp, int hint);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static kmem_cache_t *qcache;
+#else
+static struct kmem_cache *qcache;
+#endif
+
+#define debug ixp_debug
+static int ixp_debug = 0;
+module_param(ixp_debug, int, 0644);
+MODULE_PARM_DESC(ixp_debug, "Enable debug");
+
+static int ixp_init_crypto = 1;
+module_param(ixp_init_crypto, int, 0444); /* RO after load/boot */
+MODULE_PARM_DESC(ixp_init_crypto, "Call ixCryptoAccInit (default is 1)");
+
+static void ixp_process_pending(void *arg);
+static void ixp_registration(void *arg);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+static void ixp_process_pending_wq(struct work_struct *work);
+static void ixp_registration_wq(struct work_struct *work);
+#endif
+
+/*
+ * dummy device structure
+ */
+
+static struct {
+	softc_device_decl	sc_dev;
+} ixpdev;
+
+static device_method_t ixp_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,	ixp_newsession),
+	DEVMETHOD(cryptodev_freesession,ixp_freesession),
+	DEVMETHOD(cryptodev_process,	ixp_process),
+#ifdef __ixp46X
+	DEVMETHOD(cryptodev_kprocess,	ixp_kprocess),
+#endif
+};
+
+/*
+ * Generate a new software session.
+ */
+static int
+ixp_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
+{
+	struct ixp_data *ixp;
+	u_int32_t i;
+#define AUTH_LEN(cri, def) \
+	(cri->cri_mlen ? cri->cri_mlen : (def))
+
+	dprintk("%s():alg %d\n", __FUNCTION__,cri->cri_alg);
+	if (sid == NULL || cri == NULL) {
+		dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	if (ixp_sessions) {
+		for (i = 1; i < ixp_sesnum; i++)
+			if (ixp_sessions[i] == NULL)
+				break;
+	} else
+		i = 1;		/* NB: to silence compiler warning */
+
+	if (ixp_sessions == NULL || i == ixp_sesnum) {
+		struct ixp_data **ixpd;
+
+		if (ixp_sessions == NULL) {
+			i = 1; /* We leave ixp_sessions[0] empty */
+			ixp_sesnum = CRYPTO_SW_SESSIONS;
+		} else
+			ixp_sesnum *= 2;
+
+		ixpd = kmalloc(ixp_sesnum * sizeof(struct ixp_data *), SLAB_ATOMIC);
+		if (ixpd == NULL) {
+			/* Reset session number */
+			if (ixp_sesnum == CRYPTO_SW_SESSIONS)
+				ixp_sesnum = 0;
+			else
+				ixp_sesnum /= 2;
+			dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+			return ENOBUFS;
+		}
+		memset(ixpd, 0, ixp_sesnum * sizeof(struct ixp_data *));
+
+		/* Copy existing sessions */
+		if (ixp_sessions) {
+			memcpy(ixpd, ixp_sessions,
+			    (ixp_sesnum / 2) * sizeof(struct ixp_data *));
+			kfree(ixp_sessions);
+		}
+
+		ixp_sessions = ixpd;
+	}
+
+	ixp_sessions[i] = (struct ixp_data *) kmalloc(sizeof(struct ixp_data),
+			SLAB_ATOMIC);
+	if (ixp_sessions[i] == NULL) {
+		ixp_freesession(NULL, i);
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return ENOBUFS;
+	}
+
+	*sid = i;
+
+	ixp = ixp_sessions[i];
+	memset(ixp, 0, sizeof(*ixp));
+
+	ixp->ixp_cipher_alg = -1;
+	ixp->ixp_auth_alg = -1;
+	ixp->ixp_ctx_id = -1;
+	INIT_LIST_HEAD(&ixp->ixp_q);
+
+	ixp->ixp_ctx.useDifferentSrcAndDestMbufs = 0;
+
+	while (cri) {
+		switch (cri->cri_alg) {
+		case CRYPTO_DES_CBC:
+			ixp->ixp_cipher_alg = cri->cri_alg;
+			ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_DES;
+			ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
+			ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
+			ixp->ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
+			ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen =
+						IX_CRYPTO_ACC_DES_IV_64;
+			memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
+					cri->cri_key, (cri->cri_klen + 7) / 8);
+			break;
+
+		case CRYPTO_3DES_CBC:
+			ixp->ixp_cipher_alg = cri->cri_alg;
+			ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES;
+			ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
+			ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
+			ixp->ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
+			ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen =
+						IX_CRYPTO_ACC_DES_IV_64;
+			memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
+					cri->cri_key, (cri->cri_klen + 7) / 8);
+			break;
+
+		case CRYPTO_RIJNDAEL128_CBC:
+			ixp->ixp_cipher_alg = cri->cri_alg;
+			ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_AES;
+			ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
+			ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
+			ixp->ixp_ctx.cipherCtx.cipherBlockLen = 16;
+			ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen = 16;
+			memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
+					cri->cri_key, (cri->cri_klen + 7) / 8);
+			break;
+
+		case CRYPTO_MD5:
+		case CRYPTO_MD5_HMAC:
+			ixp->ixp_auth_alg = cri->cri_alg;
+			ixp->ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_MD5;
+			ixp->ixp_ctx.authCtx.authDigestLen = AUTH_LEN(cri, MD5_HASH_LEN);
+			ixp->ixp_ctx.authCtx.aadLen = 0;
+			/* Only MD5_HMAC needs a key */
+			if (cri->cri_alg == CRYPTO_MD5_HMAC) {
+				ixp->ixp_ctx.authCtx.authKeyLen = (cri->cri_klen + 7) / 8;
+				if (ixp->ixp_ctx.authCtx.authKeyLen >
+						sizeof(ixp->ixp_ctx.authCtx.key.authKey)) {
+					printk(
+						"ixp4xx: Invalid key length for MD5_HMAC - %d bits\n",
+							cri->cri_klen);
+					ixp_freesession(NULL, i);
+					return EINVAL;
+				}
+				memcpy(ixp->ixp_ctx.authCtx.key.authKey,
+						cri->cri_key, (cri->cri_klen + 7) / 8);
+			}
+			break;
+
+		case CRYPTO_SHA1:
+		case CRYPTO_SHA1_HMAC:
+			ixp->ixp_auth_alg = cri->cri_alg;
+			ixp->ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1;
+			ixp->ixp_ctx.authCtx.authDigestLen = AUTH_LEN(cri, SHA1_HASH_LEN);
+			ixp->ixp_ctx.authCtx.aadLen = 0;
+			/* Only SHA1_HMAC needs a key */
+			if (cri->cri_alg == CRYPTO_SHA1_HMAC) {
+				ixp->ixp_ctx.authCtx.authKeyLen = (cri->cri_klen + 7) / 8;
+				if (ixp->ixp_ctx.authCtx.authKeyLen >
+						sizeof(ixp->ixp_ctx.authCtx.key.authKey)) {
+					printk(
+						"ixp4xx: Invalid key length for SHA1_HMAC - %d bits\n",
+							cri->cri_klen);
+					ixp_freesession(NULL, i);
+					return EINVAL;
+				}
+				memcpy(ixp->ixp_ctx.authCtx.key.authKey,
+						cri->cri_key, (cri->cri_klen + 7) / 8);
+			}
+			break;
+
+		default:
+			printk("ixp: unknown algo 0x%x\n", cri->cri_alg);
+			ixp_freesession(NULL, i);
+			return EINVAL;
+		}
+		cri = cri->cri_next;
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	INIT_WORK(&ixp->ixp_pending_work, ixp_process_pending_wq);
+	INIT_WORK(&ixp->ixp_registration_work, ixp_registration_wq);
+#else
+	INIT_WORK(&ixp->ixp_pending_work, ixp_process_pending, ixp);
+	INIT_WORK(&ixp->ixp_registration_work, ixp_registration, ixp);
+#endif
+
+	return 0;
+}
+
+
+/*
+ * Free a session.
+ */
+static int
+ixp_freesession(device_t dev, u_int64_t tid)
+{
+	u_int32_t sid = CRYPTO_SESID2LID(tid);
+
+	dprintk("%s()\n", __FUNCTION__);
+	if (sid > ixp_sesnum || ixp_sessions == NULL ||
+			ixp_sessions[sid] == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	/* Silently accept and return */
+	if (sid == 0)
+		return 0;
+
+	if (ixp_sessions[sid]) {
+		if (ixp_sessions[sid]->ixp_ctx_id != -1) {
+			ixCryptoAccCtxUnregister(ixp_sessions[sid]->ixp_ctx_id);
+			ixp_sessions[sid]->ixp_ctx_id = -1;
+		}
+
+		flush_scheduled_work();
+
+		kfree(ixp_sessions[sid]);
+	}
+	ixp_sessions[sid] = NULL;
+	if (ixp_blocked) {
+		ixp_blocked = 0;
+		crypto_unblock(ixp_id, CRYPTO_SYMQ);
+	}
+	return 0;
+}
+
+
+/*
+ * callback for when hash processing is complete
+ */
+
+static void
+ixp_hash_perform_cb(
+	UINT32 hash_key_id,
+	IX_MBUF *bufp,
+	IxCryptoAccStatus status)
+{
+	struct ixp_q *q;
+
+	dprintk("%s(%u, %p, 0x%x)\n", __FUNCTION__, hash_key_id, bufp, status);
+
+	if (bufp == NULL) {
+		printk("ixp: NULL buf in %s\n", __FUNCTION__);
+		return;
+	}
+
+	q = IX_MBUF_PRIV(bufp);
+	if (q == NULL) {
+		printk("ixp: NULL priv in %s\n", __FUNCTION__);
+		return;
+	}
+
+	if (status == IX_CRYPTO_ACC_STATUS_SUCCESS) {
+		/* On success, need to copy hash back into original client buffer */
+		memcpy(q->ixp_hash_dest, q->ixp_hash_src,
+				(q->ixp_q_data->ixp_auth_alg == CRYPTO_SHA1) ?
+					SHA1_HASH_LEN : MD5_HASH_LEN);
+	}
+	else {
+		printk("ixp: hash perform failed status=%d\n", status);
+		q->ixp_q_crp->crp_etype = EINVAL;
+	}
+
+	/* Free internal buffer used for hashing */
+	kfree(IX_MBUF_MDATA(&q->ixp_q_mbuf));
+
+	crypto_done(q->ixp_q_crp);
+	kmem_cache_free(qcache, q);
+}
+
+/*
+ * setup a request and perform it
+ */
+static void
+ixp_q_process(struct ixp_q *q)
+{
+	IxCryptoAccStatus status;
+	struct ixp_data *ixp = q->ixp_q_data;
+	int auth_off = 0;
+	int auth_len = 0;
+	int crypt_off = 0;
+	int crypt_len = 0;
+	int icv_off = 0;
+	char *crypt_func;
+
+	dprintk("%s(%p)\n", __FUNCTION__, q);
+
+	if (q->ixp_q_ccrd) {
+		if (q->ixp_q_ccrd->crd_flags & CRD_F_IV_EXPLICIT) {
+			q->ixp_q_iv = q->ixp_q_ccrd->crd_iv;
+		} else {
+			q->ixp_q_iv = q->ixp_q_iv_data;
+			crypto_copydata(q->ixp_q_crp->crp_flags, q->ixp_q_crp->crp_buf,
+					q->ixp_q_ccrd->crd_inject,
+					ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen,
+					(caddr_t) q->ixp_q_iv);
+		}
+
+		if (q->ixp_q_acrd) {
+			auth_off = q->ixp_q_acrd->crd_skip;
+			auth_len = q->ixp_q_acrd->crd_len;
+			icv_off  = q->ixp_q_acrd->crd_inject;
+		}
+
+		crypt_off = q->ixp_q_ccrd->crd_skip;
+		crypt_len = q->ixp_q_ccrd->crd_len;
+	} else { /* if (q->ixp_q_acrd) */
+		auth_off = q->ixp_q_acrd->crd_skip;
+		auth_len = q->ixp_q_acrd->crd_len;
+		icv_off  = q->ixp_q_acrd->crd_inject;
+	}
+
+	if (q->ixp_q_crp->crp_flags & CRYPTO_F_SKBUF) {
+		struct sk_buff *skb = (struct sk_buff *) q->ixp_q_crp->crp_buf;
+		if (skb_shinfo(skb)->nr_frags) {
+			/*
+			 * DAVIDM fix this limitation one day by using
+			 * a buffer pool and chaining,  it is not currently
+			 * needed for current user/kernel space acceleration
+			 */
+			printk("ixp: Cannot handle fragmented skb's yet !\n");
+			q->ixp_q_crp->crp_etype = ENOENT;
+			goto done;
+		}
+		IX_MBUF_MLEN(&q->ixp_q_mbuf) =
+				IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) =  skb->len;
+		IX_MBUF_MDATA(&q->ixp_q_mbuf) = skb->data;
+	} else if (q->ixp_q_crp->crp_flags & CRYPTO_F_IOV) {
+		struct uio *uiop = (struct uio *) q->ixp_q_crp->crp_buf;
+		if (uiop->uio_iovcnt != 1) {
+			/*
+			 * DAVIDM fix this limitation one day by using
+			 * a buffer pool and chaining,  it is not currently
+			 * needed for current user/kernel space acceleration
+			 */
+			printk("ixp: Cannot handle more than 1 iovec yet !\n");
+			q->ixp_q_crp->crp_etype = ENOENT;
+			goto done;
+		}
+		IX_MBUF_MLEN(&q->ixp_q_mbuf) =
+				IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = uiop->uio_iov[0].iov_len;
+		IX_MBUF_MDATA(&q->ixp_q_mbuf) = uiop->uio_iov[0].iov_base;
+	} else /* contig buffer */ {
+		IX_MBUF_MLEN(&q->ixp_q_mbuf)  =
+				IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = q->ixp_q_crp->crp_ilen;
+		IX_MBUF_MDATA(&q->ixp_q_mbuf) = q->ixp_q_crp->crp_buf;
+	}
+
+	IX_MBUF_PRIV(&q->ixp_q_mbuf) = q;
+
+	if (ixp->ixp_auth_alg == CRYPTO_SHA1 || ixp->ixp_auth_alg == CRYPTO_MD5) {
+		/*
+		 * For SHA1 and MD5 hash, need to create an internal buffer that is big
+		 * enough to hold the original data + the appropriate padding for the
+		 * hash algorithm.
+		 */
+		UINT8 *tbuf = NULL;
+
+		IX_MBUF_MLEN(&q->ixp_q_mbuf) = IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) =
+			((IX_MBUF_MLEN(&q->ixp_q_mbuf) * 8) + 72 + 511) / 8;
+		tbuf = kmalloc(IX_MBUF_MLEN(&q->ixp_q_mbuf), SLAB_ATOMIC);
+		
+		if (IX_MBUF_MDATA(&q->ixp_q_mbuf) == NULL) {
+			printk("ixp: kmalloc(%u, SLAB_ATOMIC) failed\n",
+					IX_MBUF_MLEN(&q->ixp_q_mbuf));
+			q->ixp_q_crp->crp_etype = ENOMEM;
+			goto done;
+		}
+		memcpy(tbuf, &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_off], auth_len);
+
+		/* Set location in client buffer to copy hash into */
+		q->ixp_hash_dest =
+			&(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_off + auth_len];
+
+		IX_MBUF_MDATA(&q->ixp_q_mbuf) = tbuf;
+
+		/* Set location in internal buffer for where hash starts */
+		q->ixp_hash_src = &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_len];
+
+		crypt_func = "ixCryptoAccHashPerform";
+		status = ixCryptoAccHashPerform(ixp->ixp_ctx.authCtx.authAlgo,
+				&q->ixp_q_mbuf, ixp_hash_perform_cb, 0, auth_len, auth_len,
+				&ixp->ixp_hash_key_id);
+	}
+	else {
+		crypt_func = "ixCryptoAccAuthCryptPerform";
+		status = ixCryptoAccAuthCryptPerform(ixp->ixp_ctx_id, &q->ixp_q_mbuf,
+			NULL, auth_off, auth_len, crypt_off, crypt_len, icv_off,
+			q->ixp_q_iv);
+	}
+
+	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
+		return;
+
+	if (IX_CRYPTO_ACC_STATUS_QUEUE_FULL == status) {
+		q->ixp_q_crp->crp_etype = ENOMEM;
+		goto done;
+	}
+
+	printk("ixp: %s failed %u\n", crypt_func, status);
+	q->ixp_q_crp->crp_etype = EINVAL;
+
+done:
+	crypto_done(q->ixp_q_crp);
+	kmem_cache_free(qcache, q);
+}
+
+
+/*
+ * because we cannot process the Q from the Register callback
+ * we do it here on a task Q.
+ */
+
+static void
+ixp_process_pending(void *arg)
+{
+	struct ixp_data *ixp = arg;
+	struct ixp_q *q = NULL;
+
+	dprintk("%s(%p)\n", __FUNCTION__, arg);
+
+	if (!ixp)
+		return;
+
+	while (!list_empty(&ixp->ixp_q)) {
+		q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
+		list_del(&q->ixp_q_list);
+		ixp_q_process(q);
+	}
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+static void
+ixp_process_pending_wq(struct work_struct *work)
+{
+	struct ixp_data *ixp = container_of(work, struct ixp_data,
+								ixp_pending_work);
+	ixp_process_pending(ixp);
+}
+#endif
+
+/*
+ * callback for when context registration is complete
+ */
+
+static void
+ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, IxCryptoAccStatus status)
+{
+	int i;
+	struct ixp_data *ixp;
+	struct ixp_q *q;
+
+	dprintk("%s(%d, %p, %d)\n", __FUNCTION__, ctx_id, bufp, status);
+
+	/*
+	 * free any buffer passed in to this routine
+	 */
+	if (bufp) {
+		IX_MBUF_MLEN(bufp) = IX_MBUF_PKT_LEN(bufp) = 0;
+		kfree(IX_MBUF_MDATA(bufp));
+		IX_MBUF_MDATA(bufp) = NULL;
+	}
+
+	for (i = 0; i < ixp_sesnum; i++) {
+		ixp = ixp_sessions[i];
+		if (ixp && ixp->ixp_ctx_id == ctx_id)
+			break;
+	}
+	if (i >= ixp_sesnum) {
+		printk("ixp: invalid context id %d\n", ctx_id);
+		return;
+	}
+
+	if (IX_CRYPTO_ACC_STATUS_WAIT == status) {
+		/* this is normal to free the first of two buffers */
+		dprintk("ixp: register not finished yet.\n");
+		return;
+	}
+
+	if (IX_CRYPTO_ACC_STATUS_SUCCESS != status) {
+		printk("ixp: register failed 0x%x\n", status);
+		while (!list_empty(&ixp->ixp_q)) {
+			q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
+			list_del(&q->ixp_q_list);
+			q->ixp_q_crp->crp_etype = EINVAL;
+			crypto_done(q->ixp_q_crp);
+			kmem_cache_free(qcache, q);
+		}
+		return;
+	}
+
+	/*
+	 * we are now registered,  we cannot start processing the Q here
+	 * or we get strange errors with AES (DES/3DES seem to be ok).
+	 */
+	ixp->ixp_registered = 1;
+	schedule_work(&ixp->ixp_pending_work);
+}
+
+
+/*
+ * callback for when data processing is complete
+ */
+
+static void
+ixp_perform_cb(
+	UINT32 ctx_id,
+	IX_MBUF *sbufp,
+	IX_MBUF *dbufp,
+	IxCryptoAccStatus status)
+{
+	struct ixp_q *q;
+
+	dprintk("%s(%d, %p, %p, 0x%x)\n", __FUNCTION__, ctx_id, sbufp,
+			dbufp, status);
+
+	if (sbufp == NULL) {
+		printk("ixp: NULL sbuf in ixp_perform_cb\n");
+		return;
+	}
+
+	q = IX_MBUF_PRIV(sbufp);
+	if (q == NULL) {
+		printk("ixp: NULL priv in ixp_perform_cb\n");
+		return;
+	}
+
+	if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
+		printk("ixp: perform failed status=%d\n", status);
+		q->ixp_q_crp->crp_etype = EINVAL;
+	}
+
+	crypto_done(q->ixp_q_crp);
+	kmem_cache_free(qcache, q);
+}
+
+
+/*
+ * registration is not callable at IRQ time,  so we defer
+ * to a task queue,  this routines completes the registration for us
+ * when the task queue runs
+ *
+ * Unfortunately this means we cannot tell OCF that the driver is blocked,
+ * we do that on the next request.
+ */
+
+static void
+ixp_registration(void *arg)
+{
+	struct ixp_data *ixp = arg;
+	struct ixp_q *q = NULL;
+	IX_MBUF *pri = NULL, *sec = NULL;
+	int status = IX_CRYPTO_ACC_STATUS_SUCCESS;
+
+	if (!ixp) {
+		printk("ixp: ixp_registration with no arg\n");
+		return;
+	}
+
+	if (ixp->ixp_ctx_id != -1) {
+		ixCryptoAccCtxUnregister(ixp->ixp_ctx_id);
+		ixp->ixp_ctx_id = -1;
+	}
+
+	if (list_empty(&ixp->ixp_q)) {
+		printk("ixp: ixp_registration with no Q\n");
+		return;
+	}
+
+	/*
+	 * setup the primary and secondary buffers
+	 */
+	q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
+	if (q->ixp_q_acrd) {
+		pri = &ixp->ixp_pri_mbuf;
+		sec = &ixp->ixp_sec_mbuf;
+		IX_MBUF_MLEN(pri)  = IX_MBUF_PKT_LEN(pri) = 128;
+		IX_MBUF_MDATA(pri) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
+		IX_MBUF_MLEN(sec)  = IX_MBUF_PKT_LEN(sec) = 128;
+		IX_MBUF_MDATA(sec) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
+	}
+
+	/* Only need to register if a crypt op or HMAC op */
+	if (!(ixp->ixp_auth_alg == CRYPTO_SHA1 ||
+				ixp->ixp_auth_alg == CRYPTO_MD5)) {
+		status = ixCryptoAccCtxRegister(
+					&ixp->ixp_ctx,
+					pri, sec,
+					ixp_register_cb,
+					ixp_perform_cb,
+					&ixp->ixp_ctx_id);
+	}
+	else {
+		/* Otherwise we start processing pending q */
+		schedule_work(&ixp->ixp_pending_work);
+	}
+
+	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
+		return;
+
+	if (IX_CRYPTO_ACC_STATUS_EXCEED_MAX_TUNNELS == status) {
+		printk("ixp: ixCryptoAccCtxRegister failed (out of tunnels)\n");
+		ixp_blocked = 1;
+		/* perhaps we should return EGAIN on queued ops ? */
+		return;
+	}
+
+	printk("ixp: ixCryptoAccCtxRegister failed %d\n", status);
+	ixp->ixp_ctx_id = -1;
+
+	/*
+	 * everything waiting is toasted
+	 */
+	while (!list_empty(&ixp->ixp_q)) {
+		q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
+		list_del(&q->ixp_q_list);
+		q->ixp_q_crp->crp_etype = ENOENT;
+		crypto_done(q->ixp_q_crp);
+		kmem_cache_free(qcache, q);
+	}
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+static void
+ixp_registration_wq(struct work_struct *work)
+{
+	struct ixp_data *ixp = container_of(work, struct ixp_data,
+								ixp_registration_work);
+	ixp_registration(ixp);
+}
+#endif
+
+/*
+ * Process a request.
+ */
+static int
+ixp_process(device_t dev, struct cryptop *crp, int hint)
+{
+	struct ixp_data *ixp;
+	unsigned int lid;
+	struct ixp_q *q = NULL;
+	int status;
+
+	dprintk("%s()\n", __FUNCTION__);
+
+	/* Sanity check */
+	if (crp == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	crp->crp_etype = 0;
+
+	if (ixp_blocked)
+		return ERESTART;
+
+	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		crp->crp_etype = EINVAL;
+		goto done;
+	}
+
+	/*
+	 * find the session we are using
+	 */
+
+	lid = crp->crp_sid & 0xffffffff;
+	if (lid >= ixp_sesnum || lid == 0 || ixp_sessions == NULL ||
+			ixp_sessions[lid] == NULL) {
+		crp->crp_etype = ENOENT;
+		dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
+		goto done;
+	}
+	ixp = ixp_sessions[lid];
+
+	/*
+	 * setup a new request ready for queuing
+	 */
+	q = kmem_cache_alloc(qcache, SLAB_ATOMIC);
+	if (q == NULL) {
+		dprintk("%s,%d: ENOMEM\n", __FILE__, __LINE__);
+		crp->crp_etype = ENOMEM;
+		goto done;
+	}
+	/*
+	 * save some cycles by only zeroing the important bits
+	 */
+	memset(&q->ixp_q_mbuf, 0, sizeof(q->ixp_q_mbuf));
+	q->ixp_q_ccrd = NULL;
+	q->ixp_q_acrd = NULL;
+	q->ixp_q_crp = crp;
+	q->ixp_q_data = ixp;
+
+	/*
+	 * point the cipher and auth descriptors appropriately
+	 * check that we have something to do
+	 */
+	if (crp->crp_desc->crd_alg == ixp->ixp_cipher_alg)
+		q->ixp_q_ccrd = crp->crp_desc;
+	else if (crp->crp_desc->crd_alg == ixp->ixp_auth_alg)
+		q->ixp_q_acrd = crp->crp_desc;
+	else {
+		crp->crp_etype = ENOENT;
+		dprintk("%s,%d: bad desc match: ENOENT\n", __FILE__, __LINE__);
+		goto done;
+	}
+	if (crp->crp_desc->crd_next) {
+		if (crp->crp_desc->crd_next->crd_alg == ixp->ixp_cipher_alg)
+			q->ixp_q_ccrd = crp->crp_desc->crd_next;
+		else if (crp->crp_desc->crd_next->crd_alg == ixp->ixp_auth_alg)
+			q->ixp_q_acrd = crp->crp_desc->crd_next;
+		else {
+			crp->crp_etype = ENOENT;
+			dprintk("%s,%d: bad desc match: ENOENT\n", __FILE__, __LINE__);
+			goto done;
+		}
+	}
+
+	/*
+	 * If there is a direction change for this context then we mark it as
+	 * unregistered and re-register is for the new direction.  This is not
+	 * a very expensive operation and currently only tends to happen when
+	 * user-space application are doing benchmarks
+	 *
+	 * DM - we should be checking for pending requests before unregistering.
+	 */
+	if (q->ixp_q_ccrd && ixp->ixp_registered &&
+			ixp->ixp_crd_flags != (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT)) {
+		dprintk("%s - detected direction change on session\n", __FUNCTION__);
+		ixp->ixp_registered = 0;
+	}
+
+	/*
+	 * if we are registered,  call straight into the perform code
+	 */
+	if (ixp->ixp_registered) {
+		ixp_q_process(q);
+		return 0;
+	}
+
+	/*
+	 * the only part of the context not set in newsession is the direction
+	 * dependent parts
+	 */
+	if (q->ixp_q_ccrd) {
+		ixp->ixp_crd_flags = (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT);
+		if (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT) {
+			ixp->ixp_ctx.operation = q->ixp_q_acrd ?
+					IX_CRYPTO_ACC_OP_ENCRYPT_AUTH : IX_CRYPTO_ACC_OP_ENCRYPT;
+		} else {
+			ixp->ixp_ctx.operation = q->ixp_q_acrd ?
+					IX_CRYPTO_ACC_OP_AUTH_DECRYPT : IX_CRYPTO_ACC_OP_DECRYPT;
+		}
+	} else {
+		/* q->ixp_q_acrd must be set if we are here */
+		ixp->ixp_ctx.operation = IX_CRYPTO_ACC_OP_AUTH_CALC;
+	}
+
+	status = list_empty(&ixp->ixp_q);
+	list_add_tail(&q->ixp_q_list, &ixp->ixp_q);
+	if (status)
+		schedule_work(&ixp->ixp_registration_work);
+	return 0;
+
+done:
+	if (q)
+		kmem_cache_free(qcache, q);
+	crypto_done(crp);
+	return 0;
+}
+
+
+#ifdef __ixp46X
+/*
+ * key processing support for the ixp465
+ */
+
+
+/*
+ * copy a BN (LE) into a buffer (BE) an fill out the op appropriately
+ * assume zeroed and only copy bits that are significant
+ */
+
+static int
+ixp_copy_ibuf(struct crparam *p, IxCryptoAccPkeEauOperand *op, UINT32 *buf)
+{
+	unsigned char *src = (unsigned char *) p->crp_p;
+	unsigned char *dst;
+	int len, bits = p->crp_nbits;
+
+	dprintk("%s()\n", __FUNCTION__);
+
+	if (bits > MAX_IOP_SIZE * sizeof(UINT32) * 8) {
+		dprintk("%s - ibuf too big (%d > %d)\n", __FUNCTION__,
+				bits, MAX_IOP_SIZE * sizeof(UINT32) * 8);
+		return -1;
+	}
+
+	len = (bits + 31) / 32; /* the number UINT32's needed */
+
+	dst = (unsigned char *) &buf[len];
+	dst--;
+
+	while (bits > 0) {
+		*dst-- = *src++;
+		bits -= 8;
+	}
+
+#if 0 /* no need to zero remaining bits as it is done during request alloc */
+	while (dst > (unsigned char *) buf)
+		*dst-- = '\0';
+#endif
+
+	op->pData = buf;
+	op->dataLen = len;
+	return 0;
+}
+
+/*
+ * copy out the result,  be as forgiving as we can about small output buffers
+ */
+
+static int
+ixp_copy_obuf(struct crparam *p, IxCryptoAccPkeEauOpResult *op, UINT32 *buf)
+{
+	unsigned char *dst = (unsigned char *) p->crp_p;
+	unsigned char *src = (unsigned char *) buf;
+	int len, z, bits = p->crp_nbits;
+
+	dprintk("%s()\n", __FUNCTION__);
+
+	len = op->dataLen * sizeof(UINT32);
+
+	/* skip leading zeroes to be small buffer friendly */
+	z = 0;
+	while (z < len && src[z] == '\0')
+		z++;
+
+	src += len;
+	src--;
+	len -= z;
+
+	while (len > 0 && bits > 0) {
+		*dst++ = *src--;
+		len--;
+		bits -= 8;
+	}
+
+	while (bits > 0) {
+		*dst++ = '\0';
+		bits -= 8;
+	}
+
+	if (len > 0) {
+		dprintk("%s - obuf is %d (z=%d, ob=%d) bytes too small\n",
+				__FUNCTION__, len, z, p->crp_nbits / 8);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * the parameter offsets for exp_mod
+ */
+
+#define IXP_PARAM_BASE 0
+#define IXP_PARAM_EXP  1
+#define IXP_PARAM_MOD  2
+#define IXP_PARAM_RES  3
+
+/*
+ * key processing complete callback,  is also used to start processing
+ * by passing a NULL for pResult
+ */
+
+static void
+ixp_kperform_cb(
+	IxCryptoAccPkeEauOperation operation,
+	IxCryptoAccPkeEauOpResult *pResult,
+	BOOL carryOrBorrow,
+	IxCryptoAccStatus status)
+{
+	struct ixp_pkq *q, *tmp;
+	unsigned long flags;
+
+	dprintk("%s(0x%x, %p, %d, 0x%x)\n", __FUNCTION__, operation, pResult,
+			carryOrBorrow, status);
+
+	/* handle a completed request */
+	if (pResult) {
+		if (ixp_pk_cur && &ixp_pk_cur->pkq_result == pResult) {
+			q = ixp_pk_cur;
+			if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
+				dprintk("%s() - op failed 0x%x\n", __FUNCTION__, status);
+				q->pkq_krp->krp_status = ERANGE; /* could do better */
+			} else {
+				/* copy out the result */
+				if (ixp_copy_obuf(&q->pkq_krp->krp_param[IXP_PARAM_RES],
+						&q->pkq_result, q->pkq_obuf))
+					q->pkq_krp->krp_status = ERANGE;
+			}
+			crypto_kdone(q->pkq_krp);
+			kfree(q);
+			ixp_pk_cur = NULL;
+		} else
+			printk("%s - callback with invalid result pointer\n", __FUNCTION__);
+	}
+
+	spin_lock_irqsave(&ixp_pkq_lock, flags);
+	if (ixp_pk_cur || list_empty(&ixp_pkq)) {
+		spin_unlock_irqrestore(&ixp_pkq_lock, flags);
+		return;
+	}
+
+	list_for_each_entry_safe(q, tmp, &ixp_pkq, pkq_list) {
+
+		list_del(&q->pkq_list);
+		ixp_pk_cur = q;
+
+		spin_unlock_irqrestore(&ixp_pkq_lock, flags);
+
+		status = ixCryptoAccPkeEauPerform(
+				IX_CRYPTO_ACC_OP_EAU_MOD_EXP,
+				&q->pkq_op,
+				ixp_kperform_cb,
+				&q->pkq_result);
+	
+		if (status == IX_CRYPTO_ACC_STATUS_SUCCESS) {
+			dprintk("%s() - ixCryptoAccPkeEauPerform SUCCESS\n", __FUNCTION__);
+			return; /* callback will return here for callback */
+		} else if (status == IX_CRYPTO_ACC_STATUS_RETRY) {
+			printk("%s() - ixCryptoAccPkeEauPerform RETRY\n", __FUNCTION__);
+		} else {
+			printk("%s() - ixCryptoAccPkeEauPerform failed %d\n",
+					__FUNCTION__, status);
+		}
+		q->pkq_krp->krp_status = ERANGE; /* could do better */
+		crypto_kdone(q->pkq_krp);
+		kfree(q);
+		spin_lock_irqsave(&ixp_pkq_lock, flags);
+	}
+	spin_unlock_irqrestore(&ixp_pkq_lock, flags);
+}
+
+
+static int
+ixp_kprocess(device_t dev, struct cryptkop *krp, int hint)
+{
+	struct ixp_pkq *q;
+	int rc = 0;
+	unsigned long flags;
+
+	dprintk("%s l1=%d l2=%d l3=%d l4=%d\n", __FUNCTION__,
+			krp->krp_param[IXP_PARAM_BASE].crp_nbits,
+			krp->krp_param[IXP_PARAM_EXP].crp_nbits,
+			krp->krp_param[IXP_PARAM_MOD].crp_nbits,
+			krp->krp_param[IXP_PARAM_RES].crp_nbits);
+
+
+	if (krp->krp_op != CRK_MOD_EXP) {
+		krp->krp_status = EOPNOTSUPP;
+		goto err;
+	}
+
+	q = (struct ixp_pkq *) kmalloc(sizeof(*q), GFP_KERNEL);
+	if (q == NULL) {
+		krp->krp_status = ENOMEM;
+		goto err;
+	}
+
+	/*
+	 * The PKE engine does not appear to zero the output buffer
+	 * appropriately, so we need to do it all here.
+	 */
+	memset(q, 0, sizeof(*q));
+
+	q->pkq_krp = krp;
+	INIT_LIST_HEAD(&q->pkq_list);
+
+	if (ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_BASE], &q->pkq_op.modExpOpr.M,
+			q->pkq_ibuf0))
+		rc = 1;
+	if (!rc && ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_EXP],
+				&q->pkq_op.modExpOpr.e, q->pkq_ibuf1))
+		rc = 2;
+	if (!rc && ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_MOD],
+				&q->pkq_op.modExpOpr.N, q->pkq_ibuf2))
+		rc = 3;
+
+	if (rc) {
+		kfree(q);
+		krp->krp_status = ERANGE;
+		goto err;
+	}
+
+	q->pkq_result.pData           = q->pkq_obuf;
+	q->pkq_result.dataLen         =
+			(krp->krp_param[IXP_PARAM_RES].crp_nbits + 31) / 32;
+
+	spin_lock_irqsave(&ixp_pkq_lock, flags);
+	list_add_tail(&q->pkq_list, &ixp_pkq);
+	spin_unlock_irqrestore(&ixp_pkq_lock, flags);
+
+	if (!ixp_pk_cur)
+		ixp_kperform_cb(0, NULL, 0, 0);
+	return (0);
+
+err:
+	crypto_kdone(krp);
+	return (0);
+}
+
+
+
+#ifdef CONFIG_OCF_RANDOMHARVEST
+/*
+ * We run the random number generator output through SHA so that it
+ * is FIPS compliant.
+ */
+
+static volatile int sha_done = 0;
+static unsigned char sha_digest[20];
+
+static void
+ixp_hash_cb(UINT8 *digest, IxCryptoAccStatus status)
+{
+	dprintk("%s(%p, %d)\n", __FUNCTION__, digest, status);
+	if (sha_digest != digest)
+		printk("digest error\n");
+	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
+		sha_done = 1;
+	else
+		sha_done = -status;
+}
+
+static int
+ixp_read_random(void *arg, u_int32_t *buf, int maxwords)
+{
+	IxCryptoAccStatus status;
+	int i, n, rc;
+
+	dprintk("%s(%p, %d)\n", __FUNCTION__, buf, maxwords);
+	memset(buf, 0, maxwords * sizeof(*buf));
+	status = ixCryptoAccPkePseudoRandomNumberGet(maxwords, buf);
+	if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
+		dprintk("%s: ixCryptoAccPkePseudoRandomNumberGet failed %d\n",
+				__FUNCTION__, status);
+		return 0;
+	}
+
+	/*
+	 * run the random data through SHA to make it look more random
+	 */
+
+	n = sizeof(sha_digest); /* process digest bytes at a time */
+
+	rc = 0;
+	for (i = 0; i < maxwords; i += n / sizeof(*buf)) {
+		if ((maxwords - i) * sizeof(*buf) < n)
+			n = (maxwords - i) * sizeof(*buf);
+		sha_done = 0;
+		status = ixCryptoAccPkeHashPerform(IX_CRYPTO_ACC_AUTH_SHA1,
+				(UINT8 *) &buf[i], n, ixp_hash_cb, sha_digest);
+		if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
+			dprintk("ixCryptoAccPkeHashPerform failed %d\n", status);
+			return -EIO;
+		}
+		while (!sha_done)
+			schedule();
+		if (sha_done < 0) {
+			dprintk("ixCryptoAccPkeHashPerform failed CB %d\n", -sha_done);
+			return 0;
+		}
+		memcpy(&buf[i], sha_digest, n);
+		rc += n / sizeof(*buf);;
+	}
+
+	return rc;
+}
+#endif /* CONFIG_OCF_RANDOMHARVEST */
+
+#endif /* __ixp46X */
+
+
+
+/*
+ * our driver startup and shutdown routines
+ */
+
+static int
+ixp_init(void)
+{
+	dprintk("%s(%p)\n", __FUNCTION__, ixp_init);
+
+	if (ixp_init_crypto && ixCryptoAccInit() != IX_CRYPTO_ACC_STATUS_SUCCESS)
+		printk("ixCryptoAccInit failed, assuming already initialised!\n");
+
+	qcache = kmem_cache_create("ixp4xx_q", sizeof(struct ixp_q), 0,
+				SLAB_HWCACHE_ALIGN, NULL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+				, NULL
+#endif
+				  );
+	if (!qcache) {
+		printk("failed to create Qcache\n");
+		return -ENOENT;
+	}
+
+	memset(&ixpdev, 0, sizeof(ixpdev));
+	softc_device_init(&ixpdev, "ixp4xx", 0, ixp_methods);
+
+	ixp_id = crypto_get_driverid(softc_get_device(&ixpdev),
+				CRYPTOCAP_F_HARDWARE);
+	if (ixp_id < 0)
+		panic("IXP/OCF crypto device cannot initialize!");
+
+#define	REGISTER(alg) \
+	crypto_register(ixp_id,alg,0,0)
+
+	REGISTER(CRYPTO_DES_CBC);
+	REGISTER(CRYPTO_3DES_CBC);
+	REGISTER(CRYPTO_RIJNDAEL128_CBC);
+#ifdef CONFIG_OCF_IXP4XX_SHA1_MD5
+	REGISTER(CRYPTO_MD5);
+	REGISTER(CRYPTO_SHA1);
+#endif
+	REGISTER(CRYPTO_MD5_HMAC);
+	REGISTER(CRYPTO_SHA1_HMAC);
+#undef REGISTER
+
+#ifdef __ixp46X
+	spin_lock_init(&ixp_pkq_lock);
+	/*
+	 * we do not enable the go fast options here as they can potentially
+	 * allow timing based attacks
+	 *
+	 * http://www.openssl.org/news/secadv_20030219.txt
+	 */
+	ixCryptoAccPkeEauExpConfig(0, 0);
+	crypto_kregister(ixp_id, CRK_MOD_EXP, 0);
+#ifdef CONFIG_OCF_RANDOMHARVEST
+	crypto_rregister(ixp_id, ixp_read_random, NULL);
+#endif
+#endif
+
+	return 0;
+}
+
+static void
+ixp_exit(void)
+{
+	dprintk("%s()\n", __FUNCTION__);
+	crypto_unregister_all(ixp_id);
+	ixp_id = -1;
+	kmem_cache_destroy(qcache);
+	qcache = NULL;
+}
+
+module_init(ixp_init);
+module_exit(ixp_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("David McCullough <dmccullough@cyberguard.com>");
+MODULE_DESCRIPTION("ixp (OCF module for IXP4xx crypto)");
diff --git a/crypto/ocf/ocf-bench.c b/crypto/ocf/ocf-bench.c
new file mode 100755
index 0000000..5eef6b1
--- /dev/null
+++ b/crypto/ocf/ocf-bench.c
@@ -0,0 +1,436 @@
+/*
+ * A loadable module that benchmarks the OCF crypto speed from kernel space.
+ *
+ * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com>
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ */
+
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <cryptodev.h>
+
+#ifdef I_HAVE_AN_XSCALE_WITH_INTEL_SDK
+#define BENCH_IXP_ACCESS_LIB 1
+#endif
+#ifdef BENCH_IXP_ACCESS_LIB
+#include <IxTypes.h>
+#include <IxOsBuffMgt.h>
+#include <IxNpeDl.h>
+#include <IxCryptoAcc.h>
+#include <IxQMgr.h>
+#include <IxOsServices.h>
+#include <IxOsCacheMMU.h>
+#endif
+
+/*
+ * support for access lib version 1.4
+ */
+#ifndef IX_MBUF_PRIV
+#define IX_MBUF_PRIV(x) ((x)->priv)
+#endif
+
+/*
+ * the number of simultaneously active requests
+ */
+static int request_q_len = 20;
+module_param(request_q_len, int, 0);
+MODULE_PARM_DESC(request_q_len, "Number of outstanding requests");
+/*
+ * how many requests we want to have processed
+ */
+static int request_num = 1024;
+module_param(request_num, int, 0);
+MODULE_PARM_DESC(request_num, "run for at least this many requests");
+/*
+ * the size of each request
+ */
+static int request_size = 1500;
+module_param(request_size, int, 0);
+MODULE_PARM_DESC(request_size, "size of each request");
+
+/*
+ * a structure for each request
+ */
+typedef struct  {
+	struct work_struct work;
+#ifdef BENCH_IXP_ACCESS_LIB
+	IX_MBUF mbuf;
+#endif
+	unsigned char *buffer;
+} request_t;
+
+static request_t *requests;
+
+static int outstanding;
+static int total;
+
+/*************************************************************************/
+/*
+ * OCF benchmark routines
+ */
+
+static uint64_t ocf_cryptoid;
+static int ocf_init(void);
+static int ocf_cb(struct cryptop *crp);
+static void ocf_request(void *arg);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+static void ocf_request_wq(struct work_struct *work);
+#endif
+
+static int
+ocf_init(void)
+{
+	int error;
+	struct cryptoini crie, cria;
+	struct cryptodesc crda, crde;
+
+	memset(&crie, 0, sizeof(crie));
+	memset(&cria, 0, sizeof(cria));
+	memset(&crde, 0, sizeof(crde));
+	memset(&crda, 0, sizeof(crda));
+
+	cria.cri_alg  = CRYPTO_SHA1_HMAC;
+	cria.cri_klen = 20 * 8;
+	cria.cri_key  = "0123456789abcdefghij";
+
+	crie.cri_alg  = CRYPTO_3DES_CBC;
+	crie.cri_klen = 24 * 8;
+	crie.cri_key  = "0123456789abcdefghijklmn";
+
+	crie.cri_next = &cria;
+
+	error = crypto_newsession(&ocf_cryptoid, &crie, 0);
+	if (error) {
+		printk("crypto_newsession failed %d\n", error);
+		return -1;
+	}
+	return 0;
+}
+
+static int
+ocf_cb(struct cryptop *crp)
+{
+	request_t *r = (request_t *) crp->crp_opaque;
+
+	if (crp->crp_etype)
+		printk("Error in OCF processing: %d\n", crp->crp_etype);
+	total++;
+	crypto_freereq(crp);
+	crp = NULL;
+
+	if (total > request_num) {
+		outstanding--;
+		return 0;
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	INIT_WORK(&r->work, ocf_request_wq);
+#else
+	INIT_WORK(&r->work, ocf_request, r);
+#endif
+	schedule_work(&r->work);
+	return 0;
+}
+
+
+static void
+ocf_request(void *arg)
+{
+	request_t *r = arg;
+	struct cryptop *crp = crypto_getreq(2);
+	struct cryptodesc *crde, *crda;
+
+	if (!crp) {
+		outstanding--;
+		return;
+	}
+
+	crde = crp->crp_desc;
+	crda = crde->crd_next;
+
+	crda->crd_skip = 0;
+	crda->crd_flags = 0;
+	crda->crd_len = request_size;
+	crda->crd_inject = request_size;
+	crda->crd_alg = CRYPTO_SHA1_HMAC;
+	crda->crd_key = "0123456789abcdefghij";
+	crda->crd_klen = 20 * 8;
+
+	crde->crd_skip = 0;
+	crde->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_ENCRYPT;
+	crde->crd_len = request_size;
+	crde->crd_inject = request_size;
+	crde->crd_alg = CRYPTO_3DES_CBC;
+	crde->crd_key = "0123456789abcdefghijklmn";
+	crde->crd_klen = 24 * 8;
+
+	crp->crp_ilen = request_size + 64;
+	crp->crp_flags = CRYPTO_F_CBIMM;
+	crp->crp_buf = (caddr_t) r->buffer;
+	crp->crp_callback = ocf_cb;
+	crp->crp_sid = ocf_cryptoid;
+	crp->crp_opaque = (caddr_t) r;
+	crypto_dispatch(crp);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+static void
+ocf_request_wq(struct work_struct *work)
+{
+	request_t *r = container_of(work, request_t, work);
+	ocf_request(r);
+}
+#endif
+
+/*************************************************************************/
+#ifdef BENCH_IXP_ACCESS_LIB
+/*************************************************************************/
+/*
+ * CryptoAcc benchmark routines
+ */
+
+static IxCryptoAccCtx ixp_ctx;
+static UINT32 ixp_ctx_id;
+static IX_MBUF ixp_pri;
+static IX_MBUF ixp_sec;
+static int ixp_registered = 0;
+
+static void ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp,
+					IxCryptoAccStatus status);
+static void ixp_perform_cb(UINT32 ctx_id, IX_MBUF *sbufp, IX_MBUF *dbufp,
+					IxCryptoAccStatus status);
+static void ixp_request(void *arg);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+static void ixp_request_wq(struct work_struct *work);
+#endif
+
+static int
+ixp_init(void)
+{
+	IxCryptoAccStatus status;
+
+	ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES;
+	ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
+	ixp_ctx.cipherCtx.cipherKeyLen = 24;
+	ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
+	ixp_ctx.cipherCtx.cipherInitialVectorLen = IX_CRYPTO_ACC_DES_IV_64;
+	memcpy(ixp_ctx.cipherCtx.key.cipherKey, "0123456789abcdefghijklmn", 24);
+
+	ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1;
+	ixp_ctx.authCtx.authDigestLen = 12;
+	ixp_ctx.authCtx.aadLen = 0;
+	ixp_ctx.authCtx.authKeyLen = 20;
+	memcpy(ixp_ctx.authCtx.key.authKey, "0123456789abcdefghij", 20);
+
+	ixp_ctx.useDifferentSrcAndDestMbufs = 0;
+	ixp_ctx.operation = IX_CRYPTO_ACC_OP_ENCRYPT_AUTH ;
+
+	IX_MBUF_MLEN(&ixp_pri)  = IX_MBUF_PKT_LEN(&ixp_pri) = 128;
+	IX_MBUF_MDATA(&ixp_pri) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
+	IX_MBUF_MLEN(&ixp_sec)  = IX_MBUF_PKT_LEN(&ixp_sec) = 128;
+	IX_MBUF_MDATA(&ixp_sec) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
+
+	status = ixCryptoAccCtxRegister(&ixp_ctx, &ixp_pri, &ixp_sec,
+			ixp_register_cb, ixp_perform_cb, &ixp_ctx_id);
+
+	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status) {
+		while (!ixp_registered)
+			schedule();
+		return ixp_registered < 0 ? -1 : 0;
+	}
+
+	printk("ixp: ixCryptoAccCtxRegister failed %d\n", status);
+	return -1;
+}
+
+static void
+ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, IxCryptoAccStatus status)
+{
+	if (bufp) {
+		IX_MBUF_MLEN(bufp) = IX_MBUF_PKT_LEN(bufp) = 0;
+		kfree(IX_MBUF_MDATA(bufp));
+		IX_MBUF_MDATA(bufp) = NULL;
+	}
+
+	if (IX_CRYPTO_ACC_STATUS_WAIT == status)
+		return;
+	if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
+		ixp_registered = 1;
+	else
+		ixp_registered = -1;
+}
+
+static void
+ixp_perform_cb(
+	UINT32 ctx_id,
+	IX_MBUF *sbufp,
+	IX_MBUF *dbufp,
+	IxCryptoAccStatus status)
+{
+	request_t *r = NULL;
+
+	total++;
+	if (total > request_num) {
+		outstanding--;
+		return;
+	}
+
+	if (!sbufp || !(r = IX_MBUF_PRIV(sbufp))) {
+		printk("crappo %p %p\n", sbufp, r);
+		outstanding--;
+		return;
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	INIT_WORK(&r->work, ixp_request_wq);
+#else
+	INIT_WORK(&r->work, ixp_request, r);
+#endif
+	schedule_work(&r->work);
+}
+
+static void
+ixp_request(void *arg)
+{
+	request_t *r = arg;
+	IxCryptoAccStatus status;
+
+	memset(&r->mbuf, 0, sizeof(r->mbuf));
+	IX_MBUF_MLEN(&r->mbuf) = IX_MBUF_PKT_LEN(&r->mbuf) = request_size + 64;
+	IX_MBUF_MDATA(&r->mbuf) = r->buffer;
+	IX_MBUF_PRIV(&r->mbuf) = r;
+	status = ixCryptoAccAuthCryptPerform(ixp_ctx_id, &r->mbuf, NULL,
+			0, request_size, 0, request_size, request_size, r->buffer);
+	if (IX_CRYPTO_ACC_STATUS_SUCCESS != status) {
+		printk("status1 = %d\n", status);
+		outstanding--;
+		return;
+	}
+	return;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+static void
+ixp_request_wq(struct work_struct *work)
+{
+	request_t *r = container_of(work, request_t, work);
+	ixp_request(r);
+}
+#endif
+
+/*************************************************************************/
+#endif /* BENCH_IXP_ACCESS_LIB */
+/*************************************************************************/
+
+int
+ocfbench_init(void)
+{
+	int i, jstart, jstop;
+
+	printk("Crypto Speed tests\n");
+
+	requests = kmalloc(sizeof(request_t) * request_q_len, GFP_KERNEL);
+	if (!requests) {
+		printk("malloc failed\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < request_q_len; i++) {
+		/* +64 for return data */
+		requests[i].buffer = kmalloc(request_size + 128, GFP_DMA);
+		if (!requests[i].buffer) {
+			printk("malloc failed\n");
+			return -EINVAL;
+		}
+		memset(requests[i].buffer, '0' + i, request_size + 128);
+	}
+
+	/*
+	 * OCF benchmark
+	 */
+	printk("OCF: testing ...\n");
+	ocf_init();
+	total = outstanding = 0;
+	jstart = jiffies;
+	for (i = 0; i < request_q_len; i++) {
+		outstanding++;
+		ocf_request(&requests[i]);
+	}
+	while (outstanding > 0)
+		schedule();
+	jstop = jiffies;
+
+	printk("OCF: %d requests of %d bytes in %d jiffies\n", total, request_size,
+			jstop - jstart);
+
+#ifdef BENCH_IXP_ACCESS_LIB
+	/*
+	 * IXP benchmark
+	 */
+	printk("IXP: testing ...\n");
+	ixp_init();
+	total = outstanding = 0;
+	jstart = jiffies;
+	for (i = 0; i < request_q_len; i++) {
+		outstanding++;
+		ixp_request(&requests[i]);
+	}
+	while (outstanding > 0)
+		schedule();
+	jstop = jiffies;
+
+	printk("IXP: %d requests of %d bytes in %d jiffies\n", total, request_size,
+			jstop - jstart);
+#endif /* BENCH_IXP_ACCESS_LIB */
+
+	for (i = 0; i < request_q_len; i++)
+		kfree(requests[i].buffer);
+	kfree(requests);
+	return -EINVAL; /* always fail to load so it can be re-run quickly ;-) */
+}
+
+static void __exit ocfbench_exit(void)
+{
+}
+
+module_init(ocfbench_init);
+module_exit(ocfbench_exit);
+
+MODULE_LICENSE("BSD");
+MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_DESCRIPTION("Benchmark various in-kernel crypto speeds");
diff --git a/crypto/ocf/ocf-compat.h b/crypto/ocf/ocf-compat.h
new file mode 100755
index 0000000..53f8b0c8
--- /dev/null
+++ b/crypto/ocf/ocf-compat.h
@@ -0,0 +1,260 @@
+#ifndef _BSD_COMPAT_H_
+#define _BSD_COMPAT_H_ 1
+/****************************************************************************/
+/*
+ * Provide compat routines for older linux kernels and BSD kernels
+ *
+ * Written by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2007 David McCullough <david_mccullough@securecomputing.com>
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this file
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ */
+/****************************************************************************/
+#ifdef __KERNEL__
+/*
+ * fake some BSD driver interface stuff specifically for OCF use
+ */
+
+typedef struct ocf_device *device_t;
+
+typedef struct {
+	int (*cryptodev_newsession)(device_t dev, u_int32_t *sidp, struct cryptoini *cri);
+	int (*cryptodev_freesession)(device_t dev, u_int64_t tid);
+	int (*cryptodev_process)(device_t dev, struct cryptop *crp, int hint);
+	int (*cryptodev_kprocess)(device_t dev, struct cryptkop *krp, int hint);
+} device_method_t;
+#define DEVMETHOD(id, func)	id: func
+
+struct ocf_device {
+	char name[32];		/* the driver name */
+	char nameunit[32];	/* the driver name + HW instance */
+	int  unit;
+	device_method_t	methods;
+	void *softc;
+};
+
+#define CRYPTODEV_NEWSESSION(dev, sid, cri) \
+	((*(dev)->methods.cryptodev_newsession)(dev,sid,cri))
+#define CRYPTODEV_FREESESSION(dev, sid) \
+	((*(dev)->methods.cryptodev_freesession)(dev, sid))
+#define CRYPTODEV_PROCESS(dev, crp, hint) \
+	((*(dev)->methods.cryptodev_process)(dev, crp, hint))
+#define CRYPTODEV_KPROCESS(dev, krp, hint) \
+	((*(dev)->methods.cryptodev_kprocess)(dev, krp, hint))
+
+#define device_get_name(dev)	((dev)->name)
+#define device_get_nameunit(dev)	((dev)->nameunit)
+#define device_get_unit(dev)	((dev)->unit)
+#define device_get_softc(dev)	((dev)->softc)
+
+#define	softc_device_decl \
+		struct ocf_device _device; \
+		device_t
+
+#define	softc_device_init(_sc, _name, _unit, _methods) \
+	if (1) {\
+	strncpy((_sc)->_device.name, _name, sizeof((_sc)->_device.name) - 1); \
+	snprintf((_sc)->_device.nameunit, sizeof((_sc)->_device.name), "%s%d", _name, _unit); \
+	(_sc)->_device.unit = _unit; \
+	(_sc)->_device.methods = _methods; \
+	(_sc)->_device.softc = (void *) _sc; \
+	*(device_t *)((softc_get_device(_sc))+1) = &(_sc)->_device; \
+	} else
+
+#define	softc_get_device(_sc)	(&(_sc)->_device)
+
+/*
+ * iomem support for 2.4 and 2.6 kernels
+ */
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#define ocf_iomem_t	unsigned long
+
+/*
+ * implement simple workqueue like support for older kernels
+ */
+
+#include <linux/tqueue.h>
+
+#define work_struct tq_struct
+
+#define INIT_WORK(wp, fp, ap) \
+	do { \
+		(wp)->sync = 0; \
+		(wp)->routine = (fp); \
+		(wp)->data = (ap); \
+	} while (0)
+
+#define schedule_work(wp) \
+	do { \
+		queue_task((wp), &tq_immediate); \
+		mark_bh(IMMEDIATE_BH); \
+	} while (0)
+
+#define flush_scheduled_work()	run_task_queue(&tq_immediate)
+
+#else
+#define ocf_iomem_t	void __iomem *
+
+#include <linux/workqueue.h>
+
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include <linux/fdtable.h>
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+#define files_fdtable(files)	(files)
+#endif
+
+#ifdef MODULE_PARM
+#undef module_param	/* just in case */
+#define	module_param(a,b,c)		MODULE_PARM(a,"i")
+#endif
+
+#define bzero(s,l)		memset(s,0,l)
+#define bcopy(s,d,l)	memcpy(d,s,l)
+#define bcmp(x, y, l)	memcmp(x,y,l)
+
+#define MIN(x,y)	((x) < (y) ? (x) : (y))
+
+#define device_printf(dev, a...) ({ \
+				printk("%s: ", device_get_nameunit(dev)); printk(a); \
+			})
+
+#undef printf
+#define printf(fmt...)	printk(fmt)
+
+#define KASSERT(c,p)	if (!(c)) { printk p ; } else
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#define ocf_daemonize(str) \
+	daemonize(); \
+	spin_lock_irq(&current->sigmask_lock); \
+	sigemptyset(&current->blocked); \
+	recalc_sigpending(current); \
+	spin_unlock_irq(&current->sigmask_lock); \
+	sprintf(current->comm, str);
+#else
+#define ocf_daemonize(str) daemonize(str);
+#endif
+
+#define	TAILQ_INSERT_TAIL(q,d,m) list_add_tail(&(d)->m, (q))
+#define	TAILQ_EMPTY(q)	list_empty(q)
+#define	TAILQ_FOREACH(v, q, m) list_for_each_entry(v, q, m)
+
+#define read_random(p,l) get_random_bytes(p,l)
+
+#define DELAY(x)	((x) > 2000 ? mdelay((x)/1000) : udelay(x))
+#define strtoul simple_strtoul
+
+#define pci_get_vendor(dev)	((dev)->vendor)
+#define pci_get_device(dev)	((dev)->device)
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#define pci_set_consistent_dma_mask(dev, mask) (0)
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+#define pci_dma_sync_single_for_cpu pci_dma_sync_single
+#endif
+
+#ifndef DMA_32BIT_MASK
+#define DMA_32BIT_MASK  0x00000000ffffffffULL
+#endif
+
+#define htole32(x)	cpu_to_le32(x)
+#define htobe32(x)	cpu_to_be32(x)
+#define htole16(x)	cpu_to_le16(x)
+#define htobe16(x)	cpu_to_be16(x)
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+# define strlcpy(dest,src,len) \
+		({strncpy(dest,src,(len)-1); ((char *)dest)[(len)-1] = '\0'; })
+#endif
+
+#ifndef MAX_ERRNO
+#define MAX_ERRNO	4095
+#endif
+#ifndef IS_ERR_VALUE
+#define IS_ERR_VALUE(x) ((unsigned long)(x) >= (unsigned long)-MAX_ERRNO)
+#endif
+
+/*
+ * common debug for all
+ */
+#if 1
+#define dprintk(a...)	do { if (debug) printk(a); } while(0)
+#else
+#define dprintk(a...)
+#endif
+
+#ifndef SLAB_ATOMIC
+/* Changed in 2.6.20, must use GFP_ATOMIC now */
+#define	SLAB_ATOMIC	GFP_ATOMIC
+#endif
+
+/*
+ * need some additional support for older kernels */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,2)
+#define pci_register_driver_compat(driver, rc) \
+	do { \
+		if ((rc) > 0) { \
+			(rc) = 0; \
+		} else if (rc == 0) { \
+			(rc) = -ENODEV; \
+		} else { \
+			pci_unregister_driver(driver); \
+		} \
+	} while (0)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+#define pci_register_driver_compat(driver,rc) ((rc) = (rc) < 0 ? (rc) : 0)
+#else
+#define pci_register_driver_compat(driver,rc)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+
+#include <asm/scatterlist.h>
+
+static inline void sg_set_page(struct scatterlist *sg,  struct page *page,
+			       unsigned int len, unsigned int offset)
+{
+	sg->page = page;
+	sg->offset = offset;
+	sg->length = len;
+}
+
+static inline void *sg_virt(struct scatterlist *sg)
+{
+	return page_address(sg->page) + sg->offset;
+}
+
+#endif
+
+#endif /* __KERNEL__ */
+
+/****************************************************************************/
+#endif /* _BSD_COMPAT_H_ */
diff --git a/crypto/ocf/ocfnull/Makefile b/crypto/ocf/ocfnull/Makefile
new file mode 100755
index 0000000..044bcac
--- /dev/null
+++ b/crypto/ocf/ocfnull/Makefile
@@ -0,0 +1,12 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+obj-$(CONFIG_OCF_OCFNULL) += ocfnull.o
+
+obj ?= .
+EXTRA_CFLAGS += -I$(obj)/..
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/crypto/ocf/ocfnull/ocfnull.c b/crypto/ocf/ocfnull/ocfnull.c
new file mode 100755
index 0000000..b4ad84c
--- /dev/null
+++ b/crypto/ocf/ocfnull/ocfnull.c
@@ -0,0 +1,203 @@
+/*
+ * An OCF module for determining the cost of crypto versus the cost of
+ * IPSec processing outside of OCF.  This modules gives us the effect of
+ * zero cost encryption,  of course you will need to run it at both ends
+ * since it does no crypto at all.
+ *
+ * Written by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough 
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/crypto.h>
+#include <linux/interrupt.h>
+
+#include <cryptodev.h>
+#include <uio.h>
+
+static int32_t			 null_id = -1;
+static u_int32_t		 null_sesnum = 0;
+
+static int null_process(device_t, struct cryptop *, int);
+static int null_newsession(device_t, u_int32_t *, struct cryptoini *);
+static int null_freesession(device_t, u_int64_t);
+
+#define debug ocfnull_debug
+int ocfnull_debug = 0;
+module_param(ocfnull_debug, int, 0644);
+MODULE_PARM_DESC(ocfnull_debug, "Enable debug");
+
+/*
+ * dummy device structure
+ */
+
+static struct {
+	softc_device_decl	sc_dev;
+} nulldev;
+
+static device_method_t null_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,	null_newsession),
+	DEVMETHOD(cryptodev_freesession,null_freesession),
+	DEVMETHOD(cryptodev_process,	null_process),
+};
+
+/*
+ * Generate a new software session.
+ */
+static int
+null_newsession(device_t arg, u_int32_t *sid, struct cryptoini *cri)
+{
+	dprintk("%s()\n", __FUNCTION__);
+	if (sid == NULL || cri == NULL) {
+		dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	if (null_sesnum == 0)
+		null_sesnum++;
+	*sid = null_sesnum++;
+	return 0;
+}
+
+
+/*
+ * Free a session.
+ */
+static int
+null_freesession(device_t arg, u_int64_t tid)
+{
+	u_int32_t sid = CRYPTO_SESID2LID(tid);
+
+	dprintk("%s()\n", __FUNCTION__);
+	if (sid > null_sesnum) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	/* Silently accept and return */
+	if (sid == 0)
+		return 0;
+	return 0;
+}
+
+
+/*
+ * Process a request.
+ */
+static int
+null_process(device_t arg, struct cryptop *crp, int hint)
+{
+	unsigned int lid;
+
+	dprintk("%s()\n", __FUNCTION__);
+
+	/* Sanity check */
+	if (crp == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+
+	crp->crp_etype = 0;
+
+	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
+		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+		crp->crp_etype = EINVAL;
+		goto done;
+	}
+
+	/*
+	 * find the session we are using
+	 */
+
+	lid = crp->crp_sid & 0xffffffff;
+	if (lid >= null_sesnum || lid == 0) {
+		crp->crp_etype = ENOENT;
+		dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
+		goto done;
+	}
+
+done:
+	crypto_done(crp);
+	return 0;
+}
+
+
+/*
+ * our driver startup and shutdown routines
+ */
+
+static int
+null_init(void)
+{
+	dprintk("%s(%p)\n", __FUNCTION__, null_init);
+
+	memset(&nulldev, 0, sizeof(nulldev));
+	softc_device_init(&nulldev, "ocfnull", 0, null_methods);
+
+	null_id = crypto_get_driverid(softc_get_device(&nulldev),
+				CRYPTOCAP_F_HARDWARE);
+	if (null_id < 0)
+		panic("ocfnull: crypto device cannot initialize!");
+
+#define	REGISTER(alg) \
+	crypto_register(null_id,alg,0,0)
+	REGISTER(CRYPTO_DES_CBC);
+	REGISTER(CRYPTO_3DES_CBC);
+	REGISTER(CRYPTO_RIJNDAEL128_CBC);
+	REGISTER(CRYPTO_MD5);
+	REGISTER(CRYPTO_SHA1);
+	REGISTER(CRYPTO_MD5_HMAC);
+	REGISTER(CRYPTO_SHA1_HMAC);
+#undef REGISTER
+
+	return 0;
+}
+
+static void
+null_exit(void)
+{
+	dprintk("%s()\n", __FUNCTION__);
+	crypto_unregister_all(null_id);
+	null_id = -1;
+}
+
+module_init(null_init);
+module_exit(null_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_DESCRIPTION("ocfnull - claims a lot but does nothing");
diff --git a/crypto/ocf/pasemi/Makefile b/crypto/ocf/pasemi/Makefile
new file mode 100755
index 0000000..b0a3980
--- /dev/null
+++ b/crypto/ocf/pasemi/Makefile
@@ -0,0 +1,12 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+obj-$(CONFIG_OCF_PASEMI) += pasemi.o
+
+obj ?= .
+EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/crypto/ocf/pasemi/pasemi.c b/crypto/ocf/pasemi/pasemi.c
new file mode 100755
index 0000000..c3bb931
--- /dev/null
+++ b/crypto/ocf/pasemi/pasemi.c
@@ -0,0 +1,1009 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Driver for the PA Semi PWRficient DMA Crypto Engine
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <asm/scatterlist.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <cryptodev.h>
+#include <uio.h>
+#include "pasemi_fnu.h"
+
+#define DRV_NAME "pasemi"
+
+#define TIMER_INTERVAL 1000
+
+static void __devexit pasemi_dma_remove(struct pci_dev *pdev);
+static struct pasdma_status volatile * dma_status;
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable debug");
+
+static void pasemi_desc_start(struct pasemi_desc *desc, u64 hdr)
+{
+	desc->postop = 0;
+	desc->quad[0] = hdr;
+	desc->quad_cnt = 1;
+	desc->size = 1;
+}
+
+static void pasemi_desc_build(struct pasemi_desc *desc, u64 val)
+{
+	desc->quad[desc->quad_cnt++] = val;
+	desc->size = (desc->quad_cnt + 1) / 2;
+}
+
+static void pasemi_desc_hdr(struct pasemi_desc *desc, u64 hdr)
+{
+	desc->quad[0] |= hdr;
+}
+
+static int pasemi_desc_size(struct pasemi_desc *desc)
+{
+	return desc->size;
+}
+
+static void pasemi_ring_add_desc(
+				 struct pasemi_fnu_txring *ring,
+				 struct pasemi_desc *desc,
+				 struct cryptop *crp) {
+	int i;
+	int ring_index = 2 * (ring->next_to_fill & (TX_RING_SIZE-1));
+
+	TX_DESC_INFO(ring, ring->next_to_fill).desc_size = desc->size;
+	TX_DESC_INFO(ring, ring->next_to_fill).desc_postop = desc->postop;
+	TX_DESC_INFO(ring, ring->next_to_fill).cf_crp = crp;
+
+	for (i = 0; i < desc->quad_cnt; i += 2) {
+		ring_index = 2 * (ring->next_to_fill & (TX_RING_SIZE-1));
+		ring->desc[ring_index] = desc->quad[i];
+		ring->desc[ring_index + 1] = desc->quad[i + 1];
+		ring->next_to_fill++;
+	}
+
+	if (desc->quad_cnt & 1)
+		ring->desc[ring_index + 1] = 0;
+}
+
+static void pasemi_ring_incr(struct pasemi_softc *sc, int chan_index, int incr)
+{
+	out_le32(sc->dma_regs + PAS_DMA_TXCHAN_INCR(sc->base_chan + chan_index),
+		 incr);
+}
+
+/*
+ * Generate a new software session.
+ */
+static int
+pasemi_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
+{
+	struct cryptoini *c, *encini = NULL, *macini = NULL;
+	struct pasemi_softc *sc = device_get_softc(dev);
+	struct pasemi_session *ses = NULL, **sespp;
+	int sesn, blksz = 0;
+	u64 ccmd = 0;
+	unsigned long flags;
+	struct pasemi_desc init_desc;
+	struct pasemi_fnu_txring *txring;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+	if (sidp == NULL || cri == NULL || sc == NULL) {
+		DPRINTF("%s,%d - EINVAL\n", __FILE__, __LINE__);
+		return -EINVAL;
+	}
+	for (c = cri; c != NULL; c = c->cri_next) {
+		if (ALG_IS_SIG(c->cri_alg)) {
+			if (macini)
+				return -EINVAL;
+			macini = c;
+		} else if (ALG_IS_CIPHER(c->cri_alg)) {
+			if (encini)
+				return -EINVAL;
+			encini = c;
+		} else {
+			DPRINTF("UNKNOWN c->cri_alg %d\n", c->cri_alg);
+			return -EINVAL;
+		}
+	}
+	if (encini == NULL && macini == NULL)
+		return -EINVAL;
+	if (encini) {
+		/* validate key length */
+		switch (encini->cri_alg) {
+		case CRYPTO_DES_CBC:
+			if (encini->cri_klen != 64)
+				return -EINVAL;
+			ccmd = DMA_CALGO_DES;
+			break;
+		case CRYPTO_3DES_CBC:
+			if (encini->cri_klen != 192)
+				return -EINVAL;
+			ccmd = DMA_CALGO_3DES;
+			break;
+		case CRYPTO_AES_CBC:
+			if (encini->cri_klen != 128 &&
+			    encini->cri_klen != 192 &&
+			    encini->cri_klen != 256)
+				return -EINVAL;
+			ccmd = DMA_CALGO_AES;
+			break;
+		case CRYPTO_ARC4:
+			if (encini->cri_klen != 128)
+				return -EINVAL;
+			ccmd = DMA_CALGO_ARC;
+			break;
+		default:
+			DPRINTF("UNKNOWN encini->cri_alg %d\n",
+				encini->cri_alg);
+			return -EINVAL;
+		}
+	}
+
+	if (macini) {
+		switch (macini->cri_alg) {
+		case CRYPTO_MD5:
+		case CRYPTO_MD5_HMAC:
+			blksz = 16;
+			break;
+		case CRYPTO_SHA1:
+		case CRYPTO_SHA1_HMAC:
+			blksz = 20;
+			break;
+		default:
+			DPRINTF("UNKNOWN macini->cri_alg %d\n",
+				macini->cri_alg);
+			return -EINVAL;
+		}
+		if (((macini->cri_klen + 7) / 8) > blksz) {
+			DPRINTF("key length %d bigger than blksize %d not supported\n",
+				((macini->cri_klen + 7) / 8), blksz);
+			return -EINVAL;
+		}
+	}
+
+	for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
+		if (sc->sc_sessions[sesn] == NULL) {
+			sc->sc_sessions[sesn] = (struct pasemi_session *)
+				kzalloc(sizeof(struct pasemi_session), GFP_ATOMIC);
+			ses = sc->sc_sessions[sesn];
+			break;
+		} else if (sc->sc_sessions[sesn]->used == 0) {
+			ses = sc->sc_sessions[sesn];
+			break;
+		}
+	}
+
+	if (ses == NULL) {
+		sespp = (struct pasemi_session **)
+			kzalloc(sc->sc_nsessions * 2 *
+				sizeof(struct pasemi_session *), GFP_ATOMIC);
+		if (sespp == NULL)
+			return -ENOMEM;
+		memcpy(sespp, sc->sc_sessions,
+		       sc->sc_nsessions * sizeof(struct pasemi_session *));
+		kfree(sc->sc_sessions);
+		sc->sc_sessions = sespp;
+		sesn = sc->sc_nsessions;
+		ses = sc->sc_sessions[sesn] = (struct pasemi_session *)
+			kzalloc(sizeof(struct pasemi_session), GFP_ATOMIC);
+		if (ses == NULL)
+			return -ENOMEM;
+		sc->sc_nsessions *= 2;
+	}
+
+	ses->used = 1;
+
+	ses->dma_addr = pci_map_single(sc->dma_pdev, (void *) ses->civ,
+				       sizeof(struct pasemi_session), DMA_TO_DEVICE);
+
+	/* enter the channel scheduler */
+	spin_lock_irqsave(&sc->sc_chnlock, flags);
+
+	/* ARC4 has to be processed by the even channel */
+	if (encini && (encini->cri_alg == CRYPTO_ARC4))
+		ses->chan = sc->sc_lastchn & ~1;
+	else
+		ses->chan = sc->sc_lastchn;
+	sc->sc_lastchn = (sc->sc_lastchn + 1) % sc->sc_num_channels;
+
+	spin_unlock_irqrestore(&sc->sc_chnlock, flags);
+
+	txring = &sc->tx[ses->chan];
+
+	if (encini) {
+		ses->ccmd = ccmd;
+
+		/* get an IV */
+		/* XXX may read fewer than requested */
+		get_random_bytes(ses->civ, sizeof(ses->civ));
+
+		ses->keysz = (encini->cri_klen - 63) / 64;
+		memcpy(ses->key, encini->cri_key, (ses->keysz + 1) * 8);
+
+		pasemi_desc_start(&init_desc,
+				  XCT_CTRL_HDR(ses->chan, (encini && macini) ? 0x68 : 0x40, DMA_FN_CIV0));
+		pasemi_desc_build(&init_desc,
+				  XCT_FUN_SRC_PTR((encini && macini) ? 0x68 : 0x40, ses->dma_addr));
+	}
+	if (macini) {
+		if (macini->cri_alg == CRYPTO_MD5_HMAC ||
+		    macini->cri_alg == CRYPTO_SHA1_HMAC)
+			memcpy(ses->hkey, macini->cri_key, blksz);
+		else {
+			/* Load initialization constants(RFC 1321, 3174) */
+			ses->hiv[0] = 0x67452301efcdab89ULL;
+			ses->hiv[1] = 0x98badcfe10325476ULL;
+			ses->hiv[2] = 0xc3d2e1f000000000ULL;
+		}
+		ses->hseq = 0ULL;
+	}
+
+	spin_lock_irqsave(&txring->fill_lock, flags);
+
+	if (((txring->next_to_fill + pasemi_desc_size(&init_desc)) -
+	     txring->next_to_clean) > TX_RING_SIZE) {
+		spin_unlock_irqrestore(&txring->fill_lock, flags);
+		return ERESTART;
+	}
+
+	if (encini) {
+		pasemi_ring_add_desc(txring, &init_desc, NULL);
+		pasemi_ring_incr(sc, ses->chan,
+				 pasemi_desc_size(&init_desc));
+	}
+
+	txring->sesn = sesn;
+	spin_unlock_irqrestore(&txring->fill_lock, flags);
+
+	*sidp = PASEMI_SID(sesn);
+	return 0;
+}
+
+/*
+ * Deallocate a session.
+ */
+static int
+pasemi_freesession(device_t dev, u_int64_t tid)
+{
+	struct pasemi_softc *sc = device_get_softc(dev);
+	int session;
+	u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (sc == NULL)
+		return -EINVAL;
+	session = PASEMI_SESSION(sid);
+	if (session >= sc->sc_nsessions || !sc->sc_sessions[session])
+		return -EINVAL;
+
+	pci_unmap_single(sc->dma_pdev,
+			 sc->sc_sessions[session]->dma_addr,
+			 sizeof(struct pasemi_session), DMA_TO_DEVICE);
+	memset(sc->sc_sessions[session], 0,
+	       sizeof(struct pasemi_session));
+
+	return 0;
+}
+
+static int
+pasemi_process(device_t dev, struct cryptop *crp, int hint)
+{
+
+	int err = 0, ivsize, srclen = 0, reinit = 0, reinit_size = 0, chsel;
+	struct pasemi_softc *sc = device_get_softc(dev);
+	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
+	caddr_t ivp;
+	struct pasemi_desc init_desc, work_desc;
+	struct pasemi_session *ses;
+	struct sk_buff *skb;
+	struct uio *uiop;
+	unsigned long flags;
+	struct pasemi_fnu_txring *txring;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (crp == NULL || crp->crp_callback == NULL || sc == NULL)
+		return -EINVAL;
+
+	crp->crp_etype = 0;
+	if (PASEMI_SESSION(crp->crp_sid) >= sc->sc_nsessions)
+		return -EINVAL;
+
+	ses = sc->sc_sessions[PASEMI_SESSION(crp->crp_sid)];
+
+	crd1 = crp->crp_desc;
+	if (crd1 == NULL) {
+		err = -EINVAL;
+		goto errout;
+	}
+	crd2 = crd1->crd_next;
+
+	if (ALG_IS_SIG(crd1->crd_alg)) {
+		maccrd = crd1;
+		if (crd2 == NULL)
+			enccrd = NULL;
+		else if (ALG_IS_CIPHER(crd2->crd_alg) &&
+			 (crd2->crd_flags & CRD_F_ENCRYPT) == 0)
+			enccrd = crd2;
+		else
+			goto erralg;
+	} else if (ALG_IS_CIPHER(crd1->crd_alg)) {
+		enccrd = crd1;
+		if (crd2 == NULL)
+			maccrd = NULL;
+		else if (ALG_IS_SIG(crd2->crd_alg) &&
+			 (crd1->crd_flags & CRD_F_ENCRYPT))
+			maccrd = crd2;
+		else
+			goto erralg;
+	} else
+		goto erralg;
+
+	chsel = ses->chan;
+
+	txring = &sc->tx[chsel];
+
+	if (enccrd && !maccrd) {
+		if (enccrd->crd_alg == CRYPTO_ARC4)
+			reinit = 1;
+		reinit_size = 0x40;
+		srclen = crp->crp_ilen;
+
+		pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I
+				  | XCT_FUN_FUN(chsel));
+		if (enccrd->crd_flags & CRD_F_ENCRYPT)
+			pasemi_desc_hdr(&work_desc, XCT_FUN_CRM_ENC);
+		else
+			pasemi_desc_hdr(&work_desc, XCT_FUN_CRM_DEC);
+	} else if (enccrd && maccrd) {
+		if (enccrd->crd_alg == CRYPTO_ARC4)
+			reinit = 1;
+		reinit_size = 0x68;
+
+		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
+			/* Encrypt -> Authenticate */
+			pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_ENC_SIG
+					  | XCT_FUN_A | XCT_FUN_FUN(chsel));
+			srclen = maccrd->crd_skip + maccrd->crd_len;
+		} else {
+			/* Authenticate -> Decrypt */
+			pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_SIG_DEC
+					  | XCT_FUN_24BRES | XCT_FUN_FUN(chsel));
+			pasemi_desc_build(&work_desc, 0);
+			pasemi_desc_build(&work_desc, 0);
+			pasemi_desc_build(&work_desc, 0);
+			work_desc.postop = PASEMI_CHECK_SIG;
+			srclen = crp->crp_ilen;
+		}
+
+		pasemi_desc_hdr(&work_desc, XCT_FUN_SHL(maccrd->crd_skip / 4));
+		pasemi_desc_hdr(&work_desc, XCT_FUN_CHL(enccrd->crd_skip - maccrd->crd_skip));
+	} else if (!enccrd && maccrd) {
+		srclen = maccrd->crd_len;
+
+		pasemi_desc_start(&init_desc,
+				  XCT_CTRL_HDR(chsel, 0x58, DMA_FN_HKEY0));
+		pasemi_desc_build(&init_desc,
+				  XCT_FUN_SRC_PTR(0x58, ((struct pasemi_session *)ses->dma_addr)->hkey));
+
+		pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_SIG
+				  | XCT_FUN_A | XCT_FUN_FUN(chsel));
+	}
+
+	if (enccrd) {
+		switch (enccrd->crd_alg) {
+		case CRYPTO_3DES_CBC:
+			pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_3DES |
+					XCT_FUN_BCM_CBC);
+			ivsize = sizeof(u64);
+			break;
+		case CRYPTO_DES_CBC:
+			pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_DES |
+					XCT_FUN_BCM_CBC);
+			ivsize = sizeof(u64);
+			break;
+		case CRYPTO_AES_CBC:
+			pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_AES |
+					XCT_FUN_BCM_CBC);
+			ivsize = 2 * sizeof(u64);
+			break;
+		case CRYPTO_ARC4:
+			pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_ARC);
+			ivsize = 0;
+			break;
+		default:
+			printk(DRV_NAME ": unimplemented enccrd->crd_alg %d\n",
+			       enccrd->crd_alg);
+			err = -EINVAL;
+			goto errout;
+		}
+
+		ivp = (ivsize == sizeof(u64)) ? (caddr_t) &ses->civ[1] : (caddr_t) &ses->civ[0];
+		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
+			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+				memcpy(ivp, enccrd->crd_iv, ivsize);
+			/* If IV is not present in the buffer already, it has to be copied there */
+			if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0)
+				crypto_copyback(crp->crp_flags, crp->crp_buf,
+						enccrd->crd_inject, ivsize, ivp);
+		} else {
+			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+				/* IV is provided expicitly in descriptor */
+				memcpy(ivp, enccrd->crd_iv, ivsize);
+			else
+				/* IV is provided in the packet */
+				crypto_copydata(crp->crp_flags, crp->crp_buf,
+						enccrd->crd_inject, ivsize,
+						ivp);
+		}
+	}
+
+	if (maccrd) {
+		switch (maccrd->crd_alg) {
+		case CRYPTO_MD5:
+			pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_MD5 |
+					XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
+			break;
+		case CRYPTO_SHA1:
+			pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_SHA1 |
+					XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
+			break;
+		case CRYPTO_MD5_HMAC:
+			pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_HMAC_MD5 |
+					XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
+			break;
+		case CRYPTO_SHA1_HMAC:
+			pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_HMAC_SHA1 |
+					XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
+			break;
+		default:
+			printk(DRV_NAME ": unimplemented maccrd->crd_alg %d\n",
+			       maccrd->crd_alg);
+			err = -EINVAL;
+			goto errout;
+		}
+	}
+
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		/* using SKB buffers */
+		skb = (struct sk_buff *)crp->crp_buf;
+		if (skb_shinfo(skb)->nr_frags) {
+			printk(DRV_NAME ": skb frags unimplemented\n");
+			err = -EINVAL;
+			goto errout;
+		}
+		pasemi_desc_build(
+			&work_desc,
+			XCT_FUN_DST_PTR(skb->len, pci_map_single(
+						sc->dma_pdev, skb->data,
+						skb->len, DMA_TO_DEVICE)));
+		pasemi_desc_build(
+			&work_desc,
+			XCT_FUN_SRC_PTR(
+				srclen, pci_map_single(
+					sc->dma_pdev, skb->data,
+					srclen, DMA_TO_DEVICE)));
+		pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
+	} else if (crp->crp_flags & CRYPTO_F_IOV) {
+		/* using IOV buffers */
+		uiop = (struct uio *)crp->crp_buf;
+		if (uiop->uio_iovcnt > 1) {
+			printk(DRV_NAME ": iov frags unimplemented\n");
+			err = -EINVAL;
+			goto errout;
+		}
+
+		/* crp_olen is never set; always use crp_ilen */
+		pasemi_desc_build(
+			&work_desc,
+			XCT_FUN_DST_PTR(crp->crp_ilen, pci_map_single(
+						sc->dma_pdev,
+						uiop->uio_iov->iov_base,
+						crp->crp_ilen, DMA_TO_DEVICE)));
+		pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
+
+		pasemi_desc_build(
+			&work_desc,
+			XCT_FUN_SRC_PTR(srclen, pci_map_single(
+						sc->dma_pdev,
+						uiop->uio_iov->iov_base,
+						srclen, DMA_TO_DEVICE)));
+	} else {
+		/* using contig buffers */
+		pasemi_desc_build(
+			&work_desc,
+			XCT_FUN_DST_PTR(crp->crp_ilen, pci_map_single(
+						sc->dma_pdev,
+						crp->crp_buf,
+						crp->crp_ilen, DMA_TO_DEVICE)));
+		pasemi_desc_build(
+			&work_desc,
+			XCT_FUN_SRC_PTR(srclen, pci_map_single(
+						sc->dma_pdev,
+						crp->crp_buf, srclen,
+						DMA_TO_DEVICE)));
+		pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
+	}
+
+	spin_lock_irqsave(&txring->fill_lock, flags);
+
+	if (txring->sesn != PASEMI_SESSION(crp->crp_sid)) {
+		txring->sesn = PASEMI_SESSION(crp->crp_sid);
+		reinit = 1;
+	}
+
+	if (enccrd) {
+		pasemi_desc_start(&init_desc,
+				  XCT_CTRL_HDR(chsel, reinit ? reinit_size : 0x10, DMA_FN_CIV0));
+		pasemi_desc_build(&init_desc,
+				  XCT_FUN_SRC_PTR(reinit ? reinit_size : 0x10, ses->dma_addr));
+	}
+
+	if (((txring->next_to_fill + pasemi_desc_size(&init_desc) +
+	      pasemi_desc_size(&work_desc)) -
+	     txring->next_to_clean) > TX_RING_SIZE) {
+		spin_unlock_irqrestore(&txring->fill_lock, flags);
+		err = ERESTART;
+		goto errout;
+	}
+
+	pasemi_ring_add_desc(txring, &init_desc, NULL);
+	pasemi_ring_add_desc(txring, &work_desc, crp);
+
+	pasemi_ring_incr(sc, chsel,
+			 pasemi_desc_size(&init_desc) +
+			 pasemi_desc_size(&work_desc));
+
+	spin_unlock_irqrestore(&txring->fill_lock, flags);
+
+	mod_timer(&txring->crypto_timer, jiffies + TIMER_INTERVAL);
+
+	return 0;
+
+erralg:
+	printk(DRV_NAME ": unsupported algorithm or algorithm order alg1 %d alg2 %d\n",
+	       crd1->crd_alg, crd2->crd_alg);
+	err = -EINVAL;
+
+errout:
+	if (err != ERESTART) {
+		crp->crp_etype = err;
+		crypto_done(crp);
+	}
+	return err;
+}
+
+static int pasemi_clean_tx(struct pasemi_softc *sc, int chan)
+{
+	int i, j, ring_idx;
+	struct pasemi_fnu_txring *ring = &sc->tx[chan];
+	u16 delta_cnt;
+	int flags, loops = 10;
+	int desc_size;
+	struct cryptop *crp;
+
+	spin_lock_irqsave(&ring->clean_lock, flags);
+
+	while ((delta_cnt = (dma_status->tx_sta[sc->base_chan + chan]
+			     & PAS_STATUS_PCNT_M) - ring->total_pktcnt)
+	       && loops--) {
+
+		for (i = 0; i < delta_cnt; i++) {
+			desc_size = TX_DESC_INFO(ring, ring->next_to_clean).desc_size;
+			crp = TX_DESC_INFO(ring, ring->next_to_clean).cf_crp;
+			if (crp) {
+				ring_idx = 2 * (ring->next_to_clean & (TX_RING_SIZE-1));
+				if (TX_DESC_INFO(ring, ring->next_to_clean).desc_postop & PASEMI_CHECK_SIG) {
+					/* Need to make sure signature matched,
+					 * if not - return error */
+					if (!(ring->desc[ring_idx + 1] & (1ULL << 63)))
+						crp->crp_etype = -EINVAL;
+				}
+				crypto_done(TX_DESC_INFO(ring,
+							 ring->next_to_clean).cf_crp);
+				TX_DESC_INFO(ring, ring->next_to_clean).cf_crp = NULL;
+				pci_unmap_single(
+					sc->dma_pdev,
+					XCT_PTR_ADDR_LEN(ring->desc[ring_idx + 1]),
+					PCI_DMA_TODEVICE);
+
+				ring->desc[ring_idx] = ring->desc[ring_idx + 1] = 0;
+
+				ring->next_to_clean++;
+				for (j = 1; j < desc_size; j++) {
+					ring_idx = 2 *
+						(ring->next_to_clean &
+						 (TX_RING_SIZE-1));
+					pci_unmap_single(
+						sc->dma_pdev,
+						XCT_PTR_ADDR_LEN(ring->desc[ring_idx]),
+						PCI_DMA_TODEVICE);
+					if (ring->desc[ring_idx + 1])
+						pci_unmap_single(
+							sc->dma_pdev,
+							XCT_PTR_ADDR_LEN(
+								ring->desc[
+									ring_idx + 1]),
+							PCI_DMA_TODEVICE);
+					ring->desc[ring_idx] =
+						ring->desc[ring_idx + 1] = 0;
+					ring->next_to_clean++;
+				}
+			} else {
+				for (j = 0; j < desc_size; j++) {
+					ring_idx = 2 * (ring->next_to_clean & (TX_RING_SIZE-1));
+					ring->desc[ring_idx] =
+						ring->desc[ring_idx + 1] = 0;
+					ring->next_to_clean++;
+				}
+			}
+		}
+
+		ring->total_pktcnt += delta_cnt;
+	}
+	spin_unlock_irqrestore(&ring->clean_lock, flags);
+
+	return 0;
+}
+
+static void sweepup_tx(struct pasemi_softc *sc)
+{
+	int i;
+
+	for (i = 0; i < sc->sc_num_channels; i++)
+		pasemi_clean_tx(sc, i);
+}
+
+static irqreturn_t pasemi_intr(int irq, void *arg, struct pt_regs *regs)
+{
+	struct pasemi_softc *sc = arg;
+	unsigned int reg;
+	int chan = irq - sc->base_irq;
+	int chan_index = sc->base_chan + chan;
+	u64 stat = dma_status->tx_sta[chan_index];
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (!(stat & PAS_STATUS_CAUSE_M))
+		return IRQ_NONE;
+
+	pasemi_clean_tx(sc, chan);
+
+	stat = dma_status->tx_sta[chan_index];
+
+	reg = PAS_IOB_DMA_TXCH_RESET_PINTC |
+		PAS_IOB_DMA_TXCH_RESET_PCNT(sc->tx[chan].total_pktcnt);
+
+	if (stat & PAS_STATUS_SOFT)
+		reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
+
+	out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_RESET(chan_index), reg);
+
+
+	return IRQ_HANDLED;
+}
+
+static int pasemi_dma_setup_tx_resources(struct pasemi_softc *sc, int chan)
+{
+	u32 val;
+	int chan_index = chan + sc->base_chan;
+	int ret;
+	struct pasemi_fnu_txring *ring;
+
+	ring = &sc->tx[chan];
+
+	spin_lock_init(&ring->fill_lock);
+	spin_lock_init(&ring->clean_lock);
+
+	ring->desc_info = kzalloc(sizeof(struct pasemi_desc_info) *
+				  TX_RING_SIZE, GFP_KERNEL);
+	if (!ring->desc_info)
+		return -ENOMEM;
+
+	/* Allocate descriptors */
+	ring->desc = dma_alloc_coherent(&sc->dma_pdev->dev,
+					TX_RING_SIZE *
+					2 * sizeof(u64),
+					&ring->dma, GFP_KERNEL);
+	if (!ring->desc)
+		return -ENOMEM;
+
+	memset((void *) ring->desc, 0, TX_RING_SIZE * 2 * sizeof(u64));
+
+	out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_RESET(chan_index), 0x30);
+
+	ring->total_pktcnt = 0;
+
+	out_le32(sc->dma_regs + PAS_DMA_TXCHAN_BASEL(chan_index),
+		 PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
+
+	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32);
+	val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 2);
+
+	out_le32(sc->dma_regs + PAS_DMA_TXCHAN_BASEU(chan_index), val);
+
+	out_le32(sc->dma_regs + PAS_DMA_TXCHAN_CFG(chan_index),
+		 PAS_DMA_TXCHAN_CFG_TY_FUNC |
+		 PAS_DMA_TXCHAN_CFG_TATTR(chan) |
+		 PAS_DMA_TXCHAN_CFG_WT(2));
+
+	/* enable tx channel */
+	out_le32(sc->dma_regs +
+		 PAS_DMA_TXCHAN_TCMDSTA(chan_index),
+		 PAS_DMA_TXCHAN_TCMDSTA_EN);
+
+	out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_CFG(chan_index),
+		 PAS_IOB_DMA_TXCH_CFG_CNTTH(1000));
+
+	ring->next_to_fill = 0;
+	ring->next_to_clean = 0;
+
+	snprintf(ring->irq_name, sizeof(ring->irq_name),
+		 "%s%d", "crypto", chan);
+
+	ring->irq = irq_create_mapping(NULL, sc->base_irq + chan);
+	ret = request_irq(ring->irq, (irq_handler_t)
+			  pasemi_intr, IRQF_DISABLED, ring->irq_name, sc);
+	if (ret) {
+		printk(KERN_ERR DRV_NAME ": failed to hook irq %d ret %d\n",
+		       ring->irq, ret);
+		ring->irq = -1;
+		return ret;
+	}
+
+	setup_timer(&ring->crypto_timer, (void *) sweepup_tx, (unsigned long) sc);
+
+	return 0;
+}
+
+static device_method_t pasemi_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,		pasemi_newsession),
+	DEVMETHOD(cryptodev_freesession,	pasemi_freesession),
+	DEVMETHOD(cryptodev_process,		pasemi_process),
+};
+
+/* Set up the crypto device structure, private data,
+ * and anything else we need before we start */
+
+static int __devinit
+pasemi_dma_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct pasemi_softc *sc;
+	int ret, i;
+
+	DPRINTF(KERN_ERR "%s()\n", __FUNCTION__);
+
+	sc = kzalloc(sizeof(*sc), GFP_KERNEL);
+	if (!sc)
+		return -ENOMEM;
+
+	softc_device_init(sc, DRV_NAME, 1, pasemi_methods);
+
+	pci_set_drvdata(pdev, sc);
+
+	spin_lock_init(&sc->sc_chnlock);
+
+	sc->sc_sessions = (struct pasemi_session **)
+		kzalloc(PASEMI_INITIAL_SESSIONS *
+			sizeof(struct pasemi_session *), GFP_ATOMIC);
+	if (sc->sc_sessions == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	sc->sc_nsessions = PASEMI_INITIAL_SESSIONS;
+	sc->sc_lastchn = 0;
+	sc->base_irq = pdev->irq + 6;
+	sc->base_chan = 6;
+	sc->sc_cid = -1;
+	sc->dma_pdev = pdev;
+
+	sc->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
+	if (!sc->iob_pdev) {
+		dev_err(&pdev->dev, "Can't find I/O Bridge\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* This is hardcoded and ugly, but we have some firmware versions
+	 * who don't provide the register space in the device tree. Luckily
+	 * they are at well-known locations so we can just do the math here.
+	 */
+	sc->dma_regs =
+		ioremap(0xe0000000 + (sc->dma_pdev->devfn << 12), 0x2000);
+	sc->iob_regs =
+		ioremap(0xe0000000 + (sc->iob_pdev->devfn << 12), 0x2000);
+	if (!sc->dma_regs || !sc->iob_regs) {
+		dev_err(&pdev->dev, "Can't map registers\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	dma_status = __ioremap(0xfd800000, 0x1000, 0);
+	if (!dma_status) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "Can't map dmastatus space\n");
+		goto out;
+	}
+
+	sc->tx = (struct pasemi_fnu_txring *)
+		kzalloc(sizeof(struct pasemi_fnu_txring)
+			* 8, GFP_KERNEL);
+	if (!sc->tx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Initialize the h/w */
+	out_le32(sc->dma_regs + PAS_DMA_COM_CFG,
+		 (in_le32(sc->dma_regs + PAS_DMA_COM_CFG) |
+		  PAS_DMA_COM_CFG_FWF));
+	out_le32(sc->dma_regs + PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
+
+	for (i = 0; i < PASEMI_FNU_CHANNELS; i++) {
+		sc->sc_num_channels++;
+		ret = pasemi_dma_setup_tx_resources(sc, i);
+		if (ret)
+			goto out;
+	}
+
+	sc->sc_cid = crypto_get_driverid(softc_get_device(sc),
+					 CRYPTOCAP_F_HARDWARE);
+	if (sc->sc_cid < 0) {
+		printk(KERN_ERR DRV_NAME ": could not get crypto driver id\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	/* register algorithms with the framework */
+	printk(DRV_NAME ":");
+
+	crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
+	crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
+	crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
+	crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0);
+	crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
+	crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
+	crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
+	crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
+
+	return 0;
+
+out:
+	pasemi_dma_remove(pdev);
+	return ret;
+}
+
+#define MAX_RETRIES 5000
+
+static void pasemi_free_tx_resources(struct pasemi_softc *sc, int chan)
+{
+	struct pasemi_fnu_txring *ring = &sc->tx[chan];
+	int chan_index = chan + sc->base_chan;
+	int retries;
+	u32 stat;
+
+	/* Stop the channel */
+	out_le32(sc->dma_regs +
+		 PAS_DMA_TXCHAN_TCMDSTA(chan_index),
+		 PAS_DMA_TXCHAN_TCMDSTA_ST);
+
+	for (retries = 0; retries < MAX_RETRIES; retries++) {
+		stat = in_le32(sc->dma_regs +
+			       PAS_DMA_TXCHAN_TCMDSTA(chan_index));
+		if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
+			break;
+		cond_resched();
+	}
+
+	if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
+		dev_err(&sc->dma_pdev->dev, "Failed to stop tx channel %d\n",
+			chan_index);
+
+	/* Disable the channel */
+	out_le32(sc->dma_regs +
+		 PAS_DMA_TXCHAN_TCMDSTA(chan_index),
+		 0);
+
+	if (ring->desc_info)
+		kfree((void *) ring->desc_info);
+	if (ring->desc)
+		dma_free_coherent(&sc->dma_pdev->dev,
+				  TX_RING_SIZE *
+				  2 * sizeof(u64),
+				  (void *) ring->desc, ring->dma);
+	if (ring->irq != -1)
+		free_irq(ring->irq, sc);
+
+	del_timer(&ring->crypto_timer);
+}
+
+static void __devexit pasemi_dma_remove(struct pci_dev *pdev)
+{
+	struct pasemi_softc *sc = pci_get_drvdata(pdev);
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (sc->sc_cid >= 0) {
+		crypto_unregister_all(sc->sc_cid);
+	}
+
+	if (sc->tx) {
+		for (i = 0; i < sc->sc_num_channels; i++)
+			pasemi_free_tx_resources(sc, i);
+
+		kfree(sc->tx);
+	}
+	if (sc->sc_sessions) {
+		for (i = 0; i < sc->sc_nsessions; i++)
+			kfree(sc->sc_sessions[i]);
+		kfree(sc->sc_sessions);
+	}
+	if (sc->iob_pdev)
+		pci_dev_put(sc->iob_pdev);
+	if (sc->dma_regs)
+		iounmap(sc->dma_regs);
+	if (sc->iob_regs)
+		iounmap(sc->iob_regs);
+	kfree(sc);
+}
+
+static struct pci_device_id pasemi_dma_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa007) },
+};
+
+MODULE_DEVICE_TABLE(pci, pasemi_dma_pci_tbl);
+
+static struct pci_driver pasemi_dma_driver = {
+	.name		= "pasemi_dma",
+	.id_table	= pasemi_dma_pci_tbl,
+	.probe		= pasemi_dma_probe,
+	.remove		= __devexit_p(pasemi_dma_remove),
+};
+
+static void __exit pasemi_dma_cleanup_module(void)
+{
+	pci_unregister_driver(&pasemi_dma_driver);
+	__iounmap(dma_status);
+	dma_status = NULL;
+}
+
+int pasemi_dma_init_module(void)
+{
+	return pci_register_driver(&pasemi_dma_driver);
+}
+
+module_init(pasemi_dma_init_module);
+module_exit(pasemi_dma_cleanup_module);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Egor Martovetsky egor@pasemi.com");
+MODULE_DESCRIPTION("OCF driver for PA Semi PWRficient DMA Crypto Engine");
diff --git a/crypto/ocf/pasemi/pasemi_fnu.h b/crypto/ocf/pasemi/pasemi_fnu.h
new file mode 100755
index 0000000..1a0dcc8
--- /dev/null
+++ b/crypto/ocf/pasemi/pasemi_fnu.h
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Driver for the PA Semi PWRficient DMA Crypto Engine, soft state and
+ * hardware register layouts.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef PASEMI_FNU_H
+#define PASEMI_FNU_H
+
+#include <linux/spinlock.h>
+
+#define	PASEMI_SESSION(sid)	((sid) & 0xffffffff)
+#define	PASEMI_SID(sesn)	((sesn) & 0xffffffff)
+#define	DPRINTF(a...)	if (debug) { printk(DRV_NAME ": " a); }
+
+/* Must be a power of two */
+#define RX_RING_SIZE 512
+#define TX_RING_SIZE 512
+#define TX_DESC(ring, num)	((ring)->desc[2 * (num & (TX_RING_SIZE-1))])
+#define TX_DESC_INFO(ring, num)	((ring)->desc_info[(num) & (TX_RING_SIZE-1)])
+#define MAX_DESC_SIZE 8
+#define PASEMI_INITIAL_SESSIONS 10
+#define PASEMI_FNU_CHANNELS 8
+
+/* DMA descriptor */
+struct pasemi_desc {
+	u64 quad[2*MAX_DESC_SIZE];
+	int quad_cnt;
+	int size;
+	int postop;
+};
+
+/*
+ * Holds per descriptor data
+ */
+struct pasemi_desc_info {
+	int			desc_size;
+	int			desc_postop;
+#define PASEMI_CHECK_SIG 0x1
+
+	struct cryptop          *cf_crp;
+};
+
+/*
+ * Holds per channel data
+ */
+struct pasemi_fnu_txring {
+	volatile u64		*desc;
+	volatile struct
+	pasemi_desc_info	*desc_info;
+	dma_addr_t		dma;
+	struct timer_list       crypto_timer;
+	spinlock_t		fill_lock;
+	spinlock_t		clean_lock;
+	unsigned int		next_to_fill;
+	unsigned int		next_to_clean;
+	u16			total_pktcnt;
+	int			irq;
+	int			sesn;
+	char			irq_name[10];
+};
+
+/*
+ * Holds data specific to a single pasemi device.
+ */
+struct pasemi_softc {
+	softc_device_decl	sc_cdev;
+	struct pci_dev		*dma_pdev;	/* device backpointer */
+	struct pci_dev		*iob_pdev;	/* device backpointer */
+	void __iomem		*dma_regs;
+	void __iomem		*iob_regs;
+	int			base_irq;
+	int			base_chan;
+	int32_t			sc_cid;		/* crypto tag */
+	int			sc_nsessions;
+	struct pasemi_session	**sc_sessions;
+	int			sc_num_channels;/* number of crypto channels */
+
+	/* pointer to the array of txring datastructures, one txring per channel */
+	struct pasemi_fnu_txring *tx;
+
+	/*
+	 * mutual exclusion for the channel scheduler
+	 */
+	spinlock_t		sc_chnlock;
+	/* last channel used, for now use round-robin to allocate channels */
+	int			sc_lastchn;
+};
+
+struct pasemi_session {
+	u64 civ[2];
+	u64 keysz;
+	u64 key[4];
+	u64 ccmd;
+	u64 hkey[4];
+	u64 hseq;
+	u64 giv[2];
+	u64 hiv[4];
+
+	int used;
+	dma_addr_t	dma_addr;
+	int chan;
+};
+
+/* status register layout in IOB region, at 0xfd800000 */
+struct pasdma_status {
+	u64 rx_sta[64];
+	u64 tx_sta[20];
+};
+
+#define ALG_IS_CIPHER(alg) ((alg == CRYPTO_DES_CBC)		|| \
+				(alg == CRYPTO_3DES_CBC)	|| \
+				(alg == CRYPTO_AES_CBC)		|| \
+				(alg == CRYPTO_ARC4)		|| \
+				(alg == CRYPTO_NULL_CBC))
+
+#define ALG_IS_SIG(alg) ((alg == CRYPTO_MD5)			|| \
+				(alg == CRYPTO_MD5_HMAC)	|| \
+				(alg == CRYPTO_SHA1)		|| \
+				(alg == CRYPTO_SHA1_HMAC)	|| \
+				(alg == CRYPTO_NULL_HMAC))
+
+enum {
+	PAS_DMA_COM_TXCMD = 0x100,	/* Transmit Command Register  */
+	PAS_DMA_COM_TXSTA = 0x104,	/* Transmit Status Register   */
+	PAS_DMA_COM_RXCMD = 0x108,	/* Receive Command Register   */
+	PAS_DMA_COM_RXSTA = 0x10c,	/* Receive Status Register    */
+	PAS_DMA_COM_CFG   = 0x114,	/* DMA Configuration Register */
+};
+
+/* All these registers live in the PCI configuration space for the DMA PCI
+ * device. Use the normal PCI config access functions for them.
+ */
+
+#define PAS_DMA_COM_CFG_FWF	0x18000000
+
+#define PAS_DMA_COM_TXCMD_EN	0x00000001 /* enable */
+#define PAS_DMA_COM_TXSTA_ACT	0x00000001 /* active */
+#define PAS_DMA_COM_RXCMD_EN	0x00000001 /* enable */
+#define PAS_DMA_COM_RXSTA_ACT	0x00000001 /* active */
+
+#define _PAS_DMA_TXCHAN_STRIDE	0x20    /* Size per channel		*/
+#define _PAS_DMA_TXCHAN_TCMDSTA	0x300	/* Command / Status		*/
+#define _PAS_DMA_TXCHAN_CFG	0x304	/* Configuration		*/
+#define _PAS_DMA_TXCHAN_DSCRBU	0x308	/* Descriptor BU Allocation	*/
+#define _PAS_DMA_TXCHAN_INCR	0x310	/* Descriptor increment		*/
+#define _PAS_DMA_TXCHAN_CNT	0x314	/* Descriptor count/offset	*/
+#define _PAS_DMA_TXCHAN_BASEL	0x318	/* Descriptor ring base (low)	*/
+#define _PAS_DMA_TXCHAN_BASEU	0x31c	/*			(high)	*/
+#define PAS_DMA_TXCHAN_TCMDSTA(c) (0x300+(c)*_PAS_DMA_TXCHAN_STRIDE)
+#define    PAS_DMA_TXCHAN_TCMDSTA_EN	0x00000001	/* Enabled */
+#define    PAS_DMA_TXCHAN_TCMDSTA_ST	0x00000002	/* Stop interface */
+#define    PAS_DMA_TXCHAN_TCMDSTA_ACT	0x00010000	/* Active */
+#define PAS_DMA_TXCHAN_CFG(c)     (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
+#define    PAS_DMA_TXCHAN_CFG_TY_FUNC	0x00000002	/* Type = interface */
+#define    PAS_DMA_TXCHAN_CFG_TY_IFACE	0x00000000	/* Type = interface */
+#define    PAS_DMA_TXCHAN_CFG_TATTR_M	0x0000003c
+#define    PAS_DMA_TXCHAN_CFG_TATTR_S	2
+#define    PAS_DMA_TXCHAN_CFG_TATTR(x)	(((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
+					 PAS_DMA_TXCHAN_CFG_TATTR_M)
+#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000001c0
+#define    PAS_DMA_TXCHAN_CFG_WT_S	6
+#define    PAS_DMA_TXCHAN_CFG_WT(x)	(((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
+					 PAS_DMA_TXCHAN_CFG_WT_M)
+#define    PAS_DMA_TXCHAN_CFG_LPSQ_FAST	0x00000400
+#define    PAS_DMA_TXCHAN_CFG_LPDQ_FAST	0x00000800
+#define    PAS_DMA_TXCHAN_CFG_CF	0x00001000	/* Clean first line */
+#define    PAS_DMA_TXCHAN_CFG_CL	0x00002000	/* Clean last line */
+#define    PAS_DMA_TXCHAN_CFG_UP	0x00004000	/* update tx descr when sent */
+#define PAS_DMA_TXCHAN_INCR(c)    (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE)
+#define PAS_DMA_TXCHAN_BASEL(c)   (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE)
+#define    PAS_DMA_TXCHAN_BASEL_BRBL_M	0xffffffc0
+#define    PAS_DMA_TXCHAN_BASEL_BRBL_S	0
+#define    PAS_DMA_TXCHAN_BASEL_BRBL(x)	(((x) << PAS_DMA_TXCHAN_BASEL_BRBL_S) & \
+					 PAS_DMA_TXCHAN_BASEL_BRBL_M)
+#define PAS_DMA_TXCHAN_BASEU(c)   (0x31c+(c)*_PAS_DMA_TXCHAN_STRIDE)
+#define    PAS_DMA_TXCHAN_BASEU_BRBH_M	0x00000fff
+#define    PAS_DMA_TXCHAN_BASEU_BRBH_S	0
+#define    PAS_DMA_TXCHAN_BASEU_BRBH(x)	(((x) << PAS_DMA_TXCHAN_BASEU_BRBH_S) & \
+					 PAS_DMA_TXCHAN_BASEU_BRBH_M)
+/* # of cache lines worth of buffer ring */
+#define    PAS_DMA_TXCHAN_BASEU_SIZ_M	0x3fff0000
+#define    PAS_DMA_TXCHAN_BASEU_SIZ_S	16		/* 0 = 16K */
+#define    PAS_DMA_TXCHAN_BASEU_SIZ(x)	(((x) << PAS_DMA_TXCHAN_BASEU_SIZ_S) & \
+					 PAS_DMA_TXCHAN_BASEU_SIZ_M)
+
+#define    PAS_STATUS_PCNT_M		0x000000000000ffffull
+#define    PAS_STATUS_PCNT_S		0
+#define    PAS_STATUS_DCNT_M		0x00000000ffff0000ull
+#define    PAS_STATUS_DCNT_S		16
+#define    PAS_STATUS_BPCNT_M		0x0000ffff00000000ull
+#define    PAS_STATUS_BPCNT_S		32
+#define    PAS_STATUS_CAUSE_M		0xf000000000000000ull
+#define    PAS_STATUS_TIMER		0x1000000000000000ull
+#define    PAS_STATUS_ERROR		0x2000000000000000ull
+#define    PAS_STATUS_SOFT		0x4000000000000000ull
+#define    PAS_STATUS_INT		0x8000000000000000ull
+
+#define PAS_IOB_DMA_RXCH_CFG(i)		(0x1100 + (i)*4)
+#define    PAS_IOB_DMA_RXCH_CFG_CNTTH_M		0x00000fff
+#define    PAS_IOB_DMA_RXCH_CFG_CNTTH_S		0
+#define    PAS_IOB_DMA_RXCH_CFG_CNTTH(x)	(((x) << PAS_IOB_DMA_RXCH_CFG_CNTTH_S) & \
+						 PAS_IOB_DMA_RXCH_CFG_CNTTH_M)
+#define PAS_IOB_DMA_TXCH_CFG(i)		(0x1200 + (i)*4)
+#define    PAS_IOB_DMA_TXCH_CFG_CNTTH_M		0x00000fff
+#define    PAS_IOB_DMA_TXCH_CFG_CNTTH_S		0
+#define    PAS_IOB_DMA_TXCH_CFG_CNTTH(x)	(((x) << PAS_IOB_DMA_TXCH_CFG_CNTTH_S) & \
+						 PAS_IOB_DMA_TXCH_CFG_CNTTH_M)
+#define PAS_IOB_DMA_RXCH_STAT(i)	(0x1300 + (i)*4)
+#define    PAS_IOB_DMA_RXCH_STAT_INTGEN	0x00001000
+#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL_M	0x00000fff
+#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL_S	0
+#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL(x)	(((x) << PAS_IOB_DMA_RXCH_STAT_CNTDEL_S) &\
+						 PAS_IOB_DMA_RXCH_STAT_CNTDEL_M)
+#define PAS_IOB_DMA_TXCH_STAT(i)	(0x1400 + (i)*4)
+#define    PAS_IOB_DMA_TXCH_STAT_INTGEN	0x00001000
+#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL_M	0x00000fff
+#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL_S	0
+#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL(x)	(((x) << PAS_IOB_DMA_TXCH_STAT_CNTDEL_S) &\
+						 PAS_IOB_DMA_TXCH_STAT_CNTDEL_M)
+#define PAS_IOB_DMA_RXCH_RESET(i)	(0x1500 + (i)*4)
+#define    PAS_IOB_DMA_RXCH_RESET_PCNT_M	0xffff0000
+#define    PAS_IOB_DMA_RXCH_RESET_PCNT_S	16
+#define    PAS_IOB_DMA_RXCH_RESET_PCNT(x)	(((x) << PAS_IOB_DMA_RXCH_RESET_PCNT_S) & \
+						 PAS_IOB_DMA_RXCH_RESET_PCNT_M)
+#define    PAS_IOB_DMA_RXCH_RESET_PCNTRST	0x00000020
+#define    PAS_IOB_DMA_RXCH_RESET_DCNTRST	0x00000010
+#define    PAS_IOB_DMA_RXCH_RESET_TINTC		0x00000008
+#define    PAS_IOB_DMA_RXCH_RESET_DINTC		0x00000004
+#define    PAS_IOB_DMA_RXCH_RESET_SINTC		0x00000002
+#define    PAS_IOB_DMA_RXCH_RESET_PINTC		0x00000001
+#define PAS_IOB_DMA_TXCH_RESET(i)	(0x1600 + (i)*4)
+#define    PAS_IOB_DMA_TXCH_RESET_PCNT_M	0xffff0000
+#define    PAS_IOB_DMA_TXCH_RESET_PCNT_S	16
+#define    PAS_IOB_DMA_TXCH_RESET_PCNT(x)	(((x) << PAS_IOB_DMA_TXCH_RESET_PCNT_S) & \
+						 PAS_IOB_DMA_TXCH_RESET_PCNT_M)
+#define    PAS_IOB_DMA_TXCH_RESET_PCNTRST	0x00000020
+#define    PAS_IOB_DMA_TXCH_RESET_DCNTRST	0x00000010
+#define    PAS_IOB_DMA_TXCH_RESET_TINTC		0x00000008
+#define    PAS_IOB_DMA_TXCH_RESET_DINTC		0x00000004
+#define    PAS_IOB_DMA_TXCH_RESET_SINTC		0x00000002
+#define    PAS_IOB_DMA_TXCH_RESET_PINTC		0x00000001
+
+#define PAS_IOB_DMA_COM_TIMEOUTCFG		0x1700
+#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M	0x00ffffff
+#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S	0
+#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(x)	(((x) << PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S) & \
+						 PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M)
+
+/* Transmit descriptor fields */
+#define	XCT_MACTX_T		0x8000000000000000ull
+#define	XCT_MACTX_ST		0x4000000000000000ull
+#define XCT_MACTX_NORES		0x0000000000000000ull
+#define XCT_MACTX_8BRES		0x1000000000000000ull
+#define XCT_MACTX_24BRES	0x2000000000000000ull
+#define XCT_MACTX_40BRES	0x3000000000000000ull
+#define XCT_MACTX_I		0x0800000000000000ull
+#define XCT_MACTX_O		0x0400000000000000ull
+#define XCT_MACTX_E		0x0200000000000000ull
+#define XCT_MACTX_VLAN_M	0x0180000000000000ull
+#define XCT_MACTX_VLAN_NOP	0x0000000000000000ull
+#define XCT_MACTX_VLAN_REMOVE	0x0080000000000000ull
+#define XCT_MACTX_VLAN_INSERT   0x0100000000000000ull
+#define XCT_MACTX_VLAN_REPLACE  0x0180000000000000ull
+#define XCT_MACTX_CRC_M		0x0060000000000000ull
+#define XCT_MACTX_CRC_NOP	0x0000000000000000ull
+#define XCT_MACTX_CRC_INSERT	0x0020000000000000ull
+#define XCT_MACTX_CRC_PAD	0x0040000000000000ull
+#define XCT_MACTX_CRC_REPLACE	0x0060000000000000ull
+#define XCT_MACTX_SS		0x0010000000000000ull
+#define XCT_MACTX_LLEN_M	0x00007fff00000000ull
+#define XCT_MACTX_LLEN_S	32ull
+#define XCT_MACTX_LLEN(x)	((((long)(x)) << XCT_MACTX_LLEN_S) & \
+				 XCT_MACTX_LLEN_M)
+#define XCT_MACTX_IPH_M		0x00000000f8000000ull
+#define XCT_MACTX_IPH_S		27ull
+#define XCT_MACTX_IPH(x)	((((long)(x)) << XCT_MACTX_IPH_S) & \
+				 XCT_MACTX_IPH_M)
+#define XCT_MACTX_IPO_M		0x0000000007c00000ull
+#define XCT_MACTX_IPO_S		22ull
+#define XCT_MACTX_IPO(x)	((((long)(x)) << XCT_MACTX_IPO_S) & \
+				 XCT_MACTX_IPO_M)
+#define XCT_MACTX_CSUM_M	0x0000000000000060ull
+#define XCT_MACTX_CSUM_NOP	0x0000000000000000ull
+#define XCT_MACTX_CSUM_TCP	0x0000000000000040ull
+#define XCT_MACTX_CSUM_UDP	0x0000000000000060ull
+#define XCT_MACTX_V6		0x0000000000000010ull
+#define XCT_MACTX_C		0x0000000000000004ull
+#define XCT_MACTX_AL2		0x0000000000000002ull
+
+#define XCT_PTR_T		0x8000000000000000ull
+#define XCT_PTR_LEN_M		0x7ffff00000000000ull
+#define XCT_PTR_LEN_S		44
+#define XCT_PTR_LEN(x)		((((long)(x)) << XCT_PTR_LEN_S) & \
+				 XCT_PTR_LEN_M)
+#define XCT_PTR_ADDR_M		0x00000fffffffffffull
+#define XCT_PTR_ADDR_S		0
+#define XCT_PTR_ADDR(x)		((((long)(x)) << XCT_PTR_ADDR_S) & \
+				 XCT_PTR_ADDR_M)
+
+/* Function descriptor fields */
+#define	XCT_FUN_T		0x8000000000000000ull
+#define	XCT_FUN_ST		0x4000000000000000ull
+#define XCT_FUN_NORES		0x0000000000000000ull
+#define XCT_FUN_8BRES		0x1000000000000000ull
+#define XCT_FUN_24BRES		0x2000000000000000ull
+#define XCT_FUN_40BRES		0x3000000000000000ull
+#define XCT_FUN_I		0x0800000000000000ull
+#define XCT_FUN_O		0x0400000000000000ull
+#define XCT_FUN_E		0x0200000000000000ull
+#define XCT_FUN_FUN_S		54
+#define XCT_FUN_FUN_M		0x01c0000000000000ull
+#define XCT_FUN_FUN(num)	((((long)(num)) << XCT_FUN_FUN_S) & \
+				XCT_FUN_FUN_M)
+#define XCT_FUN_CRM_NOP		0x0000000000000000ull
+#define XCT_FUN_CRM_SIG		0x0008000000000000ull
+#define XCT_FUN_CRM_ENC		0x0010000000000000ull
+#define XCT_FUN_CRM_DEC		0x0018000000000000ull
+#define XCT_FUN_CRM_SIG_ENC	0x0020000000000000ull
+#define XCT_FUN_CRM_ENC_SIG	0x0028000000000000ull
+#define XCT_FUN_CRM_SIG_DEC	0x0030000000000000ull
+#define XCT_FUN_CRM_DEC_SIG	0x0038000000000000ull
+#define XCT_FUN_LLEN_M		0x0007ffff00000000ull
+#define XCT_FUN_LLEN_S		32ULL
+#define XCT_FUN_LLEN(x)		((((long)(x)) << XCT_FUN_LLEN_S) & \
+				 XCT_FUN_LLEN_M)
+#define XCT_FUN_SHL_M		0x00000000f8000000ull
+#define XCT_FUN_SHL_S		27ull
+#define XCT_FUN_SHL(x)		((((long)(x)) << XCT_FUN_SHL_S) & \
+				 XCT_FUN_SHL_M)
+#define XCT_FUN_CHL_M		0x0000000007c00000ull
+#define XCT_FUN_CHL_S		22ull
+#define XCT_FUN_CHL(x)		((((long)(x)) << XCT_FUN_CHL_S) & \
+				 XCT_FUN_CHL_M)
+#define XCT_FUN_HSZ_M		0x00000000003c0000ull
+#define XCT_FUN_HSZ_S		18ull
+#define XCT_FUN_HSZ(x)		((((long)(x)) << XCT_FUN_HSZ_S) & \
+				 XCT_FUN_HSZ_M)
+#define XCT_FUN_ALG_DES		0x0000000000000000ull
+#define XCT_FUN_ALG_3DES	0x0000000000008000ull
+#define XCT_FUN_ALG_AES		0x0000000000010000ull
+#define XCT_FUN_ALG_ARC		0x0000000000018000ull
+#define XCT_FUN_ALG_KASUMI	0x0000000000020000ull
+#define XCT_FUN_BCM_ECB		0x0000000000000000ull
+#define XCT_FUN_BCM_CBC		0x0000000000001000ull
+#define XCT_FUN_BCM_CFB		0x0000000000002000ull
+#define XCT_FUN_BCM_OFB		0x0000000000003000ull
+#define XCT_FUN_BCM_CNT		0x0000000000003800ull
+#define XCT_FUN_BCM_KAS_F8	0x0000000000002800ull
+#define XCT_FUN_BCM_KAS_F9	0x0000000000001800ull
+#define XCT_FUN_BCP_NO_PAD	0x0000000000000000ull
+#define XCT_FUN_BCP_ZRO		0x0000000000000200ull
+#define XCT_FUN_BCP_PL		0x0000000000000400ull
+#define XCT_FUN_BCP_INCR	0x0000000000000600ull
+#define XCT_FUN_SIG_MD5		(0ull << 4)
+#define XCT_FUN_SIG_SHA1	(2ull << 4)
+#define XCT_FUN_SIG_HMAC_MD5	(8ull << 4)
+#define XCT_FUN_SIG_HMAC_SHA1	(10ull << 4)
+#define XCT_FUN_A		0x0000000000000008ull
+#define XCT_FUN_C		0x0000000000000004ull
+#define XCT_FUN_AL2		0x0000000000000002ull
+#define XCT_FUN_SE		0x0000000000000001ull
+
+#define XCT_FUN_SRC_PTR(len, addr)	(XCT_PTR_LEN(len) | XCT_PTR_ADDR(addr))
+#define XCT_FUN_DST_PTR(len, addr)	(XCT_FUN_SRC_PTR(len, addr) | \
+					0x8000000000000000ull)
+
+#define XCT_CTRL_HDR_FUN_NUM_M		0x01c0000000000000ull
+#define XCT_CTRL_HDR_FUN_NUM_S		54
+#define XCT_CTRL_HDR_LEN_M		0x0007ffff00000000ull
+#define XCT_CTRL_HDR_LEN_S		32
+#define XCT_CTRL_HDR_REG_M		0x00000000000000ffull
+#define XCT_CTRL_HDR_REG_S		0
+
+#define XCT_CTRL_HDR(funcN,len,reg)	(0x9400000000000000ull | \
+			((((long)(funcN)) << XCT_CTRL_HDR_FUN_NUM_S) \
+			& XCT_CTRL_HDR_FUN_NUM_M) | \
+			((((long)(len)) << \
+			XCT_CTRL_HDR_LEN_S) & XCT_CTRL_HDR_LEN_M) | \
+			((((long)(reg)) << \
+			XCT_CTRL_HDR_REG_S) & XCT_CTRL_HDR_REG_M))
+
+/* Function config command options */
+#define	DMA_CALGO_DES			0x00
+#define	DMA_CALGO_3DES			0x01
+#define	DMA_CALGO_AES			0x02
+#define	DMA_CALGO_ARC			0x03
+
+#define DMA_FN_CIV0			0x02
+#define DMA_FN_CIV1			0x03
+#define DMA_FN_HKEY0			0x0a
+
+#define XCT_PTR_ADDR_LEN(ptr)		((ptr) & XCT_PTR_ADDR_M), \
+			(((ptr) & XCT_PTR_LEN_M) >> XCT_PTR_LEN_S)
+
+#endif /* PASEMI_FNU_H */
diff --git a/crypto/ocf/random.c b/crypto/ocf/random.c
new file mode 100755
index 0000000..118575a
--- /dev/null
+++ b/crypto/ocf/random.c
@@ -0,0 +1,317 @@
+/*
+ * A system independant way of adding entropy to the kernels pool
+ * this way the drivers can focus on the real work and we can take
+ * care of pushing it to the appropriate place in the kernel.
+ *
+ * This should be fast and callable from timers/interrupts
+ *
+ * Written by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/version.h>
+#include <linux/unistd.h>
+#include <linux/poll.h>
+#include <linux/random.h>
+#include <cryptodev.h>
+
+#ifdef CONFIG_OCF_FIPS
+#include "rndtest.h"
+#endif
+
+#ifndef HAS_RANDOM_INPUT_WAIT
+#error "Please do not enable OCF_RANDOMHARVEST unless you have applied patches"
+#endif
+
+/*
+ * a hack to access the debug levels from the crypto driver
+ */
+extern int crypto_debug;
+#define debug crypto_debug
+
+/*
+ * a list of all registered random providers
+ */
+static LIST_HEAD(random_ops);
+static int started = 0;
+static int initted = 0;
+
+struct random_op {
+	struct list_head random_list;
+	u_int32_t driverid;
+	int (*read_random)(void *arg, u_int32_t *buf, int len);
+	void *arg;
+};
+
+static int random_proc(void *arg);
+
+static pid_t		randomproc = (pid_t) -1;
+static spinlock_t	random_lock;
+
+/*
+ * just init the spin locks
+ */
+static int
+crypto_random_init(void)
+{
+	spin_lock_init(&random_lock);
+	initted = 1;
+	return(0);
+}
+
+/*
+ * Add the given random reader to our list (if not present)
+ * and start the thread (if not already started)
+ *
+ * we have to assume that driver id is ok for now
+ */
+int
+crypto_rregister(
+	u_int32_t driverid,
+	int (*read_random)(void *arg, u_int32_t *buf, int len),
+	void *arg)
+{
+	unsigned long flags;
+	int ret = 0;
+	struct random_op	*rops, *tmp;
+
+	dprintk("%s,%d: %s(0x%x, %p, %p)\n", __FILE__, __LINE__,
+			__FUNCTION__, driverid, read_random, arg);
+
+	if (!initted)
+		crypto_random_init();
+
+#if 0
+	struct cryptocap	*cap;
+
+	cap = crypto_checkdriver(driverid);
+	if (!cap)
+		return EINVAL;
+#endif
+
+	list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
+		if (rops->driverid == driverid && rops->read_random == read_random)
+			return EEXIST;
+	}
+
+	rops = (struct random_op *) kmalloc(sizeof(*rops), GFP_KERNEL);
+	if (!rops)
+		return ENOMEM;
+
+	rops->driverid    = driverid;
+	rops->read_random = read_random;
+	rops->arg = arg;
+
+	spin_lock_irqsave(&random_lock, flags);
+	list_add_tail(&rops->random_list, &random_ops);
+	if (!started) {
+		randomproc = kernel_thread(random_proc, NULL, CLONE_FS|CLONE_FILES);
+		if (randomproc < 0) {
+			ret = randomproc;
+			printk("crypto: crypto_rregister cannot start random thread; "
+					"error %d", ret);
+		} else
+			started = 1;
+	}
+	spin_unlock_irqrestore(&random_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(crypto_rregister);
+
+int
+crypto_runregister_all(u_int32_t driverid)
+{
+	struct random_op *rops, *tmp;
+	unsigned long flags;
+
+	dprintk("%s,%d: %s(0x%x)\n", __FILE__, __LINE__, __FUNCTION__, driverid);
+
+	list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
+		if (rops->driverid == driverid) {
+			list_del(&rops->random_list);
+			kfree(rops);
+		}
+	}
+
+	spin_lock_irqsave(&random_lock, flags);
+	if (list_empty(&random_ops) && started)
+		kill_proc_info(SIGKILL, SEND_SIG_PRIV, randomproc);
+	spin_unlock_irqrestore(&random_lock, flags);
+	return(0);
+}
+EXPORT_SYMBOL(crypto_runregister_all);
+
+/*
+ * while we can add entropy to random.c continue to read random data from
+ * the drivers and push it to random.
+ */
+static int
+random_proc(void *arg)
+{
+	int n;
+	int wantcnt;
+	int bufcnt = 0;
+	int retval = 0;
+	int *buf = NULL;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+	daemonize();
+	spin_lock_irq(&current->sigmask_lock);
+	sigemptyset(&current->blocked);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	sprintf(current->comm, "ocf-random");
+#else
+	daemonize("ocf-random");
+	allow_signal(SIGKILL);
+#endif
+
+	(void) get_fs();
+	set_fs(get_ds());
+
+#ifdef CONFIG_OCF_FIPS
+#define NUM_INT (RNDTEST_NBYTES/sizeof(int))
+#else
+#define NUM_INT 32
+#endif
+
+	/*
+	 * some devices can transferr their RNG data direct into memory,
+	 * so make sure it is device friendly
+	 */
+	buf = kmalloc(NUM_INT * sizeof(int), GFP_DMA);
+	if (NULL == buf) {
+		printk("crypto: RNG could not allocate memory\n");
+		retval = -ENOMEM;
+		goto bad_alloc;
+	}
+
+	wantcnt = NUM_INT;   /* start by adding some entropy */
+
+	/*
+	 * its possible due to errors or driver removal that we no longer
+	 * have anything to do,  if so exit or we will consume all the CPU
+	 * doing nothing
+	 */
+	while (!list_empty(&random_ops)) {
+		struct random_op	*rops, *tmp;
+
+#ifdef CONFIG_OCF_FIPS
+		if (wantcnt)
+			wantcnt = NUM_INT; /* FIPs mode can do 20000 bits or none */
+#endif
+
+		/* see if we can get enough entropy to make the world
+		 * a better place.
+		 */
+		while (bufcnt < wantcnt && bufcnt < NUM_INT) {
+			list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
+
+				n = (*rops->read_random)(rops->arg, &buf[bufcnt],
+							 NUM_INT - bufcnt);
+
+				/* on failure remove the random number generator */
+				if (n == -1) {
+					list_del(&rops->random_list);
+					printk("crypto: RNG (driverid=0x%x) failed, disabling\n",
+							rops->driverid);
+					kfree(rops);
+				} else if (n > 0)
+					bufcnt += n;
+			}
+			/* give up CPU for a bit, just in case as this is a loop */
+			schedule();
+		}
+
+
+#ifdef CONFIG_OCF_FIPS
+		if (bufcnt > 0 && rndtest_buf((unsigned char *) &buf[0])) {
+			dprintk("crypto: buffer had fips errors, discarding\n");
+			bufcnt = 0;
+		}
+#endif
+
+		/*
+		 * if we have a certified buffer,  we can send some data
+		 * to /dev/random and move along
+		 */
+		if (bufcnt > 0) {
+			/* add what we have */
+			random_input_words(buf, bufcnt, bufcnt*sizeof(int)*8);
+			bufcnt = 0;
+		}
+
+		/* give up CPU for a bit so we don't hog while filling */
+		schedule();
+
+		/* wait for needing more */
+		wantcnt = random_input_wait();
+
+		if (wantcnt <= 0)
+			wantcnt = 0; /* try to get some info again */
+		else
+		 	/* round up to one word or we can loop forever */
+			wantcnt = (wantcnt + (sizeof(int)*8)) / (sizeof(int)*8);
+		if (wantcnt > NUM_INT) {
+			wantcnt = NUM_INT;
+		}
+
+		if (signal_pending(current)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+			spin_lock_irq(&current->sigmask_lock);
+#endif
+			flush_signals(current);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+			spin_unlock_irq(&current->sigmask_lock);
+#endif
+		}
+	}
+	
+	kfree(buf);
+
+bad_alloc:
+	spin_lock_irq(&random_lock);
+	randomproc = (pid_t) -1;
+	started = 0;
+	spin_unlock_irq(&random_lock);
+
+	return retval;
+}
+
diff --git a/crypto/ocf/rndtest.c b/crypto/ocf/rndtest.c
new file mode 100755
index 0000000..34b68d8
--- /dev/null
+++ b/crypto/ocf/rndtest.c
@@ -0,0 +1,300 @@
+/*	$OpenBSD$	*/
+
+/*
+ * OCF/Linux port done by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ * The license and original author are listed below.
+ *
+ * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Jason L. Wright
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/version.h>
+#include <linux/unistd.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <cryptodev.h>
+#include "rndtest.h"
+
+static struct rndtest_stats rndstats;
+
+static	void rndtest_test(struct rndtest_state *);
+
+/* The tests themselves */
+static	int rndtest_monobit(struct rndtest_state *);
+static	int rndtest_runs(struct rndtest_state *);
+static	int rndtest_longruns(struct rndtest_state *);
+static	int rndtest_chi_4(struct rndtest_state *);
+
+static	int rndtest_runs_check(struct rndtest_state *, int, int *);
+static	void rndtest_runs_record(struct rndtest_state *, int, int *);
+
+static const struct rndtest_testfunc {
+	int (*test)(struct rndtest_state *);
+} rndtest_funcs[] = {
+	{ rndtest_monobit },
+	{ rndtest_runs },
+	{ rndtest_chi_4 },
+	{ rndtest_longruns },
+};
+
+#define	RNDTEST_NTESTS	(sizeof(rndtest_funcs)/sizeof(rndtest_funcs[0]))
+
+static void
+rndtest_test(struct rndtest_state *rsp)
+{
+	int i, rv = 0;
+
+	rndstats.rst_tests++;
+	for (i = 0; i < RNDTEST_NTESTS; i++)
+		rv |= (*rndtest_funcs[i].test)(rsp);
+	rsp->rs_discard = (rv != 0);
+}
+
+
+extern int crypto_debug;
+#define rndtest_verbose 2
+#define rndtest_report(rsp, failure, fmt, a...) \
+	{ if (failure || crypto_debug) { printk("rng_test: " fmt "\n", a); } else; }
+
+#define	RNDTEST_MONOBIT_MINONES	9725
+#define	RNDTEST_MONOBIT_MAXONES	10275
+
+static int
+rndtest_monobit(struct rndtest_state *rsp)
+{
+	int i, ones = 0, j;
+	u_int8_t r;
+
+	for (i = 0; i < RNDTEST_NBYTES; i++) {
+		r = rsp->rs_buf[i];
+		for (j = 0; j < 8; j++, r <<= 1)
+			if (r & 0x80)
+				ones++;
+	}
+	if (ones > RNDTEST_MONOBIT_MINONES &&
+	    ones < RNDTEST_MONOBIT_MAXONES) {
+		if (rndtest_verbose > 1)
+			rndtest_report(rsp, 0, "monobit pass (%d < %d < %d)",
+			    RNDTEST_MONOBIT_MINONES, ones,
+			    RNDTEST_MONOBIT_MAXONES);
+		return (0);
+	} else {
+		if (rndtest_verbose)
+			rndtest_report(rsp, 1,
+			    "monobit failed (%d ones)", ones);
+		rndstats.rst_monobit++;
+		return (-1);
+	}
+}
+
+#define	RNDTEST_RUNS_NINTERVAL	6
+
+static const struct rndtest_runs_tabs {
+	u_int16_t min, max;
+} rndtest_runs_tab[] = {
+	{ 2343, 2657 },
+	{ 1135, 1365 },
+	{ 542, 708 },
+	{ 251, 373 },
+	{ 111, 201 },
+	{ 111, 201 },
+};
+
+static int
+rndtest_runs(struct rndtest_state *rsp)
+{
+	int i, j, ones, zeros, rv = 0;
+	int onei[RNDTEST_RUNS_NINTERVAL], zeroi[RNDTEST_RUNS_NINTERVAL];
+	u_int8_t c;
+
+	bzero(onei, sizeof(onei));
+	bzero(zeroi, sizeof(zeroi));
+	ones = zeros = 0;
+	for (i = 0; i < RNDTEST_NBYTES; i++) {
+		c = rsp->rs_buf[i];
+		for (j = 0; j < 8; j++, c <<= 1) {
+			if (c & 0x80) {
+				ones++;
+				rndtest_runs_record(rsp, zeros, zeroi);
+				zeros = 0;
+			} else {
+				zeros++;
+				rndtest_runs_record(rsp, ones, onei);
+				ones = 0;
+			}
+		}
+	}
+	rndtest_runs_record(rsp, ones, onei);
+	rndtest_runs_record(rsp, zeros, zeroi);
+
+	rv |= rndtest_runs_check(rsp, 0, zeroi);
+	rv |= rndtest_runs_check(rsp, 1, onei);
+
+	if (rv)
+		rndstats.rst_runs++;
+
+	return (rv);
+}
+
+static void
+rndtest_runs_record(struct rndtest_state *rsp, int len, int *intrv)
+{
+	if (len == 0)
+		return;
+	if (len > RNDTEST_RUNS_NINTERVAL)
+		len = RNDTEST_RUNS_NINTERVAL;
+	len -= 1;
+	intrv[len]++;
+}
+
+static int
+rndtest_runs_check(struct rndtest_state *rsp, int val, int *src)
+{
+	int i, rv = 0;
+
+	for (i = 0; i < RNDTEST_RUNS_NINTERVAL; i++) {
+		if (src[i] < rndtest_runs_tab[i].min ||
+		    src[i] > rndtest_runs_tab[i].max) {
+			rndtest_report(rsp, 1,
+			    "%s interval %d failed (%d, %d-%d)",
+			    val ? "ones" : "zeros",
+			    i + 1, src[i], rndtest_runs_tab[i].min,
+			    rndtest_runs_tab[i].max);
+			rv = -1;
+		} else {
+			rndtest_report(rsp, 0,
+			    "runs pass %s interval %d (%d < %d < %d)",
+			    val ? "ones" : "zeros",
+			    i + 1, rndtest_runs_tab[i].min, src[i],
+			    rndtest_runs_tab[i].max);
+		}
+	}
+	return (rv);
+}
+
+static int
+rndtest_longruns(struct rndtest_state *rsp)
+{
+	int i, j, ones = 0, zeros = 0, maxones = 0, maxzeros = 0;
+	u_int8_t c;
+
+	for (i = 0; i < RNDTEST_NBYTES; i++) {
+		c = rsp->rs_buf[i];
+		for (j = 0; j < 8; j++, c <<= 1) {
+			if (c & 0x80) {
+				zeros = 0;
+				ones++;
+				if (ones > maxones)
+					maxones = ones;
+			} else {
+				ones = 0;
+				zeros++;
+				if (zeros > maxzeros)
+					maxzeros = zeros;
+			}
+		}
+	}
+
+	if (maxones < 26 && maxzeros < 26) {
+		rndtest_report(rsp, 0, "longruns pass (%d ones, %d zeros)",
+			maxones, maxzeros);
+		return (0);
+	} else {
+		rndtest_report(rsp, 1, "longruns fail (%d ones, %d zeros)",
+			maxones, maxzeros);
+		rndstats.rst_longruns++;
+		return (-1);
+	}
+}
+
+/*
+ * chi^2 test over 4 bits: (this is called the poker test in FIPS 140-2,
+ * but it is really the chi^2 test over 4 bits (the poker test as described
+ * by Knuth vol 2 is something different, and I take him as authoritative
+ * on nomenclature over NIST).
+ */
+#define	RNDTEST_CHI4_K	16
+#define	RNDTEST_CHI4_K_MASK	(RNDTEST_CHI4_K - 1)
+
+/*
+ * The unnormalized values are used so that we don't have to worry about
+ * fractional precision.  The "real" value is found by:
+ *	(V - 1562500) * (16 / 5000) = Vn   (where V is the unnormalized value)
+ */
+#define	RNDTEST_CHI4_VMIN	1563181		/* 2.1792 */
+#define	RNDTEST_CHI4_VMAX	1576929		/* 46.1728 */
+
+static int
+rndtest_chi_4(struct rndtest_state *rsp)
+{
+	unsigned int freq[RNDTEST_CHI4_K], i, sum;
+
+	for (i = 0; i < RNDTEST_CHI4_K; i++)
+		freq[i] = 0;
+
+	/* Get number of occurances of each 4 bit pattern */
+	for (i = 0; i < RNDTEST_NBYTES; i++) {
+		freq[(rsp->rs_buf[i] >> 4) & RNDTEST_CHI4_K_MASK]++;
+		freq[(rsp->rs_buf[i] >> 0) & RNDTEST_CHI4_K_MASK]++;
+	}
+
+	for (i = 0, sum = 0; i < RNDTEST_CHI4_K; i++)
+		sum += freq[i] * freq[i];
+
+	if (sum >= 1563181 && sum <= 1576929) {
+		rndtest_report(rsp, 0, "chi^2(4): pass (sum %u)", sum);
+		return (0);
+	} else {
+		rndtest_report(rsp, 1, "chi^2(4): failed (sum %u)", sum);
+		rndstats.rst_chi++;
+		return (-1);
+	}
+}
+
+int
+rndtest_buf(unsigned char *buf)
+{
+	struct rndtest_state rsp;
+
+	memset(&rsp, 0, sizeof(rsp));
+	rsp.rs_buf = buf;
+	rndtest_test(&rsp);
+	return(rsp.rs_discard);
+}
+
diff --git a/crypto/ocf/rndtest.h b/crypto/ocf/rndtest.h
new file mode 100755
index 0000000..e9d8ec8
--- /dev/null
+++ b/crypto/ocf/rndtest.h
@@ -0,0 +1,54 @@
+/*	$FreeBSD: src/sys/dev/rndtest/rndtest.h,v 1.1 2003/03/11 22:54:44 sam Exp $	*/
+/*	$OpenBSD$	*/
+
+/*
+ * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Jason L. Wright
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* Some of the tests depend on these values */
+#define	RNDTEST_NBYTES	2500
+#define	RNDTEST_NBITS	(8 * RNDTEST_NBYTES)
+
+struct rndtest_state {
+	int		rs_discard;	/* discard/accept random data */
+	u_int8_t	*rs_buf;
+};
+
+struct rndtest_stats {
+	u_int32_t	rst_discard;	/* number of bytes discarded */
+	u_int32_t	rst_tests;	/* number of test runs */
+	u_int32_t	rst_monobit;	/* monobit test failures */
+	u_int32_t	rst_runs;	/* 0/1 runs failures */
+	u_int32_t	rst_longruns;	/* longruns failures */
+	u_int32_t	rst_chi;	/* chi^2 failures */
+};
+
+extern int rndtest_buf(unsigned char *buf);
diff --git a/crypto/ocf/safe/Makefile b/crypto/ocf/safe/Makefile
new file mode 100755
index 0000000..9a36b08
--- /dev/null
+++ b/crypto/ocf/safe/Makefile
@@ -0,0 +1,12 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+obj-$(CONFIG_OCF_SAFE) += safe.o
+
+obj ?= .
+EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/crypto/ocf/safe/md5.c b/crypto/ocf/safe/md5.c
new file mode 100755
index 0000000..077c42e
--- /dev/null
+++ b/crypto/ocf/safe/md5.c
@@ -0,0 +1,308 @@
+/*	$KAME: md5.c,v 1.5 2000/11/08 06:13:08 itojun Exp $	*/
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/crypto/md5.c,v 1.9 2004/01/27 19:49:19 des Exp $");
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <crypto/md5.h>
+#endif
+
+#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
+
+#define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z)))
+#define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z)))
+#define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
+#define I(X, Y, Z) ((Y) ^ ((X) | (~Z)))
+
+#define ROUND1(a, b, c, d, k, s, i) { \
+	(a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
+	(a) = SHIFT((a), (s)); \
+	(a) = (b) + (a); \
+}
+
+#define ROUND2(a, b, c, d, k, s, i) { \
+	(a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
+	(a) = SHIFT((a), (s)); \
+	(a) = (b) + (a); \
+}
+
+#define ROUND3(a, b, c, d, k, s, i) { \
+	(a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
+	(a) = SHIFT((a), (s)); \
+	(a) = (b) + (a); \
+}
+
+#define ROUND4(a, b, c, d, k, s, i) { \
+	(a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
+	(a) = SHIFT((a), (s)); \
+	(a) = (b) + (a); \
+}
+
+#define Sa	 7
+#define Sb	12
+#define Sc	17
+#define Sd	22
+
+#define Se	 5
+#define Sf	 9
+#define Sg	14
+#define Sh	20
+
+#define Si	 4
+#define Sj	11
+#define Sk	16
+#define Sl	23
+
+#define Sm	 6
+#define Sn	10
+#define So	15
+#define Sp	21
+
+#define MD5_A0	0x67452301
+#define MD5_B0	0xefcdab89
+#define MD5_C0	0x98badcfe
+#define MD5_D0	0x10325476
+
+/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
+static const u_int32_t T[65] = {
+	0,
+	0xd76aa478, 	0xe8c7b756,	0x242070db,	0xc1bdceee,
+	0xf57c0faf,	0x4787c62a, 	0xa8304613,	0xfd469501,
+	0x698098d8,	0x8b44f7af,	0xffff5bb1,	0x895cd7be,
+	0x6b901122, 	0xfd987193, 	0xa679438e,	0x49b40821,
+
+	0xf61e2562,	0xc040b340, 	0x265e5a51, 	0xe9b6c7aa,
+	0xd62f105d,	0x2441453,	0xd8a1e681,	0xe7d3fbc8,
+	0x21e1cde6,	0xc33707d6, 	0xf4d50d87, 	0x455a14ed,
+	0xa9e3e905,	0xfcefa3f8, 	0x676f02d9, 	0x8d2a4c8a,
+
+	0xfffa3942,	0x8771f681, 	0x6d9d6122, 	0xfde5380c,
+	0xa4beea44, 	0x4bdecfa9, 	0xf6bb4b60, 	0xbebfbc70,
+	0x289b7ec6, 	0xeaa127fa, 	0xd4ef3085,	0x4881d05,
+	0xd9d4d039, 	0xe6db99e5, 	0x1fa27cf8, 	0xc4ac5665,
+
+	0xf4292244, 	0x432aff97, 	0xab9423a7, 	0xfc93a039,
+	0x655b59c3, 	0x8f0ccc92, 	0xffeff47d, 	0x85845dd1,
+	0x6fa87e4f, 	0xfe2ce6e0, 	0xa3014314, 	0x4e0811a1,
+	0xf7537e82, 	0xbd3af235, 	0x2ad7d2bb, 	0xeb86d391,
+};
+
+static const u_int8_t md5_paddat[MD5_BUFLEN] = {
+	0x80,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,	
+};
+
+static void md5_calc(u_int8_t *, md5_ctxt *);
+
+void md5_init(ctxt)
+	md5_ctxt *ctxt;
+{
+	ctxt->md5_n = 0;
+	ctxt->md5_i = 0;
+	ctxt->md5_sta = MD5_A0;
+	ctxt->md5_stb = MD5_B0;
+	ctxt->md5_stc = MD5_C0;
+	ctxt->md5_std = MD5_D0;
+	bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf));
+}
+
+void md5_loop(ctxt, input, len)
+	md5_ctxt *ctxt;
+	u_int8_t *input;
+	u_int len; /* number of bytes */
+{
+	u_int gap, i;
+
+	ctxt->md5_n += len * 8; /* byte to bit */
+	gap = MD5_BUFLEN - ctxt->md5_i;
+
+	if (len >= gap) {
+		bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i),
+			gap);
+		md5_calc(ctxt->md5_buf, ctxt);
+
+		for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) {
+			md5_calc((u_int8_t *)(input + i), ctxt);
+		}
+		
+		ctxt->md5_i = len - i;
+		bcopy((void *)(input + i), (void *)ctxt->md5_buf, ctxt->md5_i);
+	} else {
+		bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i),
+			len);
+		ctxt->md5_i += len;
+	}
+}
+
+void md5_pad(ctxt)
+	md5_ctxt *ctxt;
+{
+	u_int gap;
+
+	/* Don't count up padding. Keep md5_n. */	
+	gap = MD5_BUFLEN - ctxt->md5_i;
+	if (gap > 8) {
+		bcopy(md5_paddat,
+		      (void *)(ctxt->md5_buf + ctxt->md5_i),
+		      gap - sizeof(ctxt->md5_n));
+	} else {
+		/* including gap == 8 */
+		bcopy(md5_paddat, (void *)(ctxt->md5_buf + ctxt->md5_i),
+			gap);
+		md5_calc(ctxt->md5_buf, ctxt);
+		bcopy((md5_paddat + gap),
+		      (void *)ctxt->md5_buf,
+		      MD5_BUFLEN - sizeof(ctxt->md5_n));
+	}
+
+	/* 8 byte word */	
+#if BYTE_ORDER == LITTLE_ENDIAN
+	bcopy(&ctxt->md5_n8[0], &ctxt->md5_buf[56], 8);
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	ctxt->md5_buf[56] = ctxt->md5_n8[7];
+	ctxt->md5_buf[57] = ctxt->md5_n8[6];
+	ctxt->md5_buf[58] = ctxt->md5_n8[5];
+	ctxt->md5_buf[59] = ctxt->md5_n8[4];
+	ctxt->md5_buf[60] = ctxt->md5_n8[3];
+	ctxt->md5_buf[61] = ctxt->md5_n8[2];
+	ctxt->md5_buf[62] = ctxt->md5_n8[1];
+	ctxt->md5_buf[63] = ctxt->md5_n8[0];
+#endif
+
+	md5_calc(ctxt->md5_buf, ctxt);
+}
+
+void md5_result(digest, ctxt)
+	u_int8_t *digest;
+	md5_ctxt *ctxt;
+{
+	/* 4 byte words */
+#if BYTE_ORDER == LITTLE_ENDIAN
+	bcopy(&ctxt->md5_st8[0], digest, 16);
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2];
+	digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0];
+	digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6];
+	digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4];
+	digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10];
+	digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8];
+	digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14];
+	digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12];
+#endif
+}
+
+static void md5_calc(b64, ctxt)
+	u_int8_t *b64;
+	md5_ctxt *ctxt;
+{
+	u_int32_t A = ctxt->md5_sta;
+	u_int32_t B = ctxt->md5_stb;
+	u_int32_t C = ctxt->md5_stc;
+	u_int32_t D = ctxt->md5_std;
+#if BYTE_ORDER == LITTLE_ENDIAN
+	u_int32_t *X = (u_int32_t *)b64;
+#endif	
+#if BYTE_ORDER == BIG_ENDIAN
+	/* 4 byte words */
+	/* what a brute force but fast! */
+	u_int32_t X[16];
+	u_int8_t *y = (u_int8_t *)X;
+	y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
+	y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4];
+	y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8];
+	y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12];
+	y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16];
+	y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20];
+	y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24];
+	y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28];
+	y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32];
+	y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36];
+	y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40];
+	y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44];
+	y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48];
+	y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52];
+	y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56];
+	y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60];
+#endif
+
+	ROUND1(A, B, C, D,  0, Sa,  1); ROUND1(D, A, B, C,  1, Sb,  2);
+	ROUND1(C, D, A, B,  2, Sc,  3); ROUND1(B, C, D, A,  3, Sd,  4);
+	ROUND1(A, B, C, D,  4, Sa,  5); ROUND1(D, A, B, C,  5, Sb,  6);
+	ROUND1(C, D, A, B,  6, Sc,  7); ROUND1(B, C, D, A,  7, Sd,  8);
+	ROUND1(A, B, C, D,  8, Sa,  9); ROUND1(D, A, B, C,  9, Sb, 10);
+	ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12);
+	ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14);
+	ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16);
+	
+	ROUND2(A, B, C, D,  1, Se, 17); ROUND2(D, A, B, C,  6, Sf, 18);
+	ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A,  0, Sh, 20);
+	ROUND2(A, B, C, D,  5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22);
+	ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A,  4, Sh, 24);
+	ROUND2(A, B, C, D,  9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26);
+	ROUND2(C, D, A, B,  3, Sg, 27); ROUND2(B, C, D, A,  8, Sh, 28);
+	ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C,  2, Sf, 30);
+	ROUND2(C, D, A, B,  7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32);
+
+	ROUND3(A, B, C, D,  5, Si, 33); ROUND3(D, A, B, C,  8, Sj, 34);
+	ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36);
+	ROUND3(A, B, C, D,  1, Si, 37); ROUND3(D, A, B, C,  4, Sj, 38);
+	ROUND3(C, D, A, B,  7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40);
+	ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C,  0, Sj, 42);
+	ROUND3(C, D, A, B,  3, Sk, 43); ROUND3(B, C, D, A,  6, Sl, 44);
+	ROUND3(A, B, C, D,  9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46);
+	ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A,  2, Sl, 48);
+	
+	ROUND4(A, B, C, D,  0, Sm, 49); ROUND4(D, A, B, C,  7, Sn, 50);	
+	ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A,  5, Sp, 52);	
+	ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C,  3, Sn, 54);	
+	ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A,  1, Sp, 56);	
+	ROUND4(A, B, C, D,  8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58);	
+	ROUND4(C, D, A, B,  6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60);	
+	ROUND4(A, B, C, D,  4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62);	
+	ROUND4(C, D, A, B,  2, So, 63); ROUND4(B, C, D, A,  9, Sp, 64);
+
+	ctxt->md5_sta += A;
+	ctxt->md5_stb += B;
+	ctxt->md5_stc += C;
+	ctxt->md5_std += D;
+}
diff --git a/crypto/ocf/safe/md5.h b/crypto/ocf/safe/md5.h
new file mode 100755
index 0000000..690f5bf
--- /dev/null
+++ b/crypto/ocf/safe/md5.h
@@ -0,0 +1,76 @@
+/*	$FreeBSD: src/sys/crypto/md5.h,v 1.4 2002/03/20 05:13:50 alfred Exp $	*/
+/*	$KAME: md5.h,v 1.4 2000/03/27 04:36:22 sumikawa Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NETINET6_MD5_H_
+#define _NETINET6_MD5_H_
+
+#define MD5_BUFLEN	64
+
+typedef struct {
+	union {
+		u_int32_t	md5_state32[4];
+		u_int8_t	md5_state8[16];
+	} md5_st;
+
+#define md5_sta		md5_st.md5_state32[0]
+#define md5_stb		md5_st.md5_state32[1]
+#define md5_stc		md5_st.md5_state32[2]
+#define md5_std		md5_st.md5_state32[3]
+#define md5_st8		md5_st.md5_state8
+
+	union {
+		u_int64_t	md5_count64;
+		u_int8_t	md5_count8[8];
+	} md5_count;
+#define md5_n	md5_count.md5_count64
+#define md5_n8	md5_count.md5_count8
+
+	u_int	md5_i;
+	u_int8_t	md5_buf[MD5_BUFLEN];
+} md5_ctxt;
+
+extern void md5_init(md5_ctxt *);
+extern void md5_loop(md5_ctxt *, u_int8_t *, u_int);
+extern void md5_pad(md5_ctxt *);
+extern void md5_result(u_int8_t *, md5_ctxt *);
+
+/* compatibility */
+#define MD5_CTX		md5_ctxt
+#define MD5Init(x)	md5_init((x))
+#define MD5Update(x, y, z)	md5_loop((x), (y), (z))
+#define MD5Final(x, y) \
+do {				\
+	md5_pad((y));		\
+	md5_result((x), (y));	\
+} while (0)
+
+#endif /* ! _NETINET6_MD5_H_*/
diff --git a/crypto/ocf/safe/safe.c b/crypto/ocf/safe/safe.c
new file mode 100755
index 0000000..a77e3a2
--- /dev/null
+++ b/crypto/ocf/safe/safe.c
@@ -0,0 +1,2288 @@
+/*-
+ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2004-2007 David McCullough
+ * The license and original author are listed below.
+ *
+ * Copyright (c) 2003 Sam Leffler, Errno Consulting
+ * Copyright (c) 2003 Global Technology Associates, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+__FBSDID("$FreeBSD: src/sys/dev/safe/safe.c,v 1.18 2007/03/21 03:42:50 sam Exp $");
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/version.h>
+#include <linux/skbuff.h>
+#include <asm/io.h>
+
+/*
+ * SafeNet SafeXcel-1141 hardware crypto accelerator
+ */
+
+#include <cryptodev.h>
+#include <uio.h>
+#include <safe/safereg.h>
+#include <safe/safevar.h>
+
+#if 1
+#define	DPRINTF(a)	do { \
+						if (debug) { \
+							printk("%s: ", sc ? \
+								device_get_nameunit(sc->sc_dev) : "safe"); \
+							printk a; \
+						} \
+					} while (0)
+#else
+#define	DPRINTF(a)
+#endif
+
+/*
+ * until we find a cleaner way, include the BSD md5/sha1 code
+ * here
+ */
+#define HMAC_HACK 1
+#ifdef HMAC_HACK
+#define LITTLE_ENDIAN 1234
+#define BIG_ENDIAN 4321
+#ifdef __LITTLE_ENDIAN
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#ifdef __BIG_ENDIAN
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+#include <safe/md5.h>
+#include <safe/md5.c>
+#include <safe/sha1.h>
+#include <safe/sha1.c>
+
+u_int8_t hmac_ipad_buffer[64] = {
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+};
+
+u_int8_t hmac_opad_buffer[64] = {
+    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C
+};
+#endif /* HMAC_HACK */
+
+/* add proc entry for this */
+struct safe_stats safestats;
+
+#define debug safe_debug
+int safe_debug = 0;
+module_param(safe_debug, int, 0644);
+MODULE_PARM_DESC(safe_debug, "Enable debug");
+
+static	void safe_callback(struct safe_softc *, struct safe_ringentry *);
+static	void safe_feed(struct safe_softc *, struct safe_ringentry *);
+#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
+static	void safe_rng_init(struct safe_softc *);
+int safe_rngbufsize = 8;		/* 32 bytes each read  */
+module_param(safe_rngbufsize, int, 0644);
+MODULE_PARM_DESC(safe_rngbufsize, "RNG polling buffer size (32-bit words)");
+int safe_rngmaxalarm = 8;		/* max alarms before reset */
+module_param(safe_rngmaxalarm, int, 0644);
+MODULE_PARM_DESC(safe_rngmaxalarm, "RNG max alarms before reset");
+#endif /* SAFE_NO_RNG */
+
+static void safe_totalreset(struct safe_softc *sc);
+static int safe_dmamap_aligned(struct safe_softc *sc, const struct safe_operand *op);
+static int safe_dmamap_uniform(struct safe_softc *sc, const struct safe_operand *op);
+static int safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re);
+static int safe_kprocess(device_t dev, struct cryptkop *krp, int hint);
+static int safe_kstart(struct safe_softc *sc);
+static int safe_ksigbits(struct safe_softc *sc, struct crparam *cr);
+static void safe_kfeed(struct safe_softc *sc);
+static void safe_kpoll(unsigned long arg);
+static void safe_kload_reg(struct safe_softc *sc, u_int32_t off,
+								u_int32_t len, struct crparam *n);
+
+static	int safe_newsession(device_t, u_int32_t *, struct cryptoini *);
+static	int safe_freesession(device_t, u_int64_t);
+static	int safe_process(device_t, struct cryptop *, int);
+
+static device_method_t safe_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,	safe_newsession),
+	DEVMETHOD(cryptodev_freesession,safe_freesession),
+	DEVMETHOD(cryptodev_process,	safe_process),
+	DEVMETHOD(cryptodev_kprocess,	safe_kprocess),
+};
+
+#define	READ_REG(sc,r)			readl((sc)->sc_base_addr + (r))
+#define WRITE_REG(sc,r,val)		writel((val), (sc)->sc_base_addr + (r))
+
+#define SAFE_MAX_CHIPS 8
+static struct safe_softc *safe_chip_idx[SAFE_MAX_CHIPS];
+
+/*
+ * split our buffers up into safe DMAable byte fragments to avoid lockup
+ * bug in 1141 HW on rev 1.0.
+ */
+
+static int
+pci_map_linear(
+	struct safe_softc *sc,
+	struct safe_operand *buf,
+	void *addr,
+	int len)
+{
+	dma_addr_t tmp;
+	int chunk, tlen = len;
+
+	tmp = pci_map_single(sc->sc_pcidev, addr, len, PCI_DMA_BIDIRECTIONAL);
+
+	buf->mapsize += len;
+	while (len > 0) {
+		chunk = (len > sc->sc_max_dsize) ? sc->sc_max_dsize : len;
+		buf->segs[buf->nsegs].ds_addr = tmp;
+		buf->segs[buf->nsegs].ds_len  = chunk;
+		buf->segs[buf->nsegs].ds_tlen = tlen;
+		buf->nsegs++;
+		tmp  += chunk;
+		len  -= chunk;
+		tlen = 0;
+	}
+	return 0;
+}
+
+/*
+ * map in a given uio buffer (great on some arches :-)
+ */
+
+static int
+pci_map_uio(struct safe_softc *sc, struct safe_operand *buf, struct uio *uio)
+{
+	struct iovec *iov = uio->uio_iov;
+	int n;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	buf->mapsize = 0;
+	buf->nsegs = 0;
+
+	for (n = 0; n < uio->uio_iovcnt; n++) {
+		pci_map_linear(sc, buf, iov->iov_base, iov->iov_len);
+		iov++;
+	}
+
+	/* identify this buffer by the first segment */
+	buf->map = (void *) buf->segs[0].ds_addr;
+	return(0);
+}
+
+/*
+ * map in a given sk_buff
+ */
+
+static int
+pci_map_skb(struct safe_softc *sc,struct safe_operand *buf,struct sk_buff *skb)
+{
+	int i;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	buf->mapsize = 0;
+	buf->nsegs = 0;
+
+	pci_map_linear(sc, buf, skb->data, skb_headlen(skb));
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		pci_map_linear(sc, buf,
+				page_address(skb_shinfo(skb)->frags[i].page) +
+				                        skb_shinfo(skb)->frags[i].page_offset,
+				skb_shinfo(skb)->frags[i].size);
+	}
+
+	/* identify this buffer by the first segment */
+	buf->map = (void *) buf->segs[0].ds_addr;
+	return(0);
+}
+
+
+#if 0 /* not needed at this time */
+static void
+pci_sync_operand(struct safe_softc *sc, struct safe_operand *buf)
+{
+	int i;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+	for (i = 0; i < buf->nsegs; i++)
+		pci_dma_sync_single_for_cpu(sc->sc_pcidev, buf->segs[i].ds_addr,
+				buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
+}
+#endif
+
+static void
+pci_unmap_operand(struct safe_softc *sc, struct safe_operand *buf)
+{
+	int i;
+	DPRINTF(("%s()\n", __FUNCTION__));
+	for (i = 0; i < buf->nsegs; i++) {
+		if (buf->segs[i].ds_tlen) {
+			DPRINTF(("%s - unmap %d 0x%x %d\n", __FUNCTION__, i, buf->segs[i].ds_addr, buf->segs[i].ds_tlen));
+			pci_unmap_single(sc->sc_pcidev, buf->segs[i].ds_addr,
+					buf->segs[i].ds_tlen, PCI_DMA_BIDIRECTIONAL);
+			DPRINTF(("%s - unmap %d 0x%x %d done\n", __FUNCTION__, i, buf->segs[i].ds_addr, buf->segs[i].ds_tlen));
+		}
+		buf->segs[i].ds_addr = 0;
+		buf->segs[i].ds_len = 0;
+		buf->segs[i].ds_tlen = 0;
+	}
+	buf->nsegs = 0;
+	buf->mapsize = 0;
+	buf->map = 0;
+}
+
+
+/*
+ * SafeXcel Interrupt routine
+ */
+static irqreturn_t
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+safe_intr(int irq, void *arg)
+#else
+safe_intr(int irq, void *arg, struct pt_regs *regs)
+#endif
+{
+	struct safe_softc *sc = arg;
+	int stat;
+	unsigned long flags;
+
+	stat = READ_REG(sc, SAFE_HM_STAT);
+
+	DPRINTF(("%s(stat=0x%x)\n", __FUNCTION__, stat));
+
+	if (stat == 0)		/* shared irq, not for us */
+		return IRQ_NONE;
+
+	WRITE_REG(sc, SAFE_HI_CLR, stat);	/* IACK */
+
+	if ((stat & SAFE_INT_PE_DDONE)) {
+		/*
+		 * Descriptor(s) done; scan the ring and
+		 * process completed operations.
+		 */
+		spin_lock_irqsave(&sc->sc_ringmtx, flags);
+		while (sc->sc_back != sc->sc_front) {
+			struct safe_ringentry *re = sc->sc_back;
+
+#ifdef SAFE_DEBUG
+			if (debug) {
+				safe_dump_ringstate(sc, __func__);
+				safe_dump_request(sc, __func__, re);
+			}
+#endif
+			/*
+			 * safe_process marks ring entries that were allocated
+			 * but not used with a csr of zero.  This insures the
+			 * ring front pointer never needs to be set backwards
+			 * in the event that an entry is allocated but not used
+			 * because of a setup error.
+			 */
+			DPRINTF(("%s re->re_desc.d_csr=0x%x\n", __FUNCTION__, re->re_desc.d_csr));
+			if (re->re_desc.d_csr != 0) {
+				if (!SAFE_PE_CSR_IS_DONE(re->re_desc.d_csr)) {
+					DPRINTF(("%s !CSR_IS_DONE\n", __FUNCTION__));
+					break;
+				}
+				if (!SAFE_PE_LEN_IS_DONE(re->re_desc.d_len)) {
+					DPRINTF(("%s !LEN_IS_DONE\n", __FUNCTION__));
+					break;
+				}
+				sc->sc_nqchip--;
+				safe_callback(sc, re);
+			}
+			if (++(sc->sc_back) == sc->sc_ringtop)
+				sc->sc_back = sc->sc_ring;
+		}
+		spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
+	}
+
+	/*
+	 * Check to see if we got any DMA Error
+	 */
+	if (stat & SAFE_INT_PE_ERROR) {
+		printk("%s: dmaerr dmastat %08x\n", device_get_nameunit(sc->sc_dev),
+				(int)READ_REG(sc, SAFE_PE_DMASTAT));
+		safestats.st_dmaerr++;
+		safe_totalreset(sc);
+#if 0
+		safe_feed(sc);
+#endif
+	}
+
+	if (sc->sc_needwakeup) {		/* XXX check high watermark */
+		int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
+		DPRINTF(("%s: wakeup crypto %x\n", __func__,
+			sc->sc_needwakeup));
+		sc->sc_needwakeup &= ~wakeup;
+		crypto_unblock(sc->sc_cid, wakeup);
+	}
+	
+	return IRQ_HANDLED;
+}
+
+/*
+ * safe_feed() - post a request to chip
+ */
+static void
+safe_feed(struct safe_softc *sc, struct safe_ringentry *re)
+{
+	DPRINTF(("%s()\n", __FUNCTION__));
+#ifdef SAFE_DEBUG
+	if (debug) {
+		safe_dump_ringstate(sc, __func__);
+		safe_dump_request(sc, __func__, re);
+	}
+#endif
+	sc->sc_nqchip++;
+	if (sc->sc_nqchip > safestats.st_maxqchip)
+		safestats.st_maxqchip = sc->sc_nqchip;
+	/* poke h/w to check descriptor ring, any value can be written */
+	WRITE_REG(sc, SAFE_HI_RD_DESCR, 0);
+}
+
+#define	N(a)	(sizeof(a) / sizeof (a[0]))
+static void
+safe_setup_enckey(struct safe_session *ses, caddr_t key)
+{
+	int i;
+
+	bcopy(key, ses->ses_key, ses->ses_klen / 8);
+
+	/* PE is little-endian, insure proper byte order */
+	for (i = 0; i < N(ses->ses_key); i++)
+		ses->ses_key[i] = htole32(ses->ses_key[i]);
+}
+
+static void
+safe_setup_mackey(struct safe_session *ses, int algo, caddr_t key, int klen)
+{
+#ifdef HMAC_HACK
+	MD5_CTX md5ctx;
+	SHA1_CTX sha1ctx;
+	int i;
+
+
+	for (i = 0; i < klen; i++)
+		key[i] ^= HMAC_IPAD_VAL;
+
+	if (algo == CRYPTO_MD5_HMAC) {
+		MD5Init(&md5ctx);
+		MD5Update(&md5ctx, key, klen);
+		MD5Update(&md5ctx, hmac_ipad_buffer, MD5_HMAC_BLOCK_LEN - klen);
+		bcopy(md5ctx.md5_st8, ses->ses_hminner, sizeof(md5ctx.md5_st8));
+	} else {
+		SHA1Init(&sha1ctx);
+		SHA1Update(&sha1ctx, key, klen);
+		SHA1Update(&sha1ctx, hmac_ipad_buffer,
+		    SHA1_HMAC_BLOCK_LEN - klen);
+		bcopy(sha1ctx.h.b32, ses->ses_hminner, sizeof(sha1ctx.h.b32));
+	}
+
+	for (i = 0; i < klen; i++)
+		key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
+
+	if (algo == CRYPTO_MD5_HMAC) {
+		MD5Init(&md5ctx);
+		MD5Update(&md5ctx, key, klen);
+		MD5Update(&md5ctx, hmac_opad_buffer, MD5_HMAC_BLOCK_LEN - klen);
+		bcopy(md5ctx.md5_st8, ses->ses_hmouter, sizeof(md5ctx.md5_st8));
+	} else {
+		SHA1Init(&sha1ctx);
+		SHA1Update(&sha1ctx, key, klen);
+		SHA1Update(&sha1ctx, hmac_opad_buffer,
+		    SHA1_HMAC_BLOCK_LEN - klen);
+		bcopy(sha1ctx.h.b32, ses->ses_hmouter, sizeof(sha1ctx.h.b32));
+	}
+
+	for (i = 0; i < klen; i++)
+		key[i] ^= HMAC_OPAD_VAL;
+
+#if 0
+	/*
+	 * this code prevents SHA working on a BE host,
+	 * so it is obviously wrong.  I think the byte
+	 * swap setup we do with the chip fixes this for us
+	 */
+
+	/* PE is little-endian, insure proper byte order */
+	for (i = 0; i < N(ses->ses_hminner); i++) {
+		ses->ses_hminner[i] = htole32(ses->ses_hminner[i]);
+		ses->ses_hmouter[i] = htole32(ses->ses_hmouter[i]);
+	}
+#endif
+#else /* HMAC_HACK */
+	printk("safe: md5/sha not implemented\n");
+#endif /* HMAC_HACK */
+}
+#undef N
+
+/*
+ * Allocate a new 'session' and return an encoded session id.  'sidp'
+ * contains our registration id, and should contain an encoded session
+ * id on successful allocation.
+ */
+static int
+safe_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
+{
+	struct safe_softc *sc = device_get_softc(dev);
+	struct cryptoini *c, *encini = NULL, *macini = NULL;
+	struct safe_session *ses = NULL;
+	int sesn;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (sidp == NULL || cri == NULL || sc == NULL)
+		return (EINVAL);
+
+	for (c = cri; c != NULL; c = c->cri_next) {
+		if (c->cri_alg == CRYPTO_MD5_HMAC ||
+		    c->cri_alg == CRYPTO_SHA1_HMAC ||
+		    c->cri_alg == CRYPTO_NULL_HMAC) {
+			if (macini)
+				return (EINVAL);
+			macini = c;
+		} else if (c->cri_alg == CRYPTO_DES_CBC ||
+		    c->cri_alg == CRYPTO_3DES_CBC ||
+		    c->cri_alg == CRYPTO_AES_CBC ||
+		    c->cri_alg == CRYPTO_NULL_CBC) {
+			if (encini)
+				return (EINVAL);
+			encini = c;
+		} else
+			return (EINVAL);
+	}
+	if (encini == NULL && macini == NULL)
+		return (EINVAL);
+	if (encini) {			/* validate key length */
+		switch (encini->cri_alg) {
+		case CRYPTO_DES_CBC:
+			if (encini->cri_klen != 64)
+				return (EINVAL);
+			break;
+		case CRYPTO_3DES_CBC:
+			if (encini->cri_klen != 192)
+				return (EINVAL);
+			break;
+		case CRYPTO_AES_CBC:
+			if (encini->cri_klen != 128 &&
+			    encini->cri_klen != 192 &&
+			    encini->cri_klen != 256)
+				return (EINVAL);
+			break;
+		}
+	}
+
+	if (sc->sc_sessions == NULL) {
+		ses = sc->sc_sessions = (struct safe_session *)
+			kmalloc(sizeof(struct safe_session), SLAB_ATOMIC);
+		if (ses == NULL)
+			return (ENOMEM);
+		memset(ses, 0, sizeof(struct safe_session));
+		sesn = 0;
+		sc->sc_nsessions = 1;
+	} else {
+		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
+			if (sc->sc_sessions[sesn].ses_used == 0) {
+				ses = &sc->sc_sessions[sesn];
+				break;
+			}
+		}
+
+		if (ses == NULL) {
+			sesn = sc->sc_nsessions;
+			ses = (struct safe_session *)
+				kmalloc((sesn + 1) * sizeof(struct safe_session), SLAB_ATOMIC);
+			if (ses == NULL)
+				return (ENOMEM);
+			memset(ses, 0, (sesn + 1) * sizeof(struct safe_session));
+			bcopy(sc->sc_sessions, ses, sesn *
+			    sizeof(struct safe_session));
+			bzero(sc->sc_sessions, sesn *
+			    sizeof(struct safe_session));
+			kfree(sc->sc_sessions);
+			sc->sc_sessions = ses;
+			ses = &sc->sc_sessions[sesn];
+			sc->sc_nsessions++;
+		}
+	}
+
+	bzero(ses, sizeof(struct safe_session));
+	ses->ses_used = 1;
+
+	if (encini) {
+		/* get an IV */
+		/* XXX may read fewer than requested */
+		read_random(ses->ses_iv, sizeof(ses->ses_iv));
+
+		ses->ses_klen = encini->cri_klen;
+		if (encini->cri_key != NULL)
+			safe_setup_enckey(ses, encini->cri_key);
+	}
+
+	if (macini) {
+		ses->ses_mlen = macini->cri_mlen;
+		if (ses->ses_mlen == 0) {
+			if (macini->cri_alg == CRYPTO_MD5_HMAC)
+				ses->ses_mlen = MD5_HASH_LEN;
+			else
+				ses->ses_mlen = SHA1_HASH_LEN;
+		}
+
+		if (macini->cri_key != NULL) {
+			safe_setup_mackey(ses, macini->cri_alg, macini->cri_key,
+			    macini->cri_klen / 8);
+		}
+	}
+
+	*sidp = SAFE_SID(device_get_unit(sc->sc_dev), sesn);
+	return (0);
+}
+
+/*
+ * Deallocate a session.
+ */
+static int
+safe_freesession(device_t dev, u_int64_t tid)
+{
+	struct safe_softc *sc = device_get_softc(dev);
+	int session, ret;
+	u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (sc == NULL)
+		return (EINVAL);
+
+	session = SAFE_SESSION(sid);
+	if (session < sc->sc_nsessions) {
+		bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
+		ret = 0;
+	} else
+		ret = EINVAL;
+	return (ret);
+}
+
+
+static int
+safe_process(device_t dev, struct cryptop *crp, int hint)
+{
+	struct safe_softc *sc = device_get_softc(dev);
+	int err = 0, i, nicealign, uniform;
+	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
+	int bypass, oplen, ivsize;
+	caddr_t iv;
+	int16_t coffset;
+	struct safe_session *ses;
+	struct safe_ringentry *re;
+	struct safe_sarec *sa;
+	struct safe_pdesc *pd;
+	u_int32_t cmd0, cmd1, staterec;
+	unsigned long flags;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (crp == NULL || crp->crp_callback == NULL || sc == NULL) {
+		safestats.st_invalid++;
+		return (EINVAL);
+	}
+	if (SAFE_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
+		safestats.st_badsession++;
+		return (EINVAL);
+	}
+
+	spin_lock_irqsave(&sc->sc_ringmtx, flags);
+	if (sc->sc_front == sc->sc_back && sc->sc_nqchip != 0) {
+		safestats.st_ringfull++;
+		sc->sc_needwakeup |= CRYPTO_SYMQ;
+		spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
+		return (ERESTART);
+	}
+	re = sc->sc_front;
+
+	staterec = re->re_sa.sa_staterec;	/* save */
+	/* NB: zero everything but the PE descriptor */
+	bzero(&re->re_sa, sizeof(struct safe_ringentry) - sizeof(re->re_desc));
+	re->re_sa.sa_staterec = staterec;	/* restore */
+
+	re->re_crp = crp;
+	re->re_sesn = SAFE_SESSION(crp->crp_sid);
+
+	re->re_src.nsegs = 0;
+	re->re_dst.nsegs = 0;
+
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		re->re_src_skb = (struct sk_buff *)crp->crp_buf;
+		re->re_dst_skb = (struct sk_buff *)crp->crp_buf;
+	} else if (crp->crp_flags & CRYPTO_F_IOV) {
+		re->re_src_io = (struct uio *)crp->crp_buf;
+		re->re_dst_io = (struct uio *)crp->crp_buf;
+	} else {
+		safestats.st_badflags++;
+		err = EINVAL;
+		goto errout;	/* XXX we don't handle contiguous blocks! */
+	}
+
+	sa = &re->re_sa;
+	ses = &sc->sc_sessions[re->re_sesn];
+
+	crd1 = crp->crp_desc;
+	if (crd1 == NULL) {
+		safestats.st_nodesc++;
+		err = EINVAL;
+		goto errout;
+	}
+	crd2 = crd1->crd_next;
+
+	cmd0 = SAFE_SA_CMD0_BASIC;		/* basic group operation */
+	cmd1 = 0;
+	if (crd2 == NULL) {
+		if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
+		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
+		    crd1->crd_alg == CRYPTO_NULL_HMAC) {
+			maccrd = crd1;
+			enccrd = NULL;
+			cmd0 |= SAFE_SA_CMD0_OP_HASH;
+		} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
+		    crd1->crd_alg == CRYPTO_3DES_CBC ||
+		    crd1->crd_alg == CRYPTO_AES_CBC ||
+		    crd1->crd_alg == CRYPTO_NULL_CBC) {
+			maccrd = NULL;
+			enccrd = crd1;
+			cmd0 |= SAFE_SA_CMD0_OP_CRYPT;
+		} else {
+			safestats.st_badalg++;
+			err = EINVAL;
+			goto errout;
+		}
+	} else {
+		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
+		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
+		    crd1->crd_alg == CRYPTO_NULL_HMAC) &&
+		    (crd2->crd_alg == CRYPTO_DES_CBC ||
+			crd2->crd_alg == CRYPTO_3DES_CBC ||
+		        crd2->crd_alg == CRYPTO_AES_CBC ||
+		        crd2->crd_alg == CRYPTO_NULL_CBC) &&
+		    ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
+			maccrd = crd1;
+			enccrd = crd2;
+		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
+		    crd1->crd_alg == CRYPTO_3DES_CBC ||
+		    crd1->crd_alg == CRYPTO_AES_CBC ||
+		    crd1->crd_alg == CRYPTO_NULL_CBC) &&
+		    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
+			crd2->crd_alg == CRYPTO_SHA1_HMAC ||
+			crd2->crd_alg == CRYPTO_NULL_HMAC) &&
+		    (crd1->crd_flags & CRD_F_ENCRYPT)) {
+			enccrd = crd1;
+			maccrd = crd2;
+		} else {
+			safestats.st_badalg++;
+			err = EINVAL;
+			goto errout;
+		}
+		cmd0 |= SAFE_SA_CMD0_OP_BOTH;
+	}
+
+	if (enccrd) {
+		if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
+			safe_setup_enckey(ses, enccrd->crd_key);
+
+		if (enccrd->crd_alg == CRYPTO_DES_CBC) {
+			cmd0 |= SAFE_SA_CMD0_DES;
+			cmd1 |= SAFE_SA_CMD1_CBC;
+			ivsize = 2*sizeof(u_int32_t);
+		} else if (enccrd->crd_alg == CRYPTO_3DES_CBC) {
+			cmd0 |= SAFE_SA_CMD0_3DES;
+			cmd1 |= SAFE_SA_CMD1_CBC;
+			ivsize = 2*sizeof(u_int32_t);
+		} else if (enccrd->crd_alg == CRYPTO_AES_CBC) {
+			cmd0 |= SAFE_SA_CMD0_AES;
+			cmd1 |= SAFE_SA_CMD1_CBC;
+			if (ses->ses_klen == 128)
+			     cmd1 |=  SAFE_SA_CMD1_AES128;
+			else if (ses->ses_klen == 192)
+			     cmd1 |=  SAFE_SA_CMD1_AES192;
+			else
+			     cmd1 |=  SAFE_SA_CMD1_AES256;
+			ivsize = 4*sizeof(u_int32_t);
+		} else {
+			cmd0 |= SAFE_SA_CMD0_CRYPT_NULL;
+			ivsize = 0;
+		}
+
+		/*
+		 * Setup encrypt/decrypt state.  When using basic ops
+		 * we can't use an inline IV because hash/crypt offset
+		 * must be from the end of the IV to the start of the
+		 * crypt data and this leaves out the preceding header
+		 * from the hash calculation.  Instead we place the IV
+		 * in the state record and set the hash/crypt offset to
+		 * copy both the header+IV.
+		 */
+		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
+			cmd0 |= SAFE_SA_CMD0_OUTBOUND;
+
+			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+				iv = enccrd->crd_iv;
+			else
+				iv = (caddr_t) ses->ses_iv;
+			if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
+				crypto_copyback(crp->crp_flags, crp->crp_buf,
+				    enccrd->crd_inject, ivsize, iv);
+			}
+			bcopy(iv, re->re_sastate.sa_saved_iv, ivsize);
+			/* make iv LE */
+			for (i = 0; i < ivsize/sizeof(re->re_sastate.sa_saved_iv[0]); i++)
+				re->re_sastate.sa_saved_iv[i] =
+					cpu_to_le32(re->re_sastate.sa_saved_iv[i]);
+			cmd0 |= SAFE_SA_CMD0_IVLD_STATE | SAFE_SA_CMD0_SAVEIV;
+			re->re_flags |= SAFE_QFLAGS_COPYOUTIV;
+		} else {
+			cmd0 |= SAFE_SA_CMD0_INBOUND;
+
+			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
+				bcopy(enccrd->crd_iv,
+					re->re_sastate.sa_saved_iv, ivsize);
+			} else {
+				crypto_copydata(crp->crp_flags, crp->crp_buf,
+				    enccrd->crd_inject, ivsize,
+				    (caddr_t)re->re_sastate.sa_saved_iv);
+			}
+			/* make iv LE */
+			for (i = 0; i < ivsize/sizeof(re->re_sastate.sa_saved_iv[0]); i++)
+				re->re_sastate.sa_saved_iv[i] =
+					cpu_to_le32(re->re_sastate.sa_saved_iv[i]);
+			cmd0 |= SAFE_SA_CMD0_IVLD_STATE;
+		}
+		/*
+		 * For basic encryption use the zero pad algorithm.
+		 * This pads results to an 8-byte boundary and
+		 * suppresses padding verification for inbound (i.e.
+		 * decrypt) operations.
+		 *
+		 * NB: Not sure if the 8-byte pad boundary is a problem.
+		 */
+		cmd0 |= SAFE_SA_CMD0_PAD_ZERO;
+
+		/* XXX assert key bufs have the same size */
+		bcopy(ses->ses_key, sa->sa_key, sizeof(sa->sa_key));
+	}
+
+	if (maccrd) {
+		if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
+			safe_setup_mackey(ses, maccrd->crd_alg,
+			    maccrd->crd_key, maccrd->crd_klen / 8);
+		}
+
+		if (maccrd->crd_alg == CRYPTO_MD5_HMAC) {
+			cmd0 |= SAFE_SA_CMD0_MD5;
+			cmd1 |= SAFE_SA_CMD1_HMAC;	/* NB: enable HMAC */
+		} else if (maccrd->crd_alg == CRYPTO_SHA1_HMAC) {
+			cmd0 |= SAFE_SA_CMD0_SHA1;
+			cmd1 |= SAFE_SA_CMD1_HMAC;	/* NB: enable HMAC */
+		} else {
+			cmd0 |= SAFE_SA_CMD0_HASH_NULL;
+		}
+		/*
+		 * Digest data is loaded from the SA and the hash
+		 * result is saved to the state block where we
+		 * retrieve it for return to the caller.
+		 */
+		/* XXX assert digest bufs have the same size */
+		bcopy(ses->ses_hminner, sa->sa_indigest,
+			sizeof(sa->sa_indigest));
+		bcopy(ses->ses_hmouter, sa->sa_outdigest,
+			sizeof(sa->sa_outdigest));
+
+		cmd0 |= SAFE_SA_CMD0_HSLD_SA | SAFE_SA_CMD0_SAVEHASH;
+		re->re_flags |= SAFE_QFLAGS_COPYOUTICV;
+	}
+
+	if (enccrd && maccrd) {
+		/*
+		 * The offset from hash data to the start of
+		 * crypt data is the difference in the skips.
+		 */
+		bypass = maccrd->crd_skip;
+		coffset = enccrd->crd_skip - maccrd->crd_skip;
+		if (coffset < 0) {
+			DPRINTF(("%s: hash does not precede crypt; "
+				"mac skip %u enc skip %u\n",
+				__func__, maccrd->crd_skip, enccrd->crd_skip));
+			safestats.st_skipmismatch++;
+			err = EINVAL;
+			goto errout;
+		}
+		oplen = enccrd->crd_skip + enccrd->crd_len;
+		if (maccrd->crd_skip + maccrd->crd_len != oplen) {
+			DPRINTF(("%s: hash amount %u != crypt amount %u\n",
+				__func__, maccrd->crd_skip + maccrd->crd_len,
+				oplen));
+			safestats.st_lenmismatch++;
+			err = EINVAL;
+			goto errout;
+		}
+#ifdef SAFE_DEBUG
+		if (debug) {
+			printf("mac: skip %d, len %d, inject %d\n",
+			    maccrd->crd_skip, maccrd->crd_len,
+			    maccrd->crd_inject);
+			printf("enc: skip %d, len %d, inject %d\n",
+			    enccrd->crd_skip, enccrd->crd_len,
+			    enccrd->crd_inject);
+			printf("bypass %d coffset %d oplen %d\n",
+				bypass, coffset, oplen);
+		}
+#endif
+		if (coffset & 3) {	/* offset must be 32-bit aligned */
+			DPRINTF(("%s: coffset %u misaligned\n",
+				__func__, coffset));
+			safestats.st_coffmisaligned++;
+			err = EINVAL;
+			goto errout;
+		}
+		coffset >>= 2;
+		if (coffset > 255) {	/* offset must be <256 dwords */
+			DPRINTF(("%s: coffset %u too big\n",
+				__func__, coffset));
+			safestats.st_cofftoobig++;
+			err = EINVAL;
+			goto errout;
+		}
+		/*
+		 * Tell the hardware to copy the header to the output.
+		 * The header is defined as the data from the end of
+		 * the bypass to the start of data to be encrypted. 
+		 * Typically this is the inline IV.  Note that you need
+		 * to do this even if src+dst are the same; it appears
+		 * that w/o this bit the crypted data is written
+		 * immediately after the bypass data.
+		 */
+		cmd1 |= SAFE_SA_CMD1_HDRCOPY;
+		/*
+		 * Disable IP header mutable bit handling.  This is
+		 * needed to get correct HMAC calculations.
+		 */
+		cmd1 |= SAFE_SA_CMD1_MUTABLE;
+	} else {
+		if (enccrd) {
+			bypass = enccrd->crd_skip;
+			oplen = bypass + enccrd->crd_len;
+		} else {
+			bypass = maccrd->crd_skip;
+			oplen = bypass + maccrd->crd_len;
+		}
+		coffset = 0;
+	}
+	/* XXX verify multiple of 4 when using s/g */
+	if (bypass > 96) {		/* bypass offset must be <= 96 bytes */
+		DPRINTF(("%s: bypass %u too big\n", __func__, bypass));
+		safestats.st_bypasstoobig++;
+		err = EINVAL;
+		goto errout;
+	}
+
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		if (pci_map_skb(sc, &re->re_src, re->re_src_skb)) {
+			safestats.st_noload++;
+			err = ENOMEM;
+			goto errout;
+		}
+	} else if (crp->crp_flags & CRYPTO_F_IOV) {
+		if (pci_map_uio(sc, &re->re_src, re->re_src_io)) {
+			safestats.st_noload++;
+			err = ENOMEM;
+			goto errout;
+		}
+	}
+	nicealign = safe_dmamap_aligned(sc, &re->re_src);
+	uniform = safe_dmamap_uniform(sc, &re->re_src);
+
+	DPRINTF(("src nicealign %u uniform %u nsegs %u\n",
+		nicealign, uniform, re->re_src.nsegs));
+	if (re->re_src.nsegs > 1) {
+		re->re_desc.d_src = sc->sc_spalloc.dma_paddr +
+			((caddr_t) sc->sc_spfree - (caddr_t) sc->sc_spring);
+		for (i = 0; i < re->re_src_nsegs; i++) {
+			/* NB: no need to check if there's space */
+			pd = sc->sc_spfree;
+			if (++(sc->sc_spfree) == sc->sc_springtop)
+				sc->sc_spfree = sc->sc_spring;
+
+			KASSERT((pd->pd_flags&3) == 0 ||
+				(pd->pd_flags&3) == SAFE_PD_DONE,
+				("bogus source particle descriptor; flags %x",
+				pd->pd_flags));
+			pd->pd_addr = re->re_src_segs[i].ds_addr;
+			pd->pd_size = re->re_src_segs[i].ds_len;
+			pd->pd_flags = SAFE_PD_READY;
+		}
+		cmd0 |= SAFE_SA_CMD0_IGATHER;
+	} else {
+		/*
+		 * No need for gather, reference the operand directly.
+		 */
+		re->re_desc.d_src = re->re_src_segs[0].ds_addr;
+	}
+
+	if (enccrd == NULL && maccrd != NULL) {
+		/*
+		 * Hash op; no destination needed.
+		 */
+	} else {
+		if (crp->crp_flags & (CRYPTO_F_IOV|CRYPTO_F_SKBUF)) {
+			if (!nicealign) {
+				safestats.st_iovmisaligned++;
+				err = EINVAL;
+				goto errout;
+			}
+			if (uniform != 1) {
+				device_printf(sc->sc_dev, "!uniform source\n");
+				if (!uniform) {
+					/*
+					 * There's no way to handle the DMA
+					 * requirements with this uio.  We
+					 * could create a separate DMA area for
+					 * the result and then copy it back,
+					 * but for now we just bail and return
+					 * an error.  Note that uio requests
+					 * > SAFE_MAX_DSIZE are handled because
+					 * the DMA map and segment list for the
+					 * destination wil result in a
+					 * destination particle list that does
+					 * the necessary scatter DMA.
+					 */ 
+					safestats.st_iovnotuniform++;
+					err = EINVAL;
+					goto errout;
+				}
+			} else
+				re->re_dst = re->re_src;
+		} else {
+			safestats.st_badflags++;
+			err = EINVAL;
+			goto errout;
+		}
+
+		if (re->re_dst.nsegs > 1) {
+			re->re_desc.d_dst = sc->sc_dpalloc.dma_paddr +
+			    ((caddr_t) sc->sc_dpfree - (caddr_t) sc->sc_dpring);
+			for (i = 0; i < re->re_dst_nsegs; i++) {
+				pd = sc->sc_dpfree;
+				KASSERT((pd->pd_flags&3) == 0 ||
+					(pd->pd_flags&3) == SAFE_PD_DONE,
+					("bogus dest particle descriptor; flags %x",
+						pd->pd_flags));
+				if (++(sc->sc_dpfree) == sc->sc_dpringtop)
+					sc->sc_dpfree = sc->sc_dpring;
+				pd->pd_addr = re->re_dst_segs[i].ds_addr;
+				pd->pd_flags = SAFE_PD_READY;
+			}
+			cmd0 |= SAFE_SA_CMD0_OSCATTER;
+		} else {
+			/*
+			 * No need for scatter, reference the operand directly.
+			 */
+			re->re_desc.d_dst = re->re_dst_segs[0].ds_addr;
+		}
+	}
+
+	/*
+	 * All done with setup; fillin the SA command words
+	 * and the packet engine descriptor.  The operation
+	 * is now ready for submission to the hardware.
+	 */
+	sa->sa_cmd0 = cmd0 | SAFE_SA_CMD0_IPCI | SAFE_SA_CMD0_OPCI;
+	sa->sa_cmd1 = cmd1
+		    | (coffset << SAFE_SA_CMD1_OFFSET_S)
+		    | SAFE_SA_CMD1_SAREV1	/* Rev 1 SA data structure */
+		    | SAFE_SA_CMD1_SRPCI
+		    ;
+	/*
+	 * NB: the order of writes is important here.  In case the
+	 * chip is scanning the ring because of an outstanding request
+	 * it might nab this one too.  In that case we need to make
+	 * sure the setup is complete before we write the length
+	 * field of the descriptor as it signals the descriptor is
+	 * ready for processing.
+	 */
+	re->re_desc.d_csr = SAFE_PE_CSR_READY | SAFE_PE_CSR_SAPCI;
+	if (maccrd)
+		re->re_desc.d_csr |= SAFE_PE_CSR_LOADSA | SAFE_PE_CSR_HASHFINAL;
+	wmb();
+	re->re_desc.d_len = oplen
+			  | SAFE_PE_LEN_READY
+			  | (bypass << SAFE_PE_LEN_BYPASS_S)
+			  ;
+
+	safestats.st_ipackets++;
+	safestats.st_ibytes += oplen;
+
+	if (++(sc->sc_front) == sc->sc_ringtop)
+		sc->sc_front = sc->sc_ring;
+
+	/* XXX honor batching */
+	safe_feed(sc, re);
+	spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
+	return (0);
+
+errout:
+	if (re->re_src.map != re->re_dst.map)
+		pci_unmap_operand(sc, &re->re_dst);
+	if (re->re_src.map)
+		pci_unmap_operand(sc, &re->re_src);
+	spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
+	if (err != ERESTART) {
+		crp->crp_etype = err;
+		crypto_done(crp);
+	} else {
+		sc->sc_needwakeup |= CRYPTO_SYMQ;
+	}
+	return (err);
+}
+
+static void
+safe_callback(struct safe_softc *sc, struct safe_ringentry *re)
+{
+	struct cryptop *crp = (struct cryptop *)re->re_crp;
+	struct cryptodesc *crd;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	safestats.st_opackets++;
+	safestats.st_obytes += re->re_dst.mapsize;
+
+	if (re->re_desc.d_csr & SAFE_PE_CSR_STATUS) {
+		device_printf(sc->sc_dev, "csr 0x%x cmd0 0x%x cmd1 0x%x\n",
+			re->re_desc.d_csr,
+			re->re_sa.sa_cmd0, re->re_sa.sa_cmd1);
+		safestats.st_peoperr++;
+		crp->crp_etype = EIO;		/* something more meaningful? */
+	}
+
+	if (re->re_dst.map != NULL && re->re_dst.map != re->re_src.map)
+		pci_unmap_operand(sc, &re->re_dst);
+	pci_unmap_operand(sc, &re->re_src);
+
+	/* 
+	 * If result was written to a differet mbuf chain, swap
+	 * it in as the return value and reclaim the original.
+	 */
+	if ((crp->crp_flags & CRYPTO_F_SKBUF) && re->re_src_skb != re->re_dst_skb) {
+		device_printf(sc->sc_dev, "no CRYPTO_F_SKBUF swapping support\n");
+		/* kfree_skb(skb) */
+		/* crp->crp_buf = (caddr_t)re->re_dst_skb */
+		return;
+	}
+
+	if (re->re_flags & SAFE_QFLAGS_COPYOUTIV) {
+		/* copy out IV for future use */
+		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+			int i;
+			int ivsize;
+
+			if (crd->crd_alg == CRYPTO_DES_CBC ||
+			    crd->crd_alg == CRYPTO_3DES_CBC) {
+				ivsize = 2*sizeof(u_int32_t);
+			} else if (crd->crd_alg == CRYPTO_AES_CBC) {
+				ivsize = 4*sizeof(u_int32_t);
+			} else
+				continue;
+			crypto_copydata(crp->crp_flags, crp->crp_buf,
+			    crd->crd_skip + crd->crd_len - ivsize, ivsize,
+			    (caddr_t)sc->sc_sessions[re->re_sesn].ses_iv);
+			for (i = 0;
+					i < ivsize/sizeof(sc->sc_sessions[re->re_sesn].ses_iv[0]);
+					i++)
+				sc->sc_sessions[re->re_sesn].ses_iv[i] =
+					cpu_to_le32(sc->sc_sessions[re->re_sesn].ses_iv[i]);
+			break;
+		}
+	}
+
+	if (re->re_flags & SAFE_QFLAGS_COPYOUTICV) {
+		/* copy out ICV result */
+		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+			if (!(crd->crd_alg == CRYPTO_MD5_HMAC ||
+			    crd->crd_alg == CRYPTO_SHA1_HMAC ||
+			    crd->crd_alg == CRYPTO_NULL_HMAC))
+				continue;
+			if (crd->crd_alg == CRYPTO_SHA1_HMAC) {
+				/*
+				 * SHA-1 ICV's are byte-swapped; fix 'em up
+				 * before copy them to their destination.
+				 */
+				re->re_sastate.sa_saved_indigest[0] =
+					cpu_to_be32(re->re_sastate.sa_saved_indigest[0]);
+				re->re_sastate.sa_saved_indigest[1] = 
+					cpu_to_be32(re->re_sastate.sa_saved_indigest[1]);
+				re->re_sastate.sa_saved_indigest[2] =
+					cpu_to_be32(re->re_sastate.sa_saved_indigest[2]);
+			} else {
+				re->re_sastate.sa_saved_indigest[0] =
+					cpu_to_le32(re->re_sastate.sa_saved_indigest[0]);
+				re->re_sastate.sa_saved_indigest[1] = 
+					cpu_to_le32(re->re_sastate.sa_saved_indigest[1]);
+				re->re_sastate.sa_saved_indigest[2] =
+					cpu_to_le32(re->re_sastate.sa_saved_indigest[2]);
+			}
+			crypto_copyback(crp->crp_flags, crp->crp_buf,
+			    crd->crd_inject,
+			    sc->sc_sessions[re->re_sesn].ses_mlen,
+			    (caddr_t)re->re_sastate.sa_saved_indigest);
+			break;
+		}
+	}
+	crypto_done(crp);
+}
+
+
+#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
+#define	SAFE_RNG_MAXWAIT	1000
+
+static void
+safe_rng_init(struct safe_softc *sc)
+{
+	u_int32_t w, v;
+	int i;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	WRITE_REG(sc, SAFE_RNG_CTRL, 0);
+	/* use default value according to the manual */
+	WRITE_REG(sc, SAFE_RNG_CNFG, 0x834);	/* magic from SafeNet */
+	WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
+
+	/*
+	 * There is a bug in rev 1.0 of the 1140 that when the RNG
+	 * is brought out of reset the ready status flag does not
+	 * work until the RNG has finished its internal initialization.
+	 *
+	 * So in order to determine the device is through its
+	 * initialization we must read the data register, using the
+	 * status reg in the read in case it is initialized.  Then read
+	 * the data register until it changes from the first read.
+	 * Once it changes read the data register until it changes
+	 * again.  At this time the RNG is considered initialized. 
+	 * This could take between 750ms - 1000ms in time.
+	 */
+	i = 0;
+	w = READ_REG(sc, SAFE_RNG_OUT);
+	do {
+		v = READ_REG(sc, SAFE_RNG_OUT);
+		if (v != w) {
+			w = v;
+			break;
+		}
+		DELAY(10);
+	} while (++i < SAFE_RNG_MAXWAIT);
+
+	/* Wait Until data changes again */
+	i = 0;
+	do {
+		v = READ_REG(sc, SAFE_RNG_OUT);
+		if (v != w)
+			break;
+		DELAY(10);
+	} while (++i < SAFE_RNG_MAXWAIT);
+}
+
+static __inline void
+safe_rng_disable_short_cycle(struct safe_softc *sc)
+{
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	WRITE_REG(sc, SAFE_RNG_CTRL,
+		READ_REG(sc, SAFE_RNG_CTRL) &~ SAFE_RNG_CTRL_SHORTEN);
+}
+
+static __inline void
+safe_rng_enable_short_cycle(struct safe_softc *sc)
+{
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	WRITE_REG(sc, SAFE_RNG_CTRL, 
+		READ_REG(sc, SAFE_RNG_CTRL) | SAFE_RNG_CTRL_SHORTEN);
+}
+
+static __inline u_int32_t
+safe_rng_read(struct safe_softc *sc)
+{
+	int i;
+
+	i = 0;
+	while (READ_REG(sc, SAFE_RNG_STAT) != 0 && ++i < SAFE_RNG_MAXWAIT)
+		;
+	return READ_REG(sc, SAFE_RNG_OUT);
+}
+
+static int
+safe_read_random(void *arg, u_int32_t *buf, int maxwords)
+{
+	struct safe_softc *sc = (struct safe_softc *) arg;
+	int i, rc;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+	
+	safestats.st_rng++;
+	/*
+	 * Fetch the next block of data.
+	 */
+	if (maxwords > safe_rngbufsize)
+		maxwords = safe_rngbufsize;
+	if (maxwords > SAFE_RNG_MAXBUFSIZ)
+		maxwords = SAFE_RNG_MAXBUFSIZ;
+retry:
+	/* read as much as we can */
+	for (rc = 0; rc < maxwords; rc++) {
+		if (READ_REG(sc, SAFE_RNG_STAT) != 0)
+			break;
+		buf[rc] = READ_REG(sc, SAFE_RNG_OUT);
+	}
+	if (rc == 0)
+		return 0;
+	/*
+	 * Check the comparator alarm count and reset the h/w if
+	 * it exceeds our threshold.  This guards against the
+	 * hardware oscillators resonating with external signals.
+	 */
+	if (READ_REG(sc, SAFE_RNG_ALM_CNT) > safe_rngmaxalarm) {
+		u_int32_t freq_inc, w;
+
+		DPRINTF(("%s: alarm count %u exceeds threshold %u\n", __func__,
+			(unsigned)READ_REG(sc, SAFE_RNG_ALM_CNT), safe_rngmaxalarm));
+		safestats.st_rngalarm++;
+		safe_rng_enable_short_cycle(sc);
+		freq_inc = 18;
+		for (i = 0; i < 64; i++) {
+			w = READ_REG(sc, SAFE_RNG_CNFG);
+			freq_inc = ((w + freq_inc) & 0x3fL);
+			w = ((w & ~0x3fL) | freq_inc);
+			WRITE_REG(sc, SAFE_RNG_CNFG, w);
+
+			WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
+
+			(void) safe_rng_read(sc);
+			DELAY(25);
+
+			if (READ_REG(sc, SAFE_RNG_ALM_CNT) == 0) {
+				safe_rng_disable_short_cycle(sc);
+				goto retry;
+			}
+			freq_inc = 1;
+		}
+		safe_rng_disable_short_cycle(sc);
+	} else
+		WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
+
+	return(rc);
+}
+#endif /* defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG) */
+
+
+/*
+ * Resets the board.  Values in the regesters are left as is
+ * from the reset (i.e. initial values are assigned elsewhere).
+ */
+static void
+safe_reset_board(struct safe_softc *sc)
+{
+	u_int32_t v;
+	/*
+	 * Reset the device.  The manual says no delay
+	 * is needed between marking and clearing reset.
+	 */
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	v = READ_REG(sc, SAFE_PE_DMACFG) &~
+		(SAFE_PE_DMACFG_PERESET | SAFE_PE_DMACFG_PDRRESET |
+		 SAFE_PE_DMACFG_SGRESET);
+	WRITE_REG(sc, SAFE_PE_DMACFG, v
+				    | SAFE_PE_DMACFG_PERESET
+				    | SAFE_PE_DMACFG_PDRRESET
+				    | SAFE_PE_DMACFG_SGRESET);
+	WRITE_REG(sc, SAFE_PE_DMACFG, v);
+}
+
+/*
+ * Initialize registers we need to touch only once.
+ */
+static void
+safe_init_board(struct safe_softc *sc)
+{
+	u_int32_t v, dwords;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	v = READ_REG(sc, SAFE_PE_DMACFG);
+	v &=~ (   SAFE_PE_DMACFG_PEMODE
+			| SAFE_PE_DMACFG_FSENA		/* failsafe enable */
+			| SAFE_PE_DMACFG_GPRPCI		/* gather ring on PCI */
+			| SAFE_PE_DMACFG_SPRPCI		/* scatter ring on PCI */
+			| SAFE_PE_DMACFG_ESDESC		/* endian-swap descriptors */
+			| SAFE_PE_DMACFG_ESPDESC	/* endian-swap part. desc's */
+			| SAFE_PE_DMACFG_ESSA		/* endian-swap SA's */
+			| SAFE_PE_DMACFG_ESPACKET	/* swap the packet data */
+		  );
+	v |= SAFE_PE_DMACFG_FSENA		/* failsafe enable */
+	  |  SAFE_PE_DMACFG_GPRPCI		/* gather ring on PCI */
+	  |  SAFE_PE_DMACFG_SPRPCI		/* scatter ring on PCI */
+	  |  SAFE_PE_DMACFG_ESDESC		/* endian-swap descriptors */
+	  |  SAFE_PE_DMACFG_ESPDESC		/* endian-swap part. desc's */
+	  |  SAFE_PE_DMACFG_ESSA		/* endian-swap SA's */
+#if 0
+	  |  SAFE_PE_DMACFG_ESPACKET    /* swap the packet data */
+#endif
+	  ;
+	WRITE_REG(sc, SAFE_PE_DMACFG, v);
+
+#ifdef __BIG_ENDIAN
+	/* tell the safenet that we are 4321 and not 1234 */
+	WRITE_REG(sc, SAFE_ENDIAN, 0xe4e41b1b);
+#endif
+
+	if (sc->sc_chiprev == SAFE_REV(1,0)) {
+		/*
+		 * Avoid large PCI DMA transfers.  Rev 1.0 has a bug where
+		 * "target mode transfers" done while the chip is DMA'ing
+		 * >1020 bytes cause the hardware to lockup.  To avoid this
+		 * we reduce the max PCI transfer size and use small source
+		 * particle descriptors (<= 256 bytes).
+		 */
+		WRITE_REG(sc, SAFE_DMA_CFG, 256);
+		device_printf(sc->sc_dev,
+			"Reduce max DMA size to %u words for rev %u.%u WAR\n",
+			(unsigned) ((READ_REG(sc, SAFE_DMA_CFG)>>2) & 0xff),
+			(unsigned) SAFE_REV_MAJ(sc->sc_chiprev),
+			(unsigned) SAFE_REV_MIN(sc->sc_chiprev));
+		sc->sc_max_dsize = 256;
+	} else {
+		sc->sc_max_dsize = SAFE_MAX_DSIZE;
+	}
+
+	/* NB: operands+results are overlaid */
+	WRITE_REG(sc, SAFE_PE_PDRBASE, sc->sc_ringalloc.dma_paddr);
+	WRITE_REG(sc, SAFE_PE_RDRBASE, sc->sc_ringalloc.dma_paddr);
+	/*
+	 * Configure ring entry size and number of items in the ring.
+	 */
+	KASSERT((sizeof(struct safe_ringentry) % sizeof(u_int32_t)) == 0,
+		("PE ring entry not 32-bit aligned!"));
+	dwords = sizeof(struct safe_ringentry) / sizeof(u_int32_t);
+	WRITE_REG(sc, SAFE_PE_RINGCFG,
+		(dwords << SAFE_PE_RINGCFG_OFFSET_S) | SAFE_MAX_NQUEUE);
+	WRITE_REG(sc, SAFE_PE_RINGPOLL, 0);	/* disable polling */
+
+	WRITE_REG(sc, SAFE_PE_GRNGBASE, sc->sc_spalloc.dma_paddr);
+	WRITE_REG(sc, SAFE_PE_SRNGBASE, sc->sc_dpalloc.dma_paddr);
+	WRITE_REG(sc, SAFE_PE_PARTSIZE,
+		(SAFE_TOTAL_DPART<<16) | SAFE_TOTAL_SPART);
+	/*
+	 * NB: destination particles are fixed size.  We use
+	 *     an mbuf cluster and require all results go to
+	 *     clusters or smaller.
+	 */
+	WRITE_REG(sc, SAFE_PE_PARTCFG, sc->sc_max_dsize);
+
+	/* it's now safe to enable PE mode, do it */
+	WRITE_REG(sc, SAFE_PE_DMACFG, v | SAFE_PE_DMACFG_PEMODE);
+
+	/*
+	 * Configure hardware to use level-triggered interrupts and
+	 * to interrupt after each descriptor is processed.
+	 */
+	WRITE_REG(sc, SAFE_HI_CFG, SAFE_HI_CFG_LEVEL);
+	WRITE_REG(sc, SAFE_HI_CLR, 0xffffffff);
+	WRITE_REG(sc, SAFE_HI_DESC_CNT, 1);
+	WRITE_REG(sc, SAFE_HI_MASK, SAFE_INT_PE_DDONE | SAFE_INT_PE_ERROR);
+}
+
+
+/*
+ * Clean up after a chip crash.
+ * It is assumed that the caller in splimp()
+ */
+static void
+safe_cleanchip(struct safe_softc *sc)
+{
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (sc->sc_nqchip != 0) {
+		struct safe_ringentry *re = sc->sc_back;
+
+		while (re != sc->sc_front) {
+			if (re->re_desc.d_csr != 0)
+				safe_free_entry(sc, re);
+			if (++re == sc->sc_ringtop)
+				re = sc->sc_ring;
+		}
+		sc->sc_back = re;
+		sc->sc_nqchip = 0;
+	}
+}
+
+/*
+ * free a safe_q
+ * It is assumed that the caller is within splimp().
+ */
+static int
+safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re)
+{
+	struct cryptop *crp;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	/*
+	 * Free header MCR
+	 */
+	if ((re->re_dst_skb != NULL) && (re->re_src_skb != re->re_dst_skb))
+#ifdef NOTYET
+		m_freem(re->re_dst_m);
+#else
+		printk("%s,%d: SKB not supported\n", __FILE__, __LINE__);
+#endif
+
+	crp = (struct cryptop *)re->re_crp;
+	
+	re->re_desc.d_csr = 0;
+	
+	crp->crp_etype = EFAULT;
+	crypto_done(crp);
+	return(0);
+}
+
+/*
+ * Routine to reset the chip and clean up.
+ * It is assumed that the caller is in splimp()
+ */
+static void
+safe_totalreset(struct safe_softc *sc)
+{
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	safe_reset_board(sc);
+	safe_init_board(sc);
+	safe_cleanchip(sc);
+}
+
+/*
+ * Is the operand suitable aligned for direct DMA.  Each
+ * segment must be aligned on a 32-bit boundary and all
+ * but the last segment must be a multiple of 4 bytes.
+ */
+static int
+safe_dmamap_aligned(struct safe_softc *sc, const struct safe_operand *op)
+{
+	int i;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	for (i = 0; i < op->nsegs; i++) {
+		if (op->segs[i].ds_addr & 3)
+			return (0);
+		if (i != (op->nsegs - 1) && (op->segs[i].ds_len & 3))
+			return (0);
+	}
+	return (1);
+}
+
+/*
+ * Is the operand suitable for direct DMA as the destination
+ * of an operation.  The hardware requires that each ``particle''
+ * but the last in an operation result have the same size.  We
+ * fix that size at SAFE_MAX_DSIZE bytes.  This routine returns
+ * 0 if some segment is not a multiple of of this size, 1 if all
+ * segments are exactly this size, or 2 if segments are at worst
+ * a multple of this size.
+ */
+static int
+safe_dmamap_uniform(struct safe_softc *sc, const struct safe_operand *op)
+{
+	int result = 1;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (op->nsegs > 0) {
+		int i;
+
+		for (i = 0; i < op->nsegs-1; i++) {
+			if (op->segs[i].ds_len % sc->sc_max_dsize)
+				return (0);
+			if (op->segs[i].ds_len != sc->sc_max_dsize)
+				result = 2;
+		}
+	}
+	return (result);
+}
+
+static int
+safe_kprocess(device_t dev, struct cryptkop *krp, int hint)
+{
+	struct safe_softc *sc = device_get_softc(dev);
+	struct safe_pkq *q;
+	unsigned long flags;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (sc == NULL) {
+		krp->krp_status = EINVAL;
+		goto err;
+	}
+
+	if (krp->krp_op != CRK_MOD_EXP) {
+		krp->krp_status = EOPNOTSUPP;
+		goto err;
+	}
+
+	q = (struct safe_pkq *) kmalloc(sizeof(*q), GFP_KERNEL);
+	if (q == NULL) {
+		krp->krp_status = ENOMEM;
+		goto err;
+	}
+	memset(q, 0, sizeof(*q));
+	q->pkq_krp = krp;
+	INIT_LIST_HEAD(&q->pkq_list);
+
+	spin_lock_irqsave(&sc->sc_pkmtx, flags);
+	list_add_tail(&q->pkq_list, &sc->sc_pkq);
+	safe_kfeed(sc);
+	spin_unlock_irqrestore(&sc->sc_pkmtx, flags);
+	return (0);
+
+err:
+	crypto_kdone(krp);
+	return (0);
+}
+
+#define	SAFE_CRK_PARAM_BASE	0
+#define	SAFE_CRK_PARAM_EXP	1
+#define	SAFE_CRK_PARAM_MOD	2
+
+static int
+safe_kstart(struct safe_softc *sc)
+{
+	struct cryptkop *krp = sc->sc_pkq_cur->pkq_krp;
+	int exp_bits, mod_bits, base_bits;
+	u_int32_t op, a_off, b_off, c_off, d_off;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (krp->krp_iparams < 3 || krp->krp_oparams != 1) {
+		krp->krp_status = EINVAL;
+		return (1);
+	}
+
+	base_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_BASE]);
+	if (base_bits > 2048)
+		goto too_big;
+	if (base_bits <= 0)		/* 5. base not zero */
+		goto too_small;
+
+	exp_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_EXP]);
+	if (exp_bits > 2048)
+		goto too_big;
+	if (exp_bits <= 0)		/* 1. exponent word length > 0 */
+		goto too_small;		/* 4. exponent not zero */
+
+	mod_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_MOD]);
+	if (mod_bits > 2048)
+		goto too_big;
+	if (mod_bits <= 32)		/* 2. modulus word length > 1 */
+		goto too_small;		/* 8. MSW of modulus != zero */
+	if (mod_bits < exp_bits)	/* 3 modulus len >= exponent len */
+		goto too_small;
+	if ((krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p[0] & 1) == 0)
+		goto bad_domain;	/* 6. modulus is odd */
+	if (mod_bits > krp->krp_param[krp->krp_iparams].crp_nbits)
+		goto too_small;		/* make sure result will fit */
+
+	/* 7. modulus > base */
+	if (mod_bits < base_bits)
+		goto too_small;
+	if (mod_bits == base_bits) {
+		u_int8_t *basep, *modp;
+		int i;
+
+		basep = krp->krp_param[SAFE_CRK_PARAM_BASE].crp_p +
+		    ((base_bits + 7) / 8) - 1;
+		modp = krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p +
+		    ((mod_bits + 7) / 8) - 1;
+		
+		for (i = 0; i < (mod_bits + 7) / 8; i++, basep--, modp--) {
+			if (*modp < *basep)
+				goto too_small;
+			if (*modp > *basep)
+				break;
+		}
+	}
+
+	/* And on the 9th step, he rested. */
+
+	WRITE_REG(sc, SAFE_PK_A_LEN, (exp_bits + 31) / 32);
+	WRITE_REG(sc, SAFE_PK_B_LEN, (mod_bits + 31) / 32);
+	if (mod_bits > 1024) {
+		op = SAFE_PK_FUNC_EXP4;
+		a_off = 0x000;
+		b_off = 0x100;
+		c_off = 0x200;
+		d_off = 0x300;
+	} else {
+		op = SAFE_PK_FUNC_EXP16;
+		a_off = 0x000;
+		b_off = 0x080;
+		c_off = 0x100;
+		d_off = 0x180;
+	}
+	sc->sc_pk_reslen = b_off - a_off;
+	sc->sc_pk_resoff = d_off;
+
+	/* A is exponent, B is modulus, C is base, D is result */
+	safe_kload_reg(sc, a_off, b_off - a_off,
+	    &krp->krp_param[SAFE_CRK_PARAM_EXP]);
+	WRITE_REG(sc, SAFE_PK_A_ADDR, a_off >> 2);
+	safe_kload_reg(sc, b_off, b_off - a_off,
+	    &krp->krp_param[SAFE_CRK_PARAM_MOD]);
+	WRITE_REG(sc, SAFE_PK_B_ADDR, b_off >> 2);
+	safe_kload_reg(sc, c_off, b_off - a_off,
+	    &krp->krp_param[SAFE_CRK_PARAM_BASE]);
+	WRITE_REG(sc, SAFE_PK_C_ADDR, c_off >> 2);
+	WRITE_REG(sc, SAFE_PK_D_ADDR, d_off >> 2);
+
+	WRITE_REG(sc, SAFE_PK_FUNC, op | SAFE_PK_FUNC_RUN);
+
+	return (0);
+
+too_big:
+	krp->krp_status = E2BIG;
+	return (1);
+too_small:
+	krp->krp_status = ERANGE;
+	return (1);
+bad_domain:
+	krp->krp_status = EDOM;
+	return (1);
+}
+
+static int
+safe_ksigbits(struct safe_softc *sc, struct crparam *cr)
+{
+	u_int plen = (cr->crp_nbits + 7) / 8;
+	int i, sig = plen * 8;
+	u_int8_t c, *p = cr->crp_p;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	for (i = plen - 1; i >= 0; i--) {
+		c = p[i];
+		if (c != 0) {
+			while ((c & 0x80) == 0) {
+				sig--;
+				c <<= 1;
+			}
+			break;
+		}
+		sig -= 8;
+	}
+	return (sig);
+}
+
+static void
+safe_kfeed(struct safe_softc *sc)
+{
+	struct safe_pkq *q, *tmp;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (list_empty(&sc->sc_pkq) && sc->sc_pkq_cur == NULL)
+		return;
+	if (sc->sc_pkq_cur != NULL)
+		return;
+	list_for_each_entry_safe(q, tmp, &sc->sc_pkq, pkq_list) {
+		sc->sc_pkq_cur = q;
+		list_del(&q->pkq_list);
+		if (safe_kstart(sc) != 0) {
+			crypto_kdone(q->pkq_krp);
+			kfree(q);
+			sc->sc_pkq_cur = NULL;
+		} else {
+			/* op started, start polling */
+			mod_timer(&sc->sc_pkto, jiffies + 1);
+			break;
+		}
+	}
+}
+
+static void
+safe_kpoll(unsigned long arg)
+{
+	struct safe_softc *sc = NULL;
+	struct safe_pkq *q;
+	struct crparam *res;
+	int i;
+	u_int32_t buf[64];
+	unsigned long flags;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (arg >= SAFE_MAX_CHIPS)
+		return;
+	sc = safe_chip_idx[arg];
+	if (!sc) {
+		DPRINTF(("%s() - bad callback\n", __FUNCTION__));
+		return;
+	}
+
+	spin_lock_irqsave(&sc->sc_pkmtx, flags);
+	if (sc->sc_pkq_cur == NULL)
+		goto out;
+	if (READ_REG(sc, SAFE_PK_FUNC) & SAFE_PK_FUNC_RUN) {
+		/* still running, check back later */
+		mod_timer(&sc->sc_pkto, jiffies + 1);
+		goto out;
+	}
+
+	q = sc->sc_pkq_cur;
+	res = &q->pkq_krp->krp_param[q->pkq_krp->krp_iparams];
+	bzero(buf, sizeof(buf));
+	bzero(res->crp_p, (res->crp_nbits + 7) / 8);
+	for (i = 0; i < sc->sc_pk_reslen >> 2; i++)
+		buf[i] = le32_to_cpu(READ_REG(sc, SAFE_PK_RAM_START +
+		    sc->sc_pk_resoff + (i << 2)));
+	bcopy(buf, res->crp_p, (res->crp_nbits + 7) / 8);
+	/*
+	 * reduce the bits that need copying if possible
+	 */
+	res->crp_nbits = min(res->crp_nbits,sc->sc_pk_reslen * 8);
+	res->crp_nbits = safe_ksigbits(sc, res);
+
+	for (i = SAFE_PK_RAM_START; i < SAFE_PK_RAM_END; i += 4)
+		WRITE_REG(sc, i, 0);
+
+	crypto_kdone(q->pkq_krp);
+	kfree(q);
+	sc->sc_pkq_cur = NULL;
+
+	safe_kfeed(sc);
+out:
+	spin_unlock_irqrestore(&sc->sc_pkmtx, flags);
+}
+
+static void
+safe_kload_reg(struct safe_softc *sc, u_int32_t off, u_int32_t len,
+    struct crparam *n)
+{
+	u_int32_t buf[64], i;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	bzero(buf, sizeof(buf));
+	bcopy(n->crp_p, buf, (n->crp_nbits + 7) / 8);
+
+	for (i = 0; i < len >> 2; i++)
+		WRITE_REG(sc, SAFE_PK_RAM_START + off + (i << 2),
+		    cpu_to_le32(buf[i]));
+}
+
+#ifdef SAFE_DEBUG
+static void
+safe_dump_dmastatus(struct safe_softc *sc, const char *tag)
+{
+	printf("%s: ENDIAN 0x%x SRC 0x%x DST 0x%x STAT 0x%x\n"
+		, tag
+		, READ_REG(sc, SAFE_DMA_ENDIAN)
+		, READ_REG(sc, SAFE_DMA_SRCADDR)
+		, READ_REG(sc, SAFE_DMA_DSTADDR)
+		, READ_REG(sc, SAFE_DMA_STAT)
+	);
+}
+
+static void
+safe_dump_intrstate(struct safe_softc *sc, const char *tag)
+{
+	printf("%s: HI_CFG 0x%x HI_MASK 0x%x HI_DESC_CNT 0x%x HU_STAT 0x%x HM_STAT 0x%x\n"
+		, tag
+		, READ_REG(sc, SAFE_HI_CFG)
+		, READ_REG(sc, SAFE_HI_MASK)
+		, READ_REG(sc, SAFE_HI_DESC_CNT)
+		, READ_REG(sc, SAFE_HU_STAT)
+		, READ_REG(sc, SAFE_HM_STAT)
+	);
+}
+
+static void
+safe_dump_ringstate(struct safe_softc *sc, const char *tag)
+{
+	u_int32_t estat = READ_REG(sc, SAFE_PE_ERNGSTAT);
+
+	/* NB: assume caller has lock on ring */
+	printf("%s: ERNGSTAT %x (next %u) back %lu front %lu\n",
+		tag,
+		estat, (estat >> SAFE_PE_ERNGSTAT_NEXT_S),
+		(unsigned long)(sc->sc_back - sc->sc_ring),
+		(unsigned long)(sc->sc_front - sc->sc_ring));
+}
+
+static void
+safe_dump_request(struct safe_softc *sc, const char* tag, struct safe_ringentry *re)
+{
+	int ix, nsegs;
+
+	ix = re - sc->sc_ring;
+	printf("%s: %p (%u): csr %x src %x dst %x sa %x len %x\n"
+		, tag
+		, re, ix
+		, re->re_desc.d_csr
+		, re->re_desc.d_src
+		, re->re_desc.d_dst
+		, re->re_desc.d_sa
+		, re->re_desc.d_len
+	);
+	if (re->re_src.nsegs > 1) {
+		ix = (re->re_desc.d_src - sc->sc_spalloc.dma_paddr) /
+			sizeof(struct safe_pdesc);
+		for (nsegs = re->re_src.nsegs; nsegs; nsegs--) {
+			printf(" spd[%u] %p: %p size %u flags %x"
+				, ix, &sc->sc_spring[ix]
+				, (caddr_t)(uintptr_t) sc->sc_spring[ix].pd_addr
+				, sc->sc_spring[ix].pd_size
+				, sc->sc_spring[ix].pd_flags
+			);
+			if (sc->sc_spring[ix].pd_size == 0)
+				printf(" (zero!)");
+			printf("\n");
+			if (++ix == SAFE_TOTAL_SPART)
+				ix = 0;
+		}
+	}
+	if (re->re_dst.nsegs > 1) {
+		ix = (re->re_desc.d_dst - sc->sc_dpalloc.dma_paddr) /
+			sizeof(struct safe_pdesc);
+		for (nsegs = re->re_dst.nsegs; nsegs; nsegs--) {
+			printf(" dpd[%u] %p: %p flags %x\n"
+				, ix, &sc->sc_dpring[ix]
+				, (caddr_t)(uintptr_t) sc->sc_dpring[ix].pd_addr
+				, sc->sc_dpring[ix].pd_flags
+			);
+			if (++ix == SAFE_TOTAL_DPART)
+				ix = 0;
+		}
+	}
+	printf("sa: cmd0 %08x cmd1 %08x staterec %x\n",
+		re->re_sa.sa_cmd0, re->re_sa.sa_cmd1, re->re_sa.sa_staterec);
+	printf("sa: key %x %x %x %x %x %x %x %x\n"
+		, re->re_sa.sa_key[0]
+		, re->re_sa.sa_key[1]
+		, re->re_sa.sa_key[2]
+		, re->re_sa.sa_key[3]
+		, re->re_sa.sa_key[4]
+		, re->re_sa.sa_key[5]
+		, re->re_sa.sa_key[6]
+		, re->re_sa.sa_key[7]
+	);
+	printf("sa: indigest %x %x %x %x %x\n"
+		, re->re_sa.sa_indigest[0]
+		, re->re_sa.sa_indigest[1]
+		, re->re_sa.sa_indigest[2]
+		, re->re_sa.sa_indigest[3]
+		, re->re_sa.sa_indigest[4]
+	);
+	printf("sa: outdigest %x %x %x %x %x\n"
+		, re->re_sa.sa_outdigest[0]
+		, re->re_sa.sa_outdigest[1]
+		, re->re_sa.sa_outdigest[2]
+		, re->re_sa.sa_outdigest[3]
+		, re->re_sa.sa_outdigest[4]
+	);
+	printf("sr: iv %x %x %x %x\n"
+		, re->re_sastate.sa_saved_iv[0]
+		, re->re_sastate.sa_saved_iv[1]
+		, re->re_sastate.sa_saved_iv[2]
+		, re->re_sastate.sa_saved_iv[3]
+	);
+	printf("sr: hashbc %u indigest %x %x %x %x %x\n"
+		, re->re_sastate.sa_saved_hashbc
+		, re->re_sastate.sa_saved_indigest[0]
+		, re->re_sastate.sa_saved_indigest[1]
+		, re->re_sastate.sa_saved_indigest[2]
+		, re->re_sastate.sa_saved_indigest[3]
+		, re->re_sastate.sa_saved_indigest[4]
+	);
+}
+
+static void
+safe_dump_ring(struct safe_softc *sc, const char *tag)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sc->sc_ringmtx, flags);
+	printf("\nSafeNet Ring State:\n");
+	safe_dump_intrstate(sc, tag);
+	safe_dump_dmastatus(sc, tag);
+	safe_dump_ringstate(sc, tag);
+	if (sc->sc_nqchip) {
+		struct safe_ringentry *re = sc->sc_back;
+		do {
+			safe_dump_request(sc, tag, re);
+			if (++re == sc->sc_ringtop)
+				re = sc->sc_ring;
+		} while (re != sc->sc_front);
+	}
+	spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
+}
+#endif /* SAFE_DEBUG */
+
+
+static int safe_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+	struct safe_softc *sc = NULL;
+	u32 mem_start, mem_len, cmd;
+	int i, rc, devinfo;
+	dma_addr_t raddr;
+	static int num_chips = 0;
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	if (pci_enable_device(dev) < 0)
+		return(-ENODEV);
+
+	if (!dev->irq) {
+		printk("safe: found device with no IRQ assigned. check BIOS settings!");
+		pci_disable_device(dev);
+		return(-ENODEV);
+	}
+
+	if (pci_set_mwi(dev)) {
+		printk("safe: pci_set_mwi failed!");
+		return(-ENODEV);
+	}
+
+	sc = (struct safe_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
+	if (!sc)
+		return(-ENOMEM);
+	memset(sc, 0, sizeof(*sc));
+
+	softc_device_init(sc, "safe", num_chips, safe_methods);
+
+	sc->sc_irq = -1;
+	sc->sc_cid = -1;
+	sc->sc_pcidev = dev;
+	if (num_chips < SAFE_MAX_CHIPS) {
+		safe_chip_idx[device_get_unit(sc->sc_dev)] = sc;
+		num_chips++;
+	}
+
+	INIT_LIST_HEAD(&sc->sc_pkq);
+	spin_lock_init(&sc->sc_pkmtx);
+
+	pci_set_drvdata(sc->sc_pcidev, sc);
+
+	/* we read its hardware registers as memory */
+	mem_start = pci_resource_start(sc->sc_pcidev, 0);
+	mem_len   = pci_resource_len(sc->sc_pcidev, 0);
+
+	sc->sc_base_addr = (ocf_iomem_t) ioremap(mem_start, mem_len);
+	if (!sc->sc_base_addr) {
+		device_printf(sc->sc_dev, "failed to ioremap 0x%x-0x%x\n",
+				mem_start, mem_start + mem_len - 1);
+		goto out;
+	}
+
+	/* fix up the bus size */
+	if (pci_set_dma_mask(sc->sc_pcidev, DMA_32BIT_MASK)) {
+		device_printf(sc->sc_dev, "No usable DMA configuration, aborting.\n");
+		goto out;
+	}
+	if (pci_set_consistent_dma_mask(sc->sc_pcidev, DMA_32BIT_MASK)) {
+		device_printf(sc->sc_dev, "No usable consistent DMA configuration, aborting.\n");
+		goto out;
+	}
+
+	pci_set_master(sc->sc_pcidev);
+
+	pci_read_config_dword(sc->sc_pcidev, PCI_COMMAND, &cmd);
+
+	if (!(cmd & PCI_COMMAND_MEMORY)) {
+		device_printf(sc->sc_dev, "failed to enable memory mapping\n");
+		goto out;
+	}
+
+	if (!(cmd & PCI_COMMAND_MASTER)) {
+		device_printf(sc->sc_dev, "failed to enable bus mastering\n");
+		goto out;
+	}
+
+	rc = request_irq(dev->irq, safe_intr, IRQF_SHARED, "safe", sc);
+	if (rc) {
+		device_printf(sc->sc_dev, "failed to hook irq %d\n", sc->sc_irq);
+		goto out;
+	}
+	sc->sc_irq = dev->irq;
+
+	sc->sc_chiprev = READ_REG(sc, SAFE_DEVINFO) &
+			(SAFE_DEVINFO_REV_MAJ | SAFE_DEVINFO_REV_MIN);
+
+	/*
+	 * Allocate packet engine descriptors.
+	 */
+	sc->sc_ringalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
+			SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
+			&sc->sc_ringalloc.dma_paddr);
+	if (!sc->sc_ringalloc.dma_vaddr) {
+		device_printf(sc->sc_dev, "cannot allocate PE descriptor ring\n");
+		goto out;
+	}
+
+	/*
+	 * Hookup the static portion of all our data structures.
+	 */
+	sc->sc_ring = (struct safe_ringentry *) sc->sc_ringalloc.dma_vaddr;
+	sc->sc_ringtop = sc->sc_ring + SAFE_MAX_NQUEUE;
+	sc->sc_front = sc->sc_ring;
+	sc->sc_back = sc->sc_ring;
+	raddr = sc->sc_ringalloc.dma_paddr;
+	bzero(sc->sc_ring, SAFE_MAX_NQUEUE * sizeof(struct safe_ringentry));
+	for (i = 0; i < SAFE_MAX_NQUEUE; i++) {
+		struct safe_ringentry *re = &sc->sc_ring[i];
+
+		re->re_desc.d_sa = raddr +
+			offsetof(struct safe_ringentry, re_sa);
+		re->re_sa.sa_staterec = raddr +
+			offsetof(struct safe_ringentry, re_sastate);
+
+		raddr += sizeof (struct safe_ringentry);
+	}
+	spin_lock_init(&sc->sc_ringmtx);
+
+	/*
+	 * Allocate scatter and gather particle descriptors.
+	 */
+	sc->sc_spalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
+			SAFE_TOTAL_SPART * sizeof (struct safe_pdesc),
+			&sc->sc_spalloc.dma_paddr);
+	if (!sc->sc_spalloc.dma_vaddr) {
+		device_printf(sc->sc_dev, "cannot allocate source particle descriptor ring\n");
+		goto out;
+	}
+	sc->sc_spring = (struct safe_pdesc *) sc->sc_spalloc.dma_vaddr;
+	sc->sc_springtop = sc->sc_spring + SAFE_TOTAL_SPART;
+	sc->sc_spfree = sc->sc_spring;
+	bzero(sc->sc_spring, SAFE_TOTAL_SPART * sizeof(struct safe_pdesc));
+
+	sc->sc_dpalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
+			SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
+			&sc->sc_dpalloc.dma_paddr);
+	if (!sc->sc_dpalloc.dma_vaddr) {
+		device_printf(sc->sc_dev, "cannot allocate destination particle descriptor ring\n");
+		goto out;
+	}
+	sc->sc_dpring = (struct safe_pdesc *) sc->sc_dpalloc.dma_vaddr;
+	sc->sc_dpringtop = sc->sc_dpring + SAFE_TOTAL_DPART;
+	sc->sc_dpfree = sc->sc_dpring;
+	bzero(sc->sc_dpring, SAFE_TOTAL_DPART * sizeof(struct safe_pdesc));
+
+	sc->sc_cid = crypto_get_driverid(softc_get_device(sc), CRYPTOCAP_F_HARDWARE);
+	if (sc->sc_cid < 0) {
+		device_printf(sc->sc_dev, "could not get crypto driver id\n");
+		goto out;
+	}
+
+	printf("%s:", device_get_nameunit(sc->sc_dev));
+
+	devinfo = READ_REG(sc, SAFE_DEVINFO);
+	if (devinfo & SAFE_DEVINFO_RNG) {
+		sc->sc_flags |= SAFE_FLAGS_RNG;
+		printf(" rng");
+	}
+	if (devinfo & SAFE_DEVINFO_PKEY) {
+		printf(" key");
+		sc->sc_flags |= SAFE_FLAGS_KEY;
+		crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0);
+#if 0
+		crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0);
+#endif
+		init_timer(&sc->sc_pkto);
+		sc->sc_pkto.function = safe_kpoll;
+		sc->sc_pkto.data = (unsigned long) device_get_unit(sc->sc_dev);
+	}
+	if (devinfo & SAFE_DEVINFO_DES) {
+		printf(" des/3des");
+		crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
+		crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
+	}
+	if (devinfo & SAFE_DEVINFO_AES) {
+		printf(" aes");
+		crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
+	}
+	if (devinfo & SAFE_DEVINFO_MD5) {
+		printf(" md5");
+		crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
+	}
+	if (devinfo & SAFE_DEVINFO_SHA1) {
+		printf(" sha1");
+		crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
+	}
+	printf(" null");
+	crypto_register(sc->sc_cid, CRYPTO_NULL_CBC, 0, 0);
+	crypto_register(sc->sc_cid, CRYPTO_NULL_HMAC, 0, 0);
+	/* XXX other supported algorithms */
+	printf("\n");
+
+	safe_reset_board(sc);		/* reset h/w */
+	safe_init_board(sc);		/* init h/w */
+
+#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
+	if (sc->sc_flags & SAFE_FLAGS_RNG) {
+		safe_rng_init(sc);
+		crypto_rregister(sc->sc_cid, safe_read_random, sc);
+	}
+#endif /* SAFE_NO_RNG */
+
+	return (0);
+
+out:
+	if (sc->sc_cid >= 0)
+		crypto_unregister_all(sc->sc_cid);
+	if (sc->sc_irq != -1)
+		free_irq(sc->sc_irq, sc);
+	if (sc->sc_ringalloc.dma_vaddr)
+		pci_free_consistent(sc->sc_pcidev,
+				SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
+				sc->sc_ringalloc.dma_vaddr, sc->sc_ringalloc.dma_paddr);
+	if (sc->sc_spalloc.dma_vaddr)
+		pci_free_consistent(sc->sc_pcidev,
+				SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
+				sc->sc_spalloc.dma_vaddr, sc->sc_spalloc.dma_paddr);
+	if (sc->sc_dpalloc.dma_vaddr)
+		pci_free_consistent(sc->sc_pcidev,
+				SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
+				sc->sc_dpalloc.dma_vaddr, sc->sc_dpalloc.dma_paddr);
+	kfree(sc);
+	return(-ENODEV);
+}
+
+static void safe_remove(struct pci_dev *dev)
+{
+	struct safe_softc *sc = pci_get_drvdata(dev);
+
+	DPRINTF(("%s()\n", __FUNCTION__));
+
+	/* XXX wait/abort active ops */
+
+	WRITE_REG(sc, SAFE_HI_MASK, 0);		/* disable interrupts */
+
+	del_timer_sync(&sc->sc_pkto);
+
+	crypto_unregister_all(sc->sc_cid);
+
+	safe_cleanchip(sc);
+
+	if (sc->sc_irq != -1)
+		free_irq(sc->sc_irq, sc);
+	if (sc->sc_ringalloc.dma_vaddr)
+		pci_free_consistent(sc->sc_pcidev,
+				SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
+				sc->sc_ringalloc.dma_vaddr, sc->sc_ringalloc.dma_paddr);
+	if (sc->sc_spalloc.dma_vaddr)
+		pci_free_consistent(sc->sc_pcidev,
+				SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
+				sc->sc_spalloc.dma_vaddr, sc->sc_spalloc.dma_paddr);
+	if (sc->sc_dpalloc.dma_vaddr)
+		pci_free_consistent(sc->sc_pcidev,
+				SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
+				sc->sc_dpalloc.dma_vaddr, sc->sc_dpalloc.dma_paddr);
+	sc->sc_irq = -1;
+	sc->sc_ringalloc.dma_vaddr = NULL;
+	sc->sc_spalloc.dma_vaddr = NULL;
+	sc->sc_dpalloc.dma_vaddr = NULL;
+}
+
+static struct pci_device_id safe_pci_tbl[] = {
+	{ PCI_VENDOR_SAFENET, PCI_PRODUCT_SAFEXCEL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, safe_pci_tbl);
+
+static struct pci_driver safe_driver = {
+	.name         = "safe",
+	.id_table     = safe_pci_tbl,
+	.probe        =	safe_probe,
+	.remove       = safe_remove,
+	/* add PM stuff here one day */
+};
+
+static int __init safe_init (void)
+{
+	struct safe_softc *sc = NULL;
+	int rc;
+
+	DPRINTF(("%s(%p)\n", __FUNCTION__, safe_init));
+
+	rc = pci_register_driver(&safe_driver);
+	pci_register_driver_compat(&safe_driver, rc);
+
+	return rc;
+}
+
+static void __exit safe_exit (void)
+{
+	pci_unregister_driver(&safe_driver);
+}
+
+module_init(safe_init);
+module_exit(safe_exit);
+
+MODULE_LICENSE("BSD");
+MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_DESCRIPTION("OCF driver for safenet PCI crypto devices");
diff --git a/crypto/ocf/safe/safereg.h b/crypto/ocf/safe/safereg.h
new file mode 100755
index 0000000..dbaf98f
--- /dev/null
+++ b/crypto/ocf/safe/safereg.h
@@ -0,0 +1,421 @@
+/*-
+ * Copyright (c) 2003 Sam Leffler, Errno Consulting
+ * Copyright (c) 2003 Global Technology Associates, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/safe/safereg.h,v 1.1 2003/07/21 21:46:07 sam Exp $
+ */
+#ifndef _SAFE_SAFEREG_H_
+#define	_SAFE_SAFEREG_H_
+
+/*
+ * Register definitions for SafeNet SafeXcel-1141 crypto device.
+ * Definitions from revision 1.3 (Nov 6 2002) of the User's Manual.
+ */
+
+#define BS_BAR			0x10	/* DMA base address register */
+#define	BS_TRDY_TIMEOUT		0x40	/* TRDY timeout */
+#define	BS_RETRY_TIMEOUT	0x41	/* DMA retry timeout */
+
+#define	PCI_VENDOR_SAFENET	0x16ae		/* SafeNet, Inc. */
+
+/* SafeNet */
+#define	PCI_PRODUCT_SAFEXCEL	0x1141		/* 1141 */
+
+#define	SAFE_PE_CSR		0x0000	/* Packet Enginge Ctrl/Status */
+#define	SAFE_PE_SRC		0x0004	/* Packet Engine Source */
+#define	SAFE_PE_DST		0x0008	/* Packet Engine Destination */
+#define	SAFE_PE_SA		0x000c	/* Packet Engine SA */
+#define	SAFE_PE_LEN		0x0010	/* Packet Engine Length */
+#define	SAFE_PE_DMACFG		0x0040	/* Packet Engine DMA Configuration */
+#define	SAFE_PE_DMASTAT		0x0044	/* Packet Engine DMA Status */
+#define	SAFE_PE_PDRBASE		0x0048	/* Packet Engine Descriptor Ring Base */
+#define	SAFE_PE_RDRBASE		0x004c	/* Packet Engine Result Ring Base */
+#define	SAFE_PE_RINGCFG		0x0050	/* Packet Engine Ring Configuration */
+#define	SAFE_PE_RINGPOLL	0x0054	/* Packet Engine Ring Poll */
+#define	SAFE_PE_IRNGSTAT	0x0058	/* Packet Engine Internal Ring Status */
+#define	SAFE_PE_ERNGSTAT	0x005c	/* Packet Engine External Ring Status */
+#define	SAFE_PE_IOTHRESH	0x0060	/* Packet Engine I/O Threshold */
+#define	SAFE_PE_GRNGBASE	0x0064	/* Packet Engine Gather Ring Base */
+#define	SAFE_PE_SRNGBASE	0x0068	/* Packet Engine Scatter Ring Base */
+#define	SAFE_PE_PARTSIZE	0x006c	/* Packet Engine Particlar Ring Size */
+#define	SAFE_PE_PARTCFG		0x0070	/* Packet Engine Particle Ring Config */
+#define	SAFE_CRYPTO_CTRL	0x0080	/* Crypto Control */
+#define	SAFE_DEVID		0x0084	/* Device ID */
+#define	SAFE_DEVINFO		0x0088	/* Device Info */
+#define	SAFE_HU_STAT		0x00a0	/* Host Unmasked Status */
+#define	SAFE_HM_STAT		0x00a4	/* Host Masked Status (read-only) */
+#define	SAFE_HI_CLR		0x00a4	/* Host Clear Interrupt (write-only) */
+#define	SAFE_HI_MASK		0x00a8	/* Host Mask Control */
+#define	SAFE_HI_CFG		0x00ac	/* Interrupt Configuration */
+#define	SAFE_HI_RD_DESCR	0x00b4	/* Force Descriptor Read */
+#define	SAFE_HI_DESC_CNT	0x00b8	/* Host Descriptor Done Count */
+#define	SAFE_DMA_ENDIAN		0x00c0	/* Master Endian Status */
+#define	SAFE_DMA_SRCADDR	0x00c4	/* DMA Source Address Status */
+#define	SAFE_DMA_DSTADDR	0x00c8	/* DMA Destination Address Status */
+#define	SAFE_DMA_STAT		0x00cc	/* DMA Current Status */
+#define	SAFE_DMA_CFG		0x00d4	/* DMA Configuration/Status */
+#define	SAFE_ENDIAN		0x00e0	/* Endian Configuration */
+#define	SAFE_PK_A_ADDR		0x0800	/* Public Key A Address */
+#define	SAFE_PK_B_ADDR		0x0804	/* Public Key B Address */
+#define	SAFE_PK_C_ADDR		0x0808	/* Public Key C Address */
+#define	SAFE_PK_D_ADDR		0x080c	/* Public Key D Address */
+#define	SAFE_PK_A_LEN		0x0810	/* Public Key A Length */
+#define	SAFE_PK_B_LEN		0x0814	/* Public Key B Length */
+#define	SAFE_PK_SHIFT		0x0818	/* Public Key Shift */
+#define	SAFE_PK_FUNC		0x081c	/* Public Key Function */
+#define SAFE_PK_RAM_START	0x1000	/* Public Key RAM start address */
+#define SAFE_PK_RAM_END		0x1fff	/* Public Key RAM end address */
+
+#define	SAFE_RNG_OUT		0x0100	/* RNG Output */
+#define	SAFE_RNG_STAT		0x0104	/* RNG Status */
+#define	SAFE_RNG_CTRL		0x0108	/* RNG Control */
+#define	SAFE_RNG_A		0x010c	/* RNG A */
+#define	SAFE_RNG_B		0x0110	/* RNG B */
+#define	SAFE_RNG_X_LO		0x0114	/* RNG X [31:0] */
+#define	SAFE_RNG_X_MID		0x0118	/* RNG X [63:32] */
+#define	SAFE_RNG_X_HI		0x011c	/* RNG X [80:64] */
+#define	SAFE_RNG_X_CNTR		0x0120	/* RNG Counter */
+#define	SAFE_RNG_ALM_CNT	0x0124	/* RNG Alarm Count */
+#define	SAFE_RNG_CNFG		0x0128	/* RNG Configuration */
+#define	SAFE_RNG_LFSR1_LO	0x012c	/* RNG LFSR1 [31:0] */
+#define	SAFE_RNG_LFSR1_HI	0x0130	/* RNG LFSR1 [47:32] */
+#define	SAFE_RNG_LFSR2_LO	0x0134	/* RNG LFSR1 [31:0] */
+#define	SAFE_RNG_LFSR2_HI	0x0138	/* RNG LFSR1 [47:32] */
+
+#define	SAFE_PE_CSR_READY	0x00000001	/* ready for processing */
+#define	SAFE_PE_CSR_DONE	0x00000002	/* h/w completed processing */
+#define	SAFE_PE_CSR_LOADSA	0x00000004	/* load SA digests */
+#define	SAFE_PE_CSR_HASHFINAL	0x00000010	/* do hash pad & write result */
+#define	SAFE_PE_CSR_SABUSID	0x000000c0	/* bus id for SA */
+#define	SAFE_PE_CSR_SAPCI	0x00000040	/* PCI bus id for SA */
+#define	SAFE_PE_CSR_NXTHDR	0x0000ff00	/* next hdr value for IPsec */
+#define	SAFE_PE_CSR_FPAD	0x0000ff00	/* fixed pad for basic ops */
+#define	SAFE_PE_CSR_STATUS	0x00ff0000	/* operation result status */
+#define	SAFE_PE_CSR_AUTH_FAIL	0x00010000	/* ICV mismatch (inbound) */
+#define	SAFE_PE_CSR_PAD_FAIL	0x00020000	/* pad verify fail (inbound) */
+#define	SAFE_PE_CSR_SEQ_FAIL	0x00040000	/* sequence number (inbound) */
+#define	SAFE_PE_CSR_XERROR	0x00080000	/* extended error follows */
+#define	SAFE_PE_CSR_XECODE	0x00f00000	/* extended error code */
+#define	SAFE_PE_CSR_XECODE_S	20
+#define	SAFE_PE_CSR_XECODE_BADCMD	0	/* invalid command */
+#define	SAFE_PE_CSR_XECODE_BADALG	1	/* invalid algorithm */
+#define	SAFE_PE_CSR_XECODE_ALGDIS	2	/* algorithm disabled */
+#define	SAFE_PE_CSR_XECODE_ZEROLEN	3	/* zero packet length */
+#define	SAFE_PE_CSR_XECODE_DMAERR	4	/* bus DMA error */
+#define	SAFE_PE_CSR_XECODE_PIPEABORT	5	/* secondary bus DMA error */
+#define	SAFE_PE_CSR_XECODE_BADSPI	6	/* IPsec SPI mismatch */
+#define	SAFE_PE_CSR_XECODE_TIMEOUT	10	/* failsafe timeout */
+#define	SAFE_PE_CSR_PAD		0xff000000	/* ESP padding control/status */
+#define	SAFE_PE_CSR_PAD_MIN	0x00000000	/* minimum IPsec padding */
+#define	SAFE_PE_CSR_PAD_16	0x08000000	/* pad to 16-byte boundary */
+#define	SAFE_PE_CSR_PAD_32	0x10000000	/* pad to 32-byte boundary */
+#define	SAFE_PE_CSR_PAD_64	0x20000000	/* pad to 64-byte boundary */
+#define	SAFE_PE_CSR_PAD_128	0x40000000	/* pad to 128-byte boundary */
+#define	SAFE_PE_CSR_PAD_256	0x80000000	/* pad to 256-byte boundary */
+
+/*
+ * Check the CSR to see if the PE has returned ownership to
+ * the host.  Note that before processing a descriptor this
+ * must be done followed by a check of the SAFE_PE_LEN register
+ * status bits to avoid premature processing of a descriptor
+ * on its way back to the host.
+ */
+#define	SAFE_PE_CSR_IS_DONE(_csr) \
+    (((_csr) & (SAFE_PE_CSR_READY | SAFE_PE_CSR_DONE)) == SAFE_PE_CSR_DONE)
+
+#define	SAFE_PE_LEN_LENGTH	0x000fffff	/* total length (bytes) */
+#define	SAFE_PE_LEN_READY	0x00400000	/* ready for processing */
+#define	SAFE_PE_LEN_DONE	0x00800000	/* h/w completed processing */
+#define	SAFE_PE_LEN_BYPASS	0xff000000	/* bypass offset (bytes) */
+#define	SAFE_PE_LEN_BYPASS_S	24
+
+#define	SAFE_PE_LEN_IS_DONE(_len) \
+    (((_len) & (SAFE_PE_LEN_READY | SAFE_PE_LEN_DONE)) == SAFE_PE_LEN_DONE)
+
+/* NB: these apply to HU_STAT, HM_STAT, HI_CLR, and HI_MASK */
+#define	SAFE_INT_PE_CDONE	0x00000002	/* PE context done */
+#define	SAFE_INT_PE_DDONE	0x00000008	/* PE descriptor done */
+#define	SAFE_INT_PE_ERROR	0x00000010	/* PE error */
+#define	SAFE_INT_PE_ODONE	0x00000020	/* PE operation done */
+
+#define	SAFE_HI_CFG_PULSE	0x00000001	/* use pulse interrupt */
+#define	SAFE_HI_CFG_LEVEL	0x00000000	/* use level interrupt */
+#define	SAFE_HI_CFG_AUTOCLR	0x00000002	/* auto-clear pulse interrupt */
+
+#define	SAFE_ENDIAN_PASS	0x000000e4	/* straight pass-thru */
+#define	SAFE_ENDIAN_SWAB	0x0000001b	/* swap bytes in 32-bit word */
+
+#define	SAFE_PE_DMACFG_PERESET	0x00000001	/* reset packet engine */
+#define	SAFE_PE_DMACFG_PDRRESET	0x00000002	/* reset PDR counters/ptrs */
+#define	SAFE_PE_DMACFG_SGRESET	0x00000004	/* reset scatter/gather cache */
+#define	SAFE_PE_DMACFG_FSENA	0x00000008	/* enable failsafe reset */
+#define	SAFE_PE_DMACFG_PEMODE	0x00000100	/* packet engine mode */
+#define	SAFE_PE_DMACFG_SAPREC	0x00000200	/* SA precedes packet */
+#define	SAFE_PE_DMACFG_PKFOLL	0x00000400	/* packet follows descriptor */
+#define	SAFE_PE_DMACFG_GPRBID	0x00003000	/* gather particle ring busid */
+#define	SAFE_PE_DMACFG_GPRPCI	0x00001000	/* PCI gather particle ring */
+#define	SAFE_PE_DMACFG_SPRBID	0x0000c000	/* scatter part. ring busid */
+#define	SAFE_PE_DMACFG_SPRPCI	0x00004000	/* PCI scatter part. ring */
+#define	SAFE_PE_DMACFG_ESDESC	0x00010000	/* endian swap descriptors */
+#define	SAFE_PE_DMACFG_ESSA	0x00020000	/* endian swap SA data */
+#define	SAFE_PE_DMACFG_ESPACKET	0x00040000	/* endian swap packet data */
+#define	SAFE_PE_DMACFG_ESPDESC	0x00080000	/* endian swap particle desc. */
+#define	SAFE_PE_DMACFG_NOPDRUP	0x00100000	/* supp. PDR ownership update */
+#define	SAFE_PD_EDMACFG_PCIMODE	0x01000000	/* PCI target mode */
+
+#define	SAFE_PE_DMASTAT_PEIDONE	0x00000001	/* PE core input done */
+#define	SAFE_PE_DMASTAT_PEODONE	0x00000002	/* PE core output done */
+#define	SAFE_PE_DMASTAT_ENCDONE	0x00000004	/* encryption done */
+#define	SAFE_PE_DMASTAT_IHDONE	0x00000008	/* inner hash done */
+#define	SAFE_PE_DMASTAT_OHDONE	0x00000010	/* outer hash (HMAC) done */
+#define	SAFE_PE_DMASTAT_PADFLT	0x00000020	/* crypto pad fault */
+#define	SAFE_PE_DMASTAT_ICVFLT	0x00000040	/* ICV fault */
+#define	SAFE_PE_DMASTAT_SPIMIS	0x00000080	/* SPI mismatch */
+#define	SAFE_PE_DMASTAT_CRYPTO	0x00000100	/* crypto engine timeout */
+#define	SAFE_PE_DMASTAT_CQACT	0x00000200	/* command queue active */
+#define	SAFE_PE_DMASTAT_IRACT	0x00000400	/* input request active */
+#define	SAFE_PE_DMASTAT_ORACT	0x00000800	/* output request active */
+#define	SAFE_PE_DMASTAT_PEISIZE	0x003ff000	/* PE input size:32-bit words */
+#define	SAFE_PE_DMASTAT_PEOSIZE	0xffc00000	/* PE out. size:32-bit words */
+
+#define	SAFE_PE_RINGCFG_SIZE	0x000003ff	/* ring size (descriptors) */
+#define	SAFE_PE_RINGCFG_OFFSET	0xffff0000	/* offset btw desc's (dwords) */
+#define	SAFE_PE_RINGCFG_OFFSET_S	16
+
+#define	SAFE_PE_RINGPOLL_POLL	0x00000fff	/* polling frequency/divisor */
+#define	SAFE_PE_RINGPOLL_RETRY	0x03ff0000	/* polling frequency/divisor */
+#define	SAFE_PE_RINGPOLL_CONT	0x80000000	/* continuously poll */
+
+#define	SAFE_PE_IRNGSTAT_CQAVAIL 0x00000001	/* command queue available */
+
+#define	SAFE_PE_ERNGSTAT_NEXT	0x03ff0000	/* index of next packet desc. */
+#define	SAFE_PE_ERNGSTAT_NEXT_S	16
+
+#define	SAFE_PE_IOTHRESH_INPUT	0x000003ff	/* input threshold (dwords) */
+#define	SAFE_PE_IOTHRESH_OUTPUT	0x03ff0000	/* output threshold (dwords) */
+
+#define	SAFE_PE_PARTCFG_SIZE	0x0000ffff	/* scatter particle size */
+#define	SAFE_PE_PARTCFG_GBURST	0x00030000	/* gather particle burst */
+#define	SAFE_PE_PARTCFG_GBURST_2	0x00000000
+#define	SAFE_PE_PARTCFG_GBURST_4	0x00010000
+#define	SAFE_PE_PARTCFG_GBURST_8	0x00020000
+#define	SAFE_PE_PARTCFG_GBURST_16	0x00030000
+#define	SAFE_PE_PARTCFG_SBURST	0x000c0000	/* scatter particle burst */
+#define	SAFE_PE_PARTCFG_SBURST_2	0x00000000
+#define	SAFE_PE_PARTCFG_SBURST_4	0x00040000
+#define	SAFE_PE_PARTCFG_SBURST_8	0x00080000
+#define	SAFE_PE_PARTCFG_SBURST_16	0x000c0000
+
+#define	SAFE_PE_PARTSIZE_SCAT	0xffff0000	/* scatter particle ring size */
+#define	SAFE_PE_PARTSIZE_GATH	0x0000ffff	/* gather particle ring size */
+
+#define	SAFE_CRYPTO_CTRL_3DES	0x00000001	/* enable 3DES support */
+#define	SAFE_CRYPTO_CTRL_PKEY	0x00010000	/* enable public key support */
+#define	SAFE_CRYPTO_CTRL_RNG	0x00020000	/* enable RNG support */
+
+#define	SAFE_DEVINFO_REV_MIN	0x0000000f	/* minor rev for chip */
+#define	SAFE_DEVINFO_REV_MAJ	0x000000f0	/* major rev for chip */
+#define	SAFE_DEVINFO_REV_MAJ_S	4
+#define	SAFE_DEVINFO_DES	0x00000100	/* DES/3DES support present */
+#define	SAFE_DEVINFO_ARC4	0x00000200	/* ARC4 support present */
+#define	SAFE_DEVINFO_AES	0x00000400	/* AES support present */
+#define	SAFE_DEVINFO_MD5	0x00001000	/* MD5 support present */
+#define	SAFE_DEVINFO_SHA1	0x00002000	/* SHA-1 support present */
+#define	SAFE_DEVINFO_RIPEMD	0x00004000	/* RIPEMD support present */
+#define	SAFE_DEVINFO_DEFLATE	0x00010000	/* Deflate support present */
+#define	SAFE_DEVINFO_SARAM	0x00100000	/* on-chip SA RAM present */
+#define	SAFE_DEVINFO_EMIBUS	0x00200000	/* EMI bus present */
+#define	SAFE_DEVINFO_PKEY	0x00400000	/* public key support present */
+#define	SAFE_DEVINFO_RNG	0x00800000	/* RNG present */
+
+#define	SAFE_REV(_maj, _min)	(((_maj) << SAFE_DEVINFO_REV_MAJ_S) | (_min))
+#define	SAFE_REV_MAJ(_chiprev) \
+	(((_chiprev) & SAFE_DEVINFO_REV_MAJ) >> SAFE_DEVINFO_REV_MAJ_S)
+#define	SAFE_REV_MIN(_chiprev)	((_chiprev) & SAFE_DEVINFO_REV_MIN)
+
+#define	SAFE_PK_FUNC_MULT	0x00000001	/* Multiply function */
+#define	SAFE_PK_FUNC_SQUARE	0x00000004	/* Square function */
+#define	SAFE_PK_FUNC_ADD	0x00000010	/* Add function */
+#define	SAFE_PK_FUNC_SUB	0x00000020	/* Subtract function */
+#define	SAFE_PK_FUNC_LSHIFT	0x00000040	/* Left-shift function */
+#define	SAFE_PK_FUNC_RSHIFT	0x00000080	/* Right-shift function */
+#define	SAFE_PK_FUNC_DIV	0x00000100	/* Divide function */
+#define	SAFE_PK_FUNC_CMP	0x00000400	/* Compare function */
+#define	SAFE_PK_FUNC_COPY	0x00000800	/* Copy function */
+#define	SAFE_PK_FUNC_EXP16	0x00002000	/* Exponentiate (4-bit ACT) */
+#define	SAFE_PK_FUNC_EXP4	0x00004000	/* Exponentiate (2-bit ACT) */
+#define	SAFE_PK_FUNC_RUN	0x00008000	/* start/status */
+
+#define	SAFE_RNG_STAT_BUSY	0x00000001	/* busy, data not valid */
+
+#define	SAFE_RNG_CTRL_PRE_LFSR	0x00000001	/* enable output pre-LFSR */
+#define	SAFE_RNG_CTRL_TST_MODE	0x00000002	/* enable test mode */
+#define	SAFE_RNG_CTRL_TST_RUN	0x00000004	/* start test state machine */
+#define	SAFE_RNG_CTRL_ENA_RING1	0x00000008	/* test entropy oscillator #1 */
+#define	SAFE_RNG_CTRL_ENA_RING2	0x00000010	/* test entropy oscillator #2 */
+#define	SAFE_RNG_CTRL_DIS_ALARM	0x00000020	/* disable RNG alarm reports */
+#define	SAFE_RNG_CTRL_TST_CLOCK	0x00000040	/* enable test clock */
+#define	SAFE_RNG_CTRL_SHORTEN	0x00000080	/* shorten state timers */
+#define	SAFE_RNG_CTRL_TST_ALARM	0x00000100	/* simulate alarm state */
+#define	SAFE_RNG_CTRL_RST_LFSR	0x00000200	/* reset LFSR */
+
+/*
+ * Packet engine descriptor.  Note that d_csr is a copy of the
+ * SAFE_PE_CSR register and all definitions apply, and d_len
+ * is a copy of the SAFE_PE_LEN register and all definitions apply.
+ * d_src and d_len may point directly to contiguous data or to a
+ * list of ``particle descriptors'' when using scatter/gather i/o.
+ */
+struct safe_desc {
+	u_int32_t	d_csr;			/* per-packet control/status */
+	u_int32_t	d_src;			/* source address */
+	u_int32_t	d_dst;			/* destination address */
+	u_int32_t	d_sa;			/* SA address */
+	u_int32_t	d_len;			/* length, bypass, status */
+};
+
+/*
+ * Scatter/Gather particle descriptor.
+ *
+ * NB: scatter descriptors do not specify a size; this is fixed
+ *     by the setting of the SAFE_PE_PARTCFG register.
+ */
+struct safe_pdesc {
+	u_int32_t	pd_addr;		/* particle address */
+#ifdef __BIG_ENDIAN
+	u_int16_t	pd_flags;		/* control word */
+	u_int16_t	pd_size;		/* particle size (bytes) */
+#else
+	u_int16_t	pd_flags;		/* control word */
+	u_int16_t	pd_size;		/* particle size (bytes) */
+#endif
+};
+
+#define	SAFE_PD_READY	0x0001			/* ready for processing */
+#define	SAFE_PD_DONE	0x0002			/* h/w completed processing */
+
+/*
+ * Security Association (SA) Record (Rev 1).  One of these is
+ * required for each operation processed by the packet engine.
+ */
+struct safe_sarec {
+	u_int32_t	sa_cmd0;
+	u_int32_t	sa_cmd1;
+	u_int32_t	sa_resv0;
+	u_int32_t	sa_resv1;
+	u_int32_t	sa_key[8];		/* DES/3DES/AES key */
+	u_int32_t	sa_indigest[5];		/* inner digest */
+	u_int32_t	sa_outdigest[5];	/* outer digest */
+	u_int32_t	sa_spi;			/* SPI */
+	u_int32_t	sa_seqnum;		/* sequence number */
+	u_int32_t	sa_seqmask[2];		/* sequence number mask */
+	u_int32_t	sa_resv2;
+	u_int32_t	sa_staterec;		/* address of state record */
+	u_int32_t	sa_resv3[2];
+	u_int32_t	sa_samgmt0;		/* SA management field 0 */
+	u_int32_t	sa_samgmt1;		/* SA management field 0 */
+};
+
+#define	SAFE_SA_CMD0_OP		0x00000007	/* operation code */
+#define	SAFE_SA_CMD0_OP_CRYPT	0x00000000	/* encrypt/decrypt (basic) */
+#define	SAFE_SA_CMD0_OP_BOTH	0x00000001	/* encrypt-hash/hash-decrypto */
+#define	SAFE_SA_CMD0_OP_HASH	0x00000003	/* hash (outbound-only) */
+#define	SAFE_SA_CMD0_OP_ESP	0x00000000	/* ESP in/out (proto) */
+#define	SAFE_SA_CMD0_OP_AH	0x00000001	/* AH in/out (proto) */
+#define	SAFE_SA_CMD0_INBOUND	0x00000008	/* inbound operation */
+#define	SAFE_SA_CMD0_OUTBOUND	0x00000000	/* outbound operation */
+#define	SAFE_SA_CMD0_GROUP	0x00000030	/* operation group */
+#define	SAFE_SA_CMD0_BASIC	0x00000000	/* basic operation */
+#define	SAFE_SA_CMD0_PROTO	0x00000010	/* protocol/packet operation */
+#define	SAFE_SA_CMD0_BUNDLE	0x00000020	/* bundled operation (resvd) */
+#define	SAFE_SA_CMD0_PAD	0x000000c0	/* crypto pad method */
+#define	SAFE_SA_CMD0_PAD_IPSEC	0x00000000	/* IPsec padding */
+#define	SAFE_SA_CMD0_PAD_PKCS7	0x00000040	/* PKCS#7 padding */
+#define	SAFE_SA_CMD0_PAD_CONS	0x00000080	/* constant padding */
+#define	SAFE_SA_CMD0_PAD_ZERO	0x000000c0	/* zero padding */
+#define	SAFE_SA_CMD0_CRYPT_ALG	0x00000f00	/* symmetric crypto algorithm */
+#define	SAFE_SA_CMD0_DES	0x00000000	/* DES crypto algorithm */
+#define	SAFE_SA_CMD0_3DES	0x00000100	/* 3DES crypto algorithm */
+#define	SAFE_SA_CMD0_AES	0x00000300	/* AES crypto algorithm */
+#define	SAFE_SA_CMD0_CRYPT_NULL	0x00000f00	/* null crypto algorithm */
+#define	SAFE_SA_CMD0_HASH_ALG	0x0000f000	/* hash algorithm */
+#define	SAFE_SA_CMD0_MD5	0x00000000	/* MD5 hash algorithm */
+#define	SAFE_SA_CMD0_SHA1	0x00001000	/* SHA-1 hash algorithm */
+#define	SAFE_SA_CMD0_HASH_NULL	0x0000f000	/* null hash algorithm */
+#define	SAFE_SA_CMD0_HDR_PROC	0x00080000	/* header processing */
+#define	SAFE_SA_CMD0_IBUSID	0x00300000	/* input bus id */
+#define	SAFE_SA_CMD0_IPCI	0x00100000	/* PCI input bus id */
+#define	SAFE_SA_CMD0_OBUSID	0x00c00000	/* output bus id */
+#define	SAFE_SA_CMD0_OPCI	0x00400000	/* PCI output bus id */
+#define	SAFE_SA_CMD0_IVLD	0x03000000	/* IV loading */
+#define	SAFE_SA_CMD0_IVLD_NONE	0x00000000	/* IV no load (reuse) */
+#define	SAFE_SA_CMD0_IVLD_IBUF	0x01000000	/* IV load from input buffer */
+#define	SAFE_SA_CMD0_IVLD_STATE	0x02000000	/* IV load from state */
+#define	SAFE_SA_CMD0_HSLD	0x0c000000	/* hash state loading */
+#define	SAFE_SA_CMD0_HSLD_SA	0x00000000	/* hash state load from SA */
+#define	SAFE_SA_CMD0_HSLD_STATE	0x08000000	/* hash state load from state */
+#define	SAFE_SA_CMD0_HSLD_NONE	0x0c000000	/* hash state no load */
+#define	SAFE_SA_CMD0_SAVEIV	0x10000000	/* save IV */
+#define	SAFE_SA_CMD0_SAVEHASH	0x20000000	/* save hash state */
+#define	SAFE_SA_CMD0_IGATHER	0x40000000	/* input gather */
+#define	SAFE_SA_CMD0_OSCATTER	0x80000000	/* output scatter */
+
+#define	SAFE_SA_CMD1_HDRCOPY	0x00000002	/* copy header to output */
+#define	SAFE_SA_CMD1_PAYCOPY	0x00000004	/* copy payload to output */
+#define	SAFE_SA_CMD1_PADCOPY	0x00000008	/* copy pad to output */
+#define	SAFE_SA_CMD1_IPV4	0x00000000	/* IPv4 protocol */
+#define	SAFE_SA_CMD1_IPV6	0x00000010	/* IPv6 protocol */
+#define	SAFE_SA_CMD1_MUTABLE	0x00000020	/* mutable bit processing */
+#define	SAFE_SA_CMD1_SRBUSID	0x000000c0	/* state record bus id */
+#define	SAFE_SA_CMD1_SRPCI	0x00000040	/* state record from PCI */
+#define	SAFE_SA_CMD1_CRMODE	0x00000300	/* crypto mode */
+#define	SAFE_SA_CMD1_ECB	0x00000000	/* ECB crypto mode */
+#define	SAFE_SA_CMD1_CBC	0x00000100	/* CBC crypto mode */
+#define	SAFE_SA_CMD1_OFB	0x00000200	/* OFB crypto mode */
+#define	SAFE_SA_CMD1_CFB	0x00000300	/* CFB crypto mode */
+#define	SAFE_SA_CMD1_CRFEEDBACK	0x00000c00	/* crypto feedback mode */
+#define	SAFE_SA_CMD1_64BIT	0x00000000	/* 64-bit crypto feedback */
+#define	SAFE_SA_CMD1_8BIT	0x00000400	/* 8-bit crypto feedback */
+#define	SAFE_SA_CMD1_1BIT	0x00000800	/* 1-bit crypto feedback */
+#define	SAFE_SA_CMD1_128BIT	0x00000c00	/* 128-bit crypto feedback */
+#define	SAFE_SA_CMD1_OPTIONS	0x00001000	/* HMAC/options mutable bit */
+#define	SAFE_SA_CMD1_HMAC	SAFE_SA_CMD1_OPTIONS
+#define	SAFE_SA_CMD1_SAREV1	0x00008000	/* SA Revision 1 */
+#define	SAFE_SA_CMD1_OFFSET	0x00ff0000	/* hash/crypto offset(dwords) */
+#define	SAFE_SA_CMD1_OFFSET_S	16
+#define	SAFE_SA_CMD1_AESKEYLEN	0x0f000000	/* AES key length */
+#define	SAFE_SA_CMD1_AES128	0x02000000	/* 128-bit AES key */
+#define	SAFE_SA_CMD1_AES192	0x03000000	/* 192-bit AES key */
+#define	SAFE_SA_CMD1_AES256	0x04000000	/* 256-bit AES key */
+
+/* 
+ * Security Associate State Record (Rev 1).
+ */
+struct safe_sastate {
+	u_int32_t	sa_saved_iv[4];		/* saved IV (DES/3DES/AES) */
+	u_int32_t	sa_saved_hashbc;	/* saved hash byte count */
+	u_int32_t	sa_saved_indigest[5];	/* saved inner digest */
+};
+#endif /* _SAFE_SAFEREG_H_ */
diff --git a/crypto/ocf/safe/safevar.h b/crypto/ocf/safe/safevar.h
new file mode 100755
index 0000000..f5b7394
--- /dev/null
+++ b/crypto/ocf/safe/safevar.h
@@ -0,0 +1,230 @@
+/*-
+ * The linux port of this code done by David McCullough
+ * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com>
+ * The license and original author are listed below.
+ *
+ * Copyright (c) 2003 Sam Leffler, Errno Consulting
+ * Copyright (c) 2003 Global Technology Associates, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/safe/safevar.h,v 1.2 2006/05/17 18:34:26 pjd Exp $
+ */
+#ifndef _SAFE_SAFEVAR_H_
+#define	_SAFE_SAFEVAR_H_
+
+/* Maximum queue length */
+#ifndef SAFE_MAX_NQUEUE
+#define SAFE_MAX_NQUEUE	60
+#endif
+
+#define	SAFE_MAX_PART		64	/* Maximum scatter/gather depth */
+#define	SAFE_DMA_BOUNDARY	0	/* No boundary for source DMA ops */
+#define	SAFE_MAX_DSIZE		2048 /* MCLBYTES Fixed scatter particle size */
+#define	SAFE_MAX_SSIZE		0x0ffff	/* Maximum gather particle size */
+#define	SAFE_MAX_DMA		0xfffff	/* Maximum PE operand size (20 bits) */
+/* total src+dst particle descriptors */
+#define	SAFE_TOTAL_DPART	(SAFE_MAX_NQUEUE * SAFE_MAX_PART)
+#define	SAFE_TOTAL_SPART	(SAFE_MAX_NQUEUE * SAFE_MAX_PART)
+
+#define	SAFE_RNG_MAXBUFSIZ	128	/* 32-bit words */
+
+#define	SAFE_CARD(sid)		(((sid) & 0xf0000000) >> 28)
+#define	SAFE_SESSION(sid)	( (sid) & 0x0fffffff)
+#define	SAFE_SID(crd, sesn)	(((crd) << 28) | ((sesn) & 0x0fffffff))
+
+#define SAFE_DEF_RTY		0xff	/* PCI Retry Timeout */
+#define SAFE_DEF_TOUT		0xff	/* PCI TRDY Timeout */
+#define SAFE_DEF_CACHELINE	0x01	/* Cache Line setting */
+
+#ifdef __KERNEL__
+/*
+ * State associated with the allocation of each chunk
+ * of memory setup for DMA.
+ */
+struct safe_dma_alloc {
+	dma_addr_t		dma_paddr;
+	void			*dma_vaddr;
+};
+
+/*
+ * Cryptographic operand state.  One of these exists for each
+ * source and destination operand passed in from the crypto
+ * subsystem.  When possible source and destination operands
+ * refer to the same memory.  More often they are distinct.
+ * We track the virtual address of each operand as well as
+ * where each is mapped for DMA.
+ */
+struct safe_operand {
+	union {
+		struct sk_buff *skb;
+		struct uio *io;
+	} u;
+	void			*map;
+	int				mapsize;	/* total number of bytes in segs */
+	struct {
+		dma_addr_t	ds_addr;
+		int			ds_len;
+		int			ds_tlen;
+	} segs[SAFE_MAX_PART];
+	int				nsegs;
+};
+
+/*
+ * Packet engine ring entry and cryptographic operation state.
+ * The packet engine requires a ring of descriptors that contain
+ * pointers to various cryptographic state.  However the ring
+ * configuration register allows you to specify an arbitrary size
+ * for ring entries.  We use this feature to collect most of the
+ * state for each cryptographic request into one spot.  Other than
+ * ring entries only the ``particle descriptors'' (scatter/gather
+ * lists) and the actual operand data are kept separate.  The
+ * particle descriptors must also be organized in rings.  The
+ * operand data can be located aribtrarily (modulo alignment constraints).
+ *
+ * Note that the descriptor ring is mapped onto the PCI bus so
+ * the hardware can DMA data.  This means the entire ring must be
+ * contiguous.
+ */
+struct safe_ringentry {
+	struct safe_desc	re_desc;	/* command descriptor */
+	struct safe_sarec	re_sa;		/* SA record */
+	struct safe_sastate	re_sastate;	/* SA state record */
+
+	struct cryptop		*re_crp;	/* crypto operation */
+
+	struct safe_operand	re_src;		/* source operand */
+	struct safe_operand	re_dst;		/* destination operand */
+
+	int			re_sesn;	/* crypto session ID */
+	int			re_flags;
+#define	SAFE_QFLAGS_COPYOUTIV	0x1		/* copy back on completion */
+#define	SAFE_QFLAGS_COPYOUTICV	0x2		/* copy back on completion */
+};
+
+#define	re_src_skb	re_src.u.skb
+#define	re_src_io	re_src.u.io
+#define	re_src_map	re_src.map
+#define	re_src_nsegs	re_src.nsegs
+#define	re_src_segs	re_src.segs
+#define	re_src_mapsize	re_src.mapsize
+
+#define	re_dst_skb	re_dst.u.skb
+#define	re_dst_io	re_dst.u.io
+#define	re_dst_map	re_dst.map
+#define	re_dst_nsegs	re_dst.nsegs
+#define	re_dst_segs	re_dst.segs
+#define	re_dst_mapsize	re_dst.mapsize
+
+struct rndstate_test;
+
+struct safe_session {
+	u_int32_t	ses_used;
+	u_int32_t	ses_klen;		/* key length in bits */
+	u_int32_t	ses_key[8];		/* DES/3DES/AES key */
+	u_int32_t	ses_mlen;		/* hmac length in bytes */
+	u_int32_t	ses_hminner[5];		/* hmac inner state */
+	u_int32_t	ses_hmouter[5];		/* hmac outer state */
+	u_int32_t	ses_iv[4];		/* DES/3DES/AES iv */
+};
+
+struct safe_pkq {
+	struct list_head	pkq_list;
+	struct cryptkop		*pkq_krp;
+};
+
+struct safe_softc {
+	softc_device_decl	sc_dev;
+	u32			sc_irq;
+
+	struct pci_dev		*sc_pcidev;
+	ocf_iomem_t		sc_base_addr;
+
+	u_int			sc_chiprev;	/* major/minor chip revision */
+	int			sc_flags;	/* device specific flags */
+#define	SAFE_FLAGS_KEY		0x01		/* has key accelerator */
+#define	SAFE_FLAGS_RNG		0x02		/* hardware rng */
+	int			sc_suspended;
+	int			sc_needwakeup;	/* notify crypto layer */
+	int32_t			sc_cid;		/* crypto tag */
+
+	struct safe_dma_alloc	sc_ringalloc;	/* PE ring allocation state */
+	struct safe_ringentry	*sc_ring;	/* PE ring */
+	struct safe_ringentry	*sc_ringtop;	/* PE ring top */
+	struct safe_ringentry	*sc_front;	/* next free entry */
+	struct safe_ringentry	*sc_back;	/* next pending entry */
+	int			sc_nqchip;	/* # passed to chip */
+	spinlock_t		sc_ringmtx;	/* PE ring lock */
+	struct safe_pdesc	*sc_spring;	/* src particle ring */
+	struct safe_pdesc	*sc_springtop;	/* src particle ring top */
+	struct safe_pdesc	*sc_spfree;	/* next free src particle */
+	struct safe_dma_alloc	sc_spalloc;	/* src particle ring state */
+	struct safe_pdesc	*sc_dpring;	/* dest particle ring */
+	struct safe_pdesc	*sc_dpringtop;	/* dest particle ring top */
+	struct safe_pdesc	*sc_dpfree;	/* next free dest particle */
+	struct safe_dma_alloc	sc_dpalloc;	/* dst particle ring state */
+	int			sc_nsessions;	/* # of sessions */
+	struct safe_session	*sc_sessions;	/* sessions */
+
+	struct timer_list	sc_pkto;	/* PK polling */
+	spinlock_t		sc_pkmtx;	/* PK lock */
+	struct list_head	sc_pkq;		/* queue of PK requests */
+	struct safe_pkq		*sc_pkq_cur;	/* current processing request */
+	u_int32_t		sc_pk_reslen, sc_pk_resoff;
+
+	int			sc_max_dsize;	/* maximum safe DMA size */
+};
+#endif /* __KERNEL__ */
+
+struct safe_stats {
+	u_int64_t st_ibytes;
+	u_int64_t st_obytes;
+	u_int32_t st_ipackets;
+	u_int32_t st_opackets;
+	u_int32_t st_invalid;		/* invalid argument */
+	u_int32_t st_badsession;	/* invalid session id */
+	u_int32_t st_badflags;		/* flags indicate !(mbuf | uio) */
+	u_int32_t st_nodesc;		/* op submitted w/o descriptors */
+	u_int32_t st_badalg;		/* unsupported algorithm */
+	u_int32_t st_ringfull;		/* PE descriptor ring full */
+	u_int32_t st_peoperr;		/* PE marked error */
+	u_int32_t st_dmaerr;		/* PE DMA error */
+	u_int32_t st_bypasstoobig;	/* bypass > 96 bytes */
+	u_int32_t st_skipmismatch;	/* enc part begins before auth part */
+	u_int32_t st_lenmismatch;	/* enc length different auth length */
+	u_int32_t st_coffmisaligned;	/* crypto offset not 32-bit aligned */
+	u_int32_t st_cofftoobig;	/* crypto offset > 255 words */
+	u_int32_t st_iovmisaligned;	/* iov op not aligned */
+	u_int32_t st_iovnotuniform;	/* iov op not suitable */
+	u_int32_t st_unaligned;		/* unaligned src caused copy */
+	u_int32_t st_notuniform;	/* non-uniform src caused copy */
+	u_int32_t st_nomap;		/* bus_dmamap_create failed */
+	u_int32_t st_noload;		/* bus_dmamap_load_* failed */
+	u_int32_t st_nombuf;		/* MGET* failed */
+	u_int32_t st_nomcl;		/* MCLGET* failed */
+	u_int32_t st_maxqchip;		/* max mcr1 ops out for processing */
+	u_int32_t st_rng;		/* RNG requests */
+	u_int32_t st_rngalarm;		/* RNG alarm requests */
+	u_int32_t st_noicvcopy;		/* ICV data copies suppressed */
+};
+#endif /* _SAFE_SAFEVAR_H_ */
diff --git a/crypto/ocf/safe/sha1.c b/crypto/ocf/safe/sha1.c
new file mode 100755
index 0000000..4e360e2
--- /dev/null
+++ b/crypto/ocf/safe/sha1.c
@@ -0,0 +1,279 @@
+/*	$KAME: sha1.c,v 1.5 2000/11/08 06:13:08 itojun Exp $	*/
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
+ * based on: http://csrc.nist.gov/fips/fip180-1.txt
+ * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
+ */
+
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/crypto/sha1.c,v 1.9 2003/06/10 21:36:57 obrien Exp $");
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+
+#include <crypto/sha1.h>
+#endif
+
+/* sanity check */
+#if BYTE_ORDER != BIG_ENDIAN
+# if BYTE_ORDER != LITTLE_ENDIAN
+#  define unsupported 1
+# endif
+#endif
+
+#ifndef unsupported
+
+/* constant table */
+static u_int32_t _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
+#define	K(t)	_K[(t) / 20]
+
+#define	F0(b, c, d)	(((b) & (c)) | ((~(b)) & (d)))
+#define	F1(b, c, d)	(((b) ^ (c)) ^ (d))
+#define	F2(b, c, d)	(((b) & (c)) | ((b) & (d)) | ((c) & (d)))
+#define	F3(b, c, d)	(((b) ^ (c)) ^ (d))
+
+#define	S(n, x)		(((x) << (n)) | ((x) >> (32 - n)))
+
+#undef H
+#define	H(n)	(ctxt->h.b32[(n)])
+#define	COUNT	(ctxt->count)
+#define	BCOUNT	(ctxt->c.b64[0] / 8)
+#define	W(n)	(ctxt->m.b32[(n)])
+
+#define	PUTBYTE(x)	{ \
+	ctxt->m.b8[(COUNT % 64)] = (x);		\
+	COUNT++;				\
+	COUNT %= 64;				\
+	ctxt->c.b64[0] += 8;			\
+	if (COUNT % 64 == 0)			\
+		sha1_step(ctxt);		\
+     }
+
+#define	PUTPAD(x)	{ \
+	ctxt->m.b8[(COUNT % 64)] = (x);		\
+	COUNT++;				\
+	COUNT %= 64;				\
+	if (COUNT % 64 == 0)			\
+		sha1_step(ctxt);		\
+     }
+
+static void sha1_step(struct sha1_ctxt *);
+
+static void
+sha1_step(ctxt)
+	struct sha1_ctxt *ctxt;
+{
+	u_int32_t	a, b, c, d, e;
+	size_t t, s;
+	u_int32_t	tmp;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+	struct sha1_ctxt tctxt;
+	bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64);
+	ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];
+	ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];
+	ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];
+	ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];
+	ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];
+	ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];
+	ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];
+	ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];
+	ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];
+	ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];
+	ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];
+	ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];
+	ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];
+	ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];
+	ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];
+	ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];
+	ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];
+	ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];
+	ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];
+	ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];
+	ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];
+	ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];
+	ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];
+	ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];
+	ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];
+	ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];
+	ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];
+	ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];
+	ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];
+	ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];
+	ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];
+	ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];
+#endif
+
+	a = H(0); b = H(1); c = H(2); d = H(3); e = H(4);
+
+	for (t = 0; t < 20; t++) {
+		s = t & 0x0f;
+		if (t >= 16) {
+			W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
+		}
+		tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
+		e = d; d = c; c = S(30, b); b = a; a = tmp;
+	}
+	for (t = 20; t < 40; t++) {
+		s = t & 0x0f;
+		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
+		tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
+		e = d; d = c; c = S(30, b); b = a; a = tmp;
+	}
+	for (t = 40; t < 60; t++) {
+		s = t & 0x0f;
+		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
+		tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
+		e = d; d = c; c = S(30, b); b = a; a = tmp;
+	}
+	for (t = 60; t < 80; t++) {
+		s = t & 0x0f;
+		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
+		tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
+		e = d; d = c; c = S(30, b); b = a; a = tmp;
+	}
+
+	H(0) = H(0) + a;
+	H(1) = H(1) + b;
+	H(2) = H(2) + c;
+	H(3) = H(3) + d;
+	H(4) = H(4) + e;
+
+	bzero(&ctxt->m.b8[0], 64);
+}
+
+/*------------------------------------------------------------*/
+
+void
+sha1_init(ctxt)
+	struct sha1_ctxt *ctxt;
+{
+	bzero(ctxt, sizeof(struct sha1_ctxt));
+	H(0) = 0x67452301;
+	H(1) = 0xefcdab89;
+	H(2) = 0x98badcfe;
+	H(3) = 0x10325476;
+	H(4) = 0xc3d2e1f0;
+}
+
+void
+sha1_pad(ctxt)
+	struct sha1_ctxt *ctxt;
+{
+	size_t padlen;		/*pad length in bytes*/
+	size_t padstart;
+
+	PUTPAD(0x80);
+
+	padstart = COUNT % 64;
+	padlen = 64 - padstart;
+	if (padlen < 8) {
+		bzero(&ctxt->m.b8[padstart], padlen);
+		COUNT += padlen;
+		COUNT %= 64;
+		sha1_step(ctxt);
+		padstart = COUNT % 64;	/* should be 0 */
+		padlen = 64 - padstart;	/* should be 64 */
+	}
+	bzero(&ctxt->m.b8[padstart], padlen - 8);
+	COUNT += (padlen - 8);
+	COUNT %= 64;
+#if BYTE_ORDER == BIG_ENDIAN
+	PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);
+	PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);
+	PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);
+	PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
+#else
+	PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);
+	PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);
+	PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);
+	PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
+#endif
+}
+
+void
+sha1_loop(ctxt, input, len)
+	struct sha1_ctxt *ctxt;
+	const u_int8_t *input;
+	size_t len;
+{
+	size_t gaplen;
+	size_t gapstart;
+	size_t off;
+	size_t copysiz;
+
+	off = 0;
+
+	while (off < len) {
+		gapstart = COUNT % 64;
+		gaplen = 64 - gapstart;
+
+		copysiz = (gaplen < len - off) ? gaplen : len - off;
+		bcopy(&input[off], &ctxt->m.b8[gapstart], copysiz);
+		COUNT += copysiz;
+		COUNT %= 64;
+		ctxt->c.b64[0] += copysiz * 8;
+		if (COUNT % 64 == 0)
+			sha1_step(ctxt);
+		off += copysiz;
+	}
+}
+
+void
+sha1_result(ctxt, digest0)
+	struct sha1_ctxt *ctxt;
+	caddr_t digest0;
+{
+	u_int8_t *digest;
+
+	digest = (u_int8_t *)digest0;
+	sha1_pad(ctxt);
+#if BYTE_ORDER == BIG_ENDIAN
+	bcopy(&ctxt->h.b8[0], digest, 20);
+#else
+	digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];
+	digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];
+	digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];
+	digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];
+	digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];
+	digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];
+	digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];
+	digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];
+	digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];
+	digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];
+#endif
+}
+
+#endif /*unsupported*/
diff --git a/crypto/ocf/safe/sha1.h b/crypto/ocf/safe/sha1.h
new file mode 100755
index 0000000..0e19d90
--- /dev/null
+++ b/crypto/ocf/safe/sha1.h
@@ -0,0 +1,72 @@
+/*	$FreeBSD: src/sys/crypto/sha1.h,v 1.8 2002/03/20 05:13:50 alfred Exp $	*/
+/*	$KAME: sha1.h,v 1.5 2000/03/27 04:36:23 sumikawa Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
+ * based on: http://csrc.nist.gov/fips/fip180-1.txt
+ * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
+ */
+
+#ifndef _NETINET6_SHA1_H_
+#define _NETINET6_SHA1_H_
+
+struct sha1_ctxt {
+	union {
+		u_int8_t	b8[20];
+		u_int32_t	b32[5];
+	} h;
+	union {
+		u_int8_t	b8[8];
+		u_int64_t	b64[1];
+	} c;
+	union {
+		u_int8_t	b8[64];
+		u_int32_t	b32[16];
+	} m;
+	u_int8_t	count;
+};
+
+#ifdef __KERNEL__
+extern void sha1_init(struct sha1_ctxt *);
+extern void sha1_pad(struct sha1_ctxt *);
+extern void sha1_loop(struct sha1_ctxt *, const u_int8_t *, size_t);
+extern void sha1_result(struct sha1_ctxt *, caddr_t);
+
+/* compatibilty with other SHA1 source codes */
+typedef struct sha1_ctxt SHA1_CTX;
+#define SHA1Init(x)		sha1_init((x))
+#define SHA1Update(x, y, z)	sha1_loop((x), (y), (z))
+#define SHA1Final(x, y)		sha1_result((y), (x))
+#endif /* __KERNEL__ */
+
+#define	SHA1_RESULTLEN	(160/8)
+
+#endif /*_NETINET6_SHA1_H_*/
diff --git a/crypto/ocf/talitos/Makefile b/crypto/ocf/talitos/Makefile
new file mode 100755
index 0000000..2591b8a
--- /dev/null
+++ b/crypto/ocf/talitos/Makefile
@@ -0,0 +1,12 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+obj-$(CONFIG_OCF_TALITOS) += talitos.o
+
+obj ?= .
+EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/crypto/ocf/talitos/talitos.c b/crypto/ocf/talitos/talitos.c
new file mode 100755
index 0000000..eaf3f30
--- /dev/null
+++ b/crypto/ocf/talitos/talitos.c
@@ -0,0 +1,1359 @@
+/*
+ * crypto/ocf/talitos/talitos.c
+ *
+ * An OCF-Linux module that uses Freescale's SEC to do the crypto.
+ * Based on crypto/ocf/hifn and crypto/ocf/safe OCF drivers
+ *
+ * Copyright (c) 2006 Freescale Semiconductor, Inc.
+ *
+ * This code written by Kim A. B. Phillips <kim.phillips@freescale.com>
+ * some code copied from files with the following:
+ * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * NOTES:
+ *
+ * The Freescale SEC (also known as 'talitos') resides on the
+ * internal bus, and runs asynchronous to the processor core.  It has
+ * a wide gamut of cryptographic acceleration features, including single-
+ * pass IPsec (also known as algorithm chaining).  To properly utilize 
+ * all of the SEC's performance enhancing features, further reworking 
+ * of higher level code (framework, applications) will be necessary.
+ *
+ * The following table shows which SEC version is present in which devices:
+ * 
+ * Devices       SEC version
+ *
+ * 8272, 8248    SEC 1.0
+ * 885, 875      SEC 1.2
+ * 8555E, 8541E  SEC 2.0
+ * 8349E         SEC 2.01
+ * 8548E         SEC 2.1
+ *
+ * The following table shows the features offered by each SEC version:
+ *
+ * 	                       Max.   chan-
+ * version  Bus I/F       Clock  nels  DEU AESU AFEU MDEU PKEU RNG KEU
+ *
+ * SEC 1.0  internal 64b  100MHz   4     1    1    1    1    1   1   0
+ * SEC 1.2  internal 32b   66MHz   1     1    1    0    1    0   0   0
+ * SEC 2.0  internal 64b  166MHz   4     1    1    1    1    1   1   0
+ * SEC 2.01 internal 64b  166MHz   4     1    1    1    1    1   1   0
+ * SEC 2.1  internal 64b  333MHz   4     1    1    1    1    1   1   1
+ *
+ * Each execution unit in the SEC has two modes of execution; channel and
+ * slave/debug.  This driver employs the channel infrastructure in the
+ * device for convenience.  Only the RNG is directly accessed due to the
+ * convenience of its random fifo pool.  The relationship between the
+ * channels and execution units is depicted in the following diagram:
+ *
+ *    -------   ------------
+ * ---| ch0 |---|          |
+ *    -------   |          |
+ *              |          |------+-------+-------+-------+------------
+ *    -------   |          |      |       |       |       |           |
+ * ---| ch1 |---|          |      |       |       |       |           |
+ *    -------   |          |   ------  ------  ------  ------      ------
+ *              |controller|   |DEU |  |AESU|  |MDEU|  |PKEU| ...  |RNG |
+ *    -------   |          |   ------  ------  ------  ------      ------
+ * ---| ch2 |---|          |      |       |       |       |           |
+ *    -------   |          |      |       |       |       |           |
+ *              |          |------+-------+-------+-------+------------
+ *    -------   |          |
+ * ---| ch3 |---|          |
+ *    -------   ------------
+ *
+ * Channel ch0 may drive an aes operation to the aes unit (AESU),
+ * and, at the same time, ch1 may drive a message digest operation
+ * to the mdeu. Each channel has an input descriptor FIFO, and the 
+ * FIFO can contain, e.g. on the 8541E, up to 24 entries, before a
+ * a buffer overrun error is triggered. The controller is responsible
+ * for fetching the data from descriptor pointers, and passing the 
+ * data to the appropriate EUs. The controller also writes the 
+ * cryptographic operation's result to memory. The SEC notifies 
+ * completion by triggering an interrupt and/or setting the 1st byte 
+ * of the hdr field to 0xff.
+ *
+ * TODO:
+ * o support more algorithms
+ * o support more versions of the SEC
+ * o add support for linux 2.4
+ * o scatter-gather (sg) support
+ * o add support for public key ops (PKEU)
+ * o add statistics
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <asm/scatterlist.h>
+#include <linux/dma-mapping.h>  /* dma_map_single() */
+#include <linux/moduleparam.h>
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+#include <linux/platform_device.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+#include <linux/of_platform.h>
+#endif
+
+#include <cryptodev.h>
+#include <uio.h>
+
+#define DRV_NAME "talitos" 
+
+#include "talitos_dev.h"
+#include "talitos_soft.h"
+
+#define read_random(p,l) get_random_bytes(p,l)
+
+const char talitos_driver_name[] = "Talitos OCF";
+const char talitos_driver_version[] = "0.2";
+
+static int talitos_newsession(device_t dev, u_int32_t *sidp,
+								struct cryptoini *cri);
+static int talitos_freesession(device_t dev, u_int64_t tid);
+static int talitos_process(device_t dev, struct cryptop *crp, int hint);
+static void dump_talitos_status(struct talitos_softc *sc);
+static int talitos_submit(struct talitos_softc *sc, struct talitos_desc *td, 
+								int chsel);
+static void talitos_doneprocessing(struct talitos_softc *sc);
+static void talitos_init_device(struct talitos_softc *sc);
+static void talitos_reset_device_master(struct talitos_softc *sc);
+static void talitos_reset_device(struct talitos_softc *sc);
+static void talitos_errorprocessing(struct talitos_softc *sc);
+#ifdef CONFIG_PPC_MERGE
+static int talitos_probe(struct of_device *ofdev, const struct of_device_id *match);
+static int talitos_remove(struct of_device *ofdev);
+#else
+static int talitos_probe(struct platform_device *pdev);
+static int talitos_remove(struct platform_device *pdev);
+#endif
+#ifdef CONFIG_OCF_RANDOMHARVEST
+static int talitos_read_random(void *arg, u_int32_t *buf, int maxwords);
+static void talitos_rng_init(struct talitos_softc *sc);
+#endif
+
+static device_method_t talitos_methods = {
+	/* crypto device methods */
+	DEVMETHOD(cryptodev_newsession,	talitos_newsession),
+	DEVMETHOD(cryptodev_freesession,talitos_freesession),
+	DEVMETHOD(cryptodev_process,	talitos_process),
+};
+
+#define debug talitos_debug
+int talitos_debug = 0;
+module_param(talitos_debug, int, 0644);
+MODULE_PARM_DESC(talitos_debug, "Enable debug");
+
+static inline void talitos_write(volatile unsigned *addr, u32 val)
+{
+        out_be32(addr, val);
+}
+
+static inline u32 talitos_read(volatile unsigned *addr)
+{
+        u32 val;
+        val = in_be32(addr);
+        return val;
+}
+
+static void dump_talitos_status(struct talitos_softc *sc)
+{
+	unsigned int v, v_hi, i, *ptr;
+	v = talitos_read(sc->sc_base_addr + TALITOS_MCR);
+	v_hi = talitos_read(sc->sc_base_addr + TALITOS_MCR_HI);
+	printk(KERN_INFO "%s: MCR          0x%08x_%08x\n",
+			device_get_nameunit(sc->sc_cdev), v, v_hi);
+	v = talitos_read(sc->sc_base_addr + TALITOS_IMR);
+	v_hi = talitos_read(sc->sc_base_addr + TALITOS_IMR_HI);
+	printk(KERN_INFO "%s: IMR          0x%08x_%08x\n",
+			device_get_nameunit(sc->sc_cdev), v, v_hi);
+	v = talitos_read(sc->sc_base_addr + TALITOS_ISR);
+	v_hi = talitos_read(sc->sc_base_addr + TALITOS_ISR_HI);
+	printk(KERN_INFO "%s: ISR          0x%08x_%08x\n",
+			device_get_nameunit(sc->sc_cdev), v, v_hi);
+	for (i = 0; i < sc->sc_num_channels; i++) { 
+		v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET + 
+			TALITOS_CH_CDPR);
+		v_hi = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET + 
+			TALITOS_CH_CDPR_HI);
+		printk(KERN_INFO "%s: CDPR     ch%d 0x%08x_%08x\n", 
+				device_get_nameunit(sc->sc_cdev), i, v, v_hi);
+	}
+	for (i = 0; i < sc->sc_num_channels; i++) { 
+		v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET + 
+			TALITOS_CH_CCPSR);
+		v_hi = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET + 
+			TALITOS_CH_CCPSR_HI);
+		printk(KERN_INFO "%s: CCPSR    ch%d 0x%08x_%08x\n", 
+				device_get_nameunit(sc->sc_cdev), i, v, v_hi);
+	}
+	ptr = sc->sc_base_addr + TALITOS_CH_DESCBUF;
+	for (i = 0; i < 16; i++) { 
+		v = talitos_read(ptr++); v_hi = talitos_read(ptr++);
+		printk(KERN_INFO "%s: DESCBUF  ch0 0x%08x_%08x (tdp%02d)\n", 
+				device_get_nameunit(sc->sc_cdev), v, v_hi, i);
+	}
+	return;
+}
+
+
+#ifdef CONFIG_OCF_RANDOMHARVEST
+/* 
+ * pull random numbers off the RNG FIFO, not exceeding amount available
+ */
+static int
+talitos_read_random(void *arg, u_int32_t *buf, int maxwords)
+{
+	struct talitos_softc *sc = (struct talitos_softc *) arg;
+	int rc;
+	u_int32_t v;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	/* check for things like FIFO underflow */
+	v = talitos_read(sc->sc_base_addr + TALITOS_RNGISR_HI);
+	if (unlikely(v)) {
+		printk(KERN_ERR "%s: RNGISR_HI error %08x\n",
+				device_get_nameunit(sc->sc_cdev), v);
+		return 0;
+	}
+	/*
+	 * OFL is number of available 64-bit words, 
+	 * shift and convert to a 32-bit word count
+	 */
+	v = talitos_read(sc->sc_base_addr + TALITOS_RNGSR_HI);
+	v = (v & TALITOS_RNGSR_HI_OFL) >> (16 - 1);
+	if (maxwords > v)
+		maxwords = v;
+	for (rc = 0; rc < maxwords; rc++) {
+		buf[rc] = talitos_read(sc->sc_base_addr + 
+			TALITOS_RNG_FIFO + rc*sizeof(u_int32_t));
+	}
+	if (maxwords & 1) {
+		/* 
+		 * RNG will complain with an AE in the RNGISR
+		 * if we don't complete the pairs of 32-bit reads
+		 * to its 64-bit register based FIFO
+		 */
+		v = talitos_read(sc->sc_base_addr + 
+			TALITOS_RNG_FIFO + rc*sizeof(u_int32_t));
+	}
+
+	return rc;
+}
+
+static void
+talitos_rng_init(struct talitos_softc *sc)
+{
+	u_int32_t v;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+	/* reset RNG EU */
+	v = talitos_read(sc->sc_base_addr + TALITOS_RNGRCR_HI);
+	v |= TALITOS_RNGRCR_HI_SR;
+	talitos_write(sc->sc_base_addr + TALITOS_RNGRCR_HI, v);
+	while ((talitos_read(sc->sc_base_addr + TALITOS_RNGSR_HI) 
+		& TALITOS_RNGSR_HI_RD) == 0)
+			cpu_relax();
+	/*
+	 * we tell the RNG to start filling the RNG FIFO
+	 * by writing the RNGDSR 
+	 */
+	v = talitos_read(sc->sc_base_addr + TALITOS_RNGDSR_HI);
+	talitos_write(sc->sc_base_addr + TALITOS_RNGDSR_HI, v);
+	/*
+	 * 64 bits of data will be pushed onto the FIFO every 
+	 * 256 SEC cycles until the FIFO is full.  The RNG then 
+	 * attempts to keep the FIFO full.
+	 */
+	v = talitos_read(sc->sc_base_addr + TALITOS_RNGISR_HI);
+	if (v) {
+		printk(KERN_ERR "%s: RNGISR_HI error %08x\n",
+			device_get_nameunit(sc->sc_cdev), v);
+		return;
+	}
+	/*
+	 * n.b. we need to add a FIPS test here - if the RNG is going 
+	 * to fail, it's going to fail at reset time
+	 */
+	return;
+}
+#endif /* CONFIG_OCF_RANDOMHARVEST */
+
+/*
+ * Generate a new software session.
+ */
+static int
+talitos_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
+{
+	struct cryptoini *c, *encini = NULL, *macini = NULL;
+	struct talitos_softc *sc = device_get_softc(dev);
+	struct talitos_session *ses = NULL;
+	int sesn;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+	if (sidp == NULL || cri == NULL || sc == NULL) {
+		DPRINTF("%s,%d - EINVAL\n", __FILE__, __LINE__);
+		return EINVAL;
+	}
+	for (c = cri; c != NULL; c = c->cri_next) {
+		if (c->cri_alg == CRYPTO_MD5 ||
+		    c->cri_alg == CRYPTO_MD5_HMAC ||
+		    c->cri_alg == CRYPTO_SHA1 ||
+		    c->cri_alg == CRYPTO_SHA1_HMAC ||
+		    c->cri_alg == CRYPTO_NULL_HMAC) {
+			if (macini)
+				return EINVAL;
+			macini = c;
+		} else if (c->cri_alg == CRYPTO_DES_CBC ||
+		    c->cri_alg == CRYPTO_3DES_CBC ||
+		    c->cri_alg == CRYPTO_AES_CBC ||
+		    c->cri_alg == CRYPTO_NULL_CBC) {
+			if (encini)
+				return EINVAL;
+			encini = c;
+		} else {
+			DPRINTF("UNKNOWN c->cri_alg %d\n", encini->cri_alg);
+			return EINVAL;
+		}
+	}
+	if (encini == NULL && macini == NULL)
+		return EINVAL;
+	if (encini) {	
+		/* validate key length */
+		switch (encini->cri_alg) {
+		case CRYPTO_DES_CBC:
+			if (encini->cri_klen != 64)
+				return EINVAL;
+			break;
+		case CRYPTO_3DES_CBC:
+			if (encini->cri_klen != 192) {
+				return EINVAL;
+			}
+			break;
+		case CRYPTO_AES_CBC:
+			if (encini->cri_klen != 128 &&
+			    encini->cri_klen != 192 &&
+			    encini->cri_klen != 256)
+				return EINVAL;
+			break;
+		default:
+			DPRINTF("UNKNOWN encini->cri_alg %d\n", 
+				encini->cri_alg);
+			return EINVAL;
+		}
+	}
+
+	if (sc->sc_sessions == NULL) {
+		ses = sc->sc_sessions = (struct talitos_session *)
+			kmalloc(sizeof(struct talitos_session), SLAB_ATOMIC);
+		if (ses == NULL)
+			return ENOMEM;
+		memset(ses, 0, sizeof(struct talitos_session));
+		sesn = 0;
+		sc->sc_nsessions = 1;
+	} else {
+		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
+			if (sc->sc_sessions[sesn].ses_used == 0) {
+				ses = &sc->sc_sessions[sesn];
+				break;
+			}
+		}
+
+		if (ses == NULL) {
+			/* allocating session */
+			sesn = sc->sc_nsessions;
+			ses = (struct talitos_session *) kmalloc(
+				(sesn + 1) * sizeof(struct talitos_session), 
+				SLAB_ATOMIC);
+			if (ses == NULL)
+				return ENOMEM;
+			memset(ses, 0,
+				(sesn + 1) * sizeof(struct talitos_session));
+			memcpy(ses, sc->sc_sessions, 
+				sesn * sizeof(struct talitos_session));
+			memset(sc->sc_sessions, 0,
+				sesn * sizeof(struct talitos_session));
+			kfree(sc->sc_sessions);
+			sc->sc_sessions = ses;
+			ses = &sc->sc_sessions[sesn];
+			sc->sc_nsessions++;
+		}
+	}
+
+	ses->ses_used = 1;
+
+	if (encini) {
+		/* get an IV */
+		/* XXX may read fewer than requested */
+		read_random(ses->ses_iv, sizeof(ses->ses_iv));
+
+		ses->ses_klen = (encini->cri_klen + 7) / 8;
+		memcpy(ses->ses_key, encini->cri_key, ses->ses_klen);
+		if (macini) {
+			/* doing hash on top of cipher */
+			ses->ses_hmac_len = (macini->cri_klen + 7) / 8;
+			memcpy(ses->ses_hmac, macini->cri_key,
+				ses->ses_hmac_len);
+		}
+	} else if (macini) {
+		/* doing hash */
+		ses->ses_klen = (macini->cri_klen + 7) / 8;
+		memcpy(ses->ses_key, macini->cri_key, ses->ses_klen);
+	}
+
+	/* back compat way of determining MSC result len */
+	if (macini) {
+		ses->ses_mlen = macini->cri_mlen;
+		if (ses->ses_mlen == 0) {
+			if (macini->cri_alg == CRYPTO_MD5_HMAC)
+				ses->ses_mlen = MD5_HASH_LEN;
+			else
+				ses->ses_mlen = SHA1_HASH_LEN;
+		}
+	}
+
+	/* really should make up a template td here, 
+	 * and only fill things like i/o and direction in process() */
+
+	/* assign session ID */
+	*sidp = TALITOS_SID(sc->sc_num, sesn);
+	return 0;
+}
+
+/*
+ * Deallocate a session.
+ */
+static int
+talitos_freesession(device_t dev, u_int64_t tid)
+{
+	struct talitos_softc *sc = device_get_softc(dev);
+	int session, ret;
+	u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
+
+	if (sc == NULL)
+		return EINVAL;
+	session = TALITOS_SESSION(sid);
+	if (session < sc->sc_nsessions) {
+		memset(&sc->sc_sessions[session], 0,
+			sizeof(sc->sc_sessions[session]));
+		ret = 0;
+	} else
+		ret = EINVAL;
+	return ret;
+}
+
+/*
+ * launch device processing - it will come back with done notification 
+ * in the form of an interrupt and/or HDR_DONE_BITS in header 
+ */
+static int 
+talitos_submit(
+	struct talitos_softc *sc,
+	struct talitos_desc *td,
+	int chsel)
+{
+	u_int32_t v;
+
+	v = dma_map_single(NULL, td, sizeof(*td), DMA_TO_DEVICE);
+	talitos_write(sc->sc_base_addr + 
+		chsel*TALITOS_CH_OFFSET + TALITOS_CH_FF, 0);
+	talitos_write(sc->sc_base_addr + 
+		chsel*TALITOS_CH_OFFSET + TALITOS_CH_FF_HI, v);
+	return 0;
+}
+
+static int
+talitos_process(device_t dev, struct cryptop *crp, int hint)
+{
+	int i, err = 0, ivsize;
+	struct talitos_softc *sc = device_get_softc(dev);
+	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
+	caddr_t iv;
+	struct talitos_session *ses;
+	struct talitos_desc *td;
+	unsigned long flags;
+	/* descriptor mappings */
+	int hmac_key, hmac_data, cipher_iv, cipher_key, 
+		in_fifo, out_fifo, cipher_iv_out;
+	static int chsel = -1;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	if (crp == NULL || crp->crp_callback == NULL || sc == NULL) {
+		return EINVAL;
+	}
+	crp->crp_etype = 0;
+	if (TALITOS_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
+		return EINVAL;
+	}
+
+	ses = &sc->sc_sessions[TALITOS_SESSION(crp->crp_sid)];
+
+        /* enter the channel scheduler */ 
+	spin_lock_irqsave(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
+
+	/* reuse channel that already had/has requests for the required EU */
+	for (i = 0; i < sc->sc_num_channels; i++) {
+		if (sc->sc_chnlastalg[i] == crp->crp_desc->crd_alg)
+			break;
+	}
+	if (i == sc->sc_num_channels) {
+		/*
+		 * haven't seen this algo the last sc_num_channels or more
+		 * use round robin in this case
+	 	 * nb: sc->sc_num_channels must be power of 2 
+		 */
+		chsel = (chsel + 1) & (sc->sc_num_channels - 1);
+	} else {
+		/*
+		 * matches channel with same target execution unit; 
+		 * use same channel in this case
+		 */
+		chsel = i;
+	}
+	sc->sc_chnlastalg[chsel] = crp->crp_desc->crd_alg;
+
+        /* release the channel scheduler lock */ 
+	spin_unlock_irqrestore(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
+
+	/* acquire the selected channel fifo lock */
+	spin_lock_irqsave(&sc->sc_chnfifolock[chsel], flags);
+
+	/* find and reserve next available descriptor-cryptop pair */
+	for (i = 0; i < sc->sc_chfifo_len; i++) {
+		if (sc->sc_chnfifo[chsel][i].cf_desc.hdr == 0) {
+			/* 
+			 * ensure correct descriptor formation by
+			 * avoiding inadvertently setting "optional" entries
+			 * e.g. not using "optional" dptr2 for MD/HMAC descs
+			 */
+			memset(&sc->sc_chnfifo[chsel][i].cf_desc,
+				0, sizeof(*td));
+			/* reserve it with done notification request bit */
+			sc->sc_chnfifo[chsel][i].cf_desc.hdr |= 
+				TALITOS_DONE_NOTIFY;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&sc->sc_chnfifolock[chsel], flags);
+
+	if (i == sc->sc_chfifo_len) {
+		/* fifo full */
+		err = ERESTART;
+		goto errout;
+	}
+	
+	td = &sc->sc_chnfifo[chsel][i].cf_desc;
+	sc->sc_chnfifo[chsel][i].cf_crp = crp;
+
+	crd1 = crp->crp_desc;
+	if (crd1 == NULL) {
+		err = EINVAL;
+		goto errout;
+	}
+	crd2 = crd1->crd_next;
+	/* prevent compiler warning */
+	hmac_key = 0;
+	hmac_data = 0;
+	if (crd2 == NULL) {
+		td->hdr |= TD_TYPE_COMMON_NONSNOOP_NO_AFEU;
+		/* assign descriptor dword ptr mappings for this desc. type */
+		cipher_iv = 1;
+		cipher_key = 2;
+		in_fifo = 3;
+		cipher_iv_out = 5;
+		if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
+		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
+		    crd1->crd_alg == CRYPTO_SHA1 ||
+		    crd1->crd_alg == CRYPTO_MD5) {
+			out_fifo = 5;
+			maccrd = crd1;
+			enccrd = NULL;
+		} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
+		    crd1->crd_alg == CRYPTO_3DES_CBC ||
+		    crd1->crd_alg == CRYPTO_AES_CBC ||
+		    crd1->crd_alg == CRYPTO_ARC4) {
+			out_fifo = 4;
+			maccrd = NULL;
+			enccrd = crd1;
+		} else {
+			DPRINTF("UNKNOWN crd1->crd_alg %d\n", crd1->crd_alg);
+			err = EINVAL;
+			goto errout;
+		}
+	} else {
+		if (sc->sc_desc_types & TALITOS_HAS_DT_IPSEC_ESP) {
+			td->hdr |= TD_TYPE_IPSEC_ESP;
+		} else {
+			DPRINTF("unimplemented: multiple descriptor ipsec\n");
+			err = EINVAL;
+			goto errout;
+		}
+		/* assign descriptor dword ptr mappings for this desc. type */
+		hmac_key = 0;
+		hmac_data = 1;
+		cipher_iv = 2;
+		cipher_key = 3;
+		in_fifo = 4;
+		out_fifo = 5;
+		cipher_iv_out = 6;
+		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
+                     crd1->crd_alg == CRYPTO_SHA1_HMAC ||
+                     crd1->crd_alg == CRYPTO_MD5 ||
+                     crd1->crd_alg == CRYPTO_SHA1) &&
+		    (crd2->crd_alg == CRYPTO_DES_CBC ||
+		     crd2->crd_alg == CRYPTO_3DES_CBC ||
+		     crd2->crd_alg == CRYPTO_AES_CBC ||
+		     crd2->crd_alg == CRYPTO_ARC4) &&
+		    ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
+			maccrd = crd1;
+			enccrd = crd2;
+		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
+		     crd1->crd_alg == CRYPTO_ARC4 ||
+		     crd1->crd_alg == CRYPTO_3DES_CBC ||
+		     crd1->crd_alg == CRYPTO_AES_CBC) &&
+		    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
+                     crd2->crd_alg == CRYPTO_SHA1_HMAC ||
+                     crd2->crd_alg == CRYPTO_MD5 ||
+                     crd2->crd_alg == CRYPTO_SHA1) &&
+		    (crd1->crd_flags & CRD_F_ENCRYPT)) {
+			enccrd = crd1;
+			maccrd = crd2;
+		} else {
+			/* We cannot order the SEC as requested */
+			printk("%s: cannot do the order\n",
+					device_get_nameunit(sc->sc_cdev));
+			err = EINVAL;
+			goto errout;
+		}
+	}
+	/* assign in_fifo and out_fifo based on input/output struct type */
+	if (crp->crp_flags & CRYPTO_F_SKBUF) {
+		/* using SKB buffers */
+		struct sk_buff *skb = (struct sk_buff *)crp->crp_buf;
+		if (skb_shinfo(skb)->nr_frags) {
+			printk("%s: skb frags unimplemented\n",
+					device_get_nameunit(sc->sc_cdev));
+			err = EINVAL;
+			goto errout;
+		}
+		td->ptr[in_fifo].ptr = dma_map_single(NULL, skb->data, 
+			skb->len, DMA_TO_DEVICE);
+		td->ptr[in_fifo].len = skb->len;
+		td->ptr[out_fifo].ptr = dma_map_single(NULL, skb->data, 
+			skb->len, DMA_TO_DEVICE);
+		td->ptr[out_fifo].len = skb->len;
+		td->ptr[hmac_data].ptr = dma_map_single(NULL, skb->data,
+			skb->len, DMA_TO_DEVICE);
+	} else if (crp->crp_flags & CRYPTO_F_IOV) {
+		/* using IOV buffers */
+		struct uio *uiop = (struct uio *)crp->crp_buf;
+		if (uiop->uio_iovcnt > 1) {
+			printk("%s: iov frags unimplemented\n",
+					device_get_nameunit(sc->sc_cdev));
+			err = EINVAL;
+			goto errout;
+		}
+		td->ptr[in_fifo].ptr = dma_map_single(NULL,
+			uiop->uio_iov->iov_base, crp->crp_ilen, DMA_TO_DEVICE);
+		td->ptr[in_fifo].len = crp->crp_ilen;
+		/* crp_olen is never set; always use crp_ilen */
+		td->ptr[out_fifo].ptr = dma_map_single(NULL,
+			uiop->uio_iov->iov_base,
+			crp->crp_ilen, DMA_TO_DEVICE);
+		td->ptr[out_fifo].len = crp->crp_ilen;
+	} else {
+		/* using contig buffers */
+		td->ptr[in_fifo].ptr = dma_map_single(NULL,
+			crp->crp_buf, crp->crp_ilen, DMA_TO_DEVICE);
+		td->ptr[in_fifo].len = crp->crp_ilen;
+		td->ptr[out_fifo].ptr = dma_map_single(NULL,
+			crp->crp_buf, crp->crp_ilen, DMA_TO_DEVICE);
+		td->ptr[out_fifo].len = crp->crp_ilen;
+	}
+	if (enccrd) {
+		switch (enccrd->crd_alg) {
+		case CRYPTO_3DES_CBC:
+			td->hdr |= TALITOS_MODE0_DEU_3DES;
+			/* FALLTHROUGH */
+		case CRYPTO_DES_CBC:
+			td->hdr |= TALITOS_SEL0_DEU
+				|  TALITOS_MODE0_DEU_CBC;
+			if (enccrd->crd_flags & CRD_F_ENCRYPT)
+				td->hdr |= TALITOS_MODE0_DEU_ENC;
+			ivsize = 2*sizeof(u_int32_t);
+			DPRINTF("%cDES ses %d ch %d len %d\n",
+				(td->hdr & TALITOS_MODE0_DEU_3DES)?'3':'1',
+				(u32)TALITOS_SESSION(crp->crp_sid),
+				chsel, td->ptr[in_fifo].len);
+			break;
+		case CRYPTO_AES_CBC:
+			td->hdr |= TALITOS_SEL0_AESU
+				|  TALITOS_MODE0_AESU_CBC;
+			if (enccrd->crd_flags & CRD_F_ENCRYPT)
+				td->hdr |= TALITOS_MODE0_AESU_ENC;
+			ivsize = 4*sizeof(u_int32_t);
+			DPRINTF("AES  ses %d ch %d len %d\n",
+				(u32)TALITOS_SESSION(crp->crp_sid),
+				chsel, td->ptr[in_fifo].len);
+			break;
+		default:
+			printk("%s: unimplemented enccrd->crd_alg %d\n",
+					device_get_nameunit(sc->sc_cdev), enccrd->crd_alg);
+			err = EINVAL;
+			goto errout;
+		}
+		/*
+		 * Setup encrypt/decrypt state.  When using basic ops
+		 * we can't use an inline IV because hash/crypt offset
+		 * must be from the end of the IV to the start of the
+		 * crypt data and this leaves out the preceding header
+		 * from the hash calculation.  Instead we place the IV
+		 * in the state record and set the hash/crypt offset to
+		 * copy both the header+IV.
+		 */
+		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
+			td->hdr |= TALITOS_DIR_OUTBOUND; 
+			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+				iv = enccrd->crd_iv;
+			else
+				iv = (caddr_t) ses->ses_iv;
+			if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
+				crypto_copyback(crp->crp_flags, crp->crp_buf,
+				    enccrd->crd_inject, ivsize, iv);
+			}
+		} else {
+			td->hdr |= TALITOS_DIR_INBOUND; 
+			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
+				iv = enccrd->crd_iv;
+				bcopy(enccrd->crd_iv, iv, ivsize);
+			} else {
+				iv = (caddr_t) ses->ses_iv;
+				crypto_copydata(crp->crp_flags, crp->crp_buf,
+				    enccrd->crd_inject, ivsize, iv);
+			}
+		}
+		td->ptr[cipher_iv].ptr = dma_map_single(NULL, iv, ivsize, 
+			DMA_TO_DEVICE);
+		td->ptr[cipher_iv].len = ivsize;
+		/*
+		 * we don't need the cipher iv out length/pointer
+		 * field to do ESP IPsec. Therefore we set the len field as 0,
+		 * which tells the SEC not to do anything with this len/ptr
+		 * field. Previously, when length/pointer as pointing to iv,
+		 * it gave us corruption of packets.
+		 */
+		td->ptr[cipher_iv_out].len = 0;
+	}
+	if (enccrd && maccrd) {
+		/* this is ipsec only for now */
+		td->hdr |= TALITOS_SEL1_MDEU
+			|  TALITOS_MODE1_MDEU_INIT
+			|  TALITOS_MODE1_MDEU_PAD;
+		switch (maccrd->crd_alg) {
+			case	CRYPTO_MD5:	
+				td->hdr |= TALITOS_MODE1_MDEU_MD5;
+				break;
+			case	CRYPTO_MD5_HMAC:	
+				td->hdr |= TALITOS_MODE1_MDEU_MD5_HMAC;
+				break;
+			case	CRYPTO_SHA1:	
+				td->hdr |= TALITOS_MODE1_MDEU_SHA1;
+				break;
+			case	CRYPTO_SHA1_HMAC:	
+				td->hdr |= TALITOS_MODE1_MDEU_SHA1_HMAC;
+				break;
+			default:
+				/* We cannot order the SEC as requested */
+				printk("%s: cannot do the order\n",
+						device_get_nameunit(sc->sc_cdev));
+				err = EINVAL;
+				goto errout;
+		}
+		if ((maccrd->crd_alg == CRYPTO_MD5_HMAC) ||
+		   (maccrd->crd_alg == CRYPTO_SHA1_HMAC)) {
+			/*
+			 * The offset from hash data to the start of
+			 * crypt data is the difference in the skips.
+			 */
+			/* ipsec only for now */
+			td->ptr[hmac_key].ptr = dma_map_single(NULL, 
+				ses->ses_hmac, ses->ses_hmac_len, DMA_TO_DEVICE);
+			td->ptr[hmac_key].len = ses->ses_hmac_len;
+			td->ptr[in_fifo].ptr  += enccrd->crd_skip;
+			td->ptr[in_fifo].len  =  enccrd->crd_len;
+			td->ptr[out_fifo].ptr += enccrd->crd_skip;
+			td->ptr[out_fifo].len =  enccrd->crd_len;
+			/* bytes of HMAC to postpend to ciphertext */
+			td->ptr[out_fifo].extent =  ses->ses_mlen;
+			td->ptr[hmac_data].ptr += maccrd->crd_skip; 
+			td->ptr[hmac_data].len = enccrd->crd_skip - maccrd->crd_skip;
+		}
+		if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
+			printk("%s: CRD_F_KEY_EXPLICIT unimplemented\n",
+					device_get_nameunit(sc->sc_cdev));
+		}
+	}
+	if (!enccrd && maccrd) {
+		/* single MD5 or SHA */
+		td->hdr |= TALITOS_SEL0_MDEU
+				|  TALITOS_MODE0_MDEU_INIT
+				|  TALITOS_MODE0_MDEU_PAD;
+		switch (maccrd->crd_alg) {
+			case	CRYPTO_MD5:	
+				td->hdr |= TALITOS_MODE0_MDEU_MD5;
+				DPRINTF("MD5  ses %d ch %d len %d\n",
+					(u32)TALITOS_SESSION(crp->crp_sid), 
+					chsel, td->ptr[in_fifo].len);
+				break;
+			case	CRYPTO_MD5_HMAC:	
+				td->hdr |= TALITOS_MODE0_MDEU_MD5_HMAC;
+				break;
+			case	CRYPTO_SHA1:	
+				td->hdr |= TALITOS_MODE0_MDEU_SHA1;
+				DPRINTF("SHA1 ses %d ch %d len %d\n",
+					(u32)TALITOS_SESSION(crp->crp_sid), 
+					chsel, td->ptr[in_fifo].len);
+				break;
+			case	CRYPTO_SHA1_HMAC:	
+				td->hdr |= TALITOS_MODE0_MDEU_SHA1_HMAC;
+				break;
+			default:
+				/* We cannot order the SEC as requested */
+				DPRINTF("cannot do the order\n");
+				err = EINVAL;
+				goto errout;
+		}
+
+		if (crp->crp_flags & CRYPTO_F_IOV)
+			td->ptr[out_fifo].ptr += maccrd->crd_inject;
+
+		if ((maccrd->crd_alg == CRYPTO_MD5_HMAC) ||
+		   (maccrd->crd_alg == CRYPTO_SHA1_HMAC)) {
+			td->ptr[hmac_key].ptr = dma_map_single(NULL, 
+				ses->ses_hmac, ses->ses_hmac_len, 
+				DMA_TO_DEVICE);
+			td->ptr[hmac_key].len = ses->ses_hmac_len;
+		}
+	} 
+	else {
+		/* using process key (session data has duplicate) */
+		td->ptr[cipher_key].ptr = dma_map_single(NULL, 
+			enccrd->crd_key, (enccrd->crd_klen + 7) / 8, 
+			DMA_TO_DEVICE);
+		td->ptr[cipher_key].len = (enccrd->crd_klen + 7) / 8;
+	}
+	/* descriptor complete - GO! */
+	return talitos_submit(sc, td, chsel);
+
+errout:
+	if (err != ERESTART) {
+		crp->crp_etype = err;
+		crypto_done(crp);
+	}
+	return err;
+}
+
+/* go through all channels descriptors, notifying OCF what has 
+ * _and_hasn't_ successfully completed and reset the device 
+ * (otherwise it's up to decoding desc hdrs!)
+ */
+static void talitos_errorprocessing(struct talitos_softc *sc)
+{
+	unsigned long flags;
+	int i, j;
+
+	/* disable further scheduling until under control */
+	spin_lock_irqsave(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
+
+	if (debug) dump_talitos_status(sc);
+	/* go through descriptors, try and salvage those successfully done, 
+	 * and EIO those that weren't
+	 */
+	for (i = 0; i < sc->sc_num_channels; i++) {
+		spin_lock_irqsave(&sc->sc_chnfifolock[i], flags);
+		for (j = 0; j < sc->sc_chfifo_len; j++) {
+			if (sc->sc_chnfifo[i][j].cf_desc.hdr) {
+				if ((sc->sc_chnfifo[i][j].cf_desc.hdr 
+					& TALITOS_HDR_DONE_BITS) 
+					!= TALITOS_HDR_DONE_BITS) {
+					/* this one didn't finish */
+					/* signify in crp->etype */
+					sc->sc_chnfifo[i][j].cf_crp->crp_etype 
+						= EIO;
+				}
+			} else
+				continue; /* free entry */
+			/* either way, notify ocf */
+			crypto_done(sc->sc_chnfifo[i][j].cf_crp);
+			/* and tag it available again
+			 *
+			 * memset to ensure correct descriptor formation by
+			 * avoiding inadvertently setting "optional" entries
+			 * e.g. not using "optional" dptr2 MD/HMAC processing
+			 */
+			memset(&sc->sc_chnfifo[i][j].cf_desc,
+				0, sizeof(struct talitos_desc));
+		}
+		spin_unlock_irqrestore(&sc->sc_chnfifolock[i], flags);
+	}
+	/* reset and initialize the SEC h/w device */
+	talitos_reset_device(sc);
+	talitos_init_device(sc);
+#ifdef CONFIG_OCF_RANDOMHARVEST
+	if (sc->sc_exec_units & TALITOS_HAS_EU_RNG)
+		talitos_rng_init(sc);
+#endif
+
+	/* Okay. Stand by. */
+	spin_unlock_irqrestore(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
+
+	return;
+}
+
+/* go through all channels descriptors, notifying OCF what's been done */
+static void talitos_doneprocessing(struct talitos_softc *sc)
+{
+	unsigned long flags;
+	int i, j;
+
+	/* go through descriptors looking for done bits */
+	for (i = 0; i < sc->sc_num_channels; i++) {
+		spin_lock_irqsave(&sc->sc_chnfifolock[i], flags);
+		for (j = 0; j < sc->sc_chfifo_len; j++) {
+			/* descriptor has done bits set? */
+			if ((sc->sc_chnfifo[i][j].cf_desc.hdr 
+				& TALITOS_HDR_DONE_BITS) 
+				== TALITOS_HDR_DONE_BITS) {
+				/* notify ocf */
+				crypto_done(sc->sc_chnfifo[i][j].cf_crp);
+				/* and tag it available again
+				 *
+				 * memset to ensure correct descriptor formation by
+				 * avoiding inadvertently setting "optional" entries
+				 * e.g. not using "optional" dptr2 MD/HMAC processing
+				 */
+				memset(&sc->sc_chnfifo[i][j].cf_desc,
+					0, sizeof(struct talitos_desc));
+			}
+		}
+		spin_unlock_irqrestore(&sc->sc_chnfifolock[i], flags);
+	}
+	return;
+}
+
+static irqreturn_t
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+talitos_intr(int irq, void *arg)
+#else
+talitos_intr(int irq, void *arg, struct pt_regs *regs)
+#endif
+{
+	struct talitos_softc *sc = arg;
+	u_int32_t v, v_hi;
+	
+	/* ack */
+	v = talitos_read(sc->sc_base_addr + TALITOS_ISR);
+	v_hi = talitos_read(sc->sc_base_addr + TALITOS_ISR_HI);
+	talitos_write(sc->sc_base_addr + TALITOS_ICR, v);
+	talitos_write(sc->sc_base_addr + TALITOS_ICR_HI, v_hi);
+
+	if (unlikely(v & TALITOS_ISR_ERROR)) {
+		/* Okay, Houston, we've had a problem here. */
+		printk(KERN_DEBUG "%s: got error interrupt - ISR 0x%08x_%08x\n",
+				device_get_nameunit(sc->sc_cdev), v, v_hi);
+		talitos_errorprocessing(sc);
+	} else
+	if (likely(v & TALITOS_ISR_DONE)) {
+		talitos_doneprocessing(sc);
+	}
+	return IRQ_HANDLED;
+}
+
+/*
+ * Initialize registers we need to touch only once.
+ */
+static void
+talitos_init_device(struct talitos_softc *sc)
+{
+	u_int32_t v;
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	/* init all channels */
+	for (i = 0; i < sc->sc_num_channels; i++) {
+		v = talitos_read(sc->sc_base_addr + 
+			i*TALITOS_CH_OFFSET + TALITOS_CH_CCCR_HI);
+		v |= TALITOS_CH_CCCR_HI_CDWE
+		  |  TALITOS_CH_CCCR_HI_CDIE;  /* invoke interrupt if done */
+		talitos_write(sc->sc_base_addr + 
+			i*TALITOS_CH_OFFSET + TALITOS_CH_CCCR_HI, v);
+	}
+	/* enable all interrupts */
+	v = talitos_read(sc->sc_base_addr + TALITOS_IMR);
+	v |= TALITOS_IMR_ALL;
+	talitos_write(sc->sc_base_addr + TALITOS_IMR, v);
+	v = talitos_read(sc->sc_base_addr + TALITOS_IMR_HI);
+	v |= TALITOS_IMR_HI_ERRONLY;
+	talitos_write(sc->sc_base_addr + TALITOS_IMR_HI, v);
+	return;
+}
+
+/*
+ * set the master reset bit on the device.
+ */
+static void
+talitos_reset_device_master(struct talitos_softc *sc)
+{
+	u_int32_t v;
+
+	/* Reset the device by writing 1 to MCR:SWR and waiting 'til cleared */
+	v = talitos_read(sc->sc_base_addr + TALITOS_MCR);
+	talitos_write(sc->sc_base_addr + TALITOS_MCR, v | TALITOS_MCR_SWR);
+
+	while (talitos_read(sc->sc_base_addr + TALITOS_MCR) & TALITOS_MCR_SWR)
+		cpu_relax();
+
+	return;
+}
+
+/*
+ * Resets the device.  Values in the registers are left as is
+ * from the reset (i.e. initial values are assigned elsewhere).
+ */
+static void
+talitos_reset_device(struct talitos_softc *sc)
+{
+	u_int32_t v;
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	/*
+	 * Master reset
+	 * errata documentation: warning: certain SEC interrupts 
+	 * are not fully cleared by writing the MCR:SWR bit, 
+	 * set bit twice to completely reset 
+	 */
+	talitos_reset_device_master(sc);	/* once */
+	talitos_reset_device_master(sc);	/* and once again */
+	
+	/* reset all channels */
+	for (i = 0; i < sc->sc_num_channels; i++) {
+		v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
+			TALITOS_CH_CCCR);
+		talitos_write(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
+			TALITOS_CH_CCCR, v | TALITOS_CH_CCCR_RESET);
+	}
+}
+
+/* Set up the crypto device structure, private data,
+ * and anything else we need before we start */
+#ifdef CONFIG_PPC_MERGE
+static int talitos_probe(struct of_device *ofdev, const struct of_device_id *match)
+#else
+static int talitos_probe(struct platform_device *pdev)
+#endif
+{
+	struct talitos_softc *sc = NULL;
+	struct resource *r;
+#ifdef CONFIG_PPC_MERGE
+	struct device *device = &ofdev->dev;
+	struct device_node *np = ofdev->node;
+	const unsigned int *prop;
+	int err;
+	struct resource res;
+#endif
+	static int num_chips = 0;
+	int rc;
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+
+	sc = (struct talitos_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
+	if (!sc)
+		return -ENOMEM;
+	memset(sc, 0, sizeof(*sc));
+
+	softc_device_init(sc, DRV_NAME, num_chips, talitos_methods);
+
+	sc->sc_irq = -1;
+	sc->sc_cid = -1;
+#ifndef CONFIG_PPC_MERGE
+	sc->sc_dev = pdev;
+#endif
+	sc->sc_num = num_chips++;
+
+#ifdef CONFIG_PPC_MERGE
+	dev_set_drvdata(device, sc);
+#else
+	platform_set_drvdata(sc->sc_dev, sc);
+#endif
+
+	/* get the irq line */
+#ifdef CONFIG_PPC_MERGE
+	err = of_address_to_resource(np, 0, &res);
+	if (err)
+		return -EINVAL;
+	r = &res;
+
+	sc->sc_irq = irq_of_parse_and_map(np, 0);
+#else
+	/* get a pointer to the register memory */
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	sc->sc_irq = platform_get_irq(pdev, 0);
+#endif
+	rc = request_irq(sc->sc_irq, talitos_intr, 0,
+			device_get_nameunit(sc->sc_cdev), sc);
+	if (rc) {
+		printk(KERN_ERR "%s: failed to hook irq %d\n", 
+				device_get_nameunit(sc->sc_cdev), sc->sc_irq);
+		sc->sc_irq = -1;
+		goto out;
+	}
+
+	sc->sc_base_addr = (ocf_iomem_t) ioremap(r->start, (r->end - r->start));
+	if (!sc->sc_base_addr) {
+		printk(KERN_ERR "%s: failed to ioremap\n",
+				device_get_nameunit(sc->sc_cdev));
+		goto out;
+	}
+
+	/* figure out our SEC's properties and capabilities */
+	sc->sc_chiprev = (u64)talitos_read(sc->sc_base_addr + TALITOS_ID) << 32
+		 | talitos_read(sc->sc_base_addr + TALITOS_ID_HI);
+	DPRINTF("sec id 0x%llx\n", sc->sc_chiprev);
+
+#ifdef CONFIG_PPC_MERGE
+	/* get SEC properties from device tree, defaulting to SEC 2.0 */
+
+	prop = of_get_property(np, "num-channels", NULL);
+	sc->sc_num_channels = prop ? *prop : TALITOS_NCHANNELS_SEC_2_0;
+
+	prop = of_get_property(np, "channel-fifo-len", NULL);
+	sc->sc_chfifo_len = prop ? *prop : TALITOS_CHFIFOLEN_SEC_2_0;
+
+	prop = of_get_property(np, "exec-units-mask", NULL);
+	sc->sc_exec_units = prop ? *prop : TALITOS_HAS_EUS_SEC_2_0;
+
+	prop = of_get_property(np, "descriptor-types-mask", NULL);
+	sc->sc_desc_types = prop ? *prop : TALITOS_HAS_DESCTYPES_SEC_2_0;
+#else
+	/* bulk should go away with openfirmware flat device tree support */
+	if (sc->sc_chiprev & TALITOS_ID_SEC_2_0) {
+		sc->sc_num_channels = TALITOS_NCHANNELS_SEC_2_0;
+		sc->sc_chfifo_len = TALITOS_CHFIFOLEN_SEC_2_0;
+		sc->sc_exec_units = TALITOS_HAS_EUS_SEC_2_0;
+		sc->sc_desc_types = TALITOS_HAS_DESCTYPES_SEC_2_0;
+	} else {
+		printk(KERN_ERR "%s: failed to id device\n",
+				device_get_nameunit(sc->sc_cdev));
+		goto out;
+	}
+#endif
+
+	/* + 1 is for the meta-channel lock used by the channel scheduler */
+	sc->sc_chnfifolock = (spinlock_t *) kmalloc(
+		(sc->sc_num_channels + 1) * sizeof(spinlock_t), GFP_KERNEL);
+	if (!sc->sc_chnfifolock)
+		goto out;
+	for (i = 0; i < sc->sc_num_channels + 1; i++) {
+		spin_lock_init(&sc->sc_chnfifolock[i]);
+	}
+
+	sc->sc_chnlastalg = (int *) kmalloc(
+		sc->sc_num_channels * sizeof(int), GFP_KERNEL);
+	if (!sc->sc_chnlastalg)
+		goto out;
+	memset(sc->sc_chnlastalg, 0, sc->sc_num_channels * sizeof(int));
+
+	sc->sc_chnfifo = (struct desc_cryptop_pair **) kmalloc(
+		sc->sc_num_channels * sizeof(struct desc_cryptop_pair *), 
+		GFP_KERNEL);
+	if (!sc->sc_chnfifo)
+		goto out;
+	for (i = 0; i < sc->sc_num_channels; i++) {
+		sc->sc_chnfifo[i] = (struct desc_cryptop_pair *) kmalloc(
+			sc->sc_chfifo_len * sizeof(struct desc_cryptop_pair), 
+			GFP_KERNEL);
+		if (!sc->sc_chnfifo[i])
+			goto out;
+		memset(sc->sc_chnfifo[i], 0, 
+			sc->sc_chfifo_len * sizeof(struct desc_cryptop_pair));
+	}
+
+	/* reset and initialize the SEC h/w device */
+	talitos_reset_device(sc);
+	talitos_init_device(sc);
+
+	sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
+	if (sc->sc_cid < 0) {
+		printk(KERN_ERR "%s: could not get crypto driver id\n",
+				device_get_nameunit(sc->sc_cdev));
+		goto out;
+	}
+
+	/* register algorithms with the framework */
+	printk("%s:", device_get_nameunit(sc->sc_cdev));
+
+	if (sc->sc_exec_units & TALITOS_HAS_EU_RNG)  {
+		printk(" rng");
+#ifdef CONFIG_OCF_RANDOMHARVEST
+		talitos_rng_init(sc);
+		crypto_rregister(sc->sc_cid, talitos_read_random, sc);
+#endif
+	}
+	if (sc->sc_exec_units & TALITOS_HAS_EU_DEU) {
+		printk(" des/3des");
+		crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
+		crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
+	}
+	if (sc->sc_exec_units & TALITOS_HAS_EU_AESU) {
+		printk(" aes");
+		crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
+	}
+	if (sc->sc_exec_units & TALITOS_HAS_EU_MDEU) {
+		printk(" md5");
+		crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
+		/* HMAC support only with IPsec for now */
+		crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
+		printk(" sha1");
+		crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
+		/* HMAC support only with IPsec for now */
+		crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
+	}
+	printk("\n");
+	return 0;
+
+out:
+#ifndef CONFIG_PPC_MERGE
+	talitos_remove(pdev);
+#endif
+	return -ENOMEM;
+}
+
+#ifdef CONFIG_PPC_MERGE
+static int talitos_remove(struct of_device *ofdev)
+#else
+static int talitos_remove(struct platform_device *pdev)
+#endif
+{
+#ifdef CONFIG_PPC_MERGE
+	struct talitos_softc *sc = dev_get_drvdata(&ofdev->dev);
+#else
+	struct talitos_softc *sc = platform_get_drvdata(pdev);
+#endif
+	int i;
+
+	DPRINTF("%s()\n", __FUNCTION__);
+	if (sc->sc_cid >= 0)
+		crypto_unregister_all(sc->sc_cid);
+	if (sc->sc_chnfifo) {
+		for (i = 0; i < sc->sc_num_channels; i++)
+			if (sc->sc_chnfifo[i])
+				kfree(sc->sc_chnfifo[i]);
+		kfree(sc->sc_chnfifo);
+	}
+	if (sc->sc_chnlastalg)
+		kfree(sc->sc_chnlastalg);
+	if (sc->sc_chnfifolock)
+		kfree(sc->sc_chnfifolock);
+	if (sc->sc_irq != -1)
+		free_irq(sc->sc_irq, sc);
+	if (sc->sc_base_addr)
+		iounmap((void *) sc->sc_base_addr);
+	kfree(sc);
+	return 0;
+}
+
+#ifdef CONFIG_PPC_MERGE
+static struct of_device_id talitos_match[] = {
+	{
+		.type = "crypto",
+		.compatible = "talitos",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, talitos_match);
+
+static struct of_platform_driver talitos_driver = {
+	.name		= DRV_NAME,
+	.match_table	= talitos_match,
+	.probe		= talitos_probe,
+	.remove		= talitos_remove,
+};
+
+static int __init talitos_init(void)
+{
+	return of_register_platform_driver(&talitos_driver);
+}
+
+static void __exit talitos_exit(void)
+{
+	of_unregister_platform_driver(&talitos_driver);
+}
+#else
+/* Structure for a platform device driver */
+static struct platform_driver talitos_driver = {
+	.probe = talitos_probe,
+	.remove = talitos_remove,
+	.driver = {
+		.name = "fsl-sec2",
+	}
+};
+
+static int __init talitos_init(void)
+{
+	return platform_driver_register(&talitos_driver);
+}
+
+static void __exit talitos_exit(void)
+{
+	platform_driver_unregister(&talitos_driver);
+}
+#endif
+
+module_init(talitos_init);
+module_exit(talitos_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("kim.phillips@freescale.com");
+MODULE_DESCRIPTION("OCF driver for Freescale SEC (talitos)");
diff --git a/crypto/ocf/talitos/talitos_dev.h b/crypto/ocf/talitos/talitos_dev.h
new file mode 100755
index 0000000..a8b0479
--- /dev/null
+++ b/crypto/ocf/talitos/talitos_dev.h
@@ -0,0 +1,277 @@
+/*
+ * Freescale SEC (talitos) device dependent data structures
+ *
+ * Copyright (c) 2006 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* device ID register values */
+#define TALITOS_ID_SEC_2_0	0x40
+#define TALITOS_ID_SEC_2_1	0x40 /* cross ref with IP block revision reg */
+
+/*
+ * following num_channels, channel-fifo-depth, exec-unit-mask, and 
+ * descriptor-types-mask are for forward-compatibility with openfirmware
+ * flat device trees
+ */
+
+/*
+ *  num_channels : the number of channels available in each SEC version.
+ */
+
+/* n.b. this driver requires these values be a power of 2 */
+#define TALITOS_NCHANNELS_SEC_1_0	4
+#define TALITOS_NCHANNELS_SEC_1_2	1
+#define TALITOS_NCHANNELS_SEC_2_0	4
+#define TALITOS_NCHANNELS_SEC_2_01	4
+#define TALITOS_NCHANNELS_SEC_2_1	4
+#define TALITOS_NCHANNELS_SEC_2_4	4
+
+/*
+ *  channel-fifo-depth : The number of descriptor
+ *  pointers a channel fetch fifo can hold.
+ */
+#define TALITOS_CHFIFOLEN_SEC_1_0	1
+#define TALITOS_CHFIFOLEN_SEC_1_2	1
+#define TALITOS_CHFIFOLEN_SEC_2_0	24
+#define TALITOS_CHFIFOLEN_SEC_2_01	24
+#define TALITOS_CHFIFOLEN_SEC_2_1	24
+#define TALITOS_CHFIFOLEN_SEC_2_4	24
+
+/* 
+ *  exec-unit-mask : The bitmask representing what Execution Units (EUs)
+ *  are available. EU information should be encoded following the SEC's 
+ *  EU_SEL0 bitfield documentation, i.e. as follows:
+ * 
+ *    bit 31 = set if SEC permits no-EU selection (should be always set)
+ *    bit 30 = set if SEC has the ARC4 EU (AFEU)
+ *    bit 29 = set if SEC has the des/3des EU (DEU)
+ *    bit 28 = set if SEC has the message digest EU (MDEU)
+ *    bit 27 = set if SEC has the random number generator EU (RNG)
+ *    bit 26 = set if SEC has the public key EU (PKEU)
+ *    bit 25 = set if SEC has the aes EU (AESU)
+ *    bit 24 = set if SEC has the Kasumi EU (KEU)
+ * 
+ */
+#define TALITOS_HAS_EU_NONE		(1<<0)
+#define TALITOS_HAS_EU_AFEU		(1<<1)
+#define TALITOS_HAS_EU_DEU		(1<<2)
+#define TALITOS_HAS_EU_MDEU		(1<<3)
+#define TALITOS_HAS_EU_RNG		(1<<4)
+#define TALITOS_HAS_EU_PKEU		(1<<5)
+#define TALITOS_HAS_EU_AESU		(1<<6)
+#define TALITOS_HAS_EU_KEU		(1<<7)
+
+/* the corresponding masks for each SEC version */
+#define TALITOS_HAS_EUS_SEC_1_0		0x7f
+#define TALITOS_HAS_EUS_SEC_1_2		0x4d
+#define TALITOS_HAS_EUS_SEC_2_0		0x7f
+#define TALITOS_HAS_EUS_SEC_2_01	0x7f
+#define TALITOS_HAS_EUS_SEC_2_1		0xff
+#define TALITOS_HAS_EUS_SEC_2_4		0x7f
+
+/*
+ *  descriptor-types-mask : The bitmask representing what descriptors
+ *  are available. Descriptor type information should be encoded 
+ *  following the SEC's Descriptor Header Dword DESC_TYPE field 
+ *  documentation, i.e. as follows:
+ *
+ *    bit 0  = set if SEC supports the aesu_ctr_nonsnoop desc. type
+ *    bit 1  = set if SEC supports the ipsec_esp descriptor type
+ *    bit 2  = set if SEC supports the common_nonsnoop desc. type
+ *    bit 3  = set if SEC supports the 802.11i AES ccmp desc. type
+ *    bit 4  = set if SEC supports the hmac_snoop_no_afeu desc. type
+ *    bit 5  = set if SEC supports the srtp descriptor type
+ *    bit 6  = set if SEC supports the non_hmac_snoop_no_afeu desc.type
+ *    bit 7  = set if SEC supports the pkeu_assemble descriptor type
+ *    bit 8  = set if SEC supports the aesu_key_expand_output desc.type
+ *    bit 9  = set if SEC supports the pkeu_ptmul descriptor type
+ *    bit 10 = set if SEC supports the common_nonsnoop_afeu desc. type
+ *    bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
+ *
+ *  ..and so on and so forth.
+ */
+#define TALITOS_HAS_DT_AESU_CTR_NONSNOOP	(1<<0)
+#define TALITOS_HAS_DT_IPSEC_ESP		(1<<1)
+#define TALITOS_HAS_DT_COMMON_NONSNOOP		(1<<2)
+
+/* the corresponding masks for each SEC version */
+#define TALITOS_HAS_DESCTYPES_SEC_2_0	0x01010ebf
+#define TALITOS_HAS_DESCTYPES_SEC_2_1	0x012b0ebf
+
+/* 
+ * a TALITOS_xxx_HI address points to the low data bits (32-63) of the register
+ */
+
+/* global register offset addresses */
+#define TALITOS_ID		0x1020
+#define TALITOS_ID_HI		0x1024
+#define TALITOS_MCR		0x1030		/* master control register */
+#define TALITOS_MCR_HI		0x1038		/* master control register */
+#define TALITOS_MCR_SWR		0x1
+#define TALITOS_IMR		0x1008		/* interrupt mask register */
+#define TALITOS_IMR_ALL		0x00010fff	/* enable all interrupts mask */
+#define TALITOS_IMR_ERRONLY	0x00010aaa	/* enable error interrupts */
+#define TALITOS_IMR_HI		0x100C		/* interrupt mask register */
+#define TALITOS_IMR_HI_ALL	0x00323333	/* enable all interrupts mask */
+#define TALITOS_IMR_HI_ERRONLY	0x00222222	/* enable error interrupts */
+#define TALITOS_ISR		0x1010		/* interrupt status register */
+#define TALITOS_ISR_ERROR	0x00010faa	/* errors mask */
+#define TALITOS_ISR_DONE	0x00000055	/* channel(s) done mask */
+#define TALITOS_ISR_HI		0x1014		/* interrupt status register */
+#define TALITOS_ICR		0x1018		/* interrupt clear register */
+#define TALITOS_ICR_HI		0x101C		/* interrupt clear register */
+
+/* channel register address stride */
+#define TALITOS_CH_OFFSET	0x100
+
+/* channel register offset addresses and bits */
+#define TALITOS_CH_CCCR		0x1108	/* Crypto-Channel Config Register */
+#define TALITOS_CH_CCCR_RESET	0x1	/* Channel Reset bit */
+#define TALITOS_CH_CCCR_HI	0x110c	/* Crypto-Channel Config Register */
+#define TALITOS_CH_CCCR_HI_CDWE	0x10	/* Channel done writeback enable bit */
+#define TALITOS_CH_CCCR_HI_NT	0x4	/* Notification type bit */
+#define TALITOS_CH_CCCR_HI_CDIE	0x2	/* Channel Done Interrupt Enable bit */
+#define TALITOS_CH_CCPSR	0x1110	/* Crypto-Channel Pointer Status Reg */
+#define TALITOS_CH_CCPSR_HI	0x1114	/* Crypto-Channel Pointer Status Reg */
+#define TALITOS_CH_FF		0x1148	/* Fetch FIFO */
+#define TALITOS_CH_FF_HI	0x114c	/* Fetch FIFO's FETCH_ADRS */
+#define TALITOS_CH_CDPR		0x1140	/* Crypto-Channel Pointer Status Reg */
+#define TALITOS_CH_CDPR_HI	0x1144	/* Crypto-Channel Pointer Status Reg */
+#define TALITOS_CH_DESCBUF	0x1180	/* (thru 11bf) Crypto-Channel 
+					 * Descriptor Buffer (debug) */
+
+/* execution unit register offset addresses and bits */
+#define TALITOS_DEUSR		0x2028	/* DEU status register */
+#define TALITOS_DEUSR_HI	0x202c	/* DEU status register */
+#define TALITOS_DEUISR		0x2030	/* DEU interrupt status register */
+#define TALITOS_DEUISR_HI	0x2034	/* DEU interrupt status register */
+#define TALITOS_DEUICR		0x2038	/* DEU interrupt control register */
+#define TALITOS_DEUICR_HI	0x203c	/* DEU interrupt control register */
+#define TALITOS_AESUISR		0x4030	/* AESU interrupt status register */
+#define TALITOS_AESUISR_HI	0x4034	/* AESU interrupt status register */
+#define TALITOS_AESUICR		0x4038	/* AESU interrupt control register */
+#define TALITOS_AESUICR_HI	0x403c	/* AESU interrupt control register */
+#define TALITOS_MDEUISR		0x6030	/* MDEU interrupt status register */
+#define TALITOS_MDEUISR_HI	0x6034	/* MDEU interrupt status register */
+#define TALITOS_RNGSR		0xa028	/* RNG status register */
+#define TALITOS_RNGSR_HI	0xa02c	/* RNG status register */
+#define TALITOS_RNGSR_HI_RD	0x1	/* RNG Reset done */
+#define TALITOS_RNGSR_HI_OFL	0xff0000/* number of dwords in RNG output FIFO*/
+#define TALITOS_RNGDSR		0xa010	/* RNG data size register */
+#define TALITOS_RNGDSR_HI	0xa014	/* RNG data size register */
+#define TALITOS_RNG_FIFO	0xa800	/* RNG FIFO - pool of random numbers */
+#define TALITOS_RNGISR		0xa030	/* RNG Interrupt status register */
+#define TALITOS_RNGISR_HI	0xa034	/* RNG Interrupt status register */
+#define TALITOS_RNGRCR		0xa018	/* RNG Reset control register */
+#define TALITOS_RNGRCR_HI	0xa01c	/* RNG Reset control register */
+#define TALITOS_RNGRCR_HI_SR	0x1	/* RNG RNGRCR:Software Reset */
+
+/* descriptor pointer entry */
+struct talitos_desc_ptr {
+	u16	len;		/* length */
+	u8	extent;		/* jump (to s/g link table) and extent */
+	u8	res;		/* reserved */
+	u32	ptr;		/* pointer */
+};
+
+/* descriptor */
+struct talitos_desc {
+	u32	hdr;				/* header */
+	u32	res;				/* reserved */
+	struct talitos_desc_ptr		ptr[7];	/* ptr/len pair array */
+};
+
+/* talitos descriptor header (hdr) bits */
+
+/* primary execution unit select */
+#define	TALITOS_SEL0_AFEU	0x10000000
+#define	TALITOS_SEL0_DEU	0x20000000
+#define	TALITOS_SEL0_MDEU	0x30000000
+#define	TALITOS_SEL0_RNG	0x40000000
+#define	TALITOS_SEL0_PKEU	0x50000000
+#define	TALITOS_SEL0_AESU	0x60000000
+
+/* primary execution unit mode (MODE0) and derivatives */
+#define	TALITOS_MODE0_AESU_CBC		0x00200000
+#define	TALITOS_MODE0_AESU_ENC		0x00100000
+#define	TALITOS_MODE0_DEU_CBC		0x00400000
+#define	TALITOS_MODE0_DEU_3DES		0x00200000
+#define	TALITOS_MODE0_DEU_ENC		0x00100000
+#define	TALITOS_MODE0_MDEU_INIT		0x01000000	/* init starting regs */
+#define	TALITOS_MODE0_MDEU_HMAC		0x00800000
+#define	TALITOS_MODE0_MDEU_PAD		0x00400000	/* PD */
+#define	TALITOS_MODE0_MDEU_MD5		0x00200000
+#define	TALITOS_MODE0_MDEU_SHA256	0x00100000
+#define	TALITOS_MODE0_MDEU_SHA1		0x00000000	/* SHA-160 */
+#define	TALITOS_MODE0_MDEU_MD5_HMAC	\
+		(TALITOS_MODE0_MDEU_MD5 | TALITOS_MODE0_MDEU_HMAC)
+#define	TALITOS_MODE0_MDEU_SHA256_HMAC	\
+		(TALITOS_MODE0_MDEU_SHA256 | TALITOS_MODE0_MDEU_HMAC)
+#define	TALITOS_MODE0_MDEU_SHA1_HMAC	\
+		(TALITOS_MODE0_MDEU_SHA1 | TALITOS_MODE0_MDEU_HMAC)
+
+/* secondary execution unit select (SEL1) */
+/* it's MDEU or nothing */
+#define	TALITOS_SEL1_MDEU	0x00030000
+
+/* secondary execution unit mode (MODE1) and derivatives */
+#define	TALITOS_MODE1_MDEU_INIT		0x00001000	/* init starting regs */
+#define	TALITOS_MODE1_MDEU_HMAC		0x00000800
+#define	TALITOS_MODE1_MDEU_PAD		0x00000400	/* PD */
+#define	TALITOS_MODE1_MDEU_MD5		0x00000200
+#define	TALITOS_MODE1_MDEU_SHA256	0x00000100
+#define	TALITOS_MODE1_MDEU_SHA1		0x00000000	/* SHA-160 */
+#define	TALITOS_MODE1_MDEU_MD5_HMAC	\
+	(TALITOS_MODE1_MDEU_MD5 | TALITOS_MODE1_MDEU_HMAC)
+#define	TALITOS_MODE1_MDEU_SHA256_HMAC	\
+	(TALITOS_MODE1_MDEU_SHA256 | TALITOS_MODE1_MDEU_HMAC)
+#define	TALITOS_MODE1_MDEU_SHA1_HMAC	\
+	(TALITOS_MODE1_MDEU_SHA1 | TALITOS_MODE1_MDEU_HMAC)
+
+/* direction of overall data flow (DIR) */
+#define	TALITOS_DIR_OUTBOUND	0x00000000
+#define	TALITOS_DIR_INBOUND	0x00000002
+
+/* done notification (DN) */
+#define	TALITOS_DONE_NOTIFY	0x00000001
+
+/* descriptor types */
+/* odd numbers here are valid on SEC2 and greater only (e.g. ipsec_esp) */
+#define TD_TYPE_AESU_CTR_NONSNOOP	(0 << 3)
+#define TD_TYPE_IPSEC_ESP		(1 << 3)
+#define TD_TYPE_COMMON_NONSNOOP_NO_AFEU	(2 << 3)
+#define TD_TYPE_HMAC_SNOOP_NO_AFEU	(4 << 3)
+
+#define TALITOS_HDR_DONE_BITS	0xff000000
+
+#define	DPRINTF(a...)	do { \
+						if (debug) { \
+							printk("%s: ", sc ? \
+								device_get_nameunit(sc->sc_cdev) : "talitos"); \
+							printk(a); \
+						} \
+					} while (0)
diff --git a/crypto/ocf/talitos/talitos_soft.h b/crypto/ocf/talitos/talitos_soft.h
new file mode 100755
index 0000000..79efdbd
--- /dev/null
+++ b/crypto/ocf/talitos/talitos_soft.h
@@ -0,0 +1,77 @@
+/*
+ * Freescale SEC data structures for integration with ocf-linux
+ *
+ * Copyright (c) 2006 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * paired descriptor and associated crypto operation
+ */
+struct desc_cryptop_pair {
+	struct talitos_desc	cf_desc;	/* descriptor ptr */
+	struct cryptop		*cf_crp;	/* cryptop ptr */
+};
+
+/*
+ * Holds data specific to a single talitos device.
+ */
+struct talitos_softc {
+	softc_device_decl	sc_cdev;
+	struct platform_device	*sc_dev;	/* device backpointer */
+	ocf_iomem_t		sc_base_addr;
+	int			sc_irq;
+	int			sc_num;		/* if we have multiple chips */
+	int32_t			sc_cid;		/* crypto tag */
+	u64			sc_chiprev;	/* major/minor chip revision */
+	int			sc_nsessions;
+	struct talitos_session	*sc_sessions;
+	int			sc_num_channels;/* number of crypto channels */
+	int			sc_chfifo_len;	/* channel fetch fifo len */
+	int			sc_exec_units;	/* execution units mask */
+	int			sc_desc_types;	/* descriptor types mask */
+	/*
+	 * mutual exclusion for intra-channel resources, e.g. fetch fifos
+	 * the last entry is a meta-channel lock used by the channel scheduler
+	 */
+	spinlock_t		*sc_chnfifolock;
+	/* sc_chnlastalgo contains last algorithm for that channel */
+	int			*sc_chnlastalg;
+	/* sc_chnfifo holds pending descriptor--crypto operation pairs */
+	struct desc_cryptop_pair	**sc_chnfifo;
+};
+
+struct talitos_session {
+	u_int32_t	ses_used;
+	u_int32_t	ses_klen;		/* key length in bits */
+	u_int32_t	ses_key[8];		/* DES/3DES/AES key */
+	u_int32_t	ses_hmac[5];		/* hmac inner state */
+	u_int32_t	ses_hmac_len;		/* hmac length */
+	u_int32_t	ses_iv[4];		/* DES/3DES/AES iv */
+	u_int32_t	ses_mlen;		/* desired hash result len (12=ipsec or 16) */
+};
+
+#define	TALITOS_SESSION(sid)	((sid) & 0x0fffffff)
+#define	TALITOS_SID(crd, sesn)	(((crd) << 28) | ((sesn) & 0x0fffffff))
diff --git a/crypto/ocf/uio.h b/crypto/ocf/uio.h
new file mode 100755
index 0000000..e82e46c
--- /dev/null
+++ b/crypto/ocf/uio.h
@@ -0,0 +1,54 @@
+#ifndef _OCF_UIO_H_
+#define _OCF_UIO_H_
+
+#include <linux/uio.h>
+
+/*
+ * The linux uio.h doesn't have all we need.  To be fully api compatible
+ * with the BSD cryptodev,  we need to keep this around.  Perhaps this can
+ * be moved back into the linux/uio.h
+ *
+ * Linux port done by David McCullough <david_mccullough@securecomputing.com>
+ * Copyright (C) 2006-2007 David McCullough
+ * Copyright (C) 2004-2005 Intel Corporation.
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ * ---------------------------------------------------------------------------
+ */
+
+struct uio {
+	struct	iovec *uio_iov;
+	int		uio_iovcnt;
+	off_t	uio_offset;
+	int		uio_resid;
+#if 0
+	enum	uio_seg uio_segflg;
+	enum	uio_rw uio_rw;
+	struct  thread *uio_td;
+#endif
+};
+
+#endif
diff --git a/crypto/xor.c b/crypto/xor.c
old mode 100644
new mode 100755
index fc5b836..a767411
--- a/crypto/xor.c
+++ b/crypto/xor.c
@@ -22,6 +22,10 @@
 #include <linux/jiffies.h>
 #include <asm/xor.h>
 
+#ifdef CONFIG_MV_XOR_MEMXOR
+#include <plat/xor.h>
+#endif
+
 /* The xor routines to use.  */
 static struct xor_block_template *active_template;
 
@@ -30,6 +34,13 @@
 {
 	unsigned long *p1, *p2, *p3, *p4;
 
+#ifdef CONFIG_MV_XOR_MEMXOR
+	if ((bytes >= CONFIG_MV_XOR_MEMXOR_THRESHOLD) && (src_count < 8)) {
+		if (!xor_memxor(src_count, bytes, dest, srcs))
+			return;
+	}
+#endif
+
 	p1 = (unsigned long *) srcs[0];
 	if (src_count == 1) {
 		active_template->do_2(bytes, dest, p1);
diff --git a/drivers/Kconfig b/drivers/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c
old mode 100644
new mode 100755
index c0a272c..0f789c8
--- a/drivers/dma/iovlock.c
+++ b/drivers/dma/iovlock.c
@@ -95,7 +95,11 @@
 
 		/* pin pages down */
 		down_read(&current->mm->mmap_sem);
+#ifdef CONFIG_MV_XOR_NET_DMA
+		ret = get_netdma_pages(
+#else
 		ret = get_user_pages(
+#endif
 			current,
 			current->mm,
 			(unsigned long) iov[i].iov_base,
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
old mode 100644
new mode 100755
index c1f7ea0..e7d39e8
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -24,6 +24,12 @@
 
 if HWMON
 
+config THERMAL_SENSOR_KW2
+	bool "KW2 Thermal Sensor"
+	default y
+	help
+	  Enable chip temperature monitoring via sysfs.
+
 config HWMON_VID
 	tristate
 	default n
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
old mode 100644
new mode 100755
index e8fe7f1..c9bb1c3
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -431,7 +431,7 @@
 
 config I2C_MV64XXX
 	tristate "Marvell mv64xxx I2C Controller"
-	depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
+	depends on (MV64X60 || PLAT_ORION || MV88F6281 || MV88F6500) && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the Marvell 64xxx line of host bridges.
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
old mode 100644
new mode 100755
index e165578..e25bbe6
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -1056,6 +1056,8 @@
 			sd->gspca_dev.usb_buf, 1, 500);
 	if (ret < 0)
 		PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value);
+
+	msleep(1);
 	return ret;
 }
 
@@ -1076,6 +1078,8 @@
 		ret = sd->gspca_dev.usb_buf[0];
 	else
 		PDEBUG(D_ERR, "Read reg [0x%02x] failed", index);
+
+	msleep(1);
 	return ret;
 }
 
@@ -1095,6 +1099,8 @@
 		ret = sd->gspca_dev.usb_buf[0];
 	else
 		PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index);
+
+	msleep(1);
 	return ret;
 }
 
@@ -1453,6 +1459,7 @@
 		if (i2c_r(sd, 0x00) < 0)
 			return -EIO;
 	}
+    PDEBUG(D_PROBE, "init_ov_sensor failed after %d attempt(s)", i);
 	return -EIO;
 }
 
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
old mode 100644
new mode 100755
index c5a7a85..60c74b2
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -19,7 +19,11 @@
 #include <linux/mmc/host.h>
 #include "queue.h"
 
+#ifdef CONFIG_ARCH_FEROCEON
+#define MMC_QUEUE_BOUNCESZ	(65536 << 2)
+#else
 #define MMC_QUEUE_BOUNCESZ	65536
+#endif
 
 #define MMC_QUEUE_SUSPENDED	(1 << 0)
 
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
old mode 100644
new mode 100755
index 432ae83..a28591c
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -242,7 +242,7 @@
 
 config MMC_MVSDIO
 	tristate "Marvell MMC/SD/SDIO host driver"
-	depends on PLAT_ORION
+	depends on PLAT_ORION || ARCH_FEROCEON
 	---help---
 	  This selects the Marvell SDIO host driver.
 	  SDIO may currently be found on the Kirkwood 88F6281 and 88F6192
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
old mode 100644
new mode 100755
index 82d1e4d..fb231ac
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -26,9 +26,14 @@
 obj-$(CONFIG_SSFDC)		+= ssfdc.o
 obj-$(CONFIG_MTD_OOPS)		+= mtdoops.o
 
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	obj-$(CONFIG_MV_NAND_SUPPORT) += ../../arch/arm/plat-feroceon/mv_drivers_lsp/mv_mtd/
+endif
+
 nftl-objs		:= nftlcore.o nftlmount.o
 inftl-objs		:= inftlcore.o inftlmount.o
 
 obj-y		+= chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
 
 obj-$(CONFIG_MTD_UBI)		+= ubi/
+
diff --git a/drivers/mtd/chips/Makefile b/drivers/mtd/chips/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
old mode 100644
new mode 100755
index 1479da6..502c537
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -302,13 +302,19 @@
  */
 static int parse_cmdline_partitions(struct mtd_info *master,
                              struct mtd_partition **pparts,
-                             unsigned long origin)
+                             unsigned long origin,
+                             const char *cmd)
 {
 	unsigned long offset;
 	int i;
 	struct cmdline_mtd_partition *part;
 	const char *mtd_id = master->name;
 
+	if (cmd!="") {
+		cmdline = cmd;
+		cmdline_parsed = 0;
+	}
+
 	/* parse command line */
 	if (!cmdline_parsed)
 		mtdpart_setup_real(cmdline);
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
old mode 100644
new mode 100755
index ae2f6db..822b3ac
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -60,4 +60,7 @@
 obj-$(CONFIG_MTD_BFIN_ASYNC)	+= bfin-async-flash.o
 obj-$(CONFIG_MTD_RBTX4939)	+= rbtx4939-flash.o
 obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
-obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+	include $(srctree)/$(MACHINE)/config/mvRules.mk
+	obj-y = ../../../$(MACHINE)/flashmap.o
+endif
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
old mode 100644
new mode 100755
index b8043a9..56b2792
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -573,7 +573,7 @@
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
-			 struct mtd_partition **pparts, unsigned long origin)
+			 struct mtd_partition **pparts, unsigned long origin,const char *cmd)
 {
 	struct mtd_part_parser *parser;
 	int ret = 0;
@@ -587,7 +587,7 @@
 			       *types);
 			continue;
 		}
-		ret = (*parser->parse_fn)(master, pparts, origin);
+		ret = (*parser->parse_fn)(master, pparts, origin, cmd);
 		if (ret > 0) {
 			printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
 			       ret, parser->name, master->name);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
old mode 100644
new mode 100755
index 2fda0b6..6407388
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -11,6 +11,11 @@
 
 if MTD_NAND
 
+config MTD_NAND_CMD
+        string "Nand Command with no bootargs"
+        default "nand_mtd:0x100000@0x0(uboot)ro,0x200000@0x100000(uimage),0xc80000@0x300000(rootfs),0x100000@0xf80000(varfs),0x4000000@0x100000(flash)"
+        help
+
 config MTD_NAND_VERIFY_WRITE
 	bool "Verify NAND page writes"
 	help
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
old mode 100644
new mode 100755
index 2957cc7..2b56446
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -52,6 +52,10 @@
 #include <linux/mtd/partitions.h>
 #endif
 
+#ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
+static char nand_name[128];
+#endif
+
 /* Define default oob placement schemes for large and small page devices */
 static struct nand_ecclayout nand_oob_8 = {
 	.eccbytes = 3,
@@ -2518,10 +2522,21 @@
 	if (!type)
 		return ERR_PTR(-ENODEV);
 
-	if (!mtd->name)
+	if (!mtd->name) {
+#ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
+		sprintf(nand_name, "%s%s", type->name,
+				(chip->num_devs == 2) ? " - Ganged" : "");
+		type->name = nand_name;
+#endif
 		mtd->name = type->name;
+	}
 
 	chip->chipsize = (uint64_t)type->chipsize << 20;
+#ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
+	chip->chipsize *= chip->num_devs;
+	if(chip->num_devs > 1)
+		type->options |= NAND_BUSWIDTH_16;
+#endif
 
 	/* Newer devices have all the information in additional id bytes */
 	if (!type->pagesize) {
@@ -2535,13 +2550,22 @@
 		extid >>= 2;
 		/* Calc oobsize */
 		mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
+#ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
+                        mtd->writesize *= chip->num_devs;
+#endif
 		extid >>= 2;
 		/* Calc blocksize. Blocksize is multiples of 64KiB */
 		mtd->erasesize = (64 * 1024) << (extid & 0x03);
+#ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
+                        mtd->erasesize *= chip->num_devs;
+#endif
 		extid >>= 2;
 		/* Get buswidth information */
 		busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
-
+#ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
+                        if(chip->num_devs > 1)
+                                busw = NAND_BUSWIDTH_16;
+#endif
 	} else {
 		/*
 		 * Old devices have chip data hardcoded in the device id table
@@ -2549,7 +2573,16 @@
 		mtd->erasesize = type->erasesize;
 		mtd->writesize = type->pagesize;
 		mtd->oobsize = mtd->writesize / 32;
+#ifdef CONFIG_MTD_NAND_NFC_MLC_SUPPORT
+		/* New devices have non standard OOB size */
+		if (chip->oobsize_ovrd)
+			mtd->oobsize = chip->oobsize_ovrd;
+#endif
 		busw = type->options & NAND_BUSWIDTH_16;
+#ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
+		mtd->erasesize *= chip->num_devs;
+		mtd->writesize *= chip->num_devs;
+#endif
 	}
 
 	/* Try to identify manufacturer */
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
old mode 100644
new mode 100755
index 55c23e5..88d13fb
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -302,6 +302,35 @@
 	return 1;
 }
 
+#ifdef CONFIG_MTD_NAND_NFC_MLC_SUPPORT
+/*
+ * Scan a given block in the custom location based on Naked symantics
+ */
+static int scan_block_custom(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+                        loff_t offs, uint8_t *buf, int page, int pos)
+{      
+        int ret;
+        struct mtd_oob_ops ops;
+
+        ops.mode = MTD_OOB_RAW;
+        ops.ooboffs = 0;
+        ops.ooblen = mtd->oobsize;
+        ops.oobbuf = (buf + mtd->writesize);
+        ops.datbuf = buf;
+        ops.len = mtd->writesize;
+
+        ret = mtd->read_oob(mtd, (offs + (mtd->writesize * page)), &ops);
+        if (ret)
+                return ret;
+
+        /* Check 2 bytes to cover the ganaged case */
+        if ((buf[pos] != 0xFF) || (buf[pos+1] != 0xFF))
+                return 1;
+
+        return 0;
+}
+#endif
+
 /*
  * Scan a given block full
  */
@@ -416,7 +445,12 @@
 
 	for (i = startblock; i < numblocks;) {
 		int ret;
-
+#ifdef CONFIG_MTD_NAND_NFC_MLC_SUPPORT
+                if (bd->options & NAND_BBT_SCANMVCUSTOM)
+                        ret = scan_block_custom(mtd, bd, from, buf,
+                                                this->bb_page, this->bb_location);
+                else
+#endif
 		if (bd->options & NAND_BBT_SCANALLPAGES)
 			ret = scan_block_full(mtd, bd, from, buf, readlen,
 					      scanlen, len);
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
old mode 100644
new mode 100755
index 69ee2c9..4825f57
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -109,6 +109,15 @@
 	{"NAND 2GiB 1,8V 16-bit",	0xB5, 0, 2048, 0, LP_OPTIONS16},
 	{"NAND 2GiB 3,3V 16-bit",	0xC5, 0, 2048, 0, LP_OPTIONS16},
 
+#ifdef CONFIG_MTD_NAND_NFC_MLC_SUPPORT
+        /* 32 Gigabit - wrongly detected due to changes in READ_ID decoding */
+        {"NAND 4GiB 3,3V 8-bit",        0xD7, 4096, 4096, 524288, LP_OPTIONS},
+        /* 32 Gigabit - wrongly detected due to changes in READ_ID decoding */
+        {"NAND 8GiB 3,3V 8-bit",        0x88, 8192, 8192, 2097152, LP_OPTIONS},
+#else
+        /* 32 Gigabit */
+        {"NAND 4GiB 3,3V 8-bit",        0xD7, 0, 4096, 0, LP_OPTIONS},
+#endif
 	/*
 	 * Renesas AND 1 Gigabit. Those chips do not support extended id and
 	 * have a strange page/block layout !  The chosen minimum erasesize is
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
old mode 100644
new mode 100755
index b2f71f7..b731534
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2282,6 +2282,33 @@
 	  To compile this driver as a module, choose M here. The module
 	  will be called via-velocity.
 
+config SK98LIN
+        tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
+        depends on PCI && !SKGE && !SKY2
+        ---help---
+          Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
+          compliant Gigabit Ethernet Adapter.
+          
+          The adapters support Jumbo Frames.
+          The dual link adapters support link-failover and dual port features.
+          Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support 
+          the scatter-gather functionality with sendfile(). Please refer to 
+          Documentation/networking/sk98lin.txt for more information about
+          optional driver parameters.
+          Questions concerning this driver may be addressed to:
+              linux@syskonnect.de
+          
+          If you want to compile this driver as a module ( = code which can be
+          inserted in and removed from the running kernel whenever you want),
+          say M here and read Documentation/modules.txt. This is recommended.
+          The module will be called sk98lin. This is recommended.
+
+config SK98LIN_NAPI
+        bool "Use Rx polling (NAPI)"
+        depends on SK98LIN
+        help
+          NAPI is a new driver API designed to reduce CPU and interrupt load
+          when the driver is receiving lots of packets from the card.
 config TIGON3
 	tristate "Broadcom Tigon3 support"
 	depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
old mode 100644
new mode 100755
index 246323d..3632f18
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -1,6 +1,8 @@
 #
 # Makefile for the Linux network (ethercard) device drivers.
 #
+obj-$(CONFIG_MV_ETH_LEGACY) += ../../arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/
+obj-$(CONFIG_MV_ETH_NETA) += ../../arch/arm/plat-feroceon/mv_drivers_lsp/mv_neta/net_dev/
 
 obj-$(CONFIG_MII) += mii.o
 obj-$(CONFIG_MDIO) += mdio.o
@@ -91,6 +93,7 @@
 obj-$(CONFIG_TC35815) += tc35815.o
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
+obj-$(CONFIG_SK98LIN) += sk98lin/
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_KS8842)	+= ks8842.o
 obj-$(CONFIG_KS8851)	+= ks8851.o
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index f590bea..30243f3 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -101,6 +101,11 @@
 {
 	skb->protocol = eth_type_trans(skb, netdev);
 
+#ifdef CONFIG_MV_ETH_NFP_EXT
+	if (!mv_eth_nfp_ext(adapter->netdev, skb, NULL))
+		return;
+#endif /* CONFIG_MV_ETH_NFP_EXT */
+
 	if (adapter->vlgrp && (status & E1000_RXD_STAT_VP))
 		vlan_gro_receive(&adapter->napi, adapter->vlgrp,
 				 le16_to_cpu(vlan), skb);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
old mode 100644
new mode 100755
index 965adb6..91a2292
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -55,6 +55,7 @@
 
 #define PPP_VERSION	"2.4.2"
 
+
 /*
  * Network protocols we support.
  */
@@ -2178,6 +2179,25 @@
 	return unit;
 }
 
+/* added for backporting from 3.0.6 kernel for NFP */
+/*
+ * Return the PPP device interface name of a channel.
+ */
+
+char *ppp_dev_name(struct ppp_channel *chan)
+{
+	struct channel *pch = chan->ppp;
+	char *name = NULL;
+
+	if (pch) {
+		read_lock_bh(&pch->upl);
+		if (pch->ppp && pch->ppp->dev)
+			name = pch->ppp->dev->name;
+		read_unlock_bh(&pch->upl);
+	}
+	return name;
+}
+
 /*
  * Disconnect a channel from the generic layer.
  * This must be called in process context.
@@ -2551,6 +2571,7 @@
 	ppp->dev = dev;
 	ppp->mru = PPP_MRU;
 	init_ppp_file(&ppp->file, INTERFACE);
+
 	ppp->file.hdrlen = PPP_HDRLEN - 2;	/* don't count proto bytes */
 	for (i = 0; i < NUM_NP; ++i)
 		ppp->npmode[i] = NPMODE_PASS;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
old mode 100644
new mode 100755
index 2559991..6b829ce
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -77,6 +77,7 @@
 #include <linux/file.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/if_arp.h>
 
 #include <linux/nsproxy.h>
 #include <net/net_namespace.h>
@@ -85,6 +86,11 @@
 
 #include <asm/uaccess.h>
 
+#if defined(CONFIG_MV_ETH_NFP_PPP_LEARN)
+extern void nfp_hook_ppp_del(int ppp_netdev_ifindex);
+extern void nfp_hook_ppp_add(int ppp_if, int eth_iif, u16 sid, u8 *remote_mac);
+#endif /* CONFIG_MV_ETH_NFP_PPP_LEARN */
+
 #define PPPOE_HASH_BITS 4
 #define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS)
 #define PPPOE_HASH_MASK	(PPPOE_HASH_SIZE - 1)
@@ -353,14 +359,44 @@
 			      unsigned long event, void *ptr)
 {
 	struct net_device *dev = (struct net_device *)ptr;
-
 	/* Only look at sockets that are using this specific device. */
 	switch (event) {
+#if defined(CONFIG_MV_ETH_NFP_PPP_LEARN)
+	case NETDEV_UP: {
+		struct net_device *ppp_netdev;
+		struct pppoe_net *pn;
+		int i;
+		
+		if (!(dev->type == ARPHRD_PPP))
+			break;
+
+		pn = pppoe_pernet(&init_net);
+		write_lock_bh(&pn->hash_lock);
+		for (i = 0; i < PPPOE_HASH_SIZE; i++) {
+			struct pppox_sock *po = pn->hash_table[i];
+
+			while (po) {
+				if ((ppp_dev_name(&po->chan) != NULL)
+					&& (!strcmp(ppp_dev_name(&po->chan), dev->name))) {
+					ppp_netdev = dev_get_by_name(&init_net, ppp_dev_name(&po->chan));
+					nfp_hook_ppp_add(ppp_netdev->ifindex,
+									po->pppoe_dev->ifindex, po->pppoe_pa.sid,
+									po->pppoe_pa.remote);
+					dev_put(ppp_netdev);
+					break;
+				}
+				po = po->next;
+			}
+		}
+		write_unlock_bh(&pn->hash_lock);
+	}
+	break;
+#endif /* CONFIG_MV_ETH_NFP_PPP_LEARN */
+
 	case NETDEV_CHANGEMTU:
 		/* A change in mtu is a bad thing, requiring
 		 * LCP re-negotiation.
 		 */
-
 	case NETDEV_GOING_DOWN:
 	case NETDEV_DOWN:
 		/* Find every socket on this device and kill it. */
@@ -588,6 +624,19 @@
 		po->pppoe_dev = NULL;
 	}
 
+#if defined(CONFIG_MV_ETH_NFP_PPP_LEARN)
+	if (ppp_dev_name(&po->chan)) {
+		struct net_device *ppp_netdev = NULL;
+		int ppp_netdev_ifindex = 0;
+		
+		ppp_netdev = dev_get_by_name(&init_net, ppp_dev_name(&po->chan));
+		ppp_netdev_ifindex = ppp_netdev->ifindex;
+		dev_put(ppp_netdev);
+		nfp_hook_ppp_del(ppp_netdev_ifindex);
+	}
+
+#endif
+
 	pppox_unbind_sock(sk);
 
 	/* Signal the death of the socket. */
@@ -600,6 +649,7 @@
 	 * protect "po" from concurrent updates
 	 * on pppoe_flush_dev
 	 */
+
 	delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote,
 		    po->pppoe_ifindex);
 
@@ -700,12 +750,14 @@
 		}
 
 		sk->sk_state = PPPOX_CONNECTED;
+
 	}
 
 	po->num = sp->sa_addr.pppoe.sid;
 
 end:
 	release_sock(sk);
+
 	return error;
 err_put:
 	if (po->pppoe_dev) {
@@ -1138,6 +1190,39 @@
 	.owner	= THIS_MODULE,
 };
 
+#if defined(CONFIG_MV_ETH_NFP_PPP_LEARN)
+void nfp_ppp_sync(void)
+{
+	int i;
+	struct pppoe_net *pn = pppoe_pernet(&init_net);
+	struct net_device *ppp_netdev = NULL;
+	struct pppox_sock *po = NULL;
+
+	rtnl_lock();
+	
+	write_lock_bh(&pn->hash_lock);
+	for (i = 0; i < PPPOE_HASH_SIZE; i++) {
+		po = pn->hash_table[i];
+
+		while (po) {
+			if (ppp_dev_name(&po->chan) != NULL) {
+				ppp_netdev = dev_get_by_name(&init_net, ppp_dev_name(&po->chan));
+				nfp_hook_ppp_add(ppp_netdev->ifindex,
+						po->pppoe_dev->ifindex, po->pppoe_pa.sid,
+						po->pppoe_pa.remote);
+				dev_put(ppp_netdev);
+				}
+			po = po->next;
+		}
+	}
+	write_unlock_bh(&pn->hash_lock);
+
+	rtnl_unlock();
+}
+EXPORT_SYMBOL(nfp_ppp_sync);
+
+#endif /* CONFIG_MV_ETH_NFP_PPP_LEARN */
+
 static __net_init int pppoe_init_net(struct net *net)
 {
 	struct pppoe_net *pn;
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
new file mode 100755
index 0000000..1b52a1a
--- /dev/null
+++ b/drivers/net/sk98lin/Makefile
@@ -0,0 +1,168 @@
+#******************************************************************************
+#
+# Name:         skge.c
+# Project:      GEnesis, PCI Gigabit Ethernet Adapter
+# Version:      $Revision: 1.1.4.3 $
+# Date:         $Date: 2006/12/14 15:23:13 $
+# Purpose:      The main driver source module
+#
+#******************************************************************************
+
+#******************************************************************************
+#
+#	(C)Copyright 1998-2002 SysKonnect GmbH.
+#	(C)Copyright 2002-2005 Marvell.
+#
+#	Makefile for Marvell Yukon chipset and SysKonnect Gigabit Ethernet 
+#	Server Adapter driver. (Kernel 2.6)
+#
+#	Author: Mirko Lindner (mlindner@syskonnect.de)
+#		Ralph Roesler (rroesler@syskonnect.de)
+#
+#	Address all question to: linux@syskonnect.de
+#
+#	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.
+#
+#	The information in this file is provided "AS IS" without warranty.
+# 
+#******************************************************************************
+
+#******************************************************************************
+#
+# History:
+#
+#	$Log: Makefile2.6,v $
+#	Revision 1.1.4.3  2006/12/14 15:23:13  mlindner
+#	Add: Enable Yukon Extreme. Define SK_EXTREME enabled
+#	
+#	Revision 1.1.4.2  2006/08/28 12:44:39  mlindner
+#	Add: install.sh script handling added
+#	
+#	Revision 1.1.4.1  2006/08/28 09:01:59  mlindner
+#	Add: Initial IPMI kernel 2.4 and 2.6 support
+#	
+#	Revision 1.1  2006/07/19 15:37:22  amock
+#	Imported/updated from Release Server GELIN_V8_35_02
+#	
+#	Revision 1.9.2.1  2005/04/11 09:01:18  mlindner
+#	Fix: Copyright year changed
+#	
+#	Revision 1.9  2004/07/13 15:54:50  rroesler
+#	Add: file skethtool.c
+#	Fix: corrected header regarding copyright
+#	Fix: minor typos corrected
+#	
+#	Revision 1.8  2004/06/08 08:39:38  mlindner
+#	Fix: Add CONFIG_SK98LIN_ZEROCOPY as default
+#	
+#	Revision 1.7  2004/06/03 16:06:56  mlindner
+#	Fix: Added compile flag SK_DIAG_SUPPORT
+#	
+#	Revision 1.6  2004/06/02 08:02:59  mlindner
+#	Add: Changed header information and inserted a GPL statement
+#	
+#
+#******************************************************************************
+
+
+#
+# Standalone driver params
+# SKPARAM += -DSK_KERNEL_24
+# SKPARAM += -DSK_KERNEL_24_26
+# SKPARAM += -DSK_KERNEL_26
+# SKPARAM += -DSK_KERNEL_22_24
+# ASFPARAM += -DSK_ASF
+
+ifdef ASFPARAM
+	ASF_OPS += \
+		skgeasf.o	\
+		skgeasfconv.o	\
+		skgespi.o	\
+		skgespilole.o	\
+		skfops.o
+else
+	ASF_OPS +=
+endif
+
+
+
+obj-$(CONFIG_SK98LIN) += sk98lin.o
+sk98lin-objs    :=	\
+		skge.o		\
+		sky2.o		\
+		skethtool.o	\
+		sky2le.o	\
+		skdim.o		\
+		skaddr.o	\
+		skgehwt.o	\
+		skgeinit.o	\
+		skgepnmi.o	\
+		skgesirq.o	\
+		sktwsi.o	\
+		sklm80.o	\
+		skqueue.o	\
+		skrlmt.o	\
+		sktimer.o	\
+		skvpd.o		\
+		skxmac2.o	\
+		skproc.o	\
+		skcsum.o	\
+		$(ASF_OPS)
+# DBGDEF =  \
+# -DDEBUG
+
+ifdef DEBUG
+DBGDEF +=  \
+-DSK_DEBUG_CHKMOD=0x00000000L \
+-DSK_DEBUG_CHKCAT=0x00000000L
+endif
+
+
+# **** possible debug modules for SK_DEBUG_CHKMOD *****************
+# SK_DBGMOD_MERR        0x00000001L     /* general module error indication */
+# SK_DBGMOD_HWM         0x00000002L     /* Hardware init module */
+# SK_DBGMOD_RLMT        0x00000004L     /* RLMT module */
+# SK_DBGMOD_VPD         0x00000008L     /* VPD module */
+# SK_DBGMOD_I2C         0x00000010L     /* I2C module */
+# SK_DBGMOD_PNMI        0x00000020L     /* PNMI module */
+# SK_DBGMOD_CSUM        0x00000040L     /* CSUM module */
+# SK_DBGMOD_ADDR        0x00000080L     /* ADDR module */
+# SK_DBGMOD_DRV         0x00010000L     /* DRV module */
+
+# **** possible debug categories for SK_DEBUG_CHKCAT **************
+# *** common modules ***
+# SK_DBGCAT_INIT        0x00000001L     module/driver initialization
+# SK_DBGCAT_CTRL        0x00000002L     controlling: add/rmv MCA/MAC and other controls (IOCTL)
+# SK_DBGCAT_ERR         0x00000004L     error handling paths
+# SK_DBGCAT_TX          0x00000008L     transmit path
+# SK_DBGCAT_RX          0x00000010L     receive path
+# SK_DBGCAT_IRQ         0x00000020L     general IRQ handling
+# SK_DBGCAT_QUEUE       0x00000040L     any queue management
+# SK_DBGCAT_DUMP        0x00000080L     large data output e.g. hex dump
+# SK_DBGCAT_FATAL       0x00000100L     large data output e.g. hex dump
+
+# *** driver (file skge.c) ***
+# SK_DBGCAT_DRV_ENTRY           0x00010000      entry points
+# SK_DBGCAT_DRV_???             0x00020000      not used
+# SK_DBGCAT_DRV_MCA             0x00040000      multicast
+# SK_DBGCAT_DRV_TX_PROGRESS     0x00080000      tx path
+# SK_DBGCAT_DRV_RX_PROGRESS     0x00100000      rx path
+# SK_DBGCAT_DRV_PROGRESS        0x00200000      general runtime
+# SK_DBGCAT_DRV_???             0x00400000      not used
+# SK_DBGCAT_DRV_PROM            0x00800000      promiscuous mode
+# SK_DBGCAT_DRV_TX_FRAME        0x01000000      display tx frames
+# SK_DBGCAT_DRV_ERROR           0x02000000      error conditions
+# SK_DBGCAT_DRV_INT_SRC         0x04000000      interrupts sources
+# SK_DBGCAT_DRV_EVENT           0x08000000      driver events
+
+EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_USE_CSUM -DSK_DIAG_SUPPORT \
+		-DGENESIS -DYUKON -DYUK2 -DCONFIG_SK98LIN_ZEROCOPY \
+		-DSK_EXTREME $(DBGDEF) $(SKPARAM) $(ASFPARAM)
+
+clean:
+	rm -f core *.o *.a *.s
+
+
diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
new file mode 100755
index 0000000..d75e75b
--- /dev/null
+++ b/drivers/net/sk98lin/h/lm80.h
@@ -0,0 +1,181 @@
+/******************************************************************************
+ *
+ * Name:	lm80.h	
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.2 $
+ * Date:	$Date: 2005/12/14 16:11:35 $
+ * Purpose:	Contains all defines for the LM80 Chip
+ *		(National Semiconductor).
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef __INC_LM80_H
+#define __INC_LM80_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+/* defines ********************************************************************/
+
+/*
+ * LM80 register definition
+ *
+ * All registers are 8 bit wide
+ */
+#define LM80_CFG			0x00	/* Configuration Register */
+#define LM80_ISRC_1			0x01	/* Interrupt Status Register 1 */
+#define LM80_ISRC_2			0x02	/* Interrupt Status Register 2 */
+#define LM80_IMSK_1			0x03	/* Interrupt Mask Register 1 */
+#define LM80_IMSK_2			0x04	/* Interrupt Mask Register 2 */
+#define LM80_FAN_CTRL		0x05	/* Fan Devisor/RST#/OS# Register */
+#define LM80_TEMP_CTRL		0x06	/* OS# Config, Temp Res. Reg */
+	/* 0x07 - 0x1f reserved	*/
+	/* current values */
+#define LM80_VT0_IN			0x20	/* current Voltage 0 value */
+#define LM80_VT1_IN			0x21	/* current Voltage 1 value */
+#define LM80_VT2_IN			0x22	/* current Voltage 2 value */
+#define LM80_VT3_IN			0x23	/* current Voltage 3 value */
+#define LM80_VT4_IN			0x24	/* current Voltage 4 value */
+#define LM80_VT5_IN			0x25	/* current Voltage 5 value */
+#define LM80_VT6_IN			0x26	/* current Voltage 6 value */
+#define LM80_TEMP_IN		0x27	/* current Temperature value */
+#define LM80_FAN1_IN		0x28	/* current Fan 1 count */
+#define LM80_FAN2_IN		0x29	/* current Fan 2 count */
+	/* limit values */
+#define LM80_VT0_HIGH_LIM	0x2a	/* high limit val for Voltage 0 */
+#define LM80_VT0_LOW_LIM	0x2b	/* low limit val for Voltage 0 */
+#define LM80_VT1_HIGH_LIM	0x2c	/* high limit val for Voltage 1 */
+#define LM80_VT1_LOW_LIM	0x2d	/* low limit val for Voltage 1 */
+#define LM80_VT2_HIGH_LIM	0x2e	/* high limit val for Voltage 2 */
+#define LM80_VT2_LOW_LIM	0x2f	/* low limit val for Voltage 2 */
+#define LM80_VT3_HIGH_LIM	0x30	/* high limit val for Voltage 3 */
+#define LM80_VT3_LOW_LIM	0x31	/* low limit val for Voltage 3 */
+#define LM80_VT4_HIGH_LIM	0x32	/* high limit val for Voltage 4 */
+#define LM80_VT4_LOW_LIM	0x33	/* low limit val for Voltage 4 */
+#define LM80_VT5_HIGH_LIM	0x34	/* high limit val for Voltage 5 */
+#define LM80_VT5_LOW_LIM	0x35	/* low limit val for Voltage 5 */
+#define LM80_VT6_HIGH_LIM	0x36	/* high limit val for Voltage 6 */
+#define LM80_VT6_LOW_LIM	0x37	/* low limit val for Voltage 6 */
+#define LM80_THOT_LIM_UP	0x38	/* hot temperature limit (high) */
+#define LM80_THOT_LIM_LO	0x39	/* hot temperature limit (low) */
+#define LM80_TOS_LIM_UP		0x3a	/* OS temperature limit (high) */
+#define LM80_TOS_LIM_LO		0x3b	/* OS temperature limit (low) */
+#define LM80_FAN1_COUNT_LIM	0x3c	/* Fan 1 count limit (high) */
+#define LM80_FAN2_COUNT_LIM	0x3d	/* Fan 2 count limit (low) */
+	/* 0x3e - 0x3f reserved	*/
+
+/*
+ * LM80 bit definitions
+ */
+
+/*	LM80_CFG		Configuration Register */
+#define LM80_CFG_START		(1<<0)	/* start monitoring operation */
+#define LM80_CFG_INT_ENA	(1<<1)	/* enables the INT# Interrupt output */
+#define LM80_CFG_INT_POL	(1<<2)	/* INT# pol: 0 act low, 1 act high */
+#define LM80_CFG_INT_CLR	(1<<3)	/* disables INT#/RST_OUT#/OS# outputs */
+#define LM80_CFG_RESET		(1<<4)	/* signals a reset */
+#define LM80_CFG_CHASS_CLR	(1<<5)	/* clears Chassis Intrusion (CI) pin */
+#define LM80_CFG_GPO		(1<<6)	/* drives the GPO# pin */
+#define LM80_CFG_INIT		(1<<7)	/* restore power on defaults */
+
+/*	LM80_ISRC_1		Interrupt Status Register 1 */
+/*	LM80_IMSK_1		Interrupt Mask Register 1 */
+#define LM80_IS_VT0			(1<<0)	/* limit exceeded for Voltage 0 */
+#define LM80_IS_VT1			(1<<1)	/* limit exceeded for Voltage 1 */
+#define LM80_IS_VT2			(1<<2)	/* limit exceeded for Voltage 2 */
+#define LM80_IS_VT3			(1<<3)	/* limit exceeded for Voltage 3 */
+#define LM80_IS_VT4			(1<<4)	/* limit exceeded for Voltage 4 */
+#define LM80_IS_VT5			(1<<5)	/* limit exceeded for Voltage 5 */
+#define LM80_IS_VT6			(1<<6)	/* limit exceeded for Voltage 6 */
+#define LM80_IS_INT_IN		(1<<7)	/* state of INT_IN# */
+
+/*	LM80_ISRC_2		Interrupt Status Register 2 */
+/*	LM80_IMSK_2		Interrupt Mask Register 2 */
+#define LM80_IS_TEMP		(1<<0)	/* HOT temperature limit exceeded */
+#define LM80_IS_BTI			(1<<1)	/* state of BTI# pin */
+#define LM80_IS_FAN1		(1<<2)	/* count limit exceeded for Fan 1 */
+#define LM80_IS_FAN2		(1<<3)	/* count limit exceeded for Fan 2 */
+#define LM80_IS_CI			(1<<4)	/* Chassis Intrusion occured */
+#define LM80_IS_OS			(1<<5)	/* OS temperature limit exceeded */
+	/* bit 6 and 7 are reserved in LM80_ISRC_2 */
+#define LM80_IS_HT_IRQ_MD	(1<<6)	/* Hot temperature interrupt mode */
+#define LM80_IS_OT_IRQ_MD	(1<<7)	/* OS temperature interrupt mode */
+
+/*	LM80_FAN_CTRL		Fan Devisor/RST#/OS# Register */
+#define LM80_FAN1_MD_SEL	(1<<0)	/* Fan 1 mode select */
+#define LM80_FAN2_MD_SEL	(1<<1)	/* Fan 2 mode select */
+#define LM80_FAN1_PRM_CTL	(3<<2)	/* Fan 1 speed control */
+#define LM80_FAN2_PRM_CTL	(3<<4)	/* Fan 2 speed control */
+#define LM80_FAN_OS_ENA		(1<<6)	/* enable OS mode on RST_OUT#/OS# pins*/
+#define LM80_FAN_RST_ENA	(1<<7)	/* sets RST_OUT#/OS# pins in RST mode */
+
+/*	LM80_TEMP_CTRL		OS# Config, Temp Res. Reg */
+#define LM80_TEMP_OS_STAT	(1<<0)	/* mirrors the state of RST_OUT#/OS# */
+#define LM80_TEMP_OS_POL	(1<<1)	/* select OS# polarity */
+#define LM80_TEMP_OS_MODE	(1<<2)	/* selects Interrupt mode */
+#define LM80_TEMP_RES		(1<<3)	/* selects 9 or 11 bit temp resulution*/
+#define LM80_TEMP_LSB		(0xf<<4)/* 4 LSBs of 11 bit temp data */
+#define LM80_TEMP_LSB_9		(1<<7)	/* LSB of 9 bit temperature data */
+
+	/* 0x07 - 0x1f reserved	*/
+/*	LM80_VT0_IN		current Voltage 0 value */
+/*	LM80_VT1_IN		current Voltage 1 value */
+/*	LM80_VT2_IN		current Voltage 2 value */
+/*	LM80_VT3_IN		current Voltage 3 value */
+/*	LM80_VT4_IN		current Voltage 4 value */
+/*	LM80_VT5_IN		current Voltage 5 value */
+/*	LM80_VT6_IN		current Voltage 6 value */
+/*	LM80_TEMP_IN		current temperature value */
+/*	LM80_FAN1_IN		current Fan 1 count */
+/*	LM80_FAN2_IN		current Fan 2 count */
+/*	LM80_VT0_HIGH_LIM	high limit val for Voltage 0 */
+/*	LM80_VT0_LOW_LIM	low limit val for Voltage 0 */
+/*	LM80_VT1_HIGH_LIM	high limit val for Voltage 1 */
+/*	LM80_VT1_LOW_LIM	low limit val for Voltage 1 */
+/*	LM80_VT2_HIGH_LIM	high limit val for Voltage 2 */
+/*	LM80_VT2_LOW_LIM	low limit val for Voltage 2 */
+/*	LM80_VT3_HIGH_LIM	high limit val for Voltage 3 */
+/*	LM80_VT3_LOW_LIM	low limit val for Voltage 3 */
+/*	LM80_VT4_HIGH_LIM	high limit val for Voltage 4 */
+/*	LM80_VT4_LOW_LIM	low limit val for Voltage 4 */
+/*	LM80_VT5_HIGH_LIM	high limit val for Voltage 5 */
+/*	LM80_VT5_LOW_LIM	low limit val for Voltage 5 */
+/*	LM80_VT6_HIGH_LIM	high limit val for Voltage 6 */
+/*	LM80_VT6_LOW_LIM	low limit val for Voltage 6 */
+/*	LM80_THOT_LIM_UP	hot temperature limit (high) */
+/*	LM80_THOT_LIM_LO	hot temperature limit (low) */
+/*	LM80_TOS_LIM_UP		OS temperature limit (high) */
+/*	LM80_TOS_LIM_LO		OS temperature limit (low) */
+/*	LM80_FAN1_COUNT_LIM	Fan 1 count limit (high) */
+/*	LM80_FAN2_COUNT_LIM	Fan 2 count limit (low) */
+	/* 0x3e - 0x3f reserved	*/
+
+#define LM80_ADDR		0x28	/* LM80 default addr */
+
+/* typedefs *******************************************************************/
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif	/* __INC_LM80_H */
diff --git a/drivers/net/sk98lin/h/mvyexhw.h b/drivers/net/sk98lin/h/mvyexhw.h
new file mode 100755
index 0000000..b153f00
--- /dev/null
+++ b/drivers/net/sk98lin/h/mvyexhw.h
@@ -0,0 +1,5050 @@
+/******************************************************************************
+ *
+ * Name:	mvyexhw.h
+ * Project:	Yukon Extreme, Common Modules
+ * Version:	$Revision: 1.3 $
+ * Date:	$Date: 2007/06/27 15:18:59 $
+ * Purpose:	Defines and Macros for the Yukon Extreme Gigabit Ethernet Adapters
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 2005-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file was automatically generated by reg.pl (Rev. 1.55) using
+ *	Yukon_Extreme_Registers_Config.csv
+ *	Yukon_Extreme_Registers_Control.csv
+ *	Yukon_Extreme_Registers_GMAC.csv
+ *
+ ******************************************************************************/
+
+#ifndef __INC_MVYEXHW_H
+#define __INC_MVYEXHW_H
+
+#define	PCI_VEN_ID						0x0000	/* 16 bit	Vendor ID Register */
+#define	PCI_DEV_ID						0x0002	/* 16 bit	Device ID Register */
+#define	PCI_CMD							0x0004	/* 16 bit	Command Register */
+#define	PCI_STAT						0x0006	/* 16 bit	Status Register */
+//#define	PCI_REV_ID						0x0008	/*  8 bit	Revision ID Register */
+#define	PCI_PIF							0x0009	/*  8 bit	Programming
+												 *			Interface
+												 *			Register, Lower
+												 *			Byte
+												 */
+#define	PCI_SCC							0x000A	/*  8 bit	Sub-Class Register,
+												 *			Middle Byte
+												 */
+#define	PCI_BCC							0x000B	/*  8 bit	Base-Class
+												 *			Register, Upper
+												 *			Byte
+												 */
+#define	PCI_CLS							0x000C	/*  8 bit	Cache Line Size
+												 *			Register
+												 */
+//#define	PCI_LAT_TIM						0x000D	/*  8 bit	Latency Timer
+//												 *			Register
+//												 */
+#define	PCI_HDRTYP						0x000E	/*  8 bit	Header Type Register  */
+//#define	PCI_BIST						0x000F	/*  8 bit	Built-in Self Test
+//												 *			(BIST) Register
+//												 */
+#define	PCI_BAR1_LO						0x0010	/* 32 bit	Base Address
+												 *			Register (1st),
+												 *			Lower Address
+												 */
+#define	PCI_BAR1_HI						0x0014	/* 32 bit	Base Address
+												 *			Register (1st),
+												 *			Upper Address
+												 */
+#define	PCI_BAR2						0x0018	/* 32 bit	Base Address
+												 *			Register (2nd)
+												 */
+#define	PCI_SSVEN_ID					0x002C	/* 16 bit	Subsystem Vendor ID
+												 *			Register
+												 */
+#define	PCI_SSDEV_ID					0x002E	/* 16 bit	Subsystem ID
+												 *			Register
+												 */
+#define	PCI_ERBAR						0x0030	/* 32 bit	Expansion Rom Base
+												 *			Address Register
+												 */
+#define	PCI_NCAP_PTR					0x0034	/*  8 bit	New Capabilities
+												 *			Pointer (New Cap
+												 *			Ptr) Register
+												 */
+#define	PCI_INT_LINE					0x003C	/*  8 bit	Interrupt Line
+												 *			Register
+												 */
+#define	PCI_INT_PIN						0x003D	/*  8 bit	Interrupt Pin
+												 *			Register
+												 */
+//#define	PCI_MIN_GNT						0x003E	/*  8 bit	Min_Gnt Register */
+//#define	PCI_MAX_LAT						0x003F	/*  8 bit	Max_Lat Register */
+#define	PCI_OUR1						0x0040	/* 32 bit	Our Register 1 */
+#define	PCI_OUR2						0x0044	/* 32 bit	Our Register 2 */
+//#define	PCI_PM_CAP_ID					0x0048	/*  8 bit	Power Management
+//												 *			Capability ID
+//												 *			Register (PM Cap
+//												 *			ID)
+//												 */
+#define	PCI_PM_NXT_PTR					0x0049	/*  8 bit	Power Management
+												 *			Next Item Pointer
+												 *			Register
+												 */
+#define	PCI_PM_CAP						0x004A	/* 16 bit	Power Management
+												 *			Capabilities
+												 *			Register
+												 */
+#define	PCI_PM_CSR						0x004C	/* 16 bit	Power Management
+												 *			Control/Status
+												 *			Register
+												 */
+#define	PCI_PM_DATA						0x004F	/*  8 bit	Power Management
+												 *			Data Register
+												 */
+//#define	PCI_VPD_CAP_ID					0x0050	/*  8 bit	VPD Capability ID
+//												 *			Register (VPD Cap
+//												 *			ID)
+//												 */
+#define	PCI_VPD_NPTR					0x0051	/*  8 bit	VPD Next Item
+												 *			Pointer Register
+												 */
+#ifdef XXX	/* Naming Conflict with Linux */
+#define	PCI_VPD_ADDR					0x0052	/* 16 bit	VPD Address Register */
+#define	PCI_VPD_DATA					0x0054	/* 32 bit	VPD Data Register */
+#endif /* XXX */
+#define	PCI_LDR_CTRL					0x0058	/* 32 bit	TWSI EEPROM Loader
+												 *			Control Register
+												 */
+//#define	PCI_MSI_CAP_ID					0x005C	/*  8 bit	MSI Capability ID
+//												 *			Register (MSI Cap
+//												 *			ID)
+//												 */
+#define	PCI_MSI_NPTR					0x005D	/*  8 bit	MSI Next Item
+												 *			Pointer Register
+												 */
+//#define	PCI_MSI_CTRL					0x005E	/* 16 bit	MSI Message Control
+//												 *			Register
+//												 */
+#define	PCI_MSI_ADDR_LO					0x0060	/* 32 bit	MSI Message Address
+												 *			Register, Lower
+												 *			Address
+												 */
+#define	PCI_MSI_ADDR_HI					0x0064	/* 32 bit	MSI Message Address
+												 *			Register, Upper
+												 *			Address
+												 */
+//#define	PCI_MSI_DATA					0x0068	/* 32 bit	MSI Message Data
+//												 *			Register
+//												 */
+#define	PCIE_STAT						0x0070	/* 32 bit	PCI Express Status
+												 *			Register
+												 */
+#define	PCIE_OUR_STAT					0x007C	/* 32 bit	Our Status Register */
+#define	PCIE_OUR3						0x0080	/* 32 bit	Our Register 3 */
+#define	PCIE_OUR4						0x0084	/* 32 bit	Our Register 4 */
+#define	PCIE_OUR5						0x0088	/* 32 bit	Our Register 5 */
+#define	PCIE_ER_MASK					0x008C	/* 32 bit	Error Reporting
+												 *			Mask Register
+												 */
+#define	CONFIG_REG0						0x0090	/* 32 bit	Config Register 0 */
+#define	CONFIG_REG1						0x0094	/* 32 bit	Config Register 1 */
+#define	PSM_CONFIG_REG0					0x0098	/* 32 bit	PSM Config Register
+												 *			0
+												 */
+#define	PSM_CONFIG_REG1					0x009C	/* 32 bit	PSM Config Register
+												 *			1
+												 */
+                                                /* Yukon-FE+ */
+#define	VPD_CTRL_ADD					0x00A0	/* 32 bit	VPD Start End
+												 *			Address
+												 */
+                                                /* Yukon-FE+ */
+#define	OTP_LDR_CTRL					0x00A4	/* 32 bit	OTP Loader Control
+												 *			Register
+												 */
+                                                /* Yukon-FE+ */
+#define	OTP_MEM_CTRL_0					0x00A8	/* 32 bit	OTP Memory Control
+												 *			Register 0
+												 */
+                                                /* Yukon-FE+ */
+#define	OTP_MEM_CTRL_1					0x00AC	/* 32 bit	OTP Memory Control
+												 *			Register 1
+												 */
+                                                /* Yukon-FE+ */
+#define	OTP_MEM_CTRL_2					0x00B0	/* 32 bit	OTP Memory Control
+												 *			Register 2
+												 */
+                                                /* Yukon-FE+ */
+#define	OTP_MEM_ST_0					0x00B4	/* 32 bit	OTP Memory Status
+												 *			Register 0
+												 */
+                                                /* Yukon-FE+ */
+#define	VPD_CTRL						0x00B8	/* 32 bit	EEPROM and OTP
+												 *			Control Register
+												 */
+                                                /* Yukon-FE+ */
+#define	OTP_MEM_CTRL_3					0x00BC	/* 32 bit	LDO Control Register */
+#define	PCIE_CAP_ID						0x00C0	/*  8 bit	PE Capability ID
+												 *			Register (PM Cap
+												 *			ID)
+												 */
+#define	PCIE_NPTR						0x00C1	/*  8 bit	PE Next Item
+												 *			Pointer Register
+												 */
+#define	PCIE_CAP						0x00C2	/* 16 bit	PE Capabilities
+												 *			Register
+												 */
+#define	DEVICE_CAPABILITIES_REGISTER	0x00C4	/* 32 bit	Device Capabilities
+												 *			Register
+												 */
+#define	PCIE_DEVCTRL					0x00C8	/* 16 bit	Device Control
+												 *			Register
+												 */
+#define	PCIE_DEVSTAT					0x00CA	/* 16 bit	Device Status
+												 *			Register
+												 */
+#define	PCIE_LNKCAP						0x00CC	/* 32 bit	Link Capabilities
+												 *			Register
+												 */
+#define	PCIE_LNKCTRL					0x00D0	/* 16 bit	Link Control
+												 *			Register
+												 */
+#define	PCIE_LNKSTAT					0x00D2	/* 16 bit	Link Status Register */
+#define	PCIE_DEV_CAP_2					0x00E4	/* 32 bit	Device Capabilities
+												 *			2 Register
+												 */
+#define	PCIE_DEV_CTRL_2					0x00E8	/* 32 bit	Device Control 2
+												 *			Register
+												 */
+#define	PCIE_AE_CAP_HDR					0x0100	/* 32 bit	Advanced Error
+												 *			Reporting
+												 *			Enhanced
+												 *			Capability Header
+												 *			Register
+												 */
+#define	PCIE_UE_STAT					0x0104	/* 32 bit	Uncorrectable Error
+												 *			Status Register
+												 */
+#define	PCIE_UE_MASK					0x0108	/* 32 bit	Uncorrectable Error
+												 *			Mask Register
+												 */
+#define	PCIE_UE_SVRT					0x010C	/* 32 bit	Uncorrectable Error
+												 *			Severity Register
+												 */
+#define	PCIE_CA_STAT					0x0110	/* 32 bit	Correctable Error
+												 *			Status Register
+												 */
+#define	PCIE_CA_MASK					0x0114	/* 32 bit	Correctable Error
+												 *			Mask Register
+												 */
+#define	PCIE_AE_CAPCTRL					0x0118	/* 32 bit	Advanced Error
+												 *			Capabilities and
+												 *			Control Register
+												 */
+#define	PCIE_HDRLOG						0x011C 	/* 13 bit	Header Log Registers */
+#define	PCIE_DEVSERNUMCAP				0x0130	/* 32 bit	Device Serial
+												 *			Number Enhanced
+												 *			Capability Header
+												 */
+#define	PCIE_SERNUM_LOWDW				0x0134	/* 32 bit	Serial Number
+												 *			Register (Lower
+												 *			DW)
+												 */
+#define	PCIE_SERNUM_UPPDW				0x0138	/* 32 bit	Serial Number
+												 *			Register (Upper
+												 *			DW)
+												 */
+#define	PCIE_PWRBDGT_CAPHDR				0x0140	/* 32 bit	Power Budgeting
+												 *			Enhanced
+												 *			Capability Header
+												 */
+#define	PCIE_PWRBDGT_DATASEL			0x0144	/* 32 bit	Power Budgeting
+												 *			Data Select
+												 *			Register
+												 */
+#define	PCIE_PWRBDGT_DATA				0x0148	/* 32 bit	Power Budgeting
+												 *			Data Register
+												 */
+#define	PCIE_PWRBDGT_CAP				0x014c	/* 32 bit	Power Budgeting
+												 *			Capability
+												 *			Register
+												 */
+#define	PCIE_TL_CTRL					0x0200	/* 32 bit	Transaction Layer
+												 *			Control Register
+												 */
+#define	PCIE_TL_STAT					0x0204	/* 32 bit	Transaction Layer
+												 *			Status Register
+												 */
+#define	PCIE_DL_CTRL					0x0208	/* 32 bit	Data Link Layer
+												 *			Control Register
+												 */
+#define	PCIE_DL_STAT					0x020C	/* 32 bit	Data Link Layer
+												 *			Status Register
+												 */
+#define	PCIE_PL_CTRL					0x0210	/* 32 bit	PE Physical Layer
+												 *			Control Register
+												 */
+#define	PCIE_PL_STAT					0x0214	/* 32 bit	PE Physical Layer
+												 *			Status Register
+												 */
+#define	PCIE_CPLTO						0x0220	/* 32 bit	PE Completion
+												 *			Timeout Register
+												 */
+#define	PCIE_FC							0x0224	/* 32 bit	PE Flow Control
+												 *			Register
+												 */
+#define	PCIE_ACKTIM_X1					0x0228	/* 32 bit	PE Ack Timer for 1x
+												 *			Link Register
+												 */
+
+/*
+ *
+ *	THE BIT DEFINES
+ *
+ */
+/*	PCI_VEN_ID						0x0000	Vendor ID Register */
+#define	PCI_VEN_ID_MSK		SHIFT0(0xffffU)	/* Vendor ID */
+#define	PCI_VEN_ID_BASE		BIT_0S
+
+/*	PCI_DEV_ID						0x0002	Device ID Register */
+#define	PCI_DEV_ID_MSK		SHIFT0(0xffffU)	/* Device ID */
+#define	PCI_DEV_ID_BASE		BIT_0S
+
+/*	PCI_CMD							0x0004	Command Register */
+/*		Bit(s) PCI_CMD_RSRV_15_11 reserved */
+#define	PCI_CMD_INT_DIS				BIT_10S			/* Interrupt Disable */
+/*		Bit(s) PCI_CMD_RSRV_9 reserved */
+#define	PCI_CMD_SERR_ENA			BIT_8S			/* SERR Enable */
+/*		Bit(s) PCI_CMD_RSRV_7 reserved */
+#define	PCI_CMD_PERREN				BIT_6S			/* PERREN */
+/*		Bit(s) PCI_CMD_RSRV_5_3 reserved */
+#define	PCI_CMD_BMEN				BIT_2S			/* BMEN */
+#define	PCI_CMD_MEMEN				BIT_1S			/* MEMEN */
+#define	PCI_CMD_IOEN				BIT_0S			/* IOEN */
+
+/*	PCI_STAT						0x0006	Status Register */
+#define	PCI_STAT_PERR				BIT_15S			/* PERR */
+#define	PCI_STAT_SERR				BIT_14S			/* SERR */
+#define	PCI_STAT_RMABORT			BIT_13S			/* RMABORT */
+#define	PCI_STAT_RTABORT			BIT_12S			/* RTABORT */
+/*		Bit(s) PCI_STAT_RSRV_11_9 reserved */
+#define	PCI_STAT_DATAPERR			BIT_8S			/* DATAPERR */
+/*		Bit(s) PCI_STAT_RSRV_7_5 reserved */
+#define	PCI_STAT_NEWCAP				BIT_4S			/* NEWCAP */
+#define	PCI_STAT_INTSTA				BIT_3S			/* INTSTA */
+/*		Bit(s) PCI_STAT_RSRV_2_0 reserved */
+
+/*	PCI_REV_ID						0x0008	Revision ID Register */
+#define	PCI_REV_ID_MSK		SHIFT0(0xffU)	/* Revision ID */
+#define	PCI_REV_ID_BASE		BIT_0S
+
+/*	PCI_PIF							0x0009	Programming Interface Register,
+ *											Lower Byte
+ */
+#define	PCI_PIF_MSK			SHIFT0(0xffU)	/* Prog IF */
+#define	PCI_PIF_BASE		BIT_0S
+
+/*	PCI_SCC							0x000A	Sub-Class Register, Middle Byte */
+#define	PCI_SCC_MSK			SHIFT0(0xffU)	/* Sub Class */
+#define	PCI_SCC_BASE		BIT_0S
+
+/*	PCI_BCC							0x000B	Base-Class Register, Upper Byte */
+#define	PCI_BCC_MSK			SHIFT0(0xffU)	/* Base Class */
+#define	PCI_BCC_BASE		BIT_0S
+
+/*	PCI_CLS							0x000C	Cache Line Size Register */
+/*		Bit(s) PCI_CLS_RSRV_7_0 reserved */
+
+/*	PCI_LAT_TIM						0x000D	Latency Timer Register */
+/*		Bit(s) PCI_LAT_TIM_RSRV_7_0 reserved */
+
+/*	PCI_HDRTYP						0x000E	Header Type Register */
+/*		Bit(s) PCI_HDRTYP_RSRV_7_0 reserved */
+
+/*	PCI_BIST						0x000F	Built-in Self Test (BIST) Register */
+/*		Bit(s) PCI_BIST_RSRV_7_0 reserved */
+
+/*	PCI_BAR1_LO						0x0010	Base Address Register (1st), Lower
+ *											Address
+ */
+#define	PCI_BAR1_LO_BASE_MSK		SHIFT14(0x3ffff)	/* Lower MEMBASE Address */
+#define	PCI_BAR1_LO_BASE_BASE		14
+#define	PCI_BAR1_LO_SIZE_MSK		SHIFT4(0x3ff)		/* MEMSIZE */
+#define	PCI_BAR1_LO_SIZE_BASE		4
+#define	PCI_BAR1_LO_PREFEN			BIT_3				/* PREFEN */
+#define	PCI_BAR1_LO_TYPE_MSK		SHIFT1(0x3)			/* Memory Type */
+#define	PCI_BAR1_LO_TYPE_BASE		1
+#define	PCI_BAR1_LO_IO_SPC			BIT_0				/* MEMSPACE */
+
+/*	PCI_BAR1_HI						0x0014	Base Address Register (1st), Upper
+ *											Address
+ */
+#define	PCI_BAR1_HI_BASE_MSK		SHIFT0(0xffffffff)	/* Upper MEMBASE */
+#define	PCI_BAR1_HI_BASE_BASE		0
+
+/*	PCI_BAR2						0x0018	Base Address Register (2nd) */
+#define	PCI_BAR2_BASE_MSK		SHIFT8(0xffffff)	/* IOBASE */
+#define	PCI_BAR2_BASE_BASE		8
+#define	PCI_BAR2_SIZE_MSK		SHIFT2(0x3f)		/* IOSIZE */
+#define	PCI_BAR2_SIZE_BASE		2
+/*		Bit(s) PCI_BAR2_RSRV_1 reserved */
+#define	PCI_BAR2_IO_SPC			BIT_0				/* IOSPACE */
+
+/*	PCI_SSVEN_ID					0x002C	Subsystem Vendor ID Register */
+#define	PCI_SSVEN_ID_MSK		SHIFT0(0xffffU)	/* Subsystem Vendor ID */
+#define	PCI_SSVEN_ID_BASE		0
+
+/*	PCI_SSDEV_ID					0x002E	Subsystem ID Register */
+#define	PCI_SSDEV_ID_MSK		SHIFT0(0xffffU)	/* Subsystem ID */
+#define	PCI_SSDEV_ID_BASE		0
+
+/*	PCI_ERBAR						0x0030	Expansion Rom Base Address Register */
+#define	PCI_ERBAR_BASE_MSK				SHIFT17(0x7fff)	/* Rombase */
+#define	PCI_ERBAR_BASE_BASE				17
+#define	PCI_ERBAR_BASE_SIZE_MSK			SHIFT14(0x7)	/* Rombase/size */
+#define	PCI_ERBAR_BASE_SIZE_BASE		14
+#define	PCI_ERBAR_SIZE_MSK				SHIFT11(0x7)	/* Romsize */
+#define	PCI_ERBAR_SIZE_BASE				11
+/*		Bit(s) PCI_ERBAR_RSRV_10_1 reserved */
+#define	PCI_ERBAR_ENA					BIT_0			/* ROMEN */
+
+/*	PCI_NCAP_PTR					0x0034	New Capabilities Pointer (New Cap
+ *											Ptr) Register
+ */
+#define	PCI_NCAP_PTR_MSK		SHIFT0(0xffU)	/* New Capabilities Pointer */
+#define	PCI_NCAP_PTR_BASE		0
+
+/*	PCI_INT_LINE					0x003C	Interrupt Line Register */
+#define	PCI_INT_LINE_MSK		SHIFT0(0xffU)	/* Interrupt Line */
+#define	PCI_INT_LINE_BASE		0
+
+/*	PCI_INT_PIN						0x003D	Interrupt Pin Register */
+#define	PCI_INT_PIN_MSK			SHIFT0(0xffU)	/* Interrupt Pin */
+#define	PCI_INT_PIN_BASE		0
+
+/*	PCI_MIN_GNT						0x003E	Min_Gnt Register */
+/*		Bit(s) PCI_MIN_GNT_RSRV_7_0 reserved */
+
+/*	PCI_MAX_LAT						0x003F	Max_Lat Register */
+/*		Bit(s) PCI_MAX_LAT_RSRV_7_0 reserved */
+
+/*	PCI_OUR1						0x0040	Our Register 1 */
+/*		Bit(s) PCI_OUR1_RSRV_31 reserved */
+#define	PCI_OUR1_SW_POR					BIT_30			/* SW POR */
+/* Enable Gen Preset during SW POR */
+#define	PCI_OUR1_EN_GEN_PRSET			BIT_29			
+#define	PCI_OUR1_GP_COMA				BIT_28			/* PHY Coma Mode */
+#define	PCI_OUR1_DIS_SPI_LOAD			BIT_27			/* Disable SPI Loader */
+#define	PCI_OUR1_GP_PWD					BIT_26			/* PHY Power Down Mode */
+#define	PCI_OUR1_DIS_VPD_LOAD			BIT_25			/* Disable VPD Loader */
+#define	PCI_OUR1_ENBOOT					BIT_24			/* En Boot */
+#define	PCI_OUR1_ENIOMAP				BIT_23			/* En IO Mapping */
+#define	PCI_OUR1_ENEPROM				BIT_22			/* En Eprom */
+#define	PCI_OUR1_PAGE_SIZ_MSK			SHIFT20(0x3)	/* Pagesize<1:0> */
+#define	PCI_OUR1_PAGE_SIZ_BASE			20
+/*		Bit(s) PCI_OUR1_RSRV_19 reserved */
+#define	PCI_OUR1_PAGE_SEL_MSK			SHIFT16(0x7)	/* Page Reg<2:0> */
+#define	PCI_OUR1_PAGE_SEL_BASE			16
+#define	PCI_OUR1_DBG_PEX_PME			BIT_15			/* DEBUG_PEX_PME */
+/*		Bit(s) PCI_OUR1_RSRV_14_10 reserved */
+/* Timer for GPHY Link Trigger */
+#define	PCI_OUR1_GP_TRIG_TIM_MSK		SHIFT8(0x3)		
+#define	PCI_OUR1_GP_TRIG_TIM_BASE		8
+#define	PCI_OUR1_L1_EVT_ENA				BIT_7			/* L1 Event Enable */
+#define	PCI_OUR1_GP_LNK_ENA				BIT_6			/* Enable GPHY Link */
+#define	PCI_OUR1_FORCE_L1				BIT_5			/* Force to L1 */
+/*		Bit(s) PCI_OUR1_RSRV_4_1 reserved */
+/* PCIE Receiver Overflow Control */
+#define	PCI_OUR1_PEX_RX_OF_CTRL			BIT_0			
+
+/*	PCI_OUR2						0x0044	Our Register 2 */
+/*		Bit(s) PCI_OUR2_RSRV_31_24 reserved */
+#define	PCI_OUR2_VPD_DEVSEL_MSK			SHIFT17(0x7f)	/* VPD Devsel */
+#define	PCI_OUR2_VPD_DEVSEL_BASE		17
+#define	PCI_OUR2_VPD_ROMSIZE_MSK		SHIFT14(0x7)	/* VPD ROM Size */
+#define	PCI_OUR2_VPD_ROMSIZE_BASE		14
+/*		Bit(s) PCI_OUR2_RSRV_13_0 reserved */
+
+/*	PCI_PM_CAP_ID					0x0048	Power Management Capability ID
+ *											Register (PM Cap ID)
+ */
+#define	PCI_PM_CAP_ID_MSK		SHIFT0(0xffU)	/* Cap ID */
+#define	PCI_PM_CAP_ID_BASE		0
+
+/*	PCI_PM_NXT_PTR					0x0049	Power Management Next Item Pointer
+ *											Register
+ */
+#define	PCI_PM_NXT_PTR_MSK		SHIFT0(0xffU)	/* Next Item Ptr */
+#define	PCI_PM_NXT_PTR_BASE		0
+
+/*	PCI_PM_CAP						0x004A	Power Management Capabilities
+ *											Register
+ */
+#define	PCI_PM_CAP_D3C_ENA				BIT_15S			/* PME Support */
+#define	PCI_PM_CAP_D3H_ENA				BIT_14S			/* PME Support */
+#define	PCI_PM_CAP_D2_ENA				BIT_13S			/* PME Support */
+#define	PCI_PM_CAP_D1_ENA				BIT_12S			/* PME Support */
+#define	PCI_PM_CAP_D0_ENA				BIT_11S			/* PME Support */
+#define	PCI_PM_CAP_D2_SUP				BIT_10S			/* D2 Support */
+#define	PCI_PM_CAP_D1_SUP				BIT_9S			/* D1 Support */
+/*		Bit(s) PCI_PM_CAP_RSRV_8_6 reserved */
+#define	PCI_PM_CAP_DSI_ENA				BIT_5S			/* DSI */
+/*		Bit(s) PCI_PM_CAP_RSRV_4_3 reserved */
+#define	PCI_PM_CAP_VER_ID_MSK			SHIFT0(0x7U)	/* Version */
+#define	PCI_PM_CAP_VER_ID_BASE			0
+
+/*	PCI_PM_CSR						0x004C	Power Management Control/Status
+ *											Register
+ */
+#define	PCI_PM_CSR_PME_STAT				BIT_15S			/* PME Status */
+#define	PCI_PM_CSR_D_SCALE_MSK			SHIFT13(0x3U)	/* Data Scale */
+#define	PCI_PM_CSR_D_SCALE_BASE			13
+#define	PCI_PM_CSR_D_SEL_MSK			SHIFT9(0xfU)	/* Data Select */
+#define	PCI_PM_CSR_D_SEL_BASE			9
+#define	PCI_PM_CSR_PMEEN				BIT_8S			/* PME En */
+/*		Bit(s) PCI_PM_CSR_RSRV_7_2 reserved */
+#define	PCI_PM_CSR_PWST_MSK				SHIFT0(0x3U)	/* Power State */
+#define	PCI_PM_CSR_PWST_BASE			0
+
+/*	PCI_PM_DATA						0x004F	Power Management Data Register */
+#define	PCI_PM_DATA_MSK			SHIFT0(0xffU)	/* Data */
+#define	PCI_PM_DATA_BASE		0
+
+/*	PCI_VPD_CAP_ID					0x0050	VPD Capability ID Register (VPD
+ *											Cap ID)
+ */
+#define	PCI_VPD_CAP_ID_MSK		SHIFT0(0xffU)	/* Cap ID */
+#define	PCI_VPD_CAP_ID_BASE		0
+
+/*	PCI_VPD_NPTR					0x0051	VPD Next Item Pointer Register */
+#define	PCI_VPD_NPTR_MSK		SHIFT0(0xffU)	/* Next Item Ptr */
+#define	PCI_VPD_NPTR_BASE		0
+
+/*	PCI_VPD_ADDR					0x0052	VPD Address Register */
+#define	PCI_VPD_ADDR_FLAG		BIT_15S			/* Flag */
+#define	PCI_VPD_ADDR_MSK		SHIFT0(0x7fffU)	/* VPD Address */
+#define	PCI_VPD_ADDR_BASE		0
+
+/*	PCI_VPD_DATA					0x0054	VPD Data Register */
+#define	PCI_VPD_DATA_MSK		SHIFT0(0xffffffff)	/* VPD Data */
+#define	PCI_VPD_DATA_BASE		0
+
+/*	PCI_LDR_CTRL					0x0058	TWSI EEPROM Loader Control Register */
+#define	PCI_LDR_CTRL_FLAG			BIT_31			/* Flag */
+#define	PCI_LDR_CTRL_ADDR_MSK		SHIFT16(0x7fff)	/* TWSI EEPROM loader Address */
+#define	PCI_LDR_CTRL_ADDR_BASE		16
+/* EEPROM loader start Address for PCI loader */
+#define	PCI_LDR_CTRL_ADDR_PCI 		SHIFT8(0xff)	
+#define	PCI_LDR_CTRL_ADDR_PCIB		8
+/* EEPROM loader start Address for PIG */
+#define	PCI_LDR_CTRL_ADDR_PIG		SHIFT0(0xff)	
+#define	PCI_LDR_CTRL_ADDR_PIGB		0
+
+/*	PCI_MSI_CAP_ID					0x005C	MSI Capability ID Register (MSI
+ *											Cap ID)
+ */
+#define	PCI_MSI_CAP_ID_MSK		SHIFT0(0xffU)	/* Cap ID */
+#define	PCI_MSI_CAP_ID_BASE		0
+
+/*	PCI_MSI_NPTR					0x005D	MSI Next Item Pointer Register */
+#define	PCI_MSI_NPTR_MSK		SHIFT0(0xffU)	/* Next Item Ptr */
+#define	PCI_MSI_NPTR_BASE		0
+
+/*	PCI_MSI_CTRL					0x005E	MSI Message Control Register */
+/*		Bit(s) PCI_MSI_CTRL_RSRV_15_8 reserved */
+#define	PCI_MSI_CTRL_64CAP				BIT_7S			/* 64 Bit Addr capable */
+#define	PCI_MSI_CTRL_MM_ENA_MSK			SHIFT4(0x7U)	/* Multiple Message Enable */
+#define	PCI_MSI_CTRL_MM_ENA_BASE		4
+#define	PCI_MSI_CTRL_MM_CAP_MSK			SHIFT1(0x7U)	/* Multiple Message Capable */
+#define	PCI_MSI_CTRL_MM_CAP_BASE		1
+#define	PCI_MSI_CTRL_ENA				BIT_0S			/* MSI Enable */
+
+/*	PCI_MSI_ADDR_LO					0x0060	MSI Message Address Register,
+ *											Lower Address
+ */
+/* MSI Message Address, Lower Address */
+#define	PCI_MSI_ADDR_LO_MSK					SHIFT2(0x3fffffff)	
+#define	PCI_MSI_ADDR_LO_BASE				2
+/*		Bit(s) PCI_MSI_ADDR_LO_RSRV_1_0 reserved */
+
+/*	PCI_MSI_ADDR_HI					0x0064	MSI Message Address Register,
+ *											Upper Address
+ */
+/* MSI Message Address, Upper Address */
+#define	PCI_MSI_ADDR_HI_MSK			SHIFT0(0xffffffff)	
+#define	PCI_MSI_ADDR_HI_BASE		0
+
+/*	PCI_MSI_DATA					0x0068	MSI Message Data Register */
+/*		Bit(s) PCI_MSI_DATA_RSRV_31_16 reserved */
+#define	PCI_MSI_DATA_MSK					SHIFT0(0xffff)	/* Message Data */
+#define	PCI_MSI_DATA_BASE					0
+
+/*	PCIE_STAT						0x0070	PCI Express Status Register */
+/*		Bit(s) PCIE_STAT_RSRV_31_30 reserved */
+#define	PCIE_STAT_FIX_MSK				SHIFT16(0x3fff)	/* Fixed value */
+#define	PCIE_STAT_FIX_BASE				16
+#define	PCIE_STAT_BUS_NUM_MSK			SHIFT8(0xff)	/* Request ID (Bus Number) */
+#define	PCIE_STAT_BUS_NUM_BASE			8
+/* Request ID (Device Number) */
+#define	PCIE_STAT_DEV_NUM_MSK			SHIFT3(0x1f)	
+#define	PCIE_STAT_DEV_NUM_BASE			3
+/* Request ID (Function Number) */
+#define	PCIE_STAT_FUN_NUM_MSK			SHIFT0(0x7)		
+#define	PCIE_STAT_FUN_NUM_BASE			0
+
+/*	PCIE_OUR_STAT					0x007C	Our Status Register */
+/*		Bit(s) PCIE_OUR_STAT_RSRV_31_26 reserved */
+#define	PCIE_OUR_STAT_DLL_ERR_MSK			SHIFT24(0x3)	/* DLL Err */
+#define	PCIE_OUR_STAT_DLL_ERR_BASE			24
+#define	PCIE_OUR_STAT_DLL_ROW_MSK			SHIFT20(0xf)	/* DLL Row */
+#define	PCIE_OUR_STAT_DLL_ROW_BASE			20
+#define	PCIE_OUR_STAT_DLL_COL_MSK			SHIFT16(0xf)	/* DLL Col */
+#define	PCIE_OUR_STAT_DLL_COL_BASE			16
+/*		Bit(s) PCIE_OUR_STAT_RSRV_15_0 reserved */
+
+/*	PCIE_OUR3						0x0080	Our Register 3 */
+/* Mask L0 condition */
+#define	PCIE_OUR3_MASK_L0_COMMA					BIT_31			
+/* Mask L0s condition */
+#define	PCIE_OUR3_MASK_L0S_COMMA				BIT_30			
+/* Select MACSec clock */
+#define	PCIE_OUR3_MACSEC_CLK_SEL				BIT_29			
+/*		Bit(s) PCIE_OUR3_RSRV_27_20 reserved */
+/* Select MAC RX clock for TX */
+#define	PCIE_OUR3_CLK_RX_TO_TX					BIT_28
+/* disable clk_clk for MAC and PHY */
+#define	PCIE_OUR3_CLK_PHY_DIS					BIT_19
+#define	PCIE_OUR3_CLK_ASF_REGS_DIS				BIT_18			/* disable clk_asf */
+/* disable clk_macsec */
+#define	PCIE_OUR3_CLK_MACSEC_REGS_DIS			BIT_17			
+/* disable clk_pci_regs_d0 */
+#define	PCIE_OUR3_CLK_PCI_REGS_DIS				BIT_16			
+/* disable clk_core_ytb_arb */
+#define	PCIE_OUR3_CLK_CORE_YTB_ARB_DIS			BIT_15			
+/* disable clk_mac_lnk1_d3 */
+#define	PCIE_OUR3_CLK_MAC_LNK1_D3_DIS			BIT_14			
+/* disable clk_core_lnk1_d0 */
+#define	PCIE_OUR3_CLK_CORE_LNK1_D0_DIS			BIT_13			
+/* disable clk_mac_lnk1_d0 */
+#define	PCIE_OUR3_CLK_MAC_LNK1_D0_DIS			BIT_12			
+/* disable clk_core_lnk1_d3 */
+#define	PCIE_OUR3_CLK_CORE_LNK1_D3_DIS			BIT_11			
+/* disable clk_pci_master_arb */
+#define	PCIE_OUR3_CLK_PCI_MST_ARB_DIS			BIT_10			
+/* disable clk_core_regs_d3 */
+#define	PCIE_OUR3_CLK_CORE_REGS_D3_DIS			BIT_9			
+/* disable clk_pci_regs_d3 */
+#define	PCIE_OUR3_CLK_PCI_REGS_D3_DIS			BIT_8			
+/* disable clk_ref_lnk1_gmac */
+#define	PCIE_OUR3_CLK_REF_LNK1_GMAC_DIS			BIT_7			
+/* disable clk_core_lnk1_gmac */
+#define	PCIE_OUR3_CLK_CORE_LNK1_GMAC_DIS		BIT_6			
+/* disable clk_pci_common */
+#define	PCIE_OUR3_CLK_PCI_COM_DIS				BIT_5			
+/* disable clk_core_common */
+#define	PCIE_OUR3_CLK_CORE_COM_DIS				BIT_4			
+/* disable clk_pci_lnk1_bmu */
+#define	PCIE_OUR3_CLK_PCI_LNK1_BMU_DIS			BIT_3			
+/* disable clk_core_lnk1_bmu */
+#define	PCIE_OUR3_CLK_CORE_LNK1_BMU_DIS			BIT_2			
+/* disable pci_clk_biu */
+#define	PCIE_OUR3_PCI_CLK_BIU_DIS				BIT_1			
+/* disable clk_core_biu */
+#define	PCIE_OUR3_CLK_CORE_BIU_DIS				BIT_0			
+
+#define PCIE_OUR3_WOL_D3_COLD_SETTING		\
+	( PCIE_OUR3_CLK_CORE_LNK1_BMU_DIS	|	\
+	  PCIE_OUR3_CLK_CORE_COM_DIS		|	\
+	  PCIE_OUR3_CLK_PCI_MST_ARB_DIS		|	\
+	  PCIE_OUR3_CLK_MAC_LNK1_D0_DIS		|	\
+	  PCIE_OUR3_CLK_CORE_LNK1_D0_DIS	|	\
+	  PCIE_OUR3_CLK_PCI_REGS_DIS		|	\
+	  PCIE_OUR3_CLK_MACSEC_REGS_DIS 	|	\
+	  PCIE_OUR3_CLK_ASF_REGS_DIS)
+
+/*	PCIE_OUR4						0x0084	Our Register 4 */
+/* PEXUNIT LTSSM State for Gating Core Clock */
+#define	PCIE_OUR4_PEX_LTSSM_STATE_MSK			SHIFT25(0x7f)	
+#define	PCIE_OUR4_PEX_LTSSM_STATE_BASE			25
+#define	PCIE_OUR4_GPHY_INT_ASPM					BIT_24			/* GPHY get INT */
+#define	PCIE_OUR4_TIM_VAL_MSK					SHIFT16(0xff)	/* Timer Value */
+#define	PCIE_OUR4_TIM_VAL_BASE					16
+/* Force ASPM Request */
+#define	PCIE_OUR4_FORCE_ASPM_REQ				BIT_15			
+#define	PCIE_OUR4_GPHY_LNK_DOWN					BIT_14			/* GPHY Link Down */
+/* Internal FIFO Empty */
+#define	PCIE_OUR4_INT_FIFO_EMPTY				BIT_13			
+#define	PCIE_OUR4_CLKRUN_REQ					BIT_12			/* Clkrun Request */
+/* Enable EC SMBUS Pin mode */
+#define	PCIE_OUR4_EN_EC_SMBUS_PIN				BIT_11			
+/* Enable PCIE RX Overflow status */
+#define	PCIE_OUR4_EN_PCIE_RX_OVERFLOW			BIT_10			
+/* Enable ASPM at No-D0 mode */
+#define	PCIE_OUR4_EN_ASPM_NOND0					BIT_9			
+/* Enable PIN#63 as LED_LIN */
+#define	PCIE_OUR4_EN_LED_LINK_PIN63				BIT_8			
+/* Force ASPM L1 Enable */
+#define	PCIE_OUR4_FORCE_ASPM_L1_ENA				BIT_7			
+/* Force ASPM L0s Enable */
+#define	PCIE_OUR4_FORCE_ASPM_L0S_ENA			BIT_6			
+/* Force CLKREQn Pin Low */
+#define	PCIE_OUR4_FORCE_CLKREQN_PIN_LO			BIT_5			
+/* Force CLKREQ Scheme Enable */
+#define	PCIE_OUR4_FORCE_CLKREQ_SCHEME_ENA		BIT_4			
+/* CLKREQn PAD Control */
+#define	PCIE_OUR4_CLKREQN_PAD_CTRL				BIT_3			
+#define	PCIE_OUR4_A1_MODE_SEL					BIT_2			/* A1 Mode Select */
+/* Enable Gate Pexunit Clock */
+#define	PCIE_OUR4_GATE_PEXUNIT_CLK_ENA			BIT_1			
+/* Enable Gate Root Core Clock */
+#define	PCIE_OUR4_GATE_ROOT_CORE_CLK_ENA		BIT_0			
+
+#if 0
+#define PCIE_OUR4_WOL_D3_COLD_SETTING		\
+	( PCIE_OUR4_GATE_ROOT_CORE_CLK_ENA	|	\
+	  PCIE_OUR4_GATE_PEXUNIT_CLK_ENA	|	\
+	  PCIE_OUR4_TIM_VAL_MSK )
+#endif
+
+/*	PCIE_OUR5						0x0088	Our Register 5 */
+/* Divide Core Clock Enable */
+#define	PCIE_OUR5_DIV_CORE_CLK_ENA				BIT_31			
+/* Soft Reset for Vmain_avlbl De-Glitch Logic */
+#define	PCIE_OUR5_SOFT_RST_VMAIN_DEGLITCH		BIT_30			
+/* Bypass Enable for Vmain_avlbl De-Glitch */
+#define	PCIE_OUR5_BYPASS_VMAIN_DEGLITCH_ENA		BIT_29			
+/* Timer of Vmain_avlbl De-Glitch */
+#define	PCIE_OUR5_TIM_VMAIN_DEGLITCH_MSK		SHIFT27(0x3)	
+#define	PCIE_OUR5_TIM_VMAIN_DEGLITCH_BASE		27
+/* PCI-E Reset De-Asserted */
+#define	PCIE_OUR5_PCIE_RST_DEASS				BIT_26			
+/* GPHY Received Packet */
+#define	PCIE_OUR5_GPHY_RX_PKT					BIT_25			
+/* Internal FIFO Not Empty */
+#define	PCIE_OUR5_INT_FIFO_NOT_EMPTY			BIT_24			
+/* Main Power is Available */
+#define	PCIE_OUR5_MAIN_PWR_AVL					BIT_23			
+#define	PCIE_OUR5_CLKRUN_REQ					BIT_22			/* CLKRUN Request */
+/* PCI-E Reset Asserted */
+#define	PCIE_OUR5_PCIE_RST_ASS					BIT_21			
+#define	PCIE_OUR5_PME_ASS						BIT_20			/* PME Asserted */
+/* PCI-E Exits L1 State */
+#define	PCIE_OUR5_PCIE_EX_L1_STATE				BIT_19			
+/* EPROM Loader Not Finished */
+#define	PCIE_OUR5_EPROM_LDR_NOT_FIN				BIT_18			
+/* PCI-E RX Exits ELEC IDLE */
+#define	PCIE_OUR5_PCIE_RX_EX_ELEC_IDLE			BIT_17			
+#define	PCIE_OUR5_GPHY_LNK_UP					BIT_16			/* GPHY Link Up */
+/* CPU Goes to Sleep */
+#define	PCIE_OUR5_CPU_SLEEP						BIT_15			
+#define	PCIE_OUR5_GPHY_INT						BIT_14			/* GPHY get INT */
+/*		Bit(s) PCIE_OUR5_RSRV_13 reserved */
+#define	PCIE_OUR5_GPHY_INT_EV					BIT_12			/* GPHY get INT */
+/* CPU Goes to Sleep and Events */
+#define	PCIE_OUR5_CPU_SLEEP_EV					BIT_11			
+/* PCI-E Reset Asserted and Events */
+#define	PCIE_OUR5_PCIE_RST_ASS_EV				BIT_10			
+/* GPHY Not Received Packet */
+#define	PCIE_OUR5_GPHY_NOT_RX_PKT				BIT_9			
+/* Internal FIFO Empty */
+#define	PCIE_OUR5_INTERNAL_FIFO_EMPTY			BIT_8			
+/* Main Power is Not Available */
+#define	PCIE_OUR5_MAIN_PWR_NOT_AVL				BIT_7			
+/* CLKRUN Not Requested */
+#define	PCIE_OUR5_CLKRUN_NOT_REQ				BIT_6			
+/* PCI-E Reset De-Asserted and Events */
+#define	PCIE_OUR5_PCIE_RST_DEASS_EV				BIT_5			
+#define	PCIE_OUR5_PME_DEASS						BIT_4			/* PME De-Asserted */
+/* PCI-E Goes to L1 State */
+#define	PCIE_OUR5_PCIE_GO_L1_STATE				BIT_3			
+/* EPROM Loader Finished */
+#define	PCIE_OUR5_EPROM_LDR_FIN					BIT_2			
+/* PCI-E Rx ELEC IDLE */
+#define	PCIE_OUR5_PCIE_RX_ELEC_IDLE				BIT_1			
+#define	PCIE_OUR5_GPHY_LNK_DOWN					BIT_0			/* GPHY Link Down */
+
+#if 0
+#define PCIE_OUR5_WOL_D3_COLD_SETTING		\
+	( PCIE_OUR5_PME_DEASS				|	\
+	  PCIE_OUR5_CLKRUN_NOT_REQ			|	\
+	  PCIE_OUR5_MAIN_PWR_NOT_AVL		|	\
+	  PCIE_OUR5_INTERNAL_FIFO_EMPTY		|	\
+	  PCIE_OUR5_GPHY_NOT_RX_PKT			|	\
+	  PCIE_OUR5_PME_ASS					|	\
+	  PCIE_OUR5_CLKRUN_REQ				|	\
+	  PCIE_OUR5_MAIN_PWR_AVL			|	\
+	  PCIE_OUR5_INT_FIFO_NOT_EMPTY		|	\
+	  PCIE_OUR5_GPHY_RX_PKT				|	\
+	  PCIE_OUR5_DIV_CORE_CLK_ENA )
+#endif
+
+/*	PCIE_ER_MASK					0x008C	Error Reporting Mask Register */
+/* Enable the Device Feature Set SERR */
+#define	PCIE_ER_MASK_DEV_FEAT_SET_SERR_ENA		BIT_31			
+/* Receiver Error Mask */
+#define	PCIE_ER_MASK_RCV_ERR_MASK				BIT_30			
+/*		Bit(s) PCIE_ER_MASK_RSRV_29_28 reserved */
+/* Enable Uncorrectable Error (UR Error) */
+#define	PCIE_ER_MASK_UR_ENA						BIT_27			
+/* Enable Uncorrectable Error (ECRC Error) */
+#define	PCIE_ER_MASK_ECRCERR_ENA				BIT_26			
+/* Enable Uncorrectable Error (Malformed TLP) */
+#define	PCIE_ER_MASK_MTLP_ENA					BIT_25			
+/* Enable Uncorrectable Error (RX Overflow) */
+#define	PCIE_ER_MASK_RCVOVFL_ENA				BIT_24			
+/* Enable Uncorrectable Error (Unexpected Completion) */
+#define	PCIE_ER_MASK_UNEXPCPL_ENA				BIT_23			
+/* Enable Uncorrectable Error (Completer Abort) */
+#define	PCIE_ER_MASK_CPLABRT_ENA				BIT_22			
+/* Enable Uncorrectable Error (Completion Timeout) */
+#define	PCIE_ER_MASK_CPLTO_ENA					BIT_21			
+/* Enable Uncorrectable Error (Flow Control Protocol Error) */
+#define	PCIE_ER_MASK_FCPROTERR_ENA				BIT_20			
+/* Enable Uncorrectable Error (Poisoned TLP) */
+#define	PCIE_ER_MASK_PTLP_ENA					BIT_19			
+/* Enable Uncorrectable Error (Data Link Protocol Error) */
+#define	PCIE_ER_MASK_DLPRTERR_ENA				BIT_18			
+/* Enable Uncorrectable Error (Training Error) */
+#define	PCIE_ER_MASK_TRAINERR_ENA				BIT_17			
+/*		Bit(s) PCIE_ER_MASK_RSRV_16 reserved */
+/* Enable Uncorrectable Error (UR Error) Send Error Message */
+#define	PCIE_ER_MASK_UR_SEND_ENA				BIT_15			
+/* Enable Uncorrectable Error (ECRC Error) Send Error Message */
+#define	PCIE_ER_MASK_ECRCERR_SEND_ENA			BIT_14			
+/* Enable Uncorrectable Error (Malformed TLP) Send Error Message */
+#define	PCIE_ER_MASK_MTLP_SEND_ENA				BIT_13			
+/* Enable Uncorrectable Error (RX Overflow) Send Error Message */
+#define	PCIE_ER_MASK_RCVOVFL_SEND_ENA			BIT_12			
+/* Enable Uncorrectable Error (Unexpected Completion) Send Error Message */
+#define	PCIE_ER_MASK_CPLUC_SEND_ENA				BIT_11			
+/* Enable Uncorrectable Error (Completer Abort) Send Error Message */
+#define	PCIE_ER_MASK_CPLABRT_SEND_ENA			BIT_10			
+/* Enable Uncorrectable Error (Completion Timeout) Send Error Message */
+#define	PCIE_ER_MASK_CPLTO_SEND_ENA				BIT_9			
+/* Enable Uncorrectable Error (Flow Control Protocol Error) Send Error Message */
+#define	PCIE_ER_MASK_FCPROTERR_SEND_ENA			BIT_8			
+/* Enable Uncorrectable Error (Poisoned TLP) Send Error Message */
+#define	PCIE_ER_MASK_PTLP_SEND_ENA				BIT_7			
+/* Enable Uncorrectable Error (Data Link Protocol Error) Send Error Message */
+#define	PCIE_ER_MASK_DLPRTERR_SEND_ENA			BIT_6			
+/* Enable Uncorrectable Error (Training Error) Send Error Message */
+#define	PCIE_ER_MASK_TRAINERR_SEND_ENA			BIT_5			
+/* Enable Correctable Error (Replay Timer Timeout) Send Error Message */
+#define	PCIE_ER_MASK_RPLYTO_SEND_ENA			BIT_4			
+/* Enable Correctable Error (REPLAY_NUM RollOver) Send Error Message */
+#define	PCIE_ER_MASK_RPLYNUMRO_SEND_ENA			BIT_3			
+/* Enable Correctable Error (Bad DLLP) Send Error Message */
+#define	PCIE_ER_MASK_BADDLLP_SEND_ENA			BIT_2			
+/* Enable Correctable Error (Bad TLP) Send Error Message */
+#define	PCIE_ER_MASK_BADTLP_SEND_ENA			BIT_1			
+/* Enable Correctable Error (RX Error) Send Error Message */
+#define	PCIE_ER_MASK_RXERR_SEND_ENA				BIT_0			
+
+/*	CONFIG_REG0						0x0090	Config Register 0 */
+#define	CONFIG_REG0_RTC_MSK							SHIFT24(0xff)	/* RTC */
+#define	CONFIG_REG0_RTC_BASE						24
+#define	CONFIG_REG0_WTC_MSK							SHIFT16(0xff)	/* WTC */
+#define	CONFIG_REG0_WTC_BASE						16
+/* Disable PCIe reset extend after Lom_disable */
+#define	CONFIG_REG0_PCIRST_LOM						BIT_15			
+/*		Bit(s) CONFIG_REG0_RSRV_14_13 reserved */
+#define	CONFIG_REG0_OSC_PU							BIT_12			/* OSC Power Up */
+/* OSC Speed Control */
+#define	CONFIG_REG0_OSC_SPEED_CTRL_MSK				SHIFT9(0x7)		
+#define	CONFIG_REG0_OSC_SPEED_CTRL_BASE				BIT_9
+#define	CONFIG_REG0_OSC_OUT							BIT_8			/* OSC output */
+/*		Bit(s) CONFIG_REG0_RSRV_7_5 reserved */
+/* Disable GPHY reset on Lom_disable mode */
+#define	CONFIG_REG0_GPHY_RST_LOMDISABLE				BIT_4			
+/* Disable GPHY DPLL reset on Lom_disable mode */
+#define	CONFIG_REG0_GPHY_RST_DPLL_LOMDISABLE		BIT_3			
+/* Disable GPHY DPLL Power Down on Lom_disable mode */
+#define	CONFIG_REG0_GPHY_PD_DPLL_LOMDISABLE			BIT_2			
+/* Enable GPHY PD on Lom_disable mode */
+#define	CONFIG_REG0_GPHY_PD_LOMDISABLE				BIT_1			
+/* <mu>C lock VPD */
+#define	CONFIG_REG0_CPU_LOCK_VPD					BIT_0			
+
+/*	CONFIG_REG1						0x0094	Config Register 1 */
+/*		Bit(s) CONFIG_REG1_RSRV_31_25 reserved */
+/* Disable Release event in CFG0x84 during PCIE reset asserted */
+#define	CONFIG_REG1_DIS_CFG84_EVENT					BIT_24			
+/* EPROM Loader Not Finished */
+#define	CONFIG_REG1_EPROM_LDR_NOT_FIN_RELEASE		BIT_23			
+/* Vmain_avlbl release gated clock */
+#define	CONFIG_REG1_VMAIN_AVLB_RELEASE				BIT_22			
+/* PCIE reset release gated clock */
+#define	CONFIG_REG1_PCIE_RST_RELEASE				BIT_21			
+/* EPROM Loader Finished */
+#define	CONFIG_REG1_EPROM_LDR_FIN					BIT_20			
+#define	CONFIG_REG1_PCIE_RX_ELEC_IDLE				BIT_19			/* Vmain_avlbl */
+#define	CONFIG_REG1_PCIE_RST						BIT_18			/* PCIE reset */
+/* Enable PCIE reset and pm2phy_off generate CLKREQ for auto-gated clock */
+#define	CONFIG_REG1_EN_PERST_PMOFF_CLKREQ			BIT_17			
+/* Enable PCIE reset generate CLKREQ for auto-gated clock */
+#define	CONFIG_REG1_EN_PERST_CLKREQ					BIT_16			
+/*		Bit(s) CONFIG_REG1_RSRV_15_9 reserved */
+/* Enable core level Config loader done for gated clock */
+#define	CONFIG_REG1_EN_CFG_LOAD_DONE				BIT_8			
+/* Enable PCIe Header Log Fix1 */
+#define	CONFIG_REG1_ENA_PCIE_HDRLOG_FIX1			BIT_7			
+/* Enable PCIe CRS Fix */
+#define	CONFIG_REG1_EN_PCIE_CRS_FIX					BIT_6			
+/* Disable PCIe Header Log Fix0 */
+#define	CONFIG_REG1_DIS_PCIE_HDRLOG_FIX0			BIT_5			
+/* Disable pexunit Synchronization Fix */
+#define	CONFIG_REG1_DIS_PEX_SYNC_FIX				BIT_4			
+/* Enable CPU reset gated by YTB cmd */
+#define	CONFIG_REG1_EN_CPU_RST_YTB_CMD				BIT_3			
+/* Disable PCIe 2.0 linkup fix */
+#define	CONFIG_REG1_DIS_PCIE20_LINKUP_FIX			BIT_2			
+/* Enable TX BMU Read IDLE for ASPM */
+#define	CONFIG_REG1_EN_ASPM_TX_BMU_RD				BIT_1			
+/* Enable TX BMU Write IDLE for ASPM */
+#define	CONFIG_REG1_EN_ASPM_TX_BMU_WR				BIT_0			
+
+/*	PSM_CONFIG_REG0					0x0098	PSM Config Register 0 */
+/* PSM Timer Configuration */
+#define	PSM_CONFIG_REG0_PSM_TIM_CONF_MSK		SHIFT0(0xffffffff)	
+#define	PSM_CONFIG_REG0_PSM_TIM_CONF_BASE		0
+
+/*	PSM_CONFIG_REG1					0x009C	PSM Config Register 1 */
+/* GPHY Energy Detect Status */
+#define	PSM_CONFIG_REG1_GPHY_ENERGY_STS		BIT_31			
+/*		Bit(s) PSM_CONFIG_REG1_RSRV_30_19 reserved */
+/* PCIE L1 Event Polarity for PSM */
+#define	PSM_CONFIG_REG1_PSM_PCIE_L1_POL		BIT_18			
+#define	PSM_CONFIG_REG1_TIMER_STAT			BIT_17			/* PSM Timer Status */
+#define	PSM_CONFIG_REG1_GPHY_INT			BIT_16			/* GPHY INT */
+/*		Bit(s) PSM_CONFIG_REG1_RSRV_15_10 reserved */
+/* Disable Loader SM after PSM go back to IDLE */
+#define	PSM_CONFIG_REG1_DIS_LOADER			BIT_9			
+#define	PSM_CONFIG_REG1_DO_PWDN				BIT_8			/* Do Power Down */
+/* Disable Plug-in-Go SM after PSM go back to IDLE */
+#define	PSM_CONFIG_REG1_DIS_PIG				BIT_7			
+/* Disable Internal PCIE reset after PSM going back to IDLE */
+#define	PSM_CONFIG_REG1_DIS_PERST			BIT_6			
+/* Enable REG18 Power Down for PSM */
+#define	PSM_CONFIG_REG1_EN_REG18_PD			BIT_5			
+/* Disable EEPROM Loader after PSM go back to IDLE */
+#define	PSM_CONFIG_REG1_EN_PSM_LOAD			BIT_4			
+/* Enable PCIE Hot reset for PSM */
+#define	PSM_CONFIG_REG1_EN_PSM_HOT_RST		BIT_3			
+/* Enable PCIE Rst event for PSM */
+#define	PSM_CONFIG_REG1_EN_PSM_PERST		BIT_2			
+/* Enable PCIE L1 Event for PSM */
+#define	PSM_CONFIG_REG1_EN_PSM_PCIE_L1		BIT_1			
+#define	PSM_CONFIG_REG1_EN_PSM				BIT_0			/* Enable PSM scheme */
+
+/*	VPD_CTRL_ADD					0x00A0	VPD Start End Address */
+#define	VPD_CTRL_ADD_VPD_END_MSK			SHIFT24(0xff)	/* VPD_END */
+#define	VPD_CTRL_ADD_VPD_END_BASE			24
+#define	VPD_CTRL_ADD_VPD_W_START_MSK		SHIFT16(0xff)	/* VPD_W_START */
+#define	VPD_CTRL_ADD_VPD_W_START_BASE		16
+#define	VPD_CTRL_ADD_VPD_START_MSK			SHIFT8(0xff)	/* VPD_START */
+#define	VPD_CTRL_ADD_VPD_START_BASE			8
+#define	VPD_CTRL_ADD_OTP_BYTE_EN_MSK		SHIFT4(0xf)		/* OTP_BYTE_EN */
+#define	VPD_CTRL_ADD_OTP_BYTE_EN_BASE		4
+/*		Bit(s) VPD_CTRL_ADD_RSRV_3 reserved */
+#define	VPD_CTRL_ADD_EEPROM_EN				BIT_2			/* EEPROM_EN */
+#define	VPD_CTRL_ADD_OTP_EN					BIT_1			/* OTP_EN */
+#define	VPD_CTRL_ADD_VPD_SEL				BIT_0			/* VPD_SEL */
+
+/*	OTP_LDR_CTRL					0x00A4	OTP Loader Control Register */
+#define	OTP_LDR_CTRL_OTP_FLAG						BIT_31			/* Flag */
+#define	OTP_LDR_CTRL_OTP_ADDR_MSK					SHIFT16(0x7fff)	/* OTP Address */
+#define	OTP_LDR_CTRL_OTP_ADDR_BASE					16
+/* EEPROM timeout flag */
+#define	OTP_LDR_CTRL_EEPROM_TIMEOUT_FLAG			BIT_15			
+/* EEPROM timeout disable */
+#define	OTP_LDR_CTRL_EEPROM_TIMEOUT_DIS				BIT_14			
+/*		Bit(s) OTP_LDR_CTRL_RSRV_13_12 reserved */
+/* EEPROM timeout value */
+#define	OTP_LDR_CTRL_EEPROM_TIMEOUT_VAL_MSK			SHIFT9(0x7)		
+#define	OTP_LDR_CTRL_EEPROM_TIMEOUT_VAL_BASE		9
+/*		Bit(s) OTP_LDR_CTRL_RSRV_8 reserved */
+/* OTP start Address */
+#define	OTP_LDR_CTRL_OTP_ST_ADD_MSK					SHIFT0(0xff)	
+#define	OTP_LDR_CTRL_OTP_ST_ADD_BASE				0
+
+/*	OTP_MEM_CTRL_0					0x00A8	OTP Memory Control Register 0 */
+#define	OTP_MEM_CTRL_0_CE2RD_SU_TIME_MSK		SHIFT24(0xff)	/* CERD setup time */
+#define	OTP_MEM_CTRL_0_CE2RD_SU_TIME_BASE		24
+/* Write data hold time */
+#define	OTP_MEM_CTRL_0_WRDAT_HLD_TIME_MSK		SHIFT20(0xf)	
+#define	OTP_MEM_CTRL_0_WRDAT_HLD_TIME_BASE		20
+#define	OTP_MEM_CTRL_0_WRDAT_VLD_TIME_MSK		SHIFT16(0xf)	/* Write valid time */
+#define	OTP_MEM_CTRL_0_WRDAT_VLD_TIME_BASE		16
+/* Write data setup time */
+#define	OTP_MEM_CTRL_0_WRDAT_SU_TIME_MSK		SHIFT12(0xf)	
+#define	OTP_MEM_CTRL_0_WRDAT_SU_TIME_BASE		12
+/* Read data setup time */
+#define	OTP_MEM_CTRL_0_RDDAT_SU_TIME_MSK		SHIFT4(0xff)	
+#define	OTP_MEM_CTRL_0_RDDAT_SU_TIME_BASE		4
+#define	OTP_MEM_CTRL_0_RST_PULSE_WIDTH_MSK		SHIFT0(0xf)		/* RSTB pulse width */
+#define	OTP_MEM_CTRL_0_RST_PULSE_WIDTH_BASE		0
+
+/*	OTP_MEM_CTRL_1					0x00AC	OTP Memory Control Register 1 */
+/* CPUMPEN hold time */
+#define	OTP_MEM_CTRL_1_CPUMEM_HLD_TIME_MSK		SHIFT28(0xf)	
+#define	OTP_MEM_CTRL_1_CPUMEM_HLD_TIME_BASE		28
+/* CPUMPEN setup time */
+#define	OTP_MEM_CTRL_1_CPUMEM_SU_TIME_MSK		SHIFT24(0xf)	
+#define	OTP_MEM_CTRL_1_CPUMEM_SU_TIME_BASE		24
+#define	OTP_MEM_CTRL_1_PGMEN_HLD_TIME_MSK		SHIFT16(0xff)	/* PGMEN hold time */
+#define	OTP_MEM_CTRL_1_PGMEN_HLD_TIME_BASE		16
+#define	OTP_MEM_CTRL_1_PGMEN_VLD_TIME_MSK		SHIFT4(0xfff)	/* Program time */
+#define	OTP_MEM_CTRL_1_PGMEN_VLD_TIME_BASE		4
+#define	OTP_MEM_CTRL_1_PGMEN_SU_TIME_MSK		SHIFT0(0xf)		/* PGMEN setup time */
+#define	OTP_MEM_CTRL_1_PGMEN_SU_TIME_BASE		0
+
+/*	OTP_MEM_CTRL_2					0x00B0	OTP Memory Control Register 2 */
+/* OTP ctrl module status */
+#define	OTP_MEM_CTRL_2_OTP_DBG_BITS_MSK			SHIFT16(0xffff)	
+#define	OTP_MEM_CTRL_2_OTP_DBG_BITS_BASE		16
+#define	OTP_MEM_CTRL_2_OTP_TST_MODE_MSK			SHIFT8(0xff)	/* OTP test mode */
+#define	OTP_MEM_CTRL_2_OTP_TST_MODE_BASE		8
+/*		Bit(s) OTP_MEM_CTRL_2_RSRV_7 reserved */
+/* Auto read back after programming */
+#define	OTP_MEM_CTRL_2_AUTO_RD_AFTER_WR			BIT_6			
+/* OTP test mode enable */
+#define	OTP_MEM_CTRL_2_TSTMODE_ENA				BIT_5			
+#define	OTP_MEM_CTRL_2_OTP_RST_WHEN_WR			BIT_4			/* OTP reset mode */
+/* OTP CEB always low */
+#define	OTP_MEM_CTRL_2_CEB_KEEP_LOW				BIT_3			
+#define	OTP_MEM_CTRL_2_BYPASS2RSTB				BIT_2			/* OTP RSTB */
+#define	OTP_MEM_CTRL_2_BYPASS2RSTB_ENA			BIT_1			/* OTP RSTB enable */
+/* OTP interface module reset */
+#define	OTP_MEM_CTRL_2_OTP_IF_FREEZE			BIT_0			
+
+/*	OTP_MEM_ST_0					0x00B4	OTP Memory Status Register 0 */
+/* OTP memory LOCK pin */
+#define	OTP_MEM_ST_0_OTP_LOCK_PIN			BIT_31				
+/*		Bit(s) OTP_MEM_ST_0_RSRV_30_24 reserved */
+/* OTP memory DOUT pin */
+#define	OTP_MEM_ST_0_OTP_DOUT_PIN			BIT_23				
+/*		Bit(s) OTP_MEM_ST_0_RSRV_22_0 reserved */
+
+/*	VPD_CTRL						0x00B8	EEPROM and OTP Control Register */
+/* mdio to ytb bus IF disable */
+#define	VPD_CTRL_MDIO2YTB_DIS			BIT_31			
+/* mdio to ytb bus IF software reset */
+#define	VPD_CTRL_MDIO2YTB_SWRST			BIT_30			
+#define	VPD_CTRL_OTP_TOP_RST			BIT_29			/* otp_top software reset */
+/*		Bit(s) VPD_CTRL_RSRV_28_18 reserved */
+#define	VPD_CTRL_OTP_IF_TMOUT_MSK		SHIFT16(0x3)	/* otp timeout reg */
+#define	VPD_CTRL_OTP_IF_TMOUT_BASE		16
+/* EEPROM loader timeout disable */
+#define	VPD_CTRL_TMOUT_DIS				BIT_15			
+/*		Bit(s) VPD_CTRL_RSRV_14 reserved */
+/* EEPROM loader timeout val */
+#define	VPD_CTRL_TMOUT_VALUE_MSK		SHIFT12(0x3)	
+#define	VPD_CTRL_TMOUT_VALUE_BASE		12
+/*		Bit(s) VPD_CTRL_RSRV_11_10 reserved */
+#define	VPD_CTRL_SPEED_SELECT_MSK		SHIFT0(0x3ff)	/* EEPROM speed select */
+#define	VPD_CTRL_SPEED_SELECT_BASE		0
+
+/*	OTP_MEM_CTRL_3					0x00BC	LDO Control Register */
+//#define	_MSK									SHIFT14(0x3ffff)	/* RSVD */
+//#define	_BASE									14
+/* CLK generator filter bypass */
+#define	OTP_MEM_CTRL_3_CLK_GEN_BYPASS			BIT_13				
+/* CLK generator soft reset */
+#define	OTP_MEM_CTRL_3_CLK_GEN_RST				BIT_12				
+/* CLK generator filter control */
+#define	OTP_MEM_CTRL_3_CLK_GEN_CTRL_MSK			SHIFT8(0xf)			
+#define	OTP_MEM_CTRL_3_CLK_GEN_CTRL_BASE		8
+/* LDO 2.5 V testmode sel */
+#define	OTP_MEM_CTRL_3_LDO25TSTMODE_MSK			SHIFT4(0x7)			
+#define	OTP_MEM_CTRL_3_LDO25TSTMODE_BASE		4
+/* LDO 1.2 V testmode sel */
+#define	OTP_MEM_CTRL_3_LDO12TSTMODE_MSK			SHIFT0(0x7)			
+#define	OTP_MEM_CTRL_3_LDO12TSTMODE_BASE		0
+
+/*	PCIE_CAP_ID						0x00C0	PE Capability ID Register (PM Cap
+ *											ID)
+ */
+#define	PCIE_CAP_ID_MSK			SHIFT0(0xffU)	/* Cap ID */
+#define	PCIE_CAP_ID_BASE		0
+
+/*	PCIE_NPTR						0x00C1	PE Next Item Pointer Register */
+#define	PCIE_NPTR_MSK		SHIFT0(0xffU)	/* Next Item Ptr */
+#define	PCIE_NPTR_BASE		0
+
+/*	PCIE_CAP						0x00C2	PE Capabilities Register */
+/*		Bit(s) PCIE_CAP_RSRV_15_14 reserved */
+#define	PCIE_CAP_INTMSG_NUM_MSK			SHIFT9(0x1fU)	/* Interrupt Message Number */
+#define	PCIE_CAP_INTMSG_NUM_BASE		9
+/*		Bit(s) PCIE_CAP_RSRV_8 reserved */
+#define	PCIE_CAP_PORT_TYP_MSK			SHIFT4(0xfU)	/* Device/Port Type */
+#define	PCIE_CAP_PORT_TYP_BASE			4
+#define	PCIE_CAP_CAP_VER_MSK			SHIFT0(0xfU)	/* Capability Version */
+#define	PCIE_CAP_CAP_VER_BASE			0
+
+/*	DEVICE_CAPABILITIES_REGISTER	0x00C4	Device Capabilities Register */
+/*		Bit(s) DEVICE_CAPABILITIES_REGISTER_RSRV_31_28 reserved */
+/* Captured Slot Power Limit Scale */
+#define	DEVICE_CAPABILITIES_REGISTER_SPL_SCALE_MSK			SHIFT26(0x3)	
+#define	DEVICE_CAPABILITIES_REGISTER_SPL_SCALE_BASE			26
+/* Captured Slot Power Limit Value */
+#define	DEVICE_CAPABILITIES_REGISTER_SPL_VAL_MSK			SHIFT18(0xff)	
+#define	DEVICE_CAPABILITIES_REGISTER_SPL_VAL_BASE			18
+/*		Bit(s) DEVICE_CAPABILITIES_REGISTER_RSRV_17_16 reserved */
+/* Role-Based Error Reporting */
+#define	DEVICE_CAPABILITIES_REGISTER_ROLE_BASED_ERR_RPT		BIT_15			
+/* Power Indicator Present */
+#define	DEVICE_CAPABILITIES_REGISTER_PI_PRS					BIT_14			
+/* Attention Indicator Present */
+#define	DEVICE_CAPABILITIES_REGISTER_AI_PRS					BIT_13			
+/* Attention Button Present */
+#define	DEVICE_CAPABILITIES_REGISTER_AB_PRS					BIT_12			
+/* Endpoint L1 Acceptable Latency */
+#define	DEVICE_CAPABILITIES_REGISTER_L1_AC_LAT_MSK			SHIFT9(0x7)		
+#define	DEVICE_CAPABILITIES_REGISTER_L1_AC_LAT_BASE			9
+/* Endpoint L0s Acceptable Latency */
+#define	DEVICE_CAPABILITIES_REGISTER_L0_AC_LAT_MSK			SHIFT6(0x7)		
+#define	DEVICE_CAPABILITIES_REGISTER_L0_AC_LAT_BASE			6
+/* Extended Tag Field Supported */
+#define	DEVICE_CAPABILITIES_REGISTER_EXTTAG_SUP				BIT_5			
+/* Phantom Functions Supported */
+#define	DEVICE_CAPABILITIES_REGISTER_PHANTOM_SUP_MSK		SHIFT3(0x3)		
+#define	DEVICE_CAPABILITIES_REGISTER_PHANTOM_SUP_BASE		3
+/* Max_Payload_Size Supported */
+#define	DEVICE_CAPABILITIES_REGISTER_MAX_PLS_SUP_MSK		SHIFT0(0x7)		
+#define	DEVICE_CAPABILITIES_REGISTER_MAX_PLS_SUP_BASE		0
+
+/*	PCIE_DEVCTRL					0x00C8	Device Control Register */
+/*		Bit(s) PCIE_DEVCTRL_RSRV_15 reserved */
+#define	PCIE_DEVCTRL_MAX_RRS_MSK		SHIFT12(0x7U)	/* Max_Read_Request_Size */
+#define	PCIE_DEVCTRL_MAX_RRS_BASE		12
+#define	PCIE_DEVCTRL_NOSNP_ENA			BIT_11S			/* Enable No Snoop */
+/* Auxiliary (AUX) Power PM Enable */
+#define	PCIE_DEVCTRL_AUXPWR_ENA			BIT_10S			
+#define	PCIE_DEVCTRL_PHANTOM__ENA		BIT_9S			/* Phantom Functions Enable */
+/* Extended Tag Field Enable */
+#define	PCIE_DEVCTRL_EXTTAG_ENA			BIT_8S			
+#define	PCIE_DEVCTRL_MAX_PLS_MSK		SHIFT5(0x7U)	/* Max_Payload_Size */
+#define	PCIE_DEVCTRL_MAX_PLS_BASE		5
+#define	PCIE_DEVCTRL_REL_ORD_ENA		BIT_4S			/* Enable Relaxed Ordering */
+/* Unsupported Request Reporting Enable */
+#define	PCIE_DEVCTRL_URR_ENA			BIT_3S			
+/* Fatal Error Reporting Enable */
+#define	PCIE_DEVCTRL_FERR_ENA			BIT_2S			
+/* Non-Fatal Error Reporting Enable */
+#define	PCIE_DEVCTRL_NFERR_ENA			BIT_1S			
+/* Correctable Error Reporting Enable */
+#define	PCIE_DEVCTRL_CERR_ENA			BIT_0S			
+
+/*	PCIE_DEVSTAT					0x00CA	Device Status Register */
+/*		Bit(s) PCIE_DEVSTAT_RSRV_15_6 reserved */
+#define	PCIE_DEVSTAT_TRANS_PEND			BIT_5S			/* Transactions Pending */
+#define	PCIE_DEVSTAT_AUXPWR_DET			BIT_4S			/* AUX Power Detected */
+/* Unsupported Request Detected */
+#define	PCIE_DEVSTAT_UR_DET				BIT_3S			
+#define	PCIE_DEVSTAT_FERR_DET			BIT_2S			/* Fatal Error Detected */
+#define	PCIE_DEVSTAT_NFERR_DET			BIT_1S			/* Non-Fatal Error Detected */
+/* Correctable Error Detected */
+#define	PCIE_DEVSTAT_CERR_DET			BIT_0S			
+
+/*	PCIE_LNKCAP						0x00CC	Link Capabilities Register */
+#define	PCIE_LNKCAP_PORT_NUM_MSK			SHIFT24(0xff)	/* Port Number */
+#define	PCIE_LNKCAP_PORT_NUM_BASE			24
+/*		Bit(s) PCIE_LNKCAP_RSRV_23_21 reserved */
+/*		Bit(s) PCIE_LNKCAP_RSRV_20_19 reserved */
+/* Clock Power Management */
+#define	PCIE_LNKCAP_CLK_PM					BIT_18			
+#define	PCIE_LNKCAP_L1_EXITLAT_MSK			SHIFT15(0x7)	/* L1 Exit Latency */
+#define	PCIE_LNKCAP_L1_EXITLAT_BASE			15
+#define	PCIE_LNKCAP_LOS_EXITLAT_MSK			SHIFT12(0x7)	/* L0s Exit Latency */
+#define	PCIE_LNKCAP_LOS_EXITLAT_BASE		12
+/* Active State Link PM Support */
+#define	PCIE_LNKCAP_ASPM_SUP_MSK			SHIFT10(0x3)	
+#define	PCIE_LNKCAP_ASPM_SUP_BASE			10
+#define	PCIE_LNKCAP_MAX_LNKWID_MSK			SHIFT4(0x3f)	/* Maximum Link Width */
+#define	PCIE_LNKCAP_MAX_LNKWID_BASE			4
+#define	PCIE_LNKCAP_MAX_LNKSPD_MSK			SHIFT0(0xf)		/* Maximum Link Speed */
+#define	PCIE_LNKCAP_MAX_LNKSPD_BASE			0
+
+/*	PCIE_LNKCTRL					0x00D0	Link Control Register */
+/*		Bit(s) PCIE_LNKCTRL_RSRV_15_9 reserved */
+/* Enable Clock Power Management */
+#define	PCIE_LNKCTRL_CLK_PM_ENA			BIT_8S			
+#define	PCIE_LNKCTRL_EXTSYNC			BIT_7S			/* Extended Sync */
+/*		Bit(s) PCIE_LNKCTRL_RSRV_ reserved */
+/*		Bit(s) PCIE_LNKCTRL_RSRV_5_4 reserved */
+/* Read Completion Boundary (RCB) */
+#define	PCIE_LNKCTRL_RCB_128B			BIT_3S			
+/*		Bit(s) PCIE_LNKCTRL_RSRV_2 reserved */
+/* Active State Link PM Control */
+#define	PCIE_LNKCTRL_ASPM_CTRL_MSK		SHIFT0(0x3U)	
+#define	PCIE_LNKCTRL_ASPM_CTRL_BASE		0
+
+/*	PCIE_LNKSTAT					0x00D2	Link Status Register */
+/*		Bit(s) PCIE_LNKSTAT_RSRV_15_14 reserved */
+/*		Bit(s) PCIE_LNKSTAT_RSRV_13 reserved */
+#define	PCIE_LNKSTAT_SCLKCFG			BIT_12S			/* Slot Clock Configuration */
+#define	PCIE_LNKSTAT_LNKTRAIN			BIT_11S			/* Link Training */
+#define	PCIE_LNKSTAT_UNDEF				BIT_10S			/* Undefined */
+#define	PCIE_LNKSTAT_NEGLNKWID_MSK		SHIFT4(0x3fU)	/* Negotiated Link Width */
+#define	PCIE_LNKSTAT_NEGLNKWID_MSK			SHIFT4(0x3fU)	
+#define	PCIE_LNKSTAT_NEGLNKWID_BASE			4
+#define	PCIE_LNKSTAT_LNKSPD_MSK				SHIFT0(0xfU)	/* Link Speed */
+#define	PCIE_LNKSTAT_LNKSPD_BASE			0
+
+/*	PCIE_DEV_CAP_2					0x00E4	Device Capabilities 2 Register */
+/*		Bit(s) PCIE_DEV_CAP_2_RSRV_31_5 reserved */
+/* Completion Timeout Disable Supported */
+#define	PCIE_DEV_CAP_2_CPL_TO_DIS_SUPP				BIT_4				
+/* Completion Timeout Ranges Supported */
+#define	PCIE_DEV_CAP_2_CPL_TO_RANGE_SUPP_MSK		SHIFT0(0xf)			
+#define	PCIE_DEV_CAP_2_CPL_TO_RANGE_SUPP_BASE		0
+
+/*	PCIE_DEV_CTRL_2					0x00E8	Device Control 2 Register */
+/*		Bit(s) PCIE_DEV_CTRL_2_RSRV_31_5 reserved */
+/* Completion Timeout Disable */
+#define	PCIE_DEV_CTRL_2_CPL_TO_DIS			BIT_4				
+/* Completion Timeout Value */
+#define	PCIE_DEV_CTRL_2_CPL_TO_VAL_MSK		SHIFT0(0xf)			
+#define	PCIE_DEV_CTRL_2_CPL_TO_VAL_BASE		0
+
+/*	PCIE_AE_CAP_HDR					0x0100	Advanced Error Reporting Enhanced
+ *											Capability Header Register
+ */
+#define	PCIE_AE_CAP_HDR_NPTR_MSK		SHIFT20(0xfff)	/* Next Capability Offset */
+#define	PCIE_AE_CAP_HDR_NPTR_BASE		20
+#define	PCIE_AE_CAP_HDR_VER_ID_MSK		SHIFT16(0xf)	/* Capability Version */
+#define	PCIE_AE_CAP_HDR_VER_ID_BASE		16
+/* PCI Express Extended Capability ID */
+#define	PCIE_AE_CAP_HDR_CAP_ID_MSK		SHIFT0(0xffff)	
+#define	PCIE_AE_CAP_HDR_CAP_ID_BASE		0
+
+/*	PCIE_UE_STAT					0x0104	Uncorrectable Error Status Register */
+/*		Bit(s) PCIE_UE_STAT_RSRV_31_21 reserved */
+/* Unsupported Request Error */
+#define	PCIE_UE_STAT_UR					BIT_20			
+#define	PCIE_UE_STAT_ECRCERR			BIT_19			/* ECRC Error */
+#define	PCIE_UE_STAT_MTLP				BIT_18			/* Malformed TLP */
+#define	PCIE_UE_STAT_RCVOVFL			BIT_17			/* Receiver Overflow */
+#define	PCIE_UE_STAT_UNEXPCPL			BIT_16			/* Unexpected Completion */
+#define	PCIE_UE_STAT_CPLABORT			BIT_15			/* Completer Abort */
+#define	PCIE_UE_STAT_CPLTO				BIT_14			/* Completion Timeout */
+/* Flow Control Protocol Error */
+#define	PCIE_UE_STAT_FCPROTERR			BIT_13			
+#define	PCIE_UE_STAT_PTLP				BIT_12			/* Poisoned TLP */
+/*		Bit(s) PCIE_UE_STAT_RSRV_11_5 reserved */
+#define	PCIE_UE_STAT_DLPROTERR			BIT_4			/* Data Link Protocol Error */
+/*		Bit(s) PCIE_UE_STAT_RSRV_3_1 reserved */
+#define	PCIE_UE_STAT_UNDEF				BIT_0			/* Undefined */
+
+/*	PCIE_UE_MASK					0x0108	Uncorrectable Error Mask Register */
+/*		Bit(s) PCIE_UE_MASK_RSRV_31_21 reserved */
+/* Unsupported Request Error */
+#define	PCIE_UE_MASK_UR					BIT_20			
+#define	PCIE_UE_MASK_ECRCERR			BIT_19			/* ECRC Error */
+#define	PCIE_UE_MASK_MTLP				BIT_18			/* Malformed TLP */
+#define	PCIE_UE_MASK_RCVOVFL			BIT_17			/* Receiver Overflow */
+#define	PCIE_UE_MASK_UNEXPCPL			BIT_16			/* Unexpected Completion */
+#define	PCIE_UE_MASK_CPLABRT			BIT_15			/* Completer Abort */
+#define	PCIE_UE_MASK_CPLTO				BIT_14			/* Completion Timeout */
+/* Flow Control Protocol Error */
+#define	PCIE_UE_MASK_FCPROTERR			BIT_13			
+#define	PCIE_UE_MASK_PTLP				BIT_12			/* Poisoned TLP */
+/*		Bit(s) PCIE_UE_MASK_RSRV_11_5 reserved */
+#define	PCIE_UE_MASK_DLPROTERR			BIT_4			/* Data Link Protocol Error */
+/*		Bit(s) PCIE_UE_MASK_RSRV_3_1 reserved */
+#define	PCIE_UE_MASK_UNDEF				BIT_0			/* Undefined */
+
+/*	PCIE_UE_SVRT					0x010C	Uncorrectable Error Severity
+ *											Register
+ */
+/*		Bit(s) PCIE_UE_SVRT_RSRV_31_21 reserved */
+/* Unsupported Request Error */
+#define	PCIE_UE_SVRT_UR					BIT_20			
+#define	PCIE_UE_SVRT_ECRCERR			BIT_19			/* ECRC Error Severity */
+#define	PCIE_UE_SVRT_MTLP				BIT_18			/* Malformed TLP */
+#define	PCIE_UE_SVRT_RCVOVFL			BIT_17			/* Receiver Overflow */
+#define	PCIE_UE_SVRT_UNEXPCPL			BIT_16			/* Unexpected Completion */
+#define	PCIE_UE_SVRT_CPLABRT			BIT_15			/* Completer Abort */
+#define	PCIE_UE_SVRT_CPLTO				BIT_14			/* Completion Timeout */
+/* Flow Control Protocol Error */
+#define	PCIE_UE_SVRT_FCPROTERR			BIT_13			
+#define	PCIE_UE_SVRT_PTLP				BIT_12			/* Poisoned TLP */
+/*		Bit(s) PCIE_UE_SVRT_RSRV_11_5 reserved */
+#define	PCIE_UE_SVRT_DLPROTERR			BIT_4			/* Data Link Protocol Error */
+/*		Bit(s) PCIE_UE_SVRT_RSRV_3_1 reserved */
+#define	PCIE_UE_SVRT_UNDEF				BIT_0			/* Undefined */
+
+/*	PCIE_CA_STAT					0x0110	Correctable Error Status Register */
+/*		Bit(s) PCIE_CA_STAT_RSRV_31_14 reserved */
+/* Advisory Non-Fatal Error Status */
+#define	PCIE_CA_STAT_ADV_NONFAT_ERRSTAT		BIT_13				
+/* Replay Timer Timeout */
+#define	PCIE_CA_STAT_RPLYTO					BIT_12				
+/*		Bit(s) PCIE_CA_STAT_RSRV_11_9 reserved */
+/* REPLAY_NUM Rollover */
+#define	PCIE_CA_STAT_RPLYNUMRO				BIT_8				
+#define	PCIE_CA_STAT_BADDLLP				BIT_7				/* Bad DLLP */
+#define	PCIE_CA_STAT_BADTLP					BIT_6				/* Bad TLP */
+/*		Bit(s) PCIE_CA_STAT_RSRV_5_1 reserved */
+#define	PCIE_CA_STAT_RCVERR					BIT_0				/* Receiver Error */
+
+/*	PCIE_CA_MASK					0x0114	Correctable Error Mask Register */
+/*		Bit(s) PCIE_CA_MASK_RSRV_31_14 reserved */
+/* Advisory Non-Fatal Error Mask */
+#define	PCIE_CA_MASK_ADV_NONFAT_ERRSTAT		BIT_13				
+/* Replay Timer Timeout */
+#define	PCIE_CA_MASK_RPLYTO					BIT_12				
+/*		Bit(s) PCIE_CA_MASK_RSRV_11_9 reserved */
+/* REPLAY_NUM Rollover */
+#define	PCIE_CA_MASK_RPLYNUMRO				BIT_8				
+#define	PCIE_CA_MASK_BADDLLP				BIT_7				/* Bad DLLP */
+#define	PCIE_CA_MASK_BADTLP					BIT_6				/* Bad TLP */
+/*		Bit(s) PCIE_CA_MASK_RSRV_5_1 reserved */
+#define	PCIE_CA_MASK_RCVERR					BIT_0				/* Receiver Error */
+
+/*	PCIE_AE_CAPCTRL					0x0118	Advanced Error Capabilities and
+ *											Control Register
+ */
+/*		Bit(s) PCIE_AE_CAPCTRL_RSRV_31_9 reserved */
+/* ECRC Check Enable */
+#define	PCIE_AE_CAPCTRL_ECRCCHK_ENA			BIT_8				
+/* ECRC Check Capable */
+#define	PCIE_AE_CAPCTRL_ECRCCHK_CAP			BIT_7				
+/* ECRC Generation Enable */
+#define	PCIE_AE_CAPCTRL_ECRCGEN_ENA			BIT_6				
+/* ECRC Generation Capable */
+#define	PCIE_AE_CAPCTRL_ECRCGEN_CAP			BIT_5				
+/* First Error Pointer */
+#define	PCIE_AE_CAPCTRL_1ERR_PTR_MSK		SHIFT0(0x1f)		
+#define	PCIE_AE_CAPCTRL_1ERR_PTR_BASE		0
+
+/*	PCIE_HDRLOG						0x011C	Header Log Registers */
+#define	PCIE_HDRLOG_MSK			SHIFT0(0xffffffffU)	/* Header Log */
+#define	PCIE_HDRLOG_BASE		0
+
+/*	PCIE_DEVSERNUMCAP				0x0130	Device Serial Number Enhanced
+ *											Capability Header
+ */
+/* Next Capability Offset */
+#define	PCIE_DEVSERNUMCAP_NPTR_MSK			SHIFT20(0xfff)	
+#define	PCIE_DEVSERNUMCAP_NPTR_BASE			20
+#define	PCIE_DEVSERNUMCAP_VER_ID_MSK		SHIFT16(0xf)	/* Capability Version */
+#define	PCIE_DEVSERNUMCAP_VER_ID_BASE		16
+/* PCI Express Extended Capability ID */
+#define	PCIE_DEVSERNUMCAP_CAP_ID_MSK		SHIFT0(0xffff)	
+#define	PCIE_DEVSERNUMCAP_CAP_ID_BASE		0
+
+/*	PCIE_SERNUM_LOWDW				0x0134	Serial Number Register (Lower DW) */
+/* Serial Number Register (Lower DW) */
+#define	PCIE_SERNUM_LOWDW_SERNUM_LOWDW_MSK		SHIFT0(0xffffffff)	
+#define	PCIE_SERNUM_LOWDW_SERNUM_LOWDW_BASE		0
+
+/*	PCIE_SERNUM_UPPDW				0x0138	Serial Number Register (Upper DW) */
+/* Serial Number Register Upper DW) */
+#define	PCIE_SERNUM_UPPDW_SERNUM_UPPDW_MSK		SHIFT0(0xffffffff)	
+#define	PCIE_SERNUM_UPPDW_SERNUM_UPPDW_BASE		0
+
+/*	PCIE_PWRBDGT_CAPHDR				0x0140	Power Budgeting Enhanced
+ *											Capability Header
+ */
+/* Next Capability Offset */
+#define	PCIE_PWRBDGT_CAPHDR_NPTR_MSK		SHIFT20(0xfff)	
+#define	PCIE_PWRBDGT_CAPHDR_NPTR_BASE		20
+#define	PCIE_PWRBDGT_CAPHDR_VER_ID_MSK		SHIFT16(0xf)	/* Capability Version */
+#define	PCIE_PWRBDGT_CAPHDR_VER_ID_BASE		16
+/* PCI Express Extended Capability ID */
+#define	PCIE_PWRBDGT_CAPHDR_CAP_ID_MSK		SHIFT0(0xffff)	
+#define	PCIE_PWRBDGT_CAPHDR_CAP_ID_BASE		0
+
+/*	PCIE_PWRBDGT_DATASEL			0x0144	Power Budgeting Data Select
+ *											Register
+ */
+/*		Bit(s) PCIE_PWRBDGT_DATASEL_RSRV_31_8 reserved */
+#define	PCIE_PWRBDGT_DATASEL_DATASEL_MSK		SHIFT0(0xff)		/* Data Select */
+#define	PCIE_PWRBDGT_DATASEL_DATASEL_BASE		0
+
+/*	PCIE_PWRBDGT_DATA				0x0148	Power Budgeting Data Register */
+/*		Bit(s) PCIE_PWRBDGT_DATA_RSRV_31_21 reserved */
+#define	PCIE_PWRBDGT_DATA_PWRRAIL_MSK			SHIFT18(0x7)	/* Power Rail */
+#define	PCIE_PWRBDGT_DATA_PWRRAIL_BASE			18
+#define	PCIE_PWRBDGT_DATA_TYPE_MSK				SHIFT15(0x7)	/* Type */
+#define	PCIE_PWRBDGT_DATA_TYPE_BASE				15
+#define	PCIE_PWRBDGT_DATA_PMSTATE_MSK			SHIFT13(0x3)	/* PM State */
+#define	PCIE_PWRBDGT_DATA_PMSTATE_BASE			13
+#define	PCIE_PWRBDGT_DATA_PMSUBSTATE_MSK		SHIFT10(0x7)	/* PM Sub State */
+#define	PCIE_PWRBDGT_DATA_PMSUBSTATE_BASE		10
+#define	PCIE_PWRBDGT_DATA_DATASCALE_MSK			SHIFT8(0x3)		/* Data Scale */
+#define	PCIE_PWRBDGT_DATA_DATASCALE_BASE		8
+#define	PCIE_PWRBDGT_DATA_BASEPWR_MSK			SHIFT0(0xff)	/* Base Power */
+#define	PCIE_PWRBDGT_DATA_BASEPWR_BASE			0
+
+/*	PCIE_PWRBDGT_CAP				0x014c	Power Budgeting Capability Register */
+/*		Bit(s) PCIE_PWRBDGT_CAP_RSRV_31_1 reserved */
+#define	PCIE_PWRBDGT_CAP_SYSALLOC			BIT_0				/* System Allocated */
+
+/*	PCIE_TL_CTRL					0x0200	Transaction Layer Control Register */
+/*		Bit(s) PCIE_TL_CTRL_RSRV_31_2 reserved */
+#define	PCIE_TL_CTRL_MAXOUTSTAND_MSK		SHIFT0(0x3)			/* Max_outstand */
+#define	PCIE_TL_CTRL_MAXOUTSTAND_BASE		0
+
+/*	PCIE_TL_STAT					0x0204	Transaction Layer Status Register */
+/*		Bit(s) PCIE_TL_STAT_RSRV_31_0 reserved */
+
+/*	PCIE_DL_CTRL					0x0208	Data Link Layer Control Register */
+/*		Bit(s) PCIE_DL_CTRL_RSRV_31_0 reserved */
+
+/*	PCIE_DL_STAT					0x020C	Data Link Layer Status Register */
+/*		Bit(s) PCIE_DL_STAT_RSRV_31_0 reserved */
+
+/*	PCIE_PL_CTRL					0x0210	PE Physical Layer Control Register */
+/*		Bit(s) PCIE_PL_CTRL_RSRV_31_16 reserved */
+#define	PCIE_PL_CTRL_N_FTS_MSK				SHIFT8(0xff)	/* N_FTS */
+#define	PCIE_PL_CTRL_N_FTS_BASE				8
+/*		Bit(s) PCIE_PL_CTRL_RSRV_7_0 reserved */
+
+/*	PCIE_PL_STAT					0x0214	PE Physical Layer Status Register */
+/*		Bit(s) PCIE_PL_STAT_RSRV_31_0 reserved */
+
+/*	PCIE_CPLTO						0x0220	PE Completion Timeout Register */
+/*		Bit(s) PCIE_CPLTO_RSRV_31_16 reserved */
+#define	PCIE_CPLTO_MSK					SHIFT0(0xffff)	/* CmpTOThrshld */
+#define	PCIE_CPLTO_BASE					0
+
+/*	PCIE_FC							0x0224	PE Flow Control Register */
+#define	PCIE_FC_PH_INIT_MSK			SHIFT24(0xff)	/* PHInitFC */
+#define	PCIE_FC_PH_INIT_BASE		24
+#define	PCIE_FC_NPH_INIT_MSK		SHIFT16(0xff)	/* NPHInitFC */
+#define	PCIE_FC_NPH_INIT_BASE		16
+#define	PCIE_FC_CH_INIT_MSK			SHIFT8(0xff)	/* CHInitFC */
+#define	PCIE_FC_CH_INIT_BASE		8
+#define	PCIE_FC_UPDATETO_MSK		SHIFT0(0xff)	/* FCUpdateTO */
+#define	PCIE_FC_UPDATETO_BASE		0
+
+/*	PCIE_ACKTIM_X1					0x0228	PE Ack Timer for 1x Link Register */
+#define	PCIE_ACKTIM_X1_RPLYTO_MSK		SHIFT16(0xffff)	/* AckRplyTOX1 */
+#define	PCIE_ACKTIM_X1_RPLYTO_BASE		16
+#define	PCIE_ACKTIM_X1_LATTO_MSK		SHIFT0(0xffff)	/* AckLatTOX1 */
+#define	PCIE_ACKTIM_X1_LATTO_BASE		0
+
+
+
+/* -------------------- */
+
+
+
+/*
+ *
+ *	THE BASE ADDRESSES
+ *
+ */
+
+/*
+ *
+ *	THE REGISTER DEFINES
+ *
+ */
+#define	GLB_RAP				0x0000	/* 32 bit	Register Address Port (RAP)
+									 *			Register
+									 */
+#define	GLB_CSR				0x0004	/* 24 bit	Control/Status Register */
+#define	GLB_PCTRL			0x0007	/*  8 bit	Power Control Register */
+#define	GLB_ISRC			0x0008	/* 32 bit	Interrupt Source Register */
+#define	GLB_IMSK			0x000C	/* 32 bit	Interrupt Mask Register */
+#define	GLB_ISRC_HW			0x0010	/* 32 bit	Interrupt HW Error Source
+									 *			Register
+									 */
+#define	GLB_IMSK_HW			0x0014	/* 32 bit	Interrupt HW Error Mask Register */
+#define	GLB_ISRC_SP1		0x0018	/* 32 bit	Special Interrupt Source
+									 *			Register 1
+									 */
+#define	GLB_ISRC_SP2		0x001C	/* 32 bit	Special Interrupt Source
+									 *			Register 2
+									 */
+#define	GLB_ISRC_SP3		0x0020	/* 32 bit	Special Interrupt Source
+									 *			Register 3
+									 */
+#define	GLB_EISR			0x0024	/* 32 bit	Enter Interrupt Service Routine
+									 *			Register
+									 */
+#define	GLB_LISR			0x0028	/* 32 bit	Leave Interrupt Service Routine
+									 *			Register
+									 */
+#define	GLB_ICTRL			0x002C	/* 32 bit	Interrupt Control Register */
+#define	SPI_CTRL			0x0060	/* 32 bit	SPI Flash Memory Control
+									 *			Register
+									 */
+#define	SPI_ADDR			0x0064	/* 32 bit	SPI Flash Memory Address
+									 *			Register
+									 */
+#define	SPI_DATA			0x0068	/* 32 bit	SPI Flash Memory Data Register */
+#define	SPI_ID				0x006C	/* 32 bit	SPI Flash Memory Vendor/Device
+									 *			ID Register
+									 */
+#define	SPI_LCFG			0x0070	/* 32 bit	SPI Flash Memory Loader
+									 *			Configuration Register
+									 */
+#define	SPI_CFG				0x0074	/* 32 bit	SPI Flash Memory Configuration
+									 *			Register
+									 */
+#define	SPI_OPC1			0x0078	/* 32 bit	SPI Flash Memory Opcode 1
+									 *			Register
+									 */
+#define	SPI_OPC2			0x007C	/* 32 bit	SPI Flash Memory Opcode 2
+									 *			Register
+									 */
+#define	GLB_BWIN			0x0080 	/* 32 bit	Block Window Register */
+#define	L1_CFG_MADDR_HI		0x0100	/*32 bit	Link1 MAC Address Register High */
+#define	M_CFG_MADDR_HI		0x0110	/*32 bit	maintenance MAC Address Register High */
+#define	L1_CFG_MADDR_LO		0x0104	/*32 bit	Link1 MAC Address Register Low */
+#define	M_CFG_MADDR_LO		0x0114	/*32 bit	maintenance MAC Address Register Low */
+#define	CFG_IF				0x0118	/* 16 bit	Interface Type Register (PMD
+									 *			Type and Connector Type)
+									 */
+#define	CFG_CREV			0x011A	/*  8 bit	Chip Revision Register */
+#define	CFG_CID				0x011B	/*  8 bit	Chip ID Register */
+#define	CFG_CGATE			0x011C	/* 16 bit	Clock Gating Register */
+#define	CFG_AIR2			0x011E	/*  8 bit	Application Information
+									 *			Register 2
+									 */
+#define	CFG_AIR1			0x011F	/*  8 bit	Application Information
+									 *			Register 1
+									 */
+#define	CFG_CDIV			0x0120	/* 32 bit	Clock Divider Register */
+#define	IRQ_TIM_INIT		0x0130	/* 32 bit	Timer Init Value Register */
+#define	IRQ_TIM_CNT			0x0134	/* 32 bit	Timer Register */
+#define	IRQ_TIM_TCTRL		0x0138	/* 32 bit	Timer Control/Test Register */
+#define	MOD_TIM_INIT		0x0140	/* 32 bit	IRQ Moderation Timer Init Value
+									 *			Register
+									 */
+#define	MOD_TIM_CNT			0x0144	/* 32 bit	IRQ Moderation Timer Register */
+#define	MOD_TIM_TCTRL		0x0148	/* 32 bit	IRQ Moderation Timer
+									 *			Control/Test Register
+									 */
+#define	MOD_TIM_MSK			0x014C	/* 32 bit	Interrupt Moderation Mask
+									 *			Register
+									 */
+#define	MOD_TIM_MSK_HW		0x0150	/* 32 bit	Interrupt Hardware Error
+									 *			Moderation Mask Register
+									 */
+#define	GLB_TCTRL			0x0158	/* 32 bit	Test Control Register 1 */
+#define	GLB_GPIO			0x015C	/* 32 bit	General Purpose I/O Register */
+#define	TWSI_CTRL			0x0160	/* 32 bit	TWSI (HW) Control Register */
+#define	TWSI_DATA			0x0164	/* 32 bit	TWSI (HW) Data Register */
+#define	TWSI_IRQ			0x0168	/* 32 bit	TWSI (HW) IRQ Register */
+#define	TWSI_SW				0x016C	/* 32 bit	TWSI (SW) Register */
+#define	PCIE_PHY			0x0170	/* 32 bit	PCI Express PHY Address Register */
+#define	RAM_ADDR			0x0180	/* 32 bit	RAM Address Register */
+#define	RAM_DATA_LO			0x0184	/* 32 bit	Data Port/Lower Dword Register */
+#define	RAM_DATA_HI			0x0188	/* 32 bit	Data Port/Upper Dword Register */
+#define	ASF_TO				0x0190	/* 32 bit	Timeout Register */
+#define	ASF_CTRL			0x01A0	/* 32 bit	FIFO Interface Control */
+#define	RSS_KEY0			0x0220	/* 32 bit	RSS Key 0 Register */
+#define	RSS_KEY1			0x0224	/* 32 bit	RSS Key 1 Register */
+#define	RSS_KEY2			0x0228	/* 32 bit	RSS Key 2 Register */
+#define	RSS_KEY3			0x022C	/* 32 bit	RSS Key 3 Register */
+#define	RSS_KEY4			0x0230	/* 32 bit	RSS Key 4 Register */
+#define	RSS_KEY5			0x0234	/* 32 bit	RSS Key 5 Register */
+#define	RSS_KEY6			0x0238	/* 32 bit	RSS Key 6 Register */
+#define	RSS_KEY7			0x023C	/* 32 bit	RSS Key 7 Register */
+#define	RSS_KEY8			0x0240	/* 32 bit	RSS Key 8 Register */
+#define	RSS_KEY9			0x0244	/* 32 bit	RSS Key 9 Register */
+#define	RSS_CFG				0x0248	/* 32 bit	RSS Configuration Register */
+#define	RBMU_DESCR			0x0400	/* 32 bit	Current Receive Descriptor
+									 *			Register
+									 */
+#define	RBMU_HASH			0x0404	/* 32 bit	RSS Hash Checksum Register */
+#define	RBMU_ADDR_HI		0x0408	/* 32 bit	Receive Buffer Address Lo
+									 *			Register
+									 */
+#define	RBMU_ADDR_LO		0x040C	/* 32 bit	Receive Buffer Address Hi
+									 *			Register
+									 */
+#define	RBMU_RFSW			0x0410	/* 32 bit	Receive Buffer Status Word
+									 *			Register
+									 */
+#define	RBMU_TSP			0x0414	/* 32 bit	Receive Timestamp Register */
+#define	RBMU_VLAN			0x0420	/* 32 bit	VLAN Tag Register */
+#define	RBMU_DONE_IDX		0x0424	/* 32 bit	Receive Done Index Register */
+#define	RBMU_REQ_ADDR_LO	0x0428	/* 32 bit	Receive Request Address, Lower
+									 *			Register
+									 */
+#define	RBMU_REQ_ADDR_HI	0x042C	/* 32 bit	Receive Request Address, Upper
+									 *			Register
+									 */
+#define	RBMU_REQ_CNT		0x0430	/* 32 bit	Receive Request Byte Count
+									 *			Register
+									 */
+#define	RBMU_CSR			0x0434	/* 32 bit	Receive BMU Control/Status
+									 *			Register
+									 */
+#define	RBMU_TEST			0x0438	/* 32 bit	Receive BMU Test Register */
+#define	RBMU_SM				0x043C	/* 32 bit	Receive BMU State Machine
+									 *			Register
+									 */
+#define	RBMU_FIFO_WM		0x0440	/* 16 bit	Receive FIFO Watermark Register */
+#define	RBMU_FIFO_AL		0x0442	/* 16 bit	Receive FIFO Alignment Register */
+#define	RPFU_CTRL			0x0450	/* 32 bit	Receive Prefetch Control
+									 *			Register
+									 */
+#define	RPFU_LAST_IDX		0x0454	/* 32 bit	Receive PFU List Last Index
+									 *			Register
+									 */
+#define	RPFU_LADR_LO		0x0458	/* 32 bit	Receive PFU List Start Address
+									 *			Low Register
+									 */
+#define	RPFU_LADR_HI		0x045C	/* 32 bit	Receive PFU List Start Address
+									 *			High Register
+									 */
+#define	RPFU_GET_IDX		0x0460	/* 32 bit	Receive PFU Get Index Register */
+#define	RPFU_PUT_IDX		0x0464	/* 32 bit	Receive PFU Put Index Register */
+#define	RPFU_FIFO_WR		0x0470	/* 32 bit	Receive PFU FIFO RAM Write and
+									 *			Write Shadow Pointer Register
+									 */
+#define	RPFU_FIFO_RD		0x0474	/* 32 bit	Receive PFU FIFO RAM Read
+									 *			Pointer Register
+									 */
+#define	RPFU_FIFO_REQ_NB	0x0478	/* 32 bit	Receive PFU Master Request
+									 *			nbytes Register
+									 */
+#define	RPFU_FIFO_LEV		0x047C	/* 32 bit	Receive PFU FIFO Shadow Level
+									 *			Register
+									 */
+#define	TBMU_DESC1			0x0680	/* 32 bit	Current Transmit Descriptor
+									 *			Register 1
+									 */
+#define	TBMU_DESC2			0x0684	/* 16 bit	Current Transmit Descriptor
+									 *			Register 2
+									 */
+#define	TBMU_ADDR_LO		0x0688	/* 32 bit	Transmit Buffer Address Lower
+									 *			Register
+									 */
+#define	TBMU_ADDR_HI		0x068C	/* 32 bit	Transmit Buffer Address Upper
+									 *			Register
+									 */
+#define	TBMU_TFSW			0x0690	/* 32 bit	Transmit Buffer Status Word
+									 *			Register
+									 */
+#define	TBMU_VLAN			0x06A0	/* 32 bit	Transmit VLAN Tag Register */
+#define	TBMU_DONE_IDX		0x06A4	/* 32 bit	Transmit Done Index Register */
+#define	TBMU_REQ_ADDR_LO	0x06A8	/* 32 bit	Transmit Request Address Lower
+									 *			Register
+									 */
+#define	TBMU_REQ_ADDR_HI	0x06AC	/* 32 bit	Transmit Request Address Upper
+									 *			Register
+									 */
+#define	TBMU_REQ_CNT		0x06B0	/* 32 bit	Transmit Request Byte Count
+									 *			Register
+									 */
+#define	TBMU_CSR			0x06B4	/* 32 bit	Transmit BMU Control/Status
+									 *			Register
+									 */
+#define	TBMU_TEST			0x06B8	/* 32 bit	Transmit BMU Test Register */
+#define	TBMU_SM				0x06BC	/* 32 bit	Transmit BMU State Machine
+									 *			Register
+									 */
+#define	TBMU_FIFO_WM		0x06C0	/* 16 bit	Transmit FIFO Watermark Register */
+#define	TBMU_FIFO_AL		0x06C2	/* 16 bit	Transmit FIFO Alignment Register */
+#define	TBMU_FIFO_WSPTR		0x06C4	/* 16 bit	Transmit FIFO Write Shadow
+									 *			Pointer Register
+									 */
+#define	TBMU_FIFO_WSLEV		0x06C6	/* 16 bit	Transmit FIFO Write Shadow
+									 *			Level Register
+									 */
+#define	TBMU_FIFO_WPTR		0x06C8	/* 16 bit	Transmit FIFO Write Pointer
+									 *			Register
+									 */
+#define	TBMU_FIFO_WLEV		0x06CA	/* 16 bit	Transmit FIFO Write Level
+									 *			Register
+									 */
+#define	TBMU_FIFO_RPTR		0x06CC	/* 16 bit	Transmit FIFO Read Pointer
+									 *			Register
+									 */
+#define	TBMU_RLEV			0x06CE	/* 16 bit	Transmit FIFO Read Level
+									 *			Register
+									 */
+#define	TPFU_CTRL			0x06D0	/* 32 bit	Transmit Prefetch Control
+									 *			Register
+									 */
+#define	TPFU_LAST_IDX		0x06D4	/* 32 bit	Transmit PFU List Last Index
+									 *			Register
+									 */
+#define	TPFU_LADR_LO		0x06D8	/* 32 bit	Transmit PFU List Start Address
+									 *			Low Register
+									 */
+#define	TPFU_LADR_HI		0x06DC	/* 32 bit	Transmit PFU List Start Address
+									 *			High Register
+									 */
+#define	TPFU_GET_IDX		0x06E0	/* 32 bit	Transmit PFU Get Index Register */
+#define	TPFU_PUT_IDX		0x06E4	/* 32 bit	Transmit PFU Put Index Register */
+#define	TPFU_FIFO_WR		0x06F0	/* 32 bit	Transmit PFU FIFO RAM Write and
+									 *			Write Shadow Pointer Register
+									 */
+#define	TPFU_FIFO_RD		0x06F4	/* 32 bit	Transmit PFU FIFO RAM Read
+									 *			Pointer Register
+									 */
+#define	TPFU_FIFO_REQ_NB	0x06F8	/* 32 bit	Transmit PFU Master Request
+									 *			nbytes Register
+									 */
+#define	TPFU_FIFO_LEV		0x06FC	/* 32 bit	Transmit PFU FIFO Shadow Level
+									 *			Register
+									 */
+#define	RA_SADDR			0x0900	/* 32 bit	ASF Receive FIFO Start Address */
+#define	RA_EADDR			0x0904	/* 32 bit	ASF Receive FIFO End Address */
+#define	RA_WPTR				0x0908	/* 32 bit	ASF Receive FIFO Write Pointer */
+#define	RA_RPTR				0x090C	/* 32 bit	ASF Receive FIFO Read Pointer */
+#define	RA_BRST				0x0910	/* 32 bit	ASF Receive FIFO Burst Control */
+#define	RA_PCNT				0x0920	/* 32 bit	ASF Receive FIFO Packet Counter */
+#define	RA_LEV				0x0924	/* 32 bit	ASF Receive FIFO Level */
+#define	RA_CTRL				0x0928	/* 32 bit	ASF Receive FIFO Control/Test */
+#define	RA_FLSH_CTRL		0x092C	/* 32 bit	ASF Receive FIFO Flush Control */
+#define	TA_SADDR			0x0940	/* 32 bit	ASF Transmit FIFO Start Address */
+#define	TA_EADDR			0x0944	/* 32 bit	ASF Transmit FIFO End Address */
+#define	TA_WPTR				0x0948	/* 32 bit	ASF Transmit FIFO Write Pointer */
+#define	TA_RPTR				0x094C	/* 32 bit	ASF Transmit FIFO Read Pointer */
+#define	TA_PCNT				0x0960	/* 32 bit	ASF Transmit FIFO Packet Counter */
+#define	TA_LEV				0x0964	/* 32 bit	ASF Transmit FIFO Level */
+#define	TA_CTRL				0x0968	/* 32 bit	ASF Transmit FIFO Control/Test */
+#define	TA_SEND_CTRL		0x096C	/* 32 bit	ASF Transmit FIFO Send Control */
+#define	RXMF_EADDR			0x0C40	/* 32 bit	Receive MAC FIFO End Address
+									 *			Register
+									 */
+#define	RXMF_AFTH			0x0C44	/* 32 bit	Receive MAC FIFO Almost Full
+									 *			Threshold Register
+									 */
+#define	RXMF_TCTL			0x0C48	/* 32 bit	Receive MAC FIFO Control/Test
+									 *			Register
+									 */
+#define	RXMF_FLMSK			0x0C4C	/* 32 bit	Receive MAC FIFO Flush Mask
+									 *			Register
+									 */
+#define	RXMF_FLTH			0x0C50	/* 32 bit	Receive MAC FIFO Flush
+									 *			Threshold Register
+									 */
+#define	RXMF_TRTH			0x0C54	/* 32 bit	Receive Truncation Threshold
+									 *			Register
+									 */
+#define	RXMF_ULTH			0x0C58	/* 32 bit	Upper/Lower Threshold/Pause
+									 *			Packets Register
+									 */
+#define	RXMF_VLTYP			0x0C5C	/* 32 bit	Receive VLAN Type Register */
+#define	RXMF_WPTR			0x0C60	/* 32 bit	Receive MAC FIFO Write Pointer
+									 *			Register
+									 */
+#define	RXMF_WLEV			0x0C68	/* 32 bit	Receive MAC FIFO Write Level
+									 *			Register
+									 */
+#define	RXMF_RPTR			0x0C70	/* 32 bit	Receive MAC FIFO Read Pointer
+									 *			Register
+									 */
+#define	RXMF_RLEV			0x0C78	/* 32 bit	Receive MAC FIFO Read Level
+									 *			Register
+									 */
+#define	TXMF_EADDR			0x0D40	/* 32 bit	Transmit MAC FIFO End Address
+									 *			Register
+									 */
+#define	TXMF_AETH			0x0D44	/* 32 bit	Transmit MAC FIFO Almost Empty
+									 *			Threshold Register
+									 */
+#define	TXMF_TCTL			0x0D48	/* 32 bit	Transmit MAC FIFO Control/Test
+									 *			Register
+									 */
+#define	TXMF_VLTYP			0x0D5C	/* 32 bit	Transmit VLAN Type Register */
+#define	TXMF_WPTR			0x0D60	/* 32 bit	Transmit MAC FIFO Write Pointer
+									 *			Register
+									 */
+#define	TXMF_WSPTR			0x0D64	/* 32 bit	Transmit MAC FIFO Write Shadow
+									 *			Pointer Register
+									 */
+#define	TXMF_WLEV			0x0D68	/* 32 bit	Transmit MAC FIFO Write Level
+									 *			Register
+									 */
+#define	TXMF_RPTR			0x0D70	/* 32 bit	Transmit MAC FIFO Read Pointer
+									 *			Register
+									 */
+#define	TXMF_RES_PTR		0x0D74	/* 32 bit	Transmit MAC FIFO Restart
+									 *			Pointer Register
+									 */
+#define	TXMF_RLEV			0x0D78	/* 32 bit	Transmit MAC FIFO Read Level
+									 *			Register
+									 */
+#define	DPOL_TIM_INIT		0x0E00	/* 32 bit	Descriptor Poll Timer Init
+									 *			Value Register
+									 */
+#define	DPOL_TIM_CNT		0x0E04	/* 32 bit	Descriptor Poll Timer Register */
+#define	DPOL_TCTL			0x0E08	/* 32 bit	Descriptor Poll Timer
+									 *			Control/Test Register
+									 */
+#define	TSP_TIM_CNT			0x0E14	/* 32 bit	Timestamp Timer Registers */
+#define	TSP_TIM_TCTL		0x0E18	/* 32 bit	Timestamp Timer Control/Test
+									 *			Register
+									 */
+//#define	POLL_CTRL			0x0E20	/* 32 bit	Poll Control Register */
+//#define	POLL_LAST_IDX		0x0E24	/* 32 bit	List Last Index Register */
+#define	POLL_LADR_LO		0x0E28	/* 32 bit	List Start Address Low Register */
+#define	POLL_LADR_HI		0x0E2C	/* 32 bit	List Start Address High Register */
+#define	CPU_ISRC			0x0E30	/* 32 bit	Interrupt Source Register */
+#define	CPU_IMSK			0x0E34	/* 32 bit	Interrupt Mask Register */
+#define	SMB_CFG				0x0E40	/* 32 bit	SMBus Config Register */
+#define	SMB_CSR				0x0E44	/* 32 bit	SMBus Control/Status Register */
+#define	CPU_WDOG			0x0E48	/* 32 bit	Watchdog Register */
+#define	CPU_CNTR			0x0E4C	/* 32 bit	Counter Register */
+#define	CPU_TIM				0x0E50	/* 32 bit	Timer Compare Register */
+#define	CPU_AHB_ADDR		0x0E54	/* 32 bit	CPU AHB Debug Register */
+#define	CPU_AHB_WDATA		0x0E58	/* 32 bit	CPU AHB Debug Register */
+#define	CPU_AHB_RDATA		0x0E5C	/* 32 bit	CPU AHB Debug Register */
+#define	HCU_MAP_BASE		0x0E60	/* 32 bit	Reset Mapping Base */
+#define	CPU_AHB_CTRL		0x0E64	/* 32 bit	CPU AHB Debug Register */
+#define	HCU_CCSR			0x0E68	/* 32 bit	CPU Control and Status Register */
+#define	HCU_HCSR			0x0E6C	/* 32 bit	Host Control and Status Register */
+#define	HCU_DATA1			0x0E70	/* 32 bit	Data Register 1 */
+#define	HCU_DATA2			0x0E74	/* 32 bit	Data Register 2 */
+#define	HCU_DATA3			0x0E78	/* 32 bit	Data Register 3 */
+#define	HCU_DATA4			0x0E7C	/* 32 bit	Data Register 4 */
+//#define	STAT_CTRL			0x0E80	/* 32 bit	Status BMU Control Register */
+//#define	STAT_LAST_IDX		0x0E84	/* 32 bit	Last Index Register */
+#define	STAT_LADR_LO		0x0E88	/* 32 bit	List Start Address Lower
+									 *			Register
+									 */
+#define	STAT_LADR_HI		0x0E8C	/* 32 bit	List Start Address Upper
+									 *			Register
+									 */
+#define	STAT_TXA_REP		0x0E90	/* 16 bit	TXA Report Index Register */
+#define	STAT_TXTH			0x0E98	/* 16 bit	TX Index Threshold Register */
+#define	STAT_PUT			0x0E9C	/* 32 bit	Put Index Register */
+#define	STAT_FIFO_WPTR		0x0EA0	/* 32 bit	FIFO Write Pointer Register */
+#define	STAT_FIFO_RPTR		0x0EA4	/* 32 bit	FIFO Read Pointer Register */
+#define	STAT_FIFO_LEV		0x0EA8	/* 32 bit	FIFO Level Register */
+//#define	STAT_FIFO_WM		0x0EAC	/*  8 bit	FIFO Watermark Register */
+#define	STAT_FIFO_WM_ISR	0x0EAD	/*  8 bit	FIFO ISR Watermark Register */
+#define	LEV_TIM_INIT		0x0EB0	/* 32 bit	Level Timer Init Value Register */
+#define	LEV_TIM_CNT			0x0EB4	/* 32 bit	Level Timer Counter Register */
+#define	LEV_TIM_TCTL		0x0EB8	/* 32 bit	Level Timer Control/Test
+									 *			Register
+									 */
+#define	TX_TIM_INIT			0x0EC0	/* 32 bit	TX TImer Init Value Register */
+#define	TX_TIM_CNT			0x0EC4	/* 32 bit	TX Timer Counter Register */
+#define	TX_TIM_TCTL			0x0EC8	/* 32 bit	TX Timer Control/Test Register */
+#define	ISR_TIM_INIT		0x0ED0	/* 32 bit	ISR Timer Init Value Register */
+#define	ISR_TIM_CNT			0x0ED4	/* 32 bit	ISR Timer Counter Register */
+#define	ISR_TIM_TCTL		0x0ED8	/* 32 bit	ISR Timer Control/Test Register */
+#define	MAC_CTRL			0x0F00	/* 16 bit	MAC Control Registers */
+#define	PHY_CFG				0x0F04	/* 32 bit	PHY Config Register, loaded
+									 *			from external memory
+									 */
+#define	MAC_ISRC			0x0F08	/* 32 bit	MAC Interrupt Source Register */
+#define	MAC_IMSK			0x0F0C	/* 32 bit	MAC Interrupt Mask Register */
+#define	LINK_CTRL			0x0F10	/* 16 bit	Link Control Register */
+#define	WOL_CSR				0x0F20	/* 16 bit	WOL Control/Status Register */
+#define	WOL_MCTRL			0x0F22	/* 16 bit	Match Control Register */
+#define	WOL_MADDR_LO		0x0F24	/* 32 bit	MAC Address Register Low
+									 *			Register
+									 */
+#define	WOL_MADDR_HI		0x0F28	/* 16 bit	MAC Address Register High
+									 *			Register
+									 */
+#define	WOL_PME_MEN			0x0F2A	/* 16 bit	PME Match Enable Register */
+#define	WOL_ASF_MEN			0x0F2C	/* 16 bit	ASF Match Enable Register */
+#define	WOL_MRSL			0x0F2E	/* 16 bit	Match Result Register */
+#define	WOL_PLEN0			0x0F30	/* 32 bit	Pattern Length Register 0 (0-3) */
+#define	WOL_PLEN1			0x0F34	/* 32 bit	Pattern Length Register 1 (4-7) */
+#define	WOL_PLEN2			0x0F38	/* 32 bit	Pattern Length Register 2 (8) */
+#define	WOL_PCNT0			0x0F40	/* 32 bit	Pattern Counter Register 0 (0-3) */
+#define	WOL_PCNT1			0x0F44	/* 32 bit	Pattern Counter Register 1 (4-7) */
+#define	WOL_PCNT2			0x0F48	/* 32 bit	Pattern Counter Register 2 (8) */
+#define	PAT_CSR				0x0F50	/* 32 bit	Pattern RAM Control/Status
+									 *			Register
+									 */
+#define	PAT_RAM				0x1000	/* 32 bit	Pattern RAM Register */
+#define	THDR0_LO			0x1900	/* 32 bit	TCP Segmentation Header
+									 *			Register 0 Lo
+									 */
+#define	THDR0_HI			0x1904	/* 32 bit	TCP Segmentation Header
+									 *			Register 0 Hi
+									 */
+#define	THDR1_LO			0x1908	/* 32 bit	TCP Segmentation Header
+									 *			Register 1 Lo
+									 */
+#define	THDR1_HI			0x190C	/* 32 bit	TCP Segmentation Header
+									 *			Register 1 Hi
+									 */
+#define	THDR2_LO			0x1910	/* 32 bit	TCP Segmentation Header
+									 *			Register 2 Lo
+									 */
+#define	THDR2_HI			0x1914	/* 32 bit	TCP Segmentation Header
+									 *			Register 2 Hi
+									 */
+#define	THDR3_LO			0x1918	/* 32 bit	TCP Segmentation Header
+									 *			Register 3 Lo
+									 */
+#define	THDR3_HI			0x191C	/* 32 bit	TCP Segmentation Header
+									 *			Register 3 Hi
+									 */
+#define	THDR4_LO			0x1920	/* 32 bit	TCP Segmentation Header
+									 *			Register 4 Lo
+									 */
+#define	THDR4_HI			0x1924	/* 32 bit	TCP Segmentation Header
+									 *			Register 4 Hi
+									 */
+#define	THDR5_LO			0x1928	/* 32 bit	TCP Segmentation Header
+									 *			Register 5 Lo
+									 */
+#define	THDR5_HI			0x192C	/* 32 bit	TCP Segmentation Header
+									 *			Register 5 Hi
+									 */
+#define	THDR6_LO			0x1930	/* 32 bit	TCP Segmentation Header
+									 *			Register 6 Lo
+									 */
+#define	THDR6_HI			0x1934	/* 32 bit	TCP Segmentation Header
+									 *			Register 6 Hi
+									 */
+#define	THDR7_LO			0x1938	/* 32 bit	TCP Segmentation Header
+									 *			Register 7 Lo
+									 */
+#define	THDR7_HI			0x193C	/* 32 bit	TCP Segmentation Header
+									 *			Register 7 Hi
+									 */
+#define	THDR8_LO			0x1940	/* 32 bit	TCP Segmentation Header
+									 *			Register 8 Lo
+									 */
+#define	THDR8_HI			0x1944	/* 32 bit	TCP Segmentation Header
+									 *			Register 8 Hi
+									 */
+#define	THDR9_LO			0x1948	/* 32 bit	TCP Segmentation Header
+									 *			Register 9 Lo
+									 */
+#define	THDR9_HI			0x194C	/* 32 bit	TCP Segmentation Header
+									 *			Register 9 Hi
+									 */
+#define	THDR10_LO			0x1950	/* 32 bit	TCP Segmentation Header
+									 *			Register 10 Lo
+									 */
+#define	THDR10_HI			0x1954	/* 32 bit	TCP Segmentation Header
+									 *			Register 10 Hi
+									 */
+#define	THDR11_LO			0x1958	/* 32 bit	TCP Segmentation Header
+									 *			Register 11 Lo
+									 */
+#define	THDR11_HI			0x195C	/* 32 bit	TCP Segmentation Header
+									 *			Register 11 Hi
+									 */
+#define	THDR12_LO			0x1960	/* 32 bit	TCP Segmentation Header
+									 *			Register 12 Lo
+									 */
+#define	THDR12_HI			0x1964	/* 32 bit	TCP Segmentation Header
+									 *			Register 12 Hi
+									 */
+#define	THDR13_LO			0x1968	/* 32 bit	TCP Segmentation Header
+									 *			Register 13 Lo
+									 */
+#define	THDR13_HI			0x196C	/* 32 bit	TCP Segmentation Header
+									 *			Register 13 Hi
+									 */
+#define	THDR14_LO			0x1970	/* 32 bit	TCP Segmentation Header
+									 *			Register 14 Lo
+									 */
+#define	THDR14_HI			0x1974	/* 32 bit	TCP Segmentation Header
+									 *			Register 14 Hi
+									 */
+#define	THDR15_LO			0x1978	/* 32 bit	TCP Segmentation Header
+									 *			Register 15 Lo
+									 */
+#define	THDR15_HI			0x197C	/* 32 bit	TCP Segmentation Header
+									 *			Register 15 Hi
+									 */
+#define	THDR16_LO			0x1980	/* 32 bit	TCP Segmentation Header
+									 *			Register 16 Lo
+									 */
+#define	THDR16_HI			0x1984	/* 32 bit	TCP Segmentation Header
+									 *			Register 16 Hi
+									 */
+#define	THDR17_LO			0x1988	/* 32 bit	TCP Segmentation Header
+									 *			Register 17 Lo
+									 */
+#define	THDR17_HI			0x198C	/* 32 bit	TCP Segmentation Header
+									 *			Register 17 Hi
+									 */
+#define	THDR18_LO			0x1990	/* 32 bit	TCP Segmentation Header
+									 *			Register 18 Lo
+									 */
+#define	THDR18_HI			0x1994	/* 32 bit	TCP Segmentation Header
+									 *			Register 18 Hi
+									 */
+#define	THDR19_LO			0x1998	/* 32 bit	TCP Segmentation Header
+									 *			Register 19 Lo
+									 */
+#define	THDR19_HI			0x199C	/* 32 bit	TCP Segmentation Header
+									 *			Register 19 Hi
+									 */
+#define	THDR20_LO			0x19A0	/* 32 bit	TCP Segmentation Header
+									 *			Register 20 Lo
+									 */
+#define	THDR20_HI			0x19A4	/* 32 bit	TCP Segmentation Header
+									 *			Register 20 Hi
+									 */
+#define	THDR21_LO			0x19A8	/* 32 bit	TCP Segmentation Header
+									 *			Register 21 Lo
+									 */
+#define	THDR21_HI			0x19AC	/* 32 bit	TCP Segmentation Header
+									 *			Register 21 Hi
+									 */
+#define	THDR22_LO			0x19B0	/* 32 bit	TCP Segmentation Header
+									 *			Register 22 Lo
+									 */
+#define	THDR22_HI			0x19B4	/* 32 bit	TCP Segmentation Header
+									 *			Register 22 Hi
+									 */
+#define	THDR23_LO			0x19B8	/* 32 bit	TCP Segmentation Header
+									 *			Register 23 Lo
+									 */
+#define	THDR23_HI			0x19BC	/* 32 bit	TCP Segmentation Header
+									 *			Register 23 Hi
+									 */
+#define	THDR24_LO			0x19C0	/* 32 bit	TCP Segmentation Header
+									 *			Register 24 Lo
+									 */
+#define	THDR24_HI			0x19C4	/* 32 bit	TCP Segmentation Header
+									 *			Register 24 Hi
+									 */
+#define	THDR25_LO			0x19C8	/* 32 bit	TCP Segmentation Header
+									 *			Register 25 Lo
+									 */
+#define	THDR25_HI			0x19CC	/* 32 bit	TCP Segmentation Header
+									 *			Register 25 Hi
+									 */
+#define	THDR26_LO			0x19D0	/* 32 bit	TCP Segmentation Header
+									 *			Register 26 Lo
+									 */
+#define	THDR26_HI			0x19D4	/* 32 bit	TCP Segmentation Header
+									 *			Register 26 Hi
+									 */
+#define	THDR27_LO			0x19D8	/* 32 bit	TCP Segmentation Header
+									 *			Register 27 Lo
+									 */
+#define	THDR27_HI			0x19DC	/* 32 bit	TCP Segmentation Header
+									 *			Register 27 Hi
+									 */
+#define	THDR28_LO			0x19E0	/* 32 bit	TCP Segmentation Header
+									 *			Register 28 Lo
+									 */
+#define	THDR28_HI			0x19E4	/* 32 bit	TCP Segmentation Header
+									 *			Register 28 Hi
+									 */
+#define	THDR29_LO			0x19E8	/* 32 bit	TCP Segmentation Header
+									 *			Register 29 Lo
+									 */
+#define	THDR29_HI			0x19EC	/* 32 bit	TCP Segmentation Header
+									 *			Register 29 Hi
+									 */
+#define	THDR30_LO			0x19F0	/* 32 bit	TCP Segmentation Header
+									 *			Register 30 Lo
+									 */
+#define	CFG_VLAN_ET1		0x2000	/* 32 bit	VLAN Ethernet Type
+									 *			Configuration Register 1
+									 */
+#define	CFG_VLAN_ET0		0x2004	/* 32 bit	VLAN Ethernet Type
+									 *			Configuration Register 0
+									 */
+#define	CFG_MACSEC_ET1		0x2008	/* 32 bit	802.1AE Ethernet Type
+									 *			Configuration Register 1
+									 */
+#define	CFG_MACSEC_ET0		0x200C	/* 32 bit	802.1AE Ethernet Type
+									 *			Configuration Register 0
+									 */
+#define	CFG_TRAIL_SZ		0x2010	/* 32 bit	Trail Size Configuration
+									 *			Register
+									 */
+#define	CFG_DEFAULT_VLAN0	0x2014	/* 32 bit	Default VLAN Register 0 */
+#define	CFG_DEFAULT_VLAN1	0x2018	/* 32 bit	Default VLAN Register 1 */
+#define	CFG_MACSEC_SL_SZ	0x201C	/* 32 bit	MACSec Size Configuration
+									 *			Register
+									 */
+#define	CFG_MIN_PKT_LEN		0x2020	/* 32 bit	Minimum Packet Length
+									 *			Configuration Register
+									 */
+#define	SEC_CLK_RST			0x2024	/* 32 bit	MACSec Clock Reset Register */
+#define	EGR_KS_SELECT		0x2028	/* 32 bit	Egress Key Store Select Register */
+#define	EGR_KS_WRDATA		0x202C	/* 32 bit	Egress Key Store Write Data
+									 *			Register
+									 */
+#define	IGR_KS_SELECT		0x2030	/* 32 bit	Ingress Key Store Select
+									 *			Register
+									 */
+#define	IGR_KS_WRDATA		0x2034	/* 32 bit	Ingress Key Store Write Data
+									 *			Register
+									 */
+#define	CFG_ELU_MC_HIGH0	0x2038	/* 32 bit	Multicast Match Register 0 */
+#define	CFG_ELU_MC_HIGH1	0x203C	/* 32 bit	Multicast Match Register 1 */
+#define	CFG_ELU_MC_HIGH2	0x2040	/* 32 bit	Multicast Match Register 2 */
+#define	CFG_ELU_MC_HIGH3	0x2044	/* 32 bit	Multicast Match Register 3 */
+#define	CFG_ELU_MC_HIGH4	0x2048	/* 32 bit	Multicast Match Register 4 */
+#define	CFG_ELU_MC_HIGH5	0x204C	/* 32 bit	Multicast Match Register 5 */
+#define	CFG_ELU_MC_LOW_MSK0	0x2050	/* 32 bit	Multicast Match Mask Register 0 */
+#define	CFG_ELU_MC_LOW_MSK1	0x2054	/* 32 bit	Multicast Match Mask Register 1 */
+#define	CFG_DEFAULT_PORT0	0x2058	/* 32 bit	Default Port Configuration
+									 *			Register 0
+									 */
+#define	CFG_DEFAULT_PORT1	0x205C	/* 32 bit	Default Port Configuration
+									 *			Register 1
+									 */
+#define	CFG_SCB_PORT0		0x2060	/* 32 bit	SCB Port Configuration Register
+									 *			0
+									 */
+#define	CFG_SCB_PORT1		0x2064	/* 32 bit	SCB Port Configuration Register
+									 *			1
+									 */
+#define	CFG_AUTH_ADJUST		0x2068	/* 32 bit	Authentication Adjustment
+									 *			Register
+									 */
+#define	CFG_ELU_GEN			0x206C	/* 32 bit	ELU Default Configuration
+									 *			Register
+									 */
+#define	CFG_ELUC_ADDR		0x2070	/* 32 bit	ELU Address Configuration
+									 *			Register
+									 */
+#define	CFG_ELUC_DATA		0x2074	/* 32 bit	ELU Context Data Configuration
+									 *			Register
+									 */
+#define	CFG_ELUE_ADDR		0x2078	/* 32 bit	ELU Entry Configuration Register */
+#define	CFG_ELUE_DATA		0x207C	/* 32 bit	ELU Lookup Entry Access
+									 *			Configuration Register
+									 */
+#define	CFG_EPR_GEN			0x2080	/* 32 bit	General Egress Parser
+									 *			Configuration Register
+									 */
+#define	EGR_HR_SELECT		0x2084	/* 32 bit	Egress Write Select for H-Store
+									 *			Register
+									 */
+#define	EGR_HR_WRDATA		0x2088	/* 32 bit	Egress Header Write Data
+									 *			Register
+									 */
+#define	IGR_HR_SELECT		0x208C	/* 32 bit	Ingress Write Select for
+									 *			H-Store Register
+									 */
+#define	IGR_HR_WRDATA		0x2090	/* 32 bit	Ingress Header Write Data
+									 *			Register
+									 */
+#define	CFG_ILU_GEN			0x2094	/*  8 bit	cfg_ilu_gen */
+#define	CFG_IMPLICIT_SCI0	0x2098	/* 32 bit	Implicit SCI Register 0 */
+#define	CFG_IMPLICIT_SCI1	0x209C	/* 32 bit	Implicit SCI Register 1 */
+#define	CFG_IMPLICIT_SCI2	0x20A0	/* 32 bit	Implicit SCI Register 2 */
+#define	CFG_IMPLICIT_SCI3	0x20A4	/* 32 bit	Implicit SCI Register 3 */
+#define	CFG_IMPLICIT_SCI4	0x20A8	/* 32 bit	Implicit SCI Register 4 */
+#define	CFG_IMPLICIT_SCI5	0x20AC	/* 32 bit	Implicit SCI Register 5 */
+#define	CFG_IMPLICIT_SCI6	0x20B0	/* 32 bit	Implicit SCI Register 6 */
+#define	CFG_IMPLICIT_SCI7	0x20B4	/* 32 bit	Implicit SCI Register 7 */
+#define	CFG_REPLAY_WINDOW0	0x20B8	/* 32 bit	Replay Window Register 0 */
+#define	CFG_REPLAY_WINDOW1	0x20BC	/* 32 bit	Replay Window Register 1 */
+#define	CFG_REPLAY_WINDOW2	0x20C0	/* 32 bit	Replay Window Register 2 */
+#define	CFG_REPLAY_WINDOW3	0x20C4	/* 32 bit	Replay Window Register 3 */
+#define	CFG_IPR_GEN			0x20C8	/* 32 bit	Ingress Primary Parser Register */
+#define	CFG_ISC_GEN			0x20CC	/* 32 bit	Ingress Security Check Block
+									 *			Register
+									 */
+#define	CFG_RPY_ADDR		0x20D0	/* 32 bit	Replay Protect Table Access
+									 *			Register
+									 */
+#define	CFG_RPY_DATA		0x20D4	/* 32 bit	ELU Context Data Register */
+#define	CFG_ILUT_ADDR		0x20E0	/* 32 bit	Ingress Lookup Table Access
+									 *			Address Configuration Register
+									 */
+#define	CFG_ILUT_DATA		0x20E4	/* 32 bit	ILU Table Data Register */
+#define	STAT_ADDR			0x20E8	/* 32 bit	Statistic Register Address */
+#define	STAT_DATA0			0x20EC	/* 32 bit	Statistic Data Register 0 */
+#define	STAT_DATA1			0x20F0	/* 32 bit	Statistic Data Register 1 */
+#define	STAT_DATA2			0x20F4	/* 32 bit	Statistic Data Register 2 */
+#define	CFG_OVER_LEN1		0x20F8	/* 32 bit	Over-Length Configuration
+									 *			Register 1
+									 */
+#define	CNT_TX_ERR			0x2100	/* 32 bit	MACSec TX Processing Error Count */
+#define	CFG_IPAR_HYST		0x2104	/* 32 bit	Ingress Parse FIFO Hysteresis */
+#define	CFG_EPAR_HYST		0x2108	/* 32 bit	Egress Parse FIFO Hysteresis */
+#define	RE_TRF_TCTL			0x2200	/* 32 bit	MACSec Retransmit FIFO Control */
+#define	RE_TRF_PCNT			0x2204	/* 32 bit	Retransmit FIFO Packet Counter */
+#define	RE_TRF_TTH			0x2208	/* 32 bit	Retransmit FIFO Transmit Start
+									 *			Threshold
+									 */
+#define	RE_TRF_WPTR			0x2210	/* 32 bit	Retransmit FIFO Write Pointer
+									 *			Register
+									 */
+#define	RE_TRF_WLEV			0x2218	/* 32 bit	Retransmit FIFO Write Level
+									 *			Register
+									 */
+#define	RE_TRF_RPTR			0x2220	/* 32 bit	Retransmit FIFO Read Pointer
+									 *			Register
+									 */
+#define	RE_TRF_RES_PTR		0x2224	/* 32 bit	Transmit FIFO Restart Pointer
+									 *			Register
+									 */
+#define	RE_TRF_RLEV			0x2228	/* 32 bit	Retransmit FIFO Read Level
+									 *			Register
+									 */
+#define	RE_TRF_RSPTR		0x222c	/* 32 bit	Retransmit FIFO Read Shadow
+									 *			Level Register
+									 */
+
+/*
+ *
+ *	THE BIT DEFINES
+ *
+ */
+/*	GLB_RAP				0x0000	Register Address Port (RAP) Register */
+/*		Bit(s) GLB_RAP_RSRV_31_7 reserved */
+#define	GLB_RAP_MSK					SHIFT0(0x7f)		/* RAP */
+#define	GLB_RAP_BASE				0
+
+/*	GLB_CSR				0x0004	Control/Status Register */
+/*		Bit(s) GLB_CSR_RSRV_23_18 reserved */
+#define	GLB_CSR_VMAIN_AVL			BIT_17			/* Vmain Available */
+#define	GLB_CSR_VAUX_AVL			BIT_16			/* Vaux Available */
+#define	GLB_CSR_RUN_PIG_ENA			BIT_15S			/* Run_PiG_Enable */
+#define	GLB_CSR_RUN_PIG_DIS			BIT_14S			/* Run_PiG_Disable */
+#define	GLB_CSR_ASF_ENA_SET			BIT_13S			/* ASF Enable Set */
+#define	GLB_CSR_ASF_ENA_CLR			BIT_12S			/* ASF Enable Clear */
+/*		Bit(s) GLB_CSR_RSRV_11 reserved */
+/*		Bit(s) GLB_CSR_RSRV_10 reserved */
+#define	GLB_CSR_LED0_ON				BIT_9S			/* LED<0>On */
+#define	GLB_CSR_LED0_OFF			BIT_8S			/* LED<0>Off */
+#define	GLB_CSR_IRQ_SW_SET			BIT_7S			/* Set IRQ SW */
+#define	GLB_CSR_IRQ_SW_CLR			BIT_6S			/* Clear IRQ SW */
+#define	GLB_CSR_STOP_MST_DONE		BIT_5S			/* Stop Master Done */
+#define	GLB_CSR_STOP_MST			BIT_4S			/* Stop Master */
+#define	GLB_CSR_MST_RST_CLR			BIT_3S			/* Master Reset Clear */
+#define	GLB_CSR_MST_RST_SET			BIT_2S			/* Master Reset Set */
+#define	GLB_CSR_SW_RST_CLR			BIT_1S			/* SW Reset Clear */
+#define	GLB_CSR_SW_RST_SET			BIT_0S			/* SW Reset Set */
+
+/*	GLB_PCTRL			0x0007	Power Control Register */
+#define	GLB_PCTRL_SW_VAUX_ENA		BIT_7S	/* Switch Vaux Enable */
+#define	GLB_PCTRL_SW_VAUX_DIS		BIT_6S	/* Switch Vaux Disable */
+#define	GLB_PCTRL_SW_VCC_ENA		BIT_5S	/* Switch VCC Enable */
+#define	GLB_PCTRL_SW_VCC_DIS		BIT_4S	/* Switch VCC Disable */
+#define	GLB_PCTRL_SW_VAUX_ON		BIT_3S	/* Switch Vaux On */
+#define	GLB_PCTRL_SW_VAUX_OFF		BIT_2S	/* Switch Vaux Off */
+#define	GLB_PCTRL_SW_VCC_ON			BIT_1S	/* Switch VCC On */
+#define	GLB_PCTRL_SW_VCC_OFF		BIT_0S	/* Switch VCC Off */
+
+/*	GLB_ISRC			0x0008	Interrupt Source Register */
+#define	GLB_ISRC_HW_IRQ				BIT_31			/* HW Interrupt */
+#define	GLB_ISRC_STAT_BMU			BIT_30			/* Status BMU */
+#define	GLB_ISRC_CPU_HOST			BIT_29			/* CPU to Host */
+#define	GLB_ISRC_CPU_TO				BIT_28			/* CPU Timeout */
+#define	GLB_ISRC_POLL_CHK			BIT_27			/* IRQ Polling CHK */
+#define	GLB_ISRC_TWSI_RDY			BIT_26			/* IRQ TWSI Ready */
+#define	GLB_ISRC_SW					BIT_25			/* IRQ SW */
+#define	GLB_ISRC_TIM				BIT_24			/* IRQ Timer */
+/*		Bit(s) GLB_ISRC_RSRV_23_8 reserved */
+/*		Bit(s) GLB_ISRC_RSRV_7_5 reserved */
+#define	GLB_ISRC_PHY				BIT_4			/* IRQ PHY */
+#define	GLB_ISRC_MAC				BIT_3			/* IRQ MAC */
+#define	GLB_ISRC_CHK_RX				BIT_2			/* IRQ CHCK Rx */
+/*		Bit(s) GLB_ISRC_RSRV_1 reserved */
+#define	GLB_ISRC_CHK_TXA			BIT_0			/* IRQ CHCK TxA */
+
+/*	GLB_IMSK			0x000C	Interrupt Mask Register */
+#define	GLB_IMSK_HW_IRQ				BIT_31			/* En IRQ HW Interrupt */
+#define	GLB_IMSK_STAT_BMU			BIT_30			/* En IRQ Status BMU */
+#define	GLB_IMSK_CPU_HOST			BIT_29			/* En CPU to Host */
+#define	GLB_IMSK_CPU_TO				BIT_28			/* En CPU Timeout */
+#define	GLB_IMSK_POLL_CHK			BIT_27			/* En IRQ Polling CHK */
+#define	GLB_IMSK_TWSI_RDY			BIT_26			/* En IRQ TWSI Ready */
+#define	GLB_IMSK_SW					BIT_25			/* En IRQ SW */
+#define	GLB_IMSK_TIM				BIT_24			/* En IRQ Timer */
+/*		Bit(s) GLB_IMSK_RSRV_23_8 reserved */
+/*		Bit(s) GLB_IMSK_RSRV_7_5 reserved */
+#define	GLB_IMSK_PHY				BIT_4			/* En IRQ PHY */
+#define	GLB_IMSK_MAC				BIT_3			/* En IRQ MAC */
+#define	GLB_IMSK_CHK_RX				BIT_2			/* En IRQ CHCK Rx */
+/*		Bit(s) GLB_IMSK_RSRV_1 reserved */
+#define	GLB_IMSK_CHK_TXA			BIT_0			/* En IRQ CHCK TxA */
+
+/*	GLB_ISRC_HW			0x0010	Interrupt HW Error Source Register */
+/*		Bit(s) GLB_ISRC_HW_RSRV_31_30 reserved */
+/* IRQ Timestamp Timer Overflow */
+#define	GLB_ISRC_HW_TSP_TIM				BIT_29			
+#define	GLB_ISRC_HW_SEN					BIT_28			/* IRQ Sensor */
+#define	GLB_ISRC_HW_MST_ERR				BIT_27			/* IRQ Master Error */
+#define	GLB_ISRC_HW_PCI_STAT			BIT_26			/* IRQ Status */
+#define	GLB_ISRC_HW_PCIE_SPE			BIT_25			/* IRQ PE */
+#define	GLB_ISRC_HW_PCIE_NO_PE			BIT_24			/* IRQ NO PE */
+/*		Bit(s) GLB_ISRC_HW_RSRV_23_8 reserved */
+/*		Bit(s) GLB_ISRC_HW_RSRV_7_4 reserved */
+#define	GLB_ISRC_HW_PAR_MAC				BIT_3			/* IRQ Par MAC */
+#define	GLB_ISRC_HW_PAR_RX				BIT_2			/* IRQ PAR Rx */
+/*		Bit(s) GLB_ISRC_HW_RSRV_1 reserved */
+#define	GLB_ISRC_HW_TCP_TXA				BIT_0			/* IRQ TCP Length TxA1 */
+
+/*	GLB_IMSK_HW			0x0014	Interrupt HW Error Mask Register */
+/*		Bit(s) GLB_IMSK_HW_RSRV_31_30 reserved */
+/* En IRQ Timestamp Timer Overflow */
+#define	GLB_IMSK_HW_TSP_TIM				BIT_29			
+#define	GLB_IMSK_HW_SEN					BIT_28			/* En IRQ Sensor */
+#define	GLB_IMSK_HW_MST_ERR				BIT_27			/* En IRQ Master Error */
+#define	GLB_IMSK_HW_PCI_STAT			BIT_26			/* En IRQ Status */
+#define	GLB_IMSK_HW_PCIE_SPE			BIT_25			/* En IRQ PE */
+#define	GLB_IMSK_HW_PCIE_NO_PE			BIT_24			/* En IRQ NO PE */
+/*		Bit(s) GLB_IMSK_HW_RSRV_23_8 reserved */
+/*		Bit(s) GLB_IMSK_HW_RSRV_7_4 reserved */
+#define	GLB_IMSK_HW_PAR_MAC				BIT_3			/* En IRQ Par MAC */
+#define	GLB_IMSK_HW_PAR_RX				BIT_2			/* En IRQ PAR Rx */
+/*		Bit(s) GLB_IMSK_HW_RSRV_1 reserved */
+#define	GLB_IMSK_HW_TCP_TXA				BIT_0			/* En IRQ TCP Length TxA1 */
+
+/*	GLB_ISRC_SP1		0x0018	Special Interrupt Source Register 1 */
+#define	GLB_ISRC_SP1__IRQ_XXX_MSK		SHIFT0(0xffffffff)	/* IRQ xxx */
+#define	GLB_ISRC_SP1__IRQ_XXX_BASE		0
+
+/*	GLB_ISRC_SP2		0x001C	Special Interrupt Source Register 2 */
+#define	GLB_ISRC_SP2__IRQ_XXX_MSK		SHIFT0(0xffffffff)	/* IRQ xxx */
+#define	GLB_ISRC_SP2__IRQ_XXX_BASE		0
+
+/*	GLB_ISRC_SP3		0x0020	Special Interrupt Source Register 3 */
+#define	GLB_ISRC_SP3__IRQ_XXX_MSK		SHIFT0(0xffffffff)	/* IRQ xxx */
+#define	GLB_ISRC_SP3__IRQ_XXX_BASE		0
+
+/*	GLB_EISR			0x0024	Enter Interrupt Service Routine Register */
+#define	GLB_EISR__IRQ_XXX_MSK		SHIFT0(0xffffffff)	/* Enter ISR Reg */
+#define	GLB_EISR__IRQ_XXX_BASE		0
+
+/*	GLB_LISR			0x0028	Leave Interrupt Service Routine Register */
+#define	GLB_LISR__IRQ_XXX_MSK		SHIFT0(0xffffffff)	/* Leave ISR Reg */
+#define	GLB_LISR__IRQ_XXX_BASE		0
+
+/*	GLB_ICTRL			0x002C	Interrupt Control Register */
+/*		Bit(s) GLB_ICTRL_RSRV_31_4 reserved */
+#define	GLB_ICTRL_ISR_MSK				BIT_3				/* isr_mask */
+#define	GLB_ICTRL_ISR_STAT				BIT_2				/* isr_status */
+#define	GLB_ICTRL_LEAVE_ISR				BIT_1				/* Leave ISR */
+#define	GLB_ICTRL_ENTER_ISR				BIT_0				/* Enter ISR */
+
+/*	SPI_CTRL			0x0060	SPI Flash Memory Control Register */
+#define	SPI_CTRL_STRT_LDR			BIT_31			/* Loader Start */
+#define	SPI_CTRL_BSY				BIT_30			/* SPI Busy */
+#define	SPI_CTRL_RESV				BIT_29			/* RESV */
+#define	SPI_CTRL_RD_ID_PROT			BIT_28			/* RD ID Protocol */
+/*		Bit(s) SPI_CTRL_RSRV_7_0 reserved */
+#define	SPI_CTRL_STRT_SPI			BIT_19			/* Start SPI */
+#define	SPI_CTRL_INST_MSK			SHIFT16(0x7)	/* Instruction */
+#define	SPI_CTRL_INST_BASE			BIT_16
+/*		Bit(s) SPI_CTRL_RSRV_7_0 reserved */
+#define	SPI_CTRL_STAT_MSK			SHIFT0(0xff)	/* SPI device Status */
+#define	SPI_CTRL_STAT_BASE			BIT_0
+
+/*	SPI_ADDR			0x0064	SPI Flash Memory Address Register */
+/*		Bit(s) SPI_ADDR_RSRV_11_0 reserved */
+#define	SPI_ADDR_MSK				SHIFT0(0xfffff)	/* SPI Flash Memory address */
+#define	SPI_ADDR_BASE				BIT_0
+
+/*	SPI_DATA			0x0068	SPI Flash Memory Data Register */
+#define	SPI_DATA_MSK		SHIFT0(0xffffffff)	/* SPI Flash Memory data */
+#define	SPI_DATA_BASE		BIT_0
+
+/*	SPI_ID				0x006C	SPI Flash Memory Vendor/Device ID Register */
+/*		Bit(s) SPI_ID_RSRV_15_0 reserved */
+#define	SPI_ID_VEN_ID_MSK			SHIFT8(0xff)	/* Vendor-ID */
+#define	SPI_ID_VEN_ID_BASE			BIT_8
+#define	SPI_ID_DEV_ID_MSK			SHIFT0(0xff)	/* Device-ID */
+#define	SPI_ID_DEV_ID_BASE			BIT_0
+
+/*	SPI_LCFG			0x0070	SPI Flash Memory Loader Configuration Register */
+/*		Bit(s) SPI_LCFG_RSRV_3_0 reserved */
+#define	SPI_LCFG_NRML_ADDR_MSK		SHIFT16(0xfff)	/* Normal Loader start address */
+#define	SPI_LCFG_NRML_ADDR_BASE		BIT_16
+/*		Bit(s) SPI_LCFG_RSRV_3_0 reserved */
+#define	SPI_LCFG_INIT_ADDR_MSK		SHIFT0(0xfff)	/* PIG Loader start address */
+#define	SPI_LCFG_INIT_ADDR_BASE		BIT_0
+
+/*	SPI_CFG				0x0074	SPI Flash Memory Configuration Register */
+/*		Bit(s) SPI_CFG_RSRV_30_0 reserved */
+#define	SPI_CFG_A17_GATE			BIT_0				/* A17 Gate */
+
+/*	SPI_OPC1			0x0078	SPI Flash Memory Opcode 1 Register */
+#define	SPI_OPC1_RDSR_MSK		SHIFT24(0xff)	/* Opcode Read Status */
+#define	SPI_OPC1_RDSR_BASE		BIT_24
+#define	SPI_OPC1_RDID_MSK		SHIFT16(0xff)	/* Opcode Read ID */
+#define	SPI_OPC1_RDID_BASE		BIT_16
+#define	SPI_OPC1_RD_MSK			SHIFT8(0xff)	/* Opcode Read */
+#define	SPI_OPC1_RD_BASE		BIT_8
+#define	SPI_OPC1_NOP_MSK		SHIFT0(0xff)	/* Opcode No Operation */
+#define	SPI_OPC1_NOP_BASE		BIT_0
+
+/*	SPI_OPC2			0x007C	SPI Flash Memory Opcode 2 Register */
+#define	SPI_OPC2_CE_MSK			SHIFT24(0xff)	/* Opcode Chip Erase */
+#define	SPI_OPC2_CE_BASE		BIT_24
+#define	SPI_OPC2_SE_MSK			SHIFT16(0xff)	/* Opcode Sector Erase */
+#define	SPI_OPC2_SE_BASE		BIT_16
+#define	SPI_OPC2_WR_MSK			SHIFT8(0xff)	/* Opcode Write */
+#define	SPI_OPC2_WR_BASE		BIT_8
+#define	SPI_OPC2_WREN_MSK		SHIFT0(0xff)	/* Opcode Write Enable */
+#define	SPI_OPC2_WREN_BASE		BIT_0
+
+/*	GLB_BWIN			0x0080	Block Window Register */
+#define	GLB_BWIN_MSK		SHIFT0(0xffffffff)	/* Mapped register XY */
+#define	GLB_BWIN_BASE		0
+
+/*	L1_CFG_MADDR_Hi		0x0100	Link1 MAC Address Register High */
+#define	CFG_MADDR_HI_VAL_3_MSK		SHIFT24(0xff)	/* MAC Addr_x<3> */
+#define	CFG_MADDR_HI_VAL_3_BASE		24
+#define	CFG_MADDR_HI_VAL_2_MSK		SHIFT16(0xff)	/* MAC Addr_x<2> */
+#define	CFG_MADDR_HI_VAL_2_BASE		16
+#define	CFG_MADDR_HI_VAL_1_MSK		SHIFT8(0xff)	/* MAC Addr_x<1> */
+#define	CFG_MADDR_HI_VAL_1_BASE		8
+#define	CFG_MADDR_HI_VAL_0_MSK		SHIFT0(0xff)	/* MAC Addr_x<0> */
+#define	CFG_MADDR_HI_VAL_0_BASE		0
+
+/*	L1_CFG_MADDR_LO		0x0104	Link1 MAC Address Register Low */
+/*		Bit(s) CFG_MADDR_LO_RSRV_31_16 reserved */
+#define	CFG_MADDR_LO_VAL_5_MSK				SHIFT8(0xff)	/* MAC Addr_x<5> */
+#define	CFG_MADDR_LO_VAL_5_BASE				8
+#define	CFG_MADDR_LO_VAL_4_MSK				SHIFT0(0xff)	/* MAC Addr_x<4> */
+#define	CFG_MADDR_LO_VAL_4_BASE				0
+
+/*	CFG_IF				0x0118	Interface Type Register (PMD Type and
+ *								Connector Type)
+ */
+#define	CFG_IF_PMD_MSK			SHIFT8(0xffU)	/* PMD */
+#define	CFG_IF_PMD_BASE			8
+#define	CFG_IF_CONN_MSK			SHIFT0(0xffU)	/* Connector */
+#define	CFG_IF_CONN_BASE		0
+
+/*	CFG_CREV			0x011A	Chip Revision Register */
+#define	CFG_CREV_MSK				SHIFT4(0xfU)	/* Chip Revision */
+#define	CFG_CREV_BASE				4
+#define	CFG_CREV_HID_ID_MSK			SHIFT0(0xfU)	/* Hidden ID */
+#define	CFG_CREV_HID_ID_BASE		0
+
+/*	CFG_CID				0x011B	Chip ID Register */
+#define	CFG_CID_MSK			SHIFT0(0xffU)	/* Chip ID */
+#define	CFG_CID_BASE		0
+
+/*	CFG_CGATE			0x011C	Clock Gating Register */
+/*		Bit(s) CFG_CGATE_RSRV_15 reserved */
+/*		Bit(s) CFG_CGATE_RSRV_14_12 reserved */
+/*		Bit(s) CFG_CGATE_RSRV_11 reserved */
+#define	CFG_CGATE_DIS_MAC			BIT_10S			/* Disable PHY/MAC Link */
+#define	CFG_CGATE_CIS_CORE			BIT_9S			/* Disable core_clk Link */
+#define	CFG_CGATE_DIS_PCI			BIT_8S			/* Disable pci_clk Link */
+/*		Bit(s) CFG_CGATE_RSRV_7_0 reserved */
+
+/*	CFG_AIR2			0x011E	Application Information Register 2 */
+/*		Bit(s) CFG_AIR2_RSRV_7_0 reserved */
+
+/*	CFG_AIR1			0x011F	Application Information Register 1 */
+/*		Bit(s) CFG_AIR1_RSRV_7_0 reserved */
+
+/*	CFG_CDIV			0x0120	Clock Divider Register */
+/*		Bit(s) CFG_CDIV_RSRV_31_24 reserved */
+#define	CFG_CDIV_MSK					SHIFT16(0xff)	/* Clock Div Value */
+#define	CFG_CDIV_BASE					16
+/*		Bit(s) CFG_CDIV_RSRV_15_2 reserved */
+#define	CFG_CDIV_ENA					BIT_1			/* Clock Div Enable */
+#define	CFG_CDIV_DIS					BIT_0			/* Clock Div Disable */
+
+/*	IRQ_TIM_INIT		0x0130	Timer Init Value Register */
+#define	IRQ_TIM_INIT_MSK		SHIFT0(0xffffffff)	/* Timer Init Value */
+#define	IRQ_TIM_INIT_BASE		0
+
+/*	IRQ_TIM_CNT			0x0134	Timer Register */
+#define	IRQ_TIM_CNT_MSK			SHIFT0(0xffffffff)	/* Timer */
+#define	IRQ_TIM_CNT_BASE		0
+
+/*	IRQ_TIM_TCTRL		0x0138	Timer Control/Test Register */
+/*		Bit(s) IRQ_TIM_TCTRL_RSRV_31_16 reserved */
+/*		Bit(s) IRQ_TIM_TCTRL_RSRV_15_11 reserved */
+#define	IRQ_TIM_TCTRL_ON					BIT_10			/* Timer Test On */
+#define	IRQ_TIM_TCTRL_OFF					BIT_9			/* Timer Test Off */
+#define	IRQ_TIM_TCTRL_STEP					BIT_8			/* Timer Step */
+/*		Bit(s) IRQ_TIM_TCTRL_RSRV_7_3 reserved */
+#define	IRQ_TIM_TCTRL_STRT					BIT_2			/* Timer Start */
+#define	IRQ_TIM_TCTRL_STOP					BIT_1			/* Timer Stop */
+#define	IRQ_TIM_TCTRL_CLR_IRQ				BIT_0			/* Timer Clear IRQ */
+
+/*	MOD_TIM_INIT		0x0140	IRQ Moderation Timer Init Value Register */
+/* IRQ Moderation Timer Init Value */
+#define	MOD_TIM_INIT_MSK		SHIFT0(0xffffffff)	
+#define	MOD_TIM_INIT_BASE		0
+
+/*	MOD_TIM_CNT			0x0144	IRQ Moderation Timer Register */
+#define	MOD_TIM_CNT_MSK			SHIFT0(0xffffffff)	/* IRQ Moderation Timer */
+#define	MOD_TIM_CNT_BASE		0
+
+/*	MOD_TIM_TCTRL		0x0148	IRQ Moderation Timer Control/Test Register */
+/*		Bit(s) MOD_TIM_TCTRL_RSRV_31_16 reserved */
+/*		Bit(s) MOD_TIM_TCTRL_RSRV_15_11 reserved */
+#define	MOD_TIM_TCTRL_ON					BIT_10			/* IM Timer Test On */
+#define	MOD_TIM_TCTRL_OFF					BIT_9			/* IM Timer Test Off */
+#define	MOD_TIM_TCTRL_STEP					BIT_8			/* IM Timer Step */
+/*		Bit(s) MOD_TIM_TCTRL_RSRV_7_3 reserved */
+#define	MOD_TIM_TCTRL_STRT					BIT_2			/* IM Timer Start */
+#define	MOD_TIM_TCTRL_STOP					BIT_1			/* IM Timer Stop */
+/*		Bit(s) MOD_TIM_TCTRL_RSRV_0 reserved */
+
+/*	MOD_TIM_MSK			0x014C	Interrupt Moderation Mask Register */
+/* En Mod IRQ xxx */
+#define	MOD_TIM_MSK_EN_MOD_IRQ_XXX_MSK			SHIFT0(0xffffffff)	
+#define	MOD_TIM_BASE_EN_MOD_IRQ_XXX_BASE		0
+
+/*	MOD_TIM_MSK_HW		0x0150	Interrupt Hardware Error Moderation Mask
+ *								Register
+ */
+/* En Mod IRQ xxx */
+#define	MOD_TIM_MSK_HW_EN_MOD_IRQ_XXX_MSK		SHIFT0(0xffffffff)	
+#define	MOD_TIM_BASE_HW_EN_MOD_IRQ_XXX_BASE		0
+
+/*	GLB_TCTRL			0x0158	Test Control Register 1 */
+#define	GLB_TCTRL_BMU_TX_FIFO_RTC			BIT_31	/* BMU TX FIFO RTC */
+#define	GLB_TCTRL_BMU_TX_FIFO_WTC			BIT_30	/* BMU TX FIFO WTC */
+#define	GLB_TCTRL_ASF_FIFO_RTC				BIT_29	/* ASF FIFO RTC */
+#define	GLB_TCTRL_ASF_FIFO_WTC				BIT_28	/* ASF FIFO WTC */
+/* Yukon Fe+ */
+#define	GLB_TCTRL_PWR_BDGT_FIFO_RTC			BIT_29	/* PWR_BDGT FIFO RTC */
+#define	GLB_TCTRL_PWR_BDGT_FIFO_WTC			BIT_28	/* PWR_BDGT FIFO WTC */
+/* Yukon Fe+ end */
+#define	GLB_TCTRL_PCIE_MAC_TX_FIFO_RTC		BIT_27	/* PCIE MAC Tx FIFO RTC */
+#define	GLB_TCTRL_PCIE_MAC_TX_FIFO_WTC		BIT_26	/* PCIE MAC Tx FIFO WTC */
+#define	GLB_TCTRL_PCIE_MAC_RX_FIFO_RTC		BIT_25	/* PCIE MAC Rx FIFO RTC */
+#define	GLB_TCTRL_PCIE_MAC_RX_FIFO_WTC		BIT_24	/* PCIE MAC Rx FIFO WTC */
+#define	GLB_TCTRL_PEX_TL_RX_FIFO_RTC		BIT_23	/* Pex Tl Rx FIFO RTC */
+#define	GLB_TCTRL_PEX_TL_RX_FIFO_WTC		BIT_22	/* Pex Tl Rx FIFO WTC */
+#define	GLB_TCTRL_PEX_TL_TX_FIFO_RTC		BIT_21	/* Pex Tl Tx FIFO RTC */
+#define	GLB_TCTRL_PEX_TL_TX_FIFO_WTC		BIT_20	/* Pex Tl Tx FIFO WTC */
+#define	GLB_TCTRL_WOL_RAM_RTC				BIT_19	/* WOL RAM RTC */
+#define	GLB_TCTRL_WOL_RAM_WTC				BIT_18	/* WOL RAM WTC */
+#define	GLB_TCTRL_RMON_RAM_RTC				BIT_17	/* RMON RAM RTC */
+#define	GLB_TCTRL_RMON_RAM_WTC				BIT_16	/* RMON RAM WTC */
+#define	GLB_TCTRL_PFU_STAT_RTC				BIT_15	/* PFU Status RTC */
+#define	GLB_TCTRL_PFU_STAT_WTC				BIT_14	/* PFU Status WTC */
+#define	GLB_TCTRL_PFU_AQ_FIFO_RTC			BIT_13	/* PFU Aq FIFO RTC */
+#define	GLB_TCTRL_PFU_AQ_FIFO_WTC			BIT_12	/* PFU Aq FIFO WTC */
+#define	GLB_TCTRL_PFU_RQ_FIFO_RTC			BIT_11	/* PFU Rq FIFO RTC */
+#define	GLB_TCTRL_PFU_RQ_FIFO_WTC			BIT_10	/* PFU Rq FIFO WTC */
+#define	GLB_TCTRL_MAC_RX_FIFO_RTC			BIT_9	/* MAC Rx FIFO RTC */
+/*		Bit(s) GLB_TCTRL_RSRV_8 reserved */
+/*		Bit(s) GLB_TCTRL_RSRV_7 reserved */
+#define	GLB_TCTRL_MAC_RX_FIFO_WTC			BIT_6	/* MAC Rx FIFO WTC */
+/*		Bit(s) GLB_TCTRL_RSRV_5 reserved */
+#define	GLB_TCTRL_MAC_TX_FIFO_RTC			BIT_4	/* MAC Tx FIFO RTC */
+/*		Bit(s) GLB_TCTRL_RSRV_3 reserved */
+#define	GLB_TCTRL_MAC_TX_FIFO_WTC			BIT_2	/* MAC Tx FIFO WTC */
+#define	GLB_TCTRL_EN_CFG_WR_ON				BIT_1	/* En Config Write On */
+#define	GLB_TCTRL_EN_CFG_WR_OFF				BIT_0	/* En Config Write Off */
+
+/*	GLB_GPIO			0x015C	General Purpose I/O Register */
+#define	GLB_GPIO_CLK_DEB_ENA			BIT_31			/* Clock Debug Enable */
+/*		Bit(s) GLB_GPIO_RSRV_30 reserved */
+#define	GLB_GPIO_CLK_DBG_MSK			SHIFT26(0xf)	/* Clock Debug */
+#define	GLB_GPIO_CLK_DBG_BASE			26
+/*		Bit(s) GLB_GPIO_RSRV_25_16 reserved */
+/* Disable Internal Reset After D3 to D0 */
+#define	GLB_GPIO_INT_RST_D3_DIS			BIT_15			
+#define	GLB_GPIO_LED_PAD_SPEED_UP		BIT_14			/* LED PAD Speed Up */
+#define	GLB_GPIO_STAT_RACE_DIS			BIT_13			/* Status Race Enable */
+#define	GLB_GPIO_TEST_SEL_MSK			SHIFT11(0x3)	/* Testmode Select */
+#define	GLB_GPIO_TEST_SEL_BASE			11
+#define	GLB_GPIO_RAND_ENA				BIT_10			/* Random Enable */
+#define	GLB_GPIO_RAND_BIT_1				BIT_9			/* Random Bit 1 */
+/*		Bit(s) GLB_GPIO_RSRV_8_0 reserved */
+
+/*	TWSI_CTRL			0x0160	TWSI (HW) Control Register */
+#define	TWSI_CTRL_FLAG				BIT_31			/* Flag */
+#define	TWSI_CTRL_ADDR_MSK			SHIFT16(0x7fff)	/* TWSI Address */
+#define	TWSI_CTRL_ADDR_BASE			BIT_16
+#define	TWSI_CTRL_DEVSEL_MSK		SHIFT9(0x7f)	/* TWSI Devsel */
+#define	TWSI_CTRL_DEVSEL_BASE		BIT_9
+/*		Bit(s) TWSI_CTRL_RSRV_3_0 reserved */
+#define	TWSI_CTRL_BURST_ENA			BIT_4			/* TWSI Burst */
+#define	TWSI_CTRL_DEVSIZE_MSK		SHIFT1(0x7)		/* TWSI Device Size */
+#define	TWSI_CTRL_DEVSIZE_BASE		BIT_1
+#define	TWSI_CTRL_STOP				BIT_0			/* TWSI Stop */
+
+/*	TWSI_DATA			0x0164	TWSI (HW) Data Register */
+#define	TWSI_DATA_MSK		SHIFT0(0xffffffff)	/* TWSI Data */
+#define	TWSI_DATA_BASE		BIT_0
+
+/*	TWSI_IRQ			0x0168	TWSI (HW) IRQ Register */
+/*		Bit(s) TWSI_IRQ_RSRV_30_0 reserved */
+#define	TWSI_IRQ_CLR_IRQ			BIT_0				/* Clear IRQ TWSI */
+
+/*	TWSI_SW				0x016C	TWSI (SW) Register */
+/*		Bit(s) TWSI_SW_RSRV_28_0 reserved */
+#define	TWSI_SW_DIR					BIT_2				/* TWSI Data Dir */
+#define	TWSI_SW_DATA				BIT_1				/* TWSI Data */
+#define	TWSI_SW_CLK					BIT_0				/* TWSI Clock */
+
+/*	PCIE_PHY			0x0170	PCI Express PHY Address Register */
+#define	PCIE_PHY_RW				BIT_31			/* PEX PHY Access Mode */
+#define	PCIE_PHY_REGFILE		BIT_30			/* PEX PHY regfile */
+#define	PCIE_PHY_ADDR_MSK		SHIFT16(0x3fff)	/* PEX PHY Address */
+#define	PCIE_PHY_ADDR_BASE		16
+#define	PCIE_PHY_DATA_MSK		SHIFT0(0xffff)	/* PEX PHY Data */
+#define	PCIE_PHY_DATA_BASE		0
+
+/*	RAM_ADDR			0x0180	RAM Address Register */
+#define	RAM_ADDR_SEL_MSK			SHIFT30(0x3)	/* RAM Select */
+#define	RAM_ADDR_SEL_BASE			30
+#define	RAM_ADDR_ADDR_MUX			BIT_29			/* RAM Address Mux */
+/*		Bit(s) RAM_ADDR_RSRV_28_9 reserved */
+#define	RAM_ADDR_MSK				SHIFT0(0x1ff)	/* RAM Address */
+#define	RAM_ADDR_BASE				0
+
+/*	RAM_DATA_LO			0x0184	Data Port/Lower Dword Register */
+#define	RAM_DATA_LO_MSK			SHIFT0(0xffffffff)	/* Data Port/lower dword */
+#define	RAM_DATA_LO_BASE		0
+
+/*	RAM_DATA_HI			0x0188	Data Port/Upper Dword Register */
+#define	RAM_DATA_HI_MSK			SHIFT0(0xffffffff)	/* Data Port/upper dword */
+#define	RAM_DATA_HI_BASE		BIT_0
+
+/*	ASF_TO				0x0190	Timeout Register */
+#define	ASF_TO_ASF_TO3_MSK		SHIFT24(0xff)	/* Timeout Value 3 */
+#define	ASF_TO_ASF_TO3_BASE		BIT_24
+#define	ASF_TO_ASF_TO2_MSK		SHIFT16(0xff)	/* Timeout Value 2 */
+#define	ASF_TO_ASF_TO2_BASE		BIT_16
+#define	ASF_TO_ASF_TO1_MSK		SHIFT8(0xff)	/* Timeout Value 1 */
+#define	ASF_TO_ASF_TO1_BASE		BIT_8
+#define	ASF_TO_ASF_TO0_MSK		SHIFT0(0xff)	/* Timeout Value 0 */
+#define	ASF_TO_ASF_TO0_BASE		BIT_0
+
+/*	ASF_CTRL			0x01A0	FIFO Interface Control */
+/*		Bit(s) ASF_CTRL_RSRV_29_0 reserved */
+#define	ASF_CTRL_ASF_ENA			BIT_1				/* Reset Clear */
+#define	ASF_CTRL_ASF_RST			BIT_0				/* Reset Set */
+
+/*	RSS_KEY0			0x0220	RSS Key 0 Register */
+#define	RSS_KEY0_MSK		SHIFT0(0xffffffff)	/* RSS Key0 */
+#define	RSS_KEY0_BASE		0
+
+/*	RSS_KEY1			0x0224	RSS Key 1 Register */
+#define	RSS_KEY1_MSK		SHIFT0(0xffffffff)	/* RSS Key1 */
+#define	RSS_KEY1_BASE		0
+
+/*	RSS_KEY2			0x0228	RSS Key 2 Register */
+#define	RSS_KEY2_MSK		SHIFT0(0xffffffff)	/* RSS Key2 */
+#define	RSS_KEY2_BASE		0
+
+/*	RSS_KEY3			0x022C	RSS Key 3 Register */
+#define	RSS_KEY3_MSK		SHIFT0(0xffffffff)	/* RSS Key3 */
+#define	RSS_KEY3_BASE		0
+
+/*	RSS_KEY4			0x0230	RSS Key 4 Register */
+#define	RSS_KEY4_MSK		SHIFT0(0xffffffff)	/* RSS Key4 */
+#define	RSS_KEY4_BASE		0
+
+/*	RSS_KEY5			0x0234	RSS Key 5 Register */
+#define	RSS_KEY5_MSK		SHIFT0(0xffffffff)	/* RSS Key5 */
+#define	RSS_KEY5_BASE		0
+
+/*	RSS_KEY6			0x0238	RSS Key 6 Register */
+#define	RSS_KEY6_MSK		SHIFT0(0xffffffff)	/* RSS Key6 */
+#define	RSS_KEY6_BASE		0
+
+/*	RSS_KEY7			0x023C	RSS Key 7 Register */
+#define	RSS_KEY7_MSK		SHIFT0(0xffffffff)	/* RSS Key7 */
+#define	RSS_KEY7_BASE		0
+
+/*	RSS_KEY8			0x0240	RSS Key 8 Register */
+#define	RSS_KEY8_MSK		SHIFT0(0xffffffff)	/* RSS Key8 */
+#define	RSS_KEY8_BASE		0
+
+/*	RSS_KEY9			0x0244	RSS Key 9 Register */
+#define	RSS_KEY9_MSK		SHIFT0(0xffffffff)	/* RSS Key9 */
+#define	RSS_KEY9_BASE		0
+
+/*	RSS_CFG				0x0248	RSS Configuration Register */
+/*		Bit(s) RSS_CFG_RSRV_31_6 reserved */
+/* NDIS_HASH_TCP_IPV6_EX Control */
+#define	RSS_CFG_NDIS_HASH_TCP_IPV6_EX_CTRL		BIT_5				
+/* NDIS_HASH_IPV6_EX Control */
+#define	RSS_CFG_NDIS_HASH_IPV6_EX_CTRL			BIT_4				
+/* NDIS_HASH_TCP_IPV6 Control */
+#define	RSS_CFG_NDIS_HASH_TCP_IPV6_CTRL			BIT_3				
+/* NDIS_HASH_IPV6 Control */
+#define	RSS_CFG_NDIS_HASH_IPV6_CTRL				BIT_2				
+/* NDIS_HASH_TCP_IPV4 Control */
+#define	RSS_CFG_NDIS_HASH_TCP_IPV4_CTRL			BIT_1				
+/* NDIS_HASH_IPV4 Control */
+#define	RSS_CFG_NDIS_HASH_IPV4_CTRL				BIT_0				
+
+/*	RBMU_DESCR			0x0400	Current Receive Descriptor Register */
+#define	RBMU_DESCR_CTRL_MSK				SHIFT16(0xffff)	/* Receive Buffer Control */
+#define	RBMU_DESCR_CTRL_BASE			16
+/* Receive Buffer Byte Count */
+#define	RBMU_DESCR_BYTE_CNT_MSK			SHIFT0(0xffff)	
+#define	RBMU_DESCR_BYTE_CNT_BASE		0
+
+/*	RBMU_HASH			0x0404	RSS Hash Checksum Register */
+#define	RBMU_HASH_MSK		SHIFT0(0xffffffff)	/* RSS Hash Checksum */
+#define	RBMU_HASH_BASE		0
+
+/*	RBMU_ADDR_HI		0x0408	Receive Buffer Address Lo Register */
+#define	RBMU_ADDR_HI_MSK		SHIFT0(0xffffffff)	/* Receive Buffer Address Lo */
+#define	RBMU_ADDR_HI_BASE		0
+
+/*	RBMU_ADDR_LO		0x040C	Receive Buffer Address Hi Register */
+#define	RBMU_ADDR_LO_MSK		SHIFT0(0xffffffff)	/* Receive Buffer Address Hi */
+#define	RBMU_ADDR_LO_BASE		0
+
+/*	RBMU_RFSW			0x0410	Receive Buffer Status Word Register */
+#define	RBMU_RFSW_MSK		SHIFT0(0xffffffff)	/* RFSW */
+#define	RBMU_RFSW_BASE		0
+
+/*	RBMU_TSP			0x0414	Receive Timestamp Register */
+#define	RBMU_TSP_MSK		SHIFT0(0xffffffff)	/* Timestamp */
+#define	RBMU_TSP_BASE		0
+
+/*	RBMU_VLAN			0x0420	VLAN Tag Register */
+/*		Bit(s) RBMU_VLAN_RSRV_31_16 reserved */
+#define	RBMU_VLAN_MSK					SHIFT0(0xffff)	/* VLAN Tag */
+#define	RBMU_VLAN_BASE					0
+
+/*	RBMU_DONE_IDX		0x0424	Receive Done Index Register */
+/*		Bit(s) RBMU_DONE_IDX_RSRV_31_12 reserved */
+#define	RBMU_DONE_IDX_MSK					SHIFT0(0xfff)		/* Done Index */
+#define	RBMU_DONE_IDX_BASE					0
+
+/*	RBMU_REQ_ADDR_LO	0x0428	Receive Request Address, Lower Register */
+#define	RBMU_REQ_ADDR_LO_MSK		SHIFT0(0xffffffff)	/* Request Addr Lo */
+#define	RBMU_REQ_ADDR_LO_BASE		0
+
+/*	RBMU_REQ_ADDR_HI	0x042C	Receive Request Address, Upper Register */
+#define	RBMU_REQ_ADDR_HI_MSK		SHIFT0(0xffffffff)	/* Request Addr Hi */
+#define	RBMU_REQ_ADDR_HI_BASE		0
+
+/*	RBMU_REQ_CNT		0x0430	Receive Request Byte Count Register */
+/*		Bit(s) RBMU_REQ_CNT_RSRV_31_11 reserved */
+/* Request Byte Count */
+#define	RBMU_REQ_CNT_MSK					SHIFT0(0x7ff)		
+#define	RBMU_REQ_CNT_BASE					0
+
+/*	RBMU_CSR			0x0434	Receive BMU Control/Status Register */
+#define	RBMU_CSR_IDLE					BIT_31			/* BMU Idle */
+#define	RBMU_CSR_TCPUDP_CSUMOK			BIT_30			/* TCP/UDP Checksum OK */
+#define	RBMU_CSR_UDP_PKT				BIT_29			/* UDP Pkt */
+#define	RBMU_CSR_FRAG_PKT				BIT_28			/* Fragment Pkt */
+#define	RBMU_CSR_IPV4_CSUMOK			BIT_27			/* IPv4 Checksum OK */
+#define	RBMU_CSR_IPV6_PKT				BIT_26			/* IPv6 Pkt */
+#define	RBMU_CSR_TCP_PKT				BIT_25			/* TCP Pkt */
+#define	RBMU_CSR_IPV4_PKT				BIT_24			/* IPv4 Pkt */
+/*		Bit(s) RBMU_CSR_RSRV_23_20 reserved */
+/* RX Core CLock Gating Enable */
+#define	RBMU_CSR_GCORECLK_ENA			BIT_19			
+/* RX Core Clock Gating Disable */
+#define	RBMU_CSR_GCORECLK_DIS			BIT_18			
+#define	RBMU_CSR_MACSEC_LE_ENA			BIT_17			/* MACSec LE Enable */
+#define	RBMU_CSR_MACSEC_LE_DIS			BIT_16			/* MACSec LE Disable */
+#define	RBMU_CSR_RSS_ENA				BIT_15			/* RSS Hash Enable */
+#define	RBMU_CSR_RSS_DIS				BIT_14			/* RSS Hash Disable */
+#define	RBMU_CSR_CSUM_ENA				BIT_13			/* RX Checksum Enable */
+#define	RBMU_CSR_CSUM_DIS				BIT_12			/* RX Checksum Disable */
+#define	RBMU_CSR_CLR_IRQ_PAR			BIT_11			/* Clear IRQ Parity */
+#define	RBMU_CSR_CLR_IRQ_CHK			BIT_10			/* Clear IRQ Check */
+#define	RBMU_CSR_STOP_RBMU				BIT_9			/* Stop Rx BMU */
+#define	RBMU_CSR_STRT_RBMU				BIT_8			/* Start Rx BMU */
+#define	RBMU_CSR_FIFO_OP_ON				BIT_7			/* FIFO Operational On */
+#define	RBMU_CSR_FIFO_OP_OFF			BIT_6			/* FIFO Operational Off */
+#define	RBMU_CSR_FIFO_ENA				BIT_5			/* FIFO Enable */
+#define	RBMU_CSR_FIFO_RST				BIT_4			/* FIFO Reset */
+#define	RBMU_CSR_RBMU_OP_ON				BIT_3			/* BMU Operational On */
+#define	RBMU_CSR_RBMU_OP_OFF			BIT_2			/* BMU Operational Off */
+#define	RBMU_CSR_RBMU_ENA				BIT_1			/* BMU Enable */
+#define	RBMU_CSR_RBMU_RST				BIT_0			/* BMU Reset */
+
+/*	RBMU_TEST			0x0438	Receive BMU Test Register */
+/*		Bit(s) RBMU_TEST_RSRV_31_25 reserved */
+/* MAC Rx RAM Read Control */
+#define	RBMU_TEST_MAC_RX_RAM_RD_CTRL		BIT_24			
+/*		Bit(s) RBMU_TEST_RSRV_23_8 reserved */
+/*		Bit(s) RBMU_TEST_RSRV_7 reserved */
+/* Testmode Req Nbytes/Addr On */
+#define	RBMU_TEST_TEST_REQ_NB_ON			BIT_6			
+/* Testmode Req Nbytes/Addr Off */
+#define	RBMU_TEST_TEST_REQ_NB_OFF			BIT_5			
+/* Teststep Req Nbytes/Addr */
+#define	RBMU_TEST_TESTSTEP_REQ_NB			BIT_4			
+/*		Bit(s) RBMU_TEST_RSRV_3 reserved */
+/* Testmode Done Index On */
+#define	RBMU_TEST_TEST_DONE_IDX_ON			BIT_2			
+/* Testmode Done Index Off */
+#define	RBMU_TEST_TEST_DONE_IDX_OFF			BIT_1			
+#define	RBMU_TEST_TESTSTEP_DONE_IDX			BIT_0			/* Teststep Done Index */
+
+/*	RBMU_SM				0x043C	Receive BMU State Machine Register */
+#define	RBMU_SM_MSK			SHIFT0(0xffffffff)	/* BMU State machine */
+#define	RBMU_SM_BASE		0
+
+/*	RBMU_FIFO_WM		0x0440	Receive FIFO Watermark Register */
+/*		Bit(s) RBMU_FIFO_WM_RSRV_15_11 reserved */
+#define	RBMU_FIFO_WM_MSK					SHIFT0(0x7ffU)	/* FIFO Watermark */
+#define	RBMU_FIFO_WM_BASE					0
+
+/*	RBMU_FIFO_AL		0x0442	Receive FIFO Alignment Register */
+/*		Bit(s) RBMU_FIFO_AL_RSRV_15_7 reserved */
+#define	RBMU_FIFO_AL_MUX_MSK			SHIFT4(0x7U)	/* MUX */
+#define	RBMU_FIFO_AL_MUX_BASE			4
+/*		Bit(s) RBMU_FIFO_AL_RSRV_3 reserved */
+#define	RBMU_FIFO_AL_VRAM_MSK			SHIFT0(0x7U)	/* VRAM */
+#define	RBMU_FIFO_AL_VRAM_BASE			0
+
+/*	RPFU_CTRL			0x0450	Receive Prefetch Control Register */
+/*		Bit(s) RPFU_CTRL_RSRV_31_15 reserved */
+/* Master Request Loopback Test On */
+#define	RPFU_CTRL_MST_REQ_LPBK_ON			BIT_14				
+/* Master Request Loopback Test Off */
+#define	RPFU_CTRL_MST_REQ_LPBK_OFF			BIT_13				
+/* Master Request Loopback Step */
+#define	RPFU_CTRL_MST_REQ_LPBK_STEP			BIT_12				
+/*		Bit(s) RPFU_CTRL_RSRV_11 reserved */
+/* FIFO Read Pointer Test On */
+#define	RPFU_CTRL_FIFO_RPTR_TEST_ON			BIT_10				
+/* FIFO Read Pointer Test Off */
+#define	RPFU_CTRL_FIFO_RPTR_TEST_OFF		BIT_9				
+/* FIFO Read Pointer Step */
+#define	RPFU_CTRL_FIFO_RPTR_TEST_STEP		BIT_8				
+/*		Bit(s) RPFU_CTRL_RSRV_7 reserved */
+/* FIFO Write Pointer Test On */
+#define	RPFU_CTRL_FIFO_WPTR_TEST_ON			BIT_6				
+/* FIFO Write Pointer Test Off */
+#define	RPFU_CTRL_FIFO_WPTR_TEST_OFF		BIT_5				
+/* FIFO Write Pointer Step */
+#define	RPFU_CTRL_FIFO_WPTR_TEST_STEP		BIT_4				
+#define	RPFU_CTRL_OP_ON						BIT_3				/* Operational On */
+#define	RPFU_CTRL_OP_OFF					BIT_2				/* Operational Off */
+#define	RPFU_CTRL_PFU_RST_CLR				BIT_1				/* PFU Reset Clear */
+#define	RPFU_CTRL_PFU_RST_SET				BIT_0				/* PFU Reset Set */
+
+/*	RPFU_LAST_IDX		0x0454	Receive PFU List Last Index Register */
+/*		Bit(s) RPFU_LAST_IDX_RSRV_31_12 reserved */
+#define	RPFU_LAST_IDX_MSK					SHIFT2(0x3ff)		/* List Last Index */
+#define	RPFU_LAST_IDX_BASE					2
+/* List Last Index Fix */
+#define	RPFU_LAST_IDX_VAL_FIX_MSK			SHIFT0(0x3)			
+#define	RPFU_LAST_IDX_VAL_FIX_BASE			0
+
+/*	RPFU_LADR_LO		0x0458	Receive PFU List Start Address Low Register */
+/* List Start Address Low */
+#define	RPFU_LADR_LO_MSK				SHIFT5(0x7ffffff)	
+#define	RPFU_LADR_LO_BASE				5
+/* List Start Address Low Fix */
+#define	RPFU_LADR_LO_VAL_FIX_MSK		SHIFT0(0x1f)		
+#define	RPFU_LADR_LO_VAL_FIX_BASE		0
+
+/*	RPFU_LADR_HI		0x045C	Receive PFU List Start Address High Register */
+#define	RPFU_LADR_HI_MSK		SHIFT0(0xffffffff)	/* List Start Address High */
+#define	RPFU_LADR_HI_BASE		0
+
+/*	RPFU_GET_IDX		0x0460	Receive PFU Get Index Register */
+/*		Bit(s) RPFU_GET_IDX_RSRV_31_12 reserved */
+#define	RPFU_GET_IDX_MSK					SHIFT0(0xfff)		/* Get Index */
+#define	RPFU_GET_IDX_BASE					0
+
+/*	RPFU_PUT_IDX		0x0464	Receive PFU Put Index Register */
+/*		Bit(s) RPFU_PUT_IDX_RSRV_31_12 reserved */
+#define	RPFU_PUT_IDX_MSK					SHIFT0(0xfff)		/* Put Index */
+#define	RPFU_PUT_IDX_BASE					0
+
+/*	RPFU_FIFO_WR		0x0470	Receive PFU FIFO RAM Write and Write Shadow
+ *								Pointer Register
+ */
+/*		Bit(s) RPFU_FIFO_WR_RSRV_31_24 reserved */
+/* FIFO Write Shadow Pointer */
+#define	RPFU_FIFO_WR_WSPTR_MSK				SHIFT16(0xff)	
+#define	RPFU_FIFO_WR_WSPTR_BASE				16
+/*		Bit(s) RPFU_FIFO_WR_RSRV_15_5 reserved */
+#define	RPFU_FIFO_WR_WPTR_MSK				SHIFT0(0x1f)	/* FIFO Write Pointer */
+#define	RPFU_FIFO_WR_WPTR_BASE				0
+
+/*	RPFU_FIFO_RD		0x0474	Receive PFU FIFO RAM Read Pointer Register */
+/*		Bit(s) RPFU_FIFO_RD_RSRV_31_5 reserved */
+#define	RPFU_FIFO_RD_RPTR_MSK			SHIFT0(0x1f)		/* FIFO Read Pointer */
+#define	RPFU_FIFO_RD_RPTR_BASE			0
+
+/*	RPFU_FIFO_REQ_NB	0x0478	Receive PFU Master Request nbytes Register */
+/*		Bit(s) RPFU_FIFO_REQ_NB_RSRV_31_27 reserved */
+/* Master Request nBytes */
+#define	RPFU_FIFO_REQ_NB_MR_MSK					SHIFT16(0x7ff)	
+#define	RPFU_FIFO_REQ_NB_MR_BASE				16
+/*		Bit(s) RPFU_FIFO_REQ_NB_RSRV_15_8 reserved */
+#define	RPFU_FIFO_REQ_NB_WM_MSK					SHIFT0(0xff)	/* FIFO Watermark */
+#define	RPFU_FIFO_REQ_NB_WM_BASE				0
+
+/*	RPFU_FIFO_LEV		0x047C	Receive PFU FIFO Shadow Level Register */
+/*		Bit(s) RPFU_FIFO_LEV_RSRV_31_24 reserved */
+#define	RPFU_FIFO_LEV_SLEV_MSK				SHIFT16(0xff)	/* FIFO Shadow level */
+#define	RPFU_FIFO_LEV_SLEV_BASE				16
+/*		Bit(s) RPFU_FIFO_LEV_RSRV_15_5 reserved */
+#define	RPFU_FIFO_LEV_MSK					SHIFT0(0x1f)	/* FIFO level */
+#define	RPFU_FIFO_LEV_BASE					0
+
+/*	TBMU_DESC1			0x0680	Current Transmit Descriptor Register 1 */
+#define	TBMU_DESC1_MSK		SHIFT16(0xffff)	/* Transmit Buffer Control */
+#define	TBMU_DESC1_BASE		16
+
+/*	TBMU_DESC2			0x0684	Current Transmit Descriptor Register 2 */
+#define	TBMU_DESC2_MSK		SHIFT0(0xffffU)	/* Transmit Buffer Byte Count */
+#define	TBMU_DESC2_BASE		0
+
+/*	TBMU_ADDR_LO		0x0688	Transmit Buffer Address Lower Register */
+#define	TBMU_ADDR_LO_MSK		SHIFT0(0xffffffff)	/* Transmit Buffer Address Lo */
+#define	TBMU_ADDR_LO_BASE		0
+
+/*	TBMU_ADDR_HI		0x068C	Transmit Buffer Address Upper Register */
+#define	TBMU_ADDR_HI_MSK		SHIFT0(0xffffffff)	/* Transmit Buffer Address Hi */
+#define	TBMU_ADDR_HI_BASE		0
+
+/*	TBMU_TFSW			0x0690	Transmit Buffer Status Word Register */
+#define	TBMU_TFSW_MSK		SHIFT0(0xffffffff)	/* TFSW */
+#define	TBMU_TFSW_BASE		0
+
+/*	TBMU_VLAN			0x06A0	Transmit VLAN Tag Register */
+/*		Bit(s) TBMU_VLAN_RSRV_31_16 reserved */
+#define	TBMU_VLAN_MSK					SHIFT0(0xffff)	/* VLAN Tag */
+#define	TBMU_VLAN_BASE					0
+
+/*	TBMU_DONE_IDX		0x06A4	Transmit Done Index Register */
+/*		Bit(s) TBMU_DONE_IDX_RSRV_31_12 reserved */
+#define	TBMU_DONE_IDX_MSK					SHIFT0(0xfff)		/* Done Index */
+#define	TBMU_DONE_IDX_BASE					0
+
+/*	TBMU_REQ_ADDR_LO	0x06A8	Transmit Request Address Lower Register */
+#define	TBMU_REQ_ADDR_LO_MSK		SHIFT0(0xffffffff)	/* Request Addr Lo */
+#define	TBMU_REQ_ADDR_LO_BASE		0
+
+/*	TBMU_REQ_ADDR_HI	0x06AC	Transmit Request Address Upper Register */
+#define	TBMU_REQ_ADDR_HI_MSK		SHIFT0(0xffffffff)	/* Request Addr Hi */
+#define	TBMU_REQ_ADDR_HI_BASE		0
+
+/*	TBMU_REQ_CNT		0x06B0	Transmit Request Byte Count Register */
+/*		Bit(s) TBMU_REQ_CNT_RSRV_31_11 reserved */
+/* Request Byte Count */
+#define	TBMU_REQ_CNT_MSK					SHIFT0(0x7ff)		
+#define	TBMU_REQ_CNT_BASE					0
+
+/*	TBMU_CSR			0x06B4	Transmit BMU Control/Status Register */
+#define	TBMU_CSR_IDLE						BIT_31			/* BMU Idle */
+/*		Bit(s) TBMU_CSR_RSRV_30_24 reserved */
+/* Tx path automatic clock gating enable */
+#define	TBMU_CSR_TX_GATE_ON					BIT_23			
+/* TX path automatic clock gating disable */
+#define	TBMU_CSR_TX_GATE_OFF				BIT_22			
+/* TX path automatic clock gating timeout */
+#define	TBMU_CSR_TX_GATE_TIMEOUT_MSK		SHIFT16(0x3f)	
+#define	TBMU_CSR_TX_GATE_TIMEOUT_BASE		16
+/*		Bit(s) TBMU_CSR_RSRV_15_14 reserved */
+/* IP ID Increment Enable */
+#define	TBMU_CSR_IP_ID_INCR_ENA				BIT_13			
+/* IP ID Increment Disable */
+#define	TBMU_CSR_IP_ID_INCR_DIS				BIT_12			
+#define	TBMU_CSR_CLR_IRQ_TCP				BIT_11			/* Clear IRQ TCP */
+#define	TBMU_CSR_CLR_IRQ_CHK				BIT_10			/* Clear IRQ Check */
+#define	TBMU_CSR_STOP_TBMU					BIT_9			/* Stop Tx BMU */
+#define	TBMU_CSR_STRT_TBMU					BIT_8			/* Start Tx BMU */
+#define	TBMU_CSR_FIFO_OP_ON					BIT_7			/* FIFO Operational On */
+#define	TBMU_CSR_FIFO_OP_OFF				BIT_6			/* FIFO Operational Off */
+#define	TBMU_CSR_FIFO_ENA					BIT_5			/* FIFO Enable */
+#define	TBMU_CSR_FIFO_RST					BIT_4			/* FIFO Reset */
+#define	TBMU_CSR_TBMU_OP_ON					BIT_3			/* BMU Operational On */
+#define	TBMU_CSR_TBMU_OP_OFF				BIT_2			/* BMU Operational Off */
+#define	TBMU_CSR_TBMU_ENA					BIT_1			/* BMU Enable */
+#define	TBMU_CSR_TBMU_RST					BIT_0			/* BMU Reset */
+
+/*	TBMU_TEST			0x06B8	Transmit BMU Test Register */
+/* BMU tx checksum auto calculation disable */
+#define	TBMU_TEST_BMU_TX_CHK_AUTO_OFF		BIT_31			
+/* BMU tx checksum auto calculation enable */
+#define	TBMU_TEST_BMU_TX_CHK_AUTO_ON		BIT_30			
+/*		Bit(s) TBMU_TEST_RSRV_29_23 reserved */
+/* Testmode Shadow Read Ptr On */
+#define	TBMU_TEST_TEST_RSPTR_ON				BIT_22			
+/* Testmode Shadow Read Ptr Off */
+#define	TBMU_TEST_TEST_RSPTR_OFF			BIT_21			
+/* Teststep Shadow Read Ptr */
+#define	TBMU_TEST_TESTSTEP_RSPTR			BIT_20			
+/*		Bit(s) TBMU_TEST_RSRV_19 reserved */
+#define	TBMU_TEST_TEST_RPTR_ON				BIT_18			/* Testmode Read Ptr On */
+/* Testmode Read Ptr Off */
+#define	TBMU_TEST_TEST_RPTR_OFF				BIT_17			
+#define	TBMU_TEST_TESTSTEP_RPTR				BIT_16			/* Teststep Read Ptr */
+/*		Bit(s) TBMU_TEST_RSRV_15 reserved */
+/* Testmode Shadow Write Ptr On */
+#define	TBMU_TEST_TEST_WSPTR_ON				BIT_14			
+/* Testmode Shadow Write Ptr Off */
+#define	TBMU_TEST_TEST_WSPTR_OFF			BIT_13			
+/* Teststep Shadow Write Ptr */
+#define	TBMU_TEST_TESTSTEP_WSPTR			BIT_12			
+/*		Bit(s) TBMU_TEST_RSRV_11 reserved */
+/* Testmode Write Ptr On */
+#define	TBMU_TEST_TEST_WPTR_ON				BIT_10			
+/* Testmode Write Ptr Off */
+#define	TBMU_TEST_TEST_WPTR_OFF				BIT_9			
+#define	TBMU_TEST_TESTSTEP_WPTR				BIT_8			/* Teststep Write Ptr */
+/*		Bit(s) TBMU_TEST_RSRV_7 reserved */
+/* Testmode Req Nbytes/Addr On */
+#define	TBMU_TEST_TEST_REQ_NB_ON			BIT_6			
+/* Testmode Req Nbytes/Addr Off */
+#define	TBMU_TEST_TEST_REQ_NB_OFF			BIT_5			
+/* Teststep Req Nbytes/Addr */
+#define	TBMU_TEST_TESTSTEP_REQ_NB			BIT_4			
+/*		Bit(s) TBMU_TEST_RSRV_3 reserved */
+/* Testmode Done Index On */
+#define	TBMU_TEST_TEST_DONE_IDX_ON			BIT_2			
+/* Testmode Done Index Off */
+#define	TBMU_TEST_TEST_DONE_IDX_OFF			BIT_1			
+#define	TBMU_TEST_TESTSTEP_DONE_IDX			BIT_0			/* Teststep Done Index */
+
+/*	TBMU_SM				0x06BC	Transmit BMU State Machine Register */
+#define	TBMU_SM_MSK			SHIFT0(0xffffffff)	/* BMU State machine */
+#define	TBMU_SM_BASE		0
+
+/*	TBMU_FIFO_WM		0x06C0	Transmit FIFO Watermark Register */
+/*		Bit(s) TBMU_FIFO_WM_RSRV_15_9 reserved */
+#define	TBMU_FIFO_WM_MSK				SHIFT3(0x3fU)	/* FIFO Watermark */
+#define	TBMU_FIFO_WM_BASE				3
+/*		Bit(s) TBMU_FIFO_WM_RSRV_2_0 reserved */
+
+/*	TBMU_FIFO_AL		0x06C2	Transmit FIFO Alignment Register */
+/*		Bit(s) TBMU_FIFO_AL_RSRV_15_7 reserved */
+#define	TBMU_FIFO_AL_MUX_MSK			SHIFT4(0x7U)	/* MUX */
+#define	TBMU_FIFO_AL_MUX_BASE			4
+/*		Bit(s) TBMU_FIFO_AL_RSRV_3 reserved */
+#define	TBMU_FIFO_AL_VRAM_MSK			SHIFT0(0x7U)	/* VRAM */
+#define	TBMU_FIFO_AL_VRAM_BASE			0
+
+/*	TBMU_FIFO_WSPTR		0x06C4	Transmit FIFO Write Shadow Pointer Register */
+/*		Bit(s) TBMU_FIFO_WSPTR_RSRV_15_9 reserved */
+/* FIFO Write Shadow Pointer */
+#define	TBMU_FIFO_WSPTR_MSK					SHIFT0(0x1ffU)	
+#define	TBMU_FIFO_WSPTR_BASE				0
+
+/*	TBMU_FIFO_WSLEV		0x06C6	Transmit FIFO Write Shadow Level Register */
+/*		Bit(s) TBMU_FIFO_WSLEV_RSRV_15_6 reserved */
+#define	TBMU_FIFO_WSLEV_MSK					SHIFT0(0x3fU)	/* FIFO Write Level */
+#define	TBMU_FIFO_WSLEV_BASE				0
+
+/*	TBMU_FIFO_WPTR		0x06C8	Transmit FIFO Write Pointer Register */
+/*		Bit(s) TBMU_FIFO_WPTR_RSRV_15_6 reserved */
+#define	TBMU_FIFO_WPTR_MSK					SHIFT0(0x3fU)	/* FIFO Write Pointer */
+#define	TBMU_FIFO_WPTR_BASE					0
+
+/*	TBMU_FIFO_WLEV		0x06CA	Transmit FIFO Write Level Register */
+/*		Bit(s) TBMU_FIFO_WLEV_RSRV_15_6 reserved */
+#define	TBMU_FIFO_WLEV_MSK					SHIFT0(0x3fU)	/* FIFO Write Level */
+#define	TBMU_FIFO_WLEV_BASE					0
+
+/*	TBMU_FIFO_RPTR		0x06CC	Transmit FIFO Read Pointer Register */
+/*		Bit(s) TBMU_FIFO_RPTR_RSRV_15_6 reserved */
+#define	TBMU_FIFO_RPTR_MSK					SHIFT0(0x3fU)	/* FIFO Read Pointer */
+#define	TBMU_FIFO_RPTR_BASE					0
+
+/*	TBMU_RLEV			0x06CE	Transmit FIFO Read Level Register */
+/*		Bit(s) TBMU_RLEV_RSRV_15_6 reserved */
+#define	TBMU_RLEV_MSK					SHIFT0(0x3fU)	/* FIFO Read Level */
+#define	TBMU_RLEV_BASE					0
+
+/*	TPFU_CTRL			0x06D0	Transmit Prefetch Control Register */
+/*		Bit(s) TPFU_CTRL_RSRV_31_15 reserved */
+/* Master Request Loopback Test On */
+#define	TPFU_CTRL_MST_REQ_LPBK_ON			BIT_14				
+/* Master Request Loopback Test Off */
+#define	TPFU_CTRL_MST_REQ_LPBK_OFF			BIT_13				
+/* Master Request Loopback Step */
+#define	TPFU_CTRL_MST_REQ_LPBK_STEP			BIT_12				
+/*		Bit(s) TPFU_CTRL_RSRV_11 reserved */
+/* FIFO Read Pointer Test On */
+#define	TPFU_CTRL_FIFO_RPTR_TEST_ON			BIT_10				
+/* FIFO Read Pointer Test Off */
+#define	TPFU_CTRL_FIFO_RPTR_TEST_OFF		BIT_9				
+/* FIFO Read Pointer Step */
+#define	TPFU_CTRL_FIFO_RPTR_TEST_STEP		BIT_8				
+/*		Bit(s) TPFU_CTRL_RSRV_7 reserved */
+/* FIFO Write Pointer Test On */
+#define	TPFU_CTRL_FIFO_WPTR_TEST_ON			BIT_6				
+/* FIFO Write Pointer Test Off */
+#define	TPFU_CTRL_FIFO_WPTR_TEST_OFF		BIT_5				
+/* FIFO Write Pointer Step */
+#define	TPFU_CTRL_FIFO_WPTR_TEST_STEP		BIT_4				
+#define	TPFU_CTRL_OP_ON						BIT_3				/* Operational On */
+#define	TPFU_CTRL_OP_OFF					BIT_2				/* Operational Off */
+#define	TPFU_CTRL_PFU_RST_CLR				BIT_1				/* PFU Reset Clear */
+#define	TPFU_CTRL_PFU_RST_SET				BIT_0				/* PFU Reset Set */
+
+/*	TPFU_LAST_IDX		0x06D4	Transmit PFU List Last Index Register */
+/*		Bit(s) TPFU_LAST_IDX_RSRV_31_12 reserved */
+#define	TPFU_LAST_IDX_MSK					SHIFT2(0x3ff)		/* List Last Index */
+#define	TPFU_LAST_IDX_BASE					2
+/* List Last Index Fix */
+#define	TPFU_LAST_IDX_VAL_FIX_MSK			SHIFT0(0x3)			
+#define	TPFU_LAST_IDX_VAL_FIX_BASE			0
+
+/*	TPFU_LADR_LO		0x06D8	Transmit PFU List Start Address Low Register */
+/* List Start Address Low */
+#define	TPFU_LADR_LO_MSK				SHIFT5(0x7ffffff)	
+#define	TPFU_LADR_LO_BASE				5
+/* List Start Address Low Fix */
+#define	TPFU_LADR_LO_VAL_FIX_MSK		SHIFT0(0x1f)		
+#define	TPFU_LADR_LO_VAL_FIX_BASE		0
+
+/*	TPFU_LADR_HI		0x06DC	Transmit PFU List Start Address High Register */
+#define	TPFU_LADR_HI_MSK		SHIFT0(0xffffffff)	/* List Start Address High */
+#define	TPFU_LADR_HI_BASE		0
+
+/*	TPFU_GET_IDX		0x06E0	Transmit PFU Get Index Register */
+/*		Bit(s) TPFU_GET_IDX_RSRV_31_12 reserved */
+#define	TPFU_GET_IDX_MSK					SHIFT0(0xfff)		/* Get Index */
+#define	TPFU_GET_IDX_BASE					0
+
+/*	TPFU_PUT_IDX		0x06E4	Transmit PFU Put Index Register */
+/*		Bit(s) TPFU_PUT_IDX_RSRV_31_12 reserved */
+#define	TPFU_PUT_IDX_MSK					SHIFT0(0xfff)		/* Put Index */
+#define	TPFU_PUT_IDX_BASE					0
+
+/*	TPFU_FIFO_WR		0x06F0	Transmit PFU FIFO RAM Write and Write Shadow
+ *								Pointer Register
+ */
+/*		Bit(s) TPFU_FIFO_WR_RSRV_31_24 reserved */
+/* FIFO Write Shadow Pointer */
+#define	TPFU_FIFO_WR_WSPTR_MSK				SHIFT16(0xff)	
+#define	TPFU_FIFO_WR_WSPTR_BASE				16
+/*		Bit(s) TPFU_FIFO_WR_RSRV_15_5 reserved */
+#define	TPFU_FIFO_WR_WPTR_MSK				SHIFT0(0x1f)	/* FIFO Write Pointer */
+#define	TPFU_FIFO_WR_WPTR_BASE				0
+
+/*	TPFU_FIFO_RD		0x06F4	Transmit PFU FIFO RAM Read Pointer Register */
+/*		Bit(s) TPFU_FIFO_RD_RSRV_31_5 reserved */
+#define	TPFU_FIFO_RD_RPTR_MSK			SHIFT0(0x1f)		/* FIFO Read Pointer */
+#define	TPFU_FIFO_RD_RPTR_BASE			0
+
+/*	TPFU_FIFO_REQ_NB	0x06F8	Transmit PFU Master Request nbytes Register */
+/*		Bit(s) TPFU_FIFO_REQ_NB_RSRV_31_27 reserved */
+/* Master Request nBytes */
+#define	TPFU_FIFO_REQ_NB_MR_MSK					SHIFT16(0x7ff)	
+#define	TPFU_FIFO_REQ_NB_MR_BASE				16
+/*		Bit(s) TPFU_FIFO_REQ_NB_RSRV_15_8 reserved */
+#define	TPFU_FIFO_REQ_NB_WM_MSK					SHIFT0(0xff)	/* FIFO Watermark */
+#define	TPFU_FIFO_REQ_NB_WM_BASE				0
+
+/*	TPFU_FIFO_LEV		0x06FC	Transmit PFU FIFO Shadow Level Register */
+/*		Bit(s) TPFU_FIFO_LEV_RSRV_31_24 reserved */
+#define	TPFU_FIFO_LEV_SLEV_MSK				SHIFT16(0xff)	/* FIFO Shadow level */
+#define	TPFU_FIFO_LEV_SLEV_BASE				16
+/*		Bit(s) TPFU_FIFO_LEV_RSRV_15_5 reserved */
+#define	TPFU_FIFO_LEV_MSK					SHIFT0(0x1f)	/* FIFO level */
+#define	TPFU_FIFO_LEV_BASE					0
+
+/*	RA_SADDR			0x0900	ASF Receive FIFO Start Address */
+/*		Bit(s) RA_SADDR_RSRV_22_0 reserved */
+#define	RA_SADDR_RA_SADDR_MSK		SHIFT0(0x1ff)		/* Start Address */
+#define	RA_SADDR_RA_SADDR_BASE		BIT_0
+
+/*	RA_EADDR			0x0904	ASF Receive FIFO End Address */
+/*		Bit(s) RA_EADDR_RSRV_22_0 reserved */
+#define	RA_EADDR_RA_EADDR_MSK		SHIFT0(0x1ff)		/* End Address */
+#define	RA_EADDR_RA_EADDR_BASE		BIT_0
+
+/*	RA_WPTR				0x0908	ASF Receive FIFO Write Pointer */
+/*		Bit(s) RA_WPTR_RSRV_22_0 reserved */
+#define	RA_WPTR_RA_WPTR_MSK			SHIFT0(0x1ff)		/* Write Pointer */
+#define	RA_WPTR_RA_WPTR_BASE		BIT_0
+
+/*	RA_RPTR				0x090C	ASF Receive FIFO Read Pointer */
+/*		Bit(s) RA_RPTR_RSRV_22_0 reserved */
+#define	RA_RPTR_RA_RPTR_MSK			SHIFT0(0x1ff)		/* Read Pointer */
+#define	RA_RPTR_RA_RPTR_BASE		BIT_0
+
+/*	RA_BRST				0x0910	ASF Receive FIFO Burst Control */
+/*		Bit(s) RA_BRST_RSRV_13_0 reserved */
+#define	RA_BRST_RA_BRST_EN				BIT_17			/* Burst Enable */
+#define	RA_BRST_RA_BRST_RST				BIT_16			/* Burst Disable */
+/*		Bit(s) RA_BRST_RSRV_6_0 reserved */
+#define	RA_BRST_RA_BRST_THRS_MSK		SHIFT0(0x1ff)	/* Burst Threshold */
+#define	RA_BRST_RA_BRST_THRS_BASE		BIT_0
+
+/*	RA_PCNT				0x0920	ASF Receive FIFO Packet Counter */
+/*		Bit(s) RA_PCNT_RSRV_22_0 reserved */
+#define	RA_PCNT_RA_PCNT_MSK			SHIFT0(0x1ff)		/* Packet Counter */
+#define	RA_PCNT_RA_PCNT_BASE		BIT_0
+
+/*	RA_LEV				0x0924	ASF Receive FIFO Level */
+/*		Bit(s) RA_LEV_RSRV_22_0 reserved */
+#define	RA_LEV_RA_LEV_MSK			SHIFT0(0x1ff)		/* Level */
+#define	RA_LEV_RA_LEV_BASE			BIT_0
+
+/*	RA_CTRL				0x0928	ASF Receive FIFO Control/Test */
+/*		Bit(s) RA_CTRL_RSRV_11_0 reserved */
+#define	RA_CTRL_RA_PCNT_DN			BIT_19			/* Packet Counter Step Down */
+#define	RA_CTRL_RA_PCNT_ENA			BIT_18			/* Packet Counter Test On */
+#define	RA_CTRL_RA_PCNT_RST			BIT_17			/* Packet Counter Test Off */
+#define	RA_CTRL_RA_PCNT_UP			BIT_16			/* Packet Counter Step Up */
+/*		Bit(s) RA_CTRL_RSRV_ reserved */
+#define	RA_CTRL_RA_WPTR_ENA			BIT_14			/* Write Pointer Test On */
+#define	RA_CTRL_RA_WPTR_RST			BIT_13			/* Write Pointer Test Off */
+#define	RA_CTRL_RA_WPTR_UP			BIT_12			/* Write Pointer Step Up */
+/*		Bit(s) RA_CTRL_RSRV_4_0 reserved */
+#define	RA_CTRL_RA_IRQ_CLR			BIT_6			/* Clear IRQ ASF Receive FIFO */
+/*		Bit(s) RA_CTRL_RSRV_1_0 reserved */
+#define	RA_CTRL_RA_OP_ON			BIT_3			/* Operational On */
+#define	RA_CTRL_RA_OP_OFF			BIT_2			/* Operational Off */
+#define	RA_CTRL_RA_RST_CLR			BIT_1			/* Reset Clear */
+#define	RA_CTRL_RA_RST_SET			BIT_0			/* Reset Set */
+
+/*	RA_FLSH_CTRL		0x092C	ASF Receive FIFO Flush Control */
+#define	RA_FLSH_CTRL_RA_FLSH				BIT_31				/* Flush */
+/*		Bit(s) RA_FLSH_CTRL_RSRV_21_0 reserved */
+#define	RA_FLSH_CTRL_RA_FLSH_QWORD_MSK		SHIFT0(0x1ff)		/* Flush Qword */
+#define	RA_FLSH_CTRL_RA_FLSH_QWORD_BASE		BIT_0
+
+/*	TA_SADDR			0x0940	ASF Transmit FIFO Start Address */
+/*		Bit(s) TA_SADDR_RSRV_22_0 reserved */
+#define	TA_SADDR_TA_SADDR_MSK		SHIFT0(0x1ff)		/* Start Address */
+#define	TA_SADDR_TA_SADDR_BASE		BIT_0
+
+/*	TA_EADDR			0x0944	ASF Transmit FIFO End Address */
+/*		Bit(s) TA_EADDR_RSRV_22_0 reserved */
+#define	TA_EADDR_TA_EADDR_MSK		SHIFT0(0x1ff)		/* End Address */
+#define	TA_EADDR_TA_EADDR_BASE		BIT_0
+
+/*	TA_WPTR				0x0948	ASF Transmit FIFO Write Pointer */
+/*		Bit(s) TA_WPTR_RSRV_22_0 reserved */
+#define	TA_WPTR_TA_WPTR_MSK			SHIFT0(0x1ff)		/* Write Pointer */
+#define	TA_WPTR_TA_WPTR_BASE		BIT_0
+
+/*	TA_RPTR				0x094C	ASF Transmit FIFO Read Pointer */
+/*		Bit(s) TA_RPTR_RSRV_22_0 reserved */
+#define	TA_RPTR_TA_RPTR_MSK			SHIFT0(0x1ff)		/* Read Pointer */
+#define	TA_RPTR_TA_RPTR_BASE		BIT_0
+
+/*	TA_PCNT				0x0960	ASF Transmit FIFO Packet Counter */
+/*		Bit(s) TA_PCNT_RSRV_22_0 reserved */
+#define	TA_PCNT_TA_PCNT_MSK			SHIFT0(0x1ff)		/* Packet Counter */
+#define	TA_PCNT_TA_PCNT_BASE		BIT_0
+
+/*	TA_LEV				0x0964	ASF Transmit FIFO Level */
+/*		Bit(s) TA_LEV_RSRV_22_0 reserved */
+#define	TA_LEV_TA_LEV_MSK			SHIFT0(0x1ff)		/* Level */
+#define	TA_LEV_TA_LEV_BASE			BIT_0
+
+/*	TA_CTRL				0x0968	ASF Transmit FIFO Control/Test */
+/*		Bit(s) TA_CTRL_RSRV_11_0 reserved */
+#define	TA_CTRL_TA_PCNT_DN			BIT_19			/* Packet Counter Step Down */
+#define	TA_CTRL_TA_PCNT_ENA			BIT_18			/* Packet Counter Test On */
+#define	TA_CTRL_TA_PCNT_RST			BIT_17			/* Packet Counter Test Off */
+#define	TA_CTRL_TA_PCNT_UP			BIT_16			/* Packet Counter Step Up */
+/*		Bit(s) TA_CTRL_RSRV_4_0 reserved */
+#define	TA_CTRL_TA_RPTR_ENA			BIT_10			/* Read Pointer Test On */
+#define	TA_CTRL_TA_RPTR_RST			BIT_9			/* Read Pointer Test Off */
+#define	TA_CTRL_TA_RPTR_UP			BIT_8			/* Read Pointer Step Up */
+/*		Bit(s) TA_CTRL_RSRV_ reserved */
+#define	TA_CTRL_TA_IRQ_CLR			BIT_6			/* Clear IRQ ASF Transmit FIFO */
+/*		Bit(s) TA_CTRL_RSRV_1_0 reserved */
+#define	TA_CTRL_TA_OP_ON			BIT_3			/* Operational On */
+#define	TA_CTRL_TA_OP_OFF			BIT_2			/* Operational Off */
+#define	TA_CTRL_TA_RST_CLR			BIT_1			/* Reset Clear */
+#define	TA_CTRL_TA_RST_SET			BIT_0			/* Reset Set */
+
+/*	TA_SEND_CTRL		0x096C	ASF Transmit FIFO Send Control */
+#define	TA_SEND_CTRL_TA_SEND				BIT_31				/* Send */
+/*		Bit(s) TA_SEND_CTRL_RSRV_21_0 reserved */
+#define	TA_SEND_CTRL_TA_SEND_QWORD_MSK		SHIFT0(0x1ff)		/* Send Qword */
+#define	TA_SEND_CTRL_TA_SEND_QWORD_BASE		BIT_0
+
+/*	RXMF_EADDR			0x0C40	Receive MAC FIFO End Address Register */
+/*		Bit(s) RXMF_EADDR_RSRV_31_1 reserved */
+#define	RXMF_EADDR_TS_DIS					BIT_0				/* TIMESTAMP_OUT_E */
+
+/*	RXMF_AFTH			0x0C44	Receive MAC FIFO Almost Full Threshold Register */
+/*		Bit(s) RXMF_AFTH_RSRV_31_9 reserved */
+/* Almost Full Threshold */
+#define	RXMF_AFTH_MSK					SHIFT0(0x1ff)		
+#define	RXMF_AFTH_BASE					0
+
+/*	RXMF_TCTL			0x0C48	Receive MAC FIFO Control/Test Register */
+/* RX MAC Clock Gating Enable */
+#define	RXMF_TCTL_GCLKMAC_ENA			BIT_31			
+/* RX MAC Clock Gating Disable */
+#define	RXMF_TCTL_GCLKMAC_DIS			BIT_30			
+/* RX Store and Forward Enable */
+#define	RXMF_TCTL_STFWD_ENA				BIT_29			
+/* RX Store and Forward Disable */
+#define	RXMF_TCTL_STFWD_DIS				BIT_28			
+#define	RXMF_TCTL_TRUNC_ENA				BIT_27			/* Truncation Enable */
+#define	RXMF_TCTL_TRUNC_DIS				BIT_26			/* Truncation Disable */
+#define	RXMF_TCTL_VLAN_ENA				BIT_25			/* VLAN Enable */
+#define	RXMF_TCTL_VLAN_DIS				BIT_24			/* VLAN Disable */
+/*		Bit(s) RXMF_TCTL_RSRV_23_20 reserved */
+/* RX MACSec Flush Enable */
+#define	RXMF_TCTL_MACSEC_FLSH_ENA			BIT_23			
+/* RX MACSec Flush Disable */
+#define	RXMF_TCTL_MACSEC_FLSH_DIS			BIT_22			
+/* ASF RX MACSec Flush Enable */
+#define	RXMF_TCTL_RA_MACSEC_FLSH_ENA		BIT_21			
+/* ASF RX MACSec Flush Disable */
+#define	RXMF_TCTL_RA_MACSEC_FLSH_DIS		BIT_20			
+/* RX Overrun Flush Enable */
+#define	RXMF_TCTL_OVRRN_FLSH_ENA			BIT_19			
+/* RX Overrun Flush Disable */
+#define	RXMF_TCTL_OVRRN_FLSH_DIS			BIT_18			
+/* ASF RX Overrun Flush Enable */
+#define	RXMF_TCTL_RA_FLSH_ENA				BIT_17			
+/* ASF RX Overrun Flush Disable */
+#define	RXMF_TCTL_RA_FLSH_DIS				BIT_16			
+/*		Bit(s) RXMF_TCTL_RSRV_ reserved */
+/* Write Pointer Test On */
+#define	RXMF_TCTL_WPTR_TEST_ON				BIT_14			
+/* Write Pointer Test Off */
+#define	RXMF_TCTL_WPTR_TEST_OFF				BIT_13			
+#define	RXMF_TCTL_WPTR_TEST_STEP			BIT_12			/* Write Pointer Step */
+/*		Bit(s) RXMF_TCTL_RSRV_ reserved */
+#define	RXMF_TCTL_RPTR_TEST_ON				BIT_10			/* Read Pointer Test On */
+/* Read Pointer Test Off */
+#define	RXMF_TCTL_RPTR_TEST_OFF				BIT_9			
+#define	RXMF_TCTL_RPTR_TEST_STEP		BIT_8			/* Read Pointer Step */
+#define	RXMF_TCTL_FLUSH_ON				BIT_7			/* FIFO Flush On */
+#define	RXMF_TCTL_FLUSH_OFF				BIT_6			/* FIFO Flush Off */
+/* Clear IRQ Receive FIFO Overrun */
+#define	RXMF_TCTL_CLR_IRQ_RX_OF			BIT_5			
+/* Clear IRQ Frame Reception Complete */
+#define	RXMF_TCTL_CLR_IRQ_RX_OK			BIT_4			
+#define	RXMF_TCTL_OP_ON					BIT_3			/* Operational On */
+#define	RXMF_TCTL_OP_OFF				BIT_2			/* Operational Off */
+#define	RXMF_TCTL_RST_CLR				BIT_1			/* MAC FIFO Reset Clear */
+#define	RXMF_TCTL_RST_SET				BIT_0			/* MAC FIFO Reset Set */
+
+/*	RXMF_FLMSK			0x0C4C	Receive MAC FIFO Flush Mask Register */
+/*		Bit(s) RXMF_FLMSK_RSRV_31_14 reserved */
+#define	RXMF_FLMSK_LEN_ERR				BIT_14				/* Length Error */
+#define	RXMF_FLMSK_VLAN					BIT_13				/* VLAN packet */
+#define	RXMF_FLMSK_JBR					BIT_12				/* Jabber */
+#define	RXMF_FLMSK_USIZE				BIT_11				/* Undersize packet */
+#define	RXMF_FLMSK_MCST					BIT_10				/* Multicast packet */
+#define	RXMF_FLMSK_BCST					BIT_9				/* Broadcast packet */
+#define	RXMF_FLMSK_RX_OK				BIT_8				/* Receive OK */
+/* Good flow control packet */
+#define	RXMF_FLMSK_GD_FC				BIT_7				
+/* Bad flow control packet */
+#define	RXMF_FLMSK_BD_FC				BIT_6				
+#define	RXMF_FLMSK_MII_ERR				BIT_5				/* MII error */
+#define	RXMF_FLMSK_TLNG					BIT_4				/* Too long packet */
+#define	RXMF_FLMSK_FRAG					BIT_3				/* Fragment */
+/*		Bit(s) RXMF_FLMSK_RSRV_2 reserved */
+#define	RXMF_FLMSK_CRC_ERR				BIT_1				/* CRC error */
+/* Receive FIFO overflow */
+#define	RXMF_FLMSK_RX_OF				BIT_0				
+
+/*	RXMF_FLTH			0x0C50	Receive MAC FIFO Flush Threshold Register */
+/*		Bit(s) RXMF_FLTH_RSRV_31_22 reserved */
+/* Pointers Delay Synchronization Enable */
+#define	RXMF_FLTH_PTR_SYNCDLY_ENA		BIT_21			
+/* Pointers Delay Synchronization Disable */
+#define	RXMF_FLTH_PTR_SYNCDLY_DIS		BIT_20			
+/* RX ASF Flag New Logic Enable */
+#define	RXMF_FLTH_ASF_NEWFLAG_ENA		BIT_19			
+/* RX ASF Flag New Logic Disable */
+#define	RXMF_FLTH_ASF_NEWFLAG_DIS		BIT_18			
+/* RX Flush Miss-Packet Enable */
+#define	RXMF_FLTH_FLSH_MISSPKT_ENA		BIT_17			
+/* RX Flush Miss-Packet Disable */
+#define	RXMF_FLTH_FLSH_MISSPKT_DIS		BIT_16			
+/*		Bit(s) RXMF_FLTH_RSRV_6_0 reserved */
+#define	RXMF_FLTH_MSK					SHIFT0(0x1ff)	/* Flush Threshold */
+#define	RXMF_FLTH_BASE					0
+
+/*	RXMF_TRTH			0x0C54	Receive Truncation Threshold Register */
+/*		Bit(s) RXMF_TRTH_RSRV_31_9 reserved */
+/* Truncation Threshold */
+#define	RXMF_TRTH_TRUNCATION_THRESHOLD_MSK		SHIFT0(0x1ff)		
+#define	RXMF_TRTH_TRUNCATION_THRESHOLD_BASE		0
+
+/*	RXMF_ULTH			0x0C58	Upper/Lower Threshold/Pause Packets Register */
+/*		Bit(s) RXMF_ULTH_RSRV_31_25 reserved */
+/* Pause Packet Watermark Low Threshold */
+#define	RXMF_ULTH_LO_TH_MSK				SHIFT16(0x1ff)	
+#define	RXMF_ULTH_LO_TH_BASE			16
+/*		Bit(s) RXMF_ULTH_RSRV_15_9 reserved */
+/* Pause Packet Watermark High Threshold */
+#define	RXMF_ULTH_HI_TH_MSK				SHIFT0(0x1ff)	
+#define	RXMF_ULTH_HI_TH_BASE			0
+
+/*	RXMF_VLTYP			0x0C5C	Receive VLAN Type Register */
+/*		Bit(s) RXMF_VLTYP_RSRV_31_16 reserved */
+#define	RXMF_VLTYP_MSK					SHIFT0(0xffff)	/* Receive VLAN Type */
+#define	RXMF_VLTYP_BASE					0
+
+/*	RXMF_WPTR			0x0C60	Receive MAC FIFO Write Pointer Register */
+/*		Bit(s) RXMF_WPTR_RSRV_31_9 reserved */
+#define	RXMF_WPTR_MSK					SHIFT0(0x1ff)		/* Write Pointer */
+#define	RXMF_WPTR_BASE					0
+
+/*	RXMF_WLEV			0x0C68	Receive MAC FIFO Write Level Register */
+/*		Bit(s) RXMF_WLEV_RSRV_31_9 reserved */
+#define	RXMF_WLEV_MSK					SHIFT0(0x1ff)		/* Write Level */
+#define	RXMF_WLEV_BASE					0
+
+/*	RXMF_RPTR			0x0C70	Receive MAC FIFO Read Pointer Register */
+/*		Bit(s) RXMF_RPTR_RSRV_31_9 reserved */
+#define	RXMF_RPTR_MSK					SHIFT0(0x1ff)		/* Read Pointer */
+#define	RXMF_RPTR_BASE					0
+
+/*	RXMF_RLEV			0x0C78	Receive MAC FIFO Read Level Register */
+/*		Bit(s) RXMF_RLEV_RSRV_31_9 reserved */
+#define	RXMF_RLEV_MSK					SHIFT0(0x1ff)		/* Read Level */
+#define	RXMF_RLEV_BASE					0
+
+/*	TXMF_EADDR			0x0D40	Transmit MAC FIFO End Address Register */
+/*		Bit(s) TXMF_EADDR_RSRV_31_4 reserved */
+/* MAC Tx RAM Read Control */
+#define	TXMF_EADDR_MAC_TX_RAM_RD_CTRL		BIT_3				
+/* BMU Tx RAM Read Control */
+#define	TXMF_EADDR_BMU_TX_RAM_RD_CTRL		BIT_2				
+/*		Bit(s) TXMF_EADDR_RSRV_1_0 reserved */
+
+/*	TXMF_AETH			0x0D44	Transmit MAC FIFO Almost Empty Threshold
+ *								Register
+ */
+/*		Bit(s) TXMF_AETH_RSRV_31_25 reserved */
+#define	TXMF_AETH_JUMBO_WM_MSK			SHIFT16(0x1ff)	/* Jumbo Mode Watermark */
+#define	TXMF_AETH_JUMBO_WM_BASE			16
+/*		Bit(s) TXMF_AETH_RSRV_15_8 reserved */
+#define	TXMF_AETH_MSK					SHIFT0(0xff)	/* Almost Empty Threshold */
+#define	TXMF_AETH_BASE					0
+
+/*	TXMF_TCTL			0x0D48	Transmit MAC FIFO Control/Test Register */
+#define	TXMF_TCTL_JUMBO_ENA				BIT_31			/* Jumbo Mode Enable */
+/* Tx Store and Forward Mode Enable */
+#define	TXMF_TCTL_STORE_FW_ENA			BIT_30			
+#define	TXMF_TCTL_FIX_440_OFF			BIT_29			/* Perf Fix #4.40 Off */
+#define	TXMF_TCTL_FIX_440_ON			BIT_28			/* Perf Fix #4.40 On */
+/* CHECKSUM SEL use WRITE status bit */
+#define	TXMF_TCTL_CHKSUM_DIS			BIT_27			
+/* CHECKSUM SEL use CALSUM status bit */
+#define	TXMF_TCTL_CHKSUM_EN				BIT_26			
+#define	TXMF_TCTL_VLAN_ENA				BIT_25			/* VLAN Enable */
+#define	TXMF_TCTL_VLAN_DIS				BIT_24			/* VLAN Disable */
+#define	TXMF_TCTL_PCI_JUMBO_ENA			BIT_23			/* PCI Jumbo Mode Enable */
+#define	TXMF_TCTL_PCI_JUMBO_DIS			BIT_22			/* PCI Jumbo Mode Disable */
+/*		Bit(s) TXMF_TCTL_RSRV_21_19 reserved */
+/* Write Shadow Pointer Test On */
+#define	TXMF_TCTL_WSPTR_TEST_ON			BIT_18			
+/* Write Shadow Pointer Test Off */
+#define	TXMF_TCTL_WSPTR_TEST_OFF		BIT_17			
+/* Write Shadow Pointer Step */
+#define	TXMF_TCTL_WSPTR_TEST_STEP		BIT_16			
+/*		Bit(s) TXMF_TCTL_RSRV_15 reserved */
+#define	TXMF_TCTL_WPTR_TEST_ON			BIT_14			/* Write Pointer Test On */
+#define	TXMF_TCTL_WPTR_TEST_OFF			BIT_13			/* Write Pointer Test Off */
+#define	TXMF_TCTL_WPTR_TEST_STEP		BIT_12			/* Write Pointer Step */
+/*		Bit(s) TXMF_TCTL_RSRV_11 reserved */
+#define	TXMF_TCTL_RPTR_TEST_ON			BIT_10			/* Read Pointer Test On */
+#define	TXMF_TCTL_RPTR_TEST_OFF			BIT_9			/* Read Pointer Test Off */
+#define	TXMF_TCTL_RPTR_TEST_STEP		BIT_8			/* Read Pointer Step */
+/*		Bit(s) TXMF_TCTL_RSRV_7 reserved */
+/* Clear IRQ Transmit FIFO Underrun */
+#define	TXMF_TCTL_CLR_IRQ_TX_UR			BIT_6			
+/* Clear IRQ Frame Transmission Complete */
+#define	TXMF_TCTL_CLR_IRQ_TX_OK			BIT_5			
+#define	TXMF_TCTL_CLR_IRQ_PAR			BIT_4			/* Clear IRQ Parity Error */
+#define	TXMF_TCTL_OP_ON					BIT_3			/* Operational On */
+#define	TXMF_TCTL_OP_OFF				BIT_2			/* Operational Off */
+#define	TXMF_TCTL_RST_CLR				BIT_1			/* MAC FIFO Reset Clear */
+#define	TXMF_TCTL_RST_SET				BIT_0			/* MAC FIFO Reset Set */
+
+/*	TXMF_VLTYP			0x0D5C	Transmit VLAN Type Register */
+/*		Bit(s) TXMF_VLTYP_RSRV_31_16 reserved */
+#define	TXMF_VLTYP_MSK					SHIFT0(0xffff)	/* Transmit VLAN Type */
+#define	TXMF_VLTYP_BASE					0
+
+/*	TXMF_WPTR			0x0D60	Transmit MAC FIFO Write Pointer Register */
+/*		Bit(s) TXMF_WPTR_RSRV_31_8 reserved */
+#define	TXMF_WPTR_MSK					SHIFT0(0xff)		/* Write Pointer */
+#define	TXMF_WPTR_BASE					0
+
+/*	TXMF_WSPTR			0x0D64	Transmit MAC FIFO Write Shadow Pointer Register */
+/*		Bit(s) TXMF_WSPTR_RSRV_31_8 reserved */
+#define	TXMF_WSPTR_MSK					SHIFT0(0xff)		/* Write Shadow Pointer */
+#define	TXMF_WSPTR_BASE					0
+
+/*	TXMF_WLEV			0x0D68	Transmit MAC FIFO Write Level Register */
+/*		Bit(s) TXMF_WLEV_RSRV_31_8 reserved */
+#define	TXMF_WLEV_MSK					SHIFT0(0xff)		/* Write Level */
+#define	TXMF_WLEV_BASE					0
+
+/*	TXMF_RPTR			0x0D70	Transmit MAC FIFO Read Pointer Register */
+/*		Bit(s) TXMF_RPTR_RSRV_31_8 reserved */
+#define	TXMF_RPTR_MSK					SHIFT0(0xff)		/* Read Pointer */
+#define	TXMF_RPTR_BASE					0
+
+/*	TXMF_RES_PTR		0x0D74	Transmit MAC FIFO Restart Pointer Register */
+/*		Bit(s) TXMF_RES_PTR_RSRV_31_8 reserved */
+#define	TXMF_RES_PTR_MSK				SHIFT0(0xff)		/* Restart Pointer */
+#define	TXMF_RES_PTR_BASE				0
+
+/*	TXMF_RLEV			0x0D78	Transmit MAC FIFO Read Level Register */
+/*		Bit(s) TXMF_RLEV_RSRV_31_8 reserved */
+#define	TXMF_RLEV_MSK					SHIFT0(0xff)		/* Read Level */
+#define	TXMF_RLEV_BASE					0
+
+/*	DPOL_TIM_INIT		0x0E00	Descriptor Poll Timer Init Value Register */
+#define	DPOL_TIM_INIT_INIT_VALUE_MSK		SHIFT0(0xffffffff)	/* Init Value */
+#define	DPOL_TIM_INIT_INIT_VALUE_BASE		0
+
+/*	DPOL_TIM_CNT		0x0E04	Descriptor Poll Timer Register */
+#define	DPOL_TIM_CNT_MSK		SHIFT0(0xffffffff)	/* Descriptor Poll Timer */
+#define	DPOL_TIM_CNT_BASE		0
+
+/*	DPOL_TCTL			0x0E08	Descriptor Poll Timer Control/Test Register */
+/*		Bit(s) DPOL_TCTL_RSRV_31_11 reserved */
+/* Descriptor Poll Timer Test On */
+#define	DPOL_TCTL_ON					BIT_10				
+/* Descriptor Poll Timer Test Off */
+#define	DPOL_TCTL_OFF					BIT_9				
+/* Descriptor Poll Timer Step */
+#define	DPOL_TCTL_STEP					BIT_8				
+/*		Bit(s) DPOL_TCTL_RSRV_7_3 reserved */
+/* Descriptor Poll Timer Start */
+#define	DPOL_TCTL_STRT					BIT_2				
+/* Descriptor Poll Timer Stop */
+#define	DPOL_TCTL_STOP					BIT_1				
+/*		Bit(s) DPOL_TCTL_RSRV_0 reserved */
+
+/*	TSP_TIM_CNT			0x0E14	Timestamp Timer Registers */
+#define	TSP_TIM_CNT_MSK			SHIFT0(0xffffffff)	/* Timestamp Timer */
+#define	TSP_TIM_CNT_BASE		0
+
+/*	TSP_TIM_TCTL		0x0E18	Timestamp Timer Control/Test Register */
+/*		Bit(s) TSP_TIM_TCTL_RSRV_31_11 reserved */
+/* Timestamp Timer Test On */
+#define	TSP_TIM_TCTL_ON						BIT_10				
+/* Timestamp Timer Test Off */
+#define	TSP_TIM_TCTL_OFF					BIT_9				
+/* Timestamp Timer Step */
+#define	TSP_TIM_TCTL_STEP					BIT_8				
+/*		Bit(s) TSP_TIM_TCTL_RSRV_7_3 reserved */
+/* Timestamp Timer Start */
+#define	TSP_TIM_TCTL_STRT					BIT_2				
+/* Timestamp Timer Stop */
+#define	TSP_TIM_TCTL_STOP					BIT_1				
+/* Timestamp Timer Clear IRQ */
+#define	TSP_TIM_TCTL_CLR_IRQ				BIT_0				
+
+/*	POLL_CTRL			0x0E20	Poll Control Register */
+/*		Bit(s) POLL_CTRL_RSRV_31_6 reserved */
+#define	POLL_CTRL_CLR_IRQ				BIT_5				/* Clear IRQ */
+#define	POLL_CTRL_POLL_REQ				BIT_4				/* Poll Request */
+#define	POLL_CTRL_OP_ON					BIT_3				/* Operational On */
+#define	POLL_CTRL_OP_OFF				BIT_2				/* Operational Off */
+#define	POLL_CTRL_POLL_RST_CLR			BIT_1				/* POLLU Reset Clear */
+#define	POLL_CTRL_POLL_RST_SET			BIT_0				/* POLLU Reset Set */
+
+/*	POLL_LAST_IDX		0x0E24	List Last Index Register */
+/*		Bit(s) POLL_LAST_IDX_RSRV_31_1 reserved */
+#define	POLL_LAST_IDX_BIT					BIT_0				/* List Last Index */
+
+/*	POLL_LADR_LO		0x0E28	List Start Address Low Register */
+/* List Start Address Low */
+#define	POLL_LADR_LO_MSK				SHIFT3(0x1fffffff)	
+#define	POLL_LADR_LO_BASE				3
+/* List Start Address Low fixed */
+#define	POLL_LADR_LO_VAL_FIX_MSK		SHIFT0(0x7)			
+#define	POLL_LADR_LO_VAL_FIX_BASE		0
+
+/*	POLL_LADR_HI		0x0E2C	List Start Address High Register */
+#define	POLL_LADR_HI_MSK		SHIFT0(0xffffffff)	/* List Start Address High */
+#define	POLL_LADR_HI_BASE		0
+
+/*	CPU_ISRC			0x0E30	Interrupt Source Register */
+/*		Bit(s) CPU_ISRC_RSRV_25_0 reserved */
+#define	CPU_ISRC_CPU				BIT_5				/* CPU Interrupt */
+#define	CPU_ISRC_TIM				BIT_4				/* Timer Interrupt */
+#define	CPU_ISRC_SMB				BIT_3				/* SMBus Interrupt */
+#define	CPU_ISRC_RX					BIT_2				/* ASF Rx Queue Interrupt */
+#define	CPU_ISRC_TX					BIT_1				/* ASF Tx Queue Interrupt */
+/* Host Communication Unit Interrupt */
+#define	CPU_ISRC_HCU				BIT_0				
+
+/*	CPU_IMSK			0x0E34	Interrupt Mask Register */
+/*		Bit(s) CPU_IMSK_RSRV_9_0 reserved */
+#define	CPU_IMSK_FIQ_CPU			BIT_21			/* CPU Interrupt mapped to FIQ */
+#define	CPU_IMSK_FIQ_TIM			BIT_20			/* TIM Interrupt mapped to FIQ */
+#define	CPU_IMSK_FIQ_SMB			BIT_19			/* SMB Interrupt mapped to FIQ */
+#define	CPU_IMSK_FIQ_RX				BIT_18			/* RX Interrupt mapped to FIQ */
+#define	CPU_IMSK_FIQ_TX				BIT_17			/* TX Interrupt mapped to FIQ */
+#define	CPU_IMSK_FIQ_HCU			BIT_16			/* HCU Interrupt mapped to FIQ */
+/*		Bit(s) CPU_IMSK_RSRV_9_0 reserved */
+#define	CPU_IMSK_IRQ_CPU			BIT_5			/* CPU Interrupt mapped to IRQ */
+#define	CPU_IMSK_IRQ_TIM			BIT_4			/* TIM Interrupt mapped to IRQ */
+#define	CPU_IMSK_IRQ_SMB			BIT_3			/* SMB Interrupt mapped to IRQ */
+#define	CPU_IMSK_IRQ_RX				BIT_2			/* RX Interrupt mapped to IRQ */
+#define	CPU_IMSK_IRQ_TX				BIT_1			/* TX Interrupt mapped to IRQ */
+#define	CPU_IMSK_IRQ_HCU			BIT_0			/* HCU Interrupt mapped to IRQ */
+
+/*	SMB_CFG				0x0E40	SMBus Config Register */
+#define	SMB_CFG_PS_MSK			SHIFT30(0x3)	/* SMBPS */
+#define	SMB_CFG_PS_BASE			BIT_30
+#define	SMB_CFG_CSE				BIT_29			/* SMBCSE */
+#define	SMB_CFG_BR_MSK			SHIFT16(0x1fff)	/* SMBBR */
+#define	SMB_CFG_BR_BASE			BIT_16
+#define	SMB_CFG_SADDR_MSK		SHIFT9(0x7f)	/* SMBSlaveAddr */
+#define	SMB_CFG_SADDR_BASE		BIT_9
+#define	SMB_CFG_SADDR_ENA		BIT_8			/* SMBSAE */
+#define	SMB_CFG_DADDR_ENA		BIT_7			/* SMBDAE */
+#define	SMB_CFG_GC_ENA			BIT_6			/* SMBGCE */
+#define	SMB_CFG_ACK_ENA			BIT_5			/* SMBEA */
+#define	SMB_CFG_IRQ_ENA			BIT_4			/* SMBIE */
+#define	SMB_CFG_OP_ON			BIT_3			/* Operational On */
+#define	SMB_CFG_OP_OFF			BIT_2			/* Operational Off */
+#define	SMB_CFG_RST_CLR			BIT_1			/* SMBus Reset Clear */
+#define	SMB_CFG_RST_SET			BIT_0			/* SMBus Reset Set */
+
+/*	SMB_CSR				0x0E44	SMBus Control/Status Register */
+#define	SMB_CSR_AL					BIT_31			/* SMBAL */
+#define	SMB_CSR_RX_ACK				BIT_30			/* SMBRxACK */
+#define	SMB_CSR_RX_FULL				BIT_29			/* SMBRxFull */
+#define	SMB_CSR_TX_EMPTY			BIT_28			/* SMBTxEmpty */
+#define	SMB_CSR_TX_DONE				BIT_27			/* SMBTxDone */
+#define	SMB_CSR_STOP				BIT_26			/* SMBSTOP */
+#define	SMB_CSR_IF					BIT_25			/* SMBIF */
+#define	SMB_CSR_RX_STRT				BIT_24			/* SMBRxSTA */
+#define	SMB_CSR_TIP					BIT_23			/* SMBTIP */
+#define	SMB_CSR_BUSY				BIT_22			/* SMBBusy */
+#define	SMB_CSR_SPEEDUP				BIT_21			/* SMBUS Timer SpeedUp */
+#define	SMB_CSR_ALERT				BIT_20			/* SMBALERT */
+#define	SMB_CSR_TX_CLR				BIT_19			/* SMBTxCLR */
+#define	SMB_CSR_TX					BIT_18			/* SMBTx */
+#define	SMB_CSR_TX_STOP				BIT_17			/* SMBTxSTO */
+#define	SMB_CSR_TX_STRT				BIT_16			/* SMBTxSTA */
+#define	SMB_CSR_RX_DATA_MSK			SHIFT8(0xff)	/* SMBRxData */
+#define	SMB_CSR_RX_DATA_BASE		BIT_8
+#define	SMB_CSR_TX_DATA_MSK			SHIFT0(0xff)	/* SMBTxData */
+#define	SMB_CSR_TX_DATA_BASE		BIT_0
+
+/*	CPU_WDOG			0x0E48	Watchdog Register */
+#define	CPU_WDOG_MSK		SHIFT0(0xffffffff)	/* Watchdog */
+#define	CPU_WDOG_BASE		BIT_0
+
+/*	CPU_CNTR			0x0E4C	Counter Register */
+#define	CPU_CNTR_MSK		SHIFT0(0xffffffff)	/* Counter */
+#define	CPU_CNTR_BASE		BIT_0
+
+/*	CPU_TIM				0x0E50	Timer Compare Register */
+#define	CPU_TIM_MSK			SHIFT0(0xffffffff)	/* Timer Compare */
+#define	CPU_TIM_BASE		BIT_0
+
+/*	CPU_AHB_ADDR		0x0E54	CPU AHB Debug Register */
+#define	CPU_AHB_ADDR_MSK		SHIFT0(0xffffffff)	/* Probe AHB address */
+#define	CPU_AHB_ADDR_BASE		BIT_0
+
+/*	CPU_AHB_WDATA		0x0E58	CPU AHB Debug Register */
+#define	CPU_AHB_WDATA_MSK		SHIFT0(0xffffffff)	/* Probe AHB wdata */
+#define	CPU_AHB_WDATA_BASE		BIT_0
+
+/*	CPU_AHB_RDATA		0x0E5C	CPU AHB Debug Register */
+#define	CPU_AHB_RDATA_MSK		SHIFT0(0xffffffff)	/* Probe AHB rdata */
+#define	CPU_AHB_RDATA_BASE		BIT_0
+
+/*	HCU_MAP_BASE		0x0E60	Reset Mapping Base */
+#define	HCU_MAP_BASE_MSK				SHIFT12(0xfffff)	/* MAPBASE */
+#define	HCU_MAP_BASE_BASE				BIT_12
+/*		Bit(s) HCU_MAP_BASE_RSRV_11_0 reserved */
+
+/*	CPU_AHB_CTRL		0x0E64	CPU AHB Debug Register */
+/* Embedded CPU SRAM Write setting */
+#define	CPU_AHB_CTRL_SRAM_WTC1				BIT_31			
+#define	CPU_AHB_CTRL_TDO					BIT_30			/* tdo */
+#define	CPU_AHB_CTRL_TMS					BIT_29			/* tms */
+#define	CPU_AHB_CTRL_TDI					BIT_28			/* tdi */
+#define	CPU_AHB_CTRL_TRST					BIT_27			/* trst */
+#define	CPU_AHB_CTRL_TCLK					BIT_26			/* tclk */
+#define	CPU_AHB_CTRL_SET_JTAG_TEST_MSK		SHIFT24(0x3)	/* CPU's JTAG testmode */
+#define	CPU_AHB_CTRL_SET_JTAG_TEST_BASE		BIT_24
+/* Embedded CPU SRAM Read setting */
+#define	CPU_AHB_CTRL_SRAM_RTC1				BIT_23			
+/* Embedded CPU SRAM Write setting */
+#define	CPU_AHB_CTRL_SRAM_WTC2_MSK			SHIFT21(0x3)	
+#define	CPU_AHB_CTRL_SRAM_WTC2_BASE			BIT_21
+/*		Bit(s) CPU_AHB_CTRL_RSRV_ reserved */
+#define	CPU_AHB_CTRL_FCE_HRESP_MSK			SHIFT18(0x3)	/* Force AHB HRESP */
+#define	CPU_AHB_CTRL_FCE_HRESP_BASE			BIT_18
+#define	CPU_AHB_CTRL_FCE_HRDY				BIT_17			/* Force AHB HREADY */
+/* Enable force AHB response */
+#define	CPU_AHB_CTRL_FCE_RESP_EN			BIT_16			
+/* Embedded CPU SRAM read setting */
+#define	CPU_AHB_CTRL_SRAM_RTC2_MSK			SHIFT14(0x3)	
+#define	CPU_AHB_CTRL_SRAM_RTC2_BASE			BIT_14
+/*		Bit(s) CPU_AHB_CTRL_RSRV_ reserved */
+#define	CPU_AHB_CTRL_PRB_HBURST_MSK			SHIFT10(0x7)	/* Probe AHB HBURST */
+#define	CPU_AHB_CTRL_PRB_HBURST_BASE		BIT_10
+#define	CPU_AHB_CTRL_PRB_HSIZE_MSK			SHIFT7(0x7)		/* Probe AHB HSIZE */
+#define	CPU_AHB_CTRL_PRB_HSIZE_BASE			BIT_7
+#define	CPU_AHB_CTRL_PRB_HTRANS_MSK			SHIFT5(0x3)		/* Probe AHB HTRANS */
+#define	CPU_AHB_CTRL_PRB_HTRANS_BASE		BIT_5
+#define	CPU_AHB_CTRL_PRB_HBUSREQ			BIT_4			/* Probe AHB HBUSREQ */
+#define	CPU_AHB_CTRL_PRB_HRESP_MSK			SHIFT2(0x3)		/* Probe AHB HRESP */
+#define	CPU_AHB_CTRL_PRB_HRESP_BASE			BIT_2
+#define	CPU_AHB_CTRL_PRB_HRDY				BIT_1			/* Probe AHB HREADY */
+#define	CPU_AHB_CTRL_PRB_HCLK				BIT_0			/* Probe AHB HCLK */
+
+/*	HCU_CCSR			0x0E68	CPU Control and Status Register */
+/*		Bit(s) HCU_CCSR_RSRV_3_0 reserved */
+#define	HCU_CCSR_SMBALERT_MONITOR			BIT_27			/* SMBALERT pin monitor */
+#define	HCU_CCSR_CPU_SLEEP					BIT_26			/* CPU sleep status */
+/* Clock Stretching Timeout */
+#define	HCU_CCSR_CS_TO						BIT_25			
+#define	HCU_CCSR_WDOG						BIT_24			/* Watchdog Reset */
+/*		Bit(s) HCU_CCSR_RSRV_5_0 reserved */
+#define	HCU_CCSR_CLR_IRQ_HOST				BIT_17			/* Clear IRQ_HOST */
+#define	HCU_CCSR_SET_IRQ_HCU				BIT_16			/* Set IRQ_HCU */
+/*		Bit(s) HCU_CCSR_RSRV_3_0 reserved */
+#define	HCU_CCSR_ARM_MRVL_ID				BIT_11			/* ARM MRVL ID */
+/* Enable ARM ITCM after CPU reset */
+#define	HCU_CCSR_EN_ARM_ITCM				BIT_10			
+#define	HCU_CCSR_AHB_RST					BIT_9			/* Reset AHB bridge */
+#define	HCU_CCSR_CPU_RST_MODE				BIT_8			/* CPU Reset Mode */
+/*		Bit(s) HCU_CCSR_RSRV_1_0 reserved */
+/* Enable Sync datapath inside AHB bridge */
+#define	HCU_CCSR_SET_SYNC_CPU				BIT_5			
+#define	HCU_CCSR_CPU_CLK_DIVIDE_MSK			SHIFT3(0x3)		/* CPU Clock Divide */
+#define	HCU_CCSR_CPU_CLK_DIVIDE_BASE		BIT_3
+#define	HCU_CCSR_OS_PRSNT					BIT_2			/* ASF OS Present */
+/* Microcontroller State */
+#define	HCU_CCSR_UC_STATE_MSK				SHIFT0(0x3)		
+#define	HCU_CCSR_UC_STATE_BASE				BIT_0
+
+/*
+ * manually defined, needed, do not remove (MA)
+ */
+#define HCU_CCSR_ASF_RESET					0
+#define HCU_CCSR_ASF_RUNNING				BIT_0
+#define HCU_CCSR_ASF_HALTED					BIT_1
+
+/*	HCU_HCSR			0x0E6C	Host Control and Status Register */
+/*		Bit(s) HCU_HCSR_RSRV_14_0 reserved */
+#define	HCU_HCSR_SET_IRQ_CPU		BIT_16			/* Set IRQ_CPU */
+/*		Bit(s) HCU_HCSR_RSRV_13_0 reserved */
+#define	HCU_HCSR_CLR_IRQ_HCU		BIT_1			/* Clear IRQ_HCU */
+#define	HCU_HCSR_SET_IRQ_HOST		BIT_0			/* Set IRQ_HOST */
+
+/*	HCU_DATA1			0x0E70	Data Register 1 */
+#define	HCU_DATA1_MSK		SHIFT0(0xffffffff)	/* DATA1 */
+#define	HCU_DATA1_BASE		BIT_0
+
+/*	HCU_DATA2			0x0E74	Data Register 2 */
+#define	HCU_DATA2_MSK		SHIFT0(0xffffffff)	/* DATA2 */
+#define	HCU_DATA2_BASE		BIT_0
+
+/*	HCU_DATA3			0x0E78	Data Register 3 */
+#define	HCU_DATA3_MSK		SHIFT0(0xffffffff)	/* DATA3 */
+#define	HCU_DATA3_BASE		BIT_0
+
+/*	HCU_DATA4			0x0E7C	Data Register 4 */
+#define	HCU_DATA4_MSK		SHIFT0(0xffffffff)	/* DATA4 */
+#define	HCU_DATA4_BASE		BIT_0
+
+/*	STAT_CTRL			0x0E80	Status BMU Control Register */
+/*		Bit(s) STAT_CTRL_RSRV_31_19 reserved */
+/* Master Request Loopback Test On */
+#define	STAT_CTRL_MST_REQ_LPBK_ON		BIT_18			
+/* Master Request Loopback Test Off */
+#define	STAT_CTRL_MST_REQ_LPBK_OFF		BIT_17			
+/* Master Request Loopback Step */
+#define	STAT_CTRL_MST_REQ_LPBK_STEP		BIT_16			
+/*		Bit(s) STAT_CTRL_RSRV_15 reserved */
+/* FIFO Read Pointer Test On */
+#define	STAT_CTRL_RPTR_TEST_ON			BIT_14			
+/* FIFO Read Pointer Test Off */
+#define	STAT_CTRL_RPTR_TEST_OFF			BIT_13			
+#define	STAT_CTRL_RPTR_TEST_STEP		BIT_12			/* FIFO Read Pointer Step */
+/*		Bit(s) STAT_CTRL_RSRV_11 reserved */
+/* FIFO Write Pointer Test On */
+#define	STAT_CTRL_WPTR_TEST_ON			BIT_10			
+/* FIFO Write Pointer Test Off */
+#define	STAT_CTRL_WPTR_TEST_OFF			BIT_9			
+#define	STAT_CTRL_WPTR_TEST_STEP		BIT_8			/* FIFO Write Pointer Step */
+/*		Bit(s) STAT_CTRL_RSRV_7_5 reserved */
+#define	STAT_CTRL_CLR_IRQ_STAT			BIT_4			/* Clear IRQ Status BMU */
+#define	STAT_CTRL_OP_ON					BIT_3			/* Operational On */
+#define	STAT_CTRL_OP_OFF				BIT_2			/* Operational Off */
+#define	STAT_CTRL_ENA					BIT_1			/* Enable */
+#define	STAT_CTRL_RST					BIT_0			/* Reset */
+
+/*	STAT_LAST_IDX		0x0E84	Last Index Register */
+/*		Bit(s) STAT_LAST_IDX_RSRV_31_12 reserved */
+#define	STAT_LAST_IDX_MSK					SHIFT2(0x3ff)		/* Last Index */
+#define	STAT_LAST_IDX_BASE					2
+#define	STAT_LAST_IDX_VAL_FIX_MSK			SHIFT0(0x3)			/* Last Index Fix */
+#define	STAT_LAST_IDX_VAL_FIX_BASE			0
+
+/*	STAT_LADR_LO		0x0E88	List Start Address Lower Register */
+/* List Start Address Lo */
+#define	STAT_LADR_LO_MSK				SHIFT5(0x7ffffff)	
+#define	STAT_LADR_LO_BASE				5
+/* List Start Address Lo Fix */
+#define	STAT_LADR_LO_VAL_FIX_MSK		SHIFT0(0x1f)		
+#define	STAT_LADR_LO_VAL_FIX_BASE		0
+
+/*	STAT_LADR_HI		0x0E8C	List Start Address Upper Register */
+#define	STAT_LADR_HI_MSK		SHIFT0(0xffffffff)	/* List Start Address Hi */
+#define	STAT_LADR_HI_BASE		0
+
+/*	STAT_TXA_REP		0x0E90	TXA Report Index Register */
+/*		Bit(s) STAT_TXA_REP_RSRV_15_12 reserved */
+#define	STAT_TXA_REP_MSK					SHIFT0(0xfffU)	/* TXA Report Index */
+#define	STAT_TXA_REP_BASE					0
+
+/*	STAT_TXTH			0x0E98	TX Index Threshold Register */
+/*		Bit(s) STAT_TXTH_RSRV_15_12 reserved */
+#define	STAT_TXTH_MSK					SHIFT0(0xfffU)	/* TX Index Threshold */
+#define	STAT_TXTH_BASE					0
+
+/*	STAT_PUT			0x0E9C	Put Index Register */
+/*		Bit(s) STAT_PUT_RSRV_31_12 reserved */
+#define	STAT_PUT_MSK					SHIFT0(0xfff)		/* Put Index */
+#define	STAT_PUT_BASE					0
+
+/*	STAT_FIFO_WPTR		0x0EA0	FIFO Write Pointer Register */
+/*		Bit(s) STAT_FIFO_WPTR_RSRV_31_5 reserved */
+/* FIFO Write Pointer */
+#define	STAT_FIFO_WPTR_MSK					SHIFT0(0x1f)		
+#define	STAT_FIFO_WPTR_BASE					0
+
+/*	STAT_FIFO_RPTR		0x0EA4	FIFO Read Pointer Register */
+/*		Bit(s) STAT_FIFO_RPTR_RSRV_31_21 reserved */
+#define	STAT_FIFO_RPTR_WSPTR_MSK			SHIFT16(0x1f)	/* FIFO Rd Shadow Ptr */
+#define	STAT_FIFO_RPTR_WSPTR_BASE			16
+/*		Bit(s) STAT_FIFO_RPTR_RSRV_15_5 reserved */
+#define	STAT_FIFO_RPTR_MSK					SHIFT0(0x1f)	/* FIFO Read Pointer */
+#define	STAT_FIFO_RPTR_BASE					0
+
+/*	STAT_FIFO_LEV		0x0EA8	FIFO Level Register */
+/*		Bit(s) STAT_FIFO_LEV_RSRV_31_21 reserved */
+#define	STAT_FIFO_LEV_SLEV_MSK				SHIFT16(0x1f)	/* FIFO Shadow Level */
+#define	STAT_FIFO_LEV_SLEV_BASE				16
+/*		Bit(s) STAT_FIFO_LEV_RSRV_15_5 reserved */
+#define	STAT_FIFO_LEV_MSK					SHIFT0(0x1f)	/* FIFO Level */
+#define	STAT_FIFO_LEV_BASE					0
+
+/*	STAT_FIFO_WM		0x0EAC	FIFO Watermark Register */
+/*		Bit(s) STAT_FIFO_WM_RSRV_7_5 reserved */
+#define	STAT_FIFO_WM_MSK				SHIFT0(0x1fU)	/* FIFO Watermark */
+#define	STAT_FIFO_WM_BASE				0
+
+/*	STAT_FIFO_WM_ISR	0x0EAD	FIFO ISR Watermark Register */
+/*		Bit(s) STAT_FIFO_WM_ISR_RSRV_7_5 reserved */
+#define	STAT_FIFO_WM_ISR_MSK				SHIFT0(0x1fU)	/* FIFO ISR Watermark */
+#define	STAT_FIFO_WM_ISR_BASE				0
+
+/*	LEV_TIM_INIT		0x0EB0	Level Timer Init Value Register */
+#define	LEV_TIM_INIT_MSK		SHIFT0(0xffffffff)	/* Level Timer Init Value */
+#define	LEV_TIM_INIT_BASE		0
+
+/*	LEV_TIM_CNT			0x0EB4	Level Timer Counter Register */
+#define	LEV_TIM_CNT_MSK			SHIFT0(0xffffffff)	/* Level Timer */
+#define	LEV_TIM_CNT_BASE		0
+
+/*	LEV_TIM_TCTL		0x0EB8	Level Timer Control/Test Register */
+/*		Bit(s) LEV_TIM_TCTL_RSRV_31_11 reserved */
+/* Level Timer Test On */
+#define	LEV_TIM_TCTL_TST_ON					BIT_10				
+/* Level Timer Test Off */
+#define	LEV_TIM_TCTL_TST_OFF				BIT_9				
+#define	LEV_TIM_TCTL_STEP					BIT_8				/* Level Timer Step */
+/*		Bit(s) LEV_TIM_TCTL_RSRV_7_3 reserved */
+/* Level Timer Start */
+#define	LEV_TIM_TCTL_STRT					BIT_2				
+#define	LEV_TIM_TCTL_STOP					BIT_1				/* Level Timer Stop */
+/*		Bit(s) LEV_TIM_TCTL_RSRV_0 reserved */
+
+/*	TX_TIM_INIT			0x0EC0	TX TImer Init Value Register */
+#define	TX_TIM_INIT_MSK			SHIFT0(0xffffffff)	/* TX Timer Init Value */
+#define	TX_TIM_INIT_BASE		0
+
+/*	TX_TIM_CNT			0x0EC4	TX Timer Counter Register */
+#define	TX_TIM_CNT_MSK		SHIFT0(0xffffffff)	/* TX Timer */
+#define	TX_TIM_CNT_BASE		0
+
+/*	TX_TIM_TCTL			0x0EC8	TX Timer Control/Test Register */
+/*		Bit(s) TX_TIM_TCTL_RSRV_31_11 reserved */
+#define	TX_TIM_TCTL_TST_ON				BIT_10				/* TX Timer Test On */
+#define	TX_TIM_TCTL_TST_OFF				BIT_9				/* TX Timer Test Off */
+#define	TX_TIM_TCTL_STEP				BIT_8				/* TX Timer Step */
+/*		Bit(s) TX_TIM_TCTL_RSRV_1_0 reserved */
+/* Deviation 5.4 fix enable */
+#define	TX_TIM_TCTL_ON					BIT_5				
+/* Deviation 5.4 fix enable */
+#define	TX_TIM_TCTL_OFF					BIT_4				
+/*		Bit(s) TX_TIM_TCTL_RSRV_3 reserved */
+#define	TX_TIM_TCTL_STRT				BIT_2				/* TX Timer Start */
+#define	TX_TIM_TCTL_STOP				BIT_1				/* TX Timer Stop */
+/*		Bit(s) TX_TIM_TCTL_RSRV_0 reserved */
+
+/*	ISR_TIM_INIT		0x0ED0	ISR Timer Init Value Register */
+#define	ISR_TIM_INIT_MSK		SHIFT0(0xffffffff)	/* ISR Timer Init Value */
+#define	ISR_TIM_INIT_BASE		0
+
+/*	ISR_TIM_CNT			0x0ED4	ISR Timer Counter Register */
+#define	ISR_TIM_CNT_MSK			SHIFT0(0xffffffff)	/* ISR Timer */
+#define	ISR_TIM_CNT_BASE		0
+
+/*	ISR_TIM_TCTL		0x0ED8	ISR Timer Control/Test Register */
+/*		Bit(s) ISR_TIM_TCTL_RSRV_31_11 reserved */
+/* ISR Timer Test On */
+#define	ISR_TIM_TCTL_TST_ON					BIT_10				
+/* ISR Timer Test Off */
+#define	ISR_TIM_TCTL_TST_OFF				BIT_9				
+#define	ISR_TIM_TCTL_STEP					BIT_8				/* ISR Timer Step */
+/*		Bit(s) ISR_TIM_TCTL_RSRV_7_3 reserved */
+#define	ISR_TIM_TCTL_STRT					BIT_2				/* ISR Timer Start */
+#define	ISR_TIM_TCTL_STOP					BIT_1				/* ISR Timer Stop */
+/*		Bit(s) ISR_TIM_TCTL_RSRV_0 reserved */
+
+/*	MAC_CTRL			0x0F00	MAC Control Registers */
+#define	MAC_CTRL_MAC_SEC_RST			BIT_15S			/* MAC SEC RST */
+#define	MAC_CTRL_MAC_SEC_RST_OFF		BIT_14S			/* MAC SEC RSt OFF */
+#define	MAC_CTRL_BYP_MACSECRX_ON		BIT_13S			/* Bypass macsec RX */
+#define	MAC_CTRL_BYP_MACSECRX_OFF		BIT_12S			/* Bypass macsec RX off */
+#define	MAC_CTRL_BYP_MACSECTX_ON		BIT_11S			/* Bypass macsec TX */
+#define	MAC_CTRL_BYP_MACSECTX_OFF		BIT_10S			/* Bypass macsec TX off */
+#define	MAC_CTRL_BYP_RETR_ON			BIT_9S			/* Bypass retransmit fifo */
+#define	MAC_CTRL_BYP_RETR_OFF			BIT_8S			/* Bypass retransmit fifo off */
+#define	MAC_CTRL_BURST_ON				BIT_7S			/* En Burstmode On */
+#define	MAC_CTRL_BURST_OFF				BIT_6S			/* En Burstmode Off */
+#define	MAC_CTRL_LPBK_ON				BIT_5S			/* Loopback On */
+#define	MAC_CTRL_LPBK_OFF				BIT_4S			/* Loopback Off */
+#define	MAC_CTRL_PAUSE_ON				BIT_3S			/* En Pause On */
+#define	MAC_CTRL_PAUSE_OFF				BIT_2S			/* En Pause Off */
+#define	MAC_CTRL_RST_CLR				BIT_1S			/* GMAC Reset Clear */
+#define	MAC_CTRL_RST_SET				BIT_0S			/* GMAC Reset Set */
+
+/*	PHY_CFG				0x0F04	PHY Config Register, loaded from external
+ *								memory
+ */
+#define	PHY_CFG_STAT_MSK				SHIFT24(0xff)	/* PHY Status */
+#define	PHY_CFG_STAT_BASE				24
+/* Internal Regulator 2.5 Power Down Enable */
+#define	PHY_CFG_INT_REG_PD_ENA			BIT_23			
+#define	PHY_CFG_TEST					BIT_22			/* Testmode */
+#define	PHY_CFG_REG18_PD				BIT_21			/* Reg18 Power Down */
+#define	PHY_CFG_REG12_SEL_MSK			SHIFT19(0x3)	/* Reg12 Sel */
+#define	PHY_CFG_REG12_SEL_BASE			BIT_19
+#define	PHY_CFG_REG18_SEL_MSK			SHIFT17(0x3)	/* Reg18 Sel */
+#define	PHY_CFG_REG18_SEL_BASE			BIT_17
+#define	PHY_CFG_SPI_LOCK				BIT_16			/* SPI Lock */
+#define	PHY_CFG_CFG_LED_MUX_MSK			SHIFT14(0x3)	/* GPHY Config for LED Mux */
+#define	PHY_CFG_CFG_LED_MUX_BASE		BIT_14
+/* GPHY Config for Int Polarity */
+#define	PHY_CFG_CFG_POL					BIT_13			
+/* GPHY Config for Energy Detect */
+#define	PHY_CFG_CFG_ERG_DET				BIT_12			
+#define	PHY_CFG_CFG_1000				BIT_11			/* GPHY Config for 1000M/HD */
+/* GPHY Config for Master/Slave */
+#define	PHY_CFG_CFG_MST_SLV				BIT_10			
+/* GPHY Config for Pause Enable */
+#define	PHY_CFG_CFG_PAUSE				BIT_9			
+#define	PHY_CFG_LED_CFG_MSK				SHIFT6(0x7)		/* GPHY LED Config */
+#define	PHY_CFG_LED_CFG_BASE			BIT_6
+/*		Bit(s) PHY_CFG_RSRV_3_0 reserved */
+#define	PHY_CFG_RST_CLR					BIT_1			/* PHY Reset Clear */
+#define	PHY_CFG_RST_SET					BIT_0			/* PHY Reset Set */
+
+/*	MAC_ISRC			0x0F08	MAC Interrupt Source Register */
+/*		Bit(s) MAC_ISRC_RSRV_31_6 reserved */
+/* Receive Counter Overflow Interrupt */
+#define	MAC_ISRC_RX_CNT_OF			BIT_5				
+/* Transmit Counter Overflow Interrupt */
+#define	MAC_ISRC_TX_CNT_OF			BIT_4				
+#define	MAC_ISRC_TX_UR				BIT_3				/* Transmit FIFO Underrun */
+/* Frame Transmission Complete */
+#define	MAC_ISRC_TX_OK				BIT_2				
+#define	MAC_ISRC_RX_OF				BIT_1				/* Receive FIFO Overrun */
+#define	MAC_ISRC_RX_OK				BIT_0				/* Frame Reception Complete */
+
+/*	MAC_IMSK			0x0F0C	MAC Interrupt Mask Register */
+/*		Bit(s) MAC_IMSK_RSRV_31_6 reserved */
+/* En IRQ Receive Counter Overflow Interrupt */
+#define	MAC_IMSK_RX_CNT_OF			BIT_5				
+/* En IRQ Transmit Counter Overflow Interrupt */
+#define	MAC_IMSK_TX_CNT_OF			BIT_4				
+/* En IRQ Transmit FIFO Underrun */
+#define	MAC_IMSK_TX_UR				BIT_3				
+/* En IRQ Frame Transmission Complete */
+#define	MAC_IMSK_TX_OK				BIT_2				
+/* En IRQ Receive FIFO Overrun */
+#define	MAC_IMSK_RX_OF				BIT_1				
+/* En IRQ Frame Reception Complete */
+#define	MAC_IMSK_RX_OK				BIT_0				
+
+/*	LINK_CTRL			0x0F10	Link Control Register */
+/*		Bit(s) LINK_CTRL_RSRV_15_2 reserved */
+#define	LINK_CTRL_RST_CLR				BIT_1S			/* Link Reset Clear */
+#define	LINK_CTRL_RST_SET				BIT_0S			/* Link Reset Set */
+
+/*	WOL_CSR				0x0F20	WOL Control/Status Register */
+#define	WOL_CSR_LC_STAT			BIT_15S	/* Link Up Status */
+#define	WOL_CSR_MP_STAT			BIT_14S	/* Magic Pattern Status */
+#define	WOL_CSR_WF_STAT			BIT_13S	/* Wake up Frame Status */
+#define	WOL_CSR_CLR_RSLT		BIT_12S	/* Clear Match Result */
+#define	WOL_CSR_LC_PME_ENA		BIT_11S	/* Enable PME on Link Up */
+#define	WOL_CSR_LC_PME_DIS		BIT_10S	/* Disable PME on Link Up */
+#define	WOL_CSR_MP_PME_ENA		BIT_9S	/* Enable PME on Magic Pattern */
+#define	WOL_CSR_MP_PME_DIS		BIT_8S	/* Disable PME on Magic Pattern */
+#define	WOL_CSR_WF_PME_ENA		BIT_7S	/* Enable PME on Wake up Frame */
+#define	WOL_CSR_WF_PME_DIS		BIT_6S	/* Disable PME on Wake up Frame */
+#define	WOL_CSR_LC_ENA			BIT_5S	/* Enable Link Up Unit */
+#define	WOL_CSR_LC_DIS			BIT_4S	/* Disable Link Up Unit */
+#define	WOL_CSR_MP_ENA			BIT_3S	/* Enable Magic Pattern Unit */
+#define	WOL_CSR_MP_DIS			BIT_2S	/* Disable Magic Pattern Unit */
+#define	WOL_CSR_WF_ENA			BIT_1S	/* Enable Pattern Match Unit */
+#define	WOL_CSR_WF_DIS			BIT_0S	/* Disable Pattern Match Unit */
+
+/*	WOL_MCTRL			0x0F22	Match Control Register */
+/*		Bit(s) WOL_MCTRL_RSRV_15_9 reserved */
+#define	WOL_MCTRL_P8_ENA			BIT_8S			/* Pattern 8 Enable */
+#define	WOL_MCTRL_P7_ENA			BIT_7S			/* Pattern 7 Enable */
+#define	WOL_MCTRL_P6_ENA			BIT_6S			/* Pattern 6 Enable */
+#define	WOL_MCTRL_P5_ENA			BIT_5S			/* Pattern 5 Enable */
+#define	WOL_MCTRL_P4_ENA			BIT_4S			/* Pattern 4 Enable */
+#define	WOL_MCTRL_P3_ENA			BIT_3S			/* Pattern 3 Enable */
+#define	WOL_MCTRL_P2_ENA			BIT_2S			/* Pattern 2 Enable */
+#define	WOL_MCTRL_P1_ENA			BIT_1S			/* Pattern 1 Enable */
+#define	WOL_MCTRL_P0_ENA			BIT_0S			/* Pattern 0 Enable */
+
+/*	WOL_MADDR_LO		0x0F24	MAC Address Register Low Register */
+#define	WOL_MADDR_LO_MAC_3_MSK		SHIFT24(0xff)	/* MAC<3> */
+#define	WOL_MADDR_LO_MAC_3_BASE		24
+#define	WOL_MADDR_LO_MAC_2_MSK		SHIFT16(0xff)	/* MAC<2> */
+#define	WOL_MADDR_LO_MAC_2_BASE		16
+#define	WOL_MADDR_LO_MAC_1_MSK		SHIFT8(0xff)	/* MAC<1> */
+#define	WOL_MADDR_LO_MAC_1_BASE		8
+#define	WOL_MADDR_LO_MAC_0_MSK		SHIFT0(0xff)	/* MAC<0> */
+#define	WOL_MADDR_LO_MAC_0_BASE		0
+
+/*	WOL_MADDR_HI		0x0F28	MAC Address Register High Register */
+#define	WOL_MADDR_HI_MAC_5_MSK		SHIFT8(0xffU)	/* MAC<5> */
+#define	WOL_MADDR_HI_MAC_5_BASE		8
+#define	WOL_MADDR_HI_MAC_4_MSK		SHIFT0(0xffU)	/* MAC<4> */
+#define	WOL_MADDR_HI_MAC_4_BASE		0
+
+/*	WOL_PME_MEN			0x0F2A	PME Match Enable Register */
+#define	WOL_PME_MEN_FRC_PME				BIT_15S			/* Force PME */
+/*		Bit(s) WOL_PME_MEN_RSRV_14_6 reserved */
+#define	WOL_PME_MEN_P8_PME_ENA			BIT_8S			/* PME 8 Enable */
+#define	WOL_PME_MEN_P7_PME_ENA			BIT_7S			/* PME 7 Enable */
+#define	WOL_PME_MEN_P6_PME_ENA			BIT_6S			/* PME 6 Enable */
+#define	WOL_PME_MEN_P5_PME_ENA			BIT_5S			/* PME 5 Enable */
+#define	WOL_PME_MEN_P4_PME_ENA			BIT_4S			/* PME 4 Enable */
+#define	WOL_PME_MEN_P3_PME_ENA			BIT_3S			/* PME 3 Enable */
+#define	WOL_PME_MEN_P2_PME_ENA			BIT_2S			/* PME 2 Enable */
+#define	WOL_PME_MEN_P1_PME_ENA			BIT_1S			/* PME 1 Enable */
+#define	WOL_PME_MEN_P0_PME_ENA			BIT_0S			/* PME 0 Enable */
+
+/*	WOL_ASF_MEN			0x0F2C	ASF Match Enable Register */
+/*		Bit(s) WOL_ASF_MEN_RSRV_15_9 reserved */
+#define	WOL_ASF_MEN_P8_ASF_ENA			BIT_8S			/* ASF 8 Enable */
+#define	WOL_ASF_MEN_P7_ASF_ENA			BIT_7S			/* ASF 7 Enable */
+#define	WOL_ASF_MEN_P6_ASF_ENA			BIT_6S			/* ASF 6 Enable */
+#define	WOL_ASF_MEN_P5_ASF_ENA			BIT_5S			/* ASF 5 Enable */
+#define	WOL_ASF_MEN_P4_ASF_ENA			BIT_4S			/* ASF 4 Enable */
+#define	WOL_ASF_MEN_P3_ASF_ENA			BIT_3S			/* ASF 3 Enable */
+#define	WOL_ASF_MEN_P2_ASF_ENA			BIT_2S			/* ASF 2 Enable */
+#define	WOL_ASF_MEN_P1_ASF_ENA			BIT_1S			/* ASF 1 Enable */
+#define	WOL_ASF_MEN_P0_ASF_ENA			BIT_0S			/* ASF 0 Enable */
+
+/*	WOL_MRSL			0x0F2E	Match Result Register */
+/*		Bit(s) WOL_MRSL_RSRV_15_9 reserved */
+#define	WOL_MRSL_P8_MATCH			BIT_8S			/* Pattern 8 Match */
+#define	WOL_MRSL_P7_MATCH			BIT_7S			/* Pattern 7 Match */
+#define	WOL_MRSL_P6_MATCH			BIT_6S			/* Pattern 6 Match */
+#define	WOL_MRSL_P5_MATCH			BIT_5S			/* Pattern 5 Match */
+#define	WOL_MRSL_P4_MATCH			BIT_4S			/* Pattern 4 Match */
+#define	WOL_MRSL_P3_MATCH			BIT_3S			/* Pattern 3 Match */
+#define	WOL_MRSL_P2_MATCH			BIT_2S			/* Pattern 2 Match */
+#define	WOL_MRSL_P1_MATCH			BIT_1S			/* Pattern 1 Match */
+#define	WOL_MRSL_P0_MATCH			BIT_0S			/* Pattern 0 Match */
+
+/*	WOL_PLEN0			0x0F30	Pattern Length Register 0 (0-3) */
+/*		Bit(s) WOL_PLEN0_RSRV_31 reserved */
+#define	WOL_PLEN0_P3_LEN_MSK		SHIFT24(0x7f)	/* Pattern 3 Length */
+#define	WOL_PLEN0_P3_LEN_BASE		24
+/*		Bit(s) WOL_PLEN0_RSRV_23 reserved */
+#define	WOL_PLEN0_P2_LEN_MSK		SHIFT16(0x7f)	/* Pattern 2 Length */
+#define	WOL_PLEN0_P2_LEN_BASE		16
+/*		Bit(s) WOL_PLEN0_RSRV_15 reserved */
+#define	WOL_PLEN0_P1_LEN_MSK		SHIFT8(0x7f)	/* Pattern 1 Length */
+#define	WOL_PLEN0_P1_LEN_BASE		8
+/*		Bit(s) WOL_PLEN0_RSRV_7 reserved */
+#define	WOL_PLEN0_P0_LEN_MSK		SHIFT0(0x7f)	/* Pattern 0 Length */
+#define	WOL_PLEN0_P0_LEN_BASE		0
+
+/*	WOL_PLEN1			0x0F34	Pattern Length Register 1 (4-7) */
+/*		Bit(s) WOL_PLEN1_RSRV_31_15 reserved */
+#define	WOL_PLEN1_P5_LEN_MSK			SHIFT8(0x7f)		/* Pattern 5 Length */
+#define	WOL_PLEN1_P5_LEN_BASE			8
+/*		Bit(s) WOL_PLEN1_RSRV_7 reserved */
+#define	WOL_PLEN1_P4_LEN_MSK			SHIFT0(0x7f)		/* Pattern 4 Length */
+#define	WOL_PLEN1_P4_LEN_BASE			0
+
+/*	WOL_PLEN2			0x0F38	Pattern Length Register 2 (8) */
+/*		Bit(s) WOL_PLEN2_RSRV_31_0 reserved */
+
+/*	WOL_PCNT0			0x0F40	Pattern Counter Register 0 (0-3) */
+/*		Bit(s) WOL_PCNT0_RSRV_31 reserved */
+#define	WOL_PCNT0_P3_CNTR_MSK		SHIFT24(0x7f)	/* Pattern 3 Counter */
+#define	WOL_PCNT0_P3_CNTR_BASE		24
+/*		Bit(s) WOL_PCNT0_RSRV_23 reserved */
+#define	WOL_PCNT0_P2_CNTR_MSK		SHIFT16(0x7f)	/* Pattern 2 Counter */
+#define	WOL_PCNT0_P2_CNTR_BASE		16
+/*		Bit(s) WOL_PCNT0_RSRV_15 reserved */
+#define	WOL_PCNT0_P1_CNTR_MSK		SHIFT8(0x7f)	/* Pattern 1 Counter */
+#define	WOL_PCNT0_P1_CNTR_BASE		8
+/*		Bit(s) WOL_PCNT0_RSRV_7 reserved */
+#define	WOL_PCNT0_P0_CNTR_MSK		SHIFT0(0x7f)	/* Pattern 0 Counter */
+#define	WOL_PCNT0_P0_CNTR_BASE		0
+
+/*	WOL_PCNT1			0x0F44	Pattern Counter Register 1 (4-7) */
+/*		Bit(s) WOL_PCNT1_RSRV_31_16 reserved */
+/*		Bit(s) WOL_PCNT1_RSRV_15 reserved */
+#define	WOL_PCNT1_P7_CNTR_BASE		BIT_24
+/*		Bit(s) WOL_PCNT1_RSRV_ reserved */
+#define	WOL_PCNT1_P6_CNTR_MSK		SHIFT16(0x7f)	/* Pattern 6 Counter */
+#define	WOL_PCNT1_P6_CNTR_BASE		BIT_16
+/*		Bit(s) WOL_PCNT1_RSRV_ reserved */
+#define	WOL_PCNT1_P5_CNTR_MSK			SHIFT8(0x7f)	/* Pattern 5 Counter */
+#define	WOL_PCNT1_P5_CNTR_BASE			8
+/*		Bit(s) WOL_PCNT1_RSRV_7 reserved */
+#define	WOL_PCNT1_P4_CNTR_MSK			SHIFT0(0x7f)	/* Pattern 4 Counter */
+#define	WOL_PCNT1_P4_CNTR_BASE			0
+
+/*	WOL_PCNT2			0x0F48	Pattern Counter Register 2 (8) */
+/*		Bit(s) WOL_PCNT2_RSRV_31_1 reserved */
+#define	WOL_PCNT2_P8_CNTR_MSK			SHIFT0(0x7f)		/* Pattern 8 Counter */
+#define	WOL_PCNT2_P8_CNTR_BASE			BIT_0
+
+/*	PAT_CSR				0x0F50	Pattern RAM Control/Status Register */
+/*		Bit(s) PAT_CSR_RSRV_31_23 reserved */
+#define	PAT_CSR_RPTR_MSK			SHIFT16(0x7f)	/* Pattern Read Pointer */
+#define	PAT_CSR_RPTR_BASE			16
+/*		Bit(s) PAT_CSR_RSRV_15_1 reserved */
+#define	PAT_CSR_BSEL				BIT_0			/* Pattern RAM Bank Select */
+
+/*	PAT_RAM				0x1000	Pattern RAM Register */
+#define	PAT_RAM_MSK			SHIFT0(0xffffffff)	/* Lower Half qword No. 0 */
+#define	PAT_RAM_BASE		0
+
+/*	THDR0_LO			0x1900	TCP Segmentation Header Register 0 Lo */
+#define	THDR0_LO_MAC_HDR_0_MSK		SHIFT0(0xffffffff)	/* MAC_HDR_0 */
+#define	THDR0_LO_MAC_HDR_0_BASE		0
+
+/*	THDR0_HI			0x1904	TCP Segmentation Header Register 0 Hi */
+#define	THDR0_HI_MAC_HDR_1_MSK		SHIFT0(0xffffffff)	/* MAC_HDR_1 */
+#define	THDR0_HI_MAC_HDR_1_BASE		0
+
+/*	THDR1_LO			0x1908	TCP Segmentation Header Register 1 Lo */
+#define	THDR1_LO_MAC_HDR_2_MSK		SHIFT0(0xffffffff)	/* MAC_HDR_2 */
+#define	THDR1_LO_MAC_HDR_2_BASE		0
+
+/*	THDR1_HI			0x190C	TCP Segmentation Header Register 1 Hi */
+#define	THDR1_HI_IP_HDR_0_MSK		SHIFT16(0xffff)	/* IP_HDR_0 */
+#define	THDR1_HI_IP_HDR_0_BASE		16
+#define	THDR1_HI_MAC_HDR_3_MSK		SHIFT0(0xffff)	/* MAC_HDR_3 */
+#define	THDR1_HI_MAC_HDR_3_BASE		0
+
+/*	THDR2_LO			0x1910	TCP Segmentation Header Register 2 Lo */
+#define	THDR2_LO_IP_HDR_1_MSK		SHIFT0(0xffffffff)	/* IP_HDR_1 */
+#define	THDR2_LO_IP_HDR_1_BASE		0
+
+/*	THDR2_HI			0x1914	TCP Segmentation Header Register 2 Hi */
+#define	THDR2_HI_IP_HDR_2_MSK		SHIFT0(0xffffffff)	/* IP_HDR_2 */
+#define	THDR2_HI_IP_HDR_2_BASE		0
+
+/*	THDR3_LO			0x1918	TCP Segmentation Header Register 3 Lo */
+#define	THDR3_LO_IP_HDR_3_MSK		SHIFT0(0xffffffff)	/* IP_HDR_3 */
+#define	THDR3_LO_IP_HDR_3_BASE		0
+
+/*	THDR3_HI			0x191C	TCP Segmentation Header Register 3 Hi */
+#define	THDR3_HI_IP_HDR_4_MSK		SHIFT0(0xffffffff)	/* IP_HDR_4 */
+#define	THDR3_HI_IP_HDR_4_BASE		0
+
+/*	THDR4_LO			0x1920	TCP Segmentation Header Register 4 Lo */
+#define	THDR4_LO_IP_HDR_5_MSK		SHIFT0(0xffffffff)	/* IP_HDR_5 */
+#define	THDR4_LO_IP_HDR_5_BASE		0
+
+/*	THDR4_HI			0x1924	TCP Segmentation Header Register 4 Hi */
+#define	THDR4_HI_IP_HDR_6_MSK		SHIFT0(0xffffffff)	/* IP_HDR_6 */
+#define	THDR4_HI_IP_HDR_6_BASE		0
+
+/*	THDR5_LO			0x1928	TCP Segmentation Header Register 5 Lo */
+#define	THDR5_LO_IP_HDR_7_MSK		SHIFT0(0xffffffff)	/* IP_HDR_7 */
+#define	THDR5_LO_IP_HDR_7_BASE		0
+
+/*	THDR5_HI			0x192C	TCP Segmentation Header Register 5 Hi */
+#define	THDR5_HI_IP_HDR_8_MSK		SHIFT0(0xffffffff)	/* IP_HDR_8 */
+#define	THDR5_HI_IP_HDR_8_BASE		0
+
+/*	THDR6_LO			0x1930	TCP Segmentation Header Register 6 Lo */
+#define	THDR6_LO_IP_HDR_9_MSK		SHIFT0(0xffffffff)	/* IP_HDR_9 */
+#define	THDR6_LO_IP_HDR_9_BASE		0
+
+/*	THDR6_HI			0x1934	TCP Segmentation Header Register 6 Hi */
+#define	THDR6_HI_IP_HDR_10_MSK		SHIFT0(0xffffffff)	/* IP_HDR_10 */
+#define	THDR6_HI_IP_HDR_10_BASE		0
+
+/*	THDR7_LO			0x1938	TCP Segmentation Header Register 7 Lo */
+#define	THDR7_LO_IP_HDR_11_MSK		SHIFT0(0xffffffff)	/* IP_HDR_11 */
+#define	THDR7_LO_IP_HDR_11_BASE		0
+
+/*	THDR7_HI			0x193C	TCP Segmentation Header Register 7 Hi */
+#define	THDR7_HI_IP_HDR_12_MSK		SHIFT0(0xffffffff)	/* IP_HDR_12 */
+#define	THDR7_HI_IP_HDR_12_BASE		0
+
+/*	THDR8_LO			0x1940	TCP Segmentation Header Register 8 Lo */
+#define	THDR8_LO_IP_HDR_13_MSK		SHIFT0(0xffffffff)	/* IP_HDR_13 */
+#define	THDR8_LO_IP_HDR_13_BASE		0
+
+/*	THDR8_HI			0x1944	TCP Segmentation Header Register 8 Hi */
+#define	THDR8_HI_IP_HDR_14_MSK		SHIFT0(0xffffffff)	/* IP_HDR_14 */
+#define	THDR8_HI_IP_HDR_14_BASE		0
+
+/*	THDR9_LO			0x1948	TCP Segmentation Header Register 9 Lo */
+#define	THDR9_LO_IP_HDR_15_MSK		SHIFT0(0xffffffff)	/* IP_HDR_15 */
+#define	THDR9_LO_IP_HDR_15_BASE		0
+
+/*	THDR9_HI			0x194C	TCP Segmentation Header Register 9 Hi */
+#define	THDR9_HI_IP_HDR_16_MSK		SHIFT0(0xffffffff)	/* IP_HDR_16 */
+#define	THDR9_HI_IP_HDR_16_BASE		0
+
+/*	THDR10_LO			0x1950	TCP Segmentation Header Register 10 Lo */
+#define	THDR10_LO_IP_HDR_17_MSK			SHIFT0(0xffffffff)	/* IP_HDR_17 */
+#define	THDR10_LO_IP_HDR_17_BASE		0
+
+/*	THDR10_HI			0x1954	TCP Segmentation Header Register 10 Hi */
+#define	THDR10_HI_IP_HDR_18_MSK			SHIFT0(0xffffffff)	/* IP_HDR_18 */
+#define	THDR10_HI_IP_HDR_18_BASE		0
+
+/*	THDR11_LO			0x1958	TCP Segmentation Header Register 11 Lo */
+#define	THDR11_LO_IP_HDR_19_MSK			SHIFT0(0xffffffff)	/* IP_HDR_19 */
+#define	THDR11_LO_IP_HDR_19_BASE		0
+
+/*	THDR11_HI			0x195C	TCP Segmentation Header Register 11 Hi */
+#define	THDR11_HI_IP_HDR_20_MSK			SHIFT0(0xffffffff)	/* IP_HDR_20 */
+#define	THDR11_HI_IP_HDR_20_BASE		0
+
+/*	THDR12_LO			0x1960	TCP Segmentation Header Register 12 Lo */
+#define	THDR12_LO_IP_HDR_21_MSK			SHIFT0(0xffffffff)	/* IP_HDR_21 */
+#define	THDR12_LO_IP_HDR_21_BASE		0
+
+/*	THDR12_HI			0x1964	TCP Segmentation Header Register 12 Hi */
+#define	THDR12_HI_IP_HDR_22_MSK			SHIFT0(0xffffffff)	/* IP_HDR_22 */
+#define	THDR12_HI_IP_HDR_22_BASE		0
+
+/*	THDR13_LO			0x1968	TCP Segmentation Header Register 13 Lo */
+#define	THDR13_LO_IP_HDR_23_MSK			SHIFT0(0xffffffff)	/* IP_HDR_23 */
+#define	THDR13_LO_IP_HDR_23_BASE		0
+
+/*	THDR13_HI			0x196C	TCP Segmentation Header Register 13 Hi */
+#define	THDR13_HI_IP_HDR_24_MSK			SHIFT0(0xffffffff)	/* IP_HDR_24 */
+#define	THDR13_HI_IP_HDR_24_BASE		0
+
+/*	THDR14_LO			0x1970	TCP Segmentation Header Register 14 Lo */
+#define	THDR14_LO_IP_HDR_25_MSK			SHIFT0(0xffffffff)	/* IP_HDR_25 */
+#define	THDR14_LO_IP_HDR_25_BASE		0
+
+/*	THDR14_HI			0x1974	TCP Segmentation Header Register 14 Hi */
+#define	THDR14_HI_IP_HDR_26_MSK			SHIFT0(0xffffffff)	/* IP_HDR_26 */
+#define	THDR14_HI_IP_HDR_26_BASE		0
+
+/*	THDR15_LO			0x1978	TCP Segmentation Header Register 15 Lo */
+#define	THDR15_LO_IP_HDR_27_MSK			SHIFT0(0xffffffff)	/* IP_HDR_27 */
+#define	THDR15_LO_IP_HDR_27_BASE		0
+
+/*	THDR15_HI			0x197C	TCP Segmentation Header Register 15 Hi */
+#define	THDR15_HI_IP_HDR_28_MSK			SHIFT0(0xffffffff)	/* IP_HDR_28 */
+#define	THDR15_HI_IP_HDR_28_BASE		0
+
+/*	THDR16_LO			0x1980	TCP Segmentation Header Register 16 Lo */
+#define	THDR16_LO_IP_HDR_29_MSK			SHIFT0(0xffffffff)	/* IP_HDR_29 */
+#define	THDR16_LO_IP_HDR_29_BASE		0
+
+/*	THDR16_HI			0x1984	TCP Segmentation Header Register 16 Hi */
+#define	THDR16_HI_IP_HDR_30_MSK			SHIFT0(0xffffffff)	/* IP_HDR_30 */
+#define	THDR16_HI_IP_HDR_30_BASE		0
+
+/*	THDR17_LO			0x1988	TCP Segmentation Header Register 17 Lo */
+#define	THDR17_LO_IP_HDR_31_MSK			SHIFT0(0xffffffff)	/* IP_HDR_31 */
+#define	THDR17_LO_IP_HDR_31_BASE		0
+
+/*	THDR17_HI			0x198C	TCP Segmentation Header Register 17 Hi */
+#define	THDR17_HI_IP_HDR_32_MSK			SHIFT0(0xffffffff)	/* IP_HDR_32 */
+#define	THDR17_HI_IP_HDR_32_BASE		0
+
+/*	THDR18_LO			0x1990	TCP Segmentation Header Register 18 Lo */
+#define	THDR18_LO_IP_HDR_33_MSK			SHIFT0(0xffffffff)	/* IP_HDR_33 */
+#define	THDR18_LO_IP_HDR_33_BASE		0
+
+/*	THDR18_HI			0x1994	TCP Segmentation Header Register 18 Hi */
+#define	THDR18_HI_IP_HDR_34_MSK			SHIFT0(0xffffffff)	/* IP_HDR_34 */
+#define	THDR18_HI_IP_HDR_34_BASE		0
+
+/*	THDR19_LO			0x1998	TCP Segmentation Header Register 19 Lo */
+#define	THDR19_LO_IP_HDR_35_MSK			SHIFT0(0xffffffff)	/* IP_HDR_35 */
+#define	THDR19_LO_IP_HDR_35_BASE		0
+
+/*	THDR19_HI			0x199C	TCP Segmentation Header Register 19 Hi */
+#define	THDR19_HI_IP_HDR_36_MSK			SHIFT0(0xffffffff)	/* IP_HDR_36 */
+#define	THDR19_HI_IP_HDR_36_BASE		0
+
+/*	THDR20_LO			0x19A0	TCP Segmentation Header Register 20 Lo */
+#define	THDR20_LO_IP_HDR_37_MSK			SHIFT0(0xffffffff)	/* IP_HDR_37 */
+#define	THDR20_LO_IP_HDR_37_BASE		0
+
+/*	THDR20_HI			0x19A4	TCP Segmentation Header Register 20 Hi */
+#define	THDR20_HI_IP_HDR_38_MSK			SHIFT0(0xffffffff)	/* IP_HDR_38 */
+#define	THDR20_HI_IP_HDR_38_BASE		0
+
+/*	THDR21_LO			0x19A8	TCP Segmentation Header Register 21 Lo */
+#define	THDR21_LO_IP_HDR_39_MSK			SHIFT0(0xffffffff)	/* IP_HDR_39 */
+#define	THDR21_LO_IP_HDR_39_BASE		0
+
+/*	THDR21_HI			0x19AC	TCP Segmentation Header Register 21 Hi */
+#define	THDR21_HI_IP_HDR_40_MSK			SHIFT0(0xffffffff)	/* IP_HDR_40 */
+#define	THDR21_HI_IP_HDR_40_BASE		0
+
+/*	THDR22_LO			0x19B0	TCP Segmentation Header Register 22 Lo */
+#define	THDR22_LO_IP_HDR_41_MSK			SHIFT0(0xffffffff)	/* IP_HDR_41 */
+#define	THDR22_LO_IP_HDR_41_BASE		0
+
+/*	THDR22_HI			0x19B4	TCP Segmentation Header Register 22 Hi */
+#define	THDR22_HI_TCP_HDR_0_MSK			SHIFT16(0xffff)	/* TCP_HDR_0 */
+#define	THDR22_HI_TCP_HDR_0_BASE		16
+#define	THDR22_HI_IP_HDR_42_MSK			SHIFT0(0xffff)	/* IP_HDR_42 */
+#define	THDR22_HI_IP_HDR_42_BASE		0
+
+/*	THDR23_LO			0x19B8	TCP Segmentation Header Register 23 Lo */
+#define	THDR23_LO_TCP_HDR_1_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_1 */
+#define	THDR23_LO_TCP_HDR_1_BASE		0
+
+/*	THDR23_HI			0x19BC	TCP Segmentation Header Register 23 Hi */
+#define	THDR23_HI_TCP_HDR_2_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_2 */
+#define	THDR23_HI_TCP_HDR_2_BASE		0
+
+/*	THDR24_LO			0x19C0	TCP Segmentation Header Register 24 Lo */
+#define	THDR24_LO_TCP_HDR_3_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_3 */
+#define	THDR24_LO_TCP_HDR_3_BASE		0
+
+/*	THDR24_HI			0x19C4	TCP Segmentation Header Register 24 Hi */
+#define	THDR24_HI_TCP_HDR_4_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_4 */
+#define	THDR24_HI_TCP_HDR_4_BASE		0
+
+/*	THDR25_LO			0x19C8	TCP Segmentation Header Register 25 Lo */
+#define	THDR25_LO_TCP_HDR_5_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_5 */
+#define	THDR25_LO_TCP_HDR_5_BASE		0
+
+/*	THDR25_HI			0x19CC	TCP Segmentation Header Register 25 Hi */
+#define	THDR25_HI_TCP_HDR_6_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_6 */
+#define	THDR25_HI_TCP_HDR_6_BASE		0
+
+/*	THDR26_LO			0x19D0	TCP Segmentation Header Register 26 Lo */
+#define	THDR26_LO_TCP_HDR_7_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_7 */
+#define	THDR26_LO_TCP_HDR_7_BASE		0
+
+/*	THDR26_HI			0x19D4	TCP Segmentation Header Register 26 Hi */
+#define	THDR26_HI_TCP_HDR_8_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_8 */
+#define	THDR26_HI_TCP_HDR_8_BASE		0
+
+/*	THDR27_LO			0x19D8	TCP Segmentation Header Register 27 Lo */
+#define	THDR27_LO_TCP_HDR_9_MSK			SHIFT0(0xffffffff)	/* TCP_HDR_9 */
+#define	THDR27_LO_TCP_HDR_9_BASE		0
+
+/*	THDR27_HI			0x19DC	TCP Segmentation Header Register 27 Hi */
+#define	THDR27_HI_TCP_HDR_10_MSK		SHIFT0(0xffffffff)	/* TCP_HDR_10 */
+#define	THDR27_HI_TCP_HDR_10_BASE		0
+
+/*	THDR28_LO			0x19E0	TCP Segmentation Header Register 28 Lo */
+#define	THDR28_LO_TCP_HDR_11_MSK		SHIFT0(0xffffffff)	/* TCP_HDR_11 */
+#define	THDR28_LO_TCP_HDR_11_BASE		0
+
+/*	THDR28_HI			0x19E4	TCP Segmentation Header Register 28 Hi */
+#define	THDR28_HI_TCP_HDR_12_MSK		SHIFT0(0xffffffff)	/* TCP_HDR_12 */
+#define	THDR28_HI_TCP_HDR_12_BASE		0
+
+/*	THDR29_LO			0x19E8	TCP Segmentation Header Register 29 Lo */
+#define	THDR29_LO_TCP_HDR_13_MSK		SHIFT0(0xffffffff)	/* TCP_HDR_13 */
+#define	THDR29_LO_TCP_HDR_13_BASE		0
+
+/*	THDR29_HI			0x19EC	TCP Segmentation Header Register 29 Hi */
+#define	THDR29_HI_TCP_HDR_14_MSK		SHIFT0(0xffffffff)	/* TCP_HDR_14 */
+#define	THDR29_HI_TCP_HDR_14_BASE		0
+
+/*	THDR30_LO			0x19F0	TCP Segmentation Header Register 30 Lo */
+/*		Bit(s) THDR30_LO_RSRV_31_16 reserved */
+#define	THDR30_LO_TCP_HDR_15_MSK		SHIFT0(0xffff)	/* TCP_HDR_15 */
+#define	THDR30_LO_TCP_HDR_15_BASE		0
+
+/*	CFG_VLAN_ET1		0x2000	VLAN Ethernet Type Configuration Register 1 */
+/*		Bit(s) CFG_VLAN_ET1_RSRV_23_0 reserved */
+#define	CFG_VLAN_ET1_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_VLAN_ET1_BASE				BIT_0
+
+/*	CFG_VLAN_ET0		0x2004	VLAN Ethernet Type Configuration Register 0 */
+/*		Bit(s) CFG_VLAN_ET0_RSRV_23_0 reserved */
+#define	CFG_VLAN_ET0_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_VLAN_ET0_BASE				BIT_0
+
+/*	CFG_MACSEC_ET1		0x2008	802.1AE Ethernet Type Configuration Register 1 */
+/*		Bit(s) CFG_MACSEC_ET1_RSRV_23_0 reserved */
+#define	CFG_MACSEC_ET1_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_MACSEC_ET1_BASE					BIT_0
+
+/*	CFG_MACSEC_ET0		0x200C	802.1AE Ethernet Type Configuration Register 0 */
+/*		Bit(s) CFG_MACSEC_ET0_RSRV_23_0 reserved */
+#define	CFG_MACSEC_ET0_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_MACSEC_ET0_BASE					BIT_0
+
+/*	CFG_TRAIL_SZ		0x2010	Trail Size Configuration Register */
+/*		Bit(s) CFG_TRAIL_SZ_RSRV_23_0 reserved */
+#define	CFG_TRAIL_SZ_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_TRAIL_SZ_BASE				BIT_0
+
+/*	CFG_DEFAULT_VLAN0	0x2014	Default VLAN Register 0 */
+/*		Bit(s) CFG_DEFAULT_VLAN0_RSRV_23_0 reserved */
+#define	CFG_DEFAULT_VLAN0_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_DEFAULT_VLAN0_BASE					BIT_0
+
+/*	CFG_DEFAULT_VLAN1	0x2018	Default VLAN Register 1 */
+/*		Bit(s) CFG_DEFAULT_VLAN1_RSRV_27_0 reserved */
+#define	CFG_DEFAULT_VLAN1_MSK					SHIFT0(0xf)			/* Val */
+#define	CFG_DEFAULT_VLAN1_BASE					BIT_0
+
+/*	CFG_MACSEC_SL_SZ	0x201C	MACSec Size Configuration Register */
+/*		Bit(s) CFG_MACSEC_SL_SZ_RSRV_23_0 reserved */
+#define	CFG_MACSEC_SL_SZ_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_MACSEC_SL_SZ_BASE				BIT_0
+
+/*	CFG_MIN_PKT_LEN		0x2020	Minimum Packet Length Configuration Register */
+/*		Bit(s) CFG_MIN_PKT_LEN_RSRV_23_0 reserved */
+#define	CFG_MIN_PKT_LEN_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_MIN_PKT_LEN_BASE				BIT_0
+
+/*	SEC_CLK_RST			0x2024	MACSec Clock Reset Register */
+/*		Bit(s) SEC_CLK_RST_RSRV_27_0 reserved */
+#define	SEC_CLK_RST_GATE_DIS			BIT_3				/* gate disable */
+#define	SEC_CLK_RST_INGRESS_RST			BIT_2				/* ingress reset */
+#define	SEC_CLK_RST_EGRESS_RST			BIT_1				/* egress reset */
+#define	SEC_CLK_RST_STAT_RST			BIT_0				/* stat reset */
+
+/*	EGR_KS_SELECT		0x2028	Egress Key Store Select Register */
+/*		Bit(s) EGR_KS_SELECT_RSRV_25_0 reserved */
+#define	EGR_KS_SELECT_CTXT_NUM_MSK			SHIFT4(0x3)			/* context number */
+#define	EGR_KS_SELECT_CTXT_NUM_BASE			BIT_4
+#define	EGR_KS_SELECT_BYTE_NUM_MSK			SHIFT0(0xf)			/* byte number */
+#define	EGR_KS_SELECT_BYTE_NUM_BASE			BIT_0
+
+/*	EGR_KS_WRDATA		0x202C	Egress Key Store Write Data Register */
+/*		Bit(s) EGR_KS_WRDATA_RSRV_23_0 reserved */
+#define	EGR_KS_WRDATA_MSK					SHIFT0(0xff)		/* Val */
+#define	EGR_KS_WRDATA_BASE					BIT_0
+
+/*	IGR_KS_SELECT		0x2030	Ingress Key Store Select Register */
+/*		Bit(s) IGR_KS_SELECT_RSRV_25_0 reserved */
+#define	IGR_KS_SELECT_CTXT_NUM_MSK			SHIFT4(0x3)			/* context number */
+#define	IGR_KS_SELECT_CTXT_NUM_BASE			BIT_4
+#define	IGR_KS_SELECT_BYTE_NUM_MSK			SHIFT0(0xf)			/* byte number */
+#define	IGR_KS_SELECT_BYTE_NUM_BASE			BIT_0
+
+/*	IGR_KS_WRDATA		0x2034	Ingress Key Store Write Data Register */
+/*		Bit(s) IGR_KS_WRDATA_RSRV_23_0 reserved */
+#define	IGR_KS_WRDATA_MSK					SHIFT0(0xff)		/* Val */
+#define	IGR_KS_WRDATA_BASE					BIT_0
+
+/*	CFG_ELU_MC_HIGH0	0x2038	Multicast Match Register 0 */
+/*		Bit(s) CFG_ELU_MC_HIGH0_RSRV_27_0 reserved */
+#define	CFG_ELU_MC_HIGH0_MSK				SHIFT0(0xf)			/* Val */
+#define	CFG_ELU_MC_HIGH0_BASE				BIT_0
+
+/*	CFG_ELU_MC_HIGH1	0x203C	Multicast Match Register 1 */
+/*		Bit(s) CFG_ELU_MC_HIGH1_RSRV_23_0 reserved */
+#define	CFG_ELU_MC_HIGH1_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_ELU_MC_HIGH1_BASE				BIT_0
+
+/*	CFG_ELU_MC_HIGH2	0x2040	Multicast Match Register 2 */
+/*		Bit(s) CFG_ELU_MC_HIGH2_RSRV_23_0 reserved */
+#define	CFG_ELU_MC_HIGH2_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_ELU_MC_HIGH2_BASE				BIT_0
+
+/*	CFG_ELU_MC_HIGH3	0x2044	Multicast Match Register 3 */
+/*		Bit(s) CFG_ELU_MC_HIGH3_RSRV_23_0 reserved */
+#define	CFG_ELU_MC_HIGH3_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_ELU_MC_HIGH3_BASE				BIT_0
+
+/*	CFG_ELU_MC_HIGH4	0x2048	Multicast Match Register 4 */
+/*		Bit(s) CFG_ELU_MC_HIGH4_RSRV_23_0 reserved */
+#define	CFG_ELU_MC_HIGH4_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_ELU_MC_HIGH4_BASE				BIT_0
+
+/*	CFG_ELU_MC_HIGH5	0x204C	Multicast Match Register 5 */
+/*		Bit(s) CFG_ELU_MC_HIGH5_RSRV_23_0 reserved */
+#define	CFG_ELU_MC_HIGH5_MSK				SHIFT0(0xff)		/* Val */
+#define	CFG_ELU_MC_HIGH5_BASE				BIT_0
+
+/*	CFG_ELU_MC_LOW_MSK0	0x2050	Multicast Match Mask Register 0 */
+/*		Bit(s) CFG_ELU_MC_LOW_MSK0_RSRV_23_0 reserved */
+#define	CFG_ELU_MC_LOW_MSK0_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_ELU_MC_LOW_BASE0_BASE				BIT_0
+
+/*	CFG_ELU_MC_LOW_MSK1	0x2054	Multicast Match Mask Register 1 */
+/*		Bit(s) CFG_ELU_MC_LOW_MSK1_RSRV_23_0 reserved */
+#define	CFG_ELU_MC_LOW_MSK1_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_ELU_MC_LOW_BASE1_BASE				BIT_0
+
+/*	CFG_DEFAULT_PORT0	0x2058	Default Port Configuration Register 0 */
+/*		Bit(s) CFG_DEFAULT_PORT0_RSRV_23_0 reserved */
+#define	CFG_DEFAULT_PORT0_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_DEFAULT_PORT0_BASE					BIT_0
+
+/*	CFG_DEFAULT_PORT1	0x205C	Default Port Configuration Register 1 */
+/*		Bit(s) CFG_DEFAULT_PORT1_RSRV_23_0 reserved */
+#define	CFG_DEFAULT_PORT1_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_DEFAULT_PORT1_BASE					BIT_0
+
+/*	CFG_SCB_PORT0		0x2060	SCB Port Configuration Register 0 */
+/*		Bit(s) CFG_SCB_PORT0_RSRV_23_0 reserved */
+#define	CFG_SCB_PORT0_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_SCB_PORT0_BASE					BIT_0
+
+/*	CFG_SCB_PORT1		0x2064	SCB Port Configuration Register 1 */
+/*		Bit(s) CFG_SCB_PORT1_RSRV_23_0 reserved */
+#define	CFG_SCB_PORT1_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_SCB_PORT1_BASE					BIT_0
+
+/*	CFG_AUTH_ADJUST		0x2068	Authentication Adjustment Register */
+/*		Bit(s) CFG_AUTH_ADJUST_RSRV_23_0 reserved */
+#define	CFG_AUTH_ADJUST_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_AUTH_ADJUST_BASE				BIT_0
+
+/*	CFG_ELU_GEN			0x206C	ELU Default Configuration Register */
+/*		Bit(s) CFG_ELU_GEN_RSRV_27_0 reserved */
+//#define	_MSK							SHIFT2(0x3)			/* min_bypass_len */
+//#define	_BASE							BIT_2
+/*		Bit(s) CFG_ELU_GEN_RSRV_1_0 reserved */
+
+/*	CFG_ELUC_ADDR		0x2070	ELU Address Configuration Register */
+/*		Bit(s) CFG_ELUC_ADDR_RSRV_25_0 reserved */
+#define	CFG_ELUC_ADDR_CTXT_NUM_MSK			SHIFT4(0x3)			/* context number */
+#define	CFG_ELUC_ADDR_CTXT_NUM_BASE			BIT_4
+#define	CFG_ELUC_ADDR_BYTE_NUM_MSK			SHIFT0(0xf)			/* byte number */
+#define	CFG_ELUC_ADDR_BYTE_NUM_BASE			BIT_0
+
+/*	CFG_ELUC_DATA		0x2074	ELU Context Data Configuration Register */
+/*		Bit(s) CFG_ELUC_DATA_RSRV_23_0 reserved */
+#define	CFG_ELUC_DATA_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_ELUC_DATA_BASE					BIT_0
+
+/*	CFG_ELUE_ADDR		0x2078	ELU Entry Configuration Register */
+/*		Bit(s) CFG_ELUE_ADDR_RSRV_23_0 reserved */
+/* Lookup entry number */
+#define	CFG_ELUE_ADDR_LKUP_NUM_MSK			SHIFT5(0x7)			
+#define	CFG_ELUE_ADDR_LKUP_NUM_BASE			BIT_5
+#define	CFG_ELUE_ADDR_BYTE_NUM_MSK			SHIFT0(0x1f)		/* byte number */
+#define	CFG_ELUE_ADDR_BYTE_NUM_BASE			BIT_0
+
+/*	CFG_ELUE_DATA		0x207C	ELU Lookup Entry Access Configuration Register */
+/*		Bit(s) CFG_ELUE_DATA_RSRV_23_0 reserved */
+#define	CFG_ELUE_DATA_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_ELUE_DATA_BASE					BIT_0
+
+/*	CFG_EPR_GEN			0x2080	General Egress Parser Configuration Register */
+/*		Bit(s) CFG_EPR_GEN_RSRV_28_0 reserved */
+#define	CFG_EPR_GEN_PARSE_VLAN				BIT_2				/* Parse VLAN */
+/*		Bit(s) CFG_EPR_GEN_RSRV_ reserved */
+#define	CFG_EPR_GEN_PREAMBLE_PRESENT		BIT_0				/* Preamble present */
+
+/*	EGR_HR_SELECT		0x2084	Egress Write Select for H-Store Register */
+/*		Bit(s) EGR_HR_SELECT_RSRV_25_0 reserved */
+#define	EGR_HR_SELECT_KEY_NUM_MSK			SHIFT4(0x3)			/* Key number */
+#define	EGR_HR_SELECT_KEY_NUM_BASE			BIT_4
+#define	EGR_HR_SELECT_BYTE_NUM_MSK			SHIFT0(0xf)			/* byte number */
+#define	EGR_HR_SELECT_BYTE_NUM_BASE			BIT_0
+
+/*	EGR_HR_WRDATA		0x2088	Egress Header Write Data Register */
+/*		Bit(s) EGR_HR_WRDATA_RSRV_23_0 reserved */
+#define	EGR_HR_WRDATA_MSK					SHIFT0(0xff)		/* Val */
+#define	EGR_HR_WRDATA_BASE					BIT_0
+
+/*	IGR_HR_SELECT		0x208C	Ingress Write Select for H-Store Register */
+/*		Bit(s) IGR_HR_SELECT_RSRV_25_0 reserved */
+#define	IGR_HR_SELECT_KEY_NUM_MSK			SHIFT4(0x3)			/* Key number */
+#define	IGR_HR_SELECT_KEY_NUM_BASE			BIT_4
+#define	IGR_HR_SELECT_BYTE_NUM_MSK			SHIFT0(0xf)			/* byte number */
+#define	IGR_HR_SELECT_BYTE_NUM_BASE			BIT_0
+
+/*	IGR_HR_WRDATA		0x2090	Ingress Header Write Data Register */
+/*		Bit(s) IGR_HR_WRDATA_RSRV_25_0 reserved */
+#define	IGR_HR_WRDATA_2_MSK					SHIFT0(0xff)		/* Val */
+#define	IGR_HR_WRDATA_2_BASE				BIT_0
+
+/*	CFG_IMPLICIT_SCI0	0x2098	Implicit SCI Register 0 */
+/*		Bit(s) CFG_IMPLICIT_SCI0_RSRV_23_0 reserved */
+#define	CFG_IMPLICIT_SCI0_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_IMPLICIT_SCI0_BASE					BIT_0
+
+/*	CFG_IMPLICIT_SCI1	0x209C	Implicit SCI Register 1 */
+/*		Bit(s) CFG_IMPLICIT_SCI1_RSRV_23_0 reserved */
+#define	CFG_IMPLICIT_SCI1_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_IMPLICIT_SCI1_BASE					BIT_0
+
+/*	CFG_IMPLICIT_SCI2	0x20A0	Implicit SCI Register 2 */
+/*		Bit(s) CFG_IMPLICIT_SCI2_RSRV_23_0 reserved */
+#define	CFG_IMPLICIT_SCI2_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_IMPLICIT_SCI2_BASE					BIT_0
+
+/*	CFG_IMPLICIT_SCI3	0x20A4	Implicit SCI Register 3 */
+/*		Bit(s) CFG_IMPLICIT_SCI3_RSRV_23_0 reserved */
+#define	CFG_IMPLICIT_SCI3_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_IMPLICIT_SCI3_BASE					BIT_0
+
+/*	CFG_IMPLICIT_SCI4	0x20A8	Implicit SCI Register 4 */
+/*		Bit(s) CFG_IMPLICIT_SCI4_RSRV_23_0 reserved */
+#define	CFG_IMPLICIT_SCI4_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_IMPLICIT_SCI4_BASE					BIT_0
+
+/*	CFG_IMPLICIT_SCI5	0x20AC	Implicit SCI Register 5 */
+/*		Bit(s) CFG_IMPLICIT_SCI5_RSRV_23_0 reserved */
+#define	CFG_IMPLICIT_SCI5_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_IMPLICIT_SCI5_BASE					BIT_0
+
+/*	CFG_IMPLICIT_SCI6	0x20B0	Implicit SCI Register 6 */
+/*		Bit(s) CFG_IMPLICIT_SCI6_RSRV_23_0 reserved */
+#define	CFG_IMPLICIT_SCI6_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_IMPLICIT_SCI6_BASE					BIT_0
+
+/*	CFG_IMPLICIT_SCI7	0x20B4	Implicit SCI Register 7 */
+/*		Bit(s) CFG_IMPLICIT_SCI7_RSRV_23_0 reserved */
+#define	CFG_IMPLICIT_SCI7_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_IMPLICIT_SCI7_BASE					BIT_0
+
+/*	CFG_REPLAY_WINDOW0	0x20B8	Replay Window Register 0 */
+/*		Bit(s) CFG_REPLAY_WINDOW0_RSRV_23_0 reserved */
+#define	CFG_REPLAY_WINDOW0_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_REPLAY_WINDOW0_BASE					BIT_0
+
+/*	CFG_REPLAY_WINDOW1	0x20BC	Replay Window Register 1 */
+/*		Bit(s) CFG_REPLAY_WINDOW1_RSRV_23_0 reserved */
+#define	CFG_REPLAY_WINDOW1_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_REPLAY_WINDOW1_BASE					BIT_0
+
+/*	CFG_REPLAY_WINDOW2	0x20C0	Replay Window Register 2 */
+/*		Bit(s) CFG_REPLAY_WINDOW2_RSRV_23_0 reserved */
+#define	CFG_REPLAY_WINDOW2_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_REPLAY_WINDOW2_BASE					BIT_0
+
+/*	CFG_REPLAY_WINDOW3	0x20C4	Replay Window Register 3 */
+/*		Bit(s) CFG_REPLAY_WINDOW3_RSRV_23_0 reserved */
+#define	CFG_REPLAY_WINDOW3_MSK					SHIFT0(0xff)		/* Val */
+#define	CFG_REPLAY_WINDOW3_BASE					BIT_0
+
+/*	CFG_IPR_GEN			0x20C8	Ingress Primary Parser Register */
+/*		Bit(s) CFG_IPR_GEN_RSRV_28_0 reserved */
+#define	CFG_IPR_GEN_PREAMBLE_PRESENT		BIT_2				/* Preamble present */
+#define	CFG_IPR_GEN_PARSE_VLAN				BIT_1				/* Parse VLAN */
+/* extract header field */
+#define	CFG_IPR_GEN_EXTRACT_HDR_FIELD		BIT_0				
+
+/*	CFG_ISC_GEN			0x20CC	Ingress Security Check Block Register */
+/*		Bit(s) CFG_ISC_GEN_RSRV_23_0 reserved */
+/*		Bit(s) CFG_ISC_GEN_RSRV_ reserved */
+/*		Bit(s) CFG_ISC_GEN_RSRV_ reserved */
+/*		Bit(s) CFG_ISC_GEN_RSRV_1_0 reserved */
+/* replay_protect */
+#define	CFG_ISC_GEN_RPY_PROTECT					BIT_2				
+/* validate_frames */
+#define	CFG_ISC_GEN_VALIDATE_FRAMES_MSK			SHIFT0(0x3)			
+#define	CFG_ISC_GEN_VALIDATE_FRAMES_BASE		BIT_0
+
+/*	CFG_RPY_ADDR		0x20D0	Replay Protect Table Access Register */
+/*		Bit(s) CFG_RPY_ADDR_RSRV_27_0 reserved */
+/* Replay table entry */
+#define	CFG_RPY_ADDR_RPY_TAB_NUM_MSK		SHIFT2(0x3)			
+#define	CFG_RPY_ADDR_RPY_TAB_NUM_BASE		BIT_2
+#define	CFG_RPY_ADDR_BYTE_NUM_MSK			SHIFT0(0x3)			/* byte number */
+#define	CFG_RPY_ADDR_BYTE_NUM_BASE			BIT_0
+
+/*	CFG_RPY_DATA		0x20D4	ELU Context Data Register */
+/*		Bit(s) CFG_RPY_DATA_RSRV_23_0 reserved */
+#define	CFG_RPY_DATA_MSK				SHIFT0(0xff)		/* val */
+#define	CFG_RPY_DATA_BASE				BIT_0
+
+/*	CFG_ILUT_ADDR		0x20E0	Ingress Lookup Table Access Address
+ *								Configuration Register
+ */
+/*		Bit(s) CFG_ILUT_ADDR_RSRV_23_0 reserved */
+/* Lookup table entry */
+#define	CFG_ILUT_ADDR_LOOKUP_NUM_MSK		SHIFT5(0x7)			
+#define	CFG_ILUT_ADDR_LOOKUP_NUM_BASE		BIT_5
+#define	CFG_ILUT_ADDR_BYTE_NUM_MSK			SHIFT0(0x1f)		/* byte number */
+#define	CFG_ILUT_ADDR_BYTE_NUM_BASE			BIT_0
+
+/*	CFG_ILUT_DATA		0x20E4	ILU Table Data Register */
+/*		Bit(s) CFG_ILUT_DATA_RSRV_23_0 reserved */
+#define	CFG_ILUT_DATA_MSK					SHIFT0(0xff)		/* val */
+#define	CFG_ILUT_DATA_BASE					BIT_0
+
+/*	STAT_ADDR			0x20E8	Statistic Register Address */
+/*		Bit(s) STAT_ADDR_RSRV_25_0 reserved */
+#define	STAT_ADDR_MSK					SHIFT0(0x3f)		/* val */
+#define	STAT_ADDR_BASE					BIT_0
+
+/*	STAT_DATA0			0x20EC	Statistic Data Register 0 */
+/*		Bit(s) STAT_DATA0_RSRV_23_0 reserved */
+#define	STAT_DATA0_MSK					SHIFT0(0xff)		/* val */
+#define	STAT_DATA0_BASE					BIT_0
+
+/*	STAT_DATA1			0x20F0	Statistic Data Register 1 */
+/*		Bit(s) STAT_DATA1_RSRV_23_0 reserved */
+#define	STAT_DATA1_MSK					SHIFT0(0xff)		/* val */
+#define	STAT_DATA1_BASE					BIT_0
+
+/*	STAT_DATA2			0x20F4	Statistic Data Register 2 */
+/*		Bit(s) STAT_DATA2_RSRV_23_0 reserved */
+#define	STAT_DATA2_MSK					SHIFT0(0xff)		/* val */
+#define	STAT_DATA2_BASE					BIT_0
+
+/*	CFG_OVER_LEN1		0x20F8	Over-Length Configuration Register 1 */
+/*		Bit(s) CFG_OVER_LEN1_RSRV_23_0 reserved */
+#define	CFG_OVER_LEN1_MSK					SHIFT0(0xff)		/* val */
+#define	CFG_OVER_LEN1_BASE					BIT_0
+
+/*	CNT_TX_ERR			0x2100	MACSec TX Processing Error Count */
+/*		Bit(s) CNT_TX_ERR_RSRV_23_0 reserved */
+#define	CNT_TX_ERR_MSK					SHIFT0(0xff)		/* err_cnt */
+#define	CNT_TX_ERR_BASE					BIT_0
+
+/*	CFG_IPAR_HYST		0x2104	Ingress Parse FIFO Hysteresis */
+/*		Bit(s) CFG_IPAR_HYST_RSRV_27_0 reserved */
+#define	CFG_IPAR_HYST_MSK					SHIFT0(0xf)			/* ipar_hyst */
+#define	CFG_IPAR_HYST_BASE					BIT_0
+
+/*	CFG_EPAR_HYST		0x2108	Egress Parse FIFO Hysteresis */
+/*		Bit(s) CFG_EPAR_HYST_RSRV_27_0 reserved */
+#define	CFG_EPAR_HYST_MSK					SHIFT0(0xf)			/* epar_hyst */
+#define	CFG_EPAR_HYST_BASE					BIT_0
+
+/*	RE_TRF_TCTL			0x2200	MACSec Retransmit FIFO Control */
+/*		Bit(s) RE_TRF_TCTL_RSRV_27_0 reserved */
+#define	RE_TRF_TCTL_RETRAN_OP_ON		BIT_3				/* Operational On */
+#define	RE_TRF_TCTL_RETRAN_OP_OFF		BIT_2				/* Operational Off */
+#define	RE_TRF_TCTL_RETRAN_RST_CLR		BIT_1				/* Reset Clear */
+#define	RE_TRF_TCTL_RETRAN_RST_SET		BIT_0				/* Reset Set */
+
+/*	RE_TRF_PCNT			0x2204	Retransmit FIFO Packet Counter */
+/*		Bit(s) RE_TRF_PCNT_RSRV_22_0 reserved */
+#define	RE_TRF_PCNT_MSK					SHIFT0(0xff)		/* Packet Counter */
+#define	RE_TRF_PCNT_BASE				BIT_0
+
+/*	RE_TRF_TTH			0x2208	Retransmit FIFO Transmit Start Threshold */
+/*		Bit(s) RE_TRF_TTH_RSRV_26_0 reserved */
+/* Transmit Start Threshold */
+#define	RE_TRF_TTH_MSK					SHIFT0(0x1f)		
+#define	RE_TRF_TTH_BASE					BIT_0
+
+/*	RE_TRF_WPTR			0x2210	Retransmit FIFO Write Pointer Register */
+/*		Bit(s) RE_TRF_WPTR_RSRV_26_0 reserved */
+#define	RE_TRF_WPTR_MSK					SHIFT0(0x1f)		/* Write Pointer */
+#define	RE_TRF_WPTR_BASE				BIT_0
+
+/*	RE_TRF_WLEV			0x2218	Retransmit FIFO Write Level Register */
+/*		Bit(s) RE_TRF_WLEV_RSRV_26_0 reserved */
+#define	RE_TRF_WLEV_MSK					SHIFT0(0x1f)		/* Write Level */
+#define	RE_TRF_WLEV_BASE				BIT_0
+
+/*	RE_TRF_RPTR			0x2220	Retransmit FIFO Read Pointer Register */
+/*		Bit(s) RE_TRF_RPTR_RSRV_26_0 reserved */
+#define	RE_TRF_RPTR_MSK					SHIFT0(0x1f)		/* Read Pointer */
+#define	RE_TRF_RPTR_BASE				BIT_0
+
+/*	RE_TRF_RES_PTR		0x2224	Transmit FIFO Restart Pointer Register */
+/*		Bit(s) RE_TRF_RES_PTR_RSRV_26_0 reserved */
+#define	RE_TRF_RES_PTR_MSK					SHIFT0(0x1f)		/* Restart Pointer */
+#define	RE_TRF_RES_PTR_BASE					BIT_0
+
+/*	RE_TRF_RLEV			0x2228	Retransmit FIFO Read Level Register */
+/*		Bit(s) RE_TRF_RLEV_RSRV_26_0 reserved */
+#define	RE_TRF_RLEV_MSK					SHIFT0(0x1f)		/* Read Level */
+#define	RE_TRF_RLEV_BASE				BIT_0
+
+/*	RE_TRF_RSPTR		0x222c	Retransmit FIFO Read Shadow Level Register */
+/*		Bit(s) RE_TRF_RSPTR_RSRV_26_0 reserved */
+#define	RE_TRF_RSPTR_MSK				SHIFT0(0x1f)		/* Read Shadow Level */
+#define	RE_TRF_RSPTR_BASE				BIT_0
+
+
+
+/* -------------------- */
+
+
+
+/*
+ *
+ *	THE BASE ADDRESSES
+ *
+ */
+
+/*
+ *
+ *	THE REGISTER DEFINES
+ *
+ */
+#define	GPSR		0x2800	/* 16 bit	General Purpose Status Register */
+#define	GPCR		0x2804	/* 16 bit	General Purpose Control Register */
+#define	TCR			0x2808	/* 16 bit	Transmit Control Register */
+#define	RCR			0x280C	/* 16 bit	Receive Control Register */
+#define	TFCR		0x2810	/* 16 bit	Transmit Flow Control Register */
+#define	TPR			0x2814	/* 16 bit	Transmit Parameter Register */
+#define	SMR			0x2818	/* 16 bit	Serial Mode Register */
+#define	SAL1		0x281C	/* 16 bit	Source Address Low */
+#define	SAM1		0x2820	/* 16 bit	Source Address Middle */
+#define	SA1H		0x2824	/* 16 bit	Source Address High */
+#define	SAL2		0x2828	/* 16 bit	Source Address Low */
+#define	SAM2		0x282C	/* 16 bit	Source Address Middle */
+#define	SAH2		0x2830	/* 16 bit	Source Address High */
+#define	MCAH1		0x2834	/* 16 bit	Multicast Address Hash Register 1 */
+#define	MCAH2		0x2838	/* 16 bit	Multicast Address Hash Register 2 */
+#define	MCAH3		0x283C	/* 16 bit	Multicast Address Hash Register 3 */
+#define	MCAH4		0x2840	/* 16 bit	Multicast Address Hash Register 4 */
+#define	TIR			0x2844	/* 16 bit	Transmit Interrupt Register */
+#define	RIR			0x2848	/* 16 bit	Receive Interrupt Register */
+#define	TIR_RIR		0x284C	/* 16 bit	Transmit and Receive Interrupt Register */
+#define	TIMR		0x2850	/* 16 bit	Transmit Interrupt Mask Register */
+#define	RIMR		0x2854	/* 16 bit	Receive Interrupt Mask Register */
+#define	TIMR_RIMR	0x2858	/* 16 bit	Transmit and Receive Interrupt Mask
+							 *			Register
+							 */
+#define	FC_TIMEOUT	0x285c	/* 16 bit	Flow Control Timeout Register */
+#define	SMICR		0x2880	/* 16 bit	SMI Control Register */
+#define	SMIDR		0x2884	/* 16 bit	SMI Data Register */
+#define	PAR			0x2888	/* 16 bit	PHY Address Register */
+
+/*
+ *
+ *	THE BIT DEFINES
+ *
+ */
+/*	GPSR		0x2800	General Purpose Status Register */
+#define	GPSR_SPEED				BIT_15S	/* Speed */
+#define	GPSR_DUPLEX				BIT_14S	/* Duplex */
+#define	GPSR_FCTLTX				BIT_13S	/* FctlTx */
+#define	GPSR_LINK				BIT_12S	/* Link */
+#define	GPSR_PAUSE				BIT_11S	/* Pause */
+#define	GPSR_TXINPROG			BIT_10S	/* TxinProg */
+#define	GPSR_EXCESSCOL			BIT_9S	/* ExcessCol */
+#define	GPSR_LATECOL			BIT_8S	/* LateCol */
+#define	GPSR_TX_EN_STATUS		BIT_7S	/* TxEnStatus */
+#define	GPSR_RX_EN_STATUS		BIT_6S	/* RxEnStatus */
+#define	GPSR_MIIPHYSTC			BIT_5S	/* MIIPhySTC */
+#define	GPSR_GIGSPEED			BIT_4S	/* GigSpeed */
+#define	GPSR_PARTITION			BIT_3S	/* Partition */
+#define	GPSR_FCTLRX				BIT_2S	/* FctlRx */
+#define	GPSR_PROMISC_MODE		BIT_1S	/* Promiscuous Mode */
+/*		Bit(s) GPSR_RSRV_0 reserved */
+
+/*	GPCR		0x2804	General Purpose Control Register */
+#define	GPCR_MDIO_SPSEL			BIT_15S	/* mac to phy mdio speed select */
+/*		Bit(s) GPCR_RSRV_14 reserved */
+#define	GPCR_FCTLTX				BIT_13S			/* FCTLTX */
+#define	GPCR_TXEN				BIT_12S			/* TxEn */
+#define	GPCR_RXEN				BIT_11S			/* RxEn */
+/*		Bit(s) GPCR_RSRV_10 reserved */
+#define	GPCR_LPBK				BIT_9S			/* LPBK */
+#define	GPCR_PAR				BIT_8S			/* PAR */
+#define	GPCR_GIGSPEED			BIT_7S			/* GigSpeed */
+#define	GPCR_FLP				BIT_6S			/* FLP */
+#define	GPCR_HD					BIT_5S			/* HD */
+#define	GPCR_FCTLRX				BIT_4S			/* FCTLRX */
+#define	GPCR_SPEED				BIT_3S			/* Speed */
+#define	GPCR_DPLYXEN			BIT_2S			/* DPLYXen */
+#define	GPCR_FCTLEN				BIT_1S			/* FCTLen */
+#define	GPCR_SPEEDEN			BIT_0S			/* SpeedEn */
+
+/*	TCR			0x2808	Transmit Control Register */
+#define	TCR_FJ					BIT_15S			/* FJ */
+#define	TCR_CRCD				BIT_14S			/* CRCD */
+#define	TCR_PADD				BIT_13S			/* PADD */
+#define	TCR_COLTH_MSK			SHIFT10(0x7U)	/* ColTh */
+#define	TCR_COLTH_BASE			10
+#define	TCR_HD_LPBK_DIS			BIT_9S			/* HALF DUPLEX LPBK DISABLE */
+#define	TCR_JAM_FIX_EN			BIT_8S			/* JAM UNH FIX_EN */
+#define	TCR_PADD_PAT_MSK		SHIFT0(0xffU)	/* Padding Pattern */
+#define	TCR_PADD_PAT_BASE		0
+
+/*	RCR			0x280C	Receive Control Register */
+#define	RCR_UNFIEN				BIT_15S			/* UnFiEn */
+#define	RCR_MUFIEN				BIT_14S			/* MuFiEn */
+#define	RCR_CRCR				BIT_13S			/* CRCR */
+/*		Bit(s) RCR_RSRV_12 reserved */
+/*		Bit(s) RCR_RSRV_11_0 reserved */
+
+/*	TFCR		0x2810	Transmit Flow Control Register */
+#define	TFCR_PAUSETIME_MSK		SHIFT0(0xffffU)	/* PauseTime */
+#define	TFCR_PAUSETIME_BASE		0
+
+/*	TPR			0x2814	Transmit Parameter Register */
+#define	TPR_JAM_LEN_MSK				SHIFT14(0x3U)	/* JAM_Len */
+#define	TPR_JAM_LEN_BASE			14
+#define	TPR_JAM_IPG_MSK				SHIFT9(0x1fU)	/* JAM_IPG */
+#define	TPR_JAM_IPG_BASE			9
+#define	TPR_IPGJAM2DATA_MSK			SHIFT4(0x1fU)	/* IPGJAM2Data */
+#define	TPR_IPGJAM2DATA_BASE		4
+#define	TPR_BACK_OFF_LIMIT_MSK		SHIFT0(0xfU)	/* Back-off Limit */
+#define	TPR_BACK_OFF_LIMIT_BASE		0
+
+/*	SMR			0x2818	Serial Mode Register */
+#define	SMR_DATA_BLINDER_MSK		SHIFT11(0x1fU)	/* Data Blinder */
+#define	SMR_DATA_BLINDER_BASE		11
+#define	SMR_LIMIT4					BIT_10S			/* Limit4 */
+#define	SMR_VLAN_EN_MFL_MSK			SHIFT8(0x3U)	/* Vlan_en, MFL */
+#define	SMR_VLAN_EN_MFL_BASE		8
+/*		Bit(s) SMR_RSRV_7_5 reserved */
+#define	SMR_IPGDATA_MSK				SHIFT0(0x1fU)	/* IPGData */
+#define	SMR_IPGDATA_BASE			0
+
+/*	SAL1		0x281C	Source Address Low */
+#define	SAL1_SA1_MSK		SHIFT0(0xffffU)	/* SA1 [15:0] */
+#define	SAL1_SA1_BASE		0
+
+/*	SAM1		0x2820	Source Address Middle */
+#define	SAM1_SA1_MSK		SHIFT0(0xffffU)	/* SA1 [31:16] */
+#define	SAM1_SA1_BASE		0
+
+/*	SA1H		0x2824	Source Address High */
+#define	SA1H_SA1_MSK		SHIFT0(0xffffU)	/* SA1 [47:32] */
+#define	SA1H_SA1_BASE		0
+
+/*	SAL2		0x2828	Source Address Low */
+#define	SAL2_SA2_MSK		SHIFT0(0xffffU)	/* SA2 [15:0] */
+#define	SAL2_SA2_BASE		0
+
+/*	SAM2		0x282C	Source Address Middle */
+#define	SAM2_SA2_MSK		SHIFT0(0xffffU)	/* SA2 [31:16] */
+#define	SAM2_SA2_BASE		0
+
+/*	SAH2		0x2830	Source Address High */
+#define	SAH2_SA2_MSK		SHIFT0(0xffffU)	/* SA 2[47:32] */
+#define	SAH2_SA2_BASE		0
+
+/*	MCAH1		0x2834	Multicast Address Hash Register 1 */
+#define	MCAH1_MCAH1_MSK			SHIFT0(0xffffU)	/* MCAH1[15:0] */
+#define	MCAH1_MCAH1_BASE		0
+
+/*	MCAH2		0x2838	Multicast Address Hash Register 2 */
+#define	MCAH2_MCAH2_MSK			SHIFT0(0xffffU)	/* MCAH2[15:0] */
+#define	MCAH2_MCAH2_BASE		0
+
+/*	MCAH3		0x283C	Multicast Address Hash Register 3 */
+#define	MCAH3__MCAH3_MSK		SHIFT0(0xffffU)	/* MCAH3[15:0] */
+#define	MCAH3__MCAH3_BASE		0
+
+/*	MCAH4		0x2840	Multicast Address Hash Register 4 */
+#define	MCAH4_MCAH4_MSK			SHIFT0(0xffffU)	/* MCAH4[15:0] */
+#define	MCAH4_MCAH4_BASE		0
+
+/*	TIR			0x2844	Transmit Interrupt Register */
+#define	TIR_LATE				BIT_15S			/* Late */
+#define	TIR_COLLISIONS			BIT_14S			/* Collisions */
+#define	TIR_DEFER				BIT_13S			/* Defer */
+#define	TIR_OUTMAXOCTETS		BIT_12S			/* OutMaxOctets */
+#define	TIR_OUT1518OCTETS		BIT_11S			/* Out1518Octets */
+#define	TIR_OUT1023OCTETS		BIT_10S			/* Out1023Octets */
+#define	TIR_OUT511OCTETS		BIT_9S			/* Out511Octets */
+#define	TIR_OUT255OCTETS		BIT_8S			/* Out255Octets */
+#define	TIR_OUT127OCTETS		BIT_7S			/* Out127Octets */
+#define	TIR_OUT64OCTETS			BIT_6S			/* Out64octets */
+#define	TIR_OUTOCTETS_MSK		SHIFT4(0x3U)	/* OutOctets */
+#define	TIR_OUTOCTETS_BASE		4
+#define	TIR_OUTMULTICASTS		BIT_3S			/* OutMulticasts */
+#define	TIR_OUTPAUSE			BIT_2S			/* OutPause */
+#define	TIR_OUTBROADCASTS		BIT_1S			/* OutBroadcasts */
+#define	TIR_OUTUNICASTS			BIT_0S			/* OutUnicasts */
+
+/*	RIR			0x2848	Receive Interrupt Register */
+#define	RIR_IN511OCTETS			BIT_15S			/* In511Octets */
+#define	RIR_IN255OCTETS			BIT_14S			/* In255Octets */
+#define	RIR_IN127OCTETS			BIT_13S			/* In127Octets */
+#define	RIR_IN64OCTETS			BIT_12S			/* In64Octets */
+#define	RIR_FRAGMENTS			BIT_11S			/* Fragments */
+#define	RIR_UNDERSIZE			BIT_10S			/* Undersize */
+#define	RIR_INBADOCTETS_MSK		SHIFT8(0x3U)	/* InBadOctets */
+#define	RIR_INBADOCTETS_BASE	8
+#define	RIR_INGOODOCTETS_MSK	SHIFT6(0x3U)	/* InGoodOctets */
+#define	RIR_INGOODOCTETS_BASE	6
+#define	RIR_SPARE				BIT_5S			/* Spare */
+#define	RIR_INFCSERR			BIT_4S			/* InFCSErr */
+#define	RIR_INMULTICASTS		BIT_3S			/* InMulticasts */
+#define	RIR_INPAUSE				BIT_2S			/* InPause */
+#define	RIR_INBROADCASTS		BIT_1S			/* InBroadcasts */
+#define	RIR_INUNICASTS			BIT_0S			/* InUnicasts */
+
+/*	TIR_RIR		0x284C	Transmit and Receive Interrupt Register */
+/*		Bit(s) TIR_RIR_RSRV_15_12 reserved */
+#define	TIR_RIR_UNDERFLOW			BIT_11S			/* Underflow */
+#define	TIR_RIR_SINGLE				BIT_10S			/* Single */
+#define	TIR_RIR_MULTIPLE			BIT_9S			/* Multiple */
+#define	TIR_RIR_EXCESSIVE			BIT_8S			/* Excessive */
+#define	TIR_RIR_ALIGMENT_ERROR		BIT_7S			/* Align_error */
+#define	TIR_RIR_OVERFLOW			BIT_6S			/* Overflow */
+#define	TIR_RIR_SYMBOL_ERR			BIT_5S			/* Symbol_error */
+#define	TIR_RIR_JABBER				BIT_4S			/* Jabber */
+#define	TIR_RIR_OVERSIZE			BIT_3S			/* OverSize */
+#define	TIR_RIR_INMAXOCTETS			BIT_2S			/* InMaxOctets */
+#define	TIR_RIR_IN1518OCTETS		BIT_1S			/* In1518Octets */
+#define	TIR_RIR_IN1023OCTETS		BIT_0S			/* In1023Octets */
+
+/*	TIMR		0x2850	Transmit Interrupt Mask Register */
+#define	TIMR_TIMR_MSK		SHIFT0(0xffffU)	/* TIMR[15:0] */
+#define	TIMR_TIMR_BASE		0
+
+/*	RIMR		0x2854	Receive Interrupt Mask Register */
+#define	RIMR_RIMR_MSK		SHIFT0(0xffffU)	/* RIMR[15:0] */
+#define	RIMR_RIMR_BASE		0
+
+/*	TIMR_RIMR	0x2858	Transmit and Receive Interrupt Mask Register */
+#define	TIMR_RIMR_TIMR_RIMR_MSK			SHIFT0(0xffffU)	/* TIMR_RIMR[15:0] */
+#define	TIMR_RIMR_TIMR_RIMR_BASE		0
+
+/*	FC_TIMEOUT	0x285c	Flow Control Timeout Register */
+#define	FC_TIMEOUT_FC_TIMEOUT_MSK		SHIFT0(0xffffU)	/* FC_TIMEOUT[15:0] */
+#define	FC_TIMEOUT_FC_TIMEOUT_BASE		0
+
+/*	SMICR		0x2880	SMI Control Register */
+#define	SMICR_PHYAD_MSK			SHIFT11(0x1fU)	/* PhyAd */
+#define	SMICR_PHYAD_BASE		11
+#define	SMICR_REGAD_MSK			SHIFT6(0x1fU)	/* RegAd */
+#define	SMICR_REGAD_BASE		6
+#define	SMICR_OPCODE			BIT_5S			/* OpCode */
+#define	SMICR_READVALID			BIT_4S			/* ReadValid */
+#define	SMICR_BUSY				BIT_3S			/* Busy */
+/*		Bit(s) SMICR_RSRV_2_0 reserved */
+
+/*	SMIDR		0x2884	SMI Data Register */
+#define	SMIDR_DATA_MSK		SHIFT0(0xffffU)	/* Data */
+#define	SMIDR_DATA_BASE		0
+
+/*	PAR			0x2888	PHY Address Register */
+/*		Bit(s) PAR_RSRV_15_6 reserved */
+#define	PAR_MIBCLRMODE			BIT_5S			/* MIBclrMode */
+#define	PAR_LOADTSTCNT			BIT_4S			/* LoadTstCnt */
+/*		Bit(s) PAR_RSRV_3_0 reserved */
+
+
+
+/* -------------------- */
+
+
+#endif	/* __INC_SKY3HW_H */
diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
new file mode 100755
index 0000000..1141782
--- /dev/null
+++ b/drivers/net/sk98lin/h/skaddr.h
@@ -0,0 +1,341 @@
+/******************************************************************************
+ *
+ * Name:	skaddr.h
+ * Project:	Gigabit Ethernet Adapters, ADDR-Modul
+ * Version:	$Revision: 2.3 $
+ * Date:	$Date: 2005/12/21 08:55:06 $
+ * Purpose:	Header file for Address Management (MC, UC, Prom).
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * This module is intended to manage multicast addresses and promiscuous mode
+ * on GEnesis adapters.
+ *
+ * Include File Hierarchy:
+ *
+ *	"skdrv1st.h"
+ *	...
+ *	"sktypes.h"
+ *	"skqueue.h"
+ *	"skaddr.h"
+ *	...
+ *	"skdrv2nd.h"
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKADDR_H
+#define __INC_SKADDR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* cplusplus */
+
+/* defines ********************************************************************/
+
+#define SK_MAC_ADDR_LEN				6	/* Length of MAC address. */
+#define	SK_MAX_ADDRS				14	/* #Addrs for exact match. */
+
+/* ----- Common return values ----- */
+
+#define SK_ADDR_SUCCESS				0	/* Function returned successfully. */
+#define SK_ADDR_ILLEGAL_PORT			100	/* Port number too high. */
+#define SK_ADDR_TOO_EARLY			101	/* Function called too early. */
+
+/* ----- Clear/Add flag bits ----- */
+
+#define SK_ADDR_PERMANENT			1	/* RLMT Address */
+
+/* ----- Additional Clear flag bits ----- */
+
+#define SK_MC_SW_ONLY				2	/* Do not update HW when clearing. */
+
+/* ----- Override flag bits ----- */
+
+#define SK_ADDR_LOGICAL_ADDRESS		0
+#define SK_ADDR_VIRTUAL_ADDRESS		(SK_ADDR_LOGICAL_ADDRESS)	/* old */
+#define SK_ADDR_PHYSICAL_ADDRESS	1
+#define SK_ADDR_CLEAR_LOGICAL		2
+#define SK_ADDR_SET_LOGICAL			4
+
+/* ----- Override return values ----- */
+
+#define SK_ADDR_OVERRIDE_SUCCESS	(SK_ADDR_SUCCESS)
+#define SK_ADDR_DUPLICATE_ADDRESS	1
+#define SK_ADDR_MULTICAST_ADDRESS	2
+
+/* ----- Partitioning of excact match table ----- */
+
+#define SK_ADDR_EXACT_MATCHES		16	/* #Exact match entries. */
+
+#define SK_ADDR_FIRST_MATCH_RLMT	1
+#define SK_ADDR_LAST_MATCH_RLMT		2
+#define SK_ADDR_FIRST_MATCH_DRV		3
+#define SK_ADDR_LAST_MATCH_DRV		(SK_ADDR_EXACT_MATCHES - 1)
+
+/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
+
+#define SK_MC_FILTERING_EXACT		0	/* Exact filtering. */
+#define SK_MC_FILTERING_INEXACT		1	/* Inexact filtering. */
+
+/* ----- Additional SkAddrMcAdd return values ----- */
+
+#define SK_MC_ILLEGAL_ADDRESS		2	/* Illegal address. */
+#define SK_MC_ILLEGAL_PORT			3	/* Illegal port (not the active one). */
+#define SK_MC_RLMT_OVERFLOW			4	/* Too many RLMT mc addresses. */
+
+/* Promiscuous mode bits ----- */
+
+#define SK_PROM_MODE_NONE			0	/* Normal receive. */
+#define SK_PROM_MODE_LLC			1	/* Receive all LLC frames. */
+#define SK_PROM_MODE_ALL_MC			2	/* Receive all multicast frames. */
+/* #define SK_PROM_MODE_NON_LLC		4 */	/* Receive all non-LLC frames. */
+
+/* Macros */
+
+#ifdef OLD_STUFF
+#ifndef SK_ADDR_EQUAL
+/*
+ * "&" instead of "&&" allows better optimization on IA-64.
+ * The replacement is safe here, as all bytes exist.
+ */
+#ifndef SK_ADDR_DWORD_COMPARE
+#define SK_ADDR_EQUAL(A1,A2)	( \
+	(((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
+	(((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
+	(((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
+	(((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
+	(((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
+	(((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
+#else	/* SK_ADDR_DWORD_COMPARE */
+#define SK_ADDR_EQUAL(A1,A2)	( \
+	(*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
+	(*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
+#endif	/* SK_ADDR_DWORD_COMPARE */
+#endif	/* SK_ADDR_EQUAL */
+#endif /* 0 */
+
+#ifndef SK_ADDR_EQUAL
+#ifndef SK_ADDR_DWORD_COMPARE
+#define SK_ADDR_EQUAL(A1,A2)	( \
+	(((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
+	(((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
+	(((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
+	(((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
+	(((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
+	(((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
+#else	/* SK_ADDR_DWORD_COMPARE */
+#define SK_ADDR_EQUAL(A1,A2)	( \
+	(*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
+	*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
+	(*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
+	*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
+#endif	/* SK_ADDR_DWORD_COMPARE */
+#endif	/* SK_ADDR_EQUAL */
+
+/* typedefs *******************************************************************/
+
+typedef struct s_MacAddr {
+	SK_U8	a[SK_MAC_ADDR_LEN];
+} SK_MAC_ADDR;
+
+
+/* SK_FILTER is used to ensure alignment of the filter. */
+typedef union s_InexactFilter {
+	SK_U8	Bytes[8];
+	SK_U64	Val;	/* Dummy entry for alignment only. */
+} SK_FILTER64;
+
+
+typedef struct s_AddrNet SK_ADDR_NET;
+
+
+typedef struct s_AddrPort {
+
+/* ----- Public part (read-only) ----- */
+
+	SK_MAC_ADDR	CurrentMacAddress;	/* Current physical MAC Address. */
+	SK_MAC_ADDR	PermanentMacAddress;	/* Permanent physical MAC Address. */
+	int		PromMode;		/* Promiscuous Mode. */
+
+/* ----- Private part ----- */
+
+	SK_MAC_ADDR	PreviousMacAddress;	/* Prev. phys. MAC Address. */
+	SK_BOOL		CurrentMacAddressSet;	/* CurrentMacAddress is set. */
+	SK_U8		Align01;
+
+	SK_U32		FirstExactMatchRlmt;
+	SK_U32		NextExactMatchRlmt;
+	SK_U32		FirstExactMatchDrv;
+	SK_U32		NextExactMatchDrv;
+	SK_MAC_ADDR	Exact[SK_ADDR_EXACT_MATCHES];
+	SK_FILTER64	InexactFilter;			/* For 64-bit hash register. */
+	SK_FILTER64	InexactRlmtFilter;		/* For 64-bit hash register. */
+	SK_FILTER64	InexactDrvFilter;		/* For 64-bit hash register. */
+} SK_ADDR_PORT;
+
+
+struct s_AddrNet {
+/* ----- Public part (read-only) ----- */
+
+	SK_MAC_ADDR		CurrentMacAddress;	/* Logical MAC Address. */
+	SK_MAC_ADDR		PermanentMacAddress;	/* Logical MAC Address. */
+
+/* ----- Private part ----- */
+
+	SK_U32			ActivePort;		/* View of module ADDR. */
+	SK_BOOL			CurrentMacAddressSet;	/* CurrentMacAddress is set. */
+	SK_U8			Align01;
+	SK_U16			Align02;
+};
+
+
+typedef struct s_Addr {
+
+/* ----- Public part (read-only) ----- */
+
+	SK_ADDR_NET		Net[SK_MAX_NETS];
+	SK_ADDR_PORT	Port[SK_MAX_MACS];
+
+/* ----- Private part ----- */
+} SK_ADDR;
+
+/* function prototypes ********************************************************/
+
+#ifndef SK_KR_PROTO
+
+/* Functions provided by SkAddr */
+
+/* ANSI/C++ compliant function prototypes */
+
+extern	int	SkAddrInit(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int	Level);
+
+extern	int	SkAddrMcClear(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber,
+	int	Flags);
+
+extern	int	SkAddrXmacMcClear(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber,
+	int	Flags);
+
+extern	int	SkAddrGmacMcClear(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber,
+	int	Flags);
+
+extern	int	SkAddrMcAdd(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	SK_U32		PortNumber,
+	SK_MAC_ADDR	*pMc,
+	int		Flags);
+
+extern	int	SkAddrXmacMcAdd(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	SK_U32		PortNumber,
+	SK_MAC_ADDR	*pMc,
+	int		Flags);
+
+extern	SK_U32	SkXmacMcHash(
+	unsigned char *pMc);
+
+extern	int	SkAddrGmacMcAdd(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	SK_U32		PortNumber,
+	SK_MAC_ADDR	*pMc,
+	int		Flags);
+
+extern	SK_U32	SkGmacMcHash(
+	unsigned char *pMc);
+
+extern	int	SkAddrMcUpdate(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber);
+
+extern	int	SkAddrXmacMcUpdate(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber);
+
+extern	int	SkAddrGmacMcUpdate(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber);
+
+extern	int	SkAddrOverride(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	SK_U32		PortNumber,
+	SK_MAC_ADDR	SK_FAR *pNewAddr,
+	int		Flags);
+
+extern	int	SkAddrPromiscuousChange(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber,
+	int	NewPromMode);
+
+extern	int	SkAddrXmacPromiscuousChange(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber,
+	int	NewPromMode);
+
+extern	int	SkAddrGmacPromiscuousChange(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	PortNumber,
+	int	NewPromMode);	
+
+#ifndef SK_SLIM
+extern	int	SkAddrSwap(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	FromPortNumber,
+	SK_U32	ToPortNumber);
+#endif
+
+#else	/* defined(SK_KR_PROTO)) */
+
+/* Non-ANSI/C++ compliant function prototypes */
+
+#error KR-style prototypes are not yet provided.
+
+#endif	/* defined(SK_KR_PROTO)) */
+
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif	/* __INC_SKADDR_H */
diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
new file mode 100755
index 0000000..b72ba1c
--- /dev/null
+++ b/drivers/net/sk98lin/h/skcsum.h
@@ -0,0 +1,233 @@
+/******************************************************************************
+ *
+ * Name:	skcsum.h
+ * Project:	GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
+ * Version:	$Revision: 2.5 $
+ * Date:	$Date: 2007/03/14 16:21:28 $
+ * Purpose:	Store/verify Internet checksum in send/receive packets.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2001 SysKonnect GmbH.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * Public header file for the "GEnesis" common module "CSUM".
+ *
+ * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
+ * and is the code name of this SysKonnect project.
+ *
+ * Compilation Options:
+ *
+ *	SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
+ *	empty module.
+ *
+ *	SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
+ *	definitions. In this case, all SKCS_PROTO_xxx definitions must be made
+ *	external.
+ *
+ *	SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
+ *	definitions. In this case, all SKCS_STATUS_xxx definitions must be made
+ *	external.
+ *
+ * Include File Hierarchy:
+ *
+ *	"h/skcsum.h"
+ *	 "h/sktypes.h"
+ *	 "h/skqueue.h"
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKCSUM_H
+#define __INC_SKCSUM_H
+
+#include "h/sktypes.h"
+#include "h/skqueue.h"
+
+/* defines ********************************************************************/
+
+/* The size of the IP header without any option fields. */
+#define SKCS_IP_HEADER_SIZE						20
+
+#ifdef SK_IPV6_SUPPORT
+/* The size of the IPv6 header */
+#define SKCS_IP6_HEADER_SIZE					40
+#endif	/* SK_IPV6_SUPPORT */
+
+/*
+ * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags'  if no user
+ * overwrite.
+ */
+#ifndef SKCS_OVERWRITE_PROTO	/* User overwrite? */
+#define SKCS_PROTO_IP		0x1		/* IP (Internet Protocol version 4) */
+#define SKCS_PROTO_TCP		0x2		/* TCP (Transmission Control Protocol) */
+#define SKCS_PROTO_UDP		0x4		/* UDP (User Datagram Protocol) */
+
+#define SKCS_PROTO_TCPV6	0x20	/* TCP for IPv6 packets */
+#define SKCS_PROTO_UDPV6	0x40	/* UDP for IPv6 packets */
+
+/* Indices for protocol statistics. */
+#define SKCS_PROTO_STATS_IP	0
+#define SKCS_PROTO_STATS_UDP	1
+#define SKCS_PROTO_STATS_TCP	2
+#define SKCS_NUM_PROTOCOLS	3	/* Number of supported protocols. */
+#endif	/* !SKCS_OVERWRITE_PROTO */
+
+/*
+ * Define the default SKCS_STATUS type and values if no user overwrite.
+ *
+ *	SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
+ *	SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
+ *	SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
+ *	SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
+ *	SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
+ *	SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
+ *	SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
+ *	SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
+ *	SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
+ *	SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
+ *	SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. 
+ *	SKCS_STATUS_NO_CSUM_POSSIBLE - Checksum could not be built (various reasons).
+ */
+#ifndef SKCS_OVERWRITE_STATUS	/* User overwrite? */
+#define SKCS_STATUS	int	/* Define status type. */
+
+#define SKCS_STATUS_UNKNOWN_IP_VERSION	1
+#define SKCS_STATUS_IP_CSUM_ERROR		2
+#define SKCS_STATUS_IP_FRAGMENT			3
+#define SKCS_STATUS_IP_CSUM_OK			4
+#define SKCS_STATUS_TCP_CSUM_ERROR		5
+#define SKCS_STATUS_UDP_CSUM_ERROR		6
+#define SKCS_STATUS_TCP_CSUM_OK			7
+#define SKCS_STATUS_UDP_CSUM_OK			8
+/* needed for Microsoft */
+#define SKCS_STATUS_IP_CSUM_ERROR_UDP	9
+#define SKCS_STATUS_IP_CSUM_ERROR_TCP	10
+/* UDP checksum may be omitted */
+#define SKCS_STATUS_IP_CSUM_OK_NO_UDP	11
+#define SKCS_STATUS_NO_CSUM_POSSIBLE	12
+#endif	/* !SKCS_OVERWRITE_STATUS */
+
+/* Clear protocol statistics event. */
+#define SK_CSUM_EVENT_CLEAR_PROTO_STATS	1
+
+/*
+ * Add two values in one's complement.
+ *
+ * Note: One of the two input values may be "longer" than 16-bit, but then the
+ * resulting sum may be 17 bits long. In this case, add zero to the result using
+ * SKCS_OC_ADD() again.
+ *
+ *	Result = Value1 + Value2
+ */
+#define SKCS_OC_ADD(Result, Value1, Value2) {				\
+	unsigned long Sum;						\
+									\
+	Sum = (unsigned long) (Value1) + (unsigned long) (Value2);	\
+	/* Add-in any carry. */						\
+	(Result) = (Sum & 0xffff) + (Sum >> 16);			\
+}
+
+/*
+ * Subtract two values in one's complement.
+ *
+ *	Result = Value1 - Value2
+ */
+#define SKCS_OC_SUB(Result, Value1, Value2)	\
+	SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff)
+
+/* typedefs *******************************************************************/
+
+/*
+ * SKCS_PROTO_STATS - The CSUM protocol statistics structure.
+ *
+ * There is one instance of this structure for each protocol supported.
+ */
+typedef struct s_CsProtocolStatistics {
+	SK_U64 RxOkCts;		/* Receive checksum ok. */
+	SK_U64 RxUnableCts;	/* Unable to verify receive checksum. */
+	SK_U64 RxErrCts;	/* Receive checksum error. */
+	SK_U64 TxOkCts;		/* Transmit checksum ok. */
+	SK_U64 TxUnableCts;	/* Unable to calculate checksum in hw. */
+} SKCS_PROTO_STATS;
+
+/*
+ * s_Csum - The CSUM module context structure.
+ */
+typedef struct s_Csum {
+	/* Enabled receive SK_PROTO_XXX bit flags. */
+	unsigned ReceiveFlags[SK_MAX_NETS];
+	unsigned TransmitFlags[SK_MAX_NETS];
+
+	/* The protocol statistics structure; one per supported protocol. */
+	SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
+} SK_CSUM;
+
+/*
+ * SKCS_PACKET_INFO - The packet information structure.
+ */
+typedef struct s_CsPacketInfo {
+	/* Bit field specifiying the desired/found protocols. */
+	unsigned ProtocolFlags;
+
+	/* Length of complete IP header, including any option fields. */
+	unsigned IpHeaderLength;
+
+	/* IP header checksum. */
+	unsigned IpHeaderChecksum;
+
+	/* TCP/UDP pseudo header checksum. */
+	unsigned PseudoHeaderChecksum;
+} SKCS_PACKET_INFO;
+
+/* function prototypes ********************************************************/
+
+#ifndef SK_CS_CALCULATE_CHECKSUM
+extern unsigned SkCsCalculateChecksum(
+	void		*pData,
+	unsigned	Length);
+#endif /* SK_CS_CALCULATE_CHECKSUM */
+
+extern int SkCsEvent(
+	SK_AC		*pAc,
+	SK_IOC		Ioc,
+	SK_U32		Event,
+	SK_EVPARA	Param);
+
+extern SKCS_STATUS SkCsGetReceiveInfo(
+	SK_AC		*pAc,
+	void		*pIpHeader,
+	unsigned	Checksum1,
+	unsigned	Checksum2,
+	int			NetNumber,
+	unsigned	Len);
+
+extern void SkCsGetSendInfo(
+	SK_AC				*pAc,
+	void				*pIpHeader,
+	SKCS_PACKET_INFO	*pPacketInfo,
+	int					NetNumber);
+
+extern void SkCsSetReceiveFlags(
+	SK_AC		*pAc,
+	unsigned	ReceiveFlags,
+	unsigned	*pChecksum1Offset,
+	unsigned	*pChecksum2Offset,
+	int			NetNumber);
+
+#endif	/* __INC_SKCSUM_H */
diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
new file mode 100755
index 0000000..adaa794
--- /dev/null
+++ b/drivers/net/sk98lin/h/skdebug.h
@@ -0,0 +1,92 @@
+/******************************************************************************
+ *
+ * Name:	skdebug.h
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.5 $
+ * Date:	$Date: 2007/03/20 08:43:56 $
+ * Purpose:	SK specific DEBUG support
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKDEBUG_H
+#define __INC_SKDEBUG_H
+
+#ifdef	DEBUG
+#ifndef SK_DBG_MSG
+#define SK_DBG_MSG(pAC,comp,cat,arg) \
+		if ( ((comp) & SK_DBG_CHKMOD(pAC)) &&	\
+		      ((cat) & SK_DBG_CHKCAT(pAC)) ) {	\
+			SK_DBG_PRINTF arg;		\
+		}
+#endif
+#ifndef SK_DBG_DMP
+#define SK_DBG_DMP(pAC,comp,cat,addr,len) \
+		if ( ((comp) & SK_DBG_CHKMOD(pAC)) &&	\
+		      ((cat) & SK_DBG_CHKCAT(pAC)) &&	\
+		      (SK_DBG_CHKCAT(pAC) & SK_DBGCAT_DUMP ) ) {	\
+			DUMP( addr, len );		\
+		}
+#endif
+#else
+#define SK_DBG_MSG(pAC,comp,lev,arg)
+#define SK_DBG_DMP(pAC,comp,cat,addr,len)
+#endif
+
+/* PLS NOTE:
+ * =========
+ * Due to any restrictions of kernel printf routines do not use other
+ * format identifiers as: %x %d %c %s .
+ * Never use any combined format identifiers such as: %lx %ld in your
+ * printf - argument (arg) because some OS specific kernel printfs may
+ * only support some basic identifiers.
+ */
+
+/* Debug modules */
+
+#define SK_DBGMOD_MERR	0x00000001L	/* general module error indication */
+#define SK_DBGMOD_HWM	0x00000002L	/* Hardware init module */
+#define SK_DBGMOD_RLMT	0x00000004L	/* RLMT module */
+#define SK_DBGMOD_VPD	0x00000008L	/* VPD module */
+#define SK_DBGMOD_I2C	0x00000010L	/* I2C module */
+#define SK_DBGMOD_PNMI	0x00000020L	/* PNMI module */
+#define SK_DBGMOD_CSUM	0x00000040L	/* CSUM module */
+#define SK_DBGMOD_ADDR	0x00000080L	/* ADDR module */
+#define SK_DBGMOD_PECP	0x00000100L	/* PECP module */
+#define SK_DBGMOD_POWM	0x00000200L	/* Power Management module */
+#ifdef SK_ASF
+#define SK_DBGMOD_ASF	0x00000400L	/* ASF module */
+#endif
+#ifdef SK_LBFO
+#define SK_DBGMOD_LACP	0x00000800L	/* link aggregation control protocol */
+#define SK_DBGMOD_FD	0x00001000L	/* frame distributor (link aggregation) */
+#endif /* SK_LBFO */
+#define SK_DBGMOD_MACS	0x00002000L	/* MACSec module */
+
+/* Debug events */
+
+#define SK_DBGCAT_INIT	0x00000001L	/* module/driver initialization */
+#define SK_DBGCAT_CTRL	0x00000002L	/* controlling devices */
+#define SK_DBGCAT_ERR	0x00000004L	/* error handling paths */
+#define SK_DBGCAT_TX	0x00000008L	/* transmit path */
+#define SK_DBGCAT_RX	0x00000010L	/* receive path */
+#define SK_DBGCAT_IRQ	0x00000020L	/* general IRQ handling */
+#define SK_DBGCAT_QUEUE	0x00000040L	/* any queue management */
+#define SK_DBGCAT_DUMP	0x00000080L	/* large data output e.g. hex dump */
+#define SK_DBGCAT_FATAL	0x00000100L	/* fatal error */
+
+#endif	/* __INC_SKDEBUG_H */
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
new file mode 100755
index 0000000..694e509
--- /dev/null
+++ b/drivers/net/sk98lin/h/skdrv1st.h
@@ -0,0 +1,185 @@
+/******************************************************************************
+ *
+ * Name:	skdrv1st.h
+ * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.6.4.2 $
+ * Date:	$Date: 2007/10/02 09:13:23 $
+ * Purpose:	First header file for driver and all other modules
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKDRV1ST_H
+#define __INC_SKDRV1ST_H
+
+/* Check kernel version */
+#include <linux/version.h>
+
+typedef struct s_AC	SK_AC;
+
+/* Set card versions */
+#define SK_FAR
+
+/* override some default functions with optimized linux functions */
+
+#define SK_PNMI_STORE_U16(p,v)		memcpy((char*)(p),(char*)&(v),2)
+#define SK_PNMI_STORE_U32(p,v)		memcpy((char*)(p),(char*)&(v),4)
+#define SK_PNMI_STORE_U64(p,v)		memcpy((char*)(p),(char*)&(v),8)
+#define SK_PNMI_READ_U16(p,v)		memcpy((char*)&(v),(char*)(p),2)
+#define SK_PNMI_READ_U32(p,v)		memcpy((char*)&(v),(char*)(p),4)
+#define SK_PNMI_READ_U64(p,v)		memcpy((char*)&(v),(char*)(p),8)
+
+#define SK_ADDR_EQUAL(a1,a2)		(!memcmp(a1,a2,6))
+
+#define SK_STRNCMP(s1,s2,len)		strncmp(s1,s2,len)
+#define SK_STRCPY(dest,src)		strcpy(dest,src)
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/byteorder.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <net/checksum.h>
+
+#define SK_CS_CALCULATE_CHECKSUM
+#define SkCsCalculateChecksum(p,l)	(~csum_fold(csum_partial(p, l, 0)))
+
+#include	"h/sktypes.h"
+#include	"h/skerror.h"
+#include	"h/skdebug.h"
+#include	"h/lm80.h"
+#include	"h/xmac_ii.h"
+
+#ifndef SK_BMU_RX_WM_PEX
+#define SK_BMU_RX_WM_PEX 0x80
+#endif
+
+#ifdef __LITTLE_ENDIAN
+#define SK_LITTLE_ENDIAN
+#else
+#define SK_BIG_ENDIAN
+#define SK_USE_REV_DESC
+#endif
+
+#define SK_NET_DEVICE	net_device
+
+
+/* we use gethrtime(), return unit: nanoseconds */
+#define SK_TICKS_PER_SEC	100
+
+#define	SK_MEM_MAPPED_IO
+
+// #define SK_RLMT_SLOW_LOOKAHEAD
+
+#define SK_MAX_MACS		2
+#define SK_MAX_NETS		2
+
+typedef void __iomem	*SK_IOC;
+
+typedef struct s_DrvRlmtMbuf SK_MBUF;
+
+#define	SK_CONST64	INT64_C
+#define	SK_CONSTU64	UINT64_C
+
+#define SK_MEMCPY(dest,src,size)	memcpy(dest,src,size)
+#define SK_MEMCMP(s1,s2,size)		memcmp(s1,s2,size)
+#define SK_MEMSET(dest,val,size)	memset(dest,val,size)
+#define SK_STRLEN(pStr)			strlen((char*)(pStr))
+#define SK_STRNCPY(pDest,pSrc,size)	strncpy((char*)(pDest),(char*)(pSrc),size)
+#define SK_STRCMP(pStr1,pStr2)		strcmp((char*)(pStr1),(char*)(pStr2))
+
+/* macros to access the adapter */
+#define SK_OUT8(b,a,v)		writeb((v), ((b)+(a)))	
+#define SK_OUT16(b,a,v)		writew((v), ((b)+(a)))	
+#define SK_OUT32(b,a,v)		writel((v), ((b)+(a)))	
+#define SK_IN8(b,a,pv)		(*(pv) = readb((b)+(a)))
+#define SK_IN16(b,a,pv)		(*(pv) = readw((b)+(a)))
+#define SK_IN32(b,a,pv)		(*(pv) = readl((b)+(a)))
+
+#define int8_t		char
+#define int16_t		short
+#define int32_t		long
+#define int64_t		long long
+#define uint8_t		u_char
+#define uint16_t	u_short
+#define uint32_t	u_long
+#define uint64_t	unsigned long long
+#define t_scalar_t	int
+#define t_uscalar_t	unsigned int
+#define uintptr_t	unsigned long
+
+#define __CONCAT__(A,B) A##B
+
+#define INT32_C(a)		__CONCAT__(a,L)
+#define INT64_C(a)		__CONCAT__(a,LL)
+#define UINT32_C(a)		__CONCAT__(a,UL)
+#define UINT64_C(a)		__CONCAT__(a,ULL)
+
+#ifdef DEBUG
+#define SK_DBG_PRINTF		printk
+#ifndef SK_DEBUG_CHKMOD
+#define SK_DEBUG_CHKMOD		0
+#endif
+#ifndef SK_DEBUG_CHKCAT
+#define SK_DEBUG_CHKCAT		0
+#endif
+/* those come from the makefile */
+#define SK_DBG_CHKMOD(pAC)	(SK_DEBUG_CHKMOD)
+#define SK_DBG_CHKCAT(pAC)	(SK_DEBUG_CHKCAT)
+
+extern void SkDbgPrintf(const char *format,...);
+
+#define SK_DBGMOD_DRV			0x00010000
+
+/**** possible driver debug categories ********************************/
+#define SK_DBGCAT_DRV_ENTRY		0x00010000
+#define SK_DBGCAT_DRV_SAP		0x00020000
+#define SK_DBGCAT_DRV_MCA		0x00040000
+#define SK_DBGCAT_DRV_TX_PROGRESS	0x00080000
+#define SK_DBGCAT_DRV_RX_PROGRESS	0x00100000
+#define SK_DBGCAT_DRV_PROGRESS		0x00200000
+#define SK_DBGCAT_DRV_MSG		0x00400000
+#define SK_DBGCAT_DRV_PROM		0x00800000
+#define SK_DBGCAT_DRV_TX_FRAME		0x01000000
+#define SK_DBGCAT_DRV_ERROR		0x02000000
+#define SK_DBGCAT_DRV_INT_SRC		0x04000000
+#define SK_DBGCAT_DRV_EVENT		0x08000000
+
+#endif
+
+#define SK_ERR_LOG		SkErrorLog
+
+extern void SkErrorLog(SK_AC*, int, int, char*);
+
+#endif
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
new file mode 100755
index 0000000..72bb552
--- /dev/null
+++ b/drivers/net/sk98lin/h/skdrv2nd.h
@@ -0,0 +1,927 @@
+/******************************************************************************
+ *
+ * Name:        skdrv2nd.h
+ * Project:     GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:     $Revision: 1.34.4.16 $
+ * Date:        $Date: 2007/10/15 14:35:35 $
+ * Purpose:     Second header file for driver and all other modules
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * This is the second include file of the driver, which includes all other
+ * neccessary files and defines all structures and constants used by the
+ * driver and the common modules.
+ *
+ * Include File Hierarchy:
+ *
+ *	see skge.c
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKDRV2ND_H
+#define __INC_SKDRV2ND_H
+
+#include "h/skqueue.h"
+#include "h/skgehwt.h"
+#include "h/sktimer.h"
+#include "h/sktwsi.h"
+#include "h/skgepnmi.h"
+#include "h/skvpd.h"
+#include "h/skgehw.h"
+#include "h/sky2le.h"
+#include "h/skgeinit.h"
+#include "h/skaddr.h"
+#include "h/skgesirq.h"
+#include "h/skcsum.h"
+#include "h/skrlmt.h"
+#include "h/skgedrv.h"
+#include "h/mvyexhw.h"
+#ifdef SK_ASF
+#include "h/skgeasf.h"
+#include "h/skgeasfconv.h"
+#endif
+
+/* Defines for the poll cotroller */
+#if !defined(SK_NETDUMP_POLL)
+#define SK_NETDUMP_POLL
+#endif
+
+#if defined(SK_NETDUMP_POLL)
+#if defined(HAVE_POLL_CONTROLLER)
+#define SK_POLL_CONTROLLER
+#define CONFIG_SK98LIN_NAPI
+#elif defined(CONFIG_NET_POLL_CONTROLLER)
+#define SK_POLL_CONTROLLER
+#if !defined(CONFIG_SK98LIN_NAPI)
+#define CONFIG_SK98LIN_NAPI
+#endif
+#endif
+#endif
+
+/******************************************************************************
+ *
+ * Generic driver defines
+ *
+ ******************************************************************************/
+
+#define USE_TIST_FOR_RESET	/* Use timestamp for reset */
+#define Y2_RECOVERY		/* use specific recovery yukon2 functions */
+#define Y2_LE_CHECK		/* activate check for LE order */
+#define Y2_SYNC_CHECK		/* activate check for receiver in sync */
+#define SK_YUKON2		/* Enable Yukon2 dual net support */
+#define USE_SK_TX_CHECKSUM	/* use the tx hw checksum driver functionality */
+#define USE_SK_RX_CHECKSUM	/* use the rx hw checksum driver functionality */
+#define USE_SK_TSO_FEATURE	/* use TCP segmentation offload if possible */
+#define SK_COPY_THRESHOLD 50	/* threshold for copying small RX frames; 
+				 * 0 avoids copying, 9001 copies all */
+#define SK_MAX_CARD_PARAM 16	/* number of adapters that can be configured via 
+				 * command line params */
+//#define USE_TX_COMPLETE	/* use of a transmit complete interrupt */
+#define Y2_RX_CHECK		/* RX Check timestamp */
+
+#define SK_REL_SPIN_LOCK(IoC)
+#define SK_ACQ_SPIN_LOCK(IoC)
+
+/*
+ * use those defines for a compile-in version of the driver instead
+ * of command line parameters
+ */
+// #define LINK_SPEED_A	{"Auto",}
+// #define LINK_SPEED_B	{"Auto",}
+// #define AUTO_NEG_A	{"Sense",}
+// #define AUTO_NEG_B	{"Sense"}
+// #define DUP_CAP_A	{"Both",}
+// #define DUP_CAP_B	{"Both",}
+// #define FLOW_CTRL_A	{"SymOrRem",}
+// #define FLOW_CTRL_B	{"SymOrRem",}
+// #define ROLE_A	{"Auto",}
+// #define ROLE_B	{"Auto",}
+// #define PREF_PORT	{"A",}
+// #define CON_TYPE 	{"Auto",}
+// #define RLMT_MODE	{"CheckLinkState",}
+
+#ifdef Y2_RECOVERY
+#define CHECK_TRANSMIT_TIMEOUT
+#define Y2_RESYNC_WATERMARK     1000000L
+#endif
+
+
+/******************************************************************************
+ *
+ * Generic ISR defines
+ *
+ ******************************************************************************/
+
+#define SkIsrRetVar     irqreturn_t
+#define SkIsrRetNone    IRQ_NONE
+#define SkIsrRetHandled IRQ_HANDLED
+
+#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
+#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
+#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
+
+/******************************************************************************
+ *
+ * Global function prototypes
+ *
+ ******************************************************************************/
+
+extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
+extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
+extern SK_U64 SkOsGetTime(SK_AC*);
+extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
+extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*);
+extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*);
+extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32);
+extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16);
+extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8);
+extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
+extern int SkDrvEnterDiagMode(SK_AC *pAc);
+extern int SkDrvLeaveDiagMode(SK_AC *pAc);
+
+/******************************************************************************
+ *
+ * Linux specific RLMT buffer structure (SK_MBUF typedef in skdrv1st)!
+ *
+ ******************************************************************************/
+
+struct s_DrvRlmtMbuf {
+	SK_MBUF         *pNext;    /* Pointer to next RLMT Mbuf.       */
+	SK_U8           *pData;    /* Data buffer (virtually contig.). */
+	unsigned         Size;     /* Data buffer size.                */
+	unsigned         Length;   /* Length of packet (<= Size).      */
+	SK_U32           PortIdx;  /* Receiving/transmitting port.     */
+#ifdef SK_RLMT_MBUF_PRIVATE
+	SK_RLMT_MBUF     Rlmt;     /* Private part for RLMT.           */
+#endif
+	struct sk_buff  *pOs;      /* Pointer to message block         */
+};
+
+/******************************************************************************
+ *
+ * Linux specific TIME defines
+ *
+ ******************************************************************************/
+
+#if SK_TICKS_PER_SEC == 100
+#define SK_PNMI_HUNDREDS_SEC(t)	(t)
+#else
+#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t)*100)/(SK_TICKS_PER_SEC))
+#endif
+
+#define SkOsGetTimeCurrent(pAC, pUsec) {\
+	static struct timeval prev_t; \
+	struct timeval t;\
+	do_gettimeofday(&t);\
+	if (prev_t.tv_sec == t.tv_sec) { \
+		if (prev_t.tv_usec > t.tv_usec) { \
+			t.tv_usec = prev_t.tv_usec; \
+		} else { \
+			prev_t.tv_usec = t.tv_usec; \
+		} \
+	} else { \
+		prev_t = t; \
+	} \
+	*pUsec = ((t.tv_sec*100L)+(t.tv_usec/10000));\
+}
+
+/******************************************************************************
+ *
+ * Linux specific IOCTL defines and typedefs
+ *
+ ******************************************************************************/
+
+#define	SK_IOCTL_BASE       (SIOCDEVPRIVATE)
+#define	SK_IOCTL_GETMIB     (SK_IOCTL_BASE + 0)
+#define	SK_IOCTL_SETMIB     (SK_IOCTL_BASE + 1)
+#define	SK_IOCTL_PRESETMIB  (SK_IOCTL_BASE + 2)
+#define	SK_IOCTL_GEN        (SK_IOCTL_BASE + 3)
+#define	SK_IOCTL_DIAG       (SK_IOCTL_BASE + 4)
+#define	SK_IOCTL_IPTOFW     (SK_IOCTL_BASE + 10)
+#define SK_IOCTL_PATTERNTOFW   (SK_IOCTL_BASE + 11)
+
+typedef struct s_IOCTL SK_GE_IOCTL;
+struct s_IOCTL {
+	char __user *	pData;
+	unsigned int	Len;
+};
+
+/******************************************************************************
+ *
+ * Generic sizes and length definitions
+ *
+ ******************************************************************************/
+
+#define TX_RING_SIZE  (24*1024)			/* GEnesis/Yukon */
+#define RX_RING_SIZE  (24*1024)			/* GEnesis/Yukon */
+#define RX_MAX_NBR_BUFFERS   128		/* Yukon-EC/-II */
+#define TX_MAX_NBR_BUFFERS   128		/* Yukon-EC/-II */
+#define MAXIMUM_LOW_ADDRESS 0xFFFFFFFF		/* Max. low address */
+
+#define	ETH_BUF_SIZE        1560		/* multiples of 8 bytes */
+#define	ETH_MAX_MTU         1500
+#define	ETH_MAX_LEN         1518
+#define ETH_MIN_MTU         60
+#define ETH_MULTICAST_BIT   0x01
+#define SK_JUMBO_MTU        9000
+
+#define TX_PRIO_LOW    0 /* asynchronous queue */
+#define TX_PRIO_HIGH   1 /* synchronous queue */
+#define DESCR_ALIGN   64 /* alignment of Rx/Tx descriptors */
+
+/******************************************************************************
+ *
+ * PNMI related definitions
+ *
+ ******************************************************************************/
+
+#define SK_DRIVER_RESET(pAC, IoC)	0
+#define SK_DRIVER_SENDEVENT(pAC, IoC)	0
+#define SK_DRIVER_SELFTEST(pAC, IoC)	0
+/* For get mtu you must add an own function */
+#define SK_DRIVER_GET_MTU(pAc,IoC,i)	0
+#define SK_DRIVER_SET_MTU(pAc,IoC,i,v)	0
+#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v)	0
+
+
+/******************************************************************************
+ *
+ * Various offsets and sizes
+ *
+ ******************************************************************************/
+
+#define	SK_DRV_MODERATION_TIMER         1   /* id */
+#define SK_DRV_MODERATION_TIMER_LENGTH  1   /* 1 second */
+
+#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
+#define C_LEN_ETHERMAC_HEADER_SRC_ADDR  6
+#define C_LEN_ETHERMAC_HEADER_LENTYPE   2
+#define C_LEN_ETHERMAC_HEADER           ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \
+                                          (C_LEN_ETHERMAC_HEADER_SRC_ADDR)  + \
+                                          (C_LEN_ETHERMAC_HEADER_LENTYPE) )
+
+#define C_LEN_ETHERMTU_MINSIZE          46
+#define C_LEN_ETHERMTU_MAXSIZE_STD      1500
+#define C_LEN_ETHERMTU_MAXSIZE_JUMBO    9000
+
+#define C_LEN_ETHERNET_MINSIZE          ( (C_LEN_ETHERMAC_HEADER) + \
+                                          (C_LEN_ETHERMTU_MINSIZE) )
+
+#define C_OFFSET_IPHEADER               C_LEN_ETHERMAC_HEADER
+#define C_OFFSET_IPHEADER_IPPROTO       9
+#define C_OFFSET_TCPHEADER_TCPCS        16
+#define C_OFFSET_UDPHEADER_UDPCS        6
+
+#define C_OFFSET_IPPROTO                ( (C_LEN_ETHERMAC_HEADER) + \
+                                          (C_OFFSET_IPHEADER_IPPROTO) )
+
+#define C_PROTO_ID_UDP                  17       /* refer to RFC 790 or Stevens'   */
+#define C_PROTO_ID_TCP                  6        /* TCP/IP illustrated for details */
+
+/******************************************************************************
+ *
+ * Tx and Rx descriptor definitions
+ *
+ ******************************************************************************/
+
+typedef struct s_RxD RXD; /* the receive descriptor */
+struct s_RxD {
+	volatile SK_U32  RBControl;     /* Receive Buffer Control            */
+	SK_U32           VNextRxd;      /* Next receive descriptor,low dword */
+	SK_U32           VDataLow;      /* Receive buffer Addr, low dword    */
+	SK_U32           VDataHigh;     /* Receive buffer Addr, high dword   */
+	SK_U32           FrameStat;     /* Receive Frame Status word         */
+	SK_U32           TimeStamp;     /* Time stamp from XMAC              */
+	SK_U32           TcpSums;       /* TCP Sum 2 / TCP Sum 1             */
+	SK_U32           TcpSumStarts;  /* TCP Sum Start 2 / TCP Sum Start 1 */
+	RXD             *pNextRxd;      /* Pointer to next Rxd               */
+	struct sk_buff  *pMBuf;         /* Pointer to Linux' socket buffer   */
+};
+
+typedef struct s_TxD TXD; /* the transmit descriptor */
+struct s_TxD {
+	volatile SK_U32  TBControl;     /* Transmit Buffer Control            */
+	SK_U32           VNextTxd;      /* Next transmit descriptor,low dword */
+	SK_U32           VDataLow;      /* Transmit Buffer Addr, low dword    */
+	SK_U32           VDataHigh;     /* Transmit Buffer Addr, high dword   */
+	SK_U32           FrameStat;     /* Transmit Frame Status Word         */
+	SK_U32           TcpSumOfs;     /* Reserved / TCP Sum Offset          */
+	SK_U16           TcpSumSt;      /* TCP Sum Start                      */
+	SK_U16           TcpSumWr;      /* TCP Sum Write                      */
+	SK_U32           TcpReserved;   /* not used                           */
+	TXD             *pNextTxd;      /* Pointer to next Txd                */
+	struct sk_buff  *pMBuf;         /* Pointer to Linux' socket buffer    */
+};
+
+/******************************************************************************
+ *
+ * Generic Yukon-II defines
+ *
+ ******************************************************************************/
+
+
+/* Number of Status LE which will be allocated at init time. */
+#define NUMBER_OF_ST_LE 4096L
+
+/* Number of revceive LE which will be allocated at init time. */
+#define NUMBER_OF_RX_LE 512
+
+/* Number of transmit LE which will be allocated at init time. */
+#define NUMBER_OF_TX_LE 1024L
+
+#define LE_SIZE   sizeof(SK_HWLE)
+#define MAX_NUM_FRAGS   (MAX_SKB_FRAGS + 1)
+#define MIN_LEN_OF_LE_TAB   128
+#define MAX_UNUSED_RX_LE_WORKING   8
+#ifdef MAX_FRAG_OVERHEAD
+#undef MAX_FRAG_OVERHEAD
+#define MAX_FRAG_OVERHEAD   4
+#endif
+// as we have a maximum of 16 physical fragments,
+// maximum 1 ADDR64 per physical fragment
+// maximum 4 LEs for VLAN, Csum, LargeSend, Packet
+#define MIN_LE_FREE_REQUIRED   ((16*2) + 4)
+#define IS_GMAC(pAc)   (!pAc->GIni.GIGenesis)
+#ifdef USE_SYNC_TX_QUEUE
+#define TXS_MAX_LE   256
+#else /* !USE_SYNC_TX_QUEUE */
+#define TXS_MAX_LE   0
+#endif
+
+#define ETHER_MAC_HDR_LEN   (6+6+2) // MAC SRC ADDR, MAC DST ADDR, TYPE
+#define IP_HDR_LEN   20
+#define TCP_CSUM_OFFS   0x10
+#define UDP_CSUM_OFFS   0x06
+
+#if (defined (Y2_RECOVERY) || defined (Y2_LE_CHECK))
+/* event for recovery from rx out of sync */
+#define SK_DRV_RECOVER    SK_DRV_PRIVATE_BASE + 1
+#endif
+/******************************************************************************
+ *
+ * Structures specific for Yukon-II
+ *
+ ******************************************************************************/
+
+typedef	struct s_frag SK_FRAG;
+struct s_frag {
+ 	SK_FRAG       *pNext;
+ 	char          *pVirt;
+  	SK_U64         pPhys;
+ 	unsigned int   FragLen;
+};
+
+typedef	struct s_packet SK_PACKET;
+struct s_packet {
+	/* Common infos: */
+	SK_PACKET       *pNext;         /* pointer for packet queues          */
+	unsigned int     PacketLen;     /* length of packet                   */
+	unsigned int     NumFrags;      /* nbr of fragments (for Rx always 1) */
+	SK_FRAG         *pFrag;         /* fragment list                      */
+	SK_FRAG          FragArray[MAX_NUM_FRAGS]; /* TX fragment array       */
+	unsigned int     NextLE;        /* next LE to use for the next packet */
+
+	/* Private infos: */
+	struct sk_buff	*pMBuf;         /* Pointer to Linux' socket buffer    */
+};
+
+typedef	struct s_queue SK_PKT_QUEUE;
+struct s_queue {
+ 	SK_PACKET       *pHead;
+ 	SK_PACKET       *pTail;
+	spinlock_t       QueueLock;     /* serialize packet accesses          */
+};
+
+/*******************************************************************************
+ *
+ * Macros specific for Yukon-II queues
+ *
+ ******************************************************************************/
+
+#define IS_Q_EMPTY(pQueue)  ((pQueue)->pHead != NULL) ? SK_FALSE : SK_TRUE
+#define IS_Q_LOCKED(pQueue) spin_is_locked(&((pQueue)->QueueLock))
+
+#define PLAIN_POP_FIRST_PKT_FROM_QUEUE(pQueue, pPacket)	{	\
+        if ((pQueue)->pHead != NULL) {				\
+		(pPacket)       = (pQueue)->pHead;		\
+		(pQueue)->pHead = (pPacket)->pNext;		\
+		if ((pQueue)->pHead == NULL) {			\
+			(pQueue)->pTail = NULL;			\
+		}						\
+		(pPacket)->pNext = NULL;			\
+	} else {						\
+		(pPacket) = NULL;				\
+	}							\
+}
+
+#define PLAIN_PUSH_PKT_AS_FIRST_IN_QUEUE(pQueue, pPacket) {	\
+	if ((pQueue)->pHead != NULL) {				\
+		(pPacket)->pNext = (pQueue)->pHead;		\
+	} else {						\
+		(pPacket)->pNext = NULL;			\
+		(pQueue)->pTail  = (pPacket);			\
+	}							\
+      	(pQueue)->pHead  = (pPacket);				\
+}
+
+#define PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(pQueue, pPacket) {	\
+	(pPacket)->pNext = NULL;				\
+	if ((pQueue)->pTail != NULL) {				\
+		(pQueue)->pTail->pNext = (pPacket);		\
+	} else {						\
+		(pQueue)->pHead        = (pPacket);		\
+	}							\
+	(pQueue)->pTail = (pPacket);				\
+}
+
+#define PLAIN_PUSH_MULTIPLE_PKT_AS_LAST_IN_QUEUE(pQueue,pPktGrpStart,pPktGrpEnd) { \
+	if ((pPktGrpStart) != NULL) {					\
+		if ((pQueue)->pTail != NULL) {				\
+			(pQueue)->pTail->pNext = (pPktGrpStart);	\
+		} else {						\
+			(pQueue)->pHead = (pPktGrpStart);		\
+		}							\
+		(pQueue)->pTail = (pPktGrpEnd);				\
+	}								\
+}
+
+/* Required: 'Flags' */ 
+#define POP_FIRST_PKT_FROM_QUEUE(pQueue, pPacket)	{	\
+	spin_lock_irqsave(&((pQueue)->QueueLock), Flags);	\
+	if ((pQueue)->pHead != NULL) {				\
+		(pPacket)       = (pQueue)->pHead;		\
+		(pQueue)->pHead = (pPacket)->pNext;		\
+		if ((pQueue)->pHead == NULL) {			\
+			(pQueue)->pTail = NULL;			\
+		}						\
+		(pPacket)->pNext = NULL;			\
+	} else {						\
+		(pPacket) = NULL;				\
+	}							\
+	spin_unlock_irqrestore(&((pQueue)->QueueLock), Flags);	\
+}
+
+/* Required: 'Flags' */
+#define PUSH_PKT_AS_FIRST_IN_QUEUE(pQueue, pPacket)	{	\
+	spin_lock_irqsave(&(pQueue)->QueueLock, Flags);		\
+	if ((pQueue)->pHead != NULL) {				\
+		(pPacket)->pNext = (pQueue)->pHead;		\
+	} else {						\
+		(pPacket)->pNext = NULL;			\
+		(pQueue)->pTail  = (pPacket);			\
+	}							\
+	(pQueue)->pHead = (pPacket);				\
+	spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags);	\
+}
+
+/* Required: 'Flags' */
+#define PUSH_PKT_AS_LAST_IN_QUEUE(pQueue, pPacket)	{	\
+	(pPacket)->pNext = NULL;				\
+	spin_lock_irqsave(&(pQueue)->QueueLock, Flags);		\
+	if ((pQueue)->pTail != NULL) {				\
+		(pQueue)->pTail->pNext = (pPacket);		\
+	} else {						\
+		(pQueue)->pHead = (pPacket);			\
+	}							\
+	(pQueue)->pTail = (pPacket);				\
+	spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags);	\
+}
+
+/* Required: 'Flags' */
+#define PUSH_MULTIPLE_PKT_AS_LAST_IN_QUEUE(pQueue,pPktGrpStart,pPktGrpEnd) {	\
+	if ((pPktGrpStart) != NULL) {					\
+		spin_lock_irqsave(&(pQueue)->QueueLock, Flags);		\
+		if ((pQueue)->pTail != NULL) {				\
+			(pQueue)->pTail->pNext = (pPktGrpStart);	\
+		} else {						\
+			(pQueue)->pHead = (pPktGrpStart);		\
+		}							\
+		(pQueue)->pTail = (pPktGrpEnd);				\
+		spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags);	\
+	}								\
+}
+
+/*
+ *Check if the low address (32 bit) is near the 4G limit or over it.
+ * Set the high address to a wrong value.
+ * Doing so we force to write the ADDR64 LE.
+ */
+#define CHECK_LOW_ADDRESS( _HighAddress, _LowAddress , _Length) {	\
+	if ((~0-_LowAddress) <_Length) {				\
+		_HighAddress= MAXIMUM_LOW_ADDRESS;			\
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,			\
+			("High Address must be set for HW. LowAddr = %d  Length = %d\n",	\
+			_LowAddress, _Length));				\
+	}								\
+}
+
+/*******************************************************************************
+ *
+ * Macros specific for Yukon-II queues (tist)
+ *
+ ******************************************************************************/
+
+#ifdef USE_TIST_FOR_RESET
+/* port is fully operational */
+#define SK_PSTATE_NOT_WAITING_FOR_TIST                  0
+/* port in reset until any tist LE */
+#define SK_PSTATE_WAITING_FOR_ANY_TIST          BIT_0
+/* port in reset until timer reaches pAC->MinTistLo */
+#define SK_PSTATE_WAITING_FOR_SPECIFIC_TIST     BIT_1   
+#define SK_PSTATE_PORT_SHIFT    4
+#define SK_PSTATE_PORT_MASK             ((1 << SK_PSTATE_PORT_SHIFT) - 1)
+
+/* use this + Port to build OP_MOD_TXINDEX_NO_PORT_A|B */
+#define OP_MOD_TXINDEX 0x71
+/* opcode for a TX_INDEX LE in which Port A has to be ignored */
+#define OP_MOD_TXINDEX_NO_PORT_A 0x71
+/* opcode for a TX_INDEX LE in which Port B has to be ignored */
+#define OP_MOD_TXINDEX_NO_PORT_B 0x72
+/* opcode for LE to be ignored because port is still in reset */
+#define OP_MOD_LE 0x7F
+
+/* set tist wait mode Bit for port */ 
+#define SK_SET_WAIT_BIT_FOR_PORT(pAC, Bit, Port)        \
+	{ \
+		(pAC)->AdapterResetState |= ((Bit) << (SK_PSTATE_PORT_SHIFT * Port)); \
+	}
+
+/* reset tist waiting for specified port */
+#define SK_CLR_STATE_FOR_PORT(pAC, Port)        \
+	{ \
+		(pAC)->AdapterResetState &= \
+			~(SK_PSTATE_PORT_MASK << (SK_PSTATE_PORT_SHIFT * Port)); \
+	}
+
+/* return SK_TRUE when port is in reset waiting for tist */
+#define SK_PORT_WAITING_FOR_TIST(pAC, Port) \
+	((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \
+		SK_PSTATE_PORT_MASK) != SK_PSTATE_NOT_WAITING_FOR_TIST)
+
+/* return SK_TRUE when port is in reset waiting for any tist */
+#define SK_PORT_WAITING_FOR_ANY_TIST(pAC, Port) \
+	((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \
+		SK_PSTATE_WAITING_FOR_ANY_TIST) == SK_PSTATE_WAITING_FOR_ANY_TIST)
+
+/* return SK_TRUE when port is in reset waiting for a specific tist */
+#define SK_PORT_WAITING_FOR_SPECIFIC_TIST(pAC, Port) \
+	((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \
+		SK_PSTATE_WAITING_FOR_SPECIFIC_TIST) == \
+		SK_PSTATE_WAITING_FOR_SPECIFIC_TIST)
+        
+/* return whether adapter is expecting a tist LE */
+#define SK_ADAPTER_WAITING_FOR_TIST(pAC)        ((pAC)->AdapterResetState != 0)
+
+/* enable timestamp timer and force creation of tist LEs */
+#define Y2_ENABLE_TIST(IoC) \
+	SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8) GMT_ST_START)
+        
+/* disable timestamp timer and stop creation of tist LEs */
+#define Y2_DISABLE_TIST(IoC) \
+	SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8) GMT_ST_STOP)
+
+/* get current value of timestamp timer */
+#define Y2_GET_TIST_LOW_VAL(IoC, pVal) \
+	SK_IN32(IoC, GMAC_TI_ST_VAL, pVal)
+
+#endif
+
+
+/*******************************************************************************
+ *
+ * Used interrupt bits in the interrupts source register
+ *
+ ******************************************************************************/
+
+#define DRIVER_IRQS	((IS_IRQ_SW) | \
+			 (IS_R1_F)   | (IS_R2_F)  | \
+			 (IS_XS1_F)  | (IS_XA1_F) | \
+			 (IS_XS2_F)  | (IS_XA2_F))
+
+#define TX_COMPL_IRQS	((IS_XS1_B)  | (IS_XS1_F) | \
+			 (IS_XA1_B)  | (IS_XA1_F) | \
+			 (IS_XS2_B)  | (IS_XS2_F) | \
+			 (IS_XA2_B)  | (IS_XA2_F))
+
+#define NAPI_DRV_IRQS	((IS_R1_F)   | (IS_R2_F) | \
+			 (IS_XS1_F)  | (IS_XA1_F)| \
+			 (IS_XS2_F)  | (IS_XA2_F))
+
+#define Y2_DRIVER_IRQS	((Y2_IS_STAT_BMU) | (Y2_IS_IRQ_SW) | (Y2_IS_POLL_CHK))
+
+#define SPECIAL_IRQS	((IS_HW_ERR)    |(IS_I2C_READY)  | \
+			 (IS_EXT_REG)   |(IS_TIMINT)     | \
+			 (IS_PA_TO_RX1) |(IS_PA_TO_RX2)  | \
+			 (IS_PA_TO_TX1) |(IS_PA_TO_TX2)  | \
+			 (IS_MAC1)      |(IS_LNK_SYNC_M1)| \
+			 (IS_MAC2)      |(IS_LNK_SYNC_M2)| \
+			 (IS_R1_C)      |(IS_R2_C)       | \
+			 (IS_XS1_C)     |(IS_XA1_C)      | \
+			 (IS_XS2_C)     |(IS_XA2_C))
+
+#define Y2_SPECIAL_IRQS	((Y2_IS_HW_ERR)   |(Y2_IS_ASF)      | \
+			 (Y2_IS_TWSI_RDY) |(Y2_IS_TIMINT)   | \
+			 (Y2_IS_IRQ_PHY2) |(Y2_IS_IRQ_MAC2) | \
+			 (Y2_IS_CHK_RX2)  |(Y2_IS_CHK_TXS2) | \
+			 (Y2_IS_CHK_TXA2) |(Y2_IS_IRQ_PHY1) | \
+			 (Y2_IS_IRQ_MAC1) |(Y2_IS_CHK_RX1)  | \
+			 (Y2_IS_CHK_TXS1) |(Y2_IS_CHK_TXA1))
+
+#define IRQ_MASK	((IS_IRQ_SW)    | \
+			 (IS_R1_F)      |(IS_R2_F)     | \
+			 (IS_XS1_F)     |(IS_XA1_F)    | \
+			 (IS_XS2_F)     |(IS_XA2_F)    | \
+			 (IS_HW_ERR)    |(IS_I2C_READY)| \
+			 (IS_EXT_REG)   |(IS_TIMINT)   | \
+			 (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
+			 (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
+			 (IS_MAC1)      |(IS_MAC2)     | \
+			 (IS_R1_C)      |(IS_R2_C)     | \
+			 (IS_XS1_C)     |(IS_XA1_C)    | \
+			 (IS_XS2_C)     |(IS_XA2_C))
+
+#define Y2_IRQ_MASK	((Y2_DRIVER_IRQS) | (Y2_SPECIAL_IRQS))
+
+#define IRQ_HWE_MASK	(IS_ERR_MSK)		/* enable all HW irqs */
+#define Y2_IRQ_HWE_MASK	(Y2_HWE_ALL_MSK)	/* enable all HW irqs */
+
+typedef struct s_DevNet DEV_NET;
+
+struct s_DevNet {
+	struct		proc_dir_entry *proc;
+	int		PortNr;
+	int		NetNr;
+	char		InitialDevName[20];
+	char		CurrentName[20];
+	SK_BOOL		NetConsoleMode;
+#ifdef Y2_RECOVERY
+	struct 		timer_list KernelTimer;	/* Kernel timer struct  */
+	int		TransmitTimeoutTimer; 	/* Transmit timer       */
+	SK_BOOL		TimerExpired;		/* Transmit timer       */
+	SK_BOOL		InRecover;		/* Recover flag		*/
+#ifdef Y2_RX_CHECK
+	SK_U32 		PreviousMACFifoRP;	/* Backup of the FRP    */
+	SK_U32 		PreviousMACFifoRLev;	/* Backup of the FRL    */
+	SK_U32 		PreviousRXFifoRP;	/* Backup of the RX FRP */
+	SK_U8 		PreviousRXFifoRLev;	/* Backup of the RX FRL */
+	SK_U32		LastJiffies;		/* Backup of the jiffies*/
+#endif
+#endif
+	SK_AC		*pAC;
+	struct 		timer_list ProcfsTimer;	/* Procfs timer struct  */
+
+};  
+
+/*******************************************************************************
+ *
+ * Rx/Tx Port structures
+ *
+ ******************************************************************************/
+
+typedef struct s_TxPort	TX_PORT;
+struct s_TxPort {                       /* the transmit descriptor rings */
+	caddr_t         pTxDescrRing;   /* descriptor area memory        */
+	SK_U64          VTxDescrRing;   /* descr. area bus virt. addr.   */
+	TXD            *pTxdRingHead;   /* Head of Tx rings              */
+	TXD            *pTxdRingTail;   /* Tail of Tx rings              */
+	TXD            *pTxdRingPrev;   /* descriptor sent previously    */
+	int             TxdRingPrevFree;/* previously # of free entrys   */
+	int             TxdRingFree;    /* # of free entrys              */
+	spinlock_t      TxDesRingLock;  /* serialize descriptor accesses */
+	SK_IOC		HwAddr;         /* bmu registers address         */
+	int             PortIndex;      /* index number of port (0 or 1) */
+	SK_PACKET      *TransmitPacketTable;
+	SK_LE_TABLE     TxALET;         /* tx (async) list element table */
+	SK_LE_TABLE     TxSLET;         /* tx (sync) list element table  */
+	SK_PKT_QUEUE    TxQ_free;
+	SK_PKT_QUEUE    TxAQ_waiting;
+	SK_PKT_QUEUE    TxSQ_waiting;
+	SK_PKT_QUEUE    TxAQ_working;
+	SK_PKT_QUEUE    TxSQ_working;
+	unsigned	LastDone;
+};
+
+typedef struct s_RxPort	RX_PORT;
+struct s_RxPort {                       /* the receive descriptor rings  */
+	caddr_t         pRxDescrRing;   /* descriptor area memory        */
+	SK_U64          VRxDescrRing;   /* descr. area bus virt. addr.   */
+	RXD            *pRxdRingHead;   /* Head of Rx rings              */
+	RXD            *pRxdRingTail;   /* Tail of Rx rings              */
+	RXD            *pRxdRingPrev;   /* descr given to BMU previously */
+	int             RxdRingFree;    /* # of free entrys              */
+	spinlock_t      RxDesRingLock;  /* serialize descriptor accesses */
+	int             RxFillLimit;    /* limit for buffers in ring     */
+	SK_IOC          HwAddr;         /* bmu registers address         */
+	int             PortIndex;      /* index number of port (0 or 1) */
+	SK_BOOL         UseRxCsum;      /* use Rx checksumming (yes/no)  */
+	SK_PACKET      *ReceivePacketTable;
+	SK_LE_TABLE     RxLET;          /* rx list element table         */
+	SK_PKT_QUEUE    RxQ_working;
+	SK_PKT_QUEUE    RxQ_waiting;
+	int             RxBufSize;
+};
+
+/*******************************************************************************
+ *
+ * Interrupt masks used in combination with interrupt moderation
+ *
+ ******************************************************************************/
+
+#define IRQ_EOF_AS_TX     ((IS_XA1_F)     | (IS_XA2_F))
+#define IRQ_EOF_SY_TX     ((IS_XS1_F)     | (IS_XS2_F))
+#define IRQ_MASK_TX_ONLY  ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX))
+#define IRQ_MASK_RX_ONLY  ((IS_R1_F)      | (IS_R2_F))
+#define IRQ_MASK_SP_ONLY  (SPECIAL_IRQS)
+#define IRQ_MASK_TX_RX    ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
+#define IRQ_MASK_SP_RX    ((SPECIAL_IRQS)    | (IRQ_MASK_RX_ONLY))
+#define IRQ_MASK_SP_TX    ((SPECIAL_IRQS)    | (IRQ_MASK_TX_ONLY))
+#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS)    | (IRQ_MASK_TX_RX))
+
+#define IRQ_MASK_Y2_TX_ONLY  (Y2_IS_STAT_BMU)
+#define IRQ_MASK_Y2_RX_ONLY  (Y2_IS_STAT_BMU)
+#define IRQ_MASK_Y2_SP_ONLY  (SPECIAL_IRQS)
+#define IRQ_MASK_Y2_TX_RX    ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
+#define IRQ_MASK_Y2_SP_RX    ((SPECIAL_IRQS)    | (IRQ_MASK_RX_ONLY))
+#define IRQ_MASK_Y2_SP_TX    ((SPECIAL_IRQS)    | (IRQ_MASK_TX_ONLY))
+#define IRQ_MASK_Y2_RX_TX_SP ((SPECIAL_IRQS)    | (IRQ_MASK_TX_RX))
+
+/*******************************************************************************
+ *
+ * Defines and typedefs regarding interrupt moderation
+ *
+ ******************************************************************************/
+
+#define C_INT_MOD_NONE			1
+#define C_INT_MOD_STATIC		2
+#define C_INT_MOD_DYNAMIC		4
+
+#define C_CLK_FREQ_GENESIS		 53215000 /* or:  53.125 MHz */
+#define C_CLK_FREQ_YUKON		 78215000 /* or:  78.125 MHz */
+#define C_CLK_FREQ_YUKON_EC		125000000 /* or: 125.000 MHz */
+
+#define C_Y2_INTS_PER_SEC_DEFAULT	5000 
+#define C_INTS_PER_SEC_DEFAULT		2000 
+#define C_INT_MOD_IPS_LOWER_RANGE	30        /* in IRQs/second */
+#define C_INT_MOD_IPS_UPPER_RANGE	40000     /* in IRQs/second */
+
+#define C_TX_INT_MOD_UPPER_RANGE	4095     /* in IRQs/second */
+
+
+typedef struct s_DynIrqModInfo {
+	SK_U64     PrevPort0RxIntrCts;
+	SK_U64     PrevPort1RxIntrCts;
+	SK_U64     PrevPort0TxIntrCts;
+	SK_U64     PrevPort1TxIntrCts;
+	SK_U64     PrevPort0StatusLeIntrCts;
+	SK_U64     PrevPort1StatusLeIntrCts;
+	int        MaxModIntsPerSec;            /* Moderation Threshold   */
+	int        MaxModIntsPerSecUpperLimit;  /* Upper limit for DIM    */
+	int        MaxModIntsPerSecLowerLimit;  /* Lower limit for DIM    */
+	long       MaskIrqModeration;           /* IRQ Mask (eg. 'TxRx')  */
+	int        IntModTypeSelect;            /* Type  (eg. 'dynamic')  */
+	int        DynIrqModSampleInterval;     /* expressed in seconds!  */
+	SK_TIMER   ModTimer;                    /* Timer for dynamic mod. */
+} DIM_INFO;
+
+/*******************************************************************************
+ *
+ * Defines and typedefs regarding wake-on-lan
+ *
+ ******************************************************************************/
+
+typedef struct s_WakeOnLanInfo {
+	SK_U32     SupportedWolOptions;         /* e.g. WAKE_PHY...         */
+	SK_U32     ConfiguredWolOptions;        /* e.g. WAKE_PHY...         */
+} WOL_INFO;
+
+#define SK_ALLOC_IRQ	0x00000001
+#define	DIAG_ACTIVE		1
+#define	DIAG_NOTACTIVE		0
+
+/****************************************************************************
+ *
+ * Per board structure / Adapter Context structure:
+ * Contains all 'per device' necessary handles, flags, locks etc.:
+ *
+ ******************************************************************************/
+
+struct s_AC  {
+	SK_GEINIT                GIni;          /* GE init struct             */
+	SK_PNMI                  Pnmi;          /* PNMI data struct           */
+	SK_VPD                   vpd;           /* vpd data struct            */
+	SK_QUEUE                 Event;         /* Event queue                */
+	SK_HWT                   Hwt;           /* Hardware Timer ctrl struct */
+	SK_TIMCTRL               Tim;           /* Software Timer ctrl struct */
+	SK_I2C                   I2c;           /* I2C relevant data structure*/
+	SK_ADDR                  Addr;          /* for Address module         */
+	SK_CSUM                  Csum;          /* for checksum module        */
+	SK_RLMT                  Rlmt;          /* for rlmt module            */
+#ifdef SK_ASF
+	SK_ASF_DATA              AsfData;
+	unsigned char            IpAddr[4];
+#endif
+#ifdef USE_ASF_DASH_FW
+	unsigned char            IpV6Addr[16*7];
+        unsigned int             ForceFWIPUpdate;
+        unsigned int             RecvNewPattern;
+        DRIVER_INTERFACE         NewPatternDef;
+#endif
+	spinlock_t               SlowPathLock;  /* Normal IRQ lock            */
+	spinlock_t               InitLock;	/* Init lock                  */
+	spinlock_t               TxQueueLock;   /* TX Queue lock              */
+	SK_PNMI_STRUCT_DATA      PnmiStruct;    /* struct for all Pnmi-Data   */
+	int                      RlmtMode;      /* link check mode to set     */
+	int                      RlmtNets;      /* Number of nets             */
+	SK_IOC                   IoBase;        /* register set of adapter    */
+	int                      BoardLevel;    /* level of hw init (0-2)     */
+	char                     DeviceStr[80]; /* adapter string from vpd    */
+	SK_U32                   AllocFlag;     /* alloc flag of resources    */
+	struct pci_dev          *PciDev;        /* for access to pci cfg space*/
+	SK_U32                   PciDevId;      /* pci device id              */
+	struct SK_NET_DEVICE    *dev[2];        /* pointer to device struct   */
+	char                     Name[30];      /* driver name                */
+	struct SK_NET_DEVICE    *Next;          /* link all devs for cleanup  */
+	struct net_device_stats  stats;         /* linux 'netstat -i' stats   */
+	int                      Index;         /* internal board idx number  */
+	int                      RxQueueSize;   /* memory used for RX queue   */
+	int                      TxSQueueSize;  /* memory used for TXS queue  */
+	int                      TxAQueueSize;  /* memory used for TXA queue  */
+	int                      PromiscCount;  /* promiscuous mode counter   */
+	int                      AllMultiCount; /* allmulticast mode counter  */
+	int                      MulticCount;   /* number of MC addresses used*/
+	int                      HWRevision;	/* Hardware revision          */
+	int                      ActivePort;	/* the active XMAC port       */
+	int                      MaxPorts;      /* number of activated ports  */
+	int                      TxDescrPerRing;/* # of descriptors TX ring   */
+	int                      RxDescrPerRing;/* # of descriptors RX ring   */
+	caddr_t                  pDescrMem;     /* Ptr to the descriptor area */
+	dma_addr_t               pDescrMemDMA;  /* PCI DMA address of area    */
+	SK_U32			 PciState[16];  /* PCI state */
+	TX_PORT                  TxPort[SK_MAX_MACS][2];
+	RX_PORT                  RxPort[SK_MAX_MACS];
+	SK_LE_TABLE              StatusLETable; 
+	unsigned                 SizeOfAlignedLETables;	
+	spinlock_t               SetPutIndexLock;
+	int                      MaxUnusedRxLeWorking;
+        int                      InterfaceUp[2];
+	unsigned int             CsOfs1;        /* for checksum calculation   */
+	unsigned int             CsOfs2;        /* for checksum calculation   */
+	SK_U32                   CsOfs;         /* for checksum calculation   */
+	SK_BOOL                  CheckQueue;    /* check event queue soon     */
+	DIM_INFO                 DynIrqModInfo; /* all data related to IntMod */
+	WOL_INFO                 WolInfo;       /* all info regarding WOL     */
+	int                      ChipsetType;   /* 0=GENESIS; 1=Yukon         */
+	SK_BOOL                  LowLatency;    /* LowLatency optimization on?*/
+	SK_U32                   TxModeration;  /* TxModeration optimization  */
+	SK_U32                   DiagModeActive;/* is diag active?            */
+	SK_BOOL                  DiagFlowCtrl;  /* for control purposes       */
+	SK_PNMI_STRUCT_DATA      PnmiBackup;    /* backup structure for PNMI  */
+	SK_BOOL                  WasIfUp[SK_MAX_MACS];
+	char                     *pVirtMemAddr;
+#ifdef USE_TIST_FOR_RESET
+	int			 AdapterResetState;
+	SK_U32			 MinTistLo;
+	SK_U32			 MinTistHi;
+#endif
+#ifdef Y2_RECOVERY
+	int                      LastPort;       /* port for curr. handled rx */
+        int                      LastOpc;        /* last rx LEs opcode	      */
+#endif
+#ifdef Y2_SYNC_CHECK
+	unsigned long            FramesWithoutSyncCheck; /* since last check  */
+#endif
+	unsigned int             InterruptSource;
+#ifdef USE_ASF_DASH_FW
+        unsigned int             ReturningFromSuspend; /* Just resumed? 
+							  Reset by ASF */
+#endif
+};
+
+
+
+#endif
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
+
diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
new file mode 100755
index 0000000..4646ec8
--- /dev/null
+++ b/drivers/net/sk98lin/h/skerror.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * Name:	skerror.h
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.5 $
+ * Date:	$Date: 2007/03/20 08:41:08 $
+ * Purpose:	SK specific Error log support
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2006 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef _INC_SKERROR_H_
+#define _INC_SKERROR_H_
+
+/*
+ * Define Error Classes
+ */
+#define SK_ERRCL_OTHER		(0)		/* Other error */
+#define SK_ERRCL_CONFIG		(1L<<0)	/* Configuration error */
+#define SK_ERRCL_INIT		(1L<<1)	/* Initialization error */
+#define SK_ERRCL_NORES		(1L<<2)	/* Out of Resources error */
+#define SK_ERRCL_SW			(1L<<3)	/* Internal Software error */
+#define SK_ERRCL_HW			(1L<<4)	/* Hardware Failure */
+#define SK_ERRCL_COMM		(1L<<5)	/* Communication error */
+#define SK_ERRCL_INFO		(1L<<6)	/* Information */
+
+/*
+ * Define Error Code Bases
+ */
+#define SK_ERRBASE_RLMT		 100	/* Base Error number for RLMT */
+#define SK_ERRBASE_HWINIT	 200	/* Base Error number for HWInit */
+#define SK_ERRBASE_VPD		 300	/* Base Error number for VPD */
+#define SK_ERRBASE_PNMI		 400	/* Base Error number for PNMI */
+#define SK_ERRBASE_CSUM		 500	/* Base Error number for Checksum */
+#define SK_ERRBASE_SIRQ		 600	/* Base Error number for Special IRQ */
+#define SK_ERRBASE_I2C		 700	/* Base Error number for I2C module */
+#define SK_ERRBASE_QUEUE	 800	/* Base Error number for Scheduler */
+#define SK_ERRBASE_ADDR		 900	/* Base Error number for Address module */
+#define SK_ERRBASE_PECP		1000	/* Base Error number for PECP */
+#define SK_ERRBASE_DRV		1100	/* Base Error number for Driver */
+#define SK_ERRBASE_ASF		1200	/* Base Error number for ASF */
+#define	SK_ERRBASE_MACSEC	1300	/* Base Error number for MACSec module */
+
+#endif	/* _INC_SKERROR_H_ */
+
diff --git a/drivers/net/sk98lin/h/skfops.h b/drivers/net/sk98lin/h/skfops.h
new file mode 100755
index 0000000..b2f5531
--- /dev/null
+++ b/drivers/net/sk98lin/h/skfops.h
@@ -0,0 +1,39 @@
+
+/******************************************************************************
+ *
+ * Name:    skfops.c
+ * Project: Gigabit Ethernet Adapters, Common Modules
+ * Version: $Revision: 1.1.2.2 $
+ * Date:    $Date: 2006/09/18 11:55:54 $
+ * Purpose: Kernel mode file read functions.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect
+ *	(C)Copyright 2002-2003 Marvell
+ *
+ *	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT
+ *	The copyright notice above does not evidence any
+ *	actual or intended publication of such source code.
+ *
+ *	This Module contains Proprietary Information of SysKonnect
+ *	and should be treated as Confidential.
+ *
+ *	The information in this file is provided for the exclusive use of
+ *	the licensees of SysKonnect.
+ *	Such users have the right to use, modify, and incorporate this code
+ *	into products for purposes authorized by the license agreement
+ *	provided they include this notice and the associated copyright notice
+ *	with any such product.
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+
+SK_BOOL fw_read(	SK_AC *pAC,    /* Pointer to adapter context */
+	char *name, SK_U8 **addr, SK_U32 *len );
+SK_BOOL fw_file_exists(	SK_AC *pAC,    /* Pointer to adapter context */
+	char *name );
+
diff --git a/drivers/net/sk98lin/h/skgeasf.h b/drivers/net/sk98lin/h/skgeasf.h
new file mode 100755
index 0000000..e5d3ea1
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgeasf.h
@@ -0,0 +1,606 @@
+/******************************************************************************
+ *
+ * Name:    skgeasf.h
+ * Project: asf/ipmi
+ * Version: $Revision: 1.1.2.2 $
+ * Date:    $Date: 2007/06/27 15:55:09 $
+ * Purpose: asf/ipmi interface in windows driver
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  (C)Copyright 1998-2002 SysKonnect.
+ *  (C)Copyright 2002-2003 Marvell.
+ *
+ *  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.
+ *
+ *  The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _INC_SKGEASF_H_
+#define _INC_SKGEASF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* __cplusplus */
+
+/* DEFINES */
+#define ASF_FW_ARP_RESOLVE                  //  FW is resolving the destination IP addr
+#define ASF_FW_WD                           //  Driver is watching the FW
+#define ASF_CHECK_HIDDEN_ID                 //  ASF init checks hidden id
+
+// modes for the asf driver
+#define SK_GEASF_MODE_UNKNOWN               0       // unknown operation mode (initial)
+#define SK_GEASF_MODE_ASF                   1       // asfec.bin binary found -> ASF operation
+#define SK_GEASF_MODE_IPMI                  2       // ipmiy2.bin binary found -> IPMI operation
+#define SK_GEASF_MODE_DASH                  3       // dashex.bin binary found -> DASH operation
+
+// chip modes for asf driver
+#define SK_GEASF_CHIP_UNKNOWN               0       // bad chip id / hidden id
+#define SK_GEASF_CHIP_EC                    1       // EC: ASF
+#define SK_GEASF_CHIP_Y2                    2       // Yukon2
+#define SK_GEASF_CHIP_EX                    3       // Yukon Extreme
+
+// dual link mode
+#define SK_GEASF_Y2_SINGLEPORT              1       // Yukon2 sigle link adapter
+#define SK_GEASF_Y2_DUALPORT                2       // Yukon2 dual link adapter
+
+#define ASF_GUI_TSF                         10      /* Time Scale Factor: 1s(GUI) <-> 10*100ms(FW) */
+
+#define ASF_MAX_STRLEN                      64
+
+// lengths used in get oid
+#define ASF_ACPI_MAXBUFFLENGTH              256     // max bytes for holding ACPI table
+#define ASF_SMBUS_MAXBUFFLENGTH             128     // max bytes for holding SMBus info
+#define ASF_FWVER_MAXBUFFLENGTH             40      // max stringlen for firmware version
+
+#define SK_ASF_EVT_TIMER_EXPIRED            1       /* Counter overflow */
+#define SK_ASF_EVT_TIMER_SPI_EXPIRED        2       /* Counter overflow */
+#define SK_ASF_EVT_TIMER_HCI_EXPIRED        3       /* Counter overflow */
+
+/*  Return codes to the PNMI module  */
+#define SK_ASF_PNMI_ERR_OK              0
+#define SK_ASF_PNMI_ERR_GENERAL         1
+#define SK_ASF_PNMI_ERR_TOO_SHORT       2
+#define SK_ASF_PNMI_ERR_BAD_VALUE       3
+#define SK_ASF_PNMI_ERR_READ_ONLY       4
+#define SK_ASF_PNMI_ERR_UNKNOWN_OID     5
+#define SK_ASF_PNMI_ERR_UNKNOWN_INST    6
+#define SK_ASF_PNMI_ERR_UNKNOWN_NET     7
+#define SK_ASF_PNMI_ERR_NOT_SUPPORTED   10
+
+#define REG_ASF_MAC_ADDR        0x0f24
+#define REG_ASF_MY_IP           0x0f50
+#define REG_ASF_STATUS_CMD      0x0e68
+#define REG_ASF_SMBUS_CFG       0x0e40
+
+#define ASF_CPU_STATE_UNKNOWN       0
+#define ASF_CPU_STATE_RESET         1
+#define ASF_CPU_STATE_RUNNING       2
+
+
+/*  ASF MIB default values */
+#define ASF_DEF_RETRANS_COUNT_MIN   0           // x1
+#define ASF_DEF_RETRANS_COUNT_MAX   255         // x1
+#define ASF_DEF_WATCHDOG_ENA        0           //
+#define ASF_DEF_WATCHDOG_TIME       1200        // *100ms
+#define ASF_DEF_WATCHDOG_TIME_MAX   36000       // *100ms
+#define ASF_DEF_WATCHDOG_TIME_MIN   600         // *100ms
+#define ASF_DEF_RETRANS_INT_MIN     0           // *100ms
+#define ASF_DEF_RETRANS_INT_MAX     2550        // *100ms
+#define ASF_DEF_HB_INT_MIN          10          // *100ms
+#define ASF_DEF_HB_INT_MAX          2550        // *100ms
+#define ASF_DEF_ASF_ENA             0
+#define ASF_DEF_RETRANS             2
+#define ASF_DEF_RETRANS_INT         10          // *100ms
+#define ASF_DEF_HB_ENA              0
+#define ASF_DEF_HB_INT              600         // *100ms
+
+/* ASF HCI Commands */
+#define YASF_HOSTCMD_ASF_INFO                   1
+#define YASF_HOSTCMD_LEG_CONF                   2
+#define YASF_HOSTCMD_ASF_CONF                   3
+#define YASF_HOSTCMD_RCTRL_CONF                 4
+#define YASF_HOSTCMD_KEEP_ALIVE                 5
+#define YASF_HOSTCMD_NEW_SEPROM_CONFIG          6
+#define YASF_HOSTCMD_ENTER_RAM_IDLE             7
+#define YASF_HOSTCMD_LEAVE_RAM_IDLE             8
+#define YASF_HOSTCMD_RUN_DIAG                   9
+#define YASF_HOSTCMD_RESET_STATE                10
+#define YASF_HOSTCMD_RESET                      11
+#define YASF_HOSTCMD_CHECK_ALIVE                12
+#define YASF_HOSTCMD_DRV_HELLO                  13
+#define YASF_HOSTCMD_DRV_GOODBYE                14
+#define YASF_HOSTCMD_DRV_STANDBY                15
+#define YASF_HOSTCMD_UPDATE_OWN_MACADDR         16
+#define YASF_HOSTCMD_ARP_RESOLVE                17
+#define YASF_HOSTCMD_RESET_COLD                 18
+#define YASF_HOSTCMD_ACPI_RMCP_DATA             19
+#define YASF_HOSTCMD_ACPI_ERROR                 20
+
+#define YASF_HOSTCMD_CFG_SET_ASF_ENABLE         100
+#define YASF_HOSTCMD_CFG_SET_RSP_ENABLE         101
+#define YASF_HOSTCMD_CFG_SET_RETRANS            102
+#define YASF_HOSTCMD_CFG_SET_RETRANS_INT        103
+#define YASF_HOSTCMD_CFG_SET_HB_ENABLE          104
+#define YASF_HOSTCMD_CFG_SET_HB_INT             105
+#define YASF_HOSTCMD_CFG_SET_IP_DESTINATION     106
+#define YASF_HOSTCMD_CFG_SET_IP_SOURCE          107
+#define YASF_HOSTCMD_CFG_SET_MAC_DESTINATION    108
+#define YASF_HOSTCMD_CFG_SET_COMMUNITY_NAME     109
+#define YASF_HOSTCMD_CFG_SET_RSP_KEY_1          110
+#define YASF_HOSTCMD_CFG_SET_RSP_KEY_2          111
+#define YASF_HOSTCMD_CFG_SET_RSP_KEY_3          112
+#define YASF_HOSTCMD_CFG_SET_DRWD_ENABLE        113
+#define YASF_HOSTCMD_CFG_SET_DRWD_INT           114
+#define YASF_HOSTCMD_CFG_SET_WD_ENABLE          115
+#define YASF_HOSTCMD_CFG_SET_WD_INT             116
+#define YASF_HOSTCMD_CFG_SET_ASF_RAMSIZE        117
+#define YASF_HOSTCMD_CFG_SET_ACTIVE_PORT        118
+#define YASF_HOSTCMD_CFG_SET_DASH_ENABLE        119
+#define YASF_HOSTCMD_CFG_SET_DEBUG_INFO         120
+
+#define YASF_HOSTCMD_CFG_STORE_CONFIG           130
+
+#define YASF_HOSTCMD_CFG_GET_ASF_ENABLE         150
+#define YASF_HOSTCMD_CFG_GET_RSP_ENABLE         151
+#define YASF_HOSTCMD_CFG_GET_RETRANS            152
+#define YASF_HOSTCMD_CFG_GET_RETRANS_INT        153
+#define YASF_HOSTCMD_CFG_GET_HB_ENABLE          154
+#define YASF_HOSTCMD_CFG_GET_HB_INT             155
+#define YASF_HOSTCMD_CFG_GET_IP_DESTINATION     156
+#define YASF_HOSTCMD_CFG_GET_IP_SOURCE          157
+#define YASF_HOSTCMD_CFG_GET_MAC_DESTINATION    158
+#define YASF_HOSTCMD_CFG_GET_COMMUNITY_NAME     159
+#define YASF_HOSTCMD_CFG_GET_RSP_KEY_1          160
+#define YASF_HOSTCMD_CFG_GET_RSP_KEY_2          161
+#define YASF_HOSTCMD_CFG_GET_RSP_KEY_3          162
+#define YASF_HOSTCMD_CFG_GET_DRWD_ENABLE        163
+#define YASF_HOSTCMD_CFG_GET_DRWD_INT           164
+#define YASF_HOSTCMD_CFG_GET_WD_ENABLE          165
+#define YASF_HOSTCMD_CFG_GET_WD_INT             166
+#define YASF_HOSTCMD_CFG_GET_ASF_RAMSIZE        167
+#define YASF_HOSTCMD_CFG_GET_FW_VERSION_STRING  168
+#define YASF_HOSTCMD_CFG_GET_SMBUS_INFOS        169
+#define YASF_HOSTCMD_CFG_GET_ACTIVE_PORT        170
+#define YASF_HOSTCMD_CFG_READ_CONFIG            180
+
+
+/* ASF HCI Master */
+#define ASF_HCI_READ            0x08000000
+#define ASF_HCI_WRITE           0x04000000
+#define ASF_HCI_CMD_RD_READY    0x02000000
+#define ASF_HCI_CMD_WR_READY    0x01000000
+#define ASF_HCI_UNSUCCESS       0x00800000
+#define ASF_HCI_OFFSET          0x000000ff
+
+#define ASF_HCI_CMDREG          0x0e70
+#define ASF_HCI_DATAREG         0x0e78
+
+#define ASF_HCI_WAIT            1
+#define ASF_HCI_NOWAIT          0
+
+#define ASF_HCI_TO              100     /* 1s */
+
+#define HCI_EN_CMD_IDLE             0
+#define HCI_EN_CMD_WRITING          1
+#define HCI_EN_CMD_READING          2
+#define HCI_EN_CMD_WAIT             3
+#define HCI_EN_CMD_READY            4
+#define HCI_EN_CMD_ERROR            5
+
+#define ASF_HCI_REC_BUF_SIZE    128
+#define ASF_HCI_TRA_BUF_SIZE    128
+
+
+/*  SEPROM  (VPD) */
+#define ASF_VPD_CONFIG_BASE     0x340
+#define ASF_VPD_CONFIG_SIZE     0x80
+#define ASF_VPD_DATA_BASE       0x3c0
+#define ASF_VPD_DATA_SIZE       0x40
+
+/*  Flash (SPI)*/
+#define ASF_FLASH_SIZE          (1024*64)
+#define ASF_FLASH_OFFS          0x20000
+#define ASF_FLASH_OFFS_VER      0x1fc00
+#define ASF_FLASH_OFFS_REV      0x1fc0b
+#define ASF_FLASH_OFFS_CS       0x1fffc
+#define ASF_FLASH_OFFS_GUID     0x1f000
+#define ASF_FLASH_OFFS_ACPI     0x1f010
+#define ASF_DASH_FLASH_SIZE_1   65536
+#define ASF_DASH_FLASH_SIZE_2   53248
+
+/*  Yukon Extreme  */
+#define ASF_FLASH_EX_OFFS          0x20000
+#define ASF_FLASH_EX_OFFS_VER      0x1cc00
+#define ASF_FLASH_EX_OFFS_REV      0x1cc0b
+#define ASF_FLASH_EX_OFFS_CS       0x1cffc
+#define ASF_FLASH_EX_OFFS_GUID     0x1c000
+#define ASF_FLASH_EX_OFFS_ACPI     0x1c010
+
+
+#define ASF_RESET_HOT           0
+#define ASF_RESET_COLD          1
+
+#define ASF_INIT_UNDEFINED      0
+#define ASF_INIT_OK             1
+#define ASF_INIT_ERROR          2
+#define ASF_INIT_ERROR_CHIP_ID  3
+#define ASF_INIT_ERROR_OPMODE   4
+
+#define RSP_KEYLENGTH           20
+
+//  ACPI module defines
+#define ASF_ACPI_STATE_OK                       1
+#define ASF_ACPI_STATE_UNDEFINED                0
+#define ASF_ACPI_STATE_ERROR                    -1
+#define ASF_ACPI_STATE_ERROR_NO_RSDPTR          -2
+#define ASF_ACPI_STATE_ERROR_RSDT               -3
+#define ASF_ACPI_STATE_ERROR_XSDT               -4
+#define ASF_ACPI_STATE_ERROR_RSDT_NO_TABLE      -5
+#define ASF_ACPI_STATE_ERROR_RSDT_HEADER        -6
+#define ASF_ACPI_STATE_ERROR_ASF                -7
+#define ASF_ACPI_STATE_ERROR_ASF_HEADER         -8
+#define ASF_ACPI_STATE_ERROR_RSDT_NO_ASF_TABLE  -9
+#define ASF_ACPI_STATE_ERROR_FILE_OPEN          -10
+#define ASF_ACPI_STATE_ERROR_FILE_MAP           -11
+#define ASF_ACPI_STATE_ERROR_FILE_SIZE          -12
+#define ASF_ACPI_STATE_ERROR_FILE_CS            -13
+
+#define ASF_RECORD_INFO                 0x00
+#define ASF_RECORD_ALRT                 0x01
+#define ASF_RECORD_RCTL                 0x02
+#define ASF_RECORD_RMCP                 0x03
+#define ASF_RECORD_ADDR                 0x04
+
+#define TABLE_HEADER_LENGTH             36
+#define SEC_COMMIT                      0x08000000
+
+
+// endianess depended macros
+
+#define REVERSE_16(x)   ((((x)<<8)&0xff00) + (((x)>>8)&0x00ff))
+
+#define REVERSE_32(x)   ( ((((SK_U32)(x))<<24UL)&0xff000000UL) + \
+                          ((((SK_U32)(x))<< 8UL)&0x00ff0000UL) + \
+                          ((((SK_U32)(x))>> 8UL)&0x0000ff00UL) + \
+                          ((((SK_U32)(x))>>24UL)&0x000000ffUL) )
+
+#ifdef SK_LITTLE_ENDIAN
+#define NTOHS(x) REVERSE_16(x)
+#define HTONS(x) REVERSE_16(x)
+#define NTOHL(x) REVERSE_32(x)
+#define HTONL(x) REVERSE_32(x)
+#else
+#define NTOHS(x) (x)
+#define HTONS(x) (x)
+#define NTOHL(x) (x)
+#define HTONL(x) (x)
+#endif
+
+/*
+ *  ASF MIB structure
+ */
+struct _STR_PET_DAT
+{
+    SK_U8   EventSensorType;
+    SK_U8   EventType;
+    SK_U8   EventOffset;
+    SK_U8   TrapSourceType;
+    SK_U8   EventSourceType;
+    SK_U8   EventSeverity;
+    SK_U8   SensorDevice;
+    SK_U8   SensorNumber;
+    SK_U8   Entity;
+    SK_U8   EntityInstance;
+    SK_U8   EventData [8];
+    SK_U8   LanguageCode;
+    SK_U8   OemCustomField [64];
+    //  83 Bytes  so far
+};
+typedef struct _STR_PET_DAT STR_PET_DAT;
+
+// structure for ACPI data for reporting to GUI
+struct _STR_ASF_ACPI
+{
+    SK_U8  buffer [ASF_ACPI_MAXBUFFLENGTH];
+    SK_U32 length;
+};
+typedef struct _STR_ASF_ACPI STR_ASF_ACPI;
+
+// structure for SMBus data for reporting to GUI
+struct _STR_ASF_SMBUSINFO
+{
+    SK_U8  UpdateReq;
+    SK_U8  buffer [ASF_SMBUS_MAXBUFFLENGTH];
+    SK_U32 length;
+};
+typedef struct _STR_ASF_SMBUSINFO STR_ASF_SMBUSINFO;
+
+struct _STR_ASF_MIB
+{
+    SK_U8               WriteToFlash;
+    SK_U8               ConfigChange;
+    //  Configuration parameter related to registers
+    SK_U8               NewParam;
+    SK_U8               Ena;
+    SK_U16              Retrans;
+    SK_U32              RetransInt;
+    SK_U8               HbEna;
+    SK_U32              HbInt;
+    SK_U8               WdEna;
+    SK_U32              WdTime;
+    SK_U8               IpSource        [4];
+    SK_U8               MacSource       [6];
+    SK_U8               IpDest          [4];
+    SK_U8               MacDest         [6];
+    SK_U8               CommunityName   [64];
+    SK_U8               Guid            [16];
+    SK_U8               RspEnable;
+    SK_U32              RetransCountMin;
+    SK_U32              RetransCountMax;
+    SK_U32              RetransIntMin;
+    SK_U32              RetransIntMax;
+    SK_U32              HbIntMin;
+    SK_U32              HbIntMax;
+    SK_U32              WdTimeMax;
+    SK_U32              WdTimeMin;
+    SK_U8               KeyOperator         [RSP_KEYLENGTH];
+    SK_U8               KeyAdministrator    [RSP_KEYLENGTH];
+    SK_U8               KeyGenerator        [RSP_KEYLENGTH];
+    STR_ASF_ACPI        Acpi;
+    STR_ASF_SMBUSINFO   SMBus;
+    SK_U8               RlmtMode;
+    SK_U8               Reserved            [6];    // reserved bytes in vpd
+    SK_U8               PattUpReq;
+};
+typedef struct _STR_ASF_MIB STR_ASF_MIB;
+
+typedef struct s_Hci
+{
+    SK_U32      To;
+    SK_U8       Status;
+    SK_U8       OldStatus;
+    SK_U32      OldCmdReg;
+    SK_U8       SendIndex;
+    SK_U8       ReceiveIndex;
+    SK_U8       SendLength;
+    SK_U8       ReceiveLength;
+    SK_U8       ExpectResponse;
+    SK_U8       Cycles;
+    SK_U64      Time;
+    SK_U8       ReceiveBuf  [ASF_HCI_REC_BUF_SIZE];
+    SK_U8       TransmitBuf [ASF_HCI_TRA_BUF_SIZE];
+    SK_TIMER    AsfTimerHci;
+} STR_HCI;
+
+/*
+ * ASF specific adapter context structure
+ */
+typedef struct s_AsfData
+{
+    SK_U8       CurrentMacAddr[6];
+    SK_U8       IpAddress[4];
+    SK_TIMER    AsfTimer;
+    SK_TIMER    AsfTimerWrSpi;
+    SK_U8       StateHci;
+    SK_U8       StateWrSpi;
+    SK_U8       DriverVersion   [5];
+    SK_U8       FlashFwVersion  [5];
+    SK_U8       FlashFwRev;
+    SK_U8       FileFwVersion   [5];
+    SK_U8       FileFwRev;
+//VSz
+    SK_U8       FlashBuffer     [ASF_FLASH_SIZE];
+    SK_U8       VpdConfigBuf    [ASF_VPD_CONFIG_SIZE];
+    STR_ASF_MIB Mib;
+    STR_HCI     Hci;
+    SK_U8       GlHciState;
+    SK_U8       LastGlHciState;
+    SK_U8       InitState;
+    SK_U8       VpdInitOk;
+    SK_U32      FwError;
+    SK_U8       CpuAlive;
+    SK_U16      FwWdIntervall;
+    SK_U16      FwRamSize;
+    SK_U8       ActivePort;
+    SK_U8       PrefPort;
+    SK_U8       FwVersionString [80];
+    SK_U8       NewGuid;
+    SK_U8       OpMode;                 // ASF or IPMI operation mode - see SkAsfInit
+    SK_U8       ChipMode;               // relevant for ASF or IPMI operation mode
+    SK_U8       DualMode;
+}SK_ASF_DATA;
+
+#define MAX_EVENT_DATA      8
+
+struct _STR_EVENT_DATA  {
+    struct _STR_EVENT_DATA  *next;
+    SK_U8                   SensorType;               // SNMP (Specific Trap)
+    SK_U8                   Type;                     // SNMP (Specific Trap)
+    SK_U8                   Offset;                   // SNMP (Specific Trap)
+    SK_U8                   SourceType;               // PET
+    SK_U8                   Severity;                 // PET
+    SK_U8                   SensorDevice;             // PET
+    SK_U8                   SensorNumber;             // PET
+    SK_U8                   Entity;                   // PET
+    SK_U8                   EntityInstance;           // PET
+    SK_U8                   DataLen;
+    SK_U8                   Data [MAX_EVENT_DATA];    // PET
+};
+typedef struct _STR_EVENT_DATA STR_EVENT_DATA;
+
+
+/* Functions provided by SkGeAsf */
+
+/* ANSI/C++ compliant function prototypes */
+
+/*
+ * Public Function prototypes
+ */
+extern int SkAsfDeInit(SK_AC *pAC, SK_IOC IoC );
+extern int SkAsfInit (SK_AC *pAC , SK_IOC IoC , int level);
+extern int SkAsfDeInitStandBy( SK_AC *pAC, SK_IOC IoC );
+extern int SkAsfInitStandBy( SK_AC *pAC, SK_IOC IoC, int Level );
+extern int SkAsfGet (SK_AC *pAC , SK_IOC IoC , SK_U8 *pBuf, unsigned int *pLen);
+extern int SkAsfPreSet (SK_AC *pAC , SK_IOC IoC , SK_U8 *pBuf, unsigned int *pLen);
+extern int SkAsfSet (SK_AC *pAC , SK_IOC IoC , SK_U8 *pBuf, unsigned int *pLen);
+extern int SkAsfEvent (SK_AC *pAC , SK_IOC IoC , SK_U32 Event , SK_EVPARA Param);
+extern int SkAsfSetOid(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, SK_U32 Inst, SK_U8 *pBuf, unsigned int *pLen);
+extern int SkAsfPreSetOid(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, SK_U32 Inst, SK_U8 *pBuf, unsigned int *pLen);
+extern int SkAsfGetOid(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, SK_U32 Inst, SK_U8 *pBuf, unsigned int *pLen);
+extern int SkAsfRestorePattern(SK_AC *pAC , SK_IOC IoC);
+
+
+SK_I8 SkAsfReadSpiConfigData( SK_AC *pAC );
+SK_I8 SkAsfWriteSpiConfigData( SK_AC *pAC );
+SK_I8 SkAsfUpdateSpiConfigData(SK_AC *pAC, SK_U8 *data , SK_U32 off , SK_U32 len, SK_U32 ClrCnt );
+SK_I8 SkAsfUpdateConfDat( SK_AC *pAC, SK_U8 Pig, SK_U16 RegOffs, SK_U8 ByteEnable, SK_U32 Val, SK_U8 ForceNewEntry );
+SK_I8 SkAsfReadConfDat( SK_AC *pAC, SK_U8 Pig, SK_U16 RegOffs, SK_U8 ByteEnable, SK_U32 *Val );
+SK_I8 SkAsfWriteDeferredFlash( SK_AC *pAC, SK_IOC IoC );
+SK_I8 SkAsfStartWriteDeferredFlash( SK_AC *pAC, SK_IOC IoC );
+void SkAsfTimer( SK_AC *pAC, SK_IOC IoC );
+void SkAsfShowMib( SK_AC *pAC );
+void AsfResetCpu( SK_AC *pAC, SK_IOC IoC );
+void AsfRunCpu( SK_AC *pAC, SK_IOC IoC );
+SK_U8 AsfCheckAliveCpu( SK_AC *pAC, SK_IOC IoC );
+SK_I8 SkAsfSeprom2Mib( SK_AC *pAC, SK_IOC IoC );
+SK_I8 SkAsfMib2Seprom( SK_AC *pAC, SK_IOC IoC );
+SK_U8 AsfSmartResetCpu( SK_AC *pAC, SK_IOC IoC, SK_U8 Cold );
+SK_U8 AsfSmartResetStateCpu( SK_AC *pAC, SK_IOC IoC );
+SK_U8 AsfCpuState( SK_AC *pAC, SK_IOC Ioc );
+
+SK_U8 AsfHciGetData( SK_AC    *pAC, SK_U8 **pHciRecBuf );
+SK_U8 AsfHciGetState( SK_AC   *pAC );
+SK_U8 AsfHciSendCommand( SK_AC *pAC, SK_IOC IoC, SK_U8 Command, SK_U8 Par1, SK_U8 Par2, SK_U8 ExpectResponse, SK_U8 Wait, SK_U8 Retry );
+SK_U8 AsfHciSendData( SK_AC *pAC, SK_IOC IoC,  SK_U8 *Buffer, SK_U8 ExpectResponse, SK_U8 Wait, SK_U8 Retry );
+SK_U8 AsfHciSendMessage( SK_AC *pAC, SK_IOC IoC, SK_U8 *message, SK_U8 length, SK_U8 ExpectResponse, SK_U8 Wait );
+void AsfLockSpi( SK_AC *pAC, SK_IOC IoC );
+void AsfUnlockSpi( SK_AC *pAC, SK_IOC IoC );
+void SkAsfHci( SK_AC *pAC, SK_IOC IoC, SK_U8 ToEna );
+void AsfWatchCpu( SK_AC *pAC, SK_IOC IoC, SK_U32 par );
+void AsfEnable(SK_AC *pAC, SK_IOC IoC );
+void AsfDisable(SK_AC *pAC, SK_IOC IoC );
+void AsfSetOsPresentBit( SK_AC *pAC, SK_IOC IoC );
+void AsfResetOsPresentBit( SK_AC *pAC, SK_IOC IoC );
+void AsfEnableFlushFifo( SK_AC *pAC, SK_IOC IoC  );
+void AsfDisableFlushFifo( SK_AC *pAC, SK_IOC IoC);
+
+
+void AsfSetUpPattern(SK_AC *pAC, SK_IOC IoC, SK_U8 port  );
+SK_I8 AsfWritePatternRam( SK_AC *pAC,
+                                 SK_IOC IoC,
+                                 SK_U8 Port,
+                                 SK_U8 PatternId1,
+                                 SK_U8 PatternId2,
+                                 SK_U8 Length1,
+                                 SK_U8 Length2,
+                                 SK_U8 *pMask1,
+                                 SK_U8 *pPattern1,
+                                 SK_U8 *pMask2,
+                                 SK_U8 *pPattern2 );
+SK_I8 AsfWritePatternRamEx( SK_AC *pAC,
+			    SK_IOC IoC,
+			    SK_U8 Port,
+			    SK_U8 PatternId,
+			    SK_U8 Length1, 
+			    SK_U8 *pMask1, 
+			    SK_U8 *pPattern1 );
+
+SK_I8 YlciEnablePattern (SK_AC *pAC, SK_IOC IoC, SK_U8 port, SK_U8 pattno );
+SK_I8 YlciDisablePattern (SK_AC *pAC, SK_IOC IoC, SK_U8 port, SK_U8 pattno );
+
+//  ACPI and "ASF!" stuff
+SK_I8 SkAsfAcpi( SK_AC *pAC, SK_IOC IoC, SK_U8 *pImage );
+//SK_I8 SkAsfAcpiRsdt( SK_AC *pAC, SK_IOC IoC, SK_U8 *pImage, HANDLE SectionHandle, SK_U32 PhysAddr );
+//SK_I8 SkAsfAcpiXsdt( SK_AC *pAC, SK_IOC IoC, SK_U8 *pImage, HANDLE SectionHandle, SK_U64 PhysAddr );
+//SK_I8 SkAsfAcpiAsf( SK_AC *pAC, SK_IOC IoC, SK_U8 *pImage, HANDLE SectionHandle, SK_U32 PhysAddr );
+SK_I8 SkAsfPatchAsfTable( SK_AC *pAC, SK_IOC IoC, SK_U8 *pImage, SK_U8 *pAsfTable, SK_U32 TableLength );
+SK_I8 SkAsfPatchGuid( SK_AC *pAC, SK_IOC IoC, SK_U8 *pImage, SK_U8 *pGuid );
+void SkAsfExamineAsfTable( SK_AC *pAC, SK_IOC IoC, SK_U8 *pAsf, SK_U32 TableLength );
+SK_I8 SkAsfSendRmcpData(SK_AC *pAC, SK_IOC IoC,SK_U8 *pData, SK_U8 Length );
+
+// ipmi
+SK_I8 AsfWriteIpmiPattern(SK_AC *pAC, SK_IOC IoC, SK_U8 port);
+
+/* in file skspilole.c */
+void spi_init_pac( SK_AC *pAC );
+
+// for cleaning up smbus register
+void AsfSetSMBusRegister(SK_IOC IoC);
+
+#define SKERR_ASF_E001      (SK_ERRBASE_ASF)
+#define SKERR_ASF_E001MSG   "SkAsfInit() error: wrong HCI version"
+#define SKERR_ASF_E002      (SKERR_ASF_E001+1)
+#define SKERR_ASF_E002MSG   "SkAsfInit() error: flash read"
+#define SKERR_ASF_E003      (SKERR_ASF_E001+2)
+#define SKERR_ASF_E003MSG   "SkAsfInit() error: flash erase"
+#define SKERR_ASF_E004      (SKERR_ASF_E001+3)
+#define SKERR_ASF_E004MSG   "SkAsfInit() error: flash write"
+#define SKERR_ASF_E005      (SKERR_ASF_E001+4)
+#define SKERR_ASF_E005MSG   "SkAsfInit() error: map FW image"
+#define SKERR_ASF_E006      (SKERR_ASF_E001+5)
+#define SKERR_ASF_E006MSG   "SkAsfInit() error: flash reread"
+#define SKERR_ASF_E007      (SKERR_ASF_E001+6)
+#define SKERR_ASF_E007MSG   "SkAsfInit() error: flash compare"
+#define SKERR_ASF_E008      (SKERR_ASF_E001+7)
+#define SKERR_ASF_E008MSG   "SkAsfInit() flash successfully updated"
+#define SKERR_ASF_E009      (SKERR_ASF_E001+8)
+#define SKERR_ASF_E009MSG   "SkAsfInit() updating flash"
+
+
+#define ASF_YEC_YTB_BASE_WOL_CTRL1          ((SK_U32)0x0f20)                    // YTB WOL CTRL register link 1
+#define ASF_YEC_PATTRAM_CLUSTER_BYTES       ((SK_U8)4)    // 4 bytes is a word
+#define ASF_YEC_PATTRAM_CLUSTER_WORDS       ((SK_U8)4)    // 4 words in a cluster
+#define ASF_YEC_PATTRAM_CLUSTER_SIZE        ((SK_U8)64)   // pattern ram has 64 cluster
+
+#define ASF_YEC_PATTERN_ENA1                (ASF_YEC_YTB_BASE_WOL_CTRL1 + 0x02)     // enable pattern register, width:8
+#define ASF_YEC_PATTERN_LENGTH_R1_L         (ASF_YEC_YTB_BASE_WOL_CTRL1 + 0x10)     // pattern length register, pattern 0-3, width: 4x8
+#define ASF_YEC_PATTERN_LENGTH_R1_H         (ASF_YEC_YTB_BASE_WOL_CTRL1 + 0x14)     // pattern length register, pattern 4-6, width: 3x8
+#define ASF_YEC_PATTERN_MATCHENA1           (ASF_YEC_YTB_BASE_WOL_CTRL1 + 0x0b)     // ASF/PME match enable register, width: 8
+#define ASF_YEC_PATTERN_CTRL1               (ASF_YEC_YTB_BASE_WOL_CTRL1 + 0x00)     // match result, match control, wol ctrl and status
+
+#define ASF_YEC_YTB_BASE_MACRXFIFO1         ((SK_U32)0x0c40)                        // base of receive MAC fifo registers, port 1
+#define ASF_YEC_MAC_FIFO_CTRL1              (ASF_YEC_YTB_BASE_MACRXFIFO1 + 0x08)    // control/test Rx MAC, link1, 32 bit
+#define ASF_YEC_MAC_FIFO_FLUSHMASK1         (ASF_YEC_YTB_BASE_MACRXFIFO1 + 0x0c)    // flush mask register Rx MAC, link1, 32 bit
+#define ASF_YEC_MAC_FIFO_FLUSHTHRES1        (ASF_YEC_YTB_BASE_MACRXFIFO1 + 0x10)    // Rx MAC FIFO Flush Threshold, link1, 32 bit
+
+#define ASF_YLCI_MACRXFIFOTHRES             8                                       // mac rx threshold in qwords
+
+
+#define ASF_PATTERN_ID_RSP					0
+#define ASF_PATTERN_ID_ARP					1
+#define ASF_PATTERN_ID_RMCP					2
+
+
+//  Yukon Extreme
+#define ASF_YEX_YTB_BASE_WOL_CTRL1          ((SK_U32)0x0f20)                    // YTB WOL CTRL register link 1
+#define ASF_YEX_PATTRAM_CLUSTER_BYTES       ((SK_U8)4)    // 4 bytes is a word
+#define ASF_YEX_PATTRAM_CLUSTER_WORDS       ((SK_U8)4)    // 4 words in a cluster
+#define ASF_YEX_PATTRAM_CLUSTER_SIZE        ((SK_U8)64)   // pattern ram has 64 cluster
+
+#define ASF_YEX_PATTERN_ENA1                (ASF_YEX_YTB_BASE_WOL_CTRL1 + 0x02)     // enable pattern register, width:8
+#define ASF_YEX_PATTERN_LENGTH_R1_L         (ASF_YEX_YTB_BASE_WOL_CTRL1 + 0x10)     // pattern length register, pattern 0-3, width: 4x8
+#define ASF_YEX_PATTERN_LENGTH_R1_H         (ASF_YEX_YTB_BASE_WOL_CTRL1 + 0x14)     // pattern length register, pattern 4-6, width: 3x8
+#define ASF_YEX_PATTERN_LENGTH_R1_EH        (ASF_YEX_YTB_BASE_WOL_CTRL1 + 0x18)     // pattern length register, pattern 7-8, width: 3x8
+#define ASF_YEX_PATTERN_MATCHENA1           (ASF_YEX_YTB_BASE_WOL_CTRL1 + 0x0c)     // ASF/PME match enable register, width: 8
+#define ASF_YEX_PATTERN_CTRL1               (ASF_YEX_YTB_BASE_WOL_CTRL1 + 0x00)     // match result, match control, wol ctrl and status
+
+#define ASF_DASH_PATTERN_NUM_ICMP	3
+#define ASF_DASH_PATTERN_NUM_ARP	4
+
+#ifdef USE_ASF_DASH_FW
+#define ASF_DASH_PATTERN_NUM_SNMP       5
+#else
+#define ASF_DASH_PATTERN_NUM_RMCP	5
+#define ASF_DASH_PATTERN_NUM_RSP	6
+#define ASF_DASH_PATTERN_NUM_TCP1	7
+#define ASF_DASH_PATTERN_NUM_TCP2	8
+#endif
+
+#endif  /* _INC_SKGEASF_H_ */
diff --git a/drivers/net/sk98lin/h/skgeasfconv.h b/drivers/net/sk98lin/h/skgeasfconv.h
new file mode 100755
index 0000000..5b50701
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgeasfconv.h
@@ -0,0 +1,94 @@
+
+/******************************************************************************
+ *
+ * Name:    skgeasfconv.h
+ * Project: asf/ipmi
+ * Version: $Revision: 1.1.2.1 $
+ * Date:    $Date: 2006/08/28 09:06:28 $
+ * Purpose: asf/ipmi interface in windows driver
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  (C)Copyright 1998-2002 SysKonnect.
+ *  (C)Copyright 2002-2003 Marvell.
+ *
+ *  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.
+ *
+ *  The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _ASFWMI_H
+#define _ASFWMI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// lengths for string conversion
+#define ASF_IPADDRGRPSIZE           (4)                                 // 4 groups in ip address string (111.222.333.444)
+#define ASF_MACADDRGRPSIZE          (6)                                 // 6 groups in mac address string (11-22-33-44-55-66)
+#define ASF_GUIDGRPSIZE             (16)                                // 16 groups in a GUID string
+#define ASF_COMMUNITYSTRLEN         (64)                                // length of community string
+#define ASF_IPADDRSTRLEN            (3*ASF_IPADDRGRPSIZE+3)             // length of xxx.xxx.xxx.xxx
+#define ASF_MACADDRSTRLEN           (2*ASF_MACADDRGRPSIZE+5)            // length of xx-xx-xx-xx-xx-xx
+#define ASF_GUIDSTRLEN              (2*ASF_GUIDGRPSIZE)                 // length of GUID string
+
+// module sizes
+#define ASF_MAX_STRINGLEN           (ASF_COMMUNITYSTRLEN+1)             // length of a ascii string (with string end marker 0x00)
+#define ASF_MAX_UNICODESTRINGLEN    (ASF_COMMUNITYSTRLEN)               // length of a unicode string (without length information)
+
+
+// tags in strings
+#define ASF_IPSEPARATOR             ('.')                               // separator in ip string
+#define ASF_MACSEPARATOR            ('-')                               // separator in mac address
+
+
+// modes for AsfWmiInternal2External() and AsfWmiExternal2Internal()
+#define ASF_MODE_IPADDR             (10)        // input is a IP address (IPv4 format)
+#define ASF_MODE_MACADDR            (11)        // input is a MAC address
+#define ASF_MODE_COMMUNITY          (12)        // input is a community string
+#define ASF_MODE_GUID               (13)        // input is a number
+#define ASF_MODE_SYSID              (14)        // input is a number
+#define ASF_MODE_MANUID             (15)        // input is a number
+
+// modes for  AsfWmiHexVal2Str()
+#define ASF_MODE_IPSTRDECIMAL       (15)        // get string with ip in decimal
+#define ASF_MODE_MACADDRHEX         (16)        // get string in hex
+
+// returncodes
+#define ASF_RETVAL_FAIL             (-1)
+#define ASF_RETVAL_UNDEFINED        (0)
+#define ASF_RETVAL_SUCCESS          (1)
+
+// Unicode String structure
+typedef struct _STR_ASF_UNISTRING
+{
+    SK_U16  len;
+    SK_U16  buf[ASF_MAX_UNICODESTRINGLEN];
+
+} STR_ASF_UNISTRING;
+
+
+// function prototypes
+SK_I8 AsfMac2Asci( SK_U8 *buf, SK_U32 *len, SK_U8 *mac );
+SK_I8 AsfIp2Asci( SK_U8 *buf, SK_U32 *len, SK_U8 *ip );
+SK_I8 AsfAsci2Mac( SK_U8 *buf, SK_U32 len, SK_U8 *mac );
+SK_I8 AsfAsci2Ip( SK_U8 *buf, SK_U32 len, SK_U8 *ip );
+SK_I8 AsfHex2Array( SK_U8 *buf, SK_U32 len, SK_U8 *array );
+SK_I8 AsfArray2Hex( SK_U8 *buf, SK_U32 len, SK_U8 *array );
+SK_I8 AsfHex2U8( SK_U8 *buf, SK_U8 *val );
+SK_I8 AsfInt2Hex( SK_U8 *buf, SK_U8 size, SK_U32 val );
+SK_I8 AsfDec2Int( SK_U8 *buf, SK_U8 size, SK_U32 *val );
+
+#ifdef __cplusplus
+}
+#endif  // cpp
+
+#endif  // asfwmi.h
+
diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
new file mode 100755
index 0000000..358bc4e
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgedrv.h
@@ -0,0 +1,58 @@
+/******************************************************************************
+ *
+ * Name:	skgedrv.h
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.6 $
+ * Date:	$Date: 2007/03/29 09:19:28 $
+ * Purpose:	Interface with the driver
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKGEDRV_H_
+#define __INC_SKGEDRV_H_
+
+/* defines ********************************************************************/
+
+/*
+ * Define the driver events.
+ * Usually the events are defined by the destination module.
+ * In case of the driver we put the definition of the events here.
+ */
+#define SK_DRV_PORT_RESET		 1	/* The port needs to be reset */
+#define SK_DRV_NET_UP			 2	/* The net is operational */
+#define SK_DRV_NET_DOWN			 3	/* The net is down */
+#define SK_DRV_SWITCH_SOFT		 4	/* Ports switch with both links connected */
+#define SK_DRV_SWITCH_HARD		 5	/* Port switch due to link failure */
+#define SK_DRV_RLMT_SEND		 6	/* Send a RLMT packet */
+#define SK_DRV_ADAP_FAIL		 7	/* The whole adapter fails */
+#define SK_DRV_PORT_FAIL		 8	/* One port fails */
+#define SK_DRV_SWITCH_INTERN	 9	/* Port switch by the driver itself */
+#define SK_DRV_POWER_DOWN		10	/* Power down mode */
+#define SK_DRV_TIMER			11	/* Timer for free use */
+#ifdef SK_NO_RLMT
+#define SK_DRV_LINK_UP			12	/* Link Up event for driver */
+#define SK_DRV_LINK_DOWN		13	/* Link Down event for driver */
+#endif
+#define SK_DRV_DOWNSHIFT_DET	14	/* Downshift 4-Pair / 2-Pair (YUKON only) */
+#define SK_DRV_RX_OVERFLOW		15	/* Receive Overflow */
+#define SK_DRV_LIPA_NOT_AN_ABLE	16	/* Link Partner not Auto-Negotiation able */
+#define SK_DRV_PEX_LINK_WIDTH	17	/* PEX negotiated Link width not maximum */
+#define SK_DRV_TX_UNDERRUN		18	/* Transmit Underrun */
+
+#define SK_DRV_PRIVATE_BASE		100	/* Base for driver private events */
+#endif /* __INC_SKGEDRV_H_ */
diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
new file mode 100755
index 0000000..39a3ede
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgehw.h
@@ -0,0 +1,3278 @@
+/******************************************************************************
+ *
+ * Name:	skgehw.h
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.75 $
+ * Date:	$Date: 2007/07/12 10:25:28 $
+ * Purpose:	Defines and Macros for the Gigabit Ethernet Adapter Product Family
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKGEHW_H
+#define __INC_SKGEHW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* defines ********************************************************************/
+
+#define BIT_31		(1UL << 31)
+#define BIT_30		(1L << 30)
+#define BIT_29		(1L << 29)
+#define BIT_28		(1L << 28)
+#define BIT_27		(1L << 27)
+#define BIT_26		(1L << 26)
+#define BIT_25		(1L << 25)
+#define BIT_24		(1L << 24)
+#define BIT_23		(1L << 23)
+#define BIT_22		(1L << 22)
+#define BIT_21		(1L << 21)
+#define BIT_20		(1L << 20)
+#define BIT_19		(1L << 19)
+#define BIT_18		(1L << 18)
+#define BIT_17		(1L << 17)
+#define BIT_16		(1L << 16)
+#define BIT_15		(1L << 15)
+#define BIT_14		(1L << 14)
+#define BIT_13		(1L << 13)
+#define BIT_12		(1L << 12)
+#define BIT_11		(1L << 11)
+#define BIT_10		(1L << 10)
+#define BIT_9		(1L << 9)
+#define BIT_8		(1L << 8)
+#define BIT_7		(1L << 7)
+#define BIT_6		(1L << 6)
+#define BIT_5		(1L << 5)
+#define BIT_4		(1L << 4)
+#define BIT_3		(1L << 3)
+#define BIT_2		(1L << 2)
+#define BIT_1		(1L << 1)
+#define BIT_0		1L
+
+#define BIT_15S		(1U << 15)
+#define BIT_14S		(1 << 14)
+#define BIT_13S		(1 << 13)
+#define BIT_12S		(1 << 12)
+#define BIT_11S		(1 << 11)
+#define BIT_10S		(1 << 10)
+#define BIT_9S		(1 << 9)
+#define BIT_8S		(1 << 8)
+#define BIT_7S 		(1 << 7)
+#define BIT_6S		(1 << 6)
+#define BIT_5S		(1 << 5)
+#define BIT_4S		(1 << 4)
+#define BIT_3S		(1 << 3)
+#define BIT_2S		(1 << 2)
+#define BIT_1S		(1 << 1)
+#define BIT_0S		1
+
+#define SHIFT31(x)	((x) << 31)
+#define SHIFT30(x)	((x) << 30)
+#define SHIFT29(x)	((x) << 29)
+#define SHIFT28(x)	((x) << 28)
+#define SHIFT27(x)	((x) << 27)
+#define SHIFT26(x)	((x) << 26)
+#define SHIFT25(x)	((x) << 25)
+#define SHIFT24(x)	((x) << 24)
+#define SHIFT23(x)	((x) << 23)
+#define SHIFT22(x)	((x) << 22)
+#define SHIFT21(x)	((x) << 21)
+#define SHIFT20(x)	((x) << 20)
+#define SHIFT19(x)	((x) << 19)
+#define SHIFT18(x)	((x) << 18)
+#define SHIFT17(x)	((x) << 17)
+#define SHIFT16(x)	((x) << 16)
+#define SHIFT15(x)	((x) << 15)
+#define SHIFT14(x)	((x) << 14)
+#define SHIFT13(x)	((x) << 13)
+#define SHIFT12(x)	((x) << 12)
+#define SHIFT11(x)	((x) << 11)
+#define SHIFT10(x)	((x) << 10)
+#define SHIFT9(x)	((x) << 9)
+#define SHIFT8(x)	((x) << 8)
+#define SHIFT7(x)	((x) << 7)
+#define SHIFT6(x)	((x) << 6)
+#define SHIFT5(x)	((x) << 5)
+#define SHIFT4(x)	((x) << 4)
+#define SHIFT3(x)	((x) << 3)
+#define SHIFT2(x)	((x) << 2)
+#define SHIFT1(x)	((x) << 1)
+#define SHIFT0(x)	((x) << 0)
+
+/* Macro for arbitrary alignment of a given pointer */
+#define ALIGN_ADDR( ADDRESS, GRANULARITY ) { \
+	SK_UPTR addr = (SK_UPTR)(ADDRESS); \
+	if (addr & ((GRANULARITY)-1)) { \
+		addr += (GRANULARITY); \
+		addr &= ~(SK_UPTR)((GRANULARITY)-1); \
+		ADDRESS = (void *)addr; \
+	}\
+}
+
+/*
+ * Configuration Space header
+ * Since this module is used for different OS', those may be
+ * duplicate on some of them (e.g. Linux). But to keep the
+ * common source, we have to live with this...
+ */
+#define PCI_VENDOR_ID	0x00	/* 16 bit	Vendor ID */
+#define PCI_DEVICE_ID	0x02	/* 16 bit	Device ID */
+#define PCI_COMMAND		0x04	/* 16 bit	Command */
+#define PCI_STATUS		0x06	/* 16 bit	Status */
+#define PCI_REV_ID		0x08	/*  8 bit	Revision ID */
+#define PCI_CLASS_CODE	0x09	/* 24 bit	Class Code */
+#define PCI_CACHE_LSZ	0x0c	/*  8 bit	Cache Line Size */
+#define PCI_LAT_TIM		0x0d	/*  8 bit	Latency Timer */
+#define PCI_HEADER_T	0x0e	/*  8 bit	Header Type */
+#define PCI_BIST		0x0f	/*  8 bit	Built-in selftest */
+#define PCI_BASE_1ST	0x10	/* 32 bit	1st Base address */
+#define PCI_BASE_2ND	0x14	/* 32 bit	2nd Base address */
+	/* Bytes 0x18..0x2b:	reserved */
+#define PCI_SUB_VID		0x2c	/* 16 bit	Subsystem Vendor ID */
+#define PCI_SUB_ID		0x2e	/* 16 bit	Subsystem ID */
+#define PCI_BASE_ROM	0x30	/* 32 bit	Expansion ROM Base Address */
+#define PCI_CAP_PTR		0x34	/*  8 bit	Capabilities Pointer */
+	/* Bytes 0x35..0x3b:	reserved */
+#define PCI_IRQ_LINE	0x3c	/*  8 bit	Interrupt Line */
+#define PCI_IRQ_PIN		0x3d	/*  8 bit	Interrupt Pin */
+#define PCI_MIN_GNT		0x3e	/*  8 bit	Min_Gnt */
+#define PCI_MAX_LAT		0x3f	/*  8 bit	Max_Lat */
+	/* Device Dependent Region */
+#define PCI_OUR_REG_1	0x40	/* 32 bit	Our Register 1 */
+#define PCI_OUR_REG_2	0x44	/* 32 bit	Our Register 2 */
+	/* Power Management Region */
+#define PCI_PM_CAP_ID	0x48	/*  8 bit	Power Management Cap. ID */
+#define PCI_PM_NITEM	0x49	/*  8 bit	PM Next Item Pointer */
+#define PCI_PM_CAP_REG	0x4a	/* 16 bit	Power Management Capabilities */
+#define PCI_PM_CTL_STS	0x4c	/* 16 bit	Power Manag. Control/Status */
+	/* Byte 0x4e:	reserved */
+#define PCI_PM_DAT_REG	0x4f	/*  8 bit	Power Manag. Data Register */
+	/* VPD Region */
+#define PCI_VPD_CAP_ID	0x50	/*  8 bit	VPD Cap. ID */
+#define PCI_VPD_NITEM	0x51	/*  8 bit	VPD Next Item Pointer */
+#define PCI_VPD_ADR_REG	0x52	/* 16 bit	VPD Address Register */
+#define PCI_VPD_DAT_REG	0x54	/* 32 bit	VPD Data Register */
+	/* Bytes 0x58..0x59:	reserved */
+#define PCI_SER_LD_CTRL	0x5a	/* 16 bit	SEEPROM Loader Ctrl (YUKON only) */
+	/* Bytes 0x5c..0xfc:	used by Yukon-2 */
+#define PCI_MSI_CAP_ID	0x5c	/*  8 bit	MSI Capability ID Register */
+#define PCI_MSI_NITEM	0x5d	/*  8 bit	MSI Next Item Pointer */
+#define PCI_MSI_CTRL	0x5e	/* 16 bit	MSI Message Control */
+#define PCI_MSI_ADR_LO	0x60	/* 32 bit	MSI Message Address (Lower) */
+#define PCI_MSI_ADR_HI	0x64	/* 32 bit	MSI Message Address (Upper) */
+#define PCI_MSI_DATA	0x68	/* 16 bit	MSI Message Data */
+	/* Bytes 0x6a..0x6b:	reserved */
+#define PCI_X_CAP_ID	0x6c	/*  8 bit	PCI-X Capability ID Register */
+#define PCI_X_NITEM		0x6d	/*  8 bit	PCI-X Next Item Pointer */
+#define PCI_X_COMMAND	0x6e	/* 16 bit	PCI-X Command */
+#define PCI_X_PE_STAT	0x70	/* 32 bit	PCI-X / PE Status */
+#define PCI_CAL_CTRL	0x74	/* 16 bit	PCI Calibration Control Register */
+#define PCI_CAL_STAT	0x76	/* 16 bit	PCI Calibration Status Register */
+#define PCI_DISC_CNT	0x78	/* 16 bit	PCI Discard Counter */
+#define PCI_RETRY_CNT	0x7a	/*  8 bit	PCI Retry Counter */
+	/* Byte 0x7b:	reserved */
+#define PCI_OUR_STATUS	0x7c	/* 32 bit	Adapter Status Register */
+#define PCI_OUR_REG_3	0x80	/* 32 bit	Our Register 3 (Yukon-ECU only) */
+#define PCI_OUR_REG_4	0x84	/* 32 bit	Our Register 4 (Yukon-ECU only) */
+#define PCI_OUR_REG_5	0x88	/* 32 bit	Our Register 5 (Yukon-ECU only) */
+#define PCI_ERR_REP_MSK	0x8c	/* 32 bit	Error Rep. Mask (Yukon-ECU A1b) */
+#define PCI_CFG_REG_0	0x90	/* 32 bit	Config Register 0 (Yukon-Ext only) */
+#define PCI_CFG_REG_1	0x94	/* 32 bit	Config Register 1 (Yukon-Ext only) */
+	/* Bytes 0x98..0xdf:	reserved */
+
+/* PCI Express Capability */
+#define PEX_CAP_ID		0xe0	/*  8 bit	PEX Capability ID */
+#define PEX_NITEM		0xe1	/*  8 bit	PEX Next Item Pointer */
+#define PEX_CAP_REG		0xe2	/* 16 bit	PEX Capability Register */
+#define PEX_DEV_CAP		0xe4	/* 32 bit	PEX Device Capabilities */
+#define PEX_DEV_CTRL	0xe8	/* 16 bit	PEX Device Control */
+#define PEX_DEV_STAT	0xea	/* 16 bit	PEX Device Status */
+#define PEX_LNK_CAP		0xec	/* 32 bit	PEX Link Capabilities */
+#define PEX_LNK_CTRL	0xf0	/* 16 bit	PEX Link Control */
+#define PEX_LNK_STAT	0xf2	/* 16 bit	PEX Link Status */
+	/* Bytes 0xf4..0xff:	reserved */
+
+/*
+ * Yukon-Extreme B0: These registers have been moved to 0xc0..0xd2.
+ *					 Use PEX_CAP_REG() macro to access
+ */
+#define PEX_CAP_REG_OFFS	0x20
+#define PEX_CAP_REGS(Reg)	((Reg) - (pAC->GIni.GIPexCapOffs))
+
+/* PCI Express Extended Capabilities */
+#define PEX_ADV_ERR_REP		0x100	/* 32 bit	PEX Advanced Error Reporting */
+#define PEX_UNC_ERR_STAT	0x104	/* 32 bit	PEX Uncorr. Errors Status */
+#define PEX_UNC_ERR_MASK	0x108	/* 32 bit	PEX Uncorr. Errors Mask */
+#define PEX_UNC_ERR_SEV		0x10c	/* 32 bit	PEX Uncorr. Errors Severity */
+#define PEX_COR_ERR_STAT	0x110	/* 32 bit	PEX Correc. Errors Status */
+#define PEX_COR_ERR_MASK	0x114	/* 32 bit	PEX Correc. Errors Mask */
+#define PEX_ADV_ERR_CAP_C	0x118	/* 32 bit	PEX Advanced Error Cap./Ctrl */
+#define PEX_HEADER_LOG		0x11c	/* 4x32 bit	PEX Header Log Register */
+
+#define PEX_COMPL_TIMEOUT	0x220	/* 32 bit	PEX Completion Timeout */
+#define PEX_FLOW_CONTROL	0x224	/* 32 bit	PEX Flow Control */
+
+/* PCI Express Ack Timer for 1x Link */
+#define PEX_ACK_LAT_TOX1	0x228	/* 16 bit	PEX Ack Latency Timeout x1 */
+#define PEX_ACK_RPLY_TOX1	0x22a	/* 16 bit	PEX Ack Reply Timeout val x1 */
+
+/*
+ * I2C Address (PCI Config)
+ *
+ * Note:
+ *	The temperature and voltage sensors are relocated on a different I2C bus
+ */
+#define I2C_ADDR_VPD	0xa0	/* I2C address for the VPD EEPROM */
+
+/*
+ * Define Bits and Values of the registers
+ */
+/*	PCI_COMMAND	16 bit	Command */
+								/* Bit 15..11:	reserved */
+#define PCI_INT_DIS		BIT_10S		/* Interrupt INTx# disable (PCI 2.3) */
+#define PCI_FBTEN		BIT_9S		/* Fast Back-To-Back enable */
+#define PCI_SERREN		BIT_8S		/* SERR enable */
+#define PCI_ADSTEP		BIT_7S		/* Address Stepping */
+#define PCI_PERREN		BIT_6S		/* Parity Report Response enable */
+#define PCI_VGA_SNOOP	BIT_5S		/* VGA palette snoop */
+#define PCI_MWIEN		BIT_4S		/* Memory write an inv cycl enable */
+#define PCI_SCYCEN		BIT_3S		/* Special Cycle enable */
+#define PCI_BMEN		BIT_2S		/* Bus Master enable */
+#define PCI_MEMEN		BIT_1S		/* Memory Space Access enable */
+#define PCI_IOEN		BIT_0S		/* I/O Space Access enable */
+
+#define PCI_COMMAND_VAL	(PCI_INT_DIS | PCI_SERREN | PCI_PERREN | \
+						 PCI_BMEN | PCI_MEMEN | PCI_IOEN)
+
+/*	PCI_STATUS	16 bit	Status */
+#define PCI_PERR		BIT_15S		/* Parity Error */
+#define PCI_SERR		BIT_14S		/* Signaled SERR */
+#define PCI_RMABORT		BIT_13S		/* Received Master Abort */
+#define PCI_RTABORT		BIT_12S		/* Received Target Abort */
+								/* Bit 11:	reserved */
+#define PCI_DEVSEL		(3<<9)		/* Bit 10.. 9:	DEVSEL Timing */
+#define PCI_DEV_FAST	(0<<9)		/*		fast */
+#define PCI_DEV_MEDIUM	(1<<9)		/*		medium */
+#define PCI_DEV_SLOW	(2<<9)		/*		slow */
+#define PCI_DATAPERR	BIT_8S		/* DATA Parity error detected */
+#define PCI_FB2BCAP		BIT_7S		/* Fast Back-to-Back Capability */
+#define PCI_UDF			BIT_6S		/* User Defined Features */
+#define PCI_66MHZCAP	BIT_5S		/* 66 MHz PCI bus clock capable */
+#define PCI_NEWCAP		BIT_4S		/* New cap. list implemented */
+#define PCI_INT_STAT	BIT_3S		/* Interrupt INTx# Status (PCI 2.3) */
+								/* Bit  2.. 0:	reserved */
+
+#define PCI_ERRBITS	(PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\
+					 PCI_DATAPERR)
+
+/*	PCI_CLASS_CODE	24 bit	Class Code */
+/*	Byte 2:		Base Class		(02) */
+/*	Byte 1:		SubClass		(00) */
+/*	Byte 0:		Programming Interface	(00) */
+
+/*	PCI_CACHE_LSZ	8 bit	Cache Line Size */
+/*	Possible values: 0, 2, 4, 8, 16, 32, 64, 128 */
+
+/*	PCI_HEADER_T	8 bit	Header Type */
+#define PCI_HD_MF_DEV	BIT_7S	/* 0= single, 1= multi-func dev */
+#define PCI_HD_TYPE		0x7f	/* Bit 6..0:	Header Layout (0=normal) */
+
+/*	PCI_BIST	8 bit	Built-in selftest */
+/*	Built-in Self test not supported (optional) */
+
+/*	PCI_BASE_1ST	32 bit	1st Base address */
+#define PCI_MEMSIZE		0x4000L		/* use 16 kB Memory Base */
+#define PCI_MEMBASE_MSK 0xffffc000L	/* Bit 31..14:	Memory Base Address */
+#define PCI_MEMSIZE_MSK 0x00003ff0L	/* Bit 13.. 4:	Memory Size Req. */
+#define PCI_PREFEN		BIT_3		/* Prefetch enable */
+#define PCI_MEM_TYP_MSK	(3L<<1)		/* Bit	2.. 1:	Memory Type Mask */
+#define PCI_MEMSPACE	BIT_0		/* Memory Space Indicator */
+
+#define PCI_MEM32BIT	(0L<<1)		/* Base addr anywhere in 32 Bit range */
+#define PCI_MEM1M		(1L<<1)		/* Base addr below 1 MegaByte */
+#define PCI_MEM64BIT	(2L<<1)		/* Base addr anywhere in 64 Bit range */
+
+/*	PCI_BASE_2ND	32 bit	2nd Base address */
+#define PCI_IOBASE		0xffffff00L	/* Bit 31.. 8:	I/O Base address */
+#define PCI_IOSIZE		0x000000fcL	/* Bit	7.. 2:	I/O Size Requirements */
+								/* Bit	1:	reserved */
+#define PCI_IOSPACE		BIT_0		/* I/O Space Indicator */
+
+/*	PCI_BASE_ROM	32 bit	Expansion ROM Base Address */
+#define PCI_ROMBASE_MSK	0xfffe0000L	/* Bit 31..17:	ROM Base address */
+#define PCI_ROMBASE_SIZ	(0x1cL<<14)	/* Bit 16..14:	Treat as Base or Size */
+#define PCI_ROMSIZE		(0x38L<<11)	/* Bit 13..11:	ROM Size Requirements */
+								/* Bit 10.. 1:	reserved */
+#define PCI_ROMEN		BIT_0		/* Address Decode enable */
+
+/* Device Dependent Region */
+/*	PCI_OUR_REG_1		32 bit	Our Register 1 */
+								/* Bit 31..29:	reserved */
+#define PCI_PHY_COMA	BIT_28		/* Set PHY to Coma Mode (YUKON only) */
+#define PCI_TEST_CAL	BIT_27		/* Test PCI buffer calib. (YUKON only) */
+#define PCI_EN_CAL		BIT_26		/* Enable PCI buffer calib. (YUKON only) */
+#define PCI_VIO			BIT_25		/* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
+/* Yukon-2 */
+#define PCI_Y2_PIG_ENA		BIT_31	/* Enable Plug-in-Go (YUKON-2) */
+#define PCI_Y2_DLL_DIS		BIT_30	/* Disable PCI DLL (YUKON-2) */
+#define PCI_SW_PWR_ON_RST	BIT_30	/* SW Power-on-reset (Yukon-Ext only) */
+#define PCI_Y2_PHY2_COMA	BIT_29	/* Set PHY 2 to Coma Mode (YUKON-2) */
+#define PCI_Y2_PHY1_COMA	BIT_28	/* Set PHY 1 to Coma Mode (YUKON-2) */
+#define PCI_Y2_PHY2_POWD	BIT_27	/* Set PHY 2 to Power Down (YUKON-2) */
+#define PCI_Y2_PHY1_POWD	BIT_26	/* Set PHY 1 to Power Down (YUKON-2) */
+								/* Bit 25:	reserved */
+#define PCI_DIS_BOOT	BIT_24		/* Disable BOOT via ROM */
+#define PCI_EN_IO		BIT_23		/* Mapping to I/O space */
+#define PCI_EN_FPROM	BIT_22		/* Enable FLASH mapping to memory */
+									/*		1 = Map Flash to memory */
+									/*		0 = Disable addr. dec */
+#define PCI_PAGESIZE	(3L<<20)	/* Bit 21..20:	FLASH Page Size */
+#define PCI_PAGE_16		(0L<<20)	/*		 16 k pages */
+#define PCI_PAGE_32K	(1L<<20)	/*		 32 k pages */
+#define PCI_PAGE_64K	(2L<<20)	/*		 64 k pages */
+#define PCI_PAGE_128K	(3L<<20)	/*		128 k pages */
+								/* Bit 19:	reserved */
+#define PCI_PAGEREG		(7L<<16)	/* Bit 18..16:	Page Register */
+#define PCI_NOTAR		BIT_15		/* No turnaround cycle */
+#define PCI_PEX_LEGNAT	BIT_15		/* PEX PM legacy/native mode (YUKON-2) */
+#define PCI_FORCE_BE	BIT_14		/* Assert all BEs on MR */
+#define PCI_DIS_MRL		BIT_13		/* Disable Mem Read Line */
+#define PCI_DIS_MRM		BIT_12		/* Disable Mem Read Multiple */
+#define PCI_DIS_MWI		BIT_11		/* Disable Mem Write & Invalidate */
+#define PCI_DISC_CLS	BIT_10		/* Disc: cacheLsz bound */
+#define PCI_BURST_DIS	BIT_9		/* Burst Disable */
+#define PCI_DIS_PCI_CLK	BIT_8		/* Disable PCI clock driving */
+#define PCI_SKEW_DAS	(0xfL<<4)	/* Bit	7.. 4:	Skew Ctrl, DAS Ext */
+#define PCI_SKEW_BASE	0xfL		/* Bit	3.. 0:	Skew Ctrl, Base */
+#define PCI_CLS_OPT		BIT_3		/* Cache Line Size opt. PCI-X (YUKON-2) */
+
+/* Yukon-EC Ultra only */
+								/* Bit 14..10:	reserved */
+#define PCI_PHY_LNK_TIM_MSK	(3L<<8)	/* Bit  9.. 8:	GPHY Link Trigger Timer */
+#define PCI_ENA_L1_EVENT	BIT_7	/* Enable PEX L1 Event */
+#define PCI_ENA_GPHY_LNK	BIT_6	/* Enable PEX L1 on GPHY Link down */
+#define PCI_FORCE_PEX_L1	BIT_5	/* Force to PEX L1 */
+								/* Bit  4.. 0:	reserved */
+
+/*	PCI_OUR_REG_2		32 bit	Our Register 2 */
+#define PCI_VPD_WR_THR	(0xffL<<24)	/* Bit 31..24:	VPD Write Threshold */
+#define PCI_DEV_SEL		(0x7fL<<17)	/* Bit 23..17:	EEPROM Device Select */
+#define PCI_VPD_ROM_SZ	(7L<<14)	/* Bit 16..14:	VPD ROM Size */
+								/* Bit 13..12:	reserved */
+#define PCI_PATCH_DIR	(0xfL<<8)	/* Bit 11.. 8:	Ext Patches dir 3..0 */
+#define PCI_PATCH_DIR_3	BIT_11
+#define PCI_PATCH_DIR_2	BIT_10
+#define PCI_PATCH_DIR_1	BIT_9
+#define PCI_PATCH_DIR_0	BIT_8
+#define PCI_EXT_PATCHS	(0xfL<<4)	/* Bit	7.. 4:	Extended Patches 3..0 */
+#define PCI_EXT_PATCH_3	BIT_7
+#define PCI_EXT_PATCH_2	BIT_6
+#define PCI_EXT_PATCH_1	BIT_5
+#define PCI_EXT_PATCH_0	BIT_4
+#define PCI_EN_DUMMY_RD	BIT_3		/* Enable Dummy Read */
+#define PCI_REV_DESC	BIT_2		/* Reverse Descriptor Bytes */
+								/* Bit	1:	reserved */
+#define PCI_USEDATA64	BIT_0		/* Use 64Bit Data bus ext */
+
+/* Power Management (PM) Region */
+/*	PCI_PM_CAP_REG		16 bit	Power Management Capabilities */
+#define PCI_PME_SUP_MSK	(0x1f<<11)	/* Bit 15..11:	PM Event (PME) Supp. Mask */
+#define PCI_PME_D3C_SUP	BIT_15S		/* PME from D3cold Support (if VAUX) */
+#define PCI_PME_D3H_SUP	BIT_14S		/* PME from D3hot Support */
+#define PCI_PME_D2_SUP	BIT_13S		/* PME from D2 Support */
+#define PCI_PME_D1_SUP	BIT_12S		/* PME from D1 Support */
+#define PCI_PME_D0_SUP	BIT_11S		/* PME from D0 Support */
+#define PCI_PM_D2_SUP	BIT_10S		/* D2 Support in 33 MHz mode */
+#define PCI_PM_D1_SUP	BIT_9S		/* D1 Support */
+								/* Bit	8.. 6:	reserved */
+#define PCI_PM_DSI		BIT_5S		/* Device Specific Initialization */
+#define PCI_PM_APS		BIT_4S		/* Auxialiary Power Source */
+#define PCI_PME_CLOCK	BIT_3S		/* PM Event Clock */
+#define PCI_PM_VER_MSK		7		/* Bit	2.. 0:	PM PCI Spec. version */
+
+/*	PCI_PM_CTL_STS		16 bit	Power Management Control/Status */
+#define PCI_PME_STATUS	BIT_15S		/* PME Status (YUKON only) */
+#define PCI_PM_DAT_SCL	(3<<13)		/* Bit 14..13:	Data Reg. scaling factor */
+#define PCI_PM_DAT_SEL	(0xf<<9)	/* Bit 12.. 9:	PM data selector field */
+#define PCI_PME_EN		BIT_8S		/* Enable PME# generation (YUKON only) */
+								/* Bit	7.. 2:	reserved */
+#define PCI_PM_STATE_MSK	3		/* Bit	1.. 0:	Power Management State */
+
+#define PCI_PM_STATE_D0		0		/* D0:	Operational (default) */
+#define PCI_PM_STATE_D1		1		/* D1:	(YUKON only) */
+#define PCI_PM_STATE_D2		2		/* D2:	(YUKON only) */
+#define PCI_PM_STATE_D3 	3		/* D3:	HOT, Power Down and Reset */
+
+/* VPD Region */
+/*	PCI_VPD_ADR_REG		16 bit	VPD Address Register */
+#define PCI_VPD_FLAG	BIT_15S		/* starts VPD rd/wr cycle */
+#define PCI_VPD_ADR_MSK	0x7fffL		/* Bit 14.. 0:	VPD Address Mask */
+
+/*	PCI_OUR_STATUS		32 bit	Adapter Status Register (Yukon-2) */
+#define PCI_OS_PCI64B	BIT_31		/* Conventional PCI 64 bits Bus */
+#define PCI_OS_PCIX		BIT_30		/* PCI-X Bus */
+#define PCI_OS_MODE_MSK	(3L<<28)	/* Bit 29..28:	PCI-X Bus Mode Mask */
+#define PCI_OS_PCI66M	BIT_27		/* PCI 66 MHz Bus */
+#define PCI_OS_PCI_X	BIT_26		/* PCI/PCI-X Bus (0 = PEX) */
+#define PCI_OS_DLLE_MSK	(3L<<24)	/* Bit 25..24:	DLL Status Indication */
+#define PCI_OS_DLLR_MSK	(0xfL<<20)	/* Bit 23..20:	DLL Row Counters Values */
+#define PCI_OS_DLLC_MSK	(0xfL<<16)	/* Bit 19..16:	DLL Col. Counters Values */
+								/* Bit 15.. 8:	reserved */
+
+#define PCI_OS_SPEED(val)	((val & PCI_OS_MODE_MSK) >> 28)	/* PCI-X Speed */
+/* possible values for the speed field of the register */
+#define PCI_OS_SPD_PCI		0		/* PCI Conventional Bus */
+#define PCI_OS_SPD_X66		1		/* PCI-X 66MHz Bus */
+#define PCI_OS_SPD_X100		2		/* PCI-X 100MHz Bus */
+#define PCI_OS_SPD_X133		3		/* PCI-X 133MHz Bus */
+
+/*	PCI_OUR_REG_3		32 bit	Our Register 3 (Yukon-ECU only) */
+								/* Bit 31..18:	reserved */
+#define P_CLK_ASF_REGS_DIS		BIT_18	/* Disable Clock ASF (Yukon-Ext only) */
+#define P_CLK_COR_REGS_D0_DIS	BIT_17	/* Disable Clock Core Regs D0 */
+#define P_CLK_PCI_REGS_D0_DIS	BIT_16	/* Disable Clock PCI  Regs D0 */
+#define P_CLK_COR_YTB_ARB_DIS	BIT_15	/* Disable Clock YTB  Arbiter */
+#define P_CLK_MAC_LNK1_D3_DIS	BIT_14	/* Disable Clock MAC  Link1 D3 */
+#define P_CLK_COR_LNK1_D0_DIS	BIT_13	/* Disable Clock Core Link1 D0 */
+#define P_CLK_MAC_LNK1_D0_DIS	BIT_12	/* Disable Clock MAC  Link1 D0 */
+#define P_CLK_COR_LNK1_D3_DIS	BIT_11	/* Disable Clock Core Link1 D3 */
+#define P_CLK_PCI_MST_ARB_DIS	BIT_10	/* Disable Clock PCI  Master Arb. */
+#define P_CLK_COR_REGS_D3_DIS	BIT_9	/* Disable Clock Core Regs D3 */
+#define P_CLK_PCI_REGS_D3_DIS	BIT_8	/* Disable Clock PCI  Regs D3 */
+#define P_CLK_REF_LNK1_GM_DIS	BIT_7	/* Disable Clock Ref. Link1 GMAC */
+#define P_CLK_COR_LNK1_GM_DIS	BIT_6	/* Disable Clock Core Link1 GMAC */
+#define P_CLK_PCI_COMMON_DIS	BIT_5	/* Disable Clock PCI  Common */
+#define P_CLK_COR_COMMON_DIS	BIT_4	/* Disable Clock Core Common */
+#define P_CLK_PCI_LNK1_BMU_DIS	BIT_3	/* Disable Clock PCI  Link1 BMU */
+#define P_CLK_COR_LNK1_BMU_DIS	BIT_2	/* Disable Clock Core Link1 BMU */
+#define P_CLK_PCI_LNK1_BIU_DIS	BIT_1	/* Disable Clock PCI  Link1 BIU */
+#define P_CLK_COR_LNK1_BIU_DIS	BIT_0	/* Disable Clock Core Link1 BIU */
+
+#define PCIE_OUR3_WOL_D3_COLD_SET	( \
+							P_CLK_ASF_REGS_DIS | \
+							P_CLK_COR_REGS_D0_DIS | \
+							P_CLK_COR_LNK1_D0_DIS | \
+							P_CLK_MAC_LNK1_D0_DIS | \
+							P_CLK_PCI_MST_ARB_DIS | \
+							P_CLK_COR_COMMON_DIS | \
+							P_CLK_COR_LNK1_BMU_DIS)
+
+/*	PCI_OUR_REG_4		32 bit	Our Register 4 (Yukon-ECU only) */
+#define P_PEX_LTSSM_STAT_MSK	(0x7fL<<25)	/* Bit 31..25:	PEX LTSSM Mask */
+									/* (Link Training & Status State Machine) */
+#define P_ASPM_GPHY_INT_ENA		BIT_24	/* GPHY Interrupt (Yukon-Ext. only) */
+#define P_TIMER_VALUE_MSK		(0xffL<<16)	/* Bit 23..16:	Timer Value Mask */
+#define P_FORCE_ASPM_REQUEST	BIT_15	/* Force ASPM Request (A1 only) */
+										/* (Active State Power Management) */
+										/* Bit 14..12: Force ASPM on Event */
+#define P_ASPM_GPHY_LINK_DOWN	BIT_14	/* GPHY Link Down (A1 only) */
+#define P_ASPM_INT_FIFO_EMPTY	BIT_13	/* Internal FIFO Empty (A1 only) */
+#define P_ASPM_CLKRUN_REQUEST	BIT_12	/* CLKRUN Request (A1 only) */
+								/* Bit 11.. 7:	reserved */
+#define P_PIN63_LINK_LED_ENA	BIT_8	/* Enable Pin #63 as Link LED (A3) */
+#define P_ASPM_FORCE_ASPM_L1	BIT_7	/* Force ASPM L1  Enable (A1b only) */
+#define P_ASPM_FORCE_ASPM_L0S	BIT_6	/* Force ASPM L0s Enable (A1b only) */
+#define P_ASPM_FORCE_CLKREQ_PIN	BIT_5	/* Force CLKREQn pin low (A1b only) */
+#define P_ASPM_FORCE_CLKREQ_ENA	BIT_4	/* Force CLKREQ Enable (A1b only) */
+#define P_ASPM_CLKREQ_PAD_CTL	BIT_3	/* CLKREQ PAD Control (A1 only) */
+#define P_ASPM_A1_MODE_SELECT	BIT_2	/* A1 Mode Select (A1 only) */
+#define P_CLK_GATE_PEX_UNIT_ENA	BIT_1	/* Enable Gate PEX Unit Clock */
+#define P_CLK_GATE_ROOT_COR_ENA	BIT_0	/* Enable Gate Root Core Clock */
+
+#define P_PEX_LTSSM_STAT(x)		(SHIFT25(x) & P_PEX_LTSSM_STAT_MSK)
+#define P_PEX_LTSSM_L1_STAT		0x34
+#define P_PEX_LTSSM_DET_STAT	0x01
+
+#define P_ASPM_CONTROL_MSK	(P_FORCE_ASPM_REQUEST | P_ASPM_GPHY_LINK_DOWN | \
+							 P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY | \
+							 P_PIN63_LINK_LED_ENA)
+
+#define PCIE_OUR4_DYN_CLK_GATE_SET	( \
+							P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) | \
+							P_TIMER_VALUE_MSK | \
+							P_ASPM_INT_FIFO_EMPTY | \
+							P_ASPM_CLKRUN_REQUEST | \
+							P_ASPM_FORCE_CLKREQ_ENA | \
+							P_ASPM_A1_MODE_SELECT | \
+							P_CLK_GATE_ROOT_COR_ENA)
+
+/*	PCI_OUR_REG_5		32 bit	Our Register 5 (Yukon-ECU only) */
+										/* Bit 31..27:	for A3 & later */
+#define P_CTL_DIV_CORE_CLK_ENA	BIT_31	/* Divide Core Clock Enable */
+#define P_CTL_SRESET_VMAIN_AV	BIT_30	/* Soft Reset for Vmain_av De-Glitch */
+#define P_CTL_BYPASS_VMAIN_AV	BIT_29	/* Bypass En. for Vmain_av De-Glitch */
+#define P_CTL_TIM_VMAIN_AV_MSK	(3<<27)	/* Bit 28..27: Timer Vmain_av Mask */
+										/* Bit 26..14: Release Clock on Event */
+#define P_REL_PCIE_RST_DE_ASS	BIT_26	/* PCIe Reset De-Asserted */
+#define P_REL_GPHY_REC_PACKET	BIT_25	/* GPHY Received Packet */
+#define P_REL_INT_FIFO_N_EMPTY	BIT_24	/* Internal FIFO Not Empty */
+#define P_REL_MAIN_PWR_AVAIL	BIT_23	/* Main Power Available */
+#define P_REL_CLKRUN_REQ_REL	BIT_22	/* CLKRUN Request Release */
+#define P_REL_PCIE_RESET_ASS	BIT_21	/* PCIe Reset Asserted */
+#define P_REL_PME_ASSERTED		BIT_20	/* PME Asserted */
+#define P_REL_PCIE_EXIT_L1_ST	BIT_19	/* PCIe Exit L1 State */
+#define P_REL_LOADER_NOT_FIN	BIT_18	/* EPROM Loader Not Finished */
+#define P_REL_PCIE_RX_EX_IDLE	BIT_17	/* PCIe Rx Exit Electrical Idle State */
+#define P_REL_GPHY_LINK_UP		BIT_16	/* GPHY Link Up */
+#define P_REL_CPU_TO_SLEEP		BIT_15	/* CPU Goes to Sleep */
+#define P_REL_GPHY_ASS_IRQ		BIT_14	/* GPHY Asserts IRQ */
+									/* Bit 13:	reserved */
+										/* Bit 12.. 0: Mask for Gate Clock */
+#define P_GAT_GPHY_ASS_IRQ		BIT_12	/* GPHY Asserts IRQ */
+#define P_GAT_CPU_TO_SLEEP		BIT_11	/* CPU Goes to Sleep and Events */
+#define P_GAT_PCIE_RST_ASSERTED	BIT_10	/* PCIe Reset Asserted */
+#define P_GAT_GPHY_N_REC_PACKET	BIT_9	/* GPHY Not Received Packet */
+#define P_GAT_INT_FIFO_EMPTY	BIT_8	/* Internal FIFO Empty */
+#define P_GAT_MAIN_PWR_N_AVAIL	BIT_7	/* Main Power Not Available */
+#define P_GAT_CLKRUN_REQ_REL	BIT_6	/* CLKRUN Not Requested */
+#define P_GAT_PCIE_RESET_ASS	BIT_5	/* PCIe Reset Asserted */
+#define P_GAT_PME_DE_ASSERTED	BIT_4	/* PME De-Asserted */
+#define P_GAT_PCIE_ENTER_L1_ST	BIT_3	/* PCIe Enter L1 State */
+#define P_GAT_LOADER_FINISHED	BIT_2	/* EPROM Loader Finished */
+#define P_GAT_PCIE_RX_EL_IDLE	BIT_1	/* PCIe Rx Electrical Idle State */
+#define P_GAT_GPHY_LINK_DOWN	BIT_0	/* GPHY Link Down */
+
+#define PCIE_OUR5_EVENT_CLK_D3_SET	( \
+							P_REL_GPHY_REC_PACKET | \
+							P_REL_INT_FIFO_N_EMPTY | \
+							P_REL_PCIE_EXIT_L1_ST | \
+							P_REL_PCIE_RX_EX_IDLE | \
+							P_GAT_GPHY_N_REC_PACKET | \
+							P_GAT_INT_FIFO_EMPTY | \
+							P_GAT_PCIE_ENTER_L1_ST | \
+							P_GAT_PCIE_RX_EL_IDLE)
+
+#/*	PCI_CFG_REG_1			32 bit	Config Register 1 (Yukon-Ext only) */
+#define P_CF1_DIS_REL_EVT_RST	BIT_24	/* Dis. Rel. Event during PCIE reset */
+										/* Bit 23..21: Release Clock on Event */
+#define P_CF1_REL_LDR_NOT_FIN	BIT_23	/* EEPROM Loader Not Finished */
+#define P_CF1_REL_VMAIN_AVLBL	BIT_22	/* Vmain available */
+#define P_CF1_REL_PCIE_RESET	BIT_21	/* PCI-E reset */
+										/* Bit 20..18: Gate Clock on Event */
+#define P_CF1_GAT_LDR_NOT_FIN	BIT_20	/* EEPROM Loader Finished */
+#define P_CF1_GAT_PCIE_RX_IDLE	BIT_19	/* PCI-E Rx Electrical idle */
+#define P_CF1_GAT_PCIE_RESET	BIT_18	/* PCI-E Reset */
+#define P_CF1_PRST_PHY_CLKREQ	BIT_17	/* Enable PCI-E rst & PM2PHY gen. CLKREQ */
+#define P_CF1_PCIE_RST_CLKREQ	BIT_16	/* Enable PCI-E rst generate CLKREQ */
+
+#define P_CF1_ENA_CFG_LDR_DONE	BIT_8	/* Enable core level Config loader done */
+
+#define P_CF1_ENA_TXBMU_RD_IDLE	BIT_1	/* Enable TX BMU Read  IDLE for ASPM */
+#define P_CF1_ENA_TXBMU_WR_IDLE	BIT_0	/* Enable TX BMU Write IDLE for ASPM */
+
+#define PCIE_CFG1_EVENT_CLK_D3_SET	( \
+							P_CF1_DIS_REL_EVT_RST | \
+							P_CF1_REL_LDR_NOT_FIN | \
+							P_CF1_REL_VMAIN_AVLBL | \
+							P_CF1_REL_PCIE_RESET | \
+							P_CF1_GAT_LDR_NOT_FIN | \
+							P_CF1_GAT_PCIE_RESET | \
+							P_CF1_PRST_PHY_CLKREQ | \
+							P_CF1_ENA_CFG_LDR_DONE | \
+							P_CF1_ENA_TXBMU_RD_IDLE | \
+							P_CF1_ENA_TXBMU_WR_IDLE)
+
+/*	PEX_DEV_CTRL			16 bit	PEX Device Control (Yukon-2) */
+								/* Bit 15	reserved */
+#define PEX_DC_MAX_RRS_MSK	(7<<12)	/* Bit 14..12:	Max. Read Request Size */
+#define PEX_DC_EN_NO_SNOOP	BIT_11S	/* Enable No Snoop */
+#define PEX_DC_EN_AUX_POW	BIT_10S	/* Enable AUX Power */
+#define PEX_DC_EN_PHANTOM	BIT_9S	/* Enable Phantom Functions */
+#define PEX_DC_EN_EXT_TAG	BIT_8S	/* Enable Extended Tag Field */
+#define PEX_DC_MAX_PLS_MSK	(7<<5)	/* Bit  7.. 5:	Max. Payload Size Mask */
+#define PEX_DC_EN_REL_ORD	BIT_4S	/* Enable Relaxed Ordering */
+#define PEX_DC_EN_UNS_RQ_RP	BIT_3S	/* Enable Unsupported Request Reporting */
+#define PEX_DC_EN_FAT_ER_RP	BIT_2S	/* Enable Fatal Error Reporting */
+#define PEX_DC_EN_NFA_ER_RP	BIT_1S	/* Enable Non-Fatal Error Reporting */
+#define PEX_DC_EN_COR_ER_RP	BIT_0S	/* Enable Correctable Error Reporting */
+
+#define PEX_DC_MAX_RD_RQ_SIZE(x)	(SHIFT12(x) & PEX_DC_MAX_RRS_MSK)
+
+/*	PEX_LNK_CAP			32 bit	PEX Link Capabilities */
+#define PEX_CAP_MAX_WI_MSK	(0x3f<<4)	/* Bit  9.. 4:	Max. Link Width Mask */
+#define PEX_CAP_MAX_SP_MSK	0x0f	/* Bit  3.. 0:	Max. Link Speed Mask */
+
+/*	PEX_LNK_CTRL			16 bit	PEX Link Control (Yukon-2) */
+#define PEX_LC_CLK_PM_ENA	BIT_8S	/* Enable Clock Power Management (CLKREQ) */
+#define PEX_LC_ASPM_LC_L1	BIT_1S	/* Enable ASPM Entry L1  */
+#define PEX_LC_ASPM_LC_L0S	BIT_0S	/* Enable ASPM Entry L0s */
+#define PEX_LC_ASPM_LC_MSK	0x03	/* Bit  1.. 0:	ASPM Link Control Mask */
+
+/*	PEX_LNK_STAT			16 bit	PEX Link Status (Yukon-2) */
+								/* Bit 15..13	reserved */
+#define PEX_LS_SLOT_CLK_CFG	BIT_12S	/* Slot Clock Config */
+#define PEX_LS_LINK_TRAIN	BIT_11S	/* Link Training */
+#define PEX_LS_TRAIN_ERROR	BIT_10S	/* Training Error */
+#define PEX_LS_LINK_WI_MSK	(0x3f<<4)	/* Bit  9.. 4:	Neg. Link Width Mask */
+#define PEX_LS_LINK_SP_MSK	0x0f	/* Bit  3.. 0:	Link Speed Mask */
+
+/*	PEX_UNC_ERR_STAT		16 bit	PEX Uncorrectable Errors Status (Yukon-2) */
+								/* Bit 31..21	reserved */
+#define PEX_UNSUP_REQ	BIT_20		/* Unsupported Request Error */
+									/* ECRC Error (not supported) */
+#define PEX_MALFOR_TLP	BIT_18		/* Malformed TLP */
+#define PEX_RX_OV		BIT_17		/* Receiver Overflow (not supported) */
+#define PEX_UNEXP_COMP	BIT_16		/* Unexpected Completion */
+									/* Completer Abort (not supported) */
+#define PEX_COMP_TO		BIT_14		/* Completion Timeout */
+#define PEX_FLOW_CTRL_P	BIT_13		/* Flow Control Protocol Error */
+#define PEX_POIS_TLP	BIT_12		/* Poisoned TLP */
+								/* Bit 11.. 5:	reserved */
+#define PEX_DATA_LINK_P BIT_4		/* Data Link Protocol Error */
+								/* Bit  3.. 1:	reserved */
+									/* Training Error (not supported) */
+
+#define PEX_FATAL_ERRORS	(PEX_MALFOR_TLP | PEX_FLOW_CTRL_P | PEX_DATA_LINK_P)
+
+/*	Control Register File (Address Map) */
+
+/*
+ *	Bank 0
+ */
+#define B0_RAP			0x0000	/*  8 bit	Register Address Port */
+	/* 0x0001 - 0x0003:	reserved */
+#define B0_CTST			0x0004	/* 16 bit	Control/Status Register */
+#define B0_LED			0x0006	/*  8 Bit	LED Register */
+#define B0_POWER_CTRL	0x0007	/*  8 Bit	Power Control reg (YUKON only) */
+#define B0_ISRC			0x0008	/* 32 bit	Interrupt Source Register */
+#define B0_IMSK			0x000c	/* 32 bit	Interrupt Mask Register */
+#define B0_HWE_ISRC		0x0010	/* 32 bit	HW Error Interrupt Src Reg */
+#define B0_HWE_IMSK		0x0014	/* 32 bit	HW Error Interrupt Mask Reg */
+#define B0_SP_ISRC		0x0018	/* 32 bit	Special Interrupt Source Reg 1 */
+
+/* Special ISR registers (Yukon-2 only) */
+#define B0_Y2_SP_ISRC2	0x001c	/* 32 bit	Special Interrupt Source Reg 2 */
+#define B0_Y2_SP_ISRC3	0x0020	/* 32 bit	Special Interrupt Source Reg 3 */
+#define B0_Y2_SP_EISR	0x0024	/* 32 bit	Enter ISR Register */
+#define B0_Y2_SP_LISR	0x0028	/* 32 bit	Leave ISR Register */
+#define B0_Y2_SP_ICR	0x002c	/* 32 bit	Interrupt Control Register */
+
+/* B0 XMAC 1 registers (GENESIS only) */
+#define B0_XM1_IMSK		0x0020	/* 16 bit r/w	XMAC 1 Interrupt Mask Register*/
+	/* 0x0022 - 0x0027:	reserved */
+#define B0_XM1_ISRC		0x0028	/* 16 bit ro	XMAC 1 Interrupt Status Reg */
+	/* 0x002a - 0x002f:	reserved */
+#define B0_XM1_PHY_ADDR 0x0030	/* 16 bit r/w	XMAC 1 PHY Address Register */
+	/* 0x0032 - 0x0033:	reserved */
+#define B0_XM1_PHY_DATA 0x0034	/* 16 bit r/w	XMAC 1 PHY Data Register */
+	/* 0x0036 - 0x003f:	reserved */
+
+/* B0 XMAC 2 registers (GENESIS only) */
+#define B0_XM2_IMSK		0x0040	/* 16 bit r/w	XMAC 2 Interrupt Mask Register*/
+	/* 0x0042 - 0x0047:	reserved */
+#define B0_XM2_ISRC		0x0048	/* 16 bit ro	XMAC 2 Interrupt Status Reg */
+	/* 0x004a - 0x004f:	reserved */
+#define B0_XM2_PHY_ADDR 0x0050	/* 16 bit r/w	XMAC 2 PHY Address Register */
+	/* 0x0052 - 0x0053:	reserved */
+#define B0_XM2_PHY_DATA 0x0054	/* 16 bit r/w	XMAC 2 PHY Data Register */
+	/* 0x0056 - 0x005f:	reserved */
+
+/* BMU Control Status Registers (Yukon and Genesis) */
+#define B0_R1_CSR		0x0060	/* 32 bit	BMU Ctrl/Stat Rx Queue 1 */
+#define B0_R2_CSR		0x0064	/* 32 bit	BMU Ctrl/Stat Rx Queue 2 */
+#define B0_XS1_CSR		0x0068	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
+#define B0_XA1_CSR		0x006c	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 1*/
+#define B0_XS2_CSR		0x0070	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
+#define B0_XA2_CSR		0x0074	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 2*/
+	/* 0x0078 - 0x007f:	reserved */
+
+/*
+ *	Bank 1
+ *	- completely empty (this is the RAP Block window)
+ *	Note: if RAP = 1 this page is reserved
+ */
+
+/*
+ *	Bank 2
+ */
+/* NA reg = 48 bit Network Address Register, 3x16 or 6x8 bit readable */
+#define B2_MAC_1		0x0100	/* NA reg	 MAC Address 1 */
+	/* 0x0106 - 0x0107:	reserved */
+#define B2_MAC_2		0x0108	/* NA reg	 MAC Address 2 */
+	/* 0x010e - 0x010f:	reserved */
+#define B2_MAC_3		0x0110	/* NA reg	 MAC Address 3 */
+	/* 0x0116 - 0x0117:	reserved */
+#define B2_CONN_TYP		0x0118	/*  8 bit	Connector type */
+#define B2_PMD_TYP		0x0119	/*  8 bit	PMD type */
+#define B2_MAC_CFG		0x011a	/*  8 bit	MAC Configuration / Chip Revision */
+#define B2_CHIP_ID		0x011b	/*  8 bit	Chip Identification Number */
+	/* Eprom registers */
+#define B2_E_0			0x011c	/*  8 bit	EPROM Byte 0 (ext. SRAM size */
+/* Yukon and Genesis */
+#define B2_E_1			0x011d	/*  8 bit	EPROM Byte 1 (PHY type) */
+#define B2_E_2			0x011e	/*  8 bit	EPROM Byte 2 */
+/* Yukon-2 */
+#define B2_Y2_CLK_GATE	0x011d	/*  8 bit	Clock Gating (Yukon-2) */
+#define B2_Y2_HW_RES	0x011e	/*  8 bit	HW Resources (Yukon-2) */
+
+#define B2_E_3			0x011f	/*  8 bit	EPROM Byte 3 */
+
+/* Yukon and Genesis */
+#define B2_FAR			0x0120	/* 32 bit	Flash-Prom Addr Reg/Cnt */
+#define B2_FDP			0x0124	/*  8 bit	Flash-Prom Data Port */
+/* Yukon-2 */
+#define B2_Y2_CLK_CTRL	0x0120	/* 32 bit	Core Clock Frequency Control */
+	/* 0x0125 - 0x0127:	reserved */
+#define B2_LD_CTRL		0x0128	/*  8 bit	EPROM loader control register */
+#define B2_LD_TEST		0x0129	/*  8 bit	EPROM loader test register */
+	/* 0x012a - 0x012f:	reserved */
+#define B2_TI_INI		0x0130	/* 32 bit	Timer Init Value */
+#define B2_TI_VAL		0x0134	/* 32 bit	Timer Value */
+#define B2_TI_CTRL		0x0138	/*  8 bit	Timer Control */
+#define B2_TI_TEST		0x0139	/*  8 Bit	Timer Test */
+	/* 0x013a - 0x013f:	reserved */
+#define B2_IRQM_INI		0x0140	/* 32 bit	IRQ Moderation Timer Init Reg.*/
+#define B2_IRQM_VAL		0x0144	/* 32 bit	IRQ Moderation Timer Value */
+#define B2_IRQM_CTRL	0x0148	/*  8 bit	IRQ Moderation Timer Control */
+#define B2_IRQM_TEST	0x0149	/*  8 bit	IRQ Moderation Timer Test */
+#define B2_IRQM_MSK 	0x014c	/* 32 bit	IRQ Moderation Mask */
+#define B2_IRQM_HWE_MSK 0x0150	/* 32 bit	IRQ Moderation HW Error Mask */
+	/* 0x0154 - 0x0157:	reserved */
+#define B2_TST_CTRL1	0x0158	/*  8 bit	Test Control Register 1 */
+#define B2_TST_CTRL2	0x0159	/*  8 bit	Test Control Register 2 */
+	/* 0x015a - 0x015b:	reserved */
+#define B2_GP_IO		0x015c	/* 32 bit	General Purpose I/O Register */
+#define B2_I2C_CTRL		0x0160	/* 32 bit	I2C HW Control Register */
+#define B2_I2C_DATA		0x0164	/* 32 bit	I2C HW Data Register */
+#define B2_I2C_IRQ		0x0168	/* 32 bit	I2C HW IRQ Register */
+#define B2_I2C_SW		0x016c	/* 32 bit	I2C SW Port Register */
+
+/* Blink Source Counter (GENESIS only) */
+#define B2_BSC_INI		0x0170	/* 32 bit	Blink Source Counter Init Val */
+#define B2_BSC_VAL		0x0174	/* 32 bit	Blink Source Counter Value */
+#define B2_BSC_CTRL		0x0178	/*  8 bit	Blink Source Counter Control */
+#define B2_BSC_STAT		0x0179	/*  8 bit	Blink Source Counter Status */
+#define B2_BSC_TST		0x017a	/* 16 bit	Blink Source Counter Test Reg */
+
+/* Yukon-2 */
+#define Y2_PEX_PHY_DATA	0x0170	/* 16 bit	PEX PHY Data Register */
+#define Y2_PEX_PHY_ADDR	0x0172	/* 16 bit	PEX PHY Address Register */
+	/* 0x017c - 0x017f:	reserved */
+
+/*
+ *	Bank 3
+ */
+/* RAM Random Registers */
+#define B3_RAM_ADDR		0x0180	/* 32 bit	RAM Address, to read or write */
+#define B3_RAM_DATA_LO	0x0184	/* 32 bit	RAM Data Word (low dWord) */
+#define B3_RAM_DATA_HI	0x0188	/* 32 bit	RAM Data Word (high dWord) */
+#define B3_RAM_PARITY	0x018c	/*  8 bit	RAM Parity (Yukon-ECU A1) */
+
+#define SELECT_RAM_BUFFER(rb, addr) (addr | (rb << 6))	/* Yukon-2 only */
+
+	/* 0x018c - 0x018f:	reserved */
+
+/* RAM Interface Registers */
+/* Yukon-2: use SELECT_RAM_BUFFER() to access the RAM buffer */
+/*
+ * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
+ * not usable in SW. Please notice these are NOT real timeouts, these are
+ * the number of qWords transferred continuously.
+ */
+#define B3_RI_WTO_R1	0x0190	/*  8 bit	WR Timeout Queue R1		(TO0) */
+#define B3_RI_WTO_XA1	0x0191	/*  8 bit	WR Timeout Queue XA1	(TO1) */
+#define B3_RI_WTO_XS1	0x0192	/*  8 bit	WR Timeout Queue XS1	(TO2) */
+#define B3_RI_RTO_R1	0x0193	/*  8 bit	RD Timeout Queue R1		(TO3) */
+#define B3_RI_RTO_XA1	0x0194	/*  8 bit	RD Timeout Queue XA1	(TO4) */
+#define B3_RI_RTO_XS1	0x0195	/*  8 bit	RD Timeout Queue XS1	(TO5) */
+#define B3_RI_WTO_R2	0x0196	/*  8 bit	WR Timeout Queue R2		(TO6) */
+#define B3_RI_WTO_XA2	0x0197	/*  8 bit	WR Timeout Queue XA2	(TO7) */
+#define B3_RI_WTO_XS2	0x0198	/*  8 bit	WR Timeout Queue XS2	(TO8) */
+#define B3_RI_RTO_R2	0x0199	/*  8 bit	RD Timeout Queue R2		(TO9) */
+#define B3_RI_RTO_XA2	0x019a	/*  8 bit	RD Timeout Queue XA2	(TO10) */
+#define B3_RI_RTO_XS2	0x019b	/*  8 bit	RD Timeout Queue XS2	(TO11) */
+#define B3_RI_TO_VAL	0x019c	/*  8 bit	Current Timeout Count Val */
+	/* 0x019d - 0x019f:	reserved */
+#define B3_RI_CTRL		0x01a0	/* 16 bit	RAM Interface Control Register */
+#define B3_RI_TEST		0x01a2	/*  8 bit	RAM Interface Test Register */
+	/* 0x01a3 - 0x01af:	reserved */
+
+/* MAC Arbiter Registers (GENESIS only) */
+/* these are the no. of qWord transferred continuously and NOT real timeouts */
+#define B3_MA_TOINI_RX1	0x01b0	/*  8 bit	Timeout Init Val Rx Path MAC 1 */
+#define B3_MA_TOINI_RX2	0x01b1	/*  8 bit	Timeout Init Val Rx Path MAC 2 */
+#define B3_MA_TOINI_TX1	0x01b2	/*  8 bit	Timeout Init Val Tx Path MAC 1 */
+#define B3_MA_TOINI_TX2	0x01b3	/*  8 bit	Timeout Init Val Tx Path MAC 2 */
+#define B3_MA_TOVAL_RX1	0x01b4	/*  8 bit	Timeout Value Rx Path MAC 1 */
+#define B3_MA_TOVAL_RX2	0x01b5	/*  8 bit	Timeout Value Rx Path MAC 1 */
+#define B3_MA_TOVAL_TX1	0x01b6	/*  8 bit	Timeout Value Tx Path MAC 2 */
+#define B3_MA_TOVAL_TX2	0x01b7	/*  8 bit	Timeout Value Tx Path MAC 2 */
+#define B3_MA_TO_CTRL	0x01b8	/* 16 bit	MAC Arbiter Timeout Ctrl Reg */
+#define B3_MA_TO_TEST	0x01ba	/* 16 bit	MAC Arbiter Timeout Test Reg */
+	/* 0x01bc - 0x01bf:	reserved */
+#define B3_MA_RCINI_RX1	0x01c0	/*  8 bit	Recovery Init Val Rx Path MAC 1 */
+#define B3_MA_RCINI_RX2	0x01c1	/*  8 bit	Recovery Init Val Rx Path MAC 2 */
+#define B3_MA_RCINI_TX1	0x01c2	/*  8 bit	Recovery Init Val Tx Path MAC 1 */
+#define B3_MA_RCINI_TX2	0x01c3	/*  8 bit	Recovery Init Val Tx Path MAC 2 */
+#define B3_MA_RCVAL_RX1	0x01c4	/*  8 bit	Recovery Value Rx Path MAC 1 */
+#define B3_MA_RCVAL_RX2	0x01c5	/*  8 bit	Recovery Value Rx Path MAC 1 */
+#define B3_MA_RCVAL_TX1	0x01c6	/*  8 bit	Recovery Value Tx Path MAC 2 */
+#define B3_MA_RCVAL_TX2	0x01c7	/*  8 bit	Recovery Value Tx Path MAC 2 */
+#define B3_MA_RC_CTRL	0x01c8	/* 16 bit	MAC Arbiter Recovery Ctrl Reg */
+#define B3_MA_RC_TEST	0x01ca	/* 16 bit	MAC Arbiter Recovery Test Reg */
+	/* 0x01cc - 0x01cf:	reserved */
+
+/* Packet Arbiter Registers (GENESIS only) */
+/* these are real timeouts */
+#define B3_PA_TOINI_RX1	0x01d0	/* 16 bit	Timeout Init Val Rx Path MAC 1 */
+	/* 0x01d2 - 0x01d3:	reserved */
+#define B3_PA_TOINI_RX2	0x01d4	/* 16 bit	Timeout Init Val Rx Path MAC 2 */
+	/* 0x01d6 - 0x01d7:	reserved */
+#define B3_PA_TOINI_TX1	0x01d8	/* 16 bit	Timeout Init Val Tx Path MAC 1 */
+	/* 0x01da - 0x01db:	reserved */
+#define B3_PA_TOINI_TX2	0x01dc	/* 16 bit	Timeout Init Val Tx Path MAC 2 */
+	/* 0x01de - 0x01df:	reserved */
+#define B3_PA_TOVAL_RX1	0x01e0	/* 16 bit	Timeout Val Rx Path MAC 1 */
+	/* 0x01e2 - 0x01e3:	reserved */
+#define B3_PA_TOVAL_RX2	0x01e4	/* 16 bit	Timeout Val Rx Path MAC 2 */
+	/* 0x01e6 - 0x01e7:	reserved */
+#define B3_PA_TOVAL_TX1	0x01e8	/* 16 bit	Timeout Val Tx Path MAC 1 */
+	/* 0x01ea - 0x01eb:	reserved */
+#define B3_PA_TOVAL_TX2	0x01ec	/* 16 bit	Timeout Val Tx Path MAC 2 */
+	/* 0x01ee - 0x01ef:	reserved */
+#define B3_PA_CTRL		0x01f0	/* 16 bit	Packet Arbiter Ctrl Register */
+#define B3_PA_TEST		0x01f2	/* 16 bit	Packet Arbiter Test Register */
+	/* 0x01f4 - 0x01ff:	reserved */
+
+/*
+ *	Bank 4 - 5
+ */
+/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+#define TXA_ITI_INI		0x0200	/* 32 bit	Tx Arb Interval Timer Init Val*/
+#define TXA_ITI_VAL		0x0204	/* 32 bit	Tx Arb Interval Timer Value */
+#define TXA_LIM_INI		0x0208	/* 32 bit	Tx Arb Limit Counter Init Val */
+#define TXA_LIM_VAL		0x020c	/* 32 bit	Tx Arb Limit Counter Value */
+#define TXA_CTRL		0x0210	/*  8 bit	Tx Arbiter Control Register */
+#define TXA_TEST		0x0211	/*  8 bit	Tx Arbiter Test Register */
+#define TXA_STAT		0x0212	/*  8 bit	Tx Arbiter Status Register */
+	/* 0x0213 - 0x021f:	reserved */
+
+	/* RSS key registers for Yukon-2 Family */
+#define B4_RSS_KEY		0x0220	/* 4x32 bit RSS Key register (Yukon-2) */
+	/* RSS key register offsets */
+#define KEY_IDX_0		 0		/* offset for location of KEY 0 */
+#define KEY_IDX_1		 4		/* offset for location of KEY 1 */
+#define KEY_IDX_2		 8		/* offset for location of KEY 2 */
+#define KEY_IDX_3		12		/* offset for location of KEY 3 */
+
+	/* 0x0280 - 0x0292:	MAC 2 */
+	/* 0x0213 - 0x027f:	reserved */
+
+/*
+ *	Bank 6
+ */
+/* External registers (GENESIS only) */
+#define B6_EXT_REG		0x0300
+
+/*
+ *	Bank 7
+ */
+/* This is a copy of the Configuration register file (lower half) */
+#define B7_CFG_SPC		0x0380
+
+/*
+ *	Bank 8 - 15
+ */
+/* Receive and Transmit Queue Registers, use Q_ADDR() to access */
+#define B8_Q_REGS		0x0400
+
+/* Queue Register Offsets, use Q_ADDR() to access */
+#define Q_D		0x00	/* 8*32	bit	Current Descriptor */
+#define Q_DA_L	0x20	/* 32 bit	Current Descriptor Address Low DWord */
+#define Q_DA_H	0x24	/* 32 bit	Current Descriptor Address High DWord */
+#define Q_AC_L	0x28	/* 32 bit	Current Address Counter Low DWord */
+#define Q_AC_H	0x2c	/* 32 bit	Current Address Counter High DWord */
+#define Q_BC	0x30	/* 32 bit	Current Byte Counter */
+#define Q_CSR	0x34	/* 32 bit	BMU Control/Status Register */
+#define Q_F		0x38	/* 32 bit	Flag Register */
+#define Q_T1	0x3c	/* 32 bit	Test Register 1 */
+#define Q_T1_TR	0x3c	/*  8 bit	Test Register 1 Transfer SM */
+#define Q_T1_WR	0x3d	/*  8 bit	Test Register 1 Write Descriptor SM */
+#define Q_T1_RD	0x3e	/*  8 bit	Test Register 1 Read Descriptor SM */
+#define Q_T1_SV	0x3f	/*  8 bit	Test Register 1 Supervisor SM */
+#define Q_T2	0x40	/* 32 bit	Test Register 2 */
+#define Q_T3	0x44	/* 32 bit	Test Register 3 */
+
+/* Yukon-2 */
+#define Q_DONE		0x24	/* 16 bit	Done Index */
+
+#define Q_WM		0x40	/* 16 bit	FIFO Watermark */
+#define Q_AL		0x42	/*  8 bit	FIFO Alignment */
+	/* 0x43:	reserved */
+/* RX Queue */
+#define Q_RX_RSP	0x44	/* 16 bit	FIFO Read Shadow Pointer */
+#define Q_RX_RSL	0x46	/*  8 bit	FIFO Read Shadow Level */
+	/* 0x47:	reserved */
+#define Q_RX_RP		0x48	/*  8 bit	FIFO Read Pointer */
+	/* 0x49:	reserved */
+#define Q_RX_RL		0x4a	/*  8 bit	FIFO Read Level */
+	/* 0x4b:	reserved */
+#define Q_RX_WP		0x4c	/*  8 bit	FIFO Write Pointer */
+#define Q_RX_WSP	0x4d	/*  8 bit	FIFO Write Shadow Pointer */
+#define Q_RX_WL		0x4e	/*  8 bit	FIFO Write Level */
+#define Q_RX_WSL	0x4f	/*  8 bit	FIFO Write Shadow Level */
+/* TX Queue */
+#define Q_TX_WSP	0x44	/* 16 bit	FIFO Write Shadow Pointer */
+#define Q_TX_WSL	0x46	/*  8 bit	FIFO Write Shadow Level */
+	/* 0x47:	reserved */
+#define Q_TX_WP		0x48	/*  8 bit	FIFO Write Pointer */
+	/* 0x49:	reserved */
+#define Q_TX_WL		0x4a	/*  8 bit	FIFO Write Level */
+	/* 0x4b:	reserved */
+#define Q_TX_RP		0x4c	/*  8 bit	FIFO Read Pointer */
+	/* 0x4d:	reserved */
+#define Q_TX_RL		0x4e	/*  8 bit	FIFO Read Level */
+	/* 0x4f:	reserved */
+
+	/* 0x48 - 0x7f:	reserved */
+
+/* Queue Prefetch Unit Offs, use Y2_PREF_Q_ADDR() to address (Yukon-2 only) */
+#define Y2_B8_PREF_REGS			0x0450
+
+#define PREF_UNIT_CTRL_REG		0x00	/* 32 bit	Prefetch Control register */
+#define PREF_UNIT_LAST_IDX_REG	0x04	/* 16 bit	Last Index */
+#define PREF_UNIT_ADDR_LOW_REG	0x08	/* 32 bit	List start addr, low part */
+#define PREF_UNIT_ADDR_HI_REG	0x0c	/* 32 bit	List start addr, high part*/
+#define PREF_UNIT_GET_IDX_REG	0x10	/* 16 bit	Get Index */
+#define PREF_UNIT_PUT_IDX_REG	0x14	/* 16 bit	Put Index */
+#define PREF_UNIT_FIFO_WP_REG	0x20	/*  8 bit	FIFO write pointer */
+#define PREF_UNIT_FIFO_RP_REG	0x24	/*  8 bit	FIFO read pointer */
+#define PREF_UNIT_FIFO_WM_REG	0x28	/*  8 bit	FIFO watermark */
+#define PREF_UNIT_FIFO_LEV_REG	0x2c	/*  8 bit	FIFO level */
+
+#define PREF_UNIT_MASK_IDX		0x0fff
+
+/*
+ *	Bank 16 - 23
+ */
+/* RAM Buffer Registers */
+#define B16_RAM_REGS	0x0800
+
+/* RAM Buffer Register Offsets, use RB_ADDR() to access */
+#define RB_START		0x00	/* 32 bit	RAM Buffer Start Address */
+#define RB_END			0x04	/* 32 bit	RAM Buffer End Address */
+#define RB_WP			0x08	/* 32 bit	RAM Buffer Write Pointer */
+#define RB_RP			0x0c	/* 32 bit	RAM Buffer Read Pointer */
+#define RB_RX_UTPP		0x10	/* 32 bit	Rx Upper Threshold, Pause Packet */
+#define RB_RX_LTPP		0x14	/* 32 bit	Rx Lower Threshold, Pause Packet */
+#define RB_RX_UTHP		0x18	/* 32 bit	Rx Upper Threshold, High Prio */
+#define RB_RX_LTHP		0x1c	/* 32 bit	Rx Lower Threshold, High Prio */
+	/* 0x10 - 0x1f:	reserved at Tx RAM Buffer Registers */
+#define RB_PC			0x20	/* 32 bit	RAM Buffer Packet Counter */
+#define RB_LEV			0x24	/* 32 bit	RAM Buffer Level Register */
+#define RB_CTRL			0x28	/* 32 bit	RAM Buffer Control Register */
+#define RB_TST1			0x29	/*  8 bit	RAM Buffer Test Register 1 */
+#define RB_TST2			0x2a	/*  8 bit	RAM Buffer Test Register 2 */
+	/* 0x2b - 0x7f:	reserved */
+
+/*
+ *	Bank 24
+ */
+/*
+ * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only)
+ * use MR_ADDR() to access
+ */
+#define RX_MFF_EA		0x0c00	/* 32 bit	Receive MAC FIFO End Address */
+#define RX_MFF_WP		0x0c04	/* 32 bit	Receive MAC FIFO Write Pointer */
+	/* 0x0c08 - 0x0c0b:	reserved */
+#define RX_MFF_RP		0x0c0c	/* 32 bit	Receive MAC FIFO Read Pointer */
+#define RX_MFF_PC		0x0c10	/* 32 bit	Receive MAC FIFO Packet Cnt */
+#define RX_MFF_LEV		0x0c14	/* 32 bit	Receive MAC FIFO Level */
+#define RX_MFF_CTRL1	0x0c18	/* 16 bit	Receive MAC FIFO Control Reg 1*/
+#define RX_MFF_STAT_TO	0x0c1a	/*  8 bit	Receive MAC Status Timeout */
+#define RX_MFF_TIST_TO	0x0c1b	/*  8 bit	Receive MAC Time Stamp Timeout */
+#define RX_MFF_CTRL2	0x0c1c	/*  8 bit	Receive MAC FIFO Control Reg 2*/
+#define RX_MFF_TST1		0x0c1d	/*  8 bit	Receive MAC FIFO Test Reg 1 */
+#define RX_MFF_TST2		0x0c1e	/*  8 bit	Receive MAC FIFO Test Reg 2 */
+	/* 0x0c1f:	reserved */
+#define RX_LED_INI		0x0c20	/* 32 bit	Receive LED Cnt Init Value */
+#define RX_LED_VAL		0x0c24	/* 32 bit	Receive LED Cnt Current Value */
+#define RX_LED_CTRL		0x0c28	/*  8 bit	Receive LED Cnt Control Reg */
+#define RX_LED_TST		0x0c29	/*  8 bit	Receive LED Cnt Test Register */
+	/* 0x0c2a - 0x0c2f:	reserved */
+#define LNK_SYNC_INI	0x0c30	/* 32 bit	Link Sync Cnt Init Value */
+#define LNK_SYNC_VAL	0x0c34	/* 32 bit	Link Sync Cnt Current Value */
+#define LNK_SYNC_CTRL	0x0c38	/*  8 bit	Link Sync Cnt Control Register */
+#define LNK_SYNC_TST	0x0c39	/*  8 bit	Link Sync Cnt Test Register */
+	/* 0x0c3a - 0x0c3b:	reserved */
+#define LNK_LED_REG		0x0c3c	/*  8 bit	Link LED Register */
+	/* 0x0c3d - 0x0c3f:	reserved */
+
+/* Receive GMAC FIFO (YUKON and Yukon-2), use MR_ADDR() to access */
+#define RX_GMF_EA		0x0c40	/* 32 bit	Rx GMAC FIFO End Address */
+#define RX_GMF_AF_THR	0x0c44	/* 32 bit	Rx GMAC FIFO Almost Full Thresh. */
+#define RX_GMF_CTRL_T	0x0c48	/* 32 bit	Rx GMAC FIFO Control/Test */
+#define RX_GMF_FL_MSK	0x0c4c	/* 32 bit	Rx GMAC FIFO Flush Mask */
+#define RX_GMF_FL_THR	0x0c50	/* 32 bit	Rx GMAC FIFO Flush Threshold */
+#define RX_GMF_TR_THR	0x0c54	/* 32 bit	Rx Truncation Threshold (Yukon-2) */
+#define RX_GMF_UP_THR	0x0c58	/* 16 bit	Rx Upper Pause Thr (Yukon-EC_U) */
+#define RX_GMF_LP_THR	0x0c5a	/* 16 bit	Rx Lower Pause Thr (Yukon-EC_U) */
+#define RX_GMF_VLAN		0x0c5c	/* 32 bit	Rx VLAN Type Register (Yukon-2) */
+#define RX_GMF_WP		0x0c60	/* 32 bit	Rx GMAC FIFO Write Pointer */
+	/* 0x0c64 - 0x0c67:	reserved */
+#define RX_GMF_WLEV		0x0c68	/* 32 bit	Rx GMAC FIFO Write Level */
+	/* 0x0c6c - 0x0c6f:	reserved */
+#define RX_GMF_RP		0x0c70	/* 32 bit	Rx GMAC FIFO Read Pointer */
+	/* 0x0c74 - 0x0c77:	reserved */
+#define RX_GMF_RLEV		0x0c78	/* 32 bit	Rx GMAC FIFO Read Level */
+	/* 0x0c7c - 0x0c7f:	reserved */
+
+/*
+ *	Bank 25
+ */
+	/* 0x0c80 - 0x0cbf:	MAC 2 */
+	/* 0x0cc0 - 0x0cff:	reserved */
+
+/*
+ *	Bank 26
+ */
+/*
+ * Transmit MAC FIFO and Transmit LED Registers (GENESIS only),
+ * use MR_ADDR() to access
+ */
+#define TX_MFF_EA		0x0d00	/* 32 bit	Transmit MAC FIFO End Address */
+#define TX_MFF_WP		0x0d04	/* 32 bit	Transmit MAC FIFO WR Pointer */
+#define TX_MFF_WSP		0x0d08	/* 32 bit	Transmit MAC FIFO WR Shadow Ptr */
+#define TX_MFF_RP		0x0d0c	/* 32 bit	Transmit MAC FIFO RD Pointer */
+#define TX_MFF_PC		0x0d10	/* 32 bit	Transmit MAC FIFO Packet Cnt */
+#define TX_MFF_LEV		0x0d14	/* 32 bit	Transmit MAC FIFO Level */
+#define TX_MFF_CTRL1	0x0d18	/* 16 bit	Transmit MAC FIFO Ctrl Reg 1 */
+#define TX_MFF_WAF		0x0d1a	/*  8 bit	Transmit MAC Wait after flush */
+	/* 0x0c1b:	reserved */
+#define TX_MFF_CTRL2	0x0d1c	/*  8 bit	Transmit MAC FIFO Ctrl Reg 2 */
+#define TX_MFF_TST1		0x0d1d	/*  8 bit	Transmit MAC FIFO Test Reg 1 */
+#define TX_MFF_TST2		0x0d1e	/*  8 bit	Transmit MAC FIFO Test Reg 2 */
+	/* 0x0d1f:	reserved */
+#define TX_LED_INI		0x0d20	/* 32 bit	Transmit LED Cnt Init Value */
+#define TX_LED_VAL		0x0d24	/* 32 bit	Transmit LED Cnt Current Val */
+#define TX_LED_CTRL		0x0d28	/*  8 bit	Transmit LED Cnt Control Reg */
+#define TX_LED_TST		0x0d29	/*  8 bit	Transmit LED Cnt Test Reg */
+	/* 0x0d2a - 0x0d3f:	reserved */
+
+/* Transmit GMAC FIFO (YUKON and Yukon-2), use MR_ADDR() to access */
+#define TX_GMF_EA		0x0d40	/* 32 bit	Tx GMAC FIFO End Address */
+#define TX_GMF_AE_THR	0x0d44	/* 32 bit	Tx GMAC FIFO Almost Empty Thresh. */
+#define TX_GMF_CTRL_T	0x0d48	/* 32 bit	Tx GMAC FIFO Control/Test */
+	/* 0x0d4c - 0x0d5b:	reserved */
+#define TX_GMF_VLAN		0x0d5c	/* 32 bit	Tx VLAN Type Register (Yukon-2) */
+#define TX_GMF_WP		0x0d60	/* 32 bit	Tx GMAC FIFO Write Pointer */
+#define TX_GMF_WSP		0x0d64	/* 32 bit	Tx GMAC FIFO Write Shadow Pointer */
+#define TX_GMF_WLEV		0x0d68	/* 32 bit	Tx GMAC FIFO Write Level */
+	/* 0x0d6c - 0x0d6f:	reserved */
+#define TX_GMF_RP		0x0d70	/* 32 bit	Tx GMAC FIFO Read Pointer */
+#define TX_GMF_RSTP		0x0d74	/* 32 bit	Tx GMAC FIFO Restart Pointer */
+#define TX_GMF_RLEV		0x0d78	/* 32 bit	Tx GMAC FIFO Read Level */
+	/* 0x0d7c - 0x0d7f:	reserved */
+
+/*
+ *	Bank 27
+ */
+	/* 0x0d80 - 0x0dbf:	MAC 2 */
+	/* 0x0daa - 0x0dff:	reserved */
+
+/*
+ *	Bank 28
+ */
+/* Descriptor Poll Timer Registers */
+#define B28_DPT_INI		0x0e00	/* 24 bit	Descriptor Poll Timer Init Val */
+#define B28_DPT_VAL		0x0e04	/* 24 bit	Descriptor Poll Timer Curr Val */
+#define B28_DPT_CTRL	0x0e08	/*  8 bit	Descriptor Poll Timer Ctrl Reg */
+	/* 0x0e09:	reserved */
+#define B28_DPT_TST		0x0e0a	/*  8 bit	Descriptor Poll Timer Test Reg */
+	/* 0x0e0b:	reserved */
+
+/* Time Stamp Timer Registers (YUKON only) */
+	/* 0x0e10:	reserved */
+#define GMAC_TI_ST_VAL	0x0e14	/* 32 bit	Time Stamp Timer Curr Val */
+#define GMAC_TI_ST_CTRL	0x0e18	/*  8 bit	Time Stamp Timer Ctrl Reg */
+	/* 0x0e19:	reserved */
+#define GMAC_TI_ST_TST	0x0e1a	/*  8 bit	Time Stamp Timer Test Reg */
+	/* 0x0e1b - 0x0e1f:	reserved */
+
+/* Polling Unit Registers (Yukon-2 only) */
+#define POLL_CTRL			0x0e20	/* 32 bit	Polling Unit Control Reg */
+#define POLL_LAST_IDX		0x0e24	/* 16 bit	Polling Unit List Last Index */
+	/* 0x0e26 - 0x0e27:	reserved */
+#define POLL_LIST_ADDR_LO	0x0e28	/* 32 bit	Poll. List Start Addr (low) */
+#define POLL_LIST_ADDR_HI	0x0e2c	/* 32 bit	Poll. List Start Addr (high) */
+	/* 0x0e30 - 0x0e3f:	reserved */
+
+/* ASF Subsystem Registers (Yukon-2 only) */
+#define B28_Y2_SMB_CONFIG	0x0e40	/* 32 bit	ASF SMBus Config Register */
+#define B28_Y2_SMB_CSD_REG	0x0e44	/* 32 bit	ASF SMB Control/Status/Data */
+	/* 0x0e48 - 0x0e5f: reserved */
+#define B28_Y2_ASF_IRQ_V_BASE	0x0e60	/* 32 bit	ASF IRQ Vector Base */
+	/* 0x0e64 - 0x0e67: reserved */
+#define B28_Y2_ASF_STAT_CMD	0x0e68	/* 32 bit	ASF Status and Command Reg */
+#define B28_Y2_ASF_HOST_COM	0x0e6c	/* 32 bit	ASF Host Communication Reg */
+#define B28_Y2_DATA_REG_1	0x0e70	/* 32 bit	ASF/Host Data Register 1 */
+#define B28_Y2_DATA_REG_2	0x0e74	/* 32 bit	ASF/Host Data Register 2 */
+#define B28_Y2_DATA_REG_3	0x0e78	/* 32 bit	ASF/Host Data Register 3 */
+#define B28_Y2_DATA_REG_4	0x0e7c	/* 32 bit	ASF/Host Data Register 4 */
+
+/*
+ *	Bank 29
+ */
+/* Status BMU Registers (Yukon-2 only) */
+#define STAT_CTRL			0x0e80	/* 32 bit	Status BMU Control Reg */
+#define STAT_LAST_IDX		0x0e84	/* 16 bit	Status BMU Last Index */
+	/* 0x0e85 - 0x0e86:	reserved */
+#define STAT_LIST_ADDR_LO	0x0e88	/* 32 bit	Status List Start Addr (low) */
+#define STAT_LIST_ADDR_HI	0x0e8c	/* 32 bit	Status List Start Addr (high) */
+#define STAT_TXA1_RIDX		0x0e90	/* 16 bit	Status TxA1 Report Index Reg */
+#define STAT_TXS1_RIDX		0x0e92	/* 16 bit	Status TxS1 Report Index Reg */
+#define STAT_TXA2_RIDX		0x0e94	/* 16 bit	Status TxA2 Report Index Reg */
+#define STAT_TXS2_RIDX		0x0e96	/* 16 bit	Status TxS2 Report Index Reg */
+#define STAT_TX_IDX_TH		0x0e98	/* 16 bit	Status Tx Index Threshold Reg */
+	/* 0x0e9a - 0x0e9b:	reserved */
+#define STAT_PUT_IDX		0x0e9c	/* 16 bit	Status Put Index Reg */
+	/* 0x0e9e - 0x0e9f:	reserved */
+
+/* FIFO Control/Status Registers (Yukon-2 only) */
+#define STAT_FIFO_WP		0x0ea0	/*  8 bit	Status FIFO Write Pointer Reg */
+	/* 0x0ea1 - 0x0ea3:	reserved */
+#define STAT_FIFO_RP		0x0ea4	/*  8 bit	Status FIFO Read Pointer Reg */
+	/* 0x0ea5:	reserved */
+#define STAT_FIFO_RSP		0x0ea6	/*  8 bit	Status FIFO Read Shadow Ptr */
+	/* 0x0ea7:	reserved */
+#define STAT_FIFO_LEVEL		0x0ea8	/*  8 bit	Status FIFO Level Reg */
+	/* 0x0ea9:	reserved */
+#define STAT_FIFO_SHLVL		0x0eaa	/*  8 bit	Status FIFO Shadow Level Reg */
+	/* 0x0eab:	reserved */
+#define STAT_FIFO_WM		0x0eac	/*  8 bit	Status FIFO Watermark Reg */
+#define STAT_FIFO_ISR_WM	0x0ead	/*  8 bit	Status FIFO ISR Watermark Reg */
+	/* 0x0eae - 0x0eaf:	reserved */
+
+/* Level and ISR Timer Registers (Yukon-2 only) */
+#define STAT_LEV_TIMER_INI	0x0eb0	/* 32 bit	Level Timer Init. Value Reg */
+#define STAT_LEV_TIMER_CNT	0x0eb4	/* 32 bit	Level Timer Counter Reg */
+#define STAT_LEV_TIMER_CTRL	0x0eb8	/*  8 bit	Level Timer Control Reg */
+#define STAT_LEV_TIMER_TEST	0x0eb9	/*  8 bit	Level Timer Test Reg */
+	/* 0x0eba - 0x0ebf:	reserved */
+#define STAT_TX_TIMER_INI	0x0ec0	/* 32 bit	Tx Timer Init. Value Reg */
+#define STAT_TX_TIMER_CNT	0x0ec4	/* 32 bit	Tx Timer Counter Reg */
+#define STAT_TX_TIMER_CTRL	0x0ec8	/*  8 bit	Tx Timer Control Reg */
+#define STAT_TX_TIMER_TEST	0x0ec9	/*  8 bit	Tx Timer Test Reg */
+	/* 0x0eca - 0x0ecf:	reserved */
+#define STAT_ISR_TIMER_INI	0x0ed0	/* 32 bit	ISR Timer Init. Value Reg */
+#define STAT_ISR_TIMER_CNT	0x0ed4	/* 32 bit	ISR Timer Counter Reg */
+#define STAT_ISR_TIMER_CTRL	0x0ed8	/*  8 bit	ISR Timer Control Reg */
+#define STAT_ISR_TIMER_TEST	0x0ed9	/*  8 bit	ISR Timer Test Reg */
+	/* 0x0eda - 0x0eff:	reserved */
+
+#define ST_LAST_IDX_MASK	0x007f	/* Last Index Mask */
+#define ST_TXRP_IDX_MASK	0x0fff	/* Tx Report Index Mask */
+#define ST_TXTH_IDX_MASK	0x0fff	/* Tx Threshold Index Mask */
+#define ST_WM_IDX_MASK		0x3f	/* FIFO Watermark Index Mask */
+
+/*
+ *	Bank 30
+ */
+/* GMAC and GPHY Control Registers (YUKON only) */
+#define GMAC_CTRL		0x0f00	/* 32 bit	GMAC Control Reg */
+#define GPHY_CTRL		0x0f04	/* 32 bit	GPHY Control Reg */
+#define GMAC_IRQ_SRC	0x0f08	/*  8 bit	GMAC Interrupt Source Reg */
+	/* 0x0f09 - 0x0f0b:	reserved */
+#define GMAC_IRQ_MSK	0x0f0c	/*  8 bit	GMAC Interrupt Mask Reg */
+	/* 0x0f0d - 0x0f0f:	reserved */
+#define GMAC_LINK_CTRL	0x0f10	/* 16 bit	Link Control Reg */
+	/* 0x0f14 - 0x0f1f:	reserved */
+
+/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+
+#define WOL_REG_OFFS	0x20	/* HW-Bug: Address is + 0x20 against spec. */
+
+#define WOL_CTRL_STAT	0x0f20	/* 16 bit	WOL Control/Status Reg */
+#define WOL_MATCH_CTL	0x0f22	/*  8 bit	WOL Match Control Reg */
+#define WOL_MATCH_RES	0x0f23	/*  8 bit	WOL Match Result Reg */
+#define WOL_MAC_ADDR_LO	0x0f24	/* 32 bit	WOL MAC Address Low */
+#define WOL_MAC_ADDR_HI	0x0f28	/* 16 bit	WOL MAC Address High */
+#define WOL_PATT_PME	0x0f2a	/*  8 bit	WOL PME Match Enable (Yukon-2) */
+#define WOL_PATT_ASFM	0x0f2b	/*  8 bit	WOL ASF Match Enable (Yukon-2) */
+#define WOL_PATT_RPTR	0x0f2c	/*  8 bit	WOL Pattern Read Pointer */
+
+/* WOL Pattern Length Registers (YUKON only) */
+
+#define WOL_PATT_LEN_LO	0x0f30		/* 32 bit	WOL Pattern Length 3..0 */
+#define WOL_PATT_LEN_HI	0x0f34		/* 24 bit	WOL Pattern Length 6..4 */
+
+/* WOL Pattern Counter Registers (YUKON only) */
+
+#define WOL_PATT_CNT_0	0x0f38		/* 32 bit	WOL Pattern Counter 3..0 */
+#define WOL_PATT_CNT_4	0x0f3c		/* 24 bit	WOL Pattern Counter 6..4 */
+	/* 0x0f40 - 0x0f7f:	reserved */
+
+/*
+ *	Bank 31
+ */
+/* 0x0f80 - 0x0fff:	reserved */
+
+/* WOL registers link 2 */
+
+/* use this macro to access WOL registers */
+#define WOL_REG(Port, Reg)	((Reg) + ((Port)*0x80) + (pAC->GIni.GIWolOffs))
+
+/*
+ *	Bank 32	- 33
+ */
+#define WOL_PATT_RAM_1	0x1000	/*  WOL Pattern RAM Link 1 */
+#define WOL_PATT_RAM_2	0x1400	/*  WOL Pattern RAM Link 2 */
+
+/* use this macro to retrieve the pattern RAM base address */
+#define WOL_PATT_RAM_BASE(Port) (WOL_PATT_RAM_1 + (Port)*0x400)
+
+/* offset to configuration space on Yukon-2 */
+#define Y2_CFG_SPC 		0x1c00
+/*
+ *	Bank 0x22 - 0x3f
+ */
+/* 0x1100 - 0x1fff:	reserved */
+
+/*
+ *	Bank 0x40 - 0x4f
+ */
+#define BASE_XMAC_1		0x2000	/* XMAC 1 registers */
+
+/*
+ *	Bank 0x50 - 0x5f
+ */
+#define BASE_GMAC_1		0x2800	/* GMAC 1 registers */
+
+/*
+ *	Bank 0x60 - 0x6f
+ */
+#define BASE_XMAC_2		0x3000	/* XMAC 2 registers */
+
+/*
+ *	Bank 0x70 - 0x7f
+ */
+#define BASE_GMAC_2		0x3800	/* GMAC 2 registers */
+
+/*
+ *	Control Register Bit Definitions:
+ */
+/*	B0_RAP		8 bit	Register Address Port */
+								/* Bit 7:	reserved */
+#define RAP_MSK			0x7f	/* Bit 6..0:	0 = block 0,..,6f = block 6f */
+
+/*	B0_CTST			24 bit	Control/Status register */
+								/* Bit 23..18:	reserved */
+#define Y2_VMAIN_AVAIL	BIT_17		/* VMAIN available (YUKON-2 only) */
+#define Y2_VAUX_AVAIL	BIT_16		/* VAUX available (YUKON-2 only) */
+#define Y2_HW_WOL_ON	BIT_15S		/* HW WOL On  (Yukon-EC Ultra A1 only) */
+#define Y2_HW_WOL_OFF	BIT_14S		/* HW WOL Off (Yukon-EC Ultra A1 only) */
+#define Y2_ASF_ENABLE	BIT_13S		/* ASF Unit Enable (YUKON-2 only) */
+#define Y2_ASF_DISABLE	BIT_12S		/* ASF Unit Disable (YUKON-2 only) */
+#define Y2_CLK_RUN_ENA	BIT_11S		/* CLK_RUN Enable  (YUKON-2 only) */
+#define Y2_CLK_RUN_DIS	BIT_10S		/* CLK_RUN Disable (YUKON-2 only) */
+#define Y2_LED_STAT_ON	BIT_9S		/* Status LED On  (YUKON-2 only) */
+#define Y2_LED_STAT_OFF	BIT_8S		/* Status LED Off (YUKON-2 only) */
+								/* Bit  7.. 0:	same as below */
+
+/*	B0_CTST			16 bit	Control/Status register */
+								/* Bit 15..14:	reserved */
+#define CS_CLK_RUN_HOT	BIT_13S		/* CLK_RUN Hot m. (YUKON-Lite only) */
+#define CS_CLK_RUN_RST	BIT_12S		/* CLK_RUN Reset  (YUKON-Lite only) */
+#define CS_CLK_RUN_ENA	BIT_11S		/* CLK_RUN Enable (YUKON-Lite only) */
+#define CS_VAUX_AVAIL	BIT_10S		/* VAUX available (YUKON only) */
+#define CS_BUS_CLOCK	BIT_9S		/* Bus Clock 0/1 = 33/66 MHz */
+#define CS_BUS_SLOT_SZ	BIT_8S		/* Slot Size 0/1 = 32/64 bit slot */
+#define CS_ST_SW_IRQ	BIT_7S		/* Set IRQ SW Request */
+#define CS_CL_SW_IRQ	BIT_6S		/* Clear IRQ SW Request */
+#define CS_STOP_DONE	BIT_5S		/* Stop Master is finished */
+#define CS_STOP_MAST	BIT_4S		/* Command Bit to stop the master */
+#define CS_MRST_CLR		BIT_3S		/* Clear Master Reset */
+#define CS_MRST_SET		BIT_2S		/* Set   Master Reset */
+#define CS_RST_CLR		BIT_1S		/* Clear Software Reset */
+#define CS_RST_SET		BIT_0S		/* Set   Software Reset */
+
+/*	B0_LED			 8 Bit	LED register (GENESIS only) */
+								/* Bit  7.. 2:	reserved */
+#define LED_STAT_ON		BIT_1S		/* Status LED On */
+#define LED_STAT_OFF	BIT_0S		/* Status LED Off */
+
+/*	B0_POWER_CTRL	 8 Bit	Power Control reg (YUKON only) */
+#define PC_VAUX_ENA		BIT_7		/* Switch VAUX Enable  */
+#define PC_VAUX_DIS		BIT_6		/* Switch VAUX Disable */
+#define PC_VCC_ENA		BIT_5		/* Switch VCC Enable  */
+#define PC_VCC_DIS		BIT_4		/* Switch VCC Disable */
+#define PC_VAUX_ON		BIT_3		/* Switch VAUX On  */
+#define PC_VAUX_OFF		BIT_2		/* Switch VAUX Off */
+#define PC_VCC_ON		BIT_1		/* Switch VCC On  */
+#define PC_VCC_OFF		BIT_0		/* Switch VCC Off */
+
+/* Yukon and Genesis */
+/*	B0_ISRC			32 bit	Interrupt Source Register */
+/*	B0_IMSK			32 bit	Interrupt Mask Register */
+/*	B0_SP_ISRC		32 bit	Special Interrupt Source Reg */
+/*	B2_IRQM_MSK 	32 bit	IRQ Moderation Mask */
+#define IS_ALL_MSK		0xbfffffffUL	/* All Interrupt bits */
+#define IS_HW_ERR		BIT_31		/* Interrupt HW Error */
+								/* Bit 30:	reserved */
+#define IS_PA_TO_RX1	BIT_29		/* Packet Arb Timeout Rx1 */
+#define IS_PA_TO_RX2	BIT_28		/* Packet Arb Timeout Rx2 */
+#define IS_PA_TO_TX1	BIT_27		/* Packet Arb Timeout Tx1 */
+#define IS_PA_TO_TX2	BIT_26		/* Packet Arb Timeout Tx2 */
+#define IS_I2C_READY	BIT_25		/* IRQ on end of I2C Tx */
+#define IS_IRQ_SW		BIT_24		/* SW forced IRQ */
+#define IS_EXT_REG		BIT_23		/* IRQ from LM80 or PHY (GENESIS only) */
+									/* IRQ from PHY (YUKON only) */
+#define IS_TIMINT		BIT_22		/* IRQ from Timer */
+#define IS_MAC1			BIT_21		/* IRQ from MAC 1 */
+#define IS_LNK_SYNC_M1	BIT_20		/* Link Sync Cnt wrap MAC 1 */
+#define IS_MAC2			BIT_19		/* IRQ from MAC 2 */
+#define IS_LNK_SYNC_M2	BIT_18		/* Link Sync Cnt wrap MAC 2 */
+/* Receive Queue 1 */
+#define IS_R1_B			BIT_17		/* Q_R1 End of Buffer */
+#define IS_R1_F			BIT_16		/* Q_R1 End of Frame */
+#define IS_R1_C			BIT_15		/* Q_R1 Encoding Error */
+/* Receive Queue 2 */
+#define IS_R2_B			BIT_14		/* Q_R2 End of Buffer */
+#define IS_R2_F			BIT_13		/* Q_R2 End of Frame */
+#define IS_R2_C			BIT_12		/* Q_R2 Encoding Error */
+/* Synchronous Transmit Queue 1 */
+#define IS_XS1_B		BIT_11		/* Q_XS1 End of Buffer */
+#define IS_XS1_F		BIT_10		/* Q_XS1 End of Frame */
+#define IS_XS1_C		BIT_9		/* Q_XS1 Encoding Error */
+/* Asynchronous Transmit Queue 1 */
+#define IS_XA1_B		BIT_8		/* Q_XA1 End of Buffer */
+#define IS_XA1_F		BIT_7		/* Q_XA1 End of Frame */
+#define IS_XA1_C		BIT_6		/* Q_XA1 Encoding Error */
+/* Synchronous Transmit Queue 2 */
+#define IS_XS2_B		BIT_5		/* Q_XS2 End of Buffer */
+#define IS_XS2_F		BIT_4		/* Q_XS2 End of Frame */
+#define IS_XS2_C		BIT_3		/* Q_XS2 Encoding Error */
+/* Asynchronous Transmit Queue 2 */
+#define IS_XA2_B		BIT_2		/* Q_XA2 End of Buffer */
+#define IS_XA2_F		BIT_1		/* Q_XA2 End of Frame */
+#define IS_XA2_C		BIT_0		/* Q_XA2 Encoding Error */
+
+/* Yukon-2 */
+/*	B0_ISRC			32 bit	Interrupt Source Register */
+/*	B0_IMSK			32 bit	Interrupt Mask Register */
+/*	B0_SP_ISRC		32 bit	Special Interrupt Source Reg */
+/*	B2_IRQM_MSK		32 bit	IRQ Moderation Mask */
+/*	B0_Y2_SP_ISRC2	32 bit	Special Interrupt Source Reg 2 */
+/*	B0_Y2_SP_ISRC3	32 bit	Special Interrupt Source Reg 3 */
+/*	B0_Y2_SP_EISR	32 bit	Enter ISR Reg */
+/*	B0_Y2_SP_LISR	32 bit	Leave ISR Reg */
+#define Y2_IS_PORT_MASK(Port, Mask)	((Mask) << (Port*8))
+#define Y2_IS_HW_ERR	BIT_31		/* Interrupt HW Error */
+#define Y2_IS_STAT_BMU	BIT_30		/* Status BMU Interrupt */
+#define Y2_IS_ASF		BIT_29		/* ASF subsystem Interrupt */
+							/* Bit 28: reserved */
+#define Y2_IS_POLL_CHK	BIT_27		/* Check IRQ from polling unit */
+#define Y2_IS_TWSI_RDY	BIT_26		/* IRQ on end of TWSI Tx */
+#define Y2_IS_IRQ_SW	BIT_25		/* SW forced IRQ */
+#define Y2_IS_TIMINT	BIT_24		/* IRQ from Timer */
+							/* Bit 23..16 reserved */
+						/* Link 2 Interrupts */
+#define Y2_IS_IRQ_PHY2	BIT_12		/* Interrupt from PHY 2 */
+#define Y2_IS_IRQ_MAC2	BIT_11		/* Interrupt from MAC 2 */
+#define Y2_IS_CHK_RX2	BIT_10		/* Descriptor error Rx 2 */
+#define Y2_IS_CHK_TXS2	BIT_9		/* Descriptor error TXS 2 */
+#define Y2_IS_CHK_TXA2	BIT_8		/* Descriptor error TXA 2 */
+							/* Bit  7.. 5 reserved */
+						/* Link 1 interrupts */
+#define Y2_IS_IRQ_PHY1	BIT_4		/* Interrupt from PHY 1 */
+#define Y2_IS_IRQ_MAC1	BIT_3		/* Interrupt from MAC 1 */
+#define Y2_IS_CHK_RX1	BIT_2		/* Descriptor error Rx 1 */
+#define Y2_IS_CHK_TXS1	BIT_1		/* Descriptor error TXS 1 */
+#define Y2_IS_CHK_TXA1	BIT_0		/* Descriptor error TXA 1 */
+
+						/* IRQ Mask for port 1 */
+#define Y2_IS_L1_MASK	(Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1 | Y2_IS_CHK_RX1 |\
+						 Y2_IS_CHK_TXS1 | Y2_IS_CHK_TXA1)
+
+						/* IRQ Mask for port 2 */
+#define Y2_IS_L2_MASK	(Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2 | Y2_IS_CHK_RX2 |\
+						 Y2_IS_CHK_TXS2 | Y2_IS_CHK_TXA2)
+
+						/* All Interrupt bits */
+#define Y2_IS_ALL_MSK	(Y2_IS_HW_ERR | Y2_IS_STAT_BMU | Y2_IS_ASF |\
+						 Y2_IS_POLL_CHK | Y2_IS_TWSI_RDY | Y2_IS_IRQ_SW |\
+						 Y2_IS_TIMINT | Y2_IS_L1_MASK | Y2_IS_L2_MASK)
+
+/*	B0_Y2_SP_ICR	32 bit	Interrupt Control Register */
+							/* Bit 31.. 4:	reserved */
+#define Y2_IC_ISR_MASK	BIT_3		/* ISR mask flag */
+#define Y2_IC_ISR_STAT	BIT_2		/* ISR status flag */
+#define Y2_IC_LEAVE_ISR	BIT_1		/* Leave ISR */
+#define Y2_IC_ENTER_ISR	BIT_0		/* Enter ISR */
+
+/* Yukon and Genesis */
+/*	B0_HWE_ISRC		32 bit	HW Error Interrupt Src Reg */
+/*	B0_HWE_IMSK		32 bit	HW Error Interrupt Mask Reg */
+/*	B2_IRQM_HWE_MSK	32 bit	IRQ Moderation HW Error Mask */
+#define IS_ERR_MSK		0x00000fffL	/* 		All Error bits */
+							/* Bit 31..14:	reserved */
+#define IS_IRQ_TIST_OV	BIT_13	/* Time Stamp Timer Overflow (YUKON only) */
+#define IS_IRQ_SENSOR	BIT_12	/* IRQ from Sensor (YUKON only) */
+#define IS_IRQ_MST_ERR	BIT_11	/* IRQ master error detected */
+#define IS_IRQ_STAT		BIT_10	/* IRQ status exception */
+#define IS_NO_STAT_M1	BIT_9	/* No Rx Status from MAC 1 */
+#define IS_NO_STAT_M2	BIT_8	/* No Rx Status from MAC 2 */
+#define IS_NO_TIST_M1	BIT_7	/* No Time Stamp from MAC 1 */
+#define IS_NO_TIST_M2	BIT_6	/* No Time Stamp from MAC 2 */
+#define IS_RAM_RD_PAR	BIT_5	/* RAM Read  Parity Error */
+#define IS_RAM_WR_PAR	BIT_4	/* RAM Write Parity Error */
+#define IS_M1_PAR_ERR	BIT_3	/* MAC 1 Parity Error */
+#define IS_M2_PAR_ERR	BIT_2	/* MAC 2 Parity Error */
+#define IS_R1_PAR_ERR	BIT_1	/* Queue R1 Parity Error */
+#define IS_R2_PAR_ERR	BIT_0	/* Queue R2 Parity Error */
+
+/* Yukon-2 */
+/*	B0_HWE_ISRC		32 bit	HW Error Interrupt Src Reg */
+/*	B0_HWE_IMSK		32 bit	HW Error Interrupt Mask Reg */
+/*	B2_IRQM_HWE_MSK	32 bit	IRQ Moderation HW Error Mask */
+						/* Bit: 31..30 reserved */
+#define Y2_IS_TIST_OV	BIT_29	/* Time Stamp Timer overflow interrupt */
+#define Y2_IS_SENSOR	BIT_28	/* Sensor interrupt */
+#define Y2_IS_MST_ERR	BIT_27	/* Master error interrupt */
+#define Y2_IS_IRQ_STAT	BIT_26	/* Status exception interrupt */
+#define Y2_IS_PCI_EXP	BIT_25	/* PCI-Express interrupt */
+#define Y2_IS_PCI_NEXP	BIT_24	/* Bus Abort detected */
+						/* Bit: 23..14 reserved */
+						/* Link 2 */
+#define Y2_IS_PAR_RD2	BIT_13	/* Read RAM parity error interrupt */
+#define Y2_IS_PAR_WR2	BIT_12	/* Write RAM parity error interrupt */
+#define Y2_IS_PAR_MAC2	BIT_11	/* MAC hardware fault interrupt */
+#define Y2_IS_PAR_RX2	BIT_10	/* Parity Error Rx Queue 2 */
+#define Y2_IS_TCP_TXS2	BIT_9	/* TCP length mismatch sync Tx queue IRQ */
+#define Y2_IS_TCP_TXA2	BIT_8	/* TCP length mismatch async Tx queue IRQ */
+						/* Bit:  9.. 6 reserved */
+						/* Link 1 */
+#define Y2_IS_PAR_RD1	BIT_5	/* Read RAM parity error interrupt */
+#define Y2_IS_PAR_WR1	BIT_4	/* Write RAM parity error interrupt */
+#define Y2_IS_PAR_MAC1	BIT_3	/* MAC hardware fault interrupt */
+#define Y2_IS_PAR_RX1	BIT_2	/* Parity Error Rx Queue 1 */
+#define Y2_IS_TCP_TXS1	BIT_1	/* TCP length mismatch sync Tx queue IRQ */
+#define Y2_IS_TCP_TXA1	BIT_0	/* TCP length mismatch async Tx queue IRQ */
+
+#define Y2_HWE_L1_MASK	(Y2_IS_PAR_RD1 | Y2_IS_PAR_WR1 | Y2_IS_PAR_MAC1 |\
+						 Y2_IS_PAR_RX1 | Y2_IS_TCP_TXS1| Y2_IS_TCP_TXA1)
+#define Y2_HWE_L2_MASK	(Y2_IS_PAR_RD2 | Y2_IS_PAR_WR2 | Y2_IS_PAR_MAC2 |\
+						 Y2_IS_PAR_RX2 | Y2_IS_TCP_TXS2| Y2_IS_TCP_TXA2)
+
+#define Y2_HWE_ALL_MSK	(Y2_IS_TIST_OV | /* Y2_IS_SENSOR | */ Y2_IS_MST_ERR |\
+						 Y2_IS_IRQ_STAT | Y2_IS_PCI_EXP |\
+						 Y2_HWE_L1_MASK | Y2_HWE_L2_MASK)
+
+/*	B2_CONN_TYP		 8 bit	Connector type */
+/*	B2_PMD_TYP		 8 bit	PMD type */
+/*	Values of connector and PMD type comply to SysKonnect internal std */
+
+/*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
+#define CFG_CHIP_R_MSK	(0xf<<4)	/* Bit 7.. 4: Chip Revision */
+									/* Bit 3.. 2:	reserved */
+#define CFG_DIS_M2_CLK	BIT_1S		/* Disable Clock for 2nd MAC */
+#define CFG_SNG_MAC		BIT_0S		/* MAC Config: 0 = 2 MACs; 1 = 1 MAC */
+
+/*	B2_CHIP_ID		 8 bit	Chip Identification Number */
+#define CHIP_ID_GENESIS		0x0a	/* Chip ID for GENESIS */
+#define CHIP_ID_YUKON		0xb0	/* Chip ID for YUKON */
+#define CHIP_ID_YUKON_LITE	0xb1	/* Chip ID for YUKON-Lite (Rev. A1-A3) */
+#define CHIP_ID_YUKON_LP	0xb2	/* Chip ID for YUKON-LP */
+#define CHIP_ID_YUKON_XL	0xb3	/* Chip ID for YUKON-2 XL */
+#define CHIP_ID_YUKON_EC_U	0xb4	/* Chip ID for YUKON-2 EC Ultra */
+#define CHIP_ID_YUKON_EX	0xb5	/* Chip ID for YUKON-2 Extreme */
+#define CHIP_ID_YUKON_EC	0xb6	/* Chip ID for YUKON-2 EC */
+#define CHIP_ID_YUKON_FE	0xb7	/* Chip ID for YUKON-2 FE */
+#define CHIP_ID_YUKON_FE_P	0xb8	/* Chip ID for YUKON-2 FE+ */
+
+#define CHIP_REV_YU_LITE_A1	3		/* Chip Rev. for YUKON-Lite A1,A2 */
+#define CHIP_REV_YU_LITE_A3	7		/* Chip Rev. for YUKON-Lite A3 */
+
+#define CHIP_REV_YU_XL_A0	0		/* Chip Rev. for Yukon-2 A0 */
+#define CHIP_REV_YU_XL_A1	1		/* Chip Rev. for Yukon-2 A1 */
+#define CHIP_REV_YU_XL_A2	2		/* Chip Rev. for Yukon-2 A2 */
+#define CHIP_REV_YU_XL_A3	3		/* Chip Rev. for Yukon-2 A3 */
+
+#define CHIP_REV_YU_EC_A1	0		/* Chip Rev. for Yukon-EC A0,A1 */
+#define CHIP_REV_YU_EC_A2	1		/* Chip Rev. for Yukon-EC A2 */
+#define CHIP_REV_YU_EC_A3	2		/* Chip Rev. for Yukon-EC A3 */
+
+#define CHIP_REV_YU_EC_U_A0	1		/* Chip Rev. for Yukon-EC Ultra A0 */
+#define CHIP_REV_YU_EC_U_A1	2		/* Chip Rev. for Yukon-EC Ultra A1 */
+#define CHIP_REV_YU_EC_U_B0	3		/* Chip Rev. for Yukon-EC Ultra B0 */
+#define CHIP_REV_YU_EC_U_B1	5		/* Chip Rev. for Yukon-EC Ultra B1 */
+
+#define CHIP_REV_YU_FE_A1	1		/* Chip Rev. for Yukon-FE A1 */
+#define CHIP_REV_YU_FE_A2	3		/* Chip Rev. for Yukon-FE A2 */
+
+#define CHIP_REV_YU_FE2_A0	0		/* Chip Rev. for Yukon-FE+ A0 */
+
+#define CHIP_REV_YU_EX_A0	1		/* Chip Rev. for Yukon-Extreme A0 */
+#define CHIP_REV_YU_EX_B0	2		/* Chip Rev. for Yukon-Extreme B0 */
+
+/*	B2_Y2_CLK_GATE	 8 bit	Clock Gating (Yukon-2 only) */
+#define Y2_STATUS_LNK2_INAC	BIT_7S	/* Status Link 2 inactiv (0 = activ) */
+#define Y2_CLK_GAT_LNK2_DIS	BIT_6S	/* Disable PHY clock for Link 2 */
+#define Y2_COR_CLK_LNK2_DIS	BIT_5S	/* Disable Core clock Link 2 */
+#define Y2_PCI_CLK_LNK2_DIS	BIT_4S	/* Disable PCI clock Link 2 */
+#define Y2_STATUS_LNK1_INAC	BIT_3S	/* Status Link 1 inactiv (0 = activ) */
+#define Y2_CLK_GAT_LNK1_DIS	BIT_2S	/* Disable PHY clock for Link 1 */
+#define Y2_COR_CLK_LNK1_DIS	BIT_1S	/* Disable Core clock Link 1 */
+#define Y2_PCI_CLK_LNK1_DIS	BIT_0S	/* Disable PCI clock Link 1 */
+
+/*	B2_Y2_HW_RES	8 bit	HW Resources (Yukon-2 only) */
+								/* Bit 7.. 6:	reserved */
+#define CFG_PEX_PME_NATIVE	BIT_5S	/* PCI-E PME native mode select */
+#define CFG_LED_MODE_MSK	(7<<2)	/* Bit  4.. 2:	LED Mode Mask */
+#define CFG_LINK_2_AVAIL	BIT_1S	/* Link 2 available */
+#define CFG_LINK_1_AVAIL	BIT_0S	/* Link 1 available */
+
+#define CFG_LED_MODE(x)		(((x) & CFG_LED_MODE_MSK) >> 2)
+#define CFG_DUAL_MAC_MSK	(CFG_LINK_2_AVAIL | CFG_LINK_1_AVAIL)
+
+#define CFG_LED_DUAL_ACT_LNK	1	/* Dual LED ACT/LNK mode */
+#define CFG_LED_LINK_MUX_P60	2	/* Link LED on pin 60 (Yukon-EC Ultra) */
+#define CFG_LED_ACT_OFF_NOTR	4	/* Activity LED off (no traffic) */
+#define CFG_LED_COMB_ACT_LNK	5	/* Combined ACT/LNK mode */
+
+/*	B2_E_3			 8 bit	lower 4 bits used for HW self test result */
+#define B2_E3_RES_MASK	0x0f
+
+/*	B2_FAR			32 bit	Flash-Prom Addr Reg/Cnt */
+#define FAR_ADDR		0x1ffffL	/* Bit 16.. 0:	FPROM Address Mask */
+
+/*	B2_Y2_CLK_CTRL	32 bit	Core Clock Frequency Control Register (Yukon-2/EC) */
+								/* Bit 31..24:	reserved */
+/* Yukon-EC/FE */
+#define Y2_CLK_DIV_VAL_MSK	(0xffL<<16)	/* Bit 23..16:	Clock Divisor Value */
+#define Y2_CLK_DIV_VAL(x)	(SHIFT16(x) & Y2_CLK_DIV_VAL_MSK)
+/* Yukon-2 */
+#define Y2_CLK_DIV_VAL2_MSK	(7L<<21)	/* Bit 23..21:	Clock Divisor Value */
+#define Y2_CLK_SELECT2_MSK	(0x1fL<<16)	/* Bit 20..16:	Clock Select */
+#define Y2_CLK_DIV_VAL_2(x)	(SHIFT21(x) & Y2_CLK_DIV_VAL2_MSK)
+#define Y2_CLK_SEL_VAL_2(x)	(SHIFT16(x) & Y2_CLK_SELECT2_MSK)
+								/* Bit 15.. 2:	reserved */
+#define Y2_CLK_DIV_ENA		BIT_1S	/* Enable  Core Clock Division */
+#define Y2_CLK_DIV_DIS		BIT_0S	/* Disable Core Clock Division */
+
+/*	B2_LD_CTRL		 8 bit	EPROM loader control register */
+/*	Bits are currently reserved */
+
+/*	B2_LD_TEST		 8 bit	EPROM loader test register */
+								/* Bit 7.. 4:	reserved */
+#define LD_T_ON			BIT_3S	/* Loader Test mode on */
+#define LD_T_OFF		BIT_2S	/* Loader Test mode off */
+#define LD_T_STEP		BIT_1S	/* Decrement FPROM addr. Counter */
+#define LD_START		BIT_0S	/* Start loading FPROM */
+
+/*
+ *	Timer Section
+ */
+/*	B2_TI_CTRL		 8 bit	Timer control */
+/*	B2_IRQM_CTRL	 8 bit	IRQ Moderation Timer Control */
+								/* Bit 7.. 3:	reserved */
+#define TIM_START		BIT_2S	/* Start Timer */
+#define TIM_STOP		BIT_1S	/* Stop  Timer */
+#define TIM_CLR_IRQ		BIT_0S	/* Clear Timer IRQ (!IRQM) */
+
+/*	B2_TI_TEST		 8 Bit	Timer Test */
+/*	B2_IRQM_TEST	 8 bit	IRQ Moderation Timer Test */
+/*	B28_DPT_TST		 8 bit	Descriptor Poll Timer Test Reg */
+								/* Bit 7.. 3:	reserved */
+#define TIM_T_ON		BIT_2S	/* Test mode on */
+#define TIM_T_OFF		BIT_1S	/* Test mode off */
+#define TIM_T_STEP		BIT_0S	/* Test step */
+
+/*	B28_DPT_INI	32 bit	Descriptor Poll Timer Init Val */
+/*	B28_DPT_VAL	32 bit	Descriptor Poll Timer Curr Val */
+								/* Bit 31..24:	reserved */
+#define DPT_MSK		0x00ffffffL	/* Bit 23.. 0:	Desc Poll Timer Bits */
+
+/*	B28_DPT_CTRL	 8 bit	Descriptor Poll Timer Ctrl Reg */
+								/* Bit  7.. 2:	reserved */
+#define DPT_START		BIT_1S	/* Start Descriptor Poll Timer */
+#define DPT_STOP		BIT_0S	/* Stop  Descriptor Poll Timer */
+
+/*	B2_TST_CTRL1	 8 bit	Test Control Register 1 */
+#define TST_FRC_DPERR_MR	BIT_7S	/* force DATAPERR on MST RD */
+#define TST_FRC_DPERR_MW	BIT_6S	/* force DATAPERR on MST WR */
+#define TST_FRC_DPERR_TR	BIT_5S	/* force DATAPERR on TRG RD */
+#define TST_FRC_DPERR_TW	BIT_4S	/* force DATAPERR on TRG WR */
+#define TST_FRC_APERR_M		BIT_3S	/* force ADDRPERR on MST */
+#define TST_FRC_APERR_T		BIT_2S	/* force ADDRPERR on TRG */
+#define TST_CFG_WRITE_ON	BIT_1S	/* Enable  Config Reg WR */
+#define TST_CFG_WRITE_OFF	BIT_0S	/* Disable Config Reg WR */
+
+/*	B2_TST_CTRL2	 8 bit	Test Control Register 2 */
+									/* Bit 7.. 4:	reserved */
+			/* force the following error on the next master read/write */
+#define TST_FRC_DPERR_MR64	BIT_3S	/* Data PERR RD 64 */
+#define TST_FRC_DPERR_MW64	BIT_2S	/* Data PERR WR 64 */
+#define TST_FRC_APERR_1M64	BIT_1S	/* Addr PERR on 1. phase */
+#define TST_FRC_APERR_2M64	BIT_0S	/* Addr PERR on 2. phase */
+
+/*	B2_GP_IO		32 bit	General Purpose I/O Register */
+						/* Bit 31..26:	reserved */
+#define GP_DIR_9	BIT_25	/* IO_9 direct, 0=In/1=Out */
+#define GP_DIR_8	BIT_24	/* IO_8 direct, 0=In/1=Out */
+#define GP_DIR_7	BIT_23	/* IO_7 direct, 0=In/1=Out */
+#define GP_DIR_6	BIT_22	/* IO_6 direct, 0=In/1=Out */
+#define GP_DIR_5	BIT_21	/* IO_5 direct, 0=In/1=Out */
+#define GP_DIR_4	BIT_20	/* IO_4 direct, 0=In/1=Out */
+#define GP_DIR_3	BIT_19	/* IO_3 direct, 0=In/1=Out */
+#define GP_DIR_2	BIT_18	/* IO_2 direct, 0=In/1=Out */
+#define GP_DIR_1	BIT_17	/* IO_1 direct, 0=In/1=Out */
+#define GP_DIR_0	BIT_16	/* IO_0 direct, 0=In/1=Out */
+						/* Bit 15..10:	reserved */
+#define GP_IO_9		BIT_9	/* IO_9 pin */
+#define GP_IO_8		BIT_8	/* IO_8 pin */
+#define GP_IO_7		BIT_7	/* IO_7 pin */
+#define GP_IO_6		BIT_6	/* IO_6 pin */
+#define GP_IO_5		BIT_5	/* IO_5 pin */
+#define GP_IO_4		BIT_4	/* IO_4 pin */
+#define GP_IO_3		BIT_3	/* IO_3 pin */
+#define GP_IO_2		BIT_2	/* IO_2 pin */
+#define GP_IO_1		BIT_1	/* IO_1 pin */
+#define GP_IO_0		BIT_0	/* IO_0 pin */
+
+/*	B2_I2C_CTRL		32 bit	I2C HW Control Register */
+#define I2C_FLAG		BIT_31		/* Start read/write if WR */
+#define I2C_ADDR		(0x7fffL<<16)	/* Bit 30..16:	Addr to be RD/WR */
+#define I2C_DEV_SEL		(0x7fL<<9)		/* Bit 15.. 9:	I2C Device Select */
+								/* Bit	8.. 5:	reserved */
+#define I2C_BURST_LEN	BIT_4		/* Burst Len, 1/4 bytes */
+#define I2C_DEV_SIZE	(7<<1)		/* Bit	3.. 1:	I2C Device Size */
+#define I2C_025K_DEV	(0<<1)		/*		0:   256 Bytes or smaller */
+#define I2C_05K_DEV		(1<<1)		/*		1:   512 Bytes */
+#define I2C_1K_DEV		(2<<1)		/*		2:  1024 Bytes */
+#define I2C_2K_DEV		(3<<1)		/*		3:  2048 Bytes */
+#define I2C_4K_DEV		(4<<1)		/*		4:  4096 Bytes */
+#define I2C_8K_DEV		(5<<1)		/*		5:  8192 Bytes */
+#define I2C_16K_DEV		(6<<1)		/*		6: 16384 Bytes */
+#define I2C_32K_DEV		(7<<1)		/*		7: 32768 Bytes */
+#define I2C_STOP		BIT_0		/* Interrupt I2C transfer */
+
+/*	B2_I2C_IRQ		32 bit	I2C HW IRQ Register */
+								/* Bit 31.. 1	reserved */
+#define I2C_CLR_IRQ		BIT_0	/* Clear I2C IRQ */
+
+/*	B2_I2C_SW		32 bit (8 bit access)	I2C SW Port Register */
+								/* Bit  7.. 3:	reserved */
+#define I2C_DATA_DIR	BIT_2S		/* direction of I2C_DATA */
+#define I2C_DATA		BIT_1S		/* I2C Data Port */
+#define I2C_CLK			BIT_0S		/* I2C Clock Port */
+
+/* I2C Address */
+#define I2C_SENS_ADDR	LM80_ADDR	/* I2C Sensor Address (Volt and Temp) */
+
+
+/*	B2_BSC_CTRL		 8 bit	Blink Source Counter Control */
+							/* Bit  7.. 2:	reserved */
+#define BSC_START	BIT_1S		/* Start Blink Source Counter */
+#define BSC_STOP	BIT_0S		/* Stop  Blink Source Counter */
+
+/*	B2_BSC_STAT		 8 bit	Blink Source Counter Status */
+							/* Bit  7.. 1:	reserved */
+#define BSC_SRC		BIT_0S		/* Blink Source, 0=Off / 1=On */
+
+/*	B2_BSC_TST		16 bit	Blink Source Counter Test Reg */
+#define BSC_T_ON	BIT_2S		/* Test mode on */
+#define BSC_T_OFF	BIT_1S		/* Test mode off */
+#define BSC_T_STEP	BIT_0S		/* Test step */
+
+/*	Y2_PEX_PHY_ADDR/DATA		PEX PHY address and data reg  (Yukon-2 only) */
+#define PEX_RD_ACCESS	BIT_31	/* Access Mode Read = 1, Write = 0 */
+#define PEX_DB_ACCESS	BIT_30	/* Access to debug register */
+
+
+/*	B3_RAM_ADDR		32 bit	RAM Address, to read or write */
+					/* Bit 31..19:	reserved */
+#define RAM_ADR_RAN	0x0007ffffL	/* Bit 18.. 0:	RAM Address Range */
+
+/* RAM Interface Registers */
+/*	B3_RI_CTRL		16 bit	RAM Interface Control Register */
+								/* Bit 15..10:	reserved */
+#define RI_CLR_RD_PERR	BIT_9S	/* Clear IRQ RAM Read  Parity Err */
+#define RI_CLR_WR_PERR	BIT_8S	/* Clear IRQ RAM Write Parity Err */
+								/* Bit	7.. 2:	reserved */
+#define RI_RST_CLR		BIT_1S	/* Clear RAM Interface Reset */
+#define RI_RST_SET		BIT_0S	/* Set   RAM Interface Reset */
+
+/*	B3_RI_TEST		 8 bit	RAM Iface Test Register */
+								/* Bit 15.. 4:	reserved */
+#define RI_T_EV			BIT_3S	/* Timeout Event occured */
+#define RI_T_ON			BIT_2S	/* Timeout Timer Test On */
+#define RI_T_OFF		BIT_1S	/* Timeout Timer Test Off */
+#define RI_T_STEP		BIT_0S	/* Timeout Timer Step */
+
+/* MAC Arbiter Registers */
+/*	B3_MA_TO_CTRL	16 bit	MAC Arbiter Timeout Ctrl Reg */
+								/* Bit 15.. 4:	reserved */
+#define MA_FOE_ON		BIT_3S	/* XMAC Fast Output Enable ON */
+#define MA_FOE_OFF		BIT_2S	/* XMAC Fast Output Enable OFF */
+#define MA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
+#define MA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
+
+/*	B3_MA_RC_CTRL	16 bit	MAC Arbiter Recovery Ctrl Reg */
+								/* Bit 15.. 8:	reserved */
+#define MA_ENA_REC_TX2	BIT_7S	/* Enable  Recovery Timer TX2 */
+#define MA_DIS_REC_TX2	BIT_6S	/* Disable Recovery Timer TX2 */
+#define MA_ENA_REC_TX1	BIT_5S	/* Enable  Recovery Timer TX1 */
+#define MA_DIS_REC_TX1	BIT_4S	/* Disable Recovery Timer TX1 */
+#define MA_ENA_REC_RX2	BIT_3S	/* Enable  Recovery Timer RX2 */
+#define MA_DIS_REC_RX2	BIT_2S	/* Disable Recovery Timer RX2 */
+#define MA_ENA_REC_RX1	BIT_1S	/* Enable  Recovery Timer RX1 */
+#define MA_DIS_REC_RX1	BIT_0S	/* Disable Recovery Timer RX1 */
+
+/* Packet Arbiter Registers */
+/*	B3_PA_CTRL		16 bit	Packet Arbiter Ctrl Register */
+								/* Bit 15..14:	reserved */
+#define PA_CLR_TO_TX2	BIT_13S	/* Clear IRQ Packet Timeout TX2 */
+#define PA_CLR_TO_TX1	BIT_12S	/* Clear IRQ Packet Timeout TX1 */
+#define PA_CLR_TO_RX2	BIT_11S	/* Clear IRQ Packet Timeout RX2 */
+#define PA_CLR_TO_RX1	BIT_10S	/* Clear IRQ Packet Timeout RX1 */
+#define PA_ENA_TO_TX2	BIT_9S	/* Enable  Timeout Timer TX2 */
+#define PA_DIS_TO_TX2	BIT_8S	/* Disable Timeout Timer TX2 */
+#define PA_ENA_TO_TX1	BIT_7S	/* Enable  Timeout Timer TX1 */
+#define PA_DIS_TO_TX1	BIT_6S	/* Disable Timeout Timer TX1 */
+#define PA_ENA_TO_RX2	BIT_5S	/* Enable  Timeout Timer RX2 */
+#define PA_DIS_TO_RX2	BIT_4S	/* Disable Timeout Timer RX2 */
+#define PA_ENA_TO_RX1	BIT_3S	/* Enable  Timeout Timer RX1 */
+#define PA_DIS_TO_RX1	BIT_2S	/* Disable Timeout Timer RX1 */
+#define PA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
+#define PA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
+
+#define PA_ENA_TO_ALL	(PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
+						 PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
+
+/* Rx/Tx Path related Arbiter Test Registers */
+/*	B3_MA_TO_TEST	16 bit	MAC Arbiter Timeout Test Reg */
+/*	B3_MA_RC_TEST	16 bit	MAC Arbiter Recovery Test Reg */
+/*	B3_PA_TEST		16 bit	Packet Arbiter Test Register */
+/*			Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
+#define TX2_T_EV	BIT_15S		/* TX2 Timeout/Recv Event occured */
+#define TX2_T_ON	BIT_14S		/* TX2 Timeout/Recv Timer Test On */
+#define TX2_T_OFF	BIT_13S		/* TX2 Timeout/Recv Timer Tst Off */
+#define TX2_T_STEP	BIT_12S		/* TX2 Timeout/Recv Timer Step */
+#define TX1_T_EV	BIT_11S		/* TX1 Timeout/Recv Event occured */
+#define TX1_T_ON	BIT_10S		/* TX1 Timeout/Recv Timer Test On */
+#define TX1_T_OFF	BIT_9S		/* TX1 Timeout/Recv Timer Tst Off */
+#define TX1_T_STEP	BIT_8S		/* TX1 Timeout/Recv Timer Step */
+#define RX2_T_EV	BIT_7S		/* RX2 Timeout/Recv Event occured */
+#define RX2_T_ON	BIT_6S		/* RX2 Timeout/Recv Timer Test On */
+#define RX2_T_OFF	BIT_5S		/* RX2 Timeout/Recv Timer Tst Off */
+#define RX2_T_STEP	BIT_4S		/* RX2 Timeout/Recv Timer Step */
+#define RX1_T_EV	BIT_3S		/* RX1 Timeout/Recv Event occured */
+#define RX1_T_ON	BIT_2S		/* RX1 Timeout/Recv Timer Test On */
+#define RX1_T_OFF	BIT_1S		/* RX1 Timeout/Recv Timer Tst Off */
+#define RX1_T_STEP	BIT_0S		/* RX1 Timeout/Recv Timer Step */
+
+
+/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+/*	TXA_ITI_INI		32 bit	Tx Arb Interval Timer Init Val */
+/*	TXA_ITI_VAL		32 bit	Tx Arb Interval Timer Value */
+/*	TXA_LIM_INI		32 bit	Tx Arb Limit Counter Init Val */
+/*	TXA_LIM_VAL		32 bit	Tx Arb Limit Counter Value */
+								/* Bit 31..24:	reserved */
+#define TXA_MAX_VAL	0x00ffffffUL/* Bit 23.. 0:	Max TXA Timer/Cnt Val */
+
+/*	TXA_CTRL		 8 bit	Tx Arbiter Control Register */
+#define TXA_ENA_FSYNC	BIT_7S	/* Enable  force of sync Tx queue */
+#define TXA_DIS_FSYNC	BIT_6S	/* Disable force of sync Tx queue */
+#define TXA_ENA_ALLOC	BIT_5S	/* Enable  alloc of free bandwidth */
+#define TXA_DIS_ALLOC	BIT_4S	/* Disable alloc of free bandwidth */
+#define TXA_START_RC	BIT_3S	/* Start sync Rate Control */
+#define TXA_STOP_RC		BIT_2S	/* Stop  sync Rate Control */
+#define TXA_ENA_ARB		BIT_1S	/* Enable  Tx Arbiter */
+#define TXA_DIS_ARB		BIT_0S	/* Disable Tx Arbiter */
+
+/*	TXA_TEST		 8 bit	Tx Arbiter Test Register */
+								/* Bit 7.. 6:	reserved */
+#define TXA_INT_T_ON	BIT_5S	/* Tx Arb Interval Timer Test On */
+#define TXA_INT_T_OFF	BIT_4S	/* Tx Arb Interval Timer Test Off */
+#define TXA_INT_T_STEP	BIT_3S	/* Tx Arb Interval Timer Step */
+#define TXA_LIM_T_ON	BIT_2S	/* Tx Arb Limit Timer Test On */
+#define TXA_LIM_T_OFF	BIT_1S	/* Tx Arb Limit Timer Test Off */
+#define TXA_LIM_T_STEP	BIT_0S	/* Tx Arb Limit Timer Step */
+
+/*	TXA_STAT		 8 bit	Tx Arbiter Status Register */
+								/* Bit 7.. 1:	reserved */
+#define TXA_PRIO_XS		BIT_0S	/* sync queue has prio to send */
+
+/*	Q_BC			32 bit	Current Byte Counter */
+								/* Bit 31..16:	reserved */
+#define BC_MAX			0xffff	/* Bit 15.. 0:	Byte counter */
+
+/* BMU Control / Status Registers (Yukon and Genesis) */
+/*	B0_R1_CSR		32 bit	BMU Ctrl/Stat Rx Queue 1 */
+/*	B0_R2_CSR		32 bit	BMU Ctrl/Stat Rx Queue 2 */
+/*	B0_XA1_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
+/*	B0_XS1_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 1 */
+/*	B0_XA2_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
+/*	B0_XS2_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 2 */
+/*	Q_CSR			32 bit	BMU Control/Status Register */
+								/* Bit 31..25:	reserved */
+#define CSR_SV_IDLE		BIT_24		/* BMU SM Idle */
+								/* Bit 23..22:	reserved */
+#define CSR_DESC_CLR	BIT_21		/* Clear Reset for Descr */
+#define CSR_DESC_SET	BIT_20		/* Set   Reset for Descr */
+#define CSR_FIFO_CLR	BIT_19		/* Clear Reset for FIFO */
+#define CSR_FIFO_SET	BIT_18		/* Set   Reset for FIFO */
+#define CSR_HPI_RUN		BIT_17		/* Release HPI SM */
+#define CSR_HPI_RST		BIT_16		/* Reset   HPI SM to Idle */
+#define CSR_SV_RUN		BIT_15		/* Release Supervisor SM */
+#define CSR_SV_RST		BIT_14		/* Reset   Supervisor SM */
+#define CSR_DREAD_RUN	BIT_13		/* Release Descr Read SM */
+#define CSR_DREAD_RST	BIT_12		/* Reset   Descr Read SM */
+#define CSR_DWRITE_RUN	BIT_11		/* Release Descr Write SM */
+#define CSR_DWRITE_RST	BIT_10		/* Reset   Descr Write SM */
+#define CSR_TRANS_RUN	BIT_9		/* Release Transfer SM */
+#define CSR_TRANS_RST	BIT_8		/* Reset   Transfer SM */
+#define CSR_ENA_POL		BIT_7		/* Enable  Descr Polling */
+#define CSR_DIS_POL		BIT_6		/* Disable Descr Polling */
+#define CSR_STOP		BIT_5		/* Stop  Rx/Tx Queue */
+#define CSR_START		BIT_4		/* Start Rx/Tx Queue */
+#define CSR_IRQ_CL_P	BIT_3		/* (Rx)	Clear Parity IRQ */
+#define CSR_IRQ_CL_B	BIT_2		/* Clear EOB IRQ */
+#define CSR_IRQ_CL_F	BIT_1		/* Clear EOF IRQ */
+#define CSR_IRQ_CL_C	BIT_0		/* Clear ERR IRQ */
+
+#define CSR_SET_RESET	(CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
+						 CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
+						 CSR_TRANS_RST)
+#define CSR_CLR_RESET	(CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
+						 CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
+						 CSR_TRANS_RUN)
+
+/* Rx BMU Control / Status Registers (Yukon-2) */
+#define BMU_IDLE			BIT_31	/* BMU Idle State */
+#define BMU_RX_TCP_PKT		BIT_30	/* Rx TCP Packet (when RSS Hash enabled) */
+#define BMU_RX_IP_PKT		BIT_29	/* Rx IP  Packet (when RSS Hash enabled) */
+								/* Bit 28..16:	reserved */
+#define BMU_ENA_RX_RSS_HASH	BIT_15	/* Enable  Rx RSS Hash */
+#define BMU_DIS_RX_RSS_HASH	BIT_14	/* Disable Rx RSS Hash */
+#define BMU_ENA_RX_CHKSUM	BIT_13	/* Enable  Rx TCP/IP Checksum Check */
+#define BMU_DIS_RX_CHKSUM	BIT_12	/* Disable Rx TCP/IP Checksum Check */
+#define BMU_CLR_IRQ_PAR		BIT_11	/* Clear IRQ on Parity errors (Rx) */
+#define BMU_CLR_IRQ_TCP		BIT_11	/* Clear IRQ on TCP segmen. error (Tx) */
+#define BMU_CLR_IRQ_CHK		BIT_10	/* Clear IRQ Check */
+#define BMU_STOP			BIT_9	/* Stop  Rx/Tx Queue */
+#define BMU_START			BIT_8	/* Start Rx/Tx Queue */
+#define BMU_FIFO_OP_ON		BIT_7	/* FIFO Operational On */
+#define BMU_FIFO_OP_OFF 	BIT_6	/* FIFO Operational Off */
+#define BMU_FIFO_ENA		BIT_5	/* Enable FIFO */
+#define BMU_FIFO_RST		BIT_4	/* Reset  FIFO */
+#define BMU_OP_ON			BIT_3	/* BMU Operational On */
+#define BMU_OP_OFF			BIT_2	/* BMU Operational Off */
+#define BMU_RST_CLR			BIT_1	/* Clear BMU Reset (Enable) */
+#define BMU_RST_SET			BIT_0	/* Set   BMU Reset */
+
+#define BMU_CLR_RESET		(BMU_FIFO_RST | BMU_OP_OFF | BMU_RST_CLR)
+#define BMU_OPER_INIT		(BMU_CLR_IRQ_PAR | BMU_CLR_IRQ_CHK | BMU_START | \
+							BMU_FIFO_ENA | BMU_OP_ON)
+							
+/* Tx BMU Control / Status Registers (Yukon-2) */
+								/* Bit 31: same as for Rx */
+								/* Bit 30..14:	reserved */
+#define BMU_TX_IPIDINCR_ON	BIT_13	/* Enable  IP ID Increment */
+#define BMU_TX_IPIDINCR_OFF	BIT_12	/* Disable IP ID Increment */
+#define BMU_TX_CLR_IRQ_TCP	BIT_11	/* Clear IRQ on TCP segm. length mism. */
+								/* Bit 10..0: same as for Rx */
+
+/*	Q_F				32 bit	Flag Register */
+									/* Bit 31..28:	reserved */
+#define F_ALM_FULL		BIT_27		/* Rx FIFO: almost full */
+#define F_EMPTY			BIT_27		/* Tx FIFO: empty flag */
+#define F_FIFO_EOF		BIT_26		/* Tag (EOF Flag) bit in FIFO */
+#define F_WM_REACHED	BIT_25		/* Watermark reached */
+#define F_M_RX_RAM_DIS	BIT_24		/* MAC Rx RAM Read Port disable */
+#define F_FIFO_LEVEL	(0x1fL<<16)	/* Bit 23..16:	# of Qwords in FIFO */
+									/* Bit 15..11: 	reserved */
+#define F_WATER_MARK	0x0007ffL	/* Bit 10.. 0:	Watermark */
+
+/*	Q_T1			32 bit	Test Register 1 */
+/*		Holds four State Machine control Bytes */
+#define SM_CTRL_SV_MSK	(0xffL<<24)	/* Bit 31..24:	Control Supervisor SM */
+#define SM_CTRL_RD_MSK	(0xffL<<16)	/* Bit 23..16:	Control Read Desc SM */
+#define SM_CTRL_WR_MSK	(0xffL<<8)	/* Bit 15.. 8:	Control Write Desc SM */
+#define SM_CTRL_TR_MSK	0xffL		/* Bit	7.. 0:	Control Transfer SM */
+
+/*	Q_T1_TR			 8 bit	Test Register 1 Transfer SM */
+/*	Q_T1_WR			 8 bit	Test Register 1 Write Descriptor SM */
+/*	Q_T1_RD			 8 bit	Test Register 1 Read Descriptor SM */
+/*	Q_T1_SV			 8 bit	Test Register 1 Supervisor SM */
+
+/* The control status byte of each machine looks like ... */
+#define SM_STATE		0xf0	/* Bit 7.. 4:	State which shall be loaded */
+#define SM_LOAD			BIT_3S	/* Load the SM with SM_STATE */
+#define SM_TEST_ON		BIT_2S	/* Switch on SM Test Mode */
+#define SM_TEST_OFF		BIT_1S	/* Go off the Test Mode */
+#define SM_STEP			BIT_0S	/* Step the State Machine */
+/* The encoding of the states is not supported by the Diagnostics Tool */
+
+/*	Q_T2			32 bit	Test Register 2 */
+								/* Bit 31.. 8:	reserved */
+#define T2_AC_T_ON		BIT_7	/* Address Counter Test Mode on */
+#define T2_AC_T_OFF		BIT_6	/* Address Counter Test Mode off */
+#define T2_BC_T_ON		BIT_5	/* Byte Counter Test Mode on */
+#define T2_BC_T_OFF		BIT_4	/* Byte Counter Test Mode off */
+#define T2_STEP04		BIT_3	/* Inc AC/Dec BC by 4 */
+#define T2_STEP03		BIT_2	/* Inc AC/Dec BC by 3 */
+#define T2_STEP02		BIT_1	/* Inc AC/Dec BC by 2 */
+#define T2_STEP01		BIT_0	/* Inc AC/Dec BC by 1 */
+
+/*	Q_T3			32 bit	Test Register 3 */
+								/* Bit 31.. 7:	reserved */
+#define T3_MUX_MSK		(7<<4)	/* Bit  6.. 4:	Mux Position */
+								/* Bit  3:	reserved */
+#define T3_VRAM_MSK		7		/* Bit  2.. 0:	Virtual RAM Buffer Address */
+
+/* PREF_UNIT_CTRL_REG	32 bit	Prefetch Control register */
+#define PREF_UNIT_OP_ON		BIT_3	/* prefetch unit operational */
+#define PREF_UNIT_OP_OFF	BIT_2	/* prefetch unit not operational */
+#define PREF_UNIT_RST_CLR	BIT_1	/* Clear Prefetch Unit Reset */
+#define PREF_UNIT_RST_SET	BIT_0	/* Set   Prefetch Unit Reset */
+
+/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+/*	RB_START		32 bit	RAM Buffer Start Address */
+/*	RB_END			32 bit	RAM Buffer End Address */
+/*	RB_WP			32 bit	RAM Buffer Write Pointer */
+/*	RB_RP			32 bit	RAM Buffer Read Pointer */
+/*	RB_RX_UTPP		32 bit	Rx Upper Threshold, Pause Pack */
+/*	RB_RX_LTPP		32 bit	Rx Lower Threshold, Pause Pack */
+/*	RB_RX_UTHP		32 bit	Rx Upper Threshold, High Prio */
+/*	RB_RX_LTHP		32 bit	Rx Lower Threshold, High Prio */
+/*	RB_PC			32 bit	RAM Buffer Packet Counter */
+/*	RB_LEV			32 bit	RAM Buffer Level Register */
+				/* Bit 31..19:	reserved */
+#define RB_MSK	0x0007ffff	/* Bit 18.. 0:	RAM Buffer Pointer Bits */
+
+/*	RB_TST2			 8 bit	RAM Buffer Test Register 2 */
+							/* Bit 7.. 4:	reserved */
+#define RB_PC_DEC		BIT_3S	/* Packet Counter Decrement */
+#define RB_PC_T_ON		BIT_2S	/* Packet Counter Test On */
+#define RB_PC_T_OFF		BIT_1S	/* Packet Counter Test Off */
+#define RB_PC_INC		BIT_0S	/* Packet Counter Increment */
+
+/*	RB_TST1			 8 bit	RAM Buffer Test Register 1 */
+							/* Bit 7:	reserved */
+#define RB_WP_T_ON		BIT_6S	/* Write Pointer Test On */
+#define RB_WP_T_OFF		BIT_5S	/* Write Pointer Test Off */
+#define RB_WP_INC		BIT_4S	/* Write Pointer Increment */
+								/* Bit 3:	reserved */
+#define RB_RP_T_ON		BIT_2S	/* Read Pointer Test On */
+#define RB_RP_T_OFF		BIT_1S	/* Read Pointer Test Off */
+#define RB_RP_INC		BIT_0S	/* Read Pointer Increment */
+
+/*	RB_CTRL			 8 bit	RAM Buffer Control Register */
+							/* Bit 7.. 6:	reserved */
+#define RB_ENA_STFWD	BIT_5S	/* Enable  Store & Forward */
+#define RB_DIS_STFWD	BIT_4S	/* Disable Store & Forward */
+#define RB_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
+#define RB_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
+#define RB_RST_CLR		BIT_1S	/* Clear RAM Buf STM Reset */
+#define RB_RST_SET		BIT_0S	/* Set   RAM Buf STM Reset */
+
+/* Yukon-2 */
+							/* Bit 31..20:	reserved */
+#define RB_CNT_DOWN		BIT_19	/* Packet Counter Decrement */
+#define RB_CNT_TST_ON	BIT_18  /* Packet Counter Test On */
+#define RB_CNT_TST_OFF	BIT_17	/* Packet Counter Test Off */
+#define RB_CNT_UP		BIT_16	/* Packet Counter Increment */
+							/* Bit 15:	reserved */
+#define RB_WP_TST_ON	BIT_14  /* Write Pointer Test On */
+#define RB_WP_TST_OFF	BIT_13	/* Write Pointer Test Off */
+#define RB_WP_UP		BIT_12	/* Write Pointer Increment  */
+							/* Bit 11:	reserved */
+#define RB_RP_TST_ON	BIT_10  /* Read Pointer Test On */
+#define RB_RP_TST_OFF	BIT_9	/* Read Pointer Test Off */
+#define RB_RP_UP		BIT_8	/* Read Pointer Increment */
+
+
+/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
+
+/*	RX_MFF_EA		32 bit	Receive MAC FIFO End Address */
+/*	RX_MFF_WP		32 bit	Receive MAC FIFO Write Pointer */
+/*	RX_MFF_RP		32 bit	Receive MAC FIFO Read Pointer */
+/*	RX_MFF_PC		32 bit	Receive MAC FIFO Packet Counter */
+/*	RX_MFF_LEV		32 bit	Receive MAC FIFO Level */
+/*	TX_MFF_EA		32 bit	Transmit MAC FIFO End Address */
+/*	TX_MFF_WP		32 bit	Transmit MAC FIFO Write Pointer */
+/*	TX_MFF_WSP		32 bit	Transmit MAC FIFO WR Shadow Pointer */
+/*	TX_MFF_RP		32 bit	Transmit MAC FIFO Read Pointer */
+/*	TX_MFF_PC		32 bit	Transmit MAC FIFO Packet Cnt */
+/*	TX_MFF_LEV		32 bit	Transmit MAC FIFO Level */
+								/* Bit 31.. 6:	reserved */
+#define MFF_MSK			0x007fL	/* Bit	5.. 0:	MAC FIFO Address/Ptr Bits */
+
+/*	RX_MFF_CTRL1	16 bit	Receive MAC FIFO Control Reg 1 */
+								/* Bit 15..14:	reserved */
+#define MFF_ENA_RDY_PAT	BIT_13S		/* Enable  Ready Patch */
+#define MFF_DIS_RDY_PAT	BIT_12S		/* Disable Ready Patch */
+#define MFF_ENA_TIM_PAT	BIT_11S		/* Enable  Timing Patch */
+#define MFF_DIS_TIM_PAT	BIT_10S		/* Disable Timing Patch */
+#define MFF_ENA_ALM_FUL	BIT_9S		/* Enable  AlmostFull Sign */
+#define MFF_DIS_ALM_FUL	BIT_8S		/* Disable AlmostFull Sign */
+#define MFF_ENA_PAUSE	BIT_7S		/* Enable  Pause Signaling */
+#define MFF_DIS_PAUSE	BIT_6S		/* Disable Pause Signaling */
+#define MFF_ENA_FLUSH	BIT_5S		/* Enable  Frame Flushing */
+#define MFF_DIS_FLUSH	BIT_4S		/* Disable Frame Flushing */
+#define MFF_ENA_TIST	BIT_3S		/* Enable  Time Stamp Gener */
+#define MFF_DIS_TIST	BIT_2S		/* Disable Time Stamp Gener */
+#define MFF_CLR_INTIST	BIT_1S		/* Clear IRQ No Time Stamp */
+#define MFF_CLR_INSTAT	BIT_0S		/* Clear IRQ No Status */
+
+#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
+
+/*	TX_MFF_CTRL1	16 bit	Transmit MAC FIFO Control Reg 1 */
+#define MFF_CLR_PERR	BIT_15S		/* Clear Parity Error IRQ */
+								/* Bit 14:	reserved */
+#define MFF_ENA_PKT_REC	BIT_13S		/* Enable  Packet Recovery */
+#define MFF_DIS_PKT_REC BIT_12S		/* Disable Packet Recovery */
+/*	MFF_ENA_TIM_PAT	 (see RX_MFF_CTRL1) Bit 11:	Enable  Timing Patch */
+/*	MFF_DIS_TIM_PAT	 (see RX_MFF_CTRL1) Bit 10:	Disable Timing Patch */
+/*	MFF_ENA_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 9:	Enable  Almost Full Sign */
+/*	MFF_DIS_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 8:	Disable Almost Full Sign */
+#define MFF_ENA_W4E		BIT_7S		/* Enable  Wait for Empty */
+#define MFF_DIS_W4E		BIT_6S		/* Disable Wait for Empty */
+/*	MFF_ENA_FLUSH	 (see RX_MFF_CTRL1) Bit	 5:	Enable  Frame Flushing */
+/*	MFF_DIS_FLUSH	 (see RX_MFF_CTRL1) Bit	 4:	Disable Frame Flushing */
+#define MFF_ENA_LOOPB	BIT_3S		/* Enable  Loopback */
+#define MFF_DIS_LOOPB	BIT_2S		/* Disable Loopback */
+#define MFF_CLR_MAC_RST	BIT_1S		/* Clear XMAC Reset */
+#define MFF_SET_MAC_RST	BIT_0S		/* Set   XMAC Reset */
+
+#define MFF_TX_CTRL_DEF	(MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
+
+/*	RX_MFF_TST2	 	 8 bit	Receive MAC FIFO Test Register 2 */
+/*	TX_MFF_TST2	 	 8 bit	Transmit MAC FIFO Test Register 2 */
+								/* Bit 7:	reserved */
+#define MFF_WSP_T_ON	BIT_6S	/* Tx: Write Shadow Pointer Test On */
+#define MFF_WSP_T_OFF	BIT_5S	/* Tx: Write Shadow Pointer Test Off */
+#define MFF_WSP_INC		BIT_4S	/* Tx: Write Shadow Pointer Increment */
+#define MFF_PC_DEC		BIT_3S	/* Packet Counter Decrement */
+#define MFF_PC_T_ON		BIT_2S	/* Packet Counter Test On */
+#define MFF_PC_T_OFF	BIT_1S	/* Packet Counter Test Off */
+#define MFF_PC_INC		BIT_0S	/* Packet Counter Increment */
+
+/*	RX_MFF_TST1	 	 8 bit	Receive MAC FIFO Test Register 1 */
+/*	TX_MFF_TST1	 	 8 bit	Transmit MAC FIFO Test Register 1 */
+					/* Bit 7:	reserved */
+#define MFF_WP_T_ON		BIT_6S	/* Write Pointer Test On */
+#define MFF_WP_T_OFF	BIT_5S	/* Write Pointer Test Off */
+#define MFF_WP_INC		BIT_4S	/* Write Pointer Increment */
+							/* Bit 3:	reserved */
+#define MFF_RP_T_ON		BIT_2S	/* Read Pointer Test On */
+#define MFF_RP_T_OFF	BIT_1S	/* Read Pointer Test Off */
+#define MFF_RP_DEC		BIT_0S	/* Read Pointer Decrement */
+
+/*	RX_MFF_CTRL2	 8 bit	Receive MAC FIFO Control Reg 2 */
+/*	TX_MFF_CTRL2	 8 bit	Transmit MAC FIFO Control Reg 2 */
+								/* Bit 7..4:	reserved */
+#define MFF_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
+#define MFF_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
+#define MFF_RST_CLR		BIT_1S	/* Clear MAC FIFO Reset */
+#define MFF_RST_SET		BIT_0S	/* Set   MAC FIFO Reset */
+
+
+/*	Link LED Counter Registers (GENESIS only) */
+
+/*	RX_LED_CTRL		 8 bit	Receive LED Cnt Control Reg */
+/*	TX_LED_CTRL		 8 bit	Transmit LED Cnt Control Reg */
+							/* Bit 7.. 3:	reserved */
+#define LED_START		BIT_2S	/* Start Counter */
+#define LED_STOP		BIT_1S	/* Stop Counter */
+#define LED_STATE		BIT_0S	/* Rx/Tx: LED State, 1=LED On */
+
+/*	LNK_SYNC_CTRL	 8 bit	Link Sync Cnt Control Register */
+							/* Bit 7.. 3:	reserved */
+#define LNK_START		BIT_2S	/* Start Counter */
+#define LNK_STOP		BIT_1S	/* Stop Counter */
+#define LNK_CLR_IRQ		BIT_0S	/* Clear Link IRQ */
+
+/*	RX_LED_TST		 8 bit	Receive LED Cnt Test Register */
+/*	TX_LED_TST		 8 bit	Transmit LED Cnt Test Register */
+/*	LNK_SYNC_TST	 8 bit	Link Sync Cnt Test Register */
+							/* Bit 7.. 3:	reserved */
+#define LED_T_ON		BIT_2S	/* LED Counter Test mode On */
+#define LED_T_OFF		BIT_1S	/* LED Counter Test mode Off */
+#define LED_T_STEP		BIT_0S	/* LED Counter Step */
+
+/*	LNK_LED_REG	 	 8 bit	Link LED Register */
+							/* Bit 7.. 6:	reserved */
+#define LED_BLK_ON		BIT_5S	/* Link LED Blinking On */
+#define LED_BLK_OFF		BIT_4S	/* Link LED Blinking Off */
+#define LED_SYNC_ON		BIT_3S	/* Use Sync Wire to switch LED */
+#define LED_SYNC_OFF	BIT_2S	/* Disable Sync Wire Input */
+#define LED_ON			BIT_1S	/* Switch LED On */
+#define LED_OFF			BIT_0S	/* Switch LED Off */
+
+/*	Receive and Transmit GMAC FIFO Registers (YUKON only) */
+
+/*	RX_GMF_EA		32 bit	Rx GMAC FIFO End Address */
+/*	Yukon-FE+ specific */
+#define TX_DYN_WM_ENA	(BIT_0S | BIT_1S)
+
+/*	RX_GMF_AF_THR	32 bit	Rx GMAC FIFO Almost Full Thresh. */
+/*	RX_GMF_WP		32 bit	Rx GMAC FIFO Write Pointer */
+/*	RX_GMF_WLEV		32 bit	Rx GMAC FIFO Write Level */
+/*	RX_GMF_RP		32 bit	Rx GMAC FIFO Read Pointer */
+/*	RX_GMF_RLEV		32 bit	Rx GMAC FIFO Read Level */
+/*	TX_GMF_EA		32 bit	Tx GMAC FIFO End Address */
+/*	TX_GMF_AE_THR	32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
+/*	TX_GMF_WP		32 bit	Tx GMAC FIFO Write Pointer */
+/*	TX_GMF_WSP		32 bit	Tx GMAC FIFO Write Shadow Pointer */
+/*	TX_GMF_WLEV		32 bit	Tx GMAC FIFO Write Level */
+/*	TX_GMF_RP		32 bit	Tx GMAC FIFO Read Pointer */
+/*	TX_GMF_RSTP		32 bit	Tx GMAC FIFO Restart Pointer */
+/*	TX_GMF_RLEV		32 bit	Tx GMAC FIFO Read Level */
+
+/*	RX_GMF_CTRL_T	32 bit	Rx GMAC FIFO Control/Test */
+						/* Bit 31..28 reserved */
+#define RX_TRUNC_ON		BIT_27	/* Enable  Packet Truncation */
+#define RX_TRUNC_OFF	BIT_26	/* Disable Packet Truncation */
+#define RX_VLAN_STRIP_ON	BIT_25	/* Enable  VLAN Stripping */
+#define RX_VLAN_STRIP_OFF	BIT_24	/* Disable VLAN Stripping */
+						/* Bit 23..15 reserved */
+#define GMF_WP_TST_ON	BIT_14	/* Write Pointer Test On */
+#define GMF_WP_TST_OFF	BIT_13	/* Write Pointer Test Off */
+#define GMF_WP_STEP		BIT_12	/* Write Pointer Step/Increment */
+						/* Bit 11:	reserved */
+#define GMF_RP_TST_ON	BIT_10	/* Read Pointer Test On */
+#define GMF_RP_TST_OFF	BIT_9	/* Read Pointer Test Off */
+#define GMF_RP_STEP		BIT_8	/* Read Pointer Step/Increment */
+#define GMF_RX_F_FL_ON	BIT_7	/* Rx FIFO Flush Mode On */
+#define GMF_RX_F_FL_OFF	BIT_6	/* Rx FIFO Flush Mode Off */
+#define GMF_CLI_RX_FO	BIT_5	/* Clear IRQ Rx FIFO Overrun */
+#define GMF_CLI_RX_FC	BIT_4	/* Clear IRQ Rx Frame Complete */
+#define GMF_OPER_ON		BIT_3	/* Operational Mode On */
+#define GMF_OPER_OFF	BIT_2	/* Operational Mode Off */
+#define GMF_RST_CLR		BIT_1	/* Clear GMAC FIFO Reset */
+#define GMF_RST_SET		BIT_0	/* Set   GMAC FIFO Reset */
+
+/*	TX_GMF_CTRL_T	32 bit	Tx GMAC FIFO Control/Test (YUKON and Yukon-2) */
+#define TX_STFW_DIS		BIT_31	/* Disable Store & Forward (Yukon-EC Ultra) */
+#define TX_STFW_ENA		BIT_30	/* Enable  Store & Forward (Yukon-EC Ultra) */
+						/* Bits 29..26: reserved */
+#define TX_VLAN_TAG_ON	BIT_25	/* Enable  VLAN tagging */
+#define TX_VLAN_TAG_OFF	BIT_24	/* Disable VLAN tagging */
+#define TX_PCI_JUM_ENA	BIT_23	/* Enable  PCI Jumbo Mode (Yukon-EC Ultra) */
+#define TX_PCI_JUM_DIS	BIT_22	/* Disable PCI Jumbo Mode (Yukon-EC Ultra) */
+						/* Bits 21..19: reserved */
+#define GMF_WSP_TST_ON	BIT_18	/* Write Shadow Pointer Test On */
+#define GMF_WSP_TST_OFF	BIT_17	/* Write Shadow Pointer Test Off */
+#define GMF_WSP_STEP	BIT_16	/* Write Shadow Pointer Step/Increment */
+						/* Bits 15..8: same as for RX_GMF_CTRL_T */
+						/* Bit 7:	reserved */
+#define GMF_CLI_TX_FU	BIT_6	/* Clear IRQ Tx FIFO Underrun */
+#define GMF_CLI_TX_FC	BIT_5	/* Clear IRQ Tx Frame Complete */
+#define GMF_CLI_TX_PE	BIT_4	/* Clear IRQ Tx Parity Error */
+						/* Bits 3..0: same as for RX_GMF_CTRL_T */
+
+#define GMF_RX_CTRL_DEF		(GMF_OPER_ON | GMF_RX_F_FL_ON)
+#define GMF_TX_CTRL_DEF		GMF_OPER_ON
+
+#define RX_GMF_AF_THR_MIN	0x0c	/* Rx GMAC FIFO Almost Full Thresh. min. */
+#define RX_GMF_FL_THR_DEF	0x0a	/* Rx GMAC FIFO Flush Threshold default */
+
+/*	GMAC_TI_ST_CTRL	 8 bit	Time Stamp Timer Ctrl Reg (YUKON only) */
+							/* Bit 7.. 3:	reserved */
+#define GMT_ST_START	BIT_2S	/* Start Time Stamp Timer */
+#define GMT_ST_STOP		BIT_1S	/* Stop  Time Stamp Timer */
+#define GMT_ST_CLR_IRQ	BIT_0S	/* Clear Time Stamp Timer IRQ */
+
+/*	POLL_CTRL		32 bit	Polling Unit control register (Yukon-2 only) */
+							/* Bit 31.. 6:	reserved */
+#define PC_CLR_IRQ_CHK	BIT_5	/* Clear IRQ Check */
+#define PC_POLL_RQ		BIT_4	/* Poll Request Start */
+#define PC_POLL_OP_ON	BIT_3	/* Operational Mode On */
+#define PC_POLL_OP_OFF	BIT_2	/* Operational Mode Off */
+#define PC_POLL_RST_CLR	BIT_1	/* Clear Polling Unit Reset (Enable) */
+#define PC_POLL_RST_SET	BIT_0	/* Set   Polling Unit Reset */
+
+
+/* The bit definition of the following registers is still missing! */
+/* B28_Y2_SMB_CONFIG		32 bit	ASF SMBus Config Register */
+/* B28_Y2_SMB_CSD_REG		32 bit	ASF SMB Control/Status/Data */
+/* B28_Y2_ASF_IRQ_V_BASE	32 bit	ASF IRQ Vector Base */
+
+/* B28_Y2_ASF_STAT_CMD		32 bit	ASF Status and Command Reg */
+/* This register is used by the host driver software */
+							/* Bit 31.. 5	reserved */
+#define Y2_ASF_OS_PRES	BIT_4S	/* ASF operation system present */
+#define Y2_ASF_RESET	BIT_3S	/* ASF system in reset state */
+#define Y2_ASF_RUNNING	BIT_2S	/* ASF system operational */
+#define Y2_ASF_CLR_HSTI	BIT_1S	/* Clear ASF IRQ */
+#define Y2_ASF_IRQ		BIT_0S	/* Issue an IRQ to ASF system */
+
+#define Y2_ASF_UC_STATE	(3<<2)	/* ASF uC State */
+#define Y2_ASF_CLK_HALT	0		/* ASF system clock stopped */
+
+/* B28_Y2_ASF_HOST_COM	32 bit	ASF Host Communication Reg */
+/* This register is used by the ASF firmware */
+							/* Bit 31.. 2	reserved */
+#define Y2_ASF_CLR_ASFI	BIT_1	/* Clear host IRQ */
+#define Y2_ASF_HOST_IRQ	BIT_0	/* Issue an IRQ to HOST system */
+
+
+/*	STAT_CTRL		32 bit	Status BMU control register (Yukon-2 only) */
+							/* Bit  7.. 5:	reserved */
+#define SC_STAT_CLR_IRQ	BIT_4	/* Status Burst IRQ clear */
+#define SC_STAT_OP_ON	BIT_3	/* Operational Mode On */
+#define SC_STAT_OP_OFF	BIT_2	/* Operational Mode Off */
+#define SC_STAT_RST_CLR	BIT_1	/* Clear Status Unit Reset (Enable) */
+#define SC_STAT_RST_SET	BIT_0	/* Set   Status Unit Reset */
+	
+/*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
+						/* Bits 31.. 8:	reserved */
+#define GMC_H_BURST_ON	BIT_7	/* Half Duplex Burst Mode On */
+#define GMC_H_BURST_OFF	BIT_6	/* Half Duplex Burst Mode Off */
+#define GMC_F_LOOPB_ON	BIT_5	/* FIFO Loopback On */
+#define GMC_F_LOOPB_OFF	BIT_4	/* FIFO Loopback Off */
+#define GMC_PAUSE_ON	BIT_3	/* Pause On */
+#define GMC_PAUSE_OFF	BIT_2	/* Pause Off */
+#define GMC_RST_CLR		BIT_1	/* Clear GMAC Reset */
+#define GMC_RST_SET		BIT_0	/* Set   GMAC Reset */
+
+/*	GPHY_CTRL		32 bit	GPHY Control Reg (YUKON only) */
+						/* Bits 31..29:	reserved */
+#define GPC_SEL_BDT		BIT_28	/* Select Bi-Dir. Transfer for MDC/MDIO */
+#define GPC_INT_POL		BIT_27	/* IRQ Polarity is Active Low */
+#define GPC_75_OHM		BIT_26	/* Use 75 Ohm Termination instead of 50 */
+#define GPC_DIS_FC		BIT_25	/* Disable Automatic Fiber/Copper Detection */
+#define GPC_DIS_SLEEP	BIT_24	/* Disable Energy Detect */
+#define GPC_HWCFG_M_3	BIT_23	/* HWCFG_MODE[3] */
+#define GPC_HWCFG_M_2	BIT_22	/* HWCFG_MODE[2] */
+#define GPC_HWCFG_M_1	BIT_21	/* HWCFG_MODE[1] */
+#define GPC_HWCFG_M_0	BIT_20	/* HWCFG_MODE[0] */
+#define GPC_ANEG_0		BIT_19	/* ANEG[0] */
+#define GPC_ENA_XC		BIT_18	/* Enable MDI crossover */
+#define GPC_DIS_125		BIT_17	/* Disable 125 MHz clock */
+#define GPC_ANEG_3		BIT_16	/* ANEG[3] */
+#define GPC_ANEG_2		BIT_15	/* ANEG[2] */
+#define GPC_ANEG_1		BIT_14	/* ANEG[1] */
+#define GPC_ENA_PAUSE	BIT_13	/* Enable Pause (SYM_OR_REM) */
+#define GPC_PHYADDR_4	BIT_12	/* Bit 4 of PHY Addr */
+#define GPC_PHYADDR_3	BIT_11	/* Bit 3 of PHY Addr */
+#define GPC_PHYADDR_2	BIT_10	/* Bit 2 of PHY Addr */
+#define GPC_PHYADDR_1	BIT_9	/* Bit 1 of PHY Addr */
+#define GPC_PHYADDR_0	BIT_8	/* Bit 0 of PHY Addr */
+						/* Bits  7..2:	reserved */
+#define GPC_RST_CLR		BIT_1	/* Clear GPHY Reset */
+#define GPC_RST_SET		BIT_0	/* Set   GPHY Reset */
+
+/* Yukon-EC Ultra only */
+#define GPC_LED_CONF_MSK	(7<<6)	/* Bit 8.. 6:	GPHY LED Config */
+#define GPC_PD_125M_CLK_OFF	BIT_5	/* Disable Power Down Clock 125 MHz */
+#define GPC_PD_125M_CLK_ON	BIT_4	/* Enable  Power Down Clock 125 MHz */
+#define GPC_DPLL_RST_SET	BIT_3	/* Set   GPHY's DPLL Reset */
+#define GPC_DPLL_RST_CLR	BIT_2	/* Clear GPHY's DPLL Reset */
+									/* (DPLL = Digital Phase Lock Loop) */
+#define GPC_LED_CONF_VAL(x)	(SHIFT6(x) & GPC_LED_CONF_MSK)
+
+#define GPC_HWCFG_GMII_COP	(GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \
+							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+
+#define GPC_HWCFG_GMII_FIB	(				 GPC_HWCFG_M_2 | \
+							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+
+#define GPC_ANEG_ADV_ALL_M	(GPC_ANEG_3 | GPC_ANEG_2 | \
+							 GPC_ANEG_1 | GPC_ANEG_0)
+
+/* forced speed and duplex mode (don't mix with other ANEG bits) */
+#define GPC_FRC10MBIT_HALF	0
+#define GPC_FRC10MBIT_FULL	GPC_ANEG_0
+#define GPC_FRC100MBIT_HALF	GPC_ANEG_1
+#define GPC_FRC100MBIT_FULL	(GPC_ANEG_0 | GPC_ANEG_1)
+
+/* auto-negotiation with limited advertised speeds */
+/* mix only with master/slave settings (for copper) */
+#define GPC_ADV_1000_HALF	GPC_ANEG_2
+#define GPC_ADV_1000_FULL	GPC_ANEG_3
+#define GPC_ADV_ALL			(GPC_ANEG_2 | GPC_ANEG_3)
+
+/* master/slave settings */
+/* only for copper with 1000 Mbps */
+#define GPC_FORCE_MASTER	0
+#define GPC_FORCE_SLAVE		GPC_ANEG_0
+#define GPC_PREF_MASTER		GPC_ANEG_1
+#define GPC_PREF_SLAVE		(GPC_ANEG_1 | GPC_ANEG_0)
+
+/*	GMAC_IRQ_SRC	 8 bit	GMAC Interrupt Source Reg (YUKON only) */
+/*	GMAC_IRQ_MSK	 8 bit	GMAC Interrupt Mask   Reg (YUKON only) */
+#define GM_IS_RX_CO_OV	BIT_5S		/* Receive Counter Overflow IRQ */
+#define GM_IS_TX_CO_OV	BIT_4S		/* Transmit Counter Overflow IRQ */
+#define GM_IS_TX_FF_UR	BIT_3S		/* Transmit FIFO Underrun */
+#define GM_IS_TX_COMPL	BIT_2S		/* Frame Transmission Complete */
+#define GM_IS_RX_FF_OR	BIT_1S		/* Receive FIFO Overrun */
+#define GM_IS_RX_COMPL	BIT_0S		/* Frame Reception Complete */
+
+#define GMAC_DEF_MSK	(GM_IS_RX_CO_OV | GM_IS_TX_CO_OV | \
+						GM_IS_TX_FF_UR)
+
+/*	GMAC_LINK_CTRL	16 bit	Link Control Reg (YUKON only) */
+						/* Bits 15.. 2:	reserved */
+#define GMLC_RST_CLR	BIT_1S		/* Clear Link Reset */
+#define GMLC_RST_SET	BIT_0S		/* Set   Link Reset */
+
+
+/*	WOL_CTRL_STAT	16 bit	WOL Control/Status Reg */
+#define WOL_CTL_LINK_CHG_OCC			BIT_15S
+#define WOL_CTL_MAGIC_PKT_OCC			BIT_14S
+#define WOL_CTL_PATTERN_OCC				BIT_13S
+
+#define WOL_CTL_CLEAR_RESULT			BIT_12S
+
+#define WOL_CTL_ENA_PME_ON_LINK_CHG		BIT_11S
+#define WOL_CTL_DIS_PME_ON_LINK_CHG		BIT_10S
+#define WOL_CTL_ENA_PME_ON_MAGIC_PKT	BIT_9S
+#define WOL_CTL_DIS_PME_ON_MAGIC_PKT	BIT_8S
+#define WOL_CTL_ENA_PME_ON_PATTERN		BIT_7S
+#define WOL_CTL_DIS_PME_ON_PATTERN		BIT_6S
+
+#define WOL_CTL_ENA_LINK_CHG_UNIT		BIT_5S
+#define WOL_CTL_DIS_LINK_CHG_UNIT		BIT_4S
+#define WOL_CTL_ENA_MAGIC_PKT_UNIT		BIT_3S
+#define WOL_CTL_DIS_MAGIC_PKT_UNIT		BIT_2S
+#define WOL_CTL_ENA_PATTERN_UNIT		BIT_1S
+#define WOL_CTL_DIS_PATTERN_UNIT		BIT_0S
+
+#define WOL_CTL_DEFAULT				\
+	(WOL_CTL_DIS_PME_ON_LINK_CHG |	\
+	 WOL_CTL_DIS_PME_ON_PATTERN |	\
+	 WOL_CTL_DIS_PME_ON_MAGIC_PKT |	\
+	 WOL_CTL_DIS_LINK_CHG_UNIT |	\
+	 WOL_CTL_DIS_PATTERN_UNIT |		\
+	 WOL_CTL_DIS_MAGIC_PKT_UNIT)
+
+/*	WOL_MATCH_CTL	 8 bit	WOL Match Control Reg */
+#define WOL_CTL_PATT_ENA(x)				(BIT_0 << (x))
+
+/*	WOL_PATT_PME	8 bit	WOL PME Match Enable (Yukon-2) */
+#define WOL_PATT_FORCE_PME				BIT_7	/* Generates a PME */
+#define WOL_PATT_MATCH_PME_ALL			0x7f
+
+#define SK_NUM_WOL_PATTERN		7
+#define SK_NUM_WOL_PATTERN_EX	9
+#define SK_NUM_WOL_PATTERN_FEP	6
+#define SK_PATTERN_PER_WORD		4
+#define SK_BITMASK_PATTERN		7
+#define SK_POW_PATTERN_LENGTH	128
+
+#define SK_WOL_PATT_LO_MSK_EX	0x0000ffffUL
+#define SK_WOL_PATT_HI_MSK_EX	0x03000000UL
+
+#define WOL_LENGTH_MSK		0x7f
+#define WOL_LENGTH_SHIFT	8
+
+
+/* typedefs ******************************************************************/
+
+/* Receive and Transmit Descriptors ******************************************/
+
+/* Transmit Descriptor struct */
+typedef	struct s_HwTxd {
+	SK_U32 volatile	TxCtrl;	/* Transmit Buffer Control Field */
+	SK_U32	TxNext;			/* Physical Address Pointer to the next TxD */
+	SK_U32	TxAdrLo;		/* Physical Tx Buffer Address lower DWord */
+	SK_U32	TxAdrHi;		/* Physical Tx Buffer Address upper DWord */
+	SK_U32	TxStat;			/* Transmit Frame Status Word */
+#ifndef SK_USE_REV_DESC
+	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
+	SK_U16	TxRes1;			/* 16 bit reserved field */
+	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
+	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
+#else  /* SK_USE_REV_DESC */
+	SK_U16	TxRes1;			/* 16 bit reserved field */
+	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
+	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
+	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
+#endif /* SK_USE_REV_DESC */
+	SK_U32  TxRes2;			/* 32 bit reserved field */
+} SK_HWTXD;
+
+/* Receive Descriptor struct */
+typedef	struct s_HwRxd {
+	SK_U32 volatile RxCtrl;	/* Receive Buffer Control Field */
+	SK_U32	RxNext;			/* Physical Address Pointer to the next RxD */
+	SK_U32	RxAdrLo;		/* Physical Rx Buffer Address lower DWord */
+	SK_U32	RxAdrHi;		/* Physical Rx Buffer Address upper DWord */
+	SK_U32	RxStat;			/* Receive Frame Status Word */
+	SK_U32	RxTiSt;			/* Receive Time Stamp (from XMAC on GENESIS) */
+#ifndef SK_USE_REV_DESC
+	SK_U16	RxTcpSum1;		/* Rx TCP Checksum 1 */
+	SK_U16	RxTcpSum2;		/* Rx TCP Checksum 2 */
+	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
+	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
+#else  /* SK_USE_REV_DESC */
+	SK_U16	RxTcpSum2;		/* Rx TCP Checksum 2 */
+	SK_U16	RxTcpSum1;		/* Rx TCP Checksum 1 */
+	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
+	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
+#endif /* SK_USE_REV_DESC */
+} SK_HWRXD;
+
+/*
+ * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
+ * should set the define SK_USE_REV_DESC.
+ * Structures are 'normally' not endianess dependent. But in this case
+ * the SK_U16 fields are bound to bit positions inside the descriptor.
+ * RxTcpSum1 e.g. must start at bit 0 within the 7.th DWord.
+ * The bit positions inside a DWord are of course endianess dependent and
+ * swap if the DWord is swapped by the hardware.
+ */
+
+/* YUKON-2 descriptors ******************************************************/
+
+typedef struct _TxMss {		/* Yukon-Extreme only */
+#ifndef SK_USE_REV_DESC
+	SK_U16	TxMssVal;		/* MSS value */
+	SK_U16	reserved;		/* reserved */
+#else  /* SK_USE_REV_DESC */
+	SK_U16	reserved;		/* TCP Checksum Calculation Start Position */
+	SK_U16	TxMssVal;		/* MSS value */
+#endif /* SK_USE_REV_DESC */
+} SK_HWTXMSS;
+
+typedef struct _TxChksum {
+#ifndef SK_USE_REV_DESC
+	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
+	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
+#else  /* SK_USE_REV_DESC */
+	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
+	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
+#endif /* SK_USE_REV_DESC */
+} SK_HWTXCS;
+
+typedef struct _LargeSend {
+#ifndef SK_USE_REV_DESC
+	SK_U16 Length;		/* Large Send Segment Length */
+	SK_U16 Reserved;	/* reserved */
+#else  /* SK_USE_REV_DESC */
+	SK_U16 Reserved;	/* reserved */
+	SK_U16 Length;		/* Large Send Segment Length */
+#endif /* SK_USE_REV_DESC */
+} SK_HWTXLS;
+
+typedef union u_HwTxBuf {
+	SK_U16	BufLen;		/* Tx Buffer Length */
+	SK_U16	VlanTag;	/* VLAN Tag */
+	SK_U16	InitCsum;	/* Init. Checksum */
+} SK_HWTXBUF;
+
+/* Tx List Element structure */
+typedef struct s_HwLeTx {
+	union {
+		SK_U32	BufAddr;	/* Tx LE Buffer Address high/low */
+		SK_U32	LsoV2Len;	/* Total lenght of LSOv2 packet */
+		SK_HWTXCS	ChkSum;	/* Tx LE TCP Checksum parameters */
+		SK_HWTXLS	LargeSend;/* Large Send length */
+		SK_HWTXMSS	Mss;	/* MSS value; Yukon-Extreme only */
+	} TxUn;
+#ifndef SK_USE_REV_DESC
+	SK_HWTXBUF	Send;
+	SK_U8	ControlFlags;	/* Tx LE Control field or Lock Number */
+	SK_U8	Opcode;			/* Tx LE Opcode field */
+#else  /* SK_USE_REV_DESC */
+	SK_U8	Opcode;			/* Tx LE Opcode field */
+	SK_U8	ControlFlags;	/* Tx LE Control field or Lock Number */
+	SK_HWTXBUF	Send;
+#endif /* SK_USE_REV_DESC */
+} SK_HWLETX;
+
+typedef struct _RxChkSum{
+#ifndef SK_USE_REV_DESC
+	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
+	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
+#else  /* SK_USE_REV_DESC */
+	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
+	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
+#endif /* SK_USE_REV_DESC */
+} SK_HWRXCS;
+
+/* Rx List Element structure */
+typedef struct s_HwLeRx {
+	union {
+		SK_U32	BufAddr;	/* Rx LE Buffer Address high/low */
+		SK_HWRXCS ChkSum;	/* Rx LE TCP Checksum parameters */
+	} RxUn;
+#ifndef SK_USE_REV_DESC
+	SK_U16	BufferLength;	/* Rx LE Buffer Length field */
+	SK_U8	ControlFlags;	/* Rx LE Control field */
+	SK_U8	Opcode;			/* Rx LE Opcode field */
+#else  /* SK_USE_REV_DESC */
+	SK_U8	Opcode;			/* Rx LE Opcode field */
+	SK_U8	ControlFlags;	/* Rx LE Control field */
+	SK_U16	BufferLength;	/* Rx LE Buffer Length field */
+#endif /* SK_USE_REV_DESC */
+} SK_HWLERX;
+
+typedef struct s_StRxTCPChkSum {
+#ifndef SK_USE_REV_DESC
+	SK_U16	RxTCPSum1;		/* Rx TCP Checksum 1 */
+	SK_U16	RxTCPSum2;		/* Rx TCP Checksum 2 */
+#else  /* SK_USE_REV_DESC */
+	SK_U16	RxTCPSum2;		/* Rx TCP Checksum 2 */
+	SK_U16	RxTCPSum1;		/* Rx TCP Checksum 1 */
+#endif /* SK_USE_REV_DESC */
+} SK_HWSTCS;
+
+typedef struct s_StRxRssFlags {
+#ifndef SK_USE_REV_DESC
+	SK_U8	FlagField;		/* contains TCP and IP flags */
+	SK_U8	reserved;		/* reserved */
+#else  /* SK_USE_REV_DESC */
+	SK_U8	reserved;		/* reserved */
+	SK_U8	FlagField;		/* contains TCP and IP flags */
+#endif /* SK_USE_REV_DESC */
+} SK_HWSTRSS;
+
+/* bit definition of MAC Sec Rx Status	(SK_HWLEST.StMacSecWord)	*/
+/*										(Yukon-Ext only)			*/
+									/* bit 31..10 reserved */
+#define MS_AUTH_RES_MSK	(0xf<<6)	/* MAC Sec, encoded auth. result info */
+									/* see figure 10-5 in 802.1AE spec */
+#define MS_ENCRYPT_ENA	BIT_5		/* MAC Sec, encryption enabled */
+#define MS_AUTHENT_ENA	BIT_4		/* MAC Sec, authentication enabled */
+#define MS_LKUP_NUM_MSK	(3<<1)		/* MAC Sec, lookup entry number mask */
+									/* Info needed 0 = Bypass etc... TBD XXX */
+#define MS_LKUP_TAB_HIT	BIT_0		/* MAC Sec, lookup table hit */
+
+/* bit definition of RSS LE bit 32/33 (SK_HWSTRSS.FlagField) */
+								/* bit 7..3 reserved */
+#define RSS_CALC_HASH_TCP_IPV6_EX_FLAG	BIT_8S	/* Yukon-Extreme B0 */
+#define RSS_CALC_HASH_IPV6_EX_FLAG		BIT_7S	/* Yukon-Extreme B0 */
+#define RSS_CALC_HASH_TCP_IPV6_FLAG		BIT_6S	/* Yukon-Extreme B0 */
+#define RSS_CALC_HASH_IPV6_FLAG			BIT_5S	/* Yukon-Extreme B0 */
+#define RSS_CALC_HASH_TCP_IPV4_FLAG		BIT_4S	/* Yukon-Extreme B0 */
+#define RSS_CALC_HASH_IPV4_FLAG			BIT_3S	/* Yukon-Extreme B0 */
+#define RSS_IPV6_FLAG	BIT_2S	/* RSS value related to IP V6 (Yukon-Ext only)*/
+#define RSS_TCP_FLAG	BIT_1S	/* RSS value related to TCP area */
+#define RSS_IP_FLAG		BIT_0S	/* RSS value related to IP area */
+/* StRxRssValue is valid if at least RSS_IP_FLAG is set */
+/* For protocol errors or other protocols an empty RSS LE is generated */
+
+typedef union u_HwStBuf {
+	SK_U16	BufLen;		/* Rx Buffer Length */
+	SK_U16	VlanTag;	/* VLAN Tag */
+	SK_U16	StTxStatHi;	/* Tx Queue Status (high) */
+	SK_HWSTRSS	Rss;	/* Flag Field for TCP and IP protocol */
+} SK_HWSTBUF;
+
+/* Status List Element structure */
+typedef struct s_HwLeSt {
+	union {
+		SK_U32	StRxStatWord;	/* Rx Status Dword */
+		SK_U32	StRxTimeStamp;	/* Rx Timestamp */
+		SK_HWSTCS StRxTCPCSum;	/* Rx TCP Checksum */
+		SK_U32	StTxStatLow;	/* Tx Queue Status (low) */
+		SK_U32	StRxRssValue;	/* Rx RSS value */
+		SK_U32	StMacSecWord;	/* Rx MAC Sec Satus Word (Yukon-Ext only) */
+	} StUn;
+#ifndef SK_USE_REV_DESC
+	SK_HWSTBUF	Stat;
+	SK_U8	Link;			/* Status LE Link field (& Csum Stat for Yukon-Ext)*/
+	SK_U8	Opcode;			/* Status LE Opcode field */
+#else  /* SK_USE_REV_DESC */
+	SK_U8	Opcode;			/* Status LE Opcode field */
+	SK_U8	Link;			/* Status LE Link field (& Csum Stat for Yukon-Ext)*/
+	SK_HWSTBUF	Stat;
+#endif /* SK_USE_REV_DESC */
+} SK_HWLEST;
+
+/* Special Action List Element */
+typedef struct s_HwLeSa {
+#ifndef SK_USE_REV_DESC
+	SK_U16	TxAIdxVld;		/* Special Action LE TxA Put Index field */
+	SK_U16	TxSIdxVld;		/* Special Action LE TxS Put Index field */
+	SK_U16	RxIdxVld;		/* Special Action LE Rx Put Index field */
+	SK_U8	Link;			/* Special Action LE Link field */
+	SK_U8	Opcode;			/* Special Action LE Opcode field */
+#else  /* SK_USE_REV_DESC */
+	SK_U16	TxSIdxVld;		/* Special Action LE TxS Put Index field */
+	SK_U16	TxAIdxVld;		/* Special Action LE TxA Put Index field */
+	SK_U8	Opcode;			/* Special Action LE Opcode field */
+	SK_U8	Link;			/* Special Action LE Link field */
+	SK_U16	RxIdxVld;		/* Special Action LE Rx Put Index field */
+#endif /* SK_USE_REV_DESC */
+} SK_HWLESA;
+
+/* Common List Element union */
+typedef union u_HwLeTxRxSt {
+	/* Transmit List Element Structure */
+	SK_HWLETX Tx;
+	/* Receive List Element Structure */
+	SK_HWLERX Rx;
+	/* Status List Element Structure */
+	SK_HWLEST St;
+	/* Special Action List Element Structure */
+	SK_HWLESA Sa;
+	/* Full List Element */
+	SK_U64 Full;
+} SK_HWLE;
+
+#define MAX_LARGE_SEND_LEN	0xffff
+
+/* mask and shift value to get Tx async queue status for port 1 */
+#define STLE_TXA1_MSKL		0x00000fff
+#define STLE_TXA1_SHIFTL	0
+
+/* mask and shift value to get Tx sync queue status for port 1 */
+#define STLE_TXS1_MSKL		0x00fff000
+#define STLE_TXS1_SHIFTL	12
+
+/* mask and shift value to get Tx async queue status for port 2 */
+#define STLE_TXA2_MSKL		0xff000000
+#define STLE_TXA2_SHIFTL	24
+#define STLE_TXA2_MSKH		0x000f
+/* this one shifts up */
+#define STLE_TXA2_SHIFTH	8
+
+/* mask and shift value to get Tx sync queue status for port 2 */
+#define STLE_TXS2_MSKL		0x00000000
+#define STLE_TXS2_SHIFTL	0
+#define STLE_TXS2_MSKH		0xfff0
+#define STLE_TXS2_SHIFTH	4
+
+/* YUKON-2 bit values */
+#define HW_OWNER		BIT_7
+#define SW_OWNER		0
+
+#define PU_PUTIDX_VALID		BIT_12
+
+/* YUKON-2 Control flags */
+#define UDPTCP			BIT_0S
+#define CALSUM			BIT_1S
+#define WR_SUM			BIT_2S
+#define INIT_SUM		BIT_3S
+#define LOCK_SUM		BIT_4S
+#define INS_VLAN		BIT_5S
+#define FRC_STAT		BIT_6S
+#define	MACSEC			BIT_6S	/* Yukon-Ext only */
+#define EOP				BIT_7S
+
+#define TX_LOCK			BIT_8S
+#define BUF_SEND		BIT_9S
+#define PACKET_SEND		BIT_10S
+
+#define NO_WARNING		BIT_14S
+#define NO_UPDATE		BIT_15S
+
+#define CALSUM_TL 		BIT_1S	/* Yukon-Ext only */
+#define CALSUM_IP 		BIT_0S	/* Yukon-Ext only */
+
+/* Yukon-Ext CSum Status defines (Rx Status, Link field) */
+#define CSS_TCPUDPCSOK	BIT_7S	/* TCP / UDP checksum is ok */
+#define CSS_ISUDP		BIT_6S	/* packet is a UDP packet */
+#define CSS_ISTCP		BIT_5S	/* packet is a TCP packet */
+#define CSS_ISIPFRAG	BIT_4S	/* packet is a TCP/UDP frag, CS calc not done */
+#define CSS_ISIPV6		BIT_3S	/* packet is a IPv6 packet */
+#define CSS_IPV4CSUMOK	BIT_2S	/* IP v4: TCP header checksum is ok */
+#define CSS_ISIPV4		BIT_1S	/* packet is a IPv4 packet */
+#define CSS_LINK_BIT	BIT_0S	/* port number (legacy) */
+
+
+/* YUKON-2 Rx/Tx opcodes defines */
+#define OP_TCPWRITE		0x11
+#define OP_TCPSTART		0x12
+#define OP_TCPINIT		0x14
+#define OP_TCPLCK		0x18
+#define OP_TCPCHKSUM	OP_TCPSTART
+#define OP_TCPIS		(OP_TCPINIT | OP_TCPSTART)
+#define OP_TCPLW		(OP_TCPLCK | OP_TCPWRITE)
+#define OP_TCPLSW		(OP_TCPLCK | OP_TCPSTART | OP_TCPWRITE)
+#define OP_TCPLISW		(OP_TCPLCK | OP_TCPINIT | OP_TCPSTART | OP_TCPWRITE)
+#define OP_ADDR64		0x21
+#define OP_VLAN		0x22
+#define OP_ADDR64VLAN	(OP_ADDR64 | OP_VLAN)
+#define OP_LRGLEN		0x24							/* not Yukon-Ext */
+#define OP_LRGLENVLAN	(OP_LRGLEN | OP_VLAN)			/* not Yukon-Ext */
+#define OP_MSS			0x28							/* Yukon-Ext only */
+#define OP_MSSVLAN		(OP_MSS | OP_VLAN)				/* Yukon-Ext only */
+#define OP_BUFFER		0x40
+#define OP_PACKET		0x41
+#define OP_LARGESEND	0x43
+#define OP_LSOV2		0x45							/* Yukon Ext only */
+
+
+/* YUKON-2 STATUS opcodes defines */
+#define OP_RXSTAT		0x60
+#define OP_RXTIMESTAMP	0x61
+#define OP_RXVLAN		0x62
+#define OP_RXCHKS		0x64
+#define OP_RXCHKSVLAN	(OP_RXCHKS | OP_RXVLAN)
+#define OP_RXTIMEVLAN	(OP_RXTIMESTAMP | OP_RXVLAN)
+#define OP_RSS_HASH		0x65
+#define OP_TXINDEXLE	0x68
+#define OP_MACSEC		0x6c							/* Yukon-Ext only */
+#define OP_MACSECVLAN	(OP_MACSEC | OP_RXVLAN)			/* Yukon-Ext only */
+
+/* YUKON-2 SPECIAL opcodes defines */
+#define OP_PUTIDX	0x70
+
+/* Descriptor Bit Definition */
+/*	TxCtrl		Transmit Buffer Control Field */
+/*	RxCtrl		Receive  Buffer Control Field */
+#define BMU_OWN			BIT_31	/* OWN bit: 0=host/1=BMU */
+#define BMU_STF			BIT_30	/* Start of Frame */
+#define BMU_EOF			BIT_29	/* End of Frame */
+#define BMU_IRQ_EOB		BIT_28	/* Req "End of Buffer" IRQ */
+#define BMU_IRQ_EOF		BIT_27	/* Req "End of Frame" IRQ */
+/* TxCtrl specific bits */
+#define BMU_STFWD		BIT_26	/* (Tx)	Store & Forward Frame */
+#define BMU_NO_FCS		BIT_25	/* (Tx) Disable MAC FCS (CRC) generation */
+#define BMU_SW			BIT_24	/* (Tx)	1 bit res. for SW use */
+/* RxCtrl specific bits */
+#define BMU_DEV_0		BIT_26	/* (Rx)	Transfer data to Dev0 */
+#define BMU_STAT_VAL	BIT_25	/* (Rx)	Rx Status Valid */
+#define BMU_TIST_VAL	BIT_24	/* (Rx)	Rx TimeStamp Valid */
+								/* Bit 23..16:	BMU Check Opcodes */
+#define BMU_CHECK		(0x55L<<16)	/* Default BMU check */
+#define BMU_TCP_CHECK	(0x56L<<16)	/* Descr with TCP ext */
+#define BMU_UDP_CHECK	(0x57L<<16)	/* Descr with UDP ext (YUKON only) */
+#define BMU_BBC			0xffffL	/* Bit 15.. 0:	Buffer Byte Counter */
+
+/*	TxStat		Transmit Frame Status Word */
+/*	RxStat		Receive Frame Status Word */
+/*
+ *Note: TxStat is reserved for ASIC loopback mode only
+ *
+ *	The Bits of the Status words are defined in xmac_ii.h
+ *	(see XMR_FS bits)
+ */
+
+/* macros ********************************************************************/
+
+/* Macro for accessing the key registers */
+#define RSS_KEY_ADDR(Port, KeyIndex)	\
+		((B4_RSS_KEY | ( ((Port) == 0) ? 0 : 0x80)) + (KeyIndex))
+
+/* Receive and Transmit Queues */
+#define Q_R1	0x0000		/* Receive Queue 1 */
+#define Q_R2	0x0080		/* Receive Queue 2 */
+#define Q_XS1	0x0200		/* Synchronous Transmit Queue 1 */
+#define Q_XA1	0x0280		/* Asynchronous Transmit Queue 1 */
+#define Q_XS2	0x0300		/* Synchronous Transmit Queue 2 */
+#define Q_XA2	0x0380		/* Asynchronous Transmit Queue 2 */
+
+#define Q_ASF_R1	0x100	/* ASF Rx Queue 1 */
+#define Q_ASF_R2	0x180	/* ASF Rx Queue 2 */
+#define Q_ASF_T1	0x140	/* ASF Tx Queue 1 */
+#define Q_ASF_T2	0x1c0	/* ASF Tx Queue 2 */
+/*
+ *	Macro Q_ADDR()
+ *
+ *	Use this macro to access the Receive and Transmit Queue Registers.
+ *
+ * para:
+ *	Queue	Queue to access.
+ *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
+ *	Offs	Queue register offset.
+ *				Values: Q_D, Q_DA_L ... Q_T2, Q_T3
+ *
+ * usage	SK_IN32(IoC, Q_ADDR(Q_R2, Q_BC), pVal)
+ */
+#define Q_ADDR(Queue, Offs)	(B8_Q_REGS + (Queue) + (Offs))
+
+/*
+ *	Macro Y2_PREF_Q_ADDR()
+ *
+ *	Use this macro to access the Prefetch Units of the receive and
+ *	transmit queues of Yukon-2.
+ *
+ * para:	
+ *	Queue	Queue to access.
+ *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, Q_XA2,
+ *	Offs	Queue register offset.
+ *				Values: PREF_UNIT_CTRL_REG ... PREF_UNIT_FIFO_LEV_REG
+ *
+ * usage	SK_IN16(IoC, Y2_Q_ADDR(Q_R2, PREF_UNIT_GET_IDX_REG), pVal)
+ */
+#define Y2_PREF_Q_ADDR(Queue, Offs)	(Y2_B8_PREF_REGS + (Queue) + (Offs))
+
+/*
+ *	Macro RB_ADDR()
+ *
+ *	Use this macro to access the RAM Buffer Registers.
+ *
+ * para:
+ *	Queue	Queue to access.
+ *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
+ *	Offs	Queue register offset.
+ *				Values: RB_START, RB_END ... RB_LEV, RB_CTRL
+ *
+ * usage	SK_IN32(IoC, RB_ADDR(Q_R2, RB_RP), pVal)
+ */
+#define RB_ADDR(Queue, Offs)	(B16_RAM_REGS + (Queue) + (Offs))
+
+
+/* MAC Related Registers */
+#define MAC_1		0	/* 1st port */
+#define MAC_2		1	/* 2nd port */
+
+/*
+ *	Macro MR_ADDR()
+ *
+ *	Use this macro to access a MAC Related Registers inside the ASIC.
+ *
+ * para:
+ *	Mac		MAC to access.
+ *				Values: MAC_1, MAC_2
+ *	Offs	MAC register offset.
+ *				Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
+ *						TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
+ *
+ * usage	SK_IN32(IoC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
+ */
+#define MR_ADDR(Mac, Offs)	(((Mac) << 7) + (Offs))
+
+/*
+ * macros to access the XMAC (GENESIS only)
+ *
+ * XM_IN16(),		to read a 16 bit register (e.g. XM_MMU_CMD)
+ * XM_OUT16(),		to write a 16 bit register (e.g. XM_MMU_CMD)
+ * XM_IN32(),		to read a 32 bit register (e.g. XM_TX_EV_CNT)
+ * XM_OUT32(),		to write a 32 bit register (e.g. XM_TX_EV_CNT)
+ * XM_INADDR(),		to read a network address register (e.g. XM_SRC_CHK)
+ * XM_OUTADDR(),	to write a network address register (e.g. XM_SRC_CHK)
+ * XM_INHASH(),		to read the XM_HSM_CHK register
+ * XM_OUTHASH()		to write the XM_HSM_CHK register
+ *
+ * para:
+ *	Mac		XMAC to access		values: MAC_1 or MAC_2
+ *	IoC		I/O context needed for SK I/O macros
+ *	Reg		XMAC Register to read or write
+ *	(p)Val	Value or pointer to the value which should be read or written
+ *
+ * usage:	XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value);
+ */
+
+#define XMA(Mac, Reg)									\
+	((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
+
+#define XM_IN16(IoC, Mac, Reg, pVal)	\
+	SK_IN16(IoC, XMA(Mac, Reg), pVal)
+
+#define XM_OUT16(IoC, Mac, Reg, Val)	\
+	SK_OUT16(IoC, XMA(Mac, Reg), Val)
+
+#ifdef SK_LITTLE_ENDIAN
+
+#define XM_IN32(IoC, Mac, Reg, pVal) {								\
+	SK_IN16(IoC, XMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal));			\
+	SK_IN16(IoC, XMA(Mac, (Reg) + 2), (SK_U16 SK_FAR *)(pVal) + 1);	\
+}
+
+#else  /* !SK_LITTLE_ENDIAN */
+
+#define XM_IN32(IoC, Mac, Reg, pVal) {							\
+	SK_IN16(IoC, XMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal) + 1);	\
+	SK_IN16(IoC, XMA(Mac, (Reg) + 2), (SK_U16 SK_FAR *)(pVal));	\
+}
+
+#endif /* !SK_LITTLE_ENDIAN */
+
+#define XM_OUT32(IoC, Mac, Reg, Val) {										\
+	SK_OUT16(IoC, XMA(Mac, Reg), (SK_U16)((Val) & 0xffffL));				\
+	SK_OUT16(IoC, XMA(Mac, (Reg) + 2), (SK_U16)(((Val) >> 16) & 0xffffL));	\
+}
+
+/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
+
+#define XM_INADDR(IoC, Mac, Reg, pVal) {				\
+	SK_U16	Word;										\
+	SK_U8	*pByte;										\
+	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
+	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
+	pByte[0] = (SK_U8)(Word & 0x00ff);					\
+	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN16((IoC), XMA((Mac), (Reg) + 2), &Word);		\
+	pByte[2] = (SK_U8)(Word & 0x00ff);					\
+	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN16((IoC), XMA((Mac), (Reg) + 4), &Word);		\
+	pByte[4] = (SK_U8)(Word & 0x00ff);					\
+	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
+}
+
+#define XM_OUTADDR(IoC, Mac, Reg, pVal) {				\
+	SK_U8	SK_FAR *pByte;								\
+	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
+	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
+		(((SK_U16)(pByte[0]) & 0x00ff) |				\
+		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), XMA((Mac), (Reg) + 2), (SK_U16)		\
+		(((SK_U16)(pByte[2]) & 0x00ff) |				\
+		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), XMA((Mac), (Reg) + 4), (SK_U16)		\
+		(((SK_U16)(pByte[4]) & 0x00ff) |				\
+		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
+}
+
+#define XM_INHASH(IoC, Mac, Reg, pVal) {				\
+	SK_U16	Word;										\
+	SK_U8	SK_FAR *pByte;								\
+	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
+	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
+	pByte[0] = (SK_U8)(Word & 0x00ff);					\
+	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN16((IoC), XMA((Mac), (Reg) + 2), &Word);		\
+	pByte[2] = (SK_U8)(Word & 0x00ff);					\
+	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN16((IoC), XMA((Mac), (Reg) + 4), &Word);		\
+	pByte[4] = (SK_U8)(Word & 0x00ff);					\
+	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN16((IoC), XMA((Mac), (Reg) + 6), &Word);		\
+	pByte[6] = (SK_U8)(Word & 0x00ff);					\
+	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
+}
+
+#define XM_OUTHASH(IoC, Mac, Reg, pVal) {				\
+	SK_U8	SK_FAR *pByte;								\
+	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
+	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
+		(((SK_U16)(pByte[0]) & 0x00ff)|					\
+		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), XMA((Mac), (Reg) + 2), (SK_U16)		\
+		(((SK_U16)(pByte[2]) & 0x00ff)|					\
+		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), XMA((Mac), (Reg) + 4), (SK_U16)		\
+		(((SK_U16)(pByte[4]) & 0x00ff)|					\
+		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), XMA((Mac), (Reg) + 6), (SK_U16)		\
+		(((SK_U16)(pByte[6]) & 0x00ff)|					\
+		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
+}
+
+/*
+ * macros to access the GMAC (YUKON only)
+ *
+ * GM_IN16(),		to read  a 16 bit register (e.g. GM_GP_STAT)
+ * GM_OUT16(),		to write a 16 bit register (e.g. GM_GP_CTRL)
+ * GM_IN32(),		to read  a 32 bit register (e.g. GM_RXF_UC_OK)
+ * GM_OUT32(),		to write a 32 bit register
+ * GM_INADDR(),		to read  a network address register (e.g. GM_SRC_ADDR_1L)
+ * GM_OUTADDR(),	to write a network address register (e.g. GM_SRC_ADDR_2L)
+ * GM_INHASH(),		to read  the hash registers (e.g. GM_MC_ADDR_H1..4)
+ * GM_OUTHASH()		to write the hash registers (e.g. GM_MC_ADDR_H1..4)
+ *
+ * para:
+ *	Mac		GMAC to access		values: MAC_1 or MAC_2
+ *	IoC		I/O context needed for SK I/O macros
+ *	Reg		GMAC Register to read or write
+ *	(p)Val	Value or pointer to the value which should be read or written
+ *
+ * usage:	GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value);
+ */
+
+#define GMA(Mac, Reg)									\
+	((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
+
+#define GM_IN16(IoC, Mac, Reg, pVal) {			\
+	SK_U8	Dummy;								\
+	SK_ACQ_SPIN_LOCK(IoC);						\
+	SK_IN16(IoC, GMA(Mac, Reg), pVal);			\
+	SK_IN8(IoC, B0_RAP, &Dummy);				\
+	SK_REL_SPIN_LOCK(IoC);						\
+}
+
+#define GM_OUT16(IoC, Mac, Reg, Val)	\
+	SK_OUT16(IoC, GMA(Mac, Reg), Val)
+
+#ifdef SK_LITTLE_ENDIAN
+
+#define GM_IN32(IoC, Mac, Reg, pVal) {									\
+	SK_U8	Dummy;														\
+	SK_ACQ_SPIN_LOCK(IoC);												\
+	SK_IN16(IoC, GMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal));				\
+	SK_IN16((IoC), GMA(Mac, (Reg) + 4), (SK_U16 SK_FAR *)(pVal) + 1);	\
+	SK_IN8(IoC, B0_RAP, &Dummy);										\
+	SK_REL_SPIN_LOCK(IoC);												\
+}
+
+#else  /* !SK_LITTLE_ENDIAN */
+
+#define GM_IN32(IoC, Mac, Reg, pVal) {							\
+	SK_U8	Dummy;												\
+	SK_ACQ_SPIN_LOCK(IoC);										\
+	SK_IN16(IoC, GMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal) + 1);	\
+	SK_IN16(IoC, GMA(Mac, (Reg) + 4), (SK_U16 SK_FAR *)(pVal));	\
+	SK_IN8(IoC, B0_RAP, &Dummy);								\
+	SK_REL_SPIN_LOCK(IoC);										\
+}
+
+#endif /* !SK_LITTLE_ENDIAN */
+
+#define GM_OUT32(IoC, Mac, Reg, Val) {										\
+	SK_OUT16(IoC, GMA(Mac, Reg), (SK_U16)((Val) & 0xffffL));				\
+	SK_OUT16(IoC, GMA(Mac, (Reg) + 4), (SK_U16)(((Val) >> 16) & 0xffffL));	\
+}
+
+#define GM_INADDR(IoC, Mac, Reg, pVal) {			\
+	SK_U16	Word;									\
+	SK_U8	Dummy;									\
+	SK_U8	*pByte;									\
+	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];			\
+	SK_ACQ_SPIN_LOCK(IoC);							\
+	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);		\
+	pByte[0] = (SK_U8)(Word & 0x00ff);				\
+	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);		\
+	SK_IN16((IoC), GMA((Mac), (Reg) + 4), &Word);	\
+	pByte[2] = (SK_U8)(Word & 0x00ff);				\
+	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);		\
+	SK_IN16((IoC), GMA((Mac), (Reg) + 8), &Word);	\
+	pByte[4] = (SK_U8)(Word & 0x00ff);				\
+	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);		\
+	SK_IN8(IoC, B0_RAP, &Dummy);					\
+	SK_REL_SPIN_LOCK(IoC);							\
+}
+
+#define GM_OUTADDR(IoC, Mac, Reg, pVal) {				\
+	SK_U8	SK_FAR *pByte;								\
+	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
+	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
+		(((SK_U16)(pByte[0]) & 0x00ff) |				\
+		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), GMA((Mac), (Reg) + 4), (SK_U16)		\
+		(((SK_U16)(pByte[2]) & 0x00ff) |				\
+		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), GMA((Mac), (Reg) + 8), (SK_U16)		\
+		(((SK_U16)(pByte[4]) & 0x00ff) |				\
+		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
+}
+
+#define GM_INHASH(IoC, Mac, Reg, pVal) {				\
+	SK_U16	Word;										\
+	SK_U8	Dummy;										\
+	SK_U8	*pByte;										\
+	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
+	SK_ACQ_SPIN_LOCK(IoC);								\
+	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
+	pByte[0] = (SK_U8)(Word & 0x00ff);					\
+	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN16((IoC), GMA((Mac), (Reg) + 4), &Word);		\
+	pByte[2] = (SK_U8)(Word & 0x00ff);					\
+	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN16((IoC), GMA((Mac), (Reg) + 8), &Word);		\
+	pByte[4] = (SK_U8)(Word & 0x00ff);					\
+	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN16((IoC), GMA((Mac), (Reg) + 12), &Word);		\
+	pByte[6] = (SK_U8)(Word & 0x00ff);					\
+	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
+	SK_IN8(IoC, B0_RAP, &Dummy);						\
+	SK_REL_SPIN_LOCK(IoC);								\
+}
+
+#define GM_OUTHASH(IoC, Mac, Reg, pVal) {				\
+	SK_U8	*pByte;										\
+	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
+	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
+		(((SK_U16)(pByte[0]) & 0x00ff)|					\
+		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), GMA((Mac), (Reg) + 4), (SK_U16)		\
+		(((SK_U16)(pByte[2]) & 0x00ff)|					\
+		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), GMA((Mac), (Reg) + 8), (SK_U16)		\
+		(((SK_U16)(pByte[4]) & 0x00ff)|					\
+		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
+	SK_OUT16((IoC), GMA((Mac), (Reg) + 12), (SK_U16)	\
+		(((SK_U16)(pByte[6]) & 0x00ff)|					\
+		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
+}
+
+/*
+ * Different MAC Types
+ */
+#define SK_MAC_XMAC		0	/* Xaqti XMAC II */
+#define SK_MAC_GMAC		1	/* Marvell GMAC */
+
+/*
+ * Different PHY Types
+ */
+#define SK_PHY_XMAC			0	/* integrated in XMAC II */
+#define SK_PHY_BCOM			1	/* Broadcom BCM5400 */
+#define SK_PHY_LONE			2	/* Level One LXT1000 */
+#define SK_PHY_NAT			3	/* National DP83891 */
+#define SK_PHY_MARV_COPPER	4	/* Marvell 88E1040S */
+#define SK_PHY_MARV_FIBER	5	/* Marvell 88E1040S working on fiber */
+
+/*
+ * PHY addresses (bits 12..8 of PHY address reg)
+ */
+#define PHY_ADDR_XMAC	(0<<8)
+#define PHY_ADDR_BCOM	(1<<8)
+#define PHY_ADDR_LONE	(3<<8)
+#define PHY_ADDR_NAT	(0<<8)
+
+/* GPHY address (bits 15..11 of SMI control reg) */
+#define PHY_ADDR_MARV	0
+
+/*
+ * macros to access the PHY
+ *
+ * PHY_READ()		read a 16 bit value from the PHY
+ * PHY_WRITE()		write a 16 bit value to the PHY
+ *
+ * para:
+ * 	IoC		I/O context needed for SK I/O macros
+ * 	pPort	Pointer to port struct for PhyAddr
+ * 	Mac		XMAC to access		values: MAC_1 or MAC_2
+ * 	PhyReg	PHY Register to read or write
+ * 	(p)Val	Value or pointer to the value which should be read or
+ *			written.
+ *
+ * usage:	PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
+ * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
+ *	comes back. This is checked in DEBUG mode.
+ */
+#ifndef DEBUG
+#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
+	SK_U16 Mmu;															\
+																		\
+	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
+	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
+	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
+		do {															\
+			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
+		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
+		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
+	}																	\
+}
+#else
+#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
+	SK_U16 Mmu;															\
+	int __i = 0;														\
+																		\
+	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
+	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
+	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
+		do {															\
+			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
+			__i++;														\
+			if (__i > 100000) {											\
+				SK_DBG_PRINTF("*****************************\n");		\
+				SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n");		\
+				SK_DBG_PRINTF("*****************************\n");		\
+				break;													\
+			}															\
+		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
+		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
+	}																	\
+}
+#endif /* DEBUG */
+
+#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) {						\
+	SK_U16 Mmu;															\
+																		\
+	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
+		do {															\
+			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
+		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
+	}																	\
+	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
+	XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val));							\
+	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
+		do {															\
+			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
+		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
+	}																	\
+}
+
+/*
+ *	Macro PCI_C()
+ *
+ *	Use this macro to access PCI config register from the I/O space.
+ *
+ * para:
+ *	pAC		Pointer to adapter context
+ *	Addr	PCI configuration register to access.
+ *			Values:	PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
+ *
+ * usage	SK_IN16(IoC, PCI_C(pAC, PCI_VENDOR_ID), pVal);
+ */
+#define PCI_C(p, Addr)		\
+	(((CHIP_ID_YUKON_2(p)) ? Y2_CFG_SPC : B7_CFG_SPC) + (Addr))
+
+/*
+ *	Macro SK_HW_ADDR(Base, Addr)
+ *
+ *	Calculates the effective HW address
+ *
+ * para:
+ *	Base	I/O or memory base address
+ *	Addr	Address offset
+ *
+ * usage:	May be used in SK_INxx and SK_OUTxx macros
+ *		#define SK_IN8(IoC, Addr, pVal) ...\
+ *			*pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
+ */
+#ifdef SK_MEM_MAPPED_IO
+#define SK_HW_ADDR(Base, Addr)	((Base) + (Addr))
+#else  /* SK_MEM_MAPPED_IO */
+#define SK_HW_ADDR(Base, Addr)	\
+			((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0)))
+#endif /* SK_MEM_MAPPED_IO */
+
+#define SZ_LONG	(sizeof(SK_U32))
+
+/*
+ *	Macro SK_HWAC_LINK_LED()
+ *
+ *	Use this macro to set the link LED mode.
+ * para:
+ *	pAC		Pointer to adapter context struct
+ *	IoC		I/O context needed for SK I/O macros
+ *	Port	Port number
+ *	Mode	Mode to set for this LED
+ */
+#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
+	SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
+
+#define SK_SET_GP_IO(IoC, Bit) {	\
+	SK_U32	DWord;					\
+	SK_IN32(IoC, B2_GP_IO, &DWord);	\
+	DWord |= ((GP_DIR_0 | GP_IO_0) << (Bit));\
+	SK_OUT32(IoC, B2_GP_IO, DWord);	\
+}
+
+#define SK_CLR_GP_IO(IoC, Bit) {	\
+	SK_U32	DWord;					\
+	SK_IN32(IoC, B2_GP_IO, &DWord);	\
+	DWord &= ~((GP_DIR_0 | GP_IO_0) << (Bit));\
+	SK_OUT32(IoC, B2_GP_IO, DWord);	\
+}
+
+#define SK_TST_MODE_ON(IoC) {			\
+	SK_U8 Byte;							\
+	SK_IN8(IoC, B2_TST_CTRL1, &Byte);	\
+	Byte &= ~TST_CFG_WRITE_OFF;			\
+	Byte |= TST_CFG_WRITE_ON;			\
+	SK_OUT8(IoC, B2_TST_CTRL1, Byte);	\
+}
+
+#define SK_TST_MODE_OFF(IoC) {			\
+	SK_U8 Byte;							\
+	SK_IN8(IoC, B2_TST_CTRL1, &Byte);	\
+	Byte &= ~TST_CFG_WRITE_ON;			\
+	Byte |= TST_CFG_WRITE_OFF;			\
+	SK_OUT8(IoC, B2_TST_CTRL1, Byte);	\
+}
+
+#define SK_GE_PCI_FIFO_SIZE		1600	/* PCI FIFO Size */
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif	/* __INC_SKGEHW_H */
+
diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
new file mode 100755
index 0000000..6656d1c
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgehwt.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Name:	skhwt.h
+ * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 2.2 $
+ * Date:	$Date: 2005/12/14 16:11:03 $
+ * Purpose:	Defines for the hardware timer functions
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ * SKGEHWT.H	contains all defines and types for the timer functions
+ */
+
+#ifndef	_SKGEHWT_H_
+#define _SKGEHWT_H_
+
+/*
+ * SK Hardware Timer
+ * - needed wherever the HWT module is used
+ * - use in Adapters context name pAC->Hwt
+ */
+typedef	struct s_Hwt {
+	SK_U32		TStart;	/* HWT start */
+	SK_U32		TStop;	/* HWT stop */
+	int		TActive;	/* HWT: flag : active/inactive */
+} SK_HWT;
+
+extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc);
+extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time);
+extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc);
+extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc);
+extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc);
+#endif	/* _SKGEHWT_H_ */
diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
new file mode 100755
index 0000000..41c4ce3
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgeinit.h
@@ -0,0 +1,1178 @@
+/******************************************************************************
+ *
+ * Name:	skgeinit.h
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.65 $
+ * Date:	$Date: 2007/07/17 08:17:49 $
+ * Purpose:	Structures and prototypes for the GE Init Module
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKGEINIT_H_
+#define __INC_SKGEINIT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+/* defines ********************************************************************/
+
+#define SK_TEST_VAL		0x11335577UL
+
+/* modifying Link LED behaviour (used with SkGeLinkLED()) */
+#define SK_LNK_OFF		LED_OFF
+#define SK_LNK_ON		(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
+#define SK_LNK_BLINK	(LED_ON | LED_BLK_ON  | LED_SYNC_ON)
+#define SK_LNK_PERM		(LED_ON | LED_BLK_OFF | LED_SYNC_ON)
+#define SK_LNK_TST		(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
+
+/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */
+#define SK_LED_OFF		LED_OFF
+#define SK_LED_ACTIVE	(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
+#define SK_LED_STANDBY	(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
+
+/* addressing LED Registers in SkGeXmitLED() */
+#define XMIT_LED_INI	0
+#define XMIT_LED_CNT	(RX_LED_VAL - RX_LED_INI)
+#define XMIT_LED_CTRL	(RX_LED_CTRL- RX_LED_INI)
+#define XMIT_LED_TST	(RX_LED_TST - RX_LED_INI)
+
+/* parameter 'Mode' when calling SkGeXmitLED() */
+#define SK_LED_DIS	0
+#define SK_LED_ENA	1
+#define SK_LED_TST	2
+
+/* Counter and Timer constants, for a host clock of 62.5 MHz */
+#define SK_XMIT_DUR		0x002faf08UL	/*  50 ms */
+#define SK_BLK_DUR		0x01dcd650UL	/* 500 ms */
+
+#define SK_DPOLL_DEF	0x00ee6b28UL	/* 250 ms at 62.5 MHz (Genesis) */
+#define SK_DPOLL_DEF_Y2	0x0000124fUL	/*  75 us (Yukon-2) */
+
+#define SK_DPOLL_MAX	0x00ffffffUL	/* 268 ms at 62.5 MHz */
+										/* 215 ms at 78.12 MHz (Yukon) */
+
+#define SK_FACT_62		100			/* is given in percent */
+#define SK_FACT_50		 81			/* on YUKON-FE+ 50 MHz */
+#define SK_FACT_53		 85			/* on GENESIS:	53.12 MHz */
+#define SK_FACT_78		125			/* on YUKON:	78.12 MHz */
+#define SK_FACT_100		161			/* on YUKON-FE:	100 MHz */
+#define SK_FACT_125		202			/* on YUKON-EC:	125 MHz */
+
+/* Timeout values */
+#define SK_MAC_TO_53	72			/* MAC arbiter timeout */
+#define SK_PKT_TO_53	0x2000		/* Packet arbiter timeout */
+#define SK_PKT_TO_MAX	0xffff		/* Maximum value */
+#define SK_RI_TO_53		36			/* RAM interface timeout */
+
+#define SK_PHY_ACC_TO	600000		/* PHY access timeout */
+
+/* RAM Buffer High Pause Threshold values */
+#define SK_RB_ULPP		( 8 * 1024)	/* Upper Level in kB/8 */
+#define SK_RB_LLPP_S	(10 * 1024)	/* Lower Level for small Queues */
+#define SK_RB_LLPP_B	(16 * 1024)	/* Lower Level for big Queues */
+
+/* Threshold values for Yukon-EC Ultra and Extreme*/
+#define SK_ECU_ULPP		0x0080	/* Upper Pause Threshold (multiples of 8) */
+#define SK_ECU_LLPP		0x0060	/* Lower Pause Threshold (multiples of 8) */
+#define SK_ECU_AE_THR	0x0070	/* Almost Empty Threshold */
+#define SK_ECU_TXFF_LEV	0x01a0	/* Tx BMU FIFO Level */
+#define SK_ECU_JUMBO_WM	0x0400	/* Jumbo Mode Watermark */
+
+#ifndef SK_BMU_RX_WM
+#define SK_BMU_RX_WM		0x600	/* BMU Rx Watermark */
+#endif
+
+#ifndef SK_BMU_TX_WM
+#define SK_BMU_TX_WM		0x600	/* BMU Tx Watermark */
+#endif
+
+/* performance sensitive drivers should set this define to 0x80 */
+#ifndef SK_BMU_RX_WM_PEX
+#define SK_BMU_RX_WM_PEX	0x80	/* BMU Rx Watermark for PEX */
+#endif
+
+/* XMAC II Rx High Watermark */
+#define SK_XM_RX_HI_WM	0x05aa		/* 1450 */
+
+/* XMAC II Tx Threshold */
+#define SK_XM_THR_REDL	0x01fb		/* .. for redundant link usage */
+#define SK_XM_THR_SL	0x01fb		/* .. for single link adapters */
+#define SK_XM_THR_MULL	0x01fb		/* .. for multiple link usage */
+#define SK_XM_THR_JUMBO	0x03fc		/* .. for jumbo frame usage */
+
+/* values for PortUsage */
+#define SK_RED_LINK		1		/* redundant link usage */
+#define SK_MUL_LINK		2		/* multiple link usage */
+#define SK_JUMBO_LINK	3		/* driver uses jumbo frames */
+
+/* Minimum RAM Buffer Rx Queue Size */
+#define SK_MIN_RXQ_SIZE	(((pAC)->GIni.GIYukon2) ? 10 : 16)		/* 10/16 kB */
+
+/* Minimum RAM Buffer Tx Queue Size */
+#define SK_MIN_TXQ_SIZE	(((pAC)->GIni.GIYukon2) ? 10 : 16)		/* 10/16 kB */
+
+/* Queue Size units (Genesis/Yukon) */
+#define QZ_UNITS		7
+#define QZ_STEP			8
+
+/* Queue Size units (Yukon-2) */
+#define QZ_STEP_Y2		1
+
+/* Percentage of queue size from whole memory */
+/* 80 % for receive */
+#define RAM_QUOTA_RX	80
+/*  0 % for sync transfer */
+#define RAM_QUOTA_SYNC	0
+/* the rest (20%) is taken for async transfer */
+
+/* Types of RAM Buffer Queues */
+#define SK_RX_SRAM_Q	1	/* small receive queue */
+#define SK_RX_BRAM_Q	2	/* big receive queue */
+#define SK_TX_RAM_Q		3	/* small or big transmit queue */
+
+/* parameter 'Dir' when calling SkGeStopPort() */
+#define SK_STOP_TX	1	/* Stops the transmit path, resets the XMAC */
+#define SK_STOP_RX	2	/* Stops the receive path */
+#define SK_STOP_ALL	3	/* Stops Rx and Tx path, resets the XMAC */
+
+/* parameter 'RstMode' when calling SkGeStopPort() */
+#define SK_SOFT_RST	1	/* perform a software reset */
+#define SK_HARD_RST	2	/* perform a hardware reset */
+
+/* Init Levels */
+#define SK_INIT_DATA	0	/* Init level 0: init data structures */
+#define SK_INIT_IO		1	/* Init level 1: init with IOs */
+#define SK_INIT_RUN		2	/* Init level 2: init for run time */
+
+/* Link Mode Parameter */
+#define SK_LMODE_HALF		1	/* Half Duplex Mode */
+#define SK_LMODE_FULL		2	/* Full Duplex Mode */
+#define SK_LMODE_AUTOHALF	3	/* AutoHalf Duplex Mode */
+#define SK_LMODE_AUTOFULL	4	/* AutoFull Duplex Mode */
+#define SK_LMODE_AUTOBOTH	5	/* AutoBoth Duplex Mode */
+#define SK_LMODE_AUTOSENSE	6	/* configured mode auto sensing */
+#define SK_LMODE_INDETERMINATED	7	/* indeterminated */
+
+/* Auto-negotiation timeout in 100ms granularity */
+#define SK_AND_MAX_TO		6	/* Wait 600 msec before link comes up */
+
+/* Auto-negotiation error codes */
+#define SK_AND_OK			0	/* no error */
+#define SK_AND_OTHER		1	/* other error than below */
+#define SK_AND_DUP_CAP		2	/* Duplex capabilities error */
+
+/* Link Speed Capabilities */
+#define SK_LSPEED_CAP_AUTO			BIT_0S	/* Automatic resolution */
+#define SK_LSPEED_CAP_10MBPS		BIT_1S	/* 10 Mbps */
+#define SK_LSPEED_CAP_100MBPS		BIT_2S	/* 100 Mbps */
+#define SK_LSPEED_CAP_1000MBPS		BIT_3S	/* 1000 Mbps */
+#define SK_LSPEED_CAP_INDETERMINATED BIT_4S /* indeterminated */
+
+/* Link Speed Parameter */
+#define SK_LSPEED_AUTO				1	/* Automatic resolution */
+#define SK_LSPEED_10MBPS			2	/* 10 Mbps */
+#define SK_LSPEED_100MBPS			3	/* 100 Mbps */
+#define SK_LSPEED_1000MBPS			4	/* 1000 Mbps */
+#define SK_LSPEED_INDETERMINATED	5	/* indeterminated */
+
+/* Link Speed Current State */
+#define SK_LSPEED_STAT_UNKNOWN		1
+#define SK_LSPEED_STAT_10MBPS		2
+#define SK_LSPEED_STAT_100MBPS 		3
+#define SK_LSPEED_STAT_1000MBPS		4
+#define SK_LSPEED_STAT_INDETERMINATED 5
+
+/* Link Capability Parameter */
+#define SK_LMODE_CAP_HALF		BIT_0S	/* Half Duplex Mode */
+#define SK_LMODE_CAP_FULL		BIT_1S	/* Full Duplex Mode */
+#define SK_LMODE_CAP_AUTOHALF	BIT_2S	/* AutoHalf Duplex Mode */
+#define SK_LMODE_CAP_AUTOFULL	BIT_3S	/* AutoFull Duplex Mode */
+#define SK_LMODE_CAP_INDETERMINATED BIT_4S /* indeterminated */
+
+/* Link Mode Current State */
+#define SK_LMODE_STAT_UNKNOWN	1	/* Unknown Duplex Mode */
+#define SK_LMODE_STAT_HALF		2	/* Half Duplex Mode */
+#define SK_LMODE_STAT_FULL		3	/* Full Duplex Mode */
+#define SK_LMODE_STAT_AUTOHALF	4	/* Half Duplex Mode obtained by Auto-Neg */
+#define SK_LMODE_STAT_AUTOFULL	5	/* Full Duplex Mode obtained by Auto-Neg */
+#define SK_LMODE_STAT_INDETERMINATED 6	/* indeterminated */
+
+/* Flow Control Mode Parameter (and capabilities) */
+#define SK_FLOW_MODE_NONE		1	/* No Flow Control */
+#define SK_FLOW_MODE_LOC_SEND	2	/* Local station sends PAUSE */
+#define SK_FLOW_MODE_SYMMETRIC	3	/* Both stations may send PAUSE */
+#define SK_FLOW_MODE_SYM_OR_REM	4	/* Both stations may send PAUSE or
+					 * just the remote station may send PAUSE
+					 */
+#define SK_FLOW_MODE_INDETERMINATED 5	/* indeterminated */
+
+/* Flow Control Status Parameter */
+#define SK_FLOW_STAT_NONE		1	/* No Flow Control */
+#define SK_FLOW_STAT_REM_SEND	2	/* Remote Station sends PAUSE */
+#define SK_FLOW_STAT_LOC_SEND	3	/* Local station sends PAUSE */
+#define SK_FLOW_STAT_SYMMETRIC	4	/* Both station may send PAUSE */
+#define SK_FLOW_STAT_INDETERMINATED 5	/* indeterminated */
+
+/* Master/Slave Mode Capabilities */
+#define SK_MS_CAP_AUTO		BIT_0S	/* Automatic resolution */
+#define SK_MS_CAP_MASTER	BIT_1S	/* This station is master */
+#define SK_MS_CAP_SLAVE		BIT_2S	/* This station is slave */
+#define SK_MS_CAP_INDETERMINATED BIT_3S	/* indeterminated */
+
+/* Set Master/Slave Mode Parameter (and capabilities) */
+#define SK_MS_MODE_AUTO		1	/* Automatic resolution */
+#define SK_MS_MODE_MASTER	2	/* This station is master */
+#define SK_MS_MODE_SLAVE	3	/* This station is slave */
+#define SK_MS_MODE_INDETERMINATED 4	/* indeterminated */
+
+/* Master/Slave Status Parameter */
+#define SK_MS_STAT_UNSET	1	/* The M/S status is not set */
+#define SK_MS_STAT_MASTER	2	/* This station is master */
+#define SK_MS_STAT_SLAVE	3	/* This station is slave */
+#define SK_MS_STAT_FAULT	4	/* M/S resolution failed */
+#define SK_MS_STAT_INDETERMINATED 5	/* indeterminated */
+
+/* parameter 'Mode' when calling SkMacSetRxCmd() */
+#define SK_STRIP_FCS_ON		BIT_0S	/* Enable  FCS stripping of Rx frames */
+#define SK_STRIP_FCS_OFF	BIT_1S	/* Disable FCS stripping of Rx frames */
+#define SK_STRIP_PAD_ON		BIT_2S	/* Enable  pad byte stripping of Rx fr */
+#define SK_STRIP_PAD_OFF	BIT_3S	/* Disable pad byte stripping of Rx fr */
+#define SK_LENERR_OK_ON		BIT_4S	/* Don't chk fr for in range len error */
+#define SK_LENERR_OK_OFF	BIT_5S	/* Check frames for in range len error */
+#define SK_BIG_PK_OK_ON		BIT_6S	/* Don't set Rx Error bit for big frames */
+#define SK_BIG_PK_OK_OFF	BIT_7S	/* Set Rx Error bit for big frames */
+#define SK_SELF_RX_ON		BIT_8S	/* Enable  Rx of own packets */
+#define SK_SELF_RX_OFF		BIT_9S	/* Disable Rx of own packets */
+
+/* parameter 'Para' when calling SkMacSetRxTxEn() */
+#define SK_MAC_LOOPB_ON		BIT_0S	/* Enable  MAC Loopback Mode */
+#define SK_MAC_LOOPB_OFF	BIT_1S	/* Disable MAC Loopback Mode */
+#define SK_PHY_LOOPB_ON		BIT_2S	/* Enable  PHY Loopback Mode */
+#define SK_PHY_LOOPB_OFF	BIT_3S	/* Disable PHY Loopback Mode */
+#define SK_PHY_FULLD_ON		BIT_4S	/* Enable  GMII Full Duplex */
+#define SK_PHY_FULLD_OFF	BIT_5S	/* Disable GMII Full Duplex */
+
+/* States of PState */
+#define SK_PRT_RESET	0	/* the port is reset */
+#define SK_PRT_STOP		1	/* the port is stopped (similar to SW reset) */
+#define SK_PRT_INIT		2	/* the port is initialized */
+#define SK_PRT_RUN		3	/* the port has an active link */
+
+/* PHY power down modes */
+#define PHY_PM_OPERATIONAL_MODE		0	/* PHY operational mode */
+#define PHY_PM_DEEP_SLEEP			1	/* Coma mode --> minimal power */
+#define PHY_PM_IEEE_POWER_DOWN		2	/* IEEE 22.2.4.1.5 compl. power down */
+#define PHY_PM_ENERGY_DETECT		3	/* Energy detect */
+#define PHY_PM_ENERGY_DETECT_PLUS	4	/* Energy detect plus */
+
+/* PCI Bus Types */
+#define SK_PCI_BUS		BIT_0S		/* normal PCI bus */
+#define SK_PCIX_BUS		BIT_1S		/* PCI-X bus */
+#define SK_PEX_BUS		BIT_2S		/* PCI-Express bus */
+
+/* Default receive frame limit for Workaround of XMAC Errata */
+#define SK_DEF_RX_WA_LIM	SK_CONSTU64(100)
+
+/* values for GILedBlinkCtrl (LED Blink Control) */
+#define SK_ACT_LED_BLINK	BIT_0S	/* Activity LED blinking */
+#define SK_DUP_LED_NORMAL	BIT_1S	/* Duplex LED normal */
+#define SK_LED_LINK100_ON	BIT_2S	/* Link 100M LED on */
+#define SK_DUAL_LED_ACT_LNK	BIT_3S	/* Dual LED ACT/LNK configuration */
+#define SK_LED_LINK_MUX_P60	BIT_4S	/* Link LED muxed to pin 60 */
+#define SK_LED_COMB_ACT_LNK	BIT_5S	/* Combined ACT/LNK LED mode */
+#define SK_ACT_LED_NOTR_OFF	BIT_6S	/* Activity LED off (no traffic) */
+
+/* Link Partner Status */
+#define SK_LIPA_UNKNOWN	0	/* Link partner is in unknown state */
+#define SK_LIPA_MANUAL	1	/* Link partner is in detected manual state */
+#define SK_LIPA_AUTO	2	/* Link partner is in auto-negotiation state */
+
+/* Maximum Restarts before restart is ignored (3Com WA) */
+#define SK_MAX_LRESTART	3	/* Max. 3 times the link is restarted */
+
+/* Max. Auto-neg. timeouts before link detection in sense mode is reset */
+#define SK_MAX_ANEG_TO	10	/* Max. 10 times the sense mode is reset */
+
+
+/******************************************************************************
+ *
+ * HW_FEATURE() macro
+ */
+
+/* DWORD 0: Features */
+#define HWF_ENA_POW_SAV_W_WOL	0x08000000UL	/* Power saving with WOL ena. */
+#define HWF_FORCE_AUTO_NEG		0x04000000UL	/* Force Auto-Negotiation */
+#define HWF_CLK_GATING_ENABLE	0x02000000UL	/* Enable Clock Gating */
+#define HWF_RED_CORE_CLK_SUP	0x01000000UL	/* Reduced Core Clock supp. */
+#define HWF_RESTORE_LOST_BARS	0x00800000UL	/* Save and restore PCI BARs */
+#define HWF_ASPM_SWITCHING		0x00400000UL	/* Activate ASPM feature */
+#define HWF_TX_IP_ID_INCR_ON	0x00200000UL	/* Enable Tx IP ID Increment */
+#define HWF_ADV_CSUM_SUPPORT	0x00100000UL	/* Sel Csum of IP and TCP/UDP */
+#define HWF_PSM_SUPPORTED		0x00080000UL	/* Power State Manager support*/
+
+
+/*-RMV- DWORD 1: Deviations (all in use) */
+#define HWF_WA_DEV_4222			0x18000000UL	/*-RMV- 4.222 (Done Idx rep.) */
+#define HWF_WA_DEV_56			0x14000000UL	/*-RMV- 5.6 (Rx Chksum 0xffff)*/
+#define HWF_WA_DEV_54			0x12000000UL	/*-RMV- 5.4 (Missing Status LE)*/
+#define HWF_WA_DEV_53			0x11000000UL	/*-RMV- 5.3 (Tx Done LSOv2 rep)*/
+#define HWF_WA_DEV_LIM_IPV6_RSS	0x10800000UL	/*-RMV- IPV6 RSS limitted */
+#define HWF_WA_DEV_4217			0x10400000UL	/*-RMV- 4.217 (PCI-E blockage) */
+#define HWF_WA_DEV_4200			0x10200000UL	/*-RMV- 4.200 (D3 Blue Screen)*/
+#define HWF_WA_DEV_4185CS		0x10100000UL	/*-RMV- 4.185 (ECU 100 CS cal)*/
+#define HWF_WA_DEV_4185			0x10080000UL	/*-RMV- 4.185 (ECU Tx h check)*/
+#define HWF_WA_DEV_4167			0x10040000UL	/*-RMV- 4.167 (Rx OvSize Hang)*/
+#define HWF_WA_DEV_4152			0x10020000UL	/*-RMV- 4.152 (RSS issue) */
+#define HWF_WA_DEV_4115			0x10010000UL	/*-RMV- 4.115 (Rx MAC FIFO) */
+#define HWF_WA_DEV_4109			0x10008000UL	/*-RMV- 4.109 (BIU hang) */
+#define HWF_WA_DEV_483			0x10004000UL	/*-RMV- 4.83 (Rx TCP wrong) */
+#define HWF_WA_DEV_479			0x10002000UL	/*-RMV- 4.79 (Rx BMU hang II) */
+#define HWF_WA_DEV_472			0x10001000UL	/*-RMV- 4.72 (GPHY2 MDC clk) */
+#define HWF_WA_DEV_463			0x10000800UL	/*-RMV- 4.63 (Rx BMU hang I) */
+#define HWF_WA_DEV_427			0x10000400UL	/*-RMV- 4.27 (Tx Done Rep) */
+#define HWF_WA_DEV_42			0x10000200UL	/*-RMV- 4.2 (pref unit burst) */
+#define HWF_WA_DEV_46			0x10000100UL	/*-RMV- 4.6 (CPU crash II) */
+#define HWF_WA_DEV_43_418		0x10000080UL	/*-RMV- 4.3 & 4.18 (PCI unexp */
+												/*-RMV- compl&Stat BMU deadl) */
+#define HWF_WA_DEV_420			0x10000040UL	/*-RMV- 4.20 (Status BMU ov) */
+#define HWF_WA_DEV_423			0x10000020UL	/*-RMV- 4.23 (TCP Segm Hang) */
+#define HWF_WA_DEV_424			0x10000010UL	/*-RMV- 4.24 (MAC reg overwr) */
+#define HWF_WA_DEV_425			0x10000008UL	/*-RMV- 4.25 (Magic packet */
+												/*-RMV- with odd offset) */
+#define HWF_WA_DEV_428			0x10000004UL	/*-RMV- 4.28 (Poll-U &BigEndi)*/
+#define HWF_WA_FIFO_FLUSH_YLA0	0x10000002UL	/*-RMV- dis Rx GMAC FIFO Flush*/
+												/*-RMV- for Yu-L Rev. A0 only */
+#define HWF_WA_COMA_MODE		0x10000001UL	/*-RMV- Coma Mode WA req */
+
+/*-RMV- DWORD 1: Deviations */
+#define HWF_WA_DEV_521			0x20000010UL	/*-RMV- 5.21 (wrong RFSW) */
+#define HWF_WA_DEV_520			0x20000008UL	/*-RMV- 5.20 (Tx lost of data)*/
+#define HWF_WA_DEV_511			0x20000004UL	/*-RMV- 5.11 (Tx Underrun) */
+#define HWF_WA_DEV_510			0x20000002UL	/*-RMV- 5.10 (Tx Checksum) */
+#define HWF_WA_DEV_51			0x20000001UL	/*-RMV- 5.1 (MACSec sync) */
+
+#if 0
+#define HWF_SYNC_TX_SUP			0x20800000UL	/* Synch. Tx Queue available */
+#define HWF_SINGLE_PORT_DEVICE	0x20400000UL	/* Device has only one LAN IF */
+#define HWF_JUMBO_FRAMES_SUP	0x20200000UL	/* Jumbo Frames supported */
+#define HWF_TX_TCP_CSUM_SUP		0x20100000UL	/* TCP Tx checksum supported */
+#define HWF_TX_UDP_CSUM_SUP		0x20080000UL	/* UDP Tx checksum supported */
+#define HWF_RX_CSUM_SUP			0x20040000UL	/* RX checksum supported */
+#define HWF_TCP_SEGM_SUP		0x20020000UL	/* TCP segmentation supported */
+#define HWF_RSS_HASH_SUP		0x20010000UL	/* RSS Hash supported */
+#define HWF_PORT_VLAN_SUP		0x20008000UL	/* VLAN can be config per port*/
+#define HWF_ROLE_PARAM_SUP		0x20004000UL	/* Role parameter supported */
+#define HWF_LOW_PMODE_SUP		0x20002000UL	/* Low Power Mode supported */
+#define HWF_ENERGIE_DEMO_SUP	0x20001000UL	/* Energy Detect mode supp. */
+#define HWF_SPEED1000_SUP		0x20000800UL	/* Line Speed 1000 supported */
+#define HWF_SPEED100_SUP		0x20000400UL	/* Line Speed 100 supported */
+#define HWF_SPEED10_SUP			0x20000200UL	/* Line Speed 10 supported */
+#define HWF_AUTONEGSENSE_SUP	0x20000100UL	/* Autoneg Sense supported */
+#define HWF_PHY_LOOPB_MD_SUP	0x20000080UL	/* PHY loopback mode supp. */
+#define HWF_ASF_SUP				0x20000040UL	/* ASF support possible */
+#define HWF_QS_STEPS_1KB		0x20000020UL	/* The Rx/Tx queues can be */
+												/* configured with 1 kB res. */
+#define HWF_OWN_RAM_PER_PORT	0x20000010UL	/* Each port has a separate */
+												/* RAM buffer */
+#define HWF_MIN_LED_IF			0x20000008UL	/* Minimal LED interface */
+												/* (e.g. for Yukon-EC) */
+#define HWF_LIST_ELEMENTS_USED	0x20000004UL	/* HW uses list elements */
+												/* (otherwise desc. are used) */
+#define HWF_GMAC_INSIDE			0x20000002UL	/* Device contains GMAC */
+#define HWF_TWSI_PRESENT		0x20000001UL	/* TWSI sensor bus present */
+#endif
+
+/* DWORD 3: still unused */
+
+
+/*
+ * HW_FEATURE()	-	returns whether the feature is serviced or not
+ */
+#define HW_FEATURE(pAC, ReqFeature) \
+	(((pAC)->GIni.HwF.Features[((ReqFeature) & 0x30000000UL) >> 28] &\
+	 ((ReqFeature) & 0x0fffffffUL)) != 0)
+
+#define HW_FEAT_LIST	0
+#define HW_DEV_LIST		1
+#define HW_DEV_LIST_2	2
+
+#define SET_HW_FEATURE_MASK(pAC, List, OffMaskValue, OnMaskValue) {	\
+	if ((List) == HW_FEAT_LIST || (List) == HW_DEV_LIST) {			\
+		(pAC)->GIni.HwF.OffMask[List] = (OffMaskValue);				\
+		(pAC)->GIni.HwF.OnMask[List] = (OnMaskValue);				\
+	}																\
+}
+
+/* driver access macros for GIni structure ***********************************/
+
+#define CHIP_ID_YUKON_2(pAC)		((pAC)->GIni.GIYukon2)
+
+#define HW_SYNC_TX_SUPPORTED(pAC)						\
+		((pAC)->GIni.GIChipId != CHIP_ID_YUKON_EC	&&	\
+		 (pAC)->GIni.GIChipId != CHIP_ID_YUKON_FE	&&	\
+		 (pAC)->GIni.GIChipId != CHIP_ID_YUKON_FE_P	&&	\
+		 (pAC)->GIni.GIChipId != CHIP_ID_YUKON_EC_U	&&	\
+		 (pAC)->GIni.GIChipId != CHIP_ID_YUKON_EX)
+
+#define HW_HAS_NEWER_PHY(pAC)							\
+		((pAC)->GIni.GIChipId == CHIP_ID_YUKON_XL	||	\
+		 (pAC)->GIni.GIChipId == CHIP_ID_YUKON_EC_U	||	\
+		 (pAC)->GIni.GIChipId == CHIP_ID_YUKON_EX)
+
+#define HW_MS_TO_TICKS(pAC, MsTime) \
+	((MsTime) * (62500L/100) * (pAC)->GIni.GIHstClkFact)
+
+#define HW_IS_EXT_LE_FORMAT(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_IS_NEW_ASF_FORMAT(pAC)	((pAC)->GIni.GIExtLeFormat)
+
+#define HW_IS_RAM_IF_AVAIL(pAC)		(					\
+	!((pAC)->GIni.GIChipId == CHIP_ID_YUKON_EC_U ||		\
+	  (pAC)->GIni.GIChipId == CHIP_ID_YUKON_EX	 ||		\
+	  (pAC)->GIni.GIChipId == CHIP_ID_YUKON_FE_P))
+
+#define HW_NUM_OF_PATTERN(pAC)		((pAC)->GIni.GINumOfPattern)
+#define HW_OTP_SUPPORTED(pAC)		((pAC)->GIni.GIChipId >= CHIP_ID_YUKON_FE_P)
+
+/* general CSUM */
+/* flag to distinguish between old style and new style csum offload */
+#define HW_SUP_FULL_OFFLOAD(pAC)		((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_NEW_LSOV1(pAC)			((pAC)->GIni.GIExtLeFormat)
+
+/* Rx CSUM IPv4 */
+#define HW_SUP_RX_CSUM_IPV4(pAC)		SK_TRUE
+#define HW_SUP_RX_CSUM_OPT_IPV4(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_RX_CSUM_TCPIPV4(pAC)		SK_TRUE
+#define HW_SUP_RX_CSUM_OPT_TCPIPV4(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_RX_CSUM_UDPIPV4(pAC)		SK_TRUE
+
+/* Rx CSUM IPv6 */
+#define HW_SUP_RX_CSUM_IPV6_EXT_HDR(pAC)((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_RX_CSUM_TCPIPV6(pAC)		((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_RX_CSUM_OPT_TCPIPV6(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_RX_CSUM_UDPIPV6(pAC)		((pAC)->GIni.GIExtLeFormat)
+
+/* Tx CSUM IPv4 */
+#define HW_SUP_TX_CSUM_IPV4(pAC)		((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_TX_CSUM_OPT_IPV4(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_TX_CSUM_TCPIPV4(pAC)		(((pAC)->GIni.GIChipId != CHIP_ID_GENESIS) &&	\
+											!HW_FEATURE(pAC, HWF_WA_DEV_4185CS))
+#define HW_SUP_TX_CSUM_OPT_TCPIPV4(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_TX_CSUM_UDPIPV4(pAC)		(((pAC)->GIni.GIChipId != CHIP_ID_GENESIS) &&	\
+											!HW_FEATURE(pAC, HWF_WA_DEV_4185CS))
+/* Tx CSUM IPv6 */
+#define HW_SUP_TX_CSUM_IPV6_EXT_HDR(pAC)((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_TX_CSUM_TCPIPV6(pAC)		((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_TX_CSUM_OPT_TCPIPV6(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_TX_CSUM_UDPIPV6(pAC)		((pAC)->GIni.GIExtLeFormat)
+
+/* Tx CSUM special flag for FiFo size */
+#define HW_SUP_TX_CSUM_FOR_JUMBO(pAC)	(		\
+	(pAC)->GIni.GIJumTcpSegSup || 				\
+	(pAC)->GIni.GIChipId == CHIP_ID_GENESIS ||	\
+	(pAC)->GIni.GIChipId == CHIP_ID_YUKON ||	\
+	(pAC)->GIni.GIChipId == CHIP_ID_YUKON_LITE)
+
+/* LSO */
+#define HW_SUP_LSOV1(pAC)				((pAC)->GIni.GIYukon2)
+#define HW_SUP_OPT_IPV4_LSOV1(pAC)		((pAC)->GIni.GIYukon2)
+#define HW_SUP_OPT_TCPIPV4_LSOV1(pAC)	((pAC)->GIni.GIYukon2)
+#define HW_SUP_LSOV2(pAC)				((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_IPV6_EXT_HDR_LSOV2(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_OPT_TCPIPV6_LSOV2(pAC)	((pAC)->GIni.GIExtLeFormat)
+#define HW_SUP_LSO_FOR_JUMBO(pAC)		((pAC)->GIni.GIJumTcpSegSup)
+
+/* RSS */
+#define HW_SUP_IPV4_RSS(pAC)			((pAC)->GIni.GIYukon2 && 				\
+										  !HW_FEATURE(pAC, HWF_WA_DEV_4152))
+#define HW_SUP_IPV6_RSS(pAC)			((pAC)->GIni.GIExtLeFormat)
+
+/* MacSec */
+#define HW_SUP_MACSEC(pAC)				SK_FALSE
+
+/* VPD Support */
+#define HW_SUP_VPD(pAC)			((pAC)->GIni.GIChipId != CHIP_ID_YUKON_FE_P)
+
+/* SPI PROM Support */
+#define HW_SUP_SPI_PROM(pAC)	((pAC)->GIni.GIChipId != CHIP_ID_YUKON_FE_P &&	\
+								 (pAC)->GIni.GIChipId != CHIP_ID_YUKON_FE)
+
+/* Battery Power Management */
+#define HW_NO_BAT_POW_MANAGEMENT(pAC)					\
+	((pAC)->GIni.GIChipId == CHIP_ID_YUKON_EC_U &&		\
+	 (pAC)->GIni.GIChipRev >= CHIP_REV_YU_EC_U_A1 &&	\
+	 (pAC)->GIni.GIChipCap == 2 &&						\
+	 !HW_FEATURE(pAC, HWF_WA_DEV_4200))
+
+/* maximal supported link speed; returns 100 or 1000 */
+#define HW_MAX_LINE_SPEED(pAC)							\
+	((pAC)->GIni.GP[MAC_1].PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS ? 1000 : 100)
+
+/* structures *****************************************************************/
+
+/*
+ * HW Feature structure
+ */
+typedef struct s_HwFeatures {
+	SK_U32	Features[4];	/* Feature list */
+	SK_U32	OffMask[4];		/* Off Mask */
+	SK_U32	OnMask[4];		/* On Mask */
+} SK_HW_FEATURES;
+
+/*
+ * MAC specific functions
+ */
+typedef struct s_GeMacFunc {
+	int	(*pFnMacUpdateStats)(SK_AC *, SK_IOC, unsigned int);
+	int	(*pFnMacStatistic)(SK_AC *, SK_IOC, unsigned int, SK_U16, SK_U32 SK_FAR *);
+	int	(*pFnMacResetCounter)(SK_AC *, SK_IOC, unsigned int);
+	int	(*pFnMacOverflow)(SK_AC *, SK_IOC, unsigned int, SK_U16, SK_U64 SK_FAR *);
+	void (*pSkGeSirqIsr)(SK_AC *, SK_IOC, SK_U32);
+#ifdef SK_DIAG
+	int	(*pFnMacPhyRead)(SK_AC *, SK_IOC, int, int, SK_U16 SK_FAR *);
+	int	(*pFnMacPhyWrite)(SK_AC *, SK_IOC, int, int, SK_U16);
+#endif /* SK_DIAG */
+} SK_GEMACFUNC;
+
+/*
+ * Port Structure
+ */
+typedef	struct s_GePort {
+#ifndef SK_DIAG
+	SK_TIMER	PWaTimer;	/* Workaround Timer */
+	SK_TIMER	HalfDupChkTimer;
+#endif /* !SK_DIAG */
+	SK_U32	PPrevShorts;	/* Previous Short Counter checking */
+	SK_U32	PPrevFcs;		/* Previous FCS Error Counter checking */
+	SK_U64	PPrevRx;		/* Previous RxOk Counter checking */
+	SK_U64	PRxLim;			/* Previous RxOk Counter checking */
+	SK_U64	LastOctets;		/* For half duplex hang check */
+	int		PLinkResCt;		/* Link Restart Counter */
+	int		PAutoNegTimeOut;/* Auto-negotiation timeout current value */
+	int		PAutoNegTOCt;	/* Auto-negotiation Timeout Counter */
+	int		PRxQSize;		/* Port Rx Queue Size in kB */
+	int		PXSQSize;		/* Port Synchronous  Transmit Queue Size in kB */
+	int		PXAQSize;		/* Port Asynchronous Transmit Queue Size in kB */
+	SK_U32	PRxQRamStart;	/* Receive Queue RAM Buffer Start Address */
+	SK_U32	PRxQRamEnd;		/* Receive Queue RAM Buffer End Address */
+	SK_U32	PXsQRamStart;	/* Sync Tx Queue RAM Buffer Start Address */
+	SK_U32	PXsQRamEnd;		/* Sync Tx Queue RAM Buffer End Address */
+	SK_U32	PXaQRamStart;	/* Async Tx Queue RAM Buffer Start Address */
+	SK_U32	PXaQRamEnd;		/* Async Tx Queue RAM Buffer End Address */
+	SK_U32	PRxOverCnt;		/* Receive Overflow Counter */
+	int		PRxQOff;		/* Rx Queue Address Offset */
+	int		PXsQOff;		/* Synchronous Tx Queue Address Offset */
+	int		PXaQOff;		/* Asynchronous Tx Queue Address Offset */
+	int		PhyType;		/* PHY used on this port */
+	int		PState;			/* Port status (reset, stop, init, run) */
+	int		PPortUsage;		/* Driver Port Usage */
+	SK_U16	PhyId1;			/* PHY Id1 on this port */
+	SK_U16	PhyAddr;		/* MDIO/MDC PHY address */
+	SK_U16	PIsave;			/* Saved Interrupt status word */
+	SK_U16	PSsave;			/* Saved PHY status word */
+	SK_U16	PGmANegAdv;		/* Saved GPhy AutoNegAdvertisment register */
+	SK_BOOL	PHWLinkUp;		/* The hardware Link is up (wiring) */
+	SK_BOOL	PLinkBroken;	/* Is Link broken ? */
+	SK_BOOL	PCheckPar;		/* Do we check for parity errors ? */
+	SK_BOOL	HalfDupTimerActive;
+	SK_U8	PLinkCap;		/* Link Capabilities */
+	SK_U8	PLinkModeConf;	/* Link Mode configured */
+	SK_U8	PLinkMode;		/* Link Mode currently used */
+	SK_U8	PLinkModeStatus;/* Link Mode Status */
+	SK_U8	PLinkSpeedCap;	/* Link Speed Capabilities (10/100/1000 Mbps) */
+	SK_U8	PLinkSpeed;		/* configured Link Speed (10/100/1000 Mbps) */
+	SK_U8	PLinkSpeedUsed;	/* current Link Speed (10/100/1000 Mbps) */
+	SK_U8	PFlowCtrlCap;	/* Flow Control Capabilities */
+	SK_U8	PFlowCtrlMode;	/* Flow Control Mode */
+	SK_U8	PFlowCtrlStatus;/* Flow Control Status */
+	SK_U8	PMSCap;			/* Master/Slave Capabilities */
+	SK_U8	PMSMode;		/* Master/Slave Mode */
+	SK_U8	PMSStatus;		/* Master/Slave Status */
+	SK_BOOL	PEnDetMode;		/* Energy Detect Mode */
+	SK_BOOL	PAutoNegFail;	/* Auto-negotiation fail flag */
+	SK_U8	PLipaAutoNeg;	/* Auto-negotiation possible with Link Partner */
+	SK_U8	PCableLen;		/* Cable Length */
+	SK_U8	PMdiPairLen[4];	/* MDI[0..3] Pair Length */
+	SK_U8	PMdiPairSts[4];	/* MDI[0..3] Pair Diagnostic Status */
+	SK_U8	PPhyPowerState;	/* PHY current power state */
+	int		PMacColThres;	/* MAC Collision Threshold */
+	int		PMacJamLen;		/* MAC Jam length */
+	int		PMacJamIpgVal;	/* MAC Jam IPG */
+	int		PMacJamIpgData;	/* MAC IPG Jam to Data */
+	int		PMacBackOffLim;	/* MAC Back-off Limit */
+	int		PMacDataBlind;	/* MAC Data Blinder */
+	int		PMacIpgData;	/* MAC Data IPG */
+	SK_U16	PMacAddr[3];	/* MAC address */
+	SK_BOOL PMacLimit4;		/* reset collision counter and backoff algorithm */
+} SK_GEPORT;
+
+/*
+ * Gigabit Ethernet Initialization Struct
+ * (has to be included in the adapter context)
+ */
+typedef	struct s_GeInit {
+	int			GIChipId;		/* Chip Identification Number */
+	int			GIChipRev;		/* Chip Revision Number */
+	SK_U8		GIPciHwRev;		/* PCI HW Revision Number */
+	SK_U8		GIPciBus;		/* PCI Bus Type (PCI / PCI-X / PCI-Express) */
+	SK_U8		GIPciMode;		/* PCI / PCI-X Mode @ Clock */
+	SK_U8		GIPexWidth;		/* PCI-Express Negotiated Link Width */
+	SK_BOOL		GIGenesis;		/* Genesis adapter ? */
+	SK_BOOL		GIYukon;		/* YUKON family (1 and 2) */
+	SK_BOOL		GIYukonLite;	/* YUKON-Lite chip */
+	SK_BOOL		GIYukon2;		/* YUKON-2 chip (-XL, -EC or -FE) */
+	SK_U8		GIConTyp;		/* Connector Type */
+	SK_U8		GIPmdTyp;		/* PMD Type */
+	SK_BOOL		GICopperType;	/* Copper Type adapter ? */
+	SK_BOOL		GIPciSlot64;	/* 64-bit PCI Slot */
+	SK_BOOL		GIPciClock66;	/* 66 MHz PCI Clock */
+	SK_BOOL		GIVauxAvail;	/* VAUX available (YUKON) */
+	SK_BOOL		GIVMainAvail;	/* VMAIN available */
+	SK_BOOL		GIYukon32Bit;	/* 32-Bit YUKON adapter */
+	SK_BOOL		GIAsfEnabled;	/* ASF subsystem enabled */
+	SK_BOOL		GIAsfRunning;	/* ASF subsystem running */
+	SK_BOOL		GIExtLeFormat;	/* Extended list element format (Yukon-Ext) */
+	SK_BOOL		GIJumTcpSegSup;	/* TCP Segmentation of Jumbo frames supported ?*/
+	SK_BOOL		GIGotoD3Cold;	/* System set to D3cold */
+	SK_U16		GILedBlinkCtrl;	/* LED Blink Control */
+	int			GIMacsFound;	/* Number of MACs found on this adapter */
+	int			GIMacType;		/* MAC Type used on this adapter */
+	int			GIChipCap;		/* Adapter's Capabilities */
+	int			GIHwResInfo;	/* HW Resources / Application Information */
+	int			GIHstClkFact;	/* Host Clock Factor (HstClk / 62.5 * 100) */
+	int			GILevel;		/* Initialization Level completed */
+	int			GIRamSize;		/* The RAM size of the adapter in kB */
+	int			GIWolOffs;		/* WOL Register Offset (HW-Bug in Rev. A) */
+	int			GIPexCapOffs;	/* PCI-E Capability Reg Off (moved in Y-Ex B0)*/
+	int			GINumOfPattern;	/* Number of Pattern supported by HW */
+	int			GITxIdxRepThres;/* Tx Index reporting threshold */
+	SK_U32		GIRamOffs;		/* RAM Address Offset for addr calculation */
+	SK_U32		GIPollTimerVal;	/* Descr. Poll Timer Init Val (HstClk ticks) */
+	SK_U32		GIValIrqMask;	/* Value for Interrupt Mask */
+	SK_U32		GIValHwIrqMask;	/* Value for HWE Interrupt Mask */
+	SK_U32		GITimeStampCnt;	/* Time Stamp High Counter (YUKON only) */
+	SK_GEPORT	GP[SK_MAX_MACS];/* Port Dependent Information */
+	SK_HW_FEATURES HwF;			/* HW Features struct */
+	SK_GEMACFUNC GIFunc;		/* MAC depedent functions */
+} SK_GEINIT;
+
+/*
+ * Error numbers and messages for skxmac2.c and skgeinit.c
+ */
+#define SKERR_HWI_E001		(SK_ERRBASE_HWINIT+1)
+#define SKERR_HWI_E001MSG	"SkXmClrExactAddr() has got illegal parameters"
+#define SKERR_HWI_E002		(SKERR_HWI_E001+1)
+#define SKERR_HWI_E002MSG	"SkGeInit(): Level 1 call missing"
+#define SKERR_HWI_E003		(SKERR_HWI_E002+1)
+#define SKERR_HWI_E003MSG	"SkGeInit() called with illegal init Level"
+#define SKERR_HWI_E004		(SKERR_HWI_E003+1)
+#define SKERR_HWI_E004MSG	"SkGeInitPort(): Queue Size illegal configured"
+#define SKERR_HWI_E005		(SKERR_HWI_E004+1)
+#define SKERR_HWI_E005MSG	"SkGeInitPort(): cannot init running ports"
+#define SKERR_HWI_E006		(SKERR_HWI_E005+1)
+#define SKERR_HWI_E006MSG	"SkGeInit() called with illegal Chip Id"
+#define SKERR_HWI_E007		(SKERR_HWI_E006+1)
+#define SKERR_HWI_E007MSG	"SkXmInitDupMd() called with invalid Dup Mode"
+#define SKERR_HWI_E008		(SKERR_HWI_E007+1)
+#define SKERR_HWI_E008MSG	"SkXmSetRxCmd() called with invalid Mode"
+#define SKERR_HWI_E009		(SKERR_HWI_E008+1)
+#define SKERR_HWI_E009MSG	"SkGeCfgSync() called although PXSQSize zero"
+#define SKERR_HWI_E010		(SKERR_HWI_E009+1)
+#define SKERR_HWI_E010MSG	"SkGeCfgSync() called with invalid parameters"
+#define SKERR_HWI_E011		(SKERR_HWI_E010+1)
+#define SKERR_HWI_E011MSG	"SkGeInitPort(): Receive Queue Size too small"
+#define SKERR_HWI_E012		(SKERR_HWI_E011+1)
+#define SKERR_HWI_E012MSG	"SkGeInitPort(): invalid Queue Size specified"
+#define SKERR_HWI_E013		(SKERR_HWI_E012+1)
+#define SKERR_HWI_E013MSG	"SkGeInitPort(): cfg changed for running queue"
+#define SKERR_HWI_E014		(SKERR_HWI_E013+1)
+#define SKERR_HWI_E014MSG	"SkGeInitPort(): unknown PortUsage specified"
+#define SKERR_HWI_E015		(SKERR_HWI_E014+1)
+#define SKERR_HWI_E015MSG	"Illegal Link Mode parameter"
+#define SKERR_HWI_E016		(SKERR_HWI_E015+1)
+#define SKERR_HWI_E016MSG	"Illegal Flow Control Mode parameter"
+#define SKERR_HWI_E017		(SKERR_HWI_E016+1)
+#define SKERR_HWI_E017MSG	"Illegal value specified for GIPollTimerVal"
+#define SKERR_HWI_E018		(SKERR_HWI_E017+1)
+#define SKERR_HWI_E018MSG	"FATAL: SkGeStopPort() does not terminate (Tx)"
+#define SKERR_HWI_E019		(SKERR_HWI_E018+1)
+#define SKERR_HWI_E019MSG	"Illegal Speed parameter"
+#define SKERR_HWI_E020		(SKERR_HWI_E019+1)
+#define SKERR_HWI_E020MSG	"Illegal Master/Slave parameter"
+#define SKERR_HWI_E021		(SKERR_HWI_E020+1)
+#define SKERR_HWI_E021MSG	"MacUpdateStats(): cannot update statistic counter"
+#define SKERR_HWI_E022		(SKERR_HWI_E021+1)
+#define SKERR_HWI_E022MSG	"MacStatistic(): illegal statistic base address"
+#define SKERR_HWI_E023		(SKERR_HWI_E022+1)
+#define SKERR_HWI_E023MSG	"SkGeInitPort(): Transmit Queue Size too small"
+#define SKERR_HWI_E024		(SKERR_HWI_E023+1)
+#define SKERR_HWI_E024MSG	"FATAL: SkGeStopPort() does not terminate (Rx)"
+#define SKERR_HWI_E025		(SKERR_HWI_E024+1)
+#define SKERR_HWI_E025MSG	"Link Partner not Auto-Neg. able"
+#define SKERR_HWI_E026		(SKERR_HWI_E025+1)
+#define SKERR_HWI_E026MSG	"PEX negotiated Link width not max."
+#define SKERR_HWI_E027		(SKERR_HWI_E026+1)
+#define SKERR_HWI_E027MSG	""
+
+/* function prototypes ********************************************************/
+
+#ifndef	SK_KR_PROTO
+
+/*
+ * public functions in skgeinit.c
+ */
+extern void SkGePortVlan(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL Enable);
+
+extern void SkGeRxRss(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	Enable);
+
+extern void SkGeRxCsum(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL Enable);
+
+extern void	SkGePollRxD(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	PollRxD);
+
+extern void	SkGePollTxD(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL PollTxD);
+
+extern void	SkGeYellowLED(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		State);
+
+extern int	SkGeCfgSync(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_U32	IntTime,
+	SK_U32	LimCount,
+	int		SyncMode);
+
+extern void	SkGeLoadLnkSyncCnt(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_U32	CntVal);
+
+extern void	SkGeStopPort(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Dir,
+	int		RstMode);
+
+extern int	SkGeInit(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Level);
+
+extern void	SkGeDeInit(
+	SK_AC	*pAC,
+	SK_IOC	IoC);
+
+extern int	SkGeInitPort(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkGeXmitLED(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Led,
+	int		Mode);
+
+extern void	SkGeInitRamIface(
+	SK_AC	*pAC,
+	SK_IOC	IoC);
+
+extern int	SkGeInitAssignRamToQueues(
+	SK_AC	*pAC,
+	int		Port,
+	SK_BOOL	DualNet);
+
+extern void	DoInitRamQueue(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		QuIoOffs,
+	SK_U32	QuStartAddr,
+	SK_U32	QuEndAddr,
+	int		QuType);
+
+extern int	SkYuk2RestartRxBmu(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void SkYuk2StopTx(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+extern void SkYuk2StartTx(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+/*
+ * public functions in skxmac2.c
+ */
+extern void SkMacRxTxDisable(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkMacSoftRst(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkMacHardRst(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkMacClearRst(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkXmInitMac(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkGmInitMac(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void SkMacInitPhy(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	DoLoop);
+
+extern void SkMacIrqDisable(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkMacFlushTxFifo(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkMacFlushRxFifo(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkMacIrq(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern int	SkMacAutoNegDone(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkMacAutoNegLipaPhy(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_U16	IStatus);
+
+extern void	SkMacSetRxTxEn(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Para);
+
+extern int	SkMacRxTxEnable(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkMacPromiscMode(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	Enable);
+
+extern void	SkMacHashing(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	Enable);
+
+extern void	SkMacTimeStamp(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	Enable);
+
+extern int	SkXmPhyRead(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Addr,
+	SK_U16	SK_FAR *pVal);
+
+extern int	SkXmPhyWrite(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Addr,
+	SK_U16	Val);
+
+extern int	SkGmPhyRead(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Addr,
+	SK_U16	SK_FAR *pVal);
+
+extern int	SkGmPhyWrite(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Addr,
+	SK_U16	Val);
+
+extern void	SkXmClrExactAddr(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		StartNum,
+	int		StopNum);
+
+extern void	SkXmInitDupMd(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkXmInitPauseMd(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+
+extern void	SkXmAutoNegLipaXmac(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_U16	IStatus);
+
+extern int SkXmUpdateStats(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Port);
+
+extern int SkGmUpdateStats(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Port);
+
+extern int SkXmMacStatistic(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Port,
+	SK_U16	StatAddr,
+	SK_U32	SK_FAR *pVal);
+
+extern int SkGmMacStatistic(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Port,
+	SK_U16	StatAddr,
+	SK_U32	SK_FAR *pVal);
+
+extern int SkXmResetCounter(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Port);
+
+extern int SkGmResetCounter(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Port);
+
+extern int SkXmOverflowStatus(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Port,
+	SK_U16	IStatus,
+	SK_U64	SK_FAR *pStatus);
+
+extern int SkGmOverflowStatus(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Port,
+	SK_U16	MacStatus,
+	SK_U64	SK_FAR *pStatus);
+
+extern int SkGmCableDiagStatus(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	StartTest);
+
+#ifdef SK_PHY_LP_MODE
+extern int SkGmEnterLowPowerMode(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_U8	Mode);
+
+extern int SkGmLeaveLowPowerMode(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port);
+#endif /* SK_PHY_LP_MODE */
+
+#ifdef SK_DIAG
+extern void	SkGePhyRead(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Addr,
+	SK_U16	*pVal);
+
+extern void	SkGePhyWrite(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Addr,
+	SK_U16	Val);
+
+extern void	SkMacSetRxCmd(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	int		Mode);
+extern void	SkMacCrcGener(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	Enable);
+extern void	SkXmSendCont(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Port,
+	SK_BOOL	Enable);
+#endif /* SK_DIAG */
+
+#else	/* SK_KR_PROTO */
+
+/*
+ * public functions in skgeinit.c
+ */
+extern void	SkGePollRxD();
+extern void	SkGePollTxD();
+extern void	SkGeYellowLED();
+extern int	SkGeCfgSync();
+extern void	SkGeLoadLnkSyncCnt();
+extern void	SkGeStopPort();
+extern int	SkGeInit();
+extern void	SkGeDeInit();
+extern int	SkGeInitPort();
+extern void	SkGeXmitLED();
+extern void	SkGeInitRamIface();
+extern int	SkGeInitAssignRamToQueues();
+extern void	SkGePortVlan();
+extern void	SkGeRxCsum();
+extern void	SkGeRxRss();
+extern void	DoInitRamQueue();
+extern int	SkYuk2RestartRxBmu();
+extern void SkYuk2StopTx();
+extern void SkYuk2StartTx();
+
+/*
+ * public functions in skxmac2.c
+ */
+extern void	SkMacRxTxDisable();
+extern void	SkMacSoftRst();
+extern void	SkMacHardRst();
+extern void	SkMacClearRst();
+extern void	SkMacInitPhy();
+extern int	SkMacRxTxEnable();
+extern void	SkMacPromiscMode();
+extern void	SkMacHashing();
+extern void	SkMacIrqDisable();
+extern void	SkMacFlushTxFifo();
+extern void	SkMacFlushRxFifo();
+extern void	SkMacIrq();
+extern int	SkMacAutoNegDone();
+extern void	SkMacAutoNegLipaPhy();
+extern void	SkMacSetRxTxEn();
+extern void	SkMacTimeStamp();
+extern void	SkXmInitMac();
+extern int	SkXmPhyRead();
+extern int	SkXmPhyWrite();
+extern void	SkGmInitMac();
+extern int	SkGmPhyRead();
+extern int	SkGmPhyWrite();
+extern void	SkXmClrExactAddr();
+extern void	SkXmInitDupMd();
+extern void	SkXmInitPauseMd();
+extern void	SkXmAutoNegLipaXmac();
+extern int	SkXmUpdateStats();
+extern int	SkGmUpdateStats();
+extern int	SkXmMacStatistic();
+extern int	SkGmMacStatistic();
+extern int	SkXmResetCounter();
+extern int	SkGmResetCounter();
+extern int	SkXmOverflowStatus();
+extern int	SkGmOverflowStatus();
+extern int	SkGmCableDiagStatus();
+#ifdef SK_PHY_LP_MODE
+extern int	SkGmEnterLowPowerMode();
+extern int	SkGmLeaveLowPowerMode();
+#endif /* SK_PHY_LP_MODE */
+
+#ifdef SK_DIAG
+extern void	SkGePhyRead();
+extern void	SkGePhyWrite();
+extern void	SkMacSetRxCmd();
+extern void	SkMacCrcGener();
+extern void	SkXmSendCont();
+#endif /* SK_DIAG */
+
+#endif /* SK_KR_PROTO */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INC_SKGEINIT_H_ */
+
diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
new file mode 100755
index 0000000..b1f1217
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgepnm2.h
@@ -0,0 +1,341 @@
+/*****************************************************************************
+ *
+ * Name:	skgepnm2.h
+ * Project:	Gigabit Ethernet Adapters, PNMI-Module
+ * Version:	$Revision: 2.6 $
+ * Date:	$Date: 2007/01/17 15:15:23 $
+ * Purpose:	Defines for Private Network Management Interface
+ *
+ ****************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef _SKGEPNM2_H_
+#define _SKGEPNM2_H_
+
+/*
+ * General definitions
+ */
+#define SK_PNMI_CHIPSET_XMAC		1	/* XMAC11800FP */
+#define SK_PNMI_CHIPSET_YUKON		2	/* YUKON */
+#define SK_PNMI_CHIPSET_YUKON_LITE	3	/* YUKON-Lite (Rev. A1-A3) */
+#define SK_PNMI_CHIPSET_YUKON_LP	4	/* YUKON-LP */
+#define SK_PNMI_CHIPSET_YUKON_XL	5	/* YUKON-2 XL */
+#define SK_PNMI_CHIPSET_YUKON_EC	6	/* YUKON-2 EC */
+#define SK_PNMI_CHIPSET_YUKON_FE	7	/* YUKON-2 FE */
+
+#define SK_PNMI_BUS_PCI		1	/* PCI bus*/
+
+/*
+ * Actions
+ */
+#define SK_PNMI_ACT_IDLE		1
+#define SK_PNMI_ACT_RESET		2
+#define SK_PNMI_ACT_SELFTEST	3
+#define SK_PNMI_ACT_RESETCNT	4
+
+/*
+ * VPD releated defines
+ */
+
+#define SK_PNMI_VPD_RW		1
+#define SK_PNMI_VPD_RO		2
+
+#define SK_PNMI_VPD_OK			0
+#define SK_PNMI_VPD_NOTFOUND	1
+#define SK_PNMI_VPD_CUT			2
+#define SK_PNMI_VPD_TIMEOUT		3
+#define SK_PNMI_VPD_FULL		4
+#define SK_PNMI_VPD_NOWRITE		5
+#define SK_PNMI_VPD_FATAL		6
+
+#define SK_PNMI_VPD_IGNORE	0
+#define SK_PNMI_VPD_CREATE	1
+#define SK_PNMI_VPD_DELETE	2
+
+
+/*
+ * RLMT related defines
+ */
+#define SK_PNMI_DEF_RLMT_CHG_THRES	240	/* 4 changes per minute */
+
+
+/*
+ * VCT internal status values
+ */
+#define SK_PNMI_VCT_PENDING		0x20
+#define SK_PNMI_VCT_TEST_DONE	0x40
+#define SK_PNMI_VCT_LINK		0x80
+
+/*
+ * Internal table definitions
+ */
+#define SK_PNMI_GET		0
+#define SK_PNMI_PRESET	1
+#define SK_PNMI_SET		2
+
+#define SK_PNMI_RO		0
+#define SK_PNMI_RW		1
+#define SK_PNMI_WO		2
+
+typedef struct s_OidTabEntry {
+	SK_U32			Id;
+	SK_U32			InstanceNo;
+	unsigned int	StructSize;
+	unsigned int	Offset;
+	int				Access;
+	int				(* Func)(SK_AC *pAc, SK_IOC pIo, int action,
+							 SK_U32 Id, char* pBuf, unsigned int* pLen,
+							 SK_U32 Instance, unsigned int TableIndex,
+							 SK_U32 NetNumber);
+	SK_U16			Param;
+} SK_PNMI_TAB_ENTRY;
+
+
+/*
+ * Trap lengths
+ */
+#define SK_PNMI_TRAP_SIMPLE_LEN			17
+#define SK_PNMI_TRAP_SENSOR_LEN_BASE	46
+#define SK_PNMI_TRAP_RLMT_CHANGE_LEN	23
+#define SK_PNMI_TRAP_RLMT_PORT_LEN		23
+
+/*
+ * Number of MAC types supported
+ */
+#define SK_PNMI_MAC_TYPES	(SK_MAC_GMAC + 1)
+
+/*
+ * MAC statistic data list (overall set for MAC types used)
+ */
+enum SK_MACSTATS {
+	SK_PNMI_HTX				= 0,
+	SK_PNMI_HTX_OCTET,
+	SK_PNMI_HTX_OCTETHIGH 	= SK_PNMI_HTX_OCTET,
+	SK_PNMI_HTX_OCTETLOW,
+	SK_PNMI_HTX_BROADCAST,
+	SK_PNMI_HTX_MULTICAST,
+	SK_PNMI_HTX_UNICAST,
+	SK_PNMI_HTX_BURST,
+	SK_PNMI_HTX_PMACC,
+	SK_PNMI_HTX_MACC,
+	SK_PNMI_HTX_COL,
+	SK_PNMI_HTX_SINGLE_COL,
+	SK_PNMI_HTX_MULTI_COL,
+	SK_PNMI_HTX_EXCESS_COL,
+	SK_PNMI_HTX_LATE_COL,
+	SK_PNMI_HTX_DEFFERAL,
+	SK_PNMI_HTX_EXCESS_DEF,
+	SK_PNMI_HTX_UNDERRUN,
+	SK_PNMI_HTX_CARRIER,
+	SK_PNMI_HTX_UTILUNDER,
+	SK_PNMI_HTX_UTILOVER,
+	SK_PNMI_HTX_64,
+	SK_PNMI_HTX_127,
+	SK_PNMI_HTX_255,
+	SK_PNMI_HTX_511,
+	SK_PNMI_HTX_1023,
+	SK_PNMI_HTX_MAX,
+	SK_PNMI_HTX_LONGFRAMES,
+	SK_PNMI_HTX_SYNC,
+	SK_PNMI_HTX_SYNC_OCTET,
+	SK_PNMI_HTX_RESERVED,
+
+	SK_PNMI_HRX,
+	SK_PNMI_HRX_OCTET,
+	SK_PNMI_HRX_OCTETHIGH	= SK_PNMI_HRX_OCTET,
+	SK_PNMI_HRX_OCTETLOW,
+	SK_PNMI_HRX_BADOCTET,
+	SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET,
+	SK_PNMI_HRX_BADOCTETLOW,
+	SK_PNMI_HRX_BROADCAST,
+	SK_PNMI_HRX_MULTICAST,
+	SK_PNMI_HRX_UNICAST,
+	SK_PNMI_HRX_PMACC,
+	SK_PNMI_HRX_MACC,
+	SK_PNMI_HRX_PMACC_ERR,
+	SK_PNMI_HRX_MACC_UNKWN,
+	SK_PNMI_HRX_BURST,
+	SK_PNMI_HRX_MISSED,
+	SK_PNMI_HRX_FRAMING,
+	SK_PNMI_HRX_UNDERSIZE,
+	SK_PNMI_HRX_OVERFLOW,
+	SK_PNMI_HRX_JABBER,
+	SK_PNMI_HRX_CARRIER,
+	SK_PNMI_HRX_IRLENGTH,
+	SK_PNMI_HRX_SYMBOL,
+	SK_PNMI_HRX_SHORTS,
+	SK_PNMI_HRX_RUNT,
+	SK_PNMI_HRX_TOO_LONG,
+	SK_PNMI_HRX_FCS,
+	SK_PNMI_HRX_CEXT,
+	SK_PNMI_HRX_UTILUNDER,
+	SK_PNMI_HRX_UTILOVER,
+	SK_PNMI_HRX_64,
+	SK_PNMI_HRX_127,
+	SK_PNMI_HRX_255,
+	SK_PNMI_HRX_511,
+	SK_PNMI_HRX_1023,
+	SK_PNMI_HRX_MAX,
+	SK_PNMI_HRX_LONGFRAMES,
+
+	SK_PNMI_HRX_RESERVED,
+
+	SK_PNMI_MAX_IDX		/* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */
+};
+
+/*
+ * MAC specific data
+ */
+typedef struct s_PnmiStatAddr {
+	SK_U16		Reg;		/* MAC register containing the value */
+	SK_BOOL		GetOffset;	/* TRUE: Offset managed by PNMI (GetStatVal()) */
+} SK_PNMI_STATADDR;
+
+
+/*
+ * SK_PNMI_STRUCT_DATA copy offset evaluation macros
+ */
+#define SK_PNMI_OFF(e)		((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
+#define SK_PNMI_MAI_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
+#define SK_PNMI_VPD_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e))
+#define SK_PNMI_SEN_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e))
+#define SK_PNMI_CHK_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e))
+#define SK_PNMI_STA_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e))
+#define SK_PNMI_CNF_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e))
+#define SK_PNMI_RLM_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e))
+#define SK_PNMI_MON_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e))
+#define SK_PNMI_TRP_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e))
+
+#define SK_PNMI_SET_STAT(b,s,o)	{SK_U32	Val32; char *pVal; \
+					Val32 = (s); \
+					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
+						&(((SK_PNMI_STRUCT_DATA *)0)-> \
+						ReturnStatus.ErrorStatus)); \
+					SK_PNMI_STORE_U32(pVal, Val32); \
+					Val32 = (o); \
+					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
+						&(((SK_PNMI_STRUCT_DATA *)0)-> \
+						ReturnStatus.ErrorOffset)); \
+					SK_PNMI_STORE_U32(pVal, Val32);}
+
+/*
+ * Time macros
+ */
+#ifndef SK_PNMI_HUNDREDS_SEC
+#if SK_TICKS_PER_SEC == 100
+#define SK_PNMI_HUNDREDS_SEC(t)	(t)
+#else
+#define SK_PNMI_HUNDREDS_SEC(t)	(((t) * 100) / (SK_TICKS_PER_SEC))
+#endif /* !SK_TICKS_PER_SEC */
+#endif /* !SK_PNMI_HUNDREDS_SEC */
+
+/*
+ * Macros to work around alignment problems
+ */
+#ifndef SK_PNMI_STORE_U16
+#define SK_PNMI_STORE_U16(p,v)	{*(char *)(p) = *((char *)&(v)); \
+					*((char *)(p) + 1) = \
+						*(((char *)&(v)) + 1);}
+#endif
+
+#ifndef SK_PNMI_STORE_U32
+#define SK_PNMI_STORE_U32(p,v)	{*(char *)(p) = *((char *)&(v)); \
+					*((char *)(p) + 1) = \
+						*(((char *)&(v)) + 1); \
+					*((char *)(p) + 2) = \
+						*(((char *)&(v)) + 2); \
+					*((char *)(p) + 3) = \
+						*(((char *)&(v)) + 3);}
+#endif
+
+#ifndef SK_PNMI_STORE_U64
+#define SK_PNMI_STORE_U64(p,v)	{*(char *)(p) = *((char *)&(v)); \
+					*((char *)(p) + 1) = \
+						*(((char *)&(v)) + 1); \
+					*((char *)(p) + 2) = \
+						*(((char *)&(v)) + 2); \
+					*((char *)(p) + 3) = \
+						*(((char *)&(v)) + 3); \
+					*((char *)(p) + 4) = \
+						*(((char *)&(v)) + 4); \
+					*((char *)(p) + 5) = \
+						*(((char *)&(v)) + 5); \
+					*((char *)(p) + 6) = \
+						*(((char *)&(v)) + 6); \
+					*((char *)(p) + 7) = \
+						*(((char *)&(v)) + 7);}
+#endif
+
+#ifndef SK_PNMI_READ_U16
+#define SK_PNMI_READ_U16(p,v)	{*((char *)&(v)) = *(char *)(p); \
+					*(((char *)&(v)) + 1) = \
+						*((char *)(p) + 1);}
+#endif
+
+#ifndef SK_PNMI_READ_U32
+#define SK_PNMI_READ_U32(p,v)	{*((char *)&(v)) = *(char *)(p); \
+					*(((char *)&(v)) + 1) = \
+						*((char *)(p) + 1); \
+					*(((char *)&(v)) + 2) = \
+						*((char *)(p) + 2); \
+					*(((char *)&(v)) + 3) = \
+						*((char *)(p) + 3);}
+#endif
+
+#ifndef SK_PNMI_READ_U64
+#define SK_PNMI_READ_U64(p,v)	{*((char *)&(v)) = *(char *)(p); \
+					*(((char *)&(v)) + 1) = \
+						*((char *)(p) + 1); \
+					*(((char *)&(v)) + 2) = \
+						*((char *)(p) + 2); \
+					*(((char *)&(v)) + 3) = \
+						*((char *)(p) + 3); \
+					*(((char *)&(v)) + 4) = \
+						*((char *)(p) + 4); \
+					*(((char *)&(v)) + 5) = \
+						*((char *)(p) + 5); \
+					*(((char *)&(v)) + 6) = \
+						*((char *)(p) + 6); \
+					*(((char *)&(v)) + 7) = \
+						*((char *)(p) + 7);}
+#endif
+
+/*
+ * Macros for Debug
+ */
+#ifdef DEBUG
+
+#define SK_PNMI_CHECKFLAGS(vSt)	{if (pAC->Pnmi.MacUpdatedFlag > 0 || \
+					pAC->Pnmi.RlmtUpdatedFlag > 0 || \
+					pAC->Pnmi.SirqUpdatedFlag > 0) { \
+						SK_DBG_MSG(pAC, \
+						SK_DBGMOD_PNMI, \
+						SK_DBGCAT_CTRL,	\
+						("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \
+						vSt, \
+						pAC->Pnmi.MacUpdatedFlag, \
+						pAC->Pnmi.RlmtUpdatedFlag, \
+						pAC->Pnmi.SirqUpdatedFlag));}}
+
+#else	/* !DEBUG */
+
+#define SK_PNMI_CHECKFLAGS(vSt)	/* Nothing */
+
+#endif	/* !DEBUG */
+
+#endif	/* _SKGEPNM2_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
new file mode 100755
index 0000000..235a7e7
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgepnmi.h
@@ -0,0 +1,1037 @@
+/*****************************************************************************
+ *
+ * Name:	skgepnmi.h
+ * Project:	Gigabit Ethernet Adapters, PNMI-Module
+ * Version:	$Revision: 2.17 $
+ * Date:	$Date: 2007/09/03 14:45:02 $
+ * Purpose:	Defines for Private Network Management Interface
+ *
+ ****************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef _SKGEPNMI_H_
+#define _SKGEPNMI_H_
+
+/*
+ * Include dependencies
+ */
+#include "h/sktypes.h"
+#include "h/skerror.h"
+#include "h/sktimer.h"
+#include "h/sktwsi.h"
+#include "h/skaddr.h"
+#include "h/skrlmt.h"
+#include "h/skvpd.h"
+
+/*
+ * Management Database Version
+ */
+#define SK_PNMI_MDB_VERSION		0x00030001	/* 3.1 */
+
+/*
+ * Event definitions
+ */
+#define SK_PNMI_EVT_SIRQ_OVERFLOW		1	/* Counter overflow */
+#define SK_PNMI_EVT_SEN_WAR_LOW			2	/* Lower war thres exceeded */
+#define SK_PNMI_EVT_SEN_WAR_UPP			3	/* Upper war thres exceeded */
+#define SK_PNMI_EVT_SEN_ERR_LOW			4	/* Lower err thres exceeded */
+#define SK_PNMI_EVT_SEN_ERR_UPP			5	/* Upper err thres exceeded */
+#define SK_PNMI_EVT_CHG_EST_TIMER		6	/* Timer event for RLMT Chg */
+#define SK_PNMI_EVT_UTILIZATION_TIMER	7	/* Timer event for Utiliza. */
+#define SK_PNMI_EVT_CLEAR_COUNTER		8	/* Clear statistic counters */
+#define SK_PNMI_EVT_XMAC_RESET			9	/* XMAC will be reset */
+#define SK_PNMI_EVT_RLMT_PORT_UP		10	/* Port came logically up */
+#define SK_PNMI_EVT_RLMT_PORT_DOWN		11	/* Port went logically down */
+#define SK_PNMI_EVT_RLMT_SEGMENTATION	13	/* Two SP root bridges found */
+#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN	14	/* Port went logically down */
+#define SK_PNMI_EVT_RLMT_ACTIVE_UP		15	/* Port came logically up */
+#define SK_PNMI_EVT_RLMT_SET_NETS		16	/* Number of nets (1 or 2). */
+#define SK_PNMI_EVT_VCT_RESET			17	/* VCT port reset timer event started with SET. */
+
+/*
+ * Return values
+ */
+#define SK_PNMI_ERR_OK				0
+#define SK_PNMI_ERR_GENERAL			1
+#define SK_PNMI_ERR_TOO_SHORT		2
+#define SK_PNMI_ERR_BAD_VALUE		3
+#define SK_PNMI_ERR_READ_ONLY		4
+#define SK_PNMI_ERR_UNKNOWN_OID		5
+#define SK_PNMI_ERR_UNKNOWN_INST	6
+#define SK_PNMI_ERR_UNKNOWN_NET 	7
+#define SK_PNMI_ERR_NOT_SUPPORTED	10
+
+/*
+ * Return values of driver reset function SK_DRIVER_RESET() and
+ * driver event function SK_DRIVER_EVENT()
+ */
+#define SK_PNMI_ERR_OK			0
+#define SK_PNMI_ERR_FAIL		1
+
+/*
+ * Return values of driver test function SK_DRIVER_SELFTEST()
+ */
+#define SK_PNMI_TST_UNKNOWN		(1 << 0)
+#define SK_PNMI_TST_TRANCEIVER	(1 << 1)
+#define SK_PNMI_TST_ASIC		(1 << 2)
+#define SK_PNMI_TST_SENSOR		(1 << 3)
+#define SK_PNMI_TST_POWERMGMT	(1 << 4)
+#define SK_PNMI_TST_PCI			(1 << 5)
+#define SK_PNMI_TST_MAC			(1 << 6)
+
+/*
+ * RLMT specific definitions
+ */
+#define SK_PNMI_RLMT_STATUS_STANDBY	1
+#define SK_PNMI_RLMT_STATUS_ACTIVE	2
+#define SK_PNMI_RLMT_STATUS_ERROR	3
+
+#define SK_PNMI_RLMT_LSTAT_PHY_DOWN	1
+#define SK_PNMI_RLMT_LSTAT_AUTONEG	2
+#define SK_PNMI_RLMT_LSTAT_LOG_DOWN	3
+#define SK_PNMI_RLMT_LSTAT_LOG_UP	4
+#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5
+
+#define SK_PNMI_RLMT_MODE_CHK_LINK	(SK_RLMT_CHECK_LINK)
+#define SK_PNMI_RLMT_MODE_CHK_RX	(SK_RLMT_CHECK_LOC_LINK)
+#define SK_PNMI_RLMT_MODE_CHK_SPT	(SK_RLMT_CHECK_SEG)
+/* #define SK_PNMI_RLMT_MODE_CHK_EX */
+
+/*
+ * OID definition
+ */
+
+#define SK_PNMI_OID_PSET				0x00400000
+#define SK_PNMI_OID_SET					0x00800000
+
+#ifndef _NDIS_	/* Check, whether NDIS already included OIDs */
+
+#define OID_GEN_XMIT_OK					0x00020101
+#define OID_GEN_RCV_OK					0x00020102
+#define OID_GEN_XMIT_ERROR				0x00020103
+#define OID_GEN_RCV_ERROR				0x00020104
+#define OID_GEN_RCV_NO_BUFFER			0x00020105
+
+/* #define OID_GEN_DIRECTED_BYTES_XMIT	0x00020201 */
+#define OID_GEN_DIRECTED_FRAMES_XMIT	0x00020202
+/* #define OID_GEN_MULTICAST_BYTES_XMIT	0x00020203 */
+#define OID_GEN_MULTICAST_FRAMES_XMIT	0x00020204
+/* #define OID_GEN_BROADCAST_BYTES_XMIT	0x00020205 */
+#define OID_GEN_BROADCAST_FRAMES_XMIT	0x00020206
+/* #define OID_GEN_DIRECTED_BYTES_RCV	0x00020207 */
+#define OID_GEN_DIRECTED_FRAMES_RCV		0x00020208
+/* #define OID_GEN_MULTICAST_BYTES_RCV	0x00020209 */
+#define OID_GEN_MULTICAST_FRAMES_RCV	0x0002020A
+/* #define OID_GEN_BROADCAST_BYTES_RCV	0x0002020B */
+#define OID_GEN_BROADCAST_FRAMES_RCV	0x0002020C
+#define OID_GEN_RCV_CRC_ERROR			0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH	0x0002020E
+
+#define OID_802_3_PERMANENT_ADDRESS		0x01010101
+#define OID_802_3_CURRENT_ADDRESS		0x01010102
+/* #define OID_802_3_MULTICAST_LIST		0x01010103 */
+/* #define OID_802_3_MAXIMUM_LIST_SIZE	0x01010104 */
+/* #define OID_802_3_MAC_OPTIONS		0x01010105 */
+			
+#define OID_802_3_RCV_ERROR_ALIGNMENT	0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION	0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS	0x01020103
+#define OID_802_3_XMIT_DEFERRED			0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS	0x01020202
+#define OID_802_3_RCV_OVERRUN			0x01020203
+#define OID_802_3_XMIT_UNDERRUN			0x01020204
+#define OID_802_3_XMIT_TIMES_CRS_LOST	0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS	0x01020207
+
+/*
+ * PnP and PM OIDs
+ */
+#ifdef SK_POWER_MGMT
+#define OID_PNP_CAPABILITIES			0xFD010100
+#define OID_PNP_SET_POWER				0xFD010101
+#define OID_PNP_QUERY_POWER				0xFD010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN		0xFD010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN	0xFD010104
+#define OID_PNP_ENABLE_WAKE_UP			0xFD010106
+#endif /* SK_POWER_MGMT */
+
+#endif /* _NDIS_ */
+
+#define OID_SKGE_MDB_VERSION			0xFF010100
+#define OID_SKGE_SUPPORTED_LIST			0xFF010101
+#define OID_SKGE_VPD_FREE_BYTES			0xFF010102
+#define OID_SKGE_VPD_ENTRIES_LIST		0xFF010103
+#define OID_SKGE_VPD_ENTRIES_NUMBER		0xFF010104
+#define OID_SKGE_VPD_KEY				0xFF010105
+#define OID_SKGE_VPD_VALUE				0xFF010106
+#define OID_SKGE_VPD_ACCESS				0xFF010107
+#define OID_SKGE_VPD_ACTION				0xFF010108
+			
+#define OID_SKGE_PORT_NUMBER			0xFF010110
+#define OID_SKGE_DEVICE_TYPE			0xFF010111
+#define OID_SKGE_DRIVER_DESCR			0xFF010112
+#define OID_SKGE_DRIVER_VERSION			0xFF010113
+#define OID_SKGE_HW_DESCR				0xFF010114
+#define OID_SKGE_HW_VERSION				0xFF010115
+#define OID_SKGE_CHIPSET				0xFF010116
+#define OID_SKGE_ACTION					0xFF010117
+#define OID_SKGE_RESULT					0xFF010118
+#define OID_SKGE_BUS_TYPE				0xFF010119
+#define OID_SKGE_BUS_SPEED				0xFF01011A
+#define OID_SKGE_BUS_WIDTH				0xFF01011B
+/* 0xFF01011C unused */
+#define OID_SKGE_DIAG_ACTION			0xFF01011D
+#define OID_SKGE_DIAG_RESULT			0xFF01011E
+#define OID_SKGE_MTU					0xFF01011F
+#define OID_SKGE_PHYS_CUR_ADDR			0xFF010120
+#define OID_SKGE_PHYS_FAC_ADDR			0xFF010121
+#define OID_SKGE_PMD					0xFF010122
+#define OID_SKGE_CONNECTOR				0xFF010123
+#define OID_SKGE_LINK_CAP				0xFF010124
+#define OID_SKGE_LINK_MODE				0xFF010125
+#define OID_SKGE_LINK_MODE_STATUS		0xFF010126
+#define OID_SKGE_LINK_STATUS			0xFF010127
+#define OID_SKGE_FLOWCTRL_CAP			0xFF010128
+#define OID_SKGE_FLOWCTRL_MODE			0xFF010129
+#define OID_SKGE_FLOWCTRL_STATUS		0xFF01012A
+#define OID_SKGE_PHY_OPERATION_CAP		0xFF01012B
+#define OID_SKGE_PHY_OPERATION_MODE		0xFF01012C
+#define OID_SKGE_PHY_OPERATION_STATUS	0xFF01012D
+#define OID_SKGE_MULTICAST_LIST			0xFF01012E
+#define OID_SKGE_CURRENT_PACKET_FILTER	0xFF01012F
+
+#define OID_SKGE_TRAP					0xFF010130
+#define OID_SKGE_TRAP_NUMBER			0xFF010131
+
+#define OID_SKGE_RLMT_MODE				0xFF010140
+#define OID_SKGE_RLMT_PORT_NUMBER		0xFF010141
+#define OID_SKGE_RLMT_PORT_ACTIVE		0xFF010142
+#define OID_SKGE_RLMT_PORT_PREFERRED	0xFF010143
+
+#define OID_SKGE_RLMT_MONITOR_NUMBER	0xFF010150
+#define OID_SKGE_RLMT_MONITOR_INDEX		0xFF010151
+#define OID_SKGE_RLMT_MONITOR_ADDR		0xFF010152
+#define OID_SKGE_RLMT_MONITOR_ERRS		0xFF010153
+#define OID_SKGE_RLMT_MONITOR_TIMESTAMP	0xFF010154
+#define OID_SKGE_RLMT_MONITOR_ADMIN		0xFF010155
+
+#define OID_SKGE_INTERMEDIATE_SUPPORT		0xFF010160
+#define OID_SKGE_SET_TEAM_MAC_ADDRESS		0xFF010161
+#define OID_SKGE_DEVICE_INFORMATION 		0xFF010162
+
+#define OID_SKGE_SPEED_CAP				0xFF010170
+#define OID_SKGE_SPEED_MODE				0xFF010171
+#define OID_SKGE_SPEED_STATUS			0xFF010172
+
+#define OID_SKGE_BOARDLEVEL				0xFF010180
+
+#define OID_SKGE_SENSOR_NUMBER			0xFF020100
+#define OID_SKGE_SENSOR_INDEX			0xFF020101
+#define OID_SKGE_SENSOR_DESCR			0xFF020102
+#define OID_SKGE_SENSOR_TYPE			0xFF020103
+#define OID_SKGE_SENSOR_VALUE			0xFF020104
+#define OID_SKGE_SENSOR_WAR_THRES_LOW	0xFF020105
+#define OID_SKGE_SENSOR_WAR_THRES_UPP	0xFF020106
+#define OID_SKGE_SENSOR_ERR_THRES_LOW	0xFF020107
+#define OID_SKGE_SENSOR_ERR_THRES_UPP	0xFF020108
+#define OID_SKGE_SENSOR_STATUS			0xFF020109
+#define OID_SKGE_SENSOR_WAR_CTS			0xFF02010A
+#define OID_SKGE_SENSOR_ERR_CTS			0xFF02010B
+#define OID_SKGE_SENSOR_WAR_TIME		0xFF02010C
+#define OID_SKGE_SENSOR_ERR_TIME		0xFF02010D
+
+#define OID_SKGE_CHKSM_NUMBER			0xFF020110
+#define OID_SKGE_CHKSM_RX_OK_CTS		0xFF020111
+#define OID_SKGE_CHKSM_RX_UNABLE_CTS	0xFF020112
+#define OID_SKGE_CHKSM_RX_ERR_CTS		0xFF020113
+#define OID_SKGE_CHKSM_TX_OK_CTS		0xFF020114
+#define OID_SKGE_CHKSM_TX_UNABLE_CTS	0xFF020115
+
+#define OID_SKGE_STAT_TX				0xFF020120
+#define OID_SKGE_STAT_TX_OCTETS			0xFF020121
+#define OID_SKGE_STAT_TX_BROADCAST		0xFF020122
+#define OID_SKGE_STAT_TX_MULTICAST		0xFF020123
+#define OID_SKGE_STAT_TX_UNICAST		0xFF020124
+#define OID_SKGE_STAT_TX_LONGFRAMES		0xFF020125
+#define OID_SKGE_STAT_TX_BURST			0xFF020126
+#define OID_SKGE_STAT_TX_PFLOWC			0xFF020127
+#define OID_SKGE_STAT_TX_FLOWC			0xFF020128
+#define OID_SKGE_STAT_TX_SINGLE_COL		0xFF020129
+#define OID_SKGE_STAT_TX_MULTI_COL		0xFF02012A
+#define OID_SKGE_STAT_TX_EXCESS_COL		0xFF02012B
+#define OID_SKGE_STAT_TX_LATE_COL		0xFF02012C
+#define OID_SKGE_STAT_TX_DEFFERAL		0xFF02012D
+#define OID_SKGE_STAT_TX_EXCESS_DEF		0xFF02012E
+#define OID_SKGE_STAT_TX_UNDERRUN		0xFF02012F
+#define OID_SKGE_STAT_TX_CARRIER		0xFF020130
+/* #define OID_SKGE_STAT_TX_UTIL		0xFF020131 */
+#define OID_SKGE_STAT_TX_64				0xFF020132
+#define OID_SKGE_STAT_TX_127			0xFF020133
+#define OID_SKGE_STAT_TX_255			0xFF020134
+#define OID_SKGE_STAT_TX_511			0xFF020135
+#define OID_SKGE_STAT_TX_1023			0xFF020136
+#define OID_SKGE_STAT_TX_MAX			0xFF020137
+#define OID_SKGE_STAT_TX_SYNC			0xFF020138
+#define OID_SKGE_STAT_TX_SYNC_OCTETS	0xFF020139
+#define OID_SKGE_STAT_RX				0xFF02013A
+#define OID_SKGE_STAT_RX_OCTETS			0xFF02013B
+#define OID_SKGE_STAT_RX_BROADCAST		0xFF02013C
+#define OID_SKGE_STAT_RX_MULTICAST		0xFF02013D
+#define OID_SKGE_STAT_RX_UNICAST		0xFF02013E
+#define OID_SKGE_STAT_RX_PFLOWC			0xFF02013F
+#define OID_SKGE_STAT_RX_FLOWC			0xFF020140
+#define OID_SKGE_STAT_RX_PFLOWC_ERR		0xFF020141
+#define OID_SKGE_STAT_RX_FLOWC_UNKWN	0xFF020142
+#define OID_SKGE_STAT_RX_BURST			0xFF020143
+#define OID_SKGE_STAT_RX_MISSED			0xFF020144
+#define OID_SKGE_STAT_RX_FRAMING		0xFF020145
+#define OID_SKGE_STAT_RX_OVERFLOW		0xFF020146
+#define OID_SKGE_STAT_RX_JABBER			0xFF020147
+#define OID_SKGE_STAT_RX_CARRIER		0xFF020148
+#define OID_SKGE_STAT_RX_IR_LENGTH		0xFF020149
+#define OID_SKGE_STAT_RX_SYMBOL			0xFF02014A
+#define OID_SKGE_STAT_RX_SHORTS			0xFF02014B
+#define OID_SKGE_STAT_RX_RUNT			0xFF02014C
+#define OID_SKGE_STAT_RX_CEXT			0xFF02014D
+#define OID_SKGE_STAT_RX_TOO_LONG		0xFF02014E
+#define OID_SKGE_STAT_RX_FCS			0xFF02014F
+/* #define OID_SKGE_STAT_RX_UTIL		0xFF020150 */
+#define OID_SKGE_STAT_RX_64				0xFF020151
+#define OID_SKGE_STAT_RX_127			0xFF020152
+#define OID_SKGE_STAT_RX_255			0xFF020153
+#define OID_SKGE_STAT_RX_511			0xFF020154
+#define OID_SKGE_STAT_RX_1023			0xFF020155
+#define OID_SKGE_STAT_RX_MAX			0xFF020156
+#define OID_SKGE_STAT_RX_LONGFRAMES		0xFF020157
+
+#define OID_SKGE_RLMT_CHANGE_CTS		0xFF020160
+#define OID_SKGE_RLMT_CHANGE_TIME		0xFF020161
+#define OID_SKGE_RLMT_CHANGE_ESTIM		0xFF020162
+#define OID_SKGE_RLMT_CHANGE_THRES		0xFF020163
+
+#define OID_SKGE_RLMT_PORT_INDEX		0xFF020164
+#define OID_SKGE_RLMT_STATUS			0xFF020165
+#define OID_SKGE_RLMT_TX_HELLO_CTS		0xFF020166
+#define OID_SKGE_RLMT_RX_HELLO_CTS		0xFF020167
+#define OID_SKGE_RLMT_TX_SP_REQ_CTS		0xFF020168
+#define OID_SKGE_RLMT_RX_SP_CTS			0xFF020169
+
+#define OID_SKGE_TX_SW_QUEUE_LEN		0xFF020170
+#define OID_SKGE_TX_SW_QUEUE_MAX		0xFF020171
+#define OID_SKGE_TX_RETRY				0xFF020172
+#define OID_SKGE_RX_INTR_CTS			0xFF020173
+#define OID_SKGE_TX_INTR_CTS			0xFF020174
+#define OID_SKGE_RX_NO_BUF_CTS			0xFF020175
+#define OID_SKGE_TX_NO_BUF_CTS			0xFF020176
+#define OID_SKGE_TX_USED_DESCR_NO		0xFF020177
+#define OID_SKGE_RX_DELIVERED_CTS		0xFF020178
+#define OID_SKGE_RX_OCTETS_DELIV_CTS	0xFF020179
+#define OID_SKGE_RX_HW_ERROR_CTS		0xFF02017A
+#define OID_SKGE_TX_HW_ERROR_CTS		0xFF02017B
+#define OID_SKGE_IN_ERRORS_CTS			0xFF02017C
+#define OID_SKGE_OUT_ERROR_CTS			0xFF02017D
+#define OID_SKGE_ERR_RECOVERY_CTS		0xFF02017E
+#define OID_SKGE_SYSUPTIME				0xFF02017F
+
+#define OID_SKGE_ALL_DATA				0xFF020190
+
+/* Defines for VCT. */
+#define OID_SKGE_VCT_GET				0xFF020200
+#define OID_SKGE_VCT_SET				0xFF020201
+#define OID_SKGE_VCT_STATUS				0xFF020202
+#define OID_SKGE_VCT_CAPABILITIES		0xFF020203
+
+#ifdef SK_DIAG_SUPPORT
+/* Defines for driver DIAG mode. */
+#define OID_SKGE_DIAG_MODE				0xFF020204
+#endif /* SK_DIAG_SUPPORT */
+
+/* New OIDs */
+#define OID_SKGE_DRIVER_RELDATE			0xFF020210
+#define OID_SKGE_DRIVER_FILENAME		0xFF020211
+#define OID_SKGE_CHIPID					0xFF020212
+#define OID_SKGE_RAMSIZE				0xFF020213
+#define OID_SKGE_VAUXAVAIL				0xFF020214
+#define OID_SKGE_PHY_TYPE				0xFF020215
+#define OID_SKGE_PHY_LP_MODE			0xFF020216
+
+/*
+ * Added for new DualNet IM driver V2
+ */
+#define OID_SKGE_MAC_COUNT				0xFF020217
+#define OID_SKGE_DUALNET_MODE			0xFF020218
+#define OID_SKGE_SET_TAGHEADER			0xFF020219
+
+#ifdef SK_ASF
+/* Defines for ASF */
+#define OID_SKGE_ASF					0xFF02021a
+#define OID_SKGE_ASF_STORE_CONFIG		0xFF02021b
+#define OID_SKGE_ASF_ENA				0xFF02021c
+#define OID_SKGE_ASF_RETRANS			0xFF02021d
+#define OID_SKGE_ASF_RETRANS_INT		0xFF02021e
+#define OID_SKGE_ASF_HB_ENA				0xFF02021f
+#define OID_SKGE_ASF_HB_INT				0xFF020220
+#define OID_SKGE_ASF_WD_ENA				0xFF020221
+#define OID_SKGE_ASF_WD_TIME			0xFF020222
+#define OID_SKGE_ASF_IP_SOURCE			0xFF020223
+#define OID_SKGE_ASF_MAC_SOURCE			0xFF020224
+#define OID_SKGE_ASF_IP_DEST			0xFF020225
+#define OID_SKGE_ASF_MAC_DEST			0xFF020226
+#define OID_SKGE_ASF_COMMUNITY_NAME		0xFF020227
+#define OID_SKGE_ASF_RSP_ENA			0xFF020228
+#define OID_SKGE_ASF_RETRANS_COUNT_MIN	0xFF020229
+#define OID_SKGE_ASF_RETRANS_COUNT_MAX	0xFF02022a
+#define OID_SKGE_ASF_RETRANS_INT_MIN	0xFF02022b
+#define OID_SKGE_ASF_RETRANS_INT_MAX	0xFF02022c
+#define OID_SKGE_ASF_HB_INT_MIN			0xFF02022d
+#define OID_SKGE_ASF_HB_INT_MAX			0xFF02022e
+#define OID_SKGE_ASF_WD_TIME_MIN		0xFF02022f
+#define OID_SKGE_ASF_WD_TIME_MAX		0xFF020230
+#define OID_SKGE_ASF_HB_CAP				0xFF020231
+#define OID_SKGE_ASF_WD_TIMER_RES		0xFF020232
+#define OID_SKGE_ASF_GUID				0xFF020233
+#define OID_SKGE_ASF_KEY_OP				0xFF020234
+#define OID_SKGE_ASF_KEY_ADM			0xFF020235
+#define OID_SKGE_ASF_KEY_GEN			0xFF020236
+#define OID_SKGE_ASF_CAP				0xFF020237
+#define OID_SKGE_ASF_PAR_1				0xFF020238
+#define OID_SKGE_ASF_OVERALL_OID		0xFF020239
+#define OID_SKGE_ASF_FW_REMOVE			0xFF02023a
+#define OID_SKGE_ASF_CHECK_SPI			0xFF02023b
+#endif /* SK_ASF */
+
+
+/* Defined for Yukon-2 path only */
+#define OID_SKGE_UPPER_MINIPORT			0xFF02023D
+
+
+#ifdef SK_ASF
+/* Defines for ASF */
+#define OID_SKGE_ASF_FWVER_OID			0xFF020240
+#define OID_SKGE_ASF_ACPI_OID			0xFF020241
+#define OID_SKGE_ASF_SMBUS_OID			0xFF020242
+#endif /* SK_ASF */
+
+/* VCT struct to store a backup copy of VCT data after a port reset. */
+typedef struct s_PnmiVct {
+	SK_U8			VctStatus;
+	SK_U8			CableLen;
+	SK_U32			MdiPairLen[4];
+	SK_U8			MdiPairSts[4];
+} SK_PNMI_VCT;
+
+
+/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
+#define SK_PNMI_VCT_NONE			0x00
+#define SK_PNMI_VCT_OLD_VCT_DATA	0x01
+#define SK_PNMI_VCT_NEW_VCT_DATA	0x02
+#define SK_PNMI_VCT_OLD_DSP_DATA	0x04
+#define SK_PNMI_VCT_NEW_DSP_DATA	0x08
+#define SK_PNMI_VCT_RUNNING			0x10
+
+
+/* VCT cable test status. */
+#define SK_PNMI_VCT_NORMAL_CABLE		0
+#define SK_PNMI_VCT_SHORT_CABLE			1
+#define SK_PNMI_VCT_OPEN_CABLE			2
+#define SK_PNMI_VCT_TEST_FAIL			3
+#define SK_PNMI_VCT_IMPEDANCE_MISMATCH	4
+#define SK_PNMI_VCT_NOT_PRESENT			5
+
+/* DSP cable ranges. */
+#define DSP_CABLE_RANGE_UNDER_50		0	/* under 50m */
+#define DSP_CABLE_RANGE_50_TO_80		1	/* 50m - 80m */
+#define DSP_CABLE_RANGE_80_TO_150		2	/* 80m - 150m*/
+#define DSP_CABLE_RANGE_110_TO_140		3	/* 110m - 140m */
+#define DSP_CABLE_RANGE_ABOVE_140		4	/* above 140m */
+#define DSP_CABLE_RANGE_NOT_SUPPORTED	((SK_U8)-1)	/* not supported */
+
+#define DSP_CABLE_RANGE_UNDER_50_END	50	/* under 50m */
+#define DSP_CABLE_RANGE_50_TO_80_END	80	/* 50m - 80m */
+#define DSP_CABLE_RANGE_80_TO_140_END	140	/* 80m - 140m */
+
+/* VCT capabilities (needed for OID_SKGE_VCT_CAPABILITIES. */
+#define SK_PNMI_VCT_SUPPORTED_VERSION	1
+#define SK_PNMI_VCT_NOT_SUPPORTED		0
+
+#define OID_SKGE_TRAP_SEN_WAR_LOW		500
+#define OID_SKGE_TRAP_SEN_WAR_UPP		501
+#define OID_SKGE_TRAP_SEN_ERR_LOW		502
+#define OID_SKGE_TRAP_SEN_ERR_UPP		503
+#define OID_SKGE_TRAP_RLMT_CHANGE_THRES	520
+#define OID_SKGE_TRAP_RLMT_CHANGE_PORT	521
+#define OID_SKGE_TRAP_RLMT_PORT_DOWN	522
+#define OID_SKGE_TRAP_RLMT_PORT_UP		523
+#define OID_SKGE_TRAP_RLMT_SEGMENTATION	524
+
+#ifdef SK_DIAG_SUPPORT
+/* Defines for driver DIAG mode. */
+#define SK_DIAG_ATTACHED	2
+#define SK_DIAG_RUNNING		1
+#define SK_DIAG_IDLE		0
+#endif /* SK_DIAG_SUPPORT */
+
+/*
+ * Generic PNMI IOCTL subcommand definitions.
+ */
+#define SK_GET_SINGLE_VAR		1
+#define SK_SET_SINGLE_VAR		2
+#define SK_PRESET_SINGLE_VAR	3
+#define SK_GET_FULL_MIB			4
+#define SK_SET_FULL_MIB			5
+#define SK_PRESET_FULL_MIB		6
+
+/*
+ * Define error numbers and messages for syslog
+ */
+#define SK_PNMI_ERR001		(SK_ERRBASE_PNMI + 1)
+#define SK_PNMI_ERR001MSG	"SkPnmiGetStruct: Unknown OID"
+#define SK_PNMI_ERR002		(SK_ERRBASE_PNMI + 2)
+#define SK_PNMI_ERR002MSG	"SkPnmiGetStruct: Cannot read VPD keys"
+#define SK_PNMI_ERR003		(SK_ERRBASE_PNMI + 3)
+#define SK_PNMI_ERR003MSG	"OidStruct: Called with wrong OID"
+#define SK_PNMI_ERR004		(SK_ERRBASE_PNMI + 4)
+#define SK_PNMI_ERR004MSG	"OidStruct: Called with wrong action"
+#define SK_PNMI_ERR005		(SK_ERRBASE_PNMI + 5)
+#define SK_PNMI_ERR005MSG	"Perform: Cannot reset driver"
+#define SK_PNMI_ERR006		(SK_ERRBASE_PNMI + 6)
+#define SK_PNMI_ERR006MSG	"Perform: Unknown OID action command"
+#define SK_PNMI_ERR007		(SK_ERRBASE_PNMI + 7)
+#define SK_PNMI_ERR007MSG	"General: Driver description not initialized"
+#define SK_PNMI_ERR008		(SK_ERRBASE_PNMI + 8)
+#define SK_PNMI_ERR008MSG	"Addr: Tried to get unknown OID"
+#define SK_PNMI_ERR009		(SK_ERRBASE_PNMI + 9)
+#define SK_PNMI_ERR009MSG	"Addr: Unknown OID"
+#define SK_PNMI_ERR010		(SK_ERRBASE_PNMI + 10)
+#define SK_PNMI_ERR010MSG	"CsumStat: Unknown OID"
+#define SK_PNMI_ERR011		(SK_ERRBASE_PNMI + 11)
+#define SK_PNMI_ERR011MSG	"SensorStat: Sensor descr string too long"
+#define SK_PNMI_ERR012		(SK_ERRBASE_PNMI + 12)
+#define SK_PNMI_ERR012MSG	"SensorStat: Unknown OID"
+#define SK_PNMI_ERR013		(SK_ERRBASE_PNMI + 13)
+#define SK_PNMI_ERR013MSG	""
+#define SK_PNMI_ERR014		(SK_ERRBASE_PNMI + 14)
+#define SK_PNMI_ERR014MSG	"Vpd: Cannot read VPD keys"
+#define SK_PNMI_ERR015		(SK_ERRBASE_PNMI + 15)
+#define SK_PNMI_ERR015MSG	"Vpd: Internal array for VPD keys too small"
+#define SK_PNMI_ERR016		(SK_ERRBASE_PNMI + 16)
+#define SK_PNMI_ERR016MSG	"Vpd: Key string too long"
+#define SK_PNMI_ERR017		(SK_ERRBASE_PNMI + 17)
+#define SK_PNMI_ERR017MSG	"Vpd: Invalid VPD status pointer"
+#define SK_PNMI_ERR018		(SK_ERRBASE_PNMI + 18)
+#define SK_PNMI_ERR018MSG	"Vpd: VPD data not valid"
+#define SK_PNMI_ERR019		(SK_ERRBASE_PNMI + 19)
+#define SK_PNMI_ERR019MSG	"Vpd: VPD entries list string too long"
+#define SK_PNMI_ERR021		(SK_ERRBASE_PNMI + 21)
+#define SK_PNMI_ERR021MSG	"Vpd: VPD data string too long"
+#define SK_PNMI_ERR022		(SK_ERRBASE_PNMI + 22)
+#define SK_PNMI_ERR022MSG	"Vpd: VPD data string too long should be errored before"
+#define SK_PNMI_ERR023		(SK_ERRBASE_PNMI + 23)
+#define SK_PNMI_ERR023MSG	"Vpd: Unknown OID in get action"
+#define SK_PNMI_ERR024		(SK_ERRBASE_PNMI + 24)
+#define SK_PNMI_ERR024MSG	"Vpd: Unknown OID in preset/set action"
+#define SK_PNMI_ERR025		(SK_ERRBASE_PNMI + 25)
+#define SK_PNMI_ERR025MSG	"Vpd: Cannot write VPD after modify entry"
+#define SK_PNMI_ERR026		(SK_ERRBASE_PNMI + 26)
+#define SK_PNMI_ERR026MSG	"Vpd: Cannot update VPD"
+#define SK_PNMI_ERR027		(SK_ERRBASE_PNMI + 27)
+#define SK_PNMI_ERR027MSG	"Vpd: Cannot delete VPD entry"
+#define SK_PNMI_ERR028		(SK_ERRBASE_PNMI + 28)
+#define SK_PNMI_ERR028MSG	"Vpd: Cannot update VPD after delete entry"
+#define SK_PNMI_ERR029		(SK_ERRBASE_PNMI + 29)
+#define SK_PNMI_ERR029MSG	"General: Driver description string too long"
+#define SK_PNMI_ERR030		(SK_ERRBASE_PNMI + 30)
+#define SK_PNMI_ERR030MSG	"General: Driver version not initialized"
+#define SK_PNMI_ERR031		(SK_ERRBASE_PNMI + 31)
+#define SK_PNMI_ERR031MSG	"General: Driver version string too long"
+#define SK_PNMI_ERR032		(SK_ERRBASE_PNMI + 32)
+#define SK_PNMI_ERR032MSG	"General: Cannot read VPD Name for HW descr"
+#define SK_PNMI_ERR033		(SK_ERRBASE_PNMI + 33)
+#define SK_PNMI_ERR033MSG	"General: HW description string too long"
+#define SK_PNMI_ERR034		(SK_ERRBASE_PNMI + 34)
+#define SK_PNMI_ERR034MSG	"General: Unknown OID"
+#define SK_PNMI_ERR035		(SK_ERRBASE_PNMI + 35)
+#define SK_PNMI_ERR035MSG	"Rlmt: Unknown OID"
+#define SK_PNMI_ERR036		(SK_ERRBASE_PNMI + 36)
+#define SK_PNMI_ERR036MSG	""
+#define SK_PNMI_ERR037		(SK_ERRBASE_PNMI + 37)
+#define SK_PNMI_ERR037MSG	"Rlmt: SK_RLMT_MODE_CHANGE event returned not 0"
+#define SK_PNMI_ERR038		(SK_ERRBASE_PNMI + 38)
+#define SK_PNMI_ERR038MSG	"Rlmt: SK_RLMT_PREFPORT_CHANGE event returned not 0"
+#define SK_PNMI_ERR039		(SK_ERRBASE_PNMI + 39)
+#define SK_PNMI_ERR039MSG	"RlmtStat: Unknown OID"
+#define SK_PNMI_ERR040		(SK_ERRBASE_PNMI + 40)
+#define SK_PNMI_ERR040MSG	"PowerManagement: Unknown OID"
+#define SK_PNMI_ERR041		(SK_ERRBASE_PNMI + 41)
+#define SK_PNMI_ERR041MSG	"MacPrivateConf: Unknown OID"
+#define SK_PNMI_ERR042		(SK_ERRBASE_PNMI + 42)
+#define SK_PNMI_ERR042MSG	"MacPrivateConf: SK_HWEV_SET_ROLE returned not 0"
+#define SK_PNMI_ERR043		(SK_ERRBASE_PNMI + 43)
+#define SK_PNMI_ERR043MSG	"MacPrivateConf: SK_HWEV_SET_LMODE returned not 0"
+#define SK_PNMI_ERR044		(SK_ERRBASE_PNMI + 44)
+#define SK_PNMI_ERR044MSG	"MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0"
+#define SK_PNMI_ERR045		(SK_ERRBASE_PNMI + 45)
+#define SK_PNMI_ERR045MSG	"MacPrivateConf: SK_HWEV_SET_SPEED returned not 0"
+#define SK_PNMI_ERR046		(SK_ERRBASE_PNMI + 46)
+#define SK_PNMI_ERR046MSG	"Monitor: Unknown OID"
+#define SK_PNMI_ERR047		(SK_ERRBASE_PNMI + 47)
+#define SK_PNMI_ERR047MSG	"SirqUpdate: Event function returned not 0"
+#define SK_PNMI_ERR048		(SK_ERRBASE_PNMI + 48)
+#define SK_PNMI_ERR048MSG	"RlmtUpdate: Event function returned not 0"
+#define SK_PNMI_ERR049		(SK_ERRBASE_PNMI + 49)
+#define SK_PNMI_ERR049MSG	"SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
+#define SK_PNMI_ERR050		(SK_ERRBASE_PNMI + 50)
+#define SK_PNMI_ERR050MSG	"SkPnmiInit: Invalid size of 'StatAddr' table!!"
+#define SK_PNMI_ERR051		(SK_ERRBASE_PNMI + 51)
+#define SK_PNMI_ERR051MSG	"SkPnmiEvent: Port switch suspicious"
+#define SK_PNMI_ERR052		(SK_ERRBASE_PNMI + 52)
+#define SK_PNMI_ERR052MSG	""
+#define SK_PNMI_ERR053		(SK_ERRBASE_PNMI + 53)
+#define SK_PNMI_ERR053MSG	"General: Driver release date not initialized"
+#define SK_PNMI_ERR054		(SK_ERRBASE_PNMI + 54)
+#define SK_PNMI_ERR054MSG	"General: Driver release date string too long"
+#define SK_PNMI_ERR055		(SK_ERRBASE_PNMI + 55)
+#define SK_PNMI_ERR055MSG	"General: Driver file name not initialized"
+#define SK_PNMI_ERR056		(SK_ERRBASE_PNMI + 56)
+#define SK_PNMI_ERR056MSG	"General: Driver file name string too long"
+
+/*
+ * Management counter macros called by the driver
+ */
+#define SK_PNMI_SET_DRIVER_DESCR(pAC,v)	((pAC)->Pnmi.pDriverDescription = \
+	(char *)(v))
+
+#define SK_PNMI_SET_DRIVER_VER(pAC,v)	((pAC)->Pnmi.pDriverVersion = \
+	(char *)(v))
+
+#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v)	((pAC)->Pnmi.pDriverReleaseDate = \
+	(char *)(v))
+
+#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v)	((pAC)->Pnmi.pDriverFileName = \
+	(char *)(v))
+
+#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \
+	{ \
+		(pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \
+		if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \
+			(pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \
+		} \
+	}
+#define SK_PNMI_CNT_TX_RETRY(pAC,p)	(((pAC)->Pnmi.Port[p].TxRetryCts)++)
+#define SK_PNMI_CNT_RX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].RxIntrCts)++)
+#define SK_PNMI_CNT_TX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].TxIntrCts)++)
+#define SK_PNMI_CNT_NO_RX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].RxNoBufCts)++)
+#define SK_PNMI_CNT_NO_TX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].TxNoBufCts)++)
+#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \
+	((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v));
+#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \
+	{ \
+		((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \
+		(pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \
+	}
+#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p)	(((pAC)->Pnmi.Port[p].ErrRecoveryCts)++);
+
+#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \
+	{ \
+		if ((p) < SK_MAX_MACS) { \
+			((pAC)->Pnmi.Port[p].StatSyncCts)++; \
+			(pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \
+		} \
+	}
+
+#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \
+	{ \
+		if ((p) < SK_MAX_MACS) { \
+			((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \
+		} \
+	}
+
+#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \
+	{ \
+		if ((p) < SK_MAX_MACS) { \
+			((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \
+		} \
+	}
+
+#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \
+	{ \
+		if ((p) < SK_MAX_MACS) { \
+			((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \
+		} \
+	}
+
+/*
+ * Conversion Macros
+ */
+#define SK_PNMI_PORT_INST2LOG(i)	((unsigned int)(i) - 1)
+#define SK_PNMI_PORT_LOG2INST(l)	((unsigned int)(l) + 1)
+#define SK_PNMI_PORT_PHYS2LOG(p)	((unsigned int)(p) + 1)
+#define SK_PNMI_PORT_LOG2PHYS(pAC,l)	((unsigned int)(l) - 1)
+#define SK_PNMI_PORT_PHYS2INST(pAC,p)	\
+	(pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2))
+#define SK_PNMI_PORT_INST2PHYS(pAC,i)	((unsigned int)(i) - 2)
+
+/*
+ * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct
+ */
+#define SK_PNMI_VPD_KEY_SIZE	5
+#define SK_PNMI_VPD_BUFSIZE		(VPD_SIZE)
+#define SK_PNMI_VPD_ENTRIES		(VPD_SIZE / 4)
+#define SK_PNMI_VPD_DATALEN		128 /*  Number of data bytes */
+
+#define SK_PNMI_MULTICAST_LISTLEN	64
+#define SK_PNMI_SENSOR_ENTRIES		(SK_MAX_SENSORS)
+#define SK_PNMI_CHECKSUM_ENTRIES	3
+#define SK_PNMI_MAC_ENTRIES			(SK_MAX_MACS + 1)
+#define SK_PNMI_MONITOR_ENTRIES		20
+#define SK_PNMI_TRAP_ENTRIES		10
+#define SK_PNMI_TRAPLEN				128
+#define SK_PNMI_STRINGLEN1			80
+#define SK_PNMI_STRINGLEN2			25
+#define SK_PNMI_TRAP_QUEUE_LEN		512
+
+typedef struct s_PnmiVpd {
+	char			VpdKey[SK_PNMI_VPD_KEY_SIZE];
+	char			VpdValue[SK_PNMI_VPD_DATALEN];
+	SK_U8			VpdAccess;
+	SK_U8			VpdAction;
+} SK_PNMI_VPD;
+
+typedef struct s_PnmiSensor {
+	SK_U8			SensorIndex;
+	char			SensorDescr[SK_PNMI_STRINGLEN2];
+	SK_U8			SensorType;
+	SK_U32			SensorValue;
+	SK_U32			SensorWarningThresholdLow;
+	SK_U32			SensorWarningThresholdHigh;
+	SK_U32			SensorErrorThresholdLow;
+	SK_U32			SensorErrorThresholdHigh;
+	SK_U8			SensorStatus;
+	SK_U64			SensorWarningCts;
+	SK_U64			SensorErrorCts;
+	SK_U64			SensorWarningTimestamp;
+	SK_U64			SensorErrorTimestamp;
+} SK_PNMI_SENSOR;
+
+typedef struct s_PnmiChecksum {
+	SK_U64			ChecksumRxOkCts;
+	SK_U64			ChecksumRxUnableCts;
+	SK_U64			ChecksumRxErrCts;
+	SK_U64			ChecksumTxOkCts;
+	SK_U64			ChecksumTxUnableCts;
+} SK_PNMI_CHECKSUM;
+
+typedef struct s_PnmiStat {
+	SK_U64			StatTxOkCts;
+	SK_U64			StatTxOctetsOkCts;
+	SK_U64			StatTxBroadcastOkCts;
+	SK_U64			StatTxMulticastOkCts;
+	SK_U64			StatTxUnicastOkCts;
+	SK_U64			StatTxLongFramesCts;
+	SK_U64			StatTxBurstCts;
+	SK_U64			StatTxPauseMacCtrlCts;
+	SK_U64			StatTxMacCtrlCts;
+	SK_U64			StatTxSingleCollisionCts;
+	SK_U64			StatTxMultipleCollisionCts;
+	SK_U64			StatTxExcessiveCollisionCts;
+	SK_U64			StatTxLateCollisionCts;
+	SK_U64			StatTxDeferralCts;
+	SK_U64			StatTxExcessiveDeferralCts;
+	SK_U64			StatTxFifoUnderrunCts;
+	SK_U64			StatTxCarrierCts;
+	SK_U64			Dummy1; /* StatTxUtilization */
+	SK_U64			StatTx64Cts;
+	SK_U64			StatTx127Cts;
+	SK_U64			StatTx255Cts;
+	SK_U64			StatTx511Cts;
+	SK_U64			StatTx1023Cts;
+	SK_U64			StatTxMaxCts;
+	SK_U64			StatTxSyncCts;
+	SK_U64			StatTxSyncOctetsCts;
+	SK_U64			StatRxOkCts;
+	SK_U64			StatRxOctetsOkCts;
+	SK_U64			StatRxBroadcastOkCts;
+	SK_U64			StatRxMulticastOkCts;
+	SK_U64			StatRxUnicastOkCts;
+	SK_U64			StatRxLongFramesCts;
+	SK_U64			StatRxPauseMacCtrlCts;
+	SK_U64			StatRxMacCtrlCts;
+	SK_U64			StatRxPauseMacCtrlErrorCts;
+	SK_U64			StatRxMacCtrlUnknownCts;
+	SK_U64			StatRxBurstCts;
+	SK_U64			StatRxMissedCts;
+	SK_U64			StatRxFramingCts;
+	SK_U64			StatRxFifoOverflowCts;
+	SK_U64			StatRxJabberCts;
+	SK_U64			StatRxCarrierCts;
+	SK_U64			StatRxIRLengthCts;
+	SK_U64			StatRxSymbolCts;
+	SK_U64			StatRxShortsCts;
+	SK_U64			StatRxRuntCts;
+	SK_U64			StatRxCextCts;
+	SK_U64			StatRxTooLongCts;
+	SK_U64			StatRxFcsCts;
+	SK_U64			Dummy2; /* StatRxUtilization */
+	SK_U64			StatRx64Cts;
+	SK_U64			StatRx127Cts;
+	SK_U64			StatRx255Cts;
+	SK_U64			StatRx511Cts;
+	SK_U64			StatRx1023Cts;
+	SK_U64			StatRxMaxCts;
+} SK_PNMI_STAT;
+
+typedef struct s_PnmiConf {
+	char			ConfMacCurrentAddr[6];
+	char			ConfMacFactoryAddr[6];
+	SK_U8			ConfPMD;
+	SK_U8			ConfConnector;
+	SK_U32			ConfPhyType;
+	SK_U32			ConfPhyMode;
+	SK_U8			ConfLinkCapability;
+	SK_U8			ConfLinkMode;
+	SK_U8			ConfLinkModeStatus;
+	SK_U8			ConfLinkStatus;
+	SK_U8			ConfFlowCtrlCapability;
+	SK_U8			ConfFlowCtrlMode;
+	SK_U8			ConfFlowCtrlStatus;
+	SK_U8			ConfPhyOperationCapability;
+	SK_U8			ConfPhyOperationMode;
+	SK_U8			ConfPhyOperationStatus;
+	SK_U8			ConfSpeedCapability;
+	SK_U8			ConfSpeedMode;
+	SK_U8			ConfSpeedStatus;
+} SK_PNMI_CONF;
+
+typedef struct s_PnmiRlmt {
+	SK_U32			RlmtIndex;
+	SK_U32			RlmtStatus;
+	SK_U64			RlmtTxHelloCts;
+	SK_U64			RlmtRxHelloCts;
+	SK_U64			RlmtTxSpHelloReqCts;
+	SK_U64			RlmtRxSpHelloCts;
+} SK_PNMI_RLMT;
+
+typedef struct s_PnmiRlmtMonitor {
+	SK_U32			RlmtMonitorIndex;
+	char			RlmtMonitorAddr[6];
+	SK_U64			RlmtMonitorErrorCts;
+	SK_U64			RlmtMonitorTimestamp;
+	SK_U8			RlmtMonitorAdmin;
+} SK_PNMI_RLMT_MONITOR;
+
+typedef struct s_PnmiRequestStatus {
+	SK_U32			ErrorStatus;
+	SK_U32			ErrorOffset;
+} SK_PNMI_REQUEST_STATUS;
+
+typedef struct s_PnmiStrucData {
+	SK_U32			MgmtDBVersion;
+	SK_PNMI_REQUEST_STATUS	ReturnStatus;
+	SK_U32			VpdFreeBytes;
+	char			VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE];
+	SK_U32			VpdEntriesNumber;
+	SK_PNMI_VPD		Vpd[SK_PNMI_VPD_ENTRIES];
+	SK_U32			PortNumber;
+	SK_U32			DeviceType;
+	char			DriverDescr[SK_PNMI_STRINGLEN1];
+	char			DriverVersion[SK_PNMI_STRINGLEN2];
+	char			DriverReleaseDate[SK_PNMI_STRINGLEN1];
+	char			DriverFileName[SK_PNMI_STRINGLEN1];
+	char			HwDescr[SK_PNMI_STRINGLEN1];
+	char			HwVersion[SK_PNMI_STRINGLEN2];
+	SK_U16			Chipset;
+	SK_U32			ChipId;
+	SK_U8			VauxAvail;
+	SK_U32			RamSize;
+	SK_U32			MtuSize;
+	SK_U32			Action;
+	SK_U32			TestResult;
+	SK_U8			BusType;
+	SK_U8			BusSpeed;
+	SK_U8			BusWidth;
+	SK_U8			SensorNumber;
+	SK_PNMI_SENSOR	Sensor[SK_PNMI_SENSOR_ENTRIES];
+	SK_U8			ChecksumNumber;
+	SK_PNMI_CHECKSUM	Checksum[SK_PNMI_CHECKSUM_ENTRIES];
+	SK_PNMI_STAT	Stat[SK_PNMI_MAC_ENTRIES];
+	SK_PNMI_CONF	Conf[SK_PNMI_MAC_ENTRIES];
+	SK_U8			RlmtMode;
+	SK_U32			RlmtPortNumber;
+	SK_U8			RlmtPortActive;
+	SK_U8			RlmtPortPreferred;
+	SK_U64			RlmtChangeCts;
+	SK_U64			RlmtChangeTime;
+	SK_U64			RlmtChangeEstimate;
+	SK_U64			RlmtChangeThreshold;
+	SK_PNMI_RLMT	Rlmt[SK_MAX_MACS];
+	SK_U32			RlmtMonitorNumber;
+	SK_PNMI_RLMT_MONITOR	RlmtMonitor[SK_PNMI_MONITOR_ENTRIES];
+	SK_U32			TrapNumber;
+	SK_U8			Trap[SK_PNMI_TRAP_QUEUE_LEN];
+	SK_U64			TxSwQueueLen;
+	SK_U64			TxSwQueueMax;
+	SK_U64			TxRetryCts;
+	SK_U64			RxIntrCts;
+	SK_U64			TxIntrCts;
+	SK_U64			RxNoBufCts;
+	SK_U64			TxNoBufCts;
+	SK_U64			TxUsedDescrNo;
+	SK_U64			RxDeliveredCts;
+	SK_U64			RxOctetsDeliveredCts;
+	SK_U64			RxHwErrorsCts;
+	SK_U64			TxHwErrorsCts;
+	SK_U64			InErrorsCts;
+	SK_U64			OutErrorsCts;
+	SK_U64			ErrRecoveryCts;
+	SK_U64			SysUpTime;
+} SK_PNMI_STRUCT_DATA;
+
+#define SK_PNMI_STRUCT_SIZE	(sizeof(SK_PNMI_STRUCT_DATA))
+
+/* The ReturnStatus field must be located before VpdFreeBytes! */
+#define SK_PNMI_MIN_STRUCT_SIZE	((unsigned int)(SK_UPTR)\
+				 &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
+
+/*
+ * Various definitions
+ */
+#define SK_PNMI_EVT_TIMER_CHECK		28125000L	/* 28125 ms */
+
+#define SK_PNMI_VCT_TIMER_CHECK		 4000000L	/* 4 sec. */
+
+#define SK_PNMI_MAX_PROTOS		3
+
+/*
+ * SK_PNMI_CNT_NO must have the value of the enum SK_PNMI_MAX_IDX.
+ * Define SK_PNMI_CHECK to check this during init level SK_INIT_IO.
+ */
+#define SK_PNMI_CNT_NO			66
+
+/*
+ * Estimate data structure
+ */
+typedef struct s_PnmiEstimate {
+	unsigned int	EstValueIndex;
+	SK_U64			EstValue[7];
+	SK_U64			Estimate;
+	SK_TIMER		EstTimer;
+} SK_PNMI_ESTIMATE;
+
+
+/*
+ * PNMI specific adapter context structure
+ */
+typedef struct s_PnmiPort {
+	SK_U64			StatSyncCts;
+	SK_U64			StatSyncOctetsCts;
+	SK_U64			StatRxLongFrameCts;
+	SK_U64			StatRxFrameTooLongCts;
+	SK_U64			StatRxPMaccErr;
+	SK_U64			TxSwQueueLen;
+	SK_U64			TxSwQueueMax;
+	SK_U64			TxRetryCts;
+	SK_U64			RxIntrCts;
+	SK_U64			TxIntrCts;
+	SK_U64			RxNoBufCts;
+	SK_U64			TxNoBufCts;
+	SK_U64			TxUsedDescrNo;
+	SK_U64			RxDeliveredCts;
+	SK_U64			RxOctetsDeliveredCts;
+	SK_U64			RxHwErrorsCts;
+	SK_U64			TxHwErrorsCts;
+	SK_U64			InErrorsCts;
+	SK_U64			OutErrorsCts;
+	SK_U64			ErrRecoveryCts;
+	SK_U64			RxShortZeroMark;
+	SK_U64			CounterOffset[SK_PNMI_CNT_NO];
+	SK_U32			CounterHigh[SK_PNMI_CNT_NO];
+	SK_BOOL			ActiveFlag;
+	SK_U8			Align[3];
+} SK_PNMI_PORT;
+
+
+typedef struct s_PnmiData {
+	SK_PNMI_PORT	Port	[SK_MAX_MACS];
+	SK_PNMI_PORT	BufPort	[SK_MAX_MACS]; /* 2002-09-13 pweber  */
+	SK_U64			VirtualCounterOffset[SK_PNMI_CNT_NO];
+	SK_U32			TestResult;
+	char			HwVersion[10];
+	SK_U16			Align01;
+
+	char			*pDriverDescription;
+	char			*pDriverVersion;
+	char			*pDriverReleaseDate;
+	char			*pDriverFileName;
+
+	int				MacUpdatedFlag;
+	int				RlmtUpdatedFlag;
+	int				SirqUpdatedFlag;
+
+	SK_U64			RlmtChangeCts;
+	SK_U64			RlmtChangeTime;
+	SK_PNMI_ESTIMATE	RlmtChangeEstimate;
+	SK_U64			RlmtChangeThreshold;
+
+	SK_U64			StartUpTime;
+	SK_U32			DeviceType;
+	char			PciBusSpeed;
+	char			PciBusWidth;
+	char			Chipset;
+	char			PMD;
+	char			Connector;
+	SK_BOOL			DualNetActiveFlag;
+	SK_U16			Align02;
+
+	char			TrapBuf[SK_PNMI_TRAP_QUEUE_LEN];
+	unsigned int	TrapBufFree;
+	unsigned int	TrapQueueBeg;
+	unsigned int	TrapQueueEnd;
+	unsigned int	TrapBufPad;
+	unsigned int	TrapUnique;
+	SK_U8			VctStatus[SK_MAX_MACS];
+	SK_PNMI_VCT		VctBackup[SK_MAX_MACS];
+	SK_TIMER		VctTimeout[SK_MAX_MACS];
+#ifdef SK_DIAG_SUPPORT
+	SK_U32			DiagAttached;
+#endif /* SK_DIAG_SUPPORT */
+	SK_BOOL         VpdKeyReadError;
+} SK_PNMI;
+
+
+/*
+ * Function prototypes
+ */
+extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
+extern int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
+	unsigned int* pLen, SK_U32 Instance, SK_U32 NetIndex);
+extern int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id,
+	void* pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
+	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+	unsigned int *pLen, SK_U32 NetIndex);
+extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+	unsigned int *pLen, SK_U32 NetIndex);
+extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+	unsigned int *pLen, SK_U32 NetIndex);
+extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event,
+	SK_EVPARA Param);
+extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
+	unsigned int * pLen, SK_U32 NetIndex);
+
+#endif
diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
new file mode 100755
index 0000000..e7f7191
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgesirq.h
@@ -0,0 +1,137 @@
+/******************************************************************************
+ *
+ * Name:	skgesirq.h
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.5 $
+ * Date:	$Date: 2005/12/14 16:11:35 $
+ * Purpose:	Gigabit Ethernet special IRQ functions
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef _INC_SKGESIRQ_H_
+#define _INC_SKGESIRQ_H_
+
+/* Define return codes of SkGePortCheckUp and CheckShort */
+#define SK_HW_PS_NONE		0	/* No action needed */
+#define SK_HW_PS_RESTART	1	/* Restart needed */
+#define SK_HW_PS_LINK		2	/* Link Up actions needed */
+
+/*
+ * Define the Event the special IRQ/INI module can handle
+ */
+#define SK_HWEV_WATIM			1	/* Timeout for WA Errata #2 XMAC */
+#define SK_HWEV_PORT_START		2	/* Port Start Event by RLMT */
+#define SK_HWEV_PORT_STOP		3	/* Port Stop Event by RLMT */
+#define SK_HWEV_CLEAR_STAT		4	/* Clear Statistics by PNMI */
+#define SK_HWEV_UPDATE_STAT		5	/* Update Statistics by PNMI */
+#define SK_HWEV_SET_LMODE		6	/* Set Link Mode by PNMI */
+#define SK_HWEV_SET_FLOWMODE	7	/* Set Flow Control Mode by PNMI */
+#define SK_HWEV_SET_ROLE		8	/* Set Master/Slave (Role) by PNMI */
+#define SK_HWEV_SET_SPEED		9	/* Set Link Speed by PNMI */
+#define SK_HWEV_HALFDUP_CHK		10	/* Half Duplex Hangup Workaround */
+
+#define SK_WA_ACT_TIME		1000000UL	/* 1000 msec (1 sec) */
+#define SK_WA_INA_TIME		 100000UL	/*  100 msec */
+
+#define SK_HALFDUP_CHK_TIME	  10000UL	/*   10 msec */
+
+/*
+ * Define the error numbers and messages
+ */
+#define SKERR_SIRQ_E001		(SK_ERRBASE_SIRQ+0)
+#define SKERR_SIRQ_E001MSG	"Unknown event"
+#define SKERR_SIRQ_E002		(SKERR_SIRQ_E001+1)
+#define SKERR_SIRQ_E002MSG	"Packet timeout RX1"
+#define SKERR_SIRQ_E003		(SKERR_SIRQ_E002+1)
+#define SKERR_SIRQ_E003MSG	"Packet timeout RX2"
+#define SKERR_SIRQ_E004		(SKERR_SIRQ_E003+1)
+#define SKERR_SIRQ_E004MSG	"MAC 1 not correctly initialized"
+#define SKERR_SIRQ_E005		(SKERR_SIRQ_E004+1)
+#define SKERR_SIRQ_E005MSG	"MAC 2 not correctly initialized"
+#define SKERR_SIRQ_E006		(SKERR_SIRQ_E005+1)
+#define SKERR_SIRQ_E006MSG	"CHECK failure R1"
+#define SKERR_SIRQ_E007		(SKERR_SIRQ_E006+1)
+#define SKERR_SIRQ_E007MSG	"CHECK failure R2"
+#define SKERR_SIRQ_E008		(SKERR_SIRQ_E007+1)
+#define SKERR_SIRQ_E008MSG	"CHECK failure XS1"
+#define SKERR_SIRQ_E009		(SKERR_SIRQ_E008+1)
+#define SKERR_SIRQ_E009MSG	"CHECK failure XA1"
+#define SKERR_SIRQ_E010		(SKERR_SIRQ_E009+1)
+#define SKERR_SIRQ_E010MSG	"CHECK failure XS2"
+#define SKERR_SIRQ_E011		(SKERR_SIRQ_E010+1)
+#define SKERR_SIRQ_E011MSG	"CHECK failure XA2"
+#define SKERR_SIRQ_E012		(SKERR_SIRQ_E011+1)
+#define SKERR_SIRQ_E012MSG	"Unexpected IRQ Master error"
+#define SKERR_SIRQ_E013		(SKERR_SIRQ_E012+1)
+#define SKERR_SIRQ_E013MSG	"Unexpected IRQ Status error"
+#define SKERR_SIRQ_E014		(SKERR_SIRQ_E013+1)
+#define SKERR_SIRQ_E014MSG	"Parity error on RAM (read)"
+#define SKERR_SIRQ_E015		(SKERR_SIRQ_E014+1)
+#define SKERR_SIRQ_E015MSG	"Parity error on RAM (write)"
+#define SKERR_SIRQ_E016		(SKERR_SIRQ_E015+1)
+#define SKERR_SIRQ_E016MSG	"Parity error MAC 1"
+#define SKERR_SIRQ_E017		(SKERR_SIRQ_E016+1)
+#define SKERR_SIRQ_E017MSG	"Parity error MAC 2"
+#define SKERR_SIRQ_E018		(SKERR_SIRQ_E017+1)
+#define SKERR_SIRQ_E018MSG	"Parity error RX 1"
+#define SKERR_SIRQ_E019		(SKERR_SIRQ_E018+1)
+#define SKERR_SIRQ_E019MSG	"Parity error RX 2"
+#define SKERR_SIRQ_E020		(SKERR_SIRQ_E019+1)
+#define SKERR_SIRQ_E020MSG	"MAC transmit FIFO underrun"
+#define SKERR_SIRQ_E021		(SKERR_SIRQ_E020+1)
+#define SKERR_SIRQ_E021MSG	"Spurious TWSI interrupt"
+#define SKERR_SIRQ_E022		(SKERR_SIRQ_E021+1)
+#define SKERR_SIRQ_E022MSG	"Cable pair swap error"
+#define SKERR_SIRQ_E023		(SKERR_SIRQ_E022+1)
+#define SKERR_SIRQ_E023MSG	"Auto-negotiation error"
+#define SKERR_SIRQ_E024		(SKERR_SIRQ_E023+1)
+#define SKERR_SIRQ_E024MSG	"FIFO overflow error"
+#define SKERR_SIRQ_E025		(SKERR_SIRQ_E024+1)
+#define SKERR_SIRQ_E025MSG	"2 Pair Downshift detected"
+#define SKERR_SIRQ_E026		(SKERR_SIRQ_E025+1)
+#define SKERR_SIRQ_E026MSG	"Uncorrectable PCI Express error"
+#define SKERR_SIRQ_E027		(SKERR_SIRQ_E026+1)
+#define SKERR_SIRQ_E027MSG	"PCI Bus Abort detected"
+#define SKERR_SIRQ_E028		(SKERR_SIRQ_E027+1)
+#define SKERR_SIRQ_E028MSG	"Parity error on RAM 1 (read)"
+#define SKERR_SIRQ_E029		(SKERR_SIRQ_E028+1)
+#define SKERR_SIRQ_E029MSG	"Parity error on RAM 1 (write)"
+#define SKERR_SIRQ_E030		(SKERR_SIRQ_E029+1)
+#define SKERR_SIRQ_E030MSG	"Parity error on RAM 2 (read)"
+#define SKERR_SIRQ_E031		(SKERR_SIRQ_E030+1)
+#define SKERR_SIRQ_E031MSG	"Parity error on RAM 2 (write)"
+#define SKERR_SIRQ_E032		(SKERR_SIRQ_E031+1)
+#define SKERR_SIRQ_E032MSG	"TCP segmentation error async. queue 1"
+#define SKERR_SIRQ_E033		(SKERR_SIRQ_E032+1)
+#define SKERR_SIRQ_E033MSG	"TCP segmentation error sync. queue 1"
+#define SKERR_SIRQ_E034		(SKERR_SIRQ_E033+1)
+#define SKERR_SIRQ_E034MSG	"TCP segmentation error async. queue 2"
+#define SKERR_SIRQ_E035		(SKERR_SIRQ_E034+1)
+#define SKERR_SIRQ_E035MSG	"TCP segmentation error sync. queue 2"
+#define SKERR_SIRQ_E036		(SKERR_SIRQ_E035+1)
+#define SKERR_SIRQ_E036MSG	"CHECK failure polling unit"
+
+extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
+extern int  SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
+extern void SkHWLinkUp(SK_AC *pAC, SK_IOC IoC, int Port);
+extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
+extern void SkGeYuSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
+extern void SkYuk2SirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
+
+#endif	/* _INC_SKGESIRQ_H_ */
+
diff --git a/drivers/net/sk98lin/h/skgespi.h b/drivers/net/sk98lin/h/skgespi.h
new file mode 100755
index 0000000..adf5194
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgespi.h
@@ -0,0 +1,254 @@
+/******************************************************************************
+ *
+ * Name:	skspi.h
+ * Project:	Flash Programmer, Manufacturing and Diagnostic Tools
+ * Version:	$Revision: 1.1.2.3 $
+ * Date:	$Date: 2007/06/27 15:54:44 $
+ * Purpose:	Contains SPI-Flash EEPROM specific definitions and constants
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect
+ *	(C)Copyright 2002-2003 Marvell
+ *
+ *	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT
+ *	The copyright notice above does not evidence any
+ *	actual or intended publication of such source code.
+ *
+ *	This Module contains Proprietary Information of SysKonnect
+ *	and should be treated as Confidential.
+ *
+ *	The information in this file is provided for the exclusive use of
+ *	the licensees of SysKonnect.
+ *	Such users have the right to use, modify, and incorporate this code
+ *	into products for purposes authorized by the license agreement
+ *	provided they include this notice and the associated copyright notice
+ *	with any such product.
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#define	__INC_SKSPI_H 
+
+/* SPI registers */
+// CHIP_IDs should be defined in skgehw.h
+#ifndef B2_CHIP_ID
+#define B2_CHIP_ID			0x011b	/* Chip Identification Number */
+#endif
+
+#ifndef CHIP_ID_GENESIS
+#define CHIP_ID_GENESIS		0x0a	/* Chip ID for GENESIS */
+#endif
+
+#ifndef CHIP_ID_YUKON
+#define CHIP_ID_YUKON		0xb0	/* Chip ID for YUKON */
+#endif
+
+#ifndef CHIP_ID_YUKON_LITE
+#define CHIP_ID_YUKON_LITE	0xb1	/* Chip ID for YUKON-Lite (Rev. A1) */
+#endif
+
+#ifndef CHIP_ID_YUKON_LP
+#define CHIP_ID_YUKON_LP	0xb2	/* Chip ID for YUKON-LP */
+#endif
+
+#ifndef CHIP_ID_YUKON_XL
+#define CHIP_ID_YUKON_XL	0xb3	/* Chip ID for YUKON-2 XL */
+#endif
+
+#ifndef CHIP_ID_YUKON_EC_U
+#define CHIP_ID_YUKON_EC_U      0xb4	/* Chip ID for YUKON-EC Ultra */
+#endif
+
+#ifndef CHIP_ID_YUKON_EX
+#define CHIP_ID_YUKON_EX	0xb5	/* Chip ID for YUKON-2 Extreme */
+#endif
+
+#ifndef CHIP_ID_YUKON_EC
+#define CHIP_ID_YUKON_EC	0xb6	/* Chip ID for YUKON-2 EC */
+#endif
+
+#define SPI_ADR_REG1	0x0120		/* VPD low  addr, SPI loader start addr */
+#define SPI_ADR_REG2	0x0124		/* VPD high addr, PiG loader start addr */
+#define SPI_CTRL_REG	0x0128		/* SPI control & status register */
+
+#define B2_TST_REG1		0x0158		/* Test control register */
+
+/* SPI commands and constants */
+
+#define SPI_PATTERN		0xffffffffL	/* Write value for SPI identification */
+#define SPI_COMP_MASK	0xfffe0000L	/* Compare Mask for SPI identification */
+
+#define SPI_VPD_MIN		0x0001f800L	/* Min Eprom addr for access via VPD port */
+#define SPI_VPD_MAX		0xfffff000L /* Max Eprom addr for access via VPD port */
+
+#define SPI_LSECT_OFF	0x18000L	/* Offset of last sector in SPI eprom */
+#define SPI_CONF_OFF	0x1c000L	/* Offset of config space in SPI eprom */
+
+#define SPI_PIG_OFF		0x1f000L	/* Plug-In-Go (PiG) Config space */
+#define SPI_NOC_OFF		0x1f800L	/* Normal Oper. Config (NOC) space */
+#define SPI_VPD_OFF		0x1c000L	/* Vital Product Data (VPD) space */
+#define SPI_PET_OFF		0x1d000L	/* Pet Frames space */
+
+#define SPI_CHIP_SIZE	0x20000L	/* Size of whole SPI eprom */
+#define SPI_SECT_SIZE	0x8000L		/* Size of a sector in SPI eprom */
+
+#define SPI_CONF_SIZE	0x4000L		/* Size of config area in SPI eprom */
+#define SPI_PIG_SIZE	0x0800L		/* Size of PiG area in SPI eprom */
+#define SPI_NOC_SIZE	0x0800L		/* Size of NOC area in SPI eprom */
+#define SPI_VPD_SIZE	0x0100L		/* Size of VPD area in SPI eprom */
+#define SPI_PET_SIZE	0x2000L		/* Size of PET area in SPI eprom */
+
+#define SPI_SECT_ERASE	0x00008000L	/* Sector erase command */
+#define SPI_CHIP_ERASE	0x00001000L /* Chip erase command */
+#define SPI_VPD_MAP		0x00080000L /* VPD to Eprom mapping flag */
+#define SPI_TIMER_SET	5			/* SPI timeout value (sec.) */
+#define SPI_TIMEOUT		0			/* Timeout check flag */
+#define SPI_READ		1			/* Read flag for spi_flash_manage() */
+#define SPI_VERIFY		2			/* Verify flag for spi_flash_manage() */
+#define SPI_WRITE		3			/* Write flag for spi_flash_manage() */
+
+/* VPD regs from PCI config reg. file mapped to control reg. file */
+
+#define VPD_ADR_REG		0x03d2		/* VPD address register in config file */
+#define VPD_DATA_PORT	0x03d4		/* VPD data port in configuration file */
+#define VPD_FLAG_MASK	0x8000		/* VPD read-write flag */
+
+#define	FT_SPI_UNKNOWN	(-1)
+#define FT_SPI			3			/* Flash type */
+#define FT_SPI_Y2		4			/* Yukon 2/EC SPI flash */
+
+/********************************************************************************
+ * Yukon 2/EC definitions and macros
+ ********************************************************************************/
+
+/* SPI EPROM CONTROL REGISTER */
+#define SPI_Y2_CONTROL_REG				0x60
+/* SPI EPROM ADDRESS REGISTER */
+#define SPI_Y2_ADDRESS_REG				0x64
+/* SPI EPROM DATA REGISTER */
+#define SPI_Y2_DATA_REG					0x68
+/* SPI EPROM VENDOR-/DEVICE-ID REGISTER */
+#define SPI_Y2_VENDOR_DEVICE_ID_REG		0x6c
+/* SPI EPROM FIRST OPCODE REGISTER */
+#define SPI_Y2_OPCODE_REG1				0x78
+/* SPI EPROM SECOND OPCODE REGISTER */
+#define SPI_Y2_OPCODE_REG2				0x7c
+
+/* SPI EPROM READ INSTRUCTION */
+#define SPI_Y2_RD						(0x09L<<16)
+/* SPI EPROM READ ID INSTRUCTION */
+#define SPI_Y2_RDID						(0x0AL<<16)
+/* SPI EPROM READ STATUS REGISTER INSTRUCTION */
+#define SPI_Y2_RDST						(0x0BL<<16)
+/* SPI EPROM WRITE ENABLE INSTRUCTION */
+#define SPI_Y2_WEN						(0x0CL<<16)
+/* SPI EPROM WRITE INSTRUCTION */
+#define SPI_Y2_WR						(0x0DL<<16)
+/* SPI EPROM SECTOR ERASE INSTRUCTION */
+#define SPI_Y2_SERS						(0x0EL<<16)
+/* SPI EPROM CHIP ERASE INSTRUCTION */
+#define SPI_Y2_CERS						(0x0FL<<16)
+/* SPI EPROM command mask  */
+#define SPI_Y2_CMD_MASK					(0x07L<<16)
+
+/* SPI flash read ID protocol */
+#define SPI_Y2_RDID_PROT				(0x01L<<28)
+
+/* SPI flash VPD mapping enable */
+#define SPI_Y2_VPD_ENABLE				(0x01L<<29)
+
+/* SPI EPROM BUSY CHECK */
+#define SPI_Y2_IS_BUSY(w)		((w)&(1L<<30))
+#define SPI_Y2_IS_BUSY_WR(w)	((w)&(1))
+
+#define SPI_Y2_MAN_ID_MASK				0xff00
+#define SPI_Y2_DEV_ID_MASK				0x00ff
+
+/* SPI flash manufacturer ID's */
+#define SPI_MAN_ID_ATMEL				0x1f
+#define SPI_MAN_ID_SST					0xbf
+#define SPI_MAN_ID_ST_M25P20			0x11
+#define SPI_MAN_ID_ST_M25P10			0x10
+
+/* wait for SPI EPROM to finish write/erase operation */
+#define SPI_Y2_WAIT_SE_FINISH_WR() {														\
+	unsigned long stat=1;																	\
+	SPI_Y2_WAIT_SE_FINISH_CMD();															\
+	/* wait for write to finish or timeout */												\
+	spi_timer(SPI_TIMER_SET);																\
+	while( SPI_Y2_IS_BUSY_WR(stat) ){														\
+		if (spi_timer(SPI_TIMEOUT)) {														\
+			break;																			\
+		}																					\
+		spi_out32(SPI_Y2_CONTROL_REG, SPI_Y2_RDST);											\
+		SPI_Y2_WAIT_SE_FINISH_CMD() 														\
+		spi_in32(SPI_Y2_CONTROL_REG, &stat);												\
+	}																						\
+}
+
+/* wait for SPI EPROM to finish command */
+#define SPI_Y2_WAIT_SE_FINISH_CMD() {														\
+	unsigned long stat=(1L<<30);																\
+	/* wait for command to finish */														\
+	spi_timer(SPI_TIMER_SET);																\
+	while( SPI_Y2_IS_BUSY(stat) ){															\
+		if (spi_timer(SPI_TIMEOUT)) {														\
+			break;																			\
+		}																					\
+		spi_in32(SPI_Y2_CONTROL_REG, &stat);												\
+	}																						\
+}
+
+#if (defined Core || defined DJGPP || !defined MSDOS)
+#define huge
+#endif /* Core || DJGPP || !MSDOS */
+
+/* function prototypes */
+
+int flash_check_spi( unsigned long *FlashSize );
+
+int spi_flash_erase(
+	unsigned long off,
+	unsigned long len);
+
+int spi_flash_manage(
+	unsigned char  *data,
+	unsigned long off,
+	unsigned long len,
+	int flag);
+
+int spi_vpd_transfer(
+	char	*buf,	
+	int	addr,	
+	int	len,	
+	int	dir);	
+
+int spi_get_pig(
+	unsigned char  *data,
+	unsigned long len);
+
+int spi_get_noc(
+	unsigned char  *data,
+	unsigned long len);
+
+int spi_update_pig(
+	unsigned char  *data,
+	unsigned long len);
+
+int spi_update_noc(
+	unsigned char  *data,
+	unsigned long len);
+
+int spi_update_pet(
+	unsigned char  *data,
+	unsigned long len);
+
+void spi_yuk2_write_enable(void);
+void spi_yuk2_sst_clear_write_protection(void);
+void spi_yuk2_erase_chip(void);
+unsigned short spi_yuk2_read_chip_id(void);
+int spi_yuk2_get_dev_index(void);
+
diff --git a/drivers/net/sk98lin/h/skgetwsi.h b/drivers/net/sk98lin/h/skgetwsi.h
new file mode 100755
index 0000000..c12133a
--- /dev/null
+++ b/drivers/net/sk98lin/h/skgetwsi.h
@@ -0,0 +1,243 @@
+/******************************************************************************
+ *
+ * Name:	skgetwsi.h
+ * Project:	Gigabit Ethernet Adapters, TWSI-Module
+ * Version:	$Revision: 1.8 $
+ * Date:	$Date: 2005/12/14 16:10:53 $
+ * Purpose:	Special defines for TWSI
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2004 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ * SKGETWSI.H	contains all SK-98xx specific defines for the TWSI handling
+ */
+
+#ifndef _INC_SKGETWSI_H_
+#define _INC_SKGETWSI_H_
+
+/*
+ * Macros to access the B2_I2C_CTRL
+ */
+#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
+	SK_OUT32(IoC, B2_I2C_CTRL,\
+		(flag ? 0x80000000UL : 0x0L) | \
+		(((SK_U32)reg << 16) & I2C_ADDR) | \
+		(((SK_U32)dev << 9) & I2C_DEV_SEL) | \
+		(dev_size & I2C_DEV_SIZE) | \
+		((burst << 4) & I2C_BURST_LEN))
+
+#define SK_I2C_STOP(IoC) {			\
+	SK_U32	I2cCtrl;				\
+	SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl);		\
+	SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP);	\
+}
+
+#define SK_I2C_GET_CTL(IoC, pI2cCtrl)	SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
+
+/*
+ * Macros to access the TWSI SW Registers
+ */
+#define SK_I2C_SET_BIT(IoC, SetBits) {			\
+	SK_U8	OrgBits;				\
+	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
+	SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits));	\
+}
+
+#define SK_I2C_CLR_BIT(IoC, ClrBits) {			\
+	SK_U8	OrgBits;				\
+	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
+	SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits)));	\
+}
+
+#define SK_I2C_GET_SW(IoC, pI2cSw)	SK_IN8(IoC, B2_I2C_SW, pI2cSw)
+
+/*
+ * define the possible sensor states
+ */
+#define SK_SEN_IDLE		0	/* Idle: sensor not read */
+#define SK_SEN_VALUE	1	/* Value Read cycle */
+#define SK_SEN_VALEXT	2	/* Extended Value Read cycle */
+
+/*
+ * Conversion factor to convert read Voltage sensor to milli Volt
+ * Conversion factor to convert read Temperature sensor to 10th degree Celsius
+ */
+#define SK_LM80_VT_LSB		22	/* 22mV LSB resolution */
+#define SK_LM80_TEMP_LSB	10	/* 1 degree LSB resolution */
+#define SK_LM80_TEMPEXT_LSB	 5	/* 0.5 degree LSB resolution for ext. val. */
+
+/*
+ * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
+ * assuming: 6500rpm, 4 pulses, divisor 1
+ */
+#define SK_LM80_FAN_FAKTOR	((22500L*60)/(1*2))
+
+/*
+ * Define sensor management data
+ * Maximum is reached on Genesis copper dual port and Yukon-64
+ * Board specific maximum is in pAC->I2c.MaxSens
+ */
+#define SK_MAX_SENSORS	8	/* maximal no. of installed sensors */
+#define SK_MIN_SENSORS	5	/* minimal no. of installed sensors */
+
+/*
+ * To watch the state machine (SM) use the timer in two ways
+ * instead of one as hitherto
+ */
+#define SK_TIMER_WATCH_SM		0	/* Watch the SM to finish in a spec. time */
+#define SK_TIMER_NEW_GAUGING	1	/* Start a new gauging when timer expires */
+
+/*
+ * Defines for the individual thresholds
+ */
+
+#define C_PLUS_20		120 / 100
+#define C_PLUS_15		115 / 100
+#define C_PLUS_10		110 / 100
+#define C_PLUS_5		105 / 100
+#define C_MINUS_5		 95 / 100
+#define C_MINUS_10		 90 / 100
+#define C_MINUS_15		 85 / 100
+
+/* Temperature sensor */
+#define SK_SEN_TEMP_HIGH_ERR	800	/* Temperature High Err  Threshold */
+#define SK_SEN_TEMP_HIGH_WARN	700	/* Temperature High Warn Threshold */
+#define SK_SEN_TEMP_LOW_WARN	100	/* Temperature Low  Warn Threshold */
+#define SK_SEN_TEMP_LOW_ERR		  0	/* Temperature Low  Err  Threshold */
+
+/* VCC which should be 5 V */
+#define SK_SEN_PCI_5V_HIGH_ERR		5588	/* Voltage PCI High Err  Threshold */
+#define SK_SEN_PCI_5V_HIGH_WARN		5346	/* Voltage PCI High Warn Threshold */
+#define SK_SEN_PCI_5V_LOW_WARN		4664	/* Voltage PCI Low  Warn Threshold */
+#define SK_SEN_PCI_5V_LOW_ERR		4422	/* Voltage PCI Low  Err  Threshold */
+
+/*
+ * VIO may be 5 V or 3.3 V. Initialization takes two parts:
+ * 1. Initialize lowest lower limit and highest higher limit.
+ * 2. After the first value is read correct the upper or the lower limit to
+ *    the appropriate C constant.
+ *
+ * Warning limits are +-5% of the exepected voltage.
+ * Error limits are +-10% of the expected voltage.
+ */
+
+/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
+
+#define SK_SEN_PCI_IO_5V_HIGH_ERR	5566	/* + 10% V PCI-IO High Err Threshold */
+#define SK_SEN_PCI_IO_5V_HIGH_WARN	5324	/* +  5% V PCI-IO High Warn Threshold */
+					/*		5000	mVolt */
+#define SK_SEN_PCI_IO_5V_LOW_WARN	4686	/* -  5% V PCI-IO Low Warn Threshold */
+#define SK_SEN_PCI_IO_5V_LOW_ERR	4444	/* - 10% V PCI-IO Low Err Threshold */
+
+#define SK_SEN_PCI_IO_RANGE_LIMITER	4000	/* 4000 mV range delimiter */
+
+/* correction values for the second pass */
+#define SK_SEN_PCI_IO_3V3_HIGH_ERR	3850	/* + 15% V PCI-IO High Err Threshold */
+#define SK_SEN_PCI_IO_3V3_HIGH_WARN	3674	/* + 10% V PCI-IO High Warn Threshold */
+					/*		3300	mVolt */
+#define SK_SEN_PCI_IO_3V3_LOW_WARN	2926	/* - 10% V PCI-IO Low Warn Threshold */
+#define SK_SEN_PCI_IO_3V3_LOW_ERR	2772	/* - 15% V PCI-IO Low Err  Threshold */
+
+/*
+ * VDD voltage
+ */
+#define SK_SEN_VDD_HIGH_ERR		3630	/* Voltage ASIC High Err  Threshold */
+#define SK_SEN_VDD_HIGH_WARN	3476	/* Voltage ASIC High Warn Threshold */
+#define SK_SEN_VDD_LOW_WARN		3146	/* Voltage ASIC Low  Warn Threshold */
+#define SK_SEN_VDD_LOW_ERR		2970	/* Voltage ASIC Low  Err  Threshold */
+
+/*
+ * PHY PLL 3V3 voltage
+ */
+#define SK_SEN_PLL_3V3_HIGH_ERR		3630	/* Voltage PMA High Err  Threshold */
+#define SK_SEN_PLL_3V3_HIGH_WARN	3476	/* Voltage PMA High Warn Threshold */
+#define SK_SEN_PLL_3V3_LOW_WARN		3146	/* Voltage PMA Low  Warn Threshold */
+#define SK_SEN_PLL_3V3_LOW_ERR		2970	/* Voltage PMA Low  Err  Threshold */
+
+/*
+ * VAUX (YUKON only)
+ */
+#define SK_SEN_VAUX_3V3_VAL		3300	/* Voltage VAUX 3.3 Volt */
+
+#define SK_SEN_VAUX_3V3_HIGH_ERR	(SK_I32)(SK_SEN_VAUX_3V3_VAL * C_PLUS_10)
+#define SK_SEN_VAUX_3V3_HIGH_WARN	(SK_I32)(SK_SEN_VAUX_3V3_VAL * C_PLUS_5)
+#define SK_SEN_VAUX_3V3_LOW_WARN	(SK_I32)(SK_SEN_VAUX_3V3_VAL * C_MINUS_5)
+#define SK_SEN_VAUX_3V3_LOW_ERR		(SK_I32)(SK_SEN_VAUX_3V3_VAL * C_MINUS_10)
+
+#define SK_SEN_VAUX_RANGE_LIMITER	1000	/* 1000 mV range delimiter */
+
+/*
+ * PHY 2V5 voltage
+ */
+#define SK_SEN_PHY_2V5_VAL		2500	/* Voltage PHY 2.5 Volt */
+
+#define SK_SEN_PHY_2V5_HIGH_ERR		(SK_I32)(SK_SEN_PHY_2V5_VAL * C_PLUS_10)
+#define SK_SEN_PHY_2V5_HIGH_WARN	(SK_I32)(SK_SEN_PHY_2V5_VAL * C_PLUS_5)
+#define SK_SEN_PHY_2V5_LOW_WARN		(SK_I32)(SK_SEN_PHY_2V5_VAL * C_MINUS_5)
+#define SK_SEN_PHY_2V5_LOW_ERR		(SK_I32)(SK_SEN_PHY_2V5_VAL * C_MINUS_10)
+
+/*
+ * ASIC Core 1V5 voltage (YUKON only)
+ */
+#define SK_SEN_CORE_1V5_VAL		1500	/* Voltage ASIC Core 1.5 Volt */
+
+#define SK_SEN_CORE_1V5_HIGH_ERR	(SK_I32)(SK_SEN_CORE_1V5_VAL * C_PLUS_10)
+#define SK_SEN_CORE_1V5_HIGH_WARN	(SK_I32)(SK_SEN_CORE_1V5_VAL * C_PLUS_5)
+#define SK_SEN_CORE_1V5_LOW_WARN	(SK_I32)(SK_SEN_CORE_1V5_VAL * C_MINUS_5)
+#define SK_SEN_CORE_1V5_LOW_ERR 	(SK_I32)(SK_SEN_CORE_1V5_VAL * C_MINUS_10)
+
+/*
+ * ASIC Core 1V2 (1V3) voltage (YUKON-2 only)
+ */
+#define SK_SEN_CORE_1V2_VAL		1200	/* Voltage ASIC Core 1.2 Volt */
+
+#define SK_SEN_CORE_1V2_HIGH_ERR	(SK_I32)(SK_SEN_CORE_1V2_VAL * C_PLUS_20)
+#define SK_SEN_CORE_1V2_HIGH_WARN	(SK_I32)(SK_SEN_CORE_1V2_VAL * C_PLUS_15)
+#define SK_SEN_CORE_1V2_LOW_WARN	(SK_I32)(SK_SEN_CORE_1V2_VAL * C_MINUS_5)
+#define SK_SEN_CORE_1V2_LOW_ERR 	(SK_I32)(SK_SEN_CORE_1V2_VAL * C_MINUS_10)
+
+#define SK_SEN_CORE_1V3_VAL		1300	/* Voltage ASIC Core 1.3 Volt */
+
+#define SK_SEN_CORE_1V3_HIGH_ERR	(SK_I32)(SK_SEN_CORE_1V3_VAL * C_PLUS_15)
+#define SK_SEN_CORE_1V3_HIGH_WARN	(SK_I32)(SK_SEN_CORE_1V3_VAL * C_PLUS_10)
+#define SK_SEN_CORE_1V3_LOW_WARN	(SK_I32)(SK_SEN_CORE_1V3_VAL * C_MINUS_5)
+#define SK_SEN_CORE_1V3_LOW_ERR 	(SK_I32)(SK_SEN_CORE_1V3_VAL * C_MINUS_10)
+
+/*
+ * FAN 1 speed
+ */
+/* assuming: 6500rpm +-15%, 4 pulses,
+ * warning at:	80 %
+ * error at:	70 %
+ * no upper limit
+ */
+#define SK_SEN_FAN_HIGH_ERR		20000	/* FAN Speed High Err Threshold */
+#define SK_SEN_FAN_HIGH_WARN	20000	/* FAN Speed High Warn Threshold */
+#define SK_SEN_FAN_LOW_WARN		 5200	/* FAN Speed Low Warn Threshold */
+#define SK_SEN_FAN_LOW_ERR		 4550	/* FAN Speed Low Err Threshold */
+
+/*
+ * Some Voltages need dynamic thresholds
+ */
+#define SK_SEN_DYN_INIT_NONE		 0  /* No dynamic init of thresholds */
+#define SK_SEN_DYN_INIT_PCI_IO		10  /* Init PCI-IO with new thresholds */
+#define SK_SEN_DYN_INIT_VAUX		11  /* Init VAUX with new thresholds */
+
+extern	int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
+#endif	/* n_INC_SKGETWSI_H */
+
diff --git a/drivers/net/sk98lin/h/skpcidevid.h b/drivers/net/sk98lin/h/skpcidevid.h
new file mode 100755
index 0000000..aef2ac4
--- /dev/null
+++ b/drivers/net/sk98lin/h/skpcidevid.h
@@ -0,0 +1,147 @@
+static struct pci_device_id sk98lin_pci_tbl[] __devinitdata = {
+/*	{ pci_vendor_id, pci_device_id, * SAMPLE ENTRY! *
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, */
+
+	/*    1 */
+	{ 0x10B7, 0x1700, /* Generic 3Com 3C940 Gigabit Ethernet Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*    2 */
+	{ 0x10B7, 0x80EB, /* Generic 3Com 3C940B Gigabit LOM Ethernet Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*    3 */
+	{ 0x1148, 0x4300, /* Generic SysKonnect SK-98xx Gigabit Ethernet Server Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*    4 */
+	{ 0x1148, 0x4320, /* Generic SysKonnect SK-98xx V2.0 Gigabit Ethernet Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*    5 */
+	{ 0x1148, 0x9000, /* Generic SysKonnect SK-9Sxx 10/100/1000Base-T Server Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*    6 */
+	{ 0x1148, 0x9E00, /* Generic SysKonnect SK-9Exx 10/100/1000Base-T Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*    7 */
+	{ 0x1186, 0x4001, /* D-Link DGE-550SX PCI-X Gigabit Ethernet Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*    8 */
+	{ 0x1186, 0x4B00, /* D-Link DGE-560T PCI Express Gigabit Ethernet Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*    9 */
+	{ 0x1186, 0x4B01, /* D-Link DGE-530T Gigabit Ethernet Adapter (rev.B) */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   10 */
+	{ 0x1186, 0x4B02, /* D-Link DGE-560SX Single Fiber Gigabit Ethernet PCI-E Adapter (rev.A) */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   11 */
+	{ 0x1186, 0x4B03, /* D-Link DGE-550T Gigabit Ethernet Adapter V.B1 */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   12 */
+	{ 0x1186, 0x4C00, /* D-Link DGE-530T Gigabit Ethernet Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   13 */
+	{ 0x11AB, 0x4320, /* Generic Marvell Yukon 88E8001/8003/8010 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   14 */
+	{ 0x11AB, 0x4340, /* Generic Marvell Yukon 88E8021 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   15 */
+	{ 0x11AB, 0x4341, /* Generic Marvell Yukon 88E8022 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   16 */
+	{ 0x11AB, 0x4342, /* Generic Marvell Yukon 88E8061 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   17 */
+	{ 0x11AB, 0x4343, /* Generic Marvell Yukon 88E8062 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   18 */
+	{ 0x11AB, 0x4344, /* Generic Marvell Yukon 88E8021 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   19 */
+	{ 0x11AB, 0x4345, /* Generic Marvell Yukon 88E8022 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   20 */
+	{ 0x11AB, 0x4346, /* Generic Marvell Yukon 88E8061 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   21 */
+	{ 0x11AB, 0x4347, /* Generic Marvell Yukon 88E8062 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   22 */
+	{ 0x11AB, 0x4350, /* Generic Marvell Yukon 88E8035 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   23 */
+	{ 0x11AB, 0x4351, /* Generic Marvell Yukon 88E8036 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   24 */
+	{ 0x11AB, 0x4352, /* Generic Marvell Yukon 88E8038 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   25 */
+	{ 0x11AB, 0x4353, /* Generic Marvell Yukon 88E8039 PCI-E Fast Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   26 */
+	{ 0x11AB, 0x4354, /* Generic Marvell Yukon 88E8040 PCI-E Fast Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   27 */
+	{ 0x11AB, 0x4355, /* Generic Marvell Yukon 88E8040T PCI-E Fast Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   28 */
+	{ 0x11AB, 0x4356, /* Generic Marvell Yukon 88EC033 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   29 */
+	{ 0x11AB, 0x4357, /* Generic Marvell Yukon 88E8042 PCI-E Fast Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   30 */
+	{ 0x11AB, 0x435A, /* Generic Marvell Yukon 88E8048 PCI-E Fast Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   31 */
+	{ 0x11AB, 0x4360, /* Generic Marvell Yukon 88E8052 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   32 */
+	{ 0x11AB, 0x4361, /* Generic Marvell Yukon 88E8050 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   33 */
+	{ 0x11AB, 0x4362, /* Generic Marvell Yukon 88E8053 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   34 */
+	{ 0x11AB, 0x4363, /* Generic Marvell Yukon 88E8055 PCI-E Gigabit Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   35 */
+	{ 0x11AB, 0x4364, /* Generic Marvell Yukon 88E8056 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   36 */
+	{ 0x11AB, 0x4365, /* Generic Marvell Yukon 88E8070 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   37 */
+	{ 0x11AB, 0x4366, /* Generic Marvell Yukon 88EC036 PCI-E Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   38 */
+	{ 0x11AB, 0x4367, /* Generic Marvell Yukon 88EC032 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   39 */
+	{ 0x11AB, 0x4368, /* Generic Marvell Yukon 88EC034 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   40 */
+	{ 0x11AB, 0x4369, /* Generic Marvell Yukon 88EC042 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   41 */
+	{ 0x11AB, 0x436A, /* Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   42 */
+	{ 0x11AB, 0x436B, /* Generic Marvell Yukon 88E8071 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   43 */
+	{ 0x11AB, 0x436C, /* Generic Marvell Yukon 88E8072 based Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   44 */
+	{ 0x11AB, 0x5005, /* Belkin Gigabit Desktop Card10/100/1000Base-T Adapter, Copper RJ-45 */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   45 */
+	{ 0x1371, 0x434E, /* Generic CNet PowerG-2000 1000/100/10Mbps N-Way PCI-Bus Giga-Card */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   46 */
+	{ 0x1737, 0x1032, /* Linksys EG1032 v2 Instant Gigabit Network Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	/*   47 */
+	{ 0x1737, 0x1064, /* Linksys EG1064 v2 Instant Gigabit Network Adapter */
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ 0, }
+};
diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
new file mode 100755
index 0000000..7c9fed5
--- /dev/null
+++ b/drivers/net/sk98lin/h/skqueue.h
@@ -0,0 +1,105 @@
+/******************************************************************************
+ *
+ * Name:	skqueue.h
+ * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 2.4 $
+ * Date:	$Date: 2005/12/14 16:11:03 $
+ * Purpose:	Defines for the Event queue
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ * SKQUEUE.H	contains all defines and types for the event queue
+ */
+
+#ifndef _SKQUEUE_H_
+#define _SKQUEUE_H_
+
+
+/*
+ * define the event classes to be served
+ */
+#define	SKGE_DRV	1	/* Driver Event Class */
+#define	SKGE_RLMT	2	/* RLMT Event Class */
+#define	SKGE_I2C	3	/* I2C Event Class */
+#define	SKGE_PNMI	4	/* PNMI Event Class */
+#define	SKGE_CSUM	5	/* Checksum Event Class */
+#define	SKGE_HWAC	6	/* Hardware Access Event Class */
+
+#define	SKGE_SWT	9	/* Software Timer Event Class */
+#define	SKGE_LACP	10	/* LACP Aggregation Event Class */
+#define	SKGE_RSF	11	/* RSF Aggregation Event Class */
+#define	SKGE_MARKER	12	/* MARKER Aggregation Event Class */
+#define	SKGE_FD		13	/* FD Distributor Event Class */
+#ifdef SK_ASF
+#define	SKGE_ASF	14	/* ASF Event Class */
+#endif
+
+/*
+ * define event queue as circular buffer
+ */
+#define SK_MAX_EVENT	64
+
+/*
+ * Parameter union for the Para stuff
+ */
+typedef	union u_EvPara {
+	void	*pParaPtr;	/* Parameter Pointer */
+	SK_U64	Para64;		/* Parameter 64bit version */
+	SK_U32	Para32[2];	/* Parameter Array of 32bit parameters */
+} SK_EVPARA;
+
+/*
+ * Event Queue
+ *	skqueue.c
+ * events are class/value pairs
+ *	class	is addressee, e.g. RLMT, PNMI etc.
+ *	value	is command, e.g. line state change, ring op change etc.
+ */
+typedef	struct s_EventElem {
+	SK_U32		Class;			/* Event class */
+	SK_U32		Event;			/* Event value */
+	SK_EVPARA	Para;			/* Event parameter */
+} SK_EVENTELEM;
+
+typedef	struct s_Queue {
+	SK_EVENTELEM	EvQueue[SK_MAX_EVENT];
+	SK_EVENTELEM	*EvPut;
+	SK_EVENTELEM	*EvGet;
+} SK_QUEUE;
+
+extern	void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level);
+extern	void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event,
+	SK_EVPARA Para);
+extern	int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc);
+
+
+/* Define Error Numbers and messages */
+#define	SKERR_Q_E001	(SK_ERRBASE_QUEUE+0)
+#define	SKERR_Q_E001MSG	"Event queue overflow"
+#define	SKERR_Q_E002	(SKERR_Q_E001+1)
+#define	SKERR_Q_E002MSG	"Undefined event class"
+#define	SKERR_Q_E003	(SKERR_Q_E001+2)
+#define	SKERR_Q_E003MSG	"Event queued in Init Level 0"
+#define	SKERR_Q_E004	(SKERR_Q_E001+3)
+#define	SKERR_Q_E004MSG	"Error Reported from Event Fuction (Queue Blocked)"
+#define	SKERR_Q_E005	(SKERR_Q_E001+4)
+#define	SKERR_Q_E005MSG	"Event scheduler called in Init Level 0 or 1"
+#endif	/* _SKQUEUE_H_ */
+
diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
new file mode 100755
index 0000000..ddf6f6d
--- /dev/null
+++ b/drivers/net/sk98lin/h/skrlmt.h
@@ -0,0 +1,443 @@
+/******************************************************************************
+ *
+ * Name:	skrlmt.h
+ * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 2.3 $
+ * Date:	$Date: 2007/07/30 08:45:33 $
+ * Purpose:	Header file for Redundant Link ManagemenT.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * This is the header file for Redundant Link ManagemenT.
+ *
+ * Include File Hierarchy:
+ *
+ *	"skdrv1st.h"
+ *	...
+ *	"sktypes.h"
+ *	"skqueue.h"
+ *	"skaddr.h"
+ *	"skrlmt.h"
+ *	...
+ *	"skdrv2nd.h"
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKRLMT_H
+#define __INC_SKRLMT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* cplusplus */
+
+/* defines ********************************************************************/
+
+#define	SK_RLMT_NET_DOWN_TEMP	1	/* NET_DOWN due to last port down. */
+#define	SK_RLMT_NET_DOWN_FINAL	2	/* NET_DOWN due to RLMT_STOP. */
+
+/* ----- Default queue sizes - must be multiples of 8 KB ----- */
+
+/* Less than 8 KB free in RX queue => pause frames. */
+#define SK_RLMT_STANDBY_QRXSIZE	128	/* Size of rx standby queue in KB. */
+#define SK_RLMT_STANDBY_QXASIZE	32	/* Size of async standby queue in KB. */
+#define SK_RLMT_STANDBY_QXSSIZE	0	/* Size of sync standby queue in KB. */
+
+#define SK_RLMT_MAX_TX_BUF_SIZE	60	/* Maximum RLMT transmit size. */
+
+/* ----- PORT states ----- */
+
+#define SK_RLMT_PS_INIT			0	/* Port state: Init. */
+#define SK_RLMT_PS_LINK_DOWN	1	/* Port state: Link down. */
+#define SK_RLMT_PS_DOWN			2	/* Port state: Port down. */
+#define SK_RLMT_PS_GOING_UP		3	/* Port state: Going up. */
+#define SK_RLMT_PS_UP			4	/* Port state: Up. */
+
+/* ----- RLMT states ----- */
+
+#define SK_RLMT_RS_INIT			0	/* RLMT state: Init. */
+#define SK_RLMT_RS_NET_DOWN		1	/* RLMT state: Net down. */
+#define SK_RLMT_RS_NET_UP		2	/* RLMT state: Net up. */
+
+/* ----- PORT events ----- */
+
+#define SK_RLMT_LINK_UP			1001	/* Link came up. */
+#define SK_RLMT_LINK_DOWN		1002	/* Link went down. */
+#define SK_RLMT_PORT_ADDR		1003	/* Port address changed. */
+
+/* ----- RLMT events ----- */
+
+#define SK_RLMT_START			2001	/* Start RLMT. */
+#define SK_RLMT_STOP			2002	/* Stop RLMT. */
+#define SK_RLMT_PACKET_RECEIVED	2003	/* Packet was received for RLMT. */
+#define SK_RLMT_STATS_CLEAR		2004	/* Clear statistics. */
+#define SK_RLMT_STATS_UPDATE	2005	/* Update statistics. */
+#define SK_RLMT_PREFPORT_CHANGE	2006	/* Change preferred port. */
+#define SK_RLMT_MODE_CHANGE		2007	/* New RlmtMode. */
+#define SK_RLMT_SET_NETS		2008	/* Number of Nets (1 or 2). */
+
+/* ----- RLMT mode bits ----- */
+
+/*
+ * CAUTION:	These defines are private to RLMT.
+ *			Please use the RLMT mode defines below.
+ */
+
+#define SK_RLMT_CHECK_LINK		  1		/* Check Link. */
+#define SK_RLMT_CHECK_LOC_LINK	  2		/* Check other link on same adapter. */
+#define SK_RLMT_CHECK_SEG		  4		/* Check segmentation. */
+
+#ifndef RLMT_CHECK_REMOTE
+#define SK_RLMT_CHECK_OTHERS	SK_RLMT_CHECK_LOC_LINK
+#else	/* RLMT_CHECK_REMOTE */
+#define SK_RLMT_CHECK_REM_LINK	  8		/* Check link(s) on other adapter(s). */
+#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED	3
+#define SK_RLMT_CHECK_OTHERS	\
+		(SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
+#endif	/* RLMT_CHECK_REMOTE */
+
+#ifndef SK_RLMT_ENABLE_TRANSPARENT
+#define SK_RLMT_TRANSPARENT		  0		/* RLMT transparent - inactive. */
+#else	/* SK_RLMT_ENABLE_TRANSPARENT */
+#define SK_RLMT_TRANSPARENT		128		/* RLMT transparent. */
+#endif	/* SK_RLMT_ENABLE_TRANSPARENT */
+
+/* ----- RLMT modes ----- */
+
+/* Check Link State. */
+#define SK_RLMT_MODE_CLS	(SK_RLMT_CHECK_LINK)
+
+/* Check Local Ports: check other links on the same adapter. */
+#define SK_RLMT_MODE_CLP	(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK)
+
+/* Check Local Ports and Segmentation Status. */
+#define SK_RLMT_MODE_CLPSS	\
+		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG)
+
+#ifdef RLMT_CHECK_REMOTE
+/* Check Local and Remote Ports: check links (local or remote). */
+	Name of define TBD!
+#define SK_RLMT_MODE_CRP	\
+		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
+
+/* Check Local and Remote Ports and Segmentation Status. */
+	Name of define TBD!
+#define SK_RLMT_MODE_CRPSS	\
+		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \
+		SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG)
+#endif	/* RLMT_CHECK_REMOTE */
+
+/* ----- RLMT lookahead result bits ----- */
+
+#define SK_RLMT_RX_RLMT			1	/* Give packet to RLMT. */
+#define SK_RLMT_RX_PROTOCOL		2	/* Give packet to protocol. */
+
+/* Macros */
+
+#if 0
+SK_AC		*pAC		/* adapter context */
+SK_U32		PortNum		/* receiving port */
+unsigned	PktLen		/* received packet's length */
+SK_BOOL		IsBc		/* Flag: packet is broadcast */
+unsigned	*pOffset	/* offs. of bytes to present to SK_RLMT_LOOKAHEAD */
+unsigned	*pNumBytes	/* #Bytes to present to SK_RLMT_LOOKAHEAD */
+#endif	/* 0 */
+
+#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \
+	SK_AC	*_pAC; \
+	SK_U32	_PortNum; \
+	_pAC = (pAC); \
+	_PortNum = (SK_U32)(PortNum); \
+	/* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \
+	_pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \
+    if (_pAC->Rlmt.RlmtOff) { \
+		*(pNumBytes) = 0; \
+    } \
+    else {\
+        if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \
+    		*(pNumBytes) = 0; \
+    	} \
+    	else if (IsBc) { \
+    		if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \
+    			*(pNumBytes) = 6; \
+    			*(pOffset) = 6; \
+    		} \
+    		else { \
+    			*(pNumBytes) = 0; \
+    		} \
+    	} \
+    	else { \
+    		if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \
+    			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+    			*(pNumBytes) = 0; \
+    		} \
+    		else { \
+    			*(pNumBytes) = 6; \
+    			*(pOffset) = 0; \
+    		} \
+    	} \
+    } \
+}
+
+#if 0
+SK_AC		*pAC		/* adapter context */
+SK_U32		PortNum		/* receiving port */
+SK_U8		*pLaPacket,	/* received packet's data (points to pOffset) */
+SK_BOOL		IsBc		/* Flag: packet is broadcast */
+SK_BOOL		IsMc		/* Flag: packet is multicast */
+unsigned	*pForRlmt	/* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */
+SK_RLMT_LOOKAHEAD() expects *pNumBytes from
+packet offset *pOffset (s.a.) at *pLaPacket.
+
+If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is
+BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler
+can trash unneeded parts of the if construction.
+#endif	/* 0 */
+
+#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \
+	SK_AC	*_pAC; \
+	SK_U32	_PortNum; \
+	SK_U8	*_pLaPacket; \
+	_pAC = (pAC); \
+	_PortNum = (SK_U32)(PortNum); \
+	_pLaPacket = (SK_U8 *)(pLaPacket); \
+	if (IsBc) {\
+		if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \
+			_PortNum].Net->NetNumber].CurrentMacAddress.a)) { \
+			_pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \
+			_pAC->Rlmt.CheckSwitch = SK_TRUE; \
+		} \
+		/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+		*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+	} \
+	else if (IsMc) { \
+		if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \
+			_pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \
+			if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \
+				*(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \
+			} \
+			else { \
+				*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+			} \
+		} \
+		else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \
+			*(pForRlmt) = SK_RLMT_RX_RLMT; \
+		} \
+		else { \
+			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+		} \
+	} \
+	else { \
+		if (SK_ADDR_EQUAL( \
+			_pLaPacket, \
+			_pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \
+			*(pForRlmt) = SK_RLMT_RX_RLMT; \
+		} \
+		else { \
+			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+		} \
+	} \
+}
+
+#ifdef SK_RLMT_FAST_LOOKAHEAD
+Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead.
+#endif	/* SK_RLMT_FAST_LOOKAHEAD */
+#ifdef SK_RLMT_SLOW_LOOKAHEAD
+Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead.
+#endif	/* SK_RLMT_SLOW_LOOKAHEAD */
+
+/* typedefs *******************************************************************/
+
+#ifdef SK_RLMT_MBUF_PRIVATE
+typedef struct s_RlmtMbuf {
+	some content
+} SK_RLMT_MBUF;
+#endif	/* SK_RLMT_MBUF_PRIVATE */
+
+
+#ifdef SK_LA_INFO
+typedef struct s_Rlmt_PacketInfo {
+	unsigned	PacketLength;			/* Length of packet. */
+	unsigned	PacketType;				/* Directed/Multicast/Broadcast. */
+} SK_RLMT_PINFO;
+#endif	/* SK_LA_INFO */
+
+
+typedef struct s_RootId {
+	SK_U8		Id[8];					/* Root Bridge Id. */
+} SK_RLMT_ROOT_ID;
+
+
+typedef struct s_port {
+	SK_MAC_ADDR	CheckAddr;
+	SK_BOOL		SuspectTx;
+} SK_PORT_CHECK;
+
+
+typedef struct s_RlmtNet SK_RLMT_NET;
+
+
+typedef struct s_RlmtPort {
+
+/* ----- Public part (read-only) ----- */
+
+	SK_U8			PortState;				/* Current state of this port. */
+
+	/* For PNMI */
+	SK_BOOL			LinkDown;
+	SK_BOOL			PortDown;
+	SK_U8			Align01;
+
+	SK_U32			PortNumber;				/* Number of port on adapter. */
+	SK_RLMT_NET *	Net;					/* Net port belongs to. */
+
+	SK_U64			TxHelloCts;
+	SK_U64			RxHelloCts;
+	SK_U64			TxSpHelloReqCts;
+	SK_U64			RxSpHelloCts;
+
+/* ----- Private part ----- */
+
+/*	SK_U64			PacketsRx; */				/* Total packets received. */
+	SK_U32			PacketsPerTimeSlot;		/* Packets rxed between TOs. */
+/*	SK_U32			DataPacketsPerTimeSlot; */	/* Data packets ... */
+	SK_U32			BpduPacketsPerTimeSlot;	/* BPDU packets rxed in TS. */
+	SK_U64			BcTimeStamp;			/* Time of last BC receive. */
+	SK_U64			GuTimeStamp;			/* Time of entering GOING_UP. */
+
+	SK_TIMER		UpTimer;				/* Timer struct Link/Port up. */
+	SK_TIMER		DownRxTimer;			/* Timer struct down rx. */
+	SK_TIMER		DownTxTimer;			/* Timer struct down tx. */
+
+	SK_U32			CheckingState;			/* Checking State. */
+
+	SK_ADDR_PORT *	AddrPort;
+
+	SK_U8			Random[4];				/* Random value. */
+	unsigned		PortsChecked;			/* #ports checked. */
+	unsigned		PortsSuspect;			/* #ports checked that are s. */
+	SK_PORT_CHECK	PortCheck[1];
+/*	SK_PORT_CHECK	PortCheck[SK_MAX_MACS - 1]; */
+
+	SK_BOOL			PortStarted;			/* Port is started. */
+	SK_BOOL			PortNoRx;				/* NoRx for >= 1 time slot. */
+	SK_BOOL			RootIdSet;
+	SK_RLMT_ROOT_ID	Root;					/* Root Bridge Id. */
+} SK_RLMT_PORT;
+
+
+struct s_RlmtNet {
+
+/* ----- Public part (read-only) ----- */
+
+	SK_U32			NetNumber;			/* Number of net. */
+
+	SK_RLMT_PORT *	Port[SK_MAX_MACS];	/* Ports that belong to this net. */
+	SK_U32			NumPorts;			/* Number of ports. */
+	SK_U32			PrefPort;			/* Preferred port. */
+
+	/* For PNMI */
+
+	SK_U32			ChgBcPrio;			/* Change Priority of last broadcast received */
+	SK_U32			RlmtMode;			/* Check ... */
+	SK_U32			ActivePort;			/* Active port. */
+	SK_U32			Preference;		/* 0xFFFFFFFF: Automatic. */
+
+	SK_U8			RlmtState;			/* Current RLMT state. */
+
+/* ----- Private part ----- */
+	SK_BOOL			RootIdSet;
+	SK_U16			Align01;
+
+	int				LinksUp;			/* #Links up. */
+	int				PortsUp;			/* #Ports up. */
+	SK_U32			TimeoutValue;		/* RLMT timeout value. */
+
+	SK_U32			CheckingState;		/* Checking State. */
+	SK_RLMT_ROOT_ID	Root;				/* Root Bridge Id. */
+
+	SK_TIMER		LocTimer;			/* Timer struct. */
+	SK_TIMER		SegTimer;			/* Timer struct. */
+};
+
+
+typedef struct s_Rlmt {
+
+/* ----- Public part (read-only) ----- */
+
+	SK_U32			NumNets;			/* Number of nets. */
+	SK_U32			NetsStarted;		/* Number of nets started. */
+	SK_RLMT_NET		Net[SK_MAX_NETS];	/* Array of available nets. */
+	SK_RLMT_PORT	Port[SK_MAX_MACS];	/* Array of available ports. */
+
+/* ----- Private part ----- */
+	SK_BOOL			CheckSwitch;
+	SK_BOOL			RlmtOff;			/* set to non zero value if:
+										 * - Mac addresses are equal
+										 * - second MAC address is zero
+										 * - it is a single link adapter
+										 * - adapter is in DualNet mode
+										 */
+	SK_U16			Align01;
+
+} SK_RLMT;
+
+
+extern	SK_MAC_ADDR	BridgeMcAddr;
+extern	SK_MAC_ADDR	SkRlmtMcAddr;
+
+/* function prototypes ********************************************************/
+
+
+#ifndef SK_KR_PROTO
+
+/* Functions provided by SkRlmt */
+
+/* ANSI/C++ compliant function prototypes */
+
+extern	void	SkRlmtInit(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	int		Level);
+
+extern	int	SkRlmtEvent(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	SK_U32		Event,
+	SK_EVPARA	Para);
+
+#else	/* defined(SK_KR_PROTO) */
+
+/* Non-ANSI/C++ compliant function prototypes */
+
+#error KR-style function prototypes are not yet provided.
+
+#endif	/* defined(SK_KR_PROTO)) */
+
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif	/* __INC_SKRLMT_H */
diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
new file mode 100755
index 0000000..2c67f5f
--- /dev/null
+++ b/drivers/net/sk98lin/h/sktimer.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * Name:	sktimer.h
+ * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 2.2 $
+ * Date:	$Date: 2005/12/14 16:11:03 $
+ * Purpose:	Defines for the timer functions
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ * SKTIMER.H	contains all defines and types for the timer functions
+ */
+
+#ifndef	_SKTIMER_H_
+#define _SKTIMER_H_
+
+#include "h/skqueue.h"
+
+/*
+ * SK timer
+ * - needed wherever a timer is used. Put this in your data structure
+ *   wherever you want.
+ */
+typedef	struct s_Timer SK_TIMER;
+
+struct s_Timer {
+	SK_TIMER	*TmNext;	/* linked list */
+	SK_U32		TmClass;	/* Timer Event class */
+	SK_U32		TmEvent;	/* Timer Event value */
+	SK_EVPARA	TmPara;		/* Timer Event parameter */
+	SK_U32		TmDelta;	/* delta time */
+	int			TmActive;	/* flag: active/inactive */
+};
+
+/*
+ * Timer control struct.
+ * - use in Adapters context name pAC->Tim
+ */
+typedef	struct s_TimCtrl {
+	SK_TIMER	*StQueue;	/* Head of Timer queue */
+} SK_TIMCTRL;
+
+extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level);
+extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer);
+extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer,
+	SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para);
+extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc);
+#endif	/* _SKTIMER_H_ */
diff --git a/drivers/net/sk98lin/h/sktwsi.h b/drivers/net/sk98lin/h/sktwsi.h
new file mode 100755
index 0000000..019987e
--- /dev/null
+++ b/drivers/net/sk98lin/h/sktwsi.h
@@ -0,0 +1,179 @@
+/******************************************************************************
+ *
+ * Name:	sktwsi.h
+ * Project:	Gigabit Ethernet Adapters, TWSI-Module
+ * Version:	$Revision: 1.2 $
+ * Date:	$Date: 2005/12/14 16:10:53 $
+ * Purpose:	Defines to access Voltage and Temperature Sensor
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ * SKTWSI.H	contains all TWSI specific defines
+ */
+
+#ifndef _SKTWSI_H_
+#define _SKTWSI_H_
+
+typedef struct  s_Sensor SK_SENSOR;
+
+#include "h/skgetwsi.h"
+
+/*
+ * Define the TWSI events.
+ */
+#define SK_I2CEV_IRQ	1	/* IRQ happened Event */
+#define SK_I2CEV_TIM	2	/* Timeout event */
+#define SK_I2CEV_CLEAR	3	/* Clear MIB Values */
+
+/*
+ * Define READ and WRITE Constants.
+ */
+#define I2C_READ	0
+#define I2C_WRITE	1
+#define I2C_BURST	1
+#define I2C_SINGLE	0
+
+#define SKERR_I2C_E001		(SK_ERRBASE_I2C+0)
+#define SKERR_I2C_E001MSG	"Sensor index unknown"
+#define SKERR_I2C_E002		(SKERR_I2C_E001+1)
+#define SKERR_I2C_E002MSG	"TWSI: transfer does not complete"
+#define SKERR_I2C_E003		(SKERR_I2C_E002+1)
+#define SKERR_I2C_E003MSG	"LM80: NAK on device send"
+#define SKERR_I2C_E004		(SKERR_I2C_E003+1)
+#define SKERR_I2C_E004MSG	"LM80: NAK on register send"
+#define SKERR_I2C_E005		(SKERR_I2C_E004+1)
+#define SKERR_I2C_E005MSG	"LM80: NAK on device (2) send"
+#define SKERR_I2C_E006		(SKERR_I2C_E005+1)
+#define SKERR_I2C_E006MSG	"Unknown event"
+#define SKERR_I2C_E007		(SKERR_I2C_E006+1)
+#define SKERR_I2C_E007MSG	"LM80 read out of state"
+#define SKERR_I2C_E008		(SKERR_I2C_E007+1)
+#define SKERR_I2C_E008MSG	"Unexpected sensor read completed"
+#define SKERR_I2C_E009		(SKERR_I2C_E008+1)
+#define SKERR_I2C_E009MSG	"WARNING: temperature sensor out of range"
+#define SKERR_I2C_E010		(SKERR_I2C_E009+1)
+#define SKERR_I2C_E010MSG	"WARNING: voltage sensor out of range"
+#define SKERR_I2C_E011		(SKERR_I2C_E010+1)
+#define SKERR_I2C_E011MSG	"ERROR: temperature sensor out of range"
+#define SKERR_I2C_E012		(SKERR_I2C_E011+1)
+#define SKERR_I2C_E012MSG	"ERROR: voltage sensor out of range"
+#define SKERR_I2C_E013		(SKERR_I2C_E012+1)
+#define SKERR_I2C_E013MSG	"ERROR: couldn't init sensor"
+#define SKERR_I2C_E014		(SKERR_I2C_E013+1)
+#define SKERR_I2C_E014MSG	"WARNING: fan sensor out of range"
+#define SKERR_I2C_E015		(SKERR_I2C_E014+1)
+#define SKERR_I2C_E015MSG	"ERROR: fan sensor out of range"
+#define SKERR_I2C_E016		(SKERR_I2C_E015+1)
+#define SKERR_I2C_E016MSG	"TWSI: active transfer does not complete"
+
+/*
+ * Define Timeout values
+ */
+#define SK_I2C_TIM_LONG		2000000L	/* 2 seconds */
+#define SK_I2C_TIM_SHORT	 100000L	/* 100 milliseconds */
+#define SK_I2C_TIM_WATCH	1000000L	/* 1 second */
+
+/*
+ * Define trap and error log hold times
+ */
+#ifndef	SK_SEN_ERR_TR_HOLD
+#define SK_SEN_ERR_TR_HOLD		(4*SK_TICKS_PER_SEC)
+#endif
+#ifndef	SK_SEN_ERR_LOG_HOLD
+#define SK_SEN_ERR_LOG_HOLD		(60*SK_TICKS_PER_SEC)
+#endif
+#ifndef	SK_SEN_WARN_TR_HOLD
+#define SK_SEN_WARN_TR_HOLD		(15*SK_TICKS_PER_SEC)
+#endif
+#ifndef	SK_SEN_WARN_LOG_HOLD
+#define SK_SEN_WARN_LOG_HOLD	(15*60*SK_TICKS_PER_SEC)
+#endif
+
+/*
+ * Defines for SenType
+ */
+#define SK_SEN_UNKNOWN	0
+#define SK_SEN_TEMP		1
+#define SK_SEN_VOLT		2
+#define SK_SEN_FAN		3
+
+/*
+ * Define for the SenErrorFlag
+ */
+#define SK_SEN_ERR_NOT_PRESENT	0	/* Error Flag: Sensor not present */
+#define SK_SEN_ERR_OK			1	/* Error Flag: O.K. */
+#define SK_SEN_ERR_WARN			2	/* Error Flag: Warning */
+#define SK_SEN_ERR_ERR			3	/* Error Flag: Error */
+#define SK_SEN_ERR_FAULTY		4	/* Error Flag: Faulty */
+
+/*
+ * Define the Sensor struct
+ */
+struct	s_Sensor {
+	char	*SenDesc;			/* Description */
+	int		SenType;			/* Voltage or Temperature */
+	SK_I32	SenValue;			/* Current value of the sensor */
+	SK_I32	SenThreErrHigh;		/* High error Threshhold of this sensor */
+	SK_I32	SenThreWarnHigh;	/* High warning Threshhold of this sensor */
+	SK_I32	SenThreErrLow;		/* Lower error Threshold of the sensor */
+	SK_I32	SenThreWarnLow;		/* Lower warning Threshold of the sensor */
+	int		SenErrFlag;			/* Sensor indicated an error */
+	SK_BOOL	SenInit;			/* Is sensor initialized ? */
+	SK_U64	SenErrCts;			/* Error trap counter */
+	SK_U64	SenWarnCts;			/* Warning trap counter */
+	SK_U64	SenBegErrTS;		/* Begin error timestamp */
+	SK_U64	SenBegWarnTS;		/* Begin warning timestamp */
+	SK_U64	SenLastErrTrapTS;	/* Last error trap timestamp */
+	SK_U64	SenLastErrLogTS;	/* Last error log timestamp */
+	SK_U64	SenLastWarnTrapTS;	/* Last warning trap timestamp */
+	SK_U64	SenLastWarnLogTS;	/* Last warning log timestamp */
+	int		SenState;			/* Sensor State (see HW specific include) */
+	int		(*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
+								/* Sensors read function */
+	SK_U16	SenReg;				/* Register Address for this sensor */
+	SK_U8	SenDev;				/* Device Selection for this sensor */
+};
+
+typedef	struct	s_I2c {
+	SK_SENSOR	SenTable[SK_MAX_SENSORS];	/* Sensor Table */
+	int			CurrSens;	/* Which sensor is currently queried */
+	int			MaxSens;	/* Max. number of sensors */
+	int			TimerMode;	/* Use the timer also to watch the state machine */
+	int			InitLevel;	/* Initialized Level */
+#ifndef SK_DIAG
+	int			DummyReads;	/* Number of non-checked dummy reads */
+	SK_TIMER	SenTimer;	/* Sensors timer */
+#endif /* !SK_DIAG */
+} SK_I2C;
+
+extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
+extern int SkI2cWrite(SK_AC *pAC, SK_IOC IoC, SK_U32 Data, int Dev, int Size,
+					   int Reg, int Burst);
+extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
+#ifdef SK_DIAG
+extern	SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
+						 int Burst);
+#else /* !SK_DIAG */
+extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
+extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
+extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
+#endif /* !SK_DIAG */
+#endif /* n_SKTWSI_H */
+
diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
new file mode 100755
index 0000000..cba0790
--- /dev/null
+++ b/drivers/net/sk98lin/h/sktypes.h
@@ -0,0 +1,49 @@
+/******************************************************************************
+ *
+ * Name:	sktypes.h
+ * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.3 $
+ * Date:	$Date: 2006/07/19 15:37:23 $
+ * Purpose:	Define data types for Linux
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+ 
+#ifndef __INC_SKTYPES_H
+#define __INC_SKTYPES_H
+
+#define SK_I8    s8    /* 8 bits (1 byte) signed       */
+#define SK_U8    u8    /* 8 bits (1 byte) unsigned     */
+#define SK_I16  s16    /* 16 bits (2 bytes) signed     */
+#define SK_U16  u16    /* 16 bits (2 bytes) unsigned   */
+#define SK_I32  s32    /* 32 bits (4 bytes) signed     */
+#define SK_U32  u32    /* 32 bits (4 bytes) unsigned   */
+#define SK_I64  s64    /* 64 bits (8 bytes) signed     */
+#define SK_U64  u64    /* 64 bits (8 bytes) unsigned   */
+
+#define SK_UPTR	ulong  /* casting pointer <-> integral */
+
+#define SK_BOOL   SK_U8
+#define SK_FALSE  0
+#define SK_TRUE   (!SK_FALSE)
+
+#endif	/* __INC_SKTYPES_H */
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
new file mode 100755
index 0000000..98b0aa7
--- /dev/null
+++ b/drivers/net/sk98lin/h/skversion.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * Name:	skversion.h
+ * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.1.4.1 $
+ * Date:	$Date: 2006/08/29 13:32:53 $
+ * Purpose:	specific version strings and numbers
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#define BOOT_STRING  "sk98lin: Network Device Driver v10.22.3.1 (alpha)\n" \
+                     "(C)Copyright 1999-2007 Marvell(R)."
+#define VER_STRING   "10.22.3.1 (alpha)"
+#define PATCHLEVEL   "03"
+#define DRIVER_FILE_NAME   "sk98lin"
+#define DRIVER_REL_DATE    "Oct-15-2007"
+#define DRV_NAME   "sk98lin"
+#define DRV_VERSION   "10.22.3.1 (alpha)"
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
new file mode 100755
index 0000000..982721e
--- /dev/null
+++ b/drivers/net/sk98lin/h/skvpd.h
@@ -0,0 +1,282 @@
+/******************************************************************************
+ *
+ * Name:	skvpd.h
+ * Project:	Gigabit Ethernet Adapters, VPD-Module
+ * Version:	$Revision: 2.9 $
+ * Date:	$Date: 2007/05/04 12:55:17 $
+ * Purpose:	Defines and Macros for VPD handling
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2004 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ * skvpd.h	contains Diagnostic specific defines for VPD handling
+ */
+
+#ifndef __INC_SKVPD_H_
+#define __INC_SKVPD_H_
+
+/*
+ * Define Resource Type Identifiers and VPD keywords
+ */
+#define RES_ID		0x82	/* Resource Type ID String (Product Name) */
+#define RES_VPD_R	0x90	/* start of VPD read only area */
+#define RES_VPD_W	0x91	/* start of VPD read/write area */
+#define RES_END		0x78	/* Resource Type End Tag */
+
+#ifndef VPD_NAME
+#define VPD_NAME	"Name"	/* Product Name, VPD name of RES_ID */
+#endif	/* VPD_NAME */
+#define VPD_PN		"PN"	/* Adapter Part Number */
+#define VPD_EC		"EC"	/* Adapter Engineering Level */
+#define VPD_MN		"MN"	/* Manufacture ID */
+#define VPD_SN		"SN"	/* Serial Number */
+#define VPD_CP		"CP"	/* Extended Capability */
+#define VPD_RV		"RV"	/* Checksum and Reserved */
+#define VPD_YA		"YA"	/* Asset Tag Identifier */
+#define VPD_VL		"VL"	/* First Error Log Message (SK specific) */
+#define VPD_VF		"VF"	/* Second Error Log Message (SK specific) */
+#define VPD_VB		"VB"	/* Boot Agent ROM Configuration (SK specific) */
+#define VPD_VE		"VE"	/* EFI UNDI Configuration (SK specific) */
+#define VPD_RW		"RW"	/* Remaining Read / Write Area */
+
+/* 'type' values for vpd_setup_para() */
+#define VPD_RO_KEY	1	/* RO keys are "PN", "EC", "MN", "SN", "RV" */
+#define VPD_RW_KEY	2	/* RW keys are "Yx", "Vx", and "RW" */
+
+/* 'op' values for vpd_setup_para() */
+#define ADD_KEY		1	/* add the key at the pos "RV" or "RW" */
+#define OWR_KEY		2	/* overwrite key if already exists */
+
+/*
+ * Define READ and WRITE Constants.
+ */
+
+#define VPD_DEV_ID_GENESIS 	0x4300
+
+#define VPD_SIZE_YUKON		256
+#define VPD_SIZE_GENESIS	512
+#define VPD_SIZE			512
+#define VPD_READ	0x0000
+#define VPD_WRITE	0x8000
+
+#define VPD_STOP(pAC,IoC)	VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
+
+#define VPD_GET_RES_LEN(p)	((unsigned int)\
+					(*(SK_U8 *)&(p)[1]) |\
+					((*(SK_U8 *)&(p)[2]) << 8))
+#define VPD_GET_VPD_LEN(p)	((unsigned int)(*(SK_U8 *)&(p)[2]))
+#define VPD_GET_VAL(p)		((char *)&(p)[3])
+
+#define VPD_MAX_LEN	50
+
+#define VPD_SPI_ADDR	0x1f700UL
+
+/* VPD status */
+	/* bit 7..1 reserved */
+#define VPD_VALID	(1<<0)	/* VPD data buffer, vpd_free_ro, */
+							/* and vpd_free_rw valid	 */
+
+/*
+ * VPD structs
+ */
+typedef	struct s_vpd_status {
+	unsigned short	Align01;			/* Alignment */
+	unsigned short	vpd_status;			/* VPD status, description see above */
+	int				vpd_free_ro;		/* unused bytes in read only area */
+	int				vpd_free_rw;		/* bytes available in read/write area */
+} SK_VPD_STATUS;
+
+typedef	struct s_vpd {
+	SK_VPD_STATUS	v;					/* VPD status structure */
+	char			vpd_buf[VPD_SIZE];	/* VPD buffer */
+	int				rom_size;			/* VPD ROM Size from PCI_OUR_REG_2 */
+	int				vpd_size;			/* saved VPD-size */
+	SK_BOOL			CfgInSpi;			/* config data is stored in SPI flash */
+} SK_VPD;
+
+typedef	struct s_vpd_para {
+	unsigned int	p_len;	/* parameter length */
+	char			*p_val;	/* points to the value */
+} SK_VPD_PARA;
+
+/*
+ * structure of Large Resource Type Identifiers
+ */
+
+/* was removed because of alignment problems */
+
+/*
+ * structure of VPD keywords
+ */
+typedef	struct s_vpd_key {
+	char			p_key[2];	/* 2 bytes ID string */
+	unsigned char	p_len;		/* 1 byte length */
+	char			p_val;		/* start of the value string */
+} SK_VPD_KEY;
+
+
+/*
+ * System specific VPD macros
+ */
+#ifndef SK_DIAG
+#ifndef VPD_DO_IO
+#define VPD_OUT8(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgByte(pAC,Addr,Val)
+#define VPD_OUT16(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgWord(pAC,Addr,Val)
+#define VPD_OUT32(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgDWord(pAC,Addr,Val)
+#define VPD_IN8(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgByte(pAC,Addr,pVal)
+#define VPD_IN16(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgWord(pAC,Addr,pVal)
+#define VPD_IN32(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgDWord(pAC,Addr,pVal)
+#else	/* VPD_DO_IO */
+#define VPD_OUT8(pAC,IoC,Addr,Val)	SK_OUT8(IoC,PCI_C(pAC,Addr),Val)
+#define VPD_OUT16(pAC,IoC,Addr,Val)	SK_OUT16(IoC,PCI_C(pAC,Addr),Val)
+#define VPD_OUT32(pAC,IoC,Addr,Val)	SK_OUT32(IoC,PCI_C(pAC,Addr),Val)
+#define VPD_IN8(pAC,IoC,Addr,pVal)	SK_IN8(IoC,PCI_C(pAC,Addr),pVal)
+#define VPD_IN16(pAC,IoC,Addr,pVal)	SK_IN16(IoC,PCI_C(pAC,Addr),pVal)
+#define VPD_IN32(pAC,IoC,Addr,pVal)	SK_IN32(IoC,PCI_C(pAC,Addr),pVal)
+#endif	/* VPD_DO_IO */
+#else	/* SK_DIAG */
+#define VPD_OUT8(pAC,Ioc,Addr,Val) {			\
+		if ((pAC)->DgT.DgUseCfgCycle)			\
+			SkPciWriteCfgByte(pAC,Addr,Val);	\
+		else									\
+			SK_OUT8(pAC,PCI_C(pAC,Addr),Val);	\
+		}
+#define VPD_OUT16(pAC,Ioc,Addr,Val) {			\
+		if ((pAC)->DgT.DgUseCfgCycle)			\
+			SkPciWriteCfgWord(pAC,Addr,Val);	\
+		else						\
+			SK_OUT16(pAC,PCI_C(pAC,Addr),Val);	\
+		}
+#define VPD_OUT32(pAC,Ioc,Addr,Val) {			\
+		if ((pAC)->DgT.DgUseCfgCycle)			\
+			SkPciWriteCfgDWord(pAC,Addr,Val);	\
+		else						\
+			SK_OUT32(pAC,PCI_C(pAC,Addr),Val);	\
+		}
+#define VPD_IN8(pAC,Ioc,Addr,pVal) {			\
+		if ((pAC)->DgT.DgUseCfgCycle)			\
+			SkPciReadCfgByte(pAC,Addr,pVal);	\
+		else						\
+			SK_IN8(pAC,PCI_C(pAC,Addr),pVal);	\
+		}
+#define VPD_IN16(pAC,Ioc,Addr,pVal) {			\
+		if ((pAC)->DgT.DgUseCfgCycle)			\
+			SkPciReadCfgWord(pAC,Addr,pVal);	\
+		else						\
+			SK_IN16(pAC,PCI_C(pAC,Addr),pVal);	\
+		}
+#define VPD_IN32(pAC,Ioc,Addr,pVal) {			\
+		if ((pAC)->DgT.DgUseCfgCycle)			\
+			SkPciReadCfgDWord(pAC,Addr,pVal);	\
+		else						\
+			SK_IN32(pAC,PCI_C(pAC,Addr),pVal);	\
+		}
+#endif /* SK_DIAG */
+
+/* function prototypes ********************************************************/
+
+#ifndef	SK_KR_PROTO
+#ifdef SK_DIAG
+extern SK_U32	VpdReadDWord(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	int			addr);
+#endif /* SK_DIAG */
+
+extern int	VpdSetupPara(
+	SK_AC		*pAC,
+	const char	*key,
+	const char	*buf,
+	int			len,
+	int			type,
+	int			op);
+
+extern SK_VPD_STATUS	*VpdStat(
+	SK_AC		*pAC,
+	SK_IOC		IoC);
+
+extern int	VpdKeys(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	char		*buf,
+	int			*len,
+	int			*elements);
+
+extern int	VpdRead(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	const char	*key,
+	char		*buf,
+	int			*len);
+
+extern SK_BOOL	VpdMayWrite(
+	char		*key);
+
+extern int	VpdWrite(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	const char	*key,
+	const char	*buf);
+
+extern int	VpdDelete(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	char		*key);
+
+extern int	VpdUpdate(
+	SK_AC		*pAC,
+	SK_IOC		IoC);
+
+extern void	VpdErrLog(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	char		*msg);
+
+int VpdInit(
+	SK_AC		*pAC,
+	SK_IOC		IoC);
+
+extern int	VpdReadBlock(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	char		*buf,
+	int			addr,
+	int			len);
+
+extern int	VpdWriteBlock(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	char		*buf,
+	int			addr,
+	int			len);
+
+#else	/* SK_KR_PROTO */
+extern SK_U32	VpdReadDWord();
+extern int	VpdSetupPara();
+extern SK_VPD_STATUS	*VpdStat();
+extern int	VpdKeys();
+extern int	VpdRead();
+extern SK_BOOL	VpdMayWrite();
+extern int	VpdWrite();
+extern int	VpdDelete();
+extern int	VpdUpdate();
+extern void	VpdErrLog();
+#endif	/* SK_KR_PROTO */
+
+#endif	/* __INC_SKVPD_H_ */
+
diff --git a/drivers/net/sk98lin/h/sky2le.h b/drivers/net/sk98lin/h/sky2le.h
new file mode 100755
index 0000000..6a26548
--- /dev/null
+++ b/drivers/net/sk98lin/h/sky2le.h
@@ -0,0 +1,973 @@
+/******************************************************************************
+ *
+ * Name:	sky2le.h
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 1.12 $
+ * Date:	$Date: 2007/03/20 08:44:20 $
+ * Purpose:	Common list element definitions and access macros.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 2002-2006 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef __INC_SKY2LE_H
+#define __INC_SKY2LE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+/* defines ********************************************************************/
+
+#define MIN_LEN_OF_LE_TAB	128
+#define MAX_LEN_OF_LE_TAB	4096
+#ifdef USE_POLLING_UNIT
+#define NUM_LE_POLLING_UNIT	2
+#endif
+#define MAX_FRAG_OVERHEAD	10
+
+/* Macro for aligning a given value */
+#define SK_ALIGN_SIZE(Value, Alignment, AlignedVal) {					\
+	(AlignedVal) = (((Value) + (Alignment) - 1) & (~((Alignment) - 1)));\
+}
+
+/******************************************************************************
+ *
+ * LE2DWord() - Converts the given Little Endian value to machine order value
+ *
+ * Description:
+ *	This function converts the Little Endian value received as an argument to
+ *	the machine order value.
+ *
+ * Returns:
+ *	The converted value
+ *
+ */
+
+#ifdef SK_LITTLE_ENDIAN
+
+#ifndef	SK_USE_REV_DESC
+#define LE2DWord(value)	(value)
+#else	/* SK_USE_REV_DESC */
+#define LE2DWord(value)					\
+	((((value)<<24L) & 0xff000000L) +	\
+	 (((value)<< 8L) & 0x00ff0000L) +	\
+	 (((value)>> 8L) & 0x0000ff00L) +	\
+	 (((value)>>24L) & 0x000000ffL))
+#endif	/* SK_USE_REV_DESC */
+
+#else	/* !SK_LITTLE_ENDIAN */
+
+#ifndef	SK_USE_REV_DESC
+#define LE2DWord(value)					\
+	((((value)<<24L) & 0xff000000L) +	\
+	 (((value)<< 8L) & 0x00ff0000L) +	\
+	 (((value)>> 8L) & 0x0000ff00L) +	\
+	 (((value)>>24L) & 0x000000ffL))
+#else	/* SK_USE_REV_DESC */
+#define LE2DWord(value)	(value)
+#endif	/* SK_USE_REV_DESC */
+
+#endif	/* !SK_LITTLE_ENDIAN */
+
+/******************************************************************************
+ *
+ * DWord2LE() - Converts the given value to a Little Endian value
+ *
+ * Description:
+ *	This function converts the value received as an argument to a Little Endian
+ *	value on Big Endian machines. If the machine running the code is Little
+ *	Endian, then no conversion is done.
+ *
+ * Returns:
+ *	The converted value
+ *
+ */
+
+#ifdef SK_LITTLE_ENDIAN
+
+#ifndef	SK_USE_REV_DESC
+#define DWord2LE(value) (value)
+#else	/* SK_USE_REV_DESC */
+#define DWord2LE(value)					\
+	((((value)<<24L) & 0xff000000L) +	\
+	 (((value)<< 8L) & 0x00ff0000L) +	\
+	 (((value)>> 8L) & 0x0000ff00L) +	\
+	 (((value)>>24L) & 0x000000ffL))
+#endif	/* SK_USE_REV_DESC */
+
+#else	/* !SK_LITTLE_ENDIAN */
+
+#ifndef	SK_USE_REV_DESC
+#define DWord2LE(value)					\
+	((((value)<<24L) & 0xff000000L) +	\
+	 (((value)<< 8L) & 0x00ff0000L) +	\
+	 (((value)>> 8L) & 0x0000ff00L) +	\
+	 (((value)>>24L) & 0x000000ffL))
+#else	/* SK_USE_REV_DESC */
+#define DWord2LE(value) (value)
+#endif	/* SK_USE_REV_DESC */
+#endif	/* !SK_LITTLE_ENDIAN */
+
+/******************************************************************************
+ *
+ * LE2Word() - Converts the given Little Endian value to machine order value
+ *
+ * Description:
+ *	This function converts the Little Endian value received as an argument to
+ *	the machine order value.
+ *
+ * Returns:
+ *	The converted value
+ *
+ */
+
+#ifdef SK_LITTLE_ENDIAN
+#ifndef	SK_USE_REV_DESC
+#define LE2Word(value) (value)
+#else	/* SK_USE_REV_DESC */
+#define LE2Word(value)				\
+	((((value)<< 8L) & 0xff00) +	\
+	 (((value)>> 8L) & 0x00ff))
+#endif	/* SK_USE_REV_DESC */
+
+#else	/* !SK_LITTLE_ENDIAN */
+#ifndef	SK_USE_REV_DESC
+#define LE2Word(value)				\
+	((((value)<< 8L) & 0xff00) +	\
+	 (((value)>> 8L) & 0x00ff))
+#else	/* SK_USE_REV_DESC */
+#define LE2Word(value) (value)
+#endif	/* SK_USE_REV_DESC */
+#endif	/* !SK_LITTLE_ENDIAN */
+
+/******************************************************************************
+ *
+ * Word2LE() - Converts the given value to a Little Endian value
+ *
+ * Description:
+ *	This function converts the value received as an argument to a Little Endian
+ *	value on Big Endian machines. If the machine running the code is Little
+ *	Endian, then no conversion is done.
+ *
+ * Returns:
+ *	The converted value
+ *
+ */
+
+#ifdef SK_LITTLE_ENDIAN
+#ifndef	SK_USE_REV_DESC
+#define Word2LE(value) (value)
+#else	/* SK_USE_REV_DESC */
+#define Word2LE(value)				\
+	((((value)<< 8L) & 0xff00) +	\
+	 (((value)>> 8L) & 0x00ff))
+#endif	/* SK_USE_REV_DESC */
+
+#else	/* !SK_LITTLE_ENDIAN */
+#ifndef	SK_USE_REV_DESC
+#define Word2LE(value)				\
+	((((value)<< 8L) & 0xff00) +	\
+	 (((value)>> 8L) & 0x00ff))
+#else	/* SK_USE_REV_DESC */
+#define Word2LE(value) (value)
+#endif	/* SK_USE_REV_DESC */
+#endif	/* !SK_LITTLE_ENDIAN */
+
+/******************************************************************************
+ *
+ * Transmit list element macros
+ *
+ */
+
+#define TXLE_SET_ADDR(pLE, Addr)	\
+	((pLE)->Tx.TxUn.BufAddr = DWord2LE(Addr))
+#define TXLE_SET_LSLEN(pLE, Len)	\
+	((pLE)->Tx.TxUn.LargeSend.Length = Word2LE(Len))
+#define TXLE_SET_STACS(pLE, Start)	\
+	((pLE)->Tx.TxUn.ChkSum.TxTcpSp = Word2LE(Start))
+#define TXLE_SET_WRICS(pLE, Write)	\
+	((pLE)->Tx.TxUn.ChkSum.TxTcpWp = Word2LE(Write))
+#define TXLE_SET_INICS(pLE, Ini)	((pLE)->Tx.Send.InitCsum = Word2LE(Ini))
+#define TXLE_SET_LEN(pLE, Len)		((pLE)->Tx.Send.BufLen = Word2LE(Len))
+#define TXLE_SET_VLAN(pLE, Vlan)	((pLE)->Tx.Send.VlanTag = Word2LE(Vlan))
+#define TXLE_SET_LCKCS(pLE, Lock)	((pLE)->Tx.ControlFlags = (Lock))
+#define TXLE_SET_CTRL(pLE, Ctrl)	((pLE)->Tx.ControlFlags = (Ctrl))
+#define TXLE_SET_OPC(pLE, Opc)		((pLE)->Tx.Opcode = (Opc))
+
+#define TXLE_GET_ADDR(pLE)		LE2DWord((pLE)->Tx.TxUn.BufAddr)
+#define TXLE_GET_LSLEN(pLE)		LE2Word((pLE)->Tx.TxUn.LargeSend.Length)
+#define TXLE_GET_STACS(pLE)		LE2Word((pLE)->Tx.TxUn.ChkSum.TxTcpSp)
+#define TXLE_GET_WRICS(pLE)		LE2Word((pLE)->Tx.TxUn.ChkSum.TxTcpWp)
+#define TXLE_GET_INICS(pLE)		LE2Word((pLE)->Tx.Send.InitCsum)
+#define TXLE_GET_LEN(pLE) 		LE2Word((pLE)->Tx.Send.BufLen)
+#define TXLE_GET_VLAN(pLE)		LE2Word((pLE)->Tx.Send.VlanTag)
+#define TXLE_GET_LCKCS(pLE)		((pLE)->Tx.ControlFlags)
+#define TXLE_GET_CTRL(pLE)		((pLE)->Tx.ControlFlags)
+#define TXLE_GET_OPC(pLE)		((pLE)->Tx.Opcode)
+
+	/* Yukon-Extreme only */
+#define TXLE_SET_LSOV2(pLE, Len)	\
+	((pLE)->Tx.TxUn.LsoV2Len = DWord2LE(Len))
+#define TXLE_SET_MSSVAL(pLE, Val)	\
+((pLE)->Tx.TxUn.Mss.TxMssVal = Word2LE(Val))
+
+#define TXLE_GET_LSOV2(pLE)		LE2DWord((pLE)->Tx.TxUn.LsoV2Len)
+#define TXLE_GET_MSSVAL(pLE)	LE2Word((pLE)->Tx.TxUn.Mss.TxMssVal)
+
+/******************************************************************************
+ *
+ * Receive list element macros
+ *
+ */
+
+#define RXLE_SET_ADDR(pLE, Addr)	\
+	((pLE)->Rx.RxUn.BufAddr = (SK_U32)DWord2LE(Addr))
+#define RXLE_SET_STACS2(pLE, Offs)	\
+	((pLE)->Rx.RxUn.ChkSum.RxTcpSp2 = Word2LE(Offs))
+#define RXLE_SET_STACS1(pLE, Offs)	\
+	((pLE)->Rx.RxUn.ChkSum.RxTcpSp1 = Word2LE(Offs))
+#define RXLE_SET_LEN(pLE, Len)		((pLE)->Rx.BufferLength = Word2LE(Len))
+#define RXLE_SET_CTRL(pLE, Ctrl)	((pLE)->Rx.ControlFlags = (Ctrl))
+#define RXLE_SET_OPC(pLE, Opc)		((pLE)->Rx.Opcode = (Opc))
+
+#define RXLE_GET_ADDR(pLE)		LE2DWord((pLE)->Rx.RxUn.BufAddr)
+#define RXLE_GET_STACS2(pLE)	LE2Word((pLE)->Rx.RxUn.ChkSum.RxTcpSp2)
+#define RXLE_GET_STACS1(pLE)	LE2Word((pLE)->Rx.RxUn.ChkSum.RxTcpSp1)
+#define RXLE_GET_LEN(pLE) 		LE2Word((pLE)->Rx.BufferLength)
+#define RXLE_GET_CTRL(pLE)		((pLE)->Rx.ControlFlags)
+#define RXLE_GET_OPC(pLE)		((pLE)->Rx.Opcode)
+
+/******************************************************************************
+ *
+ * Status list element macros
+ *
+ */
+
+#define STLE_SET_OPC(pLE, Opc)		((pLE)->St.Opcode = (Opc))
+
+#define STLE_GET_FRSTATUS(pLE)	LE2DWord((pLE)->St.StUn.StRxStatWord)
+#define STLE_GET_TIST(pLE)		LE2DWord((pLE)->St.StUn.StRxTimeStamp)
+#define STLE_GET_TCP1(pLE)		LE2Word((pLE)->St.StUn.StRxTCPCSum.RxTCPSum1)
+#define STLE_GET_TCP2(pLE)		LE2Word((pLE)->St.StUn.StRxTCPCSum.RxTCPSum2)
+#define STLE_GET_LEN(pLE)		LE2Word((pLE)->St.Stat.BufLen)
+#define STLE_GET_VLAN(pLE)		LE2Word((pLE)->St.Stat.VlanTag)
+#define STLE_GET_LINK(pLE)		((pLE)->St.Link)
+#define STLE_GET_OPC(pLE)		((pLE)->St.Opcode)
+#define STLE_GET_DONE_IDX(pLE,LowVal,HighVal) {			\
+	(LowVal) = LE2DWord((pLE)->St.StUn.StTxStatLow);	\
+	(HighVal) = LE2Word((pLE)->St.Stat.StTxStatHi);		\
+}
+
+#define STLE_GET_RSS(pLE)		LE2DWord((pLE)->St.StUn.StRxRssValue)
+#define STLE_GET_IPV6BIT(pLE)	((pLE)->St.Stat.Rss.FlagField & RSS_IPV6_FLAG)
+#define STLE_GET_IPBIT(pLE)		((pLE)->St.Stat.Rss.FlagField & RSS_IP_FLAG)
+#define STLE_GET_TCPBIT(pLE)	((pLE)->St.Stat.Rss.FlagField & RSS_TCP_FLAG)
+
+/* Yukon-Extreme only */
+#define STLE_GET_MX_STAT(pLE)	((pLE)->St.StUn.StMacSecWord)
+
+/* Yukon-Ext CSum Status defines (Rx Status, Link field) */
+#define CSS_GET_PORT(Link)			(Link & CSS_LINK_BIT)
+#define CSS_IS_IPV4(Link)			(Link & CSS_ISIPV4)
+#define CSS_IPV4_CSUM_OK(Link)		(Link & CSS_IPV4CSUMOK)
+#define CSS_IS_IPV6(Link)			(Link & CSS_ISIPV6)
+#define CSS_IS_IPFRAG(Link)			(Link & CSS_ISIPFRAG)
+#define CSS_IS_TCP(Link)			(Link & CSS_ISTCP)
+#define CSS_IS_UDP(Link)			(Link & CSS_ISUDP)
+#define CSS_TCPUDP_CSUM_OK(Link)	(Link & CSS_TCPUDPCSOK)
+
+/* always take both values as a parameter to avoid typos */
+#define STLE_GET_DONE_IDX_TXA1(LowVal,HighVal)			\
+	(((LowVal) & STLE_TXA1_MSKL) >> STLE_TXA1_SHIFTL)
+#define STLE_GET_DONE_IDX_TXS1(LowVal,HighVal)			\
+	((LowVal & STLE_TXS1_MSKL) >> STLE_TXS1_SHIFTL)
+#define STLE_GET_DONE_IDX_TXA2(LowVal,HighVal)			\
+	(((LowVal & STLE_TXA2_MSKL) >> STLE_TXA2_SHIFTL) +	\
+	((HighVal & STLE_TXA2_MSKH) << STLE_TXA2_SHIFTH))
+#define STLE_GET_DONE_IDX_TXS2(LowVal,HighVal)			\
+	((HighVal & STLE_TXS2_MSKH) >> STLE_TXS2_SHIFTH)
+
+
+#define SK_Y2_RXSTAT_CHECK_PKT(Len, RxStat, IsOk) {			\
+	(IsOk) = (((RxStat) & GMR_FS_RX_OK) != 0) &&			\
+			 (((RxStat) & GMR_FS_ANY_ERR) == 0);			\
+															\
+	if ((IsOk) && ((SK_U16)(((RxStat) & GMR_FS_LEN_MSK) >>	\
+		GMR_FS_LEN_SHIFT) != (Len))) {						\
+		/* length in MAC status differs from length in LE */\
+		(IsOk) = SK_FALSE;									\
+	}														\
+}
+
+
+/******************************************************************************
+ *
+ * Polling unit list element macros
+ *
+ * NOTE: the Idx must be <= 0xfff and PU_PUTIDX_VALID makes them valid
+ *
+ */
+
+#ifdef USE_POLLING_UNIT
+
+#define POLE_SET_OPC(pLE, Opc)		((pLE)->Sa.Opcode = (Opc))
+#define POLE_SET_LINK(pLE, Port)	((pLE)->Sa.Link = (Port))
+#define POLE_SET_RXIDX(pLE, Idx)	((pLE)->Sa.RxIdxVld = Word2LE(Idx))
+#define POLE_SET_TXAIDX(pLE, Idx)	((pLE)->Sa.TxAIdxVld = Word2LE(Idx))
+#define POLE_SET_TXSIDX(pLE, Idx)	((pLE)->Sa.TxSIdxVld = Word2LE(Idx))
+
+#define POLE_GET_OPC(pLE)		((pLE)->Sa.Opcode)
+#define POLE_GET_LINK(pLE)		((pLE)->Sa.Link)
+#define POLE_GET_RXIDX(pLE)		LE2Word((pLE)->Sa.RxIdxVld)
+#define POLE_GET_TXAIDX(pLE)	LE2Word((pLE)->Sa.TxAIdxVld)
+#define POLE_GET_TXSIDX(pLE)	LE2Word((pLE)->Sa.TxSIdxVld)
+
+#endif	/* USE_POLLING_UNIT */
+
+/******************************************************************************
+ *
+ * Debug macros for list elements
+ *
+ */
+
+#ifdef DEBUG
+
+#define SK_DBG_DUMP_RX_LE(pLE)	{										\
+	SK_U8	Opcode;														\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("=== RX_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n",	\
+		pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
+		((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5],		\
+		((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); 						\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\t (16bit) %04x %04x %04x %04x\n",							\
+		((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2],	\
+		((SK_U16 *) pLE)[3])); 											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\t (32bit) %08x %08x\n",										\
+		((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); 					\
+	Opcode = RXLE_GET_OPC(pLE);											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ?	\
+		 "Hardware" : "Software"));										\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tOpc: 0x%x ",Opcode));										\
+	switch (Opcode & (~HW_OWNER)) {										\
+	case OP_BUFFER:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_BUFFER\n"));											\
+		break;															\
+	case OP_PACKET:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_PACKET\n"));											\
+		break;															\
+	case OP_ADDR64:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_ADDR64\n"));											\
+		break;															\
+	case OP_TCPSTART:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_TCPPAR\n"));											\
+		break;															\
+	case SW_OWNER:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tunused LE\n"));											\
+		break;															\
+	default:															\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tunknown Opcode!!!\n"));									\
+	}																	\
+	if ((Opcode & OP_BUFFER) == OP_BUFFER) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tControl: 0x%x\n", RXLE_GET_CTRL(pLE)));					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tBufLen: 0x%x\n", RXLE_GET_LEN(pLE)));					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tLowAddr: 0x%x\n", RXLE_GET_ADDR(pLE)));					\
+	}																	\
+	if ((Opcode & OP_ADDR64) == OP_ADDR64) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tHighAddr: 0x%x\n", RXLE_GET_ADDR(pLE)));				\
+	}																	\
+	if ((Opcode & OP_TCPSTART) == OP_TCPSTART) {						\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tTCP Sum Start 1 : 0x%x\n", RXLE_GET_STACS1(pLE)));		\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tTCP Sum Start 2 : 0x%x\n", RXLE_GET_STACS2(pLE)));		\
+	}																	\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("=====================\n"));									\
+}
+
+#define SK_DBG_DUMP_TX_LE(pLE)	{										\
+	SK_U8	Opcode;														\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("=== TX_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n",	\
+		pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
+		((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5],		\
+		((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); 						\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\t (16bit) %04x %04x %04x %04x\n",							\
+		((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2],	\
+		((SK_U16 *) pLE)[3])); 											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\t (32bit) %08x %08x\n",										\
+		((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); 					\
+	Opcode = TXLE_GET_OPC(pLE);											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ?	\
+		"Hardware" : "Software"));										\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tOpc: 0x%x ",Opcode));										\
+	switch (Opcode & (~HW_OWNER)) {										\
+	case OP_TCPCHKSUM:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_TCPCHKSUM\n"));										\
+		break;															\
+	case OP_TCPIS:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_TCPIS\n"));											\
+		break;															\
+	case OP_TCPLCK:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_TCPLCK\n"));											\
+		break;															\
+	case OP_TCPLW:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_TCPLW\n"));											\
+		break;															\
+	case OP_TCPLSW:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_TCPLSW\n"));											\
+		break;															\
+	case OP_TCPLISW:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_TCPLISW\n"));										\
+		break;															\
+	case OP_ADDR64:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_ADDR64\n"));											\
+		break;															\
+	case OP_VLAN:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_VLAN\n"));											\
+		break;															\
+	case OP_ADDR64VLAN:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_ADDR64VLAN\n"));										\
+		break;															\
+	case OP_LRGLEN:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_LRGLEN\n"));											\
+		break;															\
+	case OP_LRGLENVLAN:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_LRGLENVLAN\n"));										\
+		break;															\
+	case OP_BUFFER:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_BUFFER\n"));											\
+		break;															\
+	case OP_PACKET:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_PACKET\n"));											\
+		break;															\
+	case OP_LARGESEND:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_LARGESEND\n"));										\
+		break;															\
+	case OP_MSS:		/* Yukon-Extreme only */						\
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_MSS\n"))												\
+		break;															\
+	case OP_MSSVLAN:	/* Yukon-Extreme only */						\
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, 					\
+			("\tOP_MSSVLAN\n"))											\
+		break;															\
+	case OP_LSOV2:		/* Yukon-Extreme only */						\
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_LSOV2\n"))											\
+		break;															\
+	case SW_OWNER:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tunused LE\n"));											\
+		break;															\
+	default:															\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tunknown Opcode!!!\n"));									\
+	}																	\
+	if ((Opcode & OP_BUFFER) == OP_BUFFER) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tControl: 0x%x\n", TXLE_GET_CTRL(pLE)));					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tBufLen: 0x%x\n", TXLE_GET_LEN(pLE)));					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tLowAddr: 0x%x\n", TXLE_GET_ADDR(pLE)));					\
+	}																	\
+	if ((Opcode & OP_ADDR64) == OP_ADDR64) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tHighAddr: 0x%x\n", TXLE_GET_ADDR(pLE)));				\
+	}																	\
+	if ((Opcode & OP_VLAN) == OP_VLAN) {								\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tVLAN Id: 0x%x\n", TXLE_GET_VLAN(pLE)));					\
+	}																	\
+	if ((Opcode & OP_LRGLEN) == OP_LRGLEN) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tLarge send length: 0x%x\n", TXLE_GET_LSLEN(pLE)));		\
+	}																	\
+	if ((Opcode & OP_MSS) == OP_MSS) {		/* Yukon-Extreme only */	\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tMSS value: 0x%x\n", TXLE_GET_MSSVAL(pLE)));				\
+	}																	\
+	if ((Opcode & OP_LSOV2) == OP_LSOV2) {	/* Yukon-Extreme only */	\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tLSOv2 lenght: 0x%x\n", TXLE_GET_LSOV2(pLE)));			\
+	}																	\
+	if ((Opcode &(~HW_OWNER)) <= OP_ADDR64) {							\
+		if ((Opcode & OP_TCPWRITE) == OP_TCPWRITE) {					\
+			SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,				\
+				("\tTCP Sum Write: 0x%x\n", TXLE_GET_WRICS(pLE)));		\
+		}																\
+		if ((Opcode & OP_TCPSTART) == OP_TCPSTART) {					\
+			SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,				\
+				("\tTCP Sum Start: 0x%x\n", TXLE_GET_STACS(pLE)));		\
+		}																\
+		if ((Opcode & OP_TCPINIT) == OP_TCPINIT) {						\
+			SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,				\
+				("\tTCP Sum Init: 0x%x\n", TXLE_GET_INICS(pLE)));		\
+		}																\
+		if ((Opcode & OP_TCPLCK) == OP_TCPLCK) {						\
+			SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,				\
+				("\tTCP Sum Lock: 0x%x\n", TXLE_GET_LCKCS(pLE)));		\
+		}																\
+	}																	\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("=====================\n"));									\
+}
+	
+#define SK_DBG_DUMP_ST_LE(pLE)	{ 										\
+	SK_U8	Opcode;														\
+	SK_U16	HighVal;													\
+	SK_U32	LowVal;														\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("=== ST_LIST_ELEMENT @addr: %p contains: %02x %02x %02x %02x %02x %02x %02x %02x\n",\
+		pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
+		((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5],		\
+		((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7]));						\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\t (16bit) %04x %04x %04x %04x\n",							\
+		((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2],	\
+		((SK_U16 *) pLE)[3])); 											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\t (32bit) %08x %08x\n",										\
+		((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1]));						\
+	Opcode = STLE_GET_OPC(pLE);											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == SW_OWNER) ?	\
+		"Hardware" : "Software"));										\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tOpc: 0x%x",	Opcode));										\
+	Opcode &= (~HW_OWNER);												\
+	switch (Opcode) {													\
+	case OP_RXSTAT:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_RXSTAT\n"));											\
+		break;															\
+	case OP_RXTIMESTAMP:												\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_RXTIMESTAMP\n"));									\
+		break;															\
+	case OP_RXVLAN:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_RXVLAN\n"));											\
+		break;															\
+	case OP_RXCHKS:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_RXCHKS\n"));											\
+		break;															\
+	case OP_RXCHKSVLAN:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_RXCHKSVLAN\n"));										\
+		break;															\
+	case OP_RXTIMEVLAN:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_RXTIMEVLAN\n"));										\
+		break;															\
+	case OP_RSS_HASH:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_RSS_HASH\n"));										\
+		break;															\
+	case OP_TXINDEXLE:													\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_TXINDEXLE\n"));										\
+		break;															\
+	case OP_MACSEC:		/* Yukon-Exteme only */							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_MACSEC\n"));											\
+		break;															\
+	case OP_MACSECVLAN:	/* Yukon-Exteme only */							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_MACSECVLAN\n"));										\
+		break;															\
+	case HW_OWNER:														\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tunused LE\n"));											\
+		break;															\
+	default:															\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tunknown status list element!!!\n"));					\
+	}																	\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tPort: %c\n", 'A' + (CSS_GET_PORT(STLE_GET_LINK(pLE)))));	\
+	if (Opcode == OP_RXSTAT) {											\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tFrameLen: 0x%x\n", STLE_GET_LEN(pLE)));					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tFrameStat: 0x%x\n", STLE_GET_FRSTATUS(pLE)));			\
+		if (HW_IS_EXT_LE_FORMAT(pAc)) {									\
+			SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,				\
+				("\tChecksum Status Field: 0x%x\n", STLE_GET_LINK(pLE)));\
+		}																\
+	}																	\
+	if ((Opcode & OP_RXVLAN) == OP_RXVLAN) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tVLAN Id: 0x%x\n", STLE_GET_VLAN(pLE)));					\
+	}																	\
+	if ((Opcode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) {					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tTimestamp: 0x%x\n", STLE_GET_TIST(pLE)));				\
+	}																	\
+	if ((Opcode & OP_RXCHKS) == OP_RXCHKS) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tTCP: 0x%x 0x%x\n", STLE_GET_TCP1(pLE),					\
+			STLE_GET_TCP2(pLE)));										\
+	}																	\
+	if (Opcode == OP_TXINDEXLE) {										\
+		STLE_GET_DONE_IDX(pLE, LowVal, HighVal);						\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tTx Index TxA1: 0x%x\n",									\
+			STLE_GET_DONE_IDX_TXA1(LowVal,HighVal)));					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tTx Index TxS1: 0x%x\n",									\
+			STLE_GET_DONE_IDX_TXS1(LowVal,HighVal)));					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tTx Index TxA2: 0x%x\n",									\
+			STLE_GET_DONE_IDX_TXA2(LowVal,HighVal)));					\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tTx Index TxS2: 0x%x\n",									\
+			STLE_GET_DONE_IDX_TXS2(LowVal,HighVal)));					\
+	}																	\
+	if ((Opcode & OP_MACSEC) == OP_MACSEC) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tMACSec Status Field\n", STLE_GET_MX_STAT(pLE)));		\
+	}																	\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("=====================\n"));									\
+}
+
+#ifdef USE_POLLING_UNIT
+#define SK_DBG_DUMP_PO_LE(pLE)	{										\
+	SK_U8	Opcode;														\
+	SK_U16	Idx;														\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("=== PO_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n",	\
+		pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
+		((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5],		\
+		((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7]));						\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\t (16bit) %04x %04x %04x %04x\n",							\
+		((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2],	\
+		((SK_U16 *) pLE)[3])); 											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\t (32bit) %08x %08x\n",										\
+		((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1]));						\
+	Opcode = POLE_GET_OPC(pLE);											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		 ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ?	\
+		  "Hardware" : "Software"));									\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		 ("\tOpc: 0x%x ",Opcode));										\
+	if ((Opcode & ~HW_OWNER) == OP_PUTIDX) {							\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tOP_PUTIDX\n"));											\
+	}																	\
+	else {																\
+		SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,					\
+			("\tunknown Opcode!!!\n"));									\
+	}																	\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tPort %c\n", 'A' + POLE_GET_LINK(pLE)));						\
+	Idx = POLE_GET_TXAIDX(pLE);											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tTxA Index is 0x%X and %svalid\n", Idx,						\
+		(Idx & PU_PUTIDX_VALID) ? "" : "not "));						\
+	Idx = POLE_GET_TXSIDX(pLE);											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tTxS Index is 0x%X and %svalid\n", Idx,						\
+		(Idx & PU_PUTIDX_VALID) ? "" : "not "));						\
+	Idx = POLE_GET_RXIDX(pLE);											\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("\tRx Index is 0x%X and %svalid\n", Idx,						\
+		(Idx & PU_PUTIDX_VALID) ? "" : "not "));						\
+	SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT,						\
+		("=====================\n"));									\
+}
+#endif	/* USE_POLLING_UNIT */
+
+#else	/* !DEBUG */
+
+#define SK_DBG_DUMP_RX_LE(pLE)
+#define SK_DBG_DUMP_TX_LE(pLE)
+#define SK_DBG_DUMP_ST_LE(pLE)
+#define SK_DBG_DUMP_PO_LE(pLE)
+
+#endif	/* !DEBUG */
+
+/******************************************************************************
+ *
+ * Macros for listelement tables
+ *
+ *
+ */
+
+#define LE_SIZE sizeof(SK_HWLE)
+#define LE_TAB_SIZE(NumElements)	((NumElements) * LE_SIZE)
+
+/* Number of unused list elements in table
+ * this macro always returns the number of free listelements - 1
+ * this way we want to guarantee that always one LE remains unused
+ */
+#define NUM_FREE_LE_IN_TABLE(pTable)								\
+	( ((pTable)->Put >= (pTable)->Done) ?							\
+	(NUM_LE_IN_TABLE(pTable) - (pTable)->Put + (pTable)->Done - 1) :\
+	((pTable)->Done - (pTable)->Put - 1) )
+
+/* total number of list elements in table */
+#define NUM_LE_IN_TABLE(pTable)		((pTable)->Num)
+
+/* get next unused Rx list element */
+#define GET_RX_LE(pLE, pTable) {									\
+	pLE = &(pTable)->pLETab[(pTable)->Put];							\
+	(pTable)->Put = ((pTable)->Put + 1) & (NUM_LE_IN_TABLE(pTable) - 1);\
+}
+
+/* get next unused Tx list element */
+#define GET_TX_LE(pLE, pTable)	GET_RX_LE(pLE, pTable)
+
+/* get next status list element expected to be finished by hw */
+#define GET_ST_LE(pLE, pTable) {									\
+	pLE = &(pTable)->pLETab[(pTable)->Done];						\
+		(pTable)->Done = ((pTable)->Done +1) & (NUM_LE_IN_TABLE(pTable) - 1);\
+}
+
+#ifdef USE_POLLING_UNIT
+/* get next polling unit list element for port */
+#define GET_PO_LE(pLE, pTable, Port) {								\
+	pLE = &(pTable)->pLETab[(Port)];								\
+}
+#endif	/* USE_POLLING_UNIT */
+
+#define GET_PUT_IDX(pTable)			((pTable)->Put)
+
+#define UPDATE_HWPUT_IDX(pTable)	{(pTable)->HwPut = (pTable)->Put; }
+
+/*
+ * get own bit of next status LE
+ * if the result is != 0 there has been at least one status LE finished
+ */
+#define OWN_OF_FIRST_LE(pTable)									\
+	(STLE_GET_OPC(&(pTable)->pLETab[(pTable)->Done]) & HW_OWNER)
+
+#define SET_DONE_INDEX(pTable, Idx)	(pTable)->Done = (Idx);
+
+#define GET_DONE_INDEX(pTable)	((pTable)->Done)
+
+#ifdef SAFE_BUT_SLOW
+
+/* check own bit of LE before current done idx */
+#define CHECK_STLE_OVERFLOW(pTable, IsOk) {						\
+		unsigned i;												\
+		if ((i = (pTable)->Done) == 0) {						\
+			i = NUM_LE_IN_TABLE(pTable);						\
+		}														\
+		else {													\
+			i = i - 1;											\
+		}														\
+		if (STLE_GET_OPC(&(pTable)->pLETab[i]) == HW_OWNER) {	\
+			(IsOk) = SK_TRUE;									\
+		}														\
+		else {													\
+			(IsOk) = SK_FALSE;									\
+		}														\
+	}
+
+
+/*
+ * for Yukon-2 the hardware is not polling the list elements, so it
+ * is not necessary to change the own-bit of Rx or Tx LEs before
+ * reusing them
+ * but it might make debugging easier if one simply can see whether
+ * a LE has been worked on
+ */
+
+#define CLEAR_LE_OWN(pTable, Idx)								\
+	STLE_SET_OPC(&(pTable)->pLETab[(Idx)], SW_OWNER)
+
+/*
+ * clear all own bits starting from old done index up to the LE before
+ * the new done index
+ */
+#define CLEAR_LE_OWN_FROM_DONE_TO(pTable, To) {					\
+		int i;													\
+		i = (pTable)->Done;										\
+		while (i != To) {										\
+			CLEAR_LE_OWN(pTable, i);							\
+			i = (i + 1) & (NUM_LE_IN_TABLE(pTable) - 1);		\
+		}														\
+	}
+
+#else	/* !SAFE_BUT_SLOW */
+
+#define CHECK_STLE_OVERFLOW(pTable, IsOk)
+#define CLEAR_LE_OWN(pTable, Idx)
+#define CLEAR_LE_OWN_FROM_DONE_TO(pTable, To)
+
+#endif	/* !SAFE_BUT_SLOW */
+
+
+/* typedefs *******************************************************************/
+
+typedef struct s_LetRxTx {
+	SK_U16	VlanId;			/* VLAN Id given down last time */
+	SK_U16	TcpWp;			/* TCP Checksum Write Position */
+	SK_U16	TcpSp1;			/* TCP Checksum Calculation Start Position 1 */
+	SK_U16	TcpSp2;			/* TCP Checksum Calculation Start Position 2 */
+	SK_U16	MssValue;		/* Maximum Segment Size */
+	SK_U16	Reserved1;		/* reserved word for furture extensions */
+	SK_U16	Reserved2;		/* reserved word for furture extensions */
+	SK_U16	Reserved3;		/* reserved word for furture extensions */
+} SK_LET_RX_TX;
+
+typedef struct s_LetStat {
+	SK_U32	RxTimeStamp;	/* Receive Timestamp */
+	SK_U32	RssHashValue;	/* RSS Hash Value */
+	SK_BOOL	RssIsIpV6;		/* RSS Hash Value: IPv6 packet detected */
+	SK_BOOL	RssIsIp;		/* RSS Hash Value: IP packet detected */
+	SK_BOOL	RssIsTcp;		/* RSS Hash Value: IP+TCP packet detected */
+	SK_BOOL	CalcHashIpV4;	/* RSS is computed over source IPv4 address */
+							/* and destination IPv4 address */
+	SK_BOOL	CalcHashTCPIPv4;/* RSS is computed over source IPv4 address, */
+							/* destination IPv4 address, source TCP port and */
+							/* destination TCP port */
+	SK_BOOL	CalcHashIPv6;	/* RSS is computed over source IPv6 address */
+							/* and destination IPv6 address */
+	SK_BOOL	CalcHashTCPIPv6;/* RSS is computed over source IPv6 address, */
+							/* destination IPv6 address, source TCP port and */ 
+							/* destination TCP port */
+	SK_BOOL	CalcHashIPv6Ex;	/* RSS is computed over home address (if not present,*/ 
+							/* source IPv6 address is used) and routing header	*/
+							/* type 2 (if not present, destination IPv6 address*/
+							/* is used) */
+	SK_BOOL	CalcHashTCPIPv6Ex;	/* RS is computed over home address (if not */
+							/* present, source IPv6 address is used) and routing */
+							/* header type 2 (if not present, destination IPv6 */
+							/* address is used), source TCP port and destiantion*/
+							/* TCP port */
+	SK_U16	VlanId;			/* VLAN Id given received by Status BMU */
+	SK_U16	TcpSum1;		/* TCP checksum 1 (status BMU) */
+	SK_U16	TcpSum2;		/* TCP checksum 2 (status BMU) */
+	SK_U32	MacSecStatus;	/* MAC Security status for packet */
+} SK_LET_STAT;
+
+typedef union s_LetBmuSpec {
+	SK_LET_RX_TX	RxTx;	/* Rx/Tx BMU specific variables */
+	SK_LET_STAT		Stat;	/* Status BMU specific variables */
+} SK_LET_BMU_S;
+
+typedef	struct s_le_table {
+	/* all LE's between Done and HWPut are owned by the hardware */
+	/* all LE's between Put and Done can be used from software */
+	/* all LE's between HWPut and Put are currently processed in DriverSend */
+	unsigned Done;			/* done index - consumed from HW and available */
+	unsigned Put;			/* put index - to be given to hardware */
+	unsigned HwPut;			/* put index actually given to hardware */
+	unsigned Num;			/* total number of list elements */
+	SK_HWLE *pLETab;		/* virtual address of list element table */
+	SK_U32	pPhyLETABLow;	/* physical address of list element table */
+	SK_U32	pPhyLETABHigh;	/* physical address of list element table */
+	/* values to remember in order to save some LEs */
+	SK_U32	BufHighAddr;	/* high address given down last time */
+	SK_LET_BMU_S Bmu;		/* contains BMU specific information */
+	SK_U32	Private;		/* driver private variable free usable */
+	SK_U16	TcpInitCsum;	/* init checksum */
+#if defined(SK_LSO_V2) && defined(SK_EXTREME)
+	unsigned DoneCorrection;	/* number of LSOv2 LEs send modulo Num */
+	unsigned BadDone;			/* real done index from HW - in Done is a corrected value */
+#endif
+} SK_LE_TABLE;
+
+/* function prototypes ********************************************************/
+
+#ifndef	SK_KR_PROTO
+
+/*
+ * public functions in sky2le.c
+ */
+extern void SkGeY2SetPutIndex(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	StartAddrPrefetchUnit,
+	SK_LE_TABLE *pLETab);
+
+extern void SkGeY2InitPrefetchUnit(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	unsigned int Queue,
+	SK_LE_TABLE *pLETab);
+
+extern void SkGeY2InitStatBmu(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_LE_TABLE *pLETab);
+
+extern void SkGeY2InitPollUnit(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_LE_TABLE *pLETab);
+
+extern void SkGeY2InitSingleLETable(
+	SK_AC	*pAC,
+	SK_LE_TABLE *pLETab,
+	unsigned int NumLE,
+	void	*pVMem,
+	SK_U32	PMemLowAddr,
+	SK_U32	PMemHighAddr);
+
+#else	/* SK_KR_PROTO */
+extern void SkGeY2SetPutIndex();
+extern void SkGeY2InitPrefetchUnit();
+extern void SkGeY2InitStatBmu();
+extern void SkGeY2InitPollUnit();
+extern void SkGeY2InitSingleLETable();
+#endif	/* SK_KR_PROTO */
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif	/* __INC_SKY2LE_H */
+
diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
new file mode 100755
index 0000000..ac5cb28
--- /dev/null
+++ b/drivers/net/sk98lin/h/xmac_ii.h
@@ -0,0 +1,1805 @@
+/******************************************************************************
+ *
+ * Name:	xmac_ii.h
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.17 $
+ * Date:	$Date: 2007/06/27 13:31:08 $
+ * Purpose:	Defines and Macros for Gigabit Ethernet Controller
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifndef __INC_XMAC_H
+#define __INC_XMAC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+/* defines ********************************************************************/
+
+/*
+ * XMAC II registers
+ *
+ * The XMAC registers are 16 or 32 bits wide.
+ * The XMACs host processor interface is set to 16 bit mode,
+ * therefore ALL registers will be addressed with 16 bit accesses.
+ *
+ * The following macros are provided to access the XMAC registers
+ * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(),
+ * XM_INHASH(), and XM_OUTHASH().
+ * The macros are defined in SkGeHw.h.
+ *
+ * Note:	NA reg	= Network Address e.g DA, SA etc.
+ *
+ */
+#define XM_MMU_CMD		0x0000	/* 16 bit r/w	MMU Command Register */
+	/* 0x0004:		reserved */
+#define XM_POFF			0x0008	/* 32 bit r/w	Packet Offset Register */
+#define XM_BURST		0x000c	/* 32 bit r/w	Burst Register for half duplex*/
+#define XM_1L_VLAN_TAG	0x0010	/* 16 bit r/w	One Level VLAN Tag ID */
+#define XM_2L_VLAN_TAG	0x0014	/* 16 bit r/w	Two Level VLAN Tag ID */
+	/* 0x0018 - 0x001e:	reserved */
+#define XM_TX_CMD		0x0020	/* 16 bit r/w	Transmit Command Register */
+#define XM_TX_RT_LIM	0x0024	/* 16 bit r/w	Transmit Retry Limit Register */
+#define XM_TX_STIME		0x0028	/* 16 bit r/w	Transmit Slottime Register */
+#define XM_TX_IPG		0x002c	/* 16 bit r/w	Transmit Inter Packet Gap */
+#define XM_RX_CMD		0x0030	/* 16 bit r/w	Receive Command Register */
+#define XM_PHY_ADDR		0x0034	/* 16 bit r/w	PHY Address Register */
+#define XM_PHY_DATA		0x0038	/* 16 bit r/w	PHY Data Register */
+	/* 0x003c: 		reserved */
+#define XM_GP_PORT		0x0040	/* 32 bit r/w	General Purpose Port Register */
+#define XM_IMSK			0x0044	/* 16 bit r/w	Interrupt Mask Register */
+#define XM_ISRC			0x0048	/* 16 bit r/o	Interrupt Status Register */
+#define XM_HW_CFG		0x004c	/* 16 bit r/w	Hardware Config Register */
+	/* 0x0050 - 0x005e:	reserved */
+#define XM_TX_LO_WM		0x0060	/* 16 bit r/w	Tx FIFO Low Water Mark */
+#define XM_TX_HI_WM		0x0062	/* 16 bit r/w	Tx FIFO High Water Mark */
+#define XM_TX_THR		0x0064	/* 16 bit r/w	Tx Request Threshold */
+#define XM_HT_THR		0x0066	/* 16 bit r/w	Host Request Threshold */
+#define XM_PAUSE_DA		0x0068	/* NA reg r/w	Pause Destination Address */
+	/* 0x006e: 		reserved */
+#define XM_CTL_PARA		0x0070	/* 32 bit r/w	Control Parameter Register */
+#define XM_MAC_OPCODE	0x0074	/* 16 bit r/w	Opcode for MAC control frames */
+#define XM_MAC_PTIME	0x0076	/* 16 bit r/w	Pause time for MAC ctrl frames*/
+#define XM_TX_STAT		0x0078	/* 32 bit r/o	Tx Status LIFO Register */
+
+	/* 0x0080 - 0x00fc:	16 NA reg r/w	Exact Match Address Registers */
+	/* 				use the XM_EXM() macro to address */
+#define XM_EXM_START	0x0080	/* r/w	Start Address of the EXM Regs */
+
+	/*
+	 * XM_EXM(Reg)
+	 *
+	 * returns the XMAC address offset of specified Exact Match Addr Reg
+	 *
+	 * para:	Reg	EXM register to addr	(0 .. 15)
+	 *
+	 * usage:	XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]);
+	 */
+#define XM_EXM(Reg)	(XM_EXM_START + ((Reg) << 3))
+
+#define XM_SRC_CHK		0x0100	/* NA reg r/w	Source Check Address Register */
+#define XM_SA			0x0108	/* NA reg r/w	Station Address Register */
+#define XM_HSM			0x0110	/* 64 bit r/w	Hash Match Address Registers */
+#define XM_RX_LO_WM		0x0118	/* 16 bit r/w	Receive Low Water Mark */
+#define XM_RX_HI_WM		0x011a	/* 16 bit r/w	Receive High Water Mark */
+#define XM_RX_THR		0x011c	/* 32 bit r/w	Receive Request Threshold */
+#define XM_DEV_ID		0x0120	/* 32 bit r/o	Device ID Register */
+#define XM_MODE			0x0124	/* 32 bit r/w	Mode Register */
+#define XM_LSA			0x0128	/* NA reg r/o	Last Source Register */
+	/* 0x012e:		reserved */
+#define XM_TS_READ		0x0130	/* 32 bit r/o	Time Stamp Read Register */
+#define XM_TS_LOAD		0x0134	/* 32 bit r/o	Time Stamp Load Value */
+	/* 0x0138 - 0x01fe:	reserved */
+#define XM_STAT_CMD	0x0200	/* 16 bit r/w	Statistics Command Register */
+#define XM_RX_CNT_EV	0x0204	/* 32 bit r/o	Rx Counter Event Register */
+#define XM_TX_CNT_EV	0x0208	/* 32 bit r/o	Tx Counter Event Register */
+#define XM_RX_EV_MSK	0x020c	/* 32 bit r/w	Rx Counter Event Mask */
+#define XM_TX_EV_MSK	0x0210	/* 32 bit r/w	Tx Counter Event Mask */
+	/* 0x0204 - 0x027e:	reserved */
+#define XM_TXF_OK		0x0280	/* 32 bit r/o	Frames Transmitted OK Conuter */
+#define XM_TXO_OK_HI	0x0284	/* 32 bit r/o	Octets Transmitted OK High Cnt*/
+#define XM_TXO_OK_LO	0x0288	/* 32 bit r/o	Octets Transmitted OK Low Cnt */
+#define XM_TXF_BC_OK	0x028c	/* 32 bit r/o	Broadcast Frames Xmitted OK */
+#define XM_TXF_MC_OK	0x0290	/* 32 bit r/o	Multicast Frames Xmitted OK */
+#define XM_TXF_UC_OK	0x0294	/* 32 bit r/o	Unicast Frames Xmitted OK */
+#define XM_TXF_LONG		0x0298	/* 32 bit r/o	Tx Long Frame Counter */
+#define XM_TXE_BURST	0x029c	/* 32 bit r/o	Tx Burst Event Counter */
+#define XM_TXF_MPAUSE	0x02a0	/* 32 bit r/o	Tx Pause MAC Ctrl Frame Cnt */
+#define XM_TXF_MCTRL	0x02a4	/* 32 bit r/o	Tx MAC Ctrl Frame Counter */
+#define XM_TXF_SNG_COL	0x02a8	/* 32 bit r/o	Tx Single Collision Counter */
+#define XM_TXF_MUL_COL	0x02ac	/* 32 bit r/o	Tx Multiple Collision Counter */
+#define XM_TXF_ABO_COL	0x02b0	/* 32 bit r/o	Tx aborted due to Exces. Col. */
+#define XM_TXF_LAT_COL	0x02b4	/* 32 bit r/o	Tx Late Collision Counter */
+#define XM_TXF_DEF		0x02b8	/* 32 bit r/o	Tx Deferred Frame Counter */
+#define XM_TXF_EX_DEF	0x02bc	/* 32 bit r/o	Tx Excessive Deferall Counter */
+#define XM_TXE_FIFO_UR	0x02c0	/* 32 bit r/o	Tx FIFO Underrun Event Cnt */
+#define XM_TXE_CS_ERR	0x02c4	/* 32 bit r/o	Tx Carrier Sense Error Cnt */
+#define XM_TXP_UTIL		0x02c8	/* 32 bit r/o	Tx Utilization in % */
+	/* 0x02cc - 0x02ce:	reserved */
+#define XM_TXF_64B		0x02d0	/* 32 bit r/o	64 Byte Tx Frame Counter */
+#define XM_TXF_127B		0x02d4	/* 32 bit r/o	65-127 Byte Tx Frame Counter */
+#define XM_TXF_255B		0x02d8	/* 32 bit r/o	128-255 Byte Tx Frame Counter */
+#define XM_TXF_511B		0x02dc	/* 32 bit r/o	256-511 Byte Tx Frame Counter */
+#define XM_TXF_1023B	0x02e0	/* 32 bit r/o	512-1023 Byte Tx Frame Counter*/
+#define XM_TXF_MAX_SZ	0x02e4	/* 32 bit r/o	1024-MaxSize Byte Tx Frame Cnt*/
+	/* 0x02e8 - 0x02fe:	reserved */
+#define XM_RXF_OK		0x0300	/* 32 bit r/o	Frames Received OK */
+#define XM_RXO_OK_HI	0x0304	/* 32 bit r/o	Octets Received OK High Cnt */
+#define XM_RXO_OK_LO	0x0308	/* 32 bit r/o	Octets Received OK Low Counter*/
+#define XM_RXF_BC_OK	0x030c	/* 32 bit r/o	Broadcast Frames Received OK */
+#define XM_RXF_MC_OK	0x0310	/* 32 bit r/o	Multicast Frames Received OK */
+#define XM_RXF_UC_OK	0x0314	/* 32 bit r/o	Unicast Frames Received OK */
+#define XM_RXF_MPAUSE	0x0318	/* 32 bit r/o	Rx Pause MAC Ctrl Frame Cnt */
+#define XM_RXF_MCTRL	0x031c	/* 32 bit r/o	Rx MAC Ctrl Frame Counter */
+#define XM_RXF_INV_MP	0x0320	/* 32 bit r/o	Rx invalid Pause Frame Cnt */
+#define XM_RXF_INV_MOC	0x0324	/* 32 bit r/o	Rx Frames with inv. MAC Opcode*/
+#define XM_RXE_BURST	0x0328	/* 32 bit r/o	Rx Burst Event Counter */
+#define XM_RXE_FMISS	0x032c	/* 32 bit r/o	Rx Missed Frames Event Cnt */
+#define XM_RXF_FRA_ERR	0x0330	/* 32 bit r/o	Rx Framing Error Counter */
+#define XM_RXE_FIFO_OV	0x0334	/* 32 bit r/o	Rx FIFO overflow Event Cnt */
+#define XM_RXF_JAB_PKT	0x0338	/* 32 bit r/o	Rx Jabber Packet Frame Cnt */
+#define XM_RXE_CAR_ERR	0x033c	/* 32 bit r/o	Rx Carrier Event Error Cnt */
+#define XM_RXF_LEN_ERR	0x0340	/* 32 bit r/o	Rx in Range Length Error */
+#define XM_RXE_SYM_ERR	0x0344	/* 32 bit r/o	Rx Symbol Error Counter */
+#define XM_RXE_SHT_ERR	0x0348	/* 32 bit r/o	Rx Short Event Error Cnt */
+#define XM_RXE_RUNT		0x034c	/* 32 bit r/o	Rx Runt Event Counter */
+#define XM_RXF_LNG_ERR	0x0350	/* 32 bit r/o	Rx Frame too Long Error Cnt */
+#define XM_RXF_FCS_ERR	0x0354	/* 32 bit r/o	Rx Frame Check Seq. Error Cnt */
+	/* 0x0358 - 0x035a:	reserved */
+#define XM_RXF_CEX_ERR	0x035c	/* 32 bit r/o	Rx Carrier Ext Error Frame Cnt*/
+#define XM_RXP_UTIL		0x0360	/* 32 bit r/o	Rx Utilization in % */
+	/* 0x0364 - 0x0366:	reserved */
+#define XM_RXF_64B		0x0368	/* 32 bit r/o	64 Byte Rx Frame Counter */
+#define XM_RXF_127B		0x036c	/* 32 bit r/o	65-127 Byte Rx Frame Counter */
+#define XM_RXF_255B		0x0370	/* 32 bit r/o	128-255 Byte Rx Frame Counter */
+#define XM_RXF_511B		0x0374	/* 32 bit r/o	256-511 Byte Rx Frame Counter */
+#define XM_RXF_1023B	0x0378	/* 32 bit r/o	512-1023 Byte Rx Frame Counter*/
+#define XM_RXF_MAX_SZ	0x037c	/* 32 bit r/o	1024-MaxSize Byte Rx Frame Cnt*/
+	/* 0x02e8 - 0x02fe:	reserved */
+
+
+/*----------------------------------------------------------------------------*/
+/*
+ * XMAC Bit Definitions
+ *
+ * If the bit access behaviour differs from the register access behaviour
+ * (r/w, r/o) this is documented after the bit number.
+ * The following bit access behaviours are used:
+ *	(sc)	self clearing
+ *	(ro)	read only
+ */
+
+/*	XM_MMU_CMD	16 bit r/w	MMU Command Register */
+								/* Bit 15..13:	reserved */
+#define XM_MMU_PHY_RDY	(1<<12)	/* Bit 12:	PHY Read Ready */
+#define XM_MMU_PHY_BUSY	(1<<11)	/* Bit 11:	PHY Busy */
+#define XM_MMU_IGN_PF	(1<<10)	/* Bit 10:	Ignore Pause Frame */
+#define XM_MMU_MAC_LB	(1<<9)	/* Bit  9:	Enable MAC Loopback */
+								/* Bit  8:	reserved */
+#define XM_MMU_FRC_COL	(1<<7)	/* Bit  7:	Force Collision */
+#define XM_MMU_SIM_COL	(1<<6)	/* Bit  6:	Simulate Collision */
+#define XM_MMU_NO_PRE	(1<<5)	/* Bit  5:	No MDIO Preamble */
+#define XM_MMU_GMII_FD	(1<<4)	/* Bit  4:	GMII uses Full Duplex */
+#define XM_MMU_RAT_CTRL	(1<<3)	/* Bit  3:	Enable Rate Control */
+#define XM_MMU_GMII_LOOP (1<<2)	/* Bit  2:	PHY is in Loopback Mode */
+#define XM_MMU_ENA_RX	(1<<1)	/* Bit  1:	Enable Receiver */
+#define XM_MMU_ENA_TX	(1<<0)	/* Bit  0:	Enable Transmitter */
+
+
+/*	XM_TX_CMD	16 bit r/w	Transmit Command Register */
+								/* Bit 15..7:	reserved */
+#define XM_TX_BK2BK		(1<<6)	/* Bit  6:	Ignor Carrier Sense (Tx Bk2Bk) */
+#define XM_TX_ENC_BYP	(1<<5)	/* Bit  5:	Set Encoder in Bypass Mode */
+#define XM_TX_SAM_LINE	(1<<4)	/* Bit  4: (sc)	Start utilization calculation */
+#define XM_TX_NO_GIG_MD	(1<<3)	/* Bit  3:	Disable Carrier Extension */
+#define XM_TX_NO_PRE	(1<<2)	/* Bit  2:	Disable Preamble Generation */
+#define XM_TX_NO_CRC	(1<<1)	/* Bit  1:	Disable CRC Generation */
+#define XM_TX_AUTO_PAD	(1<<0)	/* Bit  0:	Enable Automatic Padding */
+
+
+/*	XM_TX_RT_LIM	16 bit r/w	Transmit Retry Limit Register */
+								/* Bit 15..5:	reserved */
+#define XM_RT_LIM_MSK	0x1f	/* Bit  4..0:	Tx Retry Limit */
+
+
+/*	XM_TX_STIME	16 bit r/w	Transmit Slottime Register */
+								/* Bit 15..7:	reserved */
+#define XM_STIME_MSK	0x7f	/* Bit  6..0:	Tx Slottime bits */
+
+
+/*	XM_TX_IPG	16 bit r/w	Transmit Inter Packet Gap */
+								/* Bit 15..8:	reserved */
+#define XM_IPG_MSK		0xff	/* Bit  7..0:	IPG value bits */
+
+
+/*	XM_RX_CMD	16 bit r/w	Receive Command Register */
+								/* Bit 15..9:	reserved */
+#define XM_RX_LENERR_OK (1<<8)	/* Bit  8	don't set Rx Err bit for */
+								/*		inrange error packets */
+#define XM_RX_BIG_PK_OK	(1<<7)	/* Bit  7	don't set Rx Err bit for */
+								/*		jumbo packets */
+#define XM_RX_IPG_CAP	(1<<6)	/* Bit  6	repl. type field with IPG */
+#define XM_RX_TP_MD		(1<<5)	/* Bit  5:	Enable transparent Mode */
+#define XM_RX_STRIP_FCS	(1<<4)	/* Bit  4:	Enable FCS Stripping */
+#define XM_RX_SELF_RX	(1<<3)	/* Bit  3: 	Enable Rx of own packets */
+#define XM_RX_SAM_LINE	(1<<2)	/* Bit  2: (sc)	Start utilization calculation */
+#define XM_RX_STRIP_PAD	(1<<1)	/* Bit  1:	Strip pad bytes of Rx frames */
+#define XM_RX_DIS_CEXT	(1<<0)	/* Bit  0:	Disable carrier ext. check */
+
+
+/*	XM_PHY_ADDR	16 bit r/w	PHY Address Register */
+								/* Bit 15..5:	reserved */
+#define XM_PHY_ADDR_SZ	0x1f	/* Bit  4..0:	PHY Address bits */
+
+
+/*	XM_GP_PORT	32 bit r/w	General Purpose Port Register */
+								/* Bit 31..7:	reserved */
+#define XM_GP_ANIP		(1L<<6)	/* Bit  6: (ro)	Auto-Neg. in progress */
+#define XM_GP_FRC_INT	(1L<<5)	/* Bit  5: (sc)	Force Interrupt */
+								/* Bit  4:	reserved */
+#define XM_GP_RES_MAC	(1L<<3)	/* Bit  3: (sc)	Reset MAC and FIFOs */
+#define XM_GP_RES_STAT	(1L<<2)	/* Bit  2: (sc)	Reset the statistics module */
+								/* Bit  1:	reserved */
+#define XM_GP_INP_ASS	(1L<<0)	/* Bit  0: (ro) GP Input Pin asserted */
+
+
+/*	XM_IMSK		16 bit r/w	Interrupt Mask Register */
+/*	XM_ISRC		16 bit r/o	Interrupt Status Register */
+								/* Bit 15:	reserved */
+#define XM_IS_LNK_AE	(1<<14) /* Bit 14:	Link Asynchronous Event */
+#define XM_IS_TX_ABORT	(1<<13) /* Bit 13:	Transmit Abort, late Col. etc */
+#define XM_IS_FRC_INT	(1<<12) /* Bit 12:	Force INT bit set in GP */
+#define XM_IS_INP_ASS	(1<<11)	/* Bit 11:	Input Asserted, GP bit 0 set */
+#define XM_IS_LIPA_RC	(1<<10)	/* Bit 10:	Link Partner requests config */
+#define XM_IS_RX_PAGE	(1<<9)	/* Bit  9:	Page Received */
+#define XM_IS_TX_PAGE	(1<<8)	/* Bit  8:	Next Page Loaded for Transmit */
+#define XM_IS_AND		(1<<7)	/* Bit  7:	Auto-Negotiation Done */
+#define XM_IS_TSC_OV	(1<<6)	/* Bit  6:	Time Stamp Counter Overflow */
+#define XM_IS_RXC_OV	(1<<5)	/* Bit  5:	Rx Counter Event Overflow */
+#define XM_IS_TXC_OV	(1<<4)	/* Bit  4:	Tx Counter Event Overflow */
+#define XM_IS_RXF_OV	(1<<3)	/* Bit  3:	Receive FIFO Overflow */
+#define XM_IS_TXF_UR	(1<<2)	/* Bit  2:	Transmit FIFO Underrun */
+#define XM_IS_TX_COMP	(1<<1)	/* Bit  1:	Frame Tx Complete */
+#define XM_IS_RX_COMP	(1<<0)	/* Bit  0:	Frame Rx Complete */
+
+#define XM_DEF_MSK	(~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\
+			XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR))
+
+
+/*	XM_HW_CFG	16 bit r/w	Hardware Config Register */
+								/* Bit 15.. 4:	reserved */
+#define XM_HW_GEN_EOP	(1<<3)	/* Bit  3:	generate End of Packet pulse */
+#define XM_HW_COM4SIG	(1<<2)	/* Bit  2:	use Comma Detect for Sig. Det.*/
+								/* Bit  1:	reserved */
+#define XM_HW_GMII_MD	(1<<0)	/* Bit  0:	GMII Interface selected */
+
+
+/*	XM_TX_LO_WM	16 bit r/w	Tx FIFO Low Water Mark */
+/*	XM_TX_HI_WM	16 bit r/w	Tx FIFO High Water Mark */
+								/* Bit 15..10	reserved */
+#define XM_TX_WM_MSK	0x01ff	/* Bit  9.. 0	Tx FIFO Watermark bits */
+
+/*	XM_TX_THR	16 bit r/w	Tx Request Threshold */
+/*	XM_HT_THR	16 bit r/w	Host Request Threshold */
+/*	XM_RX_THR	16 bit r/w	Rx Request Threshold */
+								/* Bit 15..11	reserved */
+#define XM_THR_MSK		0x03ff	/* Bit 10.. 0	Rx/Tx Request Threshold bits */
+
+
+/*	XM_TX_STAT	32 bit r/o	Tx Status LIFO Register */
+#define XM_ST_VALID		(1UL<<31)	/* Bit 31:	Status Valid */
+#define XM_ST_BYTE_CNT	(0x3fffL<<17)	/* Bit 30..17:	Tx frame Length */
+#define XM_ST_RETRY_CNT	(0x1fL<<12)	/* Bit 16..12:	Retry Count */
+#define XM_ST_EX_COL	(1L<<11)	/* Bit 11:	Excessive Collisions */
+#define XM_ST_EX_DEF	(1L<<10)	/* Bit 10:	Excessive Deferral */
+#define XM_ST_BURST		(1L<<9)		/* Bit  9:	p. xmitted in burst md*/
+#define XM_ST_DEFER		(1L<<8)		/* Bit  8:	packet was defered */
+#define XM_ST_BC		(1L<<7)		/* Bit  7:	Broadcast packet */
+#define XM_ST_MC		(1L<<6)		/* Bit  6:	Multicast packet */
+#define XM_ST_UC		(1L<<5)		/* Bit  5:	Unicast packet */
+#define XM_ST_TX_UR		(1L<<4)		/* Bit  4:	FIFO Underrun occured */
+#define XM_ST_CS_ERR	(1L<<3)		/* Bit  3:	Carrier Sense Error */
+#define XM_ST_LAT_COL	(1L<<2)		/* Bit  2:	Late Collision Error */
+#define XM_ST_MUL_COL	(1L<<1)		/* Bit  1:	Multiple Collisions */
+#define XM_ST_SGN_COL	(1L<<0)		/* Bit  0:	Single Collision */
+
+/*	XM_RX_LO_WM	16 bit r/w	Receive Low Water Mark */
+/*	XM_RX_HI_WM	16 bit r/w	Receive High Water Mark */
+									/* Bit 15..11:	reserved */
+#define XM_RX_WM_MSK	0x03ff		/* Bit 11.. 0:	Rx FIFO Watermark bits */
+
+
+/*	XM_DEV_ID	32 bit r/o	Device ID Register */
+#define XM_DEV_OUI	(0x00ffffffUL<<8)	/* Bit 31..8:	Device OUI */
+#define XM_DEV_REV	(0x07L << 5)		/* Bit  7..5:	Chip Rev Num */
+
+
+/*	XM_MODE		32 bit r/w	Mode Register */
+									/* Bit 31..27:	reserved */
+#define XM_MD_ENA_REJ	(1L<<26)	/* Bit 26:	Enable Frame Reject */
+#define XM_MD_SPOE_E	(1L<<25)	/* Bit 25:	Send Pause on Edge */
+									/* 		extern generated */
+#define XM_MD_TX_REP	(1L<<24)	/* Bit 24:	Transmit Repeater Mode */
+#define XM_MD_SPOFF_I	(1L<<23)	/* Bit 23:	Send Pause on FIFO full */
+									/*		intern generated */
+#define XM_MD_LE_STW	(1L<<22)	/* Bit 22:	Rx Stat Word in Little Endian */
+#define XM_MD_TX_CONT	(1L<<21)	/* Bit 21:	Send Continuous */
+#define XM_MD_TX_PAUSE	(1L<<20)	/* Bit 20: (sc)	Send Pause Frame */
+#define XM_MD_ATS		(1L<<19)	/* Bit 19:	Append Time Stamp */
+#define XM_MD_SPOL_I	(1L<<18)	/* Bit 18:	Send Pause on Low */
+									/*		intern generated */
+#define XM_MD_SPOH_I	(1L<<17)	/* Bit 17:	Send Pause on High */
+									/*		intern generated */
+#define XM_MD_CAP		(1L<<16)	/* Bit 16:	Check Address Pair */
+#define XM_MD_ENA_HASH	(1L<<15)	/* Bit 15:	Enable Hashing */
+#define XM_MD_CSA		(1L<<14)	/* Bit 14:	Check Station Address */
+#define XM_MD_CAA		(1L<<13)	/* Bit 13:	Check Address Array */
+#define XM_MD_RX_MCTRL	(1L<<12)	/* Bit 12:	Rx MAC Control Frame */
+#define XM_MD_RX_RUNT	(1L<<11)	/* Bit 11:	Rx Runt Frames */
+#define XM_MD_RX_IRLE	(1L<<10)	/* Bit 10:	Rx in Range Len Err Frame */
+#define XM_MD_RX_LONG	(1L<<9)		/* Bit  9:	Rx Long Frame */
+#define XM_MD_RX_CRCE	(1L<<8)		/* Bit  8:	Rx CRC Error Frame */
+#define XM_MD_RX_ERR	(1L<<7)		/* Bit  7:	Rx Error Frame */
+#define XM_MD_DIS_UC	(1L<<6)		/* Bit  6:	Disable Rx Unicast */
+#define XM_MD_DIS_MC	(1L<<5)		/* Bit  5:	Disable Rx Multicast */
+#define XM_MD_DIS_BC	(1L<<4)		/* Bit  4:	Disable Rx Broadcast */
+#define XM_MD_ENA_PROM	(1L<<3)		/* Bit  3:	Enable Promiscuous */
+#define XM_MD_ENA_BE	(1L<<2)		/* Bit  2:	Enable Big Endian */
+#define XM_MD_FTF		(1L<<1)		/* Bit  1: (sc)	Flush Tx FIFO */
+#define XM_MD_FRF		(1L<<0)		/* Bit  0: (sc)	Flush Rx FIFO */
+
+#define XM_PAUSE_MODE	(XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
+#define XM_DEF_MODE		(XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
+				XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
+
+/*	XM_STAT_CMD	16 bit r/w	Statistics Command Register */
+								/* Bit 16..6:	reserved */
+#define XM_SC_SNP_RXC	(1<<5)	/* Bit  5: (sc)	Snap Rx Counters */
+#define XM_SC_SNP_TXC	(1<<4)	/* Bit  4: (sc)	Snap Tx Counters */
+#define XM_SC_CP_RXC	(1<<3)	/* Bit  3:	Copy Rx Counters Continuously */
+#define XM_SC_CP_TXC	(1<<2)	/* Bit  2:	Copy Tx Counters Continuously */
+#define XM_SC_CLR_RXC	(1<<1)	/* Bit  1: (sc)	Clear Rx Counters */
+#define XM_SC_CLR_TXC	(1<<0)	/* Bit  0: (sc)	Clear Tx Counters */
+
+
+/*	XM_RX_CNT_EV	32 bit r/o	Rx Counter Event Register */
+/*	XM_RX_EV_MSK	32 bit r/w	Rx Counter Event Mask */
+#define XMR_MAX_SZ_OV	(1UL<<31)	/* Bit 31:	1024-MaxSize Rx Cnt Ov */
+#define XMR_1023B_OV	(1L<<30)	/* Bit 30:	512-1023Byte Rx Cnt Ov */
+#define XMR_511B_OV		(1L<<29)	/* Bit 29:	256-511 Byte Rx Cnt Ov */
+#define XMR_255B_OV		(1L<<28)	/* Bit 28:	128-255 Byte Rx Cnt Ov */
+#define XMR_127B_OV		(1L<<27)	/* Bit 27:	65-127 Byte Rx Cnt Ov */
+#define XMR_64B_OV		(1L<<26)	/* Bit 26:	64 Byte Rx Cnt Ov */
+#define XMR_UTIL_OV		(1L<<25)	/* Bit 25:	Rx Util Cnt Overflow */
+#define XMR_UTIL_UR		(1L<<24)	/* Bit 24:	Rx Util Cnt Underrun */
+#define XMR_CEX_ERR_OV	(1L<<23)	/* Bit 23:	CEXT Err Cnt Ov */
+									/* Bit 22:	reserved */
+#define XMR_FCS_ERR_OV	(1L<<21)	/* Bit 21:	Rx FCS Error Cnt Ov */
+#define XMR_LNG_ERR_OV	(1L<<20)	/* Bit 20:	Rx too Long Err Cnt Ov */
+#define XMR_RUNT_OV		(1L<<19)	/* Bit 19:	Runt Event Cnt Ov */
+#define XMR_SHT_ERR_OV	(1L<<18)	/* Bit 18:	Rx Short Ev Err Cnt Ov */
+#define XMR_SYM_ERR_OV	(1L<<17)	/* Bit 17:	Rx Sym Err Cnt Ov */
+									/* Bit 16:	reserved */
+#define XMR_CAR_ERR_OV	(1L<<15)	/* Bit 15:	Rx Carr Ev Err Cnt Ov */
+#define XMR_JAB_PKT_OV	(1L<<14)	/* Bit 14:	Rx Jabb Packet Cnt Ov */
+#define XMR_FIFO_OV		(1L<<13)	/* Bit 13:	Rx FIFO Ov Ev Cnt Ov */
+#define XMR_FRA_ERR_OV	(1L<<12)	/* Bit 12:	Rx Framing Err Cnt Ov */
+#define XMR_FMISS_OV	(1L<<11)	/* Bit 11:	Rx Missed Ev Cnt Ov */
+#define XMR_BURST		(1L<<10)	/* Bit 10:	Rx Burst Event Cnt Ov */
+#define XMR_INV_MOC		(1L<<9)		/* Bit  9:	Rx with inv. MAC OC Ov */
+#define XMR_INV_MP		(1L<<8)		/* Bit  8:	Rx inv Pause Frame Ov */
+#define XMR_MCTRL_OV	(1L<<7)		/* Bit  7:	Rx MAC Ctrl-F Cnt Ov */
+#define XMR_MPAUSE_OV	(1L<<6)		/* Bit  6:	Rx Pause MAC Ctrl-F Ov */
+#define XMR_UC_OK_OV	(1L<<5)		/* Bit  5:	Rx Unicast Frame Cnt Ov */
+#define XMR_MC_OK_OV	(1L<<4)		/* Bit  4:	Rx Multicast Cnt Ov */
+#define XMR_BC_OK_OV	(1L<<3)		/* Bit  3:	Rx Broadcast Cnt Ov */
+#define XMR_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Rx OK Low Cnt Ov */
+#define XMR_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Rx OK High Cnt Ov */
+#define XMR_OK_OV		(1L<<0)		/* Bit  0:	Frames Received OK Ov */
+
+#define XMR_DEF_MSK		(XMR_OK_LO_OV | XMR_OK_HI_OV)
+
+/*	XM_TX_CNT_EV	32 bit r/o	Tx Counter Event Register */
+/*	XM_TX_EV_MSK	32 bit r/w	Tx Counter Event Mask */
+									/* Bit 31..26:	reserved */
+#define XMT_MAX_SZ_OV	(1L<<25)	/* Bit 25:	1024-MaxSize Tx Cnt Ov */
+#define XMT_1023B_OV	(1L<<24)	/* Bit 24:	512-1023Byte Tx Cnt Ov */
+#define XMT_511B_OV		(1L<<23)	/* Bit 23:	256-511 Byte Tx Cnt Ov */
+#define XMT_255B_OV		(1L<<22)	/* Bit 22:	128-255 Byte Tx Cnt Ov */
+#define XMT_127B_OV		(1L<<21)	/* Bit 21:	65-127 Byte Tx Cnt Ov */
+#define XMT_64B_OV		(1L<<20)	/* Bit 20:	64 Byte Tx Cnt Ov */
+#define XMT_UTIL_OV		(1L<<19)	/* Bit 19:	Tx Util Cnt Overflow */
+#define XMT_UTIL_UR		(1L<<18)	/* Bit 18:	Tx Util Cnt Underrun */
+#define XMT_CS_ERR_OV	(1L<<17)	/* Bit 17:	Tx Carr Sen Err Cnt Ov */
+#define XMT_FIFO_UR_OV	(1L<<16)	/* Bit 16:	Tx FIFO Ur Ev Cnt Ov */
+#define XMT_EX_DEF_OV	(1L<<15)	/* Bit 15:	Tx Ex Deferall Cnt Ov */
+#define XMT_DEF			(1L<<14)	/* Bit 14:	Tx Deferred Cnt Ov */
+#define XMT_LAT_COL_OV	(1L<<13)	/* Bit 13:	Tx Late Col Cnt Ov */
+#define XMT_ABO_COL_OV	(1L<<12)	/* Bit 12:	Tx abo dueto Ex Col Ov */
+#define XMT_MUL_COL_OV	(1L<<11)	/* Bit 11:	Tx Mult Col Cnt Ov */
+#define XMT_SNG_COL		(1L<<10)	/* Bit 10:	Tx Single Col Cnt Ov */
+#define XMT_MCTRL_OV	(1L<<9)		/* Bit  9:	Tx MAC Ctrl Counter Ov */
+#define XMT_MPAUSE		(1L<<8)		/* Bit  8:	Tx Pause MAC Ctrl-F Ov */
+#define XMT_BURST		(1L<<7)		/* Bit  7:	Tx Burst Event Cnt Ov */
+#define XMT_LONG		(1L<<6)		/* Bit  6:	Tx Long Frame Cnt Ov */
+#define XMT_UC_OK_OV	(1L<<5)		/* Bit  5:	Tx Unicast Cnt Ov */
+#define XMT_MC_OK_OV	(1L<<4)		/* Bit  4:	Tx Multicast Cnt Ov */
+#define XMT_BC_OK_OV	(1L<<3)		/* Bit  3:	Tx Broadcast Cnt Ov */
+#define XMT_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Tx OK Low Cnt Ov */
+#define XMT_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Tx OK High Cnt Ov */
+#define XMT_OK_OV		(1L<<0)		/* Bit  0:	Frames Tx OK Ov */
+
+#define XMT_DEF_MSK		(XMT_OK_LO_OV | XMT_OK_HI_OV)
+
+/*
+ * Receive Frame Status Encoding
+ */
+#define XMR_FS_LEN_MSK	(0x3fffUL<<18)	/* Bit 31..18:	Rx Frame Length */
+#define XMR_FS_2L_VLAN	(1L<<17)	/* Bit 17:	Tagged wh 2Lev VLAN ID */
+#define XMR_FS_1L_VLAN	(1L<<16)	/* Bit 16:	Tagged wh 1Lev VLAN ID */
+#define XMR_FS_BC		(1L<<15)	/* Bit 15:	Broadcast Frame */
+#define XMR_FS_MC		(1L<<14)	/* Bit 14:	Multicast Frame */
+#define XMR_FS_UC		(1L<<13)	/* Bit 13:	Unicast Frame */
+									/* Bit 12:	reserved */
+#define XMR_FS_BURST	(1L<<11)	/* Bit 11:	Burst Mode */
+#define XMR_FS_CEX_ERR	(1L<<10)	/* Bit 10:	Carrier Ext. Error */
+#define XMR_FS_802_3	(1L<<9)		/* Bit  9:	802.3 Frame */
+#define XMR_FS_COL_ERR	(1L<<8)		/* Bit  8:	Collision Error */
+#define XMR_FS_CAR_ERR	(1L<<7)		/* Bit  7:	Carrier Event Error */
+#define XMR_FS_LEN_ERR	(1L<<6)		/* Bit  6:	In-Range Length Error */
+#define XMR_FS_FRA_ERR	(1L<<5)		/* Bit  5:	Framing Error */
+#define XMR_FS_RUNT		(1L<<4)		/* Bit  4:	Runt Frame */
+#define XMR_FS_LNG_ERR	(1L<<3)		/* Bit  3:	Giant (Jumbo) Frame */
+#define XMR_FS_FCS_ERR	(1L<<2)		/* Bit  2:	Frame Check Sequ Err */
+#define XMR_FS_ERR		(1L<<1)		/* Bit  1:	Frame Error */
+#define XMR_FS_MCTRL	(1L<<0)		/* Bit  0:	MAC Control Packet */
+
+#define XMR_FS_LEN_SHIFT	18
+
+/*
+ * XMR_FS_ERR will be set if
+ *	XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
+ *	XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
+ * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
+ * XMR_FS_ERR unless the corresponding bit in the Receive Command
+ * Register is set.
+ */
+#define XMR_FS_ANY_ERR	XMR_FS_ERR
+
+/*----------------------------------------------------------------------------*/
+/*
+ * XMAC-PHY Registers, indirect addressed over the XMAC
+ */
+#define PHY_XMAC_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+#define PHY_XMAC_STAT		0x01	/* 16 bit r/w	PHY Status Register */
+#define PHY_XMAC_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
+#define PHY_XMAC_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
+#define PHY_XMAC_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+#define PHY_XMAC_AUNE_LP	0x05	/* 16 bit r/o	Link Partner Ability Reg */
+#define PHY_XMAC_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+#define PHY_XMAC_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+#define PHY_XMAC_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
+	/* 0x09 - 0x0e:		reserved */
+#define PHY_XMAC_EXT_STAT	0x0f	/* 16 bit r/o	Ext Status Register */
+#define PHY_XMAC_RES_ABI	0x10	/* 16 bit r/o	PHY Resolved Ability */
+
+/*----------------------------------------------------------------------------*/
+/*
+ * Broadcom-PHY Registers, indirect addressed over XMAC
+ */
+#define PHY_BCOM_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+#define PHY_BCOM_STAT		0x01	/* 16 bit r/o	PHY Status Register */
+#define PHY_BCOM_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
+#define PHY_BCOM_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
+#define PHY_BCOM_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+#define PHY_BCOM_AUNE_LP	0x05	/* 16 bit r/o	Link Partner Ability Reg */
+#define PHY_BCOM_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+#define PHY_BCOM_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+#define PHY_BCOM_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
+	/* Broadcom-specific registers */
+#define PHY_BCOM_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg */
+#define PHY_BCOM_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
+	/* 0x0b - 0x0e:		reserved */
+#define PHY_BCOM_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
+#define PHY_BCOM_P_EXT_CTRL	0x10	/* 16 bit r/w	PHY Extended Ctrl Reg */
+#define PHY_BCOM_P_EXT_STAT	0x11	/* 16 bit r/o	PHY Extended Stat Reg */
+#define PHY_BCOM_RE_CTR		0x12	/* 16 bit r/w	Receive Error Counter */
+#define PHY_BCOM_FC_CTR		0x13	/* 16 bit r/w	False Carrier Sense Cnt */
+#define PHY_BCOM_RNO_CTR	0x14	/* 16 bit r/w	Receiver NOT_OK Cnt */
+	/* 0x15 - 0x17:		reserved */
+#define PHY_BCOM_AUX_CTRL	0x18	/* 16 bit r/w	Auxiliary Control Reg */
+#define PHY_BCOM_AUX_STAT	0x19	/* 16 bit r/o	Auxiliary Stat Summary */
+#define PHY_BCOM_INT_STAT	0x1a	/* 16 bit r/o	Interrupt Status Reg */
+#define PHY_BCOM_INT_MASK	0x1b	/* 16 bit r/w	Interrupt Mask Reg */
+	/* 0x1c:		reserved */
+	/* 0x1d - 0x1f:		test registers */
+
+/*----------------------------------------------------------------------------*/
+/*
+ * Marvell-PHY Registers, indirect addressed over GMAC
+ */
+#define PHY_MARV_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+#define PHY_MARV_STAT		0x01	/* 16 bit r/o	PHY Status Register */
+#define PHY_MARV_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
+#define PHY_MARV_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
+#define PHY_MARV_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+#define PHY_MARV_AUNE_LP	0x05	/* 16 bit r/o	Link Partner Ability Reg */
+#define PHY_MARV_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+#define PHY_MARV_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+#define PHY_MARV_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
+	/* Marvell-specific registers */
+#define PHY_MARV_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg */
+#define PHY_MARV_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
+	/* 0x0b - 0x0e:		reserved */
+#define PHY_MARV_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
+#define PHY_MARV_PHY_CTRL	0x10	/* 16 bit r/w	PHY Specific Control Reg */
+#define PHY_MARV_PHY_STAT	0x11	/* 16 bit r/o	PHY Specific Status Reg */
+#define PHY_MARV_INT_MASK	0x12	/* 16 bit r/w	Interrupt Mask Reg */
+#define PHY_MARV_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
+#define PHY_MARV_EXT_CTRL	0x14	/* 16 bit r/w	Ext. PHY Specific Ctrl */
+#define PHY_MARV_RXE_CNT	0x15	/* 16 bit r/w	Receive Error Counter */
+#define PHY_MARV_EXT_ADR	0x16	/* 16 bit r/w	Ext. Ad. for Cable Diag. */
+#define PHY_MARV_PORT_IRQ	0x17	/* 16 bit r/o	Port 0 IRQ (88E1111 only) */
+#define PHY_MARV_LED_CTRL	0x18	/* 16 bit r/w	LED Control Reg */
+#define PHY_MARV_LED_OVER	0x19	/* 16 bit r/w	Manual LED Override Reg */
+#define PHY_MARV_EXT_CTRL_2	0x1a	/* 16 bit r/w	Ext. PHY Specific Ctrl 2 */
+#define PHY_MARV_EXT_P_STAT	0x1b	/* 16 bit r/w	Ext. PHY Spec. Stat Reg */
+#define PHY_MARV_CABLE_DIAG	0x1c	/* 16 bit r/o	Cable Diagnostic Reg */
+#define PHY_MARV_PAGE_ADDR	0x1d	/* 16 bit r/w	Extended Page Address Reg */
+#define PHY_MARV_PAGE_DATA	0x1e	/* 16 bit r/w	Extended Page Data Reg */
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+#define PHY_MARV_FE_LED_PAR	0x16	/* 16 bit r/w	LED Parallel Select Reg. */
+#define PHY_MARV_FE_LED_SER	0x17	/* 16 bit r/w	LED Stream Select S. LED */
+#define PHY_MARV_FE_VCT_TX	0x1a	/* 16 bit r/w	VCT Reg. for TXP/N Pins */
+#define PHY_MARV_FE_VCT_RX	0x1b	/* 16 bit r/o	VCT Reg. for RXP/N Pins */
+#define PHY_MARV_FE_SPEC_2	0x1c	/* 16 bit r/w	Specific Control Reg. 2 */
+
+/* for Yukon-Ultra & Yukon-Extreme PHY only */
+#define PHY_MARV_MAC_CTRL	0x15	/* 16 bit r/w	MAC Spec. Ctrl (page 2) */
+
+/*----------------------------------------------------------------------------*/
+/*
+ * Level One-PHY Registers, indirect addressed over XMAC
+ */
+#define PHY_LONE_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+#define PHY_LONE_STAT		0x01	/* 16 bit r/o	PHY Status Register */
+#define PHY_LONE_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
+#define PHY_LONE_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
+#define PHY_LONE_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+#define PHY_LONE_AUNE_LP	0x05	/* 16 bit r/o	Link Partner Ability Reg */
+#define PHY_LONE_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+#define PHY_LONE_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+#define PHY_LONE_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
+	/* Level One-specific registers */
+#define PHY_LONE_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg */
+#define PHY_LONE_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
+	/* 0x0b - 0x0e:		reserved */
+#define PHY_LONE_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
+#define PHY_LONE_PORT_CFG	0x10	/* 16 bit r/w	Port Configuration Reg*/
+#define PHY_LONE_Q_STAT		0x11	/* 16 bit r/o	Quick Status Reg */
+#define PHY_LONE_INT_ENAB	0x12	/* 16 bit r/w	Interrupt Enable Reg */
+#define PHY_LONE_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
+#define PHY_LONE_LED_CFG	0x14	/* 16 bit r/w	LED Configuration Reg */
+#define PHY_LONE_PORT_CTRL	0x15	/* 16 bit r/w	Port Control Reg */
+#define PHY_LONE_CIM		0x16	/* 16 bit r/o	CIM Reg */
+	/* 0x17 - 0x1c:		reserved */
+
+/*----------------------------------------------------------------------------*/
+/*
+ * National-PHY Registers, indirect addressed over XMAC
+ */
+#define PHY_NAT_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+#define PHY_NAT_STAT		0x01	/* 16 bit r/w	PHY Status Register */
+#define PHY_NAT_ID0			0x02	/* 16 bit r/o	PHY ID0 Register */
+#define PHY_NAT_ID1			0x03	/* 16 bit r/o	PHY ID1 Register */
+#define PHY_NAT_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+#define PHY_NAT_AUNE_LP		0x05	/* 16 bit r/o	Link Partner Ability Reg */
+#define PHY_NAT_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+#define PHY_NAT_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+#define PHY_NAT_NEPG_LP		0x08	/* 16 bit r/o	Next Page Link Partner Reg */
+	/* National-specific registers */
+#define PHY_NAT_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg */
+#define PHY_NAT_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
+	/* 0x0b - 0x0e:		reserved */
+#define PHY_NAT_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Register */
+#define PHY_NAT_EXT_CTRL1	0x10	/* 16 bit r/o	Extended Control Reg1 */
+#define PHY_NAT_Q_STAT1		0x11	/* 16 bit r/o	Quick Status Reg1 */
+#define PHY_NAT_10B_OP		0x12	/* 16 bit r/o	10Base-T Operations Reg */
+#define PHY_NAT_EXT_CTRL2	0x13	/* 16 bit r/o	Extended Control Reg1 */
+#define PHY_NAT_Q_STAT2		0x14	/* 16 bit r/o	Quick Status Reg2 */
+	/* 0x15 - 0x18:		reserved */
+#define PHY_NAT_PHY_ADDR	0x19	/* 16 bit r/o	PHY Address Register */
+
+
+/*----------------------------------------------------------------------------*/
+
+/*
+ * PHY bit definitions
+ * Bits defined as PHY_X_..., PHY_B_..., PHY_L_..., PHY_N_... or PHY_M_... are
+ * XMAC/Broadcom/LevelOne/National/Marvell-specific.
+ * All other are general.
+ */
+
+/*****  PHY_XMAC_CTRL	16 bit r/w	PHY Control Register *****/
+/*****  PHY_BCOM_CTRL	16 bit r/w	PHY Control Register *****/
+/*****  PHY_MARV_CTRL	16 bit r/w	PHY Status Register *****/
+/*****  PHY_LONE_CTRL	16 bit r/w	PHY Control Register *****/
+#define PHY_CT_RESET	(1<<15)	/* Bit 15: (sc)	clear all PHY related regs */
+#define PHY_CT_LOOP		(1<<14)	/* Bit 14:	enable Loopback over PHY */
+#define PHY_CT_SPS_LSB	(1<<13) /* Bit 13:	Speed select, lower bit */
+#define PHY_CT_ANE		(1<<12)	/* Bit 12:	Auto-Negotiation Enabled */
+#define PHY_CT_PDOWN	(1<<11)	/* Bit 11:	Power Down Mode */
+#define PHY_CT_ISOL		(1<<10)	/* Bit 10:	Isolate Mode */
+#define PHY_CT_RE_CFG	(1<<9)	/* Bit  9:	(sc) Restart Auto-Negotiation */
+#define PHY_CT_DUP_MD	(1<<8)	/* Bit  8:	Duplex Mode */
+#define PHY_CT_COL_TST	(1<<7)	/* Bit  7:	Collision Test enabled */
+#define PHY_CT_SPS_MSB	(1<<6)	/* Bit  6:	Speed select, upper bit */
+								/* Bit  5..0:	reserved */
+
+#define PHY_CT_SP1000	PHY_CT_SPS_MSB	/* enable speed of 1000 Mbps */
+#define PHY_CT_SP100	PHY_CT_SPS_LSB	/* enable speed of  100 Mbps */
+#define PHY_CT_SP10		(0)				/* enable speed of   10 Mbps */
+
+
+/*****  PHY_XMAC_STAT	16 bit r/w	PHY Status Register *****/
+/*****  PHY_BCOM_STAT	16 bit r/w	PHY Status Register *****/
+/*****  PHY_MARV_STAT	16 bit r/w	PHY Status Register *****/
+/*****  PHY_LONE_STAT	16 bit r/w	PHY Status Register *****/
+								/* Bit 15..9:	reserved */
+				/*	(BC/L1) 100/10 Mbps cap bits ignored */
+#define PHY_ST_EXT_ST	(1<<8)	/* Bit  8:	Extended Status Present */
+								/* Bit  7:	reserved */
+#define PHY_ST_PRE_SUP	(1<<6)	/* Bit  6:	Preamble Suppression */
+#define PHY_ST_AN_OVER	(1<<5)	/* Bit  5:	Auto-Negotiation Over */
+#define PHY_ST_REM_FLT	(1<<4)	/* Bit  4:	Remote Fault Condition Occured */
+#define PHY_ST_AN_CAP	(1<<3)	/* Bit  3:	Auto-Negotiation Capability */
+#define PHY_ST_LSYNC	(1<<2)	/* Bit  2:	Link Synchronized */
+#define PHY_ST_JAB_DET	(1<<1)	/* Bit  1:	Jabber Detected */
+#define PHY_ST_EXT_REG	(1<<0)	/* Bit  0:	Extended Register available */
+
+
+/*****  PHY_XMAC_ID1		16 bit r/o	PHY ID1 Register */
+/*****  PHY_BCOM_ID1		16 bit r/o	PHY ID1 Register */
+/*****  PHY_MARV_ID1		16 bit r/o	PHY ID1 Register */
+/*****  PHY_LONE_ID1		16 bit r/o	PHY ID1 Register */
+#define PHY_I1_OUI_MSK	(0x3f<<10)	/* Bit 15..10:	Organization Unique ID */
+#define PHY_I1_MOD_NUM	(0x3f<<4)	/* Bit  9.. 4:	Model Number */
+#define PHY_I1_REV_MSK	0xf			/* Bit  3.. 0:	Revision Number */
+
+/* different Broadcom PHY Ids */
+#define PHY_BCOM_ID1_A1		0x6041
+#define PHY_BCOM_ID1_B2		0x6043
+#define PHY_BCOM_ID1_C0		0x6044
+#define PHY_BCOM_ID1_C5		0x6047
+
+/* different Marvell PHY Ids */
+#define PHY_MARV_ID0_VAL	0x0141		/* Marvell Unique Identifier */
+
+#define PHY_MARV_ID1_B0		0x0C23		/* Yukon      (PHY 88E1040 Rev.C0) */
+#define PHY_MARV_ID1_B2		0x0C25		/* Yukon-Plus (PHY 88E1040 Rev.D0) */
+#define PHY_MARV_ID1_C2		0x0CC2		/* Yukon-EC   (PHY 88E1111 Rev.B1) */
+#define PHY_MARV_ID1_Y2		0x0C91		/* Yukon-XL   (PHY 88E1112 Rev.B0) */
+#define PHY_MARV_ID1_FE		0x0C83		/* Yukon-FE   (PHY 88E3082 Rev.A1) */
+#define PHY_MARV_ID1_FEP	0x0E60		/* Yukon-FE+  (PHY 88E3016 Rev.A1?) */
+#define PHY_MARV_ID1_ECU	0x0CB0		/* Yukon-ECU  (PHY 88E1149 Rev.B2?) */
+#define PHY_MARV_ID1_EX		0x0CB1		/* Yukon-Ext. (PHY 88E1149R Rev.?) */
+
+
+/*****  PHY_XMAC_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+/*****  PHY_XMAC_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
+#define PHY_AN_NXT_PG	(1<<15)	/* Bit 15:	Request Next Page */
+#define PHY_X_AN_ACK	(1<<14)	/* Bit 14:	(ro) Acknowledge Received */
+#define PHY_X_AN_RFB	(3<<12)	/* Bit 13..12:	Remote Fault Bits */
+								/* Bit 11.. 9:	reserved */
+#define PHY_X_AN_PAUSE	(3<<7)	/* Bit  8.. 7:	Pause Bits */
+#define PHY_X_AN_HD		(1<<6)	/* Bit  6:	Half Duplex */
+#define PHY_X_AN_FD		(1<<5)	/* Bit  5:	Full Duplex */
+								/* Bit  4.. 0:	reserved */
+
+/*****  PHY_BCOM_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+/*****  PHY_BCOM_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
+/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
+								/* Bit 14:	reserved */
+#define PHY_B_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
+								/* Bit 12:	reserved */
+#define PHY_B_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
+#define PHY_B_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
+								/* Bit  9..5:	100/10 BT cap bits ingnored */
+#define PHY_B_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
+
+/*****  PHY_LONE_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+/*****  PHY_LONE_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
+/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
+								/* Bit 14:	reserved */
+#define PHY_L_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
+								/* Bit 12:	reserved */
+#define PHY_L_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
+#define PHY_L_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
+								/* Bit  9..5:	100/10 BT cap bits ingnored */
+#define PHY_L_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
+
+/*****  PHY_NAT_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+/*****  PHY_NAT_AUNE_LP		16 bit r/o	Link Partner Ability Reg *****/
+/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
+								/* Bit 14:	reserved */
+#define PHY_N_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
+								/* Bit 12:	reserved */
+#define PHY_N_AN_100F	(1<<11)	/* Bit 11:	100Base-T2 FD Support */
+#define PHY_N_AN_100H	(1<<10)	/* Bit 10:	100Base-T2 HD Support */
+								/* Bit  9..5:	100/10 BT cap bits ingnored */
+#define PHY_N_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
+
+/* field type definition for PHY_x_AN_SEL */
+#define PHY_SEL_TYPE	0x01	/* 00001 = Ethernet */
+
+/*****  PHY_XMAC_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
+								/* Bit 15..4:	reserved */
+#define PHY_ANE_LP_NP	(1<<3)	/* Bit  3:	Link Partner can Next Page */
+#define PHY_ANE_LOC_NP	(1<<2)	/* Bit  2:	Local PHY can Next Page */
+#define PHY_ANE_RX_PG	(1<<1)	/* Bit  1:	Page Received */
+								/* Bit  0:	reserved */
+
+/*****  PHY_BCOM_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
+/*****  PHY_LONE_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
+/*****  PHY_MARV_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
+								/* Bit 15..5:	reserved */
+#define PHY_ANE_PAR_DF	(1<<4)	/* Bit  4:	Parallel Detection Fault */
+/*	PHY_ANE_LP_NP		(see XMAC) Bit  3:	Link Partner can Next Page */
+/*	PHY_ANE_LOC_NP		(see XMAC) Bit  2:	Local PHY can Next Page */
+/*	PHY_ANE_RX_PG		(see XMAC) Bit  1:	Page Received */
+#define PHY_ANE_LP_CAP	(1<<0)	/* Bit  0:	Link Partner Auto-Neg. Able */ 	
+
+/*****  PHY_XMAC_NEPG		16 bit r/w	Next Page Register *****/
+/*****  PHY_BCOM_NEPG		16 bit r/w	Next Page Register *****/
+/*****  PHY_LONE_NEPG		16 bit r/w	Next Page Register *****/
+/*****  PHY_XMAC_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
+/*****  PHY_BCOM_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
+/*****  PHY_LONE_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
+#define PHY_NP_MORE		(1<<15)	/* Bit 15:	More, Next Pages to follow */
+#define PHY_NP_ACK1		(1<<14)	/* Bit 14: (ro)	Ack1, for receiving a message */
+#define PHY_NP_MSG_VAL	(1<<13)	/* Bit 13:	Message Page valid */
+#define PHY_NP_ACK2		(1<<12)	/* Bit 12:	Ack2, comply with msg content */
+#define PHY_NP_TOG		(1<<11)	/* Bit 11:	Toggle Bit, ensure sync */
+#define PHY_NP_MSG		0x07ff	/* Bit 10..0:	Message from/to Link Partner */
+
+/*
+ * XMAC-Specific
+ */
+/*****  PHY_XMAC_EXT_STAT	16 bit r/w	Extended Status Register *****/
+#define PHY_X_EX_FD		(1<<15)	/* Bit 15:	Device Supports Full Duplex */
+#define PHY_X_EX_HD		(1<<14)	/* Bit 14:	Device Supports Half Duplex */
+								/* Bit 13..0:	reserved */
+
+/*****  PHY_XMAC_RES_ABI	16 bit r/o	PHY Resolved Ability *****/
+								/* Bit 15..9:	reserved */
+#define PHY_X_RS_PAUSE	(3<<7)	/* Bit  8..7:	selected Pause Mode */
+#define PHY_X_RS_HD		(1<<6)	/* Bit  6:	Half Duplex Mode selected */
+#define PHY_X_RS_FD		(1<<5)	/* Bit  5:	Full Duplex Mode selected */
+#define PHY_X_RS_ABLMIS (1<<4)	/* Bit  4:	duplex or pause cap mismatch */
+#define PHY_X_RS_PAUMIS (1<<3)	/* Bit  3:	pause capability mismatch */
+								/* Bit  2..0:	reserved */
+/*
+ * Remote Fault Bits (PHY_X_AN_RFB) encoding
+ */
+#define X_RFB_OK		(0<<12)	/* Bit 13..12	No errors, Link OK */
+#define X_RFB_LF		(1<<12)	/* Bit 13..12	Link Failure */
+#define X_RFB_OFF		(2<<12)	/* Bit 13..12	Offline */
+#define X_RFB_AN_ERR	(3<<12)	/* Bit 13..12	Auto-Negotiation Error */
+
+/*
+ * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding
+ */
+#define PHY_X_P_NO_PAUSE	(0<<7)	/* Bit  8..7:	no Pause Mode */
+#define PHY_X_P_SYM_MD		(1<<7)	/* Bit  8..7:	symmetric Pause Mode */
+#define PHY_X_P_ASYM_MD		(2<<7)	/* Bit  8..7:	asymmetric Pause Mode */
+#define PHY_X_P_BOTH_MD		(3<<7)	/* Bit  8..7:	both Pause Mode */
+
+
+/*
+ * Broadcom-Specific
+ */
+/*****  PHY_BCOM_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+#define PHY_B_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
+#define PHY_B_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
+#define PHY_B_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
+#define PHY_B_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
+#define PHY_B_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
+#define PHY_B_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
+									/* Bit  7..0:	reserved */
+
+/*****  PHY_BCOM_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+/*****  PHY_MARV_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+#define PHY_B_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
+#define PHY_B_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
+#define PHY_B_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
+#define PHY_B_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
+#define PHY_B_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
+#define PHY_B_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
+									/* Bit  9..8:	reserved */
+#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
+
+/*****  PHY_BCOM_EXT_STAT	16 bit r/o	Extended Status Register *****/
+#define PHY_B_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
+#define PHY_B_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
+#define PHY_B_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
+#define PHY_B_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
+									/* Bit 11..0:	reserved */
+
+/*****  PHY_BCOM_P_EXT_CTRL	16 bit r/w	PHY Extended Control Reg *****/
+#define PHY_B_PEC_MAC_PHY	(1<<15)	/* Bit 15:	10BIT/GMI-Interface */
+#define PHY_B_PEC_DIS_CROSS	(1<<14)	/* Bit 14:	Disable MDI Crossover */
+#define PHY_B_PEC_TX_DIS	(1<<13)	/* Bit 13:	Tx output Disabled */
+#define PHY_B_PEC_INT_DIS	(1<<12)	/* Bit 12:	Interrupts Disabled */
+#define PHY_B_PEC_F_INT		(1<<11)	/* Bit 11:	Force Interrupt */
+#define PHY_B_PEC_BY_45		(1<<10)	/* Bit 10:	Bypass 4B5B-Decoder */
+#define PHY_B_PEC_BY_SCR	(1<<9)	/* Bit  9:	Bypass Scrambler */
+#define PHY_B_PEC_BY_MLT3	(1<<8)	/* Bit  8:	Bypass MLT3 Encoder */
+#define PHY_B_PEC_BY_RXA	(1<<7)	/* Bit  7:	Bypass Rx Alignm. */
+#define PHY_B_PEC_RES_SCR	(1<<6)	/* Bit  6:	Reset Scrambler */
+#define PHY_B_PEC_EN_LTR	(1<<5)	/* Bit  5:	Enable LED Traffic Mode */
+#define PHY_B_PEC_LED_ON	(1<<4)	/* Bit  4:	Force LED's on */
+#define PHY_B_PEC_LED_OFF	(1<<3)	/* Bit  3:	Force LED's off */
+#define PHY_B_PEC_EX_IPG	(1<<2)	/* Bit  2:	Extend Tx IPG Mode */
+#define PHY_B_PEC_3_LED		(1<<1)	/* Bit  1:	Three Link LED mode */
+#define PHY_B_PEC_HIGH_LA	(1<<0)	/* Bit  0:	GMII FIFO Elasticy */
+
+/*****  PHY_BCOM_P_EXT_STAT	16 bit r/o	PHY Extended Status Reg *****/
+									/* Bit 15..14:	reserved */
+#define PHY_B_PES_CROSS_STAT	(1<<13)	/* Bit 13:	MDI Crossover Status */
+#define PHY_B_PES_INT_STAT	(1<<12)	/* Bit 12:	Interrupt Status */
+#define PHY_B_PES_RRS		(1<<11)	/* Bit 11:	Remote Receiver Stat. */
+#define PHY_B_PES_LRS		(1<<10)	/* Bit 10:	Local Receiver Stat. */
+#define PHY_B_PES_LOCKED	(1<<9)	/* Bit  9:	Locked */
+#define PHY_B_PES_LS		(1<<8)	/* Bit  8:	Link Status */
+#define PHY_B_PES_RF		(1<<7)	/* Bit  7:	Remote Fault */
+#define PHY_B_PES_CE_ER		(1<<6)	/* Bit  6:	Carrier Ext Error */
+#define PHY_B_PES_BAD_SSD	(1<<5)	/* Bit  5:	Bad SSD */
+#define PHY_B_PES_BAD_ESD	(1<<4)	/* Bit  4:	Bad ESD */
+#define PHY_B_PES_RX_ER		(1<<3)	/* Bit  3:	Receive Error */
+#define PHY_B_PES_TX_ER		(1<<2)	/* Bit  2:	Transmit Error */
+#define PHY_B_PES_LOCK_ER	(1<<1)	/* Bit  1:	Lock Error */
+#define PHY_B_PES_MLT3_ER	(1<<0)	/* Bit  0:	MLT3 code Error */
+
+/*****  PHY_BCOM_FC_CTR		16 bit r/w	False Carrier Counter *****/
+									/* Bit 15..8:	reserved */
+#define PHY_B_FC_CTR		0xff	/* Bit  7..0:	False Carrier Counter */
+
+/*****  PHY_BCOM_RNO_CTR	16 bit r/w	Receive NOT_OK Counter *****/
+#define PHY_B_RC_LOC_MSK	0xff00	/* Bit 15..8:	Local Rx NOT_OK cnt */
+#define PHY_B_RC_REM_MSK	0x00ff	/* Bit  7..0:	Remote Rx NOT_OK cnt */
+
+/*****  PHY_BCOM_AUX_CTRL	16 bit r/w	Auxiliary Control Reg *****/
+#define PHY_B_AC_L_SQE		(1<<15)	/* Bit 15:	Low Squelch */
+#define PHY_B_AC_LONG_PACK	(1<<14)	/* Bit 14:	Rx Long Packets */
+#define PHY_B_AC_ER_CTRL	(3<<12)	/* Bit 13..12:	Edgerate Control */
+									/* Bit 11:	reserved */
+#define PHY_B_AC_TX_TST		(1<<10) /* Bit 10:	Tx test bit, always 1 */
+									/* Bit  9.. 8:	reserved */
+#define PHY_B_AC_DIS_PRF	(1<<7)	/* Bit  7:	dis part resp filter */
+									/* Bit  6:	reserved */
+#define PHY_B_AC_DIS_PM		(1<<5)	/* Bit  5:	dis power management */
+									/* Bit  4:	reserved */
+#define PHY_B_AC_DIAG		(1<<3)	/* Bit  3:	Diagnostic Mode */
+									/* Bit  2.. 0:	reserved */
+
+/*****  PHY_BCOM_AUX_STAT	16 bit r/o	Auxiliary Status Reg *****/
+#define PHY_B_AS_AN_C		(1<<15)	/* Bit 15:	AutoNeg complete */
+#define PHY_B_AS_AN_CA		(1<<14)	/* Bit 14:	AN Complete Ack */
+#define PHY_B_AS_ANACK_D	(1<<13)	/* Bit 13:	AN Ack Detect */
+#define PHY_B_AS_ANAB_D		(1<<12)	/* Bit 12:	AN Ability Detect */
+#define PHY_B_AS_NPW		(1<<11)	/* Bit 11:	AN Next Page Wait */
+#define PHY_B_AS_AN_RES_MSK	(7<<8)	/* Bit 10..8:	AN HDC */
+#define PHY_B_AS_PDF		(1<<7)	/* Bit  7:	Parallel Detect. Fault */
+#define PHY_B_AS_RF			(1<<6)	/* Bit  6:	Remote Fault */
+#define PHY_B_AS_ANP_R		(1<<5)	/* Bit  5:	AN Page Received */
+#define PHY_B_AS_LP_ANAB	(1<<4)	/* Bit  4:	LP AN Ability */
+#define PHY_B_AS_LP_NPAB	(1<<3)	/* Bit  3:	LP Next Page Ability */
+#define PHY_B_AS_LS			(1<<2)	/* Bit  2:	Link Status */
+#define PHY_B_AS_PRR		(1<<1)	/* Bit  1:	Pause Resolution-Rx */
+#define PHY_B_AS_PRT		(1<<0)	/* Bit  0:	Pause Resolution-Tx */
+
+#define PHY_B_AS_PAUSE_MSK	(PHY_B_AS_PRR | PHY_B_AS_PRT)
+
+/*****  PHY_BCOM_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
+/*****  PHY_BCOM_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
+									/* Bit 15:	reserved */
+#define PHY_B_IS_PSE		(1<<14)	/* Bit 14:	Pair Swap Error */
+#define PHY_B_IS_MDXI_SC	(1<<13)	/* Bit 13:	MDIX Status Change */
+#define PHY_B_IS_HCT		(1<<12)	/* Bit 12:	counter above 32k */
+#define PHY_B_IS_LCT		(1<<11)	/* Bit 11:	counter above 128 */
+#define PHY_B_IS_AN_PR		(1<<10)	/* Bit 10:	Page Received */
+#define PHY_B_IS_NO_HDCL	(1<<9)	/* Bit  9:	No HCD Link */
+#define PHY_B_IS_NO_HDC		(1<<8)	/* Bit  8:	No HCD */
+#define PHY_B_IS_NEG_USHDC	(1<<7)	/* Bit  7:	Negotiated Unsup. HCD */
+#define PHY_B_IS_SCR_S_ER	(1<<6)	/* Bit  6:	Scrambler Sync Error */
+#define PHY_B_IS_RRS_CHANGE	(1<<5)	/* Bit  5:	Remote Rx Stat Change */
+#define PHY_B_IS_LRS_CHANGE	(1<<4)	/* Bit  4:	Local Rx Stat Change */
+#define PHY_B_IS_DUP_CHANGE	(1<<3)	/* Bit  3:	Duplex Mode Change */
+#define PHY_B_IS_LSP_CHANGE	(1<<2)	/* Bit  2:	Link Speed Change */
+#define PHY_B_IS_LST_CHANGE	(1<<1)	/* Bit  1:	Link Status Changed */
+#define PHY_B_IS_CRC_ER		(1<<0)	/* Bit  0:	CRC Error */
+
+#define PHY_B_DEF_MSK	(~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
+
+/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
+#define PHY_B_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
+#define PHY_B_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
+#define PHY_B_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
+#define PHY_B_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
+
+/*
+ * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
+ */
+#define PHY_B_RES_1000FD	(7<<8)	/* Bit 10..8:	1000Base-T Full Dup. */
+#define PHY_B_RES_1000HD	(6<<8)	/* Bit 10..8:	1000Base-T Half Dup. */
+/* others: 100/10: invalid for us */
+
+/*
+ * Level One-Specific
+ */
+/*****  PHY_LONE_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+#define PHY_L_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
+#define PHY_L_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
+#define PHY_L_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
+#define PHY_L_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
+#define PHY_L_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
+#define PHY_L_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
+									/* Bit  7..0:	reserved */
+
+/*****  PHY_LONE_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+#define PHY_L_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
+#define PHY_L_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
+#define PHY_L_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
+#define PHY_L_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
+#define PHY_L_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
+#define PHY_L_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
+									/* Bit  9..8:	reserved */
+#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
+
+/*****  PHY_LONE_EXT_STAT	16 bit r/o	Extended Status Register *****/
+#define PHY_L_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
+#define PHY_L_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
+#define PHY_L_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
+#define PHY_L_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
+									/* Bit 11..0:	reserved */
+
+/*****  PHY_LONE_PORT_CFG	16 bit r/w	Port Configuration Reg *****/
+#define PHY_L_PC_REP_MODE	(1<<15)	/* Bit 15:	Repeater Mode */
+									/* Bit 14:	reserved */
+#define PHY_L_PC_TX_DIS		(1<<13)	/* Bit 13:	Tx output Disabled */
+#define PHY_L_PC_BY_SCR		(1<<12)	/* Bit 12:	Bypass Scrambler */
+#define PHY_L_PC_BY_45		(1<<11)	/* Bit 11:	Bypass 4B5B-Decoder */
+#define PHY_L_PC_JAB_DIS	(1<<10)	/* Bit 10:	Jabber Disabled */
+#define PHY_L_PC_SQE		(1<<9)	/* Bit  9:	Enable Heartbeat */
+#define PHY_L_PC_TP_LOOP	(1<<8)	/* Bit  8:	TP Loopback */
+#define PHY_L_PC_SSS		(1<<7)	/* Bit  7:	Smart Speed Selection */
+#define PHY_L_PC_FIFO_SIZE	(1<<6)	/* Bit  6:	FIFO Size */
+#define PHY_L_PC_PRE_EN		(1<<5)	/* Bit  5:	Preamble Enable */
+#define PHY_L_PC_CIM		(1<<4)	/* Bit  4:	Carrier Integrity Mon */
+#define PHY_L_PC_10_SER		(1<<3)	/* Bit  3:	Use Serial Output */
+#define PHY_L_PC_ANISOL		(1<<2)	/* Bit  2:	Unisolate Port */
+#define PHY_L_PC_TEN_BIT	(1<<1)	/* Bit  1:	10bit iface mode on */
+#define PHY_L_PC_ALTCLOCK	(1<<0)	/* Bit  0: (ro)	ALTCLOCK Mode on */
+
+/*****  PHY_LONE_Q_STAT		16 bit r/o	Quick Status Reg *****/
+#define PHY_L_QS_D_RATE		(3<<14)	/* Bit 15..14:	Data Rate */
+#define PHY_L_QS_TX_STAT	(1<<13)	/* Bit 13:	Transmitting */
+#define PHY_L_QS_RX_STAT	(1<<12)	/* Bit 12:	Receiving */
+#define PHY_L_QS_COL_STAT	(1<<11)	/* Bit 11:	Collision */
+#define PHY_L_QS_L_STAT		(1<<10)	/* Bit 10:	Link is up */
+#define PHY_L_QS_DUP_MOD	(1<<9)	/* Bit  9:	Full/Half Duplex */
+#define PHY_L_QS_AN			(1<<8)	/* Bit  8:	AutoNeg is On */
+#define PHY_L_QS_AN_C		(1<<7)	/* Bit  7:	AN is Complete */
+#define PHY_L_QS_LLE		(7<<4)	/* Bit  6..4:	Line Length Estim. */
+#define PHY_L_QS_PAUSE		(1<<3)	/* Bit  3:	LP advertised Pause */
+#define PHY_L_QS_AS_PAUSE	(1<<2)	/* Bit  2:	LP adv. asym. Pause */
+#define PHY_L_QS_ISOLATE	(1<<1)	/* Bit  1:	CIM Isolated */
+#define PHY_L_QS_EVENT		(1<<0)	/* Bit  0:	Event has occurred */
+
+/*****  PHY_LONE_INT_ENAB	16 bit r/w	Interrupt Enable Reg *****/
+/*****  PHY_LONE_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
+									/* Bit 15..14:	reserved */
+#define PHY_L_IS_AN_F		(1<<13)	/* Bit 13:	Auto-Negotiation fault */
+									/* Bit 12:	not described */
+#define PHY_L_IS_CROSS		(1<<11)	/* Bit 11:	Crossover used */
+#define PHY_L_IS_POL		(1<<10)	/* Bit 10:	Polarity correct. used */
+#define PHY_L_IS_SS			(1<<9)	/* Bit  9:	Smart Speed Downgrade */
+#define PHY_L_IS_CFULL		(1<<8)	/* Bit  8:	Counter Full */
+#define PHY_L_IS_AN_C		(1<<7)	/* Bit  7:	AutoNeg Complete */
+#define PHY_L_IS_SPEED		(1<<6)	/* Bit  6:	Speed Changed */
+#define PHY_L_IS_DUP		(1<<5)	/* Bit  5:	Duplex Changed */
+#define PHY_L_IS_LS			(1<<4)	/* Bit  4:	Link Status Changed */
+#define PHY_L_IS_ISOL		(1<<3)	/* Bit  3:	Isolate Occured */
+#define PHY_L_IS_MDINT		(1<<2)	/* Bit  2: (ro)	STAT: MII Int Pending */
+#define PHY_L_IS_INTEN		(1<<1)	/* Bit  1:	ENAB: Enable IRQs */
+#define PHY_L_IS_FORCE		(1<<0)	/* Bit  0:	ENAB: Force Interrupt */
+
+/* int. mask */
+#define PHY_L_DEF_MSK		(PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
+
+/*****  PHY_LONE_LED_CFG	16 bit r/w	LED Configuration Reg *****/
+#define PHY_L_LC_LEDC		(3<<14)	/* Bit 15..14:	Col/Blink/On/Off */
+#define PHY_L_LC_LEDR		(3<<12)	/* Bit 13..12:	Rx/Blink/On/Off */
+#define PHY_L_LC_LEDT		(3<<10)	/* Bit 11..10:	Tx/Blink/On/Off */
+#define PHY_L_LC_LEDG		(3<<8)	/* Bit  9..8:	Giga/Blink/On/Off */
+#define PHY_L_LC_LEDS		(3<<6)	/* Bit  7..6:	10-100/Blink/On/Off */
+#define PHY_L_LC_LEDL		(3<<4)	/* Bit  5..4:	Link/Blink/On/Off */
+#define PHY_L_LC_LEDF		(3<<2)	/* Bit  3..2:	Duplex/Blink/On/Off */
+#define PHY_L_LC_PSTRECH	(1<<1)	/* Bit  1:	Strech LED Pulses */
+#define PHY_L_LC_FREQ		(1<<0)	/* Bit  0:	30/100 ms */
+
+/*****  PHY_LONE_PORT_CTRL	16 bit r/w	Port Control Reg *****/
+#define PHY_L_PC_TX_TCLK	(1<<15)	/* Bit 15:	Enable TX_TCLK */
+									/* Bit 14:	reserved */
+#define PHY_L_PC_ALT_NP		(1<<13)	/* Bit 14:	Alternate Next Page */
+#define PHY_L_PC_GMII_ALT	(1<<12)	/* Bit 13:	Alternate GMII driver */
+									/* Bit 11:	reserved */
+#define PHY_L_PC_TEN_CRS	(1<<10)	/* Bit 10:	Extend CRS*/
+									/* Bit  9..0:	not described */
+
+/*****  PHY_LONE_CIM		16 bit r/o	CIM Reg *****/
+#define PHY_L_CIM_ISOL		(0xff<<8)	/* Bit 15..8:	Isolate Count */
+#define PHY_L_CIM_FALSE_CAR	0xff		/* Bit  7..0:	False Carrier Count */
+
+/*
+ * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
+ */
+#define PHY_L_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
+#define PHY_L_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
+#define PHY_L_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
+#define PHY_L_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
+
+/*
+ * National-Specific
+ */
+/*****  PHY_NAT_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+#define PHY_N_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
+#define PHY_N_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
+#define PHY_N_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
+#define PHY_N_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
+#define PHY_N_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
+#define PHY_N_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
+#define PHY_N_1000C_APC		(1<<7)	/* Bit  7:	Asymmetric Pause Cap. */
+									/* Bit  6..0:	reserved */
+
+/*****  PHY_NAT_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+#define PHY_N_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
+#define PHY_N_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
+#define PHY_N_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
+#define PHY_N_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status*/
+#define PHY_N_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
+#define PHY_N_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
+#define PHY_N_1000C_LP_APC	(1<<9)	/* Bit  9:	LP Asym. Pause Cap. */
+									/* Bit  8:	reserved */
+#define PHY_N_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
+
+/*****  PHY_NAT_EXT_STAT	16 bit r/o	Extended Status Register *****/
+#define PHY_N_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
+#define PHY_N_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
+#define PHY_N_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
+#define PHY_N_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
+									/* Bit 11..0:	reserved */
+
+/* todo: those are still missing */
+/*****  PHY_NAT_EXT_CTRL1	16 bit r/o	Extended Control Reg1 *****/
+/*****  PHY_NAT_Q_STAT1		16 bit r/o	Quick Status Reg1 *****/
+/*****  PHY_NAT_10B_OP		16 bit r/o	10Base-T Operations Reg *****/
+/*****  PHY_NAT_EXT_CTRL2	16 bit r/o	Extended Control Reg1 *****/
+/*****  PHY_NAT_Q_STAT2		16 bit r/o	Quick Status Reg2 *****/
+/*****  PHY_NAT_PHY_ADDR	16 bit r/o	PHY Address Register *****/
+
+/*
+ * Marvell-Specific
+ */
+/*****  PHY_MARV_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+/*****  PHY_MARV_AUNE_LP	16 bit r/w	Link Partner Ability Reg *****/
+#define PHY_M_AN_NXT_PG		BIT_15S	/* Request Next Page */
+#define PHY_M_AN_ACK		BIT_14S	/* (ro)	Acknowledge Received */
+#define PHY_M_AN_RF			BIT_13S	/* Remote Fault */
+								/* Bit 12:	reserved */
+#define PHY_M_AN_ASP		BIT_11S	/* Asymmetric Pause */
+#define PHY_M_AN_PC			BIT_10S	/* MAC Pause implemented */
+#define PHY_M_AN_100_T4		BIT_9S	/* Not cap. 100Base-T4 (always 0) */
+#define PHY_M_AN_100_FD		BIT_8S	/* Advertise 100Base-TX Full Duplex */
+#define PHY_M_AN_100_HD		BIT_7S	/* Advertise 100Base-TX Half Duplex */
+#define PHY_M_AN_10_FD		BIT_6S	/* Advertise 10Base-TX Full Duplex */
+#define PHY_M_AN_10_HD		BIT_5S	/* Advertise 10Base-TX Half Duplex */
+#define PHY_M_AN_SEL_MSK	(0x1f<<4)	/* Bit  4.. 0: Selector Field Mask */
+
+/* special defines for FIBER (88E1040S only) */
+#define PHY_M_AN_ASP_X		BIT_8S	/* Asymmetric Pause */
+#define PHY_M_AN_PC_X		BIT_7S	/* MAC Pause implemented */
+#define PHY_M_AN_1000X_AHD	BIT_6S	/* Advertise 10000Base-X Half Duplex */
+#define PHY_M_AN_1000X_AFD	BIT_5S	/* Advertise 10000Base-X Full Duplex */
+
+/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+#define PHY_M_P_NO_PAUSE_X	(0<<7)	/* Bit  8.. 7:	no Pause Mode */
+#define PHY_M_P_SYM_MD_X	(1<<7)	/* Bit  8.. 7:	symmetric Pause Mode */
+#define PHY_M_P_ASYM_MD_X	(2<<7)	/* Bit  8.. 7:	asymmetric Pause Mode */
+#define PHY_M_P_BOTH_MD_X	(3<<7)	/* Bit  8.. 7:	both Pause Mode */
+
+/*****  PHY_MARV_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+#define PHY_M_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
+#define PHY_M_1000C_MSE		BIT_12S	/* Manual Master/Slave Enable */
+#define PHY_M_1000C_MSC		BIT_11S	/* M/S Configuration (1=Master) */
+#define PHY_M_1000C_MPD		BIT_10S	/* Multi-Port Device */
+#define PHY_M_1000C_AFD		BIT_9S	/* Advertise Full Duplex */
+#define PHY_M_1000C_AHD		BIT_8S	/* Advertise Half Duplex */
+									/* Bit  7..0:	reserved */
+
+/*****  PHY_MARV_PHY_CTRL	16 bit r/w	PHY Specific Ctrl Reg *****/
+#define PHY_M_PC_TX_FFD_MSK	(3<<14)	/* Bit 15..14: Tx FIFO Depth Mask */
+#define PHY_M_PC_RX_FFD_MSK	(3<<12)	/* Bit 13..12: Rx FIFO Depth Mask */
+#define PHY_M_PC_ASS_CRS_TX	BIT_11S	/* Assert CRS on Transmit */
+#define PHY_M_PC_FL_GOOD	BIT_10S	/* Force Link Good */
+#define PHY_M_PC_EN_DET_MSK	(3<<8)	/* Bit  9.. 8: Energy Detect Mask */
+#define PHY_M_PC_ENA_EXT_D	BIT_7S	/* Enable Ext. Distance (10BT) */
+#define PHY_M_PC_MDIX_MSK	(3<<5)	/* Bit  6.. 5: MDI/MDIX Config. Mask */
+#define PHY_M_PC_DIS_125CLK	BIT_4S	/* Disable 125 CLK */
+#define PHY_M_PC_MAC_POW_UP	BIT_3S	/* MAC Power up */
+#define PHY_M_PC_SQE_T_ENA	BIT_2S	/* SQE Test Enabled */
+#define PHY_M_PC_POL_R_DIS	BIT_1S	/* Polarity Reversal Disabled */
+#define PHY_M_PC_DIS_JABBER	BIT_0S	/* Disable Jabber */
+
+#define PHY_M_PC_EN_DET			SHIFT8(2)	/* Energy Detect (Mode 1) */
+#define PHY_M_PC_EN_DET_PLUS	SHIFT8(3)	/* Energy Detect Plus (Mode 2) */
+
+#define PHY_M_PC_MDI_XMODE(x)	(SHIFT5(x) & PHY_M_PC_MDIX_MSK)	
+
+#define PHY_M_PC_MAN_MDI	0		/* 00 = Manual MDI configuration */
+#define PHY_M_PC_MAN_MDIX	1		/* 01 = Manual MDIX configuration */
+#define PHY_M_PC_ENA_AUTO	3		/* 11 = Enable Automatic Crossover */
+
+/* for Yukon-2/-EC Ultra Gigabit Ethernet PHY (88E1112/88E1149 only) */
+#define PHY_M_PC_DIS_LINK_P	BIT_15S	/* Disable Link Pulses */
+#define PHY_M_PC_DSC_MSK	(7<<12)	/* Bit 14..12:	Downshift Counter */
+#define PHY_M_PC_DOWN_S_ENA	BIT_11S	/* Downshift Enable */
+									/* !!! Errata in spec. (1 = disable) */
+
+#define PHY_M_PC_DSC(x)			(SHIFT12(x) & PHY_M_PC_DSC_MSK)
+										/* 000=1x; 001=2x; 010=3x; 011=4x */
+										/* 100=5x; 101=6x; 110=7x; 111=8x */
+
+/* for Yukon-EC Ultra Gigabit Ethernet PHY (88E1149 only) */
+								/* Bit  4:	reserved */
+#define PHY_M_PC_COP_TX_DIS	BIT_3S	/* Copper Transmitter Disable */
+#define PHY_M_PC_POW_D_ENA	BIT_2S	/* Power Down Enable */
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+#define PHY_M_PC_ENA_DTE_DT	BIT_15S	/* Enable Data Terminal Equ. (DTE) Detect */
+#define PHY_M_PC_ENA_ENE_DT	BIT_14S	/* Enable Energy Detect (sense & pulse) */
+#define PHY_M_PC_DIS_NLP_CK	BIT_13S	/* Disable Normal Link Puls (NLP) Check */
+#define PHY_M_PC_ENA_LIP_NP	BIT_12S	/* Enable Link Partner Next Page Reg. */
+#define PHY_M_PC_DIS_NLP_GN	BIT_11S	/* Disable Normal Link Puls Generation */
+
+#define PHY_M_PC_DIS_SCRAMB	BIT_9S	/* Disable Scrambler */
+#define PHY_M_PC_DIS_FEFI	BIT_8S	/* Disable Far End Fault Indic. (FEFI) */
+
+#define PHY_M_PC_SH_TP_SEL	BIT_6S	/* Shielded Twisted Pair Select */
+#define PHY_M_PC_RX_FD_MSK	(3<<2)	/* Bit  3.. 2: Rx FIFO Depth Mask */
+
+/*****  PHY_MARV_PHY_STAT	16 bit r/o	PHY Specific Status Reg *****/
+#define PHY_M_PS_SPEED_MSK	(3<<14)	/* Bit 15..14: Speed Mask */
+#define PHY_M_PS_SPEED_1000	BIT_15S	/*		10 = 1000 Mbps */
+#define PHY_M_PS_SPEED_100	BIT_14S	/*		01 =  100 Mbps */
+#define PHY_M_PS_SPEED_10	0		/*		00 =   10 Mbps */
+#define PHY_M_PS_FULL_DUP	BIT_13S	/* Full Duplex */
+#define PHY_M_PS_PAGE_REC	BIT_12S	/* Page Received */
+#define PHY_M_PS_SPDUP_RES	BIT_11S	/* Speed & Duplex Resolved */
+#define PHY_M_PS_LINK_UP	BIT_10S	/* Link Up */
+#define PHY_M_PS_CABLE_MSK	(7<<7)	/* Bit  9.. 7: Cable Length Mask */
+#define PHY_M_PS_MDI_X_STAT	BIT_6S	/* MDI Crossover Stat (1=MDIX) */
+#define PHY_M_PS_DOWNS_STAT	BIT_5S	/* Downshift Status (1=downshift) */
+#define PHY_M_PS_ENDET_STAT	BIT_4S	/* Energy Detect Status (1=sleep) */
+#define PHY_M_PS_TX_P_EN	BIT_3S	/* Tx Pause Enabled */
+#define PHY_M_PS_RX_P_EN	BIT_2S	/* Rx Pause Enabled */
+#define PHY_M_PS_POL_REV	BIT_1S	/* Polarity Reversed */
+#define PHY_M_PS_JABBER		BIT_0S	/* Jabber */
+
+#define PHY_M_PS_PAUSE_MSK	(PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+#define PHY_M_PS_DTE_DETECT	BIT_15S	/* Data Terminal Equipment (DTE) Detected */
+#define PHY_M_PS_RES_SPEED	BIT_14S	/* Resolved Speed (1=100 Mbps, 0=10 Mbps */
+
+/*****  PHY_MARV_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
+/*****  PHY_MARV_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
+#define PHY_M_IS_AN_ERROR	BIT_15S	/* Auto-Negotiation Error */
+#define PHY_M_IS_LSP_CHANGE	BIT_14S	/* Link Speed Changed */
+#define PHY_M_IS_DUP_CHANGE	BIT_13S	/* Duplex Mode Changed */
+#define PHY_M_IS_AN_PR		BIT_12S	/* Page Received */
+#define PHY_M_IS_AN_COMPL	BIT_11S	/* Auto-Negotiation Completed */
+#define PHY_M_IS_LST_CHANGE	BIT_10S	/* Link Status Changed */
+#define PHY_M_IS_SYMB_ERROR	BIT_9S	/* Symbol Error */
+#define PHY_M_IS_FALSE_CARR	BIT_8S	/* False Carrier */
+#define PHY_M_IS_FIFO_ERROR	BIT_7S	/* FIFO Overflow/Underrun Error */
+#define PHY_M_IS_MDI_CHANGE	BIT_6S	/* MDI Crossover Changed */
+#define PHY_M_IS_DOWNSH_DET	BIT_5S	/* Downshift Detected */
+#define PHY_M_IS_END_CHANGE	BIT_4S	/* Energy Detect Changed */
+								/* Bit   3:	reserved */
+#define PHY_M_IS_DTE_CHANGE	BIT_2S	/* DTE Power Det. Status Changed */
+									/* (88E1111 only) */
+#define PHY_M_IS_POL_CHANGE	BIT_1S	/* Polarity Changed */
+#define PHY_M_IS_JABBER		BIT_0S	/* Jabber */
+
+#define PHY_M_DEF_MSK		(PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
+							PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR | \
+							PHY_M_IS_END_CHANGE)
+
+/*****  PHY_MARV_EXT_CTRL	16 bit r/w	Ext. PHY Specific Ctrl *****/
+#define PHY_M_EC_ENA_BC_EXT	BIT_15S	/* Enable Block Carr. Ext. (88E1111 only) */
+#define PHY_M_EC_ENA_LIN_LB	BIT_14S	/* Enable Line Loopback (88E1111 only) */
+								/* Bit 13:	reserved */
+#define PHY_M_EC_DIS_LINK_P	BIT_12S	/* Disable Link Pulses (88E1111 only) */
+#define PHY_M_EC_M_DSC_MSK	(3<<10)	/* Bit 11..10:	Master Downshift Counter */
+									/* (88E1040 Rev.C0 only) */
+#define PHY_M_EC_S_DSC_MSK	(3<<8)	/* Bit  9.. 8:	Slave  Downshift Counter */
+									/* (88E1040 Rev.C0 only) */
+#define PHY_M_EC_DSC_MSK_2	(7<<9)	/* Bit 11.. 9:	Downshift Counter */
+									/* (88E1040 Rev.D0 and higher) */
+#define PHY_M_EC_DOWN_S_ENA	BIT_8S	/* Downshift Enable (88E1040 Rev.D0 and */
+									/* 88E1111 !!! Errata in spec. (1=dis.) */
+#define PHY_M_EC_RX_TIM_CT	BIT_7S	/* RGMII Rx Timing Control*/
+#define PHY_M_EC_MAC_S_MSK	(7<<4)	/* Bit  6.. 4:	Def. MAC interface speed */
+#define PHY_M_EC_FIB_AN_ENA	BIT_3S	/* Fiber Auto-Neg. Enable 88E1040S only) */
+#define PHY_M_EC_DTE_D_ENA	BIT_2S	/* DTE Detect Enable (88E1111 only) */
+#define PHY_M_EC_TX_TIM_CT	BIT_1S	/* RGMII Tx Timing Control */
+#define PHY_M_EC_TRANS_DIS	BIT_0S	/* Transmitter Disable (88E1111 only) */
+
+#define PHY_M_EC_M_DSC(x)		(SHIFT10(x) & PHY_M_EC_M_DSC_MSK)
+									/* 00=1x; 01=2x; 10=3x; 11=4x */
+#define PHY_M_EC_S_DSC(x)		(SHIFT8(x) & PHY_M_EC_S_DSC_MSK)
+									/* 00=dis; 01=1x; 10=2x; 11=3x */
+#define PHY_M_EC_MAC_S(x)		(SHIFT4(x) & PHY_M_EC_MAC_S_MSK)
+									/* 01X=0; 110=2.5; 111=25 (MHz) */
+
+#define PHY_M_EC_DSC_2(x)		(SHIFT9(x) & PHY_M_EC_DSC_MSK_2)
+									/* 000=1x; 001=2x; 010=3x; 011=4x */
+									/* 100=5x; 101=6x; 110=7x; 111=8x */
+#define MAC_TX_CLK_0_MHZ	2
+#define MAC_TX_CLK_2_5_MHZ	6
+#define MAC_TX_CLK_25_MHZ	7
+
+/*****  PHY_MARV_LED_CTRL	16 bit r/w	LED Control Reg *****/
+#define PHY_M_LEDC_DIS_LED	BIT_15S	/* Disable LED */
+#define PHY_M_LEDC_PULS_MSK	(7<<12)	/* Bit 14..12: Pulse Stretch Mask */
+#define PHY_M_LEDC_F_INT	BIT_11S	/* Force Interrupt */
+#define PHY_M_LEDC_BL_R_MSK	(7<<8)	/* Bit 10.. 8: Blink Rate Mask */
+#define PHY_M_LEDC_DP_C_LSB	BIT_7S	/* Duplex Control (LSB, 88E1111 only) */
+#define PHY_M_LEDC_TX_C_LSB	BIT_6S	/* Tx Control (LSB, 88E1111 only) */
+#define PHY_M_LEDC_LK_C_MSK	(7<<3)	/* Bit  5.. 3: Link Control Mask */
+									/* (88E1111 only) */
+								/* Bit  7.. 5:	reserved (88E1040 only) */
+#define PHY_M_LEDC_LINK_MSK	(3<<3)	/* Bit  4.. 3: Link Control Mask */
+									/* (88E1040 only) */
+#define PHY_M_LEDC_DP_CTRL	BIT_2S	/* Duplex Control */
+#define PHY_M_LEDC_DP_C_MSB	BIT_2S	/* Duplex Control (MSB, 88E1111 only) */
+#define PHY_M_LEDC_RX_CTRL	BIT_1S	/* Rx Activity / Link */
+#define PHY_M_LEDC_TX_CTRL	BIT_0S	/* Tx Activity / Link */
+#define PHY_M_LEDC_TX_C_MSB	BIT_0S	/* Tx Control (MSB, 88E1111 only) */
+
+#define PHY_M_LED_PULS_DUR(x)	(SHIFT12(x) & PHY_M_LEDC_PULS_MSK)
+
+#define PULS_NO_STR		0		/* no pulse stretching */
+#define PULS_21MS		1		/* 21 ms to 42 ms */
+#define PULS_42MS		2		/* 42 ms to 84 ms */
+#define PULS_84MS		3		/* 84 ms to 170 ms */
+#define PULS_170MS		4		/* 170 ms to 340 ms */
+#define PULS_340MS		5		/* 340 ms to 670 ms */
+#define PULS_670MS		6		/* 670 ms to 1.3 s */
+#define PULS_1300MS		7		/* 1.3 s to 2.7 s */
+
+#define PHY_M_LED_BLINK_RT(x)	(SHIFT8(x) & PHY_M_LEDC_BL_R_MSK)
+
+#define BLINK_42MS		0		/* 42 ms */
+#define BLINK_84MS		1		/* 84 ms */
+#define BLINK_170MS		2		/* 170 ms */
+#define BLINK_340MS		3		/* 340 ms */
+#define BLINK_670MS		4		/* 670 ms */
+								/* values 5 - 7: reserved */
+
+/*****  PHY_MARV_LED_OVER	16 bit r/w	Manual LED Override Reg *****/
+#define PHY_M_LED_MO_SGMII(x)	SHIFT14(x)	/* Bit 15..14:  SGMII AN Timer */
+										/* Bit 13..12:	reserved */
+#define PHY_M_LED_MO_DUP(x)		SHIFT10(x)	/* Bit 11..10:  Duplex */
+#define PHY_M_LED_MO_10(x)		SHIFT8(x)	/* Bit  9.. 8:  Link 10 */
+#define PHY_M_LED_MO_100(x)		SHIFT6(x)	/* Bit  7.. 6:  Link 100 */
+#define PHY_M_LED_MO_1000(x)	SHIFT4(x)	/* Bit  5.. 4:  Link 1000 */
+#define PHY_M_LED_MO_RX(x)		SHIFT2(x)	/* Bit  3.. 2:  Rx */
+#define PHY_M_LED_MO_TX(x)		SHIFT0(x)	/* Bit  1.. 0:  Tx */
+
+#define MO_LED_NORM			0
+#define MO_LED_BLINK		1
+#define MO_LED_OFF			2
+#define MO_LED_ON			3
+
+/*****  PHY_MARV_EXT_CTRL_2	16 bit r/w	Ext. PHY Specific Ctrl 2 *****/
+								/* Bit 15.. 7:	reserved */
+#define PHY_M_EC2_FI_IMPED	BIT_6S	/* Fiber Input  Impedance */
+#define PHY_M_EC2_FO_IMPED	BIT_5S	/* Fiber Output Impedance */
+#define PHY_M_EC2_FO_M_CLK	BIT_4S	/* Fiber Mode Clock Enable */
+#define PHY_M_EC2_FO_BOOST	BIT_3S	/* Fiber Output Boost */
+#define PHY_M_EC2_FO_AM_MSK	7		/* Bit  2.. 0:	Fiber Output Amplitude */
+
+/*****  PHY_MARV_EXT_P_STAT 16 bit r/w	Ext. PHY Specific Status *****/
+#define PHY_M_FC_AUTO_SEL	BIT_15S	/* Fiber/Copper Auto Sel. Dis. */
+#define PHY_M_FC_AN_REG_ACC	BIT_14S	/* Fiber/Copper AN Reg. Access */
+#define PHY_M_FC_RESOLUTION	BIT_13S	/* Fiber/Copper Resolution */
+#define PHY_M_SER_IF_AN_BP	BIT_12S	/* Ser. IF AN Bypass Enable */
+#define PHY_M_SER_IF_BP_ST	BIT_11S	/* Ser. IF AN Bypass Status */
+#define PHY_M_IRQ_POLARITY	BIT_10S	/* IRQ polarity */
+#define PHY_M_DIS_AUT_MED	BIT_9S	/* Disable Aut. Medium Reg. Selection */
+									/* (88E1111 only) */
+								/* Bit  9.. 4: reserved (88E1040 only) */
+#define PHY_M_UNDOC1		BIT_7S	/* undocumented bit !! */
+#define PHY_M_DTE_POW_STAT	BIT_4S	/* DTE Power Status (88E1111 only) */
+#define PHY_M_MODE_MASK		0xf		/* Bit  3.. 0: copy of HWCFG MODE[3:0] */
+
+/*****  PHY_MARV_CABLE_DIAG	16 bit r/o	Cable Diagnostic Reg *****/
+#define PHY_M_CABD_ENA_TEST	BIT_15S		/* Enable Test (Page 0) */
+#define PHY_M_CABD_DIS_WAIT	BIT_15S		/* Disable Waiting Period (Page 1) */
+										/* (88E1111 only) */
+
+#define PHY_M_CABD_COMPLETE	BIT_14S		/* Test Completed (88E1149 only) */
+
+#define PHY_M_CABD_MODE_MSK	(3<<6)		/* Bit  7.. 6: Mode Mask */
+#define PHY_M_CABD_TEST_MODE(x)	(SHIFT6(x) & PHY_M_CABD_MODE_MSK)
+
+#define PHY_M_CABD_PWID_MSK	(3<<10)		/* Bit 11..10: Pulse Width Mask */
+#define PHY_M_CABD_PAMP_MSK	(3<<10)		/* Bit  9.. 8: Pulse Ampl. Mask */
+
+#define PHY_M_CABD_PULS_WIDT(x)	(SHIFT10(x) & PHY_M_CABD_PWID_MSK)
+#define PHY_M_CABD_PULS_AMPL(x)	(SHIFT8(x) & PHY_M_CABD_PAMP_MSK)
+
+#define PHY_M_CABD_STAT_MSK	(3<<13)		/* Bit 14..13: Status Mask */
+
+#define PHY_M_CABD_AMPL_MSK	(0x7f<<8)	/* Bit 14.. 8: Amplitude Mask */
+										/* (88E1149 only) */
+#define PHY_M_CABD_DIST_MSK	0xff		/* Bit  7.. 0: Distance Mask */
+
+/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
+#define CABD_STAT_NORMAL	0
+#define CABD_STAT_SHORT		1
+#define CABD_STAT_OPEN		2
+#define CABD_STAT_FAIL		3
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+/*****  PHY_MARV_FE_LED_PAR		16 bit r/w	LED Parallel Select Reg. *****/
+									/* Bit 15..12: reserved (used internally) */
+#define PHY_M_FELP_LED2_MSK	(0xf<<8)	/* Bit 11.. 8: LED2 Mask (LINK) */
+#define PHY_M_FELP_LED1_MSK	(0xf<<4)	/* Bit  7.. 4: LED1 Mask (ACT) */
+#define PHY_M_FELP_LED0_MSK	0xf			/* Bit  3.. 0: LED0 Mask (SPEED) */
+
+#define PHY_M_FELP_LED2_CTRL(x)	(SHIFT8(x) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x)	(SHIFT4(x) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x)	(SHIFT0(x) & PHY_M_FELP_LED0_MSK)
+
+#define LED_PAR_CTRL_COLX	0x00
+#define LED_PAR_CTRL_ERROR	0x01
+#define LED_PAR_CTRL_DUPLEX	0x02
+#define LED_PAR_CTRL_DP_COL	0x03
+#define LED_PAR_CTRL_SPEED	0x04
+#define LED_PAR_CTRL_LINK	0x05
+#define LED_PAR_CTRL_TX		0x06
+#define LED_PAR_CTRL_RX		0x07
+#define LED_PAR_CTRL_ACT	0x08
+#define LED_PAR_CTRL_LNK_RX	0x09
+#define LED_PAR_CTRL_LNK_AC	0x0a
+#define LED_PAR_CTRL_ACT_BL	0x0b
+#define LED_PAR_CTRL_TX_BL	0x0c
+#define LED_PAR_CTRL_RX_BL	0x0d
+#define LED_PAR_CTRL_COL_BL	0x0e
+#define LED_PAR_CTRL_INACT	0x0f
+
+/*****  PHY_MARV_FE_SPEC_2		16 bit r/w	Specific Control Reg. 2 *****/
+#define PHY_M_FESC_DIS_WAIT	BIT_2S	/* Disable TDR Waiting Period */
+#define PHY_M_FESC_ENA_MCLK	BIT_1S	/* Enable MAC Rx Clock in sleep mode */
+#define PHY_M_FESC_SEL_CL_A	BIT_0S	/* Select Class A driver (100B-TX) */
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+/*****  PHY_MARV_PHY_CTRL (page 1)		16 bit r/w	Fiber Specific Ctrl *****/
+#define PHY_M_FIB_FORCE_LNK	BIT_10S	/* Force Link Good */
+#define PHY_M_FIB_SIGD_POL	BIT_9S	/* SIGDET Polarity */
+#define PHY_M_FIB_TX_DIS	BIT_3S	/* Transmitter Disable */
+
+/*****  PHY_MARV_PHY_CTRL (page 2)		16 bit r/w	MAC Specific Ctrl *****/
+#define PHY_M_MAC_MD_MSK	(7<<7)	/* Bit  9.. 7: Mode Select Mask */
+#define PHY_M_MAC_GMIF_PUP	BIT_3S	/* GMII Power Up (88E1149 only) */
+
+#define PHY_M_MAC_MD_AUTO		3	/* Auto Copper/1000Base-X */
+#define PHY_M_MAC_MD_COPPER		5	/* Copper only */
+#define PHY_M_MAC_MD_1000BX		7	/* 1000Base-X only */
+#define PHY_M_MAC_MODE_SEL(x)	(SHIFT7(x) & PHY_M_MAC_MD_MSK)
+
+/*****  PHY_MARV_PHY_CTRL (page 3)		16 bit r/w	LED Control Reg. *****/
+#define PHY_M_LEDC_LOS_MSK	(0xf<<12)	/* Bit 15..12: LOS LED Ctrl. Mask */
+#define PHY_M_LEDC_INIT_MSK	(0xf<<8)	/* Bit 11.. 8: INIT LED Ctrl. Mask */
+#define PHY_M_LEDC_STA1_MSK	(0xf<<4)	/* Bit  7.. 4: STAT1 LED Ctrl. Mask */
+#define PHY_M_LEDC_STA0_MSK	0xf			/* Bit  3.. 0: STAT0 LED Ctrl. Mask */
+
+#define PHY_M_LEDC_LOS_CTRL(x)	(SHIFT12(x) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x)	(SHIFT8(x) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x)	(SHIFT4(x) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x)	(SHIFT0(x) & PHY_M_LEDC_STA0_MSK)
+
+/*****  PHY_MARV_PHY_STAT (page 3)		16 bit r/w	Polarity Control Reg. *****/
+#define PHY_M_POLC_LS1M_MSK	(0xf<<12)	/* Bit 15..12: LOS,STAT1 Mix % Mask */
+#define PHY_M_POLC_IS0M_MSK	(0xf<<8)	/* Bit 11.. 8: INIT,STAT0 Mix % Mask */
+#define PHY_M_POLC_LOS_MSK	(0x3<<6)	/* Bit  7.. 6: LOS Pol. Ctrl. Mask */
+#define PHY_M_POLC_INIT_MSK	(0x3<<4)	/* Bit  5.. 4: INIT Pol. Ctrl. Mask */
+#define PHY_M_POLC_STA1_MSK	(0x3<<2)	/* Bit  3.. 2: STAT1 Pol. Ctrl. Mask */
+#define PHY_M_POLC_STA0_MSK	0x3			/* Bit  1.. 0: STAT0 Pol. Ctrl. Mask */
+
+#define PHY_M_POLC_LS1_P_MIX(x)	(SHIFT12(x) & PHY_M_POLC_LS1M_MSK)
+#define PHY_M_POLC_IS0_P_MIX(x)	(SHIFT8(x) & PHY_M_POLC_IS0M_MSK)
+#define PHY_M_POLC_LOS_CTRL(x)	(SHIFT6(x) & PHY_M_POLC_LOS_MSK)
+#define PHY_M_POLC_INIT_CTRL(x)	(SHIFT4(x) & PHY_M_POLC_INIT_MSK)
+#define PHY_M_POLC_STA1_CTRL(x)	(SHIFT2(x) & PHY_M_POLC_STA1_MSK)
+#define PHY_M_POLC_STA0_CTRL(x)	(SHIFT0(x) & PHY_M_POLC_STA0_MSK)
+
+/*
+ * GMAC registers
+ *
+ * The GMAC registers are 16 or 32 bits wide.
+ * The GMACs host processor interface is 16 bits wide,
+ * therefore ALL registers will be addressed with 16 bit accesses.
+ *
+ * The following macros are provided to access the GMAC registers
+ * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(),
+ * GM_INHASH(), and GM_OUTHASH().
+ * The macros are defined in SkGeHw.h.
+ *
+ * Note:	NA reg	= Network Address e.g DA, SA etc.
+ *
+ */
+
+/* Port Registers */
+#define GM_GP_STAT		0x0000		/* 16 bit r/o	General Purpose Status */
+#define GM_GP_CTRL		0x0004		/* 16 bit r/w	General Purpose Control */
+#define GM_TX_CTRL		0x0008		/* 16 bit r/w	Transmit Control Reg. */
+#define GM_RX_CTRL		0x000c		/* 16 bit r/w	Receive Control Reg. */
+#define GM_TX_FLOW_CTRL	0x0010		/* 16 bit r/w	Transmit Flow-Control */
+#define GM_TX_PARAM		0x0014		/* 16 bit r/w	Transmit Parameter Reg. */
+#define GM_SERIAL_MODE	0x0018		/* 16 bit r/w	Serial Mode Register */
+
+/* Source Address Registers */
+#define GM_SRC_ADDR_1L	0x001c		/* 16 bit r/w	Source Address 1 (low) */
+#define GM_SRC_ADDR_1M	0x0020		/* 16 bit r/w	Source Address 1 (middle) */
+#define GM_SRC_ADDR_1H	0x0024		/* 16 bit r/w	Source Address 1 (high) */
+#define GM_SRC_ADDR_2L	0x0028		/* 16 bit r/w	Source Address 2 (low) */
+#define GM_SRC_ADDR_2M	0x002c		/* 16 bit r/w	Source Address 2 (middle) */
+#define GM_SRC_ADDR_2H	0x0030		/* 16 bit r/w	Source Address 2 (high) */
+
+/* Multicast Address Hash Registers */
+#define GM_MC_ADDR_H1	0x0034		/* 16 bit r/w	Multicast Address Hash 1 */
+#define GM_MC_ADDR_H2	0x0038		/* 16 bit r/w	Multicast Address Hash 2 */
+#define GM_MC_ADDR_H3	0x003c		/* 16 bit r/w	Multicast Address Hash 3 */
+#define GM_MC_ADDR_H4	0x0040		/* 16 bit r/w	Multicast Address Hash 4 */
+
+/* Interrupt Source Registers */
+#define GM_TX_IRQ_SRC	0x0044		/* 16 bit r/o	Tx Overflow IRQ Source */
+#define GM_RX_IRQ_SRC	0x0048		/* 16 bit r/o	Rx Overflow IRQ Source */
+#define GM_TR_IRQ_SRC	0x004c		/* 16 bit r/o	Tx/Rx Over. IRQ Source */
+
+/* Interrupt Mask Registers */
+#define GM_TX_IRQ_MSK	0x0050		/* 16 bit r/w	Tx Overflow IRQ Mask */
+#define GM_RX_IRQ_MSK	0x0054		/* 16 bit r/w	Rx Overflow IRQ Mask */
+#define GM_TR_IRQ_MSK	0x0058		/* 16 bit r/w	Tx/Rx Over. IRQ Mask */
+
+/* Serial Management Interface (SMI) Registers */
+#define GM_SMI_CTRL		0x0080		/* 16 bit r/w	SMI Control Register */
+#define GM_SMI_DATA		0x0084		/* 16 bit r/w	SMI Data Register */
+#define GM_PHY_ADDR		0x0088		/* 16 bit r/w	GPHY Address Register */
+
+/* MIB Counters */
+#define GM_MIB_CNT_BASE	0x0100		/* Base Address of MIB Counters */
+#define GM_MIB_CNT_SIZE	44			/* Number of MIB Counters */
+
+/*
+ * MIB Counters base address definitions (low word) -
+ * use offset 4 for access to high word	(32 bit r/o)
+ */
+#define GM_RXF_UC_OK \
+			(GM_MIB_CNT_BASE + 0)	/* Unicast Frames Received OK */
+#define GM_RXF_BC_OK \
+			(GM_MIB_CNT_BASE + 8)	/* Broadcast Frames Received OK */
+#define GM_RXF_MPAUSE \
+			(GM_MIB_CNT_BASE + 16)	/* Pause MAC Ctrl Frames Received */
+#define GM_RXF_MC_OK \
+			(GM_MIB_CNT_BASE + 24)	/* Multicast Frames Received OK */
+#define GM_RXF_FCS_ERR \
+			(GM_MIB_CNT_BASE + 32)	/* Rx Frame Check Seq. Error */
+	/* GM_MIB_CNT_BASE + 40:	reserved */
+#define GM_RXO_OK_LO \
+			(GM_MIB_CNT_BASE + 48)	/* Octets Received OK Low */
+#define GM_RXO_OK_HI \
+			(GM_MIB_CNT_BASE + 56)	/* Octets Received OK High */
+#define GM_RXO_ERR_LO \
+			(GM_MIB_CNT_BASE + 64)	/* Octets Received Invalid Low */
+#define GM_RXO_ERR_HI \
+			(GM_MIB_CNT_BASE + 72)	/* Octets Received Invalid High */
+#define GM_RXF_SHT \
+			(GM_MIB_CNT_BASE + 80)	/* Frames <64 Byte Received OK */
+#define GM_RXE_FRAG \
+			(GM_MIB_CNT_BASE + 88)	/* Frames <64 Byte Received with FCS Err */
+#define GM_RXF_64B \
+			(GM_MIB_CNT_BASE + 96)	/* 64 Byte Rx Frame */
+#define GM_RXF_127B \
+			(GM_MIB_CNT_BASE + 104)	/* 65-127 Byte Rx Frame */
+#define GM_RXF_255B \
+			(GM_MIB_CNT_BASE + 112)	/* 128-255 Byte Rx Frame */
+#define GM_RXF_511B \
+			(GM_MIB_CNT_BASE + 120)	/* 256-511 Byte Rx Frame */
+#define GM_RXF_1023B \
+			(GM_MIB_CNT_BASE + 128)	/* 512-1023 Byte Rx Frame */
+#define GM_RXF_1518B \
+			(GM_MIB_CNT_BASE + 136)	/* 1024-1518 Byte Rx Frame */
+#define GM_RXF_MAX_SZ \
+			(GM_MIB_CNT_BASE + 144)	/* 1519-MaxSize Byte Rx Frame */
+#define GM_RXF_LNG_ERR \
+			(GM_MIB_CNT_BASE + 152)	/* Rx Frame too Long Error */
+#define GM_RXF_JAB_PKT \
+			(GM_MIB_CNT_BASE + 160)	/* Rx Jabber Packet Frame */
+	/* GM_MIB_CNT_BASE + 168:	reserved */
+#define GM_RXE_FIFO_OV \
+			(GM_MIB_CNT_BASE + 176)	/* Rx FIFO overflow Event */
+	/* GM_MIB_CNT_BASE + 184:	reserved */
+#define GM_TXF_UC_OK \
+			(GM_MIB_CNT_BASE + 192)	/* Unicast Frames Xmitted OK */
+#define GM_TXF_BC_OK \
+			(GM_MIB_CNT_BASE + 200)	/* Broadcast Frames Xmitted OK */
+#define GM_TXF_MPAUSE \
+			(GM_MIB_CNT_BASE + 208)	/* Pause MAC Ctrl Frames Xmitted */
+#define GM_TXF_MC_OK \
+			(GM_MIB_CNT_BASE + 216)	/* Multicast Frames Xmitted OK */
+#define GM_TXO_OK_LO \
+			(GM_MIB_CNT_BASE + 224)	/* Octets Transmitted OK Low */
+#define GM_TXO_OK_HI \
+			(GM_MIB_CNT_BASE + 232)	/* Octets Transmitted OK High */
+#define GM_TXF_64B \
+			(GM_MIB_CNT_BASE + 240)	/* 64 Byte Tx Frame */
+#define GM_TXF_127B \
+			(GM_MIB_CNT_BASE + 248)	/* 65-127 Byte Tx Frame */
+#define GM_TXF_255B \
+			(GM_MIB_CNT_BASE + 256)	/* 128-255 Byte Tx Frame */
+#define GM_TXF_511B \
+			(GM_MIB_CNT_BASE + 264)	/* 256-511 Byte Tx Frame */
+#define GM_TXF_1023B \
+			(GM_MIB_CNT_BASE + 272)	/* 512-1023 Byte Tx Frame */
+#define GM_TXF_1518B \
+			(GM_MIB_CNT_BASE + 280)	/* 1024-1518 Byte Tx Frame */
+#define GM_TXF_MAX_SZ \
+			(GM_MIB_CNT_BASE + 288)	/* 1519-MaxSize Byte Tx Frame */
+	/* GM_MIB_CNT_BASE + 296:	reserved */
+#define GM_TXF_COL \
+			(GM_MIB_CNT_BASE + 304)	/* Tx Collision */
+#define GM_TXF_LAT_COL \
+			(GM_MIB_CNT_BASE + 312)	/* Tx Late Collision */
+#define GM_TXF_ABO_COL \
+			(GM_MIB_CNT_BASE + 320)	/* Tx aborted due to Exces. Col. */
+#define GM_TXF_MUL_COL \
+			(GM_MIB_CNT_BASE + 328)	/* Tx Multiple Collision */
+#define GM_TXF_SNG_COL \
+			(GM_MIB_CNT_BASE + 336)	/* Tx Single Collision */
+#define GM_TXE_FIFO_UR \
+			(GM_MIB_CNT_BASE + 344)	/* Tx FIFO Underrun Event */
+
+/*----------------------------------------------------------------------------*/
+/*
+ * GMAC Bit Definitions
+ *
+ * If the bit access behaviour differs from the register access behaviour
+ * (r/w, r/o) this is documented after the bit number.
+ * The following bit access behaviours are used:
+ *	(sc)	self clearing
+ *	(r/o)	read only
+ */
+
+/*	GM_GP_STAT	16 bit r/o	General Purpose Status Register */
+#define GM_GPSR_SPEED		BIT_15S	/* Port Speed (1 = 100 Mbps) */
+#define GM_GPSR_DUPLEX		BIT_14S	/* Duplex Mode (1 = Full) */
+#define GM_GPSR_FC_TX_DIS	BIT_13S	/* Tx Flow-Control Mode Disabled */
+#define GM_GPSR_LINK_UP		BIT_12S	/* Link Up Status */
+#define GM_GPSR_PAUSE		BIT_11S	/* Pause State */
+#define GM_GPSR_TX_ACTIVE	BIT_10S	/* Tx in Progress */
+#define GM_GPSR_EXC_COL		BIT_9S	/* Excessive Collisions Occured */
+#define GM_GPSR_LAT_COL		BIT_8S	/* Late Collisions Occured */
+								/* Bit   7.. 6:	reserved */
+#define GM_GPSR_PHY_ST_CH	BIT_5S	/* PHY Status Change */
+#define GM_GPSR_GIG_SPEED	BIT_4S	/* Gigabit Speed (1 = 1000 Mbps) */
+#define GM_GPSR_PART_MODE	BIT_3S	/* Partition mode */
+#define GM_GPSR_FC_RX_DIS	BIT_2S	/* Rx Flow-Control Mode Disabled */
+								/* Bit   2.. 0:	reserved */
+
+/*	GM_GP_CTRL	16 bit r/w	General Purpose Control Register */
+#define GM_GPCR_RMII_PH_ENA	BIT_15S	/* Enable RMII for PHY (Yukon-FE only) */
+#define GM_GPCR_RMII_LB_ENA	BIT_14S	/* Enable RMII Loopback (Yukon-FE only) */
+#define GM_GPCR_FC_TX_DIS	BIT_13S	/* Disable Tx Flow-Control Mode */
+#define GM_GPCR_TX_ENA		BIT_12S	/* Enable Transmit */
+#define GM_GPCR_RX_ENA		BIT_11S	/* Enable Receive */
+								/* Bit 10:	reserved */
+#define GM_GPCR_LOOP_ENA	BIT_9S	/* Enable MAC Loopback Mode */
+#define GM_GPCR_PART_ENA	BIT_8S	/* Enable Partition Mode */
+#define GM_GPCR_GIGS_ENA	BIT_7S	/* Gigabit Speed (1000 Mbps) */
+#define GM_GPCR_FL_PASS		BIT_6S	/* Force Link Pass */
+#define GM_GPCR_DUP_FULL	BIT_5S	/* Full Duplex Mode */
+#define GM_GPCR_FC_RX_DIS	BIT_4S	/* Disable Rx Flow-Control Mode */
+#define GM_GPCR_SPEED_100	BIT_3S	/* Port Speed 100 Mbps */
+#define GM_GPCR_AU_DUP_DIS	BIT_2S	/* Disable Auto-Update Duplex */
+#define GM_GPCR_AU_FCT_DIS	BIT_1S	/* Disable Auto-Update Flow-C. */
+#define GM_GPCR_AU_SPD_DIS	BIT_0S	/* Disable Auto-Update Speed */
+
+#define GM_GPCR_SPEED_1000	(GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+#define GM_GPCR_AU_ALL_DIS	(GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
+							 GM_GPCR_AU_SPD_DIS)
+
+/*	GM_TX_CTRL				16 bit r/w	Transmit Control Register */
+#define GM_TXCR_FORCE_JAM	BIT_15S	/* Force Jam / Flow-Control */
+#define GM_TXCR_CRC_DIS		BIT_14S	/* Disable insertion of CRC */
+#define GM_TXCR_PAD_DIS		BIT_13S	/* Disable padding of packets */
+#define GM_TXCR_COL_THR_MSK	(7<<10)	/* Bit 12..10: Collision Threshold Mask */
+								/* Bit   9.. 8:	reserved */
+#define GM_TXCR_PAD_PAT_MSK	0xff	/* Bit  7.. 0: Padding Pattern Mask */
+									/* (Yukon-2 only) */
+
+#define TX_COL_THR(x)		(SHIFT10(x) & GM_TXCR_COL_THR_MSK)
+
+#define TX_COL_DEF			0x04
+
+/*	GM_RX_CTRL				16 bit r/w	Receive Control Register */
+#define GM_RXCR_UCF_ENA		BIT_15S	/* Enable Unicast filtering */
+#define GM_RXCR_MCF_ENA		BIT_14S	/* Enable Multicast filtering */
+#define GM_RXCR_CRC_DIS		BIT_13S	/* Remove 4-byte CRC */
+#define GM_RXCR_PASS_FC		BIT_12S	/* Pass FC packets to FIFO (Yukon-1 only) */
+								/* Bit  11.. 0:	reserved */
+
+/*	GM_TX_PARAM				16 bit r/w	Transmit Parameter Register */
+#define GM_TXPA_JAMLEN_MSK	(3<<14)		/* Bit 15..14: Jam Length Mask */
+#define GM_TXPA_JAMIPG_MSK	(0x1f<<9)	/* Bit 13.. 9: Jam IPG Mask */
+#define GM_TXPA_JAMDAT_MSK	(0x1f<<4)	/* Bit  8.. 4: IPG Jam to Data Mask */
+#define GM_TXPA_BO_LIM_MSK	0x0f		/* Bit  3.. 0: Backoff Limit Mask */
+										/* (Yukon-2 only) */
+
+#define TX_JAM_LEN_VAL(x)	(SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
+#define TX_JAM_IPG_VAL(x)	(SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
+#define TX_IPG_JAM_DATA(x)	(SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
+#define TX_BACK_OFF_LIM(x)	((x) & GM_TXPA_BO_LIM_MSK)
+
+#define TX_JAM_LEN_DEF		0x03
+#define TX_JAM_IPG_DEF		0x0b
+#define TX_IPG_JAM_DEF		0x1c
+#define TX_BOF_LIM_DEF		0x04
+
+/*	GM_SERIAL_MODE			16 bit r/w	Serial Mode Register */
+#define GM_SMOD_DATABL_MSK	(0x1f<<11)	/* Bit 15..11:	Data Blinder */
+										/* r/o on Yukon, r/w on Yukon-EC */
+#define GM_SMOD_LIMIT_4		BIT_10S	/* 4 consecutive Tx trials */
+#define GM_SMOD_VLAN_ENA	BIT_9S	/* Enable VLAN  (Max. Frame Len) */
+#define GM_SMOD_JUMBO_ENA	BIT_8S	/* Enable Jumbo (Max. Frame Len) */
+								/* Bit   7.. 5:	reserved */
+#define GM_SMOD_IPG_MSK		0x1f	/* Bit  4.. 0:	Inter-Packet Gap (IPG) */
+
+#define DATA_BLIND_VAL(x)	(SHIFT11(x) & GM_SMOD_DATABL_MSK)
+#define IPG_DATA_VAL(x)		((x) & GM_SMOD_IPG_MSK)
+
+#define DATA_BLIND_DEF		0x04
+#define IPG_DATA_DEF		0x1e
+
+/*	GM_SMI_CTRL				16 bit r/w	SMI Control Register */
+#define GM_SMI_CT_PHY_A_MSK	(0x1f<<11)	/* Bit 15..11:	PHY Device Address */
+#define GM_SMI_CT_REG_A_MSK	(0x1f<<6)	/* Bit 10.. 6:	PHY Register Address */
+#define GM_SMI_CT_OP_RD		BIT_5S	/* OpCode Read (0=Write) */
+#define GM_SMI_CT_RD_VAL	BIT_4S	/* Read Valid (Read completed) */
+#define GM_SMI_CT_BUSY		BIT_3S	/* Busy (Operation in progress) */
+								/* Bit   2.. 0:	reserved */
+
+#define GM_SMI_CT_PHY_AD(x)	(SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
+#define GM_SMI_CT_REG_AD(x)	(SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
+
+/*	GM_PHY_ADDR				16 bit r/w	GPHY Address Register */
+								/* Bit  15.. 6:	reserved */
+#define GM_PAR_MIB_CLR		BIT_5S	/* Set MIB Clear Counter Mode */
+#define GM_PAR_MIB_TST		BIT_4S	/* MIB Load Counter (Test Mode) */
+								/* Bit   3.. 0:	reserved */
+
+/* Receive Frame Status Encoding */
+#define GMR_FS_LKUP_BIT2	BIT_31	/* MACSec Lookup entry b2 (Yukon-Ext only)*/
+#define GMR_FS_LEN_MSK	(0x7fffUL<<16)	/* Bit 30..16:	Rx Frame Length */
+#define GMR_FS_LKUP_BIT1	BIT_15	/* MACSec Lookup entry b1 (Yukon-Ext only)*/
+#define GMR_FS_LKUP_BIT0	BIT_14	/* MACSec Lookup entry b0 (Yukon-Ext only)*/
+#define GMR_FS_VLAN			BIT_13	/* VLAN Packet */
+#define GMR_FS_JABBER		BIT_12	/* Jabber Packet */
+#define GMR_FS_UN_SIZE		BIT_11	/* Undersize Packet */
+#define GMR_FS_MC			BIT_10	/* Multicast Packet */
+#define GMR_FS_BC			BIT_9	/* Broadcast Packet */
+#define GMR_FS_RX_OK		BIT_8	/* Receive OK (Good Packet) */
+#define GMR_FS_GOOD_FC		BIT_7	/* Good Flow-Control Packet */
+#define GMR_FS_BAD_FC		BIT_6	/* Bad  Flow-Control Packet */
+#define GMR_FS_MII_ERR		BIT_5	/* MII Error */
+#define GMR_FS_LONG_ERR		BIT_4	/* Too Long Packet */
+#define GMR_FS_FRAGMENT		BIT_3	/* Fragment */
+#define GMR_FS_LKUP_HIT		BIT_2	/* MACSec Lookup tab hit (Yukon-Ext only) */
+#define GMR_FS_CRC_ERR		BIT_1	/* CRC Error */
+#define GMR_FS_RX_FF_OV		BIT_0	/* Rx FIFO Overflow */
+
+/* Yukon-Ext only */
+#define GMR_FS_MACSEC_BITS	( \
+			GMR_FS_LKUP_BIT2 |\
+			GMR_FS_LKUP_BIT1 |\
+			GMR_FS_LKUP_BIT0 |\
+			GMR_FS_LKUP_HIT)
+
+#define GMR_FS_LEN_SHIFT	16
+
+/*
+ * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
+ */
+#ifdef SK_DIAG
+#define GMR_FS_ANY_ERR		( \
+			GMR_FS_RX_FF_OV | \
+			GMR_FS_CRC_ERR | \
+			GMR_FS_FRAGMENT | \
+			GMR_FS_MII_ERR | \
+			GMR_FS_BAD_FC | \
+			GMR_FS_GOOD_FC | \
+			GMR_FS_JABBER)
+#else
+#define GMR_FS_ANY_ERR		( \
+			GMR_FS_RX_FF_OV | \
+			GMR_FS_CRC_ERR | \
+			GMR_FS_FRAGMENT | \
+			GMR_FS_LONG_ERR | \
+			GMR_FS_MII_ERR | \
+			GMR_FS_BAD_FC | \
+			GMR_FS_GOOD_FC | \
+			GMR_FS_UN_SIZE | \
+			GMR_FS_JABBER)
+#endif
+
+/* Rx GMAC FIFO Flush Mask (default) */
+#define RX_FF_FL_DEF_MSK	GMR_FS_ANY_ERR
+
+/*
+ * MAC Security macros (Yukon-Ext only)
+ */
+/* EAPOL frame: hit + tab entry == 0 */
+#define GMR_IS_EAPOL_FRAME(status)	(\
+	((status) & GMR_FS_MACSEC_BITS) == GMR_FS_LKUP_HIT)
+
+/* Uncontrolled port frame: no table hit */
+#define GMR_IS_UNCON_FRAME(status)	(\
+	((status) & GMR_FS_LKUP_HIT) == 0)
+
+/* Controlled port: check key number: key = {1, 2}, key = tab entry  */
+#define GMR_IS_SECKEY_MATCH(status, key) (\
+	(status) & GMR_FS_MACSEC_BITS) == (GMR_FS_LKUP_HIT | ((key) << 14)))
+
+
+/* typedefs *******************************************************************/
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif	/* __INC_XMAC_H */
+
diff --git a/drivers/net/sk98lin/sk98lin.4 b/drivers/net/sk98lin/sk98lin.4
new file mode 100755
index 0000000..08160c6
--- /dev/null
+++ b/drivers/net/sk98lin/sk98lin.4
@@ -0,0 +1,498 @@
+.\" (C)Copyright 1999-2007 Marvell(R). -- linux@syskonnect.de
+.\" sk98lin.4 1.1 %_%LINDATE%_%
+.\" This manpage can be viewed using `groff -Tascii -man sk98lin.4 | less`
+.\"
+.TH SK98LIN 4 "%_%LINDATE%_%" "sk98lin 10.22.3.1 (alpha)"
+.SH NAME
+sk98lin \- Marvell/SysKonnect Gigabit Ethernet driver v10.22.3.1 (alpha)
+.SH SYNOPSIS
+.B insmod sk98lin.o
+.RB [ Speed_A=\c
+.IR i,j,... ]
+.RB [ Speed_B=\c
+.IR i,j,... ]
+.RB [ AutoNeg_A=\c
+.IR i,j,... ]
+.RB [ AutoNeg_B=\c
+.IR i,j,... ]
+.RB [ DupCap_A=\c
+.IR i,j,... ]
+.RB [ DupCap_B=\c
+.IR i,j,... ]
+.RB [ FlowCtrl_A=\c
+.IR i,j,... ]
+.RB [ FlowCtrl_B=\c
+.IR i,j,... ]
+.RB [ Role_A=\c
+.IR i,j,... ]
+.RB [ Role_B=\c
+.IR i,j,... ]
+.RB [ ConType=\c
+.IR i,j,... ]
+.RB [ TxModeration=\c
+.IR i,j,... ]
+.RB [ Moderation=\c
+.IR i,j,... ]
+.RB [ IntsPerSec=\c
+.IR i,j,... ]
+.RB [ PrefPort=\c
+.IR i,j,... ]
+.RB [ RlmtMode=\c
+.IR i,j,... ]
+.RB [ LowLatency=\c
+.IR i,j,... ]
+.RB [ BroadcastPrio=\c
+.IR i,j,... ]
+.SH DESCRIPTION
+.B sk98lin
+is the Gigabit Ethernet driver for Marvell and SysKonnect network adapter cards.
+It supports SysKonnect SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter and any Yukon compliant chipset.
+
+When loading the driver using 
+.BR insmod (8)
+, parameters for the network adapter cards might be stated as a sequence of comma separated commands. If for instance two network adapters are installed and AutoNegotiation on Port A of the first adapter should be ON, but on the Port A of the second adapter switched OFF, one must enter:
+
+   insmod sk98lin.o AutoNeg_A=On,Off
+
+After 
+.B sk98lin 
+is bound to one or more adapter cards and the 
+.IR /proc 
+filesystem is mounted on your system, a dedicated statistics file will be created in folder 
+.IR /proc/net/sk98lin 
+for all ports of the installed network adapter cards. Those files are named 
+.IR eth[x]
+whereby 
+.IR x 
+is the number of the interface that has been assigned to a dedicated port by the system.
+
+If loading is finished, any desired IP address can be assigned to the respective 
+.IR eth[x]
+interface using the 
+.BR ifconfig (8)
+command. This causes the adapter to connect to the Ethernet and to display a status message on the console saying "ethx: network connection up using port y" followed by the configured or detected connection parameters.
+
+The 
+.B sk98lin 
+also supports large frames (also called jumbo frames). Using jumbo frames can improve throughput tremendously when transferring large amounts of data. To enable large frames, the MTU (maximum transfer unit) size for an interface is to be set to a high value. The default MTU size is 1500 and can be changed up to 9000 (bytes). Setting the MTU size can be done when assigning the IP address to the interface or later by using the
+.BR ifconfig (8)
+command with the mtu parameter. If for instance eth0 needs an IP address and a large frame MTU size, the following two commands might be used:
+
+    ifconfig eth0 10.1.1.1
+    ifconfig eth0 mtu 9000
+
+Those two commands might even be combined into one:
+
+    ifconfig eth0 10.1.1.1 mtu 9000
+
+Note that large frames can only be used if your network infrastructure allows to do so. This means, that any switch being used in your Ethernet must also support large frames. Quite some switches support large frames, but need to be configured to do so. Most of the times, their default setting is to support only standard frames with an MTU size of 1500 (bytes). In addition to the switches inside the network, all network adapters that are to be used must also be enabled regarding jumbo frames. If an adapter is not set to receive large frames it will simply drop them. 
+
+Switching back to the standard Ethernet frame size can be done by using the
+.BR ifconfig (8)
+command again:
+
+    ifconfig eth0 mtu 1500
+
+The Marvell/SysKonnect Gigabit Ethernet driver for Linux is able to support VLAN and Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. Those features are only available after installation of open source modules which can be found on the Internet:
+
+.IR VLAN \c
+: http://www.candelatech.com/~greear/vlan.html
+.br
+.IR Link 
+.IR Aggregation \c
+: http://www.st.rim.or.jp/~yumo
+
+.br
+Note that Marvell/SysKonnect does not offer any support for these open source modules and does not take the responsibility for any kind of failures or problems arising when using these modules.
+.SH PARAMETERS
+.TP
+.BI Speed_A= i,j,...
+This parameter is used to set the speed capabilities of port A of an adapter card. It is only valid for Yukon copper adapters. Possible values are:
+.IR 10
+,
+.IR 100
+,
+.IR 1000
+or
+.IR Auto 
+whereby
+.IR Auto 
+is the default. Usually, the speed is negotiated between the two ports during link establishment. If this fails, a port can be forced to a specific setting with this parameter.
+.TP
+.BI Speed_B= i,j,...
+This parameter is used to set the speed capabilities of port B of an adapter card. It is only valid for Yukon copper adapters. Possible values are:
+.IR 10
+,
+.IR 100
+,
+.IR 1000
+or
+.IR Auto 
+whereby
+.IR Auto 
+is the default. Usually, the speed is negotiated between the two ports during link establishment. If this fails, a port can be forced to a specific setting with this parameter.
+.TP
+.BI AutoNeg_A= i,j,...
+Enables or disables the use of autonegotiation of port A of an adapter card. Possible values are:
+.IR On
+,
+.IR Off
+or
+.IR Sense
+whereby
+.IR On
+is the default. The 
+.IR Sense 
+mode automatically detects whether the link partner supports auto-negotiation or not.
+.TP
+.BI AutoNeg_B= i,j,...
+Enables or disables the use of autonegotiation of port B of an adapter card. Possible values are:
+.IR On
+,
+.IR Off
+or
+.IR Sense
+whereby
+.IR On
+is the default. The 
+.IR Sense 
+mode automatically detects whether the link partner supports auto-negotiation or not.
+.TP
+.BI DupCap_A= i,j,...
+This parameter indicates the duplex mode to be used for port A of an adapter card. Possible values are:
+.IR Half
+,
+.IR Full
+or
+.IR Both
+whereby
+.IR Both
+is the default. This parameter is only relevant if AutoNeg_A of port A is not set to 
+.IR Sense.
+If AutoNeg_A is set to 
+.IR On
+, all three values of DupCap_A (
+.IR Half
+, 
+.IR Full
+or 
+.IR Both
+) might be stated. If AutoNeg_A is set to 
+.IR Off
+, only DupCap_A values  
+.IR Full
+and 
+.IR Half
+are allowed. This DupCap_A parameter is useful if your link partner does not support all possible duplex combinations.
+.TP
+.BI DupCap_B= i,j,...
+This parameter indicates the duplex mode to be used for port B of an adapter card. Possible values are:
+.IR Half
+,
+.IR Full
+or
+.IR Both
+whereby
+.IR Both
+is the default. This parameter is only relevant if AutoNeg_B of port B is not set to
+.IR Sense.
+If AutoNeg_B is set to
+.IR On
+, all three values of DupCap_B (
+.IR Half
+,
+.IR Full
+or
+.IR Both
+) might be stated. If AutoNeg_B is set to
+.IR Off
+, only DupCap_B values
+.IR Full
+and
+.IR Half
+are allowed. This DupCap_B parameter is useful if your link partner does not support all possible duplex combinations.
+.TP
+.BI FlowCtrl_A= i,j,...
+This parameter can be used to set the flow control capabilities the port reports during auto-negotiation. Possible values are:
+.IR Sym
+,
+.IR SymOrRem
+,
+.IR LocSend
+or
+.IR None
+whereby
+.IR SymOrRem
+is the default.  The different modes have the following meaning: 
+
+.br
+.IR Sym
+= Symmetric 
+ both link partners are allowed to send PAUSE frames
+.br
+.IR SymOrRem
+= SymmetricOrRemote 
+ both or only remote partner are allowed to send PAUSE frames
+.br
+.IR LocSend
+= LocalSend
+ only local link partner is allowed to send PAUSE frames
+.br
+.IR None
+= None
+ no link partner is allowed to send PAUSE frames
+
+Note that this parameter is ignored if AutoNeg_A is set to
+.IR Off .
+.TP
+.BI FlowCtrl_B= i,j,...
+This parameter can be used to set the flow control capabilities the port reports during auto-negotiation. Possible values are:
+.IR Sym
+,
+.IR SymOrRem
+,
+.IR LocSend
+or
+.IR None
+whereby
+.IR SymOrRem
+is the default.  The different modes have the following meaning:
+
+.IR Sym
+= Symmetric
+ both link partners are allowed to send PAUSE frames
+.br
+.IR SymOrRem
+= SymmetricOrRemote
+ both or only remote partner are allowed to send PAUSE frames
+.br
+.IR LocSend
+= LocalSend
+ only local link partner is allowed to send PAUSE frames
+.br
+.IR None
+= None
+ no link partner is allowed to send PAUSE frames
+.br
+
+Note that this parameter is ignored if AutoNeg_B is set to
+.IR Off .
+.TP
+.BI Role_A= i,j,...
+This parameter is only valid for 1000Base-T adapter cards. For two 1000Base-T ports to communicate, one must take the role of the master (providing timing information), while the other must be the slave. Possible values are:
+.IR Auto
+,
+.IR Master
+or
+.IR Slave
+whereby
+.IR Auto
+is the default. Usually, the role of a port is negotiated between two ports during link establishment, but if that fails the port A of an adapter card can be forced to a specific setting with this parameter. 
+.TP
+.BI Role_B= i,j,...
+This parameter is only valid for 1000Base-T adapter cards. For two 1000Base-T ports to communicate, one must take the role of the master (providing timing information), while the other must be the slave. Possible values are:
+.IR Auto
+,
+.IR Master
+or
+.IR Slave
+whereby
+.IR Auto
+is the default. Usually, the role of a port is negotiated between two ports during link establishment, but if that fails the port B of an adapter card can be forced to a specific setting with this parameter. 
+.TP
+.BI ConType= i,j,...
+This parameter (for copper adapters only) is a combination of all five per-port parameters within one single parameter. This simplifies the configuration of both ports of an adapter card. The different values of this variable reflect the most meaningful combinations of port parameters. Possible values and their corresponding combination of per-port parameters:
+
+.br
+.ad l
+ConType | DupCap   AutoNeg   FlowCtrl   Role   Speed
+--------+-------------------------------------------
+.br
+.IR Auto \c
+    |  Both      On      SymOrRem   Auto   Auto
+.br
+.IR 1000FD \c
+  |  Full      Off       None     Auto   1000
+.br
+.IR 100FD \c
+   |  Full      Off       None     Auto   100
+.br
+.IR 100HD \c
+   |  Half      Off       None     Auto   100
+.br
+.IR 10FD \c
+    |  Full      Off       None     Auto   10
+.br
+.IR 10HD \c
+    |  Half      Off       None     Auto   10
+
+.ad b 
+Stating any other port parameter together with this 
+.IR ConType
+parameter will result in a merged configuration of those settings. This is due to
+the fact, that the per-port parameters (e.g. 
+.IR Speed_A
+) have a higher priority than the combined variable 
+.IR ConType
+.
+.TP
+.BI TxModeration= i,j,...
+Interrupt moderation is employed to limit the maximum number of transmit
+complete interrupts the driver has to serve. That is, one or more interrupts
+(which indicate any transmit packet to be processed) are queued until the
+driver processes them. The value "1" means, that all interrupts will be 
+generated immediately. 10 means, that the card will generate one interrupt
+after 10 served packets.
+.
+.TP
+.BI Moderation= i,j,...
+Interrupt moderation is employed to limit the maximum number of interrupts the driver has to serve. That is, one or more interrupts (which indicate any transmit or receive packet to be processed) are queued until the driver processes them. When queued interrupts are to be served, is determined by the 
+.IR IntsPerSec
+parameter, which is explained later below. Possible moderation modes are:
+.IR None
+,
+.IR Static
+or
+.IR Dynamic
+whereby
+.IR None
+is the default. The different modes have the following meaning:
+
+.IR None
+No interrupt moderation is applied on the adapter card. Therefore, each transmit or receive interrupt is served immediately as soon as it appears on the interrupt line of the adapter card.
+
+.br
+.IR Static
+Interrupt moderation is applied on the adapter card. All transmit and receive interrupts are queued until a complete moderation interval ends. If such a moderation interval ends, all queued interrupts are processed in one big bunch without any delay. The term 
+.IR Static
+reflects the fact, that interrupt moderation is always enabled, regardless how much network load is currently passing via a particular interface. In addition, the duration of the moderation interval has a fixed length that never changes while the driver is operational.
+
+.br
+.IR Dynamic
+Interrupt moderation might be applied on the adapter card, depending on the load of the system. If the driver detects that the system load is too high, the driver tries to shield the system against too much network load by enabling interrupt moderation. If - at a later time - the CPU utilization decreases again (or if the network load is negligible) the interrupt moderation will automatically be disabled.
+
+Interrupt moderation should be used when the driver has to handle one or more interfaces with a high network load, which - as a consequence - leads also to a high CPU utilization. When moderation is applied in such high network load situations, CPU load might be reduced by 20-30% on slow computers.
+
+Note that the drawback of using interrupt moderation is an increase of the round-trip-time (RTT), due to the queuing and serving of interrupts at dedicated
+moderation times.
+.TP
+.BI IntsPerSec= i,j,...
+This parameter determines the length of any interrupt moderation interval.
+Assuming that static interrupt moderation is to be used, an 
+.IR IntsPerSec
+parameter value of 2000 will lead to an interrupt moderation interval of
+500 microseconds. Possible values for this parameter are in the range of 30...40000 (interrupts per second). The default value is 2000.
+
+This parameter is only used, if either static or dynamic interrupt moderation
+is enabled on a network adapter card. This parameter is ignored if no moderation is
+applied.
+
+Note that the duration of the moderation interval is to be chosen with care.
+At first glance, selecting a very long duration (e.g. only 100 interrupts per
+second) seems to be meaningful, but the increase of packet-processing delay
+is tremendous. On the other hand, selecting a very short moderation time might
+compensate the use of any moderation being applied.
+.TP
+.BI PrefPort= i,j,...
+This parameter is used to force the preferred port to A or B (on dual-port network adapters). The preferred port is the one that is used if both ports A and B are detected as fully functional.  Possible values are:
+.IR A
+or
+.IR B
+whereby
+.IR A
+is the default.
+.TP
+.BI RlmtMode= i,j,...
+RLMT monitors the status of the port. If the link of the active port fails, RLMT switches immediately to the standby link. The virtual link is maintained as long as at least one 'physical' link is up.  This parameters states how RLMT should monitor both ports. Possible values are:
+.IR CheckLinkState
+,
+.IR CheckLocalPort
+,
+.IR CheckSeg
+or
+.IR DualNet
+whereby
+.IR CheckLinkState
+is the default. The different modes have the following meaning:
+
+.IR CheckLinkState
+Check link state only: RLMT uses the link state reported by the adapter hardware for each individual port to determine whether a port can be used for all network traffic or not.
+
+.br
+.IR CheckLocalPort
+In this mode, RLMT monitors the network path between the two ports of an adapter by regularly exchanging packets between them. This mode requires a network configuration in which the two ports are able to "see" each other (i.e. there must not be any router between the ports).
+
+.br
+.IR CheckSeg
+Check local port and segmentation: This mode supports the same functions as the CheckLocalPort mode and additionally checks network segmentation between the ports. Therefore, this mode is only to be used if Gigabit Ethernet switches are installed on the network that have been configured to use the Spanning Tree protocol.  
+
+.br
+.IR DualNet
+In this mode, ports A and B are used as separate devices. If you have a dual port adapter, port A will be configured as 
+.IR eth[x] 
+and port B as 
+.IR eth[x+1]
+Both ports can be used independently with distinct IP addresses. The preferred port setting is not used. RLMT is turned off.
+
+Note that RLMT modes 
+.IR CheckLocalPort 
+and 
+.IR CheckLinkState 
+are designed to operate in configurations where a network path between the ports on one adapter exists. Moreover, they are not designed to work where adapters are connected back-to-back.
+.TP
+.BI LowLatency= i,j,...
+This parameter is used to reduce the packet latency time of the adapter. Setting 
+.IR LowLatency
+to 
+.IR On 
+forces the adapter to pass any received packet immediately to upper network layers and to send out any transmit packet as fast as possible. Possible values are 
+.IR On
+or
+.IR Off
+whereby
+.IR Off
+is the default.
+
+Be aware of the fact that the system load increases if
+.IR LowLatency
+is set to 
+.IR On
+and a lot of data packets are transmitted and received.
+
+Note that this parameter is only used on adapters which are based on PCI Express compatible chipsets.
+.TP
+.BI BroadcastPrio= i,j,...
+This parameter specifies whether received broadcast packets have the
+highest priority for the port switch decision ("Off") or not ("On").
+Possible values are
+.IR On
+or
+.IR Off
+whereby
+.IR Off
+is the default.
+NOTE: This parameter is only valid for dual port adapters.
+.SH FILES
+.TP
+.B /proc/net/sk98lin/eth[x]
+.br 
+The statistics file of a particular interface of an adapter card. It contains generic information about the adapter card plus a detailed summary of all transmit and receive counters.
+.TP
+.B /usr/src/linux/Documentation/networking/sk98lin.txt
+.br 
+This is the 
+.IR README
+file of the 
+.IR sk98lin
+driver. It contains a detailed installation HOWTO and describes all parameters of the driver. It denotes also common problems and provides the solution to them.
+.SH BUGS
+Report any bugs to linux@syskonnect.de
+.SH AUTHOR
+(C)Copyright 1999-2007 Marvell(R).
+.br
+
+Ralph Roesler \- rroesler@syskonnect.de
+.br
+Mirko Lindner \- mlindner@syskonnect.de
+.SH "SEE ALSO"
+modprobe(8), insmod(8), ifconfig(8).
diff --git a/drivers/net/sk98lin/sk98lin.htm b/drivers/net/sk98lin/sk98lin.htm
new file mode 100755
index 0000000..d91a14a
--- /dev/null
+++ b/drivers/net/sk98lin/sk98lin.htm
@@ -0,0 +1,806 @@
+<HTML>
+<HEAD>
+<TITLE>sk98lin.htm</TITLE>
+<meta http-equiv="content-type" content="text-html; charset=ISO-8859-1">
+</HEAD>
+<BODY BGCOLOR=#FFFFFF TEXT=#000000 LINK=#0000FF VLINK=#003366 ALINK=#FF0000
+>
+<PRE>
+&copy;Copyright 1999-2007 Marvell&reg;.
+All rights reserved.
+</PRE>
+<HR WIDTH="100%">
+<PRE>sk98lin.htm created 15-Oct-2007
+
+Readme File for sk98lin v10.22.3.1 (alpha)
+Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter driver for LINUX
+
+</PRE>
+<H1>
+	<FONT FACE="Arial, Helevetica" SIZE=+2>
+		<B>This file contains</B>
+	</FONT>
+</H1>
+<UL>
+	<FONT FACE="Arial, Helvetica" SIZE=+1>
+		<B><A HREF="#Section1">1&nbsp;&nbsp;Overview</A></B>
+	</FONT>
+	<BR>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section2">2&nbsp;&nbsp;Supported Functions</A></B>
+</FONT>
+<BR>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section3">3&nbsp;&nbsp;Required Files</A></B>
+</FONT>
+<BR>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section4">4&nbsp;&nbsp;Installation</A></B>
+</FONT>
+<BR>
+<UL>
+	<FONT FACE="Arial, Helvetica">
+		<B><A HREF="#Section4.1">4.1&nbsp;&nbsp;Driver Installation</A></B>
+	</FONT>
+	<BR>
+
+<FONT FACE="Arial, Helvetica">
+	<B><A HREF="#Section4.2">4.2&nbsp;&nbsp;Inclusion of adapter at system start</A></B>
+</FONT>
+<BR>
+</UL>
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section5">5&nbsp;&nbsp;Driver Parameters</A></B>
+</FONT>
+<BR>
+<UL>
+	<FONT FACE="Arial, Helvetica">
+		<B><A HREF="#Section5.1">5.1&nbsp;&nbsp;Per-Port Parameters</A></B>
+	</FONT>
+	<BR>
+
+<FONT FACE="Arial, Helvetica">
+	<B><A HREF="#Section5.2">5.2&nbsp;&nbsp;Adapter Parameters</A></B>
+</FONT>
+<BR>
+</UL>
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section6">6&nbsp;&nbsp;Ethtool Support</A></B>
+</FONT>
+<BR>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section7">7&nbsp;&nbsp;Large Frame Support</A></B>
+</FONT>
+<BR>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section8">8&nbsp;&nbsp;VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)</A></B>
+</FONT>
+<BR>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section9">9&nbsp;&nbsp;Wake on Lan support</A></B>
+</FONT>
+<BR>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A HREF="#Section10">10&nbsp;&nbsp;Troubleshooting</A></B>
+</FONT>
+<BR>
+</UL><PRE>
+</PRE>
+<HR WIDTH="100%">
+<PRE>
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section1">1&nbsp;&nbsp;Overview</A></B>
+	</FONT>
+</H2>
+<PRE>The sk98lin driver supports the Marvell Yukon, Yukon EC/FE, Yukon 2
+and SysKonnect SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter on Linux.
+It has been tested with Linux on Intel/x86, x86_64 and IA64 machines.
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section2">2&nbsp;&nbsp;Supported Functions</A></B>
+	</FONT>
+</H2>
+<PRE>The following functions are supported by the driver:
+
+   NOTE 1: The hardware support depends on the used card
+ 
+   - RX/TX HW Checksum
+   - Hardware interrupt moderation (static/dynamic)
+   - Transmit poll
+   - Zerocopy/Scatter-Gather
+   - Ethtool support
+   - Wake on Lan (Magic Packet only)
+   - DualNet
+ 
+
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section3">3&nbsp;&nbsp;Required Files</A></B>
+	</FONT>
+</H2>
+<PRE>The linux kernel source.
+No additional files required.
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section4">4&nbsp;&nbsp;Installation</A></B>
+	</FONT>
+</H2>
+<PRE>It is recommended to download the latest version of the driver from the 
+SysKonnect web site www.syskonnect.com. For details on Installation 
+Instructions for sk98lin Driver, please refer to the README.txt file.
+
+</PRE>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A NAME="Section4.1">4.1&nbsp;&nbsp;Driver Installation</A></B>
+</FONT>
+<BR>
+<PRE>The following steps describe the actions that are required to install
+the driver and to start it manually. These steps should be carried
+out for the initial driver setup. Once confirmed to be ok, they can
+be included in the system start.
+
+NOTE 1: To perform the following tasks you need 'root' access.
+
+NOTE 2: In case of problems, please read the section &quot;Troubleshooting&quot; 
+        below.
+
+The driver can either be integrated into the kernel or it can be compiled 
+as a module. Select the appropriate option during the kernel 
+configuration.
+
+Compile/use the driver as a module
+----------------------------------
+To compile the driver, go to the directory /usr/src/linux and
+execute the command &quot;make menuconfig&quot; or &quot;make xconfig&quot; and proceed as 
+follows:
+
+To integrate the driver permanently into the kernel, proceed as follows:
+
+1. Select the menu &quot;Network device support&quot; and then &quot;Ethernet(1000Mbit)&quot;
+2. Mark &quot;Marvell Yukon Chipset / SysKonnect SK-98xx family support&quot; 
+   with (*) 
+3. Build a new kernel when the configuration of the above options is 
+   finished.
+4. Install the new kernel.
+5. Reboot your system.
+
+To use the driver as a module, proceed as follows:
+
+1. Enable 'loadable module support' in the kernel.
+2. For automatic driver start, enable the 'Kernel module loader'.
+3. Select the menu &quot;Network device support&quot; and then &quot;Ethernet(1000Mbit)&quot;
+4. Mark &quot;Marvell Yukon Chipset / SysKonnect SK-98xx family support&quot; 
+   with (M)
+5. Execute the command &quot;make modules&quot;.
+6. Execute the command &quot;make modules_install&quot;.
+   The appropiate modules will be installed.
+7. Reboot your system.
+
+
+Load the module manually
+------------------------
+To load the module manually, proceed as follows:
+
+1. Enter &quot;modprobe sk98lin&quot;.
+2. If a Marvell Yukon or SysKonnect SK-98xx adapter is installed in 
+   your computer and you have a /proc file system, execute the command:
+   &quot;ls /proc/net/sk98lin/&quot; 
+   This should produce an output containing a line with the following 
+   format:
+   eth0   eth1  ...
+   which indicates that your adapter has been found and initialized.
+   
+   NOTE 1: If you have more than one Marvell Yukon or SysKonnect SK-98xx 
+           adapter installed, the adapters will be listed as 'eth0', 
+           'eth1', 'eth2', etc.
+           For each adapter, repeat steps 3 and 4 below.
+
+   NOTE 2: If you have other Ethernet adapters installed, your Marvell
+           Yukon or SysKonnect SK-98xx adapter will be mapped to the 
+           next available number, e.g. 'eth1'. The mapping is executed 
+           automatically.
+           The module installation message (displayed either in a system
+           log file or on the console) prints a line for each adapter 
+           found containing the corresponding 'ethX'.
+
+3. Select an IP address and assign it to the respective adapter by 
+   entering:
+   ifconfig eth0 &lt;ip-address&gt;
+   With this command, the adapter is connected to the Ethernet. 
+   
+   SK-98xx Gigabit Ethernet Server Adapters: The yellow LED on the adapter 
+   is now active, the link status LED of the primary port is active and 
+   the link status LED of the secondary port (on dual port adapters) is 
+   blinking (if the ports are connected to a switch or hub).
+   SK-98xx V2.0 Gigabit Ethernet Adapters: The link status LED is active.
+   In addition, you will receive a status message on the console stating
+   &quot;ethX: network connection up using port Y&quot; and showing the selected 
+   connection parameters (x stands for the ethernet device number 
+   (0,1,2, etc), y stands for the port name (A or B)).
+
+   NOTE: If you are in doubt about IP addresses, ask your network
+         administrator for assistance.
+  
+4. Your adapter should now be fully operational.
+   Use 'ping &lt;otherstation&gt;' to verify the connection to other computers 
+   on your network.
+5. To check the adapter configuration view /proc/net/sk98lin/[devicename].
+   For example by executing:    
+   &quot;cat /proc/net/sk98lin/eth0&quot; 
+
+Unload the module
+-----------------
+To stop and unload the driver modules, proceed as follows:
+
+1. Execute the command &quot;ifconfig eth0 down&quot;.
+2. Execute the command &quot;rmmod sk98lin&quot;.
+
+</PRE>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A NAME="Section4.2">4.2&nbsp;&nbsp;Inclusion of adapter at system start</A></B>
+</FONT>
+<BR>
+<PRE>Since a large number of different Linux distributions are 
+available, we are unable to describe a general installation procedure
+for the driver module.
+Because the driver is now integrated in the kernel, installation should
+be easy, using the standard mechanism of your distribution.
+Refer to the distribution's manual for installation of ethernet adapters.
+
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section5">5&nbsp;&nbsp;Driver Parameters</A></B>
+	</FONT>
+</H2>
+<PRE>Parameters can be set at the command line after the module has been 
+loaded with the command 'modprobe'.
+In some distributions, the configuration tools are able to pass parameters
+to the driver module.
+
+If you use the kernel module loader, you can set driver parameters
+in the file /etc/modules.conf (or old name: /etc/conf.modules).
+To set the driver parameters in this file, proceed as follows:
+
+1. Insert a line of the form :
+   options sk98lin ...
+   For &quot;...&quot;, the same syntax is required as described for the command
+   line paramaters of modprobe below.
+2. To activate the new parameters, either reboot your computer
+   or 
+   unload and reload the driver.
+   The syntax of the driver parameters is:
+
+        modprobe sk98lin parameter=value1[,value2[,value3...]]
+
+   where value1 refers to the first adapter, value2 to the second etc.
+
+NOTE: All parameters are case sensitive. Write them exactly as shown 
+      below.
+
+Example:
+Suppose you have two adapters. You want to set auto-negotiation
+on the first adapter to ON and on the second adapter to OFF.
+You also want to set DuplexCapabilities on the first adapter
+to FULL, and on the second adapter to HALF.
+Then, you must enter:
+
+        modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half
+
+NOTE: The number of adapters that can be configured this way is
+      limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM).
+      The current limit is 16. If you happen to install
+      more adapters, adjust this and recompile.
+
+
+</PRE>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A NAME="Section5.1">5.1&nbsp;&nbsp;Per-Port Parameters</A></B>
+</FONT>
+<BR>
+<PRE>These settings are available for each port on the adapter.
+In the following description, '?' stands for the port for
+which you set the parameter (A or B).
+
+Speed
+-----
+Parameter:    Speed_?
+Values:       10, 100, 1000, Auto
+Default:      Auto
+
+This parameter is used to set the speed capabilities. It is only valid 
+for the SK-98xx V2.0 copper adapters.
+Usually, the speed is negotiated between the two ports during link 
+establishment. If this fails, a port can be forced to a specific setting
+with this parameter.
+
+Auto-Negotiation
+----------------
+Parameter:    AutoNeg_?
+Values:       On, Off, Sense
+Default:      On
+  
+The &quot;Sense&quot;-mode automatically detects whether the link partner supports
+auto-negotiation or not.
+
+Duplex Capabilities
+-------------------
+Parameter:    DupCap_?
+Values:       Half, Full, Both
+Default:      Both
+
+This parameters is only relevant if auto-negotiation for this port is 
+not set to &quot;Sense&quot;. If auto-negotiation is set to &quot;On&quot;, all three values
+are possible. If it is set to &quot;Off&quot;, only &quot;Full&quot; and &quot;Half&quot; are allowed.
+This parameter is usefull if your link partner does not support all
+possible combinations.
+
+Flow Control
+------------
+Parameter:    FlowCtrl_?
+Values:       Sym, SymOrRem, LocSend, None
+Default:      SymOrRem
+
+This parameter can be used to set the flow control capabilities the 
+port reports during auto-negotiation. It can be set for each port 
+individually.
+Possible modes:
+   -- Sym      = Symmetric: both link partners are allowed to send 
+                  PAUSE frames
+   -- SymOrRem = SymmetricOrRemote: both or only remote partner 
+                  are allowed to send PAUSE frames
+   -- LocSend  = LocalSend: only local link partner is allowed 
+                  to send PAUSE frames
+   -- None     = no link partner is allowed to send PAUSE frames
+  
+NOTE: This parameter is ignored if auto-negotiation is set to &quot;Off&quot;.
+
+Broadcast Priority
+-------------------
+Parameter:    BroadcastPrio
+Values:       On, Off
+Default:      Off
+
+This parameter specifies whether received broadcast packets have the
+highest priority for the port switch decision (&quot;Off&quot;) or not (&quot;On&quot;).
+
+NOTE: This parameter is only valid for dual port adapters.
+
+
+Role in Master-Slave-Negotiation (1000Base-T only)
+--------------------------------------------------
+Parameter:    Role_?
+Values:       Auto, Master, Slave
+Default:      Auto
+
+This parameter is only valid for the SK-9821 and SK-9822 adapters.
+For two 1000Base-T ports to communicate, one must take the role of the
+master (providing timing information), while the other must be the 
+slave. Usually, this is negotiated between the two ports during link 
+establishment. If this fails, a port can be forced to a specific setting
+with this parameter.
+
+
+</PRE>
+
+<FONT FACE="Arial, Helvetica" SIZE=+1>
+	<B><A NAME="Section5.2">5.2&nbsp;&nbsp;Adapter Parameters</A></B>
+</FONT>
+<BR>
+<PRE>Connection Type (for copper adapters only)
+---------------
+Parameter:    ConType
+Values:       Auto, 1000FD, 100FD, 100HD, 10FD, 10HD
+Default:      Auto
+
+The parameter 'ConType' is a combination of all five per-port parameters
+within one single parameter. This simplifies the configuration of both ports
+of an adapter card! The different values of this variable reflect the most 
+meaningful combinations of port parameters.
+
+The following table shows the values of 'ConType' and the corresponding
+combinations of the per-port parameters:
+
+    ConType   |  DupCap   AutoNeg   FlowCtrl   Role             Speed
+    ----------+------------------------------------------------------
+    Auto      |  Both     On        SymOrRem   Auto             Auto
+    1000FD    |  Full     Off       None       Auto (ignored)   1000
+    100FD     |  Full     Off       None       Auto (ignored)   100
+    100HD     |  Half     Off       None       Auto (ignored)   100
+    10FD      |  Full     Off       None       Auto (ignored)   10
+    10HD      |  Half     Off       None       Auto (ignored)   10
+
+Stating any other port parameter together with this 'ConType' variable
+will result in a merged configuration of those settings. This due to 
+the fact, that the per-port parameters (e.g. Speed_? ) have a higher
+priority than the combined variable 'ConType'.
+
+NOTE: This parameter is always used on both ports of the adapter card.
+
+Transmit Moderation
+--------------------
+Parameter:    TxModeration
+Values:       1...4095
+Default:      10
+
+Interrupt moderation is employed to limit the maximum number of transmit
+complete interrupts the driver has to serve. That is, one or more interrupts
+(which indicate any transmit packet to be processed) are queued until the
+driver processes them. The value &quot;1&quot; means, that all interrupts will be 
+generated immediately. 10 means, that the card will generate one interrupt
+after 10 served packets.
+
+Interrupt Moderation
+--------------------
+Parameter:    Moderation
+Values:       None, Static, Dynamic
+Default:      None
+
+Interrupt moderation is employed to limit the maxmimum number of interrupts
+the driver has to serve. That is, one or more interrupts (which indicate any
+transmit or receive packet to be processed) are queued until the driver 
+processes them. When queued interrupts are to be served, is determined by the
+'IntsPerSec' parameter, which is explained later below.
+
+Possible modes:
+
+   -- None - No interrupt moderation is applied on the adapter card. 
+      Therefore, each transmit or receive interrupt is served immediately
+      as soon as it appears on the interrupt line of the adapter card.
+
+   -- Static - Interrupt moderation is applied on the adapter card. 
+      All transmit and receive interrupts are queued until a complete
+      moderation interval ends. If such a moderation interval ends, all
+      queued interrupts are processed in one big bunch without any delay.
+      The term 'static' reflects the fact, that interrupt moderation is
+      always enabled, regardless how much network load is currently 
+      passing via a particular interface. In addition, the duration of
+      the moderation interval has a fixed length that never changes while
+      the driver is operational.
+
+   -- Dynamic - Interrupt moderation might be applied on the adapter card,
+      depending on the load of the system. If the driver detects that the
+      system load is too high, the driver tries to shield the system against 
+      too much network load by enabling interrupt moderation. If - at a later
+      time - the CPU utilizaton decreases again (or if the network load is 
+      negligible) the interrupt moderation will automatically be disabled.
+
+Interrupt moderation should be used when the driver has to handle one or more
+interfaces with a high network load, which - as a consequence - leads also to a
+high CPU utilization. When moderation is applied in such high network load 
+situations, CPU load might be reduced by 20-30%.
+
+NOTE: The drawback of using interrupt moderation is an increase of the round-
+trip-time (RTT), due to the queueing and serving of interrupts at dedicated
+moderation times.
+
+Interrupts per second
+---------------------
+Parameter:    IntsPerSec
+Values:       30...40000 (interrupts per second)
+Default:      2000
+
+This parameter is only used, if either static or dynamic interrupt moderation
+is used on a network adapter card. Using this paramter if no moderation is
+applied, will lead to no action performed.
+
+This parameter determines the length of any interrupt moderation interval. 
+Assuming that static interrupt moderation is to be used, an 'IntsPerSec' 
+parameter value of 2000 will lead to an interrupt moderation interval of
+500 microseconds. 
+
+NOTE: The duration of the moderation interval is to be chosen with care.
+At first glance, selecting a very long duration (e.g. only 100 interrupts per 
+second) seems to be meaningful, but the increase of packet-processing delay 
+is tremendous. On the other hand, selecting a very short moderation time might
+compensate the use of any moderation being applied.
+
+Preferred Port
+--------------
+Parameter:    PrefPort
+Values:       A, B
+Default:      A
+
+This is used to force the preferred port to A or B (on dual-port network 
+adapters). The preferred port is the one that is used if both are detected
+as fully functional.
+
+RLMT Mode (Redundant Link Management Technology)
+------------------------------------------------
+Parameter:    RlmtMode
+Values:       CheckLinkState,CheckLocalPort, CheckSeg, DualNet
+Default:      CheckLinkState (DualNet on dual port adapters)
+
+RLMT monitors the status of the port. If the link of the active port 
+fails, RLMT switches immediately to the standby link. The virtual link is 
+maintained as long as at least one 'physical' link is up. 
+
+Possible modes:
+
+   -- CheckLinkState - Check link state only: RLMT uses the link state
+      reported by the adapter hardware for each individual port to 
+      determine whether a port can be used for all network traffic or 
+      not.
+
+   -- CheckLocalPort - In this mode, RLMT monitors the network path 
+      between the two ports of an adapter by regularly exchanging packets
+      between them. This mode requires a network configuration in which 
+      the two ports are able to &quot;see&quot; each other (i.e. there must not be 
+      any router between the ports).
+
+   -- CheckSeg - Check local port and segmentation: This mode supports the
+      same functions as the CheckLocalPort mode and additionally checks 
+      network segmentation between the ports. Therefore, this mode is only
+      to be used if Gigabit Ethernet switches are installed on the network
+      that have been configured to use the Spanning Tree protocol. 
+
+   -- DualNet - In this mode, ports A and B are used as separate devices. 
+      If you have a dual port adapter, port A will be configured as eth0 
+      and port B as eth1. Both ports can be used independently with 
+      distinct IP addresses. The preferred port setting is not used. 
+      RLMT is turned off.
+   
+NOTE: RLMT modes CLP and CLPSS are designed to operate in configurations 
+      where a network path between the ports on one adapter exists. 
+      Moreover, they are not designed to work where adapters are connected
+      back-to-back.
+
+LowLatency 
+----------
+Parameter:    LowLatency
+Values:       On, Off
+Default:      Off
+
+This is used to reduce the packet latency time of the adapter. Setting the 
+LowLatency parameter to 'On' forces the adapter to pass any received packet
+immediately to upper network layers and to send out any transmit packet as
+fast as possible.
+
+NOTE 1: The system load increases if LowLatency is set to 'On' and a lot
+        of data packets are transmitted and received.
+
+NOTE 2: This parameter is only used on adapters which are based on 
+        PCI Express compatible chipsets.
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section6">6&nbsp;&nbsp;Ethtool Support</A></B>
+	</FONT>
+</H2>
+<PRE>The sk98lin driver provides built-in ethtool support. The ethtool 
+can be used to display or modify interface specific configurations.
+
+Ethtool commands are invoked using a single parameter which reflects
+the requested ethtool command plus an optional number of parameters 
+which belong to the desired command.
+
+It is not the intention of this section to explain the ethtool command
+line tool and all its options. For further information refer to the 
+manpage of the ethtool.  This sections describes only the sk98lin 
+driver supported ethtool commands.
+
+Pause Parameters
+----------------
+Query command:  -a
+Set command:    -A [autoneg on|off] [rx on|off] [tx on|off]
+Sample:         ethtool -A eth0 rx off tx off
+
+Coalescing Parameters
+---------------------
+Query command:  -c
+Set command:    -C [sample-interval I]
+                   [rx-usecs N] [tx-usecs N]
+                   [rx-usecs-low N] [tx-usecs-low N]
+                   [rx-usecs-high N] [tx-usecs-high N]
+Parameter:      I = Length of sample interval, in seconds
+                    (supported values range from 1...10)
+                N = Length of coalescing interval, in microseconds
+                    (supported values range from 25...33,333)
+Sample:         ethtool -C eth2 rx-usecs 500 tx-usecs 500
+
+NOTE: The sk98lin driver does not support different settings
+      for the rx and tx interrupt coalescing parameters.
+
+Driver Information
+------------------
+Query command:  -i
+Sample:         ethtool -i eth1
+
+Checksumming Parameters
+-----------------------
+Query command:  -k
+Set command:    -K [rx on|off] [tx on|off] [sg on|off] [tso on|off]
+Sample:         ethtool -K eth0 sg off
+
+Locate NIC Command
+------------------
+Query command:  -p [N]
+Parameter:      N = Amount of time to perform locate NIC command, in seconds
+Sample:         ethtool -p 10 eth1
+
+Driver-specific Statistics
+--------------------------
+Query command:  -S
+Sample:         ethtool -S eth0
+
+Setting Parameters
+------------------
+Set command:    -s [speed 10|100|1000] [duplex half|full] 
+                   [autoneg on|off] [wol gd]
+Sample:         ethtool -s eth2 wol d
+
+NOTE: If cable is disconnected, please set the speed and duplex mode
+      if you disable/enable autonegotiation
+ 
+NOTE: To set back to the default values use the &quot;autoneg on&quot; command.
+      Sample:    ethtool -s eth2 autoneg on
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section7">7&nbsp;&nbsp;Large Frame Support</A></B>
+	</FONT>
+</H2>
+<PRE>The driver supports large frames (also called jumbo frames). Using large 
+frames can result in an improved throughput if transferring large amounts 
+of data.
+To enable large frames, set the MTU (maximum transfer unit) of the 
+interface to the desired value (up to 9000), execute the following 
+command:
+      ifconfig eth0 mtu 9000
+This will only work if you have two adapters connected back-to-back
+or if you use a switch that supports large frames. When using a switch, 
+it should be configured to allow large frames. The setting must be 
+configured on all adapters that can be reached by the large frames. 
+If one adapter is not set to receive large frames, it will simply drop 
+them.
+
+You can switch back to the standard ethernet frame size by executing the 
+following command:
+      ifconfig eth0 mtu 1500
+
+To permanently configure this setting, add a script with the 'ifconfig' 
+line to the system startup sequence (named something like &quot;S99sk98lin&quot; 
+in /etc/rc.d/rc2.d).
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section8">8&nbsp;&nbsp;VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)</A></B>
+	</FONT>
+</H2>
+<PRE>The Marvell Yukon/SysKonnect Linux drivers are able to support VLAN and 
+Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. 
+These features are only available after installation of open source 
+modules available on the Internet:
+For VLAN go to: http://www.candelatech.com/~greear/vlan.html
+For Link Aggregation go to: http://www.st.rim.or.jp/~yumo
+
+NOTE: SysKonnect GmbH does not offer any support for these open source 
+      modules and does not take the responsibility for any kind of 
+      failures or problems arising in connection with these modules.
+
+NOTE: Configuring Link Aggregation on a SysKonnect dual link adapter may 
+      cause problems when unloading the driver.
+
+
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section9">9&nbsp;&nbsp;Wake on Lan support</A></B>
+	</FONT>
+</H2>
+<PRE>The sk98lin driver supports wake up from suspend mode with MagicPacket
+on APM systems. Wake on Lan support is enabled by default. To disable it 
+please use the ethtool.
+
+NOTE 1: APM support has to be enabled in BIOS and in the kernel.
+
+NOTE 2: Refer to the kernel documentation for additional requirements 
+        regarding APM support.
+
+
+</PRE>
+<H2>
+	<FONT FACE="Arial, Helvetica" SIZE=+2>
+		<B><A NAME="Section10">10&nbsp;&nbsp;Troubleshooting</A></B>
+	</FONT>
+</H2>
+<PRE>If any problems occur during the installation process, check the 
+following list:
+
+
+Problem:  The SK-98xx adapter can not be found by the driver.
+Solution: In /proc/pci search for the following entry:
+             'Ethernet controller: SysKonnect SK-98xx ...'
+          If this entry exists, the SK-98xx or SK-98xx V2.0 adapter has 
+          been found by the system and should be operational.
+          If this entry does not exist or if the file '/proc/pci' is not 
+          found, there may be a hardware problem or the PCI support may 
+          not be enabled in your kernel.
+          The adapter can be checked using the diagnostics program which 
+          is available on the SysKonnect web site:
+          www.syskonnect.com
+          
+          Some COMPAQ machines have problems dealing with PCI under Linux.
+          Linux. This problem is described in the 'PCI howto' document
+          (included in some distributions or available from the
+          web, e.g. at 'www.linux.org'). 
+
+
+Problem:  Programs such as 'ifconfig' or 'route' can not be found or the 
+          error message 'Operation not permitted' is displayed.
+Reason:   You are not logged in as user 'root'.
+Solution: Logout and login as 'root' or change to 'root' via 'su'.
+
+
+Problem:  Upon use of the command 'ping &lt;address&gt;' the message
+          &quot;ping: sendto: Network is unreachable&quot; is displayed.
+Reason:   Your route is not set correctly.
+Solution: If you are using RedHat, you probably forgot to set up the 
+          route in the 'network configuration'.
+          Check the existing routes with the 'route' command and check 
+          if an entry for 'eth0' exists, and if so, if it is set correctly.
+
+
+Problem:  The driver can be started, the adapter is connected to the 
+          network, but you cannot receive or transmit any packets; 
+          e.g. 'ping' does not work.
+Reason:   There is an incorrect route in your routing table.
+Solution: Check the routing table with the command 'route' and read the 
+          manual help pages dealing with routes (enter 'man route').
+
+NOTE: Although the 2.2.x kernel versions generate the routing entry 
+      automatically, problems of this kind may occur here as well. We've 
+      come across a situation in which the driver started correctly at 
+      system start, but after the driver has been removed and reloaded,
+      the route of the adapter's network pointed to the 'dummy0'device 
+      and had to be corrected manually.
+
+
+Problem:  Your computer should act as a router between multiple 
+          IP subnetworks (using multiple adapters), but computers in 
+          other subnetworks cannot be reached.
+Reason:   Either the router's kernel is not configured for IP forwarding 
+          or the routing table and gateway configuration of at least one 
+          computer is not working.
+
+Problem:  Upon driver start, the following error message is displayed:
+          &quot;eth0: -- ERROR --
+          Class: internal Software error
+          Nr:    0xcc
+          Msg:   SkGeInitPort() cannot init running ports&quot;
+Reason:   You are using a driver compiled for single processor machines 
+          on a multiprocessor machine with SMP (Symmetric MultiProcessor) 
+          kernel.
+Solution: Configure your kernel appropriately and recompile the kernel or
+          the modules.
+
+
+
+If your problem is not listed here, please contact SysKonnect's technical
+support for help (linux@syskonnect.de).
+When contacting our technical support, please ensure that the following 
+information is available:
+- System Manufacturer and HW Informations (CPU, Memory... )
+- PCI-Boards in your system
+- Distribution
+- Kernel version
+- Driver version
+***End of Readme File***
+</PRE>
+</BODY>
+</HTML>
diff --git a/drivers/net/sk98lin/sk98lin.txt b/drivers/net/sk98lin/sk98lin.txt
new file mode 100755
index 0000000..39b9340
--- /dev/null
+++ b/drivers/net/sk98lin/sk98lin.txt
@@ -0,0 +1,713 @@
+(C)Copyright 1999-2007 Marvell(R).
+All rights reserved.
+================================================================================
+
+sk98lin.txt created 15-Oct-2007
+
+Readme File for sk98lin v10.22.3.1 (alpha)
+Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter driver for LINUX
+
+This file contains
+ 1  Overview
+ 2  Supported Functions
+ 3  Required Files
+ 4  Installation
+    4.1  Driver Installation
+    4.2  Inclusion of adapter at system start
+ 5  Driver Parameters
+    5.1  Per-Port Parameters
+    5.2  Adapter Parameters
+ 6  Ethtool Support
+ 7  Large Frame Support
+ 8  VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
+ 9  Wake on Lan support
+10  Troubleshooting
+
+================================================================================
+
+
+1  Overview
+===========
+
+The sk98lin driver supports the Marvell Yukon, Yukon EC/FE, Yukon 2
+and SysKonnect SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter on Linux.
+It has been tested with Linux on Intel/x86, x86_64 and IA64 machines.
+***
+
+2  Supported Functions
+======================
+
+The following functions are supported by the driver:
+
+   NOTE 1: The hardware support depends on the used card
+ 
+   - RX/TX HW Checksum
+   - Hardware interrupt moderation (static/dynamic)
+   - Transmit poll
+   - Zerocopy/Scatter-Gather
+   - Ethtool support
+   - Wake on Lan (Magic Packet only)
+   - DualNet
+ 
+
+3  Required Files
+=================
+
+The linux kernel source.
+No additional files required.
+***
+
+
+4  Installation
+===============
+
+It is recommended to download the latest version of the driver from the 
+SysKonnect web site www.syskonnect.com. For details on Installation 
+Instructions for sk98lin Driver, please refer to the README.txt file.
+
+4.1  Driver Installation
+------------------------
+
+The following steps describe the actions that are required to install
+the driver and to start it manually. These steps should be carried
+out for the initial driver setup. Once confirmed to be ok, they can
+be included in the system start.
+
+NOTE 1: To perform the following tasks you need 'root' access.
+
+NOTE 2: In case of problems, please read the section "Troubleshooting" 
+        below.
+
+The driver can either be integrated into the kernel or it can be compiled 
+as a module. Select the appropriate option during the kernel 
+configuration.
+
+Compile/use the driver as a module
+----------------------------------
+To compile the driver, go to the directory /usr/src/linux and
+execute the command "make menuconfig" or "make xconfig" and proceed as 
+follows:
+
+To integrate the driver permanently into the kernel, proceed as follows:
+
+1. Select the menu "Network device support" and then "Ethernet(1000Mbit)"
+2. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support" 
+   with (*) 
+3. Build a new kernel when the configuration of the above options is 
+   finished.
+4. Install the new kernel.
+5. Reboot your system.
+
+To use the driver as a module, proceed as follows:
+
+1. Enable 'loadable module support' in the kernel.
+2. For automatic driver start, enable the 'Kernel module loader'.
+3. Select the menu "Network device support" and then "Ethernet(1000Mbit)"
+4. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support" 
+   with (M)
+5. Execute the command "make modules".
+6. Execute the command "make modules_install".
+   The appropiate modules will be installed.
+7. Reboot your system.
+
+
+Load the module manually
+------------------------
+To load the module manually, proceed as follows:
+
+1. Enter "modprobe sk98lin".
+2. If a Marvell Yukon or SysKonnect SK-98xx adapter is installed in 
+   your computer and you have a /proc file system, execute the command:
+   "ls /proc/net/sk98lin/" 
+   This should produce an output containing a line with the following 
+   format:
+   eth0   eth1  ...
+   which indicates that your adapter has been found and initialized.
+   
+   NOTE 1: If you have more than one Marvell Yukon or SysKonnect SK-98xx 
+           adapter installed, the adapters will be listed as 'eth0', 
+           'eth1', 'eth2', etc.
+           For each adapter, repeat steps 3 and 4 below.
+
+   NOTE 2: If you have other Ethernet adapters installed, your Marvell
+           Yukon or SysKonnect SK-98xx adapter will be mapped to the 
+           next available number, e.g. 'eth1'. The mapping is executed 
+           automatically.
+           The module installation message (displayed either in a system
+           log file or on the console) prints a line for each adapter 
+           found containing the corresponding 'ethX'.
+
+3. Select an IP address and assign it to the respective adapter by 
+   entering:
+   ifconfig eth0 <ip-address>
+   With this command, the adapter is connected to the Ethernet. 
+   
+   SK-98xx Gigabit Ethernet Server Adapters: The yellow LED on the adapter 
+   is now active, the link status LED of the primary port is active and 
+   the link status LED of the secondary port (on dual port adapters) is 
+   blinking (if the ports are connected to a switch or hub).
+   SK-98xx V2.0 Gigabit Ethernet Adapters: The link status LED is active.
+   In addition, you will receive a status message on the console stating
+   "ethX: network connection up using port Y" and showing the selected 
+   connection parameters (x stands for the ethernet device number 
+   (0,1,2, etc), y stands for the port name (A or B)).
+
+   NOTE: If you are in doubt about IP addresses, ask your network
+         administrator for assistance.
+  
+4. Your adapter should now be fully operational.
+   Use 'ping <otherstation>' to verify the connection to other computers 
+   on your network.
+5. To check the adapter configuration view /proc/net/sk98lin/[devicename].
+   For example by executing:    
+   "cat /proc/net/sk98lin/eth0" 
+
+Unload the module
+-----------------
+To stop and unload the driver modules, proceed as follows:
+
+1. Execute the command "ifconfig eth0 down".
+2. Execute the command "rmmod sk98lin".
+
+4.2  Inclusion of adapter at system start
+-----------------------------------------
+
+Since a large number of different Linux distributions are 
+available, we are unable to describe a general installation procedure
+for the driver module.
+Because the driver is now integrated in the kernel, installation should
+be easy, using the standard mechanism of your distribution.
+Refer to the distribution's manual for installation of ethernet adapters.
+
+***
+
+
+5  Driver Parameters
+====================
+
+Parameters can be set at the command line after the module has been 
+loaded with the command 'modprobe'.
+In some distributions, the configuration tools are able to pass parameters
+to the driver module.
+
+If you use the kernel module loader, you can set driver parameters
+in the file /etc/modules.conf (or old name: /etc/conf.modules).
+To set the driver parameters in this file, proceed as follows:
+
+1. Insert a line of the form :
+   options sk98lin ...
+   For "...", the same syntax is required as described for the command
+   line paramaters of modprobe below.
+2. To activate the new parameters, either reboot your computer
+   or 
+   unload and reload the driver.
+   The syntax of the driver parameters is:
+
+        modprobe sk98lin parameter=value1[,value2[,value3...]]
+
+   where value1 refers to the first adapter, value2 to the second etc.
+
+NOTE: All parameters are case sensitive. Write them exactly as shown 
+      below.
+
+Example:
+Suppose you have two adapters. You want to set auto-negotiation
+on the first adapter to ON and on the second adapter to OFF.
+You also want to set DuplexCapabilities on the first adapter
+to FULL, and on the second adapter to HALF.
+Then, you must enter:
+
+        modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half
+
+NOTE: The number of adapters that can be configured this way is
+      limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM).
+      The current limit is 16. If you happen to install
+      more adapters, adjust this and recompile.
+
+
+5.1  Per-Port Parameters
+------------------------
+
+These settings are available for each port on the adapter.
+In the following description, '?' stands for the port for
+which you set the parameter (A or B).
+
+Speed
+-----
+Parameter:    Speed_?
+Values:       10, 100, 1000, Auto
+Default:      Auto
+
+This parameter is used to set the speed capabilities. It is only valid 
+for the SK-98xx V2.0 copper adapters.
+Usually, the speed is negotiated between the two ports during link 
+establishment. If this fails, a port can be forced to a specific setting
+with this parameter.
+
+Auto-Negotiation
+----------------
+Parameter:    AutoNeg_?
+Values:       On, Off, Sense
+Default:      On
+  
+The "Sense"-mode automatically detects whether the link partner supports
+auto-negotiation or not.
+
+Duplex Capabilities
+-------------------
+Parameter:    DupCap_?
+Values:       Half, Full, Both
+Default:      Both
+
+This parameters is only relevant if auto-negotiation for this port is 
+not set to "Sense". If auto-negotiation is set to "On", all three values
+are possible. If it is set to "Off", only "Full" and "Half" are allowed.
+This parameter is usefull if your link partner does not support all
+possible combinations.
+
+Flow Control
+------------
+Parameter:    FlowCtrl_?
+Values:       Sym, SymOrRem, LocSend, None
+Default:      SymOrRem
+
+This parameter can be used to set the flow control capabilities the 
+port reports during auto-negotiation. It can be set for each port 
+individually.
+Possible modes:
+   -- Sym      = Symmetric: both link partners are allowed to send 
+                  PAUSE frames
+   -- SymOrRem = SymmetricOrRemote: both or only remote partner 
+                  are allowed to send PAUSE frames
+   -- LocSend  = LocalSend: only local link partner is allowed 
+                  to send PAUSE frames
+   -- None     = no link partner is allowed to send PAUSE frames
+  
+NOTE: This parameter is ignored if auto-negotiation is set to "Off".
+
+Broadcast Priority
+-------------------
+Parameter:    BroadcastPrio
+Values:       On, Off
+Default:      Off
+
+This parameter specifies whether received broadcast packets have the
+highest priority for the port switch decision ("Off") or not ("On").
+
+NOTE: This parameter is only valid for dual port adapters.
+
+
+Role in Master-Slave-Negotiation (1000Base-T only)
+--------------------------------------------------
+Parameter:    Role_?
+Values:       Auto, Master, Slave
+Default:      Auto
+
+This parameter is only valid for the SK-9821 and SK-9822 adapters.
+For two 1000Base-T ports to communicate, one must take the role of the
+master (providing timing information), while the other must be the 
+slave. Usually, this is negotiated between the two ports during link 
+establishment. If this fails, a port can be forced to a specific setting
+with this parameter.
+
+
+5.2  Adapter Parameters
+-----------------------
+
+Connection Type (for copper adapters only)
+---------------
+Parameter:    ConType
+Values:       Auto, 1000FD, 100FD, 100HD, 10FD, 10HD
+Default:      Auto
+
+The parameter 'ConType' is a combination of all five per-port parameters
+within one single parameter. This simplifies the configuration of both ports
+of an adapter card! The different values of this variable reflect the most 
+meaningful combinations of port parameters.
+
+The following table shows the values of 'ConType' and the corresponding
+combinations of the per-port parameters:
+
+    ConType   |  DupCap   AutoNeg   FlowCtrl   Role             Speed
+    ----------+------------------------------------------------------
+    Auto      |  Both     On        SymOrRem   Auto             Auto
+    1000FD    |  Full     Off       None       Auto (ignored)   1000
+    100FD     |  Full     Off       None       Auto (ignored)   100
+    100HD     |  Half     Off       None       Auto (ignored)   100
+    10FD      |  Full     Off       None       Auto (ignored)   10
+    10HD      |  Half     Off       None       Auto (ignored)   10
+
+Stating any other port parameter together with this 'ConType' variable
+will result in a merged configuration of those settings. This due to 
+the fact, that the per-port parameters (e.g. Speed_? ) have a higher
+priority than the combined variable 'ConType'.
+
+NOTE: This parameter is always used on both ports of the adapter card.
+
+Transmit Moderation
+--------------------
+Parameter:    TxModeration
+Values:       1...4095
+Default:      10
+
+Interrupt moderation is employed to limit the maximum number of transmit
+complete interrupts the driver has to serve. That is, one or more interrupts
+(which indicate any transmit packet to be processed) are queued until the
+driver processes them. The value "1" means, that all interrupts will be 
+generated immediately. 10 means, that the card will generate one interrupt
+after 10 served packets.
+
+Interrupt Moderation
+--------------------
+Parameter:    Moderation
+Values:       None, Static, Dynamic
+Default:      None
+
+Interrupt moderation is employed to limit the maxmimum number of interrupts
+the driver has to serve. That is, one or more interrupts (which indicate any
+transmit or receive packet to be processed) are queued until the driver 
+processes them. When queued interrupts are to be served, is determined by the
+'IntsPerSec' parameter, which is explained later below.
+
+Possible modes:
+
+   -- None - No interrupt moderation is applied on the adapter card. 
+      Therefore, each transmit or receive interrupt is served immediately
+      as soon as it appears on the interrupt line of the adapter card.
+
+   -- Static - Interrupt moderation is applied on the adapter card. 
+      All transmit and receive interrupts are queued until a complete
+      moderation interval ends. If such a moderation interval ends, all
+      queued interrupts are processed in one big bunch without any delay.
+      The term 'static' reflects the fact, that interrupt moderation is
+      always enabled, regardless how much network load is currently 
+      passing via a particular interface. In addition, the duration of
+      the moderation interval has a fixed length that never changes while
+      the driver is operational.
+
+   -- Dynamic - Interrupt moderation might be applied on the adapter card,
+      depending on the load of the system. If the driver detects that the
+      system load is too high, the driver tries to shield the system against 
+      too much network load by enabling interrupt moderation. If - at a later
+      time - the CPU utilizaton decreases again (or if the network load is 
+      negligible) the interrupt moderation will automatically be disabled.
+
+Interrupt moderation should be used when the driver has to handle one or more
+interfaces with a high network load, which - as a consequence - leads also to a
+high CPU utilization. When moderation is applied in such high network load 
+situations, CPU load might be reduced by 20-30%.
+
+NOTE: The drawback of using interrupt moderation is an increase of the round-
+trip-time (RTT), due to the queueing and serving of interrupts at dedicated
+moderation times.
+
+Interrupts per second
+---------------------
+Parameter:    IntsPerSec
+Values:       30...40000 (interrupts per second)
+Default:      2000
+
+This parameter is only used, if either static or dynamic interrupt moderation
+is used on a network adapter card. Using this paramter if no moderation is
+applied, will lead to no action performed.
+
+This parameter determines the length of any interrupt moderation interval. 
+Assuming that static interrupt moderation is to be used, an 'IntsPerSec' 
+parameter value of 2000 will lead to an interrupt moderation interval of
+500 microseconds. 
+
+NOTE: The duration of the moderation interval is to be chosen with care.
+At first glance, selecting a very long duration (e.g. only 100 interrupts per 
+second) seems to be meaningful, but the increase of packet-processing delay 
+is tremendous. On the other hand, selecting a very short moderation time might
+compensate the use of any moderation being applied.
+
+Preferred Port
+--------------
+Parameter:    PrefPort
+Values:       A, B
+Default:      A
+
+This is used to force the preferred port to A or B (on dual-port network 
+adapters). The preferred port is the one that is used if both are detected
+as fully functional.
+
+RLMT Mode (Redundant Link Management Technology)
+------------------------------------------------
+Parameter:    RlmtMode
+Values:       CheckLinkState,CheckLocalPort, CheckSeg, DualNet
+Default:      CheckLinkState (DualNet on dual port adapters)
+
+RLMT monitors the status of the port. If the link of the active port 
+fails, RLMT switches immediately to the standby link. The virtual link is 
+maintained as long as at least one 'physical' link is up. 
+
+Possible modes:
+
+   -- CheckLinkState - Check link state only: RLMT uses the link state
+      reported by the adapter hardware for each individual port to 
+      determine whether a port can be used for all network traffic or 
+      not.
+
+   -- CheckLocalPort - In this mode, RLMT monitors the network path 
+      between the two ports of an adapter by regularly exchanging packets
+      between them. This mode requires a network configuration in which 
+      the two ports are able to "see" each other (i.e. there must not be 
+      any router between the ports).
+
+   -- CheckSeg - Check local port and segmentation: This mode supports the
+      same functions as the CheckLocalPort mode and additionally checks 
+      network segmentation between the ports. Therefore, this mode is only
+      to be used if Gigabit Ethernet switches are installed on the network
+      that have been configured to use the Spanning Tree protocol. 
+
+   -- DualNet - In this mode, ports A and B are used as separate devices. 
+      If you have a dual port adapter, port A will be configured as eth0 
+      and port B as eth1. Both ports can be used independently with 
+      distinct IP addresses. The preferred port setting is not used. 
+      RLMT is turned off.
+   
+NOTE: RLMT modes CLP and CLPSS are designed to operate in configurations 
+      where a network path between the ports on one adapter exists. 
+      Moreover, they are not designed to work where adapters are connected
+      back-to-back.
+
+LowLatency 
+----------
+Parameter:    LowLatency
+Values:       On, Off
+Default:      Off
+
+This is used to reduce the packet latency time of the adapter. Setting the 
+LowLatency parameter to 'On' forces the adapter to pass any received packet
+immediately to upper network layers and to send out any transmit packet as
+fast as possible.
+
+NOTE 1: The system load increases if LowLatency is set to 'On' and a lot
+        of data packets are transmitted and received.
+
+NOTE 2: This parameter is only used on adapters which are based on 
+        PCI Express compatible chipsets.
+***
+
+
+6  Ethtool Support
+==================
+
+The sk98lin driver provides built-in ethtool support. The ethtool 
+can be used to display or modify interface specific configurations.
+
+Ethtool commands are invoked using a single parameter which reflects
+the requested ethtool command plus an optional number of parameters 
+which belong to the desired command.
+
+It is not the intention of this section to explain the ethtool command
+line tool and all its options. For further information refer to the 
+manpage of the ethtool.  This sections describes only the sk98lin 
+driver supported ethtool commands.
+
+Pause Parameters
+----------------
+Query command:  -a
+Set command:    -A [autoneg on|off] [rx on|off] [tx on|off]
+Sample:         ethtool -A eth0 rx off tx off
+
+Coalescing Parameters
+---------------------
+Query command:  -c
+Set command:    -C [sample-interval I]
+                   [rx-usecs N] [tx-usecs N]
+                   [rx-usecs-low N] [tx-usecs-low N]
+                   [rx-usecs-high N] [tx-usecs-high N]
+Parameter:      I = Length of sample interval, in seconds
+                    (supported values range from 1...10)
+                N = Length of coalescing interval, in microseconds
+                    (supported values range from 25...33,333)
+Sample:         ethtool -C eth2 rx-usecs 500 tx-usecs 500
+
+NOTE: The sk98lin driver does not support different settings
+      for the rx and tx interrupt coalescing parameters.
+
+Driver Information
+------------------
+Query command:  -i
+Sample:         ethtool -i eth1
+
+Checksumming Parameters
+-----------------------
+Query command:  -k
+Set command:    -K [rx on|off] [tx on|off] [sg on|off] [tso on|off]
+Sample:         ethtool -K eth0 sg off
+
+Locate NIC Command
+------------------
+Query command:  -p [N]
+Parameter:      N = Amount of time to perform locate NIC command, in seconds
+Sample:         ethtool -p 10 eth1
+
+Driver-specific Statistics
+--------------------------
+Query command:  -S
+Sample:         ethtool -S eth0
+
+Setting Parameters
+------------------
+Set command:    -s [speed 10|100|1000] [duplex half|full] 
+                   [autoneg on|off] [wol gd]
+Sample:         ethtool -s eth2 wol d
+
+NOTE: If cable is disconnected, please set the speed and duplex mode
+      if you disable/enable autonegotiation
+ 
+NOTE: To set back to the default values use the "autoneg on" command.
+      Sample:    ethtool -s eth2 autoneg on
+***
+
+
+7  Large Frame Support
+======================
+
+The driver supports large frames (also called jumbo frames). Using large 
+frames can result in an improved throughput if transferring large amounts 
+of data.
+To enable large frames, set the MTU (maximum transfer unit) of the 
+interface to the desired value (up to 9000), execute the following 
+command:
+      ifconfig eth0 mtu 9000
+This will only work if you have two adapters connected back-to-back
+or if you use a switch that supports large frames. When using a switch, 
+it should be configured to allow large frames. The setting must be 
+configured on all adapters that can be reached by the large frames. 
+If one adapter is not set to receive large frames, it will simply drop 
+them.
+
+You can switch back to the standard ethernet frame size by executing the 
+following command:
+      ifconfig eth0 mtu 1500
+
+To permanently configure this setting, add a script with the 'ifconfig' 
+line to the system startup sequence (named something like "S99sk98lin" 
+in /etc/rc.d/rc2.d).
+***
+
+
+8  VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
+==================================================================
+
+The Marvell Yukon/SysKonnect Linux drivers are able to support VLAN and 
+Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. 
+These features are only available after installation of open source 
+modules available on the Internet:
+For VLAN go to: http://www.candelatech.com/~greear/vlan.html
+For Link Aggregation go to: http://www.st.rim.or.jp/~yumo
+
+NOTE: SysKonnect GmbH does not offer any support for these open source 
+      modules and does not take the responsibility for any kind of 
+      failures or problems arising in connection with these modules.
+
+NOTE: Configuring Link Aggregation on a SysKonnect dual link adapter may 
+      cause problems when unloading the driver.
+
+
+9  Wake on Lan support
+======================
+
+The sk98lin driver supports wake up from suspend mode with MagicPacket
+on APM systems. Wake on Lan support is enabled by default. To disable it 
+please use the ethtool.
+
+NOTE 1: APM support has to be enabled in BIOS and in the kernel.
+
+NOTE 2: Refer to the kernel documentation for additional requirements 
+        regarding APM support.
+
+
+10  Troubleshooting
+===================
+
+If any problems occur during the installation process, check the 
+following list:
+
+
+Problem:  The SK-98xx adapter can not be found by the driver.
+Solution: In /proc/pci search for the following entry:
+             'Ethernet controller: SysKonnect SK-98xx ...'
+          If this entry exists, the SK-98xx or SK-98xx V2.0 adapter has 
+          been found by the system and should be operational.
+          If this entry does not exist or if the file '/proc/pci' is not 
+          found, there may be a hardware problem or the PCI support may 
+          not be enabled in your kernel.
+          The adapter can be checked using the diagnostics program which 
+          is available on the SysKonnect web site:
+          www.syskonnect.com
+          
+          Some COMPAQ machines have problems dealing with PCI under Linux.
+          Linux. This problem is described in the 'PCI howto' document
+          (included in some distributions or available from the
+          web, e.g. at 'www.linux.org'). 
+
+
+Problem:  Programs such as 'ifconfig' or 'route' can not be found or the 
+          error message 'Operation not permitted' is displayed.
+Reason:   You are not logged in as user 'root'.
+Solution: Logout and login as 'root' or change to 'root' via 'su'.
+
+
+Problem:  Upon use of the command 'ping <address>' the message
+          "ping: sendto: Network is unreachable" is displayed.
+Reason:   Your route is not set correctly.
+Solution: If you are using RedHat, you probably forgot to set up the 
+          route in the 'network configuration'.
+          Check the existing routes with the 'route' command and check 
+          if an entry for 'eth0' exists, and if so, if it is set correctly.
+
+
+Problem:  The driver can be started, the adapter is connected to the 
+          network, but you cannot receive or transmit any packets; 
+          e.g. 'ping' does not work.
+Reason:   There is an incorrect route in your routing table.
+Solution: Check the routing table with the command 'route' and read the 
+          manual help pages dealing with routes (enter 'man route').
+
+NOTE: Although the 2.2.x kernel versions generate the routing entry 
+      automatically, problems of this kind may occur here as well. We've 
+      come across a situation in which the driver started correctly at 
+      system start, but after the driver has been removed and reloaded,
+      the route of the adapter's network pointed to the 'dummy0'device 
+      and had to be corrected manually.
+
+
+Problem:  Your computer should act as a router between multiple 
+          IP subnetworks (using multiple adapters), but computers in 
+          other subnetworks cannot be reached.
+Reason:   Either the router's kernel is not configured for IP forwarding 
+          or the routing table and gateway configuration of at least one 
+          computer is not working.
+
+Problem:  Upon driver start, the following error message is displayed:
+          "eth0: -- ERROR --
+          Class: internal Software error
+          Nr:    0xcc
+          Msg:   SkGeInitPort() cannot init running ports"
+Reason:   You are using a driver compiled for single processor machines 
+          on a multiprocessor machine with SMP (Symmetric MultiProcessor) 
+          kernel.
+Solution: Configure your kernel appropriately and recompile the kernel or
+          the modules.
+
+
+
+If your problem is not listed here, please contact SysKonnect's technical
+support for help (linux@syskonnect.de).
+When contacting our technical support, please ensure that the following 
+information is available:
+- System Manufacturer and HW Informations (CPU, Memory... )
+- PCI-Boards in your system
+- Distribution
+- Kernel version
+- Driver version
+***
+
+
+
+***End of Readme File***
diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
new file mode 100755
index 0000000..2e0f7a4
--- /dev/null
+++ b/drivers/net/sk98lin/skaddr.c
@@ -0,0 +1,1808 @@
+/******************************************************************************
+ *
+ * Name:	skaddr.c
+ * Project:	Gigabit Ethernet Adapters, ADDR-Module
+ * Version:	$Revision: 2.12 $
+ * Date:	$Date: 2007/02/12 16:40:28 $
+ * Purpose:	Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * This module is intended to manage multicast addresses, address override,
+ * and promiscuous mode on GEnesis and Yukon adapters.
+ *
+ * Address Layout:
+ *	port address:		physical MAC address
+ *	1st exact match:	logical MAC address (GEnesis only)
+ *	2nd exact match:	RLMT multicast (GEnesis only)
+ *	exact match 3-13:	OS-specific multicasts (GEnesis only)
+ *
+ * Include File Hierarchy:
+ *
+ *	"skdrv1st.h"
+ *	"skdrv2nd.h"
+ *
+ ******************************************************************************/
+
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skaddr.c,v 2.12 2007/02/12 16:40:28 tschilli Exp $ (C) Marvell.";
+#endif /* DEBUG ||!LINT || !SK_SLIM */
+
+#define __SKADDR_C
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* cplusplus */
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+
+/* defines ********************************************************************/
+
+#define XMAC_POLY	0xEDB88320UL	/* CRC32-Poly - XMAC: Little Endian */
+#define GMAC_POLY	0x04C11DB7L	/* CRC16-Poly - GMAC: Little Endian */
+#define HASH_BITS	6				/* #bits in hash */
+#define SK_MC_BIT	0x01
+
+/* Error numbers and messages. */
+
+#define SKERR_ADDR_E001		(SK_ERRBASE_ADDR + 0)
+#define SKERR_ADDR_E001MSG	"Bad Flags."
+#define SKERR_ADDR_E002		(SKERR_ADDR_E001 + 1)
+#define SKERR_ADDR_E002MSG	"New Error."
+
+/* typedefs *******************************************************************/
+
+/* None. */
+
+/* global variables ***********************************************************/
+
+/* 64-bit hash values with all bits set. */
+
+SK_U16	OnesHash[4] = {0xffff, 0xffff, 0xffff, 0xffff};
+
+/* local variables ************************************************************/
+
+#ifdef DEBUG
+static int	Next0[SK_MAX_MACS] = {0};
+#endif	/* DEBUG */
+
+/* functions ******************************************************************/
+
+/******************************************************************************
+ *
+ *	SkAddrInit - initialize data, set state to init
+ *
+ * Description:
+ *
+ *	SK_INIT_DATA
+ *	============
+ *
+ *	This routine clears the multicast tables and resets promiscuous mode.
+ *	Some entries are reserved for the "logical MAC address", the
+ *	SK-RLMT multicast address, and the BPDU multicast address.
+ *
+ *
+ *	SK_INIT_IO
+ *	==========
+ *
+ *	All permanent MAC addresses are read from EPROM.
+ *	If the current MAC addresses are not already set in software,
+ *	they are set to the values of the permanent addresses.
+ *	The current addresses are written to the corresponding MAC.
+ *
+ *
+ *	SK_INIT_RUN
+ *	===========
+ *
+ *	Nothing.
+ *
+ * Context:
+ *	init, pageable
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS
+ */
+int	SkAddrInit(
+SK_AC	*pAC,	/* the adapter context */
+SK_IOC	IoC,	/* I/O context */
+int		Level)	/* initialization level */
+{
+	int			j;
+	SK_U32		i;
+	SK_U8		*InAddr;
+	SK_U16		*OutAddr;
+	SK_ADDR_PORT	*pAPort;
+
+	switch (Level) {
+	case SK_INIT_DATA:
+		SK_MEMSET((char *)&pAC->Addr, (SK_U8)0, (SK_U16)sizeof(SK_ADDR));
+
+		for (i = 0; i < SK_MAX_MACS; i++) {
+			pAPort = &pAC->Addr.Port[i];
+			pAPort->PromMode = SK_PROM_MODE_NONE;
+
+			pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+			pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+			pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+			pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+		}
+#ifdef xDEBUG
+		for (i = 0; i < SK_MAX_MACS; i++) {
+			if (pAC->Addr.Port[i].NextExactMatchRlmt <
+				SK_ADDR_FIRST_MATCH_RLMT) {
+				Next0[i] |= 4;
+			}
+		}
+#endif	/* DEBUG */
+		/* pAC->Addr.InitDone = SK_INIT_DATA; */
+		break;
+
+	case SK_INIT_IO:
+#ifndef SK_NO_RLMT
+		for (i = 0; i < SK_MAX_NETS; i++) {
+			pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
+		}
+#endif /* !SK_NO_RLMT */
+#ifdef xDEBUG
+		for (i = 0; i < SK_MAX_MACS; i++) {
+			if (pAC->Addr.Port[i].NextExactMatchRlmt <
+				SK_ADDR_FIRST_MATCH_RLMT) {
+				Next0[i] |= 8;
+			}
+		}
+#endif	/* DEBUG */
+
+		/* Read permanent logical MAC address from Control Register File. */
+		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+			InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
+			SK_IN8(IoC, B2_MAC_1 + j, InAddr);
+		}
+
+		if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
+			/* Set the current logical MAC address to the permanent one. */
+			pAC->Addr.Net[0].CurrentMacAddress =
+				pAC->Addr.Net[0].PermanentMacAddress;
+			pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
+		}
+
+		/* Set the current logical MAC address. */
+		pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
+			pAC->Addr.Net[0].CurrentMacAddress;
+#if SK_MAX_NETS > 1
+		/* Set logical MAC address for net 2 to. */
+		if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
+			pAC->Addr.Net[1].PermanentMacAddress =
+				pAC->Addr.Net[0].PermanentMacAddress;
+			pAC->Addr.Net[1].PermanentMacAddress.a[5] += 1;
+			/* Set the current logical MAC address to the permanent one. */
+			pAC->Addr.Net[1].CurrentMacAddress =
+				pAC->Addr.Net[1].PermanentMacAddress;
+			pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
+		}
+#endif	/* SK_MAX_NETS > 1 */
+
+#ifdef DEBUG
+		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+				("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
+					i,
+					pAC->Addr.Net[i].PermanentMacAddress.a[0],
+					pAC->Addr.Net[i].PermanentMacAddress.a[1],
+					pAC->Addr.Net[i].PermanentMacAddress.a[2],
+					pAC->Addr.Net[i].PermanentMacAddress.a[3],
+					pAC->Addr.Net[i].PermanentMacAddress.a[4],
+					pAC->Addr.Net[i].PermanentMacAddress.a[5]));
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+				("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
+					i,
+					pAC->Addr.Net[i].CurrentMacAddress.a[0],
+					pAC->Addr.Net[i].CurrentMacAddress.a[1],
+					pAC->Addr.Net[i].CurrentMacAddress.a[2],
+					pAC->Addr.Net[i].CurrentMacAddress.a[3],
+					pAC->Addr.Net[i].CurrentMacAddress.a[4],
+					pAC->Addr.Net[i].CurrentMacAddress.a[5]));
+		}
+#endif	/* DEBUG */
+
+		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+			pAPort = &pAC->Addr.Port[i];
+
+			/* Read permanent port addresses from Control Register File. */
+			for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+				InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
+				SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
+			}
+
+			if (!pAPort->CurrentMacAddressSet) {
+				/*
+				 * Set the current and previous physical MAC address
+				 * of this port to its permanent MAC address.
+				 */
+				pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
+				pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
+				pAPort->CurrentMacAddressSet = SK_TRUE;
+			}
+
+			/* Set port's current physical MAC address. */
+			OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+#ifdef GENESIS
+			if (pAC->GIni.GIGenesis) {
+				XM_OUTADDR(IoC, i, XM_SA, OutAddr);
+			}
+#endif /* GENESIS */
+#ifdef YUKON
+			if (!pAC->GIni.GIGenesis) {
+				GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
+			}
+#endif /* YUKON */
+#ifdef DEBUG
+			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+				("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+					pAPort->PermanentMacAddress.a[0],
+					pAPort->PermanentMacAddress.a[1],
+					pAPort->PermanentMacAddress.a[2],
+					pAPort->PermanentMacAddress.a[3],
+					pAPort->PermanentMacAddress.a[4],
+					pAPort->PermanentMacAddress.a[5]));
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+				("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+					pAPort->CurrentMacAddress.a[0],
+					pAPort->CurrentMacAddress.a[1],
+					pAPort->CurrentMacAddress.a[2],
+					pAPort->CurrentMacAddress.a[3],
+					pAPort->CurrentMacAddress.a[4],
+					pAPort->CurrentMacAddress.a[5]));
+#endif /* DEBUG */
+		}
+		/* pAC->Addr.InitDone = SK_INIT_IO; */
+		break;
+
+	case SK_INIT_RUN:
+#ifdef xDEBUG
+		for (i = 0; i < SK_MAX_MACS; i++) {
+			if (pAC->Addr.Port[i].NextExactMatchRlmt <
+				SK_ADDR_FIRST_MATCH_RLMT) {
+				Next0[i] |= 16;
+			}
+		}
+#endif	/* DEBUG */
+
+		/* pAC->Addr.InitDone = SK_INIT_RUN; */
+		break;
+
+	default:	/* error */
+		break;
+	}
+
+	return (SK_ADDR_SUCCESS);
+
+}	/* SkAddrInit */
+
+#ifndef SK_SLIM
+
+/******************************************************************************
+ *
+ *	SkAddrMcClear - clear the multicast table
+ *
+ * Description:
+ *	This routine clears the multicast table.
+ *
+ *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+ *	immediately.
+ *
+ *	It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
+ *	to the adapter in use. The real work is done there.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+ *	may be called after SK_INIT_IO without limitation
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrMcClear(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* I/O context */
+SK_U32	PortNumber,	/* Index of affected port */
+int		Flags)		/* permanent/non-perm, sw-only */
+{
+	int ReturnCode;
+
+	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+
+	if (pAC->GIni.GIGenesis) {
+#ifdef GENESIS
+		ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
+#endif
+	}
+	else {
+#ifdef YUKON
+		ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
+#endif
+	}
+
+	return (ReturnCode);
+
+}	/* SkAddrMcClear */
+
+#endif /* !SK_SLIM */
+
+#ifndef SK_SLIM
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkAddrXmacMcClear - clear the multicast table
+ *
+ * Description:
+ *	This routine clears the multicast table
+ *	(either entry 2 or entries 3-16 and InexactFilter) of the given port.
+ *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+ *	immediately.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+ *	may be called after SK_INIT_IO without limitation
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrXmacMcClear(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* I/O context */
+SK_U32	PortNumber,	/* Index of affected port */
+int		Flags)		/* permanent/non-perm, sw-only */
+{
+	int i;
+
+	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
+
+		/* Clear RLMT multicast addresses. */
+		pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+	}
+	else {	/* not permanent => DRV */
+
+		/* Clear InexactFilter */
+		for (i = 0; i < 8; i++) {
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+		}
+
+		/* Clear DRV multicast addresses. */
+
+		pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+	}
+
+	if (!(Flags & SK_MC_SW_ONLY)) {
+		(void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
+	}
+
+	return (SK_ADDR_SUCCESS);
+
+}	/* SkAddrXmacMcClear */
+#endif	/* GENESIS */
+#endif /* !SK_SLIM */
+
+#ifndef SK_SLIM
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkAddrGmacMcClear - clear the multicast table
+ *
+ * Description:
+ *	This routine clears the multicast hashing table (InexactFilter)
+ *	(either the RLMT or the driver bits) of the given port.
+ *
+ *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+ *	immediately.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+ *	may be called after SK_INIT_IO without limitation
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrGmacMcClear(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* I/O context */
+SK_U32	PortNumber,	/* Index of affected port */
+int		Flags)		/* permanent/non-perm, sw-only */
+{
+	int i;
+
+#ifdef DEBUG
+	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]));
+#endif	/* DEBUG */
+
+	/* Clear InexactFilter */
+	for (i = 0; i < 8; i++) {
+		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+	}
+
+	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
+
+		/* Copy DRV bits to InexactFilter. */
+		for (i = 0; i < 8; i++) {
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
+
+			/* Clear InexactRlmtFilter. */
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
+		}
+	}
+	else {	/* not permanent => DRV */
+
+		/* Copy RLMT bits to InexactFilter. */
+		for (i = 0; i < 8; i++) {
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
+
+			/* Clear InexactDrvFilter. */
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
+		}
+	}
+
+#ifdef DEBUG
+	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]));
+#endif	/* DEBUG */
+
+	if (!(Flags & SK_MC_SW_ONLY)) {
+		(void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
+	}
+
+	return (SK_ADDR_SUCCESS);
+
+}	/* SkAddrGmacMcClear */
+#endif	/* YUKON */
+
+#ifndef SK_ADDR_CHEAT
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmacMcHash - hash multicast address
+ *
+ * Description:
+ *	This routine computes the hash value for a multicast address.
+ *	A CRC32 algorithm is used.
+ *
+ * Notes:
+ *	The code was adapted from the XaQti data sheet.
+ *
+ * Context:
+ *	runtime, pageable
+ *
+ * Returns:
+ *	Hash value of multicast address.
+ */
+SK_U32 SkXmacMcHash(
+unsigned char *pMc)	/* Multicast address */
+{
+	SK_U32 Idx;
+	SK_U32 Bit;
+	SK_U32 Data;
+	SK_U32 Crc;
+
+	Crc = 0xFFFFFFFFUL;
+	for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
+		Data = *pMc++;
+		for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
+			Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
+		}
+	}
+
+	return (Crc & ((1 << HASH_BITS) - 1));
+
+}	/* SkXmacMcHash */
+#endif	/* GENESIS */
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkGmacMcHash - hash multicast address
+ *
+ * Description:
+ *	This routine computes the hash value for a multicast address.
+ *	A CRC16 algorithm is used.
+ *
+ * Notes:
+ *
+ *
+ * Context:
+ *	runtime, pageable
+ *
+ * Returns:
+ *	Hash value of multicast address.
+ */
+SK_U32 SkGmacMcHash(
+unsigned char *pMc)	/* Multicast address */
+{
+	SK_U32 Data;
+	SK_U32 TmpData;
+	SK_U32 Crc;
+	int Byte;
+	int Bit;
+
+	Crc = 0xFFFFFFFFUL;
+	for (Byte = 0; Byte < 6; Byte++) {
+		/* Get next byte. */
+		Data = (SK_U32) pMc[Byte];
+
+		/* Change bit order in byte. */
+		TmpData = Data;
+		for (Bit = 0; Bit < 8; Bit++) {
+			if (TmpData & 1L) {
+				Data |=  1L << (7 - Bit);
+			}
+			else {
+				Data &= ~(1L << (7 - Bit));
+			}
+			TmpData >>= 1;
+		}
+
+		Crc ^= (Data << 24);
+		for (Bit = 0; Bit < 8; Bit++) {
+			if (Crc & 0x80000000) {
+				Crc = (Crc << 1) ^ GMAC_POLY;
+			}
+			else {
+				Crc <<= 1;
+			}
+		}
+	}
+
+	return (Crc & ((1 << HASH_BITS) - 1));
+
+}	/* SkGmacMcHash */
+#endif	/* YUKON */
+#endif	/* !SK_ADDR_CHEAT */
+
+/******************************************************************************
+ *
+ *	SkAddrMcAdd - add a multicast address to a port
+ *
+ * Description:
+ *	This routine enables reception for a given address on the given port.
+ *
+ *	It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
+ *	adapter in use. The real work is done there.
+ *
+ * Notes:
+ *	The return code is only valid for SK_PROM_MODE_NONE.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_DATA
+ *
+ * Returns:
+ *	SK_MC_FILTERING_EXACT
+ *	SK_MC_FILTERING_INEXACT
+ *	SK_MC_ILLEGAL_ADDRESS
+ *	SK_MC_ILLEGAL_PORT
+ *	SK_MC_RLMT_OVERFLOW
+ */
+int	SkAddrMcAdd(
+SK_AC		*pAC,		/* adapter context */
+SK_IOC		IoC,		/* I/O context */
+SK_U32		PortNumber,	/* Port Number */
+SK_MAC_ADDR	*pMc,		/* multicast address to be added */
+int			Flags)		/* permanent/non-permanent */
+{
+	int ReturnCode;
+
+	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+
+	if (pAC->GIni.GIGenesis) {
+#ifdef GENESIS
+		ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
+#endif
+	}
+	else {
+#ifdef YUKON
+		ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
+#endif
+	}
+
+	return (ReturnCode);
+
+}	/* SkAddrMcAdd */
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkAddrXmacMcAdd - add a multicast address to a port
+ *
+ * Description:
+ *	This routine enables reception for a given address on the given port.
+ *
+ * Notes:
+ *	The return code is only valid for SK_PROM_MODE_NONE.
+ *
+ *	The multicast bit is only checked if there are no free exact match
+ *	entries.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_DATA
+ *
+ * Returns:
+ *	SK_MC_FILTERING_EXACT
+ *	SK_MC_FILTERING_INEXACT
+ *	SK_MC_ILLEGAL_ADDRESS
+ *	SK_MC_RLMT_OVERFLOW
+ */
+int	SkAddrXmacMcAdd(
+SK_AC		*pAC,		/* adapter context */
+SK_IOC		IoC,		/* I/O context */
+SK_U32		PortNumber,	/* Port Number */
+SK_MAC_ADDR	*pMc,		/* multicast address to be added */
+int		Flags)		/* permanent/non-permanent */
+{
+	int	i;
+	SK_U8	Inexact;
+#ifndef SK_ADDR_CHEAT
+	SK_U32 HashBit;
+#endif	/* !defined(SK_ADDR_CHEAT) */
+
+	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
+#ifdef xDEBUG
+		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
+			SK_ADDR_FIRST_MATCH_RLMT) {
+			Next0[PortNumber] |= 1;
+			return (SK_MC_RLMT_OVERFLOW);
+		}
+#endif	/* DEBUG */
+
+		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
+			SK_ADDR_LAST_MATCH_RLMT) {
+			return (SK_MC_RLMT_OVERFLOW);
+		}
+
+		/* Set a RLMT multicast address. */
+
+		pAC->Addr.Port[PortNumber].Exact[
+			pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
+
+		return (SK_MC_FILTERING_EXACT);
+	}
+
+#ifdef xDEBUG
+	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
+		SK_ADDR_FIRST_MATCH_DRV) {
+			Next0[PortNumber] |= 2;
+		return (SK_MC_RLMT_OVERFLOW);
+	}
+#endif	/* DEBUG */
+
+	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
+
+		/* Set exact match entry. */
+		pAC->Addr.Port[PortNumber].Exact[
+			pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
+
+		/* Clear InexactFilter */
+		for (i = 0; i < 8; i++) {
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+		}
+	}
+	else {
+		if (!(pMc->a[0] & SK_MC_BIT)) {
+			/* Hashing only possible with multicast addresses */
+			return (SK_MC_ILLEGAL_ADDRESS);
+		}
+#ifndef SK_ADDR_CHEAT
+		/* Compute hash value of address. */
+		HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
+
+		/* Add bit to InexactFilter. */
+		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
+			1 << (HashBit % 8);
+#else	/* SK_ADDR_CHEAT */
+		/* Set all bits in InexactFilter. */
+		for (i = 0; i < 8; i++) {
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
+		}
+#endif	/* SK_ADDR_CHEAT */
+	}
+
+	for (Inexact = 0, i = 0; i < 8; i++) {
+		Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+	}
+
+	if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
+		return (SK_MC_FILTERING_EXACT);
+	}
+	else {
+		return (SK_MC_FILTERING_INEXACT);
+	}
+
+}	/* SkAddrXmacMcAdd */
+#endif	/* GENESIS */
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkAddrGmacMcAdd - add a multicast address to a port
+ *
+ * Description:
+ *	This routine enables reception for a given address on the given port.
+ *
+ * Notes:
+ *	The return code is only valid for SK_PROM_MODE_NONE.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_DATA
+ *
+ * Returns:
+ *	SK_MC_FILTERING_INEXACT
+ *	SK_MC_ILLEGAL_ADDRESS
+ */
+int	SkAddrGmacMcAdd(
+SK_AC		*pAC,		/* adapter context */
+SK_IOC		IoC,		/* I/O context */
+SK_U32		PortNumber,	/* Port Number */
+SK_MAC_ADDR	*pMc,		/* multicast address to be added */
+int		Flags)		/* permanent/non-permanent */
+{
+	int	i;
+#ifndef SK_ADDR_CHEAT
+	SK_U32 HashBit;
+#endif	/* !defined(SK_ADDR_CHEAT) */
+
+	if (!(pMc->a[0] & SK_MC_BIT)) {
+		/* Hashing only possible with multicast addresses */
+		return (SK_MC_ILLEGAL_ADDRESS);
+	}
+
+#ifndef SK_ADDR_CHEAT
+
+	/* Compute hash value of address. */
+	HashBit = SkGmacMcHash(&pMc->a[0]);
+
+	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
+
+		/* Add bit to InexactRlmtFilter. */
+		pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
+			1 << (HashBit % 8);
+
+		/* Copy bit to InexactFilter. */
+		for (i = 0; i < 8; i++) {
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
+		}
+
+#ifdef DEBUG
+		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
+			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]));
+#endif	/* DEBUG */
+	}
+	else {	/* not permanent => DRV */
+
+		/* Add bit to InexactDrvFilter. */
+		pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
+			1 << (HashBit % 8);
+
+		/* Copy bit to InexactFilter. */
+		for (i = 0; i < 8; i++) {
+			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
+		}
+
+#ifdef DEBUG
+		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
+			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]));
+#endif	/* DEBUG */
+	}
+
+#else	/* SK_ADDR_CHEAT */
+
+	/* Set all bits in InexactFilter. */
+	for (i = 0; i < 8; i++) {
+		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
+	}
+#endif	/* SK_ADDR_CHEAT */
+
+	return (SK_MC_FILTERING_INEXACT);
+
+}	/* SkAddrGmacMcAdd */
+#endif	/* YUKON */
+#endif /* !SK_SLIM */
+
+/******************************************************************************
+ *
+ *	SkAddrMcUpdate - update the HW MC address table and set the MAC address
+ *
+ * Description:
+ *	This routine enables reception of the addresses contained in a local
+ *	table for a given port.
+ *	It also programs the port's current physical MAC address.
+ *
+ *	It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
+ *	to the adapter in use. The real work is done there.
+ *
+ * Notes:
+ *	The return code is only valid for SK_PROM_MODE_NONE.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	SK_MC_FILTERING_EXACT
+ *	SK_MC_FILTERING_INEXACT
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrMcUpdate(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* I/O context */
+SK_U32	PortNumber)	/* Port Number */
+{
+	int ReturnCode = SK_ADDR_ILLEGAL_PORT;
+
+#if (!defined(SK_SLIM) || defined(DEBUG))
+	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+#endif /* !SK_SLIM || DEBUG */
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
+	}
+#endif /* GENESIS */
+#ifdef YUKON
+	if (!pAC->GIni.GIGenesis) {
+		ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
+	}
+#endif /* YUKON */
+	return (ReturnCode);
+
+}	/* SkAddrMcUpdate */
+
+
+#ifdef GENESIS
+
+/******************************************************************************
+ *
+ *	SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
+ *
+ * Description:
+ *	This routine enables reception of the addresses contained in a local
+ *	table for a given port.
+ *	It also programs the port's current physical MAC address.
+ *
+ * Notes:
+ *	The return code is only valid for SK_PROM_MODE_NONE.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	SK_MC_FILTERING_EXACT
+ *	SK_MC_FILTERING_INEXACT
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrXmacMcUpdate(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* I/O context */
+SK_U32	PortNumber)	/* Port Number */
+{
+	SK_U32		i;
+	SK_U8		Inexact;
+	SK_U16		*OutAddr;
+	SK_ADDR_PORT	*pAPort;
+
+	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("SkAddrXmacMcUpdate on Port %u.\n", PortNumber));
+
+	pAPort = &pAC->Addr.Port[PortNumber];
+
+#ifdef DEBUG
+	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]));
+#endif /* DEBUG */
+
+	/* Start with 0 to also program the logical MAC address. */
+	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
+		/* Set exact match address i on XMAC */
+		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
+		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
+	}
+
+	/* Clear other permanent exact match addresses on XMAC */
+	if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
+
+		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
+			SK_ADDR_LAST_MATCH_RLMT);
+	}
+
+	for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
+		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
+		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
+	}
+
+	/* Clear other non-permanent exact match addresses on XMAC */
+	if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
+
+		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
+			SK_ADDR_LAST_MATCH_DRV);
+	}
+
+	for (Inexact = 0, i = 0; i < 8; i++) {
+		Inexact |= pAPort->InexactFilter.Bytes[i];
+	}
+
+	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
+
+		/* Set all bits in 64-bit hash register. */
+		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
+
+		/* Enable Hashing */
+		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+	}
+	else if (Inexact != 0) {
+
+		/* Set 64-bit hash register to InexactFilter. */
+		XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
+
+		/* Enable Hashing */
+		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+	}
+	else {
+		/* Disable Hashing */
+		SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
+	}
+
+	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
+		(void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+	}
+
+	/* Set port's current physical MAC address. */
+	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+
+	XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+
+#ifdef xDEBUG
+	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
+		SK_U8		InAddr8[6];
+		SK_U16		*InAddr;
+
+		/* Get exact match address i from port PortNumber. */
+		InAddr = (SK_U16 *) &InAddr8[0];
+
+		XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
+
+		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+			("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
+			 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
+				i,
+				PortNumber,
+				InAddr8[0],
+				InAddr8[1],
+				InAddr8[2],
+				InAddr8[3],
+				InAddr8[4],
+				InAddr8[5],
+				pAPort->Exact[i].a[0],
+				pAPort->Exact[i].a[1],
+				pAPort->Exact[i].a[2],
+				pAPort->Exact[i].a[3],
+				pAPort->Exact[i].a[4],
+				pAPort->Exact[i].a[5]));
+	}
+#endif /* DEBUG */
+
+	/* Determine return value. */
+	if (Inexact == 0 && pAPort->PromMode == 0) {
+		return (SK_MC_FILTERING_EXACT);
+	}
+	else {
+		return (SK_MC_FILTERING_INEXACT);
+	}
+
+}	/* SkAddrXmacMcUpdate */
+
+#endif  /* GENESIS */
+
+#ifdef YUKON
+
+/******************************************************************************
+ *
+ *	SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
+ *
+ * Description:
+ *	This routine enables reception of the addresses contained in a local
+ *	table for a given port.
+ *	It also programs the port's current physical MAC address.
+ *
+ * Notes:
+ *	The return code is only valid for SK_PROM_MODE_NONE.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	SK_MC_FILTERING_EXACT
+ *	SK_MC_FILTERING_INEXACT
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrGmacMcUpdate(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* I/O context */
+SK_U32	PortNumber)	/* Port Number */
+{
+#ifndef SK_SLIM
+	SK_U32		i;
+	SK_U8		Inexact;
+#endif	/* not SK_SLIM */
+	SK_U16		*OutAddr;
+	SK_ADDR_PORT	*pAPort;
+
+	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("SkAddrGmacMcUpdate on Port %u.\n", PortNumber));
+
+	pAPort = &pAC->Addr.Port[PortNumber];
+
+#ifdef DEBUG
+	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]));
+#endif /* DEBUG */
+
+#ifndef SK_SLIM
+	for (Inexact = 0, i = 0; i < 8; i++) {
+		Inexact |= pAPort->InexactFilter.Bytes[i];
+	}
+
+	/* Set 64-bit hash register to InexactFilter. */
+	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
+		&pAPort->InexactFilter.Bytes[0]);
+
+	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
+
+		/* Set all bits in 64-bit hash register. */
+		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+
+		/* Enable Hashing */
+		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+	}
+	else {
+		/* Enable Hashing. */
+		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+	}
+
+	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
+		(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+	}
+#else /* SK_SLIM */
+
+	/* Set all bits in 64-bit hash register. */
+	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+
+	/* Enable Hashing */
+	SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+
+	(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+
+#endif /* SK_SLIM */
+
+	/* Set port's current physical MAC address. */
+	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
+
+	/* Set port's current logical MAC address. */
+	OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
+	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
+
+#ifdef DEBUG
+	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+			pAPort->Exact[0].a[0],
+			pAPort->Exact[0].a[1],
+			pAPort->Exact[0].a[2],
+			pAPort->Exact[0].a[3],
+			pAPort->Exact[0].a[4],
+			pAPort->Exact[0].a[5]));
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+		("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+			pAPort->CurrentMacAddress.a[0],
+			pAPort->CurrentMacAddress.a[1],
+			pAPort->CurrentMacAddress.a[2],
+			pAPort->CurrentMacAddress.a[3],
+			pAPort->CurrentMacAddress.a[4],
+			pAPort->CurrentMacAddress.a[5]));
+#endif /* DEBUG */
+
+#ifndef SK_SLIM
+	/* Determine return value. */
+	if (Inexact == 0 && pAPort->PromMode == 0) {
+		return (SK_MC_FILTERING_EXACT);
+	}
+	else {
+		return (SK_MC_FILTERING_INEXACT);
+	}
+#else /* SK_SLIM */
+	return (SK_MC_FILTERING_INEXACT);
+#endif /* SK_SLIM */
+
+}	/* SkAddrGmacMcUpdate */
+
+#endif /* YUKON */
+
+#ifndef SK_NO_MAO
+
+/******************************************************************************
+ *
+ *	SkAddrOverride - override a port's MAC address
+ *
+ * Description:
+ *	This routine overrides the MAC address of one port.
+ *
+ * NOTE: It can be called with pNewAddr set to NULL from the RLMT module!
+ *       This is correct in combination with Flags set to SK_ADDR_SET_LOGICAL
+ *       or SK_ADDR_CLEAR_LOGICAL. All other calls will be handled as an error
+ *       and SK_MC_ILLEGAL_ADDRESS will be returned then.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS if successful.
+ *	SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
+ *	SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
+ *	SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
+ */
+int	SkAddrOverride(
+SK_AC		*pAC,				/* adapter context */
+SK_IOC		IoC,				/* I/O context */
+SK_U32		PortNumber,			/* Port Number */
+SK_MAC_ADDR	SK_FAR *pNewAddr,	/* new MAC address */
+int			Flags)				/* logical/physical MAC address */
+{
+#ifndef SK_NO_RLMT
+	SK_EVPARA	Para;
+#endif /* !SK_NO_RLMT */
+	SK_U32		NetNumber;
+	SK_U32		i;
+	SK_U16		SK_FAR *OutAddr;
+
+#ifndef SK_NO_RLMT
+	NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
+#else
+	NetNumber = 0;
+#endif /* SK_NO_RLMT */
+#if (!defined(SK_SLIM) || defined(DEBUG))
+	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+#endif /* !SK_SLIM || DEBUG */
+
+	if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
+		return (SK_ADDR_MULTICAST_ADDRESS);
+	}
+
+	if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
+		return (SK_ADDR_TOO_EARLY);
+	}
+
+	if (Flags & SK_ADDR_SET_LOGICAL) {	/* Activate logical MAC address. */
+		/* Parameter *pNewAddr is ignored. */
+		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+				return (SK_ADDR_TOO_EARLY);
+			}
+		}
+#ifndef SK_NO_RLMT
+		/* Set PortNumber to number of net's active port. */
+		PortNumber = pAC->Rlmt.Net[NetNumber].
+			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+#endif /* !SK_NO_RLMT */
+		pAC->Addr.Port[PortNumber].Exact[0] =
+			pAC->Addr.Net[NetNumber].CurrentMacAddress;
+
+		/* Write address to first exact match entry of active port. */
+		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+	}
+	else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
+		/* Deactivate logical MAC address. */
+		/* Parameter *pNewAddr is ignored. */
+		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+				return (SK_ADDR_TOO_EARLY);
+			}
+		}
+#ifndef SK_NO_RLMT
+		/* Set PortNumber to number of net's active port. */
+		PortNumber = pAC->Rlmt.Net[NetNumber].
+			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+#endif /* !SK_NO_RLMT */
+		for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
+			pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
+		}
+
+		/* Write address to first exact match entry of active port. */
+		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+	}
+	else if (pNewAddr == NULL) {
+		/* Prevent accessing a NULL pointer (was complained by Prefast)  */
+		return (SK_MC_ILLEGAL_ADDRESS);
+	}
+	else {
+		if (Flags & SK_ADDR_PHYSICAL_ADDRESS) {	/* Physical MAC address. */
+				
+			for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+				if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+					return (SK_ADDR_TOO_EARLY);
+				}
+			}
+
+			/*
+			 * In dual net mode it should be possible to set all MAC
+			 * addresses independently. Therefore the equality checks
+			 * against the locical address of the same port and the
+			 * physical address of the other port are suppressed here.
+			 */
+#ifndef SK_NO_RLMT
+			if (pAC->Rlmt.NumNets == 1) {
+#endif /* SK_NO_RLMT */
+				if (SK_ADDR_EQUAL(pNewAddr->a,
+					pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
+					return (SK_ADDR_DUPLICATE_ADDRESS);
+				}
+
+				for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+					if (SK_ADDR_EQUAL(pNewAddr->a,
+						pAC->Addr.Port[i].CurrentMacAddress.a)) {
+						if (i == PortNumber) {
+							return (SK_ADDR_SUCCESS);
+						}
+						else {
+							return (SK_ADDR_DUPLICATE_ADDRESS);
+						}
+					}
+				}
+#ifndef SK_NO_RLMT
+			}
+			else {
+				if (SK_ADDR_EQUAL(pNewAddr->a,
+					pAC->Addr.Port[PortNumber].CurrentMacAddress.a)) {
+					return (SK_ADDR_SUCCESS);
+				}
+			}
+#endif /* SK_NO_RLMT */
+
+			pAC->Addr.Port[PortNumber].PreviousMacAddress =
+				pAC->Addr.Port[PortNumber].CurrentMacAddress;
+			pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
+
+			/* Change port's physical MAC address. */
+			OutAddr = (SK_U16 SK_FAR *) pNewAddr;
+#ifdef GENESIS
+			if (pAC->GIni.GIGenesis) {
+				XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+			}
+#endif /* GENESIS */
+#ifdef YUKON
+			if (!pAC->GIni.GIGenesis) {
+				GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
+			}
+#endif /* YUKON */
+
+#ifndef SK_NO_RLMT
+			/* Report address change to RLMT. */
+			Para.Para32[0] = PortNumber;
+			Para.Para32[0] = -1;
+			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
+#endif /* !SK_NO_RLMT */
+		}
+		else {	/* Logical MAC address. */
+			if (SK_ADDR_EQUAL(pNewAddr->a,
+				pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
+				return (SK_ADDR_SUCCESS);
+			}
+
+			for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+				if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+					return (SK_ADDR_TOO_EARLY);
+				}
+			}
+
+			/*
+			 * In dual net mode on Yukon-2 adapters the physical address
+			 * of port 0 and the logical address of port 1 are equal - in
+			 * this case the equality check of the physical address leads
+			 * to an error and is suppressed here.
+			 */
+#ifndef SK_NO_RLMT
+			if (pAC->Rlmt.NumNets == 1) {
+#endif /* SK_NO_RLMT */
+				for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+					if (SK_ADDR_EQUAL(pNewAddr->a,
+						pAC->Addr.Port[i].CurrentMacAddress.a)) {
+						return (SK_ADDR_DUPLICATE_ADDRESS);
+					}
+				}
+#ifndef SK_NO_RLMT
+			}
+#endif /* SK_NO_RLMT */
+
+			/*
+			 * In case that the physical and the logical MAC addresses are equal
+			 * we must also change the physical MAC address here.
+			 * In this case we have an adapter which initially was programmed with
+			 * two identical MAC addresses.
+			 */
+			if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
+					pAC->Addr.Port[PortNumber].Exact[0].a)) {
+
+				pAC->Addr.Port[PortNumber].PreviousMacAddress =
+					pAC->Addr.Port[PortNumber].CurrentMacAddress;
+				pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
+
+#ifndef SK_NO_RLMT
+				/* Report address change to RLMT. */
+				Para.Para32[0] = PortNumber;
+				Para.Para32[0] = -1;
+				SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
+#endif /* !SK_NO_RLMT */
+			}
+
+#ifndef SK_NO_RLMT
+			/* Set PortNumber to number of net's active port. */
+			PortNumber = pAC->Rlmt.Net[NetNumber].
+				Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+#endif /* !SK_NO_RLMT */
+			pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
+			pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
+#ifdef DEBUG
+			SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+				("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
+					pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
+					pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
+					pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
+					pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
+					pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
+					pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]));
+
+			SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+				("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+					pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
+					pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
+					pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
+					pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
+					pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
+					pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]));
+#endif /* DEBUG */
+
+			/* Write address to first exact match entry of active port. */
+			(void)SkAddrMcUpdate(pAC, IoC, PortNumber);
+		}
+	}
+
+	return (SK_ADDR_SUCCESS);
+
+}	/* SkAddrOverride */
+
+#endif /* SK_NO_MAO */
+
+/******************************************************************************
+ *
+ *	SkAddrPromiscuousChange - set promiscuous mode for given port
+ *
+ * Description:
+ *	This routine manages promiscuous mode:
+ *	- none
+ *	- all LLC frames
+ *	- all MC frames
+ *
+ *	It calls either SkAddrXmacPromiscuousChange or
+ *	SkAddrGmacPromiscuousChange, according to the adapter in use.
+ *	The real work is done there.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrPromiscuousChange(
+SK_AC	*pAC,			/* adapter context */
+SK_IOC	IoC,			/* I/O context */
+SK_U32	PortNumber,		/* port whose promiscuous mode changes */
+int		NewPromMode)	/* new promiscuous mode */
+{
+	int ReturnCode = SK_ADDR_ILLEGAL_PORT;
+
+#if (!defined(SK_SLIM) || defined(DEBUG))
+	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+#endif /* !SK_SLIM || DEBUG */
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		ReturnCode =
+			SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
+	}
+#endif /* GENESIS */
+#ifdef YUKON
+	if (!pAC->GIni.GIGenesis) {
+		ReturnCode =
+			SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
+	}
+#endif /* YUKON */
+
+	return (ReturnCode);
+
+}	/* SkAddrPromiscuousChange */
+
+#ifdef GENESIS
+
+/******************************************************************************
+ *
+ *	SkAddrXmacPromiscuousChange - set promiscuous mode for given port
+ *
+ * Description:
+ *	This routine manages promiscuous mode:
+ *	- none
+ *	- all LLC frames
+ *	- all MC frames
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrXmacPromiscuousChange(
+SK_AC	*pAC,			/* adapter context */
+SK_IOC	IoC,			/* I/O context */
+SK_U32	PortNumber,		/* port whose promiscuous mode changes */
+int		NewPromMode)	/* new promiscuous mode */
+{
+	int			i;
+	SK_BOOL		InexactModeBit;
+	SK_U8		Inexact;
+	SK_U8		HwInexact;
+	SK_FILTER64	HwInexactFilter;
+	SK_U16		LoMode;		/* Lower 16 bits of XMAC Mode Register. */
+	int			CurPromMode = SK_PROM_MODE_NONE;
+
+	/* Read CurPromMode from Hardware. */
+	XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
+
+	if ((LoMode & XM_MD_ENA_PROM) != 0) {
+		/* Promiscuous mode! */
+		CurPromMode |= SK_PROM_MODE_LLC;
+	}
+
+	for (Inexact = 0xFF, i = 0; i < 8; i++) {
+		Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+	}
+
+	if (Inexact == 0xFF) {
+		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
+	}
+	else {
+		/* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
+		XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
+
+		InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
+
+		/* Read 64-bit hash register from XMAC */
+		XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
+
+		for (HwInexact = 0xFF, i = 0; i < 8; i++) {
+			HwInexact &= HwInexactFilter.Bytes[i];
+		}
+
+		if (InexactModeBit && (HwInexact == 0xFF)) {
+			CurPromMode |= SK_PROM_MODE_ALL_MC;
+		}
+	}
+
+	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
+
+	if (NewPromMode == CurPromMode) {
+		return (SK_ADDR_SUCCESS);
+	}
+
+	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
+		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC. */
+
+		/* Set all bits in 64-bit hash register. */
+		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
+
+		/* Enable Hashing */
+		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+	}
+	else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
+		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm MC. */
+		for (Inexact = 0, i = 0; i < 8; i++) {
+			Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+		}
+		if (Inexact == 0) {
+			/* Disable Hashing */
+			SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
+		}
+		else {
+			/* Set 64-bit hash register to InexactFilter. */
+			XM_OUTHASH(IoC, PortNumber, XM_HSM,
+				&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
+
+			/* Enable Hashing */
+			SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+		}
+	}
+
+	if ((NewPromMode & SK_PROM_MODE_LLC) &&
+		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
+		/* Set the MAC in Promiscuous Mode */
+		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
+	}
+	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
+		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC. */
+		/* Clear Promiscuous Mode */
+		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
+	}
+
+	return (SK_ADDR_SUCCESS);
+
+}	/* SkAddrXmacPromiscuousChange */
+
+#endif /* GENESIS */
+
+#ifdef YUKON
+
+/******************************************************************************
+ *
+ *	SkAddrGmacPromiscuousChange - set promiscuous mode for given port
+ *
+ * Description:
+ *	This routine manages promiscuous mode:
+ *	- none
+ *	- all LLC frames
+ *	- all MC frames
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrGmacPromiscuousChange(
+SK_AC	*pAC,			/* adapter context */
+SK_IOC	IoC,			/* I/O context */
+SK_U32	PortNumber,		/* port whose promiscuous mode changes */
+int		NewPromMode)	/* new promiscuous mode */
+{
+	if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+
+	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
+
+	switch(NewPromMode) {
+	case (SK_PROM_MODE_NONE):							/* 0 */
+
+		/* Normal receive mode */
+		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
+		break;
+
+	case (SK_PROM_MODE_LLC):							/* 1 */
+		/* This mode is ignored and mapped to prom. mode */
+	case (SK_PROM_MODE_LLC | SK_PROM_MODE_ALL_MC):		/* 3 */
+
+		/* Set the MAC to promiscuous mode. */
+		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
+		break;
+
+	case (SK_PROM_MODE_ALL_MC):							/* 2 */
+
+		/* Disable MC hashing */
+		SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
+		break;
+
+	default:
+		break;
+	}
+
+	return (SK_ADDR_SUCCESS);
+}	/* SkAddrGmacPromiscuousChange */
+
+#endif /* YUKON */
+
+#ifndef SK_SLIM
+
+/******************************************************************************
+ *
+ *	SkAddrSwap - swap address info
+ *
+ * Description:
+ *	This routine swaps address info of two ports.
+ *
+ * Context:
+ *	runtime, pageable
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	SK_ADDR_SUCCESS
+ *	SK_ADDR_ILLEGAL_PORT
+ */
+int	SkAddrSwap(
+SK_AC	*pAC,			/* adapter context */
+SK_IOC	IoC,			/* I/O context */
+SK_U32	FromPortNumber,		/* Port1 Index */
+SK_U32	ToPortNumber)		/* Port2 Index */
+{
+	int			i;
+	SK_U8		Byte;
+	SK_MAC_ADDR	MacAddr;
+	SK_U32		DWord;
+
+	if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+
+	if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+
+	if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
+		return (SK_ADDR_ILLEGAL_PORT);
+	}
+
+	/*
+	 * Swap:
+	 * - Exact Match Entries (GEnesis and Yukon)
+	 *   Yukon uses first entry for the logical MAC
+	 *   address (stored in the second GMAC register).
+	 * - FirstExactMatchRlmt (GEnesis only)
+	 * - NextExactMatchRlmt (GEnesis only)
+	 * - FirstExactMatchDrv (GEnesis only)
+	 * - NextExactMatchDrv (GEnesis only)
+	 * - 64-bit filter (InexactFilter)
+	 * - Promiscuous Mode
+	 * of ports.
+	 */
+
+	for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
+		MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
+		pAC->Addr.Port[FromPortNumber].Exact[i] =
+			pAC->Addr.Port[ToPortNumber].Exact[i];
+		pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
+	}
+
+	for (i = 0; i < 8; i++) {
+		Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
+		pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
+			pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
+		pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
+	}
+
+	i = pAC->Addr.Port[FromPortNumber].PromMode;
+	pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
+	pAC->Addr.Port[ToPortNumber].PromMode = i;
+
+	if (pAC->GIni.GIGenesis) {
+		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
+		pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
+			pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
+		pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
+
+		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
+		pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
+			pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
+		pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
+
+		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
+		pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
+			pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
+		pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
+
+		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
+		pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
+			pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
+		pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
+	}
+
+	/* CAUTION: Solution works if only ports of one adapter are in use. */
+	for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
+		Net->NetNumber].NumPorts; i++) {
+		if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
+			Port[i]->PortNumber == ToPortNumber) {
+			pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
+				ActivePort = i;
+			/* 20001207 RA: Was "ToPortNumber;". */
+		}
+	}
+
+	(void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
+	(void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
+
+	return (SK_ADDR_SUCCESS);
+
+}	/* SkAddrSwap */
+
+#endif /* !SK_SLIM */
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
diff --git a/drivers/net/sk98lin/skcsum.c b/drivers/net/sk98lin/skcsum.c
new file mode 100755
index 0000000..d8e516c
--- /dev/null
+++ b/drivers/net/sk98lin/skcsum.c
@@ -0,0 +1,1138 @@
+/******************************************************************************
+ *
+ * Name:	skcsum.c
+ * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 2.4 $
+ * Date:	$Date: 2007/03/14 16:20:40 $
+ * Purpose:	Store/verify Internet checksum in send/receive packets.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2003 SysKonnect GmbH.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#ifdef SK_USE_CSUM	/* Check if CSUM is to be used. */
+
+#ifndef lint
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skcsum.c,v 2.4 2007/03/14 16:20:40 rassmann Exp $ (C) SysKonnect.";
+#endif	/* !lint */
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * This is the "GEnesis" common module "CSUM".
+ *
+ * This module contains the code necessary to calculate, store, and verify the
+ * Internet Checksum of IP, TCP, and UDP frames.
+ *
+ * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
+ * and is the code name of this SysKonnect project.
+ *
+ * Compilation Options:
+ *
+ *	SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
+ *	empty module.
+ *
+ *	SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
+ *	definitions. In this case, all SKCS_PROTO_xxx definitions must be made
+ *	external.
+ *
+ *	SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
+ *	definitions. In this case, all SKCS_STATUS_xxx definitions must be made
+ *	external.
+ *
+ * Include File Hierarchy:
+ *
+ *	"h/skdrv1st.h"
+ *	"h/skcsum.h"
+ *	"h/sktypes.h"
+ *	"h/skqueue.h"
+ *	"h/skdrv2nd.h"
+ *
+ ******************************************************************************/
+
+#include "h/skdrv1st.h"
+#include "h/skcsum.h"
+#include "h/skdrv2nd.h"
+
+/* defines ********************************************************************/
+
+/* The size of an Ethernet MAC header. */
+#define SKCS_ETHERNET_MAC_HEADER_SIZE			(6+6+2)
+
+/* The size of the used topology's MAC header. */
+#define	SKCS_MAC_HEADER_SIZE	SKCS_ETHERNET_MAC_HEADER_SIZE
+
+/*
+ * Field offsets within the IPv4 header.
+ */
+
+/* "Internet Header Version" and "Length". */
+#define SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH	0
+
+/* "Total Length". */
+#define SKCS_OFS_IP_TOTAL_LENGTH				2
+
+/* "Flags" "Fragment Offset". */
+#define SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET	6
+
+/* "Next Level Protocol" identifier. */
+#define SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL			9
+
+/* Source IP address. */
+#define SKCS_OFS_IP_SOURCE_ADDRESS				12
+
+/* Destination IP address. */
+#define SKCS_OFS_IP_DESTINATION_ADDRESS			16
+
+#ifdef SK_IPV6_SUPPORT
+/*
+ * Field offsets in the IPv6 header
+ */
+
+/* Payload length field (size without IP header) */
+#define SKCS_OFS_IP6_PAYLOAD_LENGTH				4
+
+/* Next header identifier */
+#define SKCS_OFS_IP6_NEXT_HEADER				6
+
+/* Source IP adress (16 byte) */
+#define SKCS_OFS_IP6_SOURCE_ADDRESS				8
+
+/* Destination IP address (16 byte) */
+#define SKCS_OFS_IP6_DESTINATION_ADDRESS		32
+
+#endif	/* SK_IPV6_SUPPORT */
+
+/*
+ * Field offsets within the UDP header.
+ */
+
+/* UDP checksum. */
+#define SKCS_OFS_UDP_CHECKSUM					6
+
+/* IP "Next Level Protocol" identifiers (see RFC 790). */
+#define SKCS_PROTO_ID_TCP		6	/* Transport Control Protocol */
+#define SKCS_PROTO_ID_UDP		17	/* User Datagram Protocol */
+#ifdef SK_IPV6_SUPPORT
+#define SKCS_PROTO_ID_ICMPV6	58	/* ICMPv6 */
+#define SKCS_PROTO_ID_NONE		59	/* No next header (used with IPv6) */
+#endif	/* SK_IPV6_SUPPORT */
+
+/* IP "Don't Fragment" bit. */
+#define SKCS_IP_DONT_FRAGMENT	SKCS_HTON16(0x4000)
+
+/* Add a byte offset to a pointer. */
+#define SKCS_IDX(pPtr, Ofs)	((void *) ((char *) (pPtr) + (Ofs)))
+
+/* Check whether offset is within buffer. */
+#define SKCS_IDX_CHECK(Le, Ofs)	((Le) <= (Ofs))
+
+/*
+ * Macros that convert host to network representation and vice versa, i.e.
+ * little/big endian conversion on little endian machines only.
+ */
+#ifdef SK_LITTLE_ENDIAN
+#define SKCS_HTON16(Val16)	(((unsigned) (Val16) >> 8) | (((Val16) & 0xff) << 8))
+#endif	/* SK_LITTLE_ENDIAN */
+#ifdef SK_BIG_ENDIAN
+#define SKCS_HTON16(Val16)	(Val16)
+#endif	/* SK_BIG_ENDIAN */
+#define SKCS_NTOH16(Val16)	SKCS_HTON16(Val16)
+
+/* typedefs *******************************************************************/
+
+/* function prototypes ********************************************************/
+
+/******************************************************************************
+ *
+ *	SkCsGetSendInfo - get checksum information for a send packet
+ *
+ * Description:
+ *	Get all checksum information necessary to send a TCP or UDP packet. The
+ *	function checks the IP header passed to it. If the high-level protocol
+ *	is either TCP or UDP the pseudo header checksum is calculated and
+ *	returned.
+ *
+ *	The function returns the total length of the IP header (including any
+ *	IP option fields), which is the same as the start offset of the IP data
+ *	which in turn is the start offset of the TCP or UDP header.
+ *
+ *	The function also returns the TCP or UDP pseudo header checksum, which
+ *	should be used as the start value for the hardware checksum calculation.
+ *	(Note that any actual pseudo header checksum can never calculate to
+ *	zero.)
+ *
+ * Note:
+ *	There is a bug in the GENESIS ASIC which may lead to wrong checksums.
+ *
+ * Arguments:
+ *	pAc - A pointer to the adapter context struct.
+ *
+ *	pIpHeader - Pointer to IP header. Must be at least the IP header *not*
+ *	including any option fields, i.e. at least 20 bytes.
+ *
+ *	Note: This pointer will be used to address 8-, 16-, and 32-bit
+ *	variables with the respective alignment offsets relative to the pointer.
+ *	Thus, the pointer should point to a 32-bit aligned address. If the
+ *	target system cannot address 32-bit variables on non 32-bit aligned
+ *	addresses, then the pointer *must* point to a 32-bit aligned address.
+ *
+ *	pPacketInfo - A pointer to the packet information structure for this
+ *	packet. Before calling this SkCsGetSendInfo(), the following field must
+ *	be initialized:
+ *
+ *		ProtocolFlags - Initialize with any combination of
+ *		SKCS_PROTO_XXX bit flags. SkCsGetSendInfo() will only work on
+ *		the protocols specified here. Any protocol(s) not specified
+ *		here will be ignored.
+ *
+ *		Note: Only one checksum can be calculated in hardware. Thus, if
+ *		SKCS_PROTO_IP is specified in the 'ProtocolFlags',
+ *		SkCsGetSendInfo() must calculate the IP header checksum in
+ *		software. It might be a better idea to have the calling
+ *		protocol stack calculate the IP header checksum.
+ *
+ * Returns: N/A
+ *	On return, the following fields in 'pPacketInfo' may or may not have
+ *	been filled with information, depending on the protocol(s) found in the
+ *	packet:
+ *
+ *	ProtocolFlags - Returns the SKCS_PROTO_XXX bit flags of the protocol(s)
+ *	that were both requested by the caller and actually found in the packet.
+ *	Protocol(s) not specified by the caller and/or not found in the packet
+ *	will have their respective SKCS_PROTO_XXX bit flags reset.
+ *
+ *	Note: For IP fragments, TCP and UDP packet information is ignored.
+ *
+ *	IpHeaderLength - The total length in bytes of the complete IP header
+ *	including any option fields is returned here. This is the start offset
+ *	of the IP data, i.e. the TCP or UDP header if present.
+ *
+ *	IpHeaderChecksum - If IP has been specified in the 'ProtocolFlags', the
+ *	16-bit Internet Checksum of the IP header is returned here. This value
+ *	is to be stored into the packet's 'IP Header Checksum' field.
+ *
+ *	PseudoHeaderChecksum - If this is a TCP or UDP packet and if TCP or UDP
+ *	has been specified in the 'ProtocolFlags', the 16-bit Internet Checksum
+ *	of the TCP or UDP pseudo header is returned here.
+ */
+void SkCsGetSendInfo(
+SK_AC				*pAc,			/* Adapter context struct. */
+void				*pIpHeader,		/* IP header. */
+SKCS_PACKET_INFO	*pPacketInfo,	/* Packet information struct. */
+int					NetNumber)		/* Net number */
+{
+	/* Internet Header Version found in IP header. */
+	unsigned InternetHeaderVersion;
+
+	/* Length of the IP header as found in IP header. */
+	unsigned IpHeaderLength;
+
+	/* Bit field specifiying the desired/found protocols. */
+	unsigned ProtocolFlags;
+
+	/* Next level protocol identifier found in IP header. */
+	unsigned NextLevelProtocol;
+
+	/* Length of IP data portion. */
+	unsigned IpDataLength;
+
+	/* TCP/UDP pseudo header checksum. */
+	unsigned long PseudoHeaderChecksum;
+
+	/* Pointer to next level protocol statistics structure. */
+	SKCS_PROTO_STATS *NextLevelProtoStats;
+
+	/* Temporary variable. */
+	unsigned Tmp;
+
+	Tmp = *(SK_U8 *)
+		SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH);
+
+	/* Get the Internet Header Version (IHV). */
+	/* Note: The IHV is stored in the upper four bits. */
+
+	InternetHeaderVersion = Tmp >> 4;
+
+	/* Check the Internet Header Version. */
+	/* Note: We currently only support IP version 4. */
+
+	if (InternetHeaderVersion != 4) {	/* IPv4? */
+		SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX,
+			("Tx: Unknown Internet Header Version %u.\n",
+			InternetHeaderVersion));
+		pPacketInfo->ProtocolFlags = 0;
+		pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++;
+		return;
+	}
+
+	/* Get the IP header length (IHL). */
+	/*
+	 * Note: The IHL is stored in the lower four bits as the number of
+	 * 4-byte words.
+	 */
+
+	IpHeaderLength = (Tmp & 0xf) * 4;
+	pPacketInfo->IpHeaderLength = IpHeaderLength;
+
+	/* Check the IP header length. */
+
+	/* 04-Aug-1998 sw - Really check the IHL? Necessary? */
+
+	if (IpHeaderLength < 5*4) {
+		SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX,
+			("Tx: Invalid IP Header Length %u.\n", IpHeaderLength));
+		pPacketInfo->ProtocolFlags = 0;
+		pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++;
+		return;
+	}
+
+	/* This is an IPv4 frame with a header of valid length. */
+
+	pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxOkCts++;
+
+	/* Check if we should calculate the IP header checksum. */
+
+	ProtocolFlags = pPacketInfo->ProtocolFlags;
+
+	if (ProtocolFlags & SKCS_PROTO_IP) {
+		pPacketInfo->IpHeaderChecksum =
+			SkCsCalculateChecksum(pIpHeader, IpHeaderLength);
+	}
+
+	/* Get the next level protocol identifier. */
+
+	NextLevelProtocol =
+		*(SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL);
+
+	/*
+	 * Check if this is a TCP or UDP frame and if we should calculate the
+	 * TCP/UDP pseudo header checksum.
+	 *
+	 * Also clear all protocol bit flags of protocols not present in the
+	 * frame.
+	 */
+
+	if ((ProtocolFlags & SKCS_PROTO_TCP) != 0 &&
+		NextLevelProtocol == SKCS_PROTO_ID_TCP) {
+		/* TCP/IP frame. */
+		ProtocolFlags &= SKCS_PROTO_TCP | SKCS_PROTO_IP;
+		NextLevelProtoStats =
+			&pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP];
+	}
+	else if ((ProtocolFlags & SKCS_PROTO_UDP) != 0 &&
+		NextLevelProtocol == SKCS_PROTO_ID_UDP) {
+		/* UDP/IP frame. */
+		ProtocolFlags &= SKCS_PROTO_UDP | SKCS_PROTO_IP;
+		NextLevelProtoStats =
+			&pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP];
+	}
+	else {
+		/*
+		 * Either not a TCP or UDP frame and/or TCP/UDP processing not
+		 * specified.
+		 */
+		pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP;
+		return;
+	}
+
+	/* Check if this is an IP fragment. */
+
+	/*
+	 * Note: An IP fragment has a non-zero "Fragment Offset" field and/or
+	 * the "More Fragments" bit set. Thus, if both the "Fragment Offset"
+	 * and the "More Fragments" are zero, it is *not* a fragment. We can
+	 * easily check both at the same time since they are in the same 16-bit
+	 * word.
+	 */
+
+	if ((*(SK_U16 *)
+		SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) &
+		~SKCS_IP_DONT_FRAGMENT) != 0) {
+		/* IP fragment; ignore all other protocols. */
+		pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP;
+		NextLevelProtoStats->TxUnableCts++;
+		return;
+	}
+
+	/*
+	 * Calculate the TCP/UDP pseudo header checksum.
+	 */
+
+	/* Get total length of IP header and data. */
+
+	IpDataLength =
+		*(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH);
+
+	/* Get length of IP data portion. */
+
+	IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength;
+
+	/* Calculate the sum of all pseudo header fields (16-bit). */
+
+	PseudoHeaderChecksum =
+		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
+			SKCS_OFS_IP_SOURCE_ADDRESS + 0) +
+		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
+			SKCS_OFS_IP_SOURCE_ADDRESS + 2) +
+		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
+			SKCS_OFS_IP_DESTINATION_ADDRESS + 0) +
+		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
+			SKCS_OFS_IP_DESTINATION_ADDRESS + 2) +
+		(unsigned long) SKCS_HTON16(NextLevelProtocol) +
+		(unsigned long) SKCS_HTON16(IpDataLength);
+	
+	/* Add-in any carries. */
+
+	SKCS_OC_ADD(PseudoHeaderChecksum, PseudoHeaderChecksum, 0);
+
+	/* Add-in any new carry. */
+
+	SKCS_OC_ADD(pPacketInfo->PseudoHeaderChecksum, PseudoHeaderChecksum, 0);
+
+	pPacketInfo->ProtocolFlags = ProtocolFlags;
+	NextLevelProtoStats->TxOkCts++;	/* Success. */
+}	/* SkCsGetSendInfo */
+
+
+/******************************************************************************
+ *
+ *	SkCsGetReceiveInfo - verify checksum information for a received packet
+ *
+ * Description:
+ *	Verify a received frame's checksum. The function returns a status code
+ *	reflecting the result of the verification.
+ *
+ * Note:
+ *	Before calling this function you have to verify that the frame is
+ *	not padded and Checksum1 and Checksum2 are bigger than 1.
+ *
+ * Arguments:
+ *	pAc - Pointer to adapter context struct.
+ *
+ *	pIpHeader - Pointer to IP header. Must be at least the length in bytes
+ *	of the received IP header including any option fields. For UDP packets,
+ *	8 additional bytes are needed to access the UDP checksum.
+ *
+ *	Note: The actual length of the IP header is stored in the lower four
+ *	bits of the first octet of the IP header as the number of 4-byte words,
+ *	so it must be multiplied by four to get the length in bytes. Thus, the
+ *	maximum IP header length is 15 * 4 = 60 bytes.
+ *
+ *	Checksum1 - The first 16-bit Internet Checksum calculated by the
+ *	hardware starting at the offset returned by SkCsSetReceiveFlags().
+ *
+ *	Checksum2 - The second 16-bit Internet Checksum calculated by the
+ *	hardware starting at the offset returned by SkCsSetReceiveFlags().
+ *
+ *  NetNumber - The net number.
+ *
+ *  Len - The packet length (without MAC header) - never access memory
+ *	behind pIpHeader[Len].
+ *
+ * Returns:
+ *	SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
+ *	SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
+ *	SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
+ *	SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
+ *	SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
+ *	SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
+ *	SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
+ *	SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
+ *	SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
+ *	SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
+ *	SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum.
+ *	SKCS_STATUS_NO_CSUM_POSSIBLE - Checksum could not be built (various reasons).
+ *
+ *	Note: If SKCS_OVERWRITE_STATUS is defined, the SKCS_STATUS_XXX values
+ *	returned here can be defined in some header file by the module using CSUM.
+ *	In this way, the calling module can assign return values for its own needs,
+ *	e.g. by assigning bit flags to the individual protocols.
+ */
+SKCS_STATUS SkCsGetReceiveInfo(
+SK_AC		*pAc,		/* Adapter context struct. */
+void		*pIpHeader,	/* IP header. */
+unsigned	Checksum1,	/* Hardware checksum 1. */
+unsigned	Checksum2,	/* Hardware checksum 2. */
+int			NetNumber,	/* Net number. */
+unsigned	Len)		/* Packet length (without MAC header). */
+{
+	/* Internet Header Version found in IP header. */
+	unsigned InternetHeaderVersion;
+
+	/* Length of the IP header as found in IP header. */
+	unsigned IpHeaderLength;
+
+	/* Length of IP data portion. */
+	unsigned IpDataLength;
+
+	/* IP header checksum. */
+	unsigned IpHeaderChecksum;
+
+	/* IP header options checksum, if any. */
+	unsigned IpOptionsChecksum;
+
+	/* IP data checksum, i.e. TCP/UDP checksum. */
+	unsigned IpDataChecksum;
+
+	/* Next level protocol identifier found in IP header. */
+	unsigned NextLevelProtocol;
+
+	/* The checksum of the "next level protocol", i.e. TCP or UDP. */
+	unsigned long NextLevelProtocolChecksum;
+
+	/* Pointer to next level protocol statistics structure. */
+	SKCS_PROTO_STATS *NextLevelProtoStats;
+
+	/* Temporary variable. */
+	unsigned Tmp;
+
+#ifdef SK_IPV6_SUPPORT
+	/* For parsing IPv6 packets */
+	SK_U8	*pDst;
+	SK_U32	ProtCsum;
+	SK_U32	Pseudo;
+	SK_U32	Pseudo2;
+	SK_U16	Offset;
+	SK_U16	NextHeaderOffset;
+	SK_U16	OptSize;
+	SK_U8	NextHeader;
+#endif
+
+	if (SKCS_IDX_CHECK(Len, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH)) {
+		pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+		return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+	}
+
+	Tmp = *(SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH);
+
+	/* Get the Internet Header Version (IHV). */
+	/* Note: The IHV is stored in the upper four bits. */
+
+	InternetHeaderVersion = Tmp >> 4;
+
+	/* Check the Internet Header Version. */
+
+#ifdef SK_IPV6_SUPPORT
+	if (InternetHeaderVersion == 6) {	/* IPv6? */
+
+		if ((pAc->Csum.ReceiveFlags[NetNumber] &
+			(SKCS_PROTO_TCPV6 | SKCS_PROTO_UDPV6)) == 0) {
+
+			/* The OS/stack told us not to verify IPv6 checksum. */
+			return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+		}
+
+		/* Get the payload length. the payload starts immediately after the
+		 * IPv6 header. This value includes all additional headers!
+		 */
+		 /* first test if the frame has at least the length of the IPv6 header */
+		if (Len < SKCS_IP6_HEADER_SIZE) {
+			pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+			return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+		}
+		IpDataLength = *(SK_U16 *)
+			SKCS_IDX(pIpHeader, SKCS_OFS_IP6_PAYLOAD_LENGTH);
+		IpDataLength = SKCS_NTOH16(IpDataLength);
+
+		/* Before we can proceed we need to find the protocol frame that
+		 * contains the checksum. We support TCP and UDP.
+		 */
+
+		Offset = SKCS_IP6_HEADER_SIZE;
+		NextHeaderOffset = SKCS_OFS_IP6_NEXT_HEADER;
+		/* this access has been secured by checking frame len against SKCS_IP6_HEADER_SIZE */
+		NextHeader = *(SK_U8 *) SKCS_IDX(pIpHeader, NextHeaderOffset);
+
+		pDst = (SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP6_DESTINATION_ADDRESS);
+
+		do {
+			if ((NextHeader == SKCS_PROTO_ID_TCP) ||
+				(NextHeader == SKCS_PROTO_ID_UDP)) {
+
+				/* We found the TCP/UDP header */
+				break;
+			}
+
+			/* Check type of next header to find "Next Header" field */
+			switch (NextHeader) {
+
+			case 0:		/* hop-by-hop options header	*/
+			case 60:	/* Destination options header	*/
+				NextHeaderOffset = Offset;
+
+				/*
+				 * Calculate the size of the option header. The size is in
+				 * units of 8-octets and does not contain the first 8 octets.
+				 */
+				if (SKCS_IDX_CHECK(Len, (unsigned) (NextHeaderOffset + 1))) {
+					pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+					return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+				}
+				OptSize = *(SK_U8 *) SKCS_IDX(pIpHeader, NextHeaderOffset + 1);
+				OptSize *= 8;
+				Offset += OptSize + 8;
+				break;
+
+			case 43:	/* routing header				*/
+				NextHeaderOffset = Offset;
+
+				/*
+				 * Calculate the size of the option header. The size is in
+				 * units of 8-octets and does not contain the first 8 octets.
+				 */
+				if (SKCS_IDX_CHECK(Len, (unsigned) (NextHeaderOffset + 1))) {
+					pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+					return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+				}
+				OptSize = *(SK_U8 *) SKCS_IDX(pIpHeader, NextHeaderOffset + 1);
+				OptSize *= 8;
+				Offset += OptSize + 8;
+
+				/*
+				 * If SegLeft != 0, use the last address in the routing header
+				 * as IP dst in the pseudo header (for both, type 0 and type 2).
+				 */
+				if (*(SK_U8 *) SKCS_IDX(pIpHeader, NextHeaderOffset + 3) != 0) {
+					SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
+						("Rx: IPv6 Routing Header with SegLeft != 0.\n"));
+					pDst = (SK_U8 *) SKCS_IDX(pIpHeader, Offset - 16);
+				}
+				break;
+
+			case 44:	/* fragment header */
+				pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+				return (SKCS_STATUS_IP_FRAGMENT);
+
+			case 46:	/* resource ReSerVation protocol */
+			case 41:	/* encapsulated IPv6 header */
+			case 59:	/* No next header */
+				SK_DBG_MSG(
+					pAc,
+					SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
+					("Rx: Header in IPv6 packet can not be processed: %u.\n",
+						NextHeader));
+				pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+				return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+
+			case 51:	/* authentication header, would have to use OptSize *= 4! */
+			case 50:	/* encapsulating security payload */
+			case 58:	/* ICMP v6 */
+			default:
+				pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+				return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+			}
+
+			/* Continue with the next header */
+			if (SKCS_IDX_CHECK(Len, NextHeaderOffset)) {
+				pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+				return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+			}
+			NextHeader = *(SK_U8 *) SKCS_IDX(pIpHeader, NextHeaderOffset);
+		} while (Offset < (IpDataLength + SKCS_IP6_HEADER_SIZE));
+
+		if (Offset >= (IpDataLength + SKCS_IP6_HEADER_SIZE)) {
+			/* We passed the end of the packet without finding the payload. */
+			SK_DBG_MSG(
+				pAc,
+				SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
+				("Rx: malformed IPv6 packet.\n"));
+				pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+				return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+		}
+
+		/* Before starting checksum calculating, check if we really need to. */
+		if ((NextHeader == SKCS_PROTO_ID_TCP) &&
+			(((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_TCPV6) == 0))) {
+
+			/* Header is TCP but we shall not verify TCP checksum. */
+			return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+		}
+		if ((NextHeader == SKCS_PROTO_ID_UDP) &&
+			(((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_UDPV6) == 0))) {
+
+			/* Header is UDP but we shall not verify UDP checksum. */
+			return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+		}
+
+		if (IpDataLength + SKCS_IP6_HEADER_SIZE > Len) {
+			pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+			return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+		}
+		ProtCsum = SkCsCalculateChecksum(
+			SKCS_IDX(pIpHeader, Offset),
+			IpDataLength + SKCS_IP6_HEADER_SIZE -Offset);
+
+		/*
+		 * Calculate the pseudo header checksum.
+		 */
+
+		/* Start with src and dest address */
+		/* this access has been secured by checking frame len against SKCS_IP6_HEADER_SIZE */
+		Pseudo = SkCsCalculateChecksum(
+					SKCS_IDX(pIpHeader, SKCS_OFS_IP6_SOURCE_ADDRESS), 16);
+
+		Pseudo2 = SkCsCalculateChecksum(pDst, 16);
+		SKCS_OC_ADD(Pseudo, Pseudo, Pseudo2);
+		SKCS_OC_ADD(Pseudo, Pseudo, 0);		/* Add-in any carries. */
+
+		SKCS_OC_ADD(Pseudo, Pseudo,
+			SKCS_HTON16(IpDataLength + SKCS_IP6_HEADER_SIZE -Offset));
+		SKCS_OC_ADD(Pseudo, Pseudo, SKCS_HTON16(NextHeader));
+		SKCS_OC_ADD(Pseudo, Pseudo, 0);		/* Add-in any carries. */
+
+		/* Add to protocol part's checksum */
+		SKCS_OC_ADD(ProtCsum, ProtCsum, Pseudo);
+		SKCS_OC_ADD(ProtCsum, ProtCsum, 0);	/* Add-in any carries. */
+
+		/*
+		 * Check result. We can only process TCP or UDP.
+		 */
+		switch (NextHeader) {
+		case SKCS_PROTO_ID_TCP:
+			if (ProtCsum != 0xFFFF) {
+				pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP].RxErrCts++;
+				return (SKCS_STATUS_TCP_CSUM_ERROR);
+			}
+			pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP].RxOkCts++;
+			return (SKCS_STATUS_TCP_CSUM_OK);
+
+		case SKCS_PROTO_ID_UDP:
+
+			if (ProtCsum != 0xFFFF) {
+				pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP].RxErrCts++;
+				return (SKCS_STATUS_UDP_CSUM_ERROR);
+			}
+			pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP].RxOkCts++;
+			return (SKCS_STATUS_UDP_CSUM_OK);
+
+		default:
+			/* This case should already be eliminated because we only compute
+			 * the checksum for TCP, UDP or ICMPv6
+			 */
+			return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+		}
+	}
+#endif	/* SK_IPV6_SUPPORT */
+
+	if (InternetHeaderVersion != 4) {	/* IPv4? */
+		SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
+			("Rx: Unknown Internet Header Version %u.\n",
+			InternetHeaderVersion));
+		pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+		return (SKCS_STATUS_UNKNOWN_IP_VERSION);
+	}
+
+	/* Get the IP header length (IHL). */
+	/*
+	 * Note: The IHL is stored in the lower four bits as the number of
+	 * 4-byte words.
+	 */
+
+	IpHeaderLength = (Tmp & 0xf) * 4;
+
+	/* Check the IP header length. */
+
+	/* 04-Aug-1998 sw - Really check the IHL? Necessary? */
+
+	if (IpHeaderLength < 5*4) {
+		SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
+			("Rx: Invalid IP Header Length %u.\n", IpHeaderLength));
+		pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++;
+		return (SKCS_STATUS_IP_CSUM_ERROR);
+	}
+
+	/* This is an IPv4 frame with a header of valid length. */
+
+	/* First test if the frame has at least the length of the IP header. */
+	if (Len < IpHeaderLength) {
+		pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+		return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+	}
+
+	/* Get the IP header and data checksum. */
+	IpDataChecksum = Checksum2;
+
+	/* Get the next level protocol identifier. */
+	/* this access has been secured by checking frame len against IpHeaderLength */
+	NextLevelProtocol = *(SK_U8 *)
+		SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL);
+
+	if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_IP) != 0) {
+
+		/* IPv4 checksum verification is specified */
+
+		/*
+		 * The IP header checksum is calculated as follows:
+		 *
+		 *	IpHeaderChecksum = Checksum1 - Checksum2
+		 */
+
+		SKCS_OC_SUB(IpHeaderChecksum, Checksum1, Checksum2);
+
+		/* Check if any IP header options. */
+
+		if (IpHeaderLength > SKCS_IP_HEADER_SIZE) {
+
+			/*
+			 * Get the IP options checksum.
+			 *
+			 * This access has been secured by checking the frame length
+			 * against IpHeaderLength.
+			 */
+			IpOptionsChecksum = SkCsCalculateChecksum(
+				SKCS_IDX(pIpHeader, SKCS_IP_HEADER_SIZE),
+				IpHeaderLength - SKCS_IP_HEADER_SIZE);
+
+			/* Adjust the IP header and IP data checksums. */
+
+			SKCS_OC_ADD(IpHeaderChecksum, IpHeaderChecksum, IpOptionsChecksum);
+
+			SKCS_OC_SUB(IpDataChecksum, IpDataChecksum, IpOptionsChecksum);
+		}
+
+		/*
+		 * Check if the IP header checksum is ok.
+		 *
+		 * NOTE: We must check the IP header checksum even if the caller
+		 * just wants us to check upper-layer checksums, because we cannot do
+		 * any further processing of the packet without a valid IP checksum.
+		 */
+
+		if (IpHeaderChecksum != 0xffff) {
+			pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++;
+			/* The NDIS tester wants to know the upper level protocol, too. */
+			if (NextLevelProtocol == SKCS_PROTO_ID_TCP) {
+				return(SKCS_STATUS_IP_CSUM_ERROR_TCP);
+			}
+			else if (NextLevelProtocol == SKCS_PROTO_ID_UDP) {
+				return(SKCS_STATUS_IP_CSUM_ERROR_UDP);
+			}
+			return (SKCS_STATUS_IP_CSUM_ERROR);
+		}
+	}
+
+	/*
+	 * Check if this is a TCP or UDP frame and if we should calculate the
+	 * TCP/UDP pseudo header checksum.
+	 *
+	 * Also clear all protocol bit flags of protocols not present in the
+	 * frame.
+	 */
+
+	if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_TCP) != 0 &&
+		NextLevelProtocol == SKCS_PROTO_ID_TCP) {
+		/* TCP/IP frame. */
+		NextLevelProtoStats =
+			&pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP];
+	}
+	else if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_UDP) != 0 &&
+		NextLevelProtocol == SKCS_PROTO_ID_UDP) {
+		/* UDP/IP frame. */
+		NextLevelProtoStats =
+			&pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP];
+	}
+	else {
+		/*
+		 * Either not a TCP or UDP frame and/or TCP/UDP processing not
+		 * specified.
+		 */
+		return (SKCS_STATUS_IP_CSUM_OK);
+	}
+
+	/* Check if this is an IP fragment. */
+
+	/*
+	 * Note: An IP fragment has a non-zero "Fragment Offset" field and/or
+	 * the "More Fragments" bit set. Thus, if both the "Fragment Offset"
+	 * and the "More Fragments" are zero, it is *not* a fragment. We can
+	 * easily check both at the same time since they are in the same 16-bit
+	 * word.
+	 *
+	 * This access has been secured by checking the frame length
+	 * against IpHeaderLength.
+	 */
+
+	if ((*(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) &
+		~SKCS_IP_DONT_FRAGMENT) != 0) {
+		/* IP fragment; ignore all other protocols. */
+		NextLevelProtoStats->RxUnableCts++;
+		return (SKCS_STATUS_IP_FRAGMENT);
+	}
+
+	if (SKCS_IDX_CHECK(Len, (IpHeaderLength + 6 + 1))) {
+		pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
+		return (SKCS_STATUS_NO_CSUM_POSSIBLE);
+	}
+
+	/*
+	 * A checksum value of 0 in UDP over IPv4 frames means that no checksum
+	 * was inserted by the sender (RFC 768).
+	 */
+
+	if (NextLevelProtocol == SKCS_PROTO_ID_UDP &&
+		*(SK_U16 *) SKCS_IDX(pIpHeader, IpHeaderLength + 6) == 0x0000) {
+
+		NextLevelProtoStats->RxOkCts++;
+		
+		return (SKCS_STATUS_IP_CSUM_OK_NO_UDP);
+	}
+
+	/*
+	 * Calculate the TCP/UDP checksum.
+	 */
+
+	/*
+	 * Get total length of IP header and data.
+	 *
+	 * This access has been secured by checking the frame length
+	 * against IpHeaderLength.
+	 */
+
+	IpDataLength =
+		*(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH);
+
+	/* Get length of IP data portion. */
+
+	IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength;
+
+	/*
+	 * This access has been secured by checking the frame length
+	 * against IpHeaderLength.
+	 */
+
+	NextLevelProtocolChecksum =
+
+		/* Calculate the pseudo header checksum. */
+
+		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
+			SKCS_OFS_IP_SOURCE_ADDRESS + 0) +
+		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
+			SKCS_OFS_IP_SOURCE_ADDRESS + 2) +
+		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
+			SKCS_OFS_IP_DESTINATION_ADDRESS + 0) +
+		(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
+			SKCS_OFS_IP_DESTINATION_ADDRESS + 2) +
+		(unsigned long) SKCS_HTON16(NextLevelProtocol) +
+		(unsigned long) SKCS_HTON16(IpDataLength) +
+
+		/* Add the TCP/UDP header checksum. */
+
+		(unsigned long) IpDataChecksum;
+
+	/* Add-in any carries. */
+
+	SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0);
+
+	/* Add-in any new carry. */
+
+	SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0);
+
+	/* Check if the TCP/UDP checksum is ok. */
+
+	if ((unsigned) NextLevelProtocolChecksum == 0xffff) {
+
+		/* TCP/UDP checksum ok. */
+
+		NextLevelProtoStats->RxOkCts++;
+
+		return (NextLevelProtocol == SKCS_PROTO_ID_TCP ?
+			SKCS_STATUS_TCP_CSUM_OK : SKCS_STATUS_UDP_CSUM_OK);
+	}
+	
+	/* TCP/UDP checksum error. */
+
+	NextLevelProtoStats->RxErrCts++;
+
+	return (NextLevelProtocol == SKCS_PROTO_ID_TCP ?
+		SKCS_STATUS_TCP_CSUM_ERROR : SKCS_STATUS_UDP_CSUM_ERROR);
+}	/* SkCsGetReceiveInfo */
+
+
+/******************************************************************************
+ *
+ *	SkCsSetReceiveFlags - set checksum receive flags
+ *
+ * Description:
+ *	Use this function to set the various receive flags. According to the
+ *	protocol flags set by the caller, the start offsets within received
+ *	packets of the two hardware checksums are returned. These offsets must
+ *	be stored in all receive descriptors.
+ *
+ * Arguments:
+ *	pAc - Pointer to adapter context struct.
+ *
+ *	ReceiveFlags - Any combination of SK_PROTO_XXX flags of the protocols
+ *	for which the caller wants checksum information on received frames.
+ *
+ *	pChecksum1Offset - The start offset of the first receive descriptor
+ *	hardware checksum to be calculated for received frames is returned
+ *	here.
+ *
+ *	pChecksum2Offset - The start offset of the second receive descriptor
+ *	hardware checksum to be calculated for received frames is returned
+ *	here.
+ *
+ * Returns: N/A
+ *	Returns the two hardware checksum start offsets.
+ */
+void SkCsSetReceiveFlags(
+SK_AC		*pAc,				/* Adapter context struct. */
+unsigned	ReceiveFlags,		/* New receive flags. */
+unsigned	*pChecksum1Offset,	/* Offset for hardware checksum 1. */
+unsigned	*pChecksum2Offset,	/* Offset for hardware checksum 2. */
+int			NetNumber)
+{
+	/* Save the receive flags. */
+
+	pAc->Csum.ReceiveFlags[NetNumber] = ReceiveFlags;
+
+	/* First checksum start offset is the IP header. */
+	*pChecksum1Offset = SKCS_MAC_HEADER_SIZE;
+
+	/*
+	 * Second checksum start offset is the IP data. Note that this may vary
+	 * if there are any IP header options in the actual packet.
+	 */
+	*pChecksum2Offset = SKCS_MAC_HEADER_SIZE + SKCS_IP_HEADER_SIZE;
+}	/* SkCsSetReceiveFlags */
+
+#ifndef SK_CS_CALCULATE_CHECKSUM
+
+/******************************************************************************
+ *
+ *	SkCsCalculateChecksum - calculate checksum for specified data
+ *
+ * Description:
+ *	Calculate and return the 16-bit Internet Checksum for the specified
+ *	data.
+ *
+ * Arguments:
+ *	pData - Pointer to data for which the checksum shall be calculated.
+ *	Note: The pointer should be aligned on a 16-bit boundary.
+ *
+ *	Length - Length in bytes of data to checksum.
+ *
+ * Returns:
+ *	The 16-bit Internet Checksum for the specified data.
+ *
+ *	Note: The checksum is calculated in the machine's natural byte order,
+ *	i.e. little vs. big endian. Thus, the resulting checksum is different
+ *	for the same input data on little and big endian machines.
+ *
+ *	However, when written back to the network packet, the byte order is
+ *	always in correct network order.
+ */
+unsigned SkCsCalculateChecksum(
+void		*pData,		/* Data to checksum. */
+unsigned	Length)		/* Length of data. */
+{
+	SK_U16 *pU16;		/* Pointer to the data as 16-bit words. */
+	unsigned long Checksum;	/* Checksum; must be at least 32 bits. */
+
+	/* Sum up all 16-bit words. */
+
+	pU16 = (SK_U16 *) pData;
+	for (Checksum = 0; Length > 1; Length -= 2) {
+		Checksum += *pU16++;
+	}
+
+	/* If this is an odd number of bytes, add-in the last byte. */
+
+	if (Length > 0) {
+#ifdef SK_BIG_ENDIAN
+		/* Add the last byte as the high byte. */
+		Checksum += ((unsigned) *(SK_U8 *) pU16) << 8;
+#else	/* !SK_BIG_ENDIAN */
+		/* Add the last byte as the low byte. */
+		Checksum += *(SK_U8 *) pU16;
+#endif	/* !SK_BIG_ENDIAN */
+	}
+
+	/* Add-in any carries. */
+
+	SKCS_OC_ADD(Checksum, Checksum, 0);
+
+	/* Add-in any new carry. */
+
+	SKCS_OC_ADD(Checksum, Checksum, 0);
+
+	/* Note: All bits beyond the 16-bit limit are now zero. */
+
+	return ((unsigned) Checksum);
+}	/* SkCsCalculateChecksum */
+
+#endif /* SK_CS_CALCULATE_CHECKSUM */
+
+/******************************************************************************
+ *
+ *	SkCsEvent - the CSUM event dispatcher
+ *
+ * Description:
+ *	This is the event handler for the CSUM module.
+ *
+ * Arguments:
+ *	pAc - Pointer to adapter context.
+ *
+ *	Ioc - I/O context.
+ *
+ *	Event -	 Event id.
+ *
+ *	Param - Event dependent parameter.
+ *
+ * Returns:
+ *	0 (Success)
+ */
+int SkCsEvent(
+SK_AC		*pAc,	/* Pointer to adapter context. */
+SK_IOC		Ioc,	/* I/O context. */
+SK_U32		Event,	/* Event id. */
+SK_EVPARA	Param)	/* Event dependent parameter. */
+{
+	int ProtoIndex;
+	int	NetNumber;
+
+	switch (Event) {
+	/*
+	 * Clear protocol statistics.
+	 *
+	 * Param - Protocol index, or -1 for all protocols.
+	 *		 - Net number.
+	 */
+	case SK_CSUM_EVENT_CLEAR_PROTO_STATS:
+		ProtoIndex = (int)Param.Para32[1];
+		NetNumber = (int)Param.Para32[0];
+		if (ProtoIndex < 0) {	/* Clear for all protocols. */
+			if (NetNumber >= 0) {
+				SK_MEMSET(&pAc->Csum.ProtoStats[NetNumber][0], 0,
+					sizeof(pAc->Csum.ProtoStats[NetNumber]));
+			}
+		}
+		else {					/* Clear for individual protocol. */
+			SK_MEMSET(&pAc->Csum.ProtoStats[NetNumber][ProtoIndex], 0,
+				sizeof(pAc->Csum.ProtoStats[NetNumber][ProtoIndex]));
+		}
+		break;
+
+	default:
+		break;
+	}
+	return (0);	/* Success. */
+}	/* SkCsEvent */
+
+#endif	/* SK_USE_CSUM */
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
new file mode 100755
index 0000000..b4dd0c2
--- /dev/null
+++ b/drivers/net/sk98lin/skdim.c
@@ -0,0 +1,387 @@
+/******************************************************************************
+ *
+ * Name:        skdim.c
+ * Project:     GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:     $Revision: 1.6.4.1 $
+ * Date:        $Date: 2006/11/29 14:10:32 $
+ * Purpose:     All functions regardig interrupt moderation
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet 
+ *      Server Adapters.
+ *
+ *	Author: Ralph Roesler (rroesler@syskonnect.de)
+ *	        Mirko Lindner (mlindner@syskonnect.de)
+ *
+ *	Address all question to: linux@syskonnect.de
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ *****************************************************************************/
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+
+/******************************************************************************
+ *
+ * Local Function Prototypes
+ *
+ *****************************************************************************/
+
+static SK_U64 getIsrCalls(SK_AC *pAC);
+static SK_BOOL isIntModEnabled(SK_AC *pAC);
+static void setCurrIntCtr(SK_AC *pAC);
+static void enableIntMod(SK_AC *pAC); 
+static void disableIntMod(SK_AC *pAC);
+
+#define M_DIMINFO pAC->DynIrqModInfo
+
+/******************************************************************************
+ *
+ * Global Functions
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * 	SkDimModerate - Moderates the IRQs depending on the current needs
+ *
+ * Description:
+ *	Moderation of IRQs depends on the number of occurred IRQs with 
+ *	respect to the previous moderation cycle.
+ *
+ * Returns:	N/A
+ *
+ */
+void SkDimModerate(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+	SK_U64  IsrCalls = getIsrCalls(pAC);
+
+	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> SkDimModerate\n"));
+
+	if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+		if (isIntModEnabled(pAC)) {
+			if (IsrCalls < M_DIMINFO.MaxModIntsPerSecLowerLimit) {
+				disableIntMod(pAC);
+			}
+		} else {
+			if (IsrCalls > M_DIMINFO.MaxModIntsPerSecUpperLimit) {
+				enableIntMod(pAC);
+			}
+		}
+	}
+	setCurrIntCtr(pAC);
+
+	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== SkDimModerate\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	SkDimStartModerationTimer - Starts the moderation timer
+ *
+ * Description:
+ *	Dynamic interrupt moderation is regularly checked using the
+ *	so-called moderation timer. This timer is started with this function.
+ *
+ * Returns:	N/A
+ */
+void SkDimStartModerationTimer(
+SK_AC *pAC) /* pointer to adapter control context */
+{
+	SK_EVPARA   EventParam;   /* Event struct for timer event */
+ 
+	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("==> SkDimStartModerationTimer\n"));
+
+	if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+		SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+		EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
+		SkTimerStart(pAC, pAC->IoBase,
+			&pAC->DynIrqModInfo.ModTimer,
+			pAC->DynIrqModInfo.DynIrqModSampleInterval * 1000000,
+			SKGE_DRV, SK_DRV_TIMER, EventParam);
+	}
+
+	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("<== SkDimStartModerationTimer\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	SkDimEnableModerationIfNeeded - Enables or disables any moderationtype
+ *
+ * Description:
+ *	This function effectively initializes the IRQ moderation of a network
+ *	adapter. Depending on the configuration, this might be either static
+ *	or dynamic. If no moderation is configured, this function will do
+ *	nothing.
+ *
+ * Returns:	N/A
+ */
+void SkDimEnableModerationIfNeeded(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("==> SkDimEnableModerationIfNeeded\n"));
+
+	if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_NONE) {
+		if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
+			enableIntMod(pAC);   
+		} else { /* must be C_INT_MOD_DYNAMIC */
+			SkDimStartModerationTimer(pAC);
+		}
+	}
+
+	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("<== SkDimEnableModerationIfNeeded\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	SkDimDisableModeration - disables moderation if it is enabled
+ *
+ * Description:
+ *	Disabling of the moderation requires that is enabled already.
+ *
+ * Returns:	N/A
+ */
+void SkDimDisableModeration(
+SK_AC  *pAC,                /* pointer to adapter control context */
+int     CurrentModeration)  /* type of current moderation         */
+{
+	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("==> SkDimDisableModeration\n"));
+
+	if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_NONE) {
+		if (CurrentModeration == C_INT_MOD_STATIC) {
+			disableIntMod(pAC);
+		} else { /* must be C_INT_MOD_DYNAMIC */
+			SkTimerStop(pAC, pAC->IoBase, &M_DIMINFO.ModTimer);
+			disableIntMod(pAC);
+		}
+	}
+
+	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("<== SkDimDisableModeration\n"));
+}
+
+/******************************************************************************
+ *
+ * Local Functions
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * 	getIsrCalls - evaluate the number of IRQs handled in mod interval
+ *
+ * Description:
+ *	Depending on the selected moderation mask, this function will return
+ *	the number of interrupts handled in the previous moderation interval.
+ *	This evaluated number is based on the current number of interrupts
+ *	stored in PNMI-context and the previous stored interrupts.
+ *
+ * Returns:
+ *	the number of IRQs handled
+ */
+static SK_U64 getIsrCalls(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+	SK_U64   RxPort0IntDiff = 0, RxPort1IntDiff = 0;
+	SK_U64   TxPort0IntDiff = 0, TxPort1IntDiff = 0;
+	SK_U64   StatusPort0IntDiff = 0, StatusPort1IntDiff = 0;
+
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>getIsrCalls\n"));
+
+	if (!CHIP_ID_YUKON_2(pAC)) {
+		if ((M_DIMINFO.MaskIrqModeration == IRQ_MASK_TX_ONLY) ||
+		    (M_DIMINFO.MaskIrqModeration == IRQ_MASK_SP_TX)) {
+			if (pAC->GIni.GIMacsFound == 2) {
+				TxPort1IntDiff = 
+					pAC->Pnmi.Port[1].TxIntrCts - 
+					M_DIMINFO.PrevPort1TxIntrCts;
+			}
+			TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
+					M_DIMINFO.PrevPort0TxIntrCts;
+		} else if ((M_DIMINFO.MaskIrqModeration == IRQ_MASK_RX_ONLY) ||
+		           (M_DIMINFO.MaskIrqModeration == IRQ_MASK_SP_RX)) {
+			if (pAC->GIni.GIMacsFound == 2) {
+				RxPort1IntDiff =
+					pAC->Pnmi.Port[1].RxIntrCts - 
+					M_DIMINFO.PrevPort1RxIntrCts;
+			}
+			RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
+					M_DIMINFO.PrevPort0RxIntrCts;
+		} else {
+			if (pAC->GIni.GIMacsFound == 2) {
+				RxPort1IntDiff = 
+					pAC->Pnmi.Port[1].RxIntrCts - 
+					M_DIMINFO.PrevPort1RxIntrCts;
+				TxPort1IntDiff =
+					pAC->Pnmi.Port[1].TxIntrCts - 
+					M_DIMINFO.PrevPort1TxIntrCts;
+			} 
+			RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
+					M_DIMINFO.PrevPort0RxIntrCts;
+			TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
+					M_DIMINFO.PrevPort0TxIntrCts;
+		}
+        	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+				("==>getIsrCalls (!CHIP_ID_YUKON_2)\n"));
+		return (RxPort0IntDiff + RxPort1IntDiff + 
+		        TxPort0IntDiff + TxPort1IntDiff);
+	}
+
+	/*
+	** We have a Yukon2 compliant chipset if we come up to here
+	**
+	if (pAC->GIni.GIMacsFound == 2) {
+		StatusPort1IntDiff = pAC->Pnmi.Port[1].StatusLeIntrCts - 
+					M_DIMINFO.PrevPort1StatusIntrCts;
+	}
+	StatusPort0IntDiff = pAC->Pnmi.Port[0].StatusLeIntrCts - 
+				M_DIMINFO.PrevPort0StatusIntrCts;
+	*/
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("==>getIsrCalls (CHIP_ID_YUKON_2)\n"));
+	return (StatusPort0IntDiff + StatusPort1IntDiff);
+}
+
+/*****************************************************************************
+ *
+ * 	setCurrIntCtr - stores the current number of interrupts
+ *
+ * Description:
+ *	Stores the current number of occurred interrupts in the adapter
+ *	context. This is needed to evaluate the  umber of interrupts within
+ *	the moderation interval.
+ *
+ * Returns:	N/A
+ *
+ */
+static void setCurrIntCtr(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>setCurrIntCtr\n"));
+
+	if (!CHIP_ID_YUKON_2(pAC)) {
+		if (pAC->GIni.GIMacsFound == 2) {
+			M_DIMINFO.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
+			M_DIMINFO.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
+		} 
+		M_DIMINFO.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
+		M_DIMINFO.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
+        	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+				("<== setCurrIntCtr (!CHIP_ID_YUKON_2)\n"));
+		return;
+	}
+
+	/*
+	** We have a Yukon2 compliant chipset if we come up to here
+	**
+	if (pAC->GIni.GIMacsFound == 2) {
+		M_DIMINFO.PrevPort1StatusIntrCts = pAC->Pnmi.Port[1].StatusLeIntrCts;
+	} 
+	M_DIMINFO.PrevPort0StatusIntrCts = pAC->Pnmi.Port[0].StatusLeIntrCts;
+	*/
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("<== setCurrIntCtr (CHIP_ID_YUKON_2)\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	isIntModEnabled - returns the current state of interrupt moderation
+ *
+ * Description:
+ *	This function retrieves the current value of the interrupt moderation
+ *	command register. Its content determines whether any moderation is 
+ *	running or not.
+ *
+ * Returns:
+ *	SK_TRUE : IRQ moderation is currently active
+ *	SK_FALSE: No IRQ moderation is active
+ */
+static SK_BOOL isIntModEnabled(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+	unsigned long CtrCmd;
+
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>isIntModEnabled\n"));
+
+	SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
+	if ((CtrCmd & TIM_START) == TIM_START) {
+        	SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("<== isIntModEnabled (SK_TRUE)\n"));
+		return SK_TRUE;
+	}
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
+			("<== isIntModEnabled (SK_FALSE)\n"));
+	return SK_FALSE;
+}
+
+/*****************************************************************************
+ *
+ * 	enableIntMod - enables the interrupt moderation
+ *
+ * Description:
+ *	Enabling the interrupt moderation is done by putting the desired
+ *	moderation interval in the B2_IRQM_INI register, specifying the
+ *	desired maks in the B2_IRQM_MSK register and finally starting the
+ *	IRQ moderation timer using the B2_IRQM_CTRL register.
+ *
+ * Returns:	N/A
+ *
+ */
+static void enableIntMod(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+	unsigned long ModBase;
+
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> enableIntMod\n"));
+	ModBase = ((62500L/100) * pAC->GIni.GIHstClkFact * 1000) / M_DIMINFO.MaxModIntsPerSec;
+
+	SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
+	SK_OUT32(pAC->IoBase, B2_IRQM_MSK, M_DIMINFO.MaskIrqModeration);
+	SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
+
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== enableIntMod\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	disableIntMod - disables the interrupt moderation
+ *
+ * Description:
+ *	Disabling the interrupt moderation is done by stopping the
+ *	IRQ moderation timer using the B2_IRQM_CTRL register.
+ *
+ * Returns:	N/A
+ *
+ */
+static void disableIntMod(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> disableIntMod\n"));
+
+	SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
+
+        SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== disableIntMod\n"));
+} 
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
new file mode 100755
index 0000000..1c2ccbf
--- /dev/null
+++ b/drivers/net/sk98lin/skethtool.c
@@ -0,0 +1,1274 @@
+/******************************************************************************
+ *
+ * Name:        skethtool.c
+ * Project:     GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:     $Revision: 1.9.2.8 $
+ * Date:        $Date: 2007/06/25 14:40:17 $
+ * Purpose:     All functions regarding ethtool handling
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet 
+ *      Server Adapters.
+ *
+ *	Author: Ralph Roesler (rroesler@syskonnect.de)
+ *	        Mirko Lindner (mlindner@syskonnect.de)
+ *
+ *	Address all question to: linux@syskonnect.de
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ *****************************************************************************/
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#include "h/skversion.h"
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+
+/******************************************************************************
+ *
+ * Local Functions
+ *
+ *****************************************************************************/
+static void toggleLeds(unsigned long ptr);
+
+/******************************************************************************
+ *
+ * External Functions and Data
+ *
+ *****************************************************************************/
+
+extern void SkDimDisableModeration(SK_AC *pAC, int CurrentModeration);
+extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);
+
+/******************************************************************************
+ *
+ * Defines
+ *
+ *****************************************************************************/
+
+#ifndef ETHT_STATSTRING_LEN
+#define ETHT_STATSTRING_LEN 32
+#endif
+
+#define ENABLE_FUTURE_ETH
+
+#define SK98LIN_STAT(m)	sizeof(((SK_AC *)0)->m),offsetof(SK_AC, m)
+
+#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half  | SUPPORTED_10baseT_Full  | \
+                         SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+                         SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
+                         SUPPORTED_TP)
+
+#define ADV_COPPER_ALL  (ADVERTISED_10baseT_Half  | ADVERTISED_10baseT_Full  | \
+                         ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+                         ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
+                         ADVERTISED_TP)
+
+#define SUPP_FIBRE_ALL  (SUPPORTED_1000baseT_Full | \
+                         SUPPORTED_FIBRE          | \
+                         SUPPORTED_Autoneg)
+
+#define ADV_FIBRE_ALL   (ADVERTISED_1000baseT_Full | \
+                         ADVERTISED_FIBRE          | \
+                         ADVERTISED_Autoneg)
+
+struct sk98lin_stats {
+	char stat_string[ETHT_STATSTRING_LEN];
+	int  sizeof_stat;
+	int  stat_offset;
+};
+
+static struct sk98lin_stats sk98lin_etht_stats_port0[] = {
+	{ "rx_packets" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxOkCts) },
+	{ "tx_packets" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxOkCts) },
+	{ "rx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxOctetsOkCts) },
+	{ "tx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxOctetsOkCts) },
+	{ "rx_errors" , SK98LIN_STAT(PnmiStruct.InErrorsCts) },
+	{ "tx_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxSingleCollisionCts) },
+	{ "rx_dropped" , SK98LIN_STAT(PnmiStruct.RxNoBufCts) },
+	{ "tx_dropped" , SK98LIN_STAT(PnmiStruct.TxNoBufCts) },
+	{ "multicasts" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxMulticastOkCts) },
+	{ "collisions" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxSingleCollisionCts) },
+	{ "rx_length_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxRuntCts) },
+	{ "rx_buffer_overflow_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFifoOverflowCts) },
+	{ "rx_crc_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFcsCts) },
+	{ "rx_frame_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFramingCts) },
+	{ "rx_too_short_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxShortsCts) },
+	{ "rx_too_long_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxTooLongCts) },
+	{ "rx_carrier_extension_errors", SK98LIN_STAT(PnmiStruct.Stat[0].StatRxCextCts) },
+	{ "rx_symbol_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxSymbolCts) },
+	{ "rx_llc_mac_size_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxIRLengthCts) },
+	{ "rx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxCarrierCts) },
+	{ "rx_jabber_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxJabberCts) },
+	{ "rx_missed_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxMissedCts) },
+	{ "tx_abort_collision_errors" , SK98LIN_STAT(stats.tx_aborted_errors) },
+	{ "tx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxCarrierCts) },
+	{ "tx_buffer_underrun_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxFifoUnderrunCts) },
+	{ "tx_heartbeat_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxCarrierCts) } ,
+	{ "tx_window_errors" , SK98LIN_STAT(stats.tx_window_errors) }
+};
+
+static struct sk98lin_stats sk98lin_etht_stats_port1[] = {
+	{ "rx_packets" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxOkCts) },
+	{ "tx_packets" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxOkCts) },
+	{ "rx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxOctetsOkCts) },
+	{ "tx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxOctetsOkCts) },
+	{ "rx_errors" , SK98LIN_STAT(PnmiStruct.InErrorsCts) },
+	{ "tx_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxSingleCollisionCts) },
+	{ "rx_dropped" , SK98LIN_STAT(PnmiStruct.RxNoBufCts) },
+	{ "tx_dropped" , SK98LIN_STAT(PnmiStruct.TxNoBufCts) },
+	{ "multicasts" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxMulticastOkCts) },
+	{ "collisions" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxSingleCollisionCts) },
+	{ "rx_length_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxRuntCts) },
+	{ "rx_buffer_overflow_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFifoOverflowCts) },
+	{ "rx_crc_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFcsCts) },
+	{ "rx_frame_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFramingCts) },
+	{ "rx_too_short_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxShortsCts) },
+	{ "rx_too_long_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxTooLongCts) },
+	{ "rx_carrier_extension_errors", SK98LIN_STAT(PnmiStruct.Stat[1].StatRxCextCts) },
+	{ "rx_symbol_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxSymbolCts) },
+	{ "rx_llc_mac_size_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxIRLengthCts) },
+	{ "rx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxCarrierCts) },
+	{ "rx_jabber_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxJabberCts) },
+	{ "rx_missed_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxMissedCts) },
+	{ "tx_abort_collision_errors" , SK98LIN_STAT(stats.tx_aborted_errors) },
+	{ "tx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxCarrierCts) },
+	{ "tx_buffer_underrun_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxFifoUnderrunCts) },
+	{ "tx_heartbeat_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxCarrierCts) } ,
+	{ "tx_window_errors" , SK98LIN_STAT(stats.tx_window_errors) }
+};
+
+static int DuplexAutoNegConfMap[9][3]= {
+	{ -1                     , -1         , -1              },
+	{ 0                      , -1         , -1              },
+	{ SK_LMODE_HALF          , DUPLEX_HALF, AUTONEG_DISABLE },
+	{ SK_LMODE_FULL          , DUPLEX_FULL, AUTONEG_DISABLE },
+	{ SK_LMODE_AUTOHALF      , DUPLEX_HALF, AUTONEG_ENABLE  },
+	{ SK_LMODE_AUTOFULL      , DUPLEX_FULL, AUTONEG_ENABLE  },
+	{ SK_LMODE_AUTOBOTH      , DUPLEX_FULL, AUTONEG_ENABLE  },
+	{ SK_LMODE_AUTOSENSE     , -1         , -1              },
+	{ SK_LMODE_INDETERMINATED, -1         , -1              }
+};
+
+static int SpeedConfMap[6][2] = {
+	{ 0                       , -1         },
+	{ SK_LSPEED_AUTO          , -1         },
+	{ SK_LSPEED_10MBPS        , SPEED_10   },
+	{ SK_LSPEED_100MBPS       , SPEED_100  },
+	{ SK_LSPEED_1000MBPS      , SPEED_1000 },
+	{ SK_LSPEED_INDETERMINATED, -1         }
+};
+
+static int AdvSpeedMap[6][2] = {
+	{ 0                       , -1         },
+	{ SK_LSPEED_AUTO          , -1         },
+	{ SK_LSPEED_10MBPS        , ADVERTISED_10baseT_Half   | ADVERTISED_10baseT_Full },
+	{ SK_LSPEED_100MBPS       , ADVERTISED_100baseT_Half  | ADVERTISED_100baseT_Full },
+	{ SK_LSPEED_1000MBPS      , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
+	{ SK_LSPEED_INDETERMINATED, -1         }
+};
+
+#define SK98LIN_STATS_LEN sizeof(sk98lin_etht_stats_port0) / sizeof(struct sk98lin_stats)
+
+static int nbrBlinkQuarterSeconds;
+static int currentPortIndex;
+static SK_BOOL isLocateNICrunning   = SK_FALSE;
+static SK_BOOL isDualNetCard        = SK_FALSE;
+static SK_BOOL doSwitchLEDsOn       = SK_FALSE;
+static SK_BOOL boardWasDown[2]      = { SK_FALSE, SK_FALSE };
+static struct timer_list locateNICtimer;
+
+/******************************************************************************
+ *
+ * Ethtool Functions
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * 	SkGeGetSettings - retrieves the current settings of the selected adapter
+ *
+ * Description:
+ *	The current configuration of the selected adapter is returned.
+ *	This configuration involves a)speed, b)duplex and c)autoneg plus
+ *	a number of other variables.
+ *
+ * Returns:	N/A
+ *
+ */
+int SkGeGetSettings(struct net_device *dev,
+			struct ethtool_cmd *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	int			port         = pNet->PortNr;
+	SK_GEPORT		*pPort       = &pAC->GIni.GP[port];
+
+	ecmd->phy_address = port;
+	ecmd->speed       = SpeedConfMap[pPort->PLinkSpeedUsed][1];
+	ecmd->duplex      = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
+	ecmd->autoneg     = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (pAC->GIni.GICopperType) {
+		ecmd->port        = PORT_TP;
+		ecmd->supported   = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
+		if (pAC->GIni.GIGenesis) {
+			ecmd->supported &= ~(SUPPORTED_10baseT_Half);
+			ecmd->supported &= ~(SUPPORTED_10baseT_Full);
+			ecmd->supported &= ~(SUPPORTED_100baseT_Half);
+			ecmd->supported &= ~(SUPPORTED_100baseT_Full);
+		} else {
+			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
+			} 
+			if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) ||
+				(pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P)) {
+				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
+				ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
+			}
+		}
+		if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
+			ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
+			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+				ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
+			} 
+		} else {
+			ecmd->advertising = ecmd->supported;
+		}
+		if (ecmd->autoneg == AUTONEG_ENABLE) {
+			ecmd->advertising |= ADVERTISED_Autoneg;
+		} else {
+			ecmd->advertising = ADVERTISED_TP;
+		}
+	} else {
+		ecmd->port        = PORT_FIBRE;
+		ecmd->supported   = (SUPP_FIBRE_ALL);
+		ecmd->advertising = (ADV_FIBRE_ALL);
+	}
+	return(0);
+}
+
+
+
+/*****************************************************************************
+ *
+ * 	SkGeGetDrvInfo - returns generic driver and adapter information
+ *
+ * Description:
+ *	Generic driver information is returned via this function, such as
+ *	the name of the driver, its version and and firmware version.
+ *	In addition to this, the location of the selected adapter is 
+ *	returned as a bus info string (e.g. '01:05.0').
+ *	
+ * Returns:	N/A
+ *
+ */
+void SkGeGetDrvInfo(struct net_device *dev,
+			struct ethtool_drvinfo *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	char			versionString[32];
+
+	snprintf(versionString, 32, "%s (%s)", VER_STRING, PATCHLEVEL);
+	strncpy(ecmd->driver, DRIVER_FILE_NAME , 32);
+	strncpy(ecmd->version, versionString , 32);
+	strncpy(ecmd->fw_version, "N/A", 32);
+	strncpy(ecmd->bus_info, pci_name(pAC->PciDev), 32);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19)
+	ecmd->n_stats = SK98LIN_STATS_LEN;
+#endif
+}
+
+/*****************************************************************************
+ *
+ * 	SkGeGetWolSettings - retrieves the WOL settings of the 
+ *	selected adapter
+ *
+ * Description:
+ *	All current WOL settings of a selected adapter are placed in the 
+ *	passed ethtool_wolinfo structure and are returned to the caller.
+ *
+ * Returns:	N/A
+ *
+ */
+void SkGeGetWolSettings(struct net_device *dev,
+			struct ethtool_wolinfo *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+
+	ecmd->supported = pAC->WolInfo.SupportedWolOptions;
+	ecmd->wolopts   = pAC->WolInfo.ConfiguredWolOptions;
+}
+
+/*****************************************************************************
+ *
+ * 	SkGeGetPauseParam - retrieves the pause parameters
+ *
+ * Description:
+ *	All current pause parameters of a selected adapter are placed 
+ *	in the passed ethtool_pauseparam structure and are returned.
+ *
+ * Returns:	N/A
+ *
+ */
+void SkGeGetPauseParam(struct net_device *dev,
+			struct ethtool_pauseparam *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	int			port         = pNet->PortNr;
+	SK_GEPORT		*pPort       = &pAC->GIni.GP[port];
+
+	/* Get the pause parameters */
+	ecmd->rx_pause = 0;
+	ecmd->tx_pause = 0;
+
+	if (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND) {
+		ecmd->tx_pause = 1;
+	} 
+	if ((pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
+	    (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM)) {
+		ecmd->tx_pause = 1;
+		ecmd->rx_pause = 1;
+	}
+
+	if ((ecmd->rx_pause == 0) && (ecmd->tx_pause == 0)) {
+		ecmd->autoneg = SK_FALSE;
+	} else {
+		ecmd->autoneg = SK_TRUE;
+	}
+}
+
+
+/*****************************************************************************
+ *
+ * 	SkGeGetCoalesce - retrieves the IRQ moderation settings 
+ *
+ * Description:
+ *	All current IRQ moderation settings of a selected adapter are placed 
+ *	in the passed ethtool_coalesce structure and are returned.
+ *
+ * Returns:	N/A
+ *
+ */
+int SkGeGetCoalesce(struct net_device *dev,
+			struct ethtool_coalesce *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+
+	DIM_INFO *Info = &pAC->DynIrqModInfo;
+	SK_BOOL UseTxIrqModeration = SK_FALSE;
+	SK_BOOL UseRxIrqModeration = SK_FALSE;
+
+	if (Info->IntModTypeSelect != C_INT_MOD_NONE) {
+		if (CHIP_ID_YUKON_2(pAC)) {
+			UseRxIrqModeration = SK_TRUE;
+			UseTxIrqModeration = SK_TRUE;
+		} else {
+			if ((Info->MaskIrqModeration == IRQ_MASK_RX_ONLY) ||
+			    (Info->MaskIrqModeration == IRQ_MASK_SP_RX)   ||
+			    (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) {
+				UseRxIrqModeration = SK_TRUE;
+			}
+			if ((Info->MaskIrqModeration == IRQ_MASK_TX_ONLY) ||
+			    (Info->MaskIrqModeration == IRQ_MASK_SP_TX)   ||
+			    (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) {
+				UseTxIrqModeration = SK_TRUE;
+			}
+		}
+
+		if (UseRxIrqModeration) {
+			ecmd->rx_coalesce_usecs = 1000000 / Info->MaxModIntsPerSec;
+		}
+		if (UseTxIrqModeration) {
+			ecmd->tx_coalesce_usecs = 1000000 / Info->MaxModIntsPerSec;
+		}
+		if (Info->IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+			ecmd->rate_sample_interval = Info->DynIrqModSampleInterval; 
+			if (UseRxIrqModeration) {
+				ecmd->use_adaptive_rx_coalesce = 1;
+				ecmd->rx_coalesce_usecs_low = 
+					1000000 / Info->MaxModIntsPerSecLowerLimit;
+				ecmd->rx_coalesce_usecs_high = 
+					1000000 / Info->MaxModIntsPerSecUpperLimit;
+			}
+			if (UseTxIrqModeration) {
+				ecmd->use_adaptive_tx_coalesce = 1;
+				ecmd->tx_coalesce_usecs_low = 
+					1000000 / Info->MaxModIntsPerSecLowerLimit;
+				ecmd->tx_coalesce_usecs_high = 
+					1000000 / Info->MaxModIntsPerSecUpperLimit;
+			}
+		}
+	}
+	return(0);
+}
+
+/*****************************************************************************
+ *
+ * 	SkGeGetRxCsum - retrieves the RxCsum parameters
+ *
+ * Description:
+ *	All current RxCsum parameters of a selected adapter are placed 
+ *	in the passed net_device structure and are returned.
+ *
+ * Returns:	N/A
+ *
+ */
+SK_U32 SkGeGetRxCsum(struct net_device *dev)
+{
+
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	int			port         = pNet->PortNr;
+
+	return pAC->RxPort[port].UseRxCsum;
+}
+
+
+/*****************************************************************************
+ *
+ * 	SkGeGetStrings - retrieves the statistic strings
+ *
+ * Description:
+ *	N/A
+ *
+ * Returns:	N/A
+ *
+ */
+void SkGeGetStrings(struct net_device *dev, 
+			u32 stringset,
+			u8 *strings)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	int			port         = pNet->PortNr;
+	int			i;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19)
+	struct sk98lin_stats *sk98lin_etht_stats = 
+		(port == 0) ? sk98lin_etht_stats_port0 : sk98lin_etht_stats_port1;
+
+	switch(stringset) {
+		case ETH_SS_STATS: {
+			for(i=0; i < SK98LIN_STATS_LEN; i++) {
+				memcpy(&strings[i * ETHT_STATSTRING_LEN],
+					&(sk98lin_etht_stats[i].stat_string),
+					ETHT_STATSTRING_LEN);
+			}
+			break;
+		}
+	}
+#endif
+}
+
+
+/*****************************************************************************
+ *
+ * 	SkGeGetStatsLen - retrieves the statistic count
+ *
+ * Description:
+ *	N/A
+ *
+ * Returns:	N/A
+ *
+ */
+int SkGeGetStatsLen(struct net_device *dev)
+{
+	return SK98LIN_STATS_LEN;
+}
+
+
+
+
+/*****************************************************************************
+ *
+ * 	SkGeGetEthStats - retrieves the card statistics
+ *
+ * Description:
+ *	All current statistics of a selected adapter are placed 
+ *	in the passed ethtool_stats structure and are returned.
+ *
+ * Returns:	N/A
+ *
+ */
+void SkGeGetEthStats(struct net_device *dev,
+			struct ethtool_stats *stats,
+			u64 *data)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	SK_U32			Size         = sizeof(SK_PNMI_STRUCT_DATA);
+	SK_PNMI_STRUCT_DATA     *pPnmiStruct = &pAC->PnmiStruct;
+	int			port         = pNet->PortNr;
+	int			i;
+
+	struct sk98lin_stats *sk98lin_etht_stats = 
+		(port == 0) ? sk98lin_etht_stats_port0 : sk98lin_etht_stats_port1;
+
+	if (netif_running(pAC->dev[port])) {
+		SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, port);
+	}
+
+	for(i = 0; i < SK98LIN_STATS_LEN; i++) {
+		if (netif_running(pAC->dev[port])) {
+			data[i] = (sk98lin_etht_stats[i].sizeof_stat ==
+				sizeof(uint64_t)) ?
+				*(uint64_t *)((char *)pAC +
+				sk98lin_etht_stats[i].stat_offset) :
+				*(uint32_t *)((char *)pAC +
+				sk98lin_etht_stats[i].stat_offset);
+		} else {
+			data[i] = (sk98lin_etht_stats[i].sizeof_stat ==
+				sizeof(uint64_t)) ? (uint64_t) 0 : (uint32_t) 0;
+		}
+	}
+}
+
+
+/*****************************************************************************
+ *
+ *	SkGeSetSettings - configures the settings of a selected adapter
+ *
+ * Description:
+ *	Possible settings that may be altered are a)speed, b)duplex or 
+ *	c)autonegotiation.
+ *
+ * Returns:
+ *	==0:	everything fine, no error
+ *	!=0:	the return value is the error code of the failure 
+ */
+int SkGeSetSettings(struct net_device *dev,
+			struct ethtool_cmd *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	int			port         = pNet->PortNr;
+
+	SK_U32       Instance;
+	char         Buf[4];
+	unsigned int Len = 1;
+	int Ret;
+
+	if (port == 0) {
+		Instance = (pAC->RlmtNets == 2) ? 1 : 2;
+	} else {
+		Instance = (pAC->RlmtNets == 2) ? 2 : 3;
+	}
+
+	if (((ecmd->autoneg == AUTONEG_DISABLE) || (ecmd->autoneg == AUTONEG_ENABLE)) &&
+	    ((ecmd->duplex == DUPLEX_FULL) || (ecmd->duplex == DUPLEX_HALF))) {
+		if (ecmd->autoneg == AUTONEG_DISABLE) {
+			if (ecmd->duplex == DUPLEX_FULL) { 
+				*Buf = (char) SK_LMODE_FULL;
+			} else {
+				*Buf = (char) SK_LMODE_HALF;
+			}
+		} else {
+		/* Autoneg on. Enable autoparam */
+			*Buf = (char) SK_LMODE_AUTOBOTH;
+		}
+
+		Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, 
+					&Buf, &Len, Instance, pNet->NetNr);
+	
+		if (Ret != SK_PNMI_ERR_OK) {
+			return -EINVAL;
+		}
+	} else if (ecmd->autoneg == AUTONEG_ENABLE) {
+	/* Set default values */
+		*Buf = (char) SK_LMODE_AUTOBOTH;
+		Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, 
+					&Buf, &Len, Instance, pNet->NetNr);
+	}
+
+	if ((ecmd->speed == SPEED_1000) ||
+	    (ecmd->speed == SPEED_100)  || 
+	    (ecmd->speed == SPEED_10)) {
+
+		if (ecmd->autoneg == AUTONEG_ENABLE) {
+			*Buf = (char) SK_LSPEED_AUTO;
+		} else if (ecmd->speed == SPEED_1000) {
+			*Buf = (char) SK_LSPEED_1000MBPS;
+		} else if (ecmd->speed == SPEED_100) {
+			*Buf = (char) SK_LSPEED_100MBPS;
+		} else {
+			*Buf = (char) SK_LSPEED_10MBPS;
+		}
+
+		Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
+					&Buf, &Len, Instance, pNet->NetNr);
+	
+		if (Ret != SK_PNMI_ERR_OK) {
+			return -EINVAL;
+		}
+	} else if (ecmd->autoneg == AUTONEG_ENABLE) {
+		*Buf = (char) SK_LSPEED_AUTO;
+		Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
+					&Buf, &Len, Instance, pNet->NetNr);
+	} else {
+		return -EINVAL;
+	}
+
+	return(0);
+}
+
+/*****************************************************************************
+ *
+ *	SkGeSetWolSettings - configures the WOL settings of a selected adapter
+ *
+ * Description:
+ *	The WOL settings of a selected adapter are configured regarding
+ *	the parameters in the passed ethtool_wolinfo structure.
+ *	Note that currently only wake on magic packet is supported!
+ *
+ * Returns:
+ *	==0:	everything fine, no error
+ *	!=0:	the return value is the error code of the failure 
+ */
+int SkGeSetWolSettings(struct net_device *dev,
+			struct ethtool_wolinfo *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+
+	if (ecmd->wolopts != WAKE_MAGIC && ecmd->wolopts != 0)
+		return -EOPNOTSUPP;
+
+	if (((ecmd->wolopts & WAKE_MAGIC) == WAKE_MAGIC) || (ecmd->wolopts == 0)) {
+		pAC->WolInfo.ConfiguredWolOptions = ecmd->wolopts;
+		return 0;
+	}
+	return -EFAULT;
+}
+
+
+/*****************************************************************************
+ *
+ *	SkGeSetPauseParam - configures the pause parameters of an adapter
+ *
+ * Description:
+ *	This function sets the Rx or Tx pause parameters 
+ *
+ * Returns:
+ *	==0:	everything fine, no error
+ *	!=0:	the return value is the error code of the failure 
+ */
+int SkGeSetPauseParam(struct net_device *dev,
+			struct ethtool_pauseparam *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	int			port         = pNet->PortNr;
+	SK_GEPORT		*pPort = &pAC->GIni.GP[port];
+	int			PrevSpeedVal = pPort->PLinkSpeedUsed;
+	SK_U32			Instance;
+	char			Buf[4];
+	int			Ret;
+	SK_BOOL			prevAutonegValue = SK_TRUE;
+	int			prevTxPause      = 0;
+	int			prevRxPause      = 0;
+	unsigned int		Len              = 1;
+
+
+        if (port == 0) {
+                Instance = (pAC->RlmtNets == 2) ? 1 : 2;
+        } else {
+                Instance = (pAC->RlmtNets == 2) ? 2 : 3;
+        }
+
+	/*
+	** we have to determine the current settings to see if 
+	** the operator requested any modification of the flow 
+	** control parameters...
+	*/
+	if (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND) {
+		prevTxPause = 1;
+	} 
+	if ((pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
+	    (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM)) {
+		prevTxPause = 1;
+		prevRxPause = 1;
+	}
+
+	if ((prevRxPause == 0) && (prevTxPause == 0)) {
+		prevAutonegValue = SK_FALSE;
+	}
+
+
+	/*
+	** perform modifications regarding the changes 
+	** requested by the operator
+	*/
+	if (ecmd->autoneg != prevAutonegValue) {
+		if (ecmd->autoneg == AUTONEG_DISABLE) {
+			*Buf = (char) SK_FLOW_MODE_NONE;
+		} else {
+			*Buf = (char) SK_FLOW_MODE_SYMMETRIC;
+		}
+	} else {
+		if(ecmd->rx_pause && ecmd->tx_pause) {
+			*Buf = (char) SK_FLOW_MODE_SYMMETRIC;
+		} else if (ecmd->rx_pause && !ecmd->tx_pause) {
+			*Buf = (char) SK_FLOW_MODE_SYM_OR_REM;
+		} else if(!ecmd->rx_pause && ecmd->tx_pause) {
+			*Buf = (char) SK_FLOW_MODE_LOC_SEND;
+		} else {
+			*Buf = (char) SK_FLOW_MODE_NONE;
+		}
+	}
+
+	Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
+			&Buf, &Len, Instance, pNet->NetNr);
+
+	if (Ret != SK_PNMI_ERR_OK) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
+		("ethtool (sk98lin): error changing rx/tx pause (%i)\n", Ret));
+	}  else {
+		Len = 1; /* set buffer length to correct value */
+	}
+
+	/*
+	** It may be that autoneg has been disabled! Therefore
+	** set the speed to the previously used value...
+	*/
+	*Buf = (char) PrevSpeedVal;
+
+	Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
+			&Buf, &Len, Instance, pNet->NetNr);
+
+	if (Ret != SK_PNMI_ERR_OK) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
+		("ethtool (sk98lin): error setting speed (%i)\n", Ret));
+	}
+        return 0;
+}
+
+
+/*****************************************************************************
+ *
+ *	SkGeSetCoalesce - configures the IRQ moderation of an adapter
+ *
+ * Description:
+ *	Depending on the desired IRQ moderation parameters, either a) static,
+ *	b) dynamic or c) no moderation is configured. 
+ *
+ * Returns:
+ *	==0:	everything fine, no error
+ *	!=0:	the return value is the error code of the failure 
+ *
+ * Notes:
+ *	The supported timeframe for the coalesced interrupts ranges from
+ *	33.333us (30 IntsPerSec) down to 25us (40.000 IntsPerSec).
+ *	Any requested value that is not in this range will abort the request!
+ */
+int SkGeSetCoalesce(struct net_device *dev,
+			struct ethtool_coalesce *ecmd)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	DIM_INFO		*Info        = &pAC->DynIrqModInfo;
+	int			PrevModeration = Info->IntModTypeSelect;
+
+	Info->IntModTypeSelect = C_INT_MOD_NONE; /* initial default */
+
+	if ((ecmd->rx_coalesce_usecs) || (ecmd->tx_coalesce_usecs)) {
+		if (ecmd->rx_coalesce_usecs) {
+			if ((ecmd->rx_coalesce_usecs < 25) ||
+			    (ecmd->rx_coalesce_usecs > 33333)) {
+				return -EINVAL; 
+			}
+		}
+		if (ecmd->tx_coalesce_usecs) {
+			if ((ecmd->tx_coalesce_usecs < 25) ||
+			    (ecmd->tx_coalesce_usecs > 33333)) {
+				return -EINVAL; 
+			}
+		}
+		if (!CHIP_ID_YUKON_2(pAC)) {
+			if ((Info->MaskIrqModeration == IRQ_MASK_SP_RX) ||
+			    (Info->MaskIrqModeration == IRQ_MASK_SP_TX) ||
+			    (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) {
+				Info->MaskIrqModeration = IRQ_MASK_SP_ONLY;
+			} 
+		}
+		Info->IntModTypeSelect = C_INT_MOD_STATIC;
+		if (ecmd->rx_coalesce_usecs) {
+			Info->MaxModIntsPerSec = 
+				1000000 / ecmd->rx_coalesce_usecs;
+			if (!CHIP_ID_YUKON_2(pAC)) {
+				if (Info->MaskIrqModeration == IRQ_MASK_TX_ONLY) {
+					Info->MaskIrqModeration = IRQ_MASK_TX_RX;
+				} 
+				if (Info->MaskIrqModeration == IRQ_MASK_SP_ONLY) {
+					Info->MaskIrqModeration = IRQ_MASK_SP_RX;
+				} 
+				if (Info->MaskIrqModeration == IRQ_MASK_SP_TX) {
+					Info->MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+				}
+			} else {
+				Info->MaskIrqModeration = Y2_IRQ_MASK;
+			}
+		}
+		if (ecmd->tx_coalesce_usecs) {
+			Info->MaxModIntsPerSec = 
+				1000000 / ecmd->tx_coalesce_usecs;
+			if (!CHIP_ID_YUKON_2(pAC)) {
+				if (Info->MaskIrqModeration == IRQ_MASK_RX_ONLY) {
+					Info->MaskIrqModeration = IRQ_MASK_TX_RX;
+				} 
+				if (Info->MaskIrqModeration == IRQ_MASK_SP_ONLY) {
+					Info->MaskIrqModeration = IRQ_MASK_SP_TX;
+				} 
+				if (Info->MaskIrqModeration == IRQ_MASK_SP_RX) {
+					Info->MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+				}
+			} else {
+				Info->MaskIrqModeration = Y2_IRQ_MASK;
+			}
+		}
+	}
+	if ((ecmd->rate_sample_interval)  ||
+	    (ecmd->rx_coalesce_usecs_low) ||
+	    (ecmd->tx_coalesce_usecs_low) ||
+	    (ecmd->rx_coalesce_usecs_high)||
+	    (ecmd->tx_coalesce_usecs_high)) {
+		if (ecmd->rate_sample_interval) {
+			if ((ecmd->rate_sample_interval < 1) ||
+			    (ecmd->rate_sample_interval > 10)) {
+				return -EINVAL; 
+			}
+		}
+		if (ecmd->rx_coalesce_usecs_low) {
+			if ((ecmd->rx_coalesce_usecs_low < 25) ||
+			    (ecmd->rx_coalesce_usecs_low > 33333)) {
+				return -EINVAL; 
+			}
+		}
+		if (ecmd->rx_coalesce_usecs_high) {
+			if ((ecmd->rx_coalesce_usecs_high < 25) ||
+			    (ecmd->rx_coalesce_usecs_high > 33333)) {
+				return -EINVAL; 
+			}
+		}
+		if (ecmd->tx_coalesce_usecs_low) {
+			if ((ecmd->tx_coalesce_usecs_low < 25) ||
+			    (ecmd->tx_coalesce_usecs_low > 33333)) {
+				return -EINVAL; 
+			}
+		}
+		if (ecmd->tx_coalesce_usecs_high) {
+			if ((ecmd->tx_coalesce_usecs_high < 25) ||
+			    (ecmd->tx_coalesce_usecs_high > 33333)) {
+				return -EINVAL; 
+			}
+		}
+
+		Info->IntModTypeSelect = C_INT_MOD_DYNAMIC;
+		if (ecmd->rate_sample_interval) {
+			Info->DynIrqModSampleInterval = 
+				ecmd->rate_sample_interval; 
+		}
+		if (ecmd->rx_coalesce_usecs_low) {
+			Info->MaxModIntsPerSecLowerLimit = 
+				1000000 / ecmd->rx_coalesce_usecs_low;
+		}
+		if (ecmd->tx_coalesce_usecs_low) {
+			Info->MaxModIntsPerSecLowerLimit = 
+				1000000 / ecmd->tx_coalesce_usecs_low;
+		}
+		if (ecmd->rx_coalesce_usecs_high) {
+			Info->MaxModIntsPerSecUpperLimit = 
+				1000000 / ecmd->rx_coalesce_usecs_high;
+		}
+		if (ecmd->tx_coalesce_usecs_high) {
+			Info->MaxModIntsPerSecUpperLimit = 
+				1000000 / ecmd->tx_coalesce_usecs_high;
+		}
+	}
+
+	if ((PrevModeration         == C_INT_MOD_NONE) &&
+	    (Info->IntModTypeSelect != C_INT_MOD_NONE)) {
+		SkDimEnableModerationIfNeeded(pAC);
+	}
+	if (PrevModeration != C_INT_MOD_NONE) {
+		SkDimDisableModeration(pAC, PrevModeration);
+		if (Info->IntModTypeSelect != C_INT_MOD_NONE) {
+			SkDimEnableModerationIfNeeded(pAC);
+		}
+	}
+
+        return 0;
+}
+
+#ifdef ENABLE_FUTURE_ETH
+/*****************************************************************************
+ *
+ *	SkGeSetSG - set the SG parameters
+ *
+ * Description:
+ *	This function sets the SG parameters 
+ *
+ * Returns:
+ *	==0:	everything fine, no error
+ *	!=0:	the return value is the error code of the failure 
+ */
+int SkGeSetSG(struct net_device *dev,
+			u32 data)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+
+	if (pAC->GIni.GIGenesis)
+		return -EOPNOTSUPP;
+
+	return ethtool_op_set_sg(dev, data);
+}
+
+#endif
+
+#ifdef ENABLE_FUTURE_ETH
+
+/*****************************************************************************
+ *
+ *	SkGeSetTxCsum - set the TxCsum parameters
+ *
+ * Description:
+ *	This function sets the TxCsum parameters 
+ *
+ * Returns:
+ *	==0:	everything fine, no error
+ *	!=0:	the return value is the error code of the failure 
+ */
+int SkGeSetTxCsum(struct net_device *dev,
+			u32 data)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+
+	if (pAC->GIni.GIGenesis)
+		return -EOPNOTSUPP;
+
+	return ethtool_op_set_tx_csum(dev, data);
+}
+
+#endif
+
+/*****************************************************************************
+ *
+ *	SkGeSetRxCsum - set the SkGeSetRxCsum parameters
+ *
+ * Description:
+ *	This function sets the RxCsum parameters 
+ *
+ * Returns:
+ *	==0:	everything fine, no error
+ *	!=0:	the return value is the error code of the failure 
+ */
+int SkGeSetRxCsum(struct net_device *dev,
+			u32 data)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	int			port         = pNet->PortNr;
+
+	if (pAC->GIni.GIGenesis && data)
+		return -EOPNOTSUPP;
+
+	pAC->RxPort[port].UseRxCsum = data;
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * 	SkGePhysId - start the locate NIC feature of the elected adapter 
+ *
+ * Description:
+ *	This function is used if the user want to locate a particular NIC.
+ *	All LEDs are regularly switched on and off, so the NIC can easily
+ *	be identified.
+ *
+ * Returns:	
+ *	==0:	everything fine, no error, locateNIC test was started
+ *	!=0:	one locateNIC test runs already
+ *
+ */
+int SkGePhysId(struct net_device *dev,
+			u32 data)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+	SK_IOC                   IoC       = pAC->IoBase;
+	int			port         = pNet->PortNr;
+	struct SK_NET_DEVICE	*pDev        = pAC->dev[port];
+	int			OtherPort    = (port) ? 0 : 1;
+	struct SK_NET_DEVICE	*pOtherDev   = pAC->dev[OtherPort];
+
+	if (isLocateNICrunning) {
+		return -EFAULT;
+	}
+	isLocateNICrunning = SK_TRUE;
+	currentPortIndex = port;
+	isDualNetCard = (pDev != pOtherDev) ? SK_TRUE : SK_FALSE;
+	doSwitchLEDsOn = SK_FALSE;
+
+	if (netif_running(pAC->dev[port])) {
+		boardWasDown[0] = SK_FALSE;
+	} else {
+		(*pDev->netdev_ops->ndo_open)(pDev);
+		boardWasDown[0] = SK_TRUE;
+	}
+
+	if (isDualNetCard) {
+		if (netif_running(pAC->dev[OtherPort])) {
+			boardWasDown[1] = SK_FALSE;
+		} else {
+			(*pOtherDev->netdev_ops->ndo_open)(pOtherDev);
+			boardWasDown[1] = SK_TRUE;
+		}
+	}
+
+	if ( (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) ||
+	     (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) ) {
+	  SkMacClearRst(pAC, IoC, port);
+	}
+
+
+	if ((data < 1) || (data > 30)) {
+		data = 3; /* three seconds default */
+	}
+	nbrBlinkQuarterSeconds = 4*data;
+
+	init_timer(&locateNICtimer);
+	locateNICtimer.function = toggleLeds;
+	locateNICtimer.data     = (unsigned long) pNet;
+	locateNICtimer.expires  = jiffies + HZ; /* initially 1sec */
+	add_timer(&locateNICtimer);
+
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * 	toggleLeds - Changes the LED state of an adapter
+ *
+ * Description:
+ *	This function changes the current state of all LEDs of an adapter so
+ *	that it can be located by a user. If the requested time interval for
+ *	this test has elapsed, this function cleans up everything that was 
+ *	temporarily setup during the locate NIC test. This involves of course
+ *	also closing or opening any adapter so that the initial board state 
+ *	is recovered.
+ *
+ * Returns:	N/A
+ *
+ */
+static void toggleLeds(
+unsigned long ptr)  /* holds the pointer to adapter control context */
+{
+	DEV_NET              *pNet      = (DEV_NET*) ptr;
+	SK_AC                *pAC       = pNet->pAC;
+	int                   port      = pNet->PortNr;
+	SK_IOC                IoC       = pAC->IoBase;
+	struct SK_NET_DEVICE *pDev      = pAC->dev[port];
+	int                   OtherPort = (port) ? 0 : 1;
+	struct SK_NET_DEVICE *pOtherDev = pAC->dev[OtherPort];
+	SK_U16                PageSelect;
+	SK_BOOL               YukLedState;
+
+	SK_U16  YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON)  |
+			    PHY_M_LED_MO_10(MO_LED_ON)   |
+			    PHY_M_LED_MO_100(MO_LED_ON)  |
+			    PHY_M_LED_MO_1000(MO_LED_ON) | 
+			    PHY_M_LED_MO_RX(MO_LED_ON));
+	SK_U16  YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF)  |
+			     PHY_M_LED_MO_10(MO_LED_OFF)   |
+			     PHY_M_LED_MO_100(MO_LED_OFF)  |
+			     PHY_M_LED_MO_1000(MO_LED_OFF) | 
+			     PHY_M_LED_MO_RX(MO_LED_OFF) | 
+			     PHY_M_LED_MO_TX(MO_LED_OFF));
+
+	nbrBlinkQuarterSeconds--;
+	if (nbrBlinkQuarterSeconds <= 0) {
+	  /*
+	   * We have to stop the device again in case the device has no
+	   * been up.
+	   */
+
+	  if (!boardWasDown[0]) {
+	    /*
+	     * The board is already up as we bring it up in case it is not.
+	     */
+	  } else {
+	    (*pDev->netdev_ops->ndo_stop)(pDev);
+	  }
+	  if (isDualNetCard) {
+	    if (!boardWasDown[1]) {
+	      /*
+	       * The board is already up as we bring it up in case it is not.
+	       */
+	    } else {
+	      (*pOtherDev->netdev_ops->ndo_stop)(pOtherDev);
+	    }
+	    
+	  }
+
+	  isDualNetCard      = SK_FALSE;
+	  isLocateNICrunning = SK_FALSE;
+	  return;
+	}
+	doSwitchLEDsOn = (doSwitchLEDsOn) ? SK_FALSE : SK_TRUE;
+
+	if ( (doSwitchLEDsOn) && (nbrBlinkQuarterSeconds > 2) ){
+		if (pAC->GIni.GIGenesis) {
+			SK_OUT8(IoC,MR_ADDR(port,LNK_LED_REG),(SK_U8)SK_LNK_ON);
+			SkGeYellowLED(pAC,IoC,LED_ON >> 1);
+			SkGeXmitLED(pAC,IoC,MR_ADDR(port,RX_LED_INI),SK_LED_TST);
+			if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM) {
+				SkXmPhyWrite(pAC,IoC,port,PHY_BCOM_P_EXT_CTRL,PHY_B_PEC_LED_ON);
+			} else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE) {
+				SkXmPhyWrite(pAC,IoC,port,PHY_LONE_LED_CFG,0x0800);
+			} else {
+				SkGeXmitLED(pAC,IoC,MR_ADDR(port,TX_LED_INI),SK_LED_TST);
+			}
+		} else {
+		  if ( (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) ||
+ 		       (pAC->GIni.GIChipId == CHIP_ID_YUKON_2(pAC)) ||
+ 		       (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) ) {
+
+		    YukLedOn = 0;
+		    YukLedState = 1;
+ 		    YukLedOn |= PHY_M_LEDC_INIT_CTRL(YukLedState ? 9 : 8);
+		    YukLedState = 1;
+		    YukLedOn |= PHY_M_LEDC_STA1_CTRL(YukLedState ? 9 : 8);
+		    YukLedState = 1;
+		    YukLedOn |= PHY_M_LEDC_STA0_CTRL(YukLedState ? 9 : 8);
+		    YukLedState = 1;
+		    YukLedOn |= PHY_M_LEDC_LOS_CTRL(YukLedState ? 9 : 8);
+		       
+		    /* save page register */
+		    SkGmPhyRead(pAC, IoC, port, PHY_MARV_EXT_ADR, &PageSelect);
+		    
+		    /* select page 3 for LED control */
+		    SkGmPhyWrite(pAC, IoC, port, PHY_MARV_EXT_ADR, 3);
+		    
+		    SkGmPhyWrite(pAC, IoC, port, PHY_MARV_PHY_CTRL, YukLedOn);
+		    
+		    /* restore page register */
+		    SkGmPhyWrite(pAC, IoC, port, PHY_MARV_EXT_ADR, PageSelect);
+		  }
+		  else {
+		    SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_OVER,YukLedOn);	
+		  }
+		}
+	} else {
+		if (pAC->GIni.GIGenesis) {
+		        
+			SK_OUT8(IoC,MR_ADDR(port,LNK_LED_REG),(SK_U8)SK_LNK_OFF);
+			SkGeYellowLED(pAC,IoC,LED_OFF >> 1);
+			SkGeXmitLED(pAC,IoC,MR_ADDR(port,RX_LED_INI),SK_LED_DIS);
+			if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM) {
+				SkXmPhyWrite(pAC,IoC,port,PHY_BCOM_P_EXT_CTRL,PHY_B_PEC_LED_OFF);
+			} else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE) {
+				SkXmPhyWrite(pAC,IoC,port,PHY_LONE_LED_CFG,PHY_L_LC_LEDT);
+			} else {
+				SkGeXmitLED(pAC,IoC,MR_ADDR(port,TX_LED_INI),SK_LED_DIS);
+			}
+		} else {
+		  if ( (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) ||
+ 		       (pAC->GIni.GIChipId == CHIP_ID_YUKON_2(pAC)) ||
+ 		       (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) ) {
+
+		    YukLedOn = 0;
+		    YukLedState = 1;
+ 		    YukLedOn |= PHY_M_LEDC_INIT_CTRL(YukLedState ? 9 : 8);
+		    YukLedState = 1;
+		    YukLedOn |= PHY_M_LEDC_STA1_CTRL(YukLedState ? 9 : 8);
+		    YukLedState = 1;
+		    YukLedOn |= PHY_M_LEDC_STA0_CTRL(YukLedState ? 9 : 8);
+		    YukLedState = 1;
+		    YukLedOn |= PHY_M_LEDC_LOS_CTRL(YukLedState ? 9 : 8);
+
+		    /* save page register */
+		    SkGmPhyRead(pAC, IoC, port, PHY_MARV_EXT_ADR, &PageSelect);
+		    
+		    /* select page 3 for LED control */
+		    SkGmPhyWrite(pAC, IoC, port, PHY_MARV_EXT_ADR, 3);
+		    
+		    SkGmPhyWrite(pAC, IoC, port, PHY_MARV_PHY_CTRL, YukLedOff);
+		    
+		    /* restore page register */
+		    SkGmPhyWrite(pAC, IoC, port, PHY_MARV_EXT_ADR, PageSelect);
+		  }
+		  else {
+		    SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_OVER,YukLedOff);	
+		  }
+		}
+	}
+
+	locateNICtimer.function = toggleLeds;
+	locateNICtimer.data     = (unsigned long) pNet;
+	locateNICtimer.expires  = jiffies + (HZ/4);
+	add_timer(&locateNICtimer);
+} 
+
+#ifdef NETIF_F_TSO
+/*****************************************************************************
+ *
+ *	SkGeSetTSO - set the TSO parameters
+ *
+ * Description:
+ *	This function sets the TSO parameters 
+ *
+ * Returns:
+ *	==0:	everything fine, no error
+ *	!=0:	the return value is the error code of the failure 
+ */
+int SkGeSetTSO(struct net_device *dev,
+			u32 data)
+{
+	DEV_NET			*pNet        = (DEV_NET*)netdev_priv(dev);
+	SK_AC			*pAC         = pNet->pAC;
+
+	if (CHIP_ID_YUKON_2(pAC)) {
+		if (data) {
+			if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) && (dev->mtu > ETH_MAX_MTU)) {
+				dev->features &= ~NETIF_F_TSO;
+			} else {
+				dev->features |= NETIF_F_TSO;
+			}
+		} else {
+			dev->features &= ~NETIF_F_TSO;
+		}
+		return 0;
+	}
+	return -EOPNOTSUPP;
+
+}
+#endif
+
+
+
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
diff --git a/drivers/net/sk98lin/skfops.c b/drivers/net/sk98lin/skfops.c
new file mode 100755
index 0000000..e47ec67
--- /dev/null
+++ b/drivers/net/sk98lin/skfops.c
@@ -0,0 +1,273 @@
+/******************************************************************************
+ *
+ * Name:    skfops.c
+ * Project: Gigabit Ethernet Adapters, Common Modules
+ * Version: $Revision: 1.1.2.2 $
+ * Date:    $Date: 2006/09/18 11:57:21 $
+ * Purpose: Kernel mode file read functions.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  (C)Copyright 1998-2002 SysKonnect GmbH.
+ *  (C)Copyright 2002-2003 Marvell.
+ *
+ *  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.
+ *
+ *  The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * This module is intended to handle all file read functions
+ *
+ * Include File Hierarchy:
+ *
+ *   "h/skdrv1st.h"
+ *   "h/skdrv2nd.h"
+ *
+ ******************************************************************************/
+
+/*
+ Event queue and dispatcher
+*/
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+"$Header: /data/cvs/sweprojects/yukon2/lindrv/asf_linux/Attic/skfops.c,v 1.1.2.2 2006/09/18 11:57:21 mlindner Exp $" ;
+#endif
+
+#include "h/sktypes.h"
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+
+
+/********************************************************
+		Local Variables
+********************************************************/
+
+
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+
+
+/********************************************************
+		Local Functions
+********************************************************/
+
+/** 
+ *  @brief This function opens/create a file in kernel mode.
+ *  
+ *  @param filename	Name of the file to be opened
+ *  @param flags		File flags 
+ *  @param mode		File permissions
+ *  @return 		file pointer if successful or NULL if failed.
+ */
+static struct file * sk_fopen(const char * filename, 
+	unsigned int flags,
+	int mode)
+{
+	int		orgfsuid, orgfsgid;
+	struct		file *	file_ret;
+
+	/* Save uid and gid used for filesystem access.  */
+	orgfsuid = current->fsuid;
+	orgfsgid = current->fsgid;
+
+	/* Set user and group to 0 (root) */
+	current->fsuid = 0;
+	current->fsgid = 0;
+  
+	/* Open the file in kernel mode */
+	file_ret = filp_open(filename, flags, mode);
+	
+	/* Restore the uid and gid */
+	current->fsuid = orgfsuid;
+	current->fsgid = orgfsgid;
+
+	/* Check if the file was opened successfully
+	  and return the file pointer of it was.
+	 */
+	return ((IS_ERR(file_ret)) ? NULL : file_ret);
+}
+
+
+
+/** 
+ *  @brief This function closes a file in kernel mode.
+ *  
+ *  @param file_ptr     File pointer 
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int sk_fclose(struct file * file_ptr)
+{
+	int	orgfsuid, orgfsgid;
+	int	file_ret;
+
+	if((NULL == file_ptr) || (IS_ERR(file_ptr)))
+		return -ENOENT;
+	
+	/* Save uid and gid used for filesystem access.  */
+	orgfsuid = current->fsuid;
+	orgfsgid = current->fsgid;
+
+	/* Set user and group to 0 (root) */
+	current->fsuid = 0;
+	current->fsgid = 0;
+  
+	/* Close the file in kernel mode (user_id = 0) */
+	file_ret = filp_close(file_ptr, 0);
+	
+	/* Restore the uid and gid */
+	current->fsuid = orgfsuid;
+	current->fsgid = orgfsgid;
+
+    return (file_ret);
+}
+
+
+
+/** 
+ *  @brief This function reads data from files in kernel mode.
+ *  
+ *  @param file_ptr     File pointer
+ *  @param buf		Buffers to read data into
+ *  @param len		Length of buffer
+ *  @return 		number of characters read	
+ */
+static int sk_fread(struct file * file_ptr, char * buf, int len)
+{
+	int				orgfsuid, orgfsgid;
+	int				file_ret;
+	mm_segment_t	orgfs;
+
+	/* Check if the file pointer is valid */
+	if((NULL == file_ptr) || (IS_ERR(file_ptr)))
+		return -ENOENT;
+
+	/* Check for a valid file read function */
+	if(file_ptr->f_op->read == NULL)
+		return  -ENOSYS;
+
+	/* Check for access permissions */
+	if(((file_ptr->f_flags & O_ACCMODE) & (O_RDONLY | O_RDWR)) == 0)
+		return -EACCES;
+
+	/* Check if there is a valid length */
+	if(0 >= len)
+		return -EINVAL;
+
+	/* Save uid and gid used for filesystem access.  */
+	orgfsuid = current->fsuid;
+	orgfsgid = current->fsgid;
+
+	/* Set user and group to 0 (root) */
+	current->fsuid = 0;
+	current->fsgid = 0;
+
+	/* Save FS register and set FS register to kernel
+	  space, needed for read and write to accept
+	  buffer in kernel space.  */
+	orgfs = get_fs();
+
+	/* Set the FS register to KERNEL mode.  */
+	set_fs(KERNEL_DS);
+
+	/* Read the actual data from the file */
+	file_ret = file_ptr->f_op->read(file_ptr, buf, len, &file_ptr->f_pos);
+
+	/* Restore the FS register */
+	set_fs(orgfs);
+
+	/* Restore the uid and gid */
+	current->fsuid = orgfsuid;
+	current->fsgid = orgfsgid;
+
+    return (file_ret);
+}
+
+
+
+/********************************************************
+		Global Functions
+********************************************************/
+
+/** 
+ *  @brief This function reads FW/Helper.
+ *  
+ *  @param name		File name
+ *  @param addr		Pointer to buffer storing FW/Helper
+ *  @param len     	Pointer to length of FW/Helper
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+SK_BOOL fw_read(	SK_AC *pAC,    /* Pointer to adapter context */
+	char *name, SK_U8 **addr, SK_U32 *len )
+{
+	struct 	file *fp;
+	SK_BOOL 	ret;
+	SK_U8	*ptr;
+
+	fp = sk_fopen(name, O_RDWR, 0 );
+
+	if ( fp == NULL ) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("fw_read: Could not open file:%s\n", name));
+		return SK_FALSE;
+	}
+
+	/*calculate file length*/
+	*len = fp->f_dentry->d_inode->i_size - fp->f_pos;
+
+	ptr = (SK_U8 *)kmalloc( *len, GFP_KERNEL );
+
+	if ( ptr == NULL ) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("fw_read: vmalloc failure!\n"));
+		return SK_FALSE;
+	}
+	if(sk_fread(fp, ptr,*len) > 0) {
+		*addr = ptr;
+		ret = SK_TRUE;
+	} else {
+		kfree(ptr);
+		*addr = NULL;
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("fw_read: failed to read file:%s\n", name));
+		ret = SK_FALSE;
+	}
+     	
+	sk_fclose( fp );
+	return ret;
+}
+
+
+/** 
+ *  @brief This function checks whether the file 'name' exists.
+ *  
+ *  @param name		File name
+ *  @return 		SK_TRUE or SK_FALSE
+ */
+SK_BOOL fw_file_exists(	SK_AC *pAC,    /* Pointer to adapter context */
+	char *name )
+{
+	struct 	file *fp;
+
+	fp = sk_fopen(name, O_RDONLY | O_LARGEFILE, 0 );
+
+	if ( fp == NULL ) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("fw_file_exists: Could not open file:%s\n", name));
+		return SK_FALSE;
+	}
+	sk_fclose( fp );
+	return SK_TRUE;
+}
+
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
new file mode 100755
index 0000000..a324578
--- /dev/null
+++ b/drivers/net/sk98lin/skge.c
@@ -0,0 +1,6989 @@
+/******************************************************************************
+ *
+ * Name:        skge.c
+ * Project:     GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:     $Revision: 1.74.2.38 $
+ * Date:        $Date: 2007/10/02 09:03:51 $
+ * Purpose:     The main driver source module
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet 
+ *      Server Adapters.
+ *
+ *	Author: Mirko Lindner (mlindner@syskonnect.de)
+ *	        Ralph Roesler (rroesler@syskonnect.de)
+ *
+ *	Address all question to: linux@syskonnect.de
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ *	All source files in this sk98lin directory except of the sk98lin 
+ *	Linux specific files
+ *
+ *		- skdim.c
+ *		- skethtool.c
+ *		- skge.c
+ *		- skproc.c
+ *		- sky2.c
+ *		- Makefile
+ *		- h/skdrv1st.h
+ *		- h/skdrv2nd.h
+ *		- h/sktypes.h
+ *		- h/skversion.h
+ *
+ *	are part of SysKonnect's common modules for the SK-9xxx adapters.
+ *
+ *	Those common module files which are not Linux specific are used to 
+ *	build drivers on different OS' (e.g. Windows, MAC OS) so that those
+ *	drivers are based on the same set of files
+ *
+ *	At a first glance, this seems to complicate things unnescessarily on 
+ *	Linux, but please do not try to 'clean up' them without VERY good 
+ *	reasons, because this will make it more difficult to keep the sk98lin
+ *	driver for Linux in synchronisation with the other drivers running on
+ *	other operating systems.
+ *
+ ******************************************************************************/
+
+#include	"h/skversion.h"
+
+#include	<linux/module.h>
+#include	<linux/init.h>
+#include	<linux/ethtool.h>
+
+#ifdef USE_ASF_DASH_FW
+#include        <linux/netdevice.h>
+#include        <linux/inetdevice.h>
+#include        <net/if_inet6.h>
+#include        <linux/ipv6.h>
+#endif
+
+#ifdef CONFIG_PROC_FS
+#include 	<linux/proc_fs.h>
+#endif
+
+#include	"h/skdrv1st.h"
+#include	"h/skdrv2nd.h"
+#include	"h/skpcidevid.h"
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
+#include	<linux/moduleparam.h>
+#endif
+
+#define ENABLE_FUTURE_ETH
+
+/*******************************************************************************
+ *
+ * Defines
+ *
+ ******************************************************************************/
+
+/* for debuging on x86 only */
+/* #define BREAKPOINT() asm(" int $3"); */
+
+
+/* Set blink mode*/
+#define OEM_CONFIG_VALUE (	SK_ACT_LED_BLINK | \
+				SK_DUP_LED_NORMAL | \
+				SK_LED_LINK100_ON)
+
+#define CLEAR_AND_START_RX(Port) SK_OUT8(pAC->IoBase, RxQueueAddr[(Port)]+Q_CSR, CSR_START | CSR_IRQ_CL_F)
+#define START_RX(Port) SK_OUT8(pAC->IoBase, RxQueueAddr[(Port)]+Q_CSR, CSR_START)
+#define CLEAR_TX_IRQ(Port,Prio) SK_OUT8(pAC->IoBase, TxQueueAddr[(Port)][(Prio)]+Q_CSR, CSR_IRQ_CL_F)
+
+
+/*******************************************************************************
+ *
+ * Local Function Prototypes
+ *
+ ******************************************************************************/
+
+static int 	__devinit sk98lin_init_device(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void 	sk98lin_remove_device(struct pci_dev *pdev);
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
+static int	sk98lin_suspend(struct pci_dev *pdev, pm_message_t state);
+#else
+static int	sk98lin_suspend(struct pci_dev *pdev, SK_U32 state);
+#endif
+static int	sk98lin_resume(struct pci_dev *pdev);
+static void	SkEnableWOMagicPacket(SK_AC *pAC, SK_IOC IoC, SK_MAC_ADDR MacAddr);
+#endif
+#ifdef Y2_RECOVERY
+static void	SkGeHandleKernelTimer(unsigned long ptr);
+void		SkGeCheckTimer(DEV_NET *pNet);
+static SK_BOOL  CheckRXCounters(DEV_NET *pNet);
+static void	CheckRxPath(DEV_NET *pNet);
+#endif
+static void	FreeResources(struct SK_NET_DEVICE *dev);
+static int	SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
+static SK_BOOL	BoardAllocMem(SK_AC *pAC);
+static void	BoardFreeMem(SK_AC *pAC);
+static void	BoardInitMem(SK_AC *pAC);
+static void	SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, int*, SK_BOOL);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+static SkIsrRetVar	SkGeIsr(int irq, void *dev_id);
+#else
+static SkIsrRetVar	SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+static SkIsrRetVar	SkGeIsrOnePort(int irq, void *dev_id);
+#else
+static SkIsrRetVar	SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);
+#endif
+static int	SkGeOpen(struct SK_NET_DEVICE *dev);
+static int	SkGeClose(struct SK_NET_DEVICE *dev);
+static int	SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
+static int	SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
+static void	SkGeSetRxMode(struct SK_NET_DEVICE *dev);
+static struct	net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
+static int	SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
+static void	GetConfiguration(SK_AC*);
+static void	ProductStr(SK_AC*);
+static int	XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
+static void	FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
+static void	FillRxRing(SK_AC*, RX_PORT*);
+static SK_BOOL	FillRxDescriptor(SK_AC*, RX_PORT*);
+#ifdef CONFIG_SK98LIN_NAPI
+static int	SkGePoll(struct net_device *dev, int *budget);
+static void	ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL, int*, int);
+#else
+static void	ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
+#endif
+#ifdef SK_POLL_CONTROLLER
+static void	SkGeNetPoll(struct SK_NET_DEVICE *dev);
+#endif
+static void	ClearRxRing(SK_AC*, RX_PORT*);
+static void	ClearTxRing(SK_AC*, TX_PORT*);
+static int	SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
+static void	PortReInitBmu(SK_AC*, int);
+static int	SkGeIocMib(DEV_NET*, unsigned int, int);
+static int	SkGeInitPCI(SK_AC *pAC);
+static SK_U32   ParseDeviceNbrFromSlotName(const char *SlotName);
+static int      SkDrvInitAdapter(SK_AC *pAC, int devNbr);
+static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
+extern void	SkLocalEventQueue(	SK_AC *pAC,
+					SK_U32 Class,
+					SK_U32 Event,
+					SK_U32 Param1,
+					SK_U32 Param2,
+					SK_BOOL Flag);
+extern void	SkLocalEventQueue64(	SK_AC *pAC,
+					SK_U32 Class,
+					SK_U32 Event,
+					SK_U64 Param,
+					SK_BOOL Flag);
+
+static int	XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
+
+/*******************************************************************************
+ *
+ * Extern Function Prototypes
+ *
+ ******************************************************************************/
+
+extern SK_BOOL SkY2AllocateResources(SK_AC *pAC);
+extern void SkY2FreeResources(SK_AC *pAC);
+extern void SkY2AllocateRxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);
+extern void SkY2FreeRxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);
+extern void SkY2FreeTxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+extern SkIsrRetVar SkY2Isr(int irq,void *dev_id);
+#else
+extern SkIsrRetVar SkY2Isr(int irq,void *dev_id,struct pt_regs *ptregs);
+#endif
+extern int SkY2Xmit(struct sk_buff *skb,struct SK_NET_DEVICE *dev);
+extern void SkY2PortStop(SK_AC *pAC,SK_IOC IoC,int Port,int Dir,int RstMode);
+extern void SkY2PortStart(SK_AC *pAC,SK_IOC IoC,int Port);
+extern int SkY2RlmtSend(SK_AC *pAC,int PortNr,struct sk_buff *pMessage);
+extern void SkY2RestartStatusUnit(SK_AC *pAC);
+extern void FillReceiveTableYukon2(SK_AC *pAC,SK_IOC IoC,int Port);
+#ifdef CONFIG_SK98LIN_NAPI
+extern int SkY2Poll(struct net_device *dev, int *budget);
+#endif
+
+extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);	
+extern void SkDimStartModerationTimer(SK_AC *pAC);
+extern void SkDimModerate(SK_AC *pAC);
+
+#ifndef ENABLE_FUTURE_ETH
+extern int SkEthIoctl(struct net_device *netdev, struct ifreq *ifr);
+#else
+/* Ethtool functions */
+extern int SkGeGetSettings(struct net_device *dev, struct ethtool_cmd *ecmd);
+extern void SkGeGetDrvInfo(struct net_device *dev, struct ethtool_drvinfo *ecmd);
+extern void SkGeGetWolSettings(struct net_device *dev, struct ethtool_wolinfo *ecmd);
+extern void SkGeGetPauseParam(struct net_device *dev, struct ethtool_pauseparam *ecmd);
+extern int SkGeGetCoalesce(struct net_device *dev, struct ethtool_coalesce *ecmd);
+extern SK_U32 SkGeGetRxCsum(struct net_device *dev);
+extern void SkGeGetStrings(struct net_device *dev, u32 stringset, u8 *strings);
+extern int SkGeGetStatsLen(struct net_device *dev);
+extern void SkGeGetEthStats(struct net_device *dev, struct ethtool_stats *stats, u64 *data);
+extern int SkGeSetSettings(struct net_device *dev, struct ethtool_cmd *ecmd);
+extern int SkGeSetWolSettings(struct net_device *dev, struct ethtool_wolinfo *ewol);
+extern int SkGeSetPauseParam(struct net_device *dev, struct ethtool_pauseparam *ecmd);
+extern int SkGeSetCoalesce(struct net_device *dev, struct ethtool_coalesce *ecmd);
+extern int SkGeSetSG(struct net_device *dev, u32 data);
+extern int SkGeSetTxCsum(struct net_device *dev, u32 data);
+extern int SkGeSetRxCsum(struct net_device *dev, u32 data);
+extern int SkGePhysId(struct net_device *dev, u32 data);
+#endif
+
+#ifdef NETIF_F_TSO
+extern int SkGeSetTSO(struct net_device *netdev, u32 data);
+#endif
+
+#ifdef CONFIG_PROC_FS
+static const char 	SK_Root_Dir_entry[] = "sk98lin";
+static struct		proc_dir_entry *pSkRootDir;
+extern struct	file_operations sk_proc_fops;
+#endif
+
+#ifdef DEBUG
+static void	DumpMsg(struct sk_buff*, char*);
+static void	DumpData(char*, int);
+static void	DumpLong(char*, int);
+#endif
+
+/* global variables *********************************************************/
+static const char *BootString = BOOT_STRING;
+struct SK_NET_DEVICE *SkGeRootDev = NULL;
+static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
+
+/* local variables **********************************************************/
+static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
+static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
+static int sk98lin_max_boards_found = 0;
+static int is_closed = 0;
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry	*pSkRootDir;
+#endif
+
+
+
+#ifdef ENABLE_FUTURE_ETH
+static struct ethtool_ops sk98lin_ethtool_ops = {
+	.get_sg			= ethtool_op_get_sg,
+	.get_link		= ethtool_op_get_link,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+/*	.get_perm_addr		= ethtool_op_get_perm_addr, */ 
+	.get_settings		= SkGeGetSettings,
+	.get_drvinfo		= SkGeGetDrvInfo,
+	.get_wol		= SkGeGetWolSettings,
+	.get_pauseparam		= SkGeGetPauseParam,
+	.get_coalesce		= SkGeGetCoalesce,
+	.get_rx_csum		= SkGeGetRxCsum,
+	.get_strings		= SkGeGetStrings,
+	.get_stats_count	= SkGeGetStatsLen,
+	.get_ethtool_stats	= SkGeGetEthStats,
+
+	.set_settings		= SkGeSetSettings,
+	.set_wol		= SkGeSetWolSettings,
+	.set_pauseparam		= SkGeSetPauseParam,
+	.set_coalesce		= SkGeSetCoalesce,
+	.set_sg			= SkGeSetSG,
+	.set_tx_csum		= SkGeSetTxCsum,
+	.set_rx_csum		= SkGeSetRxCsum,
+
+	.phys_id		= SkGePhysId,
+
+#ifdef NETIF_F_TSO
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= SkGeSetTSO,
+#endif
+
+/*	.get_regs_len	= */
+/*	.get_regs	= */
+/*	.get_msglevel	= */
+/*	.nway_reset	= */
+/*	.get_ringparam	= */
+/*	.set_msglevel	= */
+/*	.set_ringparam	= */
+};
+#endif
+
+MODULE_DEVICE_TABLE(pci, sk98lin_pci_tbl);
+
+static struct pci_driver sk98lin_driver = {
+	.name		= DRIVER_FILE_NAME,
+	.id_table	= sk98lin_pci_tbl,
+	.probe		= sk98lin_init_device,
+	.remove		= __devexit_p(sk98lin_remove_device),
+#ifdef CONFIG_PM
+	.suspend	= sk98lin_suspend,
+	.resume		= sk98lin_resume
+#endif
+};
+
+
+static struct net_device_ops sk98lin_netdev_ops = {
+	.ndo_open		= SkGeOpen,
+	.ndo_stop		= SkGeClose,
+	.ndo_set_multicast_list	= SkGeSetRxMode,
+	.ndo_set_mac_address	= SkGeSetMacAddr,
+	.ndo_change_mtu		= SkGeChangeMtu,
+	.ndo_do_ioctl		= SkGeIoctl,
+	.ndo_get_stats		= SkGeStats
+};
+
+/*****************************************************************************
+ *
+ * 	sk98lin_init_device - initialize the adapter
+ *
+ * Description:
+ *	This function initializes the adapter. Resources for
+ *	the adapter are allocated and the adapter is brought into Init 1
+ *	state.
+ *
+ * Returns:
+ *	0, if everything is ok
+ *	!=0, on error
+ */
+static int __devinit sk98lin_init_device(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+
+{
+	static SK_BOOL 		sk98lin_boot_string = SK_FALSE;
+	static SK_BOOL 		sk98lin_proc_entry = SK_FALSE;
+	static int		sk98lin_boards_found = 0;
+	SK_AC			*pAC;
+	DEV_NET			*pNet = NULL;
+	struct SK_NET_DEVICE *dev = NULL;
+	int			retval;
+#ifdef CONFIG_PROC_FS
+#endif
+	int			pci_using_dac;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		printk(KERN_ERR "Cannot enable PCI device, "
+			"aborting.\n");
+		return retval;
+	}
+
+	dev = NULL;
+	pNet = NULL;
+
+	/* INSERT * We have to find the power-management capabilities */
+	/* Find power-management capability. */
+
+	pci_using_dac = 0;		/* Set 32 bit DMA per default */
+	/* Configure DMA attributes. */
+	retval = pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL);
+	if (!retval) {
+		pci_using_dac = 1;
+	} else {
+		retval = pci_set_dma_mask(pdev, (u64) 0xffffffff);
+		if (retval) {
+			printk(KERN_ERR "No usable DMA configuration, "
+			       "aborting.\n");
+			return retval;
+		}
+	}
+
+
+	if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
+		printk(KERN_ERR "Unable to allocate etherdev "
+			"structure!\n");
+		return -ENODEV;
+	}
+
+	pNet = netdev_priv(dev);
+	pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
+	if (pNet->pAC == NULL){
+		free_netdev(dev);
+		printk(KERN_ERR "Unable to allocate adapter "
+			"structure!\n");
+		return -ENODEV;
+	}
+
+	/* Print message */
+	if (!sk98lin_boot_string) {
+		/* set display flag to TRUE so that */
+		/* we only display this string ONCE */
+		sk98lin_boot_string = SK_TRUE;
+		printk("%s\n", BootString);
+	}
+
+	memset(pNet->pAC, 0, sizeof(SK_AC));
+	pAC = pNet->pAC;
+	pAC->PciDev = pdev;
+	pAC->PciDevId = pdev->device;
+	pAC->dev[0] = dev;
+	pAC->dev[1] = dev;
+	sprintf(pAC->Name, "SysKonnect SK-98xx");
+	pAC->CheckQueue = SK_FALSE;
+	pAC->InterfaceUp[0] = 0;
+	pAC->InterfaceUp[1] = 0;
+	dev->irq = pdev->irq;
+	retval = SkGeInitPCI(pAC);
+	if (retval) {
+		printk("SKGE: PCI setup failed: %i\n", retval);
+		free_netdev(dev);
+		return -ENODEV;
+	}
+
+//	SET_MODULE_OWNER(dev);
+#ifdef ENABLE_FUTURE_ETH
+	SET_ETHTOOL_OPS(dev, &sk98lin_ethtool_ops);
+#endif
+
+	dev->netdev_ops		= &sk98lin_netdev_ops;
+	dev->flags		&= ~IFF_RUNNING;
+#ifdef SK_POLL_CONTROLLER
+	dev->poll_controller	=  SkGeNetPoll;
+#endif
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	pAC->Index = sk98lin_boards_found;
+
+	if (SkGeBoardInit(dev, pAC)) {
+		free_netdev(dev);
+		return -ENODEV;
+	} else {
+		ProductStr(pAC);
+	}
+
+	if (pci_using_dac)
+		dev->features |= NETIF_F_HIGHDMA;
+
+	/* shifter to later moment in time... */
+	if (CHIP_ID_YUKON_2(pAC)) {
+		sk98lin_netdev_ops.ndo_start_xmit = SkY2Xmit;
+#ifdef CONFIG_SK98LIN_NAPI
+		dev->poll =  &SkY2Poll;
+		dev->weight = 64;
+#endif
+	} else {
+		sk98lin_netdev_ops.ndo_start_xmit = SkGeXmit;
+#ifdef CONFIG_SK98LIN_NAPI
+		dev->poll =  &SkGePoll;
+		dev->weight = 64;
+#endif
+	}
+
+#ifdef NETIF_F_TSO
+#ifdef USE_SK_TSO_FEATURE
+	if (CHIP_ID_YUKON_2(pAC)) {
+		dev->features |= NETIF_F_TSO;
+	}
+#endif
+#endif
+#ifdef CONFIG_SK98LIN_ZEROCOPY
+	if (pAC->GIni.GIChipId != CHIP_ID_GENESIS)
+		dev->features |= NETIF_F_SG;
+#endif
+#ifdef USE_SK_TX_CHECKSUM
+	if (pAC->GIni.GIChipId != CHIP_ID_GENESIS)
+		dev->features |= NETIF_F_IP_CSUM;
+#endif
+#ifdef USE_SK_RX_CHECKSUM
+	pAC->RxPort[0].UseRxCsum = SK_TRUE;
+	if (pAC->GIni.GIMacsFound == 2 ) {
+		pAC->RxPort[1].UseRxCsum = SK_TRUE;
+	}
+#endif
+
+	/* Save the hardware revision */
+	pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+		(pAC->GIni.GIPciHwRev & 0x0F);
+
+	/* Set driver globals */
+	pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
+	pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
+
+	SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
+	SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
+			sizeof(SK_PNMI_STRUCT_DATA));
+
+	/* Register net device */
+	retval = register_netdev(dev);
+	if (retval) {
+		printk(KERN_ERR "SKGE: Could not register device.\n");
+		FreeResources(dev);
+		free_netdev(dev);
+		return retval;
+	}
+
+	/* Save initial device name */
+	strcpy(pNet->InitialDevName, dev->name);
+
+	/* Set network to off */
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	/* Print adapter specific string from vpd and config settings */
+	printk("%s: %s\n", pNet->InitialDevName, pAC->DeviceStr);
+	printk("      PrefPort:%c  RlmtMode:%s\n",
+		'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
+		(pAC->RlmtMode==0)  ? "Check Link State" :
+		((pAC->RlmtMode==1) ? "Check Link State" :
+		((pAC->RlmtMode==3) ? "Check Local Port" :
+		((pAC->RlmtMode==7) ? "Check Segmentation" :
+		((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
+
+	SkGeYellowLED(pAC, pAC->IoBase, 1);
+	memcpy((caddr_t) dev->dev_addr,
+		(caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
+
+	/* First adapter... Create proc and print message */
+#ifdef CONFIG_PROC_FS
+	if (!sk98lin_proc_entry) {
+		sk98lin_proc_entry = SK_TRUE;
+		SK_MEMCPY(&SK_Root_Dir_entry, BootString,
+			sizeof(SK_Root_Dir_entry) - 1);
+
+		/*Create proc (directory)*/
+		if(!pSkRootDir) {
+			pSkRootDir = proc_mkdir(SK_Root_Dir_entry, init_net.proc_net);
+			if (!pSkRootDir) {
+				printk(KERN_WARNING "%s: Unable to create /proc/net/%s",
+					dev->name, SK_Root_Dir_entry);
+			}
+/*
+			else {
+				pSkRootDir->owner = THIS_MODULE;
+			}
+*/
+		}
+	}
+
+	/* Create proc file */
+	/* No further proc file creation here */
+
+#endif
+
+	pNet->PortNr = 0;
+	pNet->NetNr  = 0;
+
+	sk98lin_boards_found++;
+	pci_set_drvdata(pdev, dev);
+
+	/* More then one port found */
+	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+		dev = alloc_etherdev(sizeof(DEV_NET));
+		if (!dev) {
+			printk(KERN_ERR "Unable to allocate etherdev "
+				"structure!\n");
+			return -ENODEV;
+		}
+
+		pAC->dev[1]   = dev;
+		pNet          = netdev_priv(dev);
+		pNet->PortNr  = 1;
+		pNet->NetNr   = 1;
+		pNet->pAC     = pAC;
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+			sk98lin_netdev_ops.ndo_start_xmit = SkY2Xmit;
+#ifdef CONFIG_SK98LIN_NAPI
+			dev->poll =  &SkY2Poll;
+			dev->weight = 64;
+#endif
+		} else {
+			sk98lin_netdev_ops.ndo_start_xmit = SkGeXmit;
+#ifdef CONFIG_SK98LIN_NAPI
+			dev->poll =  &SkGePoll;
+			dev->weight = 64;
+#endif
+		}
+
+#ifdef ENABLE_FUTURE_ETH
+		SET_ETHTOOL_OPS(dev, &sk98lin_ethtool_ops);
+#endif
+		sk98lin_netdev_ops.ndo_open = SkGeOpen;
+		sk98lin_netdev_ops.ndo_stop = SkGeClose;
+		sk98lin_netdev_ops.ndo_get_stats = SkGeStats;
+		sk98lin_netdev_ops.ndo_set_multicast_list = SkGeSetRxMode;
+		sk98lin_netdev_ops.ndo_set_mac_address = SkGeSetMacAddr;
+		sk98lin_netdev_ops.ndo_do_ioctl = SkGeIoctl;
+		sk98lin_netdev_ops.ndo_change_mtu = SkGeChangeMtu;
+		dev->flags             &= ~IFF_RUNNING;
+#ifdef SK_POLL_CONTROLLER
+		dev->poll_controller	= SkGeNetPoll;
+#endif
+
+#ifdef NETIF_F_TSO
+#ifdef USE_SK_TSO_FEATURE
+		if (CHIP_ID_YUKON_2(pAC)) {
+			dev->features |= NETIF_F_TSO;
+		}
+#endif
+#endif
+#ifdef CONFIG_SK98LIN_ZEROCOPY
+		/* Don't handle if Genesis chipset */
+		if (pAC->GIni.GIChipId != CHIP_ID_GENESIS)
+			dev->features |= NETIF_F_SG;
+#endif
+#ifdef USE_SK_TX_CHECKSUM
+		/* Don't handle if Genesis chipset */
+		if (pAC->GIni.GIChipId != CHIP_ID_GENESIS)
+			dev->features |= NETIF_F_IP_CSUM;
+#endif
+
+		if (register_netdev(dev)) {
+			printk(KERN_ERR "SKGE: Could not register device.\n");
+			free_netdev(dev);
+			pAC->dev[1] = pAC->dev[0];
+		} else {
+
+		/* Save initial device name */
+		strcpy(pNet->InitialDevName, dev->name);
+
+		/* Set network to off */
+		netif_stop_queue(dev);
+		netif_carrier_off(dev);
+
+
+#ifdef CONFIG_PROC_FS
+	/* No further proc file creation here */
+#endif
+
+		memcpy((caddr_t) &dev->dev_addr,
+		(caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
+	
+		printk("%s: %s\n", pNet->InitialDevName, pAC->DeviceStr);
+		printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
+		}
+	}
+
+	pAC->Index = sk98lin_boards_found;
+	sk98lin_max_boards_found = sk98lin_boards_found;
+	return 0;
+}
+
+
+
+/*****************************************************************************
+ *
+ * 	SkGeInitPCI - Init the PCI resources
+ *
+ * Description:
+ *	This function initialize the PCI resources and IO
+ *
+ * Returns: N/A
+ *	
+ */
+static int SkGeInitPCI(SK_AC *pAC)
+{
+	struct SK_NET_DEVICE *dev = pAC->dev[0];
+	struct pci_dev *pdev = pAC->PciDev;
+	int retval;
+
+	if (pci_enable_device(pdev) != 0) {
+		return 1;
+	}
+
+	dev->mem_start = pci_resource_start (pdev, 0);
+	pci_set_master(pdev);
+
+	if (pci_request_regions(pdev, DRIVER_FILE_NAME) != 0) {
+		retval = 2;
+		goto out_disable;
+	}
+
+#ifdef SK_BIG_ENDIAN
+	/*
+	 * On big endian machines, we use the adapter's aibility of
+	 * reading the descriptors as big endian.
+	 */
+	{
+		SK_U32		our2;
+		SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
+		our2 |= PCI_REV_DESC;
+		SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
+	}
+#endif
+
+	/*
+	 * Remap the regs into kernel space.
+	 */
+	pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
+
+	if (!pAC->IoBase){
+		retval = 3;
+		goto out_release;
+	}
+
+	return 0;
+
+ out_release:
+	pci_release_regions(pdev);
+ out_disable:
+	pci_disable_device(pdev);
+	return retval;
+}
+
+#ifdef CONFIG_PROC_FS
+/*****************************************************************************
+ *
+ * 	SkGeHandleProcfsTimer - Handle the procfs timer requests
+ *
+ * Description:
+ *      Checks, if the device's name changed. If this is the case 
+ *      it deletes the old profs entry and creates a new one with 
+ *      the new name.
+ *
+ * Returns:	N/A
+ *
+ */
+static void SkGeHandleProcfsTimer(unsigned long ptr)
+{
+	DEV_NET         *pNet = (DEV_NET*) ptr;
+	struct proc_dir_entry *pProcFile;
+
+	/*
+	 * If the current name and the last saved name of the device differ
+	 * we need to update our procfs entry.
+	 */
+	if ( (pSkRootDir) && 
+	     (strcmp(pNet->CurrentName, pNet->pAC->dev[pNet->NetNr]->name) != 0) ) {
+
+	  if (pNet->pAC->InterfaceUp[pNet->NetNr] == 1)
+	    remove_proc_entry(pNet->CurrentName, pSkRootDir);
+
+	  /*
+	   * InterfaceUp only holds 1 if both the network interface is up and
+	   * the corresponding procfs entry is done. Otherwise it is set to 0.
+	   */
+	  pNet->pAC->InterfaceUp[pNet->NetNr] = 0;
+
+	  pProcFile = create_proc_entry(pNet->pAC->dev[pNet->NetNr]->name, S_IRUGO, pSkRootDir);
+	  pProcFile->proc_fops = &sk_proc_fops;
+	  pProcFile->data      = pNet->pAC->dev[pNet->NetNr];
+
+	  /*
+	   * Remember, interface dev nr pNet->NetNr is up and procfs entry is created.
+	   */
+	  pNet->pAC->InterfaceUp[pNet->NetNr] = 1;
+
+	  strcpy(pNet->CurrentName, pNet->pAC->dev[pNet->NetNr]->name);
+	}
+
+	/*
+	 * Restart Procfs Timer
+	 */
+	pNet->ProcfsTimer.expires	= jiffies + HZ*5; /* 5 secs */
+	add_timer(&pNet->ProcfsTimer);
+}
+#endif
+
+#ifdef Y2_RECOVERY
+/*****************************************************************************
+ *
+ * 	SkGeHandleKernelTimer - Handle the kernel timer requests
+ *
+ * Description:
+ *	If the requested time interval for the timer has elapsed, 
+ *	this function checks the link state.
+ *
+ * Returns:	N/A
+ *
+ */
+static void SkGeHandleKernelTimer(
+unsigned long ptr)  /* holds the pointer to adapter control context */
+{
+	DEV_NET         *pNet = (DEV_NET*) ptr;
+	SkGeCheckTimer(pNet);	
+}
+
+/*****************************************************************************
+ *
+ * 	sk98lin_check_timer - Resume the the card
+ *
+ * Description:
+ *	This function checks the kernel timer
+ *
+ * Returns: N/A
+ *	
+ */
+void SkGeCheckTimer(
+DEV_NET *pNet)  /* holds the pointer to adapter control context */
+{
+	SK_AC           *pAC = pNet->pAC;
+	SK_BOOL		StartTimer = SK_TRUE;
+	SK_U32          StatSpeed, StatDuplex, NewTimerInterval;
+
+#ifdef SK_EXTREME
+	if (HW_IS_EXT_LE_FORMAT(pAC)) {
+	/* Disable checks for Yukon Extreme */
+		return;
+	}
+#endif
+
+	StatSpeed = pAC->GIni.GP[pNet->NetNr].PLinkSpeedUsed;
+	if (StatSpeed == SK_LSPEED_STAT_10MBPS) {
+		StatDuplex = pAC->GIni.GP[pNet->NetNr].PLinkModeStatus;
+		if ((StatDuplex == SK_LMODE_STAT_AUTOHALF) ||
+			(StatDuplex == SK_LMODE_STAT_HALF)) {
+				NewTimerInterval = (HZ*2);
+		} else {
+			NewTimerInterval = (HZ);
+		}
+	} else if (StatSpeed == SK_LSPEED_STAT_100MBPS) {
+		NewTimerInterval = (HZ/2);
+	} else if (StatSpeed == SK_LSPEED_STAT_1000MBPS) {
+		NewTimerInterval = (HZ/4);
+	} else {
+		NewTimerInterval = (HZ*2);
+	}
+
+	if (pNet->InRecover) {
+	        pNet->KernelTimer.expires = jiffies + NewTimerInterval;
+		add_timer(&pNet->KernelTimer);
+
+		return;
+	}
+	if (pNet->TimerExpired)
+		return;
+	pNet->TimerExpired = SK_TRUE;
+
+#define TXPORT pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]
+#define RXPORT pAC->RxPort[pNet->PortNr]
+
+	if (	(CHIP_ID_YUKON_2(pAC)) &&
+		(netif_running(pAC->dev[pNet->PortNr]))) {
+		
+#ifdef Y2_RX_CHECK
+		if (HW_FEATURE(pAC, HWF_WA_DEV_4167)) {
+		/* Checks the RX path */
+			CheckRxPath(pNet);
+		}
+#endif
+
+		/* Check the transmitter */
+		if (!(IS_Q_EMPTY(&TXPORT.TxAQ_working))) {
+			if (TXPORT.LastDone != TXPORT.TxALET.Done) {
+				TXPORT.LastDone = TXPORT.TxALET.Done;
+				pNet->TransmitTimeoutTimer = 0;
+			} else {
+				pNet->TransmitTimeoutTimer++;
+				if (pNet->TransmitTimeoutTimer >= 10) {
+					pNet->TransmitTimeoutTimer = 0;
+#ifdef CHECK_TRANSMIT_TIMEOUT
+					StartTimer =  SK_FALSE;
+					SkLocalEventQueue(pAC, SKGE_DRV, 
+						SK_DRV_RECOVER,pNet->PortNr,-1,SK_FALSE);
+#endif
+				}
+			} 
+		} 
+
+#ifdef CHECK_TRANSMIT_TIMEOUT
+//		if (!timer_pending(&pNet->KernelTimer)) {
+			pNet->KernelTimer.expires = jiffies + NewTimerInterval;
+			add_timer(&pNet->KernelTimer);
+			pNet->TimerExpired = SK_FALSE;
+//		}
+#endif
+	}
+}
+
+
+/*****************************************************************************
+*
+* CheckRXCounters - Checks the the statistics for RX path hang
+*
+* Description:
+*	This function is called periodical by a timer. 
+*
+* Notes:
+*
+* Function Parameters:
+*
+* Returns:
+*	Traffic status
+*
+*/
+static SK_BOOL CheckRXCounters(
+DEV_NET *pNet)  /* holds the pointer to adapter control context */
+{
+	SK_AC           	*pAC = pNet->pAC;
+	SK_BOOL bStatus 	= SK_FALSE;
+
+	/* Variable used to store the MAC RX FIFO RP, RPLev*/
+	SK_U32			MACFifoRP = 0;
+	SK_U32			MACFifoRLev = 0;
+
+	/* Variable used to store the PCI RX FIFO RP, RPLev*/
+	SK_U32			RXFifoRP = 0;
+	SK_U8			RXFifoRLev = 0;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> CheckRXCounters()\n"));
+
+	/*Check if statistic counters hangs*/
+	if (pNet->LastJiffies == pAC->dev[pNet->PortNr]->last_rx) {
+		/* Now read the values of read pointer/level from MAC RX FIFO again */
+		SK_IN32(pAC->IoBase, MR_ADDR(pNet->PortNr, RX_GMF_RP), &MACFifoRP);
+		SK_IN32(pAC->IoBase, MR_ADDR(pNet->PortNr, RX_GMF_RLEV), &MACFifoRLev);
+
+		/* Now read the values of read pointer/level from RX FIFO again */
+		SK_IN8(pAC->IoBase, Q_ADDR(pAC->GIni.GP[pNet->PortNr].PRxQOff, Q_RX_RP), &RXFifoRP);
+		SK_IN8(pAC->IoBase, Q_ADDR(pAC->GIni.GP[pNet->PortNr].PRxQOff, Q_RX_RL), &RXFifoRLev);
+
+		/* Check if the MAC RX hang */
+		if ((MACFifoRP == pNet->PreviousMACFifoRP) &&
+			(MACFifoRLev != 0) &&
+			(MACFifoRLev >= pNet->PreviousMACFifoRLev)){
+			bStatus = SK_TRUE;
+		}
+
+		/* Check if the PCI RX hang */
+		if ((RXFifoRP == pNet->PreviousRXFifoRP) &&
+			(RXFifoRLev != 0) &&
+			(RXFifoRLev >= pNet->PreviousRXFifoRLev)){
+			/*Set the flag to indicate that the RX FIFO hangs*/
+			bStatus = SK_TRUE;
+		}
+	}
+
+	/* Store now the values of counters for next check */
+	pNet->LastJiffies = pAC->dev[pNet->PortNr]->last_rx;
+
+	/* Store the values of  read pointer/level from MAC RX FIFO for next test */
+	pNet->PreviousMACFifoRP = MACFifoRP;
+	pNet->PreviousMACFifoRLev = MACFifoRLev;
+
+	/* Store the values of  read pointer/level from RX FIFO for next test */
+	pNet->PreviousRXFifoRP = RXFifoRP;
+	pNet->PreviousRXFifoRLev = RXFifoRLev;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== CheckRXCounters()\n"));
+
+	return bStatus;
+}
+
+/*****************************************************************************
+*
+* CheckRxPath - Checks if the RX path
+*
+* Description:
+*	This function is called periodical by a timer. 
+*
+* Notes:
+*
+* Function Parameters:
+*
+* Returns:
+*	None.
+*
+*/
+static void  CheckRxPath(
+DEV_NET *pNet)  /* holds the pointer to adapter control context */
+{
+	unsigned long		Flags;    /* for the spin locks    */
+	/* Initialize the pAC structure.*/
+	SK_AC           	*pAC = pNet->pAC;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> CheckRxPath()\n"));
+
+	/*If the statistics are not changed then could be an RX problem */
+	if (CheckRXCounters(pNet)){
+		/* 
+		 * First we try the simple solution by resetting the Level Timer
+		 */
+
+		/* Stop Level Timer of Status BMU */
+		SK_OUT8(pAC->IoBase, STAT_LEV_TIMER_CTRL, TIM_STOP);
+
+		/* Start Level Timer of Status BMU */
+		SK_OUT8(pAC->IoBase, STAT_LEV_TIMER_CTRL, TIM_START);
+
+		if (!CheckRXCounters(pNet)) {
+			return;
+		}
+
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+		SkLocalEventQueue(pAC, SKGE_DRV,
+			SK_DRV_RECOVER,pNet->PortNr,-1,SK_TRUE);
+
+		/* Reset the fifo counters */
+		pNet->PreviousMACFifoRP = 0;
+		pNet->PreviousMACFifoRLev = 0;
+		pNet->PreviousRXFifoRP = 0;
+		pNet->PreviousRXFifoRLev = 0;
+
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== CheckRxPath()\n"));
+}
+
+
+
+#endif
+
+
+#ifdef CONFIG_PM
+/*****************************************************************************
+ *
+ * 	sk98lin_resume - Resume the the card
+ *
+ * Description:
+ *	This function resumes the card into the D0 state
+ *
+ * Returns: N/A
+ *	
+ */
+static int sk98lin_resume(
+struct pci_dev *pdev)   /* the device that is to resume */
+{
+	struct net_device   *dev  = pci_get_drvdata(pdev);
+	DEV_NET		    *pNet = (DEV_NET*)netdev_priv(dev);
+	SK_AC		    *pAC  = pNet->pAC;
+	SK_U16		     PmCtlSts;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+	int                  rCode;
+#endif
+#ifdef USE_ASF_DASH_FW
+	SK_U32               TmpVal32;
+#endif
+
+	if (pAC->GIni.GIChipId != CHIP_ID_YUKON_EX) {
+
+		/* Set the power state to D0 */
+		pci_set_power_state(pdev, 0);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
+		pci_restore_state(pdev);
+#else
+		pci_restore_state(pdev, pAC->PciState);
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+		rCode = pci_enable_device(pdev);
+		if (rCode)
+			return rCode;
+#else       
+		pci_enable_device(pdev);
+#endif
+		pci_set_master(pdev);
+
+		pci_enable_wake(pdev, 3, 0);
+		pci_enable_wake(pdev, 4, 0);
+	}
+
+	/* Set the adapter power state to D0 */
+	SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts);
+	PmCtlSts &= ~(PCI_PM_STATE_D3);	/* reset all DState bits */
+	PmCtlSts |= PCI_PM_STATE_D0;
+	SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PmCtlSts);
+
+#ifdef USE_ASF_DASH_FW
+	pAC->ReturningFromSuspend = 1;
+#endif
+
+	/* Reinit the adapter and start the port again */
+	pAC->BoardLevel = SK_INIT_DATA;
+	SkDrvLeaveDiagMode(pAC);
+
+#ifdef USE_ASF_DASH_FW
+	SK_IN32(pAC->IoBase, 0xE7C, &TmpVal32);
+	printk("sk98lin: resume complete (reason: %u)\n", TmpVal32);
+#endif
+
+	return 0;
+
+}
+ 
+/*****************************************************************************
+ *
+ * 	sk98lin_suspend - Suspend the card
+ *
+ * Description:
+ *	This function suspends the card into a defined state
+ *
+ * Returns: N/A
+ *	
+ */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
+static int sk98lin_suspend(
+struct pci_dev	*pdev,   /* pointer to the device that is to suspend */
+pm_message_t	state)  /* what power state is desired by Linux?    */
+#else
+static int sk98lin_suspend(
+struct pci_dev	*pdev,   /* pointer to the device that is to suspend */
+SK_U32	state)  /* what power state is desired by Linux?    */
+#endif
+{
+	struct net_device   *dev  = pci_get_drvdata(pdev);
+	DEV_NET		    *pNet = (DEV_NET*)netdev_priv(dev);
+	SK_AC		    *pAC  = pNet->pAC;
+	SK_U16		     PciPMControlStatus;
+	SK_U16		     PciPMCapabilities;
+	SK_MAC_ADDR	     MacAddr;
+	int		     i;
+
+	/* GEnesis and first yukon revs do not support power management */
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+		if (pAC->GIni.GIChipRev == 0) {
+			return 0; /* power management not supported */
+		}
+	} 
+
+	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+		return 0; /* not supported for this chipset */
+	}
+
+	if (pAC->WolInfo.ConfiguredWolOptions == 0) {
+		return 0; /* WOL possible, but disabled via ethtool */
+	}
+
+	if(netif_running(dev)) {
+		netif_stop_queue(dev); /* stop device if running */
+	}
+	
+	/* read the PM control/status register from the PCI config space */
+	SK_IN16(pAC->IoBase, PCI_C(pAC, PCI_PM_CTL_STS), &PciPMControlStatus);
+
+	/* read the power management capabilities from the config space */
+	SK_IN16(pAC->IoBase, PCI_C(pAC, PCI_PM_CAP_REG), &PciPMCapabilities);
+
+	/* Enable WakeUp with Magic Packet - get MAC address from adapter */
+	for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+		/* virtual address: will be used for data */
+		SK_IN8(pAC->IoBase, (B2_MAC_1 + i), &MacAddr.a[i]);
+	}
+
+	SkDrvEnterDiagMode(pAC);
+	SkEnableWOMagicPacket(pAC, pAC->IoBase, MacAddr);
+
+	if (pAC->GIni.GIChipId != CHIP_ID_YUKON_EX) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
+		pci_save_state(pdev);
+#else
+		pci_save_state(pdev, pAC->PciState);
+#endif
+		// Eventually we need to evaluate the return values
+		pci_enable_wake(pdev, 3, 1);	/* D3 hot */
+		pci_enable_wake(pdev, 4, 1);	/* D3 cold */
+
+		pci_disable_device(pdev);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
+		pci_set_power_state(pdev, pci_choose_state(pdev, state)); /* set the state */
+#else
+		pci_set_power_state(pdev, state); /* set the state */
+#endif
+	}
+
+#ifdef USE_ASF_DASH_FW
+	SkAsfSuspend(pAC, pAC->IoBase);
+	printk("sk98lin: suspend complete\n");
+#endif
+
+	return 0;
+}
+
+
+/******************************************************************************
+ *
+ *	SkEnableWOMagicPacket - Enable Wake on Magic Packet on the adapter
+ *
+ * Context:
+ *	init, pageable
+ *	the adapter should be de-initialized before calling this function
+ *
+ * Returns:
+ *	nothing
+ */
+
+static void SkEnableWOMagicPacket(
+SK_AC         *pAC,      /* Adapter Control Context          */
+SK_IOC         IoC,      /* I/O control context              */
+SK_MAC_ADDR    MacAddr)  /* MacAddr expected in magic packet */
+{
+	SK_U16	Word;
+	SK_U32	DWord;
+	int 	i;
+	int	HwPortIndex;
+	int	Port = 0;
+
+	/* use Port 0 as long as we do not have any dual port cards which support WOL */
+	HwPortIndex = 0;
+	DWord = 0;
+
+	SK_OUT16(IoC, B0_CTST, 0x0002);				/* clear S/W Reset */
+	SK_OUT16(IoC, GMAC_LINK_CTRL, 0x0002);			/* clear Link Reset */
+
+	/*
+	 * PHY Configuration:
+	 * Autonegotioation is enabled, advertise 10 HD, 10 FD,
+	 * 100 HD, and 100 FD.
+	 */
+	if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) ||
+		(pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
+		(pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) || 
+		(CHIP_ID_YUKON_2(pAC)) ) {
+
+	        SK_OUT32(pAC->IoBase, 0x1c84, 0x7000);
+	        SK_OUT32(pAC->IoBase, 0x1c88, 0x0);
+		SK_OUT8(IoC, B0_POWER_CTRL, 0xa9);		/* enable VAUX */
+
+		/* WA code for COMA mode */
+		/* Only for yukon plus based chipsets rev A3 */
+		if  ( (pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) &&
+		      (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) ) {
+			SK_IN32(IoC, B2_GP_IO, &DWord);
+			DWord |= GP_DIR_9;			/* set to output */
+			DWord &= ~GP_IO_9;			/* clear PHY reset (active high) */
+			SK_OUT32(IoC, B2_GP_IO, DWord);		/* clear PHY reset */
+		}
+
+		if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) ||
+			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+			SK_OUT32(IoC, GPHY_CTRL, 0x01f04001);	/* set PHY reset */
+			SK_OUT32(IoC, GPHY_CTRL, 0x01f04002);	/* clear PHY reset */
+		} else {
+			SK_OUT8(IoC, GPHY_CTRL, 0x02);		/* clear PHY reset */
+		}
+
+		SK_OUT8(IoC, GMAC_CTRL, 0x02);			/* clear MAC reset */
+		SkGmPhyWrite(pAC, IoC, Port, 4, 0x01e1);	/* advertise 10/100 HD/FD */
+		SkGmPhyWrite(pAC, IoC, Port, 9, 0x0000);	/* do not advertise 1000 HD/FD */
+		SkGmPhyWrite(pAC, IoC, Port, 00, 0xB300);	/* 100 MBit, disable Autoneg */
+	} else if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) ||
+			   (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P)) {
+		SK_OUT8(IoC, B0_POWER_CTRL, 0xa9);		/* enable VAUX */
+		SK_OUT8(IoC, GPHY_CTRL, 0x02);			/* clear PHY reset */
+		SK_OUT8(IoC, GMAC_CTRL, 0x02);			/* clear MAC reset */
+		SkGmPhyWrite(pAC, IoC, Port, 16, 0x0130);	/* Enable Automatic Crossover */
+		SkGmPhyWrite(pAC, IoC, Port, 00, 0xB300);	/* 100 MBit, disable Autoneg */
+	}
+
+
+	/*
+	 * MAC Configuration:
+	 * Set the MAC to 100 HD and enable the auto update features
+	 * for Speed, Flow Control and Duplex Mode.
+	 * If autonegotiation completes successfully the
+	 * MAC takes the link parameters from the PHY.
+	 * If the link partner doesn't support autonegotiation
+	 * the MAC can receive magic packets if the link partner
+	 * uses 100 HD.
+	 */
+	SK_OUT16(IoC, 0x2804, 0x3832);
+
+
+	/*
+	 * Set Up Magic Packet parameters
+	 */
+#ifndef USE_ASF_DASH_FW
+	for (i = 0; i < 6; i+=2) {				/* set up magic packet MAC address */
+		SK_IN16(IoC, B2_MAC_1 + i, &Word);
+		SK_OUT16(IoC, WOL_MAC_ADDR_LO + i, Word);
+	}
+#endif
+#ifdef USE_ASF_DASH_FW
+	for (i = 0; i < 6; i+=2) {				/* set up magic packet MAC address */
+		SK_OUT16(IoC, WOL_MAC_ADDR_LO + i, 0x0);
+	}
+#endif
+
+	SK_OUT16(IoC, WOL_CTRL_STAT, 0x0208);			/* enable PME on magic packet */
+
+	/*
+	 * Set up PME generation
+	 */
+	/* set PME legacy mode */
+	/* Only for PCI express based chipsets */
+	if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) ||
+		(pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) || 
+		(CHIP_ID_YUKON_2(pAC))) {
+		if (pAC->GIni.GIChipId != CHIP_ID_YUKON_EX) {
+	  		SkPciReadCfgDWord(pAC, PCI_OUR_REG_1, &DWord);
+	  		DWord |= 0x8000;
+	  		SkPciWriteCfgDWord(pAC, PCI_OUR_REG_1, DWord);
+		}
+	}
+
+
+#ifndef USE_ASF_DASH_FW
+	SK_OUT8(IoC, RX_GMF_CTRL_T, (SK_U8)GMF_RST_SET);
+#endif
+
+	SK_OUT16(IoC, B0_CTST, Y2_HW_WOL_OFF);
+
+	/* clear PME status and switch adapter to DState 3 */
+	SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &Word);
+	Word |= 0x103;
+	SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, Word);
+
+}	/* SkEnableWOMagicPacket */
+#endif
+
+
+/*****************************************************************************
+ *
+ * 	FreeResources - release resources allocated for adapter
+ *
+ * Description:
+ *	This function releases the IRQ, unmaps the IO and
+ *	frees the desriptor ring.
+ *
+ * Returns: N/A
+ *	
+ */
+static void FreeResources(struct SK_NET_DEVICE *dev)
+{
+SK_U32 AllocFlag;
+DEV_NET		*pNet;
+SK_AC		*pAC;
+
+	if (netdev_priv(dev)) {
+		pNet = (DEV_NET*)netdev_priv(dev);
+		pAC = pNet->pAC;
+		AllocFlag = pAC->AllocFlag;
+		if (pAC->PciDev) {
+			pci_release_regions(pAC->PciDev);
+		}
+		if (AllocFlag & SK_ALLOC_IRQ) {
+			free_irq(dev->irq, dev);
+		}
+		if (pAC->IoBase) {
+			iounmap(pAC->IoBase);
+		}
+		if (CHIP_ID_YUKON_2(pAC)) {
+			SkY2FreeResources(pAC);
+		} else {
+			BoardFreeMem(pAC);
+		}
+	}
+	
+} /* FreeResources */
+
+MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
+MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(DRV_VERSION);
+
+#ifdef LINK_SPEED_A
+static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
+#else
+static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef LINK_SPEED_B
+static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
+#else
+static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef AUTO_NEG_A
+static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
+#else
+static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef DUP_CAP_A
+static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;
+#else
+static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef FLOW_CTRL_A
+static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;
+#else
+static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef ROLE_A
+static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;
+#else
+static char *Role_A[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef AUTO_NEG_B
+static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;
+#else
+static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef DUP_CAP_B
+static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;
+#else
+static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef FLOW_CTRL_B
+static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;
+#else
+static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef ROLE_B
+static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
+#else
+static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef CON_TYPE
+static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
+#else
+static char *ConType[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef PREF_PORT
+static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
+#else
+static char *PrefPort[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef RLMT_MODE
+static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
+#else
+static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+static int   IntsPerSec[SK_MAX_CARD_PARAM];
+static char *Moderation[SK_MAX_CARD_PARAM];
+static char *ModerationMask[SK_MAX_CARD_PARAM];
+
+static int   TxModeration[SK_MAX_CARD_PARAM];
+static char *LowLatency[SK_MAX_CARD_PARAM];
+static char *BroadcastPrio[SK_MAX_CARD_PARAM];
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
+module_param_array(Speed_A, charp, NULL, 0);
+module_param_array(Speed_B, charp, NULL, 0);
+module_param_array(AutoNeg_A, charp, NULL, 0);
+module_param_array(AutoNeg_B, charp, NULL, 0);
+module_param_array(DupCap_A, charp, NULL, 0);
+module_param_array(DupCap_B, charp, NULL, 0);
+module_param_array(FlowCtrl_A, charp, NULL, 0);
+module_param_array(FlowCtrl_B, charp, NULL, 0);
+module_param_array(Role_A, charp, NULL, 0);
+module_param_array(Role_B, charp, NULL, 0);
+module_param_array(ConType, charp, NULL, 0);
+module_param_array(PrefPort, charp, NULL, 0);
+module_param_array(RlmtMode, charp, NULL, 0);
+/* used for interrupt moderation */
+module_param_array(IntsPerSec, int, NULL, 0);
+module_param_array(Moderation, charp, NULL, 0);
+module_param_array(ModerationMask, charp, NULL, 0);
+module_param_array(LowLatency, charp, NULL, 0);
+module_param_array(TxModeration, int, NULL, 0);
+module_param_array(BroadcastPrio, charp, NULL, 0);
+#else
+MODULE_PARM(Speed_A,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(Speed_B,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(AutoNeg_A,  "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(AutoNeg_B,  "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(DupCap_A,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(DupCap_B,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(Role_A,	"1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(Role_B,	"1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(ConType,	"1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(PrefPort,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(RlmtMode,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(IntsPerSec,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
+MODULE_PARM(Moderation,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(ModerationMask, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(LowLatency, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(TxModeration, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(BroadcastPrio, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+#endif
+
+
+/*****************************************************************************
+ *
+ * 	sk98lin_remove_device - device deinit function
+ *
+ * Description:
+ *	Disable adapter if it is still running, free resources,
+ *	free device struct.
+ *
+ * Returns: N/A
+ */
+
+static void sk98lin_remove_device(struct pci_dev *pdev)
+{
+DEV_NET		*pNet;
+SK_AC		*pAC;
+struct SK_NET_DEVICE *next;
+unsigned long Flags;
+struct net_device *dev = pci_get_drvdata(pdev);
+
+
+	/* Device not available. Return. */
+	if (!dev)
+		return;
+
+	pNet = (DEV_NET*)netdev_priv(dev);
+	pAC = pNet->pAC;
+	next = pAC->Next;
+
+#ifndef SK_ASF
+	netif_stop_queue(dev);
+#endif
+
+	SkAddrMcUpdate(pAC,pAC->IoBase, 0); /* Mac update */
+	SkGeYellowLED(pAC, pAC->IoBase, 0);
+
+	if(pAC->BoardLevel == SK_INIT_RUN) {
+		/* board is still alive */
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+#ifndef SK_ASF
+		SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
+					0, -1, SK_FALSE);
+		SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
+					1, -1, SK_TRUE);
+#endif
+
+		/* disable interrupts */
+		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+		SkGeDeInit(pAC, pAC->IoBase);
+
+#ifdef SK_ASF
+		SkAsfDeInit(pAC, pAC->IoBase);
+#endif
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+		pAC->BoardLevel = SK_INIT_DATA;
+		/* We do NOT check here, if IRQ was pending, of course*/
+	}
+
+	if(pAC->BoardLevel == SK_INIT_IO) {
+		/* board is still alive */
+		SkGeDeInit(pAC, pAC->IoBase);
+#ifdef SK_ASF
+		SkAsfDeInit(pAC, pAC->IoBase);
+#endif
+		pAC->BoardLevel = SK_INIT_DATA;
+	}
+
+	if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
+		unregister_netdev(pAC->dev[1]);
+		free_netdev(pAC->dev[1]);
+	}
+
+	FreeResources(dev);
+
+#ifdef CONFIG_PROC_FS
+	/* Remove the sk98lin procfs device entries */
+	if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
+		if (pAC->InterfaceUp[1] == 1) {
+			remove_proc_entry(pAC->dev[1]->name, pSkRootDir);
+		}
+	}
+	if (pAC->InterfaceUp[0] == 1) {
+		remove_proc_entry(pAC->dev[0]->name, pSkRootDir);
+	}
+#endif
+	
+	sk98lin_netdev_ops.ndo_get_stats = NULL;
+	/*
+	 * otherwise unregister_netdev calls get_stats with
+	 * invalid IO ...  :-(
+	 */
+	unregister_netdev(dev);
+	free_netdev(dev);
+	kfree(pAC);
+	sk98lin_max_boards_found--;
+
+#ifdef CONFIG_PROC_FS
+	/* Remove all Proc entries if last device */
+	if (sk98lin_max_boards_found == 0) {
+		/* clear proc-dir */
+		remove_proc_entry(pSkRootDir->name, init_net.proc_net);
+	}
+#endif
+
+}
+
+
+/*****************************************************************************
+ *
+ * 	SkGeBoardInit - do level 0 and 1 initialization
+ *
+ * Description:
+ *	This function prepares the board hardware for running. The desriptor
+ *	ring is set up, the IRQ is allocated and the configuration settings
+ *	are examined.
+ *
+ * Returns:
+ *	0, if everything is ok
+ *	!=0, on error
+ */
+static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
+{
+short	i;
+char	*DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
+char	*VerStr	= VER_STRING;
+int	Ret;			/* return code of request_irq */
+SK_BOOL	DualNet;
+#ifndef SK_ASF	
+unsigned long   Flags;    	/* for the spin locks	*/
+#endif
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
+	for (i=0; i<SK_MAX_MACS; i++) {
+		pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0];
+		pAC->TxPort[i][0].PortIndex = i;
+		pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i];
+		pAC->RxPort[i].PortIndex = i;
+	}
+
+	/* Initialize the mutexes */
+	for (i=0; i<SK_MAX_MACS; i++) {
+		spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
+		spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
+	}
+
+	spin_lock_init(&pAC->InitLock);		/* Init lock */
+	spin_lock_init(&pAC->SlowPathLock);
+	spin_lock_init(&pAC->TxQueueLock);	/* for Yukon2 chipsets */
+	spin_lock_init(&pAC->SetPutIndexLock);	/* for Yukon2 chipsets */
+
+	/* level 0 init common modules here */
+
+#ifdef SK_ASF	
+	spin_lock(&pAC->SlowPathLock);
+#endif
+#ifndef SK_ASF
+	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+#endif
+	/* Does a RESET on board ...*/
+	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
+		printk("HWInit (0) failed.\n");
+#ifdef SK_ASF	
+		spin_unlock(&pAC->SlowPathLock);
+#endif
+#ifndef SK_ASF	
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+#endif
+		return(-EAGAIN);
+	}
+	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_DATA);
+	SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
+	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
+	SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
+	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
+	SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
+#ifdef SK_ASF
+	SkAsfInit(pAC, pAC->IoBase, SK_INIT_DATA);
+#endif
+
+
+	pAC->BoardLevel = SK_INIT_DATA;
+	pAC->RxPort[0].RxBufSize = ETH_BUF_SIZE;
+	pAC->RxPort[1].RxBufSize = ETH_BUF_SIZE;
+
+	SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
+	SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
+
+	/* level 1 init common modules here (HW init) */
+	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+		printk("sk98lin: HWInit (1) failed.\n");
+#ifdef SK_ASF	
+		spin_unlock(&pAC->SlowPathLock);
+#endif
+#ifndef SK_ASF	
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+#endif
+		return(-EAGAIN);
+	}
+	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
+	SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+	SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+	SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
+#ifdef SK_ASF
+	SkAsfInit(pAC, pAC->IoBase, SK_INIT_IO);
+#endif
+#ifdef Y2_RECOVERY
+	/* mark entries invalid */
+	pAC->LastPort = 3;
+	pAC->LastOpc = 0xFF;
+#endif
+
+	/* Set chipset type support */
+	if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
+		(pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) ||
+		(pAC->GIni.GIChipId == CHIP_ID_YUKON_LP)) {
+		pAC->ChipsetType = 1;	/* Yukon chipset (descriptor logic) */
+	} else if (CHIP_ID_YUKON_2(pAC)) {
+		pAC->ChipsetType = 2;	/* Yukon2 chipset (list logic) */
+	} else {
+		pAC->ChipsetType = 0;	/* Genesis chipset (descriptor logic) */
+	}
+
+	/* wake on lan support */
+	pAC->WolInfo.SupportedWolOptions = 0;
+#if defined (ETHTOOL_GWOL) && defined (ETHTOOL_SWOL)
+	if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
+		pAC->WolInfo.SupportedWolOptions  = WAKE_MAGIC;
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+			if (pAC->GIni.GIChipRev == 0) {
+				pAC->WolInfo.SupportedWolOptions = 0;
+			}
+		} 
+	}
+#endif
+	pAC->WolInfo.ConfiguredWolOptions = pAC->WolInfo.SupportedWolOptions;
+
+	GetConfiguration(pAC);
+	if (pAC->RlmtNets == 2) {
+		pAC->GIni.GP[0].PPortUsage = SK_MUL_LINK;
+		pAC->GIni.GP[1].PPortUsage = SK_MUL_LINK;
+	}
+
+	/* Set the tx moderation parameter */
+	if (pAC->TxModeration) {
+		pAC->GIni.GITxIdxRepThres = pAC->TxModeration;
+	}
+
+	pAC->BoardLevel = SK_INIT_IO;
+#ifdef SK_ASF	
+	spin_unlock(&pAC->SlowPathLock);
+#endif
+#ifndef SK_ASF	
+	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+#endif
+
+	if (!CHIP_ID_YUKON_2(pAC)) {
+		if (pAC->GIni.GIMacsFound == 2) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
+			Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, dev->name, dev);
+#else
+			Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, dev->name, dev);
+#endif
+		} else if (pAC->GIni.GIMacsFound == 1) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
+			Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, dev->name, dev);
+#else
+			Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, dev->name, dev);
+#endif
+		} else {
+			printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
+				pAC->GIni.GIMacsFound);
+			return -EAGAIN;
+		}
+	}
+	else {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
+		Ret = request_irq(dev->irq, SkY2Isr, IRQF_SHARED, dev->name, dev);
+#else
+		Ret = request_irq(dev->irq, SkY2Isr, SA_SHIRQ, dev->name, dev);
+#endif
+	}
+
+	if (Ret) {
+		printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
+			dev->irq);
+		return -EAGAIN;
+	}
+	pAC->AllocFlag |= SK_ALLOC_IRQ;
+
+	/* 
+	** Alloc descriptor/LETable memory for this board (both RxD/TxD)
+	*/
+	if (CHIP_ID_YUKON_2(pAC)) {
+		if (!SkY2AllocateResources(pAC)) {
+			printk("No memory for Yukon2 settings\n");
+			return(-EAGAIN);
+		}
+	} else {
+		if(!BoardAllocMem(pAC)) {
+			printk("No memory for descriptor rings.\n");
+			return(-EAGAIN);
+		}
+	}
+
+#ifdef SK_USE_CSUM
+	SkCsSetReceiveFlags(pAC,
+		SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP,
+		&pAC->CsOfs1, &pAC->CsOfs2, 0);
+	pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;
+#endif
+
+	/*
+	** Function BoardInitMem() for Yukon dependent settings...
+	*/
+	BoardInitMem(pAC);
+	/* tschilling: New common function with minimum size check. */
+	DualNet = SK_FALSE;
+	if (pAC->RlmtNets == 2) {
+		DualNet = SK_TRUE;
+	}
+
+	/*
+	 * Register the device here
+	 */
+	pAC->Next = SkGeRootDev;
+	SkGeRootDev = dev;
+
+	return (0);
+} /* SkGeBoardInit */
+
+
+/*****************************************************************************
+ *
+ * 	BoardAllocMem - allocate the memory for the descriptor rings
+ *
+ * Description:
+ *	This function allocates the memory for all descriptor rings.
+ *	Each ring is aligned for the desriptor alignment and no ring
+ *	has a 4 GByte boundary in it (because the upper 32 bit must
+ *	be constant for all descriptiors in one rings).
+ *
+ * Returns:
+ *	SK_TRUE, if all memory could be allocated
+ *	SK_FALSE, if not
+ */
+static SK_BOOL BoardAllocMem(
+SK_AC	*pAC)
+{
+caddr_t		pDescrMem;	/* pointer to descriptor memory area */
+size_t		AllocLength;	/* length of complete descriptor area */
+int		i;		/* loop counter */
+unsigned long	BusAddr;
+
+	
+	/* rings plus one for alignment (do not cross 4 GB boundary) */
+	/* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */
+#if (BITS_PER_LONG == 32)
+	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
+#else
+	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+		+ RX_RING_SIZE + 8;
+#endif
+
+	pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
+					 &pAC->pDescrMemDMA);
+
+	if (pDescrMem == NULL) {
+		return (SK_FALSE);
+	}
+	pAC->pDescrMem = pDescrMem;
+	BusAddr = (unsigned long) pAC->pDescrMemDMA;
+
+	/* Descriptors need 8 byte alignment, and this is ensured
+	 * by pci_alloc_consistent.
+	 */
+	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+			("TX%d/A: pDescrMem: %lX,   PhysDescrMem: %lX\n",
+			i, (unsigned long) pDescrMem,
+			BusAddr));
+		pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
+		pAC->TxPort[i][0].VTxDescrRing = BusAddr;
+		pDescrMem += TX_RING_SIZE;
+		BusAddr += TX_RING_SIZE;
+	
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+			("RX%d: pDescrMem: %lX,   PhysDescrMem: %lX\n",
+			i, (unsigned long) pDescrMem,
+			(unsigned long)BusAddr));
+		pAC->RxPort[i].pRxDescrRing = pDescrMem;
+		pAC->RxPort[i].VRxDescrRing = BusAddr;
+		pDescrMem += RX_RING_SIZE;
+		BusAddr += RX_RING_SIZE;
+	} /* for */
+	
+	return (SK_TRUE);
+} /* BoardAllocMem */
+
+
+/****************************************************************************
+ *
+ *	BoardFreeMem - reverse of BoardAllocMem
+ *
+ * Description:
+ *	Free all memory allocated in BoardAllocMem: adapter context,
+ *	descriptor rings, locks.
+ *
+ * Returns:	N/A
+ */
+static void BoardFreeMem(
+SK_AC		*pAC)
+{
+size_t		AllocLength;	/* length of complete descriptor area */
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("BoardFreeMem\n"));
+
+	if (pAC->pDescrMem) {
+
+#if (BITS_PER_LONG == 32)
+		AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
+#else
+		AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+			+ RX_RING_SIZE + 8;
+#endif
+
+		pci_free_consistent(pAC->PciDev, AllocLength,
+			    pAC->pDescrMem, pAC->pDescrMemDMA);
+		pAC->pDescrMem = NULL;
+	}
+} /* BoardFreeMem */
+
+
+/*****************************************************************************
+ *
+ * 	BoardInitMem - initiate the descriptor rings
+ *
+ * Description:
+ *	This function sets the descriptor rings or LETables up in memory.
+ *	The adapter is initialized with the descriptor start addresses.
+ *
+ * Returns:	N/A
+ */
+static void BoardInitMem(
+SK_AC	*pAC)	/* pointer to adapter context */
+{
+int	i;		/* loop counter */
+int	RxDescrSize;	/* the size of a rx descriptor rounded up to alignment*/
+int	TxDescrSize;	/* the size of a tx descriptor rounded up to alignment*/
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("BoardInitMem\n"));
+
+	if (!pAC->GIni.GIYukon2) {
+		RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
+		pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
+		TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
+		pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
+	
+		for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+			SetupRing(
+				pAC,
+				pAC->TxPort[i][0].pTxDescrRing,
+				pAC->TxPort[i][0].VTxDescrRing,
+				(RXD**)&pAC->TxPort[i][0].pTxdRingHead,
+				(RXD**)&pAC->TxPort[i][0].pTxdRingTail,
+				(RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
+				&pAC->TxPort[i][0].TxdRingFree,
+				&pAC->TxPort[i][0].TxdRingPrevFree,
+				SK_TRUE);
+			SetupRing(
+				pAC,
+				pAC->RxPort[i].pRxDescrRing,
+				pAC->RxPort[i].VRxDescrRing,
+				&pAC->RxPort[i].pRxdRingHead,
+				&pAC->RxPort[i].pRxdRingTail,
+				&pAC->RxPort[i].pRxdRingPrev,
+				&pAC->RxPort[i].RxdRingFree,
+				&pAC->RxPort[i].RxdRingFree,
+				SK_FALSE);
+		}
+	}
+} /* BoardInitMem */
+
+/*****************************************************************************
+ *
+ * 	SetupRing - create one descriptor ring
+ *
+ * Description:
+ *	This function creates one descriptor ring in the given memory area.
+ *	The head, tail and number of free descriptors in the ring are set.
+ *
+ * Returns:
+ *	none
+ */
+static void SetupRing(
+SK_AC		*pAC,
+void		*pMemArea,	/* a pointer to the memory area for the ring */
+uintptr_t	VMemArea,	/* the virtual bus address of the memory area */
+RXD		**ppRingHead,	/* address where the head should be written */
+RXD		**ppRingTail,	/* address where the tail should be written */
+RXD		**ppRingPrev,	/* address where the tail should be written */
+int		*pRingFree,	/* address where the # of free descr. goes */
+int		*pRingPrevFree,	/* address where the # of free descr. goes */
+SK_BOOL		IsTx)		/* flag: is this a tx ring */
+{
+int	i;		/* loop counter */
+int	DescrSize;	/* the size of a descriptor rounded up to alignment*/
+int	DescrNum;	/* number of descriptors per ring */
+RXD	*pDescr;	/* pointer to a descriptor (receive or transmit) */
+RXD	*pNextDescr;	/* pointer to the next descriptor */
+RXD	*pPrevDescr;	/* pointer to the previous descriptor */
+uintptr_t VNextDescr;	/* the virtual bus address of the next descriptor */
+
+	if (IsTx == SK_TRUE) {
+		DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
+			DESCR_ALIGN;
+		DescrNum = TX_RING_SIZE / DescrSize;
+	} else {
+		DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
+			DESCR_ALIGN;
+		DescrNum = RX_RING_SIZE / DescrSize;
+	}
+	
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("Descriptor size: %d   Descriptor Number: %d\n",
+		DescrSize,DescrNum));
+	
+	pDescr = (RXD*) pMemArea;
+	pPrevDescr = NULL;
+	pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
+	VNextDescr = VMemArea + DescrSize;
+	for(i=0; i<DescrNum; i++) {
+		/* set the pointers right */
+		pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
+		pDescr->pNextRxd = pNextDescr;
+		pDescr->TcpSumStarts = pAC->CsOfs;
+
+		/* advance one step */
+		pPrevDescr = pDescr;
+		pDescr = pNextDescr;
+		pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
+		VNextDescr += DescrSize;
+	}
+	pPrevDescr->pNextRxd = (RXD*) pMemArea;
+	pPrevDescr->VNextRxd = VMemArea;
+	pDescr               = (RXD*) pMemArea;
+	*ppRingHead          = (RXD*) pMemArea;
+	*ppRingTail          = *ppRingHead;
+	*ppRingPrev          = pPrevDescr;
+	*pRingFree           = DescrNum;
+	*pRingPrevFree       = DescrNum;
+} /* SetupRing */
+
+
+/*****************************************************************************
+ *
+ * 	PortReInitBmu - re-initiate the descriptor rings for one port
+ *
+ * Description:
+ *	This function reinitializes the descriptor rings of one port
+ *	in memory. The port must be stopped before.
+ *	The HW is initialized with the descriptor start addresses.
+ *
+ * Returns:
+ *	none
+ */
+static void PortReInitBmu(
+SK_AC	*pAC,		/* pointer to adapter context */
+int	PortIndex)	/* index of the port for which to re-init */
+{
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("PortReInitBmu "));
+
+	/* set address of first descriptor of ring in BMU */
+	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
+		(uint32_t)(((caddr_t)
+		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
+		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
+		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
+		0xFFFFFFFF));
+	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
+		(uint32_t)(((caddr_t)
+		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
+		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
+		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
+	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
+		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
+		pAC->RxPort[PortIndex].pRxDescrRing +
+		pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
+	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
+		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
+		pAC->RxPort[PortIndex].pRxDescrRing +
+		pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
+} /* PortReInitBmu */
+
+
+/****************************************************************************
+ *
+ *	SkGeIsr - handle adapter interrupts
+ *
+ * Description:
+ *	The interrupt routine is called when the network adapter
+ *	generates an interrupt. It may also be called if another device
+ *	shares this interrupt vector with the driver.
+ *
+ * Returns: N/A
+ *
+ */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+static SkIsrRetVar SkGeIsr(int irq, void *dev_id)
+#else
+static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)
+#endif
+{
+struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
+DEV_NET		*pNet;
+SK_AC		*pAC;
+SK_U32		IntSrc;		/* interrupts source register contents */	
+
+	pNet = (DEV_NET*)netdev_priv(dev);
+	pAC = pNet->pAC;
+	
+	/*
+	 * Check and process if its our interrupt
+	 */
+	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
+	if ((IntSrc == 0) && (!pNet->NetConsoleMode)) {
+		return SkIsrRetNone;
+	}
+
+#ifdef CONFIG_SK98LIN_NAPI
+	if (netif_rx_schedule_prep(dev)) {
+		pAC->GIni.GIValIrqMask &= ~(NAPI_DRV_IRQS);
+		SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+		__netif_rx_schedule(dev);
+	}
+
+#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+	if (IntSrc & IS_XA1_F) {
+		CLEAR_TX_IRQ(0, TX_PRIO_LOW);
+	}
+	if (IntSrc & IS_XA2_F) {
+		CLEAR_TX_IRQ(1, TX_PRIO_LOW);
+	}
+#endif
+
+
+#else
+	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
+#if 0 /* software irq currently not used */
+		if (IntSrc & IS_IRQ_SW) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("Software IRQ\n"));
+		}
+#endif
+		if (IntSrc & IS_R1_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF RX1 IRQ\n"));
+			ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+			CLEAR_AND_START_RX(0);
+			SK_PNMI_CNT_RX_INTR(pAC, 0);
+		}
+		if (IntSrc & IS_R2_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF RX2 IRQ\n"));
+			ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+			CLEAR_AND_START_RX(1);
+			SK_PNMI_CNT_RX_INTR(pAC, 1);
+		}
+#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+		if (IntSrc & IS_XA1_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF AS TX1 IRQ\n"));
+			CLEAR_TX_IRQ(0, TX_PRIO_LOW);
+			SK_PNMI_CNT_TX_INTR(pAC, 0);
+			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+		}
+		if (IntSrc & IS_XA2_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF AS TX2 IRQ\n"));
+			CLEAR_TX_IRQ(1, TX_PRIO_LOW);
+			SK_PNMI_CNT_TX_INTR(pAC, 1);
+			spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+			FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
+			spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+		}
+#if 0 /* only if sync. queues used */
+		if (IntSrc & IS_XS1_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF SY TX1 IRQ\n"));
+			CLEAR_TX_IRQ(0, TX_PRIO_HIGH);
+			SK_PNMI_CNT_TX_INTR(pAC, 1);
+			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
+			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+		}
+		if (IntSrc & IS_XS2_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF SY TX2 IRQ\n"));
+			CLEAR_TX_IRQ(1, TX_PRIO_HIGH);
+			SK_PNMI_CNT_TX_INTR(pAC, 1);
+			spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
+			FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
+			spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
+		}
+#endif
+#endif
+
+		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+	} /* while (IntSrc & IRQ_MASK != 0) */
+#endif
+
+#ifndef CONFIG_SK98LIN_NAPI
+	/* Handle interrupts */
+	spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+	FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+	spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+	START_RX(0);
+	spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+	FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
+	spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+	ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+	START_RX(1);
+#endif
+
+	IntSrc &= pAC->GIni.GIValIrqMask;
+	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+			("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
+		pAC->CheckQueue = SK_FALSE;
+		spin_lock(&pAC->SlowPathLock);
+		if (IntSrc & SPECIAL_IRQS)
+			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+
+		SkEventDispatcher(pAC, pAC->IoBase);
+		spin_unlock(&pAC->SlowPathLock);
+		START_RX(0);
+		START_RX(1);
+	}
+
+	if (pAC->CheckQueue) {
+		pAC->CheckQueue = SK_FALSE;
+		spin_lock(&pAC->SlowPathLock);
+		SkEventDispatcher(pAC, pAC->IoBase);
+		spin_unlock(&pAC->SlowPathLock);
+	}
+
+	/* IRQ is processed - Enable IRQs again*/
+	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+
+	return SkIsrRetHandled;
+
+} /* SkGeIsr */
+
+
+/****************************************************************************
+ *
+ *	SkGeIsrOnePort - handle adapter interrupts for single port adapter
+ *
+ * Description:
+ *	The interrupt routine is called when the network adapter
+ *	generates an interrupt. It may also be called if another device
+ *	shares this interrupt vector with the driver.
+ *	This is the same as above, but handles only one port.
+ *
+ * Returns: N/A
+ *
+ */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id)
+#else
+static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)
+#endif
+{
+struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
+DEV_NET		*pNet;
+SK_AC		*pAC;
+SK_U32		IntSrc;		/* interrupts source register contents */	
+
+	pNet = (DEV_NET*)netdev_priv(dev);
+	pAC = pNet->pAC;
+	
+	/*
+	 * Check and process if its our interrupt
+	 */
+	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
+	if ((IntSrc == 0) && (!pNet->NetConsoleMode)) {
+		return SkIsrRetNone;
+
+	}
+	
+#ifdef CONFIG_SK98LIN_NAPI
+	if (netif_rx_schedule_prep(dev)) {
+		CLEAR_AND_START_RX(0);
+		CLEAR_TX_IRQ(0, TX_PRIO_LOW);
+		pAC->GIni.GIValIrqMask &= ~(NAPI_DRV_IRQS);
+		SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+		__netif_rx_schedule(dev);
+	} 
+
+#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+	if (IntSrc & IS_XA1_F) {
+		CLEAR_TX_IRQ(0, TX_PRIO_LOW);
+	}
+#endif
+#else
+	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
+#if 0 /* software irq currently not used */
+		if (IntSrc & IS_IRQ_SW) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("Software IRQ\n"));
+		}
+#endif
+		if (IntSrc & IS_R1_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF RX1 IRQ\n"));
+			ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+			CLEAR_AND_START_RX(0);
+			SK_PNMI_CNT_RX_INTR(pAC, 0);
+		}
+#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+		if (IntSrc & IS_XA1_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF AS TX1 IRQ\n"));
+			CLEAR_TX_IRQ(0, TX_PRIO_LOW);
+			SK_PNMI_CNT_TX_INTR(pAC, 0);
+			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+		}
+#if 0 /* only if sync. queues used */
+		if (IntSrc & IS_XS1_F) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_INT_SRC,
+				("EOF SY TX1 IRQ\n"));
+			CLEAR_TX_IRQ(0, TX_PRIO_HIGH);
+			SK_PNMI_CNT_TX_INTR(pAC, 0);
+			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
+			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+		}
+#endif
+#endif
+
+		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+	} /* while (IntSrc & IRQ_MASK != 0) */
+#endif
+	
+#ifndef CONFIG_SK98LIN_NAPI
+	spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+	FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+	spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+	START_RX(0);
+#endif
+
+	IntSrc &= pAC->GIni.GIValIrqMask;
+	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+			("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
+		pAC->CheckQueue = SK_FALSE;
+		spin_lock(&pAC->SlowPathLock);
+		if (IntSrc & SPECIAL_IRQS)
+			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+
+		SkEventDispatcher(pAC, pAC->IoBase);
+		spin_unlock(&pAC->SlowPathLock);
+		START_RX(0);
+	}
+
+	/* IRQ is processed - Enable IRQs again*/
+	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+
+	return SkIsrRetHandled;
+
+} /* SkGeIsrOnePort */
+
+/****************************************************************************
+ *
+ *	SkGeOpen - handle start of initialized adapter
+ *
+ * Description:
+ *	This function starts the initialized adapter.
+ *	The board level variable is set and the adapter is
+ *	brought to full functionality.
+ *	The device flags are set for operation.
+ *	Do all necessary level 2 initialization, enable interrupts and
+ *	give start command to RLMT.
+ *
+ * Returns:
+ *	0 on success
+ *	!= 0 on error
+ */
+static int SkGeOpen(
+struct SK_NET_DEVICE *dev)  /* the device that is to be opened */
+{
+	DEV_NET        *pNet = (DEV_NET*)netdev_priv(dev);
+	SK_AC          *pAC  = pNet->pAC;
+	unsigned long   Flags;    	/* for the spin locks	*/
+	SK_BOOL         DualNet;
+	int             CurrMac;	/* loop ctr for ports	*/
+#ifndef SK_ASF
+	unsigned long   InitFlags;
+#endif
+	SK_U32          StatSpeed, StatDuplex, NewTimerInterval;
+#ifdef SK_ASF
+	SK_EVPARA       Para;
+	SK_U32          TmpVal32;
+#endif
+
+	struct proc_dir_entry *pProcFile;
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
+
+#ifdef SK_ASF
+	spin_lock(&pAC->InitLock);
+#endif
+#ifndef SK_ASF
+	spin_lock_irqsave(&pAC->InitLock, InitFlags);
+#endif
+
+	if (pAC->DiagModeActive == DIAG_ACTIVE) {
+		if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+#ifdef SK_ASF
+			spin_unlock(&pAC->InitLock);
+#endif
+#ifndef SK_ASF
+			spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+#endif
+			return (-1);   /* still in use by diag; deny actions */
+		} 
+	}
+
+	if (!try_module_get(THIS_MODULE)) {
+#ifdef SK_ASF
+		spin_unlock(&pAC->InitLock);
+#endif
+#ifndef SK_ASF
+		spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+#endif
+		return (-1);	/* increase of usage count not possible */
+	}
+
+	/* Set blink mode */
+	if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
+		pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
+
+	if (pAC->BoardLevel == SK_INIT_DATA) {
+		/* level 1 init common modules here */
+		if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+			module_put(THIS_MODULE); /* decrease usage count */
+#ifdef SK_ASF
+			spin_unlock(&pAC->InitLock);
+#endif
+#ifndef SK_ASF
+			spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+#endif
+			printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
+			return (-1);
+		}
+		SkI2cInit	(pAC, pAC->IoBase, SK_INIT_IO);
+		SkEventInit	(pAC, pAC->IoBase, SK_INIT_IO);
+		SkPnmiInit	(pAC, pAC->IoBase, SK_INIT_IO);
+		SkAddrInit	(pAC, pAC->IoBase, SK_INIT_IO);
+		SkRlmtInit	(pAC, pAC->IoBase, SK_INIT_IO);
+		SkTimerInit	(pAC, pAC->IoBase, SK_INIT_IO);
+#ifdef SK_ASF
+		SkAsfInit	(pAC, pAC->IoBase, SK_INIT_IO);
+#endif
+		pAC->BoardLevel = SK_INIT_IO;
+#ifdef Y2_RECOVERY
+		/* mark entries invalid */
+		pAC->LastPort = 3;
+		pAC->LastOpc = 0xFF;
+#endif
+	}
+
+	if (pAC->BoardLevel != SK_INIT_RUN) {
+		/* tschilling: Level 2 init modules here, check return value. */
+		if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
+			module_put(THIS_MODULE); /* decrease usage count */
+#ifdef SK_ASF
+			spin_unlock(&pAC->InitLock);
+#endif
+#ifndef SK_ASF
+			spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+#endif
+			printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
+			return (-1);
+		}
+		SkI2cInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+		SkEventInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+		SkPnmiInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+		SkAddrInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+		SkRlmtInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+		SkTimerInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+		
+#ifdef SK_ASF
+#ifndef USE_ASF_DASH_FW
+		SkAsfInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+#endif
+#endif
+		pAC->BoardLevel = SK_INIT_RUN;
+	}
+#ifdef USE_ASF_DASH_FW
+	SkAsfInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+#endif
+
+	DualNet = SK_FALSE;
+	if (pAC->RlmtNets == 2) {
+
+	        DualNet = SK_TRUE;
+	}
+	
+	if (SkGeInitAssignRamToQueues(
+		pAC,
+		pAC->ActivePort,
+		DualNet)) {
+		if (CHIP_ID_YUKON_2(pAC)) {
+			SkY2FreeResources(pAC);
+		} else {
+			BoardFreeMem(pAC);
+		}
+#ifdef SK_ASF
+		spin_unlock(&pAC->InitLock);
+#endif
+#ifndef SK_ASF
+		spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+#endif
+		printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
+		return(-EAGAIN);
+	}
+
+	for (CurrMac=0; CurrMac<pAC->GIni.GIMacsFound; CurrMac++) {
+		if (!CHIP_ID_YUKON_2(pAC)) {
+			/* Enable transmit descriptor polling. */
+			SkGePollTxD(pAC, pAC->IoBase, CurrMac, SK_TRUE);
+			FillRxRing(pAC, &pAC->RxPort[CurrMac]);
+			SkMacRxTxEnable(pAC, pAC->IoBase, pNet->PortNr);
+		}
+	}
+
+	SkGeYellowLED(pAC, pAC->IoBase, 1);
+	SkDimEnableModerationIfNeeded(pAC);	
+
+	if (!CHIP_ID_YUKON_2(pAC)) {
+		/*
+		** Has been setup already at SkGeInit(SK_INIT_IO),
+		** but additional masking added for Genesis & Yukon
+		** chipsets -> modify it...
+		*/
+		pAC->GIni.GIValIrqMask &= IRQ_MASK;
+#ifndef USE_TX_COMPLETE
+		pAC->GIni.GIValIrqMask &= ~(TX_COMPL_IRQS);
+#endif
+	}
+
+	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+
+	if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
+		SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
+					pAC->RlmtNets, -1, SK_FALSE);
+		SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
+					pAC->RlmtMode, 0, SK_FALSE);
+	}
+
+	SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_START,
+				pNet->NetNr, -1, SK_TRUE);
+	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+
+#ifdef Y2_RECOVERY
+	pNet->TimerExpired = SK_FALSE;
+	pNet->InRecover = SK_FALSE;
+	pNet->NetConsoleMode = SK_FALSE;
+
+	StatSpeed = pAC->GIni.GP[pNet->NetNr].PLinkSpeedUsed;
+	if (StatSpeed == SK_LSPEED_STAT_10MBPS) {
+		StatDuplex = pAC->GIni.GP[pNet->NetNr].PLinkModeStatus;
+		if ((StatDuplex == SK_LMODE_STAT_AUTOHALF) ||
+			(StatDuplex == SK_LMODE_STAT_HALF)) {
+				NewTimerInterval = (HZ*2);
+		} else {
+			NewTimerInterval = (HZ);
+		}
+	} else if (StatSpeed == SK_LSPEED_STAT_100MBPS) {
+		NewTimerInterval = (HZ/2);
+	} else if (StatSpeed == SK_LSPEED_STAT_1000MBPS) {
+		NewTimerInterval = (HZ/4);
+	} else {
+		NewTimerInterval = (HZ*2);
+	}
+
+	/* Initialize the kernel timer */
+	init_timer(&pNet->KernelTimer);
+	pNet->KernelTimer.function	= SkGeHandleKernelTimer;
+	pNet->KernelTimer.data		= (unsigned long) pNet;
+	pNet->KernelTimer.expires	= jiffies + NewTimerInterval;
+	add_timer(&pNet->KernelTimer);
+#endif
+#ifdef SK_ASF
+#ifndef USE_ASF_DASH_FW
+	/*  Set OS Present Flag in ASF Status and Command Register */
+	SK_IN32( pAC->IoBase, REG_ASF_STATUS_CMD, &TmpVal32 );
+	TmpVal32 |= BIT_4;
+	SK_OUT32( pAC->IoBase, REG_ASF_STATUS_CMD, TmpVal32 );
+
+	/*  Disable ARP pattern, OS is now responsible for ARP handling */
+	YlciDisablePattern(pAC, pAC->IoBase, 0, 5);
+
+	if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+
+		/*  Disable ARP pattern, OS is now responsible for ARP handling */
+		YlciDisablePattern(pAC, pAC->IoBase, 1, 5);
+	}	 
+#endif
+#ifdef USE_ASF_DASH_FW
+	SK_IN32( pAC->IoBase, REG_ASF_STATUS_CMD, &TmpVal32 );
+	TmpVal32 |= BIT_2; // Dash works with Yukon Extreme
+	SK_OUT32( pAC->IoBase, REG_ASF_STATUS_CMD, TmpVal32 );
+#endif
+	if (is_closed) {	 
+		Para.Para32[0] = pAC->ActivePort;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
+	}	
+#endif
+
+	/* Enable interrupts */
+	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+
+	pAC->MaxPorts++;
+
+	/* Set state to open */
+	is_closed = 0;
+
+	/* Initialize the procfs timer */
+	init_timer(&pNet->ProcfsTimer);
+	pNet->ProcfsTimer.function	= SkGeHandleProcfsTimer;
+	pNet->ProcfsTimer.data		= (unsigned long) pNet;
+	pNet->ProcfsTimer.expires	= jiffies + HZ*5; /* initially 5 secs */
+	add_timer(&pNet->ProcfsTimer);
+
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
+		SK_OUT8(pAC->IoBase, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
+			PC_VAUX_OFF | PC_VCC_ON));
+	}
+
+#ifdef SK_ASF
+	spin_unlock(&pAC->InitLock);
+#endif
+#ifndef SK_ASF
+	spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+#endif
+
+#ifdef CONFIG_PROC_FS
+	if ((!pAC->InterfaceUp[pNet->NetNr]) && (pSkRootDir)) {
+		pProcFile = create_proc_entry(pAC->dev[pNet->NetNr]->name, S_IRUGO, pSkRootDir);
+		pProcFile->proc_fops = &sk_proc_fops;
+		pProcFile->data      = dev;
+
+		/*
+		 * Remember, interface dev nr pNet->NetNr is up
+		 */
+		pAC->InterfaceUp[pNet->NetNr] = 1;
+
+		strcpy(pNet->CurrentName, pNet->pAC->dev[pNet->NetNr]->name);
+	}
+#endif
+
+	if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) ||
+		(CHIP_ID_YUKON_2(pAC)) ) {
+		pAC->StatusLETable.Done  = 0;
+		pAC->StatusLETable.Put   = 0;
+		pAC->StatusLETable.HwPut = 0;
+		SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable);
+	}
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeOpen suceeded\n"));
+
+	return (0);
+} /* SkGeOpen */
+
+
+/****************************************************************************
+ *
+ *	SkGeClose - Stop initialized adapter
+ *
+ * Description:
+ *	Close initialized adapter.
+ *
+ * Returns:
+ *	0 - on success
+ *	error code - on error
+ */
+static int SkGeClose(
+struct SK_NET_DEVICE *dev)  /* the device that is to be closed */
+{
+	DEV_NET         *pNet = (DEV_NET*)netdev_priv(dev);
+	SK_AC           *pAC  = pNet->pAC;
+	DEV_NET         *newPtrNet;
+	unsigned long    Flags;		/* for the spin locks		*/
+	unsigned long    InitFlags;	/* for the spin locks		*/
+	int              CurrMac;	/* loop ctr for the current MAC	*/
+	int              PortIdx;
+#ifdef CONFIG_SK98LIN_NAPI
+	int              WorkToDo = 1; /* min(*budget, dev->quota);    */
+	int              WorkDone = 0;
+#endif
+#ifdef USE_ASF_DASH_FW
+	SK_EVPARA	Para2;
+#endif
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
+	spin_lock_irqsave(&pAC->InitLock, InitFlags);
+#ifdef SK_ASF
+	SkAsfDeInit(pAC, pAC->IoBase);
+#endif
+
+#ifdef CONFIG_PROC_FS
+	del_timer(&pNet->ProcfsTimer);
+#endif
+
+#ifdef Y2_RECOVERY
+	pNet->InRecover = SK_TRUE;
+	del_timer(&pNet->KernelTimer);
+#endif
+
+	if (pAC->DiagModeActive == DIAG_ACTIVE) {
+		if (pAC->DiagFlowCtrl == SK_FALSE) {
+			module_put(THIS_MODULE);
+			/* 
+			** notify that the interface which has been closed
+			** by operator interaction must not be started up 
+			** again when the DIAG has finished. 
+			*/
+			newPtrNet = (DEV_NET *)netdev_priv(pAC->dev[0]);
+			if (newPtrNet == pNet) {
+				pAC->WasIfUp[0] = SK_FALSE;
+			} else {
+				pAC->WasIfUp[1] = SK_FALSE;
+			}
+			return 0; /* return to system everything is fine... */
+		} else {
+			pAC->DiagFlowCtrl = SK_FALSE;
+		}
+	}
+
+#ifdef SK_ASF
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+#else
+	netif_stop_queue(dev);
+#endif
+
+	if (pAC->RlmtNets == 1)
+		PortIdx = pAC->ActivePort;
+	else
+		PortIdx = pNet->NetNr;
+
+#ifdef USE_ASF_DASH_FW
+	SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+		SK_PROM_MODE_ALL_MC);
+#else
+	/*
+	 * Clear multicast table, promiscuous mode ....
+	 */
+	SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
+	SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+		SK_PROM_MODE_NONE);
+#endif
+
+	if (pAC->MaxPorts == 1) {
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+		/* disable interrupts */
+		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+
+#ifdef USE_ASF_DASH_FW
+		SkTimerStop(pAC, pAC->IoBase, &pAC->Rlmt.Net[pNet->NetNr].LocTimer);
+		SkTimerStop(pAC, pAC->IoBase, &pAC->Rlmt.Net[pNet->NetNr].SegTimer);
+		
+		pAC->Rlmt.Net[pNet->NetNr].RlmtState = SK_RLMT_RS_INIT;
+		pAC->Rlmt.Net[pNet->NetNr].RootIdSet = SK_FALSE;
+		Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
+		Para2.Para32[1] = pNet->NetNr;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
+		
+		pAC->Rlmt.NetsStarted--;
+#endif
+		
+#ifndef SK_ASF
+		SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
+					pNet->NetNr, -1, SK_TRUE);
+		/* stop the hardware */
+		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+#endif
+
+		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 1)) {
+		/* RLMT check link state mode */
+			for (CurrMac=0; CurrMac<pAC->GIni.GIMacsFound; CurrMac++) {
+				if (CHIP_ID_YUKON_2(pAC)) {
+#ifdef SK_ASF
+					SkY2PortStop(	pAC, 
+							pAC->IoBase,
+							CurrMac,
+							SK_STOP_RX,
+							SK_HARD_RST);
+					SkY2PortStop(	pAC, 
+							pAC->IoBase,
+							CurrMac,
+							SK_STOP_TX,
+							SK_HARD_RST);
+#else
+					SkY2PortStop(	pAC, 
+							pAC->IoBase,
+							CurrMac,
+							SK_STOP_ALL,
+							SK_HARD_RST);
+#endif
+				} else {
+					SkGeStopPort(	pAC,
+							pAC->IoBase,
+							CurrMac,
+							SK_STOP_ALL,
+							SK_HARD_RST);
+				}
+			} /* for */
+		} else {
+		/* Single link or single port */
+			if (CHIP_ID_YUKON_2(pAC)) {
+#ifdef SK_ASF
+				SkY2PortStop(	pAC, 
+						pAC->IoBase,
+						PortIdx,
+						SK_STOP_RX,
+						SK_HARD_RST);
+				SkY2PortStop(	pAC, 
+						pAC->IoBase,
+						PortIdx,
+						SK_STOP_TX,
+						SK_HARD_RST);
+#else
+				SkY2PortStop(	pAC, 
+						pAC->IoBase,
+						PortIdx,
+						SK_STOP_ALL,
+						SK_HARD_RST);
+#endif
+			} else {
+				SkGeStopPort(	pAC,
+						pAC->IoBase,
+						PortIdx,
+						SK_STOP_ALL,
+						SK_HARD_RST);
+			}
+		}
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+	} else {
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+#ifndef SK_ASF
+		SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
+					pNet->NetNr, -1, SK_FALSE);
+		SkLocalEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
+					pNet->NetNr, -1, SK_TRUE);
+#endif
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+		
+		/* Stop port */
+		spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
+			[TX_PRIO_LOW].TxDesRingLock, Flags);
+		if (CHIP_ID_YUKON_2(pAC)) {
+#ifdef SK_ASF
+			SkY2PortStop(pAC, pAC->IoBase, pNet->PortNr,
+				SK_STOP_RX, SK_HARD_RST);
+			SkY2PortStop(pAC, pAC->IoBase, pNet->PortNr,
+				SK_STOP_TX, SK_HARD_RST);
+#else
+			SkY2PortStop(pAC, pAC->IoBase, pNet->PortNr,
+				SK_STOP_ALL, SK_HARD_RST);
+#endif
+		}
+		else {
+			SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
+				SK_STOP_ALL, SK_HARD_RST);
+		}
+		spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
+			[TX_PRIO_LOW].TxDesRingLock, Flags);
+	}
+
+	if (pAC->RlmtNets == 1) {
+		/* clear all descriptor rings */
+		for (CurrMac=0; CurrMac<pAC->GIni.GIMacsFound; CurrMac++) {
+			if (!CHIP_ID_YUKON_2(pAC)) {
+#ifdef CONFIG_SK98LIN_NAPI
+				WorkToDo = 1;
+				ReceiveIrq(pAC,&pAC->RxPort[CurrMac],
+						SK_TRUE,&WorkDone,WorkToDo);
+#else
+				ReceiveIrq(pAC,&pAC->RxPort[CurrMac],SK_TRUE);
+#endif
+				ClearRxRing(pAC, &pAC->RxPort[CurrMac]);
+				ClearTxRing(pAC, &pAC->TxPort[CurrMac][TX_PRIO_LOW]);
+			} else {
+				SkY2FreeRxBuffers(pAC, pAC->IoBase, CurrMac);
+				SkY2FreeTxBuffers(pAC, pAC->IoBase, CurrMac);
+			}
+		}
+	} else {
+		/* clear port descriptor rings */
+		if (!CHIP_ID_YUKON_2(pAC)) {
+#ifdef CONFIG_SK98LIN_NAPI
+			WorkToDo = 1;
+			ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE, &WorkDone, WorkToDo);
+#else
+			ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
+#endif
+			ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
+			ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
+		}
+		else {
+			SkY2FreeRxBuffers(pAC, pAC->IoBase, pNet->PortNr);
+			SkY2FreeTxBuffers(pAC, pAC->IoBase, pNet->PortNr);
+		}
+	}
+
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
+		SK_OUT8(pAC->IoBase, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
+			PC_VAUX_ON | PC_VCC_OFF));
+	}
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeClose: done "));
+
+	SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
+	SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
+			sizeof(SK_PNMI_STRUCT_DATA));
+
+	pAC->MaxPorts--;
+	module_put(THIS_MODULE);
+
+#ifdef Y2_RECOVERY
+	pNet->InRecover = SK_FALSE;
+#endif
+	is_closed = 1;
+	spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+
+	return (0);
+} /* SkGeClose */
+
+
+/*****************************************************************************
+ *
+ * 	SkGeXmit - Linux frame transmit function
+ *
+ * Description:
+ *	The system calls this function to send frames onto the wire.
+ *	It puts the frame in the tx descriptor ring. If the ring is
+ *	full then, the 'tbusy' flag is set.
+ *
+ * Returns:
+ *	0, if everything is ok
+ *	!=0, on error
+ * WARNING: returning 1 in 'tbusy' case caused system crashes (double
+ *	allocated skb's) !!!
+ */
+static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
+{
+DEV_NET		*pNet;
+SK_AC		*pAC;
+int			Rc;	/* return code of XmitFrame */
+
+	pNet = (DEV_NET*)netdev_priv(dev);
+	pAC = pNet->pAC;
+
+	if ((!skb_shinfo(skb)->nr_frags) ||
+		(pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
+		/* Don't activate scatter-gather and hardware checksum */
+
+		if (pAC->RlmtNets == 2)
+			Rc = XmitFrame(
+				pAC,
+				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+				skb);
+		else
+			Rc = XmitFrame(
+				pAC,
+				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+				skb);
+	} else {
+		/* scatter-gather and hardware TCP checksumming anabled*/
+		if (pAC->RlmtNets == 2)
+			Rc = XmitFrameSG(
+				pAC,
+				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+				skb);
+		else
+			Rc = XmitFrameSG(
+				pAC,
+				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+				skb);
+	}
+
+	/* Transmitter out of resources? */
+	if (Rc <= 0) {
+		netif_stop_queue(dev);
+	}
+
+	/* If not taken, give buffer ownership back to the
+	 * queueing layer.
+	 */
+	if (Rc < 0)
+		return (1);
+
+	dev->trans_start = jiffies;
+	return (0);
+} /* SkGeXmit */
+
+#ifdef CONFIG_SK98LIN_NAPI
+/*****************************************************************************
+ *
+ * 	SkGePoll - NAPI Rx polling callback for GEnesis and Yukon chipsets
+ *
+ * Description:
+ *	Called by the Linux system in case NAPI polling is activated
+ *
+ * Returns:
+ *	The number of work data still to be handled
+ */
+static int SkGePoll(struct net_device *dev, int *budget) 
+{
+	SK_AC		*pAC = ((DEV_NET*)(netdev_priv(dev)))->pAC; /* pointer to adapter context */
+	int		WorkToDo = min(*budget, dev->quota);
+	int		WorkDone = 0;
+	unsigned long	Flags;       
+
+
+	if (pAC->dev[0] != pAC->dev[1]) {
+		spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+		FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
+		spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+
+		ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE, &WorkDone, WorkToDo);
+		CLEAR_AND_START_RX(1);
+	}
+	spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+	FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+	spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+
+	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE, &WorkDone, WorkToDo);
+	CLEAR_AND_START_RX(0);
+
+	*budget -= WorkDone;
+	dev->quota -= WorkDone;
+
+	if(WorkDone < WorkToDo) {
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+		netif_rx_complete(dev);
+		pAC->GIni.GIValIrqMask |= (NAPI_DRV_IRQS);
+#ifndef USE_TX_COMPLETE
+		pAC->GIni.GIValIrqMask &= ~(TX_COMPL_IRQS);
+#endif
+		/* enable interrupts again */
+		SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+	}
+	return (WorkDone >= WorkToDo);
+} /* SkGePoll */
+#endif
+
+#ifdef SK_POLL_CONTROLLER
+/*****************************************************************************
+ *
+ * 	SkGeNetPoll - Polling "interrupt"
+ *
+ * Description:
+ *	Polling 'interrupt' - used by things like netconsole and netdump
+ *	to send skbs without having to re-enable interrupts.
+ *	It's not called while the interrupt routine is executing.
+ */
+static void SkGeNetPoll(
+struct SK_NET_DEVICE *dev) 
+{
+DEV_NET		*pNet;
+SK_AC		*pAC;
+
+	pNet = (DEV_NET*) dev->priv;
+	pAC = pNet->pAC;
+	pNet->NetConsoleMode = SK_TRUE;
+
+		/*  Prevent any reconfiguration while handling
+		    the 'interrupt' */
+		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+
+		if (!CHIP_ID_YUKON_2(pAC)) {
+		/* Handle the GENESIS Isr */
+			if (pAC->GIni.GIMacsFound == 2)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+				SkGeIsr(dev->irq, dev);
+#else
+				SkGeIsr(dev->irq, dev, NULL);
+#endif
+			else
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+				SkGeIsrOnePort(dev->irq, dev);
+#else
+				SkGeIsrOnePort(dev->irq, dev, NULL);
+#endif
+		} else {
+		/* Handle the Yukon2 Isr */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+			SkY2Isr(dev->irq, dev);
+#else
+			SkY2Isr(dev->irq, dev, NULL);
+#endif
+		}
+
+}
+#endif
+
+
+/*****************************************************************************
+ *
+ * 	XmitFrame - fill one socket buffer into the transmit ring
+ *
+ * Description:
+ *	This function puts a message into the transmit descriptor ring
+ *	if there is a descriptors left.
+ *	Linux skb's consist of only one continuous buffer.
+ *	The first step locks the ring. It is held locked
+ *	all time to avoid problems with SWITCH_../PORT_RESET.
+ *	Then the descriptoris allocated.
+ *	The second part is linking the buffer to the descriptor.
+ *	At the very last, the Control field of the descriptor
+ *	is made valid for the BMU and a start TX command is given
+ *	if necessary.
+ *
+ * Returns:
+ *	> 0 - on succes: the number of bytes in the message
+ *	= 0 - on resource shortage: this frame sent or dropped, now
+ *		the ring is full ( -> set tbusy)
+ *	< 0 - on failure: other problems ( -> return failure to upper layers)
+ */
+static int XmitFrame(
+SK_AC 		*pAC,		/* pointer to adapter context	        */
+TX_PORT		*pTxPort,	/* pointer to struct of port to send to */
+struct sk_buff	*pMessage)	/* pointer to send-message              */
+{
+	TXD		*pTxd;		/* the rxd to fill */
+	TXD		*pOldTxd;
+	unsigned long	 Flags;
+	SK_U64		 PhysAddr;
+	int	 	 Protocol;
+	int		 IpHeaderLength;
+	int		 BytesSend = pMessage->len;
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
+
+	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+#ifndef USE_TX_COMPLETE
+	if ((pTxPort->TxdRingPrevFree - pTxPort->TxdRingFree) > 6)  {
+		FreeTxDescriptors(pAC, pTxPort);
+		pTxPort->TxdRingPrevFree = pTxPort->TxdRingFree;
+	}
+#endif
+	if (pTxPort->TxdRingFree == 0) {
+		/* 
+		** not enough free descriptors in ring at the moment.
+		** Maybe free'ing some old one help?
+		*/
+		FreeTxDescriptors(pAC, pTxPort);
+		if (pTxPort->TxdRingFree == 0) {
+			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_TX_PROGRESS,
+				("XmitFrame failed\n"));
+			/* 
+			** the desired message can not be sent
+			** Because tbusy seems to be set, the message 
+			** should not be freed here. It will be used 
+			** by the scheduler of the ethernet handler 
+			*/
+			return (-1);
+		}
+	}
+
+	/*
+	** If the passed socket buffer is of smaller MTU-size than 60,
+	** copy everything into new buffer and fill all bytes between
+	** the original packet end and the new packet end of 60 with 0x00.
+	** This is to resolve faulty padding by the HW with 0xaa bytes.
+	*/
+	if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+		if ((pMessage = skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) == NULL) {
+#else
+		if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
+#endif
+			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+			return 0;
+		}
+		pMessage->len = C_LEN_ETHERNET_MINSIZE;
+	}
+
+	/* 
+	** advance head counter behind descriptor needed for this frame, 
+	** so that needed descriptor is reserved from that on. The next
+	** action will be to add the passed buffer to the TX-descriptor
+	*/
+	pTxd = pTxPort->pTxdRingHead;
+	pTxPort->pTxdRingHead = pTxd->pNextTxd;
+	pTxPort->TxdRingFree--;
+
+#ifdef SK_DUMP_TX
+	DumpMsg(pMessage, "XmitFrame");
+#endif
+
+	/* 
+	** First step is to map the data to be sent via the adapter onto
+	** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
+	** and 2.6 need to use pci_map_page() for that mapping.
+	*/
+	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+					virt_to_page(pMessage->data),
+					((unsigned long) pMessage->data & ~PAGE_MASK),
+					pMessage->len,
+					PCI_DMA_TODEVICE);
+	pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+	pTxd->pMBuf     = pMessage;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
+#else
+	if (pMessage->ip_summed == CHECKSUM_HW) {
+#endif
+		Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff);
+		if ((Protocol == C_PROTO_ID_UDP) && 
+			(pAC->GIni.GIChipRev == 0) &&
+			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+			pTxd->TBControl = BMU_TCP_CHECK;
+		} else {
+			pTxd->TBControl = BMU_UDP_CHECK;
+		}
+
+		IpHeaderLength  = (SK_U8)pMessage->data[C_OFFSET_IPHEADER];
+		IpHeaderLength  = (IpHeaderLength & 0xf) * 4;
+		pTxd->TcpSumOfs = 0; /* PH-Checksum already calculated */
+		pTxd->TcpSumSt  = C_LEN_ETHERMAC_HEADER + IpHeaderLength + 
+							(Protocol == C_PROTO_ID_UDP ?
+							C_OFFSET_UDPHEADER_UDPCS : 
+							C_OFFSET_TCPHEADER_TCPCS);
+		pTxd->TcpSumWr  = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
+
+		pTxd->TBControl |= BMU_OWN | BMU_STF | 
+				   BMU_SW  | BMU_EOF |
+#ifdef USE_TX_COMPLETE
+				   BMU_IRQ_EOF |
+#endif
+				   pMessage->len;
+	} else {
+		pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK | 
+				  BMU_SW  | BMU_EOF |
+#ifdef USE_TX_COMPLETE
+				   BMU_IRQ_EOF |
+#endif
+			pMessage->len;
+	}
+
+	/* 
+	** If previous descriptor already done, give TX start cmd 
+	*/
+	pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
+	if ((pOldTxd->TBControl & BMU_OWN) == 0) {
+		SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+	}	
+
+	/* 
+	** after releasing the lock, the skb may immediately be free'd 
+	*/
+	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+	if (pTxPort->TxdRingFree != 0) {
+		return (BytesSend);
+	} else {
+		return (0);
+	}
+
+} /* XmitFrame */
+
+/*****************************************************************************
+ *
+ * 	XmitFrameSG - fill one socket buffer into the transmit ring
+ *                (use SG and TCP/UDP hardware checksumming)
+ *
+ * Description:
+ *	This function puts a message into the transmit descriptor ring
+ *	if there is a descriptors left.
+ *
+ * Returns:
+ *	> 0 - on succes: the number of bytes in the message
+ *	= 0 - on resource shortage: this frame sent or dropped, now
+ *		the ring is full ( -> set tbusy)
+ *	< 0 - on failure: other problems ( -> return failure to upper layers)
+ */
+static int XmitFrameSG(
+SK_AC 		*pAC,		/* pointer to adapter context           */
+TX_PORT		*pTxPort,	/* pointer to struct of port to send to */
+struct sk_buff	*pMessage)	/* pointer to send-message              */
+{
+
+	TXD		*pTxd;
+	TXD		*pTxdFst;
+	TXD		*pTxdLst;
+	int 	 	 CurrFrag;
+	int		 BytesSend;
+	int		 IpHeaderLength; 
+	int		 Protocol;
+	skb_frag_t	*sk_frag;
+	SK_U64		 PhysAddr;
+	unsigned long	 Flags;
+
+	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+#ifndef USE_TX_COMPLETE
+	FreeTxDescriptors(pAC, pTxPort);
+#endif
+	if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
+		FreeTxDescriptors(pAC, pTxPort);
+		if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
+			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_TX_PROGRESS,
+				("XmitFrameSG failed - Ring full\n"));
+				/* this message can not be sent now */
+			return(-1);
+		}
+	}
+
+	pTxd      = pTxPort->pTxdRingHead;
+	pTxdFst   = pTxd;
+	pTxdLst   = pTxd;
+	BytesSend = 0;
+	Protocol  = 0;
+
+	/* 
+	** Map the first fragment (header) into the DMA-space
+	*/
+	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+			virt_to_page(pMessage->data),
+			((unsigned long) pMessage->data & ~PAGE_MASK),
+			skb_headlen(pMessage),
+			PCI_DMA_TODEVICE);
+
+	pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+
+	/* 
+	** Does the HW need to evaluate checksum for TCP or UDP packets? 
+	*/
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
+#else
+	if (pMessage->ip_summed == CHECKSUM_HW) {
+#endif
+		pTxd->TBControl = BMU_STF | BMU_STFWD | skb_headlen(pMessage);
+		/* 
+		** We have to use the opcode for tcp here,  because the
+		** opcode for udp is not working in the hardware yet 
+		** (Revision 2.0)
+		*/
+		Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff);
+		if ((Protocol == C_PROTO_ID_UDP) && 
+			(pAC->GIni.GIChipRev == 0) &&
+			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+			pTxd->TBControl |= BMU_TCP_CHECK;
+		} else {
+			pTxd->TBControl |= BMU_UDP_CHECK;
+		}
+
+		IpHeaderLength  = ((SK_U8)pMessage->data[C_OFFSET_IPHEADER] & 0xf)*4;
+		pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */
+		pTxd->TcpSumSt  = C_LEN_ETHERMAC_HEADER + IpHeaderLength +
+						(Protocol == C_PROTO_ID_UDP ?
+						C_OFFSET_UDPHEADER_UDPCS :
+						C_OFFSET_TCPHEADER_TCPCS);
+		pTxd->TcpSumWr  = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
+	} else {
+		pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_STF |
+					skb_headlen(pMessage);
+	}
+
+	pTxd = pTxd->pNextTxd;
+	pTxPort->TxdRingFree--;
+	BytesSend += skb_headlen(pMessage);
+
+	/* 
+	** Browse over all SG fragments and map each of them into the DMA space
+	*/
+	for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
+		sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
+		/* 
+		** we already have the proper value in entry
+		*/
+		PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+						 sk_frag->page,
+						 sk_frag->page_offset,
+						 sk_frag->size,
+						 PCI_DMA_TODEVICE);
+
+		pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+		pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+		pTxd->pMBuf     = pMessage;
+		
+		/* 
+		** Does the HW need to evaluate checksum for TCP or UDP packets? 
+		*/
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+		if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
+#else
+		if (pMessage->ip_summed == CHECKSUM_HW) {
+#endif
+			pTxd->TBControl = BMU_OWN | BMU_SW | BMU_STFWD;
+			/* 
+			** We have to use the opcode for tcp here because the 
+			** opcode for udp is not working in the hardware yet 
+			** (revision 2.0)
+			*/
+			if ((Protocol == C_PROTO_ID_UDP) && 
+				(pAC->GIni.GIChipRev == 0) &&
+				(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+				pTxd->TBControl |= BMU_TCP_CHECK;
+			} else {
+				pTxd->TBControl |= BMU_UDP_CHECK;
+			}
+		} else {
+			pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN;
+		}
+
+		/* 
+		** Do we have the last fragment? 
+		*/
+		if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags )  {
+#ifdef USE_TX_COMPLETE
+			pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF | sk_frag->size;
+#else
+			pTxd->TBControl |= BMU_EOF | sk_frag->size;
+#endif
+			pTxdFst->TBControl |= BMU_OWN | BMU_SW;
+
+		} else {
+			pTxd->TBControl |= sk_frag->size;
+		}
+		pTxdLst = pTxd;
+		pTxd    = pTxd->pNextTxd;
+		pTxPort->TxdRingFree--;
+		BytesSend += sk_frag->size;
+	}
+
+	/* 
+	** If previous descriptor already done, give TX start cmd 
+	*/
+	if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
+		SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+	}
+
+	pTxPort->pTxdRingPrev = pTxdLst;
+	pTxPort->pTxdRingHead = pTxd;
+
+	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+
+	if (pTxPort->TxdRingFree > 0) {
+		return (BytesSend);
+	} else {
+		return (0);
+	}
+}
+
+/*****************************************************************************
+ *
+ * 	FreeTxDescriptors - release descriptors from the descriptor ring
+ *
+ * Description:
+ *	This function releases descriptors from a transmit ring if they
+ *	have been sent by the BMU.
+ *	If a descriptors is sent, it can be freed and the message can
+ *	be freed, too.
+ *	The SOFTWARE controllable bit is used to prevent running around a
+ *	completely free ring for ever. If this bit is no set in the
+ *	frame (by XmitFrame), this frame has never been sent or is
+ *	already freed.
+ *	The Tx descriptor ring lock must be held while calling this function !!!
+ *
+ * Returns:
+ *	none
+ */
+static void FreeTxDescriptors(
+SK_AC	*pAC,		/* pointer to the adapter context */
+TX_PORT	*pTxPort)	/* pointer to destination port structure */
+{
+TXD	*pTxd;		/* pointer to the checked descriptor */
+TXD	*pNewTail;	/* pointer to 'end' of the ring */
+SK_U32	Control;	/* TBControl field of descriptor */
+SK_U64	PhysAddr;	/* address of DMA mapping */
+
+	pNewTail = pTxPort->pTxdRingTail;
+	pTxd     = pNewTail;
+	/*
+	** loop forever; exits if BMU_SW bit not set in start frame
+	** or BMU_OWN bit set in any frame
+	*/
+	while (1) {
+		Control = pTxd->TBControl;
+		if ((Control & BMU_SW) == 0) {
+			/*
+			** software controllable bit is set in first
+			** fragment when given to BMU. Not set means that
+			** this fragment was never sent or is already
+			** freed ( -> ring completely free now).
+			*/
+			pTxPort->pTxdRingTail = pTxd;
+			netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
+			return;
+		}
+		if (Control & BMU_OWN) {
+			pTxPort->pTxdRingTail = pTxd;
+			if (pTxPort->TxdRingFree > 0) {
+				netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
+			}
+			return;
+		}
+		
+		/* 
+		** release the DMA mapping, because until not unmapped
+		** this buffer is considered being under control of the
+		** adapter card!
+		*/
+		PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
+		PhysAddr |= (SK_U64) pTxd->VDataLow;
+		pci_unmap_page(pAC->PciDev, PhysAddr,
+				 pTxd->pMBuf->len,
+				 PCI_DMA_TODEVICE);
+
+		if (Control & BMU_EOF)
+			DEV_KFREE_SKB_ANY(pTxd->pMBuf);	/* free message */
+
+		pTxPort->TxdRingFree++;
+		pTxd->TBControl &= ~BMU_SW;
+		pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
+	} /* while(forever) */
+} /* FreeTxDescriptors */
+
+/*****************************************************************************
+ *
+ * 	FillRxRing - fill the receive ring with valid descriptors
+ *
+ * Description:
+ *	This function fills the receive ring descriptors with data
+ *	segments and makes them valid for the BMU.
+ *	The active ring is filled completely, if possible.
+ *	The non-active ring is filled only partial to save memory.
+ *
+ * Description of rx ring structure:
+ *	head - points to the descriptor which will be used next by the BMU
+ *	tail - points to the next descriptor to give to the BMU
+ *	
+ * Returns:	N/A
+ */
+static void FillRxRing(
+SK_AC		*pAC,		/* pointer to the adapter context */
+RX_PORT		*pRxPort)	/* ptr to port struct for which the ring
+				   should be filled */
+{
+unsigned long	Flags;
+
+	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
+	while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {
+		if(!FillRxDescriptor(pAC, pRxPort))
+			break;
+	}
+	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
+} /* FillRxRing */
+
+
+/*****************************************************************************
+ *
+ * 	FillRxDescriptor - fill one buffer into the receive ring
+ *
+ * Description:
+ *	The function allocates a new receive buffer and
+ *	puts it into the next descriptor.
+ *
+ * Returns:
+ *	SK_TRUE - a buffer was added to the ring
+ *	SK_FALSE - a buffer could not be added
+ */
+static SK_BOOL FillRxDescriptor(
+SK_AC		*pAC,		/* pointer to the adapter context struct */
+RX_PORT		*pRxPort)	/* ptr to port struct of ring to fill */
+{
+struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
+RXD		*pRxd;		/* the rxd to fill */
+SK_U16		Length;		/* data fragment length */
+SK_U64		PhysAddr;	/* physical address of a rx buffer */
+
+	pMsgBlock = alloc_skb(pRxPort->RxBufSize, GFP_ATOMIC);
+	if (pMsgBlock == NULL) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+			SK_DBGCAT_DRV_ENTRY,
+			("%s: Allocation of rx buffer failed !\n",
+			pAC->dev[pRxPort->PortIndex]->name));
+		SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);
+		return(SK_FALSE);
+	}
+	skb_reserve(pMsgBlock, 2); /* to align IP frames */
+	/* skb allocated ok, so add buffer */
+	pRxd = pRxPort->pRxdRingTail;
+	pRxPort->pRxdRingTail = pRxd->pNextRxd;
+	pRxPort->RxdRingFree--;
+	Length = pRxPort->RxBufSize;
+	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+		virt_to_page(pMsgBlock->data),
+		((unsigned long) pMsgBlock->data &
+		~PAGE_MASK),
+		pRxPort->RxBufSize - 2,
+		PCI_DMA_FROMDEVICE);
+
+	pRxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+	pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+	pRxd->pMBuf     = pMsgBlock;
+	pRxd->RBControl = BMU_OWN       | 
+			  BMU_STF       | 
+			  BMU_IRQ_EOF   | 
+			  BMU_TCP_CHECK | 
+			  Length;
+	return (SK_TRUE);
+
+} /* FillRxDescriptor */
+
+
+/*****************************************************************************
+ *
+ * 	ReQueueRxBuffer - fill one buffer back into the receive ring
+ *
+ * Description:
+ *	Fill a given buffer back into the rx ring. The buffer
+ *	has been previously allocated and aligned, and its phys.
+ *	address calculated, so this is no more necessary.
+ *
+ * Returns: N/A
+ */
+static void ReQueueRxBuffer(
+SK_AC		*pAC,		/* pointer to the adapter context struct */
+RX_PORT		*pRxPort,	/* ptr to port struct of ring to fill */
+struct sk_buff	*pMsg,		/* pointer to the buffer */
+SK_U32		PhysHigh,	/* phys address high dword */
+SK_U32		PhysLow)	/* phys address low dword */
+{
+RXD		*pRxd;		/* the rxd to fill */
+SK_U16		Length;		/* data fragment length */
+
+	pRxd = pRxPort->pRxdRingTail;
+	pRxPort->pRxdRingTail = pRxd->pNextRxd;
+	pRxPort->RxdRingFree--;
+	Length = pRxPort->RxBufSize;
+
+	pRxd->VDataLow  = PhysLow;
+	pRxd->VDataHigh = PhysHigh;
+	pRxd->pMBuf     = pMsg;
+	pRxd->RBControl = BMU_OWN       | 
+			  BMU_STF       |
+			  BMU_IRQ_EOF   | 
+			  BMU_TCP_CHECK | 
+			  Length;
+	return;
+} /* ReQueueRxBuffer */
+
+/*****************************************************************************
+ *
+ * 	ReceiveIrq - handle a receive IRQ
+ *
+ * Description:
+ *	This function is called when a receive IRQ is set.
+ *	It walks the receive descriptor ring and sends up all
+ *	frames that are complete.
+ *
+ * Returns:	N/A
+ */
+static void ReceiveIrq(
+#ifdef CONFIG_SK98LIN_NAPI
+SK_AC    *pAC,          /* pointer to adapter context          */
+RX_PORT  *pRxPort,      /* pointer to receive port struct      */
+SK_BOOL   SlowPathLock, /* indicates if SlowPathLock is needed */
+int      *WorkDone,
+int       WorkToDo)
+#else
+SK_AC    *pAC,          /* pointer to adapter context          */
+RX_PORT  *pRxPort,      /* pointer to receive port struct      */
+SK_BOOL   SlowPathLock) /* indicates if SlowPathLock is needed */
+#endif
+{
+	RXD             *pRxd;          /* pointer to receive descriptors         */
+	struct sk_buff  *pMsg;          /* pointer to message holding frame       */
+	struct sk_buff  *pNewMsg;       /* pointer to new message for frame copy  */
+	SK_MBUF         *pRlmtMbuf;     /* ptr to buffer for giving frame to RLMT */
+	SK_EVPARA        EvPara;        /* an event parameter union        */	
+	SK_U32           Control;       /* control field of descriptor     */
+	unsigned long    Flags;         /* for spin lock handling          */
+	int              PortIndex = pRxPort->PortIndex;
+	int              FrameLength;   /* total length of received frame  */
+	int              IpFrameLength; /* IP length of the received frame */
+	unsigned int     Offset;
+	unsigned int     NumBytes;
+	unsigned int     RlmtNotifier;
+	SK_BOOL          IsBc;          /* we received a broadcast packet  */
+	SK_BOOL          IsMc;          /* we received a multicast packet  */
+	SK_BOOL          IsBadFrame;    /* the frame received is bad!      */
+	SK_U32           FrameStat;
+	unsigned short   Csum1;
+	unsigned short   Csum2;
+	unsigned short   Type;
+	int              Result;
+	SK_U64           PhysAddr;
+
+rx_start:	
+	/* do forever; exit if BMU_OWN found */
+	for ( pRxd = pRxPort->pRxdRingHead ;
+		  pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
+		  pRxd = pRxd->pNextRxd,
+		  pRxPort->pRxdRingHead = pRxd,
+		  pRxPort->RxdRingFree ++) {
+
+		/*
+		 * For a better understanding of this loop
+		 * Go through every descriptor beginning at the head
+		 * Please note: the ring might be completely received so the OWN bit
+		 * set is not a good crirteria to leave that loop.
+		 * Therefore the RingFree counter is used.
+		 * On entry of this loop pRxd is a pointer to the Rxd that needs
+		 * to be checked next.
+		 */
+
+		Control = pRxd->RBControl;
+	
+#ifdef CONFIG_SK98LIN_NAPI
+		if (*WorkDone >= WorkToDo) {
+			break;
+		}
+		(*WorkDone)++;
+#endif
+
+		/* check if this descriptor is ready */
+		if ((Control & BMU_OWN) != 0) {
+			/* this descriptor is not yet ready */
+			/* This is the usual end of the loop */
+			/* We don't need to start the ring again */
+			FillRxRing(pAC, pRxPort);
+			return;
+		}
+
+		/* get length of frame and check it */
+		FrameLength = Control & BMU_BBC;
+		if (FrameLength > pRxPort->RxBufSize) {
+			goto rx_failed;
+		}
+
+		/* check for STF and EOF */
+		if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
+			goto rx_failed;
+		}
+
+		/* here we have a complete frame in the ring */
+		pMsg = pRxd->pMBuf;
+
+		FrameStat = pRxd->FrameStat;
+
+		/* check for frame length mismatch */
+#define XMR_FS_LEN_SHIFT	18
+#define GMR_FS_LEN_SHIFT	16
+		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+			if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
+				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+					SK_DBGCAT_DRV_RX_PROGRESS,
+					("skge: Frame length mismatch (%u/%u).\n",
+					FrameLength,
+					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+				goto rx_failed;
+			}
+		} else {
+			if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
+				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+					SK_DBGCAT_DRV_RX_PROGRESS,
+					("skge: Frame length mismatch (%u/%u).\n",
+					FrameLength,
+					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+				goto rx_failed;
+			}
+		}
+
+		/* Set Rx Status */
+		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+			IsBc = (FrameStat & XMR_FS_BC) != 0;
+			IsMc = (FrameStat & XMR_FS_MC) != 0;
+			IsBadFrame = (FrameStat &
+				(XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
+		} else {
+			IsBc = (FrameStat & GMR_FS_BC) != 0;
+			IsMc = (FrameStat & GMR_FS_MC) != 0;
+			IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
+							((FrameStat & GMR_FS_RX_OK) == 0));
+		}
+
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
+			("Received frame of length %d on port %d\n",
+			FrameLength, PortIndex));
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
+			("Number of free rx descriptors: %d\n",
+			pRxPort->RxdRingFree));
+/* DumpMsg(pMsg, "Rx");	*/
+
+		if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
+			/* there is a receive error in this frame */
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_RX_PROGRESS,
+				("skge: Error in received frame, dropped!\n"
+				"Control: %x\nRxStat: %x\n",
+				Control, FrameStat));
+
+			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+			PhysAddr |= (SK_U64) pRxd->VDataLow;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
+			pci_dma_sync_single(pAC->PciDev,
+						(dma_addr_t) PhysAddr,
+						FrameLength,
+						PCI_DMA_FROMDEVICE);
+#else
+			pci_dma_sync_single_for_cpu(pAC->PciDev,
+						(dma_addr_t) PhysAddr,
+						FrameLength,
+						PCI_DMA_FROMDEVICE);
+#endif
+			ReQueueRxBuffer(pAC, pRxPort, pMsg,
+				pRxd->VDataHigh, pRxd->VDataLow);
+
+			continue;
+		}
+
+		/*
+		 * if short frame then copy data to reduce memory waste
+		 */
+		if ((FrameLength < SK_COPY_THRESHOLD) &&
+			((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {
+			/*
+			 * Short frame detected and allocation successfull
+			 */
+			/* use new skb and copy data */
+			skb_reserve(pNewMsg, 2);
+			skb_put(pNewMsg, FrameLength);
+			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+			PhysAddr |= (SK_U64) pRxd->VDataLow;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
+			pci_dma_sync_single(pAC->PciDev,
+						(dma_addr_t) PhysAddr,
+						FrameLength,
+						PCI_DMA_FROMDEVICE);
+#else
+			pci_dma_sync_single_for_device(pAC->PciDev,
+						(dma_addr_t) PhysAddr,
+						FrameLength,
+						PCI_DMA_FROMDEVICE);
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
+			skb_copy_to_linear_data(pNewMsg, pMsg->data,
+				FrameLength);
+#else
+			eth_copy_and_sum(pNewMsg, pMsg->data,
+				FrameLength, 0);
+#endif
+			ReQueueRxBuffer(pAC, pRxPort, pMsg,
+				pRxd->VDataHigh, pRxd->VDataLow);
+
+			pMsg = pNewMsg;
+
+		} else {
+			/*
+			 * if large frame, or SKB allocation failed, pass
+			 * the SKB directly to the networking
+			 */
+			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+			PhysAddr |= (SK_U64) pRxd->VDataLow;
+
+			/* release the DMA mapping */
+			pci_unmap_single(pAC->PciDev,
+					 PhysAddr,
+					 pRxPort->RxBufSize - 2,
+					 PCI_DMA_FROMDEVICE);
+			skb_put(pMsg, FrameLength); /* set message len */
+			pMsg->ip_summed = CHECKSUM_NONE; /* initial default */
+
+			if (pRxPort->UseRxCsum) {
+				Type = ntohs(*((short*)&pMsg->data[12]));
+				if (Type == 0x800) {
+					IpFrameLength = (int) ntohs((unsigned short)
+							((unsigned short *) pMsg->data)[8]);
+					if ((FrameLength - IpFrameLength) == 0xe) {
+						Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
+						Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
+						if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) &&
+							(pAC->GIni.GIChipId == CHIP_ID_GENESIS)) ||
+							(pAC->ChipsetType)) {
+							Result = SkCsGetReceiveInfo(pAC, &pMsg->data[14],
+								Csum1, Csum2, PortIndex, IpFrameLength);
+							if ((Result == SKCS_STATUS_IP_FRAGMENT) ||
+							    (Result == SKCS_STATUS_IP_CSUM_OK)  ||
+							    (Result == SKCS_STATUS_TCP_CSUM_OK) ||
+							    (Result == SKCS_STATUS_UDP_CSUM_OK)) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+								pMsg->ip_summed = CHECKSUM_COMPLETE;
+								pMsg->csum = Csum1 & 0xffff;
+#else
+								pMsg->ip_summed = CHECKSUM_UNNECESSARY;
+#endif
+							} else if ((Result == SKCS_STATUS_TCP_CSUM_ERROR)    ||
+							           (Result == SKCS_STATUS_UDP_CSUM_ERROR)    ||
+							           (Result == SKCS_STATUS_IP_CSUM_ERROR_UDP) ||
+							           (Result == SKCS_STATUS_IP_CSUM_ERROR_TCP) ||
+							           (Result == SKCS_STATUS_IP_CSUM_ERROR)) {
+								/* HW Checksum error */
+								SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+								SK_DBGCAT_DRV_RX_PROGRESS,
+								("skge: CRC error. Frame dropped!\n"));
+								goto rx_failed;
+							} else {
+								pMsg->ip_summed = CHECKSUM_NONE;
+							}
+						}/* checksumControl calculation valid */
+					} /* Frame length check */
+				} /* IP frame */
+			} /* pRxPort->UseRxCsum */
+		} /* frame > SK_COPY_TRESHOLD */
+		
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("V"));
+		RlmtNotifier = SK_RLMT_RX_PROTOCOL;
+		SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
+					IsBc, &Offset, &NumBytes);
+		if (NumBytes != 0) {
+			SK_RLMT_LOOKAHEAD(pAC,PortIndex,&pMsg->data[Offset],
+						IsBc,IsMc,&RlmtNotifier);
+		}
+		if (RlmtNotifier == SK_RLMT_RX_PROTOCOL) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("W"));
+			/* send up only frames from active port */
+			if ((PortIndex == pAC->ActivePort)||(pAC->RlmtNets == 2)) {
+				SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
+#ifdef xDEBUG
+				DumpMsg(pMsg, "Rx");
+#endif
+				SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,FrameLength,PortIndex);
+				pMsg->dev = pAC->dev[PortIndex];
+				pMsg->protocol = eth_type_trans(pMsg,pAC->dev[PortIndex]);
+				netif_rx(pMsg); /* frame for upper layer */
+				pAC->dev[PortIndex]->last_rx = jiffies;
+			} else {
+				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+					SK_DBGCAT_DRV_RX_PROGRESS,("D"));
+				DEV_KFREE_SKB(pMsg); /* drop frame */
+			}
+		} else { /* packet for RLMT stack */
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_RX_PROGRESS,("R"));
+			pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
+				pAC->IoBase, FrameLength);
+			if (pRlmtMbuf != NULL) {
+				pRlmtMbuf->pNext = NULL;
+				pRlmtMbuf->Length = FrameLength;
+				pRlmtMbuf->PortIdx = PortIndex;
+				EvPara.pParaPtr = pRlmtMbuf;
+				memcpy((char*)(pRlmtMbuf->pData),
+					   (char*)(pMsg->data),
+					   FrameLength);
+
+				/* SlowPathLock needed? */
+				if (SlowPathLock == SK_TRUE) {
+					spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+					SkEventQueue(pAC, SKGE_RLMT,
+						SK_RLMT_PACKET_RECEIVED,
+						EvPara);
+					pAC->CheckQueue = SK_TRUE;
+					spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+				} else {
+					SkEventQueue(pAC, SKGE_RLMT,
+						SK_RLMT_PACKET_RECEIVED,
+						EvPara);
+					pAC->CheckQueue = SK_TRUE;
+				}
+
+				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+					SK_DBGCAT_DRV_RX_PROGRESS,("Q"));
+			}
+			if ((pAC->dev[PortIndex]->flags & (IFF_PROMISC | IFF_ALLMULTI)) ||
+			    (RlmtNotifier & SK_RLMT_RX_PROTOCOL)) {
+				pMsg->dev = pAC->dev[PortIndex];
+				pMsg->protocol = eth_type_trans(pMsg,pAC->dev[PortIndex]);
+#ifdef CONFIG_SK98LIN_NAPI
+				netif_receive_skb(pMsg);
+#else
+				netif_rx(pMsg);
+#endif
+				pAC->dev[PortIndex]->last_rx = jiffies;
+			} else {
+				DEV_KFREE_SKB(pMsg);
+			}
+		} /* if packet for RLMT stack */
+	} /* for ... scanning the RXD ring */
+
+	/* RXD ring is empty -> fill and restart */
+	FillRxRing(pAC, pRxPort);
+	return;
+
+rx_failed:
+	/* remove error frame */
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
+		("Schrottdescriptor, length: 0x%x\n", FrameLength));
+
+	/* release the DMA mapping */
+
+	PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+	PhysAddr |= (SK_U64) pRxd->VDataLow;
+	pci_unmap_page(pAC->PciDev,
+			 PhysAddr,
+			 pRxPort->RxBufSize - 2,
+			 PCI_DMA_FROMDEVICE);
+	DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
+	pRxd->pMBuf = NULL;
+	pRxPort->RxdRingFree++;
+	pRxPort->pRxdRingHead = pRxd->pNextRxd;
+	goto rx_start;
+
+} /* ReceiveIrq */
+
+/*****************************************************************************
+ *
+ * 	ClearRxRing - remove all buffers from the receive ring
+ *
+ * Description:
+ *	This function removes all receive buffers from the ring.
+ *	The receive BMU must be stopped before calling this function.
+ *
+ * Returns: N/A
+ */
+static void ClearRxRing(
+SK_AC	*pAC,		/* pointer to adapter context */
+RX_PORT	*pRxPort)	/* pointer to rx port struct */
+{
+RXD		*pRxd;	/* pointer to the current descriptor */
+unsigned long	Flags;
+SK_U64		PhysAddr;
+
+	if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
+		return;
+	}
+	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
+	pRxd = pRxPort->pRxdRingHead;
+	do {
+		if (pRxd->pMBuf != NULL) {
+
+			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+			PhysAddr |= (SK_U64) pRxd->VDataLow;
+			pci_unmap_page(pAC->PciDev,
+					 PhysAddr,
+					 pRxPort->RxBufSize - 2,
+					 PCI_DMA_FROMDEVICE);
+			DEV_KFREE_SKB(pRxd->pMBuf);
+			pRxd->pMBuf = NULL;
+		}
+		pRxd->RBControl &= BMU_OWN;
+		pRxd = pRxd->pNextRxd;
+		pRxPort->RxdRingFree++;
+	} while (pRxd != pRxPort->pRxdRingTail);
+	pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;
+	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
+} /* ClearRxRing */
+
+/*****************************************************************************
+ *
+ *	ClearTxRing - remove all buffers from the transmit ring
+ *
+ * Description:
+ *	This function removes all transmit buffers from the ring.
+ *	The transmit BMU must be stopped before calling this function
+ *	and transmitting at the upper level must be disabled.
+ *	The BMU own bit of all descriptors is cleared, the rest is
+ *	done by calling FreeTxDescriptors.
+ *
+ * Returns: N/A
+ */
+static void ClearTxRing(
+SK_AC	*pAC,		/* pointer to adapter context */
+TX_PORT	*pTxPort)	/* pointer to tx prt struct */
+{
+TXD		*pTxd;		/* pointer to the current descriptor */
+int		i;
+unsigned long	Flags;
+
+	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+	pTxd = pTxPort->pTxdRingHead;
+	for (i=0; i<pAC->TxDescrPerRing; i++) {
+		pTxd->TBControl &= ~BMU_OWN;
+		pTxd = pTxd->pNextTxd;
+	}
+	FreeTxDescriptors(pAC, pTxPort);
+	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+} /* ClearTxRing */
+
+/*****************************************************************************
+ *
+ * 	SkGeSetMacAddr - Set the hardware MAC address
+ *
+ * Description:
+ *	This function sets the MAC address used by the adapter.
+ *
+ * Returns:
+ *	0, if everything is ok
+ *	!=0, on error
+ */
+static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
+{
+
+DEV_NET *pNet = (DEV_NET*)netdev_priv(dev);
+SK_AC	*pAC = pNet->pAC;
+int	Ret;
+
+struct sockaddr	*addr = p;
+unsigned long	Flags;
+	
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeSetMacAddr starts now...\n"));
+
+	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
+	
+	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+
+	if (pAC->RlmtNets == 2)
+		Ret = SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
+			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
+	else
+		Ret = SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
+			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
+	
+	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+
+	if (Ret != SK_ADDR_OVERRIDE_SUCCESS)
+		return -EBUSY;
+
+	return 0;
+} /* SkGeSetMacAddr */
+
+
+/*****************************************************************************
+ *
+ * 	SkGeSetRxMode - set receive mode
+ *
+ * Description:
+ *	This function sets the receive mode of an adapter. The adapter
+ *	supports promiscuous mode, allmulticast mode and a number of
+ *	multicast addresses. If more multicast addresses the available
+ *	are selected, a hash function in the hardware is used.
+ *
+ * Returns:
+ *	0, if everything is ok
+ *	!=0, on error
+ */
+static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
+{
+
+DEV_NET		*pNet;
+SK_AC		*pAC;
+
+struct dev_mc_list	*pMcList;
+int			i;
+int			PortIdx;
+unsigned long		Flags;
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeSetRxMode starts now... "));
+
+	pNet = (DEV_NET*)netdev_priv(dev);
+	pAC = pNet->pAC;
+	if (pAC->RlmtNets == 1)
+		PortIdx = pAC->ActivePort;
+	else
+		PortIdx = pNet->NetNr;
+
+	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+	if (dev->flags & IFF_PROMISC) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+			("PROMISCUOUS mode\n"));
+		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+			SK_PROM_MODE_LLC);
+	} else if (dev->flags & IFF_ALLMULTI) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+			("ALLMULTI mode\n"));
+		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+			SK_PROM_MODE_ALL_MC);
+	} else {
+		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+			SK_PROM_MODE_NONE);
+		SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
+
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+			("Number of MC entries: %d ", dev->mc_count));
+		
+		pMcList = dev->mc_list;
+		for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) {
+			SkAddrMcAdd(pAC, pAC->IoBase, PortIdx,
+				(SK_MAC_ADDR*)pMcList->dmi_addr, 0);
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA,
+				("%02x:%02x:%02x:%02x:%02x:%02x\n",
+				pMcList->dmi_addr[0],
+				pMcList->dmi_addr[1],
+				pMcList->dmi_addr[2],
+				pMcList->dmi_addr[3],
+				pMcList->dmi_addr[4],
+				pMcList->dmi_addr[5]));
+		}
+		SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
+	}
+	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+	
+	return;
+} /* SkGeSetRxMode */
+
+
+/*****************************************************************************
+ *
+ * 	SkSetMtuBufferSize - set the MTU buffer to another value
+ *
+ * Description:
+ *	This function sets the new buffers and is called whenever the MTU 
+ *      size is changed
+ *
+ * Returns:
+ *	N/A
+ */
+
+static void SkSetMtuBufferSize(
+SK_AC	*pAC,		/* pointer to adapter context */
+int	PortNr,		/* Port number */
+int	Mtu)		/* pointer to tx prt struct */
+{
+	pAC->RxPort[PortNr].RxBufSize = Mtu + 32;
+
+	/* RxBufSize must be a multiple of 8 */
+	while (pAC->RxPort[PortNr].RxBufSize % 8) {
+		pAC->RxPort[PortNr].RxBufSize = 
+			pAC->RxPort[PortNr].RxBufSize + 1;
+	}
+
+	if (Mtu > ETH_MAX_MTU) {
+		pAC->GIni.GP[PortNr].PPortUsage = SK_JUMBO_LINK;
+	} else {
+		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+			pAC->GIni.GP[PortNr].PPortUsage = SK_MUL_LINK;
+		} else {
+			pAC->GIni.GP[PortNr].PPortUsage = SK_RED_LINK;
+		}
+	}
+
+	return;
+}
+
+
+/*****************************************************************************
+ *
+ * 	SkGeChangeMtu - set the MTU to another value
+ *
+ * Description:
+ *	This function sets is called whenever the MTU size is changed
+ *	(ifconfig mtu xxx dev ethX). If the MTU is bigger than standard
+ *	ethernet MTU size, long frame support is activated.
+ *
+ * Returns:
+ *	0, if everything is ok
+ *	!=0, on error
+ */
+static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
+{
+DEV_NET			*pNet;
+SK_AC			*pAC;
+unsigned long		Flags;
+#ifdef CONFIG_SK98LIN_NAPI
+int			WorkToDo = 1; // min(*budget, dev->quota);
+int			WorkDone = 0;
+#endif
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeChangeMtu starts now...\n"));
+
+	pNet = (DEV_NET*) netdev_priv(dev);
+	pAC  = pNet->pAC;
+
+	/* MTU size outside the spec */
+	if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
+		return -EINVAL;
+	}
+
+	/* MTU > 1500 on yukon FE and FE+ not allowed */
+	if (((pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) ||
+		 (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P))
+		&& (NewMtu > ETH_MAX_MTU)) {
+		return -EINVAL;
+	}
+
+	/* Diag access active */
+	if (pAC->DiagModeActive == DIAG_ACTIVE) {
+		if (pAC->DiagFlowCtrl == SK_FALSE) {
+			return -1; /* still in use, deny any actions of MTU */
+		} else {
+			pAC->DiagFlowCtrl = SK_FALSE;
+		}
+	}
+
+	/* TSO on Yukon Ultra and MTU > 1500 not supported */
+#ifdef NETIF_F_TSO
+#ifdef USE_SK_TSO_FEATURE
+	if (CHIP_ID_YUKON_2(pAC)) {
+		if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) && (NewMtu > ETH_MAX_MTU)) {
+			dev->features &= ~NETIF_F_TSO;
+		} else {
+			dev->features |= NETIF_F_TSO;
+		}
+	}
+#endif
+#endif
+	dev->mtu = NewMtu;
+
+	if (NewMtu < 1500) {
+		return 0;
+	}
+
+	SkSetMtuBufferSize(pAC, pNet->PortNr, NewMtu);
+
+	if(!netif_running(dev)) {
+	/* Preset MTU size if device not ready/running */
+		return 0;
+	}
+
+	/*  Prevent any reconfiguration while changing the MTU 
+	    by disabling any interrupts */
+	SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+
+	/* Notify RLMT that the port has to be stopped */
+	netif_stop_queue(dev);
+	SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
+				pNet->PortNr, -1, SK_TRUE);
+	spin_lock(&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW].TxDesRingLock);
+
+
+	/* Change RxFillLimit to 1 */
+	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+		pAC->RxPort[pNet->PortNr].RxFillLimit = 1;
+	} else {
+		pAC->RxPort[1 - pNet->PortNr].RxFillLimit = 1;
+		pAC->RxPort[pNet->PortNr].RxFillLimit = pAC->RxDescrPerRing -
+					(pAC->RxDescrPerRing / 4);
+	}
+
+	/* clear and reinit the rx rings here, because of new MTU size */
+	if (CHIP_ID_YUKON_2(pAC)) {
+		SkY2PortStop(pAC, pAC->IoBase, pNet->PortNr, SK_STOP_ALL, SK_SOFT_RST);
+		SkY2AllocateRxBuffers(pAC, pAC->IoBase, pNet->PortNr);
+		SkY2PortStart(pAC, pAC->IoBase, pNet->PortNr);
+	} else {
+//		SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, SK_STOP_ALL, SK_SOFT_RST);
+#ifdef CONFIG_SK98LIN_NAPI
+		WorkToDo = 1;
+		ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE, &WorkDone, WorkToDo);
+#else
+		ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
+#endif
+		ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
+		FillRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
+
+		/* Enable transmit descriptor polling */
+		SkGePollTxD(pAC, pAC->IoBase, pNet->PortNr, SK_TRUE);
+		FillRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
+	}
+
+	netif_start_queue(pAC->dev[pNet->PortNr]);
+
+	spin_unlock(&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW].TxDesRingLock);
+
+
+	/* Notify RLMT about the changing and restarting one (or more) ports */
+	SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_START,
+					pNet->PortNr, -1, SK_TRUE);
+
+	/* Enable Interrupts again */
+	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+
+	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+	return 0;
+
+}
+
+
+/*****************************************************************************
+ *
+ * 	SkGeStats - return ethernet device statistics
+ *
+ * Description:
+ *	This function return statistic data about the ethernet device
+ *	to the operating system.
+ *
+ * Returns:
+ *	pointer to the statistic structure.
+ */
+static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
+{
+	DEV_NET		*pNet = (DEV_NET*)netdev_priv(dev);
+	SK_AC		*pAC = pNet->pAC;
+	unsigned long	LateCollisions, ExcessiveCollisions, RxTooLong;
+	unsigned long	Flags; /* for spin lock */
+    	SK_U32		MaxNumOidEntries, Oid, Len;
+	char		Buf[8];
+	struct {
+		SK_U32         Oid;
+		unsigned long *pVar;
+	} Vars[] = {
+		{ OID_SKGE_STAT_TX_LATE_COL,   &LateCollisions               },
+		{ OID_SKGE_STAT_TX_EXCESS_COL, &ExcessiveCollisions          },
+		{ OID_SKGE_STAT_RX_TOO_LONG,   &RxTooLong                    },
+		{ OID_SKGE_STAT_RX,            &pAC->stats.rx_packets        },
+		{ OID_SKGE_STAT_TX,            &pAC->stats.tx_packets        },
+		{ OID_SKGE_STAT_RX_OCTETS,     &pAC->stats.rx_bytes          },
+		{ OID_SKGE_STAT_TX_OCTETS,     &pAC->stats.tx_bytes          },
+		{ OID_SKGE_RX_NO_BUF_CTS,      &pAC->stats.rx_dropped        },
+		{ OID_SKGE_TX_NO_BUF_CTS,      &pAC->stats.tx_dropped        },
+		{ OID_SKGE_STAT_RX_MULTICAST,  &pAC->stats.multicast         },
+		{ OID_SKGE_STAT_RX_RUNT,       &pAC->stats.rx_length_errors  },
+		{ OID_SKGE_STAT_RX_FCS,        &pAC->stats.rx_crc_errors     },
+		{ OID_SKGE_STAT_RX_FRAMING,    &pAC->stats.rx_frame_errors   },
+		{ OID_SKGE_STAT_RX_OVERFLOW,   &pAC->stats.rx_over_errors    },
+		{ OID_SKGE_STAT_RX_MISSED,     &pAC->stats.rx_missed_errors  },
+		{ OID_SKGE_STAT_TX_CARRIER,    &pAC->stats.tx_carrier_errors },
+		{ OID_SKGE_STAT_TX_UNDERRUN,   &pAC->stats.tx_fifo_errors    },
+	};
+	
+	if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
+	    (pAC->BoardLevel     == SK_INIT_RUN)) {
+		memset(&pAC->stats, 0x00, sizeof(pAC->stats)); /* clean first */
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+
+    		MaxNumOidEntries = sizeof(Vars) / sizeof(Vars[0]);
+    		for (Oid = 0; Oid < MaxNumOidEntries; Oid++) {
+			if (SkPnmiGetVar(pAC,pAC->IoBase, Vars[Oid].Oid,
+				&Buf, &Len, 1, pNet->NetNr) != SK_PNMI_ERR_OK) {
+				memset(Buf, 0x00, sizeof(Buf));
+			}
+			*Vars[Oid].pVar = (unsigned long) (*((SK_U64 *) Buf));
+		}
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+
+		pAC->stats.collisions =	LateCollisions + ExcessiveCollisions;
+		pAC->stats.tx_errors =	pAC->stats.tx_carrier_errors +
+					pAC->stats.tx_fifo_errors;
+		pAC->stats.rx_errors =	pAC->stats.rx_length_errors + 
+					pAC->stats.rx_crc_errors +
+					pAC->stats.rx_frame_errors + 
+					pAC->stats.rx_over_errors +
+					pAC->stats.rx_missed_errors;
+
+		if (dev->mtu > ETH_MAX_MTU) {
+			pAC->stats.rx_errors = pAC->stats.rx_errors - RxTooLong;
+		}
+	}
+
+	return(&pAC->stats);
+} /* SkGeStats */
+
+/*****************************************************************************
+ *
+ * 	SkGeIoctl - IO-control function
+ *
+ * Description:
+ *	This function is called if an ioctl is issued on the device.
+ *	There are three subfunction for reading, writing and test-writing
+ *	the private MIB data structure (usefull for SysKonnect-internal tools).
+ *
+ * Returns:
+ *	0, if everything is ok
+ *	!=0, on error
+ */
+static int SkGeIoctl(
+struct SK_NET_DEVICE *dev,  /* the device the IOCTL is to be performed on   */
+struct ifreq         *rq,   /* additional request structure containing data */
+int                   cmd)  /* requested IOCTL command number               */
+{
+	DEV_NET          *pNet = (DEV_NET*)netdev_priv(dev);
+	SK_AC            *pAC  = pNet->pAC;
+	struct pci_dev   *pdev = NULL;
+	void             *pMemBuf;
+	SK_GE_IOCTL       Ioctl;
+	unsigned long     Flags; /* for spin lock */
+	unsigned int      Err = 0;
+	unsigned int      Length = 0;
+	int               HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
+	int               Size = 0;
+	int               Ret = 0;
+
+#ifdef USE_ASF_DASH_FW
+       DRIVER_INTERFACE  DInterfaceFW;
+       struct in_device *pindev;
+       struct inet6_dev *iface;
+       struct inet6_ifaddr *address_list;
+       struct in6_addr *address;
+       SK_U32 i;
+#if 0
+       SK_U8 *charPtr;
+#endif
+       SK_U32 savedaddr;
+#endif
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeIoctl starts now...\n"));
+
+	if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
+		return -EFAULT;
+	}
+
+#ifdef USE_ASF_DASH_FW
+	if(copy_from_user(&DInterfaceFW, rq->ifr_data, sizeof(DRIVER_INTERFACE))) {
+		return -EFAULT;
+	}
+#endif
+
+	switch(cmd) {
+#ifndef ENABLE_FUTURE_ETH
+	case SIOCETHTOOL:
+		return SkEthIoctl(dev, rq );
+#endif
+	case SK_IOCTL_SETMIB:     /* FALL THRU */
+	case SK_IOCTL_PRESETMIB:  /* FALL THRU (if capable!) */
+		if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ 	case SK_IOCTL_GETMIB:
+		if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
+			Ioctl.Len<sizeof(pAC->PnmiStruct)?
+			Ioctl.Len : sizeof(pAC->PnmiStruct))) {
+			return -EFAULT;
+		}
+		Size = SkGeIocMib(pNet, Ioctl.Len, cmd);
+		if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct,
+			Ioctl.Len<Size? Ioctl.Len : Size)) {
+			return -EFAULT;
+		}
+		Ioctl.Len = Size;
+		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+			return -EFAULT;
+		}
+		break;
+	case SK_IOCTL_GEN:
+		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+			Length = Ioctl.Len;
+		} else {
+			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
+		}
+		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+			return -ENOMEM;
+		}
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+			Err = -EFAULT;
+			goto fault_gen;
+		}
+		if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
+			Err = -EFAULT;
+			goto fault_gen;
+		}
+		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+			Err = -EFAULT;
+			goto fault_gen;
+		}
+		Ioctl.Len = Length;
+		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+			Err = -EFAULT;
+			goto fault_gen;
+		}
+fault_gen:
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+		kfree(pMemBuf); /* cleanup everything */
+		break;
+	case SK_IOCTL_DIAG:
+		if (!capable(CAP_NET_ADMIN)) return -EPERM;
+		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+			Length = Ioctl.Len;
+		} else {
+			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
+		}
+		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+			return -ENOMEM;
+		}
+		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+			Err = -EFAULT;
+			goto fault_diag;
+		}
+		pdev = pAC->PciDev;
+		Length = 3 * sizeof(SK_U32);  /* Error, Bus and Device */
+		/* 
+		** While coding this new IOCTL interface, only a few lines of code
+		** are to to be added. Therefore no dedicated function has been 
+		** added. If more functionality is added, a separate function 
+		** should be used...
+		*/
+		* ((SK_U32 *)pMemBuf) = 0;
+		* ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
+		* ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
+
+		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+			Err = -EFAULT;
+			goto fault_diag;
+		}
+		Ioctl.Len = Length;
+		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+			Err = -EFAULT;
+			goto fault_diag;
+		}
+fault_diag:
+		kfree(pMemBuf); /* cleanup everything */
+		break;
+
+#ifdef USE_ASF_DASH_FW
+	case SK_IOCTL_IPTOFW:
+	  pindev = (struct in_device*) dev->ip_ptr;
+
+	  if(netif_running(dev)) {
+	    if (dev->ip_ptr != NULL) {
+	      /* Now we extract the device IP address */
+	      u32 ip_address = htonl((pindev->ifa_list)->ifa_address);
+	      unsigned char *pip_address = (char*)&ip_address;
+	      pAC->IpAddr[3] = (unsigned char)pip_address[0];
+	      pAC->IpAddr[2] = (unsigned char)pip_address[1];
+	      pAC->IpAddr[1] = (unsigned char)pip_address[2];
+	      pAC->IpAddr[0] = (unsigned char)pip_address[3];
+	      pAC->ForceFWIPUpdate = 1;
+	    } else {
+	      /* This should never happen... But if it happens it is only bad in case we are running DASH */
+	    pAC->IpAddr[3] = 0;
+	    pAC->IpAddr[2] = 0;
+	    pAC->IpAddr[1] = 0;
+	    pAC->IpAddr[0] = 0;
+	    }
+	    
+	    savedaddr = 0;
+	    
+	    /* Next we extract the IPv6 address */
+	    iface = (struct inet6_dev*)dev->ip6_ptr;
+	    if (iface != NULL) {
+	      address_list = iface->addr_list;
+	    while (address_list != NULL) {
+	      address = &address_list->addr;
+	      
+	      for (i=0; i<16; i++)
+		pAC->IpV6Addr[i+savedaddr*16] = (unsigned char) address->s6_addr[i];	    
+	      
+	      savedaddr++;
+	      
+	      address_list = address_list->if_next;
+	    }
+	    pAC->ForceFWIPUpdate = 1;
+	    } else {
+	      // So eventually there is no IpV6 support in this kernel.
+	      for (i=0; i<16; i++)
+		pAC->IpV6Addr[i] = 0;
+	    }
+	    
+	    rq->ifr_name[0] = 'A';
+	    rq->ifr_name[1] = 'C';
+	    rq->ifr_name[2] = 'K';
+	  } else {
+	    rq->ifr_name[0] = 'D';
+	    rq->ifr_name[1] = 'E';
+	    rq->ifr_name[2] = 'C';
+	  }
+	  
+	  break;
+	case SK_IOCTL_PATTERNTOFW:
+	  memcpy(&pAC->NewPatternDef, &DInterfaceFW, sizeof(DInterfaceFW));
+
+#if 0
+	  charPtr = (SK_U8*) &pAC->NewPatternDef.New_Pattern;
+	  for (i=0; i<= sizeof(STR_YASF_CANON);i++) {
+	    printk("%02x ", charPtr[i]);
+	    if ((i+1)%16==0)
+	      printk("\n");
+	  }
+	  printk("\n");
+#endif
+
+#if 0
+	  printk("sk98lin: Patterns to be downloaded: ");
+	  for (i=0; i<26; i++)
+	    if (pAC->NewPatternDef.ElementArrayDl[i] != 0x00)
+	      printk("%c ", pAC->NewPatternDef.ElementArrayDl[i]);
+	  printk("\n");
+	  printk("sk98lin: Patterns to be enabled: ");
+	  for (i=0; i<26; i++)
+	    if (pAC->NewPatternDef.ElementArrayEn[i] != 0x00)
+	      printk("%c ", pAC->NewPatternDef.ElementArrayEn[i]);
+	  printk("\n");
+#endif
+
+	  pAC->RecvNewPattern = 1;
+
+	  break;
+#endif
+	default:
+		Err = -EOPNOTSUPP;
+	}
+
+	return(Err);
+
+} /* SkGeIoctl */
+
+
+/*****************************************************************************
+ *
+ * 	SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message
+ *
+ * Description:
+ *	This function reads/writes the MIB data using PNMI (Private Network
+ *	Management Interface).
+ *	The destination for the data must be provided with the
+ *	ioctl call and is given to the driver in the form of
+ *	a user space address.
+ *	Copying from the user-provided data area into kernel messages
+ *	and back is done by copy_from_user and copy_to_user calls in
+ *	SkGeIoctl.
+ *
+ * Returns:
+ *	returned size from PNMI call
+ */
+static int SkGeIocMib(
+DEV_NET		*pNet,	/* pointer to the adapter context */
+unsigned int	Size,	/* length of ioctl data */
+int		mode)	/* flag for set/preset */
+{
+	SK_AC		*pAC = pNet->pAC;
+	unsigned long	Flags;  /* for spin lock */
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("SkGeIocMib starts now...\n"));
+
+	/* access MIB */
+	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+	switch(mode) {
+	case SK_IOCTL_GETMIB:
+		SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+			pNet->NetNr);
+		break;
+	case SK_IOCTL_PRESETMIB:
+		SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+			pNet->NetNr);
+		break;
+	case SK_IOCTL_SETMIB:
+		SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+			pNet->NetNr);
+		break;
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+		("MIB data access succeeded\n"));
+	return (Size);
+} /* SkGeIocMib */
+
+
+/*****************************************************************************
+ *
+ * 	GetConfiguration - read configuration information
+ *
+ * Description:
+ *	This function reads per-adapter configuration information from
+ *	the options provided on the command line.
+ *
+ * Returns:
+ *	none
+ */
+static void GetConfiguration(
+SK_AC	*pAC)	/* pointer to the adapter context structure */
+{
+SK_I32	Port;		/* preferred port */
+SK_BOOL	AutoSet;
+SK_BOOL DupSet;
+int	LinkSpeed		= SK_LSPEED_AUTO;	/* Link speed */
+int	AutoNeg			= 1;			/* autoneg off (0) or on (1) */
+int	DuplexCap		= 0;			/* 0=both,1=full,2=half */
+int	FlowCtrl		= SK_FLOW_MODE_SYM_OR_REM;	/* FlowControl  */
+int	MSMode			= SK_MS_MODE_AUTO;	/* master/slave mode    */
+int	IrqModMaskOffset	= 6;			/* all ints moderated=default */
+
+SK_BOOL IsConTypeDefined	= SK_TRUE;
+SK_BOOL IsLinkSpeedDefined	= SK_TRUE;
+SK_BOOL IsFlowCtrlDefined	= SK_TRUE;
+SK_BOOL IsRoleDefined		= SK_TRUE;
+SK_BOOL IsModeDefined		= SK_TRUE;
+/*
+ *	The two parameters AutoNeg. and DuplexCap. map to one configuration
+ *	parameter. The mapping is described by this table:
+ *	DuplexCap ->	|	both	|	full	|	half	|
+ *	AutoNeg		|		|		|		|
+ *	-----------------------------------------------------------------
+ *	Off		|    illegal	|	Full	|	Half	|
+ *	-----------------------------------------------------------------
+ *	On		|   AutoBoth	|   AutoFull	|   AutoHalf	|
+ *	-----------------------------------------------------------------
+ *	Sense		|   AutoSense	|   AutoSense	|   AutoSense	|
+ */
+int	Capabilities[3][3] =
+		{ {                -1, SK_LMODE_FULL     , SK_LMODE_HALF     },
+		  {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
+		  {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
+
+SK_U32	IrqModMask[7][2] =
+		{ { IRQ_MASK_RX_ONLY , Y2_DRIVER_IRQS  },
+		  { IRQ_MASK_TX_ONLY , Y2_DRIVER_IRQS  },
+		  { IRQ_MASK_SP_ONLY , Y2_SPECIAL_IRQS },
+		  { IRQ_MASK_SP_RX   , Y2_IRQ_MASK     },
+		  { IRQ_MASK_TX_RX   , Y2_DRIVER_IRQS  },
+		  { IRQ_MASK_SP_TX   , Y2_IRQ_MASK     },
+		  { IRQ_MASK_RX_TX_SP, Y2_IRQ_MASK     } };
+
+#define DC_BOTH	0
+#define DC_FULL 1
+#define DC_HALF 2
+#define AN_OFF	0
+#define AN_ON	1
+#define AN_SENS	2
+#define M_CurrPort pAC->GIni.GP[Port]
+
+
+	/*
+	** Set the default values first for both ports!
+	*/
+	for (Port = 0; Port < SK_MAX_MACS; Port++) {
+		M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+		M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+		M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+		M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
+	}
+
+	/*
+	** Check merged parameter ConType. If it has not been used,
+	** verify any other parameter (e.g. AutoNeg) and use default values. 
+	**
+	** Stating both ConType and other lowlevel link parameters is also
+	** possible. If this is the case, the passed ConType-parameter is 
+	** overwritten by the lowlevel link parameter.
+	**
+	** The following settings are used for a merged ConType-parameter:
+	**
+	** ConType   DupCap   AutoNeg   FlowCtrl      Role      Speed
+	** -------   ------   -------   --------   ----------   -----
+	**  Auto      Both      On      SymOrRem      Auto       Auto
+	**  1000FD    Full      Off       None      <ignored>    1000
+	**  100FD     Full      Off       None      <ignored>    100
+	**  100HD     Half      Off       None      <ignored>    100
+	**  10FD      Full      Off       None      <ignored>    10
+	**  10HD      Half      Off       None      <ignored>    10
+	** 
+	** This ConType parameter is used for all ports of the adapter!
+	*/
+	if ( (ConType != NULL)                && 
+	     (pAC->Index < SK_MAX_CARD_PARAM) &&
+	     (ConType[pAC->Index] != NULL) ) {
+
+		/* Check chipset family */
+		if ((!pAC->ChipsetType) && 
+			(strcmp(ConType[pAC->Index],"Auto")!=0) &&
+			(strcmp(ConType[pAC->Index],"")!=0)) {
+			/* Set the speed parameter back */
+			printk("sk98lin: Illegal value \"%s\" " 
+				"for ConType."
+				" Using Auto.\n", 
+				ConType[pAC->Index]);
+
+			ConType[pAC->Index] = "Auto";	
+		}
+
+		if ((pAC->ChipsetType) && 
+			(pAC->GIni.GICopperType != SK_TRUE) && 
+			(strcmp(ConType[pAC->Index],"") != 0) &&
+			(strcmp(ConType[pAC->Index],"1000FD") != 0)) {
+			/* Set the speed parameter back */
+			printk("sk98lin: Illegal value \"%s\" " 
+				"for ConType."
+				" Using Auto.\n", 
+				ConType[pAC->Index]);
+			IsConTypeDefined = SK_FALSE;
+			ConType[pAC->Index] = "Auto";
+		}	
+
+		if (strcmp(ConType[pAC->Index],"")==0) {
+			IsConTypeDefined = SK_FALSE; /* No ConType defined */
+		} else if (strcmp(ConType[pAC->Index],"Auto")==0) {
+		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+			M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+			M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
+		    }
+		} else if (strcmp(ConType[pAC->Index],"1000FD")==0) {
+		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+			M_CurrPort.PLinkSpeed    = SK_LSPEED_1000MBPS;
+		    }
+		} else if (strcmp(ConType[pAC->Index],"100FD")==0) {
+		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+			M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
+		    }
+		} else if (strcmp(ConType[pAC->Index],"100HD")==0) {
+		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+			M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
+		    }
+		} else if (strcmp(ConType[pAC->Index],"10FD")==0) {
+		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+			M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
+		    }
+		} else if (strcmp(ConType[pAC->Index],"10HD")==0) {
+		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+			M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
+		    }
+		} else { 
+		    printk("sk98lin: Illegal value \"%s\" for ConType\n", 
+			ConType[pAC->Index]);
+		    IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
+		}
+	} else {
+	    IsConTypeDefined = SK_FALSE; /* No ConType defined */
+	}
+
+	/*
+	** Parse any parameter settings for port A:
+	** a) any LinkSpeed stated?
+	*/
+	if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		Speed_A[pAC->Index] != NULL) {
+		if (strcmp(Speed_A[pAC->Index],"")==0) {
+		    IsLinkSpeedDefined = SK_FALSE;
+		} else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
+		    LinkSpeed = SK_LSPEED_AUTO;
+		} else if (strcmp(Speed_A[pAC->Index],"10")==0) {
+		    LinkSpeed = SK_LSPEED_10MBPS;
+		} else if (strcmp(Speed_A[pAC->Index],"100")==0) {
+		    LinkSpeed = SK_LSPEED_100MBPS;
+		} else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
+		    if ((pAC->PciDev->vendor == 0x11ab ) &&
+		    	((pAC->PciDev->device == 0x4350) ||
+				 (pAC->PciDev->device == 0x4354))) {
+				LinkSpeed = SK_LSPEED_100MBPS;
+				printk("sk98lin: Illegal value \"%s\" for Speed_A.\n"
+					"Gigabit speed not possible with this chip revision!",
+					Speed_A[pAC->Index]);
+			} else {
+				LinkSpeed = SK_LSPEED_1000MBPS;
+		    }
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for Speed_A\n",
+			Speed_A[pAC->Index]);
+		    IsLinkSpeedDefined = SK_FALSE;
+		}
+	} else {
+		if ((pAC->PciDev->vendor == 0x11ab ) && 
+			((pAC->PciDev->device == 0x4350) ||
+			 (pAC->PciDev->device == 0x4354))) {
+			/* Gigabit speed not supported
+			 * Swith to speed 100
+			 */
+			LinkSpeed = SK_LSPEED_100MBPS;
+		} else {
+			IsLinkSpeedDefined = SK_FALSE;
+		}
+	}
+
+	/* 
+	** Check speed parameter: 
+	**    Only copper type adapter and GE V2 cards 
+	*/
+	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
+		((LinkSpeed != SK_LSPEED_AUTO) &&
+		(LinkSpeed != SK_LSPEED_1000MBPS))) {
+		printk("sk98lin: Illegal value for Speed_A. "
+			"Not a copper card or GE V2 card\n    Using "
+			"speed 1000\n");
+		LinkSpeed = SK_LSPEED_1000MBPS;
+	}
+	
+	/*	
+	** Decide whether to set new config value if somethig valid has
+	** been received.
+	*/
+	if (IsLinkSpeedDefined) {
+		pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
+	} 
+
+	/* 
+	** b) Any Autonegotiation and DuplexCapabilities set?
+	**    Please note that both belong together...
+	*/
+	AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
+	AutoSet = SK_FALSE;
+	if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		AutoNeg_A[pAC->Index] != NULL) {
+		AutoSet = SK_TRUE;
+		if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
+		    AutoSet = SK_FALSE;
+		} else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
+		    AutoNeg = AN_ON;
+		} else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
+		    AutoNeg = AN_OFF;
+		} else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
+		    AutoNeg = AN_SENS;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n",
+			AutoNeg_A[pAC->Index]);
+		}
+	}
+
+	DuplexCap = DC_BOTH;
+	DupSet    = SK_FALSE;
+	if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		DupCap_A[pAC->Index] != NULL) {
+		DupSet = SK_TRUE;
+		if (strcmp(DupCap_A[pAC->Index],"")==0) {
+		    DupSet = SK_FALSE;
+		} else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
+		    DuplexCap = DC_BOTH;
+		} else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
+		    DuplexCap = DC_FULL;
+		} else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
+		    DuplexCap = DC_HALF;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for DupCap_A\n",
+			DupCap_A[pAC->Index]);
+		}
+	}
+
+	/* 
+	** Check for illegal combinations 
+	*/
+	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
+		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
+		(DuplexCap == SK_LMODE_STAT_HALF)) &&
+		(pAC->ChipsetType)) {
+		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
+					"    Using Full Duplex.\n");
+				DuplexCap = DC_FULL;
+	}
+
+	if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
+		printk("sk98lin, Port A: DuplexCapabilities"
+			" ignored using Sense mode\n");
+	}
+
+	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
+		printk("sk98lin: Port A: Illegal combination"
+			" of values AutoNeg. and DuplexCap.\n    Using "
+			"Full Duplex\n");
+		DuplexCap = DC_FULL;
+	}
+
+	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
+		DuplexCap = DC_FULL;
+	}
+	
+	if (!AutoSet && DupSet) {
+		AutoNeg = AN_ON;
+	}
+	
+	/* 
+	** set the desired mode 
+	*/
+	if (AutoSet || DupSet) {
+	    pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+	}
+	
+	/* 
+	** c) Any Flowcontrol-parameter set?
+	*/
+	if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		FlowCtrl_A[pAC->Index] != NULL) {
+		if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
+		    IsFlowCtrlDefined = SK_FALSE;
+		} else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
+		    FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+		} else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
+		    FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+		} else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
+		    FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+		} else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
+		    FlowCtrl = SK_FLOW_MODE_NONE;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
+			FlowCtrl_A[pAC->Index]);
+		    IsFlowCtrlDefined = SK_FALSE;
+		}
+	} else {
+	   IsFlowCtrlDefined = SK_FALSE;
+	}
+
+	if (IsFlowCtrlDefined) {
+	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
+		printk("sk98lin: Port A: FlowControl"
+			" impossible without AutoNegotiation,"
+			" disabled\n");
+		FlowCtrl = SK_FLOW_MODE_NONE;
+	    }
+	    pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
+	}
+
+	/*
+	** d) What is with the RoleParameter?
+	*/
+	if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		Role_A[pAC->Index] != NULL) {
+		if (strcmp(Role_A[pAC->Index],"")==0) {
+		   IsRoleDefined = SK_FALSE;
+		} else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
+		    MSMode = SK_MS_MODE_AUTO;
+		} else if (strcmp(Role_A[pAC->Index],"Master")==0) {
+		    MSMode = SK_MS_MODE_MASTER;
+		} else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
+		    MSMode = SK_MS_MODE_SLAVE;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for Role_A\n",
+			Role_A[pAC->Index]);
+		    IsRoleDefined = SK_FALSE;
+		}
+	} else {
+	   IsRoleDefined = SK_FALSE;
+	}
+
+	if (IsRoleDefined == SK_TRUE) {
+	    pAC->GIni.GP[0].PMSMode = MSMode;
+	}
+	
+
+	
+	/* 
+	** Parse any parameter settings for port B:
+	** a) any LinkSpeed stated?
+	*/
+	IsConTypeDefined   = SK_TRUE;
+	IsLinkSpeedDefined = SK_TRUE;
+	IsFlowCtrlDefined  = SK_TRUE;
+	IsModeDefined      = SK_TRUE;
+
+	if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		Speed_B[pAC->Index] != NULL) {
+		if (strcmp(Speed_B[pAC->Index],"")==0) {
+		    IsLinkSpeedDefined = SK_FALSE;
+		} else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
+		    LinkSpeed = SK_LSPEED_AUTO;
+		} else if (strcmp(Speed_B[pAC->Index],"10")==0) {
+		    LinkSpeed = SK_LSPEED_10MBPS;
+		} else if (strcmp(Speed_B[pAC->Index],"100")==0) {
+		    LinkSpeed = SK_LSPEED_100MBPS;
+		} else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
+		    LinkSpeed = SK_LSPEED_1000MBPS;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for Speed_B\n",
+			Speed_B[pAC->Index]);
+		    IsLinkSpeedDefined = SK_FALSE;
+		}
+	} else {
+	    IsLinkSpeedDefined = SK_FALSE;
+	}
+
+	/* 
+	** Check speed parameter:
+	**    Only copper type adapter and GE V2 cards 
+	*/
+	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
+		((LinkSpeed != SK_LSPEED_AUTO) &&
+		(LinkSpeed != SK_LSPEED_1000MBPS))) {
+		printk("sk98lin: Illegal value for Speed_B. "
+			"Not a copper card or GE V2 card\n    Using "
+			"speed 1000\n");
+		LinkSpeed = SK_LSPEED_1000MBPS;
+	}
+
+	/*      
+	** Decide whether to set new config value if somethig valid has
+	** been received.
+	*/
+	if (IsLinkSpeedDefined) {
+	    pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
+	}
+
+	/* 
+	** b) Any Autonegotiation and DuplexCapabilities set?
+	**    Please note that both belong together...
+	*/
+	AutoNeg = AN_SENS; /* default: do auto Sense */
+	AutoSet = SK_FALSE;
+	if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		AutoNeg_B[pAC->Index] != NULL) {
+		AutoSet = SK_TRUE;
+		if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
+		    AutoSet = SK_FALSE;
+		} else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
+		    AutoNeg = AN_ON;
+		} else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
+		    AutoNeg = AN_OFF;
+		} else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
+		    AutoNeg = AN_SENS;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n",
+			AutoNeg_B[pAC->Index]);
+		}
+	}
+
+	DuplexCap = DC_BOTH;
+	DupSet    = SK_FALSE;
+	if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		DupCap_B[pAC->Index] != NULL) {
+		DupSet = SK_TRUE;
+		if (strcmp(DupCap_B[pAC->Index],"")==0) {
+		    DupSet = SK_FALSE;
+		} else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
+		    DuplexCap = DC_BOTH;
+		} else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
+		    DuplexCap = DC_FULL;
+		} else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
+		    DuplexCap = DC_HALF;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for DupCap_B\n",
+			DupCap_B[pAC->Index]);
+		}
+	}
+
+	
+	/* 
+	** Check for illegal combinations 
+	*/
+	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
+		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
+		(DuplexCap == SK_LMODE_STAT_HALF)) &&
+		(pAC->ChipsetType)) {
+		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
+					"    Using Full Duplex.\n");
+				DuplexCap = DC_FULL;
+	}
+
+	if (AutoSet && AutoNeg==AN_SENS && DupSet) {
+		printk("sk98lin, Port B: DuplexCapabilities"
+			" ignored using Sense mode\n");
+	}
+
+	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
+		printk("sk98lin: Port B: Illegal combination"
+			" of values AutoNeg. and DuplexCap.\n    Using "
+			"Full Duplex\n");
+		DuplexCap = DC_FULL;
+	}
+
+	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
+		DuplexCap = DC_FULL;
+	}
+	
+	if (!AutoSet && DupSet) {
+		AutoNeg = AN_ON;
+	}
+
+	/* 
+	** set the desired mode 
+	*/
+	if (AutoSet || DupSet) {
+	    pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+	}
+
+	/*
+	** c) Any FlowCtrl parameter set?
+	*/
+	if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		FlowCtrl_B[pAC->Index] != NULL) {
+		if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
+		    IsFlowCtrlDefined = SK_FALSE;
+		} else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
+		    FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+		} else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
+		    FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+		} else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
+		    FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+		} else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
+		    FlowCtrl = SK_FLOW_MODE_NONE;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n",
+			FlowCtrl_B[pAC->Index]);
+		    IsFlowCtrlDefined = SK_FALSE;
+		}
+	} else {
+		IsFlowCtrlDefined = SK_FALSE;
+	}
+
+	if (IsFlowCtrlDefined) {
+	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
+		printk("sk98lin: Port B: FlowControl"
+			" impossible without AutoNegotiation,"
+			" disabled\n");
+		FlowCtrl = SK_FLOW_MODE_NONE;
+	    }
+	    pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
+	}
+
+	/*
+	** d) What is the RoleParameter?
+	*/
+	if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		Role_B[pAC->Index] != NULL) {
+		if (strcmp(Role_B[pAC->Index],"")==0) {
+		    IsRoleDefined = SK_FALSE;
+		} else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
+		    MSMode = SK_MS_MODE_AUTO;
+		} else if (strcmp(Role_B[pAC->Index],"Master")==0) {
+		    MSMode = SK_MS_MODE_MASTER;
+		} else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
+		    MSMode = SK_MS_MODE_SLAVE;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for Role_B\n",
+			Role_B[pAC->Index]);
+		    IsRoleDefined = SK_FALSE;
+		}
+	} else {
+	    IsRoleDefined = SK_FALSE;
+	}
+
+	if (IsRoleDefined) {
+	    pAC->GIni.GP[1].PMSMode = MSMode;
+	}
+	
+	/*
+	** Evaluate settings for both ports
+	*/
+	pAC->ActivePort = 0;
+	if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		PrefPort[pAC->Index] != NULL) {
+		if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
+			pAC->ActivePort             =  0;
+			pAC->Rlmt.Net[0].Preference = -1; /* auto */
+			pAC->Rlmt.Net[0].PrefPort   =  0;
+		} else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
+			/*
+			** do not set ActivePort here, thus a port
+			** switch is issued after net up.
+			*/
+			Port                        = 0;
+			pAC->Rlmt.Net[0].Preference = Port;
+			pAC->Rlmt.Net[0].PrefPort   = Port;
+		} else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
+			/*
+			** do not set ActivePort here, thus a port
+			** switch is issued after net up.
+			*/
+			if (pAC->GIni.GIMacsFound == 1) {
+				printk("sk98lin: Illegal value \"B\" for PrefPort.\n"
+					"      Port B not available on single port adapters.\n");
+
+				pAC->ActivePort             =  0;
+				pAC->Rlmt.Net[0].Preference = -1; /* auto */
+				pAC->Rlmt.Net[0].PrefPort   =  0;
+			} else {
+				Port                        = 1;
+				pAC->Rlmt.Net[0].Preference = Port;
+				pAC->Rlmt.Net[0].PrefPort   = Port;
+			}
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for PrefPort\n",
+			PrefPort[pAC->Index]);
+		}
+	}
+
+	pAC->RlmtNets = 1;
+	pAC->RlmtMode = 0;
+
+	if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+		RlmtMode[pAC->Index] != NULL) {
+		if (strcmp(RlmtMode[pAC->Index], "") == 0) {
+			if (pAC->GIni.GIMacsFound == 2) {
+				pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+				pAC->RlmtNets = 2;
+			}
+		} else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
+			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+		} else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
+			pAC->RlmtMode = SK_RLMT_CHECK_LINK |
+					SK_RLMT_CHECK_LOC_LINK;
+		} else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
+			pAC->RlmtMode = SK_RLMT_CHECK_LINK     |
+					SK_RLMT_CHECK_LOC_LINK |
+					SK_RLMT_CHECK_SEG;
+		} else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
+			(pAC->GIni.GIMacsFound == 2)) {
+			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+			pAC->RlmtNets = 2;
+		} else {
+		    printk("sk98lin: Illegal value \"%s\" for"
+			" RlmtMode, using default\n", 
+			RlmtMode[pAC->Index]);
+			pAC->RlmtMode = 0;
+		}
+	} else {
+		if (pAC->GIni.GIMacsFound == 2) {
+			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+			pAC->RlmtNets = 2;
+		}
+	}
+
+#ifdef SK_YUKON2
+	/*
+	** use dualnet config per default
+	*
+	pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+	pAC->RlmtNets = 2;
+	*/
+#endif
+
+
+	/*
+	** Check the TxModeration parameters
+	*/
+	pAC->TxModeration = 0;
+	if (TxModeration[pAC->Index] != 0) {
+		if (!HW_IS_EXT_LE_FORMAT(pAC)) {
+	   		printk("sk98lin: Illegal value for TxModeration. "
+				"Not a Yukon 2 card\n    Disable tx moderation.\n");
+
+		} else if ((TxModeration[pAC->Index] < 1) || 
+			(TxModeration[pAC->Index] > C_TX_INT_MOD_UPPER_RANGE)) {
+	   		printk("sk98lin: Illegal value \"%d\" for TxModeration. (Range: 1 - %d)\n"
+				"      Disable tx moderation.\n", 
+				TxModeration[pAC->Index],
+				C_TX_INT_MOD_UPPER_RANGE);
+		} else {
+			pAC->TxModeration = TxModeration[pAC->Index];
+		}
+	}
+
+	/*
+	** Check the LowLatance parameters
+	*/
+	pAC->LowLatency = SK_FALSE;
+	if (LowLatency[pAC->Index] != NULL) {
+		if (strcmp(LowLatency[pAC->Index], "On") == 0) {
+			pAC->LowLatency = SK_TRUE;
+		}
+	}
+
+	/*
+	** Check the BroadcastPrio parameters
+	*/
+	pAC->Rlmt.Net[0].ChgBcPrio = SK_FALSE;
+	if (BroadcastPrio[pAC->Index] != NULL) {
+		if (strcmp(BroadcastPrio[pAC->Index], "On") == 0) {
+			pAC->Rlmt.Net[0].ChgBcPrio = SK_TRUE;
+		}
+	}
+
+	/*
+	** Check the interrupt moderation parameters
+	*/
+	pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+	if (Moderation[pAC->Index] != NULL) {
+		if (strcmp(Moderation[pAC->Index], "") == 0) {
+			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+		} else if (strcmp(Moderation[pAC->Index], "Static") == 0) {
+			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
+		} else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
+			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
+		} else if (strcmp(Moderation[pAC->Index], "None") == 0) {
+			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+		} else {
+	   		printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
+				"      Disable interrupt moderation.\n",
+				Moderation[pAC->Index]);
+		}
+	} else {
+/* Set interrupt moderation if wished */
+#ifdef CONFIG_SK98LIN_STATINT
+		pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
+#endif
+	}
+
+	if (ModerationMask[pAC->Index] != NULL) {
+		if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
+			IrqModMaskOffset = 0;
+		} else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
+			IrqModMaskOffset = 1;
+		} else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
+			IrqModMaskOffset = 2;
+		} else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
+			IrqModMaskOffset = 3;
+		} else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
+			IrqModMaskOffset = 3;
+		} else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
+			IrqModMaskOffset = 4;
+		} else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
+			IrqModMaskOffset = 4;
+		} else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
+			IrqModMaskOffset = 5;
+		} else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
+			IrqModMaskOffset = 5;
+		} else { /* some rubbish stated */
+			// IrqModMaskOffset = 6; ->has been initialized
+			// already at the begin of this function...
+		}
+	}
+	if (!CHIP_ID_YUKON_2(pAC)) {
+		pAC->DynIrqModInfo.MaskIrqModeration = IrqModMask[IrqModMaskOffset][0];
+	} else {
+		pAC->DynIrqModInfo.MaskIrqModeration = IrqModMask[IrqModMaskOffset][1];
+	}
+
+	if (!CHIP_ID_YUKON_2(pAC)) {
+		pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+	} else {
+		pAC->DynIrqModInfo.MaxModIntsPerSec = C_Y2_INTS_PER_SEC_DEFAULT;
+	}
+	if (IntsPerSec[pAC->Index] != 0) {
+		if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) || 
+			(IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
+	   		printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n"
+				"      Using default value of %i.\n", 
+				IntsPerSec[pAC->Index],
+				C_INT_MOD_IPS_LOWER_RANGE,
+				C_INT_MOD_IPS_UPPER_RANGE,
+				pAC->DynIrqModInfo.MaxModIntsPerSec);
+		} else {
+			pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
+		}
+	} 
+
+	/*
+	** Evaluate upper and lower moderation threshold
+	*/
+	pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
+		pAC->DynIrqModInfo.MaxModIntsPerSec +
+		(pAC->DynIrqModInfo.MaxModIntsPerSec / 5);
+
+	pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
+		pAC->DynIrqModInfo.MaxModIntsPerSec -
+		(pAC->DynIrqModInfo.MaxModIntsPerSec / 5);
+
+	pAC->DynIrqModInfo.DynIrqModSampleInterval = 
+		SK_DRV_MODERATION_TIMER_LENGTH;
+
+} /* GetConfiguration */
+
+
+/*****************************************************************************
+ *
+ * 	ProductStr - return a adapter identification string from vpd
+ *
+ * Description:
+ *	This function reads the product name string from the vpd area
+ *	and puts it the field pAC->DeviceString.
+ *
+ * Returns: N/A
+ */
+static void ProductStr(SK_AC *pAC)
+{
+	char Default[] = "Generic Marvell Yukon chipset Ethernet device";
+	char Key[] = VPD_NAME; /* VPD productname key */
+	int StrLen = 80;       /* stringlen           */
+	unsigned long Flags;
+	int ReturnCode = 0;
+
+	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+	if ((ReturnCode = VpdRead(pAC, pAC->IoBase, Key, pAC->DeviceStr, &StrLen)) != 0) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
+			("Error reading VPD data: %d\n", ReturnCode));
+		strcpy(pAC->DeviceStr, Default);
+	}
+	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+} /* ProductStr */
+
+/****************************************************************************/
+/* functions for common modules *********************************************/
+/****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ *	SkDrvAllocRlmtMbuf - allocate an RLMT mbuf
+ *
+ * Description:
+ *	This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure
+ *	is embedded into a socket buff data area.
+ *
+ * Context:
+ *	runtime
+ *
+ * Returns:
+ *	NULL or pointer to Mbuf.
+ */
+SK_MBUF *SkDrvAllocRlmtMbuf(
+SK_AC		*pAC,		/* pointer to adapter context */
+SK_IOC		IoC,		/* the IO-context */
+unsigned	BufferSize)	/* size of the requested buffer */
+{
+SK_MBUF		*pRlmtMbuf;	/* pointer to a new rlmt-mbuf structure */
+struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
+
+	pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);
+	if (pMsgBlock == NULL) {
+		return (NULL);
+	}
+	pRlmtMbuf = (SK_MBUF*) pMsgBlock->data;
+	skb_reserve(pMsgBlock, sizeof(SK_MBUF));
+	pRlmtMbuf->pNext = NULL;
+	pRlmtMbuf->pOs = pMsgBlock;
+	pRlmtMbuf->pData = pMsgBlock->data;	/* Data buffer. */
+	pRlmtMbuf->Size = BufferSize;		/* Data buffer size. */
+	pRlmtMbuf->Length = 0;		/* Length of packet (<= Size). */
+	return (pRlmtMbuf);
+
+} /* SkDrvAllocRlmtMbuf */
+
+
+/*****************************************************************************
+ *
+ *	SkDrvFreeRlmtMbuf - free an RLMT mbuf
+ *
+ * Description:
+ *	This routine frees one or more RLMT mbuf(s).
+ *
+ * Context:
+ *	runtime
+ *
+ * Returns:
+ *	Nothing
+ */
+void  SkDrvFreeRlmtMbuf(
+SK_AC		*pAC,		/* pointer to adapter context */
+SK_IOC		IoC,		/* the IO-context */
+SK_MBUF		*pMbuf)		/* size of the requested buffer */
+{
+SK_MBUF		*pFreeMbuf;
+SK_MBUF		*pNextMbuf;
+
+	pFreeMbuf = pMbuf;
+	do {
+		pNextMbuf = pFreeMbuf->pNext;
+		DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
+		pFreeMbuf = pNextMbuf;
+	} while ( pFreeMbuf != NULL );
+} /* SkDrvFreeRlmtMbuf */
+
+
+/*****************************************************************************
+ *
+ *	SkOsGetTime - provide a time value
+ *
+ * Description:
+ *	This routine provides a time value. The unit is 1/HZ (defined by Linux).
+ *	It is not used for absolute time, but only for time differences.
+ *
+ *
+ * Returns:
+ *	Time value
+ */
+SK_U64 SkOsGetTime(SK_AC *pAC)
+{
+	SK_U64	PrivateJiffies;
+
+	SkOsGetTimeCurrent(pAC, &PrivateJiffies);
+
+	return PrivateJiffies;
+} /* SkOsGetTime */
+
+
+/*****************************************************************************
+ *
+ *	SkPciReadCfgDWord - read a 32 bit value from pci config space
+ *
+ * Description:
+ *	This routine reads a 32 bit value from the pci configuration
+ *	space.
+ *
+ * Returns:
+ *	0 - indicate everything worked ok.
+ *	!= 0 - error indication
+ */
+int SkPciReadCfgDWord(
+SK_AC *pAC,		/* Adapter Control structure pointer */
+int PciAddr,		/* PCI register address */
+SK_U32 *pVal)		/* pointer to store the read value */
+{
+	pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
+	return(0);
+} /* SkPciReadCfgDWord */
+
+
+/*****************************************************************************
+ *
+ *	SkPciReadCfgWord - read a 16 bit value from pci config space
+ *
+ * Description:
+ *	This routine reads a 16 bit value from the pci configuration
+ *	space.
+ *
+ * Returns:
+ *	0 - indicate everything worked ok.
+ *	!= 0 - error indication
+ */
+int SkPciReadCfgWord(
+SK_AC *pAC,	/* Adapter Control structure pointer */
+int PciAddr,		/* PCI register address */
+SK_U16 *pVal)		/* pointer to store the read value */
+{
+	pci_read_config_word(pAC->PciDev, PciAddr, pVal);
+	return(0);
+} /* SkPciReadCfgWord */
+
+
+/*****************************************************************************
+ *
+ *	SkPciReadCfgByte - read a 8 bit value from pci config space
+ *
+ * Description:
+ *	This routine reads a 8 bit value from the pci configuration
+ *	space.
+ *
+ * Returns:
+ *	0 - indicate everything worked ok.
+ *	!= 0 - error indication
+ */
+int SkPciReadCfgByte(
+SK_AC *pAC,	/* Adapter Control structure pointer */
+int PciAddr,		/* PCI register address */
+SK_U8 *pVal)		/* pointer to store the read value */
+{
+	pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
+	return(0);
+} /* SkPciReadCfgByte */
+
+
+/*****************************************************************************
+ *
+ *	SkPciWriteCfgDWord - write a 32 bit value to pci config space
+ *
+ * Description:
+ *	This routine writes a 32 bit value to the pci configuration
+ *	space.
+ *
+ * Returns:
+ *	0 - indicate everything worked ok.
+ *	!= 0 - error indication
+ */
+int SkPciWriteCfgDWord(
+SK_AC *pAC,	/* Adapter Control structure pointer */
+int PciAddr,		/* PCI register address */
+SK_U32 Val)		/* pointer to store the read value */
+{
+	pci_write_config_dword(pAC->PciDev, PciAddr, Val);
+	return(0);
+} /* SkPciWriteCfgDWord */
+
+
+/*****************************************************************************
+ *
+ *	SkPciWriteCfgWord - write a 16 bit value to pci config space
+ *
+ * Description:
+ *	This routine writes a 16 bit value to the pci configuration
+ *	space. The flag PciConfigUp indicates whether the config space
+ *	is accesible or must be set up first.
+ *
+ * Returns:
+ *	0 - indicate everything worked ok.
+ *	!= 0 - error indication
+ */
+int SkPciWriteCfgWord(
+SK_AC *pAC,	/* Adapter Control structure pointer */
+int PciAddr,		/* PCI register address */
+SK_U16 Val)		/* pointer to store the read value */
+{
+	pci_write_config_word(pAC->PciDev, PciAddr, Val);
+	return(0);
+} /* SkPciWriteCfgWord */
+
+
+/*****************************************************************************
+ *
+ *	SkPciWriteCfgWord - write a 8 bit value to pci config space
+ *
+ * Description:
+ *	This routine writes a 8 bit value to the pci configuration
+ *	space. The flag PciConfigUp indicates whether the config space
+ *	is accesible or must be set up first.
+ *
+ * Returns:
+ *	0 - indicate everything worked ok.
+ *	!= 0 - error indication
+ */
+int SkPciWriteCfgByte(
+SK_AC *pAC,	/* Adapter Control structure pointer */
+int PciAddr,		/* PCI register address */
+SK_U8 Val)		/* pointer to store the read value */
+{
+	pci_write_config_byte(pAC->PciDev, PciAddr, Val);
+	return(0);
+} /* SkPciWriteCfgByte */
+
+
+/*****************************************************************************
+ *
+ *	SkDrvEvent - handle driver events
+ *
+ * Description:
+ *	This function handles events from all modules directed to the driver
+ *
+ * Context:
+ *	Is called under protection of slow path lock.
+ *
+ * Returns:
+ *	0 if everything ok
+ *	< 0  on error
+ *	
+ */
+int SkDrvEvent(
+SK_AC     *pAC,    /* pointer to adapter context */
+SK_IOC     IoC,    /* IO control context         */
+SK_U32     Event,  /* event-id                   */
+SK_EVPARA  Param)  /* event-parameter            */
+{
+	SK_MBUF         *pRlmtMbuf;   /* pointer to a rlmt-mbuf structure   */
+	struct sk_buff  *pMsg;        /* pointer to a message block         */
+	SK_BOOL          DualNet;
+	SK_U32           Reason;
+	unsigned long    Flags;
+	unsigned long    InitFlags;
+	int              FromPort;    /* the port from which we switch away */
+	int              ToPort;      /* the port we switch to              */
+	int              Stat;
+	DEV_NET 	*pNet = NULL;
+#ifdef CONFIG_SK98LIN_NAPI
+	int              WorkToDo = 1; /* min(*budget, dev->quota); */
+	int              WorkDone = 0;
+#endif
+
+	switch (Event) {
+	case SK_DRV_PORT_FAIL:
+		FromPort = Param.Para32[0];
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+			("PORT FAIL EVENT, Port: %d\n", FromPort));
+		if (FromPort == 0) {
+			printk("%s: Port A failed.\n", pAC->dev[0]->name);
+		} else {
+			printk("%s: Port B failed.\n", pAC->dev[1]->name);
+		}
+		break;
+	case SK_DRV_PORT_RESET:
+		FromPort = Param.Para32[0];
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+			("PORT RESET EVENT, Port: %d ", FromPort));
+		SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
+					FromPort, SK_FALSE);
+		spin_lock_irqsave(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+		if (CHIP_ID_YUKON_2(pAC)) {
+			SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
+		} else {
+			SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
+		}
+		pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
+		spin_unlock_irqrestore(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+		
+		if (!CHIP_ID_YUKON_2(pAC)) {
+#ifdef CONFIG_SK98LIN_NAPI
+			WorkToDo = 1;
+			ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo);
+#else
+			ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
+#endif
+			ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
+		}
+		spin_lock_irqsave(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+
+#ifdef USE_TIST_FOR_RESET
+                if (!HW_IS_EXT_LE_FORMAT(pAC) && pAC->GIni.GIYukon2) {
+#ifdef Y2_RECOVERY
+			/* for Yukon II we want to have tist enabled all the time */
+			if (!SK_ADAPTER_WAITING_FOR_TIST(pAC)) {
+				Y2_ENABLE_TIST(pAC->IoBase);
+			}
+#else
+			/* make sure that we do not accept any status LEs from now on */
+			if (SK_ADAPTER_WAITING_FOR_TIST(pAC)) {
+#endif
+				/* port already waiting for tist */
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+					("Port %c is now waiting for specific Tist\n",
+					'A' +  FromPort));
+				SK_SET_WAIT_BIT_FOR_PORT(
+					pAC,
+					SK_PSTATE_WAITING_FOR_SPECIFIC_TIST,
+					FromPort);
+				/* get current timestamp */
+				Y2_GET_TIST_LOW_VAL(pAC->IoBase, &pAC->MinTistLo);
+				pAC->MinTistHi = pAC->GIni.GITimeStampCnt;
+#ifndef Y2_RECOVERY
+			} else {
+				/* nobody is waiting yet */
+				SK_SET_WAIT_BIT_FOR_PORT(
+					pAC,
+					SK_PSTATE_WAITING_FOR_ANY_TIST,
+					FromPort);
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+					("Port %c is now waiting for any Tist (0x%X)\n",
+					'A' +  FromPort, pAC->AdapterResetState));
+				/* start tist */
+				Y2_ENABLE_TIST(pAC-IoBase);
+			}
+#endif
+		}
+#endif
+
+#ifdef Y2_LE_CHECK
+		/* mark entries invalid */
+		pAC->LastPort = 3;
+		pAC->LastOpc = 0xFF;
+#endif
+		if (CHIP_ID_YUKON_2(pAC)) {
+			SkY2PortStart(pAC, IoC, FromPort);
+		} else {
+			/* tschilling: Handling of return value inserted. */
+			if (SkGeInitPort(pAC, IoC, FromPort)) {
+				if (FromPort == 0) {
+					printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
+				} else {
+					printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
+				}
+			}
+			SkAddrMcUpdate(pAC,IoC, FromPort);
+			PortReInitBmu(pAC, FromPort);
+			SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+			CLEAR_AND_START_RX(FromPort);
+		}
+		spin_unlock_irqrestore(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+		break;
+	case SK_DRV_NET_UP:
+		spin_lock_irqsave(&pAC->InitLock, InitFlags);
+		FromPort = Param.Para32[0];
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+			("NET UP EVENT, Port: %d ", FromPort));
+		SkAddrMcUpdate(pAC,IoC, FromPort); /* Mac update */
+		if (DoPrintInterfaceChange) {
+			printk("%s: network connection up using port %c\n",
+				pAC->dev[FromPort]->name, 'A'+FromPort);
+
+			/* tschilling: Values changed according to LinkSpeedUsed. */
+			Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
+			if (Stat == SK_LSPEED_STAT_10MBPS) {
+				printk("    speed:           10\n");
+			} else if (Stat == SK_LSPEED_STAT_100MBPS) {
+				printk("    speed:           100\n");
+			} else if (Stat == SK_LSPEED_STAT_1000MBPS) {
+				printk("    speed:           1000\n");
+			} else {
+				printk("    speed:           unknown\n");
+			}
+
+			Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
+			if ((Stat == SK_LMODE_STAT_AUTOHALF) ||
+			    (Stat == SK_LMODE_STAT_AUTOFULL)) {
+				printk("    autonegotiation: yes\n");
+			} else {
+				printk("    autonegotiation: no\n");
+			}
+
+			if ((Stat == SK_LMODE_STAT_AUTOHALF) ||
+			    (Stat == SK_LMODE_STAT_HALF)) {
+				printk("    duplex mode:     half\n");
+			} else {
+				printk("    duplex mode:     full\n");
+			}
+
+			Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
+			if (Stat == SK_FLOW_STAT_REM_SEND ) {
+				printk("    flowctrl:        remote send\n");
+			} else if (Stat == SK_FLOW_STAT_LOC_SEND ) {
+				printk("    flowctrl:        local send\n");
+			} else if (Stat == SK_FLOW_STAT_SYMMETRIC ) {
+				printk("    flowctrl:        symmetric\n");
+			} else {
+				printk("    flowctrl:        none\n");
+			}
+		
+			/* tschilling: Check against CopperType now. */
+			if ((pAC->GIni.GICopperType == SK_TRUE) &&
+				(pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
+				SK_LSPEED_STAT_1000MBPS)) {
+				Stat = pAC->GIni.GP[FromPort].PMSStatus;
+				if (Stat == SK_MS_STAT_MASTER ) {
+					printk("    role:            master\n");
+				} else if (Stat == SK_MS_STAT_SLAVE ) {
+					printk("    role:            slave\n");
+				} else {
+					printk("    role:            ???\n");
+				}
+			}
+
+			/* Display interrupt moderation informations */
+			if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
+				printk("    irq moderation:  static (%d ints/sec)\n",
+					pAC->DynIrqModInfo.MaxModIntsPerSec);
+			} else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+				printk("    irq moderation:  dynamic (%d ints/sec)\n",
+					pAC->DynIrqModInfo.MaxModIntsPerSec);
+			} else {
+				printk("    irq moderation:  disabled\n");
+			}
+	
+#ifdef NETIF_F_TSO
+			if (CHIP_ID_YUKON_2(pAC)) {
+				if (pAC->dev[FromPort]->features & NETIF_F_TSO) {
+					printk("    tcp offload:     enabled\n");
+				} else {
+					printk("    tcp offload:     disabled\n");
+				}
+			}
+#endif
+
+			if (pAC->dev[FromPort]->features & NETIF_F_SG) {
+				printk("    scatter-gather:  enabled\n");
+			} else {
+				printk("    scatter-gather:  disabled\n");
+			}
+
+			if (pAC->dev[FromPort]->features & NETIF_F_IP_CSUM) {
+				printk("    tx-checksum:     enabled\n");
+			} else {
+				printk("    tx-checksum:     disabled\n");
+			}
+
+			if (pAC->RxPort[FromPort].UseRxCsum) {
+				printk("    rx-checksum:     enabled\n");
+			} else {
+				printk("    rx-checksum:     disabled\n");
+			}
+#ifdef CONFIG_SK98LIN_NAPI
+				printk("    rx-polling:      enabled\n");
+#endif
+			if (pAC->TxModeration) {
+				printk("    tx moderation:   %d\n", 
+					pAC->TxModeration);
+			}
+
+			if (pAC->LowLatency) {
+				printk("    low latency:     enabled\n");
+			}
+
+			if (pAC->Rlmt.Net[0].ChgBcPrio) {
+				printk("    broadcast prio:  enabled\n");
+			}
+#ifdef SK_ASF
+#ifdef USE_ASF_DASH_FW
+			printk("    Firmware:        enabled\n");
+#endif
+#ifndef USE_ASF_DASH_FW
+			printk("    IPMI:            enabled\n");
+#endif
+#endif
+		} else {
+			DoPrintInterfaceChange = SK_TRUE;
+		}
+	
+		if ((FromPort != pAC->ActivePort)&&(pAC->RlmtNets == 1)) {
+			SkLocalEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
+						pAC->ActivePort, FromPort, SK_FALSE);
+		}
+
+		/* Inform the world that link protocol is up. */
+		netif_wake_queue(pAC->dev[FromPort]);
+		netif_carrier_on(pAC->dev[FromPort]);
+		pAC->dev[FromPort]->flags |= IFF_RUNNING;
+		spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+		break;
+	case SK_DRV_NET_DOWN:
+		Reason   = Param.Para32[0];
+		FromPort = Param.Para32[1];
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+			("NET DOWN EVENT "));
+
+		/* Stop queue and carrier */
+		netif_stop_queue(pAC->dev[FromPort]);
+		netif_carrier_off(pAC->dev[FromPort]);
+
+		/* Print link change */
+		if (DoPrintInterfaceChange) {
+			if (pAC->dev[FromPort]->flags & IFF_RUNNING) {
+				printk("%s: network connection down\n", 
+					pAC->dev[FromPort]->name);
+			}
+		} else {
+			DoPrintInterfaceChange = SK_TRUE;
+		}
+		pAC->dev[FromPort]->flags &= ~IFF_RUNNING;
+		break;
+	case SK_DRV_SWITCH_HARD:   /* FALL THRU */
+	case SK_DRV_SWITCH_SOFT:   /* FALL THRU */
+	case SK_DRV_SWITCH_INTERN:
+		FromPort = Param.Para32[0];
+		ToPort   = Param.Para32[1];
+		printk("%s: switching from port %c to port %c\n",
+			pAC->dev[0]->name, 'A'+FromPort, 'A'+ToPort);
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+			("PORT SWITCH EVENT, From: %d  To: %d (Pref %d) ",
+			FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
+		SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
+					FromPort, SK_FALSE);
+		SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
+					ToPort, SK_FALSE);
+		spin_lock_irqsave(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+		if (CHIP_ID_YUKON_2(pAC)) {
+			SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
+			SkY2PortStop(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
+		}
+		else {
+			SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
+			SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
+		}
+		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+		spin_unlock_irqrestore(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+
+		
+		if (!CHIP_ID_YUKON_2(pAC)) {
+#ifdef CONFIG_SK98LIN_NAPI
+			WorkToDo = 1;
+			ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo);
+			ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE, &WorkDone, WorkToDo);
+#else
+			ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
+			ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
+#endif
+			ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
+			ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
+		} 
+
+		spin_lock_irqsave(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+		pAC->ActivePort = ToPort;
+
+		/* tschilling: New common function with minimum size check. */
+		DualNet = SK_FALSE;
+		if (pAC->RlmtNets == 2) {
+			DualNet = SK_TRUE;
+		}
+		
+		if (SkGeInitAssignRamToQueues(
+			pAC,
+			pAC->ActivePort,
+			DualNet)) {
+			spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+			spin_unlock_irqrestore(
+				&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+				Flags);
+			printk("SkGeInitAssignRamToQueues failed.\n");
+			break;
+		}
+
+		if (!CHIP_ID_YUKON_2(pAC)) {
+			/* tschilling: Handling of return values inserted. */
+			if (SkGeInitPort(pAC, IoC, FromPort) ||
+				SkGeInitPort(pAC, IoC, ToPort)) {
+				printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
+			}
+		}
+		if (!CHIP_ID_YUKON_2(pAC)) {
+			if (Event == SK_DRV_SWITCH_SOFT) {
+				SkMacRxTxEnable(pAC, IoC, FromPort);
+			}
+			SkMacRxTxEnable(pAC, IoC, ToPort);
+		}
+
+		SkAddrSwap(pAC, IoC, FromPort, ToPort);
+		SkAddrMcUpdate(pAC, IoC, FromPort);
+		SkAddrMcUpdate(pAC, IoC, ToPort);
+
+#ifdef USE_TIST_FOR_RESET
+                if (!HW_IS_EXT_LE_FORMAT(pAC) && pAC->GIni.GIYukon2) {
+			/* make sure that we do not accept any status LEs from now on */
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+				("both Ports now waiting for specific Tist\n"));
+			SK_SET_WAIT_BIT_FOR_PORT(
+				pAC,
+				SK_PSTATE_WAITING_FOR_ANY_TIST,
+				0);
+			SK_SET_WAIT_BIT_FOR_PORT(
+				pAC,
+				SK_PSTATE_WAITING_FOR_ANY_TIST,
+				1);
+
+			/* start tist */
+			Y2_ENABLE_TIST(pAC->IoBase);
+		}
+#endif
+		if (!CHIP_ID_YUKON_2(pAC)) {
+			PortReInitBmu(pAC, FromPort);
+			PortReInitBmu(pAC, ToPort);
+			SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+			SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
+			CLEAR_AND_START_RX(FromPort);
+			CLEAR_AND_START_RX(ToPort);
+		} else {
+			SkY2PortStart(pAC, IoC, FromPort);
+			SkY2PortStart(pAC, IoC, ToPort);
+#ifdef SK_YUKON2
+			/* in yukon-II always port 0 has to be started first */
+			// SkY2PortStart(pAC, IoC, 0);
+			// SkY2PortStart(pAC, IoC, 1);
+#endif
+		}
+		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+		spin_unlock_irqrestore(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+		break;
+	case SK_DRV_RLMT_SEND:	 /* SK_MBUF *pMb */
+		SK_DBG_MSG(NULL,SK_DBGMOD_DRV,SK_DBGCAT_DRV_EVENT,("RLS "));
+		pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
+		pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
+		skb_put(pMsg, pRlmtMbuf->Length);
+		if (!CHIP_ID_YUKON_2(pAC)) {
+			if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
+				pMsg) < 0) {
+				DEV_KFREE_SKB_ANY(pMsg);
+			}
+		} else {
+			if (SkY2RlmtSend(pAC, pRlmtMbuf->PortIdx, pMsg) < 0) {
+				DEV_KFREE_SKB_ANY(pMsg);
+			}
+		}
+		break;
+	case SK_DRV_TIMER:
+		if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
+			/* check what IRQs are to be moderated */
+			SkDimStartModerationTimer(pAC);
+			SkDimModerate(pAC);
+		} else {
+			printk("Expiration of unknown timer\n");
+		}
+		break;
+	case SK_DRV_ADAP_FAIL:
+#if (!defined (Y2_RECOVERY) && !defined (Y2_LE_CHECK))
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+			("ADAPTER FAIL EVENT\n"));
+		printk("%s: Adapter failed.\n", pAC->dev[0]->name);
+		SK_OUT32(pAC->IoBase, B0_IMSK, 0); /* disable interrupts */
+		break;
+#endif
+
+#if (defined (Y2_RECOVERY) || defined (Y2_LE_CHECK))
+	case SK_DRV_RECOVER:
+		spin_lock_irqsave(&pAC->InitLock, InitFlags);
+		pNet = (DEV_NET *)netdev_priv(pAC->dev[Param.Para32[0]]);
+
+		/* Recover already in progress */
+		if (pNet->InRecover) {
+			break;
+		}
+
+		netif_stop_queue(pAC->dev[Param.Para32[0]]); /* stop device if running */
+		pNet->InRecover = SK_TRUE;
+
+		FromPort = Param.Para32[0];
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+			("PORT RESET EVENT, Port: %d ", FromPort));
+
+		/* Disable interrupts */
+		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+		SK_OUT32(pAC->IoBase, B0_HWE_IMSK, 0);
+
+		SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
+					FromPort, SK_FALSE);
+		spin_lock_irqsave(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+		if (CHIP_ID_YUKON_2(pAC)) {
+			SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
+		} else {
+			SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
+		}
+		pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
+		spin_unlock_irqrestore(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+		
+		if (!CHIP_ID_YUKON_2(pAC)) {
+#ifdef CONFIG_SK98LIN_NAPI
+			WorkToDo = 1;
+			ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo);
+#else
+			ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
+#endif
+			ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
+		}
+		spin_lock_irqsave(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+
+#ifdef USE_TIST_FOR_RESET
+		if (!HW_IS_EXT_LE_FORMAT(pAC) && pAC->GIni.GIYukon2) {
+#if 0
+			/* make sure that we do not accept any status LEs from now on */
+			Y2_ENABLE_TIST(pAC->IoBase);
+
+			/* get current timestamp */
+			Y2_GET_TIST_LOW_VAL(pAC->IoBase, &pAC->MinTistLo);
+			pAC->MinTistHi = pAC->GIni.GITimeStampCnt;
+
+			SK_SET_WAIT_BIT_FOR_PORT(
+				pAC,
+				SK_PSTATE_WAITING_FOR_SPECIFIC_TIST,
+				FromPort);
+#endif
+			SK_SET_WAIT_BIT_FOR_PORT(
+				pAC,
+				SK_PSTATE_WAITING_FOR_ANY_TIST,
+				FromPort);
+
+			/* start tist */
+                        Y2_ENABLE_TIST(pAC->IoBase);
+		}
+#endif
+
+		/* Restart Receive BMU on Yukon-2 */
+		if (HW_FEATURE(pAC, HWF_WA_DEV_4167)) {
+			SkYuk2RestartRxBmu(pAC, IoC, FromPort);
+		}
+
+#ifdef Y2_LE_CHECK
+		/* mark entries invalid */
+		pAC->LastPort = 3;
+		pAC->LastOpc = 0xFF;
+#endif
+
+#endif
+		/* Restart ports but do not initialize PHY. */
+		if (CHIP_ID_YUKON_2(pAC)) {
+			SkY2PortStart(pAC, IoC, FromPort);
+		} else {
+			/* tschilling: Handling of return value inserted. */
+			if (SkGeInitPort(pAC, IoC, FromPort)) {
+				if (FromPort == 0) {
+					printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
+				} else {
+					printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
+				}
+			}
+			SkAddrMcUpdate(pAC,IoC, FromPort);
+			PortReInitBmu(pAC, FromPort);
+			SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+			CLEAR_AND_START_RX(FromPort);
+		}
+		spin_unlock_irqrestore(
+			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+			Flags);
+
+		/* Map any waiting RX buffers to HW */
+		FillReceiveTableYukon2(pAC, pAC->IoBase, FromPort);
+
+		pNet->InRecover = SK_FALSE;
+		/* enable Interrupts */
+		SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+		SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+		netif_wake_queue(pAC->dev[FromPort]);
+		spin_unlock_irqrestore(&pAC->InitLock, InitFlags);
+		break;
+	default:
+		break;
+	}
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+		("END EVENT "));
+
+	return (0);
+} /* SkDrvEvent */
+
+
+/******************************************************************************
+ *
+ *	SkLocalEventQueue()	-	add event to queue
+ *
+ * Description:
+ *	This function adds an event to the event queue and run the
+ *	SkEventDispatcher. At least Init Level 1 is required to queue events,
+ *	but will be scheduled add Init Level 2.
+ *
+ * returns:
+ *	nothing
+ */
+void SkLocalEventQueue(
+SK_AC *pAC,		/* Adapters context */
+SK_U32 Class,		/* Event Class */
+SK_U32 Event,		/* Event to be queued */
+SK_U32 Param1,		/* Event parameter 1 */
+SK_U32 Param2,		/* Event parameter 2 */
+SK_BOOL Dispatcher)	/* Dispatcher flag:
+			 *	TRUE == Call SkEventDispatcher
+			 *	FALSE == Don't execute SkEventDispatcher
+			 */
+{
+	SK_EVPARA 	EvPara;
+	EvPara.Para32[0] = Param1;
+	EvPara.Para32[1] = Param2;
+	
+
+	if (Class == SKGE_PNMI) {
+		SkPnmiEvent(	pAC,
+				pAC->IoBase,
+				Event,
+				EvPara);
+	} else {
+		SkEventQueue(	pAC,
+				Class,
+				Event,
+				EvPara);
+	}
+
+	/* Run the dispatcher */
+	if (Dispatcher) {
+		SkEventDispatcher(pAC, pAC->IoBase);
+	}
+
+}
+
+/******************************************************************************
+ *
+ *	SkLocalEventQueue64()	-	add event to queue (64bit version)
+ *
+ * Description:
+ *	This function adds an event to the event queue and run the
+ *	SkEventDispatcher. At least Init Level 1 is required to queue events,
+ *	but will be scheduled add Init Level 2.
+ *
+ * returns:
+ *	nothing
+ */
+void SkLocalEventQueue64(
+SK_AC *pAC,		/* Adapters context */
+SK_U32 Class,		/* Event Class */
+SK_U32 Event,		/* Event to be queued */
+SK_U64 Param,		/* Event parameter */
+SK_BOOL Dispatcher)	/* Dispatcher flag:
+			 *	TRUE == Call SkEventDispatcher
+			 *	FALSE == Don't execute SkEventDispatcher
+			 */
+{
+	SK_EVPARA 	EvPara;
+	EvPara.Para64 = Param;
+
+
+	if (Class == SKGE_PNMI) {
+		SkPnmiEvent(	pAC,
+				pAC->IoBase,
+				Event,
+				EvPara);
+	} else {
+		SkEventQueue(	pAC,
+				Class,
+				Event,
+				EvPara);
+	}
+
+	/* Run the dispatcher */
+	if (Dispatcher) {
+		SkEventDispatcher(pAC, pAC->IoBase);
+	}
+
+}
+
+
+/*****************************************************************************
+ *
+ *	SkErrorLog - log errors
+ *
+ * Description:
+ *	This function logs errors to the system buffer and to the console
+ *
+ * Returns:
+ *	0 if everything ok
+ *	< 0  on error
+ *	
+ */
+void SkErrorLog(
+SK_AC	*pAC,
+int	ErrClass,
+int	ErrNum,
+char	*pErrorMsg)
+{
+char	ClassStr[80];
+
+	switch (ErrClass) {
+	case SK_ERRCL_OTHER:
+		strcpy(ClassStr, "Other error");
+		break;
+	case SK_ERRCL_CONFIG:
+		strcpy(ClassStr, "Configuration error");
+		break;
+	case SK_ERRCL_INIT:
+		strcpy(ClassStr, "Initialization error");
+		break;
+	case SK_ERRCL_NORES:
+		strcpy(ClassStr, "Out of resources error");
+		break;
+	case SK_ERRCL_SW:
+		strcpy(ClassStr, "internal Software error");
+		break;
+	case SK_ERRCL_HW:
+		strcpy(ClassStr, "Hardware failure");
+		break;
+	case SK_ERRCL_COMM:
+		strcpy(ClassStr, "Communication error");
+		break;
+	case SK_ERRCL_INFO:
+		strcpy(ClassStr, "Information");
+		break;
+	}
+
+	if (ErrClass == SK_ERRCL_INFO) {
+		printk(KERN_INFO "%s: -- INFORMATION --\n"
+			"        Msg:  %s\n", pAC->dev[0]->name,
+			pErrorMsg);
+	} else {
+		printk(KERN_INFO "%s: -- ERROR --\n        Class:  %s\n"
+			"        Nr:  0x%x\n        Msg:  %s\n", pAC->dev[0]->name,
+			ClassStr, ErrNum, pErrorMsg);
+	}
+
+} /* SkErrorLog */
+
+/*****************************************************************************
+ *
+ *	SkDrvEnterDiagMode - handles DIAG attach request
+ *
+ * Description:
+ *	Notify the kernel to NOT access the card any longer due to DIAG
+ *	Deinitialize the Card
+ *
+ * Returns:
+ *	int
+ */
+int SkDrvEnterDiagMode(
+SK_AC   *pAc)   /* pointer to adapter context */
+{
+	SK_AC   *pAC  = NULL;
+	DEV_NET *pNet = NULL;
+
+	pNet = (DEV_NET *)netdev_priv(pAc->dev[0]);
+	pAC = pNet->pAC;
+
+	SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), 
+			sizeof(SK_PNMI_STRUCT_DATA));
+
+	pAC->DiagModeActive = DIAG_ACTIVE;
+	if (pAC->BoardLevel > SK_INIT_DATA) {
+		if (netif_running(pAC->dev[0])) {
+			pAC->WasIfUp[0] = SK_TRUE;
+			pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose      */
+			DoPrintInterfaceChange = SK_FALSE;
+			SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
+		} else {
+			pAC->WasIfUp[0] = SK_FALSE;
+		}
+
+		if (pNet != (DEV_NET *)netdev_priv(pAc->dev[1])) {
+			pNet = (DEV_NET *)netdev_priv(pAc->dev[1]);
+			if (netif_running(pAC->dev[1])) {
+				pAC->WasIfUp[1] = SK_TRUE;
+				pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+				DoPrintInterfaceChange = SK_FALSE;
+				SkDrvDeInitAdapter(pAC, 1);  /* do SkGeClose  */
+			} else {
+				pAC->WasIfUp[1] = SK_FALSE;
+			}
+		}
+		pAC->BoardLevel = SK_INIT_DATA;
+	}
+	return(0);
+}
+
+/*****************************************************************************
+ *
+ *	SkDrvLeaveDiagMode - handles DIAG detach request
+ *
+ * Description:
+ *	Notify the kernel to may access the card again after use by DIAG
+ *	Initialize the Card
+ *
+ * Returns:
+ * 	int
+ */
+int SkDrvLeaveDiagMode(
+SK_AC   *pAc)   /* pointer to adapter control context */
+{ 
+	SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), 
+			sizeof(SK_PNMI_STRUCT_DATA));
+	pAc->DiagModeActive    = DIAG_NOTACTIVE;
+	pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
+	if (pAc->WasIfUp[0] == SK_TRUE) {
+		pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+		DoPrintInterfaceChange = SK_FALSE;
+		SkDrvInitAdapter(pAc, 0);    /* first device  */
+	}
+	if (pAc->WasIfUp[1] == SK_TRUE) {
+		pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+		DoPrintInterfaceChange = SK_FALSE;
+		SkDrvInitAdapter(pAc, 1);    /* second device */
+	}
+	return(0);
+}
+
+/*****************************************************************************
+ *
+ *	ParseDeviceNbrFromSlotName - Evaluate PCI device number
+ *
+ * Description:
+ * 	This function parses the PCI slot name information string and will
+ *	retrieve the devcie number out of it. The slot_name maintianed by
+ *	linux is in the form of '02:0a.0', whereas the first two characters 
+ *	represent the bus number in hex (in the sample above this is 
+ *	pci bus 0x02) and the next two characters the device number (0x0a).
+ *
+ * Returns:
+ *	SK_U32: The device number from the PCI slot name
+ */ 
+
+static SK_U32 ParseDeviceNbrFromSlotName(
+const char *SlotName)   /* pointer to pci slot name eg. '02:0a.0' */
+{
+	char	*CurrCharPos	= (char *) SlotName;
+	int	FirstNibble	= -1;
+	int	SecondNibble	= -1;
+	SK_U32	Result		=  0;
+
+	while (*CurrCharPos != '\0') {
+		if (*CurrCharPos == ':') { 
+			while (*CurrCharPos != '.') {
+				CurrCharPos++;  
+				if (	(*CurrCharPos >= '0') && 
+					(*CurrCharPos <= '9')) {
+					if (FirstNibble == -1) {
+						/* dec. value for '0' */
+						FirstNibble = *CurrCharPos - 48;
+					} else {
+						SecondNibble = *CurrCharPos - 48;
+					}  
+				} else if (	(*CurrCharPos >= 'a') && 
+						(*CurrCharPos <= 'f')  ) {
+					if (FirstNibble == -1) {
+						FirstNibble = *CurrCharPos - 87; 
+					} else {
+						SecondNibble = *CurrCharPos - 87; 
+					}
+				} else {
+					Result = 0;
+				}
+			}
+
+			Result = FirstNibble;
+			Result = Result << 4; /* first nibble is higher one */
+			Result = Result | SecondNibble;
+		}
+		CurrCharPos++;   /* next character */
+	}
+	return (Result);
+}
+
+/****************************************************************************
+ *
+ *	SkDrvDeInitAdapter - deinitialize adapter (this function is only 
+ *				called if Diag attaches to that card)
+ *
+ * Description:
+ *	Close initialized adapter.
+ *
+ * Returns:
+ *	0 - on success
+ *	error code - on error
+ */
+static int SkDrvDeInitAdapter(
+SK_AC   *pAC,		/* pointer to adapter context   */
+int      devNbr)	/* what device is to be handled */
+{
+	struct SK_NET_DEVICE *dev;
+
+	dev = pAC->dev[devNbr];
+
+	/*
+	** Function SkGeClose() uses MOD_DEC_USE_COUNT (2.2/2.4)
+	** or module_put() (2.6) to decrease the number of users for
+	** a device, but if a device is to be put under control of 
+	** the DIAG, that count is OK already and does not need to 
+	** be adapted! Hence the opposite MOD_INC_USE_COUNT or 
+	** try_module_get() needs to be used again to correct that.
+	*/
+	if (!try_module_get(THIS_MODULE)) {
+		return (-1);
+	}
+
+	if (SkGeClose(dev) != 0) {
+		module_put(THIS_MODULE);
+		return (-1);
+	}
+	return (0);
+
+} /* SkDrvDeInitAdapter() */
+
+/****************************************************************************
+ *
+ *	SkDrvInitAdapter - Initialize adapter (this function is only 
+ *				called if Diag deattaches from that card)
+ *
+ * Description:
+ *	Close initialized adapter.
+ *
+ * Returns:
+ *	0 - on success
+ *	error code - on error
+ */
+static int SkDrvInitAdapter(
+SK_AC   *pAC,		/* pointer to adapter context   */
+int      devNbr)	/* what device is to be handled */
+{
+	struct SK_NET_DEVICE *dev;
+
+	dev = pAC->dev[devNbr];
+
+	if (SkGeOpen(dev) != 0) {
+		return (-1);
+	} else {
+		/*
+		** Function SkGeOpen() uses MOD_INC_USE_COUNT (2.2/2.4) 
+		** or try_module_get() (2.6) to increase the number of 
+		** users for a device, but if a device was just under 
+		** control of the DIAG, that count is OK already and 
+		** does not need to be adapted! Hence the opposite 
+		** MOD_DEC_USE_COUNT or module_put() needs to be used 
+		** again to correct that.
+		*/
+		module_put(THIS_MODULE);
+	}
+
+	/*
+	** Use correct MTU size and indicate to kernel TX queue can be started
+	*/ 
+	if (SkGeChangeMtu(dev, dev->mtu) != 0) {
+		return (-1);
+	} 
+	return (0);
+
+} /* SkDrvInitAdapter */
+
+static int __init sk98lin_init(void)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
+	return pci_register_driver(&sk98lin_driver);
+#else
+	return pci_module_init(&sk98lin_driver);
+#endif
+}
+
+static void __exit sk98lin_cleanup(void)
+{
+	pci_unregister_driver(&sk98lin_driver);
+}
+
+module_init(sk98lin_init);
+module_exit(sk98lin_cleanup);
+
+
+#ifdef DEBUG
+/****************************************************************************/
+/* "debug only" section *****************************************************/
+/****************************************************************************/
+
+/*****************************************************************************
+ *
+ *	DumpMsg - print a frame
+ *
+ * Description:
+ *	This function prints frames to the system logfile/to the console.
+ *
+ * Returns: N/A
+ *	
+ */
+static void DumpMsg(
+struct sk_buff *skb,  /* linux' socket buffer  */
+char           *str)  /* additional msg string */
+{
+	int msglen = (skb->len > 64) ? 64 : skb->len;
+
+	if (skb == NULL) {
+		printk("DumpMsg(): NULL-Message\n");
+		return;
+	}
+
+	if (skb->data == NULL) {
+		printk("DumpMsg(): Message empty\n");
+		return;
+	}
+
+	printk("DumpMsg: PhysPage: %p\n", 
+		page_address(virt_to_page(skb->data)));
+	printk("--- Begin of message from %s , len %d (from %d) ----\n", 
+		str, msglen, skb->len);
+	DumpData((char *)skb->data, msglen);
+	printk("------- End of message ---------\n");
+} /* DumpMsg */
+
+/*****************************************************************************
+ *
+ *	DumpData - print a data area
+ *
+ * Description:
+ *	This function prints a area of data to the system logfile/to the
+ *	console.
+ *
+ * Returns: N/A
+ *	
+ */
+static void DumpData(
+char  *p,     /* pointer to area containing the data */
+int    size)  /* the size of that data area in bytes */
+{
+	register int  i;
+	int           haddr = 0, addr = 0;
+	char          hex_buffer[180] = { '\0' };
+	char          asc_buffer[180] = { '\0' };
+	char          HEXCHAR[] = "0123456789ABCDEF";
+
+	for (i=0; i < size; ) {
+		if (*p >= '0' && *p <='z') {
+			asc_buffer[addr] = *p;
+		} else {
+			asc_buffer[addr] = '.';
+		}
+		addr++;
+		asc_buffer[addr] = 0;
+		hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
+		haddr++;
+		hex_buffer[haddr] = HEXCHAR[*p & 0x0f];
+		haddr++;
+		hex_buffer[haddr] = ' ';
+		haddr++;
+		hex_buffer[haddr] = 0;
+		p++;
+		i++;
+		if (i%16 == 0) {
+			printk("%s  %s\n", hex_buffer, asc_buffer);
+			addr = 0;
+			haddr = 0;
+		}
+	}
+} /* DumpData */
+
+
+/*****************************************************************************
+ *
+ *	DumpLong - print a data area as long values
+ *
+ * Description:
+ *	This function prints a long variable to the system logfile/to the
+ *	console.
+ *
+ * Returns: N/A
+ *	
+ */
+static void DumpLong(
+char  *pc,    /* location of the variable to print */
+int    size)  /* how large is the variable?        */
+{
+	register int   i;
+	int            haddr = 0;
+	char           hex_buffer[180] = { '\0' };
+	char           HEXCHAR[] = "0123456789ABCDEF";
+	long          *p = (long*) pc;
+	int            l;
+
+	for (i=0; i < size; ) {
+		l = (long) *p;
+		hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
+		haddr++;
+		hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf];
+		haddr++;
+		hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf];
+		haddr++;
+		hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf];
+		haddr++;
+		hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf];
+		haddr++;
+		hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf];
+		haddr++;
+		hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf];
+		haddr++;
+		hex_buffer[haddr] = HEXCHAR[l & 0x0f];
+		haddr++;
+		hex_buffer[haddr] = ' ';
+		haddr++;
+		hex_buffer[haddr] = 0;
+		p++;
+		i++;
+		if (i%8 == 0) {
+			printk("%4x %s\n", (i-8)*4, hex_buffer);
+			haddr = 0;
+		}
+	}
+	printk("------------------------\n");
+} /* DumpLong */
+
+#endif
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
+
diff --git a/drivers/net/sk98lin/skgeasf.c b/drivers/net/sk98lin/skgeasf.c
new file mode 100755
index 0000000..0680b8b
--- /dev/null
+++ b/drivers/net/sk98lin/skgeasf.c
@@ -0,0 +1,6444 @@
+/******************************************************************************
+ *
+ * Name:    skgeasf.c
+ * Project: Gigabit Ethernet Adapters, Common Modules
+ * Version: $Revision: 1.1.2.6 $
+ * Date:    $Date: 2007/06/28 09:40:54 $
+ * Purpose: ASF Handler.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  (C)Copyright 1998-2002 SysKonnect GmbH.
+ *  (C)Copyright 2002-2003 Marvell.
+ *
+ *  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.
+ *
+ *  The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * This module is intended to handle all the asf functions
+ *
+ * Include File Hierarchy:
+ *
+ *   "h/skdrv1st.h"
+ *   "h/skdrv2nd.h"
+ *
+ ******************************************************************************/
+
+/*
+ Event queue and dispatcher
+*/
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+"$Header: /data/cvs/sweprojects/yukon2/lindrv/asf_linux/Attic/skgeasf.c,v 1.1.2.6 2007/06/28 09:40:54 marcusr Exp $" ;
+#endif
+
+#define __SKASF_C
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* cplusplus */
+
+
+// #include <ntddk.h>
+// #include <wdm.h>
+
+
+#include "h/sktypes.h"
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#include "h/skgeasf.h"
+#include "h/skgespi.h"
+#include "h/skfops.h"
+#include <acpi/acpi.h>
+
+//#include "h/yuk.h"
+//#include "h/skvpd.h"
+
+//#include <stdlib.h>
+
+static char *AsfFileName  = "/etc/sk98lin/AcpiAsf.bin";
+#ifndef USE_ASF_DASH_FW
+static char *IpmiFileNameS1  = "/etc/sk98lin/ipmiyk2-s1.bin";
+static char *IpmiFileNameS2  = "/etc/sk98lin/ipmiyk2-s2.bin";
+#endif
+#ifdef USE_ASF_DASH_FW
+static char *DashFileNameS1  = "/etc/sk98lin/dashyex-s1.bin";
+static char *DashFileNameS2  = "/etc/sk98lin/dashyex-s2.bin";
+#endif
+// static char *SimuAsfTab 	= "/etc/sk98lin/AcpiAsf.bin";
+
+// ARP pattern 40 byte (5 bytes in mask)
+// this pattern length corresponds with YLCI_MACRXFIFOTHRES
+// Pattern mask for ARP Frames
+#ifdef ASF_ONLY_ARP_REQUEST
+static SK_U8 ARP_FRAME_PATTERN[] =
+{
+    /* MAC Header - 14 bytes */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Dest MAC Addr */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Src MAC Addr  */
+    0x08, 0x06,                              /*Frame Type    */
+    /* ARP Header - 28 bytes */
+    0x00, 0x01,                              /* hard type    */
+    0x08, 0x00,                              /* prot type    */
+    0x06,                                    /* hard size    */
+    0x04,                                    /* prot size    */
+    0x00, 0x01,                              /* op = request */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /* senders mac  */
+    0x00, 0x00, 0x00, 0x00,                  /* senders ip   */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /* target mac   */
+    0x00, 0x00};
+static SK_U8 ARP_PATTERN_MASK[] = { 0x00, 0xF0, 0x3F, 0x00, 0x00 };
+#else
+static SK_U8 ARP_FRAME_PATTERN[] =
+{
+    /* MAC Header - 14 bytes */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Dest MAC Addr */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Src MAC Addr  */
+    0x08, 0x06,                              /*Frame Type    */
+    /* ARP Header - 28 bytes */
+    0x00, 0x01,                              /* hard type    */
+    0x08, 0x00,                              /* prot type    */
+    0x06,                                    /* hard size    */
+    0x04,                                    /* prot size    */
+    0x00, 0x00,                              /* op = request */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /* senders mac  */
+    0x00, 0x00, 0x00, 0x00,                  /* senders ip   */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /* target mac   */
+    0x00, 0x00};
+static SK_U8 ARP_PATTERN_MASK[] = { 0x00, 0xF0, 0x00, 0x00, 0x00 };
+#endif
+
+// RSP pattern - 40 bytes (this makes 5 bytes in RSP_PATTERN_MASK)
+// this pattern length corresponds with YLCI_MACRXFIFOTHRES
+static SK_U8 RSP_FRAME_PATTERN[] =
+{   /* MAC Header (14 bytes) */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     /*Dest MAC Addr*/
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     /*Src MAC Addr */
+    0x08, 0x00,                             /*Frame Type   */
+    /* IP Header (20 bytes) */
+    0x45, 0x00, 0x00, 0x00,                 /* Version & Header Length */
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x11, 0x00, 0x00,                 /* Protocol */
+    0x00, 0x00, 0x00, 0x00,                 /*Src IP address*/
+    0x00, 0x00, 0x00, 0x00,                 /*My IP address*/
+    /* part of UDP Header (6 bytes) */
+    0x00, 0x00,                             /* src port   */
+    0x02, 0x98,                             /* dest. port */
+    0x00, 0x00};                            /* length     */
+
+// Pattern mask for RSP Frames
+static SK_U8 RSP_PATTERN_MASK[] = { 0x00, 0x70, 0x80, 0x00, 0x30 };
+
+// RMCP pattern (unsecure port)
+// this pattern length corresponds with YLCI_MACRXFIFOTHRES
+static SK_U8 RMCP_FRAME_PATTERN[] =
+{   /* MAC Header */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Dest MAC Addr*/
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Src MAC Addr */
+    0x08, 0x00,                              /*Frame Type   */
+    /* IP Header */
+    0x45, 0x00, 0x00, 0x00,                  /* Version & Header Length */
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x11, 0x00, 0x00,                  /* Protocol */
+    0x00, 0x00, 0x00, 0x00,                  /*Src IP address*/
+    0x00, 0x00, 0x00, 0x00,                  /*My IP address*/
+    /* UDP Header */
+    0x00, 0x00,                             /* src port */
+    0x02, 0x6f,                             /* unsecure dest. port */
+    0x00, 0x00};
+
+// Pattern mask for RMCP Frames
+static SK_U8 RMCP_PATTERN_MASK[] = { 0x00, 0x70, 0x80, 0x00, 0x30 };
+
+#if 0
+// TCP pattern
+static SK_U8 TCP_FRAME_PATTERN[] =
+{   /* MAC Header */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Dest MAC Addr*/
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Src MAC Addr */
+    0x08, 0x00,                              /*Frame Type   */
+    /* IP Header */
+    0x45, 0x00, 0x00, 0x00,                  /* Version & Header Length */
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x06, 0x00, 0x00,                  /* Protocol */
+    0x00, 0x00, 0x00, 0x00,                  /*Src IP address*/
+    0x00, 0x00, 0x00, 0x00,                  /*My IP address*/
+    /* UDP Header */
+    0x00, 0x00,                             /* src port */
+    0x02, 0x6f,                             /* unsecure dest. port */
+    0x00, 0x00};
+
+// Pattern mask for TCP Frames
+static SK_U8 TCP_PATTERN_MASK[] = 
+{ 0x00, 0x70, 0x80, 0x00, 0x30 };
+#endif
+
+// ICMP pattern
+static SK_U8 ICMP_FRAME_PATTERN[] =
+{   /* MAC Header */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Dest MAC Addr*/
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /*Src MAC Addr */
+    0x08, 0x00,                              /*Frame Type   */
+    /* IP Header */
+    0x45, 0x00, 0x00, 0x00,                  /* Version & Header Length */
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x01, 0x00, 0x00,                  /* Protocol */
+    0x00, 0x00, 0x00, 0x00,                  /*Src IP address*/
+    0x00, 0x00, 0x00, 0x00,                  /*My IP address*/
+    /* ICMP Header */
+    0x00, 0x00,                          
+    0x00, 0x00,                      
+    0x00, 0x00};
+
+// Pattern mask for ICMP Frames
+static SK_U8 ICMP_PATTERN_MASK[] = 
+{ 0x00, 0x70, 0x80, 0x00, 0x00 };
+
+// SNMP pattern
+static SK_U8 SNMP_FRAME_PATTERN[] =
+{   /* MAC Header */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /* Dest MAC Addr */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,      /* Src MAC Addr */
+    0x08, 0x00,                              /* Frame Type */
+    /* IP Header */
+    0x45, 0x00, 0x00, 0x00,                  /* Version & Header Length */
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x11, 0x00, 0x00,                  /* Protocol */
+    0x00, 0x00, 0x00, 0x00,                  /* Src IP address */
+    0x00, 0x00, 0x00, 0x00,                  /* My IP address */
+    /* UDP Header */
+    0x00, 0x00,                              /* src port */
+    0x00, 0xa1,                              /* unsecure dest. port */
+    0x00, 0x00};
+
+// Pattern mask for SNMP Frames
+static SK_U8 SNMP_PATTERN_MASK[] = 
+{ 0x00, 0x70, 0x80, 0x00, 0x30 };
+
+/*****************************************************************************
+*
+* SkAsfRestorePattern - interface function (global symbol)
+*
+* Description:
+* restores pattern for ASF and IPMI
+*
+* Returns:
+*   Always 0
+*/
+
+int SkAsfRestorePattern (
+    SK_AC *pAC ,    /* Pointer to adapter context */
+    SK_IOC IoC)     /* IO context handle */
+{
+    if (pAC->AsfData.OpMode == SK_GEASF_MODE_ASF) {
+
+        // asf mode ->  we are running on
+        // yukon ec with only one port
+        AsfSetUpPattern(pAC, IoC, 0);
+
+    } else {
+        if (pAC->AsfData.OpMode == SK_GEASF_MODE_IPMI) {
+            // ipmi mode ->  we are running on
+            // yukon 2 with at least one port
+            AsfSetUpPattern(pAC, IoC, 0);       // port A
+
+            if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+                AsfSetUpPattern(pAC, IoC, 1);   // port B
+            }
+        }
+    }
+
+    return (SK_ASF_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+*
+* SkAsfInit - Init function of ASF
+*
+* Description:
+*   SK_INIT_DATA: Initialises the data structures
+*   SK_INIT_IO: Resets the XMAC statistics, determines the device and
+*    connector type.
+*   SK_INIT_RUN: Starts a timer event for port switch per hour
+*    calculation.
+*
+* Returns:
+*   Always 0
+*/
+int SkAsfInit(
+             SK_AC *pAC,    /* Pointer to adapter context */
+             SK_IOC IoC,    /* IO context handle */
+             int Level)     /* Initialization level */
+{
+	SK_U32          TmpVal32;
+	SK_U32          FlashOffset = 0;
+	SK_U32          i;
+
+	SK_U32          FileLengthS1;
+	SK_U32          FileLengthS2;
+	char            *FwFileNameS1 = NULL;
+	char            *FwFileNameS2 = NULL;
+	SK_U8           *pAsfFwS1 = NULL;
+	SK_U8           *pAsfFwS2 = NULL;
+
+	SK_U8           FlashOk;
+	int             RetCode;
+	SK_BOOL         DoUpdate = SK_FALSE;
+	SK_U8           lRetCode;
+	SK_U32          FwImageCsOk;
+	SK_U32          FwFlashCsOk;
+	SK_U32          FwImageCs = 0;
+	SK_U32          FwFlashCs = 0;
+	SK_U32          FwCs;
+	SK_U32          *pTmp32;
+	SK_U8           *pHciRecBuf;
+	SK_EVPARA       EventParam; /* Event struct for timer event */
+	unsigned long   FlashSize;
+	unsigned long   EraseOff = 0;
+	SK_U32          SpiRetVal;
+	SK_U8           Tmp1Val8, Tmp2Val8;
+	SK_BOOL         YukonEcA1;
+	SK_U8           OldGuid[16];
+	SK_U8           AsfFlag = 0, IpmiFlag = 0, AsfDashFlag = 0;
+	SK_U8           AsfHintBit = 0, IpmiHintBit = 0, NoHintBit = 0;
+
+	RetCode = SK_ASF_PNMI_ERR_OK;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+		("ASF: SkAsfInit: Called, level=%d  sizof ASF-MIB:0x%x Bytes\n", Level, sizeof(STR_ASF_MIB) ) );
+
+	/* YukonEcA1 introduced by rschmidt */
+	YukonEcA1 = (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC && pAC->GIni.GIChipRev == CHIP_REV_YU_EC_A1);
+
+	switch(Level)
+	{
+	case SK_INIT_DATA:
+		/* Set structure to zero */
+		//  This will be done in function "AsfReadConfiguration"
+		//  SK_MEMSET((char *)&pAC->AsfData, 0, sizeof(pAC->AsfData));
+
+		pAC->AsfData.ActivePort = 0;
+		pAC->AsfData.OpMode     = SK_GEASF_MODE_IPMI;
+		pAC->AsfData.ChipMode   = SK_GEASF_CHIP_UNKNOWN;
+
+		pAC->AsfData.InitState  = ASF_INIT_UNDEFINED;
+		break;
+
+	case SK_INIT_IO:
+#if (0)
+		/*  Set OS Present Flag in ASF Status and Command Register */
+		SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+		TmpVal32 |= BIT_4;
+		SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );
+#endif
+
+#ifdef USE_ASF_DASH_FW
+		AsfResetOsPresentBit( pAC, IoC );
+
+		YlciEnablePattern( pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ARP );
+		YlciEnablePattern( pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ICMP );
+		YlciEnablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_SNMP);
+#endif
+
+#ifdef ASF_CHECK_HIDDEN_ID  // here we will check hidden id _and_ chip id
+
+		/* check chip id */
+		SK_IN8( IoC, B2_CHIP_ID, &Tmp1Val8 );
+		switch(Tmp1Val8)
+		{
+
+#ifdef CHIP_ID_YUKON_EX					
+		case CHIP_ID_YUKON_EX:
+		  pAC->AsfData.ChipMode = SK_GEASF_CHIP_EX;
+		  
+		  //pAC->AsfData.FlashOffs 	= ASF_FLASH_EX_OFFS;
+		  //pAC->AsfData.FlashOffsVer 	= ASF_FLASH_EX_OFFS_VER;
+		  //pAC->AsfData.FlashOffsRev 	= ASF_FLASH_EX_OFFS_REV;
+		  //pAC->AsfData.FlashOffsCs 	= ASF_FLASH_EX_OFFS_CS;
+		  //pAC->AsfData.FlashOffsGuid	= ASF_FLASH_EX_OFFS_GUID;
+		  //pAC->AsfData.FlashOffsAcpi	= ASF_FLASH_EX_OFFS_ACPI;
+		  break;
+#endif  //  CHIP_ID_YUKON_EX
+		case CHIP_ID_YUKON_EC:
+			/* YUKON_EC */
+			/* chip-id is ok, check hidden id */
+			SK_IN8( IoC, B2_MAC_CFG, &Tmp2Val8 );
+			Tmp2Val8 &= 0x03;
+			if( (Tmp2Val8 != 1) &&       //  88E8052
+				(Tmp2Val8 != 3) ) {      //  88E8050
+				RetCode = SK_ASF_PNMI_ERR_GENERAL;
+			} else {
+				pAC->AsfData.ChipMode = SK_GEASF_CHIP_EC;
+			}
+			break;
+		case CHIP_ID_YUKON_XL:
+			/* YUKON_2 */
+                        /* chip-id is ok, check hidden id */
+			SK_IN8( IoC, B2_MAC_CFG, &Tmp2Val8 );
+			Tmp2Val8 &= 0x03;
+			if(Tmp2Val8 != 0) {
+				RetCode = SK_ASF_PNMI_ERR_GENERAL;
+			} else {
+				pAC->AsfData.ChipMode = SK_GEASF_CHIP_Y2;
+			}
+			break;
+		default:
+			/* Nothing to do. Chip id does not match */
+			RetCode = SK_ASF_PNMI_ERR_GENERAL;
+			break;
+		}
+
+		if (RetCode != SK_ASF_PNMI_ERR_OK) {
+
+			pAC->AsfData.InitState = ASF_INIT_ERROR_CHIP_ID;
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF/IPMI NOT SUPPORTED ***\n"));
+
+			/* hidden ID doesn't match (which card do we access?)
+			// do not set any registers
+
+			AsfDisable(pAC, IoC);
+
+			AsfResetCpu(pAC, IoC);       // reset cpu
+
+			// disable all pattern for asf/ipmi
+			YlciDisablePattern(pAC, IoC, 0, 4);
+			YlciDisablePattern(pAC, IoC, 0, 5);
+			YlciDisablePattern(pAC, IoC, 0, 6);
+
+			if ( (CHIP_ID_YUKON_2(pAC)) && (pAC->GIni.GIMacsFound == 2) ) {
+				// do not forget the second link
+				// disable all pattern for asf/ipmi
+				YlciDisablePattern(pAC, IoC, 1, 4);
+				YlciDisablePattern(pAC, IoC, 1, 5);
+				YlciDisablePattern(pAC, IoC, 1, 6);
+			}
+			*/
+			break;
+		}
+
+#endif
+		/* CHECK the ASF hint bits...
+		 * all YukonII:
+		 * Application Information Register auf 0x011e, Bit 7:6
+		 * 
+		 * Kodierung:
+		 *      0b00    kein "hint"; jetziger Zustand
+		 *      0b01    customer wants ASF to be loaded
+		 *      0b10    customer wants IPMI to be loaded
+		 *      0b11    customer does not want ASF or IPMI to go in here
+		 * 
+		 *  Alle bisherigen EEPROM Versionen bringen 0b00.
+		 */
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** CHECK ASF hint bits ***\n"));
+		SK_IN32(IoC, B2_Y2_HW_RES, &TmpVal32);
+		switch(TmpVal32 & 0xc0) {
+		case 0xc0:
+			AsfHintBit  = 0;
+			IpmiHintBit = 0;
+			NoHintBit   = 1;
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF hint bits: NO ASF/IPMI ***\n"));
+			break;
+		case 0x40:
+			AsfHintBit  = 1;
+			IpmiHintBit = 0;
+			NoHintBit   = 0;
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF hint bits: ASF ***\n"));
+			break;
+		case 0x80:
+			AsfHintBit  = 0;
+			IpmiHintBit = 1;
+			NoHintBit   = 0;
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF hint bits: IPMI ***\n"));
+			break;
+		default:
+			AsfHintBit  = 0;
+			IpmiHintBit = 0;
+			NoHintBit   = 1;
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF hint bits: Default ASF/IPMI ***\n"));
+			break;
+		}
+
+		/* here we do not know which firmware we must load (ipmi or asf)... */
+		pAC->AsfData.OpMode = SK_GEASF_MODE_UNKNOWN;
+		AsfFlag  = 0;
+		IpmiFlag = 0;
+		AsfDashFlag = 0;		
+
+		/* try to open the ASF binary */
+		if ( fw_file_exists(pAC, AsfFileName) ) {
+			/* here we have found the asf binary */
+			
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF binary file found...\n"));
+			AsfFlag = 1;
+			FwFileNameS1 = AsfFileName;
+			FwFileNameS2 = NULL;
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("*** AsfFlag = 1 ***\n"));
+		} else {
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF binary file _NOT_ found!\n"));
+		}
+
+
+#ifdef USE_ASF_DASH_FW
+		/* try to open ASF DASH binary */
+		if ( fw_file_exists(pAC, DashFileNameS1)  && 
+			fw_file_exists(pAC, DashFileNameS2) ) {
+			/* here we have found the ASF DASH binary */
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF DASH binary file found...\n"));
+			AsfDashFlag = 1;
+			FwFileNameS1 = DashFileNameS1;
+			FwFileNameS2 = DashFileNameS2;
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("*** IpmiFlag = 1 ***\n"));
+		} else {
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF DASH binary file _NOT_ found!\n"));
+		}
+#else
+		/* try to open IPMI binary */
+		if ( fw_file_exists(pAC, IpmiFileNameS1)  && 
+			fw_file_exists(pAC, IpmiFileNameS2) ) {
+			/* here we have found the ipmi binary */
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** IPMI binary file found...\n"));
+			IpmiFlag = 1;
+			FwFileNameS1 = IpmiFileNameS1;
+			FwFileNameS2 = IpmiFileNameS2;
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("*** IpmiFlag = 1 ***\n"));
+		} else {
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** IPMI binary file _NOT_ found!\n"));
+		}
+#endif
+
+		/* set the operation mode */
+		if ( (AsfFlag == 1) && ( (AsfHintBit == 1) && (IpmiHintBit == 0) && (NoHintBit == 0) ) ) {
+		/* we are in the ASF mode */
+			if ( (pAC->AsfData.ChipMode == SK_GEASF_CHIP_EC) ||
+				(pAC->AsfData.ChipMode == SK_GEASF_CHIP_Y2) ) {
+				/* ASF can run on YukonEC and Yukon2 */
+				pAC->AsfData.OpMode = SK_GEASF_MODE_ASF;
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** SK_GEASF_MODE_ASF ***\n"));
+				YlciDisablePattern(pAC, IoC, 0, 5);  //  Disable ARP pattern, OS is now responsible for ARP handling
+			}
+		} else {
+		/* are we in the ipmi mode ? */
+			if ( (IpmiFlag == 1) && ( (IpmiHintBit == 1) && (AsfHintBit == 0) && (NoHintBit == 0) ) ) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("*** Ipmi bits OK - ChipMode: %x ***\n", pAC->AsfData.ChipMode));
+				if (pAC->AsfData.ChipMode == SK_GEASF_CHIP_Y2) {
+					/* IPMI can run only on Yukon2 */
+					pAC->AsfData.OpMode = SK_GEASF_MODE_IPMI;
+
+					/* set ASF enable bit in general register (0x0004)
+					 * and set the AsfEnable byte in pAC structure
+					 * (pAC->GIni.GIAsfEnabled = SK_TRUE)
+					 */
+					AsfEnable(pAC, IoC);
+
+					/* check if we have a dual port adapter */
+					if ( (CHIP_ID_YUKON_2(pAC)) && (pAC->GIni.GIMacsFound == 2) ) {
+						pAC->AsfData.DualMode = SK_GEASF_Y2_DUALPORT;
+					} else {
+						pAC->AsfData.DualMode = SK_GEASF_Y2_SINGLEPORT;
+					}
+
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+						("SkAsfInit: *** SK_GEASF_MODE_IPMI (%d) ***\n", pAC->AsfData.DualMode));
+
+#if 0
+					/*  Disable ARP pattern, OS is now responsible for ARP handling */
+					YlciDisablePattern(pAC, IoC, 0, 5);
+					// AsfSetUpPattern(pAC, IoC, 0);
+
+					if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+					/* Disable ARP pattern, OS is now responsible for ARP handling */
+						YlciDisablePattern(pAC, IoC, 1, 5);
+						// AsfSetUpPattern(pAC, IoC, 1);
+					}
+#endif
+				}
+			}
+		}
+
+#ifdef USE_ASF_DASH_FW
+		//  run Dash without hint bit
+		if (pAC->AsfData.OpMode == SK_GEASF_MODE_UNKNOWN) {
+		  if( (  (pAC->AsfData.ChipMode == SK_GEASF_CHIP_EC)|| 
+			 (pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX)  ) && 
+		      (AsfDashFlag == 1) && (NoHintBit == 1) ) {
+
+                    // ASF can run on YukonEC without hint bits
+                    pAC->AsfData.OpMode = SK_GEASF_MODE_DASH;
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_INIT, ("SkAsfInit: *** SK_GEASF_MODE_DASH EC ***\n"));
+		    
+		    /* To early, we need to do this if interface is up */
+                    // YlciDisablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ARP );  //  Disable ARP pattern, OS is now responsible for ARP handling
+                    // YlciDisablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ICMP);  //  Disable ICMP pattern, OS is now responsible for ICMP handling
+		  }
+		}
+#endif
+
+		if (pAC->AsfData.OpMode == SK_GEASF_MODE_UNKNOWN) {
+			if( (pAC->AsfData.ChipMode == SK_GEASF_CHIP_EC) && (AsfFlag == 1) && (NoHintBit == 1) ) {
+			/* ASF can run on YukonEC without hint bits */
+				pAC->AsfData.OpMode = SK_GEASF_MODE_ASF;
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** SK_GEASF_MODE_ASF EC ***\n"));
+				YlciDisablePattern(pAC, IoC, 0, 5);  //  Disable ARP pattern, OS is now responsible for ARP handling
+			} else {
+			/* error - we could not find our operation mode! */
+				pAC->AsfData.InitState = ASF_INIT_ERROR_OPMODE;
+				RetCode = SK_ASF_PNMI_ERR_GENERAL;
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfInit: *** ASF/IPMI UNKNOWN OPMODE ***\n"));
+
+				AsfDisable(pAC, IoC);    // disable pattern matching for ASF/IPMI
+
+				AsfResetCpu(pAC, IoC);       // reset cpu
+
+				/* disable all pattern for asf/ipmi */
+				YlciDisablePattern(pAC, IoC, 0, 4);
+				YlciDisablePattern(pAC, IoC, 0, 5);
+				YlciDisablePattern(pAC, IoC, 0, 6);
+
+				if ( (CHIP_ID_YUKON_2(pAC)) && (pAC->GIni.GIMacsFound == 2) ) {
+				/* do not forget the second link
+				 * disable all pattern for asf/ipmi
+				 */
+					YlciDisablePattern(pAC, IoC, 1, 4);
+					YlciDisablePattern(pAC, IoC, 1, 5);
+					YlciDisablePattern(pAC, IoC, 1, 6);
+				}
+				break; // leave "case SK_INIT_IO"
+			}
+		}
+
+		/* Send CheckAlive command to CPU */
+		if ( ((pAC->AsfData.OpMode == SK_GEASF_MODE_ASF) ||
+		      (pAC->AsfData.OpMode == SK_GEASF_MODE_IPMI) ||
+		      (pAC->AsfData.OpMode == SK_GEASF_MODE_DASH)) &&
+		     (RetCode == SK_ASF_PNMI_ERR_OK) ) {
+
+		  if( AsfCheckAliveCpu( pAC, IoC ) != 1 )  { //  Not alive
+		    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("           ******************************\n"));
+		    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfInit: *     CPU is NOT running !   *\n"));
+		    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("           ******************************\n"));
+		    pAC->AsfData.CpuAlive = 0;
+		  } else  {
+		    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("           ******************************\n"));
+		    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfInit: *        CPU is running      *\n"));
+		    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("           ******************************\n"));
+		    pAC->AsfData.CpuAlive = 1;
+		    
+#if 0
+		    if( AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_DRV_HELLO, 0, 0, 0, ASF_HCI_WAIT, 3 ) != HCI_EN_CMD_READY )  {
+		      printk("ASF: DRV_HELLO failed\n");
+		    } else {
+		      printk("ASF: DRV_HELLO OK\n");
+		    }
+#endif
+		  }
+		}
+
+		/* START FLASH PROC */
+		/* Try to open the FW image file    */
+		if (fw_read(pAC,FwFileNameS1,&pAsfFwS1,&FileLengthS1) && 
+			fw_read(pAC,FwFileNameS2,&pAsfFwS2,&FileLengthS2)) {
+			/* Set the flash offset to 128k */
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Flash files opened:\n"));
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("          %s: size: 0x%d offs:0x%x\n", FwFileNameS1, FileLengthS1, FlashOffset));
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("          %s: size: 0x%d offs:0x%x\n", FwFileNameS2, FileLengthS2, FlashOffset));
+
+#ifdef USE_ASF_DASH_FW
+			/*  calculate CS of the FW image */
+			pTmp32 = (SK_U32 *) pAsfFwS1;
+			for( i=0, FwCs=0; i<ASF_DASH_FLASH_SIZE_1; i+=4 )  {
+			  FwCs += *pTmp32;
+			  pTmp32++;
+			}
+
+			pTmp32 = (SK_U32 *) pAsfFwS2;
+			for( i=0; i<ASF_DASH_FLASH_SIZE_2; i+=4 )  {
+			  FwCs += *pTmp32;
+			  pTmp32++;
+			}
+#else
+			/*  calculate CS of the FW image */
+			pTmp32 = (SK_U32 *) pAsfFwS1;
+			for( i=0, FwCs=0; i<ASF_FLASH_SIZE; i+=4 )  {
+				FwCs += *pTmp32;
+				pTmp32++;
+			}
+
+			pTmp32 = (SK_U32 *) pAsfFwS2;
+			for( i=0; i<ASF_FLASH_SIZE; i+=4 )  {
+				FwCs += *pTmp32;
+				pTmp32++;
+			}
+
+#endif
+
+			if( FwCs == 0  )  {  //  CS == 0 => O.K.
+				FwImageCsOk = 1;
+				FwImageCs = *(pTmp32 - 1);
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    FW Image Checksum O.K. \n"));
+			} else  {
+				printk("sk98lin: File FW Checksum not OK\n");
+
+				FwImageCsOk = 0;
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: FW Image Checksum:0x%x\n", FwCs));
+			}
+
+#ifdef USE_ASF_DASH_FW
+			pAC->AsfData.DriverVersion[0] = 'v';
+			pAC->AsfData.DriverVersion[1] = '3';
+			pAC->AsfData.DriverVersion[2] = '.';
+			pAC->AsfData.DriverVersion[3] = '0';
+			pAC->AsfData.DriverVersion[4] = '0';
+
+			for( i=0; i<5; i++ )
+				pAC->AsfData.FileFwVersion[i] = *(pAsfFwS2 + ASF_FLASH_EX_OFFS_VER - 65536 + i);
+
+			pAC->AsfData.FileFwRev = *(pAsfFwS2 + ASF_FLASH_EX_OFFS_REV - 65536);
+#else
+			pAC->AsfData.DriverVersion[0] = 'v';
+			pAC->AsfData.DriverVersion[1] = '1';
+			pAC->AsfData.DriverVersion[2] = '.';
+			pAC->AsfData.DriverVersion[3] = '1';
+			pAC->AsfData.DriverVersion[4] = '0';
+
+			for( i=0; i<5; i++ )
+				pAC->AsfData.FileFwVersion[i] = *(pAsfFwS2 + ASF_FLASH_OFFS_VER - 65536 + i);
+
+			pAC->AsfData.FileFwRev = *(pAsfFwS2 + ASF_FLASH_OFFS_REV - 65536);
+#endif
+	
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    FW Image:%c%c%c%c %c Driver:%c%c%c%c\n",
+					pAC->AsfData.FileFwVersion[1], pAC->AsfData.FileFwVersion[2],
+					pAC->AsfData.FileFwVersion[3], pAC->AsfData.FileFwVersion[4],
+					pAC->AsfData.FileFwRev,
+					pAC->AsfData.DriverVersion[1], pAC->AsfData.DriverVersion[2],
+					pAC->AsfData.DriverVersion[3], pAC->AsfData.DriverVersion[4] ));
+
+
+			/* check, whether the FW file version suits the driver version */
+			if( (pAC->AsfData.FileFwVersion[1] == pAC->AsfData.DriverVersion[1]) &&
+				(pAC->AsfData.FileFwVersion[3] == pAC->AsfData.DriverVersion[3]) &&
+				(pAC->AsfData.FileFwVersion[4] == pAC->AsfData.DriverVersion[4]) &&
+				(FwImageCsOk == 1) ) {
+
+				/* read the flash  (upper 128k) */
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    FW suits the driver´s version\n"));
+
+				if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )  {
+				  SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Extreme -> Do not reset !!\n"));
+				}
+				else if (YukonEcA1)  {  // was if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_A1) before
+				  SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Chip Rev. A1 -> Do reset !!\n"));
+				  				  
+				  AsfResetCpu(pAC, IoC);
+
+
+				  // AsfSmartResetCpu( pAC, IoC, ASF_RESET_HOT );  // fixed in A2
+				} else  {
+					/*
+					 * just in case the FW is not running !!
+					 * (shouldn´t happen with A2 and later versions)
+					 */
+					if( !pAC->AsfData.CpuAlive )  {
+						SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("  *** FW is not running !!  *** \n"));
+
+						AsfResetCpu(pAC, IoC);
+						// AsfSmartResetCpu( pAC, IoC, ASF_RESET_HOT );
+						// AsfRunCpu( IoC );
+					}
+				}
+
+				if (!YukonEcA1) {
+#ifdef USE_ASF_DASH_FW
+				  AsfLockSpi( pAC, IoC );
+#else
+				  SK_OUT8(IoC, GPHY_CTRL + 2, 1);  //  Lock the SPI access
+#endif
+				}
+
+				spi_init_pac( pAC );
+
+				if (!flash_check_spi( &FlashSize )) {
+#ifdef USE_ASF_DASH_FW
+				  printk("sk98lin: SPI not present!\n");
+#endif
+				}
+				else {
+				  SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Flash found with size of %d KBytes\n", FlashSize/1024));
+				}
+
+				/* Read flash low pages */				
+#ifdef USE_ASF_DASH_FW
+				FwCs = 0;
+
+				SpiRetVal = spi_flash_manage( pAC->AsfData.FlashBuffer, ASF_FLASH_EX_OFFS, ASF_DASH_FLASH_SIZE_1, SPI_READ );
+
+				pTmp32 = (SK_U32 *) pAC->AsfData.FlashBuffer;
+				for( i=0; i< ASF_DASH_FLASH_SIZE_1; i+=4 )  {
+				  FwCs += *pTmp32;
+				  pTmp32++;
+				}
+#else
+				SpiRetVal = spi_flash_manage( pAC->AsfData.FlashBuffer, ASF_FLASH_OFFS, ASF_FLASH_SIZE, SPI_READ );
+
+				if( SpiRetVal == 0 )  {
+				/* calculate CS of the FW flash */
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Flash low pages loaded. Calculate the CS of the FW flash.\n"));
+
+					pTmp32 = (SK_U32 *) pAC->AsfData.FlashBuffer;
+					for( i=0, FwCs=0; i<ASF_FLASH_SIZE; i+=4 )  {
+						FwCs += *pTmp32;
+						pTmp32++;
+					}
+				} else {
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: SPI read\n"));
+					SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E002, SKERR_ASF_E002MSG);
+					RetCode = SK_ASF_PNMI_ERR_GENERAL;
+				}
+#endif
+
+
+#ifdef USE_ASF_DASH_FW
+				if( SpiRetVal == 0 )  {
+				} else {
+				  RetCode = SK_ASF_PNMI_ERR_GENERAL;
+				}
+#endif
+
+				/* Read flash high pages */
+#ifdef USE_ASF_DASH_FW
+				SpiRetVal = spi_flash_manage( pAC->AsfData.FlashBuffer, ASF_FLASH_EX_OFFS + 65536, ASF_DASH_FLASH_SIZE_2, SPI_READ );
+#else
+				SpiRetVal = spi_flash_manage( pAC->AsfData.FlashBuffer, ASF_FLASH_OFFS + 65536, ASF_FLASH_SIZE, SPI_READ );
+#endif
+
+#ifdef USE_ASF_DASH_FW
+				if( SpiRetVal == 0 )  {
+				} else {
+				  RetCode = SK_ASF_PNMI_ERR_GENERAL;
+				}
+#endif
+
+				if (!YukonEcA1) {
+#ifdef USE_ASF_DASH_FW
+				  AsfUnlockSpi( pAC, IoC );
+#else
+				  SK_OUT8(IoC, GPHY_CTRL + 2, 0);  //  Unlock the SPI access
+#endif
+				}
+
+#ifdef USE_ASF_DASH_FW
+				if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )  {							
+				  AsfRunCpu( pAC, IoC );
+				}
+#endif
+
+
+				if (( SpiRetVal == 0 ) && (!RetCode)) {
+				/* calculate CS of the FW flash */
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Flash high pages loaded. Calculate the CS of the FW flash.\n"));
+					pTmp32 = (SK_U32 *) pAC->AsfData.FlashBuffer;
+#ifdef USE_ASF_DASH_FW
+					for( i=0; i< ASF_DASH_FLASH_SIZE_2; i+=4 )  {
+#else
+					for( i=0; i<ASF_FLASH_SIZE; i+=4 )  {
+#endif					
+						FwCs += *pTmp32;
+						pTmp32++;
+					}
+
+					if( FwCs == 0  )  {  //  CS == 0 => O.K.
+						FwFlashCsOk = 1;
+						FwFlashCs = *(pTmp32 - 1);
+						SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    FW Flash Checksum O.K. \n"));
+					} else  {
+						FwFlashCsOk = 0;
+#ifdef USE_ASF_DASH_FW
+						printk("sk98lin: Chip FW Checksum not OK\n");
+#endif						
+						SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: FW Flash Checksum:0x%x\n", FwCs));
+					}
+
+#ifdef USE_ASF_DASH_FW
+					/* read the FW flash version/rev */
+					for( i=0; i<5; i++ ) {
+						pAC->AsfData.FlashFwVersion[i] =  pAC->AsfData.FlashBuffer[ASF_FLASH_EX_OFFS_VER - 65536 + i];
+					}
+
+					pAC->AsfData.FlashFwRev = pAC->AsfData.FlashBuffer[ASF_FLASH_EX_OFFS_REV - 65536 ];
+
+					/* read the GUID from flash */
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("   *** GUID ***\n"));
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    "));
+					for( i=0; i<16; i++ ) {
+						pAC->AsfData.Mib.Guid[i] =  pAC->AsfData.FlashBuffer[ASF_FLASH_EX_OFFS_GUID - 65536 +i];
+						SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%x ", pAC->AsfData.Mib.Guid[i]));
+						OldGuid[i] = pAC->AsfData.FlashBuffer[ASF_FLASH_EX_OFFS_GUID - 65536 +i];
+					}
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n"));
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    FW Flash:>>%c%c%c%c %c<<\n",
+						pAC->AsfData.FlashFwVersion[1], pAC->AsfData.FlashFwVersion[2],
+						pAC->AsfData.FlashFwVersion[3], pAC->AsfData.FlashFwVersion[4],
+						pAC->AsfData.FlashFwRev ));
+#else
+					/* read the FW flash version/rev */
+					for( i=0; i<5; i++ ) {
+						pAC->AsfData.FlashFwVersion[i] =  pAC->AsfData.FlashBuffer[ASF_FLASH_OFFS_VER - 65536 + i];
+					}
+
+					pAC->AsfData.FlashFwRev = pAC->AsfData.FlashBuffer[ASF_FLASH_OFFS_REV - 65536 ];
+
+					/* read the GUID from flash */
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("   *** GUID ***\n"));
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    "));
+					for( i=0; i<16; i++ ) {
+						pAC->AsfData.Mib.Guid[i] =  pAC->AsfData.FlashBuffer[ASF_FLASH_OFFS_GUID - 65536 +i];
+						SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%x ", pAC->AsfData.Mib.Guid[i]));
+						OldGuid[i] = pAC->AsfData.FlashBuffer[ASF_FLASH_OFFS_GUID - 65536 +i];
+					}
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n"));
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    FW Flash:>>%c%c%c%c %c<<\n",
+						pAC->AsfData.FlashFwVersion[1], pAC->AsfData.FlashFwVersion[2],
+ 						pAC->AsfData.FlashFwVersion[3], pAC->AsfData.FlashFwVersion[4],
+						pAC->AsfData.FlashFwRev ));
+#endif
+
+
+#ifdef USE_ASF_DASH_FW
+#ifdef FORCE_FW_FLASH
+					// Flash though Flash Version already the Chip and Flash Version of Driver are the same
+					pAC->AsfData.FileFwRev = 'x';
+#endif
+#endif
+
+					/* check the FW version/rev and update the flash if necessary */
+					if( (pAC->AsfData.FlashFwVersion[1] != pAC->AsfData.DriverVersion[1]) ||
+						(pAC->AsfData.FlashFwVersion[3] != pAC->AsfData.DriverVersion[3]) ||
+						(pAC->AsfData.FlashFwVersion[4] != pAC->AsfData.DriverVersion[4]) ||
+						(pAC->AsfData.FlashFwRev != pAC->AsfData.FileFwRev)               ||
+						(pAC->AsfData.FileFwRev == 'x')                                   ||   // Rev == 'x' means: do allways a flash update ! (for test purposes)
+						(FwFlashCsOk != 1))                                                   // Checksum error in flash
+					{
+						SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Updating flash\n"));
+						// AsfResetCpu( pAC, IoC );
+						for( i=0; i<ASF_FLASH_SIZE; i++ )
+							pAC->AsfData.FlashBuffer[i] = *(pAsfFwS1 + FlashOffset + i);
+
+						/* flash erase, determine flash size and select area to be erased */
+						switch (FlashSize) {
+							case ASF_FLASH_SIZE * 4:	/* 256 kB */
+#ifdef USE_ASF_DASH_FW
+							       FlashOffset = ASF_FLASH_EX_OFFS;
+ 								EraseOff = ASF_FLASH_EX_OFFS;
+#else
+								EraseOff = ASF_FLASH_OFFS;
+#endif
+
+								break;
+							case ASF_FLASH_SIZE * 2:	/* 128 kB */
+#ifdef USE_ASF_DASH_FW
+							        FlashOffset = 0;
+#endif
+								EraseOff = 0;
+								break;
+							default:			/* unsupported */
+								SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Unsupported Flash Size: %lu\n", FlashSize ));
+								RetCode = SK_ASF_PNMI_ERR_GENERAL;
+#ifdef USE_ASF_DASH_FW
+								printk("sk98lin: Flash Size not supported\n");
+#endif
+								break;
+						}
+						if (!RetCode)
+							DoUpdate = SK_TRUE;
+					} else  {
+						SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Flash is up to date\n"));
+#ifdef USE_ASF_DASH_FW
+						printk("sk98lin: Flash is up to date\n");
+#endif
+						
+					}
+
+
+
+					if (DoUpdate) {
+					        /* This hangs the CPU in case we do NOT flash */
+					        /* So we defer it to this point where we are */
+  					        /* sure we will flash. */
+#ifdef USE_ASF_DASH_FW
+					        AsfSmartResetCpu( pAC, IoC, ASF_RESET_COLD );
+#endif
+
+#ifdef USE_ASF_DASH_FW
+					        printk("sk98lin: Starting the flash process\n");
+#endif
+							
+						if (spi_flash_erase( EraseOff, ASF_FLASH_SIZE * 2) == 0 ) {
+							/*
+							 * Handle sector 1
+							 * (first flash file)
+							 */
+							/*  write sector 1 buffer to flash and check the buffer */
+#ifdef USE_ASF_DASH_FW
+							if (spi_flash_manage( pAC->AsfData.FlashBuffer, FlashOffset, ASF_DASH_FLASH_SIZE_1, SPI_WRITE ) == 0 ) {
+								/*  read buffer back */
+								if( spi_flash_manage( pAC->AsfData.FlashBuffer, FlashOffset, ASF_DASH_FLASH_SIZE_1, SPI_READ ) == 0 )  {
+								  /*  compare buffer with content of flash image file  */
+								  for( i=0,FlashOk=1; i<ASF_DASH_FLASH_SIZE_1; i++ )  {
+								    if( pAC->AsfData.FlashBuffer[i] != *(pAsfFwS1 + i) ) {
+								      FlashOk = 0;
+								    }
+								  }
+#else
+							if (spi_flash_manage( pAC->AsfData.FlashBuffer, ASF_FLASH_OFFS, ASF_FLASH_SIZE, SPI_WRITE ) == 0 ) {
+								/*  read buffer back */
+								if( spi_flash_manage( pAC->AsfData.FlashBuffer, ASF_FLASH_OFFS, ASF_FLASH_SIZE, SPI_READ ) == 0 )  {
+									/*  compare buffer with content of flash image file  */
+									for( i=0,FlashOk=1; i<ASF_FLASH_SIZE; i++ )  {
+										if( pAC->AsfData.FlashBuffer[i] != *(pAsfFwS1 + FlashOffset + i) )
+											FlashOk = 0;
+									}
+#endif
+									
+
+									if( FlashOk  )  {
+									/* read the GUID from flash */
+#ifdef USE_ASF_DASH_FW
+									  printk("sk98lin: Flash Part 1 succeeded\n");
+#endif
+									
+									   SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Flash successfully updated (Sector1)\n"));
+									} else  {
+#ifdef USE_ASF_DASH_FW
+									  printk("sk98lin: Flash Part 1 did not succeed\n");
+#endif									
+										RetCode = SK_ASF_PNMI_ERR_GENERAL;
+										SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: compare flash content (Sector1)\n"));
+										SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E007, SKERR_ASF_E007MSG);
+									}
+								} else  {
+									RetCode = SK_ASF_PNMI_ERR_GENERAL;
+									SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: Flash reread (Sector1)\n"));
+									SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E006, SKERR_ASF_E006MSG);
+								}
+							} else  {
+								RetCode = SK_ASF_PNMI_ERR_GENERAL;
+								SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: Flash write (Sector1)\n"));
+								SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E004, SKERR_ASF_E004MSG);
+							}
+
+
+							/*
+							 * Handle sector 2
+							 * (second flash file)
+							 */
+							FlashOk = 1;
+							for( i=0; i<ASF_FLASH_SIZE; i++ )
+#ifdef USE_ASF_DASH_FW
+								pAC->AsfData.FlashBuffer[i] = *(pAsfFwS2 + i);
+#else
+								pAC->AsfData.FlashBuffer[i] = *(pAsfFwS2 + FlashOffset + i);
+#endif
+
+#ifdef USE_ASF_DASH_FW
+							/*  write sector 2 buffer to flash and check the buffer */
+							if (spi_flash_manage( pAC->AsfData.FlashBuffer, FlashOffset + ASF_DASH_FLASH_SIZE_1, ASF_DASH_FLASH_SIZE_2, SPI_WRITE ) == 0 ) {
+								/*  read buffer back */
+								if( spi_flash_manage( pAC->AsfData.FlashBuffer, FlashOffset + ASF_DASH_FLASH_SIZE_1, ASF_DASH_FLASH_SIZE_2, SPI_READ ) == 0 )  {
+									/*  compare buffer with content of flash image file  */
+									for( i=0,FlashOk=1; i<ASF_DASH_FLASH_SIZE_2; i++ )  {
+										if( pAC->AsfData.FlashBuffer[i] != *(pAsfFwS2 + i) )
+											FlashOk = 0;
+									}
+#else
+							/*  write sector 2 buffer to flash and check the buffer */
+							if (spi_flash_manage( pAC->AsfData.FlashBuffer, ASF_FLASH_OFFS + 65536, ASF_FLASH_SIZE, SPI_WRITE ) == 0 ) {
+								/*  read buffer back */
+								if( spi_flash_manage( pAC->AsfData.FlashBuffer, ASF_FLASH_OFFS + 65536, ASF_FLASH_SIZE, SPI_READ ) == 0 )  {
+									/*  compare buffer with content of flash image file  */
+									for( i=0,FlashOk=1; i<ASF_FLASH_SIZE; i++ )  {
+										if( pAC->AsfData.FlashBuffer[i] != *(pAsfFwS2 +FlashOffset + i) )
+											FlashOk = 0;
+									}
+#endif
+
+									if( FlashOk  )  {
+#ifdef USE_ASF_DASH_FW
+									  printk("sk98lin: Flash Part 2 succeeded\n");
+#endif
+
+									/* read the GUID from flash */
+										for( i=0; i<16; i++ )
+											pAC->AsfData.Mib.Guid[i] =  pAC->AsfData.FlashBuffer[ASF_FLASH_OFFS_GUID - 65536 +i];
+
+										/* check if new GUID */
+										for( i=0; i<16; i++) {
+											if(OldGuid[i] != pAC->AsfData.Mib.Guid[i]) {
+												SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,(" *** NEW GUID (%x)***\n", pAC->AsfData.Mib.Guid[i]));
+												pAC->AsfData.NewGuid = 1;
+												break;
+											}
+										}
+										SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Flash successfully updated (Sector2)\n"));
+									} else  {
+#ifdef USE_ASF_DASH_FW
+									  printk("sk98lin: Flash Part 2 did not succeed\n");
+#endif
+									
+										RetCode = SK_ASF_PNMI_ERR_GENERAL;
+										SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: compare flash content (Sector2)\n"));
+										SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E007, SKERR_ASF_E007MSG);
+									}
+								} else  {
+									RetCode = SK_ASF_PNMI_ERR_GENERAL;
+									SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: Flash reread (Sector2)\n"));
+									SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E006, SKERR_ASF_E006MSG);
+								}
+							} else  {
+								RetCode = SK_ASF_PNMI_ERR_GENERAL;
+								SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: Flash write (Sector2)\n"));
+								SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E004, SKERR_ASF_E004MSG);
+							}
+						} else  {
+							RetCode = SK_ASF_PNMI_ERR_GENERAL;
+							SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: Flash erase\n"));
+							SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E003, SKERR_ASF_E003MSG);
+						}
+						/* write pattern etc. */
+						if (pAC->AsfData.OpMode == SK_GEASF_MODE_IPMI) {
+							/* ipmi on yukon2 */
+							AsfSetUpPattern(pAC, IoC, 0);
+							if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+								AsfSetUpPattern(pAC, IoC, 1);
+							}
+						}
+
+						/* run cpu */
+						AsfRunCpu( pAC, IoC );
+					} /* if DoUpdate */
+				} else {
+					SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error: SPI read\n"));
+					SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_ASF_E002, SKERR_ASF_E002MSG);
+					RetCode = SK_ASF_PNMI_ERR_GENERAL;
+				}
+			}
+
+			/* Clear the buffer */
+			if (pAsfFwS1 != NULL)
+				kfree(pAsfFwS1);
+			if (pAsfFwS2 != NULL)
+				kfree(pAsfFwS2);
+		}
+
+		break;
+
+	case SK_INIT_RUN:
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfInit: SK_INIT_RUN\n"));
+
+		if( pAC->AsfData.InitState != ASF_INIT_UNDEFINED ) {
+
+#ifdef USE_ASF_DASH_FW
+		  /* We need to reenable the OS here and the ARPs done by the HOST */
+		  /* as we will leave this function directly with quick break*/
+
+		  /*  Set OS Present Flag in ASF Status and Command Register */
+		  AsfSetOsPresentBit( pAC, IoC );
+
+		  /*  Disable ARP pattern, host system takes over the ARP handling */
+		  YlciDisablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ARP );  //  Disable ARP pattern, OS is now responsible for ARP handling
+		  YlciDisablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ICMP);  //  Disable ICMP pattern, OS is now responsible for ICMP handling
+		  YlciDisablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_SNMP );  //  Disable ARP pattern, OS is now responsible for SNMP handling
+
+		  AsfDisableFlushFifo( pAC, IoC );
+
+		  AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_DRV_HELLO, 0, 0, 0, ASF_HCI_WAIT, 3 );
+#endif
+		  
+		  break;
+		}
+		
+#ifndef USE_ASF_DASH_FW
+		YlciDisablePattern(pAC, IoC, 0, 5);  //  Disable ARP pattern, OS is now responsible for ARP handling
+
+		if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+			YlciDisablePattern(pAC, IoC, 1, 5);  //  Disable ARP pattern, OS is now responsible for ARP handling
+		}
+#endif
+
+		/* write pattern etc. */
+		if (pAC->AsfData.OpMode == SK_GEASF_MODE_IPMI) {
+		// ipmi on yukon2
+			AsfSetUpPattern(pAC, IoC, 0);
+			if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+				AsfSetUpPattern(pAC, IoC, 1);
+			}
+		}
+
+		if( !pAC->AsfData.CpuAlive )  {
+		  AsfResetCpu(pAC, IoC);
+		  AsfRunCpu( pAC, IoC );
+		}
+
+		/*  ASF MIB parameter to default values */
+		pAC->AsfData.Mib.WdTimeMax          = ASF_DEF_WATCHDOG_TIME_MAX;
+		pAC->AsfData.Mib.WdTimeMin          = ASF_DEF_WATCHDOG_TIME_MIN;
+		pAC->AsfData.Mib.RetransCountMin    = ASF_DEF_RETRANS_COUNT_MIN;
+		pAC->AsfData.Mib.RetransCountMax    = ASF_DEF_RETRANS_COUNT_MAX;
+		pAC->AsfData.Mib.RetransIntMin      = ASF_DEF_RETRANS_INT_MIN;
+		pAC->AsfData.Mib.RetransIntMax      = ASF_DEF_RETRANS_INT_MAX;
+		pAC->AsfData.Mib.HbIntMin           = ASF_DEF_HB_INT_MIN;
+		pAC->AsfData.Mib.HbIntMax           = ASF_DEF_HB_INT_MAX;
+		pAC->AsfData.Mib.Ena                = ASF_DEF_ASF_ENA;
+		pAC->AsfData.Mib.RspEnable          = 0;
+		pAC->AsfData.Mib.Retrans            = ASF_DEF_RETRANS;
+		pAC->AsfData.Mib.RetransInt         = ASF_DEF_RETRANS_INT;
+		pAC->AsfData.Mib.HbEna              = ASF_DEF_HB_ENA;
+		pAC->AsfData.Mib.HbInt              = ASF_DEF_HB_INT;
+		pAC->AsfData.Mib.WdEna              = ASF_DEF_WATCHDOG_ENA;
+		pAC->AsfData.Mib.WdTime             = ASF_DEF_WATCHDOG_TIME;
+		pAC->AsfData.Mib.CommunityName[0]   = 0x00;
+		pAC->AsfData.Mib.RlmtMode           = 0xff;     // only for IPMI op mode
+		pAC->AsfData.Mib.PattUpReq          = 0;        // update pattern request flag
+
+		/* Start ASF timer */
+		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+		SkTimerStart(pAC, IoC, &pAC->AsfData.AsfTimer,
+					  5000000, SKGE_ASF, SK_ASF_EVT_TIMER_EXPIRED,
+					  EventParam);
+		//  initialize the FW WD functionality
+		pAC->AsfData.FwWdIntervall = 120;
+		if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )  {
+		  pAC->AsfData.FwRamSize = 0;
+		} else {
+
+   		   if( RetCode == SK_ASF_PNMI_ERR_OK )  {
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Check FW Ramsize\n"));
+			lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_ASF_RAMSIZE, 0, 0, 1, ASF_HCI_WAIT, 2 );
+
+			if( lRetCode == HCI_EN_CMD_READY )  {
+			// Fetch received data from HCI interface
+				AsfHciGetData( pAC, &pHciRecBuf );
+				pAC->AsfData.FwRamSize  = ((SK_U16)*(pHciRecBuf+2)) << 8;
+				pAC->AsfData.FwRamSize |= ((SK_U16)*(pHciRecBuf+3)) << 0;
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** FW RamSize: %dkB \n", pAC->AsfData.FwRamSize));
+			}  //  if( lRetCode == HCI_EN_CMD_READY )
+			if( lRetCode == HCI_EN_CMD_ERROR )  {
+				SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** error\n"));
+				RetCode = SK_ASF_PNMI_ERR_GENERAL;
+			}
+		   }
+		}
+
+		if( RetCode == SK_ASF_PNMI_ERR_OK )  {
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** ASF Init O.K. *** (%d)\n", pAC->GIni.GIRamSize));
+			pAC->AsfData.InitState = ASF_INIT_OK;
+			pAC->GIni.GIRamSize -= pAC->AsfData.FwRamSize;  //  shorten RAM buffer by FwRamSize
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** New RAM value (%dk)\n", pAC->GIni.GIRamSize));
+
+#ifdef CHIP_ID_YUKON_EX				
+		  switch(pAC->AsfData.OpMode)  {
+		  case SK_GEASF_MODE_DASH:
+		    pAC->GIni.GINumOfPattern -= 6;
+		    break;
+		  default:
+		    pAC->GIni.GINumOfPattern -= 3;
+		    break;
+		  }
+		  SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_INIT,("    *** New # of pattern (%d)\n", pAC->GIni.GINumOfPattern));
+#endif // CHIP_ID_YUKON_EX	
+			
+		} else  {
+			SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** ASF Init failed ***\n"));
+
+			AsfSmartResetCpu( pAC, IoC, ASF_RESET_HOT );
+			pAC->AsfData.InitState = ASF_INIT_ERROR;  //  disable ASF functionality
+			// after reset the cpu clean up some important registers
+			AsfSetSMBusRegister(IoC);
+		}
+
+		/* fetch the home MAC address from adapter */
+		for (i = 0; i < 6; i++) {
+			SK_IN8(IoC, (B2_MAC_1 + i), &pAC->AsfData.Mib.MacSource[i] );
+		}
+
+#ifdef USE_ASF_DASH_FW
+		printk("sk98lin: Using IP %u.%u.%u.%u for DASH FW\n", (unsigned int)pAC->IpAddr[0], (unsigned int)pAC->IpAddr[1], (unsigned int)pAC->IpAddr[2], (unsigned int)pAC->IpAddr[3]);
+#endif
+			
+#ifdef USE_ASF_DASH_FW	
+		/* Write patterns to pattern RAM on the Yukon board*/
+		AsfSetUpPattern(pAC, IoC, 0);
+#endif
+
+#ifdef USE_ASF_DASH_FW
+		/*  Set OS Present Flag in ASF Status and Command Register */
+		AsfSetOsPresentBit( pAC, IoC );
+
+		/*  Disable ARP pattern, host system takes over the ARP handling */
+		YlciDisablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ARP );  //  Disable ARP pattern, OS is now responsible for ARP handling
+		YlciDisablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ICMP);  //  Disable ICMP pattern, OS is now responsible for ICMP handling
+		YlciDisablePattern(pAC, IoC, 0, ASF_DASH_PATTERN_NUM_SNMP);  //  Disable SNMP pattern, OS is now responsible for SNMP handling
+#endif
+
+#ifdef USE_ASF_DASH_FW
+		if( AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_DRV_HELLO, 0, 0, 0, ASF_HCI_WAIT, 3 ) != HCI_EN_CMD_READY )  {
+		  printk("sk98lin: Communication Driver <-> FW is failing\n");
+		} else {
+		  printk("sk98lin: Communication Driver <-> FW is working properly\n");
+		}
+#endif
+
+		break;
+
+	default:
+		break; /* Nothing todo */
+	}
+
+	return( RetCode );
+}
+
+/*****************************************************************************
+*
+* AsfSetSMBusRegister - cleaning up register for SMBus
+*
+* Description:  If the ASF FW goes into smart reset, this function is
+*               cleaning up the SMBus register.
+*
+* Returns:
+*/
+
+void AsfSetSMBusRegister(
+    SK_IOC IoC)    /* IO context handle */
+{
+
+    SK_U32 TmpVal32;
+    SK_U32 mask;
+
+    // get register
+    SK_IN32(IoC, REG_ASF_SMBUS_CFG, &TmpVal32);
+
+    // delete bit 4: SMBC_IE
+    // delete bit 5: SMBC_EA
+    // delete bit 6: SMBC_GCE
+    // delete bit 7: SMBC_DAE
+    // delete bit 8: SMBC_SAE
+
+    mask      = 0x000001f0;
+    TmpVal32 &= (~mask);
+
+    // set register
+    SK_OUT32(IoC, REG_ASF_SMBUS_CFG, TmpVal32);
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** ASF cleaning up SMBusRegister 0x%x with 0x%x ***\n", REG_ASF_SMBUS_CFG, TmpVal32));
+}
+
+
+/*****************************************************************************
+*
+* SkAsfDeInit - DeInit function of ASF
+*
+* Description:
+*
+* Returns:
+*   Always 0
+*/
+int SkAsfDeInit(
+SK_AC *pAC,         /* Pointer to adapter context */
+SK_IOC IoC )  {     /* IO context handle */
+#ifndef USE_ASF_DASH_FW
+SK_U32  TmpVal32;
+#endif
+
+#ifdef USE_ASF_DASH_FW
+    /*  Reset OS Present Flag in ASF Status and Command Register */
+    AsfResetOsPresentBit( pAC, IoC );
+#else
+    /*  Reset OS Present Flag in ASF Status and Command Register */
+    SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+    TmpVal32 &= ~BIT_4;
+    SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );
+#endif
+
+    if( pAC->AsfData.InitState == ASF_INIT_OK )  {
+#ifdef USE_ASF_DASH_FW
+      switch(pAC->AsfData.OpMode)  {
+      case SK_GEASF_MODE_ASF:
+	//  Enable ARP pattern, ASF FW is now responsible for ARP handling
+	YlciEnablePattern ( pAC, IoC, 0, ASF_PATTERN_ID_ARP );
+	break;
+      case SK_GEASF_MODE_IPMI:
+	//  Enable ARP pattern, ASF FW is now responsible for ARP handling
+	YlciEnablePattern ( pAC, IoC, 0, ASF_PATTERN_ID_ARP );
+	
+	if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+	  YlciEnablePattern ( pAC, IoC, 1, ASF_PATTERN_ID_ARP );
+	}
+	break;
+      case SK_GEASF_MODE_DASH:
+	//  Enable ARP pattern, ASF FW is now responsible for ARP handling
+	YlciEnablePattern( pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ARP );
+	YlciEnablePattern( pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ICMP );
+	YlciEnablePattern( pAC, IoC, 0, ASF_DASH_PATTERN_NUM_SNMP );		
+	break;
+      }  //  switch(pAC->AsfData.OpMode) 
+      
+      //  Inform the FW that the driver will be unloaded
+      AsfHciSendCommand( pAC ,IoC , YASF_HOSTCMD_DRV_GOODBYE, 0, 0, 0, ASF_HCI_WAIT, 2 );
+      
+      //  will be done in FW now		
+      // if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )
+      // AsfEnableFlushFifo( pAC, IoC );
+#else
+      if (pAC->AsfData.OpMode == SK_GEASF_MODE_ASF) {
+	//  Enable ARP pattern, ASF FW is now responsible for ARP handling
+	YlciEnablePattern ( pAC, IoC, 0, 5 );
+      }
+      
+      if (pAC->AsfData.OpMode == SK_GEASF_MODE_IPMI) {
+	//  Enable ARP pattern, ASF FW is now responsible for ARP handling
+	YlciEnablePattern ( pAC, IoC, 0, 5 );
+	
+	if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+	  YlciEnablePattern ( pAC, IoC, 1, 5 );
+	}
+      }
+      
+      //  Inform the FW that the driver will be unloaded
+      AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_DRV_GOODBYE, 0, 0, 0, ASF_HCI_WAIT, 2 );
+#endif
+    }
+
+    return( 0 );
+}
+
+/*****************************************************************************
+*
+* SkAsfDeInitStandBy - StandBy -DeInit function of ASF
+*
+* Description:
+*
+* Returns:
+*   Always 0
+*/
+int SkAsfDeInitStandBy(
+SK_AC *pAC,         /* Pointer to adapter context */
+SK_IOC IoC )  {     /* IO context handle */
+
+#ifdef USE_ASF_DASH_FW
+    if( pAC->AsfData.InitState == ASF_INIT_OK )  {	
+      //  will be done in FW now
+      if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )
+	AsfEnableFlushFifo( pAC, IoC );
+      
+      switch(pAC->AsfData.OpMode)  {
+      case SK_GEASF_MODE_ASF:
+      case SK_GEASF_MODE_IPMI:
+	//  Enable ARP pattern, ASF FW is now responsible for ARP handling
+	YlciEnablePattern ( pAC, IoC, pAC->AsfData.ActivePort, ASF_PATTERN_ID_ARP );
+	break;
+      case SK_GEASF_MODE_DASH:
+	//  Enable ARP pattern, ASF FW is now responsible for ARP handling
+	YlciEnablePattern( pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ARP );
+	YlciEnablePattern( pAC, IoC, 0, ASF_DASH_PATTERN_NUM_ICMP );		
+	YlciEnablePattern( pAC, IoC, 0, ASF_DASH_PATTERN_NUM_SNMP );
+	break;
+      }  //  switch(pAC->AsfData.OpMode) 
+      
+      //  Inform the FW that the driver will be unloaded
+      AsfHciSendCommand( pAC ,IoC , YASF_HOSTCMD_DRV_STANDBY, 0, 0, 0, ASF_HCI_WAIT, 2 );
+    }
+#else
+    if( pAC->AsfData.InitState == ASF_INIT_OK )  {
+        //  Enable ARP pattern, ASF FW is now responsible for ARP handling
+        YlciEnablePattern ( pAC, IoC, pAC->AsfData.ActivePort, 5 );
+        //  Inform the FW that the driver will be unloaded
+        AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_DRV_STANDBY, 0, 0, 0, ASF_HCI_WAIT, 2 );
+    }
+#endif
+
+    return( 0 );
+}
+
+/*****************************************************************************
+*
+* SkAsfInitStandBy - StandBy - Init function of ASF
+*
+* Description:
+*
+* Returns:
+*   Always 0
+*/
+int SkAsfInitStandBy(
+SK_AC   *pAC,       /* Pointer to adapter context */
+SK_IOC  IoC,        /* IO context handle */
+int     Level) {    /* Initialization level */
+#ifndef USE_ASF_DASH_FW
+    SK_U32          TmpVal32;
+#endif
+    SK_EVPARA       EventParam; /* Event struct for timer event */
+	
+#ifdef USE_ASF_DASH_FW
+    if( pAC->AsfData.InitState == ASF_INIT_OK )  {
+        switch(Level)
+        {
+            case SK_INIT_DATA:
+                /*  Set OS Present Flag in ASF Status and Command Register */
+	        AsfSetOsPresentBit( pAC, IoC );
+
+                //  Disable ARP pattern, host system takes over the ARP handling
+                YlciDisablePattern( pAC, IoC,pAC->AsfData.ActivePort, ASF_PATTERN_ID_ARP);
+                //  Inform the FW that the driver will be activated again
+                AsfHciSendCommand( pAC ,IoC , YASF_HOSTCMD_DRV_HELLO, 0, 0, 0, ASF_HCI_WAIT, 2 );
+
+                break;
+
+            case SK_INIT_IO:
+                break;
+
+            case SK_INIT_RUN:
+                SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+                SkTimerStart(pAC, IoC, &pAC->AsfData.AsfTimer,
+                            5000000, SKGE_ASF, SK_ASF_EVT_TIMER_EXPIRED,  EventParam);
+                break;
+        }  //  switch( Level )
+    }  //  if( pAC->AsfData.InitState == ASF_INIT_OK 
+#else
+    if( pAC->AsfData.InitState == ASF_INIT_OK )  {
+        switch(Level)
+        {
+            case SK_INIT_DATA:
+                /*  Set OS Present Flag in ASF Status and Command Register */
+                SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+                TmpVal32 |= BIT_4;
+                //  Disable ARP pattern, host system takes over the ARP handling
+                YlciDisablePattern ( pAC, IoC, pAC->AsfData.ActivePort, 5 );
+
+                // Inform the FW that the driver will be activated again
+		// Schlechte Idee, schaltet ASF beim laden des Treibers ab
+                // AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_DRV_HELLO, 0, 0, 0, ASF_HCI_WAIT, 2 );
+                break;
+
+            case SK_INIT_IO:
+                break;
+
+            case SK_INIT_RUN:
+                SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+                SkTimerStart(pAC, IoC, &pAC->AsfData.AsfTimer,
+                            5000000, SKGE_ASF, SK_ASF_EVT_TIMER_EXPIRED,  EventParam);
+                break;
+        }  //  switch( Level )
+    }  //  if( pAC->AsfData.InitState == ASF_INIT_OK )
+#endif
+    return( 0 );
+}
+
+
+
+/******************************************************************************
+*
+*   SkAsfSeprom2Mib     reads ASF MIB config data from SEPROM
+*
+*   Context:
+*
+*
+*   Returns:    0:  successful
+*               1:  error
+*/
+
+SK_I8 SkAsfSeprom2Mib(
+SK_AC *pAC,      /* Pointer to adapter context */
+SK_IOC IoC ) {   /* IO context handle */
+
+    SK_U8   ind;
+    SK_U8   i;
+    SK_U8   version;
+    SK_I8   RetCode;
+    SK_U32  our_reg2;
+    SK_U32  Len;
+
+    ind = 0;
+
+    VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
+    pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
+
+    Len = VpdReadBlock( pAC, IoC, &pAC->AsfData.VpdConfigBuf[0], ASF_VPD_CONFIG_BASE, ASF_VPD_CONFIG_SIZE );
+    if( Len == ASF_VPD_CONFIG_SIZE )  {
+        RetCode = SK_ASF_PNMI_ERR_OK;
+        /* check, whether the signature is valid */
+        if( pAC->AsfData.VpdConfigBuf[0] == 'A' &&
+            pAC->AsfData.VpdConfigBuf[1] == 'S' &&
+            pAC->AsfData.VpdConfigBuf[2] == 'F' &&
+            pAC->AsfData.VpdConfigBuf[3] == '!' ) {
+            ind = 4;
+            version = pAC->AsfData.VpdConfigBuf[ind++];
+            switch( version )  {
+                case 1:
+                    pAC->AsfData.Mib.Ena =          pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.RspEnable =    pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.Retrans =      (SK_U16)  pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.Retrans |=     (SK_U16) (pAC->AsfData.VpdConfigBuf[ind++] << 8);
+                    pAC->AsfData.Mib.RetransInt =   (SK_U32)  pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.RetransInt |=  (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 8);
+                    pAC->AsfData.Mib.RetransInt |=  (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 16);
+                    pAC->AsfData.Mib.RetransInt |=  (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 24);
+                    pAC->AsfData.Mib.HbEna =        pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.HbInt =        (SK_U32)  pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.HbInt |=       (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 8);
+                    pAC->AsfData.Mib.HbInt |=       (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 16);
+                    pAC->AsfData.Mib.HbInt |=       (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 24);
+                    pAC->AsfData.Mib.WdEna =        pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.WdTime =       (SK_U32)  pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.WdTime |=      (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 8);
+                    pAC->AsfData.Mib.WdTime |=      (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 16);
+                    pAC->AsfData.Mib.WdTime |=      (SK_U32) (pAC->AsfData.VpdConfigBuf[ind++] << 24);
+                    for( i=0; i<4; i++ )
+                        pAC->AsfData.Mib.IpDest[i] =        pAC->AsfData.VpdConfigBuf[ind++];
+                    for( i=0; i<4; i++ )
+                        pAC->AsfData.Mib.IpSource[i] =      pAC->AsfData.VpdConfigBuf[ind++];
+                    for( i=0; i<6; i++ )
+                        pAC->AsfData.Mib.MacDest[i] =       pAC->AsfData.VpdConfigBuf[ind++];
+                    for( i=0; i<64; i++ )
+                        pAC->AsfData.Mib.CommunityName[i] = pAC->AsfData.VpdConfigBuf[ind++];
+                    for( i=0; i<6; i++ )
+                        pAC->AsfData.Mib.Reserved[i] =      pAC->AsfData.VpdConfigBuf[ind++];
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("     O.K.\n"));
+                    break;
+
+                case 2:
+                    pAC->AsfData.Mib.Ena =                      pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.RspEnable =                pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.Retrans =      (SK_U16)    pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.RetransInt =   (SK_U32)    pAC->AsfData.VpdConfigBuf[ind++] * 10;
+                    pAC->AsfData.Mib.HbEna =                    pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.HbInt =        (SK_U32)    pAC->AsfData.VpdConfigBuf[ind++] * 10;
+                    pAC->AsfData.Mib.WdEna =                    pAC->AsfData.VpdConfigBuf[ind++];
+                    pAC->AsfData.Mib.WdTime =       (SK_U32)    pAC->AsfData.VpdConfigBuf[ind++] * 10;
+                    for( i=0; i<4; i++ )
+                        pAC->AsfData.Mib.IpDest[i] =        pAC->AsfData.VpdConfigBuf[ind++];
+                    for( i=0; i<4; i++ )
+                        pAC->AsfData.Mib.IpSource[i] =      pAC->AsfData.VpdConfigBuf[ind++];
+                    for( i=0; i<6; i++ )
+                        pAC->AsfData.Mib.MacDest[i] =       pAC->AsfData.VpdConfigBuf[ind++];
+                    for( i=0; i<10; i++ )
+                        pAC->AsfData.Mib.CommunityName[i] = pAC->AsfData.VpdConfigBuf[ind++];
+                    for( i=0; i<6; i++ )
+                        pAC->AsfData.Mib.Reserved[i] =      pAC->AsfData.VpdConfigBuf[ind++];
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("     O.K.\n"));
+                    break;
+
+                default:
+                    // invalidate ASF signature, this causes a new formating of the SEEPROM
+                    pAC->AsfData.VpdConfigBuf[0] = 'x';
+                    pAC->AsfData.VpdConfigBuf[1] = 'x';
+                    pAC->AsfData.VpdConfigBuf[2] = 'x';
+                    pAC->AsfData.VpdConfigBuf[3] = 'x';
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("     unknown version: 0x%x\n", version ));
+                    break;
+            }  //  switch( version )  {
+        }
+        else  {
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("     *** Error: Signature not valid\n"));
+        }
+    }  //  if( Len == ..  )
+    else  {
+        RetCode = SK_ASF_PNMI_ERR_GENERAL;
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("     *** failed\n"));
+    }
+
+    return( RetCode );
+}
+
+/******************************************************************************
+*
+*   SkAsfMib2Seprom     writes ASF MIB config data to SEPROM
+*
+*   Context:
+*
+*
+*   Returns:    0:  successful
+*               1:  error
+*/
+
+SK_I8 SkAsfMib2Seprom(
+SK_AC *pAC,      /* Pointer to adapter context */
+SK_IOC IoC ) {   /* IO context handle */
+
+    SK_U8   ind;
+    SK_U8   i;
+    SK_I8   RetCode;
+    SK_U32  our_reg2;
+    SK_U32  Len;
+    SK_U8   version;
+
+    version = 2;
+
+    ind = 0;
+    pAC->AsfData.VpdConfigBuf[ind++] = 'A';
+    pAC->AsfData.VpdConfigBuf[ind++] = 'S';
+    pAC->AsfData.VpdConfigBuf[ind++] = 'F';
+    pAC->AsfData.VpdConfigBuf[ind++] = '!';
+    pAC->AsfData.VpdConfigBuf[ind++] = version;
+    switch( version )  {
+        case 1:  //  101 Bytes
+            pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.Ena;
+            pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.RspEnable;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.Retrans >> 0) & 0x00ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.Retrans >> 8) & 0x00ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.RetransInt >> 0)  & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.RetransInt >> 8)  & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.RetransInt >> 16) & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.RetransInt >> 24) & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.HbEna;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.HbInt >> 0)  & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.HbInt >> 8)  & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.HbInt >> 16) & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.HbInt >> 24) & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.WdEna;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.WdTime >> 0)  & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.WdTime >> 8)  & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.WdTime >> 16) & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.WdTime >> 24) & 0x000000ff;
+            for( i=0; i<4; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.IpDest[i];
+            for( i=0; i<4; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.IpSource[i];
+            for( i=0; i<6; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.MacDest[i];
+            for( i=0; i<64; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.CommunityName[i];
+            for( i=0; i<6; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.Reserved[i];
+            break;
+
+        case 2:  //  40 Bytes
+            pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.Ena;
+            pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.RspEnable;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) pAC->AsfData.Mib.Retrans & 0x00ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.RetransInt / 10)  & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.HbEna;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.HbInt / 10)  & 0x000000ff;
+            pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.WdEna;
+            pAC->AsfData.VpdConfigBuf[ind++] = (SK_U8) (pAC->AsfData.Mib.WdTime / 10)  & 0x000000ff;
+            for( i=0; i<4; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.IpDest[i];
+            for( i=0; i<4; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.IpSource[i];
+            for( i=0; i<6; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.MacDest[i];
+            for( i=0; i<10; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.CommunityName[i];
+            for( i=0; i<6; i++ )
+                pAC->AsfData.VpdConfigBuf[ind++] = pAC->AsfData.Mib.Reserved[i];
+            break;
+
+        default:
+            break;
+    }  //  switch( version )  {
+
+
+
+    VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
+    pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
+
+    // enable Config write Reg 0x158
+    // SK_IN8( IoC, B2_TST_REG1, &TmpVal8 )
+    // TmpVal8 &= ~0x03;
+    // TmpVal8 |= 0x02;
+    // SK_OUT8( IoC, B2_TST_REG1, TmpVal8 )
+    SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfMib2Seprom \n"));
+    Len = VpdWriteBlock(pAC,IoC, &pAC->AsfData.VpdConfigBuf[0], ASF_VPD_CONFIG_BASE, ASF_VPD_CONFIG_SIZE );
+    if( Len == ASF_VPD_CONFIG_SIZE )  {
+        RetCode = SK_ASF_PNMI_ERR_OK;
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    O.K. \n"));
+    }
+    else  {
+        RetCode = SK_ASF_PNMI_ERR_GENERAL;
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** failed \n"));
+    }
+
+    // disable Config write Reg 0x158
+    // SK_IN8( IoC, B2_TST_REG1, &TmpVal8 )
+    // TmpVal8 &= ~0x03;
+    // TmpVal8 |= 0x01;
+    // SK_OUT8( IoC, B2_TST_REG1, TmpVal8 )
+    SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+    return( RetCode );
+}
+
+
+/******************************************************************************
+*
+*   SkAsfTriggerPetFrames
+*
+*   Context:
+*   init, pageable
+*
+*   Returns: void
+*/
+
+void SkAsfTriggerPetFrames (SK_IOC IoC, SK_U32 *TmpVal32)
+{
+
+    return;
+}
+
+/******************************************************************************
+*
+*   SkAsfPreSetOid -
+*
+* Context:
+*   init, pageable
+*
+* Returns:
+*/
+int SkAsfPreSetOid(
+            SK_AC *pAC, /* the adapter context */
+            SK_IOC IoC, /* I/O context */
+            SK_U32 Id,  /* OID  */
+            SK_U32 Inst,
+            SK_U8 *pBuf,
+            unsigned int *pLen)
+{
+    SK_U32 RetCode = SK_ASF_PNMI_ERR_OK;
+
+
+    switch( Id )  {
+        case OID_SKGE_ASF_ENA:
+            break;
+
+        default:
+            *pLen = 0;
+            RetCode = SK_ASF_PNMI_ERR_NOT_SUPPORTED;
+            break;
+    }
+
+    return(RetCode);
+}
+
+/******************************************************************************
+*
+*   SkAsfSetOid -
+*
+* Context:
+*   init, pageable
+*
+* Returns:
+*/
+int SkAsfSetOid(
+            SK_AC *pAC, /* the adapter context */
+            SK_IOC IoC, /* I/O context */
+            SK_U32 Id,  /* OID  */
+            SK_U32 Inst,
+            SK_U8 *pBuf,
+            unsigned int *pLen)
+{
+    SK_U16          i;
+
+    SK_U32  RetCode = SK_ASF_PNMI_ERR_OK;
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfSetOid -> OID:0x%x Len:%d ***********************\n", Id, *pLen ));
+
+    if( pAC->AsfData.InitState != ASF_INIT_OK )  {
+        return( SK_ASF_PNMI_ERR_GENERAL );
+    }
+
+    switch( Id )  {
+        case OID_SKGE_ASF_STORE_CONFIG:
+            pAC->AsfData.Mib.NewParam = 4;
+            break;
+
+        case OID_SKGE_ASF_ENA:
+            if( *pLen == 1 )  {
+                if( *pBuf != pAC->AsfData.Mib.Ena )
+                    pAC->AsfData.Mib.ConfigChange |= 0x01;
+                pAC->AsfData.Mib.Ena = *pBuf;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_ENA: %d\n",  pAC->AsfData.Mib.Ena ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_RETRANS:
+            if( *pLen == 2 )  {
+                pAC->AsfData.Mib.Retrans = *( (SK_U16 *) pBuf );
+                *pLen = 2;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS: %d\n",  pAC->AsfData.Mib.Retrans ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_RETRANS_INT:
+            if( *pLen == 2 )  {
+                pAC->AsfData.Mib.RetransInt = *( (SK_U16 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 2;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_INT: %d\n",  pAC->AsfData.Mib.RetransInt ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_HB_ENA:
+            if( *pLen == 1 )  {
+                pAC->AsfData.Mib.HbEna = *pBuf;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_HB_ENA: %d\n",  pAC->AsfData.Mib.HbEna ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_HB_INT:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.HbInt = *( (SK_U32 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_HB_INT: %d\n",  pAC->AsfData.Mib.HbInt ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_WD_ENA:
+            if( *pLen == 1 )  {
+                pAC->AsfData.Mib.WdEna = *pBuf;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_WD_ENA: %d\n",  pAC->AsfData.Mib.WdEna ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_WD_TIME:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.WdTime = *( (SK_U32 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_WD_TIME: %d\n",  pAC->AsfData.Mib.WdTime ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_IP_DEST:
+            if( AsfAsci2Ip( pBuf, *pLen, pAC->AsfData.Mib.IpDest )  == 1 )   {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_IP_DEST: %d.%d.%d.%d\n",
+                                        pAC->AsfData.Mib.IpDest[0], pAC->AsfData.Mib.IpDest[1],
+                                        pAC->AsfData.Mib.IpDest[2], pAC->AsfData.Mib.IpDest[3] ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_GENERAL;
+            break;
+
+        case OID_SKGE_ASF_MAC_DEST:
+            if( AsfAsci2Mac( pBuf, *pLen, pAC->AsfData.Mib.MacDest )  == 1 )   {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_MAC_DEST: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                        pAC->AsfData.Mib.MacDest[0], pAC->AsfData.Mib.MacDest[1],
+                                        pAC->AsfData.Mib.MacDest[2], pAC->AsfData.Mib.MacDest[3],
+                                        pAC->AsfData.Mib.MacDest[4], pAC->AsfData.Mib.MacDest[5] ));
+#ifdef ASF_FW_ARP_RESOLVE
+                //  just for FW-ARP-Resolve testing purposes
+//                for( i=0; i<6; i++ )
+//                    pAC->AsfData.Mib.MacDest[i] = 0;
+#endif  //  ASF_FW_ARP_RESOLVE
+
+            }
+            else
+                RetCode = SK_PNMI_ERR_GENERAL;
+            break;
+
+        case OID_SKGE_ASF_COMMUNITY_NAME:
+            for( i=0; (i<*pLen)&&(i<63); i++ )
+                pAC->AsfData.Mib.CommunityName[i] = *(pBuf + i);
+            pAC->AsfData.Mib.CommunityName[i] = 0;
+            break;
+
+        case OID_SKGE_ASF_RSP_ENA:
+            if( *pLen == 1 )  {
+                if( *pBuf != pAC->AsfData.Mib.RspEnable )
+                    pAC->AsfData.Mib.ConfigChange |= 0x02;
+
+                pAC->AsfData.Mib.RspEnable = *pBuf;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RSP_ENA: %d\n",  pAC->AsfData.Mib.RspEnable ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_RETRANS_COUNT_MIN:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.RetransCountMin = *( (SK_U32 *) pBuf );
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_COUNT_MIN: %d\n",  pAC->AsfData.Mib.RetransCountMin ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_RETRANS_COUNT_MAX:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.RetransCountMax = *( (SK_U32 *) pBuf );
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_COUNT_MAX: %d\n",  pAC->AsfData.Mib.RetransCountMax ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_RETRANS_INT_MIN:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.RetransIntMin = *( (SK_U32 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_INT_MIN: %d\n",  pAC->AsfData.Mib.RetransIntMin ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_RETRANS_INT_MAX:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.RetransIntMax = *( (SK_U32 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_INT_MAX: %d\n",  pAC->AsfData.Mib.RetransIntMax ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_HB_INT_MIN:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.HbIntMin = *( (SK_U32 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_HB_INT_MIN: %d\n",  pAC->AsfData.Mib.HbIntMin ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_HB_INT_MAX:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.HbIntMax = *( (SK_U32 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_HB_INT_MAX: %d\n",  pAC->AsfData.Mib.HbIntMax ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_WD_TIME_MIN:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.WdTimeMin = *( (SK_U32 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_WD_TIME_MIN: %d\n",  pAC->AsfData.Mib.WdTimeMin ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_WD_TIME_MAX:
+            if( *pLen == 4 )  {
+                pAC->AsfData.Mib.WdTimeMax = *( (SK_U32 *) pBuf ) * ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_WD_TIME_MAX: %d\n",  pAC->AsfData.Mib.WdTimeMax ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_KEY_OP:
+            if( *pLen == (RSP_KEYLENGTH*2) )  {
+                AsfHex2Array( pBuf, *pLen, pAC->AsfData.Mib.KeyOperator );
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_KEY_OP:\n >"));
+                for( i=0; i<RSP_KEYLENGTH; i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyOperator[i] ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_KEY_ADM:
+            if( *pLen == (RSP_KEYLENGTH*2) )  {
+                AsfHex2Array( pBuf, *pLen, pAC->AsfData.Mib.KeyAdministrator );
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_KEY_ADM:\n >"));
+                for( i=0; i<RSP_KEYLENGTH; i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyAdministrator[i] ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_KEY_GEN:
+            if( *pLen == (RSP_KEYLENGTH*2) )  {
+                AsfHex2Array( pBuf, *pLen, pAC->AsfData.Mib.KeyGenerator );
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_KEY_GEN:\n >"));
+                for( i=0; i<RSP_KEYLENGTH; i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyGenerator[i] ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_PAR_1:
+            if( *pLen == 1 )  {
+                pAC->AsfData.Mib.Reserved[Id-OID_SKGE_ASF_PAR_1] = *pBuf;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_PAR_X: ---\n" ));
+            }
+            else
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            break;
+
+        case OID_SKGE_ASF_IP_SOURCE:
+            *pLen = 0;
+            break;
+
+        case OID_SKGE_ASF_FWVER_OID:
+            // fall through
+        case OID_SKGE_ASF_ACPI_OID:
+            // fall through
+        case OID_SKGE_ASF_SMBUS_OID:
+            // these OIDs are read only - they cannot be set
+            *pLen = 0;
+            break;
+
+        default:
+            *pLen = 0;
+            RetCode = SK_ASF_PNMI_ERR_NOT_SUPPORTED;
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID not supported \n" ));
+            break;
+    }
+
+    if( RetCode != SK_ASF_PNMI_ERR_OK )  { //  No bytes used
+        if( RetCode == SK_PNMI_ERR_TOO_SHORT )  {
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error Length: %d \n", *pLen ));
+        }
+        else  {
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Error ???\n", *pLen ));
+        }
+        *pLen = 0;
+    }
+    else
+        pAC->AsfData.Mib.NewParam = 2;  //  Trigger SEPROM Update
+
+
+    return(RetCode);
+}
+
+
+/******************************************************************************
+*
+*   SkAsfGetOid -
+*
+* Context:
+*   init, pageable
+*
+* Returns:
+*/
+int SkAsfGetOid(
+            SK_AC *pAC, /* the adapter context */
+            SK_IOC IoC, /* I/O context */
+            SK_U32 Id,  /* OID  */
+            SK_U32 Inst,
+            SK_U8 *pBuf,
+            unsigned int *pLen)
+{
+    SK_U32  TmpVal32;
+    SK_U32  RetCode = SK_ASF_PNMI_ERR_OK;
+    SK_U8   i;
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfGetOid -> OID:0x%x Len:%d\n", Id, *pLen ));
+
+    if( pAC->AsfData.InitState != ASF_INIT_OK )  {
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfSetOid -> Get OID denied, ASF not initialized !\n", Id, *pLen ));
+        if( Id != OID_SKGE_ASF_CAP )
+            return( SK_ASF_PNMI_ERR_GENERAL );
+    }
+
+    switch( Id )  {
+        case OID_SKGE_ASF_CAP:
+            if( *pLen >= 4 )  {
+                TmpVal32 = 0;
+                if( (pAC->AsfData.InitState != ASF_INIT_UNDEFINED) &&
+                    (pAC->AsfData.InitState != ASF_INIT_ERROR_CHIP_ID) )
+                    TmpVal32 |= BIT_0;  //  ASF capable
+                if( pAC->AsfData.InitState == ASF_INIT_OK )
+                    TmpVal32 |= BIT_1;  //  ASF Init OK
+                if( pAC->AsfData.Mib.Ena )
+                    TmpVal32 |= BIT_2;  //  ASF enable
+                *( (SK_U32 *) pBuf ) = TmpVal32;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_ENA: %d\n",  pAC->AsfData.Mib.Ena ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_ENA:
+            if( *pLen >= 1 )  {
+                *( (SK_U8 *) pBuf ) = pAC->AsfData.Mib.Ena;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_ENA: %d\n",  pAC->AsfData.Mib.Ena ));
+            }
+            else  {
+                *pLen = 1;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_RETRANS:
+            if( *pLen >= 2 )  {
+                *( (SK_U16 *) pBuf ) = pAC->AsfData.Mib.Retrans;
+                *pLen = 2;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS: %d\n",  pAC->AsfData.Mib.Retrans ));
+            }
+            else  {
+                *pLen = 2;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_RETRANS_INT:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.RetransInt / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_INT: %d\n",  pAC->AsfData.Mib.RetransInt ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_HB_ENA:
+            if( *pLen >= 1 )  {
+                *( (SK_U8 *) pBuf ) = pAC->AsfData.Mib.HbEna;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_HB_ENA: %d\n",  pAC->AsfData.Mib.HbEna ));
+            }
+            else  {
+                *pLen = 1;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_HB_INT:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.HbInt / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_HB_INT: %d\n",  pAC->AsfData.Mib.HbInt ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_WD_ENA:
+            if( *pLen >= 1 )  {
+                *( (SK_U8 *) pBuf ) = pAC->AsfData.Mib.WdEna;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_WD_ENA: %d\n",  pAC->AsfData.Mib.WdEna ));
+            }
+            else  {
+                *pLen = 1;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_WD_TIME:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.WdTime / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_WD_TIME: %d\n",  pAC->AsfData.Mib.WdTime ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_IP_SOURCE:
+            if( *pLen >= 16 )  {
+                AsfIp2Asci( pBuf+1, pLen, pAC->AsfData.Mib.IpSource );
+                *pBuf = (SK_U8) *pLen;
+                (*pLen)++;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_IP_SOURCE: %d.%d.%d.%d\n",
+                                        pAC->AsfData.Mib.IpSource[0], pAC->AsfData.Mib.IpSource[1],
+                                        pAC->AsfData.Mib.IpSource[2], pAC->AsfData.Mib.IpSource[3] ));
+            }
+            else  {
+                *pLen = 16;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_IP_DEST:
+            if( *pLen >= 16 )  {
+                AsfIp2Asci( pBuf+1, pLen, pAC->AsfData.Mib.IpDest );
+                *pBuf = (SK_U8) *pLen;
+                (*pLen)++;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_IP_DEST: %d.%d.%d.%d\n",
+                                        pAC->AsfData.Mib.IpDest[0], pAC->AsfData.Mib.IpDest[1],
+                                        pAC->AsfData.Mib.IpDest[2], pAC->AsfData.Mib.IpDest[3] ));
+            }
+            else  {
+                *pLen = 16;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_MAC_DEST:
+            if( *pLen >= 18 )  {
+                AsfMac2Asci( pBuf+1, pLen, pAC->AsfData.Mib.MacDest );
+                *pBuf = (SK_U8) *pLen;
+                (*pLen)++;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_MAC_DEST: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                        pAC->AsfData.Mib.MacDest[0], pAC->AsfData.Mib.MacDest[1],
+                                        pAC->AsfData.Mib.MacDest[2], pAC->AsfData.Mib.MacDest[3],
+                                        pAC->AsfData.Mib.MacDest[4], pAC->AsfData.Mib.MacDest[5] ));
+            }
+            else  {
+                *pLen = 18;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_MAC_SOURCE:
+            if( *pLen >= 18 )  {
+                AsfMac2Asci( pBuf+1, pLen, pAC->AsfData.Mib.MacSource );
+                *pBuf = (SK_U8) *pLen;
+                (*pLen)++;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_MAC_SOURCE: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                        pAC->AsfData.Mib.MacSource[0], pAC->AsfData.Mib.MacSource[1],
+                                        pAC->AsfData.Mib.MacSource[2], pAC->AsfData.Mib.MacSource[3],
+                                        pAC->AsfData.Mib.MacSource[4], pAC->AsfData.Mib.MacSource[5] ));
+            }
+            else  {
+                *pLen = 18;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_COMMUNITY_NAME:
+            if( *pLen >= 64 )  {
+                for( *pLen=0; *pLen<63; (*pLen)++  )  {
+                    *(pBuf + *pLen + 1 ) = pAC->AsfData.Mib.CommunityName[*pLen];
+
+                    if( pAC->AsfData.Mib.CommunityName[*pLen] != 0 )  {
+                        *(pBuf + *pLen + 1 ) = pAC->AsfData.Mib.CommunityName[*pLen];
+                    }
+                    else  {
+                        break;
+                    }
+                }
+                *pBuf = (SK_U8) *pLen;
+                (*pLen)++;
+            }
+            else  {
+                *pLen = 64;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_RSP_ENA:
+            if( *pLen >= 1 )  {
+                *( (SK_U8 *) pBuf ) = pAC->AsfData.Mib.RspEnable;
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RSP_ENA: %d\n",  pAC->AsfData.Mib.RspEnable ));
+            }
+            else  {
+                *pLen = 1;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_RETRANS_COUNT_MIN:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.RetransCountMin;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_COUNT_MIN: %d\n",  pAC->AsfData.Mib.RetransCountMin ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_RETRANS_COUNT_MAX:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.RetransCountMax;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_COUNT_MAX: %d\n",  pAC->AsfData.Mib.RetransCountMax ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_RETRANS_INT_MIN:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.RetransIntMin / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_INT_MIN: %d\n",  pAC->AsfData.Mib.RetransIntMin ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_RETRANS_INT_MAX:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.RetransIntMax / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_RETRANS_INT_MAX: %d\n",  pAC->AsfData.Mib.RetransIntMax ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_HB_INT_MIN:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.HbIntMin / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_HB_INT_MIN: %d\n",  pAC->AsfData.Mib.HbIntMin ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_HB_INT_MAX:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.HbIntMax / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_HB_INT_MAX: %d\n",  pAC->AsfData.Mib.HbIntMax ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_WD_TIME_MIN:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.WdTimeMin / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_WD_TIME_MIN: %d\n",  pAC->AsfData.Mib.WdTimeMin ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_WD_TIME_MAX:
+            if( *pLen >= 4 )  {
+                *( (SK_U32 *) pBuf ) = pAC->AsfData.Mib.WdTimeMax / ASF_GUI_TSF;
+                *pLen = 4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_WD_TIME_MAX: %d\n",  pAC->AsfData.Mib.WdTimeMax ));
+            }
+            else  {
+                *pLen = 4;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_GUID:
+            if( *pLen >= 33 )  {
+                AsfArray2Hex( pBuf+1, 16, pAC->AsfData.Mib.Guid );
+                *pBuf = 32;
+                *pLen = 33;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_GUID\n" ));
+            }
+            else  {
+                *pLen = 33;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_KEY_OP:
+            if( *pLen >= 41 )  {
+                AsfArray2Hex( pBuf+1, 40, pAC->AsfData.Mib.KeyOperator );
+                *pBuf = (SK_U8) 40;
+                *pLen = 41;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_KEY_OP:\n >"));
+                for( i=0; i<RSP_KEYLENGTH; i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyOperator[i] ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+            }
+            else  {
+                *pLen = 41;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_KEY_ADM:
+            if( *pLen >= 41 )  {
+                AsfArray2Hex( pBuf+1, 40, pAC->AsfData.Mib.KeyAdministrator );
+                *pBuf = (SK_U8) 40;
+                *pLen = 41;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_KEY_ADM:\n >"));
+                for( i=0; i<RSP_KEYLENGTH; i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyAdministrator[i] ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+            }
+            else  {
+                *pLen = 41;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_KEY_GEN:
+            if( *pLen >= 41 )  {
+                AsfArray2Hex( pBuf+1, 40, pAC->AsfData.Mib.KeyGenerator );
+                *pBuf = (SK_U8) 40;
+                *pLen = 41;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_KEY_GEN:\n >"));
+                for( i=0; i<RSP_KEYLENGTH; i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyGenerator[i] ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+            }
+            else  {
+                *pLen = 41;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_PAR_1:
+            if( *pLen >= 1 )  {
+                *( (SK_U8 *) pBuf ) = pAC->AsfData.Mib.Reserved[Id-OID_SKGE_ASF_PAR_1];
+                *pLen = 1;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_PAR_X: --\n"));
+            }
+            else  {
+                *pLen = 1;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_FWVER_OID:
+            // returns the firmware revision to GUI
+            if (*pLen >= ASF_FWVER_MAXBUFFLENGTH) {
+                for (i=0; i < ASF_FWVER_MAXBUFFLENGTH; i++ ) {
+                    // maybe we should lock the access to FwVersionString against reading/writing at the same time?
+                    *((SK_U8 *)pBuf+i) = pAC->AsfData.FwVersionString[i];
+                }
+                *pLen = ASF_FWVER_MAXBUFFLENGTH;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_FWVER_OID: %d\n", *pLen));
+            }
+            else {
+                // set the right length
+                *pLen   = ASF_FWVER_MAXBUFFLENGTH;
+                RetCode = SK_PNMI_ERR_TOO_SHORT;
+            }
+            break;
+
+        case OID_SKGE_ASF_ACPI_OID:
+            // returns ACPI/ASF table (ASF_ACPI_MAXBUFFLENGTH bytes) to GUI
+            if ( (pAC->AsfData.Mib.Acpi.length > 0) && (pAC->AsfData.Mib.Acpi.length <= ASF_ACPI_MAXBUFFLENGTH) ) {
+                if (*pLen >= pAC->AsfData.Mib.Acpi.length) {
+                    // there is enough space in buffer for reporting ACPI buffer
+                    for (i=0; i < pAC->AsfData.Mib.Acpi.length; i++) {
+                        // maybe we should lock the access to Acpi.buffer against reading/writing at the same time?
+                        *((SK_U8 *)pBuf+i) = pAC->AsfData.Mib.Acpi.buffer[i];
+                    }
+                    *pLen = pAC->AsfData.Mib.Acpi.length;
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_ACPI_OID: %d\n", *pLen));
+                }
+                else {
+                    // there is not enough space in buffer to report ACPI buffer
+                    *pLen   = ASF_ACPI_MAXBUFFLENGTH;
+                    RetCode = SK_PNMI_ERR_TOO_SHORT;
+                }
+            }
+            else {
+                // no buffer to report
+                *pLen = 0;
+            }
+            break;
+
+        case OID_SKGE_ASF_SMBUS_OID:
+            // set a request flag, that smbus info must be updated
+            pAC->AsfData.Mib.SMBus.UpdateReq = 1;
+            // returns SMBus table GUI
+            if ( (pAC->AsfData.Mib.SMBus.length > 0) && (pAC->AsfData.Mib.SMBus.length <= ASF_SMBUS_MAXBUFFLENGTH) ) {
+                if (*pLen >= pAC->AsfData.Mib.SMBus.length) {
+                    // there is enough space in buffer for reporting ACPI buffer
+                    for (i=0; i < pAC->AsfData.Mib.SMBus.length; i++) {
+                        // maybe we should lock the access to SMBus.buffer against reading/writing at the same time?
+                        *((SK_U8 *)pBuf+i) = pAC->AsfData.Mib.SMBus.buffer[i];
+                    }
+                    *pLen = pAC->AsfData.Mib.SMBus.length;
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID_SKGE_ASF_SMBUS_OID: %d\n", *pLen));
+                }
+                else {
+                    // there is not enough space in buffer to report SMBus buffer
+                    *pLen   = ASF_SMBUS_MAXBUFFLENGTH;
+                    RetCode = SK_PNMI_ERR_TOO_SHORT;
+                }
+            }
+            else {
+                // no buffer to report
+                *pLen = 0;
+            }
+            break;
+
+        case OID_SKGE_ASF_HB_CAP:
+            // oid not used
+            *pLen = 0;
+            break;
+
+        default:
+            *pLen   = 0;
+            RetCode = SK_ASF_PNMI_ERR_NOT_SUPPORTED;
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    OID not supported\n",  pAC->AsfData.Mib.Ena ));
+            break;
+    }
+
+    return(RetCode);
+}
+
+
+/******************************************************************************
+*
+*   SkAsfGet -
+*
+* Context:
+*   init, pageable
+*
+* Returns:
+*/
+int SkAsfGet(
+            SK_AC *pAC,    /* the adapter context */
+            SK_IOC IoC, /* I/O context */
+            SK_U8 *pBuf,
+            unsigned int *pLen)
+{
+    SK_U32  RetCode = SK_ASF_PNMI_ERR_OK;
+
+    return(RetCode) ;
+}
+
+
+/******************************************************************************
+*
+*   SkAsfPreSet -
+*
+* Context:
+*   init, pageable
+*
+* Returns:
+*/
+int SkAsfPreSet(
+               SK_AC *pAC, /* the adapter context */
+               SK_IOC IoC, /* I/O context */
+               SK_U8 *pBuf,
+               unsigned int *pLen)
+{
+    /* preset the Return code to error */
+    SK_U32  RetCode = SK_ASF_PNMI_ERR_OK;
+
+    return(RetCode);
+}
+
+/******************************************************************************
+*
+*   SkAsfSet -
+*
+* Context:
+*   init, pageable
+*
+* Returns:
+*/
+int SkAsfSet(
+            SK_AC *pAC, /* the adapter context */
+            SK_IOC IoC, /* I/O context */
+            SK_U8 *pBuf,
+            unsigned int *pLen)
+{
+    SK_U32  RetCode = SK_ASF_PNMI_ERR_OK;
+
+    return(RetCode);
+}
+
+SK_I8 SkAsfStartWriteDeferredFlash( SK_AC *pAC, SK_IOC IoC )  {
+    SK_I8	RetCode;
+    SK_EVPARA	EventParam;
+
+    RetCode = 1;
+    if( pAC->AsfData.StateWrSpi == 0 )  {
+        pAC->AsfData.StateWrSpi++;
+        SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+        SkTimerStart(pAC, IoC, &pAC->AsfData.AsfTimerWrSpi,
+                     10000, SKGE_ASF, SK_ASF_EVT_TIMER_SPI_EXPIRED,
+                     EventParam);
+        RetCode = 0;
+    }
+
+    return( RetCode );
+}
+
+SK_I8 SkAsfWriteDeferredFlash( SK_AC *pAC, SK_IOC IoC )  {
+    SK_I8       RetCode;
+    SK_U8       StartAgain;
+
+    RetCode = 1;  //  unsuccessfull
+    StartAgain = 0;
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("          WriteDeferredFlash:  State:%d\n", pAC->AsfData.StateWrSpi ));
+
+#ifdef _XXX_
+
+    switch( pAC->AsfData.StateWrSpi )  {
+        case 0:  //  idle State
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("          WriteDeferredFlash:  idle\n"));
+            break;
+
+        case 1: //  erase SPI flash sector
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("          WriteDeferredFlash:  Erase flash\n"));
+            if (spi_flash_erase(pAC, ASF_SPI_SECTOR, ASF_SPI_SECTOR_SIZE)  == 0 )  {  //  successfull
+                RetCode = 0;
+                StartAgain = 1;
+                pAC->AsfData.StateWrSpi++;
+            }
+            else
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("          WriteDeferredFlash:  Error Erase flash\n"));
+            break;
+
+        default:
+            //  128 * 0x100 (256)  Bytes
+            if( pAC->AsfData.StateWrSpi <= 129 )  {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("          WriteDeferredFlash:  Write addr:0x%x size:0x%x\n",
+                                                                    ASF_SPI_SECTOR+((pAC->AsfData.StateWrSpi-2)*0x100), 0x100 ));
+                if (spi_flash_manage(pAC,
+                                     &pAC->AsfData.SpiBuf[(pAC->AsfData.StateWrSpi-2)*0x100],
+                                     ASF_SPI_SECTOR+((pAC->AsfData.StateWrSpi-2)*0x100),
+                                     0x100, SPI_WRITE)  == 0 ) {
+                    RetCode = 0;
+                    StartAgain = 1;
+                    pAC->AsfData.StateWrSpi++;
+                }
+                else
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("          WriteDeferredFlash:  Error Write addr:0x%x size:0x%x\n",
+                                                                   ASF_SPI_SECTOR+((pAC->AsfData.StateWrSpi-2)*0x100), 0x100 ));
+            }
+            else  {
+                //  Finish
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("          WriteDeferredFlash:  Finish\n"));
+                RetCode = 1;
+            }
+            break;
+
+    }  //   switch( pAC->AsfData.StateWrSpi )
+
+    if( StartAgain )  {
+        SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+        SkTimerStart(pAC, IoC, &pAC->AsfData.AsfTimerWrSpi,
+                     10000, SKGE_ASF, SK_ASF_EVT_TIMER_SPI_EXPIRED,
+                     EventParam);
+    }
+    else  {
+        pAC->AsfData.StateWrSpi = 0;
+        pAC->AsfData.Mib.WriteToFlash = 0;
+    }
+
+#endif //  _XXX_
+
+    return( RetCode );
+}
+
+
+/*****************************************************************************
+*
+* SkAsfEvent - Event handler
+*
+* Description:
+*   Handles the following events:
+*   SK_ASF_EVT_TIMER_EXPIRED When a hardware counter overflows an
+*
+* Returns:
+*   Always 0
+*/
+int SkAsfEvent(
+              SK_AC *pAC, /* Pointer to adapter context */
+              SK_IOC IoC, /* IO context handle */
+              SK_U32 Event,  /* Event-Id */
+              SK_EVPARA Param) /* Event dependent parameter */
+{
+
+    switch(Event)
+    {
+        case SK_ASF_EVT_TIMER_EXPIRED:
+            // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("ASF: SkAsfEvent -> Timer expired\n" ));
+            SkAsfTimer( pAC, IoC );
+            break;
+
+        case SK_ASF_EVT_TIMER_SPI_EXPIRED:
+            // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("ASF: SkAsfEvent -> TimerWrSpi expired State:%d\n",
+            //                                                pAC->AsfData.StateWrSpi ));
+            SkAsfWriteDeferredFlash( pAC, IoC );
+            break;
+
+        case SK_ASF_EVT_TIMER_HCI_EXPIRED:
+            //  SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("ASF: SkAsfEvent -> TimerWrHci expired GlHciState:%d\n",
+            //                                                pAC->AsfData.GlHciState ));
+            SkAsfHci( pAC, IoC, 1 );
+            break;
+
+        default:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("ASF: SkAsfEvent -> Unknown Event:0x%x\n", Event ));
+            break;
+    }
+    return(0); /* Success. */
+} /* SkAsfEvent */
+
+/*****************************************************************************
+*
+* SkAsfTimer - general ASF  timer
+*
+* Description:
+*
+* Returns:
+*   Always 0
+*/
+void SkAsfTimer(
+SK_AC *pAC, /* Pointer to adapter context */
+SK_IOC IoC ) /* IO context handle */  {
+
+    SK_EVPARA   EventParam;
+    SK_U8       i, NewAddr;
+    SK_U8       lRetCode;
+    SK_U8       TmpBuffer[128];
+    SK_U8       Ind;
+    SK_U8       Length;
+    SK_U8       *pHciRecBuf;
+
+    AsfWatchCpu(pAC, IoC, 50 );
+
+    pHciRecBuf = NULL;
+
+    // check, whether IP address has changed
+    NewAddr = 0;
+    for( i=0; i<4; i++ )  {
+        if( pAC->IpAddr[i] != pAC->AsfData.Mib.IpSource[i] )  {
+            NewAddr = 1;
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: New IP Addr detected\n"));
+        }
+    }
+
+    if( pAC->AsfData.Mib.NewParam > 1 ) {
+        pAC->AsfData.Mib.NewParam--;
+    }
+
+    switch(  pAC->AsfData.GlHciState  )  {
+        /*------------------------------------------------------------------------------------------------------
+         *  check for changes in config data
+         *----------------------------------------------------------------------------------------------------*/
+        case 0:
+	  
+	  switch(pAC->AsfData.OpMode)  {
+	  case SK_GEASF_MODE_ASF:
+	    if(pAC->AsfData.LastGlHciState == 255) {
+	      pAC->AsfData.LastGlHciState = 0;
+	      pAC->AsfData.GlHciState     = 100;  //  Fetch ASF configuration from FW
+	      pAC->AsfData.Mib.PattUpReq  = 1;    // ...and update pattern ram
+	    }
+	    else {
+	      if ( (pAC->AsfData.Mib.SMBus.UpdateReq >= 1) && (pAC->AsfData.GlHciState == 0) ) {
+		// lock this mechanism, if the GlHciState goes really to the "SMBus update state"
+		// pAC->AsfData.Mib.SMBus.UpdateReq = 0;
+		
+		// go to SMBus update state
+		pAC->AsfData.GlHciState = 20;
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("Go to State 20\n"));
+	      }
+	      
+	      if ( (pAC->AsfData.Mib.NewParam == 1) || (NewAddr && pAC->AsfData.Mib.Ena))  {
+		pAC->AsfData.GlHciState = 50;
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: Start Update ASF config data\n"));
+	                    }
+	      
+	      if ( pAC->AsfData.VpdInitOk == 0 )  {
+		pAC->AsfData.GlHciState = 1;
+		SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: Start Init Vpd \n"));
+	      }
+	    }
+#ifdef ASF_FW_WD
+	    //  FW WD functionality
+	    if( pAC->AsfData.FwWdIntervall > 1 )
+	      pAC->AsfData.FwWdIntervall--;
+	    if( pAC->AsfData.FwWdIntervall == 1 )  {
+	                        pAC->AsfData.GlHciState = 1;  //  go to check alive
+	    }
+#endif
+	    break;
+	    
+	  case SK_GEASF_MODE_IPMI:
+
+	    if ( (NewAddr == 1) ||
+		 (pAC->AsfData.ActivePort   != (SK_U8)(pAC->ActivePort & 0xff)) ||
+		 (pAC->AsfData.PrefPort     != (SK_U8)(pAC->Rlmt.Net[0].PrefPort & 0xff)) ||
+		 (pAC->AsfData.Mib.RlmtMode != (SK_U8)(pAC->Rlmt.NumNets & 0xff)) ) {
+	      
+	      // config has changed for IPMI
+	      pAC->AsfData.GlHciState = 30;
+	      SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+			 ("SkAsfTimer: IPMI update config with %d 0x%08x 0x%08x\n",
+			  NewAddr, pAC->ActivePort, pAC->Rlmt.Net[0].PrefPort, pAC->Rlmt.NumNets));
+	    }
+	    
+	    // check the ipmi firmware
+	    if( pAC->AsfData.FwWdIntervall > 1 ) {
+	      pAC->AsfData.FwWdIntervall--;
+	    }
+	    else {
+	      pAC->AsfData.GlHciState = 1;  //  go to check alive
+	    }
+	    
+	    break;
+	    
+	  case SK_GEASF_MODE_DASH:
+	    if ( NewAddr == 1 ){
+	      // config has changed for DASH
+
+	      pAC->AsfData.GlHciState = 40;
+	      SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+			 ("SkAsfTimer: DASH update config with NewAddr: %d\n",NewAddr ));
+	    }
+	    
+	    // check the DASH firmware
+	    if( pAC->AsfData.FwWdIntervall > 1 ) {
+	      pAC->AsfData.FwWdIntervall--;
+	    }
+	    else {
+	      pAC->AsfData.GlHciState = 1;  //  go to check alive
+	    }
+	    
+	    //if( AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_DRV_HELLO, 0, 0, 0, ASF_HCI_WAIT, 3 ) != HCI_EN_CMD_READY )  {
+	    //  printk("ASF: DRV_HELLO failed\n");
+	    //} else {
+	    //  printk("ASF: DRV_HELLO OK\n");
+	    //}
+	    
+	    break;
+	    
+	  default:
+	    printk("Unknow Mode\n");
+
+	    break;
+	  }
+	  
+	  break;
+	  
+            /*------------------------------------------------------------------------------------------------------
+             *  Do VPD init
+             *  Due to the SPI/VPD problem (A1), VpdInit MUST NOT be invoked while the ASF FW is running from flash.
+             *  Therefore we do it here, while the ASF FW is running in the RamIdleLoop
+             *----------------------------------------------------------------------------------------------------*/
+        case 1:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CHECK_ALIVE, 0, 0, 0, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                pAC->AsfData.GlHciState++;
+                // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+                //    ("SkAsfTimer: *** CPU is running (%d) ***\n", pAC->AsfData.OpMode));
+                // CheckAlive was initiated by WD
+                if( pAC->AsfData.FwWdIntervall == 1 )  {
+                    pAC->AsfData.GlHciState = 0;
+                    pAC->AsfData.FwWdIntervall = 10;
+                }
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR )  {
+                pAC->AsfData.GlHciState = 255;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: *** CPU is NOT running !!! ***\n"));
+                AsfResetCpu( pAC, IoC );
+                AsfRunCpu( pAC, IoC );
+                // CheckAlive was initiated by WD
+                if( pAC->AsfData.FwWdIntervall == 1 )  {
+                    pAC->AsfData.GlHciState = 0;
+                    pAC->AsfData.FwWdIntervall = 60;
+                }
+            }
+            break;
+
+        case 2:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_ENTER_RAM_IDLE, 0, 0, 0, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                pAC->AsfData.GlHciState++;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sent ENTER_RAM_IDLE \n"));
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 3:
+            if( pAC->AsfData.VpdInitOk == 0 )  {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: VpdInit\n"));
+                if (VpdInit(pAC, IoC) == 0) {
+                    pAC->AsfData.VpdInitOk = 1;
+                    pAC->AsfData.GlHciState++;
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfTimer: VPD init o.k.\n"));
+                }
+                else
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfTimer: VPD init error\n"));
+            }
+            else
+                pAC->AsfData.GlHciState++;
+            break;
+        case 4:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_LEAVE_RAM_IDLE, 0, 0, 0, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                pAC->AsfData.GlHciState++;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sent LEAVE_RAM_IDLE \n"));
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        case 5:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_UPDATE_OWN_MACADDR, 0, 0, 0, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                if(pAC->AsfData.NewGuid)
+                    pAC->AsfData.GlHciState = 50;   // Write default parameters to SEEPROM
+                else {
+                    pAC->AsfData.GlHciState     = 100;  //  Fetch ASF configuration from FW
+                    pAC->AsfData.Mib.PattUpReq  = 1;    // ...and update pattern ram
+                }
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sent LEAVE_RAM_IDLE \n"));
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+
+        /*------------------------------------------------------------------------------------------------------
+         *  updates SMBus structure via HCI
+         *----------------------------------------------------------------------------------------------------*/
+        case 20:
+            // If there is a request for updating, we work it out and go to idle state.
+            pAC->AsfData.Mib.SMBus.UpdateReq = 0;
+
+            // get SMBus infos from FW
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_SMBUS_INFOS, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: SMBus info update via HCI l:%d\n", Length))
+
+                pAC->AsfData.Mib.SMBus.length = 0;
+                for( i=0; (i<ASF_SMBUS_MAXBUFFLENGTH)&&(i<Length); i++ )  {
+                    pAC->AsfData.Mib.SMBus.length   += 1;
+                    pAC->AsfData.Mib.SMBus.buffer[i] = *(pHciRecBuf+2+i);
+                }
+                pAC->AsfData.GlHciState = 0; // go to idle
+            }
+            if (lRetCode == HCI_EN_CMD_ERROR) {
+                pAC->AsfData.GlHciState = 255;
+            }
+            break;
+
+
+        /*------------------------------------------------------------------------------------------------------
+         *  IPMI states 30...36
+         *----------------------------------------------------------------------------------------------------*/
+
+        case 30:
+            // RLMT mode has changed (only relevant in IPMI operation mode)
+            // in IPMI operation mode, we use the  YASF_HOSTCMD_CFG_SET_RSP_ENABLE message
+            // as indicator for RLMT mode / Dual Net mode
+            // pAC->AsfData.Mib.RlmtMode > 1  => Dual Net Mode On
+            // else                           => RLMT Mode On
+	    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+                ("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_RSP_ENABLE 0x%x -> 0x%x\n", pAC->AsfData.Mib.RlmtMode, pAC->Rlmt.NumNets));
+
+            pAC->AsfData.Mib.RlmtMode = (SK_U8)(pAC->Rlmt.NumNets & 0xff);
+
+            if (pAC->AsfData.Mib.RlmtMode > 1) {
+                // switch to Dual net mode
+                if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+                    // enable pattern for port b
+                    YlciEnablePattern(pAC, IoC, 1, 4);      // RSP pattern
+                    YlciEnablePattern(pAC, IoC, 1, 6);      // RMCP pattern
+                }
+
+                // enable pattern for port a
+                YlciEnablePattern(pAC, IoC, 0, 4);          // RSP pattern
+                YlciEnablePattern(pAC, IoC, 0, 6);          // RMCP pattern
+            }
+
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_RSP_ENABLE;
+            TmpBuffer[Ind++] = 1 + 2;  // Length
+            TmpBuffer[Ind++] = pAC->AsfData.Mib.RlmtMode;
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+
+        case 31:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 32:
+	   SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_ACTIVE_PORT act 0x%x -> 0x%x pref 0x%x -> 0x%x\n", pAC->AsfData.ActivePort, pAC->ActivePort, pAC->AsfData.PrefPort, pAC->Rlmt.Net[0].PrefPort));
+
+            pAC->AsfData.ActivePort = (SK_U8)(pAC->ActivePort & 0xff);
+            pAC->AsfData.PrefPort   = (SK_U8)(pAC->Rlmt.Net[0].PrefPort & 0xff);
+
+            // write always pattern enable for the active port
+            if (pAC->AsfData.Mib.RlmtMode <= 1) {
+                // we are in rlmt mode
+                if (pAC->AsfData.ActivePort == 1) {
+                    if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+                        // enable pattern for port b
+                        YlciEnablePattern(pAC, IoC, 1, 4);      // RSP pattern
+                        YlciEnablePattern(pAC, IoC, 1, 6);      // RMCP pattern
+                    }
+
+                    // disable pattern for port a
+                    YlciDisablePattern(pAC, IoC, 0, 4);         // RSP pattern
+                    YlciDisablePattern(pAC, IoC, 0, 6);         // RMCP pattern
+                }
+                else {
+                    // enable pattern for port a
+                    YlciEnablePattern(pAC, IoC, 0, 4);          // RSP pattern
+                    YlciEnablePattern(pAC, IoC, 0, 6);          // RMCP pattern
+
+                    if (pAC->AsfData.DualMode == SK_GEASF_Y2_DUALPORT) {
+                        // disable pattern for port b
+                        YlciDisablePattern(pAC, IoC, 1, 4);     // RSP pattern
+                        YlciDisablePattern(pAC, IoC, 1, 6);     // RMCP pattern
+                    }
+                }
+            }
+
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_ACTIVE_PORT;
+            TmpBuffer[Ind++] = 1 + 3;  // Length
+            TmpBuffer[Ind++] = pAC->AsfData.ActivePort;
+
+            // preferred port
+            if (pAC->AsfData.PrefPort == 2) {
+                // note: 0 = "auto", 1 = port A, 2 = port B,
+                TmpBuffer[Ind++] = 1;   // port B
+            }
+            else {
+                TmpBuffer[Ind++] = 0;   // port A
+            }
+
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+
+        case 33:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE) ) {
+                pAC->AsfData.GlHciState++;          // next state
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR ) {
+                pAC->AsfData.GlHciState = 255;      // error state
+            }
+            break;
+
+        case 34:
+            // Comment: Error? Empty IpAddr! -> No SW-Assignment for the BMC-IP
+            // printk("Omitting Command 34 <- not implemented\n");
+            pAC->AsfData.GlHciState++;
+            break;
+
+        case 35:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))  {
+                pAC->AsfData.GlHciState++;          // finisch
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR ) {
+                pAC->AsfData.GlHciState = 255;      // error
+            }
+            break;
+
+        case 36:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_FW_VERSION_STRING, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_FW_VERSION_STRING l:%d\n",Length))
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("         >"))
+                for( i=0; (i<79)&&(i<Length); i++ )  {
+                    pAC->AsfData.FwVersionString[i]   = *(pHciRecBuf+2+i);
+                    pAC->AsfData.FwVersionString[i+1] = 0;
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%c",pAC->AsfData.FwVersionString[i]))
+                }
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"))
+                pAC->AsfData.GlHciState = 254;      // go to finish
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR ) {
+                pAC->AsfData.GlHciState = 255;      // error state
+            }
+            break;
+
+    // DASH ASF FW CMDS (40-48)
+    case 40:
+      pAC->AsfData.GlHciState++;
+      break;
+      
+    case 41:
+      pAC->AsfData.GlHciState++;
+      break;
+      
+    case 42:
+      SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+		 ("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_DASH_ENABLE \n"));
+      Ind = 0;
+      TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_DASH_ENABLE;
+      TmpBuffer[Ind++] = 1 + 2;  // Length
+      TmpBuffer[Ind++] = pAC->AsfData.Mib.RlmtMode;
+      lRetCode = AsfHciSendData(pAC ,IoC , TmpBuffer, 0, ASF_HCI_WAIT, 2 );
+      pAC->AsfData.GlHciState++;
+      break;
+      
+    case 43:
+      lRetCode = AsfHciGetState( pAC );
+      if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE)) {
+	pAC->AsfData.GlHciState++;
+      }
+
+      if( lRetCode == HCI_EN_CMD_ERROR ) {
+	pAC->AsfData.GlHciState = 255;
+      }
+      
+      break;
+	    
+    case 44:
+      //SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+      //	 ("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_ACTIVE_PORT act 0x%x -> 0x%x pref 0x%x -> 0x%x\n",
+      //	  pAC->AsfData.ActivePort, pAC->ActivePort, pAC->AsfData.PrefPort, pAC->GeneralConfig.PrefPort));
+      SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+		 ("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_ACTIVE_PORT act 0x%x -> 0x%x\n",
+		  pAC->AsfData.ActivePort, pAC->ActivePort));
+
+      
+      pAC->AsfData.ActivePort = (SK_U8)(pAC->ActivePort & 0xff);
+      // pAC->AsfData.PrefPort   = (SK_U8)(pAC->PrefPort & 0xff);
+      
+      Ind = 0;
+      TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_ACTIVE_PORT;
+      TmpBuffer[Ind++] = 1 + 3;  // Length
+      TmpBuffer[Ind++] = pAC->AsfData.ActivePort;
+      // preferred port
+      if (pAC->AsfData.PrefPort == 2) {
+	// note: 0 = "auto", 1 = port A, 2 = port B,
+	TmpBuffer[Ind++] = 1;   // port B
+      }
+      else {
+	TmpBuffer[Ind++] = 0;   // port A
+      }
+      
+      lRetCode = AsfHciSendData(pAC ,IoC , TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+      pAC->AsfData.GlHciState++;
+      break;
+      
+    case 45:
+      lRetCode = AsfHciGetState( pAC );
+
+      if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE) ) {
+	pAC->AsfData.GlHciState++;          // next state
+      }
+      if( lRetCode == HCI_EN_CMD_ERROR ) {
+	pAC->AsfData.GlHciState = 255;      // error state
+      }
+      break;
+      
+    case 46:
+      SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+		 ("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_IP_SOURCE %03d.%03d.%03d.%03d -> %03d.%03d.%03d.%03d\n",
+		  pAC->AsfData.Mib.IpSource[0], pAC->AsfData.Mib.IpSource[1], pAC->AsfData.Mib.IpSource[2], pAC->AsfData.Mib.IpSource[3],
+		  pAC->IpAddr[0], pAC->IpAddr[1], pAC->IpAddr[2], pAC->IpAddr[3]));
+      Ind = 0;
+      TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_IP_SOURCE;
+      TmpBuffer[Ind++] = 4 + 2;  // Length
+
+      for( i=0; i<4; i++ ) {
+	TmpBuffer[Ind++] = pAC->IpAddr[i];
+      }
+
+      lRetCode = AsfHciSendData(pAC ,IoC , TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+      pAC->AsfData.GlHciState++;
+      break;
+      
+    case 47:
+      lRetCode = AsfHciGetState( pAC );
+      if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))  {
+	for( i=0; i<4; i++ ) {
+	  pAC->AsfData.Mib.IpSource[i] = pAC->IpAddr[i];
+	}
+	pAC->AsfData.GlHciState++;          // finish
+      }
+      if( lRetCode == HCI_EN_CMD_ERROR ) {
+	pAC->AsfData.GlHciState = 255;      // error
+      }
+      break;
+      
+    case 48:
+      lRetCode = AsfHciSendCommand(pAC ,IoC , YASF_HOSTCMD_CFG_GET_FW_VERSION_STRING, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+      if( lRetCode == HCI_EN_CMD_READY )  {
+	// Fetch received data from HCI interface
+	AsfHciGetData( pAC, &pHciRecBuf );
+	Length = *(pHciRecBuf + 1);
+	SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_FW_VERSION_STRING l:%d\n",Length));
+	for( i=0; (i<79)&&(i<Length); i++ )  {
+	  pAC->AsfData.FwVersionString[i]   = *(pHciRecBuf+2+i);
+	  pAC->AsfData.FwVersionString[i+1] = 0;
+	}
+	pAC->AsfData.GlHciState = 254;      // go to finish
+      }
+      if( lRetCode == HCI_EN_CMD_ERROR ) {
+	pAC->AsfData.GlHciState = 255;      // error state
+      }
+      break;
+        /*------------------------------------------------------------------------------------------------------
+         *  Send new ASF configuration data to FW (SEEPROM)
+         *----------------------------------------------------------------------------------------------------*/
+        /* YASF_HOSTCMD_CFG_SET_ASF_ENABLE */
+        case 50:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_ASF_ENABLE\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_ASF_ENABLE;
+            TmpBuffer[Ind++] = 1 + 2;  // Length
+            TmpBuffer[Ind++] = pAC->AsfData.Mib.Ena;
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 51:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_RSP_ENABLE */
+        case 52:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_RSP_ENABLE\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_RSP_ENABLE;
+            TmpBuffer[Ind++] = 1 + 2;  // Length
+            TmpBuffer[Ind++] = pAC->AsfData.Mib.RspEnable;
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 53:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_RETRANS */
+        case 54:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_RETRANS\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_RETRANS;
+            TmpBuffer[Ind++] = 1 + 2;  // Length
+            TmpBuffer[Ind++] = (SK_U8) pAC->AsfData.Mib.Retrans;
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 55:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_RETRANS_INT */
+        case 56:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_RETRANS_INT\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_RETRANS_INT;
+            TmpBuffer[Ind++] = 2 + 2;  // Length
+            TmpBuffer[Ind++] = (SK_U8)((pAC->AsfData.Mib.RetransInt >> 8) & 0x000000FF);
+            TmpBuffer[Ind++] = (SK_U8)((pAC->AsfData.Mib.RetransInt >> 0) & 0x000000FF);
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 57:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_HB_ENABLE */
+        case 58:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_HB_ENABLE\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_HB_ENABLE;
+            TmpBuffer[Ind++] = 1 + 2;  // Length
+            TmpBuffer[Ind++] = (SK_U8) pAC->AsfData.Mib.HbEna;
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 59:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_HB_INT */
+        case 60:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_HB_INT\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_HB_INT;
+            TmpBuffer[Ind++] = 2 + 2;  // Length
+            TmpBuffer[Ind++] = (SK_U8)((pAC->AsfData.Mib.HbInt >> 8) & 0x000000FF);
+            TmpBuffer[Ind++] = (SK_U8)((pAC->AsfData.Mib.HbInt >> 0) & 0x000000FF);
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 61:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_DRWD_ENABLE */
+        case 62:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_DRWD_ENABLE\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_DRWD_ENABLE;
+            TmpBuffer[Ind++] = 1 + 2;  // Length
+            TmpBuffer[Ind++] = (SK_U8) pAC->AsfData.Mib.WdEna;
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 63:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_DRWD_INT */
+        case 64:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_DRWD_INT\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_DRWD_INT;
+            TmpBuffer[Ind++] = 2 + 2;  // Length
+            TmpBuffer[Ind++] = (SK_U8)((pAC->AsfData.Mib.WdTime >> 8) & 0x000000FF);
+            TmpBuffer[Ind++] = (SK_U8)((pAC->AsfData.Mib.WdTime >> 0) & 0x000000FF);
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 65:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_IP_DESTINATION */
+        case 66:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_IP_DESTINATION\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_IP_DESTINATION;
+            TmpBuffer[Ind++] = 4 + 2;  // Length
+            for( i=0; i<4; i++ )
+                TmpBuffer[Ind++] = pAC->AsfData.Mib.IpDest[i];
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 67:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_IP_SOURCE */
+        case 68:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_IP_SOURCE\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_IP_SOURCE;
+            TmpBuffer[Ind++] = 4 + 2;  // Length
+            for( i=0; i<4; i++ )
+                TmpBuffer[Ind++] = pAC->IpAddr[i];
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 69:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))  {
+                for( i=0; i<4; i++ )
+                    pAC->AsfData.Mib.IpSource[i] = pAC->IpAddr[i];
+                    #ifdef ASF_FW_ARP_RESOLVE
+                        pAC->AsfData.GlHciState = 150;  //  do ARP resolve
+                    #else
+                        pAC->AsfData.GlHciState++;
+                    #endif
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_MAC_DESTINATION */
+        case 70:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_MAC_DESTINATION\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_MAC_DESTINATION;
+            TmpBuffer[Ind++] = 6 + 2;  // Length
+            for( i=0; i<6; i++ )
+                TmpBuffer[Ind++] = pAC->AsfData.Mib.MacDest[i];
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 71:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_COMMUNITY_NAME */
+        case 72:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_COMMUNITY_NAME\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_COMMUNITY_NAME;
+            TmpBuffer[Ind++] = 2;  // Length
+            for( i=0; i<64; i++ )  {
+                TmpBuffer[1]++;
+                TmpBuffer[Ind++] = pAC->AsfData.Mib.CommunityName[i];
+                if( TmpBuffer[Ind-1] == 0 )
+                    break;
+            }
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 73:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_RSP_KEY_1 */
+        case 74:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_RSP_KEY_1\n >"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_RSP_KEY_1;
+            TmpBuffer[Ind++] = 20 + 2;  // Length
+            for( i=0; i<20; i++ )  {
+                TmpBuffer[Ind++] = pAC->AsfData.Mib.KeyOperator[i];
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyOperator[i] ));
+            }
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n" ));
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 75:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_RSP_KEY_2 */
+        case 76:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_RSP_KEY_2\n >"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_RSP_KEY_2;
+            TmpBuffer[Ind++] = 20 + 2;  // Length
+            for( i=0; i<20; i++ )  {
+                TmpBuffer[Ind++] = pAC->AsfData.Mib.KeyAdministrator[i];
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyAdministrator[i] ));
+            }
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n" ));
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 77:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        /* YASF_HOSTCMD_CFG_SET_RSP_KEY_3 */
+        case 78:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_RSP_KEY_3\n >"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_RSP_KEY_3;
+            TmpBuffer[Ind++] = 20 + 2;  // Length
+            for( i=0; i<20; i++ )  {
+                TmpBuffer[Ind++] = pAC->AsfData.Mib.KeyGenerator[i];
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x",pAC->AsfData.Mib.KeyGenerator[i] ));
+            }
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n" ));
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 79:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE)){
+                if(pAC->AsfData.ChipMode == SK_GEASF_CHIP_Y2) {
+                    pAC->AsfData.GlHciState++;
+                }
+                else {
+                    pAC->AsfData.GlHciState+=2;
+                }
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        case 80:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  YASF_HOSTCMD_CFG_SET_ACTIVE_PORT\n"));
+            Ind = 0;
+            TmpBuffer[Ind++] = YASF_HOSTCMD_CFG_SET_ACTIVE_PORT;
+            TmpBuffer[Ind++] = 1 + 3;  // Length
+            TmpBuffer[Ind++] = pAC->AsfData.ActivePort;
+            TmpBuffer[Ind++] = pAC->AsfData.ActivePort;     // Preferred port not set directly in RLMT
+            lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_NOWAIT, 0 );
+            pAC->AsfData.GlHciState++;
+            break;
+        case 81:
+            lRetCode = AsfHciGetState( pAC );
+            if( (lRetCode == HCI_EN_CMD_READY) || (lRetCode == HCI_EN_CMD_IDLE))
+                pAC->AsfData.GlHciState++;
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+        case 82:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_STORE_CONFIG, 0, 0, 0, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sent  YASF_HOSTCMD_CFG_STORE_CONFIG\n"));
+                pAC->AsfData.GlHciState = 100;
+                //  check, whether ASF Enable has changed
+                if( pAC->AsfData.Mib.ConfigChange & 0x01 )  {
+                    // set/reset asf enable
+                    if( pAC->AsfData.Mib.Ena )  {
+                        AsfEnable(pAC, IoC );
+                        /* Force initialization of the pattern ram
+                         * (important for the very first enable of ASF)
+                         */
+                        pAC->AsfData.Mib.ConfigChange |= 0x02;
+                    }
+                    else  {
+                        AsfDisable(pAC, IoC );
+                    }
+                }
+                //  check, whether RSP Enable has changed
+                if( pAC->AsfData.Mib.ConfigChange & 0x02 )  {
+                    AsfSetUpPattern( pAC, IoC, 0 );     // Port 0
+                    if(pAC->AsfData.ChipMode == SK_GEASF_CHIP_Y2) {
+                        AsfSetUpPattern( pAC, IoC, 1 ); // Port 1
+                    }
+                }
+                pAC->AsfData.Mib.ConfigChange = 0;
+                pAC->AsfData.Mib.NewParam = 0;
+            }
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        /*------------------------------------------------------------------------------------------------------
+         *  Get ASF configuration data from FW (SEEPROM)
+         *----------------------------------------------------------------------------------------------------*/
+
+        case 100:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_ASF_ENABLE, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                pAC->AsfData.Mib.Ena = *(pHciRecBuf+2);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_ASF_ENABLE:0x%x \n",
+                                                              pAC->AsfData.Mib.Ena ));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 101:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_RSP_ENABLE, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                pAC->AsfData.Mib.RspEnable = *(pHciRecBuf+2);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_RSP_ENABLE:0x%x \n",
+                                                              pAC->AsfData.Mib.RspEnable ));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 102:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_RETRANS, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                pAC->AsfData.Mib.Retrans = *(pHciRecBuf+2);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_RETRANS:0x%x \n",
+                                                              pAC->AsfData.Mib.Retrans ));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 103:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_RETRANS_INT, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                pAC->AsfData.Mib.RetransInt  = ((SK_U32)*(pHciRecBuf+2)) << 8;
+                pAC->AsfData.Mib.RetransInt |= ((SK_U32)*(pHciRecBuf+3)) << 0;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_RETRANS_INT:0x%x \n",
+                                                              pAC->AsfData.Mib.RetransInt ));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 104:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_HB_ENABLE, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                pAC->AsfData.Mib.HbEna = *(pHciRecBuf+2);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_HB_ENABLE:0x%x \n",
+                                                              pAC->AsfData.Mib.HbEna ));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 105:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_HB_INT, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                pAC->AsfData.Mib.HbInt  = ((SK_U32)*(pHciRecBuf+2)) << 8;
+                pAC->AsfData.Mib.HbInt |= ((SK_U32)*(pHciRecBuf+3)) << 0;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_HB_INT:0x%x \n",
+                                                              pAC->AsfData.Mib.HbInt));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 106:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_DRWD_ENABLE, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                pAC->AsfData.Mib.WdEna = *(pHciRecBuf+2);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_DRWD_ENABLE:0x%x \n",
+                                                              pAC->AsfData.Mib.WdEna ));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 107:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_DRWD_INT, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                pAC->AsfData.Mib.WdTime  = ((SK_U32)*(pHciRecBuf+2)) << 8;
+                pAC->AsfData.Mib.WdTime |= ((SK_U32)*(pHciRecBuf+3)) << 0;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_DRWD_INT:0x%x \n",
+                                                              pAC->AsfData.Mib.HbInt));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 108:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_IP_DESTINATION, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                for( i=0; i<4; i++ )
+                    pAC->AsfData.Mib.IpDest[i]  = *(pHciRecBuf+2+i);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_IP_DESTINATION %d.%d.%d.%d\n",
+                        pAC->AsfData.Mib.IpDest[0], pAC->AsfData.Mib.IpDest[1],
+                        pAC->AsfData.Mib.IpDest[2], pAC->AsfData.Mib.IpDest[3]));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 109:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_IP_SOURCE, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                for( i=0; i<4; i++ )
+                    pAC->AsfData.Mib.IpSource[i]  = *(pHciRecBuf+2+i);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_IP_SOURCE %d.%d.%d.%d\n",
+                        pAC->AsfData.Mib.IpSource[0], pAC->AsfData.Mib.IpSource[1],
+                        pAC->AsfData.Mib.IpSource[2], pAC->AsfData.Mib.IpSource[3]));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 110:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_MAC_DESTINATION, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                for( i=0; i<6; i++ )
+                    pAC->AsfData.Mib.MacDest[i]  = *(pHciRecBuf+2+i);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+                           ("SkAsfTimer: YASF_HOSTCMD_CFG_GET_MAC_DESTINATION %02x-%02x-%02x-%02x-%02x-%02x\n",
+                       pAC->AsfData.Mib.MacDest[0], pAC->AsfData.Mib.MacDest[1], pAC->AsfData.Mib.MacDest[2],
+                       pAC->AsfData.Mib.MacDest[3], pAC->AsfData.Mib.MacDest[4], pAC->AsfData.Mib.MacDest[5]));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 111:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_COMMUNITY_NAME, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_COMMUNITY_NAME l:%d >",Length))
+                for( i=0; (i<63)&&(i<Length); i++ )  {
+                    pAC->AsfData.Mib.CommunityName[i]  = *(pHciRecBuf+2+i);
+                    pAC->AsfData.Mib.CommunityName[i+1]  = 0;
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%c",pAC->AsfData.Mib.CommunityName[i]))
+                }
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"))
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 112:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_RSP_KEY_1, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_RSP_KEY_1: (%d)\n  >", Length));
+                for( i=0; (i<20)&&(i<Length); i++ )  {
+                    pAC->AsfData.Mib.KeyOperator[i]  = *(pHciRecBuf+2+i);
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x", pAC->AsfData.Mib.KeyOperator[i]));
+                }
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 113:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_RSP_KEY_2, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_RSP_KEY_2: (%d)\n  >", Length));
+                for( i=0; (i<20)&&(i<Length); i++ )  {
+                    pAC->AsfData.Mib.KeyAdministrator[i]  = *(pHciRecBuf+2+i);
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x", pAC->AsfData.Mib.KeyAdministrator[i]));
+                }
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 114:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_RSP_KEY_3, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_RSP_KEY_3: (%d)\n  >", Length));
+                for( i=0; (i<20)&&(i<Length); i++ )  {
+                    pAC->AsfData.Mib.KeyGenerator[i]  = *(pHciRecBuf+2+i);
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%02x", pAC->AsfData.Mib.KeyGenerator[i]));
+                }
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 115:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_FW_VERSION_STRING, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_FW_VERSION_STRING l:%d\n",Length))
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("         >"))
+                for( i=0; (i<79)&&(i<Length); i++ )  {
+                    pAC->AsfData.FwVersionString[i]   = *(pHciRecBuf+2+i);
+                    pAC->AsfData.FwVersionString[i+1] = 0;
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("%c",pAC->AsfData.FwVersionString[i]))
+                }
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("<\n"))
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 116:
+            // get SMBus infos from FW
+
+            // do not ask twice
+            pAC->AsfData.Mib.SMBus.UpdateReq = 0;
+
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_SMBUS_INFOS, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: YASF_HOSTCMD_CFG_GET_SMBUS_INFOS l:%d\n", Length))
+
+                pAC->AsfData.Mib.SMBus.length = 0;
+                for( i=0; (i<ASF_SMBUS_MAXBUFFLENGTH)&&(i<Length); i++ )  {
+                    pAC->AsfData.Mib.SMBus.length   += 1;
+                    pAC->AsfData.Mib.SMBus.buffer[i] = *(pHciRecBuf+2+i);
+                    if ( (i%16) != 0) {
+                        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,(" 0x%02x", pAC->AsfData.Mib.SMBus.buffer[i]))
+                    }
+                    else {
+                        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n         > 0x%02x", pAC->AsfData.Mib.SMBus.buffer[i]))
+                    }
+                }
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n\n"))
+                if(pAC->AsfData.ChipMode == SK_GEASF_CHIP_Y2) {
+                    pAC->AsfData.GlHciState++;
+                }
+                else {
+                    pAC->AsfData.GlHciState+=2;
+                }
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+
+            if( lRetCode == HCI_EN_CMD_ERROR ) {
+                pAC->AsfData.GlHciState = 255;
+            }
+            break;
+
+        case 117:
+            lRetCode = AsfHciSendCommand(pAC, IoC, YASF_HOSTCMD_CFG_GET_ACTIVE_PORT, 0, 0, 1, ASF_HCI_NOWAIT, 0 );
+            if( lRetCode == HCI_EN_CMD_READY )  {
+                // Fetch received data from HCI interface
+                AsfHciGetData( pAC, &pHciRecBuf );
+                Length = *(pHciRecBuf + 1);
+                pAC->AsfData.ActivePort = *(pHciRecBuf + 2);
+                pAC->AsfData.PrefPort   = *(pHciRecBuf + 3);
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+                    ("SkAsfTimer: YASF_HOSTCMD_CFG_GET_ACTIVE_PORT: %d %d\n  >",
+                    pAC->AsfData.ActivePort, pAC->AsfData.PrefPort));
+                pAC->AsfData.GlHciState++;
+            }  //  if( lRetCode == HCI_EN_CMD_READY )
+            if( lRetCode == HCI_EN_CMD_ERROR )
+                pAC->AsfData.GlHciState = 255;
+            break;
+
+        case 118:
+            if (pAC->AsfData.Mib.PattUpReq != 0)   {
+                pAC->AsfData.Mib.PattUpReq = 0;
+
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+                    ("SkAsfTimer: update pattern in state %d with rsp %d\n",
+                    pAC->AsfData.GlHciState, pAC->AsfData.Mib.RspEnable));
+
+                AsfSetUpPattern(pAC, IoC, 0);       // Port 0
+                if(pAC->AsfData.ChipMode == SK_GEASF_CHIP_Y2) {
+                    AsfSetUpPattern(pAC, IoC, 1);   // Port 1
+                }
+            }
+            pAC->AsfData.GlHciState = 254;
+            break;
+
+        /*------------------------------------------------------------------------------------------------------
+         *  ARP resolve
+         *----------------------------------------------------------------------------------------------------*/
+
+        case 150:
+
+#ifdef ASF_FW_ARP_RESOLVE
+            if (pAC->AsfData.OpMode == SK_GEASF_MODE_ASF) {
+
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: sending  ARP REQUEST\n"));
+                Ind = 0;
+                TmpBuffer[Ind++] = YASF_HOSTCMD_ARP_RESOLVE;
+                TmpBuffer[Ind++] = 4 + 2;  // Length
+                for( i=0; i<4; i++ )
+                    TmpBuffer[Ind++] = pAC->AsfData.Mib.IpDest[i];
+                AsfSetUpPattern( pAC, IoC, pAC->AsfData.ActivePort );  //  prepare pattern logik for ARP handling
+                YlciEnablePattern ( pAC, IoC, pAC->AsfData.ActivePort, 5 );  //  enable the ARP pattern
+                AsfEnable(pAC, IoC );  //  enable ASF logik for receiving ARP response
+                lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 1, ASF_HCI_NOWAIT, 0 );
+                if( lRetCode == HCI_EN_CMD_READY )  {
+                    YlciDisablePattern ( pAC, IoC, pAC->AsfData.ActivePort, 5 );  //  disable the ARP pattern
+                    if( pAC->AsfData.Mib.Ena == 0 )
+                        AsfDisable(pAC, IoC );
+                    // Fetch received data from HCI interface
+                    AsfHciGetData( pAC, &pHciRecBuf );
+                    for( i=0; i<6; i++ )
+                        pAC->AsfData.Mib.MacDest[i]  = *(pHciRecBuf+2+i);
+
+                    if( (pAC->AsfData.Mib.MacDest[0] == 0) && (pAC->AsfData.Mib.MacDest[1] == 0) &&
+                        (pAC->AsfData.Mib.MacDest[2] == 0) && (pAC->AsfData.Mib.MacDest[3] == 0) &&
+                        (pAC->AsfData.Mib.MacDest[4] == 0) && (pAC->AsfData.Mib.MacDest[5] == 0)    )  {
+                        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+                                   ("SkAsfTimer: YASF_HOSTCMD_ARP_RESOLVE     NOT RESOLVED !!\n"));
+                    }
+                    else  {
+                        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+                                   ("SkAsfTimer: YASF_HOSTCMD_ARP_RESOLVE %02x-%02x-%02x-%02x-%02x-%02x\n",
+                               pAC->AsfData.Mib.MacDest[0], pAC->AsfData.Mib.MacDest[1], pAC->AsfData.Mib.MacDest[2],
+                               pAC->AsfData.Mib.MacDest[3], pAC->AsfData.Mib.MacDest[4], pAC->AsfData.Mib.MacDest[5]));
+
+                    }
+
+                    pAC->AsfData.GlHciState++;
+                }  //  if( lRetCode == HCI_EN_CMD_READY )
+                if( lRetCode == HCI_EN_CMD_ERROR )  {
+                    pAC->AsfData.GlHciState = 255;
+                    YlciDisablePattern ( pAC, IoC, pAC->AsfData.ActivePort, 5 );    //  disable the ARP pattern
+                    if( pAC->AsfData.Mib.Ena == 0 )
+                        AsfDisable(pAC, IoC );
+                }
+            }
+            else {
+                pAC->AsfData.GlHciState++;
+            }
+
+#else   //  ASF_FW_ARP_RESOLVE
+
+            pAC->AsfData.GlHciState++;
+
+#endif
+            break;
+
+        case 151:
+            pAC->AsfData.GlHciState = 70;
+            break;
+
+        /*------------------------------------------------------------------------------------------------------
+         *  Finish state
+         *----------------------------------------------------------------------------------------------------*/
+        case 254:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: ***** Finish *****\n"));
+            pAC->AsfData.FwError = 0;
+            pAC->AsfData.GlHciState = 0;
+            pAC->AsfData.Mib.NewParam = 0;
+            pAC->AsfData.LastGlHciState = pAC->AsfData.GlHciState;
+            break;
+
+        /*------------------------------------------------------------------------------------------------------
+         *  Error handling
+         *----------------------------------------------------------------------------------------------------*/
+        case 255:
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: ***** ERROR *****\n"));
+            pAC->AsfData.FwError++;
+            if(pAC->AsfData.FwError > 2) {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("***** CPU RESET *****\n"));
+                AsfSmartResetCpu( pAC, IoC, ASF_RESET_HOT );
+                AsfRunCpu( pAC, IoC );
+            }
+            pAC->AsfData.LastGlHciState = pAC->AsfData.GlHciState; // Store Error State
+            pAC->AsfData.GlHciState = 0;
+            pAC->AsfData.Mib.NewParam = 0;
+            pAC->AsfData.Hci.Status = HCI_EN_CMD_IDLE;
+            break;
+    }  //   switch(  &pAC->AsfData.GlHciState == 0  )  {
+
+    if( pAC->AsfData.GlHciState != pAC->AsfData.LastGlHciState )  {
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfTimer: New State %d -> %d\n", pAC->AsfData.LastGlHciState, pAC->AsfData.GlHciState));
+        if( pAC->AsfData.LastGlHciState != 255 ) { // Don't overwrite Error State, it will be checked in case 0
+            pAC->AsfData.LastGlHciState = pAC->AsfData.GlHciState;
+        }
+    }
+
+    if( pAC->AsfData.GlHciState == 0 )  {  //  idle
+        SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+        SkTimerStart(pAC, IoC, &pAC->AsfData.AsfTimer,
+                     1000000, SKGE_ASF, SK_ASF_EVT_TIMER_EXPIRED,
+                     EventParam);
+    }
+    else  {
+        SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+        SkTimerStart(pAC, IoC, &pAC->AsfData.AsfTimer,
+                     30000, SKGE_ASF, SK_ASF_EVT_TIMER_EXPIRED,
+                     EventParam);
+    }
+
+    return;
+}
+
+#if (0)
+/*****************************************************************************
+*
+* AsfReadConfiguration
+*
+* Description:
+*
+* Returns:
+*
+*/
+NDIS_STATUS AsfReadConfiguration(
+IN SK_AC *pAc,
+IN NDIS_HANDLE ConfigHandle,
+IN NDIS_HANDLE WrapperConfigContext)
+{
+    SK_DBG_MSG(pAc, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,
+    ("AsfReadConfiguration (No data loaded !)\n" ));
+
+    return (NDIS_STATUS_SUCCESS);
+}
+#endif
+
+
+/*****************************************************************************
+*
+* SkAsfShowMib
+*
+* Description:
+*
+* Returns:
+*
+*/
+void SkAsfShowMib( SK_AC *pAC )  {
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("ASF MIB (h):\n") );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("------------\n") );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   Ena:            %d\n", pAC->AsfData.Mib.Ena ) );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   Retrans:        %d Int:%d\n", pAC->AsfData.Mib.Retrans,
+                                                                                    pAC->AsfData.Mib.RetransInt ) );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   HbEna:          %d Int:%d\n", pAC->AsfData.Mib.HbEna,
+                                                                                    pAC->AsfData.Mib.HbInt ) );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   WdEna:          %d Time:%d\n", pAC->AsfData.Mib.WdEna,
+                                                                                    pAC->AsfData.Mib.WdTime ) );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   IpDest (d):     %d.%d.%d.%d\n",
+                                                    pAC->AsfData.Mib.IpDest[0], pAC->AsfData.Mib.IpDest[1],
+                                                    pAC->AsfData.Mib.IpDest[2], pAC->AsfData.Mib.IpDest[3] ) );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   IpSource (d):   %d.%d.%d.%d\n",
+                                                    pAC->AsfData.Mib.IpSource[0], pAC->AsfData.Mib.IpSource[1],
+                                                    pAC->AsfData.Mib.IpSource[2], pAC->AsfData.Mib.IpSource[3] ) );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   MacDest:        %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                                    pAC->AsfData.Mib.MacDest[0], pAC->AsfData.Mib.MacDest[1],
+                                                    pAC->AsfData.Mib.MacDest[2], pAC->AsfData.Mib.MacDest[3],
+                                                    pAC->AsfData.Mib.MacDest[4], pAC->AsfData.Mib.MacDest[5] ) );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   MacSource:      %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                                    pAC->AsfData.Mib.MacSource[0], pAC->AsfData.Mib.MacSource[1],
+                                                    pAC->AsfData.Mib.MacSource[2], pAC->AsfData.Mib.MacSource[3],
+                                                    pAC->AsfData.Mib.MacSource[4], pAC->AsfData.Mib.MacSource[5] ) );
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL, ("   CommunityName:  >%s<\n", pAC->AsfData.Mib.CommunityName ) );
+}
+
+/*****************************************************************************
+*
+* AsfCpuState
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8 AsfCpuState( SK_AC *pAC, SK_IOC IoC )  {
+  SK_U32 TmpVal32;
+  
+  SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+  
+  if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )  {
+    if( (TmpVal32&(BIT_0 | BIT_1)) == 0 ) {
+      return( ASF_CPU_STATE_RESET );
+    }
+    else  if ( (TmpVal32&(BIT_0 | BIT_1)) == 1 ) {
+      return( ASF_CPU_STATE_RUNNING );
+    }
+    else  {
+      return( ASF_CPU_STATE_UNKNOWN );
+    }
+  }
+  else  {
+    if( TmpVal32 & BIT_3 )
+      return( ASF_CPU_STATE_RESET );
+    if( TmpVal32 & BIT_2 )
+      return( ASF_CPU_STATE_RUNNING );
+  }
+  
+  return( ASF_CPU_STATE_UNKNOWN );
+}
+
+/*****************************************************************************
+*
+* AsfResetCpu
+*
+* Description:
+*
+* Returns:
+*
+*/
+void AsfResetCpu(SK_AC *pAC, SK_IOC IoC)  {
+    SK_U32 TmpVal32;
+
+    if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )  {
+      SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+      TmpVal32 &= ~(BIT_0 | BIT_1);
+      SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );
+    }
+    else  {
+      SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+      TmpVal32 &= ~(BIT_2 | BIT_3);
+      TmpVal32 |= BIT_3;
+      SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );
+    }
+}
+
+/*****************************************************************************
+*
+* AsfSmartResetCpu
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8 AsfSmartResetCpu( SK_AC *pAC, SK_IOC IoC, SK_U8 Cold )  {
+SK_U64 StartTime, CurrTime;
+SK_U8   ResetCommand;
+
+    if( Cold )
+        ResetCommand = YASF_HOSTCMD_RESET_COLD;
+    else
+        ResetCommand = YASF_HOSTCMD_RESET;
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfSmartResetCpu -> \n"));
+
+    //  check, whether cpu is already in reset state...
+    if( AsfCpuState( pAC, IoC ) != ASF_CPU_STATE_RESET )  {
+        // ...if not, try SmartReset
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfSmartResetCpu -> Send reset command\n"));
+        if( AsfHciSendCommand( pAC, IoC, ResetCommand, 0, 0, 0, ASF_HCI_WAIT, 2 ) != HCI_EN_CMD_READY )  {
+          //  if Smart Reset fails, do hard reset
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfSmartResetCpu -> Do hard reset\n"));
+            AsfResetCpu( pAC, IoC );
+        }
+        StartTime = SkOsGetTime(pAC);
+        while( AsfCpuState( pAC, IoC ) != ASF_CPU_STATE_RESET ) {
+            CurrTime = SkOsGetTime(pAC);
+            if ( (CurrTime - StartTime) > (SK_TICKS_PER_SEC*1) )  {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfSmartResetCpu -> Error: CPU is not in reset state - Do hard reset\n"));
+                AsfResetCpu( pAC, IoC );
+                break;
+            }
+        }  //  while( AsfCpuState( IoC ) != ASF_CPU_STATE_RESET ) {
+
+        if( AsfCpuState( pAC, IoC ) == ASF_CPU_STATE_RESET )
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfSmartResetCpu -> CPU is in reset state\n"));
+
+    }  //  if( AsfCpuState( IoC ) != ASF_CPU_STATE_RESET )  {
+    else  {
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfSmartResetCpu -> Cpu already in reset state\n"));
+    }
+
+    return( 1 );
+}
+
+/*****************************************************************************
+*
+* AsfSmartResetStateCpu
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8 AsfSmartResetStateCpu( SK_AC *pAC, SK_IOC IoC )  {
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("Send AsfSmartResetStateCpu\n"));
+    return( AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_RESET_STATE, 0, 0, 0, ASF_HCI_WAIT, 3 ) );
+}
+
+/*****************************************************************************
+*
+* AsfRunCpu
+*
+* Description:
+*
+* Returns:
+*
+*/
+void AsfRunCpu( SK_AC *pAC, SK_IOC IoC )  {
+  SK_U32 TmpVal32;
+  
+  if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )  {
+    SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+    TmpVal32 |= BIT_0;  // Set to running state
+    SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );
+  }
+  else  {
+    SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+    TmpVal32 &= ~(BIT_2 | BIT_3);
+    TmpVal32 |= BIT_3;  // Set to Reset state (Clk running)
+    SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );
+    TmpVal32 &= ~(BIT_2 | BIT_3);
+    TmpVal32 |= BIT_2;  // Set to running state
+    SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );
+  }
+}
+
+
+/*****************************************************************************
+*
+* AsfCheckAliveCpu
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8 AsfCheckAliveCpu( SK_AC *pAC, SK_IOC IoC )  {
+SK_U8 Alive;
+
+    //SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfCheckAliveCpu -> \n"));
+    Alive = 0;  //  Not alive
+    //  check, whether cpu is in reset state...
+    if( AsfCpuState( pAC, IoC ) != ASF_CPU_STATE_RESET )  {
+        // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfSmartResetCpu -> Send Check Alive command\n"));
+        if( AsfHciSendCommand( pAC, IoC, YASF_HOSTCMD_CHECK_ALIVE, 0, 0, 0, ASF_HCI_WAIT, 2 ) != HCI_EN_CMD_READY )  {
+          //  if Smart Reset fails, do hard reset
+            // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfCheckAliveCpu -> Not alive\n"));
+        }
+        else
+            Alive = 1;
+    }  //  if( AsfCpuState( IoC ) != ASF_CPU_STATE_RESET )  {
+    else  {
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("AsfCheckAliveCpu -> *** CPU is in reset state ***\n"));
+    }
+
+    return( Alive );
+}
+
+/*****************************************************************************
+*
+* AsfSetOsPresentBit
+*
+* Description:
+*
+* Returns:
+*
+*/
+void AsfSetOsPresentBit( SK_AC *pAC, SK_IOC IoC )  {
+    SK_U32 TmpVal32;
+	
+    SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+    if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )
+        TmpVal32 |= BIT_2;
+	else
+        TmpVal32 |= BIT_4;
+    SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );	
+}
+
+/*****************************************************************************
+*
+* AsfResetOsPresentBit
+*
+* Description:
+*
+* Returns:
+*
+*/
+void AsfResetOsPresentBit( SK_AC *pAC, SK_IOC IoC )  {
+    SK_U32 TmpVal32;
+
+    SK_IN32( IoC, REG_ASF_STATUS_CMD, &TmpVal32 );
+    if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )
+	    TmpVal32 &= ~BIT_2;
+	else
+	    TmpVal32 &= ~BIT_4;
+    SK_OUT32( IoC, REG_ASF_STATUS_CMD, TmpVal32 );	
+}
+
+/*****************************************************************************
+*
+* AsfEnableFlushFifo
+*
+* Description:
+*
+* Returns:
+*
+*/
+void AsfEnableFlushFifo( SK_AC *pAC, SK_IOC IoC )  {
+    SK_U32 TmpVal32;
+
+    //ADD
+    return;
+
+#ifdef CHIP_ID_YUKON_EX	
+    SK_IN32( IoC, RXMF_TCTL, &TmpVal32 );
+	TmpVal32 &= ~(BIT_23 | BIT_22);
+	TmpVal32 |= BIT_23;
+    SK_OUT32( IoC, RXMF_TCTL, TmpVal32 );	
+#endif
+
+}
+
+/*****************************************************************************
+*
+* AsfDisableFlushFifo
+*
+* Description:
+*
+* Returns:
+*
+*/
+void AsfDisableFlushFifo( SK_AC *pAC , SK_IOC IoC)  {
+    SK_U32 TmpVal32;
+
+#ifdef CHIP_ID_YUKON_EX	
+    SK_IN32( IoC, RXMF_TCTL, &TmpVal32 );
+	TmpVal32 &= ~(BIT_23 | BIT_22);
+	TmpVal32 |= BIT_22;
+    SK_OUT32( IoC, RXMF_TCTL, TmpVal32 );	
+#endif
+
+}
+
+/*****************************************************************************
+*
+* AsfLockSpi
+*
+* Description:
+*
+* Returns:
+*
+*/
+void AsfLockSpi( SK_AC *pAC, SK_IOC IoC )  {
+    SK_U8 TmpVal8;
+
+    SK_IN8( IoC, GPHY_CTRL + 2, &TmpVal8);
+    TmpVal8 |= BIT_0;
+    SK_OUT8( IoC, GPHY_CTRL + 2, TmpVal8);
+}
+
+/*****************************************************************************
+*
+* AsfUnlockSpi
+*
+* Description:
+*
+* Returns:
+*
+*/
+void AsfUnlockSpi( SK_AC *pAC, SK_IOC IoC )  {
+    SK_U8 TmpVal8;
+
+    SK_IN8( IoC, GPHY_CTRL + 2, &TmpVal8);
+    TmpVal8 &= ~BIT_0;
+    SK_OUT8( IoC, GPHY_CTRL + 2, TmpVal8);
+}
+
+/*****************************************************************************
+*
+* SkAsfHci
+*
+* Description:
+*
+* Returns:
+*
+*/
+void SkAsfHci(
+SK_AC *pAC, /* Pointer to adapter context */
+SK_IOC IoC,
+SK_U8   ToEna ) /* IO context handle */  {
+
+    SK_EVPARA   EventParam;
+    SK_U32      Cmd;
+    SK_U32      SendValue;
+    SK_U32      RecValue;
+
+    if (pAC->AsfData.Hci.Status == HCI_EN_CMD_IDLE)
+        return;
+
+    pAC->AsfData.Hci.Cycles++;
+
+    // Check, whether there is something to do
+    SK_IN32( IoC, ASF_HCI_CMDREG, &Cmd );
+    if( pAC->AsfData.Hci.OldCmdReg != Cmd )  {
+        pAC->AsfData.Hci.OldCmdReg = Cmd;
+        // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfHci CmdReg: 0x%x\n", Cmd ));
+    }
+
+    // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("                    CmdReg: 0x%x\n", Cmd ));
+
+    if ((Cmd & (ASF_HCI_READ | ASF_HCI_WRITE | ASF_HCI_CMD_RD_READY | ASF_HCI_CMD_WR_READY | ASF_HCI_UNSUCCESS)) == 0)
+    {
+        // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfHci State: 0x%x\n", pAC->AsfData.Hci.Status ));
+        switch( pAC->AsfData.Hci.Status )  {
+
+            case HCI_EN_CMD_WRITING:
+                SendValue = 0;
+                if (pAC->AsfData.Hci.SendLength > 0)
+                {
+                    pAC->AsfData.Hci.SendLength--;
+                    SendValue = ((SK_U32)pAC->AsfData.Hci.TransmitBuf[pAC->AsfData.Hci.SendIndex +0]) << 24;
+                    if (pAC->AsfData.Hci.SendLength > 0)
+                    {
+                        pAC->AsfData.Hci.SendLength--;
+                        SendValue += ((SK_U32)pAC->AsfData.Hci.TransmitBuf[pAC->AsfData.Hci.SendIndex +1]) << 16;
+                        if (pAC->AsfData.Hci.SendLength > 0)
+                        {
+                            pAC->AsfData.Hci.SendLength--;
+                            SendValue += ((SK_U32)pAC->AsfData.Hci.TransmitBuf[pAC->AsfData.Hci.SendIndex +2]) << 8;
+                            if (pAC->AsfData.Hci.SendLength > 0)
+                            {
+                                pAC->AsfData.Hci.SendLength--;
+                                SendValue += ((SK_U32)pAC->AsfData.Hci.TransmitBuf[pAC->AsfData.Hci.SendIndex +3]) << 0;
+                            }
+                        }
+                    }
+                }
+
+                // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        SendValue: 0x%x l:%d\n",
+                //                                             SendValue, pAC->AsfData.Hci.SendLength ));
+                SK_OUT32( IoC, ASF_HCI_DATAREG, SendValue);
+                if (pAC->AsfData.Hci.SendLength == 0)
+                {
+                    SK_OUT32( IoC, ASF_HCI_CMDREG, ASF_HCI_WRITE | ASF_HCI_CMD_WR_READY | ASF_HCI_UNSUCCESS | (pAC->AsfData.Hci.SendIndex/4));
+                    pAC->AsfData.Hci.Status = HCI_EN_CMD_WAIT;
+                }
+                else
+                {
+                    SK_OUT32( IoC, ASF_HCI_CMDREG, ASF_HCI_WRITE | ASF_HCI_UNSUCCESS | (pAC->AsfData.Hci.SendIndex/4));
+                    pAC->AsfData.Hci.SendIndex += 4;
+                }
+                break;
+
+            case HCI_EN_CMD_WAIT:
+                if( pAC->AsfData.Hci.ExpectResponse )  {
+                    pAC->AsfData.Hci.Status = HCI_EN_CMD_READING;
+                    pAC->AsfData.Hci.ReceiveIndex = 0;
+                    // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        Wait for response\n" ));
+                    SK_OUT32( IoC, ASF_HCI_CMDREG, ASF_HCI_READ | ASF_HCI_UNSUCCESS | (pAC->AsfData.Hci.ReceiveIndex/4));
+                }
+                else  {
+                    pAC->AsfData.Hci.Status = HCI_EN_CMD_READY;
+                    pAC->AsfData.Hci.ReceiveBuf[1] = 0;  /*Length*/
+                }
+                break;
+
+            case HCI_EN_CMD_READING:
+                SK_IN32( IoC, ASF_HCI_DATAREG, &RecValue );
+                // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        RecValue: 0x%x\n", RecValue ));
+                pAC->AsfData.Hci.ReceiveBuf[pAC->AsfData.Hci.ReceiveIndex+3] = (SK_U8) (RecValue >>  0) & 0x000000ff;
+                pAC->AsfData.Hci.ReceiveBuf[pAC->AsfData.Hci.ReceiveIndex+2] = (SK_U8) (RecValue >>  8) & 0x000000ff;
+                pAC->AsfData.Hci.ReceiveBuf[pAC->AsfData.Hci.ReceiveIndex+1] = (SK_U8) (RecValue >> 16) & 0x000000ff;
+                pAC->AsfData.Hci.ReceiveBuf[pAC->AsfData.Hci.ReceiveIndex+0] = (SK_U8) (RecValue >> 24) & 0x000000ff;
+                pAC->AsfData.Hci.ReceiveIndex   += 4;
+                //SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        RecValue: 0x%x RecIndex:%d l:%d\n",
+                //                          RecValue,pAC->AsfData.Hci.ReceiveIndex, pAC->AsfData.Hci.ReceiveBuf[1] ));
+                if( pAC->AsfData.Hci.ReceiveBuf[1] > pAC->AsfData.Hci.ReceiveIndex )  { /* check length*/
+                    SK_OUT32( IoC, ASF_HCI_CMDREG, ASF_HCI_READ | ASF_HCI_UNSUCCESS | (pAC->AsfData.Hci.ReceiveIndex/4));
+                }
+                else  {
+                    SK_OUT32( IoC, ASF_HCI_CMDREG, ASF_HCI_CMD_RD_READY );
+                    pAC->AsfData.Hci.Status = HCI_EN_CMD_READY;
+                }
+                break;
+
+            case HCI_EN_CMD_READY:
+                break;
+
+        }  //  switch( pAC->AsfData.Hci.Status )  {
+
+        pAC->AsfData.Hci.To = 0;
+
+    }  //  if ((Cmd & (ASF_HCI_READ | ASF_HCI_WRITE | ASF_HCI_CMD_RD_READY | ASF_HCI_CMD_WR_READY)) == 0)
+    else  {
+
+        if( ToEna )
+            pAC->AsfData.Hci.To++;
+        /*  Timeout ! */
+        if( pAC->AsfData.Hci.To > ASF_HCI_TO )  {
+            pAC->AsfData.Hci.Status = HCI_EN_CMD_ERROR;
+        }
+    }
+
+    if( ToEna )  {
+        if( pAC->AsfData.Hci.Status != HCI_EN_CMD_IDLE &&
+            pAC->AsfData.Hci.Status != HCI_EN_CMD_READY &&
+            pAC->AsfData.Hci.Status != HCI_EN_CMD_ERROR ) {
+            SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+            SkTimerStart(pAC, IoC, &pAC->AsfData.Hci.AsfTimerHci,  /*  10ms */
+                         10000, SKGE_ASF, SK_ASF_EVT_TIMER_HCI_EXPIRED,
+                         EventParam);
+        }
+    }
+
+    return;
+}
+
+
+/*****************************************************************************
+*
+* AsfHciGetData
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8 AsfHciGetData( SK_AC  *pAC, SK_U8 **pHciRecBuf )  {
+    *pHciRecBuf = pAC->AsfData.Hci.ReceiveBuf;
+    return( 1 );
+}
+
+/*****************************************************************************
+*
+* AsfHciGetState
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8   AsfHciGetState( SK_AC *pAC )  {
+    SK_U8   Stat;
+    SK_U64  DiffTime;
+
+    Stat = pAC->AsfData.Hci.Status;
+    if( Stat == HCI_EN_CMD_READY )  {
+        pAC->AsfData.Hci.Status = HCI_EN_CMD_IDLE;
+        DiffTime = SkOsGetTime(pAC) - pAC->AsfData.Hci.Time;
+//        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    *** Cycles:%d Time:%lums\n",
+//             pAC->AsfData.Hci.Cycles, DiffTime / (10*1000) ));
+    }
+    return( Stat );
+}
+
+
+/*****************************************************************************
+*
+* AsfHciSendCommand
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8   AsfHciSendCommand(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   Command,
+SK_U8   Par1,
+SK_U8   Par2,
+SK_U8   ExpectResponse,
+SK_U8   Wait,
+SK_U8   Retry )  {
+    SK_U8   RetCode;
+    SK_U8   Message[4];
+    SK_U64  StartTime;
+    SK_U64  CurrTime;
+    SK_U64  TmpTime;
+
+    do {
+        if( pAC->AsfData.Hci.Status == HCI_EN_CMD_IDLE )  {
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Send Command cmd:0x%x p1:0x%x p2:0x%x wait:%d Retry:%d\n",
+                                                           Command, Par1, Par2, Wait, Retry ));
+            Message[0] = Command;
+            Message[1] = 2;  //  Length
+            Message[2] = Par1;
+            Message[3] = Par2;
+            RetCode = AsfHciSendMessage(pAC, IoC, Message, 4, ExpectResponse, Wait );
+        }
+
+        if( Wait )  {
+            StartTime = SkOsGetTime(pAC);
+
+            TmpTime = StartTime + 1;
+            do {
+                CurrTime = SkOsGetTime(pAC);
+                if( CurrTime > TmpTime )  {
+		  SkAsfHci( pAC, IoC, 0 );
+
+                    TmpTime = CurrTime + 1;
+                }
+                RetCode = AsfHciGetState( pAC );
+
+                if  ( (CurrTime - StartTime) > (SK_TICKS_PER_SEC*1) ) {
+                    RetCode = HCI_EN_CMD_ERROR;
+                    break;
+                }
+            } while( (RetCode != HCI_EN_CMD_READY) && (RetCode != HCI_EN_CMD_ERROR) );
+
+            if( (RetCode != HCI_EN_CMD_READY) )  {
+                pAC->AsfData.Hci.Status = HCI_EN_CMD_IDLE;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Command not confirmed RetCode:0x%x\n", RetCode ));
+            }
+        }  //  if( wait...
+        else  {
+            RetCode = AsfHciGetState( pAC );
+            if( (RetCode == HCI_EN_CMD_ERROR) )  {
+                pAC->AsfData.Hci.Status = HCI_EN_CMD_IDLE;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Command not confirmed RetCode:0x%x\n", RetCode ));
+            }
+        }
+
+        if( Retry > 0 )
+            Retry--;
+        else
+            break;
+
+    } while ( Wait && (RetCode != HCI_EN_CMD_READY) );
+
+    if( (RetCode == HCI_EN_CMD_READY) )  {
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Command successfully conveyed\n"));
+#if (0)
+	if (Wait)
+	  printk("    Time required: %lu\n", (CurrTime-StartTime));
+#endif
+    }
+
+    return( RetCode );
+}
+
+/*****************************************************************************
+*
+* AsfHciSendData
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8   AsfHciSendData(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   *Buffer,
+SK_U8   ExpectResponse,
+SK_U8   Wait,
+SK_U8   Retry )  {
+    SK_U8   RetCode;
+    SK_U64  StartTime;
+    SK_U64  CurrTime;
+    SK_U64  TmpTime;
+    SK_U8   Length;
+    SK_U8   Command;
+
+    do {
+        if( pAC->AsfData.Hci.Status == HCI_EN_CMD_IDLE )  {
+            Command = *(Buffer + 0 );
+            Length =  *(Buffer + 1);
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Send Data cmd:0x%x Length:%d wait:%d Retry:%d\n",
+                                                           Command, Length, Wait, Retry ));
+            RetCode = AsfHciSendMessage(pAC, IoC, Buffer, Length, ExpectResponse, Wait );
+        }
+        if( Wait )  {
+            StartTime = SkOsGetTime(pAC);
+            TmpTime = StartTime + 1;
+            do {
+                CurrTime = SkOsGetTime(pAC);
+                if( CurrTime > TmpTime )  {
+                    SkAsfHci( pAC, IoC, 0 );
+                    TmpTime = CurrTime + 1;
+                }
+                RetCode = AsfHciGetState( pAC );
+                if ( (CurrTime - StartTime) > (SK_TICKS_PER_SEC*1) )  {
+                    RetCode = HCI_EN_CMD_ERROR;
+                    break;
+                }
+            } while ( (RetCode == HCI_EN_CMD_WRITING) || (RetCode == HCI_EN_CMD_WAIT) );
+
+            if( RetCode != HCI_EN_CMD_READY )  {
+                pAC->AsfData.Hci.Status = HCI_EN_CMD_IDLE;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Data not confirmed RetCode:0x%x\n", RetCode ));
+            }
+        }  //  if( wait...
+        else  {
+            RetCode = AsfHciGetState( pAC );
+            if( RetCode == HCI_EN_CMD_ERROR )  {
+                pAC->AsfData.Hci.Status = HCI_EN_CMD_IDLE;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Data not confirmed RetCode:0x%x\n", RetCode ));
+            }
+        }
+        if( Retry > 0 )
+            Retry--;
+        else
+            break;
+    } while ( Wait && (RetCode != HCI_EN_CMD_READY) );
+
+    if( RetCode == HCI_EN_CMD_READY )  {
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Data successfully conveyed\n"));
+    }
+
+    return( RetCode );
+}
+
+/*****************************************************************************
+*
+* AsfHciSendMessage
+*
+* Description:
+*
+* Returns:
+*
+*/
+SK_U8    AsfHciSendMessage(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   *message,
+SK_U8   length,
+SK_U8   ExpectResponse,
+SK_U8   Wait )  {
+    SK_U8       RetCode;
+    SK_U8       i;
+    SK_EVPARA   EventParam;
+
+    RetCode = 0;
+
+    if( length > ASF_HCI_TRA_BUF_SIZE )
+        return( RetCode );
+
+    if( pAC->AsfData.Hci.Status == HCI_EN_CMD_IDLE )
+    {
+        // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Send Message\n" ));
+
+        SK_OUT32( IoC, ASF_HCI_CMDREG, (SK_U32) 0 );
+        SK_OUT32( IoC, ASF_HCI_DATAREG, (SK_U32) 0 );
+        for( i=0; i<length; i++ )
+            pAC->AsfData.Hci.TransmitBuf[i] = message[i];
+        pAC->AsfData.Hci.SendLength = length;
+        if( ExpectResponse )
+            pAC->AsfData.Hci.ExpectResponse = 1;
+        else
+            pAC->AsfData.Hci.ExpectResponse = 0;
+        pAC->AsfData.Hci.Status = HCI_EN_CMD_WRITING;
+        pAC->AsfData.Hci.OldCmdReg = 0;
+        pAC->AsfData.Hci.SendIndex = 0;
+        pAC->AsfData.Hci.Cycles = 0;
+        pAC->AsfData.Hci.Time = SkOsGetTime( pAC );
+        RetCode = 1;  //  successfull
+    }
+    else
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Send Message -> Not Idle\n" ));
+
+
+    if( !Wait )  {
+        // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    Send Message -> Start Timer\n" ));
+        SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+        SkTimerStart(pAC, IoC, &pAC->AsfData.Hci.AsfTimerHci,
+                     10000, SKGE_ASF, SK_ASF_EVT_TIMER_HCI_EXPIRED,
+                     EventParam);
+    }
+
+    return( RetCode );
+}
+
+
+void AsfWatchCpu(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U32  par )  {
+
+#ifdef _XXX_
+SK_U32  FwAlive, LastFetch;
+
+    SK_IN32( IoC, B28_Y2_DATA_REG_4, &FwAlive );
+    SK_IN32( IoC, 0x64, &LastFetch );
+    if( LastFetch < 0x20000 )
+        pAC->AsfData.FwError++;
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("(%d) AsfWatchCpu: FwAlive:0x%x LastFetch:0x%x Err:%d\n",
+                                                   par, FwAlive , LastFetch, pAC->AsfData.FwError ));
+#endif // _XXX_
+
+    return;
+}
+
+
+void AsfEnable(
+SK_AC   *pAC,
+SK_IOC  IoC )  {
+    SK_U32 TmpVal32;
+
+    SK_IN32(IoC, B0_CTST, &TmpVal32);
+    TmpVal32 &= ~0x00003000;    // clear bit13, bit12
+    TmpVal32 |= 0x00002000;             // set bit13
+    SK_OUT32(IoC, B0_CTST, TmpVal32);
+    SK_OUT32(IoC, B0_CTST, Y2_ASF_ENABLE);
+
+    pAC->GIni.GIAsfEnabled = SK_TRUE;   // update asf flag for common modules
+}
+
+void AsfDisable(
+SK_AC   *pAC,
+SK_IOC  IoC )  {
+    SK_U32 TmpVal32;
+
+    SK_IN32(IoC, B0_CTST, &TmpVal32);
+    TmpVal32 &= ~0x00003000;    // clear bit13, bit12
+    TmpVal32 |= 0x00001000;             // set bit13
+    SK_OUT32(IoC, B0_CTST, TmpVal32);
+    SK_OUT32(IoC, B0_CTST, Y2_ASF_DISABLE);
+
+    pAC->GIni.GIAsfEnabled = SK_FALSE;  // update asf flag for common modules
+}
+
+
+
+/*****************************************************************************
+*
+* AsfWriteIpmiPattern
+*
+* Description:  write all 3 pattern for IPMI to pattern ram
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:      YLCI_SUCCESS
+*               YLCI_ERROR
+*
+*/
+
+SK_I8 AsfWriteIpmiPattern(
+    SK_AC   *pAC,
+    SK_IOC  IoC,
+    SK_U8   port)
+{
+    SK_I8   RetVal;
+    SK_U8   i, j;
+    SK_U32  idx;
+    SK_U32  PattRamCluster[ASF_YEC_PATTRAM_CLUSTER_WORDS];
+    SK_U8   PattSrcByte[2];     // 2 pattern bytes to read/write in one cluster
+    SK_U32  TmpVal32;
+    SK_U32  mask;
+    SK_U8   pattern_no;
+
+    RetVal = 1;     // success
+
+    if (RetVal == 1) {
+
+        for (i = 0; (i < ASF_YEC_PATTRAM_CLUSTER_SIZE) && (RetVal == 1); i++) {
+            // pattern ram is organized into cluster (i is cluster index)
+            // _after_ writing a whole cluster (= 128bit), the pattern will be written into ram!
+
+            // read a cluster
+            for (j=0; j < ASF_YEC_PATTRAM_CLUSTER_WORDS; j++) {
+                PattRamCluster[j] = 0;
+            }
+
+            //-----------------------
+            // read source pattern 6
+            //-----------------------
+            pattern_no = 6;
+            for (j=0; j < 2; j++) {
+                // we have 2 pattern bytes to read/write for one cluster
+                // i is cluster index
+                // j is byte index
+                idx = 2*i+j;
+                if (idx < 40) {
+                    // we can read from our pattern pointer
+                    PattSrcByte[j] = RMCP_FRAME_PATTERN[idx];
+
+                    // read from our enable mask pointer
+                    TmpVal32 = RMCP_PATTERN_MASK[idx/8];
+                    mask     = 0x01 << (idx % 8);
+
+                    if ( (TmpVal32 & mask) != 0 ) {
+                        // enable byte
+                        PattRamCluster[j*2+1] |= (BIT_24 << pattern_no);
+                    }
+                    else {
+                        // disable byte
+                        PattRamCluster[j*2+1] &= ~(BIT_24 << pattern_no);
+                    }
+                }
+                else {
+                    // fill up with zeros
+                    PattSrcByte[j] = 0;
+                    // disable byte
+                    PattRamCluster[j*2+1] &= ~(BIT_24 << pattern_no);
+                }
+            }
+
+            // upper words are interesting here
+            idx = 1;
+
+            // first byte
+            mask = 0x000000ff;
+            j    = pattern_no % 4;
+            PattRamCluster[idx] &= ~(mask << 8 * j);    // delete byte in word
+            mask = PattSrcByte[0];
+            PattRamCluster[idx] |= (mask << 8 * j);     // write pattern byte
+
+            // second byte
+            mask = 0x000000ff;
+            PattRamCluster[idx+2] &= ~(mask << 8 * j);  // delete byte in word
+            mask = PattSrcByte[1];
+            PattRamCluster[idx+2] |= (mask << 8 * j);   // write pattern byte
+
+            //-----------------------
+            // read source pattern 5
+            //-----------------------
+            pattern_no = 5;
+            for (j=0; j < 2; j++) {
+                // we have 2 pattern bytes to read/write for one cluster
+                // i is cluster index
+                // j is byte index
+                idx = 2*i+j;
+                if (idx < 40) {
+                    // we can read from our pattern pointer
+                    PattSrcByte[j] = ARP_FRAME_PATTERN[idx];
+
+                    // read from our enable mask pointer
+                    TmpVal32 = ARP_PATTERN_MASK[idx/8];
+                    mask     = 0x01 << (idx % 8);
+
+                    if ( (TmpVal32 & mask) != 0 ) {
+                        // enable byte
+                        PattRamCluster[j*2+1] |= (BIT_24 << pattern_no);
+                    }
+                    else {
+                        // disable byte
+                        PattRamCluster[j*2+1] &= ~(BIT_24 << pattern_no);
+                    }
+                }
+                else {
+                    // fill up with zeros
+                    PattSrcByte[j] = 0;
+                    // disable byte
+                    PattRamCluster[j*2+1] &= ~(BIT_24 << pattern_no);
+                }
+            }
+
+            // upper words are interesting here
+            idx = 1;
+
+            // first byte
+            mask = 0x000000ff;
+            j    = pattern_no % 4;
+            PattRamCluster[idx] &= ~(mask << 8 * j);    // delete byte in word
+            mask = PattSrcByte[0];
+            PattRamCluster[idx] |= (mask << 8 * j);     // write pattern byte
+
+            // second byte
+            mask = 0x000000ff;
+            PattRamCluster[idx+2] &= ~(mask << 8 * j);  // delete byte in word
+            mask = PattSrcByte[1];
+            PattRamCluster[idx+2] |= (mask << 8 * j);   // write pattern byte
+
+            //-----------------------
+            // read source pattern 4
+            //-----------------------
+            pattern_no = 4;
+            for (j=0; j < 2; j++) {
+                // we have 2 pattern bytes to read/write for one cluster
+                // i is cluster index
+                // j is byte index
+                idx = 2*i+j;
+                if (idx < 40) {
+                    // we can read from our pattern pointer
+                    PattSrcByte[j] = RSP_FRAME_PATTERN[idx];
+
+                    // read from our enable mask pointer
+                    TmpVal32 = RSP_PATTERN_MASK[idx/8];
+                    mask     = 0x01 << (idx % 8);
+
+                    if ( (TmpVal32 & mask) != 0 ) {
+                        // enable byte
+                        PattRamCluster[j*2+1] |= (BIT_24 << pattern_no);
+                    }
+                    else {
+                        // disable byte
+                        PattRamCluster[j*2+1] &= ~(BIT_24 << pattern_no);
+                    }
+                }
+                else {
+                    // fill up with zeros
+                    PattSrcByte[j] = 0;
+                    // disable byte
+                    PattRamCluster[j*2+1] &= ~(BIT_24 << pattern_no);
+                }
+            }
+
+            // upper words are interesting here
+            idx = 1;
+
+            // first byte
+            mask = 0x000000ff;
+            j    = pattern_no % 4;
+            PattRamCluster[idx] &= ~(mask << 8 * j);    // delete byte in word
+            mask = PattSrcByte[0];
+            PattRamCluster[idx] |= (mask << 8 * j);     // write pattern byte
+
+            // second byte
+            mask = 0x000000ff;
+            PattRamCluster[idx+2] &= ~(mask << 8 * j);  // delete byte in word
+            mask = PattSrcByte[1];
+            PattRamCluster[idx+2] |= (mask << 8 * j);   // write pattern byte
+
+            // write a cluster
+            // after writing the last cluster word, the hardware will trigger writing all cluster words
+            for (j=0; j < ASF_YEC_PATTRAM_CLUSTER_WORDS; j++) {
+                idx = ASF_YEC_PATTRAM_CLUSTER_WORDS*ASF_YEC_PATTRAM_CLUSTER_BYTES*i + ASF_YEC_PATTRAM_CLUSTER_BYTES*j;
+
+                if( port == 0 )  {
+		    SK_OUT32( IoC, WOL_PATT_RAM_1+idx, PattRamCluster[j] );
+		}
+                else  {
+                    SK_OUT32( IoC, WOL_PATT_RAM_2+idx, PattRamCluster[j] );
+                }
+            }
+        }
+    }
+
+    return (RetVal);
+}
+
+void AsfSetUpPattern(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   port )  {
+
+    SK_U8   TmpVal8;
+    SK_U16  TmpVal16;
+    SK_U32  TmpVal32;
+
+    if( port > 1 )
+        return;
+
+    switch (pAC->AsfData.OpMode) {
+        case SK_GEASF_MODE_ASF:
+            // see "problems.txt" note #344
+            // set MAC Rx fifo flush threshold register
+            // (please refer also to note #yuk_hw01)
+            SK_IN32(IoC, ASF_YEC_MAC_FIFO_FLUSHTHRES1+(port*0x80), &TmpVal32);
+            TmpVal32 &= ~0x7f;  // delete bit 6:0
+            TmpVal32 |= ASF_YLCI_MACRXFIFOTHRES;
+            SK_OUT32(IoC, ASF_YEC_MAC_FIFO_FLUSHTHRES1+(port*0x80), TmpVal32);
+
+            // disable Wake Up Frame Unit before write to pattern ram
+            SK_IN16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), &TmpVal16);
+            TmpVal16 &= ~0x03;   // clear bit 0, bit1
+            TmpVal16 |=  0x01;   // set bit 0
+            SK_OUT16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), TmpVal16);
+
+            //  Set new pattern for ASF
+            //  This will override the driver WOL pattern, but the driver is going to set
+            //  the WOL pattern again before it "shut down" or "stand by"
+            if( pAC->AsfData.Mib.RspEnable )  {
+                // security is on - write ARP and RSP pattern
+                AsfWritePatternRam(pAC, IoC, port, 5, 6, 40, 40,
+                                   ARP_PATTERN_MASK, ARP_FRAME_PATTERN,
+                                   RSP_PATTERN_MASK, RSP_FRAME_PATTERN);
+            }
+            else  {
+                // security is off - write ARP and RMCP pattern
+                AsfWritePatternRam(pAC, IoC, port, 5, 6, 40, 40,
+                                   ARP_PATTERN_MASK, ARP_FRAME_PATTERN,
+                                   RMCP_PATTERN_MASK, RMCP_FRAME_PATTERN);
+            }
+
+            // set pattern length register
+            SK_IN32(IoC, ASF_YEC_PATTERN_LENGTH_R1_H+(port*0x80), &TmpVal32);
+            TmpVal32 &= ~(0x0000007f << 8*(5%4));
+            TmpVal32 |= (40-1) << 8*(5%4);     // write length-1 to pattern length register
+            SK_OUT32(IoC, ASF_YEC_PATTERN_LENGTH_R1_H+(port*0x80), TmpVal32);
+            // set pattern length register
+            SK_IN32(IoC, ASF_YEC_PATTERN_LENGTH_R1_H+(port*0x80), &TmpVal32);
+            TmpVal32 &= ~(0x0000007f << 8*(6%4));
+            TmpVal32 |= (40-1) << 8*(6%4);     // write length-1 to pattern length register
+            SK_OUT32(IoC, ASF_YEC_PATTERN_LENGTH_R1_H+(port*0x80), TmpVal32);
+
+            // set ASF match enable register (incomming packets will redirect to ASF queue)
+            SK_IN8(IoC, ASF_YEC_PATTERN_MATCHENA1+(port*0x80), &TmpVal8);
+            TmpVal8 |= 0x40;    // pattern 6 enable
+            SK_OUT8(IoC, ASF_YEC_PATTERN_MATCHENA1+(port*0x80), TmpVal8);
+
+            // enable pattern pattno
+            SK_IN8(IoC, ASF_YEC_PATTERN_ENA1+(port*0x80), &TmpVal8);
+            TmpVal8 |= 0x40;    // pattern 6 enable
+            SK_OUT8(IoC, ASF_YEC_PATTERN_ENA1+(port*0x80), TmpVal8);
+
+            // enable Wake Up Frame Unit
+            SK_IN16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), &TmpVal16);
+            TmpVal16 &= ~0x03;   // delete bit 0 and 1
+            TmpVal16 |= 0x02;   // set bit 1
+            SK_OUT16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), TmpVal16);
+            break;
+        case SK_GEASF_MODE_IPMI:
+            // disable Wake Up Frame Unit before write to pattern ram
+            SK_IN16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), &TmpVal16);
+            TmpVal16 &= ~0x03;   // clear bit 0, bit1
+            TmpVal16 |= 0x01;   // set bit 0
+            SK_OUT16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), TmpVal16);
+
+            // write all 3 pattern (RMCP, RSP and ARP)
+            AsfWriteIpmiPattern(pAC, IoC, port);
+
+            // set pattern length register
+            SK_IN32(IoC, ASF_YEC_PATTERN_LENGTH_R1_H+(port*0x80), &TmpVal32);
+            TmpVal32 &= 0xff000000;     // delete length for pattern 4, 5 and 6
+            TmpVal32 |= 0x00272727;     // set new length for pattern 4, 5 and 6
+            SK_OUT32(IoC, ASF_YEC_PATTERN_LENGTH_R1_H+(port*0x80), TmpVal32);
+
+            // set ASF match enable register (incomming packets will redirect to ASF queue)
+            SK_IN8(IoC, ASF_YEC_PATTERN_MATCHENA1+(port*0x80), &TmpVal8);
+            TmpVal8 = 0x50;    // enable pattern 4 and 6 (do not enable arp pattern)
+            SK_OUT8(IoC, ASF_YEC_PATTERN_MATCHENA1+(port*0x80), TmpVal8);
+
+            // enable pattern pattno
+            SK_IN8(IoC, ASF_YEC_PATTERN_ENA1+(port*0x80), &TmpVal8);
+            TmpVal8 = 0x50;    // enable pattern 4 and 6 (do not enable arp pattern)
+            SK_OUT8(IoC, ASF_YEC_PATTERN_ENA1+(port*0x80), TmpVal8);
+
+            // enable Wake Up Frame Unit
+            SK_IN16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), &TmpVal16);
+            TmpVal16 &= ~0x03;   // delete bit 0 and 1
+            TmpVal16 |= 0x02;   // set bit 1
+            SK_OUT16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), TmpVal16);
+            break;
+
+        case SK_GEASF_MODE_DASH:
+	    //  currently only supported on Yukon Extreme
+	    if( pAC->AsfData.ChipMode != SK_GEASF_CHIP_EX )
+	      break;
+			
+            // disable Wake Up Frame Unit before write to pattern ram
+            SK_IN16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), &TmpVal16);
+            TmpVal16 &= ~0x03;   // clear bit 0, bit1
+            TmpVal16 |=  0x01;   // set bit 0
+            SK_OUT16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), TmpVal16);
+
+            // write all 3 pattern 
+	    AsfWritePatternRamEx(pAC, IoC, port, ASF_DASH_PATTERN_NUM_ARP,  40, ARP_PATTERN_MASK, ARP_FRAME_PATTERN );
+	    AsfWritePatternRamEx(pAC, IoC, port, ASF_DASH_PATTERN_NUM_ICMP, 40, ICMP_PATTERN_MASK, ICMP_FRAME_PATTERN );
+	    AsfWritePatternRamEx(pAC, IoC, port, ASF_DASH_PATTERN_NUM_SNMP, 40, SNMP_PATTERN_MASK, SNMP_FRAME_PATTERN );
+	    //AsfWritePatternRamEx(pAC, IoC, port, ASF_DASH_PATTERN_NUM_RMCP, 40, RMCP_PATTERN_MASK, RMCP_FRAME_PATTERN );
+	    //AsfWritePatternRamEx(pAC, IoC, port, ASF_DASH_PATTERN_NUM_RSP,  40, RSP_PATTERN_MASK, RSP_FRAME_PATTERN );
+	    //AsfWritePatternRamEx(pAC, IoC, port, ASF_DASH_PATTERN_NUM_TCP1, 40, TCP_PATTERN_MASK, TCP_FRAME_PATTERN );
+	    //AsfWritePatternRamEx(pAC, IoC, port, ASF_DASH_PATTERN_NUM_TCP2, 40, TCP_PATTERN_MASK, TCP_FRAME_PATTERN );
+	    
+	    //YlciEnablePattern( pAC, IoC, port, ASF_DASH_PATTERN_NUM_RMCP );		
+	    //YlciEnablePattern( pAC, IoC, port, ASF_DASH_PATTERN_NUM_RSP );		
+	    //YlciEnablePattern( pAC, IoC, port, ASF_DASH_PATTERN_NUM_TCP1 );		
+	    //YlciEnablePattern( pAC, IoC, port, ASF_DASH_PATTERN_NUM_TCP2 );		
+			
+            // enable Wake Up Frame Unit
+            SK_IN16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), &TmpVal16);
+            TmpVal16 &= ~0x03;   // delete bit 0 and 1
+            TmpVal16 |=  0x02;   // set bit 1
+            SK_OUT16(IoC, ASF_YEC_PATTERN_CTRL1+(port*0x80), TmpVal16);
+            break;
+			
+        default:
+            break;
+    }
+
+    return;
+}
+
+/*****************************************************************************
+*
+* AsfWritePatternRam
+*
+* Description:  write to pattern ram
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:      1:  SUCCESS
+*               0:  YLCI_ERROR
+*
+*/
+
+SK_I8 AsfWritePatternRam(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   Port,                       /* for future use   */
+SK_U8   PatternId1,                  /* 0..6             */
+SK_U8   PatternId2,                  /* 0..6             */
+SK_U8   Length1,                     /* 1..128 bytes     */
+SK_U8   Length2,                     /* 1..128 bytes     */
+SK_U8   *pMask1,
+SK_U8   *pPattern1,
+SK_U8   *pMask2,
+SK_U8   *pPattern2)
+
+{
+    SK_U8   i, j;
+    SK_I8   RetVal;
+    SK_U32  idx;
+    SK_U32  PattRamCluster[ASF_YEC_PATTRAM_CLUSTER_WORDS];
+    SK_U8   PattSrcByte1[2];     // 2 pattern bytes to read/write in one cluster
+    SK_U8   PattSrcByte2[2];     // 2 pattern bytes to read/write in one cluster
+    SK_U32  TmpVal32;
+    SK_U32  mask;
+
+    RetVal = 1;  //  success
+
+    // pattern size up to 128 bytes, pattern id can be 0...6
+    if ( (Length1 <= SK_POW_PATTERN_LENGTH) && (PatternId1 < SK_NUM_WOL_PATTERN) ) {
+
+        for (i = 0; (i < ASF_YEC_PATTRAM_CLUSTER_SIZE) && (RetVal == 1); i++) {
+            // pattern ram is organized into cluster (i is cluster index)
+            // _after_ writing a whole cluster (= 128bit), the pattern will be written into ram!
+
+            // read a cluster
+            for (j=0; j < ASF_YEC_PATTRAM_CLUSTER_WORDS; j++) {
+                PattRamCluster[j] = 0;
+            }
+            // read source pattern 1
+            for (j=0; j < 2; j++) {
+                // we have 2 pattern bytes to read/write for one cluster
+                // i is cluster index
+                // j is byte index
+                idx = 2*i+j;
+                if ( idx < Length1 ) {
+                    // we can read from our pattern pointer
+                    PattSrcByte1[j] = pPattern1[idx];
+
+                    // read from our enable mask pointer
+                    TmpVal32 = pMask1[idx/8];
+                    mask     = 0x01 << (idx % 8);
+
+                    if ( (TmpVal32 & mask) != 0 ) {
+                        // enable byte
+                        PattRamCluster[j*2+1] |= (BIT_24 << PatternId1);
+                    }
+                    else {
+                        // disable byte
+                        PattRamCluster[j*2+1] &= ~(BIT_24 << PatternId1);
+                    }
+                }
+                else {
+                    // fill up with zeros
+                    PattSrcByte1[j] = 0;
+                    // disable byte
+                    PattRamCluster[j*2+1] &= ~(BIT_24 << PatternId1);
+                }
+            }
+            // read source pattern 2
+            for (j=0; j < 2; j++) {
+                // we have 2 pattern bytes to read/write for one cluster
+                // i is cluster index
+                // j is byte index
+                idx = 2*i+j;
+                if ( idx < Length2 ) {
+                    // we can read from our pattern pointer
+                    PattSrcByte2[j] = pPattern2[idx];
+
+                    // read from our enable mask pointer
+                    TmpVal32 = pMask2[idx/8];
+                    mask     = 0x01 << (idx % 8);
+
+                    if ( (TmpVal32 & mask) != 0 ) {
+                        // enable byte
+                        PattRamCluster[j*2+1] |= (BIT_24 << PatternId2);
+                    }
+                    else {
+                        // disable byte
+                        PattRamCluster[j*2+1] &= ~(BIT_24 << PatternId2);
+                    }
+                }
+                else {
+                    // fill up with zeros
+                    PattSrcByte2[j] = 0;
+                    // disable byte
+                    PattRamCluster[j*2+1] &= ~(BIT_24 << PatternId2);
+                }
+            }
+            // set our pattern into PattRamCluster[]
+            if (PatternId1 >= 4) {
+                // upper words are interesting here
+                idx = 1;
+            }
+            else {
+                // lower words are interesting here
+                idx = 0;
+            }
+            // first byte
+            mask = 0x000000ff;
+            j    = PatternId1 % 4;
+            PattRamCluster[idx] &= ~(mask << 8 * j);    // delete byte in word
+            mask = PattSrcByte1[0];
+            PattRamCluster[idx] |= (mask << 8 * j);     // write pattern byte
+            // second byte
+            mask = 0x000000ff;
+            PattRamCluster[idx+2] &= ~(mask << 8 * j);  // delete byte in word
+            mask = PattSrcByte1[1];
+            PattRamCluster[idx+2] |= (mask << 8 * j);   // write pattern byte
+
+            // set our pattern into PattRamCluster[]
+            if (PatternId2 >= 4) {
+                // upper words are interesting here
+                idx = 1;
+            }
+            else {
+                // lower words are interesting here
+                idx = 0;
+            }
+            // first byte
+            mask = 0x000000ff;
+            j    = PatternId2 % 4;
+            PattRamCluster[idx] &= ~(mask << 8 * j);    // delete byte in word
+            mask = PattSrcByte2[0];
+            PattRamCluster[idx] |= (mask << 8 * j);     // write pattern byte
+            // second byte
+            mask = 0x000000ff;
+            PattRamCluster[idx+2] &= ~(mask << 8 * j);  // delete byte in word
+            mask = PattSrcByte2[1];
+            PattRamCluster[idx+2] |= (mask << 8 * j);   // write pattern byte
+
+            // write a cluster
+            // after writing the last cluster word, the hardware will trigger writing all cluster words
+            for (j=0; j < ASF_YEC_PATTRAM_CLUSTER_WORDS; j++) {
+                idx = ASF_YEC_PATTRAM_CLUSTER_WORDS*ASF_YEC_PATTRAM_CLUSTER_BYTES*i + ASF_YEC_PATTRAM_CLUSTER_BYTES*j;
+                if( Port == 0 )  {
+                    SK_OUT32( IoC, WOL_PATT_RAM_1+idx, PattRamCluster[j] );
+                }
+                else  {
+                    SK_OUT32( IoC, WOL_PATT_RAM_2+idx, PattRamCluster[j] );
+                }
+            }
+        }
+    }
+    else {
+        RetVal = 0;  //  error
+    }
+
+    return(RetVal);
+}
+
+/*****************************************************************************
+*
+* YlciWritePatternRamEx
+*
+* Description:  write to pattern ram
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:      1:  SUCCESS
+*               0:  YLCI_ERROR
+*
+*/
+
+// #ifdef CHIP_ID_YUKON_EX		
+SK_I8 AsfWritePatternRamEx(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   Port,                        /* for future use   */
+SK_U8   PatternId ,                  /* 0..9             */
+SK_U8   Length ,                     /* 1..128 bytes     */
+SK_U8   *pMask ,
+SK_U8   *pPattern )
+
+{
+    SK_U8   i, j;
+    SK_I8   RetVal;
+    SK_U32  idx;
+    SK_U32  PattRamCluster[ASF_YEC_PATTRAM_CLUSTER_WORDS];
+    SK_U8   PattSrcByte[2];     // 2 pattern bytes to read/write in one cluster
+    SK_U32  TmpVal32;
+    SK_U32  mask;
+	SK_U8   TmpPatternId;
+	SK_U8	bank;
+	SK_U16  AsfYexPatternLengthReg;
+	
+    RetVal = 1;  //  success
+
+    // pattern size up to 128 bytes, pattern id can be 0...6
+    if ( Length <= SK_POW_PATTERN_LENGTH ) {
+    	if ( PatternId < SK_NUM_WOL_PATTERN_EX ) {
+			
+			if( PatternId < SK_NUM_WOL_PATTERN )  {
+				TmpPatternId = PatternId;
+				bank = 0;
+			}
+			else  {
+				TmpPatternId = PatternId - SK_NUM_WOL_PATTERN;
+				bank = 1;
+			}
+
+			//  select pattern bank
+            SK_IN32( IoC, PAT_CSR, &TmpVal32 );
+			if( bank == 0 )
+				TmpVal32 &= ~(PAT_CSR_BSEL);
+			else
+				TmpVal32 |= PAT_CSR_BSEL;
+            SK_OUT32( IoC, PAT_CSR, TmpVal32 );
+			
+	        for (i = 0; (i < ASF_YEC_PATTRAM_CLUSTER_SIZE) && (RetVal == 1); i++) {
+	            // pattern ram is organized into cluster (i is cluster index)
+	            // _after_ writing a whole cluster (= 128bit), the pattern will be written into ram!
+
+	            // read a cluster
+	            for (j=0; j < ASF_YEC_PATTRAM_CLUSTER_WORDS; j++) {
+	                idx = ASF_YEC_PATTRAM_CLUSTER_WORDS*ASF_YEC_PATTRAM_CLUSTER_BYTES*i + ASF_YEC_PATTRAM_CLUSTER_BYTES*j;
+	                if( Port == 0 )  {
+	                    SK_IN32( IoC, WOL_PATT_RAM_1+idx, &PattRamCluster[j] );
+	                }
+	                else  {
+	                    SK_IN32( IoC, WOL_PATT_RAM_2+idx, &PattRamCluster[j] );
+	                }
+	            }
+	            // read source pattern 
+	            for (j=0; j < 2; j++) {
+	                // we have 2 pattern bytes to read/write for one cluster
+	                // i is cluster index
+	                // j is byte index
+	                idx = 2*i+j;
+	                if ( idx < Length ) {
+	                    // we can read from our pattern pointer
+	                    PattSrcByte[j] = pPattern[idx];
+
+	                    // read from our enable mask pointer
+	                    TmpVal32 = pMask[idx/8];
+	                    mask     = 0x01 << (idx % 8);
+
+	                    if ( (TmpVal32 & mask) != 0 ) {
+	                        // enable byte
+	                        PattRamCluster[j*2+1] |= (BIT_24 << TmpPatternId);
+	                    }
+	                    else {
+	                        // disable byte
+	                        PattRamCluster[j*2+1] &= ~(BIT_24 << TmpPatternId);
+	                    }
+	                }
+	                else {
+	                    // fill up with zeros
+	                    PattSrcByte[j] = 0;
+	                    // disable byte
+	                    PattRamCluster[j*2+1] &= ~(BIT_24 << TmpPatternId);
+	                }
+	            }
+	            // set our pattern into PattRamCluster[]
+	            if (TmpPatternId >= 4) {
+	                // upper words are interesting here
+	                idx = 1;
+	            }
+	            else {
+	                // lower words are interesting here
+	                idx = 0;
+	            }
+	            // first byte
+	            mask = 0x000000ff;
+	            j    = TmpPatternId % 4;
+	            PattRamCluster[idx] &= ~(mask << 8 * j);    // delete byte in word
+	            mask = PattSrcByte[0];
+	            PattRamCluster[idx] |= (mask << 8 * j);     // write pattern byte
+	            // second byte
+	            mask = 0x000000ff;
+	            PattRamCluster[idx+2] &= ~(mask << 8 * j);  // delete byte in word
+	            mask = PattSrcByte[1];
+	            PattRamCluster[idx+2] |= (mask << 8 * j);   // write pattern byte
+
+	            // write a cluster
+	            // after writing the last cluster word, the hardware will trigger writing all cluster words
+	            for (j=0; j < ASF_YEC_PATTRAM_CLUSTER_WORDS; j++) {
+	                idx = ASF_YEC_PATTRAM_CLUSTER_WORDS*ASF_YEC_PATTRAM_CLUSTER_BYTES*i + ASF_YEC_PATTRAM_CLUSTER_BYTES*j;
+	                if( Port == 0 )  {
+	                    SK_OUT32( IoC, WOL_PATT_RAM_1+idx, PattRamCluster[j] );
+	                }
+	                else  {
+	                    SK_OUT32( IoC, WOL_PATT_RAM_2+idx, PattRamCluster[j] );
+	                }
+	            }
+	        }  //  	for (i = 0; (i < ASF_YEC_PATTRAM_CLUSTER_SIZE) && (RetVal == 1); i++)
+	        
+			//  Set pattern length register
+			AsfYexPatternLengthReg = ASF_YEX_PATTERN_LENGTH_R1_L+(Port*0x80)+( (PatternId/4)*sizeof(SK_U32) );
+		    SK_IN32(IoC, AsfYexPatternLengthReg, &TmpVal32);		
+		    TmpVal32 &= ~(0x0000007f << 8*(PatternId%4));			
+		    TmpVal32 |= (Length-1) << 8*(PatternId%4);     // write length-1 to pattern length register
+		    SK_OUT32(IoC, AsfYexPatternLengthReg, TmpVal32);
+			
+    	}  //  if ( PatternId < SK_NUM_WOL_PATTERN_EX ) 
+		else  {
+	        RetVal = 0;  //  error
+		}
+    }  //   if ( Length1 <= SK_POW_PATTERN_LENGTH )
+    else {
+        RetVal = 0;  //  error
+    }
+    return(RetVal);
+}
+// #endif //  CHIP_ID_YUKON_EX	
+
+SK_I8 YlciEnablePattern (
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   port,
+SK_U8   pattno )
+{
+
+
+    if (port > 1) {
+        return (1);
+    }
+    
+    if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )  {
+      SK_U16   val16;
+      
+      if( pAC->AsfData.OpMode != SK_GEASF_MODE_DASH )
+	pattno += 6;
+      
+      // set ASF match enable register (incomming packets will redirect to ASF queue)
+      SK_IN16(IoC, ASF_YEX_PATTERN_MATCHENA1+(port*0x80), &val16);
+      val16 |= (0x01 << pattno);
+      SK_OUT16(IoC, ASF_YEX_PATTERN_MATCHENA1+(port*0x80), val16);
+      
+      // enable pattern pattno
+      SK_IN16(IoC, ASF_YEX_PATTERN_ENA1+(port*0x80), &val16);
+      val16 |= (0x01 << pattno);
+      SK_OUT16(IoC, ASF_YEX_PATTERN_ENA1+(port*0x80), val16);
+    }
+    else  {
+      SK_U8   val8;
+      pattno += 4;
+      // set ASF match enable register (incomming packets will redirect to ASF queue)
+      SK_IN8(IoC, ASF_YEC_PATTERN_MATCHENA1+(port*0x80), &val8);
+      val8 |= (0x01 << pattno);
+      SK_OUT8(IoC, ASF_YEC_PATTERN_MATCHENA1+(port*0x80), val8);
+      
+      // enable pattern pattno
+      SK_IN8(IoC, ASF_YEC_PATTERN_ENA1+(port*0x80), &val8);
+      val8 |= (0x01 << pattno);
+      SK_OUT8(IoC, ASF_YEC_PATTERN_ENA1+(port*0x80), val8);
+    }
+
+    return ( 1 );
+}
+
+// Called YlciDisablePatternType in Windows Code
+SK_I8 YlciDisablePattern (
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   port,
+SK_U8   pattno )
+{
+    if (port > 1) {
+        return (1);
+    }
+    if( pAC->AsfData.ChipMode == SK_GEASF_CHIP_EX )  {
+      SK_U16   val16;
+      
+      if( pAC->AsfData.OpMode != SK_GEASF_MODE_DASH )
+	pattno += 6;
+      
+      // set ASF match disable register (incomming packets will redirect to ASF queue)
+      SK_IN16(IoC, ASF_YEX_PATTERN_MATCHENA1+(port*0x80), &val16);
+      val16 &= ~(0x01 << pattno);
+      SK_OUT16(IoC, ASF_YEX_PATTERN_MATCHENA1+(port*0x80), val16);
+      
+      // disable pattern pattno
+      SK_IN16(IoC, ASF_YEX_PATTERN_ENA1+(port*0x80), &val16);
+	    val16 &= ~(0x01 << pattno);
+	    SK_OUT16(IoC, ASF_YEX_PATTERN_ENA1+(port*0x80), val16);
+    }
+    else  {
+      SK_U8   val8;
+      pattno += 4;
+      // set ASF match disable register (incomming packets will redirect to ASF queue)
+      SK_IN8(IoC, ASF_YEC_PATTERN_MATCHENA1+(port*0x80), &val8);
+      val8 &= ~(0x01 << pattno);
+      SK_OUT8(IoC, ASF_YEC_PATTERN_MATCHENA1+(port*0x80), val8);
+      
+      // disable pattern pattno
+      SK_IN8(IoC, ASF_YEC_PATTERN_ENA1+(port*0x80), &val8);
+      val8 &= ~(0x01 << pattno);
+      SK_OUT8(IoC, ASF_YEC_PATTERN_ENA1+(port*0x80), val8);
+    }	
+    return ( 1 );
+}
+
+#if (0)
+
+/*****************************************************************************
+*
+* SkAsfAcpi
+*
+* Description:  Searches for the Root System Description Pointer "RSD PTR"
+*               within the range of 0xE0000 .. 0xFFFFF (ACPI Spec 5.2.4.1).
+*               The "RSD PTR" is the entry point of the ACPI data base. It
+*               contains pointer to the "RSDT" (32bit) and "XSDT" (64bit)
+*               tables, which in turn contain lists of pointers that are
+*               pointing to ACPI sub tables e.g. "ASF!" .
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:       1: OK
+*                0: UNDEFINED
+*               <0: Error Codes
+*
+*/
+SK_I8 SkAsfAcpi(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8 *pImage )  {
+    HANDLE              SectionHandle;
+    NTSTATUS            NtRet;
+    unsigned char       *pU8;
+    PVOID               BaseAddress;
+    ULONG               CommitSize;
+    ULONG               i;
+    LARGE_INTEGER       MaxSize;
+    LARGE_INTEGER       SectOffset;
+    SIZE_T              ViewSize;
+    SK_U32              RsdtAddr;
+    SK_U64              XsdtAddr;
+    SK_I8               AcpiState;
+    SK_I8               RetVal;
+    UNICODE_STRING      SectionName;
+    OBJECT_ATTRIBUTES   ObjAttrs;
+
+    WCHAR               const SectionNameConst[] = L"\\Device\\PhysicalMemory";
+
+    RsdtAddr = 0;
+    AcpiState = ASF_ACPI_STATE_OK;
+
+    //  Initialize object attributes
+    SectionName.Buffer =        (PWSTR)&SectionNameConst[0];
+    SectionName.Length =        wcslen(SectionNameConst) * sizeof(WCHAR);
+    SectionName.MaximumLength = SectionName.Length + sizeof(WCHAR);
+
+#if NDIS_VERSION > 50
+    // WinXP
+    InitializeObjectAttributes(
+                            &ObjAttrs,
+                            &SectionName,
+                            (OBJ_KERNEL_HANDLE | OBJ_FORCE_ACCESS_CHECK),
+                            (HANDLE)NULL,
+                            (PSECURITY_DESCRIPTOR)NULL
+                           );
+#else
+    // Win2k
+    InitializeObjectAttributes(
+                            &ObjAttrs,
+                            &SectionName,
+                            (OBJ_KERNEL_HANDLE),
+                            (HANDLE)NULL,
+                            (PSECURITY_DESCRIPTOR)NULL
+                           );
+#endif
+
+    //  Get a SectionHandle to the "\\Device\\PhysicalMemory" section
+    NtRet = ZwOpenSection( &SectionHandle,      //  OUT PHANDLE  SectionHandle
+                           SECTION_MAP_READ,    //  IN ACCESS_MASK  DesiredAccess,
+                           &ObjAttrs );         //  IN POBJECT_ATTRIBUTES  ObjectAttributes
+
+    if( NtRet == STATUS_SUCCESS )  {
+        BaseAddress = NULL;
+        SectOffset.QuadPart =   0xe0000;
+        CommitSize =            0x1ffff;
+        ViewSize =              0x1ffff;
+        NtRet = ZwMapViewOfSection( SectionHandle,          // IN HANDLE  SectionHandle
+                                    NtCurrentProcess(),     // IN HANDLE  ProcessHandle
+                                    &BaseAddress,           // IN OUT PVOID  *BaseAddress
+                                    0L,                     // IN ULONG  ZeroBits
+                                    CommitSize,             // IN ULONG  CommitSize,
+                                    &SectOffset,            // IN OUT PLARGE_INTEGER  SectionOffset  OPTIONAL,
+                                    &ViewSize,              // IN OUT PSIZE_T  ViewSize,
+                                    ViewShare,              // IN SECTION_INHERIT  InheritDisposition,
+                                    0,                      // IN ULONG  AllocationType,
+                                    PAGE_READONLY           // IN ULONG  Protect
+                                    );
+        if( NtRet == STATUS_SUCCESS )  {
+            //  Update ASF! table
+            //  Search for the "RSD PTR" signature
+            pU8 = ((unsigned char *) BaseAddress);
+            for( i=0; i<(0x1ffff-7); i++ ) {
+                if( (*(pU8 + 0 ) == 'R') && (*(pU8 + 1 ) == 'S') && (*(pU8 + 2 ) == 'D') && (*(pU8 + 3 ) == ' ') &&
+                    (*(pU8 + 4 ) == 'P') && (*(pU8 + 5 ) == 'T') && (*(pU8 + 6 ) == 'R')    )  {
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfAcpi -> RSD PTR found at 0x%x (phys)\n", 0xe0000+i ));
+                    //  Get Address of the Root System Description Table "RSDT"
+                    RsdtAddr = *( (SK_U32 *)(pU8 + 16) );
+                    if( RsdtAddr != 0 )  {
+                        //  32bit platform
+                        // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfAcpi -> RSDT (0x%x)\n", RsdtAddr));
+                        RetVal = SkAsfAcpiRsdt( pAC, IoC, pImage, SectionHandle, RsdtAddr );
+                        if( RetVal < ASF_ACPI_STATE_UNDEFINED )
+                            AcpiState = RetVal;
+                    }
+                    else  {
+                        //  64bit platform
+                        XsdtAddr = *( (SK_U64 *)(pU8 + 24) );
+                        // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfAcpi -> XSDT (0x%x)\n", XsdtAddr ));
+                        RetVal = SkAsfAcpiXsdt( pAC, IoC, pImage, SectionHandle, XsdtAddr );
+                        if( RetVal < ASF_ACPI_STATE_UNDEFINED )
+                            AcpiState = RetVal;
+                    }
+                    break;
+                }
+                else
+                    pU8++;
+            }
+            if( i >= (0x1ffff-7) )  {
+                AcpiState = ASF_ACPI_STATE_ERROR_NO_RSDPTR;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfAcpi -> *** Error: no RSD PTR found\n"));
+            }
+            //  Update GUID
+            //  Search for the "_UUID_" signature
+            pU8 = ((unsigned char *) BaseAddress);
+            for( i=0; i<(0x1ffff-7); i++ ) {
+                if( (*(pU8 + 0 ) == '_') && (*(pU8 + 1 ) == 'U') && (*(pU8 + 2 ) == 'U') && (*(pU8 + 3 ) == 'I') &&
+                    (*(pU8 + 4 ) == 'D') && (*(pU8 + 5 ) == '_')   )  {
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfAcpi -> _UUID_ found at 0x%x (phys)\n", 0xe0000+i ));
+//                    RetVal = SkAsfPatchGuid( pAC, IoC, pImage, (pU8+6) );
+                    RetVal = SkAsfPatchGuid( pAC, IoC, pImage, (pU8+9) );   // pw Bug Fix
+                    if( RetVal < ASF_ACPI_STATE_UNDEFINED )
+                        AcpiState = RetVal;
+                    break;
+                }
+                else
+                    pU8++;
+            }
+            if( i >= (0x1ffff-7) )  {
+                AcpiState = ASF_ACPI_STATE_ERROR_NO_RSDPTR;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfAcpi -> *** Error: no _UUID_ found\n"));
+            }
+
+            ZwUnmapViewOfSection( NtCurrentProcess(), BaseAddress );
+        }  //  if( NtRet == STATUS_SUCCESS )  {
+        ZwClose( SectionHandle );
+    }
+
+    return( AcpiState );
+}
+#endif
+
+#if (0)
+
+/*****************************************************************************
+*
+* SkAsfAcpiRsdt
+*
+* Description:  Searches in the pointer list of the RSDT table for the "ASF!"
+*               table pointer.
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:       1: OK
+*                0: UNDEFINED
+*               <0: Error Codes
+*
+*/
+SK_I8 SkAsfAcpiRsdt(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   *pImage,
+HANDLE  SectionHandle,
+SK_U32  PhysAddr    )  {
+    SK_I8 RetVal;
+    NTSTATUS            NtRet;
+    unsigned char       *pU8;
+    PVOID               BaseAddress;
+    ULONG               CommitSize;
+    ULONG               i;
+    LARGE_INTEGER       MaxSize;
+    LARGE_INTEGER       SectOffset;
+    SIZE_T              ViewSize;
+
+    SK_U32              Length;
+    SK_U32              NumTables;
+    SK_U32              TableAddr;
+    SK_U8               CheckSum;
+    SK_U8               Rev;
+
+    RetVal = ASF_ACPI_STATE_UNDEFINED;
+
+    //  Try to map a view to the "RSDT" table
+    BaseAddress = NULL;
+    SectOffset.QuadPart =   PhysAddr; //  will be roundet down to the next allocation boundery
+    CommitSize =            PAGE_SIZE*2;
+    ViewSize =              PAGE_SIZE*2;
+    NtRet = ZwMapViewOfSection( SectionHandle,          // IN HANDLE  SectionHandle
+                                NtCurrentProcess(),     // IN HANDLE  ProcessHandle
+                                &BaseAddress,           // IN OUT PVOID  *BaseAddress
+                                0L,                     // IN ULONG  ZeroBits
+                                CommitSize,             // IN ULONG  CommitSize,
+                                &SectOffset,            // IN OUT PLARGE_INTEGER  SectionOffset  OPTIONAL,
+                                &ViewSize,              // IN OUT PSIZE_T  ViewSize,
+                                ViewShare,              // IN SECTION_INHERIT  InheritDisposition,
+                                0,                      // IN ULONG  AllocationType,
+                                PAGE_READONLY           // IN ULONG  Protect
+                                );
+    if( NtRet == STATUS_SUCCESS )  {
+        pU8 = ((unsigned char *) BaseAddress);
+        //   search for "RSDT" signature, because BaseAddress is roundet down to the
+        //   next allocation boundary  (PAGE_SIZE ??)
+        for( i=0; i<PAGE_SIZE; i++ )  {
+            if( (*(pU8 + 0 ) == 'R') && (*(pU8 + 1 ) == 'S') &&
+                (*(pU8 + 2 ) == 'D') && (*(pU8 + 3 ) == 'T')    )
+                break;
+            else
+                pU8++;
+        }
+        //  if "RSDT" Table has been found, check header
+        if( i < PAGE_SIZE )  {
+            //  Check the signature and header
+            Length = *( (SK_U32 *) (pU8 + 4) );
+            Rev = *( pU8 + 8);
+            CheckSum = 0;
+            for( i=0; i<Length; i++ )
+                CheckSum += *(pU8+i);
+            if( (CheckSum == 0) && (Rev == 1) )  {
+                if( (Length >= TABLE_HEADER_LENGTH))  {
+                    NumTables = (Length - TABLE_HEADER_LENGTH) / 4;
+                    // SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfAcpiRsdt -> %d tables in the list\n", NumTables));
+                    pU8 += TABLE_HEADER_LENGTH;
+                    //  check all list entries (phys. addr) for a valid "ASF!" table
+                    for( i=0; i<NumTables; i++ )  {
+                        RetVal = SkAsfAcpiAsf( pAC, IoC, pImage, SectionHandle, *((SK_U32 *) pU8) );
+                        if( RetVal == ASF_ACPI_STATE_OK )
+                            break;
+                        pU8 += 4;
+                    }
+                }
+                else
+                    RetVal = ASF_ACPI_STATE_ERROR_RSDT_NO_TABLE;
+            }
+            else
+                RetVal = ASF_ACPI_STATE_ERROR_RSDT_HEADER;
+        }  //  if( i < PAGE_SIZE )  {
+        else
+            RetVal = ASF_ACPI_STATE_ERROR_RSDT;
+        ZwUnmapViewOfSection( NtCurrentProcess(), BaseAddress );
+    }
+    else
+        RetVal = ASF_ACPI_STATE_ERROR_RSDT;
+
+    return( RetVal );
+}
+#endif
+
+#if (0)
+/*****************************************************************************
+*
+* SkAsfAcpiXsdt
+*
+* Description:  Searches in the pointer list of the XSDT table for the "ASF!"
+*               table pointer.
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:       1: OK
+*                0: UNDEFINED
+*               <0: Error Codes
+*
+*/
+SK_I8 SkAsfAcpiXsdt(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   *pImage,
+HANDLE  SectionHandle,
+SK_U64  PhysAddr )  {
+    SK_I8 RetVal;
+
+    RetVal = ASF_ACPI_STATE_ERROR_XSDT;
+
+    return( RetVal );
+}
+#endif
+
+#if (0)
+/*****************************************************************************
+*
+* SkAsfAcpiAsf
+*
+* Description:  Checks, whether the given PhysAddr points to a valid ASF! table.
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:       1: OK
+*                0: UNDEFINED
+*               <0: Error Codes
+*
+*/
+SK_I8 SkAsfAcpiAsf(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   *pImage,
+HANDLE  SectionHandle,
+SK_U32  PhysAddr    )  {
+    SK_I8 RetVal;
+    NTSTATUS            NtRet;
+    unsigned char       *pU8;
+    PVOID               BaseAddress;
+    ULONG               CommitSize;
+    ULONG               i;
+    LARGE_INTEGER       MaxSize;
+    LARGE_INTEGER       SectOffset;
+    SIZE_T              ViewSize;
+
+    SK_U32              Length;
+    SK_U32              NumTables;
+    SK_U32              TableAddr;
+    SK_U8               CheckSum;
+    SK_U8               Rev;
+
+    NDIS_STATUS     Status;
+    NDIS_HANDLE     FileHandle;
+    UINT            FileLength;
+    SK_U8           *pAcpiAsf;
+
+    RetVal = ASF_ACPI_STATE_ERROR_RSDT_NO_ASF_TABLE;
+
+    /* Try to open the ASF Simulation file (AcpiAsf.bin) */
+    NdisOpenFile( (PNDIS_STATUS) &Status,
+                  (PNDIS_HANDLE) &FileHandle,
+                  (PUINT) &FileLength,
+                  (PNDIS_STRING) &SimuAsfTab,
+                  HighestPhysAddress  );
+
+    if(Status == NDIS_STATUS_SUCCESS) {
+        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("*** AcpiAsf.bin opened successfully ***\n"));
+        /* Try to map AcpiAsf.bin */
+        NdisMapFile( (PNDIS_STATUS)&Status, (PVOID)&pAcpiAsf, FileHandle );
+        if(Status == NDIS_STATUS_SUCCESS) {
+            pU8 = ((unsigned char *) pAcpiAsf);
+            //   search for "ASF!" signature, because BaseAddress is roundet down to the
+            //   next allocation boundary  (PAGE_SIZE ??)
+            for( i=0; i<PAGE_SIZE; i++ )  {
+                if( (*(pU8 + 0 ) == 'A') && (*(pU8 + 1 ) == 'S') &&
+                    (*(pU8 + 2 ) == 'F') && (*(pU8 + 3 ) == '!')    )
+                    break;
+                else
+                    pU8++;
+            }
+            //  if "ASF!" Table has been found, check header
+            if( i < PAGE_SIZE )  {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("Simulation ASF! table found\n"));
+                Length = *( (SK_U32 *) (pU8 + 4) );
+                Rev = *( pU8 + 8);
+                CheckSum = 0;
+                for( i=0; i<Length; i++ )
+                    CheckSum += *(pU8+i);
+                if( (CheckSum == 0) && ( (Rev == 0x10) || (Rev == 0x20) ) )  {  //  Revision 0x10, 0x20 => ASF
+                    RetVal = SkAsfPatchAsfTable( pAC, IoC, pImage, pU8, Length );
+                }
+                else
+                    RetVal = ASF_ACPI_STATE_ERROR_ASF_HEADER;
+            }  //  if( i < PAGE_SIZE )  {
+            else
+                RetVal = ASF_ACPI_STATE_ERROR_ASF;
+        }
+    }
+    else { // No Simulation File, take REAL ASF! Table
+        //  Try to map a view to the "ASF" table
+        BaseAddress = NULL;
+        SectOffset.QuadPart =   PhysAddr;
+        CommitSize =            PAGE_SIZE*2;
+        ViewSize =              PAGE_SIZE*2;
+        NtRet = ZwMapViewOfSection( SectionHandle,          // IN HANDLE  SectionHandle
+                                    NtCurrentProcess(),     // IN HANDLE  ProcessHandle
+                                    &BaseAddress,           // IN OUT PVOID  *BaseAddress
+                                    0L,                     // IN ULONG  ZeroBits
+                                    CommitSize,             // IN ULONG  CommitSize,
+                                    &SectOffset,            // IN OUT PLARGE_INTEGER  SectionOffset  OPTIONAL,
+                                    &ViewSize,              // IN OUT PSIZE_T  ViewSize,
+                                    ViewShare,              // IN SECTION_INHERIT  InheritDisposition,
+                                    0,                      // IN ULONG  AllocationType,
+                                    PAGE_READONLY           // IN ULONG  Protect
+                                    );
+        if( NtRet == STATUS_SUCCESS )  {
+            pU8 = ((unsigned char *) BaseAddress);
+            //   search for "ASF!" signature, because BaseAddress is roundet down to the
+            //   next allocation boundary  (PAGE_SIZE ??)
+            for( i=0; i<PAGE_SIZE; i++ )  {
+                if( (*(pU8 + 0 ) == 'A') && (*(pU8 + 1 ) == 'S') &&
+                    (*(pU8 + 2 ) == 'F') && (*(pU8 + 3 ) == '!')    )
+                    break;
+                else
+                    pU8++;
+            }
+            //  if "ASF!" Table has been found, check header
+            if( i < PAGE_SIZE )  {
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("SkAsfAcpiAsf -> ASF! table found at 0x%x (phys)\n", PhysAddr ));
+                Length = *( (SK_U32 *) (pU8 + 4) );
+                Rev = *( pU8 + 8);
+                CheckSum = 0;
+                for( i=0; i<Length; i++ )
+                    CheckSum += *(pU8+i);
+                if( (CheckSum == 0) && ( (Rev == 0x10) || (Rev == 0x20) ) )  {  //  Revision 0x10, 0x20 => ASF
+                    RetVal = SkAsfPatchAsfTable( pAC, IoC, pImage, pU8, Length );
+                }
+                else
+                    RetVal = ASF_ACPI_STATE_ERROR_ASF_HEADER;
+            }  //  if( i < PAGE_SIZE )  {
+            else
+                RetVal = ASF_ACPI_STATE_ERROR_ASF;
+
+            ZwUnmapViewOfSection( NtCurrentProcess(), BaseAddress );
+        }
+        else
+            RetVal = ASF_ACPI_STATE_ERROR_ASF;
+
+        ZwUnmapViewOfSection( NtCurrentProcess(), BaseAddress );
+    }
+
+    return( RetVal );
+}
+#endif
+
+#if (0)
+/*****************************************************************************
+*
+* SkAsfPatchAsfTable
+*
+* Description:  Ovverides the table in the fw image with the current
+*               BIOS - ASF! - table.
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:       1: OK
+*                0: UNDEFINED
+*               <0: Error Codes
+*
+*/
+SK_I8 SkAsfPatchAsfTable(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8 *pImage,
+SK_U8 *pAsfTable,
+SK_U32 TableLength )  {
+
+    SK_I8           RetVal;
+    SK_U32          i,j;
+    SK_U8           *pAcpiAsf;
+    SK_U8           FwImageCsOk;
+    SK_U32          FwImageCs;
+    SK_U32          FwCs;
+    SK_U32          *pTmp32;
+
+    RetVal = ASF_ACPI_STATE_OK;
+
+    //  calculate CS of the FW image
+    pTmp32 = (SK_U32 *) pImage;
+    for( i=0, FwCs=0; i<ASF_FLASH_SIZE; i+=4 )  {
+        FwCs += *pTmp32;
+        pTmp32++;
+    }
+    if( FwCs == 0  )  {  //  CS == 0 => O.K.
+        pAcpiAsf = (SK_U8 *) (pImage + ASF_FLASH_OFFS_ACPI);
+        //  write new "ASF!" - table to the FW image file
+        for( i=0; i<TableLength; i++ )  {
+            *(pAcpiAsf+i) = *(pAsfTable+i);
+        }
+        //  erase dynamic parts of the ASF! - table
+        SkAsfExamineAsfTable( pAC, IoC, pAcpiAsf, TableLength );
+        //  calculate new FW image checksum
+        pTmp32 = (SK_U32 *) pImage;
+        for( i=0, FwCs=0; i<ASF_FLASH_SIZE-4; i+=4 )  {
+            FwCs += *pTmp32;
+            pTmp32++;
+        }
+        *pTmp32 = (~FwCs)+1;
+    }  //  if( FwCs == 0  )  {  //  CS == 0 => O.K.
+    else
+        RetVal = ASF_ACPI_STATE_ERROR_FILE_CS;
+
+    return( RetVal);
+}
+#endif
+
+#if (0)
+/*****************************************************************************
+*
+* SkAsfPatchGuid
+*
+* Description:  Ovverides the GUID in the fw image with the current
+*               SMBios UUID.
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:       1: OK
+*                0: UNDEFINED
+*               <0: Error Codes
+*
+*/
+SK_I8 SkAsfPatchGuid(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8 *pImage,
+SK_U8 *pGuid )  {
+    SK_I8           RetVal;
+    SK_U32          i;
+    SK_U8           *pAcpiAsf;
+    SK_U8           FwImageCsOk;
+    SK_U32          FwImageCs;
+    SK_U32          FwCs;
+    SK_U32          *pTmp32;
+
+    RetVal = ASF_ACPI_STATE_OK;
+
+    //  calculate CS of the FW image
+    pTmp32 = (SK_U32 *) pImage;
+    for( i=0, FwCs=0; i<ASF_FLASH_SIZE; i+=4 )  {
+        FwCs += *pTmp32;
+        pTmp32++;
+    }
+    if( FwCs == 0  )  {  //  CS == 0 => O.K.
+        pAcpiAsf = (SK_U8 *) (pImage + ASF_FLASH_OFFS_GUID);
+        //  write new GUID table to the FW image file
+        for( i=0; i<16; i++ )  {
+            *(pAcpiAsf+i) = *(pGuid+i);
+        }
+        //  calculate new FW image checksum
+        pTmp32 = (SK_U32 *) pImage;
+        for( i=0, FwCs=0; i<ASF_FLASH_SIZE-4; i+=4 )  {
+            FwCs += *pTmp32;
+            pTmp32++;
+        }
+        *pTmp32 = (~FwCs)+1;
+    }  //  if( FwCs == 0  )  {  //  CS == 0 => O.K.
+    else
+        RetVal = ASF_ACPI_STATE_ERROR_FILE_CS;
+
+    return( RetVal);
+}
+#endif
+
+#if (0)
+/*****************************************************************************
+*
+* SkAsfExamineAsfTable
+*
+* Description:  Ovverides the dynamic parts of the ASF! table in order to
+*               avoid frequently flash writes caused by changing data.
+*
+* Notes:        none
+*
+* Context:      none
+*
+* Returns:       1: OK
+*                0: UNDEFINED
+*               <0: Error Codes
+*
+*/
+void SkAsfExamineAsfTable(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8 *pAsf,
+SK_U32 TableLength )  {
+    SK_U8   *pTmp, *pRmcp, *x;
+    SK_U8   Type;
+    SK_U8   LastRecord;
+    SK_U8   Cs;
+    SK_U16  Length;
+    SK_U16  i,j;
+
+    // copy the ASF table to our asf-mib structure
+    // and print the asf table to debug output
+    pAC->AsfData.Mib.Acpi.length = TableLength;
+    for( i=0; i<TableLength; i++ )  {
+        if (i < ASF_ACPI_MAXBUFFLENGTH) {
+            pAC->AsfData.Mib.Acpi.buffer[i] = *(pAsf+i);
+        }
+        if( i % 16 )  {
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,(" %02x", *(pAsf+i)));
+        }
+        else  {
+            SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n %02x", *(pAsf+i)));
+        }
+    }
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n"));
+
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\nASF! Table:\n"));
+    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    L:%d Rev:%d Cs:0x%x\n", *((SK_U32 *)(pAsf+4)), *(pAsf+8),*(pAsf+9)  ));
+    pTmp = pAsf+36;  //  offset to the 1st information record
+    do {
+        Type =          (*pTmp) & 0x7f;
+        LastRecord =    (*pTmp) & 0x80;
+        Length =        *((SK_U16 *) (pTmp+2));
+        switch( Type )  {
+            case ASF_RECORD_INFO:
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    ASF_INFO L:%d\n", *((SK_U16 *)(pTmp+2)) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("      MinWd %d MinWait:%d\n", *(pTmp+4),*(pTmp+5) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("      SystemId:   %02x\n", *((SK_U16 *)(pTmp+6)) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("      ManufactId: %02x %02x %02x %02x Flags:0x%x\n",
+                                                                      *(pTmp+8),*(pTmp+9),*(pTmp+10),*(pTmp+11),*(pTmp+12)  ));
+                pTmp += Length;
+                break;
+            case ASF_RECORD_ALRT:
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    ASF_ALRT L:%d\n", *((SK_U16 *)(pTmp+4)) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("      As:0x%x DAs:0x%x\n", *(pTmp+4),*(pTmp+5) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("      NumAlrt:%d L:%d\n", *(pTmp+6),*(pTmp+7) ));
+                x = pTmp+8;
+                for( i=0; i<*(pTmp+6); i++ )  {
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        Ev%d",i));
+                    for( j=0; j<12; j++ )
+                        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,(" %02x", *(x++) ));
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n"));
+                }
+                pTmp += Length;
+                break;
+            case ASF_RECORD_RCTL:
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    ASF_RCTL L:%d\n", *((SK_U16 *)(pTmp+2)) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("      NumCtrl:%d L:%d\n", *(pTmp+4),*(pTmp+5) ));
+                x = pTmp+6;
+                for( i=0; i<*(pTmp+4); i++ )  {
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        Ctrl%d",i));
+                    for( j=0; j<4; j++ )
+                        SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,(" %02x", *(x++) ));
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n"));
+                }
+                pTmp += Length;
+                break;
+            case ASF_RECORD_RMCP:
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    ASF_RMCP L:%d\n", *((SK_U16 *)(pTmp+2)) ));
+                pRmcp = pTmp+4;
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        "));
+                for( i=0; i<19; i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,(" %02x", *(pRmcp+i) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n"));
+
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        RemCtrlCap:"));
+                for( i=0; i<7; i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,(" %02x", *(pRmcp+i) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n"));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        BootOptionCompletionCode: %02x\n", *(pRmcp+7)));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        IANA EnterpriseId:        %02x %02x %02x %02x\n",
+                                                                                *(pRmcp+8),*(pRmcp+9), *(pRmcp+10), *(pRmcp+11)  ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        SpecialCommand:           %02x\n", *(pRmcp+12)));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        SpecialCommandPar:        %02x %02x\n", *(pRmcp+13), *(pRmcp+14)));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        BootOptions:              %02x %02x\n", *(pRmcp+15), *(pRmcp+16)));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("        OEM Parameter:            %02x %02x\n", *(pRmcp+17), *(pRmcp+18)));
+                pRmcp +=    7;      //  skip Remote Control Capabilities
+                //  if cpu is running, provide RMCP data to firmware
+                if( pAC->AsfData.CpuAlive )
+                    SkAsfSendRmcpData( pAC, IoC, pRmcp, 12 );
+                for( i=0; i<12; i++ )
+                    *(pRmcp++) = 0; //  erase dynamic part of the record
+                pTmp += Length;
+                break;
+            case ASF_RECORD_ADDR:
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    ASF_ADDR L:%d SEEPROM Adr:0x%x NumAddr:%d\n",
+                                                               *((SK_U16 *)(pTmp+2)), *(pTmp+4), *(pTmp+5) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("      Addr:"));
+                for( i=0; i<*(pTmp+5); i++ )
+                    SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,(" %02x", *(pTmp+6+i) ));
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("\n"));
+                pTmp += Length;
+                break;
+            default:
+                SK_DBG_MSG(pAC, SK_DBGMOD_ASF, SK_DBGCAT_CTRL,("    UNKNOWN Type:0x%x L:%d\n", *pTmp, *((SK_U16 *)(pTmp+2)) ));
+                LastRecord = 1;
+                break;
+        }
+        if( LastRecord )
+            break;
+    } while ( (SK_U32)(pTmp-pAsf) < TableLength );
+
+    //  calculate new checksum
+    *(pAsf+9) = 0; //  delete old Cs
+    for( Cs=0, i=0; i<TableLength; i++ )
+        Cs += *(pAsf + i);
+    *(pAsf+9) = (~Cs)+1;  //  write new Cs
+
+#ifdef CS_CHECK
+    //  just for a check
+    for( Cs=0, i=0; i<TableLength; i++ )
+        Cs += *(pAsf + i);
+#endif  // CS_CHECK
+
+    return;
+}
+#endif
+
+
+SK_I8 SkAsfSendRmcpData(
+SK_AC   *pAC,
+SK_IOC  IoC,
+SK_U8   *pData,
+SK_U8   Length )  {
+    SK_I8   RetVal;
+    SK_U8   lRetCode;
+    SK_U8   Ind, i;
+    SK_U8   TmpBuffer [20];
+
+    RetVal = 1;
+    Ind = 0;
+
+    if( Length <= 18 )  {
+        TmpBuffer[Ind++] = YASF_HOSTCMD_ACPI_RMCP_DATA;
+        TmpBuffer[Ind++] = 2 + Length;  // Length
+        for( i=0; i<Length; i++ )
+            TmpBuffer[Ind++] = *(pData + i );
+        lRetCode = AsfHciSendData(pAC, IoC, TmpBuffer, 0, ASF_HCI_WAIT, 0 );
+        if( lRetCode == HCI_EN_CMD_ERROR )
+            RetVal = 0;
+    }
+    else
+        RetVal = -1;
+
+    return( RetVal );
+}
+
+
+#ifdef __cplusplus
+}
+#endif  /* __cplusplus */
+/* End of file */
+
+
diff --git a/drivers/net/sk98lin/skgeasfconv.c b/drivers/net/sk98lin/skgeasfconv.c
new file mode 100755
index 0000000..4799c1d
--- /dev/null
+++ b/drivers/net/sk98lin/skgeasfconv.c
@@ -0,0 +1,219 @@
+/******************************************************************************
+ *
+ * Name:    skgeasfconv.c
+ * Project: asf/ipmi
+ * Version: $Revision: 1.1.2.1 $
+ * Date:    $Date: 2006/08/28 09:06:52 $
+ * Purpose: asf/ipmi interface in windows driver
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  (C)Copyright 1998-2002 SysKonnect GmbH.
+ *  (C)Copyright 2002-2003 Marvell.
+ *
+ *  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.
+ *
+ *  The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+"$Header: /data/cvs/sweprojects/yukon2/lindrv/asf_linux/Attic/skgeasfconv.c,v 1.1.2.1 2006/08/28 09:06:52 mlindner Exp $" ;
+#endif
+
+#define __SKASF_C
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* cplusplus */
+
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#include "h/sktypes.h"
+// #include <stdlib.h>     // for string operations
+
+
+SK_I8 AsfMac2Asci( SK_U8 *buf, SK_U32 *len, SK_U8 *mac )  {
+	SK_I8 	RetCode;
+//	SK_U8	i, x;
+	SK_U8	i;
+
+	RetCode = 1;
+	*len = 0;
+	for( i=0; i<6; i++ )  {
+		AsfInt2Hex( &buf[*len], 2, (SK_U32) mac[i] );
+		(*len)+=2;
+		if( i < 5 )
+			buf[(*len)++] = '-';
+	}
+	return( RetCode );
+}
+
+SK_I8 AsfAsci2Mac( SK_U8 *buf, SK_U32 len, SK_U8 *mac )  {
+	SK_I8 	RetCode;
+	SK_U8	i, ind;
+
+	RetCode = 1;
+
+	ind = 0;
+	for( i=0; i<6; i++ )  {
+		AsfHex2U8( &buf[ind], &mac[i] );
+		ind+=2;
+		if( (buf[ind] != '-') && (buf[ind] != ':') && ( i < 5) )  {
+			RetCode = 0;
+			break;
+		}
+		ind++;
+	}
+
+	return( RetCode );
+}
+
+SK_I8 AsfIp2Asci( SK_U8 *buf, SK_U32 *len, SK_U8 *ip )  {
+	SK_I8 	RetCode;
+	SK_U8	i, x;
+
+	RetCode = 1;
+	*len = 0;
+	for( i=0; i<4; i++ )  {
+		x = ip[i] / 100;  /*  H  */
+		if( x > 0 )
+			buf[(*len)++] = '0' + x;
+		x = (ip[i] % 100) / 10;  /*  Z */
+		if( (x > 0) || (ip[i] > 99))
+			buf[(*len)++] = '0' + x;
+		x = ip[i] % 10;  /* E */
+		buf[(*len)++] = '0' + x;
+		if( i < 3 )
+			buf[(*len)++] = '.';
+	}
+	return( RetCode );
+}
+
+SK_I8 AsfAsci2Ip( SK_U8 *buf, SK_U32 len, SK_U8 *ip )  {
+	SK_I8 	RetCode;
+	SK_U8	TmpBuf [3];
+	SK_U8	i,j, ind, bind;
+
+	RetCode = 1;
+
+	bind = 0;
+	ind = 0;
+	for ( i=0; i<len; i++ ) {
+		if( buf[i]  != '.' )  {
+			if( bind < 3 )
+				TmpBuf[bind++] = buf[i];
+			else  {
+				RetCode = -1;
+				break;
+			}
+		}  //  	if( buf[i]  != ':' ) 
+		if( (buf[i]  == '.') || (i==(len-1)) ) {
+			ip[ind] = 0;
+			j = 0;
+			if( bind == 3 )  {
+				bind--;
+				ip[ind] += ( (TmpBuf[j++]-0x30) * 100 );
+			}
+			if( bind == 2 )  {
+				bind--;
+				ip[ind] += ( (TmpBuf[j++]-0x30) * 10 );
+			}
+			if( bind == 1)  {
+				bind--;
+				ip[ind] += (TmpBuf[j++]-0x30);
+			}
+			ind++;
+			bind = 0;
+		}  //  else  if( buf[i]  != ':' )  {
+	}  //	for ( i=0; i<ASF_MAC_STRLEN; i++ ) {
+
+	return( RetCode );
+}
+
+SK_I8 AsfHex2Array( SK_U8 *buf, SK_U32 len, SK_U8 *array )  {
+	SK_I8 	RetCode;
+	SK_U8	i;
+
+	RetCode = 1;
+
+	for( i=0; i<len; i+=2 )  {
+		AsfHex2U8( &buf[i], &array[i/2] );
+	}
+	return( RetCode );
+}
+
+SK_I8 AsfArray2Hex( SK_U8 *buf, SK_U32 len, SK_U8 *array )  {
+	SK_I8 	RetCode;
+	SK_U8	i;
+
+	RetCode = 1;
+
+	for( i=0; i<len; i+=2 )  {
+		AsfInt2Hex( &buf[i], 2, (SK_U32) array[i/2] );
+	}
+	return( RetCode );
+}
+
+SK_I8 AsfHex2U8( SK_U8 *buf, SK_U8 *val )  {
+	SK_U8 i, size;
+	
+	size = 2;
+	*val = 0;
+	for( i=0; i<size; i++ )  {
+		if( (buf[size-1-i] >= '0') && (buf[size-1-i] <= '9') )
+			*val |= ((buf[size-1-i]-'0') << (i*4));
+
+		if( (buf[size-1-i] >= 'A') && (buf[size-1-i] <= 'F') )
+			*val |= ((buf[size-1-i]-'A'+10) << (i*4));
+
+		if( (buf[size-1-i] >= 'a') && (buf[size-1-i] <= 'f') )
+			*val |= ((buf[size-1-i]-'a'+10) << (i*4));
+	}
+	return( 1 );
+}
+
+SK_I8 AsfInt2Hex( SK_U8 *buf, SK_U8 size, SK_U32 val )  {
+	SK_U8 i;
+	SK_U8 x;
+
+	if( size > 4 )
+		return( 0 );
+
+	for( i=0; i<size; i++ )  {
+		x = (SK_U8) (val>>(i*4))&0x000f;
+		if( (x >= 0) && (x <= 9) )
+			buf[size-1-i] = x + '0';
+		if( (x >= 0xa) && (x <= 0xf) )
+			buf[size-1-i] = x - 0xa + 'A';
+	}
+	return( 1 );
+}
+
+SK_I8 AsfDec2Int( SK_U8 *buf, SK_U8 size, SK_U32 *val )  {
+	SK_U8 i;
+	
+	*val = 0;
+
+	if( size > 4 )
+		return( 0 );
+
+	for( i=0; i<size; i++ )  {
+		if( (buf[size-1-i] >= '0') && (buf[size-1-i] <= '9') )
+			*val |= ((buf[size-1-i]-'0') << (i+8));
+	}
+	return( 1 );
+}
+
+
+#ifdef __cplusplus
+}
+#endif  /* __cplusplus */
+
diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
new file mode 100755
index 0000000..12276db
--- /dev/null
+++ b/drivers/net/sk98lin/skgehwt.c
@@ -0,0 +1,167 @@
+/******************************************************************************
+ *
+ * Name:	skgehwt.c
+ * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 2.3 $
+ * Date:	$Date: 2005/12/14 16:11:02 $
+ * Purpose:	Hardware Timer
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2004 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ *	Event queue and dispatcher
+ */
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skgehwt.c,v 2.3 2005/12/14 16:11:02 ibrueder Exp $ (C) Marvell.";
+#endif
+
+#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+
+#ifdef __C2MAN__
+/*
+ *   Hardware Timer function queue management.
+ */
+intro()
+{}
+#endif
+
+/*
+ * Prototypes of local functions.
+ */
+#define	SK_HWT_MAX	65000UL * 160		/* ca. 10 sec. */
+
+/* correction factor */
+#define	SK_HWT_FAC	(10 * (SK_U32)pAC->GIni.GIHstClkFact / 16)
+
+/*
+ * Initialize hardware timer.
+ *
+ * Must be called during init level 1.
+ */
+void	SkHwtInit(
+SK_AC	*pAC,	/* Adapters context */
+SK_IOC	Ioc)	/* IoContext */
+{
+	pAC->Hwt.TStart = 0 ;
+	pAC->Hwt.TStop	= 0 ;
+	pAC->Hwt.TActive = SK_FALSE;
+
+	SkHwtStop(pAC, Ioc);
+}
+
+/*
+ *
+ * Start hardware timer (clock ticks are 16us).
+ *
+ */
+void	SkHwtStart(
+SK_AC	*pAC,	/* Adapters context */
+SK_IOC	Ioc,	/* IoContext */
+SK_U32	Time)	/* Time in usec to load the timer */
+{
+	if (Time > SK_HWT_MAX)
+		Time = SK_HWT_MAX;
+
+	pAC->Hwt.TStart = Time;
+	pAC->Hwt.TStop = 0L;
+
+	if (!Time) {
+		Time = 1L;
+	}
+
+	SK_OUT32(Ioc, B2_TI_INI, Time * SK_HWT_FAC);
+
+	SK_OUT16(Ioc, B2_TI_CTRL, TIM_START);	/* Start timer */
+
+	pAC->Hwt.TActive = SK_TRUE;
+}
+
+/*
+ * Stop hardware timer.
+ * and clear the timer IRQ
+ */
+void	SkHwtStop(
+SK_AC	*pAC,	/* Adapters context */
+SK_IOC	Ioc)	/* IoContext */
+{
+	SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
+
+	SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
+
+	pAC->Hwt.TActive = SK_FALSE;
+}
+
+/*
+ *	Stop hardware timer and read time elapsed since last start.
+ *
+ * returns
+ *	The elapsed time since last start in units of 16us.
+ *
+ */
+SK_U32	SkHwtRead(
+SK_AC	*pAC,	/* Adapters context */
+SK_IOC	Ioc)	/* IoContext */
+{
+	SK_U32	TRead;
+	SK_U32	IStatus;
+	SK_U32	TimerInt;
+
+	TimerInt = CHIP_ID_YUKON_2(pAC) ? Y2_IS_TIMINT : IS_TIMINT;
+
+	if (pAC->Hwt.TActive) {
+		
+		SkHwtStop(pAC, Ioc);
+
+		SK_IN32(Ioc, B2_TI_VAL, &TRead);
+		TRead /= SK_HWT_FAC;
+
+		SK_IN32(Ioc, B0_ISRC, &IStatus);
+
+		/* Check if timer expired (or wrapped around) */
+		if ((TRead > pAC->Hwt.TStart) || ((IStatus & TimerInt) != 0)) {
+
+			SkHwtStop(pAC, Ioc);
+
+			pAC->Hwt.TStop = pAC->Hwt.TStart;
+		}
+		else {
+
+			pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
+		}
+	}
+	return(pAC->Hwt.TStop);
+}
+
+/*
+ * interrupt source= timer
+ */
+void	SkHwtIsr(
+SK_AC	*pAC,	/* Adapters context */
+SK_IOC	Ioc)	/* IoContext */
+{
+	SkHwtStop(pAC, Ioc);
+
+	pAC->Hwt.TStop = pAC->Hwt.TStart;
+
+	SkTimerDone(pAC, Ioc);
+}
+
+/* End of file */
diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
new file mode 100755
index 0000000..51acf5d
--- /dev/null
+++ b/drivers/net/sk98lin/skgeinit.c
@@ -0,0 +1,3933 @@
+/******************************************************************************
+ *
+ * Name:	skgeinit.c
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.116 $
+ * Date:	$Date: 2007/06/27 14:35:58 $
+ * Purpose:	Contains functions to initialize the adapter
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+
+/* global variables ***********************************************************/
+
+/* local variables ************************************************************/
+
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skgeinit.c,v 2.116 2007/06/27 14:35:58 rschmidt Exp $ (C) Marvell.";
+#endif
+
+struct s_QOffTab {
+	int	RxQOff;		/* Receive Queue Address Offset */
+	int	XsQOff;		/* Sync Tx Queue Address Offset */
+	int	XaQOff;		/* Async Tx Queue Address Offset */
+};
+
+static struct s_QOffTab QOffTab[] = {
+	{Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2}
+};
+
+struct s_Config {
+	char	ScanString[8];
+	SK_U32	Value;
+};
+
+static struct s_Config OemConfig = {
+	{'O','E','M','_','C','o','n','f'},
+#ifdef SK_OEM_CONFIG
+	OEM_CONFIG_VALUE,
+#else
+	0,
+#endif
+};
+
+#ifndef SK_SLIM
+/******************************************************************************
+ *
+ *	SkGePortVlan() - Enable / Disable VLAN support
+ *
+ * Description:
+ *	Enable or disable the VLAN support of the selected port.
+ *	The new configuration is *not* saved over any SkGeStopPort() and
+ *	SkGeInitPort() calls.
+ *	Currently this function is only supported on Yukon-2/EC adapters.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGePortVlan(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port number */
+SK_BOOL	Enable)	/* Flag */
+{
+	SK_U32	RxCtrl;
+	SK_U32	TxCtrl;
+
+	if (CHIP_ID_YUKON_2(pAC)) {
+		if (Enable) {
+			RxCtrl = RX_VLAN_STRIP_ON;
+			TxCtrl = TX_VLAN_TAG_ON;
+		}
+		else {
+			RxCtrl = RX_VLAN_STRIP_OFF;
+			TxCtrl = TX_VLAN_TAG_OFF;
+		}
+
+		SK_OUT32(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), RxCtrl);
+
+		SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TxCtrl);
+	}
+}	/* SkGePortVlan */
+
+
+/******************************************************************************
+ *
+ *	SkGeRxRss() - Enable / Disable RSS Hash Calculation
+ *
+ * Description:
+ *	Enable or disable the RSS hash calculation of the selected port.
+ *	The new configuration is *not* saved over any SkGeStopPort() and
+ *	SkGeInitPort() calls.
+ *	Currently this function is only supported on Yukon-2/EC adapters.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGeRxRss(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port number */
+SK_BOOL	Enable)	/* Flag */
+{
+	if (CHIP_ID_YUKON_2(pAC)) {
+		SK_OUT32(IoC, Q_ADDR(pAC->GIni.GP[Port].PRxQOff, Q_CSR),
+			Enable ? BMU_ENA_RX_RSS_HASH : BMU_DIS_RX_RSS_HASH);
+	}
+}	/* SkGeRxRss */
+
+
+/******************************************************************************
+ *
+ *	SkGeRxCsum() - Enable / Disable Receive Checksum
+ *
+ * Description:
+ *	Enable or disable the checksum of the selected port.
+ *	The new configuration is *not* saved over any SkGeStopPort() and
+ *	SkGeInitPort() calls.
+ *	Currently this function is only supported on Yukon-2/EC adapters.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGeRxCsum(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port number */
+SK_BOOL	Enable)	/* Flag */
+{
+	if (CHIP_ID_YUKON_2(pAC)) {
+		SK_OUT32(IoC, Q_ADDR(pAC->GIni.GP[Port].PRxQOff, Q_CSR),
+			Enable ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+	}
+}	/* SkGeRxCsum */
+#endif /* !SK_SLIM */
+
+/******************************************************************************
+ *
+ *	SkGePollRxD() - Enable / Disable Descriptor Polling of RxD Ring
+ *
+ * Description:
+ *	Enable or disable the descriptor polling of the receive descriptor
+ *	ring (RxD) for port 'Port'.
+ *	The new configuration is *not* saved over any SkGeStopPort() and
+ *	SkGeInitPort() calls.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGePollRxD(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL PollRxD)	/* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
+{
+	SK_GEPORT *pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (SK_U32)((PollRxD) ?
+		CSR_ENA_POL : CSR_DIS_POL));
+}	/* SkGePollRxD */
+
+
+/******************************************************************************
+ *
+ *	SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
+ *
+ * Description:
+ *	Enable or disable the descriptor polling of the transmit descriptor
+ *	ring(s) (TxD) for port 'Port'.
+ *	The new configuration is *not* saved over any SkGeStopPort() and
+ *	SkGeInitPort() calls.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGePollTxD(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL PollTxD)	/* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
+{
+	SK_GEPORT *pPrt;
+	SK_U32	DWord;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL);
+
+	if (pPrt->PXSQSize != 0) {
+		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
+	}
+
+	if (pPrt->PXAQSize != 0) {
+		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
+	}
+}	/* SkGePollTxD */
+
+#ifndef SK_SLIM
+/******************************************************************************
+ *
+ *	SkGeYellowLED() - Switch the yellow LED on or off.
+ *
+ * Description:
+ *	Switch the yellow LED on or off.
+ *
+ * Note:
+ *	This function may be called any time after SkGeInit(Level 1).
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGeYellowLED(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		State)		/* yellow LED state, 0 = OFF, 0 != ON */
+{
+	int	LedReg;
+
+	if (CHIP_ID_YUKON_2(pAC)) {
+		/* different mapping on Yukon-2 */
+		LedReg = B0_CTST + 1;
+	}
+	else {
+		LedReg = B0_LED;
+	}
+
+	if (State == 0) {
+		/* Switch state LED OFF */
+		SK_OUT8(IoC, LedReg, LED_STAT_OFF);
+	}
+	else {
+		/* Switch state LED ON */
+		SK_OUT8(IoC, LedReg, LED_STAT_ON);
+	}
+}	/* SkGeYellowLED */
+#endif /* !SK_SLIM */
+
+#if (!defined(SK_SLIM) || defined(GENESIS))
+/******************************************************************************
+ *
+ *	SkGeXmitLED() - Modify the Operational Mode of a transmission LED.
+ *
+ * Description:
+ *	The Rx or Tx LED which is specified by 'Led' will be
+ *	enabled, disabled or switched on in test mode.
+ *
+ * Note:
+ *	'Led' must contain the address offset of the LEDs INI register.
+ *
+ * Usage:
+ *	SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGeXmitLED(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Led,		/* offset to the LED Init Value register */
+int		Mode)		/* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
+{
+	SK_U32	LedIni;
+
+	switch (Mode) {
+	case SK_LED_ENA:
+		LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+		SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni);
+		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
+		break;
+	case SK_LED_TST:
+		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON);
+		SK_OUT32(IoC, Led + XMIT_LED_CNT, 100);
+		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
+		break;
+	case SK_LED_DIS:
+	default:
+		/*
+		 * Do NOT stop the LED Timer here. The LED might be
+		 * in on state. But it needs to go off.
+		 */
+		SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
+		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
+	}
+
+	/*
+	 * 1000BT: the Transmit LED is driven by the PHY.
+	 * But the default LED configuration is used for
+	 * Level One and Broadcom PHYs.
+	 * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.
+	 * In this case it has to be added here.)
+	 */
+}	/* SkGeXmitLED */
+#endif /* !SK_SLIM || GENESIS */
+
+
+/******************************************************************************
+ *
+ *	DoCalcAddr() - Calculates the start and the end address of a queue.
+ *
+ * Description:
+ *	This function calculates the start and the end address of a queue.
+ *  Afterwards the 'StartVal' is incremented to the next start position.
+ *	If the port is already initialized the calculated values
+ *	will be checked against the configured values and an
+ *	error will be returned, if they are not equal.
+ *	If the port is not initialized the values will be written to
+ *	*StartAdr and *EndAddr.
+ *
+ * Returns:
+ *	0:	success
+ *	1:	configuration error
+ */
+static int DoCalcAddr(
+SK_AC		*pAC, 				/* Adapter Context */
+SK_GEPORT	SK_FAR *pPrt,		/* port index */
+int			QuSize,				/* size of the queue to configure in kB */
+SK_U32		SK_FAR *StartVal,	/* start value for address calculation */
+SK_U32		SK_FAR *QuStartAddr,/* start addr to calculate */
+SK_U32		SK_FAR *QuEndAddr)	/* end address to calculate */
+{
+	SK_U32	EndVal;
+	SK_U32	NextStart;
+	int		Rtv;
+
+	Rtv = 0;
+	if (QuSize == 0) {
+		EndVal = *StartVal;
+		NextStart = EndVal;
+	}
+	else {
+		EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1;
+		NextStart = EndVal + 1;
+	}
+
+	if (pPrt->PState >= SK_PRT_INIT) {
+		if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) {
+			Rtv = 1;
+		}
+	}
+	else {
+		*QuStartAddr = *StartVal;
+		*QuEndAddr = EndVal;
+	}
+
+	*StartVal = NextStart;
+	return(Rtv);
+}	/* DoCalcAddr */
+
+/******************************************************************************
+ *
+ *	SkGeRoundQueueSize() - Round the given queue size to the adpaters QZ units
+ *
+ * Description:
+ *	This function rounds the given queue size in kBs to adapter specific
+ *	queue size units (Genesis and Yukon: 8 kB, Yukon-2/EC: 1 kB).
+ *
+ * Returns:
+ *	the rounded queue size in kB
+ */
+static int SkGeRoundQueueSize(
+SK_AC	*pAC,		/* Adapter Context */
+int	QueueSizeKB)	/* Queue size in kB */
+{
+	int QueueSizeSteps;
+
+	QueueSizeSteps = (CHIP_ID_YUKON_2(pAC)) ? QZ_STEP_Y2 : QZ_STEP;
+
+	return((QueueSizeKB + QueueSizeSteps - 1) & ~(QueueSizeSteps - 1));
+}	/* SkGeRoundQueueSize */
+
+
+/******************************************************************************
+ *
+ *	SkGeInitAssignRamToQueues() - allocate default queue sizes
+ *
+ * Description:
+ *	This function assigns the memory to the different queues and ports.
+ *	When DualNet is set to SK_TRUE all ports get the same amount of memory.
+ *	Otherwise the first port gets most of the memory and all the
+ *	other ports just the required minimum.
+ *	This function can only be called when pAC->GIni.GIRamSize and
+ *	pAC->GIni.GIMacsFound have been initialized, usually this happens
+ *	at init level 1
+ *
+ * Returns:
+ *	0 - ok
+ *	1 - invalid input values
+ *	2 - not enough memory
+ */
+
+int SkGeInitAssignRamToQueues(
+SK_AC	*pAC,			/* Adapter Context */
+int		ActivePort,		/* Active Port in RLMT mode */
+SK_BOOL	DualNet)		/* Dual Net active */
+{
+	int	i;
+	int	UsedKilobytes;			/* memory already assigned */
+	int	ActivePortKilobytes;	/* memory available for active port */
+	int	MinQueueSize;			/* min. memory for queues */
+	int	TotalRamSize;			/* total memory for queues */
+	SK_BOOL	DualPortYukon2;
+	SK_GEPORT *pPrt;
+
+	if (ActivePort >= pAC->GIni.GIMacsFound) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+			("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
+			ActivePort));
+		return(1);
+	}
+
+	DualPortYukon2 = (CHIP_ID_YUKON_2(pAC) && pAC->GIni.GIMacsFound == 2);
+
+	TotalRamSize = pAC->GIni.GIRamSize;
+
+	if (DualPortYukon2) {
+		TotalRamSize *= 2;
+	}
+
+	MinQueueSize = SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE;
+
+	if (MinQueueSize > pAC->GIni.GIRamSize) {
+		MinQueueSize = pAC->GIni.GIRamSize;
+	}
+
+	if ((pAC->GIni.GIMacsFound * MinQueueSize +
+		 RAM_QUOTA_SYNC * SK_MIN_TXQ_SIZE) > TotalRamSize) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+			("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
+			TotalRamSize));
+		return(2);
+	}
+
+	if (DualNet) {
+		/* every port gets the same amount of memory */
+		ActivePortKilobytes = TotalRamSize / pAC->GIni.GIMacsFound;
+
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+			pPrt = &pAC->GIni.GP[i];
+
+			if (DualPortYukon2) {
+				ActivePortKilobytes = pAC->GIni.GIRamSize;
+			}
+			/* take away the minimum memory for active queues */
+			ActivePortKilobytes -= MinQueueSize;
+
+			/* receive queue gets the minimum + 80% of the rest */
+			pPrt->PRxQSize = SkGeRoundQueueSize(pAC,
+				(int)((long)ActivePortKilobytes * RAM_QUOTA_RX) / 100)
+				+ SK_MIN_RXQ_SIZE;
+
+			ActivePortKilobytes -= (pPrt->PRxQSize - SK_MIN_RXQ_SIZE);
+
+			/* synchronous transmit queue */
+			pPrt->PXSQSize = 0;
+
+			/* asynchronous transmit queue */
+			pPrt->PXAQSize = SkGeRoundQueueSize(pAC,
+				ActivePortKilobytes + SK_MIN_TXQ_SIZE);
+		}
+	}
+	else {	/* RLMT Mode or single link adapter */
+
+		UsedKilobytes = 0;
+
+		/* set standby queue size defaults for all standby ports */
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+			if (i != ActivePort) {
+				pPrt = &pAC->GIni.GP[i];
+
+				if (DualPortYukon2) {
+					pPrt->PRxQSize = SkGeRoundQueueSize(pAC,
+						(int)((long)(pAC->GIni.GIRamSize - MinQueueSize) *
+						RAM_QUOTA_RX) / 100) + SK_MIN_RXQ_SIZE;
+
+					pPrt->PXAQSize = pAC->GIni.GIRamSize - pPrt->PRxQSize;
+				}
+				else {
+					pPrt->PRxQSize = SK_MIN_RXQ_SIZE;
+					pPrt->PXAQSize = SK_MIN_TXQ_SIZE;
+				}
+				pPrt->PXSQSize = 0;
+
+				/* Count used RAM */
+				UsedKilobytes += pPrt->PRxQSize + pPrt->PXAQSize;
+			}
+		}
+		/* what's left? */
+		ActivePortKilobytes = TotalRamSize - UsedKilobytes;
+
+		/* assign it to the active port */
+		/* first take away the minimum memory */
+		ActivePortKilobytes -= MinQueueSize;
+		pPrt = &pAC->GIni.GP[ActivePort];
+
+		/* receive queue gets 80% of the rest */
+		pPrt->PRxQSize = SkGeRoundQueueSize(pAC,
+			(int)((long)ActivePortKilobytes * RAM_QUOTA_RX) / 100);
+
+		ActivePortKilobytes -= pPrt->PRxQSize;
+
+		/* add the minimum memory for Rx queue */
+		pPrt->PRxQSize += MinQueueSize/2;
+
+		/* synchronous transmit queue */
+		pPrt->PXSQSize = 0;
+
+		/* asynchronous transmit queue gets 20% of the rest */
+		pPrt->PXAQSize = SkGeRoundQueueSize(pAC, ActivePortKilobytes) +
+			/* add the minimum memory for Tx queue */
+			MinQueueSize/2;
+	}
+
+#ifdef DEBUG
+	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+		pPrt = &pAC->GIni.GP[i];
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+			("Port %d: RxQSize=%u, TxAQSize=%u, TxSQSize=%u\n",
+			i, pPrt->PRxQSize, pPrt->PXAQSize, pPrt->PXSQSize));
+	}
+#endif /* DEBUG */
+
+	return(0);
+}	/* SkGeInitAssignRamToQueues */
+
+
+/******************************************************************************
+ *
+ *	SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
+ *
+ * Description:
+ *	This function verifies the Queue Size Configuration specified
+ *	in the variables PRxQSize, PXSQSize, and PXAQSize of all
+ *	used ports.
+ *	This requirements must be fullfilled to have a valid configuration:
+ *		- The size of all queues must not exceed GIRamSize.
+ *		- The queue sizes must be specified in units of 8 kB (Genesis & Yukon).
+ *		- The size of Rx queues of available ports must not be
+ *		  smaller than 16 kB (Genesis & Yukon) resp. 10 kB (Yukon-2).
+ *		- The size of at least one Tx queue (synch. or asynch.)
+ *		  of available ports must not be smaller than 16 kB (Genesis & Yukon),
+ *		  resp. 10 kB (Yukon-2) when Jumbo Frames are used.
+ *		- The RAM start and end addresses must not be changed
+ *		  for ports which are already initialized.
+ *	Furthermore SkGeCheckQSize() defines the Start and End Addresses
+ *  of all ports and stores them into the HWAC port	structure.
+ *
+ * Returns:
+ *	0:	Queue Size Configuration valid
+ *	1:	Queue Size Configuration invalid
+ */
+static int SkGeCheckQSize(
+SK_AC	 *pAC,		/* Adapter Context */
+int		 Port)		/* port index */
+{
+	SK_GEPORT *pPrt;
+	int	i;
+	int	Rtv;
+	int	Rtv2;
+	SK_U32	StartAddr;
+#ifndef SK_SLIM
+	int	UsedMem;	/* total memory used (max. found ports) */
+#endif
+
+	Rtv = 0;
+
+#ifndef SK_SLIM
+
+	UsedMem = 0;
+
+	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+		pPrt = &pAC->GIni.GP[i];
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+			UsedMem = 0;
+		}
+		else if (((pPrt->PRxQSize & QZ_UNITS) != 0 ||
+				  (pPrt->PXSQSize & QZ_UNITS) != 0 ||
+				  (pPrt->PXAQSize & QZ_UNITS) != 0)) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
+			return(1);
+		}
+
+#ifndef SK_DIAG
+		if (i == Port && pAC->GIni.GIRamSize > SK_MIN_RXQ_SIZE &&
+			pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
+			return(1);
+		}
+
+		/*
+		 * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
+		 * if Jumbo Frames are used, this size has to be >= 16 kB.
+		 */
+		if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
+			(pPrt->PPortUsage == SK_JUMBO_LINK &&
+			((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
+			 (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
+				SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
+				return(1);
+		}
+#endif /* !SK_DIAG */
+
+		UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
+
+		if (UsedMem > pAC->GIni.GIRamSize) {
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
+			return(1);
+		}
+	}
+
+#endif /* !SK_SLIM */
+
+	/* Now start address calculation */
+	StartAddr = pAC->GIni.GIRamOffs;
+	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+		pPrt = &pAC->GIni.GP[i];
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+			StartAddr = 0;
+		}
+
+		/* Calculate/Check values for the receive queue */
+		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
+			&pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
+		Rtv |= Rtv2;
+
+		/* Calculate/Check values for the synchronous Tx queue */
+		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr,
+			&pPrt->PXsQRamStart, &pPrt->PXsQRamEnd);
+		Rtv |= Rtv2;
+
+		/* Calculate/Check values for the asynchronous Tx queue */
+		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr,
+			&pPrt->PXaQRamStart, &pPrt->PXaQRamEnd);
+		Rtv |= Rtv2;
+
+		if (Rtv) {
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG);
+			return(1);
+		}
+	}
+
+	return(0);
+}	/* SkGeCheckQSize */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkGeInitMacArb() - Initialize the MAC Arbiter
+ *
+ * Description:
+ *	This function initializes the MAC Arbiter.
+ *	It must not be called if there is still an
+ *	initialized or active port.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeInitMacArb(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+	/* release local reset */
+	SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
+
+	/* configure timeout values */
+	SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53);
+	SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53);
+	SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53);
+	SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53);
+
+	SK_OUT8(IoC, B3_MA_RCINI_RX1, 0);
+	SK_OUT8(IoC, B3_MA_RCINI_RX2, 0);
+	SK_OUT8(IoC, B3_MA_RCINI_TX1, 0);
+	SK_OUT8(IoC, B3_MA_RCINI_TX2, 0);
+
+	/* recovery values are needed for XMAC II Rev. B2 only */
+	/* Fast Output Enable Mode was intended to use with Rev. B2, but now? */
+
+	/*
+	 * There is no start or enable button to push, therefore
+	 * the MAC arbiter is configured and enabled now.
+	 */
+}	/* SkGeInitMacArb */
+
+
+/******************************************************************************
+ *
+ *	SkGeInitPktArb() - Initialize the Packet Arbiter
+ *
+ * Description:
+ *	This function initializes the Packet Arbiter.
+ *	It must not be called if there is still an
+ *	initialized or active port.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeInitPktArb(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+	/* release local reset */
+	SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
+
+	/* configure timeout values */
+	SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
+	SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
+	SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
+	SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
+
+	/*
+	 * enable timeout timers if jumbo frames not used
+	 * NOTE: the packet arbiter timeout interrupt is needed for
+	 * half duplex hangup workaround
+	 */
+	if (pAC->GIni.GP[MAC_1].PPortUsage != SK_JUMBO_LINK &&
+		pAC->GIni.GP[MAC_2].PPortUsage != SK_JUMBO_LINK) {
+		if (pAC->GIni.GIMacsFound == 1) {
+			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
+		}
+		else {
+			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2);
+		}
+	}
+}	/* SkGeInitPktArb */
+#endif /* GENESIS */
+
+
+/******************************************************************************
+ *
+ *	SkGeInitMacFifo() - Initialize the MAC FIFOs
+ *
+ * Description:
+ *	Initialize all MAC FIFOs of the specified port
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeInitMacFifo(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_U16	Word;
+	/*
+	 * For each FIFO:
+	 *	- release local reset
+	 *	- use default value for MAC FIFO size
+	 *	- setup defaults for the control register
+	 *	- enable the FIFO
+	 */
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		/* configure Rx MAC FIFO */
+		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
+		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
+		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
+
+		/* configure Tx MAC FIFO */
+		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
+		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
+		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
+
+		/* enable frame flushing if jumbo frames used */
+		if (pAC->GIni.GP[Port].PPortUsage == SK_JUMBO_LINK) {
+			SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
+		}
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		Word = (SK_U16)GMF_RX_CTRL_DEF;
+
+		/* disable Rx GMAC FIFO Flush for YUKON-Plus */
+		if (pAC->GIni.GIYukonLite) {
+
+			Word &= ~GMF_RX_F_FL_ON;
+		}
+
+		/* configure Rx GMAC FIFO */
+		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
+
+		Word = RX_FF_FL_DEF_MSK;
+
+#ifndef SK_DIAG
+		if (HW_FEATURE(pAC, HWF_WA_DEV_4115)) {
+			/*
+			 * Flushing must be enabled (needed for ASF see dev. #4.29),
+			 * but the flushing mask should be disabled (see dev. #4.115)
+			 */
+			Word = 0;
+		}
+#endif /* !SK_DIAG */
+
+		/* set Rx GMAC FIFO Flush Mask (after clearing reset) */
+		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), Word);
+
+		/* default: 0x0a -> 56 bytes on Yukon-1 and 64 bytes on Yukon-2 */
+		Word = (SK_U16)RX_GMF_FL_THR_DEF;
+
+		if (CHIP_ID_YUKON_2(pAC) && pAC->GIni.GIAsfEnabled) {
+			/* WA for dev. #4.30 & 4.89 (reduce to 0x08 -> 48 bytes) */
+			Word -= 2;
+		}
+		else if (HW_FEATURE(pAC, HWF_WA_DEV_521)) {
+			Word = 0x178;
+		}
+		else {
+			/*
+			 * because Pause Packet Truncation in GMAC is not working
+			 * we have to increase the Flush Threshold to 64 bytes
+			 * in order to flush pause packets in Rx FIFO on Yukon-1
+			 */
+			Word++;
+		}
+
+		/* set Rx GMAC FIFO Flush Threshold (after clearing reset) */
+		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), Word);
+
+		/* configure Tx GMAC FIFO */
+		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+		SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
+
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U ||
+			pAC->GIni.GIChipId == CHIP_ID_YUKON_EX ||
+			pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+			/* set Rx Pause Threshold */
+			SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_LP_THR), (SK_U16)SK_ECU_LLPP);
+			SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_UP_THR), (SK_U16)SK_ECU_ULPP);
+
+			if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EX &&
+				pAC->GIni.GIChipRev != CHIP_REV_YU_EX_A0) ||
+				pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+				/* Yukon-Extreme BO and further Extreme devices */
+				/* enable Store & Forward mode for TX */
+				SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TX_STFW_ENA);
+			}
+			else {
+				if (pAC->GIni.GP[Port].PPortUsage == SK_JUMBO_LINK) {
+					/* set Tx GMAC FIFO Almost Empty Threshold */
+					SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR),
+						(SK_ECU_JUMBO_WM << 16) | (SK_U16)SK_ECU_AE_THR);
+					/* disable Store & Forward mode for TX */
+					SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TX_STFW_DIS);
+				}
+#ifdef TEST_ONLY
+				else {
+					/* enable Store & Forward mode for TX */
+					SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TX_STFW_ENA);
+				}
+#endif /* TEST_ONLY */
+			}
+		}
+	}
+
+	if (HW_FEATURE(pAC, HWF_WA_DEV_520)) {
+		/* disable dynamic watermark */
+		SK_IN16(IoC, MR_ADDR(Port, TX_GMF_EA), &Word);
+
+		SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_EA), Word & ~TX_DYN_WM_ENA);
+	}
+
+#endif /* YUKON */
+
+}	/* SkGeInitMacFifo */
+
+#ifdef SK_LNK_SYNC_CNT
+/******************************************************************************
+ *
+ *	SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
+ *
+ * Description:
+ *	This function starts the Link Sync Counter of the specified
+ *	port and enables the generation of an Link Sync IRQ.
+ *	The Link Sync Counter may be used to detect an active link,
+ *	if autonegotiation is not used.
+ *
+ * Note:
+ *	o To ensure receiving the Link Sync Event the LinkSyncCounter
+ *	  should be initialized BEFORE clearing the XMAC's reset!
+ *	o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this
+ *	  function.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGeLoadLnkSyncCnt(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_U32	CntVal)		/* Counter value */
+{
+	SK_U32	OrgIMsk;
+	SK_U32	NewIMsk;
+	SK_U32	ISrc;
+	SK_BOOL	IrqPend;
+
+	/* stop counter */
+	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_STOP);
+
+	/*
+	 * ASIC problem:
+	 * Each time starting the Link Sync Counter an IRQ is generated
+	 * by the adapter. See problem report entry from 21.07.98
+	 *
+	 * Workaround:	Disable Link Sync IRQ and clear the unexpeced IRQ
+	 *		if no IRQ is already pending.
+	 */
+	IrqPend = SK_FALSE;
+	SK_IN32(IoC, B0_ISRC, &ISrc);
+	SK_IN32(IoC, B0_IMSK, &OrgIMsk);
+
+	if (Port == MAC_1) {
+		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
+		if ((ISrc & IS_LNK_SYNC_M1) != 0) {
+			IrqPend = SK_TRUE;
+		}
+	}
+	else {
+		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2;
+		if ((ISrc & IS_LNK_SYNC_M2) != 0) {
+			IrqPend = SK_TRUE;
+		}
+	}
+
+	if (!IrqPend) {
+		SK_OUT32(IoC, B0_IMSK, NewIMsk);
+	}
+
+	/* load counter */
+	SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
+
+	/* start counter */
+	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_START);
+
+	if (!IrqPend) {
+		/* clear the unexpected IRQ */
+		SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_CLR_IRQ);
+
+		/* restore the interrupt mask */
+		SK_OUT32(IoC, B0_IMSK, OrgIMsk);
+	}
+}	/* SkGeLoadLnkSyncCnt*/
+#endif /* SK_LNK_SYNC_CNT */
+
+#if defined(SK_DIAG) || defined(SK_CFG_SYNC)
+/******************************************************************************
+ *
+ *	SkGeCfgSync() - Configure synchronous bandwidth for this port.
+ *
+ * Description:
+ *	This function may be used to configure synchronous bandwidth
+ *	to the specified port. This may be done any time after
+ *	initializing the port. The configuration values are NOT saved
+ *	in the HWAC port structure and will be overwritten any
+ *	time when stopping and starting the port.
+ *	Any values for the synchronous configuration will be ignored
+ *	if the size of the synchronous queue is zero!
+ *
+ *	The default configuration for the synchronous service is
+ *	TXA_ENA_FSYNC. This means if the size of
+ *	the synchronous queue is unequal zero but no specific
+ *	synchronous bandwidth is configured, the synchronous queue
+ *	will always have the 'unlimited' transmit priority!
+ *
+ *	This mode will be restored if the synchronous bandwidth is
+ *	deallocated ('IntTime' = 0 and 'LimCount' = 0).
+ *
+ * Returns:
+ *	0:	success
+ *	1:	parameter configuration error
+ *	2:	try to configure quality of service although no
+ *		synchronous queue is configured
+ */
+int SkGeCfgSync(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_U32	IntTime,	/* Interval Timer Value in units of 8ns */
+SK_U32	LimCount,	/* Number of bytes to transfer during IntTime */
+int		SyncMode)	/* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */
+{
+	int Rtv;
+
+	Rtv = 0;
+
+	/* check the parameters */
+	if (LimCount > IntTime ||
+		(LimCount == 0 && IntTime != 0) ||
+		(LimCount != 0 && IntTime == 0)) {
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
+		return(1);
+	}
+
+	if (pAC->GIni.GP[Port].PXSQSize == 0) {
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
+		return(2);
+	}
+
+	/* calculate register values */
+	IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
+	LimCount = LimCount / 8;
+
+	if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
+		return(1);
+	}
+
+	/*
+	 * - Enable 'Force Sync' to ensure the synchronous queue
+	 *   has the priority while configuring the new values.
+	 * - Also 'disable alloc' to ensure the settings complies
+	 *   to the SyncMode parameter.
+	 * - Disable 'Rate Control' to configure the new values.
+	 * - write IntTime and LimCount
+	 * - start 'Rate Control' and disable 'Force Sync'
+	 *   if Interval Timer or Limit Counter not zero.
+	 */
+	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+		TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+	SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
+	SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
+
+	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+		(SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
+
+	if (IntTime != 0 || LimCount != 0) {
+		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
+	}
+
+	return(0);
+}	/* SkGeCfgSync */
+#endif /* SK_DIAG || SK_CFG_SYNC*/
+
+
+/******************************************************************************
+ *
+ *	DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue
+ *
+ * Desccription:
+ *	If the queue is used, enable and initialize it.
+ *	Make sure the queue is still reset, if it is not used.
+ *
+ * Returns:
+ *	nothing
+ */
+void DoInitRamQueue(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+int		QuIoOffs,		/* Queue I/O Address Offset */
+SK_U32	QuStartAddr,	/* Queue Start Address */
+SK_U32	QuEndAddr,		/* Queue End Address */
+int		QuType)			/* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
+{
+	SK_U32	RxUpThresVal;
+	SK_U32	RxLoThresVal;
+
+	if (QuStartAddr != QuEndAddr) {
+		/* calculate thresholds, assume we have a big Rx queue */
+		RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8;
+		RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8;
+
+		/* build HW address format */
+		QuStartAddr = QuStartAddr / 8;
+		QuEndAddr = QuEndAddr / 8;
+
+		/* release local reset */
+		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR);
+
+		/* configure addresses */
+		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr);
+		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr);
+		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr);
+		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr);
+
+		switch (QuType) {
+		case SK_RX_SRAM_Q:
+			/* configure threshold for small Rx Queue */
+			RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8;
+
+			/* continue with SK_RX_BRAM_Q */
+		case SK_RX_BRAM_Q:
+			/* write threshold for Rx Queue (Pause packets) */
+			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
+			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
+
+			/* the high priority threshold not used */
+			break;
+		case SK_TX_RAM_Q:
+			/*
+			 * Do NOT use Store & Forward under normal operation due to
+			 * performance optimization (GENESIS only).
+			 * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB)
+			 * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
+			 * we NEED Store & Forward of the RAM buffer.
+			 */
+			if (pAC->GIni.GP[MAC_1].PPortUsage == SK_JUMBO_LINK ||
+				pAC->GIni.GP[MAC_2].PPortUsage == SK_JUMBO_LINK ||
+				pAC->GIni.GIYukon) {
+				/* enable Store & Forward Mode for the Tx Side */
+				SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
+			}
+			break;
+		}
+
+		/* set queue operational */
+		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD);
+	}
+	else {
+		/* ensure the queue is still disabled */
+		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET);
+	}
+}	/* DoInitRamQueue */
+
+
+/******************************************************************************
+ *
+ *	SkGeInitRamBufs() - Initialize the RAM Buffer Queues
+ *
+ * Description:
+ *	Initialize all RAM Buffer Queues of the specified port
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeInitRamBufs(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT *pPrt;
+	int RxQType;
+
+	if (!HW_IS_RAM_IF_AVAIL(pAC)) {
+		return;
+	}
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PRxQSize <= SK_MIN_RXQ_SIZE) {
+		RxQType = SK_RX_SRAM_Q;		/* small Rx Queue */
+	}
+	else {
+		RxQType = SK_RX_BRAM_Q;		/* big Rx Queue */
+	}
+
+	DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
+		pPrt->PRxQRamEnd, RxQType);
+
+	DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
+		pPrt->PXsQRamEnd, SK_TX_RAM_Q);
+
+	DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
+		pPrt->PXaQRamEnd, SK_TX_RAM_Q);
+
+}	/* SkGeInitRamBufs */
+
+
+/******************************************************************************
+ *
+ *	SkGeInitRamIface() - Initialize the RAM Interface
+ *
+ * Description:
+ *	This function initializes the Adapters RAM Interface.
+ *
+ * Note:
+ *	This function is used in the diagnostics.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGeInitRamIface(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+	int i;
+	int RamBuffers;
+
+	if (!HW_IS_RAM_IF_AVAIL(pAC)) {
+		return;
+	}
+
+	if (CHIP_ID_YUKON_2(pAC)) {
+		RamBuffers = pAC->GIni.GIMacsFound;
+	}
+	else {
+		RamBuffers = 1;
+	}
+
+	for (i = 0; i < RamBuffers; i++) {
+		/* release local reset */
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_CTRL), (SK_U8)RI_RST_CLR);
+
+		/* configure timeout values */
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53);
+		SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
+	}
+}	/* SkGeInitRamIface */
+
+
+/******************************************************************************
+ *
+ *	SkGeInitBmu() - Initialize the BMU state machines
+ *
+ * Description:
+ *	Initialize all BMU state machines of the specified port
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeInitBmu(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		RxWm;
+	SK_U16		TxWm;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	RxWm = SK_BMU_RX_WM;
+	TxWm = SK_BMU_TX_WM;
+
+	if (CHIP_ID_YUKON_2(pAC)) {
+
+		if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
+			/* for better performance set it to 128 */
+			RxWm = SK_BMU_RX_WM_PEX;
+		}
+
+		/* Rx Queue: Release all local resets and set the watermark */
+		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_CLR_RESET);
+		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_OPER_INIT);
+		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_FIFO_OP_ON);
+
+		SK_OUT16(IoC, Q_ADDR(pPrt->PRxQOff, Q_WM), RxWm);
+
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U &&
+			pAC->GIni.GIChipRev >= CHIP_REV_YU_EC_U_A1) {
+			/* MAC Rx RAM Read is controlled by hardware */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), F_M_RX_RAM_DIS);
+		}
+
+		/*
+		 * Tx Queue: Release all local resets if the queue is used !
+		 * 		set watermark
+		 */
+		if (pPrt->PXSQSize != 0 && HW_SYNC_TX_SUPPORTED(pAC)) {
+			/* Yukon-EC doesn't have a synchronous Tx queue */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_CLR_RESET);
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_OPER_INIT);
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_FIFO_OP_ON);
+
+			SK_OUT16(IoC, Q_ADDR(pPrt->PXsQOff, Q_WM), TxWm);
+		}
+
+		if (pPrt->PXAQSize != 0) {
+
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_CLR_RESET);
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_OPER_INIT);
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_FIFO_OP_ON);
+
+#if (!defined(SK_SLIM) && !defined(SK_DIAG))
+			if (HW_FEATURE(pAC, HWF_TX_IP_ID_INCR_ON)) {
+				/* Enable Tx IP ID Increment */
+				SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_TX_IPIDINCR_ON);
+			}
+#endif /* !SK_SLIM && !SK_DIAG */
+
+			SK_OUT16(IoC, Q_ADDR(pPrt->PXaQOff, Q_WM), TxWm);
+
+			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U &&
+				pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A0) {
+				/* fix for Yukon-EC Ultra: set BMU FIFO level */
+				SK_OUT16(IoC, Q_ADDR(pPrt->PXaQOff, Q_AL), SK_ECU_TXFF_LEV);
+			}
+		}
+	}
+	else {
+		if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
+			/* for better performance */
+			RxWm /= 2;
+			TxWm /= 2;
+		}
+
+		/* Rx Queue: Release all local resets and set the watermark */
+		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
+		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
+
+		/*
+		 * Tx Queue: Release all local resets if the queue is used !
+		 * 		set watermark
+		 */
+		if (pPrt->PXSQSize != 0) {
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
+		}
+
+		if (pPrt->PXAQSize != 0) {
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
+		}
+	}
+	/*
+	 * Do NOT enable the descriptor poll timers here, because
+	 * the descriptor addresses are not specified yet.
+	 */
+}	/* SkGeInitBmu */
+
+
+/******************************************************************************
+ *
+ *	TestStopBit() -	Test the stop bit of the queue
+ *
+ * Description:
+ *	Stopping a queue is not as simple as it seems to be.
+ *	If descriptor polling is enabled, it may happen
+ *	that RX/TX stop is done and SV idle is NOT set.
+ *	In this case we have to issue another stop command.
+ *
+ * Returns:
+ *	The queues control status register
+ */
+static SK_U32 TestStopBit(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		QuIoOffs)	/* Queue I/O Address Offset */
+{
+	SK_U32	QuCsr;	/* CSR contents */
+
+	SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
+
+	if (CHIP_ID_YUKON_2(pAC)) {
+		if ((QuCsr & (BMU_STOP | BMU_IDLE)) == 0) {
+			/* Stop Descriptor overridden by start command */
+			SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), BMU_STOP);
+
+			SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
+		}
+	}
+	else {
+		if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
+			/* Stop Descriptor overridden by start command */
+			SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
+
+			SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
+		}
+	}
+	return(QuCsr);
+}	/* TestStopBit */
+
+
+/******************************************************************************
+ *
+ *	SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'.
+ *
+ * Description:
+ *	After calling this function the descriptor rings and Rx and Tx
+ *	queues of this port may be reconfigured.
+ *
+ *	It is possible to stop the receive and transmit path separate or
+ *	both together.
+ *
+ *	Dir =	SK_STOP_TX 	Stops the transmit path only and resets the MAC.
+ *				The receive queue is still active and
+ *				the pending Rx frames may be still transferred
+ *				into the RxD.
+ *		SK_STOP_RX	Stop the receive path. The tansmit path
+ *				has to be stopped once before.
+ *		SK_STOP_ALL	SK_STOP_TX + SK_STOP_RX
+ *
+ *	RstMode =	SK_SOFT_RST	Resets the MAC, the PHY is still alive.
+ *				SK_HARD_RST	Resets the MAC and the PHY.
+ *
+ * Example:
+ *	1) A Link Down event was signaled for a port. Therefore the activity
+ *	of this port should be stopped and a hardware reset should be issued
+ *	to enable the workaround of XMAC Errata #2. But the received frames
+ *	should not be discarded.
+ *		...
+ *		SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST);
+ *		(transfer all pending Rx frames)
+ *		SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST);
+ *		...
+ *
+ *	2) An event was issued which request the driver to switch
+ *	the 'virtual active' link to an other already active port
+ *	as soon as possible. The frames in the receive queue of this
+ *	port may be lost. But the PHY must not be reset during this
+ *	event.
+ *		...
+ *		SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST);
+ *		...
+ *
+ * Extended Description:
+ *	If SK_STOP_TX is set,
+ *		o disable the MAC's receive and transmitter to prevent
+ *		  from sending incomplete frames
+ *		o stop the port's transmit queues before terminating the
+ *		  BMUs to prevent from performing incomplete PCI cycles
+ *		  on the PCI bus
+ *		- The network Rx and Tx activity and PCI Tx transfer is
+ *		  disabled now.
+ *		o reset the MAC depending on the RstMode
+ *		o Stop Interval Timer and Limit Counter of Tx Arbiter,
+ *		  also disable Force Sync bit and Enable Alloc bit.
+ *		o perform a local reset of the port's Tx path
+ *			- reset the PCI FIFO of the async Tx queue
+ *			- reset the PCI FIFO of the sync Tx queue
+ *			- reset the RAM Buffer async Tx queue
+ *			- reset the RAM Buffer sync Tx queue
+ *			- reset the MAC Tx FIFO
+ *		o switch Link and Tx LED off, stop the LED counters
+ *
+ *	If SK_STOP_RX is set,
+ *		o stop the port's receive queue
+ *		- The path data transfer activity is fully stopped now.
+ *		o perform a local reset of the port's Rx path
+ *			- reset the PCI FIFO of the Rx queue
+ *			- reset the RAM Buffer receive queue
+ *			- reset the MAC Rx FIFO
+ *		o switch Rx LED off, stop the LED counter
+ *
+ *	If all ports are stopped,
+ *		o reset the RAM Interface.
+ *
+ * Notes:
+ *	o This function may be called during the driver states RESET_PORT and
+ *	  SWITCH_PORT.
+ */
+void SkGeStopPort(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port to stop (MAC_1 + n) */
+int		Dir,	/* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
+int		RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
+{
+	SK_GEPORT *pPrt;
+	SK_U32	RxCsr;
+	SK_U32	XsCsr;
+	SK_U32	XaCsr;
+	SK_U64	ToutStart;
+	SK_U32	CsrStart;
+	SK_U32	CsrStop;
+	SK_U32	CsrIdle;
+	SK_U32	CsrTest;
+	SK_U8	rsl;	/* FIFO read shadow level */
+	SK_U8	rl;		/* FIFO read level */
+	int		i;
+	int		ToutCnt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkGeStopPort: Port %d, Dir %d, RstMode %d\n",
+		 Port, Dir, RstMode));
+
+	/* set the proper values of Q_CSR register layout depending on the chip */
+	if (CHIP_ID_YUKON_2(pAC)) {
+		CsrStart = BMU_START;
+		CsrStop = BMU_STOP;
+		CsrIdle = BMU_IDLE;
+		CsrTest = BMU_IDLE;
+	}
+	else {
+		CsrStart = CSR_START;
+		CsrStop = CSR_STOP;
+		CsrIdle = CSR_SV_IDLE;
+		CsrTest = CSR_SV_IDLE | CSR_STOP;
+	}
+
+	if ((Dir & SK_STOP_TX) != 0) {
+
+		if (!pAC->GIni.GIAsfEnabled) {
+			/* disable receiver and transmitter */
+			SkMacRxTxDisable(pAC, IoC, Port);
+		}
+		else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EX) {
+			/*
+			 * Enable flushing of non ASF packets;
+			 * required, because MAC is not disabled
+			 */
+			SK_OUT32(IoC, MR_ADDR(Port, RX_GMF_CTRL_T),
+				RXMF_TCTL_MACSEC_FLSH_ENA);
+		}
+
+		/* stop both transmit queues */
+		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CsrStop);
+		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CsrStop);
+		/*
+		 * If the BMU is in the reset state CSR_STOP will terminate
+		 * immediately.
+		 */
+
+		ToutStart = SkOsGetTime(pAC);
+		ToutCnt = 0;
+		do {
+#ifdef GENESIS
+			if (pAC->GIni.GIGenesis) {
+				/* clear Tx packet arbiter timeout IRQ */
+				SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
+					PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
+				/*
+				 * If the transfer stucks at the XMAC the STOP command will not
+				 * terminate if we don't flush the XMAC's transmit FIFO !
+				 */
+				SkMacFlushTxFifo(pAC, IoC, Port);
+			}
+#endif /* GENESIS */
+
+			XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
+
+			if (HW_SYNC_TX_SUPPORTED(pAC)) {
+				XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
+			}
+			else {
+				XsCsr = XaCsr;
+			}
+
+			if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
+				/*
+				 * Timeout of 1/18 second reached.
+				 * This needs to be checked at 1/18 sec only.
+				 */
+				ToutCnt++;
+				if (ToutCnt > 1) {
+					/*
+					 * If BMU stop doesn't terminate, we assume that
+					 * we have a stable state and can reset the BMU,
+					 * the Prefetch Unit, and RAM buffer now.
+					 */
+					break;			/* ===> leave do/while loop here */
+				}
+				/*
+				 * Cache incoherency workaround: assume a start command
+				 * has been lost while sending the frame.
+				 */
+				ToutStart = SkOsGetTime(pAC);
+
+				if ((XsCsr & CsrStop) != 0) {
+					SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CsrStart);
+				}
+
+				if ((XaCsr & CsrStop) != 0) {
+					SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CsrStart);
+				}
+
+				/*
+				 * After the previous operations the X(s|a)Csr does no
+				 * longer contain the proper values
+				 */
+				XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
+
+				if (HW_SYNC_TX_SUPPORTED(pAC)) {
+					XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
+				}
+				else {
+					XsCsr = XaCsr;
+				}
+			}
+			/*
+			 * Because of the ASIC problem report entry from 21.08.1998 it is
+			 * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
+			 * (valid for GENESIS only)
+			 */
+		} while (((XsCsr & CsrTest) != CsrIdle ||
+				  (XaCsr & CsrTest) != CsrIdle));
+
+		if (pAC->GIni.GIAsfEnabled) {
+
+			pPrt->PState = (RstMode == SK_SOFT_RST) ? SK_PRT_STOP :
+				SK_PRT_RESET;
+		}
+		else {
+			/* Reset the MAC depending on the RstMode */
+			if (RstMode == SK_SOFT_RST) {
+
+				SkMacSoftRst(pAC, IoC, Port);
+			}
+			else {
+#ifdef SK_DIAG
+				if (HW_FEATURE(pAC, HWF_WA_DEV_472) && Port == MAC_1 &&
+					pAC->GIni.GP[MAC_2].PState == SK_PRT_RUN) {
+
+					pAC->GIni.GP[MAC_1].PState = SK_PRT_RESET;
+
+					/* set GPHY Control reset */
+					SK_OUT8(IoC, MR_ADDR(MAC_1, GPHY_CTRL), (SK_U8)GPC_RST_SET);
+				}
+				else {
+
+					SkMacHardRst(pAC, IoC, Port);
+				}
+#else /* !SK_DIAG */
+				SkMacHardRst(pAC, IoC, Port);
+#endif /* !SK_DIAG */
+			}
+		}
+
+		/* disable Force Sync bit and Enable Alloc bit */
+		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+			TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+		/* Stop Interval Timer and Limit Counter of Tx Arbiter */
+		SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
+		SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
+
+		/* Perform a local reset of the port's Tx path */
+		if (CHIP_ID_YUKON_2(pAC)) {
+			/* Reset the PCI FIFO of the async Tx queue */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR),
+				BMU_RST_SET | BMU_FIFO_RST);
+
+			/* Reset the PCI FIFO of the sync Tx queue */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR),
+				BMU_RST_SET | BMU_FIFO_RST);
+
+			/* Reset the Tx prefetch units */
+			SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PXaQOff, PREF_UNIT_CTRL_REG),
+				PREF_UNIT_RST_SET);
+			SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PXsQOff, PREF_UNIT_CTRL_REG),
+				PREF_UNIT_RST_SET);
+		}
+		else {
+			/* Reset the PCI FIFO of the async Tx queue */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
+			/* Reset the PCI FIFO of the sync Tx queue */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
+		}
+
+		/* Reset the RAM Buffer async Tx queue */
+		SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
+		/* Reset the RAM Buffer sync Tx queue */
+		SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
+
+		/* Reset Tx MAC FIFO */
+#ifdef GENESIS
+		if (pAC->GIni.GIGenesis) {
+			/* Note: MFF_RST_SET does NOT reset the XMAC ! */
+			SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET);
+
+			/* switch Link and Tx LED off, stop the LED counters */
+			/* Link LED is switched off by the RLMT and the Diag itself */
+			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
+		}
+#endif /* GENESIS */
+
+#ifdef YUKON
+		if (pAC->GIni.GIYukon) {
+			/* do the reset only if ASF is not enabled */
+			if (!pAC->GIni.GIAsfEnabled) {
+				/* Reset Tx MAC FIFO */
+				SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+			}
+
+			/* set Pause Off */
+			SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_PAUSE_OFF);
+		}
+#endif /* YUKON */
+	}
+
+	if ((Dir & SK_STOP_RX) != 0) {
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+			/*
+			 * The RX Stop command will not work for Yukon-2 if the BMU does not
+			 * reach the end of packet and since we can't make sure that we have
+			 * incoming data, we must reset the BMU while it is not during a DMA
+			 * transfer. Since it is possible that the RX path is still active,
+			 * the RX RAM buffer will be stopped first, so any possible incoming
+			 * data will not trigger a DMA. After the RAM buffer is stopped, the
+			 * BMU is polled until any DMA in progress is ended and only then it
+			 * will be reset.
+			 */
+
+			/* disable the RAM Buffer receive queue */
+			SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_DIS_OP_MD);
+
+			i = 0xffff;
+			while (--i) {
+				SK_IN8(IoC, RB_ADDR(pPrt->PRxQOff, Q_RX_RSL), &rsl);
+				SK_IN8(IoC, RB_ADDR(pPrt->PRxQOff, Q_RX_RL), &rl);
+
+				if (rsl == rl) {
+					break;
+				}
+			}
+
+			/*
+			 * If the Rx side is blocked, the above loop cannot terminate.
+			 * But, if there was any traffic it should be terminated, now.
+			 * However, stop the Rx BMU and the Prefetch Unit !
+			 */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR),
+				BMU_RST_SET | BMU_FIFO_RST);
+			/* reset the Rx prefetch unit */
+			SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PRxQOff, PREF_UNIT_CTRL_REG),
+				PREF_UNIT_RST_SET);
+		}
+		else {
+			/*
+			 * The RX Stop Command will not terminate if no buffers
+			 * are queued in the RxD ring. But it will always reach
+			 * the Idle state. Therefore we can use this feature to
+			 * stop the transfer of received packets.
+			 */
+			/* stop the port's receive queue */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CsrStop);
+
+			i = 100;
+			do {
+#ifdef GENESIS
+				if (pAC->GIni.GIGenesis) {
+					/* clear Rx packet arbiter timeout IRQ */
+					SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
+						PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
+				}
+#endif /* GENESIS */
+
+				RxCsr = TestStopBit(pAC, IoC, pPrt->PRxQOff);
+
+				/* timeout if i==0 (bug fix for #10748) */
+				if (--i == 0) {
+					SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
+						SKERR_HWI_E024MSG);
+					break;
+				}
+			/*
+			 * Because of the ASIC problem report entry from 21.08.1998 it is
+			 * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
+			 * (valid for GENESIS only)
+			 */
+			} while ((RxCsr & CsrTest) != CsrIdle);
+			/* The path data transfer activity is fully stopped now */
+
+			/* Perform a local reset of the port's Rx path */
+			/* Reset the PCI FIFO of the Rx queue */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
+		}
+
+		/* Reset the RAM Buffer receive queue */
+		SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
+
+#ifdef GENESIS
+		if (pAC->GIni.GIGenesis) {
+			/* Reset Rx MAC FIFO */
+			SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
+
+			/* switch Rx LED off, stop the LED counter */
+			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
+		}
+#endif /* GENESIS */
+
+#ifdef YUKON
+		if (pAC->GIni.GIYukon && !pAC->GIni.GIAsfEnabled) {
+			/* Reset Rx MAC FIFO */
+			SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+		}
+
+#ifndef NDIS_MINIPORT_DRIVER	/* temp. ifndef, remove after PM module rework*/
+		/* WA for Dev. #4.169 */
+		if ((pAC->GIni.GIChipId == CHIP_ID_YUKON ||
+			 pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) &&
+			RstMode == SK_HARD_RST) {
+			/* set Link Control reset */
+			SK_OUT8(IoC, MR_ADDR(Port, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_SET);
+
+			/* clear Link Control reset */
+			SK_OUT8(IoC, MR_ADDR(Port, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_CLR);
+		}
+#endif /* !NDIS_MINIPORT */
+#endif /* YUKON */
+	}
+}	/* SkGeStopPort */
+
+
+/******************************************************************************
+ *
+ *	SkGeInit0() - Level 0 Initialization
+ *
+ * Description:
+ *	- Initialize the BMU address offsets
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeInit0(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+	int i;
+	SK_GEPORT *pPrt;
+
+	for (i = 0; i < SK_MAX_MACS; i++) {
+		pPrt = &pAC->GIni.GP[i];
+
+		pPrt->PState = SK_PRT_RESET;
+		pPrt->PPortUsage = SK_RED_LINK;
+		pPrt->PRxQOff = QOffTab[i].RxQOff;
+		pPrt->PXsQOff = QOffTab[i].XsQOff;
+		pPrt->PXaQOff = QOffTab[i].XaQOff;
+		pPrt->PCheckPar = SK_FALSE;
+		pPrt->PIsave = 0;
+		pPrt->PPrevShorts = 0;
+		pPrt->PLinkResCt = 0;
+		pPrt->PAutoNegTOCt = 0;
+		pPrt->PPrevRx = 0;
+		pPrt->PPrevFcs = 0;
+		pPrt->PRxLim = SK_DEF_RX_WA_LIM;
+		pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
+		pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS;
+		pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS;
+		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN;
+		pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE;
+		pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
+		pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL |
+			SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL);
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+		pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
+		pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+		pPrt->PMSCap = 0;
+		pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO;
+		pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET;
+		pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
+		pPrt->PEnDetMode = SK_FALSE;
+		pPrt->PAutoNegFail = SK_FALSE;
+		pPrt->PHWLinkUp = SK_FALSE;
+		pPrt->PLinkBroken = SK_TRUE;	/* See WA code */
+		pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
+		pPrt->PMacColThres = TX_COL_DEF;
+		pPrt->PMacJamLen = TX_JAM_LEN_DEF;
+		pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF;
+		pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
+		pPrt->PMacBackOffLim = TX_BOF_LIM_DEF;
+		pPrt->PMacDataBlind = DATA_BLIND_DEF;
+		pPrt->PMacIpgData = IPG_DATA_DEF;
+		pPrt->PMacLimit4 = SK_FALSE;
+	}
+
+	pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
+	pAC->GIni.GIChipCap = 0;
+	pAC->GIni.GIPexCapOffs = 0;
+	pAC->GIni.GIExtLeFormat = SK_FALSE;
+	pAC->GIni.GIJumTcpSegSup = SK_FALSE;
+	pAC->GIni.GIGotoD3Cold = SK_FALSE;
+	pAC->GIni.GIVMainAvail = SK_TRUE;
+	pAC->GIni.GITxIdxRepThres = 10;
+
+	for (i = 0; i < 4; i++) {
+		pAC->GIni.HwF.Features[i] = 0x00000000;
+		pAC->GIni.HwF.OnMask[i]   = 0x00000000;
+		pAC->GIni.HwF.OffMask[i]  = 0x00000000;
+	}
+
+}	/* SkGeInit0*/
+
+#ifdef SK_PCI_RESET
+/******************************************************************************
+ *
+ *	SkGePciReset() - Reset PCI interface
+ *
+ * Description:
+ *	o Read PCI configuration.
+ *	o Change power state to 3.
+ *	o Change power state to 0.
+ *	o Restore PCI configuration.
+ *
+ * Returns:
+ *	0:	Success.
+ *	1:	Power state could not be changed to 3.
+ */
+static int SkGePciReset(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+	int		i;
+	SK_U16	PmCtlSts;
+	SK_U32	Bp1;
+	SK_U32	Bp2;
+	SK_U16	PciCmd;
+	SK_U8	Cls;
+	SK_U8	Lat;
+	SK_U8	ConfigSpace[PCI_CFG_SIZE];
+
+	/*
+	 * Note: Switching to D3 state is like a software reset.
+	 *		 Switching from D3 to D0 is a hardware reset.
+	 *		 We have to save and restore the configuration space.
+	 */
+	for (i = 0; i < PCI_CFG_SIZE; i++) {
+		SkPciReadCfgDWord(pAC, i*4, &ConfigSpace[i]);
+	}
+
+	/* We know the RAM Interface Arbiter is enabled. */
+	SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D3);
+
+	SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts);
+
+	if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D3) {
+		return(1);
+	}
+
+	/* Return to D0 state. */
+	SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D0);
+
+	/* Check for D0 state. */
+	SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts);
+
+	if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D0) {
+		return(1);
+	}
+
+	/* Check PCI Config Registers. */
+	SkPciReadCfgWord(pAC, PCI_COMMAND, &PciCmd);
+	SkPciReadCfgByte(pAC, PCI_CACHE_LSZ, &Cls);
+	SkPciReadCfgDWord(pAC, PCI_BASE_1ST, &Bp1);
+
+	/*
+	 * Compute the location in PCI config space of BAR2
+	 * relativ to the location of BAR1
+	 */
+	if ((Bp1 & PCI_MEM_TYP_MSK) == PCI_MEM64BIT) {
+		/* BAR1 is 64 bits wide */
+		i = 8;
+	}
+	else {
+		i = 4;
+	}
+
+	SkPciReadCfgDWord(pAC, PCI_BASE_1ST + i, &Bp2);
+	SkPciReadCfgByte(pAC, PCI_LAT_TIM, &Lat);
+
+	if (PciCmd != 0 || Cls != 0 || (Bp1 & 0xfffffff0L) != 0 || Bp2 != 1 ||
+		Lat != 0) {
+		return(1);
+	}
+
+	/* Restore PCI Config Space. */
+	for (i = 0; i < PCI_CFG_SIZE; i++) {
+		SkPciWriteCfgDWord(pAC, i*4, ConfigSpace[i]);
+	}
+
+	return(0);
+}	/* SkGePciReset */
+#endif /* SK_PCI_RESET */
+
+
+/******************************************************************************
+ *
+ *	SkGeSetUpSupFeatures() - Collect Feature List for HW_FEATURE Macro
+ *
+ * Description:
+ *	This function collects the available features and required
+ *	deviation services of the Adapter and provides these
+ *	information in the GIHwF struct. This information is used as
+ *	default value and may be overritten by the driver using the
+ *	SET_HW_FEATURE_MASK() macro in its Init0 phase.
+ *
+ * Notice:
+ *	Using the On and Off mask: Never switch on the same bit in both
+ *	masks simultaneously. However, if doing the Off mask will win.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeSetUpSupFeatures(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+	int i;
+	SK_U16 Word;
+
+	switch (pAC->GIni.GIChipId) {
+	case CHIP_ID_YUKON_EC:
+		pAC->GIni.GIJumTcpSegSup = SK_TRUE;
+
+		if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_A1) {
+			/* A0/A1 */
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_42   | HWF_WA_DEV_46   | HWF_WA_DEV_43_418 |
+				HWF_WA_DEV_420  | HWF_WA_DEV_423  | HWF_WA_DEV_424 |
+				HWF_WA_DEV_425  | HWF_WA_DEV_427  | HWF_WA_DEV_428 |
+				HWF_WA_DEV_483  | HWF_WA_DEV_4109 |
+				HWF_WA_DEV_4152 | HWF_WA_DEV_4167;
+		}
+		else {
+			/* A2/A3 */
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_424  | HWF_WA_DEV_425 | HWF_WA_DEV_427 |
+				HWF_WA_DEV_428  | HWF_WA_DEV_483 | HWF_WA_DEV_4109 |
+				HWF_WA_DEV_4152 | HWF_WA_DEV_4167;
+		}
+		pAC->GIni.HwF.Features[HW_DEV_LIST] |= HWF_WA_DEV_4222 | HWF_WA_DEV_463;
+		break;
+	case CHIP_ID_YUKON_FE:
+		pAC->GIni.HwF.Features[HW_DEV_LIST] =
+			HWF_WA_DEV_427  | HWF_WA_DEV_4109 | HWF_WA_DEV_463 |
+			HWF_WA_DEV_4152 | HWF_WA_DEV_4167 | HWF_WA_DEV_4222;
+		break;
+	case CHIP_ID_YUKON_XL:
+		pAC->GIni.GIJumTcpSegSup = SK_TRUE;
+
+		switch (pAC->GIni.GIChipRev) {
+		case CHIP_REV_YU_XL_A0:		/* still needed for Diag */
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_427  | HWF_WA_DEV_463 | HWF_WA_DEV_472 |
+				HWF_WA_DEV_479  | HWF_WA_DEV_483 | HWF_WA_DEV_4115 |
+				HWF_WA_DEV_4152 | HWF_WA_DEV_4167;
+			break;
+
+		case CHIP_REV_YU_XL_A1:
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_427  | HWF_WA_DEV_483  | HWF_WA_DEV_4109 |
+				HWF_WA_DEV_4115 | HWF_WA_DEV_4152 | HWF_WA_DEV_4167;
+			break;
+
+		case CHIP_REV_YU_XL_A2:
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_427  | HWF_WA_DEV_483 | HWF_WA_DEV_4109 |
+				HWF_WA_DEV_4115 | HWF_WA_DEV_4167;
+			break;
+
+		case CHIP_REV_YU_XL_A3:
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_427 | HWF_WA_DEV_483 | HWF_WA_DEV_4109 |
+				HWF_WA_DEV_4115;
+			break;
+		}
+		if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
+			pAC->GIni.HwF.Features[HW_DEV_LIST] |= HWF_WA_DEV_4222;
+		}
+		break;
+	case CHIP_ID_YUKON_EC_U:
+		if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A0) {
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_427 | HWF_WA_DEV_483 | HWF_WA_DEV_4109 |
+				HWF_WA_DEV_4217;
+		}
+		else if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A1) {
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_427 | HWF_WA_DEV_4109 | HWF_WA_DEV_4185 |
+				HWF_WA_DEV_4217;
+
+			/* check for Rev. A1 */
+			SK_IN16(IoC, Q_ADDR(Q_XA1, Q_WM), &Word);
+
+			if (Word == 0) {
+				pAC->GIni.HwF.Features[HW_DEV_LIST] |=
+					HWF_WA_DEV_4185CS | HWF_WA_DEV_4200;
+			}
+		}
+		else {	/* CHIP_REV_YU_EC_U_B0 */
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_427 | HWF_WA_DEV_4109 | HWF_WA_DEV_4185 |
+				HWF_WA_DEV_4217;
+			pAC->GIni.HwF.Features[HW_FEAT_LIST] |= HWF_ENA_POW_SAV_W_WOL;
+		}
+		pAC->GIni.HwF.Features[HW_DEV_LIST] |= HWF_WA_DEV_4222;
+
+		break;
+	case CHIP_ID_YUKON_EX:
+		if (pAC->GIni.GIChipRev == CHIP_REV_YU_EX_A0) {
+			pAC->GIni.HwF.Features[HW_DEV_LIST] =
+				HWF_WA_DEV_4217 | HWF_WA_DEV_LIM_IPV6_RSS | HWF_WA_DEV_53 |
+				HWF_WA_DEV_54 | HWF_WA_DEV_56 | HWF_WA_DEV_4109 |
+				HWF_WA_DEV_4222;
+			pAC->GIni.HwF.Features[HW_DEV_LIST_2] = HWF_WA_DEV_51;
+		}
+		else {
+			if (pAC->GIni.GIChipRev == CHIP_REV_YU_EX_B0) {
+				pAC->GIni.HwF.Features[HW_DEV_LIST_2] =
+					HWF_WA_DEV_510 | HWF_WA_DEV_511;
+			}
+			pAC->GIni.HwF.Features[HW_FEAT_LIST] =
+				HWF_ADV_CSUM_SUPPORT | HWF_PSM_SUPPORTED | HWF_ENA_POW_SAV_W_WOL;
+			pAC->GIni.HwF.Features[HW_DEV_LIST] = HWF_WA_DEV_4109;
+			pAC->GIni.GIJumTcpSegSup = SK_TRUE;
+		}
+		break;
+	case CHIP_ID_YUKON_FE_P:
+		pAC->GIni.HwF.Features[HW_FEAT_LIST] =
+			HWF_ADV_CSUM_SUPPORT | HWF_PSM_SUPPORTED | HWF_ENA_POW_SAV_W_WOL;
+		pAC->GIni.HwF.Features[HW_DEV_LIST] = HWF_WA_DEV_4109;
+
+		if (pAC->GIni.GIChipRev == CHIP_REV_YU_FE2_A0) {
+			pAC->GIni.HwF.Features[HW_DEV_LIST_2] =
+				HWF_WA_DEV_520 | HWF_WA_DEV_521;
+		}
+		break;
+	}
+
+	for (i = 0; i < 4; i++) {
+		pAC->GIni.HwF.Features[i] =
+			(pAC->GIni.HwF.Features[i] | pAC->GIni.HwF.OnMask[i]) &
+				~pAC->GIni.HwF.OffMask[i];
+	}
+}	/* SkGeSetUpSupFeatures */
+
+
+/******************************************************************************
+ *
+ *	SkGeInit1() - Level 1 Initialization
+ *
+ * Description:
+ *	o Do a software reset.
+ *	o Clear all reset bits.
+ *	o Verify that the detected hardware is present.
+ *	  Return an error if not.
+ *	o Get the hardware configuration
+ *		+ Read the number of MACs/Ports.
+ *		+ Read the RAM size.
+ *		+ Read the PCI Revision Id.
+ *		+ Find out the adapters host clock speed
+ *		+ Read and check the PHY type
+ *
+ * Returns:
+ *	0:	success
+ *	5:	Unexpected PHY type detected
+ *	6:	HW self test failed
+ */
+static int SkGeInit1(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+	SK_U8	Byte;
+	SK_U16	Word;
+	SK_U32	CtrlStat;
+	SK_U32	VauxAvail;
+	SK_U32	DWord;
+	SK_U32	Our1;
+	SK_U32	PowerDownBit;
+	SK_BOOL	FiberType;
+	SK_GEPORT *pPrt;
+	int	LedCfg;
+	int	RetVal;
+	int	i, j;
+
+	RetVal = 0;
+
+#ifdef SK_SLIM
+#ifndef SK_ASF
+	SkPciWriteCfgDWord(IoC, PCI_OUR_REG_3, 0);
+#endif /* !SK_ASF */
+#else /* !SK_SLIM */
+	/* read Chip Identification Number */
+	SK_IN8(IoC, B2_CHIP_ID, &Byte);
+	pAC->GIni.GIChipId = Byte;
+
+	if (Byte == CHIP_ID_YUKON_EC_U || Byte == CHIP_ID_YUKON_EX) {
+		/* Enable all clocks: otherwise the system will hang */
+		/* Do not use PCI_C here */
+		SK_OUT32(IoC, Y2_CFG_SPC + PCI_OUR_REG_3, 0);
+	}
+#endif /* !SK_SLIM */
+
+	/* save CLK_RUN & ASF_ENABLE bits (YUKON-Lite, YUKON-EC) */
+	SK_IN32(IoC, B0_CTST, &CtrlStat);
+
+#ifdef SK_PCI_RESET
+	(void)SkGePciReset(pAC, IoC);
+#endif /* SK_PCI_RESET */
+
+	/* release the SW-reset */
+	/* Important: SW-reset has to be cleared here, to ensure
+	 * the CHIP_ID can be read I/O-mapped based, too -
+	 * remember the RAP register can only be written if SW-reset is cleared.
+	 */
+	SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
+
+#ifdef SK_SLIM
+	/* read Chip Identification Number */
+	SK_IN8(IoC, B2_CHIP_ID, &Byte);
+	pAC->GIni.GIChipId = Byte;
+
+	pAC->GIni.GIAsfEnabled = SK_FALSE;
+#endif /* SK_SLIM */
+
+	/* ASF support only for Yukon-2 */
+	if ((pAC->GIni.GIChipId >= CHIP_ID_YUKON_XL) &&
+		(pAC->GIni.GIChipId <= CHIP_ID_YUKON_EC)) {
+#ifdef SK_ASF
+		if ((CtrlStat & Y2_ASF_ENABLE) != 0) {
+			/* do the SW-reset only if ASF is not enabled */
+			pAC->GIni.GIAsfEnabled = SK_TRUE;
+		}
+#else /* !SK_ASF */
+
+		/* put ASF system in reset state */
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EX) {
+			/* Do not touch bit 5..3 */
+			SK_IN16(IoC, B28_Y2_ASF_STAT_CMD, &Word);
+
+			pAC->GIni.GIAsfRunning =
+				((Word & HCU_CCSR_UC_STATE_MSK) == HCU_CCSR_ASF_RUNNING);
+
+			Word &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE |
+				HCU_CCSR_UC_STATE_MSK);
+
+			SK_OUT16(IoC, B28_Y2_ASF_STAT_CMD, Word);
+		}
+		else {	/* Yukon-EC / Yukon-2 */
+			SK_IN8(IoC, B28_Y2_ASF_STAT_CMD, &Byte);
+
+			pAC->GIni.GIAsfRunning = Byte & Y2_ASF_RUNNING;
+
+			SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)Y2_ASF_RESET);
+		}
+
+		/* disable ASF Unit */
+		SK_OUT16(IoC, B0_CTST, Y2_ASF_DISABLE);
+#endif /* !SK_ASF */
+	}
+
+	if (!pAC->GIni.GIAsfEnabled) {
+		/* Yukon-2: required for Diag and Power Management */
+		/* set the SW-reset */
+		SK_OUT8(IoC, B0_CTST, CS_RST_SET);
+
+		/* release the SW-reset */
+		SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
+	}
+
+	/* enable Config Write */
+	SK_TST_MODE_ON(IoC);
+
+	/* reset all error bits in the PCI STATUS register */
+	/*
+	 * Note: PCI Cfg cycles cannot be used, because they are not
+	 *		 available on some platforms after 'boot time'.
+	 */
+	SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
+
+	SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), Word | (SK_U16)PCI_ERRBITS);
+
+	/* release Master Reset */
+	SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
+
+#ifdef CLK_RUN
+	CtrlStat |= CS_CLK_RUN_ENA;
+
+	/* restore CLK_RUN bits */
+	SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
+		(CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
+#endif /* CLK_RUN */
+
+	if ((pAC->GIni.GIChipId >= CHIP_ID_YUKON_XL) &&
+		(pAC->GIni.GIChipId <= CHIP_ID_YUKON_FE_P)) {
+
+		pAC->GIni.GIYukon2 = SK_TRUE;
+		pAC->GIni.GIValIrqMask = Y2_IS_ALL_MSK;
+		pAC->GIni.GIValHwIrqMask = Y2_HWE_ALL_MSK;
+
+		VauxAvail = Y2_VAUX_AVAIL;
+
+		/* check if VMAIN is available */
+		if ((CtrlStat & Y2_VMAIN_AVAIL) == 0) {
+			pAC->GIni.GIVMainAvail = SK_FALSE;
+		}
+
+		/* needed before using PEX_CAP_REG() macro */
+		if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EX &&
+			pAC->GIni.GIChipRev > CHIP_REV_YU_EX_A0) ||
+			pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+
+			pAC->GIni.GIPexCapOffs = PEX_CAP_REG_OFFS;
+		}
+
+		SK_IN32(IoC, PCI_C(pAC, PCI_OUR_STATUS), &DWord);
+
+		if ((DWord & PCI_OS_PCI_X) != 0) {
+#ifndef SK_SLIM
+			/* this is a PCI / PCI-X bus */
+			if ((DWord & PCI_OS_PCIX) != 0) {
+				/* this is a PCI-X bus */
+				pAC->GIni.GIPciBus = SK_PCIX_BUS;
+
+				/* PCI-X is always 64-bit wide */
+				pAC->GIni.GIPciSlot64 = SK_TRUE;
+
+				pAC->GIni.GIPciMode = (SK_U8)(PCI_OS_SPEED(DWord));
+			}
+			else {
+				/* this is a conventional PCI bus */
+				pAC->GIni.GIPciBus = SK_PCI_BUS;
+
+				SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_2), &Word);
+
+				/* check if 64-bit width is used */
+				pAC->GIni.GIPciSlot64 = (SK_BOOL)
+					(((DWord & PCI_OS_PCI64B) != 0) &&
+					((Word & PCI_USEDATA64) != 0));
+
+				/* check if 66 MHz PCI Clock is active */
+				pAC->GIni.GIPciClock66 = (SK_BOOL)((DWord & PCI_OS_PCI66M) != 0);
+			}
+#endif /* !SK_SLIM */
+		}
+		else {
+			/* this is a PEX bus */
+			pAC->GIni.GIPciBus = SK_PEX_BUS;
+
+			/* clear any PEX errors */
+			SK_OUT32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), 0xffffffffUL);
+
+			SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord);
+
+			if ((DWord & PEX_RX_OV) != 0) {
+				/* Dev. #4.205 occured */
+				pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP;
+				pAC->GIni.GIValIrqMask &= ~Y2_IS_HW_ERR;
+			}
+
+			SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_STAT)), &Word);
+
+			pAC->GIni.GIPexWidth = (SK_U8)((Word & PEX_LS_LINK_WI_MSK) >> 4);
+		}
+		/*
+		 * Yukon-2 chips family has a different way of providing
+		 * the number of MACs available
+		 */
+		pAC->GIni.GIMacsFound = 1;
+
+		/* get HW Resources */
+		SK_IN8(IoC, B2_Y2_HW_RES, &Byte);
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+			/*
+			 * OEM config value is overwritten and should not
+			 * be used for Yukon-2
+			 */
+			pAC->GIni.GILedBlinkCtrl |= SK_ACT_LED_BLINK;
+
+#ifndef SK_SLIM
+			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U ||
+				pAC->GIni.GIChipId == CHIP_ID_YUKON_EX ||
+				pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+				/* LED Configuration is stored in GPIO */
+				SK_IN8(IoC, B2_GP_IO, &Byte);
+			}
+#endif /* !SK_SLIM */
+
+			if ((LedCfg = CFG_LED_MODE(Byte)) == CFG_LED_DUAL_ACT_LNK) {
+
+				pAC->GIni.GILedBlinkCtrl |= SK_DUAL_LED_ACT_LNK;
+			}
+			else if (LedCfg == CFG_LED_LINK_MUX_P60) {
+				/* LED pin 60 used differently */
+				pAC->GIni.GILedBlinkCtrl |= SK_LED_LINK_MUX_P60;
+			}
+			else if (LedCfg == CFG_LED_ACT_OFF_NOTR) {
+				/* Activity LED off if no traffic */
+				pAC->GIni.GILedBlinkCtrl |= SK_ACT_LED_NOTR_OFF;
+			}
+			else if (LedCfg == CFG_LED_COMB_ACT_LNK) {
+				/* Combined Activity/Link LED mode */
+				pAC->GIni.GILedBlinkCtrl |= SK_LED_COMB_ACT_LNK;
+			}
+		}
+
+		/* save HW Resources / Application Information */
+		pAC->GIni.GIHwResInfo = Byte;
+
+		if ((Byte & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
+
+			SK_IN8(IoC, B2_Y2_CLK_GATE, &Byte);
+
+			if (!(Byte & Y2_STATUS_LNK2_INAC)) {
+				/* Link 2 activ */
+				pAC->GIni.GIMacsFound++;
+			}
+		}
+
+#ifdef VCPU
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
+			/* temporary WA for reported number of links */
+			pAC->GIni.GIMacsFound = 2;
+		}
+#endif /* VCPU */
+
+		/* read Chip Revision */
+		SK_IN8(IoC, B2_MAC_CFG, &Byte);
+
+		pAC->GIni.GIChipCap = Byte & 0x0f;
+	}
+	else {
+		pAC->GIni.GIYukon2 = SK_FALSE;
+		pAC->GIni.GIValIrqMask = IS_ALL_MSK;
+		pAC->GIni.GIValHwIrqMask = 0;	/* not activated */
+
+		VauxAvail = CS_VAUX_AVAIL;
+
+		/* read number of MACs and Chip Revision */
+		SK_IN8(IoC, B2_MAC_CFG, &Byte);
+
+		pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
+	}
+
+	/* get Chip Revision Number */
+	pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
+
+#ifndef SK_DIAG
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL &&
+		pAC->GIni.GIChipRev == CHIP_REV_YU_XL_A0) {
+		/* Yukon-2 Chip Rev. A0 */
+		return(6);
+	}
+#endif /* !SK_DIAG */
+
+	/* read the adapters RAM size */
+	SK_IN8(IoC, B2_E_0, &Byte);
+
+	pAC->GIni.GIGenesis = SK_FALSE;
+	pAC->GIni.GIYukon = SK_FALSE;
+	pAC->GIni.GIYukonLite = SK_FALSE;
+	pAC->GIni.GIVauxAvail = SK_FALSE;
+
+#ifdef GENESIS
+	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+
+		pAC->GIni.GIGenesis = SK_TRUE;
+
+		if (Byte == (SK_U8)3) {
+			/* special case: 4 x 64k x 36, offset = 0x80000 */
+			pAC->GIni.GIRamSize = 1024;
+			pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
+		}
+		else {
+			pAC->GIni.GIRamSize = (int)Byte * 512;
+			pAC->GIni.GIRamOffs = 0;
+		}
+		/* all GENESIS adapters work with 53.125 MHz host clock */
+		pAC->GIni.GIHstClkFact = SK_FACT_53;
+
+		/* set Descr. Poll Timer Init Value to 250 ms */
+		pAC->GIni.GIPollTimerVal =
+			SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
+
+		pAC->GIni.GIYukon = SK_TRUE;
+
+		pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
+
+#ifndef SK_SLIM
+		pAC->GIni.GIRamOffs = 0;
+
+		/* WA for Yukon chip Rev. A0 */
+		pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
+			pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
+
+		/* get PM Capabilities of PCI config space */
+		SK_IN16(IoC, PCI_C(pAC, PCI_PM_CAP_REG), &Word);
+
+		/* check if VAUX is available */
+		if (((CtrlStat & VauxAvail) != 0) &&
+			/* check also if PME from D3cold is set */
+			((Word & PCI_PME_D3C_SUP) != 0)) {
+			/* set entry in GE init struct */
+			pAC->GIni.GIVauxAvail = SK_TRUE;
+		}
+#endif /* !SK_SLIM */
+
+		if (!CHIP_ID_YUKON_2(pAC)) {
+
+			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
+				/* this is Rev. A1 */
+				pAC->GIni.GIYukonLite = SK_TRUE;
+			}
+#ifndef SK_SLIM
+			else {
+				/* save Flash-Address Register */
+				SK_IN32(IoC, B2_FAR, &DWord);
+
+				/* test Flash-Address Register */
+				SK_OUT8(IoC, B2_FAR + 3, 0xff);
+				SK_IN8(IoC, B2_FAR + 3, &Byte);
+
+				if (Byte != 0) {
+					/* this is Rev. A0 */
+					pAC->GIni.GIYukonLite = SK_TRUE;
+
+					/* restore Flash-Address Register */
+					SK_OUT32(IoC, B2_FAR, DWord);
+				}
+			}
+#endif /* !SK_SLIM */
+		}
+		else {
+			/* Check for CLS = 0 (dev. #4.55) */
+			if (pAC->GIni.GIPciBus != SK_PEX_BUS) {
+				/* PCI and PCI-X */
+				SK_IN8(IoC, PCI_C(pAC, PCI_CACHE_LSZ), &Byte);
+
+				if (Byte == 0) {
+					/* set CLS to 2 if configured to 0 */
+					SK_OUT8(IoC, PCI_C(pAC, PCI_CACHE_LSZ), 2);
+				}
+
+				if (pAC->GIni.GIPciBus == SK_PCIX_BUS) {
+					/* set Cache Line Size opt. */
+					SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord);
+					DWord |= PCI_CLS_OPT;
+					SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord);
+				}
+			}
+		}
+
+		/* GeCommon also used in ASF firmware: VMain may not be available */
+		if (pAC->GIni.GIVMainAvail) {
+			/* switch power to VCC (WA for VAUX problem) */
+			SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
+				PC_VAUX_OFF | PC_VCC_ON));
+#ifdef DEBUG
+			SK_IN32(IoC, B0_CTST, &DWord);
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("Ctrl/Stat & Switch: 0x%08X\n", DWord));
+#endif /* DEBUG */
+		}
+
+		Byte = 0;
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+			switch (pAC->GIni.GIChipId) {
+			/* PEX adapters work with different host clock */
+			case CHIP_ID_YUKON_EC:
+			case CHIP_ID_YUKON_EC_U:
+			case CHIP_ID_YUKON_EX:		/* to be checked */
+				/* Yukon-EC works with 125 MHz host clock */
+				pAC->GIni.GIHstClkFact = SK_FACT_125;
+				break;
+			case CHIP_ID_YUKON_FE:
+				/* Yukon-FE works with 100 MHz host clock */
+				pAC->GIni.GIHstClkFact = SK_FACT_100;
+				break;
+			case CHIP_ID_YUKON_FE_P:
+				/* Yukon-FE+ works with 50 MHz core clock */
+				pAC->GIni.GIHstClkFact = SK_FACT_50;
+				break;
+			case CHIP_ID_YUKON_XL:
+				/* all Yukon-2 adapters work with 156 MHz host clock */
+				pAC->GIni.GIHstClkFact = 2 * SK_FACT_78;
+
+				if (pAC->GIni.GIChipRev > CHIP_REV_YU_XL_A1) {
+					/* enable bits are inverted */
+					Byte = (SK_U8)(Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+						Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+						Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+				}
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E006,
+					SKERR_HWI_E006MSG);
+			}
+
+			pAC->GIni.GIPollTimerVal =
+				SK_DPOLL_DEF_Y2 * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+
+			/* set power down bit */
+			PowerDownBit = PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD;
+
+			/* disable Core Clock Division, set Clock Select to 0 (Yukon-2) */
+			SK_OUT32(IoC, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS);
+
+			/* enable MAC/PHY, PCI and Core Clock for both Links */
+			SK_OUT8(IoC, B2_Y2_CLK_GATE, Byte);
+		}
+		else {
+			/* YUKON adapters work with 78 MHz host clock */
+			pAC->GIni.GIHstClkFact = SK_FACT_78;
+
+			pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;	/* 215 ms */
+
+			/* read the Interrupt source */
+			SK_IN32(IoC, B0_ISRC, &DWord);
+
+			if ((DWord & IS_HW_ERR) != 0) {
+				/* read the HW Error Interrupt source */
+				SK_IN32(IoC, B0_HWE_ISRC, &DWord);
+
+				if ((DWord & IS_IRQ_SENSOR) != 0) {
+					/* disable HW Error IRQ */
+					pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
+				}
+			}
+			/* set power down bit */
+			PowerDownBit = PCI_PHY_COMA;
+		}
+
+		SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &Our1);
+
+		Our1 &= ~PowerDownBit;
+
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL &&
+			pAC->GIni.GIChipRev > CHIP_REV_YU_XL_A1) {
+			/* deassert Low Power for 1st PHY */
+			Our1 |= PCI_Y2_PHY1_COMA;
+
+			if (pAC->GIni.GIMacsFound > 1) {
+				/* deassert Low Power for 2nd PHY */
+				Our1 |= PCI_Y2_PHY2_COMA;
+			}
+		}
+		else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U ||
+				 pAC->GIni.GIChipId == CHIP_ID_YUKON_EX ||
+				 pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+
+			/* enable all clocks; PCI_OUR_REG_3 is set at the top of the function */
+			SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord);
+
+			DWord &= P_ASPM_CONTROL_MSK;
+			/* set all bits to 0 except bits 15..12 and 8 */
+			SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord);
+
+			SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_5), &DWord);
+
+			DWord &= P_CTL_TIM_VMAIN_AV_MSK;
+			/* set all bits to 0 except bits 28 & 27 */
+			SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), DWord);
+
+			/* set all bits to 0 */
+			SK_OUT32(IoC, PCI_C(pAC, PCI_CFG_REG_1), 0);
+
+#if (!defined(SK_SLIM) && !defined(SK_DIAG))
+			/* enable HW WOL */
+			SK_OUT16(IoC, B0_CTST, (SK_U16)Y2_HW_WOL_ON);
+#endif /* !SK_SLIM && !SK_DIAG */
+
+			/* Enable workaround for dev. #4.107 on Yukon-Ultra & Extreme */
+			SK_IN32(IoC, B2_GP_IO, &DWord);
+			DWord |= GLB_GPIO_STAT_RACE_DIS;
+			SK_OUT32(IoC, B2_GP_IO, DWord);
+		}
+
+		/* release PHY from PowerDown/COMA Mode */
+		SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), Our1);
+
+		if (!pAC->GIni.GIAsfEnabled) {
+
+			for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+				/* set Link Control reset */
+				SK_OUT8(IoC, MR_ADDR(i, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_SET);
+
+				/* clear Link Control reset */
+				SK_OUT8(IoC, MR_ADDR(i, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_CLR);
+			}
+		}
+	}
+#endif /* YUKON */
+
+	SK_TST_MODE_OFF(IoC);
+
+#ifndef SK_SLIM
+	if (!CHIP_ID_YUKON_2(pAC)) {
+		/* this is a conventional PCI bus */
+		pAC->GIni.GIPciBus = SK_PCI_BUS;
+
+		/* check if 64-bit PCI Slot is present */
+		pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
+
+		/* check if 66 MHz PCI Clock is active */
+		pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
+	}
+
+	/* read PCI HW Revision Id. */
+	SK_IN8(IoC, PCI_C(pAC, PCI_REV_ID), &pAC->GIni.GIPciHwRev);
+
+	/* read connector type */
+	SK_IN8(IoC, B2_CONN_TYP, &pAC->GIni.GIConTyp);
+#endif /* !SK_SLIM */
+
+	/* read the PMD type */
+	SK_IN8(IoC, B2_PMD_TYP, &Byte);
+
+	pAC->GIni.GIPmdTyp = Byte;
+
+	FiberType = (Byte == 'L' || Byte == 'S' || Byte == 'P');
+
+	pAC->GIni.GICopperType = (SK_BOOL)(Byte == 'T' || Byte == '1' ||
+		(pAC->GIni.GIYukon2 && !FiberType));
+
+	/* read the PHY type (Yukon and Genesis) */
+	SK_IN8(IoC, B2_E_1, &Byte);
+
+	Byte &= 0x0f;	/* the PHY type is stored in the lower nibble */
+	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+		pPrt = &pAC->GIni.GP[i];
+
+		/* get the MAC addresses */
+		for (j = 0; j < 3; j++) {
+			SK_IN16(IoC, B2_MAC_1 + i * 8 + j * 2, &pPrt->PMacAddr[j]);
+		}
+
+#ifdef GENESIS
+		if (pAC->GIni.GIGenesis) {
+			switch (Byte) {
+			case SK_PHY_XMAC:
+				pPrt->PhyAddr = PHY_ADDR_XMAC;
+				break;
+			case SK_PHY_BCOM:
+				pPrt->PhyAddr = PHY_ADDR_BCOM;
+				pPrt->PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
+					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
+				break;
+#ifdef OTHER_PHY
+			case SK_PHY_LONE:
+				pPrt->PhyAddr = PHY_ADDR_LONE;
+				break;
+			case SK_PHY_NAT:
+				pPrt->PhyAddr = PHY_ADDR_NAT;
+				break;
+#endif /* OTHER_PHY */
+			default:
+				/* ERROR: unexpected PHY type detected */
+				RetVal = 5;
+			}
+		}
+#endif /* GENESIS */
+
+#ifdef YUKON
+		if (pAC->GIni.GIYukon) {
+
+			if (((Byte < (SK_U8)SK_PHY_MARV_COPPER) || pAC->GIni.GIYukon2) &&
+				!FiberType) {
+				/* if this field is not initialized */
+				Byte = (SK_U8)SK_PHY_MARV_COPPER;
+
+				pAC->GIni.GICopperType = SK_TRUE;
+			}
+
+			pPrt->PhyAddr = PHY_ADDR_MARV;
+
+			if (pAC->GIni.GICopperType) {
+
+				if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE ||
+					pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P ||
+					(pAC->GIni.GIChipId == CHIP_ID_YUKON_EC &&
+					pAC->GIni.GIChipCap == 2)) {
+
+					pPrt->PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_100MBPS |
+						SK_LSPEED_CAP_10MBPS);
+
+					pAC->GIni.GIRamSize = 4;
+				}
+				else {
+					pPrt->PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_1000MBPS |
+						SK_LSPEED_CAP_100MBPS | SK_LSPEED_CAP_10MBPS |
+						SK_LSPEED_CAP_AUTO);
+				}
+
+				pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
+
+				pPrt->PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
+					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
+			}
+			else {
+				Byte = (SK_U8)SK_PHY_MARV_FIBER;
+			}
+		}
+
+		/* clear TWSI IRQ */
+		SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+
+#endif /* YUKON */
+
+		pPrt->PhyType = (int)Byte;
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+			("PHY type: %d  PHY addr: %04x\n",
+			Byte, pPrt->PhyAddr));
+	}
+
+	/* get MAC Type & set function pointers dependent on */
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		pAC->GIni.GINumOfPattern = 0;
+		pAC->GIni.GIMacType = SK_MAC_XMAC;
+
+		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkXmUpdateStats;
+		pAC->GIni.GIFunc.pFnMacStatistic	= SkXmMacStatistic;
+		pAC->GIni.GIFunc.pFnMacResetCounter	= SkXmResetCounter;
+		pAC->GIni.GIFunc.pFnMacOverflow		= SkXmOverflowStatus;
+#ifdef SK_DIAG
+		pAC->GIni.GIFunc.pFnMacPhyRead		= SkXmPhyRead;
+		pAC->GIni.GIFunc.pFnMacPhyWrite		= SkXmPhyWrite;
+#else	/* SK_DIAG */
+		pAC->GIni.GIFunc.pSkGeSirqIsr		= SkGeYuSirqIsr;
+#endif /* !SK_DIAG */
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		pAC->GIni.GINumOfPattern = SK_NUM_WOL_PATTERN;
+
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EX) {
+
+			pAC->GIni.GIExtLeFormat = SK_TRUE;
+			pAC->GIni.GINumOfPattern += 2;
+
+			/* Bypass MACSec unit */
+			SK_OUT32(IoC, GMAC_CTRL, MAC_CTRL_BYP_MACSECRX_ON |
+				MAC_CTRL_BYP_MACSECTX_ON | MAC_CTRL_BYP_RETR_ON);
+		}
+		else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+
+			pAC->GIni.GIExtLeFormat = SK_TRUE;
+			pAC->GIni.GINumOfPattern -= 1;
+		}
+
+#ifndef SK_SLIM
+		pAC->GIni.GIMacType = SK_MAC_GMAC;
+
+		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkGmUpdateStats;
+		pAC->GIni.GIFunc.pFnMacStatistic	= SkGmMacStatistic;
+		pAC->GIni.GIFunc.pFnMacResetCounter	= SkGmResetCounter;
+		pAC->GIni.GIFunc.pFnMacOverflow		= SkGmOverflowStatus;
+#endif /* !SK_SLIM */
+
+#ifdef SK_DIAG
+		pAC->GIni.GIFunc.pFnMacPhyRead		= SkGmPhyRead;
+		pAC->GIni.GIFunc.pFnMacPhyWrite		= SkGmPhyWrite;
+#else	/* SK_DIAG */
+		if (CHIP_ID_YUKON_2(pAC)) {
+			pAC->GIni.GIFunc.pSkGeSirqIsr	= SkYuk2SirqIsr;
+		}
+		else {
+			pAC->GIni.GIFunc.pSkGeSirqIsr	= SkGeYuSirqIsr;
+		}
+#endif /* !SK_DIAG */
+
+#ifdef SPECIAL_HANDLING
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+			/* check HW self test result */
+			SK_IN8(IoC, B2_E_3, &Byte);
+			if (Byte & B2_E3_RES_MASK) {
+				RetVal = 6;
+			}
+		}
+#endif
+	}
+#endif /* YUKON */
+
+	SkGeSetUpSupFeatures(pAC, IoC);
+
+	return(RetVal);
+}	/* SkGeInit1 */
+
+
+/******************************************************************************
+ *
+ *	SkGeInit2() - Level 2 Initialization
+ *
+ * Description:
+ *	- start the Blink Source Counter
+ *	- start the Descriptor Poll Timer
+ *	- configure the MAC-Arbiter
+ *	- configure the Packet-Arbiter
+ *	- enable the Tx Arbiters
+ *	- enable the RAM Interface Arbiter
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeInit2(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+#ifdef YUKON
+	SK_U16	Word;
+#if (!defined(SK_SLIM) && !defined(SK_DIAG))
+	SK_EVPARA	Para;
+#endif /* !SK_SLIM && !SK_DIAG */
+#endif /* YUKON */
+#ifdef GENESIS
+	SK_U32	DWord;
+#endif /* GENESIS */
+	int		i;
+
+	/* start the Descriptor Poll Timer */
+	if (pAC->GIni.GIPollTimerVal != 0) {
+		if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) {
+			pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG);
+		}
+
+		SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal);
+
+		SK_OUT8(IoC, B28_DPT_CTRL, DPT_START);
+	}
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		/* start the Blink Source Counter */
+		DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+
+		SK_OUT32(IoC, B2_BSC_INI, DWord);
+
+		SK_OUT8(IoC, B2_BSC_CTRL, BSC_START);
+
+		/*
+		 * Configure the MAC Arbiter and the Packet Arbiter.
+		 * They will be started once and never be stopped.
+		 */
+		SkGeInitMacArb(pAC, IoC);
+
+		SkGeInitPktArb(pAC, IoC);
+	}
+#endif /* GENESIS */
+
+#ifdef xSK_DIAG
+	if (pAC->GIni.GIYukon) {
+		/* start Time Stamp Timer */
+		SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
+	}
+#endif /* SK_DIAG */
+
+	/* enable the Tx Arbiters */
+	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+		SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB);
+	}
+
+	/* enable the RAM Interface Arbiter */
+	SkGeInitRamIface(pAC, IoC);
+
+#ifdef YUKON
+	if (CHIP_ID_YUKON_2(pAC)) {
+
+		if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
+
+			SK_TST_MODE_ON(IoC);
+
+			/* get Max. Read Request Size */
+			SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_DEV_CTRL)), &Word);
+
+			/* check for HW-default value of 512 bytes */
+			if ((Word & PEX_DC_MAX_RRS_MSK) == PEX_DC_MAX_RD_RQ_SIZE(2)) {
+				/* change Max. Read Request Size to 2048 bytes */
+				Word &= ~PEX_DC_MAX_RRS_MSK;
+				Word |= PEX_DC_MAX_RD_RQ_SIZE(4);
+
+				SK_OUT16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_DEV_CTRL)), Word);
+			}
+
+#ifdef REPLAY_TIMER
+			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) {
+				/* PEX Ack Reply Timeout to 40 us */
+				SK_OUT16(IoC, PCI_C(pAC, PEX_ACK_RPLY_TOX1), 0x2710);
+			}
+#endif
+
+			SK_TST_MODE_OFF(IoC);
+
+#if (!defined(SK_SLIM) && !defined(SK_DIAG))
+			SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CAP)), &Word);
+
+			Word = (Word & PEX_CAP_MAX_WI_MSK) >> 4;
+
+			/* compare PEX Negotiated Link Width against max. capabil */
+			if (pAC->GIni.GIPexWidth != (SK_U8)Word) {
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("PEX negotiated Link width is: %d, exp.: %d\n",
+					 pAC->GIni.GIPexWidth, Word));
+
+#ifndef NDIS_MINIPORT_DRIVER
+				SK_ERR_LOG(pAC, SK_ERRCL_INFO, SKERR_HWI_E026,
+					SKERR_HWI_E026MSG);
+#endif
+				Para.Para64 = 0;
+				SkEventQueue(pAC, SKGE_DRV, SK_DRV_PEX_LINK_WIDTH, Para);
+			}
+#endif /* !SK_SLIM && !SK_DIAG */
+		}
+
+		/*
+		 * Writing the HW Error Mask Reg. will not generate an IRQ
+		 * as long as the B0_IMSK is not set by the driver.
+		 */
+		SK_OUT32(IoC, B0_HWE_IMSK, pAC->GIni.GIValHwIrqMask);
+	}
+#endif /* YUKON */
+}	/* SkGeInit2 */
+
+
+/******************************************************************************
+ *
+ *	SkGeInit() - Initialize the GE Adapter with the specified level.
+ *
+ * Description:
+ *	Level	0:	Initialize the Module structures.
+ *	Level	1:	Generic Hardware Initialization. The IOP/MemBase pointer has
+ *				to be set before calling this level.
+ *
+ *			o Do a software reset.
+ *			o Clear all reset bits.
+ *			o Verify that the detected hardware is present.
+ *			  Return an error if not.
+ *			o Get the hardware configuration
+ *				+ Set GIMacsFound with the number of MACs.
+ *				+ Store the RAM size in GIRamSize.
+ *				+ Save the PCI Revision ID in GIPciHwRev.
+ *			o return an error
+ *				if Number of MACs > SK_MAX_MACS
+ *
+ *			After returning from Level 0 the adapter
+ *			may be accessed with I/O operations.
+ *
+ *	Level	2:	start the Blink Source Counter
+ *
+ * Returns:
+ *	0:	success
+ *	1:	Number of MACs exceeds SK_MAX_MACS (after level 1)
+ *	2:	Adapter not present or not accessible
+ *	3:	Illegal initialization level
+ *	4:	Initialization level 1 call missing
+ *	5:	Unexpected PHY type detected
+ *	6:	HW self test failed
+ */
+int	SkGeInit(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Level)		/* Initialization Level */
+{
+	int		RetVal;		/* return value */
+	SK_U32	DWord;
+
+	RetVal = 0;
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("SkGeInit(Level %d)\n", Level));
+
+	switch (Level) {
+	case SK_INIT_DATA:
+		/* Initialization Level 0 */
+		SkGeInit0(pAC, IoC);
+		pAC->GIni.GILevel = SK_INIT_DATA;
+		break;
+
+	case SK_INIT_IO:
+		/* Initialization Level 1 */
+		RetVal = SkGeInit1(pAC, IoC);
+		if (RetVal != 0) {
+			break;
+		}
+
+		/* check if the adapter seems to be accessible */
+		SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
+		SK_IN32(IoC, B2_IRQM_INI, &DWord);
+		SK_OUT32(IoC, B2_IRQM_INI, 0L);
+
+		if (DWord != SK_TEST_VAL) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+				("Error accessing IRQM register, 0x%08lX\n", DWord));
+			RetVal = 2;
+			break;
+		}
+
+#ifdef DEBUG
+		/* check if the number of GIMacsFound matches SK_MAX_MACS */
+		if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
+			RetVal = 1;
+			break;
+		}
+#endif /* DEBUG */
+
+		/* Level 1 successfully passed */
+		pAC->GIni.GILevel = SK_INIT_IO;
+		break;
+
+	case SK_INIT_RUN:
+		/* Initialization Level 2 */
+		if (pAC->GIni.GILevel != SK_INIT_IO) {
+#ifndef SK_DIAG
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG);
+#endif /* !SK_DIAG */
+			RetVal = 4;
+			break;
+		}
+
+		SkGeInit2(pAC, IoC);
+
+		/* Level 2 successfully passed */
+		pAC->GIni.GILevel = SK_INIT_RUN;
+		break;
+
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
+		RetVal = 3;
+		break;
+	}
+
+	return(RetVal);
+}	/* SkGeInit */
+
+
+/******************************************************************************
+ *
+ *	SkGeDeInit() - Deinitialize the adapter
+ *
+ * Description:
+ *	All ports of the adapter will be stopped if not already done.
+ *	Do a software reset and switch off all LEDs.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGeDeInit(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC)		/* I/O Context */
+{
+	int	i;
+	SK_U16	Word;
+#ifdef SK_PHY_LP_MODE_DEEP_SLEEP
+	SK_U32	DWord;
+#endif /* SK_PHY_LP_MODE_DEEP_SLEEP */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkGeDeInit:  GILevel = %d, PState = %d\n",
+		 pAC->GIni.GILevel, pAC->GIni.GP[0].PState));
+
+	/* check for static clock gating */
+	if (pAC->GIni.GILevel == SK_INIT_DATA) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("Adapter is already de-initialized\n"));
+
+		return;
+	}
+
+#if (!defined(SK_SLIM) && !defined(VCPU))
+	/* ensure I2C is ready */
+	SkI2cWaitIrq(pAC, IoC);
+#endif
+
+#ifdef SK_PHY_LP_MODE_DEEP_SLEEP
+	/*
+	 * for power saving purposes within mobile environments
+	 * we set the PHY to coma mode.
+	 */
+
+	if (CHIP_ID_YUKON_2(pAC) && !pAC->GIni.GIAsfEnabled
+#ifdef XXX
+		|| (pAC->GIni.GIYukonLite && pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3)
+#endif /* XXX */
+		) {
+
+		/* flag for SkGmEnterLowPowerMode() that the call was from here */
+		pAC->GIni.GILevel = SK_INIT_IO;
+
+		/* for all ports switch PHY to coma mode */
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+			/* Reset Rx MAC FIFO */
+			SK_OUT8(IoC, MR_ADDR(i, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+
+			(void)SkGmEnterLowPowerMode(pAC, IoC, i, PHY_PM_DEEP_SLEEP);
+		}
+
+		if (pAC->GIni.GIVauxAvail) {
+			/* switch power to VAUX */
+			SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
+				PC_VAUX_ON | PC_VCC_OFF));
+#ifdef DEBUG
+			SK_IN32(IoC, B0_CTST, &DWord);
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("Ctrl/Stat & Switch: 0x%08X\n", DWord));
+#endif /* DEBUG */
+		}
+
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U ||
+			pAC->GIni.GIChipId == CHIP_ID_YUKON_EX ||
+			pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+			/* disable HW WOL */
+			SK_OUT16(IoC, B0_CTST, (SK_U16)Y2_HW_WOL_OFF);
+
+			if (HW_FEATURE(pAC, HWF_ENA_POW_SAV_W_WOL)) {
+
+				SK_IN32(IoC, GPHY_CTRL, &DWord);
+
+				/* Enable Shutdown of 2.5V regulator when Vmain not present */
+				SK_OUT32(IoC, GPHY_CTRL, DWord | PHY_CFG_INT_REG_PD_ENA);
+
+				/* put CPU into halt state */
+				SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)HCU_CCSR_ASF_RESET);
+
+				SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)HCU_CCSR_ASF_HALTED);
+
+				/* check for Yukon-Ultra A3,B0 / Yukon-Extreme A0 */
+				if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U &&
+					 pAC->GIni.GIChipRev >= CHIP_REV_YU_EC_U_A1 &&
+					 (pAC->GIni.GIPciHwRev >> 4) > 1) ||
+					(pAC->GIni.GIChipId == CHIP_ID_YUKON_EX &&
+					 pAC->GIni.GIChipRev == CHIP_REV_YU_EX_A0)) {
+
+					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+						("Enable static clock gating, Chip Rev.=%d\n",
+						pAC->GIni.GIChipRev));
+
+					/* Enable static clock gating */
+					SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_3), PCIE_OUR3_WOL_D3_COLD_SET);
+				}
+				else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EX &&
+						 pAC->GIni.GIChipRev != CHIP_REV_YU_EX_A0 ||
+						pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+
+					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+						("Enable dynamic clock gating, Chip Rev.=%d\n",
+						pAC->GIni.GIChipRev));
+
+					/* set events for gate / release core clock in D3 */
+					SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), PCIE_OUR5_EVENT_CLK_D3_SET);
+
+					SK_OUT32(IoC, PCI_C(pAC, PCI_CFG_REG_1), PCIE_CFG1_EVENT_CLK_D3_SET);
+
+					SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord);
+
+					/* save bit 8 for LED scheme #3 */
+					DWord &= P_PIN63_LINK_LED_ENA;
+					DWord |= PCIE_OUR4_DYN_CLK_GATE_SET;
+
+					/* set dynamic core clock gating */
+					SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord);
+				}
+			}
+		}
+	}
+	else if (pAC->GIni.GIYukonLite) {
+		/* switch PHY to IEEE Power Down mode */
+		(void)SkGmEnterLowPowerMode(pAC, IoC, 0, PHY_PM_IEEE_POWER_DOWN);
+
+		if (pAC->GIni.GIVauxAvail) {
+			/* switch power to VAUX */
+			SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
+				PC_VAUX_ON | PC_VCC_OFF));
+		}
+	}
+
+#else /* !SK_PHY_LP_MODE_DEEP_SLEEP */
+
+	if (!pAC->GIni.GIAsfEnabled) {
+		/* stop all current transfer activity */
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+			if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
+				pAC->GIni.GP[i].PState != SK_PRT_RESET) {
+
+				SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
+			}
+		}
+	}
+
+	/* reset all bits in the PCI STATUS register */
+	/*
+	 * Note: PCI Cfg cycles cannot be used, because they are not
+	 *	 available on some platforms after 'boot time'.
+	 */
+	SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
+
+	SK_TST_MODE_ON(IoC);
+
+	SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), Word | (SK_U16)PCI_ERRBITS);
+
+	SK_TST_MODE_OFF(IoC);
+
+	if (!pAC->GIni.GIAsfEnabled) {
+		/* set the SW-reset */
+		SK_OUT8(IoC, B0_CTST, CS_RST_SET);
+	}
+#endif /* !SK_PHY_LP_MODE_DEEP_SLEEP */
+
+	pAC->GIni.GILevel = SK_INIT_DATA;
+
+}	/* SkGeDeInit */
+
+
+#ifdef XXX
+/******************************************************************************
+ *
+ *	SkGeByPassMacSec()	- Startup initialization for MAC Security unit
+ *
+ * Description:
+ *	Set the MAC security unit into a state to bypass all data.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGeByPassMacSec(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port to configure */
+{
+	if (HW_IS_EXT_LE_FORMAT(pAC)) {
+		/* Bypass all MacSec frames */
+		SK_OUT32(IoC, MR_ADDR(Port, MAC_CTRL),
+			MAC_CTRL_BYP_MACSECRX_ON |
+			MAC_CTRL_BYP_MACSECTX_ON |
+			MAC_CTRL_BYP_RETR_ON);
+	}
+}
+#endif
+
+/******************************************************************************
+ *
+ *	SkGeInitPort()	Initialize the specified port.
+ *
+ * Description:
+ *	PRxQSize, PXSQSize, and PXAQSize has to be
+ *	configured for the specified port before calling this function.
+ *  The descriptor rings has to be initialized too.
+ *
+ *	o (Re)configure queues of the specified port.
+ *	o configure the MAC of the specified port.
+ *	o put ASIC and MAC(s) in operational mode.
+ *	o initialize Rx/Tx and Sync LED
+ *	o initialize RAM Buffers and MAC FIFOs
+ *
+ *	The port is ready to connect when returning.
+ *
+ * Note:
+ *	The MAC's Rx and Tx state machine is still disabled when returning.
+ *
+ * Returns:
+ *	0:	success
+ *	1:	Queue size initialization error. The configured values
+ *		for PRxQSize, PXSQSize, or PXAQSize are invalid for one
+ *		or more queues. The specified port was NOT initialized.
+ *		An error log entry was generated.
+ *	2:	The port has to be stopped before it can be initialized again.
+ */
+int SkGeInitPort(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port to configure */
+{
+	SK_GEPORT *pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (SkGeCheckQSize(pAC, Port) != 0) {
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
+		return(1);
+	}
+
+	if (pPrt->PState >= SK_PRT_INIT) {
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
+		return(2);
+	}
+
+	/* configuration ok, initialize the Port now */
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		/* initialize Rx, Tx and Link LED */
+		/*
+		 * If 1000BT PHY needs LED initialization than swap
+		 * LED and XMAC initialization order
+		 */
+		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
+		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
+		/* The Link LED is initialized by RLMT or Diagnostics itself */
+
+		SkXmInitMac(pAC, IoC, Port);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		SkGmInitMac(pAC, IoC, Port);
+	}
+#endif /* YUKON */
+
+	/* do NOT initialize the Link Sync Counter */
+
+	SkGeInitMacFifo(pAC, IoC, Port);
+
+	SkGeInitRamBufs(pAC, IoC, Port);
+
+	if (pPrt->PXSQSize != 0) {
+		/* enable Force Sync bit if synchronous queue available */
+		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
+	}
+
+	SkGeInitBmu(pAC, IoC, Port);
+
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EX) {
+		/*
+		 * Disable flushing of non ASF packets;
+		 * must be done after initializing the BMUs;
+		 * drivers without ASF support should do this too, otherwise
+		 * it may happen that they cannot run on an ASF devices;
+		 * remember that the MAC FIFO isn't reset during initialization.
+		 */
+		SK_OUT32(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), RXMF_TCTL_MACSEC_FLSH_DIS);
+	}
+
+	/* mark port as initialized */
+	pPrt->PState = SK_PRT_INIT;
+
+	return(0);
+}	/* SkGeInitPort */
+
+
+#if (defined(YUK2) && !defined(SK_SLIM))
+/******************************************************************************
+ *
+ *	SkGeRamWrite() - Writes One quadword to RAM
+ *
+ * Returns:
+ *	0
+ */
+static void SkGeRamWrite(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	Addr,		/* Address to be written to (in quadwords) */
+SK_U32	LowDword,	/* Lower Dword to be written */
+SK_U32	HighDword,	/* Upper Dword to be written */
+int		Port)		/* Select RAM buffer (Yukon-2 has 2 RAM buffers) */
+{
+	SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_ADDR), Addr);
+
+	/* Write Access is initiated by writing the upper Dword */
+	SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_DATA_LO), LowDword);
+
+	SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_DATA_HI), HighDword);
+}
+
+/******************************************************************************
+ *
+ * SkYuk2RestartRxBmu() - Restart Receive BMU on Yukon-2
+ *
+ * return:
+ *	0	o.k.
+ *	1	timeout
+ */
+int SkYuk2RestartRxBmu(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_U8		Byte;
+	SK_U16		Word;
+	SK_U16		MacCtrl;
+	SK_U16		MacCtrlSave;
+	SK_U16		RxCtrl;
+	SK_U16		FlushMask;
+	SK_U16		FlushTrsh;
+	SK_U32		RamAdr;
+	SK_U32		StartTime;
+	SK_U32		CurrTime;
+	SK_U32		Delta;
+	SK_U32		TimeOut;
+	SK_BOOL		TimeStampDisabled;
+	SK_GEPORT	*pPrt;			/* GIni Port struct pointer */
+	SK_U16		WordBuffer[4];	/* Buffer to handle MAC address */
+	int			i;
+	int			Rtv;
+
+	Rtv = 0;
+
+	/* read the MAC Interrupt source register */
+	SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &Word);
+
+	/* check if a packet was received by the MAC */
+	if ((Word & GM_IS_RX_COMPL) == 0) {
+		/* workaround not necessary */
+		return(0);
+	}
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/*
+	 1. save Rx MAC FIFO Flush Mask and Rx MAC FIFO Flush Threshold
+	 2. save MAC Rx Control Register
+	 3. re-initialize MAC Rx FIFO, Rx RAM Buffer Queue, PCI Rx FIFO,
+		Rx BMU and Rx Prefetch Unit of the link.
+	 4. set Rx MAC FIFO Flush Mask to 0xffff
+		set Rx MAC FIFO Flush Threshold to a high value, e.g. 0x20
+	 5. set MAC to loopback mode and switch MAC back to Rx/Tx enable
+	 6. clear Rx/Tx Frame Complete IRQ in Rx/T MAC FIFO Control Register
+	 7. send one packet with a size of 64bytes (size below flush threshold)
+		from TXA RAM Buffer Queue to set the rx_sop flop:
+		- set TxAQ Write Pointer to (packet size in qwords + 2)
+		- set TxAQ Level to (packet size in qwords + 2)
+		- write Internal Status Word 1 and 2 to TxAQ RAM Buffer Queue QWord 0,1
+		  according to figure 61 on page 330 of Yukon-2 Spec.
+		- write MAC header with Destination Address = own MAC address to
+		  TxAQ RAM Buffer Queue QWords 2 and 3
+		- set TxAQ Packet Counter to 1 -> packet is transmitted immediately
+	 8. poll MAC IRQ Source Register for IRQ Rx/Tx Frame Complete
+	 9. restore MAC Rx Control Register
+	10. restore Rx MAC FIFO Flush Mask and Rx MAC FIFO Flush Threshold
+	11. set MAC back to GMII mode
+	*/
+
+	/* save MAC General Purpose Control */
+	GM_IN16(IoC, Port, GM_GP_CTRL, &MacCtrlSave);
+
+	/* save Rx MAC FIFO Flush Mask */
+	SK_IN16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), &FlushMask);
+
+	/* save Rx MAC FIFO Flush Threshold */
+	SK_IN16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), &FlushTrsh);
+
+	/* save MAC Rx Control Register */
+	GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkYuk2RestartRxBmu: Port %d, RxCtrl=0x%04X\n",
+		 Port, RxCtrl));
+
+	/* configure the MAC FIFOs */
+	SkGeInitMacFifo(pAC, IoC, Port);
+
+	SkGeInitRamBufs(pAC, IoC, Port);
+
+	SkGeInitBmu(pAC, IoC, Port);
+
+	SK_IN8(IoC, GMAC_TI_ST_CTRL, &Byte);
+
+	TimeStampDisabled = (Byte & GMT_ST_START) == 0;
+
+	if (TimeStampDisabled) {
+		/* start Time Stamp Timer */
+		SkMacTimeStamp(pAC, IoC, Port, SK_TRUE);
+	}
+
+	/* configure Rx MAC FIFO */
+	SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), GMF_RX_CTRL_DEF);
+
+	/* set Rx MAC FIFO Flush Mask */
+	SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), 0xffff);
+
+	/* set Rx MAC FIFO Flush Threshold */
+	SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), 0x20);
+
+	/* set to promiscuous mode */
+	Word = RxCtrl & ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+
+	/* set MAC Rx Control Register */
+	GM_OUT16(IoC, Port, GM_RX_CTRL, Word);
+
+	MacCtrl = MacCtrlSave | GM_GPCR_LOOP_ENA | GM_GPCR_FL_PASS |
+		GM_GPCR_DUP_FULL | GM_GPCR_AU_ALL_DIS;
+
+	/* enable MAC Loopback Mode */
+	GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrl);
+
+	/* enable MAC Rx/Tx */
+	GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+
+	/* clear MAC IRQ Rx Frame Complete */
+	SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FC);
+
+	/* clear MAC IRQ Tx Frame Complete */
+	SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FC);
+
+/* get current value of timestamp timer */
+	SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime);
+
+	/* check for half-duplex */
+	if ((MacCtrlSave & GM_GPCR_DUP_FULL) == 0) {
+		/* set delay to 20 ms */
+		TimeOut = HW_MS_TO_TICKS(pAC, 20);
+
+		do {
+			/* dummy read */
+			GM_IN16(IoC, Port, GM_GP_STAT, &Word);
+
+			/* get current value of timestamp timer */
+			SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
+
+			if (CurrTime >= StartTime) {
+				Delta = CurrTime - StartTime;
+			}
+			else {
+				Delta = CurrTime + ~StartTime + 1;
+			}
+
+		} while (Delta < TimeOut);
+	}
+
+	/* send one packet with a size of 64bytes from RAM buffer*/
+
+	RamAdr = pPrt->PXaQRamStart / 8;
+
+	SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_WP), RamAdr + 10);
+
+	SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_LEV), 10);
+
+	/* write 1st status quad word (packet end address in RAM, packet length */
+	SkGeRamWrite(pAC, IoC, RamAdr, (RamAdr + 9) << 16, 64, Port);
+
+	/* write 2nd status quad word */
+	SkGeRamWrite(pAC, IoC, RamAdr + 1, 0, 0, Port);
+
+	for (i = 0; i < 3; i++) {
+		/* set MAC Destination Address */
+		WordBuffer[i] = pPrt->PMacAddr[i];
+	}
+
+	WordBuffer[3] = WordBuffer[0];
+
+	/* write DA to MAC header */
+	SkGeRamWrite(pAC, IoC, RamAdr + 2, (SK_U32)(*(SK_U32 *)&WordBuffer[0]),
+		(SK_U32)(*(SK_U32 *)&WordBuffer[2]), Port);
+
+	WordBuffer[0] = WordBuffer[1];
+	WordBuffer[1] = WordBuffer[2];
+	WordBuffer[2] = 0x3200;		/* len / type field (big endian) */
+	WordBuffer[3] = 0;
+
+	/* write SA and type field to MAC header */
+	SkGeRamWrite(pAC, IoC, RamAdr + 3, (SK_U32)(*(SK_U32 *)&WordBuffer[0]),
+		(SK_U32)(*(SK_U32 *)&WordBuffer[2]), Port);
+
+	SkGeRamWrite(pAC, IoC, RamAdr + 4, 0x4c56524d,	/* "MRVL" */
+		0x00464d2d, Port);							/* "-MF"  */
+
+	for (i = 0; i < 5; i++) {
+		/* fill packet with zeroes */
+		SkGeRamWrite(pAC, IoC, RamAdr + 5 + i, 0, 0, Port);
+	}
+
+	SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_PC), 1);
+
+	/* get current value of timestamp timer */
+	SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime);
+
+	/* set timeout to 10 ms */
+	TimeOut = HW_MS_TO_TICKS(pAC, 10);
+
+	do {
+		/* get current value of timestamp timer */
+		SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
+
+		if (CurrTime >= StartTime) {
+			Delta = CurrTime - StartTime;
+		}
+		else {
+			Delta = CurrTime + ~StartTime + 1;
+		}
+
+		if (Delta > TimeOut) {
+			Rtv = 1;
+			break;
+		}
+
+		/* read the MAC Interrupt source register */
+		SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &Word);
+
+	} while ((Word & (GM_IS_TX_COMPL | GM_IS_RX_COMPL)) !=
+			 (GM_IS_TX_COMPL | GM_IS_RX_COMPL));
+
+	/* clear MAC IRQ Rx Frame Complete */
+	SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FC);
+
+	if (TimeStampDisabled) {
+		/* stop Time Stamp Timer */
+		SkMacTimeStamp(pAC, IoC, Port, SK_FALSE);
+	}
+
+	/* restore MAC General Purpose Control */
+	GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrlSave);
+
+	/* restore MAC Rx Control Register */
+	GM_OUT16(IoC, Port, GM_RX_CTRL, RxCtrl);
+
+	/* restore Rx MAC FIFO Flush Mask */
+	SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), FlushMask);
+
+	/* restore Rx MAC FIFO Flush Threshold */
+	SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), FlushTrsh);
+
+	return(Rtv);
+
+}	/* SkYuk2RestartRxBmu */
+
+
+/******************************************************************************
+ *
+ *	SkYuk2StopTx() - Stop Tx Path on Yukon-2 device family
+ *
+ * Description:
+ *	This fuction stop the transmit path of Yukon devices.
+ *	Currently this fuction is only tested for Yukon-Extreme.
+ *	Please use SkYuk2StartTx() to restart a stopped port.
+ *
+ * return:
+ *	nothing
+ */
+void SkYuk2StopTx(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index 0 or 1 */
+{
+	SK_U16 Word;
+	SK_GEPORT *pPrt;
+	SK_U64	ToutStart;
+	int		ToutCnt;
+	SK_U32	XaCsr;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Disable MAC Tx */
+	GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+	Word &= ~GM_GPCR_TX_ENA;
+	GM_OUT16(IoC, Port, GM_GP_CTRL, Word);
+
+	/* stop transmit queue */
+	SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_STOP);
+
+	/* If the BMU is in the reset state CSR_STOP will terminate immediately */
+
+	ToutStart = SkOsGetTime(pAC);
+	ToutCnt = 0;
+
+	do {
+		XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
+
+		if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
+			/*
+			 * Timeout of 1/18 second reached.
+			 * This needs to be checked at 1/18 sec only.
+			 */
+			ToutCnt++;
+
+			if (ToutCnt > 1) {
+				/*
+				 * If BMU stop doesn't terminate, we assume that
+				 * we have a stable state and can reset the BMU,
+				 * the Prefetch Unit, and RAM buffer now.
+				 */
+				break;			/* ===> leave do/while loop here */
+			}
+			/*
+			 * Cache incoherency workaround: assume a start command
+			 * has been lost while sending the frame.
+			 */
+			ToutStart = SkOsGetTime(pAC);
+
+			if ((XaCsr & BMU_STOP) != 0) {
+				SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_START);
+			}
+
+			/*
+			 * After the previous operations the X(s|a)Csr does no
+			 * longer contain the proper values
+			 */
+			XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
+		}
+	} while ((XaCsr & BMU_IDLE) != BMU_IDLE);
+
+	/* Perform a local reset of the port's Tx path */
+	/* Reset the PCI FIFO of the async Tx queue */
+	SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_RST_SET | BMU_FIFO_RST);
+
+	/* Reset the Tx prefetch units */
+	SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PXaQOff, PREF_UNIT_CTRL_REG),
+		PREF_UNIT_RST_SET);
+
+	/* Reset the RAM Buffer async Tx queue */
+	SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
+
+	if (pAC->GIni.GIAsfEnabled) {
+		/*
+		 * ASF firmware is checking start and end pointer its ASF queue
+		 * periodically.
+		 * The idea is to set the transmit queue in non operational mode when
+		 * stopping the port and to reset the ASF transmit queue when
+		 * re-starting the transmit path. ASF will reinitialize the
+		 * transmit queue by its own when trying to send the next packet.
+		 */
+		SK_OUT8(IoC, RB_ADDR((Port ? Q_ASF_T2 : Q_ASF_T1), RB_CTRL), RB_DIS_OP_MD);
+	}
+	
+	SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+}
+
+/******************************************************************************
+ *
+ *	SkYuk2StartTx() - Start Tx Path on Yukon-2 device family
+ *
+ * Description:
+ *	This function re-starts the transmit path of a Yukon-II device which was
+ *	previously stopped with SkYuk2StopTx(). Currently this fuction was only
+ *	tested for Yukon-Extreme.
+ *
+ * return:
+ *	nothing
+ */
+void SkYuk2StartTx(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index 0 or 1 */
+{
+	SK_GEPORT *pPrt;
+	SK_U16		Word;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pAC->GIni.GIAsfEnabled) {
+		/*
+		 * ASF TX queue is in non-operational state. Reset it now.
+		 * ASF firmware is checking start and end pointer its ASF queue
+		 * periodically.
+		 * The idea is to set the transmit queue in non operational mode when
+		 * stopping the port and to reset the ASF transmit queue when
+		 * re-starting the transmit path. ASF will reinitialize the
+		 * transmit queue by its own when trying to send the next packet.
+		 */
+		SK_OUT8(IoC, RB_ADDR((Port ? Q_ASF_T2 : Q_ASF_T1), RB_CTRL), RB_RST_SET);
+	}
+
+	/* configure Tx GMAC FIFO */
+	SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+	SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
+
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U ||
+		pAC->GIni.GIChipId == CHIP_ID_YUKON_EX) {
+		/* set Rx Pause Threshold */
+		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_LP_THR), (SK_U16)SK_ECU_LLPP);
+		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_UP_THR), (SK_U16)SK_ECU_ULPP);
+
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EX &&
+			pAC->GIni.GIChipRev != CHIP_REV_YU_EX_A0) {
+			/* Yukon-Extreme BO and further Extreme devices */
+			/* enable Store & Forward mode for TX */
+			SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TX_STFW_ENA);
+		}
+		else {
+			if (pAC->GIni.GP[Port].PPortUsage == SK_JUMBO_LINK) {
+				/* set Tx GMAC FIFO Almost Empty Threshold */
+				SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR),
+					(SK_ECU_JUMBO_WM << 16) | (SK_U16)SK_ECU_AE_THR);
+				/* disable Store & Forward mode for TX */
+				SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TX_STFW_DIS);
+			}
+		}
+	}
+
+	DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
+		pPrt->PXaQRamEnd, SK_TX_RAM_Q);
+
+	/*
+	 * Tx Queue: Release all local resets if the queue is used !
+	 * 		set watermark
+	 */
+
+	if (pPrt->PXAQSize != 0) {
+
+		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_CLR_RESET);
+		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_OPER_INIT);
+		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_FIFO_OP_ON);
+
+		if (HW_FEATURE(pAC, HWF_TX_IP_ID_INCR_ON)) {
+			/* Enable Tx IP ID Increment */
+			SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_TX_IPIDINCR_ON);
+		}
+
+		SK_OUT16(IoC, Q_ADDR(pPrt->PXaQOff, Q_WM), SK_BMU_TX_WM);
+	}
+
+	/* WA for dev. #4.209 */
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U &&
+		pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A1) {
+		/* enable/disable Store & Forward mode for TX */
+		SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
+			pPrt->PLinkSpeedUsed != (SK_U8)SK_LSPEED_STAT_1000MBPS ?
+			TX_STFW_ENA : TX_STFW_DIS);
+	}
+
+	/* Enable MAC Tx */
+	GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+	Word |= GM_GPCR_TX_ENA;
+	GM_OUT16(IoC, Port, GM_GP_CTRL, Word);
+}
+#endif /* YUK2 && !SK_SLIM */
+
+/* End of File */
+
diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
new file mode 100755
index 0000000..bce42ac
--- /dev/null
+++ b/drivers/net/sk98lin/skgemib.c
@@ -0,0 +1,1282 @@
+/*****************************************************************************
+ *
+ * Name:	skgemib.c
+ * Project:	Gigabit Ethernet Adapters, PNMI-Module
+ * Version:	$Revision: 2.11 $
+ * Date:	$Date: 2007/03/28 13:43:43 $
+ * Purpose:	Private Network Management Interface Management Database
+ *
+ ****************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ * PRIVATE OID handler function prototypes
+ */
+PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action,
+	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
+	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int* pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+
+#ifdef SK_POWER_MGMT
+PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+#endif /* SK_POWER_MGMT */
+
+#ifdef SK_DIAG_SUPPORT
+PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+#endif /* SK_DIAG_SUPPORT */
+
+#ifdef SK_ASF
+PNMI_STATIC int Asf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+	unsigned int TableIndex, SK_U32 NetIndex);
+#endif /* SK_ASF */
+
+
+/* defines *******************************************************************/
+#define ID_TABLE_SIZE (sizeof(IdTable)/sizeof(IdTable[0]))
+
+
+/* global variables **********************************************************/
+
+/*
+ * Table to correlate OID with handler function and index to
+ * hardware register stored in StatAddress if applicable.
+ */
+PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
+	{OID_GEN_XMIT_OK,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
+	{OID_GEN_RCV_OK,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
+	{OID_GEN_XMIT_ERROR,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, General, 0},
+	{OID_GEN_RCV_ERROR,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, General, 0},
+	{OID_GEN_RCV_NO_BUFFER,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, General, 0},
+	{OID_GEN_DIRECTED_FRAMES_XMIT,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
+	{OID_GEN_MULTICAST_FRAMES_XMIT,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
+	{OID_GEN_BROADCAST_FRAMES_XMIT,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
+	{OID_GEN_DIRECTED_FRAMES_RCV,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
+	{OID_GEN_MULTICAST_FRAMES_RCV,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
+	{OID_GEN_BROADCAST_FRAMES_RCV,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
+	{OID_GEN_RCV_CRC_ERROR,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
+	{OID_GEN_TRANSMIT_QUEUE_LENGTH,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, General, 0},
+	{OID_802_3_PERMANENT_ADDRESS,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, 0},
+	{OID_802_3_CURRENT_ADDRESS,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, 0},
+	{OID_802_3_RCV_ERROR_ALIGNMENT,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
+	{OID_802_3_XMIT_ONE_COLLISION,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
+	{OID_802_3_XMIT_MORE_COLLISIONS,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
+	{OID_802_3_XMIT_DEFERRED,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
+	{OID_802_3_XMIT_MAX_COLLISIONS,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
+	{OID_802_3_RCV_OVERRUN,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
+	{OID_802_3_XMIT_UNDERRUN,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
+	{OID_802_3_XMIT_TIMES_CRS_LOST,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
+	{OID_802_3_XMIT_LATE_COLLISIONS,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
+#ifdef SK_POWER_MGMT
+	{OID_PNP_CAPABILITIES,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, PowerManagement, 0},
+	{OID_PNP_SET_POWER,
+		0,
+		0,
+		0,
+		SK_PNMI_WO, PowerManagement, 0},
+	{OID_PNP_QUERY_POWER,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, PowerManagement, 0},
+	{OID_PNP_ADD_WAKE_UP_PATTERN,
+		0,
+		0,
+		0,
+		SK_PNMI_WO, PowerManagement, 0},
+	{OID_PNP_REMOVE_WAKE_UP_PATTERN,
+		0,
+		0,
+		0,
+		SK_PNMI_WO, PowerManagement, 0},
+	{OID_PNP_ENABLE_WAKE_UP,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, PowerManagement, 0},
+#endif /* SK_POWER_MGMT */
+#ifdef SK_DIAG_SUPPORT
+	{OID_SKGE_DIAG_MODE,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, DiagActions, 0},
+#endif /* SK_DIAG_SUPPORT */
+#ifdef SK_ASF
+	{OID_SKGE_ASF,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_STORE_CONFIG,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_ENA,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_RETRANS,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_RETRANS_INT,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_HB_ENA,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_HB_INT,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_WD_ENA,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_WD_TIME,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_IP_SOURCE,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_MAC_SOURCE,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_IP_DEST,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_MAC_DEST,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_COMMUNITY_NAME,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_RSP_ENA,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_RETRANS_COUNT_MIN,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_RETRANS_COUNT_MAX,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_RETRANS_INT_MIN,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_RETRANS_INT_MAX,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_HB_INT_MIN,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_HB_INT_MAX,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_WD_TIME_MIN,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_WD_TIME_MAX,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_HB_CAP,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_WD_TIMER_RES,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_GUID,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_KEY_OP,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_KEY_ADM,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_KEY_GEN,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_CAP,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_PAR_1,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_OVERALL_OID,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_FWVER_OID,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Asf, 0},
+	{OID_SKGE_ASF_ACPI_OID,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Asf, 0},
+	{OID_SKGE_ASF_SMBUS_OID,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Asf, 0},
+	{OID_SKGE_ASF_FW_REMOVE,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, Asf, 0},
+	{OID_SKGE_ASF_CHECK_SPI,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Asf, 0},
+#endif /* SK_ASF */
+	{OID_SKGE_MDB_VERSION,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(MgmtDBVersion),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_SUPPORTED_LIST,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_ALL_DATA,
+		0,
+		0,
+		0,
+		SK_PNMI_RW, OidStruct, 0},
+	{OID_SKGE_VPD_FREE_BYTES,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(VpdFreeBytes),
+		SK_PNMI_RO, Vpd, 0},
+	{OID_SKGE_VPD_ENTRIES_LIST,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(VpdEntriesList),
+		SK_PNMI_RO, Vpd, 0},
+	{OID_SKGE_VPD_ENTRIES_NUMBER,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(VpdEntriesNumber),
+		SK_PNMI_RO, Vpd, 0},
+	{OID_SKGE_VPD_KEY,
+		SK_PNMI_VPD_ENTRIES,
+		sizeof(SK_PNMI_VPD),
+		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
+		SK_PNMI_RO, Vpd, 0},
+	{OID_SKGE_VPD_VALUE,
+		SK_PNMI_VPD_ENTRIES,
+		sizeof(SK_PNMI_VPD),
+		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
+		SK_PNMI_RO, Vpd, 0},
+	{OID_SKGE_VPD_ACCESS,
+		SK_PNMI_VPD_ENTRIES,
+		sizeof(SK_PNMI_VPD),
+		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
+		SK_PNMI_RO, Vpd, 0},
+	{OID_SKGE_VPD_ACTION,
+		SK_PNMI_VPD_ENTRIES,
+		sizeof(SK_PNMI_VPD),
+		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
+		SK_PNMI_RW, Vpd, 0},
+	{OID_SKGE_PORT_NUMBER,		
+		1,
+		0,
+		SK_PNMI_MAI_OFF(PortNumber),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_DEVICE_TYPE,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(DeviceType),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_DRIVER_DESCR,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(DriverDescr),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_DRIVER_VERSION,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(DriverVersion),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_DRIVER_RELDATE,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(DriverReleaseDate),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_DRIVER_FILENAME,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(DriverFileName),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_HW_DESCR,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(HwDescr),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_HW_VERSION,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(HwVersion),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_CHIPSET,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(Chipset),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_CHIPID,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(ChipId),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_RAMSIZE,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RamSize),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_VAUXAVAIL,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(VauxAvail),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_ACTION,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(Action),
+		SK_PNMI_RW, Perform, 0},
+	{OID_SKGE_RESULT,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TestResult),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_BUS_TYPE,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(BusType),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_BUS_SPEED,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(BusSpeed),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_BUS_WIDTH,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(BusWidth),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_TX_SW_QUEUE_LEN,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TxSwQueueLen),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_TX_SW_QUEUE_MAX,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TxSwQueueMax),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_TX_RETRY,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TxRetryCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_RX_INTR_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RxIntrCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_TX_INTR_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TxIntrCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_RX_NO_BUF_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RxNoBufCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_TX_NO_BUF_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TxNoBufCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_TX_USED_DESCR_NO,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TxUsedDescrNo),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_RX_DELIVERED_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RxDeliveredCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_RX_OCTETS_DELIV_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_RX_HW_ERROR_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RxHwErrorsCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_TX_HW_ERROR_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TxHwErrorsCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_IN_ERRORS_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(InErrorsCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_OUT_ERROR_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(OutErrorsCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_ERR_RECOVERY_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(ErrRecoveryCts),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_SYSUPTIME,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(SysUpTime),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_SENSOR_NUMBER,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(SensorNumber),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_SENSOR_INDEX,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_DESCR,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_TYPE,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_VALUE,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_WAR_THRES_LOW,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_WAR_THRES_UPP,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_ERR_THRES_LOW,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_ERR_THRES_UPP,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_STATUS,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_WAR_CTS,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_ERR_CTS,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_WAR_TIME,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_SENSOR_ERR_TIME,
+		SK_PNMI_SENSOR_ENTRIES,
+		sizeof(SK_PNMI_SENSOR),
+		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
+		SK_PNMI_RO, SensorStat, 0},
+	{OID_SKGE_CHKSM_NUMBER,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(ChecksumNumber),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_CHKSM_RX_OK_CTS,
+		SKCS_NUM_PROTOCOLS,
+		sizeof(SK_PNMI_CHECKSUM),
+		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
+		SK_PNMI_RO, CsumStat, 0},
+	{OID_SKGE_CHKSM_RX_UNABLE_CTS,
+		SKCS_NUM_PROTOCOLS,
+		sizeof(SK_PNMI_CHECKSUM),
+		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
+		SK_PNMI_RO, CsumStat, 0},
+	{OID_SKGE_CHKSM_RX_ERR_CTS,
+		SKCS_NUM_PROTOCOLS,
+		sizeof(SK_PNMI_CHECKSUM),
+		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
+		SK_PNMI_RO, CsumStat, 0},
+	{OID_SKGE_CHKSM_TX_OK_CTS,
+		SKCS_NUM_PROTOCOLS,
+		sizeof(SK_PNMI_CHECKSUM),
+		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
+		SK_PNMI_RO, CsumStat, 0},
+	{OID_SKGE_CHKSM_TX_UNABLE_CTS,
+		SKCS_NUM_PROTOCOLS,
+		sizeof(SK_PNMI_CHECKSUM),
+		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
+		SK_PNMI_RO, CsumStat, 0},
+	{OID_SKGE_STAT_TX,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
+	{OID_SKGE_STAT_TX_OCTETS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
+	{OID_SKGE_STAT_TX_BROADCAST,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
+	{OID_SKGE_STAT_TX_MULTICAST,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
+	{OID_SKGE_STAT_TX_UNICAST,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
+	{OID_SKGE_STAT_TX_LONGFRAMES,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
+	{OID_SKGE_STAT_TX_BURST,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
+	{OID_SKGE_STAT_TX_PFLOWC,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
+	{OID_SKGE_STAT_TX_FLOWC,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
+	{OID_SKGE_STAT_TX_SINGLE_COL,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
+	{OID_SKGE_STAT_TX_MULTI_COL,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
+	{OID_SKGE_STAT_TX_EXCESS_COL,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
+	{OID_SKGE_STAT_TX_LATE_COL,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
+	{OID_SKGE_STAT_TX_DEFFERAL,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
+	{OID_SKGE_STAT_TX_EXCESS_DEF,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
+	{OID_SKGE_STAT_TX_UNDERRUN,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
+	{OID_SKGE_STAT_TX_CARRIER,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
+/*	{OID_SKGE_STAT_TX_UTIL,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
+		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
+	{OID_SKGE_STAT_TX_64,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
+	{OID_SKGE_STAT_TX_127,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
+	{OID_SKGE_STAT_TX_255,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
+	{OID_SKGE_STAT_TX_511,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
+	{OID_SKGE_STAT_TX_1023,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
+	{OID_SKGE_STAT_TX_MAX,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
+	{OID_SKGE_STAT_TX_SYNC,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
+	{OID_SKGE_STAT_TX_SYNC_OCTETS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
+	{OID_SKGE_STAT_RX,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
+	{OID_SKGE_STAT_RX_OCTETS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
+	{OID_SKGE_STAT_RX_BROADCAST,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
+	{OID_SKGE_STAT_RX_MULTICAST,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
+	{OID_SKGE_STAT_RX_UNICAST,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
+	{OID_SKGE_STAT_RX_LONGFRAMES,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
+	{OID_SKGE_STAT_RX_PFLOWC,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
+	{OID_SKGE_STAT_RX_FLOWC,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
+	{OID_SKGE_STAT_RX_PFLOWC_ERR,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
+	{OID_SKGE_STAT_RX_FLOWC_UNKWN,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
+	{OID_SKGE_STAT_RX_BURST,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
+	{OID_SKGE_STAT_RX_MISSED,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
+	{OID_SKGE_STAT_RX_FRAMING,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
+	{OID_SKGE_STAT_RX_OVERFLOW,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
+	{OID_SKGE_STAT_RX_JABBER,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
+	{OID_SKGE_STAT_RX_CARRIER,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
+	{OID_SKGE_STAT_RX_IR_LENGTH,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
+	{OID_SKGE_STAT_RX_SYMBOL,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
+	{OID_SKGE_STAT_RX_SHORTS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
+	{OID_SKGE_STAT_RX_RUNT,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
+	{OID_SKGE_STAT_RX_CEXT,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
+	{OID_SKGE_STAT_RX_TOO_LONG,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
+	{OID_SKGE_STAT_RX_FCS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
+/*	{OID_SKGE_STAT_RX_UTIL,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
+		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
+	{OID_SKGE_STAT_RX_64,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
+	{OID_SKGE_STAT_RX_127,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
+	{OID_SKGE_STAT_RX_255,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
+	{OID_SKGE_STAT_RX_511,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
+	{OID_SKGE_STAT_RX_1023,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
+	{OID_SKGE_STAT_RX_MAX,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_STAT),
+		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
+		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
+	{OID_SKGE_PHYS_CUR_ADDR,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
+		SK_PNMI_RW, Addr, 0},
+	{OID_SKGE_PHYS_FAC_ADDR,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
+		SK_PNMI_RO, Addr, 0},
+	{OID_SKGE_PMD,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_CONNECTOR,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_PHY_TYPE,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
+		SK_PNMI_RO, MacPrivateConf, 0},
+#ifdef SK_PHY_LP_MODE
+		{OID_SKGE_PHY_LP_MODE,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyMode),
+		SK_PNMI_RW, MacPrivateConf, 0},
+#endif
+	{OID_SKGE_LINK_CAP,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_LINK_MODE,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
+		SK_PNMI_RW, MacPrivateConf, 0},
+	{OID_SKGE_LINK_MODE_STATUS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_LINK_STATUS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_FLOWCTRL_CAP,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_FLOWCTRL_MODE,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
+		SK_PNMI_RW, MacPrivateConf, 0},
+	{OID_SKGE_FLOWCTRL_STATUS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_PHY_OPERATION_CAP,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_PHY_OPERATION_MODE,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
+		SK_PNMI_RW, MacPrivateConf, 0},
+	{OID_SKGE_PHY_OPERATION_STATUS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_SPEED_CAP,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_SPEED_MODE,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode),
+		SK_PNMI_RW, MacPrivateConf, 0},
+	{OID_SKGE_SPEED_STATUS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_CONF),
+		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus),
+		SK_PNMI_RO, MacPrivateConf, 0},
+	{OID_SKGE_TRAP,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(Trap),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_TRAP_NUMBER,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(TrapNumber),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_RLMT_MODE,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtMode),
+		SK_PNMI_RW, Rlmt, 0},
+	{OID_SKGE_RLMT_PORT_NUMBER,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtPortNumber),
+		SK_PNMI_RO, Rlmt, 0},
+	{OID_SKGE_RLMT_PORT_ACTIVE,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtPortActive),
+		SK_PNMI_RO, Rlmt, 0},
+	{OID_SKGE_RLMT_PORT_PREFERRED,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtPortPreferred),
+		SK_PNMI_RW, Rlmt, 0},
+	{OID_SKGE_RLMT_CHANGE_CTS,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtChangeCts),
+		SK_PNMI_RO, Rlmt, 0},
+	{OID_SKGE_RLMT_CHANGE_TIME,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtChangeTime),
+		SK_PNMI_RO, Rlmt, 0},
+	{OID_SKGE_RLMT_CHANGE_ESTIM,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtChangeEstimate),
+		SK_PNMI_RO, Rlmt, 0},
+	{OID_SKGE_RLMT_CHANGE_THRES,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtChangeThreshold),
+		SK_PNMI_RW, Rlmt, 0},
+	{OID_SKGE_RLMT_PORT_INDEX,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_RLMT),
+		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
+		SK_PNMI_RO, RlmtStat, 0},
+	{OID_SKGE_RLMT_STATUS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_RLMT),
+		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
+		SK_PNMI_RO, RlmtStat, 0},
+	{OID_SKGE_RLMT_TX_HELLO_CTS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_RLMT),
+		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
+		SK_PNMI_RO, RlmtStat, 0},
+	{OID_SKGE_RLMT_RX_HELLO_CTS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_RLMT),
+		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
+		SK_PNMI_RO, RlmtStat, 0},
+	{OID_SKGE_RLMT_TX_SP_REQ_CTS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_RLMT),
+		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
+		SK_PNMI_RO, RlmtStat, 0},
+	{OID_SKGE_RLMT_RX_SP_CTS,
+		SK_PNMI_MAC_ENTRIES,
+		sizeof(SK_PNMI_RLMT),
+		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
+		SK_PNMI_RO, RlmtStat, 0},
+	{OID_SKGE_RLMT_MONITOR_NUMBER,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(RlmtMonitorNumber),
+		SK_PNMI_RO, General, 0},
+	{OID_SKGE_RLMT_MONITOR_INDEX,
+		SK_PNMI_MONITOR_ENTRIES,
+		sizeof(SK_PNMI_RLMT_MONITOR),
+		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
+		SK_PNMI_RO, Monitor, 0},
+	{OID_SKGE_RLMT_MONITOR_ADDR,
+		SK_PNMI_MONITOR_ENTRIES,
+		sizeof(SK_PNMI_RLMT_MONITOR),
+		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
+		SK_PNMI_RO, Monitor, 0},
+	{OID_SKGE_RLMT_MONITOR_ERRS,
+		SK_PNMI_MONITOR_ENTRIES,
+		sizeof(SK_PNMI_RLMT_MONITOR),
+		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
+		SK_PNMI_RO, Monitor, 0},
+	{OID_SKGE_RLMT_MONITOR_TIMESTAMP,
+		SK_PNMI_MONITOR_ENTRIES,
+		sizeof(SK_PNMI_RLMT_MONITOR),
+		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
+		SK_PNMI_RO, Monitor, 0},
+	{OID_SKGE_RLMT_MONITOR_ADMIN,
+		SK_PNMI_MONITOR_ENTRIES,
+		sizeof(SK_PNMI_RLMT_MONITOR),
+		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
+		SK_PNMI_RW, Monitor, 0},
+	{OID_SKGE_MTU,
+		1,
+		0,
+		SK_PNMI_MAI_OFF(MtuSize),
+		SK_PNMI_RW, MacPrivateConf, 0},
+	{OID_SKGE_VCT_GET,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Vct, 0},
+	{OID_SKGE_VCT_SET,
+		0,
+		0,
+		0,
+		SK_PNMI_WO, Vct, 0},
+	{OID_SKGE_VCT_STATUS,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Vct, 0},
+	{OID_SKGE_VCT_CAPABILITIES,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, Vct, 0},
+	{OID_SKGE_BOARDLEVEL,
+		0,
+		0,
+		0,
+		SK_PNMI_RO, General, 0},
+};
+
diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
new file mode 100755
index 0000000..cb14805
--- /dev/null
+++ b/drivers/net/sk98lin/skgepnmi.c
@@ -0,0 +1,8463 @@
+/*****************************************************************************
+ *
+ * Name:	skgepnmi.c
+ * Project:	Gigabit Ethernet Adapters, PNMI-Module
+ * Version:	$Revision: 2.29 $
+ * Date:	$Date: 2007/09/03 14:16:57 $
+ * Purpose:	Private Network Management Interface
+ *
+ ****************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skgepnmi.c,v 2.29 2007/09/03 14:16:57 mkunz Exp $ (C) Marvell.";
+#endif
+
+#include "h/skdrv1st.h"
+#include "h/sktypes.h"
+#include "h/xmac_ii.h"
+#include "h/skdebug.h"
+#include "h/skqueue.h"
+#include "h/skgepnmi.h"
+#include "h/skgesirq.h"
+#include "h/skcsum.h"
+#include "h/skvpd.h"
+#include "h/skgehw.h"
+#include "h/sky2le.h"
+#include "h/skgeinit.h"
+#include "h/skdrv2nd.h"
+#include "h/skgepnm2.h"
+#ifdef SK_POWER_MGMT
+#include "h/skgepmgt.h"
+#endif /* SK_POWER_MGMT */
+
+/* defines *******************************************************************/
+
+#ifndef DEBUG
+#define PNMI_STATIC	static
+#else	/* DEBUG */
+#define PNMI_STATIC
+#endif /* DEBUG */
+
+/*
+ * Private Function prototypes
+ */
+
+PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
+	PhysPortIndex);
+PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
+	PhysPortIndex);
+PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
+PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
+PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
+	unsigned int PhysPortIndex, unsigned int StatIndex);
+PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
+	unsigned int StatIndex, SK_U32 NetIndex);
+PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
+PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
+	unsigned int *pEntries);
+PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
+	unsigned int KeyArrLen, unsigned int *pKeyNo);
+PNMI_STATIC int LookupId(SK_U32 Id);
+PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
+	unsigned int LastMac);
+PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
+	unsigned int *pLen, SK_U32 NetIndex);
+PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
+	char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
+PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
+	unsigned int PortIndex);
+PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
+	unsigned int SensorIndex);
+PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
+PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
+PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
+PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
+PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
+PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
+PNMI_STATIC void VctGetResults(SK_AC *, SK_IOC, SK_U32);
+
+/*
+ * Table to correlate OID with handler function and index to
+ * hardware register stored in StatAddress if applicable.
+ */
+#include "skgemib.c"
+
+/* global variables **********************************************************/
+
+/*
+ * Overflow status register bit table and corresponding counter
+ * dependent on MAC type - the number relates to the size of overflow
+ * mask returned by the pFnMacOverflow function
+ */
+PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
+/* Bit0  */	{ SK_PNMI_HTX, 				SK_PNMI_HTX_UNICAST},
+/* Bit1  */	{ SK_PNMI_HTX_OCTETHIGH, 	SK_PNMI_HTX_BROADCAST},
+/* Bit2  */	{ SK_PNMI_HTX_OCTETLOW, 	SK_PNMI_HTX_PMACC},
+/* Bit3  */	{ SK_PNMI_HTX_BROADCAST, 	SK_PNMI_HTX_MULTICAST},
+/* Bit4  */	{ SK_PNMI_HTX_MULTICAST, 	SK_PNMI_HTX_OCTETLOW},
+/* Bit5  */	{ SK_PNMI_HTX_UNICAST, 		SK_PNMI_HTX_OCTETHIGH},
+/* Bit6  */	{ SK_PNMI_HTX_LONGFRAMES, 	SK_PNMI_HTX_64},
+/* Bit7  */	{ SK_PNMI_HTX_BURST, 		SK_PNMI_HTX_127},
+/* Bit8  */	{ SK_PNMI_HTX_PMACC, 		SK_PNMI_HTX_255},
+/* Bit9  */	{ SK_PNMI_HTX_MACC, 		SK_PNMI_HTX_511},
+/* Bit10 */	{ SK_PNMI_HTX_SINGLE_COL, 	SK_PNMI_HTX_1023},
+/* Bit11 */	{ SK_PNMI_HTX_MULTI_COL, 	SK_PNMI_HTX_MAX},
+/* Bit12 */	{ SK_PNMI_HTX_EXCESS_COL, 	SK_PNMI_HTX_LONGFRAMES},
+/* Bit13 */	{ SK_PNMI_HTX_LATE_COL, 	SK_PNMI_HTX_RESERVED},
+/* Bit14 */	{ SK_PNMI_HTX_DEFFERAL, 	SK_PNMI_HTX_COL},
+/* Bit15 */	{ SK_PNMI_HTX_EXCESS_DEF, 	SK_PNMI_HTX_LATE_COL},
+/* Bit16 */	{ SK_PNMI_HTX_UNDERRUN, 	SK_PNMI_HTX_EXCESS_COL},
+/* Bit17 */	{ SK_PNMI_HTX_CARRIER, 		SK_PNMI_HTX_MULTI_COL},
+/* Bit18 */	{ SK_PNMI_HTX_UTILUNDER, 	SK_PNMI_HTX_SINGLE_COL},
+/* Bit19 */	{ SK_PNMI_HTX_UTILOVER, 	SK_PNMI_HTX_UNDERRUN},
+/* Bit20 */	{ SK_PNMI_HTX_64, 			SK_PNMI_HTX_RESERVED},
+/* Bit21 */	{ SK_PNMI_HTX_127, 			SK_PNMI_HTX_RESERVED},
+/* Bit22 */	{ SK_PNMI_HTX_255, 			SK_PNMI_HTX_RESERVED},
+/* Bit23 */	{ SK_PNMI_HTX_511, 			SK_PNMI_HTX_RESERVED},
+/* Bit24 */	{ SK_PNMI_HTX_1023, 		SK_PNMI_HTX_RESERVED},
+/* Bit25 */	{ SK_PNMI_HTX_MAX, 			SK_PNMI_HTX_RESERVED},
+/* Bit26 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+/* Bit27 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+/* Bit28 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+/* Bit29 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+/* Bit30 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+/* Bit31 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+/* Bit32 */	{ SK_PNMI_HRX, 				SK_PNMI_HRX_UNICAST},
+/* Bit33 */	{ SK_PNMI_HRX_OCTETHIGH, 	SK_PNMI_HRX_BROADCAST},
+/* Bit34 */	{ SK_PNMI_HRX_OCTETLOW, 	SK_PNMI_HRX_PMACC},
+/* Bit35 */	{ SK_PNMI_HRX_BROADCAST, 	SK_PNMI_HRX_MULTICAST},
+/* Bit36 */	{ SK_PNMI_HRX_MULTICAST, 	SK_PNMI_HRX_FCS},
+/* Bit37 */	{ SK_PNMI_HRX_UNICAST, 		SK_PNMI_HRX_RESERVED},
+/* Bit38 */	{ SK_PNMI_HRX_PMACC, 		SK_PNMI_HRX_OCTETLOW},
+/* Bit39 */	{ SK_PNMI_HRX_MACC, 		SK_PNMI_HRX_OCTETHIGH},
+/* Bit40 */	{ SK_PNMI_HRX_PMACC_ERR, 	SK_PNMI_HRX_BADOCTETLOW},
+/* Bit41 */	{ SK_PNMI_HRX_MACC_UNKWN,	SK_PNMI_HRX_BADOCTETHIGH},
+/* Bit42 */	{ SK_PNMI_HRX_BURST, 		SK_PNMI_HRX_UNDERSIZE},
+/* Bit43 */	{ SK_PNMI_HRX_MISSED, 		SK_PNMI_HRX_RUNT},
+/* Bit44 */	{ SK_PNMI_HRX_FRAMING, 		SK_PNMI_HRX_64},
+/* Bit45 */	{ SK_PNMI_HRX_OVERFLOW, 	SK_PNMI_HRX_127},
+/* Bit46 */	{ SK_PNMI_HRX_JABBER, 		SK_PNMI_HRX_255},
+/* Bit47 */	{ SK_PNMI_HRX_CARRIER, 		SK_PNMI_HRX_511},
+/* Bit48 */	{ SK_PNMI_HRX_IRLENGTH, 	SK_PNMI_HRX_1023},
+/* Bit49 */	{ SK_PNMI_HRX_SYMBOL, 		SK_PNMI_HRX_MAX},
+/* Bit50 */	{ SK_PNMI_HRX_SHORTS, 		SK_PNMI_HRX_LONGFRAMES},
+/* Bit51 */	{ SK_PNMI_HRX_RUNT, 		SK_PNMI_HRX_TOO_LONG},
+/* Bit52 */	{ SK_PNMI_HRX_TOO_LONG, 	SK_PNMI_HRX_JABBER},
+/* Bit53 */	{ SK_PNMI_HRX_FCS, 			SK_PNMI_HRX_RESERVED},
+/* Bit54 */	{ SK_PNMI_HRX_RESERVED, 	SK_PNMI_HRX_OVERFLOW},
+/* Bit55 */	{ SK_PNMI_HRX_CEXT, 		SK_PNMI_HRX_RESERVED},
+/* Bit56 */	{ SK_PNMI_HRX_UTILUNDER, 	SK_PNMI_HRX_RESERVED},
+/* Bit57 */	{ SK_PNMI_HRX_UTILOVER, 	SK_PNMI_HRX_RESERVED},
+/* Bit58 */	{ SK_PNMI_HRX_64, 			SK_PNMI_HRX_RESERVED},
+/* Bit59 */	{ SK_PNMI_HRX_127, 			SK_PNMI_HRX_RESERVED},
+/* Bit60 */	{ SK_PNMI_HRX_255, 			SK_PNMI_HRX_RESERVED},
+/* Bit61 */	{ SK_PNMI_HRX_511, 			SK_PNMI_HRX_RESERVED},
+/* Bit62 */	{ SK_PNMI_HRX_1023, 		SK_PNMI_HRX_RESERVED},
+/* Bit63 */	{ SK_PNMI_HRX_MAX, 			SK_PNMI_HRX_RESERVED}
+};
+
+/*
+ * Table for hardware register saving on resets and port switches
+ */
+PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
+	/* SK_PNMI_HTX */
+	{{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_OCTETHIGH */
+	{{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
+	/* SK_PNMI_HTX_OCTETLOW */
+	{{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
+	/* SK_PNMI_HTX_BROADCAST */
+	{{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
+	/* SK_PNMI_HTX_MULTICAST */
+	{{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
+	/* SK_PNMI_HTX_UNICAST */
+	{{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
+	/* SK_PNMI_HTX_BURST */
+	{{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_PMACC */
+	{{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
+	/* SK_PNMI_HTX_MACC */
+	{{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_COL */
+	{{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
+	/* SK_PNMI_HTX_SINGLE_COL */
+	{{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
+	/* SK_PNMI_HTX_MULTI_COL */
+	{{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
+	/* SK_PNMI_HTX_EXCESS_COL */
+	{{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
+	/* SK_PNMI_HTX_LATE_COL */
+	{{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
+	/* SK_PNMI_HTX_DEFFERAL */
+	{{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_EXCESS_DEF */
+	{{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_UNDERRUN */
+	{{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
+	/* SK_PNMI_HTX_CARRIER */
+	{{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_UTILUNDER */
+	{{0, SK_FALSE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_UTILOVER */
+	{{0, SK_FALSE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_64 */
+	{{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
+	/* SK_PNMI_HTX_127 */
+	{{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
+	/* SK_PNMI_HTX_255 */
+	{{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
+	/* SK_PNMI_HTX_511 */
+	{{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
+	/* SK_PNMI_HTX_1023 */
+	{{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
+	/* SK_PNMI_HTX_MAX */
+	{{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
+	/* SK_PNMI_HTX_LONGFRAMES  */
+	{{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
+	/* SK_PNMI_HTX_SYNC */
+	{{0, SK_FALSE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_SYNC_OCTET */
+	{{0, SK_FALSE}, {0, SK_FALSE}},
+	/* SK_PNMI_HTX_RESERVED */
+	{{0, SK_FALSE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX */
+	{{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_OCTETHIGH */
+	{{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
+	/* SK_PNMI_HRX_OCTETLOW */
+	{{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
+	/* SK_PNMI_HRX_BADOCTETHIGH */
+	{{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
+	/* SK_PNMI_HRX_BADOCTETLOW */
+	{{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
+	/* SK_PNMI_HRX_BROADCAST */
+	{{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
+	/* SK_PNMI_HRX_MULTICAST */
+	{{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
+	/* SK_PNMI_HRX_UNICAST */
+	{{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
+	/* SK_PNMI_HRX_PMACC */
+	{{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
+	/* SK_PNMI_HRX_MACC */
+	{{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_PMACC_ERR */
+	{{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_MACC_UNKWN */
+	{{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_BURST */
+	{{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_MISSED */
+	{{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_FRAMING */
+	{{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_UNDERSIZE */
+	{{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
+	/* SK_PNMI_HRX_OVERFLOW */
+	{{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
+	/* SK_PNMI_HRX_JABBER */
+	{{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
+	/* SK_PNMI_HRX_CARRIER */
+	{{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_IRLENGTH */
+	{{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_SYMBOL */
+	{{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_SHORTS */
+	{{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_RUNT */
+	{{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
+	/* SK_PNMI_HRX_TOO_LONG */
+	{{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
+	/* SK_PNMI_HRX_FCS */
+	{{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
+	/* SK_PNMI_HRX_CEXT */
+	{{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_UTILUNDER */
+	{{0, SK_FALSE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_UTILOVER */
+	{{0, SK_FALSE}, {0, SK_FALSE}},
+	/* SK_PNMI_HRX_64 */
+	{{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
+	/* SK_PNMI_HRX_127 */
+	{{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
+	/* SK_PNMI_HRX_255 */
+	{{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
+	/* SK_PNMI_HRX_511 */
+	{{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
+	/* SK_PNMI_HRX_1023 */
+	{{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
+	/* SK_PNMI_HRX_MAX */
+	{{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
+	/* SK_PNMI_HRX_LONGFRAMES */
+	{{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
+	/* SK_PNMI_HRX_RESERVED */
+	{{0, SK_FALSE}, {0, SK_FALSE}}
+};
+
+
+/*****************************************************************************
+ *
+ * Public functions
+ *
+ */
+
+/*****************************************************************************
+ *
+ * SkPnmiInit - Init function of PNMI
+ *
+ * Description:
+ *	SK_INIT_DATA: Initializes the data structures
+ *	SK_INIT_IO:   Resets the XMAC statistics, determines the device and
+ *	              connector type.
+ *	SK_INIT_RUN:  Starts a timer event for port switch per hour
+ *	              calculation.
+ *
+ * Returns:
+ *	Always 0
+ */
+int SkPnmiInit(
+SK_AC	*pAC,		/* Pointer to adapter context */
+SK_IOC	IoC,		/* IO context handle */
+int		Level)		/* Initialization level */
+{
+	unsigned int	PortMax;	/* Number of ports */
+	unsigned int	PortIndex;	/* Current port index in loop */
+	SK_EVPARA		EventParam;	/* Event struct for timer event */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+		("PNMI: SkPnmiInit: Called, level=%d\n", Level));
+
+	switch (Level) {
+
+	case SK_INIT_DATA:
+		SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
+
+		pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
+		pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+		pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
+
+		for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
+
+			pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
+			pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
+
+			/* Initialize DSP variables for Vct() to 0xff => Never written! */		
+			pAC->GIni.GP[PortIndex].PCableLen = 0xff;
+			pAC->Pnmi.VctBackup[PortIndex].CableLen = 0xff;
+		}
+
+#ifdef SK_PNMI_CHECK
+		if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
+					   ("CounterOffset struct size (%d) differs from"
+						"SK_PNMI_MAX_IDX (%d)\n",
+						SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
+		}
+
+		if (SK_PNMI_MAX_IDX !=
+			(sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG);
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
+					   ("StatAddr table size (%d) differs from "
+						"SK_PNMI_MAX_IDX (%d)\n",
+						(sizeof(StatAddr) /
+						 (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)),
+						 SK_PNMI_MAX_IDX));
+		}
+#endif /* SK_PNMI_CHECK */
+		break;
+
+	case SK_INIT_IO:
+
+		/* Reset MAC counters. */
+		PortMax = pAC->GIni.GIMacsFound;
+
+		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
+
+			pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
+		}
+
+		/* Get PCI bus speed. */
+		if (pAC->GIni.GIPciClock66) {
+
+			pAC->Pnmi.PciBusSpeed = 66;
+		}
+		else {
+			pAC->Pnmi.PciBusSpeed = 33;
+		}
+
+		/* Get PCI bus width. */
+		if (pAC->GIni.GIPciSlot64) {
+
+			pAC->Pnmi.PciBusWidth = 64;
+		}
+		else {
+			pAC->Pnmi.PciBusWidth = 32;
+		}
+
+		/* Get chipset. */
+		switch (pAC->GIni.GIChipId) {
+
+		case CHIP_ID_GENESIS:
+			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
+			break;
+
+		case CHIP_ID_YUKON:
+			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
+			break;
+
+		case CHIP_ID_YUKON_LITE:
+			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_LITE;
+			break;
+
+		case CHIP_ID_YUKON_LP:
+			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_LP;
+			break;
+
+		case CHIP_ID_YUKON_XL:
+			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_XL;
+			break;
+
+		case CHIP_ID_YUKON_EC:
+			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_EC;
+			break;
+
+		case CHIP_ID_YUKON_FE:
+			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_FE;
+			break;
+
+		default:
+			break;
+		}
+
+		/* Get PMD and Device Type. */
+		switch (pAC->GIni.GIPmdTyp) {
+
+		case 'S':
+			pAC->Pnmi.PMD = 3;
+			pAC->Pnmi.DeviceType = 0x00020001;
+			break;
+
+		case 'L':
+			pAC->Pnmi.PMD = 2;
+			pAC->Pnmi.DeviceType = 0x00020003;
+			break;
+
+		case 'C':
+			pAC->Pnmi.PMD = 4;
+			pAC->Pnmi.DeviceType = 0x00020005;
+			break;
+
+		case 'T':
+			pAC->Pnmi.PMD = 5;
+			pAC->Pnmi.DeviceType = 0x00020007;
+			break;
+
+		default :
+			pAC->Pnmi.PMD = 1;
+			pAC->Pnmi.DeviceType = 0;
+			break;
+		}
+
+		if (pAC->GIni.GIMacsFound > 1) {
+
+			pAC->Pnmi.DeviceType++;
+		}
+
+		/* Get connector type. */
+		switch (pAC->GIni.GIConTyp) {
+
+		case 'C':
+			pAC->Pnmi.Connector = 2;
+			break;
+
+		case 'D':
+			pAC->Pnmi.Connector = 3;
+			break;
+
+		case 'F':
+			pAC->Pnmi.Connector = 4;
+			break;
+
+		case 'J':
+			pAC->Pnmi.Connector = 5;
+			break;
+
+		case 'V':
+			pAC->Pnmi.Connector = 6;
+			break;
+
+		default:
+			pAC->Pnmi.Connector = 1;
+			break;
+		}
+		break;
+
+	case SK_INIT_RUN:
+
+		/* Start timer for RLMT change counter. */
+		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+
+		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
+			SK_PNMI_EVT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
+			EventParam);
+		break;
+
+	default:
+		break; /* Nothing to do. */
+	}
+
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ * SkPnmiGetVar - Retrieves the value of a single OID
+ *
+ * Description:
+ *	Calls a general sub-function for all this stuff. If the instance
+ *	-1 is passed, the values of all instances are returned in an
+ *	array of values.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
+ *	                         the data.
+ *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+int SkPnmiGetVar(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+SK_U32 Id,		/* Object ID that is to be processed */
+void *pBuf,		/* Buffer to which the management data will be copied */
+unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+		("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+			Id, *pLen, Instance, NetIndex));
+
+	return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
+		Instance, NetIndex));
+}
+
+/*****************************************************************************
+ *
+ * SkPnmiPreSetVar - Presets the value of a single OID
+ *
+ * Description:
+ *	Calls a general sub-function for all this stuff. The preset does
+ *	the same as a set, but returns just before finally setting the
+ *	new value. This is usefull to check if a set might be successfull.
+ *	If the instance -1 is passed, an array of values is supposed and
+ *	all instances of the OID will be set.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+int SkPnmiPreSetVar(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+SK_U32 Id,		/* Object ID that is to be processed */
+void *pBuf,		/* Buffer to which the management data will be copied */
+unsigned int *pLen,	/* Total length of management data */
+SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+		("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+			Id, *pLen, Instance, NetIndex));
+
+	return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
+		Instance, NetIndex));
+}
+
+/*****************************************************************************
+ *
+ * SkPnmiSetVar - Sets the value of a single OID
+ *
+ * Description:
+ *	Calls a general sub-function for all this stuff. The preset does
+ *	the same as a set, but returns just before finally setting the
+ *	new value. This is usefull to check if a set might be successfull.
+ *	If the instance -1 is passed, an array of values is supposed and
+ *	all instances of the OID will be set.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+int SkPnmiSetVar(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+SK_U32 Id,		/* Object ID that is to be processed */
+void *pBuf,		/* Buffer to which the management data will be copied */
+unsigned int *pLen,	/* Total length of management data */
+SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+		("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+			Id, *pLen, Instance, NetIndex));
+
+	return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
+		Instance, NetIndex));
+}
+
+/*****************************************************************************
+ *
+ * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
+ *
+ * Description:
+ *	Runs through the IdTable, queries the single OIDs and stores the
+ *	returned data into the management database structure
+ *	SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
+ *	is stored in the IdTable. The return value of the function will also
+ *	be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
+ *	minimum size of SK_PNMI_MIN_STRUCT_SIZE.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
+ *	                         the data.
+ *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
+ */
+int SkPnmiGetStruct(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+void *pBuf,		/* Buffer to which the management data will be copied. */
+unsigned int *pLen,	/* Length of buffer */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	int		Ret;
+	unsigned int	TableIndex;
+	unsigned int	DstOffset;
+	unsigned int	InstanceNo;
+	unsigned int	InstanceCnt;
+	SK_U32		Instance;
+	unsigned int	TmpLen;
+	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+		("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
+			*pLen, NetIndex));
+
+	if (*pLen < SK_PNMI_STRUCT_SIZE) {
+
+		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
+
+			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, (SK_U32)(-1));
+		}
+
+		*pLen = SK_PNMI_STRUCT_SIZE;
+		return (SK_PNMI_ERR_TOO_SHORT);
+	}
+
+	/* Check NetIndex. */
+	if (NetIndex >= pAC->Rlmt.NumNets) {
+		return (SK_PNMI_ERR_UNKNOWN_NET);
+	}
+
+	/* Update statistics. */
+	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
+
+	if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
+		SK_PNMI_ERR_OK) {
+
+		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+		return (Ret);
+	}
+
+	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+
+		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+		return (Ret);
+	}
+
+	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+
+		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+		return (Ret);
+	}
+
+	/* Increment semaphores to indicate that an update was already done. */
+	pAC->Pnmi.MacUpdatedFlag ++;
+	pAC->Pnmi.RlmtUpdatedFlag ++;
+	pAC->Pnmi.SirqUpdatedFlag ++;
+
+	/*
+	 * Get VPD keys for instance calculation.
+	 * Please read comment in Vpd().
+	 */
+	if (pAC->Pnmi.VpdKeyReadError == SK_FALSE) {
+		Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
+		if ((Ret != SK_PNMI_ERR_OK) && (pAC->Pnmi.VpdKeyReadError == SK_FALSE)){
+
+			pAC->Pnmi.MacUpdatedFlag --;
+			pAC->Pnmi.RlmtUpdatedFlag --;
+			pAC->Pnmi.SirqUpdatedFlag --;
+
+			SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+			SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+			*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+	}
+
+	/* Retrieve values. */
+	SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
+
+	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
+
+		InstanceNo = IdTable[TableIndex].InstanceNo;
+		for (InstanceCnt = 1; InstanceCnt <= InstanceNo; InstanceCnt ++) {
+
+			DstOffset = IdTable[TableIndex].Offset +
+				(InstanceCnt - 1) *
+				IdTable[TableIndex].StructSize;
+
+			/*
+			 * For the VPD the instance is not an index number
+			 * but the key itself. Determin with the instance
+			 * counter the VPD key to be used.
+			 */
+			if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
+				IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
+				IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
+				IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
+
+				SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
+			}
+			else {
+				Instance = (SK_U32)InstanceCnt;
+			}
+
+			TmpLen = *pLen - DstOffset;
+			Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
+				IdTable[TableIndex].Id, (char *)pBuf +
+				DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
+
+			/*
+			 * An unknown instance error means that we reached
+			 * the last instance of that variable. Proceed with
+			 * the next OID in the table and ignore the return
+			 * code.
+			 */
+			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
+
+				break;
+			}
+
+			if (Ret != SK_PNMI_ERR_OK) {
+
+				pAC->Pnmi.MacUpdatedFlag --;
+				pAC->Pnmi.RlmtUpdatedFlag --;
+				pAC->Pnmi.SirqUpdatedFlag --;
+
+				SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+				SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
+				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+				return (Ret);
+			}
+		}
+	}
+
+	pAC->Pnmi.MacUpdatedFlag --;
+	pAC->Pnmi.RlmtUpdatedFlag --;
+	pAC->Pnmi.SirqUpdatedFlag --;
+
+	*pLen = SK_PNMI_STRUCT_SIZE;
+	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
+ *
+ * Description:
+ *	Calls a general sub-function for all this set stuff. The preset does
+ *	the same as a set, but returns just before finally setting the
+ *	new value. This is usefull to check if a set might be successfull.
+ *	The sub-function runs through the IdTable, checks which OIDs are able
+ *	to set, and calls the handler function of the OID to perform the
+ *	preset. The return value of the function will also be stored in
+ *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+ *	SK_PNMI_MIN_STRUCT_SIZE.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ */
+int SkPnmiPreSetStruct(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+void *pBuf,		/* Buffer which contains the data to be set */
+unsigned int *pLen,	/* Length of buffer */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+		("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
+			*pLen, NetIndex));
+
+	return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
+    					pLen, NetIndex));
+}
+
+/*****************************************************************************
+ *
+ * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
+ *
+ * Description:
+ *	Calls a general sub-function for all this set stuff. The return value
+ *	of the function will also be stored in SK_PNMI_STRUCT_DATA if the
+ *	passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
+ *	The sub-function runs through the IdTable, checks which OIDs are able
+ *	to set, and calls the handler function of the OID to perform the
+ *	set. The return value of the function will also be stored in
+ *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+ *	SK_PNMI_MIN_STRUCT_SIZE.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ */
+int SkPnmiSetStruct(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+void *pBuf,		/* Buffer which contains the data to be set */
+unsigned int *pLen,	/* Length of buffer */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+		("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
+			*pLen, NetIndex));
+
+	return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
+    					pLen, NetIndex));
+}
+
+/*****************************************************************************
+ *
+ * SkPnmiEvent - Event handler
+ *
+ * Description:
+ *	Handles the following events:
+ *	SK_PNMI_EVT_SIRQ_OVERFLOW     When a hardware counter overflows an
+ *	                              interrupt will be generated which is
+ *	                              first handled by SIRQ which generates a
+ *	                              this event. The event increments the
+ *	                              upper 32 bit of the 64 bit counter.
+ *	SK_PNMI_EVT_SEN_XXX           The event is generated by the I2C module
+ *	                              when a sensor reports a warning or
+ *	                              error. The event will store a trap
+ *	                              message in the trap buffer.
+ *	SK_PNMI_EVT_CHG_EST_TIMER     The timer event was initiated by this
+ *	                              module and is used to calculate the
+ *	                              port switches per hour.
+ *	SK_PNMI_EVT_CLEAR_COUNTER     The event clears all counters and
+ *	                              timestamps.
+ *	SK_PNMI_EVT_XMAC_RESET        The event is generated by the driver
+ *	                              before a hard reset of the XMAC is
+ *	                              performed. All counters will be saved
+ *	                              and added to the hardware counter
+ *	                              values after reset to grant continuous
+ *	                              counter values.
+ *	SK_PNMI_EVT_RLMT_PORT_UP      Generated by RLMT to notify that a port
+ *	                              went logically up. A trap message will
+ *	                              be stored to the trap buffer.
+ *	SK_PNMI_EVT_RLMT_PORT_DOWN    Generated by RLMT to notify that a port
+ *	                              went logically down. A trap message will
+ *	                              be stored to the trap buffer.
+ *	SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
+ *	                              spanning tree root bridges were
+ *	                              detected. A trap message will be stored
+ *	                              to the trap buffer.
+ *	SK_PNMI_EVT_RLMT_ACTIVE_DOWN  Notifies PNMI that an active port went
+ *	                              down. PNMI will not further add the
+ *	                              statistic values to the virtual port.
+ *	SK_PNMI_EVT_RLMT_ACTIVE_UP    Notifies PNMI that a port went up and
+ *	                              is now an active port. PNMI will now
+ *	                              add the statistic data of this port to
+ *	                              the virtual port.
+ *	SK_PNMI_EVT_RLMT_SET_NETS     Notifies PNMI about the net mode. The first parameter
+ *	                              contains the number of nets. 1 means single net, 2 means
+ *	                              dual net. The second parameter is -1
+ *
+ * Returns:
+ *	Always 0
+ */
+int SkPnmiEvent(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+SK_U32 Event,		/* Event-Id */
+SK_EVPARA Param)	/* Event dependent parameter */
+{
+	unsigned int	PhysPortIndex;
+	unsigned int	MaxNetNumber;
+	int			CounterIndex;
+	SK_U16		MacStatus;
+	SK_U64		OverflowStatus;
+	SK_U64		Mask;
+	int			MacType;
+	SK_U64		Value;
+	SK_U32		Val32;
+	SK_U16		Register;
+	SK_EVPARA	EventParam;
+	SK_U64		NewestValue;
+	SK_U64		OldestValue;
+	SK_U64		Delta;
+	SK_PNMI_ESTIMATE *pEst;
+	SK_U32		NetIndex;
+	SK_U32		RetCode;
+
+#ifdef DEBUG
+	if (Event != SK_PNMI_EVT_XMAC_RESET) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+			("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
+			(unsigned int)Event, (unsigned int)Param.Para64));
+	}
+#endif /* DEBUG */
+	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
+
+	MacType = pAC->GIni.GIMacType;
+
+	switch (Event) {
+
+	case SK_PNMI_EVT_SIRQ_OVERFLOW:
+		PhysPortIndex = (int)Param.Para32[0];
+		MacStatus = (SK_U16)Param.Para32[1];
+#ifdef DEBUG
+		if (PhysPortIndex >= SK_MAX_MACS) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
+				 " wrong, PhysPortIndex=0x%x\n",
+				PhysPortIndex));
+			return (0);
+		}
+#endif /* DEBUG */
+		OverflowStatus = 0;
+
+		/* Check which source caused an overflow interrupt. */
+		if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
+				MacStatus, &OverflowStatus) != 0) ||
+			(OverflowStatus == 0)) {
+
+			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+			return (0);
+		}
+
+		/*
+		 * Check the overflow status register and increment
+		 * the upper dword of corresponding counter.
+		 */
+		for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
+			CounterIndex ++) {
+
+			Mask = (SK_U64)1 << CounterIndex;
+			if ((OverflowStatus & Mask) == 0) {
+				continue;
+			}
+
+			switch (StatOvrflwBit[CounterIndex][MacType]) {
+
+			case SK_PNMI_HTX_UTILUNDER:
+			case SK_PNMI_HTX_UTILOVER:
+				if (MacType == SK_MAC_XMAC) {
+					XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
+					Register |= XM_TX_SAM_LINE;
+					XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
+				}
+				break;
+
+			case SK_PNMI_HRX_UTILUNDER:
+			case SK_PNMI_HRX_UTILOVER:
+				if (MacType == SK_MAC_XMAC) {
+					XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
+					Register |= XM_RX_SAM_LINE;
+					XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
+				}
+				break;
+
+			case SK_PNMI_HTX_OCTETHIGH:
+			case SK_PNMI_HTX_OCTETLOW:
+			case SK_PNMI_HTX_RESERVED:
+			case SK_PNMI_HRX_OCTETHIGH:
+			case SK_PNMI_HRX_OCTETLOW:
+			case SK_PNMI_HRX_IRLENGTH:
+			case SK_PNMI_HRX_RESERVED:
+
+			/* The following counters aren't be handled (id > 63). */
+			case SK_PNMI_HTX_SYNC:
+			case SK_PNMI_HTX_SYNC_OCTET:
+				break;
+
+			case SK_PNMI_HRX_LONGFRAMES:
+				if (MacType == SK_MAC_GMAC) {
+					pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] ++;
+				}
+				break;
+
+			default:
+				pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] ++;
+			}
+		}
+		break;
+
+	case SK_PNMI_EVT_SEN_WAR_LOW:
+#ifdef DEBUG
+		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
+				(unsigned int)Param.Para64));
+			return (0);
+		}
+#endif /* DEBUG */
+
+		/*
+		 * Store a trap message in the trap buffer and generate
+		 * an event for user space applications with the
+		 * SK_DRIVER_SENDEVENT macro.
+		 */
+		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
+			(unsigned int)Param.Para64);
+		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+		break;
+
+	case SK_PNMI_EVT_SEN_WAR_UPP:
+#ifdef DEBUG
+		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
+				(unsigned int)Param.Para64));
+			return (0);
+		}
+#endif /* DEBUG */
+
+		/*
+		 * Store a trap message in the trap buffer and generate
+		 * an event for user space applications with the
+		 * SK_DRIVER_SENDEVENT macro.
+		 */
+		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
+			(unsigned int)Param.Para64);
+		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+		break;
+
+	case SK_PNMI_EVT_SEN_ERR_LOW:
+#ifdef DEBUG
+		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
+				(unsigned int)Param.Para64));
+			return (0);
+		}
+#endif /* DEBUG */
+
+		/*
+		 * Store a trap message in the trap buffer and generate
+		 * an event for user space applications with the
+		 * SK_DRIVER_SENDEVENT macro.
+		 */
+		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
+			(unsigned int)Param.Para64);
+		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+		break;
+
+	case SK_PNMI_EVT_SEN_ERR_UPP:
+#ifdef DEBUG
+		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
+				(unsigned int)Param.Para64));
+			return (0);
+		}
+#endif /* DEBUG */
+
+		/*
+		 * Store a trap message in the trap buffer and generate
+		 * an event for user space applications with the
+		 * SK_DRIVER_SENDEVENT macro.
+		 */
+		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
+			(unsigned int)Param.Para64);
+		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+		break;
+
+	case SK_PNMI_EVT_CHG_EST_TIMER:
+		/*
+		 * Calculate port switch average on a per hour basis
+		 *   Time interval for check       : 28125 ms (SK_PNMI_EVT_TIMER_CHECK)
+		 *   Number of values for average  : 8
+		 *
+		 * Be careful in changing these values, on change check
+		 *   - typedef of SK_PNMI_ESTIMATE (Size of EstValue
+		 *     array one less than value number)
+		 *   - Timer initialization SkTimerStart() in SkPnmiInit
+		 *   - Delta value below must be multiplicated with power of 2
+		 */
+		pEst = &pAC->Pnmi.RlmtChangeEstimate;
+		CounterIndex = pEst->EstValueIndex + 1;
+		if (CounterIndex == 7) {
+
+			CounterIndex = 0;
+		}
+		pEst->EstValueIndex = CounterIndex;
+
+		NewestValue = pAC->Pnmi.RlmtChangeCts;
+		OldestValue = pEst->EstValue[CounterIndex];
+		pEst->EstValue[CounterIndex] = NewestValue;
+
+		/*
+		 * Calculate average. Delta stores the number of
+		 * port switches per 28125 * 8 = 225000 ms
+		 */
+		if (NewestValue >= OldestValue) {
+
+			Delta = NewestValue - OldestValue;
+		}
+		else {
+			/* Overflow situation. */
+			Delta = (SK_U64)(0 - OldestValue) + NewestValue;
+		}
+
+		/*
+		 * Extrapolate delta to port switches per hour.
+		 *     Estimate = Delta * (3600000 / 225000)
+		 *              = Delta * 16
+		 *              = Delta << 4
+		 */
+		pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
+
+		/*
+		 * Check if threshold is exceeded. If the threshold is
+		 * permanently exceeded every 28125 ms an event will be
+		 * generated to remind the user of this condition.
+		 */
+		if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
+			(pAC->Pnmi.RlmtChangeEstimate.Estimate >=
+			pAC->Pnmi.RlmtChangeThreshold)) {
+
+			QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
+			(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+		}
+
+		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+
+		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
+			SK_PNMI_EVT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
+			EventParam);
+		break;
+
+	case SK_PNMI_EVT_CLEAR_COUNTER:
+		/*
+		 *  Param.Para32[0] contains the NetIndex (0 ..1).
+		 *  Param.Para32[1] is reserved, contains -1.
+		 */
+		NetIndex = (SK_U32)Param.Para32[0];
+
+#ifdef DEBUG
+		if (NetIndex >= pAC->Rlmt.NumNets) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
+				NetIndex));
+
+			return (0);
+		}
+#endif /* DEBUG */
+
+		/*
+		 * Set all counters and timestamps to zero.
+		 * The according NetIndex is required as a
+		 * parameter of the event.
+		 */
+		ResetCounter(pAC, IoC, NetIndex);
+		break;
+
+	case SK_PNMI_EVT_XMAC_RESET:
+		/*
+		 * To grant continuous counter values store the current
+		 * XMAC statistic values to the entries 1..n of the
+		 * CounterOffset array. XMAC Errata #2
+		 */
+#ifdef DEBUG
+		if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
+				(unsigned int)Param.Para64));
+			return (0);
+		}
+#endif /* DEBUG */
+
+		PhysPortIndex = (unsigned int)Param.Para64;
+
+		/* Update XMAC statistic to get fresh values. */
+		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
+			SK_PNMI_ERR_OK) {
+
+			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+			return (0);
+		}
+
+		/* Increment semaphore to indicate that an update was already done. */
+		pAC->Pnmi.MacUpdatedFlag ++;
+
+		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+			CounterIndex ++) {
+
+			if (!StatAddr[CounterIndex][MacType].GetOffset) {
+				continue;
+			}
+
+			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
+				GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+			
+			pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
+		}
+
+		pAC->Pnmi.MacUpdatedFlag --;
+		break;
+
+	case SK_PNMI_EVT_RLMT_PORT_UP:
+		PhysPortIndex = (unsigned int)Param.Para32[0];
+#ifdef DEBUG
+		if (PhysPortIndex >= SK_MAX_MACS) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
+				 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
+
+			return (0);
+		}
+#endif /* DEBUG */
+
+		/*
+		 * Store a trap message in the trap buffer and generate an event for
+		 * user space applications with the SK_DRIVER_SENDEVENT macro.
+		 */
+		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
+		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+
+		/* Bugfix for XMAC errata (#10620). */
+		if (MacType == SK_MAC_XMAC) {
+			/* Add incremental difference to offset (#10620). */
+			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
+				XM_RXE_SHT_ERR, &Val32);
+
+			Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
+				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
+
+			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
+				Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
+		}
+
+		/* Tell VctStatus() that a link was up meanwhile. */
+		pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;		
+		break;
+
+	case SK_PNMI_EVT_RLMT_PORT_DOWN:
+		PhysPortIndex = (unsigned int)Param.Para32[0];
+
+#ifdef DEBUG
+		if (PhysPortIndex >= SK_MAX_MACS) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
+				 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
+
+			return (0);
+		}
+#endif /* DEBUG */
+
+		/*
+		 * Store a trap message in the trap buffer and generate an event for
+		 * user space applications with the SK_DRIVER_SENDEVENT macro.
+		 */
+		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
+		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+
+		/* Bugfix #10620 - get zero level for incremental difference. */
+		if (MacType == SK_MAC_XMAC) {
+
+			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
+				XM_RXE_SHT_ERR, &Val32);
+
+			pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
+				(((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
+				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
+		}
+		break;
+
+	case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
+		PhysPortIndex = (unsigned int)Param.Para32[0];
+		NetIndex = (SK_U32)Param.Para32[1];
+
+#ifdef DEBUG
+		if (PhysPortIndex >= SK_MAX_MACS) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
+				PhysPortIndex));
+		}
+
+		if (NetIndex >= pAC->Rlmt.NumNets) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
+				NetIndex));
+		}
+#endif /* DEBUG */
+
+		/* For now, ignore event if NetIndex != 0. */
+		if (Param.Para32[1] != 0) {
+
+			return (0);
+		}
+
+		/* Nothing to do if port is already inactive. */
+		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+
+			return (0);
+		}
+
+		/*
+		 * Update statistic counters to calculate new offset for the virtual
+		 * port and increment semaphore to indicate that an update was already
+		 * done.
+		 */
+		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
+			SK_PNMI_ERR_OK) {
+
+			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+			return (0);
+		}
+		pAC->Pnmi.MacUpdatedFlag ++;
+
+		/*
+		 * Calculate new counter offset for virtual port to grant continous
+		 * counting on port switches. The virtual port consists of all currently
+		 * active ports. The port down event indicates that a port is removed
+		 * from the virtual port. Therefore add the counter value of the removed
+		 * port to the CounterOffset for the virtual port to grant the same
+		 * counter value.
+		 */
+		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+			CounterIndex ++) {
+
+			if (!StatAddr[CounterIndex][MacType].GetOffset) {
+				continue;
+			}
+
+			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+
+			pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
+		}
+
+		/* Set port to inactive. */
+		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
+
+		pAC->Pnmi.MacUpdatedFlag --;
+		break;
+
+	case SK_PNMI_EVT_RLMT_ACTIVE_UP:
+		PhysPortIndex = (unsigned int)Param.Para32[0];
+		NetIndex = (SK_U32)Param.Para32[1];
+
+#ifdef DEBUG
+		if (PhysPortIndex >= SK_MAX_MACS) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
+				PhysPortIndex));
+		}
+
+		if (NetIndex >= pAC->Rlmt.NumNets) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
+				NetIndex));
+		}
+#endif /* DEBUG */
+
+		/* For now, ignore event if NetIndex != 0. */
+		if (Param.Para32[1] != 0) {
+
+			return (0);
+		}
+
+		/* Nothing to do if port is already inactive. */
+		if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+
+			return (0);
+		}
+
+		/* Statistic maintenance. */
+		pAC->Pnmi.RlmtChangeCts ++;
+		pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+
+		/*
+		 * Store a trap message in the trap buffer and generate an event for
+		 * user space applications with the SK_DRIVER_SENDEVENT macro.
+		 */
+		QueueRlmtNewMacTrap(pAC, PhysPortIndex);
+		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+
+		/*
+		 * Update statistic counters to calculate new offset for the virtual
+		 * port and increment semaphore to indicate that an update was
+		 * already done.
+		 */
+		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
+			SK_PNMI_ERR_OK) {
+
+			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+			return (0);
+		}
+		pAC->Pnmi.MacUpdatedFlag ++;
+
+		/*
+		 * Calculate new counter offset for virtual port to grant continous
+		 * counting on port switches. A new port is added to the virtual port.
+		 * Therefore substract the counter value of the new port from the
+		 * CounterOffset for the virtual port to grant the same value.
+		 */
+		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+			CounterIndex ++) {
+
+			if (!StatAddr[CounterIndex][MacType].GetOffset) {
+				continue;
+			}
+
+			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+
+			pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
+		}
+
+		/* Set port to active. */
+		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
+
+		pAC->Pnmi.MacUpdatedFlag --;
+		break;
+
+	case SK_PNMI_EVT_RLMT_SEGMENTATION:
+		/* Para.Para32[0] contains the NetIndex. */
+
+		/*
+		 * Store a trap message in the trap buffer and generate an event for
+		 * user space applications with the SK_DRIVER_SENDEVENT macro.
+		 */
+		QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
+		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+		break;
+
+	case SK_PNMI_EVT_RLMT_SET_NETS:
+		/*
+		 *  Param.Para32[0] contains the number of Nets.
+		 *  Param.Para32[1] is reserved, contains -1.
+		 */
+		/* Check number of nets. */
+		MaxNetNumber = pAC->GIni.GIMacsFound;
+
+		if (((unsigned int)Param.Para32[0] < 1) ||
+			((unsigned int)Param.Para32[0] > MaxNetNumber)) {
+
+			return (SK_PNMI_ERR_UNKNOWN_NET);
+		}
+
+		if ((unsigned int)Param.Para32[0] == 1) { /* SingleNet mode. */
+			pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
+		}
+		else { /* DualNet mode. */
+			pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
+		}
+		break;
+
+	case SK_PNMI_EVT_VCT_RESET:
+		PhysPortIndex = Param.Para32[0];
+
+		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
+
+			RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
+
+			if (RetCode == 2) {
+				/*
+				 * VCT test is still running.
+				 * Start VCT timer counter again.
+				 */
+				SK_MEMSET((char *)&Param, 0, sizeof(Param));
+
+				Param.Para32[0] = PhysPortIndex;
+				Param.Para32[1] = -1;
+
+				SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex],
+					SK_PNMI_VCT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
+
+				break;
+			}
+
+			VctGetResults(pAC, IoC, PhysPortIndex);
+
+			EventParam.Para32[0] = PhysPortIndex;
+			EventParam.Para32[1] = -1;
+			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, EventParam);
+
+			/* SkEventDispatcher(pAC, IoC); */
+		}
+
+		break;
+
+	default:
+		break;
+	}
+
+	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+	return (0);
+}
+
+
+/******************************************************************************
+ *
+ * Private functions
+ *
+ */
+
+/*****************************************************************************
+ *
+ * PnmiVar - Gets, presets, and sets single OIDs
+ *
+ * Description:
+ *	Looks up the requested OID, calls the corresponding handler
+ *	function, and passes the parameters with the get, preset, or
+ *	set command. The function is called by SkGePnmiGetVar,
+ *	SkGePnmiPreSetVar, or SkGePnmiSetVar.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_XXX. For details have a look at the description of the
+ *	calling functions.
+ *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
+ */
+PNMI_STATIC int PnmiVar(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* Total length of pBuf management data  */
+SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	unsigned int	TableIndex;
+	int		Ret;
+
+	if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_OID);
+	}
+
+	/* Check NetIndex. */
+	if (NetIndex >= pAC->Rlmt.NumNets) {
+		return (SK_PNMI_ERR_UNKNOWN_NET);
+	}
+
+	SK_PNMI_CHECKFLAGS("PnmiVar: On call");
+
+	Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
+		Instance, TableIndex, NetIndex);
+
+	SK_PNMI_CHECKFLAGS("PnmiVar: On return");
+
+	return (Ret);
+}
+
+/*****************************************************************************
+ *
+ * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
+ *
+ * Description:
+ *	The return value of the function will also be stored in
+ *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+ *	SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
+ *	checks which OIDs are able to set, and calls the handler function of
+ *	the OID to perform the set. The return value of the function will
+ *	also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
+ *	minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
+ *	by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_XXX. The codes are described in the calling functions.
+ *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
+ */
+PNMI_STATIC int PnmiStruct(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int  Action,	/* PRESET/SET action to be performed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* Length of pBuf management data buffer */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	int		Ret;
+	unsigned int	TableIndex;
+	unsigned int	DstOffset;
+	unsigned int	Len;
+	unsigned int	InstanceNo;
+	unsigned int	InstanceCnt;
+	SK_U32		Instance;
+	SK_U32		Id;
+
+	/* Check if the passed buffer has the right size. */
+	if (*pLen < SK_PNMI_STRUCT_SIZE) {
+
+		/* Check if we can return the error within the buffer. */
+		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
+
+			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, (SK_U32)(-1));
+		}
+
+		*pLen = SK_PNMI_STRUCT_SIZE;
+		return (SK_PNMI_ERR_TOO_SHORT);
+	}
+
+	/* Check NetIndex. */
+	if (NetIndex >= pAC->Rlmt.NumNets) {
+		return (SK_PNMI_ERR_UNKNOWN_NET);
+	}
+
+	SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
+
+	/*
+	 * Update the values of RLMT and SIRQ and increment semaphores to
+	 * indicate that an update was already done.
+	 */
+	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+
+		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+		return (Ret);
+	}
+
+	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+
+		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+		return (Ret);
+	}
+
+	pAC->Pnmi.RlmtUpdatedFlag ++;
+	pAC->Pnmi.SirqUpdatedFlag ++;
+
+	/* PRESET/SET values. */
+	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
+
+		if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
+			(IdTable[TableIndex].Access != SK_PNMI_WO)) {
+			continue;
+		}
+
+		InstanceNo = IdTable[TableIndex].InstanceNo;
+		Id = IdTable[TableIndex].Id;
+
+		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
+			InstanceCnt ++) {
+
+			DstOffset = IdTable[TableIndex].Offset +
+				(InstanceCnt - 1) * IdTable[TableIndex].StructSize;
+
+			/*
+			 * Because VPD multiple instance variables are
+			 * not setable we do not need to evaluate VPD
+			 * instances. Have a look to VPD instance
+			 * calculation in SkPnmiGetStruct().
+			 */
+			Instance = (SK_U32)InstanceCnt;
+
+			/* Evaluate needed buffer length. */
+			Len = 0;
+			Ret = IdTable[TableIndex].Func(pAC, IoC,
+				SK_PNMI_GET, IdTable[TableIndex].Id,
+				NULL, &Len, Instance, TableIndex, NetIndex);
+
+			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
+
+				break;
+			}
+			if (Ret != SK_PNMI_ERR_TOO_SHORT) {
+
+				pAC->Pnmi.RlmtUpdatedFlag --;
+				pAC->Pnmi.SirqUpdatedFlag --;
+
+				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+				SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_GENERAL, DstOffset);
+				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+			if (Id == OID_SKGE_VPD_ACTION) {
+
+				switch (*(pBuf + DstOffset)) {
+
+				case SK_PNMI_VPD_CREATE:
+					Len = 3 + *(pBuf + DstOffset + 3);
+					break;
+
+				case SK_PNMI_VPD_DELETE:
+					Len = 3;
+					break;
+
+				default:
+					Len = 1;
+					break;
+				}
+			}
+
+			/* Call the OID handler function. */
+			Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
+				IdTable[TableIndex].Id, pBuf + DstOffset,
+				&Len, Instance, TableIndex, NetIndex);
+
+			if (Ret != SK_PNMI_ERR_OK) {
+
+				pAC->Pnmi.RlmtUpdatedFlag --;
+				pAC->Pnmi.SirqUpdatedFlag --;
+
+				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+				SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, DstOffset);
+				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+		}
+	}
+
+	pAC->Pnmi.RlmtUpdatedFlag --;
+	pAC->Pnmi.SirqUpdatedFlag --;
+
+	SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * LookupId - Lookup an OID in the IdTable
+ *
+ * Description:
+ *	Scans the IdTable to find the table entry of an OID.
+ *
+ * Returns:
+ *	The table index or -1 if not found.
+ */
+PNMI_STATIC int LookupId(
+SK_U32 Id)		/* Object identifier to be searched */
+{
+	int i;
+
+	for (i = 0; i < ID_TABLE_SIZE; i++) {
+
+		if (IdTable[i].Id == Id) {
+
+			return (i);
+		}
+	}
+
+	return (-1);
+}
+
+/*****************************************************************************
+ *
+ * OidStruct - Handler of OID_SKGE_ALL_DATA
+ *
+ * Description:
+ *	This OID performs a Get/Preset/SetStruct call and returns all data
+ *	in a SK_PNMI_STRUCT_DATA structure.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int OidStruct(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	if (Id != OID_SKGE_ALL_DATA) {
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, SK_PNMI_ERR003MSG);
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_GENERAL);
+	}
+
+	/* Check instance. We only handle single instance variables. */
+	if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_INST);
+	}
+
+	switch (Action) {
+
+	case SK_PNMI_GET:
+		return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+
+	case SK_PNMI_PRESET:
+		return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+
+	case SK_PNMI_SET:
+		return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+	}
+
+	SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
+
+	*pLen = 0;
+	return (SK_PNMI_ERR_GENERAL);
+}
+
+/*****************************************************************************
+ *
+ * Perform - OID handler of OID_SKGE_ACTION
+ *
+ * Description:
+ *	None.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int Perform(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	int	Ret;
+	SK_U32	ActionOp;
+
+	/* Check instance. We only handle single instance variables. */
+	if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_INST);
+	}
+
+	if (*pLen < sizeof(SK_U32)) {
+
+		*pLen = sizeof(SK_U32);
+		return (SK_PNMI_ERR_TOO_SHORT);
+	}
+
+	/* Check if a GET should be performed. */
+	if (Action == SK_PNMI_GET) {
+
+		/* A GET is easy. We always return the same value. */
+		ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
+		SK_PNMI_STORE_U32(pBuf, ActionOp);
+		*pLen = sizeof(SK_U32);
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	/* Continue with PRESET/SET action. */
+	if (*pLen > sizeof(SK_U32)) {
+
+		return (SK_PNMI_ERR_BAD_VALUE);
+	}
+
+	/* Check if the command is a known one. */
+	SK_PNMI_READ_U32(pBuf, ActionOp);
+	if (*pLen > sizeof(SK_U32) ||
+		(ActionOp != SK_PNMI_ACT_IDLE &&
+		ActionOp != SK_PNMI_ACT_RESET &&
+		ActionOp != SK_PNMI_ACT_SELFTEST &&
+		ActionOp != SK_PNMI_ACT_RESETCNT)) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_BAD_VALUE);
+	}
+
+	/* A PRESET ends here. */
+	if (Action == SK_PNMI_PRESET) {
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	switch (ActionOp) {
+
+	case SK_PNMI_ACT_IDLE:
+		/* Nothing to do. */
+		break;
+
+	case SK_PNMI_ACT_RESET:
+		/* Perform a driver reset or something that comes near to this. */
+		Ret = SK_DRIVER_RESET(pAC, IoC);
+		if (Ret != 0) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, SK_PNMI_ERR005MSG);
+
+			return (SK_PNMI_ERR_GENERAL);
+		}
+		break;
+
+	case SK_PNMI_ACT_SELFTEST:
+		/*
+		 * Perform a driver selftest or something similar to this.
+		 * Currently this feature is not used and will probably
+		 * implemented in another way.
+		 */
+		Ret = SK_DRIVER_SELFTEST(pAC, IoC);
+		pAC->Pnmi.TestResult = Ret;
+		break;
+
+	case SK_PNMI_ACT_RESETCNT:
+		/* Set all counters and timestamps to zero. */
+		ResetCounter(pAC, IoC, NetIndex);
+		break;
+
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, SK_PNMI_ERR006MSG);
+
+		return (SK_PNMI_ERR_GENERAL);
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
+ *
+ * Description:
+ *	Retrieves the statistic values of the virtual port (logical
+ *	index 0). Only special OIDs of NDIS are handled which consist
+ *	of a 32 bit instead of a 64 bit value. The OIDs are public
+ *	because perhaps some other platform can use them too.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int Mac8023Stat(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex,	/* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	int     Ret;
+	SK_U64  StatVal;
+	SK_U32  StatVal32;
+	SK_BOOL Is64BitReq = SK_FALSE;
+
+	/* Only the active MAC is returned. */
+	if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_INST);
+	}
+
+	/* Check action type. */
+	if (Action != SK_PNMI_GET) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_READ_ONLY);
+	}
+
+	/* Check length. */
+	switch (Id) {
+
+	case OID_802_3_PERMANENT_ADDRESS:
+	case OID_802_3_CURRENT_ADDRESS:
+		if (*pLen < sizeof(SK_MAC_ADDR)) {
+
+			*pLen = sizeof(SK_MAC_ADDR);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	default:
+#ifndef SK_NDIS_64BIT_CTR
+		if (*pLen < sizeof(SK_U32)) {
+			*pLen = sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+
+#else /* SK_NDIS_64BIT_CTR */
+
+		/* For compatibility, at least 32 bits are required for OID. */
+		if (*pLen < sizeof(SK_U32)) {
+			/*
+			 * Indicate handling for 64 bit values,
+			 * if insufficient space is provided.
+			 */
+			*pLen = sizeof(SK_U64);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+
+		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
+#endif /* SK_NDIS_64BIT_CTR */
+		break;
+	}
+
+	/*
+	 * Update all statistics, because we retrieve virtual MAC, which
+	 * consists of multiple physical statistics and increment semaphore
+	 * to indicate that an update was already done.
+	 */
+	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+	if (Ret != SK_PNMI_ERR_OK) {
+
+		*pLen = 0;
+		return (Ret);
+	}
+	pAC->Pnmi.MacUpdatedFlag ++;
+
+	/* Get value (MAC index 0 identifies the virtual MAC). */
+	switch (Id) {
+
+	case OID_802_3_PERMANENT_ADDRESS:
+		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
+		*pLen = sizeof(SK_MAC_ADDR);
+		break;
+
+	case OID_802_3_CURRENT_ADDRESS:
+		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
+		*pLen = sizeof(SK_MAC_ADDR);
+		break;
+
+	default:
+		StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
+
+		/* By default 32 bit values are evaluated. */
+		if (!Is64BitReq) {
+			StatVal32 = (SK_U32)StatVal;
+			SK_PNMI_STORE_U32(pBuf, StatVal32);
+			*pLen = sizeof(SK_U32);
+		}
+		else {
+			SK_PNMI_STORE_U64(pBuf, StatVal);
+			*pLen = sizeof(SK_U64);
+		}
+		break;
+	}
+
+	pAC->Pnmi.MacUpdatedFlag --;
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
+ *
+ * Description:
+ *	Retrieves the MAC statistic data.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int MacPrivateStat(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	unsigned int	LogPortMax;
+	unsigned int	LogPortIndex;
+	unsigned int	PhysPortMax;
+	unsigned int	Limit;
+	unsigned int	Offset;
+	int				MacType;
+	int				Ret;
+	SK_U64			StatVal;
+
+	/* Calculate instance if wished. MAC index 0 is the virtual MAC. */
+	PhysPortMax = pAC->GIni.GIMacsFound;
+	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+	
+	MacType = pAC->GIni.GIMacType;
+
+	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */
+		LogPortMax--;
+	}
+
+	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */
+		/* Check instance range. */
+		if ((Instance < 1) || (Instance > LogPortMax)) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_UNKNOWN_INST);
+		}
+		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+		Limit = LogPortIndex + 1;
+	}
+
+	else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */
+
+		LogPortIndex = 0;
+		Limit = LogPortMax;
+	}
+
+	/* Check action. */
+	if (Action != SK_PNMI_GET) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_READ_ONLY);
+	}
+
+	/* Check length. */
+	if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
+
+		*pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
+		return (SK_PNMI_ERR_TOO_SHORT);
+	}
+
+	/*
+	 * Update MAC statistic and increment semaphore to indicate that
+	 * an update was already done.
+	 */
+	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+	if (Ret != SK_PNMI_ERR_OK) {
+
+		*pLen = 0;
+		return (Ret);
+	}
+	pAC->Pnmi.MacUpdatedFlag ++;
+
+	/* Get value. */
+	Offset = 0;
+	for (; LogPortIndex < Limit; LogPortIndex ++) {
+
+		switch (Id) {
+
+/* XXX not yet implemented due to XMAC problems
+		case OID_SKGE_STAT_TX_UTIL:
+			return (SK_PNMI_ERR_GENERAL);
+*/
+/* XXX not yet implemented due to XMAC problems
+		case OID_SKGE_STAT_RX_UTIL:
+			return (SK_PNMI_ERR_GENERAL);
+*/
+		case OID_SKGE_STAT_RX:
+			if (MacType == SK_MAC_GMAC) {
+				StatVal =
+					GetStatVal(pAC, IoC, LogPortIndex,
+							   SK_PNMI_HRX_BROADCAST, NetIndex) +
+					GetStatVal(pAC, IoC, LogPortIndex,
+							   SK_PNMI_HRX_MULTICAST, NetIndex) +
+					GetStatVal(pAC, IoC, LogPortIndex,
+							   SK_PNMI_HRX_UNICAST, NetIndex) +
+					GetStatVal(pAC, IoC, LogPortIndex,
+							   SK_PNMI_HRX_UNDERSIZE, NetIndex);
+			}
+			else {
+				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+					IdTable[TableIndex].Param, NetIndex);
+			}
+			break;
+
+		case OID_SKGE_STAT_TX:
+			if (MacType == SK_MAC_GMAC) {
+				StatVal =
+					GetStatVal(pAC, IoC, LogPortIndex,
+							   SK_PNMI_HTX_BROADCAST, NetIndex) +
+					GetStatVal(pAC, IoC, LogPortIndex,
+							   SK_PNMI_HTX_MULTICAST, NetIndex) +
+					GetStatVal(pAC, IoC, LogPortIndex,
+							   SK_PNMI_HTX_UNICAST, NetIndex);
+			}
+			else {
+				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+					IdTable[TableIndex].Param, NetIndex);
+			}
+			break;
+
+		default:
+			StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+				IdTable[TableIndex].Param, NetIndex);
+		}
+		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
+
+		Offset += sizeof(SK_U64);
+	}
+	*pLen = Offset;
+
+	pAC->Pnmi.MacUpdatedFlag --;
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
+ *
+ * Description:
+ *	Get/Presets/Sets the current and factory MAC address. The MAC
+ *	address of the virtual port, which is reported to the OS, may
+ *	not be changed, but the physical ones. A set to the virtual port
+ *	will be ignored. No error should be reported because otherwise
+ *	a multiple instance set (-1) would always fail.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int Addr(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	int		Ret;
+	unsigned int	LogPortMax;
+	unsigned int	PhysPortMax;
+	unsigned int	LogPortIndex;
+	unsigned int	PhysPortIndex;
+	unsigned int	Limit;
+	unsigned int	Offset = 0;
+
+	/* Calculate instance if wished. MAC index 0 is the virtual MAC. */
+	PhysPortMax = pAC->GIni.GIMacsFound;
+	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+
+	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */
+		LogPortMax--;
+	}
+
+	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */
+		/* Check instance range. */
+		if ((Instance < 1) || (Instance > LogPortMax)) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_UNKNOWN_INST);
+		}
+		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+		Limit = LogPortIndex + 1;
+	}
+	else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */
+
+		LogPortIndex = 0;
+		Limit = LogPortMax;
+	}
+
+	/* Perform action. */
+	if (Action == SK_PNMI_GET) {
+
+		/* Check length. */
+		if (*pLen < (Limit - LogPortIndex) * 6) {
+
+			*pLen = (Limit - LogPortIndex) * 6;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+
+		/* Get value. */
+		for (; LogPortIndex < Limit; LogPortIndex ++) {
+
+			switch (Id) {
+
+			case OID_SKGE_PHYS_CUR_ADDR:
+				if (LogPortIndex == 0) {
+					CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
+				}
+				else {
+					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+
+					CopyMac(pBuf + Offset,
+						&pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
+				}
+				Offset += 6;
+				break;
+
+			case OID_SKGE_PHYS_FAC_ADDR:
+				if (LogPortIndex == 0) {
+					CopyMac(pBuf + Offset,
+						&pAC->Addr.Net[NetIndex].PermanentMacAddress);
+				}
+				else {
+					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+
+					CopyMac(pBuf + Offset,
+						&pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
+				}
+				Offset += 6;
+				break;
+
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, SK_PNMI_ERR008MSG);
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+		}
+
+		*pLen = Offset;
+	}
+	else {
+		/*
+		 * The logical MAC address may not be changed,
+		 * only the physical ones.
+		 */
+		if (Id == OID_SKGE_PHYS_FAC_ADDR) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_READ_ONLY);
+		}
+
+		/* Only the current address may be changed. */
+		if (Id != OID_SKGE_PHYS_CUR_ADDR) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, SK_PNMI_ERR009MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		/* Check length. */
+		if (*pLen < (Limit - LogPortIndex) * 6) {
+
+			*pLen = (Limit - LogPortIndex) * 6;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		if (*pLen > (Limit - LogPortIndex) * 6) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_BAD_VALUE);
+		}
+
+		/* Check action. */
+		if (Action == SK_PNMI_PRESET) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_OK);
+		}
+
+		/* Set OID_SKGE_MAC_CUR_ADDR.  */
+		for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
+
+			/*
+			 * A set to virtual port and set of broadcast
+			 * address will be ignored.
+			 */
+			if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
+				"\xff\xff\xff\xff\xff\xff", 6) == 0) {
+				continue;
+			}
+
+			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+
+			Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
+				(SK_MAC_ADDR *)(pBuf + Offset),
+				(LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
+				SK_ADDR_PHYSICAL_ADDRESS));
+			if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
+
+				return (SK_PNMI_ERR_GENERAL);
+			}
+		}
+		*pLen = Offset;
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
+ *
+ * Description:
+ *	Retrieves the statistic values of the CSUM module. The CSUM data
+ *	structure must be available in the SK_AC even if the CSUM module
+ *	is not included, because PNMI reads the statistic data from the
+ *	CSUM part of SK_AC directly.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int CsumStat(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	unsigned int	Index;
+	unsigned int	Limit;
+	unsigned int	Offset = 0;
+	SK_U64		StatVal;
+
+	/* Calculate instance if wished. */
+	if (Instance != (SK_U32)(-1)) {
+
+		if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_UNKNOWN_INST);
+		}
+		Index = (unsigned int)Instance - 1;
+		Limit = Index + 1;
+	}
+	else {
+		Index = 0;
+		Limit = SKCS_NUM_PROTOCOLS;
+	}
+
+	/* Check action. */
+	if (Action != SK_PNMI_GET) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_READ_ONLY);
+	}
+
+	/* Check length. */
+	if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
+
+		*pLen = (Limit - Index) * sizeof(SK_U64);
+		return (SK_PNMI_ERR_TOO_SHORT);
+	}
+
+	/* Get value. */
+	for (; Index < Limit; Index ++) {
+
+		switch (Id) {
+
+		case OID_SKGE_CHKSM_RX_OK_CTS:
+			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
+			break;
+
+		case OID_SKGE_CHKSM_RX_UNABLE_CTS:
+			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
+			break;
+
+		case OID_SKGE_CHKSM_RX_ERR_CTS:
+			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
+			break;
+
+		case OID_SKGE_CHKSM_TX_OK_CTS:
+			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
+			break;
+
+		case OID_SKGE_CHKSM_TX_UNABLE_CTS:
+			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
+			break;
+
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, SK_PNMI_ERR010MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
+		Offset += sizeof(SK_U64);
+	}
+
+	/* Store used buffer space. */
+	*pLen = Offset;
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
+ *
+ * Description:
+ *	Retrieves the statistic values of the I2C module, which handles
+ *	the temperature and voltage sensors.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int SensorStat(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	unsigned int	i;
+	unsigned int	Index;
+	unsigned int	Limit;
+	unsigned int	Offset;
+	unsigned int	Len;
+	SK_U32		Val32;
+	SK_U64		Val64;
+
+	/* Calculate instance if wished. */
+	if ((Instance != (SK_U32)(-1))) {
+
+		if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_UNKNOWN_INST);
+		}
+
+		Index = (unsigned int)Instance -1;
+		Limit = (unsigned int)Instance;
+	}
+	else {
+		Index = 0;
+		Limit = (unsigned int) pAC->I2c.MaxSens;
+	}
+
+	/* Check action. */
+	if (Action != SK_PNMI_GET) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_READ_ONLY);
+	}
+
+	/* Check length. */
+	switch (Id) {
+
+	case OID_SKGE_SENSOR_VALUE:
+	case OID_SKGE_SENSOR_WAR_THRES_LOW:
+	case OID_SKGE_SENSOR_WAR_THRES_UPP:
+	case OID_SKGE_SENSOR_ERR_THRES_LOW:
+	case OID_SKGE_SENSOR_ERR_THRES_UPP:
+		if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
+
+			*pLen = (Limit - Index) * sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_SKGE_SENSOR_DESCR:
+		for (Offset = 0, i = Index; i < Limit; i ++) {
+
+			Len = (unsigned int)
+				SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
+			if (Len >= SK_PNMI_STRINGLEN2) {
+
+				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011, SK_PNMI_ERR011MSG);
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+			Offset += Len;
+		}
+		if (*pLen < Offset) {
+
+			*pLen = Offset;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_SKGE_SENSOR_INDEX:
+	case OID_SKGE_SENSOR_TYPE:
+	case OID_SKGE_SENSOR_STATUS:
+		if (*pLen < Limit - Index) {
+
+			*pLen = Limit - Index;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_SKGE_SENSOR_WAR_CTS:
+	case OID_SKGE_SENSOR_WAR_TIME:
+	case OID_SKGE_SENSOR_ERR_CTS:
+	case OID_SKGE_SENSOR_ERR_TIME:
+		if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
+
+			*pLen = (Limit - Index) * sizeof(SK_U64);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, SK_PNMI_ERR012MSG);
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_GENERAL);
+	}
+
+	/* Get value. */
+	for (Offset = 0; Index < Limit; Index ++) {
+
+		switch (Id) {
+
+		case OID_SKGE_SENSOR_INDEX:
+			*(pBuf + Offset) = (char)Index;
+			Offset++;
+			break;
+
+		case OID_SKGE_SENSOR_DESCR:
+			Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
+			SK_MEMCPY(pBuf + Offset + 1, pAC->I2c.SenTable[Index].SenDesc, Len);
+			*(pBuf + Offset) = (char)Len;
+			Offset += Len + 1;
+			break;
+
+		case OID_SKGE_SENSOR_TYPE:
+			*(pBuf + Offset) = (char)pAC->I2c.SenTable[Index].SenType;
+			Offset++;
+			break;
+
+		case OID_SKGE_SENSOR_VALUE:
+			Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
+			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+			Offset += sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_SENSOR_WAR_THRES_LOW:
+			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+				SenThreWarnLow;
+			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+			Offset += sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_SENSOR_WAR_THRES_UPP:
+			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+				SenThreWarnHigh;
+			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+			Offset += sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_SENSOR_ERR_THRES_LOW:
+			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+				SenThreErrLow;
+			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+			Offset += sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_SENSOR_ERR_THRES_UPP:
+			Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
+			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+			Offset += sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_SENSOR_STATUS:
+			*(pBuf + Offset) = (char)pAC->I2c.SenTable[Index].SenErrFlag;
+			Offset++;
+			break;
+
+		case OID_SKGE_SENSOR_WAR_CTS:
+			Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
+			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+			Offset += sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_SENSOR_ERR_CTS:
+			Val64 = pAC->I2c.SenTable[Index].SenErrCts;
+			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+			Offset += sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_SENSOR_WAR_TIME:
+			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
+				SenBegWarnTS);
+			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+			Offset += sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_SENSOR_ERR_TIME:
+			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
+				SenBegErrTS);
+			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+			Offset += sizeof(SK_U64);
+			break;
+
+		default:
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+				("SensorStat: Unknown OID should be handled before"));
+
+			return (SK_PNMI_ERR_GENERAL);
+		}
+	}
+
+	/* Store used buffer space. */
+	*pLen = Offset;
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * Vpd - OID handler function of OID_SKGE_VPD_XXX
+ *
+ * Description:
+ *	Get/preset/set of VPD data. As instance the name of a VPD key
+ *	can be passed. The Instance parameter is a SK_U32 and can be
+ *	used as a string buffer for the VPD key, because their maximum
+ *	length is 4 byte.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int Vpd(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_VPD_STATUS	*pVpdStatus;
+	unsigned int	BufLen;
+	char		Buf[256];
+	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
+	char		KeyStr[SK_PNMI_VPD_KEY_SIZE];
+	unsigned int	KeyNo;
+	unsigned int	Offset;
+	unsigned int	Index;
+	unsigned int	FirstIndex;
+	unsigned int	LastIndex;
+	unsigned int	Len;
+	int		Ret;
+	SK_U32		Val32;
+
+	/*
+	 * VpdKeyReadError will be set in GetVpdKeyArr() if an error occurs.
+	 * Due to the fact that some drivers use SkPnmiGetStruct() to retrieve
+	 * all statistical data, an error in GetVpdKeyArr() will generate a PNMI
+	 * error and terminate SkPnmiGetStruct() without filling in statistical
+	 * data into the PNMI struct. In this case the driver will get no values
+	 * for statistical purposes (netstat, ifconfig etc.). GetVpdKeyArr() is
+	 * the first function to be called in SkPnmiGetStruct(), so any error
+	 * will terminate SkPnmiGetStruct() immediately. Hence, VpdKeyReadError will
+	 * be set during the first call to GetVpdKeyArr() to make successful calls
+	 * to SkPnmiGetStruct() possible. But there is another point to consider:
+	 * When filling in the statistical data into the PNMI struct, the VPD
+	 * handler Vpd() will also be called. If GetVpdKeyArr() in Vpd() would
+	 * return with SK_PNMI_ERR_GENERAL, SkPnmiGetStruct() would fail again.
+	 * For this reason VpdKeyReadError is checked here and, if set, Vpd()
+	 * will return without doing anything and the return value SK_PNMI_ERR_OK.
+	 * Therefore SkPnmiGetStruct() is able to continue and fill in all other
+	 * statistical data.
+	 */
+	if (pAC->Pnmi.VpdKeyReadError == SK_TRUE) {
+		return (SK_PNMI_ERR_OK);
+	}
+
+	/* Get array of all currently stored VPD keys. */
+	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
+	if (Ret != SK_PNMI_ERR_OK) {
+		*pLen = 0;
+		return (Ret);
+	}
+
+	/*
+	 * If instance is not -1, try to find the requested VPD key for
+	 * the multiple instance variables. The other OIDs as for example
+	 * OID VPD_ACTION are single instance variables and must be
+	 * handled separatly.
+	 */
+	FirstIndex = 0;
+	LastIndex = KeyNo;
+
+	if ((Instance != (SK_U32)(-1))) {
+
+		if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
+			Id == OID_SKGE_VPD_ACCESS) {
+
+			SK_STRNCPY(KeyStr, (char *)&Instance, 4);
+			KeyStr[4] = 0;
+
+			for (Index = 0; Index < KeyNo; Index ++) {
+
+				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
+					FirstIndex = Index;
+					LastIndex = Index+1;
+					break;
+				}
+			}
+			if (Index == KeyNo) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_UNKNOWN_INST);
+			}
+		}
+		else if (Instance != 1) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_UNKNOWN_INST);
+		}
+	}
+
+	/* Get value, if a query should be performed. */
+	if (Action == SK_PNMI_GET) {
+
+		switch (Id) {
+
+		case OID_SKGE_VPD_FREE_BYTES:
+			/* Check length of buffer. */
+			if (*pLen < sizeof(SK_U32)) {
+
+				*pLen = sizeof(SK_U32);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			/* Get number of free bytes. */
+			pVpdStatus = VpdStat(pAC, IoC);
+
+			if (pVpdStatus == NULL) {
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+					(SK_PNMI_ERR017MSG));
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+			if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+					(SK_PNMI_ERR018MSG));
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+
+			Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
+			SK_PNMI_STORE_U32(pBuf, Val32);
+			*pLen = sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_VPD_ENTRIES_LIST:
+			/* Check length. */
+			for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
+
+				Len += SK_STRLEN(KeyArr[Index]) + 1;
+			}
+			if (*pLen < Len) {
+
+				*pLen = Len;
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+
+			/* Get value. */
+			*(pBuf) = (char)Len - 1;
+			for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
+
+				Len = SK_STRLEN(KeyArr[Index]);
+				SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
+
+				Offset += Len;
+
+				if (Index < KeyNo - 1) {
+
+					*(pBuf + Offset) = ' ';
+					Offset++;
+				}
+			}
+			*pLen = Offset;
+			break;
+
+		case OID_SKGE_VPD_ENTRIES_NUMBER:
+			/* Check length. */
+			if (*pLen < sizeof(SK_U32)) {
+
+				*pLen = sizeof(SK_U32);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+
+			Val32 = (SK_U32)KeyNo;
+			SK_PNMI_STORE_U32(pBuf, Val32);
+			*pLen = sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_VPD_KEY:
+			/* Check buffer length, if it is large enough. */
+			for (Len = 0, Index = FirstIndex;
+				Index < LastIndex; Index ++) {
+
+				Len += SK_STRLEN(KeyArr[Index]) + 1;
+			}
+			if (*pLen < Len) {
+
+				*pLen = Len;
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+
+			/*
+			 * Get the key to an intermediate buffer, because
+			 * we have to pretend a length byte.
+			 */
+			for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) {
+
+				Len = SK_STRLEN(KeyArr[Index]);
+
+				*(pBuf + Offset) = (char)Len;
+				SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], Len);
+				Offset += Len + 1;
+			}
+			*pLen = Offset;
+			break;
+
+		case OID_SKGE_VPD_VALUE:
+			/* Check the buffer length if it is large enough. */
+			for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) {
+
+				BufLen = 256;
+				if (VpdRead(pAC, IoC, KeyArr[Index], Buf, (int *)&BufLen) > 0 ||
+					BufLen >= SK_PNMI_VPD_DATALEN) {
+
+					SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+						(SK_PNMI_ERR021MSG));
+
+					return (SK_PNMI_ERR_GENERAL);
+				}
+				Offset += BufLen + 1;
+			}
+			if (*pLen < Offset) {
+
+				*pLen = Offset;
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+
+			/*
+			 * Get the value to an intermediate buffer, because
+			 * we have to pretend a length byte.
+			 */
+			for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) {
+
+				BufLen = 256;
+				if (VpdRead(pAC, IoC, KeyArr[Index], Buf, (int *)&BufLen) > 0 ||
+					BufLen >= SK_PNMI_VPD_DATALEN) {
+
+					SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+						(SK_PNMI_ERR022MSG));
+
+					*pLen = 0;
+					return (SK_PNMI_ERR_GENERAL);
+				}
+
+				*(pBuf + Offset) = (char)BufLen;
+				SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
+				Offset += BufLen + 1;
+			}
+			*pLen = Offset;
+			break;
+
+		case OID_SKGE_VPD_ACCESS:
+			if (*pLen < LastIndex - FirstIndex) {
+
+				*pLen = LastIndex - FirstIndex;
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+
+			for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) {
+
+				if (VpdMayWrite(KeyArr[Index])) {
+
+					*(pBuf + Offset) = SK_PNMI_VPD_RW;
+				}
+				else {
+					*(pBuf + Offset) = SK_PNMI_VPD_RO;
+				}
+				Offset++;
+			}
+			*pLen = Offset;
+			break;
+
+		case OID_SKGE_VPD_ACTION:
+			Offset = LastIndex - FirstIndex;
+			if (*pLen < Offset) {
+
+				*pLen = Offset;
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			SK_MEMSET(pBuf, 0, Offset);
+			*pLen = Offset;
+			break;
+
+		default:
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				(SK_PNMI_ERR023MSG));
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+	}
+	else {
+		/* The only OID which can be set is VPD_ACTION. */
+		if (Id != OID_SKGE_VPD_ACTION) {
+
+			if (Id == OID_SKGE_VPD_FREE_BYTES ||
+				Id == OID_SKGE_VPD_ENTRIES_LIST ||
+				Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
+				Id == OID_SKGE_VPD_KEY ||
+				Id == OID_SKGE_VPD_VALUE ||
+				Id == OID_SKGE_VPD_ACCESS) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_READ_ONLY);
+			}
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+				(SK_PNMI_ERR024MSG));
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		/*
+		 * From this point we handle VPD_ACTION. Check the buffer
+		 * length. It should at least have the size of one byte.
+		 */
+		if (*pLen < 1) {
+
+			*pLen = 1;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+
+		/* The first byte contains the VPD action type we should perform. */
+		switch (*pBuf) {
+
+		case SK_PNMI_VPD_IGNORE:
+			/* Nothing to do. */
+			break;
+
+		case SK_PNMI_VPD_CREATE:
+			/*
+			 * We have to create a new VPD entry or we modify
+			 * an existing one. Check first the buffer length.
+			 */
+			if (*pLen < 4) {
+
+				*pLen = 4;
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			KeyStr[0] = pBuf[1];
+			KeyStr[1] = pBuf[2];
+			KeyStr[2] = 0;
+
+			/*
+			 * Is the entry writable or does it belong to the
+			 * read-only area?
+			 */
+			if (!VpdMayWrite(KeyStr)) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+
+			Offset = (int)pBuf[3] & 0xFF;
+
+			SK_MEMCPY(Buf, pBuf + 4, Offset);
+			Buf[Offset] = 0;
+
+			/* A PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				return (SK_PNMI_ERR_OK);
+			}
+
+			/* Write the new entry or modify an existing one .*/
+			Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
+			if (Ret == SK_PNMI_VPD_NOWRITE ) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+			else if (Ret != SK_PNMI_VPD_OK) {
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+					(SK_PNMI_ERR025MSG));
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+
+			/*
+			 * Perform an update of the VPD data. This is
+			 * not mandantory, but just to be sure.
+			 */
+			Ret = VpdUpdate(pAC, IoC);
+			if (Ret != SK_PNMI_VPD_OK) {
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+					(SK_PNMI_ERR026MSG));
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+			break;
+
+		case SK_PNMI_VPD_DELETE:
+			/* Check if the buffer size is plausible. */
+			if (*pLen < 3) {
+
+				*pLen = 3;
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			if (*pLen > 3) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+			KeyStr[0] = pBuf[1];
+			KeyStr[1] = pBuf[2];
+			KeyStr[2] = 0;
+
+			/* Find the passed key in the array. */
+			for (Index = 0; Index < KeyNo; Index ++) {
+
+				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
+
+					break;
+				}
+			}
+
+			/*
+			 * If we cannot find the key it is wrong, so we
+			 * return an appropriate error value.
+			 */
+			if (Index == KeyNo) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+
+			if (Action == SK_PNMI_PRESET) {
+
+				return (SK_PNMI_ERR_OK);
+			}
+
+			/* Ok, you wanted it and you will get it. */
+			Ret = VpdDelete(pAC, IoC, KeyStr);
+			if (Ret != SK_PNMI_VPD_OK) {
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+					(SK_PNMI_ERR027MSG));
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+
+			/*
+			 * Perform an update of the VPD data. This is
+			 * not mandantory, but just to be sure.
+			 */
+			Ret = VpdUpdate(pAC, IoC);
+			if (Ret != SK_PNMI_VPD_OK) {
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+					(SK_PNMI_ERR028MSG));
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+			break;
+
+		default:
+			*pLen = 0;
+			return (SK_PNMI_ERR_BAD_VALUE);
+		}
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * General - OID handler function of various single instance OIDs
+ *
+ * Description:
+ *	The code is simple. No description necessary.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int General(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	int		Ret;
+	unsigned int	Index;
+	unsigned int	Len;
+	unsigned int	Offset;
+	unsigned int	Val;
+	SK_U8		Val8;
+	SK_U16		Val16;
+	SK_U32		Val32;
+	SK_U64		Val64;
+	SK_U64		Val64RxHwErrs = 0;
+	SK_U64		Val64RxRunt = 0;
+	SK_U64		Val64RxFcs = 0;
+	SK_U64		Val64TxHwErrs = 0;
+	SK_BOOL		Is64BitReq = SK_FALSE;
+	char		Buf[256];
+	int			MacType;
+
+	/* Check instance. We only handle single instance variables. */
+	if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_INST);
+	}
+
+	/* Check action. We only allow get requests. */
+	if (Action != SK_PNMI_GET) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_READ_ONLY);
+	}
+
+	MacType = pAC->GIni.GIMacType;
+
+	/* Check length for the various supported OIDs. */
+	switch (Id) {
+
+	case OID_GEN_XMIT_ERROR:
+	case OID_GEN_RCV_ERROR:
+	case OID_GEN_RCV_NO_BUFFER:
+#ifndef SK_NDIS_64BIT_CTR
+		if (*pLen < sizeof(SK_U32)) {
+			*pLen = sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+
+#else /* SK_NDIS_64BIT_CTR */
+
+		/* For compatibility, at least 32bit are required for OID. */
+		if (*pLen < sizeof(SK_U32)) {
+			/*
+			 * Indicate handling for 64bit values,
+			 * if insufficient space is provided.
+			 */
+			*pLen = sizeof(SK_U64);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+
+		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
+#endif /* SK_NDIS_64BIT_CTR */
+		break;
+
+	case OID_SKGE_PORT_NUMBER:
+	case OID_SKGE_DEVICE_TYPE:
+	case OID_SKGE_RESULT:
+	case OID_SKGE_RLMT_MONITOR_NUMBER:
+	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+	case OID_SKGE_TRAP_NUMBER:
+	case OID_SKGE_MDB_VERSION:
+	case OID_SKGE_BOARDLEVEL:
+	case OID_SKGE_CHIPID:
+	case OID_SKGE_RAMSIZE:
+		if (*pLen < sizeof(SK_U32)) {
+
+			*pLen = sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_SKGE_CHIPSET:
+		if (*pLen < sizeof(SK_U16)) {
+
+			*pLen = sizeof(SK_U16);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_SKGE_BUS_TYPE:
+	case OID_SKGE_BUS_SPEED:
+	case OID_SKGE_BUS_WIDTH:
+	case OID_SKGE_SENSOR_NUMBER:
+	case OID_SKGE_CHKSM_NUMBER:
+	case OID_SKGE_VAUXAVAIL:
+		if (*pLen < sizeof(SK_U8)) {
+
+			*pLen = sizeof(SK_U8);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_SKGE_TX_SW_QUEUE_LEN:
+	case OID_SKGE_TX_SW_QUEUE_MAX:
+	case OID_SKGE_TX_RETRY:
+	case OID_SKGE_RX_INTR_CTS:
+	case OID_SKGE_TX_INTR_CTS:
+	case OID_SKGE_RX_NO_BUF_CTS:
+	case OID_SKGE_TX_NO_BUF_CTS:
+	case OID_SKGE_TX_USED_DESCR_NO:
+	case OID_SKGE_RX_DELIVERED_CTS:
+	case OID_SKGE_RX_OCTETS_DELIV_CTS:
+	case OID_SKGE_RX_HW_ERROR_CTS:
+	case OID_SKGE_TX_HW_ERROR_CTS:
+	case OID_SKGE_IN_ERRORS_CTS:
+	case OID_SKGE_OUT_ERROR_CTS:
+	case OID_SKGE_ERR_RECOVERY_CTS:
+	case OID_SKGE_SYSUPTIME:
+		if (*pLen < sizeof(SK_U64)) {
+
+			*pLen = sizeof(SK_U64);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	default:
+		/* Checked later. */
+		break;
+	}
+
+	/* Update statistics. */
+	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
+		Id == OID_SKGE_TX_HW_ERROR_CTS ||
+		Id == OID_SKGE_IN_ERRORS_CTS ||
+		Id == OID_SKGE_OUT_ERROR_CTS ||
+		Id == OID_GEN_XMIT_ERROR ||
+		Id == OID_GEN_RCV_ERROR) {
+
+		/*
+		 * Force the XMAC to update its statistic counters and
+		 * Increment semaphore to indicate that an update was
+		 * already done.
+		 */
+		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+		if (Ret != SK_PNMI_ERR_OK) {
+
+			*pLen = 0;
+			return (Ret);
+		}
+		pAC->Pnmi.MacUpdatedFlag ++;
+
+		/*
+		 * Some OIDs consist of multiple hardware counters. Those
+		 * values which are contained in all of them will be added
+		 * now.
+		 */
+		switch (Id) {
+
+		case OID_SKGE_RX_HW_ERROR_CTS:
+		case OID_SKGE_IN_ERRORS_CTS:
+		case OID_GEN_RCV_ERROR:
+			Val64RxHwErrs =
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
+
+
+			/*
+			 * In some cases the runt and fcs counters are incremented when collisions
+			 * occur. We have to correct those counters here.
+			 */
+			Val64RxRunt = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex);
+			Val64RxFcs = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex);
+
+			if (Val64RxRunt > Val64RxFcs) {
+				Val64RxRunt -= Val64RxFcs;
+				Val64RxHwErrs += Val64RxRunt;
+			}
+			else {
+				Val64RxFcs -= Val64RxRunt;
+				Val64RxHwErrs += Val64RxFcs;
+			}
+			break;
+
+		case OID_SKGE_TX_HW_ERROR_CTS:
+		case OID_SKGE_OUT_ERROR_CTS:
+		case OID_GEN_XMIT_ERROR:
+			Val64TxHwErrs =
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
+			break;
+		}
+	}
+
+	/* Retrieve value. */
+	switch (Id) {
+
+	case OID_SKGE_SUPPORTED_LIST:
+		Len = ID_TABLE_SIZE * sizeof(SK_U32);
+		if (*pLen < Len) {
+
+			*pLen = Len;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		for (Offset = 0, Index = 0; Offset < Len; Index ++) {
+
+			Val32 = (SK_U32)IdTable[Index].Id;
+			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+			Offset += sizeof(SK_U32);
+		}
+		*pLen = Len;
+		break;
+
+	case OID_SKGE_BOARDLEVEL:
+		Val32 = (SK_U32)pAC->GIni.GILevel;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_SKGE_PORT_NUMBER:
+		Val32 = (SK_U32)pAC->GIni.GIMacsFound;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_SKGE_DEVICE_TYPE:
+		Val32 = (SK_U32)pAC->Pnmi.DeviceType;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_SKGE_DRIVER_DESCR:
+		if (pAC->Pnmi.pDriverDescription == NULL) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, SK_PNMI_ERR007MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
+		if (Len > SK_PNMI_STRINGLEN1) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, SK_PNMI_ERR029MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		if (*pLen < Len) {
+
+			*pLen = Len;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		*pBuf = (char)(Len - 1);
+		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
+		*pLen = Len;
+		break;
+
+	case OID_SKGE_DRIVER_VERSION:
+		if (pAC->Pnmi.pDriverVersion == NULL) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, SK_PNMI_ERR030MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
+		if (Len > SK_PNMI_STRINGLEN1) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, SK_PNMI_ERR031MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		if (*pLen < Len) {
+
+			*pLen = Len;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		*pBuf = (char)(Len - 1);
+		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
+		*pLen = Len;
+		break;
+
+	case OID_SKGE_DRIVER_RELDATE:
+		if (pAC->Pnmi.pDriverReleaseDate == NULL) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR053, SK_PNMI_ERR053MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
+		if (Len > SK_PNMI_STRINGLEN1) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR054, SK_PNMI_ERR054MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		if (*pLen < Len) {
+
+			*pLen = Len;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		*pBuf = (char)(Len - 1);
+		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
+		*pLen = Len;
+		break;
+
+	case OID_SKGE_DRIVER_FILENAME:
+		if (pAC->Pnmi.pDriverFileName == NULL) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR055, SK_PNMI_ERR055MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
+		if (Len > SK_PNMI_STRINGLEN1) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR056, SK_PNMI_ERR056MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		if (*pLen < Len) {
+
+			*pLen = Len;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		*pBuf = (char)(Len - 1);
+		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
+		*pLen = Len;
+		break;
+
+	case OID_SKGE_HW_DESCR:
+		/*
+		 * The hardware description is located in the VPD. This
+		 * query may move to the initialisation routine. But
+		 * the VPD data is cached and therefore a call here
+		 * will not make much difference.
+		 * Please read comment in Vpd().
+		 */
+		if (pAC->Pnmi.VpdKeyReadError == SK_TRUE) {
+			return (SK_PNMI_ERR_OK);
+		}
+
+		Len = 256;
+		if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, SK_PNMI_ERR032MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+		Len ++;
+		if (Len > SK_PNMI_STRINGLEN1) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, SK_PNMI_ERR033MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+		if (*pLen < Len) {
+
+			*pLen = Len;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		*pBuf = (char)(Len - 1);
+		SK_MEMCPY(pBuf + 1, Buf, Len - 1);
+		*pLen = Len;
+		break;
+
+	case OID_SKGE_HW_VERSION:
+		if (*pLen < 5) {
+
+			*pLen = 5;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
+		pBuf[0] = 4;
+		pBuf[1] = 'v';
+		pBuf[2] = (char)('0' | ((Val8 >> 4) & 0x0f));
+		pBuf[3] = '.';
+		pBuf[4] = (char)('0' | (Val8 & 0x0f));
+		*pLen = 5;
+		break;
+
+	case OID_SKGE_CHIPSET:
+		Val16 = pAC->Pnmi.Chipset;
+		SK_PNMI_STORE_U16(pBuf, Val16);
+		*pLen = sizeof(SK_U16);
+		break;
+
+	case OID_SKGE_CHIPID:
+		Val32 = pAC->GIni.GIChipId;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_SKGE_RAMSIZE:
+		Val32 = pAC->GIni.GIRamSize;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_SKGE_VAUXAVAIL:
+		*pBuf = (char)pAC->GIni.GIVauxAvail;
+		*pLen = sizeof(char);
+		break;
+
+	case OID_SKGE_BUS_TYPE:
+		*pBuf = (char)SK_PNMI_BUS_PCI;
+		*pLen = sizeof(char);
+		break;
+
+	case OID_SKGE_BUS_SPEED:
+		*pBuf = pAC->Pnmi.PciBusSpeed;
+		*pLen = sizeof(char);
+		break;
+
+	case OID_SKGE_BUS_WIDTH:
+		*pBuf = pAC->Pnmi.PciBusWidth;
+		*pLen = sizeof(char);
+		break;
+
+	case OID_SKGE_RESULT:
+		Val32 = pAC->Pnmi.TestResult;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_SKGE_SENSOR_NUMBER:
+		*pBuf = (char)pAC->I2c.MaxSens;
+		*pLen = sizeof(char);
+		break;
+
+	case OID_SKGE_CHKSM_NUMBER:
+		*pBuf = SKCS_NUM_PROTOCOLS;
+		*pLen = sizeof(char);
+		break;
+
+	case OID_SKGE_TRAP_NUMBER:
+		GetTrapQueueLen(pAC, &Len, &Val);
+		Val32 = (SK_U32)Val;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_SKGE_TRAP:
+		GetTrapQueueLen(pAC, &Len, &Val);
+		if (*pLen < Len) {
+
+			*pLen = Len;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		CopyTrapQueue(pAC, pBuf);
+		*pLen = Len;
+		break;
+
+	case OID_SKGE_RLMT_MONITOR_NUMBER:
+		/* Not yet implemented by RLMT, therefore we return zero elements. */
+		Val32 = 0;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_SKGE_TX_SW_QUEUE_LEN:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
+					pAC->Pnmi.BufPort[1].TxSwQueueLen;
+			}			
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
+					pAC->Pnmi.Port[1].TxSwQueueLen;
+			}			
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+
+	case OID_SKGE_TX_SW_QUEUE_MAX:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
+					pAC->Pnmi.BufPort[1].TxSwQueueMax;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
+					pAC->Pnmi.Port[1].TxSwQueueMax;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_TX_RETRY:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
+					pAC->Pnmi.BufPort[1].TxRetryCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].TxRetryCts +
+					pAC->Pnmi.Port[1].TxRetryCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_RX_INTR_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
+					pAC->Pnmi.BufPort[1].RxIntrCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].RxIntrCts +
+					pAC->Pnmi.Port[1].RxIntrCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_TX_INTR_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
+					pAC->Pnmi.BufPort[1].TxIntrCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].TxIntrCts +
+					pAC->Pnmi.Port[1].TxIntrCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_RX_NO_BUF_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
+					pAC->Pnmi.BufPort[1].RxNoBufCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
+					pAC->Pnmi.Port[1].RxNoBufCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_TX_NO_BUF_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
+					pAC->Pnmi.BufPort[1].TxNoBufCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
+					pAC->Pnmi.Port[1].TxNoBufCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_TX_USED_DESCR_NO:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
+					pAC->Pnmi.BufPort[1].TxUsedDescrNo;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
+					pAC->Pnmi.Port[1].TxUsedDescrNo;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_RX_DELIVERED_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
+					pAC->Pnmi.BufPort[1].RxDeliveredCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
+					pAC->Pnmi.Port[1].RxDeliveredCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_RX_OCTETS_DELIV_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
+					pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
+					pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_RX_HW_ERROR_CTS:
+		SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_TX_HW_ERROR_CTS:
+		SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_IN_ERRORS_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = Val64RxHwErrs +
+					pAC->Pnmi.BufPort[0].RxNoBufCts +
+					pAC->Pnmi.BufPort[1].RxNoBufCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = Val64RxHwErrs +
+					pAC->Pnmi.Port[0].RxNoBufCts +
+					pAC->Pnmi.Port[1].RxNoBufCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_OUT_ERROR_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = Val64TxHwErrs +
+					pAC->Pnmi.BufPort[0].TxNoBufCts +
+					pAC->Pnmi.BufPort[1].TxNoBufCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = Val64TxHwErrs +
+					pAC->Pnmi.Port[0].TxNoBufCts +
+					pAC->Pnmi.Port[1].TxNoBufCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_ERR_RECOVERY_CTS:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
+					pAC->Pnmi.BufPort[1].ErrRecoveryCts;
+			}
+		}
+		else {
+			/* DualNet mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
+			}
+			/* SingleNet mode. */
+			else {
+				Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
+					pAC->Pnmi.Port[1].ErrRecoveryCts;
+			}
+		}
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_SYSUPTIME:
+		Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+		Val64 -= pAC->Pnmi.StartUpTime;
+		SK_PNMI_STORE_U64(pBuf, Val64);
+		*pLen = sizeof(SK_U64);
+		break;
+
+	case OID_SKGE_MDB_VERSION:
+		Val32 = SK_PNMI_MDB_VERSION;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	case OID_GEN_RCV_ERROR:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+		}
+		else {
+			Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+		}
+
+		/*
+		 * By default 32bit values are evaluated.
+		 */
+		if (!Is64BitReq) {
+			Val32 = (SK_U32)Val64;
+			SK_PNMI_STORE_U32(pBuf, Val32);
+			*pLen = sizeof(SK_U32);
+		}
+		else {
+			SK_PNMI_STORE_U64(pBuf, Val64);
+			*pLen = sizeof(SK_U64);
+		}
+		break;
+
+	case OID_GEN_XMIT_ERROR:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+		}
+		else {
+			Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+		}
+
+		/*
+		 * By default 32bit values are evaluated.
+		 */
+		if (!Is64BitReq) {
+			Val32 = (SK_U32)Val64;
+			SK_PNMI_STORE_U32(pBuf, Val32);
+			*pLen = sizeof(SK_U32);
+		}
+		else {
+			SK_PNMI_STORE_U64(pBuf, Val64);
+			*pLen = sizeof(SK_U64);
+		}
+		break;
+
+	case OID_GEN_RCV_NO_BUFFER:
+		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+		if (MacType == SK_MAC_XMAC) {
+			Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex);
+
+		}
+		else {
+			Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts +
+				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex);
+		}
+
+		/*
+		 * By default 32bit values are evaluated.
+		 */
+		if (!Is64BitReq) {
+			Val32 = (SK_U32)Val64;
+			SK_PNMI_STORE_U32(pBuf, Val32);
+			*pLen = sizeof(SK_U32);
+		}
+		else {
+			SK_PNMI_STORE_U64(pBuf, Val64);
+			*pLen = sizeof(SK_U64);
+		}
+		break;
+
+	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+		Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
+		SK_PNMI_STORE_U32(pBuf, Val32);
+		*pLen = sizeof(SK_U32);
+		break;
+
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, SK_PNMI_ERR034MSG);
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_GENERAL);
+	}
+
+	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
+		Id == OID_SKGE_TX_HW_ERROR_CTS ||
+		Id == OID_SKGE_IN_ERRORS_CTS ||
+		Id == OID_SKGE_OUT_ERROR_CTS ||
+		Id == OID_GEN_XMIT_ERROR ||
+		Id == OID_GEN_RCV_ERROR) {
+
+		pAC->Pnmi.MacUpdatedFlag --;
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
+ *
+ * Description:
+ *	Get/Presets/Sets the RLMT OIDs.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int Rlmt(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	int		Ret;
+	unsigned int	PhysPortIndex;
+	unsigned int	PhysPortMax;
+	SK_EVPARA	EventParam;
+	SK_U32		Val32;
+	SK_U64		Val64;
+
+	/* Check instance. Only single instance OIDs are allowed here. */
+	if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_INST);
+	}
+
+	/* Perform the requested action. */
+	if (Action == SK_PNMI_GET) {
+
+		/* Check if the buffer length is large enough. */
+		switch (Id) {
+
+		case OID_SKGE_RLMT_MODE:
+		case OID_SKGE_RLMT_PORT_ACTIVE:
+		case OID_SKGE_RLMT_PORT_PREFERRED:
+			if (*pLen < sizeof(SK_U8)) {
+
+				*pLen = sizeof(SK_U8);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			break;
+
+		case OID_SKGE_RLMT_PORT_NUMBER:
+			if (*pLen < sizeof(SK_U32)) {
+
+				*pLen = sizeof(SK_U32);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			break;
+
+		case OID_SKGE_RLMT_CHANGE_CTS:
+		case OID_SKGE_RLMT_CHANGE_TIME:
+		case OID_SKGE_RLMT_CHANGE_ESTIM:
+		case OID_SKGE_RLMT_CHANGE_THRES:
+			if (*pLen < sizeof(SK_U64)) {
+
+				*pLen = sizeof(SK_U64);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			break;
+
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, SK_PNMI_ERR035MSG);
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		/*
+		 * Update RLMT statistic and increment semaphores to indicate
+		 * that an update was already done. Maybe RLMT will hold its
+		 * statistic always up to date some time. Then we can
+		 * remove this type of call.
+		 */
+		if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+
+			*pLen = 0;
+			return (Ret);
+		}
+		pAC->Pnmi.RlmtUpdatedFlag ++;
+
+		/* Retrieve value. */
+		switch (Id) {
+
+		case OID_SKGE_RLMT_MODE:
+			*pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
+			*pLen = sizeof(char);
+			break;
+
+		case OID_SKGE_RLMT_PORT_NUMBER:
+			Val32 = (SK_U32)pAC->GIni.GIMacsFound;
+			SK_PNMI_STORE_U32(pBuf, Val32);
+			*pLen = sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_RLMT_PORT_ACTIVE:
+			*pBuf = 0;
+			/*
+			 * If multiple ports may become active this OID
+			 * doesn't make sense any more. A new variable in
+			 * the port structure should be created. However,
+			 * for this variable the first active port is
+			 * returned.
+			 */
+			PhysPortMax = pAC->GIni.GIMacsFound;
+
+			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+				PhysPortIndex ++) {
+
+				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+
+					*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
+					break;
+				}
+			}
+			*pLen = sizeof(char);
+			break;
+
+		case OID_SKGE_RLMT_PORT_PREFERRED:
+			*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
+			*pLen = sizeof(char);
+			break;
+
+		case OID_SKGE_RLMT_CHANGE_CTS:
+			Val64 = pAC->Pnmi.RlmtChangeCts;
+			SK_PNMI_STORE_U64(pBuf, Val64);
+			*pLen = sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_RLMT_CHANGE_TIME:
+			Val64 = pAC->Pnmi.RlmtChangeTime;
+			SK_PNMI_STORE_U64(pBuf, Val64);
+			*pLen = sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_RLMT_CHANGE_ESTIM:
+			Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
+			SK_PNMI_STORE_U64(pBuf, Val64);
+			*pLen = sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_RLMT_CHANGE_THRES:
+			Val64 = pAC->Pnmi.RlmtChangeThreshold;
+			SK_PNMI_STORE_U64(pBuf, Val64);
+			*pLen = sizeof(SK_U64);
+			break;
+
+		default:
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+				("Rlmt: Unknown OID should be handled before"));
+
+			pAC->Pnmi.RlmtUpdatedFlag --;
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		pAC->Pnmi.RlmtUpdatedFlag --;
+	}
+	else {
+		/* Perform a PRESET or SET. */
+		switch (Id) {
+
+		case OID_SKGE_RLMT_MODE:
+			/* Check if the buffer length is plausible. */
+			if (*pLen < sizeof(char)) {
+
+				*pLen = sizeof(char);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			/* Check if the value range is correct. */
+			if (*pLen != sizeof(char) ||
+				(*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
+				*(SK_U8 *)pBuf > 15) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_OK);
+			}
+			/* Send an event to RLMT to change the mode. */
+			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+			
+			EventParam.Para32[0] |= (SK_U32)(*pBuf);
+			EventParam.Para32[1] = 0;
+			if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
+				EventParam) > 0) {
+
+				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, SK_PNMI_ERR037MSG);
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+			break;
+
+		case OID_SKGE_RLMT_PORT_PREFERRED:
+			/* PRESET/SET action makes no sense in Dual Net mode. */
+			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+				break;
+			}
+			
+			/* Check if the buffer length is plausible. */
+			if (*pLen < sizeof(char)) {
+
+				*pLen = sizeof(char);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			/* Check if the value range is correct. */
+			if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
+				(SK_U8)pAC->GIni.GIMacsFound) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_OK);
+			}
+
+			/*
+			 * Send an event to RLMT change the preferred port.
+			 * A param of -1 means automatic mode. RLMT will
+			 * make the decision which is the preferred port.
+			 */
+			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+
+			EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
+			EventParam.Para32[1] = NetIndex;
+			if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
+				EventParam) > 0) {
+
+				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, SK_PNMI_ERR038MSG);
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+			break;
+
+		case OID_SKGE_RLMT_CHANGE_THRES:
+			/* Check if the buffer length is plausible. */
+			if (*pLen < sizeof(SK_U64)) {
+
+				*pLen = sizeof(SK_U64);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+
+			/* There are not many restrictions to the value range. */
+			if (*pLen != sizeof(SK_U64)) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_OK);
+			}
+			/*
+			 * Store the new threshold, which will be taken
+			 * on the next timer event.
+			 */
+			SK_PNMI_READ_U64(pBuf, Val64);
+			pAC->Pnmi.RlmtChangeThreshold = Val64;
+			break;
+
+		default:
+			/* The other OIDs are not be able for set. */
+			*pLen = 0;
+			return (SK_PNMI_ERR_READ_ONLY);
+		}
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
+ *
+ * Description:
+ *	Performs get requests on multiple instance variables.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int RlmtStat(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	unsigned int	PhysPortMax;
+	unsigned int	PhysPortIndex;
+	unsigned int	Limit;
+	unsigned int	Offset;
+	int		Ret;
+	SK_U32		Val32;
+	SK_U64		Val64;
+
+	/* Calculate the port indexes from the instance. */
+	PhysPortMax = pAC->GIni.GIMacsFound;
+
+	if ((Instance != (SK_U32)(-1))) {
+		/* Check instance range. */
+		if ((Instance < 1) || (Instance > PhysPortMax)) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_UNKNOWN_INST);
+		}
+
+		/* SingleNet mode. */
+		PhysPortIndex = Instance - 1;
+
+		/* DualNet mode. */
+		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+			PhysPortIndex = NetIndex;
+		}
+
+		/* Both net modes. */
+		Limit = PhysPortIndex + 1;
+	}
+	else {
+		/* SingleNet mode. */
+		PhysPortIndex = 0;
+		Limit = PhysPortMax;
+
+		/* DualNet mode. */
+		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+			PhysPortIndex = NetIndex;
+			Limit = PhysPortIndex + 1;
+		}
+	}
+
+	/* Currently only GET requests are allowed. */
+	if (Action != SK_PNMI_GET) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_READ_ONLY);
+	}
+
+	/* Check if the buffer length is large enough. */
+	switch (Id) {
+
+	case OID_SKGE_RLMT_PORT_INDEX:
+	case OID_SKGE_RLMT_STATUS:
+		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
+
+			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_SKGE_RLMT_TX_HELLO_CTS:
+	case OID_SKGE_RLMT_RX_HELLO_CTS:
+	case OID_SKGE_RLMT_TX_SP_REQ_CTS:
+	case OID_SKGE_RLMT_RX_SP_CTS:
+		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
+
+			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, SK_PNMI_ERR039MSG);
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_GENERAL);
+
+	}
+
+	/*
+	 * Update statistic and increment semaphores to indicate that
+	 * an update was already done.
+	 */
+	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+
+		*pLen = 0;
+		return (Ret);
+	}
+	pAC->Pnmi.RlmtUpdatedFlag ++;
+
+	/* Get value. */
+	Offset = 0;
+	for (; PhysPortIndex < Limit; PhysPortIndex ++) {
+
+		switch (Id) {
+
+		case OID_SKGE_RLMT_PORT_INDEX:
+			Val32 = PhysPortIndex;
+			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+			Offset += sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_RLMT_STATUS:
+			if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
+				SK_RLMT_PS_INIT ||
+				pAC->Rlmt.Port[PhysPortIndex].PortState ==
+				SK_RLMT_PS_DOWN) {
+
+				Val32 = SK_PNMI_RLMT_STATUS_ERROR;
+			}
+			else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+
+				Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
+			}
+			else {
+				Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
+			}
+			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+			Offset += sizeof(SK_U32);
+			break;
+
+		case OID_SKGE_RLMT_TX_HELLO_CTS:
+			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
+			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+			Offset += sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_RLMT_RX_HELLO_CTS:
+			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
+			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+			Offset += sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_RLMT_TX_SP_REQ_CTS:
+			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
+			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+			Offset += sizeof(SK_U64);
+			break;
+
+		case OID_SKGE_RLMT_RX_SP_CTS:
+			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
+			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+			Offset += sizeof(SK_U64);
+			break;
+
+		default:
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+				("RlmtStat: Unknown OID should be errored before"));
+
+			pAC->Pnmi.RlmtUpdatedFlag --;
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+	}
+	*pLen = Offset;
+
+	pAC->Pnmi.RlmtUpdatedFlag --;
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * MacPrivateConf - OID handler function of OIDs concerning the configuration
+ *
+ * Description:
+ *	Get/Presets/Sets the OIDs concerning the configuration.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int MacPrivateConf(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	unsigned int	PhysPortMax;
+	unsigned int	PhysPortIndex;
+	unsigned int	LogPortMax;
+	unsigned int	LogPortIndex;
+	unsigned int	Limit;
+	unsigned int	Offset;
+	char		Val8;
+	char 		*pBufPtr;
+	int			Ret;
+	SK_EVPARA	EventParam;
+	SK_U32		Val32;
+#ifdef SK_PHY_LP_MODE
+	SK_U8	CurrentPhyPowerState;
+#endif /* SK_PHY_LP_MODE */
+
+	/* Calculate instance if wished. MAC index 0 is the virtual MAC. */
+	PhysPortMax = pAC->GIni.GIMacsFound;
+	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+
+	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */
+		LogPortMax--;
+	}
+
+	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */
+		/* Check instance range. */
+		if ((Instance < 1) || (Instance > LogPortMax)) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_UNKNOWN_INST);
+		}
+		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+		Limit = LogPortIndex + 1;
+	}
+
+	else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */
+
+		LogPortIndex = 0;
+		Limit = LogPortMax;
+	}
+
+	/* Perform action. */
+	if (Action == SK_PNMI_GET) {
+
+		/* Check length. */
+		switch (Id) {
+
+		case OID_SKGE_PMD:
+		case OID_SKGE_CONNECTOR:
+		case OID_SKGE_LINK_CAP:
+		case OID_SKGE_LINK_MODE:
+		case OID_SKGE_LINK_MODE_STATUS:
+		case OID_SKGE_LINK_STATUS:
+		case OID_SKGE_FLOWCTRL_CAP:
+		case OID_SKGE_FLOWCTRL_MODE:
+		case OID_SKGE_FLOWCTRL_STATUS:
+		case OID_SKGE_PHY_OPERATION_CAP:
+		case OID_SKGE_PHY_OPERATION_MODE:
+		case OID_SKGE_PHY_OPERATION_STATUS:
+		case OID_SKGE_SPEED_CAP:
+		case OID_SKGE_SPEED_MODE:
+		case OID_SKGE_SPEED_STATUS:
+#ifdef SK_PHY_LP_MODE
+		case OID_SKGE_PHY_LP_MODE:
+#endif
+			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
+
+				*pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			break;
+
+		case OID_SKGE_MTU:
+		case OID_SKGE_PHY_TYPE:
+			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
+
+				*pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			break;
+
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, SK_PNMI_ERR041MSG);
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		/*
+		 * Update statistic and increment semaphore to indicate
+		 * that an update was already done.
+		 */
+		if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+
+			*pLen = 0;
+			return (Ret);
+		}
+		pAC->Pnmi.SirqUpdatedFlag ++;
+
+		/* Get value. */
+		Offset = 0;
+		for (; LogPortIndex < Limit; LogPortIndex ++) {
+
+			pBufPtr = pBuf + Offset;
+
+			switch (Id) {
+
+			case OID_SKGE_PMD:
+				*pBufPtr = pAC->Pnmi.PMD;
+				Offset++;
+				break;
+
+			case OID_SKGE_CONNECTOR:
+				*pBufPtr = pAC->Pnmi.Connector;
+				Offset++;
+				break;
+
+			case OID_SKGE_PHY_TYPE:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						continue;
+					}
+					/* Get value for physical port. */
+					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+					Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
+				}
+				else { /* DualNet mode. */
+					
+					Val32 = pAC->GIni.GP[NetIndex].PhyType;
+				}
+				SK_PNMI_STORE_U32(pBufPtr, Val32);
+				Offset += sizeof(SK_U32);
+				break;
+
+#ifdef SK_PHY_LP_MODE
+			case OID_SKGE_PHY_LP_MODE:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						continue;
+					}
+					/* Get value for physical port. */
+					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+					*pBufPtr = (SK_U8)pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
+				}
+				else { /* DualNet mode. */
+					
+					*pBufPtr = (SK_U8)pAC->GIni.GP[NetIndex].PPhyPowerState;
+				}
+				Offset += sizeof(SK_U8);
+				break;
+#endif
+
+			case OID_SKGE_LINK_CAP:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
+					}
+				}
+				else { /* DualNet mode. */
+					
+					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_LINK_MODE:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_LINK_MODE_STATUS:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+
+						*pBufPtr =
+							CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_LINK_STATUS:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+	
+						*pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_FLOWCTRL_CAP:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+	
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_FLOWCTRL_MODE:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+	
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_FLOWCTRL_STATUS:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+	
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_PHY_OPERATION_CAP:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet Mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+	
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_PHY_OPERATION_MODE:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_PHY_OPERATION_STATUS:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
+					}
+				}
+				else {
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_SPEED_CAP:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+	
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_SPEED_MODE:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+	
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_SPEED_STATUS:
+				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+					if (LogPortIndex == 0) {
+						/* Get value for virtual port. */
+						VirtualConf(pAC, IoC, Id, pBufPtr);
+					}
+					else {
+						/* Get value for physical port. */
+						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+							pAC, LogPortIndex);
+	
+						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
+					}
+				}
+				else { /* DualNet mode. */
+
+					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
+				}
+				Offset++;
+				break;
+
+			case OID_SKGE_MTU:
+				Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
+				SK_PNMI_STORE_U32(pBufPtr, Val32);
+				Offset += sizeof(SK_U32);
+				break;
+
+			default:
+				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+					("MacPrivateConf: Unknown OID should be handled before"));
+
+				pAC->Pnmi.SirqUpdatedFlag --;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+		}
+		*pLen = Offset;
+		pAC->Pnmi.SirqUpdatedFlag --;
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	/*
+	 * From here SET or PRESET action. Check if the passed
+	 * buffer length is plausible.
+	 */
+	switch (Id) {
+
+	case OID_SKGE_LINK_MODE:
+	case OID_SKGE_FLOWCTRL_MODE:
+	case OID_SKGE_PHY_OPERATION_MODE:
+	case OID_SKGE_SPEED_MODE:
+		if (*pLen < Limit - LogPortIndex) {
+
+			*pLen = Limit - LogPortIndex;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		if (*pLen != Limit - LogPortIndex) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_BAD_VALUE);
+		}
+		break;
+
+#ifdef SK_PHY_LP_MODE
+	case OID_SKGE_PHY_LP_MODE:
+		if (*pLen < Limit - LogPortIndex) {
+
+			*pLen = Limit - LogPortIndex;
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+#endif /* SK_PHY_LP_MODE */
+
+	case OID_SKGE_MTU:
+		if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
+
+			*pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	default:
+		*pLen = 0;
+		return (SK_PNMI_ERR_READ_ONLY);
+	}
+
+	/* Perform PRESET or SET. */
+	Offset = 0;
+	for (; LogPortIndex < Limit; LogPortIndex ++) {
+
+		Val8 = *(pBuf + Offset);
+
+		switch (Id) {
+
+		case OID_SKGE_LINK_MODE:
+			/* Check the value range. */
+			if (Val8 == 0) {
+				Offset++;
+				break;
+			}
+			if (Val8 < SK_LMODE_HALF ||
+				(LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
+				(LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				return (SK_PNMI_ERR_OK);
+			}
+
+			if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+				if (LogPortIndex == 0) {
+					/*
+					 * The virtual port consists of all currently
+					 * active ports. Find them and send an event
+					 * with the new link mode to SIRQ.
+					 */
+					for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+						PhysPortIndex ++) {
+
+						if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+							continue;
+						}
+
+						EventParam.Para32[0] = PhysPortIndex;
+						EventParam.Para32[1] = (SK_U32)Val8;
+						if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
+							EventParam) > 0) {
+
+							SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR043,
+								SK_PNMI_ERR043MSG);
+
+							*pLen = 0;
+							return (SK_PNMI_ERR_GENERAL);
+						}
+					} /* for */
+				}
+				else {
+					/*
+					 * Send an event with the new link mode to
+					 * the SIRQ module.
+					 */
+					EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+						pAC, LogPortIndex);
+					EventParam.Para32[1] = (SK_U32)Val8;
+					if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
+						EventParam) > 0) {
+
+						SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR043,
+							SK_PNMI_ERR043MSG);
+
+						*pLen = 0;
+						return (SK_PNMI_ERR_GENERAL);
+					}
+				}
+			}
+			else { /* DualNet mode. */
+
+				/*
+				 * Send an event with the new link mode to
+				 * the SIRQ module.
+				 */
+				EventParam.Para32[0] = NetIndex;
+				EventParam.Para32[1] = (SK_U32)Val8;
+				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
+					EventParam) > 0) {
+
+					SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR043,
+						SK_PNMI_ERR043MSG);
+
+					*pLen = 0;
+					return (SK_PNMI_ERR_GENERAL);
+				}
+			}
+			Offset++;
+			break;
+
+		case OID_SKGE_FLOWCTRL_MODE:
+			/* Check the value range. */
+			if (Val8 == 0) {
+				Offset++;
+				break;
+			}
+			if (Val8 < SK_FLOW_MODE_NONE ||
+				(LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
+				(LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				return (SK_PNMI_ERR_OK);
+			}
+
+			if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+				if (LogPortIndex == 0) {
+					/*
+					 * The virtual port consists of all currently
+					 * active ports. Find them and send an event
+					 * with the new flow control mode to SIRQ.
+					 */
+					for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+						PhysPortIndex ++) {
+
+						if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+							continue;
+						}
+
+						EventParam.Para32[0] = PhysPortIndex;
+						EventParam.Para32[1] = (SK_U32)Val8;
+						if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE,
+							EventParam) > 0) {
+
+							SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR044,
+								SK_PNMI_ERR044MSG);
+
+							*pLen = 0;
+							return (SK_PNMI_ERR_GENERAL);
+						}
+					}
+				}
+				else {
+					/*
+					 * Send an event with the new flow control
+					 * mode to the SIRQ module.
+					 */
+					EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+						pAC, LogPortIndex);
+					EventParam.Para32[1] = (SK_U32)Val8;
+					if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE,
+						EventParam) > 0) {
+
+						SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR044,
+							SK_PNMI_ERR044MSG);
+
+						*pLen = 0;
+						return (SK_PNMI_ERR_GENERAL);
+					}
+				}
+			}
+			else { /* DualNet mode. */
+				
+				/*
+				 * Send an event with the new link mode to
+				 * the SIRQ module.
+				 */
+				EventParam.Para32[0] = NetIndex;
+				EventParam.Para32[1] = (SK_U32)Val8;
+				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE,
+					EventParam) > 0) {
+
+					SK_ERR_LOG(pAC, SK_ERRCL_SW,
+						SK_PNMI_ERR044,
+						SK_PNMI_ERR044MSG);
+
+					*pLen = 0;
+					return (SK_PNMI_ERR_GENERAL);
+				}
+			}
+			Offset++;
+			break;
+
+		case OID_SKGE_PHY_OPERATION_MODE :
+			/* Check the value range. */
+			if (Val8 == 0) {
+				/* Mode of this port remains unchanged. */
+				Offset++;
+				break;
+			}
+			if (Val8 < SK_MS_MODE_AUTO ||
+				(LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
+				(LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				return (SK_PNMI_ERR_OK);
+			}
+
+			if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+				if (LogPortIndex == 0) {
+					/*
+					 * The virtual port consists of all currently
+					 * active ports. Find them and send an event
+					 * with new master/slave (role) mode to SIRQ.
+					 */
+					for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+						PhysPortIndex ++) {
+
+						if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+							continue;
+						}
+
+						EventParam.Para32[0] = PhysPortIndex;
+						EventParam.Para32[1] = (SK_U32)Val8;
+						if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_ROLE,
+							EventParam) > 0) {
+
+							SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042,
+								SK_PNMI_ERR042MSG);
+
+							*pLen = 0;
+							return (SK_PNMI_ERR_GENERAL);
+						}
+					}
+				}
+				else {
+					/*
+					 * Send an event with the new master/slave
+					 * (role) mode to the SIRQ module.
+					 */
+					EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+						pAC, LogPortIndex);
+					EventParam.Para32[1] = (SK_U32)Val8;
+					if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_ROLE,
+						EventParam) > 0) {
+
+						SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042,
+							SK_PNMI_ERR042MSG);
+
+						*pLen = 0;
+						return (SK_PNMI_ERR_GENERAL);
+					}
+				}
+			}
+			else { /* DualNet mode. */
+
+				/*
+				 * Send an event with the new link mode to
+				 * the SIRQ module.
+				 */
+				EventParam.Para32[0] = NetIndex;
+				EventParam.Para32[1] = (SK_U32)Val8;
+				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_ROLE,
+					EventParam) > 0) {
+
+					SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042,
+						SK_PNMI_ERR042MSG);
+
+					*pLen = 0;
+					return (SK_PNMI_ERR_GENERAL);
+				}
+			}
+			Offset++;
+			break;
+
+		case OID_SKGE_SPEED_MODE:
+			/* Check the value range. */
+			if (Val8 == 0) {
+				Offset++;
+				break;
+			}
+			if (Val8 < (SK_LSPEED_AUTO) ||
+				(LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
+				(LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				return (SK_PNMI_ERR_OK);
+			}
+
+			if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+				if (LogPortIndex == 0) {
+
+					/*
+					 * The virtual port consists of all currently
+					 * active ports. Find them and send an event
+					 * with the new flow control mode to SIRQ.
+					 */
+					for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+						PhysPortIndex ++) {
+
+						if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+							continue;
+						}
+
+						EventParam.Para32[0] = PhysPortIndex;
+						EventParam.Para32[1] = (SK_U32)Val8;
+						if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED,
+							EventParam) > 0) {
+
+							SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR045,
+								SK_PNMI_ERR045MSG);
+
+							*pLen = 0;
+							return (SK_PNMI_ERR_GENERAL);
+						}
+					}
+				}
+				else {
+					/*
+					 * Send an event with the new flow control
+					 * mode to the SIRQ module.
+					 */
+					EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+						pAC, LogPortIndex);
+					EventParam.Para32[1] = (SK_U32)Val8;
+					if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED,
+						EventParam) > 0) {
+
+						SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR045,
+							SK_PNMI_ERR045MSG);
+
+						*pLen = 0;
+						return (SK_PNMI_ERR_GENERAL);
+					}
+				}
+			}
+			else { /* DualNet mode. */
+				
+				/*
+				 * Send an event with the new link mode to
+				 * the SIRQ module.
+				 */
+				EventParam.Para32[0] = NetIndex;
+				EventParam.Para32[1] = (SK_U32)Val8;
+				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED,
+					EventParam) > 0) {
+
+					SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR045,
+						SK_PNMI_ERR045MSG);
+
+					*pLen = 0;
+					return (SK_PNMI_ERR_GENERAL);
+				}
+			}
+			Offset++;
+			break;
+
+		case OID_SKGE_MTU:
+			/* Check the value range. */
+			SK_PNMI_READ_U32((pBuf + Offset), Val32);
+
+			if (Val32 == 0) {
+				/* MTU of this port remains unchanged. */
+				Offset += sizeof(SK_U32);
+				break;
+			}
+
+			if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
+				*pLen = 0;
+				return (SK_PNMI_ERR_BAD_VALUE);
+			}
+
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+				return (SK_PNMI_ERR_OK);
+			}
+
+			if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
+				return (SK_PNMI_ERR_GENERAL);
+			}
+
+			Offset += sizeof(SK_U32);
+			break;
+
+#ifdef SK_PHY_LP_MODE
+		case OID_SKGE_PHY_LP_MODE:
+			/* The PRESET ends here. */
+			if (Action == SK_PNMI_PRESET) {
+
+				return (SK_PNMI_ERR_OK);
+			}
+
+			if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+				if (LogPortIndex == 0) {
+					Offset = 0;
+					continue;
+				}
+			}
+			/* Set value for physical port. */
+			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+			CurrentPhyPowerState = pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
+
+			switch (Val8) {
+				case PHY_PM_OPERATIONAL_MODE:
+					/* If LowPowerMode is active, we can leave it. */
+					if (CurrentPhyPowerState) {
+
+						Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex);
+
+						if (CurrentPhyPowerState == PHY_PM_DEEP_SLEEP ||
+							CurrentPhyPowerState == PHY_PM_IEEE_POWER_DOWN) {
+
+							SkDrvInitAdapter(pAC);
+						}
+						break;
+					}
+					else {
+						*pLen = 0;
+						return (SK_PNMI_ERR_GENERAL);
+					}
+				case PHY_PM_DEEP_SLEEP:
+				case PHY_PM_IEEE_POWER_DOWN:
+					/* If no LowPowerMode is active, we can enter it. */
+					if (!CurrentPhyPowerState) {
+						SkDrvDeInitAdapter(pAC);
+					}
+
+				case PHY_PM_ENERGY_DETECT:
+				case PHY_PM_ENERGY_DETECT_PLUS:
+					/* If no LowPowerMode is active, we can enter it. */
+					if (!CurrentPhyPowerState) {
+
+						Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf);
+						break;
+					}
+					else {
+						*pLen = 0;
+						return (SK_PNMI_ERR_GENERAL);
+					}
+				default:
+					*pLen = 0;
+					return (SK_PNMI_ERR_BAD_VALUE);
+			}
+			Offset++;
+			break;
+#endif /* SK_PHY_LP_MODE */
+
+		default:
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+				("MacPrivateConf: Unknown OID should be handled before set"));
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * Monitor - OID handler function for RLMT_MONITOR_XXX
+ *
+ * Description:
+ *	Because RLMT currently does not support the monitoring of
+ *	remote adapter cards, we return always an empty table.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+ *	                         value range.
+ *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+PNMI_STATIC int Monitor(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	unsigned int	Index;
+	unsigned int	Limit;
+	unsigned int	Offset;
+	unsigned int	Entries;
+
+	/* Not implemented yet. Return always an empty table. */
+	Entries = 0;
+
+	/* Calculate instance if wished. */
+	if ((Instance != (SK_U32)(-1))) {
+
+		if ((Instance < 1) || (Instance > Entries)) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_UNKNOWN_INST);
+		}
+
+		Index = (unsigned int)Instance - 1;
+		Limit = (unsigned int)Instance;
+	}
+	else {
+		Index = 0;
+		Limit = Entries;
+	}
+
+	/* GET/SET value. */
+	if (Action == SK_PNMI_GET) {
+
+		for (Offset = 0; Index < Limit; Index ++) {
+
+			switch (Id) {
+
+			case OID_SKGE_RLMT_MONITOR_INDEX:
+			case OID_SKGE_RLMT_MONITOR_ADDR:
+			case OID_SKGE_RLMT_MONITOR_ERRS:
+			case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
+			case OID_SKGE_RLMT_MONITOR_ADMIN:
+				break;
+
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046, SK_PNMI_ERR046MSG);
+
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+		}
+		*pLen = Offset;
+	}
+	else {
+		/* Only MONITOR_ADMIN can be set. */
+		if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_READ_ONLY);
+		}
+
+		/* Check if the length is plausible. */
+		if (*pLen < (Limit - Index)) {
+
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		/* Okay, we have a wide value range. */
+		if (*pLen != (Limit - Index)) {
+
+			*pLen = 0;
+			return (SK_PNMI_ERR_BAD_VALUE);
+		}
+
+		/*
+		 * Not yet implemented. Return always BAD_VALUE,
+		 * because the table is empty.
+		 */
+		*pLen = 0;
+		return (SK_PNMI_ERR_BAD_VALUE);
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * VirtualConf - Calculates the values of configuration OIDs for virtual port
+ *
+ * Description:
+ *	We handle here the get of the configuration group OIDs, which are
+ *	a little bit complicated. The virtual port consists of all currently
+ *	active physical ports. If multiple ports are active and configured
+ *	differently we get in some trouble to return a single value. So we
+ *	get the value of the first active port and compare it with that of
+ *	the other active ports. If they are not the same, we return a value
+ *	that indicates that the state is indeterminated.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void VirtualConf(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf)		/* Buffer used for the management data transfer */
+{
+	unsigned int	PhysPortMax;
+	unsigned int	PhysPortIndex;
+	SK_U8		Val8;
+	SK_U32		Val32;
+	SK_BOOL		PortActiveFlag;
+	SK_GEPORT	*pPrt;
+
+	*pBuf = 0;
+	PortActiveFlag = SK_FALSE;
+	PhysPortMax = pAC->GIni.GIMacsFound;
+
+	for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) {
+
+		pPrt = &pAC->GIni.GP[PhysPortIndex];
+
+		/* Check if the physical port is active. */
+		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+			continue;
+		}
+
+		PortActiveFlag = SK_TRUE;
+
+		switch (Id) {
+
+		case OID_SKGE_PHY_TYPE:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+				Val32 = pPrt->PhyType;
+				SK_PNMI_STORE_U32(pBuf, Val32);
+				continue;
+			}
+			break;
+
+		case OID_SKGE_LINK_CAP:
+
+			/*
+			 * Different capabilities should not happen, but
+			 * in the case of the cases OR them all together.
+			 * From a curious point of view the virtual port
+			 * is capable of all found capabilities.
+			 */
+			*pBuf |= pPrt->PLinkCap;
+			break;
+
+		case OID_SKGE_LINK_MODE:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PLinkModeConf;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different link mode
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != pPrt->PLinkModeConf) {
+
+				*pBuf = SK_LMODE_INDETERMINATED;
+			}
+			break;
+
+		case OID_SKGE_LINK_MODE_STATUS:
+			/* Get the link mode of the physical port. */
+			Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
+
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = Val8;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different link mode status
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != Val8) {
+
+				*pBuf = SK_LMODE_STAT_INDETERMINATED;
+			}
+			break;
+
+		case OID_SKGE_LINK_STATUS:
+			/* Get the link status of the physical port. */
+			Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
+
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = Val8;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different link status
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != Val8) {
+
+				*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
+			}
+			break;
+
+		case OID_SKGE_FLOWCTRL_CAP:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PFlowCtrlCap;
+				continue;
+			}
+
+			/*
+			 * From a curious point of view the virtual port
+			 * is capable of all found capabilities.
+			 */
+			*pBuf |= pPrt->PFlowCtrlCap;
+			break;
+
+		case OID_SKGE_FLOWCTRL_MODE:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PFlowCtrlMode;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different flow-control mode
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != pPrt->PFlowCtrlMode) {
+
+				*pBuf = SK_FLOW_MODE_INDETERMINATED;
+			}
+			break;
+
+		case OID_SKGE_FLOWCTRL_STATUS:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PFlowCtrlStatus;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different flow-control status
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != pPrt->PFlowCtrlStatus) {
+
+				*pBuf = SK_FLOW_STAT_INDETERMINATED;
+			}
+			break;
+
+		case OID_SKGE_PHY_OPERATION_CAP:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PMSCap;
+				continue;
+			}
+
+			/*
+			 * From a curious point of view the virtual port
+			 * is capable of all found capabilities.
+			 */
+			*pBuf |= pPrt->PMSCap;
+			break;
+
+		case OID_SKGE_PHY_OPERATION_MODE:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PMSMode;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different master/slave mode
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != pPrt->PMSMode) {
+
+				*pBuf = SK_MS_MODE_INDETERMINATED;
+			}
+			break;
+
+		case OID_SKGE_PHY_OPERATION_STATUS:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PMSStatus;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different master/slave status
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != pPrt->PMSStatus) {
+
+				*pBuf = SK_MS_STAT_INDETERMINATED;
+			}
+			break;
+
+		case OID_SKGE_SPEED_MODE:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PLinkSpeed;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different link speed
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != pPrt->PLinkSpeed) {
+
+				*pBuf = SK_LSPEED_INDETERMINATED;
+			}
+			break;
+
+		case OID_SKGE_SPEED_STATUS:
+			/* Check if it is the first active port. */
+			if (*pBuf == 0) {
+
+				*pBuf = pPrt->PLinkSpeedUsed;
+				continue;
+			}
+
+			/*
+			 * If we find an active port with a different link speed used
+			 * than the first one we return indeterminated.
+			 */
+			if (*pBuf != pPrt->PLinkSpeedUsed) {
+
+				*pBuf = SK_LSPEED_STAT_INDETERMINATED;
+			}
+			break;
+		}
+	}
+
+	/* If no port is active return an indeterminated answer. */
+	if (!PortActiveFlag) {
+
+		switch (Id) {
+
+		case OID_SKGE_LINK_CAP:
+			*pBuf = SK_LMODE_CAP_INDETERMINATED;
+			break;
+
+		case OID_SKGE_LINK_MODE:
+			*pBuf = SK_LMODE_INDETERMINATED;
+			break;
+
+		case OID_SKGE_LINK_MODE_STATUS:
+			*pBuf = SK_LMODE_STAT_INDETERMINATED;
+			break;
+
+		case OID_SKGE_LINK_STATUS:
+			*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
+			break;
+
+		case OID_SKGE_FLOWCTRL_CAP:
+		case OID_SKGE_FLOWCTRL_MODE:
+			*pBuf = SK_FLOW_MODE_INDETERMINATED;
+			break;
+
+		case OID_SKGE_FLOWCTRL_STATUS:
+			*pBuf = SK_FLOW_STAT_INDETERMINATED;
+			break;
+			
+		case OID_SKGE_PHY_OPERATION_CAP:
+			*pBuf = SK_MS_CAP_INDETERMINATED;
+			break;
+
+		case OID_SKGE_PHY_OPERATION_MODE:
+			*pBuf = SK_MS_MODE_INDETERMINATED;
+			break;
+
+		case OID_SKGE_PHY_OPERATION_STATUS:
+			*pBuf = SK_MS_STAT_INDETERMINATED;
+			break;
+		case OID_SKGE_SPEED_CAP:
+			*pBuf = SK_LSPEED_CAP_INDETERMINATED;
+			break;
+
+		case OID_SKGE_SPEED_MODE:
+			*pBuf = SK_LSPEED_INDETERMINATED;
+			break;
+
+		case OID_SKGE_SPEED_STATUS:
+			*pBuf = SK_LSPEED_STAT_INDETERMINATED;
+			break;
+		}
+	}
+}
+
+/*****************************************************************************
+ *
+ * CalculateLinkStatus - Determins the link status of a physical port
+ *
+ * Description:
+ *	Determins the link status the following way:
+ *	  LSTAT_PHY_DOWN:  Link is down
+ *	  LSTAT_AUTONEG:   Auto-negotiation failed
+ *	  LSTAT_LOG_DOWN:  Link is up but RLMT did not yet put the port
+ *	                   logically up.
+ *	  LSTAT_LOG_UP:    RLMT marked the port as up
+ *
+ * Returns:
+ *	Link status of physical port
+ */
+PNMI_STATIC SK_U8 CalculateLinkStatus(
+SK_AC *pAC,			/* Pointer to adapter context */
+SK_IOC IoC,			/* IO context handle */
+unsigned int PhysPortIndex)	/* Physical port index */
+{
+	SK_U8	Result;
+
+	if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
+
+		Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
+	}
+	else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
+
+		Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
+				}
+	else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
+
+		Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
+	}
+	else {
+		Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
+	}
+
+	return (Result);
+}
+
+/*****************************************************************************
+ *
+ * CalculateLinkModeStatus - Determins the link mode status of a phys. port
+ *
+ * Description:
+ *	The COMMON module only tells us if the mode is half or full duplex.
+ *	But in the decade of auto sensing it is usefull for the user to
+ *	know if the mode was negotiated or forced. Therefore we have a
+ *	look to the mode, which was last used by the negotiation process.
+ *
+ * Returns:
+ *	The link mode status
+ */
+PNMI_STATIC SK_U8 CalculateLinkModeStatus(
+SK_AC *pAC,			/* Pointer to adapter context */
+SK_IOC IoC,			/* IO context handle */
+unsigned int PhysPortIndex)	/* Physical port index */
+{
+	SK_U8	Result;
+
+	/* Get the current mode, which can be full or half duplex. */
+	Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
+
+	/* Check if no valid mode could be found (link is down). */
+	if (Result < SK_LMODE_STAT_HALF) {
+
+		Result = SK_LMODE_STAT_UNKNOWN;
+	}
+	else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
+		/*
+		 * Auto-negotiation was used to bring up the link. Change
+		 * the already found duplex status that it indicates
+		 * auto-negotiation was involved.
+		 */
+		if (Result == SK_LMODE_STAT_HALF) {
+
+			Result = SK_LMODE_STAT_AUTOHALF;
+		}
+		else if (Result == SK_LMODE_STAT_FULL) {
+
+			Result = SK_LMODE_STAT_AUTOFULL;
+		}
+	}
+
+	return (Result);
+}
+
+/*****************************************************************************
+ *
+ * GetVpdKeyArr - Obtain an array of VPD keys
+ *
+ * Description:
+ *	Read the VPD keys and build an array of VPD keys, which are
+ *	easy to access.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK	     Task successfully performed.
+ *	SK_PNMI_ERR_GENERAL  Something went wrong.
+ */
+PNMI_STATIC int GetVpdKeyArr(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+char *pKeyArr,		/* Ptr KeyArray */
+unsigned int KeyArrLen,	/* Length of array in bytes */
+unsigned int *pKeyNo)	/* Number of keys */
+{
+	unsigned int		BufKeysLen = SK_PNMI_VPD_BUFSIZE;
+	char			BufKeys[SK_PNMI_VPD_BUFSIZE];
+	unsigned int		StartOffset;
+	unsigned int		Offset;
+	int			Index;
+	int			Ret;
+
+	SK_MEMSET(pKeyArr, 0, KeyArrLen);
+
+	/* Get VPD key list. */
+	Ret = VpdKeys(pAC, IoC, BufKeys, (int *)&BufKeysLen, (int *)pKeyNo);
+
+	if (Ret > 0) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+			(SK_PNMI_ERR014MSG));
+
+		/* Please read comment in Vpd(). */
+		pAC->Pnmi.VpdKeyReadError = SK_TRUE;
+		return (SK_PNMI_ERR_GENERAL);
+	}
+	/* If no keys are available return now. */
+	if (*pKeyNo == 0 || BufKeysLen == 0) {
+
+		return (SK_PNMI_ERR_OK);
+	}
+	/*
+	 * If the key list is too long for us trunc it and give a
+	 * errorlog notification. This case should not happen because
+	 * the maximum number of keys is limited due to RAM limitations.
+	 */
+	if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+			(SK_PNMI_ERR015MSG));
+
+		*pKeyNo = SK_PNMI_VPD_ENTRIES;
+	}
+
+	/*
+	 * Now build an array of fixed string length size and copy
+	 * the keys together.
+	 */
+	for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
+		Offset ++) {
+
+		if (BufKeys[Offset] != 0) {
+			continue;
+		}
+
+		if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+					   (SK_PNMI_ERR016MSG));
+
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
+			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
+
+		Index ++;
+		StartOffset = Offset + 1;
+	}
+
+	/* Last key not zero terminated? Get it anyway. */
+	if (StartOffset < Offset) {
+
+		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
+			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * SirqUpdate - Let the SIRQ update its internal values
+ *
+ * Description:
+ *	Just to be sure that the SIRQ module holds its internal data
+ *	structures up to date, we send an update event before we make
+ *	any access.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK	     Task successfully performed.
+ *	SK_PNMI_ERR_GENERAL  Something went wrong.
+ */
+PNMI_STATIC int SirqUpdate(
+SK_AC *pAC,	/* Pointer to adapter context */
+SK_IOC IoC)	/* IO context handle */
+{
+	SK_EVPARA	EventParam;
+
+	/* Was the module already updated during the current PNMI call? */
+	if (pAC->Pnmi.SirqUpdatedFlag > 0) {
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	/* Send an synchronuous update event to the module. */
+	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+	
+	if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam)) {
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, SK_PNMI_ERR047MSG);
+
+		return (SK_PNMI_ERR_GENERAL);
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * RlmtUpdate - Let the RLMT update its internal values
+ *
+ * Description:
+ *	Just to be sure that the RLMT module holds its internal data
+ *	structures up to date, we send an update event before we make
+ *	any access.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK	     Task successfully performed.
+ *	SK_PNMI_ERR_GENERAL  Something went wrong.
+ */
+PNMI_STATIC int RlmtUpdate(
+SK_AC *pAC,	/* Pointer to adapter context */
+SK_IOC IoC,	/* IO context handle */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_EVPARA	EventParam;
+
+	/* Was the module already updated during the current PNMI call? */
+	if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	/* Send an synchronuous update event to the module. */
+	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+	EventParam.Para32[0] = NetIndex;
+	EventParam.Para32[1] = (SK_U32)-1;
+	if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, SK_PNMI_ERR048MSG);
+
+		return (SK_PNMI_ERR_GENERAL);
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * MacUpdate - Force the XMAC to output the current statistic
+ *
+ * Description:
+ *	The XMAC holds its statistic internally. To obtain the current
+ *	values we must send a command so that the statistic data will
+ *	be written to a predefined memory area on the adapter.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK	     Task successfully performed.
+ *	SK_PNMI_ERR_GENERAL  Something went wrong.
+ */
+PNMI_STATIC int MacUpdate(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+unsigned int FirstMac,	/* Index of the first Mac to be updated */
+unsigned int LastMac)	/* Index of the last Mac to be updated */
+{
+	unsigned int	MacIndex;
+
+	/*
+	 * Were the statistics already updated during the
+	 * current PNMI call?
+	 */
+	if (pAC->Pnmi.MacUpdatedFlag > 0) {
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	/* Send an update command to all MACs specified. */
+	for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
+
+		/*
+		 * 2002-09-13 pweber:	Freeze the current SW counters.
+		 *                      (That should be done as close as
+		 *                      possible to the update of the
+		 *                      HW counters).
+		 */
+		if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
+			pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
+		}
+			
+		/* 2002-09-13 pweber:  Update the HW counter.  */
+		if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
+
+			return (SK_PNMI_ERR_GENERAL);
+		}
+	}
+
+	return (SK_PNMI_ERR_OK);
+}
+
+/*****************************************************************************
+ *
+ * GetStatVal - Retrieve an XMAC statistic counter
+ *
+ * Description:
+ *	Retrieves the statistic counter of a virtual or physical port. The
+ *	virtual port is identified by the index 0. It consists of all
+ *	currently active ports. To obtain the counter value for this port
+ *	we must add the statistic counter of all active ports. To grant
+ *	continuous counter values for the virtual port even when port
+ *	switches occur we must additionally add a delta value, which was
+ *	calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
+ *
+ * Returns:
+ *	Requested statistic value
+ */
+PNMI_STATIC SK_U64 GetStatVal(
+SK_AC *pAC,					/* Pointer to adapter context */
+SK_IOC IoC,					/* IO context handle */
+unsigned int LogPortIndex,	/* Index of the logical Port to be processed */
+unsigned int StatIndex,		/* Index to statistic value */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	unsigned int	PhysPortIndex;
+	unsigned int	PhysPortMax;
+	SK_U64			Val = 0;
+
+	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {	/* DualNet mode. */
+
+		PhysPortIndex = NetIndex;
+
+		Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+	}
+	else {	/* SingleNet mode. */
+
+		if (LogPortIndex == 0) {
+
+			PhysPortMax = pAC->GIni.GIMacsFound;
+
+			/* Add counter of all active ports. */
+			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+				PhysPortIndex ++) {
+
+				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+
+					Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+				}
+			}
+
+			/* Correct value because of port switches. */
+			Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
+		}
+		else {
+			/* Get counter value of physical port. */
+			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+
+			Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+		}
+	}
+	return (Val);
+}
+
+/*****************************************************************************
+ *
+ * GetPhysStatVal - Get counter value for physical port
+ *
+ * Description:
+ *	Builds a 64bit counter value. Except for the octet counters
+ *	the lower 32bit are counted in hardware and the upper 32bit
+ *	in software by monitoring counter overflow interrupts in the
+ *	event handler. To grant continous counter values during XMAC
+ *	resets (caused by a workaround) we must add a delta value.
+ *	The delta was calculated in the event handler when a
+ *	SK_PNMI_EVT_XMAC_RESET was received.
+ *
+ * Returns:
+ *	Counter value
+ */
+PNMI_STATIC SK_U64 GetPhysStatVal(
+SK_AC *pAC,					/* Pointer to adapter context */
+SK_IOC IoC,					/* IO context handle */
+unsigned int PhysPortIndex,	/* Index of the logical Port to be processed */
+unsigned int StatIndex)		/* Index to statistic value */
+{
+	SK_U64	Val = 0;
+	SK_U32	LowVal = 0;
+	SK_U32	HighVal = 0;
+	SK_U16	Word;
+	int		MacType;
+	unsigned int HelpIndex;
+	SK_GEPORT	*pPrt;
+
+	SK_PNMI_PORT	*pPnmiPrt;
+	SK_GEMACFUNC	*pFnMac;
+
+	pPrt = &pAC->GIni.GP[PhysPortIndex];
+
+	MacType = pAC->GIni.GIMacType;
+
+	/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+	if (MacType == SK_MAC_XMAC) {
+		pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
+	}
+	else {
+		pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
+	}
+
+	pFnMac   = &pAC->GIni.GIFunc;
+
+	switch (StatIndex) {
+	case SK_PNMI_HTX:
+		if (MacType == SK_MAC_GMAC) {
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+							StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
+							&LowVal);
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+							StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
+							&HighVal);
+			LowVal += HighVal;
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+							StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
+							&HighVal);
+			LowVal += HighVal;
+		}
+		else {
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+										  StatAddr[StatIndex][MacType].Reg,
+										  &LowVal);
+		}
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+
+	case SK_PNMI_HRX:
+		if (MacType == SK_MAC_GMAC) {
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+							StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
+							&LowVal);
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+							StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
+							&HighVal);
+			LowVal += HighVal;
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+							StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
+							&HighVal);
+			LowVal += HighVal;
+		}
+		else {
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+										  StatAddr[StatIndex][MacType].Reg,
+										  &LowVal);
+		}
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+
+	case SK_PNMI_HTX_OCTET:
+	case SK_PNMI_HRX_OCTET:
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex][MacType].Reg,
+									  &HighVal);
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex + 1][MacType].Reg,
+									  &LowVal);
+		break;
+
+	case SK_PNMI_HTX_BURST:
+	case SK_PNMI_HTX_EXCESS_DEF:
+	case SK_PNMI_HTX_CARRIER:
+		/* Not supported by GMAC. */
+		if (MacType == SK_MAC_GMAC) {
+			return (Val);
+		}
+
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex][MacType].Reg,
+									  &LowVal);
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+
+	case SK_PNMI_HTX_MACC:
+		/* GMAC only supports PAUSE MAC control frames. */
+		if (MacType == SK_MAC_GMAC) {
+			HelpIndex = SK_PNMI_HTX_PMACC;
+		}
+		else {
+			HelpIndex = StatIndex;
+		}
+
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+								StatAddr[HelpIndex][MacType].Reg,
+								&LowVal);
+
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+
+	case SK_PNMI_HTX_COL:
+	case SK_PNMI_HRX_UNDERSIZE:
+		/* Not supported by XMAC. */
+		if (MacType == SK_MAC_XMAC) {
+			return (Val);
+		}
+
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex][MacType].Reg,
+									  &LowVal);
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+
+	case SK_PNMI_HTX_DEFFERAL:
+		/* Not supported by GMAC. */
+		if (MacType == SK_MAC_GMAC) {
+			return (Val);
+		}
+
+		/*
+		 * XMAC counts frames with deferred transmission
+		 * even in full-duplex mode.
+		 *
+		 * In full-duplex mode the counter remains constant!
+		 */
+		if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
+			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
+
+			LowVal = 0;
+			HighVal = 0;
+		}
+		else {
+			/* Otherwise get contents of hardware register. */
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+										  StatAddr[StatIndex][MacType].Reg,
+										  &LowVal);
+			HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		}
+		break;
+
+	case SK_PNMI_HRX_BADOCTET:
+		/* Not supported by XMAC. */
+		if (MacType == SK_MAC_XMAC) {
+			return (Val);
+		}
+
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex][MacType].Reg,
+									  &HighVal);
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex + 1][MacType].Reg,
+									  &LowVal);
+		break;
+
+	case SK_PNMI_HTX_OCTETLOW:
+	case SK_PNMI_HRX_OCTETLOW:
+	case SK_PNMI_HRX_BADOCTETLOW:
+		return (Val);
+
+	case SK_PNMI_HRX_LONGFRAMES:
+		/* For XMAC the SW counter is managed by PNMI. */
+		if (MacType == SK_MAC_XMAC) {
+			return (pPnmiPrt->StatRxLongFrameCts);
+		}
+
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex][MacType].Reg,
+									  &LowVal);
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+
+	case SK_PNMI_HRX_TOO_LONG:
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+								StatAddr[StatIndex][MacType].Reg,
+								&LowVal);
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+
+		Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+
+		if (MacType == SK_MAC_GMAC) {
+			/* For GMAC the SW counter is additionally managed by PNMI. */
+			Val += pPnmiPrt->StatRxFrameTooLongCts;
+		}
+		else {
+			/*
+			 * Frames longer than IEEE 802.3 frame max size are counted
+			 * by XMAC in frame_too_long counter even reception of long
+			 * frames was enabled and the frame was correct.
+			 * So correct the value by subtracting RxLongFrame counter.
+			 */
+			Val -= pPnmiPrt->StatRxLongFrameCts;
+		}
+
+		LowVal = (SK_U32)Val;
+		HighVal = (SK_U32)(Val >> 32);
+		break;
+
+	case SK_PNMI_HRX_SHORTS:
+		/* Not supported by GMAC. */
+		if (MacType == SK_MAC_GMAC) {
+			/* GM_RXE_FRAG?? */
+			return (Val);
+		}
+
+		/*
+		 * XMAC counts short frame errors even if link down (#10620).
+		 * If the link is down, the counter remains constant.
+		 */
+		if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
+
+			/* Otherwise get incremental difference. */
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+										  StatAddr[StatIndex][MacType].Reg,
+										  &LowVal);
+			HighVal = pPnmiPrt->CounterHigh[StatIndex];
+
+			Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+			Val -= pPnmiPrt->RxShortZeroMark;
+
+			LowVal = (SK_U32)Val;
+			HighVal = (SK_U32)(Val >> 32);
+		}
+		break;
+
+	case SK_PNMI_HRX_MACC:
+	case SK_PNMI_HRX_MACC_UNKWN:
+	case SK_PNMI_HRX_BURST:
+	case SK_PNMI_HRX_MISSED:
+	case SK_PNMI_HRX_FRAMING:
+	case SK_PNMI_HRX_CARRIER:
+	case SK_PNMI_HRX_IRLENGTH:
+	case SK_PNMI_HRX_SYMBOL:
+	case SK_PNMI_HRX_CEXT:
+		/* Not supported by GMAC. */
+		if (MacType == SK_MAC_GMAC) {
+			return (Val);
+		}
+
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex][MacType].Reg,
+									  &LowVal);
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+
+	case SK_PNMI_HRX_PMACC_ERR:
+		/* For GMAC the SW counter is managed by PNMI. */
+		if (MacType == SK_MAC_GMAC) {
+			return (pPnmiPrt->StatRxPMaccErr);
+		}
+
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex][MacType].Reg,
+									  &LowVal);
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+
+	/* SW counter managed by PNMI. */
+	case SK_PNMI_HTX_SYNC:
+		LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
+		HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
+		break;
+
+	/* SW counter managed by PNMI. */
+	case SK_PNMI_HTX_SYNC_OCTET:
+		LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
+		HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
+		break;
+
+	case SK_PNMI_HRX_FCS:
+		/*
+		 * Broadcom filters FCS errors and counts them in
+		 * Receive Error Counter register.
+		 */
+		if (pPrt->PhyType == SK_PHY_BCOM) {
+#ifdef GENESIS
+			/* Do not read while not initialized (PHY_READ hangs!). */
+			if (pPrt->PState != SK_PRT_RESET) {
+				SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
+				
+				LowVal = Word;
+			}
+			HighVal = pPnmiPrt->CounterHigh[StatIndex];
+#endif /* GENESIS */
+		}
+		else {
+			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+										  StatAddr[StatIndex][MacType].Reg,
+										  &LowVal);
+			HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		}
+		break;
+
+	default:
+		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+									  StatAddr[StatIndex][MacType].Reg,
+									  &LowVal);
+		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+		break;
+	}
+
+	Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+
+	/* Correct value because of possible XMAC reset (XMAC Errata #2). */
+	Val += pPnmiPrt->CounterOffset[StatIndex];
+
+	return (Val);
+}
+
+/*****************************************************************************
+ *
+ * ResetCounter - Set all counters and timestamps to zero
+ *
+ * Description:
+ *	Notifies other common modules which store statistic data to
+ *	reset their counters and finally reset our own counters.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void ResetCounter(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+SK_U32 NetIndex)
+{
+	unsigned int	PhysPortIndex;
+	SK_EVPARA	EventParam;
+
+	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+
+	/* Notify sensor module. */
+	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
+
+	/* Notify RLMT module. */
+	EventParam.Para32[0] = NetIndex;
+	EventParam.Para32[1] = (SK_U32)-1;
+	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
+	EventParam.Para32[1] = 0;
+
+	/* Notify SIRQ module. */
+	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
+
+	/* Notify CSUM module. */
+#ifdef SK_USE_CSUM
+	EventParam.Para32[0] = NetIndex;
+	EventParam.Para32[1] = (SK_U32)-1;
+	SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
+		EventParam);
+#endif /* SK_USE_CSUM */
+
+	/* Clear XMAC statistics. */
+	for (PhysPortIndex = 0; PhysPortIndex <
+		(unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
+
+		(void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
+
+		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
+			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
+
+		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterOffset,
+			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterOffset));
+
+		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
+			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
+
+		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncOctetsCts,
+			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncOctetsCts));
+
+		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatRxLongFrameCts,
+			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatRxLongFrameCts));
+
+		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatRxFrameTooLongCts,
+			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatRxFrameTooLongCts));
+
+		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatRxPMaccErr,
+			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatRxPMaccErr));
+	}
+
+	/* Clear local statistics. */
+	SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
+		  sizeof(pAC->Pnmi.VirtualCounterOffset));
+
+	pAC->Pnmi.RlmtChangeCts = 0;
+	pAC->Pnmi.RlmtChangeTime = 0;
+
+	SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
+		sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
+	pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
+	pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
+	pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
+	pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
+	pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
+	pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
+	pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
+	pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
+	pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
+	pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
+	pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
+	pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
+}
+
+/*****************************************************************************
+ *
+ * GetTrapEntry - Get an entry in the trap buffer
+ *
+ * Description:
+ *	The trap buffer stores various events. A user application somehow
+ *	gets notified that an event occured and retrieves the trap buffer
+ *	contens (or simply polls the buffer). The buffer is organized as
+ *	a ring which stores the newest traps at the beginning. The oldest
+ *	traps are overwritten by the newest ones. Each trap entry has a
+ *	unique number, so that applications may detect new trap entries.
+ *
+ * Returns:
+ *	A pointer to the trap entry
+ */
+PNMI_STATIC char* GetTrapEntry(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_U32 TrapId,		/* SNMP ID of the trap */
+unsigned int Size)	/* Space needed for trap entry */
+{
+	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
+	unsigned int	BufFree = pAC->Pnmi.TrapBufFree;
+	unsigned int	Beg = pAC->Pnmi.TrapQueueBeg;
+	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
+	char			*pBuf = &pAC->Pnmi.TrapBuf[0];
+	int			Wrap;
+	unsigned int	NeededSpace;
+	unsigned int	EntrySize;
+	SK_U32			Val32;
+	SK_U64			Val64;
+
+	/* Last byte of entry will get a copy of the entry length. */
+	Size ++;
+
+	/* Calculate needed buffer space. */
+	if (Beg >= Size) {
+
+		NeededSpace = Size;
+		Wrap = SK_FALSE;
+	}
+	else {
+		NeededSpace = Beg + Size;
+		Wrap = SK_TRUE;
+	}
+
+	/*
+	 * Check if enough buffer space is provided. Otherwise
+	 * free some entries. Leave one byte space between begin
+	 * and end of buffer to make it possible to detect whether
+	 * the buffer is full or empty.
+	 */
+	while (BufFree < NeededSpace + 1) {
+
+		if (End == 0) {
+
+			End = SK_PNMI_TRAP_QUEUE_LEN;
+		}
+
+		EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
+		BufFree += EntrySize;
+		End -= EntrySize;
+#ifdef DEBUG
+		SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
+#endif /* DEBUG */
+		if (End == BufPad) {
+#ifdef DEBUG
+			SK_MEMSET(pBuf, (char)(-1), End);
+#endif /* DEBUG */
+			BufFree += End;
+			End = 0;
+			BufPad = 0;
+		}
+	}
+
+	/*
+	 * Insert new entry as first entry. Newest entries are
+	 * stored at the beginning of the queue.
+	 */
+	if (Wrap) {
+
+		BufPad = Beg;
+		Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
+	}
+	else {
+		Beg = Beg - Size;
+	}
+	BufFree -= NeededSpace;
+
+	/* Save the current offsets. */
+	pAC->Pnmi.TrapQueueBeg = Beg;
+	pAC->Pnmi.TrapQueueEnd = End;
+	pAC->Pnmi.TrapBufPad = BufPad;
+	pAC->Pnmi.TrapBufFree = BufFree;
+
+	/* Initialize the trap entry. */
+	*(pBuf + Beg + Size - 1) = (char)Size;
+	*(pBuf + Beg) = (char)Size;
+	Val32 = (pAC->Pnmi.TrapUnique) ++;
+	SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
+	SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
+	Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+	SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
+
+	return (pBuf + Beg);
+}
+
+/*****************************************************************************
+ *
+ * CopyTrapQueue - Copies the trap buffer for the TRAP OID
+ *
+ * Description:
+ *	On a query of the TRAP OID the trap buffer contents will be
+ *	copied continuously to the request buffer, which must be large
+ *	enough. No length check is performed.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void CopyTrapQueue(
+SK_AC *pAC,		/* Pointer to adapter context */
+char *pDstBuf)		/* Buffer to which the queued traps will be copied */
+{
+	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
+	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
+	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
+	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
+	unsigned int	Len;
+	unsigned int	DstOff = 0;
+
+	while (Trap != End) {
+
+		Len = (unsigned int)*(pBuf + Trap);
+
+		/*
+		 * Last byte containing a copy of the length will
+		 * not be copied.
+		 */
+		*(pDstBuf + DstOff) = (char)(Len - 1);
+		SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
+		DstOff += Len - 1;
+
+		Trap += Len;
+		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
+
+			Trap = BufPad;
+		}
+	}
+}
+
+/*****************************************************************************
+ *
+ * GetTrapQueueLen - Get the length of the trap buffer
+ *
+ * Description:
+ *	Evaluates the number of currently stored traps and the needed
+ *	buffer size to retrieve them.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void GetTrapQueueLen(
+SK_AC *pAC,		/* Pointer to adapter context */
+unsigned int *pLen,	/* Length in Bytes of all queued traps */
+unsigned int *pEntries)	/* Returns number of trapes stored in queue */
+{
+	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
+	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
+	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
+	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
+	unsigned int	Len;
+	unsigned int	Entries = 0;
+	unsigned int	TotalLen = 0;
+
+	while (Trap != End) {
+
+		Len = (unsigned int)*(pBuf + Trap);
+		TotalLen += Len - 1;
+		Entries ++;
+
+		Trap += Len;
+		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
+
+			Trap = BufPad;
+		}
+	}
+
+	*pEntries = Entries;
+	*pLen = TotalLen;
+}
+
+/*****************************************************************************
+ *
+ * QueueSimpleTrap - Store a simple trap to the trap buffer
+ *
+ * Description:
+ *	A simple trap is a trap with now additional data. It consists
+ *	simply of a trap code.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void QueueSimpleTrap(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_U32 TrapId)		/* Type of sensor trap */
+{
+	GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
+}
+
+/*****************************************************************************
+ *
+ * QueueSensorTrap - Stores a sensor trap in the trap buffer
+ *
+ * Description:
+ *	Gets an entry in the trap buffer and fills it with sensor related
+ *	data.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void QueueSensorTrap(
+SK_AC *pAC,			/* Pointer to adapter context */
+SK_U32 TrapId,			/* Type of sensor trap */
+unsigned int SensorIndex)	/* Index of sensor which caused the trap */
+{
+	char		*pBuf;
+	unsigned int	Offset;
+	unsigned int	DescrLen;
+	SK_U32		Val32;
+
+	/* Get trap buffer entry. */
+	DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
+	
+	pBuf = GetTrapEntry(pAC, TrapId,
+		SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
+	Offset = SK_PNMI_TRAP_SIMPLE_LEN;
+
+	/* Store additionally sensor trap related data. */
+	Val32 = OID_SKGE_SENSOR_INDEX;
+	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+	*(pBuf + Offset + 4) = 4;
+	Val32 = (SK_U32)SensorIndex;
+	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
+	Offset += 9;
+	
+	Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
+	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+	*(pBuf + Offset + 4) = (char)DescrLen;
+	SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
+		DescrLen);
+	Offset += DescrLen + 5;
+
+	Val32 = OID_SKGE_SENSOR_TYPE;
+	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+	*(pBuf + Offset + 4) = 1;
+	*(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
+	Offset += 6;
+
+	Val32 = OID_SKGE_SENSOR_VALUE;
+	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+	*(pBuf + Offset + 4) = 4;
+	Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
+	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
+}
+
+/*****************************************************************************
+ *
+ * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
+ *
+ * Description:
+ *	Nothing further to explain.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void QueueRlmtNewMacTrap(
+SK_AC *pAC,		/* Pointer to adapter context */
+unsigned int ActiveMac)	/* Index (0..n) of the currently active port */
+{
+	char	*pBuf;
+	SK_U32	Val32;
+
+	pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
+		SK_PNMI_TRAP_RLMT_CHANGE_LEN);
+
+	Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
+	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
+	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
+	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
+}
+
+/*****************************************************************************
+ *
+ * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
+ *
+ * Description:
+ *	Nothing further to explain.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void QueueRlmtPortTrap(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_U32 TrapId,		/* Type of RLMT port trap */
+unsigned int PortIndex)	/* Index of the port, which changed its state */
+{
+	char	*pBuf;
+	SK_U32	Val32;
+
+	pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
+
+	Val32 = OID_SKGE_RLMT_PORT_INDEX;
+	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
+	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
+	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
+}
+
+/*****************************************************************************
+ *
+ * CopyMac - Copies a MAC address
+ *
+ * Description:
+ *	Nothing further to explain.
+ *
+ * Returns:
+ *	Nothing
+ */
+PNMI_STATIC void CopyMac(
+char		*pDst,	/* Pointer to destination buffer */
+SK_MAC_ADDR *pMac)	/* Pointer of Source */
+{
+	int	i;
+
+	for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
+
+		*(pDst + i) = pMac->a[i];
+	}
+}
+
+#ifdef SK_POWER_MGMT
+/*****************************************************************************
+ *
+ * PowerManagement - OID handler function of PowerManagement OIDs
+ *
+ * Description:
+ *	The code is simple. No description necessary.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                               exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+
+PNMI_STATIC int PowerManagement(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* Get/PreSet/Set action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
+unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	int i;
+	unsigned int HwPortIndex;
+
+	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
+
+	/* Check instance. We only handle single instance variables. */
+	if ((Instance != (SK_U32)(-1))) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_INST);
+	}
+
+	/* Get hardware port index */
+	HwPortIndex = NetIndex;
+
+	/* Check length. */
+	switch (Id) {
+
+	case OID_PNP_CAPABILITIES:
+		if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
+
+			*pLen = sizeof(SK_PNP_CAPABILITIES);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_PNP_SET_POWER:
+	case OID_PNP_QUERY_POWER:
+		if (*pLen < sizeof(SK_DEVICE_POWER_STATE)) {
+
+			*pLen = sizeof(SK_DEVICE_POWER_STATE);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_PNP_ADD_WAKE_UP_PATTERN:
+	case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+		if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
+
+			*pLen = sizeof(SK_PM_PACKET_PATTERN);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	case OID_PNP_ENABLE_WAKE_UP:
+		if (*pLen < sizeof(SK_U32)) {
+
+			*pLen = sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+	}
+
+	/* Perform action. */
+	if (Action == SK_PNMI_GET) {
+
+		/* Get value. */
+		switch (Id) {
+
+		case OID_PNP_CAPABILITIES:
+			RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
+			break;
+
+		case OID_PNP_QUERY_POWER:
+			/*
+			 * The Windows DDK describes: An OID_PNP_QUERY_POWER requests
+			 * the miniport to indicate whether it can transition its NIC
+			 * to the low-power state.
+			 * A miniport driver must always return NDIS_STATUS_SUCCESS
+			 * to a query of OID_PNP_QUERY_POWER.
+			 */
+			*pLen = sizeof(SK_DEVICE_POWER_STATE);
+			RetCode = SK_PNMI_ERR_OK;
+			break;
+
+			/*
+			 * NDIS handles these OIDs as write-only.
+			 * So in case of get action the buffer with written length = 0
+			 * is returned.
+			 */
+		case OID_PNP_SET_POWER:
+		case OID_PNP_ADD_WAKE_UP_PATTERN:
+		case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+			*pLen = 0;
+			RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
+			break;
+
+		case OID_PNP_ENABLE_WAKE_UP:
+			RetCode = SkPowerGetEnableWakeUp(pAC, IoC, HwPortIndex, pBuf, pLen);
+			break;
+
+		default:
+			RetCode = SK_PNMI_ERR_GENERAL;
+			break;
+		}
+
+		return (RetCode);
+	}
+
+	/* Perform PRESET or SET. */
+
+	/* The POWER module does not support PRESET action. */
+	if (Action == SK_PNMI_PRESET) {
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	i = HwPortIndex;
+
+	switch (Id) {
+	case OID_PNP_SET_POWER:
+		/* Dual net mode? */
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+			if (RetCode = SkPowerSetPower(pAC, IoC, i, pBuf, pLen)) {
+				break;
+			}
+		}
+		break;
+
+	case OID_PNP_ADD_WAKE_UP_PATTERN:
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+			if (RetCode = SkPowerAddWakeUpPattern(pAC, IoC, i, pBuf, pLen)) {
+				break;
+			}
+		}
+		break;
+
+	case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+			if (RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, i, pBuf, pLen)) {
+				break;
+			}
+		}
+		break;
+
+	case OID_PNP_ENABLE_WAKE_UP:
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+			if (RetCode = SkPowerSetEnableWakeUp(pAC, IoC, i, pBuf, pLen)) {
+				break;
+			}
+		}
+		break;
+
+	default:
+		RetCode = SK_PNMI_ERR_READ_ONLY;
+	}
+
+	return (RetCode);
+}
+#endif /* SK_POWER_MGMT */
+
+#ifdef SK_DIAG_SUPPORT
+/*****************************************************************************
+ *
+ * DiagActions - OID handler function of Diagnostic driver
+ *
+ * Description:
+ *	The code is simple. No description necessary.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+
+PNMI_STATIC int DiagActions(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_U32	DiagStatus;
+	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
+
+	/* Check instance. We only handle single instance variables. */
+	if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_INST);
+	}
+
+	/* Check length. */
+	switch (Id) {
+
+	case OID_SKGE_DIAG_MODE:
+		if (*pLen < sizeof(SK_U32)) {
+
+			*pLen = sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
+		*pLen = 0;
+		return (SK_PNMI_ERR_GENERAL);
+	}
+
+	/* Perform action. */
+	if (Action == SK_PNMI_GET) {
+
+		/* Get value. */
+		switch (Id) {
+
+		case OID_SKGE_DIAG_MODE:
+			DiagStatus = pAC->Pnmi.DiagAttached;
+			SK_PNMI_STORE_U32(pBuf, DiagStatus);
+			*pLen = sizeof(SK_U32);
+			RetCode = SK_PNMI_ERR_OK;
+			break;
+
+		default:
+			*pLen = 0;
+			RetCode = SK_PNMI_ERR_GENERAL;
+			break;
+		}
+		return (RetCode);
+	}
+
+	/* From here SET or PRESET value. */
+
+	/* PRESET value is not supported. */
+	if (Action == SK_PNMI_PRESET) {
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	/* SET value. */
+	switch (Id) {
+		case OID_SKGE_DIAG_MODE:
+
+			/* Handle the SET. */
+			switch (*pBuf) {
+
+				/* Attach the DIAG to this adapter. */
+				case SK_DIAG_ATTACHED:
+					/* Check if we come from running. */
+					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+
+						RetCode = SkDrvLeaveDiagMode(pAC);
+					}
+					else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
+
+						RetCode = SK_PNMI_ERR_OK;
+					}
+					else {
+
+						RetCode = SK_PNMI_ERR_GENERAL;
+					}
+
+					if (RetCode == SK_PNMI_ERR_OK) {
+
+						pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
+					}
+					break;
+
+				/* Enter the DIAG mode in the driver. */
+				case SK_DIAG_RUNNING:
+					RetCode = SK_PNMI_ERR_OK;
+
+					/*
+					 * If DiagAttached is set, we can tell the driver
+					 * to enter the DIAG mode.
+					 */
+					if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
+						/* If DiagMode is not active, we can enter it. */
+						if (!pAC->DiagModeActive) {
+
+							RetCode = SkDrvEnterDiagMode(pAC);
+						}
+						else {
+
+							RetCode = SK_PNMI_ERR_GENERAL;
+						}
+					}
+					else {
+
+						RetCode = SK_PNMI_ERR_GENERAL;
+					}
+
+					if (RetCode == SK_PNMI_ERR_OK) {
+
+						pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
+					}
+					break;
+
+				case SK_DIAG_IDLE:
+					/* Check if we come from running. */
+					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+
+						RetCode = SkDrvLeaveDiagMode(pAC);
+
+					}
+					else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
+
+						RetCode = SK_PNMI_ERR_OK;
+					}
+					else {
+
+						RetCode = SK_PNMI_ERR_GENERAL;
+					}
+
+					if (RetCode == SK_PNMI_ERR_OK) {
+
+						pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
+					}
+					break;
+
+				default:
+					RetCode = SK_PNMI_ERR_BAD_VALUE;
+					break;
+			}
+			break;
+
+		default:
+			RetCode = SK_PNMI_ERR_GENERAL;
+	}
+
+	if (RetCode == SK_PNMI_ERR_OK) {
+		*pLen = sizeof(SK_U32);
+	}
+	else {
+
+		*pLen = 0;
+	}
+	return (RetCode);
+}
+#endif /* SK_DIAG_SUPPORT */
+
+/*****************************************************************************
+*
+* VctGetDspLength
+*
+* Description:
+* 	Reads/Calculates the DSP length
+*   
+*
+* Returns:
+*   Always 0
+*/
+static void VctGetDspLength(
+SK_AC		*pAC,
+SK_IOC		IoC,
+SK_U32		Port,
+SK_PNMI_VCT	*pvctInfo)
+{
+	SK_U8	port_cable_length;
+	SK_U8	len;
+	SK_U32	ret_code;
+	int		chipid;
+
+	port_cable_length = pAC->GIni.GP[Port].PCableLen;
+	chipid = pAC->GIni.GIChipId;
+	
+	/*
+	 * Calculate DPS length
+	 */
+	if (pAC->GIni.GP[Port].PLinkSpeedUsed == SK_LSPEED_1000MBPS) {
+		if ((chipid  == CHIP_ID_YUKON_XL)	 ||
+			(chipid  == CHIP_ID_YUKON_EC_U) ||
+			(chipid  == CHIP_ID_YUKON_EX)) {
+	    
+			/* Calculate DSP length */
+			if (port_cable_length < 13) {
+				len = 1;			
+			}
+			else if (port_cable_length < 36) {
+				len = 3 * (port_cable_length) - 38;			
+			}
+			else if (port_cable_length < 68) {
+				len = port_cable_length + (port_cable_length / 2);			
+			}
+			else {
+				len = port_cable_length + 37;			
+			}
+
+			if (len <= DSP_CABLE_RANGE_UNDER_50_END) {
+				pvctInfo->CableLen = DSP_CABLE_RANGE_UNDER_50;
+			}
+			else if (len <= DSP_CABLE_RANGE_50_TO_80_END) {
+				pvctInfo->CableLen = DSP_CABLE_RANGE_50_TO_80;
+			}
+			else if (len <= DSP_CABLE_RANGE_80_TO_140_END) {
+				pvctInfo->CableLen = DSP_CABLE_RANGE_80_TO_150;
+			}
+			else {
+				pvctInfo->CableLen = DSP_CABLE_RANGE_ABOVE_140;
+			}
+		}
+		else {
+			pvctInfo->CableLen = port_cable_length;			
+		}
+	}
+	else {
+		pvctInfo->CableLen = DSP_CABLE_RANGE_NOT_SUPPORTED;
+	}
+}
+
+
+
+
+/*****************************************************************************
+ *
+ * Vct - OID handler function of OIDs for Virtual Cable Tester (VCT)
+ *
+ * Description:
+ *	The code is simple. No description necessary.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was performed successfully.
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *	                         the correct data (e.g. a 32bit value is
+ *	                         needed, but a 16 bit value was passed).
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter).
+ *	SK_PNMI_ERR_READ_ONLY	 Only the Get action is allowed.
+ *
+ */
+
+PNMI_STATIC int Vct(
+SK_AC *pAC,		/* Pointer to adapter context */
+SK_IOC IoC,		/* IO context handle */
+int Action,		/* GET/PRESET/SET action */
+SK_U32 Id,		/* Object ID that is to be processed */
+char *pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,	/* Instance (-1,2..n) that is to be queried */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+	SK_GEPORT	*pPrt;
+	SK_PNMI_VCT	*pVctBackupData;
+	SK_U32		LogPortMax;
+	SK_U32		PhysPortMax;
+	SK_U32		PhysPortIndex;
+	SK_U32		Limit;
+	SK_U32		Offset;
+	SK_U32		RetCode;
+	int			i;
+	SK_EVPARA	Para;
+
+	RetCode = SK_PNMI_ERR_GENERAL;
+
+	/* Calculate the port indexes from the instance. */
+	PhysPortMax = pAC->GIni.GIMacsFound;
+	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+
+	/* Dual net mode? */
+	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+		LogPortMax--;
+	}
+
+	if ((Instance != (SK_U32) (-1))) {
+		/*
+		 * Get one instance of that OID, so check the instance range:
+		 * There is no virtual port with an Instance == 1, so we get
+		 * the values from one physical port only.
+		 */
+		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+			PhysPortIndex = NetIndex;
+		}
+		else {
+			if ((Instance < 2) || (Instance > LogPortMax)) {
+				*pLen = 0;
+				return (SK_PNMI_ERR_UNKNOWN_INST);
+			}
+			PhysPortIndex = Instance - 2;
+		}
+		Limit = PhysPortIndex + 1;
+	}
+	else {
+		/*
+		 * Instance == (SK_U32) (-1), so get all instances of that OID.
+		 * There is no virtual port with an Instance == 1, so we get
+		 * the values from all physical ports.
+		 */
+
+		/* DualNet mode. */
+		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+			PhysPortIndex = NetIndex;
+			Limit = PhysPortIndex + 1;
+		}
+		/* SingleNet mode. */
+		else {
+			PhysPortIndex = 0;
+			Limit = PhysPortMax;
+		}
+	}
+
+	pPrt = &pAC->GIni.GP[PhysPortIndex];
+
+	/* Check MAC type. */
+	if ((Id != OID_SKGE_VCT_CAPABILITIES) &&
+		(pPrt->PhyType != SK_PHY_MARV_COPPER)) {
+		*pLen = 0;
+		return (SK_PNMI_ERR_NOT_SUPPORTED);
+	}
+
+	/* Check action type. */
+	if (Action == SK_PNMI_GET) {
+		/* Check length. */
+		switch (Id) {
+
+		case OID_SKGE_VCT_GET:
+			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
+				*pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			break;
+
+		case OID_SKGE_VCT_STATUS:
+		case OID_SKGE_VCT_CAPABILITIES:
+			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
+				*pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
+				return (SK_PNMI_ERR_TOO_SHORT);
+			}
+			break;
+
+		default:
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+
+		/* Get value. */
+		Offset = 0;
+		for (; PhysPortIndex < Limit; PhysPortIndex++) {
+
+			pPrt = &pAC->GIni.GP[PhysPortIndex];
+
+			switch (Id) {
+
+			case OID_SKGE_VCT_GET:
+				if (!pPrt->PHWLinkUp &&
+					(pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
+
+					RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
+
+					if (RetCode == 0) {
+
+						/* VCT test is finished, so save the data. */
+						VctGetResults(pAC, IoC, PhysPortIndex);
+
+						Para.Para32[0] = PhysPortIndex;
+						Para.Para32[1] = -1;
+						SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+
+						/* SkEventDispatcher(pAC, IoC); */
+					}
+				}
+
+				/* Initialize backup data pointer. */
+				pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
+
+				/* Get all results. */
+				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
+
+				Offset++;
+
+				VctGetDspLength(pAC, IoC, PhysPortIndex, pVctBackupData);
+				
+				*(pBuf + Offset) = pVctBackupData->CableLen;
+				Offset++;
+				for (i = 0; i < 4; i++) {
+
+					SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->MdiPairLen[i]);
+					Offset += sizeof(SK_U32);
+				}
+				for (i = 0; i < 4; i++) {
+
+					*(pBuf + Offset) = pVctBackupData->MdiPairSts[i];
+					Offset++;
+				}
+
+				RetCode = SK_PNMI_ERR_OK;
+				break;
+
+			case OID_SKGE_VCT_STATUS:
+				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
+
+				Offset++;
+				RetCode = SK_PNMI_ERR_OK;
+				break;
+
+			case OID_SKGE_VCT_CAPABILITIES:
+				if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+					*(pBuf + Offset) = SK_PNMI_VCT_NOT_SUPPORTED;
+				}
+				else {
+					*(pBuf + Offset) = SK_PNMI_VCT_SUPPORTED_VERSION;
+				}
+				Offset++;
+
+				RetCode = SK_PNMI_ERR_OK;
+				break;
+
+			default:
+				*pLen = 0;
+				return (SK_PNMI_ERR_GENERAL);
+			}
+		} /* for */
+		*pLen = Offset;
+		return (RetCode);
+
+	} /* if SK_PNMI_GET */
+
+	/*
+	 * From here SET or PRESET action. Check if the passed
+	 * buffer length is plausible.
+	 */
+
+	/* Check length. */
+	switch (Id) {
+	case OID_SKGE_VCT_SET:
+		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
+			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
+			return (SK_PNMI_ERR_TOO_SHORT);
+		}
+		break;
+
+	default:
+		*pLen = 0;
+		return (SK_PNMI_ERR_GENERAL);
+	}
+
+	/* Perform PRESET or SET. */
+
+	/* VCT does not support PRESET action. */
+	if (Action == SK_PNMI_PRESET) {
+
+		return (SK_PNMI_ERR_OK);
+	}
+
+	Offset = 0;
+	for (; PhysPortIndex < Limit; PhysPortIndex++) {
+
+		pPrt = &pAC->GIni.GP[PhysPortIndex];
+
+		switch (Id) {
+		case OID_SKGE_VCT_SET: /* Start VCT test. */
+			if (!pPrt->PHWLinkUp) {
+				SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
+
+				RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
+
+				if (RetCode == 0) { /* RetCode: 0 => Start! */
+					pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
+					pAC->Pnmi.VctStatus[PhysPortIndex] &=
+						~(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_LINK);
+
+					/* Start VCT timer counter. */
+					SK_MEMSET((char *)&Para, 0, sizeof(Para));
+					Para.Para32[0] = PhysPortIndex;
+					Para.Para32[1] = -1;
+
+					SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex],
+						SK_PNMI_VCT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
+
+					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+					RetCode = SK_PNMI_ERR_OK;
+				}
+				else { /* RetCode: 2 => Running! */
+					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+					RetCode = SK_PNMI_ERR_OK;
+				}
+			}
+			else { /* RetCode: 4 => Link! */
+				RetCode = 4;
+				SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+				RetCode = SK_PNMI_ERR_OK;
+			}
+			Offset += sizeof(SK_U32);
+			break;
+
+		default:
+			*pLen = 0;
+			return (SK_PNMI_ERR_GENERAL);
+		}
+	} /* for */
+	*pLen = Offset;
+	return (RetCode);
+
+} /* Vct */
+
+
+/*****************************************************************************
+*
+* VctGetResults
+*
+* Description:
+*   Read and calculate the Results
+*   
+*
+* Returns:
+*   Always 0
+*/
+static void VctGetResults(
+SK_AC		*pAC,
+SK_IOC		IoC,
+SK_U32		Port)
+{
+	int			i;
+	SK_U8		tmp_u8;
+	SK_U32		tmp_u32;
+	SK_U32		MinCableLen;
+	SK_GEPORT	*pPrt;
+	SK_PNMI_VCT *pVctInfo;
+	int			ChipId;
+
+	pPrt = &pAC->GIni.GP[Port];
+	pVctInfo = &pAC->Pnmi.VctBackup[Port];
+	ChipId = pAC->GIni.GIChipId;
+
+	/*
+	 * Calculate VCT length and status
+	 */
+	if (ChipId == CHIP_ID_YUKON_EX) {
+		/*
+		 * For Yukon Extreme PHY the previous VCT status determination is different and 
+		 * therefore the status result from PNMI is not valid. Calculate VCT status for
+		 * each cable pair based on reflection amplitude polarity and amplitude value.
+		 */
+		for (i = 0; i < 4; i++) {
+			/* Invalid VCT status for cable pair */
+			if ((pPrt->PMdiPairLen[i]) == 0xff &&
+				(pPrt->PMdiPairSts[i]) == 0xff) {
+				pVctInfo->MdiPairSts[i] = SK_PNMI_VCT_TEST_FAIL;
+			}
+			/* No fault reported for cable pair */
+			else if ((pPrt->PMdiPairLen[i]) == 0 &&
+					 (pPrt->PMdiPairSts[i]) == 0) {
+				pVctInfo->MdiPairSts[i] = SK_PNMI_VCT_NORMAL_CABLE;
+			}
+			/*
+			 * Positive reflection amplitude polarity and amlitude value
+			 * greater than 40 --> open/broken cable pair.
+			 */
+			else if ((pPrt->PMdiPairSts[i] & 0x80) &&
+					 ((pPrt->PMdiPairSts[i] & 0x7f) > 40)) {
+				pVctInfo->MdiPairSts[i] = SK_PNMI_VCT_OPEN_CABLE;
+			}
+			/*
+			 * Negative reflection amplitude polarity and amlitude value
+			 * greater than 40 --> short at same cable pair.
+			 */
+			else if (((pPrt->PMdiPairSts[i] & 0x80) == 0) &&
+					 ((pPrt->PMdiPairSts[i] & 0x7f) > 40)) {
+				pVctInfo->MdiPairSts[i] = SK_PNMI_VCT_SHORT_CABLE;
+			}
+			/*
+			 * Positive or negative reflection amplitude polarity and amlitude value
+			 * less than or equal to 40 --> impedance missmatch at same cable pair.
+			 */
+			else {
+				pVctInfo->MdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
+			}
+		}
+	}
+	else {
+		for (i=0; i<4; i++) {
+			if (((ChipId  == CHIP_ID_YUKON_FE) ||
+				 (ChipId  == CHIP_ID_YUKON_FE_P)) &&
+				(i > 1)) {
+				pVctInfo->MdiPairSts[i] = SK_PNMI_VCT_NOT_PRESENT;
+			}
+			else {
+				if ((pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) &&
+					(pPrt->PMdiPairLen[i] > 28) && (pPrt->PMdiPairLen[i] < 0xff)) {
+					pVctInfo->MdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
+				}
+				else {
+					pVctInfo->MdiPairSts[i] = pPrt->PMdiPairSts[i];
+				}
+			}
+		}	
+	}
+	
+	/* 
+	 * Calculate length for each cable pair.
+	 * Ignore values <= MinLength, the linear factor is 4/5. 
+	 */
+	switch (ChipId) {
+		case CHIP_ID_YUKON_FE:
+			MinCableLen = 25;
+			break;
+		case CHIP_ID_YUKON_FE_P:
+			MinCableLen = 17;
+			break;
+		case CHIP_ID_YUKON_EX:
+			MinCableLen = 8;
+			break;
+		default:
+			MinCableLen = 35;
+			break;
+	}
+
+	for (i=0; i<4; i++) {
+		if ((pPrt->PMdiPairLen[i] > (SK_U32)MinCableLen) && 
+			(pPrt->PMdiPairLen[i] < (SK_U32)0xff)) {
+
+			pVctInfo->MdiPairLen[i] = 1000UL *  
+				((pPrt->PMdiPairLen[i] - MinCableLen) * 4 / 5);
+		}
+		else {
+			/* No cable or short cable. */
+			pVctInfo->MdiPairLen[i] = 0;
+		}
+	}
+
+	/* Swap pair length and status for Yukon FE due to hardware design issue */
+	if (ChipId  == CHIP_ID_YUKON_FE) {
+
+		tmp_u8 = pVctInfo->MdiPairSts[0];
+		pVctInfo->MdiPairSts[0] = pVctInfo->MdiPairSts[1];
+		pVctInfo->MdiPairSts[1] = tmp_u8;
+
+		tmp_u32 = pVctInfo->MdiPairLen[0];
+		pVctInfo->MdiPairLen[0] = pVctInfo->MdiPairLen[1];
+		pVctInfo->MdiPairLen[1] = tmp_u32;
+	}
+
+
+	pAC->Pnmi.VctStatus[Port] &= ~SK_PNMI_VCT_PENDING;
+	pAC->Pnmi.VctStatus[Port] |= (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
+	pAC->Pnmi.VctStatus[Port] &= ~SK_PNMI_VCT_OLD_VCT_DATA;
+
+} /* GetVctResults */
+
+
+PNMI_STATIC void CheckVctStatus(
+SK_AC		*pAC,
+SK_IOC		IoC,
+char		*pBuf,
+SK_U32		Offset,
+SK_U32		PhysPortIndex)
+{
+	SK_GEPORT 	*pPrt;
+	SK_PNMI_VCT	*pVctData;
+	SK_U8		VctStatus;
+	SK_U32		RetCode;
+
+	pPrt = &pAC->GIni.GP[PhysPortIndex];
+
+	pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
+	pVctData->VctStatus = SK_PNMI_VCT_NONE;
+
+	VctStatus = pAC->Pnmi.VctStatus[PhysPortIndex];
+
+	if (!pPrt->PHWLinkUp) {
+
+		/* Was a VCT test ever made before? */
+		if (VctStatus & SK_PNMI_VCT_TEST_DONE) {
+			if (VctStatus & SK_PNMI_VCT_LINK) {
+				pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
+			}
+			else {
+				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
+			}
+		}
+
+		/* Check VCT test status. */
+		RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
+
+		if (RetCode == 2) { /* VCT test is running. */
+			pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
+		}
+		else { /* VCT data was copied to pAC here. Check PENDING state. */
+			if (VctStatus & SK_PNMI_VCT_PENDING) {
+				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
+			}
+		}
+
+		if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
+			pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
+		}
+	}
+	else {
+		/* Was a VCT test ever made before? */
+		if (VctStatus & SK_PNMI_VCT_TEST_DONE) {
+			pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
+			pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
+		}
+
+		/* DSP only valid in 100/1000 modes. */
+		if (pPrt->PLinkSpeedUsed != SK_LSPEED_STAT_10MBPS) {
+			pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
+		}
+	}
+} /* CheckVctStatus */
+
+
+/*****************************************************************************
+ *
+ *      SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
+ *                       PNMI function depending on the subcommand and
+ *                       returns all data belonging to the complete database
+ *                       or OID request.
+ *
+ * Description:
+ *	Looks up the requested subcommand, calls the corresponding handler
+ *	function and passes all required parameters to it.
+ *	The function is called by the driver. It is needed to handle the new
+ *  generic PNMI IOCTL. This IOCTL is given to the driver and contains both
+ *  the OID and a subcommand to decide what kind of request has to be done.
+ *
+ * Returns:
+ *	SK_PNMI_ERR_OK           The request was successfully performed
+ *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
+ *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
+ *	                         the data.
+ *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
+ *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *	                         adapter.
+ */
+int SkPnmiGenIoctl(
+SK_AC		*pAC,		/* Pointer to adapter context struct */
+SK_IOC		IoC,		/* I/O context */
+void		*pBuf,		/* Buffer used for the management data transfer */
+unsigned int *pLen,		/* Length of buffer */
+SK_U32		NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+{
+SK_I32	Mode;			/* Store value of subcommand. */
+SK_U32	Oid;			/* Store value of OID. */
+int		ReturnCode;		/* Store return value to show status of PNMI action. */
+int 	HeaderLength;	/* Length of desired action plus OID. */
+
+	ReturnCode = SK_PNMI_ERR_GENERAL;
+
+	SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
+	SK_MEMCPY(&Oid, (char *)pBuf + sizeof(SK_I32), sizeof(SK_U32));
+	HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
+	*pLen = *pLen - HeaderLength;
+	SK_MEMCPY((char *)pBuf + sizeof(SK_I32), (char *)pBuf + HeaderLength, *pLen);
+
+	switch (Mode) {
+	case SK_GET_SINGLE_VAR:
+		ReturnCode = SkPnmiGetVar(pAC, IoC, Oid,
+				(char *)pBuf + sizeof(SK_I32), pLen,
+				((SK_U32) (-1)), NetIndex);
+		SK_PNMI_STORE_U32(pBuf, ReturnCode);
+		*pLen = *pLen + sizeof(SK_I32);
+		break;
+	case SK_PRESET_SINGLE_VAR:
+		ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid,
+				(char *)pBuf + sizeof(SK_I32), pLen,
+				((SK_U32) (-1)), NetIndex);
+		SK_PNMI_STORE_U32(pBuf, ReturnCode);
+		*pLen = *pLen + sizeof(SK_I32);
+		break;
+	case SK_SET_SINGLE_VAR:
+		ReturnCode = SkPnmiSetVar(pAC, IoC, Oid,
+				(char *)pBuf + sizeof(SK_I32), pLen,
+				((SK_U32) (-1)), NetIndex);
+		SK_PNMI_STORE_U32(pBuf, ReturnCode);
+		*pLen = *pLen + sizeof(SK_I32);
+		break;
+	case SK_GET_FULL_MIB:
+		ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+		break;
+	case SK_PRESET_FULL_MIB:
+		ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+		break;
+	case SK_SET_FULL_MIB:
+		ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+		break;
+	default:
+		break;
+	}
+	
+	return (ReturnCode);
+
+} /* SkGeIocGen */
+
+#ifdef SK_ASF
+/*****************************************************************************
+ *
+ * Asf
+ *
+ * Description:
+ *  The code is simple. No description necessary.
+ *
+ * Returns:
+ *  SK_PNMI_ERR_OK           The request was successfully performed.
+ *  SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+ *  SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+ *                           the correct data (e.g. a 32bit value is
+ *                           needed, but a 16 bit value was passed).
+ *  SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+ *                           exist (e.g. port instance 3 on a two port
+ *                           adapter.
+ */
+
+PNMI_STATIC int Asf(
+SK_AC *pAC,     /* Pointer to adapter context */
+SK_IOC IoC,     /* IO context handle */
+int Action,     /* GET/PRESET/SET action */
+SK_U32 Id,      /* Object ID that is to be processed */
+char *pBuf,     /* Buffer used for the management data transfer */
+unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+SK_U32 Instance,    /* Instance (1..n) that is to be queried or -1 */
+unsigned int TableIndex, /* Index to the Id table */
+SK_U32 NetIndex)    /* NetIndex (0..n), in single net mode always zero */
+{
+	SK_U32  RetCode = SK_PNMI_ERR_GENERAL;
+
+	/*
+	 * Check instance. We only handle single instance variables.
+	 */
+	if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+		*pLen = 0;
+		return (SK_PNMI_ERR_UNKNOWN_INST);
+	}
+
+	/* Perform action. */
+	/* GET value. */
+	if (Action == SK_PNMI_GET) {
+		switch (Id) {
+			case OID_SKGE_ASF:
+				RetCode = SkAsfGet(pAC, IoC, (SK_U8 *) pBuf, pLen);
+				break;
+			default:
+				RetCode = SkAsfGetOid( pAC, IoC, Id, Instance, (SK_U8 *)pBuf, pLen);
+				break;
+		}
+
+		return (RetCode);
+	}
+
+	/* PRESET value. */
+	if (Action == SK_PNMI_PRESET) {
+		switch (Id) {
+			case OID_SKGE_ASF:
+				RetCode = SkAsfPreSet(pAC, IoC, (SK_U8 *) pBuf, pLen);
+				break;
+			default:
+				RetCode = SkAsfPreSetOid( pAC, IoC, Id, Instance, (SK_U8 *)pBuf, pLen);
+				break;
+		}
+	}
+
+	/* SET value. */
+	if (Action == SK_PNMI_SET) {
+		switch (Id) {
+			case OID_SKGE_ASF:
+				RetCode = SkAsfSet(pAC, IoC, (SK_U8 *) pBuf, pLen);
+				break;
+			default:
+				RetCode = SkAsfSetOid( pAC, IoC, Id, Instance, (SK_U8 *)pBuf, pLen);
+				break;
+		}
+	}
+	return (RetCode);
+}
+#endif /* SK_ASF */
diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
new file mode 100755
index 0000000..bfe8d83
--- /dev/null
+++ b/drivers/net/sk98lin/skgesirq.c
@@ -0,0 +1,2720 @@
+/******************************************************************************
+ *
+ * Name:	skgesirq.c
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.36 $
+ * Date:	$Date: 2007/06/27 14:40:43 $
+ * Purpose:	Special IRQ module
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ *	Special Interrupt handler
+ *
+ *	The following abstract should show how this module is included
+ *	in the driver path:
+ *
+ *	In the ISR of the driver the bits for frame transmission complete and
+ *	for receive complete are checked and handled by the driver itself.
+ *	The bits of the slow path mask are checked after that and then the
+ *	entry into the so-called "slow path" is prepared. It is an implementors
+ *	decision whether this is executed directly or just scheduled by
+ *	disabling the mask. In the interrupt service routine some events may be
+ *	generated, so it would be a good idea to call the EventDispatcher
+ *	right after this ISR.
+ *
+ *	The Interrupt source register of the adapter is NOT read by this module.
+ *	SO if the drivers implementor needs a while loop around the
+ *	slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
+ *	each loop entered.
+ *
+ *	However, the MAC Interrupt status registers are read in a while loop.
+ *
+ */
+
+#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+#ifndef SK_SLIM
+#include "h/skgepnmi.h"		/* PNMI Definitions */
+#include "h/skrlmt.h"		/* RLMT Definitions */
+#endif
+#include "h/skdrv2nd.h"		/* Adapter Control and Driver specific Def. */
+
+/* local variables ************************************************************/
+
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skgesirq.c,v 2.36 2007/06/27 14:40:43 rschmidt Exp $ (C) Marvell.";
+#endif
+
+/* local function prototypes */
+#ifdef GENESIS
+static int	SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
+static int	SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
+static void	SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
+#endif /* GENESIS */
+#ifdef YUKON
+static int	SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
+static void	SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
+#endif /* YUKON */
+#ifdef OTHER_PHY
+static int	SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
+static int	SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
+static void	SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
+#endif /* OTHER_PHY */
+
+#ifdef GENESIS
+/*
+ * array of Rx counter from XMAC which are checked
+ * in AutoSense mode to check whether a link is not able to auto-negotiate.
+ */
+static const SK_U16 SkGeRxRegs[]= {
+	XM_RXF_64B,
+	XM_RXF_127B,
+	XM_RXF_255B,
+	XM_RXF_511B,
+	XM_RXF_1023B,
+	XM_RXF_MAX_SZ
+};
+#endif /* GENESIS */
+
+#ifdef __C2MAN__
+/*
+ *	Special IRQ function
+ *
+ *	General Description:
+ *
+ */
+intro()
+{}
+#endif
+
+/******************************************************************************
+ *
+ *	SkHWInitDefSense() - Default Autosensing mode initialization
+ *
+ * Description: sets the PLinkMode for HWInit
+ *
+ * Returns: N/A
+ */
+static void SkHWInitDefSense(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	pPrt->PAutoNegTimeOut = 0;
+
+	if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+		pPrt->PLinkMode = pPrt->PLinkModeConf;
+		return;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+		("AutoSensing: First mode %d on Port %d\n",
+		(int)SK_LMODE_AUTOFULL, Port));
+
+	pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
+
+	return;
+}	/* SkHWInitDefSense */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkHWSenseGetNext() - Get Next Autosensing Mode
+ *
+ * Description: gets the appropriate next mode
+ *
+ * Note:
+ *
+ */
+static SK_U8 SkHWSenseGetNext(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	pPrt->PAutoNegTimeOut = 0;
+
+	if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+		/* Leave all as configured */
+		return(pPrt->PLinkModeConf);
+	}
+
+	if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
+		/* Return next mode AUTOBOTH */
+		return((SK_U8)SK_LMODE_AUTOBOTH);
+	}
+
+	/* Return default autofull */
+	return((SK_U8)SK_LMODE_AUTOFULL);
+}	/* SkHWSenseGetNext */
+
+
+/******************************************************************************
+ *
+ *	SkHWSenseSetNext() - Autosensing Set next mode
+ *
+ * Description:	sets the appropriate next mode
+ *
+ * Returns: N/A
+ */
+static void SkHWSenseSetNext(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_U8	NewMode)	/* New Mode to be written in sense mode */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	pPrt->PAutoNegTimeOut = 0;
+
+	if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+		return;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+		("AutoSensing: next mode %d on Port %d\n",
+		(int)NewMode, Port));
+
+	pPrt->PLinkMode = NewMode;
+
+	return;
+}	/* SkHWSenseSetNext */
+#endif /* GENESIS */
+
+
+/******************************************************************************
+ *
+ *	SkHWLinkDown() - Link Down handling
+ *
+ * Description: handles the hardware link down signal
+ *
+ * Returns: N/A
+ */
+void SkHWLinkDown(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Disable all MAC interrupts */
+	SkMacIrqDisable(pAC, IoC, Port);
+
+	/* Disable Receiver and Transmitter */
+	SkMacRxTxDisable(pAC, IoC, Port);
+
+	/* Init default sense mode */
+	SkHWInitDefSense(pAC, IoC, Port);
+
+	if (!pPrt->PHWLinkUp) {
+		return;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Link down Port %d\n", Port));
+
+	/* Set Link to DOWN */
+	pPrt->PHWLinkUp = SK_FALSE;
+
+#ifndef SK_SLIM
+	/* Reset Port stati */
+	pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+	pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
+#endif /* !SK_SLIM */
+
+	/* Re-init PHY especially when the AutoSense default is set now */
+	SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
+
+	/* GP0: used for workaround of Rev. C Errata 2 */
+
+	/* Do NOT signal to RLMT */
+
+	/* Do NOT start the timer here */
+}	/* SkHWLinkDown */
+
+
+/******************************************************************************
+ *
+ *	SkHWLinkUp() - Link Up handling
+ *
+ * Description: handles the hardware link up signal
+ *
+ * Returns: N/A
+ */
+void SkHWLinkUp(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PHWLinkUp) {
+		/* We do NOT need to proceed on active link */
+		return;
+	}
+
+	pPrt->PHWLinkUp = SK_TRUE;
+
+#ifndef SK_SLIM
+	pPrt->PAutoNegFail = SK_FALSE;
+	pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+
+	if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
+		pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
+		pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
+		/* Link is up and no Auto-negotiation should be done */
+
+		/* Link speed should be the configured one */
+		switch (pPrt->PLinkSpeed) {
+		case SK_LSPEED_AUTO:
+			/* default is 1000 Mbps */
+		case SK_LSPEED_1000MBPS:
+			pPrt->PLinkSpeedUsed = (SK_U8)
+				((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) ?
+				 SK_LSPEED_STAT_1000MBPS : SK_LSPEED_STAT_100MBPS;
+			break;
+		case SK_LSPEED_100MBPS:
+			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
+			break;
+		case SK_LSPEED_10MBPS:
+			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
+			break;
+		}
+
+		/* Set Link Mode Status */
+		pPrt->PLinkModeStatus = (SK_U8)((pPrt->PLinkMode == SK_LMODE_FULL) ?
+			 SK_LMODE_STAT_FULL : SK_LMODE_STAT_HALF);
+
+		/* No flow control without auto-negotiation */
+		pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+#endif /* !SK_SLIM */
+
+		/* enable Rx/Tx */
+		(void)SkMacRxTxEnable(pAC, IoC, Port);
+#ifndef SK_SLIM
+	}
+#endif /* !SK_SLIM */
+}	/* SkHWLinkUp */
+
+
+/******************************************************************************
+ *
+ *	SkMacParity() - MAC parity workaround
+ *
+ * Description: handles MAC parity errors correctly
+ *
+ * Returns: N/A
+ */
+static void SkMacParity(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_EVPARA	Para;
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	SK_U32		TxMax;		/* Tx Max Size Counter */
+
+	TxMax = 0;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Clear IRQ Tx Parity Error */
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+		/* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
+		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
+			(SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
+			pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
+	}
+#endif /* YUKON */
+
+	if (pPrt->PCheckPar) {
+
+		if (Port == MAC_1) {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
+		}
+		else {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
+		}
+		Para.Para64 = Port;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+
+		Para.Para32[0] = Port;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+
+		return;
+	}
+
+	/* Check whether frames with a size of 1k were sent */
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		/* Snap statistic counters */
+		(void)SkXmUpdateStats(pAC, IoC, Port);
+
+		(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		(void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
+	}
+#endif /* YUKON */
+
+	if (TxMax > 0) {
+		/* From now on check the parity */
+		pPrt->PCheckPar = SK_TRUE;
+	}
+}	/* SkMacParity */
+
+
+/******************************************************************************
+ *
+ *	SkGeYuHwErr() - Hardware Error service routine (Genesis and Yukon)
+ *
+ * Description: handles all HW Error interrupts
+ *
+ * Returns: N/A
+ */
+static void SkGeYuHwErr(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O context */
+SK_U32	HwStatus)	/* Interrupt status word */
+{
+	SK_EVPARA	Para;
+	SK_U16		Word;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+		("HW-Error Status: 0x%08lX\n", HwStatus));
+
+	if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
+		/* PCI Errors occured */
+		if ((HwStatus & IS_IRQ_STAT) != 0) {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
+		}
+		else {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
+		}
+
+		/* Reset all bits in the PCI STATUS register */
+		SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
+
+		SK_TST_MODE_ON(IoC);
+		SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+		SK_TST_MODE_OFF(IoC);
+
+		Para.Para64 = 0;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+	}
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		if ((HwStatus & IS_NO_STAT_M1) != 0) {
+			/* Ignore it */
+			/* This situation is also indicated in the descriptor */
+			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+		}
+
+		if ((HwStatus & IS_NO_STAT_M2) != 0) {
+			/* Ignore it */
+			/* This situation is also indicated in the descriptor */
+			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+		}
+
+		if ((HwStatus & IS_NO_TIST_M1) != 0) {
+			/* Ignore it */
+			/* This situation is also indicated in the descriptor */
+			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
+		}
+
+		if ((HwStatus & IS_NO_TIST_M2) != 0) {
+			/* Ignore it */
+			/* This situation is also indicated in the descriptor */
+			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
+		}
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+		/* This is necessary only for Rx timing measurements */
+		if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
+			/* increment Time Stamp Timer counter (high) */
+			pAC->GIni.GITimeStampCnt++;
+
+			/* Clear Time Stamp Timer IRQ */
+			SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
+		}
+
+		if ((HwStatus & IS_IRQ_SENSOR) != 0) {
+			/* no sensors on 32-bit Yukon */
+			if (pAC->GIni.GIYukon32Bit) {
+				/* disable HW Error IRQ */
+				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
+			}
+		}
+	}
+#endif /* YUKON */
+
+	if ((HwStatus & IS_RAM_RD_PAR) != 0) {
+
+		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
+		Para.Para64 = 0;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+	}
+
+	if ((HwStatus & IS_RAM_WR_PAR) != 0) {
+
+		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
+		Para.Para64 = 0;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+	}
+
+	if ((HwStatus & IS_M1_PAR_ERR) != 0) {
+		SkMacParity(pAC, IoC, MAC_1);
+	}
+
+	if ((HwStatus & IS_M2_PAR_ERR) != 0) {
+		SkMacParity(pAC, IoC, MAC_2);
+	}
+
+	if ((HwStatus & IS_R1_PAR_ERR) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
+		Para.Para64 = MAC_1;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+
+		Para.Para32[0] = MAC_1;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+
+	if ((HwStatus & IS_R2_PAR_ERR) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
+		Para.Para64 = MAC_2;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+
+		Para.Para32[0] = MAC_2;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+}	/* SkGeYuHwErr */
+
+#ifdef YUK2
+/******************************************************************************
+ *
+ *	SkYuk2HwPortErr() - Service HW Errors for specified port (Yukon-2 only)
+ *
+ * Description: handles the HW Error interrupts for a specific port.
+ *
+ * Returns: N/A
+ */
+static void SkYuk2HwPortErr(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	HwStatus,	/* Interrupt status word */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_EVPARA	Para;
+	int			Queue;
+
+	if (Port == MAC_2) {
+		HwStatus >>= 8;
+	}
+
+	if ((HwStatus & Y2_HWE_L1_MASK) == 0) {
+		return;
+	}
+
+	if ((HwStatus & Y2_IS_PAR_RD1) != 0) {
+		/* Clear IRQ */
+		SK_OUT16(IoC, SELECT_RAM_BUFFER(Port, B3_RI_CTRL), RI_CLR_RD_PERR);
+
+		if (Port == MAC_1) {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E028, SKERR_SIRQ_E028MSG);
+		}
+		else {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E030, SKERR_SIRQ_E030MSG);
+		}
+	}
+
+	if ((HwStatus & Y2_IS_PAR_WR1) != 0) {
+		/* Clear IRQ */
+		SK_OUT16(IoC, SELECT_RAM_BUFFER(Port, B3_RI_CTRL), RI_CLR_WR_PERR);
+
+		if (Port == MAC_1) {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E029, SKERR_SIRQ_E029MSG);
+		}
+		else {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E031, SKERR_SIRQ_E031MSG);
+		}
+	}
+
+	if ((HwStatus & Y2_IS_PAR_MAC1) != 0) {
+		/* Clear IRQ */
+		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
+
+		if (Port == MAC_1) {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
+		}
+		else {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
+		}
+	}
+
+	if ((HwStatus & Y2_IS_PAR_RX1) != 0) {
+		if (Port == MAC_1) {
+			Queue = Q_R1;
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
+		}
+		else {
+			Queue = Q_R2;
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
+		}
+		/* Clear IRQ */
+		SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_PAR);
+	}
+
+	if ((HwStatus & Y2_IS_TCP_TXS1) != 0) {
+		if (Port == MAC_1) {
+			Queue = Q_XS1;
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E033, SKERR_SIRQ_E033MSG);
+		}
+		else {
+			Queue = Q_XS2;
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E035, SKERR_SIRQ_E035MSG);
+		}
+		/* Clear IRQ */
+		SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_TCP);
+	}
+
+	if ((HwStatus & Y2_IS_TCP_TXA1) != 0) {
+		if (Port == MAC_1) {
+			Queue = Q_XA1;
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E032, SKERR_SIRQ_E032MSG);
+		}
+		else {
+			Queue = Q_XA2;
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E034, SKERR_SIRQ_E034MSG);
+		}
+		/* Clear IRQ */
+		SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_TCP);
+	}
+
+	Para.Para64 = Port;
+	SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+
+	Para.Para32[0] = Port;
+	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+
+}	/* SkYuk2HwPortErr */
+
+/******************************************************************************
+ *
+ *	SkYuk2HwErr() - Hardware Error service routine (Yukon-2 only)
+ *
+ * Description: handles all HW Error interrupts
+ *
+ * Returns: N/A
+ */
+static void SkYuk2HwErr(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	HwStatus)	/* Interrupt status word */
+{
+	SK_EVPARA	Para;
+	SK_U16		Word;
+	SK_U32		DWord;
+	SK_U32		TlpHead[4];
+	int			i;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+		("HW-Error Status: 0x%08lX\n", HwStatus));
+
+	/* This is necessary only for Rx timing measurements */
+	if ((HwStatus & Y2_IS_TIST_OV) != 0) {
+		/* increment Time Stamp Timer counter (high) */
+		pAC->GIni.GITimeStampCnt++;
+
+		/* Clear Time Stamp Timer IRQ */
+		SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
+	}
+
+	/* Evaluate Y2_IS_PCI_NEXP before Y2_IS_MST_ERR or Y2_IS_IRQ_STAT */
+	if ((HwStatus & Y2_IS_PCI_NEXP) != 0) {
+		/*
+		 * This error is also mapped either to Master Abort (Y2_IS_MST_ERR)
+		 * or Target Abort (Y2_IS_IRQ_STAT) bit and can only be cleared there.
+		 * Therefore handle this event just by printing an error log entry.
+		 */
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E027, SKERR_SIRQ_E027MSG);
+	}
+
+	if ((HwStatus & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) != 0) {
+		/* PCI Errors occured */
+		if ((HwStatus & Y2_IS_IRQ_STAT) != 0) {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
+		}
+		else {
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
+		}
+
+		/* Reset all bits in the PCI STATUS register */
+		SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
+
+		SK_TST_MODE_ON(IoC);
+		SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+		SK_TST_MODE_OFF(IoC);
+
+		Para.Para64 = 0;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+	}
+
+	/* check for PCI-Express Uncorrectable Error */
+	if ((HwStatus & Y2_IS_PCI_EXP) != 0) {
+		/*
+		 * On PCI-Express bus bridges are called root complexes (RC).
+		 * PCI-Express errors are recognized by the root complex too,
+		 * which requests the system to handle the problem. After error
+		 * occurence it may be that no access to the adapter may be performed
+		 * any longer.
+		 */
+
+		/* Get uncorrectable error status */
+		SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("PEX Uncorr.Error Status: 0x%08lX\n", DWord));
+
+		if (DWord != PEX_UNSUP_REQ) {
+			/* ignore Unsupported Request Errors */
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E026, SKERR_SIRQ_E026MSG);
+		}
+
+		if ((DWord & (PEX_FATAL_ERRORS | PEX_POIS_TLP)) != 0) {
+			/*
+			 * Stop only, if the uncorrectable error is fatal or
+			 * Poisoned TLP occured
+			 */
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Header Log:"));
+
+			for (i = 0; i < 4; i++) {
+				/* get TLP Header from Log Registers */
+				SK_IN32(IoC, PCI_C(pAC, PEX_HEADER_LOG + i*4), &TlpHead[i]);
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+					(" 0x%08lX", TlpHead[i]));
+			}
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("\n"));
+
+			/* check for vendor defined broadcast message */
+			if (TlpHead[0] == 0x73004001 && (SK_U8)TlpHead[1] == 0x7f) {
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+					("Vendor defined broadcast message\n"));
+			}
+			else {
+				Para.Para64 = 0;
+				SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+
+				pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP;
+				/* Rewrite HW IRQ mask */
+				SK_OUT32(IoC, B0_HWE_IMSK, pAC->GIni.GIValHwIrqMask);
+			}
+		}
+
+		/* clear any PEX errors */
+		SK_TST_MODE_ON(IoC);
+		SK_OUT32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), 0xffffffffUL);
+		SK_TST_MODE_OFF(IoC);
+
+		SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord);
+
+		if ((DWord & PEX_RX_OV) != 0) {
+			/* Dev #4.205 occured */
+			pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP;
+			pAC->GIni.GIValIrqMask &= ~Y2_IS_HW_ERR;
+		}
+	}
+
+	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+		SkYuk2HwPortErr(pAC, IoC, HwStatus, i);
+	}
+
+}	/* SkYuk2HwErr */
+#endif /* YUK2 */
+
+/******************************************************************************
+ *
+ *	SkGeSirqIsr() - Wrapper for Special Interrupt Service Routine
+ *
+ * Description: calls the preselected special ISR (slow path)
+ *
+ * Returns: N/A
+ */
+void SkGeSirqIsr(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O context */
+SK_U32	Istatus)	/* Interrupt status word */
+{
+	pAC->GIni.GIFunc.pSkGeSirqIsr(pAC, IoC, Istatus);
+}
+
+/******************************************************************************
+ *
+ *	SkGeYuSirqIsr() - Special Interrupt Service Routine
+ *
+ * Description: handles all non data transfer specific interrupts (slow path)
+ *
+ * Returns: N/A
+ */
+void SkGeYuSirqIsr(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	Istatus)	/* Interrupt status word */
+{
+	SK_EVPARA	Para;
+	SK_U32		RegVal32;	/* Read register value */
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	SK_U16		PhyInt;
+	int			i;
+	int			Rtv;
+
+	if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
+		/* read the HW Error Interrupt source */
+		SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+
+		SkGeYuHwErr(pAC, IoC, RegVal32);
+	}
+
+	/*
+	 * Packet Timeout interrupts
+	 */
+	/* Check whether MACs are correctly initialized */
+	if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
+		pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
+		/* MAC 1 was not initialized but Packet timeout occured */
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
+			SKERR_SIRQ_E004MSG);
+	}
+
+	if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
+		pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
+		/* MAC 2 was not initialized but Packet timeout occured */
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
+			SKERR_SIRQ_E005MSG);
+	}
+
+	if ((Istatus & IS_PA_TO_RX1) != 0) {
+		/* Means network is filling us up */
+		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
+			SKERR_SIRQ_E002MSG);
+		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
+	}
+
+	if ((Istatus & IS_PA_TO_RX2) != 0) {
+		/* Means network is filling us up */
+		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
+			SKERR_SIRQ_E003MSG);
+		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
+	}
+
+	if ((Istatus & IS_PA_TO_TX1) != 0) {
+
+		pPrt = &pAC->GIni.GP[MAC_1];
+
+		/* May be a normal situation in a server with a slow network */
+		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
+
+#ifdef GENESIS
+		if (pAC->GIni.GIGenesis) {
+			/*
+			 * workaround: if in half duplex mode, check for Tx hangup.
+			 * Read number of TX'ed bytes, wait for 10 ms, then compare
+			 * the number with current value. If nothing changed, we assume
+			 * that Tx is hanging and do a FIFO flush (see event routine).
+			 */
+			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
+				!pPrt->HalfDupTimerActive) {
+				/*
+				 * many more pack. arb. timeouts may come in between,
+				 * we ignore those
+				 */
+				pPrt->HalfDupTimerActive = SK_TRUE;
+
+				/* Snap statistic counters */
+				(void)SkXmUpdateStats(pAC, IoC, 0);
+
+				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
+
+				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
+
+				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
+
+				pPrt->LastOctets += RegVal32;
+
+				Para.Para32[0] = 0;
+				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
+					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
+			}
+		}
+#endif /* GENESIS */
+	}
+
+	if ((Istatus & IS_PA_TO_TX2) != 0) {
+
+		pPrt = &pAC->GIni.GP[MAC_2];
+
+		/* May be a normal situation in a server with a slow network */
+		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
+
+#ifdef GENESIS
+		if (pAC->GIni.GIGenesis) {
+			/* workaround: see above */
+			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+				 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
+				!pPrt->HalfDupTimerActive) {
+				pPrt->HalfDupTimerActive = SK_TRUE;
+
+				/* Snap statistic counters */
+				(void)SkXmUpdateStats(pAC, IoC, 1);
+
+				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
+
+				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
+
+				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
+
+				pPrt->LastOctets += RegVal32;
+
+				Para.Para32[0] = 1;
+				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
+					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
+			}
+		}
+#endif /* GENESIS */
+	}
+
+	/* Check interrupts of the particular queues */
+	if ((Istatus & IS_R1_C) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
+			SKERR_SIRQ_E006MSG);
+		Para.Para64 = MAC_1;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+		Para.Para32[0] = MAC_1;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+
+	if ((Istatus & IS_R2_C) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
+			SKERR_SIRQ_E007MSG);
+		Para.Para64 = MAC_2;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+		Para.Para32[0] = MAC_2;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+
+	if ((Istatus & IS_XS1_C) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
+			SKERR_SIRQ_E008MSG);
+		Para.Para64 = MAC_1;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+		Para.Para32[0] = MAC_1;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+
+	if ((Istatus & IS_XA1_C) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
+			SKERR_SIRQ_E009MSG);
+		Para.Para64 = MAC_1;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+		Para.Para32[0] = MAC_1;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+
+	if ((Istatus & IS_XS2_C) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
+			SKERR_SIRQ_E010MSG);
+		Para.Para64 = MAC_2;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+		Para.Para32[0] = MAC_2;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+
+	if ((Istatus & IS_XA2_C) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
+			SKERR_SIRQ_E011MSG);
+		Para.Para64 = MAC_2;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+		Para.Para32[0] = MAC_2;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+
+	/* External reg interrupt */
+	if ((Istatus & IS_EXT_REG) != 0) {
+		/* Test IRQs from PHY */
+		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+			pPrt = &pAC->GIni.GP[i];
+
+			if (pPrt->PState == SK_PRT_RESET) {
+				continue;
+			}
+
+#ifdef GENESIS
+			if (pAC->GIni.GIGenesis) {
+
+				switch (pPrt->PhyType) {
+
+				case SK_PHY_XMAC:
+					break;
+
+				case SK_PHY_BCOM:
+					SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
+
+					if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
+						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+							("Port %d PHY Int: 0x%04X\n", i, PhyInt));
+						SkPhyIsrBcom(pAC, IoC, i, PhyInt);
+					}
+					break;
+#ifdef OTHER_PHY
+				case SK_PHY_LONE:
+					SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
+
+					if ((PhyInt & PHY_L_DEF_MSK) != 0) {
+						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+							("Port %d PHY Int: 0x%04X\n", i, PhyInt));
+						SkPhyIsrLone(pAC, IoC, i, PhyInt);
+					}
+					break;
+#endif /* OTHER_PHY */
+				}
+			}
+#endif /* GENESIS */
+
+#ifdef YUKON
+			if (pAC->GIni.GIYukon) {
+				/* Read PHY Interrupt Status */
+				Rtv = SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
+
+				if (Rtv == 0 && (PhyInt & PHY_M_DEF_MSK) != 0) {
+					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+						("Port %d PHY Int: 0x%04X\n", i, PhyInt));
+
+					SkPhyIsrGmac(pAC, IoC, i, PhyInt);
+				}
+			}
+#endif /* YUKON */
+		}
+	}
+
+	/* TWSI Ready interrupt */
+	if ((Istatus & IS_I2C_READY) != 0) {
+#ifdef SK_SLIM
+		SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+#else
+		SkI2cIsr(pAC, IoC);
+#endif
+	}
+
+	/* SW forced interrupt */
+	if ((Istatus & IS_IRQ_SW) != 0) {
+		/* clear the software IRQ */
+		SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
+	}
+
+	if ((Istatus & IS_LNK_SYNC_M1) != 0) {
+		/*
+		 * We do NOT need the Link Sync interrupt, because it shows
+		 * only a link going down.
+		 */
+		/* clear interrupt */
+		SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LNK_CLR_IRQ);
+	}
+
+	/* Check MAC after link sync counter */
+	if ((Istatus & IS_MAC1) != 0) {
+		/* IRQ from MAC 1 */
+		SkMacIrq(pAC, IoC, MAC_1);
+	}
+
+	if ((Istatus & IS_LNK_SYNC_M2) != 0) {
+		/*
+		 * We do NOT need the Link Sync interrupt, because it shows
+		 * us only a link going down.
+		 */
+		/* clear interrupt */
+		SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LNK_CLR_IRQ);
+	}
+
+	/* Check MAC after link sync counter */
+	if ((Istatus & IS_MAC2) != 0) {
+		/* IRQ from MAC 2 */
+		SkMacIrq(pAC, IoC, MAC_2);
+	}
+
+	/* Timer interrupt (served last) */
+	if ((Istatus & IS_TIMINT) != 0) {
+		/* check for HW Errors */
+		if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
+			/* read the HW Error Interrupt source */
+			SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+
+			SkGeYuHwErr(pAC, IoC, RegVal32);
+		}
+
+		SkHwtIsr(pAC, IoC);
+	}
+
+}	/* SkGeYuSirqIsr */
+
+#ifdef YUK2
+/******************************************************************************
+ *
+ *	SkYuk2PortSirq() - Service HW Errors for specified port (Yukon-2 only)
+ *
+ * Description: handles the HW Error interrupts for a specific port.
+ *
+ * Returns: N/A
+ */
+static void SkYuk2PortSirq(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	IStatus,	/* Interrupt status word */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_EVPARA	Para;
+	int			Queue;
+	int			Rtv;
+	SK_U16		PhyInt;
+
+	if (Port == MAC_2) {
+		IStatus >>= 8;
+	}
+
+	/* Interrupt from PHY */
+	if ((IStatus & Y2_IS_IRQ_PHY1) != 0 &&
+		pAC->GIni.GP[Port].PState != SK_PRT_RESET) {
+		/* Read PHY Interrupt Status */
+		Rtv = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyInt);
+
+		if (Rtv == 0 && (PhyInt & PHY_M_DEF_MSK) != 0) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+				("Port %d PHY Int: 0x%04X\n", Port, PhyInt));
+
+			SkPhyIsrGmac(pAC, IoC, Port, PhyInt);
+		}
+	}
+
+	/* Interrupt from MAC */
+	if ((IStatus & Y2_IS_IRQ_MAC1) != 0) {
+		SkMacIrq(pAC, IoC, Port);
+	}
+
+	if ((IStatus & (Y2_IS_CHK_RX1 | Y2_IS_CHK_TXS1 | Y2_IS_CHK_TXA1)) != 0) {
+		if ((IStatus & Y2_IS_CHK_RX1) != 0) {
+			if (Port == MAC_1) {
+				Queue = Q_R1;
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E006,
+					SKERR_SIRQ_E006MSG);
+			}
+			else {
+				Queue = Q_R2;
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E007,
+					SKERR_SIRQ_E007MSG);
+			}
+			/* Clear IRQ */
+			SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK);
+		}
+
+		if ((IStatus & Y2_IS_CHK_TXS1) != 0) {
+			if (Port == MAC_1) {
+				Queue = Q_XS1;
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E008,
+					SKERR_SIRQ_E008MSG);
+			}
+			else {
+				Queue = Q_XS2;
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E010,
+					SKERR_SIRQ_E010MSG);
+			}
+			/* Clear IRQ */
+			SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK);
+		}
+
+		if ((IStatus & Y2_IS_CHK_TXA1) != 0) {
+			if (Port == MAC_1) {
+				Queue = Q_XA1;
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E009,
+					SKERR_SIRQ_E009MSG);
+			}
+			else {
+				Queue = Q_XA2;
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E011,
+					SKERR_SIRQ_E011MSG);
+			}
+			/* Clear IRQ */
+			SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK);
+		}
+
+		Para.Para64 = Port;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+
+		Para.Para32[0] = Port;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+}	/* SkYuk2PortSirq */
+#endif /* YUK2 */
+
+/******************************************************************************
+ *
+ *	SkYuk2SirqIsr() - Special Interrupt Service Routine	(Yukon-2 only)
+ *
+ * Description: handles all non data transfer specific interrupts (slow path)
+ *
+ * Returns: N/A
+ */
+void SkYuk2SirqIsr(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	Istatus)	/* Interrupt status word */
+{
+#ifdef YUK2
+	SK_EVPARA	Para;
+	SK_U32		RegVal32;	/* Read register value */
+	SK_U8		Value;
+
+	/* HW Error indicated ? */
+	if (((Istatus & Y2_IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
+		/* read the HW Error Interrupt source */
+		SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+
+		SkYuk2HwErr(pAC, IoC, RegVal32);
+	}
+
+	/* Interrupt from ASF Subsystem */
+	if ((Istatus & Y2_IS_ASF) != 0) {
+		/* clear IRQ */
+		/* later on clearing should be done in ASF ISR handler */
+		SK_IN8(IoC, B28_Y2_ASF_STAT_CMD, &Value);
+		Value |= Y2_ASF_CLR_HSTI;
+		SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, Value);
+		/* Call IRQ handler in ASF Module */
+		/* TBD */
+	}
+
+	/* Check IRQ from polling unit */
+	if ((Istatus & Y2_IS_POLL_CHK) != 0) {
+		/* Clear IRQ */
+		SK_OUT32(IoC, POLL_CTRL, PC_CLR_IRQ_CHK);
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E036,
+			SKERR_SIRQ_E036MSG);
+		Para.Para64 = 0;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+	}
+
+	/* TWSI Ready interrupt */
+	if ((Istatus & Y2_IS_TWSI_RDY) != 0) {
+#ifdef SK_SLIM
+		SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+#else
+		SkI2cIsr(pAC, IoC);
+#endif
+	}
+
+	/* SW forced interrupt */
+	if ((Istatus & Y2_IS_IRQ_SW) != 0) {
+		/* clear the software IRQ */
+		SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
+	}
+
+	if ((Istatus & Y2_IS_L1_MASK) != 0) {
+		SkYuk2PortSirq(pAC, IoC, Istatus, MAC_1);
+	}
+
+	if ((Istatus & Y2_IS_L2_MASK) != 0) {
+		SkYuk2PortSirq(pAC, IoC, Istatus, MAC_2);
+	}
+
+	/* Timer interrupt (served last) */
+	if ((Istatus & Y2_IS_TIMINT) != 0) {
+
+		if (((Istatus & Y2_IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
+			/* read the HW Error Interrupt source */
+			SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+
+			/* otherwise we would generate error log entries periodically */
+			RegVal32 &= pAC->GIni.GIValHwIrqMask;
+			if (RegVal32 != 0) {
+				SkYuk2HwErr(pAC, IoC, RegVal32);
+			}
+		}
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("Timer Int: 0x%08lX\n", Istatus));
+		SkHwtIsr(pAC, IoC);
+	}
+#endif /* YUK2 */
+
+}	/* SkYuk2SirqIsr */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
+ *
+ * return:
+ *	0	o.k. nothing needed
+ *	1	Restart needed on this port
+ */
+static int SkGePortCheckShorts(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_U32		Shorts;			/* Short Event Counter */
+	SK_U32		CheckShorts;	/* Check value for Short Event Counter */
+	SK_U64		RxCts;			/* Rx Counter (packets on network) */
+	SK_U32		RxTmp;			/* Rx temp. Counter */
+	SK_U32		FcsErrCts;		/* FCS Error Counter */
+	SK_GEPORT	*pPrt;			/* GIni Port struct pointer */
+	int			Rtv;			/* Return value */
+	int			i;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Default: no action */
+	Rtv = SK_HW_PS_NONE;
+
+	(void)SkXmUpdateStats(pAC, IoC, Port);
+
+	/* Extra precaution: check for short Event counter */
+	(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
+
+	/*
+	 * Read Rx counters (packets seen on the network and not necessarily
+	 * really received.
+	 */
+	RxCts = 0;
+
+	for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
+
+		(void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
+
+		RxCts += (SK_U64)RxTmp;
+	}
+
+	/* On default: check shorts against zero */
+	CheckShorts = 0;
+
+	/* Extra precaution on active links */
+	if (pPrt->PHWLinkUp) {
+		/* Reset Link Restart counter */
+		pPrt->PLinkResCt = 0;
+		pPrt->PAutoNegTOCt = 0;
+
+		/* If link is up check for 2 */
+		CheckShorts = 2;
+
+		(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
+
+		if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE &&
+			pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_UNKNOWN &&
+			(pPrt->PLinkMode == (SK_U8)SK_LMODE_HALF ||
+			 pPrt->PLinkMode == (SK_U8)SK_LMODE_FULL)) {
+			/*
+			 * This is autosensing and we are in the fallback
+			 * manual full/half duplex mode.
+			 */
+			if (RxCts == pPrt->PPrevRx) {
+				/* Nothing received, restart link */
+				pPrt->PPrevFcs = FcsErrCts;
+				pPrt->PPrevShorts = Shorts;
+
+				return(SK_HW_PS_RESTART);
+			}
+			else {
+				pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_MANUAL;
+			}
+		}
+
+		if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
+			(!(FcsErrCts - pPrt->PPrevFcs))) {
+			/*
+			 * Note: The compare with zero above has to be done the way shown,
+			 * otherwise the Linux driver will have a problem.
+			 */
+			/*
+			 * We received a bunch of frames or no CRC error occured on the
+			 * network -> ok.
+			 */
+			pPrt->PPrevRx = RxCts;
+			pPrt->PPrevFcs = FcsErrCts;
+			pPrt->PPrevShorts = Shorts;
+
+			return(SK_HW_PS_NONE);
+		}
+
+		pPrt->PPrevFcs = FcsErrCts;
+	}
+
+
+	if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("Short Event Count Restart Port %d \n", Port));
+		Rtv = SK_HW_PS_RESTART;
+	}
+
+	pPrt->PPrevShorts = Shorts;
+	pPrt->PPrevRx = RxCts;
+
+	return(Rtv);
+}	/* SkGePortCheckShorts */
+#endif /* GENESIS */
+
+
+/******************************************************************************
+ *
+ * SkGePortCheckUp() - Check if the link is up
+ *
+ * return:
+ *	0	o.k. nothing needed
+ *	1	Restart needed on this port
+ *	2	Link came up
+ */
+static int SkGePortCheckUp(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	SK_BOOL		AutoNeg;	/* Is Auto-negotiation used ? */
+	int			Rtv;		/* Return value */
+
+	Rtv = SK_HW_PS_NONE;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	AutoNeg = pPrt->PLinkMode != SK_LMODE_HALF &&
+			  pPrt->PLinkMode != SK_LMODE_FULL;
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		switch (pPrt->PhyType) {
+
+		case SK_PHY_XMAC:
+			Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
+			break;
+		case SK_PHY_BCOM:
+			Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
+			break;
+#ifdef OTHER_PHY
+		case SK_PHY_LONE:
+			Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
+			break;
+		case SK_PHY_NAT:
+			Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
+			break;
+#endif /* OTHER_PHY */
+		}
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
+	}
+#endif /* YUKON */
+
+	return(Rtv);
+}	/* SkGePortCheckUp */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
+ *
+ * return:
+ *	0	o.k. nothing needed
+ *	1	Restart needed on this port
+ *	2	Link came up
+ */
+static int SkGePortCheckUpXmac(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+{
+	SK_U32	Shorts;		/* Short Event Counter */
+	int		Done;
+	SK_U16	Isrc;		/* Interrupt source register */
+	SK_U16	IsrcSum;	/* Interrupt source register sum */
+	SK_U16	LpAb;		/* Link Partner Ability */
+	SK_U16	ResAb;		/* Resolved Ability */
+	SK_U16	ExtStat;	/* Extended Status Register */
+	SK_U8	NextMode;	/* Next AutoSensing Mode */
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	SK_U32	SK_FAR GpReg;	/* General Purpose register value */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PHWLinkUp) {
+		if (pPrt->PhyType != SK_PHY_XMAC) {
+			return(SK_HW_PS_NONE);
+		}
+		else {
+			return(SkGePortCheckShorts(pAC, IoC, Port));
+		}
+	}
+
+	IsrcSum = pPrt->PIsave;
+	pPrt->PIsave = 0;
+
+	/* Now wait for each port's link */
+	if (pPrt->PLinkBroken) {
+		/* Link was broken */
+		XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
+
+		if ((GpReg & XM_GP_INP_ASS) == 0) {
+			/* The Link is in sync */
+			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+			IsrcSum |= Isrc;
+			SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
+
+			if ((Isrc & XM_IS_INP_ASS) == 0) {
+				/* It has been in sync since last time */
+				/* Restart the PORT */
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+					("Link in sync Restart Port %d\n", Port));
+
+				(void)SkXmUpdateStats(pAC, IoC, Port);
+
+				/* We now need to reinitialize the PrevShorts counter */
+				(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
+				pPrt->PPrevShorts = Shorts;
+
+				pPrt->PLinkBroken = SK_FALSE;
+
+				/*
+				 * Link Restart Workaround:
+				 *  it may be possible that the other Link side
+				 *  restarts its link as well an we detect
+				 *  another PLinkBroken. To prevent this
+				 *  happening we check for a maximum number
+				 *  of consecutive restart. If those happens,
+				 *  we do NOT restart the active link and
+				 *  check whether the link is now o.k.
+				 */
+				pPrt->PLinkResCt++;
+
+				pPrt->PAutoNegTimeOut = 0;
+
+				if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
+					return(SK_HW_PS_RESTART);
+				}
+
+				pPrt->PLinkResCt = 0;
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
+			}
+			else {
+				pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
+
+				/* Do nothing more if link is broken */
+				return(SK_HW_PS_NONE);
+			}
+		}
+		else {
+			/* Do nothing more if link is broken */
+			return(SK_HW_PS_NONE);
+		}
+
+	}
+	else {
+		/* Link was not broken, check if it is */
+		XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+		IsrcSum |= Isrc;
+		if ((Isrc & XM_IS_INP_ASS) != 0) {
+			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+			IsrcSum |= Isrc;
+			if ((Isrc & XM_IS_INP_ASS) != 0) {
+				XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+				IsrcSum |= Isrc;
+				if ((Isrc & XM_IS_INP_ASS) != 0) {
+					pPrt->PLinkBroken = SK_TRUE;
+					/* Re-Init Link partner Autoneg flag */
+					pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
+					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+						("Link broken Port %d\n", Port));
+
+					/* Cable removed-> reinit sense mode */
+					SkHWInitDefSense(pAC, IoC, Port);
+
+					return(SK_HW_PS_RESTART);
+				}
+			}
+		}
+		else {
+			SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
+
+			if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
+				return(SK_HW_PS_RESTART);
+			}
+		}
+	}
+
+	/*
+	 * here we usually can check whether the link is in sync and
+	 * auto-negotiation is done.
+	 */
+	XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
+	XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+	IsrcSum |= Isrc;
+
+	SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
+
+	if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
+		if ((GpReg & XM_GP_INP_ASS) == 0) {
+			/* Save Auto-negotiation Done interrupt only if link is in sync */
+			pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
+		}
+#ifdef DEBUG
+		if ((pPrt->PIsave & XM_IS_AND) != 0) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("AutoNeg done rescheduled Port %d\n", Port));
+		}
+#endif /* DEBUG */
+		return(SK_HW_PS_NONE);
+	}
+
+	if (AutoNeg) {
+		/* Auto-Negotiation Done ? */
+		if ((IsrcSum & XM_IS_AND) != 0) {
+
+			SkHWLinkUp(pAC, IoC, Port);
+
+			Done = SkMacAutoNegDone(pAC, IoC, Port);
+
+			if (Done != SK_AND_OK) {
+				/* Get PHY parameters, for debugging only */
+				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
+				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+					("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
+					Port, LpAb, ResAb));
+
+				/* Try next possible mode */
+				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
+
+				SkHWLinkDown(pAC, IoC, Port);
+
+				if (Done == SK_AND_DUP_CAP) {
+					/* GoTo next mode */
+					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
+				}
+
+				return(SK_HW_PS_RESTART);
+			}
+			/*
+			 * Dummy Read extended status to prevent extra link down/ups
+			 * (clear Page Received bit if set)
+			 */
+			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
+
+			return(SK_HW_PS_LINK);
+		}
+
+		/* AutoNeg not done, but HW link is up. Check for timeouts */
+		if (pPrt->PAutoNegTimeOut++ >= SK_AND_MAX_TO) {
+			/* Increase the Timeout counter */
+			pPrt->PAutoNegTOCt++;
+
+			/* Timeout occured */
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+				("AutoNeg timeout Port %d\n", Port));
+			if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE &&
+				pPrt->PLipaAutoNeg != (SK_U8)SK_LIPA_AUTO) {
+				/* Set Link manually up */
+				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+					("Set manual full duplex Port %d\n", Port));
+			}
+
+			if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE &&
+				pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO &&
+				pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
+				/*
+				 * This is rather complicated.
+				 * we need to check here whether the LIPA_AUTO
+				 * we saw before is false alert. We saw at one
+				 * switch (SR8800) that on boot time it sends
+				 * just one auto-neg packet and does no further
+				 * auto-negotiation.
+				 * Solution: we restart the autosensing after
+				 * a few timeouts.
+				 */
+				pPrt->PAutoNegTOCt = 0;
+				pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
+				SkHWInitDefSense(pAC, IoC, Port);
+			}
+
+			/* Do the restart */
+			return(SK_HW_PS_RESTART);
+		}
+	}
+	else {
+		/* Link is up and we don't need more */
+#ifdef DEBUG
+		if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("ERROR: LiPa auto detected on port %d\n", Port));
+		}
+#endif /* DEBUG */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("Link sync(GP), Port %d\n", Port));
+		SkHWLinkUp(pAC, IoC, Port);
+
+		/*
+		 * Link sync (GP) and so assume a good connection. But if no
+		 * bunch of frames received in a time slot (maybe broken Tx cable)
+		 * the port is restart.
+		 */
+		return(SK_HW_PS_LINK);
+	}
+
+	return(SK_HW_PS_NONE);
+}	/* SkGePortCheckUpXmac */
+
+
+/******************************************************************************
+ *
+ * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
+ *
+ * return:
+ *	0	o.k. nothing needed
+ *	1	Restart needed on this port
+ *	2	Link came up
+ */
+static int SkGePortCheckUpBcom(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	int			Done;
+	SK_U16		Isrc;		/* Interrupt source register */
+	SK_U16		PhyStat;	/* PHY Status Register */
+	SK_U16		ResAb;		/* Master/Slave resolution */
+	SK_U16		Ctrl;		/* Broadcom control flags */
+#ifdef DEBUG
+	SK_U16		LpAb;
+	SK_U16		ExtStat;
+#endif /* DEBUG */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Check for No HCD Link events (#10523) */
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
+
+	if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
+		/*
+		 * Workaround BCom Errata:
+		 *	enable and disable loopback mode if "NO HCD" occurs.
+		 */
+		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
+		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
+			(SK_U16)(Ctrl | PHY_CT_LOOP));
+		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
+			(SK_U16)(Ctrl & ~PHY_CT_LOOP));
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("No HCD Link event, Port %d\n", Port));
+	}
+
+	/* Not obsolete: link status bit is latched to 0 and autoclearing! */
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+
+	if (pPrt->PHWLinkUp) {
+		return(SK_HW_PS_NONE);
+	}
+
+	/*
+	 * Here we usually can check whether the link is in sync and
+	 * auto-negotiation is done.
+	 */
+
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
+
+	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+
+	if ((ResAb & PHY_B_1000S_MSF) != 0) {
+		/* Error */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("Master/Slave Fault, ResAb: 0x%04X\n", ResAb));
+
+		pPrt->PAutoNegFail = SK_TRUE;
+		pPrt->PMSStatus = SK_MS_STAT_FAULT;
+
+		return(SK_HW_PS_RESTART);
+	}
+
+	if ((PhyStat & PHY_ST_LSYNC) == 0) {
+		return(SK_HW_PS_NONE);
+	}
+
+	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Port %d, ResAb: 0x%04X\n", Port, ResAb));
+
+	if (AutoNeg) {
+		/* Auto-Negotiation Over ? */
+		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
+
+			SkHWLinkUp(pAC, IoC, Port);
+
+			Done = SkMacAutoNegDone(pAC, IoC, Port);
+
+			if (Done != SK_AND_OK) {
+#ifdef DEBUG
+				/* Get PHY parameters, for debugging only */
+				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
+				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
+					Port, LpAb, ExtStat));
+#endif /* DEBUG */
+				return(SK_HW_PS_RESTART);
+			}
+			else {
+				return(SK_HW_PS_LINK);
+			}
+		}
+	}
+	else {	/* !AutoNeg */
+		/* Link is up and we don't need more */
+#ifdef DEBUG
+		if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("ERROR: LiPa auto detected on port %d\n", Port));
+		}
+#endif /* DEBUG */
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("Link sync(GP), Port %d\n", Port));
+		SkHWLinkUp(pAC, IoC, Port);
+
+		return(SK_HW_PS_LINK);
+	}
+
+	return(SK_HW_PS_NONE);
+}	/* SkGePortCheckUpBcom */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
+ *
+ * return:
+ *	0	o.k. nothing needed
+ *	1	Restart needed on this port
+ *	2	Link came up
+ */
+static int SkGePortCheckUpGmac(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	int			Done;
+	SK_U16		PhyStat;	/* PHY Status */
+	SK_U16		PhySpecStat;/* PHY Specific Status */
+	SK_U16		ResAb;		/* Master/Slave resolution */
+
+#ifndef SK_SLIM
+	SK_EVPARA	Para;
+	int			i;
+	SK_U16		Word;		/* I/O helper */
+	SK_U16		DspOffs;	/* DSP Register Offset */
+	SK_U16		DspCtrl;	/* DSP Control Value */
+	SK_U16		DspIncr;	/* Increment to access MDI pair */
+#ifdef DEBUG
+	SK_U16		LinkPartAb;	/* Link Partner Ability */
+#endif /* DEBUG */
+#endif /* !SK_SLIM */
+
+#ifdef xDEBUG
+	SK_U64	StartTime;
+#endif /* DEBUG */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PHWLinkUp) {
+		return(SK_HW_PS_NONE);
+	}
+
+	/* Read PHY Status */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
+
+	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+
+	if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("Phy1000BT: 0x%04X, ", ResAb));
+
+		if ((ResAb & PHY_B_1000S_MSF) != 0) {
+			/* Error */
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("Master/Slave Fault, ResAb: 0x%04X\n", ResAb));
+
+			pPrt->PAutoNegFail = SK_TRUE;
+			pPrt->PMSStatus = SK_MS_STAT_FAULT;
+
+			return(SK_HW_PS_RESTART);
+		}
+	}
+
+	/* Read PHY Specific Status */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PhySpecStat: 0x%04X\n", PhySpecStat));
+
+#if (defined(DEBUG) && !defined(SK_SLIM))
+	/* Read PHY Auto-Negotiation Expansion */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &LinkPartAb);
+
+	if ((LinkPartAb & PHY_ANE_RX_PG) != 0 ||
+		(PhySpecStat & PHY_M_PS_PAGE_REC) != 0) {
+		/* Read PHY Next Page Link Partner */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("Page received, NextPage: 0x%04X\n", Word));
+	}
+#endif /* DEBUG && !SK_SLIM */
+
+	if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
+		/* Link down */
+		return(SK_HW_PS_NONE);
+	}
+
+#ifndef SK_SLIM
+	if (pAC->GIni.GICopperType) {
+
+#ifdef DEBUG
+		if ((LinkPartAb & PHY_ANE_LP_CAP) == 0) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("Link Partner is not AN able, AN Exp.: 0x%04X\n", Word));
+		}
+
+		if ((LinkPartAb & PHY_ANE_PAR_DF) == 0) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("Parallel Detection Fault, AN Exp.: 0x%04X\n", Word));
+		}
+#endif /* DEBUG */
+
+		if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+
+			if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0) {
+				/* Downshift detected */
+				Para.Para64 = Port;
+				SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("Downshift detected, PhySpecStat: 0x%04X\n", PhySpecStat));
+
+				SK_ERR_LOG(pAC, SK_ERRCL_INFO, SKERR_SIRQ_E025,
+					SKERR_SIRQ_E025MSG);
+			}
+
+			pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+				SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+		}
+
+		if ((PhySpecStat & PHY_M_PS_MDI_X_STAT) != 0) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("MDI Xover detected, PhyStat: 0x%04X\n", PhySpecStat));
+		}
+
+		if (HW_HAS_NEWER_PHY(pAC)) {
+			/* on PHY 88E1112 cable length is in Reg. 26, Page 5 */
+			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
+#ifdef XXX
+				/* select page 5 to access VCT DSP distance register */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 5);
+
+				/* get VCT DSP distance */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL_2, &PhySpecStat);
+
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
+
+				pPrt->PCableLen = (SK_U8)(PhySpecStat & PHY_M_EC2_FO_AM_MSK);
+#endif
+				DspOffs = 29;
+				DspCtrl = 0x8754;
+				DspIncr = 0x1000;
+			}
+			else {	/* CHIP_ID_YUKON_EC_U || CHIP_ID_YUKON_EX */
+
+				DspOffs = 19;
+				DspCtrl = 0x1018;
+				DspIncr = 0x0001;
+
+				/* select page 0xff to access VCT DSP distance register */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0x00ff);
+			}
+
+			for (Word = 0, i = 0; i < 4; i++) {
+				/* select register for MDI pair 0..3 */
+				SkGmPhyWrite(pAC, IoC, Port, DspOffs, DspCtrl + i * DspIncr);
+
+				/* get length for MDI pair 0..3 */
+				SkGmPhyRead(pAC, IoC, Port, DspOffs + 2, &PhySpecStat);
+
+				Word += PhySpecStat;
+			}
+
+			pPrt->PCableLen = Word / 4;	/* calculate the average */
+
+			/* set page register back to 0 */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
+		}
+		else {	/* CHIP_ID_YUKON || CHIP_ID_YUKON_LITE || CHIP_ID_YUKON_EC */
+			/* on these PHYs the rough estimated cable length is in Reg. 17 */
+			pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
+		}
+	}
+
+#ifdef xDEBUG
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("LinkUp Port %d, PHY register dump: 0x%04X\n", Port));
+
+	for (i = 0; i < PHY_MARV_PAGE_ADDR; i++) {
+		/* dump all PHY register */
+		SkGmPhyRead(pAC, IoC, Port, i, &Word);
+	}
+
+	StartTime = SkOsGetTime(pAC);
+
+	while (SkOsGetTime(pAC) - StartTime < SK_TICKS_PER_SEC / 2) {
+		/* dummy PHY read */
+		SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
+	}
+#endif /* DEBUG */
+
+#endif /* !SK_SLIM */
+
+	if (AutoNeg) {
+		/* Auto-Negotiation Complete ? */
+		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
+
+			SkHWLinkUp(pAC, IoC, Port);
+
+			Done = SkMacAutoNegDone(pAC, IoC, Port);
+
+			if (Done != SK_AND_OK) {
+				return(SK_HW_PS_RESTART);
+			}
+
+			return(SK_HW_PS_LINK);
+		}
+	}
+	else {	/* !AutoNeg */
+#if (defined(DEBUG) && !defined(SK_SLIM))
+		if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("ERROR: LiPa auto detected on port %d\n", Port));
+		}
+#endif /* DEBUG && !SK_SLIM */
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("Link sync, Port %d\n", Port));
+		SkHWLinkUp(pAC, IoC, Port);
+
+		return(SK_HW_PS_LINK);
+	}
+
+	return(SK_HW_PS_NONE);
+}	/* SkGePortCheckUpGmac */
+
+#endif /* YUKON */
+
+
+#ifdef OTHER_PHY
+/******************************************************************************
+ *
+ * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
+ *
+ * return:
+ *	0	o.k. nothing needed
+ *	1	Restart needed on this port
+ *	2	Link came up
+ */
+static int SkGePortCheckUpLone(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	int			Done;
+	SK_U16		Isrc;		/* Interrupt source register */
+	SK_U16		LpAb;		/* Link Partner Ability */
+	SK_U16		ExtStat;	/* Extended Status Register */
+	SK_U16		PhyStat;	/* PHY Status Register */
+	SK_U16		StatSum;
+	SK_U8		NextMode;	/* Next AutoSensing Mode */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PHWLinkUp) {
+		return(SK_HW_PS_NONE);
+	}
+
+	StatSum = pPrt->PIsave;
+	pPrt->PIsave = 0;
+
+	/*
+	 * here we usually can check whether the link is in sync and
+	 * auto-negotiation is done.
+	 */
+	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
+	StatSum |= PhyStat;
+
+#ifdef XXX
+	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+#endif
+
+	if ((PhyStat & PHY_ST_LSYNC) == 0) {
+		/* Save Auto-negotiation Done bit */
+		pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
+#ifdef DEBUG
+		if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("AutoNeg done rescheduled Port %d\n", Port));
+		}
+#endif /* DEBUG */
+		return(SK_HW_PS_NONE);
+	}
+
+	if (AutoNeg) {
+		/* Auto-Negotiation Over ? */
+		if ((StatSum & PHY_ST_AN_OVER) != 0) {
+
+			SkHWLinkUp(pAC, IoC, Port);
+
+			Done = SkMacAutoNegDone(pAC, IoC, Port);
+
+			if (Done != SK_AND_OK) {
+				/* Get PHY parameters, for debugging only */
+				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
+				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
+					 Port, LpAb, ExtStat));
+
+				/* Try next possible mode */
+				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
+
+				SkHWLinkDown(pAC, IoC, Port);
+
+				if (Done == SK_AND_DUP_CAP) {
+					/* GoTo next mode */
+					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
+				}
+
+				return(SK_HW_PS_RESTART);
+
+			}
+			else {
+				/*
+				 * Dummy Read interrupt status to prevent
+				 * extra link down/ups
+				 */
+				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
+				return(SK_HW_PS_LINK);
+			}
+		}
+
+		/* AutoNeg not done, but HW link is up. Check for timeouts */
+		if (pPrt->PAutoNegTimeOut++ >= SK_AND_MAX_TO) {
+			/* Timeout occured */
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+				("AutoNeg timeout Port %d\n", Port));
+			if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE &&
+				pPrt->PLipaAutoNeg != (SK_U8)SK_LIPA_AUTO) {
+				/* Set Link manually up */
+				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+					("Set manual full duplex Port %d\n", Port));
+			}
+
+			/* Do the restart */
+			return(SK_HW_PS_RESTART);
+		}
+	}
+	else {
+		/* Link is up and we don't need more */
+#ifdef DEBUG
+		if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("ERROR: LiPa auto detected on port %d\n", Port));
+		}
+#endif /* DEBUG */
+
+		/*
+		 * Dummy Read interrupt status to prevent
+		 * extra link down/ups
+		 */
+		SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("Link sync(GP), Port %d\n", Port));
+
+		SkHWLinkUp(pAC, IoC, Port);
+
+		return(SK_HW_PS_LINK);
+	}
+
+	return(SK_HW_PS_NONE);
+}	/* SkGePortCheckUpLone */
+
+
+/******************************************************************************
+ *
+ * SkGePortCheckUpNat() - Check if the link is up on National PHY
+ *
+ * return:
+ *	0	o.k. nothing needed
+ *	1	Restart needed on this port
+ *	2	Link came up
+ */
+static int SkGePortCheckUpNat(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+{
+	/* todo: National */
+	return(SK_HW_PS_NONE);
+}	/* SkGePortCheckUpNat */
+#endif /* OTHER_PHY */
+
+
+/******************************************************************************
+ *
+ *	SkGeSirqEvent() - Event Service Routine
+ *
+ * Description:
+ *
+ * Notes:
+ */
+int	SkGeSirqEvent(
+SK_AC		*pAC,		/* Adapter Context */
+SK_IOC		IoC,		/* I/O Context */
+SK_U32		Event,		/* Module specific Event */
+SK_EVPARA	Para)		/* Event specific Parameter */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	int			Port;
+	SK_U32		Val32;
+	int			PortStat;
+#ifndef SK_SLIM
+	SK_U8		Val8;
+#endif
+#ifdef GENESIS
+	SK_U64		Octets;
+#endif /* GENESIS */
+
+	Port = (int)Para.Para32[0];
+	pPrt = &pAC->GIni.GP[Port];
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+		("SIRQ HW Event: %u\n", Event));
+
+	switch (Event) {
+	case SK_HWEV_WATIM:
+		if (pPrt->PState == SK_PRT_RESET) {
+
+			PortStat = SK_HW_PS_NONE;
+		}
+		else {
+			/* Check whether port came up */
+			PortStat = SkGePortCheckUp(pAC, IoC, Port);
+		}
+
+		switch (PortStat) {
+		case SK_HW_PS_RESTART:
+			if (pPrt->PHWLinkUp) {
+				/* Set Link to down */
+				SkHWLinkDown(pAC, IoC, Port);
+
+				/*
+				 * Signal directly to RLMT to ensure correct
+				 * sequence of SWITCH and RESET event.
+				 */
+				SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+			}
+
+			/* Restart needed */
+			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+			break;
+
+		case SK_HW_PS_LINK:
+			/* Signal to RLMT */
+			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
+			break;
+		}
+
+		/* Start again the check Timer */
+		if (pPrt->PHWLinkUp) {
+
+			Val32 = SK_WA_ACT_TIME;
+		}
+		else {
+			Val32 = SK_WA_INA_TIME;
+
+			if (pAC->GIni.GIYukon) {
+				Val32 *= 5;
+			}
+		}
+		/* Start workaround Errata #2 timer */
+		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
+			SKGE_HWAC, SK_HWEV_WATIM, Para);
+
+		break;
+
+	case SK_HWEV_PORT_START:
+
+#ifndef SK_SLIM
+		if (pPrt->PHWLinkUp) {
+			/*
+			 * Signal directly to RLMT to ensure correct
+			 * sequence of SWITCH and RESET event.
+			 */
+			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+		}
+#endif /* !SK_SLIM */
+
+		SkHWLinkDown(pAC, IoC, Port);
+
+		/* Schedule Port RESET */
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+
+		/* Start workaround Errata #2 timer */
+		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+			SKGE_HWAC, SK_HWEV_WATIM, Para);
+
+		break;
+
+	case SK_HWEV_PORT_STOP:
+#ifndef SK_SLIM
+		if (pPrt->PHWLinkUp) {
+			/*
+			 * Signal directly to RLMT to ensure correct
+			 * sequence of SWITCH and RESET event.
+			 */
+			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+		}
+#endif /* !SK_SLIM */
+
+		/* Stop Workaround Timer */
+		SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
+
+		SkHWLinkDown(pAC, IoC, Port);
+		break;
+
+#ifndef SK_SLIM
+	case SK_HWEV_UPDATE_STAT:
+		/* We do NOT need to update any statistics */
+		break;
+
+	case SK_HWEV_CLEAR_STAT:
+		/* We do NOT need to clear any statistics */
+		for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
+			pPrt->PPrevRx = 0;
+			pPrt->PPrevFcs = 0;
+			pPrt->PPrevShorts = 0;
+		}
+		break;
+
+	case SK_HWEV_SET_LMODE:
+		Val8 = (SK_U8)Para.Para32[1];
+		if (pPrt->PLinkModeConf != Val8) {
+			/* Set New link mode */
+			pPrt->PLinkModeConf = Val8;
+
+			/* Restart Port */
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+		}
+		break;
+
+	case SK_HWEV_SET_FLOWMODE:
+		Val8 = (SK_U8)Para.Para32[1];
+		if (pPrt->PFlowCtrlMode != Val8) {
+			/* Set New Flow Control mode */
+			pPrt->PFlowCtrlMode = Val8;
+
+			/* Restart Port */
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+		}
+		break;
+
+	case SK_HWEV_SET_ROLE:
+		/* not possible for fiber */
+		if (!pAC->GIni.GICopperType) {
+			break;
+		}
+		Val8 = (SK_U8)Para.Para32[1];
+		if (pPrt->PMSMode != Val8) {
+			/* Set New Role (Master/Slave) mode */
+			pPrt->PMSMode = Val8;
+
+			/* Restart Port */
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+		}
+		break;
+
+	case SK_HWEV_SET_SPEED:
+		if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+			break;
+		}
+		Val8 = (SK_U8)Para.Para32[1];
+		if (pPrt->PLinkSpeed != Val8) {
+			/* Set New Speed parameter */
+			pPrt->PLinkSpeed = Val8;
+
+			/* Restart Port */
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+		}
+		break;
+#endif /* !SK_SLIM */
+
+#ifdef GENESIS
+	case SK_HWEV_HALFDUP_CHK:
+		if (pAC->GIni.GIGenesis) {
+			/*
+			 * half duplex hangup workaround.
+			 * See packet arbiter timeout interrupt for description
+			 */
+			pPrt->HalfDupTimerActive = SK_FALSE;
+			if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
+
+				/* Snap statistic counters */
+				(void)SkXmUpdateStats(pAC, IoC, Port);
+
+				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
+
+				Octets = (SK_U64)Val32 << 32;
+
+				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
+
+				Octets += Val32;
+
+				if (pPrt->LastOctets == Octets) {
+					/* Tx hanging, a FIFO flush restarts it */
+					SkMacFlushTxFifo(pAC, IoC, Port);
+				}
+			}
+		}
+		break;
+#endif /* GENESIS */
+
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
+		break;
+	}
+
+	return(0);
+}	/* SkGeSirqEvent */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkPhyIsrBcom() - PHY interrupt service routine
+ *
+ * Description: handles all interrupts from BCom PHY
+ *
+ * Returns: N/A
+ */
+static void SkPhyIsrBcom(
+SK_AC		*pAC,		/* Adapter Context */
+SK_IOC		IoC,		/* I/O Context */
+int			Port,		/* Port Index (MAC_1 + n) */
+SK_U16		IStatus)	/* Interrupt Status */
+{
+	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+	SK_EVPARA	Para;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if ((IStatus & PHY_B_IS_PSE) != 0) {
+		/* Incorrectable pair swap error */
+		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
+			SKERR_SIRQ_E022MSG);
+	}
+
+	if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
+
+		SkHWLinkDown(pAC, IoC, Port);
+
+		Para.Para32[0] = (SK_U32)Port;
+		/* Signal to RLMT */
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+
+		/* Start workaround Errata #2 timer */
+		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+			SKGE_HWAC, SK_HWEV_WATIM, Para);
+	}
+
+}	/* SkPhyIsrBcom */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkPhyIsrGmac() - PHY interrupt service routine
+ *
+ * Description: handles all interrupts from Marvell PHY
+ *
+ * Returns: N/A
+ */
+static void SkPhyIsrGmac(
+SK_AC		*pAC,		/* Adapter Context */
+SK_IOC		IoC,		/* I/O Context */
+int			Port,		/* Port Index (MAC_1 + n) */
+SK_U16		IStatus)	/* Interrupt Status */
+{
+	SK_GEPORT	*pPrt;	/* GIni Port struct pointer */
+	SK_EVPARA	Para;
+#ifdef xDEBUG
+	int		i;
+	SK_U16		Word;
+	SK_U32		DWord;
+#endif /* DEBUG */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Port %d PHY IRQ, PhyIsrc: 0x%04X\n", Port, IStatus));
+
+	if ((IStatus & PHY_M_IS_LST_CHANGE) != 0) {
+
+		Para.Para32[0] = (SK_U32)Port;
+
+		if (pPrt->PHWLinkUp) {
+
+#ifdef xDEBUG
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &Word);
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("Link Status changed, PhySpecStat: 0x%04X, ", Word));
+
+			/* read the GMAC Interrupt source register */
+			SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &Word);
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("GmacIrqSrc: 0x%02X\n", Word));
+
+			if (Word != 0 && (IStatus & PHY_M_IS_SYMB_ERROR) != 0) {
+				/* read all MIB Counters  */
+				for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
+					GM_IN32(IoC, Port, GM_MIB_CNT_BASE + 8*i, &DWord);
+
+					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+						("MIB Addr 0x%04X: 0x%08X\n",
+						BASE_GMAC_1 + GM_MIB_CNT_BASE + 8*i, DWord));
+				}
+			}
+#endif /* DEBUG */
+
+			SkHWLinkDown(pAC, IoC, Port);
+
+#ifdef XXX
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("AutoNeg.Adv: 0x%04X\n", Word));
+
+			/* Set Auto-negotiation advertisement */
+			if (pAC->GIni.GIChipId != CHIP_ID_YUKON_FE &&
+				pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
+				/* restore Asymmetric Pause bit */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
+					(SK_U16)(Word | PHY_M_AN_ASP));
+			}
+#endif /* XXX */
+
+			/* Signal to RLMT */
+			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+		}
+		else {
+			if ((IStatus & PHY_M_IS_AN_COMPL) != 0) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("Auto-Negotiation completed\n"));
+			}
+
+			if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("Link Speed changed\n"));
+			}
+
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_WATIM, Para);
+		}
+	}
+
+	if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
+		/* the copper PHY makes 1 retry */
+		if (pAC->GIni.GICopperType) {
+			/* not logged as error, it might be the first attempt */
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("Auto-Negotiation Error\n"));
+		}
+		else {
+			/* Auto-Negotiation Error */
+			SK_ERR_LOG(pAC, SK_ERRCL_INFO, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
+		}
+	}
+
+	if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
+		/* FIFO Overflow/Underrun Error */
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
+	}
+
+}	/* SkPhyIsrGmac */
+#endif /* YUKON */
+
+
+#ifdef OTHER_PHY
+/******************************************************************************
+ *
+ *	SkPhyIsrLone() - PHY interrupt service routine
+ *
+ * Description: handles all interrupts from LONE PHY
+ *
+ * Returns: N/A
+ */
+static void SkPhyIsrLone(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_U16	IStatus)	/* Interrupt Status */
+{
+	SK_EVPARA	Para;
+
+	if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
+
+		SkHWLinkDown(pAC, IoC, Port);
+
+		Para.Para32[0] = (SK_U32)Port;
+		/* Signal to RLMT */
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+	}
+
+}	/* SkPhyIsrLone */
+#endif /* OTHER_PHY */
+
+/* End of File */
+
diff --git a/drivers/net/sk98lin/skgespi.c b/drivers/net/sk98lin/skgespi.c
new file mode 100755
index 0000000..cd06cad
--- /dev/null
+++ b/drivers/net/sk98lin/skgespi.c
@@ -0,0 +1,1740 @@
+/******************************************************************************
+ *
+ * Name:	skspi.c
+ * Project:	Flash Programmer, Manufacturing and Diagnostic Tools
+ * Version:	$Revision: 1.1.2.4 $
+ * Date:	$Date: 2007/06/28 09:28:04 $
+ * Purpose:	Contains SPI-Flash EEPROM specific functions
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect
+ *	(C)Copyright 2002-2003 Marvell
+ *
+ *	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT
+ *	The copyright notice above does not evidence any
+ *	actual or intended publication of such source code.
+ *
+ *	This Module contains Proprietary Information of SysKonnect
+ *	and should be treated as Confidential.
+ *
+ *	The information in this file is provided for the exclusive use of
+ *	the licensees of SysKonnect.
+ *	Such users have the right to use, modify, and incorporate this code
+ *	into products for purposes authorized by the license agreement
+ *	provided they include this notice and the associated copyright notice
+ *	with any such product.
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skgespi.c,v 1.1.2.4 2007/06/28 09:28:04 marcusr Exp $ (C) Marvell.";
+
+/*
+#include <stdio.h>
+#include <malloc.h>
+#include <assert.h>
+*/
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#include "h/skgespi.h"
+
+#ifdef Core
+	#include "h/skdrv1st.h"
+	#include "h/skdrv2nd.h"
+	#define fl_print pAC->Gui.WPrint
+#else
+	extern void fl_print(char *msg, ...);	
+#endif /* Core */
+
+extern int fl_type;
+extern long max_pages;
+extern long max_faddr;
+
+/* low level SPI programming external interface */
+
+extern void spi_in8(unsigned short, unsigned char *);
+extern void spi_in16(unsigned short, unsigned short *);
+extern void spi_in32(unsigned short, unsigned long *);
+extern void spi_out8(unsigned short, unsigned char);
+extern void spi_out16(unsigned short, unsigned short);
+extern void spi_out32(unsigned short, unsigned long);
+extern int  spi_timer(unsigned int);
+extern void *spi_malloc(unsigned long);
+extern void spi_free(void *);
+
+/* global variables */
+unsigned char chip_id;
+
+/* local variables */
+static int spi_yuk2_dev = -1;
+
+/*
+ * Yukon 2/EC SPI flash device structure/table
+ */
+static struct {
+	char			*man_name;
+	unsigned char	man_id;
+	char			*dev_name;
+	unsigned char	dev_id;
+	unsigned long	sector_size;
+	unsigned long	sector_num;
+	char			set_protocol;
+
+	struct {
+		unsigned char	op_read;
+		unsigned char	op_write;
+		unsigned char	op_write_enable;
+		unsigned char	op_write_disable;
+		unsigned char	op_read_status;
+		unsigned char	op_read_id;
+		unsigned char	op_sector_erase;
+		unsigned char	op_chip_erase;
+	} opcodes;
+} spi_yuk2_dev_table[] = {
+	{ "Atmel",	SPI_MAN_ID_ATMEL,		"AT25F2048",	0x63,	0x10000,	4,		0,	{0x03,0x02,0x06,0x04,0x05,0x15,0x52,0x62}	} ,
+	{ "Atmel",	SPI_MAN_ID_ATMEL,		"AT25F1024",	0x60,	0x8000,		4,		0,	{0x03,0x02,0x06,0x04,0x05,0x15,0x52,0x62}	} ,
+	{ "SST",	SPI_MAN_ID_SST,			"SST25VF512",	0x48,	0x1000,		16,		1,	{0x03,0x02,0x06,0x04,0x05,0x90,0x20,0x60}	} ,
+	{ "SST",	SPI_MAN_ID_SST,			"SST25VF010",	0x49,	0x1000,		32,		1,	{0x03,0x02,0x06,0x04,0x05,0x90,0x20,0x60}	} ,
+	{ "SST",	SPI_MAN_ID_SST,			"SST25VF020",	0x43,	0x1000,		64,		1,	{0x03,0x02,0x06,0x04,0x05,0x90,0x20,0x60}	} ,
+	{ "SST",	SPI_MAN_ID_SST,			"SST25VF040",	0x44,	0x1000,		128,	1,	{0x03,0x02,0x06,0x04,0x05,0x90,0x20,0x60}	} ,
+	{ "ST",		SPI_MAN_ID_ST_M25P20,	"M25P20",		0x11,	0x10000,	4,		1,	{0x03,0x02,0x06,0x04,0x05,0xab,0xd8,0xc7}	} ,
+	{ "ST",		SPI_MAN_ID_ST_M25P10,	"M25P10",		0x10,	0x8000,		4,		1,	{0x03,0x02,0x06,0x04,0x05,0xab,0xd8,0xc7}	}
+};
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_yuk_flash_erase(unsigned long off,unsigned long len)
+ *
+ *	Send chip erase command to SPI Eprom
+ *
+ * Uses:	spi_in32, spi_out32, spi_in8, spi_timer
+ *
+ * IN:
+ *	off	start offset in flash eprom for erase
+ *      len	length in flash eprom for erase
+ *		(all nessesory sectors will be erased)
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+static int spi_yuk_flash_erase(
+unsigned long off,
+unsigned long len)
+{
+	char cr;
+	unsigned long creg, i;
+	/* Save SPI control register */
+	spi_in32(SPI_CTRL_REG, &creg);
+
+	if ((off+len-1) > 0x1ffffL) {
+		return(1);	/* more than 4 segments for erase */
+	}
+
+#ifdef XXX
+    /* there is some problem with chip erase. dr */
+
+    /* use faster chip erase command if all sectors should be erased */
+	if(len > SPI_SECT_SIZE*3L) {
+
+		spi_out32(SPI_CTRL_REG, SPI_CHIP_ERASE);
+		
+		spi_timer(SPI_TIMER_SET);
+
+		do {
+			/* Read device status */				
+			spi_in8(SPI_CTRL_REG, &cr);
+			
+			if (spi_timer(SPI_TIMEOUT)) {
+				fl_print("\nSPI chip erase timeout: %d sec\n", SPI_TIMER_SET);
+				return(1);
+			}
+		}
+		while (cr & 1);          /* is chip busy ? */
+		/* Restore SPI control register */
+		spi_out32(SPI_CTRL_REG, creg);
+	
+		return(0);
+	}
+#endif
+
+	for (i = (off >> 15); i <= ((off + len - 1) >> 15); i++) {
+		/* Clear chip command */
+		spi_out32(SPI_CTRL_REG, (i << 22) | SPI_SECT_ERASE);
+		
+		spi_timer(SPI_TIMER_SET);
+
+		do {
+			/* Read device status */				
+			spi_in8(SPI_CTRL_REG, &cr);
+			
+			if (spi_timer(SPI_TIMEOUT)) {
+				fl_print("\nSPI chip erase timeout: %d sec\n", SPI_TIMER_SET);
+				return(1);
+			}
+		}
+		while (cr & 1);          /* is chip busy ? */
+	}
+	/* Restore SPI control register */
+	spi_out32(SPI_CTRL_REG, creg);
+	
+	return(0);
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_yuk_flash_manage(
+ *	unsigned char  *data,
+ *	unsigned long off,
+ *	unsigned long len,
+ *	int flag)
+ *
+ *	Read, Verify or Write SPI Eprom
+ *
+ * Uses:	spi_in32, spi_out32, spi_in8, spi_out8, spi_in16, spi_out16, spi_timer
+ *
+ * IN:
+ *	data	data buffer
+ *	off	start offset in flash eprom for operation
+ *      len	length in flash eprom
+ *	flag	SPI_READ
+ *		SPI_VERIFY
+ *		SPI_WRITE
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+static unsigned short rol2(
+unsigned short adr)
+{
+	unsigned short	adr2;
+	
+	/* YUKON-Lite Rev. A1 */
+	if (chip_id == CHIP_ID_YUKON_LITE || chip_id == CHIP_ID_YUKON_LP) {
+		
+		/* switch address bits [1:0] with [14:13] */
+		adr2 = adr & 0x6000;
+		adr2 = adr2 >> 13;
+		adr2 = adr2 & 0x0003;
+		adr  = adr << 2;
+		adr  = adr & 0x7ffc;
+		adr  = adr | adr2;
+	}
+	
+	return(adr);
+}
+
+static int spi_yuk_flash_manage(
+unsigned char  *data,
+unsigned long off,
+unsigned long len,
+int flag)
+{
+	unsigned long a1, a2, cr, i;
+	unsigned short adr, as, ret=0;
+	unsigned char ch, tr;
+	unsigned long progress;
+	unsigned long last_progress;
+
+	/* Save VPD lower address */
+	spi_in32(SPI_ADR_REG1, &a1);
+
+	/* Save VPD higher address */
+	spi_in32(SPI_ADR_REG2, &a2);
+
+	/* Set VPD lower address to 0 (15 higher bit)*/
+	spi_out32(SPI_ADR_REG1, SPI_VPD_MIN);
+
+	/* Set VPD higher address to 0x7fff (15 higher bit)*/
+	spi_out32(SPI_ADR_REG2, SPI_VPD_MAX);
+
+	/* Save SPI control register */
+	spi_in32(SPI_CTRL_REG, &cr);
+
+	/* Enable VPD to SPI mapping (set bit 19) */
+	spi_out32(SPI_CTRL_REG, SPI_VPD_MAP);
+
+	/* Save Test Control Register 1 */
+	spi_in8(B2_TST_REG1, &tr);
+
+	/* Enable write to mapped PCI config register file */
+	spi_out8(B2_TST_REG1, 2);
+
+	progress = last_progress = 0;
+
+	for (i = off, adr = (unsigned short)(off >> 2); i < off + len; i++) {		
+		progress = (i * 100) / len;
+
+		if((progress - last_progress) >= 10) {
+			fl_print(".");
+			last_progress += 10;
+		}
+
+		/* Set new address to VPD Address reg, initiate reading */
+		if ((i % 4) == 0) {
+		
+			spi_out16(VPD_ADR_REG, rol2(adr++));
+			
+			/* Wait for termination */
+			spi_timer(SPI_TIMER_SET);
+			do {
+				/* Read VPD_ADDR reg for flag check */	
+				spi_in16(VPD_ADR_REG, &as);
+				
+				if (spi_timer(SPI_TIMEOUT)) {
+					fl_print("\nSPI read timeout: %d sec. Offset:0x%05lx\n",
+						SPI_TIMER_SET, i);
+					ret = 1;
+					break;
+				}
+			}
+			while (!(as & VPD_FLAG_MASK)); /* check  flag */
+			
+			if (ret) {
+				break;
+			}
+		}
+		
+		switch (flag) {
+		case SPI_READ:
+			/* Read byte from VPD port */
+			spi_in8((unsigned short)(VPD_DATA_PORT +
+				(unsigned short)(i % 4)), &ch);
+			*(data++) = ch;
+			break;
+		case SPI_VERIFY:
+			/* Read and verify byte from VPD port */
+			spi_in8((unsigned short)(VPD_DATA_PORT +
+				(unsigned short)(i % 4)), &ch);
+			if (ch != *(data++)) {
+				fl_print("\n*** SPI data verify error at address 0x%05lx, ",
+					"is %x, should %x\n",
+					i, ch, *(data - 1));
+				ret = 1;
+			}
+			break;
+		case SPI_WRITE:
+			/* Write byte to VPD port */
+			spi_out8((unsigned short)(VPD_DATA_PORT +
+				(unsigned short)(i % 4)), *(data++));
+	
+			if ((i % 4) == 3) {
+				/* Set old Address to VPD_ADDR reg, initiate writing */
+				spi_out16((unsigned short)VPD_ADR_REG,
+					(unsigned short)(rol2((unsigned short)(adr - 1)) | VPD_FLAG_MASK));
+		
+				/* Wait for termination */
+				spi_timer(SPI_TIMER_SET);
+				do {
+					/* Read VPD_ADDR reg for flag check*/	
+					spi_in16(VPD_ADR_REG, &as);
+					
+					if (spi_timer(SPI_TIMEOUT)) {
+						fl_print("\nSPI write timeout: %d sec. Offset:0x%05lx\n",
+							SPI_TIMER_SET, i);
+						ret = 1;
+						break;
+					}
+				}
+				while (as & VPD_FLAG_MASK); /* check  flag */
+			}
+			break;
+		}
+
+		if (ret) {
+			break;	
+		}
+	}
+	/* Restore Test Control Register 1 */
+	spi_out8(B2_TST_REG1, tr);
+
+	/* Restore VPD lower address*/
+	spi_out32(SPI_ADR_REG1, a1);
+
+	/* Restore VPD higher address*/
+	spi_out32(SPI_ADR_REG2, a2);
+
+	/* Restore SPI control register */
+	spi_out32(SPI_CTRL_REG, cr);
+
+	fl_print(".");
+	return(ret);	
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_yuk_update_config(
+ *	unsigned char  *data,
+ *	unsigned long off,
+ *	unsigned long len)
+ *
+ *	Update part of config area
+ *
+ * Uses:	spi_flash_manage, spi_flash_erase
+ *
+ * IN:
+ *	data	data buffer
+ *	off	start offset in flash eprom (config area) for operation
+ *      len	length of changing data
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+static int spi_yuk_update_config(
+unsigned char  *data,
+unsigned long off,
+unsigned long len)
+{
+	unsigned char *spibuf;
+	unsigned long i;
+
+	spibuf = spi_malloc((unsigned long)SPI_SECT_SIZE);
+
+	if(spibuf == NULL) {
+		return(51);
+	}
+	
+	if (spi_flash_manage(spibuf, SPI_LSECT_OFF, SPI_SECT_SIZE, SPI_READ)) {
+	
+		spi_free(spibuf);
+		return(1);
+	}
+	
+	for (i = 0; i < len; i++) {
+		spibuf[off + i - SPI_LSECT_OFF] = data[i];
+	}
+	
+	if (spi_flash_erase(SPI_LSECT_OFF, SPI_SECT_SIZE)) {
+
+		spi_free(spibuf);
+		return(7);
+	}
+	
+	if (spi_flash_manage(spibuf, SPI_LSECT_OFF, SPI_SECT_SIZE, SPI_WRITE)) {
+	
+		spi_free(spibuf);
+		return(8);
+	}
+	spi_free(spibuf);	
+	return(0);
+}	
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	void spi_yuk2_write_enable()
+ *
+ *	This function will set the Write enable setting of the SPI EPROM
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	nothing
+ *
+ * END_MANUAL_ENTRY()
+ */
+void spi_yuk2_write_enable()
+{
+	unsigned long spi_ctrl_reg;
+	
+	/* execute write enable command */
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;
+	spi_ctrl_reg |= SPI_Y2_WEN;	
+	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+	
+	/* wait for the SPI to finish command */
+	SPI_Y2_WAIT_SE_FINISH_WR();
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	static unsigned long spi_yuk2_read_dword(
+ *  unsigned long	address)
+ *
+ *	The function reads a dword from the specified address in the SPI EPROM.
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	dword read from given address
+ *
+ * END_MANUAL_ENTRY()
+ */
+static unsigned long spi_yuk2_read_dword(
+unsigned long	address)		/* addres in the SPI EPROM to read from */
+{
+	unsigned long reg_val = 0;
+	unsigned long spi_ctrl_reg;
+
+	/* write spi address */
+	spi_out32(SPI_Y2_ADDRESS_REG, address);
+
+	/* execute spi read command */
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;
+	spi_ctrl_reg |= SPI_Y2_RD;	
+	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+
+	/* wait for the SPI to finish RD operation */
+	SPI_Y2_WAIT_SE_FINISH_CMD();
+   
+	/* read the returned data */
+	spi_in32(SPI_Y2_DATA_REG, &reg_val);
+
+	return reg_val;
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	static int spi_yuk2_write_dword(
+ *	unsigned long	address,
+ *	unsigned long	value)
+ *
+ *	This function writes the specified dword in the specified SPI EPROM location.
+ *  The SPI EPROM should have been put previously in write enable mode and
+ *  the target sector erased for the access to succeed.
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	0 - if successful
+ *	1 - if fails
+ *
+ * END_MANUAL_ENTRY()
+ */
+static int spi_yuk2_write_dword(
+unsigned long	address,			/* address to write to */
+unsigned long	value)				/* new value to be written */
+{
+	unsigned long spi_ctrl_reg;
+	unsigned long verify_value;
+
+	spi_yuk2_write_enable();
+	
+	/* write spi address */
+	spi_out32(SPI_Y2_ADDRESS_REG, address);   
+	/* write the new value */
+	spi_out32(SPI_Y2_DATA_REG, value);
+
+	/* execute the spi write command */
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;
+	spi_ctrl_reg |= SPI_Y2_WR;	
+	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+	
+	/* wait for write to finish */
+	SPI_Y2_WAIT_SE_FINISH_WR();
+	
+	verify_value = spi_yuk2_read_dword(address);
+
+	/* verify if write was successful*/
+	if ( verify_value == value ) {
+		return 0;
+	} 
+	else {
+		fl_print("\n*** SPI data write error at address 0x%08x, ","is 0x%08x, should 0x%08x\n", address, 
+																	verify_value, value);
+		return 1;
+	}
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	static int spi_yuk2_sst_write_dword(
+ *	unsigned long	address,
+ *	unsigned long	value)
+ *
+ *	This function writes the specified dword in the specified SPI EPROM location.
+ *  The SPI EPROM should have been put previously in write enable mode and
+ *  the target sector erased for the access to succeed.
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	0 - if successful
+ *	1 - if fails
+ *
+ * END_MANUAL_ENTRY()
+ */
+static int spi_yuk2_sst_write_dword(
+unsigned long	address,			/* address to write to */
+unsigned long	value)				/* new value to be written */
+{
+	unsigned long spi_ctrl_reg;
+	unsigned long verify_value;
+	unsigned long i;
+
+	for (i = 0; i < 4; i++) {
+
+		spi_yuk2_write_enable();
+
+		/* write spi address */
+		spi_out32(SPI_Y2_ADDRESS_REG, address + i);   
+		/* write the new value */
+		spi_out32(SPI_Y2_DATA_REG, (value >> i*8) & 0x000000ff);
+
+		/* execute the spi write command */
+		spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+		spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;
+		spi_ctrl_reg |= SPI_Y2_WR;	
+		spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+		
+		/* wait for write to finish */
+		SPI_Y2_WAIT_SE_FINISH_WR();
+		
+		verify_value = spi_yuk2_read_dword(address);
+
+		/* verify if write was successful*/
+		if ( ((verify_value >> i*8) & 0x000000ff) != ((value >> i*8) & 0x000000ff) ) {
+			fl_print("\n*** SPI data write error at address 0x%08x, ","is 0x%08x, should 0x%08x\n", address + i, 
+																		((verify_value >> i*8) & 0x000000ff), ((value >> i*8) & 0x000000ff));
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int spi_yuk2_sst_clear_write_protection()
+ *
+ *	Clear the write protection bits for SST flash types because
+ *	they are set by default.
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	nothing
+ *
+ * END_MANUAL_ENTRY()
+ */
+void spi_yuk2_sst_clear_write_protection()
+{
+	unsigned long spi_ctrl_reg;
+	unsigned long op;
+	unsigned long addr;
+	unsigned char status;
+
+	spi_in32(SPI_Y2_OPCODE_REG1, &op);
+	op &= 0xffff00ff;
+	op |= 0x00000100;
+	spi_out32(SPI_Y2_OPCODE_REG1, op);
+
+	spi_in32(SPI_Y2_OPCODE_REG2, &op);
+	op &= 0xffffff00;
+	op |= 0x00000050;
+	spi_out32(SPI_Y2_OPCODE_REG2, op);
+
+	/* execute write status register enable command */
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;
+	spi_ctrl_reg |= SPI_Y2_WEN;	
+	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+	
+	/* wait for the SPI to finish RD operation */
+	SPI_Y2_WAIT_SE_FINISH_CMD();
+
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	status = (unsigned char)(spi_ctrl_reg & 0xfffffff3);
+	addr = ((unsigned long)status | (unsigned long)(status << 8) | (unsigned long)(status << 16) | (unsigned long)(status << 24));
+        
+	/* write spi address */
+	spi_out32(SPI_Y2_ADDRESS_REG, addr);   
+	/* write the new value */
+	spi_out32(SPI_Y2_DATA_REG, addr);
+
+	/* execute the write status register command */
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;
+	spi_ctrl_reg |= SPI_Y2_RD;
+	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+
+        /* wait for the SPI to finish RD operation */
+	SPI_Y2_WAIT_SE_FINISH_CMD();
+			
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	static void spi_yuk2_erase_sector(
+ *	unsigned long	sector_num)
+ *
+ *	This function will erase the sector specified allowing thus data to be written
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	nothing
+ *
+ * END_MANUAL_ENTRY()
+ */
+static void spi_yuk2_erase_sector(
+unsigned long	sector_num)		/* sector to be erased */
+{
+	unsigned long spi_ctrl_reg;
+
+	spi_yuk2_write_enable();
+
+	/* write sector start address */
+	spi_out32(SPI_Y2_ADDRESS_REG, spi_yuk2_dev_table[spi_yuk2_dev].sector_size * sector_num);
+
+	/* execute erase sector command */
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;
+	spi_ctrl_reg |= SPI_Y2_SERS;		
+	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+	SPI_Y2_WAIT_SE_FINISH_WR();
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	void spi_yuk2_erase_chip()
+ *
+ *	This function will erase the complete SPI EPROM chip
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	nothing
+ *
+ * END_MANUAL_ENTRY()
+ */
+void spi_yuk2_erase_chip()
+{
+	unsigned long spi_ctrl_reg;
+
+	spi_yuk2_write_enable();
+
+	/* execute erase chip command */
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;
+	spi_ctrl_reg |= SPI_Y2_CERS;		
+	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+	SPI_Y2_WAIT_SE_FINISH_WR();
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	unsigned short spi_yuk2_read_chip_id()
+ *
+ *	Read SPI vendor and device id
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	The lower byte containes the device id and the upper the vendor id
+ *
+ * END_MANUAL_ENTRY()
+ */
+unsigned short spi_yuk2_read_chip_id()
+{
+	unsigned short	chip_id_local;
+	unsigned long	spi_ctrl_reg = 0;
+	unsigned long	opcode_reg1;
+
+	/* 
+	 * set read id opcode for flash currently selected
+	 */
+	spi_in32(SPI_Y2_OPCODE_REG1, &opcode_reg1);
+	opcode_reg1 &= 0xff00ffffL;
+	opcode_reg1 |= (((unsigned long)spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read_id) << 16);
+	spi_out32(SPI_Y2_OPCODE_REG1, opcode_reg1);
+
+	/*
+	 * read spi control register
+	 */
+	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);
+	spi_ctrl_reg &= ~(SPI_Y2_CMD_MASK | SPI_Y2_RDID_PROT);
+
+	/* select protocol for chip id read out */
+	if( spi_yuk2_dev_table[spi_yuk2_dev].set_protocol ) {
+		spi_ctrl_reg |= SPI_Y2_RDID_PROT;
+	}
+	
+	/* execute read chip id command */
+	spi_ctrl_reg |= SPI_Y2_RDID;
+	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);
+	SPI_Y2_WAIT_SE_FINISH_CMD();
+
+	spi_in16(SPI_Y2_VENDOR_DEVICE_ID_REG, &chip_id_local);
+	return (chip_id_local);
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int spi_yuk2_get_dev_index(void)
+ *
+ *	Identify the SPI device and return its device
+ *	table index
+ *
+ * Uses:
+ *
+ * IN:
+ *
+ * return:
+ *	-1	unknown or no flash device
+ *	>=0	flash device table index
+ *
+ * END_MANUAL_ENTRY()
+ */
+#ifdef USE_ASF_DASH_FW
+int spi_yuk2_get_dev_index()
+{
+	unsigned short	spi_chip_id;
+	unsigned char	man_id;
+	unsigned char	dev_id;
+	unsigned int	i;
+
+	/* search for flash in device table */
+	for(i = 0; i < (sizeof(spi_yuk2_dev_table) / sizeof(spi_yuk2_dev_table[0])); i++) {
+		if (chip_id != CHIP_ID_YUKON_EC_U && chip_id != CHIP_ID_YUKON_EX &&
+			(i == 0 || i == 1)) {
+			continue;
+		}
+		spi_yuk2_dev = i;
+
+		spi_chip_id = spi_yuk2_read_chip_id();
+
+		man_id = (unsigned char)((spi_chip_id & SPI_Y2_MAN_ID_MASK) >> 8);
+		dev_id = (unsigned char)(spi_chip_id & SPI_Y2_DEV_ID_MASK);
+
+		if(spi_yuk2_dev_table[i].man_id == man_id &&
+		   spi_yuk2_dev_table[i].dev_id == dev_id) {
+			fl_print("\nFlash Device\t: %s ", spi_yuk2_dev_table[i].dev_name);
+			fl_print("(VID 0x%2.2x, ", man_id);
+			fl_print("DID 0x%2.2x)\n", dev_id);
+			return(i);
+		}
+	}
+
+	spi_yuk2_dev = -1;
+	return(-1);
+}
+#else
+int spi_yuk2_get_dev_index()
+{
+	unsigned short	chip_id_local;
+	unsigned char	man_id;
+	unsigned char	dev_id;
+	int		i;
+
+	/* search for flash in device table */
+	for(i = 0; i < (sizeof(spi_yuk2_dev_table) / sizeof(spi_yuk2_dev_table[0])); i++) {
+      spi_yuk2_dev = i;
+		chip_id_local = spi_yuk2_read_chip_id();
+
+		man_id = (unsigned char)((chip_id_local & SPI_Y2_MAN_ID_MASK) >> 8);
+		dev_id = (unsigned char)(chip_id_local & SPI_Y2_DEV_ID_MASK);
+
+		if(spi_yuk2_dev_table[i].man_id == man_id &&
+		   spi_yuk2_dev_table[i].dev_id == dev_id) {
+			fl_print("\nFlash Device %s found\n", spi_yuk2_dev_table[i].dev_name);
+			fl_print("  - Vendor ID : 0x%2.2x \n", man_id);
+			fl_print("  - Device ID : 0x%2.2x \n", dev_id);
+			return(i);
+		}
+	}
+
+	spi_yuk2_dev = -1;
+	return(-1);
+}
+#endif
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	static int spi_yuk2_flash_erase(unsigned long off,unsigned long len)
+ *
+ *	Erase all sectors of the flash prom affected by the address
+ *	range denoted by parameters "off" (address offset) and "len"
+ *	(length of address range).
+ *
+ * Uses:	spi_in32, spi_out32, spi_in8, spi_timer
+ *
+ * IN:
+ *	off:	start offset in flash eprom for erase
+ *  len:	length in flash eprom for erase
+ *			(all necessary sectors will be erased)
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+
+static int spi_yuk2_flash_erase(
+unsigned long off,
+unsigned long len)
+{
+	unsigned long	flash_size;
+	unsigned long	i;
+	unsigned long	start_sector;
+	unsigned long	end_sector;
+
+	if(len == 0) {
+		return(0);
+	}
+
+	flash_size = spi_yuk2_dev_table[spi_yuk2_dev].sector_size * 
+							spi_yuk2_dev_table[spi_yuk2_dev].sector_num;
+
+	/*
+	 * flash size is smaller than address range which
+	 * should be erased --> don't erase flash.
+	 */
+	if ((off+len-1) > flash_size) {
+		return(1);
+	}
+
+	/*
+	 * Erase complete flash if all sectors of flash are affected
+	 */
+	if(len > (spi_yuk2_dev_table[spi_yuk2_dev].sector_size * 
+		(spi_yuk2_dev_table[spi_yuk2_dev].sector_num - 1))) {
+		
+		spi_yuk2_erase_chip();
+	}
+	/*
+	 * Erase all affected sectors
+	 */
+	else {
+		start_sector = off / spi_yuk2_dev_table[spi_yuk2_dev].sector_size;
+		end_sector   = (off + len - 1) / spi_yuk2_dev_table[spi_yuk2_dev].sector_size;
+		
+		for (i = start_sector; i <= end_sector; i++) {
+			spi_yuk2_erase_sector(i);
+		}
+	}
+
+	return(0);
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	static int spi_yuk2_flash_manage(
+ *	unsigned char  *data,
+ *	unsigned long off,
+ *	unsigned long len,
+ *	int flag)
+ *
+ *	Read, Verify or Write SPI Eprom
+ *
+ * Uses:	spi_in32, spi_out32, spi_in8, spi_out8, spi_in16, spi_out16, spi_timer
+ *
+ * IN:
+ *	data	data buffer
+ *	off		start offset in flash eprom for operation
+ *  len		length in flash eprom
+ *	flag	SPI_READ
+ *			SPI_VERIFY
+ *			SPI_WRITE
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+#ifdef USE_ASF_DASH_FW
+static int spi_yuk2_flash_manage(
+unsigned char huge *data,
+unsigned long off,
+unsigned long len,
+int flag)
+{
+	unsigned long		addr; 
+	unsigned long		spi_data;
+	unsigned long huge	*spi_data_ptr;
+	unsigned long		progress;
+	unsigned long		last_progress;
+	int					ret = 0;
+	unsigned char		ChipId,ChipRev,ByteVal;
+
+	// assert(!(off&3));
+
+	len = (len + 3) & ~3;
+
+	spi_in8(B2_CHIP_ID, &ChipId);
+	spi_in8(B2_MAC_CFG, &ChipRev);
+	ChipRev = (unsigned char)((ChipRev & CFG_CHIP_R_MSK) >> 4);
+	
+	if ((ChipId == CHIP_ID_YUKON_EX) &&
+		(ChipRev != CHIP_REV_YU_EX_A0) &&
+		(spi_yuk2_dev_table[spi_yuk2_dev].sector_size *
+		spi_yuk2_dev_table[spi_yuk2_dev].sector_num >= 0x40000)) {
+
+		spi_in8(SPI_CFG, &ByteVal);
+		ByteVal |= SPI_CFG_A17_GATE;	
+		spi_out8(SPI_CFG, ByteVal);
+	}
+
+	progress = last_progress = 0;
+
+	for (addr = off, spi_data_ptr = (unsigned long huge *)data;
+							addr < off + len; addr+=4, spi_data_ptr++) {
+		progress = ((addr - off) * 100) / len;
+
+		if((progress - last_progress) >= 10) {
+			fl_print(".");
+			last_progress += 10;
+		}
+
+		switch (flag) {
+			case SPI_READ:
+				/* Read a dword from SPI flash */
+				*(spi_data_ptr) = spi_yuk2_read_dword(addr);				
+			break;
+
+			case SPI_VERIFY:
+				/* Read and verify dword from SPI flash */
+				spi_data = spi_yuk2_read_dword(addr);
+
+
+				if (spi_data != *(spi_data_ptr)) {
+					fl_print("\n*** SPI data verify error at address 0x%08lx, ",
+						"is %x, should %x\n", addr, spi_data, *(spi_data_ptr));
+					ret = 1;
+				}
+			break;
+
+			case SPI_WRITE:
+#if 0
+#ifndef SK_DIAG
+				/*
+				 * Flash-only adapters only support
+				 * Flash sector sizes of 4096 bytes
+				 */
+				if (max_faddr == 0x1000) {
+					if (ModifiedPages[addr >> 12] != (unsigned char)1) {
+#if 0
+
+						if ((addr % 4096) == 0) {
+							fl_print("not writing to sector %d\n",addr >> 12);
+						}
+#endif
+						continue;
+					}
+				}
+#endif	/* !SK_DIAG */
+#endif
+
+					/* Write a dword to SPI flash */
+				if (spi_yuk2_dev_table[spi_yuk2_dev].man_id == SPI_MAN_ID_SST) {
+					ret = spi_yuk2_sst_write_dword(addr, *(spi_data_ptr));
+				}
+				else {
+					ret = spi_yuk2_write_dword(addr, *(spi_data_ptr));
+				}
+
+			break;
+		}
+
+		if (ret) {
+			break;	
+		}
+	}
+
+	fl_print(".");
+	return(ret);
+}
+#else
+static int spi_yuk2_flash_manage(
+unsigned char  *data,
+unsigned long off,
+unsigned long len,
+int flag)
+{
+	unsigned long		addr; 
+	unsigned long		spi_data;
+	unsigned int		*spi_data_ptr;
+	int			ret = 0;
+	len = (len + 3) & ~3;
+
+	for (addr = off, spi_data_ptr = (unsigned int *)data; addr < off + len; addr+=4, spi_data_ptr++) {
+
+		switch (flag) {
+			case SPI_READ:
+				/* Read a dword from SPI flash */
+				*(spi_data_ptr) = spi_yuk2_read_dword(addr);
+			break;
+
+			case SPI_VERIFY:
+				/* Read and verify dword from SPI flash */
+				spi_data = spi_yuk2_read_dword(addr);
+			break;
+
+				if (spi_data != *(spi_data_ptr)) {
+					fl_print("\n*** SPI data verify error at address 0x%08lx, ","is %x, should %x\n", addr, 
+																				spi_data, *(spi_data_ptr));
+					ret = 1;
+				}
+			break;
+
+			case SPI_WRITE:
+				/* Write a dword to SPI flash */
+				if (spi_yuk2_dev_table[spi_yuk2_dev].man_id == SPI_MAN_ID_SST) {
+					ret = spi_yuk2_sst_write_dword(addr, *(spi_data_ptr));
+				}
+				else {
+					ret = spi_yuk2_write_dword(addr, *(spi_data_ptr));
+				}
+			break;
+		}
+
+		if (ret) {
+			break;	
+		}
+	}
+
+	return(ret);
+}
+#endif
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	static int spi_yuk2_update_config(
+ *	unsigned char  *data,
+ *	unsigned long off,
+ *	unsigned long len)
+ *
+ *	Update part of config area
+ *
+ * Uses:	spi_flash_manage, spi_flash_erase
+ *
+ * IN:
+ *	data	data buffer
+ *	off	start offset in flash eprom (config area) for operation
+ *      len	length of changing data
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+static int spi_yuk2_update_config(
+unsigned char  *data,
+unsigned long off,
+unsigned long len)
+{
+	unsigned char  *spibuf;
+	unsigned long start_sector;
+	unsigned long end_sector;
+	unsigned long i;
+
+	/* determine the affected sectors */
+	start_sector = off / spi_yuk2_dev_table[spi_yuk2_dev].sector_size;
+	end_sector   = (off + len - 1) / spi_yuk2_dev_table[spi_yuk2_dev].sector_size;
+	
+	/* 
+	 * allocate the necessary memory for temporary 
+	 * save of the affected sectors
+	 */
+	spibuf = spi_malloc((unsigned long)(((end_sector - start_sector) + 1) * spi_yuk2_dev_table[spi_yuk2_dev].sector_size));
+
+	if(spibuf == NULL) {
+		return(51);
+	}
+	
+	/* read out the affected sectors */
+	if (spi_flash_manage(spibuf, 
+							start_sector * spi_yuk2_dev_table[spi_yuk2_dev].sector_size, 
+							((end_sector - start_sector) + 1) * spi_yuk2_dev_table[spi_yuk2_dev].sector_size, 
+							SPI_READ)) {	
+
+		spi_free(spibuf);
+		return(1);
+	}
+	
+	/* update the just read out data */
+	for (i = 0; i < len; i++) {
+		spibuf[off + i - SPI_LSECT_OFF] = data[i];
+	}
+	
+	/* erase the affected sectors */
+	if (spi_flash_erase(start_sector * spi_yuk2_dev_table[spi_yuk2_dev].sector_size, 
+						((end_sector - start_sector) + 1) * spi_yuk2_dev_table[spi_yuk2_dev].sector_size)) {
+
+		spi_free(spibuf);
+		return(7);
+	}
+	
+	/* write the updated data back to the flash */
+	if (spi_flash_manage(spibuf, 
+						 start_sector * spi_yuk2_dev_table[spi_yuk2_dev].sector_size,  
+						 ((end_sector - start_sector) + 1) * spi_yuk2_dev_table[spi_yuk2_dev].sector_size, 
+						 SPI_WRITE)) {
+	
+		spi_free(spibuf);
+		return(8);
+	}
+
+	spi_free(spibuf);	
+	return(0);
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	static int spi_update_config(
+ *	unsigned char  *data,
+ *	unsigned long off,
+ *	unsigned long len)
+ *
+ *	Update part of config area
+ *
+ * Uses:	spi_flash_manage, spi_flash_erase
+ *
+ * IN:
+ *	data	data buffer
+ *	off	start offset in flash eprom (config area) for operation
+ *      len	length of changing data
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+static int spi_update_config(
+unsigned char  *data,
+unsigned long off,
+unsigned long len)
+{
+	switch (fl_type) {
+		case FT_SPI:
+			return(spi_yuk_update_config(data, off, len));
+		break;
+
+		case FT_SPI_Y2:
+			return(spi_yuk2_update_config(data, off, len));
+		break;
+	}
+
+	return(1);
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     flash_check_spi( unsigned long *FlashSize )
+ *
+ *	Determines whether a SPI Eprom present
+ *
+ * Uses:	spi_in32, spi_out32
+ *
+ * IN:
+ *
+ * return:
+ *	0	No SPI
+ *	1	SPI detected
+ *
+ * END_MANUAL_ENTRY()
+ */
+
+#ifdef USE_ASF_DASH_FW
+int flash_check_spi( 
+unsigned long *FlashSize )
+{
+	unsigned long a1,a2;
+	unsigned long opcodes;
+
+	
+	*FlashSize = 0;
+
+	spi_in8(B2_CHIP_ID, &chip_id);
+
+	if (chip_id == CHIP_ID_YUKON_LITE || chip_id == CHIP_ID_YUKON_LP) {
+		/* YUKON-Lite Rev. A1 */
+		fl_type = FT_SPI;
+		*FlashSize = max_pages * max_faddr;
+		fl_print("\nFlash Device\t: SPI\n");
+		return(1);
+	}
+
+	if (chip_id >= CHIP_ID_YUKON_XL && chip_id <= CHIP_ID_YUKON_FE) {		
+		fl_type = FT_SPI_Y2;
+
+		spi_yuk2_dev = spi_yuk2_get_dev_index();
+
+		/* unknown or no flash */
+		if(spi_yuk2_dev < 0) {
+			fl_print("\nFlash device\t: none\n");
+			fl_type = FT_SPI_UNKNOWN;
+			return(0);
+		}
+		
+		max_pages = (long)(spi_yuk2_dev_table[spi_yuk2_dev].sector_num);
+		max_faddr = (long)(spi_yuk2_dev_table[spi_yuk2_dev].sector_size);
+		*FlashSize = spi_yuk2_dev_table[spi_yuk2_dev].sector_num * spi_yuk2_dev_table[spi_yuk2_dev].sector_size;
+
+		/*
+		 * work around for SST flash types to clear write 
+		 * protection bits which are set by default.
+		 */
+		if (spi_yuk2_dev_table[spi_yuk2_dev].man_id == SPI_MAN_ID_SST) {
+			spi_yuk2_sst_clear_write_protection();
+		}
+
+		/*
+		 * set the opcodes for the SPI flash found 
+		 */
+		spi_in32(SPI_Y2_OPCODE_REG1, &opcodes);
+		opcodes &= 0x000000ffL;
+		opcodes |= ((((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read)) << 8) | 
+					(((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read_id)) << 16) |
+					(((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read_status)) << 24));
+
+		spi_out32(SPI_Y2_OPCODE_REG1, opcodes);
+
+		opcodes = (((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_write_enable)) | 
+				   (((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_write)) << 8) | 
+				   (((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_sector_erase)) << 16) |
+				   (((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_chip_erase)) << 24));
+
+		spi_out32(SPI_Y2_OPCODE_REG2, opcodes);
+
+		return(1);
+	}	
+
+	/* Save Eprom Address Register 1 */
+	spi_in32(SPI_ADR_REG1, &a1);
+	
+	/* Write SPI pattern */
+	spi_out32(SPI_ADR_REG1, SPI_PATTERN);
+	
+	/* Read SPI pattern */
+	spi_in32(SPI_ADR_REG1, &a2);
+	
+	/* Restore Eprom Address Register 1 */
+	spi_out32(SPI_ADR_REG1, a1);
+	
+	/* This is a SPI Eprom if one of bits 31..16 are set */
+	if ((a2 & SPI_COMP_MASK) != 0) {
+		/* YUKON-Lite Rev. A0 */
+		fl_type = FT_SPI;
+		*FlashSize = max_pages * max_faddr;
+		return(1);
+	}
+	return(0);
+}
+#else
+int flash_check_spi( 
+unsigned long *FlashSize )
+{
+	unsigned long a1,a2;
+	unsigned long opcodes;
+	
+	*FlashSize = 0;
+
+	spi_in8(B2_CHIP_ID, &chip_id);
+
+	if (chip_id == CHIP_ID_YUKON_LITE || chip_id == CHIP_ID_YUKON_LP) {
+		/* YUKON-Lite Rev. A1 */
+		fl_type = FT_SPI;
+		*FlashSize = max_pages * max_faddr;
+		return(1);
+	}
+
+	if (chip_id == CHIP_ID_YUKON_XL || chip_id == CHIP_ID_YUKON_EC) {		
+		fl_type = FT_SPI_Y2;
+		spi_yuk2_dev = spi_yuk2_get_dev_index();
+
+		/* unknown or no flash */
+		if(spi_yuk2_dev < 0) {
+			fl_print("\nNo SPI flash found !\n");
+			fl_type = FT_SPI_UNKNOWN;
+			return(0);
+		}
+		
+		max_pages = (long)(spi_yuk2_dev_table[spi_yuk2_dev].sector_num);
+		max_faddr = (long)(spi_yuk2_dev_table[spi_yuk2_dev].sector_size);
+		*FlashSize = spi_yuk2_dev_table[spi_yuk2_dev].sector_num * spi_yuk2_dev_table[spi_yuk2_dev].sector_size;
+
+		/*
+		 * work around for SST flash types to clear write 
+		 * protection bits which are set by default.
+		 */
+		if (spi_yuk2_dev_table[spi_yuk2_dev].man_id == SPI_MAN_ID_SST) {
+			spi_yuk2_sst_clear_write_protection();
+		}
+
+		/*
+		 * set the opcodes for the SPI flash found 
+		 */
+		spi_in32(SPI_Y2_OPCODE_REG1, &opcodes);
+		opcodes &= 0x000000ffL;
+		opcodes |= ((((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read)) << 8) | 
+					(((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read_id)) << 16) |
+					(((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read_status)) << 24));
+
+		spi_out32(SPI_Y2_OPCODE_REG1, opcodes);
+
+		opcodes = (((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_write_enable)) | 
+				   (((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_write)) << 8) | 
+				   (((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_sector_erase)) << 16) |
+				   (((unsigned long)(spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_chip_erase)) << 24));
+
+		spi_out32(SPI_Y2_OPCODE_REG2, opcodes);
+
+		return(1);
+	}	
+
+	/* Save Eprom Address Register 1 */
+	spi_in32(SPI_ADR_REG1, &a1);
+	
+	/* Write SPI pattern */
+	spi_out32(SPI_ADR_REG1, SPI_PATTERN);
+	
+	/* Read SPI pattern */
+	spi_in32(SPI_ADR_REG1, &a2);
+	
+	/* Restore Eprom Address Register 1 */
+	spi_out32(SPI_ADR_REG1, a1);
+	
+	/* This is a SPI Eprom if one of bits 31..16 are set */
+	if ((a2 & SPI_COMP_MASK) != 0) {
+		/* YUKON-Lite Rev. A0 */
+		fl_type = FT_SPI;
+		*FlashSize = max_pages * max_faddr;
+		return(1);
+	}
+	return(0);
+}
+#endif
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_flash_erase(unsigned long off,unsigned long len)
+ *
+ *	Send chip erase command to SPI Eprom
+ *
+ * Uses:	spi_in32, spi_out32, spi_in8, spi_timer
+ *
+ * IN:
+ *	off	start offset in flash eprom for erase
+ *      len	length in flash eprom for erase
+ *		(all nessesory sectors will be erased)
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_flash_erase(
+unsigned long off,
+unsigned long len)
+{
+	switch (fl_type) {
+		case FT_SPI:
+			return(spi_yuk_flash_erase(off, len));
+		break;
+
+		case FT_SPI_Y2:
+			return(spi_yuk2_flash_erase(off, len));
+		break;
+	}
+
+	return(1);
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_flash_manage(
+ *	unsigned char  *data,
+ *	unsigned long off,
+ *	unsigned long len,
+ *	int flag)
+ *
+ *	Read, Verify or Write SPI Eprom
+ *
+ * Uses:	spi_in32, spi_out32, spi_in8, spi_out8, spi_in16, spi_out16, spi_timer
+ *
+ * IN:
+ *	data	data buffer
+ *	off		start offset in flash eprom for operation
+ *  len		length in flash eprom
+ *	flag	SPI_READ
+ *			SPI_VERIFY
+ *			SPI_WRITE
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_flash_manage(
+unsigned char  *data,
+unsigned long off,
+unsigned long len,
+int flag)
+{
+	switch (fl_type) {
+		case FT_SPI:
+			return(spi_yuk_flash_manage(data, off, len, flag));
+		break;
+
+		case FT_SPI_Y2:
+			return(spi_yuk2_flash_manage(data, off, len, flag));
+		break;
+	}
+
+	return(1);
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_get_pig(
+ *	unsigned char  *data,
+ *	unsigned long len)
+ *
+ *	Get data from PiG area in SPI eprom
+ *
+ * Uses: spi_update_config
+ *
+ * IN:
+ *	data	data buffer
+ *      len	length of wanted data
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_get_pig(
+unsigned char  *data,
+unsigned long len)
+{
+	return(spi_flash_manage(data, SPI_PIG_OFF, len, SPI_READ));
+}	
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_get_noc(
+ *	unsigned char  *data,
+ *	unsigned long len)
+ *
+ *	Get data from VPD area in SPI eprom
+ *
+ * Uses: spi_update_config
+ *
+ * IN:
+ *	data	data buffer
+ *      len	length of wanted data
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_get_noc(
+unsigned char  *data,
+unsigned long len)
+{
+	return(spi_flash_manage(data, SPI_NOC_OFF, len, SPI_READ));
+}	
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_update_pig(
+ *	unsigned char  *data,
+ *	unsigned long len)
+ *
+ *	Update data in PiG area in SPI eprom
+ *
+ * Uses: spi_update_config
+ *
+ * IN:
+ *	data	data buffer
+ *      len	length of data to update
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_update_pig(
+unsigned char  *data,
+unsigned long len)
+{
+	return(spi_update_config(data, SPI_PIG_OFF, len));
+}	
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_update_noc(
+ *	unsigned char  *data,
+ *	unsigned long len)
+ *
+ *	Update data in NOC area in SPI eprom
+ *
+ * Uses: spi_update_config
+ *
+ * IN:
+ *	data	data buffer
+ *      len	length of data to update
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_update_noc(
+unsigned char  *data,
+unsigned long len)
+{
+	return(spi_update_config(data, SPI_NOC_OFF, len));
+}	
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_vpd_tranfer(
+ *		char	*buf,	
+ *		int	addr,	
+ *		int	len,	
+ *		int	dir)	
+ *
+ *	Read or update data in VPD area in SPI eprom
+ *
+ * Uses: spi_update_config
+ *
+ * IN:
+ *	buf		data buffer
+ *	addr		VPD start address
+ *	len		number of bytes to read / to write
+ *	dir		transfer direction may be VPD_READ or VPD_WRITE
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_vpd_transfer(
+char	*buf,	/* data buffer */
+int		addr,	/* VPD start address */
+int		len,	/* number of bytes to read / to write */
+int		dir)	/* transfer direction may be VPD_READ or VPD_WRITE */
+{
+	if (dir == 0) {
+		return(spi_flash_manage(buf, SPI_VPD_OFF + addr, len, SPI_READ));
+	}
+	else {
+		return(spi_update_config(buf, SPI_VPD_OFF + addr, len));
+	}	
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_update_pet(
+ *	unsigned char  *data,
+ *	unsigned long len)
+ *
+ *	Update data in PET area in SPI eprom
+ *
+ * Uses: spi_update_config
+ *
+ * IN:
+ *	data	data buffer
+ *      len	length of data to update
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_update_pet(
+unsigned char  *data,
+unsigned long len)
+{
+	return(spi_update_config(data, SPI_PET_OFF, len));
+}	
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ *	int     spi_get_pet(
+ *	unsigned char  *data,
+ *	unsigned long len)
+ *
+ *	Get data from Pet frames area in SPI eprom
+ *
+ * Uses: spi_update_config
+ *
+ * IN:
+ *	data	data buffer
+ *      len	length of wanted data
+ *
+ * return:
+ *	0	Success
+ *	1	Timeout
+ *
+ * END_MANUAL_ENTRY()
+ */
+int spi_get_pet(
+unsigned char  *data,
+unsigned long len)
+{
+	return(spi_flash_manage(data, SPI_PET_OFF, len, SPI_READ));
+}	
diff --git a/drivers/net/sk98lin/skgespilole.c b/drivers/net/sk98lin/skgespilole.c
new file mode 100755
index 0000000..a38ea90
--- /dev/null
+++ b/drivers/net/sk98lin/skgespilole.c
@@ -0,0 +1,107 @@
+/******************************************************************************
+ *
+ * Name:	skspilole.c
+ * Project:	Flash Programmer, Manufacturing and Diagnostic Tools
+ * Version:	$Revision: 1.1.2.1 $
+ * Date:	$Date: 2006/08/28 09:06:52 $
+ * Purpose:	Contains Low Level Functions for the integration of the skspi.c module
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect
+ *	(C)Copyright 2002-2003 Marvell
+ *
+ *	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT
+ *	The copyright notice above does not evidence any
+ *	actual or intended publication of such source code.
+ *
+ *	This Module contains Proprietary Information of SysKonnect
+ *	and should be treated as Confidential.
+ *
+ *	The information in this file is provided for the exclusive use of
+ *	the licensees of SysKonnect.
+ *	Such users have the right to use, modify, and incorporate this code
+ *	into products for purposes authorized by the license agreement
+ *	provided they include this notice and the associated copyright notice
+ *	with any such product.
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skgespilole.c,v 1.1.2.1 2006/08/28 09:06:52 mlindner Exp $ (C) Marvell.";
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#include "h/skgespi.h"
+
+
+SK_AC *lpAC;
+static  SK_U32 timebuf;
+
+int fl_type;
+/*
+ * global vars
+ */
+long max_pages = 0;
+long max_faddr = 0;
+
+
+/* low level SPI programming interface */
+
+void spi_init_pac( SK_AC *pAC )  {
+	lpAC = pAC;
+}
+
+void spi_in8(unsigned short offs, unsigned char *val )  {
+	SK_IN8( lpAC->IoBase, offs, val ); 
+}
+
+void spi_in16(unsigned short offs, unsigned short *val ){
+	SK_IN16( lpAC->IoBase, offs, val ); 
+}
+
+void spi_in32(unsigned short offs, unsigned long *val ){
+	SK_IN32( lpAC->IoBase, offs, val ); 
+}
+
+void spi_out8(unsigned short offs, unsigned char val ){
+	SK_OUT8( lpAC->IoBase, offs, val ); 
+}
+
+void spi_out16(unsigned short offs, unsigned short val ){
+	SK_OUT16( lpAC->IoBase, offs, val ); 
+}
+
+void spi_out32(unsigned short offs, unsigned long val ){
+	SK_OUT32( lpAC->IoBase, offs, val ); 
+}
+
+int  spi_timer(unsigned int t){
+	if(t)
+	{
+		timebuf = (SK_U32)SkOsGetTime(lpAC)+(SK_U32)t*SK_TICKS_PER_SEC ; 
+	} else
+	{
+		if((timebuf <= (SK_U32)SkOsGetTime(lpAC)))
+		{
+			return(1); 
+		}
+	}
+	return(0); 
+}
+
+/*  dummies */
+void fl_print(char *msg, ...) {
+}
+
+unsigned char *spi_malloc( unsigned short size )  {
+	return( kmalloc(size,GFP_KERNEL) );
+}
+
+void spi_free( unsigned char *buf )  {
+	kfree(buf);
+}
+
diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
new file mode 100755
index 0000000..de429f2
--- /dev/null
+++ b/drivers/net/sk98lin/sklm80.c
@@ -0,0 +1,215 @@
+/******************************************************************************
+ *
+ * Name:	sklm80.c
+ * Project:	Gigabit Ethernet Adapters, TWSI-Module
+ * Version:	$Revision: 1.2 $
+ * Date:	$Date: 2005/12/14 16:10:53 $
+ * Purpose:	Functions to access Voltage and Temperature Sensor (LM80)
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+	LM80 functions
+*/
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: sklm80.c,v 1.2 2005/12/14 16:10:53 ibrueder Exp $ (C) Marvell. ";
+#endif
+
+#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+#include "h/lm80.h"
+#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+
+#ifdef	SK_DIAG
+#define	BREAK_OR_WAIT(pAC,IoC,Event)	SkI2cWait(pAC,IoC,Event)
+#else	/* nSK_DIAG */
+#define	BREAK_OR_WAIT(pAC,IoC,Event)	break
+#endif	/* nSK_DIAG */
+
+#ifdef	SK_DIAG
+/*
+ * read the register 'Reg' from the device 'Dev'
+ *
+ * return 	read error	-1
+ *		success		the read value
+ */
+int	SkLm80RcvReg(
+SK_IOC	IoC,		/* Adapter Context */
+int		Dev,		/* I2C device address */
+int		Reg)		/* register to read */
+{
+	int	Val = 0;
+	int	TempExt;
+
+	/* Signal device number */
+	if (SkI2cSndDev(IoC, Dev, I2C_WRITE)) {
+		return(-1);
+	}
+
+	if (SkI2cSndByte(IoC, Reg)) {
+		return(-1);
+	}
+
+	/* repeat start */
+	if (SkI2cSndDev(IoC, Dev, I2C_READ)) {
+		return(-1);
+	}
+
+	switch (Reg) {
+	case LM80_TEMP_IN:
+		Val = (int)SkI2cRcvByte(IoC, 1);
+
+		/* First: correct the value: it might be negative */
+		if ((Val & 0x80) != 0) {
+			/* Value is negative */
+			Val = Val - 256;
+		}
+		Val = Val * SK_LM80_TEMP_LSB;
+		SkI2cStop(IoC);
+		
+		TempExt = (int)SkLm80RcvReg(IoC, LM80_ADDR, LM80_TEMP_CTRL);
+		
+		if (Val > 0) {
+			Val += ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB);
+		}
+		else {
+			Val -= ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB);
+		}
+		return(Val);
+		break;
+	case LM80_VT0_IN:
+	case LM80_VT1_IN:
+	case LM80_VT2_IN:
+	case LM80_VT3_IN:
+		Val = (int)SkI2cRcvByte(IoC, 1) * SK_LM80_VT_LSB;
+		break;
+	
+	default:
+		Val = (int)SkI2cRcvByte(IoC, 1);
+		break;
+	}
+
+	SkI2cStop(IoC);
+	return(Val);
+}
+#endif	/* SK_DIAG */
+
+/*
+ * read a sensors value (LM80 specific)
+ *
+ * This function reads a sensors value from the TWSI sensor chip LM80.
+ * The sensor is defined by its index into the sensors database in the struct
+ * pAC points to.
+ *
+ * Returns	1 if the read is completed
+ *		0 if the read must be continued (TWSI Bus still allocated)
+ */
+int SkLm80ReadSensor(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context needed in level 1 and 2 */
+SK_SENSOR	*pSen)	/* Sensor to be read */
+{
+	SK_I32		Value;
+
+	switch (pSen->SenState) {
+	case SK_SEN_IDLE:
+		/* Send address to ADDR register */
+		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0);
+
+		pSen->SenState = SK_SEN_VALUE ;
+		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
+	
+	case SK_SEN_VALUE:
+		/* Read value from data register */
+		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
+		
+		Value &= 0xff; /* only least significant byte is valid */
+
+		/* Do NOT check the Value against the thresholds */
+		/* Checking is done in the calling instance */
+
+		if (pSen->SenType == SK_SEN_VOLT) {
+			/* Voltage sensor */
+			pSen->SenValue = Value * SK_LM80_VT_LSB;
+			pSen->SenState = SK_SEN_IDLE ;
+			return(1);
+		}
+
+		if (pSen->SenType == SK_SEN_FAN) {
+			if (Value != 0 && Value != 0xff) {
+				/* Fan speed counter */
+				pSen->SenValue = SK_LM80_FAN_FAKTOR/Value;
+			}
+			else {
+				/* Indicate Fan error */
+				pSen->SenValue = 0;
+			}
+			pSen->SenState = SK_SEN_IDLE ;
+			return(1);
+		}
+
+		/* First: correct the value: it might be negative */
+		if ((Value & 0x80) != 0) {
+			/* Value is negative */
+			Value = Value - 256;
+		}
+
+		/* We have a temperature sensor and need to get the signed extension.
+		 * For now we get the extension from the last reading, so in the normal
+		 * case we won't see flickering temperatures.
+		 */
+		pSen->SenValue = (Value * SK_LM80_TEMP_LSB) +
+			(pSen->SenValue % SK_LM80_TEMP_LSB);
+
+		/* Send address to ADDR register */
+		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
+
+		pSen->SenState = SK_SEN_VALEXT ;
+		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
+	
+	case SK_SEN_VALEXT:
+		/* Read value from data register */
+		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
+		Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */
+
+		/* cut the LSB bit */
+		pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) *
+			SK_LM80_TEMP_LSB);
+
+		if (pSen->SenValue < 0) {
+			/* Value negative: The bit value must be subtracted */
+			pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
+		}
+		else {
+			/* Value positive: The bit value must be added */
+			pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
+		}
+
+		pSen->SenState = SK_SEN_IDLE ;
+		return(1);
+	
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG);
+		return(1);
+	}
+
+	/* Not completed */
+	return(0);
+}
+
diff --git a/drivers/net/sk98lin/skproc.c b/drivers/net/sk98lin/skproc.c
new file mode 100755
index 0000000..323d16e
--- /dev/null
+++ b/drivers/net/sk98lin/skproc.c
@@ -0,0 +1,477 @@
+/******************************************************************************
+ *
+ * Name:	skproc.c
+ * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 1.15 $
+ * Date:	$Date: 2006/07/19 15:37:21 $
+ * Purpose:	Functions to display statictic data
+ *
+ ******************************************************************************/
+ 
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet 
+ *      Server Adapters.
+ *
+ *	Author: Ralph Roesler (rroesler@syskonnect.de)
+ *	        Mirko Lindner (mlindner@syskonnect.de)
+ *
+ *	Address all question to: linux@syskonnect.de
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ *****************************************************************************/
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#include "h/skversion.h"
+
+extern struct SK_NET_DEVICE *SkGeRootDev;
+
+/******************************************************************************
+ *
+ * Local Function Prototypes and Local Variables
+ *
+ *****************************************************************************/
+
+static int sk_proc_print(void *writePtr, char *format, ...);
+static void sk_gen_browse(void *buffer);
+static int len;
+
+static int sk_seq_show(struct seq_file *seq, void *v);
+static int sk_proc_open(struct inode *inode, struct file *file);
+struct file_operations sk_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= sk_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+struct net_device *currDev = NULL;
+
+/*****************************************************************************
+ *
+ * 	sk_gen_browse -generic  print "summaries" entry 
+ *
+ * Description:
+ *	This function fills the proc entry with statistic data about 
+ *	the ethernet device.
+ *  
+ * Returns:	N/A
+ *	
+ */
+static void sk_gen_browse(
+void *buffer)  /* buffer where the statistics will be stored in */
+{
+	struct SK_NET_DEVICE	*SkgeProcDev = SkGeRootDev;
+	struct SK_NET_DEVICE	*next;
+	SK_BOOL			DisableStatistic = 0;
+	SK_PNMI_STRUCT_DATA 	*pPnmiStruct;
+	SK_PNMI_STAT		*pPnmiStat;
+	unsigned long		Flags;	
+	unsigned int		Size;
+	DEV_NET			*pNet;
+	SK_AC			*pAC;
+	char			sens_msg[50];
+	int 			card_type;
+	int			MaxSecurityCount = 0;
+	int 			t;
+	int 			i;
+
+	while (SkgeProcDev) {
+		MaxSecurityCount++;
+		if (MaxSecurityCount > 100) {
+			printk("Max limit for sk_proc_read security counter!\n");
+			return;
+		}
+		pNet = (DEV_NET*)netdev_priv(SkgeProcDev);
+		pAC = pNet->pAC;
+		next = pAC->Next;
+		pPnmiStruct = &pAC->PnmiStruct;
+		/* NetIndex in GetStruct is now required, zero is only dummy */
+
+		for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
+			if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
+				t--;
+
+			spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+			Size = SK_PNMI_STRUCT_SIZE;
+			DisableStatistic = 0;
+			if (pAC->BoardLevel == SK_INIT_DATA) {
+				SK_MEMCPY(&(pAC->PnmiStruct), &(pAC->PnmiBackup), sizeof(SK_PNMI_STRUCT_DATA));
+				if (pAC->DiagModeActive == DIAG_NOTACTIVE) {
+					pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
+				}
+			} else {
+				SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, t-1);
+			}
+			spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+			if (strcmp(pAC->dev[t-1]->name, currDev->name) == 0) {
+				if (!pAC->GIni.GIYukon32Bit)
+					card_type = 64;
+				else
+					card_type = 32;
+
+				pPnmiStat = &pPnmiStruct->Stat[0];
+				len = sk_proc_print(buffer, 
+					"\nDetailed statistic for device %s\n",
+					pAC->dev[t-1]->name);
+				len += sk_proc_print(buffer,
+					"=======================================\n");
+	
+				/* Board statistics */
+				len += sk_proc_print(buffer, 
+					"\nBoard statistics\n\n");
+				len += sk_proc_print(buffer,
+					"Card name                      %s\n",
+					pAC->DeviceStr);
+				len += sk_proc_print(buffer,
+					"Vendor/Device ID               %x/%x\n",
+					pAC->PciDev->vendor,
+					pAC->PciDev->device);
+				len += sk_proc_print(buffer,
+					"Card type (Bit)                %d\n",
+					card_type);
+					
+				len += sk_proc_print(buffer,
+					"Active Port                    %c\n",
+					'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
+					Net[t-1].PrefPort]->PortNumber);
+				len += sk_proc_print(buffer,
+					"Preferred Port                 %c\n",
+					'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
+					Net[t-1].PrefPort]->PortNumber);
+
+				if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
+					len += sk_proc_print(buffer,
+					"Interrupt Moderation           static (%d ints/sec)\n",
+					pAC->DynIrqModInfo.MaxModIntsPerSec);
+				} else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+					len += sk_proc_print(buffer,
+					"Interrupt Moderation           dynamic (%d ints/sec)\n",
+					pAC->DynIrqModInfo.MaxModIntsPerSec);
+				} else {
+					len += sk_proc_print(buffer,
+					"Interrupt Moderation           disabled\n");
+				}
+
+				if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
+					len += sk_proc_print(buffer,
+						"Bus type                       PCI-Express\n");
+					len += sk_proc_print(buffer,
+						"Bus width (Lanes)              %d\n",
+						pAC->GIni.GIPexWidth);
+				} else {
+					if (pAC->GIni.GIPciBus == SK_PCIX_BUS) {
+						len += sk_proc_print(buffer,
+							"Bus type                       PCI-X\n");
+						if (pAC->GIni.GIPciMode == PCI_OS_SPD_X133) {
+							len += sk_proc_print(buffer,
+								"Bus speed (MHz)                133\n");
+						} else if (pAC->GIni.GIPciMode == PCI_OS_SPD_X100) {
+							len += sk_proc_print(buffer,
+								"Bus speed (MHz)                100\n");
+						} else if (pAC->GIni.GIPciMode == PCI_OS_SPD_X66) {
+							len += sk_proc_print(buffer,
+								"Bus speed (MHz)                66\n");
+						} else {
+							len += sk_proc_print(buffer,
+								"Bus speed (MHz)                33\n");
+						}
+					} else {
+						len += sk_proc_print(buffer,
+							"Bus type                       PCI\n");
+						len += sk_proc_print(buffer,
+							"Bus speed (MHz)                %d\n",
+							pPnmiStruct->BusSpeed);
+					}
+					len += sk_proc_print(buffer,
+						"Bus width (Bit)                %d\n",
+						pPnmiStruct->BusWidth);
+				}
+
+				len += sk_proc_print(buffer,
+					"Driver version                 %s (%s)\n",
+					VER_STRING, PATCHLEVEL);
+				len += sk_proc_print(buffer,
+					"Driver release date            %s\n",
+					pAC->Pnmi.pDriverReleaseDate);
+				len += sk_proc_print(buffer,
+					"Hardware revision              v%d.%d\n",
+					(pAC->GIni.GIPciHwRev >> 4) & 0x0F,
+					pAC->GIni.GIPciHwRev & 0x0F);
+
+				if (!netif_running(pAC->dev[t-1])) {
+					len += sk_proc_print(buffer,
+						"\n      Device %s is down.\n"
+						"      Therefore no statistics are available.\n"
+						"      After bringing the device up (ifconfig)"
+						" statistics will\n"
+						"      be displayed.\n",
+						pAC->dev[t-1]->name);
+					DisableStatistic = 1;
+				}
+
+				/* Display only if statistic info available */
+				/* Print sensor informations */
+				if (!DisableStatistic) {
+					for (i=0; i < pAC->I2c.MaxSens; i ++) {
+						/* Check type */
+						switch (pAC->I2c.SenTable[i].SenType) {
+						case 1:
+							strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+							strcat(sens_msg, " (C)");
+							len += sk_proc_print(buffer,
+								"%-25s      %d.%02d\n",
+								sens_msg,
+								pAC->I2c.SenTable[i].SenValue / 10,
+								pAC->I2c.SenTable[i].SenValue %
+								10);
+
+							strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+							strcat(sens_msg, " (F)");
+							len += sk_proc_print(buffer,
+								"%-25s      %d.%02d\n",
+								sens_msg,
+								((((pAC->I2c.SenTable[i].SenValue)
+								*10)*9)/5 + 3200)/100,
+								((((pAC->I2c.SenTable[i].SenValue)
+								*10)*9)/5 + 3200) % 10);
+							break;
+						case 2:
+							strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+							strcat(sens_msg, " (V)");
+							len += sk_proc_print(buffer,
+								"%-25s      %d.%03d\n",
+								sens_msg,
+								pAC->I2c.SenTable[i].SenValue / 1000,
+								pAC->I2c.SenTable[i].SenValue % 1000);
+							break;
+						case 3:
+							strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+							strcat(sens_msg, " (rpm)");
+							len += sk_proc_print(buffer,
+								"%-25s      %d\n",
+								sens_msg,
+								pAC->I2c.SenTable[i].SenValue);
+							break;
+						default:
+							break;
+						}
+					}
+			
+					/*Receive statistics */
+					len += sk_proc_print(buffer, 
+					"\nReceive statistics\n\n");
+
+					len += sk_proc_print(buffer,
+						"Received bytes                 %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxOctetsOkCts);
+					len += sk_proc_print(buffer,
+						"Received packets               %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxOkCts);
+#if 0
+					if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && 
+						pAC->HWRevision < 12) {
+						pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - 
+							pPnmiStat->StatRxShortsCts;
+						pPnmiStat->StatRxShortsCts = 0;
+					}
+#endif
+					if (pAC->dev[t-1]->mtu > 1500) 
+						pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
+							pPnmiStat->StatRxTooLongCts;
+
+					len += sk_proc_print(buffer,
+						"Receive errors                 %Lu\n",
+						(unsigned long long) pPnmiStruct->InErrorsCts);
+					len += sk_proc_print(buffer,
+						"Receive dropped                %Lu\n",
+						(unsigned long long) pPnmiStruct->RxNoBufCts);
+					len += sk_proc_print(buffer,
+						"Received multicast             %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxMulticastOkCts);
+#ifdef ADVANCED_STATISTIC_OUTPUT
+					len += sk_proc_print(buffer,
+						"Receive error types\n");
+					len += sk_proc_print(buffer,
+						"   length                      %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxRuntCts);
+					len += sk_proc_print(buffer,
+						"   buffer overflow             %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxFifoOverflowCts);
+					len += sk_proc_print(buffer,
+						"   bad crc                     %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxFcsCts);
+					len += sk_proc_print(buffer,
+						"   framing                     %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxFramingCts);
+					len += sk_proc_print(buffer,
+						"   missed frames               %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxMissedCts);
+
+					if (pAC->dev[t-1]->mtu > 1500)
+						pPnmiStat->StatRxTooLongCts = 0;
+
+					len += sk_proc_print(buffer,
+						"   too long                    %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxTooLongCts);					
+					len += sk_proc_print(buffer,
+						"   carrier extension           %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxCextCts);				
+					len += sk_proc_print(buffer,
+						"   too short                   %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxShortsCts);				
+					len += sk_proc_print(buffer,
+						"   symbol                      %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxSymbolCts);				
+					len += sk_proc_print(buffer,
+						"   LLC MAC size                %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxIRLengthCts);				
+					len += sk_proc_print(buffer,
+						"   carrier event               %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxCarrierCts);				
+					len += sk_proc_print(buffer,
+						"   jabber                      %Lu\n",
+						(unsigned long long) pPnmiStat->StatRxJabberCts);				
+#endif
+
+					/*Transmit statistics */
+					len += sk_proc_print(buffer, 
+					"\nTransmit statistics\n\n");
+				
+					len += sk_proc_print(buffer,
+						"Transmitted bytes              %Lu\n",
+						(unsigned long long) pPnmiStat->StatTxOctetsOkCts);
+					len += sk_proc_print(buffer,
+						"Transmitted packets            %Lu\n",
+						(unsigned long long) pPnmiStat->StatTxOkCts);
+					len += sk_proc_print(buffer,
+						"Transmit errors                %Lu\n",
+						(unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
+					len += sk_proc_print(buffer,
+						"Transmit dropped               %Lu\n",
+						(unsigned long long) pPnmiStruct->TxNoBufCts);
+					len += sk_proc_print(buffer,
+						"Transmit collisions            %Lu\n",
+						(unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
+#ifdef ADVANCED_STATISTIC_OUTPUT
+					len += sk_proc_print(buffer,
+						"Transmit error types\n");
+					len += sk_proc_print(buffer,
+						"   excessive collision         %ld\n",
+						pAC->stats.tx_aborted_errors);
+					len += sk_proc_print(buffer,
+						"   carrier                     %Lu\n",
+						(unsigned long long) pPnmiStat->StatTxCarrierCts);
+					len += sk_proc_print(buffer,
+						"   fifo underrun               %Lu\n",
+						(unsigned long long) pPnmiStat->StatTxFifoUnderrunCts);
+					len += sk_proc_print(buffer,
+						"   heartbeat                   %Lu\n",
+						(unsigned long long) pPnmiStat->StatTxCarrierCts);
+					len += sk_proc_print(buffer,
+						"   window                      %ld\n",
+						pAC->stats.tx_window_errors);
+#endif
+				} /* if (!DisableStatistic) */
+				
+			} /* if (strcmp(pACname, currDeviceName) == 0) */
+		}
+		SkgeProcDev = next;
+	}
+}
+
+/*****************************************************************************
+ *
+ *      sk_proc_print - generic line print  
+ *
+ * Description:
+ *	This function fills the proc entry with statistic data about the 
+ *	ethernet device.
+ *  
+ * Returns:
+ *	the number of bytes written
+ *      
+ */ 
+static int sk_proc_print(
+void *writePtr, /* the buffer pointer         */
+char *format,   /* the format of the string   */
+...)            /* variable list of arguments */
+{   
+#define MAX_LEN_SINGLE_LINE 256
+	char     str[MAX_LEN_SINGLE_LINE];
+	va_list  a_start;
+	int      lenght = 0;
+
+	struct seq_file *seq = (struct seq_file *) writePtr;
+
+	SK_MEMSET(str, 0, MAX_LEN_SINGLE_LINE);
+
+	va_start(a_start, format);
+	vsprintf(str, format, a_start);
+	va_end(a_start);
+
+	lenght = strlen(str);
+
+	seq_printf(seq, str);
+	return lenght;
+}
+
+/*****************************************************************************
+ *
+ *      sk_seq_show - show proc information of a particular adapter
+ *
+ * Description:
+ *	This function fills the proc entry with statistic data about the
+ *	ethernet device. It invokes the generic sk_gen_browse() to print
+ *	out all items one per one.
+ *  
+ * Returns:
+ *	the number of bytes written
+ *      
+ */
+static int sk_seq_show(
+struct seq_file *seq,  /* the sequence pointer */
+void            *v)    /* additional pointer   */
+{
+	void *castedBuffer = (void *) seq;
+	currDev = seq->private;
+	sk_gen_browse(castedBuffer);
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ *      sk_proc_open - register the show function when proc is open'ed
+ *  
+ * Description:
+ *	This function is called whenever a sk98lin proc file is queried.
+ *  
+ * Returns:
+ *	the return value of single_open()
+ *      
+ */
+static int sk_proc_open(
+struct inode *inode,  /* the inode of the file   */
+struct file  *file)   /* the file pointer itself */
+{
+	return single_open(file, sk_seq_show, PDE(inode)->data);
+}
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
new file mode 100755
index 0000000..10bf790
--- /dev/null
+++ b/drivers/net/sk98lin/skqueue.c
@@ -0,0 +1,238 @@
+/******************************************************************************
+ *
+ * Name:	skqueue.c
+ * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 2.5 $
+ * Date:	$Date: 2005/12/14 16:11:02 $
+ * Purpose:	Management of an event queue.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+
+/*
+ *	Event queue and dispatcher
+ */
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skqueue.c,v 2.5 2005/12/14 16:11:02 ibrueder Exp $ (C) Marvell.";
+#endif
+
+#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+#include "h/skqueue.h"		/* Queue Definitions */
+#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+
+#ifdef __C2MAN__
+/*
+	Event queue management.
+
+	General Description:
+
+ */
+intro()
+{}
+#endif
+
+#define PRINTF(a,b,c)
+
+/******************************************************************************
+ *
+ *	SkEventInit() - init event queue management
+ *
+ * Description:
+ * 	This function initializes event queue management.
+ *	It must be called during init level 0.
+ *
+ * Returns:
+ *	nothing
+ */
+void	SkEventInit(
+SK_AC	*pAC,	/* Adapter context */
+SK_IOC	Ioc,	/* IO context */
+int		Level)	/* Init level */
+{
+	switch (Level) {
+	case SK_INIT_DATA:
+		pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue;
+		break;
+	default:
+		break;
+	}
+}
+
+/******************************************************************************
+ *
+ *	SkEventQueue()	-	add event to queue
+ *
+ * Description:
+ *	This function adds an event to the event queue.
+ *	At least Init Level 1 is required to queue events,
+ *	but will be scheduled add Init Level 2.
+ *
+ * returns:
+ *	nothing
+ */
+void	SkEventQueue(
+SK_AC		*pAC,	/* Adapters context */
+SK_U32		Class,	/* Event Class */
+SK_U32		Event,	/* Event to be queued */
+SK_EVPARA	Para)	/* Event parameter */
+{
+
+	if (pAC->GIni.GILevel == SK_INIT_DATA) {
+		SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E003, SKERR_Q_E003MSG);
+	}
+	else {
+		pAC->Event.EvPut->Class = Class;
+		pAC->Event.EvPut->Event = Event;
+		pAC->Event.EvPut->Para = Para;
+	
+		if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
+			pAC->Event.EvPut = pAC->Event.EvQueue;
+
+		if (pAC->Event.EvPut == pAC->Event.EvGet) {
+			SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
+		}
+	}
+}
+
+/******************************************************************************
+ *
+ *	SkEventDispatcher() -	 Event Dispatcher
+ *
+ * Description:
+ *	The event dispatcher performs the following operations:
+ *		o while event queue is not empty
+ *			- get event from queue
+ *			- send event to state machine
+ *		  end
+ *
+ * CAUTION:
+ *	The event functions MUST report an error if performing a reinitialization
+ *	of the event queue, e.g. performing level Init 0..2 while in dispatcher
+ *	call!
+ *  ANY OTHER return value delays scheduling the other events in the
+ *	queue. In this case the event blocks the queue until
+ *  the error condition is cleared!
+ *
+ * Returns:
+ *	The return value error reported by individual event function
+ */
+int	SkEventDispatcher(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	Ioc)	/* Io context */
+{
+	SK_EVENTELEM	*pEv;	/* pointer into queue */
+	SK_U32			Class;
+	int			Rtv;
+
+	if (pAC->GIni.GILevel != SK_INIT_RUN) {
+		SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E005, SKERR_Q_E005MSG);
+	}
+
+	pEv = pAC->Event.EvGet;
+	
+	PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
+	
+	while (pEv != pAC->Event.EvPut) {
+		PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event);
+
+		switch (Class = pEv->Class) {
+#ifndef SK_USE_LAC_EV
+#ifndef SK_SLIM
+		case SKGE_RLMT:		/* RLMT Event */
+			Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+		case SKGE_I2C:		/* I2C Event */
+			Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+		case SKGE_PNMI:		/* PNMI Event */
+			Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+#endif	/* not SK_SLIM */
+#endif	/* not SK_USE_LAC_EV */
+		case SKGE_DRV:		/* Driver Event */
+			Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+#ifndef SK_USE_SW_TIMER
+		case SKGE_HWAC:
+			Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+#else /* !SK_USE_SW_TIMER */
+        case SKGE_SWT :
+			Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+#endif /* !SK_USE_SW_TIMER */
+#if defined(SK_USE_LAC_EV) || defined(SK_LBFO)
+		case SKGE_LACP :
+			Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+		case SKGE_RSF :
+			Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+		case SKGE_MARKER :
+			Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+		case SKGE_FD :
+			Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+#endif /* SK_USE_LAC_EV */
+#ifdef SK_ASF
+		case SKGE_ASF :
+			Rtv = SkAsfEvent(pAC,Ioc,pEv->Event,pEv->Para);
+			break ;
+#endif
+#ifdef	SK_USE_CSUM
+		case SKGE_CSUM :
+			Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
+			break;
+#endif	/* SK_USE_CSUM */
+		default :
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG);
+			Rtv = 0;
+		}
+
+		if (Rtv != 0) {
+			/* 
+			 * Special Case: See CAUTION statement above.
+			 * We assume the event queue is reset.
+			 */
+			if (pAC->Event.EvGet != pAC->Event.EvQueue &&
+				pAC->Event.EvGet != pEv) {
+				/*
+				 * Create an error log entry if the
+				 * event queue isn't reset.
+				 * In this case it may be blocked.
+				 */
+				SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E004, SKERR_Q_E004MSG);
+			}
+
+			return(Rtv);
+		}
+
+		if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT])
+			pEv = pAC->Event.EvQueue;
+
+		/* Renew get: it is used in queue_events to detect overruns */
+		pAC->Event.EvGet = pEv;
+	}
+
+	return(0);
+}
+
+/* End of file */
diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
new file mode 100755
index 0000000..f407043
--- /dev/null
+++ b/drivers/net/sk98lin/skrlmt.c
@@ -0,0 +1,3283 @@
+/******************************************************************************
+ *
+ * Name:	skrlmt.c
+ * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+ * Version:	$Revision: 2.6 $
+ * Date:	$Date: 2007/07/30 08:50:12 $
+ * Purpose:	Manage links on SK-NET Adapters, esp. redundant ones.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2003 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Description:
+ *
+ * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
+ * It is mainly intended for adapters with more than one link.
+ * For such adapters, this module realizes Redundant Link ManagemenT (RLMT).
+ *
+ * Include File Hierarchy:
+ *
+ *	"skdrv1st.h"
+ *	"skdrv2nd.h"
+ *
+ ******************************************************************************/
+
+#ifndef	lint
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skrlmt.c,v 2.6 2007/07/30 08:50:12 tschilli Exp $ (C) Marvell.";
+#endif	/* !defined(lint) */
+
+#define __SKRLMT_C
+
+#ifdef __cplusplus
+extern "C" {
+#endif	/* cplusplus */
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+
+/* defines ********************************************************************/
+
+#ifndef SK_HWAC_LINK_LED
+#define SK_HWAC_LINK_LED(a,b,c,d)
+#endif	/* !defined(SK_HWAC_LINK_LED) */
+
+#ifndef DEBUG
+#define RLMT_STATIC	static
+#else	/* DEBUG */
+#define RLMT_STATIC
+
+#ifndef SK_LITTLE_ENDIAN
+/* First 32 bits */
+#define OFFS_LO32	1
+
+/* Second 32 bits */
+#define OFFS_HI32	0
+#else	/* SK_LITTLE_ENDIAN */
+/* First 32 bits */
+#define OFFS_LO32	0
+
+/* Second 32 bits */
+#define OFFS_HI32	1
+#endif	/* SK_LITTLE_ENDIAN */
+
+#endif	/* DEBUG */
+
+/* ----- Private timeout values ----- */
+
+#define SK_RLMT_MIN_TO_VAL			   125000	/* 1/8 sec. */
+#define SK_RLMT_DEF_TO_VAL			  1000000	/* 1 sec. */
+#define SK_RLMT_PORTDOWN_TIM_VAL	   900000	/* another 0.9 sec. */
+#define SK_RLMT_PORTSTART_TIM_VAL	   100000	/* 0.1 sec. */
+#define SK_RLMT_PORTUP_TIM_VAL		  2500000	/* 2.5 sec. */
+#define SK_RLMT_SEG_TO_VAL			900000000	/* 15 min. */
+
+/* Assume tick counter increment is 1 - may be set OS-dependent. */
+#ifndef SK_TICK_INCR
+#define SK_TICK_INCR	SK_CONSTU64(1)
+#endif	/* !defined(SK_TICK_INCR) */
+
+/*
+ * Amount that a time stamp must be later to be recognized as "substantially
+ * later". This is about 1/128 sec, but above 1 tick counter increment.
+ */
+#define SK_RLMT_BC_DELTA		(1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
+									(SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
+
+/* ----- Private RLMT defaults ----- */
+
+#define SK_RLMT_DEF_PREF_PORT	0					/* "Lower" port. */
+#define SK_RLMT_DEF_MODE 		SK_RLMT_CHECK_LINK	/* Default RLMT Mode. */
+
+/* ----- Private RLMT checking states ----- */
+
+#define SK_RLMT_RCS_SEG			1		/* RLMT Check State: check seg. */
+#define SK_RLMT_RCS_START_SEG	2		/* RLMT Check State: start check seg. */
+#define SK_RLMT_RCS_SEND_SEG	4		/* RLMT Check State: send BPDU packet */
+#define SK_RLMT_RCS_REPORT_SEG	8		/* RLMT Check State: report seg. */
+
+/* ----- Private PORT checking states ----- */
+
+#define SK_RLMT_PCS_TX			1		/* Port Check State: check tx. */
+#define SK_RLMT_PCS_RX			2		/* Port Check State: check rx. */
+
+/* ----- Private PORT events ----- */
+
+/* Note: Update simulation when changing these. */
+#define SK_RLMT_PORTSTART_TIM	1100	/* Port start timeout. */
+#define SK_RLMT_PORTUP_TIM		1101	/* Port can now go up. */
+#define SK_RLMT_PORTDOWN_RX_TIM	1102	/* Port did not receive once ... */
+#define SK_RLMT_PORTDOWN		1103	/* Port went down. */
+#define SK_RLMT_PORTDOWN_TX_TIM	1104	/* Partner did not receive ... */
+
+/* ----- Private RLMT events ----- */
+
+/* Note: Update simulation when changing these. */
+#define SK_RLMT_TIM				2100	/* RLMT timeout. */
+#define SK_RLMT_SEG_TIM			2101	/* RLMT segmentation check timeout. */
+
+#define TO_SHORTEN(tim)	((tim) / 2)
+
+/* Error numbers and messages. */
+#define SKERR_RLMT_E001		(SK_ERRBASE_RLMT + 0)
+#define SKERR_RLMT_E001_MSG	"No Packet."
+#define SKERR_RLMT_E002		(SKERR_RLMT_E001 + 1)
+#define SKERR_RLMT_E002_MSG	"Short Packet."
+#define SKERR_RLMT_E003		(SKERR_RLMT_E002 + 1)
+#define SKERR_RLMT_E003_MSG	"Unknown RLMT event."
+#define SKERR_RLMT_E004		(SKERR_RLMT_E003 + 1)
+#define SKERR_RLMT_E004_MSG	"PortsUp incorrect."
+#define SKERR_RLMT_E005		(SKERR_RLMT_E004 + 1)
+#define SKERR_RLMT_E005_MSG	\
+ "Net seems to be segmented (different root bridges are reported on the ports)."
+#define SKERR_RLMT_E006		(SKERR_RLMT_E005 + 1)
+#define SKERR_RLMT_E006_MSG	"Duplicate MAC Address detected."
+#define SKERR_RLMT_E007		(SKERR_RLMT_E006 + 1)
+#define SKERR_RLMT_E007_MSG	"LinksUp incorrect."
+#define SKERR_RLMT_E008		(SKERR_RLMT_E007 + 1)
+#define SKERR_RLMT_E008_MSG	"Port not started but link came up."
+#define SKERR_RLMT_E009		(SKERR_RLMT_E008 + 1)
+#define SKERR_RLMT_E009_MSG	"Corrected illegal setting of Preferred Port."
+#define SKERR_RLMT_E010		(SKERR_RLMT_E009 + 1)
+#define SKERR_RLMT_E010_MSG	"Ignored illegal Preferred Port."
+
+/* LLC field values. */
+#define LLC_COMMAND_RESPONSE_BIT		1
+#define LLC_TEST_COMMAND				0xE3
+#define LLC_UI							0x03
+
+/* RLMT Packet fields. */
+#define	SK_RLMT_DSAP					0
+#define	SK_RLMT_SSAP					0
+#define SK_RLMT_CTRL					(LLC_TEST_COMMAND)
+#define SK_RLMT_INDICATOR0				0x53	/* S */
+#define SK_RLMT_INDICATOR1				0x4B	/* K */
+#define SK_RLMT_INDICATOR2				0x2D	/* - */
+#define SK_RLMT_INDICATOR3				0x52	/* R */
+#define SK_RLMT_INDICATOR4				0x4C	/* L */
+#define SK_RLMT_INDICATOR5				0x4D	/* M */
+#define SK_RLMT_INDICATOR6				0x54	/* T */
+#define SK_RLMT_PACKET_VERSION			0
+
+/* RLMT SPT Flag values. */
+#define	SK_RLMT_SPT_FLAG_CHANGE			0x01
+#define	SK_RLMT_SPT_FLAG_CHANGE_ACK		0x80
+
+/* RLMT SPT Packet fields. */
+#define	SK_RLMT_SPT_DSAP				0x42
+#define	SK_RLMT_SPT_SSAP				0x42
+#define SK_RLMT_SPT_CTRL				(LLC_UI)
+#define	SK_RLMT_SPT_PROTOCOL_ID0		0x00
+#define	SK_RLMT_SPT_PROTOCOL_ID1		0x00
+#define	SK_RLMT_SPT_PROTOCOL_VERSION_ID	0x00
+#define	SK_RLMT_SPT_BPDU_TYPE			0x00
+#define	SK_RLMT_SPT_FLAGS				0x00	/* ?? */
+#define	SK_RLMT_SPT_ROOT_ID0			0xFF	/* Lowest possible priority. */
+#define	SK_RLMT_SPT_ROOT_ID1			0xFF	/* Lowest possible priority. */
+
+/* Remaining 6 bytes will be the current port address. */
+#define	SK_RLMT_SPT_ROOT_PATH_COST0		0x00
+#define	SK_RLMT_SPT_ROOT_PATH_COST1		0x00
+#define	SK_RLMT_SPT_ROOT_PATH_COST2		0x00
+#define	SK_RLMT_SPT_ROOT_PATH_COST3		0x00
+#define	SK_RLMT_SPT_BRIDGE_ID0			0xFF	/* Lowest possible priority. */
+#define	SK_RLMT_SPT_BRIDGE_ID1			0xFF	/* Lowest possible priority. */
+
+/* Remaining 6 bytes will be the current port address. */
+#define	SK_RLMT_SPT_PORT_ID0			0xFF	/* Lowest possible priority. */
+#define	SK_RLMT_SPT_PORT_ID1			0xFF	/* Lowest possible priority. */
+#define	SK_RLMT_SPT_MSG_AGE0			0x00
+#define	SK_RLMT_SPT_MSG_AGE1			0x00
+#define	SK_RLMT_SPT_MAX_AGE0			0x00
+#define	SK_RLMT_SPT_MAX_AGE1			0xFF
+#define	SK_RLMT_SPT_HELLO_TIME0			0x00
+#define	SK_RLMT_SPT_HELLO_TIME1			0xFF
+#define	SK_RLMT_SPT_FWD_DELAY0			0x00
+#define	SK_RLMT_SPT_FWD_DELAY1			0x40
+
+/* Size defines. */
+#define SK_RLMT_MIN_PACKET_SIZE			34
+#define SK_RLMT_MAX_PACKET_SIZE			(SK_RLMT_MAX_TX_BUF_SIZE)
+#define SK_PACKET_DATA_LEN				(SK_RLMT_MAX_PACKET_SIZE - \
+										SK_RLMT_MIN_PACKET_SIZE)
+
+/* ----- RLMT packet types ----- */
+#define SK_PACKET_ANNOUNCE				1	/* Port announcement. */
+#define SK_PACKET_ALIVE					2	/* Alive packet to port. */
+#define SK_PACKET_ADDR_CHANGED			3	/* Port address changed. */
+#define SK_PACKET_CHECK_TX				4	/* Check your tx line. */
+
+#ifdef SK_LITTLE_ENDIAN
+#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \
+	SK_U8	*_Addr = (SK_U8*)(Addr); \
+	SK_U16	_Val = (SK_U16)(Val); \
+	*_Addr++ = (SK_U8)(_Val >> 8); \
+	*_Addr = (SK_U8)(_Val & 0xFF); \
+}
+#endif	/* SK_LITTLE_ENDIAN */
+
+#ifdef SK_BIG_ENDIAN
+#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
+#endif	/* SK_BIG_ENDIAN */
+
+#define AUTONEG_FAILED	SK_FALSE
+#define AUTONEG_SUCCESS	SK_TRUE
+
+
+/* typedefs *******************************************************************/
+
+/* RLMT packet.  Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */
+typedef struct s_RlmtPacket {
+	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
+	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
+	SK_U8	TypeLen[2];
+	SK_U8	DSap;
+	SK_U8	SSap;
+	SK_U8	Ctrl;
+	SK_U8	Indicator[7];
+	SK_U8	RlmtPacketType[2];
+	SK_U8	Align1[2];
+	SK_U8	Random[4];				/* Random value of requesting(!) station. */
+	SK_U8	RlmtPacketVersion[2];	/* RLMT Packet version. */
+	SK_U8	Data[SK_PACKET_DATA_LEN];
+} SK_RLMT_PACKET;
+
+typedef struct s_SpTreeRlmtPacket {
+	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
+	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
+	SK_U8	TypeLen[2];
+	SK_U8	DSap;
+	SK_U8	SSap;
+	SK_U8	Ctrl;
+	SK_U8	ProtocolId[2];
+	SK_U8	ProtocolVersionId;
+	SK_U8	BpduType;
+	SK_U8	Flags;
+	SK_U8	RootId[8];
+	SK_U8	RootPathCost[4];
+	SK_U8	BridgeId[8];
+	SK_U8	PortId[2];
+	SK_U8	MessageAge[2];
+	SK_U8	MaxAge[2];
+	SK_U8	HelloTime[2];
+	SK_U8	ForwardDelay[2];
+} SK_SPTREE_PACKET;
+
+/* global variables ***********************************************************/
+
+SK_MAC_ADDR	SkRlmtMcAddr =	{{0x01,  0x00,  0x5A,  0x52,  0x4C,  0x4D}};
+SK_MAC_ADDR	BridgeMcAddr =	{{0x01,  0x80,  0xC2,  0x00,  0x00,  0x00}};
+SK_MAC_ADDR	BcAddr = 		{{0xFF,  0xFF,  0xFF,  0xFF,  0xFF,  0xFF}};
+
+/* local variables ************************************************************/
+
+/* None. */
+
+/* functions ******************************************************************/
+
+RLMT_STATIC void	SkRlmtCheckSwitch(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	NetIdx);
+RLMT_STATIC void	SkRlmtCheckSeg(
+	SK_AC	*pAC,
+	SK_IOC	IoC,
+	SK_U32	NetIdx);
+RLMT_STATIC void	SkRlmtEvtSetNets(
+	SK_AC		*pAC,
+	SK_IOC		IoC,
+	SK_EVPARA	Para);
+
+/******************************************************************************
+ *
+ *	SkRlmtInit - initialize data, set state to init
+ *
+ * Description:
+ *
+ *	SK_INIT_DATA
+ *	============
+ *
+ *	This routine initializes all RLMT-related variables to a known state.
+ *	The initial state is SK_RLMT_RS_INIT.
+ *	All ports are initialized to SK_RLMT_PS_INIT.
+ *
+ *
+ *	SK_INIT_IO
+ *	==========
+ *
+ *	Nothing.
+ *
+ *
+ *	SK_INIT_RUN
+ *	===========
+ *
+ *	Determine the adapter's random value.
+ *	Set the hw registers, the "logical MAC address", the
+ *	RLMT multicast address, and eventually the BPDU multicast address.
+ *
+ * Context:
+ *	init, pageable
+ *
+ * Returns:
+ *	Nothing.
+ */
+void	SkRlmtInit(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Level)	/* Initialization Level */
+{
+	SK_U32		i, j;
+	SK_U64		Random;
+	SK_EVPARA	Para;
+    SK_MAC_ADDR		VirtualMacAddress;
+    SK_MAC_ADDR		PhysicalAMacAddress;
+    SK_BOOL		VirtualMacAddressSet;
+    SK_BOOL		PhysicalAMacAddressSet;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
+		("RLMT Init level %d.\n", Level));
+
+	switch (Level) {
+	case SK_INIT_DATA:	/* Initialize data structures. */
+		SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT));
+
+		for (i = 0; i < SK_MAX_MACS; i++) {
+			pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT;
+			pAC->Rlmt.Port[i].LinkDown = SK_TRUE;
+			pAC->Rlmt.Port[i].PortDown = SK_TRUE;
+			pAC->Rlmt.Port[i].PortStarted = SK_FALSE;
+			pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;
+			pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;
+			pAC->Rlmt.Port[i].PortNumber = i;
+			pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0];
+			pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i];
+		}
+
+		pAC->Rlmt.NumNets = 1;
+		for (i = 0; i < SK_MAX_NETS; i++) {
+			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* Automatic. */
+			/* Just assuming. */
+			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+			pAC->Rlmt.Net[i].NetNumber = i;
+		}
+
+		pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0];
+		pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];
+#if SK_MAX_NETS > 1
+		pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];
+#endif	/* SK_MAX_NETS > 1 */
+		pAC->Rlmt.RlmtOff = SK_FALSE;
+		break;
+
+	case SK_INIT_IO:	/* GIMacsFound first available here. */
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
+			("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound));
+
+		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
+
+		/* Initialize HW registers? */
+		if (pAC->GIni.GIMacsFound == 1) {
+			/* Single link adapter --> no RLMT */
+			pAC->Rlmt.RlmtOff = SK_TRUE;
+			Para.Para32[0] = SK_RLMT_MODE_CLS;
+			Para.Para32[1] = 0;
+			(void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);
+		}
+		break;
+
+	case SK_INIT_RUN:
+		/* Ensure RLMT is set to one net. */
+		if (pAC->Rlmt.NumNets > 1) {
+			Para.Para32[0] = 1;
+			Para.Para32[1] = -1;
+			SkRlmtEvtSetNets(pAC, IoC, Para);
+		}
+
+		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+			Random = SkOsGetTime(pAC);
+			*(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;
+
+			for (j = 0; j < 4; j++) {
+				pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort->
+					CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j];
+			}
+
+			(void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
+			
+			/* Add RLMT MC address. */
+			(void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT);
+
+			if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) {
+				/* Add BPDU MC address. */
+				(void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT);
+			}
+
+			(void)SkAddrMcUpdate(pAC, IoC, i);
+		}
+
+    	VirtualMacAddressSet = SK_FALSE;
+		/* Read virtual MAC address from Control Register File. */
+		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+			
+            SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]);
+            VirtualMacAddressSet |= VirtualMacAddress.a[j];
+		}
+    	
+        PhysicalAMacAddressSet = SK_FALSE;
+		/* Read physical MAC address for MAC A from Control Register File. */
+		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+			
+            SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]);
+            PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j];
+		}
+
+        /* check if the two mac addresses contain reasonable values */
+        if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) {
+
+            pAC->Rlmt.RlmtOff = SK_TRUE;
+        }
+
+        /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
+           and the RLMT_LOOKAHEAD macros */
+        else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) {
+
+            pAC->Rlmt.RlmtOff = SK_TRUE;
+        }
+
+		break;
+
+	default:	/* error */
+		break;
+	}
+	return;
+}	/* SkRlmtInit */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtBuildCheckChain - build the check chain
+ *
+ * Description:
+ *	This routine builds the local check chain:
+ *	- Each port that is up checks the next port.
+ *	- The last port that is up checks the first port that is up.
+ *
+ * Notes:
+ *	- Currently only local ports are considered when building the chain.
+ *	- Currently the SuspectState is just reset;
+ *	  it would be better to save it ...
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtBuildCheckChain(
+SK_AC	*pAC,	/* Adapter Context */
+SK_U32	NetIdx)	/* Net Number */
+{
+	SK_U32			i;
+	SK_U32			NumMacsUp;
+	SK_RLMT_PORT *	FirstMacUp;
+	SK_RLMT_PORT *	PrevMacUp;
+
+	FirstMacUp	= NULL;
+	PrevMacUp	= NULL;
+	
+	if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
+		for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) {
+			pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
+		}
+		return;	/* Done. */
+	}
+			
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SkRlmtBuildCheckChain.\n"));
+
+	NumMacsUp = 0;
+
+	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+		pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
+		pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0;
+		pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &=
+			~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);
+
+		/*
+		 * If more than two links are detected we should consider
+		 * checking at least two other ports:
+		 * 1. the next port that is not LinkDown and
+		 * 2. the next port that is not PortDown.
+		 */
+		if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
+			if (NumMacsUp == 0) {
+				FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
+			}
+			else {
+				PrevMacUp->PortCheck[
+					pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr =
+					pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress;
+				PrevMacUp->PortCheck[
+					PrevMacUp->PortsChecked].SuspectTx = SK_FALSE;
+				PrevMacUp->PortsChecked++;
+			}
+			PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
+			NumMacsUp++;
+		}
+	}
+
+	if (NumMacsUp > 1) {
+		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr =
+			FirstMacUp->AddrPort->CurrentMacAddress;
+		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx =
+			SK_FALSE;
+		PrevMacUp->PortsChecked++;
+	}
+
+#ifdef DEBUG
+	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Port %d checks %d other ports: %2X.\n", i,
+				pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
+				pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]));
+	}
+#endif	/* DEBUG */
+
+	return;
+}	/* SkRlmtBuildCheckChain */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtBuildPacket - build an RLMT packet
+ *
+ * Description:
+ *	This routine sets up an RLMT packet.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	NULL or pointer to RLMT mbuf
+ */
+RLMT_STATIC SK_MBUF	*SkRlmtBuildPacket(
+SK_AC		*pAC,		/* Adapter Context */
+SK_IOC		IoC,		/* I/O Context */
+SK_U32		PortNumber,	/* Sending port */
+SK_U16		PacketType,	/* RLMT packet type */
+SK_MAC_ADDR	*SrcAddr,	/* Source address */
+SK_MAC_ADDR	*DestAddr)	/* Destination address */
+{
+	int		i;
+	SK_U16		Length;
+	SK_MBUF		*pMb;
+	SK_RLMT_PACKET	*pPacket;
+
+#ifdef DEBUG
+	SK_U8	CheckSrc  = 0;
+	SK_U8	CheckDest = 0;
+	
+	for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {
+		CheckSrc  |= SrcAddr->a[i];
+		CheckDest |= DestAddr->a[i];
+	}
+
+	if ((CheckSrc == 0) || (CheckDest == 0)) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
+			("SkRlmtBuildPacket: Invalid %s%saddr.\n",
+			 (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")));
+	}
+#endif
+
+	if (pAC->Rlmt.RlmtOff) {
+		/* When RLMT is off we do not want to send RLMT packets */
+		return(NULL);
+	}
+
+	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) {
+		pPacket = (SK_RLMT_PACKET*)pMb->pData;
+		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+			pPacket->DstAddr[i] = DestAddr->a[i];
+			pPacket->SrcAddr[i] = SrcAddr->a[i];
+		}
+		pPacket->DSap = SK_RLMT_DSAP;
+		pPacket->SSap = SK_RLMT_SSAP;
+		pPacket->Ctrl = SK_RLMT_CTRL;
+		pPacket->Indicator[0] = SK_RLMT_INDICATOR0;
+		pPacket->Indicator[1] = SK_RLMT_INDICATOR1;
+		pPacket->Indicator[2] = SK_RLMT_INDICATOR2;
+		pPacket->Indicator[3] = SK_RLMT_INDICATOR3;
+		pPacket->Indicator[4] = SK_RLMT_INDICATOR4;
+		pPacket->Indicator[5] = SK_RLMT_INDICATOR5;
+		pPacket->Indicator[6] = SK_RLMT_INDICATOR6;
+
+		SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]);
+
+		for (i = 0; i < 4; i++) {
+			pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i];
+		}
+		
+		SK_U16_TO_NETWORK_ORDER(
+			SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]);
+
+		for (i = 0; i < SK_PACKET_DATA_LEN; i++) {
+			pPacket->Data[i] = 0x00;
+		}
+
+		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
+		pMb->Length = Length;
+		pMb->PortIdx = PortNumber;
+		Length -= 14;
+		SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);
+
+		if (PacketType == SK_PACKET_ALIVE) {
+			pAC->Rlmt.Port[PortNumber].TxHelloCts++;
+		}
+	}
+
+	return (pMb);
+}	/* SkRlmtBuildPacket */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtBuildSpanningTreePacket - build spanning tree check packet
+ *
+ * Description:
+ *	This routine sets up a BPDU packet for spanning tree check.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	NULL or pointer to RLMT mbuf
+ */
+RLMT_STATIC SK_MBUF	*SkRlmtBuildSpanningTreePacket(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	PortNumber)	/* Sending port */
+{
+	unsigned			i;
+	SK_U16				Length;
+	SK_MBUF				*pMb;
+	SK_SPTREE_PACKET	*pSPacket;
+
+	if (pAC->Rlmt.RlmtOff) {
+		/* When RLMT is off we do not want to send RLMT packets */
+		return(NULL);
+	}
+
+	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=
+		NULL) {
+		pSPacket = (SK_SPTREE_PACKET*)pMb->pData;
+		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+			pSPacket->DstAddr[i] = BridgeMcAddr.a[i];
+			pSPacket->SrcAddr[i] =
+				pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
+		}
+		pSPacket->DSap = SK_RLMT_SPT_DSAP;
+		pSPacket->SSap = SK_RLMT_SPT_SSAP;
+		pSPacket->Ctrl = SK_RLMT_SPT_CTRL;
+
+		pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;
+		pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;
+		pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;
+		pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;
+		pSPacket->Flags = SK_RLMT_SPT_FLAGS;
+		pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;
+		pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;
+		pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;
+		pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;
+		pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;
+		pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;
+		pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;
+		pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;
+
+		/*
+		 * Use logical MAC address as bridge ID and filter these packets
+		 * on receive.
+		 */
+		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+			pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =
+				pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber].
+					CurrentMacAddress.a[i];
+		}
+		pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;
+		pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;
+		pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;
+		pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;
+		pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;
+		pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;
+		pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;
+		pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;
+		pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;
+		pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;
+
+		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
+		pMb->Length = Length;
+		pMb->PortIdx = PortNumber;
+		Length -= 14;
+		SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);
+
+		pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++;
+	}
+
+	return (pMb);
+}	/* SkRlmtBuildSpanningTreePacket */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtSend - build and send check packets
+ *
+ * Description:
+ *	Depending on the RLMT state and the checking state, several packets
+ *	are sent through the indicated port.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	Nothing.
+ */
+RLMT_STATIC void	SkRlmtSend(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	PortNumber)	/* Sending port */
+{
+	unsigned	j;
+	SK_EVPARA	Para;
+	SK_RLMT_PORT	*pRPort;
+
+	pRPort = &pAC->Rlmt.Port[PortNumber];
+	if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
+		if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {
+			/* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
+			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+				&SkRlmtMcAddr)) != NULL) {
+				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+			}
+		}
+		else {
+			/*
+			 * Send a directed RLMT packet to all ports that are
+			 * checked by the indicated port.
+			 */
+			for (j = 0; j < pRPort->PortsChecked; j++) {
+				if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+					SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+					&pRPort->PortCheck[j].CheckAddr)) != NULL) {
+					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+				}
+			}
+		}
+	}
+
+	if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
+		(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) {
+		/*
+		 * Send a BPDU packet to make a connected switch tell us
+		 * the correct root bridge.
+		 */
+		if ((Para.pParaPtr =
+			SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) {
+			pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG;
+			pRPort->RootIdSet = SK_FALSE;
+
+			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
+				("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber));
+		}
+	}
+	return;
+}	/* SkRlmtSend */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtPortReceives - check if port is (going) down and bring it up
+ *
+ * Description:
+ *	This routine checks if a port who received a non-BPDU packet
+ *	needs to go up or needs to be stopped going down.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	Nothing.
+ */
+RLMT_STATIC void	SkRlmtPortReceives(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+SK_U32	PortNumber)		/* Port to check */
+{
+	SK_RLMT_PORT	*pRPort;
+	SK_EVPARA		Para;
+
+	pRPort = &pAC->Rlmt.Port[PortNumber];
+	pRPort->PortNoRx = SK_FALSE;
+
+	if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
+		!(pRPort->CheckingState & SK_RLMT_PCS_TX)) {
+		/*
+		 * Port is marked down (rx), but received a non-BPDU packet.
+		 * Bring it up.
+		 */
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+			("SkRlmtPacketReceive: Received on PortDown.\n"));
+
+		pRPort->PortState = SK_RLMT_PS_GOING_UP;
+		pRPort->GuTimeStamp = SkOsGetTime(pAC);
+		Para.Para32[0] = PortNumber;
+		Para.Para32[1] = (SK_U32)-1;
+		SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
+			SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para);
+		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
+		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
+		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+	}	/* PortDown && !SuspectTx */
+	else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+			("SkRlmtPacketReceive: Stop bringing port down.\n"));
+		SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
+		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
+		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+	}	/* PortGoingDown */
+
+	return;
+}	/* SkRlmtPortReceives */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtPacketReceive - receive a packet for closer examination
+ *
+ * Description:
+ *	This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	Nothing.
+ */
+RLMT_STATIC void	SkRlmtPacketReceive(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+SK_MBUF	*pMb)	/* Received packet */
+{
+#ifdef xDEBUG
+	extern	void DumpData(char *p, int size);
+#endif	/* DEBUG */
+	int					i;
+	unsigned			j;
+	SK_U16				PacketType;
+	SK_U32				PortNumber;
+	SK_ADDR_PORT		*pAPort;
+	SK_RLMT_PORT		*pRPort;
+	SK_RLMT_PACKET		*pRPacket;
+	SK_SPTREE_PACKET	*pSPacket;
+	SK_EVPARA			Para;
+
+	PortNumber	= pMb->PortIdx;
+	pAPort = &pAC->Addr.Port[PortNumber];
+	pRPort = &pAC->Rlmt.Port[PortNumber];
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+		("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber));
+
+	pRPacket = (SK_RLMT_PACKET*)pMb->pData;
+	pSPacket = (SK_SPTREE_PACKET*)pRPacket;
+
+#ifdef xDEBUG
+	DumpData((char *)pRPacket, 32);
+#endif	/* DEBUG */
+	if (pAC->Rlmt.RlmtOff) {
+		/* When RLMT is off we should not get any RLMT packets */
+		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+		return;
+	}
+	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) {
+		SkRlmtPortReceives(pAC, IoC, PortNumber);
+	}
+	
+	/* Check destination address. */
+
+	if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) &&
+		!SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) &&
+		!SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) {
+
+		/* Not sent to current MAC or registered MC address => Trash it. */
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+			("SkRlmtPacketReceive: Not for me.\n"));
+
+		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+		return;
+	}
+	else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) {
+
+		/*
+		 * Was sent by same port (may happen during port switching
+		 * or in case of duplicate MAC addresses).
+		 */
+
+		/*
+		 * Check for duplicate address here:
+		 * If Packet.Random != My.Random => DupAddr.
+		 */
+		for (i = 3; i >= 0; i--) {
+			if (pRPort->Random[i] != pRPacket->Random[i]) {
+				break;
+			}
+		}
+
+		/*
+		 * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
+		 * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
+		 * pRPacket->SSap).
+		 */
+		if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP &&
+			pRPacket->Ctrl == SK_RLMT_CTRL &&
+			pRPacket->SSap == SK_RLMT_SSAP &&
+			pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
+			pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
+			pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
+			pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
+			pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
+			pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
+			pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+				("SkRlmtPacketReceive: Duplicate MAC Address.\n"));
+
+			/* Error Log entry. */
+			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
+		}
+		else {
+			/* Simply trash it. */
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+				("SkRlmtPacketReceive: Sent by me.\n"));
+		}
+
+		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+		return;
+	}
+
+	/* Check SuspectTx entries. */
+	if (pRPort->PortsSuspect > 0) {
+		for (j = 0; j < pRPort->PortsChecked; j++) {
+			if (pRPort->PortCheck[j].SuspectTx &&
+				SK_ADDR_EQUAL(
+					pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) {
+				pRPort->PortCheck[j].SuspectTx = SK_FALSE;
+				pRPort->PortsSuspect--;
+				break;
+			}
+		}
+	}
+
+	/* Determine type of packet. */
+	if (pRPacket->DSap == SK_RLMT_DSAP &&
+		pRPacket->Ctrl == SK_RLMT_CTRL &&
+		(pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP &&
+		pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
+		pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
+		pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
+		pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
+		pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
+		pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
+		pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
+
+		/* It's an RLMT packet. */
+		PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) |
+			pRPacket->RlmtPacketType[1]);
+
+		switch (PacketType) {
+		case SK_PACKET_ANNOUNCE:	/* Not yet used. */
+#if 0
+			/* Build the check chain. */
+			SkRlmtBuildCheckChain(pAC);
+#endif	/* 0 */
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+				("SkRlmtPacketReceive: Announce.\n"));
+
+			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+			break;
+
+		case SK_PACKET_ALIVE:
+			if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+					("SkRlmtPacketReceive: Alive Reply.\n"));
+
+				if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
+					SK_ADDR_EQUAL(
+						pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) {
+					/* Obviously we could send something. */
+					if (pRPort->CheckingState & SK_RLMT_PCS_TX) {
+						pRPort->CheckingState &=  ~SK_RLMT_PCS_TX;
+						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+					}
+
+					if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
+						!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
+						pRPort->PortState = SK_RLMT_PS_GOING_UP;
+						pRPort->GuTimeStamp = SkOsGetTime(pAC);
+
+						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+
+						Para.Para32[0] = PortNumber;
+						Para.Para32[1] = (SK_U32)-1;
+						SkTimerStart(pAC, IoC, &pRPort->UpTimer,
+							SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT,
+							SK_RLMT_PORTUP_TIM, Para);
+					}
+				}
+
+				/* Mark sending port as alive? */
+				SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+			}
+			else {	/* Alive Request Packet. */
+				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+					("SkRlmtPacketReceive: Alive Request.\n"));
+
+				pRPort->RxHelloCts++;
+
+				/* Answer. */
+				for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+					pRPacket->DstAddr[i] = pRPacket->SrcAddr[i];
+					pRPacket->SrcAddr[i] =
+						pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
+				}
+				pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT;
+
+				Para.pParaPtr = pMb;
+				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+			}
+			break;
+
+		case SK_PACKET_CHECK_TX:
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+				("SkRlmtPacketReceive: Check your tx line.\n"));
+
+			/* A port checking us requests us to check our tx line. */
+			pRPort->CheckingState |= SK_RLMT_PCS_TX;
+
+			/* Start PortDownTx timer. */
+			Para.Para32[0] = PortNumber;
+			Para.Para32[1] = (SK_U32)-1;
+			SkTimerStart(pAC, IoC, &pRPort->DownTxTimer,
+				SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
+				SK_RLMT_PORTDOWN_TX_TIM, Para);
+
+			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+
+			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+				&SkRlmtMcAddr)) != NULL) {
+				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+			}
+			break;
+
+		case SK_PACKET_ADDR_CHANGED:
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+				("SkRlmtPacketReceive: Address Change.\n"));
+
+			/* Build the check chain. */
+			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+			break;
+
+		default:
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+				("SkRlmtPacketReceive: Unknown RLMT packet.\n"));
+
+			/* RA;:;: ??? */
+			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+		}
+	}
+	else if (pSPacket->DSap == SK_RLMT_SPT_DSAP &&
+		pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
+		(pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+			("SkRlmtPacketReceive: BPDU Packet.\n"));
+
+		/* Spanning Tree packet. */
+		pRPort->RxSpHelloCts++;
+
+		if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt.
+			Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) {
+			/*
+			 * Check segmentation if a new root bridge is set and
+			 * the segmentation check is not currently running.
+			 */
+			if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) &&
+				(pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
+				(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG)
+				!= 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState &
+				SK_RLMT_RCS_SEG) == 0) {
+				pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
+					SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
+			}
+
+			/* Store tree view of this port. */
+			for (i = 0; i < 8; i++) {
+				pRPort->Root.Id[i] = pSPacket->RootId[i];
+			}
+			pRPort->RootIdSet = SK_TRUE;
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
+				("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+					PortNumber,
+					pRPort->Root.Id[0], pRPort->Root.Id[1],
+					pRPort->Root.Id[2], pRPort->Root.Id[3],
+					pRPort->Root.Id[4], pRPort->Root.Id[5],
+					pRPort->Root.Id[6], pRPort->Root.Id[7]));
+		}
+
+		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+		if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState &
+			SK_RLMT_RCS_REPORT_SEG) != 0) {
+			SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber);
+		}
+	}
+	else {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+			("SkRlmtPacketReceive: Unknown Packet Type.\n"));
+
+		/* Unknown packet. */
+		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+	}
+	return;
+}	/* SkRlmtPacketReceive */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtCheckPort - check if a port works
+ *
+ * Description:
+ *	This routine checks if a port whose link is up received something
+ *	and if it seems to transmit successfully.
+ *
+ *	# PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
+ *	# PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
+ *	# RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
+ *
+ *	if (Rx - RxBpdu == 0) {	# No rx.
+ *		if (state == PsUp) {
+ *			PortCheckingState |= ChkRx
+ *		}
+ *		if (ModeCheckSeg && (Timeout ==
+ *			TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
+ *			RlmtCheckingState |= ChkSeg)
+ *			PortCheckingState |= ChkSeg
+ *		}
+ *		NewTimeout = TO_SHORTEN(Timeout)
+ *		if (NewTimeout < RLMT_MIN_TIMEOUT) {
+ *			NewTimeout = RLMT_MIN_TIMEOUT
+ *			PortState = PsDown
+ *			...
+ *		}
+ *	}
+ *	else {	# something was received
+ *		# Set counter to 0 at LinkDown?
+ *		#   No - rx may be reported after LinkDown ???
+ *		PortCheckingState &= ~ChkRx
+ *		NewTimeout = RLMT_DEFAULT_TIMEOUT
+ *		if (RxAck == 0) {
+ *			possible reasons:
+ *			is my tx line bad? --
+ *				send RLMT multicast and report
+ *				back internally? (only possible
+ *				between ports on same adapter)
+ *		}
+ *		if (RxChk == 0) {
+ *			possible reasons:
+ *			- tx line of port set to check me
+ *			  maybe bad
+ *			- no other port/adapter available or set
+ *			  to check me
+ *			- adapter checking me has a longer
+ *			  timeout
+ *			??? anything that can be done here?
+ *		}
+ *	}
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	New timeout value.
+ */
+RLMT_STATIC SK_U32	SkRlmtCheckPort(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	PortNumber)	/* Port to check */
+{
+	unsigned		i;
+	SK_U32			NewTimeout;
+	SK_RLMT_PORT	*pRPort;
+	SK_EVPARA		Para;
+
+	pRPort = &pAC->Rlmt.Port[PortNumber];
+
+	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
+				PortNumber, pRPort->PacketsPerTimeSlot));
+
+		/*
+		 * Check segmentation if there was no receive at least twice
+		 * in a row (PortNoRx is already set) and the segmentation
+		 * check is not currently running.
+		 */
+
+		if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
+			(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
+			!(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) {
+			pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
+				SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
+		}
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
+				pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX));
+
+		if (pRPort->PortState != SK_RLMT_PS_DOWN) {
+			NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
+			if (NewTimeout < SK_RLMT_MIN_TO_VAL) {
+				NewTimeout = SK_RLMT_MIN_TO_VAL;
+			}
+
+			if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
+				Para.Para32[0] = PortNumber;
+				pRPort->CheckingState |= SK_RLMT_PCS_RX;
+
+				/*
+				 * What shall we do if the port checked by this one receives
+				 * our request frames?  What's bad - our rx line or his tx line?
+				 */
+				Para.Para32[1] = (SK_U32)-1;
+				SkTimerStart(pAC, IoC, &pRPort->DownRxTimer,
+					SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
+					SK_RLMT_PORTDOWN_RX_TIM, Para);
+
+				for (i = 0; i < pRPort->PortsChecked; i++) {
+					if (pRPort->PortCheck[i].SuspectTx) {
+						continue;
+					}
+					pRPort->PortCheck[i].SuspectTx = SK_TRUE;
+					pRPort->PortsSuspect++;
+					if ((Para.pParaPtr =
+						SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX,
+							&pAC->Addr.Port[PortNumber].CurrentMacAddress,
+							&pRPort->PortCheck[i].CheckAddr)) != NULL) {
+						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+					}
+				}
+			}
+		}
+		else {	/* PortDown -- or all partners suspect. */
+			NewTimeout = SK_RLMT_DEF_TO_VAL;
+		}
+		pRPort->PortNoRx = SK_TRUE;
+	}
+	else {	/* A non-BPDU packet was received. */
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
+				PortNumber,
+				pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
+				pRPort->PacketsPerTimeSlot));
+		
+		SkRlmtPortReceives(pAC, IoC, PortNumber);
+		if (pAC->Rlmt.CheckSwitch) {
+			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+		}
+
+		NewTimeout = SK_RLMT_DEF_TO_VAL;
+	}
+
+	return (NewTimeout);
+}	/* SkRlmtCheckPort */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
+ *
+ * Description:
+ *	This routine selects the port that received a broadcast frame
+ *	substantially later than all other ports.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	SK_BOOL
+ */
+RLMT_STATIC SK_BOOL	SkRlmtSelectBcRx(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	Active,		/* Active port */
+SK_U32	PrefPort,	/* Preferred port */
+SK_U32	*pSelect)	/* New active port */
+{
+	SK_U64		BcTimeStamp;
+	SK_U32		i;
+	SK_BOOL		PortFound;
+
+	BcTimeStamp = 0;	/* Not totally necessary, but feeling better. */
+	PortFound = SK_FALSE;
+	
+	/* Select port with the latest TimeStamp. */
+	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
+				i,
+   				pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
+				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
+				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)));
+
+		if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
+			if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
+				BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp;
+				*pSelect = i;
+				PortFound = SK_TRUE;
+			}
+		}
+	}
+
+	if (PortFound) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Port %d received the last broadcast.\n", *pSelect));
+
+		/* Look if another port's time stamp is similar. */
+		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+			if (i == *pSelect) {
+				continue;
+			}
+			if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx &&
+				(pAC->Rlmt.Port[i].BcTimeStamp >
+				 BcTimeStamp - SK_RLMT_BC_DELTA ||
+				pAC->Rlmt.Port[i].BcTimeStamp +
+				 SK_RLMT_BC_DELTA > BcTimeStamp)) {
+				PortFound = SK_FALSE;
+				
+				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+					("Port %d received a broadcast at a similar time.\n", i));
+				break;
+			}
+		}
+	}
+
+#ifdef DEBUG
+	if (PortFound) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
+			 "latest broadcast (%u).\n",
+				*pSelect,
+				BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp));
+	}
+#endif	/* DEBUG */
+
+	return (PortFound);
+}	/* SkRlmtSelectBcRx */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
+ *
+ * Description:
+ *	This routine selects a good port (it is PortUp && !SuspectRx).
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	SK_BOOL
+ */
+RLMT_STATIC SK_BOOL	SkRlmtSelectNotSuspect(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	Active,		/* Active port */
+SK_U32	PrefPort,	/* Preferred port */
+SK_U32	*pSelect)	/* New active port */
+{
+	SK_U32		i;
+	SK_BOOL		PortFound;
+
+	PortFound = SK_FALSE;
+
+	/* Select first port that is PortUp && !SuspectRx. */
+	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+		if (!pAC->Rlmt.Port[i].PortDown &&
+			!(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) {
+			*pSelect = i;
+			if (!pAC->Rlmt.Port[Active].PortDown &&
+				!(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) {
+				*pSelect = Active;
+			}
+			if (!pAC->Rlmt.Port[PrefPort].PortDown &&
+				!(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) {
+				*pSelect = PrefPort;
+			}
+			PortFound = SK_TRUE;
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+				("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
+					*pSelect));
+			break;
+		}
+	}
+	return (PortFound);
+}	/* SkRlmtSelectNotSuspect */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
+ *
+ * Description:
+ *	This routine selects a port that is up.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	SK_BOOL
+ */
+RLMT_STATIC SK_BOOL	SkRlmtSelectUp(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+SK_U32	Active,			/* Active port */
+SK_U32	PrefPort,		/* Preferred port */
+SK_U32	*pSelect,		/* New active port */
+SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
+{
+	SK_U32		i;
+	SK_BOOL		PortFound;
+
+	PortFound = SK_FALSE;
+
+	/* Select first port that is PortUp. */
+	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP &&
+			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+			*pSelect = i;
+			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP &&
+				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
+				*pSelect = Active;
+			}
+			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP &&
+				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
+				*pSelect = PrefPort;
+			}
+			PortFound = SK_TRUE;
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+				("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect));
+			break;
+		}
+	}
+	return (PortFound);
+}	/* SkRlmtSelectUp */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
+ *
+ * Description:
+ *	This routine selects the port that is going up for the longest time.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	SK_BOOL
+ */
+RLMT_STATIC SK_BOOL	SkRlmtSelectGoingUp(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+SK_U32	Active,			/* Active port */
+SK_U32	PrefPort,		/* Preferred port */
+SK_U32	*pSelect,		/* New active port */
+SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
+{
+	SK_U64		GuTimeStamp;
+	SK_U32		i;
+	SK_BOOL		PortFound;
+
+	GuTimeStamp = 0;
+	PortFound = SK_FALSE;
+
+	/* Select port that is PortGoingUp for the longest time. */
+	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
+			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
+			*pSelect = i;
+			PortFound = SK_TRUE;
+			break;
+		}
+	}
+
+	if (!PortFound) {
+		return (SK_FALSE);
+	}
+
+	for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
+			pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp &&
+			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
+			*pSelect = i;
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect));
+	return (SK_TRUE);
+}	/* SkRlmtSelectGoingUp */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
+ *
+ * Description:
+ *	This routine selects a port that is down.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	SK_BOOL
+ */
+RLMT_STATIC SK_BOOL	SkRlmtSelectDown(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+SK_U32	Active,			/* Active port */
+SK_U32	PrefPort,		/* Preferred port */
+SK_U32	*pSelect,		/* New active port */
+SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
+{
+	SK_U32		i;
+	SK_BOOL		PortFound;
+
+	PortFound = SK_FALSE;
+
+	/* Select first port that is PortDown. */
+	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN &&
+			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+			*pSelect = i;
+			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN &&
+				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
+				*pSelect = Active;
+			}
+			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN &&
+				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
+				*pSelect = PrefPort;
+			}
+			PortFound = SK_TRUE;
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+				("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect));
+			break;
+		}
+	}
+	return (PortFound);
+}	/* SkRlmtSelectDown */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtCheckSwitch - select new active port and switch to it
+ *
+ * Description:
+ *	This routine decides which port should be the active one and queues
+ *	port switching if necessary.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	Nothing.
+ */
+RLMT_STATIC void	SkRlmtCheckSwitch(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+SK_U32	NetIdx)	/* Net index */
+{
+	SK_EVPARA	Para;
+	SK_U32		Active;
+	SK_U32		PrefPort;
+	SK_U32		i;
+	SK_BOOL		PortFound;
+
+	Active = pAC->Rlmt.Net[NetIdx].ActivePort;	/* Index of active port. */
+	PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort;	/* Index of preferred port. */
+	PortFound = SK_FALSE;
+	pAC->Rlmt.CheckSwitch = SK_FALSE;
+
+#if 0	/* RW 2001/10/18 - active port becomes always prefered one */
+	if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */
+		/* disable auto-fail back */
+		PrefPort = Active;
+	}
+#endif
+
+	if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) {
+		/* Last link went down - shut down the net. */
+		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN;
+		Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP;
+		Para.Para32[1] = NetIdx;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para);
+
+		Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+			Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
+		Para.Para32[1] = NetIdx;
+		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
+		return;
+	}	/* pAC->Rlmt.LinksUp == 0 */
+	else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 &&
+		pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) {
+		/* First link came up - get the net up. */
+		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP;
+
+		/*
+		 * If pAC->Rlmt.ActivePort != Para.Para32[0],
+		 * the DRV switches to the port that came up.
+		 */
+		for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+			if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
+				if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) {
+					i = Active;
+				}
+				if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) {
+					i = PrefPort;
+				}
+				PortFound = SK_TRUE;
+				break;
+			}
+		}
+
+		if (PortFound) {
+			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
+			Para.Para32[1] = NetIdx;
+			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
+
+			pAC->Rlmt.Net[NetIdx].ActivePort = i;
+			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
+			Para.Para32[1] = NetIdx;
+			SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
+
+			if (pAC->Rlmt.NumNets == 1) {
+				if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+					(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
+					pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
+					SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
+					CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
+
+					/*
+					 * Send announce packet to RLMT multicast address to force
+					 * switches to learn the new location of the logical MAC address.
+					 */
+					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+				}
+			}
+		}
+		else {
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG);
+		}
+
+		return;
+	}	/* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
+	else {	/* Cannot be reached in dual-net mode. */
+		Para.Para32[0] = Active;
+
+		/*
+		 * Preselection:
+		 *	If RLMT Mode != CheckLinkState
+		 *		select port that received a broadcast frame substantially later
+		 *		than all other ports
+		 *	else select first port that is not SuspectRx
+		 *	else select first port that is PortUp
+		 *	else select port that is PortGoingUp for the longest time
+		 *	else select first port that is PortDown
+		 *	else stop.
+		 *
+		 * For the preselected port:
+		 *	If ActivePort is equal in quality, select ActivePort.
+		 *
+		 *	If PrefPort is equal in quality, select PrefPort.
+		 *
+		 *	If ActivePort != SelectedPort,
+		 *		If old ActivePort is LinkDown,
+		 *			SwitchHard
+		 *		else
+		 *			SwitchSoft
+		 */
+		/* check of ChgBcPrio flag added */
+		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
+			(!pAC->Rlmt.Net[0].ChgBcPrio)) {
+			
+			if (!PortFound) {
+				PortFound = SkRlmtSelectBcRx(
+					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+			}
+
+			if (!PortFound) {
+				PortFound = SkRlmtSelectNotSuspect(
+					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+			}
+		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+
+		/* with changed priority for last broadcast received */
+		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
+			(pAC->Rlmt.Net[0].ChgBcPrio)) {
+			if (!PortFound) {
+				PortFound = SkRlmtSelectNotSuspect(
+					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+			}
+
+			if (!PortFound) {
+				PortFound = SkRlmtSelectBcRx(
+					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+			}
+		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+
+		if (!PortFound) {
+			PortFound = SkRlmtSelectUp(
+				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+		}
+
+		if (!PortFound) {
+			PortFound = SkRlmtSelectUp(
+				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+		}
+
+		if (!PortFound) {
+			PortFound = SkRlmtSelectGoingUp(
+				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+		}
+
+		if (!PortFound) {
+			PortFound = SkRlmtSelectGoingUp(
+				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+		}
+
+		if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) {
+			if (!PortFound) {
+				PortFound = SkRlmtSelectDown(pAC, IoC,
+					Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+			}
+
+			if (!PortFound) {
+				PortFound = SkRlmtSelectDown(pAC, IoC,
+					Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+			}
+		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+
+		if (PortFound) {
+
+			if (Para.Para32[1] != Active) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+					("Active: %d, Para1: %d.\n", Active, Para.Para32[1]));
+				pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
+				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+					Port[Para.Para32[0]]->PortNumber;
+				Para.Para32[1] = pAC->Rlmt.Net[NetIdx].
+					Port[Para.Para32[1]]->PortNumber;
+				SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE);
+				if (pAC->Rlmt.Port[Active].LinkDown) {
+					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para);
+				}
+				else {
+					SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
+					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para);
+				}
+				Para.Para32[1] = NetIdx;
+				Para.Para32[0] =
+					pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber;
+				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
+				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+					Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
+				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
+				if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+					(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0],
+					SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress,
+					&SkRlmtMcAddr)) != NULL) {
+					/*
+					 * Send announce packet to RLMT multicast address to force
+					 * switches to learn the new location of the logical
+					 * MAC address.
+					 */
+					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+				}	/* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
+			}	/* Para.Para32[1] != Active */
+		}	/* PortFound */
+		else {
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG);
+		}
+	}	/* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
+	return;
+}	/* SkRlmtCheckSwitch */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtCheckSeg - Report if segmentation is detected
+ *
+ * Description:
+ *	This routine checks if the ports see different root bridges and reports
+ *	segmentation in such a case.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	Nothing.
+ */
+RLMT_STATIC void	SkRlmtCheckSeg(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+SK_U32	NetIdx)	/* Net number */
+{
+	SK_EVPARA	Para;
+	SK_RLMT_NET	*pNet;
+	SK_U32		i, j;
+	SK_BOOL		Equal;
+
+	pNet = &pAC->Rlmt.Net[NetIdx];
+	pNet->RootIdSet = SK_FALSE;
+	Equal = SK_TRUE;
+
+	for (i = 0; i < pNet->NumPorts; i++) {
+		if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) {
+			continue;
+		}
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
+			("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i,
+				pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
+				pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
+				pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
+				pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]));
+
+		if (!pNet->RootIdSet) {
+			pNet->Root = pNet->Port[i]->Root;
+			pNet->RootIdSet = SK_TRUE;
+			continue;
+		}
+
+		for (j = 0; j < 8; j ++) {
+			Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j];
+			if (!Equal) {
+				break;
+			}
+		}
+		
+		if (!Equal) {
+			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);
+			Para.Para32[0] = NetIdx;
+			Para.Para32[1] = (SK_U32)-1;
+			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para);
+
+			pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG;
+
+			/* 2000-03-06 RA: New. */
+			Para.Para32[0] = NetIdx;
+			Para.Para32[1] = (SK_U32)-1;
+			SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL,
+				SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+			break;
+		}
+	}	/* for (i = 0; i < pNet->NumPorts; i++) */
+
+	/* 2000-03-06 RA: Moved here. */
+	/* Segmentation check not running anymore. */
+	pNet->CheckingState &= ~SK_RLMT_RCS_SEG;
+
+}	/* SkRlmtCheckSeg */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtPortStart - initialize port variables and start port
+ *
+ * Description:
+ *	This routine initializes a port's variables and issues a PORT_START
+ *	to the HWAC module.  This handles retries if the start fails or the
+ *	link eventually goes down.
+ *
+ * Context:
+ *	runtime, pageable?
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtPortStart(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	PortNumber)	/* Port number */
+{
+	SK_EVPARA	Para;
+
+	pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN;
+	pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE;
+	pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE;
+	pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE;
+	pAC->Rlmt.Port[PortNumber].CheckingState = 0;
+	pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
+	Para.Para32[0] = PortNumber;
+	Para.Para32[1] = (SK_U32)-1;
+	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+}	/* SkRlmtPortStart */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtPortStartTim - PORT_START_TIM
+ *
+ * Description:
+ *	This routine handles PORT_START_TIM events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtPortStartTim(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
+{
+	SK_U32			i;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]));
+
+		if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"));
+		return;
+	}
+
+	/*
+	 * Used to start non-preferred ports if the preferred one
+	 * does not come up.
+	 * This timeout needs only be set when starting the first
+	 * (preferred) port.
+	 */
+	if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
+		/* PORT_START failed. */
+		for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) {
+			if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) {
+				SkRlmtPortStart(pAC, IoC,
+					pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber);
+			}
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"));
+}	/* SkRlmtEvtPortStartTim */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtLinkUp - LINK_UP
+ *
+ * Description:
+ *	This routine handles LLINK_UP events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtLinkUp(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
+{
+	SK_U32			i;
+	SK_RLMT_PORT	*pRPort;
+	SK_EVPARA		Para2;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]));
+
+	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+	if (!pRPort->PortStarted) {
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+				("SK_RLMT_LINK_UP Event EMPTY.\n"));
+		return;
+	}
+
+	if (!pRPort->LinkDown) {
+		/* RA;:;: Any better solution? */
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_LINK_UP Event EMPTY.\n"));
+		return;
+	}
+
+	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
+	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+
+	/* Do something if timer already fired? */
+
+	pRPort->LinkDown = SK_FALSE;
+	pRPort->PortState = SK_RLMT_PS_GOING_UP;
+	pRPort->GuTimeStamp = SkOsGetTime(pAC);
+	pRPort->BcTimeStamp = 0;
+	pRPort->Net->LinksUp++;
+	if (pRPort->Net->LinksUp == 1) {
+		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE);
+	}
+	else {
+		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
+	}
+
+	for (i = 0; i < pRPort->Net->NumPorts; i++) {
+		if (!pRPort->Net->Port[i]->PortStarted) {
+			SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber);
+		}
+	}
+
+	SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+
+	if (pRPort->Net->LinksUp >= 2) {
+		if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
+			/* Build the check chain. */
+			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+		}
+	}
+
+	/* If the first link comes up, start the periodical RLMT timeout. */
+	if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 &&
+		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) {
+		Para2.Para32[0] = pRPort->Net->NetNumber;
+		Para2.Para32[1] = (SK_U32)-1;
+		SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer,
+			pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2);
+	}
+
+	Para2 = Para;
+	Para2.Para32[1] = (SK_U32)-1;
+	SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
+		SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
+
+	/* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
+	if (pAC->Rlmt.NumNets == 1) {
+		if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+			(pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
+			(Para2.pParaPtr =
+				SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
+				&pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
+			) != NULL) {
+
+			/* Send "new" packet to RLMT multicast address. */
+			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+		}
+	}
+
+	if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
+		if ((Para2.pParaPtr =
+			SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) {
+			pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE;
+			pRPort->Net->CheckingState |=
+				SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
+
+			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+
+			Para.Para32[1] = (SK_U32)-1;
+			SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer,
+				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_LINK_UP Event END.\n"));
+}	/* SkRlmtEvtLinkUp */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtPortUpTim - PORT_UP_TIM
+ *
+ * Description:
+ *	This routine handles PORT_UP_TIM events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtPortUpTim(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
+{
+	SK_RLMT_PORT	*pRPort;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_PORTUP_TIM Event EMPTY.\n"));
+		return;
+	}
+
+	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+	if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]));
+		return;
+	}
+
+	pRPort->PortDown = SK_FALSE;
+	pRPort->PortState = SK_RLMT_PS_UP;
+	pRPort->Net->PortsUp++;
+	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
+		if (pAC->Rlmt.NumNets <= 1) {
+			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+		}
+		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PORTUP_TIM Event END.\n"));
+}	/* SkRlmtEvtPortUpTim */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtPortDownTim - PORT_DOWN_*
+ *
+ * Description:
+ *	This routine handles PORT_DOWN_* events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtPortDownX(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_U32		Event,	/* Event code */
+SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
+{
+	SK_RLMT_PORT	*pRPort;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
+			Para.Para32[0], Event));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_PORTDOWN* Event EMPTY.\n"));
+		return;
+	}
+
+	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+	if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
+		!(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event));
+		return;
+	}
+	
+	/* Stop port's timers. */
+	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
+	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+
+	if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) {
+		pRPort->PortState = SK_RLMT_PS_DOWN;
+	}
+
+	if (!pRPort->PortDown) {
+		pRPort->Net->PortsUp--;
+		pRPort->PortDown = SK_TRUE;
+		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para);
+	}
+
+	pRPort->PacketsPerTimeSlot = 0;
+	/* pRPort->DataPacketsPerTimeSlot = 0; */
+	pRPort->BpduPacketsPerTimeSlot = 0;
+	pRPort->BcTimeStamp = 0;
+
+	/*
+	 * RA;:;: To be checked:
+	 * - actions at RLMT_STOP: We should not switch anymore.
+	 */
+	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
+		if (Para.Para32[0] ==
+			pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) {
+			/* Active Port went down. */
+			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event));
+}	/* SkRlmtEvtPortDownX */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtLinkDown - LINK_DOWN
+ *
+ * Description:
+ *	This routine handles LINK_DOWN events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtLinkDown(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
+{
+	SK_RLMT_PORT	*pRPort;
+
+	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]));
+
+	if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
+		pRPort->Net->LinksUp--;
+		pRPort->LinkDown = SK_TRUE;
+		pRPort->PortState = SK_RLMT_PS_LINK_DOWN;
+		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF);
+
+		if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) {
+			/* Build the check chain. */
+			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+		}
+
+		/* Ensure that port is marked down. */
+		Para.Para32[1] = -1;
+		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_LINK_DOWN Event END.\n"));
+}	/* SkRlmtEvtLinkDown */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtPortAddr - PORT_ADDR
+ *
+ * Description:
+ *	This routine handles PORT_ADDR events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtPortAddr(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
+{
+	SK_U32			i, j;
+	SK_RLMT_PORT	*pRPort;
+	SK_MAC_ADDR		*pOldMacAddr;
+	SK_MAC_ADDR		*pNewMacAddr;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_PORT_ADDR Event EMPTY.\n"));
+		return;
+	}
+
+	/* Port's physical MAC address changed. */
+	pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress;
+	pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress;
+
+	/*
+	 * NOTE: This is not scalable for solutions where ports are
+	 *	 checked remotely.  There, we need to send an RLMT
+	 *	 address change packet - and how do we ensure delivery?
+	 */
+	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+		pRPort = &pAC->Rlmt.Port[i];
+		for (j = 0; j < pRPort->PortsChecked; j++) {
+			if (SK_ADDR_EQUAL(
+				pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) {
+				pRPort->PortCheck[j].CheckAddr = *pNewMacAddr;
+			}
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_PORT_ADDR Event END.\n"));
+}	/* SkRlmtEvtPortAddr */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtStart - START
+ *
+ * Description:
+ *	This routine handles START events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtStart(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+{
+	SK_EVPARA	Para2;
+	SK_U32		PortIdx;
+	SK_U32		PortNumber;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_START Event EMPTY.\n"));
+		return;
+	}
+
+	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad NetNumber %d.\n", Para.Para32[0]));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_START Event EMPTY.\n"));
+		return;
+	}
+
+	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_START Event EMPTY.\n"));
+		return;
+	}
+
+	if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("All nets should have been started.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_START Event EMPTY.\n"));
+		return;
+	}
+
+	if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >=
+		pAC->Rlmt.Net[Para.Para32[0]].NumPorts) {
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG);
+
+		/* Change PrefPort to internal default. */
+		Para2.Para32[0] = 0xFFFFFFFF;
+		Para2.Para32[1] = Para.Para32[0];
+		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2);
+	}
+
+	PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort;
+	PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber;
+
+	pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0;
+	pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0;
+	pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0;
+	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN;
+
+	/* Start preferred port. */
+	SkRlmtPortStart(pAC, IoC, PortNumber);
+
+	/* Start Timer (for first port only). */
+	Para2.Para32[0] = PortNumber;
+	Para2.Para32[1] = (SK_U32)-1;
+	SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer,
+		SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2);
+
+	pAC->Rlmt.NetsStarted++;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_START Event END.\n"));
+}	/* SkRlmtEvtStart */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtStop - STOP
+ *
+ * Description:
+ *	This routine handles STOP events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtStop(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+{
+	SK_EVPARA	Para2;
+	SK_U32		PortNumber;
+	SK_U32		i;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_STOP Event EMPTY.\n"));
+		return;
+	}
+
+	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad NetNumber %d.\n", Para.Para32[0]));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_STOP Event EMPTY.\n"));
+		return;
+	}
+
+	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_STOP Event EMPTY.\n"));
+		return;
+	}
+
+	if (pAC->Rlmt.NetsStarted == 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("All nets are stopped.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_STOP Event EMPTY.\n"));
+		return;
+	}
+
+	/* Stop RLMT timers. */
+	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer);
+	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer);
+
+	/* Stop net. */
+	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT;
+	pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE;
+	Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
+	Para2.Para32[1] = Para.Para32[0];			/* Net# */
+	SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
+
+	/* Stop ports. */
+	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
+		if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) {
+			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer);
+			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer);
+			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer);
+
+			pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT;
+			pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
+			pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE;
+			Para2.Para32[0] = PortNumber;
+			Para2.Para32[1] = (SK_U32)-1;
+			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2);
+		}
+	}
+
+	pAC->Rlmt.NetsStarted--;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_STOP Event END.\n"));
+}	/* SkRlmtEvtStop */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtTim - TIM
+ *
+ * Description:
+ *	This routine handles TIM events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtTim(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+{
+	SK_RLMT_PORT	*pRPort;
+	SK_U32			Timeout;
+	SK_U32			NewTimeout;
+	SK_U32			PortNumber;
+	SK_U32			i;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_TIM Event BEGIN.\n"));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_TIM Event EMPTY.\n"));
+		return;
+	}
+
+	if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 ||
+		pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) {
+		/* Mode changed or all links down: No more link checking. */
+		return;
+	}
+
+#if 0
+	pAC->Rlmt.SwitchCheckCounter--;
+	if (pAC->Rlmt.SwitchCheckCounter == 0) {
+		pAC->Rlmt.SwitchCheckCounter;
+	}
+#endif	/* 0 */
+
+	NewTimeout = SK_RLMT_DEF_TO_VAL;
+	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
+		pRPort = &pAC->Rlmt.Port[PortNumber];
+		if (!pRPort->LinkDown) {
+			Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber);
+			if (Timeout < NewTimeout) {
+				NewTimeout = Timeout;
+			}
+
+			/*
+			 * These counters should be set to 0 for all ports before the
+			 * first frame is sent in the next loop.
+			 */
+			pRPort->PacketsPerTimeSlot = 0;
+			/* pRPort->DataPacketsPerTimeSlot = 0; */
+			pRPort->BpduPacketsPerTimeSlot = 0;
+		}
+	}
+	pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout;
+
+	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) {
+		/*
+		 * If checking remote ports, also send packets if
+		 *   (LinksUp == 1) &&
+		 *   this port checks at least one (remote) port.
+		 */
+
+		/*
+		 * Must be new loop, as SkRlmtCheckPort can request to
+		 * check segmentation when e.g. checking the last port.
+		 */
+		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+			if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) {
+				SkRlmtSend(pAC, IoC,
+					pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber);
+			}
+		}
+	}
+
+	SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer,
+		pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM,
+		Para);
+
+	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 &&
+		(pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) &&
+		(pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) {
+		SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer,
+			SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+		pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG;
+		pAC->Rlmt.Net[Para.Para32[0]].CheckingState |=
+			SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_TIM Event END.\n"));
+}	/* SkRlmtEvtTim */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtSegTim - SEG_TIM
+ *
+ * Description:
+ *	This routine handles SEG_TIM events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtSegTim(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+{
+#ifdef xDEBUG
+	int j;
+#endif	/* DEBUG */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_SEG_TIM Event BEGIN.\n"));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_SEG_TIM Event EMPTY.\n"));
+		return;
+	}
+
+#ifdef xDEBUG
+	for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) {
+		SK_ADDR_PORT	*pAPort;
+		SK_U32			k;
+		SK_U16			*InAddr;
+		SK_U8			InAddr8[6];
+
+		InAddr = (SK_U16 *)&InAddr8[0];
+		pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort;
+		for (k = 0; k < pAPort->NextExactMatchRlmt; k++) {
+			/* Get exact match address k from port j. */
+			XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
+				XM_EXM(k), InAddr);
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+				("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x --  %02x %02x %02x %02x %02x %02x.\n",
+					k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
+					InAddr8[0], InAddr8[1], InAddr8[2],
+					InAddr8[3], InAddr8[4], InAddr8[5],
+					pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
+					pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
+					pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]));
+		}
+	}
+#endif	/* xDEBUG */
+				
+	SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_SEG_TIM Event END.\n"));
+}	/* SkRlmtEvtSegTim */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtPacketRx - PACKET_RECEIVED
+ *
+ * Description:
+ *	This routine handles PACKET_RECEIVED events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtPacketRx(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_MBUF *pMb */
+{
+	SK_MBUF	*pMb;
+	SK_MBUF	*pNextMb;
+	SK_U32	NetNumber;
+
+	
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"));
+
+	/* Should we ignore frames during port switching? */
+
+#ifdef DEBUG
+	pMb = Para.pParaPtr;
+	if (pMb == NULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"));
+	}
+	else if (pMb->pNext != NULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("More than one mbuf or pMb->pNext not set.\n"));
+	}
+#endif	/* DEBUG */
+
+	for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) {
+		pNextMb = pMb->pNext;
+		pMb->pNext = NULL;
+
+		NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber;
+		if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) {
+			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+		}
+		else {
+			SkRlmtPacketReceive(pAC, IoC, pMb);
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PACKET_RECEIVED Event END.\n"));
+}	/* SkRlmtEvtPacketRx */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtStatsClear - STATS_CLEAR
+ *
+ * Description:
+ *	This routine handles STATS_CLEAR events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtStatsClear(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+{
+	SK_U32			i;
+	SK_RLMT_PORT	*pRPort;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_STATS_CLEAR Event BEGIN.\n"));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"));
+		return;
+	}
+
+	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad NetNumber %d.\n", Para.Para32[0]));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"));
+		return;
+	}
+
+	/* Clear statistics for logical and physical ports. */
+	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+		pRPort =
+			&pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber];
+		pRPort->TxHelloCts = 0;
+		pRPort->RxHelloCts = 0;
+		pRPort->TxSpHelloReqCts = 0;
+		pRPort->RxSpHelloCts = 0;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_STATS_CLEAR Event END.\n"));
+}	/* SkRlmtEvtStatsClear */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtStatsUpdate - STATS_UPDATE
+ *
+ * Description:
+ *	This routine handles STATS_UPDATE events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtStatsUpdate(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_STATS_UPDATE Event BEGIN.\n"));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"));
+		return;
+	}
+
+	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad NetNumber %d.\n", Para.Para32[0]));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"));
+		return;
+	}
+
+	/* Update statistics - currently always up-to-date. */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_STATS_UPDATE Event END.\n"));
+}	/* SkRlmtEvtStatsUpdate */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtPrefportChange - PREFPORT_CHANGE
+ *
+ * Description:
+ *	This routine handles PREFPORT_CHANGE events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtPrefportChange(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 PortIndex; SK_U32 NetNumber */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]));
+
+	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad NetNumber %d.\n", Para.Para32[1]));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"));
+		return;
+	}
+
+	/* 0xFFFFFFFF == auto-mode. */
+	if (Para.Para32[0] == 0xFFFFFFFF) {
+		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT;
+	}
+	else {
+		if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) {
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+				("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"));
+			return;
+		}
+
+		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0];
+	}
+
+	pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0];
+
+	if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
+		SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_PREFPORT_CHANGE Event END.\n"));
+}	/* SkRlmtEvtPrefportChange */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtSetNets - SET_NETS
+ *
+ * Description:
+ *	This routine handles SET_NETS events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtSetNets(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 NumNets; SK_U32 -1 */
+{
+	int i;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_SET_NETS Event BEGIN.\n"));
+
+	if (Para.Para32[1] != (SK_U32)-1) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad Parameter.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_SET_NETS Event EMPTY.\n"));
+		return;
+	}
+
+	if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
+		Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad number of nets: %d.\n", Para.Para32[0]));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_SET_NETS Event EMPTY.\n"));
+		return;
+	}
+
+	if (Para.Para32[0] == pAC->Rlmt.NumNets) {	/* No change. */
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_SET_NETS Event EMPTY.\n"));
+		return;
+	}
+
+	/* Entering and leaving dual mode only allowed while nets are stopped. */
+	if (pAC->Rlmt.NetsStarted > 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Changing dual mode only allowed while all nets are stopped.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_SET_NETS Event EMPTY.\n"));
+		return;
+	}
+
+	if (Para.Para32[0] == 1) {
+		if (pAC->Rlmt.NumNets > 1) {
+			/* Clear logical MAC addr from second net's active port. */
+			(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
+				Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL);
+			pAC->Rlmt.Net[1].NumPorts = 0;
+		}
+
+		pAC->Rlmt.NumNets = Para.Para32[0];
+		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
+			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
+			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+			/* Just assuming. */
+			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+			pAC->Rlmt.Net[i].NetNumber = i;
+		}
+
+		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0];
+		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
+
+		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("RLMT: Changed to one net with two ports.\n"));
+	}
+	else if (Para.Para32[0] == 2) {
+		/* Turn off RLMT when dual net mode is used */
+		pAC->Rlmt.RlmtOff = SK_TRUE;
+		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
+		pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
+		pAC->Rlmt.Net[0].NumPorts =
+			pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts;
+		
+		pAC->Rlmt.NumNets = Para.Para32[0];
+		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
+			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
+			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+			/* Just assuming. */
+			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+
+			pAC->Rlmt.Net[i].NetNumber = i;
+		}
+
+		/* Set logical MAC addr on second net's active port. */
+		(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
+			Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL);
+
+		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("RLMT: Changed to two nets with one port each.\n"));
+	}
+	else {
+		/* Not implemented for more than two nets. */
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SetNets not implemented for more than two nets.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_SET_NETS Event EMPTY.\n"));
+		return;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_SET_NETS Event END.\n"));
+}	/* SkRlmtSetNets */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvtModeChange - MODE_CHANGE
+ *
+ * Description:
+ *	This routine handles MODE_CHANGE events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	Nothing
+ */
+RLMT_STATIC void	SkRlmtEvtModeChange(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_EVPARA	Para)	/* SK_U32 NewMode; SK_U32 NetNumber */
+{
+	SK_EVPARA	Para2;
+	SK_U32		i;
+	SK_U32		PrevRlmtMode;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+		("SK_RLMT_MODE_CHANGE Event BEGIN.\n"));
+
+	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Bad NetNumber %d.\n", Para.Para32[1]));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"));
+		return;
+	}
+
+	Para.Para32[0] |= SK_RLMT_CHECK_LINK;
+
+	if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) &&
+		Para.Para32[0] != SK_RLMT_MODE_CLS) {
+		pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Forced RLMT mode to CLS on single port net.\n"));
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"));
+		return;
+	}
+
+	/* Update RLMT mode. */
+	PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode;
+	pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0];
+
+	if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) !=
+		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
+		/* SK_RLMT_CHECK_LOC_LINK bit changed. */
+		if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 &&
+			pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 &&
+			pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) {
+			/* 20001207 RA: Was "PortsUp == 1". */
+			Para2.Para32[0] = Para.Para32[1];
+			Para2.Para32[1] = (SK_U32)-1;
+			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer,
+				pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue,
+				SKGE_RLMT, SK_RLMT_TIM, Para2);
+		}
+	}
+
+	if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) !=
+		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) {
+		/* SK_RLMT_CHECK_SEG bit changed. */
+		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) {
+			(void)SkAddrMcClear(pAC, IoC,
+				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+				SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
+
+			/* Add RLMT MC address. */
+			(void)SkAddrMcAdd(pAC, IoC,
+				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+				&SkRlmtMcAddr, SK_ADDR_PERMANENT);
+
+			if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode &
+				SK_RLMT_CHECK_SEG) != 0) {
+				/* Add BPDU MC address. */
+				(void)SkAddrMcAdd(pAC, IoC,
+					pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+					&BridgeMcAddr, SK_ADDR_PERMANENT);
+
+				if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
+					if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown &&
+						(Para2.pParaPtr = SkRlmtBuildSpanningTreePacket(
+						pAC, IoC, i)) != NULL) {
+						pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet =
+							SK_FALSE;
+						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+					}
+				}
+			}
+			(void)SkAddrMcUpdate(pAC, IoC,
+				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber);
+		}	/* for ... */
+
+		if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) {
+			Para2.Para32[0] = Para.Para32[1];
+			Para2.Para32[1] = (SK_U32)-1;
+			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer,
+				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2);
+		}
+	}	/* SK_RLMT_CHECK_SEG bit changed. */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("SK_RLMT_MODE_CHANGE Event END.\n"));
+}	/* SkRlmtEvtModeChange */
+
+
+/******************************************************************************
+ *
+ *	SkRlmtEvent - a PORT- or an RLMT-specific event happened
+ *
+ * Description:
+ *	This routine calls subroutines to handle PORT- and RLMT-specific events.
+ *
+ * Context:
+ *	runtime, pageable?
+ *	may be called after SK_INIT_IO
+ *
+ * Returns:
+ *	0
+ */
+int	SkRlmtEvent(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_U32		Event,	/* Event code */
+SK_EVPARA	Para)	/* Event-specific parameter */
+{
+	switch (Event) {
+	
+	/* ----- PORT events ----- */
+
+	case SK_RLMT_PORTSTART_TIM:	/* From RLMT via TIME. */
+		SkRlmtEvtPortStartTim(pAC, IoC, Para);
+		break;
+	case SK_RLMT_LINK_UP:		/* From SIRQ. */
+		SkRlmtEvtLinkUp(pAC, IoC, Para);
+		break;
+	case SK_RLMT_PORTUP_TIM:	/* From RLMT via TIME. */
+		SkRlmtEvtPortUpTim(pAC, IoC, Para);
+		break;
+	case SK_RLMT_PORTDOWN:			/* From RLMT. */
+	case SK_RLMT_PORTDOWN_RX_TIM:	/* From RLMT via TIME. */
+	case SK_RLMT_PORTDOWN_TX_TIM:	/* From RLMT via TIME. */
+		SkRlmtEvtPortDownX(pAC, IoC, Event, Para);
+		break;
+	case SK_RLMT_LINK_DOWN:		/* From SIRQ. */
+		SkRlmtEvtLinkDown(pAC, IoC, Para);
+		break;
+	case SK_RLMT_PORT_ADDR:		/* From ADDR. */
+		SkRlmtEvtPortAddr(pAC, IoC, Para);
+		break;
+
+	/* ----- RLMT events ----- */
+
+	case SK_RLMT_START:		/* From DRV. */
+		SkRlmtEvtStart(pAC, IoC, Para);
+		break;
+	case SK_RLMT_STOP:		/* From DRV. */
+		SkRlmtEvtStop(pAC, IoC, Para);
+		break;
+	case SK_RLMT_TIM:		/* From RLMT via TIME. */
+		SkRlmtEvtTim(pAC, IoC, Para);
+		break;
+	case SK_RLMT_SEG_TIM:
+		SkRlmtEvtSegTim(pAC, IoC, Para);
+		break;
+	case SK_RLMT_PACKET_RECEIVED:	/* From DRV. */
+		SkRlmtEvtPacketRx(pAC, IoC, Para);
+		break;
+	case SK_RLMT_STATS_CLEAR:	/* From PNMI. */
+		SkRlmtEvtStatsClear(pAC, IoC, Para);
+		break;
+	case SK_RLMT_STATS_UPDATE:	/* From PNMI. */
+		SkRlmtEvtStatsUpdate(pAC, IoC, Para);
+		break;
+	case SK_RLMT_PREFPORT_CHANGE:	/* From PNMI. */
+		SkRlmtEvtPrefportChange(pAC, IoC, Para);
+		break;
+	case SK_RLMT_MODE_CHANGE:	/* From PNMI. */
+		SkRlmtEvtModeChange(pAC, IoC, Para);
+		break;
+	case SK_RLMT_SET_NETS:	/* From DRV. */
+		SkRlmtEvtSetNets(pAC, IoC, Para);
+		break;
+
+	/* ----- Unknown events ----- */
+
+	default:	/* Create error log entry. */
+		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+			("Unknown RLMT Event %d.\n", Event));
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
+		break;
+	}	/* switch() */
+
+	return (0);
+}	/* SkRlmtEvent */
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
new file mode 100755
index 0000000..0530b31
--- /dev/null
+++ b/drivers/net/sk98lin/sktimer.c
@@ -0,0 +1,237 @@
+/******************************************************************************
+ *
+ * Name:	sktimer.c
+ * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+ * Version:	$Revision: 2.3 $
+ * Date:	$Date: 2005/12/14 16:11:02 $
+ * Purpose:	High level timer functions.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2004 Marvell.
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ *	Event queue and dispatcher
+ */
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: sktimer.c,v 2.3 2005/12/14 16:11:02 ibrueder Exp $ (C) Marvell.";
+#endif
+
+#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+
+#ifdef __C2MAN__
+/*
+	Event queue management.
+
+	General Description:
+
+ */
+intro()
+{}
+#endif
+
+
+/* Forward declaration */
+static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
+
+
+/*
+ * Inits the software timer
+ *
+ * needs to be called during Init level 1.
+ */
+void	SkTimerInit(
+SK_AC	*pAC,		/* Adapters context */
+SK_IOC	Ioc,		/* IoContext */
+int		Level)		/* Init Level */
+{
+	switch (Level) {
+	case SK_INIT_DATA:
+		pAC->Tim.StQueue = 0;
+		break;
+	case SK_INIT_IO:
+		SkHwtInit(pAC, Ioc);
+		SkTimerDone(pAC, Ioc);
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * Stops a high level timer
+ * - If a timer is not in the queue the function returns normally, too.
+ */
+void	SkTimerStop(
+SK_AC		*pAC,		/* Adapters context */
+SK_IOC		Ioc,		/* IoContext */
+SK_TIMER	*pTimer)	/* Timer Pointer to be started */
+{
+	SK_TIMER	**ppTimPrev;
+	SK_TIMER	*pTm;
+
+	/* remove timer from queue */
+	pTimer->TmActive = SK_FALSE;
+
+	if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
+		SkHwtStop(pAC, Ioc);
+	}
+
+	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
+		ppTimPrev = &pTm->TmNext ) {
+
+		if (pTm == pTimer) {
+			/*
+			 * Timer found in queue
+			 * - dequeue it
+			 * - correct delta of the next timer
+			 */
+			*ppTimPrev = pTm->TmNext;
+
+			if (pTm->TmNext) {
+				/* correct delta of next timer in queue */
+				pTm->TmNext->TmDelta += pTm->TmDelta;
+			}
+			return;
+		}
+	}
+}
+
+/*
+ * Start a high level software timer
+ */
+void	SkTimerStart(
+SK_AC		*pAC,		/* Adapters context */
+SK_IOC		Ioc,		/* IoContext */
+SK_TIMER	*pTimer,	/* Timer Pointer to be started */
+SK_U32		Time,		/* Time Value (in microsec.) */
+SK_U32		Class,		/* Event Class for this timer */
+SK_U32		Event,		/* Event Value for this timer */
+SK_EVPARA	Para)		/* Event Parameter for this timer */
+{
+	SK_TIMER	**ppTimPrev;
+	SK_TIMER	*pTm;
+	SK_U32		Delta;
+
+	SkTimerStop(pAC, Ioc, pTimer);
+
+	pTimer->TmClass = Class;
+	pTimer->TmEvent = Event;
+	pTimer->TmPara = Para;
+	pTimer->TmActive = SK_TRUE;
+
+	if (!pAC->Tim.StQueue) {
+		/* first Timer to be started */
+		pAC->Tim.StQueue = pTimer;
+		pTimer->TmNext = 0;
+		pTimer->TmDelta = Time;
+
+		SkHwtStart(pAC, Ioc, Time);
+
+		return;
+	}
+
+	/* timer correction */
+	timer_done(pAC, Ioc, 0);
+
+	/* find position in queue */
+	Delta = 0;
+	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
+		ppTimPrev = &pTm->TmNext ) {
+
+		if (Delta + pTm->TmDelta > Time) {
+			/* the timer needs to be inserted here */
+			break;
+		}
+		Delta += pTm->TmDelta;
+	}
+
+	/* insert in queue */
+	*ppTimPrev = pTimer;
+	pTimer->TmNext = pTm;
+	pTimer->TmDelta = Time - Delta;
+
+	if (pTm) {
+		/* there is a next timer:  correct its Delta value */
+		pTm->TmDelta -= pTimer->TmDelta;
+	}
+
+	/* restart with first */
+	SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
+}
+
+
+void	SkTimerDone(
+SK_AC	*pAC,		/* Adapters context */
+SK_IOC	Ioc)		/* IoContext */
+{
+	timer_done(pAC, Ioc, 1);
+}
+
+
+static void	timer_done(
+SK_AC	*pAC,		/* Adapters context */
+SK_IOC	Ioc,		/* IoContext */
+int		Restart)	/* Do we need to restart the Hardware timer ? */
+{
+	SK_U32		Delta;
+	SK_TIMER	*pTm;
+	SK_TIMER	*pTComp;	/* Timer completed now now */
+	SK_TIMER	**ppLast;	/* Next field of Last timer to be deq */
+	int		Done = 0;
+
+	Delta = SkHwtRead(pAC, Ioc);
+
+	ppLast = &pAC->Tim.StQueue;
+	pTm = pAC->Tim.StQueue;
+	while (pTm && !Done) {
+		if (Delta >= pTm->TmDelta) {
+			/* Timer ran out */
+			pTm->TmActive = SK_FALSE;
+			Delta -= pTm->TmDelta;
+			ppLast = &pTm->TmNext;
+			pTm = pTm->TmNext;
+		}
+		else {
+			/* We found the first timer that did not run out */
+			pTm->TmDelta -= Delta;
+			Delta = 0;
+			Done = 1;
+		}
+	}
+	*ppLast = 0;
+	/*
+	 * pTm points to the first Timer that did not run out.
+	 * StQueue points to the first Timer that run out.
+	 */
+
+	for (pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
+		SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
+	}
+
+	/* Set head of timer queue to the first timer that did not run out */
+	pAC->Tim.StQueue = pTm;
+
+	if (Restart && pAC->Tim.StQueue) {
+		/* Restart HW timer */
+		SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
+	}
+}
+
+/* End of file */
diff --git a/drivers/net/sk98lin/sktwsi.c b/drivers/net/sk98lin/sktwsi.c
new file mode 100755
index 0000000..cc4b639
--- /dev/null
+++ b/drivers/net/sk98lin/sktwsi.c
@@ -0,0 +1,1363 @@
+/******************************************************************************
+ *
+ * Name:	sktwsi.c
+ * Project:	Gigabit Ethernet Adapters, TWSI-Module
+ * Version:	$Revision: 1.15 $
+ * Date:	$Date: 2007/06/27 14:49:16 $
+ * Purpose:	Functions to access Voltage and Temperature Sensor
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2006 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+ *	TWSI Protocol
+ */
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: sktwsi.c,v 1.15 2007/06/27 14:49:16 malthoff Exp $ (C) Marvell.";
+#endif
+
+#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+#include "h/lm80.h"
+#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+
+#ifdef __C2MAN__
+/*
+	TWSI protocol implementation.
+
+	General Description:
+
+	The TWSI protocol is used for the temperature sensors and for
+	the serial EEPROM which hold the configuration.
+
+	This file covers functions that allow to read write and do
+	some bulk requests a specified TWSI address.
+
+	The Genesis has 2 TWSI buses. One for the EEPROM which holds
+	the VPD Data and one for temperature and voltage sensor.
+	The following picture shows the TWSI buses, TWSI devices and
+	their control registers.
+
+	Note: The VPD functions are in skvpd.c
+.
+.	PCI Config TWSI Bus for VPD Data:
+.
+.		      +------------+
+.		      | VPD EEPROM |
+.		      +------------+
+.			     |
+.			     | <-- TWSI
+.			     |
+.		 +-----------+-----------+
+.		 |			 |
+.	+-----------------+	+-----------------+
+.	| PCI_VPD_ADR_REG |	| PCI_VPD_DAT_REG |
+.	+-----------------+	+-----------------+
+.
+.
+.	TWSI Bus for LM80 sensor:
+.
+.			+-----------------+
+.			| Temperature and |
+.			| Voltage Sensor  |
+.			| 	LM80	  |
+.			+-----------------+
+.				|
+.				|
+.			TWSI --> |
+.				|
+.			     +----+
+.	     +-------------->| OR |<--+
+.	     |		     +----+   |
+.     +------+------+		      |
+.     |		    |		      |
+. +--------+	+--------+	+----------+
+. | B2_I2C |	| B2_I2C |	|  B2_I2C  |
+. | _CTRL  |	| _DATA  |	|   _SW    |
+. +--------+	+--------+	+----------+
+.
+	The TWSI bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
+	and B2_I2C_DATA registers.
+	For driver software it is recommended to use the TWSI control and
+	data register, because TWSI bus timing is done by the ASIC and
+	an interrupt may be received when the TWSI request is completed.
+
+	Clock Rate Timing:			MIN	MAX	generated by
+		VPD EEPROM:			50 kHz	100 kHz		HW
+		LM80 over TWSI Ctrl/Data reg.	50 kHz	100 kHz		HW
+		LM80 over B2_I2C_SW register	0	400 kHz		SW
+
+	Note:	The clock generated by the hardware is dependend on the
+		PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
+		clock is 50 kHz.
+ */
+intro()
+{}
+#endif
+
+#ifdef SK_DIAG
+/*
+ * TWSI Fast Mode timing values used by the LM80.
+ * If new devices are added to the TWSI bus the timing values have to be checked.
+ */
+#ifndef I2C_SLOW_TIMING
+#define T_CLK_LOW			1300L	/* clock low time in ns */
+#define T_CLK_HIGH			 600L	/* clock high time in ns */
+#define T_DATA_IN_SETUP		 100L	/* data in Set-up Time */
+#define T_START_HOLD		 600L	/* start condition hold time */
+#define T_START_SETUP		 600L	/* start condition Set-up time */
+#define T_STOP_SETUP		 600L	/* stop condition Set-up time */
+#define T_BUS_IDLE			1300L	/* time the bus must free after Tx */
+#define T_CLK_2_DATA_OUT	 900L	/* max. clock low to data output valid */
+#else	/* I2C_SLOW_TIMING */
+/* TWSI Standard Mode Timing */
+#define T_CLK_LOW			4700L	/* clock low time in ns */
+#define T_CLK_HIGH			4000L	/* clock high time in ns */
+#define T_DATA_IN_SETUP		 250L	/* data in Set-up Time */
+#define T_START_HOLD		4000L	/* start condition hold time */
+#define T_START_SETUP		4700L	/* start condition Set-up time */
+#define T_STOP_SETUP		4000L	/* stop condition Set-up time */
+#define T_BUS_IDLE			4700L	/* time the bus must free after Tx */
+#endif	/* !I2C_SLOW_TIMING */
+
+#define NS2BCLK(x)	(((x)*125)/10000)
+
+/*
+ * TWSI Wire Operations
+ *
+ * About I2C_CLK_LOW():
+ *
+ * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
+ * clock to low, to prevent the ASIC and the TWSI data client from driving the
+ * serial data line simultaneously (ASIC: last bit of a byte = '1', TWSI client
+ * send an 'ACK'). See also Concentrator Bugreport No. 10192.
+ */
+#define I2C_DATA_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA)
+#define I2C_DATA_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA)
+#define I2C_DATA_OUT(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
+#define I2C_DATA_IN(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
+#define I2C_CLK_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_CLK)
+#define I2C_CLK_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
+#define I2C_START_COND(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK)
+
+#define NS2CLKT(x)	((x*125L)/10000)
+
+/*--------------- TWSI Interface Register Functions --------------- */
+
+/*
+ * sending one bit
+ */
+void SkI2cSndBit(
+SK_IOC	IoC,	/* I/O Context */
+SK_U8	Bit)	/* Bit to send */
+{
+	I2C_DATA_OUT(IoC);
+	if (Bit) {
+		I2C_DATA_HIGH(IoC);
+	}
+	else {
+		I2C_DATA_LOW(IoC);
+	}
+	SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
+	I2C_CLK_HIGH(IoC);
+	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
+	I2C_CLK_LOW(IoC);
+}	/* SkI2cSndBit*/
+
+
+/*
+ * Signal a start to the TWSI Bus.
+ *
+ * A start is signaled when data goes to low in a high clock cycle.
+ *
+ * Ends with Clock Low.
+ *
+ * Status: not tested
+ */
+void SkI2cStart(
+SK_IOC	IoC)	/* I/O Context */
+{
+	/* Init data and Clock to output lines */
+	/* Set Data high */
+	I2C_DATA_OUT(IoC);
+	I2C_DATA_HIGH(IoC);
+	/* Set Clock high */
+	I2C_CLK_HIGH(IoC);
+
+	SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
+
+	/* Set Data Low */
+	I2C_DATA_LOW(IoC);
+
+	SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
+
+	/* Clock low without Data to Input */
+	I2C_START_COND(IoC);
+
+	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
+}	/* SkI2cStart */
+
+
+void SkI2cStop(
+SK_IOC	IoC)	/* I/O Context */
+{
+	/* Init data and Clock to output lines */
+	/* Set Data low */
+	I2C_DATA_OUT(IoC);
+	I2C_DATA_LOW(IoC);
+
+	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
+
+	/* Set Clock high */
+	I2C_CLK_HIGH(IoC);
+
+	SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
+
+	/*
+	 * Set Data High:	Do it by setting the Data Line to Input.
+	 *			Because of a pull up resistor the Data Line
+	 *			floods to high.
+	 */
+	I2C_DATA_IN(IoC);
+
+	/*
+	 *	When TWSI activity is stopped
+	 *	 o	DATA should be set to input and
+	 *	 o	CLOCK should be set to high!
+	 */
+	SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
+}	/* SkI2cStop */
+
+
+/*
+ * Receive just one bit via the TWSI bus.
+ *
+ * Note:	Clock must be set to LOW before calling this function.
+ *
+ * Returns The received bit.
+ */
+int SkI2cRcvBit(
+SK_IOC	IoC)	/* I/O Context */
+{
+	int	Bit;
+	SK_U8	I2cSwCtrl;
+
+	/* Init data as input line */
+	I2C_DATA_IN(IoC);
+
+	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
+
+	I2C_CLK_HIGH(IoC);
+
+	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
+
+	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
+
+	Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
+
+	I2C_CLK_LOW(IoC);
+	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
+
+	return(Bit);
+}	/* SkI2cRcvBit */
+
+
+/*
+ * Receive an ACK.
+ *
+ * returns	0 If acknowledged
+ *		1 in case of an error
+ */
+int SkI2cRcvAck(
+SK_IOC	IoC)	/* I/O Context */
+{
+	/*
+	 * Received bit must be zero.
+	 */
+	return(SkI2cRcvBit(IoC) != 0);
+}	/* SkI2cRcvAck */
+
+
+/*
+ * Send an NACK.
+ */
+void SkI2cSndNAck(
+SK_IOC	IoC)	/* I/O Context */
+{
+	/*
+	 * Received bit must be zero.
+	 */
+	SkI2cSndBit(IoC, 1);
+}	/* SkI2cSndNAck */
+
+
+/*
+ * Send an ACK.
+ */
+void SkI2cSndAck(
+SK_IOC IoC)	/* I/O Context */
+{
+	/*
+	 * Received bit must be zero.
+	 */
+	SkI2cSndBit(IoC, 0);
+}	/* SkI2cSndAck */
+
+
+/*
+ * Send one byte to the TWSI device and wait for ACK.
+ *
+ * Return acknowleged status.
+ */
+int SkI2cSndByte(
+SK_IOC	IoC,	/* I/O Context */
+int		Byte)	/* byte to send */
+{
+	int	i;
+
+	for (i = 0; i < 8; i++) {
+		if (Byte & (1<<(7-i))) {
+			SkI2cSndBit(IoC, 1);
+		}
+		else {
+			SkI2cSndBit(IoC, 0);
+		}
+	}
+
+	return(SkI2cRcvAck(IoC));
+}	/* SkI2cSndByte */
+
+
+/*
+ * Receive one byte and ack it.
+ *
+ * Return byte.
+ */
+int SkI2cRcvByte(
+SK_IOC	IoC,	/* I/O Context */
+int		Last)	/* Last Byte Flag */
+{
+	int	i;
+	int	Byte = 0;
+
+	for (i = 0; i < 8; i++) {
+		Byte <<= 1;
+		Byte |= SkI2cRcvBit(IoC);
+	}
+
+	if (Last) {
+		SkI2cSndNAck(IoC);
+	}
+	else {
+		SkI2cSndAck(IoC);
+	}
+
+	return(Byte);
+}	/* SkI2cRcvByte */
+
+
+/*
+ * Start dialog and send device address
+ *
+ * Return 0 if acknowleged, 1 in case of an error
+ */
+int SkI2cSndDev(
+SK_IOC	IoC,	/* I/O Context */
+int		Addr,	/* Device Address */
+int		Rw)		/* Read / Write Flag */
+{
+	SkI2cStart(IoC);
+	Rw = ~Rw;
+	Rw &= I2C_WRITE;
+	return(SkI2cSndByte(IoC, (Addr << 1) | Rw));
+}	/* SkI2cSndDev */
+
+#endif /* SK_DIAG */
+
+/*----------------- TWSI CTRL Register Functions ----------*/
+
+/*
+ * waits for a completion of a TWSI transfer
+ *
+ * returns	0:	success, transfer completes
+ *			1:	error,	 transfer does not complete, TWSI transfer
+ *						 killed, wait loop terminated.
+ */
+int SkI2cWait(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Event)	/* complete event to wait for (I2C_READ or I2C_WRITE) */
+{
+	SK_U64	StartTime;
+	SK_U64	CurrTime;
+	SK_U32	I2cCtrl;
+
+	StartTime = SkOsGetTime(pAC);
+
+	do {
+		CurrTime = SkOsGetTime(pAC);
+
+#ifdef YUKON_DBG
+//		printf("StartTime=%lu, CurrTime=%lu\n", StartTime, CurrTime);
+		if (kbhit()) {
+			return(0);
+		}
+#endif /* YUKON_DBG */
+
+		if (CurrTime - StartTime > SK_TICKS_PER_SEC / 8) {
+
+			SK_I2C_STOP(IoC);
+#ifndef SK_DIAG
+			if (pAC->I2c.InitLevel > SK_INIT_DATA) {
+				SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
+			}
+#endif /* !SK_DIAG */
+			return(1);
+		}
+
+		SK_I2C_GET_CTL(IoC, &I2cCtrl);
+
+	} while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
+
+	return(0);
+}	/* SkI2cWait */
+
+
+/*
+ * waits for a completion of a TWSI transfer
+ *
+ * Returns
+ *	Nothing
+ */
+void SkI2cWaitIrq(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC)	/* I/O Context */
+{
+	SK_SENSOR	*pSen;
+	SK_U64		StartTime;
+	SK_U32		IrqSrc;
+	SK_U32		IsTwsiReadyBit;
+
+	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+
+	if (pSen->SenState == SK_SEN_IDLE) {
+		return;
+	}
+
+	IsTwsiReadyBit = CHIP_ID_YUKON_2(pAC) ? Y2_IS_TWSI_RDY : IS_I2C_READY;
+
+	StartTime = SkOsGetTime(pAC);
+
+	do {
+		if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
+
+			SK_I2C_STOP(IoC);
+#ifndef SK_DIAG
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
+#endif /* !SK_DIAG */
+			return;
+		}
+
+		SK_IN32(IoC, B0_ISRC, &IrqSrc);
+
+	} while ((IrqSrc & IsTwsiReadyBit) == 0);
+
+	pSen->SenState = SK_SEN_IDLE;
+	return;
+}	/* SkI2cWaitIrq */
+
+/*
+ * writes a single byte or 4 bytes into the TWSI device
+ *
+ * returns	0:	success
+ *			1:	error
+ */
+int SkI2cWrite(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+SK_U32	I2cData,	/* TWSI Data to write */
+int		I2cDev,		/* TWSI Device Address */
+int		I2cDevSize,	/* TWSI Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
+int		I2cReg,		/* TWSI Device Register Address */
+int		I2cBurst)	/* TWSI Burst Flag */
+{
+	SK_OUT32(IoC, B2_I2C_DATA, I2cData);
+
+	SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
+
+	return(SkI2cWait(pAC, IoC, I2C_WRITE));
+}	/* SkI2cWrite*/
+
+
+#ifdef SK_DIAG
+/*
+ * reads a single byte or 4 bytes from the TWSI device
+ *
+ * returns	the word read
+ */
+SK_U32 SkI2cRead(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		I2cDev,		/* TWSI Device Address */
+int		I2cDevSize,	/* TWSI Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
+int		I2cReg,		/* TWSI Device Register Address */
+int		I2cBurst)	/* TWSI Burst Flag */
+{
+	SK_U32	Data;
+
+	SK_OUT32(IoC, B2_I2C_DATA, 0);
+
+	SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
+
+	if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
+		w_print("%s\n", SKERR_I2C_E002MSG);
+	}
+
+	SK_IN32(IoC, B2_I2C_DATA, &Data);
+
+	return(Data);
+}	/* SkI2cRead */
+#endif /* SK_DIAG */
+
+
+/*
+ * read a sensor's value
+ *
+ * This function reads a sensor's value from the TWSI sensor chip. The sensor
+ * is defined by its index into the sensors database in the struct pAC points
+ * to.
+ * Returns
+ *		1 if the read is completed
+ *		0 if the read must be continued (TWSI Bus still allocated)
+ */
+int SkI2cReadSensor(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_SENSOR	*pSen)	/* Sensor to be read */
+{
+	if (pSen->SenRead != NULL) {
+		return((*pSen->SenRead)(pAC, IoC, pSen));
+	}
+
+	return(0); /* no success */
+}	/* SkI2cReadSensor */
+
+/*
+ * Do the Init state 0 initialization
+ */
+static int SkI2cInit0(
+SK_AC	*pAC)	/* Adapter Context */
+{
+	int			i;
+	SK_SENSOR	*pSen;
+
+	/* Begin with first sensor */
+	pAC->I2c.CurrSens = 0;
+
+	/* Begin with timeout control for state machine */
+	pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
+
+	/* Set sensor number to zero */
+	pAC->I2c.MaxSens = 0;
+
+#ifndef SK_DIAG
+	/* Initialize Number of Dummy Reads */
+	pAC->I2c.DummyReads = SK_MAX_SENSORS;
+#endif /* !SK_DIAG */
+
+	for (i = 0; i < SK_MAX_SENSORS; i++) {
+		pSen = &pAC->I2c.SenTable[i];
+
+		pSen->SenDesc = "unknown";
+		pSen->SenType = SK_SEN_UNKNOWN;
+		pSen->SenThreErrHigh = 0;
+		pSen->SenThreErrLow = 0;
+		pSen->SenThreWarnHigh = 0;
+		pSen->SenThreWarnLow = 0;
+		pSen->SenReg = LM80_FAN2_IN;
+		pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+		pSen->SenValue = 0;
+		pSen->SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
+		pSen->SenErrCts = 0;
+		pSen->SenBegErrTS = 0;
+		pSen->SenState = SK_SEN_IDLE;
+		pSen->SenRead = NULL;
+		pSen->SenDev = 0;
+	}
+
+	/* Now we are "INIT data"ed */
+	pAC->I2c.InitLevel = SK_INIT_DATA;
+	return(0);
+}	/* SkI2cInit0*/
+
+
+/*
+ * Do the init state 1 initialization
+ *
+ * initialize the following register of the LM80:
+ * Configuration register:
+ * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
+ *
+ * Interrupt Mask Register 1:
+ * - all interrupts are Disabled (0xff)
+ *
+ * Interrupt Mask Register 2:
+ * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
+ *
+ * Fan Divisor/RST_OUT register:
+ * - Divisors set to 1 (bits 00), all others 0s.
+ *
+ * OS# Configuration/Temperature resolution Register:
+ * - all 0s
+ *
+ */
+static int SkI2cInit1(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC)	/* I/O Context */
+{
+	int			i;
+	SK_U8		I2cSwCtrl;
+	SK_GEPORT	*pPrt;	/* GIni Port struct pointer */
+	SK_SENSOR	*pSen;
+
+	if (pAC->I2c.InitLevel != SK_INIT_DATA) {
+		/* Re-init not needed in TWSI module */
+		return(0);
+	}
+
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC ||
+		pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U ||
+		pAC->GIni.GIChipId == CHIP_ID_YUKON_EX ||
+		pAC->GIni.GIChipId == CHIP_ID_YUKON_FE ||
+		pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+		/* No sensors on Yukon-EC, -ECU, -EX, -FE, ad -FE+. */
+		return(0);
+	}
+
+	/* Set the Direction of TWSI-Data Pin to IN */
+	SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
+
+	/* Check for 32-Bit Yukon with Low at TWSI-Data Pin */
+	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
+
+	if ((I2cSwCtrl & I2C_DATA) == 0) {
+		/* this is a 32-Bit board */
+		pAC->GIni.GIYukon32Bit = SK_TRUE;
+		return(0);
+	}
+
+	/* Check for 64 Bit Yukon without sensors */
+	if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
+		return(0);
+	}
+
+	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
+
+	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
+
+	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
+
+	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
+
+	(void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
+		LM80_CFG, 0);
+
+	/*
+	 * MaxSens has to be updated here, because PhyType is not
+	 * set when performing Init Level 0
+	 */
+	pAC->I2c.MaxSens = 5;
+
+	pPrt = &pAC->GIni.GP[0];
+
+	if (pAC->GIni.GIGenesis) {
+		if (pPrt->PhyType == SK_PHY_BCOM) {
+			if (pAC->GIni.GIMacsFound == 1) {
+				pAC->I2c.MaxSens += 1;
+			}
+			else {
+				pAC->I2c.MaxSens += 3;
+			}
+		}
+	}
+	else {
+		pAC->I2c.MaxSens += 3;
+	}
+
+	for (i = 0; i < pAC->I2c.MaxSens; i++) {
+		pSen = &pAC->I2c.SenTable[i];
+		switch (i) {
+		case 0:
+			pSen->SenDesc = "Temperature";
+			pSen->SenType = SK_SEN_TEMP;
+			pSen->SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
+			pSen->SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
+			pSen->SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
+			pSen->SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
+			pSen->SenReg = LM80_TEMP_IN;
+			break;
+		case 1:
+			pSen->SenDesc = "Voltage PCI";
+			pSen->SenType = SK_SEN_VOLT;
+			pSen->SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
+			pSen->SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
+			if (pAC->GIni.GIPciBus != SK_PEX_BUS) {
+				pSen->SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
+				pSen->SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
+			}
+			else {
+				pSen->SenThreWarnLow = 0;
+				pSen->SenThreErrLow = 0;
+			}
+			pSen->SenReg = LM80_VT0_IN;
+			break;
+		case 2:
+			pSen->SenDesc = "Voltage PCI-IO";
+			pSen->SenType = SK_SEN_VOLT;
+			pSen->SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
+			pSen->SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
+			if (pAC->GIni.GIPciBus != SK_PEX_BUS) {
+				pSen->SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
+				pSen->SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
+			}
+			else {
+				pSen->SenThreWarnLow = 0;
+				pSen->SenThreErrLow = 0;
+			}
+			pSen->SenReg = LM80_VT1_IN;
+			pSen->SenInit = SK_SEN_DYN_INIT_PCI_IO;
+			break;
+		case 3:
+			if (pAC->GIni.GIGenesis) {
+				pSen->SenDesc = "Voltage ASIC";
+			}
+			else {
+				pSen->SenDesc = "Voltage VMAIN";
+			}
+			pSen->SenType = SK_SEN_VOLT;
+			pSen->SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
+			pSen->SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
+			pSen->SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
+			pSen->SenThreErrLow = SK_SEN_VDD_LOW_ERR;
+			pSen->SenReg = LM80_VT2_IN;
+			break;
+		case 4:
+			if (pAC->GIni.GIGenesis) {
+				if (pPrt->PhyType == SK_PHY_BCOM) {
+					pSen->SenDesc = "Voltage PHY A PLL";
+					pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+					pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+					pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+					pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+				}
+				else {
+					pSen->SenDesc = "Voltage PMA";
+					pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+					pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+					pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+					pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+				}
+			}
+			else {
+				pSen->SenDesc = "Voltage VAUX";
+				pSen->SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
+				pSen->SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
+				if (pAC->GIni.GIVauxAvail) {
+					pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
+					pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
+				}
+				else {
+					pSen->SenThreErrLow = 0;
+					pSen->SenThreWarnLow = 0;
+				}
+			}
+			pSen->SenType = SK_SEN_VOLT;
+			pSen->SenReg = LM80_VT3_IN;
+			break;
+		case 5:
+			if (CHIP_ID_YUKON_2(pAC)) {
+				if (pAC->GIni.GIChipRev == CHIP_REV_YU_XL_A0) {
+					pSen->SenDesc = "Voltage Core 1V3";
+					pSen->SenThreErrHigh = SK_SEN_CORE_1V3_HIGH_ERR;
+					pSen->SenThreWarnHigh = SK_SEN_CORE_1V3_HIGH_WARN;
+					pSen->SenThreWarnLow = SK_SEN_CORE_1V3_LOW_WARN;
+					pSen->SenThreErrLow = SK_SEN_CORE_1V3_LOW_ERR;
+				}
+				else {
+					pSen->SenDesc = "Voltage Core 1V2";
+					pSen->SenThreErrHigh = SK_SEN_CORE_1V2_HIGH_ERR;
+					pSen->SenThreWarnHigh = SK_SEN_CORE_1V2_HIGH_WARN;
+					pSen->SenThreWarnLow = SK_SEN_CORE_1V2_LOW_WARN;
+					pSen->SenThreErrLow = SK_SEN_CORE_1V2_LOW_ERR;
+				}
+			}
+			else {
+				if (pAC->GIni.GIGenesis) {
+					pSen->SenDesc = "Voltage PHY 2V5";
+					pSen->SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
+					pSen->SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
+					pSen->SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
+					pSen->SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
+				}
+				else {
+					pSen->SenDesc = "Voltage Core 1V5";
+					pSen->SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
+					pSen->SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
+					pSen->SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
+					pSen->SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
+				}
+			}
+			pSen->SenType = SK_SEN_VOLT;
+			pSen->SenReg = LM80_VT4_IN;
+			break;
+		case 6:
+			if (CHIP_ID_YUKON_2(pAC)) {
+				pSen->SenDesc = "Voltage PHY 1V5";
+				pSen->SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
+				pSen->SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
+				if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
+					pSen->SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
+					pSen->SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
+				}
+				else {
+					pSen->SenThreWarnLow = 0;
+					pSen->SenThreErrLow = 0;
+				}
+			}
+			else {
+				if (pAC->GIni.GIGenesis) {
+					pSen->SenDesc = "Voltage PHY B PLL";
+				}
+				else {
+					pSen->SenDesc = "Voltage PHY 3V3";
+				}
+				pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+				pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+				pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+				pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+			}
+			pSen->SenType = SK_SEN_VOLT;
+			pSen->SenReg = LM80_VT5_IN;
+			break;
+		case 7:
+			if (pAC->GIni.GIGenesis) {
+				pSen->SenDesc = "Speed Fan";
+				pSen->SenType = SK_SEN_FAN;
+				pSen->SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
+				pSen->SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
+				pSen->SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
+				pSen->SenThreErrLow = SK_SEN_FAN_LOW_ERR;
+				pSen->SenReg = LM80_FAN2_IN;
+			}
+			else {
+				pSen->SenDesc = "Voltage PHY 2V5";
+				pSen->SenType = SK_SEN_VOLT;
+				pSen->SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
+				pSen->SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
+				pSen->SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
+				pSen->SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
+				pSen->SenReg = LM80_VT6_IN;
+			}
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
+				SKERR_I2C_E001, SKERR_I2C_E001MSG);
+			break;
+		}
+
+		pSen->SenValue = 0;
+		pSen->SenErrFlag = SK_SEN_ERR_OK;
+		pSen->SenErrCts = 0;
+		pSen->SenBegErrTS = 0;
+		pSen->SenState = SK_SEN_IDLE;
+		if (pSen->SenThreWarnLow != 0) {
+			pSen->SenRead = SkLm80ReadSensor;
+		}
+		pSen->SenDev = LM80_ADDR;
+	}
+
+#ifndef SK_DIAG
+	pAC->I2c.DummyReads = pAC->I2c.MaxSens;
+#endif /* !SK_DIAG */
+
+	/* Clear TWSI IRQ */
+	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+
+	/* Now we are I/O initialized */
+	pAC->I2c.InitLevel = SK_INIT_IO;
+	return(0);
+}	/* SkI2cInit1 */
+
+
+/*
+ * Init level 2: Start first sensor read.
+ */
+static int SkI2cInit2(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC)	/* I/O Context */
+{
+	int			ReadComplete;
+	SK_SENSOR	*pSen;
+
+	if (pAC->I2c.InitLevel != SK_INIT_IO) {
+		/* ReInit not needed in TWSI module */
+		/* Init0 and Init2 not permitted */
+		return(0);
+	}
+
+	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+
+	ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+
+	if (ReadComplete) {
+		SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
+	}
+
+	/* Now we are correctly initialized */
+	pAC->I2c.InitLevel = SK_INIT_RUN;
+
+	return(0);
+}	/* SkI2cInit2*/
+
+
+/*
+ * Initialize TWSI devices
+ *
+ * Get the first voltage value and discard it.
+ * Go into temperature read mode. A default pointer is not set.
+ *
+ * The things to be done depend on the init level in the parameter list:
+ * Level 0:
+ *	Initialize only the data structures. Do NOT access hardware.
+ * Level 1:
+ *	Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
+ * Level 2:
+ *	Everything is possible. Interrupts may be used from now on.
+ *
+ * return:
+ *	0 = success
+ *	other = error.
+ */
+int SkI2cInit(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context needed in levels 1 and 2 */
+int		Level)	/* Init Level */
+{
+
+	switch (Level) {
+	case SK_INIT_DATA:
+		return(SkI2cInit0(pAC));
+	case SK_INIT_IO:
+		return(SkI2cInit1(pAC, IoC));
+	case SK_INIT_RUN:
+		return(SkI2cInit2(pAC, IoC));
+	default:
+		break;
+	}
+
+	return(0);
+}	/* SkI2cInit */
+
+
+#ifndef SK_DIAG
+/*
+ * Interrupt service function for the TWSI Interface
+ *
+ * Clears the Interrupt source
+ *
+ * Reads the register and check it for sending a trap.
+ *
+ * Starts the timer if necessary.
+ */
+void SkI2cIsr(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC)	/* I/O Context */
+{
+	SK_EVPARA	Para;
+
+	/* Clear TWSI IRQ */
+	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+
+	Para.Para64 = 0;
+	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
+}	/* SkI2cIsr */
+
+
+/*
+ * Check this sensors Value against the threshold and send events.
+ */
+static void SkI2cCheckSensor(
+SK_AC		*pAC,	/* Adapter Context */
+SK_SENSOR	*pSen)
+{
+	SK_EVPARA	ParaLocal;
+	SK_BOOL		TooHigh;	/* Is sensor too high? */
+	SK_BOOL		TooLow;		/* Is sensor too low? */
+	SK_U64		CurrTime;	/* Current Time */
+	SK_BOOL		DoTrapSend;	/* We need to send a trap */
+	SK_BOOL		DoErrLog;	/* We need to log the error */
+	SK_BOOL		IsError;	/* Error occured */
+
+	/* Check Dummy Reads first */
+	if (pAC->I2c.DummyReads > 0) {
+		pAC->I2c.DummyReads--;
+		return;
+	}
+
+	/* Get the current time */
+	CurrTime = SkOsGetTime(pAC);
+
+	/* Set para to the most useful setting: The current sensor. */
+	ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
+
+	/* Check the Value against the thresholds. First: Error Thresholds */
+	TooHigh = pSen->SenValue > pSen->SenThreErrHigh;
+	TooLow  = pSen->SenValue < pSen->SenThreErrLow;
+
+	IsError = SK_FALSE;
+
+	if (TooHigh || TooLow) {
+		/* Error condition is satisfied */
+		DoTrapSend = SK_TRUE;
+		DoErrLog = SK_TRUE;
+
+		/* Now error condition is satisfied */
+		IsError = SK_TRUE;
+
+		if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
+			/* This state is the former one */
+
+			/* So check first whether we have to send a trap */
+			if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD > CurrTime) {
+				/*
+				 * Do NOT send the Trap. The hold back time
+				 * has to run out first.
+				 */
+				DoTrapSend = SK_FALSE;
+			}
+
+			/* Check now whether we have to log an Error */
+			if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD > CurrTime) {
+				/*
+				 * Do NOT log the error. The hold back time
+				 * has to run out first.
+				 */
+				DoErrLog = SK_FALSE;
+			}
+		}
+		else {
+			/* We came from a different state -> Set Begin Time Stamp */
+			pSen->SenBegErrTS = CurrTime;
+			pSen->SenErrFlag = SK_SEN_ERR_ERR;
+		}
+
+		if (DoTrapSend) {
+			/* Set current Time */
+			pSen->SenLastErrTrapTS = CurrTime;
+			pSen->SenErrCts++;
+
+			/* Queue PNMI Event */
+			SkEventQueue(pAC, SKGE_PNMI, TooHigh ?
+				SK_PNMI_EVT_SEN_ERR_UPP : SK_PNMI_EVT_SEN_ERR_LOW,
+				ParaLocal);
+		}
+
+		if (DoErrLog) {
+			/* Set current Time */
+			pSen->SenLastErrLogTS = CurrTime;
+
+			if (pSen->SenType == SK_SEN_TEMP) {
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
+			}
+			else if (pSen->SenType == SK_SEN_VOLT) {
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
+			}
+			else {
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
+			}
+		}
+	}
+
+	/* Check the Value against the thresholds */
+	/* 2nd: Warning thresholds */
+	TooHigh = pSen->SenValue > pSen->SenThreWarnHigh;
+	TooLow  = pSen->SenValue < pSen->SenThreWarnLow;
+
+	if (!IsError && (TooHigh || TooLow)) {
+		/* Error condition is satisfied */
+		DoTrapSend = SK_TRUE;
+		DoErrLog = SK_TRUE;
+
+		if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
+			/* This state is the former one */
+
+			/* So check first whether we have to send a trap */
+			if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
+				/*
+				 * Do NOT send the Trap. The hold back time
+				 * has to run out first.
+				 */
+				DoTrapSend = SK_FALSE;
+			}
+
+			/* Check now whether we have to log an Error */
+			if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
+				/*
+				 * Do NOT log the error. The hold back time
+				 * has to run out first.
+				 */
+				DoErrLog = SK_FALSE;
+			}
+		}
+		else {
+			/* We came from a different state -> Set Begin Time Stamp */
+			pSen->SenBegWarnTS = CurrTime;
+			pSen->SenErrFlag = SK_SEN_ERR_WARN;
+		}
+
+		if (DoTrapSend) {
+			/* Set current Time */
+			pSen->SenLastWarnTrapTS = CurrTime;
+			pSen->SenWarnCts++;
+
+			/* Queue PNMI Event */
+			SkEventQueue(pAC, SKGE_PNMI, TooHigh ?
+				SK_PNMI_EVT_SEN_WAR_UPP : SK_PNMI_EVT_SEN_WAR_LOW, ParaLocal);
+		}
+
+		if (DoErrLog) {
+			/* Set current Time */
+			pSen->SenLastWarnLogTS = CurrTime;
+
+			if (pSen->SenType == SK_SEN_TEMP) {
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
+			}
+			else if (pSen->SenType == SK_SEN_VOLT) {
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
+			}
+			else {
+				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
+			}
+		}
+	}
+
+	/* Check for NO error at all */
+	if (!IsError && !TooHigh && !TooLow) {
+		/* Set o.k. Status if no error and no warning condition */
+		pSen->SenErrFlag = SK_SEN_ERR_OK;
+	}
+
+	/* End of check against the thresholds */
+
+	if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
+		/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
+		pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+
+		if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
+			/* 5V PCI-IO Voltage */
+			pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
+			pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
+		}
+		else {
+			/* 3.3V PCI-IO Voltage */
+			pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
+			pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
+		}
+	}
+
+#ifdef TEST_ONLY
+	/* Dynamic thresholds also for VAUX of LM80 sensor */
+	if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
+
+		pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+
+		/* 3.3V VAUX Voltage */
+		if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
+			pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
+			pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
+		}
+		/* 0V VAUX Voltage */
+		else {
+			pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
+			pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
+		}
+	}
+
+	/* Check initialization state: the VIO Thresholds need adaption */
+	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
+		 pSen->SenValue > SK_SEN_WARNLOW2C &&
+		 pSen->SenValue < SK_SEN_WARNHIGH2) {
+
+		pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
+		pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
+		pSen->SenInit = SK_TRUE;
+	}
+
+	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
+		 pSen->SenValue > SK_SEN_WARNLOW2 &&
+		 pSen->SenValue < SK_SEN_WARNHIGH2C) {
+
+		pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
+		pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
+		pSen->SenInit = SK_TRUE;
+	}
+#endif
+
+	if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
+	}
+}	/* SkI2cCheckSensor */
+
+
+/*
+ * The only Event to be served is the timeout event
+ *
+ */
+int SkI2cEvent(
+SK_AC		*pAC,	/* Adapter Context */
+SK_IOC		IoC,	/* I/O Context */
+SK_U32		Event,	/* Module specific Event */
+SK_EVPARA	Para)	/* Event specific Parameter */
+{
+	int			ReadComplete;
+	SK_SENSOR	*pSen;
+	SK_U32		Time;
+	SK_EVPARA	ParaLocal;
+	int			i;
+
+	/* New case: no sensors */
+	if (pAC->I2c.MaxSens == 0) {
+		return(0);
+	}
+
+	switch (Event) {
+	case SK_I2CEV_IRQ:
+		pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+		ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+
+		if (ReadComplete) {
+			/* Check sensor against defined thresholds */
+			SkI2cCheckSensor(pAC, pSen);
+
+			/* Increment Current sensor and set appropriate Timeout */
+			pAC->I2c.CurrSens++;
+			if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
+				pAC->I2c.CurrSens = 0;
+				Time = SK_I2C_TIM_LONG;
+			}
+			else {
+				Time = SK_I2C_TIM_SHORT;
+			}
+
+			/* Start Timer */
+			ParaLocal.Para64 = (SK_U64)0;
+
+			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+
+			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+		}
+		else {
+			/* Start Timer */
+			ParaLocal.Para64 = (SK_U64)0;
+
+			pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
+
+			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
+				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+		}
+		break;
+	case SK_I2CEV_TIM:
+		if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
+
+			ParaLocal.Para64 = (SK_U64)0;
+			SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
+
+			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+			ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+
+			if (ReadComplete) {
+				/* Check sensor against defined thresholds */
+				SkI2cCheckSensor(pAC, pSen);
+
+				/* Increment Current sensor and set appropriate Timeout */
+				pAC->I2c.CurrSens++;
+				if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
+					pAC->I2c.CurrSens = 0;
+					Time = SK_I2C_TIM_LONG;
+				}
+				else {
+					Time = SK_I2C_TIM_SHORT;
+				}
+
+				/* Start Timer */
+				ParaLocal.Para64 = (SK_U64)0;
+
+				pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+
+				SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+					SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+			}
+		}
+		else {
+			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+			pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
+			SK_I2C_STOP(IoC);
+
+			/* Increment Current sensor and set appropriate Timeout */
+			pAC->I2c.CurrSens++;
+			if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
+				pAC->I2c.CurrSens = 0;
+				Time = SK_I2C_TIM_LONG;
+			}
+			else {
+				Time = SK_I2C_TIM_SHORT;
+			}
+
+			/* Start Timer */
+			ParaLocal.Para64 = (SK_U64)0;
+
+			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+
+			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+		}
+		break;
+	case SK_I2CEV_CLEAR:
+		for (i = 0; i < SK_MAX_SENSORS; i++) {
+			pSen = &pAC->I2c.SenTable[i];
+
+			pSen->SenErrFlag = SK_SEN_ERR_OK;
+			pSen->SenErrCts = 0;
+			pSen->SenWarnCts = 0;
+			pSen->SenBegErrTS = 0;
+			pSen->SenBegWarnTS = 0;
+			pSen->SenLastErrTrapTS = (SK_U64)0;
+			pSen->SenLastErrLogTS = (SK_U64)0;
+			pSen->SenLastWarnTrapTS = (SK_U64)0;
+			pSen->SenLastWarnLogTS = (SK_U64)0;
+		}
+		break;
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
+	}
+
+	return(0);
+}	/* SkI2cEvent*/
+
+#endif /* !SK_DIAG */
+
diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
new file mode 100755
index 0000000..678ddc9
--- /dev/null
+++ b/drivers/net/sk98lin/skvpd.c
@@ -0,0 +1,1390 @@
+/******************************************************************************
+ *
+ * Name:	skvpd.c
+ * Project:	Gigabit Ethernet Adapters, VPD-Module
+ * Version:	$Revision: 2.12 $
+ * Date:	$Date: 2007/06/27 14:23:55 $
+ * Purpose:	Shared software to read and write VPD
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*
+	Please refer skvpd.txt for information how to include this module
+ */
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skvpd.c,v 2.12 2007/06/27 14:23:55 malthoff Exp $ (C) Marvell.";
+
+#include "h/skdrv1st.h"
+#include "h/sktypes.h"
+#include "h/skdebug.h"
+#include "h/skdrv2nd.h"
+
+#define SPI_Y2_IS_BUSY(w)		((w)&(1L<<30))
+#define SPI_Y2_CMD_MASK			(0x07L<<16)		/* SPI EPROM command mask  */
+#define SPI_Y2_RD				(0x09L<<16)		/* SPI EPROM READ INSTRUCTION */
+
+
+
+/*
+ * Static functions
+ */
+#ifndef SK_KR_PROTO
+static SK_VPD_PARA	*vpd_find_para(
+	SK_AC	*pAC,
+	const char	*key,
+	SK_VPD_PARA *p);
+#else	/* SK_KR_PROTO */
+static SK_VPD_PARA	*vpd_find_para();
+#endif	/* SK_KR_PROTO */
+
+/*
+ * waits for a completion of a VPD transfer
+ * The VPD transfer must complete within SK_TICKS_PER_SEC/16
+ *
+ * returns	0:	success, transfer completes
+ *		error	exit(9) with a error message
+ */
+static int VpdWait(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+int		event)	/* event to wait for (VPD_READ / VPD_write) completion*/
+{
+	SK_I64	start_time;
+	SK_I64	curr_time;
+	SK_U16	state;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD wait for %s\n", event ? "Write" : "Read"));
+
+	start_time = (SK_I64)SkOsGetTime(pAC);
+
+	do {
+		curr_time = (SK_I64)SkOsGetTime(pAC);
+
+		if (curr_time - start_time > SK_TICKS_PER_SEC) {
+
+			/* Bug fix AF: Thu Mar 28 2002
+			 * Do not call: VPD_STOP(pAC, IoC);
+			 * A pending VPD read cycle can not be aborted by writing
+			 * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
+			 * Although the write threshold in the OUR-register protects
+			 * VPD read only space from being overwritten this does not
+			 * protect a VPD read from being `converted` into a VPD write
+			 * operation (on the fly). As a consequence the VPD_STOP would
+			 * delete VPD read only data. In case of any problems with the
+			 * I2C bus we exit the loop here. The I2C read operation can
+			 * not be aborted except by a reset (->LR).
+			 */
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
+				("ERROR:VPD wait timeout\n"));
+			return(1);
+		}
+
+		VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+			("state = %x, event %x\n", state, event));
+
+	} while ((int)(state & PCI_VPD_FLAG) == event);
+
+	return(0);
+}
+
+#ifndef SK_SLIM		/* needs to be enabled for ASF w/o EEPORM */
+/******************************************************************************
+ *
+ * 	SpiWait()	- waits for a SPI read completion
+ *
+ * Descritption:
+ *	Waits for a completion of a SPI read transfer
+ *	The SPI transfer must complete within one SK_TICKS_PER_SEC
+ *
+ * returns	0:	success, transfer completes
+ *		error	exit(9) with a error message
+ */
+static int SpiWait(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC)	/* IO Context */
+{
+	SK_I64	start_time;
+	SK_I64	curr_time;
+	SK_U32	stat;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("SPI wait for"));
+
+	start_time = (SK_I64)SkOsGetTime(pAC);
+
+	do {
+		curr_time = (SK_I64)SkOsGetTime(pAC);
+
+		SK_IN32(IoC, SPI_CTRL, &stat);
+
+		if (SPI_Y2_IS_BUSY(stat) && curr_time - start_time > SK_TICKS_PER_SEC) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
+				("ERROR:SPI wait timeout\n"));
+			return(1);
+		}
+	} while (SPI_Y2_IS_BUSY(stat));
+
+	return(0);
+}
+#endif /* !SK_SLIM */
+
+#ifdef SK_DIAG
+/*
+ * Read the dword at address 'addr' from the VPD EEPROM.
+ *
+ * Needed Time:	MIN 1,3 ms	MAX 2,6 ms
+ *
+ * Note: The DWord is returned in the endianess of the machine the routine
+ *       is running on.
+ *
+ * Returns the data read.
+ */
+SK_U32 VpdReadDWord(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+int		addr)	/* VPD address */
+{
+	SK_U32	Rtv;
+
+	/* start VPD read */
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD read dword at 0x%x\n", addr));
+	addr &= ~VPD_WRITE;		/* ensure the R/W bit is set to read */
+
+	VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
+
+	/* ignore return code here */
+	(void)VpdWait(pAC, IoC, VPD_READ);
+
+	/* Don't swap here, it's a data stream of bytes */
+	Rtv = 0;
+
+	VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD read dword data = 0x%x\n", Rtv));
+	return(Rtv);
+}
+#endif /* SK_DIAG */
+
+
+#ifdef XXX
+/*
+	Write the dword 'data' at address 'addr' into the VPD EEPROM, and
+	verify that the data is written.
+
+ Needed Time:
+
+.				MIN		MAX
+. -------------------------------------------------------------------
+. write				1.8 ms		3.6 ms
+. internal write cyles		0.7 ms		7.0 ms
+. -------------------------------------------------------------------
+. over all program time	 	2.5 ms		10.6 ms
+. read				1.3 ms		2.6 ms
+. -------------------------------------------------------------------
+. over all 			3.8 ms		13.2 ms
+.
+
+ Returns	0:	success
+			1:	error,	I2C transfer does not terminate
+			2:	error,	data verify error
+
+ */
+static int VpdWriteDWord(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+int		addr,	/* VPD address */
+SK_U32	data)	/* VPD data to write */
+{
+	/* start VPD write */
+	/* Don't swap here, it's a data stream of bytes */
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD write dword at addr 0x%x, data = 0x%x\n", addr, data));
+	VPD_OUT32(pAC, IoC, PCI_VPD_DAT_REG, (SK_U32)data);
+	/* But do it here */
+	addr |= VPD_WRITE;
+
+	VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)(addr | VPD_WRITE));
+
+	/* this may take up to 10,6 ms */
+	if (VpdWait(pAC, IoC, VPD_WRITE)) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("Write Timed Out\n"));
+		return(1);
+	};
+
+	/* verify data */
+	if (VpdReadDWord(pAC, IoC, addr) != data) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("Data Verify Error\n"));
+		return(2);
+	}
+	return(0);
+}	/* VpdWriteDWord */
+
+#endif /* XXX */
+
+
+#ifndef SK_SLIM
+/*
+ *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
+ *	or to the I2C EEPROM.
+ *
+ * Returns number of bytes read / written.
+ */
+static int VpdWriteStream(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+char	*buf,	/* data buffer */
+int		Addr,	/* VPD start address */
+int		Len)	/* number of bytes to read / to write */
+{
+	int		i;
+	int		j;
+	SK_U16	AdrReg;
+	int		Rtv;
+	SK_U8	* pComp;	/* Compare pointer */
+	SK_U8	Data;		/* Input Data for Compare */
+
+	/* Init Compare Pointer */
+	pComp = (SK_U8 *) buf;
+
+	for (i = 0; i < Len; i++, buf++) {
+		if ((i % SZ_LONG) == 0) {
+			/*
+			 * At the begin of each cycle read the Data Reg
+			 * So it is initialized even if only a few bytes
+			 * are written.
+			 */
+			AdrReg = (SK_U16) Addr;
+			AdrReg &= ~VPD_WRITE;	/* READ operation */
+
+			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+
+			/* Wait for termination */
+			Rtv = VpdWait(pAC, IoC, VPD_READ);
+			if (Rtv != 0) {
+				return(i);
+			}
+		}
+
+		/* Write current byte */
+		VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i % SZ_LONG), *(SK_U8 *)buf);
+
+		if (((i % SZ_LONG) == 3) || (i == (Len - 1))) {
+			/* New Address needs to be written to VPD_ADDR reg */
+			AdrReg = (SK_U16) Addr;
+			Addr += SZ_LONG;
+			AdrReg |= VPD_WRITE;	/* WRITE operation */
+
+			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+
+			/* Wait for termination */
+			Rtv = VpdWait(pAC, IoC, VPD_WRITE);
+			if (Rtv != 0) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+					("Write Timed Out\n"));
+				return(i - (i % SZ_LONG));
+			}
+
+			/*
+			 * Now re-read to verify
+			 */
+			AdrReg &= ~VPD_WRITE;	/* READ operation */
+
+			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+
+			/* Wait for termination */
+			Rtv = VpdWait(pAC, IoC, VPD_READ);
+			if (Rtv != 0) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+					("Verify Timed Out\n"));
+				return(i - (i % SZ_LONG));
+			}
+
+			for (j = 0; j <= (int)(i % SZ_LONG); j++, pComp++) {
+
+				VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
+
+				if (Data != *pComp) {
+					/* Verify Error */
+					SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+						("WriteStream Verify Error\n"));
+					return(i - (i % SZ_LONG) + j);
+				}
+			}
+		}
+	}
+
+	return(Len);
+}
+#endif /* !SK_SLIM */
+
+/*
+ *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
+ *	or to the I2C EEPROM.
+ *
+ * Returns number of bytes read / written.
+ */
+static int VpdReadStream(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+char	*buf,	/* data buffer */
+int		Addr,	/* VPD start address */
+int		Len)	/* number of bytes to read / to write */
+{
+	int		i;
+	SK_U16	AdrReg;
+	int		Rtv;
+
+	for (i = 0; i < Len; i++, buf++) {
+		if ((i % SZ_LONG) == 0) {
+			/* New Address needs to be written to VPD_ADDR reg */
+			AdrReg = (SK_U16) Addr;
+			Addr += SZ_LONG;
+			AdrReg &= ~VPD_WRITE;	/* READ operation */
+
+			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+
+			/* Wait for termination */
+			Rtv = VpdWait(pAC, IoC, VPD_READ);
+			if (Rtv != 0) {
+				return(i);
+			}
+		}
+		VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i % SZ_LONG), (SK_U8 *)buf);
+	}
+
+	return(Len);
+}
+
+
+/*
+ *	Read ore writes 'len' bytes of VPD data, starting at 'addr' from
+ *	or to the I2C EEPROM.
+ *
+ * Returns number of bytes read / written.
+ */
+static int VpdTransferBlock(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+char	*buf,	/* data buffer */
+int		addr,	/* VPD start address */
+int		len,	/* number of bytes to read / to write */
+int		dir)	/* transfer direction may be VPD_READ or VPD_WRITE */
+{
+	int		Rtv;	/* Return value */
+	int		vpd_rom_size;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD %s block, addr = 0x%x, len = %d\n",
+		dir ? "write" : "read", addr, len));
+
+	if (len == 0) {
+		return(0);
+	}
+
+	vpd_rom_size = pAC->vpd.rom_size;
+
+	if (addr > vpd_rom_size - 4) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("Address error: 0x%x, exp. < 0x%x\n",
+			addr, vpd_rom_size - 4));
+		return(0);
+	}
+
+	if (addr + len > vpd_rom_size) {
+		len = vpd_rom_size - addr;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("Warning: len was cut to %d\n", len));
+	}
+
+	if (dir == VPD_READ) {
+		Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
+	}
+#ifndef SK_SLIM
+	else {
+		Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
+	}
+#endif /* !SK_SLIM */
+
+	return(Rtv);
+}
+
+#ifndef SK_SLIM		/* needs to be enabled for ASF w/o EEPROM */
+/******************************************************************************
+ *
+ *	SpiReadBlock()	-	Read VPD data from SPI flash
+ *
+ * Description:
+ *	Read 'len' bytes of VPD data, starting at 'addr' from the SPI flash.
+ *	If the device doesn't have an EEPROM. The data VPD data is stored in the
+ *	SPI flash and is read only.
+ *
+ * Returns:
+ *	number of read bytes
+ */
+static int SpiReadBlock(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+char	*buf,	/* data buffer */
+int		addr,	/* VPD start address */
+int		len)	/* number of bytes to read / to write */
+{
+	int		vpd_rom_size;
+	int		i;
+	union {
+		SK_U32	RegVal;
+		SK_U8	Byte[4];
+	} uBuf;
+	SK_U32	SpiCtrlReg;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD SPI read block, addr = 0x%x, len = %d\n", addr, len));
+
+	if (len == 0) {
+		return(0);
+	}
+
+	vpd_rom_size = pAC->vpd.rom_size;
+
+	if (addr > vpd_rom_size - 4) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("Address error: 0x%x, exp. < 0x%x\n",
+			addr, vpd_rom_size - 4));
+		return(0);
+	}
+
+	if (addr + len > vpd_rom_size) {
+		len = vpd_rom_size - addr;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("Warning: len was cut to %d\n", len));
+	}
+
+	addr += VPD_SPI_ADDR;
+
+	for (i = 0; i < len; i++, buf++) {
+		if ((i % SZ_LONG) == 0) {
+			/* write spi address */
+			SK_OUT32(IoC, SPI_ADDR, addr);
+
+			/* execute spi read command */
+			SK_IN32(IoC, SPI_CTRL, &SpiCtrlReg);
+			SpiCtrlReg &= ~SPI_Y2_CMD_MASK;
+			SpiCtrlReg |= SPI_Y2_RD;
+			SK_OUT32(IoC, SPI_CTRL, SpiCtrlReg);
+
+			/* wait for the SPI to finish RD operation */
+			if (SpiWait(pAC, IoC)) {;
+				break;
+			}
+
+			/* read the returned data */
+			SK_IN32(IoC, SPI_DATA, &uBuf.RegVal);
+
+			addr += 4;
+		}
+		*buf = uBuf.Byte[i % SZ_LONG];
+	}
+
+	return(i);
+}
+#endif /* !SK_SLIM */
+
+/*
+ *	Read 'len' bytes of VPD data, starting at 'addr'.
+ *
+ * Returns number of bytes read.
+ */
+int VpdReadBlock(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+char	*buf,	/* buffer were the data should be stored */
+int		addr,	/* start reading at the VPD address */
+int		len)	/* number of bytes to read */
+{
+	if (pAC->vpd.CfgInSpi) {
+		return(SpiReadBlock(pAC, IoC, buf, addr, len));
+	}
+
+	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
+}
+
+/*
+ *	Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
+ *
+ * Returns number of bytes writes.
+ */
+int VpdWriteBlock(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+char	*buf,	/* buffer, holds the data to write */
+int		addr,	/* start writing at the VPD address */
+int		len)	/* number of bytes to write */
+{
+	if (!pAC->vpd.CfgInSpi) {
+		return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
+	}
+
+	return(0);		/* not supported */
+}
+
+/******************************************************************************
+ *
+ *	VpdInit() - (re)initialize the VPD buffer
+ *
+ * Description:
+ *	Reads the VPD data from the EEPROM into the VPD buffer.
+ *	Get the remaining read only and read / write space.
+ *
+ * Returns:
+ *	0:	success
+ *	1:	fatal VPD error
+ */
+int VpdInit(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC)	/* IO Context */
+{
+	SK_VPD_PARA *r, rp;	/* RW or RV */
+	int		i;
+	unsigned char	x;
+	int		vpd_size;
+	SK_U16	dev_id;
+	SK_U32	our_reg2;
+	SK_U8	Byte;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit ... "));
+
+	if (pAC->GIni.GILevel < SK_INIT_IO) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("Wrong Init Level"));
+		return (1);
+	}
+
+	VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
+
+	VPD_IN8(pAC, IoC, PCI_PM_NITEM, &Byte);
+
+	if (!HW_SUP_VPD(pAC)) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VPD not supported"));
+		return (1);
+	}
+
+#ifndef SK_SLIM		/* needs to be enabled for ASF w/o EEPROM */
+	pAC->vpd.CfgInSpi = (Byte != PCI_VPD_CAP_ID && pAC->GIni.GIYukon2) ?
+		SK_TRUE : SK_FALSE;
+#endif	/* !SK_SLIM */
+
+	VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
+
+	pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
+
+	/*
+	 * this function might get used before the hardware is initialized
+	 * therefore we cannot always trust in GIChipId
+	 */
+	if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
+		dev_id != VPD_DEV_ID_GENESIS) ||
+		((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
+		!pAC->GIni.GIGenesis)) {
+
+		/* for Yukon the VPD size is always 256 */
+		vpd_size = VPD_SIZE_YUKON;
+	}
+#ifndef SK_SLIM
+	else {
+		/* Genesis uses the maximum ROM size up to 512 for VPD */
+		if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
+			vpd_size = VPD_SIZE_GENESIS;
+		}
+		else {
+			vpd_size = pAC->vpd.rom_size;
+		}
+	}
+#endif /* !SK_SLIM */
+
+	/* read the VPD data into the VPD buffer */
+	if (VpdReadBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size) != vpd_size) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("Block Read Error\n"));
+		return(1);
+	}
+
+	pAC->vpd.vpd_size = vpd_size;
+
+#ifndef SK_SLIM
+	/* Asus K8V Se Deluxe bugfix. Correct VPD content */
+	i = 62;
+	if (!SK_STRNCMP(pAC->vpd.vpd_buf + i, " 8<E", 4)) {
+
+		pAC->vpd.vpd_buf[i + 2] = '8';
+	}
+#endif /* !SK_SLIM */
+
+	/* find the end tag of the RO area */
+	if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("Encoding Error: RV Tag not found\n"));
+		return(1);
+	}
+
+	if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("Encoding Error: Invalid VPD struct size\n"));
+		return(1);
+	}
+	pAC->vpd.v.vpd_free_ro = r->p_len - 1;
+
+	/* test the checksum */
+	for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
+		x += pAC->vpd.vpd_buf[i];
+	}
+
+	if (x != 0) {
+		/* checksum error */
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("VPD Checksum Error\n"));
+		return(1);
+	}
+
+#ifndef SK_SLIM		/* needs to be enabled for ASF w/o EEPROM */
+	if (pAC->vpd.CfgInSpi) {
+		pAC->vpd.v.vpd_free_rw = 0;
+	}
+	else {
+#endif	/* !SK_SLIM */
+		/* find and check the end tag of the RW area */
+		if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+				("Encoding Error: RV Tag not found\n"));
+			return(1);
+		}
+
+		if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+				("Encoding Error: Invalid VPD struct size\n"));
+			return(1);
+		}
+		pAC->vpd.v.vpd_free_rw = r->p_len;
+#ifndef SK_SLIM		/* needs to be enabled for ASF w/o EEPROM */
+	}
+#endif	/* !SK_SLIM */
+	
+	/* everything seems to be ok */
+	if (pAC->GIni.GIChipId != 0) {
+		pAC->vpd.v.vpd_status |= VPD_VALID;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
+		("done. Free RO = %d, Free RW = %d\n",
+		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
+
+	return(0);
+}
+
+
+/*
+ *	find the Keyword 'key' in the VPD buffer and fills the
+ *	parameter struct 'p' with it's values
+ *
+ * returns	*p	success
+ *		0:	parameter was not found or VPD encoding error
+ */
+static SK_VPD_PARA *vpd_find_para(
+SK_AC		*pAC,	/* Adapters Context */
+const char	*key,	/* keyword to find (e.g. "MN") */
+SK_VPD_PARA	*p)		/* parameter description struct */
+{
+	char *v	;	/* points to VPD buffer */
+	int max;	/* Maximum Number of Iterations */
+	int len;
+
+	v = pAC->vpd.vpd_buf;
+	max = 128;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD find para %s .. ", key));
+
+	/* check mandatory resource type ID string (Product Name) */
+	if (*v != (char)RES_ID) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("Error: 0x%x missing\n", RES_ID));
+		return(0);
+	}
+
+	len = VPD_GET_RES_LEN(v);
+
+	if (SK_STRCMP(key, VPD_NAME) == 0) {
+		p->p_len = len;
+		p->p_val = VPD_GET_VAL(v);
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+			("found, len = %d\n", len));
+		return(p);
+	}
+
+	v += 3 + len + 3;
+
+	for ( ; ; ) {
+		if (SK_MEMCMP(key, v, 2) == 0) {
+			p->p_len = VPD_GET_VPD_LEN(v);
+			p->p_val = VPD_GET_VAL(v);
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+				("found, len = %d\n", p->p_len));
+			return(p);
+		}
+
+		/* exit when reaching the "RW" Tag or the maximum of itera. */
+		max--;
+		if (SK_MEMCMP(VPD_RW, v, 2) == 0 || max == 0) {
+			break;
+		}
+
+		len = 3 + VPD_GET_VPD_LEN(v);
+
+		if (SK_MEMCMP(VPD_RV, v, 2) == 0) {
+			len += 3;					/* skip VPD-W */
+		}
+		v += len;
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+			("scanning '%c%c' len = %d\n", v[0], v[1], v[2]));
+	}
+
+#ifdef DEBUG
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
+	if (max == 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("Key/Len Encoding error\n"));
+	}
+#endif /* DEBUG */
+	return(0);
+}
+
+
+/*
+ *	Move 'n' bytes. Begin with the last byte if 'n' is > 0,
+ *	Start with the last byte if n is < 0.
+ *
+ * returns nothing
+ */
+static void vpd_move_para(
+char	*start,		/* start of memory block */
+char	*end,		/* end of memory block to move */
+int		n)			/* number of bytes the memory block has to be moved */
+{
+	char *p;
+	int i;		/* number of byte copied */
+
+	if (n == 0) {
+		return;
+	}
+
+	i = (int) (end - start + 1);
+	if (n < 0) {
+		p = start + n;
+		while (i != 0) {
+			*p++ = *start++;
+			i--;
+		}
+	}
+	else {
+		p = end + n;
+		while (i != 0) {
+			*p-- = *end--;
+			i--;
+		}
+	}
+}
+
+
+/*
+ *	setup the VPD keyword 'key' at 'ip'.
+ *
+ * returns nothing
+ */
+static void vpd_insert_key(
+const char	*key,	/* keyword to insert */
+const char	*buf,	/* buffer with the keyword value */
+int		len,		/* length of the value string */
+char	*ip)		/* inseration point */
+{
+	SK_VPD_KEY *p;
+
+	p = (SK_VPD_KEY *) ip;
+	p->p_key[0] = key[0];
+	p->p_key[1] = key[1];
+	p->p_len = (unsigned char)len;
+	SK_MEMCPY(&p->p_val, buf, len);
+}
+
+
+/*
+ *	Setup the VPD end tag "RV" / "RW".
+ *	Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
+ *
+ * returns	0:	success
+ *		1:	encoding error
+ */
+static int vpd_mod_endtag(
+SK_AC	*pAC,		/* Adapters Context */
+char	*etp)		/* end pointer input position */
+{
+	SK_VPD_KEY *p;
+	unsigned char	x;
+	int	i;
+	int	vpd_size;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD modify endtag at 0x%x = '%c%c'\n", etp, etp[0], etp[1]));
+
+	vpd_size = pAC->vpd.vpd_size;
+
+	p = (SK_VPD_KEY *) etp;
+
+	if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
+		/* something wrong here, encoding error */
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+			("Encoding Error: invalid end tag\n"));
+		return(1);
+	}
+	if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
+		/* create "RW" tag */
+		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
+		pAC->vpd.v.vpd_free_rw = (int) p->p_len;
+		i = pAC->vpd.v.vpd_free_rw;
+		etp += 3;
+	}
+	else {
+		/* create "RV" tag */
+		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
+		pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
+
+		/* setup checksum */
+		for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
+			x += pAC->vpd.vpd_buf[i];
+		}
+		p->p_val = (char) 0 - x;
+		i = pAC->vpd.v.vpd_free_ro;
+		etp += 4;
+	}
+	while (i) {
+		*etp++ = 0x00;
+		i--;
+	}
+
+	return(0);
+}
+
+
+/*
+ *	Insert a VPD keyword into the VPD buffer.
+ *
+ *	The keyword 'key' is inserted at the position 'ip' in the
+ *	VPD buffer.
+ *	The keywords behind the input position will
+ *	be moved. The VPD end tag "RV" or "RW" is generated again.
+ *
+ * returns	0:	success
+ *		2:	value string was cut
+ *		4:	VPD full, keyword was not written
+ *		6:	fatal VPD error
+ *
+ */
+int	VpdSetupPara(
+SK_AC	*pAC,		/* Adapters Context */
+const char	*key,	/* keyword to insert */
+const char	*buf,	/* buffer with the keyword value */
+int		len,		/* length of the keyword value */
+int		type,		/* VPD_RO_KEY or VPD_RW_KEY */
+int		op)			/* operation to do: ADD_KEY or OWR_KEY */
+{
+	SK_VPD_PARA vp;
+	char	*etp;		/* end tag position */
+	int	free;		/* remaining space in selected area */
+	char	*ip;		/* input position inside the VPD buffer */
+	int	rtv;		/* return code */
+	int	head;		/* additional haeder bytes to move */
+	int	found;		/* additinoal bytes if the keyword was found */
+	int vpd_size;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("VPD setup para key = %s, val = %s\n", key, buf));
+
+	vpd_size = pAC->vpd.vpd_size;
+
+	rtv = 0;
+	ip = 0;
+	if (type == VPD_RW_KEY) {
+		/* end tag is "RW" */
+		free = pAC->vpd.v.vpd_free_rw;
+		etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
+	}
+	else {
+		/* end tag is "RV" */
+		free = pAC->vpd.v.vpd_free_ro;
+		etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
+	}
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+		("Free RO = %d, Free RW = %d\n",
+		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
+
+	head = 0;
+	found = 0;
+	if (op == OWR_KEY) {
+		if (vpd_find_para(pAC, key, &vp)) {
+			found = 3;
+			ip = vp.p_val - 3;
+			free += vp.p_len + 3;
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+				("Overwrite Key\n"));
+		}
+		else {
+			op = ADD_KEY;
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+				("Add Key\n"));
+		}
+	}
+	if (op == ADD_KEY) {
+		ip = etp;
+		vp.p_len = 0;
+		head = 3;
+	}
+
+	if (len + 3 > free) {
+		if (free < 7) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("VPD Buffer Overflow, keyword not written\n"));
+			return(4);
+		}
+		/* cut it again */
+		len = free - 3;
+		rtv = 2;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("VPD Buffer Full, Keyword was cut\n"));
+	}
+
+	vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
+
+	vpd_insert_key(key, buf, len, ip);
+
+	if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
+		pAC->vpd.v.vpd_status &= ~VPD_VALID;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("VPD Encoding Error\n"));
+		return(6);
+	}
+
+	return(rtv);
+}
+
+#ifndef SK_SLIM
+/*
+ *	Read the contents of the VPD EEPROM and copy it to the
+ *	VPD buffer if not already done.
+ *
+ * return:	A pointer to the vpd_status structure. The structure contains
+ *		this fields.
+ */
+SK_VPD_STATUS *VpdStat(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC)	/* IO Context */
+{
+	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+		(void)VpdInit(pAC, IoC);
+	}
+	return(&pAC->vpd.v);
+}
+
+
+/*
+ *	Read the contents of the VPD EEPROM and copy it to the VPD
+ *	buffer if not already done.
+ *	Scan the VPD buffer for VPD keywords and create the VPD
+ *	keyword list by copying the keywords to 'buf', all after
+ *	each other and terminated with a '\0'.
+ *
+ * Exceptions:
+ *		o The Resource Type ID String (product name) is called "Name"
+ *		o The VPD end tags 'RV' and 'RW' are not listed
+ *
+ *	The number of copied keywords is counted in 'elements'.
+ *
+ * returns	0:	success
+ *		2:	buffer overflow, one or more keywords are missing
+ *		6:	fatal VPD error
+ *
+ *	example values after returning:
+ *
+ *		buf =	"Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
+ *		*len =		30
+ *		*elements =	 9
+ */
+int VpdKeys(
+SK_AC	*pAC,		/* Adapters Context */
+SK_IOC	IoC,		/* IO Context */
+char	*buf,		/* buffer where to copy the keywords */
+int		*len,		/* buffer length */
+int		*elements)	/* number of keywords returned */
+{
+	char *v;
+	int n;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
+
+	*elements = 0;
+	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+		if (VpdInit(pAC, IoC) != 0) {
+			*len = 0;
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("VPD Init Error, terminated\n"));
+			return(6);
+		}
+	}
+
+	if ((signed)SK_STRLEN(VPD_NAME) + 1 <= *len) {
+		v = pAC->vpd.vpd_buf;
+		SK_STRCPY(buf, VPD_NAME);
+		n = SK_STRLEN(VPD_NAME) + 1;
+		buf += n;
+		*elements = 1;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+			("'%c%c' ", v[0], v[1]));
+	}
+	else {
+		*len = 0;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("buffer overflow\n"));
+		return(2);
+	}
+
+	v += 3 + VPD_GET_RES_LEN(v) + 3;
+
+	for ( ; ; ) {
+		/* exit when reaching the "RW" Tag */
+		if (SK_MEMCMP(VPD_RW, v, 2) == 0) {
+			break;
+		}
+
+		if (SK_MEMCMP(VPD_RV, v, 2) == 0) {
+			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
+			continue;
+		}
+
+		if (n + 3 <= *len) {
+			SK_MEMCPY(buf, v, 2);
+			buf += 2;
+			*buf++ = '\0';
+			n += 3;
+			v += 3 + VPD_GET_VPD_LEN(v);
+			*elements += 1;
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+				("'%c%c' ", v[0], v[1]));
+		}
+		else {
+			*len = n;
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("buffer overflow\n"));
+			return(2);
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
+	*len = n;
+	return(0);
+}
+
+#endif /* !SK_SLIM */
+
+/*
+ *	Read the contents of the VPD EEPROM and copy it to the
+ *	VPD buffer if not already done. Search for the VPD keyword
+ *	'key' and copy its value to 'buf'. Add a terminating '\0'.
+ *	If the value does not fit into the buffer cut it after
+ *	'len' - 1 bytes.
+ *
+ * returns	0:	success
+ *		1:	keyword not found
+ *		2:	value string was cut
+ *		3:	VPD transfer timeout
+ *		6:	fatal VPD error
+ */
+int VpdRead(
+SK_AC		*pAC,	/* Adapters Context */
+SK_IOC		IoC,	/* IO Context */
+const char	*key,	/* keyword to read (e.g. "MN") */
+char		*buf,	/* buffer where to copy the keyword value */
+int			*len)	/* buffer length */
+{
+	SK_VPD_PARA *p, vp;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
+
+	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+		if (VpdInit(pAC, IoC) != 0) {
+			*len = 0;
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("VPD init error\n"));
+			return(6);
+		}
+	}
+
+	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
+		if (p->p_len > (*(unsigned *)len) - 1) {
+			p->p_len = *len - 1;
+		}
+		SK_MEMCPY(buf, p->p_val, p->p_len);
+		buf[p->p_len] = '\0';
+		*len = p->p_len;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+			("%c%c%c%c.., len = %d\n",
+			buf[0], buf[1], buf[2], buf[3], *len));
+	}
+	else {
+		*len = 0;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
+		return(1);
+	}
+	return(0);
+}
+
+#ifndef SK_SLIM
+/*
+ *	Check whether a given key may be written
+ *
+ * returns
+ *	SK_TRUE		Yes it may be written
+ *	SK_FALSE	No it may be written
+ */
+SK_BOOL VpdMayWrite(
+char	*key)	/* keyword to write (allowed values "Yx", "Vx") */
+{
+	if ((*key != 'Y' && *key != 'V') ||
+		key[1] < '0' || key[1] > 'Z' ||
+		(key[1] > '9' && key[1] < 'A') || SK_STRLEN(key) != 2) {
+
+		return(SK_FALSE);
+	}
+	return(SK_TRUE);
+}
+
+/*
+ *	Read the contents of the VPD EEPROM and copy it to the VPD
+ *	buffer if not already done. Insert/overwrite the keyword 'key'
+ *	in the VPD buffer. Cut the keyword value if it does not fit
+ *	into the VPD read / write area.
+ *
+ * returns	0:	success
+ *		2:	value string was cut
+ *		3:	VPD transfer timeout
+ *		4:	VPD full, keyword was not written
+ *		5:	keyword cannot be written
+ *		6:	fatal VPD error
+ */
+int VpdWrite(
+SK_AC		*pAC,	/* Adapters Context */
+SK_IOC		IoC,	/* IO Context */
+const char	*key,	/* keyword to write (allowed values "Yx", "Vx") */
+const char	*buf)	/* buffer where the keyword value can be read from */
+{
+	int len;		/* length of the keyword to write */
+	int rtv;		/* return code */
+	int rtv2;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
+		("VPD write %s = %s\n", key, buf));
+
+	if ((*key != 'Y' && *key != 'V') ||
+		key[1] < '0' || key[1] > 'Z' ||
+		(key[1] > '9' && key[1] < 'A') || SK_STRLEN(key) != 2) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("illegal key tag, keyword not written\n"));
+		return(5);
+	}
+
+	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+		if (VpdInit(pAC, IoC) != 0) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("VPD init error\n"));
+			return(6);
+		}
+	}
+
+	rtv = 0;
+	len = SK_STRLEN(buf);
+	if (len > VPD_MAX_LEN) {
+		/* cut it */
+		len = VPD_MAX_LEN;
+		rtv = 2;
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("keyword too long, cut after %d bytes\n", VPD_MAX_LEN));
+	}
+	if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("VPD write error\n"));
+		return(rtv2);
+	}
+
+	return(rtv);
+}
+
+/*
+ *	Read the contents of the VPD EEPROM and copy it to the
+ *	VPD buffer if not already done. Remove the VPD keyword
+ *	'key' from the VPD buffer.
+ *	Only the keywords in the read/write area can be deleted.
+ *	Keywords in the read only area cannot be deleted.
+ *
+ * returns	0:	success, keyword was removed
+ *		1:	keyword not found
+ *		5:	keyword cannot be deleted
+ *		6:	fatal VPD error
+ */
+int VpdDelete(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+char	*key)	/* keyword to read (e.g. "MN") */
+{
+	SK_VPD_PARA *p, vp;
+	char *etp;
+	int	vpd_size;
+
+	vpd_size = pAC->vpd.vpd_size;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD delete key %s\n", key));
+	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+		if (VpdInit(pAC, IoC) != 0) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("VPD init error\n"));
+			return(6);
+		}
+	}
+
+	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
+		if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
+			/* try to delete read only keyword */
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("cannot delete RO keyword\n"));
+			return(5);
+		}
+
+		etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
+
+		vpd_move_para(vp.p_val + vp.p_len, etp + 2,
+			- ((int)(vp.p_len + 3)));
+		if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
+			pAC->vpd.v.vpd_status &= ~VPD_VALID;
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("VPD encoding error\n"));
+			return(6);
+		}
+	}
+	else {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+			("keyword not found\n"));
+		return(1);
+	}
+
+	return(0);
+}
+
+/*
+ *	If the VPD buffer contains valid data write the VPD
+ *	read/write area back to the VPD EEPROM.
+ *
+ * returns	0:	success
+ *		2:	not supported
+ *		3:	VPD transfer timeout
+ */
+int VpdUpdate(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC)	/* IO Context */
+{
+	int vpd_size;
+
+	vpd_size = pAC->vpd.vpd_size;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
+	if (pAC->vpd.CfgInSpi) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("not supported"));
+		return(2);
+	}
+
+	if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
+		if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
+			vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("transfer timed out\n"));
+			return(3);
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
+	return(0);
+}
+
+/*
+ *	Read the contents of the VPD EEPROM and copy it to the VPD buffer
+ *	if not already done. If the keyword "VF" is not present it will be
+ *	created and the error log message will be stored to this keyword.
+ *	If "VF" is not present the error log message will be stored to the
+ *	keyword "VL". "VL" will created or overwritten if "VF" is present.
+ *	The VPD read/write area is saved to the VPD EEPROM.
+ *
+ * returns nothing, errors will be ignored.
+ */
+void VpdErrLog(
+SK_AC	*pAC,	/* Adapters Context */
+SK_IOC	IoC,	/* IO Context */
+char	*msg)	/* error log message */
+{
+	SK_VPD_PARA *v, vf;	/* VF */
+	int len;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
+		("VPD error log msg %s\n", msg));
+
+	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+		if (VpdInit(pAC, IoC) != 0) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+				("VPD init error\n"));
+			return;
+		}
+	}
+
+	len = SK_STRLEN(msg);
+	if (len > VPD_MAX_LEN) {
+		/* cut it */
+		len = VPD_MAX_LEN;
+	}
+	if ((v = vpd_find_para(pAC, VPD_VF, &vf)) != NULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("overwrite VL\n"));
+		(void)VpdSetupPara(pAC, VPD_VL, msg, len, VPD_RW_KEY, OWR_KEY);
+	}
+	else {
+		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("write VF\n"));
+		(void)VpdSetupPara(pAC, VPD_VF, msg, len, VPD_RW_KEY, ADD_KEY);
+	}
+
+	(void)VpdUpdate(pAC, IoC);
+}
+#endif /* !SK_SLIM */
+
diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
new file mode 100755
index 0000000..c3ec8c1
--- /dev/null
+++ b/drivers/net/sk98lin/skxmac2.c
@@ -0,0 +1,5747 @@
+/******************************************************************************
+ *
+ * Name:	skxmac2.c
+ * Project:	Gigabit Ethernet Adapters, Common Modules
+ * Version:	$Revision: 2.79 $
+ * Date:	$Date: 2007/07/26 11:45:58 $
+ * Purpose:	Contains functions to initialize the MACs and PHYs
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 1998-2002 SysKonnect.
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+
+/* typedefs *******************************************************************/
+
+/* BCOM PHY magic pattern list */
+typedef struct s_PhyHack {
+	int		PhyReg;		/* PHY register */
+	SK_U16	PhyVal;		/* Value to write */
+} BCOM_HACK;
+
+/* local variables ************************************************************/
+
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: skxmac2.c,v 2.79 2007/07/26 11:45:58 malthoff Exp $ (C) Marvell.";
+#endif
+
+#ifdef GENESIS
+BCOM_HACK BcomRegA1Hack[] = {
+ { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
+ { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
+ { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
+ { 0, 0 }
+};
+BCOM_HACK BcomRegC0Hack[] = {
+ { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
+ { 0x15, 0x0A04 }, { 0x18, 0x0420 },
+ { 0, 0 }
+};
+#endif
+
+/* function prototypes ********************************************************/
+#ifdef GENESIS
+static void	SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
+static void	SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
+static int	SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
+static int	SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
+#endif /* GENESIS */
+#ifdef YUKON
+static void	SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
+static int	SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
+#endif /* YUKON */
+#ifdef OTHER_PHY
+static void	SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
+static void	SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
+static int	SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
+static int	SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
+#endif /* OTHER_PHY */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmPhyRead() - Read from XMAC PHY register
+ *
+ * Description:	reads a 16-bit word from XMAC PHY or ext. PHY
+ *
+ * Returns:
+ *	nothing
+ */
+int SkXmPhyRead(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+int		Port,			/* Port Index (MAC_1 + n) */
+int		PhyReg,			/* Register Address (Offset) */
+SK_U16	SK_FAR *pVal)	/* Pointer to Value */
+{
+	SK_U16		Mmu;
+	SK_GEPORT	*pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* write the PHY register's address */
+	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
+
+	/* get the PHY register's value */
+	XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
+
+	if (pPrt->PhyType != SK_PHY_XMAC) {
+		do {
+			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+			/* wait until 'Ready' is set */
+		} while ((Mmu & XM_MMU_PHY_RDY) == 0);
+
+		/* get the PHY register's value */
+		XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
+	}
+
+	return(0);
+}	/* SkXmPhyRead */
+
+
+/******************************************************************************
+ *
+ *	SkXmPhyWrite() - Write to XMAC PHY register
+ *
+ * Description:	writes a 16-bit word to XMAC PHY or ext. PHY
+ *
+ * Returns:
+ *	nothing
+ */
+int SkXmPhyWrite(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	Val)		/* Value */
+{
+	SK_U16		Mmu;
+	SK_GEPORT	*pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PhyType != SK_PHY_XMAC) {
+		do {
+			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+			/* wait until 'Busy' is cleared */
+		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
+	}
+
+	/* write the PHY register's address */
+	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
+
+	/* write the PHY register's value */
+	XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
+
+	if (pPrt->PhyType != SK_PHY_XMAC) {
+		do {
+			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+			/* wait until 'Busy' is cleared */
+		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
+	}
+
+	return(0);
+}	/* SkXmPhyWrite */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkGmPhyRead() - Read from GPHY register
+ *
+ * Description:	reads a 16-bit word from GPHY through MDIO
+ *
+ * Returns:
+ *	0	o.k.
+ *	1	error during MDIO read
+ *	2	timeout
+ */
+int SkGmPhyRead(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+int		Port,			/* Port Index (MAC_1 + n) */
+int		PhyReg,			/* Register Address (Offset) */
+SK_U16	SK_FAR *pVal)	/* Pointer to Value */
+{
+	SK_U16	Word;
+	SK_U16	Ctrl;
+	SK_GEPORT	*pPrt;
+	SK_U32	StartTime;
+	SK_U32	CurrTime;
+	SK_U32	Delta;
+	SK_U32	TimeOut;
+	int		Rtv;
+
+	Rtv = 0;
+
+	*pVal = 0xffff;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* additional check for MDC/MDIO activity */
+	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+
+	if ((Ctrl & GM_SMI_CT_BUSY) != 0) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("SkGmPhyRead, Port: %d, Reg: %2d, Busy (Ctrl=0x%04X)\n",
+			 Port, PhyReg, Ctrl));
+
+		return(1);
+	}
+
+	/* set PHY-Register offset and 'Read' OpCode (= 1) */
+	Word = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
+		GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
+
+	GM_OUT16(IoC, Port, GM_SMI_CTRL, Word);
+
+	/* additional check for MDC/MDIO activity */
+	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+
+	if (Ctrl == 0xffff || (Ctrl & GM_SMI_CT_OP_RD) == 0) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("SkGmPhyRead, Port: %d, Reg: %2d, Error (Ctrl=0x%04X)\n",
+			 Port, PhyReg, Ctrl));
+
+		return(1);
+	}
+
+	Word |= GM_SMI_CT_BUSY;
+
+	/* get current value of timestamp timer */
+	SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime);
+
+	/* set timeout to 10 ms */
+	TimeOut = HW_MS_TO_TICKS(pAC, 10);
+
+	do {	/* wait until 'Busy' is cleared and 'ReadValid' is set */
+#ifdef VCPU
+		VCPUwaitTime(1000);
+#endif /* VCPU */
+
+		/* get current value of timestamp timer */
+		SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
+
+		if (CurrTime >= StartTime) {
+			Delta = CurrTime - StartTime;
+		}
+		else {
+			Delta = CurrTime + ~StartTime + 1;
+		}
+
+		if (Delta > TimeOut) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("SkGmPhyRead, Port: %d, Reg: %2d, Timeout (Ctrl=0x%04X)\n",
+				 Port, PhyReg, Ctrl));
+
+			Rtv = 2;
+			break;
+		}
+
+		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+
+		/* Error on reading SMI Control Register */
+		if (Ctrl == 0xffff) {
+			return(1);
+		}
+
+	} while ((Ctrl ^ Word) != (GM_SMI_CT_RD_VAL | GM_SMI_CT_BUSY));
+
+	GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
+
+	/* dummy read after GM_IN16() */
+	SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkGmPhyRead, Port: %d, Reg: %2d, Val = 0x%04X\n",
+		 Port, PhyReg, *pVal));
+
+#if defined(VCPU) || defined(SK_DIAG)
+	c_print("Read 0x%04X from PHY reg %u on port %c\n",
+		*pVal, PhyReg, 'A' + Port);
+#endif  /* VCPU */
+
+	return(Rtv);
+}	/* SkGmPhyRead */
+
+
+/******************************************************************************
+ *
+ *	SkGmPhyWrite() - Write to GPHY register
+ *
+ * Description:	writes a 16-bit word to GPHY through MDIO
+ *
+ * Returns:
+ *	0	o.k.
+ *	1	error during MDIO read
+ *	2	timeout
+ */
+int SkGmPhyWrite(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	Val)		/* Value */
+{
+	SK_U16	Ctrl;
+	SK_GEPORT	*pPrt;
+	SK_U32	StartTime;
+	SK_U32	CurrTime;
+	SK_U32	Delta;
+	SK_U32	TimeOut;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkGmPhyWrite, Port: %d, Reg: %2d, Val = 0x%04X\n",
+		 Port, PhyReg, Val));
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* write the PHY register's value */
+	GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
+
+#ifdef DEBUG
+	/* additional check for MDC/MDIO activity */
+	GM_IN16(IoC, Port, GM_SMI_DATA, &Ctrl);
+
+	if (Ctrl != Val) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("PHY write impossible on Port %d (Val=0x%04X)\n", Port, Ctrl));
+
+		return(1);
+	}
+#endif /* DEBUG */
+
+	/* set PHY-Register offset and 'Write' OpCode (= 0) */
+	Ctrl = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
+		GM_SMI_CT_REG_AD(PhyReg));
+
+	GM_OUT16(IoC, Port, GM_SMI_CTRL, Ctrl);
+
+	/* get current value of timestamp timer */
+	SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime);
+
+	/* set timeout to 10 ms */
+	TimeOut = HW_MS_TO_TICKS(pAC, 10);
+
+	do {	/* wait until 'Busy' is cleared */
+#ifdef VCPU
+		VCPUwaitTime(1000);
+#endif /* VCPU */
+
+		/* get current value of timestamp timer */
+		SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
+
+		if (CurrTime >= StartTime) {
+			Delta = CurrTime - StartTime;
+		}
+		else {
+			Delta = CurrTime + ~StartTime + 1;
+		}
+
+		if (Delta > TimeOut) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("PHY write timeout on Port %d (Ctrl=0x%04X)\n", Port, Ctrl));
+			return(2);
+		}
+
+		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+
+		/* Error on reading SMI Control Register */
+		if (Ctrl == 0xffff) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("PHY write error on Port %d (Ctrl=0x%04X)\n", Port, Ctrl));
+			return(1);
+		}
+
+	} while ((Ctrl & GM_SMI_CT_BUSY) != 0);
+
+	/* dummy read after GM_IN16() */
+	SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
+
+#if defined(VCPU) || defined(SK_DIAG)
+	c_print("Wrote 0x%04X to PHY reg %u on port %c\n",
+		Val, PhyReg, 'A' + Port);
+#endif /* VCPU || SK_DIAG */
+
+	return(0);
+}	/* SkGmPhyWrite */
+#endif /* YUKON */
+
+
+#ifdef SK_DIAG
+/******************************************************************************
+ *
+ *	SkGePhyRead() - Read from PHY register
+ *
+ * Description:	calls a read PHY routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGePhyRead(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	*pVal)		/* Pointer to Value */
+{
+	pAC->GIni.GIFunc.pFnMacPhyRead(pAC, IoC, Port, PhyReg, pVal);
+}	/* SkGePhyRead */
+
+
+/******************************************************************************
+ *
+ *	SkGePhyWrite() - Write to PHY register
+ *
+ * Description:	calls a write PHY routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGePhyWrite(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	Val)		/* Value */
+{
+	pAC->GIni.GIFunc.pFnMacPhyWrite(pAC, IoC, Port, PhyReg, Val);
+}	/* SkGePhyWrite */
+#endif /* SK_DIAG */
+
+
+/******************************************************************************
+ *
+ *	SkMacPromiscMode() - Enable / Disable Promiscuous Mode
+ *
+ * Description:
+ *	enables / disables promiscuous mode by setting Mode Register (XMAC) or
+ *	Receive Control Register (GMAC) dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacPromiscMode(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
+{
+#ifdef YUKON
+	SK_U16	RcReg;
+#endif
+#ifdef GENESIS
+	SK_U32	SK_FAR MdReg;
+#endif
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+		/* enable or disable promiscuous mode */
+		if (Enable) {
+			MdReg |= XM_MD_ENA_PROM;
+		}
+		else {
+			MdReg &= ~XM_MD_ENA_PROM;
+		}
+		/* setup Mode Register */
+		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+
+		/* enable or disable unicast and multicast filtering */
+		if (Enable) {
+			RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+		}
+		else {
+			RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+		}
+		/* setup Receive Control Register */
+		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
+	}
+#endif /* YUKON */
+
+}	/* SkMacPromiscMode*/
+
+
+/******************************************************************************
+ *
+ *	SkMacHashing() - Enable / Disable Hashing
+ *
+ * Description:
+ *	enables / disables hashing by setting Mode Register (XMAC) or
+ *	Receive Control Register (GMAC) dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacHashing(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
+{
+#ifdef YUKON
+	SK_U16	RcReg;
+#endif
+#ifdef GENESIS
+	SK_U32	SK_FAR MdReg;
+#endif
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+		/* enable or disable hashing */
+		if (Enable) {
+			MdReg |= XM_MD_ENA_HASH;
+		}
+		else {
+			MdReg &= ~XM_MD_ENA_HASH;
+		}
+		/* setup Mode Register */
+		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+
+		/* enable or disable multicast filtering */
+		if (Enable) {
+			RcReg |= GM_RXCR_MCF_ENA;
+		}
+		else {
+			RcReg &= ~GM_RXCR_MCF_ENA;
+		}
+		/* setup Receive Control Register */
+		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
+	}
+#endif /* YUKON */
+
+}	/* SkMacHashing*/
+
+
+#ifdef SK_DIAG
+/******************************************************************************
+ *
+ *	SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
+ *
+ * Description:
+ *	The features
+ *	 - FCS stripping,					SK_STRIP_FCS_ON/OFF
+ *	 - pad byte stripping,				SK_STRIP_PAD_ON/OFF
+ *	 - don't set XMR_FS_ERR in status	SK_LENERR_OK_ON/OFF
+ *	   for inrange length error frames
+ *	 - don't set XMR_FS_ERR in status	SK_BIG_PK_OK_ON/OFF
+ *		for frames > 1514 bytes
+ *	- enable Rx of own packets			SK_SELF_RX_ON/OFF
+ *
+ *	for incoming packets may be enabled/disabled by this function.
+ *	Additional modes may be added later.
+ *	Multiple modes can be enabled/disabled at the same time.
+ *	The new configuration is written to the Rx Command register immediately.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmSetRxCmd(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
+						SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
+{
+	SK_U16	OldRxCmd;
+	SK_U16	RxCmd;
+
+	XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
+
+	RxCmd = OldRxCmd;
+
+	switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
+	case SK_STRIP_FCS_ON:
+		RxCmd |= XM_RX_STRIP_FCS;
+		break;
+	case SK_STRIP_FCS_OFF:
+		RxCmd &= ~XM_RX_STRIP_FCS;
+		break;
+	}
+
+	switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
+	case SK_STRIP_PAD_ON:
+		RxCmd |= XM_RX_STRIP_PAD;
+		break;
+	case SK_STRIP_PAD_OFF:
+		RxCmd &= ~XM_RX_STRIP_PAD;
+		break;
+	}
+
+	switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
+	case SK_LENERR_OK_ON:
+		RxCmd |= XM_RX_LENERR_OK;
+		break;
+	case SK_LENERR_OK_OFF:
+		RxCmd &= ~XM_RX_LENERR_OK;
+		break;
+	}
+
+	switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
+	case SK_BIG_PK_OK_ON:
+		RxCmd |= XM_RX_BIG_PK_OK;
+		break;
+	case SK_BIG_PK_OK_OFF:
+		RxCmd &= ~XM_RX_BIG_PK_OK;
+		break;
+	}
+
+	switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
+	case SK_SELF_RX_ON:
+		RxCmd |= XM_RX_SELF_RX;
+		break;
+	case SK_SELF_RX_OFF:
+		RxCmd &= ~XM_RX_SELF_RX;
+		break;
+	}
+
+	/* Write the new mode to the Rx command register if required */
+	if (OldRxCmd != RxCmd) {
+		XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
+	}
+}	/* SkXmSetRxCmd */
+
+
+/******************************************************************************
+ *
+ *	SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
+ *
+ * Description:
+ *	The features
+ *	 - FCS (CRC) stripping,				SK_STRIP_FCS_ON/OFF
+ *	 - don't set GMR_FS_LONG_ERR		SK_BIG_PK_OK_ON/OFF
+ *		for frames > 1514 bytes
+ *	- enable Rx of own packets			SK_SELF_RX_ON/OFF
+ *
+ *	for incoming packets may be enabled/disabled by this function.
+ *	Additional modes may be added later.
+ *	Multiple modes can be enabled/disabled at the same time.
+ *	The new configuration is written to the Rx Command register immediately.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmSetRxCmd(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
+						SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
+{
+	SK_U16	RxCmd;
+
+	if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
+
+		GM_IN16(IoC, Port, GM_RX_CTRL, &RxCmd);
+
+		if ((Mode & SK_STRIP_FCS_ON) != 0) {
+			RxCmd |= GM_RXCR_CRC_DIS;
+		}
+		else {
+			RxCmd &= ~GM_RXCR_CRC_DIS;
+		}
+		/* Write the new mode to the Rx Control register */
+		GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
+	}
+
+	if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
+
+		GM_IN16(IoC, Port, GM_SERIAL_MODE, &RxCmd);
+
+		if ((Mode & SK_BIG_PK_OK_ON) != 0) {
+			RxCmd |= GM_SMOD_JUMBO_ENA;
+		}
+		else {
+			RxCmd &= ~GM_SMOD_JUMBO_ENA;
+		}
+		/* Write the new mode to the Serial Mode register */
+		GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
+	}
+}	/* SkGmSetRxCmd */
+
+
+/******************************************************************************
+ *
+ *	SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
+ *
+ * Description:	modifies the MAC's Rx Control reg. dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacSetRxCmd(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Mode)		/* Rx Mode */
+{
+	if (pAC->GIni.GIGenesis) {
+
+		SkXmSetRxCmd(pAC, IoC, Port, Mode);
+	}
+	else {
+
+		SkGmSetRxCmd(pAC, IoC, Port, Mode);
+	}
+
+}	/* SkMacSetRxCmd */
+
+
+/******************************************************************************
+ *
+ *	SkMacCrcGener() - Enable / Disable CRC Generation
+ *
+ * Description:	enables / disables CRC generation dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacCrcGener(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
+{
+	SK_U16	Word;
+
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN16(IoC, Port, XM_TX_CMD, &Word);
+
+		if (Enable) {
+			Word &= ~XM_TX_NO_CRC;
+		}
+		else {
+			Word |= XM_TX_NO_CRC;
+		}
+		/* setup Tx Command Register */
+		XM_OUT16(IoC, Port, XM_TX_CMD, Word);
+	}
+	else {
+
+		GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
+
+		if (Enable) {
+			Word &= ~GM_TXCR_CRC_DIS;
+		}
+		else {
+			Word |= GM_TXCR_CRC_DIS;
+		}
+		/* setup Tx Control Register */
+		GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
+	}
+
+}	/* SkMacCrcGener*/
+
+#endif /* SK_DIAG */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmClrExactAddr() - Clear Exact Match Address Registers
+ *
+ * Description:
+ *	All Exact Match Address registers of the XMAC 'Port' will be
+ *	cleared starting with 'StartNum' up to (and including) the
+ *	Exact Match address number of 'StopNum'.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkXmClrExactAddr(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		StartNum,	/* Begin with this Address Register Index (0..15) */
+int		StopNum)	/* Stop after finished with this Register Idx (0..15) */
+{
+	int		i;
+	SK_U16	ZeroAddr[3] = {0, 0, 0};
+
+	if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
+		StartNum > StopNum) {
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
+		return;
+	}
+
+	for (i = StartNum; i <= StopNum; i++) {
+		XM_OUTADDR(IoC, Port, XM_EXM(i), ZeroAddr);
+	}
+}	/* SkXmClrExactAddr */
+#endif /* GENESIS */
+
+
+/******************************************************************************
+ *
+ *	SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
+ *
+ * Description:
+ *	Flush the transmit FIFO of the MAC specified by the index 'Port'
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacFlushTxFifo(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+#ifdef GENESIS
+	SK_U32	SK_FAR MdReg;
+
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+		/* no way to flush the FIFO we have to issue a reset */
+		/* TBD */
+	}
+#endif /* YUKON */
+
+}	/* SkMacFlushTxFifo */
+
+
+/******************************************************************************
+ *
+ *	SkMacFlushRxFifo() - Flush the MAC's receive FIFO
+ *
+ * Description:
+ *	Flush the receive FIFO of the MAC specified by the index 'Port'
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacFlushRxFifo(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+#ifdef GENESIS
+	SK_U32	SK_FAR MdReg;
+
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+		/* no way to flush the FIFO we have to issue a reset */
+		/* TBD */
+	}
+#endif /* YUKON */
+
+}	/* SkMacFlushRxFifo */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmSoftRst() - Do a XMAC software reset
+ *
+ * Description:
+ *	The PHY registers should not be destroyed during this
+ *	kind of software reset. Therefore the XMAC Software Reset
+ *	(XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
+ *
+ *	The software reset is done by
+ *		- disabling the Rx and Tx state machine,
+ *		- resetting the statistics module,
+ *		- clear all other significant XMAC Mode,
+ *		  Command, and Control Registers
+ *		- clearing the Hash Register and the
+ *		  Exact Match Address registers, and
+ *		- flushing the XMAC's Rx and Tx FIFOs.
+ *
+ * Note:
+ *	Another requirement when stopping the XMAC is to
+ *	avoid sending corrupted frames on the network.
+ *	Disabling the Tx state machine will NOT interrupt
+ *	the currently transmitted frame. But we must take care
+ *	that the Tx FIFO is cleared AFTER the current frame
+ *	is complete sent to the network.
+ *
+ *	It takes about 12ns to send a frame with 1538 bytes.
+ *	One PCI clock goes at least 15ns (66MHz). Therefore
+ *	after reading XM_GP_PORT back, we are sure that the
+ *	transmitter is disabled AND idle. And this means
+ *	we may flush the transmit FIFO now.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmSoftRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U16	ZeroAddr[4] = {0, 0, 0, 0};
+
+	/* reset the statistics module */
+	XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
+
+	/* disable all XMAC IRQs */
+	XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
+
+	XM_OUT32(IoC, Port, XM_MODE, 0);		/* clear Mode Reg */
+
+	XM_OUT16(IoC, Port, XM_TX_CMD, 0);		/* reset TX CMD Reg */
+	XM_OUT16(IoC, Port, XM_RX_CMD, 0);		/* reset RX CMD Reg */
+
+	/* disable all PHY IRQs */
+	switch (pAC->GIni.GP[Port].PhyType) {
+	case SK_PHY_BCOM:
+			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
+			break;
+#ifdef OTHER_PHY
+		case SK_PHY_LONE:
+			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
+			break;
+		case SK_PHY_NAT:
+			/* todo: National
+			 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
+			break;
+#endif /* OTHER_PHY */
+	}
+
+	/* clear the Hash Register */
+	XM_OUTHASH(IoC, Port, XM_HSM, ZeroAddr);
+
+	/* clear the Exact Match Address registers */
+	SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
+
+	/* clear the Source Check Address registers */
+	XM_OUTHASH(IoC, Port, XM_SRC_CHK, ZeroAddr);
+
+}	/* SkXmSoftRst */
+
+
+/******************************************************************************
+ *
+ *	SkXmHardRst() - Do a XMAC hardware reset
+ *
+ * Description:
+ *	The XMAC of the specified 'Port' and all connected devices
+ *	(PHY and SERDES) will receive a reset signal on its *Reset pins.
+ *	External PHYs must be reset by clearing a bit in the GPIO register
+ *  (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
+ *
+ * ATTENTION:
+ * 	It is absolutely necessary to reset the SW_RST Bit first
+ *	before calling this function.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmHardRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U32	Reg;
+	int		i;
+	int		TOut;
+	SK_U16	Word;
+
+	for (i = 0; i < 4; i++) {
+		/* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
+		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+
+		TOut = 0;
+		do {
+			if (TOut++ > 10000) {
+				/*
+				 * Adapter seems to be in RESET state.
+				 * Registers cannot be written.
+				 */
+				return;
+			}
+
+			SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+
+			SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
+
+		} while ((Word & MFF_SET_MAC_RST) == 0);
+	}
+
+	/* For external PHYs there must be special handling */
+	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
+
+		SK_IN32(IoC, B2_GP_IO, &Reg);
+
+		if (Port == 0) {
+			Reg |= GP_DIR_0;	/* set to output */
+			Reg &= ~GP_IO_0;	/* set PHY reset (active low) */
+		}
+		else {
+			Reg |= GP_DIR_2;	/* set to output */
+			Reg &= ~GP_IO_2;	/* set PHY reset (active low) */
+		}
+		/* reset external PHY */
+		SK_OUT32(IoC, B2_GP_IO, Reg);
+
+		/* short delay */
+		SK_IN32(IoC, B2_GP_IO, &Reg);
+	}
+}	/* SkXmHardRst */
+
+
+/******************************************************************************
+ *
+ *	SkXmClearRst() - Release the PHY & XMAC reset
+ *
+ * Description:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmClearRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U32	DWord;
+
+	/* clear HW reset */
+	SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+
+	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
+
+		SK_IN32(IoC, B2_GP_IO, &DWord);
+
+		if (Port == 0) {
+			DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
+		}
+		else {
+			DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
+		}
+		/* Clear PHY reset */
+		SK_OUT32(IoC, B2_GP_IO, DWord);
+
+		/* enable GMII interface */
+		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
+	}
+}	/* SkXmClearRst */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkGmSoftRst() - Do a GMAC software reset
+ *
+ * Description:
+ *	The GPHY registers should not be destroyed during this
+ *	kind of software reset.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmSoftRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U16	EmptyHash[4] = { 0x0000, 0x0000, 0x0000, 0x0000 };
+	SK_U16	RxCtrl;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkGmSoftRst: Port %d\n", Port));
+
+	/* reset the statistics module */
+	(void)SkGmResetCounter(pAC, IoC, Port);
+
+	/* disable all GMAC IRQs */
+	SK_OUT8(IoC, MR_ADDR(Port, GMAC_IRQ_MSK), 0);
+
+	if (pAC->GIni.GP[Port].PState != SK_PRT_RESET) {
+		/* disable all PHY IRQs */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+	}
+
+	/* clear the Hash Register */
+	GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
+
+	/* enable Unicast and Multicast filtering */
+	GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
+
+	GM_OUT16(IoC, Port, GM_RX_CTRL, RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+
+}	/* SkGmSoftRst */
+
+
+/******************************************************************************
+ *
+ *	SkGmHardRst() - Do a GMAC hardware reset
+ *
+ * Description:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmHardRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U32	DWord;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkGmHardRst: Port %d\n", Port));
+
+	/* WA code for COMA mode */
+	if (pAC->GIni.GIYukonLite &&
+		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
+
+		SK_IN32(IoC, B2_GP_IO, &DWord);
+
+		DWord |= (GP_DIR_9 | GP_IO_9);
+
+		/* set PHY reset */
+		SK_OUT32(IoC, B2_GP_IO, DWord);
+	}
+
+	/* set GPHY Control reset */
+	SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET);
+
+	if (!pAC->GIni.GIAsfEnabled) {
+		/* set GMAC Control reset */
+		SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_SET);
+	}
+
+}	/* SkGmHardRst */
+
+
+/******************************************************************************
+ *
+ *	SkGmClearRst() - Release the GPHY & GMAC reset
+ *
+ * Description:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmClearRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U32	DWord;
+#ifdef SK_DIAG
+	SK_U16	PhyId0;
+	SK_U16	PhyId1;
+	SK_U16	Word;
+#endif /* SK_DIAG */
+
+#ifdef DEBUG
+	SK_U8	Byte;
+#endif /* DEBUG */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkGmClearRst: Port %d\n", Port));
+
+	/* WA code for COMA mode */
+	if (pAC->GIni.GIYukonLite &&
+		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
+
+		SK_IN32(IoC, B2_GP_IO, &DWord);
+
+		DWord |= GP_DIR_9;		/* set to output */
+		DWord &= ~GP_IO_9;		/* clear PHY reset (active high) */
+
+		/* clear PHY reset */
+		SK_OUT32(IoC, B2_GP_IO, DWord);
+	}
+
+#ifdef VCPU
+	/* set MAC Reset before PHY reset is set */
+	SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_SET);
+#endif /* VCPU */
+
+	if (CHIP_ID_YUKON_2(pAC)) {
+		/* set GPHY Control reset */
+		SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET);
+
+		/* release GPHY Control reset */
+		SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_CLR);
+
+#ifdef DEBUG
+		/* additional check for PEX */
+		SK_IN8(IoC, GPHY_CTRL, &Byte);
+
+		Byte &= GPC_RST_CLR | GPC_RST_SET;
+
+		if (pAC->GIni.GIPciBus == SK_PEX_BUS && Byte != GPC_RST_CLR) {
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("Error on PEX-bus after GPHY reset (GPHY Ctrl=0x%02X)\n",
+				Byte));
+		}
+#endif /* DEBUG */
+	}
+	else {
+		/* set HWCFG_MODE */
+		DWord = GPC_INT_POL | GPC_DIS_FC | GPC_DIS_SLEEP |
+			GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
+			(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
+			GPC_HWCFG_GMII_FIB);
+
+		/* set GPHY Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
+
+		/* release GPHY Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
+	}
+
+#ifdef VCPU
+	/* wait for internal initialization of GPHY */
+	VCPUprintf(0, "Waiting until PHY %d is ready to initialize\n", Port);
+	VCpuWait(10000);
+#endif /* VCPU */
+
+	/* clear GMAC Control reset */
+	SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
+
+#ifdef VCPU
+	/* wait for stable GMAC clock */
+	VCpuWait(9000);
+#endif /* VCPU */
+
+#ifdef SK_DIAG
+	if (HW_FEATURE(pAC, HWF_WA_DEV_472) && Port == MAC_2) {
+
+		/* clear GMAC 1 Control reset */
+		SK_OUT8(IoC, MR_ADDR(MAC_1, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
+
+		do {
+			/* set GMAC 2 Control reset */
+			SK_OUT8(IoC, MR_ADDR(MAC_2, GMAC_CTRL), (SK_U8)GMC_RST_SET);
+
+			/* clear GMAC 2 Control reset */
+			SK_OUT8(IoC, MR_ADDR(MAC_2, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
+
+			SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_ID0, &PhyId0);
+
+			SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_ID1, &PhyId1);
+
+			SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_INT_MASK, &Word);
+
+		} while (Word != 0 || PhyId0 != PHY_MARV_ID0_VAL ||
+				 PhyId1 != PHY_MARV_ID1_Y2);
+	}
+#endif /* SK_DIAG */
+
+#ifdef VCPU
+	VCpuWait(2000);
+
+	SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
+
+	SK_IN32(IoC, B0_ISRC, &DWord);
+#endif /* VCPU */
+
+}	/* SkGmClearRst */
+#endif /* YUKON */
+
+
+/******************************************************************************
+ *
+ *	SkMacSoftRst() - Do a MAC software reset
+ *
+ * Description:	calls a MAC software reset routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacSoftRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	/* disable receiver and transmitter */
+	SkMacRxTxDisable(pAC, IoC, Port);
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		SkXmSoftRst(pAC, IoC, Port);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		SkGmSoftRst(pAC, IoC, Port);
+	}
+#endif /* YUKON */
+
+	/* flush the MAC's Rx and Tx FIFOs */
+	SkMacFlushTxFifo(pAC, IoC, Port);
+
+	SkMacFlushRxFifo(pAC, IoC, Port);
+
+	pAC->GIni.GP[Port].PState = SK_PRT_STOP;
+
+}	/* SkMacSoftRst */
+
+
+/******************************************************************************
+ *
+ *	SkMacHardRst() - Do a MAC hardware reset
+ *
+ * Description:	calls a MAC hardware reset routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacHardRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		SkXmHardRst(pAC, IoC, Port);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		SkGmHardRst(pAC, IoC, Port);
+	}
+#endif /* YUKON */
+
+	pAC->GIni.GP[Port].PHWLinkUp = SK_FALSE;
+
+	pAC->GIni.GP[Port].PState = SK_PRT_RESET;
+
+}	/* SkMacHardRst */
+
+#ifndef SK_SLIM
+/******************************************************************************
+ *
+ *	SkMacClearRst() - Clear the MAC reset
+ *
+ * Description:	calls a clear MAC reset routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacClearRst(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		SkXmClearRst(pAC, IoC, Port);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		SkGmClearRst(pAC, IoC, Port);
+	}
+#endif /* YUKON */
+
+}	/* SkMacClearRst */
+#endif /* !SK_SLIM */
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmInitMac() - Initialize the XMAC II
+ *
+ * Description:
+ *	Initialize the XMAC of the specified port.
+ *	The XMAC must be reset or stopped before calling this function.
+ *
+ * Note:
+ *	The XMAC's Rx and Tx state machine is still disabled when returning.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkXmInitMac(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	int			i;
+	SK_U16		SWord;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PState == SK_PRT_STOP) {
+		/* Verify that the reset bit is cleared */
+		SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
+
+		if ((SWord & MFF_SET_MAC_RST) != 0) {
+			/* PState does not match HW state */
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+				("SkXmInitMac: PState does not match HW state"));
+			/* Correct it */
+			pPrt->PState = SK_PRT_RESET;
+		}
+	}
+
+	if (pPrt->PState == SK_PRT_RESET) {
+
+		SkXmClearRst(pAC, IoC, Port);
+
+		if (pPrt->PhyType != SK_PHY_XMAC) {
+			/* read Id from external PHY (all have the same address) */
+			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
+
+			/*
+			 * Optimize MDIO transfer by suppressing preamble.
+			 * Must be done AFTER first access to BCOM chip.
+			 */
+			XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
+
+			XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
+
+			if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
+				/*
+				 * Workaround BCOM Errata for the C0 type.
+				 * Write magic patterns to reserved registers.
+				 */
+				i = 0;
+				while (BcomRegC0Hack[i].PhyReg != 0) {
+					SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
+						BcomRegC0Hack[i].PhyVal);
+					i++;
+				}
+			}
+			else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
+				/*
+				 * Workaround BCOM Errata for the A1 type.
+				 * Write magic patterns to reserved registers.
+				 */
+				i = 0;
+				while (BcomRegA1Hack[i].PhyReg != 0) {
+					SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
+						BcomRegA1Hack[i].PhyVal);
+					i++;
+				}
+			}
+
+			/*
+			 * Workaround BCOM Errata (#10523) for all BCom PHYs.
+			 * Disable Power Management after reset.
+			 */
+			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
+
+			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+				(SK_U16)(SWord | PHY_B_AC_DIS_PM));
+
+			/* PHY LED initialization is done in SkGeXmitLED() */
+		}
+
+		/* Dummy read the Interrupt source register */
+		XM_IN16(IoC, Port, XM_ISRC, &SWord);
+
+		/*
+		 * The auto-negotiation process starts immediately after
+		 * clearing the reset. The auto-negotiation process should be
+		 * started by the SIRQ, therefore stop it here immediately.
+		 */
+		SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
+	}
+
+	/*
+	 * configure the XMACs Station Address
+	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
+	 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
+	 */
+	for (i = 0; i < 3; i++) {
+		/*
+		 * The following 2 statements are together endianess
+		 * independent. Remember this when changing.
+		 */
+		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
+
+		XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
+	}
+
+	/* Tx Inter Packet Gap (XM_TX_IPG):	use default */
+	/* Tx High Water Mark (XM_TX_HI_WM):	use default */
+	/* Tx Low Water Mark (XM_TX_LO_WM):	use default */
+	/* Host Request Threshold (XM_HT_THR):	use default */
+	/* Rx Request Threshold (XM_RX_THR):	use default */
+	/* Rx Low Water Mark (XM_RX_LO_WM):	use default */
+
+	/* configure Rx High Water Mark (XM_RX_HI_WM) */
+	XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
+
+	/* Configure Tx Request Threshold */
+	SWord = SK_XM_THR_SL;				/* for single port */
+
+	if (pAC->GIni.GIMacsFound > 1) {
+		switch (pPrt->PPortUsage) {
+		case SK_RED_LINK:
+			SWord = SK_XM_THR_REDL;		/* redundant link */
+			break;
+		case SK_MUL_LINK:
+			SWord = SK_XM_THR_MULL;		/* load balancing */
+			break;
+		case SK_JUMBO_LINK:
+			SWord = SK_XM_THR_JUMBO;	/* jumbo frames */
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
+			break;
+		}
+	}
+	XM_OUT16(IoC, Port, XM_TX_THR, SWord);
+
+	/* setup register defaults for the Tx Command Register */
+	XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
+
+	/* setup register defaults for the Rx Command Register */
+	SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
+
+	if (pPrt->PPortUsage == SK_JUMBO_LINK) {
+		SWord |= XM_RX_BIG_PK_OK;
+	}
+
+	if (pPrt->PLinkMode == SK_LMODE_HALF) {
+		/*
+		 * If in manual half duplex mode the other side might be in
+		 * full duplex mode, so ignore if a carrier extension is not seen
+		 * on frames received
+		 */
+		SWord |= XM_RX_DIS_CEXT;
+	}
+
+	XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
+
+	/*
+	 * setup register defaults for the Mode Register
+	 *	- Don't strip error frames to avoid Store & Forward
+	 *	  on the Rx side.
+	 *	- Enable 'Check Station Address' bit
+	 *	- Enable 'Check Address Array' bit
+	 */
+	XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
+
+	/*
+	 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
+	 *	- Enable all bits excepting 'Octets Rx OK Low CntOv'
+	 *	  and 'Octets Rx OK Hi Cnt Ov'.
+	 */
+	XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
+
+	/*
+	 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
+	 *	- Enable all bits excepting 'Octets Tx OK Low CntOv'
+	 *	  and 'Octets Tx OK Hi Cnt Ov'.
+	 */
+	XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
+
+	/*
+	 * Do NOT init XMAC interrupt mask here.
+	 * All interrupts remain disable until link comes up!
+	 */
+
+	/*
+	 * Any additional configuration changes may be done now.
+	 * The last action is to enable the Rx and Tx state machine.
+	 * This should be done after the auto-negotiation process
+	 * has been completed successfully.
+	 */
+}	/* SkXmInitMac */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkGmInitMac() - Initialize the GMAC
+ *
+ * Description:
+ *	Initialize the GMAC of the specified port.
+ *	The GMAC must be reset or stopped before calling this function.
+ *
+ * Note:
+ *	The GMAC's Rx and Tx state machine is still disabled when returning.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGmInitMac(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	int			i;
+	SK_U16		SWord;
+	SK_U32		DWord;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("SkGmInitMac: Port %d, PState = %d, PLinkSpeed = %d\n",
+		 Port, pPrt->PState, pPrt->PLinkSpeed));
+
+	if (pPrt->PState == SK_PRT_STOP) {
+		/* Verify that the reset bit is cleared */
+		SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
+
+		if ((DWord & GMC_RST_SET) != 0) {
+			/* PState does not match HW state */
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("SkGmInitMac: PState does not match HW state"));
+			/* Correct it */
+			pPrt->PState = SK_PRT_RESET;
+		}
+		else {
+			/* enable PHY interrupts */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
+				(SK_U16)PHY_M_DEF_MSK);
+		}
+	}
+
+	if (pPrt->PState == SK_PRT_RESET) {
+
+		SkGmHardRst(pAC, IoC, Port);
+
+		SkGmClearRst(pAC, IoC, Port);
+
+#ifndef SK_SLIM
+		if (HW_FEATURE(pAC, HWF_FORCE_AUTO_NEG) &&
+			pPrt->PLinkModeConf < SK_LMODE_AUTOHALF) {
+			/* Force Auto-Negotiation */
+			pPrt->PLinkMode = (pPrt->PLinkModeConf == SK_LMODE_FULL) ?
+				SK_LMODE_AUTOBOTH : SK_LMODE_AUTOHALF;
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("SkGmInitMac: Force Auto-Negotiation, PLinkMode = %d",
+				pPrt->PLinkMode));
+		}
+#endif /* !SK_SLIM */
+
+		/* Auto-negotiation ? */
+		if (pPrt->PLinkMode == SK_LMODE_HALF ||
+			 pPrt->PLinkMode == SK_LMODE_FULL) {
+			/* Auto-negotiation disabled */
+
+			/* get General Purpose Control */
+			GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
+
+			/* disable auto-update for speed, duplex and flow-control */
+			SWord |= GM_GPCR_AU_ALL_DIS;
+
+			/* setup General Purpose Control Register */
+			GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+
+			SWord = GM_GPCR_AU_ALL_DIS;
+		}
+		else {
+			SWord = 0;
+		}
+
+		/* speed settings */
+		switch (pPrt->PLinkSpeed) {
+		case SK_LSPEED_AUTO:
+		case SK_LSPEED_1000MBPS:
+			if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+
+				SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
+			}
+			break;
+		case SK_LSPEED_100MBPS:
+			SWord |= GM_GPCR_SPEED_100;
+			break;
+		case SK_LSPEED_10MBPS:
+			break;
+		}
+
+		/* duplex settings */
+		if (pPrt->PLinkMode != SK_LMODE_HALF) {
+			/* set full duplex */
+			SWord |= GM_GPCR_DUP_FULL;
+		}
+
+		/* flow-control settings */
+		switch (pPrt->PFlowCtrlMode) {
+		case SK_FLOW_MODE_NONE:
+			/* disable Tx & Rx flow-control */
+			SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+			break;
+		case SK_FLOW_MODE_LOC_SEND:
+			/* disable Rx flow-control */
+			SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+			break;
+		case SK_FLOW_MODE_SYMMETRIC:
+		case SK_FLOW_MODE_SYM_OR_REM:
+			/* enable Tx & Rx flow-control */
+			break;
+		}
+
+		/* setup General Purpose Control Register */
+		GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+
+		/* dummy read the Interrupt Source Register */
+		SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &SWord);
+
+#ifndef VCPU
+		SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
+#endif /* !VCPU */
+	}
+
+#ifndef VCPU	/* saves some time in co-sim */
+	(void)SkGmResetCounter(pAC, IoC, Port);
+#endif
+
+	/* setup Transmit Control Register */
+	GM_OUT16(IoC, Port, GM_TX_CTRL, (SK_U16)TX_COL_THR(pPrt->PMacColThres));
+
+	/* setup Receive Control Register */
+	SWord = GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | GM_RXCR_CRC_DIS;
+
+	GM_OUT16(IoC, Port, GM_RX_CTRL, SWord);
+
+	/* setup Transmit Flow Control Register */
+	GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
+
+	/* setup Transmit Parameter Register */
+#ifdef VCPU
+	GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
+#endif /* VCPU */
+
+	SWord = (SK_U16)(TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
+		TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
+		TX_IPG_JAM_DATA(pPrt->PMacJamIpgData) |
+		TX_BACK_OFF_LIM(pPrt->PMacBackOffLim));
+
+	GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
+
+	/* configure the Serial Mode Register */
+	SWord = (SK_U16)(DATA_BLIND_VAL(pPrt->PMacDataBlind) |
+		GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData));
+
+	if (pPrt->PMacLimit4) {
+		/* reset of collision counter after 4 consecutive collisions */
+		SWord |= GM_SMOD_LIMIT_4;
+	}
+
+	if (pPrt->PPortUsage == SK_JUMBO_LINK) {
+		/* enable jumbo mode (Max. Frame Length = 9018) */
+		SWord |= GM_SMOD_JUMBO_ENA;
+	}
+
+	GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
+
+	/*
+	 * configure the GMACs Station Addresses
+	 * in PROM you can find our addresses at:
+	 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
+	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
+	 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
+	 */
+
+	for (i = 0; i < 3; i++) {
+		/*
+		 * The following 2 statements are together endianess
+		 * independent. Remember this when changing.
+		 */
+		/* physical address: will be used for pause frames */
+		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
+
+#ifdef WA_DEV_16
+		/* WA for deviation #16 */
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
+			/* swap the address bytes */
+			SWord = ((SWord & 0xff00) >> 8)	| ((SWord & 0x00ff) << 8);
+
+			/* write to register in reversed order */
+			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
+		}
+		else {
+			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+		}
+#else
+		GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+#endif /* WA_DEV_16 */
+
+		/* virtual address: will be used for data */
+		SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
+
+		GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
+
+		/* reset Multicast filtering Hash registers 1-3 */
+		GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + i * 4, 0);
+	}
+
+	/* reset Multicast filtering Hash register 4 */
+	GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
+
+	/* enable interrupt mask for counter overflows */
+	GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
+	GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
+	GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
+
+	pPrt->PState = SK_PRT_STOP;
+
+}	/* SkGmInitMac */
+#endif /* YUKON */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmInitDupMd() - Initialize the XMACs Duplex Mode
+ *
+ * Description:
+ *	This function initializes the XMACs Duplex Mode.
+ *	It should be called after successfully finishing
+ *	the Auto-negotiation Process
+ *
+ * Returns:
+ *	nothing
+ */
+void SkXmInitDupMd(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	switch (pAC->GIni.GP[Port].PLinkModeStatus) {
+	case SK_LMODE_STAT_AUTOHALF:
+	case SK_LMODE_STAT_HALF:
+		/* Configuration Actions for Half Duplex Mode */
+		/*
+		 * XM_BURST = default value. We are probable not quick
+		 * 	enough at the 'XMAC' bus to burst 8kB.
+		 *	The XMAC stops bursting if no transmit frames
+		 *	are available or the burst limit is exceeded.
+		 */
+		/* XM_TX_RT_LIM = default value (15) */
+		/* XM_TX_STIME = default value (0xff = 4096 bit times) */
+		break;
+	case SK_LMODE_STAT_AUTOFULL:
+	case SK_LMODE_STAT_FULL:
+		/* Configuration Actions for Full Duplex Mode */
+		/*
+		 * The duplex mode is configured by the PHY,
+		 * therefore it seems to be that there is nothing
+		 * to do here.
+		 */
+		break;
+	case SK_LMODE_STAT_UNKNOWN:
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
+		break;
+	}
+}	/* SkXmInitDupMd */
+
+
+/******************************************************************************
+ *
+ *	SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
+ *
+ * Description:
+ *	This function initializes the Pause Mode which should
+ *	be used for this port.
+ *	It should be called after successfully finishing
+ *	the Auto-negotiation Process
+ *
+ * Returns:
+ *	nothing
+ */
+void SkXmInitPauseMd(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U32	SK_FAR DWord;
+	SK_U16		Word;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+
+	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
+		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
+
+		/* disable Pause Frame Reception */
+		Word |= XM_MMU_IGN_PF;
+	}
+	else {
+		/*
+		 * enabling pause frame reception is required for 1000BT
+		 * because the XMAC is not reset if the link is going down
+		 */
+		/* enable Pause Frame Reception */
+		Word &= ~XM_MMU_IGN_PF;
+	}
+
+	XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
+
+	XM_IN32(IoC, Port, XM_MODE, &DWord);
+
+	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
+		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
+
+		/*
+		 * Configure Pause Frame Generation
+		 * Use internal and external Pause Frame Generation.
+		 * Sending pause frames is edge triggered.
+		 * Send a Pause frame with the maximum pause time if
+		 * internal oder external FIFO full condition occurs.
+		 * Send a zero pause time frame to re-start transmission.
+		 */
+
+		/* XM_PAUSE_DA = '010000C28001' (default) */
+
+		/* XM_MAC_PTIME = 0xffff (maximum) */
+		/* remember this value is defined in big endian (!) */
+		XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
+
+		/* set Pause Mode in Mode Register */
+		DWord |= XM_PAUSE_MODE;
+
+		/* set Pause Mode in MAC Rx FIFO */
+		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
+	}
+	else {
+		/*
+		 * disable pause frame generation is required for 1000BT
+		 * because the XMAC is not reset if the link is going down
+		 */
+		/* disable Pause Mode in Mode Register */
+		DWord &= ~XM_PAUSE_MODE;
+
+		/* disable Pause Mode in MAC Rx FIFO */
+		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
+	}
+
+	XM_OUT32(IoC, Port, XM_MODE, DWord);
+}	/* SkXmInitPauseMd*/
+
+
+/******************************************************************************
+ *
+ *	SkXmInitPhyXmac() - Initialize the XMAC PHY registers
+ *
+ * Description:	initializes all the XMACs PHY registers
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmInitPhyXmac(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	DoLoop)		/* Should a PHY LoopBack be set-up? */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		Ctrl;
+
+	pPrt = &pAC->GIni.GP[Port];
+	Ctrl = 0;
+
+	/* Auto-negotiation ? */
+	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyXmac: no auto-negotiation Port %d\n", Port));
+		/* set DuplexMode in Config register */
+		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+			Ctrl |= PHY_CT_DUP_MD;
+		}
+
+		/*
+		 * Do NOT enable Auto-negotiation here. This would hold
+		 * the link down because no IDLEs are transmitted
+		 */
+	}
+	else {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyXmac: with auto-negotiation Port %d\n", Port));
+		/* set Auto-negotiation advertisement */
+
+		/* set Full/half duplex capabilities */
+		switch (pPrt->PLinkMode) {
+		case SK_LMODE_AUTOHALF:
+			Ctrl |= PHY_X_AN_HD;
+			break;
+		case SK_LMODE_AUTOFULL:
+			Ctrl |= PHY_X_AN_FD;
+			break;
+		case SK_LMODE_AUTOBOTH:
+			Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+				SKERR_HWI_E015MSG);
+		}
+
+		/* set Flow-control capabilities */
+		switch (pPrt->PFlowCtrlMode) {
+		case SK_FLOW_MODE_NONE:
+			Ctrl |= PHY_X_P_NO_PAUSE;
+			break;
+		case SK_FLOW_MODE_LOC_SEND:
+			Ctrl |= PHY_X_P_ASYM_MD;
+			break;
+		case SK_FLOW_MODE_SYMMETRIC:
+			Ctrl |= PHY_X_P_SYM_MD;
+			break;
+		case SK_FLOW_MODE_SYM_OR_REM:
+			Ctrl |= PHY_X_P_BOTH_MD;
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+				SKERR_HWI_E016MSG);
+		}
+
+		/* Write AutoNeg Advertisement Register */
+		SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
+
+		/* Restart Auto-negotiation */
+		Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
+	}
+
+	if (DoLoop) {
+		/* set the PHY Loopback bit, too */
+		Ctrl |= PHY_CT_LOOP;
+	}
+
+	/* Write to the PHY control register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
+}	/* SkXmInitPhyXmac */
+
+
+/******************************************************************************
+ *
+ *	SkXmInitPhyBcom() - Initialize the Broadcom PHY registers
+ *
+ * Description:	initializes all the Broadcom PHY registers
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmInitPhyBcom(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	DoLoop)		/* Should a PHY LoopBack be set-up? */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		Ctrl1;
+	SK_U16		Ctrl2;
+	SK_U16		Ctrl3;
+	SK_U16		Ctrl4;
+	SK_U16		Ctrl5;
+
+	Ctrl1 = PHY_CT_SP1000;
+	Ctrl2 = 0;
+	Ctrl3 = PHY_SEL_TYPE;
+	Ctrl4 = PHY_B_PEC_EN_LTR;
+	Ctrl5 = PHY_B_AC_TX_TST;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* manually Master/Slave ? */
+	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+		Ctrl2 |= PHY_B_1000C_MSE;
+
+		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+			Ctrl2 |= PHY_B_1000C_MSC;
+		}
+	}
+
+	/* Auto-negotiation ? */
+	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyBcom: no auto-negotiation Port %d\n", Port));
+		/* set DuplexMode in Config register */
+		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+			Ctrl1 |= PHY_CT_DUP_MD;
+		}
+
+		/* Determine Master/Slave manually if not already done */
+		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+			Ctrl2 |= PHY_B_1000C_MSE;	/* set it to Slave */
+		}
+
+		/*
+		 * Do NOT enable Auto-negotiation here. This would hold
+		 * the link down because no IDLES are transmitted
+		 */
+	}
+	else {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyBcom: with auto-negotiation Port %d\n", Port));
+		/* set Auto-negotiation advertisement */
+
+		/*
+		 * Workaround BCOM Errata #1 for the C5 type.
+		 * 1000Base-T Link Acquisition Failure in Slave Mode
+		 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+		 */
+		Ctrl2 |= PHY_B_1000C_RD;
+
+		 /* set Full/half duplex capabilities */
+		switch (pPrt->PLinkMode) {
+		case SK_LMODE_AUTOHALF:
+			Ctrl2 |= PHY_B_1000C_AHD;
+			break;
+		case SK_LMODE_AUTOFULL:
+			Ctrl2 |= PHY_B_1000C_AFD;
+			break;
+		case SK_LMODE_AUTOBOTH:
+			Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+				SKERR_HWI_E015MSG);
+		}
+
+		/* set Flow-control capabilities */
+		switch (pPrt->PFlowCtrlMode) {
+		case SK_FLOW_MODE_NONE:
+			Ctrl3 |= PHY_B_P_NO_PAUSE;
+			break;
+		case SK_FLOW_MODE_LOC_SEND:
+			Ctrl3 |= PHY_B_P_ASYM_MD;
+			break;
+		case SK_FLOW_MODE_SYMMETRIC:
+			Ctrl3 |= PHY_B_P_SYM_MD;
+			break;
+		case SK_FLOW_MODE_SYM_OR_REM:
+			Ctrl3 |= PHY_B_P_BOTH_MD;
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+				SKERR_HWI_E016MSG);
+		}
+
+		/* Restart Auto-negotiation */
+		Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
+	}
+
+	/* Initialize LED register here? */
+	/* No. Please do it in SkDgXmitLed() (if required) and swap
+		init order of LEDs and XMAC. (MAl) */
+
+	/* Write 1000Base-T Control Register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Set 1000B-T Ctrl Reg = 0x%04X\n", Ctrl2));
+
+	/* Write AutoNeg Advertisement Register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Set Auto-Neg.Adv.Reg = 0x%04X\n", Ctrl3));
+
+	if (DoLoop) {
+		/* set the PHY Loopback bit, too */
+		Ctrl1 |= PHY_CT_LOOP;
+	}
+
+	if (pPrt->PPortUsage == SK_JUMBO_LINK) {
+		/* configure FIFO to high latency for transmission of ext. packets */
+		Ctrl4 |= PHY_B_PEC_HIGH_LA;
+
+		/* configure reception of extended packets */
+		Ctrl5 |= PHY_B_AC_LONG_PACK;
+
+		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
+	}
+
+	/* Configure LED Traffic Mode and Jumbo Frame usage if specified */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
+
+	/* Write to the PHY control register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Control Reg = 0x%04X\n", Ctrl1));
+}	/* SkXmInitPhyBcom */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+#ifdef SK_PHY_LP_MODE
+/******************************************************************************
+ *
+ *	SkGmEnterLowPowerMode()
+ *
+ * Description:
+ *	This function sets the Marvell Alaska PHY to the low power mode
+ *	given by parameter mode.
+ *	The following low power modes are available:
+ *
+ *		- COMA Mode (Deep Sleep):
+ *			The PHY cannot wake up on its own.
+ *
+ *		- IEEE 22.2.4.1.5 compatible power down mode
+ *			The PHY cannot wake up on its own.
+ *
+ *		- energy detect mode
+ *			The PHY can wake up on its own by detecting activity
+ *			on the CAT 5 cable.
+ *
+ *		- energy detect plus mode
+ *			The PHY can wake up on its own by detecting activity
+ *			on the CAT 5 cable.
+ *			Connected devices can be woken up by sending normal link
+ *			pulses every second.
+ *
+ * Note:
+ *
+ * Returns:
+ *		0: ok
+ *		1: error
+ */
+int SkGmEnterLowPowerMode(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (e.g. MAC_1) */
+SK_U8	Mode)		/* low power mode */
+{
+	SK_U8	LastMode;
+	SK_U8	Byte;
+	SK_U16	Word;
+	SK_U16	PhySpec;
+	SK_U16	ClkDiv;
+	SK_U32	DWord;
+	SK_U32	PowerDownBit;
+	int		ChipId;
+	int		Ret = 0;
+
+	if (!(CHIP_ID_YUKON_2(pAC) || (pAC->GIni.GIYukonLite &&
+		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3))) {
+
+		return(1);
+	}
+
+	/* save current power mode */
+	LastMode = pAC->GIni.GP[Port].PPhyPowerState;
+	pAC->GIni.GP[Port].PPhyPowerState = Mode;
+
+	ChipId = pAC->GIni.GIChipId;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_POWM, SK_DBGCAT_CTRL,
+		("SkGmEnterLowPowerMode: %u\n", Mode));
+
+	/* release GPHY Control reset */
+	SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_CLR);
+
+	/* release GMAC reset */
+	SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
+
+	if (ChipId == CHIP_ID_YUKON_EC_U || ChipId == CHIP_ID_YUKON_EX) {
+		/* select page 2 to access MAC control register */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2);
+
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+		/* allow GMII Power Down */
+		Word &= ~PHY_M_MAC_GMIF_PUP;
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+
+		/* set page register back to 0 */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
+	}
+
+	switch (Mode) {
+	/* COMA mode (deep sleep) */
+	case PHY_PM_DEEP_SLEEP:
+		/* setup General Purpose Control Register */
+		GM_OUT16(IoC, Port, GM_GP_CTRL, GM_GPCR_FL_PASS |
+			GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+			/* set power down bit */
+			PowerDownBit = (Port == MAC_1) ? PCI_Y2_PHY1_POWD :
+				PCI_Y2_PHY2_POWD;
+
+			if (ChipId != CHIP_ID_YUKON_EC) {
+
+				if (ChipId == CHIP_ID_YUKON_EC_U) {
+
+					SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhySpec);
+					/* enable Power Down */
+					PhySpec |= PHY_M_PC_POW_D_ENA;
+					SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec);
+				}
+
+				/* set IEEE compatible Power Down Mode (dev. #4.99) */
+				Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_PDOWN);
+			}
+		}
+		else {
+			/* apply COMA mode workaround for Yukon-Plus*/
+			(void)SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 31);
+
+			Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xfff3);
+
+			PowerDownBit = PCI_PHY_COMA;
+		}
+
+		SK_TST_MODE_ON(IoC);
+
+		SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord);
+
+		/* set PHY to PowerDown/COMA Mode */
+		SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord | PowerDownBit);
+
+		/* check if this routine was called from a for() loop */
+		if (CHIP_ID_YUKON_2(pAC) &&
+			(pAC->GIni.GIMacsFound == 1 || Port == MAC_2)) {
+
+			if (ChipId == CHIP_ID_YUKON_EC_U ||
+				ChipId == CHIP_ID_YUKON_EX ||
+				ChipId == CHIP_ID_YUKON_FE_P) {
+				/* set GPHY Control reset */
+				SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET);
+
+				/* additional power saving measurements */
+				SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord);
+
+				if (pAC->GIni.GIGotoD3Cold) {
+					/* set gating core clock for LTSSM in DETECT state */
+					DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_DET_STAT) |
+						/* enable Gate Root Core Clock */
+						P_CLK_GATE_ROOT_COR_ENA);
+
+					/* set Mask Register for Release/Gate Clock */
+					SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5),
+						P_REL_MAIN_PWR_AVAIL | P_GAT_MAIN_PWR_N_AVAIL);
+				}
+				else {
+					/* set gating core clock for LTSSM in L1 state */
+					DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) |
+						/* auto clock gated scheme controlled by CLKREQ */
+						P_ASPM_A1_MODE_SELECT |
+						/* enable Gate Root Core Clock */
+						P_CLK_GATE_ROOT_COR_ENA);
+
+					if (HW_FEATURE(pAC, HWF_WA_DEV_4200)) {
+						/* enable Clock Power Management (CLKREQ) */
+						SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), &Word);
+						Word |= PEX_LC_CLK_PM_ENA;
+						SK_OUT16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), Word);
+					}
+					else {
+						/* force CLKREQ Enable in Our4 (A1b only) */
+						DWord |= P_ASPM_FORCE_CLKREQ_ENA;
+					}
+
+					/* set Mask Register for Release/Gate Clock */
+					SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5),
+						P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST |
+						P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE |
+						P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN);
+				}
+
+				SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord);
+
+				if (!pAC->GIni.GIAsfRunning) {
+					/* put CPU into halt state */
+					SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)HCU_CCSR_ASF_RESET);
+
+					SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)HCU_CCSR_ASF_HALTED);
+				}
+			}
+			else {
+				/* ASF system clock stopped */
+				SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)Y2_ASF_CLK_HALT);
+			}
+
+			if (HW_FEATURE(pAC, HWF_RED_CORE_CLK_SUP)) {
+				/* divide clock by 4 only for Yukon-EC */
+				ClkDiv = (ChipId == CHIP_ID_YUKON_EC) ? 1 : 0;
+
+				/* on Yukon-2 clock select value is 31 */
+				DWord = (ChipId == CHIP_ID_YUKON_XL) ?
+					(Y2_CLK_DIV_VAL_2(0) | Y2_CLK_SEL_VAL_2(31)) :
+					 Y2_CLK_DIV_VAL(ClkDiv);
+
+				/* check for Yukon-2 dual port PCI-Express adapter */
+				if (!(pAC->GIni.GIMacsFound == 2 &&
+					  pAC->GIni.GIPciBus == SK_PEX_BUS)) {
+					/* enable Core Clock Division */
+					DWord |= Y2_CLK_DIV_ENA;
+				}
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("Set Core Clock: 0x%08X\n", DWord));
+
+				/* reduce Core Clock Frequency */
+				SK_OUT32(IoC, B2_Y2_CLK_CTRL, DWord);
+			}
+
+			if (HW_FEATURE(pAC, HWF_CLK_GATING_ENABLE)) {
+				/* check for Yukon-2 Rev. A2 */
+				if (ChipId == CHIP_ID_YUKON_XL &&
+					pAC->GIni.GIChipRev > CHIP_REV_YU_XL_A1) {
+					/* enable bits are inverted */
+					Byte = 0;
+				}
+				else {
+					Byte = (SK_U8)(Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+						Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+						Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+				}
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("Set Clock Gating: 0x%02X\n", Byte));
+
+				/* disable MAC/PHY, PCI and Core Clock for both Links */
+				SK_OUT8(IoC, B2_Y2_CLK_GATE, Byte);
+			}
+
+			if (pAC->GIni.GILevel != SK_INIT_IO &&
+				pAC->GIni.GIMacsFound == 1 &&
+				pAC->GIni.GIPciBus == SK_PEX_BUS) {
+
+				if (ChipId == CHIP_ID_YUKON_EC_U ||
+					ChipId == CHIP_ID_YUKON_EX ||
+					ChipId == CHIP_ID_YUKON_FE_P) {
+
+#ifdef PCI_E_L1_STATE
+					SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_1), &Word);
+					/* force to PCIe L1 */
+					Word |= (SK_U16)PCI_FORCE_PEX_L1;
+					SK_OUT16(IoC, PCI_C(pAC, PCI_OUR_REG_1), Word);
+#else /* !PCI_E_L1_STATE */
+
+#ifdef DEEP_SLEEP_D1
+					SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), &Word);
+					/* check if ASPM L1 enabled */
+					if ((Word & PEX_LC_ASPM_LC_L1) != 0) {
+						break;
+					}
+#else
+					break;
+#endif /* !DEEP_SLEEP_D1 */
+
+#endif /* !PCI_E_L1_STATE */
+				}
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+					("Switch to D1 state\n", DWord));
+
+				/* switch to D1 state */
+				SK_OUT8(IoC, PCI_C(pAC, PCI_PM_CTL_STS), PCI_PM_STATE_D1);
+			}
+		}
+
+		break;
+
+	/* IEEE 22.2.4.1.5 compatible power down mode */
+	case PHY_PM_IEEE_POWER_DOWN:
+
+		if (!CHIP_ID_YUKON_2(pAC) && !pAC->GIni.GIYukonLite) {
+
+			Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhySpec);
+
+			/* disable MAC 125 MHz clock */
+			PhySpec |= PHY_M_PC_DIS_125CLK;
+			PhySpec &= ~PHY_M_PC_MAC_POW_UP;
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec);
+
+			/* these register changes must be followed by a software reset */
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word | PHY_CT_RESET);
+		}
+
+		/* switch IEEE compatible power down mode on */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_PDOWN);
+
+		break;
+
+	/* energy detect and energy detect plus mode */
+	case PHY_PM_ENERGY_DETECT:
+	case PHY_PM_ENERGY_DETECT_PLUS:
+
+		Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhySpec);
+
+#ifdef XXX
+		/* disable Polarity Reversal */
+		PhySpec |= PHY_M_PC_POL_R_DIS;
+#endif /* XXX */
+
+		if (!CHIP_ID_YUKON_2(pAC)) {
+			/* disable MAC 125 MHz clock */
+			PhySpec |= PHY_M_PC_DIS_125CLK;
+		}
+
+		if (ChipId == CHIP_ID_YUKON_FE || ChipId == CHIP_ID_YUKON_FE_P) {
+			/* enable Energy Detect (sense & pulse) */
+			PhySpec |= PHY_M_PC_ENA_ENE_DT;
+		}
+		else {
+			/* clear energy detect mode bits */
+			PhySpec &= ~PHY_M_PC_EN_DET_MSK;
+
+			PhySpec |= (Mode == PHY_PM_ENERGY_DETECT) ? PHY_M_PC_EN_DET :
+				PHY_M_PC_EN_DET_PLUS;
+		}
+
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec);
+
+		/* these register changes must be followed by a software reset */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+		Word |= PHY_CT_RESET;
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+
+		if (ChipId == CHIP_ID_YUKON_FE_P) {
+			/* Re-enable Link Partner Next Page */
+			PhySpec |= PHY_M_PC_ENA_LIP_NP;
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec);
+		}
+
+		if (ChipId == CHIP_ID_YUKON_EC_U ||
+			ChipId == CHIP_ID_YUKON_EX ||
+			ChipId == CHIP_ID_YUKON_FE_P) {
+			/* additional power saving measurements */
+			SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord);
+
+			if (pAC->GIni.GIGotoD3Cold) {
+				/* set gating core clock for LTSSM in DETECT state */
+				DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_DET_STAT) |
+					/* enable Gate Root Core Clock */
+					P_CLK_GATE_ROOT_COR_ENA);
+
+				/* set Mask Register for Release/Gate Clock */
+				SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5),
+					P_REL_MAIN_PWR_AVAIL | P_GAT_MAIN_PWR_N_AVAIL);
+			}
+			else {
+				/* set gating core clock for LTSSM in L1 state */
+				DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) |
+					/* auto clock gated scheme controlled by CLKREQ */
+					P_ASPM_A1_MODE_SELECT |
+					/* enable Gate Root Core Clock */
+					P_CLK_GATE_ROOT_COR_ENA);
+
+				if (HW_FEATURE(pAC, HWF_WA_DEV_4200)) {
+					/* enable Clock Power Management (CLKREQ) */
+					SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), &Word);
+					Word |= PEX_LC_CLK_PM_ENA;
+					SK_OUT16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), Word);
+				}
+				else {
+					/* force CLKREQ Enable in Our4 (A1b only) */
+					DWord |= P_ASPM_FORCE_CLKREQ_ENA;
+				}
+
+				/* set Mask Register for Release/Gate Clock */
+				SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5),
+					P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST |
+					P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE |
+					P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN);
+			}
+
+			SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord);
+
+#ifdef PCI_E_L1_STATE
+			SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_1), &Word);
+			/* enable PCIe L1 on GPHY link down */
+			Word |= (SK_U16)PCI_ENA_GPHY_LNK;
+			SK_OUT16(IoC, PCI_C(pAC, PCI_OUR_REG_1), Word);
+#endif /* PCI_E_L1_STATE */
+		}
+
+		pAC->GIni.GP[Port].PState = SK_PRT_STOP;
+		break;
+
+	/* don't change current power mode */
+	default:
+		pAC->GIni.GP[Port].PPhyPowerState = LastMode;
+		Ret = 1;
+	}
+
+	return(Ret);
+
+}	/* SkGmEnterLowPowerMode */
+
+/******************************************************************************
+ *
+ *	SkGmLeaveLowPowerMode()
+ *
+ * Description:
+ *	Leave the current low power mode and switch to normal mode
+ *
+ * Note:
+ *
+ * Returns:
+ *		0:	ok
+ *		1:	error
+ */
+int SkGmLeaveLowPowerMode(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (e.g. MAC_1) */
+{
+	SK_U32	DWord;
+	SK_U32	PowerDownBit;
+	SK_U16	Word;
+	SK_U8	LastMode;
+	int		ChipId;
+	int		Ret = 0;
+
+	if (!(CHIP_ID_YUKON_2(pAC) || (pAC->GIni.GIYukonLite &&
+		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3))) {
+
+		return(1);
+	}
+
+	/* save current power mode */
+	LastMode = pAC->GIni.GP[Port].PPhyPowerState;
+	pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
+
+	ChipId = pAC->GIni.GIChipId;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_POWM, SK_DBGCAT_CTRL,
+		("SkGmLeaveLowPowerMode: %u\n", LastMode));
+
+	switch (LastMode) {
+	/* COMA mode (deep sleep) */
+	case PHY_PM_DEEP_SLEEP:
+
+		if (ChipId == CHIP_ID_YUKON_EC_U ||
+			ChipId == CHIP_ID_YUKON_EX ||
+			ChipId == CHIP_ID_YUKON_FE_P) {
+#ifdef PCI_E_L1_STATE
+			SkPciReadCfgWord(pAC, PCI_OUR_REG_1, &Word);
+
+			/* set the default value into bits 6 & 5 */
+			Word &= ~(SK_U16)(PCI_ENA_GPHY_LNK | PCI_FORCE_PEX_L1);
+
+			SkPciWriteCfgWord(pAC, PCI_OUR_REG_1, Word);
+#endif /* PCI_E_L1_STATE */
+
+			SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord);
+
+			DWord &= P_ASPM_CONTROL_MSK;
+			/* set all bits to 0 except bits 15..12 and 8 */
+			SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord);
+
+			/* set to default value */
+			SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), 0);
+		}
+
+		SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &Word);
+
+		if ((Word & PCI_PM_STATE_MSK) != 0) {
+			/* switch to D0 state */
+			SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, Word & ~PCI_PM_STATE_MSK);
+		}
+
+		SK_TST_MODE_ON(IoC);
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+			/* disable Core Clock Division */
+			SK_OUT32(IoC, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS);
+
+			/* set power down bit */
+			PowerDownBit = (Port == MAC_1) ? PCI_Y2_PHY1_POWD :
+				PCI_Y2_PHY2_POWD;
+		}
+		else {
+			PowerDownBit = PCI_PHY_COMA;
+		}
+
+		SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord);
+
+		/* Release PHY from PowerDown/COMA Mode */
+		SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord & ~PowerDownBit);
+
+		SK_TST_MODE_OFF(IoC);
+
+		if (CHIP_ID_YUKON_2(pAC)) {
+
+			if (ChipId == CHIP_ID_YUKON_FE) {
+				/* release IEEE compatible Power Down Mode */
+				Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_ANE);
+			}
+			else if (ChipId == CHIP_ID_YUKON_EC_U ||
+					 ChipId == CHIP_ID_YUKON_EX ||
+					 ChipId == CHIP_ID_YUKON_FE_P) {
+				/* release GPHY Control reset */
+				SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_CLR);
+			}
+		}
+		else {
+			SK_IN32(IoC, B2_GP_IO, &DWord);
+
+			/* set to output */
+			DWord |= (GP_DIR_9 | GP_IO_9);
+
+			/* set PHY reset */
+			SK_OUT32(IoC, B2_GP_IO, DWord);
+
+			DWord &= ~GP_IO_9;	/* clear PHY reset (active high) */
+
+			/* clear PHY reset */
+			SK_OUT32(IoC, B2_GP_IO, DWord);
+		}
+
+		break;
+
+	/* IEEE 22.2.4.1.5 compatible power down mode */
+	case PHY_PM_IEEE_POWER_DOWN:
+
+		if (ChipId != CHIP_ID_YUKON_XL) {
+
+			Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+			Word &= ~PHY_M_PC_DIS_125CLK;	/* enable MAC 125 MHz clock */
+			Word |= PHY_M_PC_MAC_POW_UP;	/* set MAC power up */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+
+			/* these register changes must be followed by a software reset */
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+			Word |= PHY_CT_RESET;
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+		}
+
+		/* switch IEEE compatible power down mode off */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+		Word &= ~PHY_CT_PDOWN;
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+
+		break;
+
+	/* energy detect and energy detect plus mode */
+	case PHY_PM_ENERGY_DETECT:
+	case PHY_PM_ENERGY_DETECT_PLUS:
+
+		if (ChipId != CHIP_ID_YUKON_XL) {
+
+			Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+
+			if (ChipId == CHIP_ID_YUKON_FE || ChipId == CHIP_ID_YUKON_FE_P) {
+				/* disable Energy Detect */
+				Word &= ~PHY_M_PC_ENA_ENE_DT;
+			}
+			else {
+				/* disable energy detect mode & enable MAC 125 MHz clock */
+				Word &= ~(PHY_M_PC_EN_DET_MSK | PHY_M_PC_DIS_125CLK);
+			}
+
+#ifdef XXX
+			/* enable Polarity Reversal */
+			Word &= ~PHY_M_PC_POL_R_DIS;
+#endif /* XXX */
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+
+			/* these register changes must be followed by a software reset */
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+			Word |= PHY_CT_RESET;
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+		}
+		break;
+
+	/* don't change current power mode */
+	default:
+		pAC->GIni.GP[Port].PPhyPowerState = LastMode;
+		Ret = 1;
+	}
+
+	return(Ret);
+
+}	/* SkGmLeaveLowPowerMode */
+#endif /* SK_PHY_LP_MODE */
+
+/******************************************************************************
+ *
+ *	SkGmInitPhyMarv() - Initialize the Marvell PHY registers
+ *
+ * Description:	initializes all the Marvell PHY registers
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmInitPhyMarv(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	DoLoop)		/* Should a PHY LoopBack be set-up? */
+{
+	SK_GEPORT	*pPrt;
+	SK_BOOL		AutoNeg;
+	SK_BOOL		NewPhyType;
+	SK_U16		PhyCtrl;
+	SK_U16		C1000BaseT;
+	SK_U16		AutoNegAdv;
+	SK_U8		PauseMode;
+	int			ChipId;
+#ifndef SK_SLIM
+	int			MacCtrl;
+	SK_U16		LoopSpeed;
+#endif /* !SK_SLIM */
+	SK_U16		Word;
+	SK_U16		PageReg;
+#ifndef VCPU
+	SK_U16		PhySpec;
+	SK_U16		ExtPhyCtrl;
+	SK_U16		BlinkCtrl;
+	SK_U16		LedCtrl;
+	SK_U16		LedConf;
+	SK_U16		LedOver;
+	int			Mode;
+#ifndef SK_DIAG
+	SK_EVPARA	Para;
+#endif /* !SK_DIAG */
+#if (defined(SK_DIAG) || (defined(DEBUG) && !defined(SK_SLIM)))
+	SK_U16		PhyStat;
+	SK_U16		PhyStat1;
+	SK_U16		PhySpecStat;
+#endif /* SK_DIAG || (DEBUG && !SK_SLIM) */
+#endif /* !VCPU */
+
+	/* set Pause On */
+	PauseMode = (SK_U8)GMC_PAUSE_ON;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	ChipId = pAC->GIni.GIChipId;
+
+	NewPhyType = HW_HAS_NEWER_PHY(pAC);
+
+	/* Auto-negotiation ? */
+	AutoNeg = pPrt->PLinkMode != SK_LMODE_HALF &&
+			  pPrt->PLinkMode != SK_LMODE_FULL;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("InitPhyMarv: Port %d, Auto-neg. %s, LMode %d, LSpeed %d, FlowC %d\n",
+		 Port, AutoNeg ? "ON" : "OFF",
+		 pPrt->PLinkMode, pPrt->PLinkSpeed, pPrt->PFlowCtrlMode));
+
+#ifndef VCPU
+	ExtPhyCtrl = 0;
+
+	/* read Id from PHY */
+	if (SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1) != 0) {
+
+#ifndef SK_DIAG
+		Para.Para64 = Port;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+#endif /* !SK_DIAG */
+
+		return;
+	}
+#endif /* !VCPU */
+
+	if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+
+#ifndef SK_SLIM
+		if (DoLoop) {
+			/* special setup for newer PHYs */
+			if (NewPhyType) {
+
+				LoopSpeed = pPrt->PLinkSpeed;
+
+				if (LoopSpeed == SK_LSPEED_AUTO) {
+					/* force 1000 Mbps */
+					LoopSpeed = SK_LSPEED_1000MBPS;
+				}
+				LoopSpeed += 2;
+
+				/* save page register */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &PageReg);
+
+				/* select page 2 to access MAC control register */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2);
+
+				if (ChipId == CHIP_ID_YUKON_XL) {
+					/* set PHY reg 0, page 2, field [6:4] */
+					MacCtrl = PHY_MARV_CTRL;
+					LoopSpeed <<= 4;
+				}
+				else {	/* CHIP_ID_YUKON_EC_U || CHIP_ID_YUKON_EX */
+					/* set PHY reg 21, page 2, field [2:0] */
+					MacCtrl = PHY_MARV_MAC_CTRL;
+				}
+
+				/* set MAC interface speed */
+				SkGmPhyWrite(pAC, IoC, Port, MacCtrl, LoopSpeed);
+
+				/* restore page register */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, PageReg);
+
+				/* disable link pulses */
+				Word = PHY_M_PC_DIS_LINK_P;
+			}
+			else {
+				/* set 'MAC Power up'-bit, set Manual MDI configuration */
+				Word = PHY_M_PC_MAC_POW_UP;
+			}
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+		}
+#ifndef VCPU
+		else
+#endif /* !VCPU */
+#endif /* !SK_SLIM */
+#ifndef VCPU
+		if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO && !NewPhyType &&
+			(pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+			/* Read Ext. PHY Specific Control */
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
+
+			ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+				PHY_M_EC_MAC_S_MSK);
+
+			ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+
+			/* on PHY 88E1040 Rev.D0 (and newer) downshift control changed */
+			if (pAC->GIni.GIYukonLite || ChipId == CHIP_ID_YUKON_EC) {
+				/* set downshift counter to 3x and enable downshift */
+				ExtPhyCtrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA;
+			}
+			else {
+				/* set master & slave downshift counter to 1x */
+				ExtPhyCtrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+			}
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("Set Ext. PHY Ctrl = 0x%04X\n", ExtPhyCtrl));
+		}
+#endif /* !VCPU */
+	}
+
+#ifndef VCPU
+	if (CHIP_ID_YUKON_2(pAC)) {
+		/* Read PHY Specific Control */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhySpec);
+
+		if (!DoLoop && pAC->GIni.GICopperType) {
+
+			if (ChipId == CHIP_ID_YUKON_FE || ChipId == CHIP_ID_YUKON_FE_P) {
+				/* enable Automatic Crossover (!!! Bits 5..4) */
+				PhySpec |= (SK_U16)(PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1);
+
+				if (ChipId == CHIP_ID_YUKON_FE_P &&
+					pAC->GIni.GIChipRev == CHIP_REV_YU_FE2_A0) {
+					/* Enable Class A driver for FE+ A0 */
+					SkGmPhyRead(pAC, IoC, Port, PHY_MARV_FE_SPEC_2, &Word);
+					Word |= PHY_M_FESC_SEL_CL_A;
+					SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_FE_SPEC_2, Word);
+				}
+			}
+			else {
+				if (!pPrt->PEnDetMode) {
+					/* disable Energy Detect Mode */
+					PhySpec &= ~PHY_M_PC_EN_DET_MSK;
+				}
+
+				/* enable Automatic Crossover */
+				PhySpec |= (SK_U16)PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
+
+				/* downshift on PHY 88E1112 and 88E1149 is changed */
+				if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO &&
+					NewPhyType) {
+					/* set downshift counter to 3x and enable downshift */
+					PhySpec &= ~PHY_M_PC_DSC_MSK;
+					PhySpec |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
+				}
+			}
+		}
+		/* workaround for deviation #4.88 (CRC errors) */
+		else {
+			/* disable Automatic Crossover */
+			PhySpec &= ~PHY_M_PC_MDIX_MSK;
+		}
+
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec);
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("Set PHY Spec Reg. = 0x%04X\n", PhySpec));
+	}
+
+	/* special setup for PHY 88E1112 Fiber */
+	if (ChipId == CHIP_ID_YUKON_XL && !pAC->GIni.GICopperType) {
+		/* select 1000BASE-X only mode in MAC Specific Ctrl Reg. */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2);
+
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+
+		Word &= ~PHY_M_MAC_MD_MSK;
+		Word |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX);
+
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+
+		/* select page 1 to access Fiber registers */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 1);
+
+		if (pAC->GIni.GIPmdTyp == 'P') {
+			/* for SFP-module set SIGDET polarity to low */
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+
+			Word |= PHY_M_FIB_SIGD_POL;
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+		}
+	}
+#endif /* !VCPU */
+
+	/* Read PHY Control */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+
+	Word = PhyCtrl;
+
+	if (!AutoNeg) {
+		/* disable Auto-negotiation */
+		Word &= ~PHY_CT_ANE;
+	}
+
+	/* assert software reset */
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word | PHY_CT_RESET);
+
+	PhyCtrl = 0 /* PHY_CT_COL_TST */;
+	C1000BaseT = 0;
+	AutoNegAdv = PHY_SEL_TYPE;
+
+#ifndef SK_SLIM
+	/* manually Master/Slave ? */
+	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+		/* enable Manual Master/Slave */
+		C1000BaseT |= PHY_M_1000C_MSE;
+
+		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+			C1000BaseT |= PHY_M_1000C_MSC;	/* set it to Master */
+		}
+	}
+#endif /* !SK_SLIM */
+
+	/* Auto-negotiation ? */
+	if (!AutoNeg) {
+
+		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+			/* set Full Duplex Mode */
+			PhyCtrl |= PHY_CT_DUP_MD;
+		}
+
+#ifndef SK_SLIM
+		/* set Master/Slave manually if not already done */
+		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+			C1000BaseT |= PHY_M_1000C_MSE;	/* set it to Slave */
+		}
+#endif /* !SK_SLIM */
+
+		/* set Speed */
+		switch (pPrt->PLinkSpeed) {
+		case SK_LSPEED_AUTO:
+		case SK_LSPEED_1000MBPS:
+			PhyCtrl |= (((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) ?
+						PHY_CT_SP1000 : PHY_CT_SP100);
+			break;
+		case SK_LSPEED_100MBPS:
+			PhyCtrl |= PHY_CT_SP100;
+			break;
+		case SK_LSPEED_10MBPS:
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
+				SKERR_HWI_E019MSG);
+		}
+
+		if ((pPrt->PFlowCtrlMode == SK_FLOW_STAT_NONE) ||
+			/* disable Pause also for 10/100 Mbps in half duplex mode */
+			(!(ChipId == CHIP_ID_YUKON_EC_U || ChipId == CHIP_ID_YUKON_EX) &&
+			(pPrt->PLinkMode == SK_LMODE_HALF) &&
+			 ((pPrt->PLinkSpeed == SK_LSPEED_STAT_100MBPS) ||
+			  (pPrt->PLinkSpeed == SK_LSPEED_STAT_10MBPS)))) {
+
+			/* set Pause Off */
+			PauseMode = (SK_U8)GMC_PAUSE_OFF;
+		}
+
+		SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), PauseMode);
+
+		if (!DoLoop) {
+			/* assert software reset */
+			PhyCtrl |= PHY_CT_RESET;
+		}
+	}
+	else {
+		/* set Auto-negotiation advertisement */
+
+		if (pAC->GIni.GICopperType) {
+			/* set Speed capabilities */
+			switch (pPrt->PLinkSpeed) {
+			case SK_LSPEED_AUTO:
+				if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+					C1000BaseT |= PHY_M_1000C_AFD;
+#ifdef xSK_DIAG
+					C1000BaseT |= PHY_M_1000C_AHD;
+#endif /* SK_DIAG */
+				}
+				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+				break;
+			case SK_LSPEED_1000MBPS:
+				if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+					C1000BaseT |= PHY_M_1000C_AFD;
+#ifdef xSK_DIAG
+					C1000BaseT |= PHY_M_1000C_AHD;
+#endif /* SK_DIAG */
+				}
+				break;
+			case SK_LSPEED_100MBPS:
+				if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_100MBPS) != 0) {
+					AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+						/* advertise 10Base-T also */
+						PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+				}
+				break;
+			case SK_LSPEED_10MBPS:
+				if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_10MBPS) != 0) {
+					AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+				}
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
+					SKERR_HWI_E019MSG);
+			}
+
+			/* set Full/half duplex capabilities */
+			switch (pPrt->PLinkMode) {
+			case SK_LMODE_AUTOHALF:
+				C1000BaseT &= ~PHY_M_1000C_AFD;
+				AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
+				break;
+			case SK_LMODE_AUTOFULL:
+				C1000BaseT &= ~PHY_M_1000C_AHD;
+				AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
+				break;
+			case SK_LMODE_AUTOBOTH:
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+					SKERR_HWI_E015MSG);
+			}
+
+			/* set Flow-control capabilities */
+			switch (pPrt->PFlowCtrlMode) {
+			case SK_FLOW_MODE_NONE:
+				AutoNegAdv |= PHY_B_P_NO_PAUSE;
+				break;
+			case SK_FLOW_MODE_LOC_SEND:
+				AutoNegAdv |= PHY_B_P_ASYM_MD;
+				break;
+			case SK_FLOW_MODE_SYMMETRIC:
+				AutoNegAdv |= PHY_B_P_SYM_MD;
+				break;
+			case SK_FLOW_MODE_SYM_OR_REM:
+				AutoNegAdv |= PHY_B_P_BOTH_MD;
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+					SKERR_HWI_E016MSG);
+			}
+		}
+		else {	/* special defines for FIBER (88E1040S only) */
+
+			/* set Full/half duplex capabilities */
+			switch (pPrt->PLinkMode) {
+			case SK_LMODE_AUTOHALF:
+				AutoNegAdv |= PHY_M_AN_1000X_AHD;
+				break;
+			case SK_LMODE_AUTOFULL:
+				AutoNegAdv |= PHY_M_AN_1000X_AFD;
+				break;
+			case SK_LMODE_AUTOBOTH:
+				AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+					SKERR_HWI_E015MSG);
+			}
+
+			/* set Flow-control capabilities */
+			switch (pPrt->PFlowCtrlMode) {
+			case SK_FLOW_MODE_NONE:
+				AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
+				break;
+			case SK_FLOW_MODE_LOC_SEND:
+				AutoNegAdv |= PHY_M_P_ASYM_MD_X;
+				break;
+			case SK_FLOW_MODE_SYMMETRIC:
+				AutoNegAdv |= PHY_M_P_SYM_MD_X;
+				break;
+			case SK_FLOW_MODE_SYM_OR_REM:
+				AutoNegAdv |= PHY_M_P_BOTH_MD_X;
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+					SKERR_HWI_E016MSG);
+			}
+		}
+
+		if (!DoLoop) {
+			/* Restart Auto-negotiation */
+			PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+		}
+	}
+
+#ifdef VCPU
+	/*
+	 * E-mail from Gu Lin (08-03-2002):
+	 */
+
+	/* Program PHY register 30 as 16'h0708 for simulation speed up */
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0x0700 /* 0x0708 */);
+
+	VCpuWait(2000);
+
+#else /* !VCPU */
+
+	if (ChipId != CHIP_ID_YUKON_FE && ChipId != CHIP_ID_YUKON_FE_P) {
+		/* Write 1000Base-T Control Register */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("Set 1000B-T Ctrl  = 0x%04X\n", C1000BaseT));
+	}
+
+	/* Write AutoNeg Advertisement Register */
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Set Auto-Neg.Adv. = 0x%04X\n", AutoNegAdv));
+#endif /* !VCPU */
+
+#ifndef SK_SLIM
+	if (DoLoop) {
+		/* set the PHY Loopback bit */
+		PhyCtrl |= PHY_CT_LOOP;
+	}
+#endif /* !SK_SLIM */
+
+	/* Write to the PHY Control register */
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Set PHY Ctrl Reg. = 0x%04X\n", PhyCtrl));
+
+#ifdef VCPU
+	VCpuWait(2000);
+#else /* !VCPU */
+
+	LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS);
+
+	LedOver = 0;
+
+	BlinkCtrl = pAC->GIni.GILedBlinkCtrl;
+
+	if ((BlinkCtrl & SK_ACT_LED_BLINK) != 0) {
+
+		if (ChipId == CHIP_ID_YUKON_FE) {
+			/* on 88E3082 these bits are at 11..9 (shifted left) */
+			LedCtrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
+
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_FE_LED_PAR, &Word);
+
+			/* delete LED1 (Activity) control bits */
+			Word &= ~PHY_M_FELP_LED1_MSK;
+
+			/* change ACT LED control to LINK/ACT or blink mode */
+			Word |= PHY_M_FELP_LED1_CTRL(
+				((BlinkCtrl & SK_LED_COMB_ACT_LNK) != 0) ?
+				LED_PAR_CTRL_LNK_AC : LED_PAR_CTRL_ACT_BL);
+
+			/* check for LINK_LED mux */
+			if ((BlinkCtrl & SK_LED_LINK_MUX_P60) != 0) {
+				/* delete LED0 (Speed) control bits */
+				Word &= ~PHY_M_FELP_LED0_MSK;
+				/* change Speed LED control to Link indication */
+				Word |= PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_LINK);
+			}
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_FE_LED_PAR, Word);
+		}
+		else if (ChipId == CHIP_ID_YUKON_FE_P) {
+			/* Enable Link Partner Next Page */
+			PhySpec |= PHY_M_PC_ENA_LIP_NP;
+
+			/* disable Energy Detect and enable scrambler */
+			PhySpec &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB);
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec);
+
+			/* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */
+			Word = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) |
+				PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) |
+				PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED);
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_FE_LED_PAR, Word);
+		}
+		else if (NewPhyType) {
+			/* save page register */
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &PageReg);
+
+			/* select page 3 to access LED control register */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 3);
+
+			LedConf = PHY_M_LEDC_LOS_CTRL(1) |		/* LINK/ACT (Yukon-2 only) */
+					  PHY_M_LEDC_STA1_CTRL(7) |		/* 100 Mbps */
+					  PHY_M_LEDC_STA0_CTRL(7);		/* 1000 Mbps */
+
+			Mode = 7;		/* 10 Mbps: On */
+
+			if (ChipId == CHIP_ID_YUKON_XL) {
+				/* set Polarity Control register */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_STAT, (SK_U16)
+					(PHY_M_POLC_LS1_P_MIX(4) | PHY_M_POLC_IS0_P_MIX(4) |
+					 PHY_M_POLC_LOS_CTRL(2) | PHY_M_POLC_INIT_CTRL(2) |
+					 PHY_M_POLC_STA1_CTRL(2) | PHY_M_POLC_STA0_CTRL(2)));
+			}
+			else if (ChipId == CHIP_ID_YUKON_EC_U ||
+					 ChipId == CHIP_ID_YUKON_EX) {
+				/* check for LINK_LED mux */
+				if ((BlinkCtrl & SK_LED_LINK_MUX_P60) != 0) {
+
+					/* LED scheme 2 */
+					SK_IN16(IoC, GPHY_CTRL, &Word);
+
+					Word |= GPC_LED_CONF_VAL(4);
+
+					/* set GPHY LED Config */
+					SK_OUT16(IoC, GPHY_CTRL, Word);
+				}
+				else {
+
+					SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_4), &Word);
+
+					if ((Word & P_PIN63_LINK_LED_ENA) == 0) {
+						/* LED scheme 1 */
+						Mode = 8;	/* 10 Mbps: forced Off */
+
+						if ((BlinkCtrl & SK_ACT_LED_NOTR_OFF) == 0) {
+							/* set LED[5:4] Function Control and Polarity */
+							SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_STAT,
+								(SK_U16)
+								/* LED_ACT to Link/Act. */
+								(PHY_M_LEDC_STA1_CTRL(1) |
+								/* LED_DUP to Duplex */
+								PHY_M_LEDC_STA0_CTRL(6)));
+						}
+					}
+					/* LED scheme 3 if P_PIN63_LINK_LED_ENA is set */
+				}
+
+				/* set Blink Rate in LED Timer Control Register */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
+					LedCtrl | (SK_U16)PHY_M_LED_BLINK_RT(BLINK_84MS));
+			}
+
+			LedConf |= PHY_M_LEDC_INIT_CTRL(Mode);
+
+			/* set LED Function Control register */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, LedConf);
+
+#if (defined(SK_DIAG) || (defined(DEBUG) && !defined(SK_SLIM)))
+			/* select page 6 to access Packet Generation register */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 6);
+
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+
+			Word |= BIT_4S;			/* enable CRC checker */
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+#endif /* SK_DIAG || (DEBUG && !SK_SLIM) */
+
+			/* restore page register */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, PageReg);
+		}
+		else {
+			/* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
+			LedCtrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+
+			/* on PHY 88E1111 there is a change for LED control */
+			if (ChipId == CHIP_ID_YUKON_EC &&
+				(BlinkCtrl & SK_DUAL_LED_ACT_LNK) != 0) {
+				/* Yukon-EC needs setting of 2 bits: 0,6=11) */
+				LedCtrl |= PHY_M_LEDC_TX_C_LSB;
+			}
+			/* turn off the Rx LED (LED_RX) */
+			LedOver |= PHY_M_LED_MO_RX(MO_LED_OFF);
+		}
+	}
+
+	if ((BlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
+		/* disable blink mode (LED_DUPLEX) on collisions */
+		LedCtrl |= PHY_M_LEDC_DP_CTRL;
+	}
+
+	if (ChipId == CHIP_ID_YUKON_EC_U) {
+		if (pAC->GIni.GIChipRev >= CHIP_REV_YU_EC_U_A1) {
+			/* apply fixes in PHY AFE */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0x00ff);
+
+			/* increase differential signal amplitude in 10BASE-T */
+			SkGmPhyWrite(pAC, IoC, Port, 24, 0xaa99);
+			SkGmPhyWrite(pAC, IoC, Port, 23, 0x2011);
+
+			/* fix for IEEE A/B Symmetry failure in 1000BASE-T */
+			SkGmPhyWrite(pAC, IoC, Port, 24, 0xa204);
+			SkGmPhyWrite(pAC, IoC, Port, 23, 0x2002);
+
+			/* set page register to 0 */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
+		}
+	}
+	else if (ChipId == CHIP_ID_YUKON_FE_P &&
+			 pAC->GIni.GIChipRev == CHIP_REV_YU_FE2_A0) {
+		/* apply workaround for integrated resistors calibration */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 17);
+
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0x3f60);
+	}
+	else if (ChipId != CHIP_ID_YUKON_EX) {
+		/* no effect on Yukon-XL */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
+
+#ifndef SK_SLIM
+		if ((BlinkCtrl & SK_LED_LINK100_ON) != 0) {
+			/* only in forced 100 Mbps mode */
+			if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
+				/* turn on 100 Mbps LED (LED_LINK100) */
+				LedOver |= PHY_M_LED_MO_100(MO_LED_ON);
+			}
+		}
+#endif /* !SK_SLIM */
+
+		if (LedOver != 0) {
+			/* set Manual LED Override */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER, LedOver);
+		}
+	}
+
+#ifdef SK_DIAG
+	c_print("Set PHY Ctrl = 0x%04X\n", PhyCtrl);
+	c_print("Set 1000 B-T = 0x%04X\n", C1000BaseT);
+	c_print("Set Auto-Neg = 0x%04X\n", AutoNegAdv);
+	c_print("Set PHY Spec = 0x%04X\n", PhySpec);
+	c_print("Set Ext Ctrl = 0x%04X\n", ExtPhyCtrl);
+#endif /* SK_DIAG */
+
+#if (defined(SK_DIAG) || (defined(DEBUG) && !defined(SK_SLIM)))
+	/* Read PHY Control */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Ctrl Reg. = 0x%04X\n", PhyCtrl));
+
+	/* Read AutoNeg Advertisement Register */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Auto-Neg.Adv. = 0x%04X\n", AutoNegAdv));
+
+	if (ChipId != CHIP_ID_YUKON_FE && ChipId != CHIP_ID_YUKON_FE_P) {
+		/* Read 1000Base-T Control Register */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("1000B-T Ctrl  = 0x%04X\n", C1000BaseT));
+
+		/* Read Ext. PHY Specific Control */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("Ext. PHY Ctrl = 0x%04X\n", ExtPhyCtrl));
+	}
+
+	/* Read PHY Status */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Stat Reg. = 0x%04X\n", PhyStat));
+
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Stat Reg. = 0x%04X\n", PhyStat1));
+
+	/* Read PHY Specific Status */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Spec Stat = 0x%04X\n", PhySpecStat));
+#endif /* SK_DIAG || (DEBUG && !SK_SLIM) */
+
+#ifdef SK_DIAG
+	c_print("PHY Ctrl Reg = 0x%04X\n", PhyCtrl);
+	c_print("PHY 1000 Reg = 0x%04X\n", C1000BaseT);
+	c_print("PHY AnAd Reg = 0x%04X\n", AutoNegAdv);
+	c_print("Ext Ctrl Reg = 0x%04X\n", ExtPhyCtrl);
+	c_print("PHY Stat Reg = 0x%04X\n", PhyStat);
+	c_print("PHY Stat Reg = 0x%04X\n", PhyStat1);
+	c_print("PHY Spec Reg = 0x%04X\n", PhySpecStat);
+#endif /* SK_DIAG */
+
+	/* enable PHY interrupts */
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, (SK_U16)PHY_M_DEF_MSK);
+#endif /* !VCPU */
+
+}	/* SkGmInitPhyMarv */
+#endif /* YUKON */
+
+
+#ifdef OTHER_PHY
+/******************************************************************************
+ *
+ *	SkXmInitPhyLone() - Initialize the Level One PHY registers
+ *
+ * Description:	initializes all the Level One PHY registers
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmInitPhyLone(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	DoLoop)		/* Should a PHY LoopBack be set-up? */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		Ctrl1;
+	SK_U16		Ctrl2;
+	SK_U16		Ctrl3;
+
+	Ctrl1 = PHY_CT_SP1000;
+	Ctrl2 = 0;
+	Ctrl3 = PHY_SEL_TYPE;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* manually Master/Slave ? */
+	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+		Ctrl2 |= PHY_L_1000C_MSE;
+
+		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+			Ctrl2 |= PHY_L_1000C_MSC;
+		}
+	}
+
+	/* Auto-negotiation ? */
+	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+		/*
+		 * level one spec say: "1000 Mbps: manual mode not allowed"
+		 * but lets see what happens...
+		 */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyLone: no auto-negotiation Port %d\n", Port));
+		/* set DuplexMode in Config register */
+		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+			Ctrl1 |= PHY_CT_DUP_MD;
+		}
+
+		/* Determine Master/Slave manually if not already done */
+		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+			Ctrl2 |= PHY_L_1000C_MSE;	/* set it to Slave */
+		}
+		/*
+		 * Do NOT enable Auto-negotiation here. This would hold
+		 * the link down because no IDLES are transmitted
+		 */
+	}
+	else {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyLone: with auto-negotiation Port %d\n", Port));
+		/* set Auto-negotiation advertisement */
+
+		/* set Full/half duplex capabilities */
+		switch (pPrt->PLinkMode) {
+		case SK_LMODE_AUTOHALF:
+			Ctrl2 |= PHY_L_1000C_AHD;
+			break;
+		case SK_LMODE_AUTOFULL:
+			Ctrl2 |= PHY_L_1000C_AFD;
+			break;
+		case SK_LMODE_AUTOBOTH:
+			Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+				SKERR_HWI_E015MSG);
+		}
+
+		/* set Flow-control capabilities */
+		switch (pPrt->PFlowCtrlMode) {
+		case SK_FLOW_MODE_NONE:
+			Ctrl3 |= PHY_L_P_NO_PAUSE;
+			break;
+		case SK_FLOW_MODE_LOC_SEND:
+			Ctrl3 |= PHY_L_P_ASYM_MD;
+			break;
+		case SK_FLOW_MODE_SYMMETRIC:
+			Ctrl3 |= PHY_L_P_SYM_MD;
+			break;
+		case SK_FLOW_MODE_SYM_OR_REM:
+			Ctrl3 |= PHY_L_P_BOTH_MD;
+			break;
+		default:
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+				SKERR_HWI_E016MSG);
+		}
+
+		/* Restart Auto-negotiation */
+		Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
+	}
+
+	/* Write 1000Base-T Control Register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("1000B-T Ctrl Reg = 0x%04X\n", Ctrl2));
+
+	/* Write AutoNeg Advertisement Register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Auto-Neg.Adv.Reg = 0x%04X\n", Ctrl3));
+
+	if (DoLoop) {
+		/* set the PHY Loopback bit, too */
+		Ctrl1 |= PHY_CT_LOOP;
+	}
+
+	/* Write to the PHY control register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Control Reg = 0x%04X\n", Ctrl1));
+}	/* SkXmInitPhyLone */
+
+
+/******************************************************************************
+ *
+ *	SkXmInitPhyNat() - Initialize the National PHY registers
+ *
+ * Description:	initializes all the National PHY registers
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmInitPhyNat(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	DoLoop)		/* Should a PHY LoopBack be set-up? */
+{
+/* todo: National */
+}	/* SkXmInitPhyNat */
+#endif /* OTHER_PHY */
+
+
+/******************************************************************************
+ *
+ *	SkMacInitPhy() - Initialize the PHY registers
+ *
+ * Description:	calls the Init PHY routines dep. on board type
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacInitPhy(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	DoLoop)		/* Should a PHY LoopBack be set-up? */
+{
+	SK_GEPORT	*pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		switch (pPrt->PhyType) {
+		case SK_PHY_XMAC:
+			SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
+			break;
+		case SK_PHY_BCOM:
+			SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
+			break;
+#ifdef OTHER_PHY
+		case SK_PHY_LONE:
+			SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
+			break;
+		case SK_PHY_NAT:
+			SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
+			break;
+#endif /* OTHER_PHY */
+		}
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
+	}
+#endif /* YUKON */
+
+}	/* SkMacInitPhy */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmAutoNegDoneXmac() - Auto-negotiation handling
+ *
+ * Description:
+ *	This function handles the auto-negotiation if the Done bit is set.
+ *
+ * Returns:
+ *	SK_AND_OK	o.k.
+ *	SK_AND_DUP_CAP	Duplex capability error happened
+ *	SK_AND_OTHER	Other error happened
+ */
+static int SkXmAutoNegDoneXmac(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		ResAb;		/* Resolved Ability */
+	SK_U16		LinkPartAb;	/* Link Partner Ability */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("AutoNegDoneXmac, Port %d\n", Port));
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Get PHY parameters */
+	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LinkPartAb);
+	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
+
+	if ((LinkPartAb & PHY_X_AN_RFB) != 0) {
+		/* At least one of the remote fault bit is set */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("AutoNegFail: Remote fault bit set Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+
+		return(SK_AND_OTHER);
+	}
+
+	/* Check Duplex mismatch */
+	if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+	}
+	else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+	}
+	else {
+		/* Error */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+
+		return(SK_AND_DUP_CAP);
+	}
+
+	/* Check PAUSE mismatch */
+	/* We are NOT using chapter 4.23 of the Xaqti manual */
+	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+	if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
+		 pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
+		(LinkPartAb & PHY_X_P_SYM_MD) != 0) {
+		/* Symmetric PAUSE */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+	}
+	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
+			 (LinkPartAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
+		/* enable PAUSE receive, disable PAUSE transmit */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+	}
+	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
+			 (LinkPartAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
+		/* disable PAUSE receive, enable PAUSE transmit */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+	}
+	else {
+		/* PAUSE mismatch -> no PAUSE */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+	}
+
+	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+
+	return(SK_AND_OK);
+}	/* SkXmAutoNegDoneXmac */
+
+
+/******************************************************************************
+ *
+ *	SkXmAutoNegDoneBcom() - Auto-negotiation handling
+ *
+ * Description:
+ *	This function handles the auto-negotiation if the Done bit is set.
+ *
+ * Returns:
+ *	SK_AND_OK	o.k.
+ *	SK_AND_DUP_CAP	Duplex capability error happened
+ *	SK_AND_OTHER	Other error happened
+ */
+static int SkXmAutoNegDoneBcom(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+#ifdef TEST_ONLY
+	SK_U16		ResAb;		/* Resolved Ability */
+#endif
+	SK_U16		LinkPartAb;	/* Link Partner Ability */
+	SK_U16		AuxStat;	/* Auxiliary Status */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("AutoNegDoneBcom, Port %d\n", Port));
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Get PHY parameters */
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LinkPartAb);
+#ifdef TEST_ONLY
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+#endif
+
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
+
+	if ((LinkPartAb & PHY_B_AN_RF) != 0) {
+		/* Remote fault bit is set: Error */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("AutoNegFail: Remote fault bit set Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+
+		return(SK_AND_OTHER);
+	}
+
+	/* Check Duplex mismatch */
+	if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+	}
+	else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+	}
+	else {
+		/* Error */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+
+		return(SK_AND_DUP_CAP);
+	}
+
+#ifdef TEST_ONLY
+	/* Check Master/Slave resolution */
+	if ((ResAb & PHY_B_1000S_MSF) != 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("Master/Slave Fault Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+		pPrt->PMSStatus = SK_MS_STAT_FAULT;
+		return(SK_AND_OTHER);
+	}
+
+	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+#endif
+
+	/* Check PAUSE mismatch ??? */
+	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+	if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
+		/* Symmetric PAUSE */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+	}
+	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
+		/* enable PAUSE receive, disable PAUSE transmit */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+	}
+	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
+		/* disable PAUSE receive, enable PAUSE transmit */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+	}
+	else {
+		/* PAUSE mismatch -> no PAUSE */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+	}
+
+	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+
+	return(SK_AND_OK);
+}	/* SkXmAutoNegDoneBcom */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkGmAutoNegDoneMarv() - Auto-negotiation handling
+ *
+ * Description:
+ *	This function handles the auto-negotiation if the Done bit is set.
+ *
+ * Returns:
+ *	SK_AND_OK	o.k.
+ *	SK_AND_DUP_CAP	Duplex capability error happened
+ *	SK_AND_OTHER	Other error happened
+ */
+static int SkGmAutoNegDoneMarv(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		ResAb;		/* Resolved Ability */
+	SK_U16		AuxStat;	/* Auxiliary Status */
+	SK_U16		Word;
+	SK_U8		PauseMode;	/* Pause Mode */
+#ifndef SK_SLIM
+	SK_U16		LinkPartAb;	/* Link Partner Ability */
+#ifndef SK_DIAG
+	SK_EVPARA	Para;
+#endif /* !SK_DIAG */
+#endif /* !SK_SLIM */
+
+	/* set Pause On */
+	PauseMode = (SK_U8)GMC_PAUSE_ON;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("AutoNegDoneMarv, Port %d\n", Port));
+
+	pPrt = &pAC->GIni.GP[Port];
+
+#ifndef SK_SLIM
+	/* Get PHY parameters */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LinkPartAb);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Link P.Abil. = 0x%04X\n", LinkPartAb));
+
+	if ((LinkPartAb & PHY_M_AN_RF) != 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("AutoNegFail: Remote fault bit set Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+
+		return(SK_AND_OTHER);
+	}
+
+	if (pAC->GIni.GICopperType) {
+		/* Read PHY Auto-Negotiation Expansion */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &LinkPartAb);
+
+		if ((LinkPartAb & PHY_ANE_LP_CAP) == 0) {
+
+			pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
+
+#ifndef SK_DIAG
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+				("Link Partner not Auto-Neg. able, AN Exp.: 0x%04X\n",
+				LinkPartAb));
+
+#ifndef NDIS_MINIPORT_DRIVER
+			SK_ERR_LOG(pAC, SK_ERRCL_INFO, SKERR_HWI_E025, SKERR_HWI_E025MSG);
+#endif
+			Para.Para64 = Port;
+			SkEventQueue(pAC, SKGE_DRV, SK_DRV_LIPA_NOT_AN_ABLE, Para);
+#else
+			c_print("Link Partner not Auto-Neg. able, AN Exp.: 0x%04X\n",
+				LinkPartAb);
+#endif /* !SK_DIAG */
+
+			if (HW_FEATURE(pAC, HWF_FORCE_AUTO_NEG) &&
+				pPrt->PLinkModeConf < SK_LMODE_AUTOHALF) {
+				/* set used link speed */
+				pPrt->PLinkSpeedUsed = pPrt->PLinkSpeed;
+
+				/* Set Link Mode Status */
+				pPrt->PLinkModeStatus = (SK_U8)
+					(pPrt->PLinkModeConf == SK_LMODE_FULL) ?
+					SK_LMODE_STAT_FULL : SK_LMODE_STAT_HALF;
+
+				return(SK_AND_OK);
+			}
+		}
+		else {
+			pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
+		}
+	}
+#endif /* !SK_SLIM */
+
+	if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
+
+		/* Check Master/Slave resolution */
+		if ((ResAb & PHY_B_1000S_MSF) != 0) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("Master/Slave Fault Port %d\n", Port));
+			pPrt->PAutoNegFail = SK_TRUE;
+			pPrt->PMSStatus = SK_MS_STAT_FAULT;
+			return(SK_AND_OTHER);
+		}
+
+		pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+			(SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
+	}
+
+	/* Read PHY Specific Status */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
+
+	/* Check Speed & Duplex resolved */
+	if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+
+		return(SK_AND_DUP_CAP);
+	}
+
+	if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+		pPrt->PLinkModeStatus = (SK_U8)(((AuxStat & PHY_M_PS_FULL_DUP) != 0) ?
+			SK_LMODE_STAT_AUTOFULL : SK_LMODE_STAT_AUTOHALF);
+	}
+	else {
+		pPrt->PLinkModeStatus = (SK_U8)(((AuxStat & PHY_M_PS_FULL_DUP) != 0) ?
+			SK_LMODE_STAT_FULL : SK_LMODE_STAT_HALF);
+	}
+
+	if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE ||
+		pAC->GIni.GIChipId == CHIP_ID_YUKON_FE_P) {
+		/* set used link speed */
+		pPrt->PLinkSpeedUsed = (SK_U8)(((AuxStat & PHY_M_PS_SPEED_100) != 0) ?
+			SK_LSPEED_STAT_100MBPS : SK_LSPEED_STAT_10MBPS);
+
+		/* Yukon-FE PHYs don't report the Flow-Control resolution */
+		AuxStat = 0;
+
+		/* read MAC General Purpose Status */
+		GM_IN16(IoC, Port, GM_GP_STAT, &Word);
+
+		/* get the negotiated Flow-Control resolution from GPSR */
+		if ((Word & GM_GPSR_FC_RX_DIS) == 0) {
+			AuxStat |= PHY_M_PS_RX_P_EN;
+		}
+
+		if ((Word & GM_GPSR_FC_TX_DIS) == 0) {
+			AuxStat |= PHY_M_PS_TX_P_EN;
+		}
+	}
+	else {
+		/* set used link speed */
+		switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
+		case (unsigned)PHY_M_PS_SPEED_1000:
+			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+			break;
+		case PHY_M_PS_SPEED_100:
+			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
+			break;
+		default:
+			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
+		}
+
+		if (HW_HAS_NEWER_PHY(pAC)) {
+			/* Tx & Rx Pause Enabled bits are at 9..8 */
+			AuxStat >>= 6;
+
+			if (!pAC->GIni.GICopperType) {
+				/* always 1000 Mbps on fiber */
+				pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+			}
+		}
+
+		AuxStat &= PHY_M_PS_PAUSE_MSK;
+	}
+
+	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+	if (AuxStat == PHY_M_PS_PAUSE_MSK) {
+		/* Symmetric PAUSE */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+	}
+	else if (AuxStat == PHY_M_PS_RX_P_EN) {
+		/* enable PAUSE receive, disable PAUSE transmit */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+	}
+	else if (AuxStat == PHY_M_PS_TX_P_EN) {
+		/* disable PAUSE receive, enable PAUSE transmit */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+	}
+	else {
+		/* PAUSE mismatch -> no PAUSE */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("LinkSpeedUsed = %d\n", pPrt->PLinkSpeedUsed));
+
+	if ((pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE) ||
+		/* disable Pause also for 10/100 Mbps in half duplex mode */
+		(!(pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U ||
+		   pAC->GIni.GIChipId == CHIP_ID_YUKON_EX) &&
+		(pPrt->PLinkSpeedUsed < (SK_U8)SK_LSPEED_STAT_1000MBPS) &&
+		 pPrt->PLinkModeStatus == (SK_U8)SK_LMODE_STAT_AUTOHALF)) {
+
+		/* set Pause Off */
+		PauseMode = (SK_U8)GMC_PAUSE_OFF;
+	}
+
+	SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), PauseMode);
+
+	return(SK_AND_OK);
+}	/* SkGmAutoNegDoneMarv */
+#endif /* YUKON */
+
+
+#ifdef OTHER_PHY
+/******************************************************************************
+ *
+ *	SkXmAutoNegDoneLone() - Auto-negotiation handling
+ *
+ * Description:
+ *	This function handles the auto-negotiation if the Done bit is set.
+ *
+ * Returns:
+ *	SK_AND_OK	o.k.
+ *	SK_AND_DUP_CAP	Duplex capability error happened
+ *	SK_AND_OTHER	Other error happened
+ */
+static int SkXmAutoNegDoneLone(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		ResAb;		/* Resolved Ability */
+	SK_U16		LinkPartAb;	/* Link Partner Ability */
+	SK_U16		QuickStat;	/* Auxiliary Status */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("AutoNegDoneLone, Port %d\n", Port));
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Get PHY parameters */
+	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LinkPartAb);
+	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
+	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
+
+	if ((LinkPartAb & PHY_L_AN_RF) != 0) {
+		/* Remote fault bit is set */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("AutoNegFail: Remote fault bit set Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+
+		return(SK_AND_OTHER);
+	}
+
+	/* Check Duplex mismatch */
+	if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+	}
+	else {
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+	}
+
+	/* Check Master/Slave resolution */
+	if ((ResAb & PHY_L_1000S_MSF) != 0) {
+		/* Error */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("Master/Slave Fault Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+		pPrt->PMSStatus = SK_MS_STAT_FAULT;
+		return(SK_AND_OTHER);
+	}
+
+	pPrt->PMSStatus = ((ResAb & PHY_L_1000S_MSR) != 0) ?
+		(SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
+
+	/* Check PAUSE mismatch */
+	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+	/* we must manually resolve the abilities here */
+	pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+
+	switch (pPrt->PFlowCtrlMode) {
+	case SK_FLOW_MODE_NONE:
+		/* default */
+		break;
+	case SK_FLOW_MODE_LOC_SEND:
+		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
+			(PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
+			/* disable PAUSE receive, enable PAUSE transmit */
+			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+		}
+		break;
+	case SK_FLOW_MODE_SYMMETRIC:
+		if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
+			/* Symmetric PAUSE */
+			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+		}
+		break;
+	case SK_FLOW_MODE_SYM_OR_REM:
+		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
+			PHY_L_QS_AS_PAUSE) {
+			/* enable PAUSE receive, disable PAUSE transmit */
+			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+		}
+		else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
+			/* Symmetric PAUSE */
+			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+		}
+		break;
+	default:
+		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+			SKERR_HWI_E016MSG);
+	}
+
+	return(SK_AND_OK);
+}	/* SkXmAutoNegDoneLone */
+
+
+/******************************************************************************
+ *
+ *	SkXmAutoNegDoneNat() - Auto-negotiation handling
+ *
+ * Description:
+ *	This function handles the auto-negotiation if the Done bit is set.
+ *
+ * Returns:
+ *	SK_AND_OK	o.k.
+ *	SK_AND_DUP_CAP	Duplex capability error happened
+ *	SK_AND_OTHER	Other error happened
+ */
+static int SkXmAutoNegDoneNat(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+/* todo: National */
+	return(SK_AND_OK);
+}	/* SkXmAutoNegDoneNat */
+#endif /* OTHER_PHY */
+
+
+/******************************************************************************
+ *
+ *	SkMacAutoNegDone() - Auto-negotiation handling
+ *
+ * Description:	calls the auto-negotiation done routines dep. on board type
+ *
+ * Returns:
+ *	SK_AND_OK	o.k.
+ *	SK_AND_DUP_CAP	Duplex capability error happened
+ *	SK_AND_OTHER	Other error happened
+ */
+int SkMacAutoNegDone(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	int	Rtv;
+
+	Rtv = SK_AND_OK;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		switch (pPrt->PhyType) {
+
+		case SK_PHY_XMAC:
+			Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
+			break;
+		case SK_PHY_BCOM:
+			Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
+			break;
+#ifdef OTHER_PHY
+		case SK_PHY_LONE:
+			Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
+			break;
+		case SK_PHY_NAT:
+			Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
+			break;
+#endif /* OTHER_PHY */
+		default:
+			return(SK_AND_OTHER);
+		}
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
+	}
+#endif /* YUKON */
+
+	if (Rtv != SK_AND_OK) {
+		return(Rtv);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("AutoNeg done Port %d\n", Port));
+
+	/* We checked everything and may now enable the link */
+	pPrt->PAutoNegFail = SK_FALSE;
+
+	SkMacRxTxEnable(pAC, IoC, Port);
+
+	return(SK_AND_OK);
+}	/* SkMacAutoNegDone */
+
+
+#ifndef SK_SLIM
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
+ *
+ * Description:
+ *  sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
+ *  enables Rx/Tx
+ *
+ * Returns: N/A
+ */
+static void SkXmSetRxTxEn(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Para)		/* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
+{
+	SK_U16	Word;
+
+	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+
+	switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
+	case SK_MAC_LOOPB_ON:
+		Word |= XM_MMU_MAC_LB;
+		break;
+	case SK_MAC_LOOPB_OFF:
+		Word &= ~XM_MMU_MAC_LB;
+		break;
+	}
+
+	switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
+	case SK_PHY_LOOPB_ON:
+		Word |= XM_MMU_GMII_LOOP;
+		break;
+	case SK_PHY_LOOPB_OFF:
+		Word &= ~XM_MMU_GMII_LOOP;
+		break;
+	}
+
+	switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
+	case SK_PHY_FULLD_ON:
+		Word |= XM_MMU_GMII_FD;
+		break;
+	case SK_PHY_FULLD_OFF:
+		Word &= ~XM_MMU_GMII_FD;
+		break;
+	}
+
+	XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+
+	/* dummy read to ensure writing */
+	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+
+}	/* SkXmSetRxTxEn */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
+ *
+ * Description:
+ *  sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
+ *  enables Rx/Tx
+ *
+ * Returns: N/A
+ */
+static void SkGmSetRxTxEn(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Para)		/* Parameter to set: MAC LoopBack, Duplex Mode */
+{
+	SK_U16	Ctrl;
+
+	GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
+
+	switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
+	case SK_MAC_LOOPB_ON:
+		Ctrl |= GM_GPCR_LOOP_ENA;
+		break;
+	case SK_MAC_LOOPB_OFF:
+		Ctrl &= ~GM_GPCR_LOOP_ENA;
+		break;
+	}
+
+	switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
+	case SK_PHY_FULLD_ON:
+		Ctrl |= GM_GPCR_DUP_FULL;
+		break;
+	case SK_PHY_FULLD_OFF:
+		Ctrl &= ~GM_GPCR_DUP_FULL;
+		break;
+	}
+
+	GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+
+}	/* SkGmSetRxTxEn */
+#endif /* YUKON */
+
+
+/******************************************************************************
+ *
+ *	SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
+ *
+ * Description:	calls the Special Set Rx/Tx Enable routines dep. on board type
+ *
+ * Returns: N/A
+ */
+void SkMacSetRxTxEn(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Para)
+{
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		SkXmSetRxTxEn(pAC, IoC, Port, Para);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		SkGmSetRxTxEn(pAC, IoC, Port, Para);
+	}
+#endif /* YUKON */
+
+}	/* SkMacSetRxTxEn */
+#endif /* !SK_SLIM */
+
+
+/******************************************************************************
+ *
+ *	SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
+ *
+ * Description:	enables Rx/Tx dep. on board type
+ *
+ * Returns:
+ *	0	o.k.
+ *	!= 0	Error happened
+ */
+int SkMacRxTxEnable(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		Reg;		/* 16-bit register value */
+	SK_U16		IntMask;	/* MAC interrupt mask */
+#ifdef GENESIS
+	SK_U16		SWord;
+#endif
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (!pPrt->PHWLinkUp) {
+		/* The Hardware link is NOT up */
+		return(0);
+	}
+
+	if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
+		 pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
+		 pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
+		 pPrt->PAutoNegFail) {
+		/* Auto-negotiation is not done or failed */
+		return(0);
+	}
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		/* set Duplex Mode and Pause Mode */
+		SkXmInitDupMd(pAC, IoC, Port);
+
+		SkXmInitPauseMd(pAC, IoC, Port);
+
+		/*
+		 * Initialize the Interrupt Mask Register. Default IRQs are...
+		 *	- Link Asynchronous Event
+		 *	- Link Partner requests config
+		 *	- Auto Negotiation Done
+		 *	- Rx Counter Event Overflow
+		 *	- Tx Counter Event Overflow
+		 *	- Transmit FIFO Underrun
+		 */
+		IntMask = XM_DEF_MSK;
+
+#ifdef DEBUG
+		/* add IRQ for Receive FIFO Overflow */
+		IntMask &= ~XM_IS_RXF_OV;
+#endif /* DEBUG */
+
+		if (pPrt->PhyType != SK_PHY_XMAC) {
+			/* disable GP0 interrupt bit */
+			IntMask |= XM_IS_INP_ASS;
+		}
+
+		XM_OUT16(IoC, Port, XM_IMSK, IntMask);
+
+		/* get MMU Command Reg. */
+		XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
+
+		if (pPrt->PhyType != SK_PHY_XMAC &&
+			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
+			 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
+			/* set to Full Duplex */
+			Reg |= XM_MMU_GMII_FD;
+		}
+
+		switch (pPrt->PhyType) {
+		case SK_PHY_BCOM:
+			/*
+			 * Workaround BCOM Errata (#10523) for all BCom Phys
+			 * Enable Power Management after link up
+			 */
+			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
+			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+				(SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
+			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
+				(SK_U16)PHY_B_DEF_MSK);
+			break;
+#ifdef OTHER_PHY
+		case SK_PHY_LONE:
+			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
+			break;
+		case SK_PHY_NAT:
+			/* todo National:
+			SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
+			/* no interrupts possible from National ??? */
+			break;
+#endif /* OTHER_PHY */
+		}
+
+		/* enable Rx/Tx */
+		XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+		/*
+		 * Initialize the Interrupt Mask Register. Default IRQs are...
+		 *	- Rx Counter Event Overflow
+		 *	- Tx Counter Event Overflow
+		 *	- Transmit FIFO Underrun
+		 */
+		IntMask = GMAC_DEF_MSK;
+
+#if (defined(DEBUG) || defined(YUK2)) && (!defined(SK_SLIM))
+		/* add IRQ for Receive FIFO Overrun */
+		IntMask |= GM_IS_RX_FF_OR;
+#endif
+
+		SK_OUT8(IoC, MR_ADDR(Port, GMAC_IRQ_MSK), (SK_U8)IntMask);
+
+		/* get General Purpose Control */
+		GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
+
+		if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
+			pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
+			/* set to Full Duplex */
+			Reg |= GM_GPCR_DUP_FULL;
+
+#ifndef SK_SLIM
+			if (HW_FEATURE(pAC, HWF_FORCE_AUTO_NEG) &&
+				pPrt->PLinkModeConf < SK_LMODE_AUTOHALF) {
+				/* disable auto-update for speed, duplex and flow-control */
+				Reg |= GM_GPCR_AU_ALL_DIS;
+			}
+#endif /* !SK_SLIM */
+		}
+
+		/* WA for dev. #4.209 */
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U &&
+			pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A1) {
+			/* enable/disable Store & Forward mode for TX */
+			SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
+				pPrt->PLinkSpeedUsed != (SK_U8)SK_LSPEED_STAT_1000MBPS ?
+				TX_STFW_ENA : TX_STFW_DIS);
+		}
+
+		/* enable Rx/Tx */
+		GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+	}
+#endif /* YUKON */
+
+	pAC->GIni.GP[Port].PState = SK_PRT_RUN;
+
+	return(0);
+
+}	/* SkMacRxTxEnable */
+
+
+/******************************************************************************
+ *
+ *	SkMacRxTxDisable() - Disable Receiver and Transmitter
+ *
+ * Description:	disables Rx/Tx dep. on board type
+ *
+ * Returns: N/A
+ */
+void SkMacRxTxDisable(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_U16	Word;
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+
+		Word &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+
+		XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
+
+		/* dummy read to ensure writing */
+		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+
+		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+
+		Word &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+
+		GM_OUT16(IoC, Port, GM_GP_CTRL, Word);
+	}
+#endif /* YUKON */
+
+}	/* SkMacRxTxDisable */
+
+
+/******************************************************************************
+ *
+ *	SkMacIrqDisable() - Disable IRQ from MAC
+ *
+ * Description:	sets the IRQ-mask to disable IRQ dep. on board type
+ *
+ * Returns: N/A
+ */
+void SkMacIrqDisable(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+#ifdef GENESIS
+	SK_U16		Word;
+#endif
+
+	pPrt = &pAC->GIni.GP[Port];
+
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+
+		/* disable all XMAC IRQs */
+		XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
+
+		/* disable all PHY interrupts */
+		switch (pPrt->PhyType) {
+			case SK_PHY_BCOM:
+				/* Make sure that PHY is initialized */
+				if (pPrt->PState != SK_PRT_RESET) {
+					/* NOT allowed if BCOM is in RESET state */
+					/* Workaround BCOM Errata (#10523) all BCom */
+					/* disable Power Management if link is down */
+					SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
+					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+						(SK_U16)(Word | PHY_B_AC_DIS_PM));
+					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
+				}
+				break;
+#ifdef OTHER_PHY
+			case SK_PHY_LONE:
+				SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
+				break;
+			case SK_PHY_NAT:
+				/* todo: National
+				SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
+				break;
+#endif /* OTHER_PHY */
+		}
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+		/* disable all GMAC IRQs */
+		SK_OUT8(IoC, MR_ADDR(Port, GMAC_IRQ_MSK), 0);
+
+#ifndef VCPU
+		if (pPrt->PState != SK_PRT_RESET) {
+			/* disable all PHY IRQs */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+		}
+#endif /* !VCPU */
+	}
+#endif /* YUKON */
+
+}	/* SkMacIrqDisable */
+
+
+#ifndef SK_SLIM
+/******************************************************************************
+ *
+ *	SkMacTimeStamp() - Enable / Disable Time Stamp
+ *
+ * Description:	enable / disable Time Stamp generation for Rx packets
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacTimeStamp(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
+{
+	SK_U32	SK_FAR MdReg;
+	SK_U8	TimeCtrl;
+
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+		if (Enable) {
+			MdReg |= XM_MD_ATS;
+		}
+		else {
+			MdReg &= ~XM_MD_ATS;
+		}
+		/* setup Mode Register */
+		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+	}
+	else {
+		if (Enable) {
+			TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
+		}
+		else {
+			TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
+		}
+		/* Start/Stop Time Stamp Timer */
+		SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
+	}
+
+}	/* SkMacTimeStamp*/
+#endif /* !SK_SLIM */
+
+#ifdef SK_DIAG
+/******************************************************************************
+ *
+ *	SkXmSendCont() - Enable / Disable Send Continuous Mode
+ *
+ * Description:	enable / disable Send Continuous Mode on XMAC resp.
+ *								Packet Generation on GPHY
+ *
+ * Returns:
+ *	nothing
+ */
+void SkXmSendCont(
+SK_AC	*pAC,	/* Adapter Context */
+SK_IOC	IoC,	/* I/O Context */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
+{
+	SK_U16	Reg;
+	SK_U16	PageReg;
+	SK_U32	SK_FAR MdReg;
+
+	if (pAC->GIni.GIGenesis) {
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+		if (Enable) {
+			MdReg |= XM_MD_TX_CONT;
+		}
+		else {
+			MdReg &= ~XM_MD_TX_CONT;
+		}
+		/* setup Mode Register */
+		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+	}
+	else {
+		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) {
+			/* select page 18 */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 18);
+
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PAGE_DATA, &Reg);
+
+			Reg &= ~0x003c;			/* clear bits 5..2 */
+
+			if (Enable) {
+				/* enable packet generation, 1518 byte length */
+				Reg |= (BIT_5S | BIT_3S);
+			}
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, Reg);
+		}
+
+		if (HW_HAS_NEWER_PHY(pAC)) {
+			/* save page register */
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &PageReg);
+
+			/* select page 6 to access Packet Generation register */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 6);
+
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Reg);
+
+			Reg &= ~0x003f;			/* clear bits 5..0 */
+
+			if (Enable) {
+				/* enable packet generation, 1518 byte length */
+				Reg |= (BIT_3S | BIT_1S);
+			}
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Reg);
+
+			/* restore page register */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, PageReg);
+		}
+	}
+
+}	/* SkXmSendCont */
+
+#else /* !SK_DIAG */
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
+ *
+ *	This function analyses the Interrupt status word. If any of the
+ *	Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
+ *	is set true.
+ */
+void SkXmAutoNegLipaXmac(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_U16	IStatus)	/* Interrupt Status word to analyse */
+{
+	SK_GEPORT	*pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
+		(IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("AutoNegLipa: AutoNeg detected on Port %d, IStatus = 0x%04X\n",
+			Port, IStatus));
+
+		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
+	}
+}	/* SkXmAutoNegLipaXmac */
+#endif /* GENESIS */
+
+
+/******************************************************************************
+ *
+ *	SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
+ *
+ *	This function analyses the PHY status word.
+ *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
+ *	is set true.
+ */
+void SkMacAutoNegLipaPhy(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_U16	PhyStat)	/* PHY Status word to analyse */
+{
+	SK_GEPORT	*pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
+		(PhyStat & PHY_ST_AN_OVER) != 0) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("AutoNegLipa: AutoNeg detected on Port %d, PhyStat = 0x%04X\n",
+			Port, PhyStat));
+
+		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
+	}
+}	/* SkMacAutoNegLipaPhy */
+
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmIrq() - Interrupt Service Routine
+ *
+ * Description:	services an Interrupt Request of the XMAC
+ *
+ * Note:
+ *	With an external PHY, some interrupt bits are not meaningfull any more:
+ *	- LinkAsyncEvent (bit #14)		XM_IS_LNK_AE
+ *	- LinkPartnerReqConfig (bit #10)	XM_IS_LIPA_RC
+ *	- Page Received (bit #9)		XM_IS_RX_PAGE
+ *	- NextPageLoadedForXmt (bit #8)		XM_IS_TX_PAGE
+ *	- AutoNegDone (bit #7)			XM_IS_AND
+ *	Also probably not valid any more is the GP0 input bit:
+ *	- GPRegisterBit0set			XM_IS_INP_ASS
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmIrq(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		IStatus;	/* Interrupt status read from the XMAC */
+	SK_U16		IStatus2;
+#ifdef SK_SLIM
+	SK_U64		OverflowStatus;
+#else
+	SK_EVPARA	Para;
+#endif /* SK_SLIM */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	XM_IN16(IoC, Port, XM_ISRC, &IStatus);
+
+	/* Link Partner Auto-negable ? */
+	if (pPrt->PhyType == SK_PHY_XMAC) {
+		SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
+	}
+	else {
+		/* mask bits that are not used with ext. PHY */
+		IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
+			XM_IS_RX_PAGE | XM_IS_TX_PAGE |
+			XM_IS_AND | XM_IS_INP_ASS);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+		("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
+
+	if (!pPrt->PHWLinkUp) {
+		/* Spurious XMAC interrupt */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("SkXmIrq: spurious interrupt on Port %d\n", Port));
+		return;
+	}
+
+	if ((IStatus & XM_IS_INP_ASS) != 0) {
+		/* Reread ISR Register if link is not in sync */
+		XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
+			 Port, IStatus, IStatus2));
+		IStatus &= ~XM_IS_INP_ASS;
+		IStatus |= IStatus2;
+	}
+
+	if ((IStatus & XM_IS_LNK_AE) != 0) {
+		/* not used, GP0 is used instead */
+	}
+
+	if ((IStatus & XM_IS_TX_ABORT) != 0) {
+		/* not used */
+	}
+
+	if ((IStatus & XM_IS_FRC_INT) != 0) {
+		/* not used, use ASIC IRQ instead if needed */
+	}
+
+	if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
+		SkHWLinkDown(pAC, IoC, Port);
+
+		/* Signal to RLMT */
+		Para.Para32[0] = (SK_U32)Port;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+
+		/* Start workaround Errata #2 timer */
+		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+			SKGE_HWAC, SK_HWEV_WATIM, Para);
+	}
+
+	if ((IStatus & XM_IS_RX_PAGE) != 0) {
+		/* not used */
+	}
+
+	if ((IStatus & XM_IS_TX_PAGE) != 0) {
+		/* not used */
+	}
+
+	if ((IStatus & XM_IS_AND) != 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+			("SkXmIrq: AND on link that is up Port %d\n", Port));
+	}
+
+	if ((IStatus & XM_IS_TSC_OV) != 0) {
+		/* not used */
+	}
+
+	/* Combined Tx & Rx Counter Overflow SIRQ Event */
+	if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
+#ifdef SK_SLIM
+		SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
+#else
+		Para.Para32[0] = (SK_U32)Port;
+		Para.Para32[1] = (SK_U32)IStatus;
+		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
+#endif /* SK_SLIM */
+	}
+
+	if ((IStatus & XM_IS_RXF_OV) != 0) {
+		/* normal situation -> no effect */
+#ifdef DEBUG
+		pPrt->PRxOverCnt++;
+#endif /* DEBUG */
+	}
+
+	if ((IStatus & XM_IS_TXF_UR) != 0) {
+		/* may NOT happen -> error log */
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
+	}
+
+	if ((IStatus & XM_IS_TX_COMP) != 0) {
+		/* not served here */
+	}
+
+	if ((IStatus & XM_IS_RX_COMP) != 0) {
+		/* not served here */
+	}
+}	/* SkXmIrq */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkGmIrq() - Interrupt Service Routine
+ *
+ * Description:	services an Interrupt Request of the GMAC
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmIrq(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U8		IStatus;	/* Interrupt status */
+#ifdef SK_SLIM
+	SK_U64		OverflowStatus;
+#else
+	SK_EVPARA	Para;
+#endif /* SK_SLIM */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	SK_IN8(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &IStatus);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+		("GmacIrq Port %d Isr 0x%02X\n", Port, IStatus));
+
+	/* Combined Tx & Rx Counter Overflow SIRQ Event */
+	if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
+		/* these IRQs will be cleared by reading GMACs register */
+#ifdef SK_SLIM
+		SkGmOverflowStatus(pAC, IoC, Port, (SK_U16)IStatus, &OverflowStatus);
+#else
+		Para.Para32[0] = (SK_U32)Port;
+		Para.Para32[1] = (SK_U32)IStatus;
+		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
+#endif /* SK_SLIM */
+	}
+
+#ifndef SK_SLIM
+	if (IStatus & GM_IS_RX_FF_OR) {
+		/* clear GMAC Rx FIFO Overrun IRQ */
+		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
+
+		Para.Para64 = Port;
+		SkEventQueue(pAC, SKGE_DRV, SK_DRV_RX_OVERFLOW, Para);
+
+#ifdef DEBUG
+		pPrt->PRxOverCnt++;
+#endif /* DEBUG */
+	}
+#endif /* !SK_SLIM */
+
+	if (IStatus & GM_IS_TX_FF_UR) {
+		/* clear GMAC Tx FIFO Underrun IRQ */
+		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
+
+#ifndef SK_SLIM
+		if (HW_FEATURE(pAC, HWF_WA_DEV_511)) {
+			Para.Para32[0] = (SK_U32)Port;
+			Para.Para32[1] = 0;
+			SkEventQueue(pAC, SKGE_DRV, SK_DRV_TX_UNDERRUN, Para);
+		}
+		else {
+			/* may NOT happen -> error log */
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
+		}
+#endif /* !SK_SLIM */
+	}
+
+	if (IStatus & GM_IS_TX_COMPL) {
+		/* not served here */
+	}
+
+	if (IStatus & GM_IS_RX_COMPL) {
+		/* not served here */
+	}
+}	/* SkGmIrq */
+#endif /* YUKON */
+
+
+/******************************************************************************
+ *
+ *	SkMacIrq() - Interrupt Service Routine for MAC
+ *
+ * Description:	calls the Interrupt Service Routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacIrq(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		/* IRQ from XMAC */
+		SkXmIrq(pAC, IoC, Port);
+	}
+#endif /* GENESIS */
+
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+		/* IRQ from GMAC */
+		SkGmIrq(pAC, IoC, Port);
+	}
+#endif /* YUKON */
+
+}	/* SkMacIrq */
+
+#endif /* !SK_DIAG */
+
+#ifdef GENESIS
+/******************************************************************************
+ *
+ *	SkXmUpdateStats() - Force the XMAC to output the current statistic
+ *
+ * Description:
+ *	The XMAC holds its statistic internally. To obtain the current
+ *	values a command must be sent so that the statistic data will
+ *	be written to a predefined memory area on the adapter.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkXmUpdateStats(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+unsigned int Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		StatReg;
+	int			WaitIndex;
+
+	pPrt = &pAC->GIni.GP[Port];
+	WaitIndex = 0;
+
+	/* Send an update command to XMAC specified */
+	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
+
+	/*
+	 * It is an auto-clearing register. If the command bits
+	 * went to zero again, the statistics are transferred.
+	 * Normally the command should be executed immediately.
+	 * But just to be sure we execute a loop.
+	 */
+	do {
+
+		XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
+
+		if (++WaitIndex > 10) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
+
+			return(1);
+		}
+	} while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
+
+	return(0);
+}	/* SkXmUpdateStats */
+
+
+/******************************************************************************
+ *
+ *	SkXmMacStatistic() - Get XMAC counter value
+ *
+ * Description:
+ *	Gets the 32bit counter value. Except for the octet counters
+ *	the lower 32bit are counted in hardware and the upper 32bit
+ *	must be counted in software by monitoring counter overflow interrupts.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkXmMacStatistic(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+unsigned int Port,		/* Port Index (MAC_1 + n) */
+SK_U16	StatAddr,		/* MIB counter base address */
+SK_U32	SK_FAR *pVal)	/* Pointer to return statistic value */
+{
+	if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
+
+		return(1);
+	}
+
+	XM_IN32(IoC, Port, StatAddr, pVal);
+
+	return(0);
+}	/* SkXmMacStatistic */
+
+
+/******************************************************************************
+ *
+ *	SkXmResetCounter() - Clear MAC statistic counter
+ *
+ * Description:
+ *	Force the XMAC to clear its statistic counter.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkXmResetCounter(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+unsigned int Port)	/* Port Index (MAC_1 + n) */
+{
+	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+	/* Clear two times according to XMAC Errata #3 */
+	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+
+	return(0);
+}	/* SkXmResetCounter */
+
+
+/******************************************************************************
+ *
+ *	SkXmOverflowStatus() - Gets the status of counter overflow interrupt
+ *
+ * Description:
+ *	Checks the source causing an counter overflow interrupt. On success the
+ *	resulting counter overflow status is written to <pStatus>, whereas the
+ *	upper dword stores the XMAC ReceiveCounterEvent register and the lower
+ *	dword the XMAC TransmitCounterEvent register.
+ *
+ * Note:
+ *	For XMAC the interrupt source is a self-clearing register, so the source
+ *	must be checked only once. SIRQ module does another check to be sure
+ *	that no interrupt get lost during process time.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkXmOverflowStatus(
+SK_AC	*pAC,				/* Adapter Context */
+SK_IOC	IoC,				/* I/O Context */
+unsigned int Port,			/* Port Index (MAC_1 + n) */
+SK_U16	IStatus,			/* Interrupt Status from MAC */
+SK_U64	SK_FAR *pStatus)	/* Pointer for return overflow status value */
+{
+	SK_U64	Status;	/* Overflow status */
+	SK_U32	SK_FAR RegVal;
+
+	Status = 0;
+
+	if ((IStatus & XM_IS_RXC_OV) != 0) {
+
+		XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
+		Status |= (SK_U64)RegVal << 32;
+	}
+
+	if ((IStatus & XM_IS_TXC_OV) != 0) {
+
+		XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
+		Status |= (SK_U64)RegVal;
+	}
+
+	*pStatus = Status;
+
+	return(0);
+}	/* SkXmOverflowStatus */
+#endif /* GENESIS */
+
+
+#ifdef YUKON
+/******************************************************************************
+ *
+ *	SkGmUpdateStats() - Force the GMAC to output the current statistic
+ *
+ * Description:
+ *	Empty function for GMAC. Statistic data is accessible in direct way.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkGmUpdateStats(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+unsigned int Port)	/* Port Index (MAC_1 + n) */
+{
+	return(0);
+}
+
+
+/******************************************************************************
+ *
+ *	SkGmMacStatistic() - Get GMAC counter value
+ *
+ * Description:
+ *	Gets the 32bit counter value. Except for the octet counters
+ *	the lower 32bit are counted in hardware and the upper 32bit
+ *	must be counted in software by monitoring counter overflow interrupts.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkGmMacStatistic(
+SK_AC	*pAC,			/* Adapter Context */
+SK_IOC	IoC,			/* I/O Context */
+unsigned int Port,		/* Port Index (MAC_1 + n) */
+SK_U16	StatAddr,		/* MIB counter base address */
+SK_U32	SK_FAR *pVal)	/* Pointer to return statistic value */
+{
+
+	if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
+
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
+		return(1);
+	}
+
+	GM_IN32(IoC, Port, StatAddr, pVal);
+
+	/* dummy read after GM_IN32() */
+	SK_IN16(IoC, B0_RAP, &StatAddr);
+
+	return(0);
+}	/* SkGmMacStatistic */
+
+
+/******************************************************************************
+ *
+ *	SkGmResetCounter() - Clear MAC statistic counter
+ *
+ * Description:
+ *	Force GMAC to clear its statistic counter.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkGmResetCounter(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+unsigned int Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U16	Reg;	/* PHY Address Register */
+	SK_U16	Word;
+	int		i;
+
+	GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
+
+	/* set MIB Clear Counter Mode */
+	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
+
+	/* read all MIB Counters with Clear Mode set */
+	for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
+		/* the reset is performed only when the lower 16 bits are read */
+		GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
+	}
+
+	/* clear MIB Clear Counter Mode */
+	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
+
+	return(0);
+}	/* SkGmResetCounter */
+
+
+/******************************************************************************
+ *
+ *	SkGmOverflowStatus() - Gets the status of counter overflow interrupt
+ *
+ * Description:
+ *	Checks the source causing an counter overflow interrupt. On success the
+ *	resulting counter overflow status is written to <pStatus>, whereas the
+ *	the following bit coding is used:
+ *	63:56 - unused
+ *	55:48 - TxRx interrupt register bit 7:0
+ *	47:32 - Rx interrupt register
+ *	31:24 - unused
+ *	23:16 - TxRx interrupt register bit 15:8
+ *	15: 0 - Tx interrupt register
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkGmOverflowStatus(
+SK_AC	*pAC,				/* Adapter Context */
+SK_IOC	IoC,				/* I/O Context */
+unsigned int Port,			/* Port Index (MAC_1 + n) */
+SK_U16	IStatus,			/* Interrupt Status from MAC */
+SK_U64	SK_FAR *pStatus)	/* Pointer for return overflow status value */
+{
+	SK_U16	RegVal;
+#ifndef SK_SLIM
+	SK_U64	Status;		/* Overflow status */
+
+	Status = 0;
+#endif /* !SK_SLIM */
+
+	if ((IStatus & GM_IS_RX_CO_OV) != 0) {
+		/* this register is self-clearing after read */
+		GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
+
+#ifndef SK_SLIM
+		Status |= (SK_U64)RegVal << 32;
+#endif /* !SK_SLIM */
+	}
+
+	if ((IStatus & GM_IS_TX_CO_OV) != 0) {
+		/* this register is self-clearing after read */
+		GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
+
+#ifndef SK_SLIM
+		Status |= (SK_U64)RegVal;
+#endif /* !SK_SLIM */
+	}
+
+	/* this register is self-clearing after read */
+	GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
+
+#ifndef SK_SLIM
+	/* Rx overflow interrupt register bits (LoByte) */
+	Status |= (SK_U64)((SK_U8)RegVal) << 48;
+	/* Tx overflow interrupt register bits (HiByte) */
+	Status |= (SK_U64)(RegVal >> 8) << 16;
+
+	*pStatus = Status;
+#endif /* !SK_SLIM */
+
+	/* dummy read after GM_IN16() */
+	SK_IN16(IoC, B0_RAP, &RegVal);
+
+	return(0);
+}	/* SkGmOverflowStatus */
+
+
+#ifndef SK_SLIM
+/******************************************************************************
+ *
+ *	SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
+ *
+ * Description:
+ *  starts the cable diagnostic test if 'StartTest' is true
+ *  gets the results if 'StartTest' is true
+ *
+ * NOTE:	this test is meaningful only when link is down
+ *
+ * Returns:
+ *	0:  success
+ *	1:  no YUKON copper
+ *	2:  test in progress
+ *	3:  PHY read error
+ */
+int SkGmCableDiagStatus(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	StartTest)	/* flag for start / get result */
+{
+	int		i;
+	int		CableDiagOffs;
+	int		MdiPairs;
+	int		ChipId;
+	int		Rtv;
+	SK_BOOL	FastEthernet;
+	SK_BOOL	NewPhyType;
+	SK_U16	Ctrl;
+	SK_U16	RegVal;
+	SK_GEPORT	*pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+
+		return(1);
+	}
+
+	ChipId = pAC->GIni.GIChipId;
+
+	NewPhyType = HW_HAS_NEWER_PHY(pAC);
+
+	if (ChipId == CHIP_ID_YUKON_FE || ChipId == CHIP_ID_YUKON_FE_P) {
+
+		CableDiagOffs = PHY_MARV_FE_VCT_TX;
+		FastEthernet = SK_TRUE;
+		MdiPairs = 2;
+	}
+	else {
+		CableDiagOffs = NewPhyType ? PHY_MARV_PHY_CTRL : PHY_MARV_CABLE_DIAG;
+
+		if (ChipId == CHIP_ID_YUKON_EX) {
+
+			CableDiagOffs += 7;		/* Advanced VCT Control Register */
+		}
+
+		FastEthernet = SK_FALSE;
+		MdiPairs = 4;
+	}
+
+	if (StartTest) {
+
+		/* set to RESET to avoid PortCheckUp */
+		pPrt->PState = SK_PRT_RESET;
+
+		/* only start the cable test */
+		if (!FastEthernet) {
+
+			if ((((pPrt->PhyId1 & PHY_I1_MOD_NUM) >> 4) == 2) &&
+				 ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4)) {
+				/* apply TDR workaround for model 2, rev. < 4 */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 30);
+
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xcc00);
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc800);
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc400);
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc000);
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc100);
+			}
+
+#ifdef YUKON_DBG
+			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) {
+				/* set address to 1 for page 1 */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 1);
+
+				/* disable waiting period */
+				SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs,
+					PHY_M_CABD_DIS_WAIT);
+			}
+#endif
+			if (NewPhyType) {
+				/* set address to 5 for page 5 */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 5);
+
+#ifdef YUKON_DBG
+				/* disable waiting period */
+				SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs + 1,
+					PHY_M_CABD_DIS_WAIT);
+#endif
+			}
+			else {
+				/* set address to 0 for MDI[0] (Page 0) */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
+			}
+		}
+		else {
+			RegVal = PHY_CT_RESET | PHY_CT_SP100;
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, RegVal);
+
+#ifdef xYUKON_DBG
+			SkGmPhyRead(pAC, IoC, Port, PHY_MARV_FE_SPEC_2, &RegVal);
+			/* disable waiting period */
+			RegVal |= PHY_M_FESC_DIS_WAIT;
+
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_FE_SPEC_2, RegVal);
+#endif
+		}
+
+		Rtv = SkGmPhyRead(pAC, IoC, Port, CableDiagOffs, &RegVal);
+
+		if (Rtv != 0) {
+			/* PHY read error */
+			return(3);
+		}
+
+		/* start Cable Diagnostic Test */
+		RegVal |= PHY_M_CABD_ENA_TEST;
+
+		if (ChipId == CHIP_ID_YUKON_EX) {
+
+			if (pAC->GIni.GIChipRev == CHIP_REV_YU_EX_A0) {
+				/* apply TDR workaround */
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 13);
+
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0x4c32);
+			}
+
+			/* select first peak above threshold */
+			RegVal |= PHY_M_CABD_TEST_MODE(1);
+
+			/* read Transmit Pulse Reg */
+			SkGmPhyRead(pAC, IoC, Port, CableDiagOffs + 5, &Ctrl);
+
+			/* select 1/2 pulse width (64ns) */
+			Ctrl |= PHY_M_CABD_PULS_WIDT(2);
+
+			SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs + 5, Ctrl);
+		}
+
+		SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs, RegVal);
+
+		return(0);
+	}
+
+	/* read Cable Diagnostic Reg */
+	Rtv = SkGmPhyRead(pAC, IoC, Port, CableDiagOffs, &RegVal);
+
+	if (Rtv != 0) {
+		/* PHY read error */
+		return(3);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Cable Diag. = 0x%04X\n", RegVal));
+
+	if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
+		/* test is running */
+		return(2);
+	}
+
+	if (ChipId == CHIP_ID_YUKON_EX) {
+		/* additional check */
+		if ((RegVal & PHY_M_CABD_COMPLETE) == 0) {
+			/* test not completed */
+			return(2);
+		}
+
+		CableDiagOffs = PHY_MARV_PHY_CTRL;
+	}
+
+	/* get the test results */
+	for (i = 0; i < MdiPairs; i++) {
+
+		if (!FastEthernet && !NewPhyType) {
+			/* set address to i for MDI[i] */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
+		}
+
+		/* get Cable Diagnostic values */
+		SkGmPhyRead(pAC, IoC, Port, CableDiagOffs, &RegVal);
+
+		pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
+
+		pPrt->PMdiPairSts[i] = (SK_U8)((ChipId == CHIP_ID_YUKON_EX) ?
+			(RegVal >> 8) : ((RegVal & PHY_M_CABD_STAT_MSK) >> 13));
+
+		if (FastEthernet || NewPhyType) {
+			/* get next register */
+			CableDiagOffs++;
+		}
+	}
+
+	return(0);
+}	/* SkGmCableDiagStatus */
+#endif /* !SK_SLIM */
+#endif /* YUKON */
+
+/* End of file */
+
diff --git a/drivers/net/sk98lin/sky2.c b/drivers/net/sk98lin/sky2.c
new file mode 100755
index 0000000..0163de6
--- /dev/null
+++ b/drivers/net/sk98lin/sky2.c
@@ -0,0 +1,2880 @@
+/******************************************************************************
+ *
+ * Name:        sky2.c
+ * Project:     Yukon2 specific functions and implementations
+ * Version:     $Revision: 1.38.4.21 $
+ * Date:        $Date: 2007/10/15 15:46:03 $
+ * Purpose:     The main driver source module
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ *	(C)Copyright 1998-2002 SysKonnect GmbH.
+ *	(C)Copyright 2002-2005 Marvell.
+ *
+ *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet 
+ *      Server Adapters.
+ *
+ *	Author: Ralph Roesler (rroesler@syskonnect.de)
+ *	        Mirko Lindner (mlindner@syskonnect.de)
+ *
+ *	Address all question to: linux@syskonnect.de
+ *
+ *	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.
+ *
+ *	The information in this file is provided "AS IS" without warranty.
+ *
+ *****************************************************************************/
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#include <linux/tcp.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14)
+#include <linux/ip.h>
+#endif
+/******************************************************************************
+ *
+ * Local Function Prototypes
+ *
+ *****************************************************************************/
+
+static void InitPacketQueues(SK_AC *pAC,int Port);
+static void GiveTxBufferToHw(SK_AC *pAC,SK_IOC IoC,int Port);
+static void GiveRxBufferToHw(SK_AC *pAC,SK_IOC IoC,int Port,SK_PACKET *pPacket);
+#ifdef SK_EXTREME
+static SK_BOOL HandleReceives(SK_AC *pAC,int Port,SK_U16 Len,SK_U32 FrameStatus,SK_U16 Tcp1,SK_U16 Tcp2,SK_U32 Tist,SK_U16 Vlan, SK_U32 ExtremeCsumResult);
+#else
+static SK_BOOL HandleReceives(SK_AC *pAC,int Port,SK_U16 Len,SK_U32 FrameStatus,SK_U16 Tcp1,SK_U16 Tcp2,SK_U32 Tist,SK_U16 Vlan);
+#endif
+static void CheckForSendComplete(SK_AC *pAC,SK_IOC IoC,int Port,SK_PKT_QUEUE *pPQ,SK_LE_TABLE *pLETab,unsigned int Done);
+static void UnmapAndFreeTxPktBuffer(SK_AC *pAC,SK_PACKET *pSkPacket,int TxPort);
+static SK_BOOL AllocateAndInitLETables(SK_AC *pAC);
+static SK_BOOL AllocatePacketBuffersYukon2(SK_AC *pAC);
+static void FreeLETables(SK_AC *pAC);
+static void FreePacketBuffers(SK_AC *pAC);
+static SK_BOOL AllocAndMapRxBuffer(SK_AC *pAC,SK_PACKET *pSkPacket,int Port);
+#ifdef CONFIG_SK98LIN_NAPI
+static SK_BOOL HandleStatusLEs(SK_AC *pAC,int *WorkDone,int WorkToDo);
+#else
+static SK_BOOL HandleStatusLEs(SK_AC *pAC);
+#endif
+
+extern void	SkGeCheckTimer		(DEV_NET *pNet);
+extern void	SkLocalEventQueue(	SK_AC *pAC,
+					SK_U32 Class,
+					SK_U32 Event,
+					SK_U32 Param1,
+					SK_U32 Param2,
+					SK_BOOL Flag);
+extern void	SkLocalEventQueue64(	SK_AC *pAC,
+					SK_U32 Class,
+					SK_U32 Event,
+					SK_U64 Param,
+					SK_BOOL Flag);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19)
+/* Need way to schedule device 0 even when it's offline. */
+static inline int __netif_rx_schedule_prep(struct net_device *dev)
+{
+	return !test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+#endif
+#endif
+
+
+/******************************************************************************
+ *
+ * Local Variables
+ *
+ *****************************************************************************/
+
+#define MAX_NBR_RX_BUFFERS_IN_HW	0x15
+static SK_U8 NbrRxBuffersInHW;
+#define FLUSH_OPC(le)
+
+/******************************************************************************
+ *
+ * Global Functions
+ *
+ *****************************************************************************/
+
+int SkY2Xmit( struct sk_buff *skb, struct SK_NET_DEVICE *dev); 
+void FillReceiveTableYukon2(SK_AC *pAC,SK_IOC IoC,int Port);
+
+/*****************************************************************************
+ *
+ * 	SkY2RestartStatusUnit - restarts teh status unit
+ *
+ * Description:
+ *	Reenables the status unit after any De-Init (e.g. when altering 
+ *	the sie of the MTU via 'ifconfig a.b.c.d mtu xxx')
+ *
+ * Returns:	N/A
+ */
+void SkY2RestartStatusUnit(
+SK_AC  *pAC)  /* pointer to adapter control context */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> SkY2RestartStatusUnit\n"));
+
+	/*
+	** It might be that the TX timer is not started. Therefore
+	** it is initialized here -> to be more investigated!
+	*/
+	SK_OUT32(pAC->IoBase, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC,10));
+
+	pAC->StatusLETable.Done  = 0;
+	pAC->StatusLETable.Put   = 0;
+	pAC->StatusLETable.HwPut = 0;
+	SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== SkY2RestartStatusUnit\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	SkY2RlmtSend - sends out a single RLMT notification
+ *
+ * Description:
+ *	This function sends out an RLMT frame
+ *
+ * Returns:	
+ *	> 0 - on succes: the number of bytes in the message
+ *	= 0 - on resource shortage: this frame sent or dropped, now
+ *	      the ring is full ( -> set tbusy)
+ *	< 0 - on failure: other problems ( -> return failure to upper layers)
+ */
+int SkY2RlmtSend (
+SK_AC          *pAC,       /* pointer to adapter control context           */
+int             PortNr,    /* index of port the packet(s) shall be send to */
+struct sk_buff *pMessage)  /* pointer to send-message                      */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("=== SkY2RlmtSend\n"));
+#if 0
+	return -1;   // temporarily do not send out RLMT frames
+#endif
+	skb_shinfo(pMessage)->nr_frags = (2*MAX_SKB_FRAGS) + PortNr;
+	return(SkY2Xmit(pMessage, pAC->dev[PortNr])); // SkY2Xmit needs device
+}
+
+/*****************************************************************************
+ *
+ * 	SkY2AllocateResources - Allocates all required resources for Yukon2
+ *
+ * Description:
+ *	This function allocates all memory needed for the Yukon2. 
+ *	It maps also RX buffers to the LETables and initializes the
+ *	status list element table.
+ *
+ * Returns:	
+ *	SK_TRUE, if all resources could be allocated and setup succeeded
+ *	SK_FALSE, if an error 
+ */
+SK_BOOL SkY2AllocateResources (
+SK_AC  *pAC)  /* pointer to adapter control context */
+{
+	int CurrMac;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("==> SkY2AllocateResources\n"));
+
+	/*
+	** Initialize the packet queue variables first
+	*/
+	for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {
+		InitPacketQueues(pAC, CurrMac);
+	}
+
+	/* 
+	** Get sufficient memory for the LETables
+	*/
+	if (!AllocateAndInitLETables(pAC)) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+			SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
+			("No memory for LETable.\n"));
+		return(SK_FALSE);
+	}
+
+	/*
+	** Allocate and intialize memory for both RX and TX 
+	** packet and fragment buffers. On an error, free 
+	** previously allocated LETable memory and quit.
+	*/
+	if (!AllocatePacketBuffersYukon2(pAC)) {
+		FreeLETables(pAC);
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+			SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
+			("No memory for Packetbuffers.\n"));
+		return(SK_FALSE);
+	}
+
+	/* 
+	** Rx and Tx LE tables will be initialized in SkGeOpen() 
+	**
+	** It might be that the TX timer is not started. Therefore
+	** it is initialized here -> to be more investigated!
+	*/
+	SK_OUT32(pAC->IoBase, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC,10));
+	SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable);
+
+	pAC->MaxUnusedRxLeWorking = MAX_UNUSED_RX_LE_WORKING;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("<== SkY2AllocateResources\n"));
+
+	return (SK_TRUE);
+}
+
+/*****************************************************************************
+ *
+ * 	SkY2FreeResources - Frees previously allocated resources of Yukon2
+ *
+ * Description:
+ *	This function frees all previously allocated memory of the Yukon2. 
+ *
+ * Returns: N/A
+ */
+void SkY2FreeResources (
+SK_AC  *pAC)  /* pointer to adapter control context */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> SkY2FreeResources\n"));
+
+	FreeLETables(pAC);
+	FreePacketBuffers(pAC);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== SkY2FreeResources\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	SkY2AllocateRxBuffers - Allocates the receive buffers for a port
+ *
+ * Description:
+ *	This function allocated all the RX buffers of the Yukon2. 
+ *
+ * Returns: N/A
+ */
+void SkY2AllocateRxBuffers (
+SK_AC    *pAC,   /* pointer to adapter control context */
+SK_IOC    IoC,	 /* I/O control context                */
+int       Port)	 /* port index of RX                   */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("==> SkY2AllocateRxBuffers (Port %c)\n", Port));
+
+	FillReceiveTableYukon2(pAC, IoC, Port);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("<== SkY2AllocateRxBuffers\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	SkY2FreeRxBuffers - Free's all allocates RX buffers of
+ *
+ * Description:
+ *	This function frees all RX buffers of the Yukon2 for a single port
+ *
+ * Returns: N/A
+ */
+void SkY2FreeRxBuffers (
+SK_AC    *pAC,   /* pointer to adapter control context */
+SK_IOC    IoC,	 /* I/O control context                */
+int       Port)	 /* port index of RX                   */
+{
+	SK_PACKET     *pSkPacket;
+	unsigned long  Flags;   /* for POP/PUSH macros */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> SkY2FreeRxBuffers (Port %c)\n", Port));
+
+	if (pAC->RxPort[Port].ReceivePacketTable   != NULL) {
+		POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);
+		while (pSkPacket != NULL) {
+			if ((pSkPacket->pFrag) != NULL) {
+				pci_unmap_page(pAC->PciDev,
+				(dma_addr_t) pSkPacket->pFrag->pPhys,
+				pSkPacket->pFrag->FragLen - 2,
+				PCI_DMA_FROMDEVICE);
+
+				/* wipe out any rubbish data that may interfere */
+				skb_shinfo(pSkPacket->pMBuf)->nr_frags = 0;
+				skb_shinfo(pSkPacket->pMBuf)->frag_list = NULL;
+				DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
+				pSkPacket->pMBuf        = NULL;
+				pSkPacket->pFrag->pPhys = (SK_U64) 0;
+				pSkPacket->pFrag->pVirt = NULL;
+			}
+			PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
+			POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== SkY2FreeRxBuffers\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	SkY2FreeTxBuffers - Free's any currently maintained Tx buffer
+ *
+ * Description:
+ *	This function frees the TX buffers of the Yukon2 for a single port
+ *	which might be in use by a transmit action
+ *
+ * Returns: N/A
+ */
+void SkY2FreeTxBuffers (
+SK_AC    *pAC,   /* pointer to adapter control context */
+SK_IOC    IoC,	 /* I/O control context                */
+int       Port)	 /* port index of TX                   */
+{
+	SK_PACKET      *pSkPacket;
+	SK_FRAG        *pSkFrag;
+	unsigned long   Flags;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> SkY2FreeTxBuffers (Port %c)\n", Port));
+ 
+	if (pAC->TxPort[Port][0].TransmitPacketTable != NULL) {
+		POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxAQ_working, pSkPacket);
+		while (pSkPacket != NULL) {
+			if ((pSkFrag = pSkPacket->pFrag) != NULL) {
+				UnmapAndFreeTxPktBuffer(pAC, pSkPacket, Port);
+			}
+			PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[Port][0].TxQ_free, pSkPacket);
+			POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxAQ_working, pSkPacket);
+		}
+#ifdef USE_SYNC_TX_QUEUE
+		POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxSQ_working, pSkPacket);
+		while (pSkPacket != NULL) {
+			if ((pSkFrag = pSkPacket->pFrag) != NULL) {
+				UnmapAndFreeTxPktBuffer(pAC, pSkPacket, Port);
+			}
+			PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[Port][0].TxQ_free, pSkPacket);
+			POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxSQ_working, pSkPacket);
+		}
+#endif
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== SkY2FreeTxBuffers\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	SkY2Isr - handle a receive IRQ for all yukon2 cards
+ *
+ * Description:
+ *	This function is called when a receive IRQ is set. (only for yukon2)
+ *	HandleReceives does the deferred processing of all outstanding
+ *	interrupt operations.
+ *
+ * Returns:	N/A
+ */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+SkIsrRetVar SkY2Isr (
+int              irq,     /* the irq we have received (might be shared!) */
+void            *dev_id)  /* current device id                           */
+#else
+SkIsrRetVar SkY2Isr (
+int              irq,     /* the irq we have received (might be shared!) */
+void            *dev_id,  /* current device id                           */
+struct  pt_regs *ptregs)  /* not used by our driver                      */
+#endif
+{
+	struct SK_NET_DEVICE  *dev  = (struct SK_NET_DEVICE *)dev_id;
+	DEV_NET               *pNet = (DEV_NET*)netdev_priv(dev);
+	SK_AC                 *pAC  = pNet->pAC;
+#ifndef CONFIG_SK98LIN_NAPI
+	SK_BOOL                handledStatLE	= SK_FALSE;
+	unsigned long          Flags;
+#endif
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+		("==> SkY2Isr\n"));
+
+	SK_IN32(pAC->IoBase, B0_Y2_SP_ISRC2, &pAC->InterruptSource);
+
+	if ((pAC->InterruptSource == 0) && (!pNet->NetConsoleMode)){
+		SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+			("No Interrupt\n ==> SkY2Isr\n"));
+		return SkIsrRetNone;
+
+	}
+
+#ifdef Y2_RECOVERY
+	if (pNet->InRecover) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+			("Already in recover\n ==> SkY2Isr\n"));
+		SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);
+		return SkIsrRetNone;
+	}
+#endif
+
+#ifdef CONFIG_SK98LIN_NAPI
+	/* Since both boards share one irq, they share one poll routine */
+	if (__netif_rx_schedule_prep(pAC->dev[0])) {
+		__netif_rx_schedule(pAC->dev[0]);
+	}
+#else
+	handledStatLE = HandleStatusLEs(pAC);
+
+	/* 
+	** Check for Special Interrupts 
+	*/
+	if ((pAC->InterruptSource & ~Y2_IS_STAT_BMU) || pAC->CheckQueue || pNet->TimerExpired) {
+		pAC->CheckQueue = SK_FALSE;
+		spin_lock_irqsave(&pAC->SetPutIndexLock, Flags);
+		SkGeSirqIsr(pAC, pAC->IoBase, pAC->InterruptSource);
+		SkEventDispatcher(pAC, pAC->IoBase);
+		spin_unlock_irqrestore(&pAC->SetPutIndexLock, Flags);
+	}
+
+	/* Speed enhancement for a2 chipsets */
+	if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {
+		spin_lock_irqsave(&pAC->SetPutIndexLock, Flags);
+		SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_XA1,0), &pAC->TxPort[0][0].TxALET);
+		SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_R1,0), &pAC->RxPort[0].RxLET);
+		spin_unlock_irqrestore(&pAC->SetPutIndexLock, Flags);
+	}
+
+	/* 
+	** Reenable interrupts and signal end of ISR 
+	*/
+	SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);
+
+	/*
+	** Stop and restart TX timer in case a Status LE was handled
+	*/
+	if ((HW_FEATURE(pAC, HWF_WA_DEV_43_418)) && (handledStatLE)) {
+		SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_STOP);
+		SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_START);
+	}
+	if (!(IS_Q_EMPTY(&(pAC->TxPort[0][TX_PRIO_LOW].TxAQ_waiting)))) {
+		GiveTxBufferToHw(pAC, pAC->IoBase, 0);
+	}
+	if (!(IS_Q_EMPTY(&(pAC->TxPort[1][TX_PRIO_LOW].TxAQ_waiting)))) {
+		GiveTxBufferToHw(pAC, pAC->IoBase, 1);
+	}
+#endif
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+		("<== SkY2Isr\n"));
+
+	return SkIsrRetHandled;
+}	/* SkY2Isr */
+
+/*****************************************************************************
+ *
+ *	SkY2Xmit - Linux frame transmit function for Yukon2
+ *
+ * Description:
+ *	The system calls this function to send frames onto the wire.
+ *	It puts the frame in the tx descriptor ring. If the ring is
+ *	full then, the 'tbusy' flag is set.
+ *
+ * Returns:
+ *	0, if everything is ok
+ *	!=0, on error
+ *
+ * WARNING: 
+ *	returning 1 in 'tbusy' case caused system crashes (double
+ *	allocated skb's) !!!
+ */
+int SkY2Xmit(
+struct sk_buff       *skb,  /* socket buffer to be sent */
+struct SK_NET_DEVICE *dev)  /* via which device?        */
+{
+	DEV_NET         *pNet    = (DEV_NET*)netdev_priv(dev);
+	SK_AC           *pAC     = pNet->pAC;
+	SK_U8            FragIdx = 0;
+	SK_PACKET       *pSkPacket;
+	SK_FRAG         *PrevFrag;
+	SK_FRAG         *CurrFrag;
+	SK_PKT_QUEUE    *pWorkQueue;  /* corresponding TX queue */
+	SK_PKT_QUEUE    *pWaitQueue; 
+	SK_PKT_QUEUE    *pFreeQueue; 
+	SK_LE_TABLE     *pLETab;      /* corresponding LETable  */ 
+	skb_frag_t      *sk_frag;
+	SK_U64           PhysAddr;
+	unsigned long    Flags;
+	unsigned int     Port;
+	int              CurrFragCtr;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("==> SkY2Xmit\n"));
+
+	/*
+	** Get port and return if no free packet is available 
+	*/
+	if (skb_shinfo(skb)->nr_frags > MAX_SKB_FRAGS) {
+		Port = skb_shinfo(skb)->nr_frags - (2*MAX_SKB_FRAGS);
+		skb_shinfo(skb)->nr_frags = 0;
+	} else {
+		Port = (pAC->RlmtNets == 2) ? pNet->PortNr : pAC->ActivePort;
+	}
+
+	if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free))) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+			SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+			("Not free packets available for send\n"));
+		return 1; /* zero bytes sent! */
+	}
+
+	/*
+	** Put any new packet to be sent in the waiting queue and 
+	** handle also any possible fragment of that packet.
+	*/
+	pWorkQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working);
+	pWaitQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting);
+	pFreeQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free);
+	pLETab     = &(pAC->TxPort[Port][TX_PRIO_LOW].TxALET);
+
+	/*
+	** Normal send operations require only one fragment, because 
+	** only one sk_buff data area is passed. 
+	** In contradiction to this, scatter-gather (zerocopy) send
+	** operations might pass one or more additional fragments 
+	** where each fragment needs a separate fragment info packet.
+	*/
+	if (((skb_shinfo(skb)->nr_frags + 1) * MAX_FRAG_OVERHEAD) > 
+					NUM_FREE_LE_IN_TABLE(pLETab)) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+			SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+			("Not enough LE available for send\n"));
+		return 1; /* zero bytes sent! */
+	}
+	
+	if ((skb_shinfo(skb)->nr_frags + 1) > MAX_NUM_FRAGS) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+			SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+			("Not even one fragment available for send\n"));
+		return 1; /* zero bytes sent! */
+	}
+
+	/*
+	** Get first packet from free packet queue
+	*/
+	POP_FIRST_PKT_FROM_QUEUE(pFreeQueue, pSkPacket);
+	if(pSkPacket == NULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+			SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+			("Could not obtain free packet used for xmit\n"));
+		return 1; /* zero bytes sent! */
+	}
+
+	pSkPacket->pFrag = &(pSkPacket->FragArray[FragIdx]);
+
+	/* 
+	** map the sk_buff to be available for the adapter 
+	*/
+	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+			virt_to_page(skb->data),
+			((unsigned long) skb->data & ~PAGE_MASK),
+			skb_headlen(skb),
+			PCI_DMA_TODEVICE);
+	pSkPacket->pMBuf	  = skb;
+	pSkPacket->pFrag->pPhys   = PhysAddr;
+	pSkPacket->pFrag->FragLen = skb_headlen(skb);
+	pSkPacket->pFrag->pNext   = NULL; /* initial has no next default */
+	pSkPacket->NumFrags	  = skb_shinfo(skb)->nr_frags + 1;
+
+	PrevFrag = pSkPacket->pFrag;
+
+	/*
+	** Each scatter-gather fragment need to be mapped...
+	*/
+        for (	CurrFragCtr = 0; 
+		CurrFragCtr < skb_shinfo(skb)->nr_frags;
+		CurrFragCtr++) {
+		FragIdx++;
+		sk_frag = &skb_shinfo(skb)->frags[CurrFragCtr];
+		CurrFrag = &(pSkPacket->FragArray[FragIdx]);
+
+		/* 
+		** map the sk_buff to be available for the adapter 
+		*/
+		PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+				sk_frag->page,
+		 		sk_frag->page_offset,
+		 		sk_frag->size,
+		 		PCI_DMA_TODEVICE);
+
+		CurrFrag->pPhys   = PhysAddr;
+ 		CurrFrag->FragLen = sk_frag->size;
+ 		CurrFrag->pNext   = NULL;
+
+		/*
+		** Add the new fragment to the list of fragments
+		*/
+		PrevFrag->pNext = CurrFrag;
+		PrevFrag = CurrFrag;
+	}
+
+	/* 
+	** Add packet to waiting packets queue 
+	*/
+	PUSH_PKT_AS_LAST_IN_QUEUE(pWaitQueue, pSkPacket);
+	GiveTxBufferToHw(pAC, pAC->IoBase, Port);
+	dev->trans_start = jiffies;
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("<== SkY2Xmit(return 0)\n"));
+	return (0);
+}	/* SkY2Xmit */
+
+#ifdef CONFIG_SK98LIN_NAPI
+/*****************************************************************************
+ *
+ *	SkY2Poll - NAPI Rx polling callback for Yukon2 chipsets
+ *
+ * Description:
+ *	Called by the Linux system in case NAPI polling is activated
+ *
+ * Returns
+ *	The number of work data still to be handled
+ *
+ * Notes
+ *	The slowpath lock needs to be set because HW accesses may
+ *	interfere with slowpath events (e.g. TWSI)
+ */
+int SkY2Poll(
+struct net_device *dev,     /* device that needs to be polled */
+int               *budget)  /* how many budget do we have?    */
+{
+	DEV_NET       *pNet         = (DEV_NET*) dev->priv;
+	SK_AC	      *pAC          = pNet->pAC;
+	int           WorkToDo      = min(*budget, dev->quota);
+	int           WorkDone      = 0;
+	SK_BOOL       handledStatLE = SK_FALSE;
+
+	handledStatLE = HandleStatusLEs(pAC, &WorkDone, WorkToDo);
+
+	*budget -= WorkDone;
+	dev->quota -= WorkDone;
+
+	/* 
+	** Check for Special Interrupts 
+	*/
+	if ((pAC->InterruptSource & ~Y2_IS_STAT_BMU) || pAC->CheckQueue || pNet->TimerExpired) {
+		pAC->CheckQueue = SK_FALSE;
+		spin_lock(&pAC->SlowPathLock);
+		SkGeSirqIsr(pAC, pAC->IoBase, pAC->InterruptSource);
+		SkEventDispatcher(pAC, pAC->IoBase);
+		spin_unlock(&pAC->SlowPathLock);
+	}
+
+	/* Speed enhancement for a2 chipsets */
+	if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {
+		spin_lock(&pAC->SlowPathLock);
+		SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_XA1,0), &pAC->TxPort[0][0].TxALET);
+		SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_R1,0), &pAC->RxPort[0].RxLET);
+		spin_unlock(&pAC->SlowPathLock);
+	}
+
+	if(WorkDone < WorkToDo) {
+		netif_rx_complete(dev);
+
+		/*
+		** Stop and restart TX timer in case a Status LE was handled
+		*/
+		if ((HW_FEATURE(pAC, HWF_WA_DEV_43_418)) && (handledStatLE)) {
+			SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_STOP);
+			SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_START);
+		}
+
+		/* 
+		** Reenable interrupts
+		*/
+		SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);
+
+		if (!(IS_Q_EMPTY(&(pAC->TxPort[0][TX_PRIO_LOW].TxAQ_waiting)))) {
+			GiveTxBufferToHw(pAC, pAC->IoBase, 0);
+		}
+		if (!(IS_Q_EMPTY(&(pAC->TxPort[1][TX_PRIO_LOW].TxAQ_waiting)))) {
+			GiveTxBufferToHw(pAC, pAC->IoBase, 1);
+		}
+	}
+
+	return (WorkDone >= WorkToDo);
+}	/* SkY2Poll */
+#endif
+
+/******************************************************************************
+ *
+ *	SkY2PortStop - stop a port on Yukon2
+ *
+ * Description:
+ *	This function stops a port of the Yukon2 chip. This stop 
+ *	stop needs to be performed in a specific order:
+ * 
+ *	a) Stop the Prefetch unit
+ *	b) Stop the Port (MAC, PHY etc.)
+ *
+ * Returns: N/A
+ */
+void SkY2PortStop(
+SK_AC   *pAC,      /* adapter control context                             */
+SK_IOC   IoC,      /* I/O control context (address of adapter registers)  */
+int      Port,     /* port to stop (MAC_1 + n)                            */
+int      Dir,      /* StopDirection (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
+int      RstMode)  /* Reset Mode (SK_SOFT_RST, SK_HARD_RST)               */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> SkY2PortStop (Port %c)\n", 'A' + Port));
+
+	/*
+	** Stop the HW
+	*/
+	SkGeStopPort(pAC, IoC, Port, Dir, RstMode);
+
+	/*
+	** Move any TX packet from work queues into the free queue again
+	** and initialize the TX LETable variables
+	*/
+	SkY2FreeTxBuffers(pAC, pAC->IoBase, Port);
+	pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Bmu.RxTx.TcpWp    = 0;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Bmu.RxTx.MssValue = 0;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxALET.BufHighAddr       = 0;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Done              = 0;    
+	pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Put               = 0;
+#ifndef USE_ASF_DASH_FW
+	pAC->GIni.GP[Port].PState = SK_PRT_STOP;
+#endif
+	/*
+	** Move any RX packet from work queue into the waiting queue
+	** and initialize the RX LETable variables
+	*/
+	SkY2FreeRxBuffers(pAC, pAC->IoBase, Port);
+	pAC->RxPort[Port].RxLET.BufHighAddr = 0;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== SkY2PortStop()\n"));
+}
+
+/******************************************************************************
+ *
+ *	SkY2PortStart - start a port on Yukon2
+ *
+ * Description:
+ *	This function starts a port of the Yukon2 chip. This start 
+ *	action needs to be performed in a specific order:
+ * 
+ *	a) Initialize the LET indices (PUT/GET to 0)
+ *	b) Initialize the LET in HW (enables also prefetch unit)
+ *	c) Move all RX buffers from waiting queue to working queue
+ *	   which involves also setting up of RX list elements
+ *	d) Initialize the FIFO settings of Yukon2 (Watermark etc.)
+ *	e) Initialize the Port (MAC, PHY etc.)
+ *	f) Initialize the MC addresses
+ *
+ * Returns:	N/A
+ */
+void SkY2PortStart(
+SK_AC   *pAC,   /* adapter control context                            */
+SK_IOC   IoC,   /* I/O control context (address of adapter registers) */
+int      Port)  /* port to start                                      */
+{
+	// SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
+	SK_HWLE   *pLE;
+	SK_U32     DWord;
+	SK_U32     PrefetchReg; /* register for Put index */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> SkY2PortStart (Port %c)\n", 'A' + Port));
+
+	/*
+	** Initialize the LET indices
+	*/
+	pAC->RxPort[Port].RxLET.Done                = 0; 
+	pAC->RxPort[Port].RxLET.Put                 = 0;
+	pAC->RxPort[Port].RxLET.HwPut               = 0;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Done  = 0;    
+	pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Put   = 0;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxALET.HwPut = 0;
+	if (HW_SYNC_TX_SUPPORTED(pAC)) {
+		pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.Done  = 0;    
+		pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.Put   = 0;
+		pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.HwPut = 0;
+	}
+	
+	if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
+		/*
+		** It might be that we have to limit the RX buffers 
+		** effectively passed to HW. Initialize the start
+		** value in that case...
+		*/
+		NbrRxBuffersInHW = 0;
+	}
+
+	/*
+	** TODO on dual net adapters we need to check if
+	** StatusLETable need to be set...
+	** 
+	** pAC->StatusLETable.Done  = 0;
+	** pAC->StatusLETable.Put   = 0;
+	** pAC->StatusLETable.HwPut = 0;
+	** SkGeY2InitPrefetchUnit(pAC, pAC->IoBase, Q_ST, &pAC->StatusLETable);
+	*/
+
+	/*
+	** Initialize the LET in HW (enables also prefetch unit)
+	*/
+	SkGeY2InitPrefetchUnit(pAC, IoC,(Port == 0) ? Q_R1 : Q_R2,
+			&pAC->RxPort[Port].RxLET);
+	SkGeY2InitPrefetchUnit( pAC, IoC,(Port == 0) ? Q_XA1 : Q_XA2, 
+			&pAC->TxPort[Port][TX_PRIO_LOW].TxALET);
+	if (HW_SYNC_TX_SUPPORTED(pAC)) {
+		SkGeY2InitPrefetchUnit( pAC, IoC, (Port == 0) ? Q_XS1 : Q_XS2,
+				&pAC->TxPort[Port][TX_PRIO_HIGH].TxSLET);
+	}
+
+
+	/*
+	** Using new values for the watermarks and the timer for
+	** low latency optimization
+	*/
+	if (pAC->LowLatency) {
+		SK_OUT8(IoC, STAT_FIFO_WM, 1);
+		SK_OUT8(IoC, STAT_FIFO_ISR_WM, 1);
+		SK_OUT32(IoC, STAT_LEV_TIMER_INI, 50);
+		SK_OUT32(IoC, STAT_ISR_TIMER_INI, 10);
+	}
+
+
+	/*
+	** Initialize the Port (MAC, PHY etc.)
+	*/
+	if (SkGeInitPort(pAC, IoC, Port)) {
+		if (Port == 0) {
+			printk("%s: SkGeInitPort A failed.\n",pAC->dev[0]->name);
+		} else {
+			printk("%s: SkGeInitPort B failed.\n",pAC->dev[1]->name);
+		}
+	}
+	
+	if (IS_GMAC(pAC)) {
+		/* disable Rx GMAC FIFO Flush Mode */
+		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8) GMF_RX_F_FL_OFF);
+	}
+
+	/*
+	** Initialize the MC addresses
+	*/
+	SkAddrMcUpdate(pAC,IoC, Port);
+
+	SkMacRxTxEnable(pAC, IoC,Port);
+				
+	SkGeRxCsum(pAC, IoC, Port, SK_TRUE);
+	
+	GET_RX_LE(pLE, &pAC->RxPort[Port].RxLET);
+	RXLE_SET_STACS1(pLE, pAC->CsOfs1);
+	RXLE_SET_STACS2(pLE, pAC->CsOfs2);
+	RXLE_SET_CTRL(pLE, 0);
+
+	RXLE_SET_OPC(pLE, OP_TCPSTART | HW_OWNER);
+	FLUSH_OPC(pLE);
+	if (Port == 0) {
+		PrefetchReg=Y2_PREF_Q_ADDR(Q_R1,PREF_UNIT_PUT_IDX_REG);
+	} else {
+		PrefetchReg=Y2_PREF_Q_ADDR(Q_R2,PREF_UNIT_PUT_IDX_REG);
+	}
+	DWord = GET_PUT_IDX(&pAC->RxPort[Port].RxLET);
+	SK_OUT32(IoC, PrefetchReg, DWord);
+	UPDATE_HWPUT_IDX(&pAC->RxPort[Port].RxLET);
+
+	pAC->GIni.GP[Port].PState = SK_PRT_RUN;
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== SkY2PortStart()\n"));
+}
+
+/******************************************************************************
+ *
+ * Local Functions
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ *	InitPacketQueues - initialize SW settings of packet queues
+ *
+ * Description:
+ *	This function will initialize the packet queues for a port.
+ *
+ * Returns: N/A
+ */
+static void InitPacketQueues(
+SK_AC  *pAC,   /* pointer to adapter control context */
+int     Port)  /* index of port to be initialized    */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("==> InitPacketQueues(Port %c)\n", 'A' + Port));
+	
+	pAC->RxPort[Port].RxQ_working.pHead = NULL;
+	pAC->RxPort[Port].RxQ_working.pTail = NULL;
+	spin_lock_init(&pAC->RxPort[Port].RxQ_working.QueueLock);
+	
+	pAC->RxPort[Port].RxQ_waiting.pHead = NULL;
+	pAC->RxPort[Port].RxQ_waiting.pTail = NULL;
+	spin_lock_init(&pAC->RxPort[Port].RxQ_waiting.QueueLock);
+	
+	pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pHead = NULL;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pTail = NULL;
+	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.QueueLock);
+
+	pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pHead = NULL;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pTail = NULL;
+	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.QueueLock);
+	
+	pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pHead = NULL;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pTail = NULL;
+	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.QueueLock);
+	
+#ifdef USE_SYNC_TX_QUEUE
+	pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pHead = NULL;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pTail = NULL;
+	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.QueueLock);
+
+	pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pHead = NULL;
+	pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pTail = NULL;
+	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.QueueLock);
+#endif
+	
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("<== InitPacketQueues(Port %c)\n", 'A' + Port));
+}	/* InitPacketQueues */
+
+/*****************************************************************************
+ *
+ *	GiveTxBufferToHw - commits a previously allocated DMA area to HW
+ *
+ * Description:
+ *	This functions gives transmit buffers to HW. If no list elements
+ *	are available the buffers will be queued. 
+ *
+ * Notes:
+ *       This function can run only once in a system at one time.
+ *
+ * Returns: N/A
+ */
+static void GiveTxBufferToHw(
+SK_AC   *pAC,   /* pointer to adapter control context         */
+SK_IOC   IoC,   /* I/O control context (address of registers) */
+int      Port)  /* port index for which the buffer is used    */
+{
+	SK_HWLE         *pLE;
+	SK_PACKET       *pSkPacket;
+	SK_FRAG         *pFrag;
+	SK_PKT_QUEUE    *pWorkQueue;   /* corresponding TX queue */
+	SK_PKT_QUEUE    *pWaitQueue; 
+	SK_LE_TABLE     *pLETab;       /* corresponding LETable  */ 
+	SK_BOOL          SetOpcodePacketFlag;
+	SK_U32           HighAddress;
+	SK_U32           LowAddress;
+	SK_U16           TcpSumStart = 0; 
+	SK_U16           TcpSumWrite = 0;
+	SK_U8            OpCode;
+	SK_U8            Ctrl;
+	unsigned long    Flags;
+	unsigned long    LockFlag;
+	int              Protocol;
+#ifdef NETIF_F_TSO
+	SK_U16           Mss;
+	int              TcpOptLen;
+	int              IpTcpLen;
+#endif
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("==> GiveTxBufferToHw\n"));
+
+	if (HW_FEATURE(pAC, HWF_WA_DEV_510)) {
+		SK_OUT32(pAC->IoBase, TBMU_TEST, TBMU_TEST_BMU_TX_CHK_AUTO_OFF);
+	}
+
+	if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) {
+		return;
+	}
+
+	spin_lock_irqsave(&pAC->TxQueueLock, LockFlag);
+
+	/*
+	** Initialize queue settings
+	*/
+	pWorkQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working);
+	pWaitQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting);
+	pLETab     = &(pAC->TxPort[Port][TX_PRIO_LOW].TxALET);
+
+	POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket);
+	while (pSkPacket != NULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+			("\tWe have a packet to send %p\n", pSkPacket));
+
+		/* 
+		** the first frag of a packet gets opcode OP_PACKET 
+		*/
+		SetOpcodePacketFlag	= SK_TRUE;
+		pFrag			= pSkPacket->pFrag;
+
+		/* 
+		** fill list elements with data from fragments 
+		*/
+		while (pFrag != NULL) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+				("\tGet LE\n"));
+#ifdef NETIF_F_TSO
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)
+			Mss = skb_shinfo(pSkPacket->pMBuf)->gso_size;
+#else
+			Mss = skb_shinfo(pSkPacket->pMBuf)->tso_size;
+#endif
+
+			if (Mss) {
+#ifdef SK_EXTREME
+				if (!HW_IS_EXT_LE_FORMAT(pAC)) {
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
+				       struct iphdr *iph = ip_hdr(pSkPacket->pMBuf);
+					struct tcphdr *tcph = tcp_hdr(pSkPacket->pMBuf);
+					
+					TcpOptLen = ((tcph->doff - 5) * 4);
+					IpTcpLen  = ((iph->ihl * 4) + sizeof(struct tcphdr));
+#else
+					TcpOptLen = ((pSkPacket->pMBuf->h.th->doff - 5) * 4);
+					IpTcpLen  = ((pSkPacket->pMBuf->nh.iph->ihl * 4) + 
+						sizeof(struct tcphdr));
+#endif
+					Mss += (TcpOptLen + IpTcpLen + C_LEN_ETHERMAC_HEADER);
+#ifdef SK_EXTREME
+				}
+#endif
+			}
+			if (pLETab->Bmu.RxTx.MssValue != Mss) {
+				pLETab->Bmu.RxTx.MssValue = Mss;
+				/* Take a new LE for TSO from the table */
+				GET_TX_LE(pLE, pLETab);
+
+#ifdef SK_EXTREME
+				if (HW_IS_EXT_LE_FORMAT(pAC)) {
+					TXLE_SET_OPC(pLE, OP_MSS | HW_OWNER);
+					TXLE_SET_MSSVAL(pLE, pLETab->Bmu.RxTx.MssValue);
+				} else {
+#endif
+					TXLE_SET_OPC(pLE, OP_LRGLEN | HW_OWNER);
+					TXLE_SET_LSLEN(pLE, pLETab->Bmu.RxTx.MssValue);
+#ifdef SK_EXTREME
+				}
+#endif
+
+				FLUSH_OPC(pLE) ;
+			}
+#endif
+			GET_TX_LE(pLE, pLETab);
+			Ctrl = 0;
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+				("\tGot empty LE %p idx %d\n", pLE, GET_PUT_IDX(pLETab)));
+
+			SK_DBG_DUMP_TX_LE(pLE);
+
+			LowAddress  = (SK_U32) (pFrag->pPhys & 0xffffffff);
+			HighAddress = (SK_U32) (pFrag->pPhys >> 32);
+
+			if (HighAddress != pLETab->BufHighAddr) {
+				/* set opcode high part of the address in one LE */
+				OpCode = OP_ADDR64 | HW_OWNER;
+	
+				/* Set now the 32 high bits of the address */
+				TXLE_SET_ADDR( pLE, HighAddress);
+	
+				/* Set the opcode into the LE */
+				TXLE_SET_OPC(pLE, OpCode);
+	
+				/* Flush the LE to memory */
+				FLUSH_OPC(pLE);
+	
+				/* remember the HighAddress we gave to the Hardware */
+				pLETab->BufHighAddr = HighAddress;
+				
+				/* get a new LE because we filled one with high address */
+				GET_TX_LE(pLE, pLETab);
+			}
+	
+			/*
+			** TCP checksum offload
+			*/
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+			if ((pSkPacket->pMBuf->ip_summed == CHECKSUM_PARTIAL) && 
+#else
+			if ((pSkPacket->pMBuf->ip_summed == CHECKSUM_HW) && 
+#endif
+			    (SetOpcodePacketFlag         == SK_TRUE)) {
+				Protocol = ((SK_U8)pSkPacket->pMBuf->data[C_OFFSET_IPPROTO] & 0xff);
+				/* if (Protocol & C_PROTO_ID_IP) { Ctrl = 0; } */
+
+				// Yukon Extreme B0
+				if (HW_FEATURE(pAC, HWF_WA_DEV_510)) {
+					if (Protocol & C_PROTO_ID_TCP) {
+						Ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+						/* TCP Checksum Calculation Start Position */
+						TcpSumStart = C_LEN_ETHERMAC_HEADER + IP_HDR_LEN;
+						/* TCP Checksum Write Position */
+						TcpSumWrite = TcpSumStart + TCP_CSUM_OFFS;
+					} else {
+						Ctrl = UDPTCP | CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+						/* TCP Checksum Calculation Start Position */
+						TcpSumStart = ETHER_MAC_HDR_LEN + IP_HDR_LEN;
+						/* UDP Checksum Write Position */
+						TcpSumWrite = TcpSumStart + UDP_CSUM_OFFS;
+					}
+				}
+				// Yukon 2, Yukon Extreme besides B0
+				else {
+					if (Protocol & C_PROTO_ID_TCP) {
+#ifdef SK_EXTREME
+						if (!HW_IS_EXT_LE_FORMAT(pAC)) {
+#endif
+							Ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+							/* TCP Checksum Calculation Start Position */
+							TcpSumStart = C_LEN_ETHERMAC_HEADER + IP_HDR_LEN;
+							/* TCP Checksum Write Position */
+							TcpSumWrite = TcpSumStart + TCP_CSUM_OFFS;
+#ifdef SK_EXTREME
+						} else {
+							Ctrl = CALSUM;
+						}
+#endif
+					} else {
+#ifdef SK_EXTREME
+						if (!HW_IS_EXT_LE_FORMAT(pAC)) {
+#endif
+							Ctrl = UDPTCP | CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+							/* TCP Checksum Calculation Start Position */
+							TcpSumStart = ETHER_MAC_HDR_LEN + IP_HDR_LEN;
+							/* UDP Checksum Write Position */
+							TcpSumWrite = TcpSumStart + UDP_CSUM_OFFS;
+#ifdef SK_EXTREME
+						} else {
+							Ctrl = CALSUM;
+						}
+#endif
+					}
+				}
+	
+				if ((Ctrl) && (pLETab->Bmu.RxTx.TcpWp != TcpSumWrite)) {
+					/* Update the last value of the write position */
+					pLETab->Bmu.RxTx.TcpWp = TcpSumWrite;
+	
+					/* Set the Lock field for this LE: */
+					/* Checksum calculation for one packet only */
+					TXLE_SET_LCKCS(pLE, 1);
+	
+					/* Set the start position for checksum. */
+					TXLE_SET_STACS(pLE, TcpSumStart);
+	
+					/* Set the position where the checksum will be writen */
+					TXLE_SET_WRICS(pLE, TcpSumWrite);
+	
+					/* Set the initial value for checksum */
+					/* PseudoHeader CS passed from Linux -> 0! */
+					TXLE_SET_INICS(pLE, 0);
+	
+					/* Set the opcode for tcp checksum */
+					TXLE_SET_OPC(pLE, OP_TCPLISW | HW_OWNER);
+	
+					/* Flush the LE to memory */
+					FLUSH_OPC(pLE);
+	
+					/* get a new LE because we filled one with data for checksum */
+					GET_TX_LE(pLE, pLETab);
+				}
+			} /* end TCP offload handling */
+	
+			TXLE_SET_ADDR(pLE, LowAddress);
+			TXLE_SET_LEN(pLE, pFrag->FragLen);
+	
+			if (SetOpcodePacketFlag){
+#ifdef NETIF_F_TSO
+				if (Mss) {
+					OpCode = OP_LARGESEND | HW_OWNER;
+				} else {
+#endif
+					OpCode = OP_PACKET | HW_OWNER;
+#ifdef NETIF_F_TSO
+				}
+#endif
+				SetOpcodePacketFlag = SK_FALSE;
+			} else {
+				/* Follow packet in a sequence has always OP_BUFFER */
+				OpCode = OP_BUFFER | HW_OWNER;
+			}
+
+			/* Check if the low address is near the upper limit. */
+			CHECK_LOW_ADDRESS(pLETab->BufHighAddr, LowAddress, pFrag->FragLen);
+
+			pFrag = pFrag->pNext;
+			if (pFrag == NULL) {
+				/* mark last fragment */
+				Ctrl |= EOP;
+			}
+			TXLE_SET_CTRL(pLE, Ctrl);
+			TXLE_SET_OPC(pLE, OpCode);
+			FLUSH_OPC(pLE);
+
+			SK_DBG_DUMP_TX_LE(pLE);
+		}
+		
+		/* 
+		** Remember next LE for tx complete 
+		*/
+		pSkPacket->NextLE = GET_PUT_IDX(pLETab);
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+			("\tNext LE for pkt %p is %d\n", pSkPacket, pSkPacket->NextLE));
+
+		/* 
+		** Add packet to working packets queue 
+		*/
+		PUSH_PKT_AS_LAST_IN_QUEUE(pWorkQueue, pSkPacket);
+
+		/* 
+		** give transmit start command
+		*/
+		if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {
+			spin_lock(&pAC->SetPutIndexLock);
+			SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_XA1,0), &pAC->TxPort[0][0].TxALET);
+			spin_unlock(&pAC->SetPutIndexLock);
+		} else {
+			/* write put index */
+			if (Port == 0) { 
+				SK_OUT32(pAC->IoBase, 
+					Y2_PREF_Q_ADDR(Q_XA1,PREF_UNIT_PUT_IDX_REG), 
+					GET_PUT_IDX(&pAC->TxPort[0][0].TxALET)); 
+				UPDATE_HWPUT_IDX(&pAC->TxPort[0][0].TxALET);
+			} else {
+				SK_OUT32(pAC->IoBase, 
+					Y2_PREF_Q_ADDR(Q_XA2, PREF_UNIT_PUT_IDX_REG), 
+					GET_PUT_IDX(&pAC->TxPort[1][0].TxALET)); 
+				UPDATE_HWPUT_IDX(&pAC->TxPort[1][0].TxALET);
+			}
+		}
+	
+		if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) {
+			break; /* get out of while */
+		}
+		POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket);
+	} /* while (pSkPacket != NULL) */
+
+	spin_unlock_irqrestore(&pAC->TxQueueLock, LockFlag);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("<== GiveTxBufferToHw\n"));
+	return;
+}	/* GiveTxBufferToHw */
+
+/***********************************************************************
+ *
+ *	GiveRxBufferToHw - commits a previously allocated DMA area to HW
+ *
+ * Description:
+ *	This functions gives receive buffers to HW. If no list elements
+ *	are available the buffers will be queued. 
+ *
+ * Notes:
+ *       This function can run only once in a system at one time.
+ *
+ * Returns: N/A
+ */
+static void GiveRxBufferToHw(
+SK_AC      *pAC,      /* pointer to adapter control context         */
+SK_IOC      IoC,      /* I/O control context (address of registers) */
+int         Port,     /* port index for which the buffer is used    */
+SK_PACKET  *pPacket)  /* receive buffer(s)                          */
+{
+	SK_HWLE         *pLE;
+	SK_LE_TABLE     *pLETab;
+	SK_BOOL         Done = SK_FALSE;  /* at least on LE changed? */
+	SK_U32          LowAddress;
+	SK_U32          HighAddress;
+	SK_U32          PrefetchReg;      /* register for Put index  */
+	unsigned        NumFree;
+	unsigned        Required;
+	unsigned long   Flags;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+	("==> GiveRxBufferToHw(Port %c, Packet %p)\n", 'A' + Port, pPacket));
+
+	pLETab	= &pAC->RxPort[Port].RxLET;
+
+	if (Port == 0) {
+		PrefetchReg = Y2_PREF_Q_ADDR(Q_R1, PREF_UNIT_PUT_IDX_REG);
+	} else {
+		PrefetchReg = Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG);
+	} 
+
+	if (pPacket != NULL) {
+		/*
+		** For the time being, we have only one packet passed
+		** to this function which might be changed in future!
+		*/
+		PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
+	}
+
+	/* 
+	** now pPacket contains the very first waiting packet
+	*/
+	POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
+	while (pPacket != NULL) {
+		if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
+			if (NbrRxBuffersInHW >= MAX_NBR_RX_BUFFERS_IN_HW) {
+				PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+					("<== GiveRxBufferToHw()\n"));
+				return;
+			} 
+			NbrRxBuffersInHW++;
+		}
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+			("Try to add packet %p\n", pPacket));
+
+		/* 
+		** Check whether we have enough listelements:
+		**
+		** we have to take into account that each fragment 
+		** may need an additional list element for the high 
+		** part of the address here I simplified it by 
+		** using MAX_FRAG_OVERHEAD maybe it's worth to split 
+		** this constant for Rx and Tx or to calculate the
+		** real number of needed LE's
+		*/
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+			("\tNum %d Put %d Done %d Free %d %d\n",
+			pLETab->Num, pLETab->Put, pLETab->Done,
+			NUM_FREE_LE_IN_TABLE(pLETab),
+			(NUM_FREE_LE_IN_TABLE(pLETab))));
+
+		Required = pPacket->NumFrags + MAX_FRAG_OVERHEAD;
+		NumFree = NUM_FREE_LE_IN_TABLE(pLETab);
+		if (NumFree) {
+			NumFree--;
+		}
+
+		if (Required > NumFree ) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+				SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+				("\tOut of LEs have %d need %d\n",
+				NumFree, Required));
+
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+				("\tWaitQueue starts with packet %p\n", pPacket));
+			PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
+			if (Done) {
+				/*
+				** write Put index to BMU or Polling Unit and make the LE's
+				** available for the hardware
+				*/
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+					("\tWrite new Put Idx\n"));
+
+				SK_OUT32(IoC, PrefetchReg, GET_PUT_IDX(pLETab));
+				UPDATE_HWPUT_IDX(pLETab);
+			}
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+				("<== GiveRxBufferToHw()\n"));
+			return;
+		} else {
+			if (!AllocAndMapRxBuffer(pAC, pPacket, Port)) {
+				/*
+				** Failure while allocating sk_buff might
+				** be due to temporary short of resources
+				** Maybe next time buffers are available.
+				** Until this, the packet remains in the 
+				** RX waiting queue...
+				*/
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+					SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+					("Failed to allocate Rx buffer\n"));
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+					("WaitQueue starts with packet %p\n", pPacket));
+				PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
+				if (Done) {
+					/*
+					** write Put index to BMU or Polling 
+					** Unit and make the LE's
+					** available for the hardware
+					*/
+					SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+						("\tWrite new Put Idx\n"));
+	
+					SK_OUT32(IoC, PrefetchReg, GET_PUT_IDX(pLETab));
+					UPDATE_HWPUT_IDX(pLETab);
+				}
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+					("<== GiveRxBufferToHw()\n"));
+				return;
+			}
+		}
+		Done = SK_TRUE;
+
+		LowAddress = (SK_U32) (pPacket->pFrag->pPhys & 0xffffffff);
+		HighAddress = (SK_U32) (pPacket->pFrag->pPhys >> 32);
+		if (HighAddress != pLETab->BufHighAddr) {
+			/* get a new LE for high address */
+			GET_RX_LE(pLE, pLETab);
+
+			/* Set now the 32 high bits of the address */
+			RXLE_SET_ADDR(pLE, HighAddress);
+
+			/* Set the control bits of the address */
+			RXLE_SET_CTRL(pLE, 0);
+
+			/* Set the opcode into the LE */
+			RXLE_SET_OPC(pLE, (OP_ADDR64 | HW_OWNER));
+
+			/* Flush the LE to memory */
+			FLUSH_OPC(pLE);
+
+			/* remember the HighAddress we gave to the Hardware */
+			pLETab->BufHighAddr = HighAddress;
+		}
+
+		/*
+		** Fill data into listelement
+		*/
+		GET_RX_LE(pLE, pLETab);
+		RXLE_SET_ADDR(pLE, LowAddress);
+		RXLE_SET_LEN(pLE, pPacket->pFrag->FragLen);
+		RXLE_SET_CTRL(pLE, 0);
+		RXLE_SET_OPC(pLE, (OP_PACKET | HW_OWNER));
+		FLUSH_OPC(pLE);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+			("=== LE filled\n"));
+
+		SK_DBG_DUMP_RX_LE(pLE);
+
+		/* 
+		** Remember next LE for rx complete 
+		*/
+		pPacket->NextLE = GET_PUT_IDX(pLETab);
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+			("\tPackets Next LE is %d\n", pPacket->NextLE));
+
+		/* 
+		** Add packet to working receive buffer queue and get
+		** any next packet out of the waiting queue
+		*/
+		PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_working, pPacket);
+		if (IS_Q_EMPTY(&(pAC->RxPort[Port].RxQ_waiting))) {
+			break; /* get out of while processing */
+		}
+		POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("\tWaitQueue is empty\n"));
+
+	if (Done) {
+		/*
+		** write Put index to BMU or Polling Unit and make the LE's
+		** available for the hardware
+		*/
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+			("\tWrite new Put Idx\n"));
+
+		/* Speed enhancement for a2 chipsets */
+		if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {
+			spin_lock_irqsave(&pAC->SetPutIndexLock, Flags);
+			SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_R1,0), pLETab);
+			spin_unlock_irqrestore(&pAC->SetPutIndexLock, Flags);
+		} else {
+			/* write put index */
+			if (Port == 0) { 
+				SK_OUT32(IoC, 
+					Y2_PREF_Q_ADDR(Q_R1, PREF_UNIT_PUT_IDX_REG), 
+					GET_PUT_IDX(pLETab)); 
+			} else {
+				SK_OUT32(IoC, 
+					Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG), 
+					GET_PUT_IDX(pLETab)); 
+			}
+
+			/* Update put index */
+			UPDATE_HWPUT_IDX(pLETab);
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("<== GiveRxBufferToHw()\n"));
+}       /* GiveRxBufferToHw */
+
+/***********************************************************************
+ *
+ *	FillReceiveTableYukon2 - map any waiting RX buffers to HW
+ *
+ * Description:
+ *	If the list element table contains more empty elements than 
+ *	specified this function tries to refill them.
+ *
+ * Notes:
+ *       This function can run only once per port in a system at one time.
+ *
+ * Returns: N/A
+ */
+void FillReceiveTableYukon2(
+SK_AC   *pAC,   /* pointer to adapter control context */
+SK_IOC   IoC,   /* I/O control context                */
+int      Port)  /* port index of RX                   */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("==> FillReceiveTableYukon2 (Port %c)\n", 'A' + Port));
+
+	if (NUM_FREE_LE_IN_TABLE(&pAC->RxPort[Port].RxLET) >
+		pAC->MaxUnusedRxLeWorking) {
+
+		/* 
+		** Give alle waiting receive buffers down 
+		** The queue holds all RX packets that
+		** need a fresh allocation of the sk_buff.
+		*/
+		if (pAC->RxPort[Port].RxQ_waiting.pHead != NULL) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+			("Waiting queue is not empty -> give it to HW"));
+			GiveRxBufferToHw(pAC, IoC, Port, NULL);
+		}
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("<== FillReceiveTableYukon2 ()\n"));
+}	/* FillReceiveTableYukon2 */
+
+/******************************************************************************
+ *
+ *
+ *	HandleReceives - will pass any ready RX packet to kernel
+ *
+ * Description:
+ *	This functions handles a received packet. It checks wether it is
+ *	valid, updates the receive list element table and gives the receive
+ *	buffer to Linux
+ *
+ * Notes:
+ *	This function can run only once per port at one time in the system.
+ *
+ * Returns: N/A
+ */
+static SK_BOOL HandleReceives(
+SK_AC  *pAC,          /* adapter control context                     */
+int     Port,         /* port on which a packet has been received    */
+SK_U16  FrameLength,  /* number of bytes which was actually received */
+SK_U32  FrameStatus,  /* MAC frame status word                       */
+SK_U16  Tcp1,         /* first hw checksum                           */
+SK_U16  Tcp2,         /* second hw checksum                          */
+SK_U32  Tist,         /* timestamp                                   */
+SK_U16  Vlan          /* Vlan Id                                     */
+#ifdef SK_EXTREME
+, SK_U32  ExtremeCsumResult
+#endif
+)
+{
+	SK_PACKET       *pSkPacket;
+	SK_LE_TABLE     *pLETab;
+	SK_MBUF         *pRlmtMbuf;  /* buffer for giving RLMT frame */
+	struct sk_buff  *pMsg;       /* ptr to message holding frame */
+#ifdef __ia64__
+	struct sk_buff  *pNewMsg;    /* used when IP aligning        */
+#endif
+	SK_BOOL         IsGoodPkt;
+	SK_BOOL         IsBc;
+	SK_BOOL         IsMc;
+	SK_EVPARA       EvPara;      /* an event parameter union     */
+	SK_I16          LenToFree;   /* must be signed integer       */
+	unsigned long   Flags;       /* for spin lock                */
+	unsigned int    RlmtNotifier;
+	unsigned short  Type;
+	int             IpFrameLength;
+	int             HeaderLength;
+	int             NumBytes; 
+	int             Result;
+	int             Offset = 0;
+	SK_U16          HighVal;
+	SK_BOOL         CheckBcMc = SK_FALSE;
+#ifdef Y2_SYNC_CHECK
+	SK_U16		MyTcp;
+#endif
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("==> HandleReceives (Port %c)\n", 'A' + Port));
+
+	if (HW_FEATURE(pAC, HWF_WA_DEV_521)) {
+		HighVal = (SK_U16)(((FrameStatus) & GMR_FS_LEN_MSK) >> GMR_FS_LEN_SHIFT);
+
+		if ((HighVal > ETH_MAX_LEN) || (FrameStatus == 0x7ffc0001)) {
+			FrameStatus = 0;
+		}
+		else if (HighVal != FrameLength) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+					("521: We take pkt len %x stat: %x\n", FrameLength, FrameStatus));
+
+				/*
+				** Try to recover the status word. The multicast and broadcast bits
+				** from status word are set when we have a valid packet header.
+				*/
+				FrameStatus = 0;
+
+				/* Set the ReceiveOK bit. */
+				FrameStatus |= GMR_FS_RX_OK;
+
+				/* Set now the length into the status word */
+				FrameStatus |= (FrameLength << GMR_FS_LEN_SHIFT);
+
+				/* Insure that bit 31 is reset */
+				FrameStatus &= ~GMR_FS_LKUP_BIT2;
+				CheckBcMc = SK_TRUE;
+		}
+	}
+
+	/* 
+	** Check whether we want to receive this packet 
+	*/
+	SK_Y2_RXSTAT_CHECK_PKT(FrameLength, FrameStatus, IsGoodPkt);
+
+	/*
+	** Take first receive buffer out of working queue 
+	*/
+	POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);
+	if (pSkPacket == NULL) {
+ 		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+			SK_DBGCAT_DRV_ERROR,
+			("Packet not available. NULL pointer.\n"));
+		return(SK_TRUE);
+	}
+
+	if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
+		NbrRxBuffersInHW--;
+	}
+
+	/* 
+	** Verify the received length of the frame! Note that having 
+	** multiple RxBuffers being aware of one single receive packet
+	** (one packet spread over multiple RxBuffers) is not supported 
+	** by this driver!
+	*/
+	if ((FrameLength > pAC->RxPort[Port].RxBufSize) || 
+		(FrameLength > (SK_U16) pSkPacket->PacketLen)) {
+		IsGoodPkt = SK_FALSE;
+	}
+
+	/* 
+	** Initialize vars for selected port 
+	*/
+	pLETab = &pAC->RxPort[Port].RxLET;
+
+	/* 
+	** Reset own bit in LE's between old and new Done index
+	** This is not really necessary but makes debugging easier 
+	*/
+	CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE);
+
+	/* 
+	** Free the list elements for new Rx buffers 
+	*/
+	SET_DONE_INDEX(pLETab, pSkPacket->NextLE);
+	pMsg = pSkPacket->pMBuf;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("Received frame of length %d on port %d\n",FrameLength, Port));
+
+	if (!IsGoodPkt) {
+		/* 
+		** release the DMA mapping 
+		*/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
+ 		pci_dma_sync_single(pAC->PciDev,
+				(dma_addr_t) pSkPacket->pFrag->pPhys,
+				pSkPacket->pFrag->FragLen,
+				PCI_DMA_FROMDEVICE);
+
+#else
+		pci_dma_sync_single_for_cpu(pAC->PciDev,
+				(dma_addr_t) pSkPacket->pFrag->pPhys,
+				pSkPacket->pFrag->FragLen,
+				PCI_DMA_FROMDEVICE);
+#endif
+
+		DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
+		PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+			("<== HandleReceives (Port %c)\n", 'A' + Port));
+
+		/*
+		** Sanity check for RxBuffer overruns...
+		*/
+		LenToFree = FrameLength - (pSkPacket->pFrag->FragLen);
+		while (LenToFree > 0) {
+			POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);
+			if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
+				NbrRxBuffersInHW--;
+			}
+			CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE);
+			SET_DONE_INDEX(pLETab, pSkPacket->NextLE);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
+			pci_dma_sync_single(pAC->PciDev,
+					(dma_addr_t) pSkPacket->pFrag->pPhys,
+					pSkPacket->pFrag->FragLen,
+					PCI_DMA_FROMDEVICE);
+#else
+			pci_dma_sync_single_for_device(pAC->PciDev,
+					(dma_addr_t) pSkPacket->pFrag->pPhys,
+					pSkPacket->pFrag->FragLen,
+					PCI_DMA_FROMDEVICE); 
+#endif
+
+			DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
+			PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
+			LenToFree = LenToFree - ((SK_I16)(pSkPacket->pFrag->FragLen));
+			
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+				("<==HandleReceives (Port %c) drop faulty len pkt(2)\n",'A'+Port));
+		}
+		return(SK_TRUE);
+	} else {
+		/* 
+		** Release the DMA mapping 
+		*/
+		pci_unmap_single(pAC->PciDev,
+				 pSkPacket->pFrag->pPhys,
+				 pAC->RxPort[Port].RxBufSize,
+				 PCI_DMA_FROMDEVICE);
+
+		skb_put(pMsg, FrameLength);		/* set message len */
+		pMsg->ip_summed = CHECKSUM_NONE;	/* initial default */
+
+#ifdef Y2_SYNC_CHECK
+		pAC->FramesWithoutSyncCheck++;
+		if (pAC->FramesWithoutSyncCheck > Y2_RESYNC_WATERMARK) {
+			if ((Tcp1 != 1) || (Tcp2 != 0)) {
+				pAC->FramesWithoutSyncCheck = 0;
+				MyTcp = (SK_U16) SkCsCalculateChecksum(
+						&pMsg->data[14],
+						FrameLength - 14);
+				if (MyTcp != Tcp1) {
+					/* Queue port reset event */
+					SkLocalEventQueue(pAC, SKGE_DRV,
+					SK_DRV_RECOVER,Port,-1,SK_FALSE);
+				}
+			}
+		}
+#endif
+
+		if (pAC->RxPort[Port].UseRxCsum) {
+#ifdef SK_EXTREME
+			if (HW_IS_EXT_LE_FORMAT(pAC)) {
+				/* Checksum calculation for Yukon Extreme */
+				if (CSS_IS_IPV4(ExtremeCsumResult) && CSS_IPV4_CSUM_OK(ExtremeCsumResult)) {
+        				pMsg->ip_summed = CHECKSUM_UNNECESSARY;
+				} else {
+        				pMsg->ip_summed = CHECKSUM_NONE;
+				}
+			} else {
+#endif
+				Type = ntohs(*((short*)&pMsg->data[12]));
+				if (Type == 0x800) {
+					*((char *)&(IpFrameLength)) = pMsg->data[16];
+					*(((char *)&(IpFrameLength))+1) = pMsg->data[17];
+					IpFrameLength = ntohs(IpFrameLength);
+					HeaderLength  = FrameLength - IpFrameLength;
+					if (HeaderLength == 0xe) {
+						Result = 
+						    SkCsGetReceiveInfo(pAC,&pMsg->data[14],Tcp1,Tcp2, Port, IpFrameLength);
+						if ((Result == SKCS_STATUS_IP_FRAGMENT) ||
+						    (Result == SKCS_STATUS_IP_CSUM_OK)  ||
+						    (Result == SKCS_STATUS_TCP_CSUM_OK) ||
+						    (Result == SKCS_STATUS_UDP_CSUM_OK)) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+							pMsg->ip_summed = CHECKSUM_COMPLETE;
+							pMsg->csum = Tcp1 & 0xffff;
+#else
+							pMsg->ip_summed = CHECKSUM_UNNECESSARY;
+#endif
+						} else if ((Result == SKCS_STATUS_TCP_CSUM_ERROR)    ||
+						           (Result == SKCS_STATUS_UDP_CSUM_ERROR)    ||
+						           (Result == SKCS_STATUS_IP_CSUM_ERROR_UDP) ||
+						           (Result == SKCS_STATUS_IP_CSUM_ERROR_TCP) ||
+						           (Result == SKCS_STATUS_IP_CSUM_ERROR)) {
+							SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+								SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+								("skge: CRC error. Frame dropped!\n"));
+							DEV_KFREE_SKB_ANY(pMsg);
+							PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
+							SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_RX_PROGRESS,
+								("<==HandleReceives(Port %c)\n",'A'+Port));
+							return(SK_TRUE);
+						} else {
+							pMsg->ip_summed = CHECKSUM_NONE;
+						}
+					} /* end if (HeaderLength == valid) */
+				} /* end if (Type == 0x800) -> IP frame */
+#ifdef SK_EXTREME
+			} /* if (HW_IS_EXT_LE_FORMAT(pAC)) */
+#endif
+		} /* end if (pRxPort->UseRxCsum) */
+		
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+			SK_DBGCAT_DRV_RX_PROGRESS,("V"));
+		RlmtNotifier = SK_RLMT_RX_PROTOCOL;
+
+		if (CheckBcMc == SK_TRUE) {
+
+			/* Check if this is a broadcast packet */
+			if (SK_ADDR_EQUAL(pMsg->data, "\xFF\xFF\xFF\xFF\xFF\xFF")) {
+
+				/* Broadcast packet */
+				FrameStatus |= GMR_FS_BC;
+			}
+			else if (pMsg->data[0] & 0x01) {
+
+				/* Multicast packet */
+				FrameStatus |= GMR_FS_MC;
+			}
+		}
+
+		IsBc = (FrameStatus & GMR_FS_BC) ? SK_TRUE : SK_FALSE;
+		SK_RLMT_PRE_LOOKAHEAD(pAC,Port,FrameLength,
+					IsBc,&Offset,&NumBytes);
+		if (NumBytes != 0) {
+			IsMc = (FrameStatus & GMR_FS_MC) ? SK_TRUE : SK_FALSE;
+			SK_RLMT_LOOKAHEAD(pAC,Port,&pMsg->data[Offset],
+						IsBc,IsMc,&RlmtNotifier);
+		}
+
+		if (RlmtNotifier == SK_RLMT_RX_PROTOCOL) {
+			SK_DBG_MSG(NULL,SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_RX_PROGRESS,("W"));
+			if ((Port == pAC->ActivePort)||(pAC->RlmtNets == 2)) {
+				/* send up only frames from active port */
+				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+					SK_DBGCAT_DRV_RX_PROGRESS,("U"));
+#ifdef xDEBUG
+				DumpMsg(pMsg, "Rx");
+#endif
+				SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
+					FrameLength, Port);
+#ifdef __ia64__
+				pNewMsg = alloc_skb(pMsg->len, GFP_ATOMIC);
+				skb_reserve(pNewMsg, 2); /* to align IP */
+				SK_MEMCPY(pNewMsg->data,pMsg->data,pMsg->len);
+				pNewMsg->ip_summed = pMsg->ip_summed;
+				skb_put(pNewMsg, pMsg->len);
+				DEV_KFREE_SKB_ANY(pMsg);
+				pMsg = pNewMsg;
+#endif
+				pMsg->dev = pAC->dev[Port];
+				pMsg->protocol = eth_type_trans(pMsg,
+					pAC->dev[Port]);
+#ifdef CONFIG_SK98LIN_NAPI
+				netif_receive_skb(pMsg);
+#else
+				netif_rx(pMsg);
+#endif
+				pAC->dev[Port]->last_rx = jiffies;
+			} else { /* drop frame */
+				SK_DBG_MSG(NULL,SK_DBGMOD_DRV,
+					SK_DBGCAT_DRV_RX_PROGRESS,("D"));
+				DEV_KFREE_SKB_ANY(pMsg);
+			}
+		} else { /* This is an RLMT-packet! */
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+				SK_DBGCAT_DRV_RX_PROGRESS,("R"));
+			pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
+				pAC->IoBase, FrameLength);
+			if (pRlmtMbuf != NULL) {
+				pRlmtMbuf->pNext = NULL;
+				pRlmtMbuf->Length = FrameLength;
+				pRlmtMbuf->PortIdx = Port;
+				EvPara.pParaPtr = pRlmtMbuf;
+				SK_MEMCPY((char*)(pRlmtMbuf->pData),
+				          (char*)(pMsg->data),FrameLength);
+
+#ifdef CONFIG_SK98LIN_NAPI
+				spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+#endif
+				SkEventQueue(pAC, SKGE_RLMT,
+						SK_RLMT_PACKET_RECEIVED,
+						EvPara);
+				pAC->CheckQueue = SK_TRUE;
+#ifdef CONFIG_SK98LIN_NAPI
+				spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+#endif
+				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+					SK_DBGCAT_DRV_RX_PROGRESS,("Q"));
+			}
+			if (pAC->dev[Port]->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
+#ifdef __ia64__
+				pNewMsg = alloc_skb(pMsg->len, GFP_ATOMIC);
+				skb_reserve(pNewMsg, 2); /* to align IP */
+				SK_MEMCPY(pNewMsg->data,pMsg->data,pMsg->len);
+				pNewMsg->ip_summed = pMsg->ip_summed;
+				pNewMsg->len = pMsg->len;
+				DEV_KFREE_SKB_ANY(pMsg);
+				pMsg = pNewMsg;
+#endif
+				pMsg->dev = pAC->dev[Port];
+				pMsg->protocol = eth_type_trans(pMsg,pAC->dev[Port]);
+				netif_rx(pMsg);
+				pAC->dev[Port]->last_rx = jiffies;
+			} else {
+				DEV_KFREE_SKB_ANY(pMsg);
+			}
+		} /* if packet for rlmt */
+		PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
+	} /* end if-else (IsGoodPkt) */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("<== HandleReceives (Port %c)\n", 'A' + Port));
+	return(SK_TRUE);
+
+}	/* HandleReceives */
+
+/***********************************************************************
+ *
+ * 	CheckForSendComplete - Frees any freeable Tx bufffer 
+ *
+ * Description:
+ *	This function checks the queues of a port for completed send
+ *	packets and returns these packets back to the OS.
+ *
+ * Notes:
+ *	This function can run simultaneously for both ports if
+ *	the OS function OSReturnPacket() can handle this,
+ *
+ *	Such a send complete does not mean, that the packet is really
+ *	out on the wire. We just know that the adapter has copied it
+ *	into its internal memory and the buffer in the systems memory
+ *	is no longer needed.
+ *
+ * Returns: N/A
+ */
+static void CheckForSendComplete(
+SK_AC         *pAC,     /* pointer to adapter control context  */
+SK_IOC         IoC,     /* I/O control context                 */
+int            Port,    /* port index                          */
+SK_PKT_QUEUE  *pPQ,     /* tx working packet queue to check    */
+SK_LE_TABLE   *pLETab,  /* corresponding list element table    */
+unsigned int   Done)    /* done index reported for this LET    */
+{
+	SK_PACKET       *pSkPacket;
+	SK_PKT_QUEUE     SendCmplPktQ = { NULL, NULL, SPIN_LOCK_UNLOCKED };
+	SK_BOOL          DoWakeQueue  = SK_FALSE;
+	unsigned long    Flags;
+	unsigned         Put;
+	
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("==> CheckForSendComplete(Port %c)\n", 'A' + Port));
+
+	/* 
+	** Reset own bit in LE's between old and new Done index
+	** This is not really necessairy but makes debugging easier 
+	*/
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("Clear Own Bits in TxTable from %d to %d\n",
+		pLETab->Done, (Done == 0) ?
+		NUM_LE_IN_TABLE(pLETab) :
+		(Done - 1)));
+
+	spin_lock_irqsave(&(pPQ->QueueLock), Flags);
+
+	CLEAR_LE_OWN_FROM_DONE_TO(pLETab, Done);
+
+	Put = GET_PUT_IDX(pLETab);
+
+	/* 
+	** Check whether some packets have been completed 
+	*/
+	PLAIN_POP_FIRST_PKT_FROM_QUEUE(pPQ, pSkPacket);
+	while (pSkPacket != NULL) {
+		
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+			("Check Completion of Tx packet %p\n", pSkPacket));
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+			("Put %d NewDone %d NextLe of Packet %d\n", Put, Done,
+			pSkPacket->NextLE));
+
+		if ((Put > Done) &&
+			((pSkPacket->NextLE > Put) || (pSkPacket->NextLE <= Done))) {
+			PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket);
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+				("Packet finished (a)\n"));
+		} else if ((Done > Put) &&
+			(pSkPacket->NextLE > Put) && (pSkPacket->NextLE <= Done)) {
+			PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket);
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+				("Packet finished (b)\n"));
+		} else if ((Done == NUMBER_OF_TX_LE-1) && (Put == 0) && (pSkPacket->NextLE == 0)) {
+			PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket);
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+				("Packet finished (b)\n"));
+			DoWakeQueue = SK_TRUE;
+		} else if (Done == Put) {
+			/* all packets have been sent */
+			PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket);
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+				("Packet finished (c)\n"));
+		} else {
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+				("Packet not yet finished\n"));
+			PLAIN_PUSH_PKT_AS_FIRST_IN_QUEUE(pPQ, pSkPacket);
+			break;
+		}
+		PLAIN_POP_FIRST_PKT_FROM_QUEUE(pPQ, pSkPacket);
+	}
+	spin_unlock_irqrestore(&(pPQ->QueueLock), Flags);
+
+	/* 
+	** Set new done index in list element table
+	*/
+	SET_DONE_INDEX(pLETab, Done);
+	 
+	/*
+	** All TX packets that are send complete should be added to
+	** the free queue again for new sents to come
+	*/
+	pSkPacket = SendCmplPktQ.pHead;
+	while (pSkPacket != NULL) {
+		while (pSkPacket->pFrag != NULL) {
+			pci_unmap_page(pAC->PciDev,
+					(dma_addr_t) pSkPacket->pFrag->pPhys,
+					pSkPacket->pFrag->FragLen,
+					PCI_DMA_FROMDEVICE);
+			pSkPacket->pFrag = pSkPacket->pFrag->pNext;
+		}
+
+		DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
+		pSkPacket->pMBuf	= NULL;
+		pSkPacket = pSkPacket->pNext; /* get next packet */
+	}
+
+	/*
+	** Append the available TX packets back to free queue
+	*/
+	if (SendCmplPktQ.pHead != NULL) { 
+		spin_lock_irqsave(&(pAC->TxPort[Port][0].TxQ_free.QueueLock), Flags);
+		if (pAC->TxPort[Port][0].TxQ_free.pTail != NULL) {
+			pAC->TxPort[Port][0].TxQ_free.pTail->pNext = SendCmplPktQ.pHead;
+			pAC->TxPort[Port][0].TxQ_free.pTail        = SendCmplPktQ.pTail;
+			if (pAC->TxPort[Port][0].TxQ_free.pHead->pNext == NULL) {
+				netif_wake_queue(pAC->dev[Port]);
+			}
+		} else {
+			pAC->TxPort[Port][0].TxQ_free.pHead = SendCmplPktQ.pHead;
+			pAC->TxPort[Port][0].TxQ_free.pTail = SendCmplPktQ.pTail; 
+			netif_wake_queue(pAC->dev[Port]);
+		}
+		if (Done == Put) {
+			netif_wake_queue(pAC->dev[Port]);
+		}
+		if (DoWakeQueue) {
+			netif_wake_queue(pAC->dev[Port]);
+			DoWakeQueue = SK_FALSE;
+		}
+		spin_unlock_irqrestore(&pAC->TxPort[Port][0].TxQ_free.QueueLock, Flags);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("<== CheckForSendComplete()\n"));
+
+	return;
+}	/* CheckForSendComplete */
+
+/*****************************************************************************
+ *
+ *	UnmapAndFreeTxPktBuffer
+ *
+ * Description:
+ *      This function free any allocated space of receive buffers
+ *
+ * Arguments:
+ *      pAC - A pointer to the adapter context struct.
+ *
+ */
+static void UnmapAndFreeTxPktBuffer(
+SK_AC       *pAC,       /* pointer to adapter context             */
+SK_PACKET   *pSkPacket,	/* pointer to port struct of ring to fill */
+int          TxPort)    /* TX port index                          */
+{
+	SK_FRAG	 *pFrag = pSkPacket->pFrag;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("--> UnmapAndFreeTxPktBuffer\n"));
+
+	while (pFrag != NULL) {
+		pci_unmap_page(pAC->PciDev,
+				(dma_addr_t) pFrag->pPhys,
+				pFrag->FragLen,
+				PCI_DMA_FROMDEVICE);
+		pFrag = pFrag->pNext;
+	}
+
+	DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
+	pSkPacket->pMBuf	= NULL;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+		("<-- UnmapAndFreeTxPktBuffer\n"));
+}
+
+/*****************************************************************************
+ *
+ * 	HandleStatusLEs
+ *
+ * Description:
+ *	This function checks for any new status LEs that may have been 
+  *	received. Those status LEs may either be Rx or Tx ones.
+ *
+ * Returns:	N/A
+ */
+static SK_BOOL HandleStatusLEs(
+#ifdef CONFIG_SK98LIN_NAPI
+SK_AC *pAC,       /* pointer to adapter context   */
+int   *WorkDone,  /* Done counter needed for NAPI */
+int    WorkToDo)  /* ToDo counter for NAPI        */
+#else
+SK_AC *pAC)       /* pointer to adapter context   */
+#endif
+{
+	int       DoneTxA[SK_MAX_MACS];
+	int       DoneTxS[SK_MAX_MACS];
+	int       Port;
+	SK_BOOL   handledStatLE = SK_FALSE;
+	SK_BOOL   NewDone       = SK_FALSE;
+	SK_HWLE  *pLE;
+	SK_U16    HighVal;
+	SK_U32    LowVal;
+	SK_U32    IntSrc;
+	SK_U8     OpCode;
+	int       i;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+		("==> HandleStatusLEs\n"));
+
+	do {
+		if (OWN_OF_FIRST_LE(&pAC->StatusLETable) != HW_OWNER)
+			break;
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+			("Check next Own Bit of ST-LE[%d]: 0x%li \n",
+			(pAC->StatusLETable.Done + 1) % NUM_LE_IN_TABLE(&pAC->StatusLETable),
+			 OWN_OF_FIRST_LE(&pAC->StatusLETable)));
+
+		while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER) {
+			GET_ST_LE(pLE, &pAC->StatusLETable);
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+				("Working on finished status LE[%d]:\n",
+				GET_DONE_INDEX(&pAC->StatusLETable)));
+#if 0
+			SK_DBG_DUMP_ST_LE(pLE);
+#endif
+			handledStatLE = SK_TRUE;
+			OpCode = STLE_GET_OPC(pLE) & ~HW_OWNER;
+			Port = STLE_GET_LINK(pLE);
+
+#ifdef USE_TIST_FOR_RESET
+			if (!HW_IS_EXT_LE_FORMAT(pAC) && SK_ADAPTER_WAITING_FOR_TIST(pAC)) {
+				/* do we just have a tist LE ? */
+				if ((OpCode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) {
+					for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+						if (SK_PORT_WAITING_FOR_ANY_TIST(pAC, i)) {
+							/* if a port is waiting for any tist it is done */
+							SK_CLR_STATE_FOR_PORT(pAC, i);
+							SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+								("Got any Tist on port %c (now 0x%X!!!)\n",
+								'A' + i, pAC->AdapterResetState));
+						}
+						if (SK_PORT_WAITING_FOR_SPECIFIC_TIST(pAC, i)) {
+							Y2_GET_TIST_LOW_VAL(pAC->IoBase, &LowVal);
+							if ((pAC->MinTistHi != pAC->GIni.GITimeStampCnt) ||
+								(pAC->MinTistLo < LowVal)) {
+								/* time is up now */
+								SK_CLR_STATE_FOR_PORT(pAC, i);
+								SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+									("Got expected Tist on Port %c (now 0x%X)!!!\n",
+									'A' + i, pAC->AdapterResetState));
+#ifdef Y2_SYNC_CHECK
+								pAC->FramesWithoutSyncCheck =
+								Y2_RESYNC_WATERMARK;						
+#endif
+							} else {
+								SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+									("Got Tist %l:%l on Port %c but still waiting\n",
+									pAC->GIni.GITimeStampCnt, pAC->MinTistLo,
+									'A' + i));
+							}
+						}
+					}
+#ifndef Y2_RECOVERY
+					if (!SK_ADAPTER_WAITING_FOR_TIST(pAC)) {
+						/* nobody needs tist anymore - turn it off */
+						Y2_DISABLE_TIST(pAC->IoBase);
+						SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+						("Turn off Tist !!!\n"));
+					}
+#endif
+				} else if (OpCode == OP_TXINDEXLE) {
+					/*
+					 * change OpCode to notify the folowing code
+					 * to ignore the done index from this LE
+					 * unfortunately tist LEs will be generated only
+					 * for RxStat LEs
+					 * so in order to get a safe Done index for a
+					 * port currently waiting for a tist we have to
+					 * get the done index directly from the BMU
+					 */
+					OpCode = OP_MOD_TXINDEX;
+					SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+						("Mark unusable TX_INDEX LE!!!\n"));
+				} else {
+					if (SK_PORT_WAITING_FOR_TIST(pAC, Port)) {
+						SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, 
+							("Ignore LE 0x%X on Port %c!!!\n",
+							OpCode, 'A' + Port));
+						OpCode = OP_MOD_LE;
+#ifdef Y2_LE_CHECK
+						/* mark entries invalid */
+						pAC->LastOpc = 0xFF;
+						pAC->LastPort = 3;
+#endif
+					}
+				}
+			} /* if (SK_ADAPTER_WAITING_FOR_TIST(pAC)) */
+#endif
+
+
+
+
+
+#ifdef Y2_LE_CHECK
+			if (!HW_IS_EXT_LE_FORMAT(pAC) && pAC->LastOpc != 0xFF) {
+				/* last opc is valid
+				 * check if current opcode follows last opcode
+				 */
+				if ((((OpCode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) && (pAC->LastOpc != OP_RXSTAT)) ||
+				    (((OpCode & OP_RXCHKS) == OP_RXCHKS) && (pAC->LastOpc != OP_RXTIMESTAMP)) ||
+				    ((OpCode == OP_RXSTAT) && (pAC->LastOpc != OP_RXCHKS))) {
+
+					/* opcode sequence broken
+					 * current LE is invalid
+					 */
+
+					if (pAC->LastOpc == OP_RXTIMESTAMP) {
+						/* force invalid checksum */
+						pLE->St.StUn.StRxTCPCSum.RxTCPSum1 = 1;
+						pLE->St.StUn.StRxTCPCSum.RxTCPSum2 = 0;
+						OpCode = pAC->LastOpc = OP_RXCHKS;
+						Port = pAC->LastPort;
+					} else if (pAC->LastOpc == OP_RXCHKS) {
+						/* force invalid frame */
+						Port = pAC->LastPort;
+						pLE->St.Stat.BufLen = 64;
+						pLE->St.StUn.StRxStatWord = GMR_FS_CRC_ERR;
+						OpCode = pAC->LastOpc = OP_RXSTAT;
+#ifdef Y2_SYNC_CHECK
+						/* force rx sync check */
+						pAC->FramesWithoutSyncCheck = Y2_RESYNC_WATERMARK;
+#endif
+					} else if (pAC->LastOpc == OP_RXSTAT) {
+						/* create dont care tist */
+						pLE->St.StUn.StRxTimeStamp = 0;
+						OpCode = pAC->LastOpc = OP_RXTIMESTAMP;
+						/* dont know the port yet */
+					} else {
+#ifdef DEBUG
+						SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+							("Unknown LastOpc %X for Timestamp on port %c.\n",
+							pAC->LastOpc, Port));
+#endif
+					}
+				}
+			}
+#endif
+
+			switch (OpCode) {
+			case OP_RXSTAT:
+#ifdef Y2_RECOVERY
+				pAC->LastOpc = OP_RXSTAT;
+#endif
+				/* 
+				** This is always the last Status LE belonging
+				** to a received packet -> handle it...
+				*/
+
+				HandleReceives(
+					pAC,
+#ifdef SK_EXTREME
+					CSS_GET_PORT(Port),
+#else
+ 					Port,
+#endif
+					STLE_GET_LEN(pLE),
+					STLE_GET_FRSTATUS(pLE),
+					pAC->StatusLETable.Bmu.Stat.TcpSum1,
+					pAC->StatusLETable.Bmu.Stat.TcpSum2,
+					pAC->StatusLETable.Bmu.Stat.RxTimeStamp,
+                                        pAC->StatusLETable.Bmu.Stat.VlanId
+#ifdef SK_EXTREME
+					,Port
+#endif
+                                        );
+#ifdef CONFIG_SK98LIN_NAPI
+				if (*WorkDone >= WorkToDo) {
+					break;
+				}
+				(*WorkDone)++;
+#endif
+				break;
+			case OP_RXVLAN:
+				/* this value will be used for next RXSTAT */
+				pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE);
+				break;
+			case OP_RXTIMEVLAN:
+				/* this value will be used for next RXSTAT */
+				pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE);
+				/* fall through */
+			case OP_RXTIMESTAMP:
+				/* this value will be used for next RXSTAT */
+				pAC->StatusLETable.Bmu.Stat.RxTimeStamp = STLE_GET_TIST(pLE);
+#ifdef Y2_RECOVERY
+				pAC->LastOpc = OP_RXTIMESTAMP;
+				pAC->LastPort = Port;
+#endif
+				break;
+			case OP_RXCHKSVLAN:
+				/* this value will be used for next RXSTAT */
+				pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE);
+				/* fall through */
+			case OP_RXCHKS:
+				/* this value will be used for next RXSTAT */
+				pAC->StatusLETable.Bmu.Stat.TcpSum1 = STLE_GET_TCP1(pLE);
+				pAC->StatusLETable.Bmu.Stat.TcpSum2 = STLE_GET_TCP2(pLE);
+#ifdef Y2_RECOVERY
+				pAC->LastPort = Port;
+				pAC->LastOpc = OP_RXCHKS;
+#endif
+				break;
+			case OP_RSS_HASH:
+				/* this value will be used for next RXSTAT */
+#if 0
+				pAC->StatusLETable.Bmu.Stat.RssHashValue = STLE_GET_RSS(pLE);
+#endif
+				break;
+			case OP_TXINDEXLE:
+				/*
+				** :;:; TODO
+				** it would be possible to check for which queues
+				** the index has been changed and call 
+				** CheckForSendComplete() only for such queues
+				*/
+				STLE_GET_DONE_IDX(pLE,LowVal,HighVal);
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+					("LowVal: 0x%x HighVal: 0x%x\n", LowVal, HighVal));
+
+				/*
+				** It would be possible to check whether we really
+				** need the values for second port or sync queue, 
+				** but I think checking whether we need them is 
+				** more expensive than the calculation
+				*/
+				DoneTxA[0] = STLE_GET_DONE_IDX_TXA1(LowVal,HighVal);
+				DoneTxS[0] = STLE_GET_DONE_IDX_TXS1(LowVal,HighVal);
+				DoneTxA[1] = STLE_GET_DONE_IDX_TXA2(LowVal,HighVal);
+				DoneTxS[1] = STLE_GET_DONE_IDX_TXS2(LowVal,HighVal);
+
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+					("DoneTxa1 0x%x DoneTxS1: 0x%x DoneTxa2 0x%x DoneTxS2: 0x%x\n",
+					DoneTxA[0], DoneTxS[0], DoneTxA[1], DoneTxS[1]));
+
+				NewDone = SK_TRUE;
+				break;
+#ifdef USE_TIST_FOR_RESET
+			case OP_MOD_TXINDEX:
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+					("OP_MOD_TXINDEX\n"));
+				SK_IN16(pAC->IoBase, Q_ADDR(Q_XA1, Q_DONE), &DoneTxA[0]);
+				if (pAC->GIni.GIMacsFound > 1) {
+					SK_IN16(pAC->IoBase, Q_ADDR(Q_XA2, Q_DONE), &DoneTxA[1]);
+				}
+				NewDone = SK_TRUE;
+				break;
+			case OP_MOD_LE:
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
+				("Ignore marked LE on port in Reset\n"));
+				break;
+#endif
+
+			default:
+				/* 
+				** Have to handle the illegal Opcode in Status LE 
+				*/
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+					("Unexpected OpCode\n"));
+				break;
+			}
+
+#ifdef Y2_RECOVERY
+			OpCode = STLE_GET_OPC(pLE) & ~HW_OWNER;
+			STLE_SET_OPC(pLE, OpCode);
+#else
+			/* 
+			** Reset own bit we have to do this in order to detect a overflow 
+			*/
+			STLE_SET_OPC(pLE, SW_OWNER);
+#endif
+		} /* while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER) */
+
+		/* 
+		** Now handle any new transmit complete 
+		*/
+		if (NewDone) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+				("Done Index for Tx BMU has been changed\n"));
+			for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
+				/* 
+				** Do we have a new Done idx ? 
+				*/
+				if (DoneTxA[Port] != GET_DONE_INDEX(&pAC->TxPort[Port][0].TxALET)) {
+					SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+						("Check TxA%d\n", Port + 1));
+					CheckForSendComplete(pAC, pAC->IoBase, Port,
+						&(pAC->TxPort[Port][0].TxAQ_working),
+						&pAC->TxPort[Port][0].TxALET,
+						DoneTxA[Port]);
+				} else {
+					SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+						("No changes for TxA%d\n", Port + 1));
+				}
+#ifdef USE_SYNC_TX_QUEUE
+				if (HW_SYNC_TX_SUPPORTED(pAC)) {
+					/* 
+					** Do we have a new Done idx ? 
+					*/
+					if (DoneTxS[Port] !=
+						GET_DONE_INDEX(&pAC->TxPort[Port][0].TxSLET)) {
+						SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+							SK_DBGCAT_DRV_INT_SRC,
+							("Check TxS%d\n", Port));
+						CheckForSendComplete(pAC, pAC->IoBase, Port,
+							&(pAC->TxPort[Port][0].TxSQ_working),
+							&pAC->TxPort[Port][0].TxSLET,
+							DoneTxS[Port]);
+					} else {
+						SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+							SK_DBGCAT_DRV_INT_SRC,
+							("No changes for TxS%d\n", Port));
+					}
+				}
+#endif
+			}
+		}
+		NewDone = SK_FALSE;
+
+		/* 
+		** Check whether we have to refill our RX table  
+		*/
+		if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
+			if (NbrRxBuffersInHW < MAX_NBR_RX_BUFFERS_IN_HW) {
+				for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
+					SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+						("Check for refill of RxBuffers on Port %c\n", 'A' + Port));
+					FillReceiveTableYukon2(pAC, pAC->IoBase, Port);
+				}
+			}
+		} else {
+			for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
+				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+					("Check for refill of RxBuffers on Port %c\n", 'A' + Port));
+				if (NUM_FREE_LE_IN_TABLE(&pAC->RxPort[Port].RxLET) >= 64) {
+					FillReceiveTableYukon2(pAC, pAC->IoBase, Port);
+				}
+			}
+		}
+#ifdef CONFIG_SK98LIN_NAPI
+		if (*WorkDone >= WorkToDo) {
+			break;
+		}
+#endif
+	} while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER);
+
+	/* 
+	** Clear status BMU 
+	*/
+	if (handledStatLE) {
+		SK_OUT32(pAC->IoBase, STAT_CTRL, SC_STAT_CLR_IRQ);
+
+		/* Reread interrupt source */
+		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+	}
+
+	return(handledStatLE);
+}	/* HandleStatusLEs */
+
+/*****************************************************************************
+ *
+ *	AllocateAndInitLETables - allocate memory for the LETable and init
+ *
+ * Description:
+ *	This function will allocate space for the LETable and will also  
+ *	initialize them. The size of the tables must have been specified 
+ *	before.
+ *
+ * Arguments:
+ *	pAC - A pointer to the adapter context struct.
+ *
+ * Returns:
+ *	SK_TRUE  - all LETables initialized
+ *	SK_FALSE - failed
+ */
+static SK_BOOL AllocateAndInitLETables(
+SK_AC *pAC)  /* pointer to adapter context */
+{
+	char           *pVirtMemAddr;
+	char           *pAddr;
+	dma_addr_t     pPhysMemAddr = 0;
+	dma_addr_t     pPhysOrgMemAddr = 0;
+	SK_U32         CurrMac;
+	unsigned       Size;
+	unsigned       Aligned;
+	unsigned       Alignment;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("==> AllocateAndInitLETables()\n"));
+
+	/*
+	** Determine how much memory we need with respect to alignment
+	*/
+	Alignment = (SK_U32) LE_TAB_SIZE(NUMBER_OF_ST_LE);
+	Size = 0;
+	for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {
+		SK_ALIGN_SIZE(LE_TAB_SIZE(NUMBER_OF_RX_LE), Alignment, Aligned);
+		Size += Aligned;
+		SK_ALIGN_SIZE(LE_TAB_SIZE(NUMBER_OF_TX_LE), Alignment, Aligned);
+		Size += Aligned;
+		SK_ALIGN_SIZE(LE_TAB_SIZE(TXS_MAX_LE), Alignment, Aligned);
+		Size += Aligned;
+	}
+	SK_ALIGN_SIZE(LE_TAB_SIZE(NUMBER_OF_ST_LE), Alignment, Aligned);
+	Size += Aligned;
+	Size += Alignment;
+	pAC->SizeOfAlignedLETables = Size;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, 
+			("Need %08x bytes in total\n", Size));
+	
+	/*
+	** Allocate the memory
+	*/
+	pVirtMemAddr = pci_alloc_consistent(pAC->PciDev, Size, &pPhysMemAddr);
+	pAC->pVirtMemAddr = pVirtMemAddr;
+
+	if (pVirtMemAddr == NULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 
+			SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
+			("AllocateAndInitLETables: kernel malloc failed!\n"));
+		return (SK_FALSE); 
+	}
+
+	/* 
+	** Initialize the memory
+	*/
+	SK_MEMSET(pVirtMemAddr, 0, Size);
+	pPhysOrgMemAddr = pPhysMemAddr;
+	pAddr = (void *) (SK_U32) pPhysMemAddr;
+	ALIGN_ADDR(pAddr, Alignment); /* Macro defined in skgew.h */
+	pPhysMemAddr = (dma_addr_t) (SK_U32) pAddr;
+	pVirtMemAddr += pPhysMemAddr - pPhysOrgMemAddr;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("Virtual address of LETab is %8p!\n", pVirtMemAddr));
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("Phys address of LETab is %8p!\n", (void *) pPhysMemAddr));
+
+	for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+			("RxLeTable for Port %c", 'A' + CurrMac));
+		SkGeY2InitSingleLETable(
+			pAC,
+			&pAC->RxPort[CurrMac].RxLET,
+			NUMBER_OF_RX_LE,
+			pVirtMemAddr,
+			(SK_U32) (pPhysMemAddr & 0xffffffff),
+			(SK_U32) (((SK_U64) pPhysMemAddr) >> 32));
+
+		SK_ALIGN_SIZE(LE_TAB_SIZE(NUMBER_OF_RX_LE), Alignment, Aligned);
+		pVirtMemAddr += Aligned;
+		pPhysMemAddr += Aligned;
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+			("TxALeTable for Port %c", 'A' + CurrMac));
+		SkGeY2InitSingleLETable(
+			pAC,
+			&pAC->TxPort[CurrMac][0].TxALET,
+			NUMBER_OF_TX_LE,
+			pVirtMemAddr,
+			(SK_U32) (pPhysMemAddr & 0xffffffff),
+			(SK_U32) (((SK_U64) pPhysMemAddr) >> 32));
+
+		SK_ALIGN_SIZE(LE_TAB_SIZE(NUMBER_OF_TX_LE), Alignment, Aligned);
+		pVirtMemAddr += Aligned;
+		pPhysMemAddr += Aligned;
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+			("TxSLeTable for Port %c", 'A' + CurrMac));
+		SkGeY2InitSingleLETable(
+			pAC,
+			&pAC->TxPort[CurrMac][0].TxSLET,
+			TXS_MAX_LE,
+			pVirtMemAddr,
+			(SK_U32) (pPhysMemAddr & 0xffffffff),
+			(SK_U32) (((SK_U64) pPhysMemAddr) >> 32));
+
+		SK_ALIGN_SIZE(LE_TAB_SIZE(TXS_MAX_LE), Alignment, Aligned);
+		pVirtMemAddr += Aligned;
+		pPhysMemAddr += Aligned;
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,("StLeTable"));
+
+	SkGeY2InitSingleLETable(
+		pAC,
+		&pAC->StatusLETable,
+		NUMBER_OF_ST_LE,
+		pVirtMemAddr,
+		(SK_U32) (pPhysMemAddr & 0xffffffff),
+		(SK_U32) (((SK_U64) pPhysMemAddr) >> 32));
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, 
+		("<== AllocateAndInitLETables(OK)\n"));
+	return(SK_TRUE);
+}	/* AllocateAndInitLETables */
+
+/*****************************************************************************
+ *
+ *	AllocatePacketBuffersYukon2 - allocate packet and fragment buffers
+ *
+ * Description:
+ *      This function will allocate space for the packets and fragments
+ *
+ * Arguments:
+ *      pAC - A pointer to the adapter context struct.
+ *
+ * Returns:
+ *      SK_TRUE  - Memory was allocated correctly
+ *      SK_FALSE - An error occured
+ */
+static SK_BOOL AllocatePacketBuffersYukon2(
+SK_AC *pAC)  /* pointer to adapter context */
+{
+	SK_PACKET       *pRxPacket;
+	SK_PACKET       *pTxPacket;
+	SK_U32           CurrBuff;
+	SK_U32           CurrMac;
+	unsigned long    Flags; /* needed for POP/PUSH functions */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("==> AllocatePacketBuffersYukon2()"));
+
+	for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {
+		/* 
+		** Allocate RX packet space, initialize the packets and
+		** add them to the RX waiting queue. Waiting queue means 
+		** that packet and fragment are initialized, but no sk_buff
+		** has been assigned to it yet.
+		*/
+		pAC->RxPort[CurrMac].ReceivePacketTable = 
+			kmalloc((RX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)), GFP_KERNEL);
+
+		if (pAC->RxPort[CurrMac].ReceivePacketTable == NULL) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
+				("AllocatePacketBuffersYukon2: no mem RxPkts (port %i)",CurrMac));
+			break;
+		} else {
+			SK_MEMSET(pAC->RxPort[CurrMac].ReceivePacketTable, 0, 
+				(RX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)));
+
+			pRxPacket = pAC->RxPort[CurrMac].ReceivePacketTable;
+
+			for (CurrBuff=0;CurrBuff<RX_MAX_NBR_BUFFERS;CurrBuff++) {
+				pRxPacket->pFrag = &(pRxPacket->FragArray[0]);
+				pRxPacket->NumFrags = 1;
+				PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[CurrMac].RxQ_waiting, pRxPacket);
+				pRxPacket++;
+			}
+		}
+
+		/*
+		** Allocate TX packet space, initialize the packets and
+		** add them to the TX free queue. Free queue means that
+		** packet is available and initialized, but no fragment
+		** has been assigned to it. (Must be done at TX side)
+		*/
+		pAC->TxPort[CurrMac][0].TransmitPacketTable = 
+			kmalloc((TX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)), GFP_KERNEL);
+
+		if (pAC->TxPort[CurrMac][0].TransmitPacketTable == NULL) {
+			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
+				("AllocatePacketBuffersYukon2: no mem TxPkts (port %i)",CurrMac));
+			kfree(pAC->RxPort[CurrMac].ReceivePacketTable);
+			return(SK_FALSE);
+		} else {
+			SK_MEMSET(pAC->TxPort[CurrMac][0].TransmitPacketTable, 0, 
+				(TX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)));
+		
+			pTxPacket = pAC->TxPort[CurrMac][0].TransmitPacketTable;
+
+			for (CurrBuff=0;CurrBuff<TX_MAX_NBR_BUFFERS;CurrBuff++) {
+				PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[CurrMac][0].TxQ_free, pTxPacket);
+				pTxPacket++;
+			}
+		}
+	} /* end for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
+		("<== AllocatePacketBuffersYukon2 (OK)\n"));
+	return(SK_TRUE);
+
+}	/* AllocatePacketBuffersYukon2 */
+
+/*****************************************************************************
+ *
+ *	FreeLETables - release allocated memory of LETables
+ *
+ * Description:
+ *      This function will free all resources of the LETables
+ *
+ * Arguments:
+ *      pAC - A pointer to the adapter context struct.
+ *
+ * Returns: N/A
+ */
+static void FreeLETables(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+	dma_addr_t	pPhysMemAddr;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> FreeLETables()\n"));
+	
+	/*
+	** The RxLETable is the first of all LET. 
+	** Therefore we can use its address for the input 
+	** of the free function.
+	*/
+	pPhysMemAddr = (((SK_U64) pAC->RxPort[0].RxLET.pPhyLETABHigh << (SK_U64) 32) | 
+			((SK_U64) pAC->RxPort[0].RxLET.pPhyLETABLow));
+
+	/* free continuous memory */
+	pci_free_consistent(pAC->PciDev, pAC->SizeOfAlignedLETables,
+			    pAC->pVirtMemAddr, pPhysMemAddr);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== FreeLETables()\n"));
+}	/* FreeLETables */
+
+/*****************************************************************************
+ *
+ *	FreePacketBuffers - free's all packet buffers of an adapter
+ *
+ * Description:
+ *      This function will free all previously allocated memory of the 
+ *	packet buffers.
+ *
+ * Arguments:
+ *      pAC - A pointer to the adapter context struct.
+ *
+ * Returns: N/A
+ */
+static void FreePacketBuffers(
+SK_AC *pAC)  /* pointer to adapter control context */
+{
+	int Port;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("==> FreePacketBuffers()\n"));
+	
+	for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
+		kfree(pAC->RxPort[Port].ReceivePacketTable);
+		kfree(pAC->TxPort[Port][0].TransmitPacketTable);
+	}
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
+		("<== FreePacketBuffers()\n"));
+}	/* FreePacketBuffers */
+
+/*****************************************************************************
+ *
+ * 	AllocAndMapRxBuffer - fill one buffer into the receive packet/fragment
+ *
+ * Description:
+ *	The function allocates a new receive buffer and assigns it to the
+ *	the passsed receive packet/fragment
+ *
+ * Returns:
+ *	SK_TRUE - a buffer was allocated and assigned
+ *	SK_FALSE - a buffer could not be added
+ */
+static SK_BOOL AllocAndMapRxBuffer(
+SK_AC      *pAC,        /* pointer to the adapter control context */
+SK_PACKET  *pSkPacket,  /* pointer to packet that is to fill      */
+int         Port)       /* port the packet belongs to             */
+{
+	struct sk_buff *pMsgBlock;  /* pointer to a new message block  */
+	SK_U64          PhysAddr;   /* physical address of a rx buffer */
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("--> AllocAndMapRxBuffer (Port: %i)\n", Port));
+
+	pMsgBlock = alloc_skb(pAC->RxPort[Port].RxBufSize, GFP_ATOMIC);
+	if (pMsgBlock == NULL) {
+		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+			SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
+			("%s: Allocation of rx buffer failed !\n",
+			pAC->dev[Port]->name));
+		SK_PNMI_CNT_NO_RX_BUF(pAC, pAC->RxPort[Port].PortIndex);
+		return(SK_FALSE);
+	}
+	skb_reserve(pMsgBlock, 8);
+
+	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+		virt_to_page(pMsgBlock->data),
+		((unsigned long) pMsgBlock->data &
+		~PAGE_MASK),
+		pAC->RxPort[Port].RxBufSize,
+		PCI_DMA_FROMDEVICE);
+
+	pSkPacket->pFrag->pVirt   = pMsgBlock->data;
+	pSkPacket->pFrag->pPhys   = PhysAddr;
+	pSkPacket->pFrag->FragLen = pAC->RxPort[Port].RxBufSize; /* for correct unmap */
+	pSkPacket->pMBuf          = pMsgBlock;	
+	pSkPacket->PacketLen      = pAC->RxPort[Port].RxBufSize;
+
+	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
+		("<-- AllocAndMapRxBuffer\n"));
+
+	return (SK_TRUE);
+}	/* AllocAndMapRxBuffer */
+
+/*******************************************************************************
+ *
+ * End of file
+ *
+ ******************************************************************************/
diff --git a/drivers/net/sk98lin/sky2le.c b/drivers/net/sk98lin/sky2le.c
new file mode 100755
index 0000000..c187773
--- /dev/null
+++ b/drivers/net/sk98lin/sky2le.c
@@ -0,0 +1,501 @@
+/*****************************************************************************
+ *
+ *	Name:		sky2le.c
+ *	Project:	Gigabit Ethernet Adapters, Common Modules
+ *	Version:	$Revision: 1.15 $
+ *	Date:		$Date: 2007/06/27 14:49:18 $
+ *	Purpose: 	Functions for handling List Element Tables
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ *	LICENSE:
+ *	(C)Copyright 2002-2007 Marvell.
+ *
+ *	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.
+ *	The information in this file is provided "AS IS" without warranty.
+ *	/LICENSE
+ *
+ ******************************************************************************/
+
+/*****************************************************************************
+ *
+ * Description:
+ *
+ * This module contains the code necessary for handling List Elements.
+ *
+ * Supported Gigabit Ethernet Chipsets:
+ *	Yukon-2 (PCI, PCI-X, PCI-Express)
+ *
+ * Include File Hierarchy:
+ *
+ *
+ *****************************************************************************/
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+
+/* defines *******************************************************************/
+/* typedefs ******************************************************************/
+/* global variables **********************************************************/
+/* local variables ***********************************************************/
+
+#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+static const char SysKonnectFileId[] =
+	"@(#) $Id: sky2le.c,v 1.15 2007/06/27 14:49:18 rschmidt Exp $ (C) Marvell.";
+#endif /* DEBUG || (!LINT && !SK_SLIM) */
+
+/* function prototypes *******************************************************/
+
+/*****************************************************************************
+ *
+ * SkGeY2InitSingleLETable() - initializes a list element table
+ *
+ * Description:
+ *	This function will initialize the selected list element table.
+ *	Should be called once during DriverInit. No InitLevel required.
+ *
+ * Arguments:
+ *	pAC			- pointer to the adapter context struct.
+ *	pLETab		- pointer to list element table structure
+ *	NumLE		- number of list elements in this table
+ *	pVMem		- virtual address of memory allocated for this LE table
+ *	PMemLowAddr - physical address of memory to be used for the LE table
+ *	PMemHighAddr
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGeY2InitSingleLETable(
+SK_AC	*pAC,			/* pointer to adapter context */
+SK_LE_TABLE	*pLETab,	/* pointer to list element table to be initialized */
+unsigned int NumLE,		/* number of list elements to be filled in tab */
+void	*pVMem,			/* virtual address of memory used for list elements */
+SK_U32	PMemLowAddr,	/* physical address of memory used for LE */
+SK_U32	PMemHighAddr)
+{
+	unsigned int i;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("==> SkGeY2InitSingleLETable()\n"));
+
+#ifdef DEBUG
+	if (NumLE != 2) {	/* not table for polling unit */
+		if ((NumLE % MIN_LEN_OF_LE_TAB) != 0 || NumLE > MAX_LEN_OF_LE_TAB) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("ERROR: Illegal number of list elements %d\n", NumLE));
+		}
+	}
+#endif /* DEBUG */
+
+	/* special case: unused list element table */
+	if (NumLE == 0) {
+		PMemLowAddr = 0;
+		PMemHighAddr = 0;
+		pVMem = 0;
+	}
+
+	/*
+	 * in order to get the best possible performance the macros to access
+	 * list elements use & instead of %
+	 * this requires the length of LE tables to be a power of 2
+	 */
+
+	/*
+	 * this code guarantees that we use the next power of 2 below the
+	 * value specified for NumLe - this way some LEs in the table may
+	 * not be used but the macros work correctly
+	 * this code does not check for bad values below 128 because in such a
+	 * case we cannot do anything here
+	 */
+
+	if ((NumLE != 2) && (NumLE != 0)) {
+		/* no check for polling unit and unused sync Tx */
+		i = MIN_LEN_OF_LE_TAB;
+		while (NumLE > i) {
+			i *= 2;
+			if (i > MAX_LEN_OF_LE_TAB) {
+				break;
+			}
+		}
+		if (NumLE != i) {
+			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+				("ERROR: Illegal number of list elements %d adjusted to %d\n",
+				NumLE, (i / 2)));
+			NumLE = i / 2;
+		}
+	}
+
+	/* set addresses */
+	pLETab->pPhyLETABLow = PMemLowAddr;
+	pLETab->pPhyLETABHigh = PMemHighAddr;
+	pLETab->pLETab = pVMem;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("contains %d LEs", NumLE));
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		(" and starts at virt %08lx and phys %08lx:%08lx\n",
+		pVMem, PMemHighAddr, PMemLowAddr));
+
+	/* initialize indexes */
+	pLETab->Done = 0;
+	pLETab->Put = 0;
+	pLETab->HwPut = 0;
+	/* initialize size */
+	pLETab->Num = NumLE;
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("<== SkGeY2InitSingleLETable()\n"));
+}	/* SkGeY2InitSingleLETable */
+
+/*****************************************************************************
+ *
+ * SkGeY2InitPrefetchUnit() - Initialize a Prefetch Unit
+ *
+ * Description:
+ *	Calling this function requires an already configured list element table.
+ *	The prefetch unit to be configured is specified in the parameter 'Queue'.
+ *	The function is able to initialize the prefetch units of the following
+ *	queues: Q_R1, Q_R2, Q_XS1, Q_XS2, Q_XA1, Q_XA2.
+ *	The function should be called before SkGeInitPort().
+ *
+ * Arguments:
+ *	pAC - pointer to the adapter context struct.
+ *	IoC - I/O context.
+ *	Queue - I/O offset of queue e.g. Q_XA1.
+ *	pLETab - pointer to list element table to be initialized
+ *
+ * Returns: N/A
+ */
+void SkGeY2InitPrefetchUnit(
+SK_AC	*pAC,			/* pointer to adapter context */
+SK_IOC	IoC,			/* I/O context */
+unsigned int Queue,		/* Queue offset for finding the right registers */
+SK_LE_TABLE	*pLETab)	/* pointer to list element table to be initialized */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("==> SkGeY2InitPrefetchUnit()\n"));
+
+#ifdef DEBUG
+	if (Queue != Q_R1 && Queue != Q_R2 && Queue != Q_XS1 &&
+		Queue != Q_XS2 && Queue != Q_XA1 && Queue != Q_XA2) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+			("ERROR: Illegal queue identifier %x\n", Queue));
+	}
+#endif /* DEBUG */
+
+	/* disable the prefetch unit */
+	SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_RST_SET);
+	SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_RST_CLR);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Base address: %08lx:%08lx\n", pLETab->pPhyLETABHigh,
+		pLETab->pPhyLETABLow));
+
+	/* Set the list base address  high part*/
+	SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_ADDR_HI_REG),
+		pLETab->pPhyLETABHigh);
+
+	/* Set the list base address low part */
+	SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_ADDR_LOW_REG),
+		pLETab->pPhyLETABLow);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Last index: %d\n", pLETab->Num-1));
+
+	/* Set the list last index */
+	SK_OUT16(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_LAST_IDX_REG),
+		(SK_U16)(pLETab->Num - 1));
+
+	/* turn on prefetch unit */
+	SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_OP_ON);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("<== SkGeY2InitPrefetchUnit()\n"));
+}	/* SkGeY2InitPrefetchUnit */
+
+
+/*****************************************************************************
+ *
+ * SkGeY2InitStatBmu() -	Initialize the Status BMU
+ *
+ * Description:
+ *	Calling this function requires an already configured list element table.
+ *	Ensure the status BMU is only initialized once during DriverInit -
+ *	InitLevel2 required.
+ *
+ * Arguments:
+ *	pAC - pointer to the adapter context struct.
+ *	IoC - I/O context.
+ *	pLETab - pointer to status LE table to be initialized
+ *
+ * Returns: N/A
+ */
+void SkGeY2InitStatBmu(
+SK_AC	*pAC,			/* pointer to adapter context */
+SK_IOC	IoC,			/* I/O context */
+SK_LE_TABLE	*pLETab)	/* pointer to status LE table */
+{
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("==> SkGeY2InitStatBmu()\n"));
+
+	/* disable the prefetch unit */
+	SK_OUT32(IoC, STAT_CTRL, SC_STAT_RST_SET);
+	SK_OUT32(IoC, STAT_CTRL, SC_STAT_RST_CLR);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Base address Low: %08lX\n", pLETab->pPhyLETABLow));
+
+	/* Set the list base address */
+	SK_OUT32(IoC, STAT_LIST_ADDR_LO, pLETab->pPhyLETABLow);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Base address High: %08lX\n", pLETab->pPhyLETABHigh));
+
+	SK_OUT32(IoC, STAT_LIST_ADDR_HI, pLETab->pPhyLETABHigh);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Last index: %d\n", pLETab->Num - 1));
+
+	/* Set the list last index */
+	SK_OUT16(IoC, STAT_LAST_IDX, (SK_U16)(pLETab->Num - 1));
+
+	if (HW_FEATURE(pAC, HWF_WA_DEV_43_418)) {
+
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+			("Set Tx index threshold\n"));
+		/* WA for dev. #4.3 */
+		SK_OUT16(IoC, STAT_TX_IDX_TH, ST_TXTH_IDX_MASK);
+
+		/* set Status-FIFO watermark */
+		SK_OUT8(IoC, STAT_FIFO_WM, 0x21);		/* WA for dev. #4.18 */
+
+		/* set Status-FIFO ISR watermark */
+		SK_OUT8(IoC, STAT_FIFO_ISR_WM, 0x07);	/* WA for dev. #4.18 */
+
+		/* WA for dev. #4.3 and #4.18 */
+		/* set Status-FIFO Tx timer init value */
+		SK_OUT32(IoC, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC, 10));
+	}
+	else {
+		/*
+		 * Further settings may be added if required...
+		 * 1) Status-FIFO watermark (STAT_FIFO_WM, STAT_FIFO_ISR_WM)
+		 * 2) Status-FIFO timer values (STAT_TX_TIMER_INI,
+		 *		STAT_LEV_TIMER_INI and STAT_ISR_TIMER_INI)
+		 * but tests shows that the default values give the best results,
+		 * therefore the defaults are used.
+		 */
+
+		SK_OUT16(IoC, STAT_TX_IDX_TH, pAC->GIni.GITxIdxRepThres);
+
+		/* set Status-FIFO watermark */
+		SK_OUT8(IoC, STAT_FIFO_WM, 0x10);
+
+		/* set Status-FIFO ISR watermark */
+		SK_OUT8(IoC, STAT_FIFO_ISR_WM,
+			HW_FEATURE(pAC, HWF_WA_DEV_4109) ? 0x10 : 0x04);
+
+		/* set ISR Timer Init Value to 400 (3.2 us on Yukon-EC) */
+		SK_OUT32(IoC, STAT_ISR_TIMER_INI, 0x0190);
+	}
+
+	/* start Status-FIFO timer */
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Start Status FiFo timer\n"));
+
+	/* enable the prefetch unit */
+	/* operational bit not functional for Yukon-EC, but fixed in Yukon-2 */
+	SK_OUT32(IoC, STAT_CTRL, SC_STAT_OP_ON);
+
+	/* start Status-FIFO timer */
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Start Status FiFo timer\n"));
+
+	SK_OUT8(IoC, STAT_TX_TIMER_CTRL, TIM_START);
+	SK_OUT8(IoC, STAT_LEV_TIMER_CTRL, TIM_START);
+	SK_OUT8(IoC, STAT_ISR_TIMER_CTRL, TIM_START);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("<== SkGeY2InitStatBmu()\n"));
+}	/* SkGeY2InitStatBmu */
+
+#ifdef USE_POLLING_UNIT
+/*****************************************************************************
+ *
+ * SkGeY2InitPollUnit() -	Initialize the Polling Unit
+ *
+ * Description:
+ *	This function will write the data of one polling LE table into the adapter.
+ *
+ * Arguments:
+ *	pAC - pointer to the adapter context struct.
+ *	IoC - I/O context.
+ *	pLETab - pointer to polling LE table to be initialized
+ *
+ * Returns: N/A
+ */
+void SkGeY2InitPollUnit(
+SK_AC	*pAC,			/* pointer to adapter context */
+SK_IOC	IoC,			/* I/O context */
+SK_LE_TABLE	*pLETab)	/* pointer to polling LE table */
+{
+	SK_HWLE	*pLE;
+	int	i;
+#ifdef VCPU
+	VCPU_VARS();
+#endif /* VCPU */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("==> SkGeY2InitPollUnit()\n"));
+
+#ifdef VCPU
+	for (i = 0; i < SK_MAX_MACS; i++) {
+		GET_PO_LE(pLE, pLETab, i);
+		VCPU_START_AND_COPY_LE();
+		/* initialize polling LE but leave indexes invalid */
+		POLE_SET_OPC(pLE, OP_PUTIDX | HW_OWNER);
+		POLE_SET_LINK(pLE, i);
+		POLE_SET_RXIDX(pLE, 0);
+		POLE_SET_TXAIDX(pLE, 0);
+		POLE_SET_TXSIDX(pLE, 0);
+		VCPU_WRITE_LE();
+		SK_DBG_DUMP_PO_LE(pLE);
+	}
+#endif	/* VCPU */
+
+	/* disable the polling unit */
+	SK_OUT32(IoC, POLL_CTRL, PC_POLL_RST_SET);
+	SK_OUT32(IoC, POLL_CTRL, PC_POLL_RST_CLR);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Base address Low: %08lX\n", pLETab->pPhyLETABLow));
+
+	/* Set the list base address */
+	SK_OUT32(IoC, POLL_LIST_ADDR_LO, pLETab->pPhyLETABLow);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("Base address High: %08lX\n", pLETab->pPhyLETABHigh));
+
+	SK_OUT32(IoC, POLL_LIST_ADDR_HI, pLETab->pPhyLETABHigh);
+
+	/* we don't need to write the last index - it is hardwired to 1 */
+
+	/* enable the prefetch unit */
+	SK_OUT32(IoC, POLL_CTRL, PC_POLL_OP_ON);
+
+	/*
+	 * now we have to start the descriptor poll timer because it triggers
+	 * the polling unit
+	 */
+
+	/*
+	 * still playing with the value (timer runs at 125 MHz)
+	 * descriptor poll timer is enabled by GeInit
+	 */
+	SK_OUT32(IoC, B28_DPT_INI,
+		(SK_DPOLL_DEF_Y2 * (SK_U32)pAC->GIni.GIHstClkFact / 100));
+
+	SK_OUT8(IoC, B28_DPT_CTRL, TIM_START);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+		("<== SkGeY2InitPollUnit()\n"));
+}	/* SkGeY2InitPollUnit */
+#endif	/* USE_POLLING_UNIT */
+
+
+/******************************************************************************
+ *
+ * SkGeY2SetPutIndex
+ *
+ * Description:
+ *	This function writes the Done index of a list element table.
+ *
+ * Notes:
+ *	Dev. Issue 4.2
+ *
+ * Returns: N/A
+ */
+void SkGeY2SetPutIndex(
+SK_AC	*pAC,					/* pointer to adapter context */
+SK_IOC	IoC,					/* pointer to the I/O context */
+SK_U32	StartAddrPrefetchUnit,	/* start address of the prefetch unit */
+SK_LE_TABLE	*pLETab)			/* list element table to work with */
+{
+	unsigned int Put;
+	SK_U16 EndOfListIndex;
+	SK_U16 HwGetIndex;
+	SK_U16 HwPutIndex;
+
+	/* set put index we would like to write */
+	Put = GET_PUT_IDX(pLETab);
+
+	/*
+	 * in this case we wrap around
+	 * new put is lower than last put given to HW
+	 */
+	if (Put < pLETab->HwPut) {
+
+		/* set put index = last index of list */
+		EndOfListIndex = (NUM_LE_IN_TABLE(pLETab)-1);
+
+		/* read get index of HW prefetch unit */
+		SK_IN16(IoC, (StartAddrPrefetchUnit + PREF_UNIT_GET_IDX_REG),
+			&HwGetIndex);
+
+		/* read put index of hw prefetch unit */
+		SK_IN16(IoC, (StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG),
+			&HwPutIndex);
+
+		/* prefetch unit reached end of list */
+		/* prefetch unit reached first list element */
+		if (HwGetIndex == 0) {
+			/* restore watermark */
+			SK_OUT8(IoC, StartAddrPrefetchUnit + PREF_UNIT_FIFO_WM_REG, 0xe0U);
+			/* write put index */
+			SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG,
+				(SK_U16)Put);
+
+			/* remember put index  we wrote to HW */
+			pLETab->HwPut = Put;
+		}
+		else if (HwGetIndex == EndOfListIndex) {
+			/* set watermark to one list element */
+			SK_OUT8(IoC, StartAddrPrefetchUnit + PREF_UNIT_FIFO_WM_REG, 8);
+			/* set put index to first list element */
+			SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG, 0);
+		}
+		/* prefetch unit did not reach end of list yet */
+		/* and we did not write put index to end of list yet */
+		else if ((HwPutIndex != EndOfListIndex) &&
+				 (HwGetIndex != EndOfListIndex)) {
+			/* write put index */
+			SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG,
+				EndOfListIndex);
+		}
+		else {
+			/* do nothing */
+		}
+	}
+	else {
+#ifdef XXX		/* leads in to problems in the Windows Driver */
+		if (Put != pLETab->HwPut) {
+			/* write put index */
+			SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG,
+				(SK_U16)Put);
+			/* update put index */
+			UPDATE_HWPUT_IDX(pLETab);
+		}
+#else
+		/* write put index */
+		SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG,
+			(SK_U16)Put);
+		/* update put index */
+		UPDATE_HWPUT_IDX(pLETab);
+#endif
+	}
+}	/* SkGeY2SetPutIndex */
+
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
old mode 100644
new mode 100755
index dd58c6a..e35349e
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -142,6 +142,10 @@
 	struct pci_dev *bridge = bus->self;
 	struct pci_bus_region region;
 	u32 l, bu, lu, io_upper16;
+#ifdef CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT
+	u16 flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+	u16 cmd, old_cmd;
+#endif
 
 	if (pci_is_enabled(bridge))
 		return;
@@ -167,6 +171,9 @@
 		io_upper16 = 0;
 		l = 0x00f0;
 		dev_info(&bridge->dev, "  IO window: disabled\n");
+#ifdef CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT
+		flags &= ~PCI_COMMAND_IO;
+#endif
 	}
 	/* Temporarily disable the I/O range before updating PCI_IO_BASE. */
 	pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
@@ -188,6 +195,9 @@
 	else {
 		l = 0x0000fff0;
 		dev_info(&bridge->dev, "  MEM window: disabled\n");
+#ifdef CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT
+		flags &= ~PCI_COMMAND_MEMORY;
+#endif
 	}
 	pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
 
@@ -223,6 +233,18 @@
 	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
 
 	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
+#ifdef CONFIG_PCIE_VIRTUAL_BRIDGE_SUPPORT
+	if (flags) {			
+		pci_read_config_word(bridge, PCI_COMMAND, &old_cmd);	
+		cmd  = old_cmd | (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+		if (cmd != old_cmd) {
+			printk("PCI: enabling bridge %s (%04x -> %04x)\n",
+			       pci_name(bridge), old_cmd, cmd);
+			pci_write_config_word(bridge, PCI_COMMAND, cmd);
+		}
+		pci_set_master(bridge);
+	}
+#endif
 }
 
 /* Check whether the bridge supports optional I/O and
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
old mode 100644
new mode 100755
index e11cca4..9a8aafb
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -274,6 +274,23 @@
 # disabling it, whereas people who accidentally switch it off may wonder why
 # their mkinitrd gets into trouble.
 
+config MV_SCATTERED_SPINUP
+	bool "Lock disk spinup"
+	default n
+	help
+	  Take care about the power supply health. Prevent to many disks
+	  to spinup at the same time.
+
+	  If in doubt, say N.
+
+config MV_DISKS_POWERUP_TO_STANDBY
+	depends on MV_SCATTERED_SPINUP
+	bool "Disk powerup to standby"
+	default n
+	help
+	  Support for disk power-up in standby mode.
+
+	  If in doubt, use N.
 menu "SCSI Transports"
 	depends on SCSI
 
@@ -340,6 +357,11 @@
 
 if SCSI_LOWLEVEL && SCSI
 
+config SCSI_MV_THOR
+	tristate "Marvell Storage Controller 6121/6122/6141/6145"
+	depends on SCSI && BLK_DEV_SD
+	help
+		Provides support for Marvell thor Storage Controller series.
 config ISCSI_TCP
 	tristate "iSCSI Initiator over TCP/IP"
 	depends on SCSI && INET
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
old mode 100644
new mode 100755
index 3ad61db..38da364
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -49,6 +49,7 @@
 obj-$(CONFIG_GVP11_SCSI)	+= gvp11.o	wd33c93.o
 obj-$(CONFIG_MVME147_SCSI)	+= mvme147.o	wd33c93.o
 obj-$(CONFIG_SGIWD93_SCSI)	+= sgiwd93.o	wd33c93.o
+obj-$(CONFIG_SCSI_MV_THOR)      += thor/
 obj-$(CONFIG_ATARI_SCSI)	+= atari_scsi.o
 obj-$(CONFIG_MAC_SCSI)		+= mac_scsi.o
 obj-$(CONFIG_SCSI_MAC_ESP)	+= esp_scsi.o	mac_esp.o
@@ -136,6 +137,7 @@
 
 obj-$(CONFIG_ARM)		+= arm/
 
+obj-$(CONFIG_SCSI_MVSATA)       += ../../arch/arm/plat-feroceon/mv_drivers_lsp/mv_sata/
 obj-$(CONFIG_CHR_DEV_ST)	+= st.o
 obj-$(CONFIG_CHR_DEV_OSST)	+= osst.o
 obj-$(CONFIG_BLK_DEV_SD)	+= sd_mod.o
@@ -156,6 +158,7 @@
 scsi_mod-$(CONFIG_SCSI_DMA)	+= scsi_lib_dma.o
 scsi_mod-y			+= scsi_scan.o scsi_sysfs.o scsi_devinfo.o
 scsi_mod-$(CONFIG_SCSI_NETLINK)	+= scsi_netlink.o
+scsi_mod-$(CONFIG_MV_SCATTERED_SPINUP)	+= scsi_spinup.o
 scsi_mod-$(CONFIG_SYSCTL)	+= scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
old mode 100644
new mode 100755
index dd098ca..c55b53e
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -63,6 +63,9 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+#include <scsi/scsi_spinup.h>
+#endif
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
@@ -781,6 +784,31 @@
  */
 static void scsi_done(struct scsi_cmnd *cmd)
 {
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+
+	unsigned long flags = 0;
+
+	/*
+	* TODO: add support to verify failed commands that didn't woke up the drive.
+	*/
+	if (scsi_spinup_enabled())
+	{
+		spin_lock_irqsave(cmd->device->host->host_lock, flags);
+		if (cmd->device->sdev_power_state == SDEV_PW_SPINNING_UP) 
+		{
+			if (cmd->device->standby_timeout_secs > 0)
+			{
+				/* had a timer before spinup, restarting the timer again */
+				cmd->device->sdev_power_state = SDEV_PW_STANDBY_TIMEOUT_WAIT;
+				standby_add_timer(cmd->device, cmd->device->standby_timeout_secs, standby_times_out);
+			}
+			else
+				cmd->device->sdev_power_state = SDEV_PW_ON;
+		}
+			spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
+	}
+#endif
+
 	blk_complete_request(cmd->request);
 }
 
@@ -1273,7 +1301,7 @@
 
 	list_for_each_entry(sdev, &shost->__devices, siblings) {
 		if (sdev->channel == channel && sdev->id == id &&
-				sdev->lun ==lun)
+				sdev->lun == lun && sdev->sdev_state != SDEV_DEL)
 			return sdev;
 	}
 
@@ -1318,6 +1346,13 @@
 {
 	int error;
 
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+	/* init will parse the kernel line for the spinup param */
+	error = scsi_spinup_init();
+	if (error)
+		return error;
+#endif
+
 	error = scsi_init_queue();
 	if (error)
 		return error;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
old mode 100644
new mode 100755
index bc9a881..a31e0ee
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -31,6 +31,9 @@
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+#include <scsi/scsi_spinup.h>
+#endif
 
 #define SG_MEMPOOL_NR		ARRAY_SIZE(scsi_sg_pools)
 #define SG_MEMPOOL_SIZE		2
@@ -1531,6 +1534,106 @@
 		scsi_target(sdev)->target_busy++;
 		shost->host_busy++;
 
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+	if ((cmd->device->host->hostt->support_scattered_spinup == 1) && /*the flag is requaired in order to support the scattered spinup*/
+		(scsi_spinup_enabled()))	/*kernel line parsed ok?*/
+	{
+		switch (cmd->cmnd[0])
+		{
+			case START_STOP:
+				switch (cmd->cmnd[4] & START_STOP_BIT)
+				{
+					case 0x0: /* STOP command */
+						/* drive is going to sleep */
+						//printk("\n Disk [%d] going to standby...\n", cmd->device->id);
+						cmd->device->sdev_power_state = SDEV_PW_STANDBY;
+					break;
+					case 0x1: /* START command */
+						/* drive is going to spin up, checking if possible */
+						if (scsi_spinup_device(cmd) == 1) {
+							/* not possible: drive queued for spinup in side scsi_spinup_device(), device queue is blocked and the current command is requeued */
+							scsi_internal_device_block(cmd->device);
+							goto not_ready;
+						}
+						/* drive was able to get the semaphore, will spinup now */
+					break;
+					default:
+					break;
+				}
+			break;
+			case READ_6:
+			case WRITE_6:
+			case READ_10:
+			case WRITE_10:
+			case SEEK_10:
+			case VERIFY_10:
+			case VERIFY:
+			case READ_16:
+			case WRITE_16:
+			case VERIFY_16:
+				/* drive is going to spin up, checking if possible */
+				if (scsi_spinup_device(cmd) == 1) {
+					/* not possible: drive queued for spinup in side scsi_spinup_device(), device queue is blocked and the current command is requeued */
+					scsi_internal_device_block(cmd->device);
+					goto not_ready;
+				}
+				/* drive was able to get the semaphore, will spinup now */
+			break;
+			case ATA_16:
+				switch (cmd->cmnd[14])
+				{
+					case STANDBY_IMMEDIATE:
+						/* drive is going to sleep */
+						//printk("\n Disk [%d] going to standby...\n", cmd->device->id);
+						cmd->device->sdev_power_state = SDEV_PW_STANDBY;
+					break;
+					case STANDBY_TIMEOUT:
+						if (cmd->cmnd[6] == 0) {
+							/* resetting the timeout standby value of 0 means remove standby timeout */
+							cmd->device->sdev_power_state = SDEV_PW_ON;
+							cmd->device->standby_timeout_secs = 0;
+						} else {
+							/*setting the timeout standby and starting the timer*/
+							//printk("\n Disk [%d] going to timeout standby with value [%d]...\n", cmd->device->id, (int) cmd->cmnd[6]);
+							cmd->device->sdev_power_state = SDEV_PW_STANDBY_TIMEOUT_WAIT;
+							standby_add_timer(cmd->device, timeout_to_jiffies((int) cmd->cmnd[6]), standby_times_out);
+						}
+					break;
+					default:
+					break;
+				}
+			break;
+			case ATA_12:
+				switch (cmd->cmnd[9])
+				{
+					case STANDBY_IMMEDIATE:
+						/* drive is going to sleep */
+						//printk("\n Disk [%d] going to standby...\n", cmd->device->id);
+						cmd->device->sdev_power_state = SDEV_PW_STANDBY;
+					break;
+					case STANDBY_TIMEOUT:
+						if (cmd->cmnd[4] == 0) {
+							/* resetting the timeout standby value of 0 means remove standby timeout */
+							cmd->device->sdev_power_state = SDEV_PW_ON;
+							cmd->device->standby_timeout_secs = 0;
+						} else {
+							/*setting the timeout standby and starting the timer*/
+							//printk("\n Disk [%d] going to timeout standby with value [%d]...\n", cmd->device->id, (int) cmd->cmnd[4]);
+							cmd->device->sdev_power_state = SDEV_PW_STANDBY_TIMEOUT_WAIT;
+							standby_add_timer(cmd->device, timeout_to_jiffies((int) cmd->cmnd[4]), standby_times_out);
+						}
+					break;
+					default:
+					break;
+				}
+			break;
+			default:
+			break;
+		}
+
+	}
+#endif		
+
 		/*
 		 * XXX(hch): This is rather suboptimal, scsi_dispatch_cmd will
 		 *		take the lock again.
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
old mode 100644
new mode 100755
index 1fbf7c7..7435a64
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -144,6 +144,50 @@
 static inline void scsi_netlink_exit(void) {}
 #endif
 
+
+/* scsi_spinup.c */
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+extern void standby_add_timer(struct scsi_device *, int,
+		void (*)(struct scsi_device *));
+extern int standby_delete_timer(struct scsi_device *);
+extern void standby_times_out(struct scsi_device *);
+
+extern void spinup_add_timer(struct scsi_device *, int,
+		void (*)(struct scsi_device *));
+extern int spinup_delete_timer(struct scsi_device *);
+extern void spinup_times_out(struct scsi_device *);
+extern int timeout_to_jiffies(int);
+extern int scsi_parse_spinup_max(char *);
+extern int scsi_parse_spinup_timeout(char *);
+extern int  scsi_spinup_down();
+extern int  scsi_spinup_up();
+extern int  scsi_spinup_enabled();
+extern int scsi_spinup_get_timeout();
+extern int __init scsi_spinup_init(void);
+extern int  scsi_spinup_device(struct scsi_cmnd *);
+extern void scsi_spinup_device_queue(struct scsi_device *);
+extern int  scsi_spinup_device_dequeue_next(void);
+#else
+/* only factive declerations for the compiler */
+static inline void scsi_spinup_init(void) {}
+static inline void standby_add_timer(void) {}
+static inline void standby_delete_timer(void) {}
+static inline void standby_times_out(void) {}
+static inline void spinup_add_timer(void) {}
+static inline void spinup_delete_timer(void) {}
+static inline void spinup_times_out(void) {}
+static inline void timeout_to_jiffies(void) {}
+static inline void scsi_parse_spinup_max(void) {}
+static inline void scsi_parse_spinup_timeout(void) {}
+static inline void scsi_spinup_down(void) {}
+static inline void scsi_spinup_up(void) {}
+static inline void scsi_spinup_enabled(void) {}
+static inline void scsi_spinup_get_timeout(void) {}
+static inline void scsi_spinup_device(void) {}
+static inline void scsi_spinup_device_queue(void ) {}
+static inline void scsi_spinup_device_dequeue_next(void) {}
+//static inline void scsi_spinup_exit(void) {}
+#endif
 /* 
  * internal scsi timeout functions: for use by mid-layer and transport
  * classes.
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
old mode 100644
new mode 100755
index 47291bc..8987b59
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -255,6 +255,19 @@
 	sdev->lun = lun;
 	sdev->channel = starget->channel;
 	sdev->sdev_state = SDEV_CREATED;
+    /*
+    * next section is for scattered spinup support.
+    */
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+#ifdef CONFIG_MV_DISKS_POWERUP_TO_STANDBY
+	sdev->sdev_power_state = SDEV_PW_STANDBY;
+#else
+	sdev->sdev_power_state = SDEV_PW_ON;
+#endif
+	init_timer(&sdev->standby_timeout);
+	init_timer(&sdev->spinup_timeout);
+	sdev->standby_timeout_secs = 0;
+#endif
 	INIT_LIST_HEAD(&sdev->siblings);
 	INIT_LIST_HEAD(&sdev->same_target_siblings);
 	INIT_LIST_HEAD(&sdev->cmd_list);
diff --git a/drivers/scsi/scsi_spinup.c b/drivers/scsi/scsi_spinup.c
new file mode 100755
index 0000000..97bc1fd
--- /dev/null
+++ b/drivers/scsi/scsi_spinup.c
@@ -0,0 +1,371 @@
+/* 
+ *  SCSI Spinup specific structures and functions.
+ *
+ *  Copyright (c) 2009 Marvell,  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_spinup.h>
+
+#include "scsi_priv.h"
+#include "scsi_logging.h"
+
+/*structure: spinup_config=<spinup_max>,<spinup_timout> example: spinup_config=2,6 (two max spinup disks, 6 seconds timeout) */
+static char *cmdline = NULL;
+
+/* Required to get the configuration string from the Kernel Command Line */
+int spinup_cmdline_config(char *s);
+__setup("spinup_config=", spinup_cmdline_config);
+
+int spinup_cmdline_config(char *s)
+{
+    cmdline = s;
+    return 1;
+}
+
+static int spinup_timeout = 0;
+static int spinup_max = 0;
+static int spinup_enabled = 0;
+
+static atomic_t spinup_now;
+struct spinup_node {
+	struct list_head list;
+	struct scsi_device *sdev;
+};
+static struct list_head spinup_list;
+
+int scsi_parse_spinup_max(char *p_config)
+{
+	/* the max spinup value is constructed as follows: */
+	/* <spinup_max>,<spinup_timout>                    */
+	unsigned int _spinup_max;
+	int syntax_err = 0;
+
+	_spinup_max = 0;
+	if (p_config == NULL)
+	    return 0;
+	while((*p_config >= '0') && (*p_config <= '9'))	{
+		_spinup_max = (_spinup_max * 10) + (*p_config - '0');
+		p_config++;
+	}
+	if ((*p_config != ',') || (_spinup_max == 0)) {
+		printk("Syntax error while parsing spinup_max value from command line\n");
+		syntax_err = 1;
+	}
+	if ((_spinup_max < 0)||(_spinup_max > 8)) {
+		printk("Syntax error while parsing spinup_max value from command line. (value must between 1 to 8\n");
+		syntax_err = 1;
+	}
+	if(syntax_err == 0) {
+		printk("  o Maximum Disk Spinup set to: %d.\n", _spinup_max);
+		return _spinup_max;
+	}
+	return 0;
+}
+
+int scsi_parse_spinup_timeout(char *p_config)
+{
+	/* the  spinup timeout value is constructed as follows: */
+	/* <spinup_max>,<spinup_timout>                         */
+	unsigned int _spinup_timout;
+	int syntax_err = 0;
+
+	_spinup_timout = 0;
+	if (p_config == NULL)
+	    return 0;
+	while((*p_config != ',') && (*p_config != '\0'))
+		p_config++;
+		
+	p_config++;
+	while((*p_config >= '0') && (*p_config <= '9'))	{
+		_spinup_timout = (_spinup_timout * 10) + (*p_config - '0');
+		p_config++;
+	}
+	if ((*p_config != '\0') || (_spinup_timout == 0)) {
+		printk("Syntax error while parsing spinup_timout value from command line\n");
+		syntax_err = 1;
+	}
+	if ((_spinup_timout < 0) || (_spinup_timout > 6)) {
+		printk("Syntax error while parsing spinup_timout value from command line (spinup_timeout must be between 1 to 6) \n");
+		syntax_err = 1;
+	}
+	if(syntax_err == 0) {
+		printk("  o Disk Spinup timeout set to: %d.\n", _spinup_timout);
+		return _spinup_timout;
+	}
+	return 0;
+}
+
+/* function convertd timeout value got from the user to jiffies */
+int timeout_to_jiffies (int timeout)
+{
+	unsigned int secs=0;
+
+	switch(timeout) {
+		case 0:		//printf("off");
+			break;
+		case 252:	//printf("21 minutes");
+			secs = 21 * 60;
+			break;
+		case 253:	//printf("vendor-specific");
+			break;
+		case 254:	//printf("?reserved");
+			break;
+		case 255:	//printf("21 minutes + 15 seconds");
+			secs = 21 * 60 + 15;
+			break;
+		default:
+			if (timeout <= 240) {
+				secs = timeout * 5;
+			} else if (timeout <= 251) {
+				secs = ((timeout - 240) * 30) * 60;
+			} else
+				printk("illegal value");
+			break;
+	}
+	return msecs_to_jiffies ((secs-1) * 1000);
+}
+
+
+void standby_add_timer(struct scsi_device *sdev, int timeout,
+		    void (*complete)(struct scsi_device *))
+{
+	/*
+	 * If the clock was already running for this device, then
+	 * first delete the timer.  The timer handling code gets rather
+	 * confused if we don't do this.
+	 */
+	if (sdev->standby_timeout.function)
+		del_timer(&sdev->standby_timeout);
+
+	sdev->standby_timeout.data = (unsigned long)sdev;
+	sdev->standby_timeout_secs = timeout;
+
+	sdev->standby_timeout.expires = timeout + jiffies ;
+	sdev->standby_timeout.function = (void (*)(unsigned long)) complete;
+
+	SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:"
+					  " %d, (%p)\n", __FUNCTION__,
+					  sdev, timeout, complete));
+
+	add_timer(&sdev->standby_timeout);
+}
+
+
+int standby_delete_timer(struct scsi_device *sdev)
+{
+	int rtn;
+
+	rtn = del_timer(&sdev->standby_timeout);
+
+	SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p,"
+					 " rtn: %d\n", __FUNCTION__,
+					 sdev, rtn));
+
+	sdev->standby_timeout.data = (unsigned long)NULL;
+	sdev->standby_timeout.function = NULL;
+
+	return rtn;
+}
+
+
+void standby_times_out(struct scsi_device *sdev)
+{
+	unsigned long flags = 0;
+
+// 	printk("\nDisk [%d] timeout done, going to sleep...\n",sdev->id);
+	spin_unlock_irqrestore(sdev->host->host_lock, flags);
+	sdev->sdev_power_state = SDEV_PW_STANDBY_TIMEOUT_PASSED;
+	spin_lock_irqsave(sdev->host->host_lock, flags);
+	standby_delete_timer(sdev);
+}
+
+void spinup_add_timer(struct scsi_device *sdev, int timeout,
+		    void (*complete)(struct scsi_device *))
+{
+	/*
+	 * If the clock was already running for this device, then
+	 * first delete the timer.  The timer handling code gets rather
+	 * confused if we don't do this.
+	 */
+	if (sdev->spinup_timeout.function)
+		del_timer(&sdev->spinup_timeout);
+		
+	
+	sdev->spinup_timeout.data = (unsigned long)sdev;
+	
+	sdev->spinup_timeout.expires = jiffies + msecs_to_jiffies (timeout * 1000);
+	sdev->spinup_timeout.function = (void (*)(unsigned long)) complete;
+
+	SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:"
+					  " %d, (%p)\n", __FUNCTION__,
+					  sdev, timeout, complete));
+	add_timer(&sdev->spinup_timeout);
+	
+}
+
+int spinup_delete_timer(struct scsi_device *sdev)
+{
+	int rtn;
+
+	rtn = del_timer(&sdev->spinup_timeout);
+
+	SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p,"
+					 " rtn: %d\n", __FUNCTION__,
+					 sdev, rtn));
+
+	sdev->spinup_timeout.data = (unsigned long)NULL;
+	sdev->spinup_timeout.function = NULL;
+
+	return rtn;
+}
+void spinup_times_out(struct scsi_device *sdev)
+{
+// 	printk("\nDisk [%d] finished spinup...\n",sdev->id);
+	scsi_spinup_up();
+	spinup_delete_timer(sdev);
+	scsi_spinup_device_dequeue_next();
+	
+}
+
+
+
+int scsi_spinup_enabled(void)
+{
+	return spinup_enabled;
+}
+
+int scsi_spinup_get_timeout(void)
+{
+	return spinup_timeout;
+}
+
+/* __setup kernel line parsing and setting up the spinup feature */
+int __init scsi_spinup_init(void)
+{
+	printk("SCSI Scattered Spinup:\n");
+	spinup_max = scsi_parse_spinup_max(cmdline);
+	spinup_timeout = scsi_parse_spinup_timeout(cmdline);
+	if ((spinup_max == 0) || (spinup_timeout == 0)){
+		spinup_enabled = 0;
+		printk("SCSI Scattered Spinup Feature Status: Disabled\n");
+	}else{
+		spinup_enabled = 1;
+		atomic_set(&spinup_now,spinup_max);
+		printk("SCSI Scattered Spinup Feature Status: Enabled\n");
+	}
+	INIT_LIST_HEAD(&spinup_list);
+	return 0;
+}
+
+void scsi_spinup_device_queue(struct scsi_device *sdev)
+{
+	struct list_head *ptr;
+	struct spinup_node *entry;
+	struct spinup_node *new = (struct spinup_node *) kmalloc(sizeof(struct spinup_node), GFP_KERNEL);
+
+	new->sdev = sdev;
+	list_add_tail(&new->list, &spinup_list);
+
+// 	printk("\n");
+// 	list_for_each(ptr, &spinup_list) {
+// 		entry = list_entry(ptr, struct spinup_node, list);
+// 		printk("[%d] ->",entry->sdev->id);
+// 	}
+// 	printk("[EOD]\n");
+}
+
+int scsi_spinup_device(struct scsi_cmnd *cmd)
+{
+	switch (cmd->device->sdev_power_state) {
+		case SDEV_PW_STANDBY:
+		case SDEV_PW_STANDBY_TIMEOUT_PASSED:
+			cmd->device->sdev_power_state = SDEV_PW_WAIT_FOR_SPIN_UP;
+			/* disk will wait here to his turn to spinup */
+// 			printk("\nDisk [%d] waiting to spinup...\n",cmd->device->id);
+			if (!scsi_spinup_down())
+			{
+// 				printk("\Disk [%d] queued up for spinup!\n", cmd->device->id);
+				scsi_spinup_device_queue(cmd->device);
+				return 1;
+			}
+			cmd->device->sdev_power_state = SDEV_PW_SPINNING_UP;
+			/* starting timer for the spinup process */
+// 			printk("\nDisk [%d] spinning up...\n",cmd->device->id);
+			spinup_add_timer(cmd->device, scsi_spinup_get_timeout(), spinup_times_out);
+		break;
+		case SDEV_PW_STANDBY_TIMEOUT_WAIT:
+			standby_add_timer(cmd->device, cmd->device->standby_timeout_secs, standby_times_out);
+		break;
+		default:
+		break;
+	}
+	return 0;
+}
+int scsi_spinup_down(void)
+{
+	if (atomic_read(&spinup_now) > 0) {
+		atomic_dec(&spinup_now);
+// 		printk("\nDown we go!! [%d] \n",(int) atomic_read(&spinup_now) );
+		return 1;
+	}
+	return 0;
+}
+int scsi_spinup_up(void)
+{
+	atomic_inc(&spinup_now);
+// 	printk("\nUP we go!! [%d] \n",(int) atomic_read(&spinup_now) );
+
+	return 0;	
+}
+int scsi_spinup_device_dequeue_next(void)
+{
+	struct list_head *ptr;
+	struct spinup_node *entry;
+
+	if(!list_empty(&spinup_list))
+	{
+		ptr = spinup_list.next;
+		entry = list_entry(ptr, struct spinup_node, list);
+// 		printk("\nNext Disk is entry: [%d] power state [%d]\n",entry->sdev->id ,entry->sdev->sdev_power_state);
+
+		if (scsi_spinup_down())
+		{
+			entry->sdev->sdev_power_state = SDEV_PW_SPINNING_UP;
+			spinup_add_timer(entry->sdev, scsi_spinup_get_timeout(), spinup_times_out);
+			scsi_internal_device_unblock(entry->sdev);
+			list_del(ptr);
+		}
+	}
+// 	printk("\n");
+// 	list_for_each(ptr, &spinup_list) {
+// 		entry = list_entry(ptr, struct spinup_node, list);
+// 		printk("[%d] ->",entry->sdev->id);
+// 	}
+// 	printk("[EOD]\n");
+	return 0;
+}
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
old mode 100644
new mode 100755
index 392d8db..38482d3
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -910,6 +910,19 @@
 void __scsi_remove_device(struct scsi_device *sdev)
 {
 	struct device *dev = &sdev->sdev_gendev;
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+	if (scsi_spinup_enabled()) {
+		if (sdev->standby_timeout_secs > 0) {
+			/* if the device had any standby timer */
+			standby_delete_timer(sdev);
+		}
+		if (sdev->spinup_timeout.function) {
+			/* deleting any spinup timer thats may be still there and freeing the semaphore */
+			spinup_delete_timer(sdev);
+			scsi_spinup_up();
+		}
+	}
+#endif
 
 	if (sdev->is_visible) {
 		if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
diff --git a/drivers/scsi/thor/Makefile b/drivers/scsi/thor/Makefile
new file mode 100755
index 0000000..2fe1167
--- /dev/null
+++ b/drivers/scsi/thor/Makefile
@@ -0,0 +1,275 @@
+#
+#
+# Note: This Makefile is for 2.6 kernel only, at present.
+#
+# V0.0.0.6 Ver.Make
+
+# default to build for the running kernel
+ifeq ("x", "x$(KERNEL_SRC)")
+	KERNEL_SRC=/lib/modules/$(shell uname -r)/build
+endif
+
+# use KERNEL_SRC if not called by our driver disk maker
+ifeq ("x", "x$(KERNEL_SOURCE_DIR)")
+        KERNEL_SRC_DIR=$(KERNEL_SRC)
+else
+	KERNEL_SRC_DIR=$(KERNEL_SOURCE_DIR)
+endif
+
+ifeq ("x", "x$(KERNEL_BUILD_DIR)")
+	KERNEL_BLD_DIR=$(KERNEL_SRC_DIR)
+else
+        KERNEL_BLD_DIR=$(KERNEL_BUILD_DIR)
+endif
+
+#ifneq ($(KERNELRELEASE),)
+#	include $(SUBDIRS)/mv_conf.mk
+#else
+#	include mv_conf.mk
+#endif
+
+SUPPORT_THOR=y
+
+ifeq ("xy", "x$(RAID_MODULE)")
+	LIB_TYPE=_raid_
+endif
+
+# KERNEL_VER := $(shell cat $(KERNEL_BLD_SRC)/include/linux/version.h | grep UTS_RELEASE | cut -c22-24 | head -n 1)
+
+# we may build for 32bit kernel on a 64bit system
+CONFIG_64BIT=$(shell [ -f $(KERNEL_BLD_DIR)/.config ] && cat $(KERNEL_BLD_DIR)/.config | grep -m 1 CONFIG_64BIT | awk -F= '{print $$2}')
+CONFIG_REGPARM=$(shell [ -f $(KERNEL_BLD_DIR)/.config ] && cat $(KERNEL_BLD_DIR)/.config | grep -m 1 CONFIG_REGPARM | awk -F= '{print $$2}')
+CONFIG_4KSTACKS=$(shell [ -f $(KERNEL_BLD_DIR)/.config ] && cat $(KERNEL_BLD_DIR)/.config | grep -m 1 CONFIG_4KSTACKS | awk -F= '{print $$2}')
+CONFIG_SUSE_KERNEL=$(shell [ -f $(KERNEL_BLD_DIR)/.config ] && cat $(KERNEL_BLD_DIR)/.config | grep -m 1 CONFIG_SUSE_KERNEL | awk -F= '{print $$2}')
+
+ifeq ($(ARCH), )
+ifeq ($(strip $(CONFIG_64BIT)),y)
+	ARCH_TYPE=x86_64
+		RAID_LIB_NAME=libmv$(LIB_TYPE)64
+else	
+	ARCH_TYPE=i386 
+	ifeq ($(strip $(CONFIG_REGPARM)),y)
+		RAID_LIB_NAME=libmv$(LIB_TYPE)32
+	else
+		RAID_LIB_NAME=libmv$(LIB_TYPE)32_noregparm
+	endif
+endif
+else
+	ARCH_TYPE=$(ARCH)
+endif
+
+MV_CC     =  $(CROSS_COMPILE)$(CC)
+MV_LD     =  $(CROSS_COMPILE)$(LD)
+
+export LD_LIBRARY_PATH
+
+odin_objs_$(SUPPORT_ODIN)   := core/odin/core_exp.o   core/odin/core_init.o   \
+		               core/odin/core_ibcd.o  core/odin/core_adpt.o   \
+		               core/odin/core_spi.o    \
+		               core/odin/core_ses.o   core/odin/core_xor.o    \
+		               core/odin/core_api.o   core/odin/scsi2sata.o   \
+		               core/odin/core_i2c.o                           \
+		               core/odin/ata2scsi.o   core/odin/core_helper.o \
+			       core/odin/core_extern.o core/odin/core_swxor.o  \
+#    core/odin/consolid.o \
+#   core/odin/core_eeprom.o \
+
+thor_objs_$(SUPPORT_THOR)   := core/thor/core_exp.o core/thor/core_init.o\
+		   core/thor/core_api.o core/thor/core_xor.o\
+		   core/thor/scsi2sata.o core/thor/core_swxor.o core/thor/core_sat.o
+
+#cons_objs_$(SUPPORT_CONSOLIDATE) := core/thor/consolid.o
+
+CORE_OBJS       :=  $(odin_objs_y) $(thor_objs_y) 
+
+
+COMM_OBJS       := lib/common/com_util.o lib/common/com_u64.o             \
+		   lib/common/com_scsi.o lib/common/com_tag.o             \
+		   lib/common/com_sgd.o  lib/common/com_nvram.o
+
+raid_objs_$(RAID_MODULE) := raid/ddf_handler.o       raid/raid0.o         \
+			    raid/raid1.o             raid/raid_util_ext.o \
+		            raid/raid_api.o          raid/raid_bga.o      \
+	                    raid/raid_cmd_handler.o  raid/raid_ddf.o      \
+		            raid/raid_eh.o           raid/raid_exp.o      \
+			    raid/raid_manage_ext.o   raid/raid_mp.o       \
+		            raid/raid_manage.o       raid/raid_res_mgmt.o \
+		            raid/raid_tset.o         raid/raid_util.o     \
+			    raid/ddf_handler_ext.o   raid/raid_api_ext.o  \
+                            raid/raid_cmd_ext.o      raid/raid_ddf_ext.o  \
+			    raid/raid_exp_ext.o
+
+cache_objs_$(CACHE_MODULE) := cache/cache_exp.o      cache/cache_mod.o
+
+raid6_objs_$(RAID6_MODULE) := raid/raid6.o math/math_matrix.o
+
+RAID_OBJS       := $(raid_objs_y)  $(raid6_objs_y) $(cache_objs_y)
+
+OSDEP_OBJS      := linux/linux_main.o    linux/hba_exp.o          \
+		   linux/hba_mod.o       linux/hba_timer.o        \
+		   linux/oss_wrapper.o   linux/linux_iface.o      \
+	           linux/res_mgmt.o 	
+
+# for partial source tree building
+core_dir_$(SUPPORT_ODIN) :=core/odin
+core_dir_$(SUPPORT_THOR) :=core/thor
+include_dir := include  include/generic  include/icommon
+
+header_dirs     :=   $(include_dir)
+
+LIBMV_OBJS	:=  $(COMM_OBJS) $(RAID_OBJS)
+
+HBA_OBJS        := $(OSDEP_OBJS) $(CORE_OBJS) $(LIBMV_OBJS) 
+
+INCLUDE_DIR     = -I$(KERNEL_BLD_DIR)/include                          \
+		  -I$(KERNEL_BLD_DIR)/include/scsi                     \
+		  -I$(KERNEL_BLD_DIR)/drivers/scsi                     \
+	 	  -I$(KERNEL_SRC_DIR)/include                          \
+	 	  -I$(KERNEL_SRC_DIR)/include/scsi                     \
+	 	  -I$(KERNEL_SRC_DIR)/drivers/scsi
+
+
+ifneq ($(KERNELRELEASE),)
+ifeq ($(SUPPORT_ODIN), y)
+obj-$(CONFIG_SCSI_MV_THOR)	:=   mv64xx.o
+mv64xx-objs   :=   $(HBA_OBJS) 
+endif
+
+ifeq ($(SUPPORT_THOR), y)
+obj-$(CONFIG_SCSI_MV_THOR)	:=   mv61xx.o
+mv61xx-objs	:=   $(HBA_OBJS) 
+endif
+
+clean-files   +=   Modules.symvers
+clean-files   +=   Module.symvers
+EXTRA_CFLAGS  :=   -I$(src)/include    -I$(src)/core            \
+		   -I$(src)/raid       -I$(src)/.               \
+		   -I$(src)/linux  -I$(src)/math            \
+                   -I$(src)/cache      -I$(src)/include/generic \
+		   -I$(src)/include/icommon
+
+EXTRA_CFLAGS  +=   -D__MV_LINUX__ $(INCLUDE_DIR)
+
+ifeq ($(CONFIG_64BIT), y)
+EXTRA_CFLAGS  +=   -D_64_SYS_
+EXTRA_CFLAGS  +=   -D_64_BIT_COMPILER
+else
+EXTRA_CFLAGS  +=   -D_32_LEGACY_
+endif
+ifeq ($(CONFIG_4KSTACKS), y)
+EXTRA_CFLAGS  +=   -D_4K_STACKS_
+endif
+
+ifeq ($(CONFIG_SUSE_KERNEL), y)
+EXTRA_CFLAGS  += -DIS_OPENSUSE_SLED_SLES=1
+else
+EXTRA_CFLAGS  += -DIS_OPENSUSE_SLED_SLES=0
+endif
+
+EXTRA_CFLAGS  +=   -include $(src)/mv_config.h
+
+ifeq ($(RAID_MODULE), y)
+EXTRA_CFLAGS  +=   -DRAID_DRIVER=1
+endif
+
+ifeq ($(RAID6_MODULE), y)
+EXTRA_CFLAGS  +=   -DSUPPORT_RAID6=1
+endif
+
+ifeq ($(CACHE_MODULE), y)
+EXTRA_CFLAGS  +=   -DCACHE_MODULE_SUPPORT=1
+endif
+
+ifeq ($(SUPPORT_ODIN), y)
+EXTRA_CFLAGS  +=   -I$(src)/core/odin -DPRODUCTNAME_ODIN
+endif
+
+ifeq ($(SUPPORT_THOR), y)
+EXTRA_CFLAGS  +=   -I$(src)/core/thor -DPRODUCTNAME_THOR
+endif
+
+
+#EXTRA_CFLAGS  += -D__MV_DEBUG__  
+EXTRA_CFLAGS  += -Wno-unused-variable  -Wno-pointer-arith
+EXTRA_CFLAGS  += -D__LEGACY_OSSW__=1
+
+else
+
+# Why use SUBDIRS? for backward compatibility
+all:
+	$(MAKE) ARCH=$(ARCH_TYPE) CC=$(MV_CC) LD=$(MV_LD) CROSS_COMPILE=$(CROSS_COMPILE) V=$(V) -C $(KERNEL_BLD_DIR) SUBDIRS=`pwd` modules
+
+lib: all
+	@mkdir -p raid_lib
+	@$(LD) -r -o $(RAID_LIB_NAME).o $(LIBMV_OBJS)
+	@cp -rf $(RAID_LIB_NAME).o ./raid_lib/$(RAID_LIB_NAME).obj
+
+partial: 
+	@echo
+	@echo -n "Creating partial source tree ... "
+	@rm -rf partial
+	@mkdir -p partial partial/lib partial/include partial/$(core_dir_y)
+	@cp Makefile.partial partial/Makefile
+	@cp patch.kbuild partial/
+	@cp patch.sh partial/
+	@cp Makefile.kbuild partial/
+	@cp -uf ./raid_lib/* ./partial/lib/
+	@cp -uf ./readme.partial ./partial/readme
+	@cp -uf linux/*.[ch] ./partial
+	@cp -uf $(core_dir_y)/*.[ch] ./partial/$(core_dir_y)
+	@cp -uf include/com_list.c ./partial/include
+	@cp -uf mv_config.h ./partial
+	@cp -uf mv_odin.h ./partial	
+	@cp -uf mv_thor.h ./partial
+	@cp -uf mv_conf.mk ./partial
+	@cp -uf mv_include.h ./partial/include
+	@for i in $(header_dirs); do cp -uf $$i/*.h  ./partial/include; done
+	@if [ "x$$?" == "x0" ];then echo done.;else echo failed.;fi
+	@echo
+
+kbuild:
+	-@cat patch.kbuild | patch -p1 -N -d $(KERNEL_SRC_DIR)/drivers/scsi
+	@./patch.sh $(KERNEL_SRC_DIR)/drivers/scsi a
+	@mkdir -p $(KERNEL_SRC_DIR)/drivers/scsi/mv
+	@cp -r * $(KERNEL_SRC_DIR)/drivers/scsi/mv
+	@cp -f Makefile.kbuild $(KERNEL_SRC_DIR)/drivers/scsi/mv/Makefile
+	@echo done.
+
+ukbuild:
+	-@cat patch.kbuild | patch -p1 -N -R -d $(KERNEL_SRC_DIR)/drivers/scsi
+	@./patch.sh $(KERNEL_SRC_DIR)/drivers/scsi
+	@rm -rf $(KERNEL_SRC_DIR)/drivers/scsi/mv
+	@echo Patch has been successfully rewinded.
+
+nonraid:
+	@echo -n "Creating non-RAID source tree ... "
+	@rm -rf thor odin norse
+	@mkdir norse
+	@mkdir -p norse/linux norse/lib/common norse/core
+	@mkdir -p norse/include/icommon norse/include/generic
+	@
+	@cp -uf linux/*.[ch] norse/linux
+	@cp -uf lib/common/*.[ch] norse/lib/common
+	@cp -uf include/*.[ch] norse/include/
+	@cp -uf include/icommon/*.[ch] norse/include/icommon
+	@cp -uf include/generic/*.[ch] norse/include/generic
+	@cp -uf patch.* norse
+	@cp -uf Makefile.kbuild norse
+	@cp -uf Makefile.nonraid norse/Makefile
+	@cp -uf mv_config.h norse
+	@cp -uf mv_include.h norse
+	@
+	@if [ "x${SUPPORT_THOR}" == "xy" ]; then mkdir norse/core/thor; cp core/thor/*.[ch] norse/core/thor;cp mv_thor.h norse;fi
+	@if [ "x${SUPPORT_THOR}" == "xy" ]; then echo "SUPPORT_THOR=y" > norse/mv_conf.mk;mv norse thor;fi
+	@
+	@if [ "x${SUPPORT_ODIN}" == "xy" ]; then mkdir norse/core/odin; cp core/odin/*.[ch] norse/core/odin;cp mv_odin.h norse;fi
+	@if [ "x${SUPPORT_ODIN}" == "xy" ]; then echo "SUPPORT_ODIN=y" > norse/mv_conf.mk;mv norse odin;fi
+	@echo "done"
+
+clean:  
+	$(MAKE) ARCH=$(ARCH_TYPE) CC=$(MV_CC) LD=$(MV_LD) CROSS_COMPILE=$(CROSS_COMPILE) V=$(V) -C $(KERNEL_BLD_DIR) SUBDIRS=`pwd` clean
+	@rm -rf partial
+	@rm -rf raid_lib
+	@rm -rf thor odin norse
+	@rm -rf *.o *.obj
+endif
diff --git a/drivers/scsi/thor/Makefile.kbuild b/drivers/scsi/thor/Makefile.kbuild
new file mode 100755
index 0000000..ee75407
--- /dev/null
+++ b/drivers/scsi/thor/Makefile.kbuild
@@ -0,0 +1,153 @@
+#
+#
+# Note: This Makefile is for 2.6 kernel, non-raid only, at present.
+#
+# V0.0.0.2 Ver.Make for kbuild
+
+# default to build for the running kernel
+ifeq ("x", "x$(KERNEL_SRC)")
+	KERNEL_SRC=/lib/modules/$(shell uname -r)/build
+endif
+
+# use KERNEL_SRC if not called by our driver disk maker
+ifeq ("x", "x$(KERNEL_SOURCE_DIR)")
+        KERNEL_SRC_DIR=$(KERNEL_SRC)
+else
+	KERNEL_SRC_DIR=$(KERNEL_SOURCE_DIR)
+endif
+
+ifeq ("x", "x$(KERNEL_BUILD_DIR)")
+	KERNEL_BLD_DIR=$(KERNEL_SRC_DIR)
+else
+        KERNEL_BLD_DIR=$(KERNEL_BUILD_DIR)
+endif
+src=$(KERNEL_SRC)/drivers/scsi/mv
+include $(src)/mv_conf.mk
+
+ifeq ("xy", "x$(RAID_MODULE)")
+	LIB_TYPE=_raid_
+endif
+
+# KERNEL_VER := $(shell cat $(KERNEL_BLD_SRC)/include/linux/version.h | grep UTS_RELEASE | cut -c22-24 | head -n 1)
+
+# we may build for 32bit kernel on a 64bit system
+CONFIG_64BIT=$(shell [ -f $(KERNEL_BLD_DIR)/.config ] && cat $(KERNEL_BLD_DIR)/.config | grep -m 1 CONFIG_64BIT | awk -F= '{print $$2}')
+CONFIG_REGPARM=$(shell [ -f $(KERNEL_BLD_DIR)/.config ] && cat $(KERNEL_BLD_DIR)/.config | grep -m 1 CONFIG_REGPARM | awk -F= '{print $$2}')
+CONFIG_SUSE_KERNEL=$(shell [ -f $(KERNEL_BLD_DIR)/.config ] && cat $(KERNEL_BLD_DIR)/.config | grep -m 1 CONFIG_SUSE_KERNEL | awk -F= '{print $$2}')
+
+ifeq ($(ARCH), )
+ifeq ($(strip $(CONFIG_64BIT)),y)
+	ARCH_TYPE=x86_64
+	RAID_LIB_NAME=libmv$(LIB_TYPE)64
+else	
+	ARCH_TYPE=i386 
+	ifeq ($(strip $(CONFIG_REGPARM)),y)
+		RAID_LIB_NAME=libmv$(LIB_TYPE)32
+	else
+		RAID_LIB_NAME=libmv$(LIB_TYPE)32_noregparm
+	endif
+endif
+else
+	ARCH_TYPE=$(ARCH)
+endif
+
+MV_CC     =  $(CROSS_COMPILE)$(CC)
+MV_LD     =  $(CROSS_COMPILE)$(LD)
+
+export LD_LIBRARY_PATH
+
+odin_objs_$(SUPPORT_ODIN)   := core/odin/core_exp.o   core/odin/core_init.o   \
+		               core/odin/core_ibcd.o  core/odin/core_adpt.o   \
+		               core/odin/core_spi.o    \
+		               core/odin/core_ses.o   core/odin/core_xor.o    \
+		               core/odin/core_api.o   core/odin/scsi2sata.o   \
+		               core/odin/core_i2c.o                           \
+		               core/odin/ata2scsi.o   core/odin/core_helper.o \
+			       core/odin/core_extern.o core/odin/core_swxor.o  \
+
+thor_objs_$(SUPPORT_THOR)   := core/thor/core_exp.o core/thor/core_init.o\
+		   core/thor/core_api.o core/thor/core_xor.o\
+		   core/thor/scsi2sata.o core/thor/core_swxor.o
+
+CORE_OBJS       :=  $(odin_objs_y) $(thor_objs_y) 
+
+COMM_OBJS       := lib/common/com_util.o lib/common/com_u64.o             \
+		   lib/common/com_scsi.o lib/common/com_tag.o             \
+		   lib/common/com_sgd.o  lib/common/com_nvram.o
+
+OSDEP_OBJS      := linux/linux_main.o    linux/hba_exp.o          \
+		   linux/hba_mod.o       linux/hba_timer.o        \
+		   linux/oss_wrapper.o   linux/linux_iface.o      \
+	           linux/res_mgmt.o 	
+
+LIBMV_OBJS	:= $(CORE_OBJS) $(COMM_OBJS) 
+
+HBA_OBJS        := $(OSDEP_OBJS) $(LIBMV_OBJS)
+
+INCLUDE_DIR     = -I$(KERNEL_BLD_DIR)/include                          \
+		  -I$(KERNEL_BLD_DIR)/include/scsi                     \
+		  -I$(KERNEL_BLD_DIR)/drivers/scsi                     \
+	 	  -I$(KERNEL_SRC_DIR)/include                          \
+	 	  -I$(KERNEL_SRC_DIR)/include/scsi                     \
+	 	  -I$(KERNEL_SRC_DIR)/drivers/scsi
+
+
+ifeq ($(SUPPORT_ODIN), y)
+obj-$(CONFIG_SCSI_MV_64xx)      :=   mv64xx.o
+mv64xx-objs   :=   $(HBA_OBJS) 
+endif
+
+ifeq ($(SUPPORT_THOR), y)
+obj-$(CONFIG_SCSI_MV_61xx)      :=   mv61xx.o
+mv61xx-objs   :=   $(HBA_OBJS) 
+endif
+
+clean-files   +=   Modules.symvers
+clean-files   +=   Module.symvers
+EXTRA_CFLAGS  :=   -I$(src)/include    -I$(src)/core            \
+		   -I$(src)/raid       -I$(src)/.               \
+		   -I$(src)/linux  -I$(src)/math            \
+                   -I$(src)/cache      -I$(src)/include/generic \
+		   -I$(src)/include/icommon
+
+EXTRA_CFLAGS  +=   -D__MV_LINUX__ $(INCLUDE_DIR)
+
+ifeq ($(CONFIG_64BIT), y)
+EXTRA_CFLAGS  +=   -D_64_SYS_
+EXTRA_CFLAGS  +=   -D_64_BIT_COMPILER
+else
+EXTRA_CFLAGS  +=   -D_32_LEGACY_
+endif
+ifeq ($(CONFIG_SUSE_KERNEL), y)
+EXTRA_CFLAGS  += -DIS_OPENSUSE_SLED_SLES=1
+else
+EXTRA_CFLAGS  += -DIS_OPENSUSE_SLED_SLES=0
+endif
+
+EXTRA_CFLAGS  +=   -include $(src)/mv_config.h
+
+ifeq ($(RAID_MODULE), y)
+EXTRA_CFLAGS  +=   -DRAID_DRIVER=1
+endif
+
+ifeq ($(RAID6_MODULE), y)
+EXTRA_CFLAGS  +=   -DSUPPORT_RAID6=1
+endif
+
+ifeq ($(CACHE_MODULE), y)
+EXTRA_CFLAGS  +=   -DCACHE_MODULE_SUPPORT=1
+endif
+
+ifeq ($(SUPPORT_ODIN), y)
+EXTRA_CFLAGS  +=   -I$(src)/core/odin -DPRODUCTNAME_ODIN
+endif
+
+ifeq ($(SUPPORT_THOR), y)
+EXTRA_CFLAGS  +=   -I$(src)/core/thor -DPRODUCTNAME_THOR
+endif
+
+
+EXTRA_CFLAGS  += #-D__MV_DEBUG__  
+EXTRA_CFLAGS  += -Wno-unused-variable  -Wno-pointer-arith
+EXTRA_CFLAGS  +=   -D__LEGACY_OSSW__=1
+
diff --git a/drivers/scsi/thor/core/thor/consolid.c b/drivers/scsi/thor/core/thor/consolid.c
new file mode 100755
index 0000000..c326fe6
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/consolid.c
@@ -0,0 +1,525 @@
+#include "mv_include.h"
+
+#ifdef SUPPORT_CONSOLIDATE
+
+#include "consolid.h"
+
+#ifdef MV_DEBUG
+#define TUNE_CONSOLIDATE
+#endif
+
+#ifdef TUNE_CONSOLIDATE
+#define CONSOLIDATE_STATISTICS_COUNT	8
+static MV_U32 gConsolidateStatistics[CONSOLIDATE_STATISTICS_COUNT];
+typedef enum{
+	CONSOLIDATE_NOT_READ_WRITE,
+	CONSOLIDATE_REQUEST_TOO_BIG,
+	CONSOLIDATE_READ_WRITE_DIFFERENT,
+	CONSOLIDATE_NO_RUNNING_REQUEST,
+	CONSOLIDATE_LESS_THAN_SEQUENTIAL_THRESHOLD,
+	CONSOLIDATE_NO_RESOURCE,
+	CONSOLIDATE_GOT_PUSHED,
+	CONSOLIDATA_RESERVED0
+}Consolidate_Statistics_Enum;
+
+void UpdateConsolidateStatistics(Consolidate_Statistics_Enum catogory)
+{
+	MV_U8 i;
+	if ( gConsolidateStatistics[catogory]==0xFFFFFFFF )
+	{
+		for ( i=0; i<CONSOLIDATE_STATISTICS_COUNT; i++ )
+			MV_DPRINT(("Consolidate statistics[%d]=0x%x.\n", i, 
+			gConsolidateStatistics[i]));
+		MV_ZeroMemory(gConsolidateStatistics, sizeof(MV_U32)*CONSOLIDATE_STATISTICS_COUNT);
+	}
+
+	gConsolidateStatistics[catogory]++;
+}
+#else
+#define UpdateConsolidateStatistics(x)
+#endif
+
+/* 
+ * Instruction: How to plug-in this command consolidate sub module to your own module.
+ * 1. Include one .h file which supplies some helper funtions like CONS_GET_EXTENSION
+ * 2. Allocate memory resouce for Consolidate_Extension and Consolidate_Device
+ * 3. Initialize command consolidate module. 
+ * 	Call Consolid_InitializeExtension to initialize Consolidate_Extension
+ *	Call Consolid_InitializeDevice for each Consolidate_Device
+ * 4. When you request comes call Consolid_ModuleSendRequest
+ * 5. At proper time, please push command consolidate module.
+ *	Sometimes command consolidate is accumulating requests and hasn't sent this internal request,
+ *	if there is nothing running now, just push this internal request out.
+ */
+#include "core_cons.h"
+
+PMV_Request Consolid_GetInternalRequest(MV_PVOID This);
+void Consolid_InitialInternalRequest(MV_PVOID This, PMV_Request, MV_BOOLEAN);
+
+void Consolid_ConsolidateRequest(PConsolidate_Extension, PMV_Request, PMV_Request);
+void Consolid_CloseRequest(PConsolidate_Extension, PConsolidate_Device, PMV_Request);
+
+void Consolid_RequestCallBack(MV_PVOID This, PMV_Request pReq);
+
+#ifdef _OS_LINUX
+#include "hba_timer.h"
+void CONS_SEND_REQUEST(MV_PVOID this, PMV_Request req)
+{
+	__hba_dump_req_info(10, req);
+	Core_InternalSendRequest(this, req);
+}
+
+static MV_VOID __consolid_timer_handler(MV_PVOID data)
+{
+	PMV_Request req = (PMV_Request)data;
+	MV_U8 dev_id = req->Device_Id;
+	PConsolidate_Device cons_dev = 
+		CONS_GET_DEVICE(req->Cmd_Initiator, dev_id);
+	MV_U32 sector = req->Data_Transfer_Length>>9;
+
+	SCSI_CDB10_SET_SECTOR(req->Cdb, sector);
+	cons_dev->Holding_Request = NULL;
+	CONS_SEND_REQUEST(req->Cmd_Initiator, req);
+}
+
+static MV_VOID __consolid_mod_timer(MV_PVOID data, PMV_Request req)
+{
+	req->Cmd_Initiator = data;
+	if (req->cons_timeout == NULL) {
+		__consolid_timer_handler(req);
+	}
+	__hba_mod_timer(req->cons_timeout, 10, req, __consolid_timer_handler);
+}
+
+static MV_VOID __consolid_del_timer(PMV_Request req)
+{
+	if (req->cons_timeout) {
+		__hba_del_timer(req->cons_timeout);
+		req->cons_timeout = NULL;
+	}
+}
+#endif
+
+/*
+ * Consolidate sub-module has got a request.
+ * Two parameters:
+ * This: is the pointer of the command initiator extention pointer.
+ * pReq: request
+ * Will send: 
+ *		a. one internal request
+ *		b. this external request and maybe one holding internal request if exists.
+ *		c. NULL if consolidate module holds this request.
+ */
+void Consolid_ModuleSendRequest(MV_PVOID This, PMV_Request pReq)
+{
+	PConsolidate_Extension pCons = CONS_GET_EXTENSION(This);
+	MV_U16 deviceId = pReq->Device_Id;
+	PConsolidate_Device pConsDevice = NULL;
+	PMV_Request pInternal = NULL;
+	MV_LBA startLBA;
+	MV_U32 sectorCount;
+
+	if ( deviceId>=MAX_DEVICE_NUMBER )
+	{
+		goto return_original_req;
+	}
+	pConsDevice = CONS_GET_DEVICE(This, deviceId);
+
+	if( pReq->Req_Flag & REQ_FLAG_NO_CONSOLIDATE )
+	{
+		goto return_original_req;
+	}
+
+	/* 
+	 * We only handle CDB 10 read/write. 
+	 * Otherwise, change the following code which gets the LBA and Sector Count from the CDB. 
+	 */
+	if ( (pReq->Cdb[0]!=SCSI_CMD_READ_10)&&(pReq->Cdb[0]!=SCSI_CMD_WRITE_10) )
+	{
+		UpdateConsolidateStatistics(CONSOLIDATE_NOT_READ_WRITE);
+		goto return_original_req;
+	}
+
+	/* It's read/write request. But is it too big for command consolidate */
+	if ( pReq->Data_Transfer_Length>CONS_MAX_EXTERNAL_REQUEST_SIZE )
+	{
+		UpdateConsolidateStatistics(CONSOLIDATE_REQUEST_TOO_BIG);
+		goto return_original_req;
+	}
+
+	/* Check whether they are all read requests or write requests. */
+	if ( 
+		( (pReq->Cdb[0]==SCSI_CMD_READ_10)&&(!pConsDevice->Is_Read) )
+		||
+		( (pReq->Cdb[0]==SCSI_CMD_WRITE_10)&&(pConsDevice->Is_Read) )
+		)
+	{
+		UpdateConsolidateStatistics(CONSOLIDATE_READ_WRITE_DIFFERENT);
+		pConsDevice->Is_Read = (pReq->Cdb[0]==SCSI_CMD_READ_10)?1:0;
+		goto return_original_req;
+	}
+
+	/* Update the consolidate device statistic including last LBA and sequential counter. */
+	U64_SET_VALUE(startLBA, SCSI_CDB10_GET_LBA(pReq->Cdb));
+	sectorCount = SCSI_CDB10_GET_SECTOR(pReq->Cdb);
+	/* Check whether it's a sequential request. */
+	if ( U64_COMPARE_U64(startLBA, pConsDevice->Last_LBA) )
+		pConsDevice->Sequential = 0; 
+	else
+		pConsDevice->Sequential++;	/* When equals, return 0. */
+
+	/* Last_LBA is actually the next expect sequential LBA. */
+	pConsDevice->Last_LBA = U64_ADD_U32(startLBA, sectorCount);
+	if ( pConsDevice->Sequential>CONS_SEQUENTIAL_MAX )	/* To avoid overflow */
+		pConsDevice->Sequential=CONS_SEQUENTIAL_THRESHOLD;
+
+	/* Is there any requests running on this device? If no, by pass. */
+	if ( !CONS_DEVICE_IS_BUSY(This, deviceId) )
+	{
+		UpdateConsolidateStatistics(CONSOLIDATE_NO_RUNNING_REQUEST);
+		goto return_original_req;
+	}
+#ifdef _OS_WINDOWS
+	/* Do we reach the sequential counter threshold? */
+	if ( pConsDevice->Sequential<CONS_SEQUENTIAL_THRESHOLD )
+	{
+		UpdateConsolidateStatistics(CONSOLIDATE_LESS_THAN_SEQUENTIAL_THRESHOLD);
+		goto return_original_req;
+	}
+#endif
+	pInternal = pConsDevice->Holding_Request;
+
+	/* Don't accumulate this request too big. */
+	if ( pInternal && 
+		( (pInternal->Data_Transfer_Length+pReq->Data_Transfer_Length>CONS_MAX_INTERNAL_REQUEST_SIZE)
+		  ||
+		  (pInternal->SG_Table.Valid_Entry_Count+pReq->SG_Table.Valid_Entry_Count>pInternal->SG_Table.Max_Entry_Count)
+		)
+	   )
+	{
+		Consolid_CloseRequest(pCons, pConsDevice, pInternal);
+		CONS_SEND_REQUEST(This, pInternal);
+		pInternal = NULL;	/* After Consolid_CloseRequest, pConsDevice->Holding_Request==NULL */
+	}
+
+	/* Get one internal request if we don't have. */
+	if ( pConsDevice->Holding_Request==NULL )
+	{
+		pConsDevice->Holding_Request = Consolid_GetInternalRequest(This);
+	}
+	pInternal = pConsDevice->Holding_Request;
+
+	/* We are out of resource. */
+	if ( pInternal==NULL )
+	{
+		UpdateConsolidateStatistics(CONSOLIDATE_NO_RESOURCE);
+		goto return_original_req;
+	}
+
+	/* Now we should be able to do consolidate requests now. */
+	Consolid_ConsolidateRequest(pCons, pInternal, pReq);
+
+	/* Is this internal request bigger enough to send? */
+	if ( pInternal->Data_Transfer_Length>=CONS_MIN_INTERNAL_REQUEST_SIZE )
+	{
+		Consolid_CloseRequest(pCons, pConsDevice, pInternal);
+		CONS_SEND_REQUEST(This, pInternal);
+		return;	/* Send this internal request. */
+	}
+	else
+	{
+#ifdef _OS_LINUX
+		__consolid_mod_timer(This, pInternal);
+#endif
+		return;	/* Hold this request. */
+	}
+
+return_original_req:
+	/* 
+	 * To keep the command order, 
+	 * if we cannot do the consolidate for pReq but we hold some internal request,
+	 * run the internal request and then run the new pReq.
+	 */
+	if ( pConsDevice && (pConsDevice->Holding_Request) )
+	{
+		pInternal = pConsDevice->Holding_Request;
+		Consolid_CloseRequest(pCons, pConsDevice, pInternal);
+		/* After Consolid_CloseRequest, pConsDevice->Holding_Request is NULL. */
+		CONS_SEND_REQUEST(This, pInternal);
+	}
+	CONS_SEND_REQUEST(This, pReq);
+	return;
+}
+
+PMV_Request Consolid_GetInternalRequest(MV_PVOID This)
+{
+	PConsolidate_Extension pCons = CONS_GET_EXTENSION(This);
+	PMV_Request pReq = NULL;
+	if ( !List_Empty(&pCons->Free_Queue) )
+		pReq = List_GetFirstEntry(&pCons->Free_Queue, MV_Request, Queue_Pointer);
+
+	/* Let's intialize this request */
+	if ( pReq )
+		Consolid_InitialInternalRequest(This, pReq, MV_FALSE);
+
+	return pReq;
+}
+
+void Consolid_ReleaseInternalRequest(PConsolidate_Extension pCons, PMV_Request pReq)
+{
+#ifdef _OS_LINUX
+	if (pReq->cons_timeout) {
+		__hba_del_timer(pReq->cons_timeout);
+		kfree(pReq->cons_timeout);
+		pReq->cons_timeout = NULL;
+	}
+#endif
+	List_AddTail(&pReq->Queue_Pointer, &pCons->Free_Queue);
+}
+
+void Consolid_ConsolidateRequest(
+	IN PConsolidate_Extension pCons,
+	IN OUT PMV_Request pInternal, 
+	IN PMV_Request pExternal
+	)
+{
+	MV_U8 i;
+	PMV_Request pAttachedReq=NULL;
+
+	/* So far we only handle SCSI Read 10 and SCSI Write 10 */
+	MV_DASSERT( (pExternal->Cdb[0]==SCSI_CMD_READ_10) || (pExternal->Cdb[0]==SCSI_CMD_WRITE_10) );
+	pAttachedReq = (PMV_Request) pInternal->Org_Req;
+
+	if ( pInternal->Data_Transfer_Length==0 )
+	{
+		/* One external request is attached to that yet. */
+		pInternal->Device_Id = pExternal->Device_Id;
+		MV_DASSERT( pAttachedReq==NULL );
+
+		pInternal->Org_Req = pExternal;
+		MV_LIST_HEAD_INIT( &pExternal->Queue_Pointer );
+
+		pInternal->Cdb[0] = pExternal->Cdb[0];	/* Command type */
+		pInternal->Cdb[2] = pExternal->Cdb[2];	/* Start LBA */
+		pInternal->Cdb[3] = pExternal->Cdb[3];
+		pInternal->Cdb[4] = pExternal->Cdb[4];
+		pInternal->Cdb[5] = pExternal->Cdb[5];
+
+		if ( pExternal->Cdb[0]==SCSI_CMD_READ_10 )
+		{
+			pInternal->Cmd_Flag = CMD_FLAG_DMA | CMD_FLAG_DATA_IN;
+		}
+		else
+		{
+			pInternal->Cmd_Flag = CMD_FLAG_DMA;
+		}
+	}
+	else
+	{
+		MV_DASSERT( pInternal->Device_Id==pExternal->Device_Id );
+		MV_DASSERT( pAttachedReq!=NULL );
+		List_AddTail(&pExternal->Queue_Pointer, &pAttachedReq->Queue_Pointer);
+	}
+
+	/* Don't set the sector count every time. Just before send, set the count. */
+	pInternal->Data_Transfer_Length += pExternal->Data_Transfer_Length;
+
+#ifdef USE_NEW_SGTABLE
+	sgdt_append_reftbl(
+		&pInternal->SG_Table, 
+		&pExternal->SG_Table,
+		0,
+		pExternal->SG_Table.Byte_Count );
+
+#else
+	for ( i=0; i<pExternal->SG_Table.Valid_Entry_Count; i++ )
+	{
+		SGTable_Append(&pInternal->SG_Table, 
+			pExternal->SG_Table.Entry_Ptr[i].Base_Address,
+			pExternal->SG_Table.Entry_Ptr[i].Base_Address_High,
+			pExternal->SG_Table.Entry_Ptr[i].Size);
+	}
+#endif
+}
+
+void Consolid_CloseRequest(
+	IN PConsolidate_Extension pCons,
+	IN PConsolidate_Device pConsDevice,
+	IN OUT PMV_Request pInternal
+	)
+{
+	/* 
+	 * This internal request is ready for handling now. 
+	 * Do whatever we need do before we send this request.
+	 */
+	MV_U32 sectorCount = pInternal->Data_Transfer_Length>>9;
+	MV_DASSERT(  pInternal->Data_Transfer_Length%512==0 );
+#ifdef _OS_LINUX
+	__consolid_del_timer(pInternal);
+#endif
+	SCSI_CDB10_SET_SECTOR(pInternal->Cdb, sectorCount);
+	pConsDevice->Holding_Request = NULL;
+}
+
+void Consolid_RequestCallBack(MV_PVOID This, PMV_Request pReq)
+{
+	PConsolidate_Extension pCons = CONS_GET_EXTENSION(This);
+	PConsolidate_Device pConsDevice = CONS_GET_DEVICE(This, pReq->Device_Id);
+	PMV_Request pExternal;
+	PMV_Request pAttachedReq = (PMV_Request) pReq->Org_Req;
+
+	if ( pReq->Scsi_Status==REQ_STATUS_SUCCESS )
+	{
+		/* Extract all the external requests. Update status and return. */
+		while ( !List_Empty(&pAttachedReq->Queue_Pointer) )
+		{
+			pExternal = List_GetFirstEntry(&pAttachedReq->Queue_Pointer, MV_Request, Queue_Pointer);
+			pExternal->Scsi_Status = REQ_STATUS_SUCCESS;
+			pExternal->Completion(pExternal->Cmd_Initiator, pExternal);
+		}
+		pAttachedReq->Scsi_Status = REQ_STATUS_SUCCESS;
+		pAttachedReq->Completion(pAttachedReq->Cmd_Initiator, pAttachedReq);
+	}
+	else
+	{
+		/* Make sure we won't do consolidate again for these requests. */		
+		pConsDevice->Sequential = 0;
+		MV_DPRINT(("Request error in consolidate.\n"));
+
+		/* If consolidate request has error, Re-send these original requests.
+		 * They go to the hardware directly. Bypass the consolidate module. */
+		while ( !List_Empty(&pAttachedReq->Queue_Pointer) )
+		{
+			pExternal = List_GetFirstEntry(&pAttachedReq->Queue_Pointer, MV_Request, Queue_Pointer);
+			pExternal->Req_Flag |= REQ_FLAG_NO_CONSOLIDATE;
+			pExternal->Scsi_Status = REQ_STATUS_PENDING;
+			CONS_SEND_REQUEST(This, pExternal);
+		}
+		CONS_SEND_REQUEST(This, pAttachedReq);
+	}
+
+	/* Release this request back to the pool. */
+	Consolid_ReleaseInternalRequest(pCons, pReq);
+}
+
+/* Initialize the command consolidate internal request. */
+void Consolid_InitialInternalRequest(
+	IN MV_PVOID This,
+	IN OUT PMV_Request pInternal,
+	IN MV_BOOLEAN firstTime
+	)
+{
+	/*
+	 * Link pointer: 
+	 * When request is free, Queue_Pointer is linked together in the request pool queue.
+	 * When request is in use, Org_Req is pointer to the first external request.
+	 * This first external request uses Queue_Pointer to link other external requests.
+	 * We cannot use internal request's Queue_Pointer to link external requests.
+	 * Because after send to core driver, this pointer will be destroyed.
+	 */
+	pInternal->Org_Req = NULL;				/* Use Queue_Pointer as the linker */
+	pInternal->Req_Flag |= REQ_FLAG_CONSOLIDATE;
+	pInternal->Scsi_Status = REQ_STATUS_PENDING;
+	pInternal->Data_Transfer_Length = 0;
+	pInternal->Cmd_Flag = 0;
+	SGTable_Init(&pInternal->SG_Table, 0);
+#ifdef _OS_LINUX
+	if (firstTime == MV_FALSE) {
+		MV_ASSERT(pInternal->cons_timeout == NULL);
+		pInternal->cons_timeout = kmalloc(sizeof(struct timer_list),
+						GFP_ATOMIC);
+		if (pInternal->cons_timeout == NULL) {
+			MV_ASSERT(0);
+			return;
+		}
+		__hba_init_timer(pInternal->cons_timeout);
+		pInternal->Cmd_Initiator = This;
+	}
+#else
+	MV_ZeroMemory(pInternal->Context, sizeof(MV_PVOID)*MAX_POSSIBLE_MODULE_NUMBER);
+#endif
+	/* 
+	 * Some variables only need initialization once. 
+	 * It won't change no matter during the life time. 
+	 */
+	if ( firstTime )
+	{
+		pInternal->Device_Id = 0;
+		pInternal->Tag = 0;						/* Haven't used. */
+		pInternal->Cmd_Initiator = This;
+		pInternal->Sense_Info_Buffer_Length = 0;
+		pInternal->Sense_Info_Buffer = NULL;
+		pInternal->Data_Buffer = NULL;			/* After consolidate, virtual address is not valid. */
+#ifdef _OS_LINUX
+		memset(pInternal->Context, 0, sizeof(MV_PVOID)*MAX_POSSIBLE_MODULE_NUMBER);
+#endif
+#ifdef _OS_WINDOWS
+		pInternal->Context[MODULE_CORE] = NULL;
+#endif
+		pInternal->Completion = Consolid_RequestCallBack;
+		MV_LIST_HEAD_INIT(&pInternal->Queue_Pointer);
+		MV_ZeroMemory(pInternal->Cdb, MAX_CDB_SIZE);
+		U64_SET_VALUE(pInternal->LBA, 0);
+		pInternal->Sector_Count = 0;
+#ifdef _OS_LINUX
+		pInternal->cons_timeout = NULL;
+#endif
+	}
+}
+
+/* Initialize the Consolidate_Extension */
+void Consolid_InitializeExtension(MV_PVOID This)
+{
+	PConsolidate_Extension pCons = CONS_GET_EXTENSION(This);
+	PMV_Request pReq;
+	MV_U32 i;
+
+	MV_LIST_HEAD_INIT(&pCons->Free_Queue);
+	for (i = 0; i < CONS_MAX_INTERNAL_REQUEST_COUNT; i++) {
+		pReq = &pCons->Requests[i];
+
+		Consolid_InitialInternalRequest(This, pReq, MV_TRUE);
+		List_AddTail(&pReq->Queue_Pointer, &pCons->Free_Queue);
+	}
+}
+
+/* 
+ * Initialize the Consolidate_Device.
+ * I don't initialize all the devices at once.
+ * Caller should call device one by one.
+ * So in this way, consolidate module doesn't all the Consolidate_Device are together
+ * or they are embedded in some caller data structure.
+ * One more advantage is that caller itself can map the Device_Id to related Consolidate_Device buffer.
+ * We don't need contiguous Device_Id.
+ */
+void Consolid_InitializeDevice(MV_PVOID This, MV_U16 Device_Id)
+{
+	PConsolidate_Device pConsDevice = CONS_GET_DEVICE(This, Device_Id);
+
+	MV_ZeroMemory(pConsDevice, sizeof(Consolidate_Device));
+}
+
+
+/*
+ * Caller pushes us to send the holding request if any.
+ */
+void
+Consolid_PushSendRequest(
+	MV_PVOID This,
+	MV_U16 Device_Id
+	)
+{
+	PConsolidate_Extension pCons = CONS_GET_EXTENSION(This);
+	PConsolidate_Device pConsDevice = CONS_GET_DEVICE(This, Device_Id);
+	PMV_Request pInternal = pConsDevice->Holding_Request;
+
+	if ( pInternal==NULL ) return;
+
+	UpdateConsolidateStatistics(CONSOLIDATE_GOT_PUSHED);
+
+	Consolid_CloseRequest(pCons, pConsDevice, pInternal);
+	/* After Consolid_CloseRequest pConsDevice->Holding_Request is NULL. */
+	CONS_SEND_REQUEST(This, pInternal);
+}
+#endif
+
diff --git a/drivers/scsi/thor/core/thor/consolid.h b/drivers/scsi/thor/core/thor/consolid.h
new file mode 100755
index 0000000..e7049a0
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/consolid.h
@@ -0,0 +1,61 @@
+#ifndef _CONSOLIDATE_H
+#define _CONSOLIDATE_H
+
+/*
+ * Here is the definition for the command consolidate sub module
+ * This is only changed when we modify the consolidate algorithm.
+ */
+#define CONS_MAX_INTERNAL_REQUEST_COUNT	32
+
+#define CONS_MAX_EXTERNAL_REQUEST_SIZE	(1024*64)
+#define CONS_SEQUENTIAL_MAX				0x7FFF		/* Avoid overflow. It's determined by Sequential variable size */
+#define CONS_SEQUENTIAL_THRESHOLD		64			/* Must bigger than OS outstanding request. Refer to Consolid_RequestCallBack */
+
+#define CONS_MAX_INTERNAL_REQUEST_SIZE	(1024*128)	/* The maximum request size hardware can handle. */
+#if defined(_OS_LINUX) && defined(SUPPORT_RAID6)
+#define CONS_MIN_INTERNAL_REQUEST_SIZE	(1024*64)
+#else
+#define CONS_MIN_INTERNAL_REQUEST_SIZE	(1024*128)	/* We'll accumulate the request to this size and then fire. */
+#endif
+
+typedef struct _Consolidate_Extension
+{
+	MV_Request	Requests[CONS_MAX_INTERNAL_REQUEST_COUNT];
+	List_Head	Free_Queue;
+}Consolidate_Extension, *PConsolidate_Extension;
+
+typedef struct _Consolidate_Device
+{
+	MV_LBA		Last_LBA;				/* last LBA*/
+	PMV_Request Holding_Request;		/* Internal request which already consolidate some external requests. */
+	MV_U16		Sequential;				/* sequential counter */
+	MV_BOOLEAN	Is_Read;				/* The last request is read or write. */
+	MV_U8		Reserved0;
+	MV_U16		Reserved1[2];			
+}Consolidate_Device, *PConsolidate_Device;
+
+void
+Consolid_ModuleSendRequest(
+	MV_PVOID This,
+	PMV_Request pReq
+	);
+
+void 
+Consolid_InitializeExtension(
+	MV_PVOID This
+	);
+
+void
+Consolid_InitializeDevice(
+	MV_PVOID This,
+	MV_U16 Device_Id
+	);
+
+void
+Consolid_PushSendRequest(
+	MV_PVOID This,
+	MV_U16 Device_Id
+	);
+
+#endif
+
diff --git a/drivers/scsi/thor/core/thor/core_api.c b/drivers/scsi/thor/core/thor/core_api.c
new file mode 100755
index 0000000..d6d65ac
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_api.c
@@ -0,0 +1,711 @@
+#include "mv_include.h"
+
+#ifdef CORE_SUPPORT_API
+
+#include "core_api.h"
+#include "core_exp.h"
+#include "core_inter.h"
+#include "core_init.h"
+#include "com_error.h"
+
+typedef MV_BOOLEAN (*CORE_Management_Command_Handler)(PCore_Driver_Extension, PMV_Request);
+CORE_Management_Command_Handler core_pd_cmd_handler[];
+
+MV_BOOLEAN
+Core_MapHDId(
+	IN PCore_Driver_Extension pCore,
+	IN MV_U16 HDId,
+	OUT MV_PU8 portId,
+	OUT MV_PU8 deviceId
+	);
+
+MV_VOID
+Core_GetHDInformation(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice,
+	OUT PHD_Info pHD 
+	);
+
+MV_VOID
+Core_GetExpInformation(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice,
+	OUT PExp_Info pExp 
+	);
+
+MV_VOID
+Core_GetPMInformation(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	OUT PPM_Info pPM 
+	);
+
+MV_VOID
+Core_GetHDConfiguration(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice,
+	OUT PHD_Config pHD 
+	);
+
+MV_VOID
+Core_SetHDConfiguration(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice,
+	IN PHD_Config pHD 
+	);
+
+/*
+ * Exposed Functions
+ */
+MV_VOID
+Core_GetHDInfo(
+	IN MV_PVOID extension,
+	IN MV_U16 HDId,
+	OUT PHD_Info pHD 
+	)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)extension;
+	MV_U16 startId, endId;
+	MV_U8 portId, deviceId;
+	PDomain_Port pPort = NULL;
+	PDomain_Device pDevice = NULL;
+	MV_U16 i;
+
+	if ( HDId==0xFF )	/* Get all the HD information */
+	{
+		/* First set invalid flag in buffer */
+		for (i=0; i<MAX_DEVICE_SUPPORTED; i++) {
+			pHD[i].Link.Self.DevID = i;
+			pHD[i].Link.Self.DevType = DEVICE_TYPE_NONE;
+		}
+		startId = 0; 
+		endId = MV_MAX_HD_DEVICE_ID-1;
+	}
+	else
+	{
+		startId = HDId;
+		endId = HDId;
+	}
+
+	for ( i=startId; i<=endId; i++ )
+	{
+		if ( Core_MapHDId(pCore, i, &portId, &deviceId) )
+		{
+			pPort = &pCore->Ports[portId];
+			pDevice = &pPort->Device[deviceId];
+			Core_GetHDInformation( pCore, pPort, pDevice, pHD );
+		} 
+/*
+		else
+		{
+			pHD->ID = i;
+			pHD->Type = DEVICE_TYPE_NONE;
+		}
+*/
+		//MV_DASSERT( pHD->Id==i );
+		pHD++;
+	}
+}
+
+#ifdef SUPPORT_PM
+MV_VOID
+Core_GetExpInfo(
+	IN MV_PVOID extension,
+	IN MV_U16 ExpId,
+	OUT PExp_Info pExp 
+	)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)extension;
+	MV_U16 startId, endId;
+	MV_U8 portId, deviceId;
+	PDomain_Port pPort = NULL;
+	PDomain_Device pDevice = NULL;
+	MV_U16 i;
+
+	if ( ExpId==0xFF )
+	{
+		/* Get all the HD information */
+		startId = 0; 
+		if (MAX_EXPANDER_SUPPORTED > 0)
+			endId = MAX_EXPANDER_SUPPORTED-1;
+		else
+			endId = 0;
+	}
+	else
+	{
+		startId = ExpId;
+		endId = ExpId;
+	}
+
+	for ( i=startId; i<=endId; i++ )
+	{
+		if ( Core_MapHDId(pCore, i, &portId, &deviceId) )
+		{
+			pPort = &pCore->Ports[portId];
+			pDevice = &pPort->Device[deviceId];
+			Core_GetExpInformation( pCore, pPort, pDevice, pExp );
+		} 
+		else
+		{
+			pExp->Link.Self.DevID = i;
+			pExp->Link.Self.DevType = DEVICE_TYPE_NONE;
+		}
+		pExp++;
+	}
+}
+
+MV_VOID
+Core_GetPMInfo(
+	IN MV_PVOID extension,
+	IN MV_U16 PMId,
+	OUT PPM_Info pPM 
+	)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)extension;
+	MV_U16 startId, endId;
+	PDomain_Port pPort = NULL;
+	MV_U16 i;
+
+	if ( PMId==0xFF )
+	{
+		/* Get all the PM information */
+		startId = 0; 
+		endId = pCore->Port_Num - 1;
+	}
+	else
+	{
+		startId = PMId;
+		endId = PMId;
+	}
+
+	for ( i=startId; i<=endId; i++ )
+	{
+		pPort = &pCore->Ports[i];
+		if ( pPort->Type != PORT_TYPE_PM )
+		{
+			if ( PMId != 0xFF )
+			{
+				// not a PM, return error
+			}
+		}
+		else 
+		{
+			Core_GetPMInformation( pCore, pPort, pPM );
+			pPM++;
+		}
+	}
+}
+#endif	/* #ifdef SUPPORT_PM */
+
+MV_VOID
+Core_GetHDConfig(
+	IN MV_PVOID extension,
+	IN MV_U16 HDId,
+	OUT PHD_Config pHD 
+	)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)extension;
+	MV_U16 startId, endId;
+	MV_U8 portId, deviceId;
+	PDomain_Port pPort = NULL;
+	PDomain_Device pDevice = NULL;
+	MV_U16 i;
+
+	/* Get all the HD configuration */
+	if ( HDId==0xFF )
+	{
+		/* First set invalid flag in buffer */
+		for (i=0; i<MAX_DEVICE_SUPPORTED; i++)
+			pHD[i].HDID = 0xFF;
+		startId = 0; 
+		endId = MV_MAX_HD_DEVICE_ID-1;
+	}
+	else
+	{
+		startId = HDId;
+		endId = HDId;
+	}
+
+
+	for ( i=startId; i<=endId; i++ )
+	{
+		if ( Core_MapHDId(pCore, i, &portId, &deviceId) )
+		{
+			pPort = &pCore->Ports[portId];
+			pDevice = &pPort->Device[deviceId];
+			Core_GetHDConfiguration( pCore, pPort, pDevice, pHD );
+		}
+		pHD++;
+	}
+}
+/*
+ * Internal Functions
+ */
+MV_BOOLEAN
+Core_MapHDId(
+	IN PCore_Driver_Extension pCore,
+	IN MV_U16 HDId,
+	OUT MV_PU8 portId,
+	OUT MV_PU8 deviceId
+	)
+{
+	if ( portId ) *portId = PATA_MapPortId(HDId);
+	if ( deviceId ) *deviceId = PATA_MapDeviceId(HDId);
+
+	if ( ((portId)&&(*portId>=MAX_PORT_NUMBER))
+		|| ((deviceId)&&(*deviceId>=MAX_DEVICE_PER_PORT))
+		)
+		return MV_FALSE;
+	else
+		return MV_TRUE;
+}
+
+MV_VOID
+Core_GetHDInformation(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice,
+	OUT PHD_Info pHD 
+	)
+{
+	pHD->Link.Self.DevID = pDevice->Id ;	
+	if ( !(pDevice->Status&DEVICE_STATUS_FUNCTIONAL) )
+	{
+		pHD->Link.Self.DevType = DEVICE_TYPE_NONE;
+		return;
+	}
+
+	// check if device type is correct; if not, generate sense
+	pHD->Link.Self.DevType = DEVICE_TYPE_HD;
+	pHD->Link.Self.PhyCnt = 1;
+	pHD->Link.Self.PhyID[0] = 0;
+
+	pHD->Link.Parent.DevID = pPort->Id;
+	pHD->Link.Parent.PhyCnt = 1;
+	if ( pPort->Type==PORT_TYPE_PM )
+	{
+		pHD->Link.Parent.DevType = DEVICE_TYPE_PM;
+		pHD->Link.Parent.PhyID[0] = pDevice->PM_Number;
+	}
+	else
+	{
+		pHD->Link.Parent.DevType = DEVICE_TYPE_PORT;
+		pHD->Link.Parent.PhyID[0] = pPort->Id;
+	}
+
+	pHD->Status = 0;
+	if ( pPort->Type==PORT_TYPE_PATA )
+		pHD->HDType = HD_TYPE_PATA;
+	else
+		pHD->HDType = HD_TYPE_SATA;
+	if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+		pHD->HDType |= HD_TYPE_ATAPI;
+
+	pHD->PIOMode = pDevice->PIO_Mode;
+	pHD->MDMAMode = pDevice->MDMA_Mode;
+	pHD->UDMAMode = pDevice->UDMA_Mode;
+	pHD->CurrentPIOMode = pDevice->Current_PIO;
+	pHD->CurrentMDMAMode = pDevice->Current_MDMA;
+	pHD->CurrentUDMAMode = pDevice->Current_UDMA;
+
+	if ( pDevice->Capacity & DEVICE_CAPACITY_NCQ_SUPPORTED )
+		pHD->FeatureSupport |= HD_FEATURE_NCQ;		
+	if ( pDevice->Capacity & DEVICE_CAPACITY_WRITECACHE_SUPPORTED )
+		pHD->FeatureSupport |= HD_FEATURE_WRITE_CACHE;		
+	if ( pDevice->Capacity & DEVICE_CAPACITY_48BIT_SUPPORTED )
+		pHD->FeatureSupport |= HD_FEATURE_48BITS;		
+	if ( pDevice->Capacity & DEVICE_CAPACITY_SMART_SUPPORTED )
+		pHD->FeatureSupport |= HD_FEATURE_SMART;	
+
+	if ( pDevice->Capacity & DEVICE_CAPACITY_RATE_1_5G )
+		pHD->FeatureSupport |= HD_FEATURE_1_5G;
+	else if ( pDevice->Capacity & DEVICE_CAPACITY_RATE_3G )
+		pHD->FeatureSupport |= HD_FEATURE_3G;
+
+	MV_CopyMemory(pHD->Model, pDevice->Model_Number, 40);
+	MV_CopyMemory(pHD->SerialNo, pDevice->Serial_Number, 20);
+	MV_CopyMemory(pHD->FWVersion, pDevice->Firmware_Revision, 8);
+
+	*(MV_PU32)pHD->WWN = pDevice->WWN;
+	pHD->Size = U64_ADD_U32(pDevice->Max_LBA, 1);
+}
+
+#ifdef SUPPORT_PM
+MV_VOID
+Core_GetExpInformation(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice,
+	OUT PExp_Info pExp 
+	)
+{
+}
+
+MV_VOID
+Core_GetPMInformation(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	OUT PPM_Info pPM 
+	)
+{
+#ifndef RAID_SIMULATE_CONFIGURATION
+	pPM->Link.Self.DevType = DEVICE_TYPE_PM;
+	pPM->Link.Self.DevID = pPort->Id;
+	pPM->Link.Self.PhyCnt = 1;
+	pPM->Link.Self.PhyID[0] = 0;
+
+	pPM->Link.Parent.DevType = DEVICE_TYPE_PORT;
+	pPM->Link.Parent.DevID = 0;
+	pPM->Link.Parent.PhyCnt = 1;
+	pPM->Link.Parent.PhyID[0] = pPort->Id;
+
+	pPM->VendorId = pPort->PM_Vendor_Id;
+	pPM->DeviceId = pPort->PM_Device_Id;
+	pPM->ProductRevision = pPort->PM_Product_Revision;
+	pPM->PMSpecRevision = pPort->PM_Spec_Revision;
+	pPM->NumberOfPorts = pPort->PM_Num_Ports;
+#endif
+}
+#endif	/* #ifdef SUPPORT_PM */
+
+MV_VOID
+Core_GetHDConfiguration(
+	PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice,
+	OUT PHD_Config pHD 
+	)
+{
+	if ( !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) )
+	{
+		pHD->HDID = 0xFF;
+		return;
+	}
+
+	pHD->HDID = pDevice->Id ;	
+
+	if (pDevice->Setting & DEVICE_SETTING_WRITECACHE_ENABLED)
+		pHD->WriteCacheOn = MV_TRUE;
+	else
+		pHD->WriteCacheOn = MV_FALSE;
+
+	if ( pDevice->Setting & DEVICE_SETTING_SMART_ENABLED )
+		pHD->SMARTOn = MV_TRUE;
+	else
+		pHD->SMARTOn = MV_FALSE;
+
+	if (pDevice->Capacity & DEVICE_CAPACITY_RATE_3G)
+		pHD->DriveSpeed = HD_SPEED_3G;
+	else
+		pHD->DriveSpeed = HD_SPEED_1_5G;
+	
+}
+
+MV_BOOLEAN core_pd_request_get_HD_info(PCore_Driver_Extension pCore, PMV_Request pMvReq)
+{
+	PHD_Info pHDInfo = (PHD_Info)pMvReq->Data_Buffer;
+	MV_U16 HDID; 
+
+	MV_CopyMemory(&HDID, &pMvReq->Cdb[2], 2);
+	Core_GetHDInfo( pCore, HDID, pHDInfo );
+	if (HDID != 0xFF && pHDInfo->Link.Self.DevType == DEVICE_TYPE_NONE)
+	{
+		if (pMvReq->Sense_Info_Buffer != NULL)
+			((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = ERR_INVALID_HD_ID;
+		pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE;
+	}
+	else
+		pMvReq->Scsi_Status = REQ_STATUS_SUCCESS;
+	return MV_TRUE;
+}
+
+#ifdef SUPPORT_PM
+MV_BOOLEAN core_pd_request_get_expander_info( PCore_Driver_Extension pCore, PMV_Request pMvReq )
+{
+	PExp_Info pExpInfo = (PExp_Info)pMvReq->Data_Buffer;
+	MV_U16 ExpID; 
+	MV_U8	status = REQ_STATUS_SUCCESS;
+
+	MV_CopyMemory(&ExpID, &pMvReq->Cdb[2], 2);
+	if (ExpID != 0xFF && ExpID > MAX_EXPANDER_SUPPORTED)
+	{
+		status = ERR_INVALID_EXP_ID;
+	}
+	else
+	{
+		Core_GetExpInfo( pCore, ExpID, pExpInfo );
+
+		if (ExpID != 0xFF && pExpInfo->Link.Self.DevType == DEVICE_TYPE_NONE)
+		{
+			status = ERR_INVALID_EXP_ID;
+		}
+	}
+
+	if (status != REQ_STATUS_SUCCESS)
+	{
+		if (pMvReq->Sense_Info_Buffer != NULL)
+			((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = status;
+		pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE;
+	}
+	else
+		pMvReq->Scsi_Status = REQ_STATUS_SUCCESS;
+
+	return MV_TRUE;
+}
+
+MV_BOOLEAN core_pd_request_get_PM_info( PCore_Driver_Extension pCore, PMV_Request pMvReq )
+{
+	PPM_Info pPMInfo = (PPM_Info)pMvReq->Data_Buffer;
+	MV_U16 PMID; 
+
+	MV_CopyMemory(&PMID, &pMvReq->Cdb[2], 2);
+	if (PMID != 0xFF && PMID > MAX_PM_SUPPORTED)
+	{
+		if (pMvReq->Sense_Info_Buffer != NULL)
+			((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = ERR_INVALID_PM_ID;
+		pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE;
+		return MV_TRUE;
+	}
+
+	Core_GetPMInfo( pCore, PMID, pPMInfo );
+	
+	pMvReq->Scsi_Status = REQ_STATUS_SUCCESS;
+	return MV_TRUE;
+}
+#endif	/*#ifdef SUPPORT_PM */
+
+MV_BOOLEAN core_pd_request_get_HD_config( PCore_Driver_Extension pCore, PMV_Request pMvReq )
+{
+	PHD_Config pHDConfig = (PHD_Config)pMvReq->Data_Buffer;
+	MV_U16 ConfigID; 
+
+	MV_CopyMemory(&ConfigID, &pMvReq->Cdb[2], 2);
+	Core_GetHDConfig( pCore, ConfigID, pHDConfig );
+
+	if (ConfigID != 0xFF && pHDConfig->HDID == 0xFF)
+	{
+		if (pMvReq->Sense_Info_Buffer != NULL)
+			((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = ERR_INVALID_HD_ID;
+		pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE;
+	}
+	else
+		pMvReq->Scsi_Status = REQ_STATUS_SUCCESS;
+
+	return MV_TRUE;
+}
+
+MV_BOOLEAN core_pd_request_get_HD_status( PCore_Driver_Extension pCore, PMV_Request pMvReq )
+{
+	PHD_Status pHDStatus = (PHD_Status)pMvReq->Data_Buffer;
+	PDomain_Port pPort = NULL;
+	PDomain_Device pDevice = NULL;
+	MV_U8 portId, deviceId;
+	MV_U16 HDId; 
+	MV_U8	cacheMode = 0;
+	MV_U8 status = REQ_STATUS_SUCCESS;
+
+	MV_CopyMemory(&HDId, &pMvReq->Cdb[2], 2);
+
+	if ( Core_MapHDId(pCore, HDId, &portId, &deviceId) )
+	{
+		pPort = &pCore->Ports[portId];
+		pDevice = &pPort->Device[deviceId];
+
+		if (pDevice->Setting & DEVICE_SETTING_SMART_ENABLED)
+		{
+			if ( !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) )
+			{
+				status = ERR_INVALID_HD_ID;
+			}
+			else 
+			{
+				if (pMvReq->Cdb[4] == APICDB4_PD_SMART_RETURN_STATUS)
+				{
+					cacheMode = CDB_CORE_SMART_RETURN_STATUS;
+				}
+				else
+					status = ERR_INVALID_REQUEST;
+			}
+
+			if (status == REQ_STATUS_SUCCESS)
+			{
+				// Convert it into SCSI_CMD_MARVELL_SPECIFIC request.
+				pMvReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+				pMvReq->Cdb[1] = CDB_CORE_MODULE;
+				pMvReq->Cdb[2] = cacheMode;
+				pMvReq->Device_Id = pDevice->Id;
+				if (pHDStatus)
+					pHDStatus->HDID = pDevice->Id;
+			}
+		}
+		else
+			status = ERR_INVALID_REQUEST;
+	} 
+	else
+	{
+		status = ERR_INVALID_HD_ID;
+	}
+
+	if (status != REQ_STATUS_SUCCESS)
+	{
+		if (pMvReq->Sense_Info_Buffer != NULL)
+			((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = status;
+		pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE;
+		return MV_TRUE;	
+	}
+	else
+	{
+		pMvReq->Scsi_Status = REQ_STATUS_SUCCESS;
+		return MV_FALSE;	// Need to access hardware.
+	}
+}
+
+MV_BOOLEAN core_pd_request_set_HD_config( PCore_Driver_Extension pCore, PMV_Request pMvReq )
+{
+	//PHD_Config pHDConfig = (PHD_Config)pMvReq->Data_Buffer;
+	PDomain_Port pPort = NULL;
+	PDomain_Device pDevice = NULL;
+	MV_U8 portId, deviceId;
+	MV_U16 HDId; 
+	MV_U8	cacheMode = 0;
+	MV_U8 status = REQ_STATUS_PENDING;
+
+	MV_CopyMemory(&HDId, &pMvReq->Cdb[2], 2);
+
+	if ( Core_MapHDId(pCore, HDId, &portId, &deviceId) )
+	{
+		pPort = &pCore->Ports[portId];
+		pDevice = &pPort->Device[deviceId];
+
+		if ( !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) )
+		{
+			status = ERR_INVALID_HD_ID;
+		}
+		else if ( pDevice->Device_Type & DEVICE_TYPE_ATAPI )
+		{
+			status = ERR_INVALID_REQUEST;
+		}
+		else 
+		{
+			if (pMvReq->Cdb[4] == APICDB4_PD_SET_WRITE_CACHE_OFF)
+			{
+				cacheMode = CDB_CORE_DISABLE_WRITE_CACHE;
+			}
+			else if (pMvReq->Cdb[4] == APICDB4_PD_SET_WRITE_CACHE_ON)
+			{
+				cacheMode = CDB_CORE_ENABLE_WRITE_CACHE;
+			}
+			else if (pMvReq->Cdb[4] == APICDB4_PD_SET_SMART_OFF)
+			{
+				if ( !(pDevice->Setting&DEVICE_SETTING_SMART_ENABLED) )
+					status = REQ_STATUS_SUCCESS;
+				cacheMode = CDB_CORE_DISABLE_SMART;
+			}
+			else if (pMvReq->Cdb[4] == APICDB4_PD_SET_SMART_ON)
+			{
+				if ( pDevice->Setting&DEVICE_SETTING_SMART_ENABLED )
+					status = REQ_STATUS_SUCCESS;
+				cacheMode = CDB_CORE_ENABLE_SMART;
+			}
+			else
+			{
+				status = ERR_INVALID_REQUEST;
+			}
+		}
+
+		if (status == REQ_STATUS_PENDING)
+		{
+			// Convert it into SCSI_CMD_MARVELL_SPECIFIC request.
+			pMvReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+			pMvReq->Cdb[1] = CDB_CORE_MODULE;
+			pMvReq->Cdb[2] = cacheMode;
+			pMvReq->Device_Id = pDevice->Id;
+		}
+	} 
+	else
+	{
+		status = ERR_INVALID_HD_ID;
+	}
+
+	if (status == REQ_STATUS_SUCCESS)
+	{
+		pMvReq->Scsi_Status = status;
+		return MV_TRUE;
+	}
+	else if (status == REQ_STATUS_PENDING)
+	{
+		//pMvReq->Scsi_Status = REQ_STATUS_SUCCESS;
+		return MV_FALSE;	// Need to access hardware.
+	}
+	else
+	{
+		if (pMvReq->Sense_Info_Buffer != NULL)
+			((MV_PU8)pMvReq->Sense_Info_Buffer)[0] = status;
+		pMvReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE;
+		return MV_TRUE;	
+	}
+}
+
+MV_BOOLEAN core_pd_request_BSL_dump( PCore_Driver_Extension pCore, PMV_Request pMvReq )
+{
+	pMvReq->Scsi_Status = REQ_STATUS_ERROR;
+	return MV_TRUE;
+}
+
+MV_BOOLEAN core_pd_request_HD_MP_check( PCore_Driver_Extension pCore, PMV_Request pMvReq )
+{
+	pMvReq->Scsi_Status = REQ_STATUS_ERROR;
+	return MV_TRUE;
+}
+
+MV_BOOLEAN core_pd_request_HD_get_MP_status( PCore_Driver_Extension pCore, PMV_Request pMvReq )
+{
+	pMvReq->Scsi_Status = REQ_STATUS_ERROR;
+	return MV_TRUE;
+}
+
+CORE_Management_Command_Handler BASEATTR core_pd_cmd_handler[APICDB1_PD_MAX] = 
+{
+	core_pd_request_get_HD_info,
+#ifdef SUPPORT_PM
+	core_pd_request_get_expander_info,
+	core_pd_request_get_PM_info,
+#else
+	NULL,
+	NULL,
+#endif
+	core_pd_request_get_HD_config,
+	core_pd_request_set_HD_config,
+	core_pd_request_BSL_dump,
+	core_pd_request_HD_MP_check,
+	core_pd_request_HD_get_MP_status,
+	core_pd_request_get_HD_status,
+	NULL
+};
+
+MV_BOOLEAN 
+Core_pd_command(
+	IN MV_PVOID extension,
+	IN PMV_Request pReq
+	)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)extension;
+
+	if ( pReq->Cdb[1] >= APICDB1_PD_MAX ) 
+	{
+		pReq->Scsi_Status = REQ_STATUS_INVALID_PARAMETER;
+		return MV_TRUE;
+	}
+	if (core_pd_cmd_handler[pReq->Cdb[1]] == NULL)
+	{
+		pReq->Scsi_Status = REQ_STATUS_INVALID_PARAMETER;
+		return MV_TRUE;
+	}
+	return core_pd_cmd_handler[pReq->Cdb[1]](pCore, pReq);
+}
+#endif
+
diff --git a/drivers/scsi/thor/core/thor/core_api.h b/drivers/scsi/thor/core/thor/core_api.h
new file mode 100755
index 0000000..6d66ba5
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_api.h
@@ -0,0 +1,45 @@
+#if !defined(CORE_API_H)
+#define CORE_API_H
+
+#ifdef CORE_SUPPORT_API
+
+#define HD_WRITECACHE_OFF		0
+#define HD_WRITECACHE_ON		1
+
+MV_VOID
+Core_GetHDInfo(
+	IN MV_PVOID extension,
+	IN MV_U16 HDId,
+	OUT PHD_Info pHD );
+
+MV_VOID
+Core_GetExpInfo(
+	IN MV_PVOID extension,
+	IN MV_U16 ExpId,
+	OUT PExp_Info pExp 
+	);
+
+MV_VOID
+Core_GetPMInfo(
+	IN MV_PVOID extension,
+	IN MV_U16 PMId,
+	OUT PPM_Info pPM 
+	);
+
+MV_VOID
+Core_GetHDConfig(
+	IN MV_PVOID extension,
+	IN MV_U16 HDId,
+	OUT PHD_Config pHD 
+	);
+
+MV_BOOLEAN 
+Core_pd_command(
+	IN MV_PVOID extension, 
+	IN PMV_Request pReq
+	);
+
+#endif
+
+#endif
+
diff --git a/drivers/scsi/thor/core/thor/core_ata.h b/drivers/scsi/thor/core/thor/core_ata.h
new file mode 100755
index 0000000..03947bb
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_ata.h
@@ -0,0 +1,261 @@
+#if !defined(CORE_ATA_H)
+#define CORE_ATA_H
+
+
+/*
+ * ATA IDE Command definition 
+ */
+/* PIO command */
+#define ATA_CMD_READ_PIO				0x20
+#define ATA_CMD_READ_PIO_EXT			0x24
+#define ATA_CMD_READ_PIO_MULTIPLE_EXT 	0x29
+#define ATA_CMD_WRITE_PIO				0x30
+#define ATA_CMD_WRITE_PIO_EXT			0x34
+#define ATA_CMD_WRITE_PIO_MULTIPLE_EXT	0x39
+
+/* DMA read write command */
+#define ATA_CMD_READ_DMA				0xC8	/* 28 bit DMA read */
+#define ATA_CMD_READ_DMA_QUEUED			0xC7	/* 28 bit TCQ DMA read */
+#define ATA_CMD_READ_DMA_EXT			0x25	/* 48 bit DMA read */
+#define ATA_CMD_READ_DMA_QUEUED_EXT		0x26	/* 48 bit TCQ DMA read */
+#define ATA_CMD_READ_FPDMA_QUEUED		0x60	/* NCQ DMA read: SATA only. Always 48 bit */
+
+#define ATA_CMD_WRITE_DMA				0xCA	
+#define ATA_CMD_WRITE_DMA_QUEUED		0xCC
+#define ATA_CMD_WRITE_DMA_EXT  			0x35
+#define ATA_CMD_WRITE_DMA_QUEUED_EXT	0x36
+#define ATA_CMD_WRITE_FPDMA_QUEUED		0x61
+
+/* Identify command */
+#define ATA_CMD_IDENTIFY_ATA			0xEC
+#define ATA_CMD_IDENTIY_ATAPI			0xA1
+
+#define ATA_CMD_VERIFY					0x40	/* 28 bit read verifty */
+#define ATA_CMD_VERIFY_EXT				0x42	/* 48 bit read verify */
+
+#define ATA_CMD_FLUSH					0xE7	/* 28 bit flush */
+#define ATA_CMD_FLUSH_EXT				0xEA	/* 48 bit flush */
+
+#define ATA_CMD_PACKET					0xA0
+#define ATA_CMD_SMART					0xB0
+	#define ATA_CMD_SMART_READ_DATA 					0xD0
+	#define ATA_CMD_SMART_ENABLE_ATTRIBUTE_AUTOSAVE	0xD2
+	#define ATA_CMD_SMART_EXECUTE_OFFLINE				0xD4
+	#define ATA_CMD_SMART_READ_LOG						0xD5
+	#define ATA_CMD_SMART_WRITE_LOG 					0xD6
+	#define ATA_CMD_ENABLE_SMART				0xD8
+	#define ATA_CMD_DISABLE_SMART				0xD9
+	#define ATA_CMD_SMART_RETURN_STATUS			0xDA
+
+#define ATA_CMD_SET_FEATURES			0xEF
+	#define ATA_CMD_ENABLE_WRITE_CACHE			0x02
+	#define ATA_CMD_SET_TRANSFER_MODE			0x03
+	#define ATA_CMD_DISABLE_READ_LOOK_AHEAD		0x55
+	#define ATA_CMD_DISABLE_WRITE_CACHE			0x82
+	#define ATA_CMD_ENABLE_READ_LOOK_AHEAD		0xAA
+
+#define ATA_CMD_STANDBY_IMMEDIATE		0xE0
+#define ATA_CMD_SEEK					0x70
+#define ATA_CMD_READ_LOG_EXT			0x2F
+#ifdef SUPPORT_ATA_SECURITY_CMD
+
+/*	security commmand */
+#define ATA_CMD_SEC_PASSWORD			0xF1
+#define ATA_CMD_SEC_UNLOCK			0xF2
+#define ATA_CMD_SEC_ERASE_PRE			0xF3
+#define ATA_CMD_SEC_ERASE_UNIT			0xF4
+#define ATA_CMD_SEC_FREEZE_LOCK			0xF5
+#define ATA_CMD_SEC_DISABLE_PASSWORD		0xF6
+
+enum _ata_passthru_protocol {
+        ATA_PROTOCOL_HARD_RESET                 = 0x00,
+        ATA_PROTOCOL_SRST                       = 0x01,
+        ATA_PROTOCOL_NON_DATA                   = 0x03,
+        ATA_PROTOCOL_PIO_IN                     = 0x04,
+        ATA_PROTOCOL_PIO_OUT                    = 0x05,
+        ATA_PROTOCOL_DMA                        = 0x06,
+        ATA_PROTOCOL_DMA_QUEUED                 = 0x07,
+        ATA_PROTOCOL_DEVICE_DIAG                = 0x08,
+        ATA_PROTOCOL_DEVICE_RESET               = 0x09,
+        ATA_PROTOCOL_UDMA_IN                    = 0x0A,
+        ATA_PROTOCOL_UDMA_OUT                   = 0x0B,
+        ATA_PROTOCOL_FPDMA                      = 0x0C,
+        ATA_PROTOCOL_RTN_INFO                   = 0x0F,
+};
+#define ATA_CMD_READ_PIO				0x20
+#define ATA_CMD_READ_PIO_MULTIPLE                       0xC4
+#define ATA_CMD_READ_PIO_EXT			0x24
+#define ATA_CMD_READ_PIO_MULTIPLE_EXT 	0x29
+#define ATA_CMD_WRITE_PIO				0x30
+#define ATA_CMD_WRITE_PIO_MULTIPLE                      0xC5
+#define ATA_CMD_WRITE_PIO_EXT			0x34
+#define ATA_CMD_WRITE_PIO_MULTIPLE_EXT	0x39
+#define ATA_CMD_WRITE_PIO_MULTIPLE_FUA_EXT              0xCE
+
+#define IS_ATA_MULTIPLE_READ_WRITE(x) \
+        ((x == ATA_CMD_READ_PIO_MULTIPLE)\
+        ||(x == ATA_CMD_READ_PIO_MULTIPLE_EXT)\
+        ||(x == ATA_CMD_WRITE_PIO_MULTIPLE)\
+        ||(x == ATA_CMD_WRITE_PIO_MULTIPLE_EXT)\
+        ||(x == ATA_CMD_WRITE_PIO_MULTIPLE_FUA_EXT))
+
+enum {
+	SG_CDB2_TLEN_NODATA	= 0 << 0,
+	SG_CDB2_TLEN_FEAT	= 1 << 0,
+	SG_CDB2_TLEN_NSECT	= 2 << 0,
+
+	SG_CDB2_TLEN_BYTES	= 0 << 2,
+	SG_CDB2_TLEN_SECTORS	= 1 << 2,
+
+	SG_CDB2_TDIR_TO_DEV	= 0 << 3,
+	SG_CDB2_TDIR_FROM_DEV	= 1 << 3,
+
+	SG_CDB2_CHECK_COND	= 1 << 5,
+};
+#define SG_READ			0
+#define SG_WRITE		1
+#define SG_PIO			0
+#define SG_DMA			1
+
+enum {
+	/*
+	 * These (redundantly) specify the category of the request
+	 */
+	TASKFILE_CMD_REQ_NODATA	= 0,	/* ide: IDE_DRIVE_TASK_NO_DATA */
+	TASKFILE_CMD_REQ_IN	= 2,	/* ide: IDE_DRIVE_TASK_IN */
+	TASKFILE_CMD_REQ_OUT	= 3,	/* ide: IDE_DRIVE_TASK_OUT */
+	TASKFILE_CMD_REQ_RAW_OUT= 4,	/* ide: IDE_DRIVE_TASK_RAW_WRITE */
+	/*
+	 * These specify the method of transfer (pio, dma, multi, ..)
+	 */
+	TASKFILE_DPHASE_NONE	= 0,	/* ide: TASKFILE_IN */
+	TASKFILE_DPHASE_PIO_IN	= 1,	/* ide: TASKFILE_IN */
+	TASKFILE_DPHASE_PIO_OUT	= 4,	/* ide: TASKFILE_OUT */
+};
+#define SG_ATA_LBA48		1
+#define SG_ATA_PROTO_NON_DATA	( 3 << 1)
+#define SG_ATA_PROTO_PIO_IN	( 4 << 1)
+#define SG_ATA_PROTO_PIO_OUT	( 5 << 1)
+#define SG_ATA_PROTO_DMA	( 6 << 1)
+#define SG_ATA_PROTO_UDMA_IN	(11 << 1) /* not yet supported in libata */
+#define SG_ATA_PROTO_UDMA_OUT	(12 << 1) /* not yet supported in libata */
+
+#endif
+
+
+
+struct _ATA_TaskFile;
+typedef struct _ATA_TaskFile ATA_TaskFile, *PATA_TaskFile;
+
+struct _ATA_TaskFile {
+	MV_U8	Features;
+	MV_U8	Sector_Count;
+	MV_U8	LBA_Low;
+	MV_U8	LBA_Mid;
+	MV_U8	LBA_High;
+	MV_U8	Device;
+	MV_U8	Command;
+
+	MV_U8	Control;
+
+	/* extension */
+	MV_U8	Feature_Exp;
+	MV_U8	Sector_Count_Exp;
+	MV_U8	LBA_Low_Exp;
+	MV_U8	LBA_Mid_Exp;
+	MV_U8	LBA_High_Exp;
+};
+
+/* ATA device identify frame */
+typedef struct _ATA_Identify_Data {
+	MV_U16 General_Config;							/*	0	*/
+	MV_U16 Obsolete0;								/*	1	*/
+	MV_U16 Specific_Config;							/*	2	*/
+	MV_U16 Obsolete1;								/*	3	*/
+	MV_U16 Retired0[2];								/*	4-5	*/
+	MV_U16 Obsolete2;								/*	6	*/
+	MV_U16 Reserved0[2];							/*	7-8	*/
+	MV_U16 Retired1;								/*	9	*/
+	MV_U8 Serial_Number[20];				        /*	10-19	*/
+	MV_U16 Retired2[2];								/*	20-21	*/
+	MV_U16 Obsolete3;								/*	22	*/
+	MV_U8 Firmware_Revision[8];						/*	23-26	*/
+	MV_U8 Model_Number[40];							/*	27-46	*/
+	MV_U16 Maximum_Block_Transfer;					/*	47	*/
+	MV_U16 Reserved1;								/*	48	*/
+	MV_U16 Capabilities[2];							/*	49-50	*/
+	MV_U16 Obsolete4[2];							/*	51-52	*/
+	MV_U16 Fields_Valid;							/*	53	*/
+	MV_U16 Obsolete5[5];							/*	54-58	*/
+	MV_U16 Current_Multiple_Sector_Setting;			/*	59	*/
+	MV_U16 User_Addressable_Sectors[2];				/*	60-61	*/
+	MV_U16 ATAPI_DMADIR;							/*	62	*/
+	MV_U16 Multiword_DMA_Modes;						/*	63	*/
+	MV_U16 PIO_Modes;								/*	64	*/
+	MV_U16 Minimum_Multiword_DMA_Cycle_Time;		/*	65	*/
+	MV_U16 Recommended_Multiword_DMA_Cycle_Time;	/*	66	*/
+	MV_U16 Minimum_PIO_Cycle_Time;					/*	67	*/
+	MV_U16 Minimum_PIO_Cycle_Time_IORDY;			/*	68	*/
+	MV_U16 Reserved2[2];							/*	69-70	*/
+	MV_U16 ATAPI_Reserved[4];						/*	71-74	*/
+	MV_U16 Queue_Depth;								/*	75	*/
+	MV_U16 SATA_Capabilities;						/*	76	*/
+	MV_U16 SATA_Reserved;							/*	77	*/
+	MV_U16 SATA_Feature_Supported;					/*	78	*/
+	MV_U16 SATA_Feature_Enabled;					/*	79	*/
+ 	MV_U16 Major_Version;							/*	80	*/
+	MV_U16 Minor_Version;							/*	81	*/
+	MV_U16 Command_Set_Supported[2];				/*	82-83	*/
+	MV_U16 Command_Set_Supported_Extension;			/*	84	*/
+	MV_U16 Command_Set_Enabled[2];					/*	85-86	*/
+	MV_U16 Command_Set_Default;						/*	87	*/
+	MV_U16 UDMA_Modes;								/*	88	*/
+	MV_U16 Time_For_Security_Erase;					/*	89	*/
+	MV_U16 Time_For_Enhanced_Security_Erase;		/*	90	*/
+	MV_U16 Current_Advanced_Power_Manage_Value;		/*	91	*/
+	MV_U16 Master_Password_Revision;				/*	92	*/
+	MV_U16 Hardware_Reset_Result;					/*	93	*/
+	MV_U16 Acoustic_Manage_Value;					/*	94	*/
+	MV_U16 Stream_Minimum_Request_Size;				/*	95	*/
+	MV_U16 Stream_Transfer_Time_DMA;				/*	96	*/
+	MV_U16 Stream_Access_Latency;					/*	97	*/
+	MV_U16 Stream_Performance_Granularity[2];		/*	98-99	*/
+	MV_U16 Max_LBA[4];								/*	100-103	*/
+	MV_U16 Stream_Transfer_Time_PIO;				/*	104	*/	
+	MV_U16 Reserved3;								/*	105	*/
+	MV_U16 Physical_Logical_Sector_Size;			/*	106	*/
+	MV_U16 Delay_Acoustic_Testing;					/*	107	*/
+	MV_U16 NAA;										/*	108	*/
+	MV_U16 Unique_ID1;								/*	109	*/
+	MV_U16 Unique_ID2;								/*	110	*/
+	MV_U16 Unique_ID3;								/*	111	*/
+	MV_U16 Reserved4[4];							/*	112-115	*/
+	MV_U16 Reserved5;								/*	116	*/
+	MV_U16 Words_Per_Logical_Sector[2];				/*	117-118	*/
+	MV_U16 Reserved6[8];							/*	119-126	*/
+	MV_U16 Removable_Media_Status_Notification;		/*	127	*/
+	MV_U16 Security_Status;							/*	128	*/
+	MV_U16 Vendor_Specific[31];						/*	129-159	*/
+	MV_U16 CFA_Power_Mode;							/*	160	*/
+	MV_U16 Reserved7[15];							/*	161-175	*/
+	MV_U16 Current_Media_Serial_Number[30];			/*	176-205	*/
+	MV_U16 Reserved8[49];							/*	206-254	*/
+	MV_U16 Integrity_Word;							/*	255	*/
+} ATA_Identify_Data, *PATA_Identify_Data;
+
+#define ATA_REGISTER_DATA			0x08
+#define ATA_REGISTER_ERROR			0x09
+#define ATA_REGISTER_FEATURES		0x09
+#define ATA_REGISTER_SECTOR_COUNT	0x0A
+#define ATA_REGISTER_LBA_LOW		0x0B
+#define ATA_REGISTER_LBA_MID		0x0C
+#define ATA_REGISTER_LBA_HIGH		0x0D
+#define ATA_REGISTER_DEVICE			0x0E
+#define ATA_REGISTER_STATUS			0x0F
+#define ATA_REGISTER_COMMAND		0x0F
+
+#define ATA_REGISTER_ALT_STATUS		0x16
+#define ATA_REGISTER_DEVICE_CONTROL	0x16
+
+#endif
+
diff --git a/drivers/scsi/thor/core/thor/core_cons.h b/drivers/scsi/thor/core/thor/core_cons.h
new file mode 100755
index 0000000..26bbdb0
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_cons.h
@@ -0,0 +1,29 @@
+#ifndef _CORE_DIRVER_CONSOLIDATE_H
+#define _CORE_DRIVER_CONSOLIDATE_H
+
+#include "core_inter.h"
+#include "core_exp.h"
+
+/*
+ * When you plug-in this command consolidate sub-module to some module
+ * Please define the following the definition.
+ * This is maintained by caller.
+ */
+/* Get the consolidate sub module extension */
+#define CONS_GET_EXTENSION(This)					\
+	(((PCore_Driver_Extension)(This))->pConsolid_Extent)
+
+/* Get the device related information consolidate module needs */
+#define CONS_GET_DEVICE(This, Device_Id)	\
+	&(((PCore_Driver_Extension)(This))->pConsolid_Device[(Device_Id)])
+
+/* For this device or port, is there any request running? If yes, busy. */
+#define CONS_DEVICE_IS_BUSY(This, deviceId)	\
+	(((PCore_Driver_Extension)(This))->Ports[PATA_MapPortId(deviceId)].Running_Slot!=0)
+
+extern void Core_InternalSendRequest(MV_PVOID This, PMV_Request pReq);
+/* In case there is something wrong. We need resend these requests and by pass them. */
+#define CONS_SEND_REQUEST	Core_InternalSendRequest
+
+#endif
+
diff --git a/drivers/scsi/thor/core/thor/core_exp.c b/drivers/scsi/thor/core/thor/core_exp.c
new file mode 100755
index 0000000..94b64d5
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_exp.c
@@ -0,0 +1,4624 @@
+#include "mv_include.h"
+
+#include "core_exp.h"
+#include "core_inter.h"
+#include "com_tag.h"
+
+#include "core_sata.h"
+#include "core_ata.h"
+
+#include "core_init.h"
+
+#if defined(_OS_LINUX)
+#include "hba_timer.h"
+#endif /* _OS_LINUX */
+
+#ifdef CORE_SUPPORT_API
+#include "core_api.h"
+#endif
+
+#ifdef SOFTWARE_XOR
+#include "core_xor.h"
+#endif
+#include "core_sat.h"
+
+#define FIS_REG_H2D_SIZE_IN_DWORD	5
+
+void sendDummyFIS( PDomain_Port pPort );
+void mv_core_put_back_request(PDomain_Port pPort);
+MV_U8 mv_core_reset_port(PDomain_Port pPort);
+#ifdef COMMAND_ISSUE_WORKROUND
+void mv_core_dump_reg(PDomain_Port pPort);
+void  mv_core_reset_command(PDomain_Port pPort);
+void mv_core_init_reset_para(PDomain_Port pPort);
+#endif
+extern MV_VOID SCSI_To_FIS(MV_PVOID pCore, PMV_Request pReq, MV_U8 tag, PATA_TaskFile pTaskFile);
+
+extern MV_BOOLEAN Category_CDB_Type(
+	IN PDomain_Device pDevice,
+	IN PMV_Request pReq
+	);
+
+extern MV_BOOLEAN ATAPI_CDB2TaskFile(
+	IN PDomain_Device pDevice,
+	IN PMV_Request pReq, 
+	OUT PATA_TaskFile pTaskFile
+	);
+
+extern MV_BOOLEAN ATA_CDB2TaskFile(
+	IN PDomain_Device pDevice,
+	IN PMV_Request pReq, 
+	IN MV_U8 tag,	
+	OUT PATA_TaskFile pTaskFile
+	);
+
+extern void Device_IssueReadLogExt(
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice
+	);
+
+extern MV_BOOLEAN mvDeviceStateMachine(
+	PCore_Driver_Extension pCore,
+	PDomain_Device pDevice
+	);
+
+void CompleteRequest(
+	IN PCore_Driver_Extension pCore,
+	IN PMV_Request pReq,
+	IN PATA_TaskFile taskFiles
+	);
+
+void CompleteRequestAndSlot(
+	IN PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PMV_Request pReq,
+	IN PATA_TaskFile taskFiles,
+	IN MV_U8 slotId
+	);
+
+#if defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX)
+void Core_ResetChannel(MV_PVOID Device, MV_PVOID temp);
+
+static MV_VOID __core_req_timeout_handler(MV_PVOID data)
+{
+	PMV_Request req = (PMV_Request) data;
+	PCore_Driver_Extension pcore;
+	PDomain_Device dev;
+	PHBA_Extension phba;
+
+	if ( NULL == req )
+		return;
+#ifdef SUPPORT_ATA_SMART
+	if(req->Cdb[0]==SCSI_CMD_SND_DIAG) {
+	MV_DPRINT(("Command :'Execute SMART self-test routine' fail.\n"));
+	hba_remove_timer(req);
+	return;
+	}
+#endif
+#ifdef SUPPORT_ATA_SECURITY_CMD
+	if(req->Cdb[0]==ATA_16 && req->Cdb[14]==0xf4) {
+		MV_PRINT("The command of Security Erase is running\n");
+		hba_remove_timer(req);
+		hba_add_timer(req,60, __core_req_timeout_handler);
+		return;
+	}
+#endif
+	pcore = HBA_GetModuleExtension(req->Cmd_Initiator, MODULE_CORE);
+	dev   = &pcore->Ports[PATA_MapPortId(req->Device_Id)].Device[PATA_MapDeviceId(req->Device_Id)];
+	phba = HBA_GetModuleExtension(req->Cmd_Initiator, MODULE_HBA);
+#ifdef MV_DEBUG
+	MV_DPRINT(("Request time out. Resetting channel %d. \n", PATA_MapPortId(req->Device_Id)));	
+	MV_DumpRequest(req, 0);
+#endif
+	hba_spin_lock_irq(&phba->desc->hba_desc->global_lock);
+	Core_ResetChannel((MV_PVOID) dev, NULL);
+	hba_spin_unlock_irq(&phba->desc->hba_desc->global_lock);
+}
+#endif /* SUPPORT_ERROR_HANDLING && _OS_LINUX */
+
+#ifdef SUPPORT_SCSI_PASSTHROUGH
+// Read TaskFile
+void readTaskFiles(IN PDomain_Port pPort, PDomain_Device pDevice, PATA_TaskFile pTaskFiles)
+{
+	MV_U32 taskFile[3];
+
+	if (pPort->Type==PORT_TYPE_PATA)
+	{
+		if ( pDevice->Is_Slave )
+		{
+			taskFile[1] = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_SLAVE_TF1);
+			taskFile[2] = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_SLAVE_TF2);
+		}
+		else
+		{
+			taskFile[1] = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_MASTER_TF1);
+			taskFile[2] = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_MASTER_TF2);
+		}
+
+		pTaskFiles->Sector_Count = (MV_U8)((taskFile[1] >> 24) & 0xFF);
+		pTaskFiles->Sector_Count_Exp = (MV_U8)((taskFile[1] >> 16) & 0xFF);
+		pTaskFiles->LBA_Low = (MV_U8)((taskFile[1] >> 8) & 0xFF);
+		pTaskFiles->LBA_Low_Exp = (MV_U8)(taskFile[1] & 0xFF);
+
+		pTaskFiles->LBA_Mid = (MV_U8)((taskFile[2] >> 24) & 0xFF);
+		pTaskFiles->LBA_Mid_Exp = (MV_U8)((taskFile[2] >> 16) & 0xFF);
+		pTaskFiles->LBA_High = (MV_U8)((taskFile[2] >> 8) & 0xFF);
+		pTaskFiles->LBA_High_Exp = (MV_U8)(taskFile[2] & 0xFF);
+	}
+	else
+	{
+//		taskFile[0] = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_TFDATA);
+		taskFile[1] = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_SIG);
+//		taskFile[2] = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_SCR);
+
+		pTaskFiles->Sector_Count = (MV_U8)((taskFile[1]) & 0xFF);
+		pTaskFiles->LBA_Low = (MV_U8)((taskFile[1] >> 8) & 0xFF);
+		pTaskFiles->LBA_Mid = (MV_U8)((taskFile[1] >> 16) & 0xFF);
+		pTaskFiles->LBA_High = (MV_U8)((taskFile[1] >> 24) & 0xFF);
+
+	}
+}
+#endif
+
+
+void mv_core_set_running_slot(PDomain_Port pPort, MV_U32 slot_num, PMV_Request pReq)
+{
+
+#ifdef MV_DEBUG
+	if ( pPort->Running_Slot >> slot_num & MV_BIT(0)  )
+	{
+		MV_DPRINT(("Why the slot[%d] is used.\n",slot_num));
+	}
+
+	if(pPort->Running_Req[slot_num]){
+		MV_DPRINT(("Why the running req[%d] is used.\n",slot_num));
+		MV_DumpRequest(pPort->Running_Req[slot_num], MV_FALSE);
+	}
+#endif
+	pPort->Running_Slot |= 1<<slot_num;
+	pPort->Running_Req[slot_num] = pReq;
+}
+
+void mv_core_reset_running_slot(PDomain_Port pPort, MV_U32 slot_num)
+{
+
+#ifdef MV_DEBUG
+	if ( !(pPort->Running_Slot >> slot_num & MV_BIT(0)) )
+	{
+		MV_DPRINT(("Why the slot[%d] is not used.\n",slot_num));
+	}
+
+	if(!pPort->Running_Req[slot_num]){
+		MV_DPRINT(("Why the running req[%d] is not used.\n",slot_num));
+		MV_DumpRequest(pPort->Running_Req[slot_num], MV_FALSE);
+	}
+#endif
+
+	pPort->Running_Req[slot_num] = NULL;
+	pPort->Running_Slot &= ~(1L<<slot_num);
+	Tag_ReleaseOne(&pPort->Tag_Pool, slot_num);
+}
+
+
+
+MV_U32 Core_ModuleGetResourceQuota(enum Resource_Type type, MV_U16 maxIo)
+{
+	MV_U32 size = 0;
+	MV_U8 sgEntryCount, tagCount;
+	
+	/* Extension quota */	
+	if ( type==RESOURCE_CACHED_MEMORY )		
+	{
+		size = ROUNDING(sizeof(Core_Driver_Extension), 8);
+	#ifdef SUPPORT_CONSOLIDATE
+		if ( maxIo>1 )
+		{
+			size += ROUNDING(sizeof(Consolidate_Extension), 8);
+			size += ROUNDING(sizeof(Consolidate_Device), 8)*MAX_DEVICE_NUMBER;
+		}
+	#endif
+
+		/* resource for SG Entry and Tag Pool */
+		if (maxIo==1) {
+			sgEntryCount = MAX_SG_ENTRY_REDUCED;
+			tagCount = 1;
+		}
+		else {
+			sgEntryCount = MAX_SG_ENTRY;
+			tagCount = MAX_SLOT_NUMBER - 1;		/* leave the last slot for PM hot-plug */
+		}
+
+#ifdef _OS_LINUX
+#ifdef USE_NEW_SGVP
+		sgEntryCount *= 2;
+#endif
+#endif /* _OS_LINUX */
+
+		size += sizeof(MV_SG_Entry) * sgEntryCount * INTERNAL_REQ_COUNT;
+		size += sizeof(MV_Request) * INTERNAL_REQ_COUNT;
+
+		/* tag pool */
+		size += ROUNDING(sizeof(MV_U16) * tagCount * MAX_PORT_NUMBER, 8); 
+
+#ifdef SUPPORT_CONSOLIDATE
+		/* resource for Consolidate_Extension->Requests[] SG Entry */	
+		if ( maxIo>1 )
+			size += sizeof(MV_SG_Entry) * sgEntryCount * CONS_MAX_INTERNAL_REQUEST_COUNT;
+#endif
+		return size;
+	}
+	
+	/* Uncached memory quota */
+	if ( type==RESOURCE_UNCACHED_MEMORY )
+	{
+		/* 
+		 * SATA port alignment quota:
+		 * Command list and received FIS is 64 byte aligned.
+		 * Command table is 128 byte aligned.
+		 * Data buffer is 8 byte aligned.
+		 * This is different with AHCI.
+		 */
+		/* 
+		 * PATA port alignment quota: Same with SATA.
+		 * The only difference is that PATA doesn't have the FIS.
+		 */
+		MV_DPRINT(("Command List Size = 0x%x.\n", (MV_U32)SATA_CMD_LIST_SIZE));
+		MV_DPRINT(("Received FIS Size = 0x%x.\n", (MV_U32)SATA_RX_FIS_SIZE));
+		MV_DPRINT(("Command Table Size = 0x%x.\n", (MV_U32)SATA_CMD_TABLE_SIZE));
+		MV_ASSERT(SATA_CMD_LIST_SIZE==ROUNDING(SATA_CMD_LIST_SIZE, 64));
+		MV_ASSERT(SATA_RX_FIS_SIZE==ROUNDING(SATA_RX_FIS_SIZE, 64));
+//		MV_ASSERT(SATA_CMD_TABLE_SIZE==ROUNDING(SATA_CMD_TABLE_SIZE, 128));
+		MV_ASSERT(SATA_SCRATCH_BUFFER_SIZE==ROUNDING(SATA_SCRATCH_BUFFER_SIZE, 8));
+		if ( maxIo>1 )
+		{
+			size = 64 + SATA_CMD_LIST_SIZE*MAX_PORT_NUMBER;								/* Command List*/
+			size += 64 + SATA_RX_FIS_SIZE*MAX_SATA_PORT_NUMBER;							/* Received FIS */
+			size += 128 + SATA_CMD_TABLE_SIZE*MAX_SLOT_NUMBER*MAX_PORT_NUMBER;			/* Command Table */
+			size += 8 + SATA_SCRATCH_BUFFER_SIZE*MAX_DEVICE_NUMBER;						/* Buffer for initialization like identify */
+		}
+		else
+		{
+		#ifndef HIBERNATION_ROUNTINE
+			size = 64 + SATA_CMD_LIST_SIZE*MAX_PORT_NUMBER;
+			size += 64 + SATA_RX_FIS_SIZE*MAX_SATA_PORT_NUMBER;
+			size += 128 + SATA_CMD_TABLE_SIZE*MAX_PORT_NUMBER;
+			size += 8 + SATA_SCRATCH_BUFFER_SIZE*MAX_DEVICE_NUMBER;
+		#else
+			size = 64 + SATA_CMD_LIST_SIZE;			/* Command List*/
+			size += 64 + SATA_RX_FIS_SIZE;			/* Received FIS */
+			size += 128 + SATA_CMD_TABLE_SIZE; 		/* Command Table */	
+			size += 8 + SATA_SCRATCH_BUFFER_SIZE;	/* Buffer for initialization like identify */
+		#endif
+		}
+
+		return size;
+	}
+
+	return 0;
+}
+
+void Core_ModuleInitialize(MV_PVOID ModulePointer, MV_U32 extensionSize, MV_U16 maxIo)
+{
+#if defined(NEW_LINUX_DRIVER) 
+	struct mv_mod_desc *mod_desc = (struct mv_mod_desc *)ModulePointer;
+	MV_PVOID		This = (MV_PVOID)mod_desc->extension;
+	PCore_Driver_Extension pCore    = (PCore_Driver_Extension) mod_desc->extension;
+	MV_U32 size=0;
+#else
+	MV_PVOID		This=ModulePointer;
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)ModulePointer;
+	Controller_Infor controller;
+#endif	/* NEW_LINUX_DRIVER*/
+
+
+	PMV_Request pReq;
+	Assigned_Uncached_Memory dmaResource;
+	PDomain_Port port;
+	MV_PVOID memVir;
+	MV_PHYSICAL_ADDR memDMA;
+	MV_PTR_INTEGER temp, tmpSG;
+	MV_U32 offset, internalReqSize, tagSize;
+	MV_U8 i,j, flagSaved, sgEntryCount, tagCount;
+	MV_U32 vsr_c[MAX_SATA_PORT_NUMBER];
+	MV_U8 vsrSkipPATAPort = 0;
+#ifndef _OS_LINUX
+	MV_PVOID pTopLayer = HBA_GetModuleExtension(pCore, MODULE_HBA);
+#endif	
+	flagSaved=pCore->VS_Reg_Saved;
+
+	if(flagSaved==VS_REG_SIG)
+	{
+		for ( j=0; j<MAX_SATA_PORT_NUMBER; j++ )
+		{
+			port = &pCore->Ports[j];
+			vsr_c[j]=port->VS_RegC;
+		}
+		/* Save the PATA Port detection skip flag */
+		vsrSkipPATAPort = pCore->Flag_Fastboot_Skip & FLAG_SKIP_PATA_PORT;
+	}
+
+	/* 
+	 * Zero core driver extension. After that, I'll ignore many variables initialization. 
+	 */
+	MV_ZeroMemory(This, extensionSize);
+
+	if(flagSaved==VS_REG_SIG)
+	{
+		pCore->VS_Reg_Saved=flagSaved;
+
+		for ( j=0; j<MAX_SATA_PORT_NUMBER; j++ )
+		{
+			port = &pCore->Ports[j];
+			port->VS_RegC=vsr_c[j];
+		}
+		/* Restore the PATA Port detection skip flag */
+		/* Only this flag should survive the S3 */
+		/* The others should be kept as default (0) */
+		pCore->Flag_Fastboot_Skip = vsrSkipPATAPort;
+	}
+
+	pCore->State = CORE_STATE_IDLE;
+	/* Set up controller information */
+#if defined(__MM_SE__) 
+	/* Set up controller information */
+	pCore->desc        = mod_desc;
+	pCore->Vendor_Id   = mod_desc->hba_desc->vendor;
+	pCore->Device_Id   = mod_desc->hba_desc->device;
+	pCore->Revision_Id = mod_desc->hba_desc->Revision_Id;	
+	MV_DPRINT(("pCore->Device_Id = 0x%x.\n",pCore->Device_Id));
+	/*
+	pCore->Sub_System_Id =mod_desc->hba_desc->Sub_System_Id;
+	pCore->Sub_Vendor_Id =mod_desc->hba_desc->Sub_Vendor_Id;
+ 	*/
+	for ( i=0; i<MAX_BASE_ADDRESS; i++ )
+	{
+		pCore->Base_Address[i] = mod_desc->hba_desc->Base_Address[i];
+		MV_DPRINT(("pCore->Base_Address[%d]=%p.\n", i,pCore->Base_Address[i]));
+	}
+	pCore->Mmio_Base = mod_desc->hba_desc->Base_Address[MV_PCI_BAR];
+ #else
+	/* Set up controller information */
+	HBA_GetControllerInfor(pCore, &controller);
+	pCore->Vendor_Id = controller.Vendor_Id;
+	pCore->Device_Id = controller.Device_Id;
+	pCore->Revision_Id = controller.Revision_Id;
+	for ( i=0; i<MAX_BASE_ADDRESS; i++ )
+	{
+		pCore->Base_Address[i] = controller.Base_Address[i];
+	}
+	pCore->Mmio_Base = controller.Base_Address[MV_PCI_BAR];
+
+#endif /*_OS_LINUX*/
+	pCore->Adapter_State = ADAPTER_INITIALIZING;
+	MV_LIST_HEAD_INIT(&pCore->Waiting_List);
+	MV_LIST_HEAD_INIT(&pCore->Internal_Req_List);
+
+	if ( maxIo==1 )
+		pCore->Is_Dump = MV_TRUE;
+	else
+		pCore->Is_Dump = MV_FALSE;
+
+	if (flagSaved!=VS_REG_SIG) {	/* Added for tuning boot up time */
+		/* This initialization is during boot up time, but not S3 */
+		/* Read registers modified by BIOS to set detection flag */
+		if ( (pCore->Device_Id==DEVICE_ID_THOR_4S1P_NEW) ||
+			 (pCore->Device_Id==DEVICE_ID_THORLITE_2S1P_WITH_FLASH) ||
+			 (pCore->Device_Id==DEVICE_ID_THORLITE_2S1P)) {
+			MV_U32 tmpReg = 0;
+			/* Read Bit[3] of PCI CNFG offset 60h to get flag for */
+			/* PATA port enable/disable (0 - default, need to detect) */
+#ifdef _OS_WINDOWS
+#undef MV_PCI_READ_CONFIG_DWORD
+#define MV_PCI_READ_CONFIG_DWORD(mod_ext, offset, reg) \
+                reg = MV_PCI_READ_DWORD(mod_ext, offset)
+			MV_PCI_READ_CONFIG_DWORD(pTopLayer, 0x60, tmpReg);
+#else
+			MV_PCI_READ_CONFIG_DWORD(pCore, 0x60, &tmpReg);
+#endif /* _OS_WINDOWS */
+			tmpReg &= MV_BIT(3);
+
+			pCore->Flag_Fastboot_Skip |= (tmpReg >> 3);		/* bit 0 */
+			/* Read Bit[10], Bit [11] of BAR5 offset A4h to get flag for */
+			/* PATA device detection (0 - default, need to detect) and */
+			/* PM detection (0 - default, need to detect) */
+			tmpReg = MV_REG_READ_DWORD(pCore->Mmio_Base, VENDOR_DETECT) & 
+						(VENDOR_DETECT_PATA | VENDOR_DETECT_PM);
+			pCore->Flag_Fastboot_Skip |= (tmpReg >> 9);		/* bit 1, 2 */
+		}
+	}
+
+	if ( (pCore->Device_Id==DEVICE_ID_THORLITE_2S1P)||(pCore->Device_Id==DEVICE_ID_THORLITE_2S1P_WITH_FLASH) )
+	{
+		pCore->SATA_Port_Num = 2;
+		pCore->PATA_Port_Num = 1;
+		pCore->Port_Num = 3;
+		MV_DPRINT(("DEVICE_ID_THORLITE_2S1P is found.\n"));
+
+	}
+	else if ( pCore->Device_Id==DEVICE_ID_THORLITE_0S1P )
+	{
+		pCore->SATA_Port_Num = 0;
+		pCore->PATA_Port_Num = 1;
+		pCore->Port_Num = 1;
+		MV_DPRINT(("DEVICE_ID_THORLITE_0S1P is found.\n"));
+
+	}
+	else
+	{
+		pCore->SATA_Port_Num = 4;
+		pCore->PATA_Port_Num = 1;
+		pCore->Port_Num = 5;
+		MV_DPRINT(("DEVICE_ID_THOR is found.\n"));
+
+	}
+
+#if /*(VER_OEM==VER_OEM_ASUS) ||*/(VER_OEM==VER_OEM_INTEL)
+	pCore->Port_Num -= pCore->PATA_Port_Num;
+	pCore->PATA_Port_Num = 0;
+#else
+	if (pCore->Flag_Fastboot_Skip & FLAG_SKIP_PATA_PORT) {
+		pCore->Port_Num -= pCore->PATA_Port_Num;
+		pCore->PATA_Port_Num = 0;
+	}
+#endif
+
+	if (pCore->Is_Dump) {
+		sgEntryCount = MAX_SG_ENTRY_REDUCED;
+		tagCount = 1;	/* do not support hot-plug when hibernation */
+	}
+	else {
+		sgEntryCount = MAX_SG_ENTRY;
+		tagCount = MAX_SLOT_NUMBER - 1;		/* reserve the last slot for PM hot-plug */
+	}
+
+#ifdef _OS_LINUX
+#ifdef USE_NEW_SGVP
+	sgEntryCount *= 2;
+#endif
+#endif /* _OS_LINUX */
+
+	tmpSG = (MV_PTR_INTEGER)This + ROUNDING(sizeof(Core_Driver_Extension),8);
+	temp = 	tmpSG + sizeof(MV_SG_Entry) * sgEntryCount * INTERNAL_REQ_COUNT;
+
+	internalReqSize = MV_REQUEST_SIZE * INTERNAL_REQ_COUNT;
+	MV_ASSERT( extensionSize >= ROUNDING(sizeof(Core_Driver_Extension),8) + internalReqSize );
+	for ( i=0; i<INTERNAL_REQ_COUNT; i++ )
+	{
+		pReq = (PMV_Request)temp;
+		pReq->SG_Table.Entry_Ptr = (PMV_SG_Entry)tmpSG;
+		pReq->SG_Table.Max_Entry_Count = sgEntryCount;
+		List_AddTail(&pReq->Queue_Pointer, &pCore->Internal_Req_List);
+		tmpSG += sizeof(MV_SG_Entry) * sgEntryCount;
+		temp += MV_REQUEST_SIZE;	/* MV_Request is 64bit aligned. */
+	}	
+//	temp = ROUNDING( (MV_PTR_INTEGER)temp, 8 );		/* Don't round the extension pointer */
+
+	/* tag pool */
+	tagSize = sizeof(MV_U16) * tagCount * MAX_PORT_NUMBER;
+
+	for ( i=0; i<MAX_PORT_NUMBER; i++ )
+	{
+		port = &pCore->Ports[i];
+		port->Tag_Pool.Stack = (MV_PU16)temp;
+		port->Tag_Pool.Size = tagCount;
+		temp += sizeof(MV_U16) * tagCount;
+	}
+
+#ifdef SUPPORT_CONSOLIDATE	
+	// Allocate resource for Consolidate_Extension->Requests[].
+	tmpSG = temp;
+	temp = temp + sizeof(MV_SG_Entry) * sgEntryCount * CONS_MAX_INTERNAL_REQUEST_COUNT;
+
+	if ( pCore->Is_Dump )
+	{
+		pCore->pConsolid_Device = NULL;
+		pCore->pConsolid_Extent = NULL;
+	}
+	else
+	{
+		MV_ASSERT( extensionSize>=
+			( ROUNDING(sizeof(Core_Driver_Extension),8) + internalReqSize + tagSize + ROUNDING(sizeof(Consolidate_Extension),8) + ROUNDING(sizeof(Consolidate_Device),8)*MAX_DEVICE_NUMBER )
+			); 
+		pCore->pConsolid_Extent = (PConsolidate_Extension)(temp);
+
+		//Initialize some fields for pCore->pConsolid_Extent->Requests[i]
+		for (i=0; i<CONS_MAX_INTERNAL_REQUEST_COUNT; i++)
+		{
+			pReq = &pCore->pConsolid_Extent->Requests[i];
+
+			pReq->SG_Table.Max_Entry_Count = sgEntryCount;
+			pReq->SG_Table.Entry_Ptr = (PMV_SG_Entry)tmpSG;
+			tmpSG += sizeof(MV_SG_Entry) * sgEntryCount;
+		}
+
+		pCore->pConsolid_Device = (PConsolidate_Device)((MV_PTR_INTEGER)pCore->pConsolid_Extent + ROUNDING(sizeof(Consolidate_Extension),8));
+	}
+#endif
+
+	/* Port_Map and Port_Num will be read from the register */
+
+	/* Init port data structure */
+	for ( i=0; i<pCore->Port_Num; i++ )
+	{
+		port = &pCore->Ports[i];
+		
+		port->Id = i;
+		port->Port_State = PORT_STATE_IDLE;
+		port->Core_Extension = pCore;
+		port->Mmio_Base = (MV_PU8)pCore->Mmio_Base + 0x100 + (i * 0x80);
+		port->Mmio_SCR = (MV_PU8)port->Mmio_Base + PORT_SCR;
+
+		Tag_Init(&port->Tag_Pool, tagCount);
+
+		for (j=0; j<MAX_DEVICE_PER_PORT; j++) 
+		{
+			port->Device[j].Id = i*MAX_DEVICE_PER_PORT + j;
+			port->Device[j].PPort = port;
+			port->Device[j].Is_Slave = 0;	/* Which one is the slave will be determined during discovery. */
+#if defined(SUPPORT_TIMER) && defined(_OS_WINDOWS)
+			port->Device[j].Timer_ID = NO_CURRENT_TIMER;
+#endif
+			port->Device[j].Reset_Count = 0;
+		}
+
+		port->Device_Number = 0;
+
+		// Set function table for each port here.
+		if ( i>=pCore->SATA_Port_Num )
+			port->Type = PORT_TYPE_PATA;
+		else
+			port->Type = PORT_TYPE_SATA;
+
+#ifdef COMMAND_ISSUE_WORKROUND
+		OSSW_INIT_TIMER(&port->timer);	
+		port->reset_hba_times= 0;
+		mv_core_init_reset_para(port);
+#endif
+
+	}
+
+	/* Get uncached memory */
+#if defined(__MM_SE__) 	
+	size = pCore->desc->ops->get_res_desc(RESOURCE_UNCACHED_MEMORY, maxIo);
+	if (HBA_GetResource(pCore->desc,
+			    RESOURCE_UNCACHED_MEMORY,
+			    size,
+			    &dmaResource))
+	{
+		//pCore->State = CORE_STATE_ZOMBIE;
+		MV_ASSERT(MV_FALSE);
+		return;
+	}
+#else
+	/* Get uncached memory */
+	HBA_GetResource(pCore, RESOURCE_UNCACHED_MEMORY, &dmaResource);
+
+#endif /*_OS_LINUX*/	
+	memVir = dmaResource.Virtual_Address;
+	memDMA = dmaResource.Physical_Address;
+	
+	/* Assign uncached memory for command list (64 byte align) */
+	offset = (MV_U32)(ROUNDING(memDMA.value,64)-memDMA.value);
+	memDMA.value += offset;
+	memVir = (MV_PU8)memVir + offset;
+	for ( i=0; i<pCore->Port_Num; i++ )
+	{
+		port = &pCore->Ports[i];
+		port->Cmd_List = memVir;
+		port->Cmd_List_DMA = memDMA;
+	#ifdef HIBERNATION_ROUNTINE
+		if((!pCore->Is_Dump)|| (i==(pCore->Port_Num-1)))
+	#endif
+		{
+			memVir = (MV_PU8)memVir + SATA_CMD_LIST_SIZE;
+			memDMA.value += SATA_CMD_LIST_SIZE;
+		}
+	}
+
+	/* Assign uncached memory for received FIS (64 byte align) */
+	offset = (MV_U32)(ROUNDING(memDMA.value,64)-memDMA.value);
+	memDMA.value += offset;
+	memVir = (MV_PU8)memVir + offset;
+	for ( i=0; i<pCore->SATA_Port_Num; i++ )
+	{
+		port = &pCore->Ports[i];	
+		port->RX_FIS = memVir;
+		port->RX_FIS_DMA = memDMA;
+	#ifdef HIBERNATION_ROUNTINE
+		if((!pCore->Is_Dump)|| (i==(pCore->SATA_Port_Num-1)))
+	#endif
+		{
+			memVir = (MV_PU8)memVir + SATA_RX_FIS_SIZE;
+			memDMA.value += SATA_RX_FIS_SIZE;
+		}
+	}
+
+	/* Assign the 32 command tables. (128 byte align) */
+	offset = (MV_U32)(ROUNDING(memDMA.value,128)-memDMA.value);
+	memDMA.value += offset;
+	memVir = (MV_PU8)memVir + offset;
+	for ( i=0; i<pCore->Port_Num; i++ )
+	{
+		port = &pCore->Ports[i];
+		port->Cmd_Table = memVir;
+		port->Cmd_Table_DMA = memDMA;
+
+		if ( !pCore->Is_Dump )
+		{
+			memVir = (MV_PU8)memVir + SATA_CMD_TABLE_SIZE * MAX_SLOT_NUMBER;
+			memDMA.value += SATA_CMD_TABLE_SIZE * MAX_SLOT_NUMBER;
+		}
+		else
+		{
+		#ifdef HIBERNATION_ROUNTINE
+			if(i==(pCore->Port_Num-1))
+		#endif
+			{
+				memVir = (MV_PU8)memVir + SATA_CMD_TABLE_SIZE;
+				memDMA.value += SATA_CMD_TABLE_SIZE;
+			}
+		}
+	}
+
+	/* Assign the scratch buffer (8 byte align) */
+	offset = (MV_U32)(ROUNDING(memDMA.value,8)-memDMA.value);
+	memDMA.value += offset;
+	memVir = (MV_PU8)memVir + offset;
+	for ( i=0; i<pCore->Port_Num; i++ )
+	{
+		port = &pCore->Ports[i];
+		for ( j=0; j<MAX_DEVICE_PER_PORT; j++ )
+		{
+			port->Device[j].Scratch_Buffer = memVir;
+			port->Device[j].Scratch_Buffer_DMA = memDMA;
+		
+		#ifdef HIBERNATION_ROUNTINE
+			if((!pCore->Is_Dump)|| (i==(pCore->Port_Num-1)))
+		#endif
+			{
+				memVir = (MV_PU8)memVir + SATA_SCRATCH_BUFFER_SIZE;
+				memDMA.value += SATA_SCRATCH_BUFFER_SIZE;
+			}
+		}
+	}
+
+	/* Let me confirm the following assumption */
+	MV_ASSERT( sizeof(SATA_FIS_REG_H2D)==sizeof(MV_U32)*FIS_REG_H2D_SIZE_IN_DWORD );
+	MV_ASSERT( sizeof(MV_Command_Table)==0x80+MAX_SG_ENTRY*sizeof(MV_SG_Entry) );
+	MV_ASSERT( sizeof(ATA_Identify_Data)==512 ); 
+
+#ifdef SUPPORT_CONSOLIDATE
+	if ( !pCore->Is_Dump )
+	{
+		Consolid_InitializeExtension(This);
+		for ( i=0; i<MAX_DEVICE_NUMBER; i++ )
+			Consolid_InitializeDevice(This, i);
+	}
+#endif
+}
+
+void Core_ModuleStart(MV_PVOID This)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+
+	mvAdapterStateMachine(pCore,NULL);
+}
+
+
+void Core_ModuleShutdown(MV_PVOID This)
+{
+	/* 
+	 * This function is equivalent to ahci_port_stop 
+	 */
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	MV_U32 tmp, i;
+	MV_LPVOID mmio;
+	for ( i=0; i<pCore->Port_Num; i++ )
+	{
+		mmio = pCore->Ports[i].Mmio_Base;
+
+		tmp = MV_REG_READ_DWORD(mmio, PORT_CMD);
+		if ( pCore->Ports[i].Type==PORT_TYPE_SATA )
+			tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
+		else
+			tmp &= ~PORT_CMD_START;
+		MV_REG_WRITE_DWORD(mmio, PORT_CMD, tmp);
+		MV_REG_READ_DWORD(mmio, PORT_CMD); /* flush */
+
+		/* 
+		 * spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
+		 * this is slightly incorrect.
+		 */
+		HBA_SleepMillisecond(pCore, 500);
+	}
+
+	/* Disable the controller interrupt */
+	tmp = MV_REG_READ_DWORD(pCore->Mmio_Base, HOST_CTL);
+	tmp &= ~(HOST_IRQ_EN);
+	MV_REG_WRITE_DWORD(pCore->Mmio_Base, HOST_CTL, tmp);
+}
+
+void Core_ModuleNotification(MV_PVOID This, enum Module_Event event, struct mod_notif_param *param)
+{
+}
+
+void Core_HandleWaitingList(PCore_Driver_Extension pCore);
+void Core_InternalSendRequest(MV_PVOID This, PMV_Request pReq);
+
+void Core_ModuleSendRequest(MV_PVOID This, PMV_Request pReq)
+{	
+#ifdef SUPPORT_CONSOLIDATE
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	PDomain_Device pDevice;
+	MV_U8 portId = PATA_MapPortId(pReq->Device_Id);
+	MV_U8 deviceId = PATA_MapDeviceId(pReq->Device_Id);
+	
+	pDevice = &pCore->Ports[portId].Device[deviceId];
+	
+	if ( (!(pDevice->Device_Type&DEVICE_TYPE_ATAPI)) && (!pCore->Is_Dump) )
+		Consolid_ModuleSendRequest(pCore, pReq);
+	else
+		Core_InternalSendRequest(pCore, pReq);
+#else
+	Core_InternalSendRequest(This, pReq);
+#endif
+}
+
+void Core_InternalSendRequest(MV_PVOID This, PMV_Request pReq)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+
+#ifdef SUPPORT_ATA_POWER_MANAGEMENT
+	PDomain_Device pdev;
+	PHBA_Extension phba;
+
+	pdev = &pCore->Ports[PATA_MapPortId(pReq->Device_Id)].Device[PATA_MapDeviceId(pReq->Device_Id)];
+	if((pdev->Status & DEVICE_STATUS_SLEEP)&&(pReq->Req_Type == REQ_TYPE_OS))
+	{
+		hba_remove_timer(pReq);
+		Core_ResetChannel((MV_PVOID) pdev, NULL);
+		pdev->Status &= ~DEVICE_STATUS_SLEEP;
+	}
+#endif
+	/* Check whether we can handle this request */
+	switch (pReq->Cdb[0])
+	{
+		case SCSI_CMD_INQUIRY:
+		case SCSI_CMD_START_STOP_UNIT:
+		case SCSI_CMD_TEST_UNIT_READY:
+		case SCSI_CMD_READ_10:
+		case SCSI_CMD_WRITE_10:
+		case SCSI_CMD_VERIFY_10:
+		case SCSI_CMD_READ_CAPACITY_10:
+		case SCSI_CMD_REQUEST_SENSE:
+		case SCSI_CMD_MODE_SELECT_10:
+		case SCSI_CMD_MODE_SENSE_10:
+		case SCSI_CMD_MARVELL_SPECIFIC:
+		default:
+			if ( pReq->Cmd_Initiator==pCore )
+			{
+				if ( !SCSI_IS_READ(pReq->Cdb[0]) && !SCSI_IS_WRITE(pReq->Cdb[0]) )
+				{
+					/* Reset request or request sense command. */
+					List_Add(&pReq->Queue_Pointer, &pCore->Waiting_List);		/* Add to the header. */
+				}
+				else
+				{
+					#ifdef SUPPORT_CONSOLIDATE
+					/* Consolidate request */
+					MV_DASSERT( !pCore->Is_Dump );
+					List_AddTail(&pReq->Queue_Pointer, &pCore->Waiting_List);	/* Append to the tail. */
+					#else
+					MV_ASSERT(MV_FALSE);
+					#endif
+				}
+			}
+			else
+			{
+				List_AddTail(&pReq->Queue_Pointer, &pCore->Waiting_List);		/* Append to the tail. */
+			}
+			Core_HandleWaitingList(pCore);
+			break;
+	}
+}
+
+void SATA_PrepareCommandHeader(PDomain_Port pPort, PMV_Request pReq, MV_U8 tag)
+{
+	MV_PHYSICAL_ADDR table_addr;
+	PMV_Command_Header header = NULL;
+	PMV_SG_Table pSGTable = &pReq->SG_Table;
+#ifdef SUPPORT_PM
+	PDomain_Device pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+#endif
+	header = SATA_GetCommandHeader(pPort, tag);
+	/* 
+	 * Set up the command header.
+	 */
+	header->FIS_Length = FIS_REG_H2D_SIZE_IN_DWORD;
+	header->Packet_Command = (pReq->Cmd_Flag&CMD_FLAG_PACKET)?1:0;
+	header->Reset = 0;
+	header->NCQ = (pReq->Cmd_Flag&CMD_FLAG_NCQ)?1:0;
+
+#ifdef SUPPORT_PM
+	header->PM_Port = pDevice->PM_Number;
+#else
+	header->PM_Port = 0;
+#endif
+	*((MV_U16 *) header) = CPU_TO_LE_16( *((MV_U16 *) header) );
+	header->PRD_Entry_Count = CPU_TO_LE_16(pSGTable->Valid_Entry_Count);
+
+	table_addr.parts.high = pPort->Cmd_Table_DMA.parts.high;
+	table_addr.parts.low = pPort->Cmd_Table_DMA.parts.low + SATA_CMD_TABLE_SIZE*tag;
+	if ( table_addr.parts.low<pPort->Cmd_Table_DMA.parts.low ) {
+		MV_DPRINT(("Cross 4G boundary.\n"));
+		table_addr.parts.high++;
+	}
+
+
+	header->Table_Address = CPU_TO_LE_32(table_addr.parts.low);
+	header->Table_Address_High = CPU_TO_LE_32(table_addr.parts.high);
+}
+
+void PATA_PrepareCommandHeader(PDomain_Port pPort, PMV_Request pReq, MV_U8 tag)
+{
+	MV_PHYSICAL_ADDR table_addr;
+	PMV_PATA_Command_Header header = NULL;
+	PMV_SG_Table pSGTable = &pReq->SG_Table;
+
+	header = PATA_GetCommandHeader(pPort, tag);
+	/* 
+	 * Set up the command header.
+	 * TCQ, Diagnostic_Command, Reset
+	 * Table_Address and Table_Address_High are fixed. Needn't set every time.
+	 */
+	header->PIO_Sector_Count = 0;		/* Only for PIO multiple sector commands */
+	header->Controller_Command = 0;
+	header->TCQ = 0;
+	header->Packet_Command = (pReq->Cmd_Flag&CMD_FLAG_PACKET)?1:0;
+
+#ifdef USE_DMA_FOR_ALL_PACKET_COMMAND
+	if ( pReq->Cmd_Flag&CMD_FLAG_PACKET )
+	{
+		header->DMA = (pReq->Cmd_Flag&CMD_FLAG_NON_DATA)?0:1;
+	}
+	else
+	{
+		header->DMA = (pReq->Cmd_Flag&CMD_FLAG_DMA)?1:0;
+	}
+#elif defined(USE_PIO_FOR_ALL_PACKET_COMMAND)
+	if ( pReq->Cmd_Flag&CMD_FLAG_PACKET )
+	{
+		header->DMA = 0;
+	}
+	else
+	{
+		header->DMA = (pReq->Cmd_Flag&CMD_FLAG_DMA)?1:0;
+	}
+#else	
+	header->DMA = (pReq->Cmd_Flag&CMD_FLAG_DMA)?1:0;
+#endif
+
+	header->Data_In = (pReq->Cmd_Flag&CMD_FLAG_DATA_IN)?1:0;
+	header->Non_Data = (pReq->Cmd_Flag&CMD_FLAG_NON_DATA)?1:0;
+
+	header->PIO_Sector_Command = 0;
+	header->Is_48Bit = (pReq->Cmd_Flag&CMD_FLAG_48BIT)?1:0;
+	header->Diagnostic_Command = 0;
+	header->Reset = 0;
+
+	header->Is_Slave = pPort->Device[PATA_MapDeviceId(pReq->Device_Id)].Is_Slave;
+
+	*((MV_U16 *) header) = CPU_TO_LE_16( *((MV_U16 *) header) );
+	header->PRD_Entry_Count = CPU_TO_LE_16(pSGTable->Valid_Entry_Count);
+
+	table_addr.parts.high = pPort->Cmd_Table_DMA.parts.high;
+	table_addr.parts.low = pPort->Cmd_Table_DMA.parts.low + SATA_CMD_TABLE_SIZE*tag;
+	if ( table_addr.parts.low<pPort->Cmd_Table_DMA.parts.low ) {
+		MV_DPRINT(("Cross 4G boundary.\n"));
+		table_addr.parts.high++;
+	}
+
+	header->Table_Address = CPU_TO_LE_32(table_addr.parts.low);
+	header->Table_Address_High = CPU_TO_LE_32(table_addr.parts.high);
+}
+
+/*
+ * Fill SATA command table
+ */
+MV_VOID SATA_PrepareCommandTable(
+	PDomain_Port pPort, 
+	PMV_Request pReq, 
+	MV_U8 tag,
+	PATA_TaskFile pTaskFile
+	)
+{
+#ifdef USE_NEW_SGTABLE
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+#else
+	PMV_SG_Entry pSGEntry = NULL;
+	MV_U8 i;
+#endif
+	PMV_Command_Table pCmdTable = Port_GetCommandTable(pPort, tag);
+
+	PMV_SG_Table pSGTable = &pReq->SG_Table;
+
+	/* Step 1: fill the command FIS: MV_Command_Table */
+	SCSI_To_FIS(pPort->Core_Extension, pReq, tag, pTaskFile);
+
+	/* Step 2. fill the ATAPI CDB */
+	if ( pReq->Cmd_Flag&CMD_FLAG_PACKET )
+	{
+		MV_CopyMemory(pCmdTable->ATAPI_CDB, pReq->Cdb, MAX_CDB_SIZE);
+	}
+
+	/* Step 3: fill the PRD Table if necessary. */
+	if ( (pSGTable) && (pSGTable->Valid_Entry_Count) )
+	{
+#ifdef USE_NEW_SGTABLE
+		MV_U16 consumed;
+		PMV_Command_Header header = NULL;
+
+		header = SATA_GetCommandHeader(pPort, tag);
+		consumed = (MV_U16)sgdt_prepare_hwprd(pCore, pSGTable, pCmdTable->PRD_Entry, HW_SG_ENTRY_MAX);
+		if (consumed == 0) {
+			/* resource not enough... */
+			MV_DPRINT(("Run out of PRD entry.\n"));
+			if( pReq->Req_Flag & REQ_FLAG_CONSOLIDATE )
+			{
+				pReq->Scsi_Status = REQ_STATUS_BUSY;
+				Tag_ReleaseOne(&pPort->Tag_Pool, tag);
+				return;
+			}
+			else
+			{
+				/* check why upper layer send request with too many sg items... */
+				MV_DASSERT( MV_FALSE );
+			}
+		}
+		header->PRD_Entry_Count = CPU_TO_LE_16(consumed);
+#else /* USE_NEW_SGTABLE */
+		if ( (pSGTable) && (pSGTable->Valid_Entry_Count) )
+		{
+			/* "Transfer Byte Count" in AHCI and 614x PRD table is zero based. */
+			for ( i=0; i<pSGTable->Valid_Entry_Count; i++ )
+			{
+				pSGEntry = &pCmdTable->PRD_Entry[i];
+				pSGEntry->Base_Address = CPU_TO_LE_32(pSGTable->Entry_Ptr[i].Base_Address);
+				pSGEntry->Base_Address_High = CPU_TO_LE_32(pSGTable->Entry_Ptr[i].Base_Address_High);
+				pSGEntry->Size = CPU_TO_LE_32(pSGTable->Entry_Ptr[i].Size-1);
+			}
+		}
+		else
+		{	
+			MV_DASSERT( !SCSI_IS_READ(pReq->Cdb[0]) && !SCSI_IS_WRITE(pReq->Cdb[0]) );
+		}
+#endif /* USE_NEW_SGTABLE */
+	}
+	else
+	{	
+		MV_DASSERT( !SCSI_IS_READ(pReq->Cdb[0]) && !SCSI_IS_WRITE(pReq->Cdb[0]) );
+	}
+}
+
+/*
+ * Fill the PATA command table
+*/
+static MV_VOID PATA_PrepareCommandTable(
+	PDomain_Port pPort, 
+	PMV_Request pReq, 
+	MV_U8 tag,
+	PATA_TaskFile pTaskFile
+	)
+{
+#ifdef USE_NEW_SGTABLE
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+#endif
+	PMV_Command_Table pCmdTable = Port_GetCommandTable(pPort, tag);
+	PMV_SG_Table pSGTable = &pReq->SG_Table;
+	MV_PU8 pU8 = (MV_PU8)pCmdTable;
+	MV_U8 device_index;
+
+	device_index = PATA_MapDeviceId(pReq->Device_Id);
+
+	/* Step 1: Fill the command block */
+	(*pU8)=pTaskFile->Features; pU8++;
+	(*pU8)=pTaskFile->Feature_Exp; pU8++;
+	(*pU8)=pTaskFile->Sector_Count; pU8++;
+	(*pU8)=pTaskFile->Sector_Count_Exp; pU8++;
+	(*pU8)=pTaskFile->LBA_Low; pU8++;
+	(*pU8)=pTaskFile->LBA_Low_Exp; pU8++;
+	(*pU8)=pTaskFile->LBA_Mid; pU8++;
+	(*pU8)=pTaskFile->LBA_Mid_Exp; pU8++;
+	(*pU8)=pTaskFile->Command; pU8++;
+	(*pU8)=pTaskFile->Device; pU8++;
+	(*pU8)=pTaskFile->LBA_High; pU8++;
+	(*pU8)=pTaskFile->LBA_High_Exp; pU8++;
+	*((MV_PU32)pU8) = 0L;
+    
+	/* Step 2: Fill the ATAPI CDB */
+	if ( pReq->Cmd_Flag&CMD_FLAG_PACKET )
+	{
+		MV_CopyMemory(pCmdTable->ATAPI_CDB, pReq->Cdb, MAX_CDB_SIZE);
+	}
+
+	/* Step 3: Fill the PRD Table if necessary. */
+	if ( (pSGTable) && (pSGTable->Valid_Entry_Count) )
+	{
+#ifdef USE_NEW_SGTABLE
+		MV_U16 consumed = (MV_U16) sgdt_prepare_hwprd(pCore, pSGTable, pCmdTable->PRD_Entry, HW_SG_ENTRY_MAX);
+		PMV_PATA_Command_Header header = NULL;
+		header = PATA_GetCommandHeader(pPort, tag);
+
+		if (consumed == 0) {
+			/* resource not enough... */
+			MV_DPRINT(("Run out of PRD entry.\n"));
+			if( pReq->Req_Flag & REQ_FLAG_CONSOLIDATE )
+			{
+				pReq->Scsi_Status = REQ_STATUS_BUSY;
+				Tag_ReleaseOne(&pPort->Tag_Pool, tag);
+				return;
+			}
+			else
+			{
+				/* check why upper layer send request with too many sg items... */
+				MV_DASSERT( MV_FALSE );
+			}
+		}
+		header->PRD_Entry_Count = CPU_TO_LE_16(consumed);
+#else
+		MV_U8 i;
+		PMV_SG_Entry pSGEntry = NULL;
+
+		/* "Transfer Byte Count" in AHCI and 614x PRD table is zero based. */
+		for ( i=0; i<pSGTable->Valid_Entry_Count; i++ )
+		{
+			pSGEntry = &pCmdTable->PRD_Entry[i];
+			pSGEntry->Base_Address = CPU_TO_LE_32(pSGTable->Entry_Ptr[i].Base_Address);
+			pSGEntry->Base_Address_High = CPU_TO_LE_32(pSGTable->Entry_Ptr[i].Base_Address_High);
+			pSGEntry->Size = CPU_TO_LE_32(pSGTable->Entry_Ptr[i].Size-1);
+		}
+#endif
+	}
+	else
+	{	
+		MV_DASSERT( !SCSI_IS_READ(pReq->Cdb[0]) && !SCSI_IS_WRITE(pReq->Cdb[0]) );
+	}
+
+}
+
+void SATA_SendFrame(PDomain_Port pPort, PMV_Request pReq, MV_U8 tag)
+{
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	#ifdef SUPPORT_ATA_SECURITY_CMD
+	PDomain_Device pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+	#endif
+	MV_DASSERT( (pPort->Running_Slot&(1<<tag))==0 );
+	MV_DASSERT( pPort->Running_Req[tag]==0 );
+	MV_DASSERT( (MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE)&(1<<tag))==0 );
+	MV_DASSERT( (MV_REG_READ_DWORD(portMmio, PORT_SCR_ACT)&(1<<tag))==0 );
+
+	mv_core_set_running_slot(pPort, tag, pReq);
+	#ifdef SUPPORT_ATA_SECURITY_CMD
+	if ( pReq->Cmd_Flag&CMD_FLAG_NCQ && !((pDevice->Setting&DEVICE_SETTING_SECURITY_LOCKED)==0x10) )
+	#else
+	if ( pReq->Cmd_Flag&CMD_FLAG_NCQ)
+	#endif
+		pPort->Setting |= PORT_SETTING_NCQ_RUNNING;
+	else
+		pPort->Setting &= ~PORT_SETTING_NCQ_RUNNING;
+
+	if ( pReq->Scsi_Status==REQ_STATUS_RETRY )
+	{
+		MV_DPRINT(("Retry request[0x%p] on port[%d]\n",pReq, pPort->Id));
+		MV_DumpRequest(pReq, MV_FALSE);
+		pPort->Setting |= PORT_SETTING_DURING_RETRY;
+	}
+	else
+	{
+		pPort->Setting &= ~PORT_SETTING_DURING_RETRY;
+	}
+
+	if ( pPort->Setting&PORT_SETTING_NCQ_RUNNING )
+	{
+		MV_REG_WRITE_DWORD(portMmio, PORT_SCR_ACT, 1<<tag);
+		MV_REG_READ_DWORD(portMmio, PORT_SCR_ACT);	/* flush */
+	}
+
+	MV_REG_WRITE_DWORD(portMmio, PORT_CMD_ISSUE, 1<<tag);
+	MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE);	/* flush */
+}
+
+MV_BOOLEAN Core_WaitingForIdle(MV_PVOID pExtension)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pExtension;
+	PDomain_Port pPort = NULL;
+	MV_U8 i;
+
+	for ( i=0; i<pCore->Port_Num; i++ )
+	{
+		pPort = &pCore->Ports[i];
+
+		if ( pPort->Running_Slot!=0 )
+			return MV_FALSE;
+	}
+	
+	return MV_TRUE;
+}
+
+MV_BOOLEAN ResetController(PCore_Driver_Extension pCore);
+
+void Core_ResetHardware(MV_PVOID pExtension)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pExtension;
+	MV_U32 i, j;
+	PDomain_Port pPort = NULL;
+	PDomain_Device pDevice = NULL;
+
+	/* Re-initialize some variables to make the reset go. */
+	pCore->Adapter_State = ADAPTER_INITIALIZING;
+	for ( i=0; i<MAX_PORT_NUMBER; i++ )
+	{
+		pPort = &pCore->Ports[i];
+		pPort->Port_State = PORT_STATE_IDLE;
+		for ( j=0; j<MAX_DEVICE_PER_PORT; j++ )
+		{
+			pDevice = &pPort->Device[j];
+			pDevice->State = DEVICE_STATE_IDLE;
+		}
+	}
+
+	/* Go through the mvAdapterStateMachine. */
+	if( pCore->Resetting==0 )
+	{
+		pCore->Resetting = 1;
+		if( !mvAdapterStateMachine(pCore,NULL) )
+		{
+			MV_ASSERT(MV_FALSE);	
+		}
+	}
+	else
+	{
+		/* I suppose that we only have one chance to call Core_ResetHardware. */
+		MV_DASSERT(MV_FALSE);
+	}
+	
+	return;
+}
+
+void PATA_LegacyPollSenseData(PCore_Driver_Extension pCore, PMV_Request pReq)
+{
+	/* 
+	 * This sense data says:
+	 * Format: Fixed format sense data
+	 * Sense key: Hardware error
+	 * Sense code and qualifier: 08h 03h LOGICAL UNIT COMMUNICATION CRC ERROR
+	 */
+	MV_U8 fakeSense[]={0xF0, 0x00, 0x04, 0x00, 0x00, 0x01, 
+		0xEA, 0x0A, 0x74, 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00};
+	MV_U32 size = MV_MIN(sizeof(fakeSense)/sizeof(MV_U8), pReq->Sense_Info_Buffer_Length);
+
+	MV_CopyMemory(pReq->Sense_Info_Buffer, fakeSense, size);
+
+}
+
+
+void Core_FillSenseData(PMV_Request pReq, MV_U8 senseKey, MV_U8 adSenseCode)
+{
+	if (pReq->Sense_Info_Buffer != NULL) {
+		((MV_PU8)pReq->Sense_Info_Buffer)[0] = 0x70;	/* Current */
+		((MV_PU8)pReq->Sense_Info_Buffer)[2] = senseKey;
+		((MV_PU8)pReq->Sense_Info_Buffer)[7] = 0;		/* additional sense length */
+		((MV_PU8)pReq->Sense_Info_Buffer)[12] = adSenseCode;	/* additional sense code */
+	}
+}
+
+
+void mvScsiInquiry(PCore_Driver_Extension pCore, PMV_Request pReq)
+{
+#ifndef _OS_BIOS
+	PDomain_Device pDevice = NULL;
+	MV_U8 portId, deviceId;
+
+	portId = PATA_MapPortId(pReq->Device_Id);
+	deviceId = PATA_MapDeviceId(pReq->Device_Id);
+	if ( (portId>=MAX_PORT_NUMBER)||(pReq->Device_Id >= MAX_DEVICE_NUMBER) ) {
+		pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+		return;
+	}
+	pDevice = &pCore->Ports[portId].Device[deviceId];
+	if ( (pDevice->Status & DEVICE_STATUS_FUNCTIONAL) == 0) {
+		/* Device is not functional */
+		pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+		return;
+	}
+
+	MV_ZeroMemory(pReq->Data_Buffer, pReq->Data_Transfer_Length);
+
+	if ( pReq->Cdb[1] & CDB_INQUIRY_EVPD )
+	{
+		MV_U8 MV_INQUIRY_VPD_PAGE0_DATA[6] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x80};
+		MV_U8 MV_INQUIRY_VPD_PAGE83_DATA[16] = {
+			0x00, 0x83, 0x00, 0x0C, 0x01, 0x02, 0x00, 0x08,
+			0x00, 0x50, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00};
+		MV_U32 tmpLen = 0;
+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+
+		/* Shall return the specific page of Vital Production Data */
+		switch (pReq->Cdb[2]) {
+		case 0x00:	/* Supported VPD pages */
+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, 6);
+			MV_CopyMemory(pReq->Data_Buffer, MV_INQUIRY_VPD_PAGE0_DATA, tmpLen);
+			break;
+		case 0x80:	/* Unit Serial Number VPD Page */
+			if (pReq->Data_Transfer_Length > 1)
+				*(((MV_PU8)(pReq->Data_Buffer)) + 1) = 0x80;
+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, 4);
+			if (tmpLen >= 4) {
+				tmpLen = MV_MIN((pReq->Data_Transfer_Length-4), 20);
+				MV_CopyMemory(((MV_PU8)(pReq->Data_Buffer)+4), pDevice->Serial_Number, tmpLen);
+				*(((MV_PU8)(pReq->Data_Buffer)) + 3) = (MV_U8)tmpLen;
+				tmpLen += 4;
+			}
+			break;
+		case 0x83:	/* Device Identification VPD Page */
+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, 16);
+			MV_CopyMemory(pReq->Data_Buffer, MV_INQUIRY_VPD_PAGE83_DATA, tmpLen);
+			break;
+		default:
+			pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;
+			Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);
+			break;
+		}
+		pReq->Data_Transfer_Length = tmpLen;
+	} 
+	else
+	{
+		/* Standard inquiry */
+		if (pReq->Cdb[2]!=0) {
+			/* PAGE CODE field must be zero when EVPD is zero for a valid request */
+			/* sense key as ILLEGAL REQUEST and additional sense code as INVALID FIELD IN CDB */
+			pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;
+			Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);
+			return;
+		}
+		else {
+			MV_U8 Vendor[9],Product[24], temp[24];
+			MV_U8 buff[42];
+			MV_U32 i, inquiryLen = 42;
+
+			MV_ZeroMemory(buff, inquiryLen);
+
+			buff[0] = (pDevice->Device_Type&DEVICE_TYPE_ATAPI)?0x5 : 0;
+			buff[1] = (pDevice->Device_Type&DEVICE_TYPE_ATAPI)?MV_BIT(7) : 0;    /* Not Removable disk */
+			buff[2] = 0x05;    /*claim conformance to SPC-3*/
+			buff[3] = 0x12;    /* set RESPONSE DATA FORMAT to 2*/
+			buff[4] = 42 - 5;
+			buff[6] = 0x0;     /* tagged queuing*/
+			buff[7] = 0X13;	
+
+			MV_CopyMemory(temp, pDevice->Model_Number, 24);
+			for (i = 0; i < 9; i++)	{
+				if (temp[i] == ' ')
+					break;
+			}
+			if (i == 9)	{
+				if (((temp[0] == 'I') && (temp[1] == 'C')) ||
+					((temp[0] == 'H') && (temp[1] == 'T')) ||
+					((temp[0] == 'H') && (temp[1] == 'D')) ||
+					((temp[0] == 'D') && (temp[1] == 'K')))
+				{ /*Hitachi*/
+					Vendor[0] = 'H';
+					Vendor[1] = 'i';
+					Vendor[2] = 't';
+					Vendor[3] = 'a';
+					Vendor[4] = 'c';
+					Vendor[5] = 'h';
+					Vendor[6] = 'i';
+					Vendor[7] = ' ';
+					Vendor[8] = '\0';
+				}
+				else if ((temp[0] == 'S') && (temp[1] == 'T'))
+				{
+					/*Seagate*/
+					Vendor[0] = 'S';
+					Vendor[1] = 'e';
+					Vendor[2] = 'a';
+					Vendor[3] = 'g';
+					Vendor[4] = 'a';
+					Vendor[5] = 't';
+					Vendor[6] = 'e';
+					Vendor[7] = ' ';
+					Vendor[8] = '\0';
+				}
+				else
+				{
+					/*Unkown*/
+					Vendor[0] = 'A';
+					Vendor[1] = 'T';
+					Vendor[2] = 'A';
+					Vendor[3] = ' ';
+					Vendor[4] = ' ';
+					Vendor[5] = ' ';
+					Vendor[6] = ' ';
+					Vendor[7] = ' ';
+					Vendor[8] = '\0';
+				}
+				MV_CopyMemory(Product, temp, 16);
+				Product[16] = '\0';
+			}
+			else {		/* i < 9 */
+				MV_U32 j = i;
+				MV_CopyMemory(Vendor, temp, j);
+				for (; j < 9; j++)
+					Vendor[j] = ' ';
+				Vendor[8] = '\0';
+				for (; i < 24; i++)	{
+					if (temp[i] != ' ')
+						break;
+				}
+				MV_CopyMemory(Product, &temp[i], 24 - i);
+				Product[16] = '\0';
+			}
+
+			MV_CopyMemory(&buff[8], Vendor, 8);
+			MV_CopyMemory(&buff[16], Product, 16);
+			MV_CopyMemory(&buff[32], pDevice->Firmware_Revision, 4);
+			MV_CopyMemory(&buff[36], "MVSATA", 6);	
+			
+			/*if pReq->Data_Transfer_Length <=36 ,buff[36]+ data miss*/
+			MV_CopyMemory( pReq->Data_Buffer, 
+							buff, 
+							MV_MIN(pReq->Data_Transfer_Length, inquiryLen));
+			pReq->Data_Transfer_Length =  MV_MIN(pReq->Data_Transfer_Length, inquiryLen);
+			pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+		}
+	}
+#endif	/* #ifndef _OS_BIOS */
+}
+
+void mvScsiReportLun(PCore_Driver_Extension pCore, PMV_Request pReq)
+{
+	MV_U32 allocLen, lunListLen;
+	MV_PU8 pBuf = pReq->Data_Buffer;
+
+	allocLen = ((MV_U32)(pReq->Cdb[6] << 24)) |
+			   ((MV_U32)(pReq->Cdb[7] << 16)) |
+			   ((MV_U32)(pReq->Cdb[8] << 8)) |
+			   ((MV_U32)(pReq->Cdb[9]));
+
+	/* allocation length should not less than 16 bytes */
+	if (allocLen < 16) {
+		pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;
+		Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);
+		return;
+	}
+
+	MV_ZeroMemory(pBuf, pReq->Data_Transfer_Length);
+	/* Only LUN 0 has device */
+	lunListLen = 8;
+	pBuf[0] = (MV_U8)((lunListLen & 0xFF000000) >> 24);
+	pBuf[1] = (MV_U8)((lunListLen & 0x00FF0000) >> 16);
+	pBuf[2] = (MV_U8)((lunListLen & 0x0000FF00) >> 8);
+	pBuf[3] = (MV_U8)(lunListLen & 0x000000FF);
+	pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+}
+
+void mvScsiReadCapacity(PCore_Driver_Extension pCore, PMV_Request pReq)
+{
+	PDomain_Device pDevice = NULL;
+	MV_LBA maxLBA;
+	MV_U32 blockLength;
+	MV_PU32 pU32Buffer;
+	MV_U8 portId, deviceId;
+
+	portId = PATA_MapPortId(pReq->Device_Id);
+	deviceId = PATA_MapDeviceId(pReq->Device_Id);
+#ifndef SECTOR_SIZE
+	#define SECTOR_SIZE	512	
+#endif
+
+	MV_DASSERT( portId < MAX_PORT_NUMBER );
+
+	if ((pReq->Cdb[8] & MV_BIT(1)) == 0)
+	{
+		if ( pReq->Cdb[2] || pReq->Cdb[3] || pReq->Cdb[4] || pReq->Cdb[5] )
+		{
+			pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST;
+			return;
+		}
+	}
+
+	/* 
+	 * The disk size as indicated by the ATA spec is the total addressable
+	 * sectors on the drive ; while the SCSI translation of the command
+	 * should be the last addressable sector.
+	 */
+	pDevice = &pCore->Ports[portId].Device[deviceId];
+//	maxLBA.value = pDevice->Max_LBA.value-1;
+	maxLBA = pDevice->Max_LBA;
+	blockLength = SECTOR_SIZE;			
+	pU32Buffer = (MV_PU32)pReq->Data_Buffer;
+
+	if (maxLBA.parts.high != 0)
+		maxLBA.parts.low = 0xFFFFFFFF;
+
+	pU32Buffer[0] = CPU_TO_BIG_ENDIAN_32(maxLBA.parts.low);
+	pU32Buffer[1] = CPU_TO_BIG_ENDIAN_32(blockLength);
+
+	pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+}
+
+void mvScsiReadCapacity_16(PCore_Driver_Extension pCore, PMV_Request pReq)
+{
+	PDomain_Device pDevice = NULL;
+	MV_U32 blockLength;
+	MV_PU32 pU32Buffer;
+	MV_U8 portId, deviceId;
+	MV_LBA maxLBA;
+	
+	portId = PATA_MapPortId(pReq->Device_Id);
+	deviceId = PATA_MapDeviceId(pReq->Device_Id);
+#ifndef SECTOR_SIZE
+	#define SECTOR_SIZE	512	
+#endif
+	MV_DASSERT( portId < MAX_PORT_NUMBER );
+
+	pDevice = &pCore->Ports[portId].Device[deviceId];		
+	//maxLBA.value = pDevice->Max_LBA.value-1;;
+	maxLBA = pDevice->Max_LBA;
+	blockLength = SECTOR_SIZE;
+	pU32Buffer = (MV_PU32)pReq->Data_Buffer;
+	pU32Buffer[0] = CPU_TO_BIG_ENDIAN_32(maxLBA.parts.high);
+	pU32Buffer[1] = CPU_TO_BIG_ENDIAN_32(maxLBA.parts.low);
+	pU32Buffer[2] =  CPU_TO_BIG_ENDIAN_32(blockLength);
+	pReq->Scsi_Status = REQ_STATUS_SUCCESS;;
+}
+
+void Port_Monitor(PDomain_Port pPort);
+#if defined(SUPPORT_ERROR_HANDLING)
+
+MV_BOOLEAN Core_IsInternalRequest(PCore_Driver_Extension pCore, PMV_Request pReq)
+{
+	PDomain_Device pDevice;
+	MV_U8 portId = PATA_MapPortId(pReq->Device_Id);
+	MV_U8 deviceId = PATA_MapDeviceId(pReq->Device_Id);
+
+	if ( portId>=MAX_PORT_NUMBER )
+		return MV_FALSE;
+	if ( deviceId>=MAX_DEVICE_PER_PORT )
+		return MV_FALSE;
+
+	pDevice = &pCore->Ports[portId].Device[deviceId];
+	if ( pReq==pDevice->Internal_Req ) 
+		return MV_TRUE;
+	else
+		return MV_FALSE;
+}
+
+void Core_ResetChannel_BH(MV_PVOID ext);
+
+void Core_ResetChannel(MV_PVOID Device, MV_PVOID temp)
+{
+	PDomain_Device pDevice = (PDomain_Device)Device;
+	PDomain_Port pPort = pDevice->PPort;
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PMV_Request pReq;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 tmp;
+	MV_U16 i;
+	
+	//mv_core_dump_reg(pPort);
+#ifdef SUPPORT_EVENT
+	core_generate_event(pCore, EVT_ID_HD_TIMEOUT, pDevice->Id, SEVERITY_WARNING, 0, NULL);
+#endif
+
+	if (pPort->Type==PORT_TYPE_PATA){
+		tmp = MV_REG_READ_DWORD( portMmio, PORT_CMD_ISSUE );
+		MV_PRINT("CI = 0x%x\n", tmp);
+	}
+	Port_Monitor( pPort );
+
+	/* toggle the start bit in cmd register */
+	tmp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp & ~MV_BIT(0));
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp | MV_BIT(0));
+	HBA_SleepMillisecond( pCore, 100 );
+	pPort->timer_para = pDevice;
+#ifdef COMMAND_ISSUE_WORKROUND
+	if((MV_REG_READ_DWORD( portMmio, PORT_CMD ) & PORT_CMD_LIST_ON) || (pDevice->Reset_Count > CORE_MAX_RESET_COUNT))
+	{
+		pPort->Hot_Plug_Timer = 0;
+		pPort->command_callback = Core_ResetChannel_BH;
+		pPort->error_state = PORT_ERROR_AT_RUNTIME;
+		pCore->Total_Device_Count--;
+		mv_core_reset_command(pPort);
+		return;
+	}
+//	mv_core_init_reset_para(pPort);
+//	pPort->timer_para = pDevice;
+#endif
+
+	Core_ResetChannel_BH(pPort);
+
+}
+void Core_ResetChannel_BH(MV_PVOID ext)
+{
+
+	PDomain_Port pPort = (PDomain_Port)ext;
+	PDomain_Device pDevice = (PDomain_Device)pPort->timer_para;
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PMV_Request pReq;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 tmp;
+	MV_U16 i;
+	pPort->timer_para = NULL;
+	pDevice->Reset_Count++;
+
+	mv_core_put_back_request(pPort);
+	
+	if ( pPort->Type == PORT_TYPE_PATA )
+		PATA_PortReset( pPort, MV_TRUE );
+	else
+		SATA_PortReset( pPort, MV_TRUE );
+	MV_DPRINT(("Finshed Core_ResetChannel_BH on port[%d].\n",pPort->Id));
+	//mv_core_init_reset_para(pPort);
+	Core_HandleWaitingList(pCore);
+}
+#endif /* SUPPORT_ERROR_HANDLING || _OS_LINUX */
+
+#define IS_SOFT_RESET_REQ(pReq) \
+	((pReq->Cdb[0]==SCSI_CMD_MARVELL_SPECIFIC)&& \
+	 (pReq->Cdb[1]==CDB_CORE_MODULE)&& \
+	 (pReq->Cdb[2]==CDB_CORE_SOFT_RESET_1 || pReq->Cdb[2]==CDB_CORE_SOFT_RESET_0))
+
+MV_BOOLEAN HandleInstantRequest(PCore_Driver_Extension pCore, PMV_Request pReq)
+{
+	/* 
+	 * Some of the requests can be returned immediately without hardware 
+	 * access. 
+	 * Handle Inquiry and Read Capacity.
+	 * If return MV_TRUE, means the request can be returned to OS now.
+	 */
+	PDomain_Device pDevice = NULL;
+	MV_U8 portId, deviceId;
+	MV_U8 ret;
+	if(IS_SOFT_RESET_REQ(pReq))
+		return MV_FALSE;
+	
+#ifdef _OS_LINUX
+	if(!__is_scsi_cmd_simulated(pReq->Cdb[0])
+#ifdef SUPPORT_ATA_POWER_MANAGEMENT
+	&& !IS_ATA_PASS_THROUGH_COMMAND(pReq)
+#endif
+	)
+		return	MV_FALSE;
+#endif
+	if ( pReq->Device_Id != VIRTUAL_DEVICE_ID )
+	{
+		portId = PATA_MapPortId(pReq->Device_Id);
+		deviceId = PATA_MapDeviceId(pReq->Device_Id);
+		if ( portId < MAX_PORT_NUMBER )				
+			pDevice = &pCore->Ports[portId].Device[deviceId];
+	}
+
+	if (pReq->Cdb[0] == SCSI_CMD_MARVELL_SPECIFIC && pReq->Cdb[1] == CDB_CORE_MODULE)
+	{
+		if (pReq->Cdb[2] == CDB_CORE_RESET_DEVICE)
+		{
+			Core_ResetChannel(pDevice,NULL);
+			return MV_TRUE;
+		}
+	}
+
+	if (pDevice && 
+	    (pDevice->Device_Type & DEVICE_TYPE_ATAPI) &&
+	    (pDevice->Status & DEVICE_STATUS_FUNCTIONAL))
+	{
+		return MV_FALSE;
+	}
+
+	ret=MV_TRUE;
+#ifdef _OS_LINUX
+	hba_map_sg_to_buffer(pReq);
+#endif /* _OS_LINUX */
+	switch ( pReq->Cdb[0] )
+	{
+	case SCSI_CMD_INQUIRY:
+		mvScsiInquiry(pCore, pReq);
+		break;
+	case SCSI_CMD_MODE_SENSE_6:
+	case SCSI_CMD_MODE_SENSE_10:
+		mvScsiModeSense(pCore, pReq);
+		break;
+	case SCSI_CMD_REPORT_LUN:
+		mvScsiReportLun(pCore, pReq);
+		break;
+	case SCSI_CMD_READ_CAPACITY_10:
+		mvScsiReadCapacity(pCore, pReq);
+		break;
+#ifdef _OS_LINUX
+	case SCSI_CMD_READ_CAPACITY_16: /* 0x9e SERVICE_ACTION_IN */
+		if ((pReq->Cdb[1] & 0x1f)==SCSI_CMD_SAI_READ_CAPACITY_16 /* SAI_READ_CAPACITY_16 */) {
+			mvScsiReadCapacity_16(pCore, pReq);
+		}
+		else
+			pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST;
+		break;
+#endif /* _OS_LINUX */
+#ifdef SUPPORT_ATA_SMART
+	case SCSI_CMD_MODE_SELECT_6:
+	case SCSI_CMD_MODE_SELECT_10:
+		ret = mvScsiModeSelect(pCore, pReq);
+		break;
+	case SCSI_CMD_LOG_SENSE:
+		mvScsiLogSenseTranslation( pCore, pReq);
+		break;
+	case SCSI_CMD_READ_DEFECT_DATA_10:
+		mvScsiReadDefectData(pCore, pReq);
+		break;
+	case SCSI_CMD_FORMAT_UNIT:
+		pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;
+		Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);
+		break;
+#endif
+	case SCSI_CMD_REQUEST_SENSE:	/* This is only for Thor hard disk */
+	case SCSI_CMD_TEST_UNIT_READY:
+	case SCSI_CMD_RESERVE_6:	/* For Thor, just return good status */
+	case SCSI_CMD_RELEASE_6:
+#ifdef CORE_IGNORE_START_STOP_UNIT
+	case SCSI_CMD_START_STOP_UNIT:
+#endif
+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+		break;
+#ifdef CORE_SUPPORT_API
+	case APICDB0_PD:
+		ret=Core_pd_command(pCore, pReq);
+		break;
+#endif /* CORE_SUPPORT_API */
+	default:
+		ret = MV_FALSE;
+	}
+#ifdef _OS_LINUX
+	hba_unmap_sg_to_buffer(pReq);
+#endif /* _OS_LINUX */
+
+	return ret;
+}
+#ifdef SUPPORT_ATA_SECURITY_CMD
+void scsi_ata_check_condition(MV_Request *req, MV_U8 sense_key,
+		MV_U8 sense_code, MV_U8 sense_qualifier)
+	{
+		 req->Scsi_Status = REQ_STATUS_HAS_SENSE;
+		 if (req->Sense_Info_Buffer) {
+			 ((MV_PU8)req->Sense_Info_Buffer)[0] = 0x70; /* As SPC-4, set Response Code 
+	to 70h, or SCSI layer didn't know to set down error disk */
+			((MV_PU8)req->Sense_Info_Buffer)[2] = sense_key;
+			/* additional sense length */
+			((MV_PU8)req->Sense_Info_Buffer)[7] = 0;
+			/* additional sense code */
+			((MV_PU8)req->Sense_Info_Buffer)[12] = sense_code;
+			/* additional sense code qualifier*/
+			((MV_PU8)req->Sense_Info_Buffer)[13] = sense_qualifier;
+		 }
+	}
+u8 mv_ata_pass_through(IN PDomain_Device pDevice,IN PMV_Request req){
+
+	MV_U8 protocol, t_length, t_dir, byte, multi_rw, command;
+	MV_U32 length, tx_length = 0, cmd_flag =0;
+	MV_PU8 buf_ptr;
+
+	protocol = (req->Cdb[1] >> 1) & 0x0F;
+	if(protocol== ATA_PROTOCOL_HARD_RESET || protocol==ATA_PROTOCOL_SRST){
+		printk("ATA_16:don't support protocol=0x%x\n",protocol);
+		scsi_ata_check_condition(req, SCSI_SK_ILLEGAL_REQUEST,
+			SCSI_ASC_INVALID_FEILD_IN_CDB, 0);
+			return MV_QUEUE_COMMAND_RESULT_FINISHED;
+		}
+	multi_rw = (req->Cdb[1] >> 5) & 0x7;
+	t_length = req->Cdb[2] & 0x3;
+	byte = (req->Cdb[2] >> 2) & 0x01;
+	t_dir = (req->Cdb[2] >> 3) & 0x1;
+
+	/* Fix hdparm -A for readahead status, set sect_num */
+	if (req->Cdb[0] == ATA_12) {
+		command = req->Cdb[9];
+		if (command == ATA_CMD_IDENTIFY_ATA && req->Cdb[4] == 0)
+		req->Cdb[4] = 1;
+	} else {
+		command = req->Cdb[14];
+		if (req->Cdb[1] & 0x01)
+			cmd_flag |= CMD_FLAG_48BIT;
+		if (command == ATA_CMD_IDENTIFY_ATA && req->Cdb[6] == 0)
+			req->Cdb[6] = 1;
+	}
+	
+	if (multi_rw != 0 && !IS_ATA_MULTIPLE_READ_WRITE(command)) {
+			scsi_ata_check_condition(req, SCSI_SK_ILLEGAL_REQUEST,
+			SCSI_ASC_INVALID_FEILD_IN_CDB, 0);
+			return MV_QUEUE_COMMAND_RESULT_FINISHED;
+		}
+	
+		if (t_length == 0)
+			cmd_flag |= CMD_FLAG_NON_DATA;
+		else {
+			if (t_dir == 0)
+				cmd_flag |= CMD_FLAG_DATA_OUT;
+			else
+				cmd_flag |= CMD_FLAG_DATA_IN;
+		}
+	
+		/* Transfer length in bytes */
+		if (byte == 0) {
+			/* Transfer length defined in Features */
+			if (t_length == 0x1) {
+				if (req->Cdb[0] == ATA_12)
+					tx_length = req->Cdb[3];
+				else
+					tx_length = req->Cdb[4];
+			}
+			/* Transfer length defined in Sector Count */
+			else if (t_length == 0x2) {
+				if (req->Cdb[0] == ATA_12)
+					tx_length = req->Cdb[4];
+				else
+					tx_length = req->Cdb[6];
+			}
+			/* t_length == 0x3 means use the length defined in the
+			nexus transaction */
+			else {
+				tx_length = req->Data_Transfer_Length;
+			}
+			/* Transfer length in sectors */
+		} else {
+			/* Transfer length defined in Features */
+			if (t_length == 0x1) {
+				if (req->Cdb[0] == ATA_12)
+					tx_length = req->Cdb[3] * 512; // fixed jyli
+				else
+					tx_length = req->Cdb[4] * 512; // fixed jyli
+			}
+			/* Transfer length defined in Sector Count */
+			else if (t_length == 0x2) {
+				if (req->Cdb[0] == ATA_12)
+					tx_length = req->Cdb[4] * 512; // fixed jyli
+				else
+					tx_length = req->Cdb[6] * 512; // fixed jyli
+			}
+			/* t_length == 0x3 means use the length defined in the
+			nexus transaction */
+			else {
+				
+				tx_length = req->Data_Transfer_Length;
+			}
+		}
+	switch (protocol) {
+	case ATA_PROTOCOL_NON_DATA:
+		if (t_length != 0) {
+			scsi_ata_check_condition(req, SCSI_SK_ILLEGAL_REQUEST,
+			SCSI_ASC_INVALID_FEILD_IN_CDB, 0);
+			return MV_QUEUE_COMMAND_RESULT_FINISHED;
+		}
+
+		break;
+
+	case ATA_PROTOCOL_PIO_IN:
+		if (!(cmd_flag & CMD_FLAG_DATA_IN)) {
+			scsi_ata_check_condition(req, SCSI_SK_ILLEGAL_REQUEST,
+			SCSI_ASC_INVALID_FEILD_IN_CDB, 0);
+			return MV_QUEUE_COMMAND_RESULT_FINISHED;
+		}
+
+		cmd_flag |= CMD_FLAG_PIO;
+		break;
+
+	case ATA_PROTOCOL_PIO_OUT:
+		if (!(cmd_flag & CMD_FLAG_DATA_OUT)) {
+			scsi_ata_check_condition(req, SCSI_SK_ILLEGAL_REQUEST,
+			        SCSI_ASC_INVALID_FEILD_IN_CDB, 0);
+			return MV_QUEUE_COMMAND_RESULT_FINISHED;
+		}
+
+		cmd_flag |= CMD_FLAG_PIO;
+		break;
+
+	case ATA_PROTOCOL_DMA:
+		cmd_flag |= CMD_FLAG_DMA;
+		break;
+	case ATA_PROTOCOL_DMA_QUEUED:
+		cmd_flag |= (CMD_FLAG_DMA | CMD_FLAG_TCQ);
+		break;
+
+	case ATA_PROTOCOL_DEVICE_DIAG:
+	case ATA_PROTOCOL_DEVICE_RESET:
+		/* Do nothing(?) */
+		break;
+
+	case ATA_PROTOCOL_UDMA_IN:
+		if (!(cmd_flag & CMD_FLAG_DATA_IN)) {
+			scsi_ata_check_condition(req, SCSI_SK_ILLEGAL_REQUEST,
+			SCSI_ASC_INVALID_FEILD_IN_CDB, 0);
+			return MV_QUEUE_COMMAND_RESULT_FINISHED;
+		}
+		cmd_flag |= CMD_FLAG_DMA;
+		break;
+
+	case ATA_PROTOCOL_UDMA_OUT:
+		if (!(cmd_flag & CMD_FLAG_DATA_OUT)) {
+			scsi_ata_check_condition(req, SCSI_SK_ILLEGAL_REQUEST,
+			SCSI_ASC_INVALID_FEILD_IN_CDB, 0);
+			return MV_QUEUE_COMMAND_RESULT_FINISHED;
+		}
+		cmd_flag |= CMD_FLAG_DMA;
+		break;
+
+	case ATA_PROTOCOL_FPDMA:
+		cmd_flag |= (CMD_FLAG_DMA | CMD_FLAG_NCQ);
+		break;
+
+	case ATA_PROTOCOL_RTN_INFO:
+		req->Scsi_Status = REQ_STATUS_SUCCESS;
+		return MV_QUEUE_COMMAND_RESULT_FINISHED;
+
+	default:
+		scsi_ata_check_condition(req, SCSI_SK_ILLEGAL_REQUEST,
+		SCSI_ASC_INVALID_FEILD_IN_CDB, 0);
+
+		return MV_QUEUE_COMMAND_RESULT_FINISHED;
+	}
+	 req->Cmd_Flag=cmd_flag;
+	return 1;
+}
+#endif
+MV_QUEUE_COMMAND_RESULT
+PrepareAndSendCommand(
+	IN PCore_Driver_Extension pCore,
+	IN PMV_Request pReq
+	)
+{
+	PDomain_Device pDevice = NULL;
+	PDomain_Port pPort = NULL;
+	MV_BOOLEAN isPATA = MV_FALSE;
+	MV_U8 i, tag;
+//	MV_U8 count=0;
+	ATA_TaskFile taskFile;
+	MV_BOOLEAN ret;
+
+	/* Associate this request to the corresponding device and port */
+	pDevice = &pCore->Ports[PATA_MapPortId(pReq->Device_Id)].Device[PATA_MapDeviceId(pReq->Device_Id)];
+	pPort = pDevice->PPort;
+
+	if ( !(pDevice->Status&DEVICE_STATUS_FUNCTIONAL) )
+	{
+		pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+		return MV_QUEUE_COMMAND_RESULT_FINISHED;
+	}
+
+	/* Set the Cmd_Flag to indicate which type of commmand it is. */
+	if ( !Category_CDB_Type(pDevice, pReq) )
+	{
+		pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST;
+		/* Invalid request and can be returned to OS now. */
+		return MV_QUEUE_COMMAND_RESULT_FINISHED;
+	} 
+#ifdef SUPPORT_ATA_SECURITY_CMD
+	else if(pReq->Cdb[0]==ATA_16)
+		{
+			ret=mv_ata_pass_through(pDevice,pReq);
+			if(ret==MV_QUEUE_COMMAND_RESULT_FINISHED)
+				return MV_QUEUE_COMMAND_RESULT_FINISHED;
+		}
+#endif
+	MV_DASSERT( pPort!=NULL );
+	if ( pPort->Running_Slot!=0 )	/* Some requests are running. */
+	{
+
+#ifdef COMMAND_ISSUE_WORKROUND
+		if(mv_core_check_is_reseeting(pCore)){
+			MV_DPRINT(("HBA is resetting, wait...\n"));
+			MV_DumpRequest(pReq, 0);
+			return MV_QUEUE_COMMAND_RESULT_FULL;
+		}
+#endif
+
+		if ((pDevice->Outstanding_Req >= MAX_SLOT_NUMBER - 2)
+			|| (pPort->Running_Slot == 0xFFFFFFFFL)){
+			MV_DPRINT(("running slot[0x%x], req=%d is full.\n",pPort->Running_Slot, pDevice->Outstanding_Req));
+			return MV_QUEUE_COMMAND_RESULT_FULL;
+		}
+		
+		if (pReq->Cmd_Flag & CMD_FLAG_SMART)
+			return MV_QUEUE_COMMAND_RESULT_FULL;
+		
+		if (	( (pReq->Cmd_Flag&CMD_FLAG_NCQ) && !(pPort->Setting&PORT_SETTING_NCQ_RUNNING) )
+				||  ( !(pReq->Cmd_Flag&CMD_FLAG_NCQ) && (pPort->Setting&PORT_SETTING_NCQ_RUNNING) )
+				|| (pReq->Scsi_Status==REQ_STATUS_RETRY)
+				|| (pPort->Setting&PORT_SETTING_DURING_RETRY)
+			)
+		{
+			return MV_QUEUE_COMMAND_RESULT_FULL;			
+		}
+	
+		if((pReq->Cmd_Flag&CMD_FLAG_NCQ)&&(pPort->Setting&PORT_SETTING_NCQ_RUNNING)&&(pPort->Running_Slot==0xffffffffL))
+		{
+			MV_PRINT("NCQ TAG is run out\n");
+			return MV_QUEUE_COMMAND_RESULT_FULL;			
+		}
+	
+		if((!(pReq->Cmd_Flag&CMD_FLAG_NCQ))&&(!(pPort->Setting&PORT_SETTING_NCQ_RUNNING))&&(pPort->Running_Slot==0xffffffffL))
+		{
+			MV_PRINT("DMA TAG is run out\n");
+			return MV_QUEUE_COMMAND_RESULT_FULL;
+		}
+
+		
+		/* In order for request sense to immediately follow the error request. */
+		if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+			return MV_QUEUE_COMMAND_RESULT_FULL;
+
+		if ((pPort->Type==PORT_TYPE_PATA)&&
+			(pPort->Port_State==PORT_STATE_INIT_DONE)){			
+			for (i=0; i<2; i++){
+				if ((&pPort->Device[i]!=pDevice)&& //check the other device				
+				    (pPort->Device[i].Device_Type&DEVICE_TYPE_ATAPI)&&
+				    (pPort->Device[i].Status & DEVICE_STATUS_FUNCTIONAL)){					
+						return MV_QUEUE_COMMAND_RESULT_FULL;
+				}
+			}//end of for	
+		}
+		
+		/* One request at a time */
+		if ( (pReq->Scsi_Status==REQ_STATUS_RETRY)
+			|| (pPort->Setting&PORT_SETTING_DURING_RETRY) 
+			)
+			return MV_QUEUE_COMMAND_RESULT_FULL;
+	}
+
+	if ( Tag_IsEmpty(&pPort->Tag_Pool) )
+		return MV_QUEUE_COMMAND_RESULT_FULL;
+
+	isPATA = (pPort->Type==PORT_TYPE_PATA)?1:0;
+
+	/* Get one slot for this request. */
+	tag = (MV_U8)Tag_GetOne(&pPort->Tag_Pool);
+
+	if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+		ret = ATAPI_CDB2TaskFile(pDevice, pReq, &taskFile);
+	else
+		ret = ATA_CDB2TaskFile(pDevice, pReq, tag, &taskFile);
+	if ( !ret )
+	{
+		pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST;
+		Tag_ReleaseOne(&pPort->Tag_Pool, tag);
+		/* Invalid request and can be returned to OS now. */
+		return MV_QUEUE_COMMAND_RESULT_FINISHED;	
+	}
+
+	if ( !isPATA )
+		SATA_PrepareCommandHeader(pPort, pReq, tag);
+	else
+		PATA_PrepareCommandHeader(pPort, pReq, tag);
+
+
+	if ( !isPATA )
+		SATA_PrepareCommandTable(pPort, pReq, tag, &taskFile);
+	else
+		PATA_PrepareCommandTable(pPort, pReq, tag, &taskFile);
+
+	/* in some cases, when preparing command table, a consolidated 
+	   request would cause PRD entries to run out. In this case, we
+	   return this request to re-try without consolidating */
+	/* This is assuming that REQ_STATUS_BUSY is ONLY used for these cases */
+	if (pReq->Scsi_Status == REQ_STATUS_BUSY)
+		return MV_QUEUE_COMMAND_RESULT_FINISHED;
+
+	SATA_SendFrame(pPort, pReq, tag);
+	/* Request is sent to the hardware and not finished yet. */
+	return MV_QUEUE_COMMAND_RESULT_SENT;
+}
+
+void Core_HandleWaitingList(PCore_Driver_Extension pCore)
+{
+	PMV_Request pReq = NULL;
+	MV_QUEUE_COMMAND_RESULT result;
+#ifdef SUPPORT_HOT_PLUG	
+	PDomain_Device pDevice;
+	MV_U8 portId, deviceId;
+#endif	
+#if defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX)
+	MV_U32 timeout;
+#endif /* efined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX) */
+
+	/* Get the request header */
+	while ( !List_Empty(&pCore->Waiting_List) )
+	{
+		pReq = (PMV_Request) List_GetFirstEntry(&pCore->Waiting_List, 
+							MV_Request, 
+							Queue_Pointer);
+		if ( NULL == pReq ) {
+			MV_ASSERT(0);
+			break;
+		}
+
+		if (pReq->Cdb[0]==0xEC){
+			MV_DPRINT(("Catch the 0xEC cmd.\n"));
+		}
+
+#if defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX)
+		pReq->eh_flag = 0;
+//		hba_init_timer(pReq);
+#endif /* defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX) */
+
+		/* During reset, we still have internal requests need to 
+		 *be handled. */
+
+		// Internal request is always at the beginning.
+		if ( (pCore->Need_Reset)&&(pReq->Cmd_Initiator!=pCore) ) 
+		{
+			/* Return the request back. */
+			List_Add(&pReq->Queue_Pointer, &pCore->Waiting_List);
+			return;
+		}
+	
+#ifdef SUPPORT_HOT_PLUG
+		/* hot plug - device is gone, reject this request */
+		if ( pReq->Device_Id != VIRTUAL_DEVICE_ID )
+		{
+			portId = PATA_MapPortId(pReq->Device_Id);
+			deviceId = PATA_MapDeviceId(pReq->Device_Id);
+			pDevice = &pCore->Ports[portId].Device[deviceId];
+
+			if ( !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) )
+			{
+				pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+				CompleteRequest(pCore, pReq, NULL);
+				return;
+			}
+
+			/* Reset is not done yet. */
+			if ( pDevice->State!=DEVICE_STATE_INIT_DONE )
+			{
+				/* check if it is the reset commands */
+				if ( !Core_IsInternalRequest(pCore, pReq) )
+				{
+					List_Add(&pReq->Queue_Pointer, &pCore->Waiting_List); /* Return the request back. */
+					return;
+				} 
+				else 
+				{
+					/* 
+					 * Cannot be the request sense. 
+					 * It's not pushed back. 
+					 */
+					MV_ASSERT( !SCSI_IS_REQUEST_SENSE(pReq->Cdb[0]) );
+				}
+			}
+		}
+#endif /* SUPPORT_HOT_PLUG */
+
+		/* Whether we can handle this request without hardware access? */
+		if ( HandleInstantRequest(pCore, pReq) ) 
+		{
+			CompleteRequest(pCore, pReq, NULL);
+			continue;
+		}
+
+		/* handle the cmd which data length is > 128k 
+		 * We suppose the data length was multiples of 128k first. 
+		 * If not, we will still verify multiples of 128k since 
+		 * no data transfer.
+		 */
+		if(pReq->Cdb[0] == SCSI_CMD_VERIFY_10)
+		{
+			PDomain_Device pDevice = &pCore->Ports[PATA_MapPortId(pReq->Device_Id)].Device[PATA_MapDeviceId(pReq->Device_Id)];
+			MV_U32 sectors = SCSI_CDB10_GET_SECTOR(pReq->Cdb);
+			
+			if((!(pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED)) && (sectors > MV_MAX_TRANSFER_SECTOR)){
+				MV_ASSERT(!pReq->Splited_Count );
+				pReq->Splited_Count = (MV_U8)((sectors + MV_MAX_TRANSFER_SECTOR -1)/MV_MAX_TRANSFER_SECTOR) - 1;
+				sectors = MV_MAX_TRANSFER_SECTOR; 
+				SCSI_CDB10_SET_SECTOR(pReq->Cdb, sectors);
+			}
+		}
+
+		result = PrepareAndSendCommand(pCore, pReq);	
+
+		switch ( result )
+		{
+			case MV_QUEUE_COMMAND_RESULT_FINISHED:
+				CompleteRequest(pCore, pReq, NULL);
+				break;
+
+			case MV_QUEUE_COMMAND_RESULT_FULL:
+				List_Add(&pReq->Queue_Pointer, &pCore->Waiting_List);
+				return;
+
+			case MV_QUEUE_COMMAND_RESULT_SENT:
+			{
+				portId = PATA_MapPortId(pReq->Device_Id);
+				deviceId = PATA_MapDeviceId(pReq->Device_Id);
+				pDevice = &pCore->Ports[portId].Device[deviceId];
+				pDevice->Outstanding_Req++;
+#if defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX)
+				/*
+				 * timeout to 15 secs if the port has just
+				 * been reset.
+				 */
+				if ( pReq->eh_flag ) {
+					timeout = HBA_REQ_TIMER_AFTER_RESET;
+					pReq->eh_flag = 0;
+				} else {
+					timeout = HBA_REQ_TIMER;
+				}
+
+				if (pDevice->Device_Type & DEVICE_TYPE_ATAPI)
+					timeout = timeout * 20 + 5;
+			#ifdef SUPPORT_ATA_SMART
+				if(pReq->Cdb[0]==SCSI_CMD_SND_DIAG) 
+					timeout = timeout * 10;
+			#endif
+				hba_init_timer(pReq);
+
+				hba_add_timer(pReq, 
+					      timeout, 
+					      __core_req_timeout_handler);
+				/*in captive mode, maybe timeout.*/
+			#ifdef SUPPORT_ATA_SMART
+				if(pReq->Cdb[0]== SCSI_CMD_MARVELL_SPECIFIC &&
+					pReq->Cdb[1]== CDB_CORE_MODULE &&
+						pReq->Cdb[2] == CDB_CORE_ATA_SMART_IMMEDIATE_OFFLINE){
+							hba_remove_timer(pReq);
+				}
+			#endif
+#elif defined(SUPPORT_ERROR_HANDLING)
+#ifdef SUPPORT_TIMER
+				/* start timer for error handling */
+				if( pDevice->Timer_ID == NO_CURRENT_TIMER )
+				{
+					// if no timer is running right now	
+					if (pDevice->Device_Type&DEVICE_TYPE_ATAPI){
+//						MV_DASSERT(pDevice->Outstanding_Req==1);
+						if (pReq->Time_Out!=0){							
+							pDevice->Timer_ID = Timer_AddRequest( pCore, pReq->Time_Out*2, Core_ResetChannel, pDevice, NULL );
+						}else {
+							pDevice->Timer_ID = Timer_AddRequest( pCore, REQUEST_TIME_OUT, Core_ResetChannel, pDevice, NULL );
+						}
+					}else {
+						pDevice->Timer_ID = Timer_AddRequest( pCore, REQUEST_TIME_OUT, Core_ResetChannel, pDevice, NULL );
+					}				
+				}
+#endif /* SUPPORT_TIMER */
+#endif /* defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX) */
+#if 0
+				{
+					MV_U8 i;
+					PMV_Request pTmpRequest = NULL;
+					PDomain_Port pPort = pDevice->PPort;
+					/* When there is reset command, other commands won't come here. */
+					if ( SCSI_IS_READ(pReq->Cdb[0]) || SCSI_IS_WRITE(pReq->Cdb[0]) )
+					{
+						for ( i=0; i<MAX_SLOT_NUMBER; i++ )
+						{
+							pTmpRequest = pPort->Running_Req[i];
+							if ( pTmpRequest && (pTmpRequest->Device_Id==pReq->Device_Id) ) 
+							{
+								MV_DASSERT( !SCSI_IS_INTERNAL(pTmpRequest->Cdb[0]) );
+							}
+						}
+
+					}
+				}
+#endif /* 0 */
+				break;
+			}
+			default:
+				MV_ASSERT(MV_FALSE);
+		}
+	}
+	
+#ifdef SUPPORT_CONSOLIDATE
+	{
+		MV_U8 i,j;
+		PDomain_Port pPort;
+
+		if ( pCore->Is_Dump ) return;
+
+		/* 
+		* If there is no more request we can do, 
+		* force command consolidate to run the holding request. 
+		*/
+		for ( i=0; i<MAX_PORT_NUMBER; i++ )
+		{
+			pPort = &pCore->Ports[i];
+			for ( j=0; j<MAX_DEVICE_PER_PORT; j++ )
+			{
+				if ( (pPort->Device[j].Status&DEVICE_STATUS_FUNCTIONAL)
+					&& (pPort->Device[j].Outstanding_Req==0) )
+				{
+					Consolid_PushSendRequest(pCore, i*MAX_DEVICE_PER_PORT+j);
+				}
+			}
+		}
+	}
+#endif /* SUPPORT_CONSOLIDATE */
+}
+
+/*
+ * Interrupt service routine and related funtion
+ * We can split this function to two functions. 
+ * One is used to check and clear interrupt, called in ISR. 
+ * The other is used in DPC.
+ */
+void SATA_PortHandleInterrupt(
+	IN PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort
+	);
+void PATA_PortHandleInterrupt(
+	IN PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort
+	);
+void SATA_HandleSerialError(
+	IN PDomain_Port pPort,
+	IN MV_U32 serialError
+	);
+void SATA_HandleHotplugInterrupt(
+	IN PDomain_Port pPort,
+	IN MV_U32 intStatus
+	);
+
+MV_BOOLEAN Core_InterruptServiceRoutine(MV_PVOID This)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	MV_U32	irqStatus;
+	MV_U8 i;
+	PDomain_Port pPort = NULL;
+
+	/* Get interrupt status */
+	irqStatus = MV_REG_READ_DWORD(pCore->Mmio_Base, HOST_IRQ_STAT);
+	irqStatus &= pCore->Port_Map;
+#ifndef  SUPPORT_TASKLET
+	if (!irqStatus) {
+		return MV_FALSE;
+	}
+
+	for ( i=0; i<pCore->Port_Num; i++ ) 
+	{
+		/* no interrupt for this port. */
+		if (!(irqStatus&(1<<i)))
+			continue;
+
+		pPort = &pCore->Ports[i];
+		if ( pPort->Type==PORT_TYPE_PATA )
+			PATA_PortHandleInterrupt(pCore, pPort);
+		else
+			SATA_PortHandleInterrupt(pCore, pPort);
+	}
+
+	/* If we need to do hard reset. And the controller is idle now. */
+	if ((pCore->Need_Reset) && (!pCore->Resetting))
+	{
+		if (Core_WaitingForIdle(pCore))
+			Core_ResetHardware(pCore);
+	}
+
+	Core_HandleWaitingList(pCore);
+#else
+	pCore->Saved_ISR_Status=irqStatus;
+#endif
+	return MV_TRUE;
+}
+
+#ifdef  SUPPORT_TASKLET
+MV_BOOLEAN Core_HandleServiceRoutine(MV_PVOID This)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	MV_U8 i;
+	PDomain_Port pPort = NULL;
+	for ( i=0; i<pCore->Port_Num; i++ ) 
+	{
+		/* no interrupt for this port. */
+		if (!(pCore->Saved_ISR_Status&(1<<i)))
+			continue;
+
+		pPort = &pCore->Ports[i];
+		if ( pPort->Type==PORT_TYPE_PATA )
+			PATA_PortHandleInterrupt(pCore, pPort);
+		else
+			SATA_PortHandleInterrupt(pCore, pPort);
+	}
+
+	/* If we need to do hard reset. And the controller is idle now. */
+	if ((pCore->Need_Reset) && (!pCore->Resetting))
+	{
+		if (Core_WaitingForIdle(pCore))
+			Core_ResetHardware(pCore);
+	}
+
+	Core_HandleWaitingList(pCore);
+
+	return MV_TRUE;
+}
+#endif
+
+void SATA_HandleSerialError(
+	IN PDomain_Port pPort,
+	IN MV_U32 serialError
+	)
+{
+	MV_DPRINT(("Error: port=%d  Serial error=0x%x.\n", pPort->Id, serialError));
+}
+
+void SATA_ResetPort(PCore_Driver_Extension pCore, MV_U8 portId);
+
+#ifdef COMMAND_ISSUE_WORKROUND
+
+void SATA_ResetPort(PCore_Driver_Extension pCore, MV_U8 portId);
+MV_BOOLEAN ResetController(PCore_Driver_Extension pCore);
+void InitChip(PCore_Driver_Extension pCore);
+void mvHandleDevicePlugin_BH(MV_PVOID ext);
+
+#define CORE_ERROR_HANDLE_RESET_DEVICE		1
+#define CORE_ERROR_HANDLE_RESET_PORT			2
+#define CORE_ERROR_HANDLE_RESET_HBA			3
+
+
+MV_U8 mv_core_reset_port(PDomain_Port pPort)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pPort->Core_Extension;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_U32 temp=0,count=0;
+	MV_U32 old_stat;
+	MV_U32 issue_reg=0;
+	MV_U8 ret=MV_TRUE;
+
+	//mvDisableIntr(portMmio, old_stat);
+
+	/* Toggle should before we clear the channel interrupt status but not the global interrupt. */
+	MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+#if 1
+	{
+		MV_U16 counter;
+		{
+			/*Doing PHY reset*/
+			MV_U32 SControl = MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);
+			SControl &= ~0x000000FF;
+#ifdef FORCE_1_5_G
+			SControl |= 0x11;
+#else
+			SControl |= 0x21;
+#endif
+			MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+			MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);	/* flush */
+			HBA_SleepMillisecond(pCore, 2);
+//			hba_msleep(2);
+
+			SControl &= ~0x0000000F;
+			MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+			MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);	/* flush */
+			HBA_SleepMillisecond(pCore, 10);
+//			hba_msleep(10);
+		}
+
+		/*Waiting PHY Ready*/
+		counter = 200;
+		while(((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT) & 0x0f) != 0x03) && (counter > 0)) {
+			HBA_SleepMillisecond(pCore, 10);
+			//hba_msleep(10);
+			counter --;
+		}
+
+		if (counter > 0) {
+			/*Some HD update status too slow, so the workaround to wait HD ready*/
+			counter = 200;
+			while (((MV_REG_READ_DWORD(portMmio, PORT_TFDATA) & 0xff) != 0x50) && (counter > 0)) {
+				HBA_SleepMillisecond(pCore, 10);
+				//hba_msleep(10);
+				counter --;
+			}
+		}
+	}
+#endif
+
+	/* Always turn the PM bit on - otherwise won't work! */
+	temp = MV_REG_READ_DWORD(portMmio, PORT_CMD);
+	MV_REG_WRITE_DWORD(portMmio, PORT_CMD, temp | MV_BIT(17));
+	temp=MV_REG_READ_DWORD(portMmio, PORT_CMD);	/* flush */
+#if 1
+	/*Clear Busy bit and error bit, do spin-up device, power on device*/
+	temp = MV_REG_READ_DWORD(portMmio, PORT_CMD);					
+	MV_REG_WRITE_DWORD(portMmio, PORT_CMD, temp | MV_BIT(3) | MV_BIT(2) | MV_BIT(1));
+	temp=MV_REG_READ_DWORD(portMmio, PORT_CMD);	/* flush */
+#endif
+	/* hardware workaround - send dummy FIS first to clear FIFO */
+	temp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp & ~PORT_CMD_START);
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp |PORT_CMD_START);
+	Tag_Init( &pPort->Tag_Pool, pPort->Tag_Pool.Size );
+	//sendDummyFIS( pPort );
+
+	// start command handling on this port
+	temp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp & ~PORT_CMD_START);
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp | PORT_CMD_START);
+	HBA_SleepMillisecond(pCore, 2000);
+	//hba_msleep(2000);
+	// reset the tag stack - to guarantee soft reset is issued at slot 0
+	Tag_Init( &pPort->Tag_Pool, pPort->Tag_Pool.Size );
+
+	// make sure CI is cleared before moving on
+	issue_reg = MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE);
+	while (issue_reg != 0 && count < 10) {
+		count++;
+		temp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+		MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp & ~PORT_CMD_START);
+		MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp | PORT_CMD_START);
+		HBA_SleepMillisecond(pCore, 1000);
+		//hba_msleep(1000);
+		issue_reg = MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE);
+	}
+	
+	//mvEnableIntr(portMmio, old_stat);
+
+	temp = MV_REG_READ_DWORD(portMmio, PORT_IRQ_STAT);
+	if(temp){
+		MV_DPRINT(("port reset but port status can not be clean[0x%x] on port[%d].\n",MV_REG_READ_DWORD( portMmio, PORT_IRQ_STAT), pPort->Id));
+		MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_STAT, temp);
+	}
+
+	if(MV_REG_READ_DWORD( portMmio, PORT_CMD) & PORT_CMD_LIST_ON){
+		MV_PRINT("port reset but command running can not be clean[0x%x] on port[%d].\n",MV_REG_READ_DWORD( portMmio, PORT_CMD_ISSUE), pPort->Id);
+		ret = MV_FALSE;
+	}
+
+	if (issue_reg != 0)
+	{
+		MV_PRINT("port reset but CI can not be clean[0x%x] on port[%d].\n",MV_REG_READ_DWORD( portMmio, PORT_CMD_ISSUE), pPort->Id);
+		ret = MV_FALSE;
+	}	
+
+	return ret;
+}
+
+
+MV_U8 mv_core_reset_hba(PDomain_Port pPort)
+{
+
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pPort->Core_Extension;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_U32 tmp;
+	pCore->error_handle_state = CORE_ERROR_HANDLE_RESET_HBA;
+	MV_REG_WRITE_DWORD(mmio, HOST_CTL, 0);
+	MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_MASK, 0);
+
+	//Reset port command start.
+	tmp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp & ~PORT_CMD_START);
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp | PORT_CMD_START);
+	HBA_SleepMillisecond(pCore, 500);
+	//hba_msleep(500);
+
+	if(ResetController(pCore) == MV_FALSE) {
+		MV_DPRINT(("Reset controller failed."));
+		return MV_FALSE;
+
+	}
+	InitChip(pCore);
+
+
+	MV_DPRINT(("Finished reset hba for port[%d], CMD=0x%x.\n",pPort->Id, MV_REG_READ_DWORD(portMmio, PORT_CMD)));
+	//mv_core_dump_reg(pPort);
+	return MV_TRUE;
+}
+
+void mv_core_reset_command_in_timer(PDomain_Port pPort)
+{
+	unsigned long flags;
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pPort->Core_Extension;
+	MV_DPRINT(("start handle reset command in timer for port[%d].\n",pPort->Id));
+	spin_lock_irqsave(&pCore->desc->hba_desc->global_lock, flags);
+	mv_core_reset_command(pPort);
+	spin_unlock_irqrestore(&pCore->desc->hba_desc->global_lock, flags);
+
+}
+
+MV_U8 mv_core_check_is_reseeting(MV_PVOID core_ext)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)core_ext;
+	return	pCore->resetting_command;
+}
+
+
+void mv_core_init_reset_para(PDomain_Port pPort)
+{
+
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pPort->Core_Extension;
+	pCore->resetting_command = MV_FALSE;
+	pPort->command_callback = NULL;
+	pPort->timer_para = NULL;
+	pPort->Hot_Plug_Timer = 0;
+	pPort->find_disk = MV_FALSE;
+//	pPort->reset_cmd_times= 0;
+	
+}
+void mv_core_put_back_request(PDomain_Port pPort)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pPort->Core_Extension;
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 i,j;
+	PMV_Request pReq = NULL;
+	PDomain_Device pDevice=NULL;	
+	/* put all the running requests back into waiting list */
+	for ( i=0; i<MAX_SLOT_NUMBER; i++ )
+	{
+		pReq = pPort->Running_Req[i];
+		if (pReq) {
+			/*
+			 * If this channel has multiple devices, pReq is 
+			 * not the internal request of pDevice
+			 */
+			if ( !Core_IsInternalRequest(pCore, pReq) )
+			{
+				List_AddTail(&pReq->Queue_Pointer, &pCore->Waiting_List);
+			}
+			else 
+			{
+				/* Can be reset command or request sense command */
+				if ( SCSI_IS_REQUEST_SENSE(pReq->Cdb[0]) )
+				{
+					MV_ASSERT( pReq->Org_Req!=NULL );
+					if ( pReq->Org_Req )
+						List_AddTail( &((PMV_Request)pReq->Org_Req)->Queue_Pointer, &pCore->Waiting_List);
+				}
+			}
+			
+			hba_remove_timer(pReq);
+			pReq->eh_flag = 1;
+			mv_core_reset_running_slot(pPort, i);
+		}
+	}
+	MV_DASSERT(pPort->Running_Slot == 0);
+	
+	/* reset device related variables */
+	for ( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+	{
+		pDevice = &pPort->Device[i];
+		
+//		pDevice->Device_Type = 0;
+//		pDevice->Need_Notify = MV_FALSE;
+#ifdef SUPPORT_TIMER 
+		if( pDevice->Timer_ID != NO_CURRENT_TIMER )
+		{
+			Timer_CancelRequest( pCore, pDevice->Timer_ID );
+			pDevice->Timer_ID = NO_CURRENT_TIMER;
+		}
+#endif /* SUPPORT_TIMER */
+		pDevice->Outstanding_Req = 0;
+		
+		/*
+		 * Go through the waiting list. If there is some reset 
+		 * request, remove that request. 
+		 */
+		mvRemoveDeviceWaitingList(pCore, pDevice->Id, MV_FALSE);
+	}
+
+	// reset the tag stack - to guarantee soft reset is issued at slot 0
+	Tag_Init( &pPort->Tag_Pool, pPort->Tag_Pool.Size );
+
+	for( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+	{
+		if( (pPort->Device[i].Status & DEVICE_STATUS_FUNCTIONAL) && 
+			(pPort->Device[i].Internal_Req != NULL) )
+		{
+			if (pCore->Total_Device_Count && (pPort->Port_State == PORT_STATE_INIT_DONE))
+				pCore->Total_Device_Count--;
+			ReleaseInternalReqToPool( pCore, pPort->Device[i].Internal_Req );
+			pPort->Device[i].Internal_Req = NULL;
+		}
+	}
+}
+
+
+#define MAX_WAIT_TIMES	3
+void  mv_core_reset_command(PDomain_Port pPort)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pPort->Core_Extension;
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 tmp;
+	MV_U32 port_id, slot_id;
+	PMV_Request pReq = NULL;
+	PDomain_Port pCheckPort;
+
+	Timer_CancelRequest(pPort, NULL);
+	MV_DPRINT(("Reset HBA times=%d, Hot_Plug_Timer=%d.\n",pPort->reset_hba_times, pPort->Hot_Plug_Timer));
+
+	/* check disk exist */
+	if ((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT) & 0xf) == 0)
+		return;
+
+	pPort->Hot_Plug_Timer++;
+
+	pCore->resetting_command = MV_TRUE;
+	for(port_id=0;port_id<MAX_PORT_NUMBER;port_id++){
+		pCheckPort = &pCore->Ports[port_id];
+		if((pCheckPort != pPort) && pCheckPort->Running_Slot){
+			if(pPort->Hot_Plug_Timer < (MAX_WAIT_TIMES -1)){
+				MV_DPRINT(("Wait port[%d] running request[0x%x].\n",pCheckPort->Id, pCheckPort->Running_Slot));
+				Timer_AddRequest(pPort, 1, mv_core_reset_command_in_timer, pPort, NULL);
+				return;
+			} else {
+				MV_DPRINT(("Abort port[%d] running request[0x%x].\n",pCheckPort->Id, pCheckPort->Running_Slot));
+				mv_core_put_back_request(pCheckPort);
+			}
+		}
+	}
+
+
+	if(pPort->Hot_Plug_Timer > MAX_WAIT_TIMES){
+		MV_DPRINT(("ERROR: Wait too long time for command running bit, failed detecting port[%d].\n",pPort->Id));
+		mv_core_init_reset_para(pPort);
+		return;
+	}
+
+	pPort->reset_hba_times++;
+	if(pPort->reset_hba_times > MAX_RESET_TIMES)
+	{
+		MV_DPRINT(("Has reset command on port [%d] more than %d.\n",pPort->Id, MAX_RESET_TIMES));
+		mv_core_init_reset_para(pPort);
+		return;
+	}
+	
+	pPort->Port_State = PORT_STATE_IDLE;
+	mv_core_reset_hba(pPort);
+	MV_DPRINT(("Re-enable AHCI mode on port[%d].\n",pPort->Id));
+	if(pPort->command_callback){
+		MV_DPRINT(("reset hba callback on port[%d].\n",pPort->Id));
+		pPort->command_callback( pPort);
+	}
+	return;
+}
+
+void mv_core_dump_reg(PDomain_Port pPort)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pPort->Core_Extension;
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_DPRINT(("Global status=0x%x.\n", MV_REG_READ_DWORD(mmio, HOST_IRQ_STAT)));
+	MV_DPRINT(("Global control=0x%x.\n", MV_REG_READ_DWORD(mmio, HOST_CTL)));
+	MV_DPRINT(("Port[%d] command =0x%x.\n",pPort->Id,  MV_REG_READ_DWORD( portMmio, PORT_CMD )));
+	MV_DPRINT(("Port[%d] command issue =0x%x.\n",pPort->Id,  MV_REG_READ_DWORD( portMmio, PORT_CMD_ISSUE)));
+	MV_DPRINT(("Port[%d] irq status=0x%x.\n",pPort->Id,  MV_REG_READ_DWORD(portMmio, PORT_IRQ_STAT)));
+}
+#endif	//COMMAND_ISSUE_WORKROUND
+
+#ifdef SUPPORT_HOT_PLUG
+void Device_SoftReset(PDomain_Port pPort, PDomain_Device pDevice);
+
+void mvRemoveDeviceWaitingList( MV_PVOID This, MV_U16 deviceId, MV_BOOLEAN returnOSRequest )
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	PMV_Request pReq = NULL;
+	List_Head *pPos;
+	List_Head remove_List;
+	MV_U8 count = 0, myCount=0, i;
+	PDomain_Device pDevice;
+	MV_U8 portNum = PATA_MapPortId(deviceId);
+	MV_U8 deviceNum = PATA_MapDeviceId(deviceId);
+	pDevice = &pCore->Ports[portNum].Device[deviceNum];
+
+	LIST_FOR_EACH(pPos, &pCore->Waiting_List) {
+		count++;
+	}
+
+	if (count!=0){
+		MV_LIST_HEAD_INIT(&remove_List);
+	}
+
+	/* 
+	 * If returnOSRequest is MV_FALSE, actually we just remove the 
+	 * internal reset command. 
+	 */
+	while ( count>0 )
+	{
+		pReq = (PMV_Request)List_GetFirstEntry(&pCore->Waiting_List, MV_Request, Queue_Pointer);
+
+		if ( pReq->Device_Id==deviceId )
+		{
+			if ( !Core_IsInternalRequest(pCore, pReq) )
+			{
+				if ( returnOSRequest ) {
+					pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+					List_AddTail(&pReq->Queue_Pointer, &remove_List);
+					myCount++;
+				} else {
+					List_AddTail(&pReq->Queue_Pointer, &pCore->Waiting_List);
+				}
+			}
+			else 
+			{
+				/* Reset command or request sense */
+				if ( SCSI_IS_REQUEST_SENSE(pReq->Cdb[0]) )
+				{
+					MV_ASSERT( pReq->Org_Req!=NULL );
+					pReq = (PMV_Request)pReq->Org_Req;
+					if ( pReq ) {
+						if ( returnOSRequest ) {
+							pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+							List_AddTail(&pReq->Queue_Pointer, &remove_List);
+							myCount++;
+						} else {
+							List_AddTail(&pReq->Queue_Pointer, &pCore->Waiting_List);
+						}
+					}
+				} else {
+					/* Reset command is removed. */
+				}
+			}
+		}
+		else
+		{
+			List_AddTail(&pReq->Queue_Pointer, &pCore->Waiting_List);
+		}
+		count--;
+	}//end of while
+
+	for (i=0; i<myCount; i++){
+		pReq = (PMV_Request)List_GetFirstEntry(&remove_List, MV_Request, Queue_Pointer);
+		MV_DASSERT(pReq && (pReq->Scsi_Status==REQ_STATUS_NO_DEVICE));
+		CompleteRequest(pCore, pReq, NULL);
+	}//end of for
+}
+
+void mvRemovePortWaitingList( MV_PVOID This, MV_U8 portId )
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	PMV_Request pReq;
+	List_Head *pPos;
+	List_Head remove_List;
+	MV_U8 count = 0, myCount=0, i;
+
+	LIST_FOR_EACH(pPos, &pCore->Waiting_List) {
+		count++;
+	}
+
+	if (count!=0){
+		MV_LIST_HEAD_INIT(&remove_List);
+	}
+
+	while ( count>0 )
+	{
+		pReq = (PMV_Request)List_GetFirstEntry(&pCore->Waiting_List, MV_Request, Queue_Pointer);
+		if ( PATA_MapPortId(pReq->Device_Id) == portId )
+		{
+			if ( pReq->Cmd_Initiator==pCore ) {
+				if ( SCSI_IS_READ(pReq->Cdb[0]) || SCSI_IS_WRITE(pReq->Cdb[0]) ) {
+					/* Command consolidate, should return */
+					pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+					List_AddTail(&pReq->Queue_Pointer, &remove_List);
+					myCount++;
+				} else if ( SCSI_IS_REQUEST_SENSE(pReq->Cdb[0]) ) {
+					/* Request sense */
+					MV_ASSERT( pReq->Org_Req!=NULL );
+					pReq = (PMV_Request)pReq->Org_Req;
+					if ( pReq ) {
+						pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+						List_AddTail(&pReq->Queue_Pointer, &remove_List);
+						myCount++;
+					} 
+				} else {
+					/* Reset command. Ignore. */
+				}
+			} else {
+				pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+				List_AddTail(&pReq->Queue_Pointer, &remove_List);
+				myCount++;
+			}
+		}
+		else
+		{
+			List_AddTail(&pReq->Queue_Pointer, &pCore->Waiting_List);
+		}
+		count--;
+	}//end of while
+
+	for (i=0; i<myCount; i++){
+		pReq = (PMV_Request)List_GetFirstEntry(&remove_List, MV_Request, Queue_Pointer);
+		MV_DASSERT(pReq && (pReq->Scsi_Status==REQ_STATUS_NO_DEVICE));
+		CompleteRequest(pCore, pReq, NULL);
+	}//end of for
+
+}
+#ifdef HOTPLUG_ISSUE_WORKROUND
+void mvHandleDeviceUnplugReset (MV_PVOID pport, MV_PVOID temp);
+#endif
+void mvHandleDeviceUnplug (PCore_Driver_Extension pCore, PDomain_Port pPort)
+{
+	PMV_Request pReq;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U8 i;
+	MV_U32 temp;
+
+	#ifdef HOTPLUG_ISSUE_WORKROUND
+	PDomain_Device pDevice = &pPort->Device[0];
+    	MV_U32 SControl = 0;
+	#endif
+#ifdef COMMAND_ISSUE_WORKROUND
+	MV_DPRINT(("Check port[%d] running slot[0x%x].\n",pPort->Id, pPort->Running_Slot));
+	Timer_CancelRequest(pPort, NULL);
+#endif
+	if( !SATA_PortDeviceDetected(pPort) )
+	{
+		/* clear the start bit in cmd register, 
+		   stop the controller from handling anymore requests */
+		temp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+		MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp & ~PORT_CMD_START);
+
+		/* Device is gone. Return the Running_Req */
+		for ( i=0; i<MAX_SLOT_NUMBER; i++ )
+		{
+			pReq =  pPort->Running_Req[i];
+			if ( pReq !=NULL )
+			{
+				pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+				CompleteRequestAndSlot(pCore, pPort, pReq, NULL, i);
+			}
+		}
+
+		if( pPort->Type == PORT_TYPE_PM )
+		{
+			pPort->Setting &= ~PORT_SETTING_PM_FUNCTIONAL;
+			pPort->Setting &= ~PORT_SETTING_PM_EXISTING;
+		}
+
+		SATA_PortReportNoDevice( pCore, pPort );
+		#ifdef HOTPLUG_ISSUE_WORKROUND
+		if( pPort->Type != PORT_TYPE_PM ){
+			
+			mvDisableIntr(portMmio, pPort->old_stat);
+			
+			SControl = MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);
+			SControl &= ~0x0000000F;
+			SControl |= 0x4;    // Disable PHY
+			MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+			MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);	/* flush */
+			HBA_SleepMillisecond(pCore, 10);
+		
+			MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+			MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);	/* flush */
+			HBA_SleepMillisecond(pCore, 10);
+		
+			pDevice->Status = DEVICE_STATUS_UNPLUG;
+			MV_DPRINT(("######### Device UNPLUG on PORT irq_mask=0x%x#########\n",pPort->old_stat));
+		
+			Timer_AddRequest( pPort, 8, mvHandleDeviceUnplugReset, pPort, NULL);
+			}
+		#endif
+	}
+	else
+	{
+		MV_DPRINT(("===== Not detect that device is out =====\n"));
+	}
+}
+
+void sendDummyFIS( PDomain_Port pPort )
+{
+	MV_U16 tag = Tag_GetOne(&pPort->Tag_Pool);
+	PMV_Command_Header header = SATA_GetCommandHeader(pPort, tag);
+	PMV_Command_Table pCmdTable = Port_GetCommandTable(pPort, tag);
+	PSATA_FIS_REG_H2D pFIS = (PSATA_FIS_REG_H2D)pCmdTable->FIS;
+#if 1//ndef _OS_LINUX
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+#endif
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 old_stat;
+	MV_U32 temp=0, count=0;
+	MV_DASSERT( tag == 0 );
+
+	mvDisableIntr(portMmio, old_stat);
+
+	MV_ZeroMemory(header, sizeof(MV_Command_Header));
+	MV_ZeroMemory(pCmdTable, sizeof(MV_Command_Table));
+	
+	header->FIS_Length = 0;
+	header->Reset = 0;
+	header->PM_Port = 0xE;
+	
+	header->Table_Address = pPort->Cmd_Table_DMA.parts.low + SATA_CMD_TABLE_SIZE*tag;
+	header->Table_Address_High = pPort->Cmd_Table_DMA.parts.high;
+	
+	pFIS->FIS_Type = SATA_FIS_TYPE_REG_H2D;
+	pFIS->PM_Port = 0;
+	pFIS->Control = 0;
+
+	MV_REG_WRITE_DWORD(portMmio, PORT_CMD_ISSUE, 1<<tag);
+	MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE);	/* flush */
+
+	HBA_SleepMicrosecond(pCore, 10);
+	//hba_msleep(10);
+
+	// make sure CI is cleared before moving on
+	do {
+		temp = MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE) & (1<<tag);
+		count++;
+		HBA_SleepMillisecond(pCore, 10);
+		//hba_msleep(10);
+	} while (temp != 0 && count < 1000);
+
+	Tag_ReleaseOne(&pPort->Tag_Pool, tag);
+	mvEnableIntr(portMmio, old_stat);
+
+	if (temp != 0)
+	{
+//		MV_DPRINT(("DummyFIS:CI can not be clean[0x%x] on port[%d].\n",MV_REG_READ_DWORD( portMmio, PORT_CMD_ISSUE), pPort->Id));
+	}	
+}
+
+
+
+
+void mvHandleDevicePlugin (PCore_Driver_Extension pCore, PDomain_Port pPort)
+{
+	PDomain_Device pDevice = &pPort->Device[0];
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U8 i;
+	MV_U32 temp=0;
+	MV_DPRINT(("Find plug in device on port[%d].\n",pPort->Id));
+
+	if( pCore->Total_Device_Count >= MAX_DEVICE_SUPPORTED ){
+		MV_DPRINT(("has many device[%d].\n", pCore->Total_Device_Count ));
+		return;
+	}
+#ifdef COMMAND_ISSUE_WORKROUND
+	pPort->reset_hba_times = 0;
+	mv_core_init_reset_para(pPort);
+#endif
+	#ifdef HOTPLUG_ISSUE_WORKROUND
+	if ( pDevice->Status == DEVICE_STATUS_UNPLUG )
+	{
+	  	MV_DPRINT(("######## Cancel hot plug INT #########"));
+	    return;
+	}
+	#endif
+	// start command handling on this port
+	mv_core_reset_port(pPort);
+	// reset the tag stack - to guarantee soft reset is issued at slot 0
+	Tag_Init( &pPort->Tag_Pool, pPort->Tag_Pool.Size );
+
+#ifdef COMMAND_ISSUE_WORKROUND
+	pPort->error_state = PORT_ERROR_AT_PLUGIN;
+	if(MV_REG_READ_DWORD( portMmio, PORT_CMD) & PORT_CMD_LIST_ON)
+	{
+		MV_PRINT("Find command running BIT is set on port[%d], reset HBA in timer handler.\n",pPort->Id);
+		pPort->Hot_Plug_Timer = 0;
+		pPort->command_callback = mvHandleDevicePlugin_BH;
+		mv_core_reset_command(pPort);
+		return;
+	}
+#endif
+	mvHandleDevicePlugin_BH(pPort);
+}
+
+void mvHandleDevicePlugin_BH(MV_PVOID  ext)
+{
+	PDomain_Port pPort = (PDomain_Port)ext;
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)pPort->Core_Extension;
+	PDomain_Device pDevice = &pPort->Device[0];
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U8 i;
+	MV_U32 temp;
+	MV_U32 tmp, old_stat;
+
+	// do software reset
+	MV_DPRINT(("Detected device plug-in, doing soft reset\n"));
+
+	if (! (SATA_PortSoftReset( pCore, pPort )) ){
+		goto start_waiting_command;
+	}
+	#ifdef HOTPLUG_ISSUE_WORKROUND
+	if ( pDevice->Status == DEVICE_STATUS_UNPLUG )
+	{
+	   MV_DPRINT(("######## Cancel hot plug  BH #########"));
+	    return;
+	}
+	#endif
+	if( pPort->Type == PORT_TYPE_PM ) 
+	{
+		/* need to send notifications for all of these devices */
+		for (i=0; i<MAX_DEVICE_PER_PORT; i++)
+		{
+			pDevice = &pPort->Device[i];
+			pDevice->Id = (pPort->Id)*MAX_DEVICE_PER_PORT + i;
+			pDevice->Need_Notify = MV_TRUE;
+			pDevice->State = DEVICE_STATE_IDLE;
+			pDevice->Device_Type = 0;
+			pDevice->Reset_Count = 0;
+		}
+
+		/*SATA_InitPM( pPort );*/
+		SATA_PortReset( pPort, MV_TRUE);
+	} 
+	else
+	{
+		/* not a PM - turn off the PM bit in command register */
+		temp = MV_REG_READ_DWORD(portMmio, PORT_CMD);					
+		MV_REG_WRITE_DWORD(portMmio, PORT_CMD, temp & (~MV_BIT(17)));
+		temp=MV_REG_READ_DWORD(portMmio, PORT_CMD);	/* flush */
+
+		if( SATA_PortDeviceDetected(pPort) )
+		{
+			if ( SATA_PortDeviceReady(pPort) )
+			{
+				MV_U32 signature;
+
+				signature = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_SIG);
+				if ( signature==0xEB140101 )				/* ATAPI signature */
+					pDevice->Device_Type |= DEVICE_TYPE_ATAPI;
+				else 
+				#ifdef HOTPLUG_ISSUE_WORKROUND
+					if(signature==0x00000101)
+				#endif
+					{
+						MV_DASSERT( signature==0x00000101 );	/* ATA signature */
+                    				pDevice->Device_Type &= ~DEVICE_TYPE_ATAPI;
+					}
+				#ifdef HOTPLUG_ISSUE_WORKROUND
+					else{
+						SATA_PortReportNoDevice(pCore,pPort);
+						return;
+						}
+				#endif
+
+				pDevice->Internal_Req = GetInternalReqFromPool(pCore);
+				if( pDevice->Internal_Req == NULL )
+				{
+					MV_DPRINT(("ERROR: Unable to get an internal request buffer\n"));
+					/* can't initialize without internal buffer - just set this disk down */
+					pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+					pDevice->State = DEVICE_STATE_INIT_DONE;
+					goto start_waiting_command;
+				}
+				else 
+				{
+					{
+						pDevice->Status = DEVICE_STATUS_EXISTING|DEVICE_STATUS_FUNCTIONAL;
+						pDevice->State = DEVICE_STATE_RESET_DONE;
+						pDevice->Id = (pPort->Id)*MAX_DEVICE_PER_PORT;
+						if(pPort->error_state == PORT_ERROR_AT_PLUGIN){
+							pDevice->Need_Notify = MV_TRUE;
+							pPort->Device_Number++;
+						}
+						pDevice->Reset_Count = 0;
+					}
+				}
+				
+				mvDeviceStateMachine (pCore, pDevice);
+			}
+		}
+	}
+
+start_waiting_command:
+	MV_DPRINT(("Finshed mvHandleDevicePlugin_BH on port[%d].\n",pPort->Id));
+	Core_HandleWaitingList(pCore);
+	
+}
+
+#ifdef SUPPORT_PM
+void mvHandlePMUnplug (PCore_Driver_Extension pCore, PDomain_Device pDevice)
+{
+	PMV_Request pReq;
+	PDomain_Port pPort = pDevice->PPort;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	List_Head *pPos;
+	MV_U8 i, count;
+	MV_U32 temp, cmdIssue;
+	MV_BOOLEAN valid;
+	#ifdef RAID_DRIVER
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_RAID);	
+	#else
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_HBA);
+	#endif
+
+	pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+	pPort->Device_Number--;
+
+	cmdIssue = MV_REG_READ_DWORD( portMmio, PORT_CMD_ISSUE );
+
+	/* toggle the start bit in cmd register */
+	temp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp & ~MV_BIT(0));
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, temp | MV_BIT(0));
+	HBA_SleepMillisecond( pCore, 100 );
+	//hba_msleep(100);
+
+	/* check for requests that are not finished, clear the port,
+	 * then re-send again */
+	for ( i=0; i<MAX_SLOT_NUMBER; i++ )
+	{
+		pReq = pPort->Running_Req[i];
+
+		if( pReq != NULL )
+		{
+			if( pReq->Device_Id == pDevice->Id )
+			{
+				pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+				CompleteRequestAndSlot(pCore, pPort, pReq, NULL, i);
+			}
+			else if ( cmdIssue & (1<<i) )
+			{
+				if( PrepareAndSendCommand( pCore, pReq ) == MV_QUEUE_COMMAND_RESULT_SENT )
+				{
+#ifdef SUPPORT_ERROR_HANDLING
+#ifdef SUPPORT_TIMER
+					/* start timer for error handling */
+					if( pDevice->Timer_ID == NO_CURRENT_TIMER )
+					{
+						// if no timer is running right now
+						pDevice->Timer_ID = Timer_AddRequest( pCore, REQUEST_TIME_OUT, Core_ResetChannel, pDevice, NULL );
+					}
+#endif /* SUPPORT_TIMER */
+#endif /* SUPPORT_ERROR_HANDLING */
+					pDevice->Outstanding_Req++;
+				}
+				else
+					MV_DASSERT(MV_FALSE);		// shouldn't happens
+			}
+		}
+	}
+
+	count = 0;
+	LIST_FOR_EACH(pPos, &pCore->Waiting_List) {
+		count++;
+	}
+	while ( count>0 )
+	{
+		pReq = (PMV_Request)List_GetFirstEntry(&pCore->Waiting_List, MV_Request, Queue_Pointer);
+
+		if ( pReq->Device_Id == pDevice->Id )
+		{
+			pReq->Scsi_Status = REQ_STATUS_NO_DEVICE;
+			CompleteRequest(pCore, pReq, NULL);
+		}
+		else
+		{
+			List_AddTail(&pReq->Queue_Pointer, &pCore->Waiting_List);
+		}
+		count--;
+	}
+
+	/* clear x bit */
+	valid = MV_FALSE;
+	do
+	{
+		mvPMDevReWrReg( pPort, MV_Read_Reg, MV_SATA_PSCR_SERROR_REG_NUM, 0, pDevice->PM_Number, MV_TRUE );
+		temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+
+		if (((temp >> 16) & 0xF0) == 0xF0)
+			valid = MV_TRUE;
+          
+		temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+	} while (valid == MV_FALSE);
+
+	mvPMDevReWrReg( pPort, MV_Write_Reg, MV_SATA_PSCR_SERROR_REG_NUM, temp, pDevice->PM_Number, MV_TRUE);
+
+	if( pDevice->Internal_Req != NULL )
+	{
+		pCore->Total_Device_Count--;
+		ReleaseInternalReqToPool( pCore, pDevice->Internal_Req );
+		pDevice->Internal_Req = NULL;
+	}
+
+	{
+		struct mod_notif_param param;
+		param.lo = pDevice->Id;
+#ifdef RAID_DRIVER
+		RAID_ModuleNotification(pUpperLayer, EVENT_DEVICE_REMOVAL, 
+					&param);
+#else
+		HBA_ModuleNotification(pUpperLayer, 
+				       EVENT_DEVICE_REMOVAL, 
+				       &param);
+#endif /* RAID_DRIVER */
+	}
+}
+
+extern MV_BOOLEAN mvDeviceStateMachine(
+	PCore_Driver_Extension pCore,
+	PDomain_Device pDevice
+	);
+
+void mvHandlePMPlugin (PCore_Driver_Extension pCore, PDomain_Device pDevice)
+{
+	PDomain_Port pPort = pDevice->PPort;
+
+	if( pCore->Total_Device_Count >= MAX_DEVICE_SUPPORTED )
+		return;
+
+	pDevice->Need_Notify = MV_TRUE;
+	pDevice->Device_Type = 0;
+	HBA_SleepMillisecond(pCore, 1000);
+	SATA_InitPMPort( pPort, pDevice->PM_Number );
+	mvDeviceStateMachine(pCore, pDevice);
+}
+#endif	/* #ifdef SUPPORT_PM */
+#endif	/* #ifdef SUPPORT_HOT_PLUG */
+
+void sata_hotplug(MV_PVOID data,MV_U32 intStatus)
+{
+#ifdef SUPPORT_HOT_PLUG
+	PDomain_Port pPort = (PDomain_Port)data;
+	PDomain_Device pDevice = &pPort->Device[0];
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	MV_U8 i, plugout=0, plugin=0;
+	MV_U32 temp;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_BOOLEAN valid;
+	MV_U32 hotPlugDevice = intStatus & PORT_IRQ_PHYRDY;
+	MV_U32 hotPlugPM = (intStatus & PORT_IRQ_ASYNC_NOTIF) || (intStatus & PORT_IRQ_SDB_FIS);
+
+	intStatus &= ~(PORT_IRQ_D2H_REG_FIS|PORT_IRQ_SDB_FIS|PORT_IRQ_PIO_DONE);
+#ifdef _OS_LINUX
+	/*fix Thor - Linux non-raid driver - hotplug 
+	Thor-Lite spec define bit25,26 as plug-out/plug-in irq status, Thor didn't define, but also will set these 
+	two bits when doing hot-plug. So clear them here if they're set.
+	If power is not stable, hot-plug will result to resetting port, meantime,PORT_IRQ_SIGNATURE_FIS will be set,
+	so also need clear it if it is set.*/
+	intStatus &= ~(PORT_IRQ_SIGNATURE_FIS|(1L<<26)|(1L<<25));
+#endif
+	/* if a hard drive or a PM is plugged in/out of the controller */
+	if( hotPlugDevice )
+	{
+		intStatus &= ~PORT_IRQ_PHYRDY;
+		/* use Phy status to determine if this is a plug in/plug out */
+		//hba_msleep(500);
+		HBA_SleepMillisecond(pCore, 500);
+		if ((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT) & 0xf) == 0)
+			plugout = MV_TRUE;
+		else
+			plugin = MV_TRUE;
+
+		/* following are special cases, so we take care of these first */
+		if( plugout )
+		{
+			if ( (pPort->Type != PORT_TYPE_PM ) && (pDevice->Status & DEVICE_STATUS_EXISTING) &&
+			     !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) )
+			{
+				/* a bad drive was unplugged */
+				pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+				MV_DPRINT(("bad drive was unplugged\n"));
+			}
+
+			if ( (pPort->Setting & PORT_SETTING_PM_EXISTING) && 
+			     !(pPort->Setting & PORT_SETTING_PM_FUNCTIONAL) )
+			{
+				/* a bad PM was unplugged */
+				pPort->Setting &= ~PORT_SETTING_PM_EXISTING;
+				MV_DPRINT(("bad PM was unplugged\n"));
+			}
+
+			mvHandleDeviceUnplug( pCore, pPort );
+			return;
+		}
+		
+		if ( ((pPort->Type == PORT_TYPE_PM) && (pPort->Setting & PORT_SETTING_PM_FUNCTIONAL)) ||
+		     ((pPort->Type != PORT_TYPE_PM) && (pDevice->Status & DEVICE_STATUS_FUNCTIONAL)) 
+			)
+		{
+			if( plugout ){
+				mvHandleDeviceUnplug( pCore, pPort );
+				return;
+			}
+		}
+		else
+		{
+			if( plugin ){
+				mvHandleDevicePlugin( pCore, pPort );
+				return;
+			}
+		}
+	}
+				
+	/* if a drive was plugged in/out of a PM */
+	if ( hotPlugPM ) 
+	{
+		intStatus &= ~PORT_IRQ_ASYNC_NOTIF;
+		intStatus &= ~PORT_IRQ_SDB_FIS;
+
+		valid = MV_FALSE;
+		do
+		{
+			mvPMDevReWrReg( pPort, MV_Read_Reg, MV_SATA_GSCR_ERROR_REG_NUM, 0, 0xF, MV_TRUE );
+			temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+			if ((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT)& 0xf) != 0x3)
+			{
+				mvHandleDeviceUnplug( pCore, pPort );
+				MV_DPRINT(("PM Lost connection 1\n"));
+				return;
+			}
+
+			if (((temp >> 16) & 0xF0) == 0xF0)
+				valid = MV_TRUE;
+              
+			temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+		} while (valid == MV_FALSE);
+
+		if (temp == 0)
+			return;
+
+		// better solution???
+		for (i=0; i<MAX_DEVICE_PER_PORT; i++)	
+		{
+			if( temp & MV_BIT(i) )
+			{
+				pDevice = &pPort->Device[i];
+				pDevice->PM_Number = i;
+				break;
+			}
+		}
+		
+		/* make sure it's a hot plug SDB */
+		valid = MV_FALSE;
+		do
+		{
+			mvPMDevReWrReg( pPort, MV_Read_Reg, MV_SATA_PSCR_SERROR_REG_NUM, 0, pDevice->PM_Number, MV_TRUE );
+			temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+			if ((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT)& 0xf) != 0x3)
+			{
+				mvHandleDeviceUnplug( pCore, pPort );
+				MV_DPRINT(("PM Lost connection 2\n"));
+				return;
+			}
+
+			if (((temp >> 16) & 0xF0) == 0xF0)
+				valid = MV_TRUE;
+              
+			temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+		} while (valid == MV_FALSE);
+
+		if( !( (temp & MV_BIT(16)) || (temp & MV_BIT(26)) ) )
+			return;
+
+		/* check phy status to determine plug in/plug out */
+		HBA_SleepMillisecond(pCore, 500);
+		//hba_msleep(500);
+
+		valid = MV_FALSE;
+		do
+		{
+			mvPMDevReWrReg(pPort, MV_Read_Reg, MV_SATA_PSCR_SSTATUS_REG_NUM, 0, pDevice->PM_Number, MV_TRUE);
+			temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+			if ((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT)& 0xf) != 0x3)
+			{
+				mvHandleDeviceUnplug( pCore, pPort );
+				MV_DPRINT(("PM Lost connection 3\n"));
+				return;
+			}
+
+			if (((temp >> 16) & 0xF0) == 0xF0)
+				valid = MV_TRUE;
+              
+			temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+		} while (valid == MV_FALSE);
+
+		if( (temp & 0xF) == 0 )
+		{
+			plugout = MV_TRUE;
+			MV_DPRINT(("PM port %d plugout\n", pDevice->PM_Number));
+		}
+		else
+		{
+			if ((temp & 0xF) == 3)
+			{
+			plugin = MV_TRUE;
+				MV_DPRINT(("PM port %d plugin\n", pDevice->PM_Number));
+			}
+			else
+			{
+				/*
+				On Sil3726, we'll see this condition.
+				Solution:
+				1. Unplug this unstable device.
+				2. Reset Channel, detect current devices to update status
+				*/
+				MV_DPRINT(("PM device connection not established, reset channel\n"));
+
+				mvHandlePMUnplug(pCore, pDevice);
+				Core_ResetChannel(pDevice,NULL);
+				return;
+			}
+		}
+
+		if ( plugout && (pDevice->Status & DEVICE_STATUS_EXISTING) &&
+			 !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) )
+		{
+			// a bad drive was unplugged
+			pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+
+			/* clear x bit */
+			valid = MV_FALSE;
+			do
+			{
+				mvPMDevReWrReg( pPort, MV_Read_Reg, MV_SATA_PSCR_SERROR_REG_NUM, 0, pDevice->PM_Number, MV_TRUE );
+				temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+				if ((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT)& 0xf) != 0x3)
+				{
+//					mvHandleDeviceUnplug( pCore, pPort );
+					MV_DPRINT(("PM Lost connection 5\n"));
+					return;
+				}
+
+				if (((temp >> 16) & 0xF0) == 0xF0)
+					valid = MV_TRUE;
+	              
+				temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+			} while (valid == MV_FALSE);
+
+			mvPMDevReWrReg( pPort, MV_Write_Reg, MV_SATA_PSCR_SERROR_REG_NUM, temp, pDevice->PM_Number, MV_TRUE);
+
+			MV_DPRINT(("bad drive was unplugged\n"));
+			mvHandlePMUnplug(pCore, pDevice);
+			return;
+		}
+
+		if( pDevice->Status & DEVICE_STATUS_FUNCTIONAL )
+		{
+			if (plugout)
+				mvHandlePMUnplug(pCore, pDevice);
+		}
+		else
+		{
+			if (plugin)
+				mvHandlePMPlugin( pCore, pDevice );
+		}
+	}
+#endif /* SUPPORT_HOT_PLUG */
+}
+#ifdef HOTPLUG_ISSUE_WORKROUND
+void mvHandleDeviceUnplugReset (MV_PVOID pport, MV_PVOID ptemp)
+{
+	
+	PDomain_Port pPort = (PDomain_Port)pport;
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PMV_Request pReq;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U8 i;
+	MV_U32 temp, temp2;
+	PDomain_Device pDevice = &pPort->Device[0];
+
+
+	MV_U32 SControl = MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);
+	SControl &= ~0x0000000F;    //Enable PHY
+	mvEnableIntr(portMmio, pPort->old_stat);
+	MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+	MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);	/* flush */
+	HBA_SleepMillisecond(pCore, 10);
+
+	MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+	MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);	/* flush */
+	HBA_SleepMillisecond(pCore, 10);
+
+    	pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+	MV_DPRINT(("######### ReEnable PHY&INT by Unplug Timer #########\n"));
+
+}
+#endif
+void SATA_HandleHotplugInterrupt(
+	IN PDomain_Port pPort,
+	IN MV_U32 intStatus
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	MV_U32 hotPlugDevice = intStatus & PORT_IRQ_PHYRDY;
+	MV_U32 hotPlugPM = (intStatus & PORT_IRQ_ASYNC_NOTIF) | (intStatus & PORT_IRQ_SDB_FIS);
+	struct mod_notif_param event_param;
+
+	#ifdef HOTPLUG_ISSUE_WORKROUND
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	PDomain_Device pDevice = &pPort->Device[0];
+	MV_U32 plugout=0,plugin=0;
+	#endif
+	if (hotPlugDevice | hotPlugPM) {
+		event_param.p_param = pPort;
+		event_param.event_id = intStatus;
+		#ifdef HOTPLUG_ISSUE_WORKROUND
+		HBA_SleepMillisecond(pCore, 500);
+		if ((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT) & 0xf) == 0)
+			plugout= MV_TRUE;
+		else
+			plugin= MV_TRUE;
+		
+		/* following are special cases, so we take care of these first */
+		if( plugout )
+		{
+			
+			if ( (pPort->Type != PORT_TYPE_PM ) && (pDevice->Status & DEVICE_STATUS_EXISTING) &&
+			     !(pDevice->Status & DEVICE_STATUS_FUNCTIONAL) )
+			{
+				/* a bad drive was unplugged */
+				pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+				MV_DPRINT(("bad drive was unplugged\n"));
+			}
+
+			if ( (pPort->Setting & PORT_SETTING_PM_EXISTING) && 
+			     !(pPort->Setting & PORT_SETTING_PM_FUNCTIONAL) )
+			{
+				/* a bad PM was unplugged */
+				pPort->Setting &= ~PORT_SETTING_PM_EXISTING;
+				MV_DPRINT(("bad PM was unplugged\n"));
+			}
+
+			mvHandleDeviceUnplug( pCore, pPort );
+			return;
+		}
+		
+		if ( ((pPort->Type == PORT_TYPE_PM) && (pPort->Setting & PORT_SETTING_PM_FUNCTIONAL)) ||
+		     ((pPort->Type != PORT_TYPE_PM) && (pDevice->Status & DEVICE_STATUS_FUNCTIONAL)) 
+			)
+		{
+			if(plugout ){
+				mvHandleDeviceUnplug( pCore, pPort );
+				return;
+			}
+		}	
+		if(plugin)
+		#endif
+			HBA_ModuleNotification(pCore, EVENT_HOT_PLUG, &event_param);
+	}
+
+	if (intStatus) {
+		MV_DPRINT(("Error: port=%d intStatus=0x%x.\n", pPort->Id, intStatus));
+		/* clear global before channel */
+		MV_REG_WRITE_DWORD(pCore->Mmio_Base, HOST_IRQ_STAT, (1L<<pPort->Id));
+		intStatus = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_IRQ_STAT);
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_IRQ_STAT, intStatus);
+	}
+}
+
+void mvCompleteSlots( PDomain_Port pPort, MV_U32 completeSlot, PATA_TaskFile taskFiles )
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+#ifdef MV_DEBUG
+	MV_LPVOID port_mmio = pPort->Mmio_Base;
+#endif
+	PDomain_Device pDevice;
+	PMV_Request pReq = NULL, pOrgReq = NULL;
+	MV_U8 slotId;
+
+	/* Complete finished commands. All of them are finished successfully.
+	 * There are three situations code will come here.
+	 * 1. No error for both NCQ and Non-NCQ.
+	 * 2. Under NCQ, some requests are completed successfully. At lease one is not.
+	 *	For the error command, by specification, SActive isn't cleared.
+	 * 3. Under non-NCQ, since no interrupt coalescing, no succesful request. 
+	 *  Hardware will return one request is completed. But software clears it above. */
+
+	for ( slotId=0; slotId<MAX_SLOT_NUMBER; slotId++ )
+	{
+		if ( !(completeSlot&(1L<<slotId)) )
+			continue;
+
+		MV_DASSERT( (MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE)&(1<<slotId))==0 );
+		MV_DASSERT( (MV_REG_READ_DWORD(port_mmio, PORT_SCR_ACT)&(1<<slotId))==0 );
+
+		completeSlot &= ~(1L<<slotId);
+				
+		/* This slot is finished. */
+		pReq = pPort->Running_Req[slotId];
+		MV_DASSERT( pReq );
+		pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+
+		if ( pReq->Scsi_Status==REQ_STATUS_RETRY )
+		{
+			MV_PRINT("Retried request[0x%p] is finished on port[%d]\n", pReq, pPort->Id);
+			MV_DumpRequest(pReq, MV_FALSE);
+		}
+	
+		if ( Core_IsInternalRequest(pCore, pReq)&&(pReq->Org_Req) )
+		{
+			/* This internal request is used to request sense. */
+			MV_ASSERT( pDevice->Device_Type&DEVICE_TYPE_ATAPI );
+			pOrgReq = pReq->Org_Req;
+			/* Copy sense from the scratch buffer to the request sense buffer. */
+			MV_CopyMemory(
+					pOrgReq->Sense_Info_Buffer,
+					pReq->Data_Buffer,
+					MV_MIN(pOrgReq->Sense_Info_Buffer_Length, pReq->Data_Transfer_Length)
+					);
+			pOrgReq->Scsi_Status = REQ_STATUS_HAS_SENSE;
+#if defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX)
+			/* remove internal req's timer */
+			hba_remove_timer(pReq);
+#endif
+			pReq = pOrgReq;
+		}
+		else
+		{
+			pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+		}
+
+		CompleteRequestAndSlot(pCore, pPort, pReq, taskFiles, slotId);
+
+		if ( completeSlot==0 )
+			break;
+	}
+}
+
+void SATA_PortHandleInterrupt(
+	IN PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort
+	)
+{
+	PDomain_Device pDevice = &pPort->Device[0];
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_LPVOID port_mmio = pPort->Mmio_Base;
+	MV_U32 orgIntStatus, intStatus, serialError, commandIssue, serialActive, temp;
+	PMV_Request pReq = NULL, pOrgReq = NULL;
+	MV_U32 completeSlot = 0;
+	MV_U16 slotId;
+	MV_U8 i,j;
+	MV_BOOLEAN hasError = MV_FALSE, finalError = MV_FALSE,reset_port=MV_FALSE;
+	MV_U32 errorSlot = 0;
+	ATA_TaskFile	taskFiles;
+#ifdef MV_DEBUG
+	MV_U32 orgSerialError, orgCommandIssue, orgSerialActive, orgCompleteSlot, orgRunningSlot;
+#endif
+
+#ifdef SUPPORT_SCSI_PASSTHROUGH
+	readTaskFiles(pPort, pDevice, &taskFiles);
+#endif
+
+
+	/* Read port interrupt status register */
+	orgIntStatus = MV_REG_READ_DWORD(port_mmio, PORT_IRQ_STAT);
+	intStatus = orgIntStatus;
+
+	if ( pPort->Setting&PORT_SETTING_NCQ_RUNNING )
+	{
+		serialActive = MV_REG_READ_DWORD(port_mmio, PORT_SCR_ACT);
+		completeSlot =  (~serialActive) & pPort->Running_Slot;
+	}
+	else
+	{
+		commandIssue = MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE);
+		completeSlot = (~commandIssue) & pPort->Running_Slot;
+	}
+
+#ifdef MV_DEBUG
+	orgCommandIssue = commandIssue;
+	orgSerialActive = serialActive;
+	orgCompleteSlot = completeSlot;
+	orgRunningSlot = pPort->Running_Slot;
+#endif
+
+	intStatus &= ~(PORT_IRQ_D2H_REG_FIS|PORT_IRQ_SDB_FIS|PORT_IRQ_PIO_DONE);	/* Used to check request is done. */
+	intStatus &= ~(PORT_IRQ_DMAS_FIS|PORT_IRQ_PIOS_FIS);						/* Needn't care. */
+
+	/* Error handling */
+	if ( 
+			(intStatus&PORT_IRQ_TF_ERR)
+		||	(intStatus&PORT_IRQ_LINK_RECEIVE_ERROR)
+		||	(intStatus&PORT_IRQ_LINK_TRANSMIT_ERROR)
+		)
+	{
+		MV_DPRINT(("Interrupt Error: 0x%x orgIntStatus: 0x%x completeSlot=0x%x on port[%d].\n", 
+			intStatus, orgIntStatus, completeSlot, pPort->Id));
+		mv_core_dump_reg( pPort);
+		//if (intStatus&PORT_IRQ_TF_ERR)
+		{
+			/* Don't do error handling when receive link error. 
+			 * Wait until we got the Task File Error */
+
+			/* read serial error only when there is error */
+			serialError = MV_REG_READ_DWORD(port_mmio, PORT_SCR_ERR);
+			MV_REG_WRITE_DWORD(port_mmio, PORT_SCR_ERR, serialError);
+
+			/* Handle serial error interrupt */
+			if ( serialError )
+			{
+				SATA_HandleSerialError(pPort, serialError); 
+			}
+
+#ifdef MV_DEBUG
+			orgSerialError = serialError;
+#endif
+
+			/* read errorSlot only when there is error */
+			errorSlot = MV_REG_READ_DWORD(port_mmio, PORT_CMD);
+
+			hasError = MV_TRUE;
+			errorSlot = (errorSlot>>8)&0x1F;
+
+			if ( pPort->Setting&PORT_SETTING_DURING_RETRY ){
+				pPort->Setting &= ~PORT_SETTING_DURING_RETRY;
+				MV_DPRINT(("Start reset port[%d], reset time=%d.\n",pPort->Id, pPort->reset_hba_times));
+				if(pPort->reset_hba_times < MAX_RESET_TIMES)
+					reset_port = MV_TRUE;
+				else
+					finalError = MV_TRUE;
+					
+			}
+			else
+			{
+				/* if the error request is any internal requests, we don't retry 
+				 *     1) read log ext - don't retry
+				 *	   2) any initialization requests such as identify - buffer
+				 *		  will conflict when we try to send read log ext to retry
+				 *	   3) request sense - included in the ATAPI condition below
+				 */
+				pReq = pPort->Running_Req[errorSlot];
+				//if ( pReq != NULL && Core_IsInternalRequest(pCore, pReq) )
+				//	finalError = MV_TRUE;
+
+				/* For ATAPI device, we don't do retry. OS already has done a lot.
+				* ATAPI device: one request at a time. */
+				if ( completeSlot==((MV_U32)1L<<errorSlot) )
+				{
+					pReq = pPort->Running_Req[errorSlot];
+					MV_ASSERT( pReq!=NULL );
+					pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+					if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+						finalError = MV_TRUE;
+				} else{
+					MV_U32 slotId=0;
+					for ( slotId=0; slotId<MAX_SLOT_NUMBER; slotId++ )
+					{
+						if ( !(completeSlot&(1L<<slotId)) )
+							continue;	
+						pReq = pPort->Running_Req[slotId];
+						MV_ASSERT( pReq!=NULL );
+						pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+						if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI ){
+							if(!(MV_REG_READ_DWORD(mmio,PORT_TFDATA)&0x01)){
+								hasError = MV_FALSE;
+							}
+						}else{
+							printk("has error is true\n");
+							}
+					}	 
+				}
+			#ifdef SUPPORT_ATA_SECURITY_CMD
+				if(intStatus&PORT_IRQ_TF_ERR){
+					
+					if((MV_REG_READ_DWORD(port_mmio, PORT_TFDATA)&0x451) && pReq){
+												
+						MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+						MV_REG_WRITE_DWORD(port_mmio, PORT_IRQ_STAT, orgIntStatus);
+
+						intStatus &= ~(PORT_IRQ_TF_ERR|PORT_IRQ_LINK_RECEIVE_ERROR|PORT_IRQ_LINK_TRANSMIT_ERROR);		
+
+						pReq->Scsi_Status=REQ_STATUS_ABORT;
+						CompleteRequestAndSlot(pCore, pPort, pReq, &taskFiles, (MV_U8)errorSlot);
+						return;
+						}
+					}
+			#endif
+			}
+		}
+		intStatus &= ~(PORT_IRQ_TF_ERR|PORT_IRQ_LINK_RECEIVE_ERROR|PORT_IRQ_LINK_TRANSMIT_ERROR);		
+	}
+
+	/* If NO device ,then only handle hotplug Interrupt. */
+	if((pPort->Type != PORT_TYPE_PM) && (pDevice->Status & DEVICE_STATUS_NO_DEVICE))
+	{
+		SATA_HandleHotplugInterrupt(pPort, intStatus);
+		return;
+	}
+
+	/* Final Error: we give up this error request. Only one request is running. 
+	 * And during retry we won't use NCQ command. */
+	if ( finalError )
+	{
+		MV_DPRINT(("Final error, abort port[%d],running slot=0x%x.\n", pPort->Id,pPort->Running_Slot));
+		MV_ASSERT( !(pPort->Setting&PORT_SETTING_NCQ_RUNNING) );
+//		MV_DASSERT( completeSlot==((MV_U32)1L<<errorSlot) );
+		MV_DASSERT( pPort->Running_Slot==completeSlot );
+
+		/* clear global before channel */
+		MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+		MV_REG_WRITE_DWORD(port_mmio, PORT_IRQ_STAT, orgIntStatus);
+
+
+		/* This is the failed request. */
+		pReq = pPort->Running_Req[errorSlot];
+		if((!errorSlot)&&(!pReq)&&(pPort->Setting&PORT_SETTING_DURING_RETRY)){
+			for(errorSlot=0;errorSlot<32;errorSlot++){
+				if((pPort->Running_Slot>>errorSlot)&0x01)
+					break;
+			}
+			pReq = pPort->Running_Req[errorSlot];
+		}
+	
+		MV_ASSERT( pReq!=NULL );
+		pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+
+		if( Core_IsInternalRequest(pCore, pReq) )
+		{
+			if( pReq->Org_Req )
+			{
+				/* This internal request is used to request sense. */
+				MV_ASSERT( pDevice->Device_Type&DEVICE_TYPE_ATAPI );
+				pOrgReq = pReq->Org_Req;
+				pOrgReq->Scsi_Status = REQ_STATUS_ERROR;
+#ifdef _OS_LINUX
+				/* remove internal req's timer */
+				hba_remove_timer(pReq);
+#endif
+				pReq = pOrgReq;
+			}
+			else if( pReq->Cdb[2] == CDB_CORE_READ_LOG_EXT )
+			{
+				pReq->Scsi_Status = REQ_STATUS_ERROR;
+			}
+			else
+			{
+				/* This internal request is initialization request like identify */
+				MV_DASSERT( pDevice->State != DEVICE_STATE_INIT_DONE );
+				pReq->Scsi_Status = REQ_STATUS_ERROR;
+			}
+		}
+		else
+		{
+			if ( pReq->Cmd_Flag&CMD_FLAG_PACKET )
+			{
+				pReq->Scsi_Status = REQ_STATUS_REQUEST_SENSE;
+			}
+			else
+			{
+				MV_DPRINT(("Finally SATA error for Req 0x%x.\n", pReq->Cdb[0]));
+				pReq->Scsi_Status = REQ_STATUS_ERROR;
+			}
+		}
+
+		CompleteRequestAndSlot(pCore, pPort, pReq, &taskFiles, (MV_U8)errorSlot);
+
+		/* Handle interrupt status register */
+		if ( intStatus )
+		{
+			SATA_HandleHotplugInterrupt(pPort, intStatus);
+		}
+
+		if(!(pDevice->Device_Type&DEVICE_TYPE_ATAPI))
+			SATA_PortReportNoDevice(pCore, pPort);
+
+		return;
+	}
+
+
+	/* The Second time to hit the error.  */
+	if ( reset_port){
+		MV_DPRINT(("retry request failed, try reset HBA for port[%d], running slot=0x%x.\n", pPort->Id, pPort->Running_Slot));
+//		mv_core_dump_reg(pPort);
+		/* Toggle the port start bit to clear up the hardware to prepare for the retry. */
+		temp = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_CMD);
+		temp &= ~PORT_CMD_START;
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_CMD, temp );
+		HBA_SleepMillisecond(pCore, 1);
+		temp |= PORT_CMD_START;
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_CMD, temp );
+		HBA_SleepMillisecond(pCore, 100);
+
+		/* Toggle should before we clear the channel interrupt status but not the global interrupt. */
+		MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+
+		MV_DASSERT( MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE)==0 );
+		MV_DASSERT( MV_REG_READ_DWORD(port_mmio, PORT_IRQ_STAT)==0 );
+		//MV_DASSERT( orgIntStatus == 0 );
+		MV_DASSERT( (MV_REG_READ_DWORD(mmio, HOST_IRQ_STAT)&(1L<<pPort->Id))==0 );
+		pPort->Hot_Plug_Timer = 0;
+		pPort->timer_para = pDevice;
+		pPort->command_callback = Core_ResetChannel_BH;
+		//Reset the device.
+		pCore->Total_Device_Count--;
+		pPort->error_state = PORT_ERROR_AT_RUNTIME;
+		mv_core_reset_command(pPort);
+		return;
+	}
+
+	/* The first time to hit the error. Under error condition, figure out all the successful requests. */
+	if ( hasError )
+	{
+		MV_DPRINT(("Has error, reset port[%d], running slot=0x%x.\n", pPort->Id, pPort->Running_Slot));
+		MV_ASSERT( !finalError );
+		if ( pPort->Setting&PORT_SETTING_NCQ_RUNNING )
+		{
+			/* For NCQ command, if error happens on one slot.
+			 * This slot is not completed. SActive is not cleared. */
+		}
+		else
+		{
+			/* For Non-NCQ command, last command is the error command. 
+			 * ASIC will stop whenever there is an error.
+			 * And we only have one request if there is no interrupt coalescing or NCQ. */
+			//MV_DASSERT( completeSlot==((MV_U32)1L<<errorSlot) );
+
+			/* The error command is finished but we clear it to make it to be retried. */
+			completeSlot=0;
+		}
+		/* Now all the completed commands are completed successfully. */
+
+		/* Reset this port to prepare for the retry. At least one request will be retried. */
+
+		MV_ASSERT( finalError==MV_FALSE );
+
+		/* Toggle the port start bit to clear up the hardware to prepare for the retry. */
+		temp = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_CMD);
+		temp &= ~PORT_CMD_START;
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_CMD, temp );
+		HBA_SleepMillisecond(pCore, 1);
+		temp |= PORT_CMD_START;
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_CMD, temp );
+		HBA_SleepMillisecond(pCore, 1);
+		/* Toggle should before we clear the channel interrupt status but not the global interrupt. */
+		MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+				
+		if(pPort->Type==PORT_TYPE_SATA){
+			//MV_DPRINT(("***pPort->Running_Slot=0x%x pDevice.Outstanding_Req=%d***\n", pPort->Running_Slot, pPort->Device[0].Outstanding_Req));
+		}
+
+		/* Abort all the others requests and retry. */
+		for ( slotId=0; slotId<MAX_SLOT_NUMBER; slotId++ )
+		{
+			pReq = pPort->Running_Req[slotId];
+			if ( !(completeSlot&(1L<<slotId)) && pReq )
+			{
+				pReq->Cmd_Flag &= 0xFF;	/* Remove NCQ setting. */
+				pReq->Scsi_Status = REQ_STATUS_RETRY;
+
+				/* Put requests to the queue head but don't run them. Should run ReadLogExt first. */
+				mv_core_reset_running_slot(pPort, slotId);
+#ifdef _OS_LINUX
+				pReq->eh_flag = 1;
+				hba_remove_timer(pReq);
+#endif
+				List_Add(&pReq->Queue_Pointer, &pCore->Waiting_List);		/* Add to the header. */
+
+				if (pPort->Type==PORT_TYPE_SATA){
+					pPort->Device[0].Outstanding_Req--;
+				}else {//PM case					
+					for (j=0; j<MAX_DEVICE_PER_PORT; j++){
+						if (pPort->Device[j].Id == pReq->Device_Id){
+							pPort->Device[j].Outstanding_Req--;
+							break;
+						}
+					}//end of for
+					MV_DASSERT(j==MAX_DEVICE_PER_PORT);					
+				}
+
+				//MV_PRINT("Abort error requests....\n");
+				//MV_DumpRequest(pReq, MV_FALSE);
+			}
+		}
+
+#ifdef SUPPORT_TIMER 
+		if(pPort->Type==PORT_TYPE_SATA)
+		{
+			MV_DASSERT(pPort->Running_Slot==0);
+			MV_DASSERT(pPort->Device[0].Outstanding_Req==0);
+
+			if( pPort->Device[0].Timer_ID != NO_CURRENT_TIMER )
+			{
+				Timer_CancelRequest( pCore, pPort->Device[0].Timer_ID );
+				pPort->Device[0].Timer_ID = NO_CURRENT_TIMER;
+				
+			}		
+		}else {//PM case
+			MV_DASSERT(pPort->Type==PORT_TYPE_PM);
+			MV_DASSERT(pPort->Running_Slot==0);
+			for (j=0; j<MAX_DEVICE_PER_PORT; j++){					
+				MV_DASSERT(pPort->Device[j].Outstanding_Req==0);
+				if( pPort->Device[j].Timer_ID != NO_CURRENT_TIMER )
+				{
+					Timer_CancelRequest( pCore, pPort->Device[j].Timer_ID );
+					pPort->Device[j].Timer_ID = NO_CURRENT_TIMER;
+				
+				}	
+			}
+		}
+#endif /* SUPPORT_TIMER */
+
+		MV_DASSERT( MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE)==0 );
+		MV_DASSERT( MV_REG_READ_DWORD(port_mmio, PORT_IRQ_STAT)==0 );
+		//MV_DASSERT( orgIntStatus == 0 );
+		MV_DASSERT( (MV_REG_READ_DWORD(mmio, HOST_IRQ_STAT)&(1L<<pPort->Id))==0 );
+
+		/* Send ReadLogExt command to clear the outstanding commands on the device. 
+		 * This request will be put to the queue head because it's Cmd_Initiator is Core Driver. 
+		 * Consider the port multiplier. */
+		for ( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+		{
+			pDevice = &pPort->Device[i];
+			if ( 
+				!(pDevice->Device_Type&DEVICE_TYPE_ATAPI)
+				&& (pDevice->Capacity&DEVICE_CAPACITY_READLOGEXT_SUPPORTED)
+				&& (pPort->Setting&PORT_SETTING_NCQ_RUNNING)
+				)
+			{
+				if(pDevice->Internal_Req){
+					Device_IssueReadLogExt(pPort, pDevice);
+				} else {
+					Core_ResetChannel(pDevice,NULL);
+					return;
+				}
+			}
+			else
+			{
+				Core_HandleWaitingList(pCore);	
+			}
+		}
+
+		/* Needn't run interrupt_handle_bottom_half except the hot plug.
+		 * Toggle start bit will clear all the interrupt. So don't clear interrupt again. 
+		 * Otherwise it'll clear Read Log Ext interrupt. 
+		 * If Device_IssueReadLogExt is called, needn't run Core_HandleWaitingList. */
+		
+	}
+
+
+	/* clear global before channel */
+	MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+	MV_REG_WRITE_DWORD(port_mmio, PORT_IRQ_STAT, orgIntStatus);
+
+	/* handle completed slots */
+	if( completeSlot )
+		mvCompleteSlots( pPort, completeSlot, &taskFiles );
+
+	/* Handle interrupt status register */
+	if ( intStatus )
+	{
+		SATA_HandleHotplugInterrupt(pPort, intStatus);
+	}
+}
+
+void PATA_PortHandleInterrupt(
+	IN PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort
+	)
+{
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_LPVOID port_mmio = pPort->Mmio_Base;
+	MV_U32 intStatus, orgIntStatus, commandIssue, taskFile=0, stateMachine, portCommand;
+	MV_U32 temp;
+	PMV_Request pReq = NULL, pOrgReq = NULL;
+	MV_U32 completeSlot = 0;
+	MV_U16 slotId = 0;
+	MV_BOOLEAN hasOneAlready = MV_FALSE;
+	MV_BOOLEAN hasError = MV_FALSE, needReset = MV_FALSE;
+	PDomain_Device pDevice=NULL;
+	ATA_TaskFile	taskFiles;
+    	
+	/* Read port interrupt status register */
+	intStatus = MV_REG_READ_DWORD(port_mmio, PORT_IRQ_STAT);
+	orgIntStatus = intStatus;
+
+	/* 
+	 * Workaround for PATA non-data command.
+	 * PATA non-data command, CI is not ready yet when interrupt is triggered.
+	 */
+	commandIssue = MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE);
+	completeSlot = (~commandIssue) & pPort->Running_Slot;
+
+/* Thor Lite D0 and Thor B0 */
+//if ( (pCore->Device_Id!=DEVICE_ID_THOR_4S1P_NEW) && (pCore->Revision_Id!=0xB0) && (pCore->Revision_Id!=0xB1) && (pCore->Revision_Id!=0xB2) )
+if ( (pCore->Device_Id!=DEVICE_ID_THOR_4S1P_NEW) && (pCore->Revision_Id<0xB0) )
+{
+	temp=1000;
+	while ( (completeSlot==0) && (temp>0) )
+	{
+		HBA_SleepMillisecond(pCore, 2);
+		commandIssue = MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE);
+		completeSlot = (~commandIssue) & pPort->Running_Slot;
+		temp--;
+	}
+
+	if ( (completeSlot==0)&&(pPort->Running_Slot!=0) )
+	{
+		MV_DPRINT(("INT but no request completed: 0x%x CI: 0x%x Running: 0x%x\n", 
+			intStatus, commandIssue, pPort->Running_Slot));
+		/*
+		 * Workaround:
+		 * If ATAPI read abort happens, got one interrupt but CI is not cleared.
+		 */
+		stateMachine = MV_REG_READ_DWORD(port_mmio, PORT_INTERNAL_STATE_MACHINE);
+		if ( stateMachine==0x60007013 )
+		{
+            		pCore->Need_Reset = 1;
+			needReset = MV_TRUE;
+
+			/* Actually one request is finished. We need figure out which one it is. */
+			portCommand = MV_REG_READ_DWORD(port_mmio, PORT_CMD);
+			MV_DASSERT( portCommand&MV_BIT(15) );	/* Command is still running */
+			portCommand = (portCommand>>8)&0x1F;
+			MV_ASSERT( portCommand<MAX_SLOT_NUMBER );
+			MV_DPRINT(("Read abort happens on slot %d.\n", portCommand));
+			completeSlot |= (1<<portCommand);
+		}
+	}
+}
+
+	/* Handle interrupt status register */
+	intStatus &= ~MV_BIT(0); intStatus &= ~MV_BIT(2);
+#ifdef ENABLE_PATA_ERROR_INTERRUPT
+	hasError = (intStatus!=0) ? MV_TRUE : MV_FALSE;
+
+	/*
+	 * Workaround:
+	 * If error interrupt bit is set. We cannot clear it.
+	 * Try to use PORT_CMD PORT_CMD_PATA_START bit to clear the error interrupt but didn't work.
+	 * So we have to disable PATA error interrupt.
+	 */
+#endif
+
+	/* Complete finished commands */
+	for ( slotId=0; slotId<MAX_SLOT_NUMBER; slotId++ )
+	{
+
+		if ( !(completeSlot&(1L<<slotId)) )
+			continue;
+
+		completeSlot &= ~(1L<<slotId);
+		MV_DASSERT( completeSlot==0 );	
+
+		/* This slot is finished. */
+		pReq = pPort->Running_Req[slotId];
+		MV_DASSERT(pReq);
+
+#if defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX)
+		hba_remove_timer(pReq);
+#endif /* defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX) */
+		mv_core_reset_running_slot(pPort, slotId);
+		MV_DASSERT( (MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_CMD_ISSUE)&(1<<slotId))==0 );
+
+		pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+
+	#ifndef ENABLE_PATA_ERROR_INTERRUPT
+		/* 
+ 		 * Workaround:
+ 		 * Sometimes we got error interrupt bit but the status is still 0x50.
+		 * In this case, the command is completed without error.
+		 * So we have to check the task status to make sure it's really an error or not.
+		 */
+		HBA_SleepMicrosecond(pCore, 2);
+		if ( !pDevice->Is_Slave )
+			taskFile = MV_REG_READ_DWORD(port_mmio, PORT_MASTER_TF0);
+		else
+			taskFile = MV_REG_READ_DWORD(port_mmio, PORT_SLAVE_TF0);
+
+
+		if ( taskFile&MV_BIT(0) )
+		{
+			hasError = MV_TRUE;
+			MV_DPRINT(("PATA request returns with error 0x%x.\n", taskFile));
+		}
+
+		#ifdef MV_DEBUG
+		if ( !(taskFile&MV_BIT(0)) && ( intStatus ) )
+		{
+			MV_DPRINT(("Error interrupt is set but status is 0x50.\n"));
+		
+		}
+		#endif
+	#endif
+
+		//if ( (hasError)&&(pCore->Device_Id!=DEVICE_ID_THOR_4S1P_NEW)&&(pCore->Revision_Id!=0xB0)&&(pCore->Revision_Id!=0xB1)&&(pCore->Revision_Id!=0xB2) )
+		if ( (hasError)&&(pCore->Device_Id!=DEVICE_ID_THOR_4S1P_NEW)&&(pCore->Revision_Id<0xB0) )
+		{
+
+			if ( pDevice->Device_Type==DEVICE_TYPE_ATAPI )
+			{
+				/*
+				 * Workaround: 
+				 * Write request if device abort, hardware state machine got wrong.
+				 * Need do reset to recover.
+				 * If the error register is 0x40, we think the error happens.
+			 	 * Suppose this problem only happens on ODD. HDD won't write abort.
+ 				 */
+
+				taskFile = taskFile>>24;  /* Get the error register */
+				if ( taskFile==0x40 )	
+				{
+					pCore->Need_Reset = 1;
+					needReset = MV_TRUE;
+				}
+			}
+		}
+		if ( Core_IsInternalRequest(pCore, pReq)&&(pReq->Org_Req) )
+		{
+			/* This internal request is used to request sense. */
+			pOrgReq = pReq->Org_Req;
+			if ( hasError )
+			{
+				MV_ASSERT( hasOneAlready==MV_FALSE );
+				hasOneAlready = MV_TRUE;
+				pOrgReq->Scsi_Status = REQ_STATUS_ERROR;
+			}
+			else
+			{
+				/* Copy sense from the scratch buffer to the request sense buffer. */
+				MV_CopyMemory(
+						pOrgReq->Sense_Info_Buffer,
+						pReq->Data_Buffer,
+						MV_MIN(pOrgReq->Sense_Info_Buffer_Length, pReq->Data_Transfer_Length)
+						);
+				pOrgReq->Scsi_Status = REQ_STATUS_HAS_SENSE;
+			}
+			pReq = pOrgReq;
+		}
+		else
+	
+		{
+			if ( hasError )
+			{
+
+				MV_ASSERT( hasOneAlready==MV_FALSE );
+				hasOneAlready = MV_TRUE;
+
+				if ( needReset )
+				{
+					/* Get sense data using legacy mode or fake a sense data here. */
+					PATA_LegacyPollSenseData(pCore, pReq);
+					pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;
+				}
+				else
+				{
+					if ( pReq->Cmd_Flag&CMD_FLAG_PACKET )
+						pReq->Scsi_Status = REQ_STATUS_REQUEST_SENSE;
+					else
+						pReq->Scsi_Status = REQ_STATUS_ERROR;
+				}
+			}
+			else
+			{
+				pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+
+			}
+		}
+
+#ifdef SUPPORT_SCSI_PASSTHROUGH
+		readTaskFiles(pPort, pDevice, &taskFiles);
+#endif
+
+		pDevice->Outstanding_Req--;
+#ifdef SUPPORT_ERROR_HANDLING
+#ifdef SUPPORT_TIMER
+		/* request for this device came back, so we cancel the timer */
+		Timer_CancelRequest( pCore, pDevice->Timer_ID );
+		pDevice->Timer_ID = NO_CURRENT_TIMER;
+
+		/* if there are more outstanding requests, we send a new timer */
+		if ( pDevice->Outstanding_Req > 0 )
+		{
+			pDevice->Timer_ID = Timer_AddRequest( pCore, REQUEST_TIME_OUT, Core_ResetChannel, pDevice, NULL );
+		}
+#endif /* SUPPORT_TIMER */
+#endif /* SUPPORT_ERROR_HANDLING */
+
+		CompleteRequest(pCore, pReq, &taskFiles);  
+
+		if ( completeSlot==0 )
+			break;
+	}
+
+	/* 
+	 * Clear the interrupt. It'll re-start the hardware to handle the next slot. 
+	 * I clear the interrupt after I've checked the CI register.
+	 * Currently we handle one request everytime in case if there is an error I don't know which one it is.
+	 */
+	MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+	MV_REG_WRITE_DWORD(port_mmio, PORT_IRQ_STAT, orgIntStatus);
+
+	
+	/* If there is more requests on the slot, we have to push back there request. */
+	if ( needReset )
+	{
+		for ( slotId=0; slotId<MAX_SLOT_NUMBER; slotId++ )
+		{
+			pReq = pPort->Running_Req[slotId];
+			if ( pReq )
+			{
+				List_Add(&pReq->Queue_Pointer, &pCore->Waiting_List);
+				mv_core_reset_running_slot(pPort, slotId);
+			}
+		}
+		MV_DASSERT(pPort->Running_Slot == 0);
+	}
+}
+
+void Device_MakeRequestSenseRequest(
+	IN PCore_Driver_Extension pCore,
+	IN PDomain_Device pDevice,
+	IN PMV_Request pNewReq,
+	IN PMV_Request pOrgReq
+	)
+{
+	PMV_SG_Table pSGTable = &pNewReq->SG_Table;
+	//MV_U8 senseSize = SATA_SCRATCH_BUFFER_SIZE;
+	MV_U8 senseSize = 18;
+	
+	MV_ZeroMvRequest(pNewReq);
+
+	pNewReq->Device_Id = pDevice->Id;
+
+	pNewReq->Scsi_Status = REQ_STATUS_PENDING;
+	pNewReq->Cmd_Initiator = pCore;
+
+	pNewReq->Data_Transfer_Length = senseSize;
+	pNewReq->Data_Buffer = pDevice->Scratch_Buffer;
+
+	pNewReq->Org_Req = pOrgReq;
+
+	pNewReq->Cmd_Flag = CMD_FLAG_DATA_IN;
+#ifdef USE_DMA_FOR_ALL_PACKET_COMMAND	
+	pNewReq->Cmd_Flag |=CMD_FLAG_DMA;
+#endif
+
+	pNewReq->Completion = NULL;
+
+	/* Make the SG table. */
+	SGTable_Init(pSGTable, 0);
+	SGTable_Append(
+		pSGTable, 
+		pDevice->Scratch_Buffer_DMA.parts.low,
+		pDevice->Scratch_Buffer_DMA.parts.high,
+		senseSize
+		);
+	MV_DASSERT( senseSize%2==0 );
+
+	/* Request Sense request */
+	pNewReq->Cdb[0]=SCSI_CMD_REQUEST_SENSE;
+	pNewReq->Cdb[4]=senseSize;
+
+	/* Fixed sense data format is 18 bytes. */
+	MV_ZeroMemory(pNewReq->Data_Buffer, senseSize);
+}
+
+void CompleteRequest(
+	IN PCore_Driver_Extension pCore,
+	IN PMV_Request pReq,
+	IN PATA_TaskFile pTaskFile
+	)
+{
+#ifdef SUPPORT_SCSI_PASSTHROUGH
+	PHD_Status pHDStatus;
+#endif
+	PDomain_Port pPort = &pCore->Ports[PATA_MapPortId(pReq->Device_Id)];
+	PDomain_Device pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+
+	//Some of the command, we need read the received FIS like smart command.
+
+	if(pReq->Splited_Count)
+	{
+		MV_DASSERT( pReq->Cdb[0]==SCSI_CMD_VERIFY_10 );
+		if(pReq->Scsi_Status == REQ_STATUS_SUCCESS)
+		{
+			MV_U32 sectors;
+			MV_LBA lba;
+			
+			pReq->Splited_Count--;
+
+			lba.value = SCSI_CDB10_GET_LBA(pReq->Cdb) + MV_MAX_TRANSFER_SECTOR;
+			sectors = MV_MAX_TRANSFER_SECTOR;
+			SCSI_CDB10_SET_LBA(pReq->Cdb, lba.value);
+			SCSI_CDB10_SET_SECTOR(pReq->Cdb, sectors);
+
+			pReq->Scsi_Status = REQ_STATUS_PENDING;
+
+			Core_ModuleSendRequest(pCore, pReq);
+
+			return;
+		}
+		else
+			pReq->Splited_Count = 0;
+	}
+
+#if defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX)
+	hba_remove_timer(pReq);
+#endif /* defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX) */	
+
+	if ( pReq->Scsi_Status==REQ_STATUS_REQUEST_SENSE )
+	{
+		/* Use the internal request to request sense. */
+		Device_MakeRequestSenseRequest(pCore, pDevice, pDevice->Internal_Req, pReq);
+		/* pReq is linked to the */
+		Core_ModuleSendRequest(pCore, pDevice->Internal_Req);
+
+		return;
+	}
+
+
+#ifdef SUPPORT_SCSI_PASSTHROUGH
+	if (pTaskFile != NULL)
+	{
+		if (pReq->Scsi_Status == REQ_STATUS_SUCCESS)
+		{
+			if (pReq->Cdb[0] == SCSI_CMD_MARVELL_SPECIFIC && pReq->Cdb[1] == CDB_CORE_MODULE)
+			{
+				if (pReq->Cdb[2] == CDB_CORE_DISABLE_WRITE_CACHE)
+					pDevice->Setting &= ~DEVICE_SETTING_WRITECACHE_ENABLED;
+				else if (pReq->Cdb[2] == CDB_CORE_ENABLE_WRITE_CACHE)
+					pDevice->Setting |= DEVICE_SETTING_WRITECACHE_ENABLED;
+				else if (pReq->Cdb[2] == CDB_CORE_DISABLE_SMART)
+					pDevice->Setting &= ~DEVICE_SETTING_SMART_ENABLED;
+				else if (pReq->Cdb[2] == CDB_CORE_ENABLE_SMART)
+					pDevice->Setting |= DEVICE_SETTING_SMART_ENABLED;
+				else if (pReq->Cdb[2] == CDB_CORE_SMART_RETURN_STATUS)
+				{
+					pHDStatus = (PHD_Status)pReq->Data_Buffer;
+					if (pHDStatus == NULL)
+					{
+#ifdef SUPPORT_EVENT
+					if (pTaskFile->LBA_Mid == 0xF4 && pTaskFile->LBA_High == 0x2C)
+						core_generate_event( pCore, EVT_ID_HD_SMART_THRESHOLD_OVER, pDevice->Id, SEVERITY_WARNING, 0, NULL );
+#endif
+					}
+					else
+					{
+						if (pTaskFile->LBA_Mid == 0xF4 && pTaskFile->LBA_High == 0x2C)
+							pHDStatus->SmartThresholdExceeded = MV_TRUE;
+						else
+							pHDStatus->SmartThresholdExceeded = MV_FALSE;
+					}
+				}
+			}
+
+
+			if (pReq->Cdb[0] == SCSI_CMD_MARVELL_SPECIFIC && pReq->Cdb[1] == CDB_CORE_MODULE
+			    && pReq->Cdb[2] == CDB_CORE_OS_SMART_CMD)
+			{
+				pReq->Cdb[6] = pTaskFile->LBA_Mid;
+				pReq->Cdb[7] = pTaskFile->LBA_High;
+				pReq->Cdb[5] = pTaskFile->LBA_Low;
+				pReq->Cdb[9] = pTaskFile->Device;
+				pReq->Cdb[8] = pTaskFile->Sector_Count;
+			}
+
+		}
+		else
+		{
+			if (pReq->Sense_Info_Buffer != NULL)
+				((MV_PU8)pReq->Sense_Info_Buffer)[0] = REQ_STATUS_ERROR;
+			pReq->Scsi_Status = REQ_STATUS_ERROR_WITH_SENSE;
+#ifdef SUPPORT_EVENT
+			if ( (pReq->Cdb[0] == SCSI_CMD_MARVELL_SPECIFIC) &&
+				 (pReq->Cdb[1] == CDB_CORE_MODULE) &&
+				 (pReq->Cdb[2] == CDB_CORE_SMART_RETURN_STATUS) )
+				core_generate_event(pCore, EVT_ID_HD_SMART_POLLING_FAIL, pDevice->Id, SEVERITY_WARNING,  0,  NULL );
+#endif
+		}
+	}
+#endif
+
+	/* Do something if necessary to return back the request. */
+	if ( (pReq->Cdb[0]==SCSI_CMD_MARVELL_SPECIFIC) && (pReq->Cdb[1]==CDB_CORE_MODULE) ) 
+	{
+		if ( pReq->Cdb[2]==CDB_CORE_SHUTDOWN )
+		{
+			if ( pReq->Device_Id<MAX_DEVICE_NUMBER-1 )
+			{
+				pReq->Device_Id++;
+				pReq->Scsi_Status = REQ_STATUS_PENDING;
+				Core_ModuleSendRequest(pCore, pReq);
+				return;
+			}
+			else
+			{
+				pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+			}
+		}
+	}
+	if(pReq->Completion)
+		pReq->Completion(pReq->Cmd_Initiator, pReq);
+}
+
+void CompleteRequestAndSlot(
+	IN PCore_Driver_Extension pCore,
+	IN PDomain_Port pPort,
+	IN PMV_Request pReq,
+	IN PATA_TaskFile pTaskFile,
+	IN MV_U8 slotId
+	)
+{
+#ifdef SUPPORT_ERROR_HANDLING
+	PDomain_Device pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+#endif
+	mv_core_reset_running_slot(pPort, slotId);
+	MV_DASSERT( (MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_CMD_ISSUE)&(1<<slotId))==0 );
+
+	if ( pPort->Type!=PORT_TYPE_PATA )
+	{
+		MV_DASSERT( (MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_SCR_ACT)&(1<<slotId))==0 );
+	}
+
+	pDevice->Outstanding_Req--;
+#ifdef SUPPORT_ERROR_HANDLING
+#ifdef SUPPORT_TIMER
+	/* request for this device came back, so we cancel the timer */
+	Timer_CancelRequest( pCore, pDevice->Timer_ID );
+	pDevice->Timer_ID = NO_CURRENT_TIMER;
+
+	/* if there are more outstanding requests, we send a new timer */
+	if ( pDevice->Outstanding_Req > 0 )
+	{
+		MV_DASSERT(pPort->Running_Slot!=0);
+		pDevice->Timer_ID = Timer_AddRequest( pCore, REQUEST_TIME_OUT, Core_ResetChannel, pDevice, NULL );
+	}
+#endif /* SUPPORT_TIMER */
+#endif /* SUPPORT_ERROR_HANDLING */
+	CompleteRequest(pCore, pReq, pTaskFile);
+}
+
+void Port_Monitor(PDomain_Port pPort)
+{
+	MV_U8 i;
+	MV_PRINT("Port_Monitor: Running_Slot=0x%x.\n", pPort->Running_Slot);
+
+	for ( i=0; i<MAX_SLOT_NUMBER; i++ )
+	{
+		if ( pPort->Running_Req[i]!=NULL )
+			MV_DumpRequest(pPort->Running_Req[i], MV_FALSE);
+	}
+}
+
+void Core_ModuleMonitor(MV_PVOID This)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	PMV_Request pReq = NULL;
+	PList_Head head = &pCore->Waiting_List;
+	PDomain_Port pPort = NULL;
+	MV_U8 i;
+
+	MV_PRINT("Core_ModuleMonitor Waiting_List:\n");
+	for (pReq = LIST_ENTRY((head)->next, MV_Request, Queue_Pointer);	\
+	     &pReq->Queue_Pointer != (head); 	\
+	     pReq = LIST_ENTRY(pReq->Queue_Pointer.next, MV_Request, Queue_Pointer))
+	{
+		MV_DumpRequest(pReq, MV_FALSE);
+	}
+
+	for ( i=0; i<pCore->Port_Num; i++ )
+	{
+		MV_PRINT("Port[%d]:\n", i);
+		pPort = &pCore->Ports[i];
+		Port_Monitor(pPort);
+	}
+}
+
+void Core_ModuleReset(MV_PVOID This)
+{
+	MV_U32 extensionSize = 0; 
+
+	extensionSize = ( ROUNDING(sizeof(Core_Driver_Extension),8)
+#ifdef SUPPORT_CONSOLIDATE
+					+ ROUNDING(sizeof(Consolidate_Extension),8) + ROUNDING(sizeof(Consolidate_Device),8)*MAX_DEVICE_NUMBER
+#endif
+					);
+			
+	/* Re-initialize all the variables even discard all the requests. */
+	Core_ModuleInitialize(This, extensionSize, 32);
+
+}
+#ifdef __MM_SE__
+
+struct mv_module_ops __core_mod_ops = {
+	.module_id              = MODULE_CORE,
+	.get_res_desc           = Core_ModuleGetResourceQuota,
+	.module_initialize      = Core_ModuleInitialize,
+	.module_start           = Core_ModuleStart,
+	.module_stop            =  Core_ModuleShutdown,
+	.module_notification    = Core_ModuleNotification,
+	.module_sendrequest     = Core_ModuleSendRequest,
+	.module_reset           =  Core_ModuleReset,
+	.module_monitor         = Core_ModuleMonitor,
+	.module_service_isr     = Core_InterruptServiceRoutine,
+#ifdef RAID_DRIVER
+	.module_send_xor_request= Core_ModuleSendXORRequest,
+#endif /* RAID_DRIVER */
+};
+
+struct mv_module_ops *mv_core_register_module(void)
+{
+	return &__core_mod_ops;
+}
+
+#endif /* _OS_LINUX */
+
diff --git a/drivers/scsi/thor/core/thor/core_exp.h b/drivers/scsi/thor/core/thor/core_exp.h
new file mode 100755
index 0000000..3525c48
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_exp.h
@@ -0,0 +1,68 @@
+#if !defined(CORE_EXPOSE_H)
+#define CORE_EXPOSE_H
+
+#ifdef __MM_SE__
+#define __ext_to_core(_ext)       ((PCore_Driver_Extension) (_ext))
+
+#define core_start_cmpl_notify(_ext)                                      \
+           {                                                              \
+		   __ext_to_core(_ext)->desc->status = MV_MOD_STARTED;    \
+		   HBA_ModuleStarted(__ext_to_core(_ext)->desc);          \
+	   }
+
+
+#define core_generate_event(ext, eid, did, slv, pc, ptr)                  \
+   {                                                                      \
+	struct mod_notif_param _param = {ptr, 0, 0, eid, did, slv, pc};   \
+	__ext_to_core(ext)->desc->parent->ops->module_notification(       \
+                                            ext->desc->parent->extension, \
+					    EVENT_LOG_GENERATED,          \
+					    &_param);                     \
+   }
+
+
+#else /* __MM_SE__ */
+#define core_generate_event(ext, eid, did, slv, pc, ptr)                \
+   {                                                                    \
+       struct mod_notif_param param = {ptr, 0, 0, eid, did, slv, pc};   \
+       HBA_ModuleNotification(ext, EVENT_LOG_GENERATED, &param);        \
+   }
+
+#define core_start_cmpl_notify(_ext)  	HBA_ModuleStarted(_ext) 
+#endif /* __MM_SE__ */
+
+
+MV_U32 Core_ModuleGetResourceQuota(enum Resource_Type type, MV_U16 maxIo);
+void Core_ModuleInitialize(MV_PVOID, MV_U32, MV_U16);
+void Core_ModuleStart(MV_PVOID);
+void Core_ModuleShutdown(MV_PVOID);
+void Core_ModuleNotification(MV_PVOID, enum Module_Event, struct mod_notif_param *);
+void Core_ModuleSendRequest(MV_PVOID, PMV_Request);
+void Core_ModuleMonitor(MV_PVOID);
+void Core_ModuleReset(MV_PVOID pExtension);
+
+MV_BOOLEAN Core_InterruptServiceRoutine(MV_PVOID This);
+
+#ifdef  SUPPORT_TASKLET
+MV_BOOLEAN Core_HandleServiceRoutine(MV_PVOID This);
+#endif
+
+#ifdef SUPPORT_ERROR_HANDLING
+#ifdef _OS_LINUX
+#define REQUEST_TIME_OUT			10		// in multiples of TIMER_INTERVAL, see hba_timer.h
+#else
+#define REQUEST_TIME_OUT			30		// in multiples of TIMER_INTERVAL, see hba_timer.h
+#endif
+#endif
+
+void mvRemoveDeviceWaitingList( MV_PVOID This, MV_U16 deviceId, MV_BOOLEAN returnOSRequest );
+void mvRemovePortWaitingList( MV_PVOID This, MV_U8 portId );
+MV_U8 mv_core_check_is_reseeting(MV_PVOID core_ext);
+void Core_FillSenseData(PMV_Request pReq, MV_U8 senseKey, MV_U8 adSenseCode);
+void RAID_ModuleNotification(MV_PVOID This,
+			     enum Module_Event event,
+			     struct mod_notif_param *param);
+
+void sata_hotplug(MV_PVOID data,MV_U32 intStatus);
+#endif /* CORE_EXPOSE_H */
+
diff --git a/drivers/scsi/thor/core/thor/core_init.c b/drivers/scsi/thor/core/thor/core_init.c
new file mode 100755
index 0000000..5874dfb
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_init.c
@@ -0,0 +1,2804 @@
+#include "mv_include.h"
+
+#include "core_exp.h"
+
+#include "core_init.h"
+#include "core_inter.h"
+
+#include "core_thor.h"
+
+#include "core_sata.h"
+
+static void Device_IssueIdentify(PDomain_Port pPort, PDomain_Device pDevice);
+static void Device_IssueSetUDMAMode(PDomain_Port pPort, PDomain_Device pDevice);
+static void Device_IssueSetPIOMode(PDomain_Port pPort, PDomain_Device pDevice);
+static void Device_EnableWriteCache(PDomain_Port pPort, PDomain_Device pDevice);
+static void Device_EnableReadAhead(PDomain_Port pPort, PDomain_Device pDevice);
+
+extern void Core_HandleWaitingList(PCore_Driver_Extension pCore);
+
+static MV_BOOLEAN mvChannelStateMachine(
+	PCore_Driver_Extension pCore,
+	PDomain_Port pPort
+	);
+
+MV_BOOLEAN mvDeviceStateMachine(
+	PCore_Driver_Extension pCore,
+	PDomain_Device pDevice
+	);
+
+#ifdef COMMAND_ISSUE_WORKROUND
+MV_U8 mv_core_reset_port(PDomain_Port pPort);
+void mv_core_dump_reg(PDomain_Port pPort);
+void mv_core_reset_command_in_timer(PDomain_Port pPort);
+void mvHandleDevicePlugin_BH(MV_PVOID  ext);
+void  mv_core_reset_command(PDomain_Port pPort);
+void mv_core_init_reset_para(PDomain_Port pPort);
+#endif
+
+
+#ifdef SUPPORT_HOT_PLUG
+void Device_SoftReset(PDomain_Port pPort, PDomain_Device pDevice)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+
+	pDevice->State = DEVICE_STATE_RESET_DONE;
+	mvDeviceStateMachine (pCore, pDevice);
+}
+#endif	/* #ifdef SUPPORT_HOT_PLUG */ 
+
+PMV_Request GetInternalReqFromPool( PCore_Driver_Extension pCore )
+{
+	if( !List_Empty(&pCore->Internal_Req_List) )
+		return ((PMV_Request)List_GetFirstEntry(&pCore->Internal_Req_List, MV_Request, Queue_Pointer));
+	else
+		return NULL;
+}
+
+void ReleaseInternalReqToPool( PCore_Driver_Extension pCore, PMV_Request pReq)
+{
+	MV_ZeroMvRequest(pReq);
+	List_AddTail( &pReq->Queue_Pointer, &pCore->Internal_Req_List );	
+}
+
+/*
+ * Initialize this port including possible device hard or soft reset.
+ */
+
+#ifdef SUPPORT_PM
+void mvPMDevReWrReg(
+	PDomain_Port pPort, 
+	MV_U8 read, 
+	MV_U8 PMreg, 
+	MV_U32 regVal, 
+	MV_U8 PMport, 
+	MV_BOOLEAN control)
+{
+	/* Always use the last slot for PM */
+	/* This will only be a problem if two PM requests are sent at the same time */
+	/* using the last slot, which should not happen in current driver, */
+	/* since our PM operations are done by polling. */
+	MV_U16 tag = MAX_SLOT_NUMBER - 1;		/* always use the last slot */
+	PMV_Command_Header header = SATA_GetCommandHeader(pPort, tag);
+	PMV_Command_Table pCmdTable = Port_GetCommandTable(pPort, tag);
+	PSATA_FIS_REG_H2D pFIS = (PSATA_FIS_REG_H2D)pCmdTable->FIS;
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 old_stat, loop=5000;
+
+	mvDisableIntr(portMmio, old_stat);
+
+	MV_ZeroMemory(header, sizeof(MV_Command_Header));
+	MV_ZeroMemory(pCmdTable, sizeof(MV_Command_Table));
+	
+	header->FIS_Length = FIS_REG_H2D_SIZE_IN_DWORD;
+	header->PM_Port = control? 0xF : PMport;
+	
+	*((MV_U16 *) header) = CPU_TO_LE_16( *((MV_U16 *) header) );
+	header->Table_Address = CPU_TO_LE_32(pPort->Cmd_Table_DMA.parts.low + SATA_CMD_TABLE_SIZE*tag);
+	header->Table_Address_High = CPU_TO_LE_32(pPort->Cmd_Table_DMA.parts.high);
+	
+	pFIS->FIS_Type = SATA_FIS_TYPE_REG_H2D;
+	pFIS->PM_Port = control? 0xF : PMport;
+	pFIS->Command =  (read)?MV_ATA_COMMAND_PM_READ_REG : MV_ATA_COMMAND_PM_WRITE_REG;
+	pFIS->Features = PMreg;
+	pFIS->Device = PMport;
+	pFIS->C = 1;
+	
+	if (!read)
+	{
+		pFIS->LBA_Low =  (MV_U8)((regVal & 0xff00) >> 8);
+		pFIS->LBA_Mid = (MV_U8)((regVal & 0xff0000) >> 16);
+		pFIS->LBA_High = (MV_U8)((regVal & 0xff000000) >> 24) ;
+		pFIS->Sector_Count = (MV_U8)(regVal & 0xff);
+	}
+
+	MV_DASSERT( (MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE)&(1<<tag))==0 );
+	
+	MV_REG_WRITE_DWORD(portMmio, PORT_CMD_ISSUE, 1<<tag);
+	MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE);	/* flush */
+	
+	//temp = MV_REG_READ_DWORD(portMmio, PORT_SCR_ERR);
+	//MV_REG_WRITE_DWORD(portMmio, PORT_SCR_ERR, temp);
+	//temp = MV_REG_READ_DWORD(portMmio, PORT_IRQ_STAT);
+	//MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_STAT, temp);
+	//MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+
+	// make sure CI is cleared before moving on
+	loop = 5000;
+	while(loop > 0) {
+		if( (MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE)&(1<<tag)) == 0 )
+			break;
+		if( (MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT)& 0xf) != 0x3)
+			break;
+		HBA_SleepMillisecond(pCore, 10);
+		loop--;
+	}
+
+	if ( (MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE)&(1<<tag)) != 0 )
+		MV_DPRINT(("read/write PM register: CI not cleared!\n"));
+
+	mvEnableIntr(portMmio, old_stat);
+	
+}
+static MV_U8 mvGetSataDeviceType(PDomain_Port pPort)
+{
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 tmp;
+
+	tmp = MV_REG_READ_DWORD(portMmio, PORT_SIG);
+
+	if(tmp == 0x96690101)
+	{
+		MV_DPRINT(("Port Multiplier detected.\n"));
+		return PORT_TYPE_PM;
+	}
+
+	return 0;
+}
+#endif /* SUPPORT_PM */
+
+
+MV_BOOLEAN SATA_DoSoftReset(PDomain_Port pPort, MV_U8 PMPort)
+{
+	MV_U16 tag = Tag_GetOne(&pPort->Tag_Pool);
+	PMV_Command_Header header = SATA_GetCommandHeader(pPort, tag);
+	PMV_Command_Table pCmdTable = Port_GetCommandTable(pPort, tag);
+	PSATA_FIS_REG_H2D pFIS = (PSATA_FIS_REG_H2D)pCmdTable->FIS;
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 old_stat;
+	MV_U32 temp = 0, count = 0;
+	MV_U8 reset = 1;
+
+	if( PMPort == 0xF )
+		MV_DASSERT( tag == 0 );
+
+	mvDisableIntr(portMmio, old_stat);
+
+	do
+	{
+		MV_ZeroMemory(header, sizeof(MV_Command_Header));
+		MV_ZeroMemory(pCmdTable, sizeof(MV_Command_Table));
+	
+		header->FIS_Length = FIS_REG_H2D_SIZE_IN_DWORD;
+		header->Reset = (reset)?1:0;
+		header->PM_Port = PMPort;
+		
+		*((MV_U16 *) header) = CPU_TO_LE_16( *((MV_U16 *) header) );
+		header->Table_Address = CPU_TO_LE_32(pPort->Cmd_Table_DMA.parts.low + SATA_CMD_TABLE_SIZE*tag);
+		header->Table_Address_High = CPU_TO_LE_32(pPort->Cmd_Table_DMA.parts.high);
+	
+		pFIS->FIS_Type = SATA_FIS_TYPE_REG_H2D;
+		pFIS->PM_Port = PMPort;
+//		pFIS->Device = 0x40;
+		pFIS->Control = (reset)?MV_BIT(2):0;
+
+		MV_REG_WRITE_DWORD(portMmio, PORT_CMD_ISSUE, 1<<tag);
+		MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE);	/* flush */
+
+		HBA_SleepMillisecond(pCore, 2);
+
+
+		reset = reset ^ 1; /*SRST CLEAR*/
+
+		count = 0;
+		// make sure CI is cleared before moving on
+		do {
+			temp = MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE) & (1<<tag);
+			count++;
+			HBA_SleepMillisecond(pCore, 10);
+		} while (temp != 0 && count < 1000);
+
+	}while(reset==0);
+	
+	Tag_ReleaseOne(&pPort->Tag_Pool, tag);
+	mvEnableIntr(portMmio, old_stat);
+#if 0//def MV_DEBUG
+	if(pPort->command_callback && pPort->reset_hba_times < MAX_RESET_TIMES){
+		pPort->Hot_Plug_Timer = 0;
+		pPort->command_callback = mvHandleDevicePlugin_BH;
+		SmallTimer_AddRequest(pPort, 10, mv_core_reset_command_in_timer, pPort, NULL);
+		pCore->resetting_command = MV_TRUE;
+		return MV_FALSE;
+	}
+
+#endif
+
+	if (temp != 0)
+	{
+		MV_PRINT("Softrest:CI can not be clean[0x%x] on port[%d].\n",MV_REG_READ_DWORD( portMmio, PORT_CMD ), pPort->Id);
+		mv_core_dump_reg(pPort);
+		if(pPort->reset_hba_times > MAX_RESET_TIMES){
+			MV_DPRINT(("Port resetted more than %d times, shut down the port.\n",MAX_RESET_TIMES));
+			return MV_FALSE;
+		}
+		pPort->Hot_Plug_Timer = 0;
+		pPort->command_callback = mvHandleDevicePlugin_BH;
+		pCore->resetting_command = MV_TRUE;
+		SmallTimer_AddRequest(pPort, 10, mv_core_reset_command_in_timer, pPort, NULL);
+		return MV_FALSE;
+	}
+
+	return MV_TRUE;
+}
+
+#ifdef SUPPORT_PM
+MV_BOOLEAN SATA_SoftResetDevice(PDomain_Port pPort, MV_U8 portNum)
+{
+#ifndef _OS_LINUX
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+#endif
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 status1, status2, loop = 20;
+
+	if (! (SATA_DoSoftReset(pPort, portNum)) )
+		return MV_FALSE;
+
+	while(loop>0)
+	{
+		status1 = MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT) & 0xf;
+		status2 = MV_REG_READ_DWORD(portMmio, PORT_TFDATA) & 0xff;
+		if (((status1 & 0xf) == 0x3) && ((status2 & 0x80) == 0))
+		{
+			MV_DPRINT(("loop = %x\n", loop));
+			pPort->Type = mvGetSataDeviceType( pPort );
+			return MV_TRUE;
+		}
+		HBA_SleepMicrosecond(pCore, 1000);
+		loop--;
+	}
+	MV_DPRINT(("Did not detect device after soft reset\n"));
+	return MV_FALSE;
+}
+
+MV_BOOLEAN SATA_SoftResetPMDevice(PDomain_Port pPort, MV_U8 portNum) 
+{
+#ifndef _OS_LINUX
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+#endif
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 status, loop = 5000;
+//	MV_U32 PMPort;
+
+	
+	if (! (SATA_DoSoftReset(pPort, portNum)) )
+		return MV_FALSE;
+
+	
+	while(loop>0)
+	{
+		status = MV_REG_READ_DWORD(portMmio, PORT_TFDATA) & 0xff;
+		/*PMPort = (MV_REG_READ_DWORD(portMmio, PORT_TFDATA) & 0xf00000) >> 20;*/
+
+		if ( ((status & 0x80) == 0)/* && (PMPort == portNum)*/ )
+		{
+
+			MV_DPRINT(("loop = %x\n", loop));
+			return MV_TRUE;
+		}
+		HBA_SleepMicrosecond(pCore, 1000);
+		
+		loop--;
+	}
+
+	MV_DPRINT(("Did not detect device after soft reset\n"));
+	return MV_FALSE;
+}
+
+MV_BOOLEAN PMPortDeviceDetected(PDomain_Port pPort, MV_U8 portNum)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 read_result, temp;
+	MV_BOOLEAN valid;
+	MV_U32 loop = 100;
+
+	while(loop>0)
+	{
+		/*Detect the sata device*/
+		valid = MV_FALSE;
+		do
+		{
+			mvPMDevReWrReg(pPort, MV_Read_Reg, MV_SATA_PSCR_SSTATUS_REG_NUM, 0, portNum, MV_TRUE);
+			temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+
+			if (((temp >> 16) & 0xF0) == 0xF0)
+				valid = MV_TRUE;
+              
+			read_result = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+		} while (valid == MV_FALSE);
+
+		if( (read_result & 0xFFF) == 0x123 || (read_result & 0xFFF) == 0x113 )
+		{
+			MV_DPRINT(("the device detected on PM port %d, Port %d ", portNum, pPort->Id));
+
+			/* clears X bit in SError */
+			mvPMDevReWrReg( pPort, MV_Write_Reg, MV_SATA_PSCR_SERROR_REG_NUM, 0xFFFFFFFF, portNum, MV_TRUE);
+			return MV_TRUE;
+		}
+		HBA_SleepMillisecond(pCore, 1);
+		loop--;
+	}
+	return MV_FALSE;
+}
+#endif /* SUPPORT_PM */
+
+void SATA_InitPMPort (PDomain_Port pPort, MV_U8 portNum)
+{
+	PDomain_Device pDevice = &pPort->Device[portNum];
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 signature, tmp;
+#ifdef SUPPORT_ERROR_HANDLING
+	#ifdef RAID_DRIVER
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_RAID);	
+	#else
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_HBA);
+	#endif
+	struct mod_notif_param param;
+#endif
+	if( PMPortDeviceDetected(pPort, portNum) ) 
+	{
+		/*
+		This delay is for SiliconImage PM
+		especiall ATAPI device
+		*/
+		HBA_SleepMillisecond(pCore, 50);
+		if ( SATA_SoftResetPMDevice(pPort, portNum) )
+		{
+			signature = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_PM_FIS_0);
+
+			if ( signature==0xEB140101 )				/* ATAPI signature */	
+				pDevice->Device_Type |= DEVICE_TYPE_ATAPI;			
+			else
+				MV_DASSERT( signature==0x00000101 );	/* ATA signature */
+	
+			pDevice->Internal_Req = GetInternalReqFromPool(pCore);
+			if( pDevice->Internal_Req == NULL )
+			{
+				MV_DPRINT(("ERROR: Unable to get an internal request buffer\n"));
+				// can't initialize without internal buffer - just set this disk down
+				pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+				pDevice->State = DEVICE_STATE_INIT_DONE;
+			}
+			else 
+			{
+				pDevice->Status = DEVICE_STATUS_EXISTING|DEVICE_STATUS_FUNCTIONAL;
+				pDevice->State = DEVICE_STATE_RESET_DONE;
+				pDevice->PM_Number = portNum;
+				pPort->Device_Number++;
+			}
+		}
+		else 
+		{
+			MV_DPRINT(("soft reset failed on PM port %d\n", portNum));
+
+#ifdef SUPPORT_ERROR_HANDLING
+			if( pDevice->Status & DEVICE_STATUS_FUNCTIONAL )
+			{
+				MV_ASSERT( pDevice->Internal_Req!=NULL );
+				pCore->Total_Device_Count--;
+				ReleaseInternalReqToPool( pCore, pDevice->Internal_Req );
+				pDevice->Internal_Req = NULL;
+				param.lo = pDevice->Id;
+				#ifdef RAID_DRIVER
+				RAID_ModuleNotification(pUpperLayer, EVENT_DEVICE_REMOVAL, &param);
+				#else
+				HBA_ModuleNotification(pUpperLayer, 
+						       EVENT_DEVICE_REMOVAL, 
+						       &param);
+				#endif
+			}
+#endif
+			pDevice->Status = DEVICE_STATUS_EXISTING;
+			pDevice->State = DEVICE_STATE_INIT_DONE;
+			pDevice->Need_Notify = MV_FALSE;
+			
+			/* toggle the start bit in cmd register */
+			tmp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+			MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp & ~MV_BIT(0));
+			MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp | MV_BIT(0));
+			HBA_SleepMillisecond( pCore, 100 );
+		}
+	}
+	else
+		pDevice->Need_Notify = MV_FALSE;
+}
+
+void SATA_InitPM (PDomain_Port pPort)
+{
+	PDomain_Device pDevice;
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 numPMPorts, temp;
+	MV_U8 i;
+	MV_BOOLEAN valid;
+
+	pPort->Setting |= PORT_SETTING_PM_EXISTING;
+	pPort->Setting |= PORT_SETTING_PM_FUNCTIONAL;
+	
+	/* fill in various information about the PM */
+
+	/* check how many ports the PM has */
+	valid = MV_FALSE;
+	do
+	{
+		mvPMDevReWrReg(pPort, MV_Read_Reg, MV_SATA_GSCR_INFO_REG_NUM, 0, 0xF, MV_TRUE);
+		temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+
+		if (((temp >> 16) & 0xF0) == 0xF0)
+			valid = MV_TRUE;
+          
+		numPMPorts = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 ) & 0xF;		
+	} while (valid == MV_FALSE);
+	
+	if ( numPMPorts > MAX_DEVICE_PER_PORT )
+		numPMPorts = MAX_DEVICE_PER_PORT;
+	else if ( numPMPorts < MAX_DEVICE_PER_PORT )
+	{
+		for( i=(MV_U8)numPMPorts; i<MAX_DEVICE_PER_PORT; i++ )
+		{
+			pPort->Device[i].Status = DEVICE_STATUS_NO_DEVICE;
+			pPort->Device[i].State = DEVICE_STATE_INIT_DONE;
+		}
+	}
+	pPort->PM_Num_Ports = (MV_U8)numPMPorts;
+
+	/* vendor ID & device ID */
+	valid = MV_FALSE;
+	do
+	{
+		mvPMDevReWrReg( pPort, MV_Read_Reg, MV_SATA_GSCR_ID_REG_NUM, 0, 0xF, MV_TRUE );
+		temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+
+		if (((temp >> 16) & 0xF0) == 0xF0)
+			valid = MV_TRUE;
+          
+		temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+	} while (valid == MV_FALSE);
+	
+	pPort->PM_Vendor_Id = (MV_U16)temp;
+	pPort->PM_Device_Id = (MV_U16)(temp >> 16);
+
+	/* product & spec revisions */
+	valid = MV_FALSE;
+	do
+	{
+		mvPMDevReWrReg( pPort, MV_Read_Reg, MV_SATA_GSCR_REVISION_REG_NUM, 0, 0xF, MV_TRUE );
+		temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+
+		if (((temp >> 16) & 0xF0) == 0xF0)
+			valid = MV_TRUE;
+          
+		temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+	} while (valid == MV_FALSE);
+	
+	pPort->PM_Product_Revision = (MV_U8)((temp & 0xFF00) >> 8);
+	if ( temp & MV_BIT(3) )
+		pPort->PM_Spec_Revision = 12;
+	else if ( temp & MV_BIT(2) )
+		pPort->PM_Spec_Revision = 11;
+	else if ( temp & MV_BIT(1) )
+		pPort->PM_Spec_Revision = 10;
+	else
+		pPort->PM_Spec_Revision = 0;
+
+	/* enable asychronous notification bit for hot plug */
+	valid = MV_FALSE;
+	do
+	{
+		mvPMDevReWrReg( pPort, MV_Read_Reg, MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM, 0, 0xF, MV_TRUE );
+		temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+
+		if (((temp >> 16) & 0xF0) == 0xF0)
+			valid = MV_TRUE;
+          
+		temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+	} while (valid == MV_FALSE);
+	
+	mvPMDevReWrReg( pPort, MV_Write_Reg, MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM, 
+					temp | MV_BIT(3), 0xF, MV_TRUE );
+
+	/* enable N & X bit in SError for hot plug */
+	valid = MV_FALSE;
+	do
+	{
+		mvPMDevReWrReg( pPort, MV_Read_Reg, MV_SATA_GSCR_ERROR_ENABLE_REG_NUM, 0, 0xF, MV_TRUE );
+		temp = MV_REG_READ_DWORD( portMmio, PORT_TFDATA);
+
+		if (((temp >> 16) & 0xF0) == 0xF0)
+			valid = MV_TRUE;
+          
+		temp = MV_REG_READ_DWORD( portMmio, PORT_PM_FIS_0 );
+	} while (valid == MV_FALSE);
+	
+	mvPMDevReWrReg( pPort, MV_Write_Reg, MV_SATA_GSCR_ERROR_ENABLE_REG_NUM, 
+					MV_BIT(16) | MV_BIT(26), 0xF, MV_TRUE );
+
+	for( i=0; i<numPMPorts; i++ )
+	{
+		pDevice = &pPort->Device[i];
+		pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+		pDevice->State = DEVICE_STATE_INIT_DONE;
+
+	
+		/*
+		When enter hibernation, do not enable device port again
+		for saving hibernation time
+		*/
+		if(!pCore->Is_Dump){
+			/*enable the device port*/
+			mvPMDevReWrReg(pPort, MV_Write_Reg, MV_SATA_PSCR_SCONTROL_REG_NUM, 0x01, i, MV_TRUE);	
+			HBA_SleepMillisecond(pCore, 1);
+			mvPMDevReWrReg(pPort, MV_Write_Reg, MV_SATA_PSCR_SCONTROL_REG_NUM, 0x00, i, MV_TRUE);
+			HBA_SleepMillisecond(pCore, 1);
+		}
+	
+		SATA_InitPMPort( pPort, i );
+	}
+
+	/* Wait for each port to finish setting flags before starting state machine*/
+	for( i=0; i<numPMPorts; i++ )
+	{
+		pDevice = &pPort->Device[i];
+		if( pDevice->Status & DEVICE_STATUS_FUNCTIONAL )
+			mvDeviceStateMachine( pCore, pDevice );
+	}
+
+	if( pPort->Device_Number == 0 )
+		mvDeviceStateMachine( pCore, &pPort->Device[0] );
+}
+
+MV_BOOLEAN SATA_PortSoftReset( PCore_Driver_Extension pCore, PDomain_Port pPort )
+{
+	PDomain_Device pDevice = &pPort->Device[0];
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 tmp;
+	MV_U8 i;
+
+	if (! (SATA_SoftResetDevice(pPort, 0xF)) )
+	{
+		/* toggle the start bit in cmd register */
+		tmp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+		MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp & ~MV_BIT(0));
+		MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp | MV_BIT(0));
+		HBA_SleepMillisecond( pCore, 100 );
+
+		if( (pPort->Type != PORT_TYPE_PM) && (pDevice->Status & DEVICE_STATUS_FUNCTIONAL) 
+#ifdef COMMAND_ISSUE_WORKROUND
+			&& !mv_core_check_is_reseeting(pCore)
+#endif
+			){
+			SATA_PortReportNoDevice( pCore, pPort );		
+		}
+		/* had trouble detecting device on this port, so we report existing
+		   but not functional */
+		pDevice->Status = DEVICE_STATUS_EXISTING;
+		pDevice->State = DEVICE_STATE_INIT_DONE;
+
+		/* set the rest of the device on this port */
+		for (i=1; i<MAX_DEVICE_PER_PORT; i++)
+		{	
+			pDevice = &pPort->Device[i];
+			pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+			pDevice->State = DEVICE_STATE_INIT_DONE;
+		}
+				
+		mvDeviceStateMachine(pCore, pDevice);
+		return MV_FALSE;
+	}
+
+	/* toggle the start bit in cmd register to make sure hardware
+	   is clean after soft reset */
+	tmp = MV_REG_READ_DWORD( portMmio, PORT_CMD );
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp & ~MV_BIT(0));
+	MV_REG_WRITE_DWORD( portMmio, PORT_CMD, tmp | MV_BIT(0));
+	HBA_SleepMillisecond( pCore, 100 );
+	
+	return MV_TRUE;
+}
+
+void SATA_PortReportNoDevice (PCore_Driver_Extension pCore, PDomain_Port pPort)
+{
+	PDomain_Device pDevice;
+	MV_U8 temp, i;
+#ifdef RAID_DRIVER
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_RAID);
+#else
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_HBA);
+#endif /* RAID_DRIVER */
+	struct mod_notif_param param;
+
+	mvRemovePortWaitingList( pCore, pPort->Id );
+
+	/* if PM - clear all the device attached to the port */
+	if( pPort->Type == PORT_TYPE_PM )
+		temp = MAX_DEVICE_PER_PORT-1;
+	else
+		temp = 0;
+		
+	for( i=0; i<=temp; i++ )
+	{
+		pDevice = &pPort->Device[i];
+
+		if( pDevice->Status & DEVICE_STATUS_FUNCTIONAL )
+		{
+			if( pDevice->Internal_Req != NULL )
+			{
+				pCore->Total_Device_Count--;
+				ReleaseInternalReqToPool( pCore, pDevice->Internal_Req );
+				pDevice->Internal_Req = NULL;
+			}
+			param.lo = pDevice->Id;
+#ifdef RAID_DRIVER
+			RAID_ModuleNotification(pUpperLayer, EVENT_DEVICE_REMOVAL, &param);
+#else
+			HBA_ModuleNotification(pUpperLayer, 
+					       EVENT_DEVICE_REMOVAL, 
+					       &param);
+#endif /* RAID_DRIVER */
+			pPort->Device_Number--;
+		}
+		
+		pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+		pDevice->State = DEVICE_STATE_INIT_DONE;
+	}
+}
+
+#ifdef SUPPORT_PM
+void mvHandlePMUnplug (PCore_Driver_Extension pCore, PDomain_Device pDevice);
+#endif
+
+void SATA_PortReset(
+	PDomain_Port pPort,
+	MV_BOOLEAN hardReset
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PDomain_Device pDevice = &pPort->Device[0];
+	MV_U32 signature;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 tmp, old_stat;
+	MV_U8 i;
+	MV_U8 skip = MV_FALSE;
+
+	/* No running commands at this moment */
+//	MV_ASSERT( pPort->Running_Slot==0 );
+//	MV_ASSERT( pPort->Port_State==PORT_STATE_IDLE );
+
+	pPort->Device_Number = 0;
+
+	MV_DPRINT(("Enter SATA_PortReset.\n"));
+	/* If we already reached the max number of devices supported,
+	   disregard the rest */
+
+	{
+#ifdef SUPPORT_PM
+		/*The timeout retry count more than CORE_MAX_RESET_COUNT*/
+		if( pPort->Type == PORT_TYPE_PM ){
+			MV_BOOLEAN RetryCountOverflow = MV_FALSE;
+			for( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+			{
+				if((pPort->Device[i].Reset_Count > CORE_MAX_RESET_COUNT)
+				    && (pPort->Device[i].Status & DEVICE_STATUS_FUNCTIONAL )){
+					mvHandlePMUnplug(pCore, &pPort->Device[i]);
+					MV_DPRINT(("Remove device %d on port %d is gone\n",i ,pPort->Id));
+					RetryCountOverflow = MV_TRUE;
+				}
+			}
+			if(RetryCountOverflow)
+				return;
+		}
+		else
+#endif
+		{
+			if((pDevice->Reset_Count > CORE_MAX_RESET_COUNT)
+			    &&  (pDevice->Status & DEVICE_STATUS_FUNCTIONAL)){
+				SATA_PortReportNoDevice( pCore, pPort );
+				MV_DPRINT(("Remove port %d\n",pPort->Id));
+				return;
+			}
+		}
+	}
+
+	
+	if( pCore->Total_Device_Count >= MAX_DEVICE_SUPPORTED )
+	{
+		for( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+		{
+			pPort->Device[i].State = DEVICE_STATE_INIT_DONE;
+			pPort->Device[i].Status = DEVICE_STATUS_NO_DEVICE;
+		}
+		MV_DPRINT(("We have too many devices %d.\n", pCore->Total_Device_Count));
+		return;
+	}
+
+	if ( hardReset )
+	{
+
+			MV_U32 SControl,CounterForHardReset = 1000;
+			SControl = MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);
+			SControl &= ~0x0000000F;
+			SControl |= 0x01;
+			MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+			HBA_SleepMillisecond(pCore, 1);
+			SControl &= ~0x0000000F;
+			SControl |= 0x00;
+			MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+			while(((MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT)&0x0F) != 0x03) && CounterForHardReset>0){
+				HBA_SleepMillisecond(pCore, 1);
+				CounterForHardReset--;
+			}
+
+	}
+
+#ifdef FORCE_1_5_G
+	/* It'll trigger OOB. Looks like PATA hardware reset. 
+	 * Downgrade 3G to 1.5G
+	 * If Port Multiplier is attached, only the PM is downgraded. */
+	{
+		SStatus = MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT);
+		if ( (SStatus&0xF0)==0x20 )
+		{
+			/* 3G */
+			SControl = MV_REG_READ_DWORD(portMmio, PORT_SCR_CTL);
+			SControl &= ~0x000000FF;
+			SControl |= 0x11;
+			MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+            HBA_SleepMillisecond(pCore, 2);
+			SControl &= ~0x000000FF;
+			SControl |= 0x10;
+			MV_REG_WRITE_DWORD(portMmio, PORT_SCR_CTL, SControl);
+			HBA_SleepMillisecond(pCore, 2);
+		}
+	}
+#endif
+
+	if( !SATA_PortDeviceDetected(pPort) )
+	{
+#if defined(SUPPORT_ERROR_HANDLING)
+		if( pPort->Setting & PORT_SETTING_PM_FUNCTIONAL )
+		{
+			pPort->Setting &= ~PORT_SETTING_PM_FUNCTIONAL;
+			pPort->Setting &= ~PORT_SETTING_PM_EXISTING;
+			MV_DPRINT(("PM on port %d is gone\n", pPort->Id));
+			SATA_PortReportNoDevice( pCore, pPort );
+		}
+		else if( pDevice->Status & DEVICE_STATUS_FUNCTIONAL ) 
+		{
+			MV_DPRINT(("device on port %d is gone\n", pPort->Id));
+			SATA_PortReportNoDevice( pCore, pPort );
+		}
+#endif
+
+		// fixed: have to set each device individually - or hot plug will have problem
+		for (i=0; i<MAX_DEVICE_PER_PORT; i++)
+		{	
+			pDevice = &pPort->Device[i];
+			pDevice->State = DEVICE_STATE_INIT_DONE;
+		}
+
+		mvDeviceStateMachine(pCore, pDevice);
+		return;
+	}
+
+	MV_DPRINT(("find device on port %d.\n", pPort->Id));
+	if( !SATA_PortDeviceReady(pPort) )
+	{	
+
+#if defined(SUPPORT_ERROR_HANDLING)
+		if( pPort->Setting & PORT_SETTING_PM_FUNCTIONAL ) 
+		{
+			pPort->Setting &= ~PORT_SETTING_PM_FUNCTIONAL;
+			MV_DPRINT(("PM on port %d is non-functional\n", pPort->Id));
+			SATA_PortReportNoDevice( pCore, pPort );
+		}
+		else if( pDevice->Status & DEVICE_STATUS_FUNCTIONAL )
+		{
+			MV_DPRINT(("device on port %d is non-functional\n", pPort->Id));
+			SATA_PortReportNoDevice( pCore, pPort );
+			pDevice->Status = DEVICE_STATUS_EXISTING;		
+		}
+#endif
+		for (i=0; i<MAX_DEVICE_PER_PORT; i++)
+		{	
+			pDevice = &pPort->Device[i];
+			pDevice->State = DEVICE_STATE_INIT_DONE;
+		}
+				
+		mvDeviceStateMachine(pCore, pDevice);
+		return;
+	}
+	MV_DPRINT(("find device ready on port %d.\n", pPort->Id));
+
+
+#ifdef SUPPORT_PM
+	/* link error work around */
+	mvDisableIntr( portMmio, old_stat );
+	MV_REG_WRITE_DWORD( pPort->Mmio_Base, PORT_VSR_ADDR, 0x5 );
+	tmp = MV_REG_READ_DWORD( pPort->Mmio_Base, PORT_VSR_DATA );
+	MV_REG_WRITE_DWORD( pPort->Mmio_Base, PORT_VSR_DATA, tmp | MV_BIT(26));
+	HBA_SleepMillisecond( pCore, 1 );
+	mvEnableIntr( portMmio, old_stat );
+	if(!pCore->Is_Dump)
+		HBA_SleepMillisecond(pCore, 1000);
+
+	if ( (pCore->State!=CORE_STATE_STARTED) &&
+		 (pCore->Flag_Fastboot_Skip & FLAG_SKIP_PM) )
+		 skip = MV_TRUE;
+
+	if(!skip) /*Not skip in running time*/
+	{
+		MV_DPRINT(("SATA_PortReset not skipped\n"));
+
+		/* Always turn the PM bit on - otherwise won't work! */
+		tmp = MV_REG_READ_DWORD(portMmio, PORT_CMD);					
+		MV_REG_WRITE_DWORD(portMmio, PORT_CMD, tmp | MV_BIT(17));
+		tmp=MV_REG_READ_DWORD(portMmio, PORT_CMD);	/* flush */
+
+
+		if(!pCore->Is_Dump) {
+			HBA_SleepMillisecond(pCore, 2000);
+			//hba_msleep(2000);
+		}
+
+		if (! (SATA_PortSoftReset( pCore, pPort )) )
+		{
+#if defined(SUPPORT_ERROR_HANDLING) || defined(_OS_LINUX)
+			if( pPort->Setting & PORT_SETTING_PM_FUNCTIONAL ) 
+			{
+				pPort->Setting &= ~PORT_SETTING_PM_FUNCTIONAL;
+				SATA_PortReportNoDevice( pCore, pPort );
+			}
+#endif
+			return;
+		}
+	} 
+	else {	
+		MV_DPRINT(("SATA_PortReset is skipped.\n"));
+	}
+
+	if( pPort->Type == PORT_TYPE_PM ) 
+	{
+		SATA_InitPM( pPort );
+	} 
+	else
+#endif	
+	{
+
+#ifdef SUPPORT_PM
+	/* not a PM - turn off the PM bit in command register */
+	tmp = MV_REG_READ_DWORD(portMmio, PORT_CMD);					
+	MV_REG_WRITE_DWORD(portMmio, PORT_CMD, tmp & (~MV_BIT(17)));
+	tmp=MV_REG_READ_DWORD(portMmio, PORT_CMD);	/* flush */
+#endif
+
+	signature = MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_SIG);
+
+
+
+	if ( signature==0xEB140101 )				/* ATAPI signature */
+	{		
+		pDevice->Device_Type |= DEVICE_TYPE_ATAPI;
+	}
+	else
+	{
+		MV_DASSERT( signature==0x00000101 );	/* ATA signature */
+	}
+
+	/* set the rest of the devices on this port */
+	for ( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+	{
+		pPort->Device[i].Status = DEVICE_STATUS_NO_DEVICE;
+		pPort->Device[i].State = DEVICE_STATE_INIT_DONE;
+	}
+	
+	/* Device is ready */
+	pPort->Device[0].Internal_Req = GetInternalReqFromPool(pCore);
+	if( pPort->Device[0].Internal_Req == NULL )
+	{
+		MV_DPRINT(("ERROR: Unable to get an internal request buffer\n"));
+		// can't initialize without internal buffer - just set this disk down
+		//pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+		//pDevice->State = DEVICE_STATE_INIT_DONE;
+	}
+	else 
+	{
+		pPort->Device[0].Status = DEVICE_STATUS_EXISTING|DEVICE_STATUS_FUNCTIONAL;
+		pPort->Device[0].State = DEVICE_STATE_RESET_DONE;
+		pPort->Device_Number = 1;	/* We have one device here. */
+	}
+
+	mvDeviceStateMachine(pCore, &pPort->Device[0]);/*This is single drive.*/
+	}
+}
+
+MV_VOID PATA_MakeControllerCommandBlock(
+	MV_PU16 pControllerCmd,
+	MV_U8 address, 
+	MV_U8 data, 
+	MV_BOOLEAN master, 
+	MV_BOOLEAN write
+	)
+{
+	*pControllerCmd = 0L;
+
+	if ( write )
+		*((MV_PU8)pControllerCmd) = data;
+	*pControllerCmd |= (address<<8);
+	if ( !master )
+		*pControllerCmd |= MV_BIT(13);
+	if ( !write )
+		*pControllerCmd |= MV_BIT(14);
+}
+
+/* Poll the ATA register using enhanced mode. Exp register and Data is not included. */
+MV_BOOLEAN PATA_PollControllerCommand(
+	PDomain_Port pPort, 
+	MV_U8 slot,
+	MV_U8 registerAddress,
+	MV_U8 registerData,
+	MV_BOOLEAN master,
+	MV_BOOLEAN write,
+	PATA_TaskFile pTaskFile
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_LPVOID port_mmio = pPort->Mmio_Base;
+	/* Cannot use Is_Slave to judge whether it's a master device. The flag may be not ready yet. */
+
+	PMV_PATA_Command_Header header = PATA_GetCommandHeader(pPort, slot);
+	PMV_Command_Table pCmdTable = Port_GetCommandTable(pPort, slot);
+	MV_PU16 pCmdTableU16 = (MV_PU16)pCmdTable;
+	MV_U32 loop = 1000, i;
+	MV_U32 temp = 0;
+
+	/* Always use the first slot */
+	MV_ASSERT( (pPort->Running_Slot&(1L<<slot))==0 );
+	MV_ZeroMemory( pTaskFile, sizeof(ATA_TaskFile) );
+	MV_ZeroMemory(header, sizeof(MV_PATA_Command_Header));
+
+	/* Command list */
+	header->Controller_Command = 1;
+	header->PIO_Sector_Count = 1;	/* How many command */
+
+	if ( !master )
+		header->Is_Slave = 1;
+
+	header->Table_Address = pPort->Cmd_Table_DMA.parts.low;
+	header->Table_Address_High = pPort->Cmd_Table_DMA.parts.high;
+
+	PATA_MakeControllerCommandBlock(pCmdTableU16++, registerAddress, registerData, master, write);
+	
+	MV_REG_WRITE_DWORD(port_mmio, PORT_CMD_ISSUE, MV_BIT(0));
+	MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE);	/* flush */
+
+	/* Loop command issue to check whether it's finished. Hardware won't trigger interrupt. */
+	while ( loop>0 )
+	{
+		/* check interrupt */
+		temp = MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE);
+
+		if ( temp ==0 )	/* It's done. */
+		{
+			/* Anyway it's still better to clear the interrupt. */
+			temp = MV_REG_READ_DWORD(port_mmio, PORT_IRQ_STAT);
+			MV_REG_WRITE_DWORD(port_mmio, PORT_IRQ_STAT, temp);
+			MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, (1L<<pPort->Id));
+
+			if ( master )
+			{
+				for (i=0; i<1000; i++)/*Workaround for WD PATA disk*/
+				{
+					temp = MV_REG_READ_DWORD(port_mmio, PORT_MASTER_TF0);
+					if(temp == 0x7F) break;
+					if((temp & 0x80) == 0) break;
+					HBA_SleepMillisecond(pCore, 1);
+				}
+
+				pTaskFile->Command = (MV_U8)temp;
+				pTaskFile->Device = (MV_U8)(temp>>8);
+				pTaskFile->Features = (MV_U8)(temp>>24);
+				temp = MV_REG_READ_DWORD(port_mmio, PORT_MASTER_TF1);
+				pTaskFile->LBA_Low = (MV_U8)(temp>>8);
+				pTaskFile->Sector_Count = (MV_U8)(temp>>24);
+				temp = MV_REG_READ_DWORD(port_mmio, PORT_MASTER_TF2);
+				pTaskFile->LBA_High = (MV_U8)(temp>>8);
+				pTaskFile->LBA_Mid = (MV_U8)(temp>>24);
+			}
+			else
+			{
+				for (i=0; i<1000; i++)/*Workaround for WD PATA disk*/
+				{
+					temp = MV_REG_READ_DWORD(port_mmio, PORT_SLAVE_TF0);
+					if(temp == 0x7F) break;
+					if((temp & 0x80) == 0) break;
+					HBA_SleepMillisecond(pCore, 1);
+				}
+
+				pTaskFile->Command = (MV_U8)temp;
+				pTaskFile->Device = (MV_U8)(temp>>8);
+				pTaskFile->Features = (MV_U8)(temp>>24);
+				temp = MV_REG_READ_DWORD(port_mmio, PORT_SLAVE_TF1);
+				pTaskFile->LBA_Low = (MV_U8)(temp>>8);
+				pTaskFile->Sector_Count = (MV_U8)(temp>>24);
+				temp = MV_REG_READ_DWORD(port_mmio, PORT_SLAVE_TF2);
+				pTaskFile->LBA_High = (MV_U8)(temp>>8);
+				pTaskFile->LBA_Mid = (MV_U8)(temp>>24);
+			}
+			return MV_TRUE;
+		}
+		HBA_SleepMillisecond(pCore, 1);
+		loop--;
+	}
+
+	/* If this command is not completed and hardware is not cleared, we'll have trouble. */
+	MV_DASSERT( MV_REG_READ_DWORD(port_mmio, PORT_CMD_ISSUE)==0 );
+
+	return MV_FALSE;
+}
+
+MV_BOOLEAN PATA_PortDeviceWaitForBusy(
+	PDomain_Port pPort, 
+	MV_BOOLEAN master
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	ATA_TaskFile taskFile;
+	/* PATA_PollControllerCommand will poll for 1 millisecond each time, so total 5 seconds ,1 second=1000 millisecond*/
+	MV_U32 retry = 5000;	
+	do {
+		if ( master ) 
+			PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE, 0xA0, master, MV_TRUE, &taskFile);
+		else
+			PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE, 0xB0, master, MV_TRUE, &taskFile);
+		HBA_SleepMillisecond(pCore, 1);
+		retry--;
+	} while ( (taskFile.Command&MV_BIT(7)) && (retry>0) );
+
+#if 1
+	if ( taskFile.Command&MV_BIT(7) )
+	{
+		MV_DPRINT(("Port %d %s is busy retry=%d.\n", 
+			pPort->Id, master?"master":"slave", (5000-retry)));
+	}
+	else
+	{
+		MV_DPRINT(("Port %d %s is not busy retry=%d.\n", 
+			pPort->Id, master?"master":"slave", (5000-retry)));
+	}
+#endif
+
+	return ( !(taskFile.Command&MV_BIT(7)) );
+}
+
+MV_BOOLEAN PATA_PortDeviceDetected(PDomain_Port pPort, MV_BOOLEAN master, MV_BOOLEAN * isATAPI)
+{
+	ATA_TaskFile taskFile;
+
+	if ( master ) 
+		PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE, 0xA0, master, MV_TRUE, &taskFile);
+	else
+		PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE, 0xB0, master, MV_TRUE, &taskFile);
+
+#if 0
+	MV_DPRINT(("PATA_PortDeviceDetected: Sector_Count=0x%x, LBA_Low=0x%x, LBA_Mid=0x%x, LBA_High=0x%x.\n",
+		taskFile.Sector_Count, taskFile.LBA_Low, taskFile.LBA_Mid, taskFile.LBA_High));
+#endif
+
+	if ( //(taskFile.Sector_Count==0x01) && 
+		(taskFile.LBA_Low==0x01)
+		&& (taskFile.LBA_Mid==0x14)
+		&& (taskFile.LBA_High==0xEB) )
+	{
+		/* ATAPI signature found */
+		*isATAPI = MV_TRUE;
+		return MV_TRUE;
+	}
+
+	if ( (taskFile.Sector_Count==0x01)
+		&& (taskFile.LBA_Low==0x01)
+		&& (taskFile.LBA_Mid==0x00)
+		&& (taskFile.LBA_High==0x00) )
+	{
+		
+		// if status is 0, conclude that drive is not present
+		if ( taskFile.Command == 0)
+			return MV_FALSE;
+
+		/* ATA signature found */
+		*isATAPI = MV_FALSE;
+		return MV_TRUE;
+	}
+	
+	return MV_FALSE;
+}
+
+MV_BOOLEAN PATA_PortDeviceReady(PDomain_Port pPort, MV_BOOLEAN master, MV_BOOLEAN * isATAPI)
+{
+	ATA_TaskFile taskFile;
+
+	if ( master ) 
+		PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE, 0xA0, master, MV_TRUE, &taskFile);
+	else
+		PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE, 0xB0, master, MV_TRUE, &taskFile);
+	
+#if 0
+	MV_DPRINT(("PATA_PortDeviceReady: Sector_Count=0x%x, LBA_Low=0x%x, LBA_Mid=0x%x, LBA_High=0x%x.\n",
+		taskFile.Sector_Count, taskFile.LBA_Low, taskFile.LBA_Mid, taskFile.LBA_High));
+#endif
+
+	if ( /* (taskFile.Sector_Count==0x01) && */
+		(taskFile.LBA_Low==0x01)
+		&& (taskFile.LBA_Mid==0x14)
+		&& (taskFile.LBA_High==0xEB) )
+	{
+		/* ATAPI device */
+		*isATAPI = MV_TRUE;
+
+
+
+		return MV_TRUE;	/* ATAPI is always ready. */
+	}
+
+	if ( (taskFile.Sector_Count==0x01)
+		&& (taskFile.LBA_Low==0x01)
+		&& (taskFile.LBA_Mid==0x00)
+		&& (taskFile.LBA_High==0x00) )
+	{
+		/* ATA device */
+		*isATAPI = MV_FALSE;
+		if ( (taskFile.Command&0x50)==0x50 )
+			return MV_TRUE;
+		else
+            return MV_FALSE;
+
+
+
+	}
+
+	return MV_FALSE;
+}
+
+void PATA_PortReset(
+	PDomain_Port pPort,
+	MV_BOOLEAN hardReset
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PDomain_Device pDevice = NULL;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_BOOLEAN temp, isMaster;
+	ATA_TaskFile taskFile;
+	MV_U8 i;
+	MV_U32 registerValue;
+	MV_U32 retry;
+	MV_U8  skip = MV_FALSE;
+	MV_BOOLEAN working[2];	/* Check whether the master/slave device is functional. */
+	MV_BOOLEAN isATAPI[2];	/* Check whether it's ATAPI device. */
+	MV_BOOLEAN unplug[2];
+#ifdef SUPPORT_ERROR_HANDLING	
+#ifdef RAID_DRIVER
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_RAID);	
+#else
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_HBA);
+#endif /* RAID_DRIVER */
+	struct mod_notif_param param;
+#endif /* SUPPORT_ERROR_HANDLING */
+
+	/* No running commands at this moment */
+	MV_ASSERT( pPort->Running_Slot==0 );
+	MV_ASSERT( pPort->Port_State==PORT_STATE_IDLE );
+
+#ifdef MV_DEBUG
+	{
+		MV_U8 i;
+		for ( i=0; i<MAX_SLOT_NUMBER; i++ )
+		{
+			MV_DASSERT(pPort->Running_Req[i]==NULL);
+		}
+	}
+#endif
+		
+	/* If we already reached the max number of devices supported,
+	   disregard the rest */
+	if( pCore->Total_Device_Count >= MAX_DEVICE_SUPPORTED )
+	{
+		for( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+		{
+			pPort->Device[i].State = DEVICE_STATE_INIT_DONE;
+			pPort->Device[i].Status = DEVICE_STATUS_NO_DEVICE;
+		}
+		return;
+	}
+
+	unplug[0]=MV_FALSE;
+	unplug[1]=MV_FALSE;
+	pPort->Device_Number = 0;
+	/*
+	 * For PATA device, reset signal is shared between master and slave.
+	 * So both hard reset and soft reset are port based, not device based.
+	 */
+	if ( hardReset )
+	{
+#if 1
+		int loop = 0;
+		registerValue = MV_REG_READ_DWORD(portMmio, PORT_CMD);
+		MV_DASSERT( !(registerValue&PORT_CMD_PATA_HARD_RESET) );
+
+		registerValue |= PORT_CMD_PATA_HARD_RESET;
+		MV_REG_WRITE_DWORD(portMmio, PORT_CMD, registerValue);
+
+		do {
+			loop++;
+			registerValue = MV_REG_READ_DWORD(portMmio, PORT_CMD);
+		} while ( registerValue&PORT_CMD_PATA_HARD_RESET && loop < 5000);
+
+		HBA_SleepMillisecond(pCore, 2500);
+		//hba_msleep(2500);
+		MV_DASSERT( MV_REG_READ_DWORD(portMmio, PORT_CMD_ISSUE)==0 );
+#endif
+	}
+
+
+	if ( (pCore->State!=CORE_STATE_STARTED) &&
+		 (pCore->Flag_Fastboot_Skip & FLAG_SKIP_PATA_DEVICE) )
+		 skip = MV_TRUE;
+
+	if (skip)
+	{
+		for (i=0; i<MAX_DEVICE_PER_PORT; i++)
+		{
+			pDevice = &pPort->Device[i];
+			pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+			pDevice->State = DEVICE_STATE_INIT_DONE;
+		}
+	}
+	else
+	{
+#if 1
+		/* Do soft reset. Soft reset is port based, not device based. */
+		pDevice = &pPort->Device[0];
+		PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE_CONTROL, MV_BIT(2), MV_TRUE, MV_TRUE, &taskFile);
+		HBA_SleepMicrosecond(pCore, 10);	/* At least 5 microseconds. */
+		//hba_msleep(10);
+
+		pDevice = &pPort->Device[0];
+		PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE_CONTROL, 0, MV_TRUE, MV_TRUE, &taskFile);
+		HBA_SleepMillisecond(pCore, 5);		/* At least 2 millisecond. */
+		//hba_msleep(5);
+#endif
+
+		isMaster = MV_TRUE;
+
+		for ( i=2; i<MAX_DEVICE_PER_PORT; i++ )
+		{
+			pDevice = &pPort->Device[i];
+			pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+			pDevice->State = DEVICE_STATE_INIT_DONE;
+		}
+
+		/* 
+		 * Check master and slave devices. Master is at device[0], Slave is at device [1].
+		 */
+		/* Slave/Master device. Detect first. After it's totally done, we can send request to the devices. */
+		for ( i=0; i<2; i++ )
+		{
+			pDevice = NULL;/* Shouldn't use pDevice here. */
+
+			/* Wait for busy after the reset */
+			temp = PATA_PortDeviceWaitForBusy(pPort, isMaster);
+
+			/* 
+			* Suppose after waiting for 5 seconds for the BSY signal, we only need check the signature once.
+			* But I found one ATAPI device BSY is clear right away.
+			* But the first time we read the signature, it's all 0x7F. 
+			* Only after a while, it will return the correct value.
+			*/
+			if ( temp )
+			{
+				/*extend retry times,20 times,sometimes PATA disk is still not ready*/
+				retry = 200;
+				do {
+					temp = PATA_PortDeviceDetected(pPort, isMaster, &isATAPI[i]);
+					temp &= PATA_PortDeviceReady(pPort, isMaster, &isATAPI[i]);
+					retry--;
+					HBA_SleepMillisecond(pCore, 1);
+					//hba_msleep(1);
+				} while ( (retry>0)&&(!temp) );
+
+				if ( !temp )
+				{
+					if ( isMaster ) 
+						PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE, 0xA0, isMaster, MV_TRUE, &taskFile);
+					else
+						PATA_PollControllerCommand(pPort, 0, ATA_REGISTER_DEVICE, 0xB0, isMaster, MV_TRUE, &taskFile);
+
+					MV_DPRINT(("PATA task file: Command=0x%x, Sector_Count=0x%x, LBA_Low=0x%x, LBA_Mid=0x%x, LBA_High=0x%x retry=%d.\n",
+						taskFile.Command, taskFile.Sector_Count, taskFile.LBA_Low, taskFile.LBA_Mid, taskFile.LBA_High, (200-retry)));
+				}
+				else
+				{
+					MV_DPRINT(("PATA is detected and ready after retry= %d.\n", (200-retry)));
+				}
+			}
+
+			working[i] = temp;
+			isMaster = MV_FALSE;
+
+			pDevice = &pPort->Device[i];
+			if ( isATAPI[i] ) 
+				pDevice->Device_Type |= DEVICE_TYPE_ATAPI;
+			else
+				pDevice->Device_Type &= ~DEVICE_TYPE_ATAPI;
+			pDevice->Is_Slave = (i==0)?MV_FALSE:MV_TRUE;
+
+			/* 
+			 * If the device has been reset for too many times, 
+			 * just set down this disk. It's better to set 
+			 * MEDIA ERROR to the timeout request. 
+			 */
+			if ( pDevice->Reset_Count>CORE_MAX_PATA_RESET_COUNT )
+				working[i] = MV_FALSE;
+
+			if ( !working[i] ) 
+			{
+				if ( pDevice->Status&DEVICE_STATUS_FUNCTIONAL )
+				{
+					pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+					MV_DPRINT(("Port %d %s is gone.\n", pPort->Id, pDevice->Is_Slave?"slave":"master"));
+					unplug[i] = MV_TRUE;
+				}
+				else
+				{
+					pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+					MV_DPRINT(("Port %d %s not ready.\n", pPort->Id, pDevice->Is_Slave?"slave":"master"));
+				}
+				pDevice->State = DEVICE_STATE_INIT_DONE;
+			}
+			else
+			{
+
+				MV_DPRINT(("Port %d %s ready.\n", pPort->Id, pDevice->Is_Slave?"slave":"master"));
+				
+				pDevice->Internal_Req = GetInternalReqFromPool(pCore);
+				if( pDevice->Internal_Req == NULL )
+				{
+					MV_DPRINT(("ERROR: Unable to get an internal request buffer\n"));
+					// can't initialize without internal buffer - just set this disk down
+					pDevice->Status = DEVICE_STATUS_NO_DEVICE;
+					pDevice->State = DEVICE_STATE_INIT_DONE;
+				}
+				else 
+				{
+					pDevice->Status = DEVICE_STATUS_EXISTING|DEVICE_STATUS_FUNCTIONAL;
+					pPort->Device_Number++;
+				}
+			}
+		}
+
+
+		/* Set Device State for all devices first */
+		for ( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+		{
+			pDevice = &pPort->Device[i];
+			if ( pDevice->Status & DEVICE_STATUS_FUNCTIONAL )
+			{
+				pDevice->State = DEVICE_STATE_RESET_DONE;
+				/* Don't start mvDeviceStateMachine now. 
+				 * It may trigger other devices to send DMA request before resetting is done. */
+			}
+		}
+
+		/* After all the flags are set, we can do some related to the state machine and waiting list. */
+		for ( i=0; i<2; i++ )
+		{
+			pDevice = &pPort->Device[i];
+			if ( unplug[i] ) 
+			{
+				if( pDevice->Internal_Req!=NULL )
+				{
+					ReleaseInternalReqToPool( pCore, pDevice->Internal_Req );
+					pDevice->Internal_Req = NULL;
+				}
+
+				mvRemoveDeviceWaitingList( pCore, pDevice->Id, MV_TRUE );
+
+			#ifdef SUPPORT_ERROR_HANDLING	
+				param.lo = pDevice->Id;
+				#ifdef RAID_DRIVER
+					RAID_ModuleNotification(pUpperLayer, EVENT_DEVICE_REMOVAL, &param);
+				#else
+					HBA_ModuleNotification(pUpperLayer, EVENT_DEVICE_REMOVAL, &param);
+				#endif
+			#endif
+			} 
+		}
+
+		/* Then run the status machine.*/
+		/* Cable detection edit: We don't run the master state machine yet, if there is
+		   a slave attached */ 
+		for ( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+		{
+			pDevice = &pPort->Device[i];
+			if ( pDevice->Status & DEVICE_STATUS_FUNCTIONAL ) 
+			{
+				if (i != 0)
+					mvDeviceStateMachine(pCore, pDevice);
+				else
+				{
+					if (!(pPort->Device[1].Status & DEVICE_STATUS_FUNCTIONAL))
+						mvDeviceStateMachine(pCore, pDevice);
+				}
+			}
+		}
+	}
+
+	if ( pPort->Device_Number==0 )
+	{
+		/* Just use the first device to make the ball roll. */
+		
+		mvDeviceStateMachine(pCore, &pPort->Device[0]);
+	}
+
+}
+
+static MV_BOOLEAN mvChannelStateMachine(
+	PCore_Driver_Extension pCore,
+	PDomain_Port pPort
+	)
+{
+	MV_U8 i;
+	MV_U8 portState;
+	PDomain_Device pDevice;
+	PDomain_Port pOrgPort = pPort;
+	#ifdef RAID_DRIVER
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_RAID);	
+	#else
+	MV_PVOID pUpperLayer = HBA_GetModuleExtension(pCore, MODULE_HBA);
+	#endif
+
+	MV_DPRINT(("Start mvChannelStateMachine.\n"));
+
+	if ( pPort==NULL )
+		portState = PORT_STATE_IDLE;
+	else {
+		portState = pPort->Port_State;
+	}
+
+	//Each step: if fail like no device, should go to the end.
+	/* Channel state machine */
+	switch ( portState )
+	{
+		case PORT_STATE_IDLE:
+			/* To do reset */
+			for( i=0; i<pCore->Port_Num; i++ )
+			{
+				pPort = &pCore->Ports[i];
+				MV_DPRINT(("Port %d start mvChannelStateMachine in PORT_STATE_IDLE.\n", pPort->Id));
+				MV_DASSERT( pPort->Port_State==PORT_STATE_IDLE );
+				if ( pPort->Type==PORT_TYPE_PATA ){
+					if(pCore->Is_Dump)
+						PATA_PortReset( pPort, MV_FALSE );
+					else
+						PATA_PortReset( pPort, MV_TRUE );
+				}
+				else
+					SATA_PortReset( pPort, MV_FALSE );
+			}
+			break;
+
+		/* 
+		 * Each port will call mvDeviceStateMachine for its devices. 
+		 * When all the devices for that port are done, will call mvChannelStateMachine.
+		 */
+
+		case PORT_STATE_INIT_DONE:
+
+			MV_DPRINT(("Discovery port[%d] is finished.\n",pPort->Id));
+
+			/* Check whether all the ports are done. */
+			for ( i=0; i<pCore->Port_Num; i++ )
+			{
+				pPort = &pCore->Ports[i];
+				if ( pPort->Port_State != PORT_STATE_INIT_DONE )
+					return MV_TRUE;
+			}
+
+			MV_DPRINT(("Discovery procedure is finished.\n"));
+			MV_DPRINT(("Check need_reset=0x%x,pCore->State=0x%x.\n",pCore->Need_Reset,pCore->State));
+
+			/* Discovery procedure is finished. */
+			if(pCore->Need_Reset == 0)
+			{
+				if ( pCore->State==CORE_STATE_IDLE )
+				{
+					pCore->State = CORE_STATE_STARTED;
+					core_start_cmpl_notify(pCore);	/* The first time initialization */
+				}
+				else
+				{
+					/* check which device on this port needs to be reported */
+					for (i=0; i<MAX_DEVICE_PER_PORT; i++)
+					{
+						pDevice = &pOrgPort->Device[i];
+						if ( pDevice->Need_Notify )
+						{
+							struct mod_notif_param param;
+							param.lo = pDevice->Id;
+#ifdef RAID_DRIVER
+							RAID_ModuleNotification(pUpperLayer, EVENT_DEVICE_ARRIVAL, &param);
+#else
+							HBA_ModuleNotification(pUpperLayer, EVENT_DEVICE_ARRIVAL, &param);
+#endif
+							pDevice->Need_Notify = MV_FALSE;	
+						}
+					}
+				}
+			}
+			else
+			{
+				pCore->Need_Reset = 0;
+				pCore->Resetting = 0;
+
+			}
+			/* Begin to handle request again. */
+			Core_HandleWaitingList(pCore);
+			break;
+	}
+
+	return MV_TRUE;
+}
+
+MV_BOOLEAN mvDeviceStateMachine(
+	PCore_Driver_Extension pCore,
+	PDomain_Device pDevice
+	)
+{
+	MV_U8 i;
+	PDomain_Port pPort = pDevice->PPort;
+
+
+	switch ( pDevice->State )
+	{
+		case DEVICE_STATE_RESET_DONE:
+			MV_DPRINT(("Device %d DEVICE_STATE_RESET_DONE.\n", pDevice->Id));
+
+			/* To do identify */
+			Device_IssueIdentify(pDevice->PPort, pDevice); 
+			break;
+
+		case DEVICE_STATE_IDENTIFY_DONE:
+			MV_DPRINT(("Device %d DEVICE_STATE_IDENTIFY_DONE.\n", pDevice->Id));
+
+			/* To do set UDMA mode */
+			Device_IssueSetPIOMode(pDevice->PPort, pDevice);
+			break;
+
+		case DEVICE_STATE_SET_UDMA_DONE:
+			MV_DPRINT(("Device %d DEVICE_STATE_SET_UDMA_DONE.\n", pDevice->Id));
+
+			/* To do set PIO mode */
+			Device_EnableWriteCache(pDevice->PPort, pDevice);
+			break;
+
+		case DEVICE_STATE_SET_PIO_DONE:
+			MV_DPRINT(("Device %d DEVICE_STATE_SET_PIO_DONE.\n", pDevice->Id));
+
+			/* To do enable write cache */
+			Device_IssueSetUDMAMode(pDevice->PPort, pDevice);
+			break;
+
+		case DEVICE_STATE_ENABLE_WRITE_CACHE_DONE:
+			MV_DPRINT(("Device %d DEVICE_STATE_ENABLE_WRITE_CACHE_DONE.\n", pDevice->Id));
+
+            /* To do enable read ahead */
+			Device_EnableReadAhead( pDevice->PPort, pDevice );
+			break;
+
+		case DEVICE_STATE_ENABLE_READ_AHEAD_DONE:
+			MV_DPRINT(("Device %d DEVICE_STATE_ENABLE_READ_AHEAD_DONE.\n", pDevice->Id));
+
+	pDevice->State = DEVICE_STATE_INIT_DONE;
+	pCore->Total_Device_Count++;
+
+#ifdef COMMAND_ISSUE_WORKROUND
+	if (mv_core_check_is_reseeting(pCore)) {
+		MV_DPRINT(("Find disk after reset HBA on port[%d].\n",pPort->Id));
+		mv_core_init_reset_para(pPort);
+	}
+#endif
+
+        	/* No break here. */
+
+		case DEVICE_STATE_INIT_DONE:
+			MV_DPRINT(("Device %d DEVICE_STATE_INIT_DONE.\n", pDevice->Id));
+			/* Check whether all devices attached to this port are done. */
+			for ( i=0; i<MAX_DEVICE_PER_PORT; i++ )
+			{
+				if ( pPort->Device[i].State!=DEVICE_STATE_INIT_DONE )
+					return MV_TRUE;
+			}
+			pPort->Port_State = PORT_STATE_INIT_DONE;
+			mvChannelStateMachine(pCore, pDevice->PPort);
+			break;
+
+		default:
+			break;
+	}
+
+	return MV_TRUE;
+}
+
+/* 
+ * Global controller reset 
+ */
+MV_BOOLEAN
+ResetController(PCore_Driver_Extension pCore)
+{
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_U32 tmp;
+	MV_BOOLEAN ret = MV_TRUE;
+
+/* #if (VER_OEM==VER_OEM_ASUS) */
+	MV_U8 i=0;
+/* #endif */
+
+	/*
+	If enter hibernation, do not do PHY reset to save time
+	*/
+	if (pCore->Is_Dump)
+		return MV_TRUE;
+
+	/* Reset controller */
+	tmp = MV_REG_READ_DWORD(mmio, HOST_CTL);
+	if ((tmp & HOST_RESET) == 0) {
+
+/* #if (VER_OEM==VER_OEM_ASUS) */
+		if(pCore->VS_Reg_Saved!=VS_REG_SIG)
+		{
+			for ( i=0; i<pCore->SATA_Port_Num; i++ )
+			{
+				Domain_Port *port;
+				port = &pCore->Ports[i];
+				MV_REG_WRITE_DWORD(port->Mmio_Base, PORT_VSR_ADDR, 0xc);
+				port->VS_RegC= MV_REG_READ_DWORD(port->Mmio_Base, PORT_VSR_DATA);
+				pCore->VS_Reg_Saved=VS_REG_SIG;
+			}
+		}
+/* #endif */
+		MV_REG_WRITE_DWORD(mmio, HOST_CTL, tmp|HOST_RESET);
+		MV_REG_READ_DWORD(mmio, HOST_CTL); /* flush */
+	}
+
+	/* Reset must complete within 1 second, or the hardware should be considered fried. */
+	HBA_SleepMillisecond(pCore, 1000);
+	//hba_msleep(1000);
+
+	tmp = MV_REG_READ_DWORD(mmio, HOST_CTL);
+	if (tmp & HOST_RESET) {
+		MV_DASSERT(MV_FALSE);	
+		ret = MV_FALSE;
+	}
+
+
+/* #if (VER_OEM==VER_OEM_ASUS) */
+	if(pCore->VS_Reg_Saved==VS_REG_SIG)
+	{
+		for ( i=0; i<pCore->SATA_Port_Num; i++ )
+		{
+			Domain_Port *port;
+			port = &pCore->Ports[i];
+			MV_REG_WRITE_DWORD(port->Mmio_Base, PORT_VSR_ADDR, 0xc);
+			MV_REG_WRITE_DWORD(port->Mmio_Base, PORT_VSR_DATA, port->VS_RegC);
+		}
+	}
+	/* link error work around */
+	for ( i=0; i<pCore->SATA_Port_Num; i++ )
+	{
+		MV_U32 tmp, old_stat;
+		Domain_Port *port;
+		port = &pCore->Ports[i];
+
+		mvDisableIntr( port->Mmio_Base, old_stat );
+		MV_REG_WRITE_DWORD( port->Mmio_Base, PORT_VSR_ADDR, 0x5 );
+		tmp = MV_REG_READ_DWORD( port->Mmio_Base, PORT_VSR_DATA );
+		MV_REG_WRITE_DWORD( port->Mmio_Base, PORT_VSR_DATA, tmp | MV_BIT(26));
+		HBA_SleepMillisecond( pCore, 1 );
+		mvEnableIntr( port->Mmio_Base, old_stat );
+	}
+
+/* #endif */
+	return ret;
+}
+
+void PATA_ResetPort(PCore_Driver_Extension pCore, MV_U8 portId)
+{
+	PDomain_Port pPort = &pCore->Ports[portId];
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 tmp;
+
+	/* Make sure port is not active. If yes, stop the port. */
+	tmp = MV_REG_READ_DWORD(portMmio, PORT_CMD);
+	/* For ACHI, four bits are avaiable. For 614x, PORT_CMD_FIS_ON is reserved. */
+	if (tmp & (PORT_CMD_PATA_LIST_ON | PORT_CMD_PATA_START)) {
+		tmp &= ~(PORT_CMD_PATA_LIST_ON | PORT_CMD_PATA_START);
+		MV_REG_WRITE_DWORD(portMmio, PORT_CMD, tmp);
+		MV_REG_READ_DWORD(portMmio, PORT_CMD); /* flush */
+
+		/* spec says 500 msecs for each bit, so
+			* this is slightly incorrect.
+			*/
+		HBA_SleepMillisecond(pCore, 500);
+	}
+
+	/* Clear error register if any */
+
+	/* Ack any pending irq events for this port */
+	tmp = MV_REG_READ_DWORD(portMmio, PORT_IRQ_STAT)&0xF;
+	if (tmp)
+		MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_STAT, tmp);
+	/* Ack pending irq in the host interrupt status register */
+	MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, 1 << portId);
+
+	/* set irq mask (enables interrupts) */
+#ifdef ENABLE_PATA_ERROR_INTERRUPT
+	MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_MASK, DEF_PORT_PATA_IRQ);
+#else
+	/* 
+	 * Workaround
+	 * If PATA device has a error, even the error bit in the interrupt register is cleared.
+	 * Internal hardware will trigger one more(OS has no idea).
+	 * So because there is interrupt bit not cleared, the next command won't be issued.
+	 */
+	MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_MASK, MV_BIT(2)|MV_BIT(0));
+#endif
+}
+
+void SATA_ResetPort(PCore_Driver_Extension pCore, MV_U8 portId)
+{
+	PDomain_Port pPort = &pCore->Ports[portId];
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_LPVOID portMmio = pPort->Mmio_Base;
+	MV_U32 tmp, j;
+
+	/* Make sure port is not active. If yes, stop the port. */
+	tmp = MV_REG_READ_DWORD(portMmio, PORT_CMD);
+	/* For ACHI, four bits are avaiable. For 614x, PORT_CMD_FIS_ON is reserved. */
+	if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
+			PORT_CMD_FIS_RX | PORT_CMD_START)) {
+		tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
+				PORT_CMD_FIS_RX | PORT_CMD_START);
+		MV_REG_WRITE_DWORD(portMmio, PORT_CMD, tmp);
+		MV_REG_READ_DWORD(portMmio, PORT_CMD); /* flush */
+
+		/* spec says 500 msecs for each bit, so
+			* this is slightly incorrect.
+			*/
+		HBA_SleepMillisecond(pCore, 500);
+		//hba_msleep(500);
+	}
+
+	//PORT_CMD enable bit(5): PIO command will issue PIO setup interrupt bit. 
+	// Only after clear the PIO setup interrupt bit, the hardware will issue the PIO done interrupt bit.
+	// Maybe in this case, we needn't enable PIO setup interrupt bit but for some others we should.
+
+	#ifdef AHCI
+	/* For 614x, it's reserved. */
+	MV_REG_WRITE_DWORD(portMmio, PORT_CMD, PORT_CMD_SPIN_UP);
+	#endif
+
+	/* Wait for SATA DET(Device Detection) */
+	j = 0;
+	while (j < 100) {
+		HBA_SleepMillisecond(pCore, 10);
+		//hba_msleep(10);
+		tmp = MV_REG_READ_DWORD(portMmio, PORT_SCR_STAT);
+		if ((tmp & 0xf) == 0x3)
+			break;
+		j++;
+	}
+
+	
+	/* Clear SATA error */
+	tmp = MV_REG_READ_DWORD(portMmio, PORT_SCR_ERR);
+	MV_REG_WRITE_DWORD(portMmio, PORT_SCR_ERR, tmp);
+
+	/* Ack any pending irq events for this port */
+	tmp = MV_REG_READ_DWORD(portMmio, PORT_IRQ_STAT);
+	if (tmp)
+		MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_STAT, tmp);
+	/* Ack pending irq in the host interrupt status register */
+	MV_REG_WRITE_DWORD(mmio, HOST_IRQ_STAT, 1 << portId);
+
+	/* set irq mask (enables interrupts) */
+	MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_MASK, DEF_PORT_IRQ);
+
+
+	/* FIFO controller workaround for 6121-B0B1B2, 6111-B0B1, and 6145-A0 */
+	if ( 
+		( (pCore->Device_Id==DEVICE_ID_THORLITE_2S1P)&&(pCore->Revision_Id>=0xB0) )
+		||
+		( (pCore->Device_Id==DEVICE_ID_THORLITE_2S1P_WITH_FLASH)&&(pCore->Revision_Id>=0xB0) )
+		||
+		( (pCore->Device_Id==DEVICE_ID_THORLITE_1S1P)&&(pCore->Revision_Id>=0xB0) )	
+		||
+		( (pCore->Device_Id==DEVICE_ID_THOR_4S1P_NEW)&&(pCore->Revision_Id>=0xA0) )
+	)
+	{
+		tmp = (MV_REG_READ_DWORD( portMmio, PORT_FIFO_CTL ) & 0xFFFFF0FF ) | 0x500;
+		MV_REG_WRITE_DWORD( portMmio, PORT_FIFO_CTL, tmp);
+		MV_REG_READ_DWORD( portMmio, PORT_FIFO_CTL);		/* flush */
+	}
+}
+/*
+ * It's equivalent to ahci_host_init and ahci_port_start
+ */
+void InitChip(PCore_Driver_Extension pCore)
+{
+	MV_LPVOID mmio = pCore->Mmio_Base;
+	MV_U8 i;
+	PDomain_Port pPort;
+	MV_U32 tmp;
+
+	pCore->Capacity = MV_REG_READ_DWORD(mmio, HOST_CAP);
+
+	/* 
+	 * For 614x, enable enhanced mode for PATA and interrupt. 
+	 * For AHCI, enable AHCI.
+	 */
+	tmp = MV_REG_READ_DWORD(mmio, HOST_CTL);
+	MV_REG_WRITE_DWORD(mmio, HOST_CTL, (MV_U32)(tmp | HOST_IRQ_EN | HOST_MVL_EN));
+	tmp = MV_REG_READ_DWORD(mmio, HOST_CTL);
+
+	/* Ports implemented: enable ports */
+	pCore->Port_Map = MV_REG_READ_DWORD(mmio, HOST_PORTS_IMPL);
+	tmp = MV_REG_READ_DWORD(mmio, HOST_CAP);
+	//MV_DASSERT( pCore->Port_Num == ((tmp & 0x1f) + 1) );
+
+	/* Initialize ports */
+	for ( i = 0; i<pCore->Port_Num; i++) {
+		pPort = &pCore->Ports[i];
+		/* make sure port is not active */
+		if ( pPort->Type==PORT_TYPE_PATA )
+			PATA_ResetPort(pCore, i);
+		else
+			SATA_ResetPort(pCore, i);
+	}
+
+
+	/* Initialize port, set uncached memory pointer. */
+	for ( i = 0; i<pCore->Port_Num; i++) {
+		pPort = &pCore->Ports[i];
+
+		/* Set the sata port register */
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_LST_ADDR_HI, pPort->Cmd_List_DMA.parts.high);
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_LST_ADDR, pPort->Cmd_List_DMA.parts.low);
+		MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_LST_ADDR);
+
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_FIS_ADDR_HI, pPort->RX_FIS_DMA.parts.high);
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_FIS_ADDR, pPort->RX_FIS_DMA.parts.low);
+		MV_REG_READ_DWORD(pPort->Mmio_Base, PORT_FIS_ADDR);
+
+		/* AHCI is different with Thor */
+		#ifdef AHCI
+		MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_CMD, 
+			PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |	PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP | PORT_CMD_START );
+		#else
+		if ( pPort->Type==PORT_TYPE_PATA )
+		{	/* 12<<24: Bit 24-28: Indicates ATAPI command CDB length in bytes */
+			MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_CMD, (12L<<24) | PORT_CMD_PATA_INTERRUPT | PORT_CMD_PATA_START );
+		}
+		else
+		{
+			/* 
+			 * Workaround: Don't enable PORT_CMD_FIS_RX otherwise system will hang.
+			 */
+			MV_REG_WRITE_DWORD(pPort->Mmio_Base, PORT_CMD, PORT_CMD_START );
+		}
+		#endif
+	}
+
+	//MV_DPRINT("HostCtrl=0x%x,HostIntStatus=0x%x\n",MV_REG_READ_DWORD(mmio, HOST_CTL),MV_REG_READ_DWORD(mmio, HOST_IRQ_STAT));
+
+}
+
+MV_BOOLEAN mvAdapterStateMachine(
+	IN OUT MV_PVOID This,
+	IN MV_PVOID temp
+	)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+
+	switch (pCore->Adapter_State)
+	{
+		case ADAPTER_INITIALIZING:
+			MV_DPRINT(("start mvAdapterStateMachine.\n"));
+			if(ResetController(pCore) == MV_FALSE) 
+				return MV_FALSE;
+
+			InitChip(pCore);
+			pCore->Adapter_State = ADAPTER_READY;
+#ifdef SUPPORT_TIMER
+			Timer_AddRequest( pCore, 2, mvAdapterStateMachine, pCore, NULL );
+#else
+			HBA_RequestTimer(pCore, 2000, (MV_VOID(*)(MV_PVOID))mvAdapterStateMachine);
+#endif
+
+			break;
+
+		case ADAPTER_READY:
+			MV_DPRINT(("start mvChannelStateMachine in timer.\n"));
+			mvChannelStateMachine(pCore, NULL);
+			break;
+
+		default:
+			break;
+	}
+	return MV_TRUE;
+}
+
+void Device_ParseIdentifyData(
+	IN PDomain_Device pDevice,
+	IN PATA_Identify_Data pATAIdentify
+	);
+
+void Core_InternalReqCallback(
+	 IN PCore_Driver_Extension pCore,
+	 IN PMV_Request pReq
+	 )
+{
+	PDomain_Port pPort; 
+	PDomain_Device pDevice;
+	PATA_Identify_Data pATAIdentify;
+	MV_U8 portId, deviceId;
+	MV_U32 tmp;
+
+	portId = PATA_MapPortId(pReq->Device_Id);
+	deviceId = PATA_MapDeviceId(pReq->Device_Id);
+
+	pPort = &pCore->Ports[portId];
+	pDevice = &pPort->Device[deviceId];
+
+	//It's possible that CDB_CORE_READ_LOG_EXT returns error and come here
+	//because we send CDB_CORE_READ_LOG_EXT no matter NCQ is running or not.
+	//if ( pReq->Cdb[2]!=CDB_CORE_READ_LOG_EXT ) 
+	if (( pReq->Cdb[2]!=CDB_CORE_READ_LOG_EXT ) && ( pReq->Cdb[2]!=CDB_CORE_ENABLE_WRITE_CACHE )&&( pReq->Cdb[2]!=CDB_CORE_ENABLE_READ_AHEAD ))
+	{
+		if( pReq->Scsi_Status != REQ_STATUS_SUCCESS )
+		{
+			/* request didn't finish correctly - we set device to existing
+			   and finish state machine */
+			pDevice->Status = DEVICE_STATUS_EXISTING;
+			pDevice->State = DEVICE_STATE_INIT_DONE;
+			mvDeviceStateMachine(pCore, pDevice);
+			return;
+		}
+	}
+
+	pATAIdentify = (PATA_Identify_Data)pPort->Device[deviceId].Scratch_Buffer;
+	/* Handle internal request like identify */
+	MV_DASSERT( pReq->Cdb[0]==SCSI_CMD_MARVELL_SPECIFIC );
+	MV_DASSERT( pReq->Cdb[1]==CDB_CORE_MODULE );
+	MV_ASSERT( portId < MAX_PORT_NUMBER );
+
+	if ( pReq->Cdb[2]==CDB_CORE_IDENTIFY )
+	{
+#ifdef _OS_LINUX
+		hba_swap_buf_le16((MV_PU16) pATAIdentify, 
+				  sizeof(ATA_Identify_Data)/sizeof(MV_U16));
+#endif /* _OS_LINUX  */
+		Device_ParseIdentifyData(pDevice, pATAIdentify);
+		if(pDevice->State != DEVICE_STATE_RESET_DONE){
+			return;
+			}
+		//MV_ASSERT( pDevice->State == DEVICE_STATE_RESET_DONE );
+		pDevice->State = DEVICE_STATE_IDENTIFY_DONE;
+
+		/* Detect PATA Cable:
+		 *** if there are master and slave, only detect after slave 
+			 has finished identify 
+		 *** if there is only master, detect after master has finished
+			 identify 
+		 */
+		if (pPort->Type == PORT_TYPE_PATA)
+		{
+			if ((pDevice->Is_Slave) ||
+				(!(pDevice->Is_Slave) && !(pPort->Device[1].Status & DEVICE_STATUS_FUNCTIONAL)))
+			{
+				tmp = MV_IO_READ_DWORD(pCore->Base_Address[4], 0);
+				if( tmp & MV_BIT(8) )	{//40 pin cable
+					pPort->PATA_cable_type = MV_40_PIN_CABLE;
+				}else {//80 pin cable
+					pPort->PATA_cable_type = MV_80_PIN_CABLE;
+				}
+
+				/* Cable is detected, now we start state machine for master,
+				   if needed */
+				if (pDevice->Is_Slave && (pPort->Device[0].Status & DEVICE_STATUS_FUNCTIONAL))
+				{
+					mvDeviceStateMachine(pCore, &pPort->Device[0]);
+				}
+			}
+		}
+
+		mvDeviceStateMachine(pCore, pDevice);
+		return;
+	}
+	else if ( pReq->Cdb[2]==CDB_CORE_SET_UDMA_MODE )
+	{
+		pDevice->State = DEVICE_STATE_SET_UDMA_DONE;
+		mvDeviceStateMachine(pCore, pDevice);
+	}
+	else if ( pReq->Cdb[2]==CDB_CORE_SET_PIO_MODE )
+	{
+		pDevice->State = DEVICE_STATE_SET_PIO_DONE;
+		mvDeviceStateMachine(pCore, pDevice);
+	}
+	else if ( pReq->Cdb[2]==CDB_CORE_ENABLE_WRITE_CACHE )
+	{
+		pDevice->State = DEVICE_STATE_ENABLE_WRITE_CACHE_DONE;
+		mvDeviceStateMachine(pCore, pDevice);
+	}
+	else if ( pReq->Cdb[2]==CDB_CORE_ENABLE_READ_AHEAD )
+	{
+		pDevice->State = DEVICE_STATE_ENABLE_READ_AHEAD_DONE;
+		mvDeviceStateMachine(pCore, pDevice);
+	}
+	else if ( pReq->Cdb[2]==CDB_CORE_READ_LOG_EXT )
+	{
+		/* Do nothing. Just use this command to clear outstanding IO during error handling. */
+		MV_PRINT("Read Log Ext is finished on device 0x%x.\n", pDevice->Id);
+	}
+}
+
+static void Device_IssueIdentify(
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice
+	)
+{
+	PMV_Request pReq = pDevice->Internal_Req;
+	PMV_SG_Table pSGTable = &pReq->SG_Table;
+
+	MV_ZeroMvRequest(pReq);
+
+	/* Prepare identify ATA task */
+	pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+	pReq->Cdb[1] = CDB_CORE_MODULE;
+	pReq->Cdb[2] = CDB_CORE_IDENTIFY;
+	pReq->Device_Id = pDevice->Id;
+
+	//pReq->Req_Flag;
+	pReq->Cmd_Initiator = pPort->Core_Extension;
+	pReq->Data_Transfer_Length = sizeof(ATA_Identify_Data);
+	pReq->Data_Buffer = pDevice->Scratch_Buffer;
+	pReq->Completion = (void(*)(MV_PVOID,PMV_Request))Core_InternalReqCallback;
+	MV_DASSERT( SATA_SCRATCH_BUFFER_SIZE>=sizeof(ATA_Identify_Data) );
+
+	/* Make SG table */
+	SGTable_Init(pSGTable, 0);
+	SGTable_Append(pSGTable, 
+				pDevice->Scratch_Buffer_DMA.parts.low, 
+				pDevice->Scratch_Buffer_DMA.parts.high,
+				pReq->Data_Transfer_Length
+				); 
+	MV_DASSERT( pReq->Data_Transfer_Length%2==0 );
+
+
+	/* Send this internal request */
+	Core_ModuleSendRequest(pPort->Core_Extension, pReq);
+}
+
+void Device_IssueReadLogExt(
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice
+	)
+{
+	PMV_Request pReq = pDevice->Internal_Req;
+	PMV_SG_Table pSGTable = &pReq->SG_Table;
+
+	MV_ZeroMvRequest(pReq);
+	MV_PRINT("Device_IssueReadLogExt on device 0x%x.\n", pDevice->Id);
+
+	//Disable NCQ after we found NCQ error.
+	pDevice->Capacity &= ~(DEVICE_CAPACITY_NCQ_SUPPORTED);
+
+	/* We support READ LOG EXT command with log page of 10h. */
+	pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+	pReq->Cdb[1] = CDB_CORE_MODULE;
+	pReq->Cdb[2] = CDB_CORE_READ_LOG_EXT;
+	pReq->Device_Id = pDevice->Id;
+
+	//pReq->Req_Flag;
+	pReq->Cmd_Initiator = pPort->Core_Extension;
+	pReq->Data_Transfer_Length = SATA_SCRATCH_BUFFER_SIZE;
+	pReq->Data_Buffer = pDevice->Scratch_Buffer;
+	pReq->Completion = (void(*)(MV_PVOID,PMV_Request))Core_InternalReqCallback;
+	MV_DASSERT( SATA_SCRATCH_BUFFER_SIZE>=sizeof(ATA_Identify_Data) );
+
+	/* Make SG table */
+	SGTable_Init(pSGTable, 0);
+	SGTable_Append(pSGTable, 
+				pDevice->Scratch_Buffer_DMA.parts.low, 
+				pDevice->Scratch_Buffer_DMA.parts.high,
+				pReq->Data_Transfer_Length
+				); 
+	MV_DASSERT( pReq->Data_Transfer_Length%2==0 );
+
+
+	/* Send this internal request */
+	Core_ModuleSendRequest(pPort->Core_Extension, pReq);
+}
+
+static MV_VOID mvAta2HostString(IN MV_U16 *source,
+                                OUT MV_U16 *target,
+                                IN MV_U32 wordsCount
+                               )
+{
+    MV_U32 i;
+    for (i=0 ; i < wordsCount; i++)
+    {
+        target[i] = (source[i] >> 8) | ((source[i] & 0xff) << 8);
+        target[i] = MV_LE16_TO_CPU(target[i]);
+    }
+}
+
+void Device_ParseIdentifyData(
+	IN PDomain_Device pDevice,
+	IN PATA_Identify_Data pATAIdentify
+	)
+{
+	PDomain_Port pPort = pDevice->PPort;
+	MV_U8 i;
+	MV_U32 temp;
+
+	/* Get serial number, firmware revision and model number. */
+	
+	MV_CopyMemory(pDevice->Serial_Number, pATAIdentify->Serial_Number, 20);
+	MV_CopyMemory(pDevice->Firmware_Revision, pATAIdentify->Firmware_Revision, 8);
+
+	MV_CopyMemory(pDevice->Model_Number, pATAIdentify->Model_Number, 40);
+	mvAta2HostString((MV_U16 *)pDevice->Serial_Number, (MV_U16 *)pDevice->Serial_Number, 10);
+	mvAta2HostString((MV_U16 *)pDevice->Firmware_Revision, (MV_U16 *)pDevice->Firmware_Revision, 4);
+
+	mvAta2HostString((MV_U16 *)pDevice->Model_Number, (MV_U16 *)pDevice->Model_Number, 20);
+
+	/* Capacity: 48 bit LBA, smart, write cache and NCQ */
+	pDevice->Capacity = 0;
+	pDevice->Setting = 0;
+	if ( pATAIdentify->Command_Set_Supported[1] & MV_BIT(10) )
+	{
+		MV_DPRINT(("Device: %d 48 bit supported.\n", pDevice->Id));
+
+		pDevice->Capacity |= DEVICE_CAPACITY_48BIT_SUPPORTED;
+	}
+	else
+	{
+		MV_DPRINT(("Device: %d 48 bit not supported.\n", pDevice->Id));
+	}
+
+	if ( pATAIdentify->Command_Set_Supported[0] & MV_BIT(0) ) 
+	{
+		pDevice->Capacity |= DEVICE_CAPACITY_SMART_SUPPORTED;
+		if ( pATAIdentify->Command_Set_Enabled[0] & MV_BIT(0) )
+		{
+			pDevice->Setting |= DEVICE_SETTING_SMART_ENABLED;
+		}
+		if ( pATAIdentify->Command_Set_Supported_Extension & MV_BIT(0) )
+		{
+			pDevice->Capacity |= DEVICE_CAPACITY_SMART_SELF_TEST_SUPPORTED;
+		}
+	}	
+	if ( pATAIdentify->Command_Set_Supported[0] & MV_BIT(5) ) 
+	{
+		pDevice->Capacity |= DEVICE_CAPACITY_WRITECACHE_SUPPORTED;
+		if ( pATAIdentify->Command_Set_Enabled[0] & MV_BIT(5) )
+		{
+			pDevice->Setting |= DEVICE_SETTING_WRITECACHE_ENABLED;
+		}
+	}
+	if ( pATAIdentify->Command_Set_Supported[0] & MV_BIT(6) ) 
+	{
+		pDevice->Capacity |= DEVICE_CAPACITY_READ_LOOK_AHEAD_SUPPORTED;
+		if ( pATAIdentify->Command_Set_Enabled[0] & MV_BIT(6) )
+		{
+			pDevice->Setting |= DEVICE_SETTING_READ_LOOK_AHEAD;
+		}
+	}	
+#ifdef SUPPORT_ATA_SECURITY_CMD
+	if ( pATAIdentify->Security_Status & MV_BIT(0) ) 
+	{
+		pDevice->Capacity |= DEVICE_CAPACITY_SECURITY_SUPPORTED;
+		if (pATAIdentify->Security_Status & MV_BIT(2) )
+		{
+			MV_DPRINT(("securiy: locked\n"));
+			pDevice->Setting |= DEVICE_SETTING_SECURITY_LOCKED;
+		}
+	}
+#endif
+	if ( pATAIdentify->SATA_Capabilities & MV_BIT(8) )
+	{
+
+		if (pDevice->Capacity & DEVICE_CAPACITY_48BIT_SUPPORTED)
+			pDevice->Capacity |= DEVICE_CAPACITY_NCQ_SUPPORTED;
+
+	}
+	if ( pATAIdentify->Command_Set_Supported_Extension & MV_BIT(5) )
+	{
+		if ( pATAIdentify->Command_Set_Default & MV_BIT(5) )
+			pDevice->Capacity |= DEVICE_CAPACITY_READLOGEXT_SUPPORTED;
+	}
+
+	temp = MV_REG_READ_DWORD( pPort->Mmio_Base, PORT_SCR_STAT );
+	if ( ((temp >> 4) & 0xF) == 1 )
+		pDevice->Capacity |= DEVICE_CAPACITY_RATE_1_5G;
+	else if ( ((temp >> 4) & 0xF) == 2 )
+		pDevice->Capacity |= DEVICE_CAPACITY_RATE_3G;
+
+	/* Disk size */
+	if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED )
+	{
+		pDevice->Max_LBA.parts.low = *((MV_PU32)&pATAIdentify->Max_LBA[0]);
+		pDevice->Max_LBA.parts.high = *((MV_PU32)&pATAIdentify->Max_LBA[2]);
+	}else 
+	{
+		pDevice->Max_LBA.parts.low = *((MV_PU32)&pATAIdentify->User_Addressable_Sectors[0]);
+		pDevice->Max_LBA.parts.high = 0;
+	}
+	/* For SATA drive, MAX LBA in identify data is actually disk size */
+	pDevice->Max_LBA = U64_SUBTRACT_U32(pDevice->Max_LBA, 1);
+
+	/* PIO, MDMA and UDMA mode */	
+   	if ( ( pATAIdentify->Fields_Valid&MV_BIT(1) )
+		&& ( pATAIdentify->PIO_Modes&0x0F ) )	
+	{
+       	if ( (MV_U8)pATAIdentify->PIO_Modes>=0x2 )
+		  	pDevice->PIO_Mode = 0x04; 
+		else
+	  		pDevice->PIO_Mode = 0x03; 
+	}
+    else
+	{
+       	pDevice->PIO_Mode = 0x02;
+	}
+
+	pDevice->MDMA_Mode = 0xFF;
+	if ( pATAIdentify->Multiword_DMA_Modes & MV_BIT(2) )
+		pDevice->MDMA_Mode = 2;
+	else if ( pATAIdentify->Multiword_DMA_Modes & MV_BIT(1) )
+		pDevice->MDMA_Mode = 1;
+	else if ( pATAIdentify->Multiword_DMA_Modes & MV_BIT(0) )
+		pDevice->MDMA_Mode = 0;
+
+	pDevice->UDMA_Mode = 0xFF;
+    if ( pATAIdentify->Fields_Valid&MV_BIT(2) )
+	{
+		for ( i=0; i<7; i++ )
+		{
+			if ( pATAIdentify->UDMA_Modes & MV_BIT(i) )
+				pDevice->UDMA_Mode = i;	
+		}
+	}	
+
+	/* CRC identify buffer to get the U32 GUID. */
+	pDevice->WWN = MV_CRC((MV_PU8)pATAIdentify, sizeof(ATA_Identify_Data));
+
+}
+
+static void Device_IssueSetMDMAMode(
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PMV_Request pReq = pDevice->Internal_Req;
+    MV_U32 temp;
+	MV_U32 offset;
+	MV_LPVOID base;
+	MV_BOOLEAN memoryIO=MV_FALSE;
+	MV_U8 mode = pDevice->MDMA_Mode;
+
+	/* Only if the Device doesn't support UDMA, we'll use MDMA mode. */
+	MV_DASSERT( pDevice->UDMA_Mode==0xFF );
+	/* Is that possible that one device doesn't support either UDMA and MDMA? */
+	MV_DASSERT( (pDevice->MDMA_Mode<=2) );
+	MV_ZeroMvRequest(pReq);
+
+	/* Set controller timing register for PATA port before set the device MDMA mode. */
+	if ( pPort->Type==PORT_TYPE_PATA )
+	{
+		if ( pCore->Device_Id==DEVICE_ID_THORLITE_2S1P 
+			|| pCore->Device_Id==DEVICE_ID_THORLITE_2S1P_WITH_FLASH
+			|| pCore->Device_Id==DEVICE_ID_THORLITE_0S1P )
+		{
+			if ( pCore->Revision_Id==0xA0 )
+			{
+				/* Thorlite A0 */
+				temp = MV_IO_READ_DWORD(pCore->Base_Address[4], 0);
+				temp &= 0xFFFF00FF;
+				temp |= 0x0000A800;
+				MV_IO_WRITE_DWORD(pCore->Base_Address[4], 0, temp);
+
+				if ( !pDevice->Is_Slave ) 
+					offset = 0x10;
+				else
+					offset = 0x14;
+				base = pCore->Base_Address[4];
+				memoryIO = MV_FALSE;
+			}
+			else
+			{
+				/* Thorlite B0 */
+				MV_DASSERT( (pCore->Revision_Id==0xB0)||(pCore->Revision_Id==0xB1)||(pCore->Revision_Id==0xB2) );
+				if ( !pDevice->Is_Slave )
+					offset = 0xA0;
+				else
+					offset = 0xA4;
+				base = pCore->Base_Address[5];
+				memoryIO = MV_TRUE;
+			}
+		} 
+		else
+		{
+			MV_DASSERT( (pCore->Device_Id==DEVICE_ID_THOR_4S1P)||(pCore->Device_Id==DEVICE_ID_THOR_4S1P_NEW) );
+			if ( pCore->Revision_Id==0x00	/* A0 */
+				|| pCore->Revision_Id==0x01	/* A1 */
+				|| pCore->Revision_Id==0x10	/* B0 and C0 */	)
+			{
+				/* Thor A0-C0 */
+				if ( !pDevice->Is_Slave )
+					offset = 0x08;
+				else
+					offset = 0x0c;
+				base = pCore->Base_Address[4];
+				memoryIO = MV_FALSE;
+			}
+			else
+			{
+				/* Thor D0 = Thor New A0 */
+				MV_DASSERT( (pCore->Revision_Id==0xA0) || (pCore->Revision_Id==0xA1) ||
+							(pCore->Revision_Id==0xA2) );
+				if ( !pDevice->Is_Slave )
+					offset = 0xA0;
+				else
+					offset = 0xA4;
+				base = pCore->Base_Address[5];
+				memoryIO = MV_TRUE;
+			}
+		}
+
+		if ( !memoryIO )
+		{
+			temp = MV_IO_READ_DWORD(base, offset);
+			temp &= 0xFFFFFF3F;
+			temp |= ((MV_U32)mode)<<6;
+			temp |= 0x100;		/* Enable MDAM */
+			MV_IO_WRITE_DWORD(base, offset, temp);
+		}
+		else
+		{
+			temp = MV_REG_READ_DWORD(base, offset);
+			temp &= 0xFFFFFF3F;
+			temp |= ((MV_U32)mode)<<6;
+			temp |= 0x100;		/* Enable MDAM */
+			MV_REG_WRITE_DWORD(base, offset, temp);
+		}
+	}
+
+	//pDevice->MDMA_Mode = mode;
+	pDevice->Current_MDMA = mode;
+	
+	/* Prepare set UDMA mode task */
+	pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+	pReq->Cdb[1] = CDB_CORE_MODULE;
+	pReq->Cdb[2] = CDB_CORE_SET_UDMA_MODE;
+	pReq->Cdb[3] = mode;
+	/* Means we are setting MDMA mode. I still use CDB_CORE_SET_UDMA_MODE because I don't want to change the state machine. */
+	pReq->Cdb[4] = MV_TRUE;
+	pReq->Device_Id = pDevice->Id;
+	//pReq->Req_Flag;
+	pReq->Cmd_Initiator = pPort->Core_Extension;
+	pReq->Data_Transfer_Length = 0;
+	pReq->Data_Buffer = NULL;
+	pReq->Completion = (void(*)(MV_PVOID,PMV_Request))Core_InternalReqCallback;
+
+
+	/* Send this internal request */
+	Core_ModuleSendRequest(pPort->Core_Extension, pReq);
+}
+
+static void Device_IssueSetUDMAMode(
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PMV_Request pReq = pDevice->Internal_Req;
+    MV_U32 temp;
+	MV_U32 offset;
+	MV_LPVOID base;
+	MV_BOOLEAN memoryIO=MV_FALSE;
+	MV_U8 mode = pDevice->UDMA_Mode;
+	
+	if ( pDevice->UDMA_Mode==0xFF )
+	{
+		Device_IssueSetMDMAMode(pPort, pDevice);
+		return;
+	}
+
+	//GT 10/19/2006 11:07AM
+	//Check PATA port cable if 40_pin or 80_pin
+	if ( pPort->Type==PORT_TYPE_PATA )
+	{
+#ifdef PATA_CABLE_DETECTION
+		if (pPort->PATA_cable_type==MV_40_PIN_CABLE){
+			if ( mode>2 ) 
+				mode = 2;
+			pDevice->UDMA_Mode = mode;
+		}
+#else
+		temp = MV_IO_READ_DWORD(pCore->Base_Address[4], 0);
+		if( temp & MV_BIT(8) )	//40_pin cable
+		{
+			if ( mode>2 ) 
+				mode = 2;
+			pDevice->UDMA_Mode = mode;
+		}
+#endif
+	}	
+	
+	/* Hardware team required us to downgrade UDMA mode to zero. */
+	//if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+	//	mode = 0;
+	//if ( mode>=5 ) mode = 4; //???
+
+	MV_ZeroMvRequest(pReq);
+
+	//if ( (pCore->Device_Id!=DEVICE_ID_THOR_4S1P_NEW) && (pCore->Revision_Id!=0xB0) && (pCore->Revision_Id!=0xB1) && (pCore->Revision_Id!=0xB2) )
+	if ( (pCore->Device_Id!=DEVICE_ID_THOR_4S1P_NEW) && (pCore->Revision_Id<0xB0) )
+	{
+		/* Degrade ATAPI device UDMA mode always to 2. */
+		if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+		{
+			if ( mode>2 ) mode = 2;
+		}
+		else
+		{
+			/*
+			* Workaround:
+			* Thor lite A0 has problem with Hitesh(IBM) HDD under UDMA 5
+			* And it has problem with any HDD under UDMA 6
+			* So we degrade the HDD mode to 5 and ignore Hitesh HDD for now.
+			*/
+			if ( mode>5 ) mode = 5;
+		}
+	}
+
+	/* 
+	 * Set controller timing register for PATA port before set the device UDMA mode.
+	 * Thorlite A0:	To enable timing programming, BAR 4 offset x0, write a800
+	 *				To set values, BAR 4 offset x10, x14
+	 * Thorlite B0:	BAR 5 offset xa0, xa4
+	 * Thor A0~C0:	BAR 4 offset x8, xc
+	 * Thor D0(=Thor New A0):BAR 5 offset xa0, xa4 ( Same as Thorlite B0 )
+	 */
+	if ( pPort->Type==PORT_TYPE_PATA )
+	{
+		if ( pCore->Device_Id==DEVICE_ID_THORLITE_2S1P 
+			|| pCore->Device_Id==DEVICE_ID_THORLITE_2S1P_WITH_FLASH
+			|| pCore->Device_Id==DEVICE_ID_THORLITE_0S1P )
+		{
+			if ( pCore->Revision_Id==0xA0 )
+			{
+				/* Thorlite A0 */
+				temp = MV_IO_READ_DWORD(pCore->Base_Address[4], 0);
+				temp &= 0xFFFF00FF;
+				temp |= 0x0000A800;
+				MV_IO_WRITE_DWORD(pCore->Base_Address[4], 0, temp);
+
+				if ( !pDevice->Is_Slave ) 
+					offset = 0x10;
+				else
+					offset = 0x14;
+				base = pCore->Base_Address[4];
+				memoryIO = MV_FALSE;
+			}
+			else
+			{
+				/* Thorlite B0 */
+				MV_DASSERT( (pCore->Revision_Id==0xB0)||(pCore->Revision_Id==0xB1)||(pCore->Revision_Id==0xB2) );
+				if ( !pDevice->Is_Slave )
+					offset = 0xA0;
+				else
+					offset = 0xA4;
+				base = pCore->Base_Address[5];
+				memoryIO = MV_TRUE;
+			}
+		} 
+		else
+		{
+			MV_DASSERT( (pCore->Device_Id==DEVICE_ID_THOR_4S1P)||(pCore->Device_Id==DEVICE_ID_THOR_4S1P_NEW) );
+			if ( pCore->Revision_Id==0x00	/* A0 */
+				|| pCore->Revision_Id==0x01	/* A1 */
+				|| pCore->Revision_Id==0x10	/* B0 and C0 */	)
+			{
+				/* Thor A0-C0 */
+				if ( !pDevice->Is_Slave )
+					offset = 0x08;
+				else
+					offset = 0x0c;
+				base = pCore->Base_Address[4];
+				memoryIO = MV_FALSE;
+			}
+			else
+			{
+				/* Thor D0 = Thor New A0 */
+				MV_DASSERT( (pCore->Revision_Id==0xA0) || (pCore->Revision_Id==0xA1) ||
+							(pCore->Revision_Id==0xA2) );
+				if ( !pDevice->Is_Slave )
+					offset = 0xA0;
+				else
+					offset = 0xA4;
+				base = pCore->Base_Address[5];
+				memoryIO = MV_TRUE;
+			}
+		}
+
+		if ( !memoryIO )
+		{
+			temp = MV_IO_READ_DWORD(base, offset);
+			temp &= 0xFFFFFFF8;
+			temp |= (MV_U32)mode;
+			MV_IO_WRITE_DWORD(base, offset, temp);
+		}
+		else
+		{
+			temp = MV_REG_READ_DWORD(base, offset);
+			temp &= 0xFFFFFFF8;
+			temp |= (MV_U32)mode;
+			MV_REG_WRITE_DWORD(base, offset, temp);
+		}
+	}
+
+	//pDevice->UDMA_Mode = mode;
+	pDevice->Current_UDMA = mode;
+
+	/* Prepare set UDMA mode task */
+	pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+	pReq->Cdb[1] = CDB_CORE_MODULE;
+	pReq->Cdb[2] = CDB_CORE_SET_UDMA_MODE;
+	pReq->Cdb[3] = mode;
+	/* Not setting MDMA but UDMA mode. */
+	pReq->Cdb[4] = MV_FALSE;
+	pReq->Device_Id = pDevice->Id;
+	//pReq->Req_Flag;
+	pReq->Cmd_Initiator = pPort->Core_Extension;
+	pReq->Data_Transfer_Length = 0;
+	pReq->Data_Buffer = NULL;
+	pReq->Completion = (void(*)(MV_PVOID,PMV_Request))Core_InternalReqCallback;
+
+
+	/* Send this internal request */
+	Core_ModuleSendRequest(pPort->Core_Extension, pReq);
+}
+
+static void Device_IssueSetPIOMode(
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PMV_Request pReq = pDevice->Internal_Req;
+    MV_U32 temp;
+	MV_U32 offset;
+	MV_LPVOID base;
+	MV_BOOLEAN memoryIO=MV_FALSE;
+	MV_U8 mode = pDevice->PIO_Mode;
+	
+	MV_ZeroMvRequest(pReq);
+
+	/* Hardware team required us to downgrade PIO mode to zero. */
+	if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+		mode = 0;
+
+
+	/* 
+	 * Set controller timing register for PATA port before set the device UDMA mode.
+	 * Thorlite A0:	To enable timing programming, BAR 4 offset x0, write a800
+	 *				To set values, BAR 4 offset x10, x14
+	 * Thorlite B0:	BAR 5 offset xa0, xa4
+	 * Thor A0~C0:	BAR 4 offset x8, xc
+	 * Thor D0:		BAR 5 offset xa0, xa4 ( Same as Thorlite B0 )
+	 */
+	if ( pPort->Type==PORT_TYPE_PATA )
+	{
+
+		if ( pCore->Device_Id==DEVICE_ID_THORLITE_2S1P 
+			|| pCore->Device_Id==DEVICE_ID_THORLITE_2S1P_WITH_FLASH
+			|| pCore->Device_Id==DEVICE_ID_THORLITE_0S1P )
+		{
+			if ( pCore->Revision_Id==0xA0 )
+			{
+				/* Thorlite A0 */
+				temp = MV_IO_READ_DWORD(pCore->Base_Address[4], 0);
+				temp &= 0xFFFF00FF;
+				temp |= 0x0000A800;
+				MV_IO_WRITE_DWORD(pCore->Base_Address[4], 0, temp);
+
+				if ( !pDevice->Is_Slave ) 
+					offset = 0x10;
+				else
+					offset = 0x14;
+				base = pCore->Base_Address[4];
+				memoryIO = MV_FALSE;
+			}
+			else
+			{
+				/* Thorlite B0 */
+				MV_DASSERT( (pCore->Revision_Id==0xB0)||(pCore->Revision_Id==0xB1)||(pCore->Revision_Id==0xB2) );
+				if ( !pDevice->Is_Slave )
+					offset = 0xA0;
+				else
+					offset = 0xA4;
+				base = pCore->Base_Address[5];
+				memoryIO = MV_TRUE;
+			}
+		} 
+		else
+		{
+
+			MV_DASSERT( (pCore->Device_Id==DEVICE_ID_THOR_4S1P)||(pCore->Device_Id==DEVICE_ID_THOR_4S1P_NEW) );
+			if ( pCore->Revision_Id==0x00	/* A0 */
+				|| pCore->Revision_Id==0x01	/* A1 */
+				|| pCore->Revision_Id==0x10	/* B0 and C0 */	)
+			{
+				/* Thor A0-C0 */
+				if ( !pDevice->Is_Slave )
+					offset = 0x08;
+				else
+					offset = 0x0c;
+				base = pCore->Base_Address[4];
+				memoryIO = MV_FALSE;
+			}
+			else
+			{
+				/* Thor D0 = Thor New A0 */
+				MV_DASSERT( (pCore->Revision_Id==0xA0) || (pCore->Revision_Id==0xA1) ||
+							(pCore->Revision_Id==0xA2) );
+				if ( !pDevice->Is_Slave )
+					offset = 0xA0;
+				else
+					offset = 0xA4;
+				base = pCore->Base_Address[5];
+				memoryIO = MV_TRUE;
+			}
+		}
+
+		if ( !memoryIO )
+		{
+			temp = MV_IO_READ_DWORD(base, offset);
+			temp &= 0xFFFFFFC7;
+			temp |= ((MV_U32)mode<<3);
+			MV_IO_WRITE_DWORD(base, offset, temp);
+		}
+		else
+		{
+			temp = MV_REG_READ_DWORD(base, offset);
+			temp &= 0xFFFFFFC7;
+			temp |= ((MV_U32)mode<<3);
+			MV_REG_WRITE_DWORD(base, offset, temp);
+		}
+	}
+
+	//pDevice->PIO_Mode = mode;
+	pDevice->Current_PIO = mode;
+	
+	/* Prepare set PIO mode task */
+	pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+	pReq->Cdb[1] = CDB_CORE_MODULE;
+	pReq->Cdb[2] = CDB_CORE_SET_PIO_MODE;
+	pReq->Cdb[3] = mode;
+	pReq->Device_Id = pDevice->Id;
+	//pReq->Req_Flag;
+	pReq->Cmd_Initiator = pPort->Core_Extension;
+	pReq->Data_Transfer_Length = 0;
+	pReq->Data_Buffer = NULL;
+	pReq->Completion = (void(*)(MV_PVOID,PMV_Request))Core_InternalReqCallback;
+
+	/* Send this internal request */
+	Core_ModuleSendRequest(pPort->Core_Extension, pReq);
+
+}
+
+static void Device_EnableWriteCache(
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PMV_Request pReq = pDevice->Internal_Req;
+
+	MV_ZeroMvRequest(pReq);
+
+	/* Prepare enable write cache command */
+	pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+	pReq->Cdb[1] = CDB_CORE_MODULE;
+	pReq->Cdb[2] = CDB_CORE_ENABLE_WRITE_CACHE;
+	pReq->Device_Id = pDevice->Id;
+	//pReq->Req_Flag;
+	pReq->Cmd_Initiator = pPort->Core_Extension;
+	pReq->Data_Transfer_Length = 0;
+	pReq->Data_Buffer = NULL;
+	pReq->Completion = (void(*)(MV_PVOID,PMV_Request))Core_InternalReqCallback;
+
+	/* skip if this is ATAPI device */
+	if( pDevice->Device_Type & DEVICE_TYPE_ATAPI )
+	{
+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+		pReq->Completion(pCore, pReq);
+	}
+	else
+	{
+
+		/* Send this internal request */
+		Core_ModuleSendRequest(pPort->Core_Extension, pReq);
+	}
+}
+
+static void Device_EnableReadAhead(
+	IN PDomain_Port pPort,
+	IN PDomain_Device pDevice
+	)
+{
+	PCore_Driver_Extension pCore = pPort->Core_Extension;
+	PMV_Request pReq = pDevice->Internal_Req;
+
+	MV_ZeroMvRequest(pReq);
+
+	/* Prepare enable read ahead command */
+	pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+	pReq->Cdb[1] = CDB_CORE_MODULE;
+	pReq->Cdb[2] = CDB_CORE_ENABLE_READ_AHEAD;
+	pReq->Device_Id = pDevice->Id;
+	//pReq->Req_Flag;
+	pReq->Cmd_Initiator = pPort->Core_Extension;
+	pReq->Data_Transfer_Length = 0;
+	pReq->Data_Buffer = NULL;
+	pReq->Completion = (void(*)(MV_PVOID,PMV_Request))Core_InternalReqCallback;
+
+	/* skip if this is ATAPI device */
+	if( pDevice->Device_Type & DEVICE_TYPE_ATAPI )
+	{
+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;
+		pReq->Completion(pCore, pReq);
+	}
+	else
+	{
+		/* Send this internal request */
+		Core_ModuleSendRequest(pPort->Core_Extension, pReq);
+	}
+}
+
diff --git a/drivers/scsi/thor/core/thor/core_init.h b/drivers/scsi/thor/core/thor/core_init.h
new file mode 100755
index 0000000..1a23a37
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_init.h
@@ -0,0 +1,135 @@
+#if !defined(CORE_INIT_H)
+#define CORE_INIT_H
+
+#include "core_inter.h"
+
+typedef enum mvAdapterState
+{
+    ADAPTER_INITIALIZING,
+    ADAPTER_READY,
+    ADAPTER_FATAL_ERROR
+} MV_ADAPTER_STATE;
+
+typedef enum mvChannelState	
+{
+    CHANNEL_NOT_CONNECTED,
+    CHANNEL_CONNECTED,
+    CHANNEL_IN_SRST,
+    CHANNEL_PM_STAGGERED_SPIN_UP,
+    CHANNEL_PM_SRST_DEVICE,
+    CHANNEL_READY,
+    CHANNEL_PM_HOT_PLUG,
+} MV_CHANNEL_STATE;
+
+MV_BOOLEAN mvAdapterStateMachine(
+	MV_PVOID This,
+	MV_PVOID temp
+	);
+
+void SATA_PortReset(
+	PDomain_Port pPort,
+	MV_BOOLEAN hardReset
+	);
+
+void PATA_PortReset(
+	PDomain_Port pPort,
+	MV_BOOLEAN hardReset
+	);
+void Core_InternalReqCallback(
+	 IN PCore_Driver_Extension pCore,
+	 IN PMV_Request pReq
+	 );
+
+MV_BOOLEAN SATA_DoSoftReset(PDomain_Port pPort, MV_U8 PMPort);
+
+#define SATA_PortDeviceDetected(port)	\
+	 ( MV_REG_READ_DWORD(port->Mmio_Base, PORT_SCR_STAT) & 0x01 )
+
+#define SATA_PortDeviceReady(port)		\
+	(								\
+		( ( (MV_REG_READ_DWORD(port->Mmio_Base, PORT_SCR_STAT) & 0x0F00 ) >> 8) != PORT_SSTATUS_IPM_NO_DEVICE )		\
+	)
+
+#define FIS_REG_H2D_SIZE_IN_DWORD	5
+
+/* PM related - move elsewhere? */
+#define MV_ATA_COMMAND_PM_READ_REG              0xe4
+#define MV_ATA_COMMAND_PM_WRITE_REG             0xe8
+
+#define MV_SATA_GSCR_ID_REG_NUM                 0
+#define MV_SATA_GSCR_REVISION_REG_NUM           1
+#define MV_SATA_GSCR_INFO_REG_NUM               2
+#define MV_SATA_GSCR_ERROR_REG_NUM              32
+#define MV_SATA_GSCR_ERROR_ENABLE_REG_NUM       33
+#define MV_SATA_GSCR_FEATURES_REG_NUM           64
+#define MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM    96
+
+#define MV_SATA_PSCR_SSTATUS_REG_NUM            0
+#define MV_SATA_PSCR_SERROR_REG_NUM             1
+#define MV_SATA_PSCR_SCONTROL_REG_NUM           2
+#define MV_SATA_PSCR_SACTIVE_REG_NUM            3
+
+#define MV_Read_Reg  1
+#define MV_Write_Reg 0
+
+void mvPMDevReWrReg(
+	PDomain_Port pPort, 
+	MV_U8 read, 
+	MV_U8 PMreg, 
+	MV_U32 regVal, 
+	MV_U8 PMport, 
+	MV_BOOLEAN control
+	);
+
+void SATA_InitPM (
+    PDomain_Port pPort
+	);
+
+void SATA_InitPMPort (
+	PDomain_Port pPort,
+	MV_U8 portNum
+	);
+
+MV_BOOLEAN SATA_SoftResetDevice(
+	PDomain_Port pPort, 
+	MV_U8 portNum
+	);
+
+MV_BOOLEAN SATA_PortSoftReset( 
+	PCore_Driver_Extension pCore, 
+	PDomain_Port pPort 
+	);
+
+void SATA_PortReportNoDevice (
+    PCore_Driver_Extension pCore, 
+	PDomain_Port pPort
+	);
+
+PMV_Request GetInternalReqFromPool( 
+	PCore_Driver_Extension pCore
+	);
+
+void ReleaseInternalReqToPool( 
+	PCore_Driver_Extension pCore, 
+	PMV_Request pReq
+	);
+
+#define mvDisableIntr(portMmio, old_stat) do{ \
+		old_stat = MV_REG_READ_DWORD(portMmio, PORT_IRQ_MASK); \
+		MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_MASK, 0);\
+		}while(0)
+
+#define mvEnableIntr(portMmio, old_stat)	MV_REG_WRITE_DWORD(portMmio, PORT_IRQ_MASK, old_stat)
+
+#define mvDisableGlobalIntr(mmio, old_stat) do{ \
+		old_stat = MV_REG_READ_DWORD(mmio, HOST_CTL); \
+		MV_REG_WRITE_DWORD(mmio, HOST_CTL, old_stat & (~HOST_IRQ_EN));\
+		}while(0)
+
+#define mvEnableGlobalIntr(mmio, old_stat)	MV_REG_WRITE_DWORD(mmio, HOST_CTL, old_stat)
+
+
+#define CORE_MAX_RESET_COUNT		0xffff	
+#define CORE_MAX_PATA_RESET_COUNT	0xffff
+#endif
+
diff --git a/drivers/scsi/thor/core/thor/core_inter.h b/drivers/scsi/thor/core/thor/core_inter.h
new file mode 100755
index 0000000..3126ea7
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_inter.h
@@ -0,0 +1,78 @@
+#if !defined(CORE_MAIN_H)
+#define CORE_MAIN_H
+
+#include "core_thor.h"
+
+#ifdef SUPPORT_CONSOLIDATE
+#include "consolid.h"
+#endif
+
+#ifdef _OS_WINDOWS
+#define CPU_TO_LE_16(x) x
+#define CPU_TO_LE_32(x) x
+#endif /* _OS_WINDOWS  */
+
+struct _Domain_Port;
+typedef struct _Domain_Port Domain_Port, *PDomain_Port;
+
+struct _Domain_Device;
+typedef struct _Domain_Device Domain_Device, *PDomain_Device;
+
+#define CORE_STATE_IDLE			0
+#define CORE_STATE_STARTED		1
+
+/* Flag definition for Fast Boot Skip */
+#define FLAG_SKIP_PATA_PORT		MV_BIT(0)
+#define FLAG_SKIP_PATA_DEVICE	MV_BIT(1)
+#define FLAG_SKIP_PM			MV_BIT(2)
+
+typedef struct _Core_Driver_Extension
+{
+#ifdef __MM_SE__	
+/* Must be first */
+	struct mv_mod_desc *desc;
+#endif /* __MM_SE__ */	
+	MV_LPVOID	Mmio_Base;						/* Memory IO base address */
+	MV_U16		Vendor_Id;
+	MV_U16		Device_Id;
+	MV_U8		State;
+	MV_U8		Revision_Id;
+	MV_U8		VS_Reg_Saved;
+	MV_U8		Flag_Fastboot_Skip;
+
+	MV_U32		Capacity;						
+	MV_U32		Port_Map;
+	MV_U8		Port_Num;						/* How much ports we have? */
+	MV_U8		SATA_Port_Num;
+	MV_U8		PATA_Port_Num;
+	MV_U8		Adapter_State;					/* Adatper state */
+	MV_U8		Is_Dump;						/* Is during dump */
+	MV_U8		Need_Reset;						/* Need_Reset == 1 means controller need reset. Lily 3/7/2006*/
+	MV_U8		Resetting;
+
+	MV_U8		Total_Device_Count;
+#ifndef  SUPPORT_TASKLET
+	MV_U8		Reserved1;
+	MV_U8		Reserved2[3];
+#else
+	MV_U32		Saved_ISR_Status;						
+#endif
+
+	MV_LPVOID	Base_Address[MAX_BASE_ADDRESS];	/* Base Address */
+	Domain_Port Ports[MAX_PORT_NUMBER];			/* Domain Ports */
+
+	List_Head	Waiting_List; 					/* Waiting Request Queue */
+	List_Head	Internal_Req_List;				/* Internal Request Queue */
+
+#ifdef SUPPORT_CONSOLIDATE
+	PConsolidate_Extension	pConsolid_Extent;	
+	PConsolidate_Device		pConsolid_Device;
+#endif
+#ifdef COMMAND_ISSUE_WORKROUND
+	MV_U32 	error_handle_state;
+	MV_U8 resetting_command;
+#endif
+}Core_Driver_Extension, *PCore_Driver_Extension;
+
+#endif /* CORE_MAIN_H */
+
diff --git a/drivers/scsi/thor/core/thor/core_sat.c b/drivers/scsi/thor/core/thor/core_sat.c
new file mode 100755
index 0000000..093a283
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_sat.c
@@ -0,0 +1,838 @@
+#include "mv_include.h"

+#include "core_sat.h"

+#include "core_inter.h"

+#include "core_thor.h"

+#include "core_exp.h"

+#include "core_sata.h"

+#include "core_ata.h"

+#include "core_init.h"

+

+#ifdef SUPPORT_ATA_SMART

+

+/***************************************************************************

+* SCSI_ATA_CheckCondition

+* Purpose: Send Check Condition when request is illegal

+*

+***************************************************************************/

+void SCSI_ATA_CheckCondition(

+	IN PMV_Request pReq,

+	IN MV_U8 senseKey,

+	IN MV_U8 senseCode

+	)

+{

+	 pReq->Scsi_Status = SCSI_STATUS_CHECK_CONDITION;

+	 if ( pReq->Sense_Info_Buffer ) {

+		((MV_PU8)pReq->Sense_Info_Buffer)[2] = senseKey;

+		((MV_PU8)pReq->Sense_Info_Buffer)[7] = 0;		// additional sense length 

+		((MV_PU8)pReq->Sense_Info_Buffer)[12] = senseCode; //additional sense code

+	 }

+}

+

+#define MAX_MODE_PAGE_LENGTH	28

+MV_U32 Core_get_mode_page_caching(MV_PU8 pBuf, PDomain_Device pDevice)

+{

+	pBuf[0] = 0x08;		/* Page Code, PS = 0; */

+	pBuf[1] = 0x12;		/* Page Length */

+	/* set the WCE and RCD bit based on device identification data */

+	if (pDevice->Setting & DEVICE_SETTING_WRITECACHE_ENABLED)

+		pBuf[2] |= MV_BIT(2);

+	pBuf[3] = 0;	/* Demand read/write retention priority */

+	pBuf[4] = 0xff;	/* Disable pre-fetch trnasfer length (4,5) */

+	pBuf[5] = 0xff;	/* all anticipatory pre-fetching is disabled */

+	pBuf[6] = 0;	/* Minimum pre-fetch (6,7) */

+	pBuf[7] = 0;

+	pBuf[8] = 0;	/* Maximum pre-fetch (8,9) */

+	pBuf[9] = 0x01;

+	pBuf[10] = 0;	/* Maximum pre-fetch ceiling (10,11) */

+	pBuf[11] = 0x01;

+//	pBuf[12] |= MV_BIT(5);	/* How do I know if Read Ahead is enabled or disabled???  */

+	pBuf[12] = 0x00;

+	pBuf[13] = 0x01;	/* Number of cache segments */

+	pBuf[14] = 0xff;	/* Cache segment size (14, 15) */

+	pBuf[15] = 0xff;

+	return 0x14;	/* Total page length in byte */

+}

+

+MV_U32 Core_Fill_ProSpecPortModePage(MV_PU8 pBuf)

+{

+	static const MV_U8 pro_spec_mode_page[] = {

+		0x19,/*Protocol Specific Port mode page*/

+		0x01,	/*Page Length*/

+		0x08, /*protocol identify*/

+		0,

+	};

+	MV_CopyMemory(pBuf, pro_spec_mode_page, sizeof(pro_spec_mode_page));

+	return sizeof(pro_spec_mode_page);	/* Total page length in byte */

+}

+

+static const MV_U8 info_except_ctrl_mode_page[] = {

+	0x1c,	/* Page Code, PS = 0; */

+	0x0a,  /* Page Length */

+	0xb7, /* Report Error  */

+	0x04, /*set MRIE*/

+	0, 0, 0, 0,

+	0, 0, 0, 0

+};

+

+MV_U32 Core_Fill_InfoExcepCtrlModePage(MV_PU8 pBuf, PDomain_Device pDevice,PMV_Request pReq)

+{

+	MV_CopyMemory(pBuf, info_except_ctrl_mode_page, sizeof(info_except_ctrl_mode_page));

+	

+	// Setting Extended Self-test Completion time

+	if(!(pDevice->Capacity & DEVICE_CAPACITY_SMART_SUPPORTED))	

+	{

+		SCSI_ATA_CheckCondition(pReq, SCSI_SK_ILLEGAL_REQUEST, 

+				SCSI_ASC_INVALID_FEILD_IN_CDB);

+	}

+	return sizeof( info_except_ctrl_mode_page);	/* Total page length in byte */

+}

+

+

+

+MV_U32  Core_Fill_CtrlModePage(MV_PU8 pBuf, PDomain_Device pDevice)

+{

+	static const MV_U8 ctrl_mode_page[] = {

+		0x0a,

+		10,

+		2,	/* DSENSE=0, GLTSD=1 */

+		0,	/* [QAM+QERR may be 1, see 05-359r1] */

+		0, 0, 0, 0, 0, 0,

+		0x02, 0x4b	/* extended self test time, see 05-359r1 */

+	};

+	MV_CopyMemory(pBuf, ctrl_mode_page, sizeof(ctrl_mode_page));

+

+	// Setting Extended Self-test Completion time

+	if(pDevice->Capacity & DEVICE_CAPACITY_SMART_SELF_TEST_SUPPORTED)

+	{

+		pBuf[10] = 0;

+		pBuf[11] = 30;

+	} else {

+		pBuf[10] = 0;

+		pBuf[11] = 0;

+	}

+	return sizeof(ctrl_mode_page);

+}

+

+MV_U32  Core_Fill_RWErrorRecoveryModePage(MV_PU8 pBuf )

+{

+	static const MV_U8 rw_recovery_mdpage[] = {

+		0x01,

+		10,

+		(1 << 7),	/* AWRE */

+		0,		/* read retry count */

+		0, 0, 0, 0,

+		0,		/* write retry count */

+		0, 0, 0

+	};

+	MV_CopyMemory(pBuf, rw_recovery_mdpage, sizeof(rw_recovery_mdpage));

+	return sizeof(rw_recovery_mdpage);

+}

+

+MV_U32 Core_Fill_ErrorCounterLogPage(MV_PU8 pBuf)

+{

+	static const MV_U8 error_counter_log_pg[] = {

+		0x03,	/* DU =0, DS =0, TSD =0, ETC=0, TMC=00, FL=11 */

+		0x02, 	/* Parameter length */

+		0x00 ,0x00

+	};

+

+	pBuf[0] = 0x00;	/* Parameter Code*/

+	pBuf[1] = 0x06;/*00,01,02,03,04,05,06 Total uncorrected errors ?*/

+       MV_CopyMemory(pBuf+2, error_counter_log_pg, sizeof(error_counter_log_pg));

+       return sizeof(error_counter_log_pg)+2;

+}

+

+MV_U32 Core_Fill_SelfTestLogPage(MV_PU8 pBuf, MV_U8 pageNum)

+{

+	static const MV_U8 self_test_results_log_pg[] = {

+		0x03,	/* DU =0, DS =0, TSD =0, ETC=0, TMC=00, FL=11 */

+		0x10, 	/* Parameter length */

+		0x81,   /*SELF-TEST CODE=100,RES=0,SELF-TEST RESULTS=0001*/

+		0x08, /*self test number*/

+		0x0, 0x0,0x0,0x0, 

+		0x0, 0x0,0x0,0x0

+	};

+

+	pBuf[0] = 0;	/* Parameter Code */

+	pBuf[1] = pageNum+1;

+       MV_CopyMemory(pBuf+2, self_test_results_log_pg, sizeof(self_test_results_log_pg));

+       return sizeof(self_test_results_log_pg)+2;

+}

+

+ MV_U32 Core_Fill_TempLogPage(MV_PU8 pBuf)

+{

+	static const MV_U8  temp_log_page[] = {

+		0x0, 0x0, 

+		0x3, 0x2, 0x0, 

+		0xFF,/*TEMPERATURE*/

+	       0x0, 0x1, 0x3, 0x2, 0x0,

+	       0xFF /*REFERENCE TEMPERATURE*/

+	};

+        MV_CopyMemory(pBuf, temp_log_page, sizeof(temp_log_page));

+        return sizeof(temp_log_page);

+}

+

+ MV_U32 Core_Fill_InfoExceptLogPage(MV_PU8 pBuf)

+{

+	static const MV_U8  info_except_log_page[] = {

+		0x0, 0x0, /*parameter code*/

+		0x3, /*DU=0 OBS=0 TSD=0 ETC=0 TMC=00 FL=11h*/

+		0x3,/*parampter length*/

+		0x0, 0x0, 

+		38, /*MOST RECENT TEMPERATURE READING*/

+	};

+

+       MV_CopyMemory(pBuf, info_except_log_page, sizeof(info_except_log_page));

+	if (info_except_ctrl_mode_page[2] & 0x4) {	/* TEST bit set */

+		pBuf[4] = SCSI_ASC_FAILURE_PREDICTION_THRESHOLD_EXCEEDED;

+		pBuf[5] = 0xff;

+	}

+        return sizeof(info_except_log_page);

+}

+ 

+ MV_U32 Core_Fill_StartStopCycleCounterLogPage(MV_PU8 pBuf)

+{

+	static const MV_U8  start_stop_cycle_counter_log_page[] = {

+		0x00, 0x01,0x15,0x06,00,00,20,8,00,12,

+		0x00, 0x02,0x16,0x06,00,00,20,8,00,12,

+		0x00,0x03,0x17,0x04,00,00,00,10,

+	       0x00, 0x04,0x18,0x04,00,00,00,02

+	};

+        MV_CopyMemory(pBuf, start_stop_cycle_counter_log_page, sizeof(start_stop_cycle_counter_log_page));

+        return sizeof(start_stop_cycle_counter_log_page);

+}

+

+

+void  mvScsiLogSenseTranslation(PCore_Driver_Extension pCore,  PMV_Request pReq)

+{

+	MV_U8 pageCode,subpcode,ppc, sp, pcontrol;

+	MV_U32 pageLen = 0, tmpLen = 0,i,n;

+

+	unsigned char ptmpBuf[512];

+	MV_U8 *buf = pReq->Data_Buffer;

+	

+	MV_ZeroMemory(buf, pReq->Data_Transfer_Length);

+	MV_ZeroMemory(ptmpBuf, sizeof(ptmpBuf));

+	

+	ppc = pReq->Cdb[1] & 0x2;

+	sp = pReq->Cdb[1] & 0x1;

+	if (ppc || sp) {

+		pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+		Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);

+		return ;

+	}

+	pcontrol = (pReq->Cdb[2] & 0xc0) >> 6;

+	pageCode = pReq->Cdb[2] & 0x3f;

+	subpcode = pReq->Cdb[3] & 0xff;

+	

+	ptmpBuf[0] = pageCode;

+	if (0 == subpcode) {

+		switch (pageCode) {

+		case SUPPORTED_LPAGES:/* Supported log pages log page */

+			n = 4;

+			ptmpBuf[0] = SUPPORTED_LPAGES; /* Page Code */

+			ptmpBuf[1] = 0x00; /*subpage Code */

+			ptmpBuf[2] = 0x00;/*length MSB*/

+			ptmpBuf[n++] = SUPPORTED_LPAGES;		/* this page */

+			ptmpBuf[n++] = WRITE_ERROR_COUNTER_LPAGE;		

+			ptmpBuf[n++] = READ_ERROR_COUNTER_LPAGE;		

+			ptmpBuf[n++] = READ_REVERSE_ERROR_COUNTER_LPAGE;	

+			ptmpBuf[n++] = VERIFY_ERROR_COUNTER_LPAGE;		

+			ptmpBuf[n++] = SELFTEST_RESULTS_LPAGE;		

+			ptmpBuf[n++] = TEMPERATURE_LPAGE;		

+			

+			ptmpBuf[n++] = STARTSTOP_CYCLE_COUNTER_LPAGE;	

+		//	ptmpBuf[n++] = SEAGATE_CACHE_LPAGE;	

+		//	ptmpBuf[n++] = SEAGATE_FACTORY_LPAGE;	

+												

+			ptmpBuf[n++] = IE_LPAGE;	/* Informational exceptions */	

+			ptmpBuf[3] = n - 4; /*length LSB*/

+			pageLen = ptmpBuf[3] ;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+4));

+			MV_CopyMemory(buf, ptmpBuf, tmpLen);

+			pReq->Data_Transfer_Length = tmpLen;

+			pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+			break;

+		case WRITE_ERROR_COUNTER_LPAGE:

+		case READ_ERROR_COUNTER_LPAGE:

+		case READ_REVERSE_ERROR_COUNTER_LPAGE:

+		case VERIFY_ERROR_COUNTER_LPAGE:

+			if (pageCode == WRITE_ERROR_COUNTER_LPAGE)

+				ptmpBuf[0] = WRITE_ERROR_COUNTER_LPAGE; // Page Code

+			if (pageCode == READ_ERROR_COUNTER_LPAGE)

+				ptmpBuf[0] = READ_ERROR_COUNTER_LPAGE; // Page Code

+			if (pageCode == READ_REVERSE_ERROR_COUNTER_LPAGE)

+				ptmpBuf[0] = READ_REVERSE_ERROR_COUNTER_LPAGE; // Page Code

+			if (pageCode == VERIFY_ERROR_COUNTER_LPAGE)

+			ptmpBuf[0] = VERIFY_ERROR_COUNTER_LPAGE; // Page Code

+			

+			ptmpBuf[1] = 0x00; // subPage Code

+			ptmpBuf[2] = 0x00;

+			

+			// Error Counter  log parameter

+			ptmpBuf[3] = Core_Fill_ErrorCounterLogPage(ptmpBuf + 4);

+			pageLen = ptmpBuf[3] ;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, pageLen);

+			

+			MV_CopyMemory(buf, ptmpBuf, tmpLen);

+			pReq->Data_Transfer_Length = tmpLen;

+			pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+			break;	

+		case SELFTEST_RESULTS_LPAGE:

+			ptmpBuf[0] = SELFTEST_RESULTS_LPAGE; // Page Code

+			ptmpBuf[1] = 0x00; // subPage Code

+			ptmpBuf[2] = 0x1;

+			ptmpBuf[3] = 0x90;

+

+			// Self-test Results log parameter

+			for(i=0; i<20; i++)

+			{

+				pageLen = Core_Fill_SelfTestLogPage(&ptmpBuf[4+(i*20)], i);

+			}

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen*20+4));

+			

+			MV_CopyMemory(buf, ptmpBuf, tmpLen);

+			pReq->Data_Transfer_Length = tmpLen;

+			pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+			break;	

+		case TEMPERATURE_LPAGE:	/* Temperature log page */

+			ptmpBuf[0] = TEMPERATURE_LPAGE; /* Page Code*/

+			ptmpBuf[1] = 0x00; /* subPage Code*/

+			ptmpBuf[2] = 0x00;

+			ptmpBuf[3] = Core_Fill_TempLogPage(ptmpBuf + 4);

+			pageLen = ptmpBuf[3] ;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, pageLen);

+			

+			MV_CopyMemory(buf, ptmpBuf, tmpLen);

+			pReq->Data_Transfer_Length = tmpLen;

+			pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+			break;	

+		case STARTSTOP_CYCLE_COUNTER_LPAGE:	/* Informational exceptions log page */

+			ptmpBuf[0] = STARTSTOP_CYCLE_COUNTER_LPAGE; /* Page Code*/

+			ptmpBuf[1] = 0x00; /* subPage Code*/

+			ptmpBuf[2] = 0x00;

+			ptmpBuf[3] = Core_Fill_StartStopCycleCounterLogPage(ptmpBuf + 4);

+

+			pageLen = ptmpBuf[3] ;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, pageLen);

+			

+			MV_CopyMemory(buf, ptmpBuf, tmpLen);

+			pReq->Data_Transfer_Length = tmpLen;

+			pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+			break;

+		case IE_LPAGE:	/* Informational exceptions log page */

+			ptmpBuf[0] = IE_LPAGE; /* Page Code*/

+			ptmpBuf[1] = 0x00; /* subPage Code*/

+			ptmpBuf[2] = 0x00;

+			ptmpBuf[3] = Core_Fill_InfoExceptLogPage(ptmpBuf + 4);

+

+			pageLen = ptmpBuf[3] ;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, pageLen);

+			

+			MV_CopyMemory(buf, ptmpBuf, tmpLen);

+			pReq->Data_Transfer_Length = tmpLen;

+			pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+			break;

+		default:

+		pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+		Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);

+		break;

+

+		}

+	} else {

+		pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+		Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);

+		return ;

+	}

+}

+static MV_U8 mvScsiModeSelectWceGet(PCore_Driver_Extension pCore, PMV_Request pReq, MV_U32 *WCEisEnabled)

+{

+    struct  scsi_cmnd *scmd=NULL;

+    struct  scatterlist *sg=NULL;

+    MV_U8  *req_buf=NULL;

+    MV_U32  length= pReq->Data_Transfer_Length;

+    MV_U8   offset= 0, cachePageOffset= 0;

+    MV_U8   rc= 1;

+

+    /* check for parameter list length error */

+    if (length < 4)

+        return 1;

+

+    if(NULL == WCEisEnabled)

+        return 1;

+

+    *WCEisEnabled= 0;

+

+    scmd=(struct scsi_cmnd *)pReq->Org_Req;

+    if(!scmd)

+        return 1;

+

+    if(!mv_use_sg(scmd))

+        return 1;

+

+    sg = (struct scatterlist *)mv_rq_bf(scmd);

+    if(NULL == sg)

+        return 1;

+

+    req_buf=(char *)(map_sg_page(sg)+sg->offset);

+    if(NULL == req_buf)

+        return 1;

+

+    /* check for invalid field in parameter list */

+    if (req_buf[0] || (req_buf[1] != 0) || req_buf[2])

+    {

+        MV_DPRINT(("Mode Select Error: invalid field in parameter \n"));

+        goto cleanup;

+    }

+

+    if (req_buf[3])

+    {

+        /* check for invalid field in parameter list */

+        if (req_buf[3] != 8)

+        {

+            MV_DPRINT(("Mode Select Error: wrong size for mode parameter"

+                     " block descriptor, BLOCK DESCRIPTOR LENGTH %d\n.",req_buf[3]));

+            goto cleanup;

+        }

+

+        /* check for parameter list length error */

+        if (length < 12)

+        {

+            goto cleanup;

+        }

+

+        /* check for invalid field in parameter list */

+        if (req_buf[4] || req_buf[5] || req_buf[6] || req_buf[7] || req_buf[8] || req_buf[9] ||(req_buf[10] != 0x2) || req_buf[11])

+        {

+            MV_DPRINT(("Mode Select Error: invalid field in parameter block descriptor list.\n"));

+            goto cleanup;

+        }

+    }

+    /* skip the mode parameter block descriptor */

+    offset = 4 + req_buf[3];

+

+    /* check for available mode pages */

+    if (length == offset)

+    {

+        MV_DPRINT(("Mode Select: no mode pages available\n"));

+        goto cleanup;

+    }

+

+    /* normalize to SELECT_10 offset */

+    if (pReq->Cdb[0]==SCSI_CMD_MODE_SELECT_10)

+        offset+= 4;

+

+    while ((offset + 2) < length)

+    {

+        switch (req_buf[offset] & 0x3f)

+        {

+            case 0x8:

+                if (req_buf[offset + 1] != 0x12)

+                {

+                    MV_DPRINT(("Mode Select Error: bad length in caching mode page %d\n.",

+                             req_buf[offset + 1]));

+                    goto cleanup;

+                }

+                cachePageOffset = offset;

+                offset += req_buf[offset + 1] + 2;

+            break;

+            case 0xa:

+                if ((req_buf[offset] != 0xa) || (req_buf[offset+1] != 0xa))

+                {

+                    MV_DPRINT(("Mode Select Error: invalid field in"

+                             " mode control page, list[%x] %x, list[%x] %x\n",

+                             offset, req_buf[offset], offset + 1, req_buf[offset+1]));

+                    goto cleanup;

+                }

+

+                if (req_buf[offset + 3] != MV_BIT(4))

+                {

+                    MV_DPRINT(("Mode Select Error: invalid field in mode control page, list[%x] %x\n",

+                             offset + 3, req_buf[offset + 3]));

+                    goto cleanup;

+                }

+

+                if (req_buf[offset + 2] || req_buf[offset + 4]  || req_buf[offset + 5]  ||

+                    req_buf[offset + 6] || req_buf[offset + 7]  ||  req_buf[offset + 8] ||

+                    req_buf[offset + 9] || req_buf[offset + 10] || req_buf[offset + 11])

+                {

+                    MV_DPRINT(("Mode Select Error: invalid field in"

+                             " mode control page, line %d\n", __LINE__));

+                    goto cleanup;

+                }

+                offset += req_buf[offset + 1] + 2;

+            break;

+            default:

+                MV_DPRINT(("Mode Select Error: invalid field in parameter "

+                         "list, mode page %d not supported, offset %d\n",

+                         req_buf[offset], offset));

+                goto cleanup;

+        }

+    }

+

+    if (length != offset)

+    {

+        MV_DPRINT(("Mode Select Error: bad length %d\n.", length));

+        goto cleanup;

+    }

+

+    if (cachePageOffset)

+    {

+        *WCEisEnabled= (req_buf[cachePageOffset+2] & MV_BIT(2)) ? 1 : 0;

+        rc= 0;

+    }

+

+cleanup:

+    kunmap_atomic(sg, KM_IRQ0);

+    return rc;

+}

+

+MV_BOOLEAN mvScsiModeSelect(PCore_Driver_Extension pCore, PMV_Request pReq)

+{

+	MV_U8 ptmpBuf[MAX_MODE_PAGE_LENGTH];

+	MV_U32 pageLen = 0, tmpLen = 0;

+	PDomain_Device pDevice = NULL;

+	MV_U8 portId, deviceId;

+	MV_U8 result = 0, cachePageOffset  =0 ,offset = 0;

+	MV_U8  wcachebit = 0,smartbit = 0;

+	MV_U8 *buf = pReq->Data_Buffer;

+	MV_U32  length = pReq->Data_Transfer_Length;

+	MV_U8   PF = (pReq->Cdb[1] & MV_BIT(4)) >> 4;

+	MV_U8   SP = (pReq->Cdb[1] & MV_BIT(0));

+	MV_U32 WCEisEnabled=0;

+	if (length == 0) {

+    		pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+        	return MV_TRUE;

+    	}

+   	 if (PF == 0 || SP == 1) {/* Invalid field in CDB,PARAMETER LIST LENGTH ERROR */

+		pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+		Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB);

+		return MV_TRUE;

+    	}

+

+	portId = PATA_MapPortId(pReq->Device_Id);

+	deviceId = PATA_MapDeviceId(pReq->Device_Id);

+	pDevice = &pCore->Ports[portId].Device[deviceId];

+	

+	if (mvScsiModeSelectWceGet(pCore, pReq, &WCEisEnabled))

+	{

+		 pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+		Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FIELD_IN_PARAMETER);

+		return MV_TRUE;

+	}

+	MV_ZeroMemory(buf, pReq->Data_Transfer_Length);

+	MV_ZeroMemory(ptmpBuf, MAX_MODE_PAGE_LENGTH);

+	/* Block Descriptor Length set to 0 - No Block Descriptor */

+

+	if (  pReq->Cdb[0]==SCSI_CMD_MODE_SELECT_6){

+		pageLen = Core_get_mode_page_caching((ptmpBuf+4), pDevice);

+		ptmpBuf[0] = (MV_U8)(4 + pageLen - 1);	/* Mode data length */

+		ptmpBuf[2] = 0x10;

+		tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+4));

+		offset = 4;

+	}

+	else if  (pReq->Cdb[0]==SCSI_CMD_MODE_SELECT_10) {	/* Mode Sense 10,select10 */

+		pageLen = Core_get_mode_page_caching((ptmpBuf+8), pDevice);

+		/* Mode Data Length, it does not include the number of bytes in */

+		/* Mode Data Length field */

+		tmpLen = 8 + pageLen - 2;

+		ptmpBuf[0] = (MV_U8)(((MV_U16)tmpLen) >> 8);

+		ptmpBuf[1] = (MV_U8)tmpLen;

+		ptmpBuf[2] = 0x00;

+		ptmpBuf[3] = 0x10;

+		tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+8));

+		offset = 8;

+	}

+	MV_CopyMemory(buf, ptmpBuf, tmpLen);

+	pReq->Data_Transfer_Length = tmpLen;

+

+        if ( (buf[offset] & 0x3f) == 0x08)

+        {

+            if (buf[offset + 1] != 0x12)

+            {

+              /* Invalid field in parameter list */

+                pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+                Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FIELD_IN_PARAMETER);

+                return MV_TRUE;

+            }

+            cachePageOffset = offset;

+            if(WCEisEnabled){

+            		// enable write cache ,send to hardware

+            		pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;

+			pReq->Cdb[1] = CDB_CORE_MODULE;

+			pReq->Cdb[2] = CDB_CORE_ENABLE_WRITE_CACHE;

+			return MV_FALSE;

+            } else{

+            		// disable write cache,send to hardware

+            		pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;

+			pReq->Cdb[1] = CDB_CORE_MODULE;

+			pReq->Cdb[2] = CDB_CORE_DISABLE_WRITE_CACHE;

+			return MV_FALSE;

+            }

+        }

+	pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+	return MV_TRUE;

+}

+

+void mvScsiReadDefectData(PCore_Driver_Extension pCore, PMV_Request req)

+{

+        MV_U8  temp_buf[6];

+        MV_U32 length;

+        MV_PU8 data_buf = req->Data_Buffer;

+

+        temp_buf[0] = 0;

+        temp_buf[1] = req->Cdb[2] & 0x18;

+        temp_buf[2] = 0;

+        temp_buf[3] = 0;

+        temp_buf[4] = 0;

+        temp_buf[5] = 0;

+        

+        length = MV_MIN(6, req->Data_Transfer_Length);

+

+        MV_CopyMemory(req->Data_Buffer, temp_buf, length);

+        req->Data_Transfer_Length = length;

+        req->Scsi_Status = REQ_STATUS_SUCCESS;

+}

+

+MV_U8 check_page_control(PMV_Request pReq,MV_U8 page_control){

+	MV_U8 ret=0;

+	switch(page_control){

+		case 0:/* only support current */

+			ret=0;

+			break;

+		case 3:

+			ret=1;

+			pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+			Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORT);

+			break;

+		case 1:

+		case 2:

+		default:

+			ret=1;

+			pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+			Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);

+			break;

+		}

+	return ret;

+}

+void mvScsiModeSense(PCore_Driver_Extension pCore, PMV_Request pReq)

+{

+	MV_U8 pageCode = pReq->Cdb[2] & 0x3F;		/* Same for mode sense 6 and 10 */

+	MV_U8 page_control=pReq->Cdb[2]>>6;

+	MV_U8 ptmpBuf[MAX_MODE_PAGE_LENGTH];

+	MV_U32 pageLen = 0, tmpLen = 0;

+	PDomain_Device pDevice = NULL;

+	MV_U8 portId, deviceId;

+	MV_U8 *buf = pReq->Data_Buffer;

+

+	portId = PATA_MapPortId(pReq->Device_Id);

+	deviceId = PATA_MapDeviceId(pReq->Device_Id);

+	pDevice = &pCore->Ports[portId].Device[deviceId];

+

+	MV_ZeroMemory(buf, pReq->Data_Transfer_Length);

+	MV_ZeroMemory(ptmpBuf, MAX_MODE_PAGE_LENGTH);

+	/* Block Descriptor Length set to 0 - No Block Descriptor */

+

+	switch (pageCode) {

+	case 0x3F:		/* Return all pages */

+	case 0x08:		/* Caching mode page */

+		if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_6) {

+			pageLen = Core_get_mode_page_caching((ptmpBuf+4), pDevice);

+			ptmpBuf[0] = (MV_U8)(4 + pageLen - 1);	/* Mode data length */

+			ptmpBuf[2] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+4));

+		}

+		else {	/* Mode Sense 10 */

+			pageLen = Core_get_mode_page_caching((ptmpBuf+8), pDevice);

+			/* Mode Data Length, it does not include the number of bytes in */

+			/* Mode Data Length field */

+			tmpLen = 8 + pageLen - 2;

+			ptmpBuf[0] = (MV_U8)(((MV_U16)tmpLen) >> 8);

+			ptmpBuf[1] = (MV_U8)tmpLen;

+			ptmpBuf[2] = 0x00;

+			ptmpBuf[3] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+8));

+		}

+		if(check_page_control(pReq,page_control))

+			break;

+		MV_CopyMemory(buf, ptmpBuf, tmpLen);

+		pReq->Data_Transfer_Length = tmpLen;

+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+		break;

+	case 0x19:	/*Protocol Specific Port mode page*/	

+		if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_6) {

+			pageLen = Core_Fill_ProSpecPortModePage(ptmpBuf+4);

+			ptmpBuf[0] = (MV_U8)(4 + pageLen - 1);	/* Mode data length */

+			ptmpBuf[2] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+4));

+		}else if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_10) {	/* Mode Sense 10 */

+			pageLen = Core_Fill_ProSpecPortModePage(ptmpBuf+8);

+			/* Mode Data Length, it does not include the number of bytes in */

+			/* Mode Data Length field */

+			tmpLen = 8 + pageLen - 2;

+			ptmpBuf[0] = (MV_U8)(((MV_U16)tmpLen) >> 8);

+			ptmpBuf[1] = (MV_U8)tmpLen;

+			ptmpBuf[2] = 0x00;

+			ptmpBuf[3] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+8));

+		}

+		if(check_page_control(pReq,page_control))

+			break;

+		MV_CopyMemory(buf, ptmpBuf, tmpLen);

+		pReq->Data_Transfer_Length = tmpLen;

+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+		break;

+	case 0x1c:	/*Informational Exceptions Control mode page*/

+		if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_6) {

+			pageLen = Core_Fill_InfoExcepCtrlModePage((ptmpBuf+4), pDevice,pReq);

+			ptmpBuf[0] = (MV_U8)(4 + pageLen - 1);	/* Mode data length */

+			ptmpBuf[2] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+4));

+		}else if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_10) {	/* Mode Sense 10 */

+			pageLen = Core_Fill_InfoExcepCtrlModePage((ptmpBuf+8), pDevice,pReq);

+			/* Mode Data Length, it does not include the number of bytes in */

+			/* Mode Data Length field */

+			tmpLen = 8 + pageLen - 2;

+			ptmpBuf[0] = (MV_U8)(((MV_U16)tmpLen) >> 8);

+			ptmpBuf[1] = (MV_U8)tmpLen;

+			ptmpBuf[2] = 0x00;

+			ptmpBuf[3] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+8));

+		}

+		if(check_page_control(pReq,page_control))

+			break;

+		MV_CopyMemory(buf, ptmpBuf, tmpLen);

+		pReq->Data_Transfer_Length = tmpLen;

+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+		break;

+	case 0x0a:  /*Control mode page*/		

+		if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_6) {

+			pageLen = Core_Fill_CtrlModePage((ptmpBuf+4), pDevice);

+			ptmpBuf[0] = (MV_U8)(4 + pageLen - 1);	/* Mode data length */

+			ptmpBuf[2] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+4));

+		}else if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_10) {	/* Mode Sense 10 */

+			pageLen = Core_Fill_CtrlModePage((ptmpBuf+8), pDevice);

+			/* Mode Data Length, it does not include the number of bytes in */

+			/* Mode Data Length field */

+			tmpLen = 8 + pageLen - 2;

+			ptmpBuf[0] = (MV_U8)(((MV_U16)tmpLen) >> 8);

+			ptmpBuf[1] = (MV_U8)tmpLen;

+			ptmpBuf[2] = 0x00;

+			ptmpBuf[3] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+8));

+		}

+		if(check_page_control(pReq,page_control))

+			break;

+		MV_CopyMemory(buf, ptmpBuf, tmpLen);

+		pReq->Data_Transfer_Length = tmpLen;

+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+		break;

+

+	case 0x01: /*RW Error Recovery*/

+		if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_6) {

+			pageLen = Core_Fill_RWErrorRecoveryModePage(ptmpBuf+4);

+			ptmpBuf[0] = (MV_U8)(4 + pageLen - 1);	/* Mode data length */

+			ptmpBuf[2] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+4));

+		}else if (pReq->Cdb[0]==SCSI_CMD_MODE_SENSE_10) {	/* Mode Sense 10 */

+			pageLen = Core_Fill_RWErrorRecoveryModePage(ptmpBuf+8);

+			/* Mode Data Length, it does not include the number of bytes in */

+			/* Mode Data Length field */

+			tmpLen = 8 + pageLen - 2;

+			ptmpBuf[0] = (MV_U8)(((MV_U16)tmpLen) >> 8);

+			ptmpBuf[1] = (MV_U8)tmpLen;

+			ptmpBuf[2] = 0x00;

+			ptmpBuf[3] = 0x10;

+			tmpLen = MV_MIN(pReq->Data_Transfer_Length, (pageLen+8));

+		}

+		if(check_page_control(pReq,page_control))

+			break;

+		MV_CopyMemory(buf, ptmpBuf, tmpLen);

+		pReq->Data_Transfer_Length = tmpLen;

+		pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+		break;

+		

+	default:

+		pReq->Scsi_Status = REQ_STATUS_HAS_SENSE;

+		Core_FillSenseData(pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB);

+		break;

+	}

+}

+

+void Core_Fill_SendDiagTaskfile( PDomain_Device device,PMV_Request req, PATA_TaskFile taskfile)

+{

+

+        if ((req->Cdb[1] & 0x04) &&

+                (device->Capacity & 

+                        DEVICE_CAPACITY_SMART_SELF_TEST_SUPPORTED) &&

+                (device->Setting & DEVICE_SETTING_SMART_ENABLED)) {

+		        

+                taskfile->LBA_Low = 0x01;

+        

+        } else if ((req->Cdb[1] & 0x04) &&

+                !((device->Capacity & 

+                        DEVICE_CAPACITY_SMART_SELF_TEST_SUPPORTED) &&

+                (device->Setting & DEVICE_SETTING_SMART_ENABLED))) {

+          //      scsi_ata_send_diag_verify_0(root, req);

+

+                taskfile->Device = MV_BIT(6);

+                taskfile->LBA_Low = 0;

+                taskfile->LBA_Mid = 0;

+                taskfile->LBA_High = 0;

+                taskfile->Sector_Count = 1;

+	        taskfile->LBA_Low_Exp = 0;

+                taskfile->LBA_Mid_Exp = 0;

+                taskfile->LBA_High_Exp = 0;

+                taskfile->Sector_Count_Exp = 0;

+                taskfile->Features = 0;

+	        taskfile->Control = 0;

+	        taskfile->Feature_Exp = 0;

+

+                if (device->Capacity & DEVICE_CAPACITY_48BIT_SUPPORTED) {

+                        taskfile->Command = ATA_CMD_VERIFY_EXT;

+                } else {

+                        taskfile->Command = ATA_CMD_VERIFY;

+                }

+

+                return;

+        } else {

+	        switch ((req->Cdb[1] & 0xE0) >> 5) {

+	        case BACKGROUND_SHORT_SELF_TEST:

+                        taskfile->LBA_Low = 0x01;

+		        break;

+	        case BACKGROUND_EXTENDED_SELF_TEST:

+                        taskfile->LBA_Low = 0x02;

+		        break;

+	        case ABORT_BACKGROUND_SELF_TEST:

+                        taskfile->LBA_Low = 0x7F;

+		        break;

+	        case FOREGROUND_SHORT_SELF_TEST:

+                        taskfile->LBA_Low = 0x81;

+		        break;

+	        case FOREGROUND_EXTENDED_SELF_TEST:

+                        taskfile->LBA_Low = 0x82;

+		        break;

+	        default:

+		        break;

+	        }

+        }

+

+        taskfile->Device = MV_BIT(6);

+        taskfile->LBA_Mid = 0x4F;

+        taskfile->LBA_High = 0xC2;

+        taskfile->Features = ATA_CMD_SMART_EXECUTE_OFFLINE;

+	 taskfile->Command = ATA_CMD_SMART;

+

+	taskfile->Sector_Count = 0;

+	taskfile->Control = 0;

+	taskfile->Feature_Exp = 0;

+	taskfile->Sector_Count_Exp = 0;

+	taskfile->LBA_Low_Exp = 0;

+	taskfile->LBA_Mid_Exp = 0;

+	taskfile->LBA_High_Exp = 0;

+}

+

+#endif //#ifdef SUPPORT_ATA_SMART

+

+

diff --git a/drivers/scsi/thor/core/thor/core_sat.h b/drivers/scsi/thor/core/thor/core_sat.h
new file mode 100755
index 0000000..ee4f278
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_sat.h
@@ -0,0 +1,78 @@
+#ifndef __CORE_SAT_H__

+#define __CORE_SAT_H__

+

+#include "core_inter.h"

+

+// ATA Specification Command Register Values (Commands)

+#define ATA_IDENTIFY_DEVICE             0xec                                              

+#define ATA_IDENTIFY_PACKET_DEVICE      0xa1

+#define ATA_SMART_CMD                   0xb0

+#define ATA_CHECK_POWER_MODE            0xe5

+

+// ATA Specification Feature Register Values (SMART Subcommands).

+// Note that some are obsolete as of ATA-7.

+#define ATA_SMART_READ_VALUES           0xd0

+#define ATA_SMART_READ_THRESHOLDS       0xd1

+#define ATA_SMART_AUTOSAVE              0xd2

+#define ATA_SMART_SAVE                  0xd3

+#define ATA_SMART_IMMEDIATE_OFFLINE     0xd4

+#define ATA_SMART_READ_LOG_SECTOR       0xd5

+#define ATA_SMART_WRITE_LOG_SECTOR      0xd6

+#define ATA_SMART_WRITE_THRESHOLDS      0xd7

+#define ATA_SMART_ENABLE                0xd8

+#define ATA_SMART_DISABLE               0xd9

+#define ATA_SMART_STATUS                0xda

+// SFF 8035i Revision 2 Specification Feature Register Value (SMART

+// Subcommand)

+#define ATA_SMART_AUTO_OFFLINE          0xdb

+

+/* ANSI SCSI-3 Log Pages retrieved by LOG SENSE. */

+#define SUPPORTED_LPAGES                        0x00

+#define BUFFER_OVERRUN_LPAGE                    0x01

+#define WRITE_ERROR_COUNTER_LPAGE               0x02

+#define READ_ERROR_COUNTER_LPAGE                0x03

+#define READ_REVERSE_ERROR_COUNTER_LPAGE        0x04

+#define VERIFY_ERROR_COUNTER_LPAGE              0x05

+#define NON_MEDIUM_ERROR_LPAGE                  0x06

+#define LAST_N_ERROR_LPAGE                      0x07

+#define FORMAT_STATUS_LPAGE                     0x08

+#define TEMPERATURE_LPAGE                       0x0d

+#define STARTSTOP_CYCLE_COUNTER_LPAGE           0x0e

+#define APPLICATION_CLIENT_LPAGE                0x0f

+#define SELFTEST_RESULTS_LPAGE                  0x10

+#define BACKGROUND_RESULTS_LPAGE                0x15   /* SBC-3 */

+#define IE_LPAGE                                0x2f

+

+/* Seagate vendor specific log pages. */

+#define SEAGATE_CACHE_LPAGE                     0x37

+#define SEAGATE_FACTORY_LPAGE                   0x3e

+

+enum mode_sense_page_code {

+        DIRECT_ACCESS_BLOCK_DEVICE_MODE_PAGE    = 0x00,

+        RW_ERROR_RECOVERY_MODE_PAGE             = 0x01,

+        CACHE_MODE_PAGE                         = 0x08,

+        CONTROL_MODE_PAGE                       = 0x0A,

+        PORT_MODE_PAGE                          = 0x19,

+        INFORMATIONAL_EXCEPTIONS_CONTROL_MODE_PAGE = 0x1C,

+        ALL_MODE_PAGE                           = 0x3F,

+};

+

+/**************************************************************/

+/**

+* Self-Test Code translation for Send Diagnostic Command

+**/

+#define DEFAULT_SELF_TEST					0x0

+#define BACKGROUND_SHORT_SELF_TEST			0x1

+#define BACKGROUND_EXTENDED_SELF_TEST		0x2

+#define ABORT_BACKGROUND_SELF_TEST			0x4

+#define FOREGROUND_SHORT_SELF_TEST			0x5

+#define FOREGROUND_EXTENDED_SELF_TEST		0x6

+

+void mvScsiReadDefectData(PCore_Driver_Extension pCore, PMV_Request req);

+void  mvScsiLogSenseTranslation(PCore_Driver_Extension pCore,  PMV_Request pReq);

+MV_BOOLEAN mvScsiModeSelect(PCore_Driver_Extension pCore, PMV_Request pReq);

+void mvScsiModeSense(PCore_Driver_Extension pCore, PMV_Request pReq);

+void Core_Fill_SendDiagTaskfile( PDomain_Device device,PMV_Request req, PATA_TaskFile taskfile);

+

+#endif /* __CORE_SAT_H__ */

+  

diff --git a/drivers/scsi/thor/core/thor/core_sata.h b/drivers/scsi/thor/core/thor/core_sata.h
new file mode 100755
index 0000000..d7a5a35
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_sata.h
@@ -0,0 +1,51 @@
+#if !defined(FIS_H)
+#define FIS_H
+
+/* SATA FIS: Register-Host to Device*/
+typedef struct _SATA_FIS_REG_H2D
+{
+	MV_U8	FIS_Type;
+#ifdef __MV_BIG_ENDIAN_BITFIELD__
+	MV_U8	C : 1;
+	MV_U8	Reserved0 : 3;
+	MV_U8	PM_Port : 4;
+#else
+	MV_U8	PM_Port : 4;
+	MV_U8	Reserved0 : 3;
+	MV_U8	C : 1;
+#endif /* __MV_BIG_ENDIAN_BITFIELD__ */
+	MV_U8	Command;
+	MV_U8	Features;
+
+	MV_U8	LBA_Low;
+	MV_U8	LBA_Mid;
+	MV_U8	LBA_High;
+	MV_U8	Device;
+
+	MV_U8	LBA_Low_Exp;
+	MV_U8	LBA_Mid_Exp;
+	MV_U8	LBA_High_Exp;
+	MV_U8	Features_Exp;
+
+	MV_U8	Sector_Count;
+	MV_U8	Sector_Count_Exp;
+	MV_U8	Reserved1;
+	MV_U8	Control;
+
+	MV_U8	Reserved2[4];
+} SATA_FIS_REG_H2D, *PSATA_FIS_REG_H2D;
+
+/* FIS type definition */
+#define SATA_FIS_TYPE_REG_H2D			0x27	/* Register FIS - Host to Device */
+#define SATA_FIS_TYPE_REG_D2H			0x34	/* Register FIS - Device to Host */
+
+#define SATA_FIS_TYPE_DMA_ACTIVATE		0x39	/* DMA Activate FIS - Device to Host */
+#define SATA_FIS_TYPE_DMA_SETUP			0x41	/* DMA Setup FIS - Bi-directional */
+
+#define SATA_FIS_TYPE_DATA				0x46	/* Data FIS - Bi-directional */
+#define SATA_FIS_TYPE_BIST_ACTIVATE		0x58	/* BIST Activate FIS - Bi-directional */
+#define SATA_FIS_TYPE_PIO_SETUP			0x5F	/* PIO Setup FIS - Device to Host */
+#define SATA_FIS_TYPE_SET_DEVICE_BITS	0xA1	/* Set Device Bits FIS - Device to Host */
+
+#endif /* FIS_H */
+
diff --git a/drivers/scsi/thor/core/thor/core_swxor.c b/drivers/scsi/thor/core/thor/core_swxor.c
new file mode 100755
index 0000000..d060e61
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_swxor.c
@@ -0,0 +1,528 @@
+#include "mv_include.h"
+#include "core_inter.h"
+
+#if defined(RAID_DRIVER) && defined(USE_NEW_SGTABLE)
+typedef struct _xor_strm_t
+{
+	sgd_t		sgd[2];
+	MV_U32		off;
+} xor_strm_t;
+
+static MV_PVOID sgd_kmap(
+	PCore_Driver_Extension	pCore,
+	sgd_t*					sg
+	)
+{
+#ifdef _OS_WINDOWS
+	sgd_pctx_t* pctx = (sgd_pctx_t*) sg;
+	MV_PTR_INTEGER addr = (MV_PTR_INTEGER)(pctx->baseAddr.value);
+
+	MV_DASSERT( sg->flags & SGD_PCTX );
+
+	addr &= ~0x80000000L; // just for fun, refer to GenerateSGTable in win_helper.c
+
+	return (MV_PVOID) addr;
+#endif /* _OS_WINDOWS */
+#ifdef _OS_LINUX
+	sgd_pctx_t* pctx = (sgd_pctx_t*)sg;
+	struct scatterlist *ksg = (struct scatterlist *)pctx->u.xctx;
+	void *kvaddr = NULL;
+
+	MV_DASSERT( sg->flags & SGD_PCTX );
+	MV_DASSERT( ksg );
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	kvaddr = page_address(ksg->page);
+	if (!kvaddr) 
+#endif
+		kvaddr = map_sg_page(ksg);
+	kvaddr += ksg->offset;
+	return kvaddr;
+#endif /* _OS_LINUX */
+}
+
+static void sgd_kunmap(
+	PCore_Driver_Extension	pCore,
+	sgd_t*					sg,
+	MV_PVOID				mapped_addr
+	)
+{
+#ifdef _OS_WINDOWS
+#endif /* _OS_WINDOWS */
+#ifdef _OS_LINUX
+	sgd_pctx_t* pctx = (sgd_pctx_t*)sg;
+	struct scatterlist *ksg = (struct scatterlist *)pctx->u.xctx;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	void *kvaddr = NULL;
+	kvaddr = page_address(ksg->page);
+	if (!kvaddr)
+#endif
+	kunmap_atomic(mapped_addr - ksg->offset, KM_IRQ0);
+#endif /* _OS_LINUX */
+}
+static MV_PVOID sgd_kmap_sec(
+	PCore_Driver_Extension	pCore,
+	sgd_t*					sg
+	)
+{
+#ifdef _OS_WINDOWS
+	sgd_pctx_t* pctx = (sgd_pctx_t*) sg;
+	MV_PTR_INTEGER addr = (MV_PTR_INTEGER)(pctx->baseAddr.value);
+
+	MV_DASSERT( sg->flags & SGD_PCTX );
+
+	addr &= ~0x80000000L; // refer to GenerateSGTable in win_helper.c
+
+	return (MV_PVOID) addr;
+#endif /* _OS_WINDOWS */
+#ifdef _OS_LINUX
+	sgd_pctx_t* pctx = (sgd_pctx_t*)sg;
+	struct scatterlist *ksg = (struct scatterlist *)pctx->u.xctx;
+	void *kvaddr = NULL;
+	MV_DASSERT( sg->flags & SGD_PCTX );
+	MV_DASSERT( ksg );
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	kvaddr = page_address(ksg->page);
+	if (!kvaddr) 
+#endif
+		kvaddr = map_sg_page_sec(ksg);
+	kvaddr += ksg->offset;
+	return kvaddr;
+#endif /* _OS_LINUX */
+}
+
+static void sgd_kunmap_sec(
+	PCore_Driver_Extension	pCore,
+	sgd_t*					sg,
+	MV_PVOID				mapped_addr
+	)
+{
+#ifdef _OS_WINDOWS
+#endif /* _OS_WINDOWS */
+#ifdef _OS_LINUX
+	sgd_pctx_t* pctx = (sgd_pctx_t*)sg;
+	struct scatterlist *ksg = (struct scatterlist *)pctx->u.xctx;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	void *kvaddr = NULL;
+	kvaddr = page_address(ksg->page);
+	if (!kvaddr)
+#endif
+	kunmap_atomic(mapped_addr - ksg->offset, KM_IRQ1);
+#endif /* _OS_LINUX */
+}
+
+void CopySGs(
+	PCore_Driver_Extension	pCore,
+	PMV_SG_Table			srctbl,
+	PMV_SG_Table			dsttbl
+	);
+
+#endif /* RAID_DRIVER && USE_NEW_SGTABLE */
+
+#if defined(RAID_DRIVER) && defined(SOFTWARE_XOR) && defined(USE_NEW_SGTABLE)
+/*
+ * CompareSGs needs not to be changed for SGD_PCTX since RAID always
+ * use memory with known virtual address.
+ */
+void
+CompareSGs( 
+	PCore_Driver_Extension	pCore,
+	PMV_XOR_Request			pXORReq,
+	PMV_SG_Table			srctbl
+	)
+{
+	MV_PU32					pSrc[2] = { NULL, };
+	sgd_t					sgd[2];
+	sgd_iter_t				sg_iter[2];
+	MV_U32					wCount[2];
+	MV_BOOLEAN				bFinished = MV_FALSE;
+	MV_U8					bIndex;
+	MV_U32					offset = 0;
+	MV_PVOID				p = NULL;
+
+	MV_ASSERT( srctbl[0].Byte_Count == srctbl[1].Byte_Count );
+
+	for( bIndex = 0; bIndex < 2; bIndex++ )
+	{
+		sgd_iter_init( &sg_iter[bIndex], srctbl[bIndex].Entry_Ptr, 0, srctbl[bIndex].Byte_Count );
+
+		sgd_iter_get_next( &sg_iter[bIndex], sgd );
+
+		sgd_get_vaddr( sgd, p );
+		pSrc[bIndex] = (MV_PU32) p;
+		
+		sgd_getsz( sgd, wCount[bIndex] );
+
+	}
+
+	while( !bFinished )
+	{
+		if( *pSrc[0] != *pSrc[1] )
+		{
+			pXORReq->Request_Status = XOR_STATUS_ERROR;
+			pXORReq->Error_Offset = offset;
+			return;
+		}
+
+		offset += sizeof( MV_U32 );
+
+		for( bIndex = 0; bIndex < 2; bIndex++ )
+		{
+			pSrc[bIndex]++;
+			wCount[bIndex] -= sizeof( MV_U32 );
+			if( wCount[bIndex] == 0 )
+			{
+				if( !sgd_iter_get_next( &sg_iter[bIndex], sgd ) )
+				{
+					bFinished = MV_TRUE;
+
+					/*
+					for( bIndex = 0; bIndex < srcCount + dstCount; bIndex++ )
+					{
+						MV_ASSERT( !sgd_iter_get_next( &sg_iter[bIndex], sgd ) );
+					}
+					*/
+					break;
+				}
+
+				sgd_get_vaddr( sgd, p );
+				pSrc[bIndex] = (MV_PU32) p;
+				
+				sgd_getsz( sgd, wCount[bIndex] );
+			}
+		}
+	}
+}
+
+#if defined(XOR_AS_GF)
+typedef MV_U8 XORUNIT;
+#else
+typedef MV_U32 XORUNIT;
+#endif
+
+void sg_xor(
+	PCore_Driver_Extension	pCore,
+	xor_strm_t*				strm,
+	MV_U8					src_cnt,
+	MV_U8					dst_cnt,
+	MV_U32					byte_cnt
+	)
+{
+	//XORUNIT	*pSrc, *pDst;
+	XORUNIT		*p;
+	MV_PVOID 	ptmp;
+	int		i;
+	XORUNIT	value = 0;
+	MV_BOOLEAN	mapped;
+	MV_U32	off = 0;
+#ifdef _OS_LINUX
+	unsigned long flags = 0;
+#endif		/* _OS_LINUX */
+
+	while( byte_cnt )
+	{
+		for( i = 0; i < src_cnt+dst_cnt; i++ )
+		{
+			mapped = MV_FALSE;
+			if( strm[i].sgd[0].flags & SGD_PCTX )
+			{
+			#ifdef _OS_LINUX
+				local_irq_save(flags);
+			#endif
+				p = (XORUNIT*) sgd_kmap(pCore,strm[i].sgd);
+				ptmp = p;
+				mapped = MV_TRUE;
+	#ifdef _OS_LINUX
+				p = (XORUNIT*)(((MV_PU8)p) + 
+				              strm[i].sgd[1].size);
+	#endif
+			}
+			else
+			{
+				ptmp = NULL;
+				sgd_get_vaddr( strm[i].sgd, ptmp );
+				p = (XORUNIT*) ptmp;
+			}
+
+			p = (XORUNIT*) (((MV_PU8) p) + strm[i].off + off);
+
+			if( i == 0 )
+				value = *p;
+			else if( i >= src_cnt )
+				*p = value;
+			else
+				value ^= *p;
+
+			if( mapped ){
+				sgd_kunmap( pCore, strm[i].sgd, ptmp );
+			#ifdef _OS_LINUX
+			 	local_irq_restore(flags);	
+			#endif
+			}
+		}
+		byte_cnt -= sizeof(XORUNIT);
+		off += sizeof(XORUNIT);
+	}
+}
+
+MV_U32 min_of(MV_U32* ele, MV_U32 cnt)
+{
+	MV_U32 v = *ele++;
+
+	while( --cnt )
+	{
+		if( *ele < v )
+			v = *ele;
+		ele++;
+	}
+
+	return v;
+}
+
+void
+XorSGs(
+	PCore_Driver_Extension	pCore,
+	MV_U8					srcCount,
+	MV_U8					dstCount,
+	PMV_SG_Table			srctbl,
+	PMV_SG_Table			dsttbl,
+	XOR_COEF				Coef[XOR_TARGET_SG_COUNT][XOR_SOURCE_SG_COUNT]
+	)
+{
+	xor_strm_t				strm[XOR_SOURCE_SG_COUNT+ XOR_TARGET_SG_COUNT];
+	sgd_iter_t				sg_iter[XOR_SOURCE_SG_COUNT + XOR_TARGET_SG_COUNT];
+	MV_U32					wCount[XOR_SOURCE_SG_COUNT + XOR_TARGET_SG_COUNT];
+	MV_U8					bIndex;
+	MV_BOOLEAN				bFinished = MV_FALSE;
+	MV_U32					tmp = srctbl[0].Byte_Count;
+	MV_U32					count = 0xffffffffL;
+
+	for( bIndex = 0; bIndex < srcCount; bIndex++ )
+	{
+		MV_ASSERT( srctbl[bIndex].Byte_Count == tmp );
+		sgd_iter_init( &sg_iter[bIndex], srctbl[bIndex].Entry_Ptr, 0, srctbl[bIndex].Byte_Count );
+	}
+
+	for( bIndex = 0; bIndex < dstCount; bIndex++ )
+	{
+		MV_ASSERT( srctbl[bIndex].Byte_Count == tmp );
+		sgd_iter_init( &sg_iter[srcCount+bIndex], dsttbl[bIndex].Entry_Ptr, 0, dsttbl[bIndex].Byte_Count );
+	}
+
+	for( bIndex = 0; bIndex < srcCount + dstCount; bIndex++ )
+	{
+		strm[bIndex].off = 0;
+		sgd_iter_get_next( &sg_iter[bIndex], strm[bIndex].sgd );		
+		sgd_getsz( strm[bIndex].sgd, wCount[bIndex] );
+
+		if( wCount[bIndex] < count )
+			count = wCount[bIndex];
+	}
+
+	while( !bFinished )
+	{
+
+		sg_xor( pCore, strm, srcCount, dstCount, count );
+
+		for( bIndex = 0; bIndex < srcCount + dstCount; bIndex++ )
+		{
+			wCount[bIndex] -= count;
+			if( wCount[bIndex] == 0 )
+			{
+				if( !sgd_iter_get_next( &sg_iter[bIndex], strm[bIndex].sgd ) )
+				{
+					bFinished = MV_TRUE;
+					break;
+				}
+
+				strm[bIndex].off = 0;
+				sgd_getsz( strm[bIndex].sgd, wCount[bIndex] );
+			}
+			else
+				strm[bIndex].off += count;
+		}
+		count = min_of( wCount, srcCount + dstCount );
+	}
+}
+
+
+
+#ifdef SIMULATOR
+void _Core_ModuleSendXORRequest(MV_PVOID This, PMV_XOR_Request pXORReq)
+#else	/*SIMULATOR*/
+void Core_ModuleSendXORRequest(MV_PVOID This, PMV_XOR_Request pXORReq)
+#endif	/*!SIMULATOR*/
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+
+	switch (pXORReq->Request_Type) 
+	{
+		case XOR_REQUEST_WRITE:
+			XorSGs( 
+				pCore, 
+				pXORReq->Source_SG_Table_Count, 
+				pXORReq->Target_SG_Table_Count,
+				pXORReq->Source_SG_Table_List,
+				pXORReq->Target_SG_Table_List,
+				pXORReq->Coef );
+			break;
+		case XOR_REQUEST_COMPARE:
+			MV_ASSERT( pXORReq->Source_SG_Table_Count == 2 );
+			CompareSGs( 
+				pCore, 
+				pXORReq,
+				pXORReq->Source_SG_Table_List );
+			break;
+		case XOR_REQUEST_DMA:
+			CopySGs(
+				pCore,
+				pXORReq->Source_SG_Table_List,
+				pXORReq->Target_SG_Table_List );
+			break;
+		default:
+			pXORReq->Request_Status = XOR_STATUS_INVALID_REQUEST;
+			break;
+	}
+#ifndef SIMULATOR
+	pXORReq->Completion( pXORReq->Cmd_Initiator, pXORReq );
+#endif	/*!SIMULATOR*/
+}
+
+#endif /* RAID_DRIVER && SOFTWARE_XOR && USE_NEW_SGTABLE */
+
+#if defined(RAID_DRIVER) && defined(USE_NEW_SGTABLE)
+
+static void sg_memcpy(
+	PCore_Driver_Extension	pCore,
+	xor_strm_t				*strm, /*strm[0]:source, strm[1]:destination*/
+	MV_U32					byte_cnt
+	)
+{
+	MV_U32		sz;
+	MV_PU32		pSrc[2] = { NULL, NULL };
+	MV_BOOLEAN	mapped[2] = { MV_FALSE, MV_FALSE };
+	MV_PVOID	p = NULL;
+	int			i;
+	MV_PVOID 	ptmp = NULL;
+#ifdef _OS_LINUX
+	unsigned long flags = 0;
+	int             enabled = 0;
+#endif		/* _OS_LINUX */
+
+	for( i = 0; i < 2; i++ )
+	{
+		sgd_getsz(strm[i].sgd,sz);
+		MV_DASSERT( strm[i].off < sz );
+		MV_DASSERT( strm[i].off+byte_cnt <= sz );
+	}
+
+#ifdef _OS_LINUX
+	if( strm[i].sgd[0].flags & SGD_PCTX ){
+		enabled = 1;
+		local_irq_save(flags);
+	}
+#endif		/* _OS_LINUX */
+
+	for( i = 0; i < 2; i++ )
+	{
+		if( strm[i].sgd[0].flags & SGD_PCTX )
+		{
+			if(i==0)
+				ptmp = (MV_PU32) sgd_kmap(pCore,strm[i].sgd);
+			else
+				ptmp = (MV_PU32) sgd_kmap_sec(pCore,strm[i].sgd);
+
+			mapped[i] = MV_TRUE;
+	#ifdef _OS_LINUX
+			pSrc[i] = (MV_PU32)((MV_PU8)ptmp + strm[i].sgd[1].size);
+	#else
+			pSrc[i] = (MV_PU32)ptmp;
+	#endif
+		}
+		else
+		{
+			sgd_get_vaddr( strm[i].sgd, p );
+			pSrc[i] = (MV_PU32) p;
+		}
+	}
+
+	MV_CopyMemory( 
+		pSrc[1]+strm[1].off/sizeof(MV_U32), 
+		pSrc[0]+strm[0].off/sizeof(MV_U32),
+		byte_cnt );
+
+	for(i = 0; i < 2; i++ ) {
+		if( mapped[i] ) {
+			if(i==0)
+				sgd_kunmap(pCore,strm[i].sgd, ptmp);
+			else
+				sgd_kunmap_sec(pCore,strm[i].sgd, ptmp);
+		}
+	}		
+
+#ifdef _OS_LINUX
+	if( enabled == 1 )
+		local_irq_restore(flags);
+#endif		/* _OS_LINUX */
+
+	return;
+}
+
+
+void CopySGs(
+	PCore_Driver_Extension	pCore,
+	PMV_SG_Table			srctbl,
+	PMV_SG_Table			dsttbl
+	)
+{
+	//MV_PU32					pSrc[2] = { NULL, };
+	sgd_iter_t				sg_iter[2];
+	MV_U32					wCount[2], count;
+	MV_BOOLEAN				bFinished = MV_FALSE;
+	MV_U8					bIndex;
+	//MV_PVOID				p;
+	xor_strm_t				strm[2];
+
+	MV_ASSERT( srctbl->Byte_Count == dsttbl->Byte_Count );
+
+	sgd_iter_init( &sg_iter[0], srctbl->Entry_Ptr, 0, srctbl->Byte_Count );
+	sgd_iter_init( &sg_iter[1], dsttbl->Entry_Ptr, 0, dsttbl->Byte_Count );
+
+	for( bIndex = 0; bIndex < 2; bIndex++ )
+	{
+		strm[bIndex].off = 0;
+		sgd_iter_get_next( &sg_iter[bIndex], strm[bIndex].sgd );
+		sgd_getsz( strm[bIndex].sgd, wCount[bIndex] );
+	}
+
+	while( !bFinished )
+	{
+		count = MV_MIN( wCount[0], wCount[1] );
+
+		sg_memcpy( 
+			pCore,
+			strm,
+			count
+			);
+
+		for( bIndex = 0; bIndex < 2; bIndex++ )
+		{
+			wCount[bIndex] -= count;
+			if( wCount[bIndex] == 0 )
+			{
+				if( !sgd_iter_get_next( &sg_iter[bIndex], strm[bIndex].sgd ) )
+				{
+					bFinished = MV_TRUE;
+					break;
+				}
+				sgd_getsz( strm[bIndex].sgd, wCount[bIndex] );
+				strm[bIndex].off = 0;
+			}
+			else
+				strm[bIndex].off += count;
+		}
+	}
+}
+
+#endif
diff --git a/drivers/scsi/thor/core/thor/core_thor.h b/drivers/scsi/thor/core/thor/core_thor.h
new file mode 100755
index 0000000..54f3753
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_thor.h
@@ -0,0 +1,501 @@
+#if !defined(CORE_SATA_H)
+#define CORE_SATA_H
+
+#include "core_ata.h"
+#include "com_tag.h"
+
+#define MAX_SATA_PORT_NUMBER		4
+#if /*(VER_OEM==VER_OEM_ASUS) || */(VER_OEM==VER_OEM_INTEL)
+#define MAX_PATA_PORT_NUMBER		0
+#else
+#define MAX_PATA_PORT_NUMBER		1
+#endif
+#define MAX_PORT_NUMBER				(MAX_SATA_PORT_NUMBER+MAX_PATA_PORT_NUMBER)
+
+#ifdef SUPPORT_PM
+#define MAX_DEVICE_PER_PORT			4	/*Hardware only support 4 device for PM*/
+#else
+#define MAX_DEVICE_PER_PORT			2
+#endif
+
+#define MAX_DEVICE_NUMBER			(MAX_PORT_NUMBER*MAX_DEVICE_PER_PORT)
+
+#define MAX_SLOT_NUMBER				32
+
+#define INTERNAL_REQ_COUNT			MAX_DEVICE_SUPPORTED
+
+#define SATA_CMD_LIST_SIZE			(32 * MAX_SLOT_NUMBER)
+#define SATA_RX_FIS_SIZE			256
+
+#define SATA_CMD_TABLE_HEADER_SIZE	0x80
+#define SATA_CMD_TABLE_SG_SIZE		(HW_SG_ENTRY_MAX * 16)
+#define SATA_CMD_TABLE_SIZE			(SATA_CMD_TABLE_HEADER_SIZE + SATA_CMD_TABLE_SG_SIZE)
+
+#define SATA_SCRATCH_BUFFER_SIZE	sizeof(ATA_Identify_Data)
+
+/* various functions for master/slave support */
+#define PATA_MapDeviceId(ID)		( (ID) % MAX_DEVICE_PER_PORT )
+#define PATA_MapPortId(ID)			( (ID) / MAX_DEVICE_PER_PORT )
+
+#define DEVICE_TYPE_ATAPI						MV_BIT(0)
+
+/* Device initialization state */
+#define DEVICE_STATE_IDLE						0x0
+#define DEVICE_STATE_RESET_DONE					0x1
+#define DEVICE_STATE_IDENTIFY_DONE				0x2
+#define DEVICE_STATE_SET_UDMA_DONE				0x3
+#define DEVICE_STATE_SET_PIO_DONE				0x4
+#define DEVICE_STATE_ENABLE_WRITE_CACHE_DONE	0x5
+#define DEVICE_STATE_ENABLE_READ_AHEAD_DONE		0x6
+#define DEVICE_STATE_INIT_DONE					0xFF
+
+/* Device status */
+#define DEVICE_STATUS_NO_DEVICE					MV_BIT(0)
+#define DEVICE_STATUS_EXISTING					MV_BIT(1)
+#define DEVICE_STATUS_FUNCTIONAL				MV_BIT(2)
+#ifdef HOTPLUG_ISSUE_WORKROUND
+#define DEVICE_STATUS_UNPLUG    				MV_BIT(3)
+#endif
+
+#ifdef SUPPORT_ATA_POWER_MANAGEMENT
+#define DEVICE_STATUS_SLEEP            MV_BIT(5)
+#define DEVICE_STATUS_IDLE             MV_BIT(6)
+#define DEVICE_STATUS_STANDBY          MV_BIT(7)
+#endif
+
+/* 3G and TCQ */
+#define DEVICE_CAPACITY_48BIT_SUPPORTED			MV_BIT(0)
+#define	DEVICE_CAPACITY_SMART_SUPPORTED			MV_BIT(1)
+#define	DEVICE_CAPACITY_WRITECACHE_SUPPORTED	MV_BIT(2)
+#define DEVICE_CAPACITY_NCQ_SUPPORTED			MV_BIT(3)
+#define DEVICE_CAPACITY_RATE_1_5G				MV_BIT(4)
+#define DEVICE_CAPACITY_RATE_3G					MV_BIT(5)	
+#define DEVICE_CAPACITY_READLOGEXT_SUPPORTED	MV_BIT(6)
+#define DEVICE_CAPACITY_READ_LOOK_AHEAD_SUPPORTED	MV_BIT(7)
+#define DEVICE_CAPACITY_SMART_SELF_TEST_SUPPORTED	MV_BIT(8)
+#define 	DEVICE_CAPABILITY_PROTECTION_INFORMATION_SUPPORTED  MV_BIT(9)
+#ifdef SUPPORT_ATA_SECURITY_CMD
+#define DEVICE_CAPACITY_SECURITY_SUPPORTED	MV_BIT(10)
+#endif
+
+#define DEVICE_SETTING_SMART_ENABLED                MV_BIT(0)
+#define DEVICE_SETTING_WRITECACHE_ENABLED           MV_BIT(1)
+#define DEVICE_SETTING_PI_ENABLED                   MV_BIT(2)
+#define DEVICE_SETTING_READ_LOOK_AHEAD				MV_BIT(3)
+#ifdef SUPPORT_ATA_SECURITY_CMD
+#define DEVICE_SETTING_SECURITY_LOCKED				MV_BIT(4)
+#endif
+
+#define PATA_CABLE_DETECTION		1
+
+#ifdef PATA_CABLE_DETECTION
+#define MV_80_PIN_CABLE				0
+#define MV_40_PIN_CABLE				1
+#endif
+
+struct _Domain_Device {
+	MV_U16 Id;
+	MV_U8 Device_Type;				/* ATA or ATAPI */
+	MV_U8 State;					/* DEVICE_STATE_XXX */
+	
+	MV_U8 Status;					/* DEVICE_STATUS_XXX */
+	MV_BOOLEAN Is_Slave;
+	MV_BOOLEAN Need_Notify;			/* added for PM hot plug */
+	MV_U8 Reserved0;
+
+	struct _Domain_Port * PPort;	/* Shortcut to the port. */
+
+	/* 
+	 * Different device should have a different struct here. 
+	 * Now it's SATA device only.
+	 */
+	MV_U16 Capacity;				/* Be able to support NCQ, 48 bit LBA. */
+	MV_U16 Setting;					/* The supported features are enabled or not. */
+
+	MV_U8 PM_Number;
+	MV_U8 PIO_Mode;
+	MV_U8 MDMA_Mode;
+	MV_U8 UDMA_Mode;
+
+	MV_U8 Current_PIO;
+	MV_U8 Current_MDMA;
+	MV_U8 Current_UDMA;
+	MV_U8 Reserved1;
+
+	MV_U64 Max_LBA;
+	MV_U8 Queue_Depth;
+	MV_U8 Timer_ID;					/* for error handling */
+	MV_U8 Outstanding_Req;			/* for error handling */
+	MV_U32 Reset_Count;				/* for error handling. If reset too many times, set down this device. */
+	MV_U8 Reserved2[4];
+
+
+	MV_U8 Serial_Number[20];
+	MV_U8 Model_Number[40];
+	MV_U8 Firmware_Revision[8];
+	MV_U32 WWN;
+
+	/* The scratch buffer used for initialization like identify */
+	MV_PVOID Scratch_Buffer;
+	MV_PHYSICAL_ADDR Scratch_Buffer_DMA;
+
+	/* Internal request used in device initialization */
+	PMV_Request Internal_Req;
+
+};
+
+/* Port initialization state */
+
+#define PORT_STATE_IDLE					0x00
+#define PORT_STATE_INIT_DONE			0xFF
+
+#define PORT_TYPE_SATA					0
+#define PORT_TYPE_PATA					1
+#define PORT_TYPE_PM					4 /*PM Support, lily tested*/
+
+#define PORT_CAPACITY_NCQ_SUPPORTED		MV_BIT(0)
+
+#define PORT_SETTING_NCQ_RUNNING		MV_BIT(0)
+#define PORT_SETTING_PM_EXISTING		MV_BIT(1)
+#define PORT_SETTING_PM_FUNCTIONAL		MV_BIT(2)	// added by Harriet for PM hot plug 
+#define PORT_SETTING_DURING_RETRY		MV_BIT(3)
+typedef void (*mv_reset_cmd_completion)(MV_PVOID);
+#define MAX_RESET_TIMES 3	
+
+#define PORT_ERROR_AT_PLUGIN			1
+#define PORT_ERROR_AT_RUNTIME		2
+
+struct _Domain_Port {
+	MV_PVOID Core_Extension;
+
+	MV_U8 Id;
+	MV_U8 Port_State;
+	MV_U8 Type;					/* PORT_TYPE_XXX */
+	MV_U8 Capacity;				/* PORT_CAPACITY_XXX */
+	MV_U8 Setting;				/* PORT_SETTING_XXX */
+	MV_U8 Device_Number;		/* How many devices this port has now? */	
+	MV_U16 PM_Vendor_Id;
+	MV_U16 PM_Device_Id;
+	MV_U8 PM_Product_Revision;
+	MV_U8 PM_Spec_Revision;
+	MV_U8 PM_Num_Ports;
+	MV_U8 PATA_cable_type;      /* Save the correct cable type from BIOS.*/
+	MV_U8 Reserved0[2];
+	MV_LPVOID Mmio_Base;		/* Base address for SATA Port Registers */
+	MV_LPVOID Mmio_SCR;			/* Base address for sata register(SCR) */
+	MV_PVOID Cmd_List;			/* Can be PMV_PATA_Command_Header or PMV_Command_Header */
+	MV_PHYSICAL_ADDR Cmd_List_DMA;
+
+	/* Received FIS */
+	MV_PVOID RX_FIS;
+	MV_PHYSICAL_ADDR RX_FIS_DMA;
+
+	/* The 32 command tables. */
+	MV_PVOID Cmd_Table;
+	MV_PHYSICAL_ADDR Cmd_Table_DMA;
+
+	/* Running MV_Requests are linked together. */	
+	PMV_Request Running_Req[MAX_SLOT_NUMBER];	
+
+	/* Which slot has requests running. */
+	MV_U32	Running_Slot;
+//	MV_U32	Reserved1;
+	MV_U32	VS_RegC;
+#ifdef COMMAND_ISSUE_WORKROUND
+	OSSW_DECLARE_TIMER(timer);
+	MV_U8 Hot_Plug_Timer;
+	MV_U8 reset_hba_times;
+	MV_PVOID	timer_para;
+	mv_reset_cmd_completion	command_callback; /* call back function */
+	MV_U8 find_disk;
+	MV_U8 error_state;
+#endif
+
+	struct _Domain_Device Device[MAX_DEVICE_PER_PORT];	
+
+	//Timer: for time out checking.
+
+	Tag_Stack Tag_Pool;
+#ifdef HOTPLUG_ISSUE_WORKROUND
+	MV_U32 old_stat;
+#endif
+};
+
+/*
+ * Hardware related format. Never change their size. Must follow hardware specification.
+ */
+/* AHCI a little difference */
+typedef struct _MV_Command_Header
+{
+#ifdef __MV_BIG_ENDIAN_BITFIELD__
+	MV_U8	Reserved0 : 2;
+	MV_U8	Packet_Command : 1;
+	MV_U8	FIS_Length : 5;
+			
+	MV_U8	PM_Port : 4;
+	MV_U8	NCQ : 1;
+	MV_U8	Reserved1: 2;
+	MV_U8	Reset : 1;
+#else /* default to __MV_LITTLE_ENDIAN_BITFIELD__ */
+	MV_U8	FIS_Length : 5;		/* Command FIS Length in DWORD */
+	MV_U8	Packet_Command : 1;	/* ATAPI packet command */
+	MV_U8	Reserved0 : 2;
+
+	MV_U8	Reset : 1;
+	MV_U8	Reserved1: 2;
+	MV_U8	NCQ : 1;
+	MV_U8	PM_Port : 4;
+#endif /* __MV_BIG_ENDIAN_BITFIELD__ */
+	MV_U16	PRD_Entry_Count : 16;
+
+	MV_U32	Reserved2;
+	MV_U32	Table_Address;
+	MV_U32	Table_Address_High;
+
+	MV_U32	Reserved3[4];
+} MV_Command_Header, *PMV_Command_Header;
+
+typedef struct _MV_PATA_Command_Header
+{
+#ifdef __MV_BIG_ENDIAN_BITFIELD__
+	MV_U8	Packet_Command : 1;	
+	MV_U8	TCQ : 1;		
+	MV_U8	Controller_Command : 1;	
+	MV_U8	PIO_Sector_Count : 5;   
+
+	MV_U8	Is_Slave : 1;		
+	MV_U8	Reset : 1;		
+	MV_U8	Diagnostic_Command : 1;	
+	MV_U8	Is_48Bit : 1;		
+	MV_U8	PIO_Sector_Command : 1;	
+	MV_U8	Non_Data : 1;		
+	MV_U8	Data_In : 1;		
+	MV_U8	DMA : 1;		
+#else /* __MV_BIG_ENDIAN_BITFIELD__ */
+	MV_U8	PIO_Sector_Count : 5;   /* PIO command data block size in sector */
+	MV_U8	Controller_Command : 1;	/* If 1, command is for the controller instead of the device */
+	MV_U8	TCQ : 1;		/* TCQ command */
+	MV_U8	Packet_Command : 1;	/* ATAPI packet command */
+
+	MV_U8	DMA : 1;		/* DMA command */
+	MV_U8	Data_In : 1;		/* Data is from device to host. */
+	MV_U8	Non_Data : 1;		/* Non data command */
+	MV_U8	PIO_Sector_Command : 1;	/* PIO multiple sectors commands including read/write sector, read/write multiple. */
+	MV_U8	Is_48Bit : 1;		/* 48 bit command */
+	MV_U8	Diagnostic_Command : 1;	/* Execute device diagnostic command */
+	MV_U8	Reset : 1;		/* Device reset command */
+	MV_U8	Is_Slave : 1;		/* 0 for master and 1 for slave */
+#endif /* __MV_BIG_ENDIAN_BITFIELD__ */
+	MV_U16	PRD_Entry_Count;
+
+
+	MV_U32	Reserved0;
+	MV_U32	Table_Address;
+	MV_U32	Table_Address_High;
+
+	MV_U32	Reserved3[4];
+} MV_PATA_Command_Header, *PMV_PATA_Command_Header;
+
+/* SATA Command Table: same with AHCI */
+typedef struct _MV_Command_Table
+{
+	MV_U8	FIS[64];								/* Command FIS */
+	MV_U8	ATAPI_CDB[32];							/* ATAPI CDB */
+	MV_U8	Reserve0[32];
+	MV_SG_Entry PRD_Entry[MAX_SG_ENTRY];		/* 32 */
+} MV_Command_Table, *PMV_Command_Table;
+
+#define DIMMSGTABLE_SIZE sizeof(AHCI_DIMM_SG_TABLE)
+
+#define	MV_PCI_BAR			 5
+#define	MV_CMD_ATAPI		 (1L << 5)
+#define	MV_CMD_WRITE		 (1L << 6)
+
+#define	RX_FIS_D2H_REG		 0x40	/* offset of D2H Register FIS data */
+
+	/* global controller registers */
+#define	HOST_CAP			 0x00 	/* host capabilities */
+#define	HOST_CTL			 0x04	/* global host control */
+#define	HOST_IRQ_STAT		 0x08 	/* interrupt status */
+#define	HOST_PORTS_IMPL		 0x0c 	/* bitmap of implemented ports */
+#define	HOST_VERSION		 0x10 	/* AHCI spec. version compliancy */
+
+	/* HOST_CTL bits */
+#define	HOST_RESET			(1L << 0)  /* reset controller; self-clear */
+#define	HOST_IRQ_EN		 	(1L << 1)  /* global IRQ enable */
+#define	HOST_MVL_EN		 	(1L << 31) /* AHCI enabled */
+
+	/* HOST_CAP bits */
+#define	HOST_CAP_64			(1L << 31) /* PCI DAC (64-bit DMA) support */
+
+	/* Vendor specific register */
+#define VENDOR_DETECT		0xA4	/* PATA device/PM detection */
+	/* VENDOR_DETECT bits */
+#define VENDOR_DETECT_PATA	(1L << 10)	/* PATA device detection (bit10) (0 - default) */
+#define VENDOR_DETECT_PM	(1L << 11)	/* PM device detection (bit11) (0 - default) */
+
+	/* registers for each SATA port */
+#define	PORT_LST_ADDR		0x00 /* command list DMA addr */
+#define	PORT_LST_ADDR_HI	0x04 /* command list DMA addr hi */
+#define	PORT_FIS_ADDR		0x08 /* FIS rx buf addr */
+#define	PORT_FIS_ADDR_HI	0x0c /* FIS rx buf addr hi */
+#define	PORT_IRQ_STAT		0x10 /* interrupt status */
+#define	PORT_IRQ_MASK		0x14 /* interrupt enable/disable mask */
+#define	PORT_CMD			0x18 /* port command */
+
+	/* For SATA port */
+#define	PORT_TFDATA			0x20	/* taskfile data */
+#define	PORT_SIG			0x24	/* device TF signature */
+#define	PORT_CMD_ISSUE		0x38 	/* command issue */
+#define	PORT_FIFO_CTL		0x44	/* vendor unique FIFO control */
+#define	PORT_SCR			0x28 	/* SATA phy register block */
+#define	PORT_SCR_STAT		0x28 	/* SATA phy register: SStatus */
+#define	PORT_SCR_CTL		0x2c 	/* SATA phy register: SControl */
+#define	PORT_SCR_ERR		0x30 	/* SATA phy register: SError */
+#define	PORT_SCR_ACT		0x34 	/* SATA phy register: SActive */
+#define	PORT_PM_FIS_0		0x3c	/* port multiplier FIS content 0 */
+#define	PORT_PM_FIS_1		0x40	/* port multiplier FIS content 1 */
+
+/* #if (VER_OEM==VER_OEM_ASUS) */
+#define	PORT_VSR_ADDR		0x78	/* port Vendor Specific Register Address */
+#define	PORT_VSR_DATA		0x7c	/* port Vendor Specific Register Data */
+/* #endif */
+#define VS_REG_SIG			0xab
+
+	/* For PATA port */
+#define	PORT_MASTER_TF0		0x20
+#define	PORT_MASTER_TF1		0x24
+#define	PORT_MASTER_TF2		0x28
+#define	PORT_SLAVE_TF0		0x30
+#define	PORT_SLAVE_TF1		0x3c
+#define	PORT_SLAVE_TF2		0x40
+#define	PORT_INTERNAL_STATE_MACHINE	0x48
+
+
+#ifdef AHCI
+	/* PORT_IRQ_{STAT,MASK} bits */
+#define	PORT_IRQ_COLD_PRES		(1L << 31)	/* cold presence detect */
+#define	PORT_IRQ_TF_ERR			(1L << 30)	/* task file error */
+#define	PORT_IRQ_HBUS_ERR		(1L << 29)	/* host bus fatal error */
+#define	PORT_IRQ_HBUS_DATA_ERR	(1L << 28)	/* host bus data error */
+#define	PORT_IRQ_IF_ERR			(1L << 27)	/* interface fatal error */
+#define	PORT_IRQ_IF_NONFATAL	(1L << 26)	/* interface non-fatal error */
+#define	PORT_IRQ_OVERFLOW		(1L << 24)	/* xfer exhausted available S/G */
+#define	PORT_IRQ_BAD_PMP		(1L << 23)	/* incorrect port multiplier */
+
+#define	PORT_IRQ_PHYRDY			(1L << 22)	 /* PhyRdy changed */
+#define PORT_IRQ_ASYNC_NOTIF	(1L << 20)	 /* Asynchronous Notification, SDB FIS */
+#define	PORT_IRQ_DEV_ILCK		(1L << 7)		/* device interlock */
+#define	PORT_IRQ_CONNECT		(1L << 6)		/* port connect change status */
+#define	PORT_IRQ_SG_DONE		(1L << 5)		/* descriptor processed */
+#define	PORT_IRQ_UNK_FIS		(1L << 4)		/* unknown FIS rx'd */
+#define	PORT_IRQ_SDB_FIS		(1L << 3)		/* Set Device Bits FIS rx'd */
+#define	PORT_IRQ_DMAS_FIS		(1L << 2)		/* DMA Setup FIS rx'd */
+#define	PORT_IRQ_PIOS_FIS		(1L << 1)		/* PIO Setup FIS rx'd */
+#define	PORT_IRQ_D2H_REG_FIS	(1L << 0)		/* D2H Register FIS rx'd */
+
+#define	PORT_IRQ_FATAL	(PORT_IRQ_TF_ERR |\
+				  		PORT_IRQ_HBUS_ERR |\
+				  		PORT_IRQ_HBUS_DATA_ERR |\
+				  		PORT_IRQ_IF_ERR)
+#define	DEF_PORT_IRQ	(PORT_IRQ_FATAL | PORT_IRQ_PHYRDY |\
+				  		PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE |\
+				  		PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS |\
+				  		PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS |\
+				  		PORT_IRQ_D2H_REG_FIS)
+#else
+	/* PORT_IRQ_{STAT,MASK} bits for SATA port */
+#define	PORT_IRQ_SIGNATURE_FIS	(1L << 31)	/* Signature FIS received */
+#define	PORT_IRQ_TF_ERR			(1L << 30)	/* task file error */
+#define	PORT_IRQ_PHYRDY			(1L << 22)	/* PhyRdy changed */
+
+#define	PORT_IRQ_BIST			(1L << 21)	/* BIST activate FIS received */
+#define	PORT_IRQ_ASYNC_NOTIF	(1L << 20)	/* Asynchronous notification received */
+#define	PORT_IRQ_LINK_RECEIVE_ERROR	(1L << 7)
+#define	PORT_IRQ_LINK_TRANSMIT_ERROR (1L << 6)
+#define	PORT_IRQ_PIO_DONE		(1L << 5)		/* PIO Data-in Done */
+#define	PORT_IRQ_UNK_FIS		(1L << 4)		/* unknown FIS rx'd */
+#define	PORT_IRQ_SDB_FIS		(1L << 3)		/* Set Device Bits FIS rx'd */
+#define	PORT_IRQ_DMAS_FIS		(1L << 2)		/* DMA Setup FIS rx'd */
+#define	PORT_IRQ_PIOS_FIS		(1L << 1)		/* PIO Setup FIS rx'd */
+#define	PORT_IRQ_D2H_REG_FIS	(1L << 0)		/* D2H Register FIS rx'd */
+
+#if 0
+#define	DEF_PORT_IRQ		 (MV_U32)(\
+				PORT_IRQ_SIGNATURE_FIS | PORT_IRQ_TF_ERR |\
+				PORT_IRQ_PHYRDY | \
+				PORT_IRQ_BIST |	PORT_IRQ_ASYNC_NOTIF | \
+				PORT_IRQ_LINK_RECEIVE_ERROR | PORT_IRQ_LINK_TRANSMIT_ERROR |\
+				PORT_IRQ_PIO_DONE | PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS | PORT_IRQ_D2H_REG_FIS)
+#else
+#define	DEF_PORT_IRQ		 (MV_U32)(\
+				PORT_IRQ_SIGNATURE_FIS | PORT_IRQ_TF_ERR |\
+				PORT_IRQ_PHYRDY | \
+				PORT_IRQ_BIST |	PORT_IRQ_ASYNC_NOTIF | \
+				PORT_IRQ_PIO_DONE | PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS | PORT_IRQ_D2H_REG_FIS)
+#endif
+
+	/* PORT_IRQ_{STAT,MASK} bits for PATA port */
+#define	PORT_IRQ_PATA_DEVICE0_DONE	MV_BIT(0)
+#define	PORT_IRQ_PATA_DEVICE0_ERROR	MV_BIT(1)
+#define	PORT_IRQ_PATA_DEVICE1_DONE	MV_BIT(2)
+#define	PORT_IRQ_PATA_DEVICE1_ERROR	MV_BIT(3)
+#define	DEF_PORT_PATA_IRQ	(PORT_IRQ_PATA_DEVICE0_DONE | PORT_IRQ_PATA_DEVICE0_ERROR\
+								| PORT_IRQ_PATA_DEVICE1_DONE | PORT_IRQ_PATA_DEVICE1_ERROR)
+#endif
+
+#ifdef AHCI
+	/* PORT_CMD bits */
+#define	PORT_CMD_LIST_ON		(1L << 15)	/* cmd list DMA engine running */
+#define	PORT_CMD_FIS_ON			(1L << 14)	/* FIS DMA engine running */
+#define	PORT_CMD_FIS_RX			(1L << 4)		/* Enable FIS receive DMA engine */
+#define	PORT_CMD_POWER_ON		(1L << 2)		/* Power up device */
+#define	PORT_CMD_SPIN_UP		(1L << 1)		/* Spin up device */
+#define	PORT_CMD_START			(1L << 0)		/* Enable port DMA engine */
+
+#define	PORT_CMD_ICC_ACTIVE		(0x1L << 28)	/* Put i/f in active state */
+#define	PORT_CMD_ICC_PARTIAL	(0x2L << 28)	/* Put i/f in partial state */
+#define	PORT_CMD_ICC_SLUMBER	(0x6L << 28)	/* Put i/f in slumber state */
+#else
+	/* PORT_CMD bits for SATA port */
+#define	PORT_CMD_LIST_ON		(1L << 15)	/* cmd list DMA engine running */
+#define	PORT_CMD_FIS_ON			(1L << 14)	/* FIS DMA engine running */
+
+#define	PORT_CMD_FIS_RX			(1L << 4)		/* Enable FIS receive DMA engine */
+#define	PORT_CMD_START			(1L << 0)		/* Enable port DMA engine */
+
+	/* PORT_CMD bits for PATA port */
+#define	PORT_CMD_PATA_LIST_ON	MV_BIT(15)
+#define	PORT_CMD_PATA_HARD_RESET	MV_BIT(3)
+#define	PORT_CMD_PATA_INTERRUPT MV_BIT(1)
+#define	PORT_CMD_PATA_START		MV_BIT(0)
+#endif
+
+#define	PORT_SSTATUS_IPM_NO_DEVICE	0x0L	/* IPM: device not present or communication not established */
+#define	PORT_SSTATUS_IPM_ACTIVE		0x1L	/* IPM: Interface in active state */
+#define	PORT_SSTATUS_IPM_PARTIAL	0x2L	/* IPM: Interface in partical power management state */
+#define	PORT_SSTATUS_IPRM_SLUMBER	0x6L	/* IPM: Interface in slumber power management state */
+
+#define	PORT_TF_STATUS_BSY	(1L<<7)	/* Task file status: BSY */
+#define	PORT_TF_STATUS_DRQ 	(1L<<3)	/* Task file status: DRQ */
+#define	PORT_TF_STATUS_ERR 	(1L<<0)	/* Task file status: ERR */
+
+
+typedef enum _MV_QUEUE_COMMAND_RESULT
+{
+    MV_QUEUE_COMMAND_RESULT_FINISHED = 0,
+    MV_QUEUE_COMMAND_RESULT_FULL,
+    MV_QUEUE_COMMAND_RESULT_SENT,
+} MV_QUEUE_COMMAND_RESULT;
+
+#define SATA_GetCommandHeader(pPort, slot)	\
+	((PMV_Command_Header)pPort->Cmd_List + slot)
+
+#define PATA_GetCommandHeader(pPort, slot)	\
+	((PMV_PATA_Command_Header)pPort->Cmd_List + slot)
+
+#define Port_GetCommandTable(pPort, slot)	\
+	((PMV_Command_Table)((MV_PU8)pPort->Cmd_Table + slot * SATA_CMD_TABLE_SIZE))
+
+#endif /* CORE_SATA_H */
+
diff --git a/drivers/scsi/thor/core/thor/core_xor.c b/drivers/scsi/thor/core/thor/core_xor.c
new file mode 100755
index 0000000..30ec591
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_xor.c
@@ -0,0 +1,846 @@
+#include "mv_include.h"
+#include "core_inter.h"
+
+#ifndef USE_NEW_SGTABLE
+#ifdef RAID_DRIVER
+#ifdef SOFTWARE_XOR
+
+#ifdef _OS_LINUX
+
+/*
+ * Software XOR operations
+ */
+void mvXORWrite (MV_PVOID This, PMV_XOR_Request pXORReq);
+void mvXORCompare (MV_PVOID This, PMV_XOR_Request pXORReq);
+void mvXORDMA (MV_PVOID This, PMV_XOR_Request pXORReq);
+
+void Core_ModuleSendXORRequest(MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+
+	switch (pXORReq->Request_Type) 
+	{
+		case XOR_REQUEST_WRITE:
+			mvXORWrite (pCore, pXORReq);
+			break;
+		case XOR_REQUEST_COMPARE:
+			mvXORCompare (pCore, pXORReq);
+			break;
+		case XOR_REQUEST_DMA:
+			mvXORDMA (pCore, pXORReq);
+			break;
+		default:
+			pXORReq->Request_Status = XOR_STATUS_INVALID_REQUEST;
+			break;
+	}
+	pXORReq->Completion( pXORReq->Cmd_Initiator, pXORReq );
+}
+
+void mvXORInit(
+	PMV_SG_Entry	*pSGPtr,
+	MV_PU32			SGSizePtr,
+	MV_PVOID		*pVirPtr,
+	MV_PU32			SGOffPtr,
+	PMV_SG_Table	SGListPtr,
+	MV_U8			tableCount,
+	MV_PU32			minSizePtr)
+{
+	MV_U8 id;
+	for ( id=0; id<tableCount; id++ ) {
+		pSGPtr[id] = SGListPtr[id].Entry_Ptr;
+		pVirPtr[id] = (MV_PVOID)
+			( (MV_PTR_INTEGER)pSGPtr[id]->Base_Address 
+			| (MV_PTR_INTEGER)((_MV_U64)pSGPtr[id]->Base_Address_High<<32) );
+		SGSizePtr[id] = pSGPtr[id]->Size;
+		SGOffPtr[id] = 0;
+		if ( *minSizePtr > SGSizePtr[id] ) *minSizePtr=SGSizePtr[id];
+	}
+}
+
+void mvXORUpdateEntry(
+	PMV_SG_Entry	*pSGPtr,
+	MV_PU32			SGSizePtr,
+	MV_PVOID		*pVirPtr,
+	MV_PU32			SGOffPtr,
+	MV_U32			finishSize,
+	MV_U8			tableCount,
+	MV_PU32			minSizePtr)
+{
+	MV_U8 id;
+	for ( id=0; id<tableCount; id++ ) {
+		if ( SGSizePtr[id] > finishSize )
+			SGSizePtr[id] -= finishSize;
+		else {
+			pSGPtr[id]++;
+			pVirPtr[id] = (MV_PVOID)
+					( (MV_PTR_INTEGER)pSGPtr[id]->Base_Address 
+					| (MV_PTR_INTEGER)((_MV_U64)pSGPtr[id]->Base_Address_High<<32) );
+			SGSizePtr[id] = pSGPtr[id]->Size;
+			SGOffPtr[id] = 0;
+		}
+		if ( *minSizePtr > SGSizePtr[id] ) *minSizePtr=SGSizePtr[id];
+	}
+}
+
+MV_PVOID mv_get_kvaddr(PMV_SG_Entry sg_entry, MV_PVOID addr)
+{
+#ifdef _OS_LINUX
+	MV_U8 map;
+	struct scatterlist *sg = NULL;
+	MV_PVOID kvaddr = NULL;
+	MV_U16 offset = 0;
+
+	sg = (MV_PVOID)((MV_PTR_INTEGER)sg_entry->Base_Address |
+		(MV_PTR_INTEGER)((_MV_U64)sg_entry->Base_Address_High << 32));
+	map = sg_entry->Reserved0;
+	if (map == 0) return sg;
+	MV_ASSERT((sg_entry->Reserved0&0x1) == 1);
+
+	offset = ((sg_entry->Reserved0) >> 16) + sg->offset;
+	kvaddr = kmap_atomic(sg->page, KM_IRQ0) + offset;
+	return kvaddr;
+#endif
+#ifdef _OS_WINDOWS
+	return addr;
+#endif
+}
+
+MV_VOID mv_put_kvaddr(PMV_SG_Entry sg_entry, MV_PVOID kvaddr)
+{
+#ifdef _OS_LINUX
+	MV_U8 map;
+	struct scatterlist *sg = NULL;
+	MV_U16 offset = 0;
+
+	map = sg_entry->Reserved0;
+	if (map == 0) return;
+	MV_ASSERT((sg_entry->Reserved0&0x1) == 1);
+
+	sg = (MV_PVOID)((MV_PTR_INTEGER)sg_entry->Base_Address |
+		(MV_PTR_INTEGER)((_MV_U64)sg_entry->Base_Address_High << 32));
+	offset = ((sg_entry->Reserved0) >> 16) + sg->offset;
+	flush_dcache_page(sg->page);
+	kunmap_atomic(kvaddr - offset, KM_IRQ0);
+#endif
+}
+
+MV_VOID mv_save_val_8(PMV_SG_Entry sg_entry, MV_U32 sge_off, 
+	MV_PU8 kaddr, MV_U8 val)
+{
+#ifdef _OS_LINUX
+	MV_U8 map;
+	struct scatterlist *sg = NULL;
+	MV_PU8 kvaddr = NULL;
+	MV_U16 offset = 0;
+
+	sg = (MV_PVOID)((MV_PTR_INTEGER)sg_entry->Base_Address |
+		(MV_PTR_INTEGER)((_MV_U64)sg_entry->Base_Address_High << 32));
+
+	map = sg_entry->Reserved0;
+	if (map == 0) {
+		MV_ASSERT((sg == (struct scatterlist *)kaddr));
+		*(kaddr + sge_off) = val;
+		return;
+	}
+
+	offset = ((sg_entry->Reserved0) >> 16) + sg->offset + sge_off;
+	kvaddr = kmap_atomic(sg->page, KM_IRQ0) + offset;
+	*(kvaddr) = val;
+	kunmap_atomic(kvaddr - offset, KM_IRQ0);
+#endif
+#ifdef _OS_WINDOWS
+	*(kaddr + sge_off) = val;
+#endif
+}
+
+#ifdef SUPPORT_XOR_DWORD
+static MV_VOID mv_save_val_32(PMV_SG_Entry sg_entry, MV_U32 sge_off, 
+	MV_PU32 kaddr, MV_U32 val)
+{
+#ifdef _OS_LINUX
+	MV_U8 map;
+	struct scatterlist *sg = NULL;
+	MV_PU32 kvaddr = NULL;
+	MV_U16 offset = 0;
+
+	sg = (MV_PVOID)((MV_PTR_INTEGER)sg_entry->Base_Address |
+		(MV_PTR_INTEGER)((_MV_U64)sg_entry->Base_Address_High << 32));
+
+	map = sg_entry->Reserved0;
+	if (map == 0) {
+		MV_ASSERT((sg == (struct scatterlist *)kaddr));
+		*(kaddr + sge_off) = val;
+		return;
+	}
+
+	offset = ((sg_entry->Reserved0) >> 16) + sg->offset;
+	kvaddr = kmap_atomic(sg->page, KM_IRQ0) + offset;
+	kvaddr += sge_off;
+	*(kvaddr) = val;
+	kvaddr -= sge_off;
+	kvaddr = (MV_PU32)((MV_PU8)kvaddr - offset);
+	kunmap_atomic(kvaddr, KM_IRQ0);
+#endif
+#ifdef _OS_WINDOWS
+	*(kaddr + sge_off) = val;
+#endif
+}
+#endif /* SUPPORT_XOR_DWORD */
+
+MV_U8 mvXORByte(
+	PMV_SG_Entry	*sg_entry,
+	MV_PU8			*pSourceVirPtr,
+	PMV_XOR_Request	pXORReq,
+	MV_U8			tId,
+	MV_PU32			sge_off
+)
+{
+	MV_U8 xorResult, sId;
+	MV_PU8 addr;
+
+	addr = mv_get_kvaddr(sg_entry[0], pSourceVirPtr[0]);
+	xorResult = GF_Multiply(*(addr + sge_off[0]), pXORReq->Coef[tId][0]);
+	mv_put_kvaddr(sg_entry[0], addr);
+
+	for ( sId=1; sId<pXORReq->Source_SG_Table_Count; sId++ ) {
+		addr = mv_get_kvaddr(sg_entry[sId], pSourceVirPtr[sId]);
+		xorResult = GF_Add(xorResult, 
+			GF_Multiply(*(addr + sge_off[sId]), pXORReq->Coef[tId][sId]));
+		mv_put_kvaddr(sg_entry[sId], addr);
+	}
+	return xorResult;
+}
+
+#ifdef SUPPORT_XOR_DWORD
+MV_U32 mvXORDWord(
+	PMV_SG_Entry	*sg_entry,
+	MV_PU32			*pSourceVirPtr,
+	PMV_XOR_Request	pXORReq,
+	MV_U8			tId,
+	MV_PU32			sge_off
+)
+{
+	MV_U8	sId;
+	MV_U32 xorResult;
+	MV_PU32 addr = NULL;
+
+	addr = mv_get_kvaddr(sg_entry[0], pSourceVirPtr[0]);
+	xorResult = GF_Multiply(*(addr + sge_off[0]), pXORReq->Coef[tId][0]);
+	mv_put_kvaddr(sg_entry[0], addr);
+
+	for ( sId=1; sId<pXORReq->Source_SG_Table_Count; sId++ ) {
+		addr = mv_get_kvaddr(sg_entry[sId], pSourceVirPtr[sId]);
+		xorResult = GF_Add(xorResult,
+			GF_Multiply(*(addr + sge_off[sId]), pXORReq->Coef[tId][sId]));
+		mv_put_kvaddr(sg_entry[sId], addr);
+	}
+	return xorResult;
+}
+#endif /* SUPPORT_XOR_DWORD */
+
+/* The SG Table should have the virtual address instead of the physical address. */
+void mvXORWrite(MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	PMV_SG_Entry	pSourceSG[XOR_SOURCE_SG_COUNT];
+	PMV_SG_Entry	pTargetSG[XOR_TARGET_SG_COUNT];
+	MV_U32			sourceSize[XOR_SOURCE_SG_COUNT];
+	MV_U32			targetSize[XOR_TARGET_SG_COUNT];
+	MV_U32			sourceOff[XOR_SOURCE_SG_COUNT];
+	MV_U32			targetOff[XOR_TARGET_SG_COUNT];
+	MV_U32 i;
+	/* source index and target index. */
+	MV_U8 sId,tId;
+	MV_U32 size, remainSize, minSize;
+#ifdef SUPPORT_XOR_DWORD
+	MV_PU32			pSourceVir[XOR_SOURCE_SG_COUNT];
+	MV_PU32			pTargetVir[XOR_TARGET_SG_COUNT];
+	MV_U32			xorResult, Dword_size;
+#else
+	MV_PU8			pSourceVir[XOR_SOURCE_SG_COUNT];
+	MV_PU8			pTargetVir[XOR_TARGET_SG_COUNT];
+	MV_U8			xorResult;
+#endif
+
+	/* Initialize these two variables. */
+	/* All the SG table should have same Byte_Count */
+	remainSize = pXORReq->Source_SG_Table_List[0].Byte_Count;
+	minSize = remainSize;
+	/* Initialize XOR source */
+	mvXORInit(pSourceSG, sourceSize, (MV_PVOID)pSourceVir, sourceOff,
+			  pXORReq->Source_SG_Table_List,
+			  pXORReq->Source_SG_Table_Count,
+			  &minSize);
+	/* Initialize XOR target */
+	mvXORInit(pTargetSG, targetSize, (MV_PVOID)pTargetVir, targetOff,
+			  pXORReq->Target_SG_Table_List,
+			  pXORReq->Target_SG_Table_Count,
+			  &minSize);
+
+	/* Navigate all the SG table, calculate the target xor value. */
+	while ( remainSize>0 ) 
+	{
+		size = minSize;
+#ifdef SUPPORT_XOR_DWORD
+		MV_DASSERT( !(size%4) );
+		Dword_size = size/4;
+		for ( i=0; i<Dword_size; i++ ) 
+#else
+		for ( i=0; i<size; i++ ) 
+#endif
+		{
+			for ( tId=0; tId<pXORReq->Target_SG_Table_Count; tId++ )
+			{
+#ifdef SUPPORT_XOR_DWORD
+				xorResult = mvXORDWord(pSourceSG, pSourceVir, pXORReq, tId, sourceOff);
+				mv_save_val_32(pTargetSG[tId], targetOff[tId], pTargetVir[tId], xorResult);
+				targetOff[tId]++;
+#else
+				xorResult = mvXORByte(pSourceSG, pSourceVir, pXORReq, tId, sourceOff);
+				mv_save_val_8(pTargetSG[tId], targetOff[tId], pTargetVir[tId], xorResult);
+				targetOff[tId]++;
+#endif
+			}
+
+			for ( sId=0; sId<pXORReq->Source_SG_Table_Count; sId++ )
+				sourceOff[sId]++;
+		}
+
+		/* Update entry pointer, size */
+		MV_DASSERT( remainSize>=size );
+		remainSize -= size;
+		minSize = remainSize;
+		/* Update XOR source */
+		mvXORUpdateEntry(pSourceSG, sourceSize, (MV_PVOID)pSourceVir, sourceOff,
+						 size, pXORReq->Source_SG_Table_Count, &minSize);
+		/* Update XOR target */
+		mvXORUpdateEntry(pTargetSG, targetSize, (MV_PVOID)pTargetVir, targetOff,
+						 size, pXORReq->Target_SG_Table_Count, &minSize);
+	}
+
+	pXORReq->Request_Status = XOR_STATUS_SUCCESS;
+}
+
+/* consolidate compare and write */
+void mvXORCompare(MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	PMV_SG_Entry	pSourceSG[XOR_SOURCE_SG_COUNT];
+	MV_U32			sourceSize[XOR_SOURCE_SG_COUNT];
+	MV_U32			sourceOff[XOR_SOURCE_SG_COUNT];
+	MV_U32			totalSize, remainSize, minSize, size, i;
+	MV_U8			sId;
+#ifdef SUPPORT_XOR_DWORD
+	MV_PU32			pSourceVir[XOR_SOURCE_SG_COUNT];
+	MV_U32			xorResult, Dword_size;
+#else
+	MV_PU8			pSourceVir[XOR_SOURCE_SG_COUNT];
+	MV_U8			xorResult;
+#endif
+
+	/* All the SG table should have same Byte_Count */
+	totalSize = remainSize = minSize = pXORReq->Source_SG_Table_List[0].Byte_Count;
+	mvXORInit(pSourceSG, sourceSize, (MV_PVOID)pSourceVir, sourceOff,
+			  pXORReq->Source_SG_Table_List,
+			  pXORReq->Source_SG_Table_Count,
+			  &minSize);
+	while ( remainSize>0 ) {
+		size = minSize;
+#ifdef SUPPORT_XOR_DWORD
+		MV_DASSERT( !(size%4) );
+		Dword_size = size/4;
+		for ( i=0; i<Dword_size; i++ ) {
+			xorResult = mvXORDWord(pSourceSG, pSourceVir, pXORReq, 0, sourceOff);
+#else
+		for ( i=0; i<size; i++ ) {
+			xorResult = mvXORByte(pSourceSG, pSourceVir, pXORReq, 0, sourceOff);
+#endif
+			if (xorResult != 0) {
+				pXORReq->Request_Status = XOR_STATUS_ERROR;
+#ifdef SUPPORT_XOR_DWORD
+				pXORReq->Error_Offset = totalSize - remainSize + i*4;
+#else
+				pXORReq->Error_Offset = totalSize - remainSize + i;
+#endif
+				return;
+			}
+			for ( sId=0; sId<pXORReq->Source_SG_Table_Count; sId++ )
+				sourceOff[sId]++;
+		}
+
+		/* Update entry pointer, size */
+		MV_DASSERT( remainSize>=size );
+		remainSize -= size;
+		minSize = remainSize;
+		mvXORUpdateEntry(pSourceSG, sourceSize, (MV_PVOID)pSourceVir, sourceOff,
+						 size, pXORReq->Source_SG_Table_Count, &minSize);
+	}
+}
+
+void mvXORDMA(MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	MV_ASSERT( MV_FALSE );
+}
+
+#endif /* _OS_LINUX */
+
+#ifdef _OS_WINDOWS
+
+/*
+ * Software XOR operations
+ */
+
+void mvXORWrite (MV_PVOID This, PMV_XOR_Request pXORReq);
+void mvXORCompare (MV_PVOID This, PMV_XOR_Request pXORReq);
+void mvXORDMA (MV_PVOID This, PMV_XOR_Request pXORReq);
+
+#ifndef SUPPORT_RAID6
+MV_U8 mvXORInitArray (
+	MV_PVOID This, 
+	PMV_XOR_Request pXORReq, 
+	PMV_SG_Entry *SG_entry,
+	MV_PU32 SG_size,
+	MV_PU8 *pSource, 
+	MV_PU32 table_size);
+#endif
+
+#ifdef SIMULATOR
+void _Core_ModuleSendXORRequest(MV_PVOID This, PMV_XOR_Request pXORReq)
+#else	/*SIMULATOR*/
+void Core_ModuleSendXORRequest(MV_PVOID This, PMV_XOR_Request pXORReq)
+#endif	/*!SIMULATOR*/
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+
+	switch (pXORReq->Request_Type) 
+	{
+		case XOR_REQUEST_WRITE:
+			mvXORWrite (pCore, pXORReq);
+			break;
+		case XOR_REQUEST_COMPARE:
+			mvXORCompare (pCore, pXORReq);
+			break;
+		case XOR_REQUEST_DMA:
+			mvXORDMA (pCore, pXORReq);
+			break;
+		default:
+			pXORReq->Request_Status = XOR_STATUS_INVALID_REQUEST;
+			break;
+	}
+#ifndef SIMULATOR
+	pXORReq->Completion( pXORReq->Cmd_Initiator, pXORReq );
+#endif	/*!SIMULATOR*/
+}
+
+#ifndef SUPPORT_RAID6
+void mvXORWrite (MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	MV_ASSERT(MV_FALSE);
+}
+
+void mvXORCompare (MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+
+//	PMV_SG_Entry SG_entry[MAX_SG_ENTRY + 1];		// last element is target
+	PMV_SG_Entry SG_entry[2];
+//	MV_U32 SG_size[MAX_SG_ENTRY + 1];
+	MV_U32 SG_size[2];	// number of source, currently support 2 sources
+
+	MV_U32 min_size;
+	MV_U32 table_size, total_byte = 0;
+	MV_U8 num_sources, sourceCount;
+	MV_U32 sizeCount;
+	//PMV_SG_Table current_table;
+//	MV_PU8 pSource[MAX_SG_ENTRY];
+	MV_PU8 pSource[2];
+	MV_U8 xorResult;
+
+	num_sources = pXORReq->Source_SG_Table_Count;
+	if (num_sources==0) {
+		pXORReq->Request_Status = XOR_STATUS_INVALID_PARAMETER;
+		return;
+	}
+
+	// init array & error checking
+	if ( mvXORInitArray(pCore, pXORReq, SG_entry, SG_size, pSource, &table_size) != num_sources ) 
+	{
+		pXORReq->Request_Status = XOR_STATUS_INVALID_PARAMETER;
+		return;
+	}
+
+	while (total_byte < table_size) 
+	{
+		min_size = SG_size[0];
+		for (sourceCount=1; sourceCount<num_sources; sourceCount++) 
+		{
+			if (min_size > SG_size[sourceCount])
+				min_size = SG_size[sourceCount];	
+		}
+
+		for (sizeCount=0; sizeCount<min_size; sizeCount++) 
+		{
+			xorResult = *pSource[0];
+			for (sourceCount=1; sourceCount<num_sources; sourceCount++) 
+			{
+//				*pSource[0] = *pSource[0] ^ *pSource[sourceCount];
+				xorResult = xorResult ^ *pSource[sourceCount];
+				pSource[sourceCount]++;
+			}
+
+//			if (*pSource[0] != 0) 
+			if (xorResult != 0)
+			{
+				pXORReq->Request_Status = XOR_STATUS_ERROR;
+				pXORReq->Error_Offset = total_byte + sizeCount;
+				return;
+			}
+			pSource[0]++;
+		}
+		total_byte += min_size;
+
+		if (total_byte<table_size) {
+			// make new size array & increment entry pointer if needed
+			for (sourceCount=0; sourceCount<num_sources; sourceCount++) 
+			{
+				SG_size[sourceCount] -= min_size;
+				if (SG_size[sourceCount] == 0)
+				{
+					SG_entry[sourceCount]++;
+					SG_size[sourceCount] = SG_entry[sourceCount]->Size;
+					pSource[sourceCount] = raid_physical_to_virtual(pXORReq->Cmd_Initiator,
+											  SG_entry[sourceCount]->Base_Address);
+				}
+			}
+		}
+	}
+
+	pXORReq->Request_Status = XOR_STATUS_SUCCESS;
+}
+
+void mvXORDMA (MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	MV_ASSERT(MV_FALSE);
+}
+
+MV_U8 mvXORInitArray (
+	MV_PVOID This, 
+	PMV_XOR_Request pXORReq, 
+	PMV_SG_Entry *SG_entry,
+	MV_PU32 SG_size,
+	MV_PU8 *pSource, 
+	MV_PU32 table_size)
+{	
+	//PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	PMV_SG_Table current_table = NULL;
+	//MV_U8 j; 
+	MV_U8 i = 0;
+
+	*table_size = 0;
+	for (i=0; i<pXORReq->Source_SG_Table_Count; i++) {
+//	while ( !List_Empty(&pXORReq->Source_SG_Table_List) )
+//	{
+//		current_table = (PMV_SG_Table)List_GetFirstEntry(&pXORReq->Source_SG_Table_List, MV_XOR_Request, Queue_Pointer);
+		current_table = &pXORReq->Source_SG_Table_List[i];
+		MV_ASSERT( current_table!=NULL );
+
+		SG_entry[i] = &current_table->Entry_Ptr[0];
+		SG_size[i] = current_table->Entry_Ptr[0].Size;
+//		pSource[i] = (MV_PU8)SG_entry[i]->Base_Address;	
+		pSource[i] = raid_physical_to_virtual(pXORReq->Cmd_Initiator, current_table->Entry_Ptr[0].Base_Address);
+
+//		i++;
+	}
+	MV_DASSERT( current_table!=NULL );
+	if ( current_table ) *table_size = current_table->Byte_Count;
+	return i;
+}
+
+#else /* SUPPORT_RAID6 */
+
+void mvXORInit(
+	PMV_SG_Entry	*pSGPtr,
+	MV_PU32			SGSizePtr,
+	MV_PVOID		*pVirPtr,
+	PMV_SG_Table	SGListPtr,
+	MV_U8			tableCount,
+	MV_PU32			minSizePtr)
+{
+	MV_U8 id;
+	for ( id=0; id<tableCount; id++ ) {
+		pSGPtr[id] = SGListPtr[id].Entry_Ptr;
+		pVirPtr[id] = (MV_PVOID)
+			( (MV_PTR_INTEGER)pSGPtr[id]->Base_Address 
+			| (MV_PTR_INTEGER)pSGPtr[id]->Base_Address_High<<32 );
+		SGSizePtr[id] = pSGPtr[id]->Size;
+		if ( *minSizePtr > SGSizePtr[id] ) *minSizePtr=SGSizePtr[id];
+	}
+}
+
+void mvXORUpdateEntry(
+	PMV_SG_Entry	*pSGPtr,
+	MV_PU32			SGSizePtr,
+	MV_PVOID		*pVirPtr,
+	MV_U32			finishSize,
+	MV_U8			tableCount,
+	MV_PU32			minSizePtr)
+{
+	MV_U8 id;
+	for ( id=0; id<tableCount; id++ ) {
+		if ( SGSizePtr[id] > finishSize )
+			SGSizePtr[id] -= finishSize;
+		else {
+			pSGPtr[id]++;
+			pVirPtr[id] = (MV_PVOID)
+					( (MV_PTR_INTEGER)pSGPtr[id]->Base_Address 
+					| (MV_PTR_INTEGER)pSGPtr[id]->Base_Address_High<<32 );
+			SGSizePtr[id] = pSGPtr[id]->Size;
+		}
+		if ( *minSizePtr > SGSizePtr[id] ) *minSizePtr=SGSizePtr[id];
+	}
+}
+
+MV_U8 mvXORByte(
+	MV_PU8			*pSourceVirPtr,
+	PMV_XOR_Request	pXORReq,
+	MV_U8			tId
+)
+{
+	MV_U8 xorResult, sId;
+
+	xorResult = GF_Multiply(*pSourceVirPtr[0], pXORReq->Coef[tId][0]);
+	for ( sId=1; sId<pXORReq->Source_SG_Table_Count; sId++ ) {
+		xorResult = GF_Add(xorResult,
+						   GF_Multiply(*pSourceVirPtr[sId], pXORReq->Coef[tId][sId]));
+	}
+	return xorResult;
+}
+
+#ifdef SUPPORT_XOR_DWORD
+MV_U32 mvXORDWord(
+	MV_PU32			*pSourceVirPtr,
+	PMV_XOR_Request	pXORReq,
+	MV_U8			tId
+)
+{
+	MV_U8	sId;
+	MV_U32 xorResult;
+
+	xorResult = GF_Multiply(*pSourceVirPtr[0], pXORReq->Coef[tId][0]);
+	for ( sId=1; sId<pXORReq->Source_SG_Table_Count; sId++ ) {
+		xorResult = GF_Add(xorResult,
+						   GF_Multiply(*pSourceVirPtr[sId], pXORReq->Coef[tId][sId]));
+	}
+	return xorResult;
+}
+#endif /* SUPPORT_XOR_DWORD */
+
+/* The SG Table should have the virtual address instead of the physical address. */
+void mvXORWrite(MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	PMV_SG_Entry	pSourceSG[XOR_SOURCE_SG_COUNT];
+	PMV_SG_Entry	pTargetSG[XOR_TARGET_SG_COUNT];
+	MV_U32			sourceSize[XOR_SOURCE_SG_COUNT];
+	MV_U32			targetSize[XOR_TARGET_SG_COUNT];
+	MV_U32 i;
+	MV_U8 sId,tId;									/* source index and target index. */
+	MV_U32 size, remainSize, minSize;
+#ifdef SUPPORT_XOR_DWORD
+	MV_PU32			pSourceVir[XOR_SOURCE_SG_COUNT];
+	MV_PU32			pTargetVir[XOR_TARGET_SG_COUNT];
+	MV_U32			xorResult, Dword_size;
+#else
+	MV_PU8			pSourceVir[XOR_SOURCE_SG_COUNT];
+	MV_PU8			pTargetVir[XOR_TARGET_SG_COUNT];
+	MV_U8			xorResult;
+#endif
+
+	/* Initialize these two variables. */
+	remainSize = pXORReq->Source_SG_Table_List[0].Byte_Count;	/* All the SG table should have same Byte_Count */
+	minSize = remainSize;
+	/* Initialize XOR source */
+	mvXORInit(pSourceSG, sourceSize, (MV_PVOID*)pSourceVir,
+			  pXORReq->Source_SG_Table_List,
+			  pXORReq->Source_SG_Table_Count,
+			  &minSize);
+	/* Initialize XOR target */
+	mvXORInit(pTargetSG, targetSize, (MV_PVOID*)pTargetVir,
+			  pXORReq->Target_SG_Table_List,
+			  pXORReq->Target_SG_Table_Count,
+			  &minSize);
+
+/*
+	for ( sId=0; sId<pXORReq->Source_SG_Table_Count; sId++ ) 
+	{
+		pSourceSG[sId] = pXORReq->Source_SG_Table_List[sId].Entry;
+		sourceSize[sId] = pSourceSG[sId]->Size;
+		pSourceVir[sId] = (MV_PVOID)
+			( (MV_PTR_INTEGER)pSourceSG[sId]->Base_Address 
+			| (MV_PTR_INTEGER)pSourceSG[sId]->Base_Address_High<<32 );
+		MV_DASSERT( remainSize==pXORReq->Source_SG_Table_List[sId].Byte_Count );
+		if ( minSize>sourceSize[sId] ) minSize=sourceSize[sId];
+	}
+
+	for ( tId=0; tId<pXORReq->Target_SG_Table_Count; tId++ ) 
+	{
+		pTargetSG[tId] = pXORReq->Target_SG_Table_List[tId].Entry;
+		targetSize[tId] = pTargetSG[tId]->Size;
+		pTargetVir[tId] = (MV_PVOID)
+			( (MV_PTR_INTEGER)pTargetSG[tId]->Base_Address 
+			| (MV_PTR_INTEGER)pTargetSG[tId]->Base_Address_High<<32 );
+		MV_DASSERT( remainSize==pXORReq->Target_SG_Table_List[tId].Byte_Count );
+		if ( minSize>targetSize[tId] ) minSize=targetSize[tId];
+	}
+*/
+
+	/* Navigate all the SG table, calculate the target xor value. */
+	while ( remainSize>0 ) 
+	{
+		size = minSize;
+#ifdef SUPPORT_XOR_DWORD
+		MV_DASSERT( !(size%4) );
+		Dword_size = size/4;
+		for ( i=0; i<Dword_size; i++ ) 
+#else
+		for ( i=0; i<size; i++ ) 
+#endif
+		{
+			for ( tId=0; tId<pXORReq->Target_SG_Table_Count; tId++ )
+			{
+#ifdef SUPPORT_XOR_DWORD
+				xorResult = mvXORDWord(pSourceVir, pXORReq, tId);
+#else
+				xorResult = mvXORByte(pSourceVir, pXORReq, tId);
+#endif
+
+/*
+				tmp = GF_Multiply(*pSourceVir[0], pXORReq->Coef[tId][0]);
+
+				for ( sId=1; sId<pXORReq->Source_SG_Table_Count; sId++ )
+				{
+					tmp = GF_Add(tmp,
+								GF_Multiply(*pSourceVir[sId], pXORReq->Coef[tId][sId]));
+				}
+				*pTargetVir[tId] = tmp;
+*/
+				*pTargetVir[tId] = xorResult;
+				pTargetVir[tId]++;
+			}
+
+			for ( sId=0; sId<pXORReq->Source_SG_Table_Count; sId++ )
+				pSourceVir[sId]++;
+		}
+
+		/* Update entry pointer, size */
+		MV_DASSERT( remainSize>=size );
+		remainSize -= size;
+		minSize = remainSize;
+		/* Update XOR source */
+		mvXORUpdateEntry(pSourceSG, sourceSize, (MV_PVOID*)pSourceVir,
+						 size, pXORReq->Source_SG_Table_Count, &minSize);
+		/* Update XOR target */
+		mvXORUpdateEntry(pTargetSG, targetSize, (MV_PVOID*)pTargetVir,
+						 size, pXORReq->Target_SG_Table_Count, &minSize);
+/*
+
+		for ( sId=0; sId<pXORReq->Source_SG_Table_Count; sId++ )
+		{
+			if ( sourceSize[sId]>size )
+			{
+				sourceSize[sId]-=size;
+			}
+			else
+			{
+				pSourceSG[sId]++;
+				pSourceVir[sId] = (MV_PVOID)
+					( (MV_PTR_INTEGER)pSourceSG[sId]->Base_Address | (MV_PTR_INTEGER)pSourceSG[sId]->Base_Address_High<<32 );
+				sourceSize[sId] = pSourceSG[sId]->Size;
+			}
+			if ( minSize>sourceSize[sId] ) minSize=sourceSize[sId];
+		}
+
+		for ( tId=0; tId<pXORReq->Target_SG_Table_Count; tId++ )
+		{
+			if ( targetSize[tId]>size )
+			{
+				targetSize[tId]-=size;
+			}
+			else
+			{
+				pTargetSG[tId]++;
+				pTargetVir[tId] = (MV_PVOID)
+					( (MV_PTR_INTEGER)pTargetSG[tId]->Base_Address | (MV_PTR_INTEGER)pTargetSG[tId]->Base_Address_High<<32 );
+				targetSize[tId] = pTargetSG[tId]->Size;
+			}
+			if ( minSize>targetSize[tId] ) minSize=targetSize[tId];
+		}
+*/
+	}
+
+	pXORReq->Request_Status = XOR_STATUS_SUCCESS;
+}
+
+//consolidate compare and write
+void mvXORCompare (MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	PMV_SG_Entry	pSourceSG[XOR_SOURCE_SG_COUNT];
+	MV_U32			sourceSize[XOR_SOURCE_SG_COUNT];
+	MV_U32			totalSize, remainSize, minSize, size, i;
+	MV_U8			sId;
+#ifdef SUPPORT_XOR_DWORD
+	MV_PU32			pSourceVir[XOR_SOURCE_SG_COUNT];
+	MV_U32			xorResult, Dword_size;
+#else
+	MV_PU8			pSourceVir[XOR_SOURCE_SG_COUNT];
+	MV_U8			xorResult;
+#endif
+
+	/* All the SG table should have same Byte_Count */
+	totalSize = remainSize = minSize = pXORReq->Source_SG_Table_List[0].Byte_Count;
+	mvXORInit(pSourceSG, sourceSize, (MV_PVOID*)pSourceVir,
+			  pXORReq->Source_SG_Table_List,
+			  pXORReq->Source_SG_Table_Count,
+			  &minSize);
+	while ( remainSize>0 ) {
+		size = minSize;
+#ifdef SUPPORT_XOR_DWORD
+		MV_DASSERT( !(size%4) );
+		Dword_size = size/4;
+		for ( i=0; i<Dword_size; i++ ) {
+			xorResult = mvXORDWord(pSourceVir, pXORReq, 0);
+#else
+		for ( i=0; i<size; i++ ) {
+			xorResult = mvXORByte(pSourceVir, pXORReq, 0);
+#endif
+			if (xorResult != 0)	{
+				pXORReq->Request_Status = XOR_STATUS_ERROR;
+#ifdef SUPPORT_XOR_DWORD
+				pXORReq->Error_Offset = totalSize - remainSize + i*4;
+#else
+				pXORReq->Error_Offset = totalSize - remainSize + i;
+#endif
+				return;
+			}
+			for ( sId=0; sId<pXORReq->Source_SG_Table_Count; sId++ )
+				pSourceVir[sId]++;
+		}
+
+		/* Update entry pointer, size */
+		MV_DASSERT( remainSize>=size );
+		remainSize -= size;
+		minSize = remainSize;
+		mvXORUpdateEntry(pSourceSG, sourceSize, (MV_PVOID*)pSourceVir,
+						 size, pXORReq->Source_SG_Table_Count, &minSize);
+	}
+}
+
+void mvXORDMA (MV_PVOID This, PMV_XOR_Request pXORReq)
+{
+	MV_ASSERT( MV_FALSE );
+}
+
+#endif /* SUPPORT_RAID6 */
+
+#endif /* _OS_WINDOWS */
+
+#endif /* SOFTWARE_XOR */
+#endif /* RAID_DRIVER */
+#endif /* USE_NEW_SGTABLE */
diff --git a/drivers/scsi/thor/core/thor/core_xor.h b/drivers/scsi/thor/core/thor/core_xor.h
new file mode 100755
index 0000000..2227b3a
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/core_xor.h
@@ -0,0 +1,12 @@
+#ifndef CORE_XOR_H
+#define CORE_XOR_H
+
+#ifdef RAID_DRIVER
+void Core_ModuleSendXORRequest(MV_PVOID This, PMV_XOR_Request pXORReq);
+void MV_DumpXORRegister(MV_PVOID This);
+MV_BOOLEAN HandleXORQueue(MV_PVOID This);
+#endif /* RAID_DRIVER */
+
+#endif
+
+
diff --git a/drivers/scsi/thor/core/thor/scsi2sata.c b/drivers/scsi/thor/core/thor/scsi2sata.c
new file mode 100755
index 0000000..1bc6a17
--- /dev/null
+++ b/drivers/scsi/thor/core/thor/scsi2sata.c
@@ -0,0 +1,763 @@
+#include "mv_include.h"
+
+#include "core_inter.h"
+
+#include "core_sata.h"
+#include "core_ata.h"
+#include "core_sat.h"
+
+/*
+ * Translate SCSI command to SATA FIS
+ * The following SCSI command set is the minimum required.
+ *		Standard Inquiry
+ *		Read Capacity
+ *		Test Unit Ready
+ *		Start/Stop Unit
+ *		Read 10
+ *		Write 10
+ *		Request Sense
+ *		Mode Sense/Select
+ */
+MV_VOID SCSI_To_FIS(MV_PVOID This, PMV_Request pReq, MV_U8 tag, PATA_TaskFile pTaskFile)
+{
+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)This;
+	PDomain_Port pPort = &pCore->Ports[PATA_MapPortId(pReq->Device_Id)];
+	PMV_Command_Table pCmdTable = Port_GetCommandTable(pPort, tag);
+
+	PSATA_FIS_REG_H2D pFIS = (PSATA_FIS_REG_H2D)pCmdTable->FIS;
+#ifdef SUPPORT_PM
+	PDomain_Device pDevice = &pPort->Device[PATA_MapDeviceId(pReq->Device_Id)];
+#endif
+	/* 
+	 * 1. SoftReset is not supported yet.
+	 * 2. PM_Port
+	 */
+	pFIS->FIS_Type = SATA_FIS_TYPE_REG_H2D;
+
+#ifdef SUPPORT_PM
+	pFIS->PM_Port = pDevice->PM_Number;
+#else
+	pFIS->PM_Port = 0;
+#endif
+
+	pFIS->C = 1;	/* Update command register rather than devcie control register */
+	pFIS->Command = pTaskFile->Command;
+	pFIS->Features = pTaskFile->Features;
+	pFIS->Device = pTaskFile->Device;
+	pFIS->Control = pTaskFile->Control;
+
+	pFIS->LBA_Low = pTaskFile->LBA_Low;
+	pFIS->LBA_Mid = pTaskFile->LBA_Mid;
+	pFIS->LBA_High = pTaskFile->LBA_High;
+	pFIS->Sector_Count = pTaskFile->Sector_Count;
+
+	/* No matter it's 48bit or not, I've set the values. */
+	pFIS->LBA_Low_Exp = pTaskFile->LBA_Low_Exp;
+	pFIS->LBA_Mid_Exp = pTaskFile->LBA_Mid_Exp;
+	pFIS->LBA_High_Exp = pTaskFile->LBA_High_Exp;
+	pFIS->Features_Exp = pTaskFile->Feature_Exp;
+	pFIS->Sector_Count_Exp = pTaskFile->Sector_Count_Exp;
+}
+
+/* Set MV_Request.Cmd_Flag */
+MV_BOOLEAN Category_CDB_Type(
+	IN PDomain_Device pDevice,
+	IN PMV_Request pReq
+	)
+{
+	PDomain_Port pPort = pDevice->PPort;
+
+	switch ( pReq->Cdb[0] )
+	{
+		case SCSI_CMD_READ_10:
+		case SCSI_CMD_READ_16:
+			pReq->Cmd_Flag |= CMD_FLAG_DATA_IN;
+			
+		case SCSI_CMD_WRITE_10:
+		case SCSI_CMD_WRITE_16:
+		case SCSI_CMD_VERIFY_10:
+			/* 
+			 * 
+			 * CMD_FLAG_DATA_IN
+			 * CMD_FLAG_NON_DATA
+			 * CMD_FLAG_DMA
+			 */
+			if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+				pReq->Cmd_Flag |= CMD_FLAG_PACKET;
+
+			if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED )
+				pReq->Cmd_Flag |= CMD_FLAG_48BIT;
+
+			if ( pDevice->Capacity&DEVICE_CAPACITY_NCQ_SUPPORTED )
+			{
+				// might be a PM - assert is no longer true
+				//MV_DASSERT( pPort->Type==PORT_TYPE_SATA );		
+#if 0
+				if ( (pReq->Cdb[0]==SCSI_CMD_READ_10)
+					|| (pReq->Cdb[0]==SCSI_CMD_WRITE_10) )
+#else
+				if (SCSI_IS_READ(pReq->Cdb[0]) || SCSI_IS_WRITE(pReq->Cdb[0]))
+#endif
+				{
+					if ( (pPort->Running_Slot==0)
+						|| (pPort->Setting&PORT_SETTING_NCQ_RUNNING) )
+					{
+						/* hardware workaround:
+						 * don't do NCQ on silicon image PM */
+						if( !((pPort->Setting & PORT_SETTING_PM_EXISTING) && 
+							(pPort->PM_Vendor_Id == 0x1095 )) )
+						{
+							if ( pReq->Scsi_Status!=REQ_STATUS_RETRY )
+								pReq->Cmd_Flag |= CMD_FLAG_NCQ;
+						}
+					}
+				}
+			}
+
+			break;
+
+		case SCSI_CMD_MARVELL_SPECIFIC:
+			{
+				/* This request should be for core module */
+				if ( pReq->Cdb[1]!=CDB_CORE_MODULE )
+					return MV_FALSE;
+				switch ( pReq->Cdb[2] )
+				{
+					case CDB_CORE_IDENTIFY:
+					case CDB_CORE_READ_LOG_EXT:
+						pReq->Cmd_Flag |= CMD_FLAG_DATA_IN;
+						break;
+					case CDB_CORE_SET_UDMA_MODE:
+					case CDB_CORE_SET_PIO_MODE:
+					case CDB_CORE_ENABLE_WRITE_CACHE:
+					case CDB_CORE_DISABLE_WRITE_CACHE:
+					case CDB_CORE_ENABLE_READ_AHEAD:
+					case CDB_CORE_DISABLE_READ_AHEAD:
+						pReq->Cmd_Flag |= CMD_FLAG_NON_DATA;
+						break;
+				#ifdef SUPPORT_ATA_SMART
+					case CDB_CORE_ATA_IDENTIFY_PACKET_DEVICE:
+						pReq->Cmd_Flag |= (CMD_FLAG_DATA_IN | CMD_FLAG_SMART);
+						break;
+					case CDB_CORE_ENABLE_SMART:
+					case CDB_CORE_DISABLE_SMART:
+					case CDB_CORE_SMART_RETURN_STATUS:
+					case  CDB_CORE_ATA_SMART_AUTO_OFFLINE:
+					case CDB_CORE_ATA_SMART_AUTOSAVE:      
+					case CDB_CORE_ATA_SMART_IMMEDIATE_OFFLINE:
+						pReq->Cmd_Flag |= (CMD_FLAG_NON_DATA | CMD_FLAG_SMART);
+						break;
+					case CDB_CORE_ATA_SMART_READ_VALUES:
+					case CDB_CORE_ATA_SMART_READ_THRESHOLDS:
+					case CDB_CORE_ATA_SMART_READ_LOG_SECTOR:
+						pReq->Cmd_Flag |= (CMD_FLAG_DATA_IN | CMD_FLAG_SMART);
+						break;
+					case CDB_CORE_ATA_SMART_WRITE_LOG_SECTOR:
+						pReq->Cmd_Flag |= (CMD_FLAG_DATA_OUT | CMD_FLAG_SMART);
+						break;
+				#endif
+					case CDB_CORE_ATA_IDENTIFY:
+						pReq->Cmd_Flag |= (CMD_FLAG_DATA_IN | CMD_FLAG_SMART);
+						break;
+					case CDB_CORE_SHUTDOWN:
+						if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+							return MV_FALSE;
+						MV_DPRINT(("Shutdown on device %d.\n", pReq->Device_Id));
+						pReq->Cmd_Flag |= CMD_FLAG_NON_DATA;
+						break;
+               #ifdef SUPPORT_ATA_POWER_MANAGEMENT
+					case CDB_CORE_ATA_SLEEP:
+					case CDB_CORE_ATA_IDLE:
+					case CDB_CORE_ATA_STANDBY:
+					case CDB_CORE_ATA_IDLE_IMMEDIATE:
+					case CDB_CORE_ATA_CHECK_POWER_MODE:
+					case CDB_CORE_ATA_STANDBY_IMMEDIATE:
+                                               pReq->Cmd_Flag |= CMD_FLAG_NON_DATA;
+                                               break;
+               #endif
+					case CDB_CORE_OS_SMART_CMD:
+						if  ((pReq->Cdb[3] != ATA_CMD_IDENTIFY_ATA) ||
+							(pReq->Cdb[3] != ATA_CMD_IDENTIY_ATAPI))
+							pReq->Cmd_Flag |= CMD_FLAG_SMART;
+						if (pDevice->Device_Type & DEVICE_TYPE_ATAPI)
+							pReq->Cmd_Flag |= CMD_FLAG_PACKET;
+						break;
+					default:
+						return MV_FALSE;
+				}
+				break;
+			}
+#ifdef SUPPORT_ATA_SECURITY_CMD
+			case ATA_16:
+			return MV_TRUE;
+			break;
+#endif
+		case SCSI_CMD_START_STOP_UNIT:	
+		case SCSI_CMD_SYNCHRONIZE_CACHE_10:
+			if ( !(pDevice->Device_Type & DEVICE_TYPE_ATAPI )){
+				if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED )
+					pReq->Cmd_Flag |= CMD_FLAG_48BIT;
+				pReq->Cmd_Flag |= CMD_FLAG_NON_DATA;
+				break;
+			}	//We will send this command to CD drive directly if it is ATAPI device.	
+		case SCSI_CMD_SND_DIAG:
+			pReq->Cmd_Flag |= CMD_FLAG_DATA_OUT;
+		case SCSI_CMD_INQUIRY:
+		case SCSI_CMD_READ_CAPACITY_10:
+		case SCSI_CMD_TEST_UNIT_READY:
+		case SCSI_CMD_MODE_SENSE_10:
+		case SCSI_CMD_MODE_SELECT_10:
+		case SCSI_CMD_PREVENT_MEDIUM_REMOVAL:
+		case SCSI_CMD_READ_TOC:
+		case SCSI_CMD_REQUEST_SENSE:
+		default:
+			if ( pDevice->Device_Type&DEVICE_TYPE_ATAPI )
+			{
+				pReq->Cmd_Flag |= CMD_FLAG_PACKET;
+				break;
+			}
+			else
+			{
+				MV_DPRINT(("Error: Unknown request: 0x%x.\n", pReq->Cdb[0]));
+				return MV_FALSE;
+			}
+	}
+
+	return MV_TRUE;
+}
+
+static void rw16_taskfile(PMV_Request req, PATA_TaskFile tf, int tag)
+{
+	if (req->Cmd_Flag & CMD_FLAG_NCQ) {
+		
+		tf->Features = req->Cdb[13];
+		tf->Feature_Exp = req->Cdb[12];
+
+		tf->Sector_Count = tag<<3;
+		
+		tf->LBA_Low = req->Cdb[9];
+		tf->LBA_Mid = req->Cdb[8];
+		tf->LBA_High = req->Cdb[7];
+		tf->LBA_Low_Exp = req->Cdb[6];
+		tf->LBA_Mid_Exp = req->Cdb[5];
+		tf->LBA_High_Exp = req->Cdb[4];
+
+		tf->Device = MV_BIT(6);
+
+		if (req->Cdb[0] == SCSI_CMD_READ_16)
+			tf->Command = ATA_CMD_READ_FPDMA_QUEUED;
+		else if (req->Cdb[0] == SCSI_CMD_WRITE_16)
+			tf->Command = ATA_CMD_WRITE_FPDMA_QUEUED;
+	} else if (req->Cmd_Flag & CMD_FLAG_48BIT) {
+		MV_DASSERT(!(req->Cmd_Flag&CMD_FLAG_NCQ));
+
+		tf->Sector_Count = req->Cdb[13];
+		tf->Sector_Count_Exp = req->Cdb[12];
+
+		tf->LBA_Low = req->Cdb[9];
+		tf->LBA_Mid = req->Cdb[8];
+		tf->LBA_High = req->Cdb[7];
+		tf->LBA_Low_Exp = req->Cdb[6];
+		tf->LBA_Mid_Exp = req->Cdb[5];
+		tf->LBA_High_Exp = req->Cdb[4];
+
+		tf->Device = MV_BIT(6);
+
+		if (req->Cdb[0] == SCSI_CMD_READ_16)
+			tf->Command = ATA_CMD_READ_DMA_EXT;
+		else if (req->Cdb[0] == SCSI_CMD_WRITE_16)
+			tf->Command = ATA_CMD_WRITE_DMA_EXT;
+	}
+}
+#ifdef SUPPORT_ATA_SECURITY_CMD
+void scsi_ata_ata_passthru_16_fill_taskfile(MV_Request *req, OUT PATA_TaskFile  taskfile)
+{
+	taskfile->Command = req->Cdb[14];
+	taskfile->Features = req->Cdb[4];
+	taskfile->Device = req->Cdb[13];
+
+	taskfile->LBA_Low = req->Cdb[8];
+	taskfile->LBA_Mid = req->Cdb[10];
+	taskfile->LBA_High = req->Cdb[12];
+	taskfile->Sector_Count = req->Cdb[6];
+	taskfile->Control = req->Cdb[15];
+	if (req->Cdb[1] & 0x01) {
+		taskfile->LBA_Low_Exp = req->Cdb[7];
+		taskfile->LBA_Mid_Exp = req->Cdb[9];
+		taskfile->LBA_High_Exp = req->Cdb[11];
+		taskfile->Sector_Count_Exp = req->Cdb[5];
+		taskfile->Feature_Exp = req->Cdb[3];
+	} else {
+		taskfile->LBA_Low_Exp = 0;
+		taskfile->LBA_Mid_Exp = 0;
+		taskfile->LBA_High_Exp = 0;
+		taskfile->Sector_Count_Exp = 0;
+		taskfile->Feature_Exp = 0;
+	}
+}
+#endif
+MV_BOOLEAN ATA_CDB2TaskFile(
+	IN PDomain_Device pDevice,
+	IN PMV_Request pReq, 
+	IN MV_U8 tag,
+	OUT PATA_TaskFile pTaskFile
+	)
+{
+	MV_ZeroMemory(pTaskFile, sizeof(ATA_TaskFile));
+
+	switch ( pReq->Cdb[0] )
+	{
+		case SCSI_CMD_READ_10:
+		case SCSI_CMD_WRITE_10:
+			{
+				
+				/* 
+				 * The OS maximum tranfer length is set to 128K.
+				 * For ATA_CMD_READ_DMA and ATA_CMD_WRITE_DMA,
+				 * the max size they can handle is 256 sectors.
+				 * And Sector_Count==0 means 256 sectors.
+				 * If OS request max lenght>128K, for 28 bit device, we have to split requests.
+				 */
+#ifndef _OS_LINUX  //Avoid keneral panic 
+				MV_DASSERT( ( (((MV_U16)pReq->Cdb[7])<<8) | (pReq->Cdb[8]) ) <= 256 );
+#endif
+				/*
+				 * 24 bit LBA can express 128GB.
+				 * 4 bytes LBA like SCSI_CMD_READ_10 can express 2TB.
+				 */
+			
+				/* Make sure Cmd_Flag has set already. */
+				#ifdef SUPPORT_ATA_SECURITY_CMD
+				if ( pReq->Cmd_Flag&CMD_FLAG_NCQ && !((pDevice->Setting&DEVICE_SETTING_SECURITY_LOCKED)==0x10))
+				#else
+				if ( pReq->Cmd_Flag&CMD_FLAG_NCQ)
+				#endif
+				{
+					
+					pTaskFile->Features = pReq->Cdb[8];
+					pTaskFile->Feature_Exp = pReq->Cdb[7];
+
+					pTaskFile->Sector_Count = tag<<3;
+					
+					pTaskFile->LBA_Low = pReq->Cdb[5];
+					pTaskFile->LBA_Mid = pReq->Cdb[4];
+					pTaskFile->LBA_High = pReq->Cdb[3];
+					pTaskFile->LBA_Low_Exp = pReq->Cdb[2];
+		
+					pTaskFile->Device = MV_BIT(6);
+
+					if ( pReq->Cdb[0]==SCSI_CMD_READ_10 )
+						pTaskFile->Command = ATA_CMD_READ_FPDMA_QUEUED;
+					else if ( pReq->Cdb[0]==SCSI_CMD_WRITE_10 )
+						pTaskFile->Command = ATA_CMD_WRITE_FPDMA_QUEUED;
+				}
+				else if ( pReq->Cmd_Flag&CMD_FLAG_48BIT )
+				{
+					MV_DASSERT( !(pReq->Cmd_Flag&CMD_FLAG_NCQ) );
+
+					pTaskFile->Sector_Count = pReq->Cdb[8];
+					pTaskFile->Sector_Count_Exp = pReq->Cdb[7];
+
+					pTaskFile->LBA_Low = pReq->Cdb[5];
+					pTaskFile->LBA_Mid = pReq->Cdb[4];
+					pTaskFile->LBA_High = pReq->Cdb[3];
+					pTaskFile->LBA_Low_Exp = pReq->Cdb[2];
+
+					pTaskFile->Device = MV_BIT(6);
+
+					if ( pReq->Cdb[0]==SCSI_CMD_READ_10 )
+						pTaskFile->Command = ATA_CMD_READ_DMA_EXT;
+					else if ( pReq->Cdb[0]==SCSI_CMD_WRITE_10 )
+						pTaskFile->Command = ATA_CMD_WRITE_DMA_EXT;
+				}
+				else
+				{
+					/* 28 bit DMA */
+					pTaskFile->Sector_Count = pReq->Cdb[8];		/* Could be zero */
+	
+					pTaskFile->LBA_Low = pReq->Cdb[5];
+					pTaskFile->LBA_Mid = pReq->Cdb[4];
+					pTaskFile->LBA_High = pReq->Cdb[3];
+			
+					pTaskFile->Device = MV_BIT(6) | (pReq->Cdb[2]&0xF);
+					
+					MV_DASSERT( (pReq->Cdb[2]&0xF0)==0 );
+
+					if ( pReq->Cdb[0]==SCSI_CMD_READ_10 )
+						pTaskFile->Command = ATA_CMD_READ_DMA;
+					else if ( pReq->Cdb[0]==SCSI_CMD_WRITE_10 )
+						pTaskFile->Command = ATA_CMD_WRITE_DMA;
+				}
+
+				break;
+			}
+#ifdef SUPPORT_ATA_SECURITY_CMD
+		case ATA_16:
+			scsi_ata_ata_passthru_16_fill_taskfile(pReq,pTaskFile);
+			break;
+#endif
+		case SCSI_CMD_READ_16:
+		case SCSI_CMD_WRITE_16:
+			rw16_taskfile(pReq, pTaskFile, tag);
+			break;
+
+		case SCSI_CMD_VERIFY_10:
+			/* 
+			 * For verify command, the size may need use two MV_U8, especially Windows.
+			 * For 28 bit device, we have to split the request.
+			 * For 48 bit device, we use ATA_CMD_VERIFY_EXT.
+			 */
+			if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED )
+			{
+				pTaskFile->Sector_Count = pReq->Cdb[8];
+				pTaskFile->Sector_Count_Exp = pReq->Cdb[7];
+
+				pTaskFile->LBA_Low = pReq->Cdb[5];
+				pTaskFile->LBA_Mid = pReq->Cdb[4];
+				pTaskFile->LBA_High = pReq->Cdb[3];
+				pTaskFile->LBA_Low_Exp = pReq->Cdb[2];
+
+				pTaskFile->Device = MV_BIT(6);
+
+				pTaskFile->Command = ATA_CMD_VERIFY_EXT;
+			}
+			else
+			{
+				pTaskFile->Sector_Count = pReq->Cdb[8];
+				
+				pTaskFile->LBA_Low = pReq->Cdb[5];
+				pTaskFile->LBA_Mid = pReq->Cdb[4];
+				pTaskFile->LBA_High = pReq->Cdb[3];
+
+				pTaskFile->Device = MV_BIT(6) | (pReq->Cdb[2]&0xF);
+				
+				MV_DASSERT( (pReq->Cdb[2]&0xF0)==0 );
+
+				pTaskFile->Command = ATA_CMD_VERIFY;				
+			}
+
+			break;
+
+		case SCSI_CMD_MARVELL_SPECIFIC:
+			{
+				/* This request should be for core module */
+				if ( pReq->Cdb[1]!=CDB_CORE_MODULE )
+					return MV_FALSE;
+				
+				switch ( pReq->Cdb[2] )
+				{
+					case CDB_CORE_IDENTIFY:
+						pTaskFile->Command = ATA_CMD_IDENTIFY_ATA;
+						break;
+					case CDB_CORE_SET_UDMA_MODE:
+						pTaskFile->Command = ATA_CMD_SET_FEATURES;
+						pTaskFile->Features = ATA_CMD_SET_TRANSFER_MODE;
+						pTaskFile->Sector_Count = 0x40 | pReq->Cdb[3];
+						MV_DASSERT( pReq->Cdb[4]==MV_FALSE );	/* Use UDMA mode */
+						break;
+
+					case CDB_CORE_SET_PIO_MODE:
+						pTaskFile->Command = ATA_CMD_SET_FEATURES;
+						pTaskFile->Features = ATA_CMD_SET_TRANSFER_MODE;
+						pTaskFile->Sector_Count = 0x08 | pReq->Cdb[3];
+						break;
+
+					case CDB_CORE_ENABLE_WRITE_CACHE:
+						pTaskFile->Command = ATA_CMD_SET_FEATURES;
+						pTaskFile->Features = ATA_CMD_ENABLE_WRITE_CACHE;
+						 pDevice->Setting |= DEVICE_SETTING_WRITECACHE_ENABLED;
+						break;
+			
+					case CDB_CORE_DISABLE_WRITE_CACHE:
+						pTaskFile->Command = ATA_CMD_SET_FEATURES;
+						pTaskFile->Features = ATA_CMD_DISABLE_WRITE_CACHE;
+						 pDevice->Setting &= ~DEVICE_SETTING_WRITECACHE_ENABLED;
+						break;
+						
+					case CDB_CORE_SHUTDOWN:
+						if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED )
+							pTaskFile->Command = ATA_CMD_FLUSH_EXT;
+						else
+							pTaskFile->Command = ATA_CMD_FLUSH;
+						break;
+
+                      	 #ifdef SUPPORT_ATA_POWER_MANAGEMENT
+					case CDB_CORE_ATA_IDLE:
+						pTaskFile->Command = 0xe3;
+						pTaskFile->Sector_Count = pReq->Cdb[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?4:6];
+							break;
+					case CDB_CORE_ATA_STANDBY:
+						pTaskFile->Command = 0xe2;
+							break;
+					case CDB_CORE_ATA_IDLE_IMMEDIATE:
+						pTaskFile->Command = 0xe1;
+							break;
+					case CDB_CORE_ATA_STANDBY_IMMEDIATE:
+						pTaskFile->Command = 0xe0;
+							break;
+					case CDB_CORE_ATA_CHECK_POWER_MODE:
+						pTaskFile->Command = 0xe5;
+							break;
+                         	        case CDB_CORE_ATA_SLEEP:
+                                               	pTaskFile->Command = 0xe6;
+                                               	break;
+                         #endif
+					case CDB_CORE_ATA_IDENTIFY:
+						pTaskFile->Command = 0xec;
+						break;
+
+					case CDB_CORE_ENABLE_READ_AHEAD:	
+						pTaskFile->Command = ATA_CMD_SET_FEATURES;
+						pTaskFile->Features = ATA_CMD_ENABLE_READ_LOOK_AHEAD;
+						break;
+
+					case CDB_CORE_DISABLE_READ_AHEAD:
+						pTaskFile->Command = ATA_CMD_SET_FEATURES;
+						pTaskFile->Features = ATA_CMD_DISABLE_READ_LOOK_AHEAD;
+						break;
+					
+					case CDB_CORE_READ_LOG_EXT:
+						pTaskFile->Command = ATA_CMD_READ_LOG_EXT;
+						pTaskFile->Sector_Count = 1;	/* Read one sector */
+						pTaskFile->LBA_Low = 0x10;		/* Page 10h */
+						break;
+
+					case CDB_CORE_OS_SMART_CMD:
+						pTaskFile->Command = pReq->Cdb[3];
+						pTaskFile->Features = pReq->Cdb[4];
+						pTaskFile->LBA_Low = pReq->Cdb[5];
+						pTaskFile->LBA_Mid  = pReq->Cdb[6];
+						pTaskFile->LBA_High = pReq->Cdb[7];
+						pTaskFile->LBA_Low_Exp = pReq->Cdb[9];
+						pTaskFile->Sector_Count = pReq->Cdb[8];
+						break;
+				#ifdef SUPPORT_ATA_SMART
+					case CDB_CORE_ATA_IDENTIFY_PACKET_DEVICE:
+						pTaskFile->Command = ATA_IDENTIFY_PACKET_DEVICE;
+						pTaskFile->Sector_Count = 0x1;
+						break;
+					case CDB_CORE_ENABLE_SMART:
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_CMD_ENABLE_SMART;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->LBA_Low = 0x1;
+						break;
+					case CDB_CORE_DISABLE_SMART:
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_CMD_DISABLE_SMART;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->LBA_Low = 0x1;
+						break;
+					case CDB_CORE_SMART_RETURN_STATUS:
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_CMD_SMART_RETURN_STATUS;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						break;	
+					case CDB_CORE_ATA_SMART_READ_VALUES:
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_SMART_READ_VALUES;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->LBA_Low = 0x1;
+						break;
+					case CDB_CORE_ATA_SMART_READ_THRESHOLDS:
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_SMART_READ_THRESHOLDS;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->LBA_Low = 0x1;
+						break;
+					case CDB_CORE_ATA_SMART_READ_LOG_SECTOR:
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_SMART_READ_LOG_SECTOR;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->Sector_Count = 0x1;
+						pTaskFile->LBA_Low = pReq->Cdb[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?5:8];
+						break;
+					case CDB_CORE_ATA_SMART_WRITE_LOG_SECTOR :
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_SMART_WRITE_LOG_SECTOR;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->Sector_Count = 0x1;
+						pTaskFile->LBA_Low = pReq->Cdb[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?5:8];
+						break;
+					case  CDB_CORE_ATA_SMART_AUTO_OFFLINE:
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_SMART_AUTO_OFFLINE;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->LBA_Low= pReq->Cdb[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?5:8];
+						pTaskFile->Sector_Count = pReq->Cdb[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?4:6];
+						break;
+					case CDB_CORE_ATA_SMART_AUTOSAVE:    
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_SMART_AUTOSAVE;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->Sector_Count =  pReq->Cdb[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?4 : 6];
+						break;
+					case CDB_CORE_ATA_SMART_IMMEDIATE_OFFLINE:
+						pTaskFile->Command = ATA_CMD_SMART;
+						pTaskFile->Features = ATA_SMART_IMMEDIATE_OFFLINE;
+						pTaskFile->LBA_Mid = 0x4F;
+						pTaskFile->LBA_High = 0xC2;
+						pTaskFile->LBA_Low= pReq->Cdb[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?5:8];
+						pTaskFile->Sector_Count =  pReq->Cdb[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?4 : 6];
+						break;
+				#endif /*#ifdef SUPPORT_ATA_SMART*/
+										
+					default:
+						return MV_FALSE;
+				}
+				break;
+			}
+
+		case SCSI_CMD_SYNCHRONIZE_CACHE_10:
+			if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED )
+				pTaskFile->Command = ATA_CMD_FLUSH_EXT;
+			else
+				pTaskFile->Command = ATA_CMD_FLUSH;
+			pTaskFile->Device = MV_BIT(6);
+			break;
+		case SCSI_CMD_START_STOP_UNIT:
+			if (pReq->Cdb[4] & MV_BIT(0))
+			{
+				pTaskFile->Command = ATA_CMD_SEEK;
+				pTaskFile->Device = MV_BIT(6);
+			}
+			else
+			{
+				pTaskFile->Command = ATA_CMD_STANDBY_IMMEDIATE;
+			}
+			break;
+		case SCSI_CMD_SND_DIAG:
+			Core_Fill_SendDiagTaskfile( pDevice,pReq, pTaskFile);
+			break;
+		case SCSI_CMD_REQUEST_SENSE:
+		case SCSI_CMD_MODE_SELECT_10:
+		case SCSI_CMD_MODE_SENSE_10:
+			MV_DPRINT(("Error: Unknown request: 0x%x.\n", pReq->Cdb[0]));
+
+		default:
+			return MV_FALSE;
+	}
+
+	/* 
+	 * Attention: Never return before this line if your return is MV_TRUE.
+	 * We need set the slave DEV bit here. 
+	 */
+	if ( pDevice->Is_Slave )		
+		pTaskFile->Device |= MV_BIT(4);
+
+	return MV_TRUE;
+}
+
+MV_BOOLEAN ATAPI_CDB2TaskFile(
+	IN PDomain_Device pDevice,
+	IN PMV_Request pReq, 
+	OUT PATA_TaskFile pTaskFile
+	)
+{
+	MV_ZeroMemory(pTaskFile, sizeof(ATA_TaskFile));
+
+	/* At the same time, set the command category as well. */
+	switch ( pReq->Cdb[0] )
+	{
+	case SCSI_CMD_MARVELL_SPECIFIC:
+		/* This request should be for core module */
+		if ( pReq->Cdb[1]!=CDB_CORE_MODULE )
+			return MV_FALSE;
+
+		switch ( pReq->Cdb[2] )
+		{
+		case CDB_CORE_IDENTIFY:
+			pTaskFile->Command = ATA_CMD_IDENTIY_ATAPI;
+			break;
+					
+		case CDB_CORE_SET_UDMA_MODE:
+			pTaskFile->Command = ATA_CMD_SET_FEATURES;
+			pTaskFile->Features = ATA_CMD_SET_TRANSFER_MODE;
+			if ( pReq->Cdb[4]==MV_TRUE )
+				pTaskFile->Sector_Count = 0x20 | pReq->Cdb[3];	/* MDMA mode */
+			else
+				pTaskFile->Sector_Count = 0x40 | pReq->Cdb[3];	/* UDMA mode*/
+
+			break;
+					
+		case CDB_CORE_SET_PIO_MODE:
+			pTaskFile->Command = ATA_CMD_SET_FEATURES;
+			pTaskFile->Features = ATA_CMD_SET_TRANSFER_MODE;
+			pTaskFile->Sector_Count = 0x08 | pReq->Cdb[3];
+			break;
+
+		case CDB_CORE_OS_SMART_CMD:
+		//Now we don't support SMART on ATAPI device.
+		default:
+			return MV_FALSE;
+		}
+		break;
+
+#ifdef _OS_LINUX
+	case SCSI_CMD_READ_DISC_INFO:
+#endif /* _OS_LINUX */
+	case SCSI_CMD_READ_10:
+	case SCSI_CMD_WRITE_10:
+	case SCSI_CMD_VERIFY_10:
+	case SCSI_CMD_INQUIRY:
+	case SCSI_CMD_READ_CAPACITY_10:
+	case SCSI_CMD_TEST_UNIT_READY:
+	case SCSI_CMD_MODE_SENSE_10:
+	case SCSI_CMD_MODE_SELECT_10:
+	case SCSI_CMD_PREVENT_MEDIUM_REMOVAL:
+	case SCSI_CMD_READ_TOC:
+	case SCSI_CMD_START_STOP_UNIT:
+	case SCSI_CMD_SYNCHRONIZE_CACHE_10:
+	case SCSI_CMD_REQUEST_SENSE:
+	default:
+		/* 
+		 * Use packet command 
+		 */
+		/* Features: DMA, OVL, DMADIR */
+#if defined(USE_DMA_FOR_ALL_PACKET_COMMAND)
+		if ( !(pReq->Cmd_Flag&CMD_FLAG_NON_DATA) )
+		{
+			pTaskFile->Features |= MV_BIT(0);
+		}
+#elif defined(USE_PIO_FOR_ALL_PACKET_COMMAND)
+		/* do nothing */
+#else
+		if ( pReq->Cmd_Flag&CMD_FLAG_DMA )
+			pTaskFile->Features |= MV_BIT(0);
+#endif
+		/* Byte count low and byte count high */
+		if ( pReq->Data_Transfer_Length>0xFFFF )
+		{
+			pTaskFile->LBA_Mid = 0xFF;
+			pTaskFile->LBA_High = 0xFF;
+		}
+		else
+		{
+			pTaskFile->LBA_Mid = (MV_U8)pReq->Data_Transfer_Length;
+			pTaskFile->LBA_High = (MV_U8)(pReq->Data_Transfer_Length>>8);
+		}
+
+		pTaskFile->Command = ATA_CMD_PACKET;
+
+		break;
+	}
+
+	/* 
+	 * Attention: Never return before this line if your return is MV_TRUE.
+	 * We need set the slave DEV bit here. 
+	 */
+	if ( pDevice->Is_Slave )		
+		pTaskFile->Device |= MV_BIT(4);
+
+	return MV_TRUE;
+}
+
diff --git a/drivers/scsi/thor/include/com_dbg.h b/drivers/scsi/thor/include/com_dbg.h
new file mode 100755
index 0000000..efcdef0
--- /dev/null
+++ b/drivers/scsi/thor/include/com_dbg.h
@@ -0,0 +1,165 @@
+#if !defined(COMMON_DEBUG_H)

+#define COMMON_DEBUG_H

+

+/* 

+ *	Marvell Debug Interface

+ * 

+ *	MACRO

+ *		MV_DEBUG is defined in debug version not in release version.

+ *	

+ *	Debug funtions:

+ *		MV_PRINT:	print string in release and debug build.

+ *		MV_DPRINT:	print string in debug build.

+ *		MV_TRACE:	print string including file name, line number in release and debug build.

+ *		MV_DTRACE:	print string including file name, line number in debug build.

+ *		MV_ASSERT:	assert in release and debug build.

+ *		MV_DASSERT: assert in debug build.

+ */

+

+#include "com_define.h"

+/*

+ *

+ * Debug funtions

+ *

+ */

+

+/* For both debug and release version */

+#if defined(SIMULATOR)

+#   include <assert.h>

+#   define MV_PRINT printf

+#   define MV_ASSERT assert

+#   define MV_TRACE(_x_)                                   \

+              do {	                                   \

+                 MV_PRINT("%s(%d) ", __FILE__, __LINE__);  \

+                 MV_PRINT _x_;                             \

+	      } while (0)

+#elif defined(_OS_WINDOWS)

+/* for VISTA */

+#   if ((_WIN32_WINNT >= 0x0600) && defined(MV_DEBUG))

+       ULONG _cdecl MV_PRINT(char* format, ...);

+#   else

+#      define MV_PRINT                      DbgPrint

+#   endif /* ((_WIN32_WINNT >= 0x0600) && defined(MV_DEBUG)) */

+

+#   if (defined(_CPU_IA_64B) || defined(_CPU_AMD_64B))

+#      if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)

+#         define NTAPI __stdcall

+#      else

+#         define NTAPI

+#      endif /* (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) */

+	

+       void NTAPI DbgBreakPoint(void);

+#      define MV_ASSERT(_condition_)    \

+                 do { if (!(_condition_)) DbgBreakPoint(); } while(0)

+#   else

+#      define MV_ASSERT(_condition_)    \

+                 do { if (!(_condition_)) {__asm int 3}; } while(0)

+#   endif /*  (defined(_CPU_IA_64B) || defined(_CPU_AMD_64B)) */

+

+#   define MV_TRACE(_x_)                                        \

+              do {                                              \

+                 MV_PRINT("%s(%d) ", __FILE__, __LINE__);       \

+                 MV_PRINT _x_;                                  \

+              } while (0)

+

+#elif defined(_OS_LINUX)

+#   define MV_PRINT(format, arg...)	printk("%s %d:" format, __FILE__, __LINE__, ## arg)

+#   define MV_ASSERT(_x_)  BUG_ON(!(_x_))

+

+#   define MV_TRACE(_x_)                                        \

+              do {                                              \

+                 MV_PRINT("%s(%d) ", __FILE__, __LINE__);       \

+                 MV_PRINT _x_;                                  \

+           } while(0)

+#elif defined(__QNXNTO__)

+#   define MV_PRINT      printk("%s: ", mv_full_name), printk

+#   define MV_ASSERT(_x_)                                       \

+              do {                                              \

+		 if (!(_x_))                                    \

+                    MV_PRINT("Assert at File %s: Line %d.\n",   \

+                             __FILE__, __LINE__);               \

+              } while (0)

+#   define MV_TRACE(_x_)                                        \

+              do {                                              \

+                 MV_PRINT("%s(%d) ", __FILE__, __LINE__);       \

+                 printk   _x_;                                  \

+           } while(0)

+#else /* OTHER OSes */

+#   define MV_PRINT(_x_)

+#   define MV_ASSERT(_condition_)

+#   define MV_TRACE(_x_)

+#endif /* _OS_WINDOWS */

+

+

+/* 

+ * Used with MV_DBG macro, see below .

+ * Should be useful for Win driver too, so it is placed here.

+ *

+ */

+#define DMSG_POKE        0x0001  /* flag controlling the dump_stack()  */

+#define DMSG_KERN        0x0002  /* kernel driver dbg msg */

+#define DMSG_SCSI        0x0004  /* SCSI Subsystem dbg msg */

+#define DMSG_CORE        0x0008  /* CORE dbg msg */

+#define DMSG_HBA         0x0010  /* HBA dbg msg */

+#define DMSG_RESER03     0x0020

+#define DMSG_FREQ        0x0040  /* msg that'll pop up 100+ times per sec */

+#define DMSG_IOCTL       0x0080  /* ioctl msg */ 

+#define DMSG_MSG         0x0100  /* plain msg, should be enabled all time */

+#define DMSG_SCSI_FREQ   0x0200  /* freq scsi dbg msg */

+#define DMSG_RAID        0x0400  /* raid dbg msg */

+#define DMSG_PROF        0x0800  /* profiling msg */

+#define DMSG_PROF_FREQ   0x1000  /* freq profiling msg */

+#define DMSG_RES     	 0x2000

+#define DMSG_SAS         0x4000  /* sas msg */

+#define DMSG_CORE_EH     0x8000  /* core error handling */

+/* For debug version only */

+#if defined(MV_DEBUG)

+#   ifdef _OS_LINUX

+       extern unsigned int mv_dbg_opts;

+#      define MV_DBG(x,...)                          \

+          do {                                       \

+	     if (unlikely(x&mv_dbg_opts)) {          \

+                MV_PRINT(__VA_ARGS__);               \

+             }                                       \

+          } while (0)

+

+#      define MV_POKE()                              \

+          do {                                       \

+		dump_stack();                        \

+          } while (0)

+

+#      define MV_DPRINT(x)                           \

+          do {                                       \

+	     if (unlikely(DMSG_CORE&mv_dbg_opts))    \

+	        MV_PRINT x;                          \

+          } while (0)

+#   else

+#      define MV_PRINT        printk

+#      define MV_DPRINT(x)	MV_PRINT x

+/* in case drivers for non-linux os go crazy */

+#      define MV_DBG(x)         do{}while(0)

+#      define MV_POKE()         

+#   endif /* _OS_LINUX */

+

+#   define MV_DASSERT	        MV_ASSERT

+#   define MV_DTRACE	        MV_DTRACE

+#else

+#   if defined(__QNXNTO__) || defined(_OS_LINUX)

+#      define MV_DBG(x,...)        do{}while(0)

+#   else

+#      define MV_DBG(x)            do{}while(0)

+#   endif /* __QNXNTO__ */

+//#   define MV_PRINT(x,...)

+#   define MV_POKE()  

+#   define MV_DPRINT(x)

+#   define MV_DASSERT(x)

+#   define MV_DTRACE(x)

+#endif /* MV_DEBUG */

+

+MV_BOOLEAN mvLogRegisterModule(MV_U8 moduleId, MV_U32 filterMask, char* name);

+MV_BOOLEAN mvLogSetModuleFilter(MV_U8 moduleId, MV_U32 filterMask);

+MV_U32 mvLogGetModuleFilter(MV_U8 moduleId);

+void mvLogMsg(MV_U8 moduleId, MV_U32 type, char* format, ...);

+

+#endif /* COMMON_DEBUG_H */

+

diff --git a/drivers/scsi/thor/include/com_list.c b/drivers/scsi/thor/include/com_list.c
new file mode 100755
index 0000000..a46fed1
--- /dev/null
+++ b/drivers/scsi/thor/include/com_list.c
@@ -0,0 +1,184 @@
+#include "com_define.h"

+#include "com_list.h"

+

+/*

+ * Insert a new entry between two known consecutive entries.

+ *

+ * This is only for internal list manipulation where we know

+ * the prev/next entries already!

+ */

+static MV_INLINE void __List_Add(List_Head *new_one,

+			      List_Head *prev,

+			      List_Head *next)

+{

+	next->prev = new_one;

+	new_one->next = next;

+	new_one->prev = prev;

+	prev->next = new_one;

+}

+

+/**

+ * List_Add - add a new entry

+ * @new_one: new entry to be added

+ * @head: list head to add it after

+ *

+ * Insert a new entry after the specified head.

+ * This is good for implementing stacks.

+ */

+static MV_INLINE void List_Add(List_Head *new_one, List_Head *head)

+{

+	__List_Add(new_one, head, head->next);

+}

+

+/**

+ * List_AddTail - add a new entry

+ * @new_one: new entry to be added

+ * @head: list head to add it before

+ *

+ * Insert a new entry before the specified head.

+ * This is useful for implementing queues.

+ */

+static MV_INLINE void List_AddTail(List_Head *new_one, List_Head *head)

+{

+	__List_Add(new_one, head->prev, head);

+}

+

+/*

+ * Delete a list entry by making the prev/next entries

+ * point to each other.

+ *

+ * This is only for internal list manipulation where we know

+ * the prev/next entries already!

+ */

+static MV_INLINE void __List_Del(List_Head * prev, List_Head * next)

+{

+	next->prev = prev;

+	prev->next = next;

+}

+

+/**

+ * List_Del - deletes entry from list.

+ * @entry: the element to delete from the list.

+ * Note: List_Empty on entry does not return true after this, the entry is

+ * in an undefined state.

+ */

+static MV_INLINE void List_Del(List_Head *entry)

+{

+	__List_Del(entry->prev, entry->next);

+	entry->next = NULL;

+	entry->prev = NULL;

+}

+

+/**

+ * List_DelInit - deletes entry from list and reinitialize it.

+ * @entry: the element to delete from the list.

+ */

+static MV_INLINE void List_DelInit(List_Head *entry)

+{

+	__List_Del(entry->prev, entry->next);

+	MV_LIST_HEAD_INIT(entry);

+}

+

+/**

+ * List_Move - delete from one list and add as another's head

+ * @list: the entry to move

+ * @head: the head that will precede our entry

+ */

+static MV_INLINE void List_Move(List_Head *list, List_Head *head)

+{

+        __List_Del(list->prev, list->next);

+        List_Add(list, head);

+}

+

+/**

+ * List_MoveTail - delete from one list and add as another's tail

+ * @list: the entry to move

+ * @head: the head that will follow our entry

+ */

+static MV_INLINE void List_MoveTail(List_Head *list,

+				  List_Head *head)

+{

+        __List_Del(list->prev, list->next);

+        List_AddTail(list, head);

+}

+

+/**

+ * List_Empty - tests whether a list is empty

+ * @head: the list to test.

+ */

+static MV_INLINE int List_Empty(const List_Head *head)

+{

+	return head->next == head;

+}

+

+static MV_INLINE int List_GetCount(const List_Head *head)

+{

+	int i=0;

+	List_Head *pos;

+	LIST_FOR_EACH(pos, head) {

+		i++;

+	}

+	return i;

+}

+

+static MV_INLINE List_Head* List_GetFirst(List_Head *head)

+{

+	List_Head * one = NULL;

+	if ( List_Empty(head) ) return NULL;

+

+	one = head->next;

+	List_Del(one);

+	return one;

+}

+

+static MV_INLINE List_Head* List_GetLast(List_Head *head)

+{

+	List_Head * one = NULL;

+	if ( List_Empty(head) ) return NULL;

+

+	one = head->prev;

+	List_Del(one);

+	return one;

+}

+

+static MV_INLINE void __List_Splice(List_Head *list,

+				 List_Head *head)

+{

+	List_Head *first = list->next;

+	List_Head *last = list->prev;

+	List_Head *at = head->next;

+

+	first->prev = head;

+	head->next = first;

+

+	last->next = at;

+	at->prev = last;

+}

+

+/**

+ * List_Splice - join two lists

+ * @list: the new list to add.

+ * @head: the place to add it in the first list.

+ */

+static MV_INLINE void List_Splice(List_Head *list, List_Head *head)

+{

+	if (!List_Empty(list))

+		__List_Splice(list, head);

+}

+

+/**

+ * List_Splice_Init - join two lists and reinitialise the emptied list.

+ * @list: the new list to add.

+ * @head: the place to add it in the first list.

+ *

+ * The list at @list is reinitialised

+ */

+static MV_INLINE void List_Splice_Init(List_Head *list,

+				    List_Head *head)

+{

+	if (!List_Empty(list)) {

+		__List_Splice(list, head);

+		MV_LIST_HEAD_INIT(list);

+	}

+}

+

diff --git a/drivers/scsi/thor/include/com_list.h b/drivers/scsi/thor/include/com_list.h
new file mode 100755
index 0000000..cbe074f
--- /dev/null
+++ b/drivers/scsi/thor/include/com_list.h
@@ -0,0 +1,193 @@
+#if !defined(COMMON_LIST_H)

+#define COMMON_LIST_H

+

+#include "com_define.h"

+

+/*

+ * Simple doubly linked list implementation.

+ *

+ * Some of the internal functions ("__xxx") are useful when

+ * manipulating whole lists rather than single entries, as

+ * sometimes we already know the next/prev entries and we can

+ * generate better code by using them directly rather than

+ * using the generic single-entry routines.

+ */

+

+#ifdef NEW_LINUX_DRIVER

+/* use native code */

+#define List_Head           struct list_head

+#define PList_Head          struct list_head *

+

+#define MV_LIST_HEAD        LIST_HEAD

+#define MV_INIT_LIST_HEAD   LIST_HEAD_INIT

+#define MV_LIST_HEAD_INIT   INIT_LIST_HEAD

+

+//#define List_Add            list_add

+//#define List_AddTail        list_add_tail

+//#define List_Del            list_del

+#define List_DelInit        list_del_init

+#define List_Move           list_move

+#define List_MoveTail       list_move_tail

+#define List_Empty          list_empty

+

+#define CONTAINER_OF        container_of

+#define LIST_ENTRY          list_entry

+#define LIST_FOR_EACH       list_for_each

+#define LIST_FOR_EACH_PREV  list_for_each_prev

+#define LIST_FOR_EACH_ENTRY list_for_each_entry

+#define LIST_FOR_EACH_ENTRY_PREV list_for_each_entry_prev

+#define LIST_FOR_EACH_ENTRY_TYPE(ptr, list_ptr, type, entry) \

+           list_for_each_entry(ptr, list_ptr, entry)

+

+#define List_Splice         list_splice

+#define List_Splice_Init    list_splice_init

+#define __List_Del          __list_del  /* internal function, use with care */

+#if 0

+

+static MV_INLINE void List_Del(List_Head *entry)

+{

+#ifdef SUPPORT_REQUEST_TIMER

+	if((entry->prev) || (entry->next))

+#endif

+	__List_Del(entry->prev, entry->next);

+	entry->next = NULL;

+	entry->prev = NULL;

+}

+

+

+static inline struct list_head *List_GetFirst(struct list_head *head)

+{

+        struct list_head * one = NULL;

+        if (list_empty(head))

+		return NULL;

+

+        one = head->next;

+        list_del(one);

+        return one;

+}

+

+static inline struct list_head *List_GetLast(struct list_head *head)

+{

+        struct list_head * one = NULL;

+        if (list_empty(head))

+		return NULL;

+

+        one = head->prev;

+        list_del(one);

+        return one;

+}

+#endif

+

+#else /* _OS_LINUX */

+/*

+ *

+ *

+ * Data Structure

+ *

+ *

+ */

+typedef struct _List_Head {

+	struct _List_Head *prev, *next;

+} List_Head, * PList_Head;

+

+

+/*

+ *

+ *

+ * Exposed Functions

+ *

+ *

+ */

+ 

+#define MV_LIST_HEAD(name) \

+	List_Head name = { &(name), &(name) }

+

+#define MV_LIST_HEAD_INIT(ptr) do { \

+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \

+} while (0)

+

+static MV_INLINE void List_Add(List_Head *new_one, List_Head *head);

+

+static MV_INLINE void List_AddTail(List_Head *new_one, List_Head *head);

+

+static MV_INLINE void List_Del(List_Head *entry);

+

+static MV_INLINE void List_DelInit(List_Head *entry);

+

+static MV_INLINE void List_Move(List_Head *list, List_Head *head);

+

+static MV_INLINE void List_MoveTail(List_Head *list,

+				  List_Head *head);

+

+static MV_INLINE int List_Empty(const List_Head *head);

+

+

+#define CONTAINER_OF(ptr, type, member) 			\

+        ( (type *)( (char *)(ptr) - OFFSET_OF(type,member) ) )

+

+#define LIST_ENTRY(ptr, type, member) \

+	CONTAINER_OF(ptr, type, member)

+

+/**

+ * LIST_FOR_EACH	-	iterate over a list

+ * @pos:	the &List_Head to use as a loop counter.

+ * @head:	the head for your list.

+ */

+#define LIST_FOR_EACH(pos, head) \

+	for (pos = (head)->next; pos != (head); pos = pos->next)

+

+/**

+ * LIST_FOR_EACH_PREV	-	iterate over a list backwards

+ * @pos:	the &List_Head to use as a loop counter.

+ * @head:	the head for your list.

+ */

+#define LIST_FOR_EACH_PREV(pos, head) \

+	for (pos = (head)->prev; pos != (head); pos = pos->prev)

+

+/**

+ * LIST_FOR_EACH_ENTRY	-	iterate over list of given type

+ * @pos:	the type * to use as a loop counter.

+ * @head:	the head for your list.

+ * @member:	the name of the list_struct within the struct.

+ */

+#define LIST_FOR_EACH_ENTRY(pos, head, member)				\

+	for (pos = LIST_ENTRY((head)->next, typeof(*pos), member);	\

+	     &pos->member != (head); 	\

+	     pos = LIST_ENTRY(pos->member.next, typeof(*pos), member))

+

+/**

+ * LIST_FOR_EACH_ENTRY_TYPE	-	iterate over list of given type

+ * @pos:	the type * to use as a loop counter.

+ * @head:	the head for your list.

+ * @member:	the name of the list_struct within the struct.

+ * @type:	the type of the struct this is embedded in.

+*/

+#define LIST_FOR_EACH_ENTRY_TYPE(pos, head, type, member)       \

+	for (pos = LIST_ENTRY((head)->next, type, member);	\

+	     &pos->member != (head); 	                        \

+	     pos = LIST_ENTRY(pos->member.next, type, member))

+

+/**

+ * LIST_FOR_EACH_ENTRY_PREV - iterate backwards over list of given type.

+ * @pos:	the type * to use as a loop counter.

+ * @head:	the head for your list.

+ * @member:	the name of the list_struct within the struct.

+ */

+#define LIST_FOR_EACH_ENTRY_PREV(pos, head, member)			\

+	for (pos = LIST_ENTRY((head)->prev, typeof(*pos), member);	\

+	     &pos->member != (head); 	\

+	     pos = LIST_ENTRY(pos->member.prev, typeof(*pos), member))

+

+#ifndef _OS_BIOS

+#include "com_list.c"

+#endif

+

+#endif /* _OS_LINUX */

+

+#define List_GetFirstEntry(head, type, member)	\

+	LIST_ENTRY(List_GetFirst(head), type, member)

+

+#define List_GetLastEntry(head, type, member)	\

+	LIST_ENTRY(List_GetLast(head), type, member)

+

+#endif /* COMMON_LIST_H */

diff --git a/drivers/scsi/thor/include/com_mod_mgmt.h b/drivers/scsi/thor/include/com_mod_mgmt.h
new file mode 100755
index 0000000..0752ef9
--- /dev/null
+++ b/drivers/scsi/thor/include/com_mod_mgmt.h
@@ -0,0 +1,134 @@
+#ifndef __MV_MODULE_MGMT__

+#define __MV_MODULE_MGMT__

+

+#include "com_define.h"

+#include "com_type.h"

+#include "com_util.h"

+

+enum {

+	/* module status (module_descriptor) */

+	MV_MOD_VOID   = 0,

+	MV_MOD_UNINIT,

+	MV_MOD_REGISTERED,  /* module ops pointer registered */

+	MV_MOD_INITED,      /* resource assigned */ 

+	MV_MOD_FUNCTIONAL,

+	MV_MOD_STARTED,

+	MV_MOD_DEINIT,      /* extension released, be gone soon */

+	MV_MOD_GONE,

+};

+

+

+/* adapter descriptor */

+struct mv_adp_desc {

+	struct list_head  hba_entry;

+	struct list_head  online_module_list;

+

+	spinlock_t        lock;

+	spinlock_t        global_lock;

+

+	/* adapter information */

+	MV_U8             Adapter_Bus_Number;

+	MV_U8             Adapter_Device_Number;

+	MV_U8             Revision_Id;

+	MV_U8             id;             /* multi-hba support, start from 0 */

+	MV_U8             pad0;

+	MV_U8             running_mod_num;/* number of up & running modules */

+

+

+	MV_U16            vendor;

+	MV_U16            device;

+	MV_U16            subsystem_vendor;

+	MV_U16            subsystem_device;

+#ifdef ODIN_DRIVER

+	MV_U8				RunAsNonRAID;

+#endif

+	/* System resource */

+	MV_PVOID          Base_Address[ROUNDING(MAX_BASE_ADDRESS, 2)];

+

+	MV_U32            max_io;

+

+#ifdef _OS_LINUX 

+	dev_t             dev_no;

+

+	struct pci_dev    *dev;

+	MV_PVOID          extension;      /* hba_ext */

+#endif /* _OS_LINUX */

+};

+

+struct mv_mod_desc;

+

+

+struct mv_mod_res {

+	struct list_head       res_entry;

+	MV_PHYSICAL_ADDR       bus_addr;

+	MV_PVOID               virt_addr;

+	

+	MV_U32                 size;

+	

+	MV_U16                 type;          /* enum Resource_Type */

+	MV_U16                 align;

+};

+

+typedef struct _Module_Interface

+{

+	MV_U8      module_id;

+	MV_U32     (*get_res_desc)(enum Resource_Type type, MV_U16 maxIo);

+	MV_VOID    (*module_initialize)(MV_PVOID extension,

+					MV_U32   size,

+					MV_U16   max_io);

+	MV_VOID    (*module_start)(MV_PVOID extension);

+	MV_VOID    (*module_stop)(MV_PVOID extension);

+	MV_VOID    (*module_notification)(MV_PVOID extension, 

+					  enum Module_Event event, 

+					  struct mod_notif_param *param);

+	MV_VOID    (*module_sendrequest)(MV_PVOID extension, 

+					 PMV_Request pReq);

+	MV_VOID    (*module_reset)(MV_PVOID extension);

+	MV_VOID    (*module_monitor)(MV_PVOID extension);

+	MV_BOOLEAN (*module_service_isr)(MV_PVOID extension);

+#ifdef RAID_DRIVER

+	MV_VOID    (*module_send_xor_request)(MV_PVOID This, 

+					      PMV_XOR_Request pXORReq);

+#endif /* RAID_DRIVER */

+} Module_Interface, *PModule_Interface;

+

+#define mv_module_ops _Module_Interface

+

+#define mv_set_mod_ops(_ops, _id, _get_res_desc, _init, _start,            \

+		       _stop, _send, _reset, _mon, _send_eh, _isr, _xor)   \

+           {                                                               \

+		   _ops->id                      = id;                     \

+		   _ops->get_res_desc            = _get_res_desc;          \

+		   _ops->module_initialize       = _init;                  \

+		   _ops->module_start            = _start;                 \

+		   _ops->module_stop             = _stop;                  \

+		   _ops->module_sendrequest      = _send;                  \

+		   _ops->module_reset            = _reset;                 \

+		   _ops->module_monitor          = _mon;                   \

+		   _ops->module_send_eh_request  = _send_eh;               \

+		   _ops->module_service_isr      = _isr;                   \

+		   _ops->module_send_xor_request = _xor;                   \

+	   }

+

+

+/* module descriptor */

+struct mv_mod_desc {

+	struct list_head           mod_entry;      /* kept in a list */

+	

+	struct mv_mod_desc         *parent;

+	struct mv_mod_desc         *child;

+

+	MV_U32                     extension_size;

+	MV_U8                      status;

+	MV_U8                      ref_count;

+	MV_U8                      module_id;

+	MV_U8                      res_entry;

+

+	MV_PVOID                   extension;      /* module extention */

+	struct mv_module_ops       *ops;           /* interface operations */

+

+	struct mv_adp_desc         *hba_desc;

+	struct list_head           res_list;

+};

+

+#endif /* __MV_MODULE_MGMT__ */

diff --git a/drivers/scsi/thor/include/com_nvram.h b/drivers/scsi/thor/include/com_nvram.h
new file mode 100755
index 0000000..2e7b039
--- /dev/null
+++ b/drivers/scsi/thor/include/com_nvram.h
@@ -0,0 +1,108 @@
+typedef union {

+    struct {

+        MV_U32 low;

+        MV_U32 high;

+    } parts;

+    MV_U8       b[8];

+    MV_U16      w[4];

+    MV_U32      d[2];        

+} SAS_ADDR, *PSAS_ADDR;

+

+typedef struct _PHY_TUNING {

+	MV_U8	AMP:4;						  /* 4 bits,  amplitude  */

+	MV_U8	Pre_Emphasis:3;				  /* 3 bits,  pre-emphasis */

+	MV_U8	Reserved_1bit_1:1;				  /* 1 bit,   reserved space */

+    MV_U8	Drive_En:6;						/* 6 bits,	drive enable */

+	MV_U8	Pre_Half_En:1;					/* 1 bit,	Half Pre-emphasis Enable*/

+	MV_U8	Reserved_1bit_2:1;				/* 1 bit, 	reserved space */

+    MV_U8	Reserved[2];					/* 2 bytes, reserved space */

+} PHY_TUNING, *PPHY_TUNING;

+

+

+/* HBA_FLAG_XX */

+#define HBA_FLAG_INT13_ENABLE				MV_BIT(0)	//int 13h enable/disable

+#define HBA_FLAG_SILENT_MODE_ENABLE			MV_BIT(1)	//silent mode enable/disable

+#define HBA_FLAG_ERROR_STOP					MV_BIT(2)	//if error then stop

+

+#define NVRAM_DATA_MAJOR_VERSION		0

+#define NVRAM_DATA_MINOR_VERSION		1

+

+/* 

+	HBA_Info_Page is saved in Flash/NVRAM, total 256 bytes.

+	The data area is valid only Signature="MRVL".

+	If any member fills with 0xFF, the member is invalid.

+*/

+typedef struct _HBA_Info_Page{

+	// Dword 0

+	MV_U8     	Signature[4];                 	/* 4 bytes, structure signature,should be "MRVL" at first initial */

+

+	// Dword 1

+	MV_U8     	MinorRev;                 		/* 2 bytes, NVRAM data structure version */

+	MV_U8		MajorRev;

+	MV_U16    	Next_Page;					  	/* 2 bytes, For future data structure expansion, 0 is for NULL pointer and current page is the last page. */

+

+	// Dword 2

+	MV_U8     	Major;                   		/* 1 byte,  BIOS major version */

+	MV_U8     	Minor;                  		/* 1 byte,	BIOS minor version */

+	MV_U8     	OEM_Num;                     	/* 1 byte,  OEM number */

+	MV_U8     	Build_Num;                    	/* 1 byte,  Build number */

+

+	// Dword 3

+	MV_U8     	Page_Code;					  	/* 1 byte,  eg. 0 for the 1st page  */

+	MV_U8     	Max_PHY_Num;				  	/* 1 byte,   maximum PHY number */

+	MV_U8		Reserved2[2];

+

+	// Dword 4

+	MV_U32     	HBA_Flag;                     	/* 

+													4 bytes, should be 0x0000,0000 at first initial

+	                                                                HBA flag:  refers to HBA_FLAG_XX

+	                                                                bit 0   --- HBA_FLAG_BBS_ENABLE

+	                                                                bit 1   --- HBA_FLAG_SILENT_MODE_ENABLE

+	                                                                bit 2   --- HBA_FLAG_ERROR_STOP

+	                                                                bit 3   --- HBA_FLAG_INT13_ENABLE

+	                                                                bit 4   --- HBA_FLAG_ERROR_STOP

+	                                                                bit 5   --- HBA_FLAG_ERROR_PASS

+	                                                                bit 6   --- HBA_FLAG_SILENT_MODE_ENABLE

+	                                           */

+	// Dword 5	                                              

+	MV_U32     	Boot_Device;					/* 4 bytes, select boot device */

+												/* for ata device, it is CRC of the serial number + model number. */

+												/* for sas device, it is CRC of sas address */

+												/* for VD, it is VD GUI */

+

+	// Dword 6-8											  

+	MV_U32     	Reserved3[3];				  	/* 12 bytes, reserved	*/

+

+	// Dword 9-13

+	MV_U8     	Serial_Num[20];				  	/* 20 bytes, controller serial number */

+

+	// Dword 14-29

+	SAS_ADDR	SAS_Address[8];               /* 64 bytes, SAS address for each port */

+

+	// Dword 30-43

+	MV_U8     	Reserved4[56];                  /* 56 bytes, reserve space for future,initial as 0xFF */   

+

+	// Dword 44-45

+	MV_U8     	PHY_Rate[8];                  	/* 8 bytes,  0:  1.5G, 1: 3.0G, should be 0x01 at first initial */

+

+	// Dword 46-53

+	PHY_TUNING    PHY_Tuning[8];				/* 32 bytes, PHY tuning parameters for each PHY*/

+

+	// Dword 54-62

+	MV_U32     	Reserved5[9];                 	/* 9 dword, reserve space for future,initial as 0xFF */

+

+	// Dword 63

+	MV_U8     	Reserved6[3];                 	/* 3 bytes, reserve space for future,initial as 0xFF */

+	MV_U8     	Check_Sum;                    	/* 1 byte,   checksum for this structure,Satisfy sum of every 8-bit value of this structure */

+}HBA_Info_Page, *pHBA_Info_Page;			/* total 256 bytes */

+

+#define FLASH_PARAM_SIZE 	(sizeof(HBA_Info_Page))

+#define ODIN_FLASH_SIZE		0x40000  				//.256k bytes

+#define PARAM_OFFSET		ODIN_FLASH_SIZE - 0x100 //.255k bytes

+

+MV_U8 mvui_init_param(MV_PVOID This, pHBA_Info_Page pHBAInfo);//get initial data from flash

+

+MV_U8	mvCaculateChecksum(MV_PU8	Address, MV_U32 Size);

+MV_U8	mvVerifyChecksum(MV_PU8	Address, MV_U32 Size);

+

+

diff --git a/drivers/scsi/thor/include/com_scsi.h b/drivers/scsi/thor/include/com_scsi.h
new file mode 100755
index 0000000..41ef9b2
--- /dev/null
+++ b/drivers/scsi/thor/include/com_scsi.h
@@ -0,0 +1,298 @@
+#ifndef __MV_COM_SCSI_H__

+#define __MV_COM_SCSI_H__

+

+/*

+ * SCSI command

+ */

+#define SCSI_CMD_INQUIRY                        0x12

+#define SCSI_CMD_START_STOP_UNIT                0x1B

+#define SCSI_CMD_TEST_UNIT_READY                0x00

+#define SCSI_CMD_RESERVE_6                      0x16

+#define SCSI_CMD_RELEASE_6                      0x17

+

+#define SCSI_CMD_READ_6                         0x08

+#define SCSI_CMD_READ_10                        0x28

+#define SCSI_CMD_READ_12                        0xA8

+#define SCSI_CMD_READ_16                        0x88

+#define SCSI_CMD_READ_LONG_10				0x3E

+#define  SCSI_CMD_READ_DEFECT_DATA_10        0x37

+

+#define SCSI_CMD_WRITE_6                        0x0A

+#define SCSI_CMD_WRITE_10                       0x2A

+#define SCSI_CMD_WRITE_12                       0xAA

+#define SCSI_CMD_WRITE_16                       0x8A

+#define SCSI_CMD_WRITE_LONG_10					0x3F

+

+#define SCSI_CMD_READ_CAPACITY_10               0x25

+#define SCSI_CMD_READ_CAPACITY_16               0x9E    /* 9Eh/10h */

+/* values for service action in */

+#define SCSI_CMD_SAI_READ_CAPACITY_16  			0x10

+

+#define SCSI_CMD_VERIFY_10                      0x2F

+#define SCSI_CMD_VERIFY_12                      0xAF

+#define SCSI_CMD_VERIFY_16                      0x8F

+

+#define SCSI_CMD_REQUEST_SENSE                  0x03

+#define SCSI_CMD_MODE_SENSE_6                   0x1A

+#define SCSI_CMD_MODE_SENSE_10                  0x5A

+#define SCSI_CMD_MODE_SELECT_6                  0x15

+#define SCSI_CMD_MODE_SELECT_10                 0x55

+

+#define SCSI_CMD_LOG_SELECT                     0x4C

+#define SCSI_CMD_LOG_SENSE                      0x4D

+

+#define SCSI_CMD_WRITE_VERIFY_10                0x2E

+#define SCSI_CMD_WRITE_VERIFY_12                0xAE

+#define SCSI_CMD_WRITE_VERIFY_16                0x8E

+#define SCSI_CMD_SYNCHRONIZE_CACHE_10           0x35

+#define SCSI_CMD_SYNCHRONIZE_CACHE_16			0x91

+

+#define SCSI_CMD_WRITE_SAME_10                  0x41

+#define SCSI_CMD_WRITE_SAME_16                  0x93

+

+#define SCSI_CMD_XDWRITE_10                     0x50

+#define SCSI_CMD_XPWRITE_10                     0x51

+#define SCSI_CMD_XDREAD_10                      0x52

+#define SCSI_CMD_XDWRITEREAD_10                 0x53

+

+#define SCSI_CMD_FORMAT_UNIT                    0x04

+

+#define SCSI_CMD_RCV_DIAG_RSLT                  0x1C

+#define SCSI_CMD_SND_DIAG                       0x1D

+

+/* MMC */

+#define SCSI_CMD_REPORT_LUN                     0xA0

+#define SCSI_CMD_PREVENT_MEDIUM_REMOVAL         0x1E

+#define SCSI_CMD_READ_SUB_CHANNEL               0x42

+#define SCSI_CMD_READ_TOC                       0x43

+#define SCSI_CMD_READ_DISC_STRUCTURE            0xAD

+#define SCSI_CMD_READ_CD                        0xBE

+#define SCSI_CMD_GET_EVENT_STATUS_NOTIFICATION  0x4A

+#define SCSI_CMD_BLANK                          0xA1

+#define SCSI_CMD_READ_DISC_INFO                 0x51

+

+#ifndef SMART_CMD

+#define SMART_CMD                               0xb0

+#endif /* SMART_CMD */

+

+#ifdef SUPPORT_ATA_POWER_MANAGEMENT

+#define ATA_CMD_SLEEP               0xe6

+#define ATA_CMD_CHK_POWER           0xe5

+#define ATA_CMD_IDLE                0xe3

+#define ATA_CMD_STANDBY             0xe2

+#define ATA_CMD_IDLEIMMEDIATE       0xe1

+#define ATA_CMD_STANDBYNOW1         0xe0

+#define ATA_CMD_DEV_RESET           0x08

+#endif

+

+#define SCSI_IS_READ(cmd)                       \

+           (((cmd) == SCSI_CMD_READ_6) ||       \

+	    ((cmd) == SCSI_CMD_READ_10)  ||     \

+            ((cmd) == SCSI_CMD_READ_12)  ||     \

+	    ((cmd) == SCSI_CMD_READ_16))

+

+#define SCSI_IS_WRITE(cmd)                      \

+           (((cmd) == SCSI_CMD_WRITE_6)  ||     \

+	    ((cmd) == SCSI_CMD_WRITE_10) ||     \

+	    ((cmd) == SCSI_CMD_WRITE_12) ||     \

+	    ((cmd) == SCSI_CMD_WRITE_16))

+

+#define SCSI_IS_MODE_SENSE(cmd)                 \

+           (((cmd) == SCSI_CMD_MODE_SENSE_6) || \

+	    ((cmd) == SCSI_CMD_MODE_SENSE_10))

+

+#define SCSI_IS_REQUEST_SENSE(cmd)              \

+           (((cmd) == SCSI_CMD_REQUEST_SENSE))

+

+#define SCSI_IS_VERIFY(cmd)                     \

+           (((cmd) == SCSI_CMD_VERIFY_10) ||    \

+	    ((cmd) == SCSI_CMD_VERIFY_16))

+

+#define SCSI_CMD_MARVELL_SPECIFIC               0xE1

+#   define CDB_CORE_MODULE                      0x1

+#      define CDB_CORE_SOFT_RESET_1				0x1

+#      define CDB_CORE_SOFT_RESET_0				0x2

+#      define CDB_CORE_IDENTIFY                 0x3

+#      define CDB_CORE_SET_UDMA_MODE            0x4

+#      define CDB_CORE_SET_PIO_MODE             0x5

+#      define CDB_CORE_ENABLE_WRITE_CACHE       0x6

+#      define CDB_CORE_DISABLE_WRITE_CACHE      0x7

+#      define CDB_CORE_ENABLE_SMART             0x8

+#      define CDB_CORE_DISABLE_SMART            0x9

+#      define CDB_CORE_SMART_RETURN_STATUS      0xA

+#      define CDB_CORE_SHUTDOWN                 0xB

+#      define CDB_CORE_ENABLE_READ_AHEAD        0xC

+#      define CDB_CORE_DISABLE_READ_AHEAD       0xD

+#      define CDB_CORE_READ_LOG_EXT             0xE

+#      define CDB_CORE_TASK_MGMT                0xF

+#      define CDB_CORE_SMP                      0x10

+#      define CDB_CORE_PM_READ_REG				0x11

+#      define CDB_CORE_PM_WRITE_REG				0x12

+#	   define CDB_CORE_RESET_DEVICE				0x13

+#	   define CDB_CORE_RESET_PORT				0x14

+#      define CDB_CORE_OS_SMART_CMD				0x15

+

+#      define CDB_CORE_ATA_SLEEP                                0x16

+#      define CDB_CORE_ATA_IDLE                                 0x17

+#      define CDB_CORE_ATA_STANDBY                              0x18

+#      define CDB_CORE_ATA_IDLE_IMMEDIATE                       0x19

+#      define CDB_CORE_ATA_STANDBY_IMMEDIATE                    0x1A

+#      define CDB_CORE_ATA_CHECK_POWER_MODE                     0x1B

+

+

+#      define    CDB_CORE_ATA_IDENTIFY_DEVICE   0x1C

+#      define    CDB_CORE_ATA_IDENTIFY_PACKET_DEVICE    0x1D

+#      define   CDB_CORE_ATA_SMART_READ_VALUES     0x1E

+#      define   CDB_CORE_ATA_SMART_READ_THRESHOLDS     0x1F

+#      define   CDB_CORE_ATA_SMART_READ_LOG_SECTOR     0x20

+#      define   CDB_CORE_ATA_SMART_WRITE_LOG_SECTOR      0x21

+#      define   CDB_CORE_ATA_SMART_AUTO_OFFLINE    0x22

+#      define   CDB_CORE_ATA_SMART_AUTOSAVE          0x23

+#      define   CDB_CORE_ATA_SMART_IMMEDIATE_OFFLINE    0x24

+#      define   CDB_CORE_ATA_IDENTIFY                 0x25

+

+

+#      define SMP_CDB_USE_ADDRESS               0x01

+

+#define SCSI_IS_INTERNAL(cmd)        ((cmd) == SCSI_CMD_MARVELL_SPECIFIC)

+

+#ifdef SIMULATOR

+#   define SCSI_CMD_READ_SCATTER				0xEE

+#   define SCSI_CMD_WRITE_SCATTER				0xEF

+#endif	// SIMULATOR

+

+/*

+ * SCSI status

+ */

+#define SCSI_STATUS_GOOD                        0x00

+#define SCSI_STATUS_CHECK_CONDITION             0x02

+#define SCSI_STATUS_CONDITION_MET               0x04

+#define SCSI_STATUS_BUSY                        0x08

+#define SCSI_STATUS_INTERMEDIATE                0x10

+#define SCSI_STATUS_INTERMEDIATE_MET            0x14

+#define SCSI_STATUS_RESERVATION_CONFLICT        0x18

+#define SCSI_STATUS_FULL                        0x28

+#define SCSI_STATUS_ACA_ACTIVE                  0x30

+#define SCSI_STATUS_ABORTED                     0x40

+

+/*

+ * SCSI sense key

+ */

+#define SCSI_SK_NO_SENSE                        0x00

+#define SCSI_SK_RECOVERED_ERROR                 0x01

+#define SCSI_SK_NOT_READY                       0x02

+#define SCSI_SK_MEDIUM_ERROR                    0x03

+#define SCSI_SK_HARDWARE_ERROR                  0x04

+#define SCSI_SK_ILLEGAL_REQUEST                 0x05

+#define SCSI_SK_UNIT_ATTENTION                  0x06

+#define SCSI_SK_DATA_PROTECT                    0x07 

+#define SCSI_SK_BLANK_CHECK                     0x08

+#define SCSI_SK_VENDOR_SPECIFIC                 0x09

+#define SCSI_SK_COPY_ABORTED                    0x0A

+#define SCSI_SK_ABORTED_COMMAND                 0x0B

+#define SCSI_SK_VOLUME_OVERFLOW                 0x0D

+#define SCSI_SK_MISCOMPARE                      0x0E

+#ifdef _XOR_DMA

+#define SCSI_SK_DMA					0x0F

+#endif

+

+/*

+ * SCSI additional sense code

+ */

+#define SCSI_ASC_NO_ASC                         0x00

+#define SCSI_ASC_LUN_NOT_READY                  0x04

+#define SCSI_ASC_ECC_ERROR                      0x10

+#define SCSI_ASC_ID_ADDR_MARK_NOT_FOUND         0x12

+#define SCSI_ASC_INVALID_OPCODE                 0x20

+#define SCSI_ASC_LBA_OUT_OF_RANGE               0x21

+#define SCSI_ASC_INVALID_FEILD_IN_CDB           0x24

+#define SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED     0x25

+#define SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORT  0x39

+#define SCSI_ASC_LOGICAL_UNIT_NOT_RESP_TO_SEL	0x05

+#define SCSI_ASC_INVALID_FIELD_IN_PARAMETER     0x26

+#define SCSI_ASC_INTERNAL_TARGET_FAILURE        0x44

+#define SCSI_ASC_FAILURE_PREDICTION_THRESHOLD_EXCEEDED	0x5D

+

+#ifdef _OS_LINUX	/* below is defined in Windows DDK scsi.h */

+#define SCSI_ADSENSE_NO_SENSE  0x98    

+#define SCSI_ADSENSE_INVALID_CDB 0x99  

+#endif

+

+/*

+ * SCSI additional sense code qualifier

+ */

+#define SCSI_ASCQ_NO_ASCQ                       0x00

+#define SCSI_ASCQ_INTERVENTION_REQUIRED         0x03

+#define SCSI_ASCQ_MAINTENANCE_IN_PROGRESS       0x80

+#define SCSI_ASCQ_HIF_GENERAL_HD_FAILURE		0x10

+

+/* SCSI command CDB helper functions. */

+#define SCSI_CDB10_GET_LBA(cdb)                  \

+           ((MV_U32) (((MV_U32) cdb[2] << 24) |  \

+		      ((MV_U32) cdb[3] << 16) |  \

+		      ((MV_U32) cdb[4] << 8)  |  \

+		      (MV_U32) cdb[5]))

+

+#define SCSI_CDB10_SET_LBA(cdb, lba)             \

+           {                                     \

+              cdb[2] = (MV_U8)(lba >> 24);       \

+              cdb[3] = (MV_U8)(lba >> 16);       \

+              cdb[4] = (MV_U8)(lba >> 8);        \

+              cdb[5] = (MV_U8)lba;               \

+           }

+#define SCSI_CDB10_GET_SECTOR(cdb)    ((cdb[7] << 8) | cdb[8])

+

+#define SCSI_CDB10_SET_SECTOR(cdb, sector)      \

+           {                                    \

+              cdb[7] = (MV_U8)(sector >> 8);    \

+              cdb[8] = (MV_U8)sector;           \

+           }

+

+#define MV_SCSI_RESPONSE_CODE                   0x70

+#define MV_SCSI_DIRECT_ACCESS_DEVICE            0x00

+

+typedef struct _MV_Sense_Data

+{

+	MV_U8 ErrorCode:7;

+	MV_U8 Valid:1;

+	MV_U8 SegmentNumber;

+	MV_U8 SenseKey:4;

+	MV_U8 Reserved:1;

+	MV_U8 IncorrectLength:1;

+	MV_U8 EndOfMedia:1;

+	MV_U8 FileMark:1;

+	MV_U8 Information[4];

+	MV_U8 AdditionalSenseLength;

+	MV_U8 CommandSpecificInformation[4];

+	MV_U8 AdditionalSenseCode;

+	MV_U8 AdditionalSenseCodeQualifier;

+	MV_U8 FieldReplaceableUnitCode;

+	MV_U8 SenseKeySpecific[3];

+}MV_Sense_Data, *PMV_Sense_Data;

+

+MV_VOID MV_SetSenseData(

+	IN PMV_Sense_Data pSense,

+	IN MV_U8 SenseKey,

+	IN MV_U8 AdditionalSenseCode,

+	IN MV_U8 ASCQ

+	);

+

+/* Virtual Device Inquiry Related */

+#define VIRTUALD_INQUIRY_DATA_SIZE		36

+#define VPD_PAGE0_VIRTUALD_SIZE			7

+#define VPD_PAGE80_VIRTUALD_SIZE		12

+#define VPD_PAGE83_VIRTUALD_SIZE		24

+

+#ifndef SUPPORT_VIRTUAL_DEVICE

+extern MV_U8 BASEATTR MV_INQUIRY_VIRTUALD_DATA[];

+#define MV_INQUIRY_VPD_PAGE0_VIRTUALD_DATA	MV_INQUIRY_VPD_PAGE0_DEVICE_DATA

+extern MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE80_VIRTUALD_DATA[];

+#define MV_INQUIRY_VPD_PAGE83_VIRTUALD_DATA	MV_INQUIRY_VPD_PAGE83_DEVICE_DATA

+#else

+extern MV_U8 BASEATTR MV_INQUIRY_VIRTUALD_DATA[];

+extern MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE0_VIRTUALD_DATA[];

+extern MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE80_VIRTUALD_DATA[];

+extern MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE83_VIRTUALD_DATA[];

+#endif

+

+#endif /*  __MV_COM_SCSI_H__ */

diff --git a/drivers/scsi/thor/include/com_sgd.h b/drivers/scsi/thor/include/com_sgd.h
new file mode 100755
index 0000000..5bbf39a
--- /dev/null
+++ b/drivers/scsi/thor/include/com_sgd.h
@@ -0,0 +1,383 @@
+#ifndef __MV_COM_SGD_H__
+#define __MV_COM_SGD_H__
+
+struct _sgd_tbl_t;
+struct _sgd_t;
+
+#define SGD_DOMAIN_MASK	0xF0000000L
+
+#define SGD_EOT			(1L<<27)	/* End of table */
+#define SGD_COMPACT		(1L<<26)	/* Compact (12 bytes) SG format, not verified yet */
+#define SGD_WIDE		(1L<<25)	/* 32 byte SG format */
+#define SGD_X64			(1L<<24)	/* the 2nd part of SGD_WIDE */
+#define SGD_NEXT_TBL	(1L<<23)	/* Next SG table format */
+#define SGD_VIRTUAL		(1L<<22)	/* Virtual SG format, either 32 or 64 bit is determined during compile time. */
+#define SGD_REFTBL		(1L<<21)	/* sg table reference format, either 32 or 64 bit is determined during compile time. */
+#define SGD_REFSGD		(1L<<20)	/* sg item reference format */
+#define SGD_VP			(1L<<19)	/* virtual and physical, not verified yet */
+#define SGD_VWOXCTX		(1L<<18)	/* virtual without translation context */
+#define SGD_PCTX		(1L<<17)	/* sgd_pctx_t, 64 bit only */
+
+typedef struct _sg_common_t
+{
+	MV_U32	dword1;
+	MV_U32	dword2;
+	MV_U32	flags;	/* SGD_xxx */
+	MV_U32	dword3;
+} sg_common_t;
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _sgd_t
+{
+	MV_U64	baseAddr;
+	MV_U32	flags;
+	MV_U32	size;
+} sgd_t;
+
+/*---------------------------------------------------------------------------*/
+
+#define GET_COMPACT_SGD_SIZE(sgd)	\
+	((((sgd_compact_t*)(sgd))->flags) & 0x3FFFFFL)
+
+#define SET_COMPACT_SGD_SIZE(sgd,sz) do {			\
+	(((sgd_compact_t*)(sgd))->flags) &= ~0x3FFFFFL;	\
+	(((sgd_compact_t*)(sgd))->flags) |= (sz);		\
+} while(0)
+
+#define SIZEOF_COMPACT_SGD	12
+
+typedef struct _sgd_compact_t
+{
+	MV_U64	baseAddr;
+	MV_U32	flags;
+} sgd_compact_t;
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _sgd_v32_t
+{
+	MV_PVOID	vaddr;
+	MV_PVOID	xctx;
+	MV_U32		flags;
+	MV_U32		size;
+} sgd_v32_t;
+
+/* sgd_v_t defines 32/64 bit virtual sgd without translation context */
+typedef struct _sgd_v_t
+{
+	union {
+		MV_PVOID	vaddr;
+		MV_U64		dummy;
+	} u;
+	MV_U32		flags;
+	MV_U32		size;
+} sgd_v_t;
+
+typedef struct _sgd_v64_t
+{
+	union {
+		MV_PVOID	vaddr;
+		MV_U64		dummy;
+	} u1;
+	MV_U32	flags;
+	MV_U32	size;
+
+	union {
+		MV_PVOID	xctx;
+		MV_U64		dummy;
+	} u2;
+	MV_U32	flagsEx;
+	MV_U32	rsvd;
+} sgd_v64_t;
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _sgd_ref32_t
+{
+	MV_PVOID	ref;
+	MV_U32		offset;
+	MV_U32		flags;
+	MV_U32		size;
+} sgd_ref32_t;
+
+typedef struct _sgd_ref64_t
+{
+	union {
+		MV_PVOID	ref;
+		MV_U64		dummy;
+	} u;
+	MV_U32	flags;
+	MV_U32	size;
+
+	MV_U32	offset;
+	MV_U32	rsvd1;
+	MV_U32	flagsEx;
+	MV_U32	rsvd2;
+} sgd_ref64_t;
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _sgd_nt_t
+{
+	union {
+		struct _sgd_tbl_t*	next;
+		MV_U64	dummy;
+	} u;
+	MV_U32	flags;
+	MV_U32	rsvd;
+} sgd_nt_t;
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _sgd_vp_t
+{
+	MV_U64	baseAddr;
+	MV_U32	flags;		// SGD_VP | SGD_WIDE
+	MV_U32	size;
+
+	union {
+		MV_PVOID vaddr;
+		MV_U64   dummy;
+	} u;
+	MV_U32	flagsEx;	// SGD_X64
+	MV_U32	rsvd;
+} sgd_vp_t;
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _sgd_pctx_t
+{
+	MV_U64	baseAddr;
+	MV_U32	flags;		// SGD_PCTX | SGD_WIDE
+	MV_U32	size;
+
+	union {
+		MV_PVOID xctx;
+		MV_U64   dummy;
+	} u;
+	MV_U32	flagsEx;	// SGD_X64
+	MV_U32	rsvd;
+} sgd_pctx_t;
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _sgd_tbl_t
+{
+	MV_U8 Max_Entry_Count;
+	MV_U8 Valid_Entry_Count;
+	MV_U8 Flag;
+	MV_U8 Reserved0;
+	MV_U32 Byte_Count;
+	sgd_t* Entry_Ptr;
+} sgd_tbl_t;
+
+#define sgd_table_init(sgdt,maxCnt,entries) do {	\
+	MV_ZeroMemory(sgdt,sizeof(sgd_tbl_t));		\
+	(sgdt)->Max_Entry_Count = (maxCnt);				\
+	(sgdt)->Entry_Ptr = (sgd_t*)(entries);			\
+} while(0)
+
+/*---------------------------------------------------------------------------*/
+
+#define sgd_inc(sgd) do {	\
+	if( (sgd)->flags & SGD_COMPACT )					\
+		sgd = (sgd_t*)(((unsigned char*) (sgd)) + 12);	\
+	else if( (sgd)->flags & SGD_WIDE )					\
+		sgd = (sgd_t*)(((unsigned char*) (sgd)) + 32);	\
+	else sgd = (sgd_t*)(((unsigned char*) (sgd)) + 16);	\
+} while(0)
+
+#define sgd_get_vaddr(sgd,v) do {				\
+	if( (sgd)->flags & SGD_VIRTUAL ) {			\
+		if( (sgd)->flags & SGD_WIDE )			\
+			(v) = ((sgd_v64_t*)(sgd))->u1.vaddr;\
+		else (v) = ((sgd_v32_t*)(sgd))->vaddr;	\
+	}											\
+	else if( (sgd)->flags & SGD_VWOXCTX )		\
+		(v) = ((sgd_v_t*)sgd)->u.vaddr;			\
+	else if( (sgd)->flags & SGD_VP )			\
+		(v) = ((sgd_vp_t*)(sgd))->u.vaddr;		\
+	else										\
+		MV_ASSERT(MV_FALSE);					\
+} while(0)
+
+#define sgd_get_xctx(sgd,v) do {	\
+	if( (sgd)->flags & SGD_WIDE )	(v) = ((sgd_v64_t*)(sgd))->u2.xctx;	\
+	else (v) = ((sgd_v32_t*)(sgd))->xctx;	\
+} while(0)
+
+#define sgd_get_ref(sgd,_ref) do {	\
+	if( (sgd)->flags & SGD_WIDE ) (_ref) = ((sgd_ref64_t*)(sgd))->u.ref;	\
+	else (_ref) = ((sgd_ref32_t*)(sgd))->ref;	\
+} while(0)
+
+#define sgd_set_ref(sgd,_ref) do {	\
+	if( (sgd)->flags & SGD_WIDE ) ((sgd_ref64_t*)(sgd))->u.ref = (_ref);	\
+	else ((sgd_ref32_t*)(sgd))->ref = (_ref);	\
+} while(0)
+
+#define sgd_get_reftbl(sgd,reft) do {	\
+	if( (sgd)->flags & SGD_WIDE )		\
+		(reft) = (sgd_tbl_t*) (((sgd_ref64_t*)(sgd))->u.ref);	\
+	else (reft) = (sgd_tbl_t*)(((sgd_ref32_t*)(sgd))->ref);	\
+} while(0)
+
+#define sgd_get_refsgd(sgd,reft) do {	\
+	if( (sgd)->flags & SGD_WIDE )		\
+		(reft) = (sgd_t*) (((sgd_ref64_t*)(sgd))->u.ref);	\
+	else (reft) = (sgd_t*)(((sgd_ref32_t*)(sgd))->ref);	\
+} while(0)
+
+#define sgd_get_refoff(sgd,off) do {	\
+	if( (sgd)->flags & SGD_WIDE )	(off) = ((sgd_ref64_t*)(sgd))->offset;	\
+	else (off) = ((sgd_ref32_t*)(sgd))->offset;	\
+} while(0)
+
+#define sgd_set_refoff(sgd,off) do {	\
+	if( (sgd)->flags & SGD_WIDE )	((sgd_ref64_t*)(sgd))->offset = (off);	\
+	else ((sgd_ref32_t*)(sgd))->offset = (off);	\
+} while(0)
+
+#define sgd_get_nexttbl(sgd,n) do {	\
+	n = ((sgd_nt_t*)(sgd))->u.next;	\
+} while(0)
+
+#define sgd_mark_eot(sgd) \
+	((sgd)->flags |= SGD_EOT)
+
+#define sgd_clear_eot(sgd) \
+	((sgd)->flags &= ~SGD_EOT)
+
+#define sgd_eot(sgd)	\
+	((sgd)->flags & SGD_EOT)
+
+#define sgd_copy(sgdDst,sgdSrc) do {	\
+	*(sgdDst) = *(sgdSrc);	\
+	if( (sgdSrc)->flags & SGD_WIDE )	\
+		(sgdDst)[1] = (sgdSrc)[1];	\
+} while(0)
+
+#define sgd_getsz(sgd,sz) do {				\
+	if( (sgd)->flags & SGD_COMPACT )		\
+		(sz) = GET_COMPACT_SGD_SIZE(sgd);	\
+	else (sz) = (sgd)->size;				\
+} while(0)
+
+#define sgd_setsz(sgd,sz) do {				\
+	if( (sgd)->flags & SGD_COMPACT )		\
+		SET_COMPACT_SGD_SIZE(sgd,sz);		\
+	else (sgd)->size = (sz);				\
+} while(0)
+
+#define sgdt_get_lastsgd(sgdt,sgd) do {		\
+	(sgd) = &(sgdt)->Entry_Ptr[(sgdt)->Valid_Entry_Count];	\
+	(sgd)--;								\
+	if( (sgd)->flags & SGD_X64 ) (sgd)--;	\
+} while(0)
+
+/*---------------------------------------------------------------------------*/
+
+typedef int (*sgd_visitor_t)(sgd_t* sgd, MV_PVOID pContext);
+
+int sgd_table_walk(
+	sgd_tbl_t*		sgdt,
+	sgd_visitor_t	visitor,
+	MV_PVOID		ctx 
+	);
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _sgd_iter_t
+{
+	sgd_t*	sgd;		/* current SG */
+	MV_U32	offset;		/* offset in the SG */
+	MV_U32	remainCnt;
+} sgd_iter_t;
+
+void  sgd_iter_init(
+	sgd_iter_t*	iter,
+	sgd_t*		sgd,
+	MV_U32		offset,
+	MV_U32		count 
+	);
+
+int sgd_iter_get_next(
+	sgd_iter_t*	iter,
+	sgd_t*		sgd
+	);
+
+/*---------------------------------------------------------------------------*/
+
+void sgd_dump(sgd_t* sg, char* prefix);
+void sgdt_dump(sgd_tbl_t *SgTbl, char* prefix);
+
+/*---------------------------------------------------------------------------*/
+
+void sgdt_append(
+	sgd_tbl_t*	sgdt,
+	MV_U32		address,
+	MV_U32		addressHigh,
+	MV_U32		size
+	);
+
+void sgdt_append_pctx(
+	sgd_tbl_t*	sgdt,
+	MV_U32		address,
+	MV_U32		addressHigh,
+	MV_U32		size,
+	MV_PVOID	xctx
+	);
+
+int sgdt_append_virtual(
+	sgd_tbl_t* sgdt,
+	MV_PVOID virtual_address,
+	MV_PVOID translation_ctx,
+	MV_U32 size 
+	);
+
+int sgdt_append_ref(
+	sgd_tbl_t*	sgdt,
+	MV_PVOID	ref,
+	MV_U32		offset,
+	MV_U32		size,
+	MV_BOOLEAN	refTbl
+	);
+
+int sgdt_append_vp(
+	sgd_tbl_t*	sgdt,
+	MV_PVOID	virtual_address,
+	MV_U32		size,
+	MV_U32		address,
+	MV_U32		addressHigh
+	);
+
+void
+sgdt_copy_partial(
+	sgd_tbl_t* sgdt,
+	sgd_t**	ppsgd,
+	MV_PU32	poff,
+	MV_U32	size
+	);
+
+void sgdt_append_sgd(
+	sgd_tbl_t*	sgdt,
+	sgd_t*		sgd
+	);
+
+#define sgdt_append_reftbl(sgdt,refSgdt,offset,size)	\
+	sgdt_append_ref(sgdt,refSgdt,offset,size,MV_TRUE)
+
+#define sgdt_append_refsgd(sgdt,refSgd,offset,size)	\
+	sgdt_append_ref(sgdt,refSgd,offset,size,MV_FALSE)
+
+/*---------------------------------------------------------------------------*/
+
+int sgdt_prepare_hwprd(
+	MV_PVOID		pCore,
+	sgd_tbl_t*		pSource,
+	sgd_t*			pSg,
+	int				availSgEntry
+	);
+
+#endif	/*__MV_COM_SGD_H__*/
diff --git a/drivers/scsi/thor/include/com_tag.h b/drivers/scsi/thor/include/com_tag.h
new file mode 100755
index 0000000..b6ee251
--- /dev/null
+++ b/drivers/scsi/thor/include/com_tag.h
@@ -0,0 +1,33 @@
+#ifndef __MV_COM_TAG_H__
+#define __MV_COM_TAG_H__
+
+#include "com_define.h"
+
+typedef struct _Tag_Stack Tag_Stack, *PTag_Stack;
+
+#define FILO_TAG 0x00
+#define FIFO_TAG 0x01
+
+/* if TagStackType!=FIFO_TAG, use FILO, */
+/* if TagStackType==FIFO_TAG, use FIFO, PtrOut is the next tag to get */
+/*  and Top is the number of available tags in the stack */
+/* when use FIFO, get tag from PtrOut and free tag to (PtrOut+Top)%Size */
+struct _Tag_Stack
+{
+	MV_PU16  Stack;
+	MV_U16   Top;
+	MV_U16   Size;
+	MV_U16   PtrOut;
+	MV_U8    TagStackType;
+#ifndef _OS_BIOS
+	MV_U8    Reserved[1];	
+#endif
+};
+
+MV_U16 Tag_GetOne(PTag_Stack pTagStack);
+MV_VOID Tag_ReleaseOne(PTag_Stack pTagStack, MV_U16 tag);
+MV_VOID Tag_Init(PTag_Stack pTagStack, MV_U16 size);
+MV_VOID Tag_Init_FIFO( PTag_Stack pTagStack, MV_U16 size );
+MV_BOOLEAN Tag_IsEmpty(PTag_Stack pTagStack);
+
+#endif /*  __MV_COM_TAG_H__ */
diff --git a/drivers/scsi/thor/include/com_type.h b/drivers/scsi/thor/include/com_type.h
new file mode 100755
index 0000000..c2ef6e5
--- /dev/null
+++ b/drivers/scsi/thor/include/com_type.h
@@ -0,0 +1,427 @@
+#ifndef __MV_COM_TYPE_H__

+#define __MV_COM_TYPE_H__

+

+#include "com_define.h"

+#include "com_list.h"

+

+#include "mv_config.h"	// USE_NEW_SGTABLE is defined in mv_config.h

+

+/*

+ * Data Structure

+ */

+#define MAX_CDB_SIZE                            16

+

+struct _MV_Request;

+typedef struct _MV_Request MV_Request, *PMV_Request;

+

+#ifdef RAID_DRIVER

+typedef struct _MV_XOR_Request MV_XOR_Request, *PMV_XOR_Request;

+#endif /* RAID_DRIVER */

+

+#define REQ_STATUS_SUCCESS                      0x0

+#define REQ_STATUS_NOT_READY                    0x1

+#define REQ_STATUS_MEDIA_ERROR                  0x2

+#define REQ_STATUS_BUSY                         0x3

+#define REQ_STATUS_INVALID_REQUEST              0x4

+#define REQ_STATUS_INVALID_PARAMETER            0x5

+#define REQ_STATUS_NO_DEVICE                    0x6

+/* Sense data structure is the SCSI "Fixed format sense datat" format. */

+#define REQ_STATUS_HAS_SENSE                    0x7

+#define REQ_STATUS_ERROR                        0x8

+#define REQ_STATUS_ERROR_WITH_SENSE             0x10

+/* Request initiator must set the status to REQ_STATUS_PENDING. */

+#define REQ_STATUS_PENDING                      0x80

+#define REQ_STATUS_RETRY                        0x81

+#define REQ_STATUS_REQUEST_SENSE                0x82

+#define REQ_STATUS_ABORT                        0x83

+

+/* 

+ * Don't change the order here. 

+ * Module_StartAll will start from big id to small id. 

+ * Make sure module_set setting matches the Module_Id 

+ * MODULE_HBA must be the first one. Refer to Module_AssignModuleExtension.

+ * And HBA_GetNextModuleSendFunction has an assumption that the next level 

+ * has larger ID.

+ */

+enum Module_Id

+{

+        MODULE_HBA = 0,

+#ifdef CACHE_MODULE_SUPPORT

+        MODULE_CACHE,

+#endif /*  CACHE_MODULE_SUPPORT */

+

+#ifdef RAID_DRIVER

+        MODULE_RAID,

+#endif /*  RAID_DRIVER */

+        MODULE_CORE,

+        MAX_MODULE_NUMBER

+};

+#define MAX_POSSIBLE_MODULE_NUMBER              MAX_MODULE_NUMBER

+

+#ifdef USE_NEW_SGTABLE

+#include "com_sgd.h"

+

+typedef sgd_tbl_t MV_SG_Table, *PMV_SG_Table;

+typedef sgd_t MV_SG_Entry, *PMV_SG_Entry;

+

+#else

+

+struct _MV_SG_Table;

+typedef struct _MV_SG_Table MV_SG_Table, *PMV_SG_Table;

+

+struct _MV_SG_Entry;

+typedef struct _MV_SG_Entry MV_SG_Entry, *PMV_SG_Entry;

+

+

+

+/* SG Table and SG Entry */

+struct _MV_SG_Entry

+{

+	MV_U32 Base_Address;

+	MV_U32 Base_Address_High;

+	MV_U32 Reserved0;

+	MV_U32 Size;

+};

+

+struct _MV_SG_Table

+{

+	MV_U8 Max_Entry_Count;

+	MV_U8 Valid_Entry_Count;

+	MV_U8 Flag;

+	MV_U8 Reserved0;

+	MV_U32 Byte_Count;

+	PMV_SG_Entry Entry_Ptr;

+};

+

+#endif

+

+#ifdef SIMULATOR

+#define	MV_REQ_COMMON_SCSI	          0

+#define	MV_REQ_COMMON_XOR	          1

+#endif	/*SIMULATOR*/

+

+/* 

+ * MV_Request is the general request type passed through different modules. 

+ * Must be 64 bit aligned.

+ */

+

+#define DEV_ID_TO_TARGET_ID(_dev_id)    ((MV_U8)((_dev_id) & 0x00FF))

+#define DEV_ID_TO_LUN(_dev_id)                ((MV_U8) (((_dev_id) & 0xFF00) >> 8))

+#define __MAKE_DEV_ID(_target_id, _lun)   (((MV_U16)(_target_id)) | (((MV_U16)(_lun)) << 8))

+

+/*Work around free disks suporting temporarily*/

+#define RESTORE_FREE_DISK_TID 1

+

+typedef void (*MV_ReqCompletion)(MV_PVOID,PMV_Request);

+

+struct _MV_Request {

+#ifdef SIMULATOR

+	MV_U32 CommonType;	// please keep it as the first field

+#endif	/* SIMULATOR */

+#ifdef __RES_MGMT__

+	List_Head pool_entry;     /* don't bother, res_mgmt use only */

+#endif /* __RES_MGMT__ */

+	List_Head Queue_Pointer;

+	List_Head Complete_Queue_Pointer;

+

+#if defined(_OS_LINUX) || defined(__QNXNTO__)

+	List_Head hba_eh_entry;           /* hba's request queue  */

+#endif /* _OS_LINUX || __QNXNTO__ */

+

+	MV_U16 Device_Id;

+

+	MV_U16 Req_Flag;                  /* Check the REQ_FLAG definition */

+	MV_U8 Scsi_Status;

+	MV_U8 Tag;                        /* Request tag */

+	MV_U8 Req_Type;                   /* Check the REQ_TYPE definition */

+#ifdef _OS_WINDOWS

+	MV_U8 Reserved0[1];

+#elif defined(SUPPORT_ERROR_HANDLING) && defined(_OS_LINUX)

+	MV_U8 eh_flag;    /* mark a req after it is re-inserted into

+			   * waiting_list due to error handling.

+			   */

+#else

+	MV_U8 Reserved0[1]; 

+#endif /* _OS_WINDOWS */

+

+	MV_PVOID Cmd_Initiator;           /* Which module(extension pointer) 

+					     creates this request. */

+

+	MV_U8 Sense_Info_Buffer_Length;

+#if RESTORE_FREE_DISK_TID

+	MV_U8 org_target_id;

+#else

+	MV_U8 Reserved1;

+#endif

+	MV_U16 SlotNo; 

+	MV_U32 Data_Transfer_Length; 

+

+	MV_U8 Cdb[MAX_CDB_SIZE]; 

+	MV_PVOID Data_Buffer; 

+	MV_PVOID Sense_Info_Buffer;

+

+	MV_SG_Table SG_Table;

+

+	MV_PVOID Org_Req;                /* The original request. */ 

+

+	/* Each module should only use Context to store module information. */

+	MV_PVOID Context[MAX_POSSIBLE_MODULE_NUMBER];

+

+	MV_PVOID Scratch_Buffer;          /* pointer to the scratch buffer 

+										 that this request used */

+	MV_PVOID SG_Buffer;

+	MV_PVOID pRaid_Request;

+

+	MV_LBA LBA;

+	MV_U32 Sector_Count;

+	MV_U32 Cmd_Flag;

+

+	MV_U32 Time_Out;                  /* how many seconds we should wait 

+					     before treating request as 

+					     timed-out */

+	MV_U32 Splited_Count;

+

+#if ERROR_HANDLING_SUPPORT

+	MV_U8   bh_eh_flag;

+	MV_U8   reserved[3];

+	MV_PVOID bh_eh_ctx; /*The type should be MV_PVOID*/

+#endif /* ERROR_HANDLING_SUPPORT */

+#ifdef _OS_LINUX

+	MV_DECLARE_TIMER(eh_timeout);

+ #ifdef SUPPORT_REQUEST_TIMER

+	MV_PVOID	err_request_ctx;

+ #endif

+#endif /* _OS_LINUX */

+#ifdef _OS_LINUX

+#ifdef _32_LEGACY_

+	MV_U8 dummy[5];

+#endif

+#endif /* _OS_LINUX */

+	MV_ReqCompletion	Completion; /* call back function */

+};

+

+#define MV_REQUEST_SIZE                   sizeof(MV_Request)

+/*

+ * Request flag is the flag for the MV_Request data structure.

+ */

+#define REQ_FLAG_LBA_VALID                MV_BIT(0)

+#define REQ_FLAG_CMD_FLAG_VALID           MV_BIT(1)

+#define REQ_FLAG_RETRY                    MV_BIT(2)

+#define REQ_FLAG_INTERNAL_SG              MV_BIT(3)

+#ifndef USE_NEW_SGTABLE	

+#define REQ_FLAG_USE_PHYSICAL_SG          MV_BIT(4)

+#define REQ_FLAG_USE_LOGICAL_SG           MV_BIT(5)

+#else

+/*temporarily reserve bit 4 & 5 until NEW_SG is enabled fixedly for all OS */

+#endif

+#define REQ_FLAG_FLUSH                    MV_BIT(6)

+#define REQ_FLAG_CONSOLIDATE			  MV_BIT(8)

+#define REQ_FLAG_NO_CONSOLIDATE           MV_BIT(9)

+#define REQ_FLAG_EXTERNAL				  MV_BIT(10)

+#define REQ_FLAG_CORE_SUB                 MV_BIT(11)

+#define REQ_FLAG_BYPASS_HYBRID            MV_BIT(12)	// hybrid disk simulation

+

+/*

+ * Request Type is the type of MV_Request.

+ */

+enum {

+	/* use a value other than 0, and now they're bit-mapped */

+	REQ_TYPE_OS       = 0x01,

+	REQ_TYPE_RAID     = 0x02,

+	REQ_TYPE_CACHE    = 0x04,

+	REQ_TYPE_INTERNAL = 0x08,

+	REQ_TYPE_SUBLD    = 0x10,

+	REQ_TYPE_SUBBGA   = 0x20,

+	REQ_TYPE_MP       = 0x40,

+};

+

+/*

+ * Command flag is the flag for the CDB command itself 

+ */

+/* The first 16 bit can be determined by the initiator. */

+#define CMD_FLAG_NON_DATA                 MV_BIT(0)  /* 1-non data; 

+							0-data command */

+#define CMD_FLAG_DMA                      MV_BIT(1)  /* 1-DMA */

+#define CMD_FLAG_PIO					  MV_BIT(2)  /* 1-PIO */

+#define CMD_FLAG_DATA_IN                  MV_BIT(3)  /* 1-host read data */

+#define CMD_FLAG_DATA_OUT                 MV_BIT(4)	 /* 1-host write data */

+#define CMD_FLAG_SMART                    MV_BIT(5)  /* 1-SMART command;0-non SMART command*/

+#define CMD_FLAG_SMART_ATA_12       MV_BIT(6)  /* SMART ATA_12  */

+#define CMD_FLAG_SMART_ATA_16       MV_BIT(7)  /* SMART ATA_16; */

+

+/*

+ * The last 16 bit only can be set by the target. Only core driver knows 

+ * the device characteristic. 

+ */

+#define CMD_FLAG_NCQ                      MV_BIT(16)

+#define CMD_FLAG_TCQ                      MV_BIT(17)

+#define CMD_FLAG_48BIT                    MV_BIT(18)

+#define CMD_FLAG_PACKET                   MV_BIT(19)  /* ATAPI packet cmd */

+#define CMD_FLAG_SCSI_PASS_THRU           MV_BIT(20)

+#define CMD_FLAG_ATA_PASS_THRU            MV_BIT(21)

+

+#ifdef RAID_DRIVER

+/* XOR request types */

+#define    XOR_REQUEST_WRITE              0

+#define    XOR_REQUEST_COMPARE            1

+#define    XOR_REQUEST_DMA                2

+

+/* XOR request status */

+#define XOR_STATUS_SUCCESS                0

+#define XOR_STATUS_INVALID_REQUEST        1

+#define XOR_STATUS_ERROR                  2

+#define XOR_STATUS_INVALID_PARAMETER      3

+#define XOR_SOURCE_SG_COUNT               11  

+#ifdef RAID6_MULTIPLE_PARITY

+#   define XOR_TARGET_SG_COUNT               3   

+#else

+#   define XOR_TARGET_SG_COUNT               1   

+#endif

+

+typedef MV_U8    XOR_COEF, *PXOR_COEF;        /* XOR Coefficient */

+

+struct _MV_XOR_Request {

+#ifdef SIMULATOR

+	MV_U32 CommonType;	// please keep it as the first field

+#endif	/*SIMULATOR*/

+	List_Head Queue_Pointer;

+

+	MV_U16 Device_Id;

+

+	MV_U8 Request_Type;                        

+	MV_U8 Request_Status;

+

+	MV_U8 Source_SG_Table_Count;        /* how many items in the 

+					       SG_Table_List */

+	MV_U8 Target_SG_Table_Count;

+#ifdef SOFTWARE_XOR

+	MV_U8 Reserved[2];

+#else

+	MV_U16 SlotNo;

+#endif /* SOFTWARE_XOR */

+

+	MV_SG_Table Source_SG_Table_List[XOR_SOURCE_SG_COUNT];

+	MV_SG_Table Target_SG_Table_List[XOR_TARGET_SG_COUNT];

+

+	

+	XOR_COEF    Coef[XOR_TARGET_SG_COUNT][XOR_SOURCE_SG_COUNT];

+

+	MV_U32 Error_Offset;                 /* byte, not sector */

+	MV_PVOID Cmd_Initiator;              /* Which module(extension pointer

+						) creates this request. */

+#ifdef RAID6_HARDWARE_XOR

+	MV_PVOID Context[MAX_POSSIBLE_MODULE_NUMBER];

+#else

+	MV_PVOID Context;

+#endif

+

+	MV_PVOID SG_Buffer;

+	void (*Completion)(MV_PVOID, PMV_XOR_Request);    /* callback */

+};

+#endif /* RAID_DRIVER */

+

+typedef struct _MV_Target_ID_Map

+{

+	MV_U16   Device_Id;

+	MV_U8    Type;                    /* 0:LD, 1:Free Disk */

+	MV_U8    Reserved;

+} MV_Target_ID_Map, *PMV_Target_ID_Map;

+

+/* Resource type */

+enum Resource_Type

+{

+	RESOURCE_CACHED_MEMORY = 0,

+#ifdef SUPPORT_DISCARDABLE_MEM

+	RESOURCE_DISCARDABLE_MEMORY,

+#endif

+	RESOURCE_UNCACHED_MEMORY

+};

+

+/* Module event type */

+enum Module_Event

+{

+	EVENT_MODULE_ALL_STARTED = 0,

+#ifdef CACHE_MODULE_SUPPORT

+	EVENT_DEVICE_CACHE_MODE_CHANGED,

+#endif /* CACHE_MODULE_SUPPORT */

+#ifdef SUPPORT_DISCARDABLE_MEM

+	EVENT_SPECIFY_RUNTIME_DEVICE,

+	EVENT_DISCARD_RESOURCE,

+#endif

+	EVENT_DEVICE_ARRIVAL,

+	EVENT_DEVICE_REMOVAL,

+	EVENT_LOG_GENERATED,

+	EVENT_HOT_PLUG,

+};

+

+/* Error_Handling_State */

+enum EH_State

+{

+	EH_NONE = 0,

+	EH_ABORT_REQUEST,

+	EH_LU_RESET,

+	EH_DEVICE_RESET,

+	EH_PORT_RESET,

+	EH_CHIP_RESET,

+	EH_SET_DISK_DOWN

+};

+

+typedef enum

+{

+	EH_REQ_NOP = 0,

+	EH_REQ_ABORT_REQUEST,

+	EH_REQ_HANDLE_TIMEOUT,

+	EH_REQ_RESET_BUS,

+	EH_REQ_RESET_CHANNEL,

+	EH_REQ_RESET_DEVICE,

+	EH_REQ_RESET_ADAPTER

+}eh_req_type_t;

+

+struct mod_notif_param {

+        MV_PVOID  p_param;

+        MV_U16    hi;

+        MV_U16    lo;

+

+        /* for event processing */

+        MV_U32    event_id;

+        MV_U16    dev_id;

+        MV_U8     severity_lvl;

+        MV_U8     param_count;

+};

+

+/*

+ * Exposed Functions

+ */

+

+/*

+ *

+ * Miscellaneous Definitions

+ *

+ */

+/* Rounding */

+

+/* Packed */

+

+#define MV_MAX(x,y)        (((x) > (y)) ? (x) : (y))

+#define MV_MIN(x,y)        (((x) < (y)) ? (x) : (y))

+

+#define MV_MAX_U64(x, y)   ((((x).value) > ((y).value)) ? (x) : (y))

+#define MV_MIN_U64(x, y)   ((((x).value) < ((y).value)) ? (x) : (y))

+

+#define MV_MAX_U8          0xFF

+#define MV_MAX_U16         0xFFFF

+#define MV_MAX_U32         0xFFFFFFFFL

+

+#ifdef _OS_LINUX

+#   define ROUNDING_MASK(x, mask)  (((x)+(mask))&~(mask))

+#   define ROUNDING(value, align)  ROUNDING_MASK(value,   \

+						 (typeof(value)) (align-1))

+#   define OFFSET_OF(type, member) offsetof(type, member)

+#else

+#   define ROUNDING(value, align)  ( ((value)+(align)-1)/(align)*(align) )

+#   define OFFSET_OF(type, member)    ((MV_U32)(MV_PTR_INTEGER)&(((type *) 0)->member))

+#   define ALIGN ROUNDING

+#endif /* _OS_LINUX */

+

+

+#endif /* __MV_COM_TYPE_H__ */

diff --git a/drivers/scsi/thor/include/com_u64.h b/drivers/scsi/thor/include/com_u64.h
new file mode 100755
index 0000000..1714f51
--- /dev/null
+++ b/drivers/scsi/thor/include/com_u64.h
@@ -0,0 +1,23 @@
+#ifndef _U64_H__
+#define _U64_H__
+
+MV_U64 U64_ADD_U32(MV_U64 v64, MV_U32 v32);
+MV_U64 U64_SUBTRACT_U32(MV_U64 v64, MV_U32 v32);
+MV_U64 U64_MULTIPLY_U32(MV_U64 v64, MV_U32 v32);
+MV_U64 U64_DIVIDE_U32(MV_U64 v64, MV_U32 v32);
+MV_I32 U64_COMPARE_U32(MV_U64 v64, MV_U32 v32);
+MV_U32 U64_MOD_U32(MV_U64 v64, MV_U32 v32);
+
+MV_U64 U64_ADD_U64(MV_U64 v1, MV_U64 v2);
+MV_U64 U64_SUBTRACT_U64(MV_U64 v1, MV_U64 v2);
+MV_U32 U64_DIVIDE_U64(MV_U64 v1, MV_U64 v2);
+MV_I32 U64_COMPARE_U64(MV_U64 v1, MV_U64 v2);
+
+#define U64_SET_VALUE(v64, v32)	do { v64.value = v32; } while(0)
+#define U64_SET_MAX_VALUE(v64)	do { v64.parts.low = v64.parts.high = 0xFFFFFFFFL; } while(0);
+#ifdef _OS_BIOS
+MV_U64 ZeroU64(MV_U64 v1);
+#endif
+
+#endif
+
diff --git a/drivers/scsi/thor/include/com_util.h b/drivers/scsi/thor/include/com_util.h
new file mode 100755
index 0000000..33c6555
--- /dev/null
+++ b/drivers/scsi/thor/include/com_util.h
@@ -0,0 +1,241 @@
+#ifndef __MV_COM_UTIL_H__
+#define __MV_COM_UTIL_H__
+
+#include "com_define.h"
+#include "com_type.h"
+
+#define MV_ZeroMemory(buf, len)           memset(buf, 0, len)
+#define MV_FillMemory(buf, len, pattern)  memset(buf, pattern, len)
+#define MV_CopyMemory(dest, source, len)  memcpy(dest, source, len)
+
+void MV_ZeroMvRequest(PMV_Request pReq);
+void MV_CopySGTable(PMV_SG_Table pTargetSGTable, PMV_SG_Table pSourceSGTable);
+
+MV_BOOLEAN MV_Equals(MV_PU8 des, MV_PU8 src, MV_U8 len);
+
+#ifndef _OS_BIOS
+#define	U64_ASSIGN(x,y)				  	((x).value = (y))
+#define	U64_ASSIGN_U64(x,y)			  	((x).value = (y).value)
+#define	U64_COMP_U64(x,y)			  	((x) == (y).value)
+#define U64_COMP_U64_VALUE(x,y)			((x).value == (y).value)
+#define U32_ASSIGN_U64(v64, v32)		((v64).value = (v32))
+#define	U64_SHIFT_LEFT(v64, v32)		((v64).value=(v64).value << (v32))
+#define	U64_SHIFT_RIGHT(v64, v32)		((v64).value=(v64).value >> (v32))
+#define U64_ZERO_VALUE(v64)				((v64).value = 0)
+#else
+#define	U64_ASSIGN(x,y)					((x) = (y))
+#define	U64_ASSIGN_U64(x,y)				((x) = (y))
+#define	U64_COMP_U64(x,y)			  	(U64_COMPARE_U64(x, y)==0)
+#define U64_COMP_U64_VALUE(x,y)			(U64_COMPARE_U64(x, y)==0)
+#define U32_ASSIGN_U64(v64, v32)		do { (v64).parts.low = v32; (v64).parts.high = 0; } while(0);
+#define	U64_SHIFT_LEFT(v64, v32)		do { (v64).parts.low=(v64).parts.low << v32; v64.parts.high = 0; } while(0);
+#define	U64_SHIFT_RIGHT(v64, v32)		do { (v64).parts.low=(v64).parts.low >> v32; v64.parts.high = 0; } while(0);
+#define U64_ZERO_VALUE(v64)				do { (v64).parts.low = (v64).parts.high = 0; } while(0);
+#endif
+
+#define MV_SWAP_32(x)                             \
+           (((MV_U32)((MV_U8)(x)))<<24 |          \
+            ((MV_U32)((MV_U8)((x)>>8)))<<16 |     \
+            ((MV_U32)((MV_U8)((x)>>16)))<<8 |     \
+            ((MV_U32)((MV_U8)((x)>>24))) )
+#define MV_SWAP_64(x)                             \
+           (((_MV_U64) (MV_SWAP_32((x).parts.low))) << 32 | \
+	    MV_SWAP_32((x).parts.high))
+#define MV_SWAP_16(x)                             \
+           (((MV_U16) ((MV_U8) (x))) << 8 |       \
+	    (MV_U16) ((MV_U8) ((x) >> 8)))
+
+#if !defined(_OS_LINUX) && !defined(__QNXNTO__)
+#   ifndef __MV_BIG_ENDIAN__
+
+#      define MV_CPU_TO_BE32(x)     MV_SWAP_32(x)
+#      define MV_CPU_TO_BE64(x)     MV_SWAP_64(x)
+#      define MV_CPU_TO_BE16(x)     MV_SWAP_16(x)
+#      define MV_BE16_TO_CPU(x)     MV_SWAP_16(x)
+#      define MV_BE32_TO_CPU(x)     MV_SWAP_32(x)
+#      define MV_BE64_TO_CPU(x)     MV_SWAP_64(x)
+
+#      define MV_CPU_TO_LE16(x)     x
+#      define MV_CPU_TO_LE32(x)     x
+#      define MV_CPU_TO_LE64(x)     x
+#      define MV_LE16_TO_CPU(x)     x
+#      define MV_LE32_TO_CPU(x)     x
+#      define MV_LE64_TO_CPU(x)     x
+
+#   else  /* __MV_BIG_ENDIAN__ */
+
+#      define MV_CPU_TO_BE32(x)     x
+#      define MV_CPU_TO_BE64(x)     x
+#      define MV_CPU_TO_BE16(x)     x
+#      define MV_BE16_TO_CPU(x)     x
+#      define MV_BE32_TO_CPU(x)     x
+#      define MV_BE64_TO_CPU(x)     x
+
+#      define MV_CPU_TO_LE16(x)     MV_SWAP_16(x)
+#      define MV_CPU_TO_LE32(x)     MV_SWAP_32(x)
+#      define MV_CPU_TO_LE64(x)     MV_SWAP_64(x)
+#      define MV_LE16_TO_CPU(x)     MV_SWAP_16(x)
+#      define MV_LE32_TO_CPU(x)     MV_SWAP_32(x)
+#      define MV_LE64_TO_CPU(x)     MV_SWAP_64(x)
+
+#   endif /* __MV_BIG_ENDIAN__ */
+
+#else /* !_OS_LINUX */
+
+#define MV_CPU_TO_LE16      cpu_to_le16
+#define MV_CPU_TO_LE32      cpu_to_le32
+#define MV_CPU_TO_LE64(x)   cpu_to_le64((x).value)
+#define MV_CPU_TO_BE16      cpu_to_be16
+#define MV_CPU_TO_BE32      cpu_to_be32
+#define MV_CPU_TO_BE64(x)   cpu_to_be64((x).value)
+
+#define MV_LE16_TO_CPU      le16_to_cpu
+#define MV_LE32_TO_CPU      le32_to_cpu
+#define MV_LE64_TO_CPU(x)   le64_to_cpu((x).value)
+#define MV_BE16_TO_CPU      be16_to_cpu
+#define MV_BE32_TO_CPU      be32_to_cpu
+#define MV_BE64_TO_CPU(x)   be64_to_cpu((x).value)
+
+#endif /* !_OS_LINUX */
+
+/*
+ * big endian bit-field structs that are larger than a single byte 
+ * need swapping
+ */
+#ifdef __MV_BIG_ENDIAN__
+#define MV_CPU_TO_LE16_PTR(pu16)        \
+   *((MV_PU16)(pu16)) = MV_CPU_TO_LE16(*(MV_PU16) (pu16))
+#define MV_CPU_TO_LE32_PTR(pu32)        \
+   *((MV_PU32)(pu32)) = MV_CPU_TO_LE32(*(MV_PU32) (pu32))
+
+#define MV_LE16_TO_CPU_PTR(pu16)        \
+   *((MV_PU16)(pu16)) = MV_LE16_TO_CPU(*(MV_PU16) (pu16))
+#define MV_LE32_TO_CPU_PTR(pu32)        \
+   *((MV_PU32)(pu32)) = MV_LE32_TO_CPU(*(MV_PU32) (pu32))
+# else  /* __MV_BIG_ENDIAN__ */
+#define MV_CPU_TO_LE16_PTR(pu16)        /* Nothing */
+#define MV_CPU_TO_LE32_PTR(pu32)        /* Nothing */
+#define MV_LE16_TO_CPU_PTR(pu32)
+#define MV_LE32_TO_CPU_PTR(pu32)
+#endif /* __MV_BIG_ENDIAN__ */
+
+/* definitions - following macro names are used by RAID module 
+   must keep consistent */
+#define CPU_TO_BIG_ENDIAN_16(x)        MV_CPU_TO_BE16(x)
+#define CPU_TO_BIG_ENDIAN_32(x)        MV_CPU_TO_BE32(x)
+#define CPU_TO_BIG_ENDIAN_64(x)        MV_CPU_TO_BE64(x)
+
+void SGTable_Init(
+    OUT PMV_SG_Table pSGTable,
+    IN MV_U8 flag
+    );
+
+#ifndef USE_NEW_SGTABLE
+void SGTable_Append(
+    OUT PMV_SG_Table pSGTable,
+    MV_U32 address,
+    MV_U32 addressHigh,
+    MV_U32 size
+    );
+#else
+#define SGTable_Append sgdt_append
+#endif
+
+MV_BOOLEAN SGTable_Available(
+    IN PMV_SG_Table pSGTable
+    );
+
+void MV_InitializeTargetIDTable(
+    IN PMV_Target_ID_Map pMapTable
+    );
+
+MV_U16 MV_MapTargetID(
+    IN PMV_Target_ID_Map    pMapTable,
+    IN MV_U16                deviceId,
+    IN MV_U8                deviceType
+    );
+
+MV_U16 MV_MapToSpecificTargetID(
+	IN PMV_Target_ID_Map	pMapTable,
+	IN MV_U16				specificId,
+	IN MV_U16				deviceId,
+	IN MV_U8				deviceType
+	);
+
+MV_U16 MV_RemoveTargetID(
+    IN PMV_Target_ID_Map    pMapTable,
+    IN MV_U16                deviceId,
+    IN MV_U8                deviceType
+    );
+
+MV_U16 MV_GetMappedID(
+	IN PMV_Target_ID_Map	pMapTable,
+	IN MV_U16				deviceId,
+	IN MV_U8				deviceType
+	);
+
+void MV_DecodeReadWriteCDB(
+	IN MV_PU8 Cdb,
+	OUT MV_LBA *pLBA,
+	OUT MV_U32 *pSectorCount);
+
+#define MV_SetLBAandSectorCount(pReq) do {								\
+	MV_DecodeReadWriteCDB(pReq->Cdb, &pReq->LBA, &pReq->Sector_Count);	\
+	pReq->Req_Flag |= REQ_FLAG_LBA_VALID;								\
+} while (0)
+
+void MV_DumpRequest(PMV_Request pReq, MV_BOOLEAN detail);
+#if defined(SUPPORT_RAID6) && defined(RAID_DRIVER)
+void MV_DumpXORRequest(PMV_XOR_Request pXORReq, MV_BOOLEAN detail);
+#endif /* SUPPORT_RAID6 */
+void MV_DumpSGTable(PMV_SG_Table pSGTable);
+const char* MV_DumpSenseKey(MV_U8 sense);
+
+MV_U32 MV_CRC(
+	IN MV_PU8  pData, 
+	IN MV_U16  len
+);
+
+#define MV_MOD_ADD(value, mod)                    \
+           do {                                   \
+              (value)++;                          \
+              if ((value) >= (mod))               \
+                 (value) = 0;                     \
+           } while (0);
+
+#ifdef MV_DEBUG
+void MV_CHECK_OS_SG_TABLE(
+    IN PMV_SG_Table pSGTable
+    );
+#endif /* MV_DEBUG */
+
+/* used for endian-ness conversion */
+static inline MV_VOID mv_swap_bytes(MV_PVOID buf, MV_U32 len)
+{
+	MV_U32 i;
+	MV_U8  tmp, *p;
+
+	/* we expect len to be in multiples of 2 */
+	if (len & 0x1)
+		return;
+
+	p = (MV_U8 *) buf;
+	for (i = 0; i < len / 2; i++) 
+	{
+		tmp = p[i];
+		p[i] = p[len - i - 1];
+		p[len - i - 1] = tmp;
+	}
+}
+
+
+#ifdef _OS_LINUX
+void List_Add(List_Head *new_one, List_Head *head);
+void List_AddTail(List_Head *new_one, List_Head *head);
+void List_Del(List_Head *entry);
+struct list_head *List_GetFirst(struct list_head *head);
+struct list_head *List_GetLast(struct list_head *head);
+
+#endif
+
+#endif /*  __MV_COM_UTIL_H__ */
diff --git a/drivers/scsi/thor/include/csmisas.h b/drivers/scsi/thor/include/csmisas.h
new file mode 100755
index 0000000..9541f0d
--- /dev/null
+++ b/drivers/scsi/thor/include/csmisas.h
@@ -0,0 +1,1223 @@
+/**************************************************************************

+

+Module Name:

+

+   CSMISAS.H

+

+

+Abstract:

+

+   This file contains constants and data structure definitions used by drivers

+   that support the Common Storage Management Interface specification for

+   SAS or SATA in either the Windows or Linux.

+

+   This should be considered as a reference implementation only.  Changes may 

+   be necessary to accommodate a specific build environment or target OS.

+

+Revision History:

+

+   001  SEF   8/12/03  Initial release.

+   002  SEF   8/20/03  Cleanup to match documentation.

+   003  SEF   9/12/03  Additional cleanup, created combined header

+   004  SEF   9/23/03  Changed base types to match linux defaults

+                       Added RAID signature

+                       Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG

+                       Changed CSMI_SAS_BEGIN_PACK to 8 for common structures

+                       Fixed other typos identified in first compilation test

+   005  SEF  10/03/03  Additions to match first version of CSMI document

+   006  SEF  10/14/03  Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER

+                       Added defines for bConnectionRate

+   007  SEF  10/15/03  Added Firmware Download Control Code and support

+                       Added CSMI revision support

+   008  SEF  10/30/03  No functional change, just updated version to track

+                       spec changes

+   009  SEF  12/09/03  No functional change, just updated version to track

+                       spec changes

+   010  SEF   3/11/04  Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the

+                       bFirmware member that is defined in the spec, but

+                       was missing in this file,

+                       added CC_CSMI_SAS_TASK_MANAGEMENT

+   011  SEF   4/02/04  No functional change, added comment line before

+                       CC_CSMI_SAS_TASK_MANAGEMENT

+   012  SEF   4/16/04  Added IOControllerNumber to linux header,

+                       Modified linux control codes to have upper word of

+                       0xCC77.... to indicate CSMI version 77

+                       Added bSignalClass to CC_CSMI_SET_PHY_INFO

+                       Added CC_CSMI_SAS_PHY_CONTROL support

+   013  SEF   5/14/04  Added CC_CSMI_SAS_GET_CONNECTOR_INFO support

+   014  SEF   5/24/04  No functional change, just updated version to track spec

+                       changes

+   015  SEF   6/16/04  changed bPinout to uPinout to reflect proper size,

+                       changed width of bLocation defines to reflect size

+   016  SEF   6/17/04  changed bLengthOfControls in CSMI_SAS_PHY_CONTROL

+                       to be proper size

+   017  SEF   9/17/04  added CSMI_SAS_SATA_PORT_SELECTOR,

+                       CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and

+                       CSMI_SAS_CON_NOT_CONNECTED

+   018  SEF   9/20/04  added CSMI_SAS_PHY_USER_PATTERN, 

+                       changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not

+                       conflict with activate definition

+   019  SEF  12/06/04  added CSMI_SAS_GET_LOCATION

+                       added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS 

+                       structure

+

+**************************************************************************/

+

+#ifndef _CSMI_SAS_H_

+#define _CSMI_SAS_H_

+

+// CSMI Specification Revision, the intent is that all versions of the

+// specification will be backward compatible after the 1.00 release.

+// Major revision number, corresponds to xxxx. of CSMI specification

+// Minor revision number, corresponds to .xxxx of CSMI specification

+#define CSMI_MAJOR_REVISION   0

+#define CSMI_MINOR_REVISION   83

+

+/*************************************************************************/

+/* TARGET OS LINUX SPECIFIC CODE                                         */

+/*************************************************************************/

+

+// EDM #ifdef _linux

+#ifdef __KERNEL__

+

+

+// Linux base types

+

+#include <linux/types.h>

+

+// pack definition

+

+// EDM #define CSMI_SAS_BEGIN_PACK(x)    pack(x)

+// EDM #define CSMI_SAS_END_PACK         pack()

+

+// IOCTL Control Codes

+// (IoctlHeader.ControlCode)

+

+// Control Codes prior to 0.77

+

+// Control Codes requiring CSMI_ALL_SIGNATURE

+

+// #define CC_CSMI_SAS_GET_DRIVER_INFO    0x12345678

+// #define CC_CSMI_SAS_GET_CNTLR_CONFIG   0x23456781

+// #define CC_CSMI_SAS_GET_CNTLR_STATUS   0x34567812

+// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0x92345678

+

+// Control Codes requiring CSMI_RAID_SIGNATURE

+

+// #define CC_CSMI_SAS_GET_RAID_INFO      0x45678123

+// #define CC_CSMI_SAS_GET_RAID_CONFIG    0x56781234

+

+// Control Codes requiring CSMI_SAS_SIGNATURE

+

+// #define CC_CSMI_SAS_GET_PHY_INFO       0x67812345

+// #define CC_CSMI_SAS_SET_PHY_INFO       0x78123456

+// #define CC_CSMI_SAS_GET_LINK_ERRORS    0x81234567

+// #define CC_CSMI_SAS_SMP_PASSTHRU       0xA1234567

+// #define CC_CSMI_SAS_SSP_PASSTHRU       0xB1234567

+// #define CC_CSMI_SAS_STP_PASSTHRU       0xC1234567

+// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567

+// #define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xE1234567

+// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567

+// #define CC_CSMI_SAS_TASK_MANAGEMENT    0xA2345678

+

+// Control Codes for 0.77 and later

+

+// Control Codes requiring CSMI_ALL_SIGNATURE

+

+#define CC_CSMI_SAS_GET_DRIVER_INFO    0xCC770001

+#define CC_CSMI_SAS_GET_CNTLR_CONFIG   0xCC770002

+#define CC_CSMI_SAS_GET_CNTLR_STATUS   0xCC770003

+#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  0xCC770004

+

+// Control Codes requiring CSMI_RAID_SIGNATURE

+

+#define CC_CSMI_SAS_GET_RAID_INFO      0xCC77000A

+#define CC_CSMI_SAS_GET_RAID_CONFIG    0xCC77000B

+

+// Control Codes requiring CSMI_SAS_SIGNATURE

+

+#define CC_CSMI_SAS_GET_PHY_INFO       0xCC770014

+#define CC_CSMI_SAS_SET_PHY_INFO       0xCC770015

+#define CC_CSMI_SAS_GET_LINK_ERRORS    0xCC770016

+#define CC_CSMI_SAS_SMP_PASSTHRU       0xCC770017

+#define CC_CSMI_SAS_SSP_PASSTHRU       0xCC770018

+#define CC_CSMI_SAS_STP_PASSTHRU       0xCC770019

+#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020

+#define CC_CSMI_SAS_GET_SCSI_ADDRESS   0xCC770021

+#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022

+#define CC_CSMI_SAS_TASK_MANAGEMENT    0xCC770023

+#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024

+#define CC_CSMI_SAS_GET_LOCATION       0xCC770025

+

+// Control Codes requiring CSMI_PHY_SIGNATURE

+

+#define CC_CSMI_SAS_PHY_CONTROL        0xCC77003C

+

+// EDM #pragma CSMI_SAS_BEGIN_PACK(8)

+#pragma pack(8)

+

+// IOCTL_HEADER

+typedef struct _IOCTL_HEADER {

+	__u32 IOControllerNumber;

+	__u32 Length;

+	__u32 ReturnCode;

+	__u32 Timeout;

+	__u16 Direction;

+} IOCTL_HEADER, *PIOCTL_HEADER;

+

+// EDM #pragma CSMI_SAS_END_PACK

+#pragma pack()

+

+#endif

+

+#define __i8    char

+

+/*************************************************************************/

+/* TARGET OS WINDOWS SPECIFIC CODE                                       */

+/*************************************************************************/

+

+#ifdef _WIN32

+

+// windows IOCTL definitions

+

+#ifndef _NTDDSCSIH_

+#include <ntddscsi.h>

+#endif

+

+// pack definition

+

+#if defined _MSC_VER

+   #define CSMI_SAS_BEGIN_PACK(x)    pack(push,x)

+   #define CSMI_SAS_END_PACK         pack(pop)

+#elif defined __BORLANDC__

+   #define CSMI_SAS_BEGIN_PACK(x)    option -a##x

+   #define CSMI_SAS_END_PACK         option -a.

+#else

+   #error "CSMISAS.H - Must externally define a pack compiler designator."

+#endif

+

+// base types

+

+#define __u8    unsigned char

+#define __u32   unsigned long

+#define __u16   unsigned short

+

+#define __i8    char

+

+// IOCTL Control Codes

+// (IoctlHeader.ControlCode)

+

+// Control Codes requiring CSMI_ALL_SIGNATURE

+

+#define CC_CSMI_SAS_GET_DRIVER_INFO    1

+#define CC_CSMI_SAS_GET_CNTLR_CONFIG   2

+#define CC_CSMI_SAS_GET_CNTLR_STATUS   3

+#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD  4

+

+// Control Codes requiring CSMI_RAID_SIGNATURE

+

+#define CC_CSMI_SAS_GET_RAID_INFO      10

+#define CC_CSMI_SAS_GET_RAID_CONFIG    11

+

+// Control Codes requiring CSMI_SAS_SIGNATURE

+

+#define CC_CSMI_SAS_GET_PHY_INFO       20

+#define CC_CSMI_SAS_SET_PHY_INFO       21

+#define CC_CSMI_SAS_GET_LINK_ERRORS    22

+#define CC_CSMI_SAS_SMP_PASSTHRU       23

+#define CC_CSMI_SAS_SSP_PASSTHRU       24

+#define CC_CSMI_SAS_STP_PASSTHRU       25

+#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26

+#define CC_CSMI_SAS_GET_SCSI_ADDRESS   27

+#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28

+#define CC_CSMI_SAS_TASK_MANAGEMENT    29

+#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30

+#define CC_CSMI_SAS_GET_LOCATION       31

+

+// Control Codes requiring CSMI_PHY_SIGNATURE

+

+#define CC_CSMI_SAS_PHY_CONTROL        60

+

+#define IOCTL_HEADER SRB_IO_CONTROL

+#define PIOCTL_HEADER PSRB_IO_CONTROL

+

+#else /* _WIN32 */

+#define _WIN32                          0

+#endif /* _WIN32 */

+

+/*************************************************************************/

+/* TARGET OS NOT DEFINED ERROR                                           */

+/*************************************************************************/

+

+// EDM #if (!_WIN32 && !_linux)

+#if (!_WIN32 && !__KERNEL__)

+   #error "Unknown target OS."

+#endif

+

+/*************************************************************************/

+/* OS INDEPENDENT CODE                                                   */

+/*************************************************************************/

+

+/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */

+

+// Return codes for all IOCTL's regardless of class

+// (IoctlHeader.ReturnCode)

+

+#define CSMI_SAS_STATUS_SUCCESS              0

+#define CSMI_SAS_STATUS_FAILED               1

+#define CSMI_SAS_STATUS_BAD_CNTL_CODE        2

+#define CSMI_SAS_STATUS_INVALID_PARAMETER    3

+#define CSMI_SAS_STATUS_WRITE_ATTEMPTED      4

+

+// Signature value

+// (IoctlHeader.Signature)

+

+#define CSMI_ALL_SIGNATURE    "CSMIALL"

+

+// Timeout value default of 60 seconds

+// (IoctlHeader.Timeout)

+

+#define CSMI_ALL_TIMEOUT      60

+

+//  Direction values for data flow on this IOCTL

+// (IoctlHeader.Direction, Linux only)

+#define CSMI_SAS_DATA_READ    0

+#define CSMI_SAS_DATA_WRITE   1

+

+// I/O Bus Types

+// ISA and EISA bus types are not supported

+// (bIoBusType)

+

+#define CSMI_SAS_BUS_TYPE_PCI       3

+#define CSMI_SAS_BUS_TYPE_PCMCIA    4

+

+// Controller Status

+// (uStatus)

+

+#define CSMI_SAS_CNTLR_STATUS_GOOD     1

+#define CSMI_SAS_CNTLR_STATUS_FAILED   2

+#define CSMI_SAS_CNTLR_STATUS_OFFLINE  3

+#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4

+

+// Offline Status Reason

+// (uOfflineReason)

+

+#define CSMI_SAS_OFFLINE_REASON_NO_REASON             0

+#define CSMI_SAS_OFFLINE_REASON_INITIALIZING          1

+#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2

+#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE  3

+

+// Controller Class

+// (bControllerClass)

+

+#define CSMI_SAS_CNTLR_CLASS_HBA    5

+

+// Controller Flag bits

+// (uControllerFlags)

+

+#define CSMI_SAS_CNTLR_SAS_HBA   0x00000001

+#define CSMI_SAS_CNTLR_SAS_RAID  0x00000002

+#define CSMI_SAS_CNTLR_SATA_HBA  0x00000004

+#define CSMI_SAS_CNTLR_SATA_RAID 0x00000008

+

+// for firmware download

+#define CSMI_SAS_CNTLR_FWD_SUPPORT  0x00010000

+#define CSMI_SAS_CNTLR_FWD_ONLINE   0x00020000

+#define CSMI_SAS_CNTLR_FWD_SRESET   0x00040000

+#define CSMI_SAS_CNTLR_FWD_HRESET   0x00080000

+#define CSMI_SAS_CNTLR_FWD_RROM     0x00100000

+

+// Download Flag bits

+// (uDownloadFlags)

+#define CSMI_SAS_FWD_VALIDATE       0x00000001

+#define CSMI_SAS_FWD_SOFT_RESET     0x00000002

+#define CSMI_SAS_FWD_HARD_RESET     0x00000004

+

+// Firmware Download Status

+// (usStatus)

+#define CSMI_SAS_FWD_SUCCESS        0

+#define CSMI_SAS_FWD_FAILED         1

+#define CSMI_SAS_FWD_USING_RROM     2

+#define CSMI_SAS_FWD_REJECT         3

+#define CSMI_SAS_FWD_DOWNREV        4

+

+// Firmware Download Severity

+// (usSeverity>

+#define CSMI_SAS_FWD_INFORMATION    0

+#define CSMI_SAS_FWD_WARNING        1

+#define CSMI_SAS_FWD_ERROR          2

+#define CSMI_SAS_FWD_FATAL          3

+

+/* * * * * * * * * * SAS RAID Class IOCTL Constants  * * * * * * * * */

+

+// Return codes for the RAID IOCTL's regardless of class

+// (IoctlHeader.ControlCode)

+

+#define CSMI_SAS_RAID_SET_OUT_OF_RANGE       1000

+

+// Signature value

+// (IoctlHeader.Signature)

+

+#define CSMI_RAID_SIGNATURE    "CSMIARY"

+

+// Timeout value default of 60 seconds

+// (IoctlHeader.Timeout)

+

+#define CSMI_RAID_TIMEOUT      60

+

+// RAID Types

+// (bRaidType)

+#define CSMI_SAS_RAID_TYPE_NONE     0

+#define CSMI_SAS_RAID_TYPE_0        1

+#define CSMI_SAS_RAID_TYPE_1        2

+#define CSMI_SAS_RAID_TYPE_10       3

+#define CSMI_SAS_RAID_TYPE_5        4

+#define CSMI_SAS_RAID_TYPE_15       5

+#define CSMI_SAS_RAID_TYPE_OTHER    255

+

+// RAID Status

+// (bStatus)

+#define CSMI_SAS_RAID_SET_STATUS_OK          0

+#define CSMI_SAS_RAID_SET_STATUS_DEGRADED    1

+#define CSMI_SAS_RAID_SET_STATUS_REBUILDING  2

+#define CSMI_SAS_RAID_SET_STATUS_FAILED      3

+

+// RAID Drive Status

+// (bDriveStatus)

+#define CSMI_SAS_DRIVE_STATUS_OK          0

+#define CSMI_SAS_DRIVE_STATUS_REBUILDING  1

+#define CSMI_SAS_DRIVE_STATUS_FAILED      2

+#define CSMI_SAS_DRIVE_STATUS_DEGRADED    3

+

+// RAID Drive Usage

+// (bDriveUsage)

+#define CSMI_SAS_DRIVE_CONFIG_NOT_USED 0

+#define CSMI_SAS_DRIVE_CONFIG_MEMBER   1

+#define CSMI_SAS_DRIVE_CONFIG_SPARE    2

+

+/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */

+

+// Return codes for SAS IOCTL's

+// (IoctlHeader.ReturnCode)

+

+#define CSMI_SAS_PHY_INFO_CHANGED            CSMI_SAS_STATUS_SUCCESS

+#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE     2000

+#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE      2001

+

+#define CSMI_SAS_PHY_DOES_NOT_EXIST          2002

+#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT     2003

+#define CSMI_SAS_PHY_CANNOT_BE_SELECTED      2004

+#define CSMI_SAS_SELECT_PHY_OR_PORT          2005

+#define CSMI_SAS_PORT_DOES_NOT_EXIST         2006

+#define CSMI_SAS_PORT_CANNOT_BE_SELECTED     2007

+#define CSMI_SAS_CONNECTION_FAILED           2008

+

+#define CSMI_SAS_NO_SATA_DEVICE              2009

+#define CSMI_SAS_NO_SATA_SIGNATURE           2010

+#define CSMI_SAS_SCSI_EMULATION              2011

+#define CSMI_SAS_NOT_AN_END_DEVICE           2012

+#define CSMI_SAS_NO_SCSI_ADDRESS             2013

+#define CSMI_SAS_NO_DEVICE_ADDRESS           2014

+

+// Signature value

+// (IoctlHeader.Signature)

+

+#define CSMI_SAS_SIGNATURE    "CSMISAS"

+

+// Timeout value default of 60 seconds

+// (IoctlHeader.Timeout)

+

+#define CSMI_SAS_TIMEOUT      60

+

+// Device types

+// (bDeviceType)

+

+#define CSMI_SAS_PHY_UNUSED               0x00

+#define CSMI_SAS_NO_DEVICE_ATTACHED       0x00

+#define CSMI_SAS_END_DEVICE               0x10

+#define CSMI_SAS_EDGE_EXPANDER_DEVICE     0x20

+#define CSMI_SAS_FANOUT_EXPANDER_DEVICE   0x30

+

+// Protocol options

+// (bInitiatorPortProtocol, bTargetPortProtocol)

+

+#define CSMI_SAS_PROTOCOL_SATA   0x01

+#define CSMI_SAS_PROTOCOL_SMP    0x02

+#define CSMI_SAS_PROTOCOL_STP    0x04

+#define CSMI_SAS_PROTOCOL_SSP    0x08

+

+// Negotiated and hardware link rates

+// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate)

+

+#define CSMI_SAS_LINK_RATE_UNKNOWN  0x00

+#define CSMI_SAS_PHY_DISABLED       0x01

+#define CSMI_SAS_LINK_RATE_FAILED   0x02

+#define CSMI_SAS_SATA_SPINUP_HOLD   0x03

+#define CSMI_SAS_SATA_PORT_SELECTOR 0x04

+#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08

+#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09

+#define CSMI_SAS_LINK_VIRTUAL       0x10

+

+// Discover state

+// (bAutoDiscover)

+

+#define CSMI_SAS_DISCOVER_NOT_SUPPORTED   0x00

+#define CSMI_SAS_DISCOVER_NOT_STARTED     0x01

+#define CSMI_SAS_DISCOVER_IN_PROGRESS     0x02

+#define CSMI_SAS_DISCOVER_COMPLETE        0x03

+#define CSMI_SAS_DISCOVER_ERROR           0x04

+

+// Programmed link rates

+// (bMinimumLinkRate, bMaximumLinkRate)

+// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate)

+

+#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00

+#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS  0x08

+#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS  0x09

+

+// Link rate

+// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO)

+

+#define CSMI_SAS_LINK_RATE_NEGOTIATE      0x00

+#define CSMI_SAS_LINK_RATE_PHY_DISABLED   0x01

+

+// Signal class

+// (bSignalClass in CSMI_SAS_SET_PHY_INFO)

+

+#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN     0x00

+#define CSMI_SAS_SIGNAL_CLASS_DIRECT      0x01

+#define CSMI_SAS_SIGNAL_CLASS_SERVER      0x02

+#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE   0x03

+

+// Link error reset

+// (bResetCounts)

+

+#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS   0x00

+#define CSMI_SAS_LINK_ERROR_RESET_COUNTS        0x01

+

+// Phy identifier

+// (bPhyIdentifier)

+

+#define CSMI_SAS_USE_PORT_IDENTIFIER   0xFF

+

+// Port identifier

+// (bPortIdentifier)

+

+#define CSMI_SAS_IGNORE_PORT           0xFF

+

+// Programmed link rates

+// (bConnectionRate)

+

+#define CSMI_SAS_LINK_RATE_NEGOTIATED  0x00

+#define CSMI_SAS_LINK_RATE_1_5_GBPS    0x08

+#define CSMI_SAS_LINK_RATE_3_0_GBPS    0x09

+

+// Connection status

+// (bConnectionStatus)

+

+#define CSMI_SAS_OPEN_ACCEPT                          0

+#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION          1

+#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED       2

+#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION           3

+#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED          4

+#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED   5

+#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON          6

+#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE         7

+#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE       8

+#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP             9

+#define CSMI_SAS_OPEN_REJECT_RETRY                    10

+#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY       11

+#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION        12

+

+// SSP Status

+// (bSSPStatus)

+

+#define CSMI_SAS_SSP_STATUS_UNKNOWN     0x00

+#define CSMI_SAS_SSP_STATUS_WAITING     0x01

+#define CSMI_SAS_SSP_STATUS_COMPLETED   0x02

+#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03

+#define CSMI_SAS_SSP_STATUS_RETRY       0x04

+#define CSMI_SAS_SSP_STATUS_NO_TAG      0x05

+

+// SSP Flags

+// (uFlags)

+

+#define CSMI_SAS_SSP_READ           0x00000001

+#define CSMI_SAS_SSP_WRITE          0x00000002

+#define CSMI_SAS_SSP_UNSPECIFIED    0x00000004

+

+#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE         0x00000000

+#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE  0x00000010

+#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED        0x00000020

+#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA            0x00000040

+

+// SSP Data present

+// (bDataPresent)

+

+#define CSMI_SAS_SSP_NO_DATA_PRESENT         0x00

+#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT   0x01

+#define CSMI_SAS_SSP_SENSE_DATA_PRESENT      0x02

+

+// STP Flags

+// (uFlags)

+

+#define CSMI_SAS_STP_READ           0x00000001

+#define CSMI_SAS_STP_WRITE          0x00000002

+#define CSMI_SAS_STP_UNSPECIFIED    0x00000004

+#define CSMI_SAS_STP_PIO            0x00000010

+#define CSMI_SAS_STP_DMA            0x00000020

+#define CSMI_SAS_STP_PACKET         0x00000040

+#define CSMI_SAS_STP_DMA_QUEUED     0x00000080

+#define CSMI_SAS_STP_EXECUTE_DIAG   0x00000100

+#define CSMI_SAS_STP_RESET_DEVICE   0x00000200

+

+// Task Management Flags

+// (uFlags)

+

+#define CSMI_SAS_TASK_IU               0x00000001

+#define CSMI_SAS_HARD_RESET_SEQUENCE   0x00000002

+#define CSMI_SAS_SUPPRESS_RESULT       0x00000004

+

+// Task Management Functions

+// (bTaskManagement)

+

+#define CSMI_SAS_SSP_ABORT_TASK           0x01

+#define CSMI_SAS_SSP_ABORT_TASK_SET       0x02

+#define CSMI_SAS_SSP_CLEAR_TASK_SET       0x04

+#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET   0x08

+#define CSMI_SAS_SSP_CLEAR_ACA            0x40

+#define CSMI_SAS_SSP_QUERY_TASK           0x80

+

+// Task Management Information

+// (uInformation)

+

+#define CSMI_SAS_SSP_TEST           1

+#define CSMI_SAS_SSP_EXCEEDED       2

+#define CSMI_SAS_SSP_DEMAND         3

+#define CSMI_SAS_SSP_TRIGGER        4

+

+// Connector Pinout Information

+// (uPinout)

+

+#define CSMI_SAS_CON_UNKNOWN              0x00000001

+#define CSMI_SAS_CON_SFF_8482             0x00000002

+#define CSMI_SAS_CON_SFF_8470_LANE_1      0x00000100

+#define CSMI_SAS_CON_SFF_8470_LANE_2      0x00000200

+#define CSMI_SAS_CON_SFF_8470_LANE_3      0x00000400

+#define CSMI_SAS_CON_SFF_8470_LANE_4      0x00000800

+#define CSMI_SAS_CON_SFF_8484_LANE_1      0x00010000

+#define CSMI_SAS_CON_SFF_8484_LANE_2      0x00020000

+#define CSMI_SAS_CON_SFF_8484_LANE_3      0x00040000

+#define CSMI_SAS_CON_SFF_8484_LANE_4      0x00080000

+

+// Connector Location Information

+// (bLocation)

+

+// same as uPinout above...

+// #define CSMI_SAS_CON_UNKNOWN              0x01

+#define CSMI_SAS_CON_INTERNAL             0x02

+#define CSMI_SAS_CON_EXTERNAL             0x04

+#define CSMI_SAS_CON_SWITCHABLE           0x08

+#define CSMI_SAS_CON_AUTO                 0x10

+#define CSMI_SAS_CON_NOT_PRESENT          0x20

+#define CSMI_SAS_CON_NOT_CONNECTED        0x80

+

+// Device location identification

+// (bIdentify)

+

+#define CSMI_SAS_LOCATE_UNKNOWN           0x00

+#define CSMI_SAS_LOCATE_FORCE_OFF         0x01

+#define CSMI_SAS_LOCATE_FORCE_ON          0x02

+

+// Location Valid flags

+// (uLocationFlags)

+

+#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID           0x00000001

+#define CSMI_SAS_LOCATE_SAS_LUN_VALID               0x00000002

+#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID  0x00000004

+#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID        0x00000008

+#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID            0x00000010

+#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID        0x00000020

+#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID        0x00000040

+

+/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */

+

+// Return codes for SAS Phy Control IOCTL's

+// (IoctlHeader.ReturnCode)

+

+// Signature value

+// (IoctlHeader.Signature)

+

+#define CSMI_PHY_SIGNATURE    "CSMIPHY"

+

+// Phy Control Functions

+// (bFunction)

+

+// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL 

+// function defined in the SAS spec

+#define CSMI_SAS_PC_NOP                   0x00000000

+#define CSMI_SAS_PC_LINK_RESET            0x00000001

+#define CSMI_SAS_PC_HARD_RESET            0x00000002

+#define CSMI_SAS_PC_PHY_DISABLE           0x00000003

+// 0x04 to 0xFF reserved...

+#define CSMI_SAS_PC_GET_PHY_SETTINGS      0x00000100

+

+// Link Flags

+#define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001

+#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE   0x00000002

+#define CSMI_SAS_PHY_AUTO_COMWAKE         0x00000004

+

+// Device Types for Phy Settings

+// (bType)

+#define CSMI_SAS_UNDEFINED 0x00

+#define CSMI_SAS_SATA      0x01

+#define CSMI_SAS_SAS       0x02

+

+// Transmitter Flags

+// (uTransmitterFlags)

+#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED    0x00000001

+

+// Receiver Flags

+// (uReceiverFlags)

+#define CSMI_SAS_PHY_EQUALIZATION_DISABLED   0x00000001

+

+// Pattern Flags

+// (uPatternFlags)

+// #define CSMI_SAS_PHY_ACTIVATE_CONTROL     0x00000001

+#define CSMI_SAS_PHY_DISABLE_SCRAMBLING      0x00000002

+#define CSMI_SAS_PHY_DISABLE_ALIGN           0x00000004

+#define CSMI_SAS_PHY_DISABLE_SSC             0x00000008

+

+#define CSMI_SAS_PHY_FIXED_PATTERN           0x00000010

+#define CSMI_SAS_PHY_USER_PATTERN            0x00000020

+

+// Fixed Patterns

+// (bFixedPattern)

+#define CSMI_SAS_PHY_CJPAT                   0x00000001

+#define CSMI_SAS_PHY_ALIGN                   0x00000002

+

+// Type Flags

+// (bTypeFlags)

+#define CSMI_SAS_PHY_POSITIVE_DISPARITY      0x01

+#define CSMI_SAS_PHY_NEGATIVE_DISPARITY      0x02

+#define CSMI_SAS_PHY_CONTROL_CHARACTER       0x04

+

+// Miscellaneous

+#define SLOT_NUMBER_UNKNOWN   0xFFFF

+

+/*************************************************************************/

+/* DATA STRUCTURES                                                       */

+/*************************************************************************/

+

+/* * * * * * * * * * Class Independent Structures * * * * * * * * * */

+

+// EDM #pragma CSMI_SAS_BEGIN_PACK(8)

+#pragma pack(8)

+

+// CC_CSMI_SAS_DRIVER_INFO

+

+typedef struct _CSMI_SAS_DRIVER_INFO {

+   __u8  szName[81];

+   __u8  szDescription[81];

+   __u16 usMajorRevision;

+   __u16 usMinorRevision;

+   __u16 usBuildRevision;

+   __u16 usReleaseRevision;

+   __u16 usCSMIMajorRevision;

+   __u16 usCSMIMinorRevision;

+} CSMI_SAS_DRIVER_INFO,

+  *PCSMI_SAS_DRIVER_INFO;

+

+typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_DRIVER_INFO Information;

+} CSMI_SAS_DRIVER_INFO_BUFFER,

+  *PCSMI_SAS_DRIVER_INFO_BUFFER;

+

+// CC_CSMI_SAS_CNTLR_CONFIGURATION

+

+typedef struct _CSMI_SAS_PCI_BUS_ADDRESS {

+   __u8  bBusNumber;

+   __u8  bDeviceNumber;

+   __u8  bFunctionNumber;

+   __u8  bReserved;

+} CSMI_SAS_PCI_BUS_ADDRESS,

+  *PCSMI_SAS_PCI_BUS_ADDRESS;

+

+typedef union _CSMI_SAS_IO_BUS_ADDRESS {

+   CSMI_SAS_PCI_BUS_ADDRESS PciAddress;

+   __u8  bReserved[32];

+} CSMI_SAS_IO_BUS_ADDRESS,

+  *PCSMI_SAS_IO_BUS_ADDRESS;

+

+typedef struct _CSMI_SAS_CNTLR_CONFIG {

+   __u32 uBaseIoAddress;

+   struct {

+      __u32 uLowPart;

+      __u32 uHighPart;

+   } BaseMemoryAddress;

+   __u32 uBoardID;

+   __u16 usSlotNumber;

+   __u8  bControllerClass;

+   __u8  bIoBusType;

+   CSMI_SAS_IO_BUS_ADDRESS BusAddress;

+   __u8  szSerialNumber[81];

+   __u16 usMajorRevision;

+   __u16 usMinorRevision;

+   __u16 usBuildRevision;

+   __u16 usReleaseRevision;

+   __u16 usBIOSMajorRevision;

+   __u16 usBIOSMinorRevision;

+   __u16 usBIOSBuildRevision;

+   __u16 usBIOSReleaseRevision;

+   __u32 uControllerFlags;

+   __u16 usRromMajorRevision;

+   __u16 usRromMinorRevision;

+   __u16 usRromBuildRevision;

+   __u16 usRromReleaseRevision;

+   __u16 usRromBIOSMajorRevision;

+   __u16 usRromBIOSMinorRevision;

+   __u16 usRromBIOSBuildRevision;

+   __u16 usRromBIOSReleaseRevision;

+   __u8  bReserved[7];

+} CSMI_SAS_CNTLR_CONFIG,

+  *PCSMI_SAS_CNTLR_CONFIG;

+

+typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_CNTLR_CONFIG Configuration;

+} CSMI_SAS_CNTLR_CONFIG_BUFFER,

+  *PCSMI_SAS_CNTLR_CONFIG_BUFFER;

+

+// CC_CSMI_SAS_CNTLR_STATUS

+

+typedef struct _CSMI_SAS_CNTLR_STATUS {

+   __u32 uStatus;

+   __u32 uOfflineReason;

+   __u8  bReserved[28];

+} CSMI_SAS_CNTLR_STATUS,

+  *PCSMI_SAS_CNTLR_STATUS;

+

+typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_CNTLR_STATUS Status;

+} CSMI_SAS_CNTLR_STATUS_BUFFER,

+  *PCSMI_SAS_CNTLR_STATUS_BUFFER;

+

+// CC_CSMI_SAS_FIRMWARE_DOWNLOAD

+

+typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD {

+   __u32 uBufferLength;

+   __u32 uDownloadFlags;

+   __u8  bReserved[32];

+   __u16 usStatus;

+   __u16 usSeverity;

+} CSMI_SAS_FIRMWARE_DOWNLOAD,

+  *PCSMI_SAS_FIRMWARE_DOWNLOAD;

+

+typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_FIRMWARE_DOWNLOAD Information;

+   __u8  bDataBuffer[1];

+} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER,

+  *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER;

+

+// CC_CSMI_SAS_RAID_INFO

+

+typedef struct _CSMI_SAS_RAID_INFO {

+   __u32 uNumRaidSets;

+   __u32 uMaxDrivesPerSet;

+   __u8  bReserved[92];

+} CSMI_SAS_RAID_INFO,

+  *PCSMI_SAS_RAID_INFO;

+

+typedef struct _CSMI_SAS_RAID_INFO_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_RAID_INFO Information;

+} CSMI_SAS_RAID_INFO_BUFFER,

+  *PCSMI_SAS_RAID_INFO_BUFFER;

+

+// CC_CSMI_SAS_GET_RAID_CONFIG

+

+typedef struct _CSMI_SAS_RAID_DRIVES {

+   __u8  bModel[40];

+   __u8  bFirmware[8];

+   __u8  bSerialNumber[40];

+   __u8  bSASAddress[8];

+   __u8  bSASLun[8];

+   __u8  bDriveStatus;

+   __u8  bDriveUsage;

+   __u8  bReserved[30];

+} CSMI_SAS_RAID_DRIVES,

+   *PCSMI_SAS_RAID_DRIVES;

+

+typedef struct _CSMI_SAS_RAID_CONFIG {

+   __u32 uRaidSetIndex;

+   __u32 uCapacity;

+   __u32 uStripeSize;

+   __u8  bRaidType;

+   __u8  bStatus;

+   __u8  bInformation;

+   __u8  bDriveCount;

+   __u8  bReserved[20];

+   CSMI_SAS_RAID_DRIVES Drives[1];

+} CSMI_SAS_RAID_CONFIG,

+   *PCSMI_SAS_RAID_CONFIG;

+

+typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_RAID_CONFIG Configuration;

+} CSMI_SAS_RAID_CONFIG_BUFFER,

+  *PCSMI_SAS_RAID_CONFIG_BUFFER;

+

+

+/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */

+

+// CC_CSMI_SAS_GET_PHY_INFO

+

+typedef struct _CSMI_SAS_IDENTIFY {

+   __u8  bDeviceType;

+   __u8  bRestricted;

+   __u8  bInitiatorPortProtocol;

+   __u8  bTargetPortProtocol;

+   __u8  bRestricted2[8];

+   __u8  bSASAddress[8];

+   __u8  bPhyIdentifier;

+   __u8  bSignalClass;

+   __u8  bReserved[6];

+} CSMI_SAS_IDENTIFY,

+  *PCSMI_SAS_IDENTIFY;

+

+typedef struct _CSMI_SAS_PHY_ENTITY {

+   CSMI_SAS_IDENTIFY Identify;

+   __u8  bPortIdentifier;

+   __u8  bNegotiatedLinkRate;

+   __u8  bMinimumLinkRate;

+   __u8  bMaximumLinkRate;

+   __u8  bPhyChangeCount;

+   __u8  bAutoDiscover;

+   __u8  bReserved[2];

+   CSMI_SAS_IDENTIFY Attached;

+} CSMI_SAS_PHY_ENTITY,

+  *PCSMI_SAS_PHY_ENTITY;

+

+typedef struct _CSMI_SAS_PHY_INFO {

+   __u8  bNumberOfPhys;

+   __u8  bReserved[3];

+   CSMI_SAS_PHY_ENTITY Phy[32];

+} CSMI_SAS_PHY_INFO,

+  *PCSMI_SAS_PHY_INFO;

+

+typedef struct _CSMI_SAS_PHY_INFO_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_PHY_INFO Information;

+} CSMI_SAS_PHY_INFO_BUFFER,

+  *PCSMI_SAS_PHY_INFO_BUFFER;

+

+// CC_CSMI_SAS_SET_PHY_INFO

+

+typedef struct _CSMI_SAS_SET_PHY_INFO {

+   __u8  bPhyIdentifier;

+   __u8  bNegotiatedLinkRate;

+   __u8  bProgrammedMinimumLinkRate;

+   __u8  bProgrammedMaximumLinkRate;

+   __u8  bSignalClass;

+   __u8  bReserved[3];

+} CSMI_SAS_SET_PHY_INFO,

+  *PCSMI_SAS_SET_PHY_INFO;

+

+typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_SET_PHY_INFO Information;

+} CSMI_SAS_SET_PHY_INFO_BUFFER,

+  *PCSMI_SAS_SET_PHY_INFO_BUFFER;

+

+// CC_CSMI_SAS_GET_LINK_ERRORS

+

+typedef struct _CSMI_SAS_LINK_ERRORS {

+   __u8  bPhyIdentifier;

+   __u8  bResetCounts;

+   __u8  bReserved[2];

+   __u32 uInvalidDwordCount;

+   __u32 uRunningDisparityErrorCount;

+   __u32 uLossOfDwordSyncCount;

+   __u32 uPhyResetProblemCount;

+} CSMI_SAS_LINK_ERRORS,

+  *PCSMI_SAS_LINK_ERRORS;

+

+typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_LINK_ERRORS Information;

+} CSMI_SAS_LINK_ERRORS_BUFFER,

+  *PCSMI_SAS_LINK_ERRORS_BUFFER;

+

+// CC_CSMI_SAS_SMP_PASSTHRU

+

+typedef struct _CSMI_SAS_SMP_REQUEST {

+   __u8  bFrameType;

+   __u8  bFunction;

+   __u8  bReserved[2];

+   __u8  bAdditionalRequestBytes[1016];

+} CSMI_SAS_SMP_REQUEST,

+  *PCSMI_SAS_SMP_REQUEST;

+

+typedef struct _CSMI_SAS_SMP_RESPONSE {

+   __u8  bFrameType;

+   __u8  bFunction;

+   __u8  bFunctionResult;

+   __u8  bReserved;

+   __u8  bAdditionalResponseBytes[1016];

+} CSMI_SAS_SMP_RESPONSE,

+  *PCSMI_SAS_SMP_RESPONSE;

+

+typedef struct _CSMI_SAS_SMP_PASSTHRU {

+   __u8  bPhyIdentifier;

+   __u8  bPortIdentifier;

+   __u8  bConnectionRate;

+   __u8  bReserved;

+   __u8  bDestinationSASAddress[8];

+   __u32 uRequestLength;

+   CSMI_SAS_SMP_REQUEST Request;

+   __u8  bConnectionStatus;

+   __u8  bReserved2[3];

+   __u32 uResponseBytes;

+   CSMI_SAS_SMP_RESPONSE Response;

+} CSMI_SAS_SMP_PASSTHRU,

+  *PCSMI_SAS_SMP_PASSTHRU;

+

+typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_SMP_PASSTHRU Parameters;

+} CSMI_SAS_SMP_PASSTHRU_BUFFER,

+  *PCSMI_SAS_SMP_PASSTHRU_BUFFER;

+

+// CC_CSMI_SAS_SSP_PASSTHRU

+

+typedef struct _CSMI_SAS_SSP_PASSTHRU {

+   __u8  bPhyIdentifier;

+   __u8  bPortIdentifier;

+   __u8  bConnectionRate;

+   __u8  bReserved;

+   __u8  bDestinationSASAddress[8];

+   __u8  bLun[8];

+   __u8  bCDBLength;

+   __u8  bAdditionalCDBLength;

+   __u8  bReserved2[2];

+   __u8  bCDB[16];

+   __u32 uFlags;

+   __u8  bAdditionalCDB[24];

+   __u32 uDataLength;

+} CSMI_SAS_SSP_PASSTHRU,

+  *PCSMI_SAS_SSP_PASSTHRU;

+

+typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS {

+   __u8  bConnectionStatus;

+   __u8  bSSPStatus;

+   __u8  bReserved[2];

+   __u8  bDataPresent;

+   __u8  bStatus;

+   __u8  bResponseLength[2];

+   __u8  bResponse[256];

+   __u32 uDataBytes;

+} CSMI_SAS_SSP_PASSTHRU_STATUS,

+  *PCSMI_SAS_SSP_PASSTHRU_STATUS;

+

+typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_SSP_PASSTHRU Parameters;

+   CSMI_SAS_SSP_PASSTHRU_STATUS Status;

+   __u8  bDataBuffer[1];

+} CSMI_SAS_SSP_PASSTHRU_BUFFER,

+  *PCSMI_SAS_SSP_PASSTHRU_BUFFER;

+

+// CC_CSMI_SAS_STP_PASSTHRU

+

+typedef struct _CSMI_SAS_STP_PASSTHRU {

+   __u8  bPhyIdentifier;

+   __u8  bPortIdentifier;

+   __u8  bConnectionRate;

+   __u8  bReserved;

+   __u8  bDestinationSASAddress[8];

+   __u8  bReserved2[4];

+   __u8  bCommandFIS[20];

+   __u32 uFlags;

+   __u32 uDataLength;

+} CSMI_SAS_STP_PASSTHRU,

+  *PCSMI_SAS_STP_PASSTHRU;

+

+typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS {

+   __u8  bConnectionStatus;

+   __u8  bReserved[3];

+   __u8  bStatusFIS[20];

+   __u32 uSCR[16];

+   __u32 uDataBytes;

+} CSMI_SAS_STP_PASSTHRU_STATUS,

+  *PCSMI_SAS_STP_PASSTHRU_STATUS;

+

+typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_STP_PASSTHRU Parameters;

+   CSMI_SAS_STP_PASSTHRU_STATUS Status;

+   __u8  bDataBuffer[1];

+} CSMI_SAS_STP_PASSTHRU_BUFFER,

+  *PCSMI_SAS_STP_PASSTHRU_BUFFER;

+

+// CC_CSMI_SAS_GET_SATA_SIGNATURE

+

+typedef struct _CSMI_SAS_SATA_SIGNATURE {

+   __u8  bPhyIdentifier;

+   __u8  bReserved[3];

+   __u8  bSignatureFIS[20];

+} CSMI_SAS_SATA_SIGNATURE,

+  *PCSMI_SAS_SATA_SIGNATURE;

+

+typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_SATA_SIGNATURE Signature;

+} CSMI_SAS_SATA_SIGNATURE_BUFFER,

+  *PCSMI_SAS_SATA_SIGNATURE_BUFFER;

+

+// CC_CSMI_SAS_GET_SCSI_ADDRESS

+

+typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   __u8  bSASAddress[8];

+   __u8  bSASLun[8];

+   __u8  bHostIndex;

+   __u8  bPathId;

+   __u8  bTargetId;

+   __u8  bLun;

+} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER,

+   *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER;

+

+// CC_CSMI_SAS_GET_DEVICE_ADDRESS

+

+typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   __u8  bHostIndex;

+   __u8  bPathId;

+   __u8  bTargetId;

+   __u8  bLun;

+   __u8  bSASAddress[8];

+   __u8  bSASLun[8];

+} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER,

+  *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER;

+

+// CC_CSMI_SAS_TASK_MANAGEMENT

+

+typedef struct _CSMI_SAS_SSP_TASK_IU {

+   __u8  bHostIndex;

+   __u8  bPathId;

+   __u8  bTargetId;

+   __u8  bLun;

+   __u32 uFlags;

+   __u32 uQueueTag;

+   __u32 uReserved;

+   __u8  bTaskManagementFunction;

+   __u8  bReserved[7];

+   __u32 uInformation;

+} CSMI_SAS_SSP_TASK_IU,

+  *PCSMI_SAS_SSP_TASK_IU;

+

+typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_SSP_TASK_IU Parameters;

+   CSMI_SAS_SSP_PASSTHRU_STATUS Status;

+} CSMI_SAS_SSP_TASK_IU_BUFFER,

+  *PCSMI_SAS_SSP_TASK_IU_BUFFER;

+

+// CC_CSMI_SAS_GET_CONNECTOR_INFO

+

+typedef struct _CSMI_SAS_GET_CONNECTOR_INFO {

+   __u32 uPinout;

+   __u8  bConnector[16];

+   __u8  bLocation;

+   __u8  bReserved[15];

+} CSMI_SAS_CONNECTOR_INFO,

+  *PCSMI_SAS_CONNECTOR_INFO;

+

+typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   CSMI_SAS_CONNECTOR_INFO Reference[32];

+} CSMI_SAS_CONNECTOR_INFO_BUFFER,

+  *PCSMI_SAS_CONNECTOR_INFO_BUFFER;

+

+// CC_CSMI_SAS_GET_LOCATION

+

+typedef struct _CSMI_SAS_LOCATION_IDENTIFIER {

+   __u32 bLocationFlags;

+   __u8  bSASAddress[8];

+   __u8  bSASLun[8];

+   __u8  bEnclosureIdentifier[8];

+   __u8  bEnclosureName[32];

+   __u8  bBayPrefix[32];

+   __u8  bBayIdentifier;

+   __u8  bLocationState;

+   __u8  bReserved[2];

+} CSMI_SAS_LOCATION_IDENTIFIER,

+  *PCSMI_SAS_LOCATION_IDENTIFIER;

+

+typedef struct _CSMI_SAS_GET_LOCATION_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   __u8  bHostIndex;

+   __u8  bPathId;

+   __u8  bTargetId;

+   __u8  bLun;

+   __u8  bIdentify;

+   __u8  bNumberOfLocationIdentifiers;

+   __u8  bLengthOfLocationIdentifier;

+   CSMI_SAS_LOCATION_IDENTIFIER Location[1];

+} CSMI_SAS_GET_LOCATION_BUFFER,

+  *PCSMI_SAS_GET_LOCATION_BUFFER;

+

+// CC_CSMI_SAS_PHY_CONTROL

+

+typedef struct _CSMI_SAS_CHARACTER {

+   __u8  bTypeFlags;

+   __u8  bValue;

+} CSMI_SAS_CHARACTER,

+  *PCSMI_SAS_CHARACTER;

+

+typedef struct _CSMI_SAS_PHY_CONTROL {

+   __u8  bType;

+   __u8  bRate;

+   __u8  bReserved[6];

+   __u32 uVendorUnique[8];

+   __u32 uTransmitterFlags;

+   __i8  bTransmitAmplitude;

+   __i8  bTransmitterPreemphasis;

+   __i8  bTransmitterSlewRate;

+   __i8  bTransmitterReserved[13];

+   __u8  bTransmitterVendorUnique[64];

+   __u32 uReceiverFlags;

+   __i8  bReceiverThreshold;

+   __i8  bReceiverEqualizationGain;

+   __i8  bReceiverReserved[14];

+   __u8  bReceiverVendorUnique[64];

+   __u32 uPatternFlags;

+   __u8  bFixedPattern;

+   __u8  bUserPatternLength;

+   __u8  bPatternReserved[6];

+   CSMI_SAS_CHARACTER UserPatternBuffer[16];

+} CSMI_SAS_PHY_CONTROL,

+  *PCSMI_SAS_PHY_CONTROL;

+

+typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER {

+   IOCTL_HEADER IoctlHeader;

+   __u32 uFunction;

+   __u8  bPhyIdentifier;

+   __u16 usLengthOfControl;

+   __u8  bNumberOfControls;

+   __u8  bReserved[4];

+   __u32 uLinkFlags;

+   __u8  bSpinupRate;

+   __u8  bLinkReserved[7];

+   __u32 uVendorUnique[8];

+   CSMI_SAS_PHY_CONTROL Control[1];

+} CSMI_SAS_PHY_CONTROL_BUFFER,

+  *PCSMI_SAS_PHY_CONTROL_BUFFER;

+

+// EDM #pragma CSMI_SAS_END_PACK

+#pragma pack()

+

+#endif // _CSMI_SAS_H_

diff --git a/drivers/scsi/thor/include/generic/com_define.h b/drivers/scsi/thor/include/generic/com_define.h
new file mode 100755
index 0000000..8463cbe
--- /dev/null
+++ b/drivers/scsi/thor/include/generic/com_define.h
@@ -0,0 +1,345 @@
+#ifndef COM_DEFINE_H

+#define COM_DEFINE_H

+

+/*

+ *  This file defines Marvell OS independent primary data type for all OS.

+ *

+ *  We have macros to differentiate different CPU and OS.

+ *

+ *  CPU definitions:

+ *  _CPU_X86_16B  

+ *  Specify 16bit x86 platform, this is used for BIOS and DOS utility.

+ *  _CPU_X86_32B

+ *  Specify 32bit x86 platform, this is used for most OS drivers.

+ *  _CPU_IA_64B

+ *  Specify 64bit IA64 platform, this is used for IA64 OS drivers.

+ *  _CPU_AMD_64B

+ *  Specify 64bit AMD64 platform, this is used for AMD64 OS drivers.

+ *

+ *  OS definitions:

+ *  _OS_WINDOWS

+ *  _OS_LINUX

+ *  _OS_FREEBSD

+ *  _OS_BIOS

+ *  __QNXNTO__

+ */

+ 

+

+#include "mv_os.h"

+

+#if !defined(IN)

+#   define IN

+#endif

+

+#if !defined(OUT)

+#   define OUT

+#endif

+

+#if defined(_OS_LINUX) || defined(__QNXNTO__)

+#   define    BUFFER_PACKED               __attribute__((packed))

+#elif defined(_OS_WINDOWS)

+#   define    BUFFER_PACKED

+#elif defined(_OS_BIOS)

+#   define    BUFFER_PACKED

+#endif /* defined(_OS_LINUX) || defined(__QNXNTO__) */

+

+#define MV_BIT(x)                         (1L << (x))

+

+#if !defined(NULL)

+#   define NULL 0

+#endif  /* NULL */

+

+#define MV_TRUE                           1

+#define MV_FALSE                          0

+

+typedef unsigned char  MV_BOOLEAN, *MV_PBOOLEAN;

+typedef unsigned char  MV_U8, *MV_PU8;

+typedef signed char  MV_I8, *MV_PI8;

+

+typedef unsigned short  MV_U16, *MV_PU16;

+typedef signed short  MV_I16, *MV_PI16;

+

+typedef void    MV_VOID, *MV_PVOID;

+

+#ifdef _OS_BIOS

+    typedef MV_U8 GEN_FAR*  MV_LPU8;

+    typedef MV_I8 GEN_FAR*  MV_LPI8;

+    typedef MV_U16 GEN_FAR* MV_LPU16;

+    typedef MV_I16 GEN_FAR* MV_LPI16;

+

+    typedef MV_U32 GEN_FAR* MV_LPU32;

+    typedef MV_I32 GEN_FAR* MV_LPI32;

+    typedef void GEN_FAR*   MV_LPVOID;

+#else

+    typedef void            *MV_LPVOID;

+#endif /* _OS_BIOS */

+

+/* Pre-define segment in C code*/

+#if defined(_OS_BIOS)

+#   define BASEATTR         __based(__segname("_CODE")) 

+#   define BASEATTRData     __based(__segname("_CODE")) 

+#else

+#   define BASEATTR 

+#endif /* _OS_BIOS */

+

+#ifdef DEBUG_COM_SPECIAL

+	#define MV_DUMP_COM_SPECIAL(pString)  						{bDbgPrintStr(pString);bCOMEnter();}

+	#define MV_DUMP32_COM_SPECIAL(pString, value) 				bDbgPrintStr_U32(pString, value)

+	#define MV_DUMP16_COM_SPECIAL(pString, value)  				bDbgPrintStr_U16(pString, value)

+	#define MV_DUMP32_COM_SPECIAL3(pString, value1, value2)  	bDbgPrintStr_U32_3(pString, value1, value2)

+	#define MV_DUMP8_COM_SPECIAL(pString, value)  				bDbgPrintStr_U8(pString, value)	

+	#define MV_HALTKEY_SPECIAL									waitForKeystroke()

+

+#else

+	#define MV_DUMP_COM_SPECIAL(pString)  						

+	#define MV_DUMP32_COM_SPECIAL(pString, value) 				

+	#define MV_DUMP16_COM_SPECIAL(pString, value)  				

+	#define MV_DUMP32_COM_SPECIAL3(pString, value1, value2)  	

+	#define MV_DUMP8_COM_SPECIAL(pString, value)  				

+	#define MV_HALTKEY_SPECIAL									

+#endif

+/* For debug version only */

+#ifdef DEBUG_BIOS

+ #ifdef DEBUG_SHOW_ALL

+	#define MV_DUMP32(_x_) 		{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMP16(_x_)  	{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMP8(_x_)  		{mvDebugDumpU8(_x_);bCOMEnter();}

+	#define MV_DUMPC32(_x_)  	{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMPC16(_x_)  	{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMPC8(_x_)  	{mvDebugDumpU8(_x_);bCOMEnter();}

+	#define MV_DUMPE32(_x_) 	{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMPE16(_x_) 	{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMPE8(_x_)  	{mvDebugDumpU8(_x_);bCOMEnter();}

+ 	#define MV_DUMP_COM(pString)  						{bDbgPrintStr(pString);bCOMEnter();}

+	#define MV_DUMP32_COM(pString, value) 				bDbgPrintStr_U32(pString, value)

+	#define MV_DUMP16_COM(pString, value)  				bDbgPrintStr_U16(pString, value)

+	#define MV_DUMP32_COM3(pString, value1, value2)  	bDbgPrintStr_U32_3(pString, value1, value2)

+	#define MV_DUMP8_COM(pString, value)  				bDbgPrintStr_U8(pString, value)

+ #else

+	#define MV_DUMP32(_x_) 		//{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMP16(_x_)  	//{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMP8(_x_)  		//{mvDebugDumpU8(_x_);bCOMEnter();}

+	#define MV_DUMPC32(_x_)  	//{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMPC16(_x_)  	//{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMPC8(_x_)  	//{mvDebugDumpU8(_x_);bCOMEnter();}

+	#define MV_DUMPE32(_x_) 	//{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMPE16(_x_) 	//{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMPE8(_x_)  	//{mvDebugDumpU8(_x_);bCOMEnter();}

+ 	#define MV_DUMP_COM(pString)  						//{bDbgPrintStr(pString);bCOMEnter();}

+	#define MV_DUMP32_COM(pString, value) 				//bDbgPrintStr_U32(pString, value)

+	#define MV_DUMP16_COM(pString, value)  				//bDbgPrintStr_U16(pString, value)

+	#define MV_DUMP32_COM3(pString, value1, value2)  	//bDbgPrintStr_U32_3(pString, value1, value2)

+	#define MV_DUMP8_COM(pString, value)  				//bDbgPrintStr_U8(pString, value)

+ 

+ #endif

+ 

+	#define MV_BIOSDEBUG(pString, value)				bDbgPrintStr_U32(pString, value)				

+	#define MV_HALTKEY			waitForKeystroke()

+	#define MV_ENTERLINE		//mvChangLine()

+#else

+	#define MV_DUMP32(_x_) 		//{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMP16(_x_)  	//{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMP8(_x_)  		//{mvDebugDumpU8(_x_);bCOMEnter();}

+	#define MV_DUMPC32(_x_)  	//{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMPC16(_x_)  	//{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMPC8(_x_)  	//{mvDebugDumpU8(_x_);bCOMEnter();}

+	#define MV_DUMPE32(_x_) 	//{mvDebugDumpU32(_x_);bCOMEnter();}

+	#define MV_DUMPE16(_x_) 	//{mvDebugDumpU16(_x_);bCOMEnter();}

+	#define MV_DUMPE8(_x_)  	//{mvDebugDumpU8(_x_);bCOMEnter();}

+ 	#define MV_DUMP_COM(pString)  						//{bDbgPrintStr(pString);bCOMEnter();}

+	#define MV_DUMP32_COM(pString, value) 				//bDbgPrintStr_U32(pString, value)

+	#define MV_DUMP16_COM(pString, value)  				//bDbgPrintStr_U16(pString, value)

+	#define MV_DUMP32_COM3(pString, value1, value2)  	//bDbgPrintStr_U32_3(pString, value1, value2)

+	#define MV_DUMP8_COM(pString, value)  				//bDbgPrintStr_U8(pString, value)

+

+	#define MV_BIOSDEBUG(pString, value)

+	#define MV_HALTKEY

+	#define MV_ENTERLINE

+	

+#endif

+

+#if defined(_OS_LINUX) || defined(__QNXNTO__)

+    /* unsigned/signed long is 64bit for AMD64, so use unsigned int instead */

+    typedef unsigned int MV_U32, *MV_PU32;

+    typedef   signed int MV_I32, *MV_PI32;

+    typedef unsigned long MV_ULONG, *MV_PULONG;

+    typedef   signed long MV_ILONG, *MV_PILONG;

+#else

+    /* unsigned/signed long is 32bit for x86, IA64 and AMD64 */

+    typedef unsigned long MV_U32, *MV_PU32;

+    typedef   signed long MV_I32, *MV_PI32;

+#endif /*  defined(_OS_LINUX) || defined(__QNXNTO__) */

+

+#if defined(_OS_WINDOWS)

+    typedef unsigned __int64 _MV_U64;

+    typedef   signed __int64 _MV_I64;

+#elif defined(_OS_LINUX) || defined(__QNXNTO__)

+    typedef unsigned long long _MV_U64;

+    typedef   signed long long _MV_I64;

+#elif defined(_OS_FREEBSD)

+#   error "No Where"

+#else

+#   error "No Where"

+#endif /* _OS_WINDOWS */

+

+typedef _MV_U64 BUS_ADDRESS;

+

+#ifdef _OS_LINUX

+#   if defined(__KCONF_64BIT__)

+#      define _SUPPORT_64_BIT

+#   else

+#      ifdef _SUPPORT_64_BIT

+#         error Error 64_BIT CPU Macro

+#      endif

+#   endif /* defined(__KCONF_64BIT__) */

+#elif defined(_OS_BIOS) || defined(__QNXNTO__)

+#   undef  _SUPPORT_64_BIT

+#else

+#   define _SUPPORT_64_BIT

+#endif /* _OS_LINUX */

+

+/*

+ * Primary Data Type

+ */

+#if defined(_OS_WINDOWS)

+    typedef union {

+        struct {

+            MV_U32 low;

+            MV_U32 high;

+        } parts;

+        _MV_U64 value;

+    } MV_U64, *PMV_U64, *MV_PU64;

+#elif defined(_OS_LINUX) || defined(__QNXNTO__)

+    typedef union {

+        struct {

+#   if defined (__MV_LITTLE_ENDIAN__)

+            MV_U32 low;

+            MV_U32 high;

+#   elif defined (__MV_BIG_ENDIAN__)

+            MV_U32 high;

+            MV_U32 low;

+#   else

+#           error "undefined endianness"

+#   endif /* __MV_LITTLE_ENDIAN__ */

+        } parts;

+        _MV_U64 value;

+    } MV_U64, *PMV_U64, *MV_PU64;

+#else

+/* BIOS compiler doesn't support 64 bit data structure. */

+    typedef union {

+        struct {

+             MV_U32 low;

+             MV_U32 high;

+        };

+        struct {

+             MV_U32 value;

+             MV_U32 value1;

+        };

+    } _MV_U64,MV_U64, *MV_PU64, *PMV_U64;

+#endif /* defined(_OS_LINUX) || defined(_OS_WINDOWS) || defined(__QNXNTO__)*/

+

+/* PTR_INTEGER is necessary to convert between pointer and integer. */

+#if defined(_SUPPORT_64_BIT)

+   typedef _MV_U64 MV_PTR_INTEGER;

+#else

+   typedef MV_U32 MV_PTR_INTEGER;

+#endif /* defined(_SUPPORT_64_BIT) */

+

+/* LBA is the logical block access */

+typedef MV_U64 MV_LBA;

+

+#if defined(_CPU_16B)

+    typedef MV_U32 MV_PHYSICAL_ADDR;

+#else

+    typedef MV_U64 MV_PHYSICAL_ADDR;

+#endif /* defined(_CPU_16B) */

+

+#if defined (_OS_WINDOWS)

+typedef PVOID MV_FILE_HANDLE;

+#elif defined(_OS_LINUX) || defined(__QNXNTO__)

+typedef MV_I32 MV_FILE_HANDLE;

+#endif

+

+/* Product device id */

+#define VENDOR_ID					0x11AB

+

+#define DEVICE_ID_THORLITE_2S1P				0x6121

+#define DEVICE_ID_THORLITE_0S1P				0x6101

+#define DEVICE_ID_THORLITE_1S1P				0x6111

+#define DEVICE_ID_THOR_4S1P				0x6141

+#define DEVICE_ID_THOR_4S1P_NEW				0x6145

+/* Revision ID starts from B1 */

+#define DEVICE_ID_THORLITE_2S1P_WITH_FLASH              0x6122

+

+ /* Odin lite version */

+#define DEVICE_ID_6320					0x6320

+#define DEVICE_ID_6340					0x6340 

+

+/* mule-board */

+#define DEVICE_ID_6440					0x6440

+

+/* Non-RAID Odin */

+#define DEVICE_ID_6445					0x6445

+

+/* mule-board */

+#define DEVICE_ID_6480					0x6480

+#define DEVICE_ID_UNKNOWN				0xFFFF

+

+

+/* OS_LINUX depedent definition*/

+

+#if defined(_OS_LINUX) || defined(__QNXNTO__)

+/* os-dependent data structures */

+#define OSSW_DECLARE_SPINLOCK(x)  spinlock_t x

+#define OSSW_DECLARE_TIMER(x)   struct timer_list x

+#define MV_DECLARE_TIMER(x)   struct timer_list x

+/* expect pointers */

+#define OSSW_INIT_SPIN_LOCK(plock) spin_lock_init(plock)

+

+#define OSSW_SPIN_LOCK_IRQ(plock)            \

+             do {                            \

+	              spin_lock_irq(plock);  \

+             } while (0)

+

+#define OSSW_SPIN_UNLOCK_IRQ(plock)           \

+             do {                             \

+	              spin_unlock_irq(plock); \

+             } while (0)

+

+#define OSSW_SPIN_LOCK_IRQSAVE(plock, flag)           \

+             do {                                     \

+	             spin_lock_irqsave(plock, flag);  \

+             } while (0)

+

+#define OSSW_SPIN_UNLOCK_IRQRESTORE(plock, flag)           \

+             do {                                          \

+	             spin_unlock_irqrestore(plock, flag);  \

+             } while (0)

+

+

+/* Delayed Execution Services */

+#define OSSW_INIT_TIMER(ptimer) init_timer(ptimer)

+

+

+#else

+

+#define OSSW_DECLARE_SPINLOCK(x)  

+#define OSSW_DECLARE_TIMER(x)  

+#define MV_DECLARE_TIMER(x)   

+/* expect pointers */

+#define OSSW_INIT_SPIN_LOCK(plock) 

+

+#define OSSW_SPIN_LOCK_IRQ(plock)           

+

+#define OSSW_SPIN_UNLOCK_IRQ(plock)           

+

+#define OSSW_SPIN_LOCK_IRQSAVE(plock, flag)          

+

+#define OSSW_SPIN_UNLOCK_IRQRESTORE(plock, flag)           

+

+/* Delayed Execution Services */

+#define OSSW_INIT_TIMER(ptimer) 

+

+#endif

+

+#endif /* COM_DEFINE_H */

diff --git a/drivers/scsi/thor/include/generic/com_error.h b/drivers/scsi/thor/include/generic/com_error.h
new file mode 100755
index 0000000..83e45e1
--- /dev/null
+++ b/drivers/scsi/thor/include/generic/com_error.h
@@ -0,0 +1,61 @@
+#ifndef __COM_ERROR_H__

+#define __COM_ERROR_H__

+#define ERR_GENERIC                              2

+#define ERR_RAID                                 50

+#define ERR_CORE                                 100

+#define ERR_API                                  150

+

+#define ERR_NONE                                 0

+#define ERR_FAIL                                 1

+/* generic error */

+#define ERR_UNKNOWN                              (ERR_GENERIC + 1)

+#define ERR_NO_RESOURCE                          (ERR_GENERIC + 2)

+#define ERR_REQ_OUT_OF_RANGE                     (ERR_GENERIC + 3)

+#define ERR_INVALID_REQUEST                      (ERR_GENERIC + 4)

+#define ERR_INVALID_PARAMETER                    (ERR_GENERIC + 5)

+#define ERR_INVALID_LD_ID                        (ERR_GENERIC + 6)

+#define ERR_INVALID_HD_ID                        (ERR_GENERIC + 7)

+#define ERR_INVALID_EXP_ID                       (ERR_GENERIC + 8)

+#define ERR_INVALID_PM_ID                        (ERR_GENERIC + 9)

+#define ERR_INVALID_BLOCK_ID                     (ERR_GENERIC + 10)

+#define ERR_INVALID_ADAPTER_ID                   (ERR_GENERIC + 11)

+#define ERR_INVALID_RAID_MODE                    (ERR_GENERIC + 12)

+

+/* RAID errors */

+#define ERR_TARGET_IN_LD_FUNCTIONAL              (ERR_RAID + 1)

+#define ERR_TARGET_NO_ENOUGH_SPACE               (ERR_RAID + 2)

+#define ERR_HD_IS_NOT_SPARE                      (ERR_RAID + 3)

+#define ERR_HD_IS_SPARE                          (ERR_RAID + 4)

+#define ERR_HD_NOT_EXIST                         (ERR_RAID + 5)

+#define ERR_HD_IS_ASSIGNED_ALREADY               (ERR_RAID + 6)

+#define ERR_INVALID_HD_COUNT                     (ERR_RAID + 7)

+#define ERR_LD_NOT_READY                         (ERR_RAID + 8)

+#define ERR_LD_NOT_EXIST                         (ERR_RAID + 9)

+#define ERR_LD_IS_FUNCTIONAL                     (ERR_RAID + 10)

+#define ERR_HAS_BGA_ACTIVITY                     (ERR_RAID + 11)

+#define ERR_NO_BGA_ACTIVITY                      (ERR_RAID + 12)

+#define ERR_BGA_RUNNING                          (ERR_RAID + 13)

+#define ERR_RAID_NO_AVAILABLE_ID                 (ERR_RAID + 14)

+#define ERR_LD_NO_ATAPI                          (ERR_RAID + 15)

+#define ERR_INVALID_RAID6_PARITY_DISK_COUNT      (ERR_RAID + 16)

+#define ERR_INVALID_BLOCK_SIZE                   (ERR_RAID + 17)

+#define ERR_MIGRATION_NOT_NEED                   (ERR_RAID + 18)

+#define ERR_STRIPE_BLOCK_SIZE_MISMATCH           (ERR_RAID + 19)

+#define ERR_MIGRATION_NOT_SUPPORT                (ERR_RAID + 20)

+#define ERR_LD_NOT_FULLY_INITED                  (ERR_RAID + 21)

+#define ERR_LD_NAME_INVALID	                     (ERR_RAID + 22)

+

+/* API errors */

+#define ERR_INVALID_MATCH_ID                     (ERR_API + 1)    

+#define ERR_INVALID_HDCOUNT                      (ERR_API + 2)

+#define ERR_INVALID_BGA_ACTION                   (ERR_API + 3)

+#define ERR_HD_IN_DIFF_CARD                      (ERR_API + 4)

+#define ERR_INVALID_FLASH_TYPE                   (ERR_API + 5)

+#define ERR_INVALID_FLASH_ACTION                 (ERR_API + 6)

+#define ERR_TOO_FEW_EVENT                        (ERR_API + 7)

+#define ERR_VD_HAS_RUNNING_OS                    (ERR_API + 8)

+#define ERR_DISK_HAS_RUNNING_OS                  (ERR_API + 9)

+#define ERR_COMMAND_NOT_SUPPURT                  (ERR_API + 10)

+#define ERR_MIGRATION_LIMIT	                     (ERR_API + 11)

+

+#endif /*  __COM_ERROR_H__ */

diff --git a/drivers/scsi/thor/include/generic/com_event_define.h b/drivers/scsi/thor/include/generic/com_event_define.h
new file mode 100755
index 0000000..9619ff2
--- /dev/null
+++ b/drivers/scsi/thor/include/generic/com_event_define.h
@@ -0,0 +1,353 @@
+#ifndef COM_EVENT_DEFINE_H

+#define COM_EVENT_DEFINE_H

+

+/****************************************

+ *         Perceived Severity

+ ****************************************/

+

+#define SEVERITY_UNKNOWN    0

+#define SEVERITY_OTHER      1

+#define SEVERITY_INFO       2

+#define SEVERITY_WARNING    3  /* used when its appropriate to let the 

+				  user decide if action is needed */

+#define SEVERITY_MINOR      4  /* indicate action is needed, but the 

+				  situation is not serious at this time */  

+#define SEVERITY_MAJOR      5  /* indicate action is needed NOW */

+#define SEVERITY_CRITICAL   6  /* indicate action is needed NOW and the 

+				  scope is broad */

+#define SEVERITY_FATAL      7  /* indicate an error occurred, but it's too

+				  late to take remedial action */

+

+/****************************************

+ *             Event Classes

+ ****************************************/

+#define EVT_CLASS_ADAPTER   0

+#define EVT_CLASS_LD        1  /* Logical Drive */

+#define EVT_CLASS_HD        2  /* Hard Drive */

+#define EVT_CLASS_PM        3  /* Port Multplier */

+#define EVT_CLASS_EXPANDER  4

+#define EVT_CLASS_MDD       5 

+#define EVT_CLASS_BSL       6  /* Bad Sector Lock */

+

+/********************************************************

+ *                 Event Codes 

+ *

+ *  !!!  When adding an EVT_CODE, Please put its severity level

+ *  !!!  and suggested mesage string as comments.  This is the 

+ *  !!!  only place to document how 'Params' in 'DriverEvent' 

+ *  !!!  structure is to be used.

+ *

+ ********************************************************/

+

+/* Event code for EVT_CLASS_LD (Logical Drive) */

+#define EVT_CODE_LD_OFFLINE                0

+#define EVT_CODE_LD_ONLINE                 1

+#define EVT_CODE_LD_CREATE                 2

+#define EVT_CODE_LD_DELETE                 3

+#define EVT_CODE_LD_DEGRADE                4

+#define EVT_CODE_LD_PARTIALLYOPTIMAL       5

+#define EVT_CODE_LD_CACHE_MODE_CHANGE      6

+#define EVT_CODE_LD_FIXED                  7

+#define EVT_CODE_LD_FOUND_ERROR            8

+#define EVT_CODE_LD_RESERVED1              9

+#define EVT_CODE_LD_RESERVED2              10

+#define EVT_CODE_LD_RESERVED3              11

+#define EVT_CODE_LD_RESERVED4              12

+#define EVT_CODE_LD_RESERVED5              13

+#define EVT_CODE_LD_RESERVED6              14

+#define EVT_CODE_LD_RESERVED7              15

+#define EVT_CODE_LD_RESERVED8              16

+#define EVT_CODE_LD_RESERVED9              17

+#define EVT_CODE_LD_RESERVED10             18

+#define EVT_CODE_LD_RESERVED11             19

+/*

+ *  NOTE: Don't change the following event code order in each event group! 

+ *      See raid_get_bga_event_id() for detail. 

+ */

+#define EVT_CODE_LD_CHECK_START            20 

+#define EVT_CODE_LD_CHECK_RESTART          21 

+#define EVT_CODE_LD_CHECK_PAUSE            22 

+#define EVT_CODE_LD_CHECK_RESUME           23 

+#define EVT_CODE_LD_CHECK_ABORT            24 

+#define EVT_CODE_LD_CHECK_COMPLETE         25 

+#define EVT_CODE_LD_CHECK_PROGRESS         26  

+#define EVT_CODE_LD_CHECK_ERROR            27 

+#define EVT_CODE_LD_CHECK_AUTO_PAUSED      28 

+#define EVT_CODE_LD_CHECK_AUTO_RESUME      29 

+

+#define EVT_CODE_LD_FIX_START              30 

+#define EVT_CODE_LD_FIX_RESTART            31 

+#define EVT_CODE_LD_FIX_PAUSE              32 

+#define EVT_CODE_LD_FIX_RESUME             33 

+#define EVT_CODE_LD_FIX_ABORT              34 

+#define EVT_CODE_LD_FIX_COMPLETE           35 

+#define EVT_CODE_LD_FIX_PROGRESS           36 

+#define EVT_CODE_LD_FIX_ERROR              37

+#define EVT_CODE_LD_FIX_AUTO_PAUSED        38 

+#define EVT_CODE_LD_FIX_AUTO_RESUME        39 

+

+#define EVT_CODE_LD_INIT_QUICK_START       40

+#define EVT_CODE_LD_INIT_QUICK_RESTART     41    

+#define EVT_CODE_LD_INIT_QUICK_PAUSE       42    

+#define EVT_CODE_LD_INIT_QUICK_RESUME      43    

+#define EVT_CODE_LD_INIT_QUICK_ABORT       44    

+#define EVT_CODE_LD_INIT_QUICK_COMPLETE    45    

+#define EVT_CODE_LD_INIT_QUICK_PROGRESS    46  

+#define EVT_CODE_LD_INIT_QUICK_ERROR       47   

+#define EVT_CODE_LD_INIT_QUICK_AUTO_PAUSED 48

+#define EVT_CODE_LD_INIT_QUICK_AUTO_RESUME 49 

+

+#define EVT_CODE_LD_INIT_BACK_START        50

+#define EVT_CODE_LD_INIT_BACK_RESTART      51

+#define EVT_CODE_LD_INIT_BACK_PAUSE        52

+#define EVT_CODE_LD_INIT_BACK_RESUME       53

+#define EVT_CODE_LD_INIT_BACK_ABORT        54

+#define EVT_CODE_LD_INIT_BACK_COMPLETE     55

+#define EVT_CODE_LD_INIT_BACK_PROGRESS     56

+#define EVT_CODE_LD_INIT_BACK_ERROR        57

+#define EVT_CODE_LD_INIT_BACK_AUTO_PAUSED  58  

+#define EVT_CODE_LD_INIT_BACK_AUTO_RESUME  59 

+

+#if 0

+#define EVT_CODE_LD_INIT_FORE_START        60

+#define EVT_CODE_LD_INIT_FORE_RESTART      61  

+#define EVT_CODE_LD_INIT_FORE_PAUSE        62

+#define EVT_CODE_LD_INIT_FORE_RESUME       63   

+#define EVT_CODE_LD_INIT_FORE_ABORT        64

+#define EVT_CODE_LD_INIT_FORE_COMPLETE     65 

+#define EVT_CODE_LD_INIT_FORE_PROGRESS     66 

+#define EVT_CODE_LD_INIT_FORE_ERROR        67

+#define EVT_CODE_LD_INIT_FORE_AUTO_PAUSED  68 

+#define EVT_CODE_LD_INIT_FORE_AUTO_RESUME  69 

+#endif

+

+#define EVT_CODE_LD_REBUILD_START          70 

+#define EVT_CODE_LD_REBUILD_RESTART        71 

+#define EVT_CODE_LD_REBUILD_PAUSE          72 

+#define EVT_CODE_LD_REBUILD_RESUME         73 

+#define EVT_CODE_LD_REBUILD_ABORT          74 

+#define EVT_CODE_LD_REBUILD_COMPLETE       75 

+#define EVT_CODE_LD_REBUILD_PROGRESS       76 

+#define EVT_CODE_LD_REBUILD_ERROR          77 

+#define EVT_CODE_LD_REBUILD_AUTO_PAUSED    78 

+#define EVT_CODE_LD_REBUILD_AUTO_RESUME	   79 

+

+#define EVT_CODE_LD_MIGRATION_START        80 

+#define EVT_CODE_LD_MIGRATION_RESTART      81 

+#define EVT_CODE_LD_MIGRATION_PAUSE        82 

+#define EVT_CODE_LD_MIGRATION_RESUME       83 

+#define EVT_CODE_LD_MIGRATION_ABORT        84 

+#define EVT_CODE_LD_MIGRATION_COMPLETE     85 

+#define EVT_CODE_LD_MIGRATION_PROGRESS     86

+#define EVT_CODE_LD_MIGRATION_ERROR        87 

+#define EVT_CODE_LD_MIGRATION_AUTO_PAUSED  88 

+#define EVT_CODE_LD_MIGRATION_AUTO_RESUME  89 

+

+/* event code for logging inconsistent LBA found in consistency check or synchronization fix */

+#define EVT_CODE_LD_INCONSISTENT_LBA       90

+

+/* only used in application */

+#define EVT_CODE_EVT_ERR                   0xffff

+#define EVT_CODE_SMART_FROM_OFF_TO_ON	   0  // SMART setting is changed from OFF-->ON

+#define EVT_CODE_SMART_FROM_ON_TO_OFF	   1  // SMART setting is changed from ON-->OFF

+#define EVT_CODE_ALARM_TURN_ON			   2			 

+#define EVT_CODE_ALARM_TURN_OFF			   3

+#define EVT_CODE_AUTO_REBUILD_ON		   4	

+#define EVT_CODE_AUTO_REBUILD_OFF		   5 

+#define EVT_CODE_HD_MP_RATE_CHANGE		   6

+

+/*

+ * Event code for EVT_CLASS_HD (Hard Disk)

+ */

+#define EVT_CODE_HD_OFFLINE                0

+#define EVT_CODE_HD_ONLINE                 1 

+#define EVT_CODE_HD_SETDOWN                2

+#define EVT_CODE_HD_TIMEOUT                3

+#define EVT_CODE_HD_RW_ERROR               4

+#define EVT_CODE_HD_SMART                  5

+#define EVT_CODE_HD_ERROR_FIXED            6

+#define EVT_CODE_HD_PLUG_IN                7

+#define EVT_CODE_HD_PLUG_OUT               8

+#define EVT_CODE_HD_ASSIGN_SPARE           9

+#define EVT_CODE_HD_REMOVE_SPARE           10

+#define EVT_CODE_HD_SMART_THRESHOLD_OVER   11

+/*New events added in March 2007 from LSI event list.*/

+#define EVT_CODE_HD_SMART_POLLING_FAIL	   12  // SMART polling failed on %s (Error %02x)

+#define EVT_CODE_BAD_BLOCK_TBL_80_FULL	   13  // Bad block table on PD %s is 80% full

+#define EVT_CODE_BAD_BLOCK_TBL_FULL	       14  // Bad block table on PD %s is full; Unable to log block %x

+#define EVT_CODE_BAD_BLOCK_REASSIGNED	   15  // Bad block reassigned on %s at %lx to %lx

+#define EVT_CODE_HD_CACHE_MODE_CHANGE	   16

+/*New event for HD media patrol.*/

+#define EVT_CODE_HD_MP_START			   17 

+#define EVT_CODE_HD_MP_RESTART			   18

+#define EVT_CODE_HD_MP_PAUSE			   19

+#define EVT_CODE_HD_MP_RESUME              20 

+#define EVT_CODE_HD_MP_ABORT               21

+#define EVT_CODE_HD_MP_COMPLETE            22

+#define EVT_CODE_HD_MP_PROGRESS            23

+#define EVT_CODE_HD_MP_ERROR               24

+#define EVT_CODE_HD_MP_AUTO_PAUSED         25

+#define EVT_CODE_HD_MP_AUTO_RESUME         26

+

+/*

+ * code for EVT_CLASS_MDD

+ */

+#define EVT_CODE_MDD_ERROR                 0

+

+/**********************************

+ *                Event IDs

+ **********************************/

+

+/*

+ * Event Id for EVT_CLASS_LD

+ */

+#define _CLASS_LD(x)                (EVT_CLASS_LD << 16 | (x))

+

+#define EVT_ID_LD_OFFLINE            _CLASS_LD(EVT_CODE_LD_OFFLINE)

+#define EVT_ID_LD_ONLINE             _CLASS_LD(EVT_CODE_LD_ONLINE) 

+#define EVT_ID_LD_CREATE             _CLASS_LD(EVT_CODE_LD_CREATE)

+#define EVT_ID_LD_DELETE             _CLASS_LD(EVT_CODE_LD_DELETE)

+#define EVT_ID_LD_DEGRADE            _CLASS_LD(EVT_CODE_LD_DEGRADE)

+#define EVT_ID_LD_PARTIALLYOPTIMAL   _CLASS_LD(EVT_CODE_LD_PARTIALLYOPTIMAL)

+#define EVT_ID_LD_CACHE_MODE_CHANGE  _CLASS_LD(EVT_CODE_LD_CACHE_MODE_CHANGE)

+#define EVT_ID_LD_FIXED              _CLASS_LD(EVT_CODE_LD_FIXED)

+#define EVT_ID_LD_FOUND_ERROR        _CLASS_LD(EVT_CODE_LD_FOUND_ERROR)

+

+#define EVT_ID_LD_CHECK_START        _CLASS_LD(EVT_CODE_LD_CHECK_START)

+#define EVT_ID_LD_CHECK_RESTART      _CLASS_LD(EVT_CODE_LD_CHECK_RESTART)

+#define EVT_ID_LD_CHECK_PAUSE        _CLASS_LD(EVT_CODE_LD_CHECK_PAUSE)

+#define EVT_ID_LD_CHECK_RESUME       _CLASS_LD(EVT_CODE_LD_CHECK_RESUME)

+#define EVT_ID_LD_CHECK_ABORT        _CLASS_LD(EVT_CODE_LD_CHECK_ABORT)

+#define EVT_ID_LD_CHECK_COMPLETE     _CLASS_LD(EVT_CODE_LD_CHECK_COMPLETE)

+#define EVT_ID_LD_CHECK_PROGRESS     _CLASS_LD(EVT_CODE_LD_CHECK_PROGRESS)

+#define EVT_ID_LD_CHECK_ERROR        _CLASS_LD(EVT_CODE_LD_CHECK_ERROR)

+#define EVT_ID_LD_CHECK_AUTO_PAUSED  _CLASS_LD(EVT_CODE_LD_CHECK_AUTO_PAUSED)

+#define EVT_ID_LD_CHECK_AUTO_RESUME  _CLASS_LD(EVT_CODE_LD_CHECK_AUTO_RESUME)

+

+#define EVT_ID_LD_FIXED_START        _CLASS_LD(EVT_CODE_LD_FIX_START)

+#define EVT_ID_LD_FIXED_RESTART      _CLASS_LD(EVT_CODE_LD_FIX_RESTART)

+#define EVT_ID_LD_FIXED_PAUSE        _CLASS_LD(EVT_CODE_LD_FIX_PAUSE)

+#define EVT_ID_LD_FIXED_RESUME       _CLASS_LD(EVT_CODE_LD_FIX_RESUME)

+#define EVT_ID_LD_FIXED_ABORT        _CLASS_LD(EVT_CODE_LD_FIX_ABORT)

+#define EVT_ID_LD_FIXED_COMPLETE     _CLASS_LD(EVT_CODE_LD_FIX_COMPLETE)

+#define EVT_ID_LD_FIXED_PROGRESS     _CLASS_LD(EVT_CODE_LD_FIX_PROGRESS)

+#define EVT_ID_LD_FIXED_ERROR        _CLASS_LD(EVT_CODE_LD_FIX_ERROR)

+#define EVT_ID_LD_FIXED_AUTO_PAUSED  _CLASS_LD(EVT_CODE_LD_FIXED_AUTO_PAUSED)

+#define EVT_ID_LD_FIXED_AUTO_RESUME  _CLASS_LD(EVT_CODE_LD_FIXED_AUTO_RESUME)

+

+#define EVT_ID_LD_INIT_QUICK_START   _CLASS_LD(EVT_CODE_LD_INIT_QUICK_START)

+#define EVT_ID_LD_INIT_QUICK_RESTART _CLASS_LD(EVT_CODE_LD_INIT_QUICK_RESTART)

+#define EVT_ID_LD_INIT_QUICK_PAUSE   _CLASS_LD(EVT_CODE_LD_INIT_QUICK_PAUSE)

+#define EVT_ID_LD_INIT_QUICK_RESUME  _CLASS_LD(EVT_CODE_LD_INIT_QUICK_RESUME)

+#define EVT_ID_LD_INIT_QUICK_ABORT   _CLASS_LD(EVT_CODE_LD_INIT_QUICK_ABORT)

+#define EVT_ID_LD_INIT_QUICK_COMPLETE _CLASS_LD(EVT_CODE_LD_INIT_QUICK_COMPLETE)

+#define EVT_ID_LD_INIT_QUICK_PROGRESS _CLASS_LD(EVT_CODE_LD_INIT_QUICK_PROGRESS)

+#define EVT_ID_LD_INIT_QUICK_ERROR   _CLASS_LD(EVT_CODE_LD_INIT_QUICK_ERROR)

+#define EVT_ID_LD_INIT_QUICK_AUTO_PAUSED   _CLASS_LD(EVT_CODE_LD_INIT_QUICK_AUTO_PAUSED)

+#define EVT_ID_LD_INIT_QUICK_AUTO_RESUME   _CLASS_LD(EVT_CODE_LD_INIT_QUICK_AUTO_RESUME)

+

+#define EVT_ID_LD_INIT_BACK_START    _CLASS_LD(EVT_CODE_LD_INIT_BACK_START)

+#define EVT_ID_LD_INIT_BACK_RESTART  _CLASS_LD(EVT_CODE_LD_INIT_BACK_RESTART)

+#define EVT_ID_LD_INIT_BACK_PAUSE    _CLASS_LD(EVT_CODE_LD_INIT_BACK_PAUSE)

+#define EVT_ID_LD_INIT_BACK_RESUME   _CLASS_LD(EVT_CODE_LD_INIT_BACK_RESUME)

+#define EVT_ID_LD_INIT_BACK_ABORT    _CLASS_LD(EVT_CODE_LD_INIT_BACK_ABORT)

+#define EVT_ID_LD_INIT_BACK_COMPLETE _CLASS_LD(EVT_CODE_LD_INIT_BACK_COMPLETE)

+#define EVT_ID_LD_INIT_BACK_PROGRESS _CLASS_LD(EVT_CODE_LD_INIT_BACK_PROGRESS)

+#define EVT_ID_LD_INIT_BACK_ERROR    _CLASS_LD(EVT_CODE_LD_INIT_BACK_ERROR)

+#define EVT_ID_LD_INIT_BACK_AUTO_PAUSED   _CLASS_LD(EVT_CODE_LD_INIT_BACK_AUTO_PAUSED)

+#define EVT_ID_LD_INIT_BACK_AUTO_RESUME   _CLASS_LD(EVT_CODE_LD_INIT_BACK_AUTO_RESUME)

+

+#if 0

+#define EVT_ID_LD_INIT_FORE_START    _CLASS_LD(EVT_CODE_LD_INIT_FORE_START)

+#define EVT_ID_LD_INIT_FORE_RESTART  _CLASS_LD(EVT_CODE_LD_INIT_FORE_RESTART)

+#define EVT_ID_LD_INIT_FORE_PAUSE    _CLASS_LD(EVT_CODE_LD_INIT_FORE_PAUSE)

+#define EVT_ID_LD_INIT_FORE_RESUME   _CLASS_LD(EVT_CODE_LD_INIT_FORE_RESUME)

+#define EVT_ID_LD_INIT_FORE_ABORT    _CLASS_LD(EVT_CODE_LD_INIT_FORE_ABORT)

+#define EVT_ID_LD_INIT_FORE_COMPLETE _CLASS_LD(EVT_CODE_LD_INIT_FORE_COMPLETE)

+#define EVT_ID_LD_INIT_FORE_PROGRESS _CLASS_LD(EVT_CODE_LD_INIT_FORE_PROGRESS)

+#define EVT_ID_LD_INIT_FORE_ERROR    _CLASS_LD(EVT_CODE_LD_INIT_FORE_ERROR)

+#define EVT_ID_LD_INIT_FORE_AUTO_PAUSED  _CLASS_LD(EVT_CODE_LD_INIT_FORE_AUTO_PAUSED)

+#define EVT_ID_LD_INIT_FORE_AUTO_RESUME  _CLASS_LD(EVT_CODE_LD_INIT_FORE_AUTO_RESUME)

+#endif

+

+#define EVT_ID_LD_REBUILD_START      _CLASS_LD(EVT_CODE_LD_REBUILD_START)

+#define EVT_ID_LD_REBUILD_RESTART    _CLASS_LD(EVT_CODE_LD_REBUILD_RESTART)

+#define EVT_ID_LD_REBUILD_PAUSE      _CLASS_LD(EVT_CODE_LD_REBUILD_PAUSE)

+#define EVT_ID_LD_REBUILD_RESUME     _CLASS_LD(EVT_CODE_LD_REBUILD_RESUME)

+#define EVT_ID_LD_REBUILD_ABORT      _CLASS_LD(EVT_CODE_LD_REBUILD_ABORT)

+#define EVT_ID_LD_REBUILD_COMPLETE   _CLASS_LD(EVT_CODE_LD_REBUILD_COMPLETE)

+#define EVT_ID_LD_REBUILD_PROGRESS   _CLASS_LD(EVT_CODE_LD_REBUILD_PROGRESS)

+#define EVT_ID_LD_REBUILD_ERROR      _CLASS_LD(EVT_CODE_LD_REBUILD_ERROR)

+#define EVT_ID_LD_REBUILD_AUTO_PAUSED _CLASS_LD(EVT_CODE_LD_REBUILD_AUTO_PAUSED)

+#define EVT_ID_LD_REBUILD_AUTO_RESUME _CLASS_LD(EVT_CODE_LD_REBUILD_AUTO_RESUME)

+

+#define EVT_ID_LD_MIGRATION_START    _CLASS_LD(EVT_CODE_LD_MIGRATION_START)

+#define EVT_ID_LD_MIGRATION_RESTART  _CLASS_LD(EVT_CODE_LD_MIGRATION_RESTART)

+#define EVT_ID_LD_MIGRATION_PAUSE    _CLASS_LD(EVT_CODE_LD_MIGRATION_PAUSE)

+#define EVT_ID_LD_MIGRATION_RESUME   _CLASS_LD(EVT_CODE_LD_MIGRATION_RESUME)

+#define EVT_ID_LD_MIGRATION_ABORT    _CLASS_LD(EVT_CODE_LD_MIGRATION_ABORT)

+#define EVT_ID_LD_MIGRATION_COMPLETE _CLASS_LD(EVT_CODE_LD_MIGRATION_COMPLETE)

+#define EVT_ID_LD_MIGRATION_PROGRESS _CLASS_LD(EVT_CODE_LD_MIGRATION_PROGRESS)

+#define EVT_ID_LD_MIGRATION_ERROR    _CLASS_LD(EVT_CODE_LD_MIGRATION_ERROR)

+#define EVT_ID_LD_MIGRATION_AUTO_PAUSED    _CLASS_LD(EVT_CODE_LD_MIGRATION_AUTO_PAUSED)

+#define EVT_ID_LD_MIGRATION_AUTO_RESUME    _CLASS_LD(EVT_CODE_LD_MIGRATION_AUTO_RESUME)

+

+#define EVT_ID_LD_INCONSISTENT_LBA   _CLASS_LD(EVT_CODE_LD_INCONSISTENT_LBA)

+

+/*

+ * Event Id for EVT_CLASS_HD

+ */

+#define _CLASS_HD(x)                    (EVT_CLASS_HD << 16 | (x))

+

+#define EVT_ID_HD_OFFLINE               _CLASS_HD(EVT_CODE_HD_OFFLINE)

+#define EVT_ID_HD_ONLINE                _CLASS_HD(EVT_CODE_HD_ONLINE)

+#define EVT_ID_HD_SETDOWN               _CLASS_HD(EVT_CODE_HD_SETDOWN)

+#define EVT_ID_HD_TIMEOUT               _CLASS_HD(EVT_CODE_HD_TIMEOUT)

+#define EVT_ID_HD_RW_ERROR              _CLASS_HD(EVT_CODE_HD_RW_ERROR)

+#define EVT_ID_HD_SMART                 _CLASS_HD(EVT_CODE_HD_SMART)

+#define EVT_ID_HD_ERROR_FIXED           _CLASS_HD(EVT_CODE_HD_ERROR_FIXED)

+#define EVT_ID_HD_PLUG_IN               _CLASS_HD(EVT_CODE_HD_PLUG_IN)

+#define EVT_ID_HD_PLUG_OUT              _CLASS_HD(EVT_CODE_HD_PLUG_OUT)

+#define EVT_ID_HD_ASSIGN_SPARE          _CLASS_HD(EVT_CODE_HD_ASSIGN_SPARE)

+#define EVT_ID_HD_REMOVE_SPARE          _CLASS_HD(EVT_CODE_HD_REMOVE_SPARE)

+#define EVT_ID_HD_SMART_THRESHOLD_OVER  _CLASS_HD(EVT_CODE_HD_SMART_THRESHOLD_OVER)

+#define EVT_ID_HD_SMART_POLLING_FAIL    _CLASS_HD(EVT_CODE_HD_SMART_POLLING_FAIL)		

+#define EVT_ID_BAD_BLOCK_TBL_80_FULL    _CLASS_HD(EVT_CODE_BAD_BLOCK_TBL_80_FULL)

+#define EVT_ID_BAD_BLOCK_TBL_FULL       _CLASS_HD(EVT_CODE_BAD_BLOCK_TBL_FULL)

+#define EVT_ID_BAD_BLOCK_REASSIGNED     _CLASS_HD(EVT_CODE_BAD_BLOCK_REASSIGNED)

+#define EVT_ID_HD_CACHE_MODE_CHANGE		_CLASS_HD(EVT_CODE_HD_CACHE_MODE_CHANGE)

+

+#define EVT_ID_HD_MP_START				_CLASS_HD(EVT_CODE_HD_MP_START)

+#define EVT_ID_HD_MP_RESTART			_CLASS_HD(EVT_CODE_HD_MP_RESTART)

+#define EVT_ID_HD_MP_PAUSE				_CLASS_HD(EVT_CODE_HD_MP_PAUSE)

+#define EVT_ID_HD_MP_RESUME				_CLASS_HD(EVT_CODE_HD_MP_RESUME)

+#define EVT_ID_HD_MP_ABORT				_CLASS_HD(EVT_CODE_HD_MP_ABORT)

+#define EVT_ID_HD_MP_COMPLETE			_CLASS_HD(EVT_CODE_HD_MP_COMPLETE)

+#define EVT_ID_HD_MP_PROGRESS			_CLASS_HD(EVT_CODE_HD_MP_PROGRESS)

+#define EVT_ID_HD_MP_ERROR				_CLASS_HD(EVT_CODE_HD_MP_ERROR)

+#define EVT_ID_HD_MP_AUTO_PAUSED		_CLASS_HD(EVT_CODE_HD_MP_AUTO_PAUSED)

+#define EVT_ID_HD_MP_AUTO_RESUME		_CLASS_HD(EVT_CODE_HD_MP_AUTO_RESUME)

+

+

+/*

+ * Id for EVT_CLASS_MDD

+ */

+

+#define _CLASS_MDD(x)                    (EVT_CLASS_MDD << 16 | (x))

+#define EVT_ID_MDD_ERROR                 _CLASS_MDD(EVT_CODE_MDD_ERROR)

+

+/*

+ * Id for EVT_CLASS_ADAPTER

+ */

+

+#define _CLASS_ADPT(x)                   (EVT_CLASS_ADAPTER << 16 | (x))

+#define EVT_ID_EVT_LOST                  _CLASS_ADPT(EVT_CODE_EVT_ERR)

+#define EVT_ID_SMART_FROM_OFF_TO_ON		 _CLASS_ADPT(EVT_CODE_SMART_FROM_OFF_TO_ON)

+#define EVT_ID_SMART_FROM_ON_TO_OFF		 _CLASS_ADPT(EVT_CODE_SMART_FROM_ON_TO_OFF)

+#define EVT_ID_ALARM_TURN_ON			 _CLASS_ADPT(EVT_CODE_ALARM_TURN_ON)

+#define EVT_ID_ALARM_TURN_OFF		     _CLASS_ADPT(EVT_CODE_ALARM_TURN_OFF)

+#define EVT_ID_AUTO_REBUILD_ON		     _CLASS_ADPT(EVT_CODE_AUTO_REBUILD_ON)

+#define EVT_ID_AUTO_REBUILD_OFF		     _CLASS_ADPT(EVT_CODE_AUTO_REBUILD_OFF)

+#define EVT_ID_HD_MP_RATE_CHANGE		 _CLASS_ADPT(EVT_CODE_HD_MP_RATE_CHANGE)

+

+#endif /*  COM_EVENT_DEFINE_H */

diff --git a/drivers/scsi/thor/include/generic/com_event_define_ext.h b/drivers/scsi/thor/include/generic/com_event_define_ext.h
new file mode 100755
index 0000000..8a5c595
--- /dev/null
+++ b/drivers/scsi/thor/include/generic/com_event_define_ext.h
@@ -0,0 +1,358 @@
+#ifndef COM_EVENT_DEFINE_EXT_H

+#define COM_EVENT_DEFINE_EXT_H

+

+//===================================================================================

+//===================================================================================

+//		All these events are new ones but which are listed in LSI product.

+//	Pay attention: All suggested display messages are from from LSI event list.

+//  We may make some little change later, especially for new events in Loki.

+//===================================================================================

+//===================================================================================

+

+//=======================================

+//=======================================

+//				Event Classes

+//=======================================

+//=======================================

+

+#define	EVT_CLASS_SAS				7		// SAS, mainly for SAS topology

+#define	EVT_CLASS_ENCL				8		// Enclosure

+#define	EVT_CLASS_BAT				9       // Battery

+#define	EVT_CLASS_FLASH				10      // Flash memory

+#define EVT_CLASS_CACHE             11      // Cache related

+#define EVT_CLASS_MISC              12      // For other miscellenous events

+

+//=============================================================

+//					Event Codes 

+//

+//	!!!  When adding an EVT_ID, Please put its severity level

+//  !!!  and suggested mesage string as comments.  This is the 

+//  !!!  only place to document how 'Params' in 'DriverEvent' 

+//  !!!  structure is to be used.

+//  !!!  Please refer to the EventMessages.doc to get details.

+//=============================================================

+

+//

+// Event code for EVT_CLASS_SAS (sas)

+//

+

+#define EVT_CODE_SAS_LOOP_DETECTED				0  //SAS Topology error: Loop detected

+#define EVT_CODE_SAS_UNADDR_DEVICE				1  //SAS Topology error: Unaddressable device

+#define EVT_CODE_SAS_MULTIPORT_SAME_ADDR		2  //SAS Topology error: Multiple ports to the same SAS address

+#define EVT_CODE_SAS_EXPANDER_ERR				3  //SAS Topology error: Expander error

+#define EVT_CODE_SAS_SMP_TIMEOUT				4  //SAS Topology error: SMP timeout

+#define EVT_CODE_SAS_OUT_OF_ROUTE_ENTRIES		5  //SAS Topology error: Out of route entries

+#define EVT_CODE_SAS_INDEX_NOT_FOUND			6  //SAS Topology error: Index not found

+#define EVT_CODE_SAS_SMP_FUNC_FAILED			7  //SAS Topology error: SMP function failed	

+#define EVT_CODE_SAS_SMP_CRC_ERR				8  //SAS Topology error: SMP CRC error

+#define EVT_CODE_SAS_MULTI_SUBTRACTIVE			9  //SAS Topology error: Multiple subtractive

+#define EVT_CODE_SAS_TABEL_TO_TABLE				10 //SAS Topology error: Table to Table

+#define EVT_CODE_SAS_MULTI_PATHS				11 //SAS Topology error: Multiple paths

+#define EVT_CODE_SAS_WIDE_PORT_LOST_LINK_ON_PHY	12 //SAS wide port %d lost link on PHY %d 

+#define EVT_CODE_SAS_WIDE_PORT_REST_LINK_ON_PHY	13 //SAS wide port %d restored link on PHY %d 

+#define EVT_CODE_SAS_PHY_EXCEED_ERR_RATE		14 //SAS port %d, PHY %d has exceeded the allowed error rate

+#define EVT_CODE_SAS_SATA_MIX_NOT_SUPPORTED		15 //SAS/SATA mixing not supported in enclosure: PD %d disabled

+

+//

+// Event code for EVT_CLASS_ENCL (enclosure)

+//

+

+#define	EVT_CODE_ENCL_SES_DISCOVERED			0   // Enclosure(SES) discovered on %d

+#define	EVT_CODE_ENCL_SAFTE_DISCOVERED			1   // Enclosure(SAFTE) discovered on %d

+#define	EVT_CODE_ENCL_COMMUNICATION_LOST		2   // Enclosure %d communication lost

+#define	EVT_CODE_ENCL_COMMUNICATION_RESTORED	3   // Enclosure %d communication restored

+#define	EVT_CODE_ENCL_FAN_FAILED				4   // Enclosure %d fan %d failed

+#define	EVT_CODE_ENCL_FAN_INSERTED				5   // Enclosure %d fan %d inserted

+#define	EVT_CODE_ENCL_FAN_REMOVED				6   // Enclosure %d fan %d removed

+#define	EVT_CODE_ENCL_PS_FAILED					7   // Enclosure %d power supply %d failed

+#define	EVT_CODE_ENCL_PS_INSERTED				8   // Enclosure %d power supply %d inserted

+#define	EVT_CODE_ENCL_PS_REMOVED				9   // Enclosure %d power supply %d removed

+#define	EVT_CODE_ENCL_SIM_FAILED				10  // Enclosure %d SIM %d failed

+#define	EVT_CODE_ENCL_SIM_INSERTED				11  // Enclosure %d SIM %d inserted

+#define	EVT_CODE_ENCL_SIM_REMOVED				12  // Enclosure %d SIM %d removed

+#define	EVT_CODE_ENCL_TEMP_SENSOR_BELOW_WARNING	13  // Enclosure %d temperature sensor %d below warning threshold

+#define	EVT_CODE_ENCL_TEMP_SENSOR_BELOW_ERR		14  // Enclosure %d temperature sensor %d below error threshold

+#define	EVT_CODE_ENCL_TEMP_SENSOR_ABOVE_WARNING	15  // Enclosure %d temperature sensor %d above warning threshold

+#define	EVT_CODE_ENCL_TEMP_SENSOR_ABOVE_ERR		16  // Enclosure %d temperature sensor %d above error threshold 

+#define EVT_CODE_ENCL_SHUTDOWN					17  // Enclosure %d shutdown

+#define EVT_CODE_ENCL_NOT_SUPPORTED				18  // Enclosure %d not supported; too many enclosures connected to port

+#define	EVT_CODE_ENCL_FW_MISMATCH				19  // Enclosure %d firmware mismatch 

+#define	EVT_CODE_ENCL_SENSOR_BAD				20  // Enclosure %d sensor %d bad

+#define	EVT_CODE_ENCL_PHY_BAD					21  // Enclosure %d phy %d bad

+#define	EVT_CODE_ENCL_IS_UNSTABLE				22  // Enclosure %d is unstable

+#define	EVT_CODE_ENCL_HW_ERR					23  // Enclosure %d hardware error

+#define	EVT_CODE_ENCL_NOT_RESPONDING			24  // Enclosure %d not responding

+#define	EVT_CODE_ENCL_HOTPLUG_DETECTED			25  // Enclosure(SES) hotplug on %d was detected, but is not supported 

+#define	EVT_CODE_ENCL_PS_SWITCHED_OFF			26  // Enclosure %d Power supply %d switched off

+#define	EVT_CODE_ENCL_PS_SWITCHED_ON			27  // Enclosure %d Power supply %d switched on

+#define	EVT_CODE_ENCL_PS_CABLE_REMOVED			28  // Enclosure %d Power supply %d cable removed

+#define	EVT_CODE_ENCL_PS_CABLE_INSERTED			29  // Enclosure %d Power supply %d cable inserted

+#define	EVT_CODE_ENCL_FAN_RETURN_TO_NORMAL		30  // Enclosure %d Fan %d returned to normal

+#define	EVT_CODE_ENCL_TEMP_RETURN_TO_NORMAL		31  // Enclosure %d Temperature %d returned to normal

+#define	EVT_CODE_ENCL_FW_DWLD_IN_PRGS			32  // Enclosure %d Firmware download in progress

+#define	EVT_CODE_ENCL_FW_DWLD_FAILED			33  // Enclosure %d Firmware download failed

+#define	EVT_CODE_ENCL_TEMP_SENSOR_DIFF_DETECTED	34  // Enclosure %d Temperature sensor %d differential detected

+#define	EVT_CODE_ENCL_FAN_SPEED_CHANGED			35  // Enclosure %d fan %d speed changed

+

+

+//

+// Event code for EVT_CLASS_BAT

+//

+

+#define EVT_CODE_BAT_PRESENT					0	// Battery present

+#define EVT_CODE_BAT_NOT_PRESENT				1   // Battery not present

+#define EVT_CODE_BAT_NEW_BAT_DETECTED			2   // New battery detected

+#define EVT_CODE_BAT_REPLACED					3   // Battery has been replaced 

+#define EVT_CODE_BAT_TEMP_IS_HIGH				4   // Battery temperature is high (%dC)

+#define EVT_CODE_BAT_VOLTAGE_LOW				5   // Battery voltage low (%f V)

+#define EVT_CODE_BAT_STARTED_CHARGING			6   // Battery started charging

+#define EVT_CODE_BAT_DISCHARGING				7   // Battery is discharging

+#define EVT_CODE_BAT_TEMP_IS_NORMAL				8	// Battery temperature is normal

+#define EVT_CODE_BAT_NEED_REPLACE				9	// Battery needs to be replacement, SOH bad

+#define EVT_CODE_BAT_RELEARN_STARTED			10  // Battery relearn started

+#define EVT_CODE_BAT_RELEARN_IN_PGRS			11  // Battery relearn in progress

+#define EVT_CODE_BAT_RELEARN_COMPLETED			12  // Battery relearn completed

+#define EVT_CODE_BAT_RELEARN_TIMED_OUT			13  // Battery relearn timed out

+#define EVT_CODE_BAT_RELEARN_PENDING			14  // Battery relearn pending: Battery is under charge

+#define EVT_CODE_BAT_RELEARN_POSTPONED			15  // Battery relearn postponed

+#define EVT_CODE_BAT_START_IN_4_DAYS			16  // Battery relearn will start in 4 days

+#define EVT_CODE_BAT_START_IN_2_DAYS			17	// Battery relearn will start in 2 days

+#define EVT_CODE_BAT_START_IN_1_DAY				18	// Battery relearn will start in 1 days

+#define EVT_CODE_BAT_START_IN_5_HOURS			19	// Battery relearn will start in 5 hours

+#define EVT_CODE_BAT_REMOVED					20  // Battery removed

+#define EVT_CODE_BAT_CHARGE_CMPLT				21  // Battery charged complete

+#define EVT_CODE_BAT_CHARGER_PROBLEM_DETECTED	22  // Battery/charger problems detected: SOH bad

+#define EVT_CODE_BAT_CAPACITY_BELOW_THRESHOLD	23  // Current capacity (%d) of the battery is below threshold (%d)

+#define EVT_CODE_BAT_CAPACITY_ABOVE_THRESHOLD	24  // Current capacity (%d) of the battery is above threshold (%d)

+

+

+

+//

+// Event code for EVT_CLASS_FLASH

+//

+

+#define EVT_CODE_FLASH_DWLDED_IMAGE_CORRUPTED	0	// Flash downloaded image corrupt

+#define EVT_CODE_FLASH_ERASE_ERR				1   // Flash erase error

+#define EVT_CODE_FLASH_ERASE_TIMEOUT			2   // Flash timeout during erase

+#define EVT_CODE_FLASH_FLASH_ERR				3	// Flash error

+#define EVT_CODE_FLASHING_IMAGE					4	// Flashing image: %d

+#define EVT_CODE_FLASHING_NEW_IMAGE_DONE		5   // Flash of new firmware images complete

+#define EVT_CODE_FLASH_PROGRAMMING_ERR			6   // Flash programming error

+#define EVT_CODE_FLASH_PROGRAMMING_TIMEOUT		7   // Flash timeout during programming

+#define EVT_CODE_FLASH_UNKNOWN_CHIP_TYPE		8   // Flash chip type unknown 

+#define EVT_CODE_FLASH_UNKNOWN_CMD_SET			9   // Flash command set unknown

+#define EVT_CODE_FLASH_VERIFY_FAILURE			10  // Flash verify failure

+#define EVT_CODE_NVRAM_CORRUPT					11	// NVRAM is corrupt; reinitializing

+#define EVT_CODE_NVRAM_MISMACTH_OCCURED			12  // NVRAM mismatch occured

+

+

+//

+// Event code for EVT_CLASS_CACHE(Cache)

+//

+

+#define EVT_CODE_CACHE_NOT_RECV_FROM_TBBU		0	// Unable to recover cache data from TBBU

+#define EVT_CODE_CACHE_RECVD_FROM_TBBU			1   // Cache data recovered from TBBU successfully

+#define EVT_CODE_CACHE_CTRLER_CACHE_DISCARDED	2   // Controller cache discarded due to memory/battery problems

+#define EVT_CODE_CACHE_FAIL_RECV_DUETO_MISMATCH	3   // Unable to recover cache data due to configuration mismatch 

+#define EVT_CODE_CACHE_DIRTY_DATA_DISCARDED		4	// Dirty cache data discarded by user

+#define EVT_CODE_CACHE_FLUSH_RATE_CHANGED		5   // Flush rate changed to %d seconds.

+

+

+//

+// Event code for EVT_CLASS_MISC

+//

+

+#define EVT_CODE_MISC_CONFIG_CLEARED				0	// Configuration cleared

+#define EVT_CODE_MISC_CHANGE_BACK_ACTIVITY_RATE		1	// Background activity rate changed to %d%%

+#define EVT_CODE_MISC_FATAL_FW_ERR					2   // Fatal firmware error: %d

+#define EVT_CODE_MISC_FACTORY_DEFAULTS_RESTORED		3   // Factory defaults restored

+#define EVT_CODE_MISC_GET_HIBER_CMD					4   // Hibernation command received from host

+#define EVT_CODE_MISC_MUTLI_BIT_ECC_ERR				5	// Multi-bit ECC error: ECAR=%x ELOG=%x, (%d)

+#define EVT_CODE_MISC_SINGLE_BIT_ECC_ERR			6   // Single-bit ECC error: ECAR=%x ELOG=%x, (%d)

+#define EVT_CODE_MISC_GET_SHUTDOWN_CMD				7	// Shutdown command received from host

+#define EVT_CODE_MISC_TIME_ESTABLISHED				8	// Time established as %d; (%d seconds since power on)

+#define EVT_CODE_MISC_USER_ENTERED_DEBUGGER			9   // User entered firmware debugger

+

+#define EVT_CODE_MISC_FORMAT_COMPLETE				10	// Format complete on %d

+#define EVT_CODE_MISC_FORMAT_STARTED				11	// Format started on %d 

+#define EVT_CODE_MISC_REASSIGN_WRITE_OP				12	// Reassign write operation on %d is %d

+#define EVT_CODE_MISC_UNEXPECTED_SENSE				13	// Unexpected sense: %d, CDB%d, Sense: %d

+#define EVT_CODE_MISC_REPLACED_MISSING				14	// Replaced missing as %d on array %d row %d

+#define EVT_CODE_MISC_NOT_A_CERTIFIED_DRIVE			15  // %d is not a certificated derive

+

+/* May put into other group???*/

+#define EVT_CODE_MISC_PD_MISSING_FROM_CONFIG_AT_BOOT	16	// PDs missing from configuration on boot	

+#define EVT_CODE_MISC_VD_MISSING_DRIVES					17  // VDs missing drives and will go offline at boot: %d

+#define EVT_CODE_MISC_VD_MISSING_AT_BOOT				18  // VDs missing at boot: %d

+#define EVT_CODE_MISC_PREVIOUS_CONFIG_MISSING_AT_BOOT	19  // Previous configuration completely missing at boot

+#define EVT_CODE_MISC_PD_TOO_SMALL_FOR_AUTOREBUILD		20  // PD too small to be used for auto-rebuild on %d.

+

+//=======================================

+//=======================================

+//				Event IDs

+//=======================================

+//=======================================

+

+//

+// Event id for EVT_CLASS_SAS

+//

+

+#define _CLASS_SAS(x)                (EVT_CLASS_SAS << 16 | (x))

+

+#define EVT_ID_SAS_LOOP_DETECTED					_CLASS_SAS(EVT_CODESAS_LOOP_DETECTED)

+#define EVT_ID_SAS_UNADDR_DEVICE					_CLASS_SAS(EVT_CODESAS_UNADDR_DEVICE)			

+#define EVT_ID_SAS_MULTIPORT_SAME_ADDR				_CLASS_SAS(EVT_CODESAS_MULTIPORT_SAME_ADDR)

+#define EVT_ID_SAS_EXPANDER_ERR						_CLASS_SAS(EVT_CODESAS_EXPANDER_ERR)

+#define EVT_ID_SAS_SMP_TIMEOUT						_CLASS_SAS(EVT_CODESAS_SMP_TIMEOUT)

+#define EVT_ID_SAS_OUT_OF_ROUTE_ENTRIES				_CLASS_SAS(EVT_CODESAS_OUT_OF_ROUTE_ENTRIES)

+#define EVT_ID_SAS_INDEX_NOT_FOUND					_CLASS_SAS(EVT_CODESAS_INDEX_NOT_FOUND)

+#define EVT_ID_SAS_SMP_FUNC_FAILED					_CLASS_SAS(EVT_CODESAS_SMP_FUNC_FAILED)

+#define EVT_ID_SAS_SMP_CRC_ERR						_CLASS_SAS(EVT_CODESAS_SMP_CRC_ERR)

+#define EVT_ID_SAS_MULTI_SUBTRACTIVE				_CLASS_SAS(EVT_CODESAS_MULTI_SUBTRACTIVE)

+#define EVT_ID_SAS_TABEL_TO_TABLE					_CLASS_SAS(EVT_CODESAS_TABEL_TO_TABLE)

+#define EVT_ID_SAS_MULTI_PATHS						_CLASS_SAS(EVT_CODESAS_MULTI_PATHS)

+#define EVT_ID_SAS_WIDE_PORT_LOST_LINK_ON_PHY		_CLASS_SAS(EVT_CODESAS_WIDE_PORT_LOST_LINK_ON_PHY)

+#define EVT_ID_SAS_WIDE_PORT_REST_LINK_ON_PHY		_CLASS_SAS(EVT_CODESAS_WIDE_PORT_REST_LINK_ON_PHY)

+#define EVT_ID_SAS_PHY_EXCEED_ERR_RATE				_CLASS_SAS(EVT_CODESAS_PHY_EXCEED_ERR_RATE)

+#define EVT_ID_SAS_SATA_MIX_NOT_SUPPORTED			_CLASS_SAS(EVT_CODESAS_SATA_MIX_NOT_SUPPORTED)

+

+//

+// Event id for EVT_CLASS_ENCL (enclosure)

+//

+

+#define _CLASS_ENCL(x)                (EVT_CLASS_ENCL << 16 | (x))

+

+#define	EVT_ID_ENCL_SES_DISCOVERED					_CLASS_ENCL(EVT_CODE_ENCL_SES_DISCOVERED)				

+#define	EVT_ID_ENCL_SAFTE_DISCOVERED				_CLASS_ENCL(EVT_CODE_ENCL_SAFTE_DISCOVERED)

+#define	EVT_ID_ENCL_COMMUNICATION_LOST				_CLASS_ENCL(EVT_CODE_ENCL_COMMUNICATION_LOST)

+#define	EVT_ID_ENCL_COMMUNICATION_RESTORED		    _CLASS_ENCL(EVT_CODE_ENCL_COMMUNICATION_RESTORED)

+#define	EVT_ID_ENCL_FAN_FAILED						_CLASS_ENCL(EVT_CODE_ENCL_FAN_FAILED)

+#define	EVT_ID_ENCL_FAN_INSERTED					_CLASS_ENCL(EVT_CODE_ENCL_FAN_INSERTED)

+#define	EVT_ID_ENCL_FAN_REMOVED						_CLASS_ENCL(EVT_CODE_ENCL_FAN_REMOVED)

+#define	EVT_ID_ENCL_PS_FAILED						_CLASS_ENCL(EVT_CODE_ENCL_PS_FAILED)

+#define	EVT_ID_ENCL_PS_INSERTED						_CLASS_ENCL(EVT_CODE_ENCL_PS_INSERTED)

+#define	EVT_ID_ENCL_PS_REMOVED						_CLASS_ENCL(EVT_CODE_ENCL_PS_REMOVED)

+#define	EVT_ID_ENCL_SIM_FAILED						_CLASS_ENCL(EVT_CODE_ENCL_SIM_FAILED)

+#define	EVT_ID_ENCL_SIM_INSERTED					_CLASS_ENCL(EVT_CODE_ENCL_SIM_INSERTED)

+#define	EVT_ID_ENCL_SIM_REMOVED						_CLASS_ENCL(EVT_CODE_ENCL_SIM_REMOVED)

+#define	EVT_ID_ENCL_TEMP_SENSOR_BELOW_WARNING		_CLASS_ENCL(EVT_CODE_ENCL_TEMP_SENSOR_BELOW_WARNING)

+#define	EVT_ID_ENCL_TEMP_SENSOR_BELOW_ERR			_CLASS_ENCL(EVT_CODE_ENCL_TEMP_SENSOR_BELOW_ERR)

+#define	EVT_ID_ENCL_TEMP_SENSOR_ABOVE_WARNING		_CLASS_ENCL(EVT_CODE_ENCL_TEMP_SENSOR_ABOVE_WARNING)

+#define	EVT_ID_ENCL_TEMP_SENSOR_ABOVE_ERR			_CLASS_ENCL(EVT_CODE_ENCL_TEMP_SENSOR_ABOVE_ERR)

+#define EVT_ID_ENCL_SHUTDOWN						_CLASS_ENCL(EVT_CODE_ENCL_SHUTDOWN)

+#define EVT_ID_ENCL_NOT_SUPPORTED				    _CLASS_ENCL(EVT_CODE_ENCL_NOT_SUPPORTED)

+#define	EVT_ID_ENCL_FW_MISMATCH						_CLASS_ENCL(EVT_CODE_ENCL_FW_MISMATCH)

+#define	EVT_ID_ENCL_SENSOR_BAD						_CLASS_ENCL(EVT_CODE_ENCL_SENSOR_BAD)

+#define	EVT_ID_ENCL_PHY_BAD							_CLASS_ENCL(EVT_CODE_ENCL_PHY_BAD)

+#define	EVT_ID_ENCL_IS_UNSTABLE						_CLASS_ENCL(EVT_CODE_ENCL_IS_UNSTABLE)

+#define	EVT_ID_ENCL_HW_ERR							_CLASS_ENCL(EVT_CODE_ENCL_HW_ERR)

+#define	EVT_ID_ENCL_NOT_RESPONDING					_CLASS_ENCL(EVT_CODE_ENCL_NOT_RESPONDING)

+#define	EVT_ID_ENCL_HOTPLUG_DETECTED				_CLASS_ENCL(EVT_CODE_ENCL_HOTPLUG_DETECTED)

+#define	EVT_ID_ENCL_PS_SWITCHED_OFF					_CLASS_ENCL(EVT_CODE_ENCL_PS_SWITCHED_OFF	)	

+#define	EVT_ID_ENCL_PS_SWITCHED_ON					_CLASS_ENCL(EVT_CODE_ENCL_PS_SWITCHED_ON)

+#define	EVT_ID_ENCL_PS_CABLE_REMOVED				_CLASS_ENCL(EVT_CODE_ENCL_PS_CABLE_REMOVED)

+#define	EVT_ID_ENCL_PS_CABLE_INSERTED				_CLASS_ENCL(EVT_CODE_ENCL_PS_CABLE_INSERTED)

+#define	EVT_ID_ENCL_FAN_RETURN_TO_NORMAL			_CLASS_ENCL(EVT_CODE_ENCL_FAN_RETURN_TO_NORMAL)	

+#define	EVT_ID_ENCL_TEMP_RETURN_TO_NORMAL			_CLASS_ENCL(EVT_CODE_ENCL_TEMP_RETURN_TO_NORMAL)		

+#define	EVT_ID_ENCL_FW_DWLD_IN_PRGS					_CLASS_ENCL(EVT_CODE_ENCL_FW_DWLD_IN_PRGS	)

+#define	EVT_ID_ENCL_FW_DWLD_FAILED					_CLASS_ENCL(EVT_CODE_ENCL_FW_DWLD_FAILED)	

+#define	EVT_ID_ENCL_TEMP_SENSOR_DIFF_DETECTED		_CLASS_ENCL(EVT_CODE_ENCL_TEMP_SENSOR_DIFF_DETECTED)

+#define	EVT_ID_ENCL_FAN_SPEED_CHANGED				_CLASS_ENCL(EVT_CODE_ENCL_FAN_SPEED_CHANGED)

+

+//

+// Event id for EVT_CLASS_BAT

+//

+

+#define _CLASS_BAT(x)                (EVT_CLASS_BAT << 16 | (x))

+

+#define EVT_ID_BAT_PRESENT						_CLASS_BAT(EVT_CODE_BAT_PRESENT)

+#define EVT_ID_BAT_NOT_PRESENT					_CLASS_BAT(EVT_CODE_BAT_NOT_PRESENT)

+#define EVT_ID_BAT_NEW_BAT_DETECTED				_CLASS_BAT(EVT_CODE_BAT_NEW_BAT_DETECTED)

+#define EVT_ID_BAT_REPLACED						_CLASS_BAT(EVT_CODE_BAT_REPLACED)

+#define EVT_ID_BAT_TEMP_IS_HIGH					_CLASS_BAT(EVT_CODE_BAT_TEMP_IS_HIGH)

+#define EVT_ID_BAT_VOLTAGE_LOW					_CLASS_BAT(EVT_CODE_BAT_VOLTAGE_LOW)

+#define EVT_ID_BAT_STARTED_CHARGING				_CLASS_BAT(EVT_CODE_BAT_STARTED_CHARGING)

+#define EVT_ID_BAT_DISCHARGING					_CLASS_BAT(EVT_CODE_BAT_DISCHARGING)

+#define EVT_ID_BAT_TEMP_IS_NORMAL				_CLASS_BAT(EVT_CODE_BAT_TEMP_IS_NORMAL)

+#define EVT_ID_BAT_NEED_REPLACE					_CLASS_BAT(EVT_CODE_BAT_NEED_REPLACE)

+#define EVT_ID_BAT_RELEARN_STARTED				_CLASS_BAT(EVT_CODE_BAT_RELEARN_STARTED)

+#define EVT_ID_BAT_RELEARN_IN_PGRS				_CLASS_BAT(EVT_CODE_BAT_RELEARN_IN_PGRS)

+#define EVT_ID_BAT_RELEARN_COMPLETED			_CLASS_BAT(EVT_CODE_BAT_RELEARN_COMPLETED)

+#define EVT_ID_BAT_RELEARN_TIMED_OUT			_CLASS_BAT(EVT_CODE_BAT_RELEARN_TIMED_OUT)

+#define EVT_ID_BAT_RELEARN_PENDING				_CLASS_BAT(EVT_CODE_BAT_RELEARN_PENDING)

+#define EVT_ID_BAT_RELEARN_POSTPONED			_CLASS_BAT(EVT_CODE_BAT_RELEARN_POSTPONED)

+#define EVT_ID_BAT_START_IN_4_DAYS				_CLASS_BAT(EVT_CODE_BAT_START_IN_4_DAYS)

+#define EVT_ID_BAT_START_IN_2_DAYS				_CLASS_BAT(EVT_CODE_BAT_START_IN_2_DAYS)

+#define EVT_ID_BAT_START_IN_1_DAY				_CLASS_BAT(EVT_CODE_BAT_START_IN_1_DAY)

+#define EVT_ID_BAT_START_IN_5_HOURS				_CLASS_BAT(EVT_CODE_BAT_START_IN_5_HOURS)

+#define EVT_ID_BAT_REMOVED						_CLASS_BAT(EVT_CODE_BAT_REMOVED)

+#define EVT_ID_BAT_CHARGE_CMPLT					_CLASS_BAT(EVT_CODE_BAT_CHARGE_CMPLT)

+#define EVT_ID_BAT_CHARGER_PROBLEM_DETECTED		_CLASS_BAT(EVT_CODE_BAT_CHARGER_PROBLEM_DETECTED)

+#define EVT_ID_BAT_CAPACITY_BELOW_THRESHOLD		_CLASS_BAT(EVT_CODE_BAT_CAPACITY_BELOW_THRESHOLD)

+#define EVT_ID_BAT_CAPACITY_ABOVE_THRESHOLD		_CLASS_BAT(EVT_CODE_BAT_CAPACITY_ABOVE_THRESHOLD)

+

+//

+// Event id for EVT_CLASS_FLASH

+//

+#define _CLASS_FLASH(x)                (EVT_CLASS_FLASH << 16 | (x))

+

+#define EVT_ID_FLASH_DWLDED_IMAGE_CORRUPTED		_CLASS_FLASH(EVT_CODE_FLASH_DWLDED_IMAGE_CORRUPTED)

+#define EVT_ID_FLASH_ERASE_ERR					_CLASS_FLASH(EVT_CODE_FLASH_ERASE_ERR)

+#define EVT_ID_FLASH_ERASE_TIMEOUT				_CLASS_FLASH(EVT_CODE_FLASH_ERASE_TIMEOUT)

+#define EVT_ID_FLASH_FLASH_ERR					_CLASS_FLASH(EVT_CODE_FLASH_FLASH_ERR)

+#define EVT_ID_FLASHING_IMAGE					_CLASS_FLASH(EVT_CODE_FLASHING_IMAGE)

+#define EVT_ID_FLASHING_NEW_IMAGE_DONE			_CLASS_FLASH(EVT_CODE_FLASHING_NEW_IMAGE_DONE)

+#define EVT_ID_FLASH_PROGRAMMING_ERR			_CLASS_FLASH(EVT_CODE_FLASH_PROGRAMMING_ERR)

+#define EVT_ID_FLASH_PROGRAMMING_TIMEOUT		_CLASS_FLASH(EVT_CODE_FLASH_PROGRAMMING_TIMEOUT)

+#define EVT_ID_FLASH_UNKNOWN_CHIP_TYPE			_CLASS_FLASH(EVT_CODE_FLASH_UNKNOWN_CHIP_TYPE)

+#define EVT_ID_FLASH_UNKNOWN_CMD_SET			_CLASS_FLASH(EVT_CODE_FLASH_UNKNOWN_CMD_SET)

+#define EVT_ID_FLASH_VERIFY_FAILURE				_CLASS_FLASH(EVT_CODE_FLASH_VERIFY_FAILURE)

+#define EVT_ID_NVRAM_CORRUPT					_CLASS_FLASH(EVT_CODE_NVRAM_CORRUPT)

+#define EVT_ID_NVRAM_MISMACTH_OCCURED			_CLASS_FLASH(EVT_CODE_NVRAM_MISMACTH_OCCURED)

+

+

+// Event code for EVT_CLASS_CACHE(Cache)

+//

+

+#define _CLASS_CACHE(x)                (EVT_CLASS_CACHE << 16 | (x))

+

+#define EVT_ID_CACHE_NOT_RECV_FROM_TBBU			_CLASS_CACHE(EVT_CODE_CACHE_NOT_RECV_FROM_TBBU)

+#define EVT_ID_CACHE_RECVD_FROM_TBBU			_CLASS_CACHE(EVT_CODE_CACHE_RECVD_FROM_TBBU)

+#define EVT_ID_CACHE_CTRLER_CACHE_DISCARDED		_CLASS_CACHE(EVT_CODE_CACHE_CTRLER_CACHE_DISCARDED)

+#define EVT_ID_CACHE_FAIL_RECV_DUETO_MISMATCH	_CLASS_CACHE(EVT_CODE_CACHE_FAIL_RECV_DUETO_MISMATCH)

+#define EVT_ID_CACHE_DIRTY_DATA_DISCARDED		_CLASS_CACHE(EVT_CODE_CACHE_DIRTY_DATA_DISCARDED)

+#define EVT_ID_CACHE_FLUSH_RATE_CHANGED			_CLASS_CACHE(EVT_CODE_CACHE_FLUSH_RATE_CHANGED)

+

+

+//

+// Event code for EVT_CLASS_MISC

+//

+

+#define _CLASS_MISC(x)                (EVT_CLASS_MISC << 16 | (x))

+

+#define EVT_ID_MISC_CONFIG_CLEARED					_CLASS_MISC(EVT_CODE_MISC_CONFIG_CLEARED)		

+#define EVT_ID_MISC_CHANGE_BACK_ACTIVITY_RATE		_CLASS_MISC(EVT_CODE_MISC_CHANGE_BACK_ACTIVITY_RATE)

+#define EVT_ID_MISC_FATAL_FW_ERR					_CLASS_MISC(EVT_CODE_MISC_FATAL_FW_ERR)

+#define EVT_ID_MISC_FACTORY_DEFAULTS_RESTORED		_CLASS_MISC(EVT_CODE_MISC_FACTORY_DEFAULTS_RESTORED)

+#define EVT_ID_MISC_GET_HIBER_CMD					_CLASS_MISC(EVT_CODE_MISC_GET_HIBER_CMD)

+#define EVT_ID_MISC_MUTLI_BIT_ECC_ERR				_CLASS_MISC(EVT_CODE_MISC_MUTLI_BIT_ECC_ERR)

+#define EVT_ID_MISC_SINGLE_BIT_ECC_ERR				_CLASS_MISC(EVT_CODE_MISC_SINGLE_BIT_ECC_ERR)

+#define EVT_ID_MISC_GET_SHUTDOWN_CMD				_CLASS_MISC(EVT_CODE_MISC_GET_SHUTDOWN_CMD)

+#define EVT_ID_MISC_TIME_ESTABLISHED				_CLASS_MISC(EVT_CODE_MISC_TIME_ESTABLISHED)

+#define EVT_ID_MISC_USER_ENTERED_DEBUGGER			_CLASS_MISC(EVT_CODE_MISC_USER_ENTERED_DEBUGGER)

+#define EVT_ID_MISC_FORMAT_COMPLETE					_CLASS_MISC(EVT_CODE_MISC_FORMAT_COMPLETE)

+#define EVT_ID_MISC_FORMAT_STARTED					_CLASS_MISC(EVT_CODE_MISC_FORMAT_STARTED)

+#define EVT_ID_MISC_REASSIGN_WRITE_OP				_CLASS_MISC(EVT_CODE_MISC_REASSIGN_WRITE_OP)

+#define EVT_ID_MISC_UNEXPECTED_SENSE				_CLASS_MISC(EVT_CODE_MISC_UNEXPECTED_SENSE)

+#define EVT_ID_MISC_REPLACED_MISSING				_CLASS_MISC(EVT_CODE_MISC_REPLACED_MISSING)

+#define EVT_ID_MISC_NOT_A_CERTIFIED_DRIVE			_CLASS_MISC(EVT_CODE_MISC_NOT_A_CERTIFIED_DRIVE)

+

+/* May put into other group???*/

+#define EVT_ID_MISC_PD_MISSING_FROM_CONFIG_AT_BOOT	_CLASS_MISC(EVT_CODE_MISC_PD_MISSING_FROM_CONFIG_AT_BOOT)

+#define EVT_ID_MISC_VD_MISSING_DRIVES				_CLASS_MISC(EVT_CODE_MISC_VD_MISSING_DRIVES)

+#define EVT_ID_MISC_VD_MISSING_AT_BOOT				_CLASS_MISC(EVT_CODE_MISC_VD_MISSING_AT_BOOT)

+#define EVT_ID_MISC_PREVIOUS_CONFIG_MISSING_AT_BOOT _CLASS_MISC(EVT_CODE_MISC_PREVIOUS_CONFIG_MISSING_AT_BOOT)

+#define EVT_ID_MISC_PD_TOO_SMALL_FOR_AUTOREBUILD	_CLASS_MISC(EVT_CODE_MISC_PD_TOO_SMALL_FOR_AUTOREBUILD)

+

+#endif

+

diff --git a/drivers/scsi/thor/include/generic/com_struct.h b/drivers/scsi/thor/include/generic/com_struct.h
new file mode 100755
index 0000000..e7693d9
--- /dev/null
+++ b/drivers/scsi/thor/include/generic/com_struct.h
@@ -0,0 +1,684 @@
+#ifndef __MV_COM_STRUCT_H__

+#define __MV_COM_STRUCT_H__

+

+#include "com_define.h"

+

+#define GET_ALL                                 0xFF

+#define ID_UNKNOWN                              0x7F

+

+#define MAX_NUM_ADAPTERS                        2

+

+#ifndef _OS_BIOS

+/* The following MAX number are to support ALL products. */

+#define MAX_HD_SUPPORTED_API                    128

+#define MAX_EXPANDER_SUPPORTED_API              16

+#define MAX_PM_SUPPORTED_API                    8

+#define MAX_LD_SUPPORTED_API                    32

+#define MAX_BLOCK_SUPPORTED_API                 512

+#define MAX_BLOCK_PER_HD_SUPPORTED_API          16

+#endif /* _OS_BIOS */

+

+#define MAX_BGA_RATE                            0xFA

+#define MAX_MEDIAPATROL_RATE                    0xFF

+

+#ifndef MV_GUID_SIZE

+#define MV_GUID_SIZE                            8

+#endif /* MV_GUID_SIZE */

+

+#define LD_MAX_NAME_LENGTH                      16

+

+#define CACHE_WRITEBACK_ENABLE                  0

+#define CACHE_WRITETHRU_ENABLE                  1

+#define CACHE_ADAPTIVE_ENABLE                   2

+#define CACHE_WRITE_POLICY_FILTER               (CACHE_WRITEBACK_ENABLE | \

+						 CACHE_WRITETHRU_ENABLE | \

+						 CACHE_ADAPTIVE_ENABLE)

+#define CACHE_LOOKAHEAD_ENABLE                  MV_BIT(2)

+

+//The Flags of Eroor Handling

+#define EH_READ_VERIFY_REQ_ERROR		MV_BIT(0)

+#define EH_WRITE_REQ_ERROR			MV_BIT(1)

+#define EH_WRITE_RECOVERY_ERROR			MV_BIT(2)

+#define EH_MEDIA_ERROR				MV_BIT(3)

+#define EH_TIMEOUT_ERROR			MV_BIT(4)

+

+#define CONSISTENCYCHECK_ONLY                   0

+#define CONSISTENCYCHECK_FIX                    1

+

+#define INIT_QUICK                              0    //Just initialize first part size of LD

+#define INIT_FULLFOREGROUND                     1    //Initialize full LD size

+#define INIT_FULLBACKGROUND                     2    //Initialize full LD size background

+#define INIT_NONE                               3

+

+#define INIT_QUICK_WITHOUT_EVENT				0xf	 // Used for QUICK INIT but set cdb[5]to 0xf so driver won't send event. 

+

+#define BGA_CONTROL_START                       0

+#define BGA_CONTROL_RESTART                     1

+#define BGA_CONTROL_PAUSE                       2

+#define BGA_CONTROL_RESUME                      3

+#define BGA_CONTROL_ABORT                       4

+#define BGA_CONTROL_COMPLETE                    5

+#define BGA_CONTROL_IN_PROCESS                  6

+#define BGA_CONTROL_TERMINATE_IMMEDIATE         7

+#define BGA_CONTROL_AUTO_PAUSE                  8

+

+#define LD_STATUS_FUNCTIONAL                    0

+#define LD_STATUS_DEGRADE                       1

+#define LD_STATUS_DELETED                       2

+#define LD_STATUS_MISSING                       3 /* LD missing in system. */

+#define LD_STATUS_OFFLINE                       4

+#define LD_STATUS_PARTIALLYOPTIMAL              5 /* r6 w/ 2 pd, 1 hd drops */

+#define LD_STATUS_INVALID                       0xFF

+

+#define LD_BGA_NONE                             0

+#define LD_BGA_REBUILD                          MV_BIT(0)

+#define LD_BGA_CONSISTENCY_FIX                  MV_BIT(1)

+#define LD_BGA_CONSISTENCY_CHECK                MV_BIT(2)

+#define LD_BGA_INIT_QUICK                       MV_BIT(3)

+#define LD_BGA_INIT_BACK                        MV_BIT(4)

+#define LD_BGA_MIGRATION                        MV_BIT(5)

+#define LD_BGA_INIT_FORE                        MV_BIT(6)                     

+

+#define LD_BGA_STATE_NONE                       0

+#define LD_BGA_STATE_RUNNING                    1

+#define LD_BGA_STATE_ABORTED                    2

+#define LD_BGA_STATE_PAUSED                     3

+#define LD_BGA_STATE_AUTOPAUSED                 4

+#define LD_BGA_STATE_DDF_PENDING                MV_BIT(7)

+

+#define LD_MODE_RAID0                           0x0

+#define LD_MODE_RAID1                           0x1

+#define LD_MODE_RAID5                           0x5

+#define LD_MODE_RAID6                           0x6

+#define LD_MODE_JBOD                            0x0f

+#define LD_MODE_RAID10                          0x10

+#define LD_MODE_RAID1E                          0x11

+#define LD_MODE_RAID50                          0x50

+#define LD_MODE_RAID60                          0x60

+#define LD_MODE_UNKNOWN							0xFF

+

+#define HD_WIPE_MDD                             0

+#define HD_WIPE_FORCE                           1

+

+#define ROUNDING_SCHEME_NONE                    0     /* no rounding */

+#define ROUNDING_SCHEME_1GB                     1     /* 1 GB rounding */

+#define ROUNDING_SCHEME_10GB                    2     /* 10 GB rounding */

+

+#define DEVICE_TYPE_NONE                        0

+#define DEVICE_TYPE_HD                          1		//  DT_DIRECT_ACCESS_BLOCK

+#define DEVICE_TYPE_PM                          2

+#define DEVICE_TYPE_EXPANDER                    3		// DT_EXPANDER

+#define DEVICE_TYPE_TAPE						4		// DT_SEQ_ACCESS

+#define DEVICE_TYPE_PRINTER						5		// DT_PRINTER

+#define DEVICE_TYPE_PROCESSOR					6		// DT_PROCESSOR

+#define DEVICE_TYPE_WRITE_ONCE					7 		// DT_WRITE_ONCE

+#define DEVICE_TYPE_CD_DVD						8		// DT_CD_DVD

+#define DEVICE_TYPE_OPTICAL_MEMORY				9 		// DT_OPTICAL_MEMORY

+#define DEVICE_TYPE_MEDIA_CHANGER				10		// DT_MEDIA_CHANGER

+#define DEVICE_TYPE_ENCLOSURE					11		// DT_ENCLOSURE

+#define DEVICE_TYPE_PORT                        0xFF	// DT_STORAGE_ARRAY_CTRL

+

+#define HD_STATUS_FREE                          MV_BIT(0)

+#define HD_STATUS_ASSIGNED                      MV_BIT(1)

+#define HD_STATUS_SPARE                         MV_BIT(2)

+#define HD_STATUS_OFFLINE                       MV_BIT(3)

+#define HD_STATUS_SMARTCHECKING                 MV_BIT(4)

+#define HD_STATUS_MP                            MV_BIT(5)

+

+#define HD_BGA_STATE_NONE                       LD_BGA_STATE_NONE

+#define HD_BGA_STATE_RUNNING                    LD_BGA_STATE_RUNNING

+#define HD_BGA_STATE_ABORTED                    LD_BGA_STATE_ABORTED

+#define HD_BGA_STATE_PAUSED                     LD_BGA_STATE_PAUSED

+#define HD_BGA_STATE_AUTOPAUSED                 LD_BGA_STATE_AUTOPAUSED

+

+#define HD_BGA_TYPE_NONE						0

+#define HD_BGA_TYPE_MP							1

+#define HD_BGA_TYPE_DATASCRUB					2

+

+#define GLOBAL_SPARE_DISK                       MV_BIT(2)

+

+#define PD_DDF_VALID                            MV_BIT(0)

+#define PD_DISK_VALID                           MV_BIT(1)

+#define PD_DDF_CLEAN                            MV_BIT(2)

+#define PD_NEED_UPDATE                          MV_BIT(3)

+#define PD_MBR_VALID                            MV_BIT(4)

+#define PD_NEED_FLUSH                           MV_BIT(5)

+#define PD_CLEAR_MBR                            MV_BIT(6)

+#if ERROR_HANDLING_SUPPORT

+#define PD_RCT_NEED_UPDATE             			MV_BIT(7)

+#endif

+

+#define PD_STATE_ONLINE                         MV_BIT(0)

+#define PD_STATE_FAILED                         MV_BIT(1)

+#define PD_STATE_REBUILDING                     MV_BIT(2)

+#define PD_STATE_TRANSITION                     MV_BIT(3)

+#define PD_STATE_SMART_ERROR                    MV_BIT(4)

+#define PD_STATE_READ_ERROR                     MV_BIT(5)

+#define PD_STATE_MISSING                        MV_BIT(6)

+

+#define HD_STATUS_SETONLINE                     0

+#define HD_STATUS_SETOFFLINE                    1

+#define HD_STATUS_INVALID                       0xFF

+

+// Definition used for old driver.

+#define HD_TYPE_SATA                            MV_BIT(0)

+#define HD_TYPE_PATA                            MV_BIT(1)

+#define HD_TYPE_SAS                             MV_BIT(2)

+#define HD_TYPE_ATAPI                           MV_BIT(3)

+#define HD_TYPE_TAPE                            MV_BIT(4)

+#define HD_TYPE_SES                             MV_BIT(5)

+

+// PD's Protocol/Connection type (used by new driver)

+#define DC_ATA		MV_BIT(0)

+#define DC_SCSI		MV_BIT(1)

+#define DC_SERIAL	MV_BIT(2)

+#define DC_PARALLEL	MV_BIT(3)

+#define DC_ATAPI	MV_BIT(4)		// used by core driver to prepare FIS

+

+// PD's Device type defined in SCSI-III specification (used by new driver)

+#define DT_DIRECT_ACCESS_BLOCK	0x00

+#define DT_SEQ_ACCESS			0x01

+#define DT_PRINTER				0x02

+#define DT_PROCESSOR			0x03

+#define DT_WRITE_ONCE			0x04

+#define DT_CD_DVD				0x05

+#define DT_OPTICAL_MEMORY		0x07

+#define DT_MEDIA_CHANGER		0x08

+#define DT_STORAGE_ARRAY_CTRL	0x0C

+#define DT_ENCLOSURE			0x0D

+// The following are defined by Marvell

+#define DT_EXPANDER				0x20

+#define DT_PM					0x21

+

+

+

+#define HD_FEATURE_NCQ                          MV_BIT(0)	/* Capability */

+#define HD_FEATURE_TCQ                          MV_BIT(1)

+#define HD_FEATURE_1_5G                         MV_BIT(2)

+#define HD_FEATURE_3G                           MV_BIT(3)

+#define HD_FEATURE_WRITE_CACHE                  MV_BIT(4)

+#define HD_FEATURE_48BITS                       MV_BIT(5)

+#define HD_FEATURE_SMART                        MV_BIT(6)

+

+#define HD_SPEED_1_5G							1		// current 

+#define HD_SPEED_3G								2

+

+#define EXP_SSP                                 MV_BIT(0)

+#define EXP_STP                                 MV_BIT(1)

+#define EXP_SMP                                 MV_BIT(2)

+

+#define HD_DMA_NONE                             0

+#define HD_DMA_1                                1

+#define HD_DMA_2                                2

+#define HD_DMA_3                                3

+#define HD_DMA_4                                4

+#define HD_DMA_5                                5

+#define HD_DMA_6                                6

+#define HD_DMA_7                                7

+#define HD_DMA_8                                8

+#define HD_DMA_9                                9

+

+#define HD_PIO_NONE                             0

+#define HD_PIO_1                                1

+#define HD_PIO_2                                2

+#define HD_PIO_3                                3

+#define HD_PIO_4                                4

+#define HD_PIO_5                                5

+

+#define HD_XCQ_OFF                              0

+#define HD_NCQ_ON                               1

+#define HD_TCQ_ON                               2

+

+#define SECTOR_LENGTH                           512

+#define SECTOR_WRITE                            0

+#define SECTOR_READ                             1

+

+#define DBG_LD2HD                               0

+#define DBG_HD2LD                               1

+

+#define DRIVER_LENGTH                           1024*16

+#define FLASH_DOWNLOAD                          0xf0

+#define FLASH_UPLOAD                            0xf

+#define    FLASH_TYPE_CONFIG                    0

+#define    FLASH_TYPE_BIN                       1

+#define    FLASH_TYPE_BIOS                      2

+#define    FLASH_TYPE_FIRMWARE                  3

+

+#define BLOCK_INVALID                           0

+#define BLOCK_VALID                             MV_BIT(0)

+#define BLOCK_ASSIGNED                          MV_BIT(1)

+

+#ifdef _OS_BIOS

+#define FREE_BLOCK(Flags)       (Flags&(BLOCK_VALID) == Flags)

+#define ASSIGN_BLOCK(Flags)     (Flags&(BLOCK_VALID|BLOCK_ASSIGNED) == Flags)

+#define INVALID_BLOCK(Flags)    (Flags&(BLOCK_VALID|BLOCK_ASSIGNED) == 0) 

+#endif /* _OS_BIOS */

+

+/* Target device type */

+#define TARGET_TYPE_LD                    0

+#define TARGET_TYPE_FREE_PD               1

+

+/*

+#define BLOCK_STATUS_NORMAL                     0

+#define BLOCK_STATUS_REBUILDING                 MV_BIT(0)

+#define BLOCK_STATUS_CONSISTENTCHECKING         MV_BIT(1)

+#define BLOCK_STATUS_INITIALIZING               MV_BIT(2)

+#define BLOCK_STATUS_MIGRATING                  MV_BIT(3)

+#define BLOCK_STATUS_OFFLINE                    MV_BIT(4)

+*/

+#define MAX_WIDEPORT_PHYS                       8

+

+#ifndef _OS_BIOS

+#pragma pack(8)

+#endif /* _OS_BIOS */

+

+typedef struct _Link_Endpoint 

+{

+	MV_U16      DevID;

+	MV_U8       DevType;         /* Refer to DEVICE_TYPE_xxx, (additional

+					type like EDGE_EXPANDER and 

+					FANOUT_EXPANDER might be added). */

+	MV_U8       PhyCnt;          /* Number of PHYs for this endpoint.  

+					Greater than 1 if it is wide port. */

+	MV_U8       PhyID[MAX_WIDEPORT_PHYS];    /* Assuming wide port has 

+						    max of 8 PHYs. */

+	MV_U8       SAS_Address[8];  /* Filled with 0 if not SAS device. */

+	MV_U8       Reserved1[8];

+} Link_Endpoint, * PLink_Endpoint;

+

+typedef struct _Link_Entity 

+{

+	Link_Endpoint    Parent;

+	MV_U8            Reserved[8];

+	Link_Endpoint    Self;

+} Link_Entity,  *PLink_Entity;

+

+typedef struct _Version_Info

+{

+	MV_U32        VerMajor;

+	MV_U32        VerMinor;

+	MV_U32        VerOEM;

+	MV_U32        VerBuild;

+}Version_Info, *PVersion_Info;

+

+#define BASE_ADDRESS_MAX_NUM                    6

+

+#define SUPPORT_LD_MODE_RAID0                   MV_BIT(0)

+#define SUPPORT_LD_MODE_RAID1                   MV_BIT(1)

+#define SUPPORT_LD_MODE_RAID10                  MV_BIT(2)

+#define SUPPORT_LD_MODE_RAID1E                  MV_BIT(3)

+#define SUPPORT_LD_MODE_RAID5                   MV_BIT(4)

+#define SUPPORT_LD_MODE_RAID6                   MV_BIT(5)

+#define SUPPORT_LD_MODE_RAID50                  MV_BIT(6)

+#define SUPPORT_LD_MODE_JBOD                    MV_BIT(7)

+

+#define FEATURE_BGA_REBUILD_SUPPORT             MV_BIT(0)

+#define FEATURE_BGA_BKINIT_SUPPORT				MV_BIT(1)

+#define FEATURE_BGA_SYNC_SUPPORT				MV_BIT(2)

+#define FEATURE_BGA_MIGRATION_SUPPORT           MV_BIT(3)

+#define FEATURE_BGA_MEDIAPATROL_SUPPORT         MV_BIT(4)

+

+typedef struct _Adapter_Info 

+{

+	Version_Info    DriverVersion;

+	Version_Info    BIOSVersion;

+	MV_U64          Reserved1[2];     /* Reserve for firmware */

+

+	MV_U32          SystemIOBusNumber;

+	MV_U32          SlotNumber;

+	MV_U32          InterruptLevel;

+	MV_U32          InterruptVector;

+    

+	MV_U16          VenID;

+	MV_U16          SubVenID;

+	MV_U16          DevID;

+	MV_U16          SubDevID;

+    

+	MV_U8           PortCount;        /* How many ports, like 4 ports,  

+					     or 4S1P. */

+	MV_U8           PortSupportType;  /* Like SATA port, SAS port, 

+					     PATA port, use MV_BIT */

+	MV_U8           Features;         /* Feature bits.  See FEATURE_XXX.

+					     If corresponding bit is set, 

+					     that feature is supported. */

+	MV_BOOLEAN      AlarmSupport;

+	MV_U8           RevisionID;		/* Chip revision */

+	MV_U8           Reserved2[11];

+    

+	MV_U8           MaxTotalBlocks;    

+	MV_U8           MaxBlockPerPD;

+	MV_U8           MaxHD;

+	MV_U8           MaxExpander;

+	MV_U8           MaxPM;

+	MV_U8           MaxLogicalDrive;

+	MV_U16          LogicalDriverMode;

+

+	MV_U8           WWN[8];            /* For future VDS use. */

+} Adapter_Info, *PAdapter_Info;

+

+typedef struct _Adapter_Config {

+	MV_BOOLEAN      AlarmOn;

+	MV_BOOLEAN      AutoRebuildOn;

+	MV_U8           BGARate;

+	MV_BOOLEAN      PollSMARTStatus;

+	MV_U8           MediaPatrolRate;

+	MV_U8           Reserved[3];

+} Adapter_Config, *PAdapter_Config;

+

+typedef struct _HD_Info

+{

+	Link_Entity     Link;             /* Including self DevID & DevType */

+	MV_U8           AdapterID;

+	MV_U8           Status;           /* Refer to HD_STATUS_XXX */

+	MV_U8           HDType;           /* HD_Type_xxx, replaced by new driver with ConnectionType & DeviceType */

+	MV_U8           PIOMode;		  /* Max PIO mode */

+	MV_U8           MDMAMode;		  /* Max MDMA mode */

+	MV_U8           UDMAMode;		  /* Max UDMA mode */

+	MV_U8           ConnectionType;	  /* DC_XXX, ConnectionType & DeviceType in new driver to replace HDType above */

+	MV_U8           DeviceType;	      /* DT_XXX */

+

+	MV_U32          FeatureSupport;   /* Support 1.5G, 3G, TCQ, NCQ, and

+					     etc, MV_BIT related */

+	MV_U8           Model[40];

+	MV_U8           SerialNo[20];

+	MV_U8           FWVersion[8];

+	MV_U64          Size;             /* unit: 1KB */

+	MV_U8           WWN[8];          /* ATA/ATAPI-8 has such definitions 

+					     for the identify buffer */

+	MV_U8           CurrentPIOMode;		/* Current PIO mode */

+	MV_U8           CurrentMDMAMode;	/* Current MDMA mode */

+	MV_U8           CurrentUDMAMode;	/* Current UDMA mode */

+	MV_U8			Reserved3[5];

+//	MV_U32			FeatureEnable;		

+

+	MV_U8           Reserved4[80];

+}HD_Info, *PHD_Info;

+

+typedef struct _HD_MBR_Info

+{

+	MV_U8           HDCount;

+	MV_U8           Reserved[7];

+	MV_U16          HDIDs[MAX_HD_SUPPORTED_API];    

+	MV_BOOLEAN      hasMBR[MAX_HD_SUPPORTED_API];

+} HD_MBR_Info, *PHD_MBR_Info;

+

+

+typedef struct _HD_FreeSpaceInfo

+{

+	MV_U16          ID;               /* ID should be unique*/

+	MV_U8           AdapterID;

+	MV_U8           Reserved[4];

+	MV_BOOLEAN      isFixed;

+

+	MV_U64          Size;             /* unit: 1KB */

+}HD_FreeSpaceInfo, *PHD_FreeSpaceInfo;

+

+typedef struct _HD_Block_Info

+{

+	MV_U16          ID;               /* ID in the HD_Info*/

+	MV_U8           Type;             /* Refer to DEVICE_TYPE_xxx */

+	MV_U8           Reserved1[5];

+

+	/* Free is 0xff */

+	MV_U16          BlockIDs[MAX_BLOCK_PER_HD_SUPPORTED_API];  

+}HD_Block_Info, *PHD_Block_Info;

+

+typedef struct _Exp_Info

+{

+	Link_Entity       Link;            /* Including self DevID & DevType */

+	MV_U8             AdapterID;

+	MV_BOOLEAN        Configuring;      

+	MV_BOOLEAN        RouteTableConfigurable;

+	MV_U8             PhyCount;

+	MV_U16            ExpChangeCount;

+	MV_U16            MaxRouteIndexes;

+	MV_U8             VendorID[8+1];

+	MV_U8             ProductID[16+1];

+	MV_U8             ProductRev[4+1];

+	MV_U8             ComponentVendorID[8+1];

+	MV_U16            ComponentID;

+	MV_U8             ComponentRevisionID;

+	MV_U8             Reserved1[17];

+}Exp_Info, * PExp_Info;

+

+typedef  struct _PM_Info{

+	Link_Entity       Link;           /* Including self DevID & DevType */

+	MV_U8             AdapterID;

+	MV_U8             ProductRevision;

+	MV_U8             PMSpecRevision; /* 10 means 1.0, 11 means 1.1 */

+	MV_U8             NumberOfPorts;

+	MV_U16            VendorId;

+	MV_U16            DeviceId;

+	MV_U8             Reserved1[8];

+}PM_Info, *PPM_Info;

+

+typedef struct _HD_CONFIG

+{

+	MV_BOOLEAN        WriteCacheOn;   /* 1: enable write cache */

+	MV_BOOLEAN        SMARTOn;        /* 1: enable S.M.A.R.T */

+	MV_BOOLEAN        Online;         /* 1: to set HD online */

+	MV_U8             DriveSpeed;	  // For SATA & SAS.  HD_SPEED_1_5G, HD_SPEED_3G etc

+	MV_U8             Reserved[2];

+	MV_U16            HDID;

+}HD_Config, *PHD_Config;

+

+typedef struct  _HD_STATUS

+{

+	MV_BOOLEAN        SmartThresholdExceeded;        

+	MV_U8             Reserved[1];

+	MV_U16            HDID;

+}HD_Status, *PHD_Status;

+

+typedef struct  _SPARE_STATUS

+{

+	MV_U16            HDID;

+	MV_U16            LDID;

+	MV_U8             Status;         /* HD_STATUS_SPARE */

+	MV_U8             Reserved[3];

+}Spare_Status, *PSpare_Status;

+

+typedef struct  _BSL{

+	MV_U64            LBA;            /* Bad sector LBA for the HD. */

+

+	MV_U32            Count;          /* How many serial bad sectors */

+	MV_BOOLEAN        Flag;           /* Fake bad sector or not. */

+	MV_U8             Reserved[3];

+}BSL,*PBSL;

+

+typedef struct _BLOCK_INFO

+{

+	MV_U16            ID;

+	MV_U16            HDID;           /* ID in the HD_Info */

+	MV_U16            Flags;          /* Refer to BLOCK_XXX definition */

+	MV_U16            LDID;           /* Belong to which LD */

+

+	MV_U8             Status;         /* Refer to BLOCK_STATUS_XXX*/

+	MV_U8             Reserved[3];

+	MV_U32            ReservedSpaceForMigration;	/* Space reserved for migration */

+

+	MV_U64            StartLBA;       /* unit: 512 bytes */

+	MV_U64            Size;           /* unit: 512 bytes, including ReservedSpaceForMigration */

+}Block_Info, *PBlock_Info;

+

+typedef struct _LD_Info

+{

+	MV_U16            ID;

+	MV_U8             Status;         /* Refer to LD_STATUS_xxx */

+	MV_U8             BGAStatus;      /* Refer to LD_BGA_STATE_xxx */

+	MV_U16            StripeBlockSize;/* unit: 512 bytes */

+	MV_U8             RaidMode;            

+	MV_U8             HDCount;

+

+	MV_U8             CacheMode;      /* Default is CacheMode_Default, 

+					     see above */

+	MV_U8             LD_GUID[MV_GUID_SIZE];

+	MV_U8             SectorCoefficient; /* (sector size) 1=>512 (default)

+						, 2=>1024, 4=>2048, 8=>4096 */

+	MV_U8             AdapterID;

+	MV_U8             Reserved[5];

+

+	MV_U64            Size;           /* LD size, unit: 512 bytes */

+

+	MV_U8             Name[LD_MAX_NAME_LENGTH];

+

+	MV_U16            BlockIDs[MAX_HD_SUPPORTED_API];        /* 32 */

+/* 

+ * According to BLOCK ID, to get the related HD ID, then WMRU can 

+ * draw the related graph like above.

+ */

+	MV_U8             SubLDCount;     /* for raid 10, 50,60 */

+	MV_U8             NumParityDisk;  /* For RAID 6. */

+	MV_U8             Reserved1[6];

+}LD_Info, *PLD_Info;

+

+typedef struct _Create_LD_Param

+{

+	MV_U8             RaidMode;

+	MV_U8             HDCount;

+	MV_U8             RoundingScheme; /* please refer to the definitions

+					     of  ROUNDING_SCHEME_XXX. */

+	MV_U8             SubLDCount;     /* for raid 10,50,60 */

+	MV_U16            StripeBlockSize;/*In sectors unit: 1KB */

+	MV_U8             NumParityDisk;  /* For RAID 6. */

+	MV_U8             CachePolicy;    /* please refer to the definitions

+					     of CACHEMODE_XXXX. */

+

+	MV_U8             InitializationOption;/* please refer to the 

+						 definitions of INIT_XXXX. */

+	MV_U8             SectorCoefficient; /* (sector size) 1=>512 

+						(default), 2=>1024, 4=>2048,

+						8=>4096 */

+	MV_U16            LDID;               /* ID of the LD to be migrated 

+						 or expanded */

+	MV_U8             Reserved2[4];

+

+	MV_U16            HDIDs[MAX_HD_SUPPORTED_API];    /* 32 */

+	MV_U8             Name[LD_MAX_NAME_LENGTH];

+

+	MV_U64            Size;           /* size of LD in sectors */

+} Create_LD_Param, *PCreate_LD_Param;

+

+typedef struct _LD_STATUS

+{

+	MV_U8            Status;          /* Refer to LD_STATUS_xxx */

+	MV_U8            Bga;             /* Refer to LD_BGA_xxx */

+	MV_U16           BgaPercentage;   /* xx% */

+	MV_U8            BgaState;        /* Refer to LD_BGA_STATE_xxx */

+	MV_U8            Reserved[1];

+	MV_U16           LDID;

+} LD_Status, *PLD_Status;

+

+typedef struct    _LD_Config

+{

+	MV_U8            CacheMode;        /* See definition 4.4.1 

+					      CacheMode_xxx */

+	MV_U8            Reserved1;        

+	MV_BOOLEAN       AutoRebuildOn;    /* 1- AutoRebuild On */

+	MV_U8            Status;

+	MV_U16           LDID;

+	MV_U8            Reserved2[2];

+

+	MV_U8            Name[LD_MAX_NAME_LENGTH];

+}LD_Config, * PLD_Config;

+

+// Giving TargetID and LUN, returns it Type and DeviceID.  If returned Type or DeviceID is 0xFF, not found.

+typedef struct    _TargetLunType

+{

+	MV_U8            AdapterID;

+	MV_U8            TargetID;       

+	MV_U8            Lun;        

+	MV_U8            Type;		// TARGET_TYPE_LD or TARGET_TYPE_FREE_PD

+	MV_U16           DeviceID;	// LD ID or PD ID depends on Type  

+	MV_U8            Reserved[30];

+}TargetLunType, * PTargetLunType;

+

+typedef struct _HD_MPSTATUS

+{

+	MV_U16            HDID;

+	MV_U16            LoopCount;      /* loop count */

+	MV_U16            ErrorCount;     /* error detected during media patrol */

+	MV_U16            Percentage;     /* xx% */

+	MV_U8             Status;         /* Refer to HD_BGA_STATE_xxx */

+	MV_U8             Type;

+	MV_U8             Reserved[50];  

+}HD_MPStatus, *PHD_MPStatus;

+

+typedef struct _HD_BGA_STATUS

+{

+	MV_U16            HDID;

+	MV_U16            Percentage;     /* xx% */

+	MV_U8             Bga;             /* Refer to HD_BGA_TYPE_xxx */

+	MV_U8             Status;          /* Refer to HD_STATUS_xxx */

+	MV_U8             BgaStatus;         /* Refer to HD_BGA_STATE_xxx */

+	MV_U8             Reserved[1];  

+}HD_BGA_Status, *PHD_BGA_Status;

+

+typedef struct _RCT_Record{

+	MV_LBA lba;

+	MV_U32 sec;	//sector count

+	MV_U8   flag;

+	MV_U8   rev[3];

+}RCT_Record, *PRCT_Record;

+

+typedef struct _DBG_DATA

+{

+	MV_U64            LBA;

+	MV_U64            Size;

+	MV_U8             Data[SECTOR_LENGTH];

+}DBG_Data, *PDBG_Data;

+

+typedef struct _DBG_HD

+{

+	MV_U64            LBA;

+	MV_U16            HDID;

+	MV_BOOLEAN        isUsed;

+	MV_U8             Reserved[5];

+}DBG_HD;

+

+typedef struct _DBG_MAP

+{

+	MV_U64            LBA;

+	MV_U16            LDID;

+	MV_BOOLEAN        isUsed;

+	MV_U8             Reserved[5];

+	DBG_HD            HDs[MAX_HD_SUPPORTED_API];

+}DBG_Map, *PDBG_Map;

+

+#ifdef CACHE_MODULE_SUPPORT

+typedef struct _LD_CACHE_STATUS

+{

+	MV_BOOLEAN       IsOnline;

+	MV_U8            CachePolicy;

+	MV_U16           StripeUnitSize;

+	MV_U32           StripeSize;

+	MV_U8            Sector_Coefficient;

+	MV_U8            RAID_Level;

+	MV_U8            Reserved[6];

+	MV_LBA	         MAX_LBA;

+#ifdef _DDR_BBU_ENABLE

+	MV_U8				LD_GUID[MV_GUID_SIZE];

+#endif

+}

+LD_CACHE_STATUS, *PLD_CACHE_STATUS;

+#endif /* CACHE_MODULE_SUPPORT */

+

+#define MAX_PASS_THRU_DATA_BUFFER_SIZE (SECTOR_LENGTH+128)

+

+typedef struct {

+	// We put Data_Buffer[] at the very beginning of this structure because SCSI commander did so.

+	MV_U8			Data_Buffer[MAX_PASS_THRU_DATA_BUFFER_SIZE];  // set by driver if read, by application if write

+	MV_U8			Reserved1[128];

+    MV_U32			Data_Length;	// set by driver if read, by application if write 

+	MV_U16			DevId;		//	PD ID (used by application only)

+	MV_U8			CDB_Type;	// define a CDB type for each CDB category (used by application only)

+	MV_U8			Reserved2;

+	MV_U32			lba;

+	MV_U8			Reserved3[64];

+} PassThrough_Config, * PPassThorugh_Config;

+

+

+#ifndef _OS_BIOS

+#pragma pack()

+#endif /* _OS_BIOS */

+

+#endif /*  __MV_COM_STRUCT_H__ */

diff --git a/drivers/scsi/thor/include/icommon/com_api.h b/drivers/scsi/thor/include/icommon/com_api.h
new file mode 100755
index 0000000..1ab210a
--- /dev/null
+++ b/drivers/scsi/thor/include/icommon/com_api.h
@@ -0,0 +1,168 @@
+#ifndef  __MV_COM_API_H__

+#define  __MV_COM_API_H__

+

+#define MAX_CDB_SIZE                           16  

+

+/* CDB definitions */

+#define APICDB0_ADAPTER                        0xF0

+#define APICDB0_LD                             0xF1

+#define APICDB0_BLOCK                          0xF2

+#define APICDB0_PD                             0xF3

+#define APICDB0_EVENT                          0xF4

+#define APICDB0_DBG                            0xF5

+#define APICDB0_FLASH                          0xF6

+

+/* for Adapter */

+#define APICDB1_ADAPTER_GETCOUNT               0

+#define APICDB1_ADAPTER_GETINFO                (APICDB1_ADAPTER_GETCOUNT + 1)

+#define APICDB1_ADAPTER_GETCONFIG              (APICDB1_ADAPTER_GETCOUNT + 2)

+#define APICDB1_ADAPTER_SETCONFIG              (APICDB1_ADAPTER_GETCOUNT + 3)

+#define APICDB1_ADAPTER_POWER_STATE_CHANGE     (APICDB1_ADAPTER_GETCOUNT + 4)

+#define APICDB1_ADAPTER_MAX                    (APICDB1_ADAPTER_GETCOUNT + 5)

+

+/* for LD */

+#define APICDB1_LD_CREATE                      0

+#define APICDB1_LD_GETMAXSIZE                  (APICDB1_LD_CREATE + 1)

+#define APICDB1_LD_GETINFO                     (APICDB1_LD_CREATE + 2)

+#define APICDB1_LD_GETTARGETLDINFO             (APICDB1_LD_CREATE + 3)

+#define APICDB1_LD_DELETE                      (APICDB1_LD_CREATE + 4)

+#define APICDB1_LD_GETSTATUS                   (APICDB1_LD_CREATE + 5)

+#define APICDB1_LD_GETCONFIG                   (APICDB1_LD_CREATE + 6)

+#define APICDB1_LD_SETCONFIG                   (APICDB1_LD_CREATE + 7)

+#define APICDB1_LD_STARTREBUILD                (APICDB1_LD_CREATE + 8)

+#define APICDB1_LD_STARTCONSISTENCYCHECK       (APICDB1_LD_CREATE + 9)

+#define APICDB1_LD_STARTINIT                   (APICDB1_LD_CREATE + 10)

+#define APICDB1_LD_STARTMIGRATION              (APICDB1_LD_CREATE + 11)

+#define APICDB1_LD_BGACONTROL                  (APICDB1_LD_CREATE + 12)

+#define APICDB1_LD_WIPEMDD                     (APICDB1_LD_CREATE + 13)

+#define APICDB1_LD_GETSPARESTATUS              (APICDB1_LD_CREATE + 14)

+#define APICDB1_LD_SETGLOBALSPARE              (APICDB1_LD_CREATE + 15)

+#define APICDB1_LD_SETLDSPARE                  (APICDB1_LD_CREATE + 16)

+#define APICDB1_LD_REMOVESPARE                 (APICDB1_LD_CREATE + 17)

+#define APICDB1_LD_HD_SETSTATUS                (APICDB1_LD_CREATE + 18)

+#define APICDB1_LD_SHUTDOWN                    (APICDB1_LD_CREATE + 19)

+#define APICDB1_LD_HD_FREE_SPACE_INFO          (APICDB1_LD_CREATE + 20)

+#define APICDB1_LD_HD_GETMBRINFO               (APICDB1_LD_CREATE + 21)

+#define APICDB1_LD_SIZEOF_MIGRATE_TARGET       (APICDB1_LD_CREATE + 22)

+#define APICDB1_LD_TARGET_LUN_TYPE			   (APICDB1_LD_CREATE + 23)

+#define APICDB1_LD_HD_MPCHECK                  (APICDB1_LD_CREATE + 24)

+#define APICDB1_LD_HD_GETMPSTATUS              (APICDB1_LD_CREATE + 25)

+#define APICDB1_LD_HD_GET_RCT_COUNT            (APICDB1_LD_CREATE + 26)

+#define APICDB1_LD_HD_RCT_REPORT               (APICDB1_LD_CREATE + 27)

+#define APICDB1_LD_HD_START_DATASCRUB          (APICDB1_LD_CREATE + 28)	// temp

+#define APICDB1_LD_HD_BGACONTROL	           (APICDB1_LD_CREATE + 29)	// temp

+#define APICDB1_LD_HD_GETBGASTATUS             (APICDB1_LD_CREATE + 30)	// temp

+// Added reserved for future expansion so that MRU/CLI can be backward compatible with drier.

+#define APICDB1_LD_RESERVED1				   (APICDB1_LD_CREATE + 31)	

+#define APICDB1_LD_RESERVED2				   (APICDB1_LD_CREATE + 32)	

+#define APICDB1_LD_RESERVED3				   (APICDB1_LD_CREATE + 33)	

+#define APICDB1_LD_RESERVED4				   (APICDB1_LD_CREATE + 34)	

+#define APICDB1_LD_RESERVED5				   (APICDB1_LD_CREATE + 35)	

+

+#define APICDB1_LD_MAX                         (APICDB1_LD_CREATE + 36)

+

+/* for PD */

+#define APICDB1_PD_GETHD_INFO                  0

+#define APICDB1_PD_GETEXPANDER_INFO            (APICDB1_PD_GETHD_INFO + 1)

+#define APICDB1_PD_GETPM_INFO                  (APICDB1_PD_GETHD_INFO + 2)

+#define APICDB1_PD_GETSETTING                  (APICDB1_PD_GETHD_INFO + 3)

+#define APICDB1_PD_SETSETTING                  (APICDB1_PD_GETHD_INFO + 4)

+#define APICDB1_PD_BSL_DUMP                    (APICDB1_PD_GETHD_INFO + 5)

+#define APICDB1_PD_RESERVED1				   (APICDB1_PD_GETHD_INFO + 6)	// not used

+#define APICDB1_PD_RESERVED2				   (APICDB1_PD_GETHD_INFO + 7)	// not used

+#define APICDB1_PD_GETSTATUS                   (APICDB1_PD_GETHD_INFO + 8)

+#define APICDB1_PD_GETHD_INFO_EXT              (APICDB1_PD_GETHD_INFO + 9)	// APICDB1_PD_GETHD_INFO extension

+#define APICDB1_PD_MAX                         (APICDB1_PD_GETHD_INFO + 10)

+

+/* Sub command for APICDB1_PD_SETSETTING */

+#define APICDB4_PD_SET_WRITE_CACHE_OFF         0

+#define APICDB4_PD_SET_WRITE_CACHE_ON          1

+#define APICDB4_PD_SET_SMART_OFF               2

+#define APICDB4_PD_SET_SMART_ON                3

+#define APICDB4_PD_SMART_RETURN_STATUS         4

+#define APICDB4_PD_SET_SPEED_3G				   5

+#define APICDB4_PD_SET_SPEED_1_5G			   6

+

+/* for Block */

+#define APICDB1_BLOCK_GETINFO                  0

+#define APICDB1_BLOCK_HD_BLOCKIDS              (APICDB1_BLOCK_GETINFO + 1)

+#define APICDB1_BLOCK_MAX                      (APICDB1_BLOCK_GETINFO + 2)

+

+/* for event */

+#define APICDB1_EVENT_GETEVENT                 0

+#define APICDB1_EVENT_MAX                      (APICDB1_EVENT_GETEVENT + 1)

+

+/* for DBG */

+#define APICDB1_DBG_PDWR                       0

+#define APICDB1_DBG_MAP                        (APICDB1_DBG_PDWR + 1)

+#define APICDB1_DBG_LDWR					   (APICDB1_DBG_PDWR + 2)

+#define APICDB1_DBG_ADD_RCT_ENTRY              (APICDB1_DBG_PDWR + 3)

+#define APICDB1_DBG_REMOVE_RCT_ENTRY           (APICDB1_DBG_PDWR + 4)

+#define APICDB1_DBG_REMOVE_ALL_RCT             (APICDB1_DBG_PDWR + 5)

+#define APICDB1_DBG_MAX                        (APICDB1_DBG_PDWR + 6)

+

+/* for FLASH */

+#define APICDB1_FLASH_BIN                      0

+

+#if defined(SUPPORT_CSMI)

+/* for SDI(HP CSMI) */

+#   define APICDB0_CSMI_CORE                      0xF7

+#   define APICDB0_CSMI_RAID                      0xF8

+#   define APICDB1_CSMI_GETINFO                   0

+#   define APICDB1_CSMI_HD_BLOCKIDS               (APICDB1_BLOCK_GETINFO + 1)

+#   define APICDB1_CSMI_MAX                       (APICDB1_BLOCK_GETINFO + 2)

+

+#   define CSMI_DRIVER_NAME                       "mv64xx"

+#   define CSMI_DRIVER_DESC                       "64xx:SAS Controller"

+#endif

+

+/* for passthru commands

+	Cdb[0]: APICDB0_PASS_THRU_CMD_SCSI or APICDB0_PASS_THRU_CMD_ATA

+	Cdb[1]: APICDB1 (Data flow)

+	Cdb[2]: TargetID MSB

+	Cdb[3]: TargetID LSB

+	Cdb[4]-Cdb[15]: SCSI/ATA command is embedded here

+		SCSI command: SCSI command Cdb bytes is in the same order as the spec

+		ATA Command:

+			Features = pReq->Cdb[0];

+			Sector_Count = pReq->Cdb[1];

+			LBA_Low = pReq->Cdb[2];

+			LBA_Mid = pReq->Cdb[3];

+			LBA_High = pReq->Cdb[4];

+			Device = pReq->Cdb[5];

+			Command = pReq->Cdb[6];

+

+			if necessary:

+			Feature_Exp = pReq->Cdb[7];

+			Sector_Count_Exp = pReq->Cdb[8];

+			LBA_Low_Exp = pReq->Cdb[9];

+			LBA_Mid_Exp = pReq->Cdb[10];

+			LBA_High_Exp = pReq->Cdb[11];

+*/

+#define APICDB0_PASS_THRU_CMD_SCSI			      0xFA

+#define APICDB0_PASS_THRU_CMD_ATA				  0xFB

+

+#define APICDB1_SCSI_NON_DATA					  0x00

+#define APICDB1_SCSI_PIO_IN						  0x01 // goes with Read Long

+#define APICDB1_SCSI_PIO_OUT					  0x02 // goes with Write Long

+

+#define APICDB1_ATA_NON_DATA					  0x00

+#define APICDB1_ATA_PIO_IN						  0x01

+#define APICDB1_ATA_PIO_OUT						  0x02

+

+#ifdef _OS_LINUX

+#ifdef NEW_IO_CONTORL_PATH  

+		#define API_IOCTL_DEFAULT_FUN				0x1981

+#else

+		#define API_IOCTL_DEFAULT_FUN				0x00

+#endif

+#define	API_IOCTL_GET_VIRTURL_ID				(API_IOCTL_DEFAULT_FUN + 1)

+#define	API_IOCTL_GET_HBA_COUNT				(API_IOCTL_DEFAULT_FUN + 2)

+#define	API_IOCTL_LOOKUP_DEV					(API_IOCTL_DEFAULT_FUN + 3)

+#define API_IOCTL_CHECK_VIRT_DEV                        (API_IOCTL_DEFAULT_FUN + 4)

+#define API_IOCTL_MAX                       				(API_IOCTL_DEFAULT_FUN + 5)

+#endif

+

+

+#endif /*  __MV_COM_API_H__ */

+

diff --git a/drivers/scsi/thor/include/icommon/com_event_struct.h b/drivers/scsi/thor/include/icommon/com_event_struct.h
new file mode 100755
index 0000000..92d8988
--- /dev/null
+++ b/drivers/scsi/thor/include/icommon/com_event_struct.h
@@ -0,0 +1,40 @@
+#ifndef COM_EVENT_DRIVER_H

+#define COM_EVENT_DRIVER_H

+

+#include "com_define.h"

+

+#define MAX_EVENTS                      20

+#define MAX_EVENT_PARAMS                4

+#define MAX_EVENTS_RETURNED             6

+

+#ifndef _OS_BIOS

+#pragma pack(8)	

+#endif /*  _OS_BIOS */

+

+typedef struct _DriverEvent

+{

+	MV_U32  TimeStamp;

+	MV_U32  SequenceNo; /* (contiguous in a single adapter) */

+	MV_U32  EventID;    /* 1st 16 bits - Event class */

+                            /* last 16 bits - Event code of this particular

+			       Event class */

+	MV_U8   Severity;

+	MV_U8   AdapterID;

+	MV_U16  DeviceID;   /* Device ID relate to the event 

+			       class (HD ID, LD ID etc) */

+	MV_U32  Params[MAX_EVENT_PARAMS]; /* Additional information if 

+					     ABSOLUTELY necessary. */

+} DriverEvent, * PDriverEvent;

+

+typedef struct _EventRequest

+{

+	MV_U8        Count; /* [OUT] # of actual events returned */

+	MV_U8        Reserved[3];

+	DriverEvent  Events[MAX_EVENTS_RETURNED]; 

+} EventRequest, * PEventRequest;

+

+#ifndef _OS_BIOS

+#pragma pack()

+#endif /*  _OS_BIOS */

+

+#endif /*  COM_EVENT_DRIVER_H */

diff --git a/drivers/scsi/thor/include/icommon/com_flash.h b/drivers/scsi/thor/include/icommon/com_flash.h
new file mode 100755
index 0000000..de00d19
--- /dev/null
+++ b/drivers/scsi/thor/include/icommon/com_flash.h
@@ -0,0 +1,26 @@
+#ifndef __MV_COM_FLASH_H__

+#define __MV_COM_FLASH_H__

+

+#include "com_define.h"

+

+#define DRIVER_LENGTH                      1024*16

+

+#ifndef _OS_BIOS

+#pragma pack(8)

+#endif /* _OS_BIOS */

+

+typedef struct _Flash_DriverData

+{

+	MV_U16            Size;

+	MV_U8             PageNumber;

+	MV_BOOLEAN        isLastPage;

+	MV_U16            Reserved[2];

+	MV_U8             Data[DRIVER_LENGTH];

+}

+Flash_DriveData, *PFlash_DriveData;

+

+#ifndef _OS_BIOS

+#pragma pack()

+#endif /* _OS_BIOS */

+

+#endif /* __MV_COM_FLASH_H__ */

diff --git a/drivers/scsi/thor/include/icommon/com_ioctl.h b/drivers/scsi/thor/include/icommon/com_ioctl.h
new file mode 100755
index 0000000..4a3735b
--- /dev/null
+++ b/drivers/scsi/thor/include/icommon/com_ioctl.h
@@ -0,0 +1,59 @@
+#ifndef __MV_COM_IOCTL_H__

+#define __MV_COM_IOCTL_H__

+

+#if defined (_OS_WINDOWS)

+#include <ntddscsi.h>

+#elif defined(_OS_LINUX)

+

+#endif /* _OS_WINDOWS */

+

+/* private IOCTL commands */

+#define MV_IOCTL_CHECK_DRIVER                                \

+	    CTL_CODE(FILE_DEVICE_CONTROLLER,                 \

+                     0x900, METHOD_BUFFERED,                 \

+                     FILE_READ_ACCESS | FILE_WRITE_ACCESS)	

+

+/*

+ * MV_IOCTL_LEAVING_S0 is a notification when the system is going 

+ * to leaving S0. This gives the driver a chance to do some house

+ * keeping work before system really going to sleep.

+ *

+ * The MV_IOCTL_LEAVING_S0 will be translated to APICDB0_ADAPTER/

+ * APICDB1_ADAPTER_POWER_STATE_CHANGE and passed down along the

+ * module stack. A module shall handle this request if necessary.

+ *

+ * Upon this request, usually the Cache module shall flush all

+ * cached data. And the RAID module shall auto-pause all background

+ * activities.

+ */

+#define MV_IOCTL_LEAVING_S0                                \

+	    CTL_CODE(FILE_DEVICE_CONTROLLER,                 \

+                     0x901, METHOD_BUFFERED,                 \

+                     FILE_READ_ACCESS | FILE_WRITE_ACCESS)	

+

+/* IOCTL signature */

+#define MV_IOCTL_DRIVER_SIGNATURE                "mv61xxsg"

+#define MV_IOCTL_DRIVER_SIGNATURE_LENGTH         8

+

+/* IOCTL command status */

+#define IOCTL_STATUS_SUCCESS                     0

+#define IOCTL_STATUS_INVALID_REQUEST             1

+#define IOCTL_STATUS_ERROR                       2

+

+#ifndef _OS_BIOS

+#pragma pack(8)

+#endif  /* _OS_BIOS */

+

+typedef struct _MV_IOCTL_BUFFER

+{

+#ifdef _OS_WINDOWS

+	SRB_IO_CONTROL Srb_Ctrl;

+#endif /* _OS_WINDOWS */

+	MV_U8          Data_Buffer[32];

+} MV_IOCTL_BUFFER, *PMV_IOCTL_BUFFER;

+

+#ifndef _OS_BIOS

+#pragma pack()

+#endif /* _OS_BIOS */

+

+#endif /* __MV_COM_IOCTL_H__ */

diff --git a/drivers/scsi/thor/lib/common/com_dbg.c b/drivers/scsi/thor/lib/common/com_dbg.c
new file mode 100755
index 0000000..9c2f622
--- /dev/null
+++ b/drivers/scsi/thor/lib/common/com_dbg.c
@@ -0,0 +1,33 @@
+#include "com_define.h"

+#include "com_type.h"

+#include "com_dbg.h"

+

+MV_BOOLEAN mvLogRegisterModule(MV_U8 moduleId, MV_U32 filterMask, char* name)

+{

+	return MV_TRUE;

+}

+

+void mvLogMsg(MV_U8 moduleId, MV_U32 type, char* format, ...)

+{

+	va_list args;

+	static char szMessageBuffer[1024];

+

+	va_start(args, format);

+	vsprintf(szMessageBuffer, format, args);

+	va_end(args);

+	MV_DPRINT((szMessageBuffer));

+}

+#if (defined(_OS_WINDOWS) && (_WIN32_WINNT >= 0x0600) && defined(MV_DEBUG) )

+ULONG _cdecl MV_PRINT(char* format, ...)

+{

+	va_list args;

+	static char szMessageBuffer[1024];

+	ULONG result;

+

+	va_start(args, format);

+	vsprintf(szMessageBuffer, format, args);

+	result = DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, szMessageBuffer);

+	va_end(args);

+	return result;

+}

+#endif

diff --git a/drivers/scsi/thor/lib/common/com_nvram.c b/drivers/scsi/thor/lib/common/com_nvram.c
new file mode 100755
index 0000000..c196c8c
--- /dev/null
+++ b/drivers/scsi/thor/lib/common/com_nvram.c
@@ -0,0 +1,164 @@
+/* ;This file is discarded after POST. */

+/*******************************************************************************

+*

+*                   Copyright 2006,MARVELL SEMICONDUCTOR ISRAEL, LTD.

+* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.

+* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT

+* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE

+* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.

+* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED,

+* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.

+*

+* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES,

+* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL

+* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.

+* (MJKK), MARVELL SEMICONDUCTOR ISRAEL. (MSIL),  MARVELL TAIWAN, LTD. AND

+* SYSKONNECT GMBH.

+*

+********************************************************************************

+* com_nvram.c - File for implementation of the Driver Intermediate Application Layer

+*

+* DESCRIPTION:

+*       None.

+*

+* DEPENDENCIES:

+*   mv_include.h

+*

+* FILE REVISION NUMBER:

+*       $Revision: 1.1.1.1 $

+*******************************************************************************/

+#ifdef ODIN_DRIVER

+#include "mv_include.h"

+#include "core_header.h"

+#include "core_helper.h"

+#include "core_spi.h"

+#include "com_nvram.h"

+

+MV_BOOLEAN mvui_init_param( MV_PVOID This, pHBA_Info_Page pHBA_Info_Param)

+{

+//	MV_U32 					nsize = FLASH_PARAM_SIZE;

+	MV_U32 					param_flash_addr=PARAM_OFFSET,i = 0;

+//	MV_U16 					my_ds=0;

+	PCore_Driver_Extension	pCore;

+	AdapterInfo				AI;

+

+	if (!This)

+		return MV_FALSE;

+

+	pCore = (PCore_Driver_Extension)This;

+	AI.bar[2] = pCore->Base_Address[2];

+

+	if (-1 == OdinSPI_Init(&AI))

+		return MV_FALSE;

+

+	/* step 1 read param from flash offset = 0x3FFF00 */

+	OdinSPI_ReadBuf( &AI, param_flash_addr, (MV_PU8)pHBA_Info_Param, FLASH_PARAM_SIZE);

+

+	/* step 2 check the signature first */

+	if(pHBA_Info_Param->Signature[0] == 'M'&& \

+	    pHBA_Info_Param->Signature[1] == 'R'&& \

+	    pHBA_Info_Param->Signature[2] == 'V'&& \

+	    pHBA_Info_Param->Signature[3] == 'L' && \

+	    (!mvVerifyChecksum((MV_PU8)pHBA_Info_Param,FLASH_PARAM_SIZE)))

+	{

+		if(pHBA_Info_Param->HBA_Flag == 0xFFFFFFFFL)

+		{

+			pHBA_Info_Param->HBA_Flag = 0;

+			pHBA_Info_Param->HBA_Flag |= HBA_FLAG_INT13_ENABLE;

+			pHBA_Info_Param->HBA_Flag &= ~HBA_FLAG_SILENT_MODE_ENABLE;

+		}

+

+		for(i=0;i<8;i++)

+		{

+			if(pHBA_Info_Param->PHY_Rate[i]>0x1)

+				/* phy host link rate */

+				pHBA_Info_Param->PHY_Rate[i] = 0x1;

+

+			// validate phy tuning

+			//pHBA_Info_Param->PHY_Tuning[i].Reserved[0] = 0;

+			//pHBA_Info_Param->PHY_Tuning[i].Reserved[1] = 0;

+		}

+	}

+	else

+	{

+		MV_FillMemory((MV_PVOID)pHBA_Info_Param, FLASH_PARAM_SIZE, 0xFF);

+		pHBA_Info_Param->Signature[0] = 'M';	

+		pHBA_Info_Param->Signature[1] = 'R';

+	   	pHBA_Info_Param->Signature[2] = 'V';

+	    pHBA_Info_Param->Signature[3] = 'L';

+

+		// Set BIOS Version

+		pHBA_Info_Param->Minor = NVRAM_DATA_MAJOR_VERSION;

+		pHBA_Info_Param->Major = NVRAM_DATA_MINOR_VERSION;

+		

+		// Set SAS address

+		for(i=0;i<MAX_PHYSICAL_PORT_NUMBER;i++)

+		{

+			pHBA_Info_Param->SAS_Address[i].b[0]=  0x50;

+			pHBA_Info_Param->SAS_Address[i].b[1]=  0x05;

+			pHBA_Info_Param->SAS_Address[i].b[2]=  0x04;

+			pHBA_Info_Param->SAS_Address[i].b[3]=  0x30;

+			pHBA_Info_Param->SAS_Address[i].b[4]=  0x11;

+			pHBA_Info_Param->SAS_Address[i].b[5]=  0xab;

+			pHBA_Info_Param->SAS_Address[i].b[6]=  0x00;

+			pHBA_Info_Param->SAS_Address[i].b[7]=  0x00; 

+			/*+(MV_U8)i; - All ports' WWN has to be same */

+		}

+		

+		/* init phy link rate */

+		for(i=0;i<8;i++)

+		{

+			/* phy host link rate */

+			pHBA_Info_Param->PHY_Rate[i] = 0x1;//Default is 3.0G;

+		}

+

+		MV_PRINT("pHBA_Info_Param->HBA_Flag = 0x%x \n",pHBA_Info_Param->HBA_Flag);

+

+		/* init setting flags */

+		pHBA_Info_Param->HBA_Flag = 0;

+		pHBA_Info_Param->HBA_Flag |= HBA_FLAG_INT13_ENABLE;

+		pHBA_Info_Param->HBA_Flag &= ~HBA_FLAG_SILENT_MODE_ENABLE;

+		/* write to flash and save it now */

+		if(OdinSPI_SectErase( &AI, param_flash_addr) != -1)

+			MV_PRINT("FLASH ERASE SUCCESS\n");

+		else

+			MV_PRINT("FLASH ERASE FAILED\n");

+

+		pHBA_Info_Param->Check_Sum = 0;

+		pHBA_Info_Param->Check_Sum=mvCaculateChecksum((MV_PU8)pHBA_Info_Param,sizeof(HBA_Info_Page));

+		/* init the parameter in ram */

+		OdinSPI_WriteBuf( &AI, param_flash_addr, (MV_PU8)pHBA_Info_Param, FLASH_PARAM_SIZE);

+	}

+	return MV_TRUE;

+}

+

+MV_U8	mvCaculateChecksum(MV_PU8	Address, MV_U32 Size)

+{

+		MV_U8 checkSum;

+		MV_U32 temp=0;

+        checkSum = 0;

+        for (temp = 0 ; temp < Size ; temp ++)

+        {

+                checkSum += Address[temp];

+        }

+        

+        checkSum = (~checkSum) + 1;

+

+

+

+		return	checkSum;

+}

+

+MV_U8	mvVerifyChecksum(MV_PU8	Address, MV_U32 Size)

+{

+		MV_U8	checkSum=0;

+		MV_U32 	temp=0;

+        for (temp = 0 ; temp < Size ; temp ++)

+        {

+            checkSum += Address[temp];

+        }

+        

+		return	checkSum;

+}

+

+#endif

diff --git a/drivers/scsi/thor/lib/common/com_scsi.c b/drivers/scsi/thor/lib/common/com_scsi.c
new file mode 100755
index 0000000..6296bb0
--- /dev/null
+++ b/drivers/scsi/thor/lib/common/com_scsi.c
@@ -0,0 +1,84 @@
+#include "com_type.h"
+#include "com_define.h"
+#include "com_dbg.h"
+#include "com_scsi.h"
+#include "com_util.h"
+
+/* NODRV device is used to send controller commands. 
+ * Now we are using "Storage array controller device" as Microsoft recommended.
+ * Peripheral Device Type: 03h Processor ( can be 3h or 0ch )
+ * Peripheral Qualifier: 0h
+ * Response Data Format: 2h ( must be 2 )
+ * Version: 4h ( must be 4, 5 or 6 ) 
+ * Only need support minimum 36 bytes inquiry data. 
+ * Must return EVPD 0x0, 0x83, 0x80 */
+#ifndef SUPPORT_VIRTUAL_DEVICE
+	/* Standard Inquiry Data for Virtual Device */
+	MV_U8 BASEATTR MV_INQUIRY_VIRTUALD_DATA[] = {
+				0x03,0x00,0x03,0x03,0xFA,0x00,0x00,0x30,
+				'M', 'a', 'r', 'v', 'e', 'l', 'l', ' ',
+				0x52,0x41,0x49,0x44,0x20,0x43,0x6F,0x6E,  /* "Raid Con" */
+				0x73,0x6F,0x6C,0x65,0x20,0x20,0x20,0x20,  /* "sole    " */
+				0x31,0x2E,0x30,0x30,0x20,0x20,0x20,0x20,  /* "1.00    " */
+				0x53,0x58,0x2F,0x52,0x53,0x41,0x46,0x2D,  /* "SX/RSAF-" */
+				0x54,0x45,0x31,0x2E,0x30,0x30,0x20,0x20,  /* "TE1.00  " */
+				0x0C,0x20,0x20,0x20,0x20,0x20,0x20,0x20
+			};
+
+	/* EVPD Inquiry Page for Virtual Device */
+	//#define MV_INQUIRY_VPD_PAGE0_VIRTUALD_DATA	MV_INQUIRY_VPD_PAGE0_DEVICE_DATA
+	MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE80_VIRTUALD_DATA[] = {
+		0x03, 0x80, 0x00, 0x08, 'C', 'o', 'n', 's', 'o', 'l', 'e', ' '};
+	//#define MV_INQUIRY_VPD_PAGE83_VIRTUALD_DATA	MV_INQUIRY_VPD_PAGE83_DEVICE_DATA
+#else
+	/* If VIRTUAL_DEVICE_TYPE==0x10, Device ID is SCSI\BridgeMARVELL_Virtual_Device__
+	 * If VIRTUAL_DEVICE_TYPE==0x0C, Device ID is SCSI\ArrayMARVELL_Virtual_Device__
+	 * If VIRTUAL_DEVICE_TYPE==0x03, Device ID is SCSI\ProcessorMARVELL_Virtual_Device__ */
+	#define VIRTUAL_DEVICE_TYPE	0x0C
+	/* Standard Inquiry Data for Virtual Device */
+	MV_U8 BASEATTR MV_INQUIRY_VIRTUALD_DATA[] = {
+					VIRTUAL_DEVICE_TYPE,0x00,0x02,0x02,0x20,0x00,0x00,0x00,//?Version should be 0x4 instead of 0x2.
+					'M', 'A', 'R', 'V', 'E', 'L', 'L', ' ',
+					'V', 'i', 'r', 't', 'u', 'a', 'l', ' ',
+					'D', 'e', 'v', 'i', 'c', 'e', ' ', ' ',
+					0x31,0x2E,0x30,0x30
+					};
+
+	/* EVPD Inquiry Page for Virtual Device */
+	MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE0_VIRTUALD_DATA[] = {
+		VIRTUAL_DEVICE_TYPE, 0x00, 0x00, 0x03, 0x00, 0x80, 0x83};
+
+	MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE80_VIRTUALD_DATA[] = {
+		VIRTUAL_DEVICE_TYPE, 0x80, 0x00, 0x08, 'V', ' ', 'D', 'e', 'v', 'i', 'c', 'e'};
+
+	//MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE83_VIRTUALD_DATA[] = {
+	//	VIRTUAL_DEVICE_TYPE, 0x83, 0x00, 0x0C, 0x01, 0x02, 0x00, 0x08,
+	//	0x00, 0x50, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00};
+	MV_U8 BASEATTR MV_INQUIRY_VPD_PAGE83_VIRTUALD_DATA[] = {
+		VIRTUAL_DEVICE_TYPE, 0x83, 0x00, 0x14, 0x02, 0x01, 0x00, 0x10,
+		'M',  'A',  'R',  'V',  'E',  'L',  'L',  ' ',	/* T10 Vendor Identification */
+		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01	/* Vendor Specific Identifier */
+	};
+#endif	/* SUPPORT_VIRTUAL_DEVICE */
+
+MV_VOID MV_SetSenseData(
+	IN PMV_Sense_Data pSense,
+	IN MV_U8 SenseKey,
+	IN MV_U8 AdditionalSenseCode,
+	IN MV_U8 ASCQ
+	)
+{
+	/* The caller should make sure it's a valid sense buffer. */
+	MV_DASSERT( pSense!=NULL );
+
+	if ( pSense!=NULL ) {
+		MV_ZeroMemory(pSense, sizeof(MV_Sense_Data));
+
+		pSense->Valid = 0;	
+		pSense->ErrorCode = MV_SCSI_RESPONSE_CODE;
+		pSense->SenseKey = SenseKey;
+		pSense->AdditionalSenseCode = AdditionalSenseCode;
+		pSense->AdditionalSenseCodeQualifier = ASCQ;
+		pSense->AdditionalSenseLength = sizeof(MV_Sense_Data) - 8;
+	}
+}
diff --git a/drivers/scsi/thor/lib/common/com_sgd.c b/drivers/scsi/thor/lib/common/com_sgd.c
new file mode 100755
index 0000000..e61a6a6
--- /dev/null
+++ b/drivers/scsi/thor/lib/common/com_sgd.c
@@ -0,0 +1,935 @@
+#include "com_type.h"
+#include "com_define.h"
+#ifdef USE_NEW_SGTABLE
+#include "com_sgd.h"
+#include "com_u64.h"
+#include "com_dbg.h"
+#include "com_util.h"
+#include "hba_exp.h"
+
+#if defined(_64BPLATFORM) || defined(_64_SYS_)
+#define USES_64B_POINTER
+#endif
+
+int sg_iter_walk( 
+	IN sgd_t* sgd, 
+	IN MV_U32 offset, 
+	IN MV_U32 count, 
+	IN sgd_visitor_t visitor, 
+	IN MV_PVOID context 
+	)
+{
+	sgd_t	sg[2];
+	int		sg_cnt = 0;
+	MV_U32	sz;
+
+	sgd_getsz(sgd,sz);
+	while( sz <= offset )
+	{
+		offset -= sz;
+		MV_ASSERT( !sgd_eot(sgd) );
+
+		sg_cnt++;
+		sgd_inc(sgd);
+		sgd_getsz(sgd,sz);
+	}
+
+	while(1)
+	{
+		if( sgd->flags & (SGD_REFTBL|SGD_REFSGD) )
+		{
+			MV_U32 copy_count = sz - offset;
+			MV_U32 offRef;
+			sgd_tbl_t* refSgdt;
+			sgd_t* refSgd;
+
+			sgd_get_reftbl(sgd,refSgdt);
+			if( sgd->flags & SGD_REFTBL )
+				refSgd = refSgdt->Entry_Ptr;
+			else
+				refSgd = (sgd_t*) refSgdt;
+
+			sgd_get_refoff(sgd,offRef);
+
+			if( copy_count > count )
+				copy_count = count;
+
+			if( !sg_iter_walk(
+				refSgd,
+				offRef + offset,
+				copy_count,
+				visitor,
+				context ) )
+				return 0;
+			count -= copy_count;
+		}
+		else if( sgd->flags & SGD_NEXT_TBL )
+		{
+			MV_ASSERT( MV_FALSE );	// TODO
+		}
+		else
+		{
+			sgd_copy( sg, sgd );
+
+			if( offset )
+			{
+				sg[0].baseAddr = U64_ADD_U32(sg[0].baseAddr,offset);
+
+				if( sgd->flags & SGD_VP )
+				{
+					((sgd_vp_t*)sg)->u.vaddr = ((MV_U8*) ((sgd_vp_t*)sg)->u.vaddr) + 
+						offset;
+				}
+
+				if (sgd->flags & SGD_PCTX) {
+					((sgd_pctx_t *)sg)->rsvd += offset;
+				}
+
+				sg[0].size -= offset;
+			}
+
+			if( sg[0].size > count )
+				sg[0].size = count;
+
+			if( !visitor( sg, context ) )
+				return 0;
+
+			count -= sg[0].size;
+		}
+
+		sg_cnt++;
+
+		if( sgd_eot(sgd) 
+			|| count==0 )
+		{
+			MV_ASSERT( count == 0 );
+			break;
+		}
+		offset = 0;
+		sgd_inc(sgd);
+		sgd_getsz(sgd,sz);
+	}
+
+	return sg_cnt;
+}
+
+int sgd_table_walk(
+	sgd_tbl_t*		sgdt,
+	sgd_visitor_t	visitor,
+	MV_PVOID		ctx 
+	)
+{
+	return sg_iter_walk( 
+		sgdt->Entry_Ptr,
+		0,
+		sgdt->Byte_Count,
+		visitor,
+		ctx );
+}
+
+void  sgd_iter_init(
+	sgd_iter_t*	iter,
+	sgd_t*		sgd,
+	MV_U32		offset,
+	MV_U32		count 
+	)
+{
+	MV_U32	sz;
+
+	sgd_getsz(sgd,sz);
+	while( sz <= offset )
+	{
+		offset -= sz;
+		MV_ASSERT( !sgd_eot(sgd) );
+		sgd_inc(sgd);
+		sgd_getsz(sgd,sz);
+	}
+
+	iter->sgd = sgd;
+	iter->offset = offset;
+	iter->remainCnt = count;
+}
+
+int sgd_iter_get_next(
+	sgd_iter_t*	iter,
+	sgd_t*		sgd
+	)
+{
+	MV_U32	sz;
+
+	if( iter->remainCnt == 0 )
+		return 0;
+
+	sgd_getsz(iter->sgd,sz);
+	while( iter->offset >= sz )
+	{
+		if( sgd_eot(iter->sgd) )
+		{
+			iter->remainCnt = 0;
+			return 0;
+		}
+
+		iter->offset -= sz;
+		sgd_inc(iter->sgd);
+		sgd_getsz(iter->sgd,sz);
+	}
+again:
+	if( iter->sgd->flags & (SGD_REFTBL|SGD_REFSGD) )
+	{
+		sgd_iter_t	sub_iter;
+		sgd_t*		refSgd;
+		sgd_tbl_t*	refSgdt;
+		MV_U32		sub_cnt = sz - iter->offset;
+		MV_U32		offRef;
+
+		if( sub_cnt > iter->remainCnt )
+			sub_cnt = iter->remainCnt;
+
+		sgd_get_reftbl(iter->sgd,refSgdt);
+
+		if( iter->sgd->flags & SGD_REFTBL )
+			refSgd = refSgdt->Entry_Ptr;
+		else
+			refSgd = (sgd_t*) refSgdt;
+
+		sgd_get_refoff(iter->sgd,offRef);
+
+		sgd_iter_init( 
+			&sub_iter, 
+			refSgd,
+			offRef + iter->offset,
+			sub_cnt );
+
+		if( !sgd_iter_get_next( &sub_iter, sgd ) )
+		{
+			if( sgd_eot(iter->sgd) )
+			{
+				iter->remainCnt = 0;
+				return 0;
+			}
+			sgd_inc(iter->sgd);
+			iter->offset = 0;
+			goto again;
+		}
+		else if( sgd->flags & SGD_NEXT_TBL )
+		{
+			MV_ASSERT( MV_FALSE );	// TODO
+		}
+		else
+		{
+			sgd_getsz(sgd,sz);
+			if( sz > iter->remainCnt )
+				sgd_setsz(sgd,iter->remainCnt);
+
+			iter->offset += sz;
+			iter->remainCnt -= sz;
+		}
+
+		return 1;
+	}
+	else
+	{
+		sgd_copy( sgd, iter->sgd );
+
+		sgd->baseAddr = U64_ADD_U32(sgd->baseAddr,iter->offset);
+
+		if( sgd->flags & SGD_VP )
+		{
+			((sgd_vp_t*)sgd)->u.vaddr = ((MV_U8*) ((sgd_vp_t*)sgd)->u.vaddr) + 
+				iter->offset;
+		}
+
+		if (sgd->flags & SGD_PCTX) {
+			((sgd_pctx_t *)sgd)->rsvd += iter->offset;
+		}
+
+		sz -= iter->offset;
+		sgd_setsz( sgd, sz );
+	}
+
+	if( sz > iter->remainCnt )
+	{
+		sgd_setsz( sgd, iter->remainCnt );
+		sz = iter->remainCnt;
+	}
+
+	iter->remainCnt -= sz;
+
+	if( sgd_eot(iter->sgd) 
+		|| iter->remainCnt == 0 )
+	{
+		iter->remainCnt = 0;
+		return 1;
+	}
+
+	iter->offset = 0;
+	sgd_inc(iter->sgd);
+
+	return 1;
+}
+
+void sgd_dump(sgd_t* sg, char* prefix)
+{
+	MV_U32	sz;
+
+	sgd_getsz(sg,sz);
+
+	if( prefix )
+	{
+#ifndef _OS_LINUX
+		MV_PRINT(prefix);
+#endif
+	}
+
+	if( sg->flags & SGD_VIRTUAL )
+	{
+		MV_PVOID vaddr, xctx;
+
+		sgd_get_vaddr(sg,vaddr);
+		sgd_get_xctx(sg,xctx);
+
+		MV_PRINT( "\tV %p T %p %08x F %08x\n"
+			, vaddr
+			, xctx
+			, sz
+			, sg->flags );
+	}
+	else if( sg->flags & (SGD_REFTBL|SGD_REFSGD) )
+	{
+		MV_PVOID ref;
+		MV_U32	refOff;
+
+		sgd_get_ref(sg,ref);
+		sgd_get_refoff(sg,refOff);
+
+		MV_PRINT( "\tR %p O %08x %08x F %08x\n"
+			, ref
+			, refOff
+			, sz
+			, sg->flags );
+	}
+	else if( sg->flags & SGD_NEXT_TBL )
+	{
+		MV_PVOID nexttbl;
+		
+		sgd_get_nexttbl(sg, nexttbl);
+
+		MV_PRINT( "\tN %p F %08x\n"
+			, nexttbl, sg->flags );
+
+	}
+	else if( sg->flags & SGD_VP )
+	{
+		sgd_vp_t* vp = (sgd_vp_t*) sg;
+		MV_PRINT( "\tX %08x_%08x %p F %08x\n"
+			, vp->baseAddr.parts.high
+			, vp->baseAddr.parts.low
+			, vp->u.vaddr
+			, sg->flags );
+	}
+	else if( sg->flags & SGD_VWOXCTX )
+	{
+		sgd_v_t* vp = (sgd_v_t*) sg;
+
+		MV_PRINT( "\tV %p T %p %08x F %08x\n"
+			, vp->u.vaddr
+			, (MV_PVOID)0
+			, sz
+			, sg->flags );
+	}
+	else if( sg->flags & SGD_PCTX )
+	{
+		sgd_pctx_t* p = (sgd_pctx_t*) sg;
+		MV_PRINT( "\tP %08x_%08x %08x F %08x X %p\n"
+			, p->baseAddr.parts.high, p->baseAddr.parts.low, p->size, p->flags
+			, p->u.xctx );
+	}
+	else
+	{
+		MV_PRINT( "\tP %08x_%08x %08x F %08x\n"
+		, sg->baseAddr.parts.high, sg->baseAddr.parts.low, sz, sg->flags );
+	}
+}
+
+void sgdl_dump(sgd_t* sg, char* prefix )
+{
+	while(1)
+	{
+		sgd_dump(sg,prefix);
+
+		if( sg->flags & SGD_REFTBL )
+		{
+			sgd_tbl_t* tbl;
+			sgd_get_reftbl(sg,tbl);
+			sgdl_dump( tbl->Entry_Ptr, "R " );
+		}
+		else if( sg->flags & SGD_REFSGD )
+		{
+			sgd_t* refsgd;
+			sgd_get_refsgd(sg,refsgd);
+			sgdl_dump( refsgd, "R " );
+		}
+
+		if( sgd_eot(sg) )
+			break;
+		sgd_inc(sg);
+	}
+}
+
+
+void sgdt_dump(sgd_tbl_t *SgTbl, char* prefix)
+{
+	sgd_t* sg = SgTbl->Entry_Ptr;
+
+	MV_PRINT( "%s %p %u of %u 0x%x bytes\n"
+		, prefix ? prefix : " "
+		, SgTbl
+		, SgTbl->Valid_Entry_Count
+		, SgTbl->Max_Entry_Count
+		, SgTbl->Byte_Count
+		);
+
+	if( !SgTbl->Valid_Entry_Count )
+		return;
+
+#if 0
+	sgdl_dump(sg, NULL);
+#else
+	while(1)
+	{
+
+		sgd_dump(sg,NULL);
+		if( sgd_eot(sg) )
+			break;
+		sgd_inc(sg);
+	}
+#endif
+}
+
+void sgdt_clear_eot(
+	sgd_tbl_t*	sgdt 
+	)
+{
+	if( sgdt->Valid_Entry_Count )
+	{
+		sgd_t* sgd;
+		sgdt_get_lastsgd(sgdt,sgd);
+
+		sgd_clear_eot(sgd);
+	}
+}
+
+void sgdt_append(
+	sgd_tbl_t*	sgdt,
+	MV_U32		address,
+	MV_U32		addressHigh,
+	MV_U32		size
+	)
+{
+	sgd_t* pSGEntry = &sgdt->Entry_Ptr[sgdt->Valid_Entry_Count];
+
+	MV_ASSERT( sgdt->Valid_Entry_Count+1<=sgdt->Max_Entry_Count );
+
+	sgdt_clear_eot(sgdt);
+
+	sgdt->Valid_Entry_Count += 1;
+	sgdt->Byte_Count += size;
+
+	pSGEntry->flags = 0;
+	pSGEntry->baseAddr.parts.low = address;
+	pSGEntry->baseAddr.parts.high = addressHigh;
+	pSGEntry->size = size;
+
+	sgd_mark_eot(pSGEntry);
+}
+
+void sgdt_append_pctx(
+	sgd_tbl_t*	sgdt,
+	MV_U32		address,
+	MV_U32		addressHigh,
+	MV_U32		size,
+	MV_PVOID	xctx
+	)
+{
+	sgd_pctx_t* pSGEntry = (sgd_pctx_t*) &sgdt->Entry_Ptr[sgdt->Valid_Entry_Count];
+
+	MV_ASSERT( sgdt->Valid_Entry_Count+2<=sgdt->Max_Entry_Count );
+
+	sgdt_clear_eot(sgdt);
+
+	sgdt->Valid_Entry_Count += 2;
+	sgdt->Byte_Count += size;
+
+	pSGEntry->flags = SGD_PCTX | SGD_WIDE | SGD_EOT;
+	pSGEntry->baseAddr.parts.low = address;
+	pSGEntry->baseAddr.parts.high = addressHigh;
+	pSGEntry->size = size;
+	pSGEntry->u.xctx = xctx;
+	pSGEntry->flagsEx = SGD_X64;
+	pSGEntry->rsvd = 0;
+}
+
+void sgdt_append_sgd(
+	sgd_tbl_t*	sgdt,
+	sgd_t*		sgd
+	)
+{
+	sgd_t*	pSGEntry = &sgdt->Entry_Ptr[sgdt->Valid_Entry_Count];
+	MV_U8	cnt = 1;
+	MV_U32	sgdsz;
+
+	sgd_getsz(sgd,sgdsz);
+
+	if( sgd->flags & SGD_WIDE )
+		cnt++;
+
+	MV_ASSERT( sgdt->Valid_Entry_Count+cnt<=sgdt->Max_Entry_Count );
+
+	sgdt_clear_eot(sgdt);
+	sgdt->Valid_Entry_Count += cnt;
+	sgdt->Byte_Count += sgdsz;
+
+	MV_CopyMemory( pSGEntry, sgd, sizeof(sgd_t) * cnt );
+
+	sgd_mark_eot(pSGEntry);
+}
+
+static int sgdt_append_virtual_wo_xctx(
+	sgd_tbl_t* sgdt,
+	MV_PVOID virtual_address,
+	MV_U32 size 
+	)
+{
+	sgd_t* sg = &sgdt->Entry_Ptr[sgdt->Valid_Entry_Count];
+	sgd_v_t* vsg = (sgd_v_t*) sg;
+
+	MV_ASSERT( sgdt->Valid_Entry_Count+1<=sgdt->Max_Entry_Count );
+
+	if( sgdt->Valid_Entry_Count + 1 > sgdt->Max_Entry_Count )
+		return -1;	// not enough space
+
+	sgdt_clear_eot(sgdt);
+
+	vsg->flags = SGD_EOT | SGD_VWOXCTX;
+	vsg->size = size;
+	vsg->u.vaddr = virtual_address;
+
+	sgdt->Valid_Entry_Count++;
+	sgdt->Byte_Count += size;
+
+	return 0;
+}
+
+int sgdt_append_virtual(
+	sgd_tbl_t* sgdt,
+	MV_PVOID virtual_address,
+	MV_PVOID translation_ctx,
+	MV_U32 size 
+	)
+{
+	sgd_t* sg;
+#ifdef USES_64B_POINTER
+	sgd_v64_t* vsg;
+#else
+	sgd_v32_t* vsg;
+#endif
+
+	if( translation_ctx == 0 )
+		return sgdt_append_virtual_wo_xctx(sgdt,virtual_address,size);
+
+	sg = &sgdt->Entry_Ptr[sgdt->Valid_Entry_Count];
+
+#ifdef USES_64B_POINTER
+	vsg = (sgd_v64_t*) sg;
+
+	MV_ASSERT( sgdt->Valid_Entry_Count+2<=sgdt->Max_Entry_Count );
+
+	if( sgdt->Valid_Entry_Count + 2 > sgdt->Max_Entry_Count )
+		return -1;	// not enough space
+
+	sgdt_clear_eot(sgdt);
+
+	vsg->u1.vaddr = virtual_address;
+	vsg->u2.xctx = translation_ctx;
+	vsg->flags = SGD_WIDE | SGD_VIRTUAL | SGD_EOT;
+	vsg->flagsEx = SGD_X64;
+	sgdt->Valid_Entry_Count++;
+#else	// USES_64B_POINTER
+	vsg = (sgd_v32_t*) sg;
+
+	MV_ASSERT( sgdt->Valid_Entry_Count+1<=sgdt->Max_Entry_Count );
+
+	if( sgdt->Valid_Entry_Count + 1 > sgdt->Max_Entry_Count )
+		return -1;	// not enough space
+
+	sgdt_clear_eot(sgdt);
+
+	vsg->vaddr = virtual_address;
+	vsg->xctx = translation_ctx;
+	vsg->flags = SGD_VIRTUAL | SGD_EOT;
+#endif	// !USES_64B_POINTER
+
+	vsg->size = size;
+
+	sgdt->Valid_Entry_Count++;
+	sgdt->Byte_Count += size;
+
+	return 0;
+}
+
+int sgdt_append_vp(
+	sgd_tbl_t*	sgdt,
+	MV_PVOID	virtual_address,
+	MV_U32		size,
+	MV_U32		address,
+	MV_U32		addressHigh
+	)
+{
+	sgd_vp_t* sg = (sgd_vp_t*) &sgdt->Entry_Ptr[sgdt->Valid_Entry_Count];
+
+	MV_ASSERT( sgdt->Valid_Entry_Count+2<=sgdt->Max_Entry_Count );
+
+	if( sgdt->Valid_Entry_Count + 2 > sgdt->Max_Entry_Count )
+		return -1;	// not enough space
+
+	sgdt_clear_eot(sgdt);
+
+	sg->baseAddr.parts.low = address;
+	sg->baseAddr.parts.high = addressHigh;
+	sg->flags = SGD_VP | SGD_WIDE | SGD_EOT;
+	sg->size = size;
+
+	sg->u.vaddr = virtual_address;
+	sg->flagsEx = SGD_X64;
+
+	sgdt->Valid_Entry_Count += 2;
+	sgdt->Byte_Count += size;
+
+	return 0;
+}
+
+int sgdt_append_ref(
+	sgd_tbl_t*	sgdt,
+	MV_PVOID	ref,
+	MV_U32		offset,
+	MV_U32		size,
+	MV_BOOLEAN	refTbl
+	)
+{
+	sgd_t* sg;
+
+	if( sgdt->Valid_Entry_Count )
+	{
+		sgdt_get_lastsgd(sgdt,sg);
+
+		if( sg->flags&(SGD_REFTBL|SGD_REFSGD) )
+		{
+			MV_PVOID lastRef;
+			MV_U32 lastOffset;
+			
+			sgd_get_ref(sg, lastRef);
+			sgd_get_refoff(sg, lastOffset);
+
+			if( lastRef == ref
+				&& lastOffset + sg->size == offset )
+			{
+				// contiguous items!
+				sg->size += size;
+				sgdt->Byte_Count += size;
+				return 0;
+			}
+		}				
+	}
+
+	sg = &sgdt->Entry_Ptr[sgdt->Valid_Entry_Count];
+
+	{
+
+#ifdef USES_64B_POINTER
+	sgd_ref64_t* rsg = (sgd_ref64_t*) sg;
+	MV_ASSERT( sgdt->Valid_Entry_Count+2<=sgdt->Max_Entry_Count );
+	if( sgdt->Valid_Entry_Count + 2 > sgdt->Max_Entry_Count )
+		return -1;	// not enough space
+	sgdt_clear_eot(sgdt);
+	rsg->u.ref = ref;
+	sgdt->Valid_Entry_Count++;
+	rsg->flags = SGD_WIDE | SGD_EOT | (refTbl ? SGD_REFTBL : SGD_REFSGD);
+	rsg->flagsEx = SGD_X64;
+#else
+
+	sgd_ref32_t* rsg = (sgd_ref32_t*) sg;
+	MV_ASSERT( sgdt->Valid_Entry_Count+1<=sgdt->Max_Entry_Count );
+	if( sgdt->Valid_Entry_Count + 1 > sgdt->Max_Entry_Count )
+		return -1;	// not enough space
+	sgdt_clear_eot(sgdt);
+	rsg->ref = ref;
+	rsg->flags = SGD_EOT | (refTbl ? SGD_REFTBL : SGD_REFSGD);
+#endif
+
+	rsg->offset = offset;
+	rsg->size = size;
+
+	sgdt->Valid_Entry_Count++;
+	sgdt->Byte_Count += size;
+
+	}
+
+	return 0;
+}
+
+
+void
+sgdt_copy_partial(
+	sgd_tbl_t* sgdt,
+	sgd_t**	ppsgd,
+	MV_PU32	poff,
+	MV_U32	size
+	)
+{
+	MV_U32	sgdsz;
+	MV_U32	tmpSize;
+	sgd_t	sgd[2];
+
+	while( size )
+	{
+		sgd_getsz( *ppsgd, sgdsz );
+		MV_ASSERT( sgdsz > *poff );
+
+		tmpSize = MV_MIN( size, sgdsz - *poff );
+
+		if( sgdt )
+		{
+			sgd_copy( sgd, *ppsgd );
+
+			sgd_setsz( sgd, tmpSize );
+
+			if( *poff )
+			{
+				if( sgd->flags & (SGD_REFTBL|SGD_REFSGD) )
+				{
+					MV_U32 refoff;
+					sgd_get_refoff( sgd, refoff );
+					sgd_set_refoff( sgd, refoff+(*poff) );
+				}
+				else
+				{
+					sgd->baseAddr = U64_ADD_U32( sgd->baseAddr, (*poff) );
+					if( sgd->flags & SGD_VP )
+					{
+						sgd_vp_t* vp = (sgd_vp_t*) sgd;
+						vp->u.vaddr = ((MV_U8*)vp->u.vaddr) + (*poff);
+					}
+
+					if (sgd->flags & SGD_PCTX) {
+						sgd_pctx_t *pctx = 
+							(sgd_pctx_t *)sgd;
+						pctx->rsvd += (*poff);
+					}
+				}
+			}
+
+			sgdt_append_sgd( sgdt, sgd );
+
+		}
+
+		if( size == sgdsz - *poff 
+			|| tmpSize == sgdsz - *poff )
+		{
+			sgd_inc( *ppsgd );
+			(*poff) = 0;
+		}
+		else
+			(*poff) += tmpSize;
+
+		size -= tmpSize;
+	}
+}
+
+#ifdef SIMULATOR
+
+int SgVisitor(sgd_t* sg, MV_PVOID ctx)
+{
+	MV_U32* p = (MV_U32*)ctx;
+
+	sgd_dump( sg, NULL );
+
+	(*p)++;
+
+	return 1;
+}
+
+void sgd_test()
+{
+	sgd_tbl_t SgTbl1 = {0,};
+	sgd_tbl_t SgTbl2 = {0,};
+	sgd_tbl_t SgTbl3 = {0,};
+	sgd_t Entries1[32];
+	sgd_t Entries2[32];
+	sgd_t Entries3[32];
+
+	SgTbl1.Max_Entry_Count = sizeof(Entries1)/sizeof(Entries1[0]);
+	SgTbl1.Entry_Ptr = Entries1;
+
+	SgTbl2.Max_Entry_Count = sizeof(Entries2)/sizeof(Entries2[0]);
+	SgTbl2.Entry_Ptr = Entries2;
+
+	SgTbl3.Max_Entry_Count = sizeof(Entries3)/sizeof(Entries3[0]);
+	SgTbl3.Entry_Ptr = Entries3;
+
+	int i;
+
+	for( i = 0; i < 32; i++ )
+	{
+		sgdt_append( &SgTbl2, 0x80000000+i*0x1000, 0x90000000, 0x1000 );
+	}
+
+	sgdt_dump( &SgTbl2, " " );
+
+	sgdt_append_reftbl( &SgTbl1, &SgTbl2, 0x3800, 0x1000*10 );
+	sgdt_append_virtual( &SgTbl1, (MV_PVOID)0x40000, (MV_PVOID)0x60000, 0x1000*10 );
+	sgdt_append_vp( &SgTbl1, (MV_PVOID)0x80000, 0x1000*10, 0x4000, 0 );
+
+	sgdt_dump( &SgTbl1, " " );
+
+	MV_PRINT( "Walking through the table:\n" );
+
+	MV_U32 index = 0;
+	sgd_table_walk( &SgTbl1, SgVisitor, &index );
+
+	sgd_iter_t iter;
+	sgd_t sg[2];
+
+	sgd_iter_init( &iter, SgTbl1.Entry_Ptr, 0, SgTbl1.Byte_Count );
+
+	MV_PRINT( "Walking through the table in another way:\n" );
+	i = 0;
+	while( sgd_iter_get_next( &iter, sg ) )
+	{
+		sgd_dump( sg, NULL );
+	}
+
+	sgdt_dump( &SgTbl1, " " );
+	sgd_t* sgd = SgTbl1.Entry_Ptr;
+	MV_U32 off = 0x1000;
+	sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x1000 );
+	sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x9000 );
+	sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x9000 );
+	sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x1000 );
+	sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x1000 );
+	sgdt_dump( &SgTbl3, " " );
+}
+#endif
+
+typedef struct _PRDTableWalkCtx
+{
+	MV_PVOID		pCore;
+	sgd_t*			pSg;
+	int				avail;
+	int				itemCnt;
+} PRDTableWalkCtx;
+
+static int PRDTablePrepareVisitor(sgd_t* sg, MV_PVOID _ctx)
+{
+	PRDTableWalkCtx* ctx = (PRDTableWalkCtx*) _ctx;
+
+	if( !ctx->avail )
+		return 0;
+
+	if( sg->flags & (SGD_VIRTUAL|SGD_VWOXCTX) )
+	{
+		MV_U32 totalSize, thisSize;
+		MV_PVOID vaddr;
+		MV_PVOID xctx;
+		MV_U64 paddr;
+#ifdef _OS_LINUX
+		MV_ASSERT( 0 );
+#endif /* _OS_LINUX */
+		sgd_getsz( sg, totalSize );
+
+		if( sg->flags & SGD_VIRTUAL )
+		{
+			sgd_get_vaddr( sg, vaddr );
+			sgd_get_xctx( sg, xctx );
+		}
+		else
+		{
+			vaddr = ((sgd_v_t*)sg)->u.vaddr;
+			xctx = 0;
+		}
+
+		while( 1 )
+		{
+			thisSize = totalSize;
+
+			if( !HBA_ModuleGetPhysicalAddress(
+					ctx->pCore, 
+					vaddr,
+					xctx,
+					&paddr,
+					&thisSize ) )
+				return 0;
+
+			ctx->avail--;
+			ctx->itemCnt++;
+
+			ctx->pSg->flags = 0;
+#ifdef ODIN_DRIVER
+			ctx->pSg->size = MV_CPU_TO_LE32(thisSize);
+#else
+			ctx->pSg->size = MV_CPU_TO_LE32(thisSize - 1);
+#endif
+			ctx->pSg->baseAddr.parts.low = MV_CPU_TO_LE32(paddr.parts.low);
+			ctx->pSg->baseAddr.parts.high = MV_CPU_TO_LE32(paddr.parts.high);
+			ctx->pSg++;
+
+			totalSize -= thisSize;
+			if( totalSize == 0 )
+				break;
+
+			if( !ctx->avail )
+				return 0;
+
+			vaddr = (MV_PVOID)((MV_PU8) vaddr + thisSize);
+		}
+	}
+	else
+	{
+		// including SGD_VP/SGD_PCTX
+		ctx->avail--;
+		ctx->itemCnt++;
+
+		ctx->pSg->flags = 0;
+#ifdef ODIN_DRIVER
+		ctx->pSg->size = MV_CPU_TO_LE32(sg->size);
+#else
+		ctx->pSg->size = MV_CPU_TO_LE32(sg->size - 1);
+#endif
+		ctx->pSg->baseAddr.parts.low = MV_CPU_TO_LE32(sg->baseAddr.parts.low);
+		ctx->pSg->baseAddr.parts.high = MV_CPU_TO_LE32(sg->baseAddr.parts.high);
+		ctx->pSg++;
+	}
+
+	return 1;
+}
+
+int sgdt_prepare_hwprd(
+	MV_PVOID		pCore,
+	sgd_tbl_t*		pSource,
+	sgd_t*			pSg,
+	int				availSgEntry
+	)
+{
+	PRDTableWalkCtx ctx;
+
+	ctx.pCore = pCore;
+	ctx.pSg = pSg;
+	ctx.avail = availSgEntry;
+	ctx.itemCnt = 0;
+
+	if( !sgd_table_walk( pSource, PRDTablePrepareVisitor, &ctx) )
+		return 0;
+
+	return ctx.itemCnt;
+}
+
+#endif // USE_NEW_SGTABLE
diff --git a/drivers/scsi/thor/lib/common/com_tag.c b/drivers/scsi/thor/lib/common/com_tag.c
new file mode 100755
index 0000000..d80e440
--- /dev/null
+++ b/drivers/scsi/thor/lib/common/com_tag.c
@@ -0,0 +1,72 @@
+#include "com_define.h"
+#include "com_tag.h"
+#include "com_dbg.h"
+
+MV_VOID Tag_Init( PTag_Stack pTagStack, MV_U16 size )
+{
+	MV_U16 i;
+	
+	MV_DASSERT( size == pTagStack->Size );
+	
+	pTagStack->Top = size;
+	pTagStack->TagStackType = FILO_TAG; 
+	pTagStack->PtrOut = 0;
+	for ( i=0; i<size; i++ )
+	{
+		pTagStack->Stack[i] = size-1-i;
+	}
+}
+
+MV_VOID Tag_Init_FIFO( PTag_Stack pTagStack, MV_U16 size )
+{
+	MV_U16 i;
+	
+	MV_DASSERT( size == pTagStack->Size );
+	
+	pTagStack->Top = size;
+	pTagStack->TagStackType = FIFO_TAG; 
+	pTagStack->PtrOut = 0;
+	for ( i=0; i<size; i++ )
+	{
+			pTagStack->Stack[i] = i;
+	}
+}
+
+MV_U16 Tag_GetOne(PTag_Stack pTagStack)
+{
+	MV_U16 nTag;
+
+	MV_DASSERT( pTagStack->Top>0 );
+	if(pTagStack->TagStackType==FIFO_TAG)
+	{
+		nTag = pTagStack->Stack[pTagStack->PtrOut++];
+		if(pTagStack->PtrOut>=pTagStack->Size)
+			pTagStack->PtrOut=0;
+		pTagStack->Top--;
+		return nTag;
+	}
+	else
+		return pTagStack->Stack[--pTagStack->Top];
+}
+
+MV_VOID Tag_ReleaseOne(PTag_Stack pTagStack, MV_U16 tag)
+{
+	MV_DASSERT( pTagStack->Top<pTagStack->Size );
+	if(pTagStack->TagStackType==FIFO_TAG)
+	{
+		pTagStack->Stack[(pTagStack->PtrOut+pTagStack->Top)%pTagStack->Size] = tag;
+		pTagStack->Top++;
+	}
+	else
+		pTagStack->Stack[pTagStack->Top++] = tag;
+}
+
+MV_BOOLEAN Tag_IsEmpty(PTag_Stack pTagStack)
+{
+	if ( pTagStack->Top==0 )
+	{
+		return MV_TRUE;
+	}
+	return MV_FALSE;
+}
+
diff --git a/drivers/scsi/thor/lib/common/com_u64.c b/drivers/scsi/thor/lib/common/com_u64.c
new file mode 100755
index 0000000..166d0bb
--- /dev/null
+++ b/drivers/scsi/thor/lib/common/com_u64.c
@@ -0,0 +1,149 @@
+#include "com_define.h"

+

+MV_U64 U64_ADD_U32(MV_U64 v64, MV_U32 v32)

+{

+#ifdef _64_BIT_COMPILER

+	v64.value += v32;

+#else

+	v64.parts.low += v32;

+	v64.parts.high = 0;	

+#endif

+	return v64;

+}

+

+MV_U64 U64_SUBTRACT_U32(MV_U64 v64, MV_U32 v32)

+{

+#ifdef _64_BIT_COMPILER

+	v64.value -= v32;

+#else

+	v64.parts.low -= v32;

+	v64.parts.high = 0;	

+#endif

+	return v64;

+}

+

+MV_U64 U64_MULTIPLY_U32(MV_U64 v64, MV_U32 v32)

+{

+#ifdef _64_BIT_COMPILER

+	v64.value *= v32;

+#else

+	v64.parts.low *= v32;

+	v64.parts.high = 0;	

+#endif

+	return v64;

+}

+

+MV_U32 U64_MOD_U32(MV_U64 v64, MV_U32 v32)

+{

+#ifdef _OS_LINUX

+	return do_div(v64.value, v32);

+#else

+	return (MV_U32) (v64.value % v32);

+#endif /* _OS_LINUX */

+}

+

+MV_U64 U64_DIVIDE_U32(MV_U64 v64, MV_U32 v32)

+{

+#ifdef _OS_LINUX

+	do_div(v64.value, v32);

+#else

+#ifdef _64_BIT_COMPILER

+	v64.value /= v32;

+#else

+	v64.parts.high = 0;	

+	v64.parts.low /= v32;

+#endif /* _64_BIT_COMPILER */

+

+#endif /* _OS_LINUX */

+	return v64;

+}

+

+MV_I32 U64_COMPARE_U32(MV_U64 v64, MV_U32 v32)

+{

+	if (v64.parts.high > 0)

+		return 1;

+	if (v64.parts.low > v32)

+		return 1;

+#ifdef _64_BIT_COMPILER

+	else if (v64.value == v32)

+#else

+	else if (v64.parts.low == v32)

+#endif

+		return 0;

+	else

+		return -1;

+}

+

+MV_U64 U64_ADD_U64(MV_U64 v1, MV_U64 v2)

+{

+#ifdef _64_BIT_COMPILER

+	v1.value += v2.value;

+#else

+	v1.parts.low += v2.parts.low;

+	v1.parts.high = 0;	

+#endif

+	return v1;

+}

+

+MV_U64 U64_SUBTRACT_U64(MV_U64 v1, MV_U64 v2)

+{

+#ifdef _64_BIT_COMPILER

+	v1.value -= v2.value;

+#else

+	v1.parts.low -= v2.parts.low;

+	v1.parts.high = 0;	

+#endif

+	return v1;

+}

+

+MV_U32 U64_DIVIDE_U64(MV_U64 v1, MV_U64 v2)

+{

+#ifdef _OS_LINUX

+	MV_U32 ret = 0;

+	while (v1.value > v2.value) {

+		v1.value -= v2.value;

+		ret++;

+	}

+	return ret;

+#else

+#ifdef _64_BIT_COMPILER

+	v1.value /= v2.value;

+#else

+	v1.parts.high = 0;	

+	v1.parts.low /= v2.parts.low;

+#endif

+	return v1.parts.low;

+#endif

+}

+

+MV_I32 U64_COMPARE_U64(MV_U64 v1, MV_U64 v2)

+{

+#ifdef _64_BIT_COMPILER

+	if (v1.value > v2.value)

+		return 1;

+	else if (v1.value == v2.value)

+		return 0;

+	else

+		return -1;

+#else

+	if (v1.value > v2.value)

+		return 1;

+	else if (v1.value == v2.value)

+		return 0;

+	else

+		return -1;

+

+#endif

+

+}

+

+#ifdef _OS_BIOS

+MV_U64 ZeroU64(MV_U64 v1)

+{

+	v1.parts.low = 0;

+	v1.parts.high = 0;

+

+	return	v1;

+}

+#endif /*  _OS_BIOS */

+

diff --git a/drivers/scsi/thor/lib/common/com_util.c b/drivers/scsi/thor/lib/common/com_util.c
new file mode 100755
index 0000000..9852272
--- /dev/null
+++ b/drivers/scsi/thor/lib/common/com_util.c
@@ -0,0 +1,737 @@
+#include "com_define.h"
+#include "com_dbg.h"
+#include "com_scsi.h"
+#include "com_util.h"
+#include "com_u64.h"
+
+#if ERROR_HANDLING_SUPPORT
+void MV_ZeroMvRequest(PMV_Request pReq)
+{
+	PMV_SG_Entry pSGEntry;
+	MV_U8 maxEntryCount;
+	MV_PVOID pSenseBuffer;
+	MV_PVOID pbheh_ctx;
+#ifdef __RES_MGMT__
+	List_Head list;
+#endif
+	MV_DASSERT(pReq);
+	pSGEntry = pReq->SG_Table.Entry_Ptr;
+	maxEntryCount = pReq->SG_Table.Max_Entry_Count;
+	pSenseBuffer = pReq->Sense_Info_Buffer;
+	pbheh_ctx = pReq->bh_eh_ctx;
+#ifdef __RES_MGMT__
+	list = pReq->pool_entry;
+#endif
+	MV_ZeroMemory(pReq, MV_REQUEST_SIZE);
+#ifdef __RES_MGMT__
+	pReq->pool_entry = list;
+#endif
+	pReq->SG_Table.Entry_Ptr = pSGEntry;
+	pReq->SG_Table.Max_Entry_Count = maxEntryCount;
+	pReq->Sense_Info_Buffer = pSenseBuffer;
+	pReq->bh_eh_ctx = pbheh_ctx;
+}
+#else
+void MV_ZeroMvRequest(PMV_Request pReq)
+{
+	PMV_SG_Entry pSGEntry;
+	MV_U8 maxEntryCount;
+	MV_PVOID pSenseBuffer;
+#ifdef __RES_MGMT__
+	List_Head list;
+#endif
+
+	MV_DASSERT(pReq);
+	pSGEntry = pReq->SG_Table.Entry_Ptr;
+	maxEntryCount = pReq->SG_Table.Max_Entry_Count;
+	pSenseBuffer = pReq->Sense_Info_Buffer;
+#ifdef __RES_MGMT__
+	list = pReq->pool_entry;
+#endif
+	MV_ZeroMemory(pReq, MV_REQUEST_SIZE);
+#ifdef __RES_MGMT__
+	pReq->pool_entry = list;
+#endif
+	pReq->SG_Table.Entry_Ptr = pSGEntry;
+	pReq->SG_Table.Max_Entry_Count = maxEntryCount;
+	pReq->Sense_Info_Buffer = pSenseBuffer;
+}
+#endif
+
+void MV_CopySGTable(PMV_SG_Table pTargetSGTable, PMV_SG_Table pSourceSGTable)
+{
+	pTargetSGTable->Valid_Entry_Count = pSourceSGTable->Valid_Entry_Count;
+	pTargetSGTable->Flag = pSourceSGTable->Flag;
+	pTargetSGTable->Byte_Count = pSourceSGTable->Byte_Count;
+	MV_CopyMemory(pTargetSGTable->Entry_Ptr, pSourceSGTable->Entry_Ptr, 
+					sizeof(MV_SG_Entry)*pTargetSGTable->Valid_Entry_Count);
+
+}
+
+#ifdef _OS_BIOS
+MV_U64 CPU_TO_BIG_ENDIAN_64(MV_U64 x)
+
+{
+	MV_U64 x1;
+	ZeroU64(x1);
+	x1.parts.low=CPU_TO_BIG_ENDIAN_32(x.parts.high);
+	x1.parts.high=CPU_TO_BIG_ENDIAN_32(x.parts.low);
+	return x1;
+}
+#endif	/* #ifdef _OS_BIOS */
+
+MV_BOOLEAN MV_Equals(
+	IN MV_PU8		des,
+	IN MV_PU8		src,
+	IN MV_U8		len							 
+)
+{
+	MV_U8 i;
+
+	for (i=0; i<len; i++){
+		if (*des != *src){
+			return MV_FALSE;
+		}
+		des++;
+		src++;
+	}
+	return MV_TRUE;
+}
+/*
+ * SG Table operation
+ */
+void SGTable_Init(
+	OUT PMV_SG_Table pSGTable,
+	IN MV_U8 flag
+	)
+{
+/*	pSGTable->Max_Entry_Count = MAX_SG_ENTRY;  set during module init */
+	pSGTable->Valid_Entry_Count = 0;
+	pSGTable->Flag = flag;
+	pSGTable->Byte_Count = 0;
+}
+
+#ifndef USE_NEW_SGTABLE
+void SGTable_Append(
+	OUT PMV_SG_Table pSGTable,
+	MV_U32 address,
+	MV_U32 addressHigh,
+	MV_U32 size
+	)
+{
+	PMV_SG_Entry pSGEntry;
+
+	pSGEntry = &pSGTable->Entry_Ptr[pSGTable->Valid_Entry_Count];
+
+	MV_ASSERT(pSGTable->Valid_Entry_Count < pSGTable->Max_Entry_Count);
+	/* 
+	 * Workaround hardware issue:
+	 * If the transfer size is odd, some request cannot be finished.
+	 * Hopefully the workaround won't damage the system.
+	 */
+#ifdef PRD_SIZE_WORD_ALIGN
+	if ( size%2 ) size++;
+#endif
+
+	pSGTable->Valid_Entry_Count += 1;
+	pSGTable->Byte_Count += size;
+
+	pSGEntry->Base_Address = address;
+	pSGEntry->Base_Address_High = addressHigh;
+	pSGEntry->Size = size;
+	pSGEntry->Reserved0 = 0;
+}
+#endif
+
+MV_BOOLEAN SGTable_Available(
+	IN PMV_SG_Table pSGTable
+	)
+{
+	return (pSGTable->Valid_Entry_Count < pSGTable->Max_Entry_Count);
+}
+
+void MV_InitializeTargetIDTable(
+	IN PMV_Target_ID_Map pMapTable
+	)
+{
+	MV_FillMemory((MV_PVOID)pMapTable, sizeof(MV_Target_ID_Map)*MV_MAX_TARGET_NUMBER, 0xFF);
+}
+
+MV_U16 MV_MapTargetID(
+	IN PMV_Target_ID_Map	pMapTable,
+	IN MV_U16				deviceId,
+	IN MV_U8				deviceType
+	)
+{
+	MV_U16 i;
+	for (i=0; i<MV_MAX_TARGET_NUMBER; i++) {
+		if (pMapTable[i].Type==0xFF) {	/* not mapped yet */
+			pMapTable[i].Device_Id = deviceId;
+			pMapTable[i].Type = deviceType;
+			break;
+		}
+	}
+	return i;
+}
+
+MV_U16 MV_MapToSpecificTargetID(
+	IN PMV_Target_ID_Map	pMapTable,
+	IN MV_U16				specificId,
+	IN MV_U16				deviceId,
+	IN MV_U8				deviceType
+	)
+{
+	/* first check if the device can be mapped to the specific ID */
+	if (pMapTable[specificId].Type==0xFF) {	/* not used yet */
+		pMapTable[specificId].Device_Id = deviceId;
+		pMapTable[specificId].Type = deviceType;
+		return specificId;
+	}
+	/* cannot mapped to the specific ID */
+	/* just map the device to first available ID */
+	return MV_MapTargetID(pMapTable, deviceId, deviceType);
+}
+
+MV_U16 MV_RemoveTargetID(
+	IN PMV_Target_ID_Map	pMapTable,
+	IN MV_U16				deviceId,
+	IN MV_U8				deviceType
+	)
+{
+	MV_U16 i;
+	for (i=0; i<MV_MAX_TARGET_NUMBER; i++) {
+		if ( (pMapTable[i].Type==deviceType) && (pMapTable[i].Device_Id==deviceId) ) {
+			pMapTable[i].Type = 0xFF;
+			pMapTable[i].Device_Id = 0xFFFF;
+			break;
+		}
+	}
+	return i;
+}
+
+MV_U16 MV_GetMappedID(
+	IN PMV_Target_ID_Map	pMapTable,
+	IN MV_U16				deviceId,
+	IN MV_U8				deviceType
+	)
+{
+	MV_U16 mappedID;
+	for (mappedID=0; mappedID<MV_MAX_TARGET_NUMBER; mappedID++) {
+		if ( (pMapTable[mappedID].Type==deviceType) && (pMapTable[mappedID].Device_Id==deviceId) )
+			break;
+	}
+	if (mappedID >= MV_MAX_TARGET_NUMBER)
+		mappedID = 0xFFFF;
+	else {
+		MV_DASSERT(mappedID < MV_MAX_TARGET_NUMBER);
+#ifdef SUPPORT_SCSI_PASSTHROUGH
+		if (mappedID == VIRTUAL_DEVICE_ID) {
+			/* Device is on LUN 1 */
+			mappedID |= 0x0100;
+		}
+#endif /* SUPPORT_SCSI_PASSTHROUGH */
+	}
+	return mappedID;
+}
+
+void MV_DecodeReadWriteCDB(
+	IN MV_PU8 Cdb,
+	OUT MV_LBA *pLBA,
+	OUT MV_U32 *pSectorCount)
+{
+	MV_LBA tmpLBA;
+	MV_U32 tmpSectorCount;
+
+	if ((!SCSI_IS_READ(Cdb[0])) && 
+	    (!SCSI_IS_WRITE(Cdb[0])) && 
+	    (!SCSI_IS_VERIFY(Cdb[0])))
+		return;
+
+	/* This is READ/WRITE command */
+	switch (Cdb[0]) {
+	case SCSI_CMD_READ_6:
+	case SCSI_CMD_WRITE_6:
+		tmpLBA.value = (MV_U32)((((MV_U32)(Cdb[1] & 0x1F))<<16) |
+					((MV_U32)Cdb[2]<<8) |
+					((MV_U32)Cdb[3]));
+		tmpSectorCount = (MV_U32)Cdb[4];
+		break;
+	case SCSI_CMD_READ_10:
+	case SCSI_CMD_WRITE_10:
+	case SCSI_CMD_VERIFY_10:
+		tmpLBA.value = (MV_U32)(((MV_U32)Cdb[2]<<24) | 
+					((MV_U32)Cdb[3]<<16) | 
+					((MV_U32)Cdb[4]<<8) | 
+					((MV_U32)Cdb[5]));
+		tmpSectorCount = ((MV_U32)Cdb[7]<<8) | (MV_U32)Cdb[8];
+		break;
+	case SCSI_CMD_READ_12:
+	case SCSI_CMD_WRITE_12:
+		tmpLBA.value = (MV_U32)(((MV_U32)Cdb[2]<<24) | 
+					((MV_U32)Cdb[3]<<16) | 
+					((MV_U32)Cdb[4]<<8) | 
+					((MV_U32)Cdb[5]));
+		tmpSectorCount = (MV_U32)(((MV_U32)Cdb[6]<<24) |
+					  ((MV_U32)Cdb[7]<<16) |
+					  ((MV_U32)Cdb[8]<<8) |
+					  ((MV_U32)Cdb[9]));
+		break;
+	case SCSI_CMD_READ_16:
+	case SCSI_CMD_WRITE_16:
+	case SCSI_CMD_VERIFY_16:
+		tmpLBA.parts.high = (MV_U32)(((MV_U32)Cdb[2]<<24) | 
+				       ((MV_U32)Cdb[3]<<16) | 
+				       ((MV_U32)Cdb[4]<<8) | 
+				       ((MV_U32)Cdb[5]));
+		tmpLBA.parts.low = (MV_U32)(((MV_U32)Cdb[6]<<24) |
+				      ((MV_U32)Cdb[7]<<16) |
+				      ((MV_U32)Cdb[8]<<8) |
+				      ((MV_U32)Cdb[9]));
+
+		tmpSectorCount = (MV_U32)(((MV_U32)Cdb[10]<<24) |
+					  ((MV_U32)Cdb[11]<<16) |
+					  ((MV_U32)Cdb[12]<<8) |
+					  ((MV_U32)Cdb[13]));
+		break;
+	default:
+		MV_DPRINT(("Unsupported READ/WRITE command [%x]\n", Cdb[0]));
+		U64_SET_VALUE(tmpLBA, 0);
+		tmpSectorCount = 0;
+	}
+	*pLBA = tmpLBA;
+	*pSectorCount = tmpSectorCount;
+}
+
+#ifndef _OS_BIOS
+void MV_DumpRequest(PMV_Request pReq, MV_BOOLEAN detail)
+{
+	MV_DPRINT(("Device[%d] Cdb[%2x,%2x,%2x,%2x, %2x,%2x,%2x,%2x, %2x,%2x,%2x,%2x].\n",
+		pReq->Device_Id,
+		pReq->Cdb[0],
+		pReq->Cdb[1],
+		pReq->Cdb[2],
+		pReq->Cdb[3],
+		pReq->Cdb[4],
+		pReq->Cdb[5],
+		pReq->Cdb[6],
+		pReq->Cdb[7],
+		pReq->Cdb[8],
+		pReq->Cdb[9],
+		pReq->Cdb[10],
+		pReq->Cdb[11]
+		));
+
+	if ( detail )
+	{
+		MV_DPRINT(("Scsi_Status=0x%x\n", pReq->Scsi_Status));
+		MV_DPRINT(("Tag=0x%x\n", pReq->Tag));
+		MV_DPRINT(("Data_Transfer_Length=%d\n", pReq->Data_Transfer_Length));
+		MV_DPRINT(("Sense_Info_Buffer_Length=%d\n", pReq->Sense_Info_Buffer_Length));
+		MV_DPRINT(("Org_Req : %p\n", pReq->Org_Req));
+	}
+}
+
+#if defined(SUPPORT_RAID6) && defined(RAID_DRIVER)
+void MV_DumpXORRequest(PMV_XOR_Request pXORReq, MV_BOOLEAN detail)
+{
+	MV_U32 i,j;
+
+	MV_PRINT("MV_XOR_Request: Type=0x%x, Source count=%d, Target count=%d\n",
+		pXORReq->Request_Type,
+		pXORReq->Source_SG_Table_Count,
+		pXORReq->Target_SG_Table_Count
+		);
+
+	if ( detail )
+	{
+		MV_PRINT("Source SG table...\n");
+		for ( i=0; i<pXORReq->Source_SG_Table_Count; i++ )
+			MV_DumpSGTable(&pXORReq->Source_SG_Table_List[i]);
+
+		MV_PRINT("Target SG table...\n");
+		for ( i=0; i<pXORReq->Target_SG_Table_Count; i++ )
+			MV_DumpSGTable(&pXORReq->Target_SG_Table_List[i]);
+
+		MV_PRINT("Coefficient...\n");
+		for ( i=0; i<pXORReq->Target_SG_Table_Count; i++ ) {
+			for ( j=0; j<pXORReq->Source_SG_Table_Count; j++ ) {
+				MV_PRINT("[%d,%d]=0x%x\n", i, j, pXORReq->Coef[i][j]);
+			}
+		}
+	}
+}
+#endif /* SUPPORT_RAID6 */
+
+void MV_DumpSGTable(PMV_SG_Table pSGTable)
+{
+#ifdef USE_NEW_SGTABLE
+	sgdt_dump(pSGTable, " ");
+#else
+	PMV_SG_Entry pSGEntry;
+	MV_U32 i;
+	MV_PRINT("SG Table: size(0x%x)\n", pSGTable->Byte_Count);
+	for ( i=0; i<pSGTable->Valid_Entry_Count; i++ )
+	{
+		pSGEntry = &pSGTable->Entry_Ptr[i];
+		MV_PRINT("%d: addr(0x%x-0x%x), size(0x%x).\n", 
+			i, pSGEntry->Base_Address_High, pSGEntry->Base_Address, pSGEntry->Size);
+	}
+#endif
+}
+
+const char* MV_DumpSenseKey(MV_U8 sense)
+{
+	switch ( sense )
+	{
+		case SCSI_SK_NO_SENSE:
+			return "SCSI_SK_NO_SENSE";
+		case SCSI_SK_RECOVERED_ERROR:
+			return "SCSI_SK_RECOVERED_ERROR";
+		case SCSI_SK_NOT_READY:
+			return "SCSI_SK_NOT_READY";
+		case SCSI_SK_MEDIUM_ERROR:
+			return "SCSI_SK_MEDIUM_ERROR";
+		case SCSI_SK_HARDWARE_ERROR:
+			return "SCSI_SK_HARDWARE_ERROR";
+		case SCSI_SK_ILLEGAL_REQUEST:
+			return "SCSI_SK_ILLEGAL_REQUEST";
+		case SCSI_SK_UNIT_ATTENTION:
+			return "SCSI_SK_UNIT_ATTENTION";
+		case SCSI_SK_DATA_PROTECT:
+			return "SCSI_SK_DATA_PROTECT";
+		case SCSI_SK_BLANK_CHECK:
+			return "SCSI_SK_BLANK_CHECK";
+		case SCSI_SK_VENDOR_SPECIFIC:
+			return "SCSI_SK_VENDOR_SPECIFIC";
+		case SCSI_SK_COPY_ABORTED:
+			return "SCSI_SK_COPY_ABORTED";
+		case SCSI_SK_ABORTED_COMMAND:
+			return "SCSI_SK_ABORTED_COMMAND";
+		case SCSI_SK_VOLUME_OVERFLOW:
+			return "SCSI_SK_VOLUME_OVERFLOW";
+		case SCSI_SK_MISCOMPARE:
+			return "SCSI_SK_MISCOMPARE";
+		default:
+			MV_DPRINT(("Unknown sense key 0x%x.\n", sense));
+			return "Unknown sense key";
+	}
+}
+#endif	/* #ifndef _OS_BIOS */
+
+static MV_U32  BASEATTR crc_tab[] = {
+        0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+        0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+        0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+        0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+        0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+        0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+        0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+        0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+        0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+        0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+        0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+        0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+        0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+        0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+        0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+        0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+        0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+        0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+        0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+        0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+        0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+        0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+        0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+        0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+        0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+        0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+        0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+        0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+        0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+        0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+        0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+        0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+        0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+        0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+        0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+        0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+        0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+        0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+        0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+        0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+        0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+        0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+        0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+        0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+        0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+        0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+        0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+        0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+        0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+        0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+        0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+        0x2d02ef8dL
+};
+
+/* Calculate CRC and generate PD_Reference number */
+MV_U32 MV_CRC(
+	IN	MV_PU8		pData, 
+	IN	MV_U16		len
+)
+{
+    MV_U16 i;
+    MV_U32 crc = MV_MAX_U32;
+
+    for (i = 0;  i < len;  i ++) {
+		crc = crc_tab[(crc ^ pData[i]) & 0xff] ^ (crc >> 8);
+    }
+    return MV_CPU_TO_BE32(crc);
+}
+
+#ifdef MV_DEBUG
+void MV_CHECK_OS_SG_TABLE(
+	IN PMV_SG_Table pSGTable
+	)
+{
+#ifndef USE_NEW_SGTABLE
+	/* Check whether there are duplicated entries pointed to the same physical address. */
+	MV_U32 i,j;
+	static MV_BOOLEAN assertSGTable = MV_TRUE;
+
+	if ( assertSGTable ) {
+		for ( i=0; i<pSGTable->Valid_Entry_Count; i++ ) {
+			for ( j=i+1; j<pSGTable->Valid_Entry_Count; j++ ) {
+				MV_DASSERT( pSGTable->Entry_Ptr[i].Base_Address!=pSGTable->Entry_Ptr[j].Base_Address );
+			}
+		}
+	}
+#endif
+}
+#endif /* MV_DEBUG */
+
+#ifdef _OS_LINUX
+
+#if 1//def MV_DEBUG
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+
+void list_add_debug(struct list_head *new_list,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	if (unlikely(next->prev != prev)) {
+		MV_DPRINT(( "list_add corruption. next->prev should be "
+			"prev (0x%p), but was 0x%p. (next=0x%p).\n",
+			prev, next->prev, next));
+
+		MV_DPRINT(( "prev=0x%p, prev->next=0x%p,  prev->prev=0x%p"
+			"next=0x%p, next->next=0x%p, next->prev=0x%p.\n",
+			prev, prev->next, prev->prev, next, next->next, next->prev));
+#ifdef MV_LINUX_KGDB
+		MV_DASSERT(0);
+#endif
+
+	}
+	if (unlikely(prev->next != next)) {
+		MV_DPRINT(( "list_add corruption. prev->next should be "
+			"next (0x%p), but was 0x%p. (prev=0x%p).\n",
+			next, prev->next, prev));
+
+		MV_DPRINT(( "prev=0x%p, prev->next=0x%p,  prev->prev=0x%p,"
+			"next=0x%p, next->next=0x%p, next->prev=0x%p.\n",
+			prev, prev->next, prev->prev, next, next->next, next->prev));
+
+#ifdef MV_LINUX_KGDB
+		MV_DASSERT(0);
+#endif
+
+	}
+	next->prev = new_list;
+	new_list->next = next;
+	new_list->prev = prev;
+	prev->next = new_list;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+void List_Del(struct list_head *entry)
+{
+	if (unlikely(entry->prev->next != entry)) {
+		MV_DPRINT(("list_del corruption. prev->next should be %p, "
+				"but was %p\n", entry, entry->prev->next));
+		MV_DPRINT(( "entry->next=%p, entry->next->next=%p,  entry->next->prev=%p.\n"
+				"entry->prev=%p, entry->prev->next=%p, entry->prev->prev=%p.\n",
+			entry->prev, entry->next->next, entry->next->prev, entry->prev, entry->prev->next, entry->prev->prev));
+
+#ifdef MV_LINUX_KGDB
+		MV_DASSERT(0);
+#endif
+	}
+	if (unlikely(entry->next->prev != entry)) {
+		MV_DPRINT(( "list_del corruption. next->prev should be %p, "
+				"but was %p\n", entry, entry->next->prev));
+
+		MV_DPRINT(("entry->next=%p, entry->next->next=%p,  entry->next->prev=%p.\n"
+				"entry->prev=%p, entry->prev->next=%p, entry->prev->prev=%p.\n",
+			entry->next, entry->next->next, entry->next->prev, entry->prev, entry->prev->next, entry->prev->prev));
+
+#ifdef MV_LINUX_KGDB
+		MV_DASSERT(0);
+#endif
+	}
+
+	if(likely(entry->prev->next == entry) && likely(entry->next->prev == entry))
+		__list_del(entry->prev, entry->next);
+	
+	entry->next = NULL;
+	entry->prev = NULL;
+}
+
+#else
+
+void List_Del(List_Head *entry)
+{
+#ifdef SUPPORT_REQUEST_TIMER
+          BUG_ON(!entry);
+          BUG_ON(!entry->prev);
+          BUG_ON(!entry->next);
+#endif
+//	list_del(entry);	//Not use kernel function, which set next,prev not NULL but LIST_POISON1 under DEBUG mode
+	__list_del(entry->prev, entry->next);
+	entry->next = NULL;	
+	entry->prev = NULL;
+
+//	if((entry->prev) || (entry->next))
+//	__List_Del(entry->prev, entry->next);
+//	entry->next = NULL;
+//	entry->prev = NULL;
+}
+
+
+#endif
+
+
+void List_Add(List_Head *new_one, List_Head *head)
+{
+          BUG_ON(!head);
+          BUG_ON(!head->prev);
+          BUG_ON(!head->next);
+	
+          BUG_ON(!new_one);
+
+#ifdef MV_DEBUG
+	list_add_debug(new_one, head, head->next);
+#else
+	list_add(new_one, head);
+#endif
+        BUG_ON(!new_one->next);
+         BUG_ON(!new_one->prev);
+         
+}
+
+void List_AddTail(List_Head *new_one, List_Head *head)
+{
+          BUG_ON(!head);
+          BUG_ON(!head->prev);
+          BUG_ON(!head->next);
+	
+          BUG_ON(!new_one);
+
+#ifdef MV_DEBUG
+	list_add_debug(new_one, head->prev, head);
+#else
+	list_add_tail(new_one, head);
+#endif
+        BUG_ON(!new_one->next);
+         BUG_ON(!new_one->prev);
+         
+}
+
+
+
+struct list_head *List_GetFirst(struct list_head *head)
+{
+        struct list_head * one = NULL;
+          BUG_ON(!head);
+          BUG_ON(!head->prev);
+          BUG_ON(!head->next);
+
+	if (unlikely(head->prev->next != head)) {
+		MV_DPRINT(( "List_GetFirst corruption. prev->next should be 0x%p, "
+				"but was 0x%p\n", head, head->prev->next));
+
+		MV_DPRINT(( "head=0x%p, head->next=0x%p,  head->prev=0x%p,"
+			"head->prev->next=0x%p, head->prev->prev=0x%p.\n",
+			head, head->next, head->prev,  head->prev->next, head->prev->prev));
+
+#ifdef MV_LINUX_KGDB
+		MV_DASSERT(0);
+#endif
+	}
+	if (unlikely(head->next->prev != head)) {
+		MV_DPRINT(( "List_GetFirst corruption. next->prev should be 0x%p, "
+				"but was 0x%p\n", head, head->next->prev));
+
+		MV_DPRINT(( "head=%p, head->next=%p,  head->prev=%p,"
+			"head->next->next=%p, head->next->prev=%p.\n",
+			head, head->next, head->prev, head->next->next, head->next->prev));
+
+#ifdef MV_LINUX_KGDB
+		MV_DASSERT(0);
+#endif
+	}
+
+      	if (list_empty(head))
+		return NULL;
+
+        one = head->next;
+        BUG_ON(!one->next);
+        BUG_ON(!one->prev);
+      	List_Del(one);
+
+	if (unlikely(head->prev->next != head)) {
+		MV_DPRINT(( "List_GetFirst after del corruption. prev->next should be 0x%p, "
+				"but was 0x%p\n", head, head->prev->next));
+#ifdef MV_LINUX_KGDB
+		MV_DASSERT(0);
+#endif
+	}
+	if (unlikely(head->next->prev != head)) {
+		MV_DPRINT(("List_GetFirst after del corruption. next->prev should be 0x%p, "
+				"but was 0x%p\n", head, head->next->prev));
+#ifdef MV_LINUX_KGDB
+		MV_DASSERT(0);
+#endif
+	}
+      	
+        return one;
+}
+
+struct list_head *List_GetLast(struct list_head *head)
+{
+        struct list_head * one = NULL;
+            BUG_ON(!head);
+          BUG_ON(!head->prev);
+          BUG_ON(!head->next);
+        if (list_empty(head))
+		return NULL;
+
+        one = head->prev;
+         BUG_ON(!one->next);
+        BUG_ON(!one->prev);
+        List_Del(one);
+        return one;
+}
+
+
+
+#endif
+
diff --git a/drivers/scsi/thor/linux/hba_exp.c b/drivers/scsi/thor/linux/hba_exp.c
new file mode 100755
index 0000000..9c135f8
--- /dev/null
+++ b/drivers/scsi/thor/linux/hba_exp.c
@@ -0,0 +1,242 @@
+#include "hba_header.h"

+#include "linux_main.h"

+

+#include "hba_exp.h"

+

+/*

+ * 

+ * Other exposed functions

+ *

+ */

+int __mv_is_mod_all_started(struct mv_adp_desc *adp_desc);

+/* 

+ * The extension is the calling module extension. 

+ *   It can be any module extension. 

+ */

+void HBA_ModuleStarted(struct mv_mod_desc *mod_desc)

+{

+	struct hba_extension *hba;

+	struct mv_mod_desc *desc;

+	MV_DBG(DMSG_KERN, "start HBA_ModuleStarted addr %p.\n",mod_desc);

+

+	desc = mod_desc;

+	while (desc->parent)

+		desc = desc->parent; /* hba to be the uppermost */

+	hba = (struct hba_extension *) desc->extension;

+

+	if (__mv_is_mod_all_started(desc->hba_desc)) {

+		MV_DBG(DMSG_HBA, "all modules have been started.\n");

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+		atomic_set(&hba->hba_sync, 0);

+#else

+		complete(&hba->cmpl);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+		/* We are totally ready for requests handling. */

+		hba->State = DRIVER_STATUS_STARTED;

+

+		/* Module 0 is the last module */

+		hba->desc->ops->module_notification(hba,

+						    EVENT_MODULE_ALL_STARTED,

+						    NULL);

+	} else {

+		/*

+		 * hba's start has already been called, so we should not

+		 * call it here. (hba is the highest module, it has no parent.)

+		 */

+		if (mod_desc->parent && mod_desc->parent->parent)

+		{

+			MV_DBG(DMSG_HBA, "start module %d.....\n",mod_desc->parent->module_id);

+			mod_desc->parent->ops->module_start(mod_desc->parent->extension);

+		}

+	}

+

+}

+

+#ifdef __BIG_ENDIAN

+void hba_swap_buf_le16(u16 *buf, unsigned int words)

+{

+

+	unsigned int i;

+

+	for (i=0; i < words; i++)

+                buf[i] = le16_to_cpu(buf[i]);

+

+}

+#else

+inline void hba_swap_buf_le16(u16 *buf, unsigned int words) {}

+#endif /* __BIG_ENDIAN */

+

+void hba_map_sg_to_buffer(void *preq)

+{

+	struct scsi_cmnd *scmd =NULL;

+	struct scatterlist *sg =NULL;

+	PMV_Request        req =NULL;

+

+	req  = (PMV_Request) preq;

+

+	if (REQ_TYPE_OS != req->Req_Type)

+		return;

+

+	scmd = (struct scsi_cmnd *) req->Org_Req;

+	sg = (struct scatterlist *) mv_rq_bf(scmd);

+

+	

+	if (mv_use_sg(scmd)) {

+		if (mv_use_sg(scmd) > 1)

+			MV_DBG(DMSG_SCSI, 

+			       "_MV_ more than 1 sg entry in an inst cmd.\n");

+	

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+		req->Data_Buffer = kmalloc(sg->length, GFP_ATOMIC);

+		if (req->Data_Buffer) {

+			memset(req->Data_Buffer, 0, sg->length);

+		}

+#else

+		req->Data_Buffer = kzalloc(sg->length, GFP_ATOMIC);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) */

+

+		req->Data_Transfer_Length = sg->length;

+	} else {

+	        req->Data_Buffer = mv_rq_bf(scmd);

+	}

+}

+

+void hba_unmap_sg_to_buffer(void *preq)

+{

+	void *buf;

+	struct scsi_cmnd *scmd = NULL;

+	struct scatterlist *sg = NULL;

+	PMV_Request        req = NULL;

+	unsigned long flags = 0;

+

+	req  = (PMV_Request) preq;

+

+	if (REQ_TYPE_OS != req->Req_Type)

+		return;

+

+	scmd = (struct scsi_cmnd *) req->Org_Req;

+	sg   = (struct scatterlist *)mv_rq_bf(scmd);

+

+	if (mv_use_sg(scmd)) {

+		//MV_WARNON(!irqs_disabled());

+		local_irq_save(flags);

+		buf = map_sg_page(sg) + sg->offset;

+		memcpy(buf, req->Data_Buffer, sg->length);

+		kunmap_atomic(buf, KM_IRQ0);

+		kfree(req->Data_Buffer);

+		local_irq_restore(flags);

+	}

+}

+

+MV_PVOID HBA_GetModuleExtension(MV_PVOID ext, MV_U32 mod_id)

+{

+	struct mv_mod_desc *mod_desc=(struct mv_mod_desc *)__ext_to_gen(ext)->desc;

+	struct mv_adp_desc *hba_desc = mod_desc->hba_desc;

+	MV_ASSERT(mod_id<MAX_MODULE_NUMBER);

+	BUG_ON(NULL == mod_desc);

+	list_for_each_entry(mod_desc, &hba_desc->online_module_list, 

+			    mod_entry)

+	{

+		BUG_ON(NULL == mod_desc);

+		if (mod_desc->status != MV_MOD_GONE) 

+		{

+			if ((mod_desc->module_id == mod_id) && (mod_desc->extension))

+			{

+				return mod_desc->extension;

+			}

+		}

+	}

+

+	MV_ASSERT(MV_FALSE);

+	return	NULL;

+}

+#ifdef THOR_DRIVER

+void HBA_TimerRoutine(unsigned long DeviceExtension)

+{

+#ifndef SUPPORT_TIMER

+	PHBA_Extension pHBA   = (PHBA_Extension)HBA_GetModuleExtension((MV_PVOID)DeviceExtension, MODULE_HBA);

+	PTimer_Module  pTimer = &pHBA->Timer_Module;

+	unsigned long  flags;

+

+	MV_DASSERT(pTimer->routine != NULL);

+	spin_lock_irqsave(&pHBA->desc->hba_desc->global_lock, flags);

+	pTimer->routine(pTimer->context);

+	spin_unlock_irqrestore(&pHBA->desc->hba_desc->global_lock, flags);

+#endif /* SUPPORT_TIMER */

+}

+

+

+void HBA_RequestTimer(

+	MV_PVOID extension,

+	MV_U32 millisecond,

+	MV_VOID (*routine) (MV_PVOID)

+	)

+{

+	PHBA_Extension pHBA   = (PHBA_Extension)HBA_GetModuleExtension(extension,MODULE_HBA);

+	PTimer_Module pTimer = &pHBA->Timer_Module;

+	u64 jif_offset;

+	

+	pTimer->routine = routine;

+	pTimer->context = extension;

+	del_timer(&pHBA->timer);

+	pHBA->timer.function = HBA_TimerRoutine;

+	pHBA->timer.data = (unsigned long)extension;

+	jif_offset = (u64)(millisecond * HZ);

+	do_div(jif_offset, 1000);

+	pHBA->timer.expires = jiffies + 1 + jif_offset;

+	add_timer(&pHBA->timer);

+}

+

+void hba_spin_lock_irq(spinlock_t* plock)

+{

+	WARN_ON(irqs_disabled());

+	spin_lock_irq(plock);                             	

+}

+

+void hba_spin_unlock_irq(spinlock_t* plock)

+{

+	spin_unlock_irq(plock);                             	

+}

+

+

+#endif

+

+#define LO_ADDR(x) ((MV_U32) ((MV_PTR_INTEGER) (x)))

+#define HI_ADDR(x) ((MV_U32) (sizeof(void *)>4?((MV_PTR_INTEGER) (x))>>32:0))

+

+MV_BOOLEAN __is_scsi_cmd_simulated(MV_U8 cmd_type)

+{

+	switch (cmd_type)

+	{

+	case SCSI_CMD_INQUIRY:

+	case SCSI_CMD_READ_CAPACITY_10:

+	case SCSI_CMD_READ_CAPACITY_16:

+	case SCSI_CMD_SYNCHRONIZE_CACHE_10:

+	case SCSI_CMD_TEST_UNIT_READY:

+	case SCSI_CMD_REQUEST_SENSE:

+	case SCSI_CMD_RESERVE_6:

+	case SCSI_CMD_RELEASE_6:

+	case SCSI_CMD_REPORT_LUN:

+	case SCSI_CMD_MODE_SENSE_6:

+	case SCSI_CMD_MODE_SENSE_10:

+	case SCSI_CMD_MODE_SELECT_6:

+	case SCSI_CMD_MODE_SELECT_10:

+#ifdef SUPPORT_ATA_SMART

+	case SCSI_CMD_LOG_SENSE:

+	case SCSI_CMD_READ_DEFECT_DATA_10:

+#endif

+#ifdef CORE_SUPPORT_API

+	case APICDB0_PD:

+#   ifdef SUPPORT_PASS_THROUGH_DIRECT

+	case APICDB0_PASS_THRU_CMD:

+#   endif /* SUPPORT_PASS_THROUGH_DIRECT */

+#   ifdef SUPPORT_CSMI

+	case APICDB0_CSMI_CORE:

+#   endif /* SUPPORT_CSMI */

+#endif /* CORE_SUPPORT_API */

+		return MV_TRUE;

+	default:

+		return MV_FALSE;

+	}

+}

+

diff --git a/drivers/scsi/thor/linux/hba_exp.h b/drivers/scsi/thor/linux/hba_exp.h
new file mode 100755
index 0000000..9f3cd66
--- /dev/null
+++ b/drivers/scsi/thor/linux/hba_exp.h
@@ -0,0 +1,177 @@
+#ifndef __HBA_EXPOSE_H__

+#define __HBA_EXPOSE_H__

+

+#ifdef SUPPORT_EVENT

+#include "com_event_struct.h"

+#include "com_event_define.h"

+#include "com_event_define_ext.h"

+#endif /* SUPPORT_EVENT */

+

+#include "hba_header.h"

+#include "com_mod_mgmt.h"

+

+struct _MV_SCP {

+	MV_U16           mapped;

+	MV_U16           map_atomic;

+	BUS_ADDRESS bus_address;

+};

+

+#define MV_SCp(cmd) ((struct _MV_SCP *)(&((struct scsi_cmnd *)cmd)->SCp))

+

+typedef struct _Assigned_Uncached_Memory

+{

+	MV_PVOID			Virtual_Address;

+	MV_PHYSICAL_ADDR	Physical_Address;

+	MV_U32				Byte_Size;

+	MV_U32				Reserved0;

+} Assigned_Uncached_Memory, *PAssigned_Uncached_Memory;

+

+typedef struct _Controller_Infor

+{

+        MV_PVOID Base_Address;

+

+        MV_U16 Vendor_Id;

+        MV_U16 Device_Id;

+        MV_U8 Revision_Id;

+        MV_U8 Reserved[3];

+} Controller_Infor, *PController_Infor;

+

+void HBA_ModuleStarted(struct mv_mod_desc *mod_desc);

+

+#ifdef SUPPORT_ATA_POWER_MANAGEMENT                                                                       

+#define IS_ATA_PASS_THROUGH_COMMAND(pReq) \

+	((pReq->Cdb[0] == SCSI_CMD_MARVELL_SPECIFIC) && \

+    		(pReq->Cdb[1] == CDB_CORE_MODULE) && (\

+			pReq->Cdb[2] == CDB_CORE_ATA_SLEEP || \

+			pReq->Cdb[2] == CDB_CORE_ATA_IDLE || \

+			pReq->Cdb[2] == CDB_CORE_ATA_STANDBY || \

+			pReq->Cdb[2] == CDB_CORE_ATA_IDLE_IMMEDIATE || \

+			pReq->Cdb[2] == CDB_CORE_ATA_CHECK_POWER_MODE || \

+			pReq->Cdb[2] == CDB_CORE_ATA_STANDBY_IMMEDIATE || \

+			pReq->Cdb[2] == CDB_CORE_RESET_DEVICE))

+#endif

+

+#define IS_ATA_12_CMD(scmd) \

+	((scmd->cmnd[0]==ATA_12)&& \

+	 (scmd->cmnd[9] ==0x08||scmd->cmnd[9] ==0xE0||\

+	 scmd->cmnd[9] ==0xE1||scmd->cmnd[9] ==0xE2||\

+	 scmd->cmnd[9] ==0xE3|| scmd->cmnd[9] ==0xE5||\

+	 scmd->cmnd[9] ==0xE6||scmd->cmnd[9] ==0xEC||\

+	 scmd->cmnd[9] ==0xA1||scmd->cmnd[9] ==0xB0))

+

+

+#ifdef SUPPORT_EVENT

+/* wrapper for DriverEvent, needed to implement queue */

+typedef struct _Driver_Event_Entry

+{

+	struct list_head Queue_Pointer;

+	DriverEvent Event;

+} Driver_Event_Entry, *PDriver_Event_Entry;

+#endif /* SUPPORT_EVENT */

+

+struct gen_module_desc {

+#ifdef __MM_SE__	

+/* Must the first */

+	struct mv_mod_desc *desc;

+#else

+	MV_PVOID	reserved;

+#endif /* __MM_SE__ */	

+};

+

+#define __ext_to_gen(_ext)       ((struct gen_module_desc *) (_ext))

+

+#define HBA_GetNextModuleSendFunction(_ext, _child_ext_p, _func_pp)          \

+           {                                                                 \

+		   *(_func_pp) = __ext_to_gen(_ext)->desc->child->ops->module_sendrequest; \

+		   *(_child_ext_p) = __ext_to_gen(_ext)->desc->child->extension;           \

+	   }

+

+#define HBA_GetUpperModuleNotificationFunction(_ext, _parent_ext_p, _func_pp) \

+           {                                                                  \

+		   *(_func_pp) = __ext_to_gen(_ext)->desc->parent->ops->module_notification; \

+		   *(_parent_ext_p) = __ext_to_gen(_ext)->desc->parent->extension;           \

+	   }

+

+

+#define hba_notify_upper_md(ext, eid, param)                 			 	\

+   {                                                                     	\

+	__ext_to_gen(ext)->desc->parent->ops->module_notification(       		\

+                                            __ext_to_gen(ext)->desc->parent->extension, 	\

+					    					eid,         				 	\

+					    					param);					 	\

+   }

+

+

+

+#define HBA_GetControllerInfor(_ext, _pinfo)                              \

+           {    \

+		   (_pinfo)->Base_Address = __ext_to_gen(_ext)->desc->hba_desc->Base_Address; \

+		   (_pinfo)->Vendor_Id    = __ext_to_gen(_ext)->desc->hba_desc->vendor;    \

+		   (_pinfo)->Device_Id    = __ext_to_gen(_ext)->desc->hba_desc->device;    \

+		   (_pinfo)->Revision_Id  = __ext_to_gen(_ext)->desc->hba_desc->Revision_Id;  \

+	   }

+

+

+void hba_swap_buf_le16(u16 *buf, unsigned int words);

+

+/* map bus addr in sg entry into cpu addr (access via. Data_Buffer) */

+void hba_map_sg_to_buffer(void *preq);

+void hba_unmap_sg_to_buffer(void *preq);

+

+void hba_log_msg(unsigned char *buf, unsigned int len);

+

+int __hba_dump_log(unsigned char *buf);

+

+static inline MV_BOOLEAN

+HBA_ModuleGetPhysicalAddress(MV_PVOID Module,

+			     MV_PVOID Virtual,

+			     MV_PVOID TranslationContext,

+			     MV_PU64 PhysicalAddress,

+			     MV_PU32 Length)

+{

+	panic("not supposed to be called.\n");

+	return MV_FALSE;

+};

+

+void __hba_dump_req_info(unsigned int module, PMV_Request req);

+int HBA_GetResource(struct mv_mod_desc *mod_desc,

+		    enum Resource_Type type,

+		    MV_U32  size,

+		    Assigned_Uncached_Memory *dma_res);

+MV_PVOID HBA_GetModuleExtension(MV_PVOID ext, MV_U32 mod_id);

+void HBA_ModuleNotification(MV_PVOID This, 

+			     enum Module_Event event, 

+			     struct mod_notif_param *event_param);

+

+#ifdef THOR_DRIVER

+void HBA_RequestTimer(

+	MV_PVOID extension,

+	MV_U32 millisecond,

+	MV_VOID (*routine) (MV_PVOID)

+	);

+void hba_spin_lock_irq(spinlock_t* plock);

+void hba_spin_unlock_irq(spinlock_t* plock);

+

+#endif

+

+#ifdef SUPPORT_REQUEST_TIMER

+#define 	add_request_timer(pReq, time, func, ctx)			\

+			{													\

+				hba_add_timer(pReq, time, (OSSW_TIMER_FUNCTION)(func));					\

+				(pReq)->err_request_ctx=(MV_PVOID)(ctx);							\

+			}	

+

+#define 	remove_request_timer(pReq)			\

+			{													\

+				hba_remove_timer(pReq);					\

+			}	

+

+#endif

+

+MV_BOOLEAN __is_scsi_cmd_simulated(MV_U8 cmd_type);

+void HBA_kunmap_sg(void*);

+/*set pci Device ID */

+MV_U16 SetDeviceID(MV_U32 pad_test);

+

+

+#endif /* __HBA_EXPOSE_H__ */

diff --git a/drivers/scsi/thor/linux/hba_header.h b/drivers/scsi/thor/linux/hba_header.h
new file mode 100755
index 0000000..f0d6825
--- /dev/null
+++ b/drivers/scsi/thor/linux/hba_header.h
@@ -0,0 +1,27 @@
+#ifndef __MV_HBA_HEADER_LINUX__

+#define  __MV_HBA_HEADER_LINUX__

+

+struct hba_extension;

+typedef struct hba_extension HBA_Extension, *PHBA_Extension;

+

+#include "mv_os.h"

+

+#include "com_type.h"

+#include "com_u64.h"

+#include "com_util.h"

+#include "com_list.h"

+#include "com_dbg.h"

+#include "com_scsi.h"

+#include "com_api.h"

+#include "com_struct.h"

+#include "com_event_struct.h"

+#include "com_sgd.h"

+

+#include "oss_wrapper.h"

+#include "hba_mod.h"

+#include "hba_timer.h"

+#include "hba_inter.h"

+

+#include "res_mgmt.h"

+

+#endif /* __MV_HBA_HEADER_LINUX__ */

diff --git a/drivers/scsi/thor/linux/hba_inter.h b/drivers/scsi/thor/linux/hba_inter.h
new file mode 100755
index 0000000..3a92466
--- /dev/null
+++ b/drivers/scsi/thor/linux/hba_inter.h
@@ -0,0 +1,64 @@
+#ifndef HBA_INTERNAL_H

+#define HBA_INTERNAL_H

+

+#include "hba_header.h"

+

+typedef struct _Timer_Module

+{

+	MV_PVOID context;

+	MV_VOID (*routine) (MV_PVOID);

+} Timer_Module, *PTimer_Module;

+

+

+struct hba_extension {

+/* Must be the first */

+/* self-descriptor */

+	struct mv_mod_desc *desc;

+	/* Device extention */

+	MV_PVOID host_data;

+	

+	

+	struct list_head        next;

+	struct pci_dev          *dev;

+	struct cdev             cdev;

+

+#ifdef THOR_DRIVER

+	struct timer_list	timer;

+	struct _Timer_Module    Timer_Module;

+#endif

+	//spinlock_t              lock;

+

+	struct Scsi_Host	*host;

+	struct completion       cmpl;

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_t                hba_sync;

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+

+	MV_U32                  State;	

+	MV_BOOLEAN              Is_Dump;

+	MV_U8                   Io_Count;

+	MV_U16                  Max_Io;

+

+#ifdef SUPPORT_EVENT

+	struct list_head        Stored_Events;

+	struct list_head        Free_Events;

+	MV_U32	                SequenceNumber;

+	MV_U8                   Num_Stored_Events;

+#endif /* SUPPORT_EVENT */

+	MV_PVOID                req_pool;

+

+	MV_U8                   Memory_Pool[1];

+

+#ifdef SUPPORT_TASKLET

+	struct tasklet_struct mv_tasklet;

+#endif

+	

+};

+

+#define DRIVER_STATUS_IDLE      1    /* The first status */

+#define DRIVER_STATUS_STARTING  2    /* Begin to start all modules */

+#define DRIVER_STATUS_STARTED   3    /* All modules are all settled. */

+#define DRIVER_STATUS_SHUTDOWN   4    /* All modules are all settled. */

+

+#endif /* HBA_INTERNAL_H */

diff --git a/drivers/scsi/thor/linux/hba_mod.c b/drivers/scsi/thor/linux/hba_mod.c
new file mode 100755
index 0000000..377573e
--- /dev/null
+++ b/drivers/scsi/thor/linux/hba_mod.c
@@ -0,0 +1,2586 @@
+/*

+ * module management module - module of the modules

+ *

+ *

+ */

+#define IOCTL_TEMPLATE

+#ifdef IOCTL_TEMPLATE

+#define SECTOR_SIZE 512

+#include <linux/hdreg.h>

+

+#endif

+#include "hba_header.h"

+

+#include "linux_main.h"

+#include "linux_iface.h"

+

+#include "hba_timer.h"

+#include "hba_mod.h"

+

+#include "res_mgmt.h"

+

+#include "hba_exp.h"

+#include <scsi/scsi_tcq.h>

+#include "core_inter.h"

+#include "core_sat.h"

+#include "core_ata.h"

+#include <scsi/scsi_eh.h>

+

+#if 0

+static void __dump_hex(const unsigned char *buf, int len)

+{

+	int i;

+

+	for (i = 0; i < len; i++) {

+		if (i && !(i % 8))

+			printk(YELLOW(" :"));

+		if (i && !(i % 16))

+			printk("\n");

+		printk(" %02X", buf[i]);

+	}

+	printk("\n");

+}

+#endif

+

+void __hba_dump_req_info(MV_U32 id, PMV_Request preq)

+{

+#if 0

+	unsigned long lba =0;

+	char *buf;

+	struct scsi_cmnd *scmd = NULL;

+	struct scatterlist *sg = NULL;

+

+	switch (preq->Cdb[0]) {

+	case SCSI_CMD_READ_10:

+	case SCSI_CMD_WRITE_10:

+		lba = preq->Cdb[2]<<24 | preq->Cdb[3]<<16 | preq->Cdb[4]<<8 | \

+			preq->Cdb[5];

+		break;

+	case SCSI_CMD_INQUIRY:

+		if (REQ_STATUS_SUCCESS != preq->Scsi_Status)

+			break;

+

+		scmd = (struct scsi_cmnd *) preq->Org_Req;

+		sg   = (struct scatterlist *) mv_rq_bf(scmd);

+		

+		/* ignored  */

+		break;

+

+		buf = map_sg_page(sg) + sg->offset;

+		MV_DBG(DMSG_SCSI, BLUE("-- inquiry dump starts -- ")"\n");

+		__dump_hex((unsigned char *)buf, mv_rq_bf_l(scmd));

+		MV_DBG(DMSG_SCSI, "-- inquiry dump ends -- \n");

+		kunmap_atomic(buf, KM_IRQ0);

+		break;

+	default:

+		lba = 0;

+		break;

+	} 

+#if 0

+	MV_DBG(DMSG_FREQ,

+	       "(%u) req "RED("%p")

+	       " dev %d : cmd %2X : lba %lu - %lu : length %d.\n",

+	       id, preq, preq->Device_Id, preq->Cdb[0], lba,

+	       lba + preq->Data_Transfer_Length/512,

+	       preq->Data_Transfer_Length);

+#endif

+#endif

+

+}

+

+static void generate_sg_table(struct hba_extension *phba,

+			      struct scsi_cmnd *scmd,

+			      PMV_SG_Table sg_table)

+{

+	struct scatterlist *sg;

+	unsigned int sg_count = 0;

+	unsigned int length;

+	BUS_ADDRESS busaddr = 0;

+	int i;

+

+	//MV_DBG(DMSG_FREQ,"%s : in %s.\n", mv_product_name, __FUNCTION__);

+

+	if (mv_rq_bf_l(scmd) > (mv_scmd_host(scmd)->max_sectors << 9)) {

+		MV_DBG(DMSG_SCSI, "ERROR: request length exceeds "

+		       "the maximum alowed value.\n");

+	}

+	

+	if (0 == mv_rq_bf_l(scmd))

+		return ;

+

+	if (mv_use_sg(scmd)) {

+		MV_DBG(DMSG_SCSI_FREQ, "%s : map %d sg entries.\n",

+		       mv_product_name, mv_use_sg(scmd));

+

+

+		sg = (struct scatterlist *) mv_rq_bf(scmd);

+		if (MV_SCp(scmd)->mapped == 0){

+			#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)

+			sg_count = pci_map_sg(phba->dev,

+					      sg,

+					      mv_use_sg(scmd),

+						  scsi_to_pci_dma_dir(scmd->sc_data_direction));

+			#else

+				sg_count = scsi_dma_map(scmd);

+			#endif

+			if (sg_count != mv_use_sg(scmd)) {

+				MV_PRINT("WARNING sg_count(%d) != scmd->use_sg(%d)\n",

+					 (unsigned int) sg_count, mv_use_sg(scmd));

+			}

+			MV_SCp(scmd)->mapped = 1;

+		}

+		for (i = 0; i < sg_count; i++) {

+			busaddr = sg_dma_address(&sg[i]);

+			length = sg_dma_len(&sg[i]);

+	#ifdef MV_DEBUG

+			if(length > 4096)

+				MV_DPRINT(("Warning: sg[%i] length %d > 4096\n", i, length));

+	#endif

+			sgdt_append_pctx(sg_table,

+					 LO_BUSADDR(busaddr), 

+					 HI_BUSADDR(busaddr),

+					 length,

+					 sg + i);

+		}

+	} else {

+		MV_DBG(DMSG_SCSI_FREQ, "map kernel addr into bus addr.\n" );

+		if (MV_SCp(scmd)->mapped == 0) {

+			busaddr = dma_map_single(&phba->dev->dev,

+				      mv_rq_bf(scmd),

+				       mv_rq_bf_l(scmd),

+					   scsi_to_pci_dma_dir(scmd->sc_data_direction));

+			MV_SCp(scmd)->bus_address = busaddr;

+			MV_SCp(scmd)->mapped = 1;

+

+		}

+	#ifdef MV_DEBUG

+			if(mv_rq_bf_l(scmd) > 4096)

+				MV_DPRINT(("Warning: single sg request_bufflen %d > 4096\n", mv_rq_bf_l(scmd)));

+	#endif

+

+		sgdt_append_vp(sg_table, 

+			       mv_rq_bf(scmd),

+			       mv_rq_bf_l(scmd),

+			       LO_BUSADDR(busaddr), 

+			       HI_BUSADDR(busaddr));

+		

+	}

+}

+

+void mv_complete_request(struct hba_extension *phba,

+				struct scsi_cmnd *scmd,

+				PMV_Request pReq)

+{

+	PMV_Sense_Data  senseBuffer = (PMV_Sense_Data) scmd->sense_buffer;

+	

+	//MV_POKE();

+	__hba_dump_req_info(phba->desc->module_id, pReq);

+

+	if (mv_rq_bf_l(scmd)) {

+		MV_DBG(DMSG_SCSI_FREQ, "unmap %d bytes.\n", 

+		        mv_rq_bf_l(scmd));

+

+	if (MV_SCp(scmd)->mapped) {

+			if (mv_use_sg(scmd)) {

+				#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)

+				pci_unmap_sg(phba->dev,

+					     mv_rq_bf(scmd),

+					     mv_use_sg(scmd),

+					 	scsi_to_pci_dma_dir(scmd->sc_data_direction));

+				#else

+				scsi_dma_unmap(scmd);

+				#endif

+			} else {

+				dma_unmap_single(&(phba->dev->dev),

+						 MV_SCp(scmd)->bus_address,

+						 mv_rq_bf_l(scmd),

+				     	scsi_to_pci_dma_dir(scmd->sc_data_direction));

+			}

+		}

+	}

+

+	MV_DBG(DMSG_SCSI_FREQ,

+	       " pReq->Scsi_Status = %x pcmd = %p.\n", 

+	        pReq->Scsi_Status, scmd);

+

+#if 0//def MV_DEBUG

+	if((pReq->Scsi_Status != REQ_STATUS_SUCCESS) && (SCSI_IS_READ(pReq->Cdb[0]) || SCSI_IS_WRITE(pReq->Cdb[0])))

+		MV_DPRINT(( "Device %d pReq->Scsi_Status = %x cmd = 0x%x.\n", pReq->Device_Id, pReq->Scsi_Status, pReq->Cdb[0]));

+#endif

+

+	switch (pReq->Scsi_Status) {

+	case REQ_STATUS_SUCCESS:

+		scmd->result = 0x00;

+		break;

+	case REQ_STATUS_MEDIA_ERROR:

+		scmd->result = (DID_BAD_TARGET << 16);

+		break;

+	case REQ_STATUS_BUSY:

+		scmd->result = (DID_BUS_BUSY << 16);

+		break;

+	case REQ_STATUS_NO_DEVICE:

+		scmd->result = (DID_NO_CONNECT << 16);

+		break;

+	case REQ_STATUS_HAS_SENSE:

+		/* Sense buffer data is valid already. */

+		scmd->result  = (DRIVER_SENSE << 24) | (DID_OK << 16) | CONDITION_GOOD;

+		senseBuffer->Valid = 1;

+

+		MV_DBG(DMSG_SCSI, "MV Sense: response %x SK %s length %x "

+		       "ASC %x ASCQ %x.\n", ((MV_PU8) senseBuffer)[0],

+		       MV_DumpSenseKey(((MV_PU8) senseBuffer)[2]),

+		       ((MV_PU8) senseBuffer)[7],

+		       ((MV_PU8) senseBuffer)[12],

+		       ((MV_PU8) senseBuffer)[13]);

+		break;

+	default:

+		scmd->result = (DRIVER_INVALID | DID_ABORT) << 16;

+		break;

+	}

+

+	scmd->scsi_done(scmd);

+}

+

+#ifdef SUPPORT_ATA_POWER_MANAGEMENT

+static inline int is_ata_16_passthrough_for_pm(struct scsi_cmnd * scmd)

+{

+	switch(scmd->cmnd[0]){

+		case ATA_16:

+			switch(scmd->cmnd[14]){

+			/* exception*/

+			#ifndef SUPPORT_ATA_SECURITY_CMD

+				case ATA_CMD_IDENTIFY_ATA:

+					return 1;

+			#endif

+				case ATA_CMD_DEV_RESET:

+				case ATA_CMD_STANDBYNOW1:

+				case ATA_CMD_IDLEIMMEDIATE:

+				case ATA_CMD_STANDBY:

+				case ATA_CMD_IDLE :

+				case ATA_CMD_CHK_POWER:

+				case ATA_CMD_SLEEP:

+				case ATA_CMD_SMART:

+					if(scmd->sc_data_direction == DMA_NONE &&

+						scmd->cmnd[4] != 0xd4)

+						return 1;

+					else

+						return 0;

+				default:

+					return 0;

+			}

+		default:

+			break;

+	}

+	return 0;

+}

+

+static void mv_pm_ata_16_complete_request(struct hba_extension * phba,

+		struct scsi_cmnd *scmd,PMV_Request pReq)

+{

+	PDomain_Device pDevice = NULL;

+	MV_U8 portId, deviceId; /*, temp;*/

+	PCore_Driver_Extension pCore; 

+

+	unsigned char *sb = scmd->sense_buffer;

+	unsigned char *desc = sb + 8;

+

+	pCore = (PCore_Driver_Extension)HBA_GetModuleExtension(phba, MODULE_CORE);

+

+	if ( pReq->Device_Id != VIRTUAL_DEVICE_ID )

+	{

+		portId = PATA_MapPortId(pReq->Device_Id);

+		deviceId = PATA_MapDeviceId(pReq->Device_Id);

+		if ( portId < MAX_PORT_NUMBER )				

+			pDevice = &pCore->Ports[portId].Device[deviceId];

+	}

+

+/* !DMA_NONE */

+	if (MV_SCp(scmd)->mapped) {

+		if (mv_use_sg(scmd)){

+			

+			#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)

+			pci_unmap_sg(phba->dev,mv_rq_bf(scmd),mv_use_sg(scmd),

+					 	scsi_to_pci_dma_dir(scmd->sc_data_direction));

+			#else

+			scsi_dma_unmap(scmd);

+			#endif

+		}

+		else 

+			dma_unmap_single(&(phba->dev->dev),MV_SCp(scmd)->bus_address,

+						mv_rq_bf_l(scmd),scsi_to_pci_dma_dir(scmd->sc_data_direction));

+	}

+	

+

+	memset(sb,0,SCSI_SENSE_BUFFERSIZE);

+	scmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; 

+

+	switch(scmd->cmnd[14]) {

+		case ATA_CMD_CHK_POWER:

+			if(!(pDevice->Status & DEVICE_STATUS_SLEEP))

+				desc[5] = 0xff;

+			if(pDevice->Status & DEVICE_STATUS_STANDBY)

+				desc[5] = 0x0;

+			if((pDevice->Status & DEVICE_STATUS_IDLE))

+				desc[5] = 0xff;

+			break;

+		case ATA_CMD_STANDBYNOW1:

+			pDevice->Status |= DEVICE_STATUS_STANDBY;

+			break;

+		case ATA_CMD_IDLEIMMEDIATE:

+			pDevice->Status |= DEVICE_STATUS_IDLE;

+			break;

+		case ATA_CMD_SLEEP:

+			pDevice->Status |= DEVICE_STATUS_SLEEP;

+			break;

+			

+		default:

+			break;

+	}

+	

+	/* Sense Data is current and format is descriptor */

+	sb[0] = 0x72;

+	desc[0] = 0x09;

+	

+	/* set length of additional sense data */

+	sb[7] = 14; // 8+14

+

+	desc[1] = 12;

+	desc[2] = 0x00;

+	desc[3] = 0; // error register

+

+	desc[13] = 0x50; // status register

+

+	if(scmd->cmnd[14] == ATA_CMD_SMART){

+		desc[9] = scmd->cmnd[10];

+		desc[10] = scmd->cmnd[11];

+		desc[11] = scmd->cmnd[12];

+	} else {

+		desc[12] = scmd->cmnd[13]; //NO_DATA

+	}

+

+	scmd->scsi_done(scmd);

+}

+#ifdef SUPPORT_ATA_SECURITY_CMD

+static void mv_ata_16_complete_request(struct hba_extension * phba,

+		struct scsi_cmnd *scmd,PMV_Request pReq)

+{

+	PDomain_Device pDevice = NULL;

+	MV_U8 portId, deviceId; /*, temp;*/

+	PCore_Driver_Extension pCore; 

+

+	unsigned char *sb = scmd->sense_buffer;

+	unsigned char *desc = sb + 8;

+

+	pCore = (PCore_Driver_Extension)HBA_GetModuleExtension(phba, MODULE_CORE);

+

+	if ( pReq->Device_Id != VIRTUAL_DEVICE_ID )

+	{

+		portId = PATA_MapPortId(pReq->Device_Id);

+		deviceId = PATA_MapDeviceId(pReq->Device_Id);

+		if ( portId < MAX_PORT_NUMBER )				

+			pDevice = &pCore->Ports[portId].Device[deviceId];

+	}

+	

+	if (MV_SCp(scmd)->mapped) {

+		if (mv_use_sg(scmd)){

+			

+			#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)

+			pci_unmap_sg(phba->dev,mv_rq_bf(scmd),mv_use_sg(scmd),

+					 	scsi_to_pci_dma_dir(scmd->sc_data_direction));

+			#else

+			scsi_dma_unmap(scmd);

+			#endif

+		}

+		else 

+			dma_unmap_single(&(phba->dev->dev),MV_SCp(scmd)->bus_address,

+						mv_rq_bf_l(scmd),scsi_to_pci_dma_dir(scmd->sc_data_direction));

+	}

+	

+	memset(sb,0,SCSI_SENSE_BUFFERSIZE);

+	scmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; 

+	

+	/* Sense Data is current and format is descriptor */

+	sb[0] = 0x72;

+	sb[1]=0x0;

+	desc[0] = 0x09;

+	/* set length of additional sense data */

+	sb[7] = 14; // 8+14

+

+	desc[1] = 12;

+	desc[2] = 0x00;

+	desc[3] = 0; 		// error register

+	desc[13] = 0x04; 	// status register

+	

+	if(scmd->cmnd[14] == ATA_CMD_SMART){

+		desc[9] = scmd->cmnd[10];

+		desc[10] = scmd->cmnd[11];

+		desc[11] = scmd->cmnd[12];

+	} else {

+		desc[12] = scmd->cmnd[13]; //NO_DATA

+	}

+	switch(scmd->cmnd[14]) {

+		case ATA_CMD_SEC_UNLOCK:

+		case ATA_CMD_SEC_ERASE_UNIT:

+			if(pReq->Scsi_Status==REQ_STATUS_SUCCESS){

+				if(pDevice->Capacity & DEVICE_CAPACITY_SECURITY_SUPPORTED){

+					if(pDevice->Setting & DEVICE_SETTING_SECURITY_LOCKED){

+						MV_DPRINT(("securiy: unlocked\n"));

+						pDevice->Setting &= ~DEVICE_SETTING_SECURITY_LOCKED;

+						}

+					}

+			}	

+			break;

+		case ATA_CMD_IDENTIFY_ATA:

+			sb[3]=0x1d;

+			break;

+		case ATA_CMD_SEC_PASSWORD:

+		case ATA_CMD_SEC_DISABLE_PASSWORD:

+		case ATA_CMD_SEC_ERASE_PRE:

+		default:

+			break;

+	}

+	switch(pReq->Scsi_Status) {

+		case REQ_STATUS_ABORT:

+			sb[1]=SCSI_SK_ABORTED_COMMAND;

+			desc[3]=0x04;

+			desc[13]=0x51;

+			break;

+		default:

+			break;

+		}

+	scmd->scsi_done(scmd);

+}

+#endif

+void mv_clear_device_status(struct hba_extension * phba,PMV_Request pReq)

+{

+	PDomain_Device pDevice = NULL;

+	MV_U8 portId, deviceId; /*, temp;*/

+	PCore_Driver_Extension pCore; 

+

+	pCore = (PCore_Driver_Extension)HBA_GetModuleExtension(phba, MODULE_CORE);

+

+	if ( pReq->Device_Id != VIRTUAL_DEVICE_ID )

+	{

+		portId = PATA_MapPortId(pReq->Device_Id);

+		deviceId = PATA_MapDeviceId(pReq->Device_Id);

+		if ( portId < MAX_PORT_NUMBER )				

+			pDevice = &pCore->Ports[portId].Device[deviceId];

+		pDevice->Status &= ~(DEVICE_STATUS_IDLE|DEVICE_STATUS_STANDBY);

+	}

+	return ;

+}

+

+#endif

+/* This should be the _only_ os request exit point. */

+static void hba_req_callback(MV_PVOID This, PMV_Request pReq)

+{

+	struct hba_extension *phba = (struct hba_extension *)This;

+	struct scsi_cmnd *scmd = (struct scsi_cmnd *)pReq->Org_Req;

+

+	/* Return this request to OS. */

+#ifdef SUPPORT_ATA_POWER_MANAGEMENT

+	if(is_ata_16_passthrough_for_pm(scmd) && 

+		pReq->Scsi_Status == REQ_STATUS_SUCCESS)

+			mv_pm_ata_16_complete_request(phba,scmd,pReq);

+#endif

+#ifdef SUPPORT_ATA_SECURITY_CMD

+	else if(scmd->cmnd[0]==ATA_16){

+		mv_ata_16_complete_request(phba,scmd,pReq);

+		}

+#endif

+#ifdef SUPPORT_ATA_POWER_MANAGEMENT

+	else{

+		mv_clear_device_status(phba,pReq);

+#endif

+		mv_complete_request(phba, scmd, pReq);

+#ifdef SUPPORT_ATA_POWER_MANAGEMENT

+	}

+#endif

+	phba->Io_Count--;

+	res_free_req_to_pool(phba->req_pool, pReq);

+}

+

+

+static int scsi_cmd_to_req_conv(struct hba_extension *phba, 

+				struct scsi_cmnd *scmd, 

+				PMV_Request pReq)

+{

+	/*

+	 * Set three flags: CMD_FLAG_NON_DATA 

+	 *                  CMD_FLAG_DATA_IN 

+	 *                  CMD_FLAG_DMA

+	 * currently data in/out all go thru DMA

+	 */

+	pReq->Cmd_Flag = 0;

+	switch (scmd->sc_data_direction) {

+	case DMA_NONE:

+		pReq->Cmd_Flag |= CMD_FLAG_NON_DATA;

+		break;

+	case DMA_FROM_DEVICE:

+		pReq->Cmd_Flag |= CMD_FLAG_DATA_IN;

+	case DMA_TO_DEVICE:

+		pReq->Cmd_Flag |= CMD_FLAG_DMA;

+		break;

+	case DMA_BIDIRECTIONAL : 

+		MV_DBG(DMSG_SCSI, "unexpected DMA_BIDIRECTIONAL.\n"

+		       );

+		break;

+	default:

+		break;

+	}

+

+	/* handling of specific cmds */

+	memset(pReq->Cdb, 0, MAX_CDB_SIZE);

+	switch (scmd->cmnd[0]){

+#if 0

+	case MODE_SELECT:

+		pReq->Cdb[0] = MODE_SELECT_10;

+		pReq->Cdb[1] = scmd->cmnd[1];

+		pReq->Cdb[8] = scmd->cmnd[4];

+		break;

+#endif

+	case READ_6:

+		pReq->Cdb[0] = READ_10;

+		pReq->Cdb[3] = scmd->cmnd[1]&0x1f;

+		pReq->Cdb[4] = scmd->cmnd[2];

+		pReq->Cdb[5] = scmd->cmnd[3];

+		pReq->Cdb[8] = scmd->cmnd[4];

+		pReq->Cdb[9] = scmd->cmnd[5];

+		break;

+

+	case WRITE_6:

+		pReq->Cdb[0] = WRITE_10;

+		pReq->Cdb[3] = scmd->cmnd[1]&0x1f;

+		pReq->Cdb[4] = scmd->cmnd[2];

+		pReq->Cdb[5] = scmd->cmnd[3];

+		pReq->Cdb[8] = scmd->cmnd[4];

+		pReq->Cdb[9] = scmd->cmnd[5];

+		break;

+	/*0xA1==SCSI_CMD_BLANK== ATA_12 */

+	case 0xA1:

+		if(IS_ATA_12_CMD(scmd))

+			pReq->Cmd_Flag |= CMD_FLAG_SMART_ATA_12;

+		else{

+			memcpy(pReq->Cdb, scmd->cmnd, MAX_CDB_SIZE);

+			break;

+		}

+	case ATA_16:

+		pReq->Cmd_Flag |= CMD_FLAG_SMART_ATA_16;

+		

+		pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;

+		pReq->Cdb[1] = CDB_CORE_MODULE;

+

+		memcpy(&pReq->Cdb[3],&scmd->cmnd[3],13);

+

+		switch(scmd->cmnd[ (pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?9 : 14])

+		{

+		#ifdef SUPPORT_ATA_POWER_MANAGEMENT

+			case 0x08:

+				pReq->Cdb[2] = CDB_CORE_RESET_DEVICE;

+				break;

+			case 0xE0:

+				pReq->Cdb[2] = CDB_CORE_ATA_STANDBY_IMMEDIATE;

+				break;

+			case 0xE1:

+				pReq->Cdb[2] = CDB_CORE_ATA_IDLE_IMMEDIATE;

+				break;

+			case 0xE2:

+				pReq->Cdb[2] = CDB_CORE_ATA_STANDBY;

+				break;

+			case 0xE3:

+				pReq->Cdb[2] = CDB_CORE_ATA_IDLE;

+				break;

+			case 0xE5:

+				pReq->Cdb[2] = CDB_CORE_ATA_CHECK_POWER_MODE;

+				break;

+			case 0xE6:

+				pReq->Cdb[2] = CDB_CORE_ATA_SLEEP;

+				break;

+		#endif

+			case 0xEC:

+				pReq->Cdb[2] = CDB_CORE_ATA_IDENTIFY;

+				break;

+		#ifdef SUPPORT_ATA_SMART

+			case ATA_IDENTIFY_PACKET_DEVICE:

+				pReq->Cdb[2] = CDB_CORE_ATA_IDENTIFY_PACKET_DEVICE;

+				break;

+			case ATA_SMART_CMD :

+				switch(scmd->cmnd[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?3 : 4])

+				{

+					case ATA_SMART_ENABLE:

+						pReq->Cdb[2] = CDB_CORE_ENABLE_SMART;

+						break;

+					case ATA_SMART_DISABLE:

+						pReq->Cdb[2] = CDB_CORE_DISABLE_SMART;

+						break;

+					case ATA_SMART_STATUS:

+						pReq->Cdb[2] = CDB_CORE_SMART_RETURN_STATUS;

+						break;

+					case ATA_SMART_READ_VALUES:

+						pReq->Cdb[2] = CDB_CORE_ATA_SMART_READ_VALUES;

+						break;

+					case ATA_SMART_READ_THRESHOLDS:

+						pReq->Cdb[2] = CDB_CORE_ATA_SMART_READ_THRESHOLDS;

+						break;

+					case  ATA_SMART_READ_LOG_SECTOR:

+						pReq->Cdb[2] = CDB_CORE_ATA_SMART_READ_LOG_SECTOR;

+						break;

+					case ATA_SMART_WRITE_LOG_SECTOR:

+						pReq->Cdb[2] = CDB_CORE_ATA_SMART_WRITE_LOG_SECTOR;

+						break;

+					case  ATA_SMART_AUTO_OFFLINE:

+						pReq->Cdb[2] = CDB_CORE_ATA_SMART_AUTO_OFFLINE;

+						break;

+					case  ATA_SMART_AUTOSAVE:

+						pReq->Cdb[2] = CDB_CORE_ATA_SMART_AUTOSAVE;

+						break;	

+					case  ATA_SMART_IMMEDIATE_OFFLINE:

+						pReq->Cdb[2] = CDB_CORE_ATA_SMART_IMMEDIATE_OFFLINE;

+						break;	

+					default:

+						pReq->Scsi_Status   =REQ_STATUS_INVALID_PARAMETER;

+						MV_PRINT("Unsupported ATA-12 or 16  subcommand =0x%x\n", \

+						scmd->cmnd[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?3 : 4]);

+						return -1;

+				}

+				break;

+			case 0xef:

+				switch(scmd->cmnd[4]){

+					case 0x2:

+						pReq->Cdb[2]=CDB_CORE_ENABLE_WRITE_CACHE ;

+					break;

+					case 0x82:

+						pReq->Cdb[2]=CDB_CORE_DISABLE_WRITE_CACHE;

+					break;

+					default:

+					pReq->Scsi_Status   =REQ_STATUS_INVALID_PARAMETER;

+					MV_PRINT("Enable/Disable Write Cache command error: parameter error:%d\n",scmd->cmnd[4]);

+					return -1;

+				}

+			break;

+		#endif /*#ifdef SUPPORT_ATA_SMART*/

+		#ifdef SUPPORT_ATA_SECURITY_CMD

+			case ATA_CMD_SEC_PASSWORD:	

+			case ATA_CMD_SEC_UNLOCK:

+					if(0){

+						int i;

+						char *buf=NULL;

+						for(i=0;i<16;i++)

+							printk(" %d:%x ",i,scmd->cmnd[i]);

+						printk("\n");

+						buf=NULL;

+						buf=bio_data(scmd->request->bio);

+						if(buf){

+							printk("bio=");

+							for(i=0;i<16;i++)

+							printk(" %x ",buf[i]);

+							printk("\n");

+							} else

+							printk("bio is NULL\n");

+					}

+			case ATA_CMD_SEC_ERASE_PRE:

+			case ATA_CMD_SEC_ERASE_UNIT:

+			case ATA_CMD_SEC_FREEZE_LOCK:

+			case ATA_CMD_SEC_DISABLE_PASSWORD:

+				pReq->Cmd_Flag &= ~CMD_FLAG_SMART_ATA_16;

+				memcpy(&pReq->Cdb[0],&scmd->cmnd[0],16);

+				break;

+			#endif

+			default:

+				pReq->Scsi_Status   =REQ_STATUS_INVALID_PARAMETER;

+				MV_PRINT("Unsupported ATA-12 or 16 Command=0x%x\n",\

+				scmd->cmnd[(pReq->Cmd_Flag & CMD_FLAG_SMART_ATA_12) ?9 : 14]);

+				return -1;

+		}

+		break;

+	default:

+		memcpy(pReq->Cdb, scmd->cmnd, MAX_CDB_SIZE);

+		break;

+	}

+	

+	pReq->Data_Buffer = mv_rq_bf(scmd);

+	pReq->Data_Transfer_Length = mv_rq_bf_l(scmd);

+	pReq->Sense_Info_Buffer = scmd->sense_buffer;

+	pReq->Sense_Info_Buffer_Length = SCSI_SENSE_BUFFERSIZE;

+

+	SGTable_Init(&pReq->SG_Table, 0);

+	generate_sg_table(phba, scmd, &pReq->SG_Table);

+

+	pReq->LBA.value = 0;

+	pReq->Sector_Count = 0;

+	MV_SetLBAandSectorCount(pReq);

+

+	pReq->Req_Type      = REQ_TYPE_OS;

+	pReq->Org_Req       = scmd;

+	pReq->Tag           = scmd->tag;

+	pReq->Scsi_Status   = REQ_STATUS_PENDING;

+	pReq->Completion    = hba_req_callback;

+	pReq->Cmd_Initiator = phba;

+	//pReq->Scsi_Status   = REQ_STATUS_INVALID_REQUEST;

+	pReq->Device_Id     = __MAKE_DEV_ID(mv_scmd_target(scmd),

+					    mv_scmd_lun(scmd));

+

+	return 0;

+}

+static void hba_shutdown_req_cb(MV_PVOID this, PMV_Request req)

+{

+	struct hba_extension *phba = (struct hba_extension *) this;

+	#ifdef SUPPORT_REQUEST_TIMER

+	if(req!=NULL)

+	{

+		MV_DBG(DMSG_HBA,"Shutdown HBA timer!\n");

+		hba_remove_timer_sync(req);

+	}

+	#endif

+	res_free_req_to_pool(phba->req_pool, req);

+	phba->Io_Count--;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_set(&phba->hba_sync, 0);

+#else

+	complete(&phba->cmpl);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+}

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+/* will wait for atomic value atomic to become zero until timed out */

+/* return how much 'timeout' is left or 0 if already timed out */

+int __hba_wait_for_atomic_timeout(atomic_t *atomic, unsigned long timeout)

+{

+	unsigned intv = HZ/20; 

+

+	while (timeout) {

+		if (0 == atomic_read(atomic))

+			break;

+

+		if (timeout < intv)

+			intv = timeout;

+		set_current_state(TASK_INTERRUPTIBLE);

+		timeout -= (intv - schedule_timeout(intv));

+	}

+	return timeout;

+}

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+

+#ifdef CACHE_MODULE_SUPPORT

+static void _hba_send_shutdown_req(PHBA_Extension phba)

+{

+	unsigned long flags;

+	PMV_Request pReq;

+

+	/*Send MV_REQUEST to do something.*/	

+	pReq = res_get_req_from_pool(phba->req_pool);

+	if (NULL == pReq) {

+		MV_PRINT("cannot allocate memory for req.\n"

+		       );

+		return;

+	}

+

+	pReq->Cmd_Initiator = phba;

+	pReq->Org_Req = NULL;

+	pReq->Completion = hba_shutdown_req_cb;

+	pReq->Req_Type = REQ_TYPE_OS;

+	pReq->Cmd_Flag = 0;

+	pReq->Cmd_Flag |= CMD_FLAG_NON_DATA;

+	pReq->Sense_Info_Buffer_Length = 0;  

+	pReq->Data_Transfer_Length = 0;

+	pReq->Data_Buffer = NULL;

+	pReq->Sense_Info_Buffer = NULL;

+

+	pReq->LBA.value = 0;

+	pReq->Sector_Count = 0;

+

+	pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+

+	SGTable_Init(&pReq->SG_Table, 0);

+	memset(pReq->Context, 0, sizeof(MV_PVOID) * MAX_POSSIBLE_MODULE_NUMBER);

+

+	MV_DPRINT(("send SHUTDOWN request to CACHE.\n"));

+	pReq->Cdb[0] = APICDB0_ADAPTER;

+	pReq->Cdb[1] = APICDB1_ADAPTER_POWER_STATE_CHANGE;

+	pReq->Cdb[2] = 0;

+

+	spin_lock_irqsave(&phba->desc->hba_desc->global_lock, flags);

+	phba->Io_Count++;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_set(&phba->hba_sync, 1);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+	phba->desc->ops->module_sendrequest(phba->desc->extension, pReq);

+	spin_unlock_irqrestore(&phba->desc->hba_desc->global_lock, flags);

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	__hba_wait_for_atomic_timeout(&phba->hba_sync, 10*HZ);

+#else

+	wait_for_completion_timeout(&phba->cmpl, 10*HZ);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+}

+#endif /* CACHE_MODULE_SUPPORT */

+

+void hba_send_shutdown_req(struct hba_extension *phba)

+{

+	unsigned long flags;

+	PMV_Request pReq;

+#ifdef CACHE_MODULE_SUPPORT

+	_hba_send_shutdown_req(phba);

+#endif

+	

+	pReq = res_get_req_from_pool(phba->req_pool);

+	if (NULL == pReq) {

+		MV_PRINT("cannot allocate memory for req.\n");

+		return;

+	}

+

+	pReq->Cmd_Initiator = phba;

+	pReq->Org_Req = pReq;

+	pReq->Req_Type = REQ_TYPE_INTERNAL;

+	pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST;

+	pReq->Completion = hba_shutdown_req_cb;

+	

+#ifdef RAID_DRIVER

+	pReq->Cdb[0] = APICDB0_LD;

+	pReq->Cdb[1] = APICDB1_LD_SHUTDOWN;

+#else

+	pReq->Device_Id = 0;

+	pReq->Cmd_Flag = 0;

+	pReq->Cmd_Flag |= CMD_FLAG_NON_DATA;

+	pReq->Sense_Info_Buffer_Length = 0;  

+	pReq->Data_Transfer_Length = 0;

+	pReq->Data_Buffer = NULL;

+	pReq->Sense_Info_Buffer = NULL;

+	SGTable_Init(&pReq->SG_Table, 0);

+	pReq->Cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;

+	pReq->Cdb[1] = CDB_CORE_MODULE;

+	pReq->Cdb[2] = CDB_CORE_SHUTDOWN;

+	pReq->LBA.value = 0;

+	pReq->Sector_Count = 0;

+	pReq->Scsi_Status = REQ_STATUS_PENDING;

+#endif

+

+	spin_lock_irqsave(&phba->desc->hba_desc->global_lock, flags);

+	phba->Io_Count++;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_set(&phba->hba_sync, 1);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+	phba->desc->ops->module_sendrequest(phba->desc->extension, pReq);

+	spin_unlock_irqrestore(&phba->desc->hba_desc->global_lock, flags);

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	__hba_wait_for_atomic_timeout(&phba->hba_sync, 10*HZ);

+#else

+	wait_for_completion_timeout(&phba->cmpl, 10*HZ);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+}

+

+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 7)

+/*openSUSE 11.1 SLES 11 SLED 11*/

+#if ((LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 27))&&(IS_OPENSUSE_SLED_SLES))

+static enum blk_eh_timer_return mv_linux_timed_out(struct scsi_cmnd *cmd)

+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)

+static enum scsi_eh_timer_return mv_linux_timed_out(struct scsi_cmnd *cmd)

+#else

+static enum blk_eh_timer_return mv_linux_timed_out(struct scsi_cmnd *cmd)

+#endif

+{

+	MV_BOOLEAN ret = MV_TRUE;

+#if ((LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 27))&&(IS_OPENSUSE_SLED_SLES))

+	return (ret)?BLK_EH_RESET_TIMER:BLK_EH_NOT_HANDLED;

+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)

+	return (ret)?EH_RESET_TIMER:EH_NOT_HANDLED;

+#else

+	return (ret)?BLK_EH_RESET_TIMER:BLK_EH_NOT_HANDLED;

+#endif

+}

+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 7) */

+

+static inline struct mv_mod_desc *

+__get_lowest_module(struct mv_adp_desc *hba_desc)

+{

+	struct mv_mod_desc *p;

+	

+	/* take a random module, and trace through its child */

+	p = list_entry(hba_desc->online_module_list.next, 

+		       struct mv_mod_desc,

+		       mod_entry);

+

+	WARN_ON(NULL == p);

+	while (p) {

+		if (NULL == p->child)

+			break;

+		p = p->child;

+	}

+	return p;

+}

+

+static int mv_linux_queue_command(struct scsi_cmnd *scmd, 

+				  void (*done) (struct scsi_cmnd *))

+{

+	struct Scsi_Host *host = mv_scmd_host(scmd);

+	struct hba_extension *hba = *((struct hba_extension * *) host->hostdata);

+	PMV_Request req;

+	unsigned long flags;

+

+	if (done == NULL) {

+		MV_PRINT( ": in queuecommand, done function can't be NULL\n");

+		return 0;

+    	}

+

+

+#if 1

+	MV_DBG(DMSG_SCSI_FREQ,

+	       "mv_linux_queue_command %p (%d/%d/%d/%d \

+	       Cdb=(%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x))\n", 

+	       scmd, host->host_no, mv_scmd_channel(scmd), 

+	       mv_scmd_target(scmd), mv_scmd_lun(scmd),

+	       *(scmd->cmnd), *(scmd->cmnd+1), 

+	       *(scmd->cmnd+2), *(scmd->cmnd+3), 

+	        *(scmd->cmnd+4), *(scmd->cmnd+5), 

+	        *(scmd->cmnd+6), *(scmd->cmnd+7), 

+	        *(scmd->cmnd+8), *(scmd->cmnd+9), 

+	        *(scmd->cmnd+10), *(scmd->cmnd+11), 

+	        *(scmd->cmnd+12), *(scmd->cmnd+13), 

+	        *(scmd->cmnd+14),*(scmd->cmnd+15));

+#endif

+	scmd->result = 0;

+ 	scmd->scsi_done = done;

+	MV_SCp(scmd)->bus_address = 0;

+	MV_SCp(scmd)->mapped = 0;

+	MV_SCp(scmd)->map_atomic = 0;

+

+#ifdef COMMAND_ISSUE_WORKROUND

+{

+	MV_U8 mv_core_check_is_reseeting(MV_PVOID core_ext);

+	struct mv_mod_desc *core_desc=__get_lowest_module(hba->desc->hba_desc);

+	if(mv_core_check_is_reseeting(core_desc->extension)){

+		//MV_DPRINT(("HOST is resetting, wait..\n"));

+		return SCSI_MLQUEUE_HOST_BUSY;

+	}

+

+}

+#endif

+	if (mv_scmd_channel(scmd)) {

+		scmd->result = DID_BAD_TARGET << 16;

+		goto done;

+	}

+

+	/* 

+	 * Get mv_request resource and translate the scsi_cmnd request 

+	 * to mv_request.

+	 */

+	req = res_get_req_from_pool(hba->req_pool);

+	if (req == NULL)

+	{

+		MV_DPRINT(("No sufficient request.\n"));

+		return SCSI_MLQUEUE_HOST_BUSY;

+	}

+	if (scsi_cmd_to_req_conv(hba, scmd, req)) {

+		struct scsi_cmnd *cmd = (struct scsi_cmnd *)req->Org_Req;

+		/* 

+		 * Even TranslateOSRequest failed, 

+		 * it still should set some of the variables to the MV_Request

+		 * especially MV_Request.Org_Req and MV_Request.Scsi_Status;

+		 */

+		if(!cmd || req->Scsi_Status==REQ_STATUS_INVALID_PARAMETER){

+			res_free_req_to_pool(hba->req_pool, req);

+			//scmd->result = (DRIVER_INVALID | SUGGEST_ABORT) << 24;

+			scmd->result |= DID_ABORT << 16;

+			scmd->scsi_done(scmd);

+			return 0;			

+		}	

+		MV_DBG(DMSG_HBA,

+		       "ERROR - Translation from OS Request failed.\n");

+		hba_req_callback(hba, req);

+		return 0;

+	}

+

+	spin_lock_irqsave(&hba->desc->hba_desc->global_lock, flags);

+	hba->Io_Count++;

+

+	if (hba->State != DRIVER_STATUS_STARTED) {

+		MV_ASSERT(0);

+		/*if ( hba->State==DRIVER_STATUS_IDLE )

+		  {

+		  hba->State = DRIVER_STATUS_STARTING;

+		  Module_StartAll(module_manage, MODULE_CORE);

+		  }*/

+	} else {

+		hba->desc->ops->module_sendrequest(hba->desc->extension, req);

+	}

+	spin_unlock_irqrestore(&hba->desc->hba_desc->global_lock, flags);

+

+	return 0;

+done:

+        scmd->scsi_done(scmd);

+        return 0;

+}

+

+#if 0

+static int mv_linux_abort(struct scsi_cmnd *cmd)

+{

+	struct Scsi_Host *host;

+	struct hba_extension *phba;

+	int  ret = FAILED;

+

+	MV_PRINT("__MV__ abort command %p.\n", cmd);

+

+	return ret;

+}

+#endif /* 0 */

+#ifdef IOCTL_TEMPLATE

+/****************************************************************

+*  Name:   mv_ial_ht_ata_cmd

+*

+*  Description:    handles mv_sata ata IOCTL special drive command (HDIO_DRIVE_CMD)

+*

+*  Parameters:     scsidev - Device to which we are issuing command

+*                  arg     - User provided data for issuing command

+*

+*  Returns:        0 on success, otherwise of failure.

+*

+****************************************************************/

+static int mv_ial_ht_ata_cmd(struct scsi_device *scsidev, void __user *arg)

+{

+	int rc = 0;

+     	u8 scsi_cmd[MAX_COMMAND_SIZE];

+      	u8 args[4] , *argbuf = NULL, *sensebuf = NULL;

+      	int argsize = 0;

+      	enum dma_data_direction data_dir;

+      	int cmd_result;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+	struct scsi_request *sreq;

+#endif

+      	if (arg == NULL)

+          	return -EINVAL;

+  

+      	if (copy_from_user(args, arg, sizeof(args)))

+          	return -EFAULT;

+      	

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+	sensebuf = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);

+	if (sensebuf) {

+		memset(sensebuf, 0, SCSI_SENSE_BUFFERSIZE);

+	}

+#else

+	sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);

+#endif 

+

+      	if (!sensebuf)

+          	return -ENOMEM;

+  

+      	memset(scsi_cmd, 0, sizeof(scsi_cmd));

+      	if (args[3]) {

+          	argsize = SECTOR_SIZE * args[3];

+          	argbuf = kmalloc(argsize, GFP_KERNEL);

+          	if (argbuf == NULL) {

+              		rc = -ENOMEM;

+              		goto error;

+     	}

+  

+     	scsi_cmd[1]  = (4 << 1); /* PIO Data-in */

+     	scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,

+                                             block count in sector count field */

+      	data_dir = DMA_FROM_DEVICE;

+      	} else {

+       		scsi_cmd[1]  = (3 << 1); /* Non-data */

+       		scsi_cmd[2]  = 0x20;     /* cc but no off.line or data xfer */

+      		data_dir = DMA_NONE;

+	}

+  

+	scsi_cmd[0] = ATA_16;

+  

+   	scsi_cmd[4] = args[2];

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)

+    	if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */

+#else

+	if (args[0] == ATA_CMD_SMART) { /* hack -- ide driver does this too... */	

+#endif	

+        	scsi_cmd[6]  = args[3];

+       		scsi_cmd[8]  = args[1];

+     		scsi_cmd[10] = 0x4f;

+    		scsi_cmd[12] = 0xc2;

+      	} else {

+          	scsi_cmd[6]  = args[1];

+      	}

+      	scsi_cmd[14] = args[0];

+      	

+      	/* Good values for timeout and retries?  Values below

+         	from scsi_ioctl_send_command() for default case... */

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+	sreq = scsi_allocate_request(scsidev, GFP_KERNEL);

+	if (!sreq) {

+		rc= -EINTR;

+		goto free_req;

+	}

+	sreq->sr_data_direction = data_dir;

+	scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5);

+

+	/* 

+	 * If there was an error condition, pass the info back to the user. 

+	 */

+	cmd_result = sreq->sr_result;

+	sensebuf = sreq->sr_sense_buffer;

+   

+#elif LINUX_VERSION_CODE >=KERNEL_VERSION(2, 6, 29)

+      	cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,

+                                sensebuf, (10*HZ), 5, 0,0);

+#else

+      	cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,

+                                sensebuf, (10*HZ), 5, 0);

+#endif

+

+  

+      	if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */

+         	u8 *desc = sensebuf + 8;

+          	cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */

+  

+          	/* If we set cc then ATA pass-through will cause a

+          	* check condition even if no error. Filter that. */

+          	if (cmd_result & SAM_STAT_CHECK_CONDITION) {

+              	struct scsi_sense_hdr sshdr;

+              	scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,

+                                   &sshdr);

+              	if (sshdr.sense_key==0 &&

+                  	sshdr.asc==0 && sshdr.ascq==0)

+                  	cmd_result &= ~SAM_STAT_CHECK_CONDITION;

+          	}

+  

+          	/* Send userspace a few ATA registers (same as drivers/ide) */

+          	if (sensebuf[0] == 0x72 &&     /* format is "descriptor" */

+              		desc[0] == 0x09 ) {        /* code is "ATA Descriptor" */

+              		args[0] = desc[13];    /* status */

+              		args[1] = desc[3];     /* error */

+              		args[2] = desc[5];     /* sector count (0:7) */

+              		if (copy_to_user(arg, args, sizeof(args)))

+                  		rc = -EFAULT;

+          	}

+      	}

+  

+      	if (cmd_result) {

+          	rc = -EIO;

+          	goto free_req;

+      	}

+  

+      	if ((argbuf) && copy_to_user(arg + sizeof(args), argbuf, argsize))

+          	rc = -EFAULT;

+      	

+free_req:

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+	scsi_release_request(sreq);

+#endif		

+error:

+      	if (sensebuf) kfree(sensebuf);

+      	if (argbuf) kfree(argbuf);

+      	return rc;

+}

+

+#ifdef SUPPORT_ATA_SECURITY_CMD

+static int check_dma (__u8 ata_op)

+{

+	switch (ata_op) {

+		case ATA_CMD_READ_DMA_EXT:

+		case ATA_CMD_READ_FPDMA_QUEUED:

+		case ATA_CMD_WRITE_DMA_EXT:

+		case ATA_CMD_WRITE_FPDMA_QUEUED:

+		case ATA_CMD_READ_DMA:

+		case ATA_CMD_WRITE_DMA:

+			return SG_DMA;

+		default:

+			return SG_PIO;

+	}

+}

+unsigned char excute_taskfile(struct scsi_device *dev,ide_task_request_t *req_task,u8 

+ rw,char *argbuf,unsigned int buff_size)

+{

+	int rc = 0;

+     	u8 scsi_cmd[MAX_COMMAND_SIZE];

+      	u8 *sensebuf = NULL;

+      	int argsize=0;

+	enum dma_data_direction data_dir;

+      	int cmd_result;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+	struct scsi_request *sreq;

+#endif

+      	argsize=buff_size;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+	sensebuf = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);

+	if (sensebuf) {

+		memset(sensebuf, 0, SCSI_SENSE_BUFFERSIZE);

+	}

+#else

+	sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);

+#endif 

+      	if (!sensebuf)

+          	return -ENOMEM;

+  

+      	memset(scsi_cmd, 0, sizeof(scsi_cmd));

+

+  	data_dir = DMA_FROM_DEVICE;   // need to fixed

+	scsi_cmd[0] = ATA_16;

+	scsi_cmd[13] = 0x40;

+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)

+      	scsi_cmd[14] = ((task_struct_t *)(&req_task->io_ports))->command;

+#else

+	scsi_cmd[14] = ((char *)(&req_task->io_ports))[7];

+#endif

+	if(check_dma(scsi_cmd[14])){

+		scsi_cmd[1] = argbuf ? SG_ATA_PROTO_DMA : SG_ATA_PROTO_NON_DATA;

+	} else {

+		scsi_cmd[1] = argbuf ? (rw ? SG_ATA_PROTO_PIO_OUT : SG_ATA_PROTO_PIO_IN) : SG_ATA_PROTO_NON_DATA;

+	}

+	scsi_cmd[ 2] = SG_CDB2_CHECK_COND;

+	if (argbuf) {

+		scsi_cmd[2] |= SG_CDB2_TLEN_NSECT | SG_CDB2_TLEN_SECTORS;

+		scsi_cmd[2] |= rw ? SG_CDB2_TDIR_TO_DEV : SG_CDB2_TDIR_FROM_DEV;

+	}

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+	sreq = scsi_allocate_request(dev, GFP_KERNEL);

+	if (!sreq) {

+		rc= -EINTR;

+		goto free_req;

+	}

+	sreq->sr_data_direction = data_dir;

+	scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5);

+

+	/* 

+	 * If there was an error condition, pass the info back to the user. 

+	 */

+	cmd_result = sreq->sr_result;

+	sensebuf = sreq->sr_sense_buffer;

+   

+#elif LINUX_VERSION_CODE >=KERNEL_VERSION(2, 6, 29)

+      	cmd_result = scsi_execute(dev, scsi_cmd, data_dir, argbuf, argsize,

+                                sensebuf, (10*HZ), 5, 0,0);

+#else

+      	cmd_result = scsi_execute(dev, scsi_cmd, data_dir, argbuf, argsize,

+                                sensebuf, (10*HZ), 5, 0);

+#endif

+  

+      	if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */

+         	u8 *desc = sensebuf + 8;

+          	cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */

+  		

+          	/* If we set cc then ATA pass-through will cause a

+          	* check condition even if no error. Filter that. */

+          	if (cmd_result & SAM_STAT_CHECK_CONDITION) {

+              	struct scsi_sense_hdr sshdr;

+              	scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,

+                                   &sshdr);

+              	if (sshdr.sense_key==0 &&

+                  	sshdr.asc==0 && sshdr.ascq==0)

+                  	cmd_result &= ~SAM_STAT_CHECK_CONDITION;

+          	}

+  

+      	}

+  

+      	if (cmd_result) {

+          	rc = EIO;

+		MV_PRINT("EIO=%d\n",-EIO);

+          	goto free_req;

+      	}

+#if 0

+      	if ( copy_to_user(argbuf,sensebuf, argsize))

+       		rc = -EFAULT;

+#endif

+free_req:

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+	scsi_release_request(sreq);

+#endif		

+      	if (sensebuf) kfree(sensebuf);

+      	return rc;

+}

+u8 mv_do_taskfile_ioctl(struct scsi_device *dev,void __user *arg){

+	ide_task_request_t *req_task=NULL;

+	char __user *buf = (char __user *)arg;

+	u8 *outbuf	= NULL;

+	u8 *inbuf	= NULL;

+	int err		= 0;

+	int tasksize	= sizeof(ide_task_request_t);

+	int taskin	= 0;

+	int taskout	= 0;

+	int rw = SG_READ;

+	

+	req_task = kzalloc(tasksize, GFP_KERNEL);

+	if (req_task == NULL) return -ENOMEM;

+	if (copy_from_user(req_task, buf, tasksize)) {

+		kfree(req_task);

+		return -EFAULT;

+	}

+

+	switch (req_task->req_cmd) {

+		case TASKFILE_CMD_REQ_OUT:

+		case TASKFILE_CMD_REQ_RAW_OUT:

+			rw         = SG_WRITE;

+			break;

+		case TASKFILE_CMD_REQ_IN:

+			break;

+	}

+	taskout = (int) req_task->out_size;

+	taskin  = (int) req_task->in_size;

+

+

+	if (taskout) {

+		int outtotal = tasksize;

+		outbuf = kzalloc(taskout, GFP_KERNEL);

+		if (outbuf == NULL) {

+			err = -ENOMEM;

+			goto abort;

+		}

+		if (copy_from_user(outbuf, buf + outtotal, taskout)) {

+			err = -EFAULT;

+			goto abort;

+		}

+	}

+

+	if (taskin) {

+		int intotal = tasksize + taskout;

+		inbuf = kzalloc(taskin, GFP_KERNEL);

+		if (inbuf == NULL) {

+			err = -ENOMEM;

+			goto abort;

+		}

+		if (copy_from_user(inbuf, buf + intotal, taskin)) {

+			err = -EFAULT;

+			goto abort;

+		}

+	}

+	

+	switch(req_task->data_phase) {

+		case TASKFILE_DPHASE_PIO_OUT:

+			err=excute_taskfile(dev,req_task,rw,outbuf,taskout);

+		default:

+			err = -EFAULT;

+			goto abort;

+	}

+	if (copy_to_user(buf, req_task, tasksize)) {

+		err = -EFAULT;

+		goto abort;

+	}

+	if (taskout) {

+		int outtotal = tasksize;

+		if (copy_to_user(buf + outtotal, outbuf, taskout)) {

+			err = -EFAULT;

+			goto abort;

+		}

+	}

+	if (taskin) {

+		int intotal = tasksize + taskout;

+		if (copy_to_user(buf + intotal, inbuf, taskin)) {

+			err = -EFAULT;

+			goto abort;

+		}

+	}

+abort:

+	kfree(req_task);

+	kfree(outbuf);

+	kfree(inbuf);

+

+	return err;

+}

+#endif

+

+/****************************************************************

+ *  Name:   mv_ial_ht_ioctl

+ *

+ *  Description:    mv_sata scsi ioctl

+ *

+ *  Parameters:     scsidev - Device to which we are issuing command

+ *                  cmd     - ioctl command

+ *                  arg     - User provided data for issuing command

+ *

+ *  Returns:        0 on success, otherwise of failure.

+ *

+ ****************************************************************/

+static int mv_ial_ht_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)

+{

+     	int rc = -ENOTTY;

+ 

+     	/* No idea how this happens.... */

+     	if (!scsidev)

+         	return -ENXIO;

+ 

+     	if (arg == NULL)

+         	return -EINVAL;

+ 

+     	switch (cmd) {

+         	case HDIO_DRIVE_CMD:

+             		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))

+                 		return -EACCES;

+ 

+             		rc =  mv_ial_ht_ata_cmd(scsidev, arg);

+             	break;

+		#ifdef SUPPORT_ATA_SECURITY_CMD

+ 		case HDIO_DRIVE_TASKFILE:

+			rc=mv_do_taskfile_ioctl(scsidev,arg);

+			break;

+		#endif

+         	default:

+             		rc = -ENOTTY;

+     	}

+ 

+     	return rc;

+}

+#endif

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)

+static irqreturn_t mv_intr_handler(int irq, void *dev_id, struct pt_regs *regs)

+#else

+static irqreturn_t mv_intr_handler(int irq, void *dev_id)

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) */

+{

+	/* MV_FALSE should be equal to IRQ_NONE (0) */

+	irqreturn_t retval = MV_FALSE;

+	unsigned long flags;

+

+	struct hba_extension *hba = (struct hba_extension *) dev_id;

+	//MV_DBG(DMSG_FREQ, "__MV__ Enter intr handler.\n");

+	

+	spin_lock_irqsave(&hba->desc->hba_desc->global_lock, flags);

+	retval = hba->desc->child->ops->module_service_isr(hba->desc->child->extension);

+	#ifdef SUPPORT_TASKLET

+	if(retval)

+		tasklet_schedule(&hba->mv_tasklet);

+	#endif

+

+	spin_unlock_irqrestore(&hba->desc->hba_desc->global_lock, flags);

+

+	//MV_DBG(DMSG_FREQ, "__MV__ Exit intr handler retval=0x%x.\n ",retval);

+	return IRQ_RETVAL(retval);

+}

+

+static int mv_linux_reset (struct scsi_cmnd *cmd)

+{

+	MV_PRINT("__MV__ reset handler %p.\n", cmd);

+	return FAILED;

+}

+

+static struct scsi_host_template mv_driver_template = {

+	.module                      =  THIS_MODULE,

+        .name                        =  "Marvell Storage Controller",

+        .proc_name                   =  mv_driver_name,

+        .proc_info                   =  mv_linux_proc_info,

+        .queuecommand                =  mv_linux_queue_command,

+#ifdef IOCTL_TEMPLATE

+        .ioctl				= mv_ial_ht_ioctl,

+#endif

+#if 0

+        .eh_abort_handler            =  mv_linux_abort,

+        .eh_device_reset_handler     =  mv_linux_reset,

+        .eh_bus_reset_handler        =  mv_linux_reset,

+#endif /* 0 */

+        .eh_host_reset_handler       =  mv_linux_reset,

+#if  LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 7) && \

+     LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)

+        .eh_timed_out                =  mv_linux_timed_out,

+#endif

+        .can_queue                   =  MV_MAX_REQUEST_DEPTH,

+        .this_id                     =  MV_SHT_THIS_ID,

+        .max_sectors                 =  MV_MAX_TRANSFER_SECTOR,

+        .sg_tablesize                =  MV_MAX_SG_ENTRY,

+        .cmd_per_lun                 =  MV_MAX_REQUEST_PER_LUN,

+        .use_clustering              =  MV_SHT_USE_CLUSTERING,

+        .emulated                    =  MV_SHT_EMULATED,

+};

+

+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)

+static struct scsi_transport_template mv_transport_template = {

+	.eh_timed_out   =  mv_linux_timed_out,

+};

+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 16) */

+

+

+/* module management & hba module code */

+extern struct mv_module_ops *mv_core_register_module(void);

+extern struct mv_module_ops *mv_hba_register_module(void);

+

+#ifdef RAID_DRIVER

+extern struct mv_module_ops *mv_raid_register_module(void);

+#else

+static inline struct mv_module_ops *mv_raid_register_module(void)

+{

+	return NULL;

+}

+#endif /* RAID_DRIVER */

+

+#ifdef CACHE_MODULE_SUPPORT

+extern struct mv_module_ops *mv_cache_register_module(void);

+#else

+static inline struct mv_module_ops *mv_cache_register_module(void)

+{

+	return NULL;

+}

+#endif /* CACHE_DRIVER */

+

+static LIST_HEAD(mv_online_adapter_list);

+

+int __mv_get_adapter_count(void)

+{

+	struct mv_adp_desc *p;

+	int i = 0;

+	

+	list_for_each_entry(p, &mv_online_adapter_list, hba_entry)

+		i++;

+	

+	return i;

+}

+

+ inline struct mv_adp_desc *__dev_to_desc(struct pci_dev *dev)

+{

+	struct mv_adp_desc *p;

+	

+	list_for_each_entry(p, &mv_online_adapter_list, hba_entry)

+		if (p->dev == dev)

+			return p;

+	return NULL;

+}

+

+MV_PVOID *mv_get_hba_extension(struct mv_adp_desc *hba_desc)

+{

+	struct mv_mod_desc *p;

+

+	list_for_each_entry(p, &hba_desc->online_module_list, mod_entry)

+		if (MODULE_HBA == p->module_id)

+			return p->extension;

+	return NULL;

+}

+

+static inline void __mv_release_hba(struct mv_adp_desc *hba_desc)

+{

+	struct mv_mod_desc *mod_desc, *p;

+	

+	list_for_each_entry_safe(mod_desc, 

+				 p, 

+				 &hba_desc->online_module_list,

+				 mod_entry) {

+		list_del(&mod_desc->mod_entry);

+		vfree(mod_desc);

+	}

+	

+	list_del(&hba_desc->hba_entry);

+	vfree(hba_desc);

+}

+

+static struct mv_adp_desc *mv_hba_init_modmm(struct pci_dev *dev)

+{

+	struct mv_adp_desc *hba_desc;

+	

+	hba_desc = vmalloc(sizeof(struct mv_adp_desc));

+	if (NULL == hba_desc) {

+		printk("Unable to get memory at hba init.\n");

+		return NULL;

+	}

+	memset(hba_desc, 0, sizeof(struct mv_adp_desc));

+	

+	INIT_LIST_HEAD(&hba_desc->online_module_list);

+	hba_desc->dev = dev;

+	list_add(&hba_desc->hba_entry, &mv_online_adapter_list);

+	

+	return hba_desc;

+}

+

+static void mv_hba_release_modmm(struct pci_dev *dev)

+{

+	struct mv_adp_desc *hba_desc;

+	

+	hba_desc = __dev_to_desc(dev);

+	

+	if (hba_desc)

+		__mv_release_hba(hba_desc);

+	else

+		printk("Weired! dev %p unassociated with any desc.\n", dev);

+}

+

+static inline struct mv_mod_desc *__alloc_mod_desc(void)

+{

+	struct mv_mod_desc *desc;

+

+	desc = vmalloc(sizeof(struct mv_mod_desc));

+	if (desc)

+		memset(desc, 0, sizeof(struct mv_mod_desc));

+	return desc;

+}

+

+static int register_online_modules(struct mv_adp_desc *hba_desc)

+{

+	struct mv_mod_desc *mod_desc, *prev;

+	struct mv_module_ops *ops;

+	

+	/*

+	 * iterate through online_module_list manually , from the lowest(CORE)

+	 * to the highest layer (HBA)

+	 */

+	hba_desc->running_mod_num = 0;

+	/* CORE */

+	ops = mv_core_register_module();

+	if (NULL == ops) {

+		printk("No core no life.\n");

+		return -1;

+	}

+	mod_desc = __alloc_mod_desc();

+	if (NULL == mod_desc)

+		goto disaster;

+

+	mod_desc->hba_desc  = hba_desc;

+	mod_desc->ops       = ops;

+	mod_desc->status    = MV_MOD_REGISTERED;

+	mod_desc->module_id = MODULE_CORE;

+	mod_desc->child     = NULL;

+	list_add(&mod_desc->mod_entry, &hba_desc->online_module_list);

+	hba_desc->running_mod_num++;

+

+#ifdef ODIN_DRIVER

+	/* when running in non-RAID, both CACHE and RAID must be disabled */

+	if(!hba_desc->RunAsNonRAID)

+	{

+#endif

+

+#ifdef RAID_DRIVER

+	/* RAID */

+	ops = mv_raid_register_module();

+	if (ops) {

+		prev = mod_desc;

+		mod_desc = __alloc_mod_desc();

+		if (NULL == mod_desc)

+			goto disaster;

+

+		mod_desc->hba_desc  = hba_desc;

+		mod_desc->ops       = ops;

+		mod_desc->status    = MV_MOD_REGISTERED;

+		mod_desc->module_id = MODULE_RAID;

+		mod_desc->child     = prev;

+		prev->parent        = mod_desc;

+		list_add(&mod_desc->mod_entry, &hba_desc->online_module_list);

+		hba_desc->running_mod_num++;

+	}

+#endif

+

+#ifdef CACHE_MODULE_SUPPORT

+	/* CACHE */

+	ops = mv_cache_register_module();

+	if (ops) {

+		prev = mod_desc;

+		mod_desc = __alloc_mod_desc();

+		if (NULL == mod_desc)

+			goto disaster;

+		

+		mod_desc->hba_desc  = hba_desc;

+		mod_desc->ops       = ops;

+		mod_desc->status    = MV_MOD_REGISTERED;

+		mod_desc->module_id = MODULE_CACHE;

+		mod_desc->child     = prev;

+		prev->parent        = mod_desc;

+		list_add(&mod_desc->mod_entry, &hba_desc->online_module_list);

+		hba_desc->running_mod_num++;

+	}

+#endif

+

+#ifdef ODIN_DRIVER

+	}

+#endif

+

+	/* HBA */

+	prev = mod_desc;

+	mod_desc = __alloc_mod_desc();

+	if (NULL == mod_desc)

+		goto disaster;

+

+	mod_desc->ops = mv_hba_register_module();

+	if (NULL == mod_desc->ops) {

+		printk("No HBA no life.\n");

+		return -1;

+	}

+

+	mod_desc->hba_desc  = hba_desc;

+	mod_desc->status    = MV_MOD_REGISTERED;

+	mod_desc->module_id = MODULE_HBA;

+	mod_desc->child     = prev;

+	mod_desc->parent    = NULL;

+	prev->parent        = mod_desc;

+	list_add(&mod_desc->mod_entry, &hba_desc->online_module_list);

+	hba_desc->running_mod_num++;

+	

+	return 0;

+disaster:

+	return -1;

+}

+

+

+static void __release_consistent_mem(struct mv_mod_res *mod_res,

+				     struct pci_dev *dev)

+{

+	dma_addr_t       dma_addr;

+	MV_PHYSICAL_ADDR phy_addr;

+

+	phy_addr = mod_res->bus_addr;

+	dma_addr = (dma_addr_t) (phy_addr.parts.low |

+				 ((u64) phy_addr.parts.high << 32));

+	pci_free_consistent(dev,

+			    mod_res->size,

+			    mod_res->virt_addr,

+			    dma_addr);

+}

+

+static int __alloc_consistent_mem(struct mv_mod_res *mod_res,

+				  struct pci_dev *dev)

+{

+	unsigned long size;

+	dma_addr_t    dma_addr;

+	BUS_ADDRESS   bus_addr;

+	MV_PHYSICAL_ADDR phy_addr;

+

+	size = mod_res->size;

+	WARN_ON(size != ROUNDING(size, 8));

+	size = ROUNDING(size, 8);

+	mod_res->virt_addr = (MV_PVOID) pci_alloc_consistent(dev,

+							     size,

+							     &dma_addr);

+	if (NULL == mod_res->virt_addr) {

+		MV_DBG(DMSG_HBA, "unable to alloc 0x%lx consistent mem.\n",

+		       size);

+		return -1;

+	}

+	memset(mod_res->virt_addr, 0, size);

+	bus_addr            = (BUS_ADDRESS) dma_addr;

+	phy_addr.parts.low  = LO_BUSADDR(bus_addr);

+	phy_addr.parts.high = HI_BUSADDR(bus_addr);

+	mod_res->bus_addr   = phy_addr;

+

+	return 0;

+}

+

+int HBA_GetResource(struct mv_mod_desc *mod_desc,

+		    enum Resource_Type type,

+		    MV_U32  size,

+		    Assigned_Uncached_Memory *dma_res)

+{

+	struct mv_mod_res *mod_res;

+

+	mod_res = vmalloc(sizeof(struct mv_mod_res));

+	if (NULL == mod_res) {

+		printk("unable to allocate memory for resource management.\n");

+		return -1;

+	}

+

+	memset(mod_res, 0, sizeof(struct mv_mod_res));

+	mod_res->size = size;

+	mod_res->type = type;

+	switch (type) {

+	case RESOURCE_UNCACHED_MEMORY :

+		if (__alloc_consistent_mem(mod_res, mod_desc->hba_desc->dev)) {

+			printk("unable to allocate 0x%x uncached mem.\n", size);

+			vfree(mod_res);

+			return -1;

+		}

+		list_add(&mod_res->res_entry, &mod_desc->res_list);

+		memset(mod_res->virt_addr, 0, size);

+		dma_res->Virtual_Address  = mod_res->virt_addr;

+		dma_res->Physical_Address = mod_res->bus_addr;

+		dma_res->Byte_Size        = size;

+		break;

+	case RESOURCE_CACHED_MEMORY :

+	default:

+		vfree(mod_res);

+		printk("unknown resource type %d.\n", type);

+		return -1;

+	}

+	return 0;

+}

+

+static void __release_resource(struct mv_adp_desc *hba_desc,

+			       struct mv_mod_desc *mod_desc)

+{

+	struct mv_mod_res *mod_res, *tmp;

+

+	list_for_each_entry_safe(mod_res,

+				 tmp,

+				 &mod_desc->res_list,

+				 res_entry) {

+		switch (mod_res->type) {

+		case RESOURCE_UNCACHED_MEMORY :

+			__release_consistent_mem(mod_res, hba_desc->dev);

+			break;

+		case RESOURCE_CACHED_MEMORY :

+			vfree(mod_res->virt_addr);

+			break;

+		default:

+			MV_DBG(DMSG_HBA, "res type %d unknown.\n",

+			       mod_res->type);

+			break;

+		}

+		list_del(&mod_res->res_entry);

+		vfree(mod_res);

+	}

+}

+

+static void __release_module_resource(struct mv_mod_desc *mod_desc)

+{

+	__release_resource(mod_desc->hba_desc, mod_desc);

+}

+

+static int __alloc_module_resource(struct mv_mod_desc *mod_desc,

+				   unsigned int max_io)

+{

+	struct mv_mod_res *mod_res = NULL;

+	unsigned int size = 0;

+	

+	/*

+	 * alloc only cached mem at this stage, uncached mem will be alloc'ed 

+	 * during mod init.

+	 */

+	INIT_LIST_HEAD(&mod_desc->res_list);

+	mod_res = vmalloc(sizeof(struct mv_mod_res));

+	if (NULL == mod_res)

+		return -1;

+	memset(mod_res, 0, sizeof(sizeof(struct mv_mod_res)));

+	mod_desc->res_entry = 1;

+	

+	size = mod_desc->ops->get_res_desc(RESOURCE_CACHED_MEMORY, max_io);

+	if (size) {

+		mod_res->virt_addr = vmalloc(size);

+		if (NULL == mod_res->virt_addr) {

+			vfree(mod_res);

+			return -1;

+		}

+		memset(mod_res->virt_addr, 0, size);

+		mod_res->type                = RESOURCE_CACHED_MEMORY;

+		mod_res->size                = size;

+		mod_desc->extension          = mod_res->virt_addr;

+		mod_desc->extension_size     = size;

+		list_add(&mod_res->res_entry, &mod_desc->res_list);

+	}

+

+	return 0;

+}

+

+static void mv_release_module_resource(struct mv_adp_desc *hba_desc)

+{

+	struct mv_mod_desc *mod_desc;

+

+	list_for_each_entry(mod_desc, &hba_desc->online_module_list, 

+			    mod_entry) {

+		if (mod_desc->status == MV_MOD_INITED) {

+			__release_module_resource(mod_desc);

+			mod_desc->status = MV_MOD_REGISTERED;

+		}

+	}

+}

+

+static int mv_alloc_module_resource(struct mv_adp_desc *hba_desc)

+{

+	struct mv_mod_desc *mod_desc;

+	int ret;

+

+	list_for_each_entry(mod_desc, &hba_desc->online_module_list, 

+			    mod_entry) {

+		ret = __alloc_module_resource(mod_desc, hba_desc->max_io);

+		if (ret)

+			goto err_out;

+		mod_desc->status = MV_MOD_INITED;

+	}

+	return 0;

+

+err_out:

+	MV_DBG(DMSG_HBA, "error %d allocating resource for mod %d.\n",

+	       ret, mod_desc->module_id);

+	list_for_each_entry(mod_desc, &hba_desc->online_module_list, 

+			    mod_entry) {

+		if (mod_desc->status == MV_MOD_INITED) {

+			__release_module_resource(mod_desc);

+			mod_desc->status = MV_MOD_REGISTERED;

+		}

+	}

+	return -1;

+}

+

+

+

+static inline struct mv_mod_desc *

+__get_highest_module(struct mv_adp_desc *hba_desc)

+{

+	struct mv_mod_desc *p;

+	

+	/* take a random module, and trace through its parent */

+	p = list_entry(hba_desc->online_module_list.next, 

+		       struct mv_mod_desc,

+		       mod_entry);

+

+	WARN_ON(NULL == p);

+	while (p) {

+		if (NULL == p->parent)

+			break;

+		p = p->parent;

+	}

+	return p;

+}

+

+static void __map_pci_addr(struct pci_dev *dev, MV_PVOID *addr_array)

+{

+	int i;

+	unsigned long addr;

+	unsigned long range;

+

+	for (i = 0; i < MAX_BASE_ADDRESS; i++) {

+		addr  = pci_resource_start(dev, i);

+		range = pci_resource_len(dev, i);

+

+		if (pci_resource_flags(dev, i) & IORESOURCE_MEM)

+			addr_array[i] =(MV_PVOID) ioremap(addr, range);

+		else if (pci_resource_flags(dev, i) & IORESOURCE_IO)

+			addr_array[i] = (MV_PVOID) ioport_map(addr, range);

+			

+

+		MV_DBG(DMSG_HBA, "BAR %d : %p.\n", 

+		       i, addr_array[i]);

+	}

+}

+

+static void __unmap_pci_addr(struct pci_dev *dev, MV_PVOID *addr_array)

+{

+	int i;

+	

+	for (i = 0; i < MAX_BASE_ADDRESS; i++) 

+		if (pci_resource_flags(dev, i) & IORESOURCE_MEM)

+                        iounmap(addr_array[i]);

+		else if (pci_resource_flags(dev, i) & IORESOURCE_IO)

+			ioport_unmap(addr_array[i]);

+}

+

+int __mv_is_mod_all_started(struct mv_adp_desc *adp_desc)

+{

+	struct mv_mod_desc *mod_desc;

+	

+	mod_desc = __get_lowest_module(adp_desc);

+

+	while (mod_desc) {

+		if (MV_MOD_STARTED != mod_desc->status)

+			return 0;

+

+		mod_desc = mod_desc->parent;

+	}

+	return 1;

+}

+

+struct hba_extension *__mv_get_ext_from_adp_id(int id)

+{

+	struct mv_adp_desc *p;

+

+	list_for_each_entry(p, &mv_online_adapter_list, hba_entry)

+		if (p->id == id)

+			return __get_highest_module(p)->extension;

+	

+	return NULL;

+}

+

+int mv_hba_start(struct pci_dev *dev)

+{

+	struct mv_adp_desc *hba_desc;

+	struct mv_mod_desc *mod_desc;

+

+	hba_desc = __dev_to_desc(dev);

+	BUG_ON(NULL == hba_desc);

+#if 0

+	mod_desc = __get_lowest_module(hba_desc);

+	if (NULL == mod_desc)

+		return -1;

+	MV_DPRINT(("Start lowest module.\n"));

+

+#ifdef THOR_DRIVER

+	spin_lock_irq(&hba_desc->global_lock);

+#endif

+

+	mod_desc->ops->module_start(mod_desc->extension);

+

+#ifdef THOR_DRIVER

+	spin_unlock_irq(&hba_desc->global_lock);

+#endif

+#endif

+	MV_DPRINT(("Start highest module.\n"));

+	mod_desc = __get_highest_module(hba_desc);

+	if (NULL == mod_desc)

+		return -1;

+

+	mod_desc->ops->module_start(mod_desc->extension);

+

+	return 0;

+}

+

+static void __hba_module_stop(struct mv_adp_desc *hba_desc)

+{

+	struct mv_mod_desc *mod_desc;

+

+	mod_desc = __get_highest_module(hba_desc);

+	if (NULL == mod_desc)

+		return;

+

+	/* starting from highest module, unlike module_start */

+	while (mod_desc) {

+		if ((MV_MOD_STARTED == mod_desc->status)) {

+			mod_desc->ops->module_stop(mod_desc->extension);

+			mod_desc->status = MV_MOD_INITED;

+		}

+		mod_desc = mod_desc->child;

+	}

+}

+

+/* stop all HBAs if dev == NULL */

+void mv_hba_stop(struct pci_dev *dev)

+{

+	struct mv_adp_desc *hba_desc;

+

+	hba_wait_eh();

+

+	if (dev) {

+		hba_desc = __dev_to_desc(dev);

+		__hba_module_stop(hba_desc);

+	} else {

+		list_for_each_entry(hba_desc, &mv_online_adapter_list, hba_entry)

+			__hba_module_stop(hba_desc);

+	}

+}

+

+void mv_hba_release(struct pci_dev *dev)

+{

+	struct mv_adp_desc *hba_desc;

+

+	hba_desc = __dev_to_desc(dev);

+	if (NULL != hba_desc) {

+		__unmap_pci_addr(hba_desc->dev, hba_desc->Base_Address);

+		mv_release_module_resource(hba_desc);

+		mv_hba_release_modmm(hba_desc->dev);

+	}

+}

+

+int mv_hba_init(struct pci_dev *dev, MV_U32 max_io)

+{

+	struct mv_adp_desc *hba_desc;

+	struct mv_mod_desc *mod_desc;

+	int    dbg_ret = 0;

+	

+	hba_desc = mv_hba_init_modmm(dev);

+	if (NULL == hba_desc)

+		goto ext_err_init;

+

+

+	hba_desc->max_io = max_io;

+	hba_desc->id     = __mv_get_adapter_count() - 1;

+	

+	if (pci_read_config_byte(hba_desc->dev, 

+				 PCI_REVISION_ID, 

+				 &hba_desc->Revision_Id)) {

+		MV_PRINT("Failed to get hba's revision id.\n");

+		goto ext_err_pci;

+	}

+	

+	hba_desc->vendor = dev->vendor;

+	hba_desc->device = dev->device;

+	hba_desc->subsystem_vendor = dev->subsystem_vendor;

+	hba_desc->subsystem_device = dev->subsystem_device;

+

+	__map_pci_addr(dev, hba_desc->Base_Address);

+	

+	spin_lock_init(&hba_desc->lock);

+	spin_lock_init(&hba_desc->global_lock);

+

+	/* For Odin family, read PCIE configuration space register bit 31:25 [PAD_TEST] (offset=0x60) */

+	/* to identify different part */

+#ifdef ODIN_DRIVER

+	if (hba_desc->device != DEVICE_ID_6480) {

+		MV_U32 padTest = 0;

+		pci_read_config_dword(dev, 0x60, &padTest);

+		hba_desc->device = SetDeviceID(padTest);

+		hba_desc->subsystem_device = hba_desc->device;

+		if (hba_desc->device == DEVICE_ID_6445)

+			hba_desc->RunAsNonRAID = MV_TRUE;

+

+		MV_DBG(DMSG_HBA, "controller device id 0x%x.\n", 

+	       hba_desc->device);

+		

+	}

+#endif

+

+

+

+	MV_DBG(DMSG_HBA, "HBA ext struct init'ed at %p.\n", 

+	        hba_desc);

+

+	if (register_online_modules(hba_desc))

+		goto ext_err_modmm;

+

+	if (mv_alloc_module_resource(hba_desc))

+		goto ext_err_modmm;

+

+	mod_desc = __get_lowest_module(hba_desc);

+	if (NULL == mod_desc)

+		goto ext_err_pci;

+

+	while (mod_desc) {

+		if (MV_MOD_INITED != mod_desc->status)

+			continue;

+		mod_desc->ops->module_initialize(mod_desc,

+						 mod_desc->extension_size,

+						 hba_desc->max_io);

+		/* there's no support for sibling module at the moment  */

+		mod_desc = mod_desc->parent;

+	}

+	return 0;

+

+ext_err_pci:

+	++dbg_ret;

+	mv_release_module_resource(hba_desc);

+ext_err_modmm:

+	++dbg_ret;

+	mv_hba_release_modmm(dev);

+ext_err_init:

+        ++dbg_ret;

+	return dbg_ret;

+}

+

+static MV_U32 HBA_ModuleGetResourceQuota(enum Resource_Type type, MV_U16 maxIo)

+{

+	MV_U32 size = 0;

+

+	if (type == RESOURCE_CACHED_MEMORY) {

+		/* Fixed memory */

+		size = OFFSET_OF(HBA_Extension, Memory_Pool);

+		size = ROUNDING(size, 8);

+

+#ifdef SUPPORT_EVENT

+		size += sizeof(Driver_Event_Entry) * MAX_EVENTS;

+		MV_ASSERT(size == ROUNDING(size, 8));

+#endif /* SUPPORT_EVENT */

+	}

+

+	return size;

+}

+

+#ifdef SUPPORT_TASKLET

+MV_BOOLEAN Core_TaskletHandler(MV_PVOID This);

+static void run_tasklet(PHBA_Extension   phba)

+{

+	struct mv_mod_desc *core_desc=__get_lowest_module(phba->desc->hba_desc);

+	unsigned long flags;

+	MV_PVOID pcore=core_desc->extension;

+	spin_lock_irqsave(&phba->desc->hba_desc->global_lock, flags);

+	Core_TaskletHandler(pcore);

+	spin_unlock_irqrestore(&phba->desc->hba_desc->global_lock, flags);

+}

+#endif

+

+static void HBA_ModuleInitialize(MV_PVOID this,

+				 MV_U32   size,

+				 MV_U16   max_io)

+{

+	struct   mv_mod_desc *mod_desc=(struct   mv_mod_desc *)this;

+	PHBA_Extension phba;

+	MV_PTR_INTEGER temp;

+	MV_U32 i;

+	MV_U32 sg_num;

+

+#ifdef SUPPORT_EVENT

+	PDriver_Event_Entry pEvent = NULL;

+#endif /* SUPPORT_EVENT */

+    

+	phba     = (PHBA_Extension) mod_desc->extension;

+	temp     = (MV_PTR_INTEGER) phba->Memory_Pool;

+

+	WARN_ON(sizeof(MV_Request) != ROUNDING(sizeof(MV_Request), 8));

+	/* 

+	 * Initialize data structure however following variables have been 

+	 * set already.

+	 *	Device_Extension

+	 *	Is_Dump

+	 */

+	phba->State    = DRIVER_STATUS_IDLE;

+	phba->Io_Count = 0;

+	phba->Max_Io   = max_io;

+	phba->desc     = mod_desc;

+

+	init_completion(&phba->cmpl);

+	temp = ROUNDING(((MV_PTR_INTEGER) temp), 8);

+

+	if (max_io > 1)

+		sg_num   = MAX_SG_ENTRY;

+	else

+		sg_num   = MAX_SG_ENTRY_REDUCED;

+

+	phba->req_pool = (MV_PVOID) res_reserve_req_pool(MODULE_HBA,

+							 max_io,

+							 sg_num);

+	BUG_ON(NULL == phba->req_pool);

+#ifdef THOR_DRIVER

+	//spin_lock_init(&phba->lock);

+	init_timer(&phba->timer);

+#endif

+

+#ifdef SUPPORT_TASKLET

+	tasklet_init(&phba->mv_tasklet,

+			(void (*)(unsigned long))run_tasklet, (unsigned long)phba);

+#endif

+

+#ifdef SUPPORT_EVENT

+	INIT_LIST_HEAD(&phba->Stored_Events);

+	INIT_LIST_HEAD(&phba->Free_Events);

+	phba->Num_Stored_Events = 0;

+	phba->SequenceNumber = 0;	/* Event sequence number */

+

+	MV_ASSERT(sizeof(Driver_Event_Entry) == 

+		  ROUNDING(sizeof(Driver_Event_Entry), 8));

+	temp = ROUNDING(((MV_PTR_INTEGER) temp), 8);

+

+	for (i = 0; i < MAX_EVENTS; i++) {

+		pEvent = (PDriver_Event_Entry) temp;

+		list_add_tail(&pEvent->Queue_Pointer, &phba->Free_Events);

+		temp += sizeof(Driver_Event_Entry);

+	}

+#endif /* SUPPORT_EVENT */

+

+}

+

+static void HBA_ModuleStart(MV_PVOID extension)

+{

+	struct Scsi_Host *host = NULL;

+	struct hba_extension *hba;

+	int ret;

+

+	struct mv_adp_desc *adp_desc;

+	struct mv_mod_desc *core_desc;

+

+	hba = (struct hba_extension *) extension;

+	host = scsi_host_alloc(&mv_driver_template, sizeof(void *));

+	if (NULL == host) {

+		MV_PRINT("Unable to allocate a scsi host.\n" );

+		goto err_out;

+	}

+

+	*((MV_PVOID *) host->hostdata) = extension;

+	hba->host = host;

+	hba->dev  = hba->desc->hba_desc->dev;

+

+	host->irq          = hba->dev->irq;

+	host->max_id       = MV_MAX_TARGET_NUMBER;

+	host->max_lun      = MV_MAX_LUN_NUMBER;

+	host->max_channel  = 0;

+	host->max_cmd_len  = 16;

+

+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)

+	host->transportt   = &mv_transport_template;

+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 16) */

+

+#ifdef USE_MSI

+	pci_enable_msi(hba->dev);

+#endif /* USE_MSI */

+

+	MV_DBG(DMSG_KERN, "start install request_irq.\n");

+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19)

+	ret = request_irq(hba->dev->irq, mv_intr_handler, IRQF_SHARED,

+			  mv_driver_name, hba);

+#else

+	ret = request_irq(hba->dev->irq, mv_intr_handler, SA_SHIRQ,

+			  mv_driver_name, hba);

+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19) */

+	if (ret < 0) {

+		MV_PRINT("Error upon requesting IRQ %d.\n", 

+		       hba->dev->irq);

+		goto  err_request_irq;

+	}

+	MV_DBG(DMSG_KERN, "request_irq has been installed.\n");

+

+	hba->desc->status = MV_MOD_STARTED;

+

+	/* To start CORE layer */

+	adp_desc = hba->desc->hba_desc;

+	core_desc = __get_lowest_module(adp_desc);

+	if (NULL == core_desc) {

+		goto err_wait_cmpl;

+	}

+

+	core_desc->ops->module_start(core_desc->extension);

+	

+

+	HBA_ModuleStarted(hba->desc);

+

+	MV_DBG(DMSG_KERN, "wait_for_completion_timeout.....\n");

+	/* wait for MODULE(CORE,RAID,HBA) init */

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_set(&hba->hba_sync, 1);

+	if (0 == __hba_wait_for_atomic_timeout(&hba->hba_sync, 30 * HZ)) 

+		goto err_wait_cmpl;

+#else

+	if (0 == wait_for_completion_timeout(&hba->cmpl, 30 * HZ)) 

+		goto err_wait_cmpl;

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+

+	hba_house_keeper_run();

+

+	if (scsi_add_host(host, &hba->dev->dev))

+		goto err_wait_cmpl;

+

+	MV_DPRINT(("Start scsi_scan_host.\n"));

+	

+	scsi_scan_host(host);

+

+	if (mv_register_chdev(hba))

+		printk("Unable to register character device interface.\n");

+

+	

+	MV_DPRINT(("Finished HBA_ModuleStart.\n"));

+

+	return;

+err_wait_cmpl:

+	printk("Timeout waiting for module start.\n");

+	free_irq(hba->dev->irq, hba);

+err_request_irq:

+	scsi_host_put(host);

+	hba->host = NULL;

+err_out:

+	return;

+}

+

+extern void hba_send_shutdown_req(PHBA_Extension phba);

+static void HBA_ModuleShutdown(MV_PVOID extension)

+{

+	PHBA_Extension hba = (PHBA_Extension) extension;

+

+	mv_unregister_chdev(hba);

+

+	if (DRIVER_STATUS_STARTED == hba->State) {

+		scsi_remove_host(hba->host);

+		scsi_host_put(hba->host);

+		hba->host = NULL;

+

+		hba_send_shutdown_req(hba);

+		while(hba->Io_Count != 0)

+			mdelay(1);

+		free_irq(hba->dev->irq, hba);

+	}

+	res_release_req_pool(hba->req_pool);

+	hba->State = DRIVER_STATUS_SHUTDOWN;

+}

+

+#ifdef SUPPORT_EVENT

+static MV_BOOLEAN add_event(IN MV_PVOID extension,

+			    IN MV_U32 eventID,

+			    IN MV_U16 deviceID,

+			    IN MV_U8 severityLevel,

+			    IN MV_U8 param_cnt,

+			    IN MV_PVOID params)

+{

+	struct hba_extension * hba = (struct hba_extension *) extension;

+	PDriver_Event_Entry pEvent;

+	static MV_U32 sequenceNo = 1;

+	if (param_cnt > MAX_EVENT_PARAMS)

+		return MV_FALSE;

+

+	if (list_empty(&hba->Free_Events)) {

+		/* No free entry, we need to reuse the oldest entry from 

+		 * Stored_Events.

+		 */

+		MV_ASSERT(!list_empty(&hba->Stored_Events));

+		MV_ASSERT(hba->Num_Stored_Events == MAX_EVENTS);

+		pEvent = List_GetFirstEntry((&hba->Stored_Events), Driver_Event_Entry, Queue_Pointer);

+	}

+	else

+	{

+		pEvent = List_GetFirstEntry((&hba->Free_Events), Driver_Event_Entry, Queue_Pointer);

+		hba->Num_Stored_Events++;

+		MV_ASSERT(hba->Num_Stored_Events <= MAX_EVENTS);

+	}

+

+	pEvent->Event.AdapterID  = hba->desc->hba_desc->id;

+	pEvent->Event.EventID    = eventID; 

+	pEvent->Event.SequenceNo = sequenceNo++;

+	pEvent->Event.Severity   = severityLevel;

+	pEvent->Event.DeviceID   = deviceID;

+//	pEvent->Event.Param_Cnt  = param_cnt;

+	pEvent->Event.TimeStamp  = ossw_get_time_in_sec();

+

+	if (param_cnt > 0 && params != NULL)

+		MV_CopyMemory( (MV_PVOID)pEvent->Event.Params, (MV_PVOID)params, param_cnt * 4 );

+

+	list_add_tail(&pEvent->Queue_Pointer, &hba->Stored_Events);

+

+	return MV_TRUE;

+}

+

+static void get_event(MV_PVOID This, PMV_Request pReq)

+{

+	struct hba_extension * hba = (struct hba_extension *) This;

+	PEventRequest pEventReq = (PEventRequest)pReq->Data_Buffer;

+	PDriver_Event_Entry pfirst_event;

+	MV_U8 count = 0;

+

+	pEventReq->Count = 0;

+	

+	if ( hba->Num_Stored_Events > 0 )

+	{	

+		MV_DASSERT( !list_empty(&hba->Stored_Events) );

+		while (!list_empty(&hba->Stored_Events) &&

+		       (count < MAX_EVENTS_RETURNED)) {

+			pfirst_event = List_GetFirstEntry((&hba->Stored_Events), Driver_Event_Entry, Queue_Pointer);

+			MV_CopyMemory(&pEventReq->Events[count], 

+				      &pfirst_event->Event, 

+				      sizeof(DriverEvent));

+			hba->Num_Stored_Events--;

+			list_add_tail(&pfirst_event->Queue_Pointer, 

+				      &hba->Free_Events );

+			count++;

+		}

+		pEventReq->Count = count;

+	}

+

+	pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+	return;

+}

+#else /* SUPPORT_EVENT */

+static inline MV_BOOLEAN add_event(IN MV_PVOID extension,

+				   IN MV_U32 eventID,

+				   IN MV_U16 deviceID,

+				   IN MV_U8 severityLevel,

+				   IN MV_U8 param_cnt,

+				   IN MV_PVOID params) {}

+

+static inline void get_event(MV_PVOID This, PMV_Request pReq) {}

+#endif /* SUPPORT_EVENT */

+

+

+void HBA_ModuleNotification(MV_PVOID This, 

+			     enum Module_Event event, 

+			     struct mod_notif_param *event_param)

+{

+	/* "This" passed in is not hba extension, it is caller's extension */

+	/* has to find own extension like the implementation in HBA */

+	MV_PVOID hba = HBA_GetModuleExtension(This, MODULE_HBA);	

+	MV_DPRINT(("Enter HBA_ModuleNotification event %x\n",event));

+//	MV_POKE();

+	switch (event) {

+	case EVENT_LOG_GENERATED:

+		add_event(hba,

+			  event_param->event_id,

+			  event_param->dev_id,

+			  event_param->severity_lvl,

+			  event_param->param_count,

+			  event_param->p_param);

+		break;

+	case EVENT_DEVICE_REMOVAL:

+	case EVENT_DEVICE_ARRIVAL:

+		hba_msg_insert(hba,

+			       event,

+			       (event_param == NULL)?0:event_param->lo);

+		break;

+	case EVENT_HOT_PLUG:

+		hba_msg_insert(event_param->p_param,

+			       event,

+			       event_param->event_id);

+		break;

+	default:

+		break;

+	}

+}

+#if 1//def SUPPORT_SCSI_PASSTHROUGH

+

+/* helper functions related to HBA_ModuleSendRequest */

+static void mvGetAdapterInfo( MV_PVOID This, PMV_Request pReq )

+{

+	PHBA_Extension hba = (PHBA_Extension)This;

+	struct mv_adp_desc *pHBA=hba->desc->hba_desc;

+	PAdapter_Info pAdInfo;

+#ifdef ODIN_DRIVER

+	PCore_Driver_Extension pCore = (PCore_Driver_Extension)HBA_GetModuleExtension(This,MODULE_CORE);

+#endif

+	/* initialize */

+	pAdInfo = (PAdapter_Info)pReq->Data_Buffer;

+	MV_ZeroMemory(pAdInfo, sizeof(Adapter_Info));

+

+

+	pAdInfo->DriverVersion.VerMajor = VER_MAJOR;

+	pAdInfo->DriverVersion.VerMinor = VER_MINOR;

+	pAdInfo->DriverVersion.VerOEM = VER_OEM;

+	pAdInfo->DriverVersion.VerBuild = VER_BUILD;

+

+	pAdInfo->SystemIOBusNumber = pHBA->Adapter_Bus_Number;

+	pAdInfo->SlotNumber = pHBA->Adapter_Device_Number;

+	pAdInfo->VenID = pHBA->vendor;

+	pAdInfo->DevID = pHBA->device;

+	pAdInfo->SubDevID = pHBA->subsystem_device;

+	pAdInfo->SubVenID = pHBA->subsystem_vendor;

+	pAdInfo->RevisionID = pHBA->Revision_Id;

+

+	if ( pHBA->device == DEVICE_ID_THORLITE_2S1P||pHBA->device == DEVICE_ID_THORLITE_2S1P_WITH_FLASH ){

+		pAdInfo->PortCount = 3;

+	}else if ( pHBA->device == DEVICE_ID_THORLITE_0S1P ){

+		pAdInfo->PortCount = 1;

+	}else if ( (pHBA->device == DEVICE_ID_6440) || 

+			   (pHBA->device == DEVICE_ID_6445) ||

+			   (pHBA->device == DEVICE_ID_6340) ){

+		pAdInfo->PortCount = 4;

+	}else if ( pHBA->device == DEVICE_ID_6480 ){

+		pAdInfo->PortCount = 8;	

+	}else if ( pHBA->device == DEVICE_ID_6320 ){

+		pAdInfo->PortCount = 2;

+	}else {

+		pAdInfo->PortCount = 5;

+	}

+

+//	pAdInfo->MaxHD = pCore->PD_Count_Supported;

+#ifdef SIMULATOR

+	pAdInfo->MaxHD = MAX_DEVICE_SUPPORTED_PERFORMANCE;

+	pAdInfo->MaxExpander = 0;

+#elif defined(ODIN_DRIVER)

+	pAdInfo->MaxHD = pCore->PD_Count_Supported;

+	pAdInfo->MaxExpander = pCore->Expander_Count_Supported;

+#else

+	pAdInfo->MaxHD = 8;

+	pAdInfo->MaxExpander = MAX_EXPANDER_SUPPORTED;

+#endif

+

+	pAdInfo->MaxPM = MAX_PM_SUPPORTED;				// 4 for now

+#ifdef RAID_DRIVER

+	raid_capability(This,  pAdInfo);

+#endif	/* RAID_DRIVER */

+	pReq->Scsi_Status = REQ_STATUS_SUCCESS;

+}

+

+#endif

+

+

+static void HBA_ModuleSendRequest(MV_PVOID this, PMV_Request req)

+{

+	PHBA_Extension phba = (PHBA_Extension) this;

+

+	switch (req->Cdb[0])

+	{

+	case APICDB0_ADAPTER:

+		if (req->Cdb[1] == APICDB1_ADAPTER_GETINFO)

+			mvGetAdapterInfo(phba, req);

+		else

+			req->Scsi_Status = REQ_STATUS_INVALID_REQUEST;

+

+		req->Completion(req->Cmd_Initiator, req);

+		break;

+	case APICDB0_EVENT:

+		if (req->Cdb[1] == APICDB1_EVENT_GETEVENT)

+			get_event(phba, req);

+		else

+			req->Scsi_Status = REQ_STATUS_INVALID_REQUEST;

+

+		req->Completion(req->Cmd_Initiator, req);

+		break;

+	default:

+		/* submit to child layer */

+		phba->desc->child->ops->module_sendrequest(

+			phba->desc->child->extension,

+			req);

+		break;

+	}

+}

+

+static struct mv_module_ops hba_module_interface = {

+	.module_id              = MODULE_HBA,

+	.get_res_desc           = HBA_ModuleGetResourceQuota,

+	.module_initialize      = HBA_ModuleInitialize,

+	.module_start           = HBA_ModuleStart,

+	.module_stop            = HBA_ModuleShutdown,

+	.module_notification    = HBA_ModuleNotification,

+	.module_sendrequest     = HBA_ModuleSendRequest,

+};

+

+struct mv_module_ops *mv_hba_register_module(void)

+{

+	return &hba_module_interface;

+}

diff --git a/drivers/scsi/thor/linux/hba_mod.h b/drivers/scsi/thor/linux/hba_mod.h
new file mode 100755
index 0000000..cc68da8
--- /dev/null
+++ b/drivers/scsi/thor/linux/hba_mod.h
@@ -0,0 +1,22 @@
+#ifndef __MODULE_MANAGE_H__

+#define __MODULE_MANAGE_H__

+#include "hba_header.h"

+

+#include "com_mod_mgmt.h"

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+/* will wait for atomic value atomic to become zero until timed out */

+/* return how much 'timeout' is left or 0 if already timed out */

+int __hba_wait_for_atomic_timeout(atomic_t *atomic, unsigned long timeout);

+#endif

+

+int  mv_hba_init(struct pci_dev *dev, MV_U32 max_io);

+void mv_hba_release(struct pci_dev *dev);

+void mv_hba_stop(struct pci_dev *dev);

+int  mv_hba_start(struct pci_dev *dev);

+

+int __mv_get_adapter_count(void);

+struct hba_extension *__mv_get_ext_from_adp_id(int id);

+ void raid_capability( MV_PVOID This, PAdapter_Info pAdInfo);

+#endif /* __MODULE_MANAGE_H__ */

+

diff --git a/drivers/scsi/thor/linux/hba_timer.c b/drivers/scsi/thor/linux/hba_timer.c
new file mode 100755
index 0000000..94bfc64
--- /dev/null
+++ b/drivers/scsi/thor/linux/hba_timer.c
@@ -0,0 +1,313 @@
+#include "hba_header.h"

+#include "core_exp.h"

+

+/* how long a time between which should each keeper work be done */

+#define KEEPER_SHIFT (HZ >> 1)

+

+static struct mv_hba_msg_queue mv_msg_queue;

+

+#ifndef SUPPORT_WORKQUEUE

+static struct task_struct *house_keeper_task;

+#endif

+

+static int __msg_queue_state;

+

+static inline int queue_state_get(void)

+{

+	return __msg_queue_state;

+}

+

+static inline void queue_state_set(int state)

+{

+	__msg_queue_state = state;

+}

+

+static void hba_proc_msg(struct mv_hba_msg *pmsg)

+{

+	PHBA_Extension phba;

+	struct scsi_device *psdev;

+

+	/* we don't do things without pmsg->data */

+	if (NULL == pmsg->data)

+		return;

+

+	phba = (PHBA_Extension) pmsg->data;

+

+	

+	MV_DBG(DMSG_HBA, "__MV__ In hba_proc_msg.\n");

+

+	MV_ASSERT(pmsg);

+

+	switch (pmsg->msg) {

+	case EVENT_DEVICE_ARRIVAL:

+		if (scsi_add_device(phba->host, 0, pmsg->param, 0))

+			MV_DBG(DMSG_SCSI, 

+			       "__MV__ add scsi disk %d-%d-%d failed.\n",

+			       0, pmsg->param, 0);

+		else

+			MV_DBG(DMSG_SCSI,

+			       "__MV__ add scsi disk %d-%d-%d.\n",

+			       0, pmsg->param, 0);

+		break;

+	case EVENT_DEVICE_REMOVAL:

+		psdev = scsi_device_lookup(phba->host, 0, pmsg->param, 0);

+

+		if (NULL != psdev) {

+			MV_DBG(DMSG_SCSI, 

+			       "__MV__ remove scsi disk %d-%d-%d.\n",

+			       0, pmsg->param, 0);

+			scsi_remove_device(psdev);

+			scsi_device_put(psdev);

+		} else {

+			MV_DBG(DMSG_SCSI,

+			       "__MV__ no disk to remove %d-%d-%d\n",

+			       0, pmsg->param, 0);

+		}

+		break;

+	case EVENT_HOT_PLUG:

+		sata_hotplug(pmsg->data, pmsg->param);

+		break;

+	default:

+		break;

+	}

+}

+

+static void mv_proc_queue(void)

+{

+	struct mv_hba_msg *pmsg;

+	

+	/* work on queue non-stop, pre-empty me! */

+	queue_state_set(MSG_QUEUE_PROC);

+

+	while (1) {

+		MV_DBG(DMSG_HBA, "__MV__ process queue starts.\n");

+		spin_lock_irq(&mv_msg_queue.lock);

+		if (list_empty(&mv_msg_queue.tasks)) {

+			/* it's important we put queue_state_set here. */

+			queue_state_set(MSG_QUEUE_IDLE);

+			spin_unlock_irq(&mv_msg_queue.lock);

+			MV_DBG(DMSG_HBA, "__MV__ process queue ends.\n");

+			break;

+		}

+		pmsg = list_entry(mv_msg_queue.tasks.next, struct mv_hba_msg, msg_list);

+		spin_unlock_irq(&mv_msg_queue.lock);

+

+		hba_proc_msg(pmsg);

+		

+		/* clean the pmsg before returning it to free?*/

+		pmsg->data = NULL;

+		spin_lock_irq(&mv_msg_queue.lock);

+		list_move_tail(&pmsg->msg_list, &(mv_msg_queue.free));

+		spin_unlock_irq(&mv_msg_queue.lock);

+		MV_DBG(DMSG_HBA, "__MV__ process queue ends.\n");

+	}

+

+}

+

+static inline MV_U32 hba_msg_queue_empty(void)

+{

+	return list_empty(&(mv_msg_queue.tasks));

+}

+

+#ifndef SUPPORT_WORKQUEUE

+static int hba_house_keeper(void *data)

+{

+	set_user_nice(current, -15);

+	

+	set_current_state(TASK_INTERRUPTIBLE);

+	while (!kthread_should_stop()) {

+

+		if (!hba_msg_queue_empty() && 

+		    MSG_QUEUE_IDLE == queue_state_get()) {

+			set_current_state(TASK_RUNNING);

+			mv_proc_queue();

+		} else {

+			schedule();

+			set_current_state(TASK_INTERRUPTIBLE);

+		}

+	}

+	

+	return 0;

+}

+

+#endif

+

+#ifdef SUPPORT_WORKQUEUE

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)

+static void mv_wq_handler(void *work)

+#else

+static void mv_wq_handler(struct work_struct *work)

+#endif

+{

+	if (hba_msg_queue_empty() ){

+		MV_DBG(DMSG_KERN,"__MV__  msg queue is empty.\n");

+		return;

+	}

+	else if (!hba_msg_queue_empty() && 

+	    MSG_QUEUE_IDLE == queue_state_get()) {

+	    	MV_DBG(DMSG_KERN,"__MV__  msg queue isn't empty.\n");

+		mv_proc_queue();

+	}

+}

+

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)

+static DECLARE_WORK(mv_wq, mv_wq_handler,NULL);

+#else

+static DECLARE_WORK(mv_wq, mv_wq_handler);

+#endif

+

+#endif /* SUPPORT_WORKQUEUE */

+

+

+

+static void hba_msg_queue_init(void)

+{

+	int i;

+	

+	spin_lock_init(&mv_msg_queue.lock);

+

+/* as we're in init, there should be no need to hold the spinlock*/

+	INIT_LIST_HEAD(&(mv_msg_queue.free));

+	INIT_LIST_HEAD(&(mv_msg_queue.tasks));

+

+	for (i = 0; i < MSG_QUEUE_DEPTH; i++) {

+		list_add_tail(&mv_msg_queue.msgs[i].msg_list, 

+			      &mv_msg_queue.free);

+	}

+	

+}

+

+

+void hba_house_keeper_init(void)

+{

+	hba_msg_queue_init();

+

+	queue_state_set(MSG_QUEUE_IDLE);

+#ifndef SUPPORT_WORKQUEUE

+	house_keeper_task = kthread_run(hba_house_keeper, NULL, "399B4F5");

+

+	if (IS_ERR(house_keeper_task)) {

+		printk("Error creating kthread, out of memory?\n");

+		house_keeper_task = NULL;

+	}

+#endif

+}

+

+void hba_house_keeper_run(void)

+{

+	/* hey hey my my */

+}

+

+void hba_house_keeper_exit(void)

+{

+#ifndef SUPPORT_WORKQUEUE

+	if (house_keeper_task)

+		kthread_stop(house_keeper_task);

+	house_keeper_task = NULL;

+#else

+	flush_scheduled_work();

+#endif

+}

+

+void hba_wait_eh()

+{

+	while (!hba_msg_queue_empty()) {

+		schedule();

+	}

+}

+

+

+void hba_msg_insert(void *data, unsigned int msg, unsigned int param)

+{

+	struct mv_hba_msg *pmsg;

+	unsigned long flags;

+

+	MV_DBG(DMSG_HBA, "__MV__ msg insert  %d.\n", msg);

+

+	spin_lock_irqsave(&mv_msg_queue.lock, flags);

+	if (list_empty(&mv_msg_queue.free)) {

+		/* should wreck some havoc ...*/

+		MV_DBG(DMSG_HBA, "-- MV -- Message queue is full.\n");

+		spin_unlock_irqrestore(&mv_msg_queue.lock, flags);

+		return;

+	}

+

+	pmsg = list_entry(mv_msg_queue.free.next, struct mv_hba_msg, msg_list);

+	pmsg->data = data;

+	pmsg->msg  = msg;

+

+	switch (msg) {

+	case EVENT_DEVICE_REMOVAL:

+	case EVENT_DEVICE_ARRIVAL:

+		pmsg->param = param;

+		break;

+	default:

+		pmsg->param = param;

+                /*(NULL==param)?0:*((unsigned int*) param);*/

+		break;

+	}

+

+	list_move_tail(&pmsg->msg_list, &mv_msg_queue.tasks);

+	spin_unlock_irqrestore(&mv_msg_queue.lock, flags);

+

+#ifndef SUPPORT_WORKQUEUE

+	if (house_keeper_task)

+		wake_up_process(house_keeper_task);

+#else

+	schedule_work(&mv_wq);

+#endif

+

+}

+#if 1//def REQUEST_TIMER

+void hba_remove_timer(PMV_Request req)

+{

+	/* should be using del_timer_sync, but ... HBA->lock ... */

+	if ( req->eh_timeout.function ) {

+		del_timer(&req->eh_timeout);

+		req->eh_timeout.function = NULL;

+#ifdef SUPPORT_REQUEST_TIMER

+		req->err_request_ctx = NULL;

+#endif

+	}

+}

+

+/* for req */

+void hba_add_timer(PMV_Request req, int timeout,

+		   MV_VOID (*function)(MV_PVOID data))

+{

+	WARN_ON(timer_pending(&req->eh_timeout)); 

+	hba_remove_timer(req);

+	req->eh_timeout.data = (unsigned long)req;

+	/* timeout is in unit of second */

+	req->eh_timeout.expires = jiffies + timeout * HZ;

+	req->eh_timeout.function = (void (*)(unsigned long)) function;

+

+	add_timer(&req->eh_timeout);

+	return;

+}

+	

+

+void hba_remove_timer_sync(PMV_Request req)

+{

+	/* should be using del_timer_sync, but ... HBA->lock ... */

+	if ( req->eh_timeout.function ) {

+		del_timer_sync(&req->eh_timeout);

+		req->eh_timeout.function = NULL;

+#ifdef SUPPORT_REQUEST_TIMER

+		req->err_request_ctx = NULL;

+#endif

+	}

+}

+void hba_init_timer(PMV_Request req)

+{

+	/*

+	 * as we have no init routine for req, we'll do init_timer every 

+	 * time it is used until we could uniformly init. all reqs

+	 */

+	req->eh_timeout.function = NULL;

+	init_timer(&req->eh_timeout);

+}

+#endif

+

diff --git a/drivers/scsi/thor/linux/hba_timer.h b/drivers/scsi/thor/linux/hba_timer.h
new file mode 100755
index 0000000..4e3c6c7
--- /dev/null
+++ b/drivers/scsi/thor/linux/hba_timer.h
@@ -0,0 +1,74 @@
+#ifndef __HBA_TIMER_H__

+#define __HBA_TIMER_H__

+

+#include "hba_header.h"

+

+#define HBA_REQ_TIMER_AFTER_RESET 30

+#define HBA_REQ_TIMER 20 

+#define HBA_REQ_TIMER_IOCTL (HBA_REQ_TIMER_AFTER_RESET+3)

+

+#define __hba_init_timer(x) \

+	do {\

+		init_timer(x);\

+		(x)->function = NULL;\

+	} while (0)

+#define __hba_add_timer(x, time, d, func) \

+	do {\

+		(x)->expires = jiffies + time;\

+		(x)->data = (unsigned long)d;\

+		(x)->function = (void (*)(unsigned long))func;\

+		add_timer(x);\

+	} while (0)

+#define __hba_mod_timer(x, time, d, func) \

+	do {\

+		(x)->expires = jiffies + time;\

+		(x)->data = (unsigned long)d;\

+		(x)->function = (void (*)(unsigned long))func;\

+		mod_timer(x, jiffies + time);\

+	} while (0)

+#define __hba_del_timer(x) \

+	do {\

+		if ((x)->function) {\

+			del_timer(x);\

+			(x)->function = NULL;\

+		}\

+	} while (0)

+

+enum _tag_hba_msg_state{

+	MSG_QUEUE_IDLE=0,

+	MSG_QUEUE_PROC

+};

+

+struct mv_hba_msg {

+	MV_PVOID data;

+	MV_U32   msg;

+	MV_U32   param;

+	struct  list_head msg_list;

+};

+

+#define MSG_QUEUE_DEPTH 32

+

+struct mv_hba_msg_queue {

+	spinlock_t lock;

+	struct list_head free;

+	struct list_head tasks;

+	struct mv_hba_msg msgs[MSG_QUEUE_DEPTH];

+};

+

+enum {

+	HBA_TIMER_IDLE = 0,

+	HBA_TIMER_RUNNING,

+	HBA_TIMER_LEAVING,

+};

+void hba_house_keeper_init(void);

+void hba_house_keeper_run(void);

+void hba_house_keeper_exit(void);

+void hba_msg_insert(void *data, unsigned int msg, unsigned int param);

+void hba_init_timer(PMV_Request req);

+void hba_remove_timer(PMV_Request req);

+void hba_remove_timer_sync(PMV_Request req);

+void hba_add_timer(PMV_Request req, int timeout,

+		   MV_VOID (*function)(MV_PVOID data));

+void hba_wait_eh(void);

+

+#endif /* __HBA_TIMER_H__ */

diff --git a/drivers/scsi/thor/linux/linux_iface.c b/drivers/scsi/thor/linux/linux_iface.c
new file mode 100755
index 0000000..e3551ae
--- /dev/null
+++ b/drivers/scsi/thor/linux/linux_iface.c
@@ -0,0 +1,681 @@
+/*

+ *

+ * linux_iface.c - Kernel/CLI interface

+ *

+ */

+

+#include "hba_header.h"

+#include "hba_mod.h"

+#include "hba_timer.h"

+

+#include "linux_iface.h"

+#include "linux_main.h"

+

+

+#define MV_DEVFS_NAME "mv"

+

+#ifdef RAID_DRIVER

+static int mv_open(struct inode *inode, struct file *file);

+#ifdef HAVE_UNLOCKED_IOCTL

+static long mv_ioctl(struct file *file, unsigned int cmd, unsigned long arg);

+#else

+static int mv_ioctl(struct inode *inode, struct file *file, unsigned int cmd,

+		    unsigned long arg);

+#endif /* HAVE_UNLOCKED_IOCTL */

+

+#define IOCTL_BUF_LEN (1024*1024)

+static unsigned char ioctl_buf[IOCTL_BUF_LEN];

+

+static struct file_operations mv_fops = {

+	.owner   =    THIS_MODULE,

+	.open    =    mv_open,

+#ifdef HAVE_UNLOCKED_IOCTL

+	.unlocked_ioctl = mv_ioctl,

+#else

+	.ioctl   =    mv_ioctl,

+#endif

+	.release =    NULL

+};

+#endif /* RAID_DRIVER */

+

+void ioctlcallback(MV_PVOID This, PMV_Request req)

+{

+	struct hba_extension *hba = (struct hba_extension *) This;

+

+	hba->Io_Count--;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_set(&hba->hba_sync, 0);

+#else

+	complete(&hba->cmpl);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+	res_free_req_to_pool(hba->req_pool, req);

+}

+

+#ifdef RAID_DRIVER

+static MV_U16 API2Driver_ID(MV_U16 API_ID)

+{

+	MV_U16	returnID = API_ID;

+	returnID &= 0xfff;

+	return returnID;

+}

+

+static LD_Info ldinfo[LDINFO_NUM] = {{0}};

+static int mv_proc_ld_info(struct Scsi_Host *host)

+{

+	struct hba_extension *hba;

+	PMV_Request req;

+	MV_U8 Cdb[MAX_CDB_SIZE]; 

+	MV_U16 LD_ID = 0XFF;

+	unsigned long flags;

+

+	Cdb[0] = APICDB0_LD;

+	Cdb[1] = APICDB1_LD_GETINFO;

+	Cdb[2] = LD_ID & 0xff;

+	Cdb[3] = API2Driver_ID(LD_ID)>>8;

+	

+	hba = __mv_get_ext_from_host(host);

+	req = res_get_req_from_pool(hba->req_pool);

+	if (req == NULL) {

+		return -1; /*FAIL.*/

+	}

+

+	req->Cmd_Initiator = hba;

+	req->Org_Req = req;

+	req->Device_Id = VIRTUAL_DEVICE_ID;

+	req->Cmd_Flag = 0;

+	req->Req_Type = REQ_TYPE_OS;

+

+	if (SCSI_IS_READ(Cdb[0]))

+		req->Cmd_Flag |= CMD_FLAG_DATA_IN;

+	if (SCSI_IS_READ(Cdb[0]) || SCSI_IS_WRITE(Cdb[0]))

+		req->Cmd_Flag |= CMD_FLAG_DMA;

+	

+	req->Data_Transfer_Length = LDINFO_NUM*sizeof(LD_Info);

+	memset(ldinfo, 0, LDINFO_NUM*sizeof(LD_Info));

+	req->Data_Buffer = ldinfo;

+	SGTable_Init(&req->SG_Table, 0);

+	memcpy(req->Cdb, Cdb, MAX_CDB_SIZE);

+	memset(req->Context, 0, sizeof(MV_PVOID)*MAX_POSSIBLE_MODULE_NUMBER);

+

+	req->LBA.value = 0;    

+	req->Sector_Count = 0; 

+	req->Completion = ioctlcallback;

+	req->Req_Type = REQ_TYPE_INTERNAL;

+

+	spin_lock_irqsave(&hba->desc->hba_desc->global_lock, flags);

+	hba->Io_Count++;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_set(&hba->hba_sync, 1);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+	hba->desc->ops->module_sendrequest(hba->desc->extension, req);

+	spin_unlock_irqrestore(&hba->desc->hba_desc->global_lock, flags);

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	if ( !__hba_wait_for_atomic_timeout(&hba->hba_sync, 

+					    HBA_REQ_TIMER_IOCTL*HZ) ) {

+#else

+	if (wait_for_completion_timeout(&hba->cmpl, 

+					HBA_REQ_TIMER_IOCTL*HZ) == 0) {

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+		MV_DBG(DMSG_HBA, "__MV__ ioctl req timed out.\n");

+	        return -1; /*FAIL.*/

+	}

+

+	return 0;/*SUCCESS.*/

+}

+

+

+static char* mv_ld_status(int status)

+{

+	switch (status) {

+	case LD_STATUS_FUNCTIONAL:

+		return "online";

+	case LD_STATUS_DEGRADE:

+		return "degraded";		

+	case LD_STATUS_DELETED:

+		return "deleted";

+	case LD_STATUS_PARTIALLYOPTIMAL:

+		return "partially optimal";

+	case LD_STATUS_OFFLINE:

+		return "offline";

+	default:

+		return "unknown";

+	}

+}

+

+static char* mv_ld_raid_mode(int status)

+{

+	switch (status) {

+	case LD_MODE_RAID0:

+		return "RAID0";

+	case LD_MODE_RAID1:

+		return "RAID1";

+	case LD_MODE_RAID10:

+		return "RAID10";

+	case LD_MODE_RAID1E:

+		return "RAID1E";

+	case LD_MODE_RAID5:

+		return "RAID5";

+	case LD_MODE_RAID50:

+		return "RAID50";

+	case LD_MODE_RAID6:

+		return "RAID6";

+	case LD_MODE_RAID60:

+		return "RAID60";

+	case LD_MODE_JBOD:

+		return "JBOD";

+	default:

+		return "unknown";	

+	}

+}

+

+static char* mv_ld_bga_status(int status)

+{

+	switch (status) {

+	case LD_BGA_STATE_RUNNING:

+		return "running";

+	case LD_BGA_STATE_ABORTED:

+		return "aborted";

+	case LD_BGA_STATE_PAUSED:

+		return "paused";

+	case LD_BGA_STATE_AUTOPAUSED:

+		return "auto paused";

+	case LD_BGA_STATE_DDF_PENDING:

+		return "DDF pending";

+	default:

+		return "N/A";

+	}

+}

+

+static int mv_ld_get_status(struct Scsi_Host *host, MV_U16 ldid, LD_Status *ldstatus)

+{

+	struct hba_extension *hba;

+	PMV_Request req;

+	MV_U8 Cdb[MAX_CDB_SIZE]; 

+	MV_U16 LD_ID = ldid;/*0XFF;*/

+	unsigned long flags;

+

+	hba = __mv_get_ext_from_host(host);

+	Cdb[0] = APICDB0_LD;

+	Cdb[1] = APICDB1_LD_GETSTATUS;

+	Cdb[2] = LD_ID & 0xff;

+	Cdb[3] = API2Driver_ID(LD_ID)>>8;

+	

+	req = res_get_req_from_pool(hba->req_pool);

+	if (req == NULL)

+		return -1;

+

+	req->Cmd_Initiator = hba;

+	req->Org_Req = req;

+	req->Device_Id = VIRTUAL_DEVICE_ID;

+	req->Cmd_Flag = 0;

+	req->Req_Type = REQ_TYPE_OS;

+

+	if (SCSI_IS_READ(Cdb[0]))

+		req->Cmd_Flag |= CMD_FLAG_DATA_IN;

+	if ( SCSI_IS_READ(Cdb[0]) || SCSI_IS_WRITE(Cdb[0]) )

+		req->Cmd_Flag |= CMD_FLAG_DMA;

+

+	/* Data Buffer */

+	req->Data_Transfer_Length = sizeof(LD_Status);

+	memset(ldstatus, 0, sizeof(LD_Status));

+	ldstatus->Status = LD_STATUS_INVALID;

+	req->Data_Buffer = ldstatus;

+	

+	SGTable_Init(&req->SG_Table, 0);

+	memcpy(req->Cdb, Cdb, MAX_CDB_SIZE);

+	memset(req->Context, 0, sizeof(MV_PVOID)*MAX_POSSIBLE_MODULE_NUMBER);

+	req->LBA.value = 0;    

+	req->Sector_Count = 0; 

+	req->Completion = ioctlcallback;

+	req->Req_Type = REQ_TYPE_INTERNAL;

+	req->Scsi_Status = REQ_STATUS_PENDING;

+

+	spin_lock_irqsave(&hba->desc->hba_desc->global_lock, flags);

+	hba->Io_Count++;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_set(&hba->hba_sync, 1);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+	hba->desc->ops->module_sendrequest(hba->desc->extension, req);

+	spin_unlock_irqrestore(&hba->desc->hba_desc->global_lock, flags);

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	if (!__hba_wait_for_atomic_timeout(&hba->hba_sync, 

+					    HBA_REQ_TIMER_IOCTL*HZ)) {

+#else

+	if (!wait_for_completion_timeout(&hba->cmpl, 

+					  HBA_REQ_TIMER_IOCTL*HZ)) {

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+		MV_DBG(DMSG_HBA, "__MV__ ioctl req timed out.\n");

+	        return -1; /*FAIL.*/

+	}

+

+	return 0;/*SUCCESS.*/

+}

+

+static int mv_ld_show_status(char *buf, PLD_Status pld_status)

+{

+	char *str, *str1;

+	int ret = 0;

+

+	if ( LD_BGA_STATE_RUNNING == pld_status->BgaState)

+	{

+		if (LD_BGA_REBUILD == pld_status->Bga)

+			str = "rebuilding";

+		else if (LD_BGA_INIT_QUICK == pld_status->Bga ||

+		          LD_BGA_INIT_BACK == pld_status->Bga)

+			str = "initializing";

+		else if (LD_BGA_CONSISTENCY_CHECK == pld_status->Bga || 

+		          LD_BGA_CONSISTENCY_FIX == pld_status->Bga)

+			str = "synchronizing";

+		else if (LD_BGA_MIGRATION == pld_status->Bga)

+			str = "migration";

+		else

+			str = "unknown bga action";

+		ret = sprintf(buf, "  %s is %d%% done", str, pld_status->BgaPercentage);

+	}

+	else if ((LD_BGA_STATE_ABORTED == pld_status->BgaState) ||

+	         (LD_BGA_STATE_PAUSED == pld_status->BgaState) || 

+	         (LD_BGA_STATE_AUTOPAUSED == pld_status->BgaState))

+	{

+		if (LD_BGA_REBUILD == pld_status->Bga)

+			str = "rebuilding";

+		else if (LD_BGA_INIT_QUICK == pld_status->Bga ||

+		         LD_BGA_INIT_BACK == pld_status->Bga)

+			str = "initializing";

+		else if (LD_BGA_CONSISTENCY_CHECK == pld_status->Bga ||

+		          LD_BGA_CONSISTENCY_FIX == pld_status->Bga)

+			str = "synchronizing";

+		else if (LD_BGA_MIGRATION == pld_status->Bga)

+			str = "migration";

+		else

+			str = "unknown bga action";

+

+		if (LD_BGA_STATE_ABORTED == pld_status->BgaState)

+			str1 = "aborted";

+		else if (LD_BGA_STATE_PAUSED == pld_status->BgaState)

+			str1 = "paused";

+		else if (LD_BGA_STATE_AUTOPAUSED == pld_status->BgaState)

+			str1 = "auto paused";

+		else

+			str1 = "aborted";

+		ret = sprintf(buf, "  %s is %s", str, str1);

+	}

+	return ret;

+}

+#endif /*RAID_DRIVER*/

+

+int mv_linux_proc_info(struct Scsi_Host *pSHost, char *pBuffer, 

+		       char **ppStart,off_t offset, int length, int inout)

+{

+	int len = 0;

+	int datalen = 0;/*use as a temp flag.*/

+#ifdef RAID_DRIVER

+	int i = 0;

+	int j = 0;

+	int ret = -1;

+	LD_Status ld_status;

+	char *tmp = NULL;

+	int tmplen = 0;

+#endif	

+	if (!pSHost || !pBuffer)

+		return (-ENOSYS);

+

+	if (inout == 1) {

+		/* User write is not supported. */

+		return (-ENOSYS);

+	}

+

+	len = sprintf(pBuffer,"Marvell %s Driver , Version %s\n",

+		      mv_product_name, mv_version_linux);

+	

+#ifdef RAID_DRIVER

+	if (mv_proc_ld_info(pSHost) == -1) {

+		len = sprintf(pBuffer,

+			      "Driver is busy, please try later.\n");

+		goto out;

+	} else {

+		for (i = 0; i < MAX_LD_SUPPORTED_PERFORMANCE; i++) {

+			if (ldinfo[i].Status != LD_STATUS_INVALID) {

+				if (ldinfo[i].Status == LD_STATUS_OFFLINE

+				        && ldinfo[i].BGAStatus == LD_BGA_STATE_RUNNING) {

+					ldinfo[i].BGAStatus = LD_BGA_STATE_AUTOPAUSED;

+				}

+				if (ldinfo[i].Status == LD_STATUS_MISSING) {

+					ldinfo[i].Status = LD_STATUS_OFFLINE;

+				}

+			} else {

+				break;

+			}

+		}

+	}

+	

+	len += sprintf(pBuffer+len,"Index RAID\tStatus  \t\tBGA Status\n");

+	for (i = 0 ; i < LDINFO_NUM ; i++) {

+		if (ldinfo[i].Size.value == 0) {

+			if (i == 0) {

+				len += sprintf(pBuffer+len,"NO Logical Disk\n");

+			}

+			break;

+		}

+

+		len += sprintf(pBuffer+len,

+			"%-5d %s\t%s",

+			ldinfo[i].ID,

+			mv_ld_raid_mode(ldinfo[i].RaidMode),

+			mv_ld_status(ldinfo[i].Status)

+			);

+

+		tmplen = 24 -strlen(mv_ld_status(ldinfo[i].Status));

+		while (j < tmplen) {

+			len += sprintf(pBuffer+len, "%s", " ");

+			j++;

+		}

+		j = 0;

+

+		len += sprintf(pBuffer+len, "%s", mv_ld_bga_status(ldinfo[i].BGAStatus));

+

+		if (ldinfo[i].BGAStatus != LD_BGA_STATE_NONE) {

+			ret = mv_ld_get_status(pSHost,ldinfo[i].ID,&ld_status);

+			if (ret == 0) {

+				if (ld_status.Status != LD_STATUS_INVALID) {

+					if (ld_status.Status == LD_STATUS_MISSING)

+						ld_status.Status = LD_STATUS_OFFLINE;

+					ld_status.BgaState = ldinfo[i].BGAStatus;

+				}

+				len += mv_ld_show_status(pBuffer+len,&ld_status);

+				ret = -1;

+			}

+		}

+

+		tmp = NULL;

+		tmplen = 0;

+		len += sprintf(pBuffer+len,"\n");

+	}

+

+out:

+#endif

+		

+	datalen = len - offset;

+	if (datalen < 0) {

+		datalen = 0;

+		*ppStart = pBuffer + len;

+	} else {

+		*ppStart = pBuffer + offset;

+	}

+	return datalen;

+} 

+

+/*

+ *Character Device Interface.

+ */

+#ifdef RAID_DRIVER

+static int mv_open(struct inode *inode, struct file *file)

+{

+	unsigned int minor_number;

+	int retval = -ENODEV;

+	unsigned long flags = 0;

+	

+	spin_lock_irqsave(&inode->i_lock, flags);

+	minor_number = MINOR(inode->i_rdev);

+	if (minor_number >= __mv_get_adapter_count()) {

+		printk("MV : No such device.\n");

+		goto out;

+	}

+	retval = 0;

+out:

+	spin_unlock_irqrestore(&inode->i_lock, flags);

+	return retval;

+}

+

+static dev_t _mv_major = 0;

+

+int mv_register_chdev(struct hba_extension *hba)

+{

+	int ret = 0;

+	dev_t num;

+

+	/*

+	 * look for already-allocated major number first, if not found or

+	 * fail to register, try allocate one .

+	 *

+	 */

+	if (_mv_major)

+	{

+		ret = register_chrdev_region(MKDEV(_mv_major,

+						   hba->desc->hba_desc->id),

+					     1,

+					     MV_DEVFS_NAME);

+		num = MKDEV(_mv_major, hba->desc->hba_desc->id);

+	}

+	if(ret)

+	{

+		MV_DBG(DMSG_KERN, "registered chrdev (%d, %d) failed.\n",

+	       	_mv_major, hba->desc->hba_desc->id);

+		return	ret;

+	}

+	if (ret || !_mv_major) {

+		ret = alloc_chrdev_region(&num,

+					  hba->desc->hba_desc->id,

+					  1,

+					  MV_DEVFS_NAME);

+		if (ret)

+		{

+			MV_DBG(DMSG_KERN, "allocate chrdev (%d, %d) failed.\n",

+		       	MAJOR(num), hba->desc->hba_desc->id);

+			return ret;

+		}

+		else

+			_mv_major = MAJOR(num);

+	}

+

+	memset(&hba->cdev, 0, sizeof(struct cdev));

+	cdev_init(&hba->cdev, &mv_fops);

+	hba->cdev.owner = THIS_MODULE;

+	hba->desc->hba_desc->dev_no = num;

+	MV_DBG(DMSG_KERN, "registered chrdev (%d, %d).\n",

+	       MAJOR(num), MINOR(num));

+	ret = cdev_add(&hba->cdev, num, 1);

+

+	return ret;

+}

+

+void mv_unregister_chdev(struct hba_extension *hba)

+{

+	cdev_del(&hba->cdev);

+	unregister_chrdev_region(hba->desc->hba_desc->dev_no, 1);

+}

+

+#ifdef HAVE_UNLOCKED_IOCTL

+static long mv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

+#else

+static int mv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 

+		    unsigned long arg)

+#endif /* HAVE_UNLOCKED_IOCTL */ 

+{

+	struct hba_extension	*hba;

+	PMV_Request    req = NULL;

+	int error = 0;

+	int ret   = 0;

+	int sptdwb_size = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);

+	int console_id  = VIRTUAL_DEVICE_ID;

+	unsigned long flags;

+	PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER psptdwb = NULL;

+	int mv_device_count;

+	struct scsi_idlun idlun;

+	

+#ifdef HAVE_UNLOCKED_IOCTL

+	hba = container_of(file->f_dentry->d_inode->i_cdev,

+			   struct hba_extension, cdev);

+#else

+	hba = container_of(inode->i_cdev,

+			   struct hba_extension, cdev);

+#endif /* HAVE_UNLOCKED_IOCTL */ 

+	/*if the driver is shutdown ,any process shouldn't call mv_ioctl*/

+	if(hba != NULL) {

+		if(DRIVER_STATUS_SHUTDOWN== hba->State ) {

+			MV_DBG(DMSG_IOCTL, "Marvell : Driver had been rmmoded ,Invalid operation.\n");

+			return -EPERM;

+		}	

+	} else {

+		MV_DBG(DMSG_IOCTL, "Marvell : Driver is not installed ,Invalid operation.\n");

+		return -EPERM;

+	}

+	mv_device_count =  __mv_get_adapter_count();

+		if (cmd >= API_IOCTL_MAX) {

+			MV_DBG(DMSG_IOCTL, "Marvell : Invalid ioctl command.\n");

+			return -EBADF;

+	}

+	

+	if (cmd == API_IOCTL_GET_VIRTURL_ID) {

+		if (copy_to_user((void *)arg,(void *)&console_id,sizeof(int)) != 0 ) {

+			MV_DBG(DMSG_IOCTL, "Marvell : Get VIRTUAL_DEVICE_ID Error.\n");

+			return -EIO;

+		}

+		return 0;

+	}

+

+	if (cmd == API_IOCTL_GET_HBA_COUNT) {

+		if (copy_to_user((void *)arg,(void *)&mv_device_count,sizeof(unsigned int)) != 0) {

+			MV_DBG(DMSG_IOCTL, "Marvell : Get Device Number Error.\n");

+			return -EIO;

+		}

+		return 0;

+	}

+

+	if (cmd == API_IOCTL_LOOKUP_DEV) {

+		if( copy_from_user(&idlun, (void *)arg, sizeof(struct scsi_idlun)) !=0) {

+			MV_DBG(DMSG_IOCTL, "Marvell : Get Device idlun Error.\n");

+			return -EIO;

+		}

+		

+		/*To check host no, if fail, return EFAULT (Bad address) */

+		if (hba->host->host_no != ((idlun.dev_id) >> 24)) {

+			MV_DBG(DMSG_IOCTL, "Marvell : lookup device host number error .\n");

+			return EFAULT;

+		}

+		return 0;

+	}

+	

+

+	psptdwb = kmalloc(sptdwb_size, GFP_ATOMIC);

+	

+	if ( NULL == psptdwb ) 

+		return -ENOMEM;

+

+	error = copy_from_user(psptdwb, (void *)arg, sptdwb_size);

+

+	if (error) {

+		ret = -EIO;

+		goto clean_psp;

+	}

+

+	if (psptdwb->sptd.DataTransferLength) {

+		if (psptdwb->sptd.DataTransferLength > IOCTL_BUF_LEN) {

+			MV_DBG(DMSG_IOCTL, "__MV__ not enough buf space.\n");

+			ret = -ENOMEM;

+			goto clean_psp;

+		}

+			

+		psptdwb->sptd.DataBuffer = ioctl_buf;

+		memset(ioctl_buf, 0, psptdwb->sptd.DataTransferLength);

+		

+		error = copy_from_user( psptdwb->sptd.DataBuffer,

+					((PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)arg)->sptd.DataBuffer,

+					psptdwb->sptd.DataTransferLength);

+		if (error) {

+			ret = -EIO;

+			goto clean_pspbuf;

+		}

+	} else {

+		psptdwb->sptd.DataBuffer = NULL;

+	}

+	

+	/*Translate request to MV_REQUEST*/

+	req = res_get_req_from_pool(hba->req_pool);

+	if (NULL == req) {

+		ret = -ENOMEM;

+		goto clean_pspbuf;

+	}

+

+	req->Cmd_Initiator = hba;

+	req->Org_Req = req;

+	req->Scsi_Status = psptdwb->sptd.ScsiStatus;

+	req->Device_Id = psptdwb->sptd.TargetId;

+	req->Cmd_Flag = 0;

+	req->Req_Type = REQ_TYPE_INTERNAL;

+

+	if (psptdwb->sptd.DataTransferLength == 0) {

+		req->Cmd_Flag |= CMD_FLAG_NON_DATA;

+	} else {

+		if (SCSI_IS_READ(psptdwb->sptd.Cdb[0]))

+			req->Cmd_Flag |= CMD_FLAG_DATA_IN;

+		if (SCSI_IS_READ(psptdwb->sptd.Cdb[0]) || SCSI_IS_WRITE(psptdwb->sptd.Cdb[0]))

+			req->Cmd_Flag |= CMD_FLAG_DMA;

+	}

+

+	req->Data_Transfer_Length = psptdwb->sptd.DataTransferLength;

+	req->Data_Buffer = psptdwb->sptd.DataBuffer;

+	req->Sense_Info_Buffer = psptdwb->Sense_Buffer;

+

+	SGTable_Init(&req->SG_Table, 0);

+	

+	memcpy(req->Cdb, psptdwb->sptd.Cdb, MAX_CDB_SIZE);

+	memset(req->Context, 0, sizeof(MV_PVOID)*MAX_POSSIBLE_MODULE_NUMBER);

+	req->LBA.value = 0;    

+	req->Sector_Count = 0; 

+	req->Completion = ioctlcallback;

+

+	spin_lock_irqsave(&hba->desc->hba_desc->global_lock, flags);

+    	hba->Io_Count++;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	atomic_set(&hba->hba_sync, 1);

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+	hba->desc->ops->module_sendrequest(hba->desc->extension, req);

+	spin_unlock_irqrestore(&hba->desc->hba_desc->global_lock, flags);

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)

+	if (!__hba_wait_for_atomic_timeout(&hba->hba_sync, 

+					    HBA_REQ_TIMER_IOCTL*HZ)) {

+#else

+	if (!wait_for_completion_timeout(&hba->cmpl, 

+					  HBA_REQ_TIMER_IOCTL*HZ)) {

+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */

+		MV_DBG(DMSG_HBA, "__MV__ ioctl req timed out.\n");

+	        ret = -EIO;

+	        goto clean_pspbuf;

+	}

+

+	if (psptdwb->sptd.DataTransferLength) {

+		error = copy_to_user(((PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)arg)->sptd.DataBuffer,

+				     psptdwb->sptd.DataBuffer,

+				     psptdwb->sptd.DataTransferLength);

+		if (error) {

+			ret = -EIO;

+			goto clean_pspbuf;

+		}

+	}

+

+	error = copy_to_user((void*)arg, psptdwb, sptdwb_size);

+	

+	if (error) {

+		ret = -EIO;

+		goto clean_pspbuf;

+	}

+

+	if (req->Scsi_Status)

+		ret = req->Scsi_Status;

+	

+	if (req->Scsi_Status == REQ_STATUS_INVALID_PARAMETER)

+		ret = -EPERM;

+	

+clean_pspbuf:

+/* use static buf instead.*/

+clean_psp:

+	kfree(psptdwb);

+	return ret;

+}

+#else  /* RAID_DRIVER */

+inline int mv_register_chdev(struct hba_extension *hba) {return 0;}

+inline void mv_unregister_chdev(struct hba_extension *hba) {}

+#endif /* RAID_DRIVER */

diff --git a/drivers/scsi/thor/linux/linux_iface.h b/drivers/scsi/thor/linux/linux_iface.h
new file mode 100755
index 0000000..e3bcc93
--- /dev/null
+++ b/drivers/scsi/thor/linux/linux_iface.h
@@ -0,0 +1,56 @@
+/*

+ *

+ *  Kernel/CLI interface

+ *

+ */

+

+#ifndef __MV_HBA_LINUX_INTERFACE__

+#define __MV_HBA_LINUX_INTERFACE__

+

+#include "com_define.h"

+#include "com_struct.h"

+#include "com_api.h"

+#include "com_scsi.h"

+#include "com_util.h"

+

+/*Request Structure.*/

+#define SENSE_INFO_BUFFER_SIZE		32

+#define MAX_COMMAND_SIZE		16

+

+/* For Character Device Interface */

+#define MV_DEVICE_MAX_SLOT 4

+

+#define LDINFO_NUM (MAX_LD_SUPPORTED_PERFORMANCE * MAX_NUM_ADAPTERS)

+#define HDINFO_NUM (MAX_DEVICE_SUPPORTED_PERFORMANCE * MAX_NUM_ADAPTERS)

+

+typedef struct _SCSI_PASS_THROUGH_DIRECT {

+	unsigned short Length;

+	unsigned char  ScsiStatus;

+	unsigned char  PathId;

+	unsigned char  TargetId;

+	unsigned char  Lun;

+	unsigned char  CdbLength;

+	unsigned char  SenseInfoLength;

+	unsigned char  DataIn;

+	unsigned long  DataTransferLength;

+	unsigned long  TimeOutValue;

+	void           *DataBuffer;

+	unsigned long  SenseInfoOffset;

+	unsigned char  Cdb[16];

+}SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;

+

+typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER{

+	SCSI_PASS_THROUGH_DIRECT        sptd;

+	unsigned long                   Filler;

+	unsigned char                   Sense_Buffer[SENSE_INFO_BUFFER_SIZE];

+}SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;

+

+int mv_linux_proc_info(struct Scsi_Host *pSHost, char *pBuffer, 

+		       char **ppStart,  off_t offset, int length, int inout);

+

+void IOHBARequestCallback(MV_PVOID This, PMV_Request pReq);

+

+int mv_register_chdev(struct hba_extension *hba);

+void mv_unregister_chdev(struct hba_extension *hba);

+

+#endif /* ifndef __MV_HBA_LINUX_INTERFACE__ */

diff --git a/drivers/scsi/thor/linux/linux_main.c b/drivers/scsi/thor/linux/linux_main.c
new file mode 100755
index 0000000..fb54aa8
--- /dev/null
+++ b/drivers/scsi/thor/linux/linux_main.c
@@ -0,0 +1,221 @@
+/*

+ *

+ *  Copyright (C) 2006 Marvell Technology Group Ltd. All Rights Reserved.

+ *  linux_main.c

+ *

+ *

+ */

+

+#include "mv_include.h"

+#include "hba_header.h"

+#include "linux_main.h"

+

+#include "hba_exp.h"

+

+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 7)

+unsigned int mv_dbg_opts = 0;

+module_param(mv_dbg_opts, uint, S_IRWXU | S_IRWXG);

+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 7) */

+

+static const struct pci_device_id mv_pci_ids[] = {

+#ifdef ODIN_DRIVER

+	{PCI_DEVICE(VENDOR_ID, DEVICE_ID_6320)},

+	{PCI_DEVICE(VENDOR_ID, DEVICE_ID_6340)},

+	{PCI_DEVICE(VENDOR_ID, DEVICE_ID_6440)},

+	{PCI_DEVICE(VENDOR_ID, DEVICE_ID_6480)},

+	{0}

+#endif

+

+#ifdef THOR_DRIVER

+	{PCI_DEVICE(VENDOR_ID, DEVICE_ID_THORLITE_0S1P)},

+	{PCI_DEVICE(VENDOR_ID, DEVICE_ID_THORLITE_2S1P)},

+	{PCI_DEVICE(VENDOR_ID, DEVICE_ID_THOR_4S1P)},

+	{PCI_DEVICE(VENDOR_ID, DEVICE_ID_THOR_4S1P_NEW)},

+	{PCI_DEVICE(VENDOR_ID,

+	           DEVICE_ID_THORLITE_2S1P_WITH_FLASH)},

+	{0}

+#endif

+

+};

+

+/* notifier block to get notified on system shutdown/halt/reboot/down */

+static int mv_linux_halt(struct notifier_block *nb, unsigned long event,

+			 void *buf)

+{

+	switch (event) {

+	case SYS_RESTART:

+	case SYS_HALT:

+	case SYS_POWER_OFF:

+		mv_hba_stop(NULL);

+		break;

+	default:

+		break;

+	}

+

+	return NOTIFY_OK;

+}

+

+static struct notifier_block mv_linux_notifier = {

+	mv_linux_halt, NULL, 0

+};

+

+#define Vendor_Unique_Register_2 0x44

+

+static int mv_probe(struct pci_dev *dev, const struct pci_device_id *id)

+{

+	unsigned int ret = PCIBIOS_SUCCESSFUL;

+	int err = 0;

+	unsigned char reg44;

+	

+	ret = pci_enable_device(dev);

+	if (ret) {

+		MV_PRINT(" enable device failed.\n");

+		return ret;

+	}

+

+	ret = pci_request_regions(dev, mv_driver_name);

+	if (ret)

+		goto err_req_region;

+	

+	

+	if ( !pci_set_dma_mask(dev, MV_DMA_BIT_MASK_64) ) {

+		ret = pci_set_consistent_dma_mask(dev, MV_DMA_BIT_MASK_64);

+		if (ret) {

+			ret = pci_set_consistent_dma_mask(dev, 

+							  MV_DMA_BIT_MASK_32);

+			if (ret)

+				goto err_dma_mask;

+		}

+	} else {

+		ret = pci_set_dma_mask(dev, MV_DMA_BIT_MASK_32);

+		if (ret)

+			goto err_dma_mask;

+		

+		ret = pci_set_consistent_dma_mask(dev, MV_DMA_BIT_MASK_32);

+		if (ret) 

+			goto err_dma_mask;

+		

+	}

+		

+	pci_set_master(dev);

+	

+	pci_read_config_byte(dev,Vendor_Unique_Register_2,&reg44);

+	reg44 |= MV_BIT(6); /* oscillation 10k HZ */

+	pci_write_config_byte(dev,Vendor_Unique_Register_2,reg44);

+

+	printk("Marvell Storage Controller is found, using IRQ %d.\n",

+	       dev->irq);

+

+	ret = mv_hba_init(dev, MV_MAX_IO);

+	if (ret) {

+		MV_DBG(DMSG_HBA, "Error no %d.\n", ret);

+		ret = -ENOMEM;

+		goto err_dma_mask;

+	}

+

+	MV_DPRINT(("Start mv_hba_start.\n"));

+

+	if (mv_hba_start(dev)) {

+		ret = -ENODEV;

+		goto err_mod_start;

+	}

+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12))	

+	if (__mv_get_adapter_count() == 1) {

+		register_reboot_notifier(&mv_linux_notifier); 

+	}

+#endif

+	MV_DPRINT(("Finished mv_probe.\n"));

+

+	return 0;

+err_mod_start:

+	err++;

+	mv_hba_stop(dev);

+	mv_hba_release(dev);

+err_dma_mask:

+	err++;

+	pci_release_regions(dev);

+err_req_region:

+	err++;

+	pci_disable_device(dev);

+

+	MV_PRINT(" error counter %d.\n", err);

+	return ret;

+}

+

+static void __devexit mv_remove(struct pci_dev *dev)

+{

+	mv_hba_stop(dev);

+	mv_hba_release(dev);

+	

+	pci_release_regions(dev);

+	pci_disable_device(dev);

+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12))

+	if (__mv_get_adapter_count() == 0) {

+		unregister_reboot_notifier(&mv_linux_notifier);

+	}

+#endif

+	MV_DPRINT(("Marvell linux driver removed !\n"));

+}

+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))

+static void mv_shutdown(struct pci_dev *pdev)

+{

+	MV_DPRINT(("%s\n",__func__));

+	mv_hba_stop(pdev);	

+}

+#endif

+static struct pci_driver mv_pci_driver = {

+	.name     = "mv_"mv_driver_name,

+	.id_table = mv_pci_ids,

+	.probe    = mv_probe,

+	.remove   = __devexit_p(mv_remove),

+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))

+	.shutdown = mv_shutdown,

+#endif

+};

+

+static int __init mv_linux_driver_init(void)

+{

+        /* default to show no msg */

+#ifdef __MV_DEBUG__

+	//mv_dbg_opts |= (DMSG_CORE|DMSG_HBA|DMSG_KERN|DMSG_SCSI|DMSG_FREQ);

+	mv_dbg_opts |= (DMSG_CORE|DMSG_HBA|DMSG_KERN|DMSG_SCSI);

+	mv_dbg_opts |= (DMSG_CORE_EH|DMSG_RAID|DMSG_SAS|DMSG_RES);

+

+	//mv_dbg_opts |= DMSG_PROF_FREQ; 

+	//mv_dbg_opts |= DMSG_SCSI_FREQ;

+

+#endif /* __MV_DEBUG__ */

+	hba_house_keeper_init();

+	

+	return pci_register_driver(&mv_pci_driver);

+}

+

+static void __exit mv_linux_driver_exit(void)

+{

+	pci_unregister_driver(&mv_pci_driver);

+	hba_house_keeper_exit();

+}

+

+MODULE_AUTHOR ("Marvell Technolog Group Ltd.");

+#ifdef ODIN_DRIVER

+MODULE_DESCRIPTION ("ODIN SAS hba driver");

+

+#ifdef RAID_DRIVER

+MODULE_LICENSE("Proprietary");

+#else /* RAID_DRIVER */

+MODULE_LICENSE("GPL"); 

+#endif /* RAID_DRIVER */

+#endif

+

+#ifdef THOR_DRIVER

+MODULE_DESCRIPTION ("Thor ATA HBA Driver");

+

+MODULE_LICENSE("Proprietary");

+

+#endif

+

+MODULE_DEVICE_TABLE(pci, mv_pci_ids);

+

+module_init(mv_linux_driver_init);

+module_exit(mv_linux_driver_exit);

+

diff --git a/drivers/scsi/thor/linux/linux_main.h b/drivers/scsi/thor/linux/linux_main.h
new file mode 100755
index 0000000..d12b947
--- /dev/null
+++ b/drivers/scsi/thor/linux/linux_main.h
@@ -0,0 +1,49 @@
+#ifndef _LINUX_MAIN_H

+#define _LINUX_MAIN_H

+

+#include "hba_header.h"

+

+#define __mv_get_ext_from_host(phost) \

+          (((struct hba_extension **) (phost)->hostdata)[0])

+

+/* for communication with OS/SCSI mid layer only */

+enum {

+#ifdef RAID_DRIVER

+	MV_MAX_REQUEST_DEPTH     = MAX_REQUEST_NUMBER_PERFORMANCE - 2,

+	MV_MAX_IO                = MAX_REQUEST_NUMBER_PERFORMANCE,

+#else /* RAID_DRIVER */

+	MV_MAX_REQUEST_DEPTH     = MAX_CORE_REQUEST_NUMBER_PERFORMANCE - 2,

+	MV_MAX_IO                = MAX_CORE_REQUEST_NUMBER_PERFORMANCE,

+#endif /* RAID_DRIVER */

+	MV_MAX_REQUEST_PER_LUN   = 32,

+	MV_MAX_SG_ENTRY          = 32,

+

+	MV_SHT_USE_CLUSTERING    = DISABLE_CLUSTERING,

+	MV_SHT_EMULATED          = 0,

+	MV_SHT_THIS_ID           = -1,

+};

+

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)

+#define mv_scmd_host(cmd)    cmd->device->host

+#define mv_scmd_channel(cmd) cmd->device->channel

+#define mv_scmd_target(cmd)  cmd->device->id

+#define mv_scmd_lun(cmd)     cmd->device->lun

+#else

+#define mv_scmd_host(cmd)    cmd->host

+#define mv_scmd_channel(cmd) cmd->channel

+#define mv_scmd_target(cmd)  cmd->target

+#define mv_scmd_lun(cmd)     cmd->lun

+#endif

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)	

+#define MV_DMA_BIT_MASK_64 DMA_64BIT_MASK

+#define MV_DMA_BIT_MASK_32 DMA_32BIT_MASK

+#else

+#define MV_DMA_BIT_MASK_64 DMA_BIT_MASK(64)

+#define MV_DMA_BIT_MASK_32 DMA_BIT_MASK(32)

+#endif

+

+#define LO_BUSADDR(x) ((MV_U32)(x))

+#define HI_BUSADDR(x) (sizeof(BUS_ADDRESS)>4? (u64)(x) >> 32 : 0)

+

+#endif /*_LINUX_MAIN_H*/

+

diff --git a/drivers/scsi/thor/linux/mv_os.h b/drivers/scsi/thor/linux/mv_os.h
new file mode 100755
index 0000000..1383dae
--- /dev/null
+++ b/drivers/scsi/thor/linux/mv_os.h
@@ -0,0 +1,208 @@
+#if !defined(LINUX_OS_H)

+#define LINUX_OS_H

+

+#ifndef LINUX_VERSION_CODE

+#   include <linux/version.h>

+#endif

+

+#ifndef AUTOCONF_INCLUDED

+#   include <linux/config.h>

+#endif /* AUTOCONF_INCLUDED */

+

+#include <linux/list.h>

+#include <linux/module.h>

+#include <linux/interrupt.h>

+#include <linux/kernel.h>

+#include <linux/errno.h>

+#include <linux/types.h>

+#include <linux/string.h>

+#include <linux/timer.h>

+#include <linux/time.h>

+#include <linux/reboot.h>

+#include <linux/ioport.h>

+#include <linux/delay.h>

+#include <linux/proc_fs.h>

+#include <linux/stat.h>

+#include <linux/cdev.h>

+#include <linux/spinlock.h>

+#include <linux/pci.h>

+#include <linux/completion.h>

+#include <linux/blkdev.h>

+#include <linux/vmalloc.h>

+#include <linux/kthread.h>

+#include <linux/nmi.h>

+

+#include <asm/uaccess.h>

+#include <asm/io.h>

+#include <asm/div64.h>

+

+#include <scsi/scsi.h>

+#include <scsi/scsi_cmnd.h>

+#include <scsi/scsi_device.h>

+#include <scsi/scsi_host.h>

+#include <scsi/scsi_transport.h>

+#include <scsi/scsi_ioctl.h>

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)

+#include <scsi/scsi_request.h>

+#endif

+

+/* OS specific flags */

+#define  _OS_LINUX            1

+#define _64_BIT_COMPILER      1

+#ifdef USE_NEW_SGTABLE

+#define USE_NEW_SGVP

+#endif /* USE_NEW_SGTABLE */

+

+#ifdef CONFIG_64BIT

+#   define __KCONF_64BIT__

+#endif /* CONFIG_64BIT */

+

+#if defined(__LITTLE_ENDIAN)

+#   define __MV_LITTLE_ENDIAN__  1

+#elif defined(__BIG_ENDIAN)

+#   define __MV_BIG_ENDIAN__     1

+#else

+#   error "error in endianness"

+#endif 

+

+#if defined(__LITTLE_ENDIAN_BITFIELD)

+#   define __MV_LITTLE_ENDIAN_BITFIELD__   1

+#elif defined(__BIG_ENDIAN_BITFIELD)

+#   define __MV_BIG_ENDIAN_BITFIELD__      1

+#else

+#   error "error in endianness"

+#endif 

+

+#ifdef __MV_DEBUG__

+#   define MV_DEBUG

+#else

+#   ifdef MV_DEBUG

+#      undef MV_DEBUG

+#   endif /* MV_DEBUG */

+#endif /* __MV_DEBUG__ */

+

+#ifndef NULL

+#   define NULL 0

+#endif

+

+/* Values for T10/04-262r7 */

+#ifndef ATA_16 

+#	define ATA_16                0x85      /* 16-byte pass-thru */

+#endif

+#ifndef ATA_12

+#	define ATA_12                0xa1      /* 12-byte pass-thru */

+#endif

+

+

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)

+#define PCI_D0 0

+#include <linux/suspend.h>

+typedef u32 pm_message_t; 

+

+static inline int try_to_freeze(unsigned long refrigerator_flags)

+{

+        if (unlikely(current->flags & PF_FREEZE)) {

+               refrigerator(refrigerator_flags);

+                return 1;

+        } else

+             return 0;

+}

+#endif

+

+/*

+ *

+ * Primary Data Type Definition 

+ *

+ */

+#include "com_define.h" 

+

+#define MV_INLINE inline

+#define CDB_INQUIRY_EVPD    1 

+

+

+typedef void (*OSSW_TIMER_FUNCTION)(unsigned long);

+typedef  void (*CORE_TIMER_FUNCTION)(void *);

+typedef  void (*OS_TIMER_FUNCTION)(void *);

+

+typedef unsigned long OSSW_TIMER_DATA;

+

+/* OS macro definition */

+#define MV_MAX_TRANSFER_SECTOR  (MV_MAX_TRANSFER_SIZE >> 9)

+

+/*Driver Version for Command Line Interface Query.*/

+#  define VER_MAJOR           1

+

+

+#   define VER_MINOR        2

+#   define VER_BUILD        24

+

+#ifdef __OEM_INTEL__

+#   define VER_OEM          VER_OEM_INTEL

+#elif defined(__OEM__ASUS__)

+#   define VER_OEM          VER_OEM_ASUS

+#else

+#   define VER_OEM         VER_OEM_GENERIC

+#endif /* __OEM_INTEL__ */

+

+

+#ifdef RAID_DRIVER

+#   define VER_TEST         ""

+#else

+#   define VER_TEST         "N"

+#endif /* RAID_DRIVER */

+#ifdef ODIN_DRIVER

+#define mv_driver_name   "mv64xx"

+

+#define mv_product_name  "ODIN"

+#endif

+

+#ifdef THOR_DRIVER

+#define mv_driver_name   "mv61xx"

+

+#define mv_product_name  "THOR"

+#endif

+

+/* call VER_VAR_TO_STRING */

+#define NUM_TO_STRING(num1, num2, num3, num4) #num1"."#num2"."#num3"."#num4

+#define VER_VAR_TO_STRING(major, minor, oem, build) NUM_TO_STRING(major, \

+								  minor, \

+								  oem,   \

+								  build)

+

+#define mv_version_linux   VER_VAR_TO_STRING(VER_MAJOR, VER_MINOR,       \

+					     VER_OEM, VER_BUILD) VER_TEST

+

+#define CPU_TO_LE_16 cpu_to_le16

+#define CPU_TO_LE_32 cpu_to_le32

+#define LE_TO_CPU_16 le16_to_cpu

+#define LE_TO_CPU_32 le32_to_cpu

+

+#ifndef scsi_to_pci_dma_dir

+#define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir))

+#endif

+

+#ifndef TRUE

+#define TRUE 	1

+#define FALSE	0

+#endif

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)

+#define map_sg_page(sg)		kmap_atomic(sg->page, KM_IRQ0)	

+#define map_sg_page_sec(sg)		kmap_atomic(sg->page, KM_IRQ1)	

+#else

+#define map_sg_page(sg)		kmap_atomic(sg_page(sg), KM_IRQ0)	

+#define map_sg_page_sec(sg)		kmap_atomic(sg_page(sg), KM_IRQ1)	

+#endif

+

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)

+#define mv_use_sg(cmd)	cmd->use_sg

+#define mv_rq_bf(cmd)	cmd->request_buffer

+#define mv_rq_bf_l(cmd)	cmd->request_bufflen

+#else

+#define mv_use_sg(cmd)	scsi_sg_count(cmd)

+#define mv_rq_bf(cmd)	scsi_sglist(cmd)

+#define mv_rq_bf_l(cmd)	scsi_bufflen(cmd)

+#endif

+

+#endif /* LINUX_OS_H */

diff --git a/drivers/scsi/thor/linux/oss_wrapper.c b/drivers/scsi/thor/linux/oss_wrapper.c
new file mode 100755
index 0000000..ac8a505
--- /dev/null
+++ b/drivers/scsi/thor/linux/oss_wrapper.c
@@ -0,0 +1,112 @@
+#include "hba_header.h"

+

+MV_U8 ossw_add_timer(struct timer_list *timer,

+		    u32 msec, 

+		    void (*function)(unsigned long),

+		    unsigned long data)

+{

+	u64 jif;

+

+	if(timer_pending(timer))

+		del_timer(timer);

+

+	timer->function = function;

+	timer->data     = data;

+

+	jif = (u64) (msec * HZ);

+	do_div(jif, 1000);         /* wait in unit of second */

+	timer->expires = jiffies + 1 + jif;

+

+	add_timer(timer);

+	return	0;

+}

+

+void ossw_del_timer(struct timer_list *timer)

+{

+	if (timer->function)

+		del_timer(timer);

+	timer->function = NULL;

+}

+

+u32 ossw_get_time_in_sec(void)

+{

+	struct timeval tv;

+

+	do_gettimeofday(&tv);

+	return (u32) tv.tv_sec;

+}

+

+u32 ossw_get_msec_of_time(void)

+{

+	struct timeval tv;

+

+	do_gettimeofday(&tv);

+	return (u32) tv.tv_usec*1000*1000;

+}

+

+#if __LEGACY_OSSW__

+//reset nmi watchdog before delay

+static void mv_touch_nmi_watchdog(void)

+{

+#ifdef CONFIG_X86_64

+	touch_nmi_watchdog();

+#endif /* CONFIG_X86_64*/

+

+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)

+	touch_softlockup_watchdog();

+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13) */

+}	

+

+void HBA_SleepMillisecond(MV_PVOID ext, MV_U32 msec)

+{

+	MV_U32	tmp=0;

+	MV_U32	mod_msec=2000;

+	if (in_softirq()||in_interrupt() || irqs_disabled()){

+		mv_touch_nmi_watchdog();

+		if (msec<=mod_msec)

+			ossw_mdelay(msec);

+		else

+		{

+			for(tmp=0;tmp<msec/mod_msec;tmp++)

+			{

+				ossw_mdelay(mod_msec);

+				mv_touch_nmi_watchdog();

+			}

+			if (msec%mod_msec)

+				ossw_mdelay(msec%mod_msec);

+		}

+		mv_touch_nmi_watchdog();

+	}else {

+		set_current_state(TASK_UNINTERRUPTIBLE);

+		schedule_timeout( msecs_to_jiffies(msec) );

+	}

+}

+

+

+void hba_msleep(MV_U32 msec)

+{

+	MV_U32	tmp=0;

+	MV_U32	mod_msec=2000;

+	if (in_softirq()||in_interrupt() || irqs_disabled()){

+		mv_touch_nmi_watchdog();

+		if (msec<=mod_msec)

+			ossw_mdelay(msec);

+		else

+		{

+			for(tmp=0;tmp<msec/mod_msec;tmp++)

+			{

+				ossw_mdelay(mod_msec);

+				mv_touch_nmi_watchdog();

+			}

+			if (msec%mod_msec)

+				ossw_mdelay(msec%mod_msec);

+		}

+		mv_touch_nmi_watchdog();

+	}else {

+		set_current_state(TASK_UNINTERRUPTIBLE);

+		schedule_timeout( msecs_to_jiffies(msec));

+	}

+}

+

+#endif

+

diff --git a/drivers/scsi/thor/linux/oss_wrapper.h b/drivers/scsi/thor/linux/oss_wrapper.h
new file mode 100755
index 0000000..569b74c
--- /dev/null
+++ b/drivers/scsi/thor/linux/oss_wrapper.h
@@ -0,0 +1,118 @@
+/*

+ * Operating System Service Wrapper 

+ *

+ * Notes :

+ * ** DO NOT include headers other than common & os specific ones

+ *

+ * ** This header is included in mv_os.h, you don't have to include it

+ *        explicitly in your code.

+ *

+ */

+#ifndef __OSS_WRAPPER_H__

+#define __OSS_WRAPPER_H__

+

+#include "com_mod_mgmt.h"

+

+/* Sychronization Services */

+

+

+/* delay in milliseconds */

+MV_U8 ossw_add_timer(struct timer_list *timer,

+		    u32 msec, 

+		    void (*function)(unsigned long),

+		    unsigned long data);

+

+void ossw_del_timer(struct timer_list *timer);

+

+/* OS Information Query Services */

+u32 ossw_get_time_in_sec(void);

+u32 ossw_get_msec_of_time(void);

+

+/* MISC Services */

+#define ossw_mdelay(x) mdelay(x)

+#define ossw_udelay(x) udelay(x)

+

+#define MV_PCI_READ_CONFIG_DWORD(ext, offset, ptr) \

+          pci_read_config_dword(ext->desc->hba_desc->dev, offset, ptr)

+

+#define MV_PCI_READ_CONFIG_WORD(ext, offset, ptr) \

+          pci_read_config_word(ext->desc->hba_desc->dev, offset, ptr)

+

+#define MV_PCI_READ_CONFIG_BYTE(ext, offset, ptr) \

+          pci_read_config_byte(ext->desc->hba_desc->dev, offset, ptr)

+

+#define MV_PCI_WRITE_CONFIG_DWORD(ext, offset, val) \

+          pci_write_config_dword(ext->desc->hba_desc->dev, offset, val)

+

+#define MV_PCI_WRITE_CONFIG_WORD(ext, offset, val) \

+          pci_write_config_word(ext->desc->hba_desc->dev, offset, val)

+

+#define MV_PCI_WRITE_CONFIG_BYTE(ext, offset, val) \

+          pci_write_config_byte(ext->desc->hba_desc->dev, offset, val)

+

+/* System dependent macro for flushing CPU write cache */

+#define MV_CPU_WRITE_BUFFER_FLUSH() smp_wmb()

+#define MV_CPU_READ_BUFFER_FLUSH()  smp_rmb()

+#define MV_CPU_BUFFER_FLUSH()       smp_mb()

+

+/* register read write: memory io */

+#define MV_REG_WRITE_BYTE(base, offset, val)    \

+    writeb(val, base + offset)

+#define MV_REG_WRITE_WORD(base, offset, val)    \

+    writew(val, base + offset)

+#define MV_REG_WRITE_DWORD(base, offset, val)    \

+    writel(val, base + offset)

+

+#define MV_REG_READ_BYTE(base, offset)			\

+	readb(base + offset)

+#define MV_REG_READ_WORD(base, offset)			\

+	readw(base + offset)

+#define MV_REG_READ_DWORD(base, offset)			\

+	readl(base + offset)

+

+/* register read write: port io */

+#define MV_IO_WRITE_BYTE(base, offset, val)    \

+    outb(val, (unsigned)(MV_PTR_INTEGER)(base + offset))

+#define MV_IO_WRITE_WORD(base, offset, val)    \

+    outw(val, (unsigned)(MV_PTR_INTEGER)(base + offset))

+#define MV_IO_WRITE_DWORD(base, offset, val)    \

+    outl(val, (unsigned)(MV_PTR_INTEGER)(base + offset))

+

+#define MV_IO_READ_BYTE(base, offset)			\

+	inb((unsigned)(MV_PTR_INTEGER)(base + offset))

+#define MV_IO_READ_WORD(base, offset)			\

+	inw((unsigned)(MV_PTR_INTEGER)(base + offset))

+#define MV_IO_READ_DWORD(base, offset)			\

+	inl((unsigned)(MV_PTR_INTEGER)(base + offset))

+

+#if __LEGACY_OSSW__

+void HBA_SleepMillisecond(MV_PVOID ext, MV_U32 msec);

+

+#   define HBA_SleepMicrosecond(_x, _y) ossw_udelay(_y)

+#   define HBA_GetTimeInSecond          ossw_get_time_in_sec

+#   define HBA_GetMillisecondInDay      ossw_get_msec_of_time

+

+#   define NO_CURRENT_TIMER  0xFF

+

+#   define SmallTimer_AddRequest(_ext, _millsec, _func, _data, _bogus)    \

+             ossw_add_timer(&_ext->timer,                               \

+			     _millsec ,                           \

+			     (OSSW_TIMER_FUNCTION) (_func),         \

+			     (OSSW_TIMER_DATA) (_data))

+

+

+

+#   define Timer_AddRequest(_ext, _sec, _func, _data, _bogus)    \

+             ossw_add_timer(&_ext->timer,                               \

+			     _sec * 1000,                           \

+			     (OSSW_TIMER_FUNCTION) (_func),         \

+			     (OSSW_TIMER_DATA) (_data))

+

+#   define Timer_CancelRequest(_data, _bogus)                     \

+              ossw_del_timer(&_data->timer)

+

+#endif /* __LEGACY_OSSW__ */

+

+void hba_msleep(MV_U32 msec);

+

+#endif /* __OSS_WRAPPER_H__ */

diff --git a/drivers/scsi/thor/linux/res_mgmt.c b/drivers/scsi/thor/linux/res_mgmt.c
new file mode 100755
index 0000000..ec57957
--- /dev/null
+++ b/drivers/scsi/thor/linux/res_mgmt.c
@@ -0,0 +1,201 @@
+#include "hba_header.h"

+#include "res_mgmt.h"

+#include "oss_wrapper.h"

+#include "linux_main.h"

+

+struct mv_request_pool *res_reserve_req_pool(MV_U32 mod_id,

+					     MV_U32 size,

+					     MV_U32 sg_count)

+{

+	int i;

+	unsigned int mem_size;

+	struct mv_request_pool *pool;

+	struct _MV_Request *req;

+	MV_SG_Entry *sg;

+

+	MV_DBG(DMSG_RES, "module %u reserves reqcount=%d, sgcount=%d,request pool of size %lu.\n",

+	       mod_id,size,sg_count,

+	       (unsigned long) (sizeof(struct _MV_Request) * size + 

+				sizeof(MV_SG_Entry)* sg_count * size));

+

+	/* 

+	 * since we almost always use sgd_t with pctx, we need x2 memory

+	 * than normal sgd_t table

+	 */

+	sg_count *= 2;

+

+	mem_size = sizeof(struct mv_request_pool);

+	pool = vmalloc(mem_size);

+	if (NULL == pool)

+		goto res_err_pool;

+	memset(pool, 0, mem_size);

+

+	/* assuming its size is already 64bit-aligned */

+	mem_size = sizeof(struct _MV_Request) * size;

+	req = vmalloc(mem_size);

+	if (NULL == req)

+		goto res_err_req;

+	memset(req, 0, mem_size);

+

+	mem_size = sizeof(MV_SG_Entry) * sg_count * size;

+	sg  = vmalloc(mem_size);

+	if (NULL == sg)

+		goto res_err_sg;

+	memset(sg, 0, mem_size);

+

+

+

+	INIT_LIST_HEAD(&pool->free_list);

+	INIT_LIST_HEAD(&pool->use_list);

+	OSSW_INIT_SPIN_LOCK(&pool->lock);

+

+	pool->mod_id  = mod_id;

+	pool->size    = size;

+	pool->req_mem = (void *) req;

+	pool->sg_mem = (void *)sg;

+	

+	for (i = 0; i < size; i++) {

+		//MV_DBG(DMSG_RES, "req no.%d at %p with sg at %p.\n",

+		 //      i, req, sg);

+

+		req->SG_Table.Entry_Ptr  = sg;

+		MV_ASSERT(sg_count<=255);

+		req->SG_Table.Max_Entry_Count = sg_count;

+		list_add_tail(&req->pool_entry, &pool->free_list);

+		req++;

+		sg += sg_count;

+	}

+#ifdef SEPARATE_IOCTL_REQ

+	INIT_LIST_HEAD(&pool->ioctl_free_list);

+	INIT_LIST_HEAD(&pool->ioctl_use_list);

+	OSSW_INIT_SPIN_LOCK(&pool->ioctl_lock);

+	mem_size = sizeof(struct _MV_Request) * MV_MAX_IOCTL_REQUEST;

+	req = vmalloc(mem_size);

+	if (NULL == req)

+		goto res_err_req;

+	memset(req, 0, mem_size);

+

+	mem_size = sizeof(MV_SG_Entry) * sg_count * MV_MAX_IOCTL_REQUEST;

+	sg  = vmalloc(mem_size);

+	if (NULL == sg)

+		goto res_err_sg;

+	memset(sg, 0, mem_size);

+

+	pool->ioctl_req_mem = (void *) req;

+	pool->ioctl_sg_mem = (void *)sg;

+

+	for (i = 0; i < MV_MAX_IOCTL_REQUEST; i++) {

+		req->SG_Table.Entry_Ptr  = sg;

+		MV_ASSERT(sg_count<=255);

+		req->SG_Table.Max_Entry_Count = sg_count;

+		list_add_tail(&req->pool_entry, &pool->ioctl_free_list);

+		req++;

+		sg += sg_count;

+	}

+	

+#endif

+		

+	return pool;

+

+res_err_sg:

+	MV_ASSERT(MV_FALSE);

+	vfree(req);

+res_err_req:

+	MV_ASSERT(MV_FALSE);

+	vfree(pool);

+res_err_pool:

+	MV_ASSERT(MV_FALSE);

+	return NULL;

+}

+

+#ifdef SUPPORT_OS_REQ_TIMER

+void mv_init_os_req_timer(struct _MV_Request * req);

+#endif

+

+struct _MV_Request *res_get_req_from_pool(struct mv_request_pool *pool)

+{

+	struct _MV_Request *req;

+	unsigned long flags;

+

+	BUG_ON(pool == NULL);

+	OSSW_SPIN_LOCK_IRQSAVE(&pool->lock, flags);

+	if (list_empty(&pool->free_list)) {

+		res_dump_pool_info(pool);

+		OSSW_SPIN_UNLOCK_IRQRESTORE(&pool->lock, flags);

+		return NULL;

+	}

+	

+	req = list_entry(pool->free_list.next, struct _MV_Request, pool_entry);

+	MV_ZeroMvRequest(req); /* FIX: we can do better than this */

+	list_move_tail(pool->free_list.next, &pool->use_list);

+#ifdef SUPPORT_OS_REQ_TIMER

+	mv_init_os_req_timer(req);

+#endif

+	OSSW_SPIN_UNLOCK_IRQRESTORE(&pool->lock, flags);

+	

+	return req;

+}

+

+void res_free_req_to_pool(struct mv_request_pool *pool,

+			  struct _MV_Request *req)

+{

+	unsigned long flags;

+

+	BUG_ON((NULL == pool) || (NULL == req));

+	OSSW_SPIN_LOCK_IRQSAVE(&pool->lock, flags);

+	list_move_tail(&req->pool_entry, &pool->free_list);

+	OSSW_SPIN_UNLOCK_IRQRESTORE(&pool->lock, flags);

+}

+

+void res_dump_pool_info(struct mv_request_pool *pool)

+{

+	

+}

+

+void res_release_req_pool(struct mv_request_pool *pool)

+{

+	BUG_ON(NULL == pool);

+	

+	MV_DBG(DMSG_RES, "module %d release pool at %p.\n",

+	       pool->mod_id, pool);

+	vfree(pool->req_mem);

+	vfree(pool->sg_mem);

+#ifdef SEPARATE_IOCTL_REQ

+	vfree(pool->ioctl_req_mem);

+	vfree(pool->ioctl_sg_mem);

+#endif

+	vfree(pool);

+}

+#ifdef SEPARATE_IOCTL_REQ

+struct _MV_Request *get_ioctl_req_from_pool(struct mv_request_pool *pool)

+{

+	struct _MV_Request *req;

+	unsigned long flags;

+	

+	BUG_ON(pool == NULL);

+	OSSW_SPIN_LOCK_IRQSAVE(&pool->ioctl_lock, flags);

+	if (list_empty(&pool->ioctl_free_list)) {

+		res_dump_pool_info(pool);

+		OSSW_SPIN_UNLOCK_IRQRESTORE(&pool->ioctl_lock, flags);

+		return NULL;

+	}

+	

+	req = list_entry(pool->ioctl_free_list.next, struct _MV_Request, pool_entry);

+	MV_ZeroMvRequest(req); 

+	list_move_tail(pool->ioctl_free_list.next, &pool->ioctl_use_list);

+	OSSW_SPIN_UNLOCK_IRQRESTORE(&pool->ioctl_lock, flags);

+	

+	return req;

+}

+

+void free_ioctl_req_to_pool(struct mv_request_pool *pool,struct _MV_Request *req)

+{

+	unsigned long flags;

+

+	BUG_ON((NULL == pool) || (NULL == req));

+	OSSW_SPIN_LOCK_IRQSAVE(&pool->ioctl_lock, flags);

+	list_move_tail(&req->pool_entry, &pool->ioctl_free_list);

+	OSSW_SPIN_UNLOCK_IRQRESTORE(&pool->ioctl_lock, flags);

+}

+

+#endif

diff --git a/drivers/scsi/thor/linux/res_mgmt.h b/drivers/scsi/thor/linux/res_mgmt.h
new file mode 100755
index 0000000..46e70b6
--- /dev/null
+++ b/drivers/scsi/thor/linux/res_mgmt.h
@@ -0,0 +1,47 @@
+#ifndef __RES_MGMT_H__

+#define __RES_MGMT_H__

+

+#include "com_type.h"

+

+struct mv_request_pool {

+	struct list_head free_list;

+	struct list_head use_list;

+#ifdef SEPARATE_IOCTL_REQ

+	struct list_head ioctl_free_list;

+	struct list_head ioctl_use_list;

+	void 		*ioctl_sg_mem;

+	void 		*ioctl_req_mem;

+	spinlock_t  ioctl_lock;

+#endif

+

+	void        *req_mem;  /* starting address of the request mem pool */

+	void 		*sg_mem;

+	spinlock_t  lock;

+	MV_U32      mod_id;

+	MV_U32      size;

+};

+

+/* request structure related

+ * mod_id   : id of the module that is making the request

+ * size     : size of the pool, measured in the number of requests

+ * sg_count : scatter gather list entries supported by each request

+ */

+struct mv_request_pool *res_reserve_req_pool(MV_U32 mod_id,

+					     MV_U32 size,

+					     MV_U32 sg_count);

+

+struct _MV_Request *res_get_req_from_pool(struct mv_request_pool *pool);

+

+void res_free_req_to_pool(struct mv_request_pool *pool,

+			  struct _MV_Request *req);

+

+void res_release_req_pool(struct mv_request_pool *pool);

+

+void res_dump_pool_info(struct mv_request_pool *pool);

+#ifdef SEPARATE_IOCTL_REQ

+struct _MV_Request *get_ioctl_req_from_pool(struct mv_request_pool *pool);

+void free_ioctl_req_to_pool(struct mv_request_pool *pool,struct _MV_Request *req);

+#endif

+

+

+#endif /* __RES_MGMT_H__ */

diff --git a/drivers/scsi/thor/mv_conf.mk b/drivers/scsi/thor/mv_conf.mk
new file mode 100755
index 0000000..006d5db
--- /dev/null
+++ b/drivers/scsi/thor/mv_conf.mk
@@ -0,0 +1,5 @@
+#

+# config file for Makefile and script

+#

+

+SUPPORT_THOR=y

diff --git a/drivers/scsi/thor/mv_config.h b/drivers/scsi/thor/mv_config.h
new file mode 100755
index 0000000..2493e24
--- /dev/null
+++ b/drivers/scsi/thor/mv_config.h
@@ -0,0 +1,17 @@
+#if !defined(MV_CONFIGURATION_H)

+#define MV_CONFIGURATION_H

+

+#ifdef PRODUCTNAME_ODIN

+#include "mv_odin.h"

+

+#elif defined(SIMULATOR)

+

+#include "mv_simu.h"

+

+#elif defined(PRODUCTNAME_THOR)

+

+#include "mv_thor.h"

+

+#endif /*PRODUCTNAME_ODIN , PRODUCTNAME_THOR*/

+

+#endif /* MV_CONFIGURATION_H */

diff --git a/drivers/scsi/thor/mv_include.h b/drivers/scsi/thor/mv_include.h
new file mode 100755
index 0000000..b9ece10
--- /dev/null
+++ b/drivers/scsi/thor/mv_include.h
@@ -0,0 +1,50 @@
+#if !defined(MV_INCLUDE_H)

+#define MV_INCLUDE_H

+

+#ifdef SIMULATOR

+#include "stdafx.h"

+#endif

+

+#include "mv_config.h"

+

+#include "mv_os.h"

+#include "com_type.h"

+#include "com_u64.h"

+

+#include "com_util.h"

+#include "com_list.h"

+

+#include "com_dbg.h"

+

+#include "hba_exp.h"

+#include "core_exp.h"

+

+#ifdef SUPPORT_TIMER

+#include "hba_timer.h"

+#endif

+

+#include "com_scsi.h"

+

+#include "com_api.h"

+#include "com_struct.h"

+#ifdef SUPPORT_SCSI_PASSTHROUGH

+#include "com_ioctl.h"

+#endif

+

+#ifndef _RAID_PARTIAL

+#ifdef RAID_DRIVER

+#include "raid_exp.h"

+#endif

+

+#ifdef SUPPORT_RAID6

+#include "math_gf.h"

+#endif

+

+#ifdef CACHE_MODULE_SUPPORT

+#include "cache_exp.h"

+#endif

+

+#endif

+

+#endif /* MV_INCLUDE_H */

+

diff --git a/drivers/scsi/thor/mv_thor.h b/drivers/scsi/thor/mv_thor.h
new file mode 100755
index 0000000..042aece
--- /dev/null
+++ b/drivers/scsi/thor/mv_thor.h
@@ -0,0 +1,174 @@
+#ifndef __MV_THOR_H__
+#define __MV_THOR_H__
+
+/* OEM Account definition */
+#define VER_OEM_GENERIC			0
+#define VER_OEM_INTEL			1
+#define VER_OEM_ASUS			2
+#if defined(__MV_LINUX__) || defined(__QNXNTO__)
+#	define THOR_DRIVER						1
+#	define NEW_LINUX_DRIVER				1
+#   define __MM_SE__                       1
+#   define __RES_MGMT__                    1
+#endif /* __MV_LINUX__ && __QNXNTO__ */
+
+#ifndef __MV_LINUX__
+#define DISPATCH_HOOK
+/*
+ * define USE_NEW_SGTABLE to use the new SG format as defined in
+ * "General SG Format" document.
+ */
+#define USE_NEW_SGTABLE
+
+/* 
+ * define USE_SRBEXT_AS_REQ to use Windows SrbExtension to store 
+ * the MV_Request with its SG Table. 
+ */
+#define USE_SRBEXT_AS_REQ
+
+#define FILTER_ASSISTED_COMMON_BUFFER
+
+#endif /* _OS_WINDOWS */
+
+#define USE_NEW_SGTABLE
+
+/* HBA macro definition */
+#define MV_MAX_TRANSFER_SIZE	(128*1024)
+#define MAX_REQUEST_NUMBER		32
+#define MAX_BASE_ADDRESS		6
+
+#define MAX_DEVICE_SUPPORTED	8
+
+/* Core driver macro definition */
+#define MAX_SG_ENTRY			34
+#define MAX_SG_ENTRY_REDUCED	16
+#define MV_MAX_PHYSICAL_BREAK	(MAX_SG_ENTRY - 1)
+
+#ifdef USE_NEW_SGTABLE
+#define HW_SG_ENTRY_MAX		(MAX_SG_ENTRY)
+#endif
+
+//#define ENABLE_PATA_ERROR_INTERRUPT	//ATAPI???
+
+/* It's dangerous. Never enable it unless we have to. */
+#define PRD_SIZE_WORD_ALIGN	
+
+/* 
+ * For ATAPI device, we can choose 
+ * 1. Enable USE_PIO_FOR_ALL_PACKET_COMMAND
+ * 2. Enable USE_DMA_FOR_ALL_PACKET_COMMAND
+ * 3. Don't enable either of them. It'll use DMA for read/write. Others will use PIO.
+ * So far, USE_DMA_FOR_ALL_PACKET_COMMAND is the best choice.
+ */
+//#define USE_PIO_FOR_ALL_PACKET_COMMAND
+#define USE_DMA_FOR_ALL_PACKET_COMMAND
+
+
+#define CORE_SUPPORT_API      1
+#define CORE_IGNORE_START_STOP_UNIT
+
+
+//#define CORE_DEBUG_MODE
+
+/* hot plug & PM */
+#define SUPPORT_HOT_PLUG	1
+#define SUPPORT_PM			1
+#define SUPPORT_ERROR_HANDLING		1
+
+#ifndef __MV_LINUX__
+#define SUPPORT_CONSOLIDATE			1
+#define SUPPORT_TIMER				1
+#define SUPPORT_SCSI_PASSTHROUGH  1
+#endif /* _OS_WINDOWS */
+
+/* pass through */
+#ifdef SUPPORT_SCSI_PASSTHROUGH		
+#define SUPPORT_VIRTUAL_DEVICE
+#define MV_MAX_TARGET_NUMBER		21		// virtual device 5 port*4 device
+#else
+#define MV_MAX_TARGET_NUMBER		20		// virtual device 5 port*4 device
+#endif
+#define MV_MAX_LUN_NUMBER			1
+#define MV_MAX_HD_DEVICE_ID		20		// virtual device 5 port*4 device
+
+#define VIRTUAL_DEVICE_ID					(MV_MAX_TARGET_NUMBER - 1) * MV_MAX_LUN_NUMBER
+
+#define SUPPORT_EVENT			  1
+
+/* RAID */
+#ifndef __MV_LINUX__
+#define PERFORMANCE_WHQL_SWITCH
+
+#define RAID_DRIVER				1
+#define SUPPORT_RAID6
+#define CACHE_MODULE_SUPPORT
+#endif /* _OS_WINDOWS */
+
+#ifdef RAID_DRIVER
+#define BGA_SUPPORT				1
+#define SOFTWARE_XOR			1
+#define SUPPORT_FREE_POLICY		1
+//#define SUPPORT_SRL				1
+#define SUPPORT_XOR_DWORD		1
+//#define SUPPORT_RAID1E				1
+#define SUPPORT_DUAL_DDF			0
+
+#ifdef SUPPORT_RAID6
+#define USE_MATH_LIBARY
+#define SUPPORT_READ_MODIFY_WRITE
+#define RAID_USE_64K_SU
+#endif
+/*
+ * define SUPPORT_NON_STRIPE to force RAID not to split RAID0/1
+ * access by stripes.
+ */
+#define SUPPORT_NON_STRIPE
+#define ALLOCATE_SENSE_BUFFER		1
+
+//#define SUPPORT_MIGRATION
+#define MV_MIGRATION_RESERVED_SPACE_V1	2048	/* 1MB & by sectors */
+#define MV_MIGRATION_RESERVED_SPACE_V2	32768 //16MB	// SECTORS
+#define MV_MIGRATION_SHIFT_SPACE		2048  // 1MB	// SECTORS
+#endif /* RAID_DRIVER */
+
+#if defined(USE_NEW_SGTABLE) && (defined(SOFTWARE_XOR) || defined(CACHE_MODULE_SUPPORT))
+#define USE_VIRTUAL_PRD_TABLE           1
+#endif
+
+#define ERROR_HANDLING_SUPPORT	0
+#define ERROR_SIMULATOR			0 /*1 for error simulator enable, 0 for disable*/
+
+/* Cache */
+#ifdef CACHE_MODULE_SUPPORT
+#define CACHE_FREE_DISK_ENABLE 1
+#endif
+
+#ifndef USE_NEW_SGTABLE
+#define SUPPORT_VIRTUAL_AND_PHYSICAL_SG
+#endif
+
+/* hardware-dependent definitions */
+#define MAX_EXPANDER_SUPPORTED				0     
+#define MAX_PM_SUPPORTED					4     
+#define MAX_BLOCK_PER_HD_SUPPORTED			8
+
+#define MAX_REQUEST_NUMBER_WHQL				MAX_REQUEST_NUMBER
+#define MAX_DEVICE_SUPPORTED_WHQL			8
+#define MAX_LD_SUPPORTED_WHQL				8
+#define MAX_BLOCK_SUPPORTED_WHQL			32
+
+#define MAX_REQUEST_NUMBER_PERFORMANCE		MAX_REQUEST_NUMBER_WHQL
+#define MAX_DEVICE_SUPPORTED_PERFORMANCE	MAX_DEVICE_SUPPORTED_WHQL
+#define MAX_LD_SUPPORTED_PERFORMANCE		MAX_LD_SUPPORTED_WHQL
+#define MAX_BLOCK_SUPPORTED_PERFORMANCE		MAX_BLOCK_SUPPORTED_WHQL
+#define MAX_CORE_REQUEST_NUMBER_PERFORMANCE   32
+
+#define COMMAND_ISSUE_WORKROUND		1
+
+#define SUPPORT_ATA_SMART        1 
+#define SUPPORT_ATA_SECURITY_CMD 1
+#define HOTPLUG_ISSUE_WORKROUND 1
+#define SUPPORT_ATA_POWER_MANAGEMENT   1
+//#define SUPPORT_WORKQUEUE             1
+
+#endif /* __MV_THOR_H__ */
diff --git a/drivers/scsi/thor/patch.kbuild b/drivers/scsi/thor/patch.kbuild
new file mode 100755
index 0000000..277fa59
--- /dev/null
+++ b/drivers/scsi/thor/patch.kbuild
@@ -0,0 +1,11 @@
+diff -uprN scsi/Makefile scsi.new/Makefile
+--- scsi/Makefile	2006-11-20 11:17:17.000000000 +0800
++++ scsi.new/Makefile	2006-11-20 11:33:53.000000000 +0800
+@@ -42,6 +42,7 @@ obj-$(CONFIG_A2091_SCSI)	+= a2091.o	wd33
+ obj-$(CONFIG_GVP11_SCSI)	+= gvp11.o	wd33c93.o
+ obj-$(CONFIG_MVME147_SCSI)	+= mvme147.o	wd33c93.o
+ obj-$(CONFIG_SGIWD93_SCSI)	+= sgiwd93.o	wd33c93.o
++obj-$(CONFIG_SCSI_MV_64xx) += mv/
+ obj-$(CONFIG_CYBERSTORM_SCSI)	+= NCR53C9x.o	cyberstorm.o
+ obj-$(CONFIG_CYBERSTORMII_SCSI)	+= NCR53C9x.o	cyberstormII.o
+ obj-$(CONFIG_BLZ2060_SCSI)	+= NCR53C9x.o	blz2060.o
diff --git a/drivers/scsi/thor/patch.sh b/drivers/scsi/thor/patch.sh
new file mode 100755
index 0000000..a303e6d
--- /dev/null
+++ b/drivers/scsi/thor/patch.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+. mv_conf.mk
+subtxt(){
+
+    if [ ! -f "$1" ] || [ ! -w "$1" ]; then
+	echo "File does not exist or is not writable."
+	exit 1
+    fi
+
+    if [ "$2" == "a" ];then
+        if [ "$SUPPORT_THOR" == "y"  ];then
+        
+            grep SCSI_MV_61xx "$1" >/dev/null 2>&1
+	    if [ "$?" == "0" ];then
+	        cat "$1"
+                return
+	    fi
+
+	    sed -e '/SCSI low-level drivers/{
+                    n
+                    n
+                    a\
+config SCSI_MV_61xx\
+	tristate "Marvell Storage Controller 6121/6122/6141/6145"\
+	depends on SCSI && BLK_DEV_SD\
+	help\
+		Provides support for Marvell 61xx Storage Controller series.\n
+}' "$1"
+
+        else
+        
+            grep SCSI_MV_64xx "$1" >/dev/null 2>&1
+            if [ "$?" == "0" ];then
+            cat "$1"
+               return
+            fi
+
+            sed -e '/SCSI low-level drivers/{
+                    n
+                    n
+                    a\
+config SCSI_MV_64xx\
+	tristate "Marvell Storage Controller 6320/6340/6440/6450/6480"\
+	depends on SCSI && BLK_DEV_SD\
+	help\
+		Provides support for Marvell 64xx Storage Controller series.\n
+}' "$1"
+        fi
+
+    else
+        if [ "$SUPPORT_THOR" == "y"  ];then
+            sed -e '/SCSI_MV_61xx/,+5 d' "$1"
+	else
+            sed -e '/SCSI_MV_64xx/,+5 d' "$1"
+	fi
+    fi
+
+}
+
+# $1 is supposed to be the $KERNEL_SRC/drivers/scsi
+if [ ! -d "$1" ];then
+    echo "Cannot find the specified directory."
+    exit 1
+fi
+
+cd "$1"
+subtxt Kconfig $2 > Kconfig.new
+mv Kconfig Kconfig.orig
+mv Kconfig.new Kconfig
+
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
old mode 100644
new mode 100755
index 5ed1b82..49de795
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -457,6 +457,22 @@
 {
 	int save_offset = offset;
 	offset = map_8250_out_reg(p, offset) << p->regshift;
+
+#ifdef CONFIG_ARCH_FEROCEON_KW2
+	/* If we are accessing DLH (0x4), DLL (0x0), LCR(0xC) or 0x1C
+	** we need to make sure that the busy bit is cleared in USR register.
+	*/
+	if ((((readb(p->membase + 0xC) & 0x80) &&
+	     ((save_offset == UART_DLL) || (save_offset == UART_DLM) ||
+	      (offset == 0x1C))) ||
+	     (save_offset == UART_LCR)) && !(readb(p->membase + 0x14) & 0x1)) {
+		unsigned int status;
+		do {
+			status = *((volatile u32 *)p->private_data);
+		} while (status & 0x1);
+	}
+#endif
+
 	/* Save the LCR value so it can be re-written when a
 	 * Busy Detect interrupt occurs. */
 	if (save_offset == UART_LCR) {
@@ -1734,7 +1750,9 @@
 	unsigned int iir;
 
 	iir = serial_in(up, UART_IIR);
-	if (!(iir & UART_IIR_NO_INT))
+#ifndef CONFIG_ARCH_FEROCEON_KW2
+	if (iir != UART_IIR_NO_INT)
+#endif
 		serial8250_handle_port(up);
 	mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
 }
diff --git a/drivers/telephony/Makefile b/drivers/telephony/Makefile
old mode 100644
new mode 100755
index 1206615..6ef69a8
--- a/drivers/telephony/Makefile
+++ b/drivers/telephony/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_PHONE) += phonedev.o
 obj-$(CONFIG_PHONE_IXJ) += ixj.o
 obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o
+obj-$(CONFIG_MV_PHONE) += ../../arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
old mode 100644
new mode 100755
index 355dffc..96f1171
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -494,7 +494,7 @@
 		return 0;
 	/* allocate 2^1 pages = 8K (on i386);
 	 * should be more than enough for one device */
-	pages_start = (char *)__get_free_pages(GFP_NOIO, 1);
+	pages_start = (char *)__get_free_pages(GFP_KERNEL, 1);
 	if (!pages_start)
 		return -ENOMEM;
 
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
old mode 100644
new mode 100755
index 2f12e2d..22b5a64
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1345,11 +1345,14 @@
 		}
 	}
 
+	free_async(as);
+
 	if (put_user(addr, (void __user * __user *)arg))
 		return -EFAULT;
 	return 0;
 
 err_out:
+	free_async(as);
 	return -EFAULT;
 }
 
@@ -1379,11 +1382,8 @@
 static int proc_reapurb(struct dev_state *ps, void __user *arg)
 {
 	struct async *as = reap_as(ps);
-	if (as) {
-		int retval = processcompl(as, (void __user * __user *)arg);
-		free_async(as);
-		return retval;
-	}
+	if (as)
+		return processcompl(as, (void __user * __user *)arg);
 	if (signal_pending(current))
 		return -EINTR;
 	return -EIO;
@@ -1391,16 +1391,11 @@
 
 static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
 {
-	int retval;
 	struct async *as;
 
-	as = async_getcompleted(ps);
-	retval = -EAGAIN;
-	if (as) {
-		retval = processcompl(as, (void __user * __user *)arg);
-		free_async(as);
-	}
-	return retval;
+	if (!(as = async_getcompleted(ps)))
+		return -EAGAIN;
+	return processcompl(as, (void __user * __user *)arg);
 }
 
 #ifdef CONFIG_COMPAT
@@ -1451,9 +1446,9 @@
 	void __user *addr = as->userurb;
 	unsigned int i;
 
-	if (as->userbuffer && urb->actual_length)
+	if (as->userbuffer)
 		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
-				 urb->actual_length))
+				 urb->transfer_buffer_length))
 			return -EFAULT;
 	if (put_user(as->status, &userurb->status))
 		return -EFAULT;
@@ -1473,6 +1468,7 @@
 		}
 	}
 
+	free_async(as);
 	if (put_user(ptr_to_compat(addr), (u32 __user *)arg))
 		return -EFAULT;
 	return 0;
@@ -1481,11 +1477,8 @@
 static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
 {
 	struct async *as = reap_as(ps);
-	if (as) {
-		int retval = processcompl_compat(as, (void __user * __user *)arg);
-		free_async(as);
-		return retval;
-	}
+	if (as)
+		return processcompl_compat(as, (void __user * __user *)arg);
 	if (signal_pending(current))
 		return -EINTR;
 	return -EIO;
@@ -1493,16 +1486,11 @@
 
 static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
 {
-	int retval;
 	struct async *as;
 
-	retval = -EAGAIN;
-	as = async_getcompleted(ps);
-	if (as) {
-		retval = processcompl_compat(as, (void __user * __user *)arg);
-		free_async(as);
-	}
-	return retval;
+	if (!(as = async_getcompleted(ps)))
+		return -EAGAIN;
+	return processcompl_compat(as, (void __user * __user *)arg);
 }
 
 #endif
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
old mode 100644
new mode 100755
index bcbe104..a9d0c01
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -111,6 +111,10 @@
 	u64			rsrc_len;	/* memory/io resource length */
 	unsigned		power_budget;	/* in mA, 0 = no limit */
 
+#if defined(CONFIG_HAVE_CLK)
+	struct clk		*clk;
+#endif
+
 #define HCD_BUFFER_POOLS	4
 	struct dma_pool		*pool [HCD_BUFFER_POOLS];
 
@@ -391,7 +395,7 @@
  * Generic bandwidth allocation constants/support
  */
 #define FRAME_TIME_USECS	1000L
-#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
+#define BitTime(bytecount) (9 * 8 * bytecount / 8) /* with integer truncation */
 		/* Trying not to use worst-case bit-stuffing
 		 * of (7/6 * 8 * bytecount) = 9.33 * bytecount */
 		/* bytecount = data payload byte count */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
old mode 100644
new mode 100755
index ed3aa7a..2bb7892
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3298,9 +3298,6 @@
 					USB_PORT_FEAT_C_SUSPEND);
 				udev = hdev->children[i-1];
 				if (udev) {
-					/* TRSMRCY = 10 msec */
-					msleep(10);
-
 					usb_lock_device(udev);
 					ret = remote_wakeup(hdev->
 							children[i-1]);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
old mode 100644
new mode 100755
index 980a8d2..da718e8
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -911,11 +911,11 @@
 	if (index <= 0)
 		return NULL;
 
-	buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO);
+	buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL);
 	if (buf) {
 		len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE);
 		if (len > 0) {
-			smallbuf = kmalloc(++len, GFP_NOIO);
+			smallbuf = kmalloc(++len, GFP_KERNEL);
 			if (!smallbuf)
 				return buf;
 			memcpy(smallbuf, buf, len);
@@ -1682,7 +1682,7 @@
 	if (cp) {
 		nintf = cp->desc.bNumInterfaces;
 		new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
-				GFP_NOIO);
+				GFP_KERNEL);
 		if (!new_interfaces) {
 			dev_err(&dev->dev, "Out of memory\n");
 			return -ENOMEM;
@@ -1691,7 +1691,7 @@
 		for (; n < nintf; ++n) {
 			new_interfaces[n] = kzalloc(
 					sizeof(struct usb_interface),
-					GFP_NOIO);
+					GFP_KERNEL);
 			if (!new_interfaces[n]) {
 				dev_err(&dev->dev, "Out of memory\n");
 				ret = -ENOMEM;
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
old mode 100644
new mode 100755
index ab93918..86422c8
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -96,6 +96,11 @@
 {
 	const struct usb_device_id *id = usb_quirk_list;
 
+#if defined(CONFIG_ARCH_FEROCEON) || defined(CONFIG_MARVELL)
+	/* By default set USB_QUIRK_STRING_FETCH_255 for all unknown devices */
+	udev->quirks = USB_QUIRK_STRING_FETCH_255;
+#endif /* CONFIG_ARCH_FEROCEON || CONFIG_ARCH_FEROCEON */
+
 	id = find_id(udev);
 	if (id)
 		udev->quirks = (u32)(id->driver_info);
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
old mode 100644
new mode 100755
index fcdcad4..8752e55
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -115,12 +115,6 @@
 	case USB_SPEED_HIGH:
 		speed = "480";
 		break;
-	case USB_SPEED_VARIABLE:
-		speed = "480";
-		break;
-	case USB_SPEED_SUPER:
-		speed = "5000";
-		break;
 	default:
 		speed = "unknown";
 	}
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
old mode 100644
new mode 100755
index a18e3c5..4d3fc89
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -81,8 +81,9 @@
 
 config USB_GADGET_VBUS_DRAW
 	int "Maximum VBUS Power usage (2-500 mA)"
-	range 2 500
-	default 2
+	range 0 500
+	default 2 if !ARCH_FEROCEON
+	default 0 if ARCH_FEROCEON
 	help
 	   Some devices need to draw power from USB when they are
 	   configured, perhaps to operate circuitry or to recharge
@@ -122,24 +123,6 @@
 # Integrated controllers
 #
 
-config USB_GADGET_AT91
-	boolean "Atmel AT91 USB Device Port"
-	depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 && !ARCH_AT91SAM9G45
-	select USB_GADGET_SELECTED
-	help
-	   Many Atmel AT91 processors (such as the AT91RM2000) have a
-	   full speed USB Device Port with support for five configurable
-	   endpoints (plus endpoint zero).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "at91_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_AT91
-	tristate
-	depends on USB_GADGET_AT91
-	default USB_GADGET
-
 config USB_GADGET_ATMEL_USBA
 	boolean "Atmel USBA"
 	select USB_GADGET_DUALSPEED
@@ -508,6 +491,36 @@
 #
 # LAST -- dummy/emulated controller
 #
+config USB_GADGET_AT91
+	boolean "AT91 USB Device Port"
+	depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9
+	select USB_GADGET_SELECTED
+	help
+	   Many Atmel AT91 processors (such as the AT91RM2000) have a
+	   full speed USB Device Port with support for five configurable
+	   endpoints (plus endpoint zero).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "at91_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_AT91
+	tristate
+	depends on USB_GADGET_AT91
+	default USB_GADGET
+
+config USB_GADGET_MRVL
+        boolean "Marvell USB Device Port"
+        depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
+	select USB_GADGET_DUALSPEED
+        help
+	  ...
+
+config USB_MRVL
+        tristate
+        depends on USB_GADGET_MRVL
+        default USB_GADGET
+        select USB_GADGET_SELECTED
 
 config USB_GADGET_DUMMY_HCD
 	boolean "Dummy HCD (DEVELOPMENT)"
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
old mode 100644
new mode 100755
index 9d7b87c..066148f
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -28,6 +28,7 @@
 obj-$(CONFIG_USB_CI13XXX)	+= ci13xxx_udc.o
 obj-$(CONFIG_USB_S3C_HSOTG)	+= s3c-hsotg.o
 obj-$(CONFIG_USB_LANGWELL)	+= langwell_udc.o
+obj-$(CONFIG_USB_MRVL)       	+= ../../../arch/arm/plat-feroceon/mv_drivers_lsp/mv_udc/
 
 #
 # USB gadget drivers
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
old mode 100644
new mode 100755
index 1e6aa50..76c637b
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -247,6 +247,7 @@
 #include <linux/string.h>
 #include <linux/freezer.h>
 #include <linux/utsname.h>
+#include <linux/version.h> 
 
 #include <asm/unaligned.h>
 
@@ -285,7 +286,7 @@
  *
  * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
  * Instead:  allocate your own, using normal USB-IF procedures. */
-#define DRIVER_VENDOR_ID	0x0525	// NetChip
+#define DRIVER_VENDOR_ID	0x1286	// Marvell
 #define DRIVER_PRODUCT_ID	0xa4a5	// Linux-USB File-backed Storage Gadget
 
 
@@ -360,6 +361,9 @@
 	unsigned short	product;
 	unsigned short	release;
 	unsigned int	buflen;
+	int		use_directio;
+	int		use_rda;
+	int		use_wr_thread;
 
 	int		transport_type;
 	char		*transport_name;
@@ -375,7 +379,14 @@
 	.vendor			= DRIVER_VENDOR_ID,
 	.product		= DRIVER_PRODUCT_ID,
 	.release		= 0xffff,	// Use controller chip type
-	.buflen			= 16384,
+	.buflen			= 32768, // 16384,
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
+	.use_directio		= 1,
+#else
+	.use_directio		= 0,
+#endif
+	.use_rda		= 1,
+	.use_wr_thread		= 1,
 	};
 
 
@@ -392,12 +403,14 @@
 module_param_named(removable, mod_data.removable, bool, S_IRUGO);
 MODULE_PARM_DESC(removable, "true to simulate removable media");
 
-module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
-MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
+module_param_named(use_directio, mod_data.use_directio, bool, S_IRUGO);
+MODULE_PARM_DESC(use_directio, "true to use O_DIRECT for file storage access");
 
-module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
-MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
+module_param_named(use_rda, mod_data.use_rda, bool, S_IRUGO);
+MODULE_PARM_DESC(use_rda, "true to use read ahead for performence enhancment");
 
+module_param_named(use_wr_thread, mod_data.use_wr_thread, bool, S_IRUGO);
+MODULE_PARM_DESC(use_wr_thread, "true to use seperate write thread for performence enhancment");
 
 /* In the non-TEST version, only the module parameters listed above
  * are available. */
@@ -422,6 +435,9 @@
 module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
 MODULE_PARM_DESC(buflen, "I/O buffer size");
 
+module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
+MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
+
 #endif /* CONFIG_USB_FILE_STORAGE_TEST */
 
 
@@ -596,7 +612,7 @@
 #define DELAYED_STATUS	(EP0_BUFSIZE + 999)	// An impossibly large value
 
 /* Number of buffers we will use.  2 is enough for double-buffering */
-#define NUM_BUFFERS	2
+#define NUM_BUFFERS	16 /* 2 */
 
 enum fsg_buffer_state {
 	BUF_STATE_EMPTY = 0,
@@ -606,6 +622,7 @@
 
 struct fsg_buffhd {
 	void				*buf;
+	dma_addr_t			dma;
 	enum fsg_buffer_state		state;
 	struct fsg_buffhd		*next;
 
@@ -617,7 +634,13 @@
 	struct usb_request		*inreq;
 	int				inreq_busy;
 	struct usb_request		*outreq;
-	int				outreq_busy;
+	volatile int			outreq_busy;
+
+	/* added to support async wr */
+	struct file	*file;
+	unsigned int	amount;
+	loff_t		file_offset;
+	struct fsg_buffhd   *next_to_wr;
 };
 
 enum fsg_state {
@@ -687,11 +710,21 @@
 
 	struct fsg_buffhd	*next_buffhd_to_fill;
 	struct fsg_buffhd	*next_buffhd_to_drain;
+	struct fsg_buffhd	*next_buffhd_to_wr;
+	struct fsg_buffhd	*next_buffhd_last_to_wr;
 	struct fsg_buffhd	buffhds[NUM_BUFFERS];
 
+	wait_queue_head_t	thread_wqh;
+	wait_queue_head_t	thread_wr_wqh;
+	wait_queue_head_t	thread_rda_wqh;
 	int			thread_wakeup_needed;
+	int			thread_wr_wakeup_needed;
+	int			thread_rda_wakeup_needed;
 	struct completion	thread_notifier;
 	struct task_struct	*thread_task;
+	struct task_struct	*thread_wr_task;
+	struct task_struct	*thread_rda_task;
+	int			num_wr_buf;
 
 	int			cmnd_size;
 	u8			cmnd[MAX_COMMAND_SIZE];
@@ -714,6 +747,23 @@
 	unsigned int		nluns;
 	struct lun		*luns;
 	struct lun		*curlun;
+
+	struct file		*rda_file;
+	struct file		*rda_dio_file;
+	loff_t			rda_file_offset;
+	loff_t			rda_dio_file_offset;
+	loff_t			rda_file_length;
+	/* rda_dio buffer is ready.						    */
+	/* set to 1 when when complete reading a buffer				    */
+	/* set to 0 when starting to fill new buffer or taking the old buffer out   */
+	int			rda_dio_ready;
+	void			*rda_dio_buf;
+	dma_addr_t		rda_dio_dma;
+	/* mark if rda_dio is valid,						    */
+	/* set to 1 only when request a new rda_dio				    */
+	/* set to 0 - in case of new write, to overcome cases of read after write   */
+	/*	    - in case of disconnect/unbind etc.				    */
+	int			rda_dio_valid; 
 };
 
 typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -1548,7 +1598,7 @@
 
 
 /*-------------------------------------------------------------------------*/
-
+int dio_count = 0;
 static int do_read(struct fsg_dev *fsg)
 {
 	struct lun		*curlun = fsg->curlun;
@@ -1559,7 +1609,9 @@
 	loff_t			file_offset, file_offset_tmp;
 	unsigned int		amount;
 	unsigned int		partial_page;
-	ssize_t			nread;
+	ssize_t			nread = 0;
+	int 			i;
+	int			hit_rda_dio = 0;
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
@@ -1587,7 +1639,30 @@
 	if (unlikely(amount_left == 0))
 		return -EIO;		// No default reply
 
-	for (;;) {
+	if(mod_data.use_rda && !mod_data.use_directio) {
+	    //unsigned int flags;
+	    if(amount_left == 64*1024) {
+		//spin_lock_irqsave(&fsg->lock, flags);
+		fsg->rda_file = curlun->filp;
+		fsg->rda_file_length = curlun->file_length;
+		fsg->rda_file_offset = file_offset + (256*1024);
+		//spin_unlock_irqrestore(&fsg->lock, flags);
+		
+		/* Tell the read ahead thread that something has happened */
+		fsg->thread_rda_wakeup_needed = 1;
+		wake_up_all(&fsg->thread_rda_wqh);
+	    }
+	}
+
+	if(mod_data.use_wr_thread) {
+	    /* wait for write to complete */
+	    while(fsg->num_wr_buf != 0) {
+              if ((rc = sleep_thread(fsg)) != 0)
+		  return rc;
+	    }
+	}
+		
+	for (i=0;;i++) {
 
 		/* Figure out how much we need to read:
 		 * Try to read the remaining amount.
@@ -1600,10 +1675,12 @@
 		amount = min((unsigned int) amount_left, mod_data.buflen);
 		amount = min((loff_t) amount,
 				curlun->file_length - file_offset);
-		partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
-		if (partial_page > 0)
+		if(!mod_data.use_directio) {
+		    partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
+		    if (partial_page > 0)
 			amount = min(amount, (unsigned int) PAGE_CACHE_SIZE -
 					partial_page);
+		}
 
 		/* Wait for the next buffer to become available */
 		bh = fsg->next_buffhd_to_fill;
@@ -1622,11 +1699,67 @@
 			curlun->info_valid = 1;
 			bh->inreq->length = 0;
 			bh->state = BUF_STATE_FULL;
+			printk("warning trying to read past end of file\n");
 			break;
 		}
 
 		/* Perform the read */
 		file_offset_tmp = file_offset;
+
+		/* if using directio and rda, first check the rda_dio buffer, */
+		/* and set a new rda buffer if needed */
+		if(mod_data.use_directio && mod_data.use_rda) {
+		    hit_rda_dio = 0;
+		
+		    //spin_lock_irqsave(&fsg->lock, flags);
+		    /* if we have rda hit */
+		    if((curlun->filp == fsg->rda_dio_file) && 
+			(file_offset_tmp == fsg->rda_dio_file_offset) &&
+			fsg->rda_dio_ready && fsg->rda_dio_valid )
+		    {
+			void *tbuf = bh->buf;
+			/* the dma feild is not used anymore can be removed */
+			dma_addr_t tdma = bh->dma;
+
+			bh->buf = fsg->rda_dio_buf;
+			bh->dma = fsg->rda_dio_dma;
+			bh->inreq->buf = bh->outreq->buf = bh->buf;
+			bh->inreq->dma = bh->outreq->dma = bh->dma;
+			fsg->rda_dio_buf = tbuf;
+			fsg->rda_dio_dma = tdma;
+			amount = min(mod_data.buflen, amount_left);
+			nread = amount;
+			hit_rda_dio = 1;
+			fsg->rda_dio_ready = 0;
+		    }
+		    /* increment mis-counter only on first block of read request, and don't go to infinity */
+		    else if((i == 0) && (dio_count <= 10) )
+			dio_count++;
+
+		    /* if there was no hit in the rda for long time or we just got hit, */
+		    /* lets set the rda again						*/
+		    /* We optimize the read  for 64k seq, can be improved for		*/
+		    /* different sequnce.						*/
+		    if( ((dio_count > 10) || (hit_rda_dio)) && (amount_left == 64*1024)) {
+			dio_count = 0;
+			fsg->rda_dio_valid = 1;	
+			fsg->rda_file = curlun->filp;
+			fsg->rda_file_length = curlun->file_length;
+			/* The fsg buffer request max is 64k							    */ 
+			/* by using 32k buffers and reading 64k ahead we get 50% of rda, this is the best tuning    */
+			/* I could find for now.								    */
+			fsg->rda_file_offset = file_offset + 64*1024;
+		
+			/* Tell the read ahead thread that something has happened */
+			fsg->thread_rda_wakeup_needed = 1;
+			wake_up_all(&fsg->thread_rda_wqh);
+		    }
+		    //spin_unlock_irqrestore(fsg->lock,flags);
+		}
+		
+		
+		/* if there was no hit in the rda the read now. */
+		if(!hit_rda_dio) 
 		nread = vfs_read(curlun->filp,
 				(char __user *) bh->buf,
 				amount, &file_offset_tmp);
@@ -1637,11 +1770,11 @@
 			return -EINTR;
 
 		if (nread < 0) {
-			LDBG(curlun, "error in file read: %d\n",
+			printk("error in file read: %d\n",
 					(int) nread);
 			nread = 0;
 		} else if (nread < amount) {
-			LDBG(curlun, "partial file read: %d/%u\n",
+			printk("partial file read: %d/%u\n",
 					(int) nread, amount);
 			nread -= (nread & 511);	// Round down to a block
 		}
@@ -1687,14 +1820,18 @@
 	unsigned int		partial_page;
 	ssize_t			nwritten;
 	int			rc;
+	int 			fua = 0;
+	unsigned long   flags;
 
 	if (curlun->ro) {
 		curlun->sense_data = SS_WRITE_PROTECTED;
 		return -EINVAL;
 	}
 	spin_lock(&curlun->filp->f_lock);
+	if(!mod_data.use_directio)
 	curlun->filp->f_flags &= ~O_SYNC;	// Default is not to wait
 	spin_unlock(&curlun->filp->f_lock);
+	fsg->rda_dio_valid = 0;
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
@@ -1713,6 +1850,8 @@
 		}
 		if (fsg->cmnd[1] & 0x08) {	// FUA
 			spin_lock(&curlun->filp->f_lock);
+		    fua = 1;	  
+		    if(!mod_data.use_directio)
 			curlun->filp->f_flags |= O_SYNC;
 			spin_unlock(&curlun->filp->f_lock);
 		}
@@ -1745,10 +1884,12 @@
 			amount = min(amount_left_to_req, mod_data.buflen);
 			amount = min((loff_t) amount, curlun->file_length -
 					usb_offset);
-			partial_page = usb_offset & (PAGE_CACHE_SIZE - 1);
-			if (partial_page > 0)
+			if(!mod_data.use_directio){
+			    partial_page = usb_offset & (PAGE_CACHE_SIZE - 1);
+			    if (partial_page > 0)
 				amount = min(amount,
-	(unsigned int) PAGE_CACHE_SIZE - partial_page);
+				    (unsigned int) PAGE_CACHE_SIZE - partial_page);
+			}
 
 			if (amount == 0) {
 				get_some_more = 0;
@@ -1789,10 +1930,9 @@
 		bh = fsg->next_buffhd_to_drain;
 		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
 			break;			// We stopped early
-		if (bh->state == BUF_STATE_FULL) {
+		if ((bh->state == BUF_STATE_FULL) && ( bh != fsg->next_buffhd_to_fill )) {
 			smp_rmb();
 			fsg->next_buffhd_to_drain = bh->next;
-			bh->state = BUF_STATE_EMPTY;
 
 			/* Did something go wrong with the transfer? */
 			if (bh->outreq->status != 0) {
@@ -1804,18 +1944,57 @@
 
 			amount = bh->outreq->actual;
 			if (curlun->file_length - file_offset < amount) {
-				LERROR(curlun,
-	"write %u @ %llu beyond end %llu\n",
-	amount, (unsigned long long) file_offset,
-	(unsigned long long) curlun->file_length);
-				amount = curlun->file_length - file_offset;
+				printk("*** write %u @ %llu beyond end %llu\n",
+				    amount, (unsigned long long) file_offset,
+				    (unsigned long long) curlun->file_length);
+				    amount = curlun->file_length - file_offset;
 			}
 
 			/* Perform the write */
 			file_offset_tmp = file_offset;
-			nwritten = vfs_write(curlun->filp,
+
+			/* if using seperate write thread */
+			if(mod_data.use_wr_thread)
+			{
+			    //unsigned int flags;
+
+			    bh->file_offset = file_offset_tmp;
+			    bh->file = curlun->filp;
+			    bh->amount = amount;
+			    /* assume the write went well */
+			    nwritten = amount;
+
+			    spin_lock_irqsave(&fsg->lock, flags);
+			    /* add the bh to the wr ll */
+			    if(fsg->next_buffhd_to_wr == NULL) /* no write is pending */
+				fsg->next_buffhd_to_wr = bh; 
+			    else  /* there is some pending writes */
+				fsg->next_buffhd_last_to_wr->next_to_wr = bh; 
+			    fsg->next_buffhd_last_to_wr = bh;
+			    fsg->num_wr_buf++;
+			    spin_unlock_irqrestore(&fsg->lock,flags);
+			    /* Tell the write thread that something has happened */
+			    fsg->thread_wr_wakeup_needed = 1;
+			    wake_up_all(&fsg->thread_wr_wqh);
+
+			    /* in case of fua wait for the actual data to be written */
+			    if(fua) {
+				/* wait for write to complete */
+				while(fsg->num_wr_buf != 0) {
+				    if ((rc = sleep_thread(fsg)) != 0)
+					return rc;
+				}
+			    }
+
+			}
+			else {
+			    bh->state = BUF_STATE_EMPTY;
+
+			    nwritten = vfs_write(curlun->filp,
 					(char __user *) bh->buf,
 					amount, &file_offset_tmp);
+			}
+
 			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
 					(unsigned long long) file_offset,
 					(int) nwritten);
@@ -1823,12 +2002,10 @@
 				return -EINTR;		// Interrupted!
 
 			if (nwritten < 0) {
-				LDBG(curlun, "error in file write: %d\n",
-						(int) nwritten);
-				nwritten = 0;
+				printk("**** error in file write: %d\n",(int) nwritten);
+								nwritten = 0;
 			} else if (nwritten < amount) {
-				LDBG(curlun, "partial file write: %d/%u\n",
-						(int) nwritten, amount);
+				printk("**** partial file write: %d/%u\n",(int) nwritten, amount);
 				nwritten -= (nwritten & 511);
 						// Round down to a block
 			}
@@ -1838,6 +2015,7 @@
 
 			/* If an error occurred, report it and its position */
 			if (nwritten < amount) {
+				printk("**** If an error occurred, report it and its position\n");
 				curlun->sense_data = SS_WRITE_ERROR;
 				curlun->sense_data_info = file_offset >> 9;
 				curlun->info_valid = 1;
@@ -1846,6 +2024,7 @@
 
 			/* Did the host decide to stop early? */
 			if (bh->outreq->actual != bh->outreq->length) {
+				printk("**** Did the host decide to stop early?\n");
 				fsg->short_packet_received = 1;
 				break;
 			}
@@ -1869,9 +2048,18 @@
 static int fsync_sub(struct lun *curlun)
 {
 	struct file	*filp = curlun->filp;
+	int		rc;
+	struct fsg_dev	*fsg = the_fsg;
 
 	if (curlun->ro || !filp)
 		return 0;
+	if(mod_data.use_wr_thread) {
+	    /* wait for write to complete */
+	    while(fsg->num_wr_buf != 0) {
+                if ((rc = sleep_thread(fsg)) != 0)
+		  return rc;
+	    }
+	}
 	return vfs_fsync(filp, filp->f_path.dentry, 1);
 }
 
@@ -3237,6 +3425,8 @@
 		DBG(fsg, "reset interface\n");
 
 reset:
+	fsg->rda_dio_valid = 0;
+
 	/* Deallocate the requests */
 	for (i = 0; i < NUM_BUFFERS; ++i) {
 		struct fsg_buffhd *bh = &fsg->buffhds[i];
@@ -3593,6 +3783,203 @@
 }
 
 
+/* write thread */
+static int fsg_write_thread(void *fsg_)
+{
+    struct fsg_dev	*fsg = (struct fsg_dev *) fsg_;
+    int			rc;
+    struct fsg_buffhd	*bh;    
+    ssize_t		nwritten;
+    unsigned long flags;
+
+    /* Allow the thread to be killed by a signal, but set the signal mask
+     * to block everything but INT, TERM, KILL, and USR1. */
+    allow_signal(SIGINT);
+    allow_signal(SIGTERM);
+    allow_signal(SIGKILL);
+    allow_signal(SIGUSR1);
+
+    /* Arrange for userspace references to be interpreted as kernel
+     * pointers.  That way we can pass a kernel pointer to a routine
+     * that expects a __user pointer and it will work okay. */
+    set_fs(get_ds());
+
+ 
+    while(fsg->state != FSG_STATE_TERMINATED) {
+
+    	bh = fsg->next_buffhd_to_wr;
+	while (bh && bh->state == BUF_STATE_FULL) {
+
+	    nwritten = vfs_write(bh->file,
+			(char __user *) bh->buf,
+			bh->amount, &bh->file_offset);
+	    //printk("fsg_write_thread -> file write %u @ %llu -> %d\n", bh->amount,
+	    //(unsigned long long) bh->file_offset,
+	    //(int) nwritten);
+
+	    if(nwritten < bh->amount)
+		printk("write didn't complete correctlly %d ??\n",nwritten);
+	    
+	    spin_lock_irqsave(&fsg->lock, flags);
+	    fsg->next_buffhd_to_wr = bh->next_to_wr; 
+	    bh->next_to_wr = NULL;
+	    bh->state = BUF_STATE_EMPTY;
+	    bh = fsg->next_buffhd_to_wr;
+	    fsg->num_wr_buf--;
+	    spin_unlock_irqrestore(&fsg->lock, flags);
+	    wakeup_thread(fsg);
+	}
+
+	if(bh && bh->state != BUF_STATE_FULL) /* should'nt happen */
+	    printk("bh %p write thread got buffer which isn't FULL (%d)??? \n", bh, bh->state);
+
+	/* no more writes for now */
+	rc = wait_event_interruptible(fsg->thread_wr_wqh,
+			fsg->thread_wr_wakeup_needed); 
+	fsg->thread_wr_wakeup_needed = 0;
+
+        if (signal_pending(current))
+                flush_signals(current);
+    }
+
+    complete_and_exit(&fsg->thread_notifier, 0);
+}
+
+
+/* read ahead for direct IO only */
+
+/* BTW: with non preamtive kernel we are sure that kernel thread won't give up the CPU, except for cases of waiting for IO like in vfs_read below, or when going to sleep etc. */
+static int fsg_rda_dio_thread(void *fsg_)
+{
+    struct fsg_dev	*fsg = (struct fsg_dev *) fsg_;
+    int			rc;
+    struct file		*rda_file = NULL;
+    loff_t		rda_file_offset = 0;
+    loff_t		tmp_offset = 0;
+    loff_t		file_length = 0;
+    int			nread;
+    //unsigned long	flags;
+    
+    /* Allow the thread to be killed by a signal, but set the signal mask
+     * to block everything but INT, TERM, KILL, and USR1. */
+    allow_signal(SIGINT);
+    allow_signal(SIGTERM);
+    allow_signal(SIGKILL);
+    allow_signal(SIGUSR1);
+
+    /* Arrange for userspace references to be interpreted as kernel
+     * pointers.  That way we can pass a kernel pointer to a routine
+     * that expects a __user pointer and it will work okay. */
+    set_fs(get_ds());
+ 
+    while(fsg->state != FSG_STATE_TERMINATED) {
+
+	//spin_lock_irqsave(&fsg->lock, flags);
+	rda_file_offset = fsg->rda_file_offset;
+	tmp_offset = rda_file_offset;
+	rda_file = fsg->rda_file;
+	file_length = fsg->rda_file_length;
+
+	if(fsg->rda_dio_valid) {
+	    if(file_length > rda_file_offset + mod_data.buflen) {
+		fsg->rda_dio_ready = 0;
+		nread = vfs_read(rda_file, fsg->rda_dio_buf, mod_data.buflen, &tmp_offset); 
+		if(nread != mod_data.buflen) {
+		    printk("read failed to excute %d \n", nread);
+		}
+		else {
+		    fsg->rda_dio_file_offset = rda_file_offset;
+		    fsg->rda_dio_file = rda_file;
+		    fsg->rda_dio_ready = 1;
+		}
+	    }
+	}   
+	//spin_unlock_irqrestore(&fsg->lock, flags);
+
+	/* no more read ahead for now */
+	rc = wait_event_interruptible(fsg->thread_rda_wqh,
+			fsg->thread_rda_wakeup_needed); 
+	fsg->thread_rda_wakeup_needed = 0;
+
+        if (signal_pending(current))
+        	flush_signals(current);
+    }
+
+    complete_and_exit(&fsg->thread_notifier, 0);
+}
+
+/* general read ahead, */
+static int fsg_rda_thread(void *fsg_)
+{
+    struct fsg_dev	*fsg = (struct fsg_dev *) fsg_;
+    int			rc;
+    char    __user  	tmp_buf[32];
+    struct file		*rda_file = NULL;
+    loff_t		rda_file_offset = 0;
+    loff_t		file_length = 0;
+    loff_t		tmp_offset = 0;
+    int			count = 64/4;
+    int			nread;
+    //unsigned int	flags;
+    
+    /* Allow the thread to be killed by a signal, but set the signal mask
+     * to block everything but INT, TERM, KILL, and USR1. */
+    allow_signal(SIGINT);
+    allow_signal(SIGTERM);
+    allow_signal(SIGKILL);
+    allow_signal(SIGUSR1);
+
+    /* Arrange for userspace references to be interpreted as kernel
+     * pointers.  That way we can pass a kernel pointer to a routine
+     * that expects a __user pointer and it will work okay. */
+    set_fs(get_ds());
+ 
+    while(fsg->state != FSG_STATE_TERMINATED) {
+
+	/* we do read ahead of 64K one page each time */
+	while( (count < (64/4)) || (fsg->rda_file_offset != rda_file_offset) 
+				|| (fsg->rda_file != rda_file) ) { 
+		   
+	    //spin_lock_irqsave(&fsg->lock, flags);
+	    if((fsg->rda_file_offset != rda_file_offset) || (fsg->rda_file != rda_file)) {
+		rda_file_offset = fsg->rda_file_offset;
+		rda_file = fsg->rda_file;
+		file_length = fsg->rda_file_length;
+		count = 0;
+	    }
+	    //spin_unlock_irqrestore(&fsg->lock, flags);
+
+	    tmp_offset = rda_file_offset + (count * PAGE_SIZE);
+	    if(file_length > tmp_offset + 32) {
+		/* we read only few bytes since we can count that the kernel will read a full page,	    */
+		/* there is no reason we will copy the entire page from the cache buffer to this tmp buffer */
+		nread = vfs_read(rda_file, tmp_buf, 32, &tmp_offset); 
+		if(nread != 32)
+		    printk("read failed to excute %d \n", nread);
+		count++;
+
+	    }
+	    else {
+		printk("read ahead got to an end of the file.\n");
+		count = 64/4;
+	    }
+	}
+	    
+	/* no more read ahead for now */
+	rc = wait_event_interruptible(fsg->thread_rda_wqh,
+			fsg->thread_rda_wakeup_needed); 
+	fsg->thread_rda_wakeup_needed = 0;
+
+        if (signal_pending(current))
+        	flush_signals(current);
+
+    }
+
+    complete_and_exit(&fsg->thread_notifier, 0);
+
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 /* If the next two routines are called while the gadget is registered,
@@ -3611,7 +3998,12 @@
 	/* R/W if we can, R/O if we must */
 	ro = curlun->ro;
 	if (!ro) {
+
+	    if(mod_data.use_directio)
+		filp = filp_open(filename, O_RDWR | O_LARGEFILE | O_DIRECT, 0);
+	    else
 		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
+	
 		if (-EROFS == PTR_ERR(filp))
 			ro = 1;
 	}
@@ -3840,6 +4232,19 @@
 		complete(&fsg->thread_notifier);
 	}
 
+	if(fsg->thread_wr_task) {
+	    fsg->thread_wr_wakeup_needed = 1;
+	    wake_up_all(&fsg->thread_wr_wqh);
+	    wait_for_completion(&fsg->thread_notifier);
+	}
+	
+	if(fsg->thread_rda_task){
+	    fsg->thread_rda_wakeup_needed = 1;
+	    wake_up_all(&fsg->thread_rda_wqh);
+	    wait_for_completion(&fsg->thread_notifier);
+	    fsg->rda_dio_valid = 0;
+	}
+	
 	/* Free the data buffers */
 	for (i = 0; i < NUM_BUFFERS; ++i)
 		kfree(fsg->buffhds[i].buf);
@@ -4099,10 +4504,74 @@
 		bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
 		if (!bh->buf)
 			goto out;
+
+		{
+		    /* 
+		     * When using kmalloc the page _count is incremented only for the first page???
+		     * If we will use DirectIO, This will cause that after the dio/bio is completed 
+		     * the pages count will be 0 and the page will be release, and we don't want it.
+		     * See in direct-io.c get_ker_pages inc, page_cache_release dec and free.       
+		     */
+		    unsigned int        start;
+		    unsigned int        len = 0;
+
+		    if(mod_data.buflen > PAGE_SIZE) 
+			len  = mod_data.buflen/PAGE_SIZE;
+
+		    start  = (unsigned int)bh->buf;
+		    while(len) {
+			struct page *t_page;
+
+			t_page = virt_to_page(start);
+			atomic_inc(&t_page->_count);
+			start += PAGE_SIZE;
+			len--;
+		    }
+		}
+
 		bh->next = bh + 1;
+		bh->next_to_wr = NULL;
 	}
+	fsg->rda_dio_buf = kmalloc(mod_data.buflen, GFP_KERNEL);
+
+	if (!fsg->rda_dio_buf)
+	    goto out;
+	{
+	    /* 
+	     * When using kmalloc the page _count is incremented only for the first page???
+	     * If we will use DirectIO, This will cause that after the dio/bio is completed 
+	     * the pages count will be 0 and the page will be release, and we don't want it.
+	     * See in direct-io.c get_ker_pages inc, page_cache_release dec and free.       
+	     */
+	    unsigned int        start;
+	    unsigned int        len = 0;
+
+	    if(mod_data.buflen > PAGE_SIZE) 
+	        len  = mod_data.buflen/PAGE_SIZE;
+
+	    start  = (unsigned int)fsg->rda_dio_buf;
+	    while(len) {
+	        struct page *t_page;
+
+	        t_page = virt_to_page(start);
+	        atomic_inc(&t_page->_count);
+	        start += PAGE_SIZE;
+	        len--;
+	    }
+	}
+
+	
+	fsg->rda_dio_ready = 0;
+
+	fsg->num_wr_buf = 0;
 	fsg->buffhds[NUM_BUFFERS - 1].next = &fsg->buffhds[0];
 
+	fsg->rda_file = NULL;
+	fsg->rda_file_offset = fsg->rda_file_length = 0;
+
+	/* init all pointers */
+	fsg->next_buffhd_last_to_wr = fsg->next_buffhd_to_wr = NULL;	
+
 	/* This should reflect the actual gadget power source */
 	usb_gadget_set_selfpowered(gadget);
 
@@ -4127,6 +4596,34 @@
 		goto out;
 	}
 
+	if(mod_data.use_wr_thread) {
+            fsg->thread_wr_task = kthread_create(fsg_write_thread, fsg,
+                       "file-write-gadget");
+            if (IS_ERR(fsg->thread_wr_task)) {
+               	rc = PTR_ERR(fsg->thread_wr_task);
+               	goto out;
+            }
+	}
+
+	if(mod_data.use_rda) {
+	    if(mod_data.use_directio) {
+        	fsg->thread_rda_task = kthread_create(fsg_rda_dio_thread, fsg,
+                        "file-rda-dio-gadget");
+        	if (IS_ERR(fsg->thread_rda_task)) {
+                	rc = PTR_ERR(fsg->thread_rda_task);
+                	goto out;
+        	}
+	    }
+	    else {
+        	fsg->thread_rda_task = kthread_create(fsg_rda_thread, fsg,
+                        "file-rda-gadget");
+        	if (IS_ERR(fsg->thread_rda_task)) {
+                	rc = PTR_ERR(fsg->thread_rda_task);
+                	goto out;
+        	}
+	    }
+	}
+
 	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
 	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
 
@@ -4162,6 +4659,10 @@
 
 	/* Tell the thread to start working */
 	wake_up_process(fsg->thread_task);
+	if(mod_data.use_wr_thread)
+	    wake_up_process(fsg->thread_wr_task);
+	if(mod_data.use_rda)
+	    wake_up_process(fsg->thread_rda_task);
 	return 0;
 
 autoconf_fail:
@@ -4231,6 +4732,9 @@
 	spin_lock_init(&fsg->lock);
 	init_rwsem(&fsg->filesem);
 	kref_init(&fsg->ref);
+	init_waitqueue_head(&fsg->thread_wqh);
+	init_waitqueue_head(&fsg->thread_wr_wqh);
+	init_waitqueue_head(&fsg->thread_rda_wqh);
 	init_completion(&fsg->thread_notifier);
 
 	the_fsg = fsg;
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
old mode 100644
new mode 100755
index f2d270b..603e09c
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -169,6 +169,12 @@
 #define gadget_is_ci13xxx(g)	0
 #endif
 
+#ifdef CONFIG_USB_GADGET_MRVL
+#define gadget_is_mrvl(g)    !strcmp("mv_udc", (g)->name)
+#else
+#define gadget_is_mrvl(g)    0
+#endif
+
 // CONFIG_USB_GADGET_SX2
 // CONFIG_USB_GADGET_AU1X00
 // ...
@@ -235,6 +241,8 @@
 		return 0x18;
 	else if (gadget_is_fsl_usb2(gadget))
 		return 0x19;
+	else if (gadget_is_mrvl(gadget))
+		return 0x1a;
 	else if (gadget_is_amd5536udc(gadget))
 		return 0x20;
 	else if (gadget_is_m66592(gadget))
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
old mode 100644
new mode 100755
index 35bf518..c9c87e1
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -226,6 +226,9 @@
 	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
 	tmp = ehci_readl(ehci, reg_ptr);
 	tmp |= USBMODE_CM_HC;
+
+	tmp |= (1 << 4); //disable USB streamin
+
 	/* The default byte access to MMR space is LE after
 	 * controller reset. Set the required endian mode
 	 * for transfer buffers to match the host microprocessor
@@ -785,10 +788,9 @@
 
 			/* start 20 msec resume signaling from this port,
 			 * and make khubd collect PORT_STAT_C_SUSPEND to
-			 * stop that signaling.  Use 5 ms extra for safety,
-			 * like usb_port_resume() does.
+			 * stop that signaling.
 			 */
-			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
+			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
 			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
 		}
@@ -1126,6 +1128,11 @@
 #define	PLATFORM_DRIVER		ehci_orion_driver
 #endif
 
+#if defined(CONFIG_ARCH_FEROCEON) || defined(CONFIG_MARVELL)
+#include "ehci_marvell.c"
+#define PLATFORM_DRIVER         ehci_marvell_driver
+#endif
+
 #ifdef CONFIG_ARCH_IXP4XX
 #include "ehci-ixp4xx.c"
 #define	PLATFORM_DRIVER		ixp4xx_ehci_driver
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
old mode 100644
new mode 100755
index 698f461..1b6f1c0
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -120,26 +120,9 @@
 	del_timer_sync(&ehci->watchdog);
 	del_timer_sync(&ehci->iaa_watchdog);
 
+	port = HCS_N_PORTS (ehci->hcs_params);
 	spin_lock_irq (&ehci->lock);
 
-	/* Once the controller is stopped, port resumes that are already
-	 * in progress won't complete.  Hence if remote wakeup is enabled
-	 * for the root hub and any ports are in the middle of a resume or
-	 * remote wakeup, we must fail the suspend.
-	 */
-	if (hcd->self.root_hub->do_remote_wakeup) {
-		port = HCS_N_PORTS(ehci->hcs_params);
-		while (port--) {
-			if (ehci->reset_done[port] != 0) {
-				spin_unlock_irq(&ehci->lock);
-				ehci_dbg(ehci, "suspend failed because "
-						"port %d is resuming\n",
-						port + 1);
-				return -EBUSY;
-			}
-		}
-	}
-
 	/* stop schedules, clean any completed work */
 	if (HC_IS_RUNNING(hcd->state)) {
 		ehci_quiesce (ehci);
@@ -155,7 +138,6 @@
 	 */
 	ehci->bus_suspended = 0;
 	ehci->owned_ports = 0;
-	port = HCS_N_PORTS(ehci->hcs_params);
 	while (port--) {
 		u32 __iomem	*reg = &ehci->regs->port_status [port];
 		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
old mode 100644
new mode 100755
index c0d4b39..d35e06e
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -822,16 +822,7 @@
 			qh->gap_uf = 0;
 
 			qh->period = urb->interval >> 3;
-			if (qh->period == 0 && urb->interval != 1) {
-				/* NOTE interval 2 or 4 uframes could work.
-				 * But interval 1 scheduling is simpler, and
-				 * includes high bandwidth.
-				 */
-				urb->interval = 1;
-			} else if (qh->period > ehci->periodic_size) {
-				qh->period = ehci->periodic_size;
-				urb->interval = qh->period << 3;
-			}
+			qh->u_period = urb->interval;
 		} else {
 			int		think_time;
 
@@ -853,10 +844,7 @@
 					usb_calc_bus_time (urb->dev->speed,
 					is_input, 0, max_packet (maxp)));
 			qh->period = urb->interval;
-			if (qh->period > ehci->periodic_size) {
-				qh->period = ehci->periodic_size;
-				urb->interval = qh->period;
-			}
+			qh->u_period = (unsigned short)~0;
 		}
 	}
 
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
old mode 100644
new mode 100755
index 5cc3f48..09713f4
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -208,7 +208,7 @@
 }
 
 static const unsigned char
-max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 };
+max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 100 };
 
 /* carryover low/fullspeed bandwidth that crosses uframe boundries */
 static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
@@ -278,10 +278,6 @@
 	}
 
 	carryover_tt_bandwidth(tt_usecs);
-
-	if (max_tt_usecs[7] < tt_usecs[7])
-		ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n",
-			frame, tt_usecs[7] - max_tt_usecs[7]);
 }
 
 /*
@@ -464,7 +460,7 @@
 	 */
 	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
 					     STS_PSS, 0, 9 * 125);
-	if (status)
+	if (status) 
 		return status;
 
 	cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
@@ -503,13 +499,15 @@
 	 */
 	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
 					     STS_PSS, STS_PSS, 9 * 125);
-	if (status)
+	if (status) 
 		return status;
 
 	cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
 	ehci_writel(ehci, cmd, &ehci->regs->command);
 	/* posted write ... */
 
+	free_cached_itd_list(ehci);
+
 	ehci->next_uframe = -1;
 	return 0;
 }
@@ -718,8 +716,11 @@
 	} else {
 		do {
 			claimed = periodic_usecs (ehci, frame, uframe);
-			if (claimed > usecs)
+			if (claimed > usecs) {
+				ehci_dbg(ehci, "check_period FAILED: claimed=%d"
+					 ", usecs=%d\n", claimed, usecs);
 				return 0;
+			}
 		} while ((frame += period) < ehci->periodic_size);
 	}
 
@@ -741,8 +742,11 @@
 	if (qh->c_usecs && uframe >= 6)		/* FSTN territory? */
 		goto done;
 
-	if (!check_period (ehci, frame, uframe, qh->period, qh->usecs))
+	if (!check_period(ehci, frame, uframe, qh->period, qh->usecs)) {
+		ehci_dbg(ehci, "check_intr_schedule: usecs=%d FAILED\n",
+			 qh->usecs);
 		goto done;
+	}
 	if (!qh->c_usecs) {
 		retval = 0;
 		*c_maskp = 0;
@@ -750,22 +754,26 @@
 	}
 
 #ifdef CONFIG_USB_EHCI_TT_NEWSCHED
-	if (tt_available (ehci, qh->period, qh->dev, frame, uframe,
+	if (tt_available(ehci, qh->period, qh->dev, frame, uframe+2,
 				qh->tt_usecs)) {
 		unsigned i;
 
 		/* TODO : this may need FSTN for SSPLIT in uframe 5. */
-		for (i=uframe+1; i<8 && i<uframe+4; i++)
+		for (i = uframe+2; i < 8 && i < uframe+5; i++)
 			if (!check_period (ehci, frame, i,
-						qh->period, qh->c_usecs))
+					   qh->period, qh->c_usecs)){
+				ehci_dbg(ehci, "check_intr_schedule: FAILED - "
+					 "frame=%d, uframe=%d, i=%d\n",
+					 frame, uframe, i);
 				goto done;
-			else
+			} else
 				mask |= 1 << i;
 
 		retval = 0;
 
 		*c_maskp = cpu_to_hc32(ehci, mask << 8);
-	}
+	} else
+		ehci_dbg(ehci, "check_intr_schedule: tt_available FAILED\n");
 #else
 	/* Make sure this tt's buffer is also available for CSPLITs.
 	 * We pessimize a bit; probably the typical full speed case
@@ -799,7 +807,7 @@
 {
 	int		status;
 	unsigned	uframe;
-	__hc32		c_mask;
+	__hc32		c_mask, s_mask = 0;
 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
 	struct ehci_qh_hw	*hw = qh->hw;
 
@@ -837,10 +845,19 @@
 				}
 			}
 
+			s_mask = (1 << uframe);
+
 		/* qh->period == 0 means every uframe */
 		} else {
+			uframe = 0;
 			frame = 0;
 			status = check_intr_schedule (ehci, 0, 0, qh, &c_mask);
+
+			/* set s_mask */
+			while(uframe < 8) {
+				s_mask |= (1 << uframe);
+				uframe += qh->u_period;
+			}	
 		}
 		if (status)
 			goto done;
@@ -848,12 +865,10 @@
 
 		/* reset S-frame and (maybe) C-frame masks */
 		hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
-		hw->hw_info2 |= qh->period
-			? cpu_to_hc32(ehci, 1 << uframe)
-			: cpu_to_hc32(ehci, QH_SMASK);
+		hw->hw_info2 |= cpu_to_hc32(ehci, s_mask);
 		hw->hw_info2 |= c_mask;
 	} else
-		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
+		ehci_dbg(ehci, "reused qh %p schedule\n", qh);
 
 	/* stuff into the periodic schedule */
 	status = qh_link_periodic (ehci, qh);
@@ -895,8 +910,11 @@
 		goto done;
 	}
 	if (qh->qh_state == QH_STATE_IDLE) {
-		if ((status = qh_schedule (ehci, qh)) != 0)
+		if ((status = qh_schedule(ehci, qh)) != 0) {
+			ehci_err(ehci, "intr_submit - qh_schedule FAILED: "
+				 "status=%d\n", status);
 			goto done;
+		}
 	}
 
 	/* then queue the urb's tds to the qh */
@@ -1247,8 +1265,8 @@
 		if (likely (!list_empty(&stream->free_list))) {
 			itd = list_entry (stream->free_list.prev,
 					struct ehci_itd, itd_list);
-			list_del (&itd->itd_list);
-			itd_dma = itd->itd_dma;
+				list_del (&itd->itd_list);
+				itd_dma = itd->itd_dma;
 		} else {
 			spin_unlock_irqrestore (&ehci->lock, flags);
 			itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
@@ -1367,7 +1385,7 @@
 		}
 
 		/* we know urb->interval is 2^N uframes */
-		uframe += period_uframes;
+	uframe += period_uframes;
 	} while (uframe < mod);
 
 	stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7));
@@ -1400,13 +1418,14 @@
 	struct ehci_iso_sched	*sched = urb->hcpriv;
 
 	if (sched->span > (mod - 8 * SCHEDULE_SLOP)) {
-		ehci_dbg (ehci, "iso request %p too long\n", urb);
+		ehci_dbg(ehci, "iso request %p too long: (%d > (%d - 80))\n",
+			 urb, sched->span, mod);
 		status = -EFBIG;
 		goto fail;
 	}
 
-	if ((stream->depth + sched->span) > mod) {
-		ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n",
+	if ((stream->depth + sched->span) >= mod) {
+		ehci_dbg(ehci, "request %p would overflow ((%d + %d) > %d)\n",
 			urb, stream->depth, sched->span, mod);
 		status = -EFBIG;
 		goto fail;
@@ -1438,10 +1457,13 @@
 
 		/* Tried to schedule too far into the future? */
 		if (unlikely((start + sched->span) >= max)) {
+			ehci_dbg(ehci, "iso request %p too far into the future"
+				 " (%d + %d >= %d)\n",
+				 urb, start, sched->span, max);
 			status = -EFBIG;
 			goto fail;
 		}
-		stream->next_uframe = start;
+		stream->next_uframe = start % mod;
 		goto ready;
 	}
 
@@ -1480,7 +1502,7 @@
 	}
 
 	/* no room in the schedule */
-	ehci_dbg (ehci, "iso %ssched full %p (now %d max %d)\n",
+	ehci_dbg(ehci, "iso %ssched full %p (now %d max %d)\n",
 		list_empty (&stream->td_list) ? "" : "re",
 		urb, now, max);
 	status = -ENOSPC;
@@ -1726,7 +1748,9 @@
 	ehci_urb_done(ehci, urb, 0);
 	retval = true;
 	urb = NULL;
+
 	(void) disable_periodic(ehci);
+
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 	if (unlikely(list_is_singular(&stream->td_list))) {
@@ -1843,8 +1867,8 @@
 	unsigned	i;
 	dma_addr_t	dma = urb->transfer_dma;
 
-	/* how many frames are needed for these transfers */
-	iso_sched->span = urb->number_of_packets * stream->interval;
+	/* how many uframes are needed for these transfers */
+	iso_sched->span = urb->number_of_packets * stream->interval * 8;
 
 	/* figure out per-frame sitd fields that we'll need later
 	 * when we fit new sitds into the schedule.
@@ -2115,8 +2139,10 @@
 	ehci_urb_done(ehci, urb, 0);
 	retval = true;
 	urb = NULL;
+
 	(void) disable_periodic(ehci);
-	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
+	
+    	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 	if (list_is_singular(&stream->td_list)) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
@@ -2148,28 +2174,28 @@
 	/* Get iso_stream head */
 	stream = iso_stream_find (ehci, urb);
 	if (stream == NULL) {
-		ehci_dbg (ehci, "can't get iso stream\n");
+		ehci_err(ehci, "can't get iso stream\n");
 		return -ENOMEM;
 	}
 	if (urb->interval != stream->interval) {
-		ehci_dbg (ehci, "can't change iso interval %d --> %d\n",
+		ehci_err(ehci, "can't change iso interval %d --> %d\n",
 			stream->interval, urb->interval);
 		goto done;
 	}
 
 #ifdef EHCI_URB_TRACE
-	ehci_dbg (ehci,
-		"submit %p dev%s ep%d%s-iso len %d\n",
-		urb, urb->dev->devpath,
-		usb_pipeendpoint (urb->pipe),
-		usb_pipein (urb->pipe) ? "in" : "out",
-		urb->transfer_buffer_length);
+	ehci_dbg(ehci,
+		 "submit %p dev%s ep%d%s-iso len %d\n",
+		 urb, urb->dev->devpath,
+		 usb_pipeendpoint (urb->pipe),
+		 usb_pipein(urb->pipe) ? "in" : "out",
+		 urb->transfer_buffer_length);
 #endif
 
 	/* allocate SITDs */
 	status = sitd_urb_transaction (stream, ehci, urb, mem_flags);
 	if (status < 0) {
-		ehci_dbg (ehci, "can't init sitds\n");
+		ehci_err(ehci, "can't init sitds\n");
 		goto done;
 	}
 
@@ -2186,8 +2212,10 @@
 	status = iso_stream_schedule(ehci, urb, stream);
 	if (status == 0)
 		sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
-	else
+    else {
+	    ehci_err(ehci, "sitd_submit: can't schedule iso stream\n");
 		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+    }
 done_not_linked:
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -2290,7 +2318,7 @@
 				 * No need to check for activity unless the
 				 * frame is current.
 				 */
-				if (frame == clock_frame && live) {
+				if ((frame == clock_frame) && live) {
 					rmb();
 					for (uf = 0; uf < 8; uf++) {
 						if (q.itd->hw_transaction[uf] &
@@ -2326,9 +2354,13 @@
 				 * No need to check for activity unless the
 				 * frame is current.
 				 */
-				if (frame == clock_frame && live &&
-						(q.sitd->hw_results &
-							SITD_ACTIVE(ehci))) {
+				if (((frame == clock_frame) ||
+				     (((frame + 1) % ehci->periodic_size)
+				      == clock_frame))
+				    && live
+				    && (q.sitd->hw_results &
+					SITD_ACTIVE(ehci))) {
+
 					incomplete = true;
 					q_p = &q.sitd->sitd_next;
 					hw_p = &q.sitd->hw_next;
@@ -2350,17 +2382,21 @@
 				q = *q_p;
 				break;
 			default:
-				dbg ("corrupt type %d frame %d shadow %p",
-					type, frame, q.ptr);
+				ehci_dbg(ehci, "corrupt type %d frame %d shadow"
+					 " %p\n",
+					 type, frame, q.ptr);
 				// BUG ();
 				q.ptr = NULL;
 			}
 
 			/* assume completion callbacks modify the queue */
 			if (unlikely (modified)) {
-				if (likely(ehci->periodic_sched > 0))
+				if (likely(ehci->periodic_sched > 0)) {
+//					restarted = 1;
 					goto restart;
-				/* short-circuit this scan */
+				}
+				/* maybe we can short-circuit this scan! */
+				/*disable_periodic(ehci);*/
 				now_uframe = clock;
 				break;
 			}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
old mode 100644
new mode 100755
index b1dce96..24b24c5
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -361,6 +361,7 @@
 	u16			tt_usecs;	/* tt downstream bandwidth */
 	unsigned short		period;		/* polling interval */
 	unsigned short		start;		/* where polling starts */
+	unsigned short		u_period;	/* polling interval in uframes */
 #define NO_FRAME ((unsigned short)~0)			/* pick new start */
 
 	struct usb_device	*dev;		/* access to TT */
diff --git a/drivers/usb/host/ehci_marvell.c b/drivers/usb/host/ehci_marvell.c
new file mode 100755
index 0000000..0b84df1
--- /dev/null
+++ b/drivers/usb/host/ehci_marvell.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2000-2002 by Dima Epshtein
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* #define DRIVER_AUTHOR "Dima Epshtein" */
+
+
+#ifdef CONFIG_USB_DEBUG
+    #define DEBUG
+#else
+    #undef DEBUG
+#endif
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "ehci.h"
+
+/* Special bits in Port status regsiter */
+#define PORT_SPEED_OFFS		26
+#define PORT_SPEED_MASK		0x3
+#define PORT_SPEED_FULL		0
+#define PORT_SPEED_LOW		1
+#define PORT_SPEED_HIGH		2
+
+static int ehci_marvell_setup(struct usb_hcd *hcd);
+
+
+void 	ehci_marvell_port_status_changed(struct ehci_hcd *ehci)
+{
+	/* GL USB-19:USB Configuration for LS Eye Pattern Test - DD and KW */
+#if defined(CONFIG_ARCH_FEROCEON_KW2) || defined(CONFIG_ARCH_FEROCEON_KW) || defined(CONFIG_ARCH_FEROCEON_MV78XX0)
+	u32 __iomem 	*reg_ptr;
+	u32 		port_status, phy_val;
+
+	/* Change PHY Tx Control Register: offset 0x420 = 0x140 + 0x2e0 */
+    	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x2e0);
+    	phy_val = ehci_readl(ehci, reg_ptr);
+
+	port_status = ehci_readl(ehci, &ehci->regs->port_status[0]); 	
+	if( (port_status & PORT_CONNECT) && 
+            (((port_status >> PORT_SPEED_OFFS) & PORT_SPEED_MASK) == PORT_SPEED_LOW) )
+	{
+		/* If Low speed device is connected - disable autocalibration */
+		/* bits[27-30] = 0, bit[26] = 1 */
+		phy_val &= ~(0xF << 27);
+		phy_val |= (1 << 26);	
+	}
+	else
+	{
+		/* Nothing connected or FS/HS devices connected - enable autocalibration */
+		phy_val &= ~(1 << 26);
+	}
+	ehci_writel(ehci, phy_val, reg_ptr);
+#endif /* CONFIG_ARCH_FEROCEON_KW2 || CONFIG_ARCH_FEROCEON_KW || CONFIG_ARCH_FEROCEON_MV78XX0 */
+}
+
+static const struct hc_driver ehci_marvell_hc_driver = {
+        .description = hcd_name,
+        .product_desc = "Marvell Orion EHCI",
+        .hcd_priv_size = sizeof(struct ehci_hcd),
+
+        /*
+         * generic hardware linkage
+         */
+        .irq = ehci_irq,
+        .flags = HCD_USB2,
+
+        /*
+         * basic lifecycle operations
+         */
+        .reset = ehci_marvell_setup,
+        .start = ehci_run,
+#ifdef CONFIG_PM
+        .bus_suspend = ehci_bus_suspend,
+        .bus_resume = ehci_bus_resume,
+#endif
+        .stop = ehci_stop,
+        .shutdown = ehci_shutdown,
+
+        /*
+         * managing i/o requests and associated device resources
+         */
+        .urb_enqueue = ehci_urb_enqueue,
+        .urb_dequeue = ehci_urb_dequeue,
+        .endpoint_disable = ehci_endpoint_disable,
+		.endpoint_reset = ehci_endpoint_reset,
+
+        /*
+         * scheduling support
+         */
+        .get_frame_number = ehci_get_frame,
+
+        /*
+         * root hub support
+         */
+        .hub_status_data = ehci_hub_status_data,
+        .hub_control = ehci_hub_control,
+        .bus_suspend = ehci_bus_suspend,
+        .bus_resume = ehci_bus_resume,
+		.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_marvell_setup(struct usb_hcd *hcd)
+{
+        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+        int retval;
+
+        /*
+         * registers start at offset
+         */
+        ehci->caps = hcd->regs;
+        ehci->regs = hcd->regs +
+                HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+        /*
+         * cache this readonly data; minimize chip reads
+         */
+        ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+        retval = ehci_halt(ehci);
+        if (retval)
+                return retval;
+
+        /*
+         * data structure init
+         */
+        retval = ehci_init(hcd);
+        if (retval)
+                return retval;
+
+	hcd->has_tt = 1;
+
+        ehci->sbrn = 0x20;
+
+        ehci_reset(ehci);
+
+        ehci_port_power(ehci, 0);
+
+        return retval;
+}
+
+static int ehci_marvell_probe(struct platform_device *pdev)
+{ 
+    int                     i, retval; 
+    struct usb_hcd          *hcd = NULL; 
+ 
+    hcd = usb_create_hcd (&ehci_marvell_hc_driver, &pdev->dev, dev_name(&pdev->dev));
+    if (hcd == NULL) 
+    { 
+        printk("%s: hcd_alloc failed\n", __FUNCTION__); 
+        return -ENOMEM; 
+    } 
+ 
+    for(i=0; i<pdev->num_resources; i++)
+    {
+        if(pdev->resource[i].flags == IORESOURCE_IRQ)
+        {
+            hcd->irq = pdev->resource[i].start; 
+        }
+        else if(pdev->resource[i].flags == IORESOURCE_DMA)
+        {
+            hcd->regs = (void *)pdev->resource[i].start; 
+    	    hcd->rsrc_start = pdev->resource[i].start;
+    	    hcd->rsrc_len = pdev->resource[i].end - hcd->rsrc_start + 1;
+        }
+    }     
+
+    retval = usb_add_hcd (hcd, hcd->irq, IRQF_SHARED);
+	if (retval != 0)
+    {
+        printk("%s: usb_add_hcd failed, retval=0x%x\n", __FUNCTION__, retval); 
+        return -ENOMEM; 
+    }    
+ 
+    return 0; 
+} 
+
+static int ehci_marvell_remove(struct platform_device *pdev)
+{ 
+    struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+    printk("USB: ehci_marvell_remove\n"); 
+   
+    usb_remove_hcd (hcd); 
+    usb_put_hcd (hcd);
+
+   return 0;
+} 
+ 
+ 
+static struct platform_driver ehci_marvell_driver =  
+{ 
+    .driver.name = "ehci_marvell", 
+    .probe = ehci_marvell_probe, 
+    .remove = ehci_marvell_remove,
+    .shutdown = usb_hcd_platform_shutdown, 
+};  
+
+
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
old mode 100644
new mode 100755
index 0919706..3ffa1f5
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -750,20 +750,7 @@
 	spin_lock_irq(&uhci->lock);
 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
 		rc = -ESHUTDOWN;
-	else if (uhci->dead)
-		;		/* Dead controllers tell no tales */
-
-	/* Once the controller is stopped, port resumes that are already
-	 * in progress won't complete.  Hence if remote wakeup is enabled
-	 * for the root hub and any ports are in the middle of a resume or
-	 * remote wakeup, we must fail the suspend.
-	 */
-	else if (hcd->self.root_hub->do_remote_wakeup &&
-			uhci->resuming_ports) {
-		dev_dbg(uhci_dev(uhci), "suspend failed because a port "
-				"is resuming\n");
-		rc = -EBUSY;
-	} else
+	else if (!uhci->dead)
 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
 	spin_unlock_irq(&uhci->lock);
 	return rc;
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
old mode 100644
new mode 100755
index 8270055..885b585
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -167,7 +167,7 @@
 				/* Port received a wakeup request */
 				set_bit(port, &uhci->resuming_ports);
 				uhci->ports_timeout = jiffies +
-						msecs_to_jiffies(25);
+						msecs_to_jiffies(20);
 
 				/* Make sure we see the port again
 				 * after the resuming period is over. */
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
old mode 100644
new mode 100755
index a9f06d7..cdfa3e8
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -62,6 +62,7 @@
 	struct usbtest_info	*info;
 	int			in_pipe;
 	int			out_pipe;
+	struct usb_endpoint_descriptor	*in_desc, *out_desc;
 	int			in_iso_pipe;
 	int			out_iso_pipe;
 	struct usb_endpoint_descriptor	*iso_in, *iso_out;
@@ -77,7 +78,7 @@
 }
 
 /* set up all urbs so they can be used with either bulk or interrupt */
-#define	INTERRUPT_RATE		1	/* msec/transfer */
+#define UNLINK_RATE     1   /* msec */
 
 #define ERROR(tdev, fmt, args...) \
 	dev_err(&(tdev)->intf->dev , fmt , ## args)
@@ -111,6 +112,7 @@
 			e = alt->endpoint + ep;
 			switch (e->desc.bmAttributes) {
 			case USB_ENDPOINT_XFER_BULK:
+			case USB_ENDPOINT_XFER_INT:
 				break;
 			case USB_ENDPOINT_XFER_ISOC:
 				if (dev->info->iso)
@@ -152,10 +154,22 @@
 	}
 
 	if (in) {
-		dev->in_pipe = usb_rcvbulkpipe (udev,
-			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-		dev->out_pipe = usb_sndbulkpipe (udev,
-			out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+        if(in->desc.bmAttributes == USB_ENDPOINT_XFER_INT) {
+            dev->in_pipe = usb_rcvintpipe (udev, 
+                        in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+            if(out)         
+                dev->out_pipe = usb_sndintpipe (udev, 
+                        out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+        }
+        else {
+			dev->in_pipe = usb_rcvbulkpipe (udev,
+				in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+			if(out)
+				dev->out_pipe = usb_sndbulkpipe (udev,
+					out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+        }
+        dev->in_desc = &in->desc;
+        dev->out_desc = &out->desc;
 	}
 	if (iso_in) {
 		dev->iso_in = &iso_in->desc;
@@ -186,19 +200,29 @@
 
 static struct urb *simple_alloc_urb (
 	struct usb_device	*udev,
-	int			pipe,
+	int					pipe,
+	struct usb_endpoint_descriptor *desc,
 	unsigned long		bytes
 )
 {
 	struct urb		*urb;
 
+	if (bytes < 0)
+		return NULL;
+
 	urb = usb_alloc_urb (0, GFP_KERNEL);
 	if (!urb)
 		return urb;
+
 	usb_fill_bulk_urb (urb, udev, pipe, NULL, bytes, simple_callback, NULL);
-	urb->interval = (udev->speed == USB_SPEED_HIGH)
-			? (INTERRUPT_RATE << 3)
-			: INTERRUPT_RATE;
+
+    if(desc != NULL) {
+        if( (udev->speed == USB_SPEED_HIGH) || 
+            ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC) )
+            urb->interval = (1 << (desc->bInterval - 1));
+        else
+            urb->interval = desc->bInterval;
+    }
 	urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 	if (usb_pipein (pipe))
 		urb->transfer_flags |= URB_SHORT_NOT_OK;
@@ -248,12 +272,12 @@
 		case 0:
 			expected = 0;
 			break;
-		/* mod63 stays in sync with short-terminated transfers,
-		 * or otherwise when host and gadget agree on how large
-		 * each usb transfer request should be.  resync is done
-		 * with set_interface or set_config.
-		 */
-		case 1:			/* mod63 */
+		/* mod255 stays in sync with short-terminated transfers,
+         * or otherwise when host and gadget agree on how large
+         * each usb transfer request should be.  resync is done
+         * with set_interface or set_config.
+         */
+        case 1:         /* mod 255 */
 			expected = i % 63;
 			break;
 		/* always fail unsupported patterns */
@@ -271,9 +295,12 @@
 
 static void simple_free_urb (struct urb *urb)
 {
-	usb_buffer_free (urb->dev, urb->transfer_buffer_length,
-			urb->transfer_buffer, urb->transfer_dma);
-	usb_free_urb (urb);
+	if(urb != NULL)
+	{	
+		if((urb->transfer_buffer != NULL) && (urb->transfer_buffer_length > 0))
+    		usb_buffer_free (urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma);
+    	usb_free_urb (urb);
+	}
 }
 
 static int simple_io (
@@ -357,6 +384,7 @@
 	sg = kmalloc (nents * sizeof *sg, GFP_KERNEL);
 	if (!sg)
 		return NULL;
+	memset(sg, 0, nents * sizeof *sg);
 	sg_init_table(sg, nents);
 
 	for (i = 0; i < nents; i++) {
@@ -395,25 +423,32 @@
 
 static int perform_sglist (
 	struct usbtest_dev	*tdev,
-	unsigned		iterations,
-	int			pipe,
+	unsigned			iterations,
+	int					pipe,
+	struct usb_endpoint_descriptor *desc,
 	struct usb_sg_request	*req,
 	struct scatterlist	*sg,
-	int			nents
+	int					nents
 )
 {
 	struct usb_device	*udev = testdev_to_usbdev(tdev);
 	int			retval = 0;
+	int         interval = 0;
 
 	while (retval == 0 && iterations-- > 0) {
-		retval = usb_sg_init (req, udev, pipe,
-				(udev->speed == USB_SPEED_HIGH)
-					? (INTERRUPT_RATE << 3)
-					: INTERRUPT_RATE,
-				sg, nents, 0, GFP_KERNEL);
+        if(desc != NULL) {
+            if( (udev->speed == USB_SPEED_HIGH) || 
+                ( (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC) )
+                interval = (1 << (desc->bInterval - 1));
+            else
+                interval = desc->bInterval;
+        }
 
+		retval = usb_sg_init (req, udev, pipe, interval,
+				                sg, nents, 0, GFP_KERNEL);		
 		if (retval)
 			break;
+
 		usb_sg_wait (req);
 		retval = req->status;
 
@@ -972,7 +1007,7 @@
 			goto cleanup;
 		}
 		req.wLength = cpu_to_le16 (len);
-		urb [i] = u = simple_alloc_urb (udev, pipe, len);
+		urb [i] = u = simple_alloc_urb (udev, pipe, NULL, len);
 		if (!u)
 			goto cleanup;
 
@@ -1043,14 +1078,15 @@
 	}
 }
 
-static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
+static int unlink1 (struct usbtest_dev *dev, int pipe, 
+                    struct usb_endpoint_descriptor *desc, int size, int async)
 {
 	struct urb		*urb;
 	struct completion	completion;
 	int			retval = 0;
 
 	init_completion (&completion);
-	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
+	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, desc, size);
 	if (!urb)
 		return -ENOMEM;
 	urb->context = &completion;
@@ -1070,7 +1106,7 @@
 	/* unlinking that should always work.  variable delay tests more
 	 * hcd states and code paths, even with little other system load.
 	 */
-	msleep (jiffies % (2 * INTERRUPT_RATE));
+	msleep (jiffies % (2 * UNLINK_RATE));
 	if (async) {
 		while (!completion_done(&completion)) {
 			retval = usb_unlink_urb(urb);
@@ -1112,14 +1148,15 @@
 				0 : retval - 2000;
 }
 
-static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
+static int unlink_simple (struct usbtest_dev *dev, int pipe, 
+                          struct usb_endpoint_descriptor *desc, int len)
 {
 	int			retval = 0;
 
 	/* test sync and async paths */
-	retval = unlink1 (dev, pipe, len, 1);
+	retval = unlink1 (dev, pipe, desc, len, 1);
 	if (!retval)
-		retval = unlink1 (dev, pipe, len, 0);
+		retval = unlink1 (dev, pipe, desc, len, 0);
 	return retval;
 }
 
@@ -1216,7 +1253,7 @@
 	int		retval = 0;
 	struct urb	*urb;
 
-	urb = simple_alloc_urb (testdev_to_usbdev (dev), 0, 512);
+	urb = simple_alloc_urb (testdev_to_usbdev (dev), 0, NULL, 512);
 	if (urb == NULL)
 		return -ENOMEM;
 
@@ -1382,7 +1419,6 @@
 			break;
 		}
 	}
-	simple_free_urb (urb);
 
 	ctx->pending--;
 	if (ctx->pending == 0) {
@@ -1408,6 +1444,7 @@
 
 	if (bytes < 0 || !desc)
 		return NULL;
+
 	maxp = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
 	maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
 	packets = DIV_ROUND_UP(bytes, maxp);
@@ -1448,12 +1485,12 @@
 {
 	struct iso_context	context;
 	struct usb_device	*udev;
-	unsigned		i;
+	unsigned			i;
 	unsigned long		packets = 0;
-	int			status = 0;
-	struct urb		*urbs[10];	/* FIXME no limit */
+	int					status = 0;
+	struct urb			*urbs[50];  /* FIXME no limit */
 
-	if (param->sglen > 10)
+	if (param->sglen > 50)
 		return -EDOM;
 
 	memset(&context, 0, sizeof context);
@@ -1497,8 +1534,6 @@
 				spin_unlock_irq (&context.lock);
 				goto fail;
 			}
-
-			simple_free_urb (urbs [i]);
 			context.pending--;
 			context.submit_error = 1;
 			break;
@@ -1519,12 +1554,11 @@
 		status = -EACCES;
 	else if (context.errors > context.packet_count / 10)
 		status = -EIO;
-	return status;
 
 fail:
 	for (i = 0; i < param->sglen; i++) {
 		if (urbs [i])
-			simple_free_urb (urbs [i]);
+			simple_free_urb (urbs [i]);	
 	}
 	return status;
 }
@@ -1627,7 +1661,7 @@
 		dev_info(&intf->dev,
 				"TEST 1:  write %d bytes %u times\n",
 				param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
+		urb = simple_alloc_urb (udev, dev->out_pipe, dev->out_desc, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
@@ -1642,7 +1676,7 @@
 		dev_info(&intf->dev,
 				"TEST 2:  read %d bytes %u times\n",
 				param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
+		urb = simple_alloc_urb (udev, dev->in_pipe, dev->in_desc, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
@@ -1657,7 +1691,7 @@
 		dev_info(&intf->dev,
 				"TEST 3:  write/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
+		urb = simple_alloc_urb (udev, dev->out_pipe, dev->out_desc, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
@@ -1673,7 +1707,7 @@
 		dev_info(&intf->dev,
 				"TEST 4:  read/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
+		urb = simple_alloc_urb (udev, dev->in_pipe, dev->in_desc, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
@@ -1699,7 +1733,7 @@
 		}
 		// FIRMWARE:  bulk sink (maybe accepts short writes)
 		retval = perform_sglist(dev, param->iterations, dev->out_pipe,
-				&req, sg, param->sglen);
+				dev->out_desc, &req, sg, param->sglen);
 		free_sglist (sg, param->sglen);
 		break;
 
@@ -1717,7 +1751,7 @@
 		}
 		// FIRMWARE:  bulk source (maybe generates short writes)
 		retval = perform_sglist(dev, param->iterations, dev->in_pipe,
-				&req, sg, param->sglen);
+				dev->in_desc, &req, sg, param->sglen);
 		free_sglist (sg, param->sglen);
 		break;
 	case 7:
@@ -1734,7 +1768,7 @@
 		}
 		// FIRMWARE:  bulk sink (maybe accepts short writes)
 		retval = perform_sglist(dev, param->iterations, dev->out_pipe,
-				&req, sg, param->sglen);
+				dev->out_desc, &req, sg, param->sglen);
 		free_sglist (sg, param->sglen);
 		break;
 	case 8:
@@ -1751,7 +1785,7 @@
 		}
 		// FIRMWARE:  bulk source (maybe generates short writes)
 		retval = perform_sglist(dev, param->iterations, dev->in_pipe,
-				&req, sg, param->sglen);
+				dev->in_desc, &req, sg, param->sglen);
 		free_sglist (sg, param->sglen);
 		break;
 
@@ -1788,7 +1822,7 @@
 		dev_info(&intf->dev, "TEST 11:  unlink %d reads of %d\n",
 				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = unlink_simple (dev, dev->in_pipe,
+			retval = unlink_simple (dev, dev->in_pipe, dev->in_desc,
 						param->length);
 		if (retval)
 			dev_err(&intf->dev, "unlink reads failed %d, "
@@ -1801,7 +1835,7 @@
 		dev_info(&intf->dev, "TEST 12:  unlink %d writes of %d\n",
 				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = unlink_simple (dev, dev->out_pipe,
+			retval = unlink_simple (dev, dev->out_pipe, dev->out_desc,
 						param->length);
 		if (retval)
 			dev_err(&intf->dev, "unlink writes failed %d, "
@@ -1967,10 +2001,22 @@
 				dev->out_pipe = usb_sndbulkpipe (udev,
 							info->ep_out);
 		}
-		if (dev->in_pipe)
-			rtest = " bulk-in";
-		if (dev->out_pipe)
-			wtest = " bulk-out";
+        if (dev->in_pipe) {
+            if(usb_pipeint(dev->in_pipe)) {
+                rtest = " intr-in";
+            }
+            else {
+                rtest = " bulk-in";
+            }
+        }           
+        if (dev->out_pipe){
+            if(usb_pipeint(dev->out_pipe)) {
+                wtest = " intr-out";
+            }
+            else {
+                wtest = " bulk-out";
+            }
+        }           
 		if (dev->in_iso_pipe)
 			irtest = " iso-in";
 		if (dev->out_iso_pipe)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
old mode 100644
new mode 100755
index 9cf4652..710cfc0
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -618,20 +618,6 @@
 	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_USPTL4_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_2_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR2_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_485USB9F_2W_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_485USB9F_4W_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_232USB9M_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_485USBTB_2W_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_485USBTB_4W_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_TTL5USB9M_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_TTL3USB9M_PID) },
-	{ USB_DEVICE(BANDB_VID, BANDB_ZZ_PROG1_USB_PID) },
 	{ USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
 	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
old mode 100644
new mode 100755
index e0fb294..bbe005c
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -489,8 +489,6 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	if (port->serial->type->max_in_flight_urbs) {
-		kfree(urb->transfer_buffer);
-
 		spin_lock_irqsave(&port->lock, flags);
 		--port->urbs_in_flight;
 		port->tx_bytes_flight -= urb->transfer_buffer_length;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
old mode 100644
new mode 100755
index 485fa9c..f11abf5
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -121,14 +121,8 @@
  * moschip_id_table_combined
  */
 #define USB_VENDOR_ID_BANDB             0x0856
-#define BANDB_DEVICE_ID_USO9ML2_2	0xAC22
-#define BANDB_DEVICE_ID_USO9ML2_4	0xAC24
-#define BANDB_DEVICE_ID_US9ML2_2	0xAC29
-#define BANDB_DEVICE_ID_US9ML2_4	0xAC30
-#define BANDB_DEVICE_ID_USPTL4_2	0xAC31
-#define BANDB_DEVICE_ID_USPTL4_4	0xAC32
-#define BANDB_DEVICE_ID_USOPTL4_2       0xAC42
 #define BANDB_DEVICE_ID_USOPTL4_4       0xAC44
+#define BANDB_DEVICE_ID_USOPTL4_2       0xAC42
 
 /* This driver also supports
  * ATEN UC2324 device using Moschip MCS7840
@@ -183,14 +177,8 @@
 static struct usb_device_id moschip_port_id_table[] = {
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
 	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
 	{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
 	{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
 	{}			/* terminating entry */
@@ -199,14 +187,8 @@
 static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
 	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
 	{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
 	{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
 	{}			/* terminating entry */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
old mode 100644
new mode 100755
index 4d0a208..3ac0de9
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1891,6 +1891,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_GO_SLOW ),
 
+/* Reported by Rohan Hart <rohan.hart17@gmail.com> */
+UNUSUAL_DEV(  0x2770, 0x915d, 0x0010, 0x0010,
+		"INTOVA",
+		"Pixtreme",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 /* Reported by Frederic Marchal <frederic.marchal@wowcompany.com>
  * Mio Moov 330
  */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
old mode 100644
new mode 100755
index 33197fa..716c8d7
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -430,8 +430,7 @@
 	u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
 	u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
 	unsigned f = 0;
-	unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE |
-			US_FL_FIX_CAPACITY |
+	unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY |
 			US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
 			US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
 			US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
old mode 100644
new mode 100755
index 3711b88..426fa8f
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -240,7 +240,7 @@
 
 config ORION_WATCHDOG
 	tristate "Orion watchdog"
-	depends on ARCH_ORION5X || ARCH_KIRKWOOD
+	depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_FEROCEON_KW
 	help
 	  Say Y here if to include support for the watchdog timer
 	  in the Marvell Orion5x and Kirkwood ARM SoCs.
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
old mode 100644
new mode 100755
index 699199b..7e24d03
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -42,6 +42,9 @@
 obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
 obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
 obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o
+ifeq ($(CONFIG_ARCH_FEROCEON),y)
+include $(srctree)/$(MACHINE)/config/mvRules.mk
+endif
 obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
 obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
diff --git a/fs/bio.c b/fs/bio.c
old mode 100644
new mode 100755
index e0c9e71..dc34387
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1141,9 +1141,17 @@
 
 static void bio_map_kern_endio(struct bio *bio, int err)
 {
-	bio_put(bio);
+	void *kaddr = bio->bi_private;
+	if (is_vmalloc_addr(kaddr)) {
+		void *addr;
+		for (addr = kaddr; addr < kaddr + bio->bi_size;
+		     addr += PAGE_SIZE)
+			invalidate_kernel_dcache_addr(addr);
+	}
+ 	bio_put(bio);
 }
 
+
 static struct bio *__bio_map_kern(struct request_queue *q, void *data,
 				  unsigned int len, gfp_t gfp_mask)
 {
@@ -1158,18 +1166,27 @@
 	if (!bio)
 		return ERR_PTR(-ENOMEM);
 
+	bio->bi_private = data;
+
 	offset = offset_in_page(kaddr);
 	for (i = 0; i < nr_pages; i++) {
 		unsigned int bytes = PAGE_SIZE - offset;
 
+        struct page *page;
+
 		if (len <= 0)
 			break;
 
 		if (bytes > len)
 			bytes = len;
 
-		if (bio_add_pc_page(q, bio, virt_to_page(data), bytes,
-				    offset) < bytes)
+		if (is_vmalloc_addr(data)) {
+			flush_kernel_dcache_addr(data);
+			page = vmalloc_to_page(data);
+		} else
+			page = virt_to_page(data);
+
+		if (bio_add_pc_page(q, bio, page, bytes, offset) < bytes)
 			break;
 
 		data += bytes;
diff --git a/fs/direct-io.c b/fs/direct-io.c
old mode 100644
new mode 100755
index 8b10b87..ad44642
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -36,7 +36,7 @@
 #include <linux/rwsem.h>
 #include <linux/uio.h>
 #include <asm/atomic.h>
-
+#include <linux/swap.h>
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
  * the size of a structure on the stack.
@@ -141,6 +141,33 @@
 	return dio->tail - dio->head;
 }
 
+/* 
+ * Get kernel pages.
+ */
+static int get_ker_pages(struct task_struct *tsk, struct mm_struct *mm,
+                unsigned long start, int len, int write, int force,
+                struct page **pages, struct vm_area_struct **vmas)
+{
+        int i = 0;
+
+        do {
+                if (pages) {
+                        pages[i] = virt_to_page(start);
+
+                        if (!pfn_valid(page_to_pfn(pages[i]))) {
+                                return i;
+                        }
+			get_page(pages[i]);
+                }
+                i++;
+                start += PAGE_SIZE;
+                len--;
+        } while(len );
+
+        return i;
+}
+
+
 /*
  * Go grab and pin some userspace pages.   Typically we'll get 64 at a time.
  */
@@ -150,11 +177,29 @@
 	int nr_pages;
 
 	nr_pages = min(dio->total_pages - dio->curr_page, DIO_PAGES);
+
+        /* If the page is a kernel page then we must give it a special treat. */
+        if ( virt_addr_valid(dio->curr_user_address) )
+        {
+                down_read(&init_mm.mmap_sem);
+                ret = get_ker_pages(
+                        current,                        /* Task for fault acounting */
+                        &init_mm,                       /* whose pages? */
+                        dio->curr_user_address,         /* Where from? */
+                        nr_pages,                       /* How many pages? */
+                        dio->rw == READ,                /* Write to memory? */
+                        0,                              /* force (?) */
+                        &dio->pages[0],
+                        NULL);                          /* vmas */
+                up_read(&init_mm.mmap_sem);
+                
+        } else {
 	ret = get_user_pages_fast(
 		dio->curr_user_address,		/* Where from? */
 		nr_pages,			/* How many pages? */
 		dio->rw == READ,		/* Write to memory? */
 		&dio->pages[0]);		/* Put results here */
+	}
 
 	if (ret < 0 && dio->blocks_available && (dio->rw & WRITE)) {
 		struct page *page = ZERO_PAGE(0);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
old mode 100644
new mode 100755
index f9d6937..8413e84
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1157,8 +1157,8 @@
  */
 static void ext3_truncate_failed_write(struct inode *inode)
 {
-	truncate_inode_pages(inode->i_mapping, inode->i_size);
-	ext3_truncate(inode);
+       truncate_inode_pages(inode->i_mapping, inode->i_size);
+       ext3_truncate(inode);
 }
 
 static int ext3_write_begin(struct file *file, struct address_space *mapping,
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
old mode 100644
new mode 100755
index 25a00d1..7ec5d7e
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -26,6 +26,12 @@
 
 	  If unsure, say N.
 
+config SQUASHFS_LZMA
+	bool "Include support for LZMA compressed file systems"
+	depends on SQUASHFS
+	select DECOMPRESS_LZMA
+	select DECOMPRESS_LZMA_NEEDED
+
 config SQUASHFS_EMBEDDED
 
 	bool "Additional option for memory-constrained systems" 
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
old mode 100644
new mode 100755
index 70e3244..45aaefd
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -4,4 +4,5 @@
 
 obj-$(CONFIG_SQUASHFS) += squashfs.o
 squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
-squashfs-y += namei.o super.o symlink.o
+squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
+squashfs-$(CONFIG_SQUASHFS_LZMA) += lzma_wrapper.o
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
old mode 100644
new mode 100755
index 2a79603..6f9914d
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -29,16 +29,14 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/buffer_head.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
 #include "squashfs_fs_i.h"
 #include "squashfs.h"
-
+#include "decompressor.h"
 /*
  * Read the metadata block length, this is stored in the first two
  * bytes of the metadata block.
@@ -153,72 +151,10 @@
 	}
 
 	if (compressed) {
-		int zlib_err = 0, zlib_init = 0;
-
-		/*
-		 * Uncompress block.
-		 */
-
-		mutex_lock(&msblk->read_data_mutex);
-
-		msblk->stream.avail_out = 0;
-		msblk->stream.avail_in = 0;
-
-		bytes = length;
-		do {
-			if (msblk->stream.avail_in == 0 && k < b) {
-				avail = min(bytes, msblk->devblksize - offset);
-				bytes -= avail;
-				wait_on_buffer(bh[k]);
-				if (!buffer_uptodate(bh[k]))
-					goto release_mutex;
-
-				if (avail == 0) {
-					offset = 0;
-					put_bh(bh[k++]);
-					continue;
-				}
-
-				msblk->stream.next_in = bh[k]->b_data + offset;
-				msblk->stream.avail_in = avail;
-				offset = 0;
-			}
-
-			if (msblk->stream.avail_out == 0 && page < pages) {
-				msblk->stream.next_out = buffer[page++];
-				msblk->stream.avail_out = PAGE_CACHE_SIZE;
-			}
-
-			if (!zlib_init) {
-				zlib_err = zlib_inflateInit(&msblk->stream);
-				if (zlib_err != Z_OK) {
-					ERROR("zlib_inflateInit returned"
-						" unexpected result 0x%x,"
-						" srclength %d\n", zlib_err,
-						srclength);
-					goto release_mutex;
-				}
-				zlib_init = 1;
-			}
-
-			zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
-
-			if (msblk->stream.avail_in == 0 && k < b)
-				put_bh(bh[k++]);
-		} while (zlib_err == Z_OK);
-
-		if (zlib_err != Z_STREAM_END) {
-			ERROR("zlib_inflate error, data probably corrupt\n");
-			goto release_mutex;
-		}
-
-		zlib_err = zlib_inflateEnd(&msblk->stream);
-		if (zlib_err != Z_OK) {
-			ERROR("zlib_inflate error, data probably corrupt\n");
-			goto release_mutex;
-		}
-		length = msblk->stream.total_out;
-		mutex_unlock(&msblk->read_data_mutex);
+		length = squashfs_decompress(msblk, buffer, bh, b, offset,
+			length, srclength, pages);
+		if (length < 0)
+			goto read_failure;
 	} else {
 		/*
 		 * Block is uncompressed.
@@ -255,9 +191,6 @@
 	kfree(bh);
 	return length;
 
-release_mutex:
-	mutex_unlock(&msblk->read_data_mutex);
-
 block_release:
 	for (; k < b; k++)
 		put_bh(bh[k]);
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
old mode 100644
new mode 100755
index 40c98fa..57314be
--- a/fs/squashfs/cache.c
+++ b/fs/squashfs/cache.c
@@ -51,7 +51,6 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
-#include <linux/zlib.h>
 #include <linux/pagemap.h>
 
 #include "squashfs_fs.h"
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
new file mode 100755
index 0000000..0b6ad9b
--- /dev/null
+++ b/fs/squashfs/decompressor.c
@@ -0,0 +1,72 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * decompressor.c
+ */
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/buffer_head.h>
+
+#include "squashfs_fs.h"
+#include "squashfs_fs_sb.h"
+#include "squashfs_fs_i.h"
+#include "decompressor.h"
+#include "squashfs.h"
+
+/*
+ * This file (and decompressor.h) implements a decompressor framework for
+ * Squashfs, allowing multiple decompressors to be easily supported
+ */
+
+static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = {
+	NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
+};
+
+static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = {
+	NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
+};
+
+static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
+	NULL, NULL, NULL, 0, "unknown", 0
+};
+
+static const struct squashfs_decompressor *decompressor[] = {
+	&squashfs_zlib_comp_ops,
+#ifdef CONFIG_SQUASHFS_LZMA
+	&squashfs_lzma_comp_ops,
+#else
+	&squashfs_lzma_unsupported_comp_ops,
+#endif
+	&squashfs_lzo_unsupported_comp_ops,
+	&squashfs_unknown_comp_ops
+};
+
+
+const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
+{
+	int i;
+
+	for (i = 0; decompressor[i]->id; i++)
+		if (id == decompressor[i]->id)
+			break;
+
+	return decompressor[i];
+}
diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h
new file mode 100755
index 0000000..7425f80
--- /dev/null
+++ b/fs/squashfs/decompressor.h
@@ -0,0 +1,55 @@
+#ifndef DECOMPRESSOR_H
+#define DECOMPRESSOR_H
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * decompressor.h
+ */
+
+struct squashfs_decompressor {
+	void	*(*init)(struct squashfs_sb_info *);
+	void	(*free)(void *);
+	int	(*decompress)(struct squashfs_sb_info *, void **,
+		struct buffer_head **, int, int, int, int, int);
+	int	id;
+	char	*name;
+	int	supported;
+};
+
+static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
+{
+	return msblk->decompressor->init(msblk);
+}
+
+static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
+	void *s)
+{
+	if (msblk->decompressor)
+		msblk->decompressor->free(s);
+}
+
+static inline int squashfs_decompress(struct squashfs_sb_info *msblk,
+	void **buffer, struct buffer_head **bh, int b, int offset, int length,
+	int srclength, int pages)
+{
+	return msblk->decompressor->decompress(msblk, buffer, bh, b, offset,
+		length, srclength, pages);
+}
+#endif
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
old mode 100644
new mode 100755
index 566b0ea..12b933a
--- a/fs/squashfs/dir.c
+++ b/fs/squashfs/dir.c
@@ -30,7 +30,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c
old mode 100644
new mode 100755
index 2b1b8fe..7f93d5a
--- a/fs/squashfs/export.c
+++ b/fs/squashfs/export.c
@@ -39,7 +39,6 @@
 #include <linux/vfs.h>
 #include <linux/dcache.h>
 #include <linux/exportfs.h>
-#include <linux/zlib.h>
 #include <linux/slab.h>
 
 #include "squashfs_fs.h"
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
old mode 100644
new mode 100755
index 717767d..a25c506
--- a/fs/squashfs/file.c
+++ b/fs/squashfs/file.c
@@ -47,7 +47,6 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 #include <linux/mutex.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c
old mode 100644
new mode 100755
index b5a2c15..7c90bbd
--- a/fs/squashfs/fragment.c
+++ b/fs/squashfs/fragment.c
@@ -36,7 +36,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c
old mode 100644
new mode 100755
index 3795b83..b7f64bc
--- a/fs/squashfs/id.c
+++ b/fs/squashfs/id.c
@@ -34,7 +34,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
old mode 100644
new mode 100755
index 9101dbd..49daaf6
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -40,7 +40,6 @@
 
 #include <linux/fs.h>
 #include <linux/vfs.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/lzma_wrapper.c b/fs/squashfs/lzma_wrapper.c
new file mode 100755
index 0000000..9fa617d
--- /dev/null
+++ b/fs/squashfs/lzma_wrapper.c
@@ -0,0 +1,151 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * lzma_wrapper.c
+ */
+
+#include <asm/unaligned.h>
+#include <linux/buffer_head.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <linux/decompress/unlzma.h>
+
+#include "squashfs_fs.h"
+#include "squashfs_fs_sb.h"
+#include "squashfs_fs_i.h"
+#include "squashfs.h"
+#include "decompressor.h"
+
+struct squashfs_lzma {
+	void	*input;
+	void	*output;
+};
+
+/* decompress_unlzma.c is currently non re-entrant... */
+DEFINE_MUTEX(lzma_mutex);
+
+/* decompress_unlzma.c doesn't provide any context in its callbacks... */
+static int lzma_error;
+
+static void error(char *m)
+{
+	ERROR("unlzma error: %s\n", m);
+	lzma_error = 1;
+}
+
+	
+static void *lzma_init(struct squashfs_sb_info *msblk)
+{
+	struct squashfs_lzma *stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+	if (stream == NULL)
+		goto failed;
+	stream->input = vmalloc(msblk->block_size);
+	if (stream->input == NULL)
+		goto failed;
+	stream->output = vmalloc(msblk->block_size);
+	if (stream->output == NULL)
+		goto failed2;
+
+	return stream;
+
+failed2:
+	vfree(stream->input);
+failed:
+	ERROR("failed to allocate lzma workspace\n");
+	kfree(stream);
+	return NULL;
+}
+
+
+static void lzma_free(void *strm)
+{
+	struct squashfs_lzma *stream = strm;
+
+	if (stream) {
+		vfree(stream->input);
+		vfree(stream->output);
+	}
+	kfree(stream);
+}
+
+
+static int lzma_uncompress(struct squashfs_sb_info *msblk, void **buffer,
+	struct buffer_head **bh, int b, int offset, int length, int srclength,
+	int pages)
+{
+	struct squashfs_lzma *stream = msblk->stream;
+	void *buff = stream->input;
+	int avail, i, bytes = length, res;
+
+	mutex_lock(&lzma_mutex);
+
+	for (i = 0; i < b; i++) {
+		wait_on_buffer(bh[i]);
+		if (!buffer_uptodate(bh[i]))
+			goto block_release;
+
+		avail = min(bytes, msblk->devblksize - offset);
+		memcpy(buff, bh[i]->b_data + offset, avail);
+		buff += avail;
+		bytes -= avail;
+		offset = 0;
+		put_bh(bh[i]);
+	}
+
+	lzma_error = 0;
+	res = unlzma(stream->input, length, NULL, NULL, stream->output, NULL,
+							error);
+	if (res || lzma_error)
+		goto failed;
+
+	/* uncompressed size is stored in the LZMA header (5 byte offset) */
+	res = bytes = get_unaligned_le32(stream->input + 5);
+	for (i = 0, buff = stream->output; bytes && i < pages; i++) {
+		avail = min_t(int, bytes, PAGE_CACHE_SIZE);
+		memcpy(buffer[i], buff, avail);
+		buff += avail;
+		bytes -= avail;
+	}
+	if (bytes)
+		goto failed;
+
+	mutex_unlock(&lzma_mutex);
+	return res;
+
+block_release:
+	for (; i < b; i++)
+		put_bh(bh[i]);
+
+failed:
+	mutex_unlock(&lzma_mutex);
+
+	ERROR("lzma decompression failed, data probably corrupt\n");
+	return -EIO;
+}
+
+const struct squashfs_decompressor squashfs_lzma_comp_ops = {
+	.init = lzma_init,
+	.free = lzma_free,
+	.decompress = lzma_uncompress,
+	.id = LZMA_COMPRESSION,
+	.name = "lzma",
+	.supported = 1
+};
+
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
old mode 100644
new mode 100755
index 9e39865..5266bd8
--- a/fs/squashfs/namei.c
+++ b/fs/squashfs/namei.c
@@ -57,7 +57,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/dcache.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
old mode 100644
new mode 100755
index 0e9feb6..d094886
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -51,6 +51,9 @@
 				u64, int);
 extern int squashfs_read_table(struct super_block *, void *, u64, int);
 
+/* decompressor.c */
+extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
+
 /* export.c */
 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
 				unsigned int);
@@ -71,7 +74,7 @@
 extern int squashfs_read_inode(struct inode *, long long);
 
 /*
- * Inodes and files operations
+ * Inodes, files and decompressor operations
  */
 
 /* dir.c */
@@ -88,3 +91,9 @@
 
 /* symlink.c */
 extern const struct address_space_operations squashfs_symlink_aops;
+
+/* zlib_wrapper.c */
+extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
+
+/* lzma wrapper.c */
+extern const struct squashfs_decompressor squashfs_lzma_comp_ops;
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
old mode 100644
new mode 100755
index 283daaf..36e1604
--- a/fs/squashfs/squashfs_fs.h
+++ b/fs/squashfs/squashfs_fs.h
@@ -211,7 +211,9 @@
 /*
  * definitions for structures on disk
  */
-#define ZLIB_COMPRESSION	 1
+#define ZLIB_COMPRESSION	1
+#define LZMA_COMPRESSION	2
+#define LZO_COMPRESSION		3
 
 struct squashfs_super_block {
 	__le32			s_magic;
diff --git a/fs/squashfs/squashfs_fs_i.h b/fs/squashfs/squashfs_fs_i.h
old mode 100644
new mode 100755
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
old mode 100644
new mode 100755
index c8c6561..7533350
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -52,25 +52,26 @@
 };
 
 struct squashfs_sb_info {
-	int			devblksize;
-	int			devblksize_log2;
-	struct squashfs_cache	*block_cache;
-	struct squashfs_cache	*fragment_cache;
-	struct squashfs_cache	*read_page;
-	int			next_meta_index;
-	__le64			*id_table;
-	__le64			*fragment_index;
-	unsigned int		*fragment_index_2;
-	struct mutex		read_data_mutex;
-	struct mutex		meta_index_mutex;
-	struct meta_index	*meta_index;
-	z_stream		stream;
-	__le64			*inode_lookup_table;
-	u64			inode_table;
-	u64			directory_table;
-	unsigned int		block_size;
-	unsigned short		block_log;
-	long long		bytes_used;
-	unsigned int		inodes;
+	const struct squashfs_decompressor	*decompressor;
+	int					devblksize;
+	int					devblksize_log2;
+	struct squashfs_cache			*block_cache;
+	struct squashfs_cache			*fragment_cache;
+	struct squashfs_cache			*read_page;
+	int					next_meta_index;
+	__le64					*id_table;
+	__le64					*fragment_index;
+	unsigned int				*fragment_index_2;
+	struct mutex				read_data_mutex;
+	struct mutex				meta_index_mutex;
+	struct meta_index			*meta_index;
+	void					*stream;
+	__le64					*inode_lookup_table;
+	u64					inode_table;
+	u64					directory_table;
+	unsigned int				block_size;
+	unsigned short				block_log;
+	long long				bytes_used;
+	unsigned int				inodes;
 };
 #endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
old mode 100644
new mode 100755
index 6c197ef..3550aec
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -35,34 +35,41 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/zlib.h>
 #include <linux/magic.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
 #include "squashfs_fs_i.h"
 #include "squashfs.h"
+#include "decompressor.h"
 
 static struct file_system_type squashfs_fs_type;
 static const struct super_operations squashfs_super_ops;
 
-static int supported_squashfs_filesystem(short major, short minor, short comp)
+static const struct squashfs_decompressor *supported_squashfs_filesystem(short
+	major, short minor, short id)
 {
+	const struct squashfs_decompressor *decompressor;
+
 	if (major < SQUASHFS_MAJOR) {
 		ERROR("Major/Minor mismatch, older Squashfs %d.%d "
 			"filesystems are unsupported\n", major, minor);
-		return -EINVAL;
+		return NULL;
 	} else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
 		ERROR("Major/Minor mismatch, trying to mount newer "
 			"%d.%d filesystem\n", major, minor);
 		ERROR("Please update your kernel\n");
-		return -EINVAL;
+		return NULL;
 	}
 
-	if (comp != ZLIB_COMPRESSION)
-		return -EINVAL;
+	decompressor = squashfs_lookup_decompressor(id);
+	if (!decompressor->supported) {
+		ERROR("Filesystem uses \"%s\" compression. This is not "
+			"supported\n", decompressor->name);
+		return NULL;
+	}
 
-	return 0;
+	return decompressor;
 }
 
 
@@ -87,13 +94,6 @@
 	}
 	msblk = sb->s_fs_info;
 
-	msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
-		GFP_KERNEL);
-	if (msblk->stream.workspace == NULL) {
-		ERROR("Failed to allocate zlib workspace\n");
-		goto failure;
-	}
-
 	sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
 	if (sblk == NULL) {
 		ERROR("Failed to allocate squashfs_super_block\n");
@@ -120,25 +120,25 @@
 		goto failed_mount;
 	}
 
+	err = -EINVAL;
+
 	/* Check it is a SQUASHFS superblock */
 	sb->s_magic = le32_to_cpu(sblk->s_magic);
 	if (sb->s_magic != SQUASHFS_MAGIC) {
 		if (!silent)
 			ERROR("Can't find a SQUASHFS superblock on %s\n",
 						bdevname(sb->s_bdev, b));
-		err = -EINVAL;
 		goto failed_mount;
 	}
 
-	/* Check the MAJOR & MINOR versions and compression type */
-	err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
+	/* Check the MAJOR & MINOR versions and lookup compression type */
+	msblk->decompressor = supported_squashfs_filesystem(
+			le16_to_cpu(sblk->s_major),
 			le16_to_cpu(sblk->s_minor),
 			le16_to_cpu(sblk->compression));
-	if (err < 0)
+	if (msblk->decompressor == NULL)
 		goto failed_mount;
 
-	err = -EINVAL;
-
 	/*
 	 * Check if there's xattrs in the filesystem.  These are not
 	 * supported in this version, so warn that they will be ignored.
@@ -205,6 +205,10 @@
 
 	err = -ENOMEM;
 
+	msblk->stream = squashfs_decompressor_init(msblk);
+	if (msblk->stream == NULL)
+		goto failed_mount;
+
 	msblk->block_cache = squashfs_cache_init("metadata",
 			SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
 	if (msblk->block_cache == NULL)
@@ -292,17 +296,16 @@
 	squashfs_cache_delete(msblk->block_cache);
 	squashfs_cache_delete(msblk->fragment_cache);
 	squashfs_cache_delete(msblk->read_page);
+	squashfs_decompressor_free(msblk, msblk->stream);
 	kfree(msblk->inode_lookup_table);
 	kfree(msblk->fragment_index);
 	kfree(msblk->id_table);
-	kfree(msblk->stream.workspace);
 	kfree(sb->s_fs_info);
 	sb->s_fs_info = NULL;
 	kfree(sblk);
 	return err;
 
 failure:
-	kfree(msblk->stream.workspace);
 	kfree(sb->s_fs_info);
 	sb->s_fs_info = NULL;
 	return -ENOMEM;
@@ -346,10 +349,10 @@
 		squashfs_cache_delete(sbi->block_cache);
 		squashfs_cache_delete(sbi->fragment_cache);
 		squashfs_cache_delete(sbi->read_page);
+		squashfs_decompressor_free(sbi, sbi->stream);
 		kfree(sbi->id_table);
 		kfree(sbi->fragment_index);
 		kfree(sbi->meta_index);
-		kfree(sbi->stream.workspace);
 		kfree(sb->s_fs_info);
 		sb->s_fs_info = NULL;
 	}
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
old mode 100644
new mode 100755
index 83d8788..e80be20
--- a/fs/squashfs/symlink.c
+++ b/fs/squashfs/symlink.c
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/pagemap.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c
new file mode 100755
index 0000000..4dd70e0
--- /dev/null
+++ b/fs/squashfs/zlib_wrapper.c
@@ -0,0 +1,150 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * zlib_wrapper.c
+ */
+
+
+#include <linux/mutex.h>
+#include <linux/buffer_head.h>
+#include <linux/zlib.h>
+
+#include "squashfs_fs.h"
+#include "squashfs_fs_sb.h"
+#include "squashfs_fs_i.h"
+#include "squashfs.h"
+#include "decompressor.h"
+
+static void *zlib_init(struct squashfs_sb_info *dummy)
+{
+	z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
+	if (stream == NULL)
+		goto failed;
+	stream->workspace = kmalloc(zlib_inflate_workspacesize(),
+		GFP_KERNEL);
+	if (stream->workspace == NULL)
+		goto failed;
+
+	return stream;
+
+failed:
+	ERROR("Failed to allocate zlib workspace\n");
+	kfree(stream);
+	return NULL;
+}
+
+
+static void zlib_free(void *strm)
+{
+	z_stream *stream = strm;
+
+	if (stream)
+		kfree(stream->workspace);
+	kfree(stream);
+}
+
+
+static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
+	struct buffer_head **bh, int b, int offset, int length, int srclength,
+	int pages)
+{
+	int zlib_err = 0, zlib_init = 0;
+	int avail, bytes, k = 0, page = 0;
+	z_stream *stream = msblk->stream;
+
+	mutex_lock(&msblk->read_data_mutex);
+
+	stream->avail_out = 0;
+	stream->avail_in = 0;
+
+	bytes = length;
+	do {
+		if (stream->avail_in == 0 && k < b) {
+			avail = min(bytes, msblk->devblksize - offset);
+			bytes -= avail;
+			wait_on_buffer(bh[k]);
+			if (!buffer_uptodate(bh[k]))
+				goto release_mutex;
+
+			if (avail == 0) {
+				offset = 0;
+				put_bh(bh[k++]);
+				continue;
+			}
+
+			stream->next_in = bh[k]->b_data + offset;
+			stream->avail_in = avail;
+			offset = 0;
+		}
+
+		if (stream->avail_out == 0 && page < pages) {
+			stream->next_out = buffer[page++];
+			stream->avail_out = PAGE_CACHE_SIZE;
+		}
+
+		if (!zlib_init) {
+			zlib_err = zlib_inflateInit(stream);
+			if (zlib_err != Z_OK) {
+				ERROR("zlib_inflateInit returned unexpected "
+					"result 0x%x, srclength %d\n",
+					zlib_err, srclength);
+				goto release_mutex;
+			}
+			zlib_init = 1;
+		}
+
+		zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
+
+		if (stream->avail_in == 0 && k < b)
+			put_bh(bh[k++]);
+	} while (zlib_err == Z_OK);
+
+	if (zlib_err != Z_STREAM_END) {
+		ERROR("zlib_inflate error, data probably corrupt\n");
+		goto release_mutex;
+	}
+
+	zlib_err = zlib_inflateEnd(stream);
+	if (zlib_err != Z_OK) {
+		ERROR("zlib_inflate error, data probably corrupt\n");
+		goto release_mutex;
+	}
+
+	mutex_unlock(&msblk->read_data_mutex);
+	return stream->total_out;
+
+release_mutex:
+	mutex_unlock(&msblk->read_data_mutex);
+
+	for (; k < b; k++)
+		put_bh(bh[k]);
+
+	return -EIO;
+}
+
+const struct squashfs_decompressor squashfs_zlib_comp_ops = {
+	.init = zlib_init,
+	.free = zlib_free,
+	.decompress = zlib_uncompress,
+	.id = ZLIB_COMPRESSION,
+	.name = "zlib",
+	.supported = 1
+};
+
diff --git a/fs/sysfs/Kconfig b/fs/sysfs/Kconfig
old mode 100644
new mode 100755
diff --git a/fs/sysfs/Makefile b/fs/sysfs/Makefile
old mode 100644
new mode 100755
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
old mode 100644
new mode 100755
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
old mode 100644
new mode 100755
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
old mode 100644
new mode 100755
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
old mode 100644
new mode 100755
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
old mode 100644
new mode 100755
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
old mode 100644
new mode 100755
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
old mode 100644
new mode 100755
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
old mode 100644
new mode 100755
diff --git a/fs/sysv/Kconfig b/fs/sysv/Kconfig
old mode 100644
new mode 100755
diff --git a/fs/sysv/Makefile b/fs/sysv/Makefile
old mode 100644
new mode 100755
diff --git a/fs/sysv/balloc.c b/fs/sysv/balloc.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c
old mode 100644
new mode 100755
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
old mode 100644
new mode 100755
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig
old mode 100644
new mode 100755
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
old mode 100644
new mode 100755
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/compress.c b/fs/ubifs/compress.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
old mode 100644
new mode 100755
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
old mode 100644
new mode 100755
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h
old mode 100644
new mode 100755
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c
old mode 100644
new mode 100755
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h
old mode 100644
new mode 100755
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
old mode 100644
new mode 100755
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
old mode 100644
new mode 100755
diff --git a/fs/udf/Kconfig b/fs/udf/Kconfig
old mode 100644
new mode 100755
diff --git a/fs/udf/Makefile b/fs/udf/Makefile
old mode 100644
new mode 100755
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
old mode 100644
new mode 100755
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
old mode 100644
new mode 100755
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
old mode 100644
new mode 100755
diff --git a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h
old mode 100644
new mode 100755
diff --git a/fs/udf/file.c b/fs/udf/file.c
old mode 100644
new mode 100755
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
old mode 100644
new mode 100755
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
old mode 100644
new mode 100755
diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
old mode 100644
new mode 100755
diff --git a/fs/udf/misc.c b/fs/udf/misc.c
old mode 100644
new mode 100755
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
old mode 100644
new mode 100755
diff --git a/fs/udf/osta_udf.h b/fs/udf/osta_udf.h
old mode 100644
new mode 100755
diff --git a/fs/udf/partition.c b/fs/udf/partition.c
old mode 100644
new mode 100755
diff --git a/fs/udf/super.c b/fs/udf/super.c
old mode 100644
new mode 100755
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
old mode 100644
new mode 100755
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
old mode 100644
new mode 100755
diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h
old mode 100644
new mode 100755
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
old mode 100644
new mode 100755
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
old mode 100644
new mode 100755
diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h
old mode 100644
new mode 100755
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
old mode 100644
new mode 100755
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/Kconfig b/fs/ufs/Kconfig
old mode 100644
new mode 100755
diff --git a/fs/ufs/Makefile b/fs/ufs/Makefile
old mode 100644
new mode 100755
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/cylinder.c b/fs/ufs/cylinder.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/swab.h b/fs/ufs/swab.h
old mode 100644
new mode 100755
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
old mode 100644
new mode 100755
diff --git a/fs/ufs/ufs_fs.h b/fs/ufs/ufs_fs.h
old mode 100644
new mode 100755
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
old mode 100644
new mode 100755
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
old mode 100644
new mode 100755
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
old mode 100644
new mode 100755
index 965df12..5135674
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1132,12 +1132,25 @@
 	xfs_buf_t		*bp = (xfs_buf_t *)bio->bi_private;
 	unsigned int		blocksize = bp->b_target->bt_bsize;
 	struct bio_vec		*bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+	void			*vaddr = NULL;
+	int				i;
 
 	xfs_buf_ioerror(bp, -error);
+	if (is_vmalloc_addr(bp->b_addr))
+		for (i = 0; i < bp->b_page_count; i++)
+			if (bvec->bv_page == bp->b_pages[i]) {
+				vaddr = bp->b_addr + i*PAGE_SIZE;
+				break;
+			}
 
 	do {
 		struct page	*page = bvec->bv_page;
 
+		if (is_vmalloc_addr(bp->b_addr)) {
+			invalidate_kernel_dcache_addr(vaddr);
+			vaddr -= PAGE_SIZE;
+		}
+
 		ASSERT(!PagePrivate(page));
 		if (unlikely(bp->b_error)) {
 			if (bp->b_flags & XBF_READ)
@@ -1202,6 +1215,9 @@
 		bio->bi_end_io = xfs_buf_bio_end_io;
 		bio->bi_private = bp;
 
+		if (is_vmalloc_addr(bp->b_addr))
+			flush_kernel_dcache_addr(bp->b_addr);
+
 		bio_add_page(bio, bp->b_pages[0], PAGE_CACHE_SIZE, 0);
 		size = 0;
 
@@ -1228,6 +1244,9 @@
 		if (nbytes > size)
 			nbytes = size;
 
+		if (is_vmalloc_addr(bp->b_addr))
+			flush_kernel_dcache_addr(bp->b_addr + PAGE_SIZE*map_i);
+
 		rbytes = bio_add_page(bio, bp->b_pages[map_i], nbytes, offset);
 		if (rbytes < nbytes)
 			break;
diff --git a/include/linux/decompress/bunzip2_mm.h b/include/linux/decompress/bunzip2_mm.h
new file mode 100755
index 0000000..cac6fef
--- /dev/null
+++ b/include/linux/decompress/bunzip2_mm.h
@@ -0,0 +1,12 @@
+#ifndef BUNZIP2_MM_H
+#define BUNZIP2_MM_H
+
+#ifdef STATIC
+/* Code active when included from pre-boot environment: */
+#define INIT
+#else
+/* Compile for initramfs/initrd code only */
+#define INIT __init
+#endif
+
+#endif
diff --git a/include/linux/decompress/inflate_mm.h b/include/linux/decompress/inflate_mm.h
new file mode 100755
index 0000000..ca4a2ae
--- /dev/null
+++ b/include/linux/decompress/inflate_mm.h
@@ -0,0 +1,12 @@
+#ifndef INFLATE_MM_H
+#define INFLATE_MM_H
+
+#ifdef STATIC
+/* Code active when included from pre-boot environment: */
+#define INIT
+#else
+/* Compile for initramfs/initrd code only */
+#define INIT __init
+#endif
+
+#endif
diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h
old mode 100644
new mode 100755
index 3e9bd6a..02191be
--- a/include/linux/decompress/mm.h
+++ b/include/linux/decompress/mm.h
@@ -63,8 +63,6 @@
 
 #define set_error_fn(x)
 
-#define INIT
-
 #else /* STATIC */
 
 /* Code active when compiled standalone for use when loading ramdisk: */
@@ -87,7 +85,6 @@
 static void(*error)(char *m);
 #define set_error_fn(x) error = x;
 
-#define INIT __init
 #define STATIC
 
 #include <linux/init.h>
diff --git a/include/linux/decompress/unlzma_mm.h b/include/linux/decompress/unlzma_mm.h
new file mode 100755
index 0000000..859287e
--- /dev/null
+++ b/include/linux/decompress/unlzma_mm.h
@@ -0,0 +1,20 @@
+#ifndef UNLZMA_MM_H
+#define UNLZMA_MM_H
+
+#ifdef STATIC
+
+/* Code active when included from pre-boot environment: */
+#define INIT
+
+#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
+
+/* Make it available to non initramfs/initrd code */
+#define INIT
+#include <linux/module.h>
+#else
+
+/* Compile for initramfs/initrd code only */
+#define INIT __init
+#endif
+
+#endif
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
old mode 100644
new mode 100755
index 211ff44..eb99c70
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -17,6 +17,12 @@
 static inline void flush_kernel_dcache_page(struct page *page)
 {
 }
+static inline void flush_kernel_dcache_addr(void *vaddr)
+{
+}
+static inline void invalidate_kernel_dcache_addr(void *vaddr)
+{
+}
 #endif
 
 #include <asm/kmap_types.h>
diff --git a/include/linux/major.h b/include/linux/major.h
old mode 100644
new mode 100755
index 6a8ca98..d909537
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -171,7 +171,12 @@
 
 #define VIOTAPE_MAJOR		230
 
+#define MV_TS_MAJOR		231	/* Marvell Transport Stream driver */
+
 #define BLOCK_EXT_MAJOR		259
 #define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
 
+#define MV_PON_MAJOR		300
+#define MV_TPM_MAJOR		301
+
 #endif
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
old mode 100644
new mode 100755
index adaf3c1..dec614a
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -11,7 +11,12 @@
 #define SUN_MOUSE_MINOR		6
 #define APOLLO_MOUSE_MINOR	7
 #define PC110PAD_MINOR		9
-/*#define ADB_MOUSE_MINOR	10	FIXME OBSOLETE */
+/*#define ADB_MOUSE_MINOR 10	FIXME OBSOLETE */
+#define CRYPTODEV_MINOR         70      /* OCF async crypto */
+#define CESADEV_MINOR		71	/* marvell CESA     */
+#define BTNSDEV_MINOR  		72	/* Marvell btns */
+#define SLICDEV_MINOR		73	/* Marvell SLIC control device */
+#define TDMDEV_MINOR		74	/* Marvell TDM test device */
 #define WATCHDOG_MINOR		130	/* Watchdog timer     */
 #define TEMP_MINOR		131	/* Temperature Sensor */
 #define RTC_MINOR		135
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
old mode 100644
new mode 100755
index fff8c53..b25a52c
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -84,12 +84,19 @@
 /* Search good / bad pattern on the first and the second page */
 #define NAND_BBT_SCAN2NDPAGE	0x00004000
 
+#ifdef CONFIG_MTD_NAND_NFC_MLC_SUPPORT
+/* Search the bad block indicators according to Marvell's Naked symantics */
+#define NAND_BBT_SCANMVCUSTOM	0x10000000
+#endif
+
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
 
 /*
  * Constants for oob configuration
  */
+#define NAND_SMALL_BADBLOCK_POS		5
+#define NAND_LARGE_BADBLOCK_POS		0
 #define ONENAND_BADBLOCK_POS	0
 
 /*
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
old mode 100644
new mode 100755
index 7a232a9..4843297
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -21,6 +21,7 @@
 #include <linux/wait.h>
 #include <linux/spinlock.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/bbm.h>
 
 struct mtd_info;
 /* Scan and identify a NAND device */
@@ -389,7 +390,14 @@
 
 	int		chip_delay;
 	unsigned int	options;
-
+#ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
+	unsigned int	num_devs;
+#endif
+#ifdef CONFIG_MTD_NAND_NFC_MLC_SUPPORT
+	unsigned int	oobsize_ovrd;
+	unsigned int	bb_location;
+	unsigned int	bb_page;
+#endif
 	int		page_shift;
 	int		phys_erase_shift;
 	int		bbt_erase_shift;
@@ -470,40 +478,6 @@
 extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
-/**
- * struct nand_bbt_descr - bad block table descriptor
- * @options:	options for this descriptor
- * @pages:	the page(s) where we find the bbt, used with option BBT_ABSPAGE
- *		when bbt is searched, then we store the found bbts pages here.
- *		Its an array and supports up to 8 chips now
- * @offs:	offset of the pattern in the oob area of the page
- * @veroffs:	offset of the bbt version counter in the oob are of the page
- * @version:	version read from the bbt page during scan
- * @len:	length of the pattern, if 0 no pattern check is performed
- * @maxblocks:	maximum number of blocks to search for a bbt. This number of
- *		blocks is reserved at the end of the device where the tables are
- *		written.
- * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
- *              bad) block in the stored bbt
- * @pattern:	pattern to identify bad block table or factory marked good /
- *		bad blocks, can be NULL, if len = 0
- *
- * Descriptor for the bad block table marker and the descriptor for the
- * pattern which identifies good and bad blocks. The assumption is made
- * that the pattern and the version count are always located in the oob area
- * of the first block.
- */
-struct nand_bbt_descr {
-	int	options;
-	int	pages[NAND_MAX_CHIPS];
-	int	offs;
-	int	veroffs;
-	uint8_t	version[NAND_MAX_CHIPS];
-	int	len;
-	int	maxblocks;
-	int	reserved_block_code;
-	uint8_t	*pattern;
-};
 
 /* Options for the bad block table descriptors */
 
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
old mode 100644
new mode 100755
index 274b619..fbde6cf
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -60,13 +60,13 @@
 	struct list_head list;
 	struct module *owner;
 	const char *name;
-	int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long);
+	int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long,const char*);
 };
 
 extern int register_mtd_parser(struct mtd_part_parser *parser);
 extern int deregister_mtd_parser(struct mtd_part_parser *parser);
 extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
-				struct mtd_partition **pparts, unsigned long origin);
+				struct mtd_partition **pparts, unsigned long origin,const char *cmd);
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while(0)
 
diff --git a/include/linux/mv_neta.h b/include/linux/mv_neta.h
new file mode 100755
index 0000000..9cf8e7a
--- /dev/null
+++ b/include/linux/mv_neta.h
@@ -0,0 +1,12 @@
+/*  mv_neta.h */
+
+#ifndef LINUX_MV_NETA_H
+#define LINUX_MV_NETA_H
+			 
+struct netaSmpGroupStruct {
+	MV_U32 portMask;
+	MV_U32 cpuMask;
+};
+
+
+#endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 812a5f3..b44a837 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2013,6 +2013,27 @@
 		return 0;
 	return dev->ethtool_ops->get_flags(dev);
 }
+
+#ifdef CONFIG_MV_ETH_NFP_EXT
+
+/* Supported flags */
+#define MV_EXT_L3_VALID_MASK	0x0001
+#define MV_EXT_L4_VALID_MASK	0x0002
+#define MV_EXT_VLAN_EXIST_MASK  0x0004
+#define MV_EXT_PPP_EXIST_MASK	0x0008
+#define MV_EXT_IP_FRAG_MASK	    0x0010
+
+typedef struct {
+	u16 flags;
+	u16 l3_type;
+	u16 l3_offset;
+	u8  l3_hdrlen;
+	u8  l4_proto;
+} MV_EXT_PKT_INFO;
+
+int mv_eth_nfp_ext(struct net_device *dev, struct sk_buff *skb, MV_EXT_PKT_INFO *pkt_info);
+#endif /* CONFIG_MV_ETH_NFP_EXT */
+
 #endif /* __KERNEL__ */
 
 #endif	/* _LINUX_NETDEVICE_H */
diff --git a/include/linux/netfilter/ipt_NFP.h b/include/linux/netfilter/ipt_NFP.h
new file mode 100755
index 0000000..b1831e1
--- /dev/null
+++ b/include/linux/netfilter/ipt_NFP.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2010 Semihalf.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _IPT_NFP_H
+#define _IPT_NFP_H
+
+#define IPT_NFP_F_SET_DSCP           0x1
+#define IPT_NFP_F_SET_DSCP_DEF       0x2
+#define IPT_NFP_F_SET_VLAN_PRIO      0x4
+#define IPT_NFP_F_SET_VLAN_PRIO_DEF  0x8
+#define IPT_NFP_F_SET_TXQ            0x10
+#define IPT_NFP_F_SET_TXP            0x20
+#define IPT_NFP_F_SET_MH             0x40
+#define IPT_NFP_F_SET_LIMIT          0x80
+#define IPT_NFP_F_SET_BURST          0x100
+#define IPT_NFP_F_SET_TXQ_DEF        0x200
+
+enum ipt_nfp_mode {
+	IPT_NFP_INIT   = -1,
+	IPT_NFP_FWD    = 0,
+	IPT_NFP_DROP   = 1,
+	IPT_NFP_MANGLE = 2,
+};
+
+/* 0..7 + one cell for global mapping regardless of the old VLAN Prio value (the '-1' option) */
+#define IPT_NFP_VPRI_MAP_SIZE	9
+#define IPT_NFP_VPRI_MAP_GLOBAL	8 /* index in the array for the global mapping */
+
+typedef struct {
+	unsigned char new_prio;
+	unsigned char valid;
+} IPT_NFP_VPRI_MAP_INFO;
+
+/* 0..63 + one cell for global mapping regardless of the old DSCP value (the '-1' option) */
+#define IPT_NFP_DSCP_MAP_SIZE	65
+#define IPT_NFP_DSCP_MAP_GLOBAL	64 /* index in the array for the global mapping */
+
+typedef struct {
+	unsigned char new_dscp;
+	unsigned char valid;
+} IPT_NFP_DSCP_MAP_INFO;
+
+typedef struct {
+	unsigned char txq;
+	unsigned char valid;
+} IPT_NFP_TXQ_MAP_INFO;
+
+struct ipt_nfp_info {
+	unsigned int		mode;
+	unsigned int		flags;
+
+	int			burst;
+	int			limit;
+
+	int			dscp;
+	int			new_dscp;
+	IPT_NFP_DSCP_MAP_INFO	dscp_map[IPT_NFP_DSCP_MAP_SIZE];
+
+	int			vlanprio;
+	int			new_vlanprio;
+	IPT_NFP_VPRI_MAP_INFO	vpri_map[IPT_NFP_VPRI_MAP_SIZE];
+
+	int			dscp_txq; /* map DSCP to TXQ */
+	int			txq;
+	IPT_NFP_TXQ_MAP_INFO	txq_map[IPT_NFP_DSCP_MAP_SIZE];
+
+	int			txp;
+	int			mh;
+
+	/* private */
+	struct ipt_entry	*entry;
+};
+
+
+static inline void nfp_update_tuple_info(struct ipt_nfp_info *dst, struct ipt_nfp_info *src)
+{
+	/* we copy (override) some of the parameters, but update (accumulate) others */
+
+	dst->mode = src->mode;
+	dst->flags |= src->flags;
+
+	if (src->flags & IPT_NFP_F_SET_BURST)
+		dst->burst = src->burst;
+
+	if (src->flags & IPT_NFP_F_SET_LIMIT)
+		dst->limit = src->limit;
+
+	if (src->flags & IPT_NFP_F_SET_DSCP) {
+		dst->dscp_map[src->dscp].new_dscp = src->new_dscp;
+		dst->dscp_map[src->dscp].valid = 1;
+	}
+
+	if (src->flags & IPT_NFP_F_SET_DSCP_DEF) {
+		dst->dscp_map[IPT_NFP_DSCP_MAP_GLOBAL].new_dscp = src->new_dscp;
+		dst->dscp_map[IPT_NFP_DSCP_MAP_GLOBAL].valid = 1;
+	}
+
+	if (src->flags & IPT_NFP_F_SET_VLAN_PRIO) {
+		dst->vpri_map[src->vlanprio].new_prio = src->new_vlanprio;
+		dst->vpri_map[src->vlanprio].valid = 1;
+	}
+
+	if (src->flags & IPT_NFP_F_SET_VLAN_PRIO_DEF) {
+		dst->vpri_map[IPT_NFP_VPRI_MAP_GLOBAL].new_prio = src->new_vlanprio;
+		dst->vpri_map[IPT_NFP_VPRI_MAP_GLOBAL].valid = 1;
+	}
+
+	if (src->flags & IPT_NFP_F_SET_TXQ) {
+		dst->txq_map[src->dscp_txq].txq = src->txq;
+		dst->txq_map[src->dscp_txq].valid = 1;
+	}
+
+	if (src->flags & IPT_NFP_F_SET_TXQ_DEF) {
+		dst->txq_map[IPT_NFP_DSCP_MAP_GLOBAL].txq = src->txq;
+		dst->txq_map[IPT_NFP_DSCP_MAP_GLOBAL].valid = 1;
+	}
+
+	if (src->flags & IPT_NFP_F_SET_TXP)
+		dst->txp = src->txp;
+
+	if (src->flags & IPT_NFP_F_SET_MH)
+		dst->mh = src->mh;
+
+	dst->entry = src->entry;
+}
+
+
+#endif
diff --git a/include/linux/netfilter/xt_layer7.h b/include/linux/netfilter/xt_layer7.h
new file mode 100755
index 0000000..147cd64
--- /dev/null
+++ b/include/linux/netfilter/xt_layer7.h
@@ -0,0 +1,13 @@
+#ifndef _XT_LAYER7_H
+#define _XT_LAYER7_H
+
+#define MAX_PATTERN_LEN 8192
+#define MAX_PROTOCOL_LEN 256
+
+struct xt_layer7_info {
+    char protocol[MAX_PROTOCOL_LEN];
+    char pattern[MAX_PATTERN_LEN];
+    u_int8_t invert;
+};
+
+#endif /* _XT_LAYER7_H */
diff --git a/include/linux/ppp_channel.h b/include/linux/ppp_channel.h
index 0d3fa63..2130c45 100644
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -72,6 +72,9 @@
 /* Get the unit number associated with a channel, or -1 if none */
 extern int ppp_unit_number(struct ppp_channel *);
 
+/* added for backporting from 3.0.6 kernel for NFP */
+char *ppp_dev_name(struct ppp_channel *chan);
+
 /*
  * SMP locking notes:
  * The channel code must ensure that when it calls ppp_unregister_channel,
diff --git a/include/linux/random.h b/include/linux/random.h
old mode 100644
new mode 100755
index 25d02fe..1e4ff6b
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -50,6 +50,10 @@
 				 unsigned int value);
 extern void add_interrupt_randomness(int irq);
 
+extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count);
+extern int random_input_wait(void);
+#define HAS_RANDOM_INPUT_WAIT 1
+
 extern void get_random_bytes(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
old mode 100644
new mode 100755
index bcdd660..b0df756
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -30,6 +30,10 @@
 #include <linux/dmaengine.h>
 #include <linux/hrtimer.h>
 
+#if defined(CONFIG_NET_SKB_HEADROOM)
+# define NET_SKB_PAD  CONFIG_NET_SKB_HEADROOM
+#endif
+
 /* Don't change this without changing skb_csum_unnecessary! */
 #define CHECKSUM_NONE 0
 #define CHECKSUM_UNNECESSARY 1
@@ -358,6 +362,10 @@
 	kmemcheck_bitfield_end(flags1);
 
 	void			(*destructor)(struct sk_buff *skb);
+#ifdef CONFIG_NET_SKB_RECYCLE
+	int				(*skb_recycle) (struct sk_buff *skb);
+	void			*hw_cookie;
+#endif /* CONFIG_NET_SKB_RECYCLE */
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 	struct nf_conntrack	*nfct;
 	struct sk_buff		*nfct_reasm;
diff --git a/include/linux/telephony.h b/include/linux/telephony.h
old mode 100644
new mode 100755
index f63afe3..e27b4f3
--- a/include/linux/telephony.h
+++ b/include/linux/telephony.h
@@ -28,6 +28,10 @@
  * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION
  * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
+ * Version:       $Revision: 4.2 $
+ *
+ * $Id: telephony.h,v 4.2 2001/08/06 07:09:43 craigs Exp $
+ *
  *****************************************************************************/
 
 #ifndef TELEPHONY_H
@@ -213,6 +217,29 @@
 ******************************************************************************/
 #define PHONE_VAD			_IOW ('q', 0xA9, int)
 
+/******************************************************************************
+* mv-phone additional commands for Caller-ID support
+******************************************************************************/
+#define PHONE_PSTN_REVERSE_POLARITY  _IO  ('q', 0xAB) /* Timor */
+#define PHONE_PSTN_SEND_NTT_CRA	     _IO  ('q', 0xAC)
+
+#define PHONE_SET_LINE_FEED_CONTROL  _IOW ('q', 0xAD, char)
+#define LF_OPEN              0
+#define LF_FORWARD_ACTIVE    1
+#define LF_FORWARD_ONHOOK_TX 2
+#define LF_TIP_OPEN          3
+#define LF_RINGING           4
+#define LF_REVERSE_ACTIVE    5
+#define LF_REVERSE_ONHOOK_TX 6
+#define LF_RING_OPEN         7
+
+#define PHONE_SET_CID_STATE	     _IO  ('q', 0xAE)
+#define CID_OFF			0
+#define CID_ON			1
+
+#define PHONE_SET_REVERSE_POLARITY   _IO  ('q', 0xAF)
+#define PHONE_SET_DIGITAL_HYBRID     _IO  ('q', 0xB0)
+#define PHONE_GET_LINE_VOLTAGE	     _IO  ('q', 0xB1)
 
 /******************************************************************************
 *
@@ -235,6 +262,26 @@
 ******************************************************************************/
 struct phone_except
 {
+#ifdef __BIG_ENDIAN_BITFIELD
+	unsigned int reserved:15;
+	unsigned int hookstate2:1;
+	unsigned int drop_out:1;
+	unsigned int reverse_polarity:1;
+	unsigned int fc3:1;
+	unsigned int fc2:1;
+	unsigned int fc1:1;
+	unsigned int fc0:1;
+	unsigned int flash:1;
+	unsigned int f3:1;
+	unsigned int f2:1;
+	unsigned int f1:1;
+	unsigned int f0:1;
+	unsigned int pstn_wink:1;
+	unsigned int caller_id:1;
+	unsigned int pstn_ring:1;
+	unsigned int hookstate:1;
+	unsigned int dtmf_ready:1;
+#else
 	unsigned int dtmf_ready:1;
 	unsigned int hookstate:1;
 	unsigned int pstn_ring:1;
@@ -249,7 +296,11 @@
 	unsigned int fc1:1;
 	unsigned int fc2:1;
 	unsigned int fc3:1;
-	unsigned int reserved:18;
+	unsigned int reverse_polarity:1;
+	unsigned int drop_out:1;
+	unsigned int hookstate2:1;
+	unsigned int reserved:15;
+#endif
 };
 
 union telephony_exception {
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
old mode 100644
new mode 100755
index be51ae2..c29af6b
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -134,7 +134,11 @@
  */
 struct nand_ecclayout {
 	__u32 eccbytes;
+#ifdef CONFIG_MTD_NAND_NFC
+	__u32 eccpos[128];
+#else
 	__u32 eccpos[64];
+#endif
 	__u32 oobavail;
 	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
 };
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
old mode 100644
new mode 100755
index 15b492a..5940567
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -120,6 +120,11 @@
 #endif
 
 	struct rt6key			rt6i_src;
+
+#if defined (CONFIG_MV_ETH_NFP_FIB_LEARN)
+	int				rt6i_iifindex;
+	bool 			nfp;
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
 };
 
 static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
old mode 100644
new mode 100755
index 3817fda..628ca78
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -119,18 +119,21 @@
 	struct sk_buff_head	arp_queue;
 	struct timer_list	timer;
 	const struct neigh_ops	*ops;
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+	bool 			nfp;
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
 	u8			primary_key[0];
 };
 
 struct neigh_ops
 {
 	int			family;
-	void			(*solicit)(struct neighbour *, struct sk_buff*);
-	void			(*error_report)(struct neighbour *, struct sk_buff*);
-	int			(*output)(struct sk_buff*);
-	int			(*connected_output)(struct sk_buff*);
-	int			(*hh_output)(struct sk_buff*);
-	int			(*queue_xmit)(struct sk_buff*);
+	void			(*solicit)(struct neighbour *, struct sk_buff *);
+	void			(*error_report)(struct neighbour *, struct sk_buff *);
+	int			(*output)(struct sk_buff *);
+	int			(*connected_output)(struct sk_buff *);
+	int			(*hh_output)(struct sk_buff *);
+	int			(*queue_xmit)(struct sk_buff *);
 };
 
 struct pneigh_entry
@@ -192,18 +195,18 @@
 extern void			neigh_table_init(struct neigh_table *tbl);
 extern void			neigh_table_init_no_netlink(struct neigh_table *tbl);
 extern int			neigh_table_clear(struct neigh_table *tbl);
-extern struct neighbour *	neigh_lookup(struct neigh_table *tbl,
+extern struct neighbour 	*neigh_lookup(struct neigh_table *tbl,
 					     const void *pkey,
 					     struct net_device *dev);
-extern struct neighbour *	neigh_lookup_nodev(struct neigh_table *tbl,
+extern struct neighbour 	*neigh_lookup_nodev(struct neigh_table *tbl,
 						   struct net *net,
 						   const void *pkey);
-extern struct neighbour *	neigh_create(struct neigh_table *tbl,
+extern struct neighbour 	*neigh_create(struct neigh_table *tbl,
 					     const void *pkey,
 					     struct net_device *dev);
 extern void			neigh_destroy(struct neighbour *neigh);
 extern int			__neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
-extern int			neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, 
+extern int			neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 					     u32 flags);
 extern void			neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 extern int			neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
@@ -260,7 +263,7 @@
 extern void *neigh_seq_next(struct seq_file *, void *, loff_t *);
 extern void neigh_seq_stop(struct seq_file *, void *);
 
-extern int			neigh_sysctl_register(struct net_device *dev, 
+extern int			neigh_sysctl_register(struct net_device *dev,
 						      struct neigh_parms *p,
 						      int p_id, int pdev_id,
 						      char *p_name,
@@ -289,7 +292,7 @@
 		neigh_destroy(neigh);
 }
 
-static inline struct neighbour * neigh_clone(struct neighbour *neigh)
+static inline struct neighbour *neigh_clone(struct neighbour *neigh)
 {
 	if (neigh)
 		atomic_inc(&neigh->refcnt);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
old mode 100644
new mode 100755
index 5cf7270..8dc6a75
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -116,6 +116,22 @@
 	u_int32_t secmark;
 #endif
 
+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \
+    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
+	struct {
+		/*
+		 * e.g. "http". NULL before decision. "unknown" after decision
+		 * if no match.
+		 */
+		char *app_proto;
+		/*
+		 * application layer data so far. NULL after match decision.
+		 */
+		char *app_data;
+		unsigned int app_data_len;
+	} layer7;
+#endif
+
 	/* Storage reserved for other modules: */
 	union nf_conntrack_proto proto;
 
@@ -292,6 +308,13 @@
 extern unsigned int nf_conntrack_htable_size;
 extern unsigned int nf_conntrack_max;
 
+#ifdef CONFIG_MV_LINUX_COUNTERS_DISABLE
+
+#define NF_CT_STAT_INC(net, count)
+#define NF_CT_STAT_INC_ATOMIC(net, count)
+
+#else 
+
 #define NF_CT_STAT_INC(net, count)	\
 	(per_cpu_ptr((net)->ct.stat, raw_smp_processor_id())->count++)
 #define NF_CT_STAT_INC_ATOMIC(net, count)		\
@@ -301,6 +324,8 @@
 	local_bh_enable();				\
 } while (0)
 
+#endif /* CONFIG_MV_LINUX_COUNTERS_DISABLE */
+
 #define MODULE_ALIAS_NFCT_HELPER(helper) \
         MODULE_ALIAS("nfct-helper-" helper)
 
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 2628c15..3135700 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -98,6 +98,15 @@
 		/* The direction (for tuplehash) */
 		u_int8_t dir;
 	} dst;
+
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+	/* If true, this connection is handled by NFP */
+	bool nfp;
+	int ifindex;
+	bool nfpCapable;
+	bool udpCsum;
+	struct ipt_nfp_info *info;
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
 };
 
 struct nf_conntrack_tuple_mask
diff --git a/include/net/route.h b/include/net/route.h
index 40f6346..4ee4a3b 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -75,6 +75,10 @@
 	/* Miscellaneous cached information */
 	__be32			rt_spec_dst; /* RFC1122 specific destination */
 	struct inet_peer	*peer; /* long-living peer info */
+
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+	bool 			nfp;
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
 };
 
 struct ip_rt_acct
diff --git a/include/net/snmp.h b/include/net/snmp.h
old mode 100644
new mode 100755
index 8c842e0..adc0dca
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -136,6 +136,20 @@
 #define SNMP_STAT_BHPTR(name)	(name[0])
 #define SNMP_STAT_USRPTR(name)	(name[1])
 
+#ifdef CONFIG_MV_LINUX_COUNTERS_DISABLE 
+
+#define SNMP_INC_STATS_BH(mib, field)
+#define SNMP_INC_STATS_USER(mib, field)
+#define SNMP_INC_STATS(mib, field)
+#define SNMP_DEC_STATS(mib, field)
+#define SNMP_ADD_STATS(mib, field, addend)
+#define SNMP_ADD_STATS_BH(mib, field, addend)
+#define SNMP_ADD_STATS_USER(mib, field, addend)
+#define SNMP_UPD_PO_STATS(mib, basefield, addend)
+#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend)
+
+#else 
+
 #define SNMP_INC_STATS_BH(mib, field) 	\
 	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field]++)
 #define SNMP_INC_STATS_USER(mib, field) \
@@ -178,4 +192,7 @@
 		ptr->mibs[basefield##PKTS]++; \
 		ptr->mibs[basefield##OCTETS] += addend;\
 	} while (0)
+
+#endif /* CONFIG_MV_LINUX_COUNTERS_DISABLE */
+
 #endif
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
old mode 100644
new mode 100755
index f097ae3..3bda7af
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -7,8 +7,11 @@
 #include <linux/workqueue.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi.h>
+#include <linux/timer.h>
 #include <asm/atomic.h>
-
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+#include <scsi/scsi_spinup.h>
+#endif
 struct request_queue;
 struct scsi_cmnd;
 struct scsi_lun;
@@ -167,6 +170,14 @@
 
 	struct scsi_dh_data	*scsi_dh_data;
 	enum scsi_device_state sdev_state;
+
+#ifdef CONFIG_MV_SCATTERED_SPINUP
+	enum scsi_device_power_state sdev_power_state;  /*Used to save the disk current power state*/
+	struct timer_list spinup_timeout;	/* Used to time out the spinup process when done. */
+	unsigned int standby_timeout_secs;
+	struct timer_list standby_timeout;	/* Used to time out the standby timeout command. */
+#endif
+
 	unsigned long		sdev_data[0];
 } __attribute__((aligned(sizeof(unsigned long))));
 
@@ -188,13 +199,10 @@
 	void (*detach)(struct scsi_device *);
 	int (*activate)(struct scsi_device *);
 	int (*prep_fn)(struct scsi_device *, struct request *);
-	int (*set_params)(struct scsi_device *, const char *);
 };
 
 struct scsi_dh_data {
 	struct scsi_device_handler *scsi_dh;
-	struct scsi_device *sdev;
-	struct kref kref;
 	char buf[0];
 };
 
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
old mode 100644
new mode 100755
index 0b4baba..a2ce414
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -48,6 +48,11 @@
 	const char *name;
 
 	/*
+	* support to scattered spinup in various drivers
+	*/
+	unsigned char support_scattered_spinup;
+
+	/*
 	 * Used to initialize old-style drivers.  For new-style drivers
 	 * just perform all work in your module initialization function.
 	 *
diff --git a/include/scsi/scsi_spinup.h b/include/scsi/scsi_spinup.h
new file mode 100755
index 0000000..8ba43de
--- /dev/null
+++ b/include/scsi/scsi_spinup.h
@@ -0,0 +1,43 @@
+/* 
+ *  SCSI Spinup specific attributes.
+ *
+ *  Copyright (c) 2009 Marvell,  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef SCSI_SPINUP_H
+#define SCSI_SPINUP_H
+
+/*
+ * more defines of SCSI / ATA commands that are not defined by default
+ */
+#define STANDBY_IMMEDIATE     0xe0
+#define SLEEP                 0xe6
+#define STANDBY_TIMEOUT       0xe3
+#define VERIFY_10             0x13
+#define START_STOP_BIT        0x00000001
+
+enum scsi_device_power_state {
+	SDEV_PW_UNKNOWN = 0,		//0
+	SDEV_PW_STANDBY,		//1
+	SDEV_PW_STANDBY_TIMEOUT_WAIT,	//2
+	SDEV_PW_STANDBY_TIMEOUT_PASSED,	//3
+    SDEV_PW_SPINNING_UP,	//4
+	SDEV_PW_WAIT_FOR_SPIN_UP,	//5
+	SDEV_PW_ON,			//6
+};
+
+#endif /* SCSI_SPINUP_H */
+
diff --git a/kernel/printk.c b/kernel/printk.c
old mode 100644
new mode 100755
index f38b07f..d2cde12
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -35,6 +35,10 @@
 #include <linux/kexec.h>
 
 #include <asm/uaccess.h>
+#ifdef CONFIG_DEBUG_LL
+/*ll_debug*/
+#include <mach/uncompress.h>
+#endif
 
 /*
  * for_each_console() allows you to iterate on each console
@@ -597,7 +601,9 @@
 
 	return r;
 }
-
+#ifdef CONFIG_DEBUG_LL
+int ll_debug = 0;
+#endif
 /* cpu currently holding logbuf_lock */
 static volatile unsigned int printk_cpu = UINT_MAX;
 
@@ -713,6 +719,9 @@
 	/* Emit the output into the temporary buffer */
 	printed_len += vscnprintf(printk_buf + printed_len,
 				  sizeof(printk_buf) - printed_len, fmt, args);
+#ifdef CONFIG_DEBUG_LL
+	{ extern void printascii(const char *); printascii(printk_buf); }
+#endif
 
 
 	p = printk_buf;
@@ -788,8 +797,15 @@
 	 * will release 'logbuf_lock' regardless of whether it
 	 * actually gets the semaphore or not.
 	 */
-	if (acquire_console_semaphore_for_printk(this_cpu))
+	if (acquire_console_semaphore_for_printk(this_cpu)) {
+#if defined(CONFIG_MV_PRINTK_SLICE_SUPPORT)
+		raw_local_irq_restore(flags);
 		release_console_sem();
+		raw_local_irq_save(flags);
+#else
+		release_console_sem();
+#endif
+	}
 
 	lockdep_on();
 out_restore_irqs:
@@ -1057,7 +1073,14 @@
 			break;			/* Nothing to print */
 		_con_start = con_start;
 		_log_end = log_end;
+#if defined(CONFIG_MV_PRINTK_SLICE_SUPPORT)
+		if((_log_end - _con_start) > CONFIG_MV_PRINTK_CHUNK_SIZE) {
+				_log_end = (_con_start + CONFIG_MV_PRINTK_CHUNK_SIZE);
+		}
+		con_start = _log_end;
+#else
 		con_start = log_end;		/* Flush */
+#endif
 		spin_unlock(&logbuf_lock);
 		stop_critical_timings();	/* don't trace print latency */
 		call_console_drivers(_con_start, _log_end);
diff --git a/kernel/sched.c b/kernel/sched.c
old mode 100644
new mode 100755
index ed61192..8a3ef10
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -131,6 +131,13 @@
 	return rt_policy(p->policy);
 }
 
+#ifdef CONFIG_MV_REAL_TIME
+int mv_task_has_rt_policy(struct task_struct *p)
+{
+	return task_has_rt_policy(p);
+}
+#endif
+
 /*
  * This is the priority-queue data structure of the RT scheduling class:
  */
diff --git a/kernel/softirq.c b/kernel/softirq.c
old mode 100644
new mode 100755
index f8749e5..b187492
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -186,7 +186,12 @@
  * we want to handle softirqs as soon as possible, but they
  * should not be able to lock up the box.
  */
+#ifdef CONFIG_MV_REAL_TIME
+#define MAX_SOFTIRQ_RESTART 2
+extern int mv_task_has_rt_policy(struct task_struct *p);
+#else
 #define MAX_SOFTIRQ_RESTART 10
+#endif
 
 asmlinkage void __do_softirq(void)
 {
@@ -200,6 +205,10 @@
 
 	__local_bh_disable((unsigned long)__builtin_return_address(0));
 	lockdep_softirq_enter();
+#ifdef CONFIG_MV_REAL_TIME
+	if (mv_task_has_rt_policy(current))
+		goto out;
+#endif /* CONFIG_MV_REAL_TIME */
 
 	cpu = smp_processor_id();
 restart:
@@ -239,6 +248,9 @@
 	if (pending && --max_restart)
 		goto restart;
 
+#ifdef CONFIG_MV_REAL_TIME
+out:
+#endif
 	if (pending)
 		wakeup_softirqd();
 
diff --git a/lib/Kconfig b/lib/Kconfig
old mode 100644
new mode 100755
index bb1326d..25e7f28
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -117,6 +117,9 @@
 config DECOMPRESS_LZMA
 	tristate
 
+config DECOMPRESS_LZMA_NEEDED
+	 boolean
+
 #
 # Generic allocator support is selected if needed
 #
diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c
old mode 100644
new mode 100755
index 600f473..6eb6433
--- a/lib/decompress_bunzip2.c
+++ b/lib/decompress_bunzip2.c
@@ -52,6 +52,7 @@
 #include <linux/slab.h>
 #endif /* STATIC */
 
+#include <linux/decompress/bunzip2_mm.h>
 #include <linux/decompress/mm.h>
 
 #ifndef INT_MAX
diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c
old mode 100644
new mode 100755
index fc686c7..cb6bcab
--- a/lib/decompress_inflate.c
+++ b/lib/decompress_inflate.c
@@ -23,6 +23,7 @@
 
 #endif /* STATIC */
 
+#include <linux/decompress/inflate_mm.h>
 #include <linux/decompress/mm.h>
 
 #define GZIP_IOBUF_SIZE (16*1024)
diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c
old mode 100644
new mode 100755
index ca82fde..b2fd927
--- a/lib/decompress_unlzma.c
+++ b/lib/decompress_unlzma.c
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #endif /* STATIC */
 
+#include <linux/decompress/unlzma_mm.h>
 #include <linux/decompress/mm.h>
 
 #define	MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -531,7 +532,7 @@
 
 
 
-STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
+STATIC int INIT unlzma(unsigned char *buf, int in_len,
 			      int(*fill)(void*, unsigned int),
 			      int(*flush)(void*, unsigned int),
 			      unsigned char *output,
@@ -664,4 +665,6 @@
 {
 	return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn);
 }
+#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
+EXPORT_SYMBOL(unlzma);
 #endif
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index c228731..482e17d 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -172,6 +172,43 @@
 			return err;
 	} while (pgd++, addr = next, addr != end);
 
+	/*
+	 * In order to support installation of a non-trivial FIQ handler, on ARM
+	 * we need to replicate kernel virtual memory to all processes (so it
+	 * can be accessed from fiq state irrespective of what current process is).
+	 * The code comes from do_translation_fault, and is arm-specific.
+	 */
+#ifdef CONFIG_MV_PHONE_USE_FIQ_PROCESSING
+	if (!err) {
+		struct task_struct *p;
+		for_each_process(p) {
+			task_lock(p);
+			if (!p->mm)
+				goto next_process;
+			if (p->mm == &init_mm)
+				goto next_process;
+			for (addr = start;
+			     addr < end; addr += PAGE_SIZE) {
+				/* "+= PMD_SIZE" may be faster... */
+				unsigned int index;
+				pgd_t *pgd, *pgd_k;
+				pmd_t *pmd, *pmd_k;
+				/*  from do_translation_fault() */
+				index = pgd_index(addr);
+				pgd = p->mm->pgd + index;
+				pgd_k = init_mm.pgd + index;
+				if (!pgd_present(*pgd))
+					set_pgd(pgd, *pgd_k);
+				pmd_k = pmd_offset(pgd_k, addr);
+				pmd   = pmd_offset(pgd, addr);
+				copy_pmd(pmd, pmd_k);
+			}
+		next_process:
+			task_unlock(p);
+		}
+	}
+#endif /* CONFIG_MV_PHONE_USE_FIQ_PROCESSING */
+
 	return nr;
 }
 
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index a29c5ab..eac48d7 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -39,6 +39,13 @@
 
 #define DRV_VERSION "1.8"
 
+
+#if defined(CONFIG_MV_ETH_NFP_VLAN_LEARN)
+extern int nfp_hook_vlan_add(int if_index, struct net_device *dev,
+					int real_if_index, int vlan_id);
+extern int nfp_hook_vlan_del(int if_index);
+#endif /* CONFIG_MV_ETH_NFP_VLAN_LEARN */
+
 /* Global VLAN variables */
 
 int vlan_net_id;
@@ -164,6 +171,10 @@
 
 	synchronize_net();
 
+#if defined(CONFIG_MV_ETH_NFP_VLAN_LEARN)
+	nfp_hook_vlan_del(dev->ifindex);
+#endif /* CONFIG_MV_ETH_NFP_VLAN_LEARN */
+
 	unregister_netdevice(dev);
 
 	/* If the group is now empty, kill off the group. */
@@ -356,6 +367,10 @@
 	if (err < 0)
 		goto out_free_newdev;
 
+#if defined(CONFIG_MV_ETH_NFP_VLAN_LEARN)
+	nfp_hook_vlan_add(new_dev->ifindex, new_dev, real_dev->ifindex, vlan_id);
+#endif /* CONFIG_MV_ETH_NFP_VLAN_LEARN */
+
 	return 0;
 
 out_free_newdev:
@@ -777,6 +792,26 @@
 	vlan_gvrp_uninit();
 }
 
+#if defined(CONFIG_MV_ETH_NFP_VLAN_LEARN)
+void vlan_sync(void)
+{
+	struct net_device *dev;
+
+	rtnl_lock();
+	for_each_netdev(&init_net, dev) {
+		if (dev->priv_flags & IFF_802_1Q_VLAN) {
+			struct vlan_dev_info *vlan = vlan_dev_info(dev);
+			struct net_device *real_dev = vlan->real_dev;
+			u16 vlan_id = vlan->vlan_id;
+
+			if (nfp_hook_vlan_add(dev->ifindex, dev, real_dev->ifindex, vlan_id))
+				printk("nfp_hook_vlan_add failed in %s\n",__func__);
+		}
+	}
+	rtnl_unlock();
+}
+#endif /* CONFIG_MV_ETH_NFP_VLAN_LEARN */
+
 module_init(vlan_proto_init);
 module_exit(vlan_cleanup_module);
 
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
old mode 100644
new mode 100755
index 57bf05c..59391ff
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -30,6 +30,12 @@
 
 static u32 fdb_salt __read_mostly;
 
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+int nfp_hook_fdb_rule_add(int br_index, int if_index, const u8 *mac, int is_local);
+int nfp_hook_fdb_rule_age(int br_index, int if_index, const u8 *mac);
+int nfp_hook_fdb_rule_del(int br_index, int if_index, const u8 *mac);
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
+
 int __init br_fdb_init(void)
 {
 	br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
@@ -58,10 +64,20 @@
 }
 
 static inline int has_expired(const struct net_bridge *br,
-				  const struct net_bridge_fdb_entry *fdb)
+				struct net_bridge_fdb_entry *fdb)
 {
-	return !fdb->is_static
-		&& time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
+	if (fdb->is_static)
+		return 0;
+
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+	if (fdb->nfp) {
+		if (nfp_hook_fdb_rule_age(fdb->dst->br->dev->ifindex,
+					fdb->dst->dev->ifindex, fdb->addr.addr) > 0)
+			fdb->ageing_timer = jiffies + fdb->dst->br->forward_delay;
+	}
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
+
+	return time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
 }
 
 static inline int br_mac_hash(const unsigned char *mac)
@@ -80,6 +96,13 @@
 
 static inline void fdb_delete(struct net_bridge_fdb_entry *f)
 {
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+	if (f->nfp) {
+		nfp_hook_fdb_rule_del(f->dst->br->dev->ifindex,
+				f->dst->dev->ifindex, f->addr.addr);
+	}
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
+
 	hlist_del_rcu(&f->hlist);
 	call_rcu(&f->rcu, fdb_rcu_free);
 }
@@ -139,6 +162,15 @@
 			unsigned long this_timer;
 			if (f->is_static)
 				continue;
+
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+			if (f->nfp) {
+				if (nfp_hook_fdb_rule_age(f->dst->br->dev->ifindex,
+							f->dst->dev->ifindex, f->addr.addr) > 0)
+					f->ageing_timer = jiffies + f->dst->br->forward_delay;
+			}
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
+
 			this_timer = f->ageing_timer + delay;
 			if (time_before_eq(this_timer, jiffies))
 				fdb_delete(f);
@@ -332,6 +364,12 @@
 		fdb->is_local = is_local;
 		fdb->is_static = is_local;
 		fdb->ageing_timer = jiffies;
+
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+		fdb->nfp = false;
+		if (!nfp_hook_fdb_rule_add(fdb->dst->br->dev->ifindex, fdb->dst->dev->ifindex, addr, is_local))
+			fdb->nfp = true;
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
 	}
 	return fdb;
 }
@@ -414,3 +452,37 @@
 		spin_unlock(&br->hash_lock);
 	}
 }
+
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+void fdb_sync(void)
+{
+	struct net_device *dev;
+	struct net_bridge *br;
+	int i;
+	rtnl_lock();	
+	for_each_netdev(&init_net, dev) {
+		if (dev->priv_flags & IFF_EBRIDGE) {
+			br = netdev_priv(dev);
+			spin_lock_bh(&br->hash_lock);
+			for (i = 0; i < BR_HASH_SIZE; i++) {
+				struct net_bridge_fdb_entry *fdb;
+				struct hlist_node *h, *n;
+				hlist_for_each_entry_safe(fdb, h, n, &br->hash[i], hlist) {
+					if (!nfp_hook_fdb_rule_add(fdb->dst->br->dev->ifindex,
+							       fdb->dst->dev->ifindex,
+							       fdb->addr.addr,
+							       fdb->is_local)) {
+						/* oeprtaion succeeded */
+						fdb->nfp = true;
+					}
+
+				}
+			}
+			spin_unlock_bh(&br->hash_lock);
+
+		}
+	}
+	rtnl_unlock();
+}
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
+
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 4a9f527..0f9980b 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -23,6 +23,11 @@
 
 #include "br_private.h"
 
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+int nfp_hook_del_br(int ifindex);
+int nfp_hook_del_port_from_br(int bridge_if, int port_if);
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
+
 /*
  * Determine initial path cost based on speed.
  * using recommendations from 802.1d standard
@@ -159,11 +164,20 @@
 	struct net_bridge_port *p, *n;
 
 	list_for_each_entry_safe(p, n, &br->port_list, list) {
+	
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+	nfp_hook_del_port_from_br(br->dev->ifindex, p->dev->ifindex);
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
+
 		del_nbp(p);
 	}
 
 	del_timer_sync(&br->gc_timer);
 
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+	nfp_hook_del_br(br->dev->ifindex);
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
+
 	br_sysfs_delbr(br->dev);
 	unregister_netdevice(br->dev);
 }
@@ -452,6 +466,10 @@
 
 	if (!p || p->br != br)
 		return -EINVAL;
+		
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+	nfp_hook_del_port_from_br(br->dev->ifindex, p->dev->ifindex);
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
 
 	del_nbp(p);
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 2114e45..6bc750d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -55,6 +55,10 @@
 	mac_addr			addr;
 	unsigned char			is_local;
 	unsigned char			is_static;
+
+#if defined(CONFIG_MV_ETH_NFP_FDB_LEARN)
+	bool 			nfp;
+#endif /* CONFIG_MV_ETH_NFP_FDB_LEARN */
 };
 
 struct net_bridge_port
diff --git a/net/core/dev.c b/net/core/dev.c
index 74d0cce..ee63836 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2266,6 +2266,25 @@
 	rcu_read_unlock();
 }
 
+
+
+#ifdef CONFIG_MV_ETH_NFP_EXT
+static struct sk_buff *handle_nfp_extrcv(struct sk_buff *skb, struct net_device *dev)
+{
+	MV_EXT_PKT_INFO *pktInfo;
+
+	pktInfo = (MV_EXT_PKT_INFO *)&skb->cb;
+	if (pktInfo->flags == 0)
+		pktInfo = NULL;
+
+	if (!mv_eth_nfp_ext(skb->dev, skb, pktInfo))
+		return NULL;
+
+	return skb;
+}
+#endif /* CONFIG_MV_ETH_NFP_EXT */
+
+
 /**
  *	netif_receive_skb - process receive buffer from network
  *	@skb: buffer to process
@@ -2328,6 +2347,12 @@
 	}
 #endif
 
+#ifdef CONFIG_MV_ETH_NFP_EXT
+	skb = handle_nfp_extrcv(skb, orig_dev);
+	if (!skb)
+		goto out;
+#endif /* CONFIG_MV_ETH_NFP_EXT */
+
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
 		if (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
 		    ptype->dev == orig_dev) {
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
old mode 100644
new mode 100755
index e587e68..c88d3d3
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -36,6 +36,12 @@
 #include <linux/string.h>
 #include <linux/log2.h>
 
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+extern int nfp_hook_arp_add(int family, const u8 *ip, u8 *mac, int if_index);
+extern int nfp_hook_arp_delete(int family, const u8 *ip);
+extern int nfp_hook_arp_is_confirmed(int family, const u8 *ip);
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 #define NEIGH_DEBUG 1
 
 #define NEIGH_PRINTK(x...) printk(x)
@@ -635,6 +641,15 @@
 	if (neigh_del_timer(neigh))
 		printk(KERN_WARNING "Impossible event.\n");
 
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+	if (neigh->nfp) {
+		nfp_hook_arp_delete(neigh->tbl->family, neigh->primary_key);
+
+		NEIGH_PRINTK2("0x%8lx: neigh %p, ref=%d, state=%d, nfp=%d is connected in %s.\n",
+			jiffies, neigh, atomic_read(&neigh->refcnt), neigh->nud_state, neigh->nfp, __func__);
+	}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 	while ((hh = neigh->hh) != NULL) {
 		neigh->hh = hh->hh_next;
 		hh->hh_next = NULL;
@@ -651,7 +666,7 @@
 	dev_put(neigh->dev);
 	neigh_parms_put(neigh->parms);
 
-	NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
+	NEIGH_PRINTK2("0x%8lx: neigh %p is destroyed in %s.\n", jiffies, neigh, __func__);
 
 	atomic_dec(&neigh->tbl->entries);
 	kmem_cache_free(neigh->tbl->kmem_cachep, neigh);
@@ -667,7 +682,7 @@
 {
 	struct hh_cache *hh;
 
-	NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
+	NEIGH_PRINTK2("0x%8lx: neigh %p is suspected in %s.\n", jiffies, neigh, __func__);
 
 	neigh->output = neigh->ops->output;
 
@@ -684,7 +699,15 @@
 {
 	struct hh_cache *hh;
 
-	NEIGH_PRINTK2("neigh %p is connected.\n", neigh);
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+	neigh->nfp = false;
+	if (!nfp_hook_arp_add(neigh->tbl->family, neigh->primary_key, neigh->ha, neigh->dev->ifindex)) {
+		neigh->nfp = true;
+
+		NEIGH_PRINTK2("0x%8lx: neigh %p, ref=%d, state=%d, nfp=%d is connected in %s.\n",
+			jiffies, neigh, atomic_read(&neigh->refcnt), neigh->nud_state, neigh->nfp, __func__);
+	}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
 
 	neigh->output = neigh->ops->connected_output;
 
@@ -731,6 +754,19 @@
 			if (time_before(n->used, n->confirmed))
 				n->used = n->confirmed;
 
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+			if ((atomic_read(&n->refcnt) == 1) && (state != NUD_FAILED) &&
+				time_after(jiffies, n->used + n->parms->gc_staletime)) {
+				if (n->nfp) {
+					if (nfp_hook_arp_is_confirmed(n->tbl->family, n->primary_key)) {
+						neigh_event_send(n, NULL);
+					}
+					NEIGH_PRINTK2("0x%8lx: neigh %p ref=%d, state=%d, NFP ARP aging in %s\n",
+						jiffies, n, atomic_read(&n->refcnt), n->nud_state, __func__);
+				}
+			}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 			if (atomic_read(&n->refcnt) == 1 &&
 			    (state == NUD_FAILED ||
 			     time_after(jiffies, n->used + n->parms->gc_staletime))) {
@@ -762,7 +798,7 @@
 	write_unlock_bh(&tbl->lock);
 }
 
-static __inline__ int neigh_max_probes(struct neighbour *n)
+static inline int neigh_max_probes(struct neighbour *n)
 {
 	struct neigh_parms *p = n->parms;
 	return (n->nud_state & NUD_PROBE ?
@@ -775,7 +811,7 @@
 	struct sk_buff *skb;
 
 	NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
-	NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
+	NEIGH_PRINTK2("0x%8lx: neigh %p is failed in %s.\n", jiffies, neigh, __func__);
 	neigh->updated = jiffies;
 
 	/* It is very thin place. report_unreachable is very complicated
@@ -815,19 +851,21 @@
 	}
 
 	if (state & NUD_REACHABLE) {
+
 		if (time_before_eq(now,
 				   neigh->confirmed + neigh->parms->reachable_time)) {
-			NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
+			NEIGH_PRINTK2("0x%8lx: neigh %p is still alive in %s.\n", now, neigh, __func__);
 			next = neigh->confirmed + neigh->parms->reachable_time;
 		} else if (time_before_eq(now,
 					  neigh->used + neigh->parms->delay_probe_time)) {
-			NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+			NEIGH_PRINTK2("0x%8lx: neigh %p is delayed in %s.\n", now, neigh, __func__);
 			neigh->nud_state = NUD_DELAY;
 			neigh->updated = jiffies;
 			neigh_suspect(neigh);
+
 			next = now + neigh->parms->delay_probe_time;
 		} else {
-			NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
+			NEIGH_PRINTK2("0x%8lx: neigh %p is suspected in %s.\n", now, neigh, __func__);
 			neigh->nud_state = NUD_STALE;
 			neigh->updated = jiffies;
 			neigh_suspect(neigh);
@@ -843,7 +881,7 @@
 			notify = 1;
 			next = neigh->confirmed + neigh->parms->reachable_time;
 		} else {
-			NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
+			NEIGH_PRINTK2("0x%8lx: neigh %p is probed in %s.\n", now, neigh, __func__);
 			neigh->nud_state = NUD_PROBE;
 			neigh->updated = jiffies;
 			atomic_set(&neigh->probes, 0);
@@ -915,7 +953,8 @@
 			return 1;
 		}
 	} else if (neigh->nud_state & NUD_STALE) {
-		NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+		NEIGH_PRINTK2("0x%8lx: neigh %p ref=%d is delayed in %s.\n",
+				now, neigh, atomic_read(&neigh->refcnt), __func__);
 		neigh->nud_state = NUD_DELAY;
 		neigh->updated = jiffies;
 		neigh_add_timer(neigh,
@@ -1566,6 +1605,8 @@
 		err = neigh_update(neigh, NULL, NUD_FAILED,
 				   NEIGH_UPDATE_F_OVERRIDE |
 				   NEIGH_UPDATE_F_ADMIN);
+		NEIGH_PRINTK2("0x%8lx: neigh %p ref=%d, release in %s\n",
+				jiffies, neigh, atomic_read(&neigh->refcnt), __func__);
 		neigh_release(neigh);
 		goto out_dev_put;
 	}
@@ -2080,7 +2121,7 @@
 static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 			    struct netlink_callback *cb)
 {
-	struct net * net = sock_net(skb->sk);
+	struct net *net = sock_net(skb->sk);
 	struct neighbour *n;
 	int rc, h, s_h = cb->args[1];
 	int idx, s_idx = idx = cb->args[2];
@@ -2254,7 +2295,7 @@
 
 			if (n->nud_state & ~NUD_NOARP)
 				break;
-		next:
+next:
 			n = n->next;
 		}
 
@@ -2817,6 +2858,35 @@
 
 #endif	/* CONFIG_SYSCTL */
 
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+void neigh_sync(int family)
+{
+	struct neigh_table *tbl;
+	struct neighbour *n;
+	int t, h, idx;
+
+	read_lock(&neigh_tbl_lock);
+	for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) {
+		if (tbl->family == family) {
+			for (h = 0; h <= tbl->hash_mask; h++) {
+				for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) {
+					if (n->dev == NULL)
+						continue;
+					n->nfp = false;
+					if (!nfp_hook_arp_add(n->tbl->family,
+							n->primary_key,
+							n->ha,
+							n->dev->ifindex)) {
+						n->nfp = true;
+					}
+				}
+			}
+		}
+	}
+	read_unlock(&neigh_tbl_lock);
+}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 static int __init neigh_init(void)
 {
 	rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
old mode 100644
new mode 100755
index ec85681..9a1640b
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -336,7 +336,7 @@
 		skb_get(list);
 }
 
-static void skb_release_data(struct sk_buff *skb)
+static inline void skb_release_data(struct sk_buff *skb)
 {
 	if (!skb->cloned ||
 	    !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
@@ -352,12 +352,20 @@
 
 		kfree(skb->head);
 	}
+#ifdef CONFIG_NET_SKB_RECYCLE
+	/* Workaround for the cases when recycle callback was not called */
+	if (skb->hw_cookie) {
+		kfree(skb->hw_cookie);
+		skb->hw_cookie = NULL;
+	}
+	skb->skb_recycle = NULL;
+#endif /* CONFIG_NET_SKB_RECYCLE */	
 }
 
 /*
  *	Free an skbuff by memory without cleaning the state.
  */
-static void kfree_skbmem(struct sk_buff *skb)
+static inline void kfree_skbmem(struct sk_buff *skb)
 {
 	struct sk_buff *other;
 	atomic_t *fclone_ref;
@@ -388,7 +396,7 @@
 	}
 }
 
-static void skb_release_head_state(struct sk_buff *skb)
+static inline void skb_release_head_state(struct sk_buff *skb)
 {
 	skb_dst_drop(skb);
 #ifdef CONFIG_XFRM
@@ -399,8 +407,11 @@
 		skb->destructor(skb);
 	}
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-	nf_conntrack_put(skb->nfct);
-	nf_conntrack_put_reasm(skb->nfct_reasm);
+	if(skb->nfct) 
+		nf_conntrack_put(skb->nfct);
+	
+	if(skb->nfct_reasm) 
+		nf_conntrack_put_reasm(skb->nfct_reasm);
 #endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(skb->nf_bridge);
@@ -415,7 +426,7 @@
 }
 
 /* Free everything but the sk_buff shell. */
-static void skb_release_all(struct sk_buff *skb)
+static inline void skb_release_all(struct sk_buff *skb)
 {
 	skb_release_head_state(skb);
 	skb_release_data(skb);
@@ -432,6 +443,11 @@
 
 void __kfree_skb(struct sk_buff *skb)
 {
+#ifdef CONFIG_NET_SKB_RECYCLE
+	if (skb->skb_recycle && !skb->skb_recycle(skb))
+		return;
+#endif /* CONFIG_NET_SKB_RECYCLE */
+ 
 	skb_release_all(skb);
 	kfree_skbmem(skb);
 }
@@ -500,7 +516,7 @@
 	if (skb_end_pointer(skb) - skb->head < skb_size)
 		return 0;
 
-	if (skb_shared(skb) || skb_cloned(skb))
+	if (skb_shared(skb) || skb_cloned(skb) || skb_has_frags(skb))
 		return 0;
 
 	skb_release_head_state(skb);
@@ -582,6 +598,12 @@
 	n->cloned = 1;
 	n->nohdr = 0;
 	n->destructor = NULL;
+
+#ifdef CONFIG_NET_SKB_RECYCLE
+	n->skb_recycle = NULL;
+	n->hw_cookie = NULL;
+#endif /* CONFIG_NET_SKB_RECYCLE */
+
 	C(tail);
 	C(end);
 	C(head);
diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c
old mode 100644
new mode 100755
index 6a667da..8bf3655
--- a/net/ipv4/inet_lro.c
+++ b/net/ipv4/inet_lro.c
@@ -338,11 +338,22 @@
 	struct tcphdr *tcph;
 	u64 flags;
 	int vlan_hdr_len = 0;
-
+/*
 	if (!lro_mgr->get_skb_header
 	    || lro_mgr->get_skb_header(skb, (void *)&iph, (void *)&tcph,
 				       &flags, priv))
 		goto out;
+*/
+	if (!lro_mgr->get_skb_header) {
+		skb_reset_network_header(skb);
+		skb_set_transport_header(skb, ip_hdrlen(skb));
+		iph = ip_hdr(skb);
+		tcph = tcp_hdr(skb);
+		flags = LRO_IPV4 | LRO_TCP;
+	}
+	else if (lro_mgr->get_skb_header(skb, (void *)&iph, (void *)&tcph,
+				       &flags, priv))
+		goto out;
 
 	if (!(flags & LRO_IPV4) || !(flags & LRO_TCP))
 		goto out;
diff --git a/net/ipv4/netfilter/IPT_EC~1.C b/net/ipv4/netfilter/IPT_EC~1.C
new file mode 100755
index 0000000..6289b64
--- /dev/null
+++ b/net/ipv4/netfilter/IPT_EC~1.C
@@ -0,0 +1,129 @@
+/* IP tables module for matching the value of the IPv4 and TCP ECN bits
+ *
+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_ecn.h>
+
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag match for IPv4");
+MODULE_LICENSE("GPL");
+
+static inline bool match_ip(const struct sk_buff *skb,
+			    const struct ipt_ecn_info *einfo)
+{
+	return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect;
+}
+
+static inline bool match_tcp(const struct sk_buff *skb,
+			     const struct ipt_ecn_info *einfo,
+			     bool *hotdrop)
+{
+	struct tcphdr _tcph;
+	const struct tcphdr *th;
+
+	/* In practice, TCP match does this, so can't fail.  But let's
+	 * be good citizens.
+	 */
+	th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
+	if (th == NULL) {
+		*hotdrop = false;
+		return false;
+	}
+
+	if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
+		if (einfo->invert & IPT_ECN_OP_MATCH_ECE) {
+			if (th->ece == 1)
+				return false;
+		} else {
+			if (th->ece == 0)
+				return false;
+		}
+	}
+
+	if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
+		if (einfo->invert & IPT_ECN_OP_MATCH_CWR) {
+			if (th->cwr == 1)
+				return false;
+		} else {
+			if (th->cwr == 0)
+				return false;
+		}
+	}
+
+	return true;
+}
+
+static bool ecn_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+	const struct ipt_ecn_info *info = par->matchinfo;
+
+	if (info->operation & IPT_ECN_OP_MATCH_IP)
+		if (!match_ip(skb, info))
+			return false;
+
+	if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
+		if (ip_hdr(skb)->protocol != IPPROTO_TCP)
+			return false;
+		if (!match_tcp(skb, info, par->hotdrop))
+			return false;
+	}
+
+	return true;
+}
+
+static bool ecn_mt_check(const struct xt_mtchk_param *par)
+{
+	const struct ipt_ecn_info *info = par->matchinfo;
+	const struct ipt_ip *ip = par->entryinfo;
+
+	if (info->operation & IPT_ECN_OP_MATCH_MASK)
+		return false;
+
+	if (info->invert & IPT_ECN_OP_MATCH_MASK)
+		return false;
+
+	if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)
+	    && ip->proto != IPPROTO_TCP) {
+		printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for"
+		       " non-tcp packets\n");
+		return false;
+	}
+
+	return true;
+}
+
+static struct xt_match ecn_mt_reg __read_mostly = {
+	.name		= "ecn",
+	.family		= NFPROTO_IPV4,
+	.match		= ecn_mt,
+	.matchsize	= sizeof(struct ipt_ecn_info),
+	.checkentry	= ecn_mt_check,
+	.me		= THIS_MODULE,
+};
+
+static int __init ecn_mt_init(void)
+{
+	return xt_register_match(&ecn_mt_reg);
+}
+
+static void __exit ecn_mt_exit(void)
+{
+	xt_unregister_match(&ecn_mt_reg);
+}
+
+module_init(ecn_mt_init);
+module_exit(ecn_mt_exit);
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 1833bdb..30d913e 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -192,6 +192,13 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_TARGET_NFP
+	tristate "NFP target support"
+	depends on NF_CONNTRACK_IPV4 && MV_ETH_NFP_NAT
+	help
+	  This target allows to process selected connections in NFP.
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_TARGET_REDIRECT
 	tristate "REDIRECT target support"
 	depends on NF_NAT
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 4811159..6d1a456 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -58,6 +58,7 @@
 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
+obj-$(CONFIG_IP_NF_TARGET_NFP) += ipt_NFP.o
 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
old mode 100644
new mode 100755
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
old mode 100644
new mode 100755
index 6289b64..f7e2fa0
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -1,129 +1,141 @@
-/* IP tables module for matching the value of the IPv4 and TCP ECN bits
+/* iptables module for the IPv4 and TCP ECN bits, Version 1.5
  *
- * (C) 2002 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2002 by Harald Welte <laforge@netfilter.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- */
+*/
 
 #include <linux/in.h>
-#include <linux/ip.h>
-#include <net/ip.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/ip.h>
 #include <linux/tcp.h>
+#include <net/checksum.h>
 
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_ecn.h>
+#include <linux/netfilter_ipv4/ipt_ECN.h>
 
-MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
-MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag match for IPv4");
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag modification");
 
-static inline bool match_ip(const struct sk_buff *skb,
-			    const struct ipt_ecn_info *einfo)
+/* set ECT codepoint from IP header.
+ * 	return false if there was an error. */
+static inline bool
+set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
 {
-	return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect;
-}
+	struct iphdr *iph = ip_hdr(skb);
 
-static inline bool match_tcp(const struct sk_buff *skb,
-			     const struct ipt_ecn_info *einfo,
-			     bool *hotdrop)
-{
-	struct tcphdr _tcph;
-	const struct tcphdr *th;
-
-	/* In practice, TCP match does this, so can't fail.  But let's
-	 * be good citizens.
-	 */
-	th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
-	if (th == NULL) {
-		*hotdrop = false;
-		return false;
+	if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
+		__u8 oldtos;
+		if (!skb_make_writable(skb, sizeof(struct iphdr)))
+			return false;
+		iph = ip_hdr(skb);
+		oldtos = iph->tos;
+		iph->tos &= ~IPT_ECN_IP_MASK;
+		iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
+		csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
 	}
-
-	if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
-		if (einfo->invert & IPT_ECN_OP_MATCH_ECE) {
-			if (th->ece == 1)
-				return false;
-		} else {
-			if (th->ece == 0)
-				return false;
-		}
-	}
-
-	if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
-		if (einfo->invert & IPT_ECN_OP_MATCH_CWR) {
-			if (th->cwr == 1)
-				return false;
-		} else {
-			if (th->cwr == 0)
-				return false;
-		}
-	}
-
 	return true;
 }
 
-static bool ecn_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+/* Return false if there was an error. */
+static inline bool
+set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
 {
-	const struct ipt_ecn_info *info = par->matchinfo;
+	struct tcphdr _tcph, *tcph;
+	__be16 oldval;
 
-	if (info->operation & IPT_ECN_OP_MATCH_IP)
-		if (!match_ip(skb, info))
-			return false;
+	/* Not enought header? */
+	tcph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
+	if (!tcph)
+		return false;
 
-	if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
-		if (ip_hdr(skb)->protocol != IPPROTO_TCP)
-			return false;
-		if (!match_tcp(skb, info, par->hotdrop))
-			return false;
-	}
+	if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) ||
+	     tcph->ece == einfo->proto.tcp.ece) &&
+	    (!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
+	     tcph->cwr == einfo->proto.tcp.cwr))
+		return true;
 
+	if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
+		return false;
+	tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb);
+
+	oldval = ((__be16 *)tcph)[6];
+	if (einfo->operation & IPT_ECN_OP_SET_ECE)
+		tcph->ece = einfo->proto.tcp.ece;
+	if (einfo->operation & IPT_ECN_OP_SET_CWR)
+		tcph->cwr = einfo->proto.tcp.cwr;
+
+	inet_proto_csum_replace2(&tcph->check, skb,
+				 oldval, ((__be16 *)tcph)[6], 0);
 	return true;
 }
 
-static bool ecn_mt_check(const struct xt_mtchk_param *par)
+static unsigned int
+ecn_tg(struct sk_buff *skb, const struct xt_target_param *par)
 {
-	const struct ipt_ecn_info *info = par->matchinfo;
-	const struct ipt_ip *ip = par->entryinfo;
+	const struct ipt_ECN_info *einfo = par->targinfo;
 
-	if (info->operation & IPT_ECN_OP_MATCH_MASK)
-		return false;
+	if (einfo->operation & IPT_ECN_OP_SET_IP)
+		if (!set_ect_ip(skb, einfo))
+			return NF_DROP;
 
-	if (info->invert & IPT_ECN_OP_MATCH_MASK)
-		return false;
+	if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR)
+	    && ip_hdr(skb)->protocol == IPPROTO_TCP)
+		if (!set_ect_tcp(skb, einfo))
+			return NF_DROP;
 
-	if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)
-	    && ip->proto != IPPROTO_TCP) {
-		printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for"
-		       " non-tcp packets\n");
+	return XT_CONTINUE;
+}
+
+static bool ecn_tg_check(const struct xt_tgchk_param *par)
+{
+	const struct ipt_ECN_info *einfo = par->targinfo;
+	const struct ipt_entry *e = par->entryinfo;
+
+	if (einfo->operation & IPT_ECN_OP_MASK) {
+		printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
+			einfo->operation);
 		return false;
 	}
-
+	if (einfo->ip_ect & ~IPT_ECN_IP_MASK) {
+		printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n",
+			einfo->ip_ect);
+		return false;
+	}
+	if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
+	    && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) {
+		printk(KERN_WARNING "ECN: cannot use TCP operations on a "
+		       "non-tcp rule\n");
+		return false;
+	}
 	return true;
 }
 
-static struct xt_match ecn_mt_reg __read_mostly = {
-	.name		= "ecn",
+static struct xt_target ecn_tg_reg __read_mostly = {
+	.name		= "ECN",
 	.family		= NFPROTO_IPV4,
-	.match		= ecn_mt,
-	.matchsize	= sizeof(struct ipt_ecn_info),
-	.checkentry	= ecn_mt_check,
+	.target		= ecn_tg,
+	.targetsize	= sizeof(struct ipt_ECN_info),
+	.table		= "mangle",
+	.checkentry	= ecn_tg_check,
 	.me		= THIS_MODULE,
 };
 
-static int __init ecn_mt_init(void)
+static int __init ecn_tg_init(void)
 {
-	return xt_register_match(&ecn_mt_reg);
+	return xt_register_target(&ecn_tg_reg);
 }
 
-static void __exit ecn_mt_exit(void)
+static void __exit ecn_tg_exit(void)
 {
-	xt_unregister_match(&ecn_mt_reg);
+	xt_unregister_target(&ecn_tg_reg);
 }
 
-module_init(ecn_mt_init);
-module_exit(ecn_mt_exit);
+module_init(ecn_tg_init);
+module_exit(ecn_tg_exit);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 2fb7b76..11731ae 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -153,6 +153,19 @@
 		goto release;
 #endif
 
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+	if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.nfp) && (ct->tuplehash[IP_CT_DIR_REPLY].tuple.nfp)) {
+		if (seq_printf(s, "[NFP (both)] "))
+			goto release;
+	} else if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.nfp) {
+		if (seq_printf(s, "[NFP (orig)] "))
+			goto release;
+	} else if (ct->tuplehash[IP_CT_DIR_REPLY].tuple.nfp) {
+		if (seq_printf(s, "[NFP (reply)] "))
+			goto release;
+	}
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
+
 	if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
 		goto release;
 	ret = 0;
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
old mode 100644
new mode 100755
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
old mode 100644
new mode 100755
index 5b1050a..a264c81
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -108,6 +108,14 @@
 #include <linux/sysctl.h>
 #endif
 
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+extern int nfp_fib_learn_en;
+extern int nfp_learn_en;
+extern int nfp_hook_fib_rule_add(int family, u8 *src_l3, u8 *dst_l3, u8 *gtw_l3, int iif, int oif);
+extern int nfp_hook_fib_rule_del(int family, u8 *src_l3, u8 *dst_l3, int iif, int oif);
+extern int nfp_hook_fib_rule_age(int family, u8 *src_l3, u8 *dst_l3, int iif, int oif);
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 #define RT_FL_TOS(oldflp) \
     ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
 
@@ -610,6 +618,12 @@
 
 static inline void rt_free(struct rtable *rt)
 {
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+		if (rt->nfp)	
+			nfp_hook_fib_rule_del(AF_INET, (u8*)(&rt->rt_src),(u8*)(&rt->rt_dst), 
+							rt->rt_iif, rt->u.dst.dev->ifindex);
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
@@ -646,6 +660,14 @@
 	    time_after_eq(jiffies, rth->u.dst.expires))
 		goto out;
 
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+	if (rth->nfp) {
+		if (nfp_hook_fib_rule_age(AF_INET,(u8 *)(&rth->rt_src), (u8 *)(&rth->rt_dst), 
+						rth->rt_iif, rth->u.dst.dev->ifindex))
+			rth->u.dst.lastuse = jiffies;
+	}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 	age = jiffies - rth->u.dst.lastuse;
 	ret = 0;
 	if ((age <= tmo1 && !rt_fast_clean(rth)) ||
@@ -769,6 +791,35 @@
 	}
 }
 
+
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+void nfp_fib_sync(void)
+{
+	struct rtable *rt;
+	int h;
+
+	for (h = 0; h <= rt_hash_mask; h++) {
+		if (!rt_hash_table[h].chain)
+			continue;
+
+		rcu_read_lock_bh();
+		for (rt = rcu_dereference(rt_hash_table[h].chain); rt;
+		    rt = rcu_dereference(rt->u.dst.rt_next)) {
+			if (rt_is_expired(rt))
+				continue;
+
+			rt->nfp = false;
+			if (!(rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST | RTCF_LOCAL | RTCF_REJECT))) {
+				if (!nfp_hook_fib_rule_add(AF_INET, (u8 *)(&rt->rt_src), (u8 *)(&rt->rt_dst),
+					  (u8 *)(&rt->rt_gateway), rt->rt_iif, rt->u.dst.dev->ifindex))
+					rt->nfp = true;
+			}
+		}
+		rcu_read_unlock_bh();
+	}
+}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 /*
  * While freeing expired entries, we compute average chain length
  * and standard deviation, using fixed-point arithmetic.
@@ -908,7 +959,14 @@
 static void rt_secret_rebuild(unsigned long __net)
 {
 	struct net *net = (struct net *)__net;
-	rt_cache_invalidate(net);
+
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+	/* If NFP enabled doesn't flush */
+    	if (!nfp_fib_learn_en || !nfp_learn_en)
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+	{
+		rt_cache_invalidate(net);
+	}
 	mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval);
 }
 
@@ -1994,7 +2052,6 @@
 		}
 	}
 
-
 	rth = dst_alloc(&ipv4_dst_ops);
 	if (!rth) {
 		err = -ENOBUFS;
@@ -2015,7 +2072,7 @@
 	rth->rt_src	= saddr;
 	rth->rt_gateway	= daddr;
 	rth->rt_iif 	=
-		rth->fl.iif	= in_dev->dev->ifindex;
+	rth->fl.iif	= in_dev->dev->ifindex;
 	rth->u.dst.dev	= (out_dev)->dev;
 	dev_hold(rth->u.dst.dev);
 	rth->idev	= in_dev_get(rth->u.dst.dev);
@@ -2030,7 +2087,17 @@
 
 	rth->rt_flags = flags;
 
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+	rth->nfp = false;
+	if (!(rth->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST | RTCF_LOCAL | RTCF_REJECT))) {
+		if (!nfp_hook_fib_rule_add(AF_INET, (u8*)(&rth->rt_src), (u8*)(&rth->rt_dst), 
+					(u8*)(&rth->rt_gateway), rth->rt_iif, rth->u.dst.dev->ifindex))
+			rth->nfp = true;
+	}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 	*result = rth;
+
 	err = 0;
  cleanup:
 	/* release the working reference to the output device */
@@ -3450,6 +3517,7 @@
 #ifdef CONFIG_SYSCTL
 	register_pernet_subsys(&sysctl_route_ops);
 #endif
+
 	return rc;
 }
 
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
old mode 100644
new mode 100755
index 0e93ca5..0c50a0e
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -46,6 +46,13 @@
 #define RT6_TRACE(x...) do { ; } while (0)
 #endif
 
+#if defined (CONFIG_MV_ETH_NFP_FIB_LEARN)
+extern int nfp_hook_fib_rule_add(int family, const u8 *src_l3, const u8 *dst_l3,
+				const u8 *def_gtw_l3, int iif, int oif);
+extern int nfp_hook_fib_rule_del(int family, const u8 *src_l3, const u8 *dst_l3, int iif, int oif);
+extern int nfp_hook_fib_rule_age(int family, u8 *src_l3, u8 *dst_l3, int iif, int oif);
+#endif /*  CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 static struct kmem_cache * fib6_node_kmem __read_mostly;
 
 enum fib_walk_state_t
@@ -399,6 +406,53 @@
 	return res;
 }
 
+
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+static int fib6_add_node(struct fib6_walker_t *w)
+{
+	struct rt6_info *rt;
+	for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
+		if (rt->rt6i_flags & RTF_CACHE) {
+			if (!nfp_hook_fib_rule_add(AF_INET6, (u8 *)&rt->rt6i_src.addr,
+				(u8 *)&rt->rt6i_dst.addr,
+				(u8 *)&rt->rt6i_gateway,
+				rt->rt6i_iifindex,
+				rt->rt6i_dev->ifindex))
+				rt->nfp = true;
+		}
+	}
+	w->leaf = rt;
+	return 0;
+}
+
+void nfp_fib6_sync(void)
+{
+	struct fib6_table *table;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	unsigned int h;
+	int res;
+	struct net *net = &init_net;
+	struct fib6_walker_t w;
+
+	w.func = fib6_add_node;
+	w.prune = 0;
+
+	rcu_read_lock();
+	for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
+		head = &net->ipv6.fib_table_hash[h];
+		hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
+			write_lock_bh(&table->tb6_lock);
+			w.root = &table->tb6_root;
+			res = fib6_walk(&w);
+			write_unlock_bh(&table->tb6_lock);
+		}
+	}
+	rcu_read_unlock();
+
+}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 /*
  *	Routing Table
  *
@@ -652,6 +706,18 @@
 		fn->fn_flags |= RTN_RTINFO;
 	}
 
+#if defined (CONFIG_MV_ETH_NFP_FIB_LEARN)
+	rt->nfp = false;
+	if (rt->rt6i_flags & RTF_CACHE)	{
+		if (!nfp_hook_fib_rule_add(AF_INET6, (u8 *)&rt->rt6i_src.addr,
+				(u8 *)&rt->rt6i_dst.addr,
+				(u8 *)&rt->rt6i_gateway,
+				rt->rt6i_iifindex,
+				rt->rt6i_dev->ifindex))
+				rt->nfp = true; 
+	}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+
 	return 0;
 }
 
@@ -1140,6 +1206,14 @@
 	}
 
 	inet6_rt_notify(RTM_DELROUTE, rt, info);
+
+#if defined (CONFIG_MV_ETH_NFP_FIB_LEARN)    
+	if (rt->rt6i_flags & RTF_CACHE)
+		if (rt->nfp)
+			nfp_hook_fib_rule_del(AF_INET6, (u8 *)&rt->rt6i_src.addr, (u8 *)&rt->rt6i_dst.addr,
+							rt->rt6i_iifindex, rt->rt6i_dev->ifindex);				
+#endif /*  CONFIG_MV_ETH_NFP_FIB_LEARN  */
+	
 	rt6_release(rt);
 }
 
@@ -1429,6 +1503,13 @@
 				  rt);
 			return -1;
 		}
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+		if (rt->nfp) {
+			if (nfp_hook_fib_rule_age(AF_INET6,(u8 *)(&rt->rt6i_src.addr), (u8 *)(&rt->rt6i_dst.addr),
+					rt->rt6i_iifindex, rt->rt6i_dev->ifindex))
+				rt->u.dst.lastuse = now;
+		}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
 		gc_args.more++;
 	}
 
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 29d643b..2a9ba03 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -190,6 +190,14 @@
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config IP6_NF_TARGET_NFP
+	tristate "NFP target support for IPv6"
+	depends on NF_CONNTRACK_IPV6
+	help
+	  This target allows to process selected connections in NFP.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 # security table for MAC policy
 config IP6_NF_SECURITY
        tristate "Security table"
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index aafbba3..75a186c 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
+obj-$(CONFIG_IP6_NF_TARGET_NFP) += ip6t_NFP.o
 
 # targets
 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
old mode 100644
new mode 100755
index d6fe764..416cbe4
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -744,6 +744,14 @@
 
 	dst_hold(&rt->u.dst);
 	if (nrt) {
+#if defined(CONFIG_MV_ETH_NFP_FIB_LEARN)
+			if ((rt->rt6i_flags & RTF_CACHE)) {
+				ipv6_addr_copy(&rt->rt6i_src.addr, &fl->fl6_src);
+				rt->rt6i_src.plen = 128;
+				rt->rt6i_iifindex = fl->iif;
+			}
+#endif /* CONFIG_MV_ETH_NFP_FIB_LEARN */
+		
 		err = ip6_ins_rt(nrt);
 		if (!err)
 			goto out2;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 634d14a..df89057 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -858,6 +858,27 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_LAYER7
+	tristate '"layer7" match support'
+	depends on NETFILTER_XTABLES
+	depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK)
+       depends on NF_CT_ACCT
+	help
+	  Say Y if you want to be able to classify connections (and their
+	  packets) based on regular expression matching of their application
+	  layer data.   This is one way to classify applications such as
+	  peer-to-peer filesharing systems that do not always use the same
+	  port.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config NETFILTER_XT_MATCH_LAYER7_DEBUG
+        bool 'Layer 7 debugging output'
+        depends on NETFILTER_XT_MATCH_LAYER7
+        help
+          Say Y to get lots of debugging output.
+
+
 config NETFILTER_XT_MATCH_STATISTIC
 	tristate '"statistic" match support'
 	depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 49f62ee..3bbe4af 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -89,6 +89,7 @@
 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_LAYER7) += xt_layer7.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
old mode 100644
new mode 100755
index 1374179..7be465a
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -45,6 +45,20 @@
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_core.h>
 
+#include <linux/netfilter/ipt_NFP.h>
+
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+extern void nfp_hook_ct_del(int family, u8 *src_l3, u8 *dst_l3, u16 sport, u16 dport, u8 proto);
+extern int  nfp_hook_ct_age(int family, u8 *src_l3, u8 *dst_l3, u16 sport, u16 dport, u8 proto);
+extern void nfp_ct_sync(int family);
+#ifdef CONFIG_MV_ETH_NFP_NAT
+extern void move_nat_to_nfp(const struct nf_conntrack_tuple *tuple,
+							const struct nf_conntrack_tuple *target,
+							enum nf_nat_manip_type maniptype);
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+extern int move_fwd_to_nfp(const struct nf_conntrack_tuple *tuple, int mode);
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
+
 #define NF_CONNTRACK_VERSION	"0.5.0"
 
 int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
@@ -201,6 +215,13 @@
 	 * too. */
 	nf_ct_remove_expectations(ct);
 
+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
+	if(ct->layer7.app_proto)
+		kfree(ct->layer7.app_proto);
+	if(ct->layer7.app_data)
+		kfree(ct->layer7.app_data);
+#endif
+
 	/* We overload first tuple to link into unconfirmed list. */
 	if (!nf_ct_is_confirmed(ct)) {
 		BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
@@ -272,6 +293,82 @@
 {
 	struct nf_conn *ct = (void *)ul_conntrack;
 
+#if defined (CONFIG_MV_ETH_NFP_CT_LEARN)
+	struct nf_conntrack_tuple *t0 = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+	struct nf_conntrack_tuple *t1 = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+	int confirmed_org = 0, confirmed_reply = 0;
+
+	if (t0 && t0->nfp) {
+		if (t0->src.l3num == AF_INET)
+			confirmed_org = nfp_hook_ct_age(t0->src.l3num, (u8 *)&(t0->src.u3.ip),
+					(u8 *)&(t0->dst.u3.ip),
+					ntohs(t0->src.u.all),
+					ntohs(t0->dst.u.all),
+					t0->dst.protonum);
+		else
+			confirmed_org = nfp_hook_ct_age(t0->src.l3num, (u8 *)&(t0->src.u3.ip6),
+					(u8 *)&(t0->dst.u3.ip6),
+					ntohs(t0->src.u.all),
+					ntohs(t0->dst.u.all),
+					t0->dst.protonum);
+	}
+
+	if (t1 && t1->nfp) {
+		if (t1->src.l3num == AF_INET)
+			confirmed_reply = nfp_hook_ct_age(t1->src.l3num, (u8 *)&(t1->src.u3.ip),
+					(u8 *)&(t1->dst.u3.ip),
+					ntohs(t1->src.u.all),
+					ntohs(t1->dst.u.all),
+					t1->dst.protonum);
+		else
+			confirmed_reply = nfp_hook_ct_age(t1->src.l3num, (u8 *)&(t1->src.u3.ip6),
+					(u8 *)&(t1->dst.u3.ip6),
+					ntohs(t1->src.u.all),
+					ntohs(t1->dst.u.all),
+					t1->dst.protonum);
+	}
+
+	if (confirmed_org || confirmed_reply) {
+		ct->timeout.expires = jiffies + (20*HZ);
+		add_timer(&ct->timeout);
+		return;
+	}
+
+	if (t0 && t0->nfp) {
+		t0->nfp = false;
+
+		if (t0->src.l3num == AF_INET)
+			nfp_hook_ct_del(t0->src.l3num, (u8 *)&(t0->src.u3.ip),
+					(u8 *)&(t0->dst.u3.ip),
+					ntohs(t0->src.u.all),
+					ntohs(t0->dst.u.all),
+					t0->dst.protonum);
+		else
+			nfp_hook_ct_del(t0->src.l3num, (u8 *)&(t0->src.u3.ip6),
+					(u8 *)&(t0->dst.u3.ip6),
+					ntohs(t0->src.u.all),
+					ntohs(t0->dst.u.all),
+					t0->dst.protonum);
+	}
+
+	if (t1 && t1->nfp) {
+		t1->nfp = false;
+
+		if (t1->src.l3num == AF_INET)
+			nfp_hook_ct_del(t1->src.l3num, (u8 *)&(t1->src.u3.ip),
+					(u8 *)&(t1->dst.u3.ip),
+					ntohs(t1->src.u.all),
+					ntohs(t1->dst.u.all),
+					t1->dst.protonum);
+		else
+			nfp_hook_ct_del(t1->src.l3num, (u8 *)&(t1->src.u3.ip6),
+					(u8 *)&(t1->dst.u3.ip6),
+					ntohs(t1->src.u.all),
+					ntohs(t1->dst.u.all),
+					t1->dst.protonum);
+	}
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
+
 	if (!test_bit(IPS_DYING_BIT, &ct->status) &&
 	    unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) {
 		/* destroy event was not delivered */
@@ -591,6 +688,18 @@
 	ct->ct_net = net;
 #endif
 
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+	ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.nfp = false;
+	ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.ifindex = -1;
+	ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.nfpCapable = false;
+	ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.info = NULL;
+
+	ct->tuplehash[IP_CT_DIR_REPLY].tuple.nfp = false;
+	ct->tuplehash[IP_CT_DIR_REPLY].tuple.ifindex = -1;
+	ct->tuplehash[IP_CT_DIR_REPLY].tuple.nfpCapable = false;
+	ct->tuplehash[IP_CT_DIR_REPLY].tuple.info = NULL;
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
+
 	/*
 	 * changes to lookup keys must be done before setting refcnt to 1
 	 */
@@ -604,6 +713,14 @@
 {
 	struct net *net = nf_ct_net(ct);
 
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.info)
+		kfree(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.info);
+
+	if (ct->tuplehash[IP_CT_DIR_REPLY].tuple.info)
+		kfree(ct->tuplehash[IP_CT_DIR_REPLY].tuple.info);
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
+
 	nf_ct_ext_destroy(ct);
 	atomic_dec(&net->ct.count);
 	nf_ct_ext_free(ct);
@@ -1239,6 +1356,84 @@
 module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint,
 		  &nf_conntrack_htable_size, 0600);
 
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+void nfp_ct_sync(int family)
+{
+	struct nf_conntrack_tuple_hash *h;
+	struct nf_conn *ct;
+	struct nf_conntrack_tuple *tuple;
+	struct nf_conntrack_tuple target_tuple;
+	struct hlist_nulls_node *n;
+	unsigned int bucket = 0;
+	enum ip_conntrack_dir dir;
+	struct net *net = &init_net;
+	unsigned long status;
+
+	spin_lock_bh(&nf_conntrack_lock);
+	/* Go over all tuples in the Linux database */
+	for (; bucket < net->ct.htable_size; bucket++) {
+		hlist_nulls_for_each_entry(h, n, &net->ct.hash[bucket], hnnode) {
+			dir = NF_CT_DIRECTION(h);
+			tuple = &h[IP_CT_DIR_ORIGINAL].tuple;
+
+			ct = nf_ct_tuplehash_to_ctrack(h);
+			if (tuple->src.l3num != family)
+				continue;
+
+			/* We want to add only NFP capable rules*/
+			if (!tuple->nfpCapable)
+				continue;
+
+			if ((tuple->info->mode != IPT_NFP_DROP) && (tuple->info->mode != IPT_NFP_FWD))
+				continue;
+
+			tuple->nfp = true;
+
+			if (tuple->info->mode == IPT_NFP_DROP) {
+				move_fwd_to_nfp(tuple, 0);
+				continue;
+			}
+
+			status = ct->status;
+
+#ifdef CONFIG_MV_ETH_NFP_NAT
+			if (status & IPS_NAT_MASK) {
+				/* NFP NAT is supported only in IPv4 */
+				if (tuple->src.l3num == AF_INET) {
+					/* status says if the original direction requires SNAT or DNAT (or both) */
+					/* if we currently work on the reply direction, we need to "reverse" the NAT status, */
+					/* e.g. if original direction was SNAT, reply should be DNAT. */
+					if (dir != IP_CT_DIR_ORIGINAL)
+						status ^= IPS_NAT_MASK;
+
+					nf_ct_invert_tuplepr(&target_tuple, &ct->tuplehash[!dir].tuple);
+
+					if ((status & IPS_NAT_MASK) == IPS_DST_NAT) {
+						move_nat_to_nfp(tuple, &target_tuple, IP_NAT_MANIP_DST);
+					} else if ((status & IPS_NAT_MASK) == IPS_SRC_NAT) {
+						move_nat_to_nfp(tuple, &target_tuple, IP_NAT_MANIP_SRC);
+					} else {
+						move_nat_to_nfp(tuple, &target_tuple, IP_NAT_MANIP_DST);
+						move_nat_to_nfp(tuple, &target_tuple, IP_NAT_MANIP_SRC);
+					}
+
+					continue;
+				} else {
+					/* NFP does not support NAT for IPv6, so nothing to do with this tuple */
+					tuple->nfp = false;
+					continue;
+				}
+			}
+#endif /* CONFIG_MV_ETH_NFP_NAT */
+			/* If we got till here, it must be IPT_NFP_FWD */
+			move_fwd_to_nfp(tuple, 1);
+		}
+	}
+
+	spin_unlock_bh(&nf_conntrack_lock);
+}
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
+
 static int nf_conntrack_init_init_net(void)
 {
 	int max_factor = 8;
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
old mode 100644
new mode 100755
index ba2b769..3db67df
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -824,6 +824,9 @@
 {
 	struct net *net = nf_ct_net(ct);
 	struct nf_conntrack_tuple *tuple;
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+	struct nf_conntrack_tuple *tupleInverseDir;
+#endif
 	enum tcp_conntrack new_state, old_state;
 	enum ip_conntrack_dir dir;
 	const struct tcphdr *th;
@@ -840,7 +843,9 @@
 	index = get_conntrack_index(th);
 	new_state = tcp_conntracks[dir][index][old_state];
 	tuple = &ct->tuplehash[dir].tuple;
-
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+	tupleInverseDir	= &ct->tuplehash[!dir].tuple;
+#endif
 	switch (new_state) {
 	case TCP_CONNTRACK_SYN_SENT:
 		if (old_state < TCP_CONNTRACK_TIME_WAIT)
@@ -961,6 +966,15 @@
 		break;
 	}
 
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+	/*
+	 * When connection is handled by NFP, we have to relax TCP tracking
+	 * rules as not all packets goes through Linux conntrack.
+	 */
+	if ((tuple->nfp) || (tupleInverseDir->nfp))
+		goto in_window;
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
+
 	if (!tcp_in_window(ct, &ct->proto.tcp, dir, index,
 			   skb, dataoff, th, pf)) {
 		spin_unlock_bh(&ct->lock);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 1a84bf6..654d994 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -171,6 +171,25 @@
 		goto release;
 #endif
 
+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
+	if(ct->layer7.app_proto &&
+           seq_printf(s, "l7proto=%s ", ct->layer7.app_proto))
+		return -ENOSPC;
+#endif
+
+#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
+	if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.nfp) && (ct->tuplehash[IP_CT_DIR_REPLY].tuple.nfp)) {
+		if (seq_printf(s, "[NFP (both)] "))
+			goto release;
+	} else if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.nfp) {
+		if (seq_printf(s, "[NFP (orig)] "))
+			goto release;
+	} else if (ct->tuplehash[IP_CT_DIR_REPLY].tuple.nfp) {
+		if (seq_printf(s, "[NFP (reply)] "))
+			goto release;
+	}
+#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */
+
 	if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
 		goto release;
 
diff --git a/net/netfilter/regexp/regexp.c b/net/netfilter/regexp/regexp.c
new file mode 100755
index 0000000..9006988
--- /dev/null
+++ b/net/netfilter/regexp/regexp.c
@@ -0,0 +1,1197 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ * @(#)regexp.c	1.3 of 18 April 87
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions.  Serious changes in
+ * regular-expression syntax might require a total rethink.
+ *
+ * This code was modified by Ethan Sommer to work within the kernel
+ * (it now uses kmalloc etc..)
+ *
+ * Modified slightly by Matthew Strait to use more modern C.
+ */
+
+#include "regexp.h"
+#include "regmagic.h"
+
+/* added by ethan and matt.  Lets it work in both kernel and user space.
+(So iptables can use it, for instance.)  Yea, it goes both ways... */
+#if __KERNEL__
+  #define malloc(foo) kmalloc(foo,GFP_ATOMIC)
+#else
+  #define printk(format,args...) printf(format,##args)
+#endif
+
+void regerror(char * s)
+{
+        printk("<3>Regexp: %s\n", s);
+        /* NOTREACHED */
+}
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases.  They are:
+ *
+ * regstart	char that must begin a match; '\0' if none obvious
+ * reganch	is the match anchored (at beginning-of-line only)?
+ * regmust	string (pointer into program) that match must include, or NULL
+ * regmlen	length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot.  Regmust permits fast rejection
+ * of lines that cannot possibly match.  The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup).  Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program".  This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology).  Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives.  (Here we
+ * have one of the subtle syntax dependencies:  an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.)  The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM.  In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure:  the tail of the branch connects
+ * to the thing following the set of BRANCHes.)  The opcodes are:
+ */
+
+/* definition	number	opnd?	meaning */
+#define	END	0	/* no	End of program. */
+#define	BOL	1	/* no	Match "" at beginning of line. */
+#define	EOL	2	/* no	Match "" at end of line. */
+#define	ANY	3	/* no	Match any one character. */
+#define	ANYOF	4	/* str	Match any character in this string. */
+#define	ANYBUT	5	/* str	Match any character not in this string. */
+#define	BRANCH	6	/* node	Match this alternative, or the next... */
+#define	BACK	7	/* no	Match "", "next" ptr points backward. */
+#define	EXACTLY	8	/* str	Match this string. */
+#define	NOTHING	9	/* no	Match empty string. */
+#define	STAR	10	/* node	Match this (simple) thing 0 or more times. */
+#define	PLUS	11	/* node	Match this (simple) thing 1 or more times. */
+#define	OPEN	20	/* no	Mark this point in input as start of #n. */
+			/*	OPEN+1 is number 1, etc. */
+#define	CLOSE	30	/* no	Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH	The set of branches constituting a single choice are hooked
+ *		together with their "next" pointers, since precedence prevents
+ *		anything being concatenated to any individual branch.  The
+ *		"next" pointer of the last BRANCH in a choice points to the
+ *		thing following the whole choice.  This is also where the
+ *		final "next" pointer of each individual branch points; each
+ *		branch starts with the operand node of a BRANCH node.
+ *
+ * BACK		Normal "next" pointers all implicitly point forward; BACK
+ *		exists to make loop structures possible.
+ *
+ * STAR,PLUS	'?', and complex '*' and '+', are implemented as circular
+ *		BRANCH structures using BACK.  Simple cases (one character
+ *		per match) are implemented with STAR and PLUS for speed
+ *		and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE	...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first.  The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node.  (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define	OP(p)	(*(p))
+#define	NEXT(p)	(((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define	OPERAND(p)	((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+#define	FAIL(m)	{ regerror(m); return(NULL); }
+#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?')
+#define	META	"^$.[()|?+*\\"
+
+/*
+ * Flags to be passed up and down.
+ */
+#define	HASWIDTH	01	/* Known never to match null string. */
+#define	SIMPLE		02	/* Simple enough to be STAR/PLUS operand. */
+#define	SPSTART		04	/* Starts with * or +. */
+#define	WORST		0	/* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+struct match_globals {
+char *reginput;		/* String-input pointer. */
+char *regbol;		/* Beginning of input, for ^ check. */
+char **regstartp;	/* Pointer to startp array. */
+char **regendp;		/* Ditto for endp. */
+char *regparse;		/* Input-scan pointer. */
+int regnpar;		/* () count. */
+char regdummy;
+char *regcode;		/* Code-emit pointer; &regdummy = don't. */
+long regsize;		/* Code size. */
+};
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define	STATIC	static
+#endif
+STATIC char *reg(struct match_globals *g, int paren,int *flagp);
+STATIC char *regbranch(struct match_globals *g, int *flagp);
+STATIC char *regpiece(struct match_globals *g, int *flagp);
+STATIC char *regatom(struct match_globals *g, int *flagp);
+STATIC char *regnode(struct match_globals *g, char op);
+STATIC char *regnext(struct match_globals *g, char *p);
+STATIC void regc(struct match_globals *g, char b);
+STATIC void reginsert(struct match_globals *g, char op, char *opnd);
+STATIC void regtail(struct match_globals *g, char *p, char *val);
+STATIC void regoptail(struct match_globals *g, char *p, char *val);
+
+
+__kernel_size_t my_strcspn(const char *s1,const char *s2)
+{
+        char *scan1;
+        char *scan2;
+        int count;
+
+        count = 0;
+        for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) {
+                for (scan2 = (char *)s2; *scan2 != '\0';)       /* ++ moved down. */
+                        if (*scan1 == *scan2++)
+                                return(count);
+                count++;
+        }
+        return(count);
+}
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code.  So we cheat:  we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it.  (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp(char *exp,int *patternsize)
+{
+	register regexp *r;
+	register char *scan;
+	register char *longest;
+	register int len;
+	int flags;
+	struct match_globals g;
+	
+	/* commented out by ethan
+	   extern char *malloc();
+	*/
+
+	if (exp == NULL)
+		FAIL("NULL argument");
+
+	/* First pass: determine size, legality. */
+	g.regparse = exp;
+	g.regnpar = 1;
+	g.regsize = 0L;
+	g.regcode = &g.regdummy;
+	regc(&g, MAGIC);
+	if (reg(&g, 0, &flags) == NULL)
+		return(NULL);
+
+	/* Small enough for pointer-storage convention? */
+	if (g.regsize >= 32767L)		/* Probably could be 65535L. */
+		FAIL("regexp too big");
+
+	/* Allocate space. */
+	*patternsize=sizeof(regexp) + (unsigned)g.regsize;
+	r = (regexp *)malloc(sizeof(regexp) + (unsigned)g.regsize);
+	if (r == NULL)
+		FAIL("out of space");
+
+	/* Second pass: emit code. */
+	g.regparse = exp;
+	g.regnpar = 1;
+	g.regcode = r->program;
+	regc(&g, MAGIC);
+	if (reg(&g, 0, &flags) == NULL)
+		return(NULL);
+
+	/* Dig out information for optimizations. */
+	r->regstart = '\0';	/* Worst-case defaults. */
+	r->reganch = 0;
+	r->regmust = NULL;
+	r->regmlen = 0;
+	scan = r->program+1;			/* First BRANCH. */
+	if (OP(regnext(&g, scan)) == END) {		/* Only one top-level choice. */
+		scan = OPERAND(scan);
+
+		/* Starting-point info. */
+		if (OP(scan) == EXACTLY)
+			r->regstart = *OPERAND(scan);
+		else if (OP(scan) == BOL)
+			r->reganch++;
+
+		/*
+		 * If there's something expensive in the r.e., find the
+		 * longest literal string that must appear and make it the
+		 * regmust.  Resolve ties in favor of later strings, since
+		 * the regstart check works with the beginning of the r.e.
+		 * and avoiding duplication strengthens checking.  Not a
+		 * strong reason, but sufficient in the absence of others.
+		 */
+		if (flags&SPSTART) {
+			longest = NULL;
+			len = 0;
+			for (; scan != NULL; scan = regnext(&g, scan))
+				if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+					longest = OPERAND(scan);
+					len = strlen(OPERAND(scan));
+				}
+			r->regmust = longest;
+			r->regmlen = len;
+		}
+	}
+
+	return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *
+reg(struct match_globals *g, int paren, int *flagp /* Parenthesized? */ )
+{
+	register char *ret;
+	register char *br;
+	register char *ender;
+	register int parno = 0; /* 0 makes gcc happy */
+	int flags;
+
+	*flagp = HASWIDTH;	/* Tentatively. */
+
+	/* Make an OPEN node, if parenthesized. */
+	if (paren) {
+		if (g->regnpar >= NSUBEXP)
+			FAIL("too many ()");
+		parno = g->regnpar;
+		g->regnpar++;
+		ret = regnode(g, OPEN+parno);
+	} else
+		ret = NULL;
+
+	/* Pick up the branches, linking them together. */
+	br = regbranch(g, &flags);
+	if (br == NULL)
+		return(NULL);
+	if (ret != NULL)
+		regtail(g, ret, br);	/* OPEN -> first. */
+	else
+		ret = br;
+	if (!(flags&HASWIDTH))
+		*flagp &= ~HASWIDTH;
+	*flagp |= flags&SPSTART;
+	while (*g->regparse == '|') {
+		g->regparse++;
+		br = regbranch(g, &flags);
+		if (br == NULL)
+			return(NULL);
+		regtail(g, ret, br);	/* BRANCH -> BRANCH. */
+		if (!(flags&HASWIDTH))
+			*flagp &= ~HASWIDTH;
+		*flagp |= flags&SPSTART;
+	}
+
+	/* Make a closing node, and hook it on the end. */
+	ender = regnode(g, (paren) ? CLOSE+parno : END);	
+	regtail(g, ret, ender);
+
+	/* Hook the tails of the branches to the closing node. */
+	for (br = ret; br != NULL; br = regnext(g, br))
+		regoptail(g, br, ender);
+
+	/* Check for proper termination. */
+	if (paren && *g->regparse++ != ')') {
+		FAIL("unmatched ()");
+	} else if (!paren && *g->regparse != '\0') {
+		if (*g->regparse == ')') {
+			FAIL("unmatched ()");
+		} else
+			FAIL("junk on end");	/* "Can't happen". */
+		/* NOTREACHED */
+	}
+
+	return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *
+regbranch(struct match_globals *g, int *flagp)
+{
+	register char *ret;
+	register char *chain;
+	register char *latest;
+	int flags;
+
+	*flagp = WORST;		/* Tentatively. */
+
+	ret = regnode(g, BRANCH);
+	chain = NULL;
+	while (*g->regparse != '\0' && *g->regparse != '|' && *g->regparse != ')') {
+		latest = regpiece(g, &flags);
+		if (latest == NULL)
+			return(NULL);
+		*flagp |= flags&HASWIDTH;
+		if (chain == NULL)	/* First piece. */
+			*flagp |= flags&SPSTART;
+		else
+			regtail(g, chain, latest);
+		chain = latest;
+	}
+	if (chain == NULL)	/* Loop ran zero times. */
+		(void) regnode(g, NOTHING);
+
+	return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized:  they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *
+regpiece(struct match_globals *g, int *flagp)
+{
+	register char *ret;
+	register char op;
+	register char *next;
+	int flags;
+
+	ret = regatom(g, &flags);
+	if (ret == NULL)
+		return(NULL);
+
+	op = *g->regparse;
+	if (!ISMULT(op)) {
+		*flagp = flags;
+		return(ret);
+	}
+
+	if (!(flags&HASWIDTH) && op != '?')
+		FAIL("*+ operand could be empty");
+	*flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+	if (op == '*' && (flags&SIMPLE))
+		reginsert(g, STAR, ret);
+	else if (op == '*') {
+		/* Emit x* as (x&|), where & means "self". */
+		reginsert(g, BRANCH, ret);			/* Either x */
+		regoptail(g, ret, regnode(g, BACK));		/* and loop */
+		regoptail(g, ret, ret);			/* back */
+		regtail(g, ret, regnode(g, BRANCH));		/* or */
+		regtail(g, ret, regnode(g, NOTHING));		/* null. */
+	} else if (op == '+' && (flags&SIMPLE))
+		reginsert(g, PLUS, ret);
+	else if (op == '+') {
+		/* Emit x+ as x(&|), where & means "self". */
+		next = regnode(g, BRANCH);			/* Either */
+		regtail(g, ret, next);
+		regtail(g, regnode(g, BACK), ret);		/* loop back */
+		regtail(g, next, regnode(g, BRANCH));		/* or */
+		regtail(g, ret, regnode(g, NOTHING));		/* null. */
+	} else if (op == '?') {
+		/* Emit x? as (x|) */
+		reginsert(g, BRANCH, ret);			/* Either x */
+		regtail(g, ret, regnode(g, BRANCH));		/* or */
+		next = regnode(g, NOTHING);		/* null. */
+		regtail(g, ret, next);
+		regoptail(g, ret, next);
+	}
+	g->regparse++;
+	if (ISMULT(*g->regparse))
+		FAIL("nested *?+");
+
+	return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization:  gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run.  Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *
+regatom(struct match_globals *g, int *flagp)
+{
+	register char *ret;
+	int flags;
+
+	*flagp = WORST;		/* Tentatively. */
+
+	switch (*g->regparse++) {
+	case '^':
+		ret = regnode(g, BOL);
+		break;
+	case '$':
+		ret = regnode(g, EOL);
+		break;
+	case '.':
+		ret = regnode(g, ANY);
+		*flagp |= HASWIDTH|SIMPLE;
+		break;
+	case '[': {
+			register int class;
+			register int classend;
+
+			if (*g->regparse == '^') {	/* Complement of range. */
+				ret = regnode(g, ANYBUT);
+				g->regparse++;
+			} else
+				ret = regnode(g, ANYOF);
+			if (*g->regparse == ']' || *g->regparse == '-')
+				regc(g, *g->regparse++);
+			while (*g->regparse != '\0' && *g->regparse != ']') {
+				if (*g->regparse == '-') {
+					g->regparse++;
+					if (*g->regparse == ']' || *g->regparse == '\0')
+						regc(g, '-');
+					else {
+						class = UCHARAT(g->regparse-2)+1;
+						classend = UCHARAT(g->regparse);
+						if (class > classend+1)
+							FAIL("invalid [] range");
+						for (; class <= classend; class++)
+							regc(g, class);
+						g->regparse++;
+					}
+				} else
+					regc(g, *g->regparse++);
+			}
+			regc(g, '\0');
+			if (*g->regparse != ']')
+				FAIL("unmatched []");
+			g->regparse++;
+			*flagp |= HASWIDTH|SIMPLE;
+		}
+		break;
+	case '(':
+		ret = reg(g, 1, &flags);
+		if (ret == NULL)
+			return(NULL);
+		*flagp |= flags&(HASWIDTH|SPSTART);
+		break;
+	case '\0':
+	case '|':
+	case ')':
+		FAIL("internal urp");	/* Supposed to be caught earlier. */
+		break;
+	case '?':
+	case '+':
+	case '*':
+		FAIL("?+* follows nothing");
+		break;
+	case '\\':
+		if (*g->regparse == '\0')
+			FAIL("trailing \\");
+		ret = regnode(g, EXACTLY);
+		regc(g, *g->regparse++);
+		regc(g, '\0');
+		*flagp |= HASWIDTH|SIMPLE;
+		break;
+	default: {
+			register int len;
+			register char ender;
+
+			g->regparse--;
+			len = my_strcspn((const char *)g->regparse, (const char *)META);
+			if (len <= 0)
+				FAIL("internal disaster");
+			ender = *(g->regparse+len);
+			if (len > 1 && ISMULT(ender))
+				len--;		/* Back off clear of ?+* operand. */
+			*flagp |= HASWIDTH;
+			if (len == 1)
+				*flagp |= SIMPLE;
+			ret = regnode(g, EXACTLY);
+			while (len > 0) {
+				regc(g, *g->regparse++);
+				len--;
+			}
+			regc(g, '\0');
+		}
+		break;
+	}
+
+	return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char *			/* Location. */
+regnode(struct match_globals *g, char op)
+{
+	register char *ret;
+	register char *ptr;
+
+	ret = g->regcode;
+	if (ret == &g->regdummy) {
+		g->regsize += 3;
+		return(ret);
+	}
+
+	ptr = ret;
+	*ptr++ = op;
+	*ptr++ = '\0';		/* Null "next" pointer. */
+	*ptr++ = '\0';
+	g->regcode = ptr;
+
+	return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc(struct match_globals *g, char b)
+{
+	if (g->regcode != &g->regdummy)
+		*g->regcode++ = b;
+	else
+		g->regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(struct match_globals *g, char op, char* opnd)
+{
+	register char *src;
+	register char *dst;
+	register char *place;
+
+	if (g->regcode == &g->regdummy) {
+		g->regsize += 3;
+		return;
+	}
+
+	src = g->regcode;
+	g->regcode += 3;
+	dst = g->regcode;
+	while (src > opnd)
+		*--dst = *--src;
+
+	place = opnd;		/* Op node, where operand used to be. */
+	*place++ = op;
+	*place++ = '\0';
+	*place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(struct match_globals *g, char *p, char *val)
+{
+	register char *scan;
+	register char *temp;
+	register int offset;
+
+	if (p == &g->regdummy)
+		return;
+
+	/* Find last node. */
+	scan = p;
+	for (;;) {
+		temp = regnext(g, scan);
+		if (temp == NULL)
+			break;
+		scan = temp;
+	}
+
+	if (OP(scan) == BACK)
+		offset = scan - val;
+	else
+		offset = val - scan;
+	*(scan+1) = (offset>>8)&0377;
+	*(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void
+regoptail(struct match_globals *g, char *p, char *val)
+{
+	/* "Operandless" and "op != BRANCH" are synonymous in practice. */
+	if (p == NULL || p == &g->regdummy || OP(p) != BRANCH)
+		return;
+	regtail(g, OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+
+/*
+ * Forwards.
+ */
+STATIC int regtry(struct match_globals *g, regexp *prog, char *string);
+STATIC int regmatch(struct match_globals *g, char *prog);
+STATIC int regrepeat(struct match_globals *g, char *p);
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop(char *op);
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(regexp *prog, char *string)
+{
+	register char *s;
+	struct match_globals g;
+
+	/* Be paranoid... */
+	if (prog == NULL || string == NULL) {
+		printk("<3>Regexp: NULL parameter\n");
+		return(0);
+	}
+
+	/* Check validity of program. */
+	if (UCHARAT(prog->program) != MAGIC) {
+		printk("<3>Regexp: corrupted program\n");
+		return(0);
+	}
+
+	/* If there is a "must appear" string, look for it. */
+	if (prog->regmust != NULL) {
+		s = string;
+		while ((s = strchr(s, prog->regmust[0])) != NULL) {
+			if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+				break;	/* Found it. */
+			s++;
+		}
+		if (s == NULL)	/* Not present. */
+			return(0);
+	}
+
+	/* Mark beginning of line for ^ . */
+	g.regbol = string;
+
+	/* Simplest case:  anchored match need be tried only once. */
+	if (prog->reganch)
+		return(regtry(&g, prog, string));
+
+	/* Messy cases:  unanchored match. */
+	s = string;
+	if (prog->regstart != '\0')
+		/* We know what char it must start with. */
+		while ((s = strchr(s, prog->regstart)) != NULL) {
+			if (regtry(&g, prog, s))
+				return(1);
+			s++;
+		}
+	else
+		/* We don't -- general case. */
+		do {
+			if (regtry(&g, prog, s))
+				return(1);
+		} while (*s++ != '\0');
+
+	/* Failure. */
+	return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+static int			/* 0 failure, 1 success */
+regtry(struct match_globals *g, regexp *prog, char *string)
+{
+	register int i;
+	register char **sp;
+	register char **ep;
+
+	g->reginput = string;
+	g->regstartp = prog->startp;
+	g->regendp = prog->endp;
+
+	sp = prog->startp;
+	ep = prog->endp;
+	for (i = NSUBEXP; i > 0; i--) {
+		*sp++ = NULL;
+		*ep++ = NULL;
+	}
+	if (regmatch(g, prog->program + 1)) {
+		prog->startp[0] = string;
+		prog->endp[0] = g->reginput;
+		return(1);
+	} else
+		return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple:  check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly.  In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int			/* 0 failure, 1 success */
+regmatch(struct match_globals *g, char *prog)
+{
+	register char *scan = prog; /* Current node. */
+	char *next;		    /* Next node. */
+
+#ifdef DEBUG
+	if (scan != NULL && regnarrate)
+		fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+	while (scan != NULL) {
+#ifdef DEBUG
+		if (regnarrate)
+			fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+		next = regnext(g, scan);
+
+		switch (OP(scan)) {
+		case BOL:
+			if (g->reginput != g->regbol)
+				return(0);
+			break;
+		case EOL:
+			if (*g->reginput != '\0')
+				return(0);
+			break;
+		case ANY:
+			if (*g->reginput == '\0')
+				return(0);
+			g->reginput++;
+			break;
+		case EXACTLY: {
+				register int len;
+				register char *opnd;
+
+				opnd = OPERAND(scan);
+				/* Inline the first character, for speed. */
+				if (*opnd != *g->reginput)
+					return(0);
+				len = strlen(opnd);
+				if (len > 1 && strncmp(opnd, g->reginput, len) != 0)
+					return(0);
+				g->reginput += len;
+			}
+			break;
+		case ANYOF:
+			if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) == NULL)
+				return(0);
+			g->reginput++;
+			break;
+		case ANYBUT:
+			if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) != NULL)
+				return(0);
+			g->reginput++;
+			break;
+		case NOTHING:
+		case BACK:
+			break;
+		case OPEN+1:
+		case OPEN+2:
+		case OPEN+3:
+		case OPEN+4:
+		case OPEN+5:
+		case OPEN+6:
+		case OPEN+7:
+		case OPEN+8:
+		case OPEN+9: {
+				register int no;
+				register char *save;
+
+				no = OP(scan) - OPEN;
+				save = g->reginput;
+
+				if (regmatch(g, next)) {
+					/*
+					 * Don't set startp if some later
+					 * invocation of the same parentheses
+					 * already has.
+					 */
+					if (g->regstartp[no] == NULL)
+						g->regstartp[no] = save;
+					return(1);
+				} else
+					return(0);
+			}
+			break;
+		case CLOSE+1:
+		case CLOSE+2:
+		case CLOSE+3:
+		case CLOSE+4:
+		case CLOSE+5:
+		case CLOSE+6:
+		case CLOSE+7:
+		case CLOSE+8:
+		case CLOSE+9:
+			{
+				register int no;
+				register char *save;
+
+				no = OP(scan) - CLOSE;
+				save = g->reginput;
+
+				if (regmatch(g, next)) {
+					/*
+					 * Don't set endp if some later
+					 * invocation of the same parentheses
+					 * already has.
+					 */
+					if (g->regendp[no] == NULL)
+						g->regendp[no] = save;
+					return(1);
+				} else
+					return(0);
+			}
+			break;
+		case BRANCH: {
+				register char *save;
+
+				if (OP(next) != BRANCH)		/* No choice. */
+					next = OPERAND(scan);	/* Avoid recursion. */
+				else {
+					do {
+						save = g->reginput;
+						if (regmatch(g, OPERAND(scan)))
+							return(1);
+						g->reginput = save;
+						scan = regnext(g, scan);
+					} while (scan != NULL && OP(scan) == BRANCH);
+					return(0);
+					/* NOTREACHED */
+				}
+			}
+			break;
+		case STAR:
+		case PLUS: {
+				register char nextch;
+				register int no;
+				register char *save;
+				register int min;
+
+				/*
+				 * Lookahead to avoid useless match attempts
+				 * when we know what character comes next.
+				 */
+				nextch = '\0';
+				if (OP(next) == EXACTLY)
+					nextch = *OPERAND(next);
+				min = (OP(scan) == STAR) ? 0 : 1;
+				save = g->reginput;
+				no = regrepeat(g, OPERAND(scan));
+				while (no >= min) {
+					/* If it could work, try it. */
+					if (nextch == '\0' || *g->reginput == nextch)
+						if (regmatch(g, next))
+							return(1);
+					/* Couldn't or didn't -- back up. */
+					no--;
+					g->reginput = save + no;
+				}
+				return(0);
+			}
+			break;
+		case END:
+			return(1);	/* Success! */
+			break;
+		default:
+			printk("<3>Regexp: memory corruption\n");
+			return(0);
+			break;
+		}
+
+		scan = next;
+	}
+
+	/*
+	 * We get here only if there's trouble -- normally "case END" is
+	 * the terminating point.
+	 */
+	printk("<3>Regexp: corrupted pointers\n");
+	return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat(struct match_globals *g, char *p)
+{
+	register int count = 0;
+	register char *scan;
+	register char *opnd;
+
+	scan = g->reginput;
+	opnd = OPERAND(p);
+	switch (OP(p)) {
+	case ANY:
+		count = strlen(scan);
+		scan += count;
+		break;
+	case EXACTLY:
+		while (*opnd == *scan) {
+			count++;
+			scan++;
+		}
+		break;
+	case ANYOF:
+		while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+			count++;
+			scan++;
+		}
+		break;
+	case ANYBUT:
+		while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+			count++;
+			scan++;
+		}
+		break;
+	default:		/* Oh dear.  Called inappropriately. */
+		printk("<3>Regexp: internal foulup\n");
+		count = 0;	/* Best compromise. */
+		break;
+	}
+	g->reginput = scan;
+
+	return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char*
+regnext(struct match_globals *g, char *p)
+{
+	register int offset;
+
+	if (p == &g->regdummy)
+		return(NULL);
+
+	offset = NEXT(p);
+	if (offset == 0)
+		return(NULL);
+
+	if (OP(p) == BACK)
+		return(p-offset);
+	else
+		return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump(regexp *r)
+{
+	register char *s;
+	register char op = EXACTLY;	/* Arbitrary non-END op. */
+	register char *next;
+	/* extern char *strchr(); */
+
+
+	s = r->program + 1;
+	while (op != END) {	/* While that wasn't END last time... */
+		op = OP(s);
+		printf("%2d%s", s-r->program, regprop(s));	/* Where, what. */
+		next = regnext(s);
+		if (next == NULL)		/* Next ptr. */
+			printf("(0)");
+		else
+			printf("(%d)", (s-r->program)+(next-s));
+		s += 3;
+		if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+			/* Literal string, where present. */
+			while (*s != '\0') {
+				putchar(*s);
+				s++;
+			}
+			s++;
+		}
+		putchar('\n');
+	}
+
+	/* Header fields of interest. */
+	if (r->regstart != '\0')
+		printf("start `%c' ", r->regstart);
+	if (r->reganch)
+		printf("anchored ");
+	if (r->regmust != NULL)
+		printf("must have \"%s\"", r->regmust);
+	printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop(char *op)
+{
+#define BUFLEN 50
+	register char *p;
+	static char buf[BUFLEN];
+
+	strcpy(buf, ":");
+
+	switch (OP(op)) {
+	case BOL:
+		p = "BOL";
+		break;
+	case EOL:
+		p = "EOL";
+		break;
+	case ANY:
+		p = "ANY";
+		break;
+	case ANYOF:
+		p = "ANYOF";
+		break;
+	case ANYBUT:
+		p = "ANYBUT";
+		break;
+	case BRANCH:
+		p = "BRANCH";
+		break;
+	case EXACTLY:
+		p = "EXACTLY";
+		break;
+	case NOTHING:
+		p = "NOTHING";
+		break;
+	case BACK:
+		p = "BACK";
+		break;
+	case END:
+		p = "END";
+		break;
+	case OPEN+1:
+	case OPEN+2:
+	case OPEN+3:
+	case OPEN+4:
+	case OPEN+5:
+	case OPEN+6:
+	case OPEN+7:
+	case OPEN+8:
+	case OPEN+9:
+		snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN);
+		p = NULL;
+		break;
+	case CLOSE+1:
+	case CLOSE+2:
+	case CLOSE+3:
+	case CLOSE+4:
+	case CLOSE+5:
+	case CLOSE+6:
+	case CLOSE+7:
+	case CLOSE+8:
+	case CLOSE+9:
+		snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+		p = NULL;
+		break;
+	case STAR:
+		p = "STAR";
+		break;
+	case PLUS:
+		p = "PLUS";
+		break;
+	default:
+		printk("<3>Regexp: corrupted opcode\n");
+		break;
+	}
+	if (p != NULL)
+		strncat(buf, p, BUFLEN-strlen(buf));
+	return(buf);
+}
+#endif
+
+
diff --git a/net/netfilter/regexp/regexp.h b/net/netfilter/regexp/regexp.h
new file mode 100755
index 0000000..a72eba7
--- /dev/null
+++ b/net/netfilter/regexp/regexp.h
@@ -0,0 +1,41 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+
+#ifndef REGEXP_H
+#define REGEXP_H
+
+
+/*
+http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h ,
+which contains a version of this library, says:
+
+ *
+ * NSUBEXP must be at least 10, and no greater than 117 or the parser
+ * will not work properly.
+ *
+
+However, it looks rather like this library is limited to 10.  If you think
+otherwise, let us know.
+*/
+
+#define NSUBEXP  10
+typedef struct regexp {
+	char *startp[NSUBEXP];
+	char *endp[NSUBEXP];
+	char regstart;		/* Internal use only. */
+	char reganch;		/* Internal use only. */
+	char *regmust;		/* Internal use only. */
+	int regmlen;		/* Internal use only. */
+	char program[1];	/* Unwarranted chumminess with compiler. */
+} regexp;
+
+regexp * regcomp(char *exp, int *patternsize);
+int regexec(regexp *prog, char *string);
+void regsub(regexp *prog, char *source, char *dest);
+void regerror(char *s);
+
+#endif
diff --git a/net/netfilter/regexp/regmagic.h b/net/netfilter/regexp/regmagic.h
new file mode 100755
index 0000000..5acf447
--- /dev/null
+++ b/net/netfilter/regexp/regmagic.h
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define	MAGIC	0234
diff --git a/net/netfilter/regexp/regsub.c b/net/netfilter/regexp/regsub.c
new file mode 100755
index 0000000..339631f
--- /dev/null
+++ b/net/netfilter/regexp/regsub.c
@@ -0,0 +1,95 @@
+/*
+ * regsub
+ * @(#)regsub.c	1.3 of 2 April 86
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ *
+ *
+ * This code was modified by Ethan Sommer to work within the kernel
+ * (it now uses kmalloc etc..)
+ *
+ */
+#include "regexp.h"
+#include "regmagic.h"
+#include <linux/string.h>
+
+
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+#if 0
+//void regerror(char * s)
+//{
+//        printk("regexp(3): %s", s);
+//        /* NOTREACHED */
+//}
+#endif
+
+/*
+ - regsub - perform substitutions after a regexp match
+ */
+void
+regsub(regexp * prog, char * source, char * dest)
+{
+	register char *src;
+	register char *dst;
+	register char c;
+	register int no;
+	register int len;
+	
+	/* Not necessary and gcc doesn't like it -MLS */
+	/*extern char *strncpy();*/
+
+	if (prog == NULL || source == NULL || dest == NULL) {
+		regerror("NULL parm to regsub");
+		return;
+	}
+	if (UCHARAT(prog->program) != MAGIC) {
+		regerror("damaged regexp fed to regsub");
+		return;
+	}
+
+	src = source;
+	dst = dest;
+	while ((c = *src++) != '\0') {
+		if (c == '&')
+			no = 0;
+		else if (c == '\\' && '0' <= *src && *src <= '9')
+			no = *src++ - '0';
+		else
+			no = -1;
+
+		if (no < 0) {	/* Ordinary character. */
+			if (c == '\\' && (*src == '\\' || *src == '&'))
+				c = *src++;
+			*dst++ = c;
+		} else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+			len = prog->endp[no] - prog->startp[no];
+			(void) strncpy(dst, prog->startp[no], len);
+			dst += len;
+			if (len != 0 && *(dst-1) == '\0') {	/* strncpy hit NUL. */
+				regerror("damaged match string");
+				return;
+			}
+		}
+	}
+	*dst++ = '\0';
+}
diff --git a/net/netfilter/xt_layer7.c b/net/netfilter/xt_layer7.c
new file mode 100755
index 0000000..a8777ef
--- /dev/null
+++ b/net/netfilter/xt_layer7.c
@@ -0,0 +1,666 @@
+/*
+  Kernel module to match application layer (OSI layer 7) data in connections.
+
+  http://l7-filter.sf.net
+
+  (C) 2003-2009 Matthew Strait and Ethan Sommer.
+
+  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.
+  http://www.gnu.org/licenses/gpl.txt
+
+  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>,
+  xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait,
+  Ethan Sommer, Justin Levandoski.
+*/
+
+#include <linux/spinlock.h>
+#include <linux/version.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_acct.h>
+#endif
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_layer7.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+
+#include "regexp/regexp.c"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
+MODULE_DESCRIPTION("iptables application layer match module");
+MODULE_ALIAS("ipt_layer7");
+MODULE_VERSION("2.21");
+
+static int maxdatalen = 2048; // this is the default
+module_param(maxdatalen, int, 0444);
+MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter");
+#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG
+	#define DPRINTK(format,args...) printk(format,##args)
+#else
+	#define DPRINTK(format,args...)
+#endif
+
+/* Number of packets whose data we look at.
+This can be modified through /proc/net/layer7_numpackets */
+static int num_packets = 10;
+
+static struct pattern_cache {
+	char * regex_string;
+	regexp * pattern;
+	struct pattern_cache * next;
+} * first_pattern_cache = NULL;
+
+DEFINE_SPINLOCK(l7_lock);
+
+static int total_acct_packets(struct nf_conn *ct)
+{
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26)
+	BUG_ON(ct == NULL);
+	return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets);
+#else
+	struct nf_conn_counter *acct;
+
+	BUG_ON(ct == NULL);
+	acct = nf_conn_acct_find(ct);
+	if (!acct)
+		return 0;
+	return (acct[IP_CT_DIR_ORIGINAL].packets + acct[IP_CT_DIR_REPLY].packets);
+#endif
+}
+
+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
+/* Converts an unfriendly string into a friendly one by
+replacing unprintables with periods and all whitespace with " ". */
+static char * friendly_print(unsigned char * s)
+{
+	char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
+	int i;
+
+	if(!f) {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory in "
+					"friendly_print, bailing.\n");
+		return NULL;
+	}
+
+	for(i = 0; i < strlen(s); i++){
+		if(isprint(s[i]) && s[i] < 128)	f[i] = s[i];
+		else if(isspace(s[i]))		f[i] = ' ';
+		else 				f[i] = '.';
+	}
+	f[i] = '\0';
+	return f;
+}
+
+static char dec2hex(int i)
+{
+	switch (i) {
+		case 0 ... 9:
+			return (i + '0');
+			break;
+		case 10 ... 15:
+			return (i - 10 + 'a');
+			break;
+		default:
+			if (net_ratelimit())
+				printk("layer7: Problem in dec2hex\n");
+			return '\0';
+	}
+}
+
+static char * hex_print(unsigned char * s)
+{
+	char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
+	int i;
+
+	if(!g) {
+	       if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory in hex_print, "
+					"bailing.\n");
+	       return NULL;
+	}
+
+	for(i = 0; i < strlen(s); i++) {
+		g[i*3    ] = dec2hex(s[i]/16);
+		g[i*3 + 1] = dec2hex(s[i]%16);
+		g[i*3 + 2] = ' ';
+	}
+	g[i*3] = '\0';
+
+	return g;
+}
+#endif // DEBUG
+
+/* Use instead of regcomp.  As we expect to be seeing the same regexps over and
+over again, it make sense to cache the results. */
+static regexp * compile_and_cache(const char * regex_string, 
+                                  const char * protocol)
+{
+	struct pattern_cache * node               = first_pattern_cache;
+	struct pattern_cache * last_pattern_cache = first_pattern_cache;
+	struct pattern_cache * tmp;
+	unsigned int len;
+
+	while (node != NULL) {
+		if (!strcmp(node->regex_string, regex_string))
+		return node->pattern;
+
+		last_pattern_cache = node;/* points at the last non-NULL node */
+		node = node->next;
+	}
+
+	/* If we reach the end of the list, then we have not yet cached
+	   the pattern for this regex. Let's do that now.
+	   Be paranoid about running out of memory to avoid list corruption. */
+	tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
+
+	if(!tmp) {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory in "
+					"compile_and_cache, bailing.\n");
+		return NULL;
+	}
+
+	tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
+	tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC);
+	tmp->next = NULL;
+
+	if(!tmp->regex_string || !tmp->pattern) {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory in "
+					"compile_and_cache, bailing.\n");
+		kfree(tmp->regex_string);
+		kfree(tmp->pattern);
+		kfree(tmp);
+		return NULL;
+	}
+
+	/* Ok.  The new node is all ready now. */
+	node = tmp;
+
+	if(first_pattern_cache == NULL) /* list is empty */
+		first_pattern_cache = node; /* make node the beginning */
+	else
+		last_pattern_cache->next = node; /* attach node to the end */
+
+	/* copy the string and compile the regex */
+	len = strlen(regex_string);
+	DPRINTK("About to compile this: \"%s\"\n", regex_string);
+	node->pattern = regcomp((char *)regex_string, &len);
+	if ( !node->pattern ) {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: Error compiling regexp "
+					"\"%s\" (%s)\n", 
+					regex_string, protocol);
+		/* pattern is now cached as NULL, so we won't try again. */
+	}
+
+	strcpy(node->regex_string, regex_string);
+	return node->pattern;
+}
+
+static int can_handle(const struct sk_buff *skb)
+{
+	if(!ip_hdr(skb)) /* not IP */
+		return 0;
+	if(ip_hdr(skb)->protocol != IPPROTO_TCP &&
+	   ip_hdr(skb)->protocol != IPPROTO_UDP &&
+	   ip_hdr(skb)->protocol != IPPROTO_ICMP)
+		return 0;
+	return 1;
+}
+
+/* Returns offset the into the skb->data that the application data starts */
+static int app_data_offset(const struct sk_buff *skb)
+{
+	/* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
+	isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
+	int ip_hl = 4*ip_hdr(skb)->ihl;
+
+	if( ip_hdr(skb)->protocol == IPPROTO_TCP ) {
+		/* 12 == offset into TCP header for the header length field.
+		Can't get this with skb->h.th->doff because the tcphdr
+		struct doesn't get set when routing (this is confirmed to be
+		true in Netfilter as well as QoS.) */
+		int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
+
+		return ip_hl + tcp_hl;
+	} else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) {
+		return ip_hl + 8; /* UDP header is always 8 bytes */
+	} else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) {
+		return ip_hl + 8; /* ICMP header is 8 bytes */
+	} else {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: tried to handle unknown "
+					"protocol!\n");
+		return ip_hl + 8; /* something reasonable */
+	}
+}
+
+/* handles whether there's a match when we aren't appending data anymore */
+static int match_no_append(struct nf_conn * conntrack, 
+                           struct nf_conn * master_conntrack, 
+                           enum ip_conntrack_info ctinfo,
+                           enum ip_conntrack_info master_ctinfo,
+                           const struct xt_layer7_info * info)
+{
+	/* If we're in here, throw the app data away */
+	if(master_conntrack->layer7.app_data != NULL) {
+
+	#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
+		if(!master_conntrack->layer7.app_proto) {
+			char * f = 
+			  friendly_print(master_conntrack->layer7.app_data);
+			char * g = 
+			  hex_print(master_conntrack->layer7.app_data);
+			DPRINTK("\nl7-filter gave up after %d bytes "
+				"(%d packets):\n%s\n",
+				strlen(f), total_acct_packets(master_conntrack), f);
+			kfree(f);
+			DPRINTK("In hex: %s\n", g);
+			kfree(g);
+		}
+	#endif
+
+		kfree(master_conntrack->layer7.app_data);
+		master_conntrack->layer7.app_data = NULL; /* don't free again */
+	}
+
+	if(master_conntrack->layer7.app_proto){
+		/* Here child connections set their .app_proto (for /proc) */
+		if(!conntrack->layer7.app_proto) {
+			conntrack->layer7.app_proto = 
+			  kmalloc(strlen(master_conntrack->layer7.app_proto)+1, 
+			    GFP_ATOMIC);
+			if(!conntrack->layer7.app_proto){
+				if (net_ratelimit())
+					printk(KERN_ERR "layer7: out of memory "
+							"in match_no_append, "
+							"bailing.\n");
+				return 1;
+			}
+			strcpy(conntrack->layer7.app_proto, 
+				master_conntrack->layer7.app_proto);
+		}
+
+		return (!strcmp(master_conntrack->layer7.app_proto, 
+				info->protocol));
+	}
+	else {
+		/* If not classified, set to "unknown" to distinguish from
+		connections that are still being tested. */
+		master_conntrack->layer7.app_proto = 
+			kmalloc(strlen("unknown")+1, GFP_ATOMIC);
+		if(!master_conntrack->layer7.app_proto){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: out of memory in "
+						"match_no_append, bailing.\n");
+			return 1;
+		}
+		strcpy(master_conntrack->layer7.app_proto, "unknown");
+		return 0;
+	}
+}
+
+/* add the new app data to the conntrack.  Return number of bytes added. */
+static int add_data(struct nf_conn * master_conntrack,
+                    char * app_data, int appdatalen)
+{
+	int length = 0, i;
+	int oldlength = master_conntrack->layer7.app_data_len;
+
+	/* This is a fix for a race condition by Deti Fliegl. However, I'm not 
+	   clear on whether the race condition exists or whether this really 
+	   fixes it.  I might just be being dense... Anyway, if it's not really 
+	   a fix, all it does is waste a very small amount of time. */
+	if(!master_conntrack->layer7.app_data) return 0;
+
+	/* Strip nulls. Make everything lower case (our regex lib doesn't
+	do case insensitivity).  Add it to the end of the current data. */
+	for(i = 0; i < maxdatalen-oldlength-1 &&
+		   i < appdatalen; i++) {
+		if(app_data[i] != '\0') {
+			/* the kernel version of tolower mungs 'upper ascii' */
+			master_conntrack->layer7.app_data[length+oldlength] =
+				isascii(app_data[i])? 
+					tolower(app_data[i]) : app_data[i];
+			length++;
+		}
+	}
+
+	master_conntrack->layer7.app_data[length+oldlength] = '\0';
+	master_conntrack->layer7.app_data_len = length + oldlength;
+
+	return length;
+}
+
+/* taken from drivers/video/modedb.c */
+static int my_atoi(const char *s)
+{
+	int val = 0;
+
+	for (;; s++) {
+		switch (*s) {
+			case '0'...'9':
+			val = 10*val+(*s-'0');
+			break;
+		default:
+			return val;
+		}
+	}
+}
+
+/* write out num_packets to userland. */
+static int layer7_read_proc(char* page, char ** start, off_t off, int count,
+                            int* eof, void * data)
+{
+	if(num_packets > 99 && net_ratelimit())
+		printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n");
+
+	page[0] = num_packets/10 + '0';
+	page[1] = num_packets%10 + '0';
+	page[2] = '\n';
+	page[3] = '\0';
+
+	*eof=1;
+
+	return 3;
+}
+
+/* Read in num_packets from userland */
+static int layer7_write_proc(struct file* file, const char* buffer,
+                             unsigned long count, void *data)
+{
+	char * foo = kmalloc(count, GFP_ATOMIC);
+
+	if(!foo){
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory, bailing. "
+					"num_packets unchanged.\n");
+		return count;
+	}
+
+	if(copy_from_user(foo, buffer, count)) {
+		return -EFAULT;
+	}
+
+
+	num_packets = my_atoi(foo);
+	kfree (foo);
+
+	/* This has an arbitrary limit to make the math easier. I'm lazy.
+	But anyway, 99 is a LOT! If you want more, you're doing it wrong! */
+	if(num_packets > 99) {
+		printk(KERN_WARNING "layer7: num_packets can't be > 99.\n");
+		num_packets = 99;
+	} else if(num_packets < 1) {
+		printk(KERN_WARNING "layer7: num_packets can't be < 1.\n");
+		num_packets = 1;
+	}
+
+	return count;
+}
+
+static bool
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+match(const struct sk_buff *skbin, const struct xt_match_param *par)
+#else
+match(const struct sk_buff *skbin,
+      const struct net_device *in,
+      const struct net_device *out,
+      const struct xt_match *match,
+      const void *matchinfo,
+      int offset,
+      unsigned int protoff,
+      bool *hotdrop)
+#endif
+{
+	/* sidestep const without getting a compiler warning... */
+	struct sk_buff * skb = (struct sk_buff *)skbin; 
+
+	const struct xt_layer7_info * info = 
+	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+		par->matchinfo;
+	#else
+		matchinfo;
+	#endif
+
+	enum ip_conntrack_info master_ctinfo, ctinfo;
+	struct nf_conn *master_conntrack, *conntrack;
+	unsigned char * app_data;
+	unsigned int pattern_result, appdatalen;
+	regexp * comppattern;
+
+	/* Be paranoid/incompetent - lock the entire match function. */
+	spin_lock_bh(&l7_lock);
+
+	if(!can_handle(skb)){
+		DPRINTK("layer7: This is some protocol I can't handle.\n");
+		spin_unlock_bh(&l7_lock);
+		return info->invert;
+	}
+
+	/* Treat parent & all its children together as one connection, except
+	for the purpose of setting conntrack->layer7.app_proto in the actual
+	connection. This makes /proc/net/ip_conntrack more satisfying. */
+	if(!(conntrack = nf_ct_get(skb, &ctinfo)) ||
+	   !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){
+		DPRINTK("layer7: couldn't get conntrack.\n");
+		spin_unlock_bh(&l7_lock);
+		return info->invert;
+	}
+
+	/* Try to get a master conntrack (and its master etc) for FTP, etc. */
+	while (master_ct(master_conntrack) != NULL)
+		master_conntrack = master_ct(master_conntrack);
+
+	/* if we've classified it or seen too many packets */
+	if(total_acct_packets(master_conntrack) > num_packets ||
+	   master_conntrack->layer7.app_proto) {
+
+		pattern_result = match_no_append(conntrack, master_conntrack, 
+						 ctinfo, master_ctinfo, info);
+
+		/* skb->cb[0] == seen. Don't do things twice if there are 
+		multiple l7 rules. I'm not sure that using cb for this purpose 
+		is correct, even though it says "put your private variables 
+		there". But it doesn't look like it is being used for anything
+		else in the skbs that make it here. */
+		skb->cb[0] = 1; /* marking it seen here's probably irrelevant */
+
+		spin_unlock_bh(&l7_lock);
+		return (pattern_result ^ info->invert);
+	}
+
+	if(skb_is_nonlinear(skb)){
+		if(skb_linearize(skb) != 0){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: failed to linearize "
+						"packet, bailing.\n");
+			spin_unlock_bh(&l7_lock);
+			return info->invert;
+		}
+	}
+
+	/* now that the skb is linearized, it's safe to set these. */
+	app_data = skb->data + app_data_offset(skb);
+	appdatalen = skb_tail_pointer(skb) - app_data;
+
+	/* the return value gets checked later, when we're ready to use it */
+	comppattern = compile_and_cache(info->pattern, info->protocol);
+
+	/* On the first packet of a connection, allocate space for app data */
+	if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] && 
+	   !master_conntrack->layer7.app_data){
+		master_conntrack->layer7.app_data = 
+			kmalloc(maxdatalen, GFP_ATOMIC);
+		if(!master_conntrack->layer7.app_data){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: out of memory in "
+						"match, bailing.\n");
+			spin_unlock_bh(&l7_lock);
+			return info->invert;
+		}
+
+		master_conntrack->layer7.app_data[0] = '\0';
+	}
+
+	/* Can be here, but unallocated, if numpackets is increased near
+	the beginning of a connection */
+	if(master_conntrack->layer7.app_data == NULL){
+		spin_unlock_bh(&l7_lock);
+		return info->invert; /* unmatched */
+	}
+
+	if(!skb->cb[0]){
+		int newbytes;
+		newbytes = add_data(master_conntrack, app_data, appdatalen);
+
+		if(newbytes == 0) { /* didn't add any data */
+			skb->cb[0] = 1;
+			/* Didn't match before, not going to match now */
+			spin_unlock_bh(&l7_lock);
+			return info->invert;
+		}
+	}
+
+	/* If looking for "unknown", then never match.  "Unknown" means that
+	we've given up; we're still trying with these packets. */
+	if(!strcmp(info->protocol, "unknown")) {
+		pattern_result = 0;
+	/* If looking for "unset", then always match. "Unset" means that we
+	haven't yet classified the connection. */
+	} else if(!strcmp(info->protocol, "unset")) {
+		pattern_result = 2;
+		DPRINTK("layer7: matched unset: not yet classified "
+			"(%d/%d packets)\n",
+                        total_acct_packets(master_conntrack), num_packets);
+	/* If the regexp failed to compile, don't bother running it */
+	} else if(comppattern && 
+		  regexec(comppattern, master_conntrack->layer7.app_data)){
+		DPRINTK("layer7: matched %s\n", info->protocol);
+		pattern_result = 1;
+	} else pattern_result = 0;
+
+	if(pattern_result == 1) {
+		master_conntrack->layer7.app_proto = 
+			kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);
+		if(!master_conntrack->layer7.app_proto){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: out of memory in "
+						"match, bailing.\n");
+			spin_unlock_bh(&l7_lock);
+			return (pattern_result ^ info->invert);
+		}
+		strcpy(master_conntrack->layer7.app_proto, info->protocol);
+	} else if(pattern_result > 1) { /* cleanup from "unset" */
+		pattern_result = 1;
+	}
+
+	/* mark the packet seen */
+	skb->cb[0] = 1;
+
+	spin_unlock_bh(&l7_lock);
+	return (pattern_result ^ info->invert);
+}
+
+// load nf_conntrack_ipv4
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+static bool check(const struct xt_mtchk_param *par)
+{
+        if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
+                printk(KERN_WARNING "can't load conntrack support for "
+                                    "proto=%d\n", par->match->family);
+#else
+static bool check(const char *tablename, const void *inf,
+		 const struct xt_match *match, void *matchinfo,
+		 unsigned int hook_mask)
+{
+        if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+                printk(KERN_WARNING "can't load conntrack support for "
+                                    "proto=%d\n", match->family);
+#endif
+                return 0;
+        }
+	return 1;
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+	static void destroy(const struct xt_mtdtor_param *par)
+	{
+		nf_ct_l3proto_module_put(par->match->family);
+	}
+#else
+	static void destroy(const struct xt_match *match, void *matchinfo)
+	{
+		nf_ct_l3proto_module_put(match->family);
+	}
+#endif
+
+static struct xt_match xt_layer7_match[] __read_mostly = {
+{
+	.name		= "layer7",
+	.family		= AF_INET,
+	.checkentry	= check,
+	.match		= match,
+	.destroy	= destroy,
+	.matchsize	= sizeof(struct xt_layer7_info),
+	.me		= THIS_MODULE
+}
+};
+
+static void layer7_cleanup_proc(void)
+{
+	remove_proc_entry("layer7_numpackets", init_net.proc_net);
+}
+
+/* register the proc file */
+static void layer7_init_proc(void)
+{
+	struct proc_dir_entry* entry;
+	entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net);
+	entry->read_proc = layer7_read_proc;
+	entry->write_proc = layer7_write_proc;
+}
+
+static int __init xt_layer7_init(void)
+{
+	need_conntrack();
+
+	layer7_init_proc();
+	if(maxdatalen < 1) {
+		printk(KERN_WARNING "layer7: maxdatalen can't be < 1, "
+			"using 1\n");
+		maxdatalen = 1;
+	}
+	/* This is not a hard limit.  It's just here to prevent people from
+	bringing their slow machines to a grinding halt. */
+	else if(maxdatalen > 65536) {
+		printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, "
+			"using 65536\n");
+		maxdatalen = 65536;
+	}
+	return xt_register_matches(xt_layer7_match,
+				   ARRAY_SIZE(xt_layer7_match));
+}
+
+static void __exit xt_layer7_fini(void)
+{
+	layer7_cleanup_proc();
+	xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match));
+}
+
+module_init(xt_layer7_init);
+module_exit(xt_layer7_fini);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
old mode 100644
new mode 100755
index b1749bc..f487381
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -37,6 +37,16 @@
 source "sound/soc/sh/Kconfig"
 source "sound/soc/txx9/Kconfig"
 
+config SND_MRVL_AUDIO
+	tristate "Marvell mv88fx Audio ALSA driver"
+	depends on MV_INCLUDE_AUDIO && SND
+	select SND_PCM
+	select SND_SOC_CS42L51
+	---help---
+	  Say Y here to include support for Marvell Audio device
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-mrvl-audio.
+
 # Supported codecs
 source "sound/soc/codecs/Kconfig"
 
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
old mode 100644
new mode 100755
index 0c5eac0..74bad08
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -14,3 +14,6 @@
 obj-$(CONFIG_SND_SOC)	+= s6000/
 obj-$(CONFIG_SND_SOC)	+= sh/
 obj-$(CONFIG_SND_SOC)	+= txx9/
+
+obj-$(CONFIG_SND_MRVL_AUDIO)  += ../../arch/arm/plat-feroceon/mv_drivers_lsp/mv_audio_soc/
+
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
old mode 100644
new mode 100755
index fb4af28..f233739
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -8,6 +8,7 @@
 snd-soc-ak4642-objs := ak4642.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-cx20442-objs := cx20442.o
+snd-soc-cs42l51-objs := cs42l51.o
 snd-soc-l3-objs := l3.o
 snd-soc-pcm3008-objs := pcm3008.o
 snd-soc-spdif-objs := spdif_transciever.o
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
new file mode 100755
index 0000000..444d7cd
--- /dev/null
+++ b/sound/soc/codecs/cs42l51.c
@@ -0,0 +1,631 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include "cs42l51.h"
+
+#define AUDIO_NAME "cs42l51"
+
+#define CS42L51_CACHE_SIZE (CS42L51_REG_MAX+1)
+
+
+
+/*#define CS42L51_DEBUG(format, args...) \
+	printk(KERN_ERR "%s(%d): "format"\n", __FUNCTION__, __LINE__, ##args)
+*/
+
+#define CS42L51_DEBUG(format, args...)
+
+/* codec private data */
+struct cs42l51_priv {
+	unsigned int sysclk;
+	struct snd_soc_codec *codec;
+};
+
+static unsigned int cs42l51_read_reg_cache(struct snd_soc_codec *codec,
+					   unsigned int reg)
+{
+	u8 *cache = codec->reg_cache;
+	if (reg > CS42L51_REG_MAX)
+		return -1;
+	return cache[reg];
+}
+
+static void cs42l51_write_reg_cache(struct snd_soc_codec *codec,
+				    u8 reg, u8 value)
+{
+	u8 *cache = codec->reg_cache;
+	if (reg > CS42L51_REG_MAX)
+		return;
+	cache[reg] = value;
+}
+
+static int cs42l51_write(struct snd_soc_codec *codec, unsigned int reg,
+			 unsigned int value)
+{
+	u8 data[2];
+
+	reg &= 0x7f;
+	data[0] = reg & 0xff;
+	data[1] = value & 0xff;
+
+	cs42l51_write_reg_cache(codec, data[0], data[1]);
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
+		return 0;
+	else
+		return -EIO;
+}
+
+static unsigned int cs42l51_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+	return cs42l51_read_reg_cache(codec, reg);
+}
+
+static unsigned int cs42l51_read_no_cache(struct snd_soc_codec *codec,
+					  unsigned int reg)
+{
+	struct i2c_msg msg[2];
+	u8 data[2];
+	struct i2c_client *i2c_client = codec->control_data;
+	int ret;
+
+	i2c_client = (struct i2c_client *)codec->control_data;
+
+	data[0] = reg & 0xff;
+	msg[0].addr = i2c_client->addr;
+	msg[0].flags = 0;
+	msg[0].buf = &data[0];
+	msg[0].len = 1;
+
+	msg[1].addr = i2c_client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = &data[1];
+	msg[1].len = 1;
+
+	ret = i2c_transfer(i2c_client->adapter, &msg[0], 2);
+	return (ret == 2) ? data[1] : -EIO;
+}
+
+static void cs42l51_fill_cache(struct snd_soc_codec *codec)
+{
+	u8 *cache = codec->reg_cache;
+	unsigned int reg;
+
+	for (reg = 1; reg <= CS42L51_REG_MAX; reg++)
+		cache[reg] = cs42l51_read_no_cache(codec, reg);
+
+}
+
+
+static void cs42l51_sync_cache(struct snd_soc_codec *codec)
+{
+	u8 *cache = codec->reg_cache;
+	unsigned int reg;
+
+	for (reg = 1; reg <= CS42L51_REG_MAX; reg++)
+		cs42l51_write(codec, reg, cache[reg]);
+}
+
+
+static void cs42l51_set_bits(struct snd_soc_codec *codec, u32 addr,
+			     u32 start_bit, u32 end_bit, u32 value)
+{
+	u32 mask;
+	u32 new_value;
+	u32 old_value;
+
+	old_value = cs42l51_read(codec, addr);
+	mask = ((1 << (end_bit + 1 - start_bit)) - 1) << start_bit;
+	new_value = old_value & (~mask);
+	new_value |= (mask & (value << start_bit));
+	cs42l51_write(codec, addr, new_value);
+}
+
+static u8 cs42l51_volume_mapping[] = {
+	0x19, 0xB2, 0xB7, 0xBD, 0xC3, 0xC9, 0xCF, 0xD5,
+	0xD8, 0xE1, 0xE7, 0xED, 0xF3, 0xF9, 0xFF, 0x00,
+	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+	0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
+};
+
+#define CS42L51_NUM_VOLUME_STEPS  ARRAY_SIZE(cs42l51_volume_mapping)
+
+static u8 cs42l51_reg2vol(u8 reg)
+{
+	u8 i;
+
+	for (i = 0; i < CS42L51_NUM_VOLUME_STEPS; i++) {
+		if (reg == cs42l51_volume_mapping[i])
+			return i;
+		if ((cs42l51_volume_mapping[i] >
+		     cs42l51_volume_mapping[CS42L51_NUM_VOLUME_STEPS - 1])
+		    && (reg > cs42l51_volume_mapping[i])
+		    && (reg < cs42l51_volume_mapping[i + 1]))
+			return i;
+
+	}
+	return 0;
+}
+
+static u8 cs42l51_vol2reg(u8 vol)
+{
+	if (vol >= CS42L51_NUM_VOLUME_STEPS)
+		vol = CS42L51_NUM_VOLUME_STEPS - 1;
+	return cs42l51_volume_mapping[vol];
+}
+
+static int cs42l51_vol_info(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 39;
+
+	return 0;
+}
+
+static int cs42l51_vol_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 reg;
+	u8 vol;
+
+	reg = snd_soc_read(codec, CS42L51_REG_VOL_OUTA_CTRL);
+	vol = cs42l51_reg2vol(reg);
+	ucontrol->value.integer.value[0] = vol;
+
+	reg = snd_soc_read(codec, CS42L51_REG_VOL_OUTB_CTRL);
+	vol = cs42l51_reg2vol(reg);
+	ucontrol->value.integer.value[1] = vol;
+	return 0;
+}
+
+static int cs42l51_vol_set(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 reg;
+	u8 vol;
+
+	vol = (u8) ucontrol->value.integer.value[0];
+	reg = cs42l51_vol2reg(vol);
+	snd_soc_update_bits(codec, CS42L51_REG_VOL_OUTA_CTRL, 0xFF, reg);
+
+	vol = (u8) ucontrol->value.integer.value[1];
+	reg = cs42l51_vol2reg(vol);
+	snd_soc_update_bits(codec, CS42L51_REG_VOL_OUTB_CTRL, 0xFF, reg);
+
+	return 0;
+}
+
+static struct snd_kcontrol_new cs42l51_snd_controls[] = {
+	{
+	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	 .name = "Playback DAC Volume",
+	 .info = cs42l51_vol_info,
+	 .get = cs42l51_vol_get,
+	 .put = cs42l51_vol_set},
+};
+
+/* add non dapm controls */
+static int cs42l51_add_controls(struct snd_soc_codec *codec)
+{
+	int err, i;
+
+	CS42L51_DEBUG("");
+
+	for (i = 0; i < ARRAY_SIZE(cs42l51_snd_controls); i++) {
+		err = snd_ctl_add(codec->card,
+				  snd_soc_cnew(&cs42l51_snd_controls[i], codec,
+					       NULL));
+
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int cs42l51_startup(struct snd_pcm_substream *stream,
+				struct snd_soc_dai *dai)
+{
+	CS42L51_DEBUG("");
+	return 0;
+}
+
+static void cs42l51_shutdown(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	CS42L51_DEBUG("");
+}
+
+static int cs42l51_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *hw_params,
+				struct snd_soc_dai *dai)
+{
+	CS42L51_DEBUG("");
+	return 0;
+}
+
+static int cs42l51_hw_free(struct snd_pcm_substream *stream,
+				struct snd_soc_dai *dai)
+{
+	CS42L51_DEBUG("");
+	return 0;
+}
+
+static int cs42l51_prepare(struct snd_pcm_substream *stream,
+				struct snd_soc_dai *dai)
+{
+	CS42L51_DEBUG("");
+	return 0;
+}
+
+static int cs42l51_trigger(struct snd_pcm_substream *stream, int cmd,
+				struct snd_soc_dai *dai)
+{
+	CS42L51_DEBUG("");
+	return 0;
+}
+
+static int cs42l51_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	CS42L51_DEBUG("mute=%d", mute);
+
+	if (mute)
+		cs42l51_set_bits(codec, CS42L51_REG_DAC_OUTPUT_CTRL, 0, 1, 3);
+	else
+		cs42l51_set_bits(codec, CS42L51_REG_DAC_OUTPUT_CTRL, 0, 1, 0);
+
+	return 0;
+}
+
+static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+				  int clk_id, unsigned int freq, int dir)
+{
+	CS42L51_DEBUG("clk_id=%d freq=%u dir=%d", clk_id, freq, dir);
+	return 0;
+}
+
+static int cs42l51_set_dai_fmt(struct snd_soc_dai *dai,
+			       unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	CS42L51_DEBUG("fmt=%u", fmt);
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_LEFT_J:
+		cs42l51_set_bits(codec, CS42L51_REG_IF_CNTRL, 3, 5, 0);
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		cs42l51_set_bits(codec, CS42L51_REG_IF_CNTRL, 3, 5, 1);
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		cs42l51_set_bits(codec, CS42L51_REG_IF_CNTRL, 3, 5, 2);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+static int cs42l51_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	CS42L51_DEBUG("bias level transition: %d -> %d",
+		codec->bias_level, level);
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+	case SND_SOC_BIAS_PREPARE:
+		cs42l51_set_bits(codec, CS42L51_REG_POWER_CNTRL, 0, 0, 0);
+		break;
+	case SND_SOC_BIAS_STANDBY:
+	case SND_SOC_BIAS_OFF:
+		cs42l51_set_bits(codec, CS42L51_REG_POWER_CNTRL, 0, 0, 1);
+		break;
+	}
+	codec->bias_level = level;
+	return 0;
+}
+
+static struct snd_soc_dai_ops cs42l51_dai_ops = {
+		.startup = cs42l51_startup,
+		.shutdown = cs42l51_shutdown,
+		.hw_params = cs42l51_hw_params,
+		.hw_free = cs42l51_hw_free,
+		.prepare = cs42l51_prepare,
+		.trigger = cs42l51_trigger,
+		.digital_mute = cs42l51_mute,
+		.set_sysclk = cs42l51_set_dai_sysclk,
+		.set_fmt = cs42l51_set_dai_fmt,
+};
+
+
+struct snd_soc_dai cs42l51_dai = {
+	.name = "CS42L51",
+	.playback = {
+		     .stream_name = "Playback",
+		     .rate_min = 44100,
+		     .rate_max = 96000,
+		     .channels_min = 1,
+		     .channels_max = 2,
+		     .rates = (SNDRV_PCM_RATE_44100 |
+			       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000),
+		     .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				 SNDRV_PCM_FMTBIT_S24_LE |
+				 SNDRV_PCM_FMTBIT_S32_LE),
+		     },
+	.capture = {
+		    .stream_name = "Capture",
+		    .rate_min = 44100,
+		    .rate_max = 96000,
+		    .channels_min = 1,
+		    .channels_max = 2,
+		    .rates = (SNDRV_PCM_RATE_44100 |
+			      SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000),
+		    .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S24_LE |
+				SNDRV_PCM_FMTBIT_S32_LE),
+		    },
+	/* pcm operations */
+	.ops = &cs42l51_dai_ops,
+};
+EXPORT_SYMBOL_GPL(cs42l51_dai);
+
+static int cs42l51_init(struct snd_soc_device *socdev)
+{
+	struct snd_soc_codec *codec = socdev->card->codec;
+	u8 reg;
+	int ret;
+
+	CS42L51_DEBUG("");
+
+	codec->owner = THIS_MODULE;
+	codec->name = "CS42L51";
+	codec->dai = &cs42l51_dai;
+#warning "Need to open this..."
+//	codec->set_bias_level = cs42l51_set_bias_level;
+	codec->num_dai = 1;
+	codec->reg_cache_size = CS42L51_CACHE_SIZE;
+	codec->reg_cache = kzalloc(codec->reg_cache_size, GFP_KERNEL);
+	if (!codec->reg_cache)
+		return -ENOMEM;
+
+	cs42l51_fill_cache(codec);
+
+	ret = -ENODEV;
+
+	reg = cs42l51_read(codec, CS42L51_REG_ID);
+	printk(KERN_INFO "cs42l51: chipid/revision = %x\n", reg);
+
+	/* Set the digital Interface format to I2S-up-to-24-bit */
+	cs42l51_set_bits(codec, CS42L51_REG_IF_CNTRL, 3, 5, 1);
+
+	/* Set the ADC Mode */
+	cs42l51_set_bits(codec, CS42L51_REG_IF_CNTRL, 2, 2, 1);
+
+	/* init the chip */
+	/* use signal processor */
+	cs42l51_write(codec, CS42L51_REG_DAC_CTRL, 0x40);
+	/* Unmute PCM-A & PCM-B and set default */
+	cs42l51_write(codec, CS42L51_REG_PCMA_MIXER_VOL_CNTRL, 0x10);
+	cs42l51_write(codec, CS42L51_REG_PCMB_MIXER_VOL_CNTRL, 0x10);
+	/* default for AOUTx */
+	cs42l51_write(codec, CS42L51_REG_VOL_OUTA_CTRL, cs42l51_vol2reg(4));
+	cs42l51_write(codec, CS42L51_REG_VOL_OUTB_CTRL, cs42l51_vol2reg(4));
+	/* swap channels */
+	cs42l51_write(codec, CS42L51_REG_CHANNEL_MIXER, 0xff);
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0) {
+		pr_err("failed to create pcms");
+		goto pcm_err;
+	}
+	cs42l51_add_controls(codec);
+
+
+	ret = snd_soc_init_card(socdev);
+	if (ret < 0) {
+		pr_err("failed to register card\n");
+		goto card_err;
+	}
+	return 0;
+
+card_err:
+	snd_soc_free_pcms(socdev);
+
+pcm_err:
+	kfree(codec->reg_cache);
+	return ret;
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+static const struct i2c_device_id cs42l51_i2c_table[] = {
+	{"i2s_i2c", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_table);
+
+static struct i2c_driver cs42l51_i2c_driver;
+static struct snd_soc_device *cs42l51_socdev;
+
+static int cs42l51_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct snd_soc_device *socdev = cs42l51_socdev;
+	struct snd_soc_codec *codec = socdev->card->codec;
+	struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
+	int ret;
+
+
+	CS42L51_DEBUG("");
+
+	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_EMUL))
+		return -EIO;
+
+	i2c_set_clientdata(client, codec);
+	codec->control_data = client;
+
+	codec->read = cs42l51_read;
+	codec->write = cs42l51_write;
+
+	ret = cs42l51_init(socdev);
+	if (ret < 0)
+		goto err;
+
+	return ret;
+
+err:
+	kfree(codec);
+	return ret;
+}
+
+static int cs42l51_i2c_remove(struct i2c_client *client)
+{
+	return 0;
+}
+
+static struct i2c_driver cs42l51_i2c_driver = {
+	.driver = {
+		   .name = "cs42l51",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = cs42l51_i2c_probe,
+	.remove = cs42l51_i2c_remove,
+	.id_table = cs42l51_i2c_table,
+};
+
+#endif
+
+static int cs42l51_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	struct cs42l51_priv *cs;
+	struct cs42l51_setup_data *setup;
+	int ret;
+
+	CS42L51_DEBUG("");
+
+	ret = -ENOMEM;
+	setup = socdev->codec_data;
+	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (codec == NULL)
+		goto out;
+
+	cs = kzalloc(sizeof(struct cs42l51_priv), GFP_KERNEL);
+	if (cs == NULL) {
+		kfree(codec);
+		goto out;
+	}
+	ret = 0;
+
+	cs->codec = codec;
+	codec->private_data = cs;
+	socdev->card->codec = codec;
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	cs42l51_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	if (setup && setup->i2c_address) {
+		codec->hw_write = (hw_write_t) i2c_master_send;
+		ret = i2c_add_driver(&cs42l51_i2c_driver);
+		if (ret)
+			printk(KERN_ERR "can't add i2c driver\n");
+	}
+#endif
+
+out:
+	return ret;
+}
+
+/* power down chip */
+static int cs42l51_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->card->codec;
+
+	CS42L51_DEBUG("");
+
+	snd_soc_free_pcms(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&cs42l51_i2c_driver);
+#endif
+	kfree(codec->private_data);
+	kfree(codec);
+
+	return 0;
+}
+
+static int cs42l51_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->card->codec;
+
+	CS42L51_DEBUG("event=%d", state.event);
+
+	cs42l51_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+static int cs42l51_resume(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->card->codec;
+
+	CS42L51_DEBUG("");
+
+	cs42l51_sync_cache(codec);
+	cs42l51_set_bias_level(codec, codec->suspend_bias_level);
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_cs42l51 = {
+	.probe = cs42l51_probe,
+	.remove = cs42l51_remove,
+	.suspend = cs42l51_suspend,
+	.resume = cs42l51_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_cs42l51);
+
+static int __init cs42l51_modinit(void)
+{
+	CS42L51_DEBUG("");
+	return snd_soc_register_dai(&cs42l51_dai);
+}
+module_init(cs42l51_modinit);
+
+static void __exit cs42l51_modexit(void)
+{
+	CS42L51_DEBUG("");
+	snd_soc_unregister_dai(&cs42l51_dai);
+}
+module_exit(cs42l51_modexit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ASoC CS42l51 codec driver");
+MODULE_AUTHOR("Yuval Elmaliah <eyuval@marvell.com>");
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h
new file mode 100755
index 0000000..3dc1008
--- /dev/null
+++ b/sound/soc/codecs/cs42l51.h
@@ -0,0 +1,62 @@
+/*
+ *
+ *	Marvell Alsa SoC Codec driver
+ *
+ *	Author: Yuval Elmaliah
+ *	Copyright (C) 2008 Marvell Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef _CS42l51_H
+#define _CS42l51_H
+
+/* register assignement */
+#define   CS42L51_REG_ID                           0x1
+#define   CS42L51_REG_POWER_CNTRL                  0x2
+#define   CS42L51_REG_MIC_POWER_CNTRL              0x3
+#define   CS42L51_REG_IF_CNTRL                     0x4
+#define   CS42L51_REG_MIC_CNTRL                    0x5
+#define   CS42L51_REG_ADC_CNTRL                    0x6
+#define   CS42L51_REG_ADC_INPUT_INV_MUTE           0x7
+#define   CS42L51_REG_DAC_OUTPUT_CTRL              0x8
+#define   CS42L51_REG_DAC_CTRL                     0x9
+#define   CS42L51_REG_ALCA_PGAA_CTRL               0xa
+#define   CS42L51_REG_ALCB_PGAB_CTRL               0xb
+#define   CS42L51_REG_ADCA_ATTENUATOR              0xc
+#define   CS42L51_REG_ADCB_ATTENUATOR              0xd
+#define   CS42L51_REG_ADCA_MIXER_VOL_CNTRL         0xe
+#define   CS42L51_REG_ADCB_MIXER_VOL_CNTRL         0xf
+#define   CS42L51_REG_PCMA_MIXER_VOL_CNTRL         0x10
+#define   CS42L51_REG_PCMB_MIXER_VOL_CNTRL         0x11
+#define   CS42L51_REG_BEEP_FREQ_TIMING_CFG         0x12
+#define   CS42L51_REG_BEEP_OFF_TIME                0x13
+#define   CS42L51_REG_BEEP_TONE_CFG                0x14
+#define   CS42L51_REG_TONE_CTRL                    0x15
+#define   CS42L51_REG_VOL_OUTA_CTRL                0x16
+#define   CS42L51_REG_VOL_OUTB_CTRL                0x17
+#define   CS42L51_REG_CHANNEL_MIXER                0x18
+#define   CS42L51_REG_LIMITER_THRESHOLD            0x19
+#define   CS42L51_REG_LIMITER_RELEASE_RATE         0x1a
+#define   CS42L51_REG_LIMITER_ATTACK_RATE          0x1b
+#define   CS42L51_REG_ALC_ENABLE_ATTACK_RATE       0x1c
+#define   CS42L51_REG_ALC_RELEASE_RATE             0x1d
+#define   CS42L51_REG_ALC_THRESHOLD                0x1e
+#define   CS42L51_REG_NOISE_GATE_CFG               0x1f
+#define   CS42L51_REG_STATUS                       0x20
+#define   CS42L51_REG_CHARGE_PUMP_FREQ             0x21
+
+#define CS42L51_REG_MAX CS42L51_REG_CHARGE_PUMP_FREQ
+
+struct cs42l51_setup_data {
+	unsigned short i2c_address;
+};
+
+/* ASoC DAI */
+extern struct snd_soc_dai cs42l51_dai;
+extern struct snd_soc_codec_device soc_codec_dev_cs42l51;
+
+#endif
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100755
index 0000000..e251d7d
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,85 @@
+# kernel sources 
+srctree  := $(shell /bin/pwd)
+
+ifndef KSRC
+KSRC  := $(srctree)/..
+endif
+
+include $(KSRC)/.config
+
+CFLAGS  := $(EXTRA_CFLAGS)
+
+ifdef CONFIG_CPU_BIG_ENDIAN
+CFLAGS  += -DCONFIG_CPU_BIG_ENDIAN
+endif
+
+CC := $(CROSS_COMPILE)gcc
+LD := $(CROSS_COMPILE)ld
+
+SUBDIRS +=
+
+TARGETS=mv_shell 
+
+ifeq ($(CONFIG_MV_ETHERNET),y)
+CFLAGS += -DCONFIG_MV_ETHERNET
+endif
+
+ifeq ($(CONFIG_MV_PON),y)
+TARGETS+=mv_omci_tool
+CFLAGS += 
+endif
+ 
+ifeq ($(CONFIG_MV_ETH_LEGACY),y)
+TARGETS+=mv_eth_tool
+CFLAGS += -DCONFIG_MV_ETH_LEGACY
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_network/mv_ethernet/
+endif 
+
+ifeq ($(CONFIG_MV_CPU_PERF_CNTRS),y)
+CFLAGS += -DCONFIG_MV_CPU_PERF_CNTRS
+endif
+
+ifeq ($(CONFIG_MV_CESA),y)
+TARGETS += mv_cesa_tool
+CFLAGS  += -I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_cesa/
+endif
+
+ifeq ($(CONFIG_MV_INCLUDE_USB),y)
+TARGETS += testusb
+endif
+
+ifeq ($(CONFIG_MV_PHONE),y)
+ifeq ($(CONFIG_SILABS_SLIC_SUPPORT),y)
+SUBDIRS+=voice/silabs
+else
+#SUBDIRS+=voice/zarlink/user
+SUBDIRS+=voice/zarlink/kernel
+endif
+endif
+
+all : Makefile $(TARGETS)
+	@for subdir in $(SUBDIRS); do \
+                (cd $$subdir && $(MAKE) $@) || exit 1; \
+        done
+	
+mv_shell : mv_shell.c 
+	$(CC) $(CFLAGS) -static mv_shell.c -o mv_shell
+
+mv_eth_tool: mv_eth_tool.c
+	$(CC) $(CFLAGS) -static mv_eth_tool.c -o mv_eth_tool
+
+mv_set_coal : mv_set_coal.c
+	$(CC) $(CFLAGS) mv_set_coal.c -o mv_set_coal
+
+mv_cesa_tool:mv_cesa_tool.c
+	$(CC) $(CFLAGS) -static mv_cesa_tool.c -o mv_cesa_tool
+
+testusb: testusb.c
+	$(CC) $(CFLAGS) -static testusb.c -o testusb -lpthread
+
+clean:
+	rm -f $(TARGETS) *.o
+	@for subdir in $(SUBDIRS); do \
+                (cd $$subdir && $(MAKE) $@) || exit 1; \
+        done
+
diff --git a/tools/ethtool/README b/tools/ethtool/README
new file mode 100755
index 0000000..900d1b5
--- /dev/null
+++ b/tools/ethtool/README
@@ -0,0 +1,3 @@
+
+ethtool-6-mrv-2.patch - this patch should be use against the user-space utility ethtool-6 in order
+to have diagnostic and tuning capabilities for Marvell integrated GbE controller.
diff --git a/tools/mv_cesa_tool.c b/tools/mv_cesa_tool.c
new file mode 100755
index 0000000..20827a0
--- /dev/null
+++ b/tools/mv_cesa_tool.c
@@ -0,0 +1,307 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include "cesa_dev.h"
+
+
+
+void show_usage(int badarg)
+{
+        fprintf(stderr,
+                "Usage:                                                                                 \n"
+                " mv_cesa_tool -h                                                                       \n"
+                "   Display this help.                                                                  \n"
+                "                                                                                       \n"
+		" mv_cesa_tool -test  <test_mode> <iter> <req_size> <checkmode>				\n"
+		"	(can be used only in Test Mode)							\n"
+		"	test_mode: Multi, Size AES, DES, 3DES MD5 SHA1     				\n"
+		"	iter	 : number of iteration to run						\n"
+		"	req_size : size of the buffer to be encrypt/decrypt/HASING			\n"
+		"	checkmode: 0 - Fast verify 							\n"
+		"		   1 - Full verify						        \n"
+		"		   2 - without verify (for performence)					\n"
+		"											\n"
+		" mv_cesa_tool -test -s <iter> <req_size> <session_id> <data_id>			\n"
+		"       (can be used only in Test Mode)                                                 \n"
+		"	+++ for debug usage only +++							\n"
+		"	req_size  : size of the buffer to be encrypt/decrypt/HASING                     \n"
+		"	iter      : number of iteration to run 						\n"
+		"	session_id: which session to open out of the cesa_test session see in kernel.	\n"
+		"	data_id   : which data pattern to use out of the cesa_test session see in kernel\n"
+		"       checkmode : 0 - Fast verify                                                     \n"
+                "                   1 - Full verify                                                     \n"
+                "                   2 - without verify (for performence)                                \n"
+		"											\n"
+		" mv_cesa_tool -debug <debug_mode> [-i index] [-v] [-s size]				\n"
+		"	(Tst_req, Tst_stats and Tst_ses can be used only in Test Mode)			\n"
+		"	debug_mode: Sts       - display general status 					\n"
+		"		    Chan      - display channel index status 				\n"
+		"		    Q         - display SW Q 						\n"
+		"		    SA        - display SA index 					\n"
+		"		    SAD       - display entire SAD					\n"
+		"		    Sram - display SRAM contents					\n"
+		"		    Tst_req - display request index with buffer of size size		\n"
+		"                   Tst_stats - display test statistics                                 \n"
+		"		    Tst_ses - display session index					\n"
+		"	-i index  : index (only relevant for: Chan, SA, Tst_req and Tst_ses  \n"
+		"	-v        : verbose mode							\n"
+		"	-s size	  : buffer size (only relevant for Tst_req)				\n\n"
+	);
+
+	exit(badarg);
+}
+
+static void get_index(int argc, char **argv, CESA_DEBUG *cesa_debug)
+{
+	int j;
+	for(j = 3; j < argc; j++) {
+      		if(!strcmp(argv[j], "-i")) {
+           		j++;
+       			break;
+		}
+       	}
+  	if(!(j < argc)) {
+		fprintf(stderr,"missing/ illegal index. \n");
+		exit(1);
+	}
+     	cesa_debug->index = atoi(argv[j]);
+}
+
+static void parse_debug_cmdline(int argc, char **argv, CESA_DEBUG *cesa_debug)
+{
+	unsigned int i = 2,j;
+
+        cesa_debug->mode = 0;
+	for(j = i; j < argc; j++) {
+		if(!strcmp(argv[j], "-v"))
+			cesa_debug->mode++; 
+	}
+
+	if(argc < 3) {
+                fprintf(stderr,"missing arguments\n");
+		exit(1);
+	}
+
+	if(!strcmp(argv[i], "Sts")) 
+        	cesa_debug->debug = STATUS;
+	else if(!strcmp(argv[i], "Chan")) {
+                cesa_debug->debug = CHAN;
+		get_index(argc, argv, cesa_debug);
+	}
+        else if(!strcmp(argv[i], "Q"))
+                cesa_debug->debug = QUEUE;
+        else if(!strcmp(argv[i], "SA")) {
+                cesa_debug->debug = SA;
+		get_index(argc, argv, cesa_debug);
+	}
+        else if(!strcmp(argv[i], "Cache_idx")) {
+                cesa_debug->debug = CACHE_IDX;
+		get_index(argc, argv, cesa_debug);
+	}
+        else if(!strcmp(argv[i], "Sram"))
+                cesa_debug->debug = SRAM;
+        else if(!strcmp(argv[i], "SAD"))
+                cesa_debug->debug = SAD;
+        else if(!strcmp(argv[i], "Tst_req")) {
+                cesa_debug->debug = TST_REQ;
+        	for(j = i; j < argc; j++) {
+                	if(!strcmp(argv[j], "-s")) {
+				j++;
+                        	break;
+			}
+		}
+		if(!(j < argc)) {
+			fprintf(stderr,"missing/illegal size\n");
+			exit(1);
+		}
+		cesa_debug->size = atoi(argv[j]);
+		get_index(argc, argv, cesa_debug);
+	}
+        else if(!strcmp(argv[i], "Tst_ses")) {
+                cesa_debug->debug = TST_SES;
+		get_index(argc, argv, cesa_debug);
+	}
+	else if(!strcmp(argv[i], "Tst_stats")) {
+		cesa_debug->debug = TST_STATS;
+        }
+	else{
+		fprintf(stderr,"illegal debug option\n");
+		exit(1);
+	}
+
+}
+
+static void parse_test_cmdline(int argc, char **argv, CESA_TEST *cesa_test)
+{
+        unsigned int i = 2;
+
+	if(argc < 6) {
+        	fprintf(stderr,"missing arguments\n");
+		exit(1);
+	}
+
+	if(!strcmp(argv[i], "-s")) { /* single test */
+		i++;
+		if(argc != 8)
+                	show_usage(1);
+		cesa_test->test = SINGLE;
+		cesa_test->iter = atoi(argv[i++]);
+		cesa_test->req_size = atoi(argv[i++]);
+		cesa_test->session_id = atoi(argv[i++]);
+		cesa_test->data_id = atoi(argv[i++]);
+                cesa_test->checkmode = atoi(argv[i++]);
+	}
+        else {
+		if(argc != 6)
+                        show_usage(1);
+		if (!strcmp(argv[i], "Multi"))
+                	cesa_test->test = MULTI;
+                else if (!strcmp(argv[i], "Size"))
+                        cesa_test->test = SIZE;
+		else if(!strcmp(argv[i], "AES"))
+                        cesa_test->test = AES;
+                else if(!strcmp(argv[i], "DES"))
+                        cesa_test->test = DES;
+                else if(!strcmp(argv[i], "3DES"))
+                        cesa_test->test = TRI_DES;
+                else if(!strcmp(argv[i], "MD5"))
+                        cesa_test->test = MD5;
+                else if(!strcmp(argv[i], "SHA1"))
+                        cesa_test->test = SHA1;
+		else {
+			fprintf(stderr,"illegal test option\n");	
+			exit(1);
+		}
+		i++;	
+		cesa_test->iter = atoi(argv[i++]);
+		cesa_test->req_size = atoi(argv[i++]);
+		cesa_test->checkmode = atoi(argv[i++]);
+        }
+}
+
+
+
+int main(int argc, char *argv[])
+{
+        char *name = "/dev/cesa";
+        int fd, t, i, fdflags;
+        int rc = 0;
+	CESA_TEST	cesa_test;
+	CESA_DEBUG	cesa_debug;
+
+	memset(&cesa_test, 0, sizeof(CESA_TEST));
+	memset(&cesa_debug, 0, sizeof(CESA_DEBUG));
+
+        /* open the device */
+        fd = open(name, O_RDWR);
+        if (fd <= 0) {
+                printf("## Cannot open %s device.##\n",name);
+                exit(2);
+        }
+
+        /* set some flags */
+        fdflags = fcntl(fd,F_GETFL,0);
+        fdflags |= O_NONBLOCK;
+        fcntl(fd,F_SETFL,fdflags);
+
+        if(argc < 2) {
+                fprintf(stderr,"missing arguments\n");
+		exit(1);
+        }
+
+	i = 1;
+
+        if (!strcmp(argv[i], "-h")) {
+                show_usage(0);
+        }
+
+        else if (!strcmp(argv[i], "-test")) { /* test */
+		parse_test_cmdline(argc, argv, &cesa_test);
+		printf("test %d iter %d req_size %d checkmode %d sess_id %d data_id %d \n", 
+			cesa_test.test, cesa_test.iter, cesa_test.req_size, cesa_test.checkmode,
+			cesa_test.session_id, cesa_test.data_id );
+
+        	rc = ioctl(fd, CIOCTEST, &cesa_test);
+	}
+	else { /* debug */
+                parse_debug_cmdline(argc, argv, &cesa_debug);
+		printf("debug %d index %d mode %d size %d \n",
+			cesa_debug.debug, cesa_debug.index, cesa_debug.mode, cesa_debug.size);
+                rc = ioctl(fd, CIOCDEBUG, &cesa_debug);
+	}
+	if(rc < 0) printf("Cesa Tool failed to perform action!\n");
+
+	close(fd);
+
+	return 0;
+}
diff --git a/tools/mv_eth_tool.c b/tools/mv_eth_tool.c
new file mode 100755
index 0000000..8227b2b
--- /dev/null
+++ b/tools/mv_eth_tool.c
@@ -0,0 +1,579 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mv_eth_proc.h"
+
+extern char **environ; /* all environments */
+
+static unsigned int port = 0, q = 0, weight = 0, status = 0, mac[6] = {0,};
+static unsigned int policy =0, command = 0, packet = 0;
+static unsigned int value = 0;
+static unsigned int inport, outport, dip, sip, da[6] = {0, }, sa[6] = {0, };
+static unsigned int db_type = 0;
+
+void show_usage(int badarg)
+{
+        fprintf(stderr,
+	"Usage: 										\n"
+	" mv_eth_tool -h		       Display this help				\n"
+	"                                                                                       \n"
+	" --- Global commands ---								\n"
+        " mv_eth_tool -txdone <quota>          Set threshold to start tx_done operations       	\n"
+	" mv_eth_tool -reuse   <0|1>           SKB reuse support:   0 - Disable, 1 - Enable    	\n"
+        " mv_eth_tool -recycle <0|1>           SKB recycle support: 0 - Disable, 1 - Enable     \n"
+        " mv_eth_tool -nfp <0|1>               NFP support: 0 - Disable, 1 - Enable             \n"
+        "                                                                                       \n"
+	" --- Port commands ---                                                                 \n"
+        " mv_eth_tool -rxcoal <port> <usec>    Set RX interrupt coalescing value               	\n"
+        " mv_eth_tool -txcoal <port> <usec>    Set TX interrupt coalescing value               	\n"
+	" mv_eth_tool -txen   <port> <deep>    Set deep of lookup for TX enable race.          	\n"
+        "                                      0 - means disable.                              	\n"
+	" mv_eth_tool -ejp    <port> <0|1>     Set EJP mode: 0 - Disable, 1 - Enable           	\n"
+	" mv_eth_tool -tx_noq <idx> <0|1>      Set queuing mode: 0 - Disable, 1 - Enable        \n"
+	" mv_eth_tool -lro    <port> <0|1>     Set LRO mode: 0 - Disable, 1 - Enable           	\n"
+	" mv_eth_tool -lro_desc <port> <value> Set LRO max concurrent sessions			\n"
+	"                                                                                       \n"
+	" --- Port/Queue commands ---                                                           \n"
+	" mv_eth_tool -tos <port> <rxq> <tos>  Map TOS field to RX queue number                 \n" 
+	"                                                                                       \n"
+	" mv_eth_tool -srq <port> <rxq> <bpdu|arp|tcp|udp>                                     	\n"
+        "                                      Set RX queue number for different packet types. 	\n"
+	"                                      rxq==8 means no special treatment.		\n"
+	"		                       rxq==8 for Arp packets means drop.      		\n"
+	"                                                                                       \n"
+	" mv_eth_tool -sq <port> <rxq> <%%2x:%%2x:%%2x:%%2x:%%2x:%%2x> 				\n"
+	"                                      Set RX queue number for a Multicast MAC         	\n"
+	"                                      rxq==8 indicates delete entry.		        \n"
+        " mv_eth_tool -srp <port> <WRR|FIXED>  Set the Rx Policy to WRR or Fixed 		\n"
+	"											\n"
+	" --- NFP commands ---                                                                  \n"
+        " mv_eth_tool -fp_st                   Display NFP Status (enabled/disabled)            \n"
+        " mv_eth_tool -fprs <inp> <outp> <DIP> <SIP> <DA> <SA>					\n"
+        "                                      Set NFP rule for IPv4 routing			\n"
+        "                                      where DA, SA - MAC addresses xx:xx:xx:xx:xx:xx   \n"
+	" mv_eth_tool -fprd <DIP> <SIP>        Delete NFP Rule for IPv4 routing			\n"
+	" mv_eth_tool -fp_print <DB>           Print NFP Rule Database,                        	\n"
+        "                                      where DB is routing,nat,bridge,ppp,sec           \n"
+	"											\n"
+	" mv_eth_tool -St <option> <port>			       		                \n"
+	"   Display different status information of the port through the kernel printk.		\n"
+	"   OPTIONS:										\n"
+	"   p                                   Display General port information.		\n"
+        "   mac                                 Display MAC addresses information               \n"
+	"   q   <0..7>                          Display specific q information.			\n"
+	"   rxp                                 Display Rx Policy information.			\n"
+	"   txp                                 Display Tx Policy information.			\n"
+	"   cntrs                               Display the HW MIB counters			\n"
+	"   regs                                Display a dump of the giga registers		\n"
+	"   stats                               Display port statistics information. 		\n"
+	"   netdev                              Display net_device status information.          \n"
+	"   nfp                                 Display port NFP statistics                     \n"
+	"   tos                                 Display port TOS to RXQ mapping                 \n"
+	"   switch                              Display switch statistics                 	\n"
+        "\n"	
+        );
+        exit(badarg);
+}
+
+static void parse_pt(char *src)
+{
+        if (!strcmp(src, "bpdu"))
+        	packet = PT_BPDU;
+	else if(!strcmp(src, "arp"))
+        	packet = PT_ARP;
+	else if(!strcmp(src, "tcp"))
+        	packet = PT_TCP;
+	else if(!strcmp(src, "udp"))
+        	packet = PT_UDP;
+	else {
+		fprintf(stderr, "Illegall packet type, packet type should be bpdu/arp/tcp/udp. \n");	
+                exit(-1);
+        }
+        return;
+}
+
+static void parse_db_name(char *src)
+{
+	if (!strcmp(src, "routing") || !strcmp(src, "route"))
+		db_type = DB_ROUTING;
+	else if (!strcmp(src, "nat"))
+		db_type = DB_NAT;
+	else if (!strcmp(src, "fdb") || !strcmp(src, "bridge"))
+		db_type = DB_FDB;
+	else if (!strcmp(src, "ppp"))
+		db_type = DB_PPP;
+	else if (!strcmp(src, "sec"))
+		db_type = DB_SEC;
+	else {
+		fprintf(stderr, "Illegall DB name, expected routing|nat|bridge|ppp|sec. \n");
+		exit(-1);
+	}
+	return;
+}
+
+static void parse_port(char *src)
+{
+	int count;
+
+        count = sscanf(src, "%x",&port);
+
+        if (count != 1)  {
+		fprintf(stderr, "Port parsing error: count=%d\n", count);	
+                exit(-1);
+        }
+        return;
+}
+
+
+static void parse_q(char *src)
+{
+	int count;
+
+        count = sscanf(src, "%x",&q);
+
+        if (count != 1) {
+		fprintf(stderr, "Queue parsing error: count=%d\n", count);	
+                exit(-1);
+        }
+        return;
+}
+
+static void parse_policy(char *src)
+{
+
+        if (!strcmp(src, "WRR"))
+        	policy = WRR;
+	else if (!strcmp(src, "FIXED"))
+        	policy = FIXED;
+	else {
+		fprintf(stderr, "Illegall policy, policy can be WRR or Fixed.\n");	
+                exit(-1);
+        }
+        return;
+}
+
+static void parse_status(char *src)
+{
+    	if (!strcmp(src, "p")) {
+      		status = STS_PORT;
+      	}
+        else if (!strcmp(src, "mac")) {
+                status = STS_PORT_MAC;
+        }
+     	else if(!strcmp(src, "q")) {
+       		status = STS_PORT_Q;
+     	}
+   	else if(!strcmp(src, "rxp")) {
+          	status = STS_PORT_RXP;
+      	}
+     	else if(!strcmp(src, "txp")) {
+           	status = STS_PORT_TXP;
+      	}
+        else if(!strcmp(src, "cntrs")) {
+                status = STS_PORT_MIB;
+        }
+        else if(!strcmp(src, "regs")) {
+                status = STS_PORT_REGS;
+        }
+      	else if(!strcmp(src, "stats")) {
+             	status = STS_PORT_STATS;
+        }
+        else if(!strcmp(src, "nfp")) {
+                status = STS_PORT_NFP_STATS;
+        }
+	else if(!strcmp(src, "netdev")) {
+                status = STS_NETDEV;
+        }
+        else if(!strcmp(src, "tos")) {
+                status = STS_PORT_TOS_MAP;
+        }
+        else if(!strcmp(src, "switch")) {
+                status = STS_SWITCH_STATS;
+        }
+        else {
+                fprintf(stderr, "Illegall status %d.\n");
+                exit(-1);
+        }
+        return;
+}
+static void parse_dec_val(char *src, unsigned int* val_ptr)
+{
+    int i, count;
+
+    count = sscanf(src, "%d", val_ptr);
+    if(count != 1) {
+        fprintf(stderr, "Illegall value - should be decimal.\n");
+        exit(-1);
+    }
+    return;
+}
+
+static void parse_hex_val(char *src, unsigned int* hex_val_ptr)
+{
+    int i, count;
+
+    count = sscanf(src, "%x", hex_val_ptr);
+    if(count != 1) {
+        fprintf(stderr, "Illegall value - should be hex.\n");
+        exit(-1);
+    }
+    return;
+}
+
+static int parse_mac(char *src, unsigned int macaddr[])
+{
+        int count;
+        int i;
+        int buf[6];
+
+        count = sscanf(src, "%2x:%2x:%2x:%2x:%2x:%2x",
+                &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5]);
+
+        if (count != 6) {
+		fprintf(stderr, "MAC parsing error: Expected %%2x:%%2x:%%2x:%%2x:%%2x:%%2x.\n");
+                exit(-1);
+        }
+
+        for (i = 0; i < count; i++) {
+                macaddr[i] = buf[i];
+        }
+        return 0;
+}
+
+static int parse_ip(char *src, unsigned int* ip)
+{
+    int count, i;
+    int buf[4];
+
+    count = sscanf(src, "%d.%d.%d.%d",
+                &buf[0], &buf[1], &buf[2], &buf[3]);
+
+    if (count != 4) {
+        fprintf(stderr, "Illegall IP address (should be %%d.%%d.%%d.%%d)\n");
+        exit(-1);
+    }
+    *ip = (((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) |
+           ((buf[2] & 0xFF) << 8) | ((buf[3] & 0xFF) << 0));
+    return 0;
+}
+
+static void parse_cmdline(int argc, char **argp)
+{
+	unsigned int i = 1;
+
+	if(argc < 2) {
+		show_usage(1);
+	}
+
+	if (!strcmp(argp[i], "-h")) {
+		show_usage(0);
+	}
+	else if (!strcmp(argp[i], "-srq")) {
+		command = COM_SRQ;
+		i++;	
+		if(argc != 5)
+			show_usage(1); 
+		parse_port(argp[i++]);
+		parse_q(argp[i++]);
+		parse_pt(argp[i++]);
+	}
+	else if (!strcmp(argp[i], "-sq")) {
+		command = COM_SQ;
+		i++;
+		if(argc != 6)
+			show_usage(1); 
+		parse_port(argp[i++]);
+		parse_q(argp[i++]);
+		parse_mac(argp[i++], mac);
+	}
+	else if (!strcmp(argp[i], "-srp")) {
+		command = COM_SRP;
+		i++;
+		if(argc != 4)
+			show_usage(1); 
+		parse_port(argp[i++]);
+		parse_policy(argp[i++]);
+	}
+	else if (!strcmp(argp[i], "-srqw")) {
+		command = COM_SRQW;
+		i++;
+		if(argc != 5)
+			show_usage(1); 
+		parse_port(argp[i++]);
+		parse_q(argp[i++]);
+		parse_hex_val(argp[i++], &weight);
+	}
+    	else if (!strcmp(argp[i], "-stp")) {
+        	command = COM_STP;
+        	i++;
+        	if(argc != 6)
+            		show_usage(1);
+		parse_port(argp[i++]);
+        	parse_q(argp[i++]);
+		parse_hex_val(argp[i++], &weight);
+		parse_policy(argp[i++]);
+    	}
+    	else if (!strcmp(argp[i], "-fprs")) {
+        	command = COM_IP_RULE_SET;
+        	i++;
+        	if(argc != 8)
+            		show_usage(1);
+		parse_dec_val(argp[i++], &inport);
+        	parse_dec_val(argp[i++], &outport);
+		parse_ip(argp[i++], &dip);
+		parse_ip(argp[i++], &sip);
+        	parse_mac(argp[i++], da);
+		parse_mac(argp[i++], sa);
+    	}
+	else if (!strcmp(argp[i], "-fprd")) {
+		command = COM_IP_RULE_DEL;
+		i++;
+		if(argc != 4)
+			show_usage(1);
+		parse_ip(argp[i++], &dip);
+		parse_ip(argp[i++], &sip);
+	}
+	else if (!strcmp(argp[i], "-fp_st")) {
+		command = COM_NFP_STATUS;
+		if(argc != 2)
+			show_usage(1);
+	}
+	else if (!strcmp(argp[i], "-fp_print")) {
+		command = COM_NFP_PRINT;
+		i++;
+		if (argc != 3)
+			show_usage(1);
+		parse_db_name(argp[i++]);
+	}
+    	else if (!strcmp(argp[i], "-txdone")) {
+        	command = COM_TXDONE_Q;
+        	i++;
+		if(argc != 3)
+			show_usage(1);
+        	parse_dec_val(argp[i++], &value);
+    	}
+    	else if (!strcmp(argp[i], "-txen")) {
+                command = COM_TX_EN;
+                i++;
+		if(argc != 4)
+			show_usage(1);
+		parse_port(argp[i++]);
+                parse_dec_val(argp[i++], &value);
+        }
+	else if (!strcmp(argp[i], "-lro")) {
+		command = COM_LRO;
+		i++;
+		if(argc != 4)
+			show_usage(1);
+		parse_port(argp[i++]);
+		parse_dec_val(argp[i++], &value);
+	}
+	else if (!strcmp(argp[i], "-lro_desc")) {
+		command = COM_LRO_DESC;
+		i++;
+		if(argc != 4)
+			show_usage(1);
+		parse_port(argp[i++]);
+		parse_dec_val(argp[i++], &value);
+	}
+        else if (!strcmp(argp[i], "-reuse")) {
+                command = COM_SKB_REUSE;
+                i++;
+		if(argc != 3)
+			show_usage(1);
+                parse_dec_val(argp[i++], &value);
+        }
+        else if (!strcmp(argp[i], "-recycle")) {
+                command = COM_SKB_RECYCLE;
+                i++;
+                if(argc != 3)
+                        show_usage(1);
+                parse_dec_val(argp[i++], &value);
+        }
+        else if (!strcmp(argp[i], "-nfp")) {
+                command = COM_NFP;
+                i++;
+                if(argc != 3)
+                        show_usage(1);
+                parse_dec_val(argp[i++], &value);
+	}
+	else if (!strcmp(argp[i], "-rxcoal")) {
+        	command = COM_RX_COAL;
+        	i++;
+		if(argc != 4)
+			show_usage(1);
+        	parse_port(argp[i++]);
+        	parse_dec_val(argp[i++], &value);
+    	}
+    	else if (!strcmp(argp[i], "-txcoal")) {
+        	command = COM_TX_COAL;
+        	i++;
+		if(argc != 4)
+			show_usage(1);
+        	parse_port(argp[i++]);
+        	parse_dec_val(argp[i++], &value);
+    	}
+        else if (!strcmp(argp[i], "-ejp")) {
+                command = COM_EJP_MODE;
+                i++;
+                if(argc != 4)
+                        show_usage(1);
+                parse_port(argp[i++]);
+                parse_dec_val(argp[i++], &value);
+	}
+        else if (!strcmp(argp[i], "-tos")) {
+                command = COM_TOS_MAP;
+                i++;
+                if(argc != 5)
+                        show_usage(1);
+                parse_port(argp[i++]);
+		parse_q(argp[i++]);
+                parse_hex_val(argp[i++], &value);
+        }
+		else if (!strcmp(argp[i], "-tx_noq")) {
+				command = COM_TX_NOQUEUE;
+				i++;
+				if(argc != 4)
+						show_usage(1);
+				parse_port(argp[i++]);
+				parse_dec_val(argp[i++], &value);
+	}
+    	else if (!strcmp(argp[i], "-St")) {
+        	command = COM_STS;
+        	i++;
+		if(argc < 4)
+			show_usage(1);
+		parse_status(argp[i++]);
+		if( status == STS_PORT_Q ) {
+            		if(argc != 5)
+                		show_usage(1);
+               		parse_q(argp[i++]);
+	    	}
+            	else if(argc != 4)
+                	show_usage(1);
+	
+		parse_port(argp[i++]);
+        }	
+	else {
+		show_usage(i++);
+	}
+}
+
+static int procit(void)
+{
+  	FILE *mvethproc;
+  	mvethproc = fopen(FILE_PATH FILE_NAME, "w");
+  	if (!mvethproc) {
+    		printf ("Eror opening file %s/%s\n",FILE_PATH,FILE_NAME);
+    		exit(-1);
+  	}
+
+	switch (command) {
+		case COM_TXDONE_Q:
+		case COM_SKB_REUSE:
+	        case COM_SKB_RECYCLE:
+	  	case COM_NFP:
+			fprintf (mvethproc, ETH_CMD_STRING, ETH_PRINTF_LIST);
+			break;
+		case COM_RX_COAL:
+		case COM_TX_COAL:
+		case COM_TX_EN:
+		case COM_EJP_MODE:
+		case COM_TX_NOQUEUE:
+		case COM_LRO:
+		case COM_LRO_DESC:
+			fprintf (mvethproc, PORT_CMD_STRING, PORT_PRINTF_LIST);
+			break;
+		case COM_TOS_MAP:
+			fprintf (mvethproc, QUEUE_CMD_STRING, QUEUE_PRINTF_LIST);
+			break;
+		case COM_IP_RULE_SET:
+			fprintf(mvethproc, IP_RULE_STRING, IP_RULE_PRINT_LIST);
+			break;
+		case COM_IP_RULE_DEL:
+			fprintf(mvethproc, IP_RULE_DEL_STRING, IP_RULE_DEL_PRINT_LIST);
+			break;
+               case COM_NFP_STATUS:
+                       fprintf(mvethproc, CMD_STRING, CMD_PRINT_LIST);
+                       break;
+		case COM_NFP_PRINT:
+			fprintf(mvethproc, NFP_DB_PRINT_STRING, NFP_DB_PRINT_PRINT_LIST);
+			break;
+		default:
+			fprintf (mvethproc, PROC_STRING, PROC_PRINT_LIST);
+			break;
+	}
+
+	fclose (mvethproc);
+	return 0;
+}
+
+int main(int argc, char **argp, char **envp)
+{
+        parse_cmdline(argc, argp);
+        return procit();
+}
+
diff --git a/tools/mv_neta_tool.c b/tools/mv_neta_tool.c
new file mode 100755
index 0000000..2fe657f
--- /dev/null
+++ b/tools/mv_neta_tool.c
@@ -0,0 +1,608 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mv_eth_proc.h"
+
+extern char **environ; /* all environments */
+
+static unsigned int port = 0, txp=0, q = 0, status = 0;
+static unsigned char mac[6] = {0,};
+static unsigned int command = 0;
+static unsigned int value = 0;
+static unsigned int inport, outport, dip, sip, da[6] = {0, }, sa[6] = {0, };
+static unsigned int db_type = 0;
+static char* name = NULL;
+
+void show_usage(int badarg)
+{
+    fprintf(stderr,
+    "Usage:                                                                                         \n"
+    " mv_neta_tool -h                               Display this help                               \n"
+    "                                                       	                                    \n"
+    " --- Global commands ---                                                                       \n"
+    " mv_neta_tool -txdone <quota>                  Set threshold to start tx_done operations       \n"
+    " mv_neta_tool -skb <0 | 1>                     SKB recycle support: 0 - disabled, 1 - enabled  \n"
+    " mv_neta_tool -nfp <0 | 1>                     NFP support: 0 - disabled, 1 - enabled          \n"
+    "                                                                                       	    \n"
+    " --- NetDev commands ---                                                                       \n"
+    " mv_neta_tool -netdev_sts <name>               Print network device status                     \n"
+    " mv_neta_tool -port_add <name> <port>          Map switch port to one of network devices       \n"
+    " mv_neta_tool -port_del <name> <port>          Unmap switch port from network device           \n"
+    " mv_neta_tool -tx_noq <name> <0 | 1>           Set queuing discipline mode               	    \n"
+    "                                                                                       	    \n"
+    " --- Port commands ---                                                                         \n"
+    " mv_neta_tool -ejp     <p> <txp> <0 | 1>       Set EJP mode: 0 - Disable, 1 - Enable           \n"
+    " mv_neta_tool -txp_bw  <p> <txp> <bw>          Set TX Port Bandwidth limitation                \n"
+    "                                                                                       	    \n"
+    " --- RXQ commands ---                                                                          \n"
+    " mv_neta_tool -rxq_time_coal <p> <q> <usec>    Set RXQ interrupt coalescing value in [usec]    \n"
+    " mv_neta_tool -rxq_pkts_coal <p> <q> <pkts>    Set RXQ interrupt coalescing value in [pkts]    \n"
+    " mv_neta_tool -rxq_tos  <p> <q> <tos>          Map TOS field to RX queue number                \n" 
+    "                                                                                       	    \n"
+    " mv_neta_tool -rxq_type <p> <q> <type>         Set RXQ for different packet types	            \n"
+    "                                               Supported types: bpdu | arp | tcp | udp. 	    \n"
+    "                                                                                       	    \n"
+    " mv_neta_tool -rxq_mc   <p> <q> <mac>          Set RXQ for a Multicast MAC                     \n"
+    "                                               rxq==8 indicates delete entry.                  \n"
+    "                                                                                               \n"
+    " --- TXQ commands ---                                                                          \n"
+    " mv_neta_tool -txq_coal <p> <txp> <q> <pkts>   Set TXQ interrupt coalescing value       	    \n"
+    " mv_neta_tool -txq_tos  <p> <txp> <q> <tos>    Map TOS field to TXQ number. <txp> ignored      \n" 
+    " mv_neta_tool -txq_wrr  <p> <txp> <q> <weight> Set TXQ weight: 0 - FIXED, other - WRR          \n"
+    " mv_neta_tool -txq_bw   <p> <txp> <txq> <bw>   Set TX Queue Bandwidth limitation               \n"
+    "                                                                                               \n"
+    " mv_neta_tool -St <options>                                                                    \n"
+    "   Display different status information of the port through the kernel printk.                 \n"
+    "   OPTIONS:                                                                                    \n"
+    "   p      <port>                       Display General port information                        \n"
+    "   mac    <port>                       Display MAC addresses information                       \n"
+    "   rxq    <port> <q> <m>               Display specific RXQ information                        \n"
+    "   txq    <port> <txp> <q> <m>         Display specific TXQ information                        \n"
+    "   cntrs  <port>                       Display the HW MIB counters	                            \n"
+    "   regs   <port>                       Display a dump of the giga registers                    \n"
+    "   stats  <port>                       Display port statistics information                     \n"
+    "   tos    <port>                       Display port TOS to RXQ mapping                 	    \n"
+    "   switch <port>                       Display switch statistics                 	            \n"
+    "   wrr    <port> <txp>                 Display TX Policy information                           \n"
+    "   txp    <port> <txp>                 Display TX registers of specific TCONT                  \n"
+    "   neta   <port>                       Display Neta registers                                  \n"
+    "   gmac   <port>                       Display GMAC registers                                  \n"
+    "   rxq_r  <port>                       Display RXQ registers                                   \n"
+    "   txq_r  <port>                       Display TXQ registers                                   \n"
+    "   hwf    <port>                       Display HWF configuration registers                     \n"
+    "   bm                                  Display BM registers                                    \n"
+    "   pnc                                 Display PNC registers                                   \n"
+    "   pmt    <port> <txp>                 Display PNC registers                                   \n"
+    "                                                                                               \n"	
+    );
+    exit(badarg);
+}
+
+static void parse_pt(char *src, int* value_ptr)
+{
+	packet_t packet;
+
+        if (!strcmp(src, "bpdu"))
+        	packet = PT_BPDU;
+	else if(!strcmp(src, "arp"))
+        	packet = PT_ARP;
+	else if(!strcmp(src, "tcp"))
+        	packet = PT_TCP;
+	else if(!strcmp(src, "udp"))
+        	packet = PT_UDP;
+	else {
+		fprintf(stderr, "illegal packet type, packet type should be bpdu/arp/tcp/udp. \n");	
+     		*value_ptr = (int)PT_NONE;
+		exit(-1);
+        }
+	*value_ptr = (int)packet;
+        return;
+}
+
+static void parse_port(char *src)
+{
+	int count;
+
+        count = sscanf(src, "%x",&port);
+
+        if (count != 1)  {
+		fprintf(stderr, "Port parsing error: count=%d\n", count);	
+                exit(-1);
+        }
+        return;
+}
+
+
+static void parse_q(char *src)
+{
+	int count;
+
+        count = sscanf(src, "%x",&q);
+
+        if (count != 1) {
+		fprintf(stderr, "Queue parsing error: count=%d\n", count);	
+                exit(-1);
+        }
+        return;
+}
+
+
+static void parse_status(char *src)
+{
+    	if (!strcmp(src, "p")) {
+      		status = STS_PORT;
+      	}
+        else if (!strcmp(src, "txp")) {
+                status = STS_TXP_REGS;
+        }
+        else if (!strcmp(src, "mac")) {
+                status = STS_PORT_MAC;
+        }
+     	else if(!strcmp(src, "rxq")) {
+       		status = STS_PORT_RXQ;
+     	}
+        else if(!strcmp(src, "txq")) {
+                status = STS_PORT_TXQ;
+        }
+     	else if(!strcmp(src, "wrr")) {
+           	status = STS_TXP_WRR;
+      	}
+        else if(!strcmp(src, "cntrs")) {
+                status = STS_PORT_MIB;
+        }
+        else if(!strcmp(src, "regs")) {
+                status = STS_PORT_REGS;
+        }
+      	else if(!strcmp(src, "stats")) {
+             	status = STS_PORT_STATS;
+        }
+        else if(!strcmp(src, "tos")) {
+                status = STS_PORT_TOS_MAP;
+        }
+        else if(!strcmp(src, "switch")) {
+                status = STS_SWITCH_STATS;
+        }
+        else if(!strcmp(src, "neta")) {
+                status = STS_NETA_REGS;
+        }
+        else if(!strcmp(src, "gmac")) {
+                status = STS_GMAC_REGS;
+        }
+        else if(!strcmp(src, "rxq_r")) {
+                status = STS_RXQ_REGS;
+        }
+        else if(!strcmp(src, "txq_r")) {
+                status = STS_TXQ_REGS;
+        }
+        else if(!strcmp(src, "hwf")) {
+                status = STS_HWF_REGS;
+        }
+        else if(!strcmp(src, "bm")) {
+                status = STS_BM_REGS;
+        }
+        else if(!strcmp(src, "pnc")) {
+                status = STS_PNC_REGS;
+        } 
+        else if(!strcmp(src, "pmt")) {
+                status = STS_PMT_REGS;
+        } 
+        else {
+                fprintf(stderr, "illegal status %d.\n");
+                exit(-1);
+        }
+        return;
+}
+static void parse_dec_val(char *src, unsigned int* val_ptr)
+{
+    int count;
+
+    count = sscanf(src, "%d", val_ptr);
+    if(count != 1) {
+        fprintf(stderr, "illegal value - should be decimal.\n");
+        exit(-1);
+    }
+    return;
+}
+
+static void parse_hex_val(char *src, unsigned int* hex_val_ptr)
+{
+    int count;
+
+    count = sscanf(src, "%x", hex_val_ptr);
+    if(count != 1) {
+        fprintf(stderr, "illegal value - should be hexadecimal\n");
+        exit(-1);
+    }
+    return;
+}
+
+static int parse_mac(char *src, unsigned char macaddr[])
+{
+        int count;
+        int i;
+        int buf[6];
+
+        count = sscanf(src, "%2x:%2x:%2x:%2x:%2x:%2x",
+                &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5]);
+
+        if (count != 6) {
+		fprintf(stderr, "MAC parsing error: Expected %%2x:%%2x:%%2x:%%2x:%%2x:%%2x.\n");
+                exit(-1);
+        }
+
+        for (i = 0; i < count; i++) {
+                macaddr[i] = buf[i] & 0xFF;
+        }
+        return 0;
+}
+
+static int parse_ip(char *src, unsigned int* ip)
+{
+    int count, i;
+    int buf[4];
+
+    count = sscanf(src, "%d.%d.%d.%d",
+                &buf[0], &buf[1], &buf[2], &buf[3]);
+
+    if (count != 4) {
+        fprintf(stderr, "illegal IP address (should be %%d.%%d.%%d.%%d)\n");
+        exit(-1);
+    }
+    *ip = (((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) |
+           ((buf[2] & 0xFF) << 8) | ((buf[3] & 0xFF) << 0));
+    return 0;
+}
+
+static void parse_cmdline(int argc, char **argp)
+{
+	unsigned int i = 1;
+
+	if(argc < 2) {
+		show_usage(1);
+	}
+
+	if (!strcmp(argp[i], "-h")) {
+		show_usage(0);
+	}
+	else if (!strcmp(argp[i], "-rxq_type")) {
+		command = COM_RXQ_TYPE;
+		i++;	
+		if(argc != 5)
+			show_usage(1); 
+		parse_dec_val(argp[i++], &port);
+		parse_dec_val(argp[i++], &q);
+		parse_pt(argp[i++], &value);
+	}
+	else if (!strcmp(argp[i], "-rxq_mc")) {
+		command = COM_RXQ_MC;
+		i++;
+		if(argc != 6)
+			show_usage(1); 
+		parse_dec_val(argp[i++], &port);
+		parse_dec_val(argp[i++], &q);
+		parse_mac(argp[i++], mac);
+	}
+    	else if (!strcmp(argp[i], "-txdone")) {
+        	command = COM_TXDONE_Q;
+        	i++;
+		if(argc != 3)
+			show_usage(1);
+        	parse_dec_val(argp[i++], &value);
+    	}
+        else if (!strcmp(argp[i], "-skb")) {
+                command = COM_SKB_RECYCLE;
+                i++;
+		if(argc != 3)
+			show_usage(1);
+                parse_dec_val(argp[i++], &value);
+        }
+        else if (!strcmp(argp[i], "-netdev_sts")) {
+                command = COM_NETDEV_STS;
+                i++;
+                if(argc != 3)
+                        show_usage(1);
+                name = argp[i++];
+        } 
+		else if (!strcmp(argp[i], "-port_add")) {
+                command = COM_NETDEV_PORT_ADD;
+                i++;
+                if(argc != 4)
+                        show_usage(1);
+                name = argp[i++];
+                parse_dec_val(argp[i++], &value);
+        }
+        else if (!strcmp(argp[i], "-port_del")) {
+                command = COM_NETDEV_PORT_DEL;
+                i++;
+                if(argc != 4)
+                        show_usage(1);
+                name = argp[i++];
+                parse_dec_val(argp[i++], &value);
+        }
+       	else if (!strcmp(argp[i], "-nfp")) {
+		 if (argc == 3) {
+		 	command = COM_NFP_ENABLE;
+			i++;
+                	parse_dec_val(argp[i++], &value);
+		 }
+		 else 
+		    	show_usage(1);
+        }
+	else if (!strcmp(argp[i], "-rxq_time_coal")) {
+        	command = COM_RXQ_TIME_COAL;
+        	i++;
+		if(argc != 5)
+			show_usage(1);
+        	parse_port(argp[i++]);
+		parse_dec_val(argp[i++], &q);
+        	parse_dec_val(argp[i++], &value);
+    	}
+        else if (!strcmp(argp[i], "-txp_bw")) {
+                command = COM_TXP_BW;
+                i++;
+                if(argc != 5)
+                        show_usage(1);
+		parse_dec_val(argp[i++], &port);
+		parse_dec_val(argp[i++], &txp);
+                parse_dec_val(argp[i++], &value);
+        }
+        else if (!strcmp(argp[i], "-rxq_pkts_coal")) {
+                command = COM_RXQ_PKTS_COAL;
+                i++;
+                if(argc != 5)
+                        show_usage(1);
+                parse_dec_val(argp[i++], &port);
+                parse_dec_val(argp[i++], &q);
+                parse_dec_val(argp[i++], &value);
+        }
+    	else if (!strcmp(argp[i], "-txq_coal")) {
+        	command = COM_TXQ_COAL;
+        	i++;
+		if(argc != 6)
+			show_usage(1);
+                parse_dec_val(argp[i++], &port);
+                parse_dec_val(argp[i++], &txp);
+                parse_dec_val(argp[i++], &q);
+        	parse_dec_val(argp[i++], &value);
+    	}
+        else if (!strcmp(argp[i], "-txq_wrr")) {
+                command = COM_TXQ_WRR;
+                i++;
+                if(argc != 6)
+                        show_usage(1);
+                parse_dec_val(argp[i++], &port);
+                parse_dec_val(argp[i++], &txp);
+                parse_dec_val(argp[i++], &q);
+                parse_dec_val(argp[i++], &value);
+        }
+	else if (!strcmp(argp[i], "-txq_bw")) {
+                command = COM_TXQ_BW;
+                i++;
+                if(argc != 6)
+                        show_usage(1);
+                parse_dec_val(argp[i++], &port);
+                parse_dec_val(argp[i++], &txp);
+                parse_dec_val(argp[i++], &q);
+                parse_dec_val(argp[i++], &value);
+        }
+        else if (!strcmp(argp[i], "-ejp")) {
+                command = COM_EJP_MODE;
+                i++;
+                if(argc != 5)
+                        show_usage(1);
+				parse_dec_val(argp[i++], &port);
+				parse_dec_val(argp[i++], &txp);
+                parse_dec_val(argp[i++], &value);
+	    }
+        else if (!strcmp(argp[i], "-rxq_tos")) {
+                command = COM_RXQ_TOS_MAP;
+                i++;
+                if(argc != 5)
+                    show_usage(1);
+
+                parse_port(argp[i++]);
+		        parse_q(argp[i++]);
+                parse_hex_val(argp[i++], &value);
+        }
+        else if (!strcmp(argp[i], "-txq_tos")) {
+                command = COM_TXQ_TOS;
+                i++;
+                if(argc != 6)
+                    show_usage(1);
+
+                parse_port(argp[i++]);
+		        parse_dec_val(argp[i++], &txp);
+                parse_q(argp[i++]);
+                parse_hex_val(argp[i++], &value);
+        }
+	    else if (!strcmp(argp[i], "-tx_noq")) {
+		    command = COM_TX_NOQUEUE;
+		    i++;
+		    if(argc != 4)
+			    show_usage(1);
+		    name = argp[i++];
+		    parse_dec_val(argp[i++], &value);
+	    }
+    	else if (!strcmp(argp[i], "-St")) {
+        	command = COM_STS;
+        	i++;
+		if(argc < 3)
+			show_usage(1);
+	
+		parse_status(argp[i++]);
+		switch(status)
+		{
+		    case STS_PNC_REGS:
+		    case STS_BM_REGS:
+                	if(argc != 3)
+                       		show_usage(1);
+				break;
+
+                    case STS_TXP_REGS:
+		            case STS_TXP_WRR:
+                    case STS_PMT_REGS:
+                        if(argc != 5)
+                            show_usage(1);
+
+                        parse_dec_val(argp[i++], &port);
+                        parse_dec_val(argp[i++], &txp);
+                        break;
+			
+		    case STS_PORT_RXQ:
+		    case STS_RXQ_REGS:
+                        if(argc < 5)
+                             show_usage(1);
+
+                        parse_dec_val(argp[i++], &port);
+                        parse_dec_val(argp[i++], &q);
+		        value = 0;
+			if(argc > 5)
+				parse_dec_val(argp[i++], &value);
+                        break;
+
+		    case STS_PORT_TXQ:
+		    case STS_TXQ_REGS:
+            	        if(argc < 6)
+                	    show_usage(1);
+
+			parse_dec_val(argp[i++], &port);
+       			parse_dec_val(argp[i++], &txp);
+		        parse_dec_val(argp[i++], &q);
+                        value = 0;
+                        if(argc > 6)
+                            parse_dec_val(argp[i++], &value);
+			break;
+
+		    default:
+            		if(argc != 4)
+                		show_usage(1);
+			parse_dec_val(argp[i++], &port);
+		}
+	}
+}
+
+static int procit(void)
+{
+  	FILE *mvethproc;
+  	mvethproc = fopen(FILE_PATH FILE_NAME, "w");
+  	if (!mvethproc) {
+    		printf ("Eror opening file %s/%s\n",FILE_PATH,FILE_NAME);
+    		exit(-1);
+  	}
+
+	switch (command) {
+		case COM_TXDONE_Q:
+		case COM_SKB_RECYCLE:
+		case COM_NFP_ENABLE:
+			fprintf (mvethproc, ETH_CMD_STRING, ETH_PRINTF_LIST);
+			break;
+
+		case COM_TX_NOQUEUE:
+		case COM_NETDEV_STS:
+		case COM_NETDEV_PORT_ADD:
+		case COM_NETDEV_PORT_DEL:
+			fprintf(mvethproc, NETDEV_CMD_STRING, NETDEV_PRINTF_LIST);
+			break; 
+
+		case COM_EJP_MODE:
+		case COM_TXP_BW:
+			fprintf (mvethproc, PORT_CMD_STRING, PORT_PRINTF_LIST);
+			break;
+
+		case COM_RXQ_TOS_MAP:
+		case COM_RXQ_PKTS_COAL:
+		case COM_RXQ_TIME_COAL:
+		case COM_RXQ_TYPE:
+			fprintf (mvethproc, RXQ_CMD_STRING, RXQ_PRINTF_LIST);
+			break;
+
+        case COM_TXQ_COAL:
+		case COM_TXQ_TOS:
+		case COM_TXQ_WRR:
+		case COM_TXQ_BW:
+                        fprintf (mvethproc, TXQ_CMD_STRING, TXQ_PRINTF_LIST);
+                        break;
+
+		case COM_STS:
+			fprintf (mvethproc, STATUS_CMD_STRING, STATUS_PRINTF_LIST);
+			break;
+
+		default:
+ 			fprintf(stderr,"Unexpected command\n");
+			show_usage(2);
+			break;
+	}
+
+	fclose (mvethproc);
+	return 0;
+}
+
+int main(int argc, char **argp, char **envp)
+{
+        parse_cmdline(argc, argp);
+        return procit();
+}
+
diff --git a/tools/mv_omci_tool.c b/tools/mv_omci_tool.c
new file mode 100755
index 0000000..543bbda
--- /dev/null
+++ b/tools/mv_omci_tool.c
@@ -0,0 +1,128 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h> 
+
+int main(int argc, char* argv[])
+{
+	char buf[1024];
+	int sz, i;
+	int sk, proto = 0x9000;
+	struct sockaddr_ll socket_address; 
+
+    	if(argc >= 2) 
+       		proto = strtol(argv[1], (char **)NULL, 16);
+
+   	printf("Open Raw socket for protocol 0x%x\n", proto);
+
+    	sk = socket(AF_PACKET, SOCK_RAW, htons(proto)); 
+    	if (sk < 0) {
+		perror("open:");
+		goto out;
+    	}
+
+    do {
+
+        sz = recv(sk, buf, 1024, 0);
+        if (sz == -1) {
+            perror("recv ERROR");
+            goto out;
+        }
+        printf("read %d bytes\n", sz);
+        i = 0;
+/*
+        while(i < sz) {
+            printf("%02x ", buf[i]);
+            i++;
+            if( (i % 32) == 0)
+		printf("\n");
+        }
+	printf("\n");
+*/
+        /* Send data back */
+	socket_address.sll_family = PF_PACKET;
+	socket_address.sll_protocol = htons(proto);
+	socket_address.sll_ifindex = 2; 
+	socket_address.sll_pkttype = PACKET_OTHERHOST; 
+ 
+        sz = sendto(sk, buf, sz, 0, 
+		    (struct sockaddr*)&socket_address, sizeof(socket_address)); 
+
+        if (sz == -1) {
+            perror("send ERROR");
+            goto out;
+        }
+        printf("send %d bytes\n", sz);
+    } while (1);
+
+out:
+    if (sk > 0)
+	close(sk);
+
+    return 0;
+}
+
diff --git a/tools/mv_set_coal.c b/tools/mv_set_coal.c
new file mode 100755
index 0000000..68b6fb1
--- /dev/null
+++ b/tools/mv_set_coal.c
@@ -0,0 +1,226 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <paths.h>
+#include <stdlib.h>
+
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#define ETH_SDMA_CONFIG_REG(port)           (MV_ETH_REG_BASE(port) + 0x41c)
+#define MV_ETH_REG_BASE(port)      	(((port) == 0) ? 0x72000 : 0x82000)
+#define ETH_RX_INTR_COAL_OFFSET             7
+#define ETH_RX_INTR_COAL_ALL_MASK           (0x3fff<<ETH_RX_INTR_COAL_OFFSET)
+#define ETH_RX_INTR_COAL_MASK(value)        (((value)<<ETH_RX_INTR_COAL_OFFSET)  \
+                                             & ETH_RX_INTR_COAL_ALL_MASK)
+
+#define ETH_TX_FIFO_URGENT_THRESH_REG(port) (MV_ETH_REG_BASE(port) + 0x474)
+#define ETH_TX_INTR_COAL_OFFSET             4
+
+
+mv_reg_read(unsigned int reg)
+{
+    unsigned int value;
+    FILE *resource_dump;
+
+    resource_dump = fopen ("/proc/resource_dump" , "w");
+    if (!resource_dump) {
+      printf ("Eror opening file /proc/resource_dump\n");
+      exit(-1);
+    }
+    fprintf (resource_dump,"register  r %08x",reg);
+    fclose (resource_dump);
+    resource_dump = fopen ("/proc/resource_dump" , "r");
+    if (!resource_dump) {
+      printf ("Eror opening file /proc/resource_dump\n");
+      exit(-1);
+    }
+    fscanf (resource_dump , "%x" , &value);
+    fclose (resource_dump);
+
+    return value;
+}
+
+void
+mv_reg_write(unsigned int reg, unsigned int value)
+{
+    FILE *resource_dump;
+
+    resource_dump = fopen ("/proc/resource_dump" , "w");
+    if (!resource_dump) {
+      printf ("Eror opening file /proc/resource_dump\n");
+      exit(-1);
+    }
+    fprintf (resource_dump,"register  w %08x %08x",reg,value);
+    fclose (resource_dump);
+    return;
+}
+
+/*******************************************************************************
+* mvEthRxCoalSet  - Sets coalescing interrupt mechanism on RX path
+*
+* DESCRIPTION:
+*       This routine sets the RX coalescing interrupt mechanism parameter.
+*       This parameter is a timeout counter, that counts in 64 tClk
+*       chunks, that when timeout event occurs a maskable interrupt occurs.
+*       The parameter is calculated using the tCLK frequency of the
+*       MV-64xxx chip, and the required number is in micro seconds.
+*
+* INPUT:
+*       MV_U32          uSec        - Number of micro seconds between 
+*                                   RX interrupts
+*
+* RETURN:
+*       None.
+*
+* COMMENT:     
+*   1 sec           - TCLK_RATE clocks
+*   1 uSec          - TCLK_RATE / 1,000,000 clocks
+*
+*   Register Value for N micro seconds -  ((N * ( (TCLK_RATE / 1,000,000)) / 64)
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+unsigned int    mvEthRxCoalSet (unsigned int uSec) 
+{ 
+    unsigned int	  port = 0;
+    unsigned int 	  Tclk = 166000000;
+    unsigned int          coal = ((uSec * ( Tclk / 1000000)) / 64);
+    unsigned int          portSdmaCfgReg;
+
+    portSdmaCfgReg =  mv_reg_read(ETH_SDMA_CONFIG_REG(port));
+    portSdmaCfgReg &= ~ETH_RX_INTR_COAL_ALL_MASK;
+    portSdmaCfgReg |= (ETH_RX_INTR_COAL_MASK(coal));
+    mv_reg_write(ETH_SDMA_CONFIG_REG(port), portSdmaCfgReg);
+    return coal;
+}
+
+/*******************************************************************************
+* mvEthTxCoalSet - Sets coalescing interrupt mechanism on TX path
+*
+* DESCRIPTION:
+*       This routine sets the TX coalescing interrupt mechanism parameter.
+*       This parameter is a timeout counter, that counts in 64 tClk
+*       chunks, that when timeout event occurs a maskable interrupt
+*       occurs.
+*       The parameter is calculated using the tCLK frequency of the
+*       MV-64xxx chip, and the required number is in micro seconds.
+*
+* INPUT:
+*       MV_U32          uSec        - Number of micro seconds between 
+*                                   RX interrupts
+*
+* RETURN:
+*       None.
+*
+* COMMENT:     
+*   1 sec           - TCLK_RATE clocks
+*   1 uSec          - TCLK_RATE / 1,000,000 clocks
+*
+*   Register Value for N micro seconds -  ((N * ( (TCLK_RATE / 1,000,000)) / 64)
+*
+*******************************************************************************/
+unsigned int    mvEthTxCoalSet(unsigned int uSec) 
+{
+    unsigned int          port = 0;
+    unsigned int          Tclk = 166000000;
+    unsigned int          coal = ((uSec * (Tclk / 1000000)) / 64);
+
+    /* Set TX Coalescing mechanism */
+    mv_reg_write (ETH_TX_FIFO_URGENT_THRESH_REG(port), 
+                  (coal << ETH_TX_INTR_COAL_OFFSET));
+    return coal;
+}
+
+int
+main(int argc, char **argv)
+{
+        unsigned int direct,usec;
+
+        if (argc == 3) {
+                sscanf(argv[1], "%x", &direct);
+                sscanf(argv[2], "%x", &usec);
+        }else{ printf ("Usage: mv_set_coal <direction 0-Rx 1-Tx> <coal in micro sec>\n");
+                return 0;
+        }
+
+        if(direct == 0)
+		mvEthRxCoalSet(usec);		
+	else
+		mvEthTxCoalSet(usec);
+
+        return 1;
+}
+
diff --git a/tools/mv_shell.c b/tools/mv_shell.c
new file mode 100755
index 0000000..7011c5d
--- /dev/null
+++ b/tools/mv_shell.c
@@ -0,0 +1,456 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <stdio.h>
+
+#define DEBUG
+
+char str[256];
+
+/*************************************************************************************/
+
+void show_help(void) {
+  printf("\n-----------\n");
+  printf("rr reg       - register read, used to read a register\n");
+  printf("rw reg value - register write, used to write a value to a register\n");
+  printf("md offset    - memory dump, used to dump 128 bytes in memory\n");
+  printf("mw reg value - memory write, used to write a value to a physical memory\n");
+#if defined (CONFIG_MV_ETHERNET) || defined (CONFIG_MV_GATEWAY)
+  printf("sr dev_addr reg - smi register read, used to read a Switch or Phy register\n");
+  printf("sw dev_addr reg value - smi register write, used to write a 16-bit value to a Switch or Phy register\n");
+#endif
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+  printf("cchelp\n");
+  printf("tcc cc0_type cc1_type cc2_type cc3_type - trigger cpu counter capture \n");
+  printf("dcc - display cpu counters \n");
+#endif
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+  printf("l2help\n");
+  printf("tl2 l20_type l21_type - trigger cpu l2 counter capture \n");
+  printf("dl2 - display cpu l2 counters \n");
+#endif
+
+  printf("quit - exit from tool\n");
+  printf("-----------\n");
+}
+
+void show_counters_help(void) {
+    int i = 1;
+    printf("cpu counter type can be one of the below, make sure no error is recieved\n");
+    printf("for example: tcc 11 2 1 4\n");
+    printf("%d: MV_CPU_CNTRS_CYCLES\n",i++);
+    printf("%d: MV_CPU_CNTRS_ICACHE_READ_MISS\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_ACCESS\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_READ_MISS\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_READ_HIT\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_WRITE_MISS\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_WRITE_HIT\n",i++);
+    printf("%d: MV_CPU_CNTRS_DTLB_MISS\n",i++);
+    printf("%d: MV_CPU_CNTRS_TLB_MISS\n",i++);
+    printf("%d: MV_CPU_CNTRS_ITLB_MISS\n",i++);
+    printf("%d: MV_CPU_CNTRS_INSTRUCTIONS\n",i++);
+    printf("%d: MV_CPU_CNTRS_SINGLE_ISSUE\n",i++);
+    printf("%d: MV_CPU_CNTRS_MMU_READ_LATENCY\n",i++);
+    printf("%d: MV_CPU_CNTRS_MMU_READ_BEAT\n",i++);
+    printf("%d: MV_CPU_CNTRS_BRANCH_RETIRED\n",i++);
+    printf("%d: MV_CPU_CNTRS_BRANCH_TAKEN\n",i++);
+    printf("%d: MV_CPU_CNTRS_BRANCH_PREDICT_MISS\n",i++);
+    printf("%d: MV_CPU_CNTRS_BRANCH_PREDICT_COUNT\n",i++);
+    printf("%d: MV_CPU_CNTRS_WB_FULL_CYCLES\n",i++);
+    printf("%d: MV_CPU_CNTRS_WB_WRITE_LATENCY\n",i++);
+    printf("%d: MV_CPU_CNTRS_WB_WRITE_BEAT\n",i++);
+    printf("%d: MV_CPU_CNTRS_ICACHE_READ_LATENCY\n",i++);
+    printf("%d: MV_CPU_CNTRS_ICACHE_READ_BEAT\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_READ_LATENCY\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_READ_BEAT\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_WRITE_LATENCY\n",i++);
+    printf("%d: MV_CPU_CNTRS_DCACHE_WRITE_BEAT\n",i++);
+    printf("%d: MV_CPU_CNTRS_LDM_STM_HOLD\n",i++);
+    printf("%d: MV_CPU_CNTRS_IS_HOLD\n",i++);
+    printf("%d: MV_CPU_CNTRS_DATA_WRITE_ACCESS\n",i++);
+    printf("%d: MV_CPU_CNTRS_DATA_READ_ACCESS\n",i++);
+    printf("%d: MV_CPU_CNTRS_BIU_SIMULT_ACCESS\n",i++);
+    printf("%d: MV_CPU_CNTRS_BIU_ANY_ACCESS\n",i++);
+}
+
+void show_l2_counters_help(void) {
+    int i = 1;
+    printf("cpu l2 counter type can be one of the below, make sure no error is recieved\n");
+    printf("%d: MV_CPU_L2_CNTRS_DATA_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_DATA_MISS_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_INST_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_INST_MISS_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_DATA_READ_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_DATA_READ_MISS_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_DATA_WRITE_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_DATA_WRITE_MISS_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_RESERVED\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_DIRTY_EVICT_REQ\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_EVICT_BUFF_STALL\n",i++);
+    printf("%d: MV_CPU_L2_CNTRS_ACTIVE_CYCLES\n",i++);
+}
+/*************************************************************************************/
+
+void gt_reg_read(unsigned int rgst) {
+  unsigned int reg = rgst, value;
+  char ch;
+  FILE *resource_dump,*output;
+
+  output = fopen ("./xxx.out","w");
+  if (!output) { printf ("Cannot open file\n");return;}
+
+  while (1){ 
+    resource_dump = fopen ("/proc/resource_dump" , "w");
+    if (!resource_dump) {
+      printf ("Error opening file /proc/resource_dump\n");
+      exit(-1);
+    }
+    fprintf (resource_dump,"register  r %08x",reg);
+    fclose (resource_dump);
+    resource_dump = fopen ("/proc/resource_dump" , "r");
+    if (!resource_dump) {
+      printf ("Error opening file /proc/resource_dump\n");
+      exit(-1);
+    }
+    fscanf (resource_dump , "%x" , &value);
+    fclose (resource_dump);
+    printf ("%08x : %08x ",reg,value);
+
+    if (!fgets (str, 255, stdin)) {
+     printf ("Error in reading line from stdin\n");
+      exit (-1);
+    }
+    if (str[0] == '.') break;
+    reg += 4;
+  
+  }
+}
+
+/*************************************************************************************/
+#if defined (CONFIG_MV_ETHERNET) || defined (CONFIG_MV_GATEWAY)
+
+void gt_smi_reg_read(unsigned int dev_addr, unsigned int rgst) {
+  unsigned int reg = rgst, value;
+  char ch;
+  FILE *resource_dump,*output;
+
+  output = fopen ("./xxx.out","w");
+  if (!output) { printf ("Cannot open file\n");return;}
+
+  while (1){ 
+    resource_dump = fopen ("/proc/resource_dump" , "w");
+    if (!resource_dump) {
+      printf ("Error opening file /proc/resource_dump\n");
+      exit(-1);
+    }
+    fprintf (resource_dump,"smi  r %08x %08x", dev_addr, reg);
+    fclose (resource_dump);
+    resource_dump = fopen ("/proc/resource_dump" , "r");
+    if (!resource_dump) {
+      printf ("Error opening file /proc/resource_dump\n");
+      exit(-1);
+    }
+    fscanf (resource_dump , "%x" , &value);
+    fclose (resource_dump);
+    printf ("SMI Device: %08x, Reg: %08x, Data: %08x ", dev_addr, reg, value);
+
+    if (!fgets (str, 255, stdin)) {
+     printf ("Error in reading line from stdin\n");
+      exit (-1);
+    }
+    if (str[0] == '.') break;
+    reg += 1;
+  
+  }
+}
+
+/*************************************************************************************/
+
+void gt_smi_reg_write(unsigned int dev_addr, unsigned int rgst, unsigned int vlue) {
+  unsigned int reg = rgst, value = vlue;
+  unsigned int element;
+  char ch;
+  FILE *resource_dump;
+  resource_dump = fopen ("/proc/resource_dump" , "w");
+  if (!resource_dump) {
+    printf ("Eror opening file /proc/resource_dump\n");
+    exit(-1);
+  }
+  fprintf (resource_dump,"smi  w %08x %08x %08x", dev_addr, reg, value);
+  fclose (resource_dump);
+}
+#endif
+/*************************************************************************************/
+
+void gt_mem_dump(unsigned int rgst) {
+  unsigned int offset = rgst, value , i , j;
+  char ch;
+  FILE *resource_dump;
+  FILE *output;
+  output = fopen ("./xxx.out","w");
+  if (!output) { printf ("Canot open file\n");return;}
+  i = 0;
+  while (1) {
+    if (i == 0) printf ("\n");
+    printf ("%08x : ",offset);
+    for (j = 0 ; j < 8 ; j++) {
+      resource_dump = fopen ("/proc/resource_dump" , "w");
+      if (!resource_dump) {
+	printf ("Eror opening file /proc/resource_dump\n");
+	exit(-1);
+      }
+
+      fprintf (resource_dump,"memory    r %08x",offset);
+      fclose (resource_dump);
+      resource_dump = fopen ("/proc/resource_dump" , "r");
+      if (!resource_dump) {
+	printf ("Eror opening file /proc/resource_dump\n");
+	exit(-1);
+      }
+      fscanf (resource_dump , "%x" , &value);
+      fclose (resource_dump);
+            printf ("%08x ",value);
+      
+      {
+	unsigned int temp;
+	temp = ((value & 0xff) << 24) |
+	  ((value & 0xff00) << 8) |
+	  ((value & 0xff0000) >> 8) |
+	  ((value & 0xff000000) >> 24);
+	value = temp;
+      }
+      fprintf (output, "%c",value & 0xff);
+      value = value >> 8;
+      fprintf (output, "%c",value & 0xff);
+      value = value >> 8;
+      fprintf (output, "%c",value & 0xff);
+      value = value >> 8;
+      fprintf (output, "%c",value & 0xff);
+      value = value >> 8;
+
+      offset += 4;
+      }
+      if (!fgets (str, 255, stdin)) {
+	printf ("Error in reading line from stdin\n");
+	exit (-1);
+      }
+      if (str[0] == '.') break;
+      i ++;
+
+  }
+  fclose (output);
+  printf ("\n");
+}
+
+/*************************************************************************************/
+
+void gt_mem_write(unsigned int rgst, unsigned int vlue) {
+  unsigned int reg = rgst, value = vlue;
+  unsigned int element;
+  char ch;
+  FILE *resource_dump;
+  resource_dump = fopen ("/proc/resource_dump" , "w");
+  if (!resource_dump) {
+    printf ("Eror opening file /proc/resource_dump\n");
+    exit(-1);
+  }
+  fprintf (resource_dump,"memory    w %08x %08x",reg,value);
+  fclose (resource_dump);
+}
+
+/*************************************************************************************/
+
+void gt_reg_write(unsigned int rgst, unsigned int vlue) {
+  unsigned int reg = rgst, value = vlue;
+  unsigned int element;
+  char ch;
+  FILE *resource_dump;
+  resource_dump = fopen ("/proc/resource_dump" , "w");
+  if (!resource_dump) {
+    printf ("Eror opening file /proc/resource_dump\n");
+    exit(-1);
+  }
+  fprintf (resource_dump,"register  w %08x %08x",reg,value);
+  fclose (resource_dump);
+}
+
+/*************************************************************************************/
+
+int main(void) {
+  unsigned int dev, reg , value , offset , element;
+  char inst[256];
+  char value_s[10];
+  printf ("\n\n\n*******\nWelcome to the GT Shell environment\n\n");
+  printf ("Write 'help' for getting help on the instructions\n");
+  while (1) {
+    memset (str , 0 , 256);
+    memset (inst , 0 , 256);
+    printf ("MV Shell -> ");
+    if (!fgets (str, 255, stdin)) {
+      printf ("Error in reading line from stdin\n");
+      exit (-1);
+    }
+    element = sscanf (str , "%s" , inst);
+    if (element == 0) continue;
+    offset = strlen (inst);
+    if (!strcmp (inst , "quit")) break;
+    
+    if (!strcmp (inst , "rr")) {
+      element = sscanf (str+offset , "%x" , &reg);
+      if (element == 1) gt_reg_read (reg);
+      else printf ("Insufficient parameters\n");
+    }
+    else if (!strcmp (inst , "rw")) {
+      element = sscanf (str+offset , "%x %x" , &reg , &value);
+      if (element == 2) gt_reg_write (reg,value);
+      else printf ("Insufficient parameters\n");
+    }
+    else if (!strcmp (inst , "help")) {
+      show_help();
+    }
+    else if (!strcmp (inst , "md")) {
+      element = sscanf (str+offset , "%x" , &reg);
+      if (element == 1) gt_mem_dump (reg);
+      else printf ("Insufficient parameters\n");
+    }
+    else if (!strcmp (inst , "mw")) {
+      element = sscanf (str+offset , "%x %x" , &reg , &value);
+      if (element == 2) gt_mem_write (reg,value);
+      else printf ("Insufficient parameters\n");
+    }
+#if defined (CONFIG_MV_ETHERNET) || defined (CONFIG_MV_GATEWAY)
+    else if (!strcmp (inst , "sr")) {
+      element = sscanf (str+offset , "%x %x %x" , &dev, &reg);
+      if (element == 2) gt_smi_reg_read (dev, reg);
+      else printf ("Insufficient parameters\n");
+    }
+    else if (!strcmp (inst , "sw")) {
+      element = sscanf (str+offset , "%x %x %x" , &dev, &reg , &value);
+      if (element == 3) gt_smi_reg_write (dev, reg, value);
+      else printf ("Insufficient parameters\n");
+    }
+#endif
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+   else if (!strcmp (inst , "cchelp")) {
+	show_counters_help();
+   }
+   else if (!strcmp (inst , "tcc")) {
+	int cc0, cc1, cc2, cc3;
+  	FILE *resource_dump;
+  	resource_dump = fopen ("/proc/resource_dump" , "w");
+  	if (!resource_dump) {
+    		printf ("Eror opening file /proc/resource_dump\n");
+    		exit(-1);
+  	}
+	sscanf(str + 3," %d %d %d %d", &cc0, &cc1, &cc2, &cc3);
+  	fprintf (resource_dump,"start_cc %d %d %d %d",cc0, cc1, cc2, cc3);
+  	fclose (resource_dump);
+   }
+   else if (!strcmp (inst , "dcc")) {
+  	FILE *resource_dump;
+  	resource_dump = fopen ("/proc/resource_dump" , "w");
+  	if (!resource_dump) {
+    		printf ("Eror opening file /proc/resource_dump\n");
+    		exit(-1);
+  	}
+  	fprintf (resource_dump,"show__cc");
+  	fclose (resource_dump);
+   }
+#endif
+#ifdef CONFIG_MV_CPU_PERF_CNTRS
+   else if (!strcmp (inst , "l2help")) {
+	show_l2_counters_help();
+   }
+   else if (!strcmp (inst , "tl2")) {
+	int l20, l21;
+  	FILE *resource_dump;
+  	resource_dump = fopen ("/proc/resource_dump" , "w");
+  	if (!resource_dump) {
+    		printf ("Eror opening file /proc/resource_dump\n");
+    		exit(-1);
+  	}
+	sscanf(str + 3," %d %d", &l20, &l21);
+  	fprintf (resource_dump,"start_l2 %d %d",l20, l21);
+  	fclose (resource_dump);
+   }
+   else if (!strcmp (inst , "dl2")) {
+  	FILE *resource_dump;
+  	resource_dump = fopen ("/proc/resource_dump" , "w");
+  	if (!resource_dump) {
+    		printf ("Eror opening file /proc/resource_dump\n");
+    		exit(-1);
+  	}
+  	fprintf (resource_dump,"show__l2");
+  	fclose (resource_dump);
+   }
+#endif
+
+    else if (strlen (str) != 0) printf ("Invalid command - %s\n",inst);
+  }
+  printf ("Good Bye\n");
+  
+}
+
+/*************************************************************************************/
+
diff --git a/tools/testusb.c b/tools/testusb.c
new file mode 100755
index 0000000..9dbbd91
--- /dev/null
+++ b/tools/testusb.c
@@ -0,0 +1,429 @@
+/* $(CROSS_COMPILE)cc -Wall -g -lpthread -o testusb testusb.c */
+
+/*
+ * Copyright (c) 2002 by David Brownell
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define __user
+
+#include <stdio.h>
+#include <string.h>
+#include <ftw.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <linux/usbdevice_fs.h>
+
+/*-------------------------------------------------------------------------*/
+
+#define	TEST_CASES	30
+
+// FIXME make these public somewhere; usbdevfs.h?
+
+struct usbtest_param {
+	// inputs
+	unsigned		test_num;	/* 0..(TEST_CASES-1) */
+	unsigned		iterations;
+	unsigned		length;
+	unsigned		vary;
+	unsigned		sglen;
+
+	// outputs
+	struct timeval		duration;
+};
+#define USBTEST_REQUEST	_IOWR('U', 100, struct usbtest_param)
+
+/*-------------------------------------------------------------------------*/
+
+/* #include <linux/usb_ch9.h> */
+
+struct usb_device_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u16 bcdUSB;
+	__u8  bDeviceClass;
+	__u8  bDeviceSubClass;
+	__u8  bDeviceProtocol;
+	__u8  bMaxPacketSize0;
+	__u16 idVendor;
+	__u16 idProduct;
+	__u16 bcdDevice;
+	__u8  iManufacturer;
+	__u8  iProduct;
+	__u8  iSerialNumber;
+	__u8  bNumConfigurations;
+} __attribute__ ((packed));
+
+enum usb_device_speed {
+	USB_SPEED_UNKNOWN = 0,			/* enumerating */
+	USB_SPEED_LOW, USB_SPEED_FULL,		/* usb 1.1 */
+	USB_SPEED_HIGH				/* usb 2.0 */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static char *speed (enum usb_device_speed s)
+{
+	switch (s) {
+	case USB_SPEED_UNKNOWN:	return "unknown";
+	case USB_SPEED_LOW:	return "low";
+	case USB_SPEED_FULL:	return "full";
+	case USB_SPEED_HIGH:	return "high";
+	default:		return "??";
+	}
+}
+
+struct testdev {
+	struct testdev		*next;
+	char			*name;
+	pthread_t		thread;
+	enum usb_device_speed	speed;
+	unsigned		ifnum : 8;
+	unsigned		forever : 1;
+	int			test;
+
+	struct usbtest_param	param;
+};
+static struct testdev		*testdevs;
+
+static int is_testdev (struct usb_device_descriptor *dev)
+{
+	/* FX2 with (tweaked) bulksrc firmware */
+	if (dev->idVendor == 0x0547 && dev->idProduct == 0x1002)
+		return 1;
+
+	/*----------------------------------------------------*/
+
+	/* devices that start up using the EZ-USB default device and
+	 * which we can use after loading simple firmware.  hotplug
+	 * can fxload it, and then run this test driver.
+	 *
+	 * we return false positives in two cases:
+	 * - the device has a "real" driver (maybe usb-serial) that
+	 *   renumerates.  the device should vanish quickly.
+	 * - the device doesn't have the test firmware installed.
+	 */
+
+	/* generic EZ-USB FX controller */
+	if (dev->idVendor == 0x0547 && dev->idProduct == 0x2235)
+		return 1;
+
+	/* generic EZ-USB FX2 controller */
+	if (dev->idVendor == 0x04b4 && dev->idProduct == 0x8613)
+		return 1;
+
+	/* CY3671 development board with EZ-USB FX */
+	if (dev->idVendor == 0x0547 && dev->idProduct == 0x0080)
+		return 1;
+
+	/* Keyspan 19Qi uses an21xx (original EZ-USB) */
+	if (dev->idVendor == 0x06cd && dev->idProduct == 0x010b)
+		return 1;
+
+	/*----------------------------------------------------*/
+
+	/* "gadget zero", Linux-USB test software */
+	if (dev->idVendor == 0x0525 && dev->idProduct == 0xa4a0)
+		return 1;
+
+	/* user mode subset of that */
+	if (dev->idVendor == 0x0525 && dev->idProduct == 0xa4a4)
+		return 1;
+
+	/* iso version of usermode code */
+	if (dev->idVendor == 0x0525 && dev->idProduct == 0xa4a3)
+		return 1;
+
+	/* some GPL'd test firmware uses these IDs */
+
+	if (dev->idVendor == 0xfff0 && dev->idProduct == 0xfff0)
+		return 1;
+
+	/*----------------------------------------------------*/
+
+	/* iBOT2 high speed webcam */
+	if (dev->idVendor == 0x0b62 && dev->idProduct == 0x0059)
+		return 1;
+
+	return 0;
+}
+
+static int find_testdev (const char *name, const struct stat *sb, int flag)
+{
+	int				fd;
+	struct usb_device_descriptor	dev;
+
+	if (flag != FTW_F)
+		return 0;
+	/* ignore /proc/bus/usb/{devices,drivers} */
+	if (strrchr (name, '/')[1] == 'd')
+		return 0;
+
+	if ((fd = open (name, O_RDONLY)) < 0) {
+		perror ("can't open dev file r/o");
+		return 0;
+	}
+	if (read (fd, &dev, sizeof dev) != sizeof dev)
+		fputs ("short devfile read!\n", stderr);
+	else if (is_testdev (&dev)) {
+		struct testdev		*entry;
+
+		if ((entry = calloc (1, sizeof *entry)) == 0) {
+			fputs ("no mem!\n", stderr);
+			goto done;
+		}
+		entry->name = strdup (name);
+		if (!entry->name) {
+			free (entry);
+			goto done;
+		}
+
+		// FIXME better to look at each interface and ask if it's
+		// bound to 'usbtest', rather than assume interface 0
+		entry->ifnum = 0;
+
+		// FIXME ask usbfs what speed; update USBDEVFS_CONNECTINFO
+		// so it tells about high speed etc
+
+		fprintf (stderr, "%s speed\t%s\n",
+				speed (entry->speed), entry->name);
+
+		entry->next = testdevs;
+		testdevs = entry;
+	}
+
+done:
+	close (fd);
+	return 0;
+}
+
+static int
+usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
+{
+	struct usbdevfs_ioctl	wrapper;
+
+	wrapper.ifno = ifno;
+	wrapper.ioctl_code = request;
+	wrapper.data = param;
+
+	return ioctl (fd, USBDEVFS_IOCTL, &wrapper);
+}
+
+static void *handle_testdev (void *arg)
+{
+	struct testdev		*dev = arg;
+	int			fd, i;
+	int			status;
+
+	if ((fd = open (dev->name, O_RDWR)) < 0) {
+		perror ("can't open dev file r/w");
+		return 0;
+	}
+
+restart:
+	for (i = 0; i < TEST_CASES; i++) {
+		if (dev->test != -1 && dev->test != i)
+			continue;
+		dev->param.test_num = i;
+
+		status = usbdev_ioctl (fd, dev->ifnum,
+				USBTEST_REQUEST, &dev->param);
+		if (status < 0 && errno == EOPNOTSUPP)
+			continue;
+
+		/* FIXME need a "syslog it" option for background testing */
+
+		/* NOTE: each thread emits complete lines; no fragments! */
+		if (status < 0) {
+			char	buf [80];
+			int	err = errno;
+
+			if (strerror_r (errno, buf, sizeof buf)) {
+				snprintf (buf, sizeof buf, "error %d", err);
+				errno = err;
+			}
+			printf ("%s test %d --> %d (%s)\n",
+				dev->name, i, errno, buf);
+		} else
+			printf ("%s test %d, %4d.%.06d secs\n", dev->name, i,
+				(int) dev->param.duration.tv_sec,
+				(int) dev->param.duration.tv_usec);
+
+		fflush (stdout);
+	}
+	if (dev->forever)
+		goto restart;
+
+	close (fd);
+	return arg;
+}
+
+int main (int argc, char **argv)
+{
+	int			c;
+	struct testdev		*entry;
+	char			*device;
+	int			all = 0, forever = 0, not = 0;
+	int			test = -1 /* all */;
+	struct usbtest_param	param;
+
+	/* pick defaults that works with all speeds, without short packets.
+	 *
+	 * Best per-frame data rates:
+	 *     high speed, bulk       512 * 13 * 8 = 53248
+	 *                 interrupt 1024 *  3 * 8 = 24576
+	 *     full speed, bulk/intr   64 * 19     =  1216
+	 *                 interrupt   64 *  1     =    64
+	 *      low speed, interrupt    8 *  1     =     8
+	 */
+	param.iterations = 1000;
+	param.length = 512;
+	param.vary = 512;
+	param.sglen = 32;
+
+	/* for easy use when hotplugging */
+	device = getenv ("DEVICE");
+
+	while ((c = getopt (argc, argv, "D:ac:g:hns:t:v:")) != EOF)
+	switch (c) {
+	case 'D':	/* device, if only one */
+		device = optarg;
+		continue;
+	case 'a':	/* use all devices */
+		device = 0;
+		all = 1;
+		continue;
+	case 'c':	/* count iterations */
+		param.iterations = atoi (optarg);
+		if (param.iterations < 0)
+			goto usage;
+		continue;
+	case 'g':	/* scatter/gather entries */
+		param.sglen = atoi (optarg);
+		if (param.sglen < 0)
+			goto usage;
+		continue;
+	case 'l':	/* loop forever */
+		forever = 1;
+		continue;
+	case 'n':	/* no test running! */
+		not = 1;
+		continue;
+	case 's':	/* size of packet */
+		param.length = atoi (optarg);
+		if (param.length < 0)
+			goto usage;
+		continue;
+	case 't':	/* run just one test */
+		test = atoi (optarg);
+		if (test < 0)
+			goto usage;
+		continue;
+	case 'v':	/* vary packet size by ... */
+		param.vary = atoi (optarg);
+		if (param.vary < 0)
+			goto usage;
+		continue;
+	case '?':
+	case 'h':
+	default:
+usage:
+		fprintf (stderr, "usage: %s [-an] [-D dev]\n"
+			"\t[-c iterations]  [-t testnum]\n"
+			"\t[-s packetsize] [-g sglen] [-v vary]\n",
+			argv [0]);
+		return 1;
+	}
+	if (optind != argc)
+		goto usage;
+	if (!all && !device) {
+		fprintf (stderr, "must specify '-a' or '-D dev', "
+			"or DEVICE=/proc/bus/usb/BBB/DDD in env\n");
+		goto usage;
+	}
+
+	if ((c = open ("/proc/bus/usb/devices", O_RDONLY)) < 0) {
+		fputs ("usbfs files are missing\n", stderr);
+		return -1;
+	}
+
+	/* collect and list the test devices */
+	if (ftw ("/proc/bus/usb", find_testdev, 3) != 0) {
+		fputs ("ftw failed; is usbfs missing?\n", stderr);
+		return -1;
+	}
+
+	/* quit, run single test, or create test threads */
+	if (!testdevs && !device) {
+		fputs ("no test devices recognized\n", stderr);
+		return -1;
+	}
+	if (not)
+		return 0;
+	if (testdevs && testdevs->next == 0 && !device)
+		device = testdevs->name;
+	for (entry = testdevs; entry; entry = entry->next) {
+		int	status;
+
+		entry->param = param;
+		entry->forever = forever;
+		entry->test = test;
+
+		if (device) {
+			if (strcmp (entry->name, device))
+				continue;
+			return handle_testdev (entry) != entry;
+		}
+		status = pthread_create (&entry->thread, 0, handle_testdev, entry);
+		if (status) {
+			perror ("pthread_create");
+			continue;
+		}
+	}
+	if (device) {
+		struct testdev		dev;
+
+		/* kernel can recognize test devices we don't */
+		fprintf (stderr, "%s: %s may see only control tests\n",
+				argv [0], device);
+
+		memset (&dev, 0, sizeof dev);
+		dev.name = device;
+		dev.param = param;
+		dev.forever = forever;
+		dev.test = test;
+		return handle_testdev (&dev) != &dev;
+	}
+
+	/* wait for tests to complete */
+	for (entry = testdevs; entry; entry = entry->next) {
+		void	*retval;
+
+		if (pthread_join (entry->thread, &retval))
+			perror ("pthread_join");
+		/* testing errors discarded! */
+	}
+
+	return 0;
+}
diff --git a/tools/tsutool/Makefile b/tools/tsutool/Makefile
new file mode 100755
index 0000000..a7e58cd
--- /dev/null
+++ b/tools/tsutool/Makefile
@@ -0,0 +1,34 @@
+# kernel sources 
+srctree  := $(shell /bin/pwd)
+
+ifndef KSRC
+KSRC  := $(srctree)/../..
+endif
+
+include $(KSRC)/.config
+
+ifdef CONFIG_CPU_BIG_ENDIAN
+CC := armeb-mv5sft-linux-gnueabi-gcc
+LD := armeb-mv5sft-linux-gnueabi-ld
+CFLAGS  += -DCONFIG_CPU_BIG_ENDIAN
+else
+CC := arm-mv5sft-linux-gnueabi-gcc
+LD := arm-mv5sft-linux-gnueabi-ld
+endif
+CFLAGS  := $(EXTRA_CFLAGS) -static
+CFLAGS  += -I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_tsu/
+
+SRCS := mv_tsu_tool.c
+OBJS := mv_tsu_tool.o
+
+TARGET := mvTsuTool
+
+default :
+	$(CC) $(CFLAGS) $(SRCS) -o $(TARGET)
+
+clean:
+	rm -f $(TARGET) $(OBJS)
+
+
+all : clean default
+
diff --git a/tools/tsutool/mv_tsu_tool.c b/tools/tsutool/mv_tsu_tool.c
new file mode 100755
index 0000000..7696e76
--- /dev/null
+++ b/tools/tsutool/mv_tsu_tool.c
@@ -0,0 +1,769 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <string.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+
+#include "mv_tsu_ioctl.h"
+
+
+/*
+ Usage:
+	TsuTool <device> <read/write> <file> <options>
+*/
+
+
+#define BUFSIZE		2048
+#define TIMESTAMP_SIZE	4
+#define TSU_TOOL_STAMP	0x4D52564C
+#define FILE_HDR_SIZE	64
+
+#define READ 		1
+#define WRITE 		0
+
+char 			*util_name;
+char 			*data_buff = NULL;
+
+int 			g_is_read = -1;
+struct tsu_buff_info 	g_buff_info;
+int			g_raw_mode = 0;
+int			g_b2b_mode = 0;
+int			g_auto_ts_mode = 0;
+int 			retry_on_fail = 0;
+int 			g_data_blk_sz = 0;	// Actual block size <= g_buf_size
+int			g_buf_size =0;		// Buffer size
+unsigned int 		g_frequency = -1;
+FILE 			*g_stat_fd = NULL;
+int 			g_ts_data_size = 0;
+int 			g_tms_data_size = 0;
+
+void data_read(int dev_fd, FILE *file_fd);
+void data_write(int dev_fd, FILE *file_fd);
+int get_buff_info(int dev_fd);
+
+void usage(void)
+{
+	fprintf(stderr,"Usage: %s <device> <r/w> <file> <options>\n",util_name);
+	fprintf(stderr,"<file> can be set to stdout.\n");
+	fprintf(stderr,"Where <options> are:\n");
+	fprintf(stderr,"-r <tms file>: Write / Read data in raw TS format.\n"
+	       "               <tms file> is the file that holds / will hold the timestamp information.\n");
+	fprintf(stderr,"-f <freq>: The frequency at which data is to be received / transmitted.\n"
+	       "           In Rx mode, this is mandatory.\n"
+	       "           In Tx mode, this will override the file header frequency.\n");
+	fprintf(stderr,"-b: Transmit the TS file in Back-to-Back mode, no timestamps are needed.\n");
+	fprintf(stderr,"-a: Enable automatic timestamp mode, timestamps are generated by TS driver.\n");
+	exit(1);
+}
+
+/*
+ * Helper function for printing the TSU statistics.
+ */
+void tsu_print_stat(struct tsu_stat *stat)
+{
+	fprintf(stderr,"\tTS Interface Error Interrupts: %d.\n",stat->ts_if_err);
+	fprintf(stderr,"\tTS Fifo Overflow Interrupts: %d.\n",stat->fifo_ovfl);
+	fprintf(stderr,"\tTS Clock Sync Expired Interrupts: %d.\n",stat->clk_sync_exp);
+	fprintf(stderr,"\tTS Connection Error Interrupts: %d.\n",stat->ts_conn_err);
+	fprintf(stderr,"\n");
+}
+
+int main(int argc, char *argv[])
+{
+	char *dev_name;
+	char *file_name;
+	int dev_fd = 0;
+	FILE *file_fd = NULL;
+	int cnt = 0;
+	struct tsu_stat tsu_stat;
+
+	/* Eecutable name.		*/
+	util_name = argv[cnt++];
+
+	if(argc < 4) {
+		if(argc > 1)
+			fprintf(stderr,"Missing parameters.\n");
+		usage();
+	}
+
+	/* Device name			*/
+	dev_name = argv[cnt++];
+
+	/* Read / Write operation.	*/
+	if(!strcmp(argv[cnt],"r")) {
+		g_is_read = 1;
+	} else if(!strcmp(argv[cnt],"w")) {
+		g_is_read = 0;
+	} else {
+		fprintf(stderr,"Bad read / write option.\n");
+		usage();
+	}
+	cnt++;
+
+	/* Open the device.		*/
+	if(g_is_read)
+		dev_fd = open(dev_name, O_RDONLY);
+	else
+		dev_fd = open(dev_name, O_WRONLY);
+
+	if(dev_fd <= 0) {
+		fprintf(stderr,"%s - Cannot open device %s.\n",util_name,dev_name);
+		exit(2);
+	}
+
+	/* Input / Output file name.	*/
+	file_name = argv[cnt++];
+	if(g_is_read) {
+		if(!strncmp(file_name,"stdout",strlen("stdout")))
+			file_fd = stdout;
+	else
+			file_fd = fopen(file_name, "w+");
+	}else{
+		file_fd = fopen(file_name, "r");
+	}
+	if(file_fd == NULL) {
+		fprintf(stderr,"%s - Cannot open file %s.\n",util_name,file_name);
+		goto error;
+	}
+
+	if(get_buff_info(dev_fd) < 0){
+		fprintf(stderr,"%s - Failed to retrieve device buffer configuration.\n");
+		goto error;
+	}
+
+	/* Allocate buffer.		*/
+	data_buff = malloc(g_buf_size);
+	if(data_buff == NULL) {
+		fprintf(stderr,"%s - Failed to allocate memory (%d Bytes).\n",util_name,
+		       BUFSIZE);
+		goto error;
+	}
+
+	if(process_options(argc,argv,cnt,dev_fd) < 0) {
+		fprintf(stderr,"Bad options.\n");
+		goto error;
+	}
+
+	/* Clear statistics.			*/
+	if(ioctl(dev_fd,MVTSU_IOCCLEARSTAT,0) < 0) {
+		fprintf(stderr,"Error Clearing statistics.\n");
+		goto error;
+	}
+
+	if(g_is_read)
+		data_read(dev_fd,file_fd);
+	else
+		data_write(dev_fd,file_fd);
+
+	/* Print statistics.			*/
+	if(ioctl(dev_fd,MVTSU_IOCGETSTAT,&tsu_stat) < 0) {
+		fprintf(stderr,"Error Printing statistics.\n");
+		goto error;
+	}
+	tsu_print_stat(&tsu_stat);
+
+error:
+	if(dev_fd != 0)
+		close(dev_fd);
+	if(file_fd != NULL)
+		fclose(file_fd);
+	if(data_buff != NULL)
+		free(data_buff);
+	if(g_stat_fd != NULL)
+		fclose(g_stat_fd);
+	return 0;
+}
+
+
+int check_write_file_device_params(struct tsu_buff_info *buff_info)
+{
+	if(!g_raw_mode) {
+		/* buffer configuration for input data & TSU must match.*/
+		if(buff_info->aggr_mode == g_buff_info.aggr_mode) {
+			if((g_buff_info.aggr_mode == aggrMode1) &&
+			   (g_buff_info.aggr_num_packets !=
+			    buff_info->aggr_num_packets)) {
+				fprintf(stderr,"Mismtach in Num of Aggregation packets (%d, %d).\n",
+				       g_buff_info.aggr_num_packets,
+				       buff_info->aggr_num_packets);
+				return -1;
+			}
+			if((g_buff_info.aggr_mode == aggrMode2) &&
+			   (g_buff_info.aggr_mode2_tmstmp_off !=
+			    buff_info->aggr_mode2_tmstmp_off)) {
+				fprintf(stderr,"Mismtach in Aggregation Timestamp offset (%d, %d).\n",
+				       g_buff_info.aggr_mode2_tmstmp_off,
+				       buff_info->aggr_mode2_tmstmp_off);
+				return -1;
+			}
+		}
+
+		if(buff_info->aggr_mode != g_buff_info.aggr_mode) {
+			if(g_buff_info.aggr_mode == aggrMode1){
+				fprintf(stderr,"Device configured in aggregation mode 1 while file is not.\n");
+				return -1;
+			}
+			if(buff_info->aggr_mode == aggrMode1) {
+				fprintf(stderr,"File configured in aggregation mode 1 while port is not.\n");
+				return -1;
+			}
+			/* File @ mode2, Device @ Aggr-Disabled.	*/
+			if((buff_info->aggr_mode == aggrMode2) &&
+			   (buff_info->aggr_mode2_tmstmp_off != TIMESTAMP_SIZE)) {
+				fprintf(stderr,"File is in aggr-mode-2 mode with timestamp "
+				       "offset != 4, and device is at aggr-dis mode.\n");
+				return -1;
+			}
+
+			/* Device @ mode2, File @ Aggr-Disabled.	*/
+			if((g_buff_info.aggr_mode == aggrMode2) &&
+			   (g_buff_info.aggr_mode2_tmstmp_off != TIMESTAMP_SIZE)) {
+				fprintf(stderr,"Device is in aggr-mode-2 mode with timestamp "
+				       "offset != 4, and file is at aggr-dis mode.\n");
+				return -1;
+			}
+		}
+	}
+	return 0;
+}
+
+
+int single_read_write(int is_read, int fd, char *buf, int count)
+{
+	int tmp = 0;
+	int ret;
+
+	while(tmp < count) {
+
+		if(is_read) {
+			ret = read(fd,buf + tmp,count - tmp);
+                } else {
+			ret = write(fd,buf + tmp,count - tmp);
+		}
+
+		if(ret <= 0)
+			return ret;
+		tmp += ret;
+	}
+	return count;
+}
+
+
+int single_fread_fwrite(int is_read, FILE *fd, char *buf, int count)
+{
+	int tmp = 0;
+	int ret;
+
+	while(tmp < count) {
+
+		if(is_read) {
+			ret = fread(buf + tmp,1,count - tmp,fd);
+                } else {
+			ret = fwrite(buf + tmp,1,count - tmp,fd);
+		}
+
+		if(ret <= 0)
+			return ret;
+		tmp += ret;
+	}
+	return count;
+}
+
+
+void setup_buffer_timestamps(char *buff, int *s_offs, int *init_tms,int *new_size)
+{
+	int i;
+	int total_diffs = 0;
+	int first_tms = -1;
+	int tmp;
+
+	memcpy(&first_tms,buff,TIMESTAMP_SIZE);
+	*init_tms = first_tms;
+
+	if(g_buff_info.aggr_mode == aggrMode1) {
+		/* Calculate the timestamp interval.		*/
+		memcpy(&tmp,
+		       buff + ((g_buff_info.aggr_num_packets - 1) * TIMESTAMP_SIZE),
+		       TIMESTAMP_SIZE);
+		total_diffs = tmp - first_tms;
+		total_diffs = total_diffs / (g_buff_info.aggr_num_packets - 1);
+
+		/* Copy timestamp interval	*/
+		memcpy(buff + (g_buff_info.aggr_num_packets - 2) * TIMESTAMP_SIZE,
+		       &total_diffs,TIMESTAMP_SIZE);
+
+		/* Copy initial timestamp	*/
+		memcpy(buff + (g_buff_info.aggr_num_packets - 1) * TIMESTAMP_SIZE,
+		       &first_tms,TIMESTAMP_SIZE);
+
+		*s_offs = (g_buff_info.aggr_num_packets - 2) * TIMESTAMP_SIZE;
+		*new_size -= (*s_offs);
+	} else {
+		*s_offs = 0;
+	}
+	return;
+}
+
+
+void data_write(int dev_fd, FILE *file_fd)
+{
+	int cnt;
+	FILE *fd;
+	int tmp;
+	int s_offs, e_offs;
+	int pkt_size;
+	int first_write = 1;
+	struct tsu_buff_info buff_info;
+	int init_tms;
+	unsigned int freq;
+
+	if(!g_b2b_mode && !g_auto_ts_mode) {
+		/* Read TS info from file header.		*/
+		/* pktsize mode aggr_pkts_num tmstmp_offset	*/
+		if(!g_raw_mode)
+			fd = file_fd;
+		else
+			fd = g_stat_fd;
+
+		if(fread(data_buff,1,FILE_HDR_SIZE,fd) < FILE_HDR_SIZE) {
+			fprintf(stderr,"Failed to read file information header.\n");
+			return;
+		}
+
+		sscanf(data_buff,"%d %d %d %d %d %d",&tmp,&pkt_size,&buff_info.aggr_mode,
+		       &buff_info.aggr_num_packets,&buff_info.aggr_mode2_tmstmp_off,
+		       &freq);
+		if(tmp != TSU_TOOL_STAMP) {
+			fprintf(stderr,"Bad stamp at file header (0x%x).\n",tmp);
+			return;
+		}
+
+		/* If user did not specify a frequency for TX, take the file frequency.	*/
+		if(g_frequency == -1)
+			g_frequency = freq;
+
+		if(pkt_size != g_buff_info.pkt_size) {
+			fprintf(stderr,"File Packet size (%d) & TSU packet size (%d) do not match.\n",
+			       pkt_size,g_buff_info.pkt_size);
+			return;
+		}
+
+		if(check_write_file_device_params(&buff_info) < 0)
+			return;
+	}
+
+	/* Calculate the values of g_ts_data_size & g_tms_data_size.	*/
+	if(g_raw_mode) {
+		if(g_buff_info.aggr_mode == aggrMode1) {
+			g_ts_data_size =
+				(g_buff_info.pkt_size *
+				 g_buff_info.aggr_num_packets);
+			g_tms_data_size = (TIMESTAMP_SIZE *
+					   g_buff_info.aggr_num_packets);
+		}
+		else if(g_buff_info.aggr_mode == aggrMode2) {
+			g_ts_data_size = g_buff_info.pkt_size;
+			g_tms_data_size = TIMESTAMP_SIZE;
+		}
+		else { /* Aggregation disabled.	*/
+			g_ts_data_size = g_buff_info.pkt_size;
+			g_tms_data_size = TIMESTAMP_SIZE;
+		}
+	} else {
+		g_ts_data_size = g_data_blk_sz;
+		g_tms_data_size = 0;
+	}
+
+	/* Setup Tx frequency.		*/
+        if(ioctl(dev_fd,MVTSU_IOCFREQSET,&g_frequency) < 0) {
+		fprintf(stderr,"Error configuring port frequency.\n");
+		goto done;
+	}
+#if 0
+	printf("g_ts_data_size = %d, g_data_blk_sz = %d.\n",
+	       g_ts_data_size,g_tms_data_size);
+#endif
+	while(1) {
+		cnt = 0;
+		s_offs = 0;
+		e_offs = 0;
+		while(cnt < g_data_blk_sz) {
+//			printf("cnt = %d, ",cnt);
+			if(g_tms_data_size) {
+				if(g_buff_info.aggr_mode == aggrMode2) {
+					e_offs += (g_buff_info.aggr_mode2_tmstmp_off -
+						   g_tms_data_size);
+					cnt += (g_buff_info.aggr_mode2_tmstmp_off -
+						   g_tms_data_size);
+				}
+//				printf("sread %d, ",g_tms_data_size);
+				tmp = single_fread_fwrite(READ,g_stat_fd,data_buff + e_offs,
+							g_tms_data_size);
+				if(tmp != g_tms_data_size) {
+					fprintf(stderr,"Error reading from timestamp file.\n");
+					goto done;
+				}
+                                e_offs += tmp;
+				cnt += tmp;
+			}
+
+//			printf("dread %d, ",g_ts_data_size);
+			tmp = single_fread_fwrite(READ,file_fd,data_buff + e_offs,
+						g_ts_data_size);
+			if(tmp < 0) {
+				fprintf(stderr,"Error reading from source file.\n");
+				goto done;
+			}
+			if(tmp == 0) {
+				/* No more input.	*/
+				goto done;
+			}
+			e_offs += tmp;
+			cnt += tmp;
+                        setup_buffer_timestamps(data_buff,&s_offs,&init_tms,&cnt);
+		}
+
+		if(first_write) {
+			struct tsu_tmstmp_info tms_info;
+			tms_info.enable_tms = !g_b2b_mode;
+			tms_info.timestamp = init_tms;
+			if(ioctl(dev_fd,MVTSU_IOCTXTMSSET,&tms_info) < 0) {
+				fprintf(stderr,"Cannot set initial timestamp for TX operation.\n");
+				goto done;
+			}
+			first_write = 0;
+		}
+
+//		printf("twrite %d.\n",g_data_blk_sz);
+		cnt = single_read_write(WRITE,dev_fd,data_buff + s_offs,
+					g_data_blk_sz);
+		if(cnt <= 0) {
+			fprintf(stderr,"Error writing to target device.\n");
+			break;
+		}
+	}
+
+done:
+	/* tell device that tx is over.		*/
+	if(ioctl(dev_fd,MVTSU_IOCTXDONE,0) < 0) {
+		fprintf(stderr,"Error in TX-Done IOCTL.\n");
+		return;
+	}
+        return;
+}
+
+void data_read(int dev_fd, FILE *file_fd)
+{
+	int cnt = 0;
+	int tmp;
+	int offs = 0;
+	int drop = 10;
+
+	/* Write TS info the file header.		*/
+	/* pktsize mode aggr_pkts_num tmstmp_offset	*/
+	sprintf(data_buff,"%d %d %d %d %d %d",
+		TSU_TOOL_STAMP,g_buff_info.pkt_size,g_buff_info.aggr_mode,
+		g_buff_info.aggr_num_packets,
+		g_buff_info.aggr_mode2_tmstmp_off, g_frequency);
+	tmp = strlen(data_buff);
+	while(tmp < FILE_HDR_SIZE)
+		data_buff[tmp++] = ' ';
+	data_buff[tmp] = '\0';
+
+	if(!g_raw_mode)
+		cnt = fwrite(data_buff,1,strlen(data_buff),file_fd);
+	else
+		cnt = fwrite(data_buff,1,strlen(data_buff),g_stat_fd);
+
+	if(cnt != strlen(data_buff)) {
+		fprintf(stderr,"Error wrting file header.\n");
+		return;
+        }
+
+	/* Calculate the values of g_ts_data_size & g_tms_data_size.	*/
+	if(g_raw_mode) {
+		if(g_buff_info.aggr_mode == aggrMode1) {
+			g_ts_data_size =
+				(g_buff_info.pkt_size *
+				 g_buff_info.aggr_num_packets);
+			g_tms_data_size = (TIMESTAMP_SIZE *
+					   g_buff_info.aggr_num_packets);
+		}
+		else if(g_buff_info.aggr_mode == aggrMode2) {
+			g_ts_data_size = g_buff_info.pkt_size;
+			g_tms_data_size = g_buff_info.aggr_mode2_tmstmp_off;
+		}
+		else { /* Aggregation disabled.	*/
+			g_ts_data_size = g_buff_info.pkt_size;
+			g_tms_data_size = TIMESTAMP_SIZE;
+		}
+	} else {
+		g_ts_data_size = g_data_blk_sz;
+		g_tms_data_size = 0;
+	}
+
+	/* Setup frequency.		*/
+        if(ioctl(dev_fd,MVTSU_IOCFREQSET,&g_frequency) < 0) {
+		fprintf(stderr,"Error configuring port frequency.\n");
+		goto done;
+	}
+
+//	fprintf(stderr,"g_raw_mode = %d, g_ts_data_size = %d, g_tms_data_size = %d.\n",
+//	       g_raw_mode, g_ts_data_size,g_tms_data_size);
+	cnt = 0;
+	while(1) {
+
+		if(offs != 0)
+			fprintf(stderr,"offs = %d.\n");
+		tmp = single_read_write(READ,dev_fd,data_buff + offs,
+					g_data_blk_sz - offs);
+		if(tmp < 0) {
+			fprintf(stderr,"Error reading from source device / file.\n");
+			break;
+		}
+		if(drop) {
+			drop--;
+			continue;
+		}
+
+		cnt += tmp;
+		if(cnt == 0)
+			break;
+		while(cnt >= (g_ts_data_size + g_tms_data_size)) {
+ //                       fprintf(stderr,"cnt - %d, ",cnt);
+			tmp = 0;
+			if(g_tms_data_size > 0) {
+				if(g_buff_info.aggr_mode == aggrMode2) {
+//					fprintf(stderr,"TMSW = %d, ",offs);
+					/* write only the timestamp part.	*/
+					tmp = single_fread_fwrite(WRITE,g_stat_fd,
+								  data_buff + offs,
+						    TIMESTAMP_SIZE);
+					if(tmp < TIMESTAMP_SIZE) {
+						fprintf(stderr,"Error writing to timestamps file.\n");
+						goto done;
+					}
+				} else {
+					tmp = single_fread_fwrite(WRITE,g_stat_fd,
+								data_buff + offs,
+								g_tms_data_size);
+					if(tmp < g_tms_data_size) {
+						fprintf(stderr,"Error writing to timestamps file.\n");
+						goto done;
+					}
+				}
+
+				offs += tmp;
+			}
+//			fprintf(stderr,"TSDW = %d.\n",offs);
+			tmp = single_fread_fwrite(WRITE,file_fd,data_buff + offs,
+						g_ts_data_size);
+			if(tmp < g_ts_data_size) {
+				fprintf(stderr,"Error writing to data file.\n");
+				goto done;
+			}
+			offs += g_ts_data_size;
+			cnt -= (g_ts_data_size + g_tms_data_size);
+		}
+
+		if(cnt > 0) {
+			memmove(data_buff,data_buff + offs, cnt);
+			offs = cnt;
+		}
+		else {
+			offs = 0;
+		}
+	}
+done:
+	return;
+}
+
+
+int get_buff_info(int dev_fd)
+{
+	char *tmp;
+
+	if(ioctl(dev_fd,MVTSU_IOCBUFFPARAMGET,&g_buff_info) < 0){
+		fprintf(stderr,"Error reading device buffer information.\n");
+		return -1;
+	}
+
+	if(g_buff_info.aggr_mode == aggrMode1) {
+		if(g_is_read)
+			g_data_blk_sz = ((g_buff_info.pkt_size + TIMESTAMP_SIZE) *
+					 g_buff_info.aggr_num_packets);
+		else
+			g_data_blk_sz = ((g_buff_info.pkt_size *
+					  g_buff_info.aggr_num_packets) +
+					 (2 * TIMESTAMP_SIZE));
+		g_buf_size = ((g_buff_info.pkt_size + TIMESTAMP_SIZE) *
+			      g_buff_info.aggr_num_packets);
+		tmp = "Mode 1";
+	} else if(g_buff_info.aggr_mode == aggrMode2) {
+		g_data_blk_sz = ((g_buff_info.pkt_size +
+				  g_buff_info.aggr_mode2_tmstmp_off) *
+				 g_buff_info.aggr_num_packets);
+		g_buf_size = g_data_blk_sz;
+		tmp = "Mode 2";
+	} else {
+		g_data_blk_sz = (g_buff_info.pkt_size + TIMESTAMP_SIZE);
+		g_buf_size = g_data_blk_sz;
+		tmp = "Disabled";
+	}
+#if 0
+	fprintf(stderr,"\n");
+        fprintf(stderr,"\tPacket Size: %d Bytes\n",g_buff_info.pkt_size);
+	fprintf(stderr,"\tAggregation %s\n",tmp);
+	if(g_buff_info.aggr_mode != aggrModeDisabled)
+		fprintf(stderr,"\tAggregation packets: %d.\n",g_buff_info.aggr_num_packets);
+	if(g_buff_info.aggr_mode == aggrMode2)
+		fprintf(stderr,"\tAggregation Timestamp offset: %d.\n",
+		       g_buff_info.aggr_mode2_tmstmp_off);
+#endif
+//	fprintf(stderr,"\tCalculated data buffer size: %d Bytes.\n",g_buf_size);
+//	fprintf(stderr,"\tCalculated data-block size: %d Bytes.\n",g_data_blk_sz);
+	return 0;
+}
+
+
+int process_options(int argc, char *argv[],int idx,int dev_fd)
+{
+	char *stat_file = NULL;
+
+	while(idx < argc) {
+		if(argv[idx][0] != '-')
+			goto error;
+		switch (argv[idx][1]) {
+		case 'r':
+			g_raw_mode = 1;
+			stat_file = argv[idx+1];
+			idx+=2;
+			break;
+		case 'f':
+			g_frequency = atoi(argv[idx+1]);
+			idx+=2;
+			break;
+		case 'b':
+			g_raw_mode = 1;
+			g_b2b_mode = 1;
+			stat_file = "/dev/zero";
+			idx += 1;
+			break;
+		case 'a':
+			g_auto_ts_mode = 1;
+			g_raw_mode = 1;
+			stat_file = "/dev/zero";
+			idx += 1;
+			break;
+		default:
+			goto error;
+		}
+	}
+
+	if(g_b2b_mode && g_is_read) {
+		fprintf(stderr,"%s - Cannot work in Back-To-Back mode in read direction.",
+		       util_name);
+		goto error;
+	}
+
+	if(g_raw_mode) {
+		if(g_is_read)
+                        g_stat_fd = fopen(stat_file, "w+");
+		else
+                        g_stat_fd = fopen(stat_file, "r");
+		if(g_stat_fd == NULL){
+			fprintf(stderr,"%s - Cannot open file %s.\n",util_name,stat_file);
+			goto error;
+		}
+	}
+
+	if(g_is_read || g_auto_ts_mode) {
+		if(g_frequency == -1) {
+			fprintf(stderr,
+				"%s - Must provide data frequency (For Rx & auto timestamp mode).\n",util_name);
+			goto error;
+		}
+	}
+
+	if(g_auto_ts_mode) {
+		if(ioctl(dev_fd,MVTSU_IOCAUTOTMS,&g_auto_ts_mode) < 0) {
+			fprintf(stderr,"Error enabling auto timestamp mode.\n");
+			goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	return -1;
+}
diff --git a/tools/voice/silabs/Makefile b/tools/voice/silabs/Makefile
new file mode 100755
index 0000000..1832f85
--- /dev/null
+++ b/tools/voice/silabs/Makefile
@@ -0,0 +1,58 @@
+# kernel sources 
+srctree  := $(shell /bin/pwd)
+
+ifndef KSRC
+KSRC  := $(srctree)/../../..
+endif
+
+include $(KSRC)/.config
+
+CFLAGS  := $(EXTRA_CFLAGS)
+
+ifdef CONFIG_CPU_BIG_ENDIAN
+CFLAGS  += -DCONFIG_CPU_BIG_ENDIAN
+endif
+
+CC := $(CROSS_COMPILE)gcc
+LD := $(CROSS_COMPILE)ld
+AR := $(CROSS_COMPILE)ar
+
+#CFLAGS += -I$(KSRC)/tools/voice/
+
+ifeq ($(CONFIG_SILABS_SLIC_SUPPORT),y)
+TARGETS += siapi_lib.o
+LIBS := libsiapi.a
+TOOL := mv_voice_tool.c
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/arch_marvell/
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/inc
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_hal/voiceband/slic/silabs/custom/
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/test/
+
+ifeq ($(CONFIG_SILAB_SLIC_SI3217x),y)
+ CFLAGS += -DSI3217x
+endif
+ifeq ($(CONFIG_SILAB_SLIC_SI3226x),y)
+ CFLAGS += -DSI3226x
+endif
+
+ifeq ($(CONFIG_MV_TDM_USE_DCO),y)
+ CFLAGS += -DMV_TDM_USE_DCO
+endif
+
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/test/
+
+all:
+	$(CC) $(CFLAGS) -static -c silabs_lib.c -o $(TARGETS)
+	$(AR) rcs $(LIBS) $(TARGETS)
+	$(CC) $(CFLAGS) -static $(PROFILE) $(TOOL) -L. $(LIBS) -o mv_voice_tool
+
+mv_voice_tool: $(PROFILE) $(TOOL)
+	$(CC) $(CFLAGS) -static $(PROFILE) $(TOOL) -L. $(LIBS) -o mv_voice_tool
+
+clean:
+	rm -f *.o *.a mv_voice_tool
+	@for subdir in $(SUBDIRS); do \
+                (cd $$subdir && $(MAKE) $@) || exit 1; \
+        done
+endif #CONFIG_SILABS_SLIC_SUPPORT
diff --git a/tools/voice/silabs/mv_voice_tool.c b/tools/voice/silabs/mv_voice_tool.c
new file mode 100755
index 0000000..fc5c46a
--- /dev/null
+++ b/tools/voice/silabs/mv_voice_tool.c
@@ -0,0 +1,1335 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include "tdm/test/tdm_dev.h"
+
+#include "silabs_lib.h"
+
+#if defined(SI3217x)
+/* SILABS si3217x */
+#include "si3217x_constants.h"
+#define MAX_DEVICES		1
+#define MAX_DEVICE_LINES	1
+#define MAX_LINES		1
+
+#elif defined(SI3226x)
+/* SILABS si3226x */
+#include "si3226x_constants.h"
+#define MAX_DEVICES		1
+#define MAX_DEVICE_LINES	2
+#define MAX_LINES		2
+#endif
+
+#define TOOL_PREFIX		">> "
+#define TIMEOUT			11000 /* usec */
+/* Line calibration increases init time significantly */
+#define LINE_CALIBRATION_SUPPORT
+
+/* Defines */
+#define GET_DEVICE(line_id)	(line_id/MAX_DEVICE_LINES)
+#define GET_LINE(line_id)	(line_id % MAX_DEVICE_LINES)
+#define N_A			0
+#define ON_HOOK			0
+#define OFF_HOOK		1
+#define CH_BUFF_SIZE		(80 * pcm_bytes)
+#define BUFF_ADDR(buff, line)	((unsigned char*)buff + (line*80*pcm_bytes))
+
+/* GLobals */
+static unsigned short total_lines = 0;
+static unsigned short total_devs = 0;
+static unsigned char pcm_bytes = 0;
+static unsigned char cal_devs = 0;
+#ifdef LINE_CALIBRATION_SUPPORT
+static unsigned short cal_lines = 0;
+#endif
+static unsigned char time_slot_table[MAX_LINES];
+static unsigned char hook_state[MAX_LINES];
+static char dev_name[] = "/dev/tdm";
+static int buff_size = 0;
+static unsigned char aud_buf[2][320 * MAX_LINES];
+static unsigned short f1Mem = 0;
+static unsigned short f2Mem = 0;
+static int offhook_count = 0;
+static unsigned int event_count = 0;
+static int tdm_fd = 0;
+static unsigned char data_buff[MAX_SLIC_RDWR_BUFF_SIZE];
+static unsigned int data_buff_ram[3];
+static int slic_init = 0;
+
+/* sin table, 256 points */
+static short sinTbl[] = {0,402,804,1205,1606,2005,2404,2801,3196,3590,3981,4370,4756,
+5139,5519,5896,6270,6639,7005,7366,7723,8075,8423,8765,9102,9433,9759,10079,10393,
+10701,11002,11297,11585,11865,12139,12405,12664,12915,13159,13394,13622,13841,14052,
+14255,14449,14634,14810,14977,15136,15285,15425,15556,15678,15790,15892,15985,16068,
+16142,16206,16260,16304,16339,16363,16378,16383,16378,16363,16339,16304,16260,16206,
+16142,16068,15985,15892,15790,15678,15556,15425,15285,15136,14977,14810,14634,14449,
+14255,14052,13841,13622,13394,13159,12915,12664,12405,12139,11865,11585,11297,11002,
+10701,10393,10079,9759,9433,9102,8765,8423,8075,7723,7366,7005,6639,6270,5896,5519,
+5139,4756,4370,3981,3590,3196,2801,2404,2005,1606,1205,804,402,0,-402,-804,-1205,-1606,
+-2005,-2404,-2801,-3196,-3590,-3981,-4370,-4756,-5139,-5519,-5896,-6270,-6639,-7005,
+-7366,-7723,-8075,-8423,-8765,-9102,-9433,-9759,-10079,-10393,-10701,-11002,-11297,
+-11585,-11865,-12139,-12405,-12664,-12915,-13159,-13394,-13622,-13841,-14052,-14255,
+-14449,-14634,-14810,-14977,-15136,-15285,-15425,-15556,-15678,-15790,-15892,-15985,
+-16068,-16142,-16206,-16260,-16304,-16339,-16363,-16378,-16383,-16378,-16363,-16339,
+-16304,-16260,-16206,-16142,-16068,-15985,-15892,-15790,-15678,-15556,-15425,-15285,
+-15136,-14977,-14810,-14634,-14449,-14255,-14052,-13841,-13622,-13394,-13159,-12915,
+-12664,-12405,-12139,-11865,-11585,-11297,-11002,-10701,-10393,-10079,-9759,-9433,-9102,
+-8765,-8423,-8075,-7723,-7366,-7005,-6639,-6270,-5896,-5519,-5139,-4756,-4370,-3981,
+-3590,-3196,-2801,-2404,-2005,-1606,-1205,-804,-402,0};
+
+/* Static APIs */
+static inline void wait_for_silabs_event(void);
+static int silabs_init(void);
+static void silabs_release(void);
+static void release(int signum);
+static void sw_tone_test(int tdm_fd, unsigned char line_id);
+static void gen_tone(unsigned short freq, unsigned char line_id, unsigned char* tx_buff);
+static void sw_loopback(int tdm_fd, unsigned char line_id);
+static void sw_loopback_two_phones_test(int tdm_fd, unsigned char line0, unsigned char line1);
+static void slic_digital_loopback(int tdm_fd, unsigned long int iterations);
+static void sw_loopback_multi_phones_test(int tdm_fd, unsigned char start_line, unsigned char end_line);
+static void channel_balancing_test(int tdm_fd, unsigned long int iterations);
+static inline int slic_dl_data_compare(int offset);
+static void set_tdm_clk_config(void);
+#if defined(MV_TDM_USE_DCO)
+static int get_tdm_clk_correction(void);
+static void set_tdm_clk_correction(int correction);
+#endif
+
+int main(void)
+{
+	int ret = 0, cmd = 0, val = 0, tdm_init = 0, toneEna = 0, preset = 0;
+	int proc_fd, fdflags, cmd_len, i, status;
+	char str[32];
+	unsigned char line0_id, line1_id;
+	tdm_dev_params_t tdm_params;
+	unsigned long int iterations;
+
+	event_count = 0;
+	slic_init = 0;
+
+	/* open tdm device */
+	tdm_fd = open(dev_name, O_RDWR); 
+	if (tdm_fd <= 0) {
+		printf("%s Cannot open %s device\n", TOOL_PREFIX, dev_name);
+		return 1;
+	}
+
+	/* set some flags */
+	fdflags = fcntl(tdm_fd, F_GETFL, 0);
+	fdflags |= O_NONBLOCK;
+	fcntl(tdm_fd, F_SETFL, fdflags);
+
+	printf("\n%s Please enter total lines number: ", TOOL_PREFIX);
+	gets(str);
+	total_lines = atoi(str);
+
+	printf("%s Please enter PCM sample size(1/2/4): ",TOOL_PREFIX);
+	gets(str);
+	pcm_bytes = atoi(str);
+
+	/* Calculate total lines buffer size */
+	buff_size = (80 * pcm_bytes * total_lines);
+
+	/* Fill TDM info */
+	tdm_params.pcm_format = pcm_bytes;
+	tdm_params.total_lines = total_lines;
+	
+	total_devs = (total_lines/MAX_DEVICE_LINES);
+	if((total_lines % MAX_DEVICE_LINES))
+		total_devs++;
+
+	/* Handle termination gracefully */
+	if (signal (SIGINT, release) == SIG_IGN)
+		signal (SIGINT, SIG_IGN);
+
+	printf("\n !!! Remember to start phone devices before performing any action !!!\n", TOOL_PREFIX);
+
+	/* Issue main menu */
+	while(1) {
+		printf("\n  Marvell Voice Tool (Silabs Edition):\n");
+		printf("  0. Read from SLIC register\n");
+		printf("  1. Write to SLIC register\n");
+		printf("  2. Start ring\n");
+		printf("  3. Stop ring\n");
+		printf("  4. Start/Stop HW Dial tone\n");
+		printf("  5. Start SW Dial tone\n");
+		printf("  6. Self echo on local phone\n");
+		printf("  7. Loopback two local phones\n");
+		printf("  8. Digital Loopback\n");
+		printf("  9. Channel balancing\n");
+		printf("  c. Config TDM PCLK\n");
+		printf("  m. Multiple local phone pairs loopback\n");
+#if defined(DEBUG)
+		printf("  r. Read from SLIC RAM\n");
+		printf("  w. Write to SLIC RAM\n");
+#endif
+#if defined(MV_TDM_USE_DCO)
+		printf("  g. Get current TDM PCLK frequency correction (DCO)\n");
+		printf("  s. Set TDM PCLK frequency correction (DCO)\n");
+#endif
+		printf("  t. Start Phone devices\n");
+		printf("  u. Stop Phone devices\n");
+		printf("  q. Quit\n");
+		printf("\n%s Please select option: ", TOOL_PREFIX);
+
+		/* Clear write buffer */
+		memset(aud_buf[1], 0, buff_size);
+		gets(str);
+		switch(str[0]) {
+			case '0':
+				printf("%s Enter channel id: ",TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter SLIC register address (decimal): ",TOOL_PREFIX);
+				gets(str);
+				cmd = atoi(str);
+				cmd_len = 1;
+				silabs_slic_reg_read(line0_id, cmd, cmd_len, data_buff);
+				printf("%s Return value: ",TOOL_PREFIX);
+				for(i = 0; i < cmd_len; i++)
+					printf("0x%x ", data_buff[i]);
+				printf("\n");
+				break;
+
+			case '1':
+				printf("%s Enter channel id: ",TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter SLIC register address (decimal): ",TOOL_PREFIX);
+				gets(str);
+				cmd = atoi(str);
+				cmd_len = 1;
+				printf("%s Enter data: ",TOOL_PREFIX);
+				for(i = 0; i < cmd_len; i++) {
+					gets(str);
+					data_buff[i] = atoi(str);
+				}
+				silabs_slic_reg_write(line0_id, cmd, cmd_len, data_buff);
+				break;
+
+			case '2':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("Start ringing on line %d\n", line0_id);
+				silabs_channel_operation(SI_CHANNEL_OP_RING_START, line0_id);
+				break;
+
+			case '3':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("Stop ringing on line %d\n", line0_id);
+				silabs_channel_operation(SI_CHANNEL_OP_RING_STOP, line0_id);
+				break;
+
+			case '4':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				toneEna = 1-toneEna;
+				if (toneEna) {
+					printf("%s Enter preset: ", TOOL_PREFIX);
+					gets(str);
+					preset = atoi(str);
+					status = silabs_channel_setup(SI_CHANNEL_SETUP_TONEGEN, line0_id, preset);
+					if (status != RC_NONE) {
+						printf("## Error, silabs_channel_setup (SI_CHANNEL_SETUP_TONEGEN) failed (status=%d) ##\n", status);
+						return -1;
+					}
+					status = silabs_channel_operation(SI_CHANNEL_OP_TONE_GEN_START, line0_id);
+				} else {
+					status = silabs_channel_operation(SI_CHANNEL_OP_TONE_GEN_STOP, line0_id);
+				}
+
+				if (status != RC_NONE) {
+					printf("## Error, silabs_channel_operation (SI_CHANNEL_OP_TONE_GEN_START) failed (status=%d) ##\n", status);
+					return -1;
+				}
+				break;
+
+			case '5':
+				if(pcm_bytes < 2) {
+					printf("Test is supported for linear mode only - try again\n");
+					break;
+				}
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				sw_tone_test(tdm_fd, line0_id);
+				break;
+
+			case '6':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				printf("%s Waiting for off-hook...\n", TOOL_PREFIX);
+				line0_id = atoi(str);
+				sw_loopback(tdm_fd, line0_id);
+				break;
+
+			case '7':
+				printf("%s Enter line #0: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter line #1: ", TOOL_PREFIX);
+				gets(str);
+				printf("Waiting for off-hook...\n");
+				line1_id = atoi(str);
+				if(line0_id >= MAX_LINES || line1_id >= MAX_LINES) {
+					printf("%s Error, line must be in the range of 0-%d\n", TOOL_PREFIX, (MAX_LINES-1));
+					break;
+				}
+				sw_loopback_two_phones_test(tdm_fd, line0_id, line1_id);
+				break;
+
+			case '8':
+				printf("%s Enter number of iterations(must be greater than 3): ", TOOL_PREFIX);
+				gets(str);
+				iterations = (unsigned long int)atoi(str);
+				if(iterations < 4) {
+					printf("Requires at least 4 iterations  - try again\n");
+					break;
+				}
+				slic_digital_loopback(tdm_fd, iterations);
+				break;
+
+			case '9':
+				printf("%s Enter number of iterations('0' - for infinite loop): ", TOOL_PREFIX);
+				gets(str);
+				iterations = (unsigned long int)atoi(str);
+				channel_balancing_test(tdm_fd, iterations);
+				break;
+#if defined(DEBUG)
+			case 'r':
+				printf("%s Enter channel id: ",TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter SLIC RAM address (decimal): ",TOOL_PREFIX);
+				gets(str);
+				cmd = atoi(str);
+				cmd_len = 1;
+				data_buff_ram[0] = 0;
+				silabs_slic_ram_read(line0_id, cmd, cmd_len, data_buff_ram);
+				printf("%s Return value: ",TOOL_PREFIX);
+				for(i = 0; i < cmd_len; i++)
+					printf("0x%x ", data_buff_ram[i]);
+				printf("\n");
+				wait_for_silabs_event();
+				break;
+
+			case 'w':
+				printf("%s Enter channel id: ",TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter SLIC RAM address (decimal): ",TOOL_PREFIX);
+				gets(str);
+				cmd = atoi(str);
+				cmd_len = 1;
+				printf("%s Enter data: ",TOOL_PREFIX);
+				for(i = 0; i < cmd_len; i++) {
+					gets(str);
+					data_buff_ram[i] = atoi(str);
+				}
+				silabs_slic_ram_write(line0_id, cmd, cmd_len, data_buff_ram);
+				break;
+#endif
+			case 'm':
+				printf("%s Enter starting line range: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter ending line range: ", TOOL_PREFIX);
+				gets(str);
+				printf("Waiting for off-hook...\n");
+				line1_id = atoi(str);
+				if((line0_id >= MAX_LINES) || (line1_id >= MAX_LINES) || ((line1_id-line0_id) % 2 == 0)) {
+					printf("%s Error, lines range must be even and \
+						between 0-%d\n", TOOL_PREFIX, (MAX_LINES-1));
+					break;
+				}
+				sw_loopback_multi_phones_test(tdm_fd, line0_id, line1_id);
+				break;
+
+			case 'c':
+				set_tdm_clk_config();
+				break;
+
+			case 'g':
+				printf("%s Current PPM correction is (+/-1000): %d", TOOL_PREFIX, get_tdm_clk_correction());
+				break;
+
+			case 's':
+				printf("%s Enter number of PPM for correction (+/-1000, 0 to disable correction): ", TOOL_PREFIX);
+				gets(str);
+				set_tdm_clk_correction((int)atoi(str));
+				break;
+
+			case 't':
+				/* Start Telephony */
+				if(ioctl(tdm_fd, TDM_DEV_TDM_START, &tdm_params)) {
+					printf("%s Error, unable to init TDM\n", TOOL_PREFIX);
+					return 1;
+				}
+
+				if(silabs_open_device()) {
+					printf("%s Error, could not open vpapi device\n", TOOL_PREFIX);
+					return 1;
+				}
+
+				if(silabs_init()) {
+					printf("%s Error, init failed\n", TOOL_PREFIX);
+					ret = 1;
+					goto voice_out;
+				}
+				slic_init = 1;
+
+				wait_for_silabs_event();
+
+				break;
+
+			case 'u':
+				/* Stop Telephony */
+				release(0);
+				break;
+
+			case 'q':
+				goto voice_out;
+
+			default:
+				printf("Option is not supported - try again\n");
+				break;
+		}
+	}
+
+voice_out:
+	release(1);
+
+	return ret;
+}
+
+void release(int signum)
+{
+	int i, status;
+
+	if (signum) {
+		printf("\n%s Stopping Phone devices and exit\n", TOOL_PREFIX);
+		sleep(1);
+	} else {
+		printf("\n%s Stopping Phone devices\n", TOOL_PREFIX);
+	}
+
+	/* Stop SLIC/s */
+	if(slic_init) {
+		/* Destroy ProSLIC channel objects. */
+		for(i=0;i<total_lines;i++) {
+			status = silabs_channel_init(SI_CHANNEL_DESTROY, i);
+			if (status != RC_NONE) {
+				printf("## Error, silabs_channel_init (SI_CHANNEL_DESTROY) failed (line=%d, status=%d) ##\n", i, status);
+				return;
+			}
+		}
+
+		/* Destroy ProSLIC Device Objects */
+		status = silabs_device_init(SI_DEVICE_DESTROY, 0);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_device_init (SI_DEVICE_CREATE) failed (status=%d) ##\n", status);
+			return;
+		}
+
+		/* Destroy ProSLIC Control Interface Object  */
+		status = silabs_control_interface(SI_IF_DESTROY);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_control_interface (SI_IF_DESTROY) failed (status=%d) ##\n", status);
+			return;
+		}
+	} else {
+		printf("\n%s SLIC already stopped\n", TOOL_PREFIX);
+	}
+
+	/* Stop TDM */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_STOP, 0)) {
+		printf("\n%s Error, unable to stop TDM\n", TOOL_PREFIX);
+		return;
+	} else {
+		printf("\n%s TDM stopped\n", TOOL_PREFIX);
+	}
+
+	if (signum)
+		close(tdm_fd);
+
+	if(silabs_close_device()) {
+		printf("\n%s Error, could not close SLIC device ##\n", TOOL_PREFIX);
+		return;
+	} else {
+		printf("\n%s SLIC device closed\n", TOOL_PREFIX);
+	}
+
+	if (signum)
+		exit(signum);
+}
+
+static void channel_balancing_test(int tdm_fd, unsigned long int iterations)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, cmp_status = 0, ch, cb_loop = 0, i;
+	unsigned long int loops = 0, index;
+	int status;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Fill Tx buffer with incremental pattern */
+	for(ch = 0; ch < total_lines; ch++) {
+		for(index = 0; index < (80 * pcm_bytes); index+=2)
+			*((unsigned short*)&aud_buf[1][(80 * pcm_bytes * ch) + index]) = (((index+3) << 8)+ (index+1));
+	}
+
+	/* Put SLIC/s in loopback mode and On-Hook transmission */
+	for(ch = 0; ch < total_lines; ch++) {
+		status = silabs_channel_set_loopback(ch, PROSLIC_LOOPBACK_DIG);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_operation (PROSLIC_LOOPBACK_DIG) failed (status=%d) ##\n", status);
+			return;
+		}
+
+		status = silabs_channel_set_line_feed(ch, LF_FWD_OHT);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_set_line_feed (LF_FWD_ACTIVE) failed (line=%d, status=%d) ##\n", i, status);
+			return;
+		}
+	}
+
+	/* Wait a bit */
+	sleep(1);
+
+	if (iterations == 0)
+		iterations = (unsigned long int)(-1); /* Assume infinite */
+
+	while (loops < iterations) {
+		cb_loop = 0;
+		i = 0;
+
+		if (ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+			printf("Error, unable to start pcm bus\n");
+			return;
+		}
+
+		while (cb_loop == 0) {
+			FD_ZERO(&rd_fds);
+			FD_ZERO(&wr_fds);
+			FD_SET(tdm_fd, &rd_fds);
+			FD_SET(tdm_fd, &wr_fds);
+
+			/* Wait for event  */
+			if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+				printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+				goto cb_out;
+			}
+
+			/* Write */
+			if (FD_ISSET(tdm_fd, &wr_fds)) {
+				msg_len = write(tdm_fd, aud_buf[1], buff_size);
+				if (msg_len < buff_size) {
+					printf("write() failed\n");
+					goto cb_out;
+				}
+			}
+
+			/* Read */
+			if (FD_ISSET(tdm_fd, &rd_fds)) {
+				memset(aud_buf[0], 0, buff_size);
+				msg_len = read(tdm_fd, aud_buf[0], buff_size);
+				if (msg_len < buff_size) {
+					printf("read() failed\n");
+					goto cb_out;
+				}
+
+				if(i > 3) {
+					for(ch = 1; ch < total_lines; ch++) {
+						if(memcmp(aud_buf[0], &aud_buf[0][(ch * pcm_bytes * 80)], (pcm_bytes * 80))) {
+							printf("\nERROR - data miscompare(ch=%d) !!!\n", ch);
+							cmp_status = 1;
+							goto cb_out;
+						}
+					}
+
+					cb_loop = 1;
+				}
+				i++;
+			}
+
+			/* Reload timeout */
+			timeout.tv_usec = TIMEOUT;
+		}
+
+		loops++;
+		if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+			printf("Error, unable to stop pcm bus\n");
+			return;
+		}
+		printf("loop #%u\n", loops);
+		sleep(1);
+	}
+
+cb_out:
+	if(cmp_status == 0) {
+		printf("\nChannel balancing test PASSED !!!\n");
+	} else {
+		printf("Dump Rx buffer:\n");
+		for(ch = 0; ch < total_lines; ch++) {
+			printf("Buffer #%d: ", ch);
+			for(i = 0; i < (pcm_bytes * 80); i++) {
+				printf("0x%x ", aud_buf[0][(ch * pcm_bytes * 80) + i]);
+			}
+			printf("\n\n");
+			sleep(1);
+		}
+	}
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+
+	/*  Return SLIC/s to no-loopback mode and Off-Hook transmission */
+	for(ch = 0; ch < total_lines; ch++) {
+		status = silabs_channel_set_loopback(ch, PROSLIC_LOOPBACK_NONE);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_operation (PROSLIC_LOOPBACK_DIG) failed (status=%d) ##\n", status);
+			return;
+		}
+
+		status = silabs_channel_set_line_feed(ch, LF_FWD_ACTIVE);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_set_line_feed (LF_FWD_ACTIVE) failed (line=%d, status=%d) ##\n", i, status);
+			return;
+		}
+	}
+}
+
+static void slic_digital_loopback(int tdm_fd, unsigned long int iterations)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, cmp_status = 0, ch;
+	unsigned long int loops = 0, index;
+	int i, status;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Put SLIC/s in loopback mode and On-Hook transmission */
+	for(ch = 0; ch < total_lines; ch++) {
+		status = silabs_channel_set_loopback(ch, PROSLIC_LOOPBACK_DIG);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_operation (PROSLIC_LOOPBACK_DIG) failed (status=%d) ##\n", status);
+			return;
+		}
+
+		status = silabs_channel_set_line_feed(ch, LF_FWD_OHT);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_set_line_feed (LF_FWD_ACTIVE) failed (line=%d, status=%d) ##\n", i, status);
+			return;
+		}
+	}
+
+	/* Wait a bit */
+	sleep(1);
+
+	/* Fill Tx buffer with incremental pattern */
+	for(ch = 0; ch < total_lines; ch++) {
+		for(index = 0; index < (80 * pcm_bytes); index++)
+			aud_buf[1][index + (80 * pcm_bytes * ch)] = (index+ch+2);
+	}
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while (loops < iterations) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			goto slic_dl_out;
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds)) {
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len < buff_size) {
+				printf("write() failed\n");
+				goto slic_dl_out;
+			}
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds)) {
+			memset(aud_buf[0], 0, buff_size);
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len < buff_size) {
+				printf("read() failed\n");
+				goto slic_dl_out;
+			}
+
+			if(loops++ > 3) {
+				for(ch = 0; ch < total_lines; ch++) {
+					if(slic_dl_data_compare(ch)) {
+						printf("\nERROR - data miscompare(loops=%d) !!!\n",loops);
+						cmp_status = 1;
+						goto slic_dl_out;
+					}
+				}
+			}
+		}
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+slic_dl_out:
+	if(cmp_status == 0)
+		printf("\nDigital loopback test(%d lines) - PASS !!!\n",total_lines);
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+
+	/*  Return SLIC/s to no-loopback mode and Off-Hook transmission */
+	for(ch = 0; ch < total_lines; ch++) {
+		status = silabs_channel_set_loopback(ch, PROSLIC_LOOPBACK_NONE);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_operation (PROSLIC_LOOPBACK_DIG) failed (status=%d) ##\n", status);
+			return;
+		}
+		
+		status = silabs_channel_set_line_feed(ch, LF_FWD_ACTIVE);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_set_line_feed (LF_FWD_ACTIVE) failed (line=%d, status=%d) ##\n", i, status);
+			return;
+		}
+	}
+}
+
+static inline int slic_dl_data_compare(int ch)
+{
+	int i = 0, offset = (ch * pcm_bytes * 80);
+
+	/* Align Tx & Rx data start */
+	while((aud_buf[1][offset] != aud_buf[0][offset+i]) && (i < (pcm_bytes * 80)))
+		i++;
+
+	if(i >= (offset + (pcm_bytes * 80))) {
+		printf("\nError, first Tx byte not found inside Rx buffer\n");
+		return -1;
+	}
+
+	if(memcmp(&aud_buf[0][offset+i], &aud_buf[1][offset], ((pcm_bytes * 80) - i))) {
+		printf("\nDump buffers:\n");
+		for(i = offset; i < (offset +(pcm_bytes * 80)); i++)
+			printf("write[%d] = 0x%x, read[%d] = 0x%x\n", i, aud_buf[1][i], i, aud_buf[0][i]);
+		return -1;
+	} else {
+		return 0;
+	}
+}
+
+static void sw_loopback(int tdm_fd, unsigned char line_id)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, status;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Wait until line goes off-hook */
+	while(hook_state[line_id] == 0) {
+		wait_for_silabs_event();
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while(hook_state[line_id] == 1) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds)) {
+			printf("Rd\n");
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len <= 0) {
+				printf("read() failed\n");
+				return;
+			}
+			memcpy(BUFF_ADDR(aud_buf[1], line_id), BUFF_ADDR(aud_buf[0], line_id), CH_BUFF_SIZE);
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds)) {
+			printf("Wr\n");
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+				return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_silabs_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static void gen_tone(unsigned short freq, unsigned char line_id, unsigned char* tx_buff)
+{
+	short i;
+	short buf[80];
+	short sample;
+
+	for(i = 0; i < 80; i++) {
+		sample = (sinTbl[f1Mem >> 8] + sinTbl[f2Mem >> 8]) >> 2;
+#ifndef CONFIG_CPU_BIG_ENDIAN 
+		buf[i] = sample;
+#else
+		buf[i] = ((sample & 0xff) << 8)+ (sample >> 8);
+#endif
+		f1Mem += freq;
+		f2Mem += freq;
+	}
+	memcpy(BUFF_ADDR(tx_buff, line_id), (void *)buf, 160);
+}
+
+static void sw_tone_test(int tdm_fd, unsigned char line_id)
+{
+	fd_set wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, x, status;
+	char str[4];
+
+	if (tdm_fd <= 0) {
+		printf("%s Device %s is not accessible\n", TOOL_PREFIX, dev_name);
+		return;
+	}
+
+	while(1) {
+		if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+			printf("Error, unable to stop pcm bus\n");
+			return;
+		}
+
+		printf("%s Choose frequency: (1) 300HZ (2) 630HZ (3) 1000HZ (4) Back to main menu: ", TOOL_PREFIX);
+		gets(str);
+		printf("%s Waiting for off-hook...\n", TOOL_PREFIX);
+
+		if(str[0] == '1') {
+			x = 2457;
+			//printf("%s Generating 300HZ tone\n", TOOL_PREFIX);
+		}
+		else if (str[0] == '2') {
+			x = 5161;
+			//printf("%s Generating 630HZ tone\n", TOOL_PREFIX);
+		}
+		else if (str[0] == '3') {
+			x = 8192;
+			//printf("%s Generating 1000HZ tone\n", TOOL_PREFIX);
+		}
+		else if (str[0] == '4') {
+			return;
+		}
+		else {
+			printf("%s Input error - try again\n", TOOL_PREFIX);
+			continue;
+		}
+
+		/* Wait until both lines go off-hook */
+		while(hook_state[line_id] == 0) {
+			wait_for_silabs_event();
+		}
+
+		if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+			printf("Error, unable to start pcm bus\n");
+			return;
+		}
+
+		printf("%s Waiting for on-hook to return to menu.\n", TOOL_PREFIX);
+
+		while(hook_state[line_id] == 1) {
+			FD_ZERO(&wr_fds);
+			FD_SET(tdm_fd, &wr_fds);
+
+			/* Wait for event  */
+			if (select(tdm_fd+1, NULL, &wr_fds, NULL, &timeout) == 0) {
+				printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+				return;
+			}
+
+			/* Write */
+			if (FD_ISSET(tdm_fd, &wr_fds)) {
+				gen_tone(x, line_id, aud_buf[1]);
+				if (pcm_bytes == 4)
+					gen_tone(x, line_id, (aud_buf[1]+160));
+
+				msg_len = write(tdm_fd, aud_buf[1], buff_size);
+				if (msg_len <= 0) {
+					printf("write() failed\n");
+					return;
+				}
+			}
+
+			/* Check hook state */
+			wait_for_silabs_event();
+
+			/* Reload timeout */
+			timeout.tv_usec = TIMEOUT;
+		}
+	}
+}
+
+static void sw_loopback_multi_phones_test(int tdm_fd, unsigned char start_line, unsigned char end_line)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len;
+	unsigned char line_id;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Wait until at least one line goes off-hook */
+	while(offhook_count == 0) {
+		wait_for_silabs_event();
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while(offhook_count) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds)) {
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len <= 0) {
+				printf("read() failed\n");
+				return;
+			}
+
+			for(line_id = start_line; line_id < end_line; line_id+=2) {
+				memcpy(BUFF_ADDR(aud_buf[1], line_id), BUFF_ADDR(aud_buf[0], (line_id+1)), CH_BUFF_SIZE);
+				memcpy(BUFF_ADDR(aud_buf[1], (line_id+1)), BUFF_ADDR(aud_buf[0], line_id), CH_BUFF_SIZE);
+			}
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds)) {
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+				return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_silabs_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static void sw_loopback_two_phones_test(int tdm_fd, unsigned char line0, unsigned char line1)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Wait until both lines go off-hook */
+	while((hook_state[line0] == 0) || (hook_state[line1] == 0)) {
+		wait_for_silabs_event();
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while((hook_state[line0] == 1) && (hook_state[line1] == 1)) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds)) {
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len <= 0) {
+				printf("read() failed\n");
+				return;
+			}
+			memcpy(BUFF_ADDR(aud_buf[1], line0), BUFF_ADDR(aud_buf[0], line1), CH_BUFF_SIZE);
+			memcpy(BUFF_ADDR(aud_buf[1], line1), BUFF_ADDR(aud_buf[0], line0), CH_BUFF_SIZE);
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds)) {
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+				return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_silabs_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static int silabs_init(void)
+{
+	int i, status;
+
+	/* Set lines status to on-hook */
+	memset(hook_state, 0, MAX_LINES);
+
+	/* Fill time slot table */
+	memset(time_slot_table, 0, MAX_LINES);
+	for(i = 0; i < total_lines; i++)
+		time_slot_table[i] = ((i+1) * pcm_bytes);
+
+	/* Create ProSLIC Control Interface Object  */
+	status = silabs_control_interface(SI_IF_CREATE);
+	if (status != RC_NONE) {
+		printf("## Error, silabs_control_interface (SI_IF_CREATE) failed (status=%d) ##\n", status);
+		return -1;
+	}
+
+	/* Create ProSLIC Device Objects */
+	status = silabs_device_init(SI_DEVICE_CREATE, 0);
+	if (status != RC_NONE) {
+		printf("## Error, silabs_device_init (SI_DEVICE_CREATE) failed (status=%d) ##\n", status);
+		return -1;
+	}
+
+	/* Create and initialize ProSLIC channel objects. Also initialize array pointers to user’s proslic 
+	channel object members to simplify initialization process. */
+	for(i=0;i<total_lines;i++) {
+		status = silabs_channel_init(SI_CHANNEL_CREATE, i);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_init (SI_CHANNEL_CREATE) failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+		status = silabs_channel_init(SI_CHANNEL_SW_INIT, i);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_init (SI_CHANNEL_SW_INIT) failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+	}
+
+	/* Establish linkage between host objects/functions and ProSLIC API */
+	status = silabs_control_interface(SI_IF_SET_FUNCS);
+	if (status != RC_NONE) {
+		printf("## Error, silabs_control_interface (SI_IF_SET_FUNCS) failed (status=%d) ##\n", status);
+		return -1;
+	}
+
+	/* Assert hardware Reset – ensure VDD, PCLK, and FSYNC are present and stable before releasing reset */
+	status = silabs_channel_operation(SI_CHANNEL_OP_RESET, 0);
+	if (status != RC_NONE) {
+		printf("## Error, silabs_channel_operation (SI_CHANNEL_OP_RESET) failed (status=%d) ##\n", status);
+		return -1;
+	}
+
+	/* Initialize device (loading of general parameters, calibrations, dc-dc powerup, etc.) */
+	status = silabs_channel_all(SI_CHANNEL_ALL_INIT);
+	if (status != RC_NONE) {
+		printf("## Error, silabs_channel_all (SI_CHANNEL_ALL_INIT) failed (status=%d) ##\n", status);
+		return -1;
+	}
+
+	/* Execute longitudinal balance calibration or reload coefficients from factory LB cal
+	Note: all batteries should be up and stable prior to executing the lb cal */
+	status = silabs_channel_all(SI_CHANNEL_ALL_LBCAL);
+	if (status != RC_NONE) {
+		printf("## Error, silabs_channel_all (SI_CHANNEL_ALL_LBCAL) failed (status=%d) ##\n", status);
+		return -1;
+	}
+
+	/* Load custom configuration presets (generated using ProSLIC API Config Tool) */
+	for(i=0;i<total_lines;i++) {
+		status = silabs_channel_setup(SI_CHANNEL_SETUP_DC_FEED, i, DCFEED_48V_20MA);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_setup (SI_CHANNEL_SETUP_DC_FEED) failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+		status = silabs_channel_setup(SI_CHANNEL_SETUP_RING, i, RING_F20_45VRMS_0VDC_BAL);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_setup (SI_CHANNEL_SETUP_RING) failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+		status = silabs_channel_setup(SI_CHANNEL_SETUP_ZSYNTH, i, ZSYN_600_0_0_30_0);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_setup (SI_CHANNEL_SETUP_ZSYNTH) failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+		status = silabs_channel_setup(SI_CHANNEL_SETUP_TONEGEN, i, TONEGEN_FCC_DIAL);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_setup (SI_CHANNEL_SETUP_TONEGEN) failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+
+		/* Extract PCM format */
+		switch(pcm_bytes) {
+			case 1:
+				status = silabs_channel_setup(SI_CHANNEL_SETUP_PCM, i, PCM_8ALAW);
+				break;
+			case 2:
+				status = silabs_channel_setup(SI_CHANNEL_SETUP_PCM, i, PCM_16LIN);
+				break;
+			case 4:
+				status = silabs_channel_setup(SI_CHANNEL_SETUP_PCM, i, PCM_16LIN_WB);
+				break;
+			default:
+				status = silabs_channel_setup(SI_CHANNEL_SETUP_PCM, i, PCM_8ALAW);
+				printf("## Warning, wrong PCM size - set to default(ALAW) ##\n");
+				break;
+		}
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_setup (SI_CHANNEL_SETUP_PCM) failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+	}
+
+	/* Set Time slot parameters and line feed.*/
+	for(i=0;i<total_lines;i++) {
+		/* Configure PCM timeslots */
+		//printf("## INFO: line(%d): rx-slot(%d) , tx-slot(%d) ##\n",i ,(time_slot_table[i] * 8) + 1, (time_slot_table[i] * 8) + 1);
+		status = silabs_PCM_TS_setup(i, (time_slot_table[i] * 8) + 1, (time_slot_table[i] * 8) + 1);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_PCM_TS_setup failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+
+		status = silabs_channel_set_line_feed(i, LF_FWD_ACTIVE);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_set_line_feed (LF_FWD_ACTIVE) failed (line=%d, status=%d) ##\n", i, status);
+			return -1;
+		}
+	}
+
+	/*  Enable Interrupts. */
+	for(i=0;i<total_lines;i++) {
+		status = silabs_channel_operation(SI_CHANNEL_OP_ENA_INT, i);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_operation (SI_CHANNEL_OP_ENA_INT) failed (status=%d) ##\n", status);
+			return -1;
+		}
+	}
+
+	/* PCM Start. */
+	for(i=0;i<total_lines;i++)  {
+		status = silabs_channel_operation(SI_CHANNEL_OP_PCM_START, i);
+		if (status != RC_NONE) {
+			printf("## Error, silabs_channel_operation (SI_CHANNEL_OP_PCM_START) failed (status=%d) ##\n", status);
+			return;
+		}
+	}
+	return 0;
+}
+
+static inline void wait_for_silabs_event(void)
+{
+	bool status;
+	SiEventType event;
+	uInt8 hookStatus;
+
+	while(silabs_get_event(&event) == true) {
+		while(event.eventsNum > 0) {
+			event.eventsNum--;
+			switch(event.irqs[event.eventsNum]) {
+				case IRQ_LOOP_STATUS:
+					silabs_channel_read_hook_status(event.chanNum, &hookStatus);
+					hook_state[event.chanNum] = hookStatus;
+					if (hook_state[event.chanNum]) {
+						printf("off-hook(%d)\n", event.chanNum);
+						offhook_count++;
+					} else {
+						printf("on-hook(%d)\n", event.chanNum);
+						offhook_count--;
+					}
+					break;
+				default:
+					break;
+			}
+		}
+	}
+}
+
+static void set_tdm_clk_config(void)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	/* Config TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_CONFIG, &tdm_dev_clk)) {
+		printf("%s Error, unable to config TDM clock.\n", TOOL_PREFIX);
+	}
+}
+
+static int get_tdm_clk_correction(void)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	/* Get TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_GET, &tdm_dev_clk)) {
+		printf("%s Error, unable to get TDM clock.\n", TOOL_PREFIX);
+		return 0;
+	}
+
+	return tdm_dev_clk.correction;
+}
+
+static void set_tdm_clk_correction(int correction)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	tdm_dev_clk.correction=correction;
+
+	/* Set TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_SET, &tdm_dev_clk)) {
+		printf("%s Error, unable to set TDM clock.\n", TOOL_PREFIX);
+	}
+}
diff --git a/tools/voice/silabs/mv_voice_tool.h b/tools/voice/silabs/mv_voice_tool.h
new file mode 100755
index 0000000..f3e4abb
--- /dev/null
+++ b/tools/voice/silabs/mv_voice_tool.h
@@ -0,0 +1,84 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#ifndef _MVZARLINKIF_H_
+#define _MVZARLINKIF_H_
+
+#include "mvSysTdmConfig.h"
+#include "voiceband/mvSysTdmSpi.h"
+
+MV_STATUS mvZarlinkIfInit(MV_U16 totalSLICs, MV_U16 pSlotInfo[][2], 
+				MV_BAND_MODE bandMode, MV_PCM_FORMAT pcmFormat);
+MV_STATUS mvZarlinkIfTimerTick(MV_SLIC_EVENT_INFO* slic_event_info);
+MV_VOID mvZarlinkIfISR(MV_U8 deviceId);
+MV_VOID mvZarlinkIfActivateRinging(MV_U16 lineId);
+MV_VOID mvZarlinkIfStopRinging(MV_U16 lineId);
+MV_VOID mvZarlinkIfHookStateGet(MV_U16 lineId, MV_U8* hookstate);
+MV_VOID mvZarlinkIfLinefeedControlSet(MV_U16 lineId, MV_LINEFEED_STATE lfState);
+MV_VOID mvZarlinkIfLinefeedControlGet(MV_U16 lineId, MV_LINEFEED_STATE* lfState);
+MV_VOID mvZarlinkIfReverseDcPolarity(MV_U16 lineId);
+MV_VOID mvZarlinkIfRelease(MV_VOID);
+MV_VOID mvZarlinkIfRegRead(MV_U8 lineId, MV_U8 cmd, MV_U8 cmdLen,MV_U8* dataBuff);
+
+#endif /* _MVZARLINKIF_H_ */
diff --git a/tools/voice/silabs/silabs_lib.c b/tools/voice/silabs/silabs_lib.c
new file mode 100755
index 0000000..0e49ad6
--- /dev/null
+++ b/tools/voice/silabs/silabs_lib.c
@@ -0,0 +1,442 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include "silabs_lib.h"
+
+/* Locals */
+static char dev_name[] = "/dev/silabs";
+static int dev_fd = 0;
+static char lib_str[] = "[silabs_lib]:";
+
+int silabs_open_device(void)
+{
+	int fdflags;
+
+	/* open the device */
+	dev_fd = open(dev_name, O_RDWR); 
+	if (dev_fd <= 0) {
+		printf("Cannot open %s device\n", dev_name);
+		return -1;
+	}
+
+	/* set some flags */
+	fdflags = fcntl(dev_fd, F_GETFL, 0);
+	fdflags |= O_NONBLOCK;
+	fcntl(dev_fd, F_SETFL, fdflags);
+
+	return 0;
+}
+
+int silabs_close_device(void)
+{
+	if(dev_fd > 0)
+		close(dev_fd);
+
+	return 0;	
+}
+
+int silabs_slic_reg_read(int line_id, unsigned char cmd, unsigned char cmd_len, unsigned char *buff)
+{
+	SilabsRegObjType data;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	data.chanNum = line_id;
+	data.func = SI_REG_READ;
+	data.regAddr = cmd;
+	data.value = 0;
+	data.ramValue = 0;
+	
+	if (ioctl(dev_fd, SILABS_MOD_IOX_REG_CTRL, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_REG_CTRL) failed\n");
+		return -1;
+	}
+
+	*buff = data.value;
+
+	return 0;
+}
+
+int silabs_slic_reg_write(int line_id, unsigned char cmd, unsigned char cmd_len, unsigned char *buff)
+{
+	SilabsRegObjType data;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	data.chanNum = line_id;
+	data.func = SI_REG_WRITE;
+	data.regAddr = cmd;
+	data.value = buff[0];
+	data.ramValue = 0;
+	
+	if (ioctl(dev_fd, SILABS_MOD_IOX_REG_CTRL, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_REG_CTRL) failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int silabs_slic_ram_read(int line_id, uInt16 cmd, unsigned char cmd_len, unsigned int *buff)
+{
+	SilabsRegObjType data;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	data.chanNum = line_id;
+	data.func = SI_RAM_READ;
+	data.ramAddr = cmd;
+	data.ramValue = 0;
+	data.value = 0;
+	
+	if (ioctl(dev_fd, SILABS_MOD_IOX_REG_CTRL, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_REG_CTRL) failed\n");
+		return -1;
+	}
+
+	*buff = data.ramValue;
+
+	return 0;
+}
+
+int silabs_slic_ram_write(int line_id, uInt16 cmd, unsigned char cmd_len, unsigned int *buff)
+{
+	SilabsRegObjType data;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	data.chanNum = line_id;
+	data.func = SI_RAM_WRITE;
+	data.ramAddr = cmd;
+	data.ramValue = buff[0];
+	data.value = 0;
+	
+	if (ioctl(dev_fd, SILABS_MOD_IOX_REG_CTRL, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_REG_CTRL) failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int silabs_control_interface(ControlFuncType func)
+{
+	SilabsModCtrlObjType data;
+
+	data.func = func;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+	
+	if (ioctl(dev_fd, SILABS_MOD_IOX_CTRL_IF, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_CTRL_IF) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int silabs_device_init(DeviceFuncType func, int devNum)
+{
+	SilabsModDevObjType data;
+
+	data.func = func;
+	data.devNum = devNum;
+			
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+	
+	if (ioctl(dev_fd, SILABS_MOD_IOX_DEVICE_INIT, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_DEVICE_INIT) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+
+int silabs_channel_init(ChannelFuncType func, int chanNum)
+{
+	SilabsModChannelObjType data;
+	
+	data.func = func;
+	data.chanNum = chanNum;
+			
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, SILABS_MOD_IOX_CHAN_INIT, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_CHAN_INIT) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int silabs_channel_all(ChannelAllFuncType func)
+{
+	SilabsModChannelAllObjType data;
+	
+	data.func = func;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, SILABS_MOD_IOX_CHAN_ALL, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_CHAN_ALL) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int silabs_channel_setup(ChannelSetupFuncType func, int chanNum, int preset)
+{
+	SilabsModChannelSetupObjType data;
+	
+	data.chanNum = chanNum;
+	data.func = func;
+	data.preset = preset;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, SILABS_MOD_IOX_CHAN_SETUP, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_CHAN_SETUP) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int silabs_channel_operation(ChannelOPFuncType func, int chanNum)
+{
+	SilabsModChannelOpObjType data;
+	
+	data.func = func;
+	data.chanNum = chanNum;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, SILABS_MOD_IOX_CHAN_OP, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_CHAN_OP) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int silabs_PCM_TS_setup(int chanNum, uInt16 rxcount, uInt16 txcount)
+{
+	SilabsModPCMTSSetupObjType data;
+	
+	data.chanNum = chanNum;
+	data.rxcount = rxcount;
+	data.txcount = txcount;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, SILABS_MOD_IOX_PCM_TS_SETUP, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_PCM_TS_SETUP) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int silabs_channel_set_line_feed(int chanNum, uInt8 newLineFeed)
+{
+	SilabsModChannelLineFeedObjType data;
+	
+	data.chanNum = chanNum;
+	data.newLineFeed = newLineFeed;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, SILABS_MOD_IOX_CHAN_LINE_FEED, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_CHAN_LINE_FEED) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int silabs_channel_read_hook_status(int chanNum, uInt8 *pHookStatus)
+{
+	SilabsModChannelReadHookStatObjType data;
+	
+	data.chanNum = chanNum;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, SILABS_MOD_IOX_CHAN_HOOK_STATUS, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_CHAN_HOOK_STATUS) failed\n");
+		return -1;
+	}
+	
+	*pHookStatus = data.hookStatus;
+
+	return data.status;
+}
+
+int silabs_channel_set_loopback(int chanNum, ProslicLoopbackModes newMode)
+{
+	SilabsModChannelSetLoopbackObjType data;
+	
+	data.chanNum = chanNum;
+	data.newMode = newMode;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, SILABS_MOD_IOX_CHAN_LOOPBACK, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_CHAN_LOOPBACK) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+bool silabs_get_event(SiEventType *event_p)
+{
+	SilabsModGetEventType data;
+	
+	data.pEvent = event_p;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return false;
+	}
+
+	
+	if (ioctl(dev_fd, SILABS_MOD_IOX_GET_EVENT, &data) < 0) {
+		printf("ioctl(SILABS_MOD_IOX_GET_EVENT) failed\n");
+		return false;
+	}
+
+	return data.newEvent;
+}
+
+int silabs_check_event(void)
+{
+	fd_set ex_fds;
+	struct timeval timeout = {0, 1};
+	int ret;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return 1;
+	}
+
+	FD_ZERO(&ex_fds);
+	FD_SET(dev_fd, &ex_fds);
+
+	/* Wait for event  */
+	ret = select(dev_fd+1, NULL, NULL, &ex_fds, &timeout);
+
+	if(FD_ISSET(dev_fd, &ex_fds))
+		return 0;
+	else
+		return 1;
+}
diff --git a/tools/voice/silabs/silabs_lib.h b/tools/voice/silabs/silabs_lib.h
new file mode 100755
index 0000000..6e4ab67
--- /dev/null
+++ b/tools/voice/silabs/silabs_lib.h
@@ -0,0 +1,92 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _SILABS_LIB_H
+#define _SILABS_LIB_H
+
+#include <stdbool.h>
+#include <slic/silabs_dev.h>
+
+int silabs_open_device(void);
+int silabs_close_device(void);
+
+int silabs_slic_reg_read(int line_id, unsigned char cmd, unsigned char cmd_len, unsigned char *buff);
+int silabs_slic_reg_write(int line_id, unsigned char cmd, unsigned char cmd_len, unsigned char *buff);
+int silabs_slic_ram_read(int line_id, uInt16 cmd, unsigned char cmd_len, unsigned int *buff);
+int silabs_slic_ram_write(int line_id, uInt16 cmd, unsigned char cmd_len, unsigned int *buff);
+
+int silabs_control_interface(ControlFuncType func);
+int silabs_device_init(DeviceFuncType func, int devNum);
+int silabs_channel_init(ChannelFuncType func, int chanNum);
+int silabs_channel_all(ChannelAllFuncType func);
+int silabs_channel_setup(ChannelSetupFuncType func, int chanNum, int preset);
+int silabs_channel_operation(ChannelOPFuncType func, int chanNum);
+int silabs_PCM_TS_setup(int chanNum, uInt16 rxcount, uInt16 txcount);
+int silabs_channel_set_line_feed(int chanNum, uInt8 newLineFeed);
+int silabs_channel_read_hook_status(int chanNum, uInt8 *pHookStatus);
+int silabs_channel_set_loopback(int chanNum, ProslicLoopbackModes newMode);
+bool silabs_get_event(SiEventType *event_p);
+int silabs_check_event(void);
+
+#endif /* _SILABS_LIB_H */
diff --git a/tools/voice/zarlink/.gitignore b/tools/voice/zarlink/.gitignore
new file mode 100755
index 0000000..5d3569a
--- /dev/null
+++ b/tools/voice/zarlink/.gitignore
@@ -0,0 +1,2 @@
+!*.a

+!lib
\ No newline at end of file
diff --git a/tools/voice/zarlink/kernel/Makefile b/tools/voice/zarlink/kernel/Makefile
new file mode 100644
index 0000000..a9121c9
--- /dev/null
+++ b/tools/voice/zarlink/kernel/Makefile
@@ -0,0 +1,60 @@
+# kernel sources 
+srctree  := $(shell /bin/pwd)
+
+ifndef KSRC
+KSRC  := $(srctree)/../../../../
+endif
+
+include $(KSRC)/.config
+
+CFLAGS  := $(EXTRA_CFLAGS)
+
+ifdef CONFIG_CPU_BIG_ENDIAN
+CFLAGS  += -DCONFIG_CPU_BIG_ENDIAN
+endif
+
+CC := $(CROSS_COMPILE)gcc
+LD := $(CROSS_COMPILE)ld
+AR := $(CROSS_COMPILE)ar
+
+#CFLAGS += -I$(KSRC)/tools/voice/
+
+ifeq ($(CONFIG_ZARLINK_SLIC_SUPPORT),y)
+TARGETS += vpapi_lib.o
+LIBS := libvpapi.a
+TOOL := mv_voice_tool.c
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/arch_marvell/
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/
+ifeq ($(CONFIG_ZARLINK_SLIC_VE792),y)
+ CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/vp792_api_lib/includes/
+ CFLAGS += -DZARLINK_SLIC_VE792
+ PROFILE = profile_79238.c
+endif
+ifeq ($(CONFIG_ZARLINK_SLIC_VE880),y)
+ CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/
+ CFLAGS += -DZARLINK_SLIC_VE880
+ PROFILE = profile_88266.c
+endif
+ifeq ($(CONFIG_ZARLINK_SLIC_VE890),y)
+ CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_hal/voiceband/slic/zarlink/api_lib/includes/
+ CFLAGS += -DZARLINK_SLIC_VE890
+ PROFILE = profile_89116.c
+endif
+
+CFLAGS += -I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone/test/
+
+all:
+	$(CC) $(CFLAGS) -static -c vpapi_lib.c -o $(TARGETS) 
+	$(AR) rcs $(LIBS) $(TARGETS)
+	$(CC) $(CFLAGS) -static $(PROFILE) $(TOOL) -L. $(LIBS) -o mv_voice_tool
+
+mv_voice_tool: $(PROFILE) $(TOOL)
+	$(CC) $(CFLAGS) -static $(PROFILE) $(TOOL) -L. $(LIBS) -o mv_voice_tool
+
+clean:
+	rm -f *.o *.a mv_voice_tool
+	@for subdir in $(SUBDIRS); do \
+                (cd $$subdir && $(MAKE) $@) || exit 1; \
+        done
+
+endif #CONFIG_ZARLINK_SLIC_SUPPORT
diff --git a/tools/voice/zarlink/kernel/mv_voice_tool.c b/tools/voice/zarlink/kernel/mv_voice_tool.c
new file mode 100644
index 0000000..8c64b02
--- /dev/null
+++ b/tools/voice/zarlink/kernel/mv_voice_tool.c
@@ -0,0 +1,1401 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include "tdm/test/tdm_dev.h"
+
+#include "vpapi_lib.h"
+
+#if defined(ZARLINK_SLIC_VE880)
+/* Zarlink VE880 */
+#include "profile_88266.h"
+#define MAX_DEVICES		2
+#define MAX_DEVICE_LINES	2
+#define MAX_LINES		4
+#define VP_DEV_SERIES		VP_DEV_880_SERIES
+#define DEV_PROFILE		ABS_VBL_FLYBACK
+#define DC_COEFF		DC_22MA_CC
+#define AC_COEFF		AC_FXS_RF14_DEF
+#define WB_AC_COEFF		AC_FXS_RF14_WB_US
+#define RING_PROFILE		RING_DEF
+
+#elif defined(ZARLINK_SLIC_VE890)
+/* Zarlink VE890 */
+#include "profile_89116.h"
+#define MAX_DEVICES		1
+#define MAX_DEVICE_LINES	1
+#define MAX_LINES		1
+#define VP_DEV_SERIES		VP_DEV_890_SERIES
+#define DEV_PROFILE		DEV_PROFILE_VE890_BB100V
+#define DC_COEFF		DC_FXS_VE890_BB100V_DEF
+#define AC_COEFF		AC_FXS_RF50_600R_DEF
+#define WB_AC_COEFF		NULL
+#define RING_PROFILE		RING_25HZ_VE890_BB100V_DEF
+
+#elif defined(ZARLINK_SLIC_VE792)
+/* Zarlink VE792 */
+#include "profile_79238.h"
+#define MAX_DEVICES		4
+#define MAX_DEVICE_LINES	8
+#define MAX_LINES		32
+#define VP_DEV_SERIES		VP_DEV_792_SERIES
+#define DEV_PROFILE		VE792_DEV_PROFILE
+#define DC_COEFF		VE792_DC_COEFF
+#define AC_COEFF		VE792_AC_COEFF_600
+#define WB_AC_COEFF		TBD /* TBD: AC profile for WideBand support */
+#define RING_PROFILE		RING_20HZ_SINE
+
+/* Power-supply related parameters */
+#define VBH			-50
+#define VBL			-25
+#define VBP			50
+#endif
+
+#define TOOL_PREFIX		">> "
+#define TIMEOUT			11000 /* usec */
+/* Line calibration increases init time significantly */
+#define LINE_CALIBRATION_SUPPORT
+
+/* Defines */
+#define GET_DEVICE(line_id)	(line_id/MAX_DEVICE_LINES)
+#define GET_LINE(line_id)	(line_id % MAX_DEVICE_LINES)
+#define N_A			0
+#define ON_HOOK			0
+#define OFF_HOOK		1
+#define CH_BUFF_SIZE		(80 * pcm_bytes)
+#define BUFF_ADDR(buff, line)	((unsigned char*)buff + (line*80*pcm_bytes))
+
+/* Extern */
+extern int dev_profile_size;
+extern int dc_profile_size;
+extern int ac_profile_size;
+extern int ring_profile_size;
+
+/* GLobals */
+static unsigned short total_lines = 0;
+static unsigned short total_devs = 0;
+static unsigned char pcm_bytes = 0;
+static unsigned char cal_devs = 0;
+#ifdef LINE_CALIBRATION_SUPPORT
+static unsigned short cal_lines = 0;
+#endif
+static VpOptionCodecType codec = VP_OPTION_ALAW;
+static unsigned char time_slot_table[MAX_LINES];
+static unsigned char hook_state[MAX_LINES];
+static char dev_name[] = "/dev/tdm";
+static int buff_size = 0;
+static unsigned char aud_buf[2][320 * MAX_LINES];
+static unsigned short f1Mem = 0;
+static unsigned short f2Mem = 0;
+static int offhook_count = 0;
+static unsigned int event_count = 0;
+static int tdm_fd = 0;
+static unsigned char data_buff[MAX_SLIC_RDWR_BUFF_SIZE];
+static int slic_init = 0;
+
+/* sin table, 256 points */
+static short sinTbl[] = {0,402,804,1205,1606,2005,2404,2801,3196,3590,3981,4370,4756,
+5139,5519,5896,6270,6639,7005,7366,7723,8075,8423,8765,9102,9433,9759,10079,10393,
+10701,11002,11297,11585,11865,12139,12405,12664,12915,13159,13394,13622,13841,14052,
+14255,14449,14634,14810,14977,15136,15285,15425,15556,15678,15790,15892,15985,16068,
+16142,16206,16260,16304,16339,16363,16378,16383,16378,16363,16339,16304,16260,16206,
+16142,16068,15985,15892,15790,15678,15556,15425,15285,15136,14977,14810,14634,14449,
+14255,14052,13841,13622,13394,13159,12915,12664,12405,12139,11865,11585,11297,11002,
+10701,10393,10079,9759,9433,9102,8765,8423,8075,7723,7366,7005,6639,6270,5896,5519,
+5139,4756,4370,3981,3590,3196,2801,2404,2005,1606,1205,804,402,0,-402,-804,-1205,-1606,
+-2005,-2404,-2801,-3196,-3590,-3981,-4370,-4756,-5139,-5519,-5896,-6270,-6639,-7005,
+-7366,-7723,-8075,-8423,-8765,-9102,-9433,-9759,-10079,-10393,-10701,-11002,-11297,
+-11585,-11865,-12139,-12405,-12664,-12915,-13159,-13394,-13622,-13841,-14052,-14255,
+-14449,-14634,-14810,-14977,-15136,-15285,-15425,-15556,-15678,-15790,-15892,-15985,
+-16068,-16142,-16206,-16260,-16304,-16339,-16363,-16378,-16383,-16378,-16363,-16339,
+-16304,-16260,-16206,-16142,-16068,-15985,-15892,-15790,-15678,-15556,-15425,-15285,
+-15136,-14977,-14810,-14634,-14449,-14255,-14052,-13841,-13622,-13394,-13159,-12915,
+-12664,-12405,-12139,-11865,-11585,-11297,-11002,-10701,-10393,-10079,-9759,-9433,-9102,
+-8765,-8423,-8075,-7723,-7366,-7005,-6639,-6270,-5896,-5519,-5139,-4756,-4370,-3981,
+-3590,-3196,-2801,-2404,-2005,-1606,-1205,-804,-402,0};
+
+/* Static APIs */
+static void vpapi_dev_init(VpDeviceIdType dev_id);
+static inline void wait_for_vpapi_event(void);
+static int vpapi_init(void);
+static void vpapi_init_done(void);
+static void vpapi_release(void);
+static void release(int signum);
+static void sw_tone_test(int tdm_fd, unsigned char line_id);
+static void gen_tone(unsigned short freq, unsigned char line_id, unsigned char* tx_buff);
+static void sw_loopback(int tdm_fd, unsigned char line_id);
+static void sw_loopback_two_phones_test(int tdm_fd, unsigned char line0, unsigned char line1);
+static void slic_digital_loopback(int tdm_fd, unsigned long int iterations);
+static void sw_loopback_multi_phones_test(int tdm_fd, unsigned char start_line, unsigned char end_line);
+static void channel_balancing_test(int tdm_fd, unsigned long int iterations);
+static inline int slic_dl_data_compare(int offset);
+#if defined(MV_TDM_USE_DCO)
+static void set_tdm_clk_config(void);
+static int get_tdm_clk_correction(void);
+static void set_tdm_clk_correction(int correction);
+#endif
+
+int main(void)
+{
+	int ret = 0, cmd = 0, val = 0, tdm_init = 0;
+	int proc_fd, fdflags, cmd_len, i;
+	char str[32];
+	unsigned char line0_id, line1_id;
+	tdm_dev_params_t tdm_params;
+	unsigned long int iterations;
+
+	event_count = 0;
+	slic_init = 0;
+
+	/* open tdm device */
+	tdm_fd = open(dev_name, O_RDWR); 
+	if (tdm_fd <= 0) {
+		printf("%s Cannot open %s device\n", TOOL_PREFIX, dev_name);
+		return 1;
+	}
+
+	/* set some flags */
+	fdflags = fcntl(tdm_fd, F_GETFL, 0);
+	fdflags |= O_NONBLOCK;
+	fcntl(tdm_fd, F_SETFL, fdflags);
+
+	printf("\n%s Please enter total lines number: ", TOOL_PREFIX);
+	gets(str);
+	total_lines = atoi(str);
+
+	printf("%s Please enter PCM sample size(1/2/4): ",TOOL_PREFIX);
+	gets(str);
+	pcm_bytes = atoi(str);
+
+	/* Calculate total lines buffer size */
+	buff_size = (80 * pcm_bytes * total_lines);
+
+	/* Fill TDM info */
+	tdm_params.pcm_format = pcm_bytes;
+	tdm_params.total_lines = total_lines;
+	
+	total_devs = (total_lines/MAX_DEVICE_LINES);
+	if((total_lines % MAX_DEVICE_LINES))
+		total_devs++;
+
+	/* Handle termination gracefully */
+	if (signal (SIGINT, release) == SIG_IGN)
+		signal (SIGINT, SIG_IGN);
+
+	printf("\n !!! Remember to start phone devices before performing any action !!!\n", TOOL_PREFIX);
+
+	/* Issue main menu */
+	while(1) {
+		printf("\n  Marvell Voice Tool (Zarlink/Ligerity Edition):\n");
+		printf("  0. Read from SLIC register (VE880 only)\n");
+		printf("  1. Write to SLIC register (VE880 only)\n");
+		printf("  2. Start ring\n");
+		printf("  3. Stop ring\n");
+		printf("  4. Start SW Dial tone\n");
+		printf("  5. Self echo on local phone\n");
+		printf("  6. Loopback two local phones\n");
+		printf("  7. Multiple local phone pairs loopback\n");
+		printf("  8. Digital Loopback (incremental pattern)\n");
+		printf("  9. Channel balancing\n");
+		printf("  a. Start Phone devices\n");
+		printf("  b. Stop Phone devices\n");
+#if defined(MV_TDM_USE_DCO)
+		printf("  c. Config TDM PCLK\n");
+		printf("  d. Get current TDM PCLK frequency correction (DCO)\n");
+		printf("  e. Set TDM PCLK frequency correction (DCO)\n");
+#endif
+		printf("  q. Quit\n");
+		printf("\n%s Please select option: ", TOOL_PREFIX);
+
+		/* Clear write buffer */
+		memset(aud_buf[1], 0, buff_size);
+		gets(str);
+		switch(str[0]) {
+			case '0':
+#if defined(ZARLINK_SLIC_VE880)
+				printf("%s Enter line id: ",TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter SLIC register command(decimal): ",TOOL_PREFIX);
+				gets(str);
+				cmd = atoi(str);
+				printf("%s Enter SLIC register command size: ",TOOL_PREFIX);
+				gets(str);
+				cmd_len = atoi(str);
+				vpapi_slic_reg_read(line0_id, cmd, cmd_len, data_buff);
+				printf("\n%s Sent command 0x%x to line(%d)\n", TOOL_PREFIX, cmd, line0_id);
+				printf("%s Return value: ",TOOL_PREFIX);
+				for(i = 0; i < cmd_len; i++)
+					printf("0x%x ", data_buff[i]);
+				printf("\n");
+#else
+				printf("%s operation not supported\n",TOOL_PREFIX);
+#endif
+				break;
+
+			case '1':
+#if defined(ZARLINK_SLIC_VE880)
+				printf("%s Enter line id: ",TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter SLIC register command(decimal): ",TOOL_PREFIX);
+				gets(str);
+				cmd = atoi(str);
+				printf("%s Enter SLIC register command size: ",TOOL_PREFIX);
+				gets(str);
+				cmd_len = atoi(str);
+				printf("%s Enter data(press Enter after each byte): ",TOOL_PREFIX);
+				for(i = 0; i < cmd_len; i++) {
+					gets(str);
+					data_buff[i] = atoi(str);
+				}
+				vpapi_slic_reg_write(line0_id, cmd, cmd_len, data_buff);
+				printf("\n%s Sent command 0x%x to line(%d)\n", TOOL_PREFIX, cmd, line0_id);
+#else
+				printf("%s operation not supported\n",TOOL_PREFIX);
+#endif
+				break;
+
+			case '2':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("Start ringing on line %d\n", line0_id);
+				vpapi_set_line_state(line0_id, VP_LINE_RINGING);
+				break;
+
+			case '3':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("Stop ringing on line %d\n", line0_id);
+				vpapi_set_line_state(line0_id, VP_LINE_STANDBY);
+				break;
+
+			case '4':
+				if(pcm_bytes < 2) {
+					printf("Test is supported for linear mode only - try again\n");
+					break;
+				}
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				sw_tone_test(tdm_fd, line0_id);
+				break;
+
+			case '5':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				printf("%s Waiting for off-hook...\n", TOOL_PREFIX);
+				line0_id = atoi(str);
+				sw_loopback(tdm_fd, line0_id);
+				break;
+
+			case '6':
+				printf("%s Enter line #0: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter line #1: ", TOOL_PREFIX);
+				gets(str);
+				printf("Waiting for off-hook...\n");
+				line1_id = atoi(str);
+				if(line0_id >= MAX_LINES || line1_id >= MAX_LINES) {
+					printf("%s Error, line must be in the range of 0-%d\n", TOOL_PREFIX, (MAX_LINES-1));
+					break;
+				}
+				sw_loopback_two_phones_test(tdm_fd, line0_id, line1_id);
+				break;
+
+			case '7':
+				printf("%s Enter starting line range: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter ending line range: ", TOOL_PREFIX);
+				gets(str);
+				printf("Waiting for off-hook...\n");
+				line1_id = atoi(str);
+				if((line0_id >= MAX_LINES) || (line1_id >= MAX_LINES) || ((line1_id-line0_id) % 2 == 0)) {
+					printf("%s Error, lines range must be even and \
+						between 0-%d\n", TOOL_PREFIX, (MAX_LINES-1));
+					break;
+				}
+				sw_loopback_multi_phones_test(tdm_fd, line0_id, line1_id);
+				break;
+
+			case '8':
+				printf("%s Enter number of iterations(must be greater than 3): ", TOOL_PREFIX);
+				gets(str);
+				iterations = (unsigned long int)atoi(str);
+				if(iterations < 4) {
+					printf("Requires at least 4 iterations  - try again\n");
+					break;
+				}
+				slic_digital_loopback(tdm_fd, iterations);
+				break;
+
+			case '9':
+				printf("%s Enter number of iterations('0' - for infinite loop): ", TOOL_PREFIX);
+				gets(str);
+				iterations = (unsigned long int)atoi(str);
+				channel_balancing_test(tdm_fd, iterations);
+				break;
+
+			case 'a':
+				/* Start Telephony */
+				if(ioctl(tdm_fd, TDM_DEV_TDM_START, &tdm_params)) {
+					printf("%s Error, unable to init TDM\n", TOOL_PREFIX);
+					return 1;
+				}
+
+				if(vpapi_open_device()) {
+					printf("%s Error, could not open vpapi device\n", TOOL_PREFIX);
+					return 1;
+				}
+
+				if(vpapi_init()) {
+					printf("%s Error, init failed\n", TOOL_PREFIX);
+					ret = 1;
+					goto voice_out;
+				}
+				slic_init = 1;
+
+				/* Wait to device/s and line/s calibration to finish */
+#ifdef LINE_CALIBRATION_SUPPORT
+				while((cal_devs < total_devs) || (cal_lines < total_lines)) {
+#else
+				while(cal_devs < total_devs) {
+#endif
+					wait_for_vpapi_event();
+				}
+				break;
+
+			case 'b':
+				/* Stop Telephony */
+				release(0);
+				break;
+
+#if defined(MV_TDM_USE_DCO)
+			case 'c':
+				set_tdm_clk_config();
+				break;
+			
+			case 'd':
+				printf("%s Current PPM correction is (+/-1000): %d", TOOL_PREFIX, get_tdm_clk_correction());
+				break;
+
+			case 'e':
+				printf("%s Enter number of PPM for correction (+/-1000, 0 to disable correction): ", TOOL_PREFIX);
+				gets(str);
+				set_tdm_clk_correction((int)atoi(str));
+				break;
+#endif
+			
+			case 'q':
+				goto voice_out;
+
+			default:
+				printf("Option is not supported - try again\n");
+				break;
+		}
+	}
+
+voice_out:
+	release(1);
+
+	return ret;
+}
+
+void release(int signum)
+{
+	if (signum) {
+		printf("\n%s Stopping Phone devices and exit\n", TOOL_PREFIX);
+		sleep(1);
+	} else {
+		printf("\n%s Stopping Phone devices\n", TOOL_PREFIX);
+	}
+
+	/* Stop SLIC/s */
+	if(slic_init) {
+		printf("\n%s Stopping SLIC\n", TOOL_PREFIX);
+		vpapi_release();
+		printf("\n%s Stopped SLIC\n", TOOL_PREFIX);
+		slic_init = 0;
+	} else {
+		printf("\n%s SLIC already stopped\n", TOOL_PREFIX);
+	}
+
+	/* Stop TDM */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_STOP, 0)) {
+		printf("\n%s Error, unable to stop TDM\n", TOOL_PREFIX);
+		return;
+	} else {
+		printf("\n%s TDM stopped\n", TOOL_PREFIX);
+	}
+
+	if (signum)
+		close(tdm_fd);
+
+	if(vpapi_close_device()) {
+		printf("\n%s Error, could not close SLIC device ##\n", TOOL_PREFIX);
+		return;
+	} else {
+		printf("\n%s SLIC device closed\n", TOOL_PREFIX);
+	}
+
+	if (signum)
+		exit(signum);
+}
+
+static void channel_balancing_test(int tdm_fd, unsigned long int iterations)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, cmp_status = 0, ch, cb_loop = 0, i;
+	unsigned long int loops = 0, index;
+	VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Fill Tx buffer with incremental pattern */
+	for(ch = 0; ch < total_lines; ch++) {
+		for(index = 0; index < (80 * pcm_bytes); index+=2)
+			*((unsigned short*)&aud_buf[1][(80 * pcm_bytes * ch) + index]) = (((index+3) << 8)+ (index+1));
+	}
+
+	/* Put SLIC/s in loopback mode */
+	for(ch = 0; ch < total_lines; ch++)
+		vpapi_set_option(1, ch, GET_DEVICE(ch), VP_OPTION_ID_LOOPBACK, &lp);
+
+	/* Wait a bit */
+	sleep(1);
+
+	/* Put SLIC/s in TALK mode */
+	for(ch = 0; ch < total_lines; ch++)
+		vpapi_set_line_state(ch, VP_LINE_TALK);
+
+	/* Wait a bit */
+	sleep(1);
+
+	if (iterations == 0)
+		iterations = (unsigned long int)(-1); /* Assume infinite */
+
+	while (loops < iterations) {
+		cb_loop = 0;
+		i = 0;
+
+		if (ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+			printf("Error, unable to start pcm bus\n");
+			return;
+		}
+
+		while (cb_loop == 0) {
+			FD_ZERO(&rd_fds);
+			FD_ZERO(&wr_fds);
+			FD_SET(tdm_fd, &rd_fds);
+			FD_SET(tdm_fd, &wr_fds);
+
+			/* Wait for event  */
+			if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+				printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+				goto cb_out;
+			}
+
+			/* Write */
+			if (FD_ISSET(tdm_fd, &wr_fds)) {
+				msg_len = write(tdm_fd, aud_buf[1], buff_size);
+				if (msg_len < buff_size) {
+					printf("write() failed\n");
+					goto cb_out;
+				}
+			}
+
+			/* Read */
+			if (FD_ISSET(tdm_fd, &rd_fds)) {
+				memset(aud_buf[0], 0, buff_size);
+				msg_len = read(tdm_fd, aud_buf[0], buff_size);
+				if (msg_len < buff_size) {
+					printf("read() failed\n");
+					goto cb_out;
+				}
+
+				if(i > 3) {
+					for(ch = 1; ch < total_lines; ch++) {
+						if(memcmp(aud_buf[0], &aud_buf[0][(ch * pcm_bytes * 80)], (pcm_bytes * 80))) {
+							printf("\nERROR - data miscompare(ch=%d) !!!\n", ch);
+							cmp_status = 1;
+							goto cb_out;
+						}
+					}
+
+					cb_loop = 1;
+				}
+				i++;
+			}
+
+			/* Reload timeout */
+			timeout.tv_usec = TIMEOUT;
+		}
+
+		loops++;
+		if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+			printf("Error, unable to stop pcm bus\n");
+			return;
+		}
+		printf("loop #%u\n", loops);
+		sleep(1);
+	}
+
+cb_out:
+	if(cmp_status == 0) {
+		printf("\nChannel balancing test PASSED !!!\n");
+	} else {
+		printf("Dump Rx buffer:\n");
+		for(ch = 0; ch < total_lines; ch++) {
+			printf("Buffer #%d: ", ch);
+			for(i = 0; i < (pcm_bytes * 80); i++) {
+				printf("0x%x ", aud_buf[0][(ch * pcm_bytes * 80) + i]);
+			}
+			printf("\n\n");
+			sleep(1);
+		}
+	}
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+
+	lp = VP_OPTION_LB_OFF;
+
+	/* Disable loopback mode */
+	for(ch = 0; ch < total_lines; ch++)
+		vpapi_set_option(1, ch, GET_DEVICE(ch), VP_OPTION_ID_LOOPBACK, &lp);
+
+	/* Put SLIC/s in STANDBY mode */
+	for(ch = 0; ch < total_lines; ch++)
+		vpapi_set_line_state(ch, VP_LINE_STANDBY);
+}
+
+static void slic_digital_loopback(int tdm_fd, unsigned long int iterations)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, cmp_status = 0, ch;
+	unsigned long int loops = 0, index;
+	VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Put SLIC/s in loopback mode */
+	for(ch = 0; ch < total_lines; ch++)
+		vpapi_set_option(1, ch, GET_DEVICE(ch), VP_OPTION_ID_LOOPBACK, &lp);
+
+	/* Wait a bit */
+	sleep(1);
+
+	/* Put SLIC/s in TALK mode */
+	for(ch = 0; ch < total_lines; ch++)
+		vpapi_set_line_state(ch, VP_LINE_TALK);
+
+	/* Fill Tx buffer with incremental pattern */
+	for(ch = 0; ch < total_lines; ch++) {
+		for(index = 0; index < (80 * pcm_bytes); index++)
+			aud_buf[1][index + (80 * pcm_bytes * ch)] = (index+ch+2);
+	}
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while (loops < iterations) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			goto slic_dl_out;
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds)) {
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len < buff_size) {
+				printf("write() failed\n");
+				goto slic_dl_out;
+			}
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds)) {
+			memset(aud_buf[0], 0, buff_size);
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len < buff_size) {
+				printf("read() failed\n");
+				goto slic_dl_out;
+			}
+
+			if(loops++ > 3) {
+				for(ch = 0; ch < total_lines; ch++) {
+					if(slic_dl_data_compare(ch)) {
+						printf("\nERROR - data miscompare(loops=%d) !!!\n",loops);
+						cmp_status = 1;
+						goto slic_dl_out;
+					}
+				}
+			}
+		}
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+slic_dl_out:
+	if(cmp_status == 0)
+		printf("\nDigital loopback test(%d lines) - PASS !!!\n",total_lines);
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+
+	lp = VP_OPTION_LB_OFF;
+
+	/* Disable loopback mode */
+	for(ch = 0; ch < total_lines; ch++)
+		vpapi_set_option(1, ch, GET_DEVICE(ch), VP_OPTION_ID_LOOPBACK, &lp);
+
+	/* Put SLIC/s in STANDBY mode */
+	for(ch = 0; ch < total_lines; ch++)
+		vpapi_set_line_state(ch, VP_LINE_STANDBY);
+}
+
+static inline int slic_dl_data_compare(int ch)
+{
+	int i = 0, offset = (ch * pcm_bytes * 80);
+
+	/* Align Tx & Rx data start */
+	while((aud_buf[1][offset] != aud_buf[0][offset+i]) && (i < (pcm_bytes * 80)))
+		i++;
+
+	if(i >= (offset + (pcm_bytes * 80))) {
+		printf("\nError, first Tx byte not found inside Rx buffer\n");
+		return -1;
+	}
+
+	if(memcmp(&aud_buf[0][offset+i], &aud_buf[1][offset], ((pcm_bytes * 80) - i))) {
+		printf("\nDump buffers:\n");
+		for(i = offset; i < (offset +(pcm_bytes * 80)); i++)
+			printf("write[%d] = 0x%x, read[%d] = 0x%x\n", i, aud_buf[1][i], i, aud_buf[0][i]);
+		return -1;
+	} else {
+		return 0;
+	}
+}
+
+static void sw_loopback(int tdm_fd, unsigned char line_id)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Wait until line goes off-hook */
+	while(hook_state[line_id] == 0) {
+		wait_for_vpapi_event();
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while(hook_state[line_id] == 1) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds)) {
+			printf("Rd\n");
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len <= 0) {
+				printf("read() failed\n");
+				return;
+			}
+			memcpy(BUFF_ADDR(aud_buf[1], line_id), BUFF_ADDR(aud_buf[0], line_id), CH_BUFF_SIZE);
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds)) {
+			printf("Wr\n");
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+				return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_vpapi_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static void gen_tone(unsigned short freq, unsigned char line_id, unsigned char* tx_buff)
+{
+	short i;
+	short buf[80];
+	short sample;
+
+	for(i = 0; i < 80; i++) {
+		sample = (sinTbl[f1Mem >> 8] + sinTbl[f2Mem >> 8]) >> 2;
+#ifndef CONFIG_CPU_BIG_ENDIAN 
+		buf[i] = sample;
+#else
+		buf[i] = ((sample & 0xff) << 8)+ (sample >> 8);
+#endif
+		f1Mem += freq;
+		f2Mem += freq;
+	}
+	memcpy(BUFF_ADDR(tx_buff, line_id), (void *)buf, 160);
+}
+
+static void sw_tone_test(int tdm_fd, unsigned char line_id)
+{
+	fd_set wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, x;
+	char str[4];
+
+	if (tdm_fd <= 0) {
+		printf("%s Device %s is not accessible\n", TOOL_PREFIX, dev_name);
+		return;
+	}
+
+	while(1) {
+		printf("%s Choose frequency: (1) 300HZ (2) 630HZ (3) 1000HZ (4) Back to main menu: ", TOOL_PREFIX);
+		gets(str);
+		printf("%s Waiting for off-hook...\n", TOOL_PREFIX);
+
+		if(str[0] == '1') {
+			x = 2457;
+			//printf("%s Generating 300HZ tone\n", TOOL_PREFIX);
+		}
+		else if (str[0] == '2') {
+			x = 5161;
+			//printf("%s Generating 630HZ tone\n", TOOL_PREFIX);
+		}
+		else if (str[0] == '3') {
+			x = 8192;
+			//printf("%s Generating 1000HZ tone\n", TOOL_PREFIX);
+		}
+		else if (str[0] == '4') {
+			return;
+		}
+		else {
+			printf("%s Input error - try again\n", TOOL_PREFIX);
+			continue;
+		}
+
+		/* Wait until both lines go off-hook */
+		while(hook_state[line_id] == 0) {
+			wait_for_vpapi_event();
+		}
+
+		if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+			printf("Error, unable to start pcm bus\n");
+			return;
+		}
+
+		printf("%s Waiting for on-hook to return to menu.\n", TOOL_PREFIX);
+
+		while(hook_state[line_id] == 1) {
+			FD_ZERO(&wr_fds);
+			FD_SET(tdm_fd, &wr_fds);
+
+			/* Wait for event  */
+			if (select(tdm_fd+1, NULL, &wr_fds, NULL, &timeout) == 0) {
+				printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+				return;
+			}
+
+			/* Write */
+			if (FD_ISSET(tdm_fd, &wr_fds)) {
+				gen_tone(x, line_id, aud_buf[1]);
+				if (pcm_bytes == 4)
+					gen_tone(x, line_id, (aud_buf[1]+160));
+
+				msg_len = write(tdm_fd, aud_buf[1], buff_size);
+				if (msg_len <= 0) {
+					printf("write() failed\n");
+					return;
+				}
+			}
+
+			/* Check hook state */
+			wait_for_vpapi_event();
+
+			/* Reload timeout */
+			timeout.tv_usec = TIMEOUT;
+		}
+	}
+}
+
+static void sw_loopback_multi_phones_test(int tdm_fd, unsigned char start_line, unsigned char end_line)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len;
+	unsigned char line_id;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Wait until at least one line goes off-hook */
+	while(offhook_count == 0) {
+		wait_for_vpapi_event();
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while(offhook_count) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds)) {
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len <= 0) {
+				printf("read() failed\n");
+				return;
+			}
+
+			for(line_id = start_line; line_id < end_line; line_id+=2) {
+				memcpy(BUFF_ADDR(aud_buf[1], line_id), BUFF_ADDR(aud_buf[0], (line_id+1)), CH_BUFF_SIZE);
+				memcpy(BUFF_ADDR(aud_buf[1], (line_id+1)), BUFF_ADDR(aud_buf[0], line_id), CH_BUFF_SIZE);
+			}
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds)) {
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+				return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_vpapi_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static void sw_loopback_two_phones_test(int tdm_fd, unsigned char line0, unsigned char line1)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len;
+
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Wait until both lines go off-hook */
+	while((hook_state[line0] == 0) || (hook_state[line1] == 0)) {
+		wait_for_vpapi_event();
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while((hook_state[line0] == 1) && (hook_state[line1] == 1)) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds)) {
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len <= 0) {
+				printf("read() failed\n");
+				return;
+			}
+			memcpy(BUFF_ADDR(aud_buf[1], line0), BUFF_ADDR(aud_buf[0], line1), CH_BUFF_SIZE);
+			memcpy(BUFF_ADDR(aud_buf[1], line1), BUFF_ADDR(aud_buf[0], line0), CH_BUFF_SIZE);
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds)) {
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+				return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_vpapi_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static int vpapi_init(void)
+{
+	int i = 0;
+	VpDeviceIdType dev_id = 0;
+	VpLineIdType line_id = 0;
+	VpStatusType status;
+	vpapi_init_device_params_t params;
+
+	/* Check params */
+	if(total_lines > MAX_LINES) {
+		printf("## Error, total number of lines(%d) exceeded maximum(%d) ##\n", total_lines, MAX_LINES);
+		return -1;
+	}
+
+	/* Set lines status to on-hook */
+	memset(hook_state, 0, MAX_LINES);
+
+	cal_devs = 0;
+#ifdef LINE_CALIBRATION_SUPPORT
+	cal_lines = 0;
+#endif
+	/* Fill time slot table */
+	memset(time_slot_table, 0, MAX_LINES);
+	for(i = 0; i < total_lines; i++)
+		time_slot_table[i] = ((i+1) * pcm_bytes); /* skip slot #0 */
+
+	/* Extract PCM format */
+	switch(pcm_bytes) {
+		case 1:
+			codec = VP_OPTION_ALAW;
+			break;
+		case 2:
+			codec = VP_OPTION_LINEAR;
+			break;
+		case 4:
+			codec = VP_OPTION_WIDEBAND;
+			break;
+		default:
+			codec = VP_OPTION_ALAW;
+			printf("## Warning, wrong PCM size - set to default(ALAW) ##\n");
+			break;
+	}
+
+#if defined(ZARLINK_SLIC_VE792)
+	/* Bring up the power supply */
+	if(vpapi_battary_on(VBH, VBL, VBP)) {
+		printf("## Error, VE792 power supply could not initialized properly ##\n");
+		return -1;
+	}
+#endif
+	/* Create max device objects */
+	for(dev_id = 0; dev_id < total_devs; dev_id++) {
+		status = vpapi_make_dev_object(VP_DEV_SERIES, dev_id);
+		if (status != VP_STATUS_SUCCESS) {
+			printf("## Error, device %d could not initialized properly(status=%d) ##\n", dev_id, status);
+			return -1;
+		}
+
+#if defined(ZARLINK_SLIC_VE792)
+		status = vpapi_map_slac_id(dev_id, 0);
+		if (status != VP_STATUS_SUCCESS) {
+			printf("## Error, SLAC %d could not be mapped(status=%d) ##\n", dev_id, status);
+			return -1;
+		}
+#endif
+		/* Create requested channels for each device */
+		while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
+			status = vpapi_make_line_object(VP_TERM_FXS_GENERIC, line_id);
+			if (status != VP_STATUS_SUCCESS) {
+				printf("## Error, line %d of device %d could not initialized \
+					roperly(status=%d) ##\n", line_id, dev_id, status);
+				return -1;
+			}
+
+			/* Map unique LineId to LineCtx */
+			status = vpapi_map_line_id(line_id);
+
+			if (status != VP_STATUS_SUCCESS) {
+				printf("## Error, line %d for device %d could not \
+					mapped(status=%d) ##\n", line_id, dev_id, status);
+				return -1;
+			}
+			line_id++;
+		}
+
+		params.dev_size = dev_profile_size;
+		params.ac_size = ac_profile_size;
+		params.dc_size = dc_profile_size;
+		params.ring_size = ring_profile_size;
+		params.fxo_ac_size = 0;
+		params.fxo_cfg_size = 0;
+
+		if (pcm_bytes < 4)
+			status = vpapi_init_device(dev_id, DEV_PROFILE, AC_COEFF, DC_COEFF, RING_PROFILE, NULL, NULL, &params);
+		else
+			status = vpapi_init_device(dev_id, DEV_PROFILE, WB_AC_COEFF, DC_COEFF, RING_PROFILE, NULL, NULL, &params);
+
+		if (status != VP_STATUS_SUCCESS) {
+			printf("## Error, device(%d) init failed(status=%d)\n", dev_id, status);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static inline void wait_for_vpapi_event(void)
+{
+	bool status;
+	VpEventType event;
+	VpDeviceIdType dev_id;
+
+	for(dev_id = 0; dev_id < total_devs ; dev_id++) {
+		while(vpapi_get_event(dev_id, &event) == true) {
+			switch(event.eventCategory) {
+				case VP_EVCAT_SIGNALING:
+					switch(event.eventId) {
+						case VP_LINE_EVID_HOOK_OFF:
+							if(cal_devs == total_devs) {
+								printf("off-hook(%d)\n", event.lineId);
+								hook_state[event.lineId] = 1;
+								offhook_count++;
+								vpapi_set_line_state(event.lineId, VP_LINE_TALK);
+							}
+							break;
+
+						case VP_LINE_EVID_HOOK_ON:
+							if(cal_devs == total_devs) {
+								printf("on-hook(%d)\n", event.lineId);
+								hook_state[event.lineId] = 0;
+								offhook_count--;
+								vpapi_set_line_state(event.lineId, VP_LINE_STANDBY);
+							}
+							break;
+
+						default:
+							/*printf("Unknown SIGNALING event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);*/
+							break;
+					}
+					break;
+
+				case VP_EVCAT_RESPONSE:
+					switch(event.eventId) {
+						case VP_DEV_EVID_DEV_INIT_CMP:
+							printf("Zarlink telephony device(%d) initialized successfully\n", event.deviceId);
+							vpapi_dev_init(event.deviceId);
+							cal_devs++;
+							break;
+
+						case VP_EVID_CAL_CMP:
+#ifdef LINE_CALIBRATION_SUPPORT
+							cal_lines++;
+							if(cal_lines == total_lines) {
+								/*VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
+								vpapi_set_option(1, 0, 0, VP_OPTION_ID_LOOPBACK, &lp); */
+								printf("Zarlink telephony lines(%d) calibrated successfully\n", total_lines);
+								vpapi_init_done();
+							}
+#endif
+							break;
+
+						default:
+							/*printf("Unknown RESPONSE event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);*/
+							break;
+					}
+					break;
+
+				case VP_EVCAT_FAULT:
+					printf("Got FAULT event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);
+					break;
+
+				default:
+					printf("Got event[category-0x%x][id-%d]\n",event.eventCategory,event.eventId);
+					break;
+			}
+		}
+	}
+}
+
+static void vpapi_init_done(void)
+{
+	VpStatusType status;
+	VpDeviceIdType dev_id;
+	VpLineIdType line_id, base_line_id;
+
+	for (dev_id = 0; dev_id < total_devs; dev_id++) {
+		base_line_id = (dev_id * MAX_DEVICE_LINES);
+		for (line_id = base_line_id; line_id < (base_line_id + MAX_DEVICE_LINES); line_id++) {
+			/* Set CODEC options */
+			status = vpapi_set_option(1, line_id, dev_id, VP_OPTION_ID_CODEC, &codec);
+			if(status != VP_STATUS_SUCCESS) {
+				printf("## Error setting VP_OPTION_ID_CODEC (%d) ##\n", status);
+				return;
+			}
+		}
+	}
+
+	return;
+}
+
+static void vpapi_dev_init(VpDeviceIdType dev_id)
+{
+	VpOptionEventMaskType event_mask;
+	VpStatusType status;
+	VpOptionTimeslotType time_slot;
+	VpLineIdType line_id;
+
+	/* Clear all events */
+	memset(&event_mask, 0xff, sizeof(VpOptionEventMaskType));
+
+	event_mask.faults = (unsigned short)VP_EVCAT_FAULT_UNMASK_ALL;
+	event_mask.signaling = (unsigned short)(~(VP_LINE_EVID_HOOK_OFF | VP_LINE_EVID_HOOK_ON));
+#ifdef LINE_CALIBRATION_SUPPORT
+	event_mask.response = (unsigned short)(~VP_EVID_CAL_CMP);
+#endif
+	status = vpapi_set_option(0, N_A, dev_id, VP_OPTION_ID_EVENT_MASK, &event_mask);
+	if(status != VP_STATUS_SUCCESS) {
+		printf("## Error while setting VP_OPTION_ID_EVENT_MASK (%d) ##\n", status);
+		return;
+	}
+
+	line_id = (dev_id * MAX_DEVICE_LINES);
+	while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
+		vpapi_set_line_state(line_id, VP_LINE_STANDBY);
+
+		/* Configure PCM timeslots */
+		time_slot.tx = time_slot.rx = time_slot_table[line_id];
+
+		/*printf("## INFO: line(%d): rx-slot(%d) , tx-slot(%d) ##\n", line_id, time_slot.rx, time_slot.tx);*/
+
+		status = vpapi_set_option(1, line_id, dev_id, VP_OPTION_ID_TIMESLOT, &time_slot);
+		if(status != VP_STATUS_SUCCESS) {
+			printf("## Error setting VP_OPTION_ID_TIMESLOT (%d) ##\n", status);
+			return;
+		}
+#if 0
+		/* Set CODEC options */
+		status = vpapi_set_option(1, line_id, dev_id, VP_OPTION_ID_CODEC, &codec);
+		if(status != VP_STATUS_SUCCESS) {
+			printf("## Error setting VP_OPTION_ID_CODEC (%d) ##\n", status);
+			return;
+		}
+#endif		
+#ifdef LINE_CALIBRATION_SUPPORT	
+		/* Start line calibration */
+		vpapi_cal_line(line_id);
+#endif
+		line_id++;
+	}
+}
+
+static void vpapi_release(void)
+{
+	VpDeviceIdType dev_id = 0;
+	VpLineIdType line_id = 0;
+	VpOptionEventMaskType event_mask;
+	VpStatusType status;
+
+
+	/* Clear all events */
+	memset(&event_mask, 0xff, sizeof(VpOptionEventMaskType));
+
+	for(dev_id = 0; dev_id < total_devs; dev_id++) {
+		/* Mask all interrupts */
+		status = vpapi_set_option(0, N_A, dev_id, VP_OPTION_ID_EVENT_MASK, &event_mask);
+
+		if(status != VP_STATUS_SUCCESS) {
+			printf("Error while setting VP_OPTION_ID_EVENT_MASK (%d)\n", status);
+			continue;
+		}
+
+		while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
+			/* Place each line in DISCONNECT state */
+			vpapi_set_line_state(line_id, VP_LINE_DISCONNECT);
+
+			/* Free line context */
+			status = vpapi_free_line_context(line_id);
+			if(status != VP_STATUS_SUCCESS) {
+				printf("Error while free line %d context\n", line_id);
+				continue;
+			}
+			line_id++;
+		}
+	}
+#if defined(ZARLINK_SLIC_VE792)
+	/* Shut down the power supply */
+	if(vpapi_battery_off()) {
+		printf("## Error while shutting down VE792 power supply ##\n");
+		sleep(1);
+	}
+#endif
+}
+
+#if defined(MV_TDM_USE_DCO)
+static void set_tdm_clk_config(void)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	/* Config TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_CONFIG, &tdm_dev_clk)) {
+		printf("%s Error, unable to config TDM clock.\n", TOOL_PREFIX);
+	}
+}
+
+static int get_tdm_clk_correction(void)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	/* Get TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_GET, &tdm_dev_clk)) {
+		printf("%s Error, unable to get TDM clock.\n", TOOL_PREFIX);
+		return 0;
+	}
+
+	return tdm_dev_clk.correction;
+}
+
+static void set_tdm_clk_correction(int correction)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	tdm_dev_clk.correction=correction;
+
+	/* Set TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_SET, &tdm_dev_clk)) {
+		printf("%s Error, unable to set TDM clock.\n", TOOL_PREFIX);
+	}
+}
+#endif
diff --git a/tools/voice/zarlink/kernel/mv_voice_tool.h b/tools/voice/zarlink/kernel/mv_voice_tool.h
new file mode 100644
index 0000000..f3e4abb
--- /dev/null
+++ b/tools/voice/zarlink/kernel/mv_voice_tool.h
@@ -0,0 +1,84 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell 
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File in accordance with the terms and conditions of the General 
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
+available along with the File in the license.txt file or by writing to the Free 
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
+DISCLAIMED.  The GPL License provides additional details about this warranty 
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or 
+modify this File under the following licensing terms. 
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer. 
+
+    *   Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution. 
+
+    *   Neither the name of Marvell nor the names of its contributors may be 
+        used to endorse or promote products derived from this software without 
+        specific prior written permission. 
+    
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#ifndef _MVZARLINKIF_H_
+#define _MVZARLINKIF_H_
+
+#include "mvSysTdmConfig.h"
+#include "voiceband/mvSysTdmSpi.h"
+
+MV_STATUS mvZarlinkIfInit(MV_U16 totalSLICs, MV_U16 pSlotInfo[][2], 
+				MV_BAND_MODE bandMode, MV_PCM_FORMAT pcmFormat);
+MV_STATUS mvZarlinkIfTimerTick(MV_SLIC_EVENT_INFO* slic_event_info);
+MV_VOID mvZarlinkIfISR(MV_U8 deviceId);
+MV_VOID mvZarlinkIfActivateRinging(MV_U16 lineId);
+MV_VOID mvZarlinkIfStopRinging(MV_U16 lineId);
+MV_VOID mvZarlinkIfHookStateGet(MV_U16 lineId, MV_U8* hookstate);
+MV_VOID mvZarlinkIfLinefeedControlSet(MV_U16 lineId, MV_LINEFEED_STATE lfState);
+MV_VOID mvZarlinkIfLinefeedControlGet(MV_U16 lineId, MV_LINEFEED_STATE* lfState);
+MV_VOID mvZarlinkIfReverseDcPolarity(MV_U16 lineId);
+MV_VOID mvZarlinkIfRelease(MV_VOID);
+MV_VOID mvZarlinkIfRegRead(MV_U8 lineId, MV_U8 cmd, MV_U8 cmdLen,MV_U8* dataBuff);
+
+#endif /* _MVZARLINKIF_H_ */
diff --git a/tools/voice/zarlink/kernel/profile_79238.c b/tools/voice/zarlink/kernel/profile_79238.c
new file mode 100644
index 0000000..7b2e1b7
--- /dev/null
+++ b/tools/voice/zarlink/kernel/profile_79238.c
@@ -0,0 +1,1248 @@
+/*

+ * profile_79238.c --

+ *

+ * This file contains profile data in byte format

+ *

+ * Project Info --

+ *   File:  C:\Documents and Settings\benavi\Desktop\profile_792\792.vpw

+ *   Type:  VCP2-792 Project (Line Module Le51HR0128)

+ *   Date:  Wednesday, June 30, 2010 14:29:56

+ *

+ *   This file was generated with Profile Wizard Version: P1.14.1

+ */

+

+#include "profile_79238.h"

+

+/*** Device_Parameters for VE792 Device Family ***/

+const VpProfileDataType VE792_DEV_PROFILE[] =

+{

+    /* Device Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0xFF,       /* 0xFF = device profile */

+        /* number of sections */    0x02,

+        /* content length */        0x24,        /* (2 + 5) + (2 + 27)      */

+    /* Section 0 ----------------------------------------------(PRE-BOOT)-- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x05,

+        /* Access 0 */

+            /* access type */       0x00,       /* 0x00 = direct page write */

+            /* page offset */       0x0B,       /* CLK_CFG register */

+            /* length */            0x01,

+            /* data */              0x00, 0x0A, /* PCLK = 8192 KHz */

+    /* Section 1 ---------------------------------------------(POST-BOOT)-- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x1B,       /* 5 + 11 + 11 */

+        /* Access 0 */

+            /* access type */       0x00,       /* 0x00 = direct page write */

+            /* page offset */       0x09,       /* PCM_CFG register */

+            /* length */            0x01,

+            /* data */              0x00, 0x40, /* Pos. edge, RCS 0, TCS 0 */

+        /* Access 1 */

+            /* access type */       0x00,       /* 0x00 = direct page write */

+            /* page offset */       0x32,       /* HBAT_ADJ + TBAT register */

+            /* length */            0x04,

+            /* data */              0x00, 0x00, /* HBAT_ADJ = 0 V */

+            /* data */              0xEC, 0xCD, /* THBAT = -30 V */

+            /* data */              0xF6, 0x66, /* TLBAT = -15 V */

+            /* data */              0x13, 0x33, /* TPBAT = 30 V */

+        /* Access 2 */

+            /* access type */       0x00,       /* 0x00 = direct page write */

+            /* page offset */       0x38,

+            /* length */            0x04,

+            /* data */              0x7F, 0xFF,

+            /* data */              0x7F, 0xFF,

+            /* data */              0x7F, 0xFF,

+            /* data */              0x00, 0x00

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/************** AC_Coefficients **************/

+

+/* AC Parameters (600) */

+const VpProfileDataType VE792_AC_COEFF_600[] = 

+{

+    /* AC Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x00,       /* 0x00 = AC profile */

+        /* number of sections */    0x01,

+        /* content length */        0x74,     /* (2 + 81) + 1 + 32 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x01,       /* 0x01 = mailbox command */

+        /* content length */        0x51,       /* 81 */

+        /* command ID */            0x2A,       /* 0x2A = WR_AC_PARAM */

+        /* data */

+            /* AC_MASK */           0x01, 0xFF,

+            /* Z FIR */             0x00, 0x22, 0xBA, 0x74, 0x45, 0x3E, 0x33,

+                                    0x5A, 0x24, 0xDC, 0x4B,

+            /* Z IIR */             0x22, 0x22, 0x97, 0x9F, 0x01,

+            /* GR */                0xA2, 0xA0,

+            /* R IIR */             0xDC, 0x01,

+            /* R FIR */             0x2A, 0x10, 0xAD, 0xC9, 0x22, 0x27, 0x22,

+                                    0x52, 0x3F, 0xBA, 0xC3, 0xB4,

+            /* B FIR */             0x00, 0x3C, 0x7A, 0x4B, 0xAF, 0x9A, 0xA9,

+                                    0xC6, 0xBA, 0x37, 0x24, 0x6B, 0x8F, 0x3B,

+                                    0x70,

+            /* B IIR */             0x2E, 0x01,

+            /* GX */                0x3A, 0x30,

+            /* X FIR */             0x3D, 0x20, 0x9F, 0x2A, 0xA3, 0x4E, 0x4B,

+                                    0x23, 0x52, 0xAB, 0xBB, 0x97, 0x00,

+            /* AISN */              0x00, 0x05,

+            /* DISN */              0x00, 0x01, 0x00, 0x07, 0x00, 0x6F, 0x00,

+                                    0x1C, 0x00, 0x80,

+            /* MTR_CFG */           0x00, 0x00,

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00,         /* VP_CFG2 bit LRG = 0 */

+        /* Meter LUT */             0x11, 0x5F,   /* Shadow Register 1 12KHz 2/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x2F,   /* Shadow Register 1 12KHz 4/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x77,   /* Shadow Register 1 12KHz 6/8 */

+                                    0x08, 0x0C,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x77,   /* Shadow Register 1 12KHz 8/8 */

+                                    0x0C, 0x12,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x9F,   /* Shadow Register 1 16KHz 2/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x67,   /* Shadow Register 1 16KHz 4/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x2F,   /* Shadow Register 1 16KHz 6/8 */

+                                    0x08, 0x0C,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x2F,   /* Shadow Register 1 16KHz 8/8 */

+                                    0x0C, 0x12    /* Shadow Register 2 */

+

+};

+

+/* AC Parameters (900) */

+const VpProfileDataType AC_COEFF_900[] = 

+{

+    /* AC Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x00,       /* 0x00 = AC profile */

+        /* number of sections */    0x01,

+        /* content length */        0x74,     /* (2 + 81) + 1 + 32 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x01,       /* 0x01 = mailbox command */

+        /* content length */        0x51,       /* 81 */

+        /* command ID */            0x2A,       /* 0x2A = WR_AC_PARAM */

+        /* data */

+            /* AC_MASK */           0x01, 0xFF,

+            /* Z FIR */             0x00, 0x4A, 0xCA, 0xBD, 0xA5, 0x43, 0x23,

+                                    0x2B, 0xA3, 0xC2, 0x3B,

+            /* Z IIR */             0xA3, 0xA1, 0x97, 0x9F, 0x01,

+            /* GR */                0xA2, 0xB0,

+            /* R IIR */             0xDC, 0x01,

+            /* R FIR */             0x3A, 0x10, 0xAD, 0xD9, 0xC3, 0xA7, 0x42,

+                                    0x42, 0xA3, 0xBA, 0x2B, 0xA4,

+            /* B FIR */             0x00, 0xAA, 0x73, 0x4B, 0x2F, 0x9B, 0xA9,

+                                    0xA5, 0xB3, 0xA6, 0x2A, 0x5C, 0x87, 0xCA,

+                                    0x70,

+            /* B IIR */             0x2E, 0x01,

+            /* GX */                0xA3, 0xA0,

+            /* X FIR */             0x27, 0x20, 0xC2, 0x2A, 0x4A, 0x2E, 0x23,

+                                    0x23, 0x22, 0x2C, 0x2A, 0x87, 0x00,

+            /* AISN */              0x00, 0x0A,

+            /* DISN */              0x00, 0x01, 0x00, 0x07, 0x00, 0x72, 0x00,

+                                    0x35, 0x00, 0x80,

+            /* MTR_CFG */           0x00, 0x00,

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00,         /* VP_CFG2 bit LRG = 0 */

+        /* Meter LUT */             0x11, 0x5F,   /* Shadow Register 1 12KHz 2/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x2F,   /* Shadow Register 1 12KHz 4/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x77,   /* Shadow Register 1 12KHz 6/8 */

+                                    0x08, 0x0C,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x77,   /* Shadow Register 1 12KHz 8/8 */

+                                    0x0C, 0x12,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x9F,   /* Shadow Register 1 16KHz 2/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x67,   /* Shadow Register 1 16KHz 4/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x2F,   /* Shadow Register 1 16KHz 6/8 */

+                                    0x08, 0x0C,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x2F,   /* Shadow Register 1 16KHz 8/8 */

+                                    0x0C, 0x12    /* Shadow Register 2 */

+

+};

+

+/************** DC_Parameters **************/

+

+/* DC Parameters */

+const VpProfileDataType VE792_DC_COEFF[] = 

+{

+    /* DC Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x01,       /* 0x01 = DC profile */

+        /* number of sections */    0x02,

+        /* content length */        0x25,       /* (2 + 13) + (2 + 20) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x01,       /* 0x01 = mailbox command */

+        /* content length */        0x0D,       /* 13 */

+        /* command ID */            0x2C,       /* 0x2C = WR_DC_PARAM */

+        /* data */                  0x11, 0x11, /* V1 */

+        /* data */                  0x11, 0xEC, /* VAS */

+        /* data */                  0x01, 0x1C, /* VAS_OFFSET */

+        /* data */                  0x55, 0x55, /* RFD */

+        /* data */                  0x80, 0x00, /* RPTC */

+        /* data */                  0x49, 0x25, /* ILA */

+    /* Section 1 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x14,       /* 20 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x33,       /* LOOP_SUP register */

+            /* length */            0x06,

+            /* data */              0xF3, 0x33, /* TGK */

+            /* data */              0x00, 0xC8, /* PGK */

+            /* data */              0x0B, 0xB8, /* TSH */

+            /* data */              0x00, 0x1E, /* DSH */

+            /* data */              0x40, 0x00, /* IFTA */

+            /* data */              0x0C, 0xCD, /* IFTD */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x3C,       /* LOOP_SUP register, HSH */

+            /* length */            0x01,

+            /* data */              0x03, 0xE8  /* HSH */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/************** Ring_Parameters **************/

+

+/* Ringing 20Hz, Sine Wave, 40Vrms */

+const VpProfileDataType RING_20HZ_SINE[] = 

+{

+    /* Ring Profile */

+    /* Balanced, Sinusoidal, Crest Factor 1.4142 */

+    /* 20 Hz, 82.86 Vpk, 15.33 V Tip Bias, 4.67 V Ring Bias */

+    /* Ring Trip: Short Loop 41.9 mA, Long Loop 8 mA */

+    /*            Current Spike Threshold 100 mA */

+    /*            Averaging Period 50 ms */

+    /* Ring Exit Hook Switch Debounce: Threshold 0 ms, Duration 0 ms */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x04,       /* 0x04 = ringing profile */

+        /* number of sections */    0x01,

+        /* content length */        0x22,       /* (2 + 32) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x20,       /* 32 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x22,       /* RING register */

+            /* length */            0x0B,       /* 11 */

+            /* data */              0x30, 0x00, /* R control / FRQR[23:16] */

+            /* data */              0xA3, 0xD7, /* FRQR[15:0] */

+            /* data */              0x46, 0xB6, /* AMPR */

+            /* data */              0x0D, 0x15, /* RBA */

+            /* data */              0x03, 0xFC, /* RBB */

+            /* data */              0x04, 0x05, /* EBR */

+            /* data */              0x35, 0xAB, /* RTSL */

+            /* data */              0x0A, 0x3D, /* RTLL */

+            /* data */              0x00, 0x19, /* RTAP */

+            /* data */              0x00, 0x00, /* RSVD */

+            /* data */              0x7F, 0xFF, /* IST */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x3A,       /* REDSH, REDD */

+            /* length */            0x02,

+            /* data */              0x00, 0x00, /* REDSH */

+            /* data */              0x00, 0x00  /* REDD */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Ringing 25Hz, Sine Wave, 40Vrms */

+const VpProfileDataType RING_25HZ_SINE[] = 

+{

+    /* Ring Profile */

+    /* Balanced, Sinusoidal, Crest Factor 1.4142 */

+    /* 25 Hz, 66.31 Vpk, 15.33 V Tip Bias, 4.67 V Ring Bias */

+    /* Ring Trip: Short Loop 19 mA, Long Loop 8 mA */

+    /*            Current Spike Threshold 100 mA */

+    /*            Averaging Period 40 ms */

+    /* Ring Exit Hook Switch Debounce: Threshold 0 ms, Duration 0 ms */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x04,       /* 0x04 = ringing profile */

+        /* number of sections */    0x01,

+        /* content length */        0x22,       /* (2 + 32) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x20,       /* 32 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x22,       /* RING register */

+            /* length */            0x0B,       /* 11 */

+            /* data */              0x30, 0x00, /* R control / FRQR[23:16] */

+            /* data */              0xCC, 0xCD, /* FRQR[15:0] */

+            /* data */              0x38, 0x97, /* AMPR */

+            /* data */              0x0D, 0x15, /* RBA */

+            /* data */              0x03, 0xFC, /* RBB */

+            /* data */              0x04, 0x05, /* EBR */

+            /* data */              0x18, 0x49, /* RTSL */

+            /* data */              0x0A, 0x3D, /* RTLL */

+            /* data */              0x00, 0x14, /* RTAP */

+            /* data */              0x00, 0x00, /* RSVD */

+            /* data */              0x7F, 0xFF, /* IST */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x3A,       /* REDSH, REDD */

+            /* length */            0x02,

+            /* data */              0x00, 0x00, /* REDSH */

+            /* data */              0x00, 0x00  /* REDD */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/************** Call_Progress_Tones **************/

+

+/* US Dial Tone */

+const VpProfileDataType TONE_DIAL[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0B,

+            /* data */              0x33, 0x33, /* FreqA = 350Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x0E, 0x14, /* FreqB = 440Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* US Ringback Tone */

+const VpProfileDataType TONE_RINGBACK[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0E,

+            /* data */              0x14, 0x7B, /* FreqA = 440Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x0F, 0x5C, /* FreqB = 480Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* US Busy Tone */

+const VpProfileDataType TONE_BUSY[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0F,

+            /* data */              0x5C, 0x29, /* FreqA = 480Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x13, 0xD7, /* FreqB = 620Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* US Reorder Tone */

+const VpProfileDataType TONE_REORDER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0F,

+            /* data */              0x5C, 0x29, /* FreqA = 480Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x13, 0xD7, /* FreqB = 620Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* US Howler Tone (ROH) */

+const VpProfileDataType TONE_US_HOWLER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x2C,

+            /* data */              0xCC, 0xCD, /* FreqA = 1400Hz */

+            /* data */              0x58, 0xD6, /* AmpA  = 0dBm0 */

+            /* data */              0x41, 0xEC, /* FreqB = 2060Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x4E, 0x66, /* FreqC = 2450Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x53, 0x33, /* FreqD = 2600Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x0F  /* Generator control = ABCD */

+};

+

+/* UK Howler Tone */

+const VpProfileDataType TONE_UK_HOWLER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x13,       /* (2 + 15) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0F,       /* 15 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x02,       /* SIG_GEN register */

+            /* length */            0x06,

+            /* data */              0x34, 0xCD, /* 1650Hz Offset */

+            /* data */              0x20, 0x00, /* Periodic, Linear */

+            /* data */              0x08, 0x31, /* FreqA = 1Hz */

+            /* data */              0x1B, 0x33, /* AmpA = 850Hz */

+            /* data */              0x80, 0x00, /* FreqB = Freq Modulated */

+            /* data */              0x00, 0x00, /* AmpB = Sequence control */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x13  /* Generators = Bias+AB */

+};

+

+/* Australia Howler Tone */

+const VpProfileDataType TONE_AUS_HOWLER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x13,       /* (2 + 15) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0F,       /* 15 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x02,       /* SIG_GEN register */

+            /* length */            0x06,

+            /* data */              0x4B, 0x33, /* 2350Hz Offset */

+            /* data */              0x20, 0x00, /* Periodic, Linear */

+            /* data */              0x08, 0x31, /* FreqA = 1Hz */

+            /* data */              0x1B, 0x33, /* AmpA = 850Hz */

+            /* data */              0x80, 0x00, /* FreqB = Freq Modulated */

+            /* data */              0x00, 0x00, /* AmpB = Sequence control */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x13  /* Generators = Bias+AB */

+};

+

+/* Japan Howler Tone */

+const VpProfileDataType TONE_NTT_HOWLER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x11,       /* (2 + 13) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0D,       /* 13 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x05,

+            /* data */              0x00, 0x00, /* One-shot, Linear */

+            /* data */              0x00, 0x23, /* FreqA = 15s Ramp */

+            /* data */              0x7F, 0xFF, /* AmpA = Maximum */

+            /* data */              0x0C, 0xCD, /* FreqB = 400Hz */

+            /* data */              0x80, 0x00, /* AmpB = Ampl Modulated */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* Special Information Tone (Called Number Not Connected) */

+const VpProfileDataType TONE_SIT[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x1E,

+            /* data */              0x66, 0x66, /* FreqA = 950Hz */

+            /* data */              0x23, 0x5D, /* AmpA  = -8dBm0 */

+            /* data */              0x2C, 0xCD, /* FreqB = 1400Hz */

+            /* data */              0x23, 0x5D, /* AmpB  = -8dBm0 */

+            /* data */              0x39, 0x9A, /* FreqC = 1800Hz */

+            /* data */              0x23, 0x5D, /* AmpC  = -8dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x07  /* Generator control = ABC */

+};

+

+/* A 1kHz tone at -10dBm0 */

+const VpProfileDataType TONE_ONEKHZ_L[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x20,

+            /* data */              0x00, 0x00, /* FreqA = 1000Hz */

+            /* data */              0x1C, 0x17, /* AmpA  = -10dBm0 */

+            /* data */              0x00, 0x00, /* FreqB = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x01  /* Generator control = A */

+};

+

+/* A 1kHz tone at 0dBm0 */

+const VpProfileDataType TONE_ONEKHZ_H[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x20,

+            /* data */              0x00, 0x00, /* FreqA = 1000Hz */

+            /* data */              0x58, 0xD6, /* AmpA  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqB = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x01  /* Generator control = A */

+};

+

+/* Call Waiting Beep */

+const VpProfileDataType TONE_CALLWAIT[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0E,

+            /* data */              0x14, 0x7B, /* FreqA = 440Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqB = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x01  /* Generator control = A */

+};

+

+/* Caller ID Alert Tone */

+const VpProfileDataType TONE_CLI[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x44,

+            /* data */              0x28, 0xF6, /* FreqA = 2130Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x58, 0x00, /* FreqB = 2750Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/************** Cadence_Definitions **************/

+

+/* US Dial Tone Cadence */

+const VpProfileDataType TONE_CAD_DIAL[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x06,       /* (2 + 4) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x04,       /* 4 */

+        /* data */                  0x00, 0x00, /* sequence length = 1 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Stutter Dial Tone Cadence */

+const VpProfileDataType TONE_CAD_STUTTER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x10,       /* (2 + 14) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0E,       /* 14 */

+        /* data */                  0x00, 0x05, /* sequence length = 6 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+        /* data */                  0x40, 0x64, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x40, 0x64, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x60, /* 04 - Branch to 00 */

+        /* data */                  0x05, 0x03, /* 05 - Generator Ctrl */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* US Ringback Tone Cadence */

+const VpProfileDataType TONE_CAD_RINGBACK[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x0E,       /* (2 + 12) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+        /* data */                  0x47, 0xD0, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x4F, 0xA0, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* US Busy Tone Cadence */

+const VpProfileDataType TONE_CAD_BUSY[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x0E,       /* (2 + 12) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+        /* data */                  0x41, 0xF4, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x41, 0xF4, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* US Reorder Tone Cadence */

+const VpProfileDataType TONE_CAD_REORDER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x0E,       /* (2 + 12) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+        /* data */                  0x40, 0xFA, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x40, 0xFA, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* US Howler Tone Cadence (ROH) */

+const VpProfileDataType TONE_CAD_US_HOWLER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x0E,       /* (2 + 12) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x05, 0x0F, /* 00 - Generator Ctrl */

+        /* data */                  0x40, 0x64, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x40, 0x64, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* UK Howler Tone Cadence */

+const VpProfileDataType TONE_CAD_UK_HOWLER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = Tone cadence prof */

+        /* number of sections */    0x01,

+        /* content length */        0x38,       /* (2 + 54) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x36,       /* 54 */

+        /* data */                  0x00, 0x19, /* sequence length = 26 */

+        /* data */                  0x05, 0x13,

+        /* data */                  0x82, 0x04,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x82, 0x8A,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x83, 0x33,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x84, 0x07,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x85, 0x12,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x86, 0x62,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x88, 0x09,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x8A, 0x1E,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x8C, 0xBD,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x90, 0x09,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x94, 0x30,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x99, 0x6A,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x9F, 0xFF

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Australia Howler Tone Cadence */

+const VpProfileDataType TONE_CAD_AUS_HOWLER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = Tone cadence prof */

+        /* number of sections */    0x01,

+        /* content length */        0x44,       /* (2 + 66) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x42,       /* 66 */

+        /* data */                  0x00, 0x1F, /* sequence length = 32 */

+        /* data */                  0x05, 0x13,

+        /* data */                  0x81, 0x03,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x81, 0x46,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x81, 0x9B,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x82, 0x05,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x82, 0x8B,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x83, 0x33,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x84, 0x07,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x85, 0x12,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x86, 0x62,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x88, 0x0A,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x8A, 0x1E,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x8C, 0xBD,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x90, 0x0A,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x94, 0x31,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x99, 0x6B,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x9F, 0xFF

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Japan Howler Tone Cadence */

+const VpProfileDataType TONE_CAD_NTT_HOWLER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x06,       /* (2 + 4) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x04,       /* 4 */

+        /* data */                  0x00, 0x00, /* sequence length = 1 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Special Information Tone Cadence */

+const VpProfileDataType TONE_CAD_SIT[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x12,       /* (2 + 16) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x10,       /* 16 */

+        /* data */                  0x00, 0x06, /* sequence length = 7 */

+        /* data */                  0x05, 0x01, /* 00 - Generator Ctrl */

+        /* data */                  0x41, 0x2C, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x02, /* 02 - Generator Ctrl */

+        /* data */                  0x41, 0x2C, /* 03 - Sequential Delay */

+        /* data */                  0x05, 0x04, /* 04 - Generator Ctrl */

+        /* data */                  0x41, 0x2C, /* 05 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 06 - Generator Ctrl */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Standard Ringing Cadence */

+const VpProfileDataType RING_CAD_STD[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x08,       /* 0x08 = ring cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x12,       /* (2 + 16) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x10,       /* 16 */

+        /* data */                  0x00, 0x06, /* sequence length = 7 */

+        /* data */                  0x02, 0x86, /* 00 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x47, 0xD0, /* 01 - Sequential Delay */

+        /* data */                  0x02, 0x83, /* 02 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x4F, 0xA0, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Ringing Cadence with CallerID */

+const VpProfileDataType RING_CAD_CID[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x08,       /* 0x08 = ring cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x28,       /* (2 + 38) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x26,       /* 38 */

+        /* data */                  0x00, 0x11, /* sequence length = 18 */

+        /* data */                  0x02, 0x86, /* 00 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x47, 0xD0, /* 01 - Sequential Delay */

+        /* data */                  0x02, 0x83, /* 02 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x0A, 0x00, /* 03 - Relative Time Marker */

+        /* data */                  0x40, 0xC8, /* 04 - Sequential Delay */

+        /* data */                  0x02, 0x85, /* 05 - Line State */

+        /* data */                  0x01, 0x3A,

+        /* data */                  0x01, 0x22, /* 06 - Start CallerID */

+        /* data */                  0x6F, 0xA0, /* 07 - Relative Delay */

+        /* data */                  0x02, 0x86, /* 08 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x47, 0xD0, /* 09 - Sequential Delay */

+        /* data */                  0x02, 0x83, /* 10 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x4F, 0xA0, /* 11 - Sequential Delay */

+        /* data */                  0x10, 0x0B, /* 12 - Branch to 08 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Ringing Always On */

+const VpProfileDataType RING_CAD_ON[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x08,       /* 0x08 = ring cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x08,       /* (2 + 6) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x06,       /* 6 */

+        /* data */                  0x00, 0x01, /* sequence length = 2 */

+        /* data */                  0x02, 0x86, /* 00 - Line State */

+        /* data */                  0x01, 0x3B,

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/************** Caller_ID **************/

+

+/* US Caller ID Type II */

+const VpProfileDataType CID_TYPE2_US[] = 

+{

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x05,       /* 0x05 = caller ID profile */

+        /* number of sections */    0x04,

+        /* content length */        0x70,       /* 112 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequencer program */

+        /* content length */        0x24,       /* 36 */

+        /* data */                  0x00, 0x10, /* sequence length = 17 */

+        /* data */                  0x01, 0x3B, /* Mute on */

+        /* data */                  0x01, 0x3D, /* Alert tone 300ms */

+        /* data */                  0x41, 0x2C, /* - TONE_CALLWAIT */

+        /* data */                  0x05, 0x00,

+        /* data */                  0x40, 0x0A, /* Silence 10ms */

+        /* data */                  0x01, 0x3E, /* Alert tone 80ms */

+        /* data */                  0x40, 0x50, /* - TONE_CLI */

+        /* data */                  0x05, 0x00,

+        /* data */                  0x01, 0x32, /* Detect interval 160ms */

+        /* data */                  0x40, 0xA0, /* - Tones: A, D */

+        /* data */                  0x09, 0xB2,

+        /* data */                  0x40, 0x64, /* Silence 100ms */

+        /* data */                  0x01, 0x26, /* Send FSK */

+        /* data */                  0x0B, 0x01,

+        /* data */                  0x09, 0x00,

+        /* data */                  0x01, 0x27,

+        /* data */                  0x01, 0x3A, /* Mute off */

+    /* Section 1 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0E,       /* 14 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x1F,       /* FSK_GEN register */

+            /* length */            0x01,

+            /* data */              0x00, 0x04, /* stop = 1, start = 0 */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x10,       /* FSK_GEN register */

+            /* length */            0x03,

+            /* data */              0x29, 0x9A, /* mark freq. 1300Hz  */

+                                    0x43, 0x33, /* space freq. 2100Hz */

+                                    0x12, 0xC6, /* amplitude = -13.5dBm0 */

+    /* Section 2 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x17,       /* 23 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x0A,       /* 10 */

+            /* data */              0x30, 0x0E,

+            /* data */              0x14, 0x7B, /* FreqA = 440Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqB = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+            /* data */              0x00, 0x01, /* Generator control = A */

+    /* Section 3 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x17,       /* 23 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x0A,       /* 10 */

+            /* data */              0x30, 0x44,

+            /* data */              0x28, 0xF6, /* FreqA = 2130Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x58, 0x00, /* FreqB = 2750Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+            /* data */              0x00, 0x03, /* Generator control = AB */

+    /* Unstructured data -------------------------------------------------- */

+                                    0x00, 0x00, /* 0-bit channel seizure */

+                                    0x00, 0x58, /* 88-bit mark period */

+                                    0x00, 0x0D, /* Detect Tones A, D */

+                                    0x01,       /* API checksum */

+                                    0x00        /* FSK Message Data */

+};

+

+/* UK Caller ID Type I */

+const VpProfileDataType CID_TYPE1_UK[] = 

+{

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x05,       /* 0x05 = caller ID profile */

+        /* number of sections */    0x03,

+        /* content length */        0x55,       /* 85 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequencer program */

+        /* content length */        0x22,       /* 34 */

+        /* data */                  0x00, 0x0F, /* sequence length = 16 */

+        /* data */                  0x40, 0x32, /* Silence 50ms */

+        /* data */                  0x03, 0x00, /* Line Reversal */

+        /* data */                  0x40, 0x64, /* Silence 100ms */

+        /* data */                  0x01, 0x3D, /* Alert tone 100ms */

+        /* data */                  0x40, 0x64, /* - TONE_CLI */

+        /* data */                  0x05, 0x00,

+        /* data */                  0x01, 0x2F, /* Mask hooks 20ms, */

+        /* data */                  0x40, 0x14, /*    Silence 100ms */

+        /* data */                  0x01, 0x2F,

+        /* data */                  0x40, 0x50,

+        /* data */                  0x01, 0x26, /* Send FSK */

+        /* data */                  0x0B, 0x01,

+        /* data */                  0x09, 0x00,

+        /* data */                  0x01, 0x27,

+        /* data */                  0x40, 0xC8, /* Silence 200ms */

+        /* data */                  0x03, 0x00, /* Line Reversal */

+    /* Section 1 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0E,       /* 14 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x1F,       /* FSK_GEN register */

+            /* length */            0x01,

+            /* data */              0x00, 0x04, /* stop = 1, start = 0 */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x10,       /* FSK_GEN register */

+            /* length */            0x03,

+            /* data */              0x29, 0x9A, /* mark freq. 1300Hz  */

+                                    0x43, 0x33, /* space freq. 2100Hz */

+                                    0x27, 0xAE, /* amplitude = -7dBm0 */

+    /* Section 2 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x17,       /* 23 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x0A,       /* 10 */

+            /* data */              0x30, 0x44,

+            /* data */              0x28, 0xF6, /* FreqA = 2130Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x58, 0x00, /* FreqB = 2750Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+            /* data */              0x00, 0x03, /* Generator control = AB */

+    /* Unstructured data -------------------------------------------------- */

+                                    0x00, 0x78, /* 120-bit channel seizure */

+                                    0x00, 0x40, /* 64-bit mark period */

+                                    0x00, 0x00,

+                                    0x01,       /* API checksum */

+                                    0x00        /* FSK Message Data */

+};

+

+/* US Caller ID (Type 1 - On-Hook) */

+const VpProfileDataType CLI_TYPE1_US[] = 

+{

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x05,       /* 0x05 = caller ID profile */

+        /* number of sections */    0x02,

+        /* content length */        0x26,       /* 38 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequencer program */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x42, 0x08, /* Silence 520ms */

+        /* data */                  0x01, 0x26, /* Send FSK */

+        /* data */                  0x0B, 0x01,

+        /* data */                  0x09, 0x00,

+        /* data */                  0x01, 0x27,

+    /* Section 1 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0E,       /* 14 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x1F,       /* FSK_GEN register */

+            /* length */            0x01,

+            /* data */              0x00, 0x04, /* stop = 1, start = 0 */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x10,       /* FSK_GEN register */

+            /* length */            0x03,

+            /* data */              0x26, 0x66, /* mark freq. 1200Hz  */

+                                    0x46, 0x66, /* space freq. 2200Hz */

+                                    0x27, 0xAE, /* amplitude = -7dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+                                    0x01, 0x30, /* 304-bit channel seizure */

+                                    0x00, 0xB8, /* 184-bit mark period */

+                                    0x00, 0x00,

+                                    0x01,       /* API checksum */

+                                    0x00        /* FSK Message Data */

+};

+

+/************** Metering_Profile **************/

+

+/* Metering Profile 12 kHz Tone */

+const VpProfileDataType METER_12KHZ[] = 

+{

+    /* Metering Profile */

+    /* 12KHz Tone Metering */

+    /* Ramp Time: 10ms, Amplitude: 2000mVrms (Normal Gain) */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x07,       /* 0x07 = Metering profile */

+        /* number of sections */    0x00,

+        /* content length */        0x06,

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x02, /* MTR_TYPE */

+        /* data */                  0x00, 0x0A, /* RAMP_TIME */

+        /* data */                  0x09, 0x94  /* RAMP_STEP */

+};

+

+/* Metering Profile Polarity Reversal */

+const VpProfileDataType METER_POLREV[] = 

+{

+    /* Metering Profile */

+    /* Polrev Pulse Metering */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x07,       /* 0x07 = Metering profile */

+        /* number of sections */    0x00,

+        /* content length */        0x02,

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x00  /* MTR_TYPE */

+};

+

+int dev_profile_size = sizeof(VE792_DEV_PROFILE);

+int dc_profile_size = sizeof(VE792_DC_COEFF);

+int ac_profile_size = sizeof(VE792_AC_COEFF_600);

+int ring_profile_size = sizeof(RING_20HZ_SINE);

+

+/* end of file profile_79238.c */

diff --git a/tools/voice/zarlink/kernel/profile_79238.h b/tools/voice/zarlink/kernel/profile_79238.h
new file mode 100644
index 0000000..dd790bd
--- /dev/null
+++ b/tools/voice/zarlink/kernel/profile_79238.h
@@ -0,0 +1,83 @@
+/*

+ * profile_79238.h --

+ *

+ * This header file exports the Profile data types

+ *

+ * Project Info --

+ *   File:  C:\Documents and Settings\benavi\Desktop\profile_792\792.vpw

+ *   Type:  VCP2-792 Project (Line Module Le51HR0128)

+ *   Date:  Thursday, June 03, 2010 13:40:38

+ *

+ *   This file was generated with Profile Wizard Version: P1.14.1

+ */

+

+#ifndef PROFILE_79238_H

+#define PROFILE_79238_H

+

+#ifdef VP_API_TYPES_H

+#include "vp_api_types.h"

+#else

+typedef unsigned char VpProfileDataType;

+#endif

+

+extern int dev_profile_size;

+extern int dc_profile_size;

+extern int ac_profile_size;

+extern int ring_profile_size;

+

+/************** Device_Parameters **************/

+/* Device Profile */

+extern const VpProfileDataType VE792_DEV_PROFILE[];

+

+/************** AC_Coefficients **************/

+extern const VpProfileDataType VE792_AC_COEFF_600[]; /* AC Parameters (600) */

+extern const VpProfileDataType AC_COEFF_900[];       /* AC Parameters (900) */

+

+/************** DC_Parameters **************/

+extern const VpProfileDataType VE792_DC_COEFF[];     /* DC Parameters */

+

+/************** Ring_Parameters **************/

+extern const VpProfileDataType RING_20HZ_SINE[];     /* Ringing 20Hz, Sine Wave, 40Vrms */

+extern const VpProfileDataType RING_25HZ_SINE[];     /* Ringing 25Hz, Sine Wave, 40Vrms */

+

+/************** Call_Progress_Tones **************/

+extern const VpProfileDataType TONE_DIAL[];          /* US Dial Tone */

+extern const VpProfileDataType TONE_RINGBACK[];      /* US Ringback Tone */

+extern const VpProfileDataType TONE_BUSY[];          /* US Busy Tone */

+extern const VpProfileDataType TONE_REORDER[];       /* US Reorder Tone */

+extern const VpProfileDataType TONE_US_HOWLER[];     /* US Howler Tone (ROH) */

+extern const VpProfileDataType TONE_UK_HOWLER[];     /* UK Howler Tone */

+extern const VpProfileDataType TONE_AUS_HOWLER[];    /* Australia Howler Tone */

+extern const VpProfileDataType TONE_NTT_HOWLER[];    /* Japan Howler Tone */

+extern const VpProfileDataType TONE_SIT[];           /* Special Information Tone (Called Number Not Connected) */

+extern const VpProfileDataType TONE_ONEKHZ_L[];      /* A 1kHz tone at -10dBm0 */

+extern const VpProfileDataType TONE_ONEKHZ_H[];      /* A 1kHz tone at 0dBm0 */

+extern const VpProfileDataType TONE_CALLWAIT[];      /* Call Waiting Beep */

+extern const VpProfileDataType TONE_CLI[];           /* Caller ID Alert Tone */

+

+/************** Cadence_Definitions **************/

+extern const VpProfileDataType TONE_CAD_DIAL[];      /* US Dial Tone Cadence */

+extern const VpProfileDataType TONE_CAD_STUTTER[];   /* Stutter Dial Tone Cadence */

+extern const VpProfileDataType TONE_CAD_RINGBACK[];  /* US Ringback Tone Cadence */

+extern const VpProfileDataType TONE_CAD_BUSY[];      /* US Busy Tone Cadence */

+extern const VpProfileDataType TONE_CAD_REORDER[];   /* US Reorder Tone Cadence */

+extern const VpProfileDataType TONE_CAD_US_HOWLER[]; /* US Howler Tone Cadence (ROH) */

+extern const VpProfileDataType TONE_CAD_UK_HOWLER[]; /* UK Howler Tone Cadence */

+extern const VpProfileDataType TONE_CAD_AUS_HOWLER[];/* Australia Howler Tone Cadence */

+extern const VpProfileDataType TONE_CAD_NTT_HOWLER[];/* Japan Howler Tone Cadence */

+extern const VpProfileDataType TONE_CAD_SIT[];       /* Special Information Tone Cadence */

+extern const VpProfileDataType RING_CAD_STD[];       /* Standard Ringing Cadence */

+extern const VpProfileDataType RING_CAD_CID[];       /* Ringing Cadence with CallerID */

+extern const VpProfileDataType RING_CAD_ON[];        /* Ringing Always On */

+

+/************** Caller_ID **************/

+extern const VpProfileDataType CID_TYPE2_US[];       /* US Caller ID Type II */

+extern const VpProfileDataType CID_TYPE1_UK[];       /* UK Caller ID Type I */

+extern const VpProfileDataType CLI_TYPE1_US[];       /* US Caller ID (Type 1 - On-Hook) */

+

+/************** Metering_Profile **************/

+extern const VpProfileDataType METER_12KHZ[];        /* Metering Profile 12 kHz Tone */

+extern const VpProfileDataType METER_POLREV[];       /* Metering Profile Polarity Reversal */

+

+#endif /* PROFILE_79238_H */

+

diff --git a/tools/voice/zarlink/kernel/profile_88266.c b/tools/voice/zarlink/kernel/profile_88266.c
new file mode 100644
index 0000000..e45b8e6
--- /dev/null
+++ b/tools/voice/zarlink/kernel/profile_88266.c
@@ -0,0 +1,644 @@
+/*
+ * profile_8266.c --
+ *
+ * This file contains profile data in byte format
+ *
+ *   This file was generated with Profile Wizard Version: P1.12.3
+ */
+
+#include "profile_88266.h"
+
+
+/*** Device Parameters for VoicePort Device Family ***/
+const VpProfileDataType ABS_VBL_FLYBACK[] = 
+{
+  /* Device Profile */
+ 0x00, 0xFF, 0x00, 0x1A, /* Profile Index and Length */
+ 0x04, 0x00, /* Version and MPI Command */
+ 0x20, 0x00, /* PCLK Frequency */
+ 0x8A, 0x00, /* Device Config 1 and MCLK Correction */
+ 0x40, 0x02, /* Clock Slot and Max Events */
+ 0x0A, 0x00, /* Device Tickrate */
+ 0xE4, 0x00, 0x05, 0x00, /* Switching Regulator Parameters */
+ 0x00, 0x00, /* RSVD */
+ 0x22, 0x00, 0x55, 0x55, /* Linecard Parameters */
+ 0xB2, 0x00, 0xB1, 0x00, 0xB0, 0x40  /* Regulator Timing Parameters */
+};
+
+/************** AC Filter Coefficients **************/
+
+/* AC FXS RF14 600 Ohm Coefficients [Default} */
+const VpProfileDataType AC_FXS_RF14_DEF[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 900 Ohm Coefficients */
+const VpProfileDataType AC_FXS_RF14_900[] = 
+{
+  /* AC Profile */
+ 0xE4, 0x00, 0xF7, 0x4C, 0x01, 0x49, 0xCA, 0x0B, 0x98, 0x34, 0x3B, 0xB2,
+ 0x2C, 0x9F, 0xA4, 0xD2, 0xA3, 0x22, 0xAC, 0x9A, 0xA4, 0xAA, 0x67, 0x9F,
+ 0x01, 0x8A, 0xB3, 0xD0, 0xA6, 0x21, 0xAA, 0x34, 0x2B, 0x2F, 0x4A, 0xA6,
+ 0xAB, 0x2F, 0x4A, 0x37, 0x88, 0x2A, 0xC0, 0x23, 0xAC, 0x2A, 0x26, 0x32,
+ 0xA5, 0x3C, 0xAD, 0xA4, 0xA7, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xAB, 0x49, 0xF1, 0x2A, 0x0A, 0x43, 0xC9, 0xF3, 0x27, 0xBC,
+ 0xE2, 0xAF, 0xAD, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Australia 220+820//220nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_AU[] = 
+{
+  /* AC Profile */
+ 0xBF, 0x00, 0xAF, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0xBA, 0x41, 0x54,
+ 0xA2, 0x2A, 0x5B, 0xA4, 0xAA, 0x3A, 0xB3, 0x9A, 0x87, 0xA2, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0x23, 0x20, 0x3E, 0xA8, 0x2A, 0x57, 0xCB, 0x34,
+ 0xBA, 0xAC, 0xBB, 0xA6, 0x88, 0xAA, 0xB0, 0x49, 0xF6, 0x3B, 0x2E, 0x49,
+ 0xFF, 0xBC, 0xA5, 0x3A, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x34, 0x5C, 0x32, 0x25, 0x1A, 0xA1, 0x3B, 0x23, 0xB3, 0x5B,
+ 0x4D, 0xB5, 0xDC, 0x60, 0x96, 0x3B, 0xA1, 0x00
+};
+
+/* AC FXS RF14 Austria 220+820//115nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_AT[] = 
+{
+  /* AC Profile */
+ 0x6D, 0x00, 0xA7, 0x4C, 0x01, 0x49, 0xCA, 0xEA, 0x98, 0xFA, 0xE1, 0x23,
+ 0xA2, 0xEA, 0xCB, 0xB3, 0xAA, 0xA3, 0xB3, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0xB3, 0x20, 0xAB, 0xA8, 0xCC, 0x24, 0x22, 0x97,
+ 0xAF, 0x8F, 0xD3, 0xBF, 0x88, 0x3B, 0xB0, 0x33, 0x46, 0x2A, 0x2E, 0x33,
+ 0x4F, 0xAE, 0xA5, 0xB3, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0x22, 0x98, 0x02, 0x42, 0xA2, 0x43, 0xA6, 0xD8,
+ 0xFA, 0x8F, 0x29, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Belgium 150+830//72 Coefficients */
+const VpProfileDataType AC_FXS_RF14_BE[] = 
+{
+  /* AC Profile */
+ 0x8F, 0x00, 0x2E, 0x4C, 0x01, 0x49, 0xCA, 0xF3, 0x98, 0x2C, 0xA1, 0xB4,
+ 0xE3, 0x34, 0xCB, 0x2C, 0x2B, 0xA3, 0xA3, 0x9A, 0x87, 0xA6, 0x97, 0x9F,
+ 0x01, 0x8A, 0x42, 0xD0, 0xBA, 0x30, 0xC2, 0x49, 0xA3, 0x4C, 0xDC, 0xC2,
+ 0x22, 0x2B, 0xBA, 0xA4, 0x88, 0xB3, 0xB0, 0xA3, 0xA4, 0x4A, 0xDD, 0xCA,
+ 0xAD, 0x43, 0xA4, 0x22, 0xAD, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x3A, 0x42, 0xA1, 0xA4, 0x19, 0x81, 0x5A, 0x4B, 0x2F, 0xA2,
+ 0xFB, 0xAF, 0xBA, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Brazil 900 Coefficients */
+const VpProfileDataType AC_FXS_RF14_BR[] = 
+{
+  /* AC Profile */
+ 0xE4, 0x00, 0xF7, 0x4C, 0x01, 0x49, 0xCA, 0x0B, 0x98, 0x34, 0x3B, 0xB2,
+ 0x2C, 0x9F, 0xA4, 0xD2, 0xA3, 0x22, 0xAC, 0x9A, 0xA4, 0xAA, 0x67, 0x9F,
+ 0x01, 0x8A, 0xB3, 0xD0, 0xA6, 0x21, 0xAA, 0x34, 0x2B, 0x2F, 0x4A, 0xA6,
+ 0xAB, 0x2F, 0x4A, 0x37, 0x88, 0x2A, 0xC0, 0xA2, 0xAC, 0x2A, 0x26, 0x32,
+ 0xA5, 0x4C, 0xAD, 0xA4, 0xA7, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x3D, 0x53, 0x22, 0x52, 0x1A, 0x22, 0x2B, 0x6A, 0x87, 0x29,
+ 0xFB, 0x2F, 0xFC, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXA RF14 China 200+680//100nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_CN[] = 
+{
+  /* AC Profile */
+ 0xB9, 0x00, 0x1F, 0x4C, 0x01, 0x49, 0xCA, 0xE9, 0x98, 0x5C, 0xB1, 0xAA,
+ 0x23, 0x43, 0xEB, 0x32, 0xAA, 0x23, 0xB3, 0x9A, 0x98, 0x94, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x30, 0x6A, 0x59, 0x2A, 0xCB, 0xB4, 0xB2,
+ 0xBF, 0x3B, 0xA3, 0x25, 0x88, 0x43, 0xC0, 0x3A, 0x45, 0x2B, 0xBD, 0x4C,
+ 0x2E, 0x4C, 0x25, 0x42, 0xAD, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xA4, 0x5A, 0x32, 0xB5, 0x12, 0xA1, 0xA2, 0x3A, 0xA4, 0xB5,
+ 0x64, 0x97, 0xAA, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Czech Republic 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_CZ[] = 
+{
+  /* AC Profile */
+ 0x1A, 0x00, 0x03, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x22, 0xBA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0xAA, 0xC0, 0x97, 0xA0, 0xAA, 0x33, 0xD2, 0xDB, 0x7C, 0x23,
+ 0x2A, 0xEB, 0x32, 0xB4, 0x88, 0x2A, 0x20, 0x6C, 0xBC, 0xCE, 0xA6, 0x2B,
+ 0xA5, 0xAA, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xC3, 0x5A, 0x22, 0xC7, 0x16, 0xE2, 0x2B, 0x42, 0xC6, 0xC8,
+ 0xFA, 0x9F, 0x2B, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Denmark 300+1000//220nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_DK[] = 
+{
+  /* AC Profile */
+ 0x7D, 0x00, 0x9A, 0x4C, 0x01, 0x49, 0xCA, 0xE6, 0x98, 0x22, 0xA1, 0x52,
+ 0xD2, 0xE7, 0x24, 0xF4, 0xCD, 0xAA, 0x97, 0x9A, 0xCA, 0xB3, 0xA5, 0x6E,
+ 0x01, 0x8A, 0x32, 0xD0, 0xAB, 0x20, 0xAA, 0x49, 0x29, 0x7A, 0x32, 0xD6,
+ 0xA2, 0xED, 0xC5, 0x97, 0x88, 0xBA, 0xC0, 0x22, 0xA7, 0x2C, 0xFE, 0x42,
+ 0xDE, 0x22, 0xB6, 0xB3, 0x9F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x23, 0x53, 0x32, 0x2C, 0x1B, 0x22, 0xCA, 0x23, 0x63, 0x2A,
+ 0x33, 0xD4, 0x2A, 0x40, 0x96, 0xA2, 0xA0, 0x00
+};
+
+/* AC FXS RF14 ETSI 270+750//150nF Harmonized Coefficients */
+const VpProfileDataType AC_FXS_RF14_EU[] = 
+{
+  /* AC Profile */
+ 0xD5, 0x00, 0xEC, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0x4A, 0xA1, 0x34,
+ 0xA2, 0xA2, 0xAC, 0x2C, 0xBB, 0x2B, 0xA4, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x9C, 0xD0, 0x2B, 0x20, 0x8F, 0x39, 0x2A, 0xBB, 0xA4, 0x24,
+ 0xB2, 0xBC, 0x4B, 0x26, 0x88, 0xA3, 0xC0, 0xC2, 0x27, 0xBA, 0x3E, 0xAC,
+ 0xAF, 0xB4, 0x26, 0x24, 0x3F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xC3, 0x5F, 0x32, 0x98, 0x03, 0xA1, 0xAA, 0x23, 0xB3, 0x2C,
+ 0x4B, 0x55, 0x25, 0x60, 0x96, 0xF2, 0xC1, 0x00
+};
+
+/* AC FXS RF14 Finland 270+910//120 Coefficients */
+const VpProfileDataType AC_FXS_RF14_FI[] = 
+{
+  /* AC Profile */
+ 0xFF, 0x00, 0x8D, 0x4C, 0x01, 0x49, 0xCA, 0xEF, 0x98, 0x2A, 0xB1, 0x23,
+ 0x33, 0xB2, 0xAB, 0x44, 0xEB, 0xA4, 0x44, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0x24, 0x20, 0x25, 0xB8, 0x2D, 0x42, 0xDB, 0xBA,
+ 0xE3, 0x43, 0xF2, 0xAC, 0x88, 0xC4, 0xB0, 0xA2, 0xA7, 0x42, 0x3E, 0xA2,
+ 0x9F, 0x32, 0x26, 0xBE, 0x2F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xA2, 0x5C, 0x22, 0xA2, 0x13, 0xC1, 0xB3, 0x22, 0x23, 0x7A,
+ 0x3D, 0xB4, 0xD4, 0x50, 0x96, 0x3C, 0x41, 0x00
+};
+
+/* AC FXS RF14 France 215+1000//137nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_FR[] = 
+{
+  /* AC Profile */
+ 0xFC, 0x00, 0xA4, 0x4C, 0x01, 0x49, 0xCA, 0xE7, 0x98, 0xBA, 0x31, 0xA5,
+ 0x62, 0x35, 0xAB, 0xAA, 0xAA, 0xAC, 0xA3, 0x9A, 0xAA, 0xA2, 0xC7, 0x6F,
+ 0x01, 0x8A, 0x2D, 0x01, 0xBB, 0x10, 0xC2, 0x38, 0x2A, 0xA1, 0xC2, 0xA9,
+ 0x23, 0xA2, 0x22, 0x2D, 0x88, 0xA3, 0xB0, 0x53, 0x55, 0x4A, 0xAD, 0xB2,
+ 0xAD, 0x5A, 0x25, 0x72, 0x5E, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x43, 0x22, 0x9F, 0x1A, 0x22, 0x4B, 0x33, 0xD5, 0x2C,
+ 0x7A, 0x87, 0xA8, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 German 220+820//115nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_DE[] = 
+{
+  /* AC Profile */
+ 0xEB, 0x00, 0xDC, 0x4C, 0x01, 0x49, 0xCA, 0xEA, 0x98, 0xA2, 0xE1, 0x24,
+ 0xA2, 0x2A, 0xCB, 0xB3, 0xAA, 0xD3, 0xB3, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0x24, 0x20, 0x2C, 0xA8, 0xAB, 0x24, 0x22, 0x97,
+ 0xAF, 0x8F, 0x23, 0xBF, 0x88, 0x3B, 0xB0, 0x33, 0x46, 0x2A, 0x2E, 0x33,
+ 0x4F, 0xAE, 0xA5, 0xB3, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x53, 0x54, 0x32, 0xC4, 0x1A, 0xA1, 0x2B, 0x2A, 0xA3, 0xAA,
+ 0x4A, 0xA5, 0xBA, 0x60, 0x96, 0xD2, 0xA1, 0x00
+};
+
+/* AC FXS RF14 Greece 400+500//50nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_GR[] = 
+{
+  /* AC Profile */
+ 0x63, 0x00, 0x7D, 0x4C, 0x01, 0x49, 0xCA, 0x03, 0x98, 0x22, 0xA6, 0x2C,
+ 0x3E, 0x2B, 0x87, 0x44, 0x36, 0x2A, 0x9F, 0x9A, 0x22, 0xBA, 0xA7, 0x9F,
+ 0x01, 0x8A, 0x7D, 0xD0, 0xAA, 0xA0, 0x22, 0xAA, 0x98, 0xB4, 0x23, 0xBE,
+ 0xAB, 0xBF, 0xAA, 0x97, 0x88, 0x3C, 0xC0, 0x3A, 0xBD, 0xED, 0x8F, 0xEB,
+ 0xA6, 0x3A, 0x8F, 0x2B, 0x6F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xD2, 0x52, 0x22, 0xA2, 0x13, 0xA1, 0x97, 0x32, 0x25, 0xCA,
+ 0x6B, 0x87, 0x2B, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Hungary 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_HU[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 India 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_IN[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Italy 180+630//60nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_IT[] = 
+{
+  /* AC Profile */
+ 0xEE, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xF3, 0x98, 0x22, 0xD2, 0xBA,
+ 0x34, 0x22, 0x3C, 0x53, 0xAB, 0xAA, 0xB4, 0x9A, 0x98, 0x1B, 0x97, 0x9F,
+ 0x01, 0x8A, 0x9C, 0xD0, 0xBC, 0xD0, 0x2A, 0x2A, 0x3C, 0x4C, 0x4E, 0x23,
+ 0xD2, 0xBB, 0xDB, 0x55, 0x88, 0xAA, 0xC0, 0x2C, 0xB5, 0x23, 0xAD, 0x4A,
+ 0x5E, 0xAD, 0xB5, 0x2B, 0x2E, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xA2, 0x52, 0xA1, 0xA3, 0x1A, 0x32, 0xAA, 0x4A, 0xAF, 0x3B,
+ 0xF4, 0x9F, 0x3A, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Japan 600+1uF Coefficients */
+const VpProfileDataType AC_FXS_RF14_JP[] = 
+{
+  /* AC Profile */
+ 0x0C, 0x00, 0x79, 0x4C, 0x01, 0x49, 0xCA, 0xF9, 0x98, 0xAC, 0xEE, 0x2A,
+ 0x87, 0x2A, 0x3F, 0xA3, 0x97, 0xE5, 0xC3, 0x9A, 0xAB, 0xA2, 0x24, 0xA6,
+ 0xD0, 0x8A, 0x42, 0xB0, 0x2A, 0xA0, 0x34, 0xAA, 0x3B, 0xA2, 0xCA, 0xAA,
+ 0xA4, 0x24, 0x3B, 0x4D, 0x88, 0xBA, 0x30, 0xAC, 0x2D, 0xAA, 0xCE, 0xAA,
+ 0x25, 0x22, 0x2C, 0xB2, 0x65, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x3B, 0x52, 0xA1, 0xA5, 0x14, 0xA2, 0x23, 0x44, 0x24, 0xA5,
+ 0x4B, 0xA4, 0xAC, 0x40, 0x96, 0x32, 0xD0, 0x00
+};
+
+/* AC FXS RF14 S. Korea 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_KR[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Mexico 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_MX[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Netherlands 600/340+422//100 Coefficients */
+const VpProfileDataType AC_FXS_RF14_NL[] = 
+{
+  /* AC Profile */
+ 0x7D, 0x00, 0x38, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x22, 0xBA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x34, 0xD0, 0xCD, 0xA0, 0xAB, 0xD3, 0x22, 0xAB, 0x4A, 0xA3,
+ 0xA2, 0x2C, 0xAB, 0x45, 0x88, 0x2A, 0x20, 0x6C, 0xBC, 0xCE, 0xA6, 0x2B,
+ 0xA5, 0xAA, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x62, 0x52, 0x22, 0xCD, 0x12, 0x23, 0x44, 0x7A, 0x87, 0x3B,
+ 0xFC, 0xBF, 0xBA, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 New Zealand 370+620//310nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_NZ[] = 
+{
+  /* AC Profile */
+ 0x14, 0x00, 0x00, 0x4C, 0x01, 0x49, 0xCA, 0xE9, 0x98, 0xAA, 0xB3, 0xB2,
+ 0xA2, 0xDA, 0xA3, 0x2B, 0x36, 0xAA, 0x25, 0x9A, 0x2B, 0xA2, 0x27, 0x6F,
+ 0x01, 0x8A, 0x1D, 0x01, 0x52, 0x50, 0x2A, 0x3B, 0x45, 0xA9, 0xCA, 0xA3,
+ 0x2C, 0xAB, 0xAA, 0x27, 0x88, 0xC3, 0x50, 0xBA, 0x8F, 0x37, 0x2F, 0xC2,
+ 0xBE, 0xEA, 0x87, 0xAA, 0x87, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x53, 0x53, 0x32, 0xCB, 0x1C, 0x42, 0x32, 0x3B, 0xB3, 0xA2,
+ 0x42, 0xB4, 0x23, 0x50, 0x96, 0x42, 0xA0, 0x00
+};
+
+/* AC FXS RF14 Norway 120+820//110nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_NO[] = 
+{
+  /* AC Profile */
+ 0x04, 0x00, 0xA8, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0xAA, 0x41, 0x22,
+ 0xA1, 0xAA, 0x3B, 0x23, 0x2A, 0xD4, 0x23, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0xEA, 0x10, 0x22, 0xB8, 0x22, 0x3B, 0x23, 0xA1,
+ 0xAA, 0xBA, 0x32, 0xC4, 0x88, 0x25, 0xB0, 0x3B, 0x24, 0x2C, 0x2D, 0xA3,
+ 0xAC, 0xF4, 0xC4, 0xAB, 0xAD, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xBB, 0x52, 0xE2, 0xBD, 0x1B, 0xA1, 0x3B, 0x2A, 0xA3, 0x3A,
+ 0x4A, 0x26, 0x29, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Portugal 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_PT[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Slovenia 600/220+820//115 Coefficients */
+const VpProfileDataType AC_FXS_RF14_SI[] = 
+{
+  /* AC Profile */
+ 0x00, 0x00, 0x00, 0x4C, 0x00, 0x49, 0xCA, 0xF5, 0x98, 0x2A, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2B, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0x55, 0xA0, 0xA2, 0xA2, 0x57, 0x2B, 0xC6, 0x23,
+ 0x34, 0xBB, 0x6A, 0xC5, 0x88, 0x2A, 0x20, 0x6C, 0xBC, 0xCE, 0xA6, 0x2B,
+ 0xA5, 0xAA, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xC8, 0xF0, 0x50,
+ 0x00, 0x86, 0xC3, 0x5A, 0x22, 0xC7, 0x16, 0xE2, 0x2B, 0x42, 0xC6, 0xC8,
+ 0xFA, 0x9F, 0x2B, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Spain 220+820//120nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_ES[] = 
+{
+  /* AC Profile */
+ 0xBF, 0x00, 0xAF, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0xBA, 0x41, 0x54,
+ 0xA2, 0x2A, 0x5B, 0xA4, 0xAA, 0x3A, 0xB3, 0x9A, 0x87, 0xA2, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0x23, 0x20, 0x3E, 0xA8, 0x2A, 0x57, 0xCB, 0x34,
+ 0xBA, 0xAC, 0xBB, 0xA6, 0x88, 0xAA, 0xB0, 0x49, 0xF6, 0x3B, 0x2E, 0x49,
+ 0xFF, 0xBC, 0xA5, 0x3A, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x34, 0x5C, 0x32, 0x25, 0x1A, 0xA1, 0x3B, 0x23, 0xB3, 0x5B,
+ 0x4D, 0xB5, 0xDC, 0x60, 0x96, 0x3B, 0xA1, 0x00
+};
+
+/* AC FXS RF14 Sweden 200+1000//100nF_900//30nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_SE[] = 
+{
+  /* AC Profile */
+ 0x0E, 0x00, 0x42, 0x4C, 0x01, 0x49, 0xCA, 0xF0, 0x98, 0x24, 0xF1, 0xB4,
+ 0xA2, 0xAB, 0x4B, 0x4B, 0xAA, 0xA7, 0xC3, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0xB3, 0x20, 0x5B, 0xB8, 0x24, 0xA2, 0x3C, 0xAC,
+ 0xAA, 0x27, 0x32, 0x9F, 0x88, 0x3A, 0xA0, 0x3A, 0x25, 0x3A, 0xAD, 0x22,
+ 0xAD, 0xBE, 0x25, 0xA5, 0x2E, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x73, 0x52, 0x22, 0xD2, 0x12, 0xB1, 0x4A, 0x23, 0xC4, 0xC3,
+ 0x6A, 0x97, 0xA8, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 U.K. 300+1000//220_370+620//310nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_GB[] = 
+{
+  /* AC Profile */
+ 0x24, 0x00, 0x0A, 0x4C, 0x01, 0x49, 0xCA, 0xE6, 0x98, 0x22, 0xA1, 0x52,
+ 0xD2, 0xE7, 0x24, 0xF4, 0xCD, 0xAA, 0x97, 0x9A, 0x2B, 0xA2, 0x27, 0x6E,
+ 0x01, 0x8A, 0x32, 0xD0, 0xCB, 0x20, 0xBB, 0x59, 0x5A, 0x4A, 0xAA, 0xB5,
+ 0x2C, 0x2D, 0x42, 0xC7, 0x88, 0xAA, 0xC0, 0xA3, 0xA7, 0xBA, 0xDE, 0x5C,
+ 0xCE, 0xAA, 0xA6, 0xA2, 0x9F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x43, 0x5B, 0x32, 0x2C, 0x1D, 0x22, 0xAA, 0x2B, 0x33, 0xBA,
+ 0x3C, 0x34, 0xBA, 0x40, 0x96, 0xA2, 0xA0, 0x00
+};
+
+/* AC FXS RF14 US 900//2.16uF_1650//(100+5nF) Coefficients */
+const VpProfileDataType AC_FXS_RF14_US_loaded[] = 
+{
+  /* AC Profile */
+ 0x01, 0x00, 0x90, 0x4C, 0x01, 0x49, 0xCA, 0x0E, 0x98, 0x32, 0x2B, 0x24,
+ 0x7C, 0x4A, 0x24, 0x55, 0xA3, 0x3A, 0xBC, 0x9A, 0xBA, 0xB3, 0xF4, 0x2D,
+ 0x01, 0x8A, 0xEB, 0xC0, 0x26, 0x21, 0xB2, 0x35, 0xB3, 0xA6, 0x2A, 0xAD,
+ 0xD4, 0xA6, 0x52, 0x4F, 0x88, 0xA3, 0xD0, 0x23, 0xAA, 0xAF, 0x62, 0xEA,
+ 0xBA, 0x2A, 0xB3, 0x4A, 0x3D, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2B, 0x4C, 0x21, 0xAC, 0x03, 0xB2, 0xA5, 0x5A, 0xE4, 0x74,
+ 0xF3, 0xA5, 0xBE, 0x60, 0x96, 0xAA, 0xC0, 0x00
+};
+
+/* AC FXS RF14 US 900//2,16uF_800//(100+50nF) Coefficients */
+const VpProfileDataType AC_FXS_RF14_US_Nonloaded[] = 
+{
+  /* AC Profile */
+ 0x01, 0x00, 0x90, 0x4C, 0x01, 0x49, 0xCA, 0x0E, 0x98, 0x32, 0x2B, 0x24,
+ 0x7C, 0x4A, 0x24, 0x55, 0xA3, 0x3A, 0xBC, 0x9A, 0xBA, 0xB3, 0xF4, 0x2D,
+ 0x01, 0x8A, 0xEB, 0xC0, 0x26, 0x21, 0xB2, 0x35, 0xB3, 0xA6, 0x2A, 0xAD,
+ 0xD4, 0xA6, 0x52, 0x4F, 0x88, 0xA3, 0xD0, 0x23, 0xAA, 0xAF, 0x62, 0xEA,
+ 0xBA, 0x2A, 0xB3, 0x4A, 0x3D, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xBD, 0x52, 0xA1, 0x62, 0x1B, 0x22, 0x3A, 0x4B, 0xB5, 0x2A,
+ 0x65, 0xA7, 0xB6, 0x70, 0x96, 0x23, 0xC0, 0x00
+};
+
+/* AC FXS RF14 US 900//2.16uF Coefficients */
+const VpProfileDataType AC_FXS_RF14_US_SS[] = 
+{
+  /* AC Profile */
+ 0x01, 0x00, 0x90, 0x4C, 0x01, 0x49, 0xCA, 0x0E, 0x98, 0x32, 0x2B, 0x24,
+ 0x7C, 0x4A, 0x24, 0x55, 0xA3, 0x3A, 0xBC, 0x9A, 0xBA, 0xB3, 0xF4, 0x2D,
+ 0x01, 0x8A, 0xEB, 0xC0, 0x26, 0x21, 0xB2, 0x35, 0xB3, 0xA6, 0x2A, 0xAD,
+ 0xD4, 0xA6, 0x52, 0x4F, 0x88, 0xA3, 0xD0, 0x23, 0xAA, 0xAF, 0x62, 0xEA,
+ 0xBA, 0x2A, 0xB3, 0x4A, 0x3D, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xDA, 0x4A, 0x41, 0x3A, 0x02, 0x23, 0x3A, 0x42, 0x25, 0xAA,
+ 0x72, 0xA5, 0x2B, 0x50, 0x96, 0x1D, 0x01, 0x00
+};
+
+/************** WideBand AC Filter Coefficients **************/
+/* AC FXS RF14 600 Ohm Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_US[] =
+{
+  /* AC Profile */
+ 0xED, 0x00, 0xA9, 0x4C, 0x01, 0x49, 0xCA, 0xFC, 0x98, 0xCC, 0x2A, 0xA2,
+ 0x3B, 0x98, 0xB3, 0x43, 0xA2, 0x3A, 0xAB, 0x9A, 0x2D, 0xAA, 0xB6, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0xC4, 0xA0, 0x2E, 0x23, 0x3A, 0x2E, 0x9F, 0x87,
+ 0x4C, 0xCE, 0xB2, 0x27, 0x88, 0xDE, 0x20, 0xAA, 0xCA, 0x22, 0x32, 0x23,
+ 0xAA, 0xA2, 0xB4, 0x2A, 0x87, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xCB, 0x5E, 0x22, 0xBC, 0x12, 0xA3, 0xA9, 0xFA, 0xC6, 0x34,
+ 0xE2, 0x9F, 0xBA, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 European Union Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_EU[] =
+{
+  /* AC Profile */
+ 0xAA, 0x00, 0x9C, 0x4C, 0x01, 0x49, 0xCA, 0xE0, 0x98, 0xAA, 0xA3, 0x6B,
+ 0x22, 0x43, 0xA2, 0xAC, 0xBF, 0x22, 0xA6, 0x9A, 0x01, 0x90, 0x01, 0x01,
+ 0x90, 0x8A, 0x2E, 0x01, 0xBA, 0x10, 0xA2, 0x3A, 0xBA, 0xE9, 0xAA, 0xB5,
+ 0x2A, 0xBC, 0xAF, 0x97, 0x88, 0xAB, 0xC0, 0x4A, 0xBE, 0xBA, 0x9F, 0xC3,
+ 0xAF, 0x3A, 0x3F, 0xCD, 0xA7, 0x82, 0xC8, 0x71, 0x80, 0x69, 0xF0, 0x50,
+ 0x00, 0x86, 0xBA, 0x52, 0xB2, 0xBA, 0x12, 0x42, 0x4A, 0x2A, 0x33, 0xBA,
+ 0x33, 0x34, 0x4B, 0x40, 0x96, 0xB2, 0xA0, 0x00
+};
+
+/* AC FXS RF14 France Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_FR[] =
+{
+  /* AC Profile */
+ 0x98, 0x00, 0x26, 0x4C, 0x01, 0x49, 0xCA, 0xD7, 0x98, 0x4F, 0x22, 0xB5,
+ 0xB1, 0xC6, 0x23, 0x3A, 0xAB, 0x24, 0xB5, 0x9A, 0x01, 0x90, 0x01, 0x01,
+ 0x90, 0x8A, 0x01, 0x11, 0x22, 0x10, 0x3A, 0x29, 0x3C, 0x29, 0x32, 0xB3,
+ 0x4A, 0x2C, 0x2E, 0xB6, 0x88, 0xAC, 0xB0, 0x43, 0x37, 0xAB, 0x3E, 0xB4,
+ 0x3E, 0x22, 0x37, 0x22, 0xAF, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xAA, 0x52, 0xE2, 0x2B, 0x12, 0x62, 0x63, 0x3A, 0x24, 0xA2,
+ 0x5C, 0x36, 0x39, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 German Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_DE[] =
+{
+  /* AC Profile */
+ 0x27, 0x00, 0xD7, 0x4C, 0x01, 0x49, 0xCA, 0xDB, 0x98, 0xBA, 0xA1, 0xBA,
+ 0x22, 0x2A, 0xF4, 0xAA, 0xAB, 0x22, 0x65, 0x9A, 0x01, 0x90, 0x01, 0x01,
+ 0x90, 0x8A, 0x2E, 0x01, 0xA3, 0x10, 0x2B, 0x29, 0x53, 0xB9, 0xBD, 0xB3,
+ 0x7B, 0xCC, 0xDB, 0xA6, 0x88, 0x2A, 0xB0, 0x2B, 0x9F, 0x2E, 0x3E, 0x22,
+ 0xBE, 0xC3, 0x26, 0x35, 0x2F, 0x82, 0xB8, 0x71, 0x80, 0xAB, 0xF0, 0x50,
+ 0x00, 0x86, 0xCA, 0x5A, 0xA2, 0xBA, 0x1F, 0x22, 0x3B, 0x2A, 0x23, 0x2B,
+ 0x3A, 0x24, 0x4B, 0x40, 0x96, 0x22, 0x21, 0x00
+};
+
+/* AC FXS RF14 China Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_CN[] =
+{
+  /* AC Profile */
+ 0xEF, 0x00, 0x46, 0x4C, 0x01, 0x49, 0xCA, 0xDA, 0x98, 0xB3, 0xB1, 0x23,
+ 0x32, 0x64, 0x97, 0xAA, 0x2B, 0x4A, 0xA4, 0x9A, 0x01, 0x90, 0x01, 0x01,
+ 0x90, 0x8A, 0x2E, 0x01, 0xCD, 0x10, 0x2B, 0x29, 0x22, 0x2A, 0xA2, 0x33,
+ 0x4B, 0x4C, 0xBD, 0xF6, 0x88, 0x2A, 0xC0, 0x52, 0x97, 0xF2, 0x2E, 0xAA,
+ 0x4E, 0xAC, 0xB5, 0x5B, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x5A, 0xA2, 0xBA, 0x1B, 0x22, 0xCA, 0x24, 0xC3, 0x43,
+ 0x42, 0xA4, 0x4B, 0x50, 0x96, 0x3C, 0x41, 0x00
+};
+
+/* AC FXS RF14 Australia Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_AU[] =
+{
+  /* AC Profile */
+ 0xC2, 0x00, 0x2E, 0x4C, 0x01, 0x49, 0xCA, 0xF0, 0x98, 0xBA, 0xA1, 0xAD,
+ 0xA3, 0xA2, 0x2C, 0x2D, 0xAB, 0x22, 0xD4, 0x9A, 0xCC, 0xA2, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0x7A, 0x10, 0xBA, 0x29, 0x2A, 0x3A, 0xA2, 0x32,
+ 0xB2, 0xAA, 0xF2, 0xA4, 0x88, 0xBA, 0xA0, 0x5C, 0x3F, 0x2C, 0xCE, 0xAA,
+ 0x87, 0xC2, 0x66, 0xDB, 0x7E, 0x82, 0xA8, 0x71, 0x80, 0x39, 0x70, 0x50,
+ 0x00, 0x86, 0xAA, 0x59, 0x81, 0x25, 0x1A, 0xA1, 0xBB, 0x2B, 0xB3, 0x2C,
+ 0x46, 0xD5, 0xBC, 0x60, 0x96, 0xAA, 0xB1, 0x00
+};
+
+/************** DC Feed Parameters **************/
+
+/* 22mA  current feed */
+const VpProfileDataType DC_22MA_CC[] = 
+{
+ /* DC Profile */
+ 0x00, 0x01, 0x01, 0x0B, 0x01, 0x08, 0xC2, 0x1A, 0x88, 0xD0, 0x05, 0xC6,
+ 0x11, 0x04, 0x01
+};
+
+/************** Ring Signal Parameters **************/
+
+/* Default Rnging, 25Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_DEF[] = 
+{
+  /* Sine, 25 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x3A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* US Ringing, 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_US[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Canada Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_CA[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* France Ringing 50Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_FR[] = 
+{
+  /* Sine, 50 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x88,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Japan Ringing 16Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_JP[] = 
+{
+  /* Sine, 16 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x2B,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* S. Korea Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_KR[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Taiwan Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_TW[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Hong Kong Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_HK[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Singapore Rnging, 24Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_SG[] = 
+{
+  /* Sine, 24 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Austria Ringing 50Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_AT[] = 
+{
+  /* Sine, 50 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x88,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Australia Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_AU[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+
+/************** Call Progress Tones **************/
+
+/************** Cadence Definitions **************/
+/* RING Cadence Profile */
+const VpProfileDataType RING_CAD_STD[] = 
+{
+  /* Cadence Profile */
+ 0x00, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x07, 0x21, 0x90,
+ 0x01, 0x00, 0x23, 0x20, 0x40, 0x00
+};
+
+/************** Caller ID **************/
+
+/************** Metering Profile **************/
+
+int dev_profile_size = sizeof(ABS_VBL_FLYBACK);
+int dc_profile_size = sizeof(DC_22MA_CC);
+int ac_profile_size = sizeof(AC_FXS_RF14_DEF);
+int ring_profile_size = sizeof(RING_DEF);
+
+/* end of file profile_8266.c */
diff --git a/tools/voice/zarlink/kernel/profile_88266.h b/tools/voice/zarlink/kernel/profile_88266.h
new file mode 100644
index 0000000..f53a0ad
--- /dev/null
+++ b/tools/voice/zarlink/kernel/profile_88266.h
@@ -0,0 +1,98 @@
+/*
+ * profile_8266.h --
+ *
+ * This header file exports the Profile data types
+ *
+ * Project Info --
+ *   File:  C:\Documents and Settings\benavi\Desktop\tmp\NewProject.vpw
+ *   Type:  Le71HR0865G Line Module Project - VBL Reg ABS Power Supply and 8.192MHz PCLK
+ *   Date:  Thursday, February 25, 2010 16:58:41
+ *
+ *   This file was generated with Profile Wizard Version: P1.12.3
+ */
+
+#ifndef PROFILE_8266_H
+#define PROFILE_8266_H
+
+#ifdef VP_API_TYPES_H
+#include "vp_api_types.h"
+#else
+typedef unsigned char VpProfileDataType;
+#endif
+
+extern int dev_profile_size;
+extern int dc_profile_size;
+extern int ac_profile_size;
+extern int ring_profile_size;
+
+/************** Device Parameters **************/
+/* Device Profile */
+extern const VpProfileDataType ABS_VBL_FLYBACK[];
+
+/************** AC Filter Coefficients **************/
+extern const VpProfileDataType AC_FXS_RF14_DEF[];    /* AC FXS RF14 600 Ohm Coefficients [Default} */
+extern const VpProfileDataType AC_FXS_RF14_900[];    /* AC FXS RF14 900 Ohm Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_AU[];     /* AC FXS RF14 Australia 220+820//220nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_AT[];     /* AC FXS RF14 Austria 220+820//115nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_BE[];     /* AC FXS RF14 Belgium 150+830//72 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_BR[];     /* AC FXS RF14 Brazil 900 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_CN[];     /* AC FXA RF14 China 200+680//100nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_CZ[];     /* AC FXS RF14 Czech Republic 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_DK[];     /* AC FXS RF14 Denmark 300+1000//220nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_EU[];     /* AC FXS RF14 ETSI 270+750//150nF Harmonized Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_FI[];     /* AC FXS RF14 Finland 270+910//120 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_FR[];     /* AC FXS RF14 France 215+1000//137nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_DE[];     /* AC FXS RF14 German 220+820//115nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_GR[];     /* AC FXS RF14 Greece 400+500//50nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_HU[];     /* AC FXS RF14 Hungary 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_IN[];     /* AC FXS RF14 India 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_IT[];     /* AC FXS RF14 Italy 180+630//60nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_JP[];     /* AC FXS RF14 Japan 600+1uF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_KR[];     /* AC FXS RF14 S. Korea 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_MX[];     /* AC FXS RF14 Mexico 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_NL[];     /* AC FXS RF14 Netherlands 600/340+422//100 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_NZ[];     /* AC FXS RF14 New Zealand 370+620//310nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_NO[];     /* AC FXS RF14 Norway 120+820//110nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_PT[];     /* AC FXS RF14 Portugal 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_SI[];     /* AC FXS RF14 Slovenia 600/220+820//115 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_ES[];     /* AC FXS RF14 Spain 220+820//120nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_SE[];     /* AC FXS RF14 Sweden 200+1000//100nF_900//30nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_GB[];     /* AC FXS RF14 U.K. 300+1000//220_370+620//310nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_US_loaded[];/* AC FXS RF14 US 900//2.16uF_1650//(100+5nF) Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_US_Nonloaded[];/* AC FXS RF14 US 900//2,16uF_800//(100+50nF) Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_US_SS[];  /* AC FXS RF14 US 900//2.16uF Coefficients */
+
+/************** WideBand AC Filter Coefficients **************/
+extern const VpProfileDataType AC_FXS_RF14_WB_US[];  /* AC FXS RF14 600 Ohm Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_EU[];  /* AC FXS RF14 European Union Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_FR[];  /* AC FXS RF14 France Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_DE[];  /* AC FXS RF14 German Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_CN[];  /* AC FXS RF14 China Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_AU[];  /* AC FXS RF14 Australia Wideband Coefficients */
+
+/************** DC Feed Parameters **************/
+extern const VpProfileDataType DC_22MA_CC[];         /* 22mA  current feed */
+
+/************** Ring Signal Parameters **************/
+extern const VpProfileDataType RING_DEF[];           /* Default Rnging, 25Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_US[];            /* US Ringing, 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_CA[];            /* Canada Ringing 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_FR[];            /* France Ringing 50Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_JP[];            /* Japan Ringing 16Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_KR[];            /* S. Korea Ringing 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_TW[];            /* Taiwan Ringing 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_HK[];            /* Hong Kong Ringing 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_SG[];            /* Singapore Rnging, 24Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_AT[];            /* Austria Ringing 50Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_AU[];            /* Australia Ringing 20Hz, Sinewave, 80Vpk */
+
+/************** Call Progress Tones **************/
+
+/************** Cadence Definitions **************/
+extern const VpProfileDataType RING_CAD_STD[]; 
+/************** Caller ID **************/
+
+/************** Metering Profile **************/
+
+#endif /* PROFILE_8266_H */
+
diff --git a/tools/voice/zarlink/kernel/profile_89116.c b/tools/voice/zarlink/kernel/profile_89116.c
new file mode 100644
index 0000000..c5867fb
--- /dev/null
+++ b/tools/voice/zarlink/kernel/profile_89116.c
@@ -0,0 +1,2412 @@
+/*

+ * profile_89116.c --

+ *

+ * This file contains profile data in byte format

+ *

+ * Project Info --

+ *   File:   C:\Microsemi\Profile_Wizard_P2.1.2\890\NewProject116_new.vpw

+ *   Type:   VE890 Configuration for 100V Buck-Boost Power Supply, Lite Narrowband FXS Coefficients, and 8.192MHz PCLK

+ *   Date:   Wednesday, May 02, 2012 12:15:05

+ *   Device: VE890 Le89316

+ *

+ *   This file was generated with Profile Wizard Version: P2.1.2

+ *

+ * Project Comments --

+ *  --------------------------------------------

+ *  Profile Wizard Coefficient Release 2.8 Notes:

+ *  --------------------------------------------

+ *  Added FXS AC Profile for Brazil (900R) and Russia (150R + (510R//47nF))

+ *  Updated FXS AC Profiles for Australia, China, GR-57 (US non-loaded), Japan, New Zealand, and the UK

+ *  --------------------------------------------

+ *  Profile Wizard Coefficient Release 2.7 Notes:

+ *  --------------------------------------------

+ *  Replaced incorrect FXS AC Profiles for GR-57, China, Finland, and Japan

+ *  --------------------------------------------

+ *  Profile Wizard Coefficient Release 2.6 Notes:

+ *  --------------------------------------------

+ *  I. General:

+ *  1. This release adds support for Mexico, Turkey, Thailand, Malaysia, Indonesia, and Ecuador, bringing

+ *  the total number of supported countries to 44.  They are:

+ *  Argentina (AR), Austria (AT), Australia (AU), Belgium (BE), Bulgaria (BG), Brazil (BR), Canada (CA), Switzerland (CH),

+ *  Chile (CL), China (CN), Czech Republic (CZ), Germany (DE), Denmark (DK), Ecuador (EC), Spain (ES), Finland (FI),

+ *  France (FR), UK (GB), Greece (GR), Hong Kong SAR China (HK), Hungary (HU), Indonesia (ID), Ireland (IE), Israel (IL),

+ *  India (IN), Iceland (IS), Italy (IT), Japan (JP), S. Korea (KR), Mexico (MX), Malaysia (MY), Netherlands (NL),

+ *  Norway (NO), New Zealand (NZ), Poland (PL), Portugal (PT), Russian Federation (RU), Sweden (SE), Singapore (SG),

+ *  Thailand (TH), Turkey (TK), Taiwan (TW), USA (US), and South Africa (ZA).

+ *  2. This release also corrects some Caller ID implementations and signal levels that were incorrect in release 2.3.

+ *  3. The coefficients in this and all releases are provided for use only with the Microsemi VoicePath API-II (VP-API-II). 

+ *  Please refer to the terms and conditions for licensing the software regarding terms and conditions of usage. These profiles 

+ *  are provided for reference only with no guarantee whatsoever by Microsemi Corporation.

+ *  4. This release is for the VE8911 chipset and includes coefficients required for FXS and FXO operation.

+ *  

+ *  II. Device Profile:

+ *  1. The default settings for the Device Profile are:

+ *         PCLK = 8192 kHz

+ *         PCM Transmit Edge = Positive

+ *         Transmit Time Slot = 0

+ *         Receive Time Slot = 0

+ *         Interrupt Mode = Open Drain

+ *         Switcher = Buck-Boost

+ *         Driver Tick Rate = 5 ms

+ *         Maximum Events / Tick = 2

+ *  2. The settings may be changed by the user as necessary.  Please refer to the VE890 and API documentation for information about

+ *  the supported settings.

+ *  

+ *  II. AC Profiles:

+ *  1. FXS Coefficients assume -6dBr RX (Output from chipset) and 0dB TX relative gain levels.

+ *  2. Supported countries not individually listed should use the default 600R profile AC_FXS_RF50_600R_DEF.

+ *  4. AC FXS Coefficients assume the use of two 25 ohm series resistors or PTCs. Customers using other PTC resistance values (such as 

+ *  7 ohms or 50 ohms) should not use these AC coefficients and can request alternate ones from Microsemi.

+ *  5. This release includes Normal (or narrowband) coefficients for the FXS port. Wideband coefficients are available upon request.

+ *  6. AC FXO Coefficients assume the use of the LC Filter on VE890 DAA Circuit consisting of CIMM and LIMM as shown

+ *  in the datasheet.

+ *  7. AC FXO Coefficients include the coefficient sets for the VE890 echo free adaptive balance.

+ *  

+ *  III. DC Profile:

+ *  1. The DC_FXS_VE890_BB100V_DEF is the default used for all countries.  Additional profiles may be created by the user if necessary.

+ *  

+ *  IV. Ring Profiles:

+ *  1. RING_25HZ_VE890_BB100V_DEF is the default ringing profile and should be used for all countries which do not have a listed Ringing Profile.  The default

+ *  ringing profile is set for a sine wave ringing with an amplitude of 50 Vrms and a frequency of 25 Hz.

+ *  2. All ringing profiles on the list have a 50 Vrms ringing level. 

+ *  3. DC biasing is set to 0 in the sample ringing profiles.

+ *  

+ *  V. Tone Profiles:

+ *  1. These profiles are available only in the full version of the API.

+ *  2. The shown levels assume a 6dB attenuation in the chipset before being outputed to line.

+ *  3. Call progress tone levels may be arbitrary as they are not always specified in national standards, or the standards may not be available to Microsemi.

+ *  4. ITU-T Recommendation E.180 (03/1998) revised on 02/2003 and ETSI TR 101 041-2 V.1.1.1 (05/1997) were used if national standards were not

+ *  available.

+ *  5. Recommended ETSI ES 201 970 call progress tones are provided for reference.

+ *  6. Modulated tones f1 x f2 are approximated as the sum of f1 + (f1+f2)/2 + (f1-f2)/2.

+ *  7. The data in these profiles may be changed by the user as necessary.

+ *   8. T_CAS_DEF is not a country-specific tone and is used by several national Caller ID profiles.

+ *  

+ *  VI. Cadence Profiles:

+ *  1. These profiles are available only in the full version of the API.

+ *  2.  ITU-T Recommendation E.180 (03/1998) revised on 02/2003 and ETSI TR 101 041-2 V.1.1.1 (05/1997) were used if national standards were not

+ *  available.

+ *  3. Recommended ETSI ES 201 970 call progress cadences are provided for reference.

+ *  4. Some countries support multiple call progress tone cadences.  The ones used are believed to be representative and most common.  The user may

+ *  wish to edit some of the cadence definitions or add additional cadences.

+ *  5. Ringing signal cadences include the alerting signal(s) and necessary delays for Type 1 Caller ID, if it is supported below in the Caller ID Profiles.

+ *  

+ *  VII. Caller ID Profiles:

+ *  1. These profiles are available only in the full version of the API.

+ *  2. The option to calculate the checksum in the API is selected for all countries except Japan, which requires that the CRC checksum be calculated by

+ *  host application.

+ *  

+ *  VIII. FXO/Dialing Profiles:

+ *  1. 44 country-specific profiles are provided.  They take into account such variations in national standards as pulse dialing, DTMF dialing, and line

+ *  event detection parameters.

+ *  2. They may be edited as necessary to meet regulatory requirements.

+ *  3. ETSI 203 021 defaults are also provided for reference.

+ *  

+ *  IX. Metering Profiles:

+ *  1. Not supported by VE890 Series.

+ *  

+ *  (c) Copyright 2011 Microsemi Corporation. All rights reserved.

+ *  

+ *  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

+ */

+

+#include "profile_89116.h"

+

+

+/************** Device_Parameters **************/

+

+/* Device Configuration Data - VE890 100V Buck-Boost */

+const VpProfileDataType DEV_PROFILE_VE890_BB100V[] =

+{

+  /* Device Profile for VE890 Device Family */

+ 0x00, 0xFF, 0x02, 0x1A, /* Profile Type and Length */

+ 0x06, 0x00, /* Version and MPI Command */

+ 0x20, 0x00, /* PCLK Frequency */

+ 0x8A, 0x00, /* Device Config 1 and MCLK Correction */

+ 0x40, 0x02, /* Clock Slot and Max Events */

+ 0x0A, 0x00, /* Device Tickrate */

+ 0xE4, 0x02, 0x44, 0x0A, /* Buck-Boost Switching Regulator Parameters */

+ 0x75, 0x00, 0x98, 0x40, 0xC0, 0x40, /* Regulator Timing Parameters */

+ 0x28, 0x40, 0x30, 0x40, 0x30, 0x40  /* FreeRun Timing Parameters */

+};

+

+/************** AC_Coefficients **************/

+

+/* AC FXS RF50 600R Normal Coefficients (Default)  */

+const VpProfileDataType AC_FXS_RF50_600R_DEF[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBC, 0x4C, 0x01, 0x49, 0xCA, 0xF1, 0x98, 0xAA, 0x5B, 0xEB,

+ 0x2C, 0x72, 0xA4, 0x26, 0x24, 0xEB, 0x2D, 0x9A, 0x2B, 0xBA, 0x27, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x2B, 0xA0, 0xD2, 0xA2, 0xAC, 0xCB, 0xE5, 0xA3,

+ 0x2B, 0xBC, 0xAD, 0x46, 0x88, 0x3C, 0x20, 0x33, 0x4D, 0xAA, 0xB7, 0x45,

+ 0xE6, 0x24, 0x5F, 0x22, 0x9F, 0x82, 0xAA, 0x71, 0x80, 0xC8, 0xF0, 0x50,

+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xDB, 0x1C, 0xA3, 0xA8, 0xFE, 0x87, 0xAA,

+ 0xFA, 0x9F, 0xB9, 0xF0, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXS RF50 ETSI ES201 970 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_ETSI[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Telcordia GR-57 900R+2.16uF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_GR57[] =

+{

+  /* AC Profile */

+ 0xE4, 0x00, 0xE1, 0x4C, 0x01, 0x49, 0xCA, 0x0E, 0x98, 0x7B, 0xCA, 0x64,

+ 0x5D, 0x2A, 0xB3, 0xBA, 0xA3, 0xC2, 0x2C, 0x9A, 0x6B, 0xA2, 0x25, 0x2D,

+ 0x01, 0x8A, 0xC3, 0xC0, 0xA2, 0x21, 0x24, 0x25, 0x22, 0x37, 0x22, 0xAD,

+ 0x2A, 0x87, 0x23, 0xA7, 0x88, 0x2A, 0xC0, 0x32, 0x2D, 0x53, 0xB4, 0x2A,

+ 0xAC, 0xA4, 0x36, 0x22, 0x6F, 0x82, 0x29, 0x71, 0x80, 0xB9, 0xF0, 0x50,

+ 0x00, 0x86, 0xA4, 0x53, 0xA1, 0x42, 0x12, 0x32, 0xAA, 0x47, 0x35, 0xAB,

+ 0x7A, 0x97, 0xB2, 0x70, 0x96, 0x25, 0xC0, 0x00

+};

+

+/* AC FXS RF50 Austria 220R+820R//115nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_AT[] =

+{

+  /* AC Profile */

+ 0x55, 0x00, 0xC7, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0x3C, 0x41, 0xB4,

+ 0xB2, 0x3B, 0x3B, 0xEA, 0xBA, 0xF4, 0x53, 0x9A, 0x2E, 0xA2, 0x97, 0x9F,

+ 0x01, 0x8A, 0x9C, 0xD0, 0x2A, 0x10, 0x97, 0xB8, 0xDA, 0x33, 0xA3, 0x3E,

+ 0xBA, 0x8F, 0xAB, 0x8F, 0x88, 0xB3, 0xC0, 0x22, 0xB6, 0xD2, 0x2D, 0xBB,

+ 0x4E, 0x22, 0x25, 0xC2, 0xAD, 0x82, 0xA8, 0xF1, 0x80, 0xA8, 0xF0, 0x50,

+ 0x00, 0x86, 0xB4, 0x5B, 0x32, 0x24, 0x1A, 0xA1, 0x2C, 0x2D, 0xB3, 0x6B,

+ 0x4C, 0xC5, 0xBC, 0x60, 0x96, 0x23, 0xA1, 0x00

+};

+

+/* AC FXS RF50 Australia 220R+820R//120nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_AU[] =

+{

+  /* AC Profile */

+ 0xF5, 0x00, 0x1A, 0x4C, 0x01, 0x49, 0xCA, 0xE6, 0x98, 0xB3, 0x51, 0x3A,

+ 0x62, 0xBC, 0xCB, 0xA3, 0xCA, 0x3A, 0xC3, 0x9A, 0x42, 0xC2, 0x97, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0xEA, 0x10, 0x3B, 0xB8, 0x2B, 0x24, 0x22, 0xA3,

+ 0x24, 0xAB, 0xC3, 0x35, 0x88, 0x25, 0xC0, 0xBD, 0x37, 0x3B, 0x3D, 0x3B,

+ 0x3E, 0x2A, 0x35, 0xC2, 0x2E, 0x82, 0x29, 0x71, 0x80, 0x29, 0xF0, 0x50,

+ 0x00, 0x86, 0x53, 0x53, 0x32, 0xA4, 0x1A, 0xA1, 0xCB, 0x2D, 0xB3, 0xBB,

+ 0x4A, 0xB5, 0x2B, 0x60, 0x96, 0xAA, 0xA1, 0x00

+};

+

+/* AC FXS RF50 Belgium 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_BE[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Bulgaria 220R+820R//115nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_BG[] =

+{

+  /* AC Profile */

+ 0x55, 0x00, 0xC7, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0x3C, 0x41, 0xB4,

+ 0xB2, 0x3B, 0x3B, 0xEA, 0xBA, 0xF4, 0x53, 0x9A, 0x2E, 0xA2, 0x97, 0x9F,

+ 0x01, 0x8A, 0x9C, 0xD0, 0x2A, 0x10, 0x97, 0xB8, 0xDA, 0x33, 0xA3, 0x3E,

+ 0xBA, 0x8F, 0xAB, 0x8F, 0x88, 0xB3, 0xC0, 0x22, 0xB6, 0xD2, 0x2D, 0xBB,

+ 0x4E, 0x22, 0x25, 0xC2, 0xAD, 0x82, 0xA8, 0xF1, 0x80, 0xA8, 0xF0, 0x50,

+ 0x00, 0x86, 0xB4, 0x5B, 0x32, 0x24, 0x1A, 0xA1, 0x2C, 0x2D, 0xB3, 0x6B,

+ 0x4C, 0xC5, 0xBC, 0x60, 0x96, 0x23, 0xA1, 0x00

+};

+

+/* AC FXS RF50 Brazil 900R Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_BR[] =

+{

+  /* AC Profile */

+ 0x33, 0x00, 0x7D, 0x4C, 0x01, 0x49, 0xCA, 0x09, 0x98, 0x22, 0x3B, 0xBB,

+ 0x2C, 0x5A, 0xA4, 0x23, 0xA3, 0x75, 0xAC, 0x9A, 0x3A, 0xAA, 0xF7, 0x9F,

+ 0x01, 0x8A, 0x2E, 0x01, 0xAD, 0xA0, 0xAA, 0xAB, 0xC2, 0x53, 0xB2, 0xAB,

+ 0xAA, 0xC5, 0xC3, 0x9F, 0x88, 0x22, 0x60, 0x42, 0xAB, 0xB2, 0x35, 0xF4,

+ 0xB5, 0x24, 0x4D, 0xC2, 0x27, 0x82, 0xA8, 0x71, 0x80, 0x29, 0xF0, 0x50,

+ 0x00, 0x86, 0xAB, 0x44, 0xE1, 0x2A, 0x0B, 0x43, 0xC8, 0x7F, 0x27, 0x3C,

+ 0xE3, 0x9F, 0x5D, 0xF0, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXS RF50 Switzerland 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_CH[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 China 200R+680R//100nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_CN[] =

+{

+  /* AC Profile */

+ 0x02, 0x00, 0xD1, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0xCC, 0xA1, 0xB2,

+ 0xD2, 0x24, 0xAB, 0xAA, 0xBA, 0xA6, 0xB3, 0x9A, 0xE2, 0x34, 0x97, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0xB4, 0x20, 0x43, 0xA8, 0xA8, 0xF3, 0xAD, 0x2F,

+ 0x22, 0xAF, 0x3A, 0x87, 0x88, 0x3C, 0xD0, 0x2A, 0xA5, 0xAA, 0x2D, 0xA3,

+ 0xAD, 0xAB, 0x25, 0x33, 0xAD, 0x82, 0xA9, 0x71, 0x80, 0xA9, 0xF0, 0x50,

+ 0x00, 0x86, 0xA3, 0x53, 0x32, 0x55, 0x12, 0xA1, 0x72, 0x3C, 0xB4, 0x26,

+ 0x6B, 0x87, 0xB9, 0xF0, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXS RF50 Germany 220R+820R//115nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_DE[] =

+{

+  /* AC Profile */

+ 0x55, 0x00, 0xC7, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0x3C, 0x41, 0xB4,

+ 0xB2, 0x3B, 0x3B, 0xEA, 0xBA, 0xF4, 0x53, 0x9A, 0x2E, 0xA2, 0x97, 0x9F,

+ 0x01, 0x8A, 0x9C, 0xD0, 0x2A, 0x10, 0x97, 0xB8, 0xDA, 0x33, 0xA3, 0x3E,

+ 0xBA, 0x8F, 0xAB, 0x8F, 0x88, 0xB3, 0xC0, 0x22, 0xB6, 0xD2, 0x2D, 0xBB,

+ 0x4E, 0x22, 0x25, 0xC2, 0xAD, 0x82, 0xA8, 0xF1, 0x80, 0xA8, 0xF0, 0x50,

+ 0x00, 0x86, 0xB4, 0x5B, 0x32, 0x24, 0x1A, 0xA1, 0x2C, 0x2D, 0xB3, 0x6B,

+ 0x4C, 0xC5, 0xBC, 0x60, 0x96, 0x23, 0xA1, 0x00

+};

+

+/* AC FXS RF50 Denmark 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_DK[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Spain 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_ES[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Finland 270R+910R//120nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_FI[] =

+{

+  /* AC Profile */

+ 0x1F, 0x00, 0xAA, 0x4C, 0x01, 0x49, 0xCA, 0xEC, 0x98, 0x2B, 0x41, 0x52,

+ 0x23, 0xAB, 0x6B, 0x22, 0x2B, 0xCA, 0xA3, 0x9A, 0x62, 0xB2, 0x97, 0x9F,

+ 0x01, 0x8A, 0x2E, 0x01, 0xBC, 0x00, 0x23, 0x58, 0x2D, 0x3A, 0xB5, 0xA1,

+ 0x23, 0xEA, 0xAA, 0x24, 0x88, 0xCB, 0x50, 0xA2, 0xAF, 0x3E, 0x2D, 0x22,

+ 0xDF, 0x3A, 0x25, 0xB3, 0x2E, 0x82, 0x32, 0x22, 0x80, 0x3C, 0xA0, 0x50,

+ 0x00, 0x86, 0xB4, 0x5A, 0x22, 0x23, 0x1A, 0xC1, 0x23, 0x22, 0x23, 0xBA,

+ 0x32, 0xC4, 0xB3, 0x50, 0x96, 0x3A, 0x31, 0x00

+};

+

+/* AC FXS RF50 France 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_FR[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 UK 370R+620R//310nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_GB[] =

+{

+  /* AC Profile */

+ 0x07, 0x00, 0xE7, 0x4C, 0x01, 0x49, 0xCA, 0xE0, 0x98, 0xDB, 0xA1, 0x2B,

+ 0x22, 0x2A, 0x24, 0xC2, 0x3C, 0xF4, 0xA6, 0x9A, 0x4B, 0xA2, 0xB6, 0x2E,

+ 0x01, 0x8A, 0xD3, 0xD0, 0x2A, 0x10, 0x23, 0x29, 0xA2, 0xDA, 0x4D, 0x26,

+ 0x43, 0xAD, 0x23, 0x97, 0x88, 0x2A, 0x50, 0x3C, 0x2E, 0x4B, 0x4D, 0x23,

+ 0x4E, 0xBB, 0x26, 0x72, 0xBF, 0x82, 0xF8, 0x71, 0x80, 0xF9, 0xF0, 0x50,

+ 0x00, 0x86, 0x73, 0x5C, 0x32, 0x2C, 0x13, 0x22, 0xAA, 0x24, 0x33, 0xAA,

+ 0x32, 0x34, 0xAA, 0x40, 0x96, 0xA3, 0xA0, 0x00

+};

+

+/* AC FXS RF50 Greece 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_GR[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Hungary 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_HU[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Ireland 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_IE[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Israel 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_IL[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Iceland 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_IS[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Italy 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_IT[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Japan 600R+1uF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_JP[] =

+{

+  /* AC Profile */

+ 0x90, 0x00, 0xD7, 0x4C, 0x01, 0x49, 0xCA, 0xF6, 0x98, 0x22, 0x2C, 0xA2,

+ 0x37, 0x34, 0x25, 0x53, 0xE5, 0x9F, 0x45, 0x9A, 0xBA, 0xA2, 0x23, 0x4B,

+ 0xC0, 0x8A, 0xAA, 0xA0, 0xC6, 0xB0, 0xAE, 0x4B, 0x2A, 0xB3, 0xAC, 0x2C,

+ 0xDF, 0xA6, 0xB3, 0x97, 0x88, 0x3A, 0x20, 0x23, 0xBE, 0x42, 0xAD, 0x32,

+ 0x9F, 0x34, 0xAD, 0x3B, 0x8F, 0x82, 0xB8, 0x71, 0x80, 0xAA, 0xF0, 0x50,

+ 0x00, 0x86, 0xBA, 0x52, 0xA1, 0xAF, 0x12, 0xA2, 0xB2, 0x4B, 0x24, 0x2D,

+ 0x43, 0xB4, 0x3D, 0x40, 0x96, 0xF2, 0xD0, 0x00

+};

+

+/* AC FXS RF50 Netherlands 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_NL[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Norway 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_NO[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 New Zealand 370R+620R//310nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_NZ[] =

+{

+  /* AC Profile */

+ 0xA9, 0x00, 0x06, 0x4C, 0x01, 0x49, 0xCA, 0xF9, 0x98, 0x4A, 0xA9, 0xBA,

+ 0xA1, 0xA2, 0xA1, 0x33, 0xBB, 0x33, 0x2D, 0x9A, 0xB4, 0xB2, 0x27, 0x1F,

+ 0x01, 0x8A, 0xBC, 0x01, 0x79, 0x70, 0x2C, 0xAB, 0x32, 0xA9, 0x24, 0xB5,

+ 0x3B, 0xCD, 0x3C, 0x8F, 0x88, 0x43, 0xD0, 0x3E, 0xA2, 0xAA, 0x2A, 0xAB,

+ 0x22, 0x2A, 0xAA, 0x3B, 0xA3, 0x82, 0xA8, 0x71, 0x80, 0xB9, 0xF0, 0x50,

+ 0x00, 0x86, 0xD2, 0x54, 0x22, 0x5C, 0x1D, 0x52, 0x2A, 0x2B, 0xA3, 0xA3,

+ 0x42, 0xA4, 0xCC, 0x50, 0x96, 0x22, 0xA0, 0x00

+};

+

+/* AC FXS RF50 Portugal 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_PT[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 Russia 150R+510R//47nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_RU[] =

+{

+  /* AC Profile */

+ 0x81, 0x00, 0x5A, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0x2C, 0xA2, 0x2A,

+ 0x44, 0x62, 0x6C, 0x22, 0xAB, 0x7A, 0xA4, 0x9A, 0xAB, 0x3A, 0x97, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x33, 0x40, 0xA2, 0xA9, 0xA2, 0x53, 0x2B, 0x2D,

+ 0x97, 0xB7, 0xAD, 0x87, 0x88, 0xDE, 0x30, 0xB2, 0x36, 0xAA, 0xCD, 0xAA,

+ 0x2F, 0x42, 0xB5, 0x42, 0x2E, 0x82, 0xBA, 0x71, 0x80, 0xA9, 0xF0, 0x50,

+ 0x00, 0x86, 0xD3, 0x5A, 0x22, 0xBC, 0x14, 0xB2, 0xA3, 0x53, 0xBF, 0xBA,

+ 0xFA, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXS RF50 Sweden 270R+750R//150nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_SE[] =

+{

+  /* AC Profile */

+ 0xC0, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0x7B, 0xB1, 0xAC,

+ 0xE2, 0xAA, 0xAC, 0x22, 0x2B, 0x4A, 0x34, 0x9A, 0xC4, 0xA2, 0xA7, 0x9F,

+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x20, 0x23, 0xA8, 0xBB, 0xAC, 0x4A, 0xA4,

+ 0x2C, 0x5D, 0x6A, 0x27, 0x88, 0xAA, 0xE0, 0x2A, 0x8F, 0x22, 0x2D, 0xAA,

+ 0xAE, 0x23, 0x25, 0x52, 0xAD, 0x82, 0x2A, 0xF1, 0x80, 0xBA, 0xE0, 0x50,

+ 0x00, 0x86, 0xD3, 0x54, 0x32, 0x97, 0x14, 0xA1, 0xAA, 0x2B, 0xB3, 0xAD,

+ 0x42, 0x45, 0xB3, 0x60, 0x96, 0xA5, 0xE1, 0x00

+};

+

+/* AC FXS RF50 South Africa 220R+820R//115nF Normal Coefficients */

+const VpProfileDataType AC_FXS_RF50_ZA[] =

+{

+  /* AC Profile */

+ 0x55, 0x00, 0xC7, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0x3C, 0x41, 0xB4,

+ 0xB2, 0x3B, 0x3B, 0xEA, 0xBA, 0xF4, 0x53, 0x9A, 0x2E, 0xA2, 0x97, 0x9F,

+ 0x01, 0x8A, 0x9C, 0xD0, 0x2A, 0x10, 0x97, 0xB8, 0xDA, 0x33, 0xA3, 0x3E,

+ 0xBA, 0x8F, 0xAB, 0x8F, 0x88, 0xB3, 0xC0, 0x22, 0xB6, 0xD2, 0x2D, 0xBB,

+ 0x4E, 0x22, 0x25, 0xC2, 0xAD, 0x82, 0xA8, 0xF1, 0x80, 0xA8, 0xF0, 0x50,

+ 0x00, 0x86, 0xB4, 0x5B, 0x32, 0x24, 0x1A, 0xA1, 0x2C, 0x2D, 0xB3, 0x6B,

+ 0x4C, 0xC5, 0xBC, 0x60, 0x96, 0x23, 0xA1, 0x00

+};

+

+/* AC FXO LC Filter 600R Normal ABF Coefficients (Default) */

+const VpProfileDataType AC_FXO_LC_600R_DEF[] =

+{

+  /* AC Profile */

+ 0xF6, 0x00, 0x42, 0xF2, 0x01, 0x4B, 0xCA, 0xFF, 0x98, 0xAA, 0x42, 0x2E,

+ 0xAC, 0xA2, 0xAA, 0xC2, 0x2C, 0x42, 0x33, 0x9A, 0xCA, 0x87, 0x01, 0x6E,

+ 0x01, 0x8A, 0xB3, 0xD0, 0x24, 0x20, 0xAC, 0xA9, 0x32, 0xB3, 0xA2, 0xD5,

+ 0x23, 0xBC, 0x2B, 0x26, 0x88, 0xA4, 0x10, 0xBC, 0x58, 0x3A, 0xA0, 0xEA,

+ 0xB9, 0xAC, 0x23, 0xAC, 0x6D, 0x82, 0x24, 0xA0, 0x80, 0x32, 0x20, 0x50,

+ 0x01, 0x76, 0x20, 0x86, 0xBD, 0xEC, 0xD4, 0x2D, 0x43, 0xC2, 0x3A, 0xDB,

+ 0x3E, 0x32, 0x6E, 0xA6, 0x87, 0x60, 0x96, 0xBD, 0x01, 0x09, 0x12, 0x86,

+ 0xC4, 0xD1, 0xB3, 0x2B, 0x42, 0xB2, 0x3A, 0xA7, 0x3B, 0x3A, 0x5B, 0x97,

+ 0x57, 0x61, 0x96, 0x22, 0xE0, 0x86, 0x34, 0xEB, 0x24, 0x22, 0x4D, 0xC2,

+ 0x33, 0xA4, 0xBA, 0x29, 0xF4, 0x87, 0xB3, 0x61, 0x96, 0x49, 0xE0, 0x86,

+ 0x16, 0xD1, 0xB3, 0xD3, 0x42, 0xE2, 0xD2, 0xAB, 0x2A, 0x3A, 0xC1, 0xCE,

+ 0x30, 0x71, 0x96, 0x13, 0xE0, 0x86, 0x4F, 0xE9, 0xF4, 0x1B, 0x31, 0x42,

+ 0x3A, 0x94, 0x1A, 0x32, 0xC2, 0xBB, 0x17, 0x61, 0x96, 0x32, 0xE0, 0x86,

+ 0x12, 0x71, 0xA7, 0x15, 0x33, 0x22, 0x1B, 0x96, 0xB9, 0x23, 0xF2, 0x5A,

+ 0x51, 0x73, 0x96, 0x1A, 0xE0, 0x86, 0x2D, 0xD4, 0x14, 0x22, 0x44, 0xC2,

+ 0x1C, 0xB1, 0x2B, 0xC4, 0x5B, 0xAF, 0x36, 0x61, 0x96, 0x07, 0xE0, 0x86,

+ 0x12, 0xF1, 0x8B, 0x1B, 0x32, 0x42, 0x23, 0xB1, 0xBA, 0x41, 0xC3, 0xAC,

+ 0x14, 0x61, 0x96, 0x29, 0xE0, 0x86, 0x3C, 0xCC, 0x43, 0x1B, 0x52, 0x42,

+ 0x4A, 0xC2, 0x2A, 0x2C, 0xAB, 0x3A, 0x3A, 0xB2, 0x96, 0x3A, 0x80, 0x86,

+ 0x18, 0x51, 0xE4, 0xB3, 0xF1, 0x23, 0x13, 0xC3, 0xAA, 0x3A, 0xBB, 0x3E,

+ 0x24, 0x61, 0x96, 0x24, 0xE0, 0x00

+};

+

+/* AC FXO LC Filter ETSI ES203 021 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_ETSI[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter TBR21 with Current Limit 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_TBR21_CR[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x38, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Telcordia GR-57 600R Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_GR57[] =

+{

+  /* AC Profile */

+ 0xF6, 0x00, 0x42, 0xF2, 0x01, 0x4B, 0xCA, 0xFF, 0x98, 0xAA, 0x42, 0x2E,

+ 0xAC, 0xA2, 0xAA, 0xC2, 0x2C, 0x42, 0x33, 0x9A, 0xCA, 0x87, 0x01, 0x6E,

+ 0x01, 0x8A, 0xB3, 0xD0, 0x24, 0x20, 0xAC, 0xA9, 0x32, 0xB3, 0xA2, 0xD5,

+ 0x23, 0xBC, 0x2B, 0x26, 0x88, 0xA4, 0x10, 0xBC, 0x58, 0x3A, 0xA0, 0xEA,

+ 0xB9, 0xAC, 0x23, 0xAC, 0x6D, 0x82, 0x24, 0xA0, 0x80, 0x32, 0x20, 0x50,

+ 0x01, 0x76, 0x20, 0x86, 0xBD, 0xEC, 0xD4, 0x2D, 0x43, 0xC2, 0x3A, 0xDB,

+ 0x3E, 0x32, 0x6E, 0xA6, 0x87, 0x60, 0x96, 0xBD, 0x01, 0x09, 0x12, 0x86,

+ 0xC4, 0xD1, 0xB3, 0x2B, 0x42, 0xB2, 0x3A, 0xA7, 0x3B, 0x3A, 0x5B, 0x97,

+ 0x57, 0x61, 0x96, 0x22, 0xE0, 0x86, 0x34, 0xEB, 0x24, 0x22, 0x4D, 0xC2,

+ 0x33, 0xA4, 0xBA, 0x29, 0xF4, 0x87, 0xB3, 0x61, 0x96, 0x49, 0xE0, 0x86,

+ 0x16, 0xD1, 0xB3, 0xD3, 0x42, 0xE2, 0xD2, 0xAB, 0x2A, 0x3A, 0xC1, 0xCE,

+ 0x30, 0x71, 0x96, 0x13, 0xE0, 0x86, 0x4F, 0xE9, 0xF4, 0x1B, 0x31, 0x42,

+ 0x3A, 0x94, 0x1A, 0x32, 0xC2, 0xBB, 0x17, 0x61, 0x96, 0x32, 0xE0, 0x86,

+ 0x12, 0x71, 0xA7, 0x15, 0x33, 0x22, 0x1B, 0x96, 0xB9, 0x23, 0xF2, 0x5A,

+ 0x51, 0x73, 0x96, 0x1A, 0xE0, 0x86, 0x2D, 0xD4, 0x14, 0x22, 0x44, 0xC2,

+ 0x1C, 0xB1, 0x2B, 0xC4, 0x5B, 0xAF, 0x36, 0x61, 0x96, 0x07, 0xE0, 0x86,

+ 0x12, 0xF1, 0x8B, 0x1B, 0x32, 0x42, 0x23, 0xB1, 0xBA, 0x41, 0xC3, 0xAC,

+ 0x14, 0x61, 0x96, 0x29, 0xE0, 0x86, 0x3C, 0xCC, 0x43, 0x1B, 0x52, 0x42,

+ 0x4A, 0xC2, 0x2A, 0x2C, 0xAB, 0x3A, 0x3A, 0xB2, 0x96, 0x3A, 0x80, 0x86,

+ 0x18, 0x51, 0xE4, 0xB3, 0xF1, 0x23, 0x13, 0xC3, 0xAA, 0x3A, 0xBB, 0x3E,

+ 0x24, 0x61, 0x96, 0x24, 0xE0, 0x00

+};

+

+/* AC FXO LC Filter Austria 220R+820R//115nF Normal Coefficients */

+const VpProfileDataType AC_FXO_LC_AT[] =

+{

+  /* AC Profile */

+ 0x10, 0x00, 0xB6, 0xF2, 0x01, 0x4B, 0xCA, 0xFD, 0x98, 0xB2, 0x33, 0x2A,

+ 0x97, 0xAA, 0x2C, 0x5A, 0xAC, 0xAA, 0x34, 0x9A, 0x01, 0x90, 0x08, 0x9F,

+ 0x01, 0x8A, 0x3B, 0xC0, 0x22, 0x10, 0xDA, 0xA9, 0x2B, 0xA8, 0x32, 0x21,

+ 0xA2, 0xA9, 0x52, 0xB3, 0x88, 0xE2, 0x50, 0x52, 0x3A, 0x2A, 0x22, 0x22,

+ 0xA3, 0x32, 0xAB, 0x2D, 0xB4, 0x82, 0xC2, 0x31, 0x80, 0xAA, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0xBA, 0xEC, 0x97, 0x2B, 0x34, 0x27, 0x3A, 0xA2,

+ 0xAA, 0xAA, 0xB2, 0xAC, 0x36, 0x60, 0x96, 0x2E, 0x01, 0x09, 0x12, 0x86,

+ 0x23, 0xFA, 0x97, 0xAA, 0x3A, 0x97, 0xAA, 0xAA, 0xAA, 0xF4, 0xBB, 0x2C,

+ 0x2B, 0x60, 0x96, 0x2E, 0x01, 0x86, 0x3A, 0xDA, 0x5F, 0xAA, 0x33, 0xAE,

+ 0xC7, 0xAD, 0x4A, 0xFA, 0xAA, 0xCB, 0x42, 0xC0, 0x96, 0xB4, 0x41, 0x86,

+ 0xBA, 0xDA, 0x3F, 0xAA, 0x3A, 0xAF, 0x98, 0x9A, 0x3A, 0xAA, 0xAA, 0x3B,

+ 0x2B, 0xB0, 0x96, 0xBC, 0x31, 0x86, 0x97, 0xF2, 0xAD, 0xBA, 0x42, 0xA3,

+ 0xCB, 0xB3, 0xCA, 0x2C, 0xA3, 0xAA, 0xD2, 0xB0, 0x96, 0x32, 0xA0, 0x86,

+ 0x3A, 0x6B, 0xA2, 0x2A, 0x02, 0xA4, 0xA3, 0x8A, 0x18, 0x23, 0x8E, 0xB8,

+ 0xBA, 0x80, 0x96, 0xA2, 0xA0, 0x86, 0xE8, 0xF2, 0x2F, 0x2B, 0x44, 0xA3,

+ 0xC6, 0xCA, 0x2B, 0x2E, 0xBA, 0x2C, 0x33, 0x70, 0x96, 0x2E, 0x01, 0x86,

+ 0xF8, 0x72, 0xBE, 0x3C, 0x43, 0xA3, 0x22, 0xC2, 0xAA, 0xA2, 0xB2, 0xAB,

+ 0xA3, 0x70, 0x96, 0x2E, 0x01, 0x86, 0xCC, 0xE2, 0xBD, 0x3A, 0x43, 0x24,

+ 0xBB, 0xBA, 0xBA, 0x4B, 0xA2, 0x2B, 0xA6, 0xB0, 0x96, 0x5D, 0x21, 0x86,

+ 0xBA, 0xEA, 0x87, 0xAB, 0x3C, 0x75, 0x2A, 0xA2, 0xAA, 0x5A, 0xB2, 0xED,

+ 0x52, 0x60, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXO LC Filter Australia 220R+820R//120nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_AU[] =

+{

+  /* AC Profile */

+ 0x10, 0x00, 0xB6, 0xF2, 0x01, 0x4B, 0xCA, 0xFD, 0x98, 0xB2, 0x33, 0x2A,

+ 0x97, 0xAA, 0x2C, 0x5A, 0xAC, 0xAA, 0x34, 0x9A, 0x01, 0x90, 0x08, 0x9F,

+ 0x01, 0x8A, 0x3B, 0xC0, 0x22, 0x10, 0xDA, 0xA9, 0x2B, 0xA8, 0x32, 0x21,

+ 0xA2, 0xA9, 0x52, 0xB3, 0x88, 0xE2, 0x50, 0x52, 0x3A, 0x2A, 0x22, 0x22,

+ 0xA3, 0x32, 0xAB, 0x2D, 0xB4, 0x82, 0xC2, 0x31, 0x80, 0xAA, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0xBA, 0xEC, 0x97, 0x2B, 0x34, 0x27, 0x3A, 0xA2,

+ 0xAA, 0xAA, 0xB2, 0xAC, 0x36, 0x60, 0x96, 0x2E, 0x01, 0x09, 0x12, 0x86,

+ 0x23, 0xFA, 0x97, 0xAA, 0x3A, 0x97, 0xAA, 0xAA, 0xAA, 0xF4, 0xBB, 0x2C,

+ 0x2B, 0x60, 0x96, 0x2E, 0x01, 0x86, 0x3A, 0xDA, 0x5F, 0xAA, 0x33, 0xAE,

+ 0xC7, 0xAD, 0x4A, 0xFA, 0xAA, 0xCB, 0x42, 0xC0, 0x96, 0xB4, 0x41, 0x86,

+ 0xBA, 0xDA, 0x3F, 0xAA, 0x3A, 0xAF, 0x98, 0x9A, 0x3A, 0xAA, 0xAA, 0x3B,

+ 0x2B, 0xB0, 0x96, 0xBC, 0x31, 0x86, 0x97, 0xF2, 0xAD, 0xBA, 0x42, 0xA3,

+ 0xCB, 0xB3, 0xCA, 0x2C, 0xA3, 0xAA, 0xD2, 0xB0, 0x96, 0x32, 0xA0, 0x86,

+ 0x3A, 0x6B, 0xA2, 0x2A, 0x02, 0xA4, 0xA3, 0x8A, 0x18, 0x23, 0x8E, 0xB8,

+ 0xBA, 0x80, 0x96, 0xA2, 0xA0, 0x86, 0xE8, 0xF2, 0x2F, 0x2B, 0x44, 0xA3,

+ 0xC6, 0xCA, 0x2B, 0x2E, 0xBA, 0x2C, 0x33, 0x70, 0x96, 0x2E, 0x01, 0x86,

+ 0xF8, 0x72, 0xBE, 0x3C, 0x43, 0xA3, 0x22, 0xC2, 0xAA, 0xA2, 0xB2, 0xAB,

+ 0xA3, 0x70, 0x96, 0x2E, 0x01, 0x86, 0xCC, 0xE2, 0xBD, 0x3A, 0x43, 0x24,

+ 0xBB, 0xBA, 0xBA, 0x4B, 0xA2, 0x2B, 0xA6, 0xB0, 0x96, 0x5D, 0x21, 0x86,

+ 0xBA, 0xEA, 0x87, 0xAB, 0x3C, 0x75, 0x2A, 0xA2, 0xAA, 0x5A, 0xB2, 0xED,

+ 0x52, 0x60, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXO LC Filter Belgium 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_BE[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Bulgaria 220R+820R//115nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_BG[] =

+{

+  /* AC Profile */

+ 0x10, 0x00, 0xB6, 0xF2, 0x01, 0x4B, 0xCA, 0xFD, 0x98, 0xB2, 0x33, 0x2A,

+ 0x97, 0xAA, 0x2C, 0x5A, 0xAC, 0xAA, 0x34, 0x9A, 0x01, 0x90, 0x08, 0x9F,

+ 0x01, 0x8A, 0x3B, 0xC0, 0x22, 0x10, 0xDA, 0xA9, 0x2B, 0xA8, 0x32, 0x21,

+ 0xA2, 0xA9, 0x52, 0xB3, 0x88, 0xE2, 0x50, 0x52, 0x3A, 0x2A, 0x22, 0x22,

+ 0xA3, 0x32, 0xAB, 0x2D, 0xB4, 0x82, 0xC2, 0x31, 0x80, 0xAA, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0xBA, 0xEC, 0x97, 0x2B, 0x34, 0x27, 0x3A, 0xA2,

+ 0xAA, 0xAA, 0xB2, 0xAC, 0x36, 0x60, 0x96, 0x2E, 0x01, 0x09, 0x12, 0x86,

+ 0x23, 0xFA, 0x97, 0xAA, 0x3A, 0x97, 0xAA, 0xAA, 0xAA, 0xF4, 0xBB, 0x2C,

+ 0x2B, 0x60, 0x96, 0x2E, 0x01, 0x86, 0x3A, 0xDA, 0x5F, 0xAA, 0x33, 0xAE,

+ 0xC7, 0xAD, 0x4A, 0xFA, 0xAA, 0xCB, 0x42, 0xC0, 0x96, 0xB4, 0x41, 0x86,

+ 0xBA, 0xDA, 0x3F, 0xAA, 0x3A, 0xAF, 0x98, 0x9A, 0x3A, 0xAA, 0xAA, 0x3B,

+ 0x2B, 0xB0, 0x96, 0xBC, 0x31, 0x86, 0x97, 0xF2, 0xAD, 0xBA, 0x42, 0xA3,

+ 0xCB, 0xB3, 0xCA, 0x2C, 0xA3, 0xAA, 0xD2, 0xB0, 0x96, 0x32, 0xA0, 0x86,

+ 0x3A, 0x6B, 0xA2, 0x2A, 0x02, 0xA4, 0xA3, 0x8A, 0x18, 0x23, 0x8E, 0xB8,

+ 0xBA, 0x80, 0x96, 0xA2, 0xA0, 0x86, 0xE8, 0xF2, 0x2F, 0x2B, 0x44, 0xA3,

+ 0xC6, 0xCA, 0x2B, 0x2E, 0xBA, 0x2C, 0x33, 0x70, 0x96, 0x2E, 0x01, 0x86,

+ 0xF8, 0x72, 0xBE, 0x3C, 0x43, 0xA3, 0x22, 0xC2, 0xAA, 0xA2, 0xB2, 0xAB,

+ 0xA3, 0x70, 0x96, 0x2E, 0x01, 0x86, 0xCC, 0xE2, 0xBD, 0x3A, 0x43, 0x24,

+ 0xBB, 0xBA, 0xBA, 0x4B, 0xA2, 0x2B, 0xA6, 0xB0, 0x96, 0x5D, 0x21, 0x86,

+ 0xBA, 0xEA, 0x87, 0xAB, 0x3C, 0x75, 0x2A, 0xA2, 0xAA, 0x5A, 0xB2, 0xED,

+ 0x52, 0x60, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXO LC Filter Brazil 900R Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_BR[] =

+{

+  /* AC Profile */

+ 0x2A, 0x00, 0x95, 0xF2, 0x01, 0x4B, 0xCA, 0x02, 0x98, 0xCC, 0x24, 0xE2,

+ 0xCD, 0xFB, 0x2C, 0x2B, 0xDD, 0xC2, 0x34, 0x9A, 0x01, 0x90, 0x08, 0x6F,

+ 0x01, 0x8A, 0x2D, 0xD0, 0x35, 0xA0, 0x2A, 0xA2, 0x2A, 0x2A, 0xC4, 0xB2,

+ 0x9F, 0xBB, 0x9F, 0xB5, 0x88, 0xA2, 0x70, 0x01, 0x90, 0x01, 0x90, 0x01,

+ 0x90, 0x01, 0x90, 0x01, 0x90, 0x82, 0x23, 0xA0, 0x80, 0xB9, 0xF0, 0x50,

+ 0x01, 0x76, 0x28, 0x86, 0x2A, 0xDD, 0xA5, 0xA3, 0x35, 0xBC, 0xBA, 0xA2,

+ 0xAB, 0xAC, 0x6A, 0x35, 0xBA, 0x50, 0x96, 0x1D, 0x01, 0x09, 0x12, 0x86,

+ 0x4B, 0xEC, 0xA5, 0xAB, 0x23, 0xB2, 0x2A, 0x6B, 0xBD, 0xA8, 0x72, 0xA5,

+ 0xC2, 0x60, 0x96, 0x5F, 0xD0, 0x86, 0x39, 0x7A, 0xCE, 0xAA, 0x3F, 0xA2,

+ 0x22, 0xB3, 0xB9, 0xBB, 0x9B, 0x2A, 0xD2, 0xB0, 0x96, 0xA3, 0xC1, 0x86,

+ 0x2A, 0xDC, 0xA5, 0xA3, 0x32, 0xDC, 0xAA, 0xA3, 0xAB, 0xBC, 0x6C, 0x35,

+ 0xBA, 0x50, 0x96, 0x1D, 0x01, 0x86, 0x4A, 0xDC, 0xB5, 0xAA, 0x23, 0xBC,

+ 0x32, 0xAC, 0xAA, 0x4B, 0xEE, 0xA4, 0xDA, 0x50, 0x96, 0x2D, 0x01, 0x86,

+ 0xAA, 0xDA, 0xA5, 0xB5, 0x2B, 0xEC, 0xBB, 0x9A, 0x2A, 0xBA, 0xCC, 0xE4,

+ 0xCC, 0x50, 0x96, 0x2D, 0x01, 0x86, 0x2A, 0xDC, 0xA6, 0x22, 0x24, 0xA4,

+ 0xAD, 0x93, 0xB9, 0xA2, 0xB2, 0xA4, 0xAA, 0x50, 0x96, 0x1D, 0x01, 0x86,

+ 0xA3, 0xFD, 0x36, 0x2A, 0x1A, 0xA3, 0x2D, 0x93, 0x59, 0xA5, 0xA2, 0xAE,

+ 0x55, 0x50, 0x96, 0x2D, 0x01, 0x86, 0x2B, 0xEA, 0xA7, 0x22, 0x22, 0xA3,

+ 0xB3, 0x9B, 0x29, 0x2A, 0x9A, 0x3C, 0xDA, 0x50, 0x96, 0x2E, 0x01, 0x86,

+ 0xCB, 0xFA, 0xB6, 0x2A, 0x12, 0xA2, 0x7B, 0x92, 0x39, 0x4A, 0x9A, 0x6B,

+ 0xD5, 0x60, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXO LC Filter Switzerland 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_CH[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter China 200R+680R//100nF Coefficients (Voice Applications) */

+const VpProfileDataType AC_FXO_LC_CN[] =

+{

+  /* AC Profile */

+ 0x7C, 0x00, 0xCA, 0xF2, 0x01, 0x4B, 0xCA, 0xFF, 0x98, 0xAD, 0xB3, 0x25,

+ 0xA7, 0xCA, 0xBC, 0xB2, 0x3D, 0xBA, 0xA4, 0x9A, 0x01, 0x90, 0x08, 0x9F,

+ 0x01, 0x8A, 0x5B, 0xC0, 0xAB, 0x10, 0x2B, 0x2C, 0xCC, 0xE8, 0xAB, 0xA0,

+ 0xA4, 0xA9, 0xC2, 0xA3, 0x88, 0x2A, 0x20, 0xB3, 0x39, 0xA3, 0x21, 0x33,

+ 0xFA, 0xB2, 0x24, 0xC2, 0x97, 0x82, 0x42, 0x31, 0x80, 0x2B, 0x60, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0xAB, 0xF2, 0xAD, 0xAA, 0x43, 0xA3, 0x2B, 0xB2,

+ 0xBA, 0x7A, 0xAA, 0xCB, 0x74, 0xC0, 0x96, 0xD3, 0x41, 0x09, 0x12, 0x86,

+ 0xA8, 0xF3, 0x3E, 0x9F, 0xB4, 0xA6, 0xE2, 0x6A, 0xAA, 0x63, 0xAB, 0xBA,

+ 0x23, 0xB0, 0x96, 0xAA, 0x21, 0x86, 0xFB, 0xEB, 0x87, 0x3B, 0x3A, 0xB5,

+ 0x73, 0xBA, 0xBB, 0x23, 0xD2, 0xB7, 0x2A, 0x50, 0x96, 0x3D, 0x01, 0x86,

+ 0xBA, 0xEA, 0x87, 0xBA, 0x3A, 0x2F, 0x3A, 0xA2, 0x3B, 0xDB, 0xCB, 0x9F,

+ 0x22, 0x60, 0x96, 0x1E, 0x01, 0x86, 0xBA, 0xEB, 0x87, 0x3B, 0x34, 0x27,

+ 0xAA, 0xA4, 0xAA, 0xAA, 0xBA, 0x2D, 0xB3, 0x60, 0x96, 0x2E, 0x01, 0x86,

+ 0x22, 0xE2, 0xAF, 0xAB, 0x32, 0xAE, 0x97, 0xAA, 0x5A, 0x2A, 0xAC, 0xAB,

+ 0xC8, 0xF0, 0x96, 0x2E, 0x01, 0x86, 0x2B, 0xD3, 0xAE, 0xAA, 0x3C, 0xCF,

+ 0xB4, 0xAA, 0x2A, 0x2B, 0xA2, 0x3B, 0x3B, 0xB0, 0x96, 0xAB, 0x41, 0x86,

+ 0x23, 0xEA, 0x4F, 0xAA, 0x3C, 0x9F, 0xA5, 0xA2, 0x3A, 0xBB, 0xAF, 0x2B,

+ 0xAC, 0xB0, 0x96, 0x5D, 0x21, 0x86, 0xAB, 0xF2, 0xAD, 0xAA, 0x43, 0xA3,

+ 0x2B, 0xB2, 0xBA, 0x7A, 0xAA, 0xCB, 0x74, 0xC0, 0x96, 0xD3, 0x41, 0x86,

+ 0xA8, 0xF2, 0xAD, 0xAC, 0xB9, 0xF7, 0xA8, 0xFB, 0xAA, 0xAD, 0xA2, 0xAA,

+ 0x52, 0xC0, 0x96, 0xAB, 0xA1, 0x00

+};

+

+/* AC FXO LC Filter China 600R Normal ABF Coefficients (Modem Applications) */

+const VpProfileDataType AC_FXO_LC_CN2[] =

+{

+  /* AC Profile */

+ 0xF6, 0x00, 0x42, 0xF2, 0x01, 0x4B, 0xCA, 0xFF, 0x98, 0xAA, 0x42, 0x2E,

+ 0xAC, 0xA2, 0xAA, 0xC2, 0x2C, 0x42, 0x33, 0x9A, 0xCA, 0x87, 0x01, 0x6E,

+ 0x01, 0x8A, 0xB3, 0xD0, 0x24, 0x20, 0xAC, 0xA9, 0x32, 0xB3, 0xA2, 0xD5,

+ 0x23, 0xBC, 0x2B, 0x26, 0x88, 0xA4, 0x10, 0xBC, 0x58, 0x3A, 0xA0, 0xEA,

+ 0xB9, 0xAC, 0x23, 0xAC, 0x6D, 0x82, 0x24, 0xA0, 0x80, 0x32, 0x20, 0x50,

+ 0x01, 0x76, 0x20, 0x86, 0xBD, 0xEC, 0xD4, 0x2D, 0x43, 0xC2, 0x3A, 0xDB,

+ 0x3E, 0x32, 0x6E, 0xA6, 0x87, 0x60, 0x96, 0xBD, 0x01, 0x09, 0x12, 0x86,

+ 0xC4, 0xD1, 0xB3, 0x2B, 0x42, 0xB2, 0x3A, 0xA7, 0x3B, 0x3A, 0x5B, 0x97,

+ 0x57, 0x61, 0x96, 0x22, 0xE0, 0x86, 0x34, 0xEB, 0x24, 0x22, 0x4D, 0xC2,

+ 0x33, 0xA4, 0xBA, 0x29, 0xF4, 0x87, 0xB3, 0x61, 0x96, 0x49, 0xE0, 0x86,

+ 0x16, 0xD1, 0xB3, 0xD3, 0x42, 0xE2, 0xD2, 0xAB, 0x2A, 0x3A, 0xC1, 0xCE,

+ 0x30, 0x71, 0x96, 0x13, 0xE0, 0x86, 0x4F, 0xE9, 0xF4, 0x1B, 0x31, 0x42,

+ 0x3A, 0x94, 0x1A, 0x32, 0xC2, 0xBB, 0x17, 0x61, 0x96, 0x32, 0xE0, 0x86,

+ 0x12, 0x71, 0xA7, 0x15, 0x33, 0x22, 0x1B, 0x96, 0xB9, 0x23, 0xF2, 0x5A,

+ 0x51, 0x73, 0x96, 0x1A, 0xE0, 0x86, 0x2D, 0xD4, 0x14, 0x22, 0x44, 0xC2,

+ 0x1C, 0xB1, 0x2B, 0xC4, 0x5B, 0xAF, 0x36, 0x61, 0x96, 0x07, 0xE0, 0x86,

+ 0x12, 0xF1, 0x8B, 0x1B, 0x32, 0x42, 0x23, 0xB1, 0xBA, 0x41, 0xC3, 0xAC,

+ 0x14, 0x61, 0x96, 0x29, 0xE0, 0x86, 0x3C, 0xCC, 0x43, 0x1B, 0x52, 0x42,

+ 0x4A, 0xC2, 0x2A, 0x2C, 0xAB, 0x3A, 0x3A, 0xB2, 0x96, 0x3A, 0x80, 0x86,

+ 0x18, 0x51, 0xE4, 0xB3, 0xF1, 0x23, 0x13, 0xC3, 0xAA, 0x3A, 0xBB, 0x3E,

+ 0x24, 0x61, 0x96, 0x24, 0xE0, 0x00

+};

+

+/* AC FXO LC Filter Germany 220R+820R//115nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_DE[] =

+{

+  /* AC Profile */

+ 0x10, 0x00, 0xB6, 0xF2, 0x01, 0x4B, 0xCA, 0xFD, 0x98, 0xB2, 0x33, 0x2A,

+ 0x97, 0xAA, 0x2C, 0x5A, 0xAC, 0xAA, 0x34, 0x9A, 0x01, 0x90, 0x08, 0x9F,

+ 0x01, 0x8A, 0x3B, 0xC0, 0x22, 0x10, 0xDA, 0xA9, 0x2B, 0xA8, 0x32, 0x21,

+ 0xA2, 0xA9, 0x52, 0xB3, 0x88, 0xE2, 0x50, 0x52, 0x3A, 0x2A, 0x22, 0x22,

+ 0xA3, 0x32, 0xAB, 0x2D, 0xB4, 0x82, 0xC2, 0x31, 0x80, 0xAA, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0xBA, 0xEC, 0x97, 0x2B, 0x34, 0x27, 0x3A, 0xA2,

+ 0xAA, 0xAA, 0xB2, 0xAC, 0x36, 0x60, 0x96, 0x2E, 0x01, 0x09, 0x12, 0x86,

+ 0x23, 0xFA, 0x97, 0xAA, 0x3A, 0x97, 0xAA, 0xAA, 0xAA, 0xF4, 0xBB, 0x2C,

+ 0x2B, 0x60, 0x96, 0x2E, 0x01, 0x86, 0x3A, 0xDA, 0x5F, 0xAA, 0x33, 0xAE,

+ 0xC7, 0xAD, 0x4A, 0xFA, 0xAA, 0xCB, 0x42, 0xC0, 0x96, 0xB4, 0x41, 0x86,

+ 0xBA, 0xDA, 0x3F, 0xAA, 0x3A, 0xAF, 0x98, 0x9A, 0x3A, 0xAA, 0xAA, 0x3B,

+ 0x2B, 0xB0, 0x96, 0xBC, 0x31, 0x86, 0x97, 0xF2, 0xAD, 0xBA, 0x42, 0xA3,

+ 0xCB, 0xB3, 0xCA, 0x2C, 0xA3, 0xAA, 0xD2, 0xB0, 0x96, 0x32, 0xA0, 0x86,

+ 0x3A, 0x6B, 0xA2, 0x2A, 0x02, 0xA4, 0xA3, 0x8A, 0x18, 0x23, 0x8E, 0xB8,

+ 0xBA, 0x80, 0x96, 0xA2, 0xA0, 0x86, 0xE8, 0xF2, 0x2F, 0x2B, 0x44, 0xA3,

+ 0xC6, 0xCA, 0x2B, 0x2E, 0xBA, 0x2C, 0x33, 0x70, 0x96, 0x2E, 0x01, 0x86,

+ 0xF8, 0x72, 0xBE, 0x3C, 0x43, 0xA3, 0x22, 0xC2, 0xAA, 0xA2, 0xB2, 0xAB,

+ 0xA3, 0x70, 0x96, 0x2E, 0x01, 0x86, 0xCC, 0xE2, 0xBD, 0x3A, 0x43, 0x24,

+ 0xBB, 0xBA, 0xBA, 0x4B, 0xA2, 0x2B, 0xA6, 0xB0, 0x96, 0x5D, 0x21, 0x86,

+ 0xBA, 0xEA, 0x87, 0xAB, 0x3C, 0x75, 0x2A, 0xA2, 0xAA, 0x5A, 0xB2, 0xED,

+ 0x52, 0x60, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXO LC Filter Denmark 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_DK[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Spain 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_ES[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Finland 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_FI[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter France 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_FR[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter UK 370R+620R//310nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_GB[] =

+{

+  /* AC Profile */

+ 0xE4, 0x00, 0x71, 0xF2, 0x01, 0x4B, 0xCA, 0xFF, 0x98, 0x23, 0xA2, 0xA4,

+ 0x3E, 0x3C, 0x4B, 0xC2, 0xAB, 0x3C, 0xA3, 0x9A, 0x01, 0x90, 0x08, 0x2E,

+ 0x01, 0x8A, 0xFA, 0xB0, 0xAA, 0x10, 0x2A, 0xAA, 0x3C, 0xA9, 0xA5, 0x2C,

+ 0x2C, 0xA3, 0x33, 0xBC, 0x88, 0xAA, 0xB0, 0x2D, 0xB4, 0xCF, 0xAA, 0xB4,

+ 0x21, 0xAE, 0xB9, 0xB2, 0xC2, 0x82, 0x3B, 0x21, 0x80, 0xAC, 0x20, 0x50,

+ 0x01, 0x76, 0x34, 0x86, 0xBD, 0xFB, 0x37, 0x3E, 0x62, 0xA6, 0x2A, 0xD2,

+ 0xAC, 0x5A, 0xC2, 0xAC, 0xBA, 0x60, 0x96, 0x2E, 0x01, 0x09, 0x12, 0x86,

+ 0xD8, 0x72, 0xAE, 0x23, 0xB3, 0x2C, 0x3A, 0xD2, 0xAA, 0xAA, 0xAB, 0x2B,

+ 0xAA, 0xB0, 0x96, 0x2B, 0x21, 0x86, 0x2A, 0xEA, 0x97, 0xAA, 0x5C, 0xAC,

+ 0x22, 0xCA, 0xCC, 0x6A, 0xCB, 0x2D, 0xA2, 0x70, 0x96, 0x2E, 0x01, 0x86,

+ 0xAA, 0xE7, 0xB7, 0x5A, 0x5C, 0xAB, 0xA3, 0xB2, 0x3C, 0xB2, 0xD4, 0xCD,

+ 0x2C, 0x60, 0x96, 0x2E, 0x01, 0x86, 0x3A, 0xE2, 0x27, 0x22, 0x5C, 0xAB,

+ 0x3A, 0xAA, 0xBB, 0x3B, 0xC3, 0x3D, 0x3B, 0x60, 0x96, 0x2E, 0x01, 0x86,

+ 0xB2, 0xEB, 0xAF, 0x6A, 0x4A, 0xBB, 0xA3, 0xA4, 0xBA, 0xA6, 0xBA, 0x2C,

+ 0x3C, 0xC0, 0x96, 0x3B, 0x41, 0x86, 0xA2, 0xE2, 0xCF, 0x32, 0x5A, 0xAB,

+ 0x25, 0xAA, 0xBA, 0xB2, 0xBA, 0xAB, 0x22, 0xC0, 0x96, 0x5D, 0x21, 0x86,

+ 0xD8, 0x7B, 0x8F, 0xAC, 0x7B, 0xAC, 0x6A, 0xBD, 0x2C, 0xAA, 0xC2, 0x5D,

+ 0x3B, 0x70, 0x96, 0x2E, 0x01, 0x86, 0xAA, 0xED, 0xAD, 0xB9, 0xFB, 0x3D,

+ 0xD3, 0xB2, 0xAA, 0x3D, 0xBD, 0x2C, 0xBD, 0xC0, 0x96, 0xAD, 0x21, 0x86,

+ 0xA8, 0xFA, 0x87, 0x98, 0xA4, 0xCB, 0xB5, 0x5C, 0xAE, 0xA2, 0xC2, 0x3C,

+ 0x4A, 0x60, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXO LC Filter Greece 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_GR[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Hong Kong SAR 600R ABF Coefficients - 4 KHz Return Loss */

+const VpProfileDataType AC_FXO_LC_HK[] =

+{

+  /* AC Profile */

+ 0xD0, 0x00, 0x7E, 0xF2, 0x01, 0x4B, 0xCA, 0x05, 0x98, 0xCD, 0x2C, 0x23,

+ 0xA5, 0x3B, 0xAD, 0x3A, 0xAC, 0xEA, 0x24, 0x9A, 0x01, 0x90, 0x08, 0x2E,

+ 0x01, 0x8A, 0xB3, 0xD0, 0x56, 0x20, 0xA2, 0xA9, 0x25, 0xA3, 0xAE, 0x35,

+ 0x22, 0x6C, 0xA7, 0xA5, 0x88, 0xB4, 0x10, 0x42, 0x58, 0xA2, 0xB0, 0xCA,

+ 0xD9, 0xA2, 0xA2, 0x23, 0xED, 0x82, 0xB3, 0xA0, 0x80, 0x98, 0x10, 0x50,

+ 0x01, 0x76, 0x20, 0x86, 0x23, 0xFB, 0xC7, 0x24, 0x33, 0x23, 0xB2, 0x72,

+ 0xAD, 0xB8, 0x7B, 0xA6, 0xBA, 0x60, 0x96, 0xCC, 0x01, 0x09, 0x12, 0x86,

+ 0xA2, 0x6C, 0x3C, 0x23, 0x36, 0xA8, 0x10, 0x84, 0x08, 0x2D, 0x8C, 0xCA,

+ 0xBD, 0xF0, 0x96, 0x2E, 0x01, 0x86, 0xAA, 0x22, 0x3D, 0x33, 0x5D, 0xA8,

+ 0x00, 0x80, 0x08, 0xDB, 0x1D, 0x10, 0x52, 0x30, 0x96, 0x5B, 0x87, 0x86,

+ 0xB3, 0xCA, 0xA8, 0x20, 0x8B, 0x28, 0xCC, 0xAA, 0x3D, 0xB2, 0x3A, 0xA4,

+ 0xA3, 0xE0, 0x96, 0xBC, 0x01, 0x86, 0xC4, 0xD1, 0xB3, 0x2B, 0x42, 0xB2,

+ 0x3A, 0xA7, 0x3B, 0x3A, 0x5B, 0x97, 0x57, 0x61, 0x96, 0x22, 0xE0, 0x86,

+ 0x34, 0xEB, 0x24, 0x22, 0x4D, 0xC2, 0x33, 0xA4, 0xBA, 0x29, 0xF4, 0x87,

+ 0xB3, 0x61, 0x96, 0x49, 0xE0, 0x86, 0x16, 0xD1, 0xB3, 0xD3, 0x42, 0xE2,

+ 0xD2, 0xAB, 0x2A, 0x3A, 0xC1, 0xCE, 0x30, 0x71, 0x96, 0x13, 0xE0, 0x86,

+ 0x4F, 0xE9, 0xF4, 0x1B, 0x31, 0x42, 0x3A, 0x94, 0x1A, 0x32, 0xC2, 0xBB,

+ 0x17, 0x61, 0x96, 0x32, 0xE0, 0x86, 0x3C, 0xCC, 0x43, 0x1B, 0x52, 0x42,

+ 0x4A, 0xC2, 0x2A, 0x2C, 0xAB, 0x3A, 0x3A, 0xB2, 0x96, 0x3A, 0x80, 0x86,

+ 0x18, 0x51, 0xE4, 0xB3, 0xF1, 0x23, 0x13, 0xC3, 0xAA, 0x3A, 0xBB, 0x3E,

+ 0x24, 0x61, 0x96, 0x24, 0xE0, 0x00

+};

+

+/* AC FXO LC Filter Hungary 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_HU[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Ireland 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_IE[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Israel 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_IL[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Iceland 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_IS[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Italy 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_IT[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Japan 600R Lowest ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_JP[] =

+{

+  /* AC Profile */

+ 0xF6, 0x00, 0x42, 0xF2, 0x01, 0x4B, 0xCA, 0xFF, 0x98, 0xAA, 0x42, 0x2E,

+ 0xAC, 0xA2, 0xAA, 0xC2, 0x2C, 0x42, 0x33, 0x9A, 0xCA, 0x87, 0x01, 0x6E,

+ 0x01, 0x8A, 0xB3, 0xD0, 0x24, 0x20, 0xAC, 0xA9, 0x32, 0xB3, 0xA2, 0xD5,

+ 0x23, 0xBC, 0x2B, 0x26, 0x88, 0xA4, 0x10, 0xBC, 0x58, 0x3A, 0xA0, 0xEA,

+ 0xB9, 0xAC, 0x23, 0xAC, 0x6D, 0x82, 0x24, 0xA0, 0x80, 0x32, 0x20, 0x50,

+ 0x01, 0x76, 0x60, 0x86, 0xBD, 0xEC, 0xD4, 0x2D, 0x43, 0xC2, 0x3A, 0xDB,

+ 0x3E, 0x32, 0x6E, 0xA6, 0x87, 0x60, 0x96, 0xBD, 0x01, 0x09, 0x12, 0x86,

+ 0xC4, 0xD1, 0xB3, 0x2B, 0x42, 0xB2, 0x3A, 0xA7, 0x3B, 0x3A, 0x5B, 0x97,

+ 0x57, 0x61, 0x96, 0x22, 0xE0, 0x86, 0x34, 0xEB, 0x24, 0x22, 0x4D, 0xC2,

+ 0x33, 0xA4, 0xBA, 0x29, 0xF4, 0x87, 0xB3, 0x61, 0x96, 0x49, 0xE0, 0x86,

+ 0x16, 0xD1, 0xB3, 0xD3, 0x42, 0xE2, 0xD2, 0xAB, 0x2A, 0x3A, 0xC1, 0xCE,

+ 0x30, 0x71, 0x96, 0x13, 0xE0, 0x86, 0x4F, 0xE9, 0xF4, 0x1B, 0x31, 0x42,

+ 0x3A, 0x94, 0x1A, 0x32, 0xC2, 0xBB, 0x17, 0x61, 0x96, 0x32, 0xE0, 0x86,

+ 0x12, 0x71, 0xA7, 0x15, 0x33, 0x22, 0x1B, 0x96, 0xB9, 0x23, 0xF2, 0x5A,

+ 0x51, 0x73, 0x96, 0x1A, 0xE0, 0x86, 0x2D, 0xD4, 0x14, 0x22, 0x44, 0xC2,

+ 0x1C, 0xB1, 0x2B, 0xC4, 0x5B, 0xAF, 0x36, 0x61, 0x96, 0x07, 0xE0, 0x86,

+ 0x12, 0xF1, 0x8B, 0x1B, 0x32, 0x42, 0x23, 0xB1, 0xBA, 0x41, 0xC3, 0xAC,

+ 0x14, 0x61, 0x96, 0x29, 0xE0, 0x86, 0x3C, 0xCC, 0x43, 0x1B, 0x52, 0x42,

+ 0x4A, 0xC2, 0x2A, 0x2C, 0xAB, 0x3A, 0x3A, 0xB2, 0x96, 0x3A, 0x80, 0x86,

+ 0x18, 0x51, 0xE4, 0xB3, 0xF1, 0x23, 0x13, 0xC3, 0xAA, 0x3A, 0xBB, 0x3E,

+ 0x24, 0x61, 0x96, 0x24, 0xE0, 0x00

+};

+

+/* AC FXO LC Filter Malaysia 600R Low ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_MY[] =

+{

+  /* AC Profile */

+ 0xF6, 0x00, 0x42, 0xF2, 0x01, 0x4B, 0xCA, 0xFF, 0x98, 0xAA, 0x42, 0x2E,

+ 0xAC, 0xA2, 0xAA, 0xC2, 0x2C, 0x42, 0x33, 0x9A, 0xCA, 0x87, 0x01, 0x6E,

+ 0x01, 0x8A, 0xB3, 0xD0, 0x24, 0x20, 0xAC, 0xA9, 0x32, 0xB3, 0xA2, 0xD5,

+ 0x23, 0xBC, 0x2B, 0x26, 0x88, 0xA4, 0x10, 0xBC, 0x58, 0x3A, 0xA0, 0xEA,

+ 0xB9, 0xAC, 0x23, 0xAC, 0x6D, 0x82, 0x24, 0xA0, 0x80, 0x32, 0x20, 0x50,

+ 0x01, 0x76, 0x40, 0x86, 0xBD, 0xEC, 0xD4, 0x2D, 0x43, 0xC2, 0x3A, 0xDB,

+ 0x3E, 0x32, 0x6E, 0xA6, 0x87, 0x60, 0x96, 0xBD, 0x01, 0x09, 0x12, 0x86,

+ 0xC4, 0xD1, 0xB3, 0x2B, 0x42, 0xB2, 0x3A, 0xA7, 0x3B, 0x3A, 0x5B, 0x97,

+ 0x57, 0x61, 0x96, 0x22, 0xE0, 0x86, 0x34, 0xEB, 0x24, 0x22, 0x4D, 0xC2,

+ 0x33, 0xA4, 0xBA, 0x29, 0xF4, 0x87, 0xB3, 0x61, 0x96, 0x49, 0xE0, 0x86,

+ 0x16, 0xD1, 0xB3, 0xD3, 0x42, 0xE2, 0xD2, 0xAB, 0x2A, 0x3A, 0xC1, 0xCE,

+ 0x30, 0x71, 0x96, 0x13, 0xE0, 0x86, 0x4F, 0xE9, 0xF4, 0x1B, 0x31, 0x42,

+ 0x3A, 0x94, 0x1A, 0x32, 0xC2, 0xBB, 0x17, 0x61, 0x96, 0x32, 0xE0, 0x86,

+ 0x12, 0x71, 0xA7, 0x15, 0x33, 0x22, 0x1B, 0x96, 0xB9, 0x23, 0xF2, 0x5A,

+ 0x51, 0x73, 0x96, 0x1A, 0xE0, 0x86, 0x2D, 0xD4, 0x14, 0x22, 0x44, 0xC2,

+ 0x1C, 0xB1, 0x2B, 0xC4, 0x5B, 0xAF, 0x36, 0x61, 0x96, 0x07, 0xE0, 0x86,

+ 0x12, 0xF1, 0x8B, 0x1B, 0x32, 0x42, 0x23, 0xB1, 0xBA, 0x41, 0xC3, 0xAC,

+ 0x14, 0x61, 0x96, 0x29, 0xE0, 0x86, 0x3C, 0xCC, 0x43, 0x1B, 0x52, 0x42,

+ 0x4A, 0xC2, 0x2A, 0x2C, 0xAB, 0x3A, 0x3A, 0xB2, 0x96, 0x3A, 0x80, 0x86,

+ 0x18, 0x51, 0xE4, 0xB3, 0xF1, 0x23, 0x13, 0xC3, 0xAA, 0x3A, 0xBB, 0x3E,

+ 0x24, 0x61, 0x96, 0x24, 0xE0, 0x00

+};

+

+/* AC FXO LC Filter Netherlands 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_NL[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Norway 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_NO[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter New Zealand 370R+620R//310nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_NZ[] =

+{

+  /* AC Profile */

+ 0x11, 0x00, 0xF1, 0xF2, 0x01, 0x4B, 0xCA, 0x05, 0x98, 0x32, 0x2B, 0x32,

+ 0xA5, 0x2D, 0xA4, 0xFA, 0x27, 0xB4, 0x5D, 0x9A, 0xD3, 0x26, 0x26, 0x2D,

+ 0x01, 0x8A, 0xD3, 0xC0, 0x97, 0x30, 0x2C, 0xA3, 0x32, 0xA8, 0x4A, 0xA2,

+ 0xD3, 0xAC, 0xCB, 0x4E, 0x88, 0xFA, 0x10, 0x2B, 0xA8, 0xAA, 0xA0, 0x32,

+ 0x4B, 0x3A, 0xAC, 0xAA, 0x33, 0x82, 0x23, 0xA0, 0x80, 0xB8, 0xF0, 0x50,

+ 0x01, 0x76, 0x34, 0x86, 0xB5, 0xF2, 0xA6, 0xB2, 0x64, 0x37, 0xBB, 0xDB,

+ 0xAC, 0x2B, 0xCC, 0xAC, 0xFA, 0x70, 0x96, 0x2E, 0x01, 0x09, 0x12, 0x86,

+ 0xD8, 0x72, 0xAE, 0x23, 0xB3, 0x2C, 0x3A, 0xD2, 0xAA, 0xAA, 0xAB, 0x2B,

+ 0xAA, 0xB0, 0x96, 0x2B, 0x21, 0x86, 0x2A, 0xEA, 0x97, 0xAA, 0x5C, 0xAC,

+ 0x22, 0xCA, 0xCC, 0x6A, 0xCB, 0x2D, 0xA2, 0x70, 0x96, 0x2E, 0x01, 0x86,

+ 0xAA, 0xE7, 0xB7, 0x5A, 0x5C, 0xAB, 0xA3, 0xB2, 0x3C, 0xB2, 0xD4, 0xCD,

+ 0x2C, 0x60, 0x96, 0x2E, 0x01, 0x86, 0x3A, 0xE2, 0x27, 0x22, 0x5C, 0xAB,

+ 0x3A, 0xAA, 0xBB, 0x3B, 0xC3, 0x3D, 0x3B, 0x60, 0x96, 0x2E, 0x01, 0x86,

+ 0xB2, 0xEB, 0xAF, 0x6A, 0x4A, 0xBB, 0xA3, 0xA4, 0xBA, 0xA6, 0xBA, 0x2C,

+ 0x3C, 0xC0, 0x96, 0x3B, 0x41, 0x86, 0xA2, 0xE2, 0xCF, 0x32, 0x5A, 0xAB,

+ 0x25, 0xAA, 0xBA, 0xB2, 0xBA, 0xAB, 0x22, 0xC0, 0x96, 0x5D, 0x21, 0x86,

+ 0xD8, 0x7B, 0x8F, 0xAC, 0x7B, 0xAC, 0x6A, 0xBD, 0x2C, 0xAA, 0xC2, 0x5D,

+ 0x3B, 0x70, 0x96, 0x2E, 0x01, 0x86, 0xAA, 0xED, 0xAD, 0xB9, 0xFB, 0x3D,

+ 0xD3, 0xB2, 0xAA, 0x3D, 0xBD, 0x2C, 0xBD, 0xC0, 0x96, 0xAD, 0x21, 0x86,

+ 0xA8, 0xFA, 0x87, 0x98, 0xA4, 0xCB, 0xB5, 0x5C, 0xAE, 0xA2, 0xC2, 0x3C,

+ 0x4A, 0x60, 0x96, 0x2E, 0x01, 0x00

+};

+

+/* AC FXO LC Filter Portugal 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_PT[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Sweden 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_SE[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Turkey 270R+750R//150nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_TK[] =

+{

+  /* AC Profile */

+ 0x3B, 0x00, 0xC2, 0xF2, 0x01, 0x4B, 0xCA, 0x00, 0x98, 0x2B, 0x45, 0x42,

+ 0xBF, 0xAB, 0x3D, 0x42, 0xAD, 0xBA, 0x25, 0x9A, 0xDC, 0x87, 0x01, 0x9F,

+ 0x01, 0x8A, 0xF3, 0xD0, 0xA2, 0x10, 0x2C, 0x2A, 0xBB, 0xA8, 0xA9, 0xF1,

+ 0xBB, 0xBA, 0xCA, 0xA4, 0x88, 0x3B, 0x30, 0x2A, 0xC9, 0xAC, 0x41, 0xBA,

+ 0x2C, 0xBA, 0xBD, 0x32, 0xC4, 0x82, 0x22, 0x31, 0x80, 0x4C, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0x44, 0xC2, 0xE2, 0xD6, 0xA2, 0x22, 0xB2, 0x5B,

+ 0x39, 0x3A, 0x1C, 0xBA, 0xAC, 0x50, 0x96, 0x9F, 0x01, 0x09, 0x12, 0x86,

+ 0xBC, 0xB1, 0xB1, 0x3F, 0x93, 0x12, 0x2B, 0x32, 0xC8, 0x32, 0x14, 0x1A,

+ 0x3C, 0x53, 0x96, 0x09, 0x60, 0x86, 0x12, 0xB2, 0x31, 0x4A, 0x82, 0x51,

+ 0x2B, 0x22, 0x28, 0x4C, 0x0B, 0x39, 0x4B, 0x53, 0x96, 0x09, 0x60, 0x86,

+ 0x43, 0xA1, 0xC0, 0xB2, 0x84, 0x11, 0x1B, 0x1F, 0x08, 0xC1, 0x03, 0xB8,

+ 0x20, 0x70, 0x96, 0xA9, 0xE0, 0x86, 0x35, 0xB6, 0xB2, 0x22, 0xC3, 0x17,

+ 0x42, 0xBC, 0x2A, 0x23, 0xA2, 0x0E, 0x23, 0xB4, 0x96, 0x39, 0x80, 0x86,

+ 0x61, 0xBC, 0x21, 0x5B, 0x83, 0x21, 0x3A, 0x12, 0x28, 0xD7, 0x0B, 0x29,

+ 0x32, 0x63, 0x96, 0xA9, 0xE0, 0x86, 0xBC, 0xB1, 0xB2, 0xB3, 0xBB, 0x63,

+ 0x41, 0xD6, 0x1B, 0x42, 0xA1, 0x97, 0x53, 0xBB, 0x96, 0x49, 0x80, 0x86,

+ 0x35, 0xBC, 0xB2, 0x52, 0xBC, 0x73, 0x2B, 0xC1, 0xBA, 0x3A, 0x94, 0x87,

+ 0x32, 0xB3, 0x96, 0x39, 0x80, 0x86, 0x18, 0x22, 0xB2, 0x13, 0xB2, 0x43,

+ 0x53, 0xC1, 0x2B, 0x41, 0xA3, 0xAE, 0x12, 0xBD, 0x96, 0x41, 0xA0, 0x86,

+ 0xCE, 0xB1, 0xB2, 0x17, 0xB1, 0xB3, 0xC2, 0xD1, 0xBA, 0x41, 0xA1, 0x2D,

+ 0x61, 0xB2, 0x96, 0xC2, 0xA0, 0x00

+};

+

+/* AC FXO LC Filter Taiwan 600R Low ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_TW[] =

+{

+  /* AC Profile */

+ 0xF6, 0x00, 0x42, 0xF2, 0x01, 0x4B, 0xCA, 0xFF, 0x98, 0xAA, 0x42, 0x2E,

+ 0xAC, 0xA2, 0xAA, 0xC2, 0x2C, 0x42, 0x33, 0x9A, 0xCA, 0x87, 0x01, 0x6E,

+ 0x01, 0x8A, 0xB3, 0xD0, 0x24, 0x20, 0xAC, 0xA9, 0x32, 0xB3, 0xA2, 0xD5,

+ 0x23, 0xBC, 0x2B, 0x26, 0x88, 0xA4, 0x10, 0xBC, 0x58, 0x3A, 0xA0, 0xEA,

+ 0xB9, 0xAC, 0x23, 0xAC, 0x6D, 0x82, 0x24, 0xA0, 0x80, 0x32, 0x20, 0x50,

+ 0x01, 0x76, 0x40, 0x86, 0xBD, 0xEC, 0xD4, 0x2D, 0x43, 0xC2, 0x3A, 0xDB,

+ 0x3E, 0x32, 0x6E, 0xA6, 0x87, 0x60, 0x96, 0xBD, 0x01, 0x09, 0x12, 0x86,

+ 0xC4, 0xD1, 0xB3, 0x2B, 0x42, 0xB2, 0x3A, 0xA7, 0x3B, 0x3A, 0x5B, 0x97,

+ 0x57, 0x61, 0x96, 0x22, 0xE0, 0x86, 0x34, 0xEB, 0x24, 0x22, 0x4D, 0xC2,

+ 0x33, 0xA4, 0xBA, 0x29, 0xF4, 0x87, 0xB3, 0x61, 0x96, 0x49, 0xE0, 0x86,

+ 0x16, 0xD1, 0xB3, 0xD3, 0x42, 0xE2, 0xD2, 0xAB, 0x2A, 0x3A, 0xC1, 0xCE,

+ 0x30, 0x71, 0x96, 0x13, 0xE0, 0x86, 0x4F, 0xE9, 0xF4, 0x1B, 0x31, 0x42,

+ 0x3A, 0x94, 0x1A, 0x32, 0xC2, 0xBB, 0x17, 0x61, 0x96, 0x32, 0xE0, 0x86,

+ 0x12, 0x71, 0xA7, 0x15, 0x33, 0x22, 0x1B, 0x96, 0xB9, 0x23, 0xF2, 0x5A,

+ 0x51, 0x73, 0x96, 0x1A, 0xE0, 0x86, 0x2D, 0xD4, 0x14, 0x22, 0x44, 0xC2,

+ 0x1C, 0xB1, 0x2B, 0xC4, 0x5B, 0xAF, 0x36, 0x61, 0x96, 0x07, 0xE0, 0x86,

+ 0x12, 0xF1, 0x8B, 0x1B, 0x32, 0x42, 0x23, 0xB1, 0xBA, 0x41, 0xC3, 0xAC,

+ 0x14, 0x61, 0x96, 0x29, 0xE0, 0x86, 0x3C, 0xCC, 0x43, 0x1B, 0x52, 0x42,

+ 0x4A, 0xC2, 0x2A, 0x2C, 0xAB, 0x3A, 0x3A, 0xB2, 0x96, 0x3A, 0x80, 0x86,

+ 0x18, 0x51, 0xE4, 0xB3, 0xF1, 0x23, 0x13, 0xC3, 0xAA, 0x3A, 0xBB, 0x3E,

+ 0x24, 0x61, 0x96, 0x24, 0xE0, 0x00

+};

+

+/* AC FXO LC Filter South Africa 220R+820R//115nF Normal ABF Coefficients */

+const VpProfileDataType AC_FXO_LC_ZA[] =

+{

+  /* AC Profile */

+ 0x10, 0x00, 0xB6, 0xF2, 0x01, 0x4B, 0xCA, 0xFD, 0x98, 0xB2, 0x33, 0x2A,

+ 0x97, 0xAA, 0x2C, 0x5A, 0xAC, 0xAA, 0x34, 0x9A, 0x01, 0x90, 0x08, 0x9F,

+ 0x01, 0x8A, 0x3B, 0xC0, 0x22, 0x10, 0xDA, 0xA9, 0x2B, 0xA8, 0x32, 0x21,

+ 0xA2, 0xA9, 0x52, 0xB3, 0x88, 0xE2, 0x50, 0x52, 0x3A, 0x2A, 0x22, 0x22,

+ 0xA3, 0x32, 0xAB, 0x2D, 0xB4, 0x82, 0xC2, 0x31, 0x80, 0xAA, 0x50, 0x50,

+ 0x01, 0x76, 0x30, 0x86, 0xBA, 0xEC, 0x97, 0x2B, 0x34, 0x27, 0x3A, 0xA2,

+ 0xAA, 0xAA, 0xB2, 0xAC, 0x36, 0x60, 0x96, 0x2E, 0x01, 0x09, 0x12, 0x86,

+ 0x23, 0xFA, 0x97, 0xAA, 0x3A, 0x97, 0xAA, 0xAA, 0xAA, 0xF4, 0xBB, 0x2C,

+ 0x2B, 0x60, 0x96, 0x2E, 0x01, 0x86, 0x3A, 0xDA, 0x5F, 0xAA, 0x33, 0xAE,

+ 0xC7, 0xAD, 0x4A, 0xFA, 0xAA, 0xCB, 0x42, 0xC0, 0x96, 0xB4, 0x41, 0x86,

+ 0xBA, 0xDA, 0x3F, 0xAA, 0x3A, 0xAF, 0x98, 0x9A, 0x3A, 0xAA, 0xAA, 0x3B,

+ 0x2B, 0xB0, 0x96, 0xBC, 0x31, 0x86, 0x97, 0xF2, 0xAD, 0xBA, 0x42, 0xA3,

+ 0xCB, 0xB3, 0xCA, 0x2C, 0xA3, 0xAA, 0xD2, 0xB0, 0x96, 0x32, 0xA0, 0x86,

+ 0x3A, 0x6B, 0xA2, 0x2A, 0x02, 0xA4, 0xA3, 0x8A, 0x18, 0x23, 0x8E, 0xB8,

+ 0xBA, 0x80, 0x96, 0xA2, 0xA0, 0x86, 0xE8, 0xF2, 0x2F, 0x2B, 0x44, 0xA3,

+ 0xC6, 0xCA, 0x2B, 0x2E, 0xBA, 0x2C, 0x33, 0x70, 0x96, 0x2E, 0x01, 0x86,

+ 0xF8, 0x72, 0xBE, 0x3C, 0x43, 0xA3, 0x22, 0xC2, 0xAA, 0xA2, 0xB2, 0xAB,

+ 0xA3, 0x70, 0x96, 0x2E, 0x01, 0x86, 0xCC, 0xE2, 0xBD, 0x3A, 0x43, 0x24,

+ 0xBB, 0xBA, 0xBA, 0x4B, 0xA2, 0x2B, 0xA6, 0xB0, 0x96, 0x5D, 0x21, 0x86,

+ 0xBA, 0xEA, 0x87, 0xAB, 0x3C, 0x75, 0x2A, 0xA2, 0xAA, 0x5A, 0xB2, 0xED,

+ 0x52, 0x60, 0x96, 0x2E, 0x01, 0x00

+};

+

+/************** DC_Parameters **************/

+

+/* DC FXS Default -- Use for for all countries unless country file exists */

+const VpProfileDataType DC_FXS_VE890_BB100V_DEF[] =

+{

+ /* DC Profile */

+ 0x00, 0x01, 0x00, 0x09, 0x02, 0x03, /* Header Information */

+ 0xC6, 0x13, 0xC4, /* Feed Parameters */

+ 0x18, 0x84, /* Loop Supervision Parameters */

+ 0x04, /* Min Floor Voltage 25V */

+ 0x00  /* Hook Threshold Hysteresis */

+};

+

+/************** Ring_Parameters **************/

+

+/* Default Ringing 25 Hz 50 Vrms - Use for all countries unless country file exists */

+const VpProfileDataType RING_25HZ_VE890_BB100V_DEF[] =

+{

+  /* Sine, 25 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x44,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* Austria Ringing 50 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_AT[] =

+{

+  /* Sine, 50 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x89,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* Canada Ringing 20 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_CA[] =

+{

+  /* Sine, 20 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x37,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* Finland Ringing 50 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_FI[] =

+{

+  /* Sine, 50 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x89,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* France Ringing 50 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_FR[] =

+{

+  /* Sine, 50 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x89,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* Hong Kong SAR Ringing 20 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_HK[] =

+{

+  /* Sine, 20 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x37,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* Japan Ringing 16 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_JP[] =

+{

+  /* Sine, 16 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x2C,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* S. Korea Ringing 20 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_KR[] =

+{

+  /* Sine, 20 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x37,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* Singapore Ringing 24 Hz 50 Vrms  */

+const VpProfileDataType RING_VE890_BB100V_SG[] =

+{

+  /* Sine, 24 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x42,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* Taiwan Ringing 20 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_TW[] =

+{

+  /* Sine, 20 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x37,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/* USA Ringing 20 Hz 50 Vrms */

+const VpProfileDataType RING_VE890_BB100V_US[] =

+{

+  /* Sine, 20 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */

+  /* Ringing Profile */

+ 0x00, 0x04, 0x00, 0x12, 0x01, 0x0C, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x37,

+ 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00,

+ 0xB0, 0x02,  /* Ring Trip Threshold (24mA) and Current Limit (54mA)*/

+ 0x0D, /* Max Supply Ringing Voltage 70V */

+ 0x02  /* Ringing Tracking Mode */

+};

+

+/************** Call_Progress_Tones **************/

+

+/************** Cadence_Definitions **************/

+

+/************** Caller_ID **************/

+

+/************** FXO_Dialing_Profile **************/

+

+/* Default FXO/Dialing */

+const VpProfileDataType FXO_DIALING_DEF[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x8F, 0x1B, /* Device Ring Period Max (71mS), Min (13mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x47, /* Ring Period Max (71mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* ETSI ES203 021 FXO/Dialing */

+const VpProfileDataType FXO_DIALING_ETSI[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x24, /* Device Ring Period Max (45mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Argentina FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_AR[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x78, /* Flash Hook Timing (600mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0x8C, /* Interdigit Min (700mS) */

+ 0x7E, 0x24, /* Device Ring Period Max (63mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x3E, /* Ring Period Max (62mS) */

+ 0x2A, 0x30, 0x21, 0x83  /* DTMF High/Low Freq Level (-6.5dBm0/-8.5dBm0) */

+};

+

+/* Austria FXO/Dialing */

+const VpProfileDataType FXO_DIALING_AT[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Australia FXO/Dialing */

+const VpProfileDataType FXO_DIALING_AU[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x86, 0x27, /* Device Ring Period Max (67mS), Min (19mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x42, /* Ring Period Max (66mS) */

+ 0x1C, 0x32, 0x16, 0x65  /* DTMF High/Low Freq Level (-10.0dBm0/-12.0dBm0) */

+};

+

+/* Belgium FXO/Dialing */

+const VpProfileDataType FXO_DIALING_BE[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x24, /* Device Ring Period Max (45mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Bulgaria FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_BG[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Brazil FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_BR[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x78, /* Flash Hook Timing (600mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x76, 0x24, /* Device Ring Period Max (59mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x3A, /* Ring Period Max (58mS) */

+ 0x23, 0x7F, 0x1C, 0x32  /* DTMF High/Low Freq Level (-8.0dBm0/-10.0dBm0) */

+};

+

+/* Canada FXO/Dialing */

+const VpProfileDataType FXO_DIALING_CA[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x78, /* Flash Hook Timing (600mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x86, 0x1B, /* Device Ring Period Max (67mS), Min (13mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x42, /* Ring Period Max (66mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Switzerland FXO/Dialing */

+const VpProfileDataType FXO_DIALING_CH[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Chile FXO/Dialing */

+const VpProfileDataType FXO_DIALING_CL[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x28, /* Flash Hook Timing (200mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* China FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_CN[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x5A, /* Flash Hook Timing (450mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x86, 0x1C, /* Device Ring Period Max (67mS), Min (14mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x42, /* Ring Period Max (66mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Czech Republic FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_CZ[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Germany FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_DE[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x24, /* Device Ring Period Max (45mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Denmark FXO/Dialing */

+const VpProfileDataType FXO_DIALING_DK[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Ecuador FXO/Dialing */

+const VpProfileDataType FXO_DIALING_EC[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Spain FXO/Dialing */

+const VpProfileDataType FXO_DIALING_ES[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x65, 0x41, /* Device Ring Period Max (50mS), Min (32mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x32, /* Ring Period Max (50mS) */

+ 0x27, 0xD4, 0x1F, 0xA3  /* DTMF High/Low Freq Level (-7.0dBm0/-9.0dBm0) */

+};

+

+/* Finland FXO/Dialing */

+const VpProfileDataType FXO_DIALING_FI[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* France FXO/Dialing */

+const VpProfileDataType FXO_DIALING_FR[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x24, /* Device Ring Period Max (45mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* UK FXO/Dialing */

+const VpProfileDataType FXO_DIALING_GB[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x0F, /* Flash Hook Timing (75mS) */

+ 0x0D, 0x06, /* Pulse Break (67mS), Pulse Make (33ms) */

+ 0x00, 0x78, /* Interdigit Min (600mS) */

+ 0x76, 0x24, /* Device Ring Period Max (59mS), Min (18mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x3A, /* Ring Period Max (58mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Greece FXO/Dialing */

+const VpProfileDataType FXO_DIALING_GR[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Hong Kong SAR FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_HK[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x64, /* Flash Hook Timing (500mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x70, 0x41, /* Device Ring Period Max (56mS), Min (32mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x37, /* Ring Period Max (55mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Hungary FXO/Dialing */

+const VpProfileDataType FXO_DIALING_HU[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Indonesia FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_ID[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Ireland FXO/Dialing */

+const VpProfileDataType FXO_DIALING_IE[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x1E, /* Flash Hook Timing (150mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Israel FXO/Dialing */

+const VpProfileDataType FXO_DIALING_IL[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x78, /* Flash Hook Timing (600mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x57, 0x23, /* Device Ring Period Max (43mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2B, /* Ring Period Max (43mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* India FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_IN[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x28, /* Flash Hook Timing (200mS) */

+ 0x0D, 0x06, /* Pulse Break (67mS), Pulse Make (33ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x7E, 0x20, /* Device Ring Period Max (63mS), Min (16mS) */

+ 0x02, /* Ring Detect Min (20Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x3E, /* Ring Period Max (62mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Iceland FXO/Dialing */

+const VpProfileDataType FXO_DIALING_IS[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Italy FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_IT[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x10, /* Flash Hook Timing (80mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0x64, /* Interdigit Min (500mS) */

+ 0x7E, 0x1C, /* Device Ring Period Max (63mS), Min (14mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x3E, /* Ring Period Max (62mS) */

+ 0x23, 0x7F, 0x1C, 0x32  /* DTMF High/Low Freq Level (-8.0dBm0/-10.0dBm0) */

+};

+

+/* Japan FXO/Dialing */

+const VpProfileDataType FXO_DIALING_JP[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x78, /* Flash Hook Timing (600mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x9A, 0x24, /* Device Ring Period Max (77mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x4C, /* Ring Period Max (76mS) */

+ 0x23, 0x7F, 0x1C, 0x32  /* DTMF High/Low Freq Level (-8.0dBm0/-10.0dBm0) */

+};

+

+/* S. Korea FXO/Dialing */

+const VpProfileDataType FXO_DIALING_KR[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x78, /* Flash Hook Timing (600mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x86, 0x1C, /* Device Ring Period Max (67mS), Min (14mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x42, /* Ring Period Max (66mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Mexico FXO/Dialing */

+const VpProfileDataType FXO_DIALING_MX[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Malaysia FXO/Dialing */

+const VpProfileDataType FXO_DIALING_MY[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Netherlands FXO/Dialing */

+const VpProfileDataType FXO_DIALING_NL[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x16, /* Flash Hook Timing (110mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Norway FXO/Dialing */

+const VpProfileDataType FXO_DIALING_NO[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* New Zealand FXO/Dialing  */

+const VpProfileDataType FXO_DIALING_NZ[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x82, /* Flash Hook Timing (650mS) */

+ 0x0D, 0x06, /* Pulse Break (67mS), Pulse Make (33ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x86, 0x24, /* Device Ring Period Max (67mS), Min (18mS) */

+ 0x01, /* Ring Detect Min (16Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x42, /* Ring Period Max (66mS) */

+ 0x1F, 0xA3, 0x1C, 0x32  /* DTMF High/Low Freq Level (-9.0dBm0/-10.0dBm0) */

+};

+

+/* Poland FXO/Dialing */

+const VpProfileDataType FXO_DIALING_PL[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Portugal FXO/Dialing */

+const VpProfileDataType FXO_DIALING_PT[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Russia FXO/Dialing */

+const VpProfileDataType FXO_DIALING_RU[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x28, /* Flash Hook Timing (200mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xB4, /* Interdigit Min (900mS) */

+ 0x7E, 0x27, /* Device Ring Period Max (63mS), Min (19mS) */

+ 0x01, /* Ring Detect Min (16Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x3E, /* Ring Period Max (62mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Sweden FXO/Dialing */

+const VpProfileDataType FXO_DIALING_SE[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Singapore FXO/Dialing */

+const VpProfileDataType FXO_DIALING_SG[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x78, /* Flash Hook Timing (600mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x65, 0x24, /* Device Ring Period Max (50mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x32, /* Ring Period Max (50mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Thailand FXO/Dialing */

+const VpProfileDataType FXO_DIALING_TH[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Turkey FXO/Dialing */

+const VpProfileDataType FXO_DIALING_TK[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x14, /* Flash Hook Timing (100mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x5B, 0x23, /* Device Ring Period Max (45mS), Min (17mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x2D, /* Ring Period Max (45mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* Taiwan FXO/Dialing */

+const VpProfileDataType FXO_DIALING_TW[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x64, /* Flash Hook Timing (500mS) */

+ 0x0D, 0x06, /* Pulse Break (67mS), Pulse Make (33ms) */

+ 0x00, 0xA0, /* Interdigit Min (800mS) */

+ 0x76, 0x24, /* Device Ring Period Max (59mS), Min (18mS) */

+ 0x03, /* Ring Detect Min (23Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x3A, /* Ring Period Max (58mS) */

+ 0x2A, 0x30, 0x21, 0x83  /* DTMF High/Low Freq Level (-6.5dBm0/-8.5dBm0) */

+};

+

+/* USA FXO/Dialing */

+const VpProfileDataType FXO_DIALING_US[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x78, /* Flash Hook Timing (600mS) */

+ 0x0C, 0x08, /* Pulse Break (60mS), Pulse Make (40ms) */

+ 0x00, 0xB4, /* Interdigit Min (900mS) */

+ 0x8F, 0x1B, /* Device Ring Period Max (71mS), Min (13mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x47, /* Ring Period Max (71mS) */

+ 0x2C, 0xB0, 0x23, 0x7F  /* DTMF High/Low Freq Level (-6.0dBm0/-8.0dBm0) */

+};

+

+/* South Africa FXO/Dialing */

+const VpProfileDataType FXO_DIALING_ZA[] =

+{

+ /* FXO/Dialing Profile */

+ 0x00, 0xFE, 0x00, 0x16, 0x01, 0x00, /* Header Information */

+ 0x00, 0x14, 0x00, 0x14, /* DTMF On (100mS), DTMF Off (100ms) */

+ 0x00, 0x12, /* Flash Hook Timing (90mS) */

+ 0x0D, 0x07, /* Pulse Break (65mS), Pulse Make (35ms) */

+ 0x00, 0x50, /* Interdigit Min (400mS) */

+ 0x86, 0x27, /* Device Ring Period Max (67mS), Min (19mS) */

+ 0x04, /* Ring Detect Min (26Vrms) */

+ 0x00, /* Disconnect Threshold (2.56V) */

+ 0x02, /* LIU Threshold (20.48V) */

+ 0x42, /* Ring Period Max (66mS) */

+ 0x1F, 0xA3, 0x19, 0x21  /* DTMF High/Low Freq Level (-9.0dBm0/-11.0dBm0) */

+};

+

+int dev_profile_size = sizeof(DEV_PROFILE_VE890_BB100V);

+int dc_profile_size = sizeof(DC_FXS_VE890_BB100V_DEF);

+int ac_profile_size = sizeof(AC_FXS_RF50_600R_DEF);

+int ring_profile_size = sizeof(RING_25HZ_VE890_BB100V_DEF);

+

+/* end of file profile_89116.c */

diff --git a/tools/voice/zarlink/kernel/profile_89116.h b/tools/voice/zarlink/kernel/profile_89116.h
new file mode 100644
index 0000000..7c05e00
--- /dev/null
+++ b/tools/voice/zarlink/kernel/profile_89116.h
@@ -0,0 +1,268 @@
+/*

+ * profile_89116.h --

+ *

+ * This header file exports the Profile data types

+ *

+ * Project Info --

+ *   File:   C:\Microsemi\Profile_Wizard_P2.1.2\890\NewProject116_new.vpw

+ *   Type:   VE890 Configuration for 100V Buck-Boost Power Supply, Lite Narrowband FXS Coefficients, and 8.192MHz PCLK

+ *   Date:   Wednesday, May 02, 2012 12:15:05

+ *   Device: VE890 Le89316

+ *

+ *   This file was generated with Profile Wizard Version: P2.1.2

+ *

+ * Project Comments --

+ *  --------------------------------------------

+ *  Profile Wizard Coefficient Release 2.8 Notes:

+ *  --------------------------------------------

+ *  Added FXS AC Profile for Brazil (900R) and Russia (150R + (510R//47nF))

+ *  Updated FXS AC Profiles for Australia, China, GR-57 (US non-loaded), Japan, New Zealand, and the UK

+ *  --------------------------------------------

+ *  Profile Wizard Coefficient Release 2.7 Notes:

+ *  --------------------------------------------

+ *  Replaced incorrect FXS AC Profiles for GR-57, China, Finland, and Japan

+ *  --------------------------------------------

+ *  Profile Wizard Coefficient Release 2.6 Notes:

+ *  --------------------------------------------

+ *  I. General:

+ *  1. This release adds support for Mexico, Turkey, Thailand, Malaysia, Indonesia, and Ecuador, bringing

+ *  the total number of supported countries to 44.  They are:

+ *  Argentina (AR), Austria (AT), Australia (AU), Belgium (BE), Bulgaria (BG), Brazil (BR), Canada (CA), Switzerland (CH),

+ *  Chile (CL), China (CN), Czech Republic (CZ), Germany (DE), Denmark (DK), Ecuador (EC), Spain (ES), Finland (FI),

+ *  France (FR), UK (GB), Greece (GR), Hong Kong SAR China (HK), Hungary (HU), Indonesia (ID), Ireland (IE), Israel (IL),

+ *  India (IN), Iceland (IS), Italy (IT), Japan (JP), S. Korea (KR), Mexico (MX), Malaysia (MY), Netherlands (NL),

+ *  Norway (NO), New Zealand (NZ), Poland (PL), Portugal (PT), Russian Federation (RU), Sweden (SE), Singapore (SG),

+ *  Thailand (TH), Turkey (TK), Taiwan (TW), USA (US), and South Africa (ZA).

+ *  2. This release also corrects some Caller ID implementations and signal levels that were incorrect in release 2.3.

+ *  3. The coefficients in this and all releases are provided for use only with the Microsemi VoicePath API-II (VP-API-II). 

+ *  Please refer to the terms and conditions for licensing the software regarding terms and conditions of usage. These profiles 

+ *  are provided for reference only with no guarantee whatsoever by Microsemi Corporation.

+ *  4. This release is for the VE8911 chipset and includes coefficients required for FXS and FXO operation.

+ *  

+ *  II. Device Profile:

+ *  1. The default settings for the Device Profile are:

+ *         PCLK = 8192 kHz

+ *         PCM Transmit Edge = Positive

+ *         Transmit Time Slot = 0

+ *         Receive Time Slot = 0

+ *         Interrupt Mode = Open Drain

+ *         Switcher = Buck-Boost

+ *         Driver Tick Rate = 5 ms

+ *         Maximum Events / Tick = 2

+ *  2. The settings may be changed by the user as necessary.  Please refer to the VE890 and API documentation for information about

+ *  the supported settings.

+ *  

+ *  II. AC Profiles:

+ *  1. FXS Coefficients assume -6dBr RX (Output from chipset) and 0dB TX relative gain levels.

+ *  2. Supported countries not individually listed should use the default 600R profile AC_FXS_RF50_600R_DEF.

+ *  4. AC FXS Coefficients assume the use of two 25 ohm series resistors or PTCs. Customers using other PTC resistance values (such as 

+ *  7 ohms or 50 ohms) should not use these AC coefficients and can request alternate ones from Microsemi.

+ *  5. This release includes Normal (or narrowband) coefficients for the FXS port. Wideband coefficients are available upon request.

+ *  6. AC FXO Coefficients assume the use of the LC Filter on VE890 DAA Circuit consisting of CIMM and LIMM as shown

+ *  in the datasheet.

+ *  7. AC FXO Coefficients include the coefficient sets for the VE890 echo free adaptive balance.

+ *  

+ *  III. DC Profile:

+ *  1. The DC_FXS_VE890_BB100V_DEF is the default used for all countries.  Additional profiles may be created by the user if necessary.

+ *  

+ *  IV. Ring Profiles:

+ *  1. RING_25HZ_VE890_BB100V_DEF is the default ringing profile and should be used for all countries which do not have a listed Ringing Profile.  The default

+ *  ringing profile is set for a sine wave ringing with an amplitude of 50 Vrms and a frequency of 25 Hz.

+ *  2. All ringing profiles on the list have a 50 Vrms ringing level. 

+ *  3. DC biasing is set to 0 in the sample ringing profiles.

+ *  

+ *  V. Tone Profiles:

+ *  1. These profiles are available only in the full version of the API.

+ *  2. The shown levels assume a 6dB attenuation in the chipset before being outputed to line.

+ *  3. Call progress tone levels may be arbitrary as they are not always specified in national standards, or the standards may not be available to Microsemi.

+ *  4. ITU-T Recommendation E.180 (03/1998) revised on 02/2003 and ETSI TR 101 041-2 V.1.1.1 (05/1997) were used if national standards were not

+ *  available.

+ *  5. Recommended ETSI ES 201 970 call progress tones are provided for reference.

+ *  6. Modulated tones f1 x f2 are approximated as the sum of f1 + (f1+f2)/2 + (f1-f2)/2.

+ *  7. The data in these profiles may be changed by the user as necessary.

+ *   8. T_CAS_DEF is not a country-specific tone and is used by several national Caller ID profiles.

+ *  

+ *  VI. Cadence Profiles:

+ *  1. These profiles are available only in the full version of the API.

+ *  2.  ITU-T Recommendation E.180 (03/1998) revised on 02/2003 and ETSI TR 101 041-2 V.1.1.1 (05/1997) were used if national standards were not

+ *  available.

+ *  3. Recommended ETSI ES 201 970 call progress cadences are provided for reference.

+ *  4. Some countries support multiple call progress tone cadences.  The ones used are believed to be representative and most common.  The user may

+ *  wish to edit some of the cadence definitions or add additional cadences.

+ *  5. Ringing signal cadences include the alerting signal(s) and necessary delays for Type 1 Caller ID, if it is supported below in the Caller ID Profiles.

+ *  

+ *  VII. Caller ID Profiles:

+ *  1. These profiles are available only in the full version of the API.

+ *  2. The option to calculate the checksum in the API is selected for all countries except Japan, which requires that the CRC checksum be calculated by

+ *  host application.

+ *  

+ *  VIII. FXO/Dialing Profiles:

+ *  1. 44 country-specific profiles are provided.  They take into account such variations in national standards as pulse dialing, DTMF dialing, and line

+ *  event detection parameters.

+ *  2. They may be edited as necessary to meet regulatory requirements.

+ *  3. ETSI 203 021 defaults are also provided for reference.

+ *  

+ *  IX. Metering Profiles:

+ *  1. Not supported by VE890 Series.

+ *  

+ *  (c) Copyright 2011 Microsemi Corporation. All rights reserved.

+ *  

+ *  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

+ */

+

+#ifndef PROFILE_89116_H

+#define PROFILE_89116_H

+

+#ifdef VP_API_TYPES_H

+#include "vp_api_types.h"

+#else

+typedef unsigned char VpProfileDataType;

+#endif

+

+extern int dev_profile_size;

+extern int dc_profile_size;

+extern int ac_profile_size;

+extern int ring_profile_size;

+

+/************** Device_Parameters **************/

+extern const VpProfileDataType DEV_PROFILE_VE890_BB100V[];/* Device Configuration Data - VE890 100V Buck-Boost */

+

+/************** AC_Coefficients **************/

+extern const VpProfileDataType AC_FXS_RF50_600R_DEF[];/* AC FXS RF50 600R Normal Coefficients (Default)  */

+extern const VpProfileDataType AC_FXS_RF50_ETSI[];   /* AC FXS RF50 ETSI ES201 970 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_GR57[];   /* AC FXS RF50 Telcordia GR-57 900R+2.16uF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_AT[];     /* AC FXS RF50 Austria 220R+820R//115nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_AU[];     /* AC FXS RF50 Australia 220R+820R//120nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_BE[];     /* AC FXS RF50 Belgium 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_BG[];     /* AC FXS RF50 Bulgaria 220R+820R//115nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_BR[];     /* AC FXS RF50 Brazil 900R Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_CH[];     /* AC FXS RF50 Switzerland 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_CN[];     /* AC FXS RF50 China 200R+680R//100nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_DE[];     /* AC FXS RF50 Germany 220R+820R//115nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_DK[];     /* AC FXS RF50 Denmark 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_ES[];     /* AC FXS RF50 Spain 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_FI[];     /* AC FXS RF50 Finland 270R+910R//120nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_FR[];     /* AC FXS RF50 France 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_GB[];     /* AC FXS RF50 UK 370R+620R//310nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_GR[];     /* AC FXS RF50 Greece 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_HU[];     /* AC FXS RF50 Hungary 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_IE[];     /* AC FXS RF50 Ireland 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_IL[];     /* AC FXS RF50 Israel 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_IS[];     /* AC FXS RF50 Iceland 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_IT[];     /* AC FXS RF50 Italy 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_JP[];     /* AC FXS RF50 Japan 600R+1uF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_NL[];     /* AC FXS RF50 Netherlands 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_NO[];     /* AC FXS RF50 Norway 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_NZ[];     /* AC FXS RF50 New Zealand 370R+620R//310nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_PT[];     /* AC FXS RF50 Portugal 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_RU[];     /* AC FXS RF50 Russia 150R+510R//47nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_SE[];     /* AC FXS RF50 Sweden 270R+750R//150nF Normal Coefficients */

+extern const VpProfileDataType AC_FXS_RF50_ZA[];     /* AC FXS RF50 South Africa 220R+820R//115nF Normal Coefficients */

+extern const VpProfileDataType AC_FXO_LC_600R_DEF[]; /* AC FXO LC Filter 600R Normal ABF Coefficients (Default) */

+extern const VpProfileDataType AC_FXO_LC_ETSI[];     /* AC FXO LC Filter ETSI ES203 021 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_TBR21_CR[]; /* AC FXO LC Filter TBR21 with Current Limit 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_GR57[];     /* AC FXO LC Filter Telcordia GR-57 600R Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_AT[];       /* AC FXO LC Filter Austria 220R+820R//115nF Normal Coefficients */

+extern const VpProfileDataType AC_FXO_LC_AU[];       /* AC FXO LC Filter Australia 220R+820R//120nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_BE[];       /* AC FXO LC Filter Belgium 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_BG[];       /* AC FXO LC Filter Bulgaria 220R+820R//115nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_BR[];       /* AC FXO LC Filter Brazil 900R Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_CH[];       /* AC FXO LC Filter Switzerland 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_CN[];       /* AC FXO LC Filter China 200R+680R//100nF Coefficients (Voice Applications) */

+extern const VpProfileDataType AC_FXO_LC_CN2[];      /* AC FXO LC Filter China 600R Normal ABF Coefficients (Modem Applications) */

+extern const VpProfileDataType AC_FXO_LC_DE[];       /* AC FXO LC Filter Germany 220R+820R//115nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_DK[];       /* AC FXO LC Filter Denmark 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_ES[];       /* AC FXO LC Filter Spain 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_FI[];       /* AC FXO LC Filter Finland 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_FR[];       /* AC FXO LC Filter France 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_GB[];       /* AC FXO LC Filter UK 370R+620R//310nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_GR[];       /* AC FXO LC Filter Greece 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_HK[];       /* AC FXO LC Filter Hong Kong SAR 600R ABF Coefficients - 4 KHz Return Loss */

+extern const VpProfileDataType AC_FXO_LC_HU[];       /* AC FXO LC Filter Hungary 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_IE[];       /* AC FXO LC Filter Ireland 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_IL[];       /* AC FXO LC Filter Israel 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_IS[];       /* AC FXO LC Filter Iceland 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_IT[];       /* AC FXO LC Filter Italy 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_JP[];       /* AC FXO LC Filter Japan 600R Lowest ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_MY[];       /* AC FXO LC Filter Malaysia 600R Low ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_NL[];       /* AC FXO LC Filter Netherlands 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_NO[];       /* AC FXO LC Filter Norway 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_NZ[];       /* AC FXO LC Filter New Zealand 370R+620R//310nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_PT[];       /* AC FXO LC Filter Portugal 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_SE[];       /* AC FXO LC Filter Sweden 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_TK[];       /* AC FXO LC Filter Turkey 270R+750R//150nF Normal ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_TW[];       /* AC FXO LC Filter Taiwan 600R Low ABF Coefficients */

+extern const VpProfileDataType AC_FXO_LC_ZA[];       /* AC FXO LC Filter South Africa 220R+820R//115nF Normal ABF Coefficients */

+

+/************** DC_Parameters **************/

+extern const VpProfileDataType DC_FXS_VE890_BB100V_DEF[];/* DC FXS Default -- Use for for all countries unless country file exists */

+

+/************** Ring_Parameters **************/

+extern const VpProfileDataType RING_25HZ_VE890_BB100V_DEF[];/* Default Ringing 25 Hz 50 Vrms - Use for all countries unless country file exists */

+extern const VpProfileDataType RING_VE890_BB100V_AT[];/* Austria Ringing 50 Hz 50 Vrms */

+extern const VpProfileDataType RING_VE890_BB100V_CA[];/* Canada Ringing 20 Hz 50 Vrms */

+extern const VpProfileDataType RING_VE890_BB100V_FI[];/* Finland Ringing 50 Hz 50 Vrms */

+extern const VpProfileDataType RING_VE890_BB100V_FR[];/* France Ringing 50 Hz 50 Vrms */

+extern const VpProfileDataType RING_VE890_BB100V_HK[];/* Hong Kong SAR Ringing 20 Hz 50 Vrms */

+extern const VpProfileDataType RING_VE890_BB100V_JP[];/* Japan Ringing 16 Hz 50 Vrms */

+extern const VpProfileDataType RING_VE890_BB100V_KR[];/* S. Korea Ringing 20 Hz 50 Vrms */

+extern const VpProfileDataType RING_VE890_BB100V_SG[];/* Singapore Ringing 24 Hz 50 Vrms  */

+extern const VpProfileDataType RING_VE890_BB100V_TW[];/* Taiwan Ringing 20 Hz 50 Vrms */

+extern const VpProfileDataType RING_VE890_BB100V_US[];/* USA Ringing 20 Hz 50 Vrms */

+

+/************** Call_Progress_Tones **************/

+

+/************** Cadence_Definitions **************/

+

+/************** Caller_ID **************/

+

+/************** FXO_Dialing_Profile **************/

+extern const VpProfileDataType FXO_DIALING_DEF[];    /* Default FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_ETSI[];   /* ETSI ES203 021 FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_AR[];     /* Argentina FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_AT[];     /* Austria FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_AU[];     /* Australia FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_BE[];     /* Belgium FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_BG[];     /* Bulgaria FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_BR[];     /* Brazil FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_CA[];     /* Canada FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_CH[];     /* Switzerland FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_CL[];     /* Chile FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_CN[];     /* China FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_CZ[];     /* Czech Republic FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_DE[];     /* Germany FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_DK[];     /* Denmark FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_EC[];     /* Ecuador FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_ES[];     /* Spain FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_FI[];     /* Finland FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_FR[];     /* France FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_GB[];     /* UK FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_GR[];     /* Greece FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_HK[];     /* Hong Kong SAR FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_HU[];     /* Hungary FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_ID[];     /* Indonesia FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_IE[];     /* Ireland FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_IL[];     /* Israel FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_IN[];     /* India FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_IS[];     /* Iceland FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_IT[];     /* Italy FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_JP[];     /* Japan FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_KR[];     /* S. Korea FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_MX[];     /* Mexico FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_MY[];     /* Malaysia FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_NL[];     /* Netherlands FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_NO[];     /* Norway FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_NZ[];     /* New Zealand FXO/Dialing  */

+extern const VpProfileDataType FXO_DIALING_PL[];     /* Poland FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_PT[];     /* Portugal FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_RU[];     /* Russia FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_SE[];     /* Sweden FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_SG[];     /* Singapore FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_TH[];     /* Thailand FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_TK[];     /* Turkey FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_TW[];     /* Taiwan FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_US[];     /* USA FXO/Dialing */

+extern const VpProfileDataType FXO_DIALING_ZA[];     /* South Africa FXO/Dialing */

+

+#endif /* PROFILE_89116_H */

+

diff --git a/tools/voice/zarlink/kernel/vpapi_lib.c b/tools/voice/zarlink/kernel/vpapi_lib.c
new file mode 100644
index 0000000..8332b2e
--- /dev/null
+++ b/tools/voice/zarlink/kernel/vpapi_lib.c
@@ -0,0 +1,432 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include "vpapi_lib.h"
+
+/* Locals */
+static char dev_name[] = "/dev/vpapi";
+static int dev_fd = 0;
+static char lib_str[] = "[vpapi_lib]:";
+
+int vpapi_open_device(void)
+{
+	int fdflags;
+
+	/* open the device */
+	dev_fd = open(dev_name, O_RDWR); 
+	if (dev_fd <= 0) {
+		printf("Cannot open %s device\n", dev_name);
+		return -1;
+	}
+
+	/* set some flags */
+	fdflags = fcntl(dev_fd, F_GETFL, 0);
+	fdflags |= O_NONBLOCK;
+	fcntl(dev_fd, F_SETFL, fdflags);
+
+	return 0;
+}
+
+int vpapi_close_device(void)
+{
+	if(dev_fd > 0)
+		close(dev_fd);
+
+	return 0;	
+}
+
+VpStatusType vpapi_make_dev_object(VpDeviceType dev_type, VpDeviceIdType dev_id)
+{
+	VpApiModMkDevObjType data;
+
+	data.deviceType = dev_type;
+	data.deviceId = dev_id;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_MK_DEV_OBJ, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_MK_DEV_OBJ) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+VpStatusType vpapi_make_line_object(VpTermType term_type, VpLineIdType line_id)
+{
+	VpApiModMkLnObjType data;
+
+	data.termType = term_type;
+	data.lineId = line_id;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_MK_LN_OBJ, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_MK_LN_OBJ) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+VpStatusType vpapi_map_line_id(VpLineIdType line_id)
+{
+	VpApiModMapLnIdType data;
+
+	data.lineId = line_id;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_MAP_LN_ID, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_MAP_LN_ID) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+VpStatusType vpapi_map_slac_id(VpDeviceIdType dev_id, unsigned char slac_id)
+{
+	VpApiModMapSlacIdType data;
+
+	data.deviceId = dev_id;
+	data.slacId = slac_id;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_MAP_SLAC_ID, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_MAP_SLAC_ID) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+VpStatusType vpapi_free_line_context(VpLineIdType line_id)
+{
+	VpApiModFreeLnCtxType data;
+
+	data.lineId = line_id;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_FREE_LN_CTX, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_FREE_LN_CTX) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+VpStatusType vpapi_init_device(VpDeviceIdType dev_id, VpProfilePtrType dev_profile_ptr,
+				VpProfilePtrType ac_profile_ptr, VpProfilePtrType dc_profile_ptr,
+				VpProfilePtrType ring_profile_ptr, VpProfilePtrType fxo_ac_profile_ptr,
+				VpProfilePtrType fxo_cfg_profile_ptr, vpapi_init_device_params_t *params_ptr)
+{
+	VpApiModInitDeviceType data;
+
+	data.deviceId = dev_id;
+	data.pDevProfile = dev_profile_ptr;
+	data.pAcProfile = ac_profile_ptr;
+	data.pDcProfile = dc_profile_ptr;
+	data.pRingProfile = ring_profile_ptr;
+	data.pFxoAcProfile = fxo_ac_profile_ptr;
+	data.pFxoCfgProfile = fxo_cfg_profile_ptr;
+	data.devProfileSize = params_ptr->dev_size;
+	data.acProfileSize = params_ptr->ac_size;
+	data.dcProfileSize = params_ptr->dc_size;
+	data.ringProfileSize = params_ptr->ring_size;
+	data.fxoAcProfileSize = params_ptr->fxo_ac_size;
+	data.fxoCfgProfileSize = params_ptr->fxo_cfg_size;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_INIT_DEV, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_INIT_DEV) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+VpStatusType vpapi_cal_line(VpLineIdType line_id)
+{
+	VpApiModCalLnType data;
+
+	data.lineId = line_id;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_CAL_LN, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_CAL_LN) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+VpStatusType vpapi_set_line_state(VpLineIdType line_id, VpLineStateType state)
+{
+	VpApiModSetLnStType data;
+
+	data.lineId = line_id;
+	data.state = state;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_SET_LN_ST, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_SET_LN_ST) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+VpStatusType vpapi_set_option(unsigned char line_request, VpLineIdType line_id, 
+				VpDeviceIdType dev_id, VpOptionIdType option, void *value_p)
+{
+	VpApiModSetOptionType data;
+	
+	data.lineRequest = line_request;
+	data.lineId = line_id;
+	data.deviceId = dev_id;
+	data.option = option;
+	data.pValue = value_p;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return VP_STATUS_FAILURE;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_SET_OPTION, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_SET_OPTION) failed\n");
+		return VP_STATUS_FAILURE;
+	}
+
+	return data.status;
+}
+
+bool vpapi_get_event(VpDeviceIdType dev_id, VpEventType *event_p)
+{
+	VpApiModGetEventType data;
+
+	data.deviceId = dev_id;
+	data.pEvent = event_p;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return false;
+	}
+
+	
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_GET_EVENT, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_GET_EVENT) failed\n");
+		return false;
+	}
+
+	return data.newEvent;
+}
+
+int vpapi_check_event(void)
+{
+	fd_set ex_fds;
+	struct timeval timeout = {0, 1};
+	int ret;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return 1;
+	}
+
+	FD_ZERO(&ex_fds);
+	FD_SET(dev_fd, &ex_fds);
+
+	/* Wait for event  */
+	ret = select(dev_fd+1, NULL, NULL, &ex_fds, &timeout);
+
+	if(FD_ISSET(dev_fd, &ex_fds))
+		return 0;
+	else
+		return 1;
+}
+
+int vpapi_battary_on(int vbh, int vbl, int vbp)
+{
+	VpModBatteryOnType data;
+
+	data.vbh = vbh;
+	data.vbl = vbl;
+	data.vbp = vbp;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_BATT_ON, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_BATT_ON) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int vpapi_battery_off(void)
+{
+	VpModBatteryOffType data;
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_BATT_OFF, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_BATT_OFF) failed\n");
+		return -1;
+	}
+
+	return data.status;
+}
+
+int vpapi_slic_reg_read(VpLineIdType line_id, unsigned char cmd, unsigned char cmd_len, unsigned char *buff)
+{
+	VpModRegOpType data;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	data.lineId = line_id;
+	data.cmd = cmd;
+	data.cmdLen = cmd_len;
+
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_REG_READ, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_REG_READ) failed\n");
+		return -1;
+	}
+
+	memcpy(buff, data.buff, cmd_len);
+
+	return 0;
+}
+
+int vpapi_slic_reg_write(VpLineIdType line_id, unsigned char cmd, unsigned char cmd_len, unsigned char *buff)
+{
+	VpModRegOpType data;
+	
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return -1;
+	}
+
+	data.lineId = line_id;
+	data.cmd = cmd;
+	data.cmdLen = cmd_len;
+	memcpy(data.buff, buff, cmd_len);
+
+	if (ioctl(dev_fd, VPAPI_MOD_IOX_REG_WRITE, &data) < 0) {
+		printf("ioctl(VPAPI_MOD_IOX_REG_WRITE) failed\n");
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/tools/voice/zarlink/kernel/vpapi_lib.h b/tools/voice/zarlink/kernel/vpapi_lib.h
new file mode 100644
index 0000000..da4ab0b
--- /dev/null
+++ b/tools/voice/zarlink/kernel/vpapi_lib.h
@@ -0,0 +1,102 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _VPAPI_LIB_H
+#define _VPAPI_LIB_H
+
+#include <stdbool.h>
+#include <slic/vpapi_dev.h>
+
+typedef struct vpapi_init_device_params {
+	unsigned short dev_size;
+	unsigned short ac_size;
+	unsigned short dc_size;
+	unsigned short ring_size;
+	unsigned short fxo_ac_size;
+	unsigned short fxo_cfg_size;
+} vpapi_init_device_params_t;
+
+int vpapi_open_device(void);
+int vpapi_close_device(void);
+int vpapi_check_event(void);
+VpStatusType vpapi_make_dev_object(VpDeviceType dev_type, VpDeviceIdType dev_id);
+VpStatusType vpapi_make_line_object(VpTermType term_type, VpLineIdType line_id);
+VpStatusType vpapi_map_line_id(VpLineIdType line_id);
+VpStatusType vpapi_map_slac_id(VpDeviceIdType dev_id, unsigned char slac_id);
+VpStatusType vpapi_free_line_context(VpLineIdType line_id);
+VpStatusType vpapi_init_device(VpDeviceIdType dev_id, VpProfilePtrType dev_profile_ptr,
+				VpProfilePtrType ac_profile_ptr, VpProfilePtrType dc_profile_ptr,
+				VpProfilePtrType ring_profile_ptr, VpProfilePtrType fxo_ac_profile_ptr,
+				VpProfilePtrType fxo_cfg_profile_ptr, vpapi_init_device_params_t *params_ptr);
+VpStatusType vpapi_cal_line(VpLineIdType line_id);
+VpStatusType vpapi_set_line_state(VpLineIdType line_id, VpLineStateType state);
+VpStatusType vpapi_set_option(unsigned char line_request, VpLineIdType line_id, VpDeviceIdType dev_id,
+				VpOptionIdType option, void *value_p);
+bool vpapi_get_event(VpDeviceIdType dev_id, VpEventType *event_p);
+int vpapi_battary_on(int vbh, int vbl, int vbp);
+int vpapi_battery_off(void);
+int vpapi_slic_reg_read(VpLineIdType line_id, unsigned char cmd, unsigned char cmd_len, unsigned char *buff);
+int vpapi_slic_reg_write(VpLineIdType line_id, unsigned char cmd, unsigned char cmd_len, unsigned char *buff);
+
+#endif /* _VPAPI_LIB_H */
diff --git a/tools/voice/zarlink/user/Makefile b/tools/voice/zarlink/user/Makefile
new file mode 100644
index 0000000..68afba4
--- /dev/null
+++ b/tools/voice/zarlink/user/Makefile
@@ -0,0 +1,105 @@
+# kernel sources 
+srctree  := $(shell /bin/pwd)
+
+ifndef KSRC
+KSRC  := $(srctree)/../../../..
+endif
+
+include $(KSRC)/.config
+
+ifdef CONFIG_CPU_BIG_ENDIAN
+CFLAGS  += -DCONFIG_CPU_BIG_ENDIAN
+endif
+
+CC := $(CROSS_COMPILE)gcc
+LD := $(CROSS_COMPILE)ld
+AR := $(CROSS_COMPILE)ar
+
+ifeq ($(CONFIG_ZARLINK_SLIC_SUPPORT),y)
+TOOL := mv_voice_tool.c
+
+ifeq ($(CONFIG_MV_TDM_USE_DCO),y)
+CFLAGS += -DMV_TDM_USE_DCO
+endif
+
+ifeq ($(CONFIG_ZARLINK_SLIC_VE880),y)
+	LIBS := zarlink_880.a
+	PRE_COMPILED_LIB := zarlink_880.lib
+	ZARLINK_BASE_PATH = api_lib
+	ZARLINK_COMMON_SRC_PATH = $(ZARLINK_BASE_PATH)/common
+	ZARLINK_ARCH_MARVELL_PATH = arch_marvell
+	ZARLINK_VP880API_SRC_PATH = $(ZARLINK_BASE_PATH)/vp880_api
+
+	CFLAGS += -DZARLINK_SLIC_VE880
+	CFLAGS += -I$(ZARLINK_BASE_PATH)/includes \
+			-I$(ZARLINK_ARCH_MARVELL_PATH) \
+			-I$(ZARLINK_BASE_PATH)/vp880_api \
+			-I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone
+
+	TARGETS =  vp_api_common.o vp_api_config.o vp_api_control.o vp_api_cslac_seq.o \
+			vp_api_init.o vp_api_query.o vp_api_test.o vp_debug.o vp880_abs_calibration.o \
+			vp880_calibration_common.o vp880_control_common.o vp880_fxo_control.o vp880_fxs_control.o \
+			vp880_init.o vp880_linestate_control.o vp880_lp_control.o vp880_query.o vp880_seq.o vp880_tracker_calibration.o
+
+	SOURCES =  $(ZARLINK_COMMON_SRC_PATH)/vp_api_common.c $(ZARLINK_COMMON_SRC_PATH)/vp_api_config.c \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_control.c $(ZARLINK_COMMON_SRC_PATH)/vp_api_cslac_seq.c \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_init.c $(ZARLINK_COMMON_SRC_PATH)/vp_api_query.c \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_test.c $(ZARLINK_COMMON_SRC_PATH)/vp_debug.c \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_abs_calibration.c $(ZARLINK_VP880API_SRC_PATH)/vp880_calibration_common.c \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_control_common.c $(ZARLINK_VP880API_SRC_PATH)/vp880_fxo_control.c \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_fxs_control.c $(ZARLINK_VP880API_SRC_PATH)/vp880_init.c \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_linestate_control.c $(ZARLINK_VP880API_SRC_PATH)/vp880_lp_control.c \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_query.c $(ZARLINK_VP880API_SRC_PATH)/vp880_seq.c \
+			$(ZARLINK_VP880API_SRC_PATH)/vp880_tracker_calibration.c
+	
+	ARCHSRC = $(ZARLINK_ARCH_MARVELL_PATH)/sys_service.c $(ZARLINK_ARCH_MARVELL_PATH)/vp_hal.c
+
+	PROFILE = profile_88266.c
+endif
+ifeq ($(CONFIG_ZARLINK_SLIC_VE792),y)
+	LIBS := zarlink_792.a
+	PRE_COMPILED_LIB := zarlink_792.lib
+	ZARLINK_BASE_PATH = vp792_api_lib
+	ZARLINK_COMMON_SRC_PATH = $(ZARLINK_BASE_PATH)/common
+	ZARLINK_ARCH_MARVELL_PATH = arch_marvell
+	ZARLINK_VP792API_SRC_PATH = $(ZARLINK_BASE_PATH)/vp792_api
+
+	CFLAGS += -DZARLINK_SLIC_VE792
+	CFLAGS += -I$(ZARLINK_BASE_PATH)/includes \
+			-I$(ZARLINK_ARCH_MARVELL_PATH) \
+			-I$(ZARLINK_BASE_PATH)/vp792_api \
+			-I$(KSRC)/arch/arm/plat-feroceon/mv_drivers_lsp/mv_phone
+
+	TARGETS = vp_api_config.o vp_api_common.o vp_api_init.o vp_api_query.o vp_api_control.o vp_debug.o \
+			vp792_common.o vp792_config.o vp792_control.o vp792_init.o vp792_query.o vp792_firmware.o
+
+	SOURCES =  $(ZARLINK_COMMON_SRC_PATH)/vp_api_config.c  $(ZARLINK_COMMON_SRC_PATH)/vp_api_common.c \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_init.c  $(ZARLINK_COMMON_SRC_PATH)/vp_api_query.c \
+			$(ZARLINK_COMMON_SRC_PATH)/vp_api_control.c $(ZARLINK_COMMON_SRC_PATH)/vp_debug.c \
+			$(ZARLINK_VP792API_SRC_PATH)/vp792_common.c $(ZARLINK_VP792API_SRC_PATH)/vp792_config.c \
+			$(ZARLINK_VP792API_SRC_PATH)/vp792_control.c $(ZARLINK_VP792API_SRC_PATH)/vp792_init.c \
+			$(ZARLINK_VP792API_SRC_PATH)/vp792_query.c $(ZARLINK_VP792API_SRC_PATH)/vp792_firmware.c
+
+	ARCHSRC = $(ZARLINK_ARCH_MARVELL_PATH)/sys_service.c $(ZARLINK_ARCH_MARVELL_PATH)/vp_hal.c $(ZARLINK_ARCH_MARVELL_PATH)/Le71HP0410G_init.c
+
+ 	PROFILE = profile_79238.c
+endif
+
+all:
+	cp libs/$(PRE_COMPILED_LIB) $(LIBS) 
+ifneq ($(CONFIG_MV_PHONE_USE_SLIC_LIBS),y)
+	rm -f *.o $(LIBS) mv_voice_tool
+	$(CC) $(CFLAGS) -static -c $(SOURCES)
+	$(AR) rcs $(LIBS) $(TARGETS)
+	rm -f *.o 
+endif	
+	$(CC) $(CFLAGS) -static $(ARCHSRC) $(PROFILE) $(TOOL) -L. $(LIBS) -o mv_voice_tool -lrt -lpthread
+
+clean:
+	rm -f *.o $(LIBS) mv_voice_tool
+	@for subdir in $(SUBDIRS); do \
+                (cd $$subdir && $(MAKE) $@) || exit 1; \
+        done
+
+endif #CONFIG_ZARLINK_SLIC_SUPPORT
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp580_api.h b/tools/voice/zarlink/user/api_lib/includes/vp580_api.h
new file mode 100644
index 0000000..249da75
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp580_api.h
@@ -0,0 +1,231 @@
+/** \file vp580_api.h
+ * vp580_api.h
+ *
+ *  Header file that define the Vp580 Device and Line Objects
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9084 $
+ * $LastChangedDate: 2011-11-09 16:54:12 -0600 (Wed, 09 Nov 2011) $
+ */
+
+#ifndef VP580_API_H
+#define VP580_API_H
+
+#include "vp_hal.h"
+#include "vp_CSLAC_types.h"
+
+#define VP580_MAX_MPI_DATA  15   /* Max data from any MPI read command */
+
+#ifndef VP580_UL_SIGREG_LEN
+#define VP580_UL_SIGREG_LEN         0x01
+#endif
+
+#define VP580_INT_SEQ_LEN       22
+#define VP580_MAX_NUM_STATES  10
+
+/**< Required Vp580 Device and Line Objects for user instantiation if a Vp580
+ * device is used
+ */
+
+/**< Structure that defines the Vp580 Device Profile. Current as of the first
+ * Device Profile version (ver 0).
+ */
+typedef struct Vp580DeviceProfileType {
+    uint8  maxNumInterrupts;
+    uint16 pcmClkRate;      /**< Used to verify valid TX/RX Timeslot setting */
+    uint8  mClkMask;
+    uint16 tickRate;        /**< Primary API-II tick for this device */
+    uint8  devCfg1;
+    uint8  debounceReg;
+    uint8  clockSlot;
+} Vp580DeviceProfileType;
+
+/**< Line Status types to minimize code space in line object, compared to each status being
+ * maintined by a uint8 type). These values are used by the line object "status" member.
+ */
+#define VP580_INIT_STATUS       (0x00)
+#define VP580_IS_FXO            (0x01)  /**< Set if the line is configured for FXO */
+
+#define VP580_SLS_CALL_FROM_API (0x02)    /**< Set if Set Line State is called from an intenral
+                                             * API function (e.g., cadence). Used to bypass the
+                                             * "same line state" test (i.e., always make the state
+                                             * change requested, even if it's the same as the
+                                             * current state).
+                                             */
+
+#define VP580_INIT_COMPLETE     (0x04)    /**< Set when InitLine has been completed */
+
+typedef struct Vp580LineObjectType {
+    uint8 channelId;    /**< Channel # for "this" line on the device.  Indexed
+                         * starting at 0, should not exceed the max number of
+                         * lines supported by the device - 1 (max = 2, then
+                         * channelId = {0, 1}
+                         */
+
+    VpTermType termType;    /**< Termination type */
+
+    uint8 status;       /**< Keeps track of several line state/config */
+
+    VpSeqDataType cadence;      /**< Sequencer related information */
+
+    VpDialPulseDetectType dpStruct; /**< Used on FXS lines for detecting pulse
+                                     * digits
+                                     */
+
+    VpDigitGenerationDataType digitGenStruct;   /**< Used on FXO lines for
+                                                 * generating pulse digits
+                                                 */
+
+    VpOptionCodecType codec;    /**< Codec mode used on this line. Maintained in
+                                 * the API-II to reduce MPI activity which is a
+                                 * shared resource and requires CRITICAL code
+                                 * section handling.
+                                 */
+
+    VpOptionEventMaskType lineEventsMask;
+    VpOptionEventMaskType lineEvents;
+
+    VpOptionPulseModeType pulseMode;
+
+    uint8 signalingData;    /**< Holds data for Signaling events on this line */
+    uint16 processData;      /**< Holds data for Process events on this line */
+    uint16 fxoData;         /**< Timestamp of event */
+
+    VpCslacTimerStruct lineTimers; /**< Timers for "this" line */
+
+    VpApiIntLineStateType lineState;    /**< Line state info used for state
+                                         * transition handling and recall
+                                         */
+#ifdef VP_CSLAC_SEQ_EN
+    /**< Array to control internally run sequences */
+    VpProfileDataType intSequence[VP580_INT_SEQ_LEN];
+#endif
+
+    /* Items saved from the Ring Profile: */
+    struct ringParams {
+        int method;
+        uint16 timerMs;
+        int state;
+    } ringParams;
+
+    VpProfilePtrType pRingingCadence;   /**< Currently used ringing cadence on
+                                         * this line
+                                         */
+
+    uint16 lineEventHandle; /**< Line specific event handle information */
+
+    VpOptionRingControlType ringCtrl;
+
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;   /* Defines how the PCM highway is
+                                             * set for "talk" linestates
+                                             */
+
+    /*
+     * NOTE: Do not move the location or name of these members. These may be
+     * used by applications to determine the gain of the GX/GR blocks in the
+     * AC profile. Using return from VpSetRelGain() is not usefull because that
+     * is the register setting. The customer would have to know how to convert
+     * that to linear values, which is not generally documented.
+     */
+    struct Vp580RelGainValues {
+        uint16 gxInt;       /**< Cached GX register, in 2.14 int format */
+        uint16 grInt;       /**< Cached GR register, in 2.14 int format */
+    } gain;
+
+    uint8 lineStateBytes[VP580_MAX_NUM_STATES]; /**< I/O Data bytes to set a
+                                                 * line state
+                                                 */
+    uint16 lineStateExist;  /* Bit map of the line states that are defined */
+
+    bool lineStateInit;         /**< TRUE if line state map is required and
+                                 * initialized for this line
+                                 */
+
+    uint8 detMap;               /**< Map in I/O data for detect bit */
+    uint8 bitMask;      /**< Bits that are used by termination type */
+
+    /* This registers may be used for detector status */
+    uint8 ioDataReg;    /* I/O Data Register for this channel */
+    uint8 ioDirReg;     /* I/O Direction Register for this channel */
+    bool ringingDet;    /**< TRUE when ringing is detected on FXO line */
+
+    uint8 ringDetMin;   /**< Minimum ringing detect period (FXO line) in 500uS
+                         * increments
+                         */
+
+    uint8 ringDetMax;   /**< Maximum ringing detect period (FXO line) in 500uS
+                         * increments
+                         */
+
+    VpLineIdType lineId;	/**< Application provided value for mapping a line to
+                             * a line context
+                             */
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+} Vp580LineObjectType;
+
+/*
+ * IMPORTANT: Make sure to update the "stateInt" member of the device object if
+ * the size of this type changes. There is no instance of this type itself.
+ */
+typedef enum Vp580DeviceStateIntType {
+    VP580_RSVD = 0x0001,            /* Not Used */
+    VP580_FORCE_SIG_READ = 0x0002   /* Set to force a signaling register read */
+} Vp580DeviceStateIntType;
+
+typedef struct Vp580DeviceObjectType {
+    VpDeviceIdType deviceId;    /**< Device chip select ID defined by user */
+    VpDeviceStaticInfoType staticInfo;  /**< Info that will not change during
+                                         * runtime
+                                         */
+    VpDeviceDynamicInfoType dynamicInfo;    /**< Info that will change during
+                                             * runtime
+                                             */
+
+    /**< State of signaling interrupt register */
+    uint8 intReg[VP580_UL_SIGREG_LEN];
+
+    VpCSLACDeviceStatusType status;
+
+    /* stateInt is a bit-mask of Vp580DeviceStateIntType values */
+    uint16 stateInt;
+
+    VpOptionEventMaskType deviceEventsMask;
+    VpOptionEventMaskType deviceEvents;
+
+    VpOptionPulseType pulseSpecs;
+
+    uint16 devTimer[VP_DEV_TIMER_LAST];
+    Vp580DeviceProfileType devProfileData;
+    VpCSLACDeviceProfileTableType devProfileTable;
+    VpCSLACProfileTableEntryType profEntry;
+
+#if !defined(VP_REDUCED_API_IF) || defined(ZARLINK_CFG_INTERNAL)
+    uint8 mpiData[VP580_MAX_MPI_DATA];  /**< Buffer for MPI Low level reads to
+                                         * hold maximum amount of MPI data that
+                                         * is possible
+                                         */
+
+    uint8 mpiLen;       /**< Length of data to be copied into mpiData buffer */
+#endif
+
+    uint16 eventHandle;  /** Application defined event handle */
+    uint16 timeStamp;   /**< Used to track event timing. Increment by ticks */
+    int16 timeRemainder;
+
+    VpGetResultsOptionsType getResultsOption;
+    VpRelGainResultsType relGainResults;
+
+    uint8 rtdReg;       /* Real-Time Data Register for this device */
+    uint8 clkFailReg;   /* Register containing clock fault status */
+
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+} Vp580DeviceObjectType;
+
+#endif  /**< vp580_api.h */
+
+
+
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp790_api.h b/tools/voice/zarlink/user/api_lib/includes/vp790_api.h
new file mode 100644
index 0000000..0c40ed0
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp790_api.h
@@ -0,0 +1,174 @@
+/** \file vp790_api.h
+ * vp790_api.h
+ *
+ *  Header file that defines the Vp790 Device and Line Objects
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9084 $
+ * $LastChangedDate: 2011-11-09 16:54:12 -0600 (Wed, 09 Nov 2011) $
+ */
+
+#ifndef VP790_API_H
+#define VP790_API_H
+
+#include "vp_hal.h"
+#include "vp_CSLAC_types.h"
+
+#define VP790_MAX_MPI_DATA  0x0E    /**< Max data from any MPI read command */
+#define VP790_INT_SEQ_LEN   22
+/*
+ * Required Vp790_ Device and Line Objects for user instantiation if a Vp790
+ * device is used
+ */
+typedef struct Vp790DeviceProfileType {
+    uint8  maxNumInterrupts;
+    uint16 pcmClkRate;
+    uint8  mClkMask;
+    uint8  mClkCorrection;
+    uint16 tickRate;
+    uint8  devCfg1;
+    uint8  clockSlot;
+    uint8  calibrationTime;
+} Vp790DeviceProfileType;
+
+typedef struct Vp790LineObjectType {
+    uint8 channelId;    /**< Channel # associated with "this" line on the
+                         * device
+                         */
+
+    VpTermType termType;    /**< Termination type of this line */
+
+    VpOptionCodecType codec;    /**< Maintains the currently used code mode to
+                                 * reduce MPI activity
+                                 */
+
+    VpOptionLineStateType lineStateBatOption;
+
+#ifdef VP_CSLAC_SEQ_EN
+    uint8 cidEncodeBuff[6]; /**< Encoded CID data from user data */
+    uint8 cidEncodeIndex;   /**< current index into encoded buffer */
+    uint8 cidEncodeSize;    /**< Size of valid CID encoded data */
+
+    VpCallerIdType callerId;    /**< Caller ID related information */
+    VpSeqDataType cadence;      /**< Sequencer related information */
+    VpCidSeqDataType cidSeq;    /**< CID Sequencer related information */
+
+    /**< Array to control internally run sequences */
+    VpProfileDataType intSequence[VP790_INT_SEQ_LEN];
+
+    bool thisFskCid;   /**< TRUE if device tick has not changed since last call
+                        * to FSK CID Generator Function call. Used to prevent
+                        * CID lockup with while() loop to load CID data in the
+                        * device.
+                        */
+#endif
+
+    bool slsCalledFromApi;  /**< TRUE if SetLineState is called by the API */
+
+    VpDialPulseDetectType dpStruct; /**< Dial Pulse Parameters for detecting
+                                     * digits on FXS lines
+                                     */
+
+    VpOptionEventMaskType lineEventsMask;
+    VpOptionEventMaskType lineEvents;
+
+    VpOptionPulseModeType pulseMode;
+
+    uint8 signalingData;    /**< Holds data for Signaling events on this line */
+    uint16 processData;     /**< Holds data for Process events on this line */
+
+    VpCslacTimerStruct lineTimers; /**< Timers for "this" line */
+
+    VpApiIntLineStateType lineState;    /**< Line state info, used for state
+                                         * transition handling.
+                                         */
+
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;   /* Defines how the PCM highway is
+                                             * set for "talk" linestates
+                                             */
+    VpOptionRingControlType ringCtrl;
+
+    VpOptionZeroCrossType zeroCross;    /**< Defines how zero crossing is
+                                         * implemented. The device doesn't really
+                                         * support zero crossing "methods", but
+                                         * storing what the user selected is
+                                         * necessary for Get Option (so the
+                                         * operations of Set/Get can be
+                                         * orthogonal)
+                                         */
+
+    VpVirtualDeviceReg virtualDeviceReg;    /**< Virtual device register to
+                                             * minimize device access
+                                             */
+
+    VpProfilePtrType pRingingCadence;   /**< Currently used ringing cadence on
+                                         * this line
+                                         */
+
+    VpProfilePtrType pCidProfileType1;  /**< Currently used caller ID profile
+                                         * on this line for sequenced cid
+                                         */
+
+    VpProfilePtrType pCidProfileType2;  /**< Currently used caller ID profile
+                                         * on this line for non-sequenced cid
+                                         */
+
+    uint16 lineEventHandle; /**< Line specific event handle information */
+
+    uint16 dtmfDigitSense;          /**< Used to hold the DTMF digit reported
+                                     * with VpDtmfDigitDetected() until the
+                                     * VP_LINE_EVID_DTMF_DIG is generated.
+                                     */
+
+    VpLineIdType lineId;	/**< Application provided value for mapping a line to
+                             * a line context
+                             */
+} Vp790LineObjectType;
+
+typedef struct Vp790DeviceObjectType {
+    VpDeviceIdType deviceId;    /**< Device chip select ID or type defined by
+                                 * user
+                                 */
+
+    VpDeviceStaticInfoType staticInfo;      /**< Info that will not change
+                                             * during runtime
+                                             */
+    VpDeviceDynamicInfoType dynamicInfo;    /**< Info that will change during
+                                             * runtime
+                                             */
+    VpCSLACDeviceStatusType status;
+
+    VpOptionEventMaskType deviceEventsMask;
+    VpOptionEventMaskType deviceEvents;
+
+    VpOptionPulseType pulseSpecs;
+
+    VpOptionCriticalFltType criticalFault;
+
+    uint16 devTimer[VP_DEV_TIMER_LAST];
+    Vp790DeviceProfileType devProfileData;
+    VpCSLACDeviceProfileTableType devProfileTable;
+    VpCSLACProfileTableEntryType profEntry;
+
+#if !defined(VP_REDUCED_API_IF) || defined(ZARLINK_CFG_INTERNAL)
+    uint8 mpiData[VP790_MAX_MPI_DATA];  /**< Buffer for MPI Low level reads to
+                                         * hold maximum amount of MPI data that
+                                         * is possible
+                                         */
+
+    uint8 mpiLen;       /**< Length of data to be copied into mpiData buffer */
+#endif
+
+    uint16 eventHandle; /**< Device level event handle information */
+    uint16 timeStamp;
+    int16 timeRemainder;
+
+    VpGetResultsOptionsType getResultsOption;
+} Vp790DeviceObjectType;
+
+#endif  /* vp790_api.h */
+
+
+
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp880_api.h b/tools/voice/zarlink/user/api_lib/includes/vp880_api.h
new file mode 100644
index 0000000..2d5109b
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp880_api.h
@@ -0,0 +1,1127 @@
+/** \file vp880_api.h
+ * vp880_api.h
+ *
+ *  Header file that define all the commands for the Vp880 device.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9253 $
+ * $LastChangedDate: 2011-12-14 11:08:16 -0600 (Wed, 14 Dec 2011) $
+ */
+
+#ifndef VP880_API_H
+#define VP880_API_H
+
+#include "vp_hal.h"
+#include "vp_CSLAC_types.h"
+#include "vp_api_common.h"
+
+#define VP880_MAX_NUM_CHANNELS   2
+
+#ifdef VP880_INCLUDE_TESTLINE_CODE
+#include "vp_api_test.h"
+  #ifdef VP880_EZ_MPI_PCM_COLLECT
+  #include  "vp_pcm_compute.h"
+  #endif
+#endif
+
+#define VP880_MAX_MPI_DATA  15   /* Max data from any MPI read command */
+#define VP880_INT_SEQ_LEN       22
+
+#ifndef VP880_DC_FEED_LEN
+#define VP880_DC_FEED_LEN    0x02
+#endif
+
+#ifndef VP880_REGULATOR_PARAM_LEN
+#define VP880_REGULATOR_PARAM_LEN   0x03
+#endif
+
+#ifndef VP880_LOOP_SUP_LEN
+#define VP880_LOOP_SUP_LEN      0x04
+#endif
+
+#ifndef VP880_SIGA_PARAMS_LEN
+#define VP880_SIGA_PARAMS_LEN   0x0B
+#endif
+
+#ifndef VP880_UL_SIGREG_LEN
+#define VP880_UL_SIGREG_LEN     0x02
+#endif
+
+#ifndef VP880_B1_FILTER_LEN
+#define VP880_B1_FILTER_LEN     0x0E
+#endif
+
+#ifndef VP880_B2_FILTER_LEN
+#define VP880_B2_FILTER_LEN     0x02
+#endif
+
+#ifndef VP880_ICR1_LEN
+#define VP880_ICR1_LEN      0x04
+#endif
+
+#ifndef VP880_ICR2_LEN
+#define VP880_ICR2_LEN      0x04
+#endif
+
+#ifndef VP880_ICR3_LEN
+#define VP880_ICR3_LEN      0x04
+#endif
+
+#ifndef VP880_ICR4_LEN
+#define VP880_ICR4_LEN      0x04
+#endif
+
+#ifndef VP880_ICR5_LEN
+#define VP880_ICR5_LEN      0x02
+#endif
+
+#ifndef VP880_ICR6_LEN
+#define VP880_ICR6_LEN      0x02
+#endif
+
+#ifndef VP880_ICR6_LEN
+#define VP880_ICR6_LEN      0x02
+#endif
+
+#ifndef VP880_BAT_CALIBRATION_LEN
+#define VP880_BAT_CALIBRATION_LEN 0x02
+#endif
+
+#ifndef VP880_REGULATOR_CTRL_LEN
+#define VP880_REGULATOR_CTRL_LEN    0x01
+#endif
+
+#ifndef VP880_TX_PCM_BUFF_LEN
+#define VP880_TX_PCM_BUFF_LEN 0x0E
+#endif
+
+#ifndef VP880_INT_SWREG_PARAM_LEN
+#define VP880_INT_SWREG_PARAM_LEN   0x06
+#endif
+
+#ifndef VP880_DISN_LEN
+#define VP880_DISN_LEN              0x01
+#endif
+
+#ifndef VP880_VP_GAIN_LEN
+#define VP880_VP_GAIN_LEN           0x01
+#endif
+
+#ifndef VP880_SYS_STATE_LEN
+#define VP880_SYS_STATE_LEN     0x01
+#endif
+
+#ifndef VP880_OP_FUNC_LEN
+#define VP880_OP_FUNC_LEN         0x01
+#endif
+
+#ifndef VP880_OP_COND_LEN
+#define VP880_OP_COND_LEN         0x01
+#endif
+
+#ifndef VP880_CONV_CFG_LEN
+#define VP880_CONV_CFG_LEN      0x01
+#endif
+
+#ifndef VP880_DEV_MODE_LEN
+#define VP880_DEV_MODE_LEN  0x01
+#endif
+
+#ifndef VP880_GEN_CTRL_LEN
+#define VP880_GEN_CTRL_LEN  0x01
+#endif
+
+#ifndef VP880_CID_PARAM_LEN
+#define VP880_CID_PARAM_LEN 0x01
+#endif
+
+
+/**< Required Vp880 Device and Line Objects for user instantiation if a Vp880 device is used */
+
+/**< Structure that defines the Vp880 Device Profile. Current as of the first
+ * Device Profile version (ver 0).
+ */
+typedef struct Vp880DeviceProfileType {
+    uint8   profVersion;
+    uint16  pcmClkRate;      /**< Used to verify valid TX/RX Timeslot setting */
+    uint16  tickRate;        /**< Primary API-II tick for this device */
+    uint8   devCfg1;
+    uint8   clockSlot;
+    uint8   systemConfig;   /**< Used to indicate system supply configuration */
+
+#ifdef VP880_FXS_SUPPORT
+    bool    peakManagement;
+    bool    lowVoltOverride;
+#endif
+} Vp880DeviceProfileType;
+
+/* Byte/Bit definitions from the device profile */
+#define VP880_DEV_PROFILE_OPERATIONAL_CFG   (2u)
+#define VP880_DEV_PROFILE_PK_PWR_MGMT       0x01
+#define VP880_DEV_PROFILE_LOW_VOLT_OVERRIDE 0x02
+
+#define VP880_DEV_PROFILE_PCLK_MSB          (6u)
+#define VP880_DEV_PROFILE_PCLK_LSB          (7u)
+#define VP880_DEV_PROFILE_DEVCFG1           (8u)
+
+#define VP880_DEV_PROFILE_SYSTEM_CFG        (9u)
+#define VP880_ABS_CFG_SINGLE                0x00
+#define VP880_ABS_CFG_SLAVE                 0x01
+#define VP880_ABS_CFG_MASTER                0x02
+#define VP880_ABS_CFG_MASK                  0x03
+
+#define VP880_DEV_PROFILE_CLOCK_SLOT        (10u)
+#define VP880_DEV_PROFILE_MAX_EVENTS        (11u)
+#define VP880_DEV_PROFILE_TICKRATE_MSB      (12u)
+#define VP880_DEV_PROFILE_TICKRATE_LSB      (13u)
+#define VP880_DEV_PROFILE_SWITCHER_CMD      (14u)
+#define VP880_DEV_PROFILE_SWITCHER_DATA0    (15u)
+#define VP880_DEV_PROFILE_SWITCHER_DATA1    (16u)
+#define VP880_DEV_PROFILE_SWITCHER_DATA2    (17u)
+
+#define VP880_ABS_DEV_PROFILE_YVOLT         (18u)
+#define VP880_ABS_DEV_PROFILE_ZVOLT         (19u)
+
+#define VP880_DEV_PROFILE_TRACKER_INT_SW_REG    (18u)
+
+#define VP880_DEV_PROFILE_ABS_INT_SW_REG    (24u)
+
+
+/**< Line Status types to minimize code space in line object (compared to each
+ * status being maintined by a uint8 type)
+ */
+typedef enum Vp880LineStatusType {
+    VP880_INIT_STATUS = 0x0000,
+
+    VP880_IS_FXO = 0x0001,  /**< Set if the line is configured for FXO */
+
+    VP880_SLS_CALL_FROM_API = 0x0002,   /**< Set if Set Line State is called
+                                         * from an API function (e.g., cadence).
+                                         */
+
+    VP880_BAD_LOOP_SUP = 0x0004,    /**< Set when the Loop Supervision has been
+                                     * changed in such a way inconsistent with
+                                     * the user's specifications. This is done
+                                     * in internal to the API to make some
+                                     * functions work (e.g., Msg Wait Pulse).
+                                     */
+
+    VP880_UNBAL_RINGING = 0x0008,   /**< Set if this line uses unbal ringing */
+
+    VP880_DP_SET1_DONE = 0x0010,    /**< Set when Dial Pulse detection machine
+                                     * is "done" on the current dial pulse using
+                                     * the "first" set of DP parameters
+                                     */
+
+    VP880_DP_SET2_DONE = 0x0020,    /**< Set when Dial Pulse detection machine
+                                     * is "done" on the current dial pulse using
+                                     * the 2nd set of DP parameters
+                                     */
+
+    VP880_LINE_IN_CAL = 0x0040,    /**< Set when line is calibrating */
+
+    VP880_LOW_POWER_EN = 0x0080,    /**< Set when line is operating in low power
+                                     * mode
+                                     */
+
+    VP880_LINE_LEAK = 0x0100,      /**< Set when leakage is detected on the line
+                                    * such that low power mode is prevented.
+                                    */
+
+    VP880_INIT_COMPLETE = 0x0800,  /**< Set when InitLine has been completed
+                                    * on this line.
+                                    */
+    VP880_PREVIOUS_HOOK = 0x1000,  /**< Set if Last Hook Event reported was
+                                    * off-hook, cleared if last event was
+                                    * on-hook.
+                                    */
+
+    VP880_RING_GEN_NORM = 0x2000,  /**< Set when the Generators are known last
+                                    * to be programmed to the application
+                                    * specified ringing profile. Cleared
+                                    * when line tests are run because the same
+                                    * generator is used for non-ringing.
+                                    */
+    VP880_RING_GEN_REV = 0x4000    /**< Set when the Generators are known last
+                                    * to be programmed to the application
+                                    * specified ringing profile. Cleared
+                                    * when line tests are run because the same
+                                    * generator is used for non-ringing.
+                                    */
+} Vp880LineStatusType;
+
+#if defined (VP880_INCLUDE_TESTLINE_CODE)
+/* Definitions for Test arguments */
+typedef union Vp880TestArgsType {
+    VpTestPrepareType           prepare;
+    VpTestConcludeType          conclude;
+    VpTestOpenVType             openV;
+    VpTestDcRLoopType           dcRloop;
+    VpTestAcRLoopType           acRloop;
+    VpTest3EleResAltResType     resFltAlt;
+    VpTestMSocketType           mSocket;
+    VpTestXConnectType          xConnect;
+    VpTest3EleCapAltResType     capAlt;
+    VpTestLoopCondType          loopCond;
+    VpTestLoopbackType          loopback;
+    VpTestRampType              ramp;
+    VpTestRampInitType          rampInit;
+} Vp880TestArgsType;
+
+typedef struct Vp880LineTestCalType {
+    uint8 slacState;
+    uint8 vpGain;
+    uint8 opCond;
+    uint8 opFunction;
+    uint8 icr2[VP880_ICR2_LEN];
+    uint8 icr3[VP880_ICR3_LEN];
+    uint8 icr4[VP880_ICR4_LEN];
+    uint8 icr6[VP880_ICR6_LEN];
+} Vp880LineTestCalType;
+
+typedef struct Vp880TestHeapType {
+    uint8 adcState;
+    int16 nextState; /**< Used when a pcm collection routine is started */
+
+    Vp880TestArgsType testArgs; /**< Saved test input arguments of current test */
+
+    uint8 opCond;                           /**< Saved Operation Condition */
+    uint8 opFunction;                       /**< Saved Operation Functions */
+    uint8 sigCtrl;                          /**< Signal Generator Control */
+    uint8 slacState;                        /**< Saved Slac State */
+    uint8 sysConfig;                        /** Saved System Configurations */
+    uint8 vpGain;                           /**< Voice Path Gain */
+    uint8 switchReg[VP880_REGULATOR_PARAM_LEN]; /**< Switching Reg Parameters */
+    uint8 dcFeed[VP880_DC_FEED_LEN];        /**< Saved DC Feed Parameters */
+    uint8 disn;                             /**< Digital Imped. Scaling Network */
+    uint8 SwRegCtrl;                        /**< Switching Regulator Control */
+
+    uint8 icr1[VP880_ICR1_LEN];
+    uint8 icr2[VP880_ICR2_LEN];
+    uint8 icr3[VP880_ICR3_LEN];
+    uint8 icr4[VP880_ICR4_LEN];
+    uint8 icr6[VP880_ICR6_LEN];
+    uint8 lpSuper[VP880_LOOP_SUP_LEN];      /**< Saved Loop Sup. Parameters */
+    uint8 sigGenAB[VP880_SIGA_PARAMS_LEN];  /**< Saved Signal Generator A & B */
+    uint8 b1Filter[VP880_B1_FILTER_LEN];    /**< Saved B1 filter coefficients */
+    uint8 b2Filter[VP880_B2_FILTER_LEN];    /**< Saved B2 filter coefficients */
+
+    /* lg res flt uses this to bump up the battery */
+    uint8 batCal[VP880_BAT_CALIBRATION_LEN];
+
+    /* used for collecting PCM data */
+    bool pcmRequest;        /** < indication that pcm data was requested */
+    VpPcmOperationMaskType operationMask;
+
+    VpPcmOperationResultsType pcmResults; /** < stores the pcm operation results */
+
+    /* Used for common setup functions */
+    uint16 commonSetupState;
+
+    /* Used for storing line event mask data */
+    VpOptionEventMaskType preTestEventMask;
+
+    /* Used for saving and restoring registers during calibration */
+    Vp880LineTestCalType calRegs;
+
+    /* Used for resflt lg speed up*/
+    uint16 speedupTime;
+    int16 previousAvg;
+    int16 vabComputed;
+    uint8 loopCnt;
+    bool compensate;
+    bool lowGain;
+
+    /* Used in the capacitance test */
+    int16 adcSampleBuffer[52];
+    uint8 requestedSamples;
+    uint8 saveConvConfig[VP880_CONV_CFG_LEN];
+    bool xtraBuffer;
+
+    /* The following members are for EZ mode calculations only*/
+#ifdef VP880_EZ_MPI_PCM_COLLECT
+    VpPcmComputeTempType ezPcmTemp;
+
+    /* Used to debug under and overflow pcm collect conditions */
+#ifdef VP_DEBUG
+    int8 underFlowValue;
+    uint32 overCnt;
+    uint32 underCnt;
+#endif
+#endif
+
+} Vp880TestHeapType;
+
+typedef struct Vp880CurrentTestType {
+    Vp880TestHeapType *pTestHeap;
+    uint8 testHeapId;
+
+    uint8 channelId;    /**< Channel # for "this" line on the device.  Indexed
+                         * starting at 0, should not exceed the max number of
+                         * lines supported by the device - 1 (max = 2, then
+                         * channelId = {0, 1}
+                         */
+
+    bool prepared;          /**< indicates if the current test is prepared */
+    bool preparing;         /**< indicates if the test prepare is complete */
+    bool concluding;        /**< indicates that the device is concluding a test */
+    bool nonIntrusiveTest;  /**< indicates a "stealth" test */
+    VpTestIdType testId;    /** < indicates the test currently running */
+
+    int16 testState;        /**< maintains the currnt state of the current TestId */
+    uint16 handle;
+
+} Vp880CurrentTestType;
+
+typedef struct Vp880CalOffCoeffs {
+    int16 nullOffset;
+    int16 vabOffset;
+    int16 vahOffset;
+    int16 valOffset;
+    int16 vbhOffset;
+    int16 vblOffset;
+    int16 imtOffset;
+    int16 ilgOffset;
+} Vp880CalOffCoeffs;
+
+#endif /*VP880_INCLUDE_TESTLINE_CODE*/
+
+typedef struct Vp880AbvCalData {
+    uint8 passCnt;
+    bool initChange;    /**< As needed, set to TRUE when a state is changed in
+                         * the calibration state machine.
+                         */
+
+    int16 swyVolt[2]; /**< One per channel used to measure SWY Voltage */
+    int16 swzVolt[2]; /**< One per channel used to measure SWZ Voltage */
+
+    uint8 isrpData[VP880_INT_SWREG_PARAM_LEN];
+    uint8 icr1[2][VP880_ICR1_LEN];
+    uint8 icr2[2][VP880_ICR2_LEN];
+    uint8 icr3[2][VP880_ICR3_LEN];
+    uint8 icr4[2][VP880_ICR4_LEN];
+    uint8 disnVal[2][VP880_DISN_LEN];
+    uint8 vpGain[2][VP880_VP_GAIN_LEN];
+    uint8 sysState[2][VP880_SYS_STATE_LEN];
+    uint8 opFunc[2][VP880_OP_FUNC_LEN];
+    uint8 opCond[2][VP880_OP_COND_LEN];
+    uint8 converterCfg[2][VP880_CONV_CFG_LEN];
+
+    /*
+     * This the switcher adjustments as determined by battery and VAS calibration
+     * procedures.
+     */
+    uint8 switcherAdjust[2][VP880_BAT_CALIBRATION_LEN];
+
+    /* This is to be compatible with VVA P1.3.0 */
+    int16 swyOffset[2];
+    int16 swzOffset[2];
+
+    /* This is to be compatible with VVA P1.3.0 but not currently measured. */
+    int16 swxbOffset[2];
+} Vp880AbvCalData;
+
+typedef struct Vp880CalLoopData {
+    int16 prevVal;
+    uint8 loopNum;
+    uint8 adcLoopMax;
+    uint8 adcRoute;
+} Vp880CalLoopData;
+
+typedef struct Vp880VocCalData {
+    int16 vocNorm;
+    int16 vocRev;
+} Vp880VocCalData;
+
+typedef struct Vp880CalTypeData {
+    int16 swyVolt;
+    Vp880CalLoopData loopData;
+    Vp880VocCalData vocData;
+} Vp880CalTypeData;
+
+
+#define VP880_AC_PROFILE_SIZE   (80)    /* 80 Bytes is fixed size known for 880
+                                         * AC Profiles up to PW 2.0.0
+                                         */
+#define VP880_DC_PROFILE_SIZE   (20)    /* 16 bytes should be enough, but this
+                                         * profile size has changed over time.
+                                         * Safe value with a few more bytes.
+                                         */
+
+#define VP880_RINGING_PROFILE_SIZE  (22)    /* 22 byte Ringing Profile size is
+                                             * the only size ever created for
+                                             * VE880 API. This should be enough.
+                                             */
+
+/*
+ * Bit-Masks for calibration update required if line configuration change
+ * attempted during calibration. Note that this only needs to flag/update the
+ * line configuration that may affect calibration.
+ */
+#define AC_PROFILE_UPDATE_REQ       0x1
+#define DC_PROFILE_UPDATE_REQ       0x2
+#define RINGING_PROFILE_UPDATE_REQ  0x4
+#define CODEC_UPDATE_REQ            0x8
+
+/*  these are in order of execution ALWAYS do not reorder them !!!! */
+typedef enum Vp880CalLineState {
+    VP880_CAL_SETUP                 =   0,
+    VP880_CAL_SETUP_RELEASE_CLAMPS,
+    VP880_RAMP_TO_POLREV_SETUP,
+    VP880_RAMP_TO_POLREV_RAMP1,
+    VP880_RAMP_TO_POLREV_SWAP_POLARITY,
+    VP880_RAMP_TO_POLREV_RAMP2,
+    VP880_RAMP_TO_POLREV_GOACTIVE,
+    VP880_RAMP_TO_POLREV_COMPLETE,
+
+    VP880_IMT_PR_SETUP              =   20,
+    VP880_IMT_PR_SET_ADC,
+    VP880_IMT_PR_MEASURE,
+
+#ifdef VP880_TRACKER_SUPPORT
+    VP880_VAS_PR_SETUP              =   30,
+    VP880_VAS_PR_STEP,
+    VP880_VAS_PR_SET_ADC,
+    VP880_VAS_PR_MEASURE,
+    VP880_VAS_PR_STORE,
+#endif
+
+    VP880_VAB_PR_SETUP              =   40,
+    VP880_VAB_PR_MEASURE,
+
+    VP880_VAB_PR_ADC_OFFSET_SETUP   =   50,
+    VP880_VAB_PR_ADC_OFFSET_MEASURE,
+
+    VP880_VA_PR_ADC_OFFSET_SETUP    =   60,
+    VP880_VA_PR_ADC_OFFSET_MEASURE,
+
+    VP880_VB_PR_ADC_OFFSET_SETUP    =   70,
+    VP880_VB_PR_ADC_OFFSET_MEASURE,
+
+    VP880_COLLAPSE_FEED             =   80,
+
+    VP880_GENA_NP_OFFSET_SETUP      =   90,
+    VP880_GENA_NP_OFFSET_SET_ADC,
+    VP880_GENA_NP_OFFSET_MEASURE,
+    VP880_GENA_NP_OFFSET_RESTORE,
+
+    VP880_ILG_OFFSET_SETUP          =   100,
+    VP880_ILG_OFFSET_MEASURE,
+
+    VP880_ILA_OFFSET_SETUP          =   110,
+    VP880_ILA_OFFSET_MEASURE,
+
+
+    VP880_RESTORE_DAC               =   120,
+
+    VP880_VAB_NP_ADC_OFFSET_SETUP   =   130,
+    VP880_VAB_NP_ADC_OFFSET_MEASURE,
+
+    VP880_VA_NP_ADC_OFFSET_SETUP    =   140,
+    VP880_VA_NP_ADC_OFFSET_MEASURE,
+
+    VP880_VB_NP_ADC_OFFSET_SETUP    =   150,
+    VP880_VB_NP_ADC_OFFSET_MEASURE,
+
+    VP880_ILA_SETUP                 =   160,
+    VP880_ILA_ADJUST,
+    VP880_ILA_SET_ADC,
+    VP880_ILA_MEASURE,
+    VP880_ILA_MEASURE_TRACKER,
+    VP880_ILA_MEASURE_ABS,
+
+    VP880_RESTORE_FEED              =   170,
+
+    VP880_IMT_NP_SETUP              =   180,
+    VP880_IMT_NP_SET_ADC,
+    VP880_IMT_NP_MEASURE,
+
+#ifdef VP880_TRACKER_SUPPORT
+    VP880_VAS_NP_SETUP              =   190,
+    VP880_VAS_NP_STEP,
+    VP880_VAS_NP_SET_ADC,
+    VP880_VAS_NP_MEASURE,
+    VP880_VAS_NP_STORE,
+#endif
+
+    VP880_VAB_NP_SETUP              =   200,
+    VP880_VAB_NP_MEASURE,
+
+    VP880_CAL_ADJUST                =   210,
+
+    VP880_CAL_RESTORE               =   254,
+
+    /**< Used in API to force valid/unused initial value */
+    VP880_CAL_ENUM_SIZE             = (VP880_CAL_RESTORE + 1)
+
+} Vp880CalLineState;
+
+typedef struct Vp880CalLineData {
+    bool calDone;           /**< TRUE when calibration has been performed on
+                             * this line
+                             */
+    bool reversePol;        /**< TRUE when line is in reverse polarity */
+
+    Vp880CalTypeData typeData;
+
+    uint8 codecReg;
+
+    uint8 dcFeedRef[VP880_DC_FEED_LEN]; /**< Customer settings per profile */
+    uint8 dcFeed[VP880_DC_FEED_LEN];    /**< Normal polarity calibrated values */
+    uint8 dcFeedPr[VP880_DC_FEED_LEN];  /**< Reverse polarity calibrated values */
+
+    Vp880CalLineState calLineState;
+    uint8 sysState;
+
+    uint8 icr2[VP880_ICR2_LEN];
+    uint8 icr3[VP880_ICR3_LEN];
+
+    uint8 disnVal[VP880_DISN_LEN];
+    uint8 vpGain[VP880_VP_GAIN_LEN];
+    uint8 loopSup[VP880_LOOP_SUP_LEN];
+
+    bool forceCalDataWrite;
+
+    /* Signal generator calibration temporary backup */
+    uint8 sigGenA[VP880_SIGA_PARAMS_LEN];
+    uint8 calReg[VP880_ICR6_LEN];
+    uint8 asscReg;
+
+    /**< Battery Calibration values used to compute final VAS values */
+    uint8 swCal[VP880_BAT_CALIBRATION_LEN];
+
+    uint16 minVas;  /**< Minimum VAS value determined during IMT calibration.
+                     * This is stored in the same format used to compute the VAS
+                     * value rather than the device format. This increases the
+                     * data memory space requirements slightly, but reduces the
+                     * size for code space and simplifies the logic when applied.
+                     */
+
+    uint16 vasStart;    /**< Starting point for VAS to reduce calibration time.
+                         * This value is based on battery adjustment and the
+                         * minimum vas allowed ("minVas" above).
+                         */
+
+    /*
+     * Cached user data applied after calibration in case line configuration is
+     * changed during calibration.
+     */
+    uint8 updateFlags;  /*
+                         * Bit-Mask to mark the information that needs to be
+                         * updated when calibration is complete. Note that some
+                         * information is automatically updated when calibration
+                         * is complete simply as part of the restore process.
+                         */
+    uint8 acProfile[VP880_AC_PROFILE_SIZE];
+    uint8 dcProfile[VP880_DC_PROFILE_SIZE];
+    uint8 ringingProfile[VP880_RINGING_PROFILE_SIZE];
+
+    VpLineStateType usrState;
+
+} Vp880CalLineData;
+
+typedef enum Vp880CalDeviceState {
+    VP880_CAL_INIT                  =   0,
+    VP880_CAL_ERROR,
+    VP880_CAL_MEASURE,
+    VP880_CAL_OFFSET,
+    VP880_CAL_ADC,
+    VP880_CAL_STATE_CHANGE,
+    VP880_CAL_INVERT_POL,
+    VP880_CONVERTER_CHECK,
+    VP880_CAL_DONE,
+    VP880_CAL_CLEANUP,
+    VP880_CAL_EXIT
+} Vp880CalDeviceState;
+
+typedef struct Vp880CalDeviceData {
+    Vp880AbvCalData abvData;
+    Vp880CalDeviceState calDeviceState;
+    int16 calSet;   /* Target values for calibration */
+    uint8 iteration;    /**< Used as fail-safe to prevent infinte retries */
+} Vp880CalDeviceData;
+
+typedef struct Vp880RingParams {
+    bool channelArray[VP880_MAX_NUM_CHANNELS];
+    uint8 stage[VP880_MAX_NUM_CHANNELS];
+    uint8 swRegParam[VP880_REGULATOR_PARAM_LEN];
+} Vp880RingParams;
+
+typedef struct Vp880LineObjectType {
+    uint8 channelId;    /**< Channel # for "this" line on the device.  Indexed
+                         * starting at 0, should not exceed the max number of
+                         * lines supported by the device - 1 (max = 2, then
+                         * channelId = {0, 1}
+                         */
+
+    uint8 ecVal;
+
+    VpTermType termType;    /**< Termination type */
+
+    uint16 status;  /**< Bit-mask of Vp880LineStatusType Keeps track of line state/config info*/
+
+#ifdef VP_CSLAC_SEQ_EN
+    VpSeqDataType cadence;      /**< Sequencer related information */
+
+    /**< Array to control internally run sequences */
+    VpProfileDataType intSequence[VP880_INT_SEQ_LEN];
+
+#ifdef VP880_FXS_SUPPORT
+    VpCallerIdType callerId;    /**< Caller ID related information */
+    VpCidSeqDataType cidSeq;    /**< CID Sequencer related information */
+    uint8 tickBeginState[VP880_CID_PARAM_LEN];
+    uint8 cidBytesRemain;
+    bool delayConsumed; /**< Set to TRUE when Polling Mode CID uses the loop
+                         * read/delay method and has started it.
+                         */
+
+    bool suspendCid;
+
+    VpProfilePtrType pRingingCadence;   /**< Currently used ringing cadence on
+                                         * this line
+                                         */
+
+    VpProfilePtrType pMeterProfile;     /**< Currently used metering profile on
+                                         * this line
+                                         */
+
+    VpProfilePtrType pCidProfileType1;  /**< Currently used caller ID profile
+                                         * on this line for sequenced cid
+                                         */
+#endif  /* VP880_FXS_SUPPORT */
+
+#ifdef VP880_FXO_SUPPORT
+    VpDigitGenerationDataType digitGenStruct;   /**< Used on FXO lines for
+                                                 * generating pulse digits
+                                                 */
+#endif  /* VP880_FXO_SUPPORT */
+#endif  /* VP_CSLAC_SEQ_EN */
+
+#ifdef VP880_FXS_SUPPORT
+    VpDialPulseDetectType dpStruct; /**< Used on FXS lines for detecting pulse
+                                     * digits
+                                     */
+
+    VpDialPulseDetectType dpStruct2;/**< Used on FXS lines for detecting pulse
+                                     * digits using 2nd set of dp specs.
+                                     */
+
+    VpOptionPulseModeType pulseMode;
+
+    /*
+     * Array to hold ringing parameters used in the Signal Generator.  This is
+     * needed when signal generator A is set to a tone, then set back to ringing
+     * without the user re-specifying the ringing profile
+     */
+    uint8 ringingParams[VP880_SIGA_PARAMS_LEN];
+
+    uint8 leakyLineCnt; /*
+                         * Keeps track of # of times off-hook was detected (LP Mode)
+                         * that was not further verified after exiting LP Mode. Reset
+                         * when off-hook is verified.
+                         */
+    /* Loop supervision parameters */
+    uint8 hookHysteresis;
+
+    bool internalTestTermApplied;
+
+    VpOptionRingControlType ringCtrl;
+
+    /*
+     * Used to track states for Ground Start Exit Timer Management. Use two steps - first step
+     * completes final state control, the second step is for final hook and ground key debounce.
+     */
+    uint8 gsTimerExitState;
+
+    /*
+     * Used to track states for Disconnect Exit Timer Management. Use two steps - first step
+     * completes final state control, the second step is for final hook and ground key debounce.
+     */
+    uint8 discTimerExitState;
+
+    VpRelayControlType relayState;   /**< Used to hold current line relay state */
+
+#endif
+
+    VpOptionEventMaskType lineEventsMask;
+    VpOptionEventMaskType lineEvents;
+
+    uint16 signaling1;
+    uint16 signaling2;
+    uint8 signalingData;    /**< Holds data for Signaling events on this line */
+
+
+#ifdef VP880_FXO_SUPPORT
+    uint8 fxoData;          /**< Holds data for FXO events on this line */
+    uint8 preRingPolRev;    /**< The polarity detected prior to ring detect */
+    VpCslacLineCondType preDisconnect;    /**< The disconnect state prior to timer start */
+
+    uint8 ringDetMax;   /**< Stores the user specified maximum ringing detect
+                         * period for FXO lines. This value may be outside the
+                         * device range, in which case the SW will implement
+                         * upper period detection
+                         */
+    uint8 ringDetMin;   /**< Stores the user specified maximum ringing detect
+                         * period for FXO lines that is within the device range.
+                         * This value is used as "minimum" that is detected by
+                         * SW. Actual minimum period is supported by the device
+                         * period detector itself.
+                         */
+#endif
+
+    uint16 processData;     /**< Holds data for Process events on this line */
+
+    uint8 responseData;     /**< Holds data for Response events on this line */
+
+    VpCslacTimerStruct lineTimers; /**< Timers for "this" line */
+    VpApiIntLineStateType lineState;    /**< Line state info used for state
+                                         * transition handling and recall
+                                         */
+    uint8 nextSlicValue;
+    uint8 slicValueCache;   /**< Used to reduce MPI reads. */
+
+    /*
+     * Holds user definition for Loop Supervision configuration when
+     * "badLoopSup" is TRUE
+     */
+    uint8 loopSup[VP880_LOOP_SUP_LEN];
+
+    uint16 lineEventHandle; /**< Line specific event handle information */
+
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;   /* Defines how the PCM highway is
+                                             * set for "talk" linestates
+                                             */
+
+    uint16 dtmfDigitSense;          /**< Used to hold the DTMF digit reported
+                                     * with VpDtmfDigitDetected() until the
+                                     * VP_LINE_EVID_DTMF_DIG is generated.
+                                     */
+
+    VpLineIdType lineId;    /**< Application provided value for mapping a line to
+                             * a line context
+                             */
+    /*
+     * NOTE: Do not move the location or name of these members. These may be
+     * used by applications to determine the gain of the GX/GR blocks in the
+     * AC profile. Using return from VpSetRelGain() is not usefull because that
+     * is the register setting. The customer would have to know how to convert
+     * that to linear values, which is not generally documented.
+     */
+    struct Vp880RelGainValues {
+        uint16 gxInt;       /**< Cached GX register, in 2.14 int format */
+        uint16 grInt;       /**< Cached GR register, in 2.14 int format */
+        int16 absGxGain;    /**< Cached ABS A-to-D Gain, simplifies code. */
+        int16 absGrGain;    /**< Cached ABS D-to-A Gain, simplifies code. */
+    } gain;
+
+    Vp880CalLineData calLineData;
+
+    VpOptionCodecType codec;
+
+#ifdef VP880_FXS_SUPPORT
+    VpHowlerModeCachedValues howlerModeCache;
+
+    uint8 icr1Values[VP880_ICR1_LEN];   /**< Cached to minimize device access */
+    uint8 icr2Values[VP880_ICR2_LEN];   /**< Cached to minimize device access */
+    uint8 icr3Values[VP880_ICR3_LEN];   /**< Cached to minimize device access */
+    uint8 icr4Values[VP880_ICR4_LEN];   /**< Cached to minimize device access */
+    uint8 icr6Values[VP880_ICR6_LEN];   /**< Cached to minimize device access */
+#endif
+
+    uint8 opCond[VP880_OP_COND_LEN];    /**< Cached to minimize device access */
+    uint8 sigGenCtrl[VP880_GEN_CTRL_LEN];   /**< Cached to minimize device access */
+
+#ifdef VP_DEBUG
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+#endif
+
+} Vp880LineObjectType;
+
+/*
+ * IMPORTANT: Make sure to update the "stateInt" member of the device object if
+ * the size of this type changes. There is no instance of this type itself.
+ */
+typedef uint32 Vp880DeviceStateIntType;
+#define VP880_IS_ABS                (0x0001)    /**< Set when the device is ABS type */
+#define VP880_RLY_PROT_REQ          (0x0002)    /**< Set when the device requires relay protction on I/O 1 */
+#define VP880_HAS_TEST_LOAD_SWITCH  (0x0004)    /**< Set when test load swith is available */
+#define VP880_HAS_CALIBRATE_CIRCUIT (0x0008)    /**< Set when test cal circuit is available */
+
+#define VP880_IS_HIGH_VOLTAGE       (0x0010)    /**< Set when device is a high voltage device */
+#define VP880_IS_SINGLE_CHANNEL     (0x0020)    /**< Set when a single channel device is found*/
+#define VP880_SYS_CAL_RESET         (0x0040)    /**< Set when Apply Cal is passed NULL to reset calibration values */
+#define VP880_LINE0_IS_FXO          (0x0080)    /**< Set if device detection indicates line0 as FXO */
+
+#define VP880_LINE1_IS_FXO          (0x0100)    /**< Set if device detection indicates line1 as FXO */
+#define VP880_WIDEBAND              (0x0200)    /**< Set if device supports Wideband mode */
+#define VP880_LINE0_LP              (0x0400)    /**< Set if line 0 allows low power mode */
+#define VP880_LINE1_LP              (0x0800)    /**< Set if line 1 allows low power mode */
+
+#define VP880_IS_FXO_ONLY           (0x1000)    /**< Set when the device contains only FXO lines */
+#define VP880_SYS_CAL_COMPLETE      (0x2000)    /**< Set when the system calibration structure has been initialied */
+#define VP880_CAL_RELOAD_REQ        (0x4000)    /**< Set when the line calibration values need to be reloaded. */
+#define VP880_FORCE_FREE_RUN        (0x8000)    /**< Set when app calls VpFreeRun() (start), cleared when called with stop.
+                                                 * This prevents the VP-API-II from automatically exiting free run mode
+                                                 * upon PCLK recovery.
+                                                 */
+
+#define VP880_SWY_DECAY_CMP         (0x10000)
+#define VP880_SWZ_DECAY_CMP         (0x20000)
+
+#define VP880_IS_TEST_CAPABLE       (0x40000)   /**< Set for devices that support Line Test */
+
+/*
+ * This value is set when either Device Calibration (VpInitDevice()/VpCalCodec()
+ * completes successfully, or when loaded values by Apply System Coeff. After
+ * VpInitDevice() this should only be NOT SET if device calibration failed or
+ * if null was passed to Apply System Coeff.
+ */
+#define VP880_DEVICE_CAL_COMPLETE   (0x80000)
+
+
+#define VP880_SYS_CAL_POLARITY_LENGTH  2
+#define VP880_SYS_CAL_CHANNEL_LENGTH   2
+
+/* Contains calibration error values -- in +/-10mv LSB */
+typedef struct Vp880SysCalResultsType {
+    int16 abvError[2];
+
+    int16 vocOffset[VP880_SYS_CAL_CHANNEL_LENGTH][VP880_SYS_CAL_POLARITY_LENGTH];
+    int16 vocError[VP880_SYS_CAL_CHANNEL_LENGTH][VP880_SYS_CAL_POLARITY_LENGTH];
+
+    int16 sigGenAError[VP880_SYS_CAL_CHANNEL_LENGTH][VP880_SYS_CAL_POLARITY_LENGTH];
+
+    int16 ila20[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila25[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila32[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila40[VP880_SYS_CAL_CHANNEL_LENGTH];
+
+    int16 ilaOffsetNorm[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 ilgOffsetNorm[VP880_SYS_CAL_CHANNEL_LENGTH];
+
+    /* Used for Tracker only */
+    uint8 vas[VP880_SYS_CAL_CHANNEL_LENGTH][VP880_SYS_CAL_POLARITY_LENGTH];
+
+    int16 vagOffsetNorm[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 vagOffsetRev[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 vbgOffsetNorm[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int16 vbgOffsetRev[VP880_SYS_CAL_CHANNEL_LENGTH];
+
+    /* Used for ABS only */
+    uint8 absNormCal[VP880_SYS_CAL_CHANNEL_LENGTH];
+    uint8 absPolRevCal[VP880_SYS_CAL_CHANNEL_LENGTH];
+
+    int16 swyOffset[VP880_SYS_CAL_CHANNEL_LENGTH];     /**< Used to hold SWY Offset */
+    int16 swzOffset[VP880_SYS_CAL_CHANNEL_LENGTH];     /**< Used to hold SWZ Offset */
+    int16 swxbOffset[VP880_SYS_CAL_CHANNEL_LENGTH];    /**< Used to hold SWXB Offset */
+
+    /* Used for capacitance line test only */
+    int32 tipCapCal[VP880_SYS_CAL_CHANNEL_LENGTH];
+    int32 ringCapCal[VP880_SYS_CAL_CHANNEL_LENGTH];
+} Vp880SysCalResultsType;
+
+#define VP880_CAL_STRUCT_SIZE   (40*sizeof(int16) + 8*sizeof(uint8) + 4*sizeof(int32))
+
+typedef struct Vp880DeviceObjectType {
+    /* Device identifier set by the application -- passed to the HAL */
+    VpDeviceIdType deviceId;
+
+    /* Silicon RCN/PCN and number of channels supported */
+    VpDeviceStaticInfoType staticInfo;
+
+    /*
+     * Weak attempt to put everything that changes during run-time into a
+     * single structure. Good idea in principle, but in practice the devices
+     * are too dis-similar to share many common structures.
+     *
+     * This holds the "last channel checked" event information, clock fault,
+     * and battery fault.
+    */
+    VpDeviceDynamicInfoType dynamicInfo;
+
+    /*
+     * Variety of common device level status such as init/not init, init in
+     * progress, test buffer read y/n?, etc.. Internally used by the VP-API-II
+     * to communicate device state.
+     *
+     * This is a bit-mask of VpDeviceStateType values
+     */
+    uint16 state;
+
+    /*
+     * Similar to common device level status, this is for 880 specific type of
+     * device level information. Such as ABS/Tracker, LPM lines, etc..
+     *
+     * This is a bit-mask of Vp880DeviceStateIntType values
+     */
+    uint32 stateInt;
+
+    /*-----------------3/18/2010 3:51PM-----------------
+     * Device Level OPTION Values
+     * --------------------------------------------------*/
+    /* OPTION_ID_EVENT_MASK for device level events */
+    VpOptionEventMaskType deviceEventsMask;
+
+    /* OPTION_ID_PULSE */
+    VpOptionPulseType pulseSpecs;
+
+    /* OPTION_ID_PULSE2 */
+    VpOptionPulseType pulseSpecs2;
+
+    /* OPTION_ID_CRITICAL_FLT */
+    VpOptionCriticalFltType criticalFault;
+
+    /*
+     * Stored device level events. Note that this is an alternative method to
+     * an event queue. So if an event queue is later used, this value could be
+     * removed and all it's uses replaced.
+     */
+    VpOptionEventMaskType deviceEvents;
+
+    /*
+     * Device level timers such as clock fault, LPM Enter/Exit, VpCalCodec()
+     * steps, etc..
+     */
+    uint16 devTimer[VP_DEV_TIMER_LAST];
+
+    /*
+     * Soft values from the device profile that are used throughout the VP-API-II
+     * (not only in Init). Note that other values may be provided by the device
+     * profile, but are stored in other ways generally because they also may NOT
+     * be provided in the device profile (i.e., API has default values).
+     */
+    Vp880DeviceProfileType devProfileData;
+
+    /* This is the profile pointer table per the VP-API-II User's Guide. */
+    VpCSLACDeviceProfileTableType devProfileTable;
+
+    /*
+     * This is the structure indicating which profile table entries have been
+     * initialized. If profile tables are disabled, this and the device profile
+     * table (devProfileTable) can be removed.
+     */
+    VpCSLACProfileTableEntryType profEntry;
+
+    /*
+     * Raw information from the device signaling register last read. This
+     * information is internally converted into useable VP-API-II information.
+     */
+    uint8 intReg[VP880_UL_SIGREG_LEN];
+    uint8 intReg2[VP880_UL_SIGREG_LEN];
+
+    /* Buffer to support VpLowLevelCmd() only. */
+#if !defined(VP_REDUCED_API_IF) || defined(ZARLINK_CFG_INTERNAL)
+    uint8 mpiData[VP880_MAX_MPI_DATA];
+#endif
+
+    /*
+     * Data length copied into mpiData buffer -- used for VpLowLevelCmd() and
+     * Apply/Get System Calibration
+     */
+    uint8 mpiLen;
+
+    /* Handle to return with events as applicable */
+    uint16 eventHandle;
+
+    /*
+     * VP-API-II timing in 500us increments (per the VP-API-II User's Guide).
+     * Generally incremented at the tick rate.
+     */
+    uint16 timeStamp;
+    int16 timeRemainder;    /**< leftover of tick time for tickrates not divisible by 0.5ms */
+
+    /* Data returned with response events as applicable */
+    uint8 responseData;
+
+    /* Data returned with "Get Option" events */
+    VpGetResultsOptionsType getResultsOption;
+
+    /* Data returned with VpSetRelGain() function call/event. */
+    VpRelGainResultsType relGainResults;
+
+#if defined (VP880_INCLUDE_TESTLINE_CODE)
+    /* Testing structure */
+    VpTestResultType testResults;
+
+    Vp880CurrentTestType currentTest;
+
+    /**< Used to hold calibration offset coeffs. One per channel */
+    Vp880CalOffCoeffs calOffsets[VP880_MAX_NUM_CHANNELS];
+
+#endif /* VP880_INCLUDE_TESTLINE_CODE */
+
+
+    /*
+     * Used to hold battery switch calibration offset. One per channel, per
+     * polarity
+     */
+    uint8 calState;
+    Vp880CalDeviceData calData;
+
+    /*
+     * Used to get better hook granularity and pcm buffered data.
+     */
+    uint8 txBuffer[VP880_TX_PCM_BUFF_LEN];
+    uint8 txBufferDataRate;
+
+    /*
+     * These switcher paramaters are from the user setting in the
+     * device profile. They should never be changed except in Init (in case
+     * the values provided are illegal).
+     */
+    uint8 swParams[VP880_REGULATOR_PARAM_LEN];
+
+    /*
+     * These switcher paramaters should always be a SW representation of the
+     * silicon used to reduce device level access. The driver MUST change this
+     * setting if the device itself is changed.
+     */
+    uint8 swParamsCache[VP880_REGULATOR_PARAM_LEN];
+
+    /*
+     * These internal switcher paramaters are from the user setting in the
+     * device profile. They should never be changed except in Init (in case
+     * the values provided are illegal).
+     */
+    uint8 intSwParams[VP880_INT_SWREG_PARAM_LEN];
+
+    /*
+     * These internal switcher paramaters are for Free Run mode only and should
+     * only be set during Init Device (in case a set was not provided or if the
+     * provided set is illegal).
+     */
+    uint8 intSwParamsFR[VP880_INT_SWREG_PARAM_LEN];
+
+    uint8 yVolt;    /* Y-Switcher Target in 1V step */
+    uint8 zVolt;    /* Z-Switcher Target in 1V step */
+
+#if defined (VP_CC_880_SERIES) || defined (VP_CC_KWRAP)
+    Vp880SysCalResultsType vp880SysCalData;
+#endif
+
+    /* used to store the in-rush current function data */
+    Vp880RingParams ringParams;
+
+#ifdef VP_DEBUG
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+#endif
+
+    /* Used to hold the device level ecVal (to keep track of WB mode). */
+    uint8 ecVal;
+
+    /*
+     * Holds the last channel information changed to/from Wideband mode since
+     * the last tick. If = 0, no change has been made. If = 1, ch0 if = 2, ch1.
+     * This is a handshake with the tick which detects it is not 0, makes the
+     * appropriate change and sets it back to 0.
+     */
+    uint8 lastCodecChange;
+
+    /* Device Mode Register (0x5E/5F) cached to minimize MPI traffic */
+    uint8 devMode[VP880_DEV_MODE_LEN];
+} Vp880DeviceObjectType;
+
+#endif  /**< vp880_api.h */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp890_api.h b/tools/voice/zarlink/user/api_lib/includes/vp890_api.h
new file mode 100644
index 0000000..1bef289
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp890_api.h
@@ -0,0 +1,851 @@
+/** \file vp890_api.h
+ * vp890_api.h
+ *
+ *  Header file that define all the commands for the Vp890 device.
+ *
+ * $Revision: 9253 $
+ * $LastChangedDate: 2011-12-14 11:08:16 -0600 (Wed, 14 Dec 2011) $
+ */
+
+#ifndef VP890_API_H
+#define VP890_API_H
+
+#include "vp_hal.h"
+#include "vp_CSLAC_types.h"
+#include "vp_api_common.h"
+
+#ifdef VP890_INCLUDE_TESTLINE_CODE
+#include "vp_api_test.h"
+  #ifdef VP890_EZ_MPI_PCM_COLLECT
+  #include  "vp_pcm_compute.h"
+  #endif
+#endif
+
+/*
+ * Note that this value must be >=2 even when only using the single FXO device.
+ * That's because this is often used in looping through the line context pointers
+ * in the device context indexed by "channelId". The FXO channelId = 1 so the
+ * loop operations must be allowed to index into the second element.
+ */
+#define VP890_MAX_NUM_CHANNELS   2
+
+#define VP890_MAX_MPI_DATA      15   /* Max data from any MPI read command */
+#define VP890_INT_SEQ_LEN       22
+
+#ifndef VP890_UL_SIGREG_LEN
+#define VP890_UL_SIGREG_LEN         0x02
+#endif
+
+#ifndef VP890_B1_FILTER_LEN
+#define VP890_B1_FILTER_LEN         0x0E
+#endif
+
+#ifndef VP890_B2_FILTER_LEN
+#define VP890_B2_FILTER_LEN         0x02
+#endif
+
+#ifndef VP890_SIGA_PARAMS_LEN
+#define VP890_SIGA_PARAMS_LEN       0x0B
+#endif
+
+#ifndef VP890_DC_FEED_LEN
+#define VP890_DC_FEED_LEN           0x02
+#endif
+
+
+#ifndef VP890_ICR1_LEN
+#define VP890_ICR1_LEN              0x04
+#endif
+
+#ifndef VP890_ICR2_LEN
+#define VP890_ICR2_LEN              0x04
+#endif
+
+#ifndef VP890_ICR3_LEN
+#define VP890_ICR3_LEN              0x04
+#endif
+
+#ifndef VP890_ICR4_LEN
+#define VP890_ICR4_LEN              0x04
+#endif
+
+#ifndef VP890_DC_CAL_REG_LEN
+#define VP890_DC_CAL_REG_LEN        0x02
+#endif
+
+#ifndef VP890_LOOP_SUP_LEN
+#define VP890_LOOP_SUP_LEN          0x04
+#endif
+
+#ifndef VP890_TEST_DATA_LEN
+#define VP890_TEST_DATA_LEN         0x0E
+#endif
+
+#ifndef VP890_REGULATOR_PARAM_LEN
+#define VP890_REGULATOR_PARAM_LEN   0x03
+#endif
+
+#ifndef VP890_REGULATOR_TIMING_LEN
+#define VP890_REGULATOR_TIMING_LEN  0x06
+#endif
+
+#ifndef VP890_REGULATOR_CTRL_LEN
+#define VP890_REGULATOR_CTRL_LEN    0x01
+#endif
+
+#ifndef VP890_CONV_CFG_LEN
+#define VP890_CONV_CFG_LEN      0x01
+#endif
+
+/**< Required Vp890 Device and Line Objects for user instantiation if a Vp890
+ * device is used
+ */
+
+/**< Structure that defines the Vp890 Device Profile. Current as of the first
+ * Device Profile version (ver 0).
+ */
+typedef struct Vp890DeviceProfileType {
+    uint8   profVersion;
+    uint16  pcmClkRate;      /**< Used to verify valid TX/RX Timeslot setting */
+    uint8   mClkMask;
+    uint16  tickRate;        /**< Primary API-II tick for this device */
+    uint8   devCfg1;
+    uint8   clockSlot;
+
+#ifdef VP890_FXS_SUPPORT
+    uint8   swParams[VP890_REGULATOR_PARAM_LEN];
+    uint8   timingParams[VP890_REGULATOR_TIMING_LEN];
+    uint8   timingParamsFR[VP890_REGULATOR_TIMING_LEN];
+
+    bool    peakManagement;
+    bool    lowVoltOverride;
+#endif
+} Vp890DeviceProfileType;
+
+#if defined (VP890_INCLUDE_TESTLINE_CODE)
+
+/* Definitions for Test arguments */
+typedef union Vp890TestArgsType {
+    VpTestPrepareType           prepare;
+    VpTestConcludeType          conclude;
+    VpTestOpenVType             openV;
+    VpTestDcRLoopType           dcRloop;
+    VpTestAcRLoopType           acRloop;
+    VpTest3EleResAltResType     resFltAlt;
+    VpTestMSocketType           mSocket;
+    VpTestXConnectType          xConnect;
+    VpTest3EleCapAltResType     capAlt;
+    VpTestLoopCondType          loopCond;
+    VpTestLoopbackType          loopback;
+    VpTestRampType              ramp;
+    VpTestRampInitType          rampInit;
+} Vp890TestArgsType;
+
+typedef struct Vp890LineTestCalType {
+    uint8 slacState;
+    uint8 vpGain;
+    uint8 opCond;
+    uint8 opFunction;
+    uint8 switchTimes[VP890_REGULATOR_TIMING_LEN];
+    uint8 icr2[VP890_ICR2_LEN];
+    uint8 icr3[VP890_ICR3_LEN];
+    uint8 icr4[VP890_ICR4_LEN];
+    uint8 icr6[VP890_DC_CAL_REG_LEN];
+} Vp890LineTestCalType;
+
+typedef struct Vp890TestHeapType {
+    uint8 adcState;
+    int16 nextState; /**< Used when a pcm collection routine is started */
+
+    Vp890TestArgsType testArgs; /**< Saved test input arguments of current test */
+
+    uint8 opCond;                           /**< Saved Operation Condition */
+    uint8 opFunction;                       /**< Saved Operation Functions */
+    uint8 opMode;                           /**< Saved Operating Mode */
+    uint8 sysConfig;                        /** Saved System Configurations */
+    uint8 sigCtrl;                          /**< Signal Generator Control */
+    uint8 convCfg;                          /**< Saved Converter Config */
+    uint8 slacState;                        /**< Saved Slac State */
+    uint8 vpGain;                           /**< Voice Path Gain */
+    uint8 disn;                             /**< Digital Imped. Scaling Network */
+    uint8 lpSuper[VP890_LOOP_SUP_LEN];      /**< Saved Loop Sup. Parameters */
+    uint8 dcFeed[VP890_DC_FEED_LEN];        /**< Saved DC Feed Parameters */
+    uint8 switchReg[VP890_REGULATOR_PARAM_LEN]; /**< Switching Reg Parameters */
+    uint8 switchTimes[VP890_REGULATOR_TIMING_LEN]; /**< Switching Reg Timing */
+
+    uint8 icr1[VP890_ICR1_LEN];
+    uint8 icr2[VP890_ICR2_LEN];
+    uint8 icr3[VP890_ICR3_LEN];
+    uint8 icr4[VP890_ICR4_LEN];
+    uint8 icr6[VP890_DC_CAL_REG_LEN];
+    uint8 sigGenAB[VP890_SIGA_PARAMS_LEN]; /**< Saved Signal Generator A & B*/
+    uint8 b1Filter[VP890_B1_FILTER_LEN];   /**< Saved B1 filter coefficients */
+    uint8 b2Filter[VP890_B2_FILTER_LEN];   /**< Saved B2 filter coefficients */
+
+    /* used for collecting PCM data */
+    bool pcmRequest;        /** < indication that pcm data was requested */
+    VpPcmOperationMaskType operationMask;
+
+    VpPcmOperationResultsType pcmResults; /** < stores the pcm operation results */
+
+    /* Used for common setup functions */
+    uint16 commonSetupState;
+
+    /* Used for storing line event mask data */
+    VpOptionEventMaskType preTestEventMask;
+
+    /* Used for saving and restoring slac state after calibration */
+    uint8 calSlacState;
+
+     /* Used for saving and restoring registers during calibration */
+    Vp890LineTestCalType calRegs;
+
+    /* Used for resflt lg speed up*/
+    uint16 speedupTime;
+    int16 previousAvg;
+    int16 vabComputed;
+    uint8 loopCnt;
+    bool compensate;
+    bool lowGain;
+
+    /* Used in the capacitance test */
+    int16 adcSampleBuffer[52];
+    uint8 requestedSamples;
+    uint8 saveConvConfig[VP890_CONV_CFG_LEN];
+    bool xtraBuffer;
+
+    /* The following members are for EZ mode calculations only*/
+#ifdef VP890_EZ_MPI_PCM_COLLECT
+    VpPcmComputeTempType ezPcmTemp;
+
+    /* Used to debug under and overflow pcm collect conditions */
+#ifdef VP_DEBUG
+    int8 underFlowValue;
+    uint32 overCnt;
+    uint32 underCnt;
+#endif
+
+#endif
+
+} Vp890TestHeapType;
+
+typedef struct Vp890CurrentTestType {
+    Vp890TestHeapType *pTestHeap;
+    uint8 testHeapId;
+
+    uint8 channelId;    /**< Channel # for "this" line on the device.  Indexed
+                         * starting at 0, should not exceed the max number of
+                         * lines supported by the device - 1 (max = 2, then
+                         * channelId = {0, 1}
+                         */
+
+    bool prepared;          /**< indicates if the current test is prepared */
+    bool preparing;         /**< indicates if the test prepare is complete */
+    bool concluding;        /**< indicates that the device is concluding a test */
+    bool nonIntrusiveTest;  /**< indicates a "stealth" test */
+    VpTestIdType testId;    /** < indicates the test currently running */
+
+    int16 testState;        /**< maintains the currnt state of the current TestId */
+    uint16 handle;
+
+} Vp890CurrentTestType;
+
+typedef struct Vp890CalOffCoeffs {
+    int16 nullOffset;
+    int16 vabOffset;
+    int16 vahOffset;
+    int16 valOffset;
+    int16 vbhOffset;
+    int16 vblOffset;
+    int16 batOffset;
+    int16 imtOffset;
+    int16 ilgOffset;
+} Vp890CalOffCoeffs;
+
+#endif /*VP890_INCLUDE_TESTLINE_CODE*/
+
+typedef enum Vp890BFiltCalStates {
+    VP890_BFILT_MEASURE,
+    VP890_BFILT_END
+} Vp890BFiltCalStates;
+
+#ifndef VP890_B1_FILTER_LEN
+#define VP890_B1_FILTER_LEN         0x0E
+#endif
+
+#ifndef VP890_B2_FILTER_LEN
+#define VP890_B2_FILTER_LEN         0x02
+#endif
+
+#ifndef VP890_OP_FUNC_LEN
+#define VP890_OP_FUNC_LEN           0x01
+#endif
+
+#ifndef VP890_OP_COND_LEN
+#define VP890_OP_COND_LEN           0x01
+#endif
+
+#ifndef VP890_CONV_CFG_LEN
+#define VP890_CONV_CFG_LEN          0x01
+#endif
+
+#ifndef VP890_VP_GAIN_LEN
+#define VP890_VP_GAIN_LEN           0x01
+#endif
+
+#ifndef VP890_DISN_LEN
+#define VP890_DISN_LEN              0x01
+#endif
+
+#ifndef VP890_SYS_STATE_LEN
+#define VP890_SYS_STATE_LEN         0x01
+#endif
+
+#ifndef VP890_GEN_CTRL_LEN
+#define VP890_GEN_CTRL_LEN          0x01
+#endif
+
+#ifndef VP890_DEV_MODE_LEN
+#define VP890_DEV_MODE_LEN          0x01
+#endif
+
+#ifndef VP890_CID_PARAM_LEN
+#define VP890_CID_PARAM_LEN         0x01
+#endif
+
+#ifndef VP890_BAT_CALIBRATION_LEN
+#define VP890_BAT_CALIBRATION_LEN   0x02
+#endif
+
+typedef struct Vp890CalBFilterData {
+    VpCalBFilterType inputData;
+    uint8 b1FiltData[VP890_B1_FILTER_LEN];
+    uint8 b2FiltData[VP890_B2_FILTER_LEN];
+    uint8 opFunct[VP890_OP_FUNC_LEN];
+    uint8 opCond[VP890_OP_COND_LEN];
+    uint8 convCfg[VP890_CONV_CFG_LEN];
+    uint8 vpGain[VP890_VP_GAIN_LEN];
+    uint16 vRms;
+    uint8 listLength;   /* In number of B-Filter coefficient sets */
+    int8 currentSet;    /* Number of currently running B-Filter set */
+    int8 bestSet;       /* Number of the best set so far */
+} Vp890CalBFilterData;
+
+#define VP890_BFILT_SAMPLE_TIME     (70)
+
+/*
+ * IMPORTANT: Make sure to update the "stateInt" member of the device object if
+ * the size of this type changes. There is no instance of this type itself.
+ */
+#define VP890_RESET             (0x0000)    /**< Set at the begining of init device */
+#define VP890_IS_HIGH_VOLTAGE   (0x0010)    /**< Set when device is high voltage device */
+#define VP890_IS_SINGLE_CHANNEL (0x0020)    /**< Set when a single channel device is found*/
+#define VP890_LINE1_IS_FXO      (0x0100)    /**< Set if device detection indicates line1 as FXO */
+#define VP890_WIDEBAND          (0x0200)    /**< Set if device supports Wideband mode */
+#define VP890_LINE0_LP          (0x0400)    /**< Set if line 0 allows low power mode */
+#define VP890_LINE1_LP          (0x0800)    /**< Set if line 1 allows low power mode */
+#define VP890_IS_FXO_ONLY       (0x1000)    /**< Set when the device contains only FXO lines */
+#define VP890_SYS_CAL_COMPLETE  (0x2000)    /**< Set when the system calibration structure has been initialied */
+#define VP890_CAL_RELOAD_REQ    (0x4000)    /**< Set when the line calibration values need to be reloaded. */
+#define VP890_FORCE_FREE_RUN    (0x8000)    /**< Set when app calls VpFreeRun() (start), cleared when called with stop.
+                                             * This prevents the VP-API-II from automatically exiting free run mode
+                                             * upon PCLK recovery.
+                                             */
+
+/**< Line Status types to minimize code space in line object (compared to each
+ * status being maintined by a uint8 type)
+ */
+typedef enum Vp890LineStatusType {
+    VP890_INIT_STATUS   = 0x0000,
+
+    VP890_IS_FXO        = 0x0001,   /**< Set if the line is configured for FXO */
+
+    VP890_BAD_LOOP_SUP  = 0x0002,   /**< Set when the Loop Supervision has been
+                                     * changed in such a way inconsistent with
+                                     * the user's specifications. This is done
+                                     * in internal to the API to make some
+                                     * functions work (e.g., Msg Wait Pulse).
+                                     */
+
+    VP890_DP_SET1_DONE  = 0x0004,   /**< Set when Dial Pulse detection machine
+                                     * is "done" on the current dial pulse using
+                                     * the "first" set of DP parameters
+                                     */
+
+    VP890_DP_SET2_DONE  = 0x0008,   /**< Set when Dial Pulse detection machine
+                                     * is "done" on the current dial pulse using
+                                     * the 2nd set of DP parameters
+                                     */
+
+    VP890_SLS_CALL_FROM_API = 0x0010,   /**< Set if Set Line State is called
+                                         * from an API function (e.g., cadence).
+                                         */
+
+    VP890_LINE_IN_CAL = 0x0020,     /**< Set while line running cal routine */
+
+    VP890_LOW_POWER_EN = 0x0080,    /**< Set when line is operating in low power
+                                     * mode
+                                     */
+
+    VP890_LINE_LEAK = 0x0100,      /**< Set when leakage is detected on the line
+                                    * such that low power mode is prevented.
+                                    */
+    VP890_CHECK_LEAK = 0x0200,     /**< Set when API-II is testing for leakage
+                                    * on the line
+                                    */
+    VP890_INIT_COMPLETE = 0x0800,  /**< Set when InitLine has been completed
+                                    * on this line.
+                                    */
+    VP890_PREVIOUS_HOOK = 0x1000,  /**< Set if Last Hook Event reported was
+                                    * off-hook, cleared if last event was
+                                    * on-hook.
+                                    */
+    VP890_RING_GEN_NORM = 0x2000,  /**< Set when the Generators are known last
+                                    * to be programmed to the application
+                                    * specified ringing profile. Cleared
+                                    * when line tests are run because the same
+                                    * generator is used for non-ringing.
+                                    */
+    VP890_RING_GEN_REV = 0x4000    /**< Set when the Generators are known last
+                                    * to be programmed to the application
+                                    * specified ringing profile. Cleared
+                                    * when line tests are run because the same
+                                    * generator is used for non-ringing.
+                                    */
+} Vp890LineStatusType;
+
+typedef struct Vp890CidCorrectionPair {
+    uint16  volts;
+    uint16  gain;
+} Vp890CidCorrectionPair;
+
+typedef enum Vp890PllRecoveryStateType {
+    VP890_PLL_RECOVERY_ST_RESET,
+    VP890_PLL_RECOVERY_ST_DISABLE,
+    VP890_PLL_RECOVERY_ST_ENABLE_1,
+    VP890_PLL_RECOVERY_ST_ENABLE_2,
+    VP890_PLL_RECOVERY_ST_MEASURE,
+    VP890_PLL_RECOVERY_ST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req*/
+} Vp890PllRecoveryStateType;
+
+typedef struct Vp890CalLoopData {
+    int16 prevVal;
+    uint8 loopNum;
+    uint8 adcLoopMax;
+    uint8 adcRoute;
+} Vp890CalLoopData;
+
+typedef struct Vp890IlaCalData {
+    int16 ilaNorm;
+    int16 ilgNorm;
+} Vp890IlaCalData;
+
+typedef struct Vp890VocCalData {
+    int16 vocNorm;
+    int16 vocRev;
+} Vp890VocCalData;
+
+
+typedef struct Vp890CalTypeData {
+    int16 swyVolt;
+    Vp890CalLoopData loopData;
+    Vp890IlaCalData ilaData;
+    Vp890VocCalData vocData;
+    Vp890CalBFilterData bFilterData;
+} Vp890CalTypeData;
+
+typedef struct Vp890CalLineData {
+    bool calDone;           /**< TRUE when calibration has been performed on
+                             * this line
+                             */
+    bool reversePol;        /**< TRUE if CAL starts in polrev */
+
+    Vp890CalTypeData typeData;
+
+    uint8 codecReg;
+
+    uint8 dcFeedRef[VP890_DC_FEED_LEN];         /* Copied from dc profile */
+    uint8 dcFeed[VP890_DC_FEED_LEN];            /* use for VAS and VOC */
+    uint8 dcFeedPr[VP890_DC_FEED_LEN];          /* use for VAS and VOC */
+
+    uint16 calState;
+    uint8 sysState;
+
+    uint8 icr2[VP890_ICR2_LEN];
+    uint8 icr3[VP890_ICR3_LEN];
+
+    uint8 disnVal[VP890_DISN_LEN];
+    uint8 vpGain[VP890_VP_GAIN_LEN];
+    uint8 loopSup[VP890_LOOP_SUP_LEN];
+
+    bool forceCalDataWrite;
+
+    /* Signal generator calibration temporary backup */
+    uint8 sigGenA[VP890_SIGA_PARAMS_LEN];
+    uint8 calReg[VP890_DC_CAL_REG_LEN];
+    uint8 asscReg;
+
+    /**< Battery Calibration values used to compute final VAS values */
+    uint8 swCal[VP890_BAT_CALIBRATION_LEN];
+
+    uint16 minVas;  /**< Minimum VAS value determined during IMT calibration.
+                     * This is stored in the same format used to compute the VAS
+                     * value rather than the device format. This increases the
+                     * data memory space requirements slightly, but reduces the
+                     * size for code space and simplifies the logic when applied.
+                     */
+    uint16 vasStart;    /**< Used to speedup VAS calibration by providing the
+                         * minimum starting VAS. This value is computed from the
+                         * battery adjustment and minVas (above).
+                         */
+} Vp890CalLineData;
+
+typedef enum Vp890FxoCurrentMonitorStates {
+    VP890_CURRENT_MONITOR_DISABLED,
+    VP890_CURRENT_MONITOR_OFFSET,
+    VP890_CURRENT_MONITOR_BUFFER0,
+    VP890_CURRENT_MONITOR_BUFFER1,
+    VP890_CURRENT_MONITOR_BUFFER2,
+    VP890_CURRENT_MONITOR_BUFFER3,
+    VP890_CURRENT_MONITOR_BUFFER4,
+    VP890_CURRENT_MONITOR_NORMAL
+} Vp890FxoCurrentMonitorStates;
+
+#define VP890_PCM_BUF_SIZE    5
+typedef struct Vp890FxoCurrentMonitorType {
+    Vp890FxoCurrentMonitorStates    stateValue;
+    int16                           currentBuffer[VP890_PCM_BUF_SIZE];
+    int16                           currentOffset;
+
+    uint8                           offsetMeasurements;
+
+    /* This is updated when delta across all data is minimal */
+    int32                           steadyStateAverage;
+
+    /* Set TRUE when last set of data experienced a line transient */
+    bool                            invalidData;
+} Vp890FxoCurrentMonitorType;
+
+typedef struct Vp890FxoLowVoltageMonitorType {
+    bool enabled;
+    uint8 numDisc;
+    uint8 numNotDisc;
+} Vp890FxoLowVoltageMonitorType;
+
+#define VP890_SYS_CAL_POLARITY_LENGTH  2
+#define VP890_SYS_CAL_CHANNEL_LENGTH   1
+
+/* Contains calibration error values -- in +/-10mv LSB */
+typedef struct Vp890SysCalResultsType {
+    int16 abvError[1];
+
+    int16 vocOffset[VP890_SYS_CAL_CHANNEL_LENGTH][VP890_SYS_CAL_POLARITY_LENGTH];
+    int16 vocError[VP890_SYS_CAL_CHANNEL_LENGTH][VP890_SYS_CAL_POLARITY_LENGTH];
+
+    int16 sigGenAError[VP890_SYS_CAL_CHANNEL_LENGTH][VP890_SYS_CAL_POLARITY_LENGTH];
+
+    int16 ila20[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila25[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila32[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 ila40[VP890_SYS_CAL_CHANNEL_LENGTH];
+
+    int16 ilaOffsetNorm[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 ilgOffsetNorm[VP890_SYS_CAL_CHANNEL_LENGTH];
+
+    uint8 vas[VP890_SYS_CAL_CHANNEL_LENGTH][VP890_SYS_CAL_POLARITY_LENGTH];
+
+    int16 vagOffsetNorm[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 vagOffsetRev[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 vbgOffsetNorm[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int16 vbgOffsetRev[VP890_SYS_CAL_CHANNEL_LENGTH];
+
+    int16 swyOffset[VP890_SYS_CAL_CHANNEL_LENGTH];     /**< Used to hold SWY Offset */
+
+    /* Used for capacitance line test only */
+    int32 tipCapCal[VP890_SYS_CAL_CHANNEL_LENGTH];
+    int32 ringCapCal[VP890_SYS_CAL_CHANNEL_LENGTH];
+} Vp890SysCalResultsType;
+
+#define VP890_CAL_STRUCT_SIZE   (18*sizeof(int16) + 2*sizeof(uint8) + 2*sizeof(int32))
+
+/* Vp890 specific Device Object */
+typedef struct Vp890DeviceObjectType {
+    VpDeviceIdType                  deviceId;           /* Device Id indication */
+
+    VpDeviceStaticInfoType          staticInfo;         /**< Info that will not change during runtime. */
+    VpDeviceDynamicInfoType         dynamicInfo;        /**< Info that will change during runtime */
+
+    /* state is a bit-mask of VpDeviceStateType values */
+    uint16                          state;
+
+    /* stateInt is a bit-mask of values */
+    uint16                          stateInt;
+
+    VpOptionEventMaskType           deviceEventsMask;
+    VpOptionEventMaskType           deviceEvents;
+    uint16                          eventHandle;        /** Application defined event handle */
+    uint16                          timeStamp;          /**< Used to track event timing. Increment by ticks */
+    int16                           timeRemainder;
+    VpGetResultsOptionsType         getResultsOption;
+    VpOptionCriticalFltType         criticalFault;
+
+    VpRelGainResultsType            relGainResults;
+
+    /* Used only to reduce MPI traffic (avoid read/modify/write */
+#ifdef VP890_FXS_SUPPORT
+    uint8                           swParamsCache[VP890_REGULATOR_PARAM_LEN];
+    uint8                           switchCtrl[VP890_REGULATOR_CTRL_LEN];
+#endif
+
+    uint8                           devMode[VP890_DEV_MODE_LEN];
+
+    uint16                          devTimer[VP_DEV_TIMER_LAST];
+
+    Vp890DeviceProfileType          devProfileData;
+    VpCSLACDeviceProfileTableType   devProfileTable;
+    VpCSLACProfileTableEntryType    profEntry;
+
+#ifdef VP890_INCLUDE_TESTLINE_CODE
+    VpTestResultType                testResults;
+#endif
+
+    uint8                           intReg[VP890_UL_SIGREG_LEN];  /**< Holds signaling data info for the device */
+    uint8                           intReg2[VP890_UL_SIGREG_LEN];
+
+    uint8                           responseData;   /**< Holds data for Response events on the device */
+
+    uint8                           txBufferDataRate;
+
+#if !defined(VP_REDUCED_API_IF) || defined(ZARLINK_CFG_INTERNAL)
+    uint8                           mpiData[VP890_MAX_MPI_DATA];  /**< Buffer for MPI Low level reads to
+                                                                   * hold maximum amount of MPI data that
+                                                                   * is possible
+                                                                   */
+#endif
+
+    uint8                           mpiLen;       /**< Length of data to be copied into mpiData buffer */
+
+#ifdef VP890_FXS_SUPPORT
+    /*  Two sets of dial pulse specifications are provide to support NTT dial
+     * pulse detection windows of 10pps and 20pps while excluding 15pps */
+    VpOptionPulseType pulseSpecs;
+    VpOptionPulseType pulseSpecs2;
+#endif
+
+    uint8 testDataBuffer[VP890_TEST_DATA_LEN];
+
+#if defined (VP890_INCLUDE_TESTLINE_CODE)
+    Vp890CurrentTestType currentTest;
+    Vp890CalOffCoeffs calOffsets[VP890_MAX_NUM_CHANNELS];
+#endif /* VP890_INCLUDE_TESTLINE_CODE */
+
+#if defined (VP_CC_890_SERIES) || defined (VP_CC_KWRAP)
+    Vp890SysCalResultsType vp890SysCalData;
+#endif
+
+#ifdef VP_DEBUG
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+#endif
+
+    /* Used to hold the device level ecVal (to keep track of WB mode). */
+    uint8 ecVal;
+
+    /*
+     * Holds the last channel information changed to/from Wideband mode since
+     * the last tick. If = 0, no change has been made. If = 1, ch0 if = 2, ch1.
+     * This is a handshake with the tick which detects it is not 0, makes the
+     * appropriate change and sets it back to 0.
+     */
+    uint8 lastCodecChange;
+} Vp890DeviceObjectType;
+
+/* 890 specific Line Object */
+typedef struct Vp890LineObjectType {
+    uint8                           channelId;
+    uint8                           ecVal;
+
+    VpTermType                      termType;
+
+    VpLineIdType                    lineId;             /**< Application provided value for mapping
+                                                         * a user defined type to a line context
+                                                         */
+
+    VpApiIntLineStateType           lineState;          /**< Line state info used for state
+                                                         * transition handling and recall */
+    uint16                          status;             /**< Bit-mask of Vp890LineStatusType */
+
+    VpOptionCodecType               codec;
+
+    /**< Used to delay slic write for LPM or Disconnect handling. */
+    uint8                           nextSlicValue;
+
+   /**< Used to reduce MPI reads. */
+    uint8                           slicValueCache;
+    uint8                           opCond[VP890_OP_COND_LEN];
+
+    VpCslacTimerStruct              lineTimers;         /**< Timers for "this" line */
+    VpOptionEventMaskType           lineEvents;
+    VpOptionEventMaskType           lineEventsMask;
+    uint16                          lineEventHandle;    /**< Line specific event handle information */
+    uint16                          signaling1;
+    uint16                          signaling2;
+
+    uint16                          dtmfDigitSense;     /**< Used to hold the DTMF digit reported
+                                                         * with VpDtmfDigitDetected() until the
+                                                         * VP_LINE_EVID_DTMF_DIG is generated. */
+    uint8                           signalingData;      /**< Holds data for Signaling events on this line */
+    uint16                          processData;        /**< Holds data for Process events on this line */
+    uint16                          responseData;       /**< Holds data for Response events on this line */
+
+#ifdef VP890_FXO_SUPPORT
+    uint8                           fxoData;            /**< Holds data for FXO events on this line */
+    uint8                           fxoRingStateFlag;   /**< Indicates a state change request during ringing,
+                                                             to be serviced when ringing is over */
+    VpLineStateType                 fxoRingState;       /**< State to change to when ringing is over */
+
+    VpCslacLineCondType             preDisconnect;      /**< The disconnect state prior to timer start */
+
+    VpDigitGenerationDataType       digitGenStruct;     /**< Used on FXO lines for
+                                                         * generating pulse digits */
+
+    uint8                           ringDetMax;         /**< Stores the user specified maximum
+                                                         * ringing detect period for FXO lines. This
+                                                         * value may be outside the device range, in
+                                                         * which case the SW will implement upper
+                                                         * period detection */
+
+    uint8                           ringDetMin;         /**< Stores the user specified maximum
+                                                         * ringing detect period for FXO lines that
+                                                         * is within the device range. This value is
+                                                         * used as "minimum" that is detected by SW.
+                                                         * Actual minimum period is supported by the
+                                                         * device period detector itself. */
+
+    uint8                           dPoh;               /**< Stores the user specified parallel
+                                                         * offhook integration time for use
+                                                         * in timing for the POH event */
+
+    uint8                           userDtg;             /* User-configured DTG setting */
+    uint8                           cidDtg;              /* DTG register setting for CID
+                                                          * correction */
+    int8                            cidCorrectionSample; /* Last line voltage sample for CID
+                                                          * correction */
+    uint8                           cidCorrectionCtr;    /* Counter for CID correction line
+                                                          * voltage samples */
+    Vp890PllRecoveryStateType       pllRecoveryState;    /* State for the pll issue fix */
+    uint8                           pllRecoverAttempts;    /* Number if pll recovery retries */
+
+    Vp890FxoCurrentMonitorType      currentMonitor;
+    Vp890FxoLowVoltageMonitorType   lowVoltageDetection;
+#endif
+
+#ifdef VP890_FXS_SUPPORT
+    /*
+     * Array to hold ringing parameters used in the Signal Generator.  This is
+     * needed when signal generator A is set to a tone, then set back to ringing
+     * without the user re-specifying the ringing profile
+     */
+    uint8                           ringingParams[VP890_SIGA_PARAMS_LEN];
+
+    VpProfilePtrType                pRingingCadence;    /**< Currently used ringing cadence on
+                                                         * this line */
+
+    VpOptionRingControlType         ringCtrl;
+
+    VpProfilePtrType                pCidProfileType1;   /**< Currently used caller ID profile
+                                                         * on this line for sequenced cid */
+
+    VpDialPulseDetectType           dpStruct;           /**< Used on FXS lines for detecting pulse
+                                                         * digits*/
+
+    VpDialPulseDetectType           dpStruct2;          /**< Used on FXS lines for detecting pulse
+                                                         * digits using 2nd set of dp specs. */
+
+    VpOptionPulseModeType           pulseMode;
+
+    VpRelayControlType              relayState;    /* Used to hold current line
+                                                    * relay state */
+
+    uint8 dcCalValues[VP890_DC_CAL_REG_LEN];
+
+    /* Loop supervision parameters */
+    uint8 hookHysteresis;
+
+    bool internalTestTermApplied;
+#endif
+
+    Vp890CalLineData                calLineData;    /* Data used during VpCalLine() */
+
+    /* Holds user definition for Loop Supervision configuration when
+     * "badLoopSup" is TRUE */
+    uint8                           loopSup[VP890_LOOP_SUP_LEN];
+
+    VpOptionPcmTxRxCntrlType        pcmTxRxCtrl;   /* Defines how the PCM highway is
+                                                    * set for "talk" linestates */
+
+    /*
+     * NOTE: Do not move the location or name of gx/grBase members. These may be
+     * used by applications to determine the gain of the GX/GR blocks in the
+     * AC profile. Using return from VpSetRelGain() is not usefull because that
+     * is the register setting. The customer would have to know how to convert
+     * that to linear values, which is not generally documented.
+     */
+    uint16                          gxBase;       /**< Cached GX register, in 2.14 int format */
+    uint16                          gxCidLevel;   /**< GX Caller ID correction factor (2.14) */
+    uint16                          gxUserLevel;  /**< User specified relative GX level (2.14) */
+    uint16                          grBase;       /**< Cached GR register, in 2.14 int format */
+    uint16                          grUserLevel;  /**< User specified relative GR level (2.14) */
+
+    int16 absGxGain; /**< Cached ABS A-to-D Gain, simplifies code. */
+    int16 absGrGain; /**< Cached ABS D-to-A Gain, simplifies code. */
+
+#ifdef VP_CSLAC_SEQ_EN
+#ifdef VP890_FXS_SUPPORT
+    VpCallerIdType                  callerId; /**< Caller ID related information */
+    VpCidSeqDataType                cidSeq;   /**< CID Sequencer related information */
+
+    bool                            suspendCid;
+    uint8                           tickBeginState[VP890_CID_PARAM_LEN];
+    uint8                           cidBytesRemain;
+    bool                            delayConsumed; /**< Set to TRUE when Polling Mode CID uses the
+                                                    * loop read/delay method and has started it.
+                                                    */
+#endif
+
+    VpSeqDataType                   cadence;  /**< Sequencer related information */
+
+    /**< Array to control internally run sequences */
+    VpProfileDataType               intSequence[VP890_INT_SEQ_LEN];
+#endif
+
+#ifdef VP890_LP_SUPPORT
+    uint8 leakyLineCnt; /*
+                         * Keeps track of # of times off-hook was detected (LP Mode)
+                         * that was not further verified after exiting LP Mode. Reset
+                         * when off-hook is verified.
+                         */
+#endif
+
+#ifdef VP890_FXS_SUPPORT
+    VpHowlerModeCachedValues howlerModeCache;
+
+    uint8 icr2Values[VP890_ICR2_LEN];   /**< Cached to minimize device access */
+    uint8 icr3Values[VP890_ICR3_LEN];   /**< Cached to minimize device access */
+    uint8 icr4Values[VP890_ICR4_LEN];   /**< Cached to minimize device access */
+#endif
+
+    /* Used in FXO PLL Recovery, FXS Line Test,  and FXS Generic and Low Power Mode Control */
+    uint8 icr1Values[VP890_ICR1_LEN];   /**< Cached to minimize device access */
+
+    uint8 sigGenCtrl[VP890_GEN_CTRL_LEN];   /**< Cached to minimize device access */
+
+#ifdef VP_DEBUG
+    /* For runtime enabling of debug output: */
+    uint32 debugSelectMask;
+#endif
+
+} Vp890LineObjectType;
+
+#endif /* VP890_API_H */
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_CSLAC_types.h b/tools/voice/zarlink/user/api_lib/includes/vp_CSLAC_types.h
new file mode 100644
index 0000000..23c7247
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_CSLAC_types.h
@@ -0,0 +1,620 @@
+/** \file vp_CSLAC_types.h
+ * vp_CSLAC_types.h
+ *
+ * Header file for internal variables used in CSLAC type API.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9103 $
+ * $LastChangedDate: 2011-11-14 11:15:45 -0600 (Mon, 14 Nov 2011) $
+ */
+
+#ifndef VP_CSLAC_TYPES_H
+#define VP_CSLAC_TYPES_H
+
+#include "vp_api_fxo_params.h"
+#include "vp_api_timer.h"
+
+#define VP_CSLAC_DEV_PROFILE_VERSION_INT_SW_CONFIG_FR   5
+#define VP_CSLAC_DEV_PROFILE_VERSION_INT_SW_CONFIG      4
+#define VP_CSLAC_DEV_PROFILE_VERSION_LINECARD_PARAM     3
+#define VP_CSLAC_DEV_PROFILE_VERSION_VBH_REG            2
+#define VP_CSLAC_DEV_PROFILE_VERSION_SW_CONFIG          1
+
+#define VP_CSLAC_FXO_VERSION_DTMF_LEVEL                 1
+#define VP_CSLAC_FXO_VERSION_POH                        2
+
+#define VP_CSLAC_DC_PROFILE_VERSION_890                 1
+
+#define VP_CSLAC_RING_PROFILE_VERSION_890               1
+
+#define VP_CSLAC_TICKSTEP_0_5MS     (0x80)      /**< CSLAC Tickrate for 0.5mS */
+#define VP_CSLAC_TICKSTEP_1MS       (0x100)     /**< CSLAC Tickrate for 1mS */
+
+#define VP_CID_TIMESCALE    1   /**< Timescale in mS for CID time data */
+
+#define VP_CSLAC_DEV_PROF_TABLE_SIZE            1
+#define VP_CSLAC_AC_PROF_TABLE_SIZE             2
+#define VP_CSLAC_DC_PROF_TABLE_SIZE             2
+#define VP_CSLAC_RINGING_PROF_TABLE_SIZE        2
+#define VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE   11
+#define VP_CSLAC_TONE_PROF_TABLE_SIZE           10
+#define VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE   4
+#define VP_CSLAC_METERING_PROF_TABLE_SIZE       2
+#define VP_CSLAC_CALLERID_PROF_TABLE_SIZE       2
+#define VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE     1
+#define VP_CSLAC_CUSTOM_TERM_PROF_TABLE_SIZE    4
+
+/* Special Howler Bit-Mask 'xxxx 11xx' */
+#define VP_CSLAC_SPECIAL_TONE_MASK  (0x0C)
+#define VP_CSLAC_STD_TONE           (0x00)
+#define VP_CSLAC_HOWLER_TONE        (0x04)  /* UK BTNR 1080 Specification */
+#define VP_CSLAC_AUS_HOWLER_TONE    (0x08)
+#define VP_CSLAC_NTT_HOWLER_TONE    (0x0C)
+
+#define VP_CSLAC_TONE_TYPE         5
+
+#define VP_CSLAC_READ_RESPONSE_MASK (VP_LINE_EVID_LLCMD_RX_CMP \
+                                   | VP_LINE_EVID_RD_OPTION \
+                                   | VP_LINE_EVID_GAIN_CMP)
+
+typedef struct VpCSLACDeviceProfileTableType {
+    VpProfilePtrType pDevProfileTable[VP_CSLAC_DEV_PROF_TABLE_SIZE];
+    VpProfilePtrType pAcProfileTable[VP_CSLAC_AC_PROF_TABLE_SIZE];
+    VpProfilePtrType pDcProfileTable[VP_CSLAC_DC_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingingProfileTable[VP_CSLAC_RINGING_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneCadProfileTable[VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneProfileTable[VP_CSLAC_TONE_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingingCadProfileTable[VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pMeteringProfileTable[VP_CSLAC_METERING_PROF_TABLE_SIZE];
+    VpProfilePtrType pCallerIdProfileTable[VP_CSLAC_CALLERID_PROF_TABLE_SIZE];
+    VpProfilePtrType pFxoConfigProfileTable[VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE];
+    VpProfilePtrType pCustomTermProfileTable[VP_CSLAC_CUSTOM_TERM_PROF_TABLE_SIZE];
+} VpCSLACDeviceProfileTableType;
+
+/**
+ * The following structure is used by the device as a bitmask indicating
+ * whether or not a given profile table entry is valid. In the bit location a
+ * value '1' = profile is current, '0' = profile is not current.
+ */
+typedef struct VpCSLACProfileTableEntryType {
+    uint16 devProfEntry;
+    uint16 acProfEntry;
+    uint16 dcProfEntry;
+    uint16 ringingProfEntry;
+    uint16 toneCadProfEntry;
+    uint16 toneProfEntry;
+    uint16 ringCadProfEntry;
+    uint16 meterProfEntry;
+    uint16 cidCadProfEntry;
+    uint16 fxoConfigProfEntry;
+    uint16 customTermProfEntry;
+} VpCSLACProfileTableEntryType;
+
+#define VP_PROF_ENTRY_INVALID   0
+#define VP_PROF_ENTRY_VALID     1
+
+typedef union VpGetResultsOptionsDataType {
+    VpOptionCriticalFltType criticalFaultOption;
+    VpOptionEventMaskType eventMaskOption;
+    VpOptionPulseModeType pulseModeOption;
+    VpOptionPulseType pulseTypeOption;
+    VpOptionRingControlType ringControlOption;
+    VpOptionZeroCrossType zeroCross;
+    VpOptionTimeslotType timeSlotOption;
+    VpOptionCodecType codecOption;
+    VpOptionPcmHwyType pcmHwyOption;
+    VpOptionLoopbackType loopBackOption;
+    VpOptionLineStateType lineStateOption;
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;
+    VpDeviceIoAccessDataType deviceIoData;
+    VpOptionDeviceIoType deviceIo;
+    VpLoopCondResultsType loopCond;
+    bool autoShutdownEn;
+    VpOptionAbsGainType absGain;
+} VpGetResultsOptionsDataType;
+
+typedef struct VpGetResultsOptionsType {
+    VpGetResultsOptionsDataType optionData;
+    uint8 chanId;
+    VpOptionIdType optionType;
+} VpGetResultsOptionsType;
+
+#define VP_CID_DTMF_ON_TIME    70   /**< Nominal 70mS +/- 5mS */
+#define VP_CID_DTMF_OFF_TIME   70   /**< Minimum 65mS */
+
+typedef enum VpCidGeneratorControlType {
+    VP_CID_GENERATOR_DATA,
+    VP_CID_GENERATOR_KEYED_CHAR,
+    VP_CID_SIGGEN_EOT,
+    VP_CID_NO_CHANGE,           /**< Load tones only, do not change generator
+                                 * state
+                                 */
+    VP_CID_GENERATOR_MARKOUT,
+    VP_CID_CTRL_TYPE_CNT,
+
+    VP_CID_GENC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCidGeneratorControlType;
+
+/* Previously VpCidStatusFlagType values */
+#define VP_CID_RESET_VALUE  (0x0000)
+
+#define VP_CID_IS_DEBOUNCE  (0x0001)    /**< Set when debounce has expired */
+#define VP_CID_CLIAWAITTONE (0x0002)
+#define VP_CID_REPEAT_MSG   (0x0004)
+#define VP_CID_AWAIT_TONE   (0x0008)    /**< Set if waiting for CPE ACK Tone */
+
+#define VP_CID_TERM_FSK     (0x0010)    /**< Set if stopping FSK generator */
+#define VP_CID_END_OF_MSG   (0x0020)    /**< Set if API detects an end of
+                                         * message in the buffered data
+                                         */
+
+#define VP_CID_FSK_GEN_VALID    (0x0040)    /**< Set if FSK Generator is programmed
+                                             * for Caller ID signals.
+                                             */
+
+#define VP_CID_IN_PROGRESS      (0x0080)    /**< Set if Caller ID is in progress */
+#define VP_CID_ACTIVE_RING_SEQ  (0x0100)    /**< Set if active CID Ring sequence */
+
+#define VP_CID_PRIMARY_FULL     (0x0200)    /**< Set when primary buffer contains
+                                             * CID data
+                                             */
+#define VP_CID_SECONDARY_FULL   (0x0400)    /**< Set when secondary buffer contains
+                                             * CID data
+                                             */
+#define VP_CID_PRIMARY_IN_USE   (0x0800)    /**< Set when primary buffer in use */
+#define VP_CID_SECONDARY_IN_USE (0x1000)    /**< Set when secondary buffer in use */
+#define VP_CID_WAIT_ON_ACTIVE   (0x2000)    /**< Set when a "wait on" mode is
+                                             * active. Should only be cleared in
+                                             * the timer function (since currently
+                                             * support only for Wait on CID or time
+                                             */
+#define VP_CID_MID_CHECKSUM     (0x4000)    /**< Set when a checksum value is being
+                                             * sent.
+                                             */
+#define VP_CID_MUTE_ON      (0x8000)    /**< Set when a "Mute On" CID operator
+                                         * is active.
+                                         */
+#define VP_CID_FSK_ACTIVE   (0x10000)   /**< Set while the FSK Generator is needed */
+
+
+typedef enum VpCidDtmfStatusType {
+    VP_CID_DTMF_RESET_VALUE = 0,
+    VP_CID_ACTIVE_ON_TIME = 1,
+    VP_CID_ACTIVE_OFF_TIME = 2
+} VpCidDtmfStatusType;
+
+/** Caller ID variables used by the line */
+typedef struct VpCallerIdType {
+    uint32 status;  /**< 'OR'ed combination of VpCidStatusFlagType */
+
+    VpCidDtmfStatusType dtmfStatus; /**< Used only for DTMF CID Message Data */
+
+    uint16 cliTimer;        /**< Time in increments of device ticks */
+    uint8 currentData;      /**< Data to repeat on the line */
+    uint16 cidCheckSum;     /**< Checksum to append to message data */
+
+    uint8 cliDebounceTime;  /**< Hook debouce specified in device ticks */
+    VpProfilePtrType pCliProfile;   /**< Currently running CID Profile */
+
+    VpDigitType cliDetectTone1;
+    VpDigitType cliDetectTone2;
+
+    uint8 cliMPIndex;       /**< Current Index into primary message buffer */
+    uint8 cliMSIndex;       /**< Current Index into secondary message buffer */
+
+    uint8 cliIndex;         /**< Current Index into profile data */
+
+    uint8 primaryBuffer[VP_SIZEOF_CID_MSG_BUFFER];
+    uint8 secondaryBuffer[VP_SIZEOF_CID_MSG_BUFFER];
+
+    uint8 primaryMsgLen;    /**< Length of data in the primary buffer */
+    uint8 secondaryMsgLen;  /**< Length of data in the secondary buffer */
+    VpDigitType digitDet;   /**< Stores the last DTMF digit detected during
+                             * Caller ID (if enabled via tone detection).
+                             */
+    uint8 messageDataRemain;    /**< Tracks the total number of message bytes remaining */
+
+    /*
+     * At the end of FSK Message Data, some systems require a mark-out time. As
+     * specified in the Profile Wizard, this is defined in # of bytes with each
+     * byte corresponding to 8.33ms (1200 baud with 1 start + 1 stop + 8 data
+     * bits = 10/1200 = 8.33ms).
+     */
+    uint8 markOutByteCount;     /* Retains the value specified in the profile */
+    uint8 markOutByteRemain;    /* Current value remaining. Clean up when = 0 */
+} VpCallerIdType;
+
+typedef enum VpCadenceStatusType {
+    VP_CADENCE_RESET_VALUE = 0x0,
+    VP_CADENCE_STATUS_ACTIVE = 0x1,
+    VP_CADENCE_STATUS_BRANCHING  = 0x2,
+    VP_CADENCE_STATUS_MID_TIMER  = 0x4,
+    VP_CADENCE_STATUS_SENDSIG  = 0x8,
+    VP_CADENCE_STATUS_METERING = 0x10,
+    VP_CADENCE_STATUS_BRANCHING_LVL2  = 0x20,
+    VP_CADENCE_STATUS_IGNORE_POLARITY = 0x40
+} VpCadenceStatusType;
+
+/** Variables to control the cadence on the line using the Sequencer */
+#define VP_CSLAC_MAX_BRANCH_DEPTH   2
+#define VP_CSLAC_BRANCH_LVL_0       0
+#define VP_CSLAC_BRANCH_LVL_1       1
+
+typedef struct VpSeqDataType {
+    VpProfilePtrType pActiveCadence;    /**< Currently Active Cadence */
+    VpProfilePtrType pCurrentPos;       /**< Current position in profile */
+
+    VpCadenceStatusType status;
+
+    uint8 index;        /**< Index in the the cadence table   */
+    uint8 length;       /**< Length of executable cadence instructions */
+
+    /**< Remaining number of repeats to perform for each branch depth */
+    uint8 count[VP_CSLAC_MAX_BRANCH_DEPTH];
+
+    uint16 timeRemain;
+    uint8 branchAt;     /**< Outermost step we're branching */
+    uint16 meteringBurst;   /**< Tracks the number of metering pulses sent */
+    bool meterPendingAbort; /**< Indicates that metering should abort after the
+                             * current pulse ends */
+    VpLineStateType meterAbortLineState; /**< The line state that should be set
+                                          * when metering aborts */
+
+    /* The following variables are for controlling signal generator ramp */
+#define VPCSLAC_MAX_GENERATOR_DATA 11
+    uint8 regData[VPCSLAC_MAX_GENERATOR_DATA];  /**< Scratchpad to reduce MPI
+                                                 * traffic.
+                                                 */
+    /*
+     * These values should correspond to device specific values for the
+     * freqency/level being set -- not a generic value.
+     */
+    uint16 startFreq;
+    bool isFreqIncrease;
+    uint16 stopFreq;
+    uint16 freqStep;
+
+    uint16 startLevel;
+    uint16 stopLevel;
+    uint16 levelStep;
+    uint8  toneType;
+} VpSeqDataType;
+/*
+ * Used to save values of registers that will be modified for Special Howler Tones. These
+ * tones require very high amplitude which can be done on VE880/890 using some back-door
+ * controls. Note that VE880/890 have the same command set in the case of these registers
+ */
+#define VP_CSLAC_ICR1_LEN       (4)
+#define VP_CSLAC_ICR2_LEN       (4)
+#define VP_CSLAC_ICR3_LEN       (4)
+#define VP_CSLAC_ICR4_LEN       (4)
+#define VP_CSLAC_DC_FEED_LEN    (2)
+#define VP_CSLAC_VP_GAIN_LEN    (1)
+#define VP_CSLAC_GR_LEN         (2)
+#define VP_CSLAC_R_LEN          (14)
+#define VP_CSLAC_DISN_LEN       (1)
+#define VP_CSLAC_OP_FUNC_LEN    (1)
+#define VP_CSLAC_SW_REG_LEN     (3)
+
+typedef struct VpHowlerModeCachedValues {
+    bool isInHowlerMode;    /**< Set to TRUE when in Howler Mode and values below are good */
+
+    uint8 icr1Reg[VP_CSLAC_ICR1_LEN];   /**< ICR1 = 0xEC/ED */
+    uint8 icr2Reg[VP_CSLAC_ICR2_LEN];   /**< ICR2 = 0xEE/EF */
+    uint8 icr3Reg[VP_CSLAC_ICR3_LEN];   /**< ICR3 = 0xF2/F3 */
+    uint8 icr4Reg[VP_CSLAC_ICR4_LEN];   /**< ICR4 = 0xEC/ED */
+    uint8 dcFeed[VP_CSLAC_DC_FEED_LEN];
+
+    uint8 digitalRxLoss[VP_CSLAC_VP_GAIN_LEN];  /**< VP Gain Reg - only changing Digital RX Loss */
+    uint8 grValue[VP_CSLAC_GR_LEN];
+    uint8 rValue[VP_CSLAC_R_LEN];
+
+    uint8 disn[VP_CSLAC_DISN_LEN];
+
+    /*
+     * Z and B will be disabled using the Operating Function Register instead of writing
+     * "disable" coefficients. Obviously - less MPI traffic by at least 33 bytes
+     */
+    uint8 opFunc[VP_CSLAC_OP_FUNC_LEN]; /**< Only disabling Z and B Filters */
+
+    uint8 swReg[VP_CSLAC_SW_REG_LEN];   /**< Used to change Tracking floor voltge to -30V */
+} VpHowlerModeCachedValues;
+
+/** Variables to control the CID sequence on the line using the CID Sequencer */
+typedef struct VpCidSeqDataType {
+    VpProfilePtrType pActiveCadence;    /**< Currently Active Cadence */
+    VpProfilePtrType pCurrentPos;       /**< Current position in profile */
+
+    uint8 index;        /**< Index in the the cadence table   */
+    uint16 timeRemain;
+} VpCidSeqDataType;
+
+typedef VpStatusType
+(*VpSeqInstructionFuncPtrType) (
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSequenceData);
+
+#define VP_SEQ_OPERATOR_MASK 0xE0
+#define VP_SEQ_SUBTYPE_MASK  0x1F
+#define VP_SEQUENCER_TICKRATE   0x0500  /* 5mS - Used with MS_TO_TICKRATE */
+
+/**< The super commands are the upper 3 bits of the command byte and therefore should never be
+ * used with types exceeding 8-bit
+ */
+#define VP_SEQ_SPRCMD_COMMAND_INSTRUCTION   (0x00)
+#define VP_SEQ_SPRCMD_TIME_INSTRUCTION      (0x20)
+#define VP_SEQ_SPRCMD_BRANCH_INSTRUCTION    (0x40)
+
+/**< The sub commands are the lower 5 bits of the command byte */
+#define VP_SEQ_SUBCMD_SIGGEN            (0x00)
+#define VP_SEQ_SUBCMD_LINE_STATE        (0x01)
+#define VP_SEQ_SUBCMD_START_CID         (0x02)
+#define VP_SEQ_SUBCMD_WAIT_ON           (0x07)  /**< Wait for CID or time to continue */
+
+#define VP_SEQ_SUBCMD_RAMP_GENERATORS   (0x08)  /**< Forces frequency/amplitude change of the tone
+                                                 * generator. Tone Cadence associated with this
+                                                 * command must be specified as "ramp" type.
+                                                 */
+
+    /**< API Internal Use only operators */
+#define VP_SEQ_SUBCMD_METERING      (0x10)  /**< Cadence Metering */
+
+    /**< Bit-Fields for Tone Generator Control (see Profile Wizard Spec). */
+#define VP_SEQ_SIGGEN_ALL_DISABLED  (0x00)
+#define VP_SEQ_SIGGEN_A_EN          (0x01)
+#define VP_SEQ_SIGGEN_B_EN          (0x02)
+#define VP_SEQ_SIGGEN_C_EN          (0x04)
+#define VP_SEQ_SIGGEN_D_EN          (0x08)
+
+/**< Definition for the states in the Profile Wizard output. These must always be used/accessed
+ * as uint8 types. Do everything possible to create compiler errors if they're used any differently
+ */
+typedef uint8 VpProfileCadencerStateTypes;
+#define VP_PROFILE_CADENCE_STATE_STANDBY            ((VpProfileCadencerStateTypes)0)
+#define VP_PROFILE_CADENCE_STATE_TIP_OPEN           ((VpProfileCadencerStateTypes)1)
+#define VP_PROFILE_CADENCE_STATE_TALK               ((VpProfileCadencerStateTypes)2)
+#define VP_PROFILE_CADENCE_STATE_ACTIVE             ((VpProfileCadencerStateTypes)3)
+#define VP_PROFILE_CADENCE_STATE_RSVD               ((VpProfileCadencerStateTypes)4)
+#define VP_PROFILE_CADENCE_STATE_OHT                ((VpProfileCadencerStateTypes)5)
+#define VP_PROFILE_CADENCE_STATE_DISCONNECT         ((VpProfileCadencerStateTypes)6)
+#define VP_PROFILE_CADENCE_STATE_RINGING            ((VpProfileCadencerStateTypes)7)
+#define VP_PROFILE_CADENCE_STATE_POLREV_STANDBY     ((VpProfileCadencerStateTypes)8)
+#define VP_PROFILE_CADENCE_STATE_POLREV_TIP_OPEN    ((VpProfileCadencerStateTypes)9)
+#define VP_PROFILE_CADENCE_STATE_POLREV_TALK        ((VpProfileCadencerStateTypes)10)
+#define VP_PROFILE_CADENCE_STATE_POLREV_ACTIVE      ((VpProfileCadencerStateTypes)11)
+#define VP_PROFILE_CADENCE_STATE_POLREV_RSVD        ((VpProfileCadencerStateTypes)12)
+#define VP_PROFILE_CADENCE_STATE_POLREV_OHT         ((VpProfileCadencerStateTypes)13)
+#define VP_PROFILE_CADENCE_STATE_POLREV_DISCONNECT  ((VpProfileCadencerStateTypes)14)
+#define VP_PROFILE_CADENCE_STATE_POLREV_RINGING     ((VpProfileCadencerStateTypes)15)
+#define VP_PROFILE_CADENCE_STATE_FXO_OHT            ((VpProfileCadencerStateTypes)16)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_OPEN      ((VpProfileCadencerStateTypes)17)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_CLOSE     ((VpProfileCadencerStateTypes)18)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_TALK      ((VpProfileCadencerStateTypes)19)
+#define VP_PROFILE_CADENCE_STATE_MSG_WAIT_NORM      ((VpProfileCadencerStateTypes)20)
+#define VP_PROFILE_CADENCE_STATE_MSG_WAIT_POLREV    ((VpProfileCadencerStateTypes)21)
+#define VP_PROFILE_CADENCE_STATE_UNKNOWN            ((VpProfileCadencerStateTypes)255)
+
+/* struct VpDialPulseDetectType is for FXS lines when detecting digits */
+typedef enum VpDialPulseDetectStatesType {
+    VP_DP_DETECT_STATE_LOOP_OPEN = 0,
+    VP_DP_DETECT_STATE_LOOP_CLOSE = 1,
+    VP_DP_DETECT_STATE_IDLE = 2
+} VpDialPulseDetectStatesType;
+
+typedef struct VpDialPulseDetectType {
+    int digits;
+    uint16 lo_time;
+    uint16 lc_time;
+    VpDialPulseDetectStatesType state;   /**< Dial Pulse State Machine state */
+    bool hookSt;
+    uint8 signalingData;
+} VpDialPulseDetectType;
+
+/* struct VpDigitGenerationDataType is for FXO lines when generating digits */
+typedef struct VpDigitGenerationDataType {
+    uint16 dtmfOnTime;
+    uint16 dtmfOffTime;
+    uint8 breakTime;
+    uint8 makeTime;
+    uint16 flashTime;
+    uint16 dpInterDigitTime;
+    uint8 dtmfHighFreqLevel[2];
+    uint8 dtmfLowFreqLevel[2];
+} VpDigitGenerationDataType;
+
+/** Virtual Device Registers - Used to reduce MPI accesses to the Device */
+typedef struct VpVirtualDeviceReg {
+    uint8 sigRegMSB;    /**< Signaling Register's Most Significant byte */
+    uint8 sigRegLSB;    /**< Signaling Register's Least Significant byte */
+    uint8 iMaskMSB;     /**< Interrupt mask for the current line */
+    uint8 iMaskLSB;     /**< Interrupt mask for the current line */
+    uint8 iMaskMSBSP;   /**< Interrupt mask for the current line */
+    uint8 iMaskLSBSP;   /**< Interrupt mask for the current line */
+    uint8 ccR1SP;
+    uint8 ccR5SP;       /**< Scratchpad for CCR5 used during metering */
+    uint8 ccR8SP;       /**< Scratchpad for CCR8 used during calibration */
+    uint8 ioReg;        /**< IO Register for QSLAC SLIC states */
+} VpVirtualDeviceReg;
+
+/**<
+ * IMPORTANT: Make sure to update the type used for "state" member inside
+ * objects, structs, and passed to functions where the comment states the value
+ * is a bit-mask of "VpDeviceStateType". Seach by "VpDeviceStateType".
+ * There are no instance of this type itself.
+ */
+typedef enum VpDeviceStateType {
+    /**< Indicates if function is running from InitDevice. Not the same as in
+     * the middle of an initialization process (including calibration). Used to
+     * allow InitDevice function calling other functions to be enabled. Otherwise,
+     * some functions will return "Device Not Initialized" error.
+     */
+    VP_DEV_INIT_IN_PROGRESS = 0x0001,
+
+    VP_DEV_INIT_CMP = 0x0002,    /**< Set if device has been initialized */
+    VP_DEV_IN_CAL = 0x0004,      /**< Set if device is busy calibrating */
+    VP_DEV_PENDING_INT = 0x0008, /**< Set if there is a pending interrupt */
+
+    VP_DEV_ABS_BAT_CAL = 0x0010, /**< Set when running ABS (batt switch) Cal */
+    VP_DEV_ABV_CAL = 0x0020,     /**< Set when running ABV Calibration on Tracker */
+    VP_DEV_ABV_CAL_ABS = 0x0040, /**< Set when running ABV Calibration on ABS */
+    VP_DEV_DISC_PENDING = 0x0080, /**< Set when a Disconnect Timer was suspsended */
+
+    VP_DEV_TEST_BUFFER_READ = 0x0100, /**< Set if test buffer was read this tick */
+
+     /**< Set if device in process of warm reboot. Note that warm reboot
+      * detection alone only helps skipping of VpCalCodec() because it is run
+      * with VpInitDevice(). But it does not ensure that VpCalLine() was
+      * previously run.
+      */
+    VP_DEV_WARM_REBOOT = 0x0200
+
+} VpDeviceStateType;
+
+typedef struct VpCSLACDeviceStatusType {
+    uint16 state;           /**< This is a bit-mask of VpDeviceStateType values */
+    uint8 globStatReg;      /**< Holds state of the device stat reg */
+    uint8 calibrating;      /**< Calibration timer */
+    uint8 numIntServiced;   /**< Max interrupts to be serviced during tick */
+} VpCSLACDeviceStatusType;
+
+#define VP_CSLAC_MAX_RCN_PCN_SIZE   2
+typedef struct VpDeviceStaticInfoType {
+    uint8 rcnPcn[VP_CSLAC_MAX_RCN_PCN_SIZE];    /**< Revision Code Number and
+                                                 * Product Code Number as
+                                                 * applicable
+                                                 */
+    uint8 maxChannels;  /**< How many lines supported by this device */
+} VpDeviceStaticInfoType;
+
+typedef struct VpDeviceDynamicInfoType {
+    uint8 lastChan;     /**< The last line checked */
+    bool clkFault;      /** TRUE if a clock fault is active */
+    bool bat1Fault;     /** TRUE if a bat1 fault is active and device level */
+    bool bat2Fault;     /** TRUE if a bat2 fault is active and device level */
+    bool bat3Fault;     /** TRUE if a bat3 fault is active and device level */
+} VpDeviceDynamicInfoType;
+
+/** Line state variables used by the line (api internal) */
+#ifdef STRICT_SIGNED_ENUM_VALUES
+typedef uint16 VpCslacLineCondType;
+
+#define VP_CSLAC_STATUS_INVALID     (0x0000)
+
+/* FXS Type Status */
+#define VP_CSLAC_HOOK   (0x0001)
+#define VP_CSLAC_GKEY   (0x0002)
+
+/* FXO Type Status */
+#define VP_CSLAC_RAW_DISC   (0x0001)
+#define VP_CSLAC_RINGING    (0x0004)
+#define VP_CSLAC_DISC       (0x0008)
+
+#define VP_CSLAC_AC_FLT     (0x0010)
+#define VP_CSLAC_DC_FLT     (0x0020)
+#define VP_CSLAC_THERM_FLT  (0x0040)
+#define VP_CSLAC_CAL_ENABLE (0x0080)
+
+#define VP_CSLAC_CAL_FAIL           (0x0100)
+#define VP_CSLAC_POLREV             (0x0200)
+#define VP_CSLAC_POLREV_REPORTED    (0x0400)
+#define VP_CSLAC_LIU                (0x0800)
+
+#define VP_CSLAC_LINE_LEAK_TEST (0x1000)
+#define VP_CSLAC_RING_AMP_DET   (0x2000)
+#define VP_CSLAC_RINGING_EXIT   (0x4000)
+#define VP_CSLAC_STATUS_VALID   (0x8000)
+#else
+typedef enum VpCslacLineCondType {
+    VP_CSLAC_STATUS_INVALID = 0x0000,
+
+    /* FXS Type Status */
+    VP_CSLAC_HOOK = 0x0001,
+    VP_CSLAC_GKEY = 0x0002,
+
+    /* FXO Type Status */
+    VP_CSLAC_RAW_DISC = 0x0001,     /*
+                                     * Set on 890 when device level disconnect
+                                     * status is set. Cleared otherwise.
+                                     */
+
+    VP_CSLAC_RINGING = 0x0004,      /**< Set when Ringing detected on Line */
+    VP_CSLAC_DISC = 0x0008,         /**< Set when Disconnect detected on Line */
+
+    VP_CSLAC_AC_FLT = 0x0010,
+    VP_CSLAC_DC_FLT = 0x0020,
+    VP_CSLAC_THERM_FLT = 0x0040,
+    VP_CSLAC_CAL_ENABLE = 0x0080,   /**< Set when the line is in a state that
+                                     * will allow device calibration
+                                     */
+
+    VP_CSLAC_CAL_FAIL = 0x0100,
+    VP_CSLAC_POLREV = 0x0200,
+    VP_CSLAC_POLREV_REPORTED = 0x0400,
+    VP_CSLAC_LIU = 0x0800,
+
+    VP_CSLAC_LINE_LEAK_TEST = 0x1000,   /**< Set when line is being tested for
+                                         * resistive leak. Clear when test is
+                                         * complete.
+                                         */
+    VP_CSLAC_RING_AMP_DET = 0x2000,
+    VP_CSLAC_RINGING_EXIT = 0x4000,     /**< Set when FXS line is exiting Ringing */
+    VP_CSLAC_STATUS_VALID = 0x8000
+} VpCslacLineCondType;
+#endif
+
+typedef enum VpCslacCalType {
+    VP_CSLAC_CAL_NONE = 0x0,
+    VP_CSLAC_CAL_VOC,
+    VP_CSLAC_CAL_ABV
+} VpCslacCalType;
+
+typedef struct VpApiIntLineStateType {
+    VpLineStateType currentState;   /**< Current state of the line */
+    VpLineStateType previous;       /**< Previous sate of the line */
+    VpLineStateType usrCurrent;     /**< Current user set state of the line */
+
+    /**< Differences between the usrCurrent state and currentState occur during most API internal
+     * line state control operations. E.g., Ringing Cadence and Calibration. When performing line
+     * state control functions on behalf of the Application (e.g., VpSendSignal()), these should
+     * be the same. For ex: if running a Forrward Disconnect Send Signal operation, for the duration
+     * the line is in VP_LINE_DISCONNECT the reported state using VpGetLineState() should be
+     * VP_LINE_DISCONNECT - not the state the line was in prior to performing VpSendSignal().
+     */
+
+    uint16 condition;   /**< 'OR' Combination of VpCslacLineCondType */
+    VpCslacCalType calType;
+} VpApiIntLineStateType;
+
+    /**< Indexes into the Custome Term Profile Type. #define instead of enums becuase the values
+     * must never be negative (many compilers treat enum = int type) and types larger than 8-bit is
+     * a waste.
+     */
+#define VP_CUSTOM_TERM_SLIC_TYPE    (6)
+#define VP_CUSTOM_TERM_NUM_STATES   (7)
+
+    /**< Indexes into the FXO/Dialing Profile Type. #define instead of enums becuase the values
+     * must never be negative (many compilers treat enum = int type) and types larger than 8-bit is
+     * a waste.
+     */
+#define VP_FXO_DIAL_PRFL_DTMF_ON_MSB    (6)
+#define VP_FXO_DIAL_PRFL_DTMF_ON_LSB    (7)
+#define VP_FXO_DIAL_PRFL_DTMF_OFF_MSB   (8)
+#define VP_FXO_DIAL_PRFL_DTMF_OFF_LSB   (9)
+#define VP_FXO_DIAL_PRFL_FLASH_HOOK_MSB (10)
+#define VP_FXO_DIAL_PRFL_FLASH_HOOK_LSB (11)
+#define VP_FXO_DIAL_PRFL_PULSE_BREAK    (12)
+#define VP_FXO_DIAL_PRFL_PULSE_MAKE     (13)
+#define VP_FXO_DIAL_PRFL_INTERDIG_MSB   (14)
+#define VP_FXO_DIAL_PRFL_INTERDIG_LSB   (15)
+#define VP_FXO_DIAL_PRFL_RING_PRD_MAX   (16)
+#define VP_FXO_DIAL_PRFL_RING_PRD_MIN   (17)
+#define VP_FXO_DIAL_PRFL_RING_VOLT_MIN  (18)
+#define VP_FXO_DIAL_PRFL_DISC_VOLT_MIN  (19)
+#define VP_FXO_DIAL_PRFL_LIU_THRESH_MIN (20)
+#define VP_FXO_DIAL_PRFL_RSVD           (21)
+#endif
+
+
+
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api.h b/tools/voice/zarlink/user/api_lib/includes/vp_api.h
new file mode 100644
index 0000000..8b6a185
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api.h
@@ -0,0 +1,147 @@
+/** \file vp_api.h
+ * vp_api.h
+ *
+ * Header file for the API-II c files.
+ *
+ * This file contains the all of the VoicePath API-II function prototypes. This
+ * file should be used to bring in the VP-API-II library modules that are
+ * necessary for a given application.
+ *
+ *****************************************************************************
+ * NOTE: Inclusion of only this file is sufficient to bring in the all the   *
+ * necessary aspects of VP_API.                                              *
+ *****************************************************************************
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+
+#ifndef VP_API_H
+#define VP_API_H
+
+/******************************************************************************
+ * VP-API Version                                                             *
+ *****************************************************************************/
+/*
+ * The following version number tag is updated at every release of the VP-API.
+ * Since the VP-API is a common interface that supports more than one device,
+ * version number change might occur when any aspect of the VP-API gets
+ * released.
+ */
+#define VP_API_VERSION_TAG (0x021300)
+
+#define VP_API_VERSION_MAJOR_NUM ((VP_API_VERSION_TAG) >> 16)
+#define VP_API_VERSION_MINOR_NUM (((VP_API_VERSION_TAG) & 0x00FF00) >> 8)
+#define VP_API_VERSION_MINI_NUM (((VP_API_VERSION_TAG) & 0x0FF))
+
+/* First include various basic data types used in the API */
+#include "vp_api_types.h"
+
+/******************************************************************************
+ * Defines the configuration of VP-API library that needs to be built.        *
+ * Please modify the following include file as per your VP-API library        *
+ * requirement(s).                                                            *
+ ******************************************************************************/
+#include "vp_api_cfg.h"
+
+/******************************************************************************
+ *                  PLEASE DO NOT MODIFY BELOW THIS LINE                      *
+ ******************************************************************************/
+/* Include the main VP-API-Common file */
+#include "vp_api_common.h"
+
+/* Include the VP-API-Header file required for the CSLAC sequencer */
+#if defined (VP_CSLAC_SEQ_EN)
+#include "vp_api_cslac_seq.h"
+#endif
+
+/* Include the necessary files depending on the requirement of the project */
+#if defined (VP_CC_790_SERIES)
+#include "vp790_api.h"    /* Vp790 device specific API functions and typedefs */
+#endif
+
+/* Include the necessary files depending on the requirement of the project */
+#if defined (VP_CC_792_SERIES)
+#include "vp792_api.h"    /* Vp790 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_880_SERIES)
+#include "vp880_api.h"    /* Vp880 device specific API functions and typedefs */
+
+/*
+ * For 0823 LM, the FXO CID line is controlled by I/O3. For 0803 LM, it's
+ * controlled by I/O2. Control with I/O3 is better since I/O2 has more features
+ *
+ *  #define VP880_FXO_CID_LINE      VP880_IODATA_IO2    Use with 0803 ref
+ *  #define VP880_FXO_CID_LINE      VP880_IODATA_IO3    Use with 0823 ref
+ */
+#define VP880_FXO_CID_LINE      VP880_IODATA_IO3
+#endif
+
+#if defined (VP_CC_890_SERIES)
+#include "vp890_api.h"    /* Vp890 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_580_SERIES)
+#include "vp580_api.h"    /* Vp580 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_VCP_SERIES)
+#include "dvp_api.h"     /* VCP device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_VCP2_SERIES)
+#include "vcp2_api.h"     /* VCP2 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_MELT_SERIES)
+#include "melt_api.h"     /* VCP2 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_KWRAP)
+#include "vp_kernel.h"    /* KWRAP device specific API functions and typedefs */
+#endif
+
+/* Macros for calling a device-specific API function using the pointer in the
+   Device Context: */
+typedef void (*VpTempFuncPtrType) (void);
+
+#define VP_CALL_DEV_FUNC(func, args) \
+    (((pDevCtx->funPtrsToApiFuncs.func) == VP_NULL) ? VP_STATUS_FUNC_NOT_SUPPORTED : (pDevCtx->funPtrsToApiFuncs.func) args )
+
+/*
+ * Based on the existing structure of the include files the following def
+ * have been moved here.
+ */
+
+#if defined(VP_CC_880_SERIES) || defined(VP_CC_790_SERIES) || defined(VP_CC_890_SERIES)
+
+typedef union VpTestHeapType {
+      uint8 dummy; /* preventing an empty union */
+  #if defined(VP_CC_880_SERIES) && defined(VP880_INCLUDE_TESTLINE_CODE)
+    Vp880TestHeapType vpTestHeap880;
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+
+  #if defined(VP_CC_890_SERIES) && defined(VP890_INCLUDE_TESTLINE_CODE)
+    Vp890TestHeapType vpTestHeap890;
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+
+  #if defined(VP_CC_790_SERIES) && defined(VP790_INCLUDE_TESTLINE_CODE)
+    /* Vp790TestHeapType vpTestHeap790; */
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+} VpTestHeapType;
+#else
+typedef char VpTestHeapType;
+#endif
+
+#endif /* VP_API_H */
+
+
+
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_cfg.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_cfg.h
new file mode 100644
index 0000000..5379fbd
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_cfg.h
@@ -0,0 +1,444 @@
+/** \file vp_api_cfg.h
+ * vp_api_cfg.h
+ *
+ * This file contains the configuration and compile time settings for
+ * building appropriate VP-API library modules needed for any application.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9058 $
+ * $LastChangedDate: 2011-11-07 14:21:29 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_CFG_H
+#define VP_API_CFG_H
+
+#include "vp_debug_masks.h"
+
+/**< NOTE Regarding compile-time settings to reduce code size. The values
+ * provided in these comments is for approximation and comparison purposes
+ * only. Specific savings will vary depending on the compiler and target
+ * processor.
+ */
+
+/**< VP_REDUCED_API_IF
+ * Define this to remove the I/F for unsupported functions. This reduces
+ * code size with the only limitation that the application cannot call
+ * functions that would return "Unsupported" for all devices used in the
+ * application. The specific functions removed will depend on the device and
+ * test packages compiled in.
+ */
+#define VP_REDUCED_API_IF
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: API DEBUG OUTPUT SELECTIONS                         *
+ *****************************************************************************/
+
+/**< VP_DEBUG
+ * If VP_DEBUG is undefined, then ALL debug messages will be compiled out. In
+ * this case, the code size will be smaller, but debug output CANNOT be enabled
+ * at runtime.
+ */
+#undef  VP_DEBUG
+
+/**< VP_CC_DEBUG_SELECT
+ * Choose which types of debug messages to be compiled in.  Only these message
+ * types can be enabled at runtime. See vp_debug_masks.h for a list of debug
+ * message types.
+ */
+#define VP_CC_DEBUG_SELECT (VP_DBG_ALL)
+
+/**< VP_OPTION_DEFAULT_DEBUG_SELECT
+ * The VP_OPTION_ID_DEBUG_SELECT option enables/disables debug output at
+ * runtime.  Define the default value of this option here.  The option will be
+ * automatically set to the default value at device initialization.  See
+ * vp_debug_masks.h for a list of debug message types.
+ *
+ * Note: The VP_OPTION_ID_DEBUG_SELECT option can be changed with VpSetOption()
+ *       only AFTER device initialization (VpInitDevice()).  If you wish to
+ *       see debug output messages during device initialization, you must set
+ *       the default VP_OPTION_ID_DEBUG_SELECT value accordingly.
+ */
+#define VP_OPTION_DEFAULT_DEBUG_SELECT  0
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: Conditionally-Compiled API Libraries                *
+ *****************************************************************************/
+
+/*
+ * Define (or undefine) the appropriate compile time switches based on your
+ * application needs.
+ *
+ * NOTE: Such library selection compile time option(s) MUST be defined before
+ * including any other file from VoicePath library.
+ *
+ * NOTE: More than one Library modules can be built simultaneosuly (if needed).
+ */
+#ifndef ZARLINK_CFG_INTERNAL
+
+  /*
+   * Define the API libraries that will be included in this build
+   * only if the kernel wrapper library is not supported.
+   */
+
+  #undef  VP_CC_790_SERIES   /**< define to build 790 specific API library;
+                              *   undef to exclude this library. */
+
+#if defined(ZARLINK_SLIC_VE792)
+  #define  VP_CC_792_SERIES    /**< define to build 792 specific API library;
+                             *   undef to exclude this library. */
+#endif
+
+#if defined(ZARLINK_SLIC_VE880)
+  #define  VP_CC_880_SERIES   /**< define to build 880 specific API library;
+                             *   undef to exclude this library. */
+#endif
+
+  #undef  VP_CC_890_SERIES   /**< define to build 890 specific API library;
+                              *   undef to exclude this library. */
+
+  #undef  VP_CC_580_SERIES   /**< define to build 580 specific API library;
+                              *   undef to exclude this library. */
+
+  /* VCP (VCP) library */
+  #undef  VP_CC_VCP_SERIES   /**< define to build VCP specific API library;
+                              *   undef to exclude this library. */
+  /* VCP2 library */
+  #undef  VP_CC_VCP2_SERIES  /**< define to build VCP2 specific API library;
+                              *   undef to exclude this library. */
+
+  #undef  VP_CC_MELT_SERIES  /**< define to build Melt specific API library;
+                              *   undef to exclude this library. */
+
+  #undef VP_CC_KWRAP
+
+  #if defined(VP_CC_KWRAP) && defined(__KWRAP__)
+    #error "VP_CC_KWWAP is only applicable to user space builds"
+  #endif
+
+#endif
+
+/******************************************************************************
+ * Include Files for the API                                                  *
+ *****************************************************************************/
+/* Include the API types for this architecture */
+#include "vp_api_types.h"
+
+/*
+ * Undef the following to remove the code necessary to run the API-II sequencer
+ * for CSLAC devices and to enable compile of API-II Lite. This is useful to
+ * reduce code space if the host is not using API-II "advanced" features.
+ */
+#if defined(VP_CC_790_SERIES) || defined(VP_CC_880_SERIES) || \
+    defined(VP_CC_890_SERIES) || defined(VP_CC_580_SERIES)
+    /**< VP_CSLAC_SEQ_EN
+     * This is used to support all cadencing type operations on both FXO and
+     * FXS line types. This includes Ringing and Tone Cadencing, Metering
+     * Pulse, and VpSendSignal(). When set to #undef the VE890 code reduces by
+     * ~17K, the VE880 code reduces by ~20K.
+     */
+#define VP_CSLAC_SEQ_EN
+#endif
+
+#if defined(VP_CC_880_SERIES) || defined(VP_CC_890_SERIES)
+    /**< VP_CSLAC_RUNTIME_CAL_ENABLED
+     * This is used to support run-time calibration via VpInitDevice() and
+     * VpCalLine(). With this #undef, System Coefficients can still be applied
+     * using VpCal(). Set to #undef saves VE880 code size by ~19K bytes (if
+     * both Tracker and ABS are supported) and VE890 by ~10K bytes.
+     */
+    #define VP_CSLAC_RUNTIME_CAL_ENABLED
+
+    /**< VP_HIGH_GAIN_MODE_SUPPORTED
+     * This is used to support High Gain States VP_LINE_HOWLER and
+     * VP_LINE_HOWLER_POLREV. Set to #undef saves code size for both VE880 and
+     * VE890 by ~2K bytes.
+     */
+    #define VP_HIGH_GAIN_MODE_SUPPORTED
+
+    /**< UK Howler Tone Specifications
+     * VE880 and VE890 Applications only. The values below affect how UK Howler
+     * Tone will be provided on the line. To send UK Howler Tone the
+     * application must do the following:
+     *
+     *      - Have the full version of VP_API-II (i.e., Le71SK0002)
+     *      - Set VP_CLSAC_SEQ_EN to #define. Note: if setting VP_CLSAC_SEQ_EN
+     *        to #define causes compiler errors, the Make process may either
+     *        not be including the required *.c and *.h files or may be using
+     *        the "Lite" version of the API (i.e., Le71SDKAPIL).
+     *      - Create a Tone Cadence Profile with UK Howler Tone.
+     *      - Provide this tone cadence to VpSetLineTone()
+     *
+     * There are two types of UK Howler Tones supported in the API:
+     *
+     *      - VP_UK_HOWLER_BTNR_VER15
+     *          The BTNR Version 15 Howler Tone will perform a frequency sweep
+     *          between [800Hz to 3200Hz] at a 500ms period. Total sweep from
+     *          [800-3200-800] will be nominal 1 second +/-166ms. At each 1
+     *          second interval over a total duration of 12 seconds the tone
+     *          level will increase by 3dB for total level increase of 36dB.
+     *          The final level will be a nominal +14.5dBm @ 600ohm on T/R
+     *          when also used with VP_LINE_HOWLER or VP_LINE_HOWLER_POLREV
+     *          line states (see VpSetLineState() in API Reference Guide).
+     *
+     *      - VP_UK_HOWLER_BTNR_DRAFT_G
+     *          Draft 960-G Howler Tone is very similar to Version 15 with
+     *          only a few differences. The frequency sweep is between [800Hz
+     *          to 2500Hz] and the level varies by 3dB during the sweep
+     *          interval such that the level at 2500Hz is ~3dB higher than the
+     *          level at 800Hz. The total sweep time of 12 seconds is the same
+     *          as well as the final output level of +14.5dBm @ 600ohm on T/R
+     *          when also used with VP_LINE_HOWLER or VP_LINE_HOWLER_POLREV
+     *          line states (see VpSetLineState() in API Reference Guide).
+     *
+     * The Application may choose which BTNR Specification to use when
+     * generating the UK Howler Tone by setting VP_UK_HOWLER_IN_USE value as
+     * follows:
+     *
+     *      To use BTNR Version 15:
+     *          #define VP_UK_HOWLER_IN_USE VP_UK_HOWLER_BTNR_VER15
+     *
+     *      To use BTNR Draft-960 G:
+     *          #define VP_UK_HOWLER_IN_USE VP_UK_HOWLER_BTNR_DRAFT_G
+     *
+     *      Previous releases (P2.18.0 and earlier) provided UK Howler Tone
+     *      per VP_UK_HOWLER_BTNR_VER15.
+     */
+    #define VP_UK_HOWLER_BTNR_VER15     0
+    #define VP_UK_HOWLER_BTNR_DRAFT_G   1
+    #define VP_UK_HOWLER_IN_USE         VP_UK_HOWLER_BTNR_VER15
+
+#endif  /* defined(VP_CC_880_SERIES) || defined(VP_CC_890_SERIES) */
+
+/**< EXTENDED_FLASH_HOOK
+ * Define the following to include the onHookMin member in the
+ * VpOptionPulseType struct.
+ */
+#undef  EXTENDED_FLASH_HOOK
+
+/******************************************************************************
+ * Library Specific COMPILE-TIME OPTIONS and defines                          *
+ *****************************************************************************/
+#ifdef VP_CC_790_SERIES
+/* VE790 library can be configured to handle the interrupt in four different
+ * configurations. Choose (only) one of the mechanisms by defining one of the
+ * following. */
+#define VP790_SIMPLE_POLLED_MODE        /* Define to use simple polled interrupt
+                                         * handling mode */
+#undef VP790_EFFICIENT_POLLED_MODE      /* Define to use efficient polled
+                                         * interrupt handling mode */
+#undef VP790_INTERRUPT_LEVTRIG_MODE     /* Define to use level triggered
+                                         * interrupt handling mode */
+#undef VP790_INTERRUPT_EDGETRIG_MODE    /* Define to use edge triggered
+                                         * interrupt handling mode */
+#endif /* VP_CC_790_SERIES */
+
+#ifdef VP_CC_880_SERIES
+
+/*******************************************************************************
+ * Applications can reduce VP-API-II driver size by changing the following for
+ * only the required silicon and termination types needed
+ *
+ * See VP-API-II User's Guide for Details.
+ ******************************************************************************/
+/**< Device Type Support.
+ * One of these MUST be defined if FXS Support is enabled. If you're not sure
+ * whether the silicon used in your application is ABS or Tracker, contact
+ * Microsemi customer support.
+ *
+ * Note that disabling either ABS or Tracker removes the associated calibration
+ * and line specific support (e.g., if disabling Tracker, then LPM also must be
+ * disabled).
+ */
+#define VP880_ABS_SUPPORT   /**< VP880_ABS_SUPPORT
+                             *  #define this to support VE880 ABS type silicon.
+                             * This includes but not limited to Le88266/86 and
+                             * Le8822x/24x. When set to #undef reduces code
+                             * size by ~9K bytes.
+                             */
+
+#define VP880_TRACKER_SUPPORT   /**< VP880_TRACKER_SUPPORT
+                                 * #define this to support VE880 Tracker type
+                                 * silicon. This includes but not limited to
+                                 * VE8820 Chipset and Le88276.
+                                 */
+
+/**< VE880 Termination Type Support.
+ *
+ * Note: Both ABS and Tracker can be #undef while FXO defined. This results in
+ * support for FXO only silicon, and FXO/FXS silicon support for the FXO
+ * termination type only. FXS support requires either ABS or Tracker support.
+ */
+#define VP880_FXO_SUPPORT
+#define VP880_FXS_SUPPORT
+
+/**< VP880_LP_SUPPORT
+ * When set to #undef, all of the code in the VE880 API that supports
+ * termination types VP_TERM_FXS_LOW_PWR, VP_TERM_FXS_SPLITTER_LP, and
+ * VP_TERM_FXS_ISOLATE_LP will be removed. When disabled, the VE880 code
+ * size is reduced by ~7K bytes.
+ */
+#define VP880_LP_SUPPORT
+
+/**< Specific FXO Algorithm support.
+ *
+ * The VP880_CLARE Ringing Detect algorithm uses features of the Clare and VE880
+ * silicon to provide maximum performance of signal detection on FXO lines.
+ * Alternative methods (with VP880_CLARE_RINGING_DETECT set to #undef) do not
+ * require connection of I/O4 to Clare device, but have the following drawbacks:
+ *
+ *    1. Ringing Signals MUST contain polarity reversal to be detected AND
+ *       must exceed ~70V peak.
+ *    2. Line-In-Use is disabled.
+ *    3. Frequency Discriminaation is poor (limited to tickrate).
+ *
+ * It is recommended that all designs connect the CLARE Ringing output to IO4
+ * of the silicon. In that case, this value should be #define.
+ *
+ * Note: If FXO Support is disabled, this setting has no affect.
+ */
+#define VP880_CLARE_RINGING_DETECT
+
+/**< VP880_FXO_FULL_WAVE_RINGING
+ * Selects whether the Ringing input is 1/2-wave of full-wave. This must be
+ * set to #undef when using CPC5621 since this device provides only 1/2-wave
+ * ringing. For all other Clare devices, set to #define.
+ */
+#define VP880_FXO_FULL_WAVE_RINGING
+
+/**< VP880_ALWAYS_USE_INTERNAL_TEST_TERMINATION
+ * Define this option to always use the internal test termination for relay
+ * state VP_RELAY_BRIDGED_TEST, even for devices that have the test load
+ * switch. This is Microsemi's recommendation since the Internal Test
+ * Termination provides better isolation from the customer load and loop
+ * conditions when compared to the external test load.
+ */
+#undef  VP880_ALWAYS_USE_INTERNAL_TEST_TERMINATION
+
+/* VE880 library can be configured to handle the interrupt in four different
+ * configurations. Choose (only) one of the mechanisms by defining one of the
+ * following. */
+#define VP880_SIMPLE_POLLED_MODE        /* Define to use simple polled interrupt
+                                         * handling mode */
+#undef  VP880_EFFICIENT_POLLED_MODE     /* Define to use efficient polled
+                                         * interrupt handling mode */
+#undef  VP880_INTERRUPT_LEVTRIG_MODE    /* Define to use level triggered
+                                         * interrupt handling mode */
+#undef  VP880_INTERRUPT_EDGETRIG_MODE   /* Define to use edge triggered
+                                         * interrupt handling mode */
+#undef  VP880_INCLUDE_TESTLINE_CODE     /* Defines whether or not to enable
+                                         * 880 line test capabilities */
+
+/**< VE880 Line Test Package Defines
+ * Defines all possible VE880 test line packages. There should be no reason to
+ * change these values. But if they are changed, they must be different from
+ * each other.
+ */
+#define VP880_LINE_TEST_AUDITOR 1
+#define VP880_LINE_TEST_PROFESSIONAL 2
+
+#ifdef VP880_INCLUDE_TESTLINE_CODE
+
+/**< VP880_INCLUDE_LINE_TEST_PACKAGE
+ * Selects the VE880 Line Test Package to include. Note that both Auditor and
+ * Professional cannot be included in the same build.
+ */
+#define VP880_INCLUDE_LINE_TEST_PACKAGE VP880_LINE_TEST_PROFESSIONAL
+
+/**< VP880_EZ_MPI_PCM_COLLECT
+ * #define this to have the api collect PCM samples via the MPI bus.
+ * If #undef, the Line Test code will expect the PCM samples from an
+ * external process (DSP or uProcessor) connected to the PCM BUS
+ */
+#define  VP880_EZ_MPI_PCM_COLLECT
+
+/**< VP880_PCM_CALCULATION_TIME
+ * Define the maximum expected computation time to arrive at results for
+ * VpTestLineCallback() after having collected the necessary PCM samples.
+ */
+#define VP880_PCM_CALCULATION_TIME 1000     /* time is in ms */
+
+#endif /* VP880_INCLUDE_TESTLINE_CODE */
+
+#endif /* VP_CC_880_SERIES */
+
+#ifdef VP_CC_580_SERIES
+/* VE580 library can be configured to handle the interrupt in four different
+ * configurations. Choose (only) one of the mechanisms by defining one of the
+ * following. */
+#define VP580_SIMPLE_POLLED_MODE        /* Define to use simple polled interrupt
+                                         * handling mode */
+#undef VP580_EFFICIENT_POLLED_MODE      /* Define to use efficient polled
+                                         * interrupt handling mode */
+#undef VP580_INTERRUPT_LEVTRIG_MODE     /* Define to use level triggered
+                                         * interrupt handling mode */
+#undef VP580_INTERRUPT_EDGETRIG_MODE    /* Define to use edge triggered
+                                         * interrupt handling mode */
+#endif
+
+#ifdef VP_CC_890_SERIES
+
+/**< VE890 Generic Termination Type Support */
+#define VP890_FXO_SUPPORT
+#define VP890_FXS_SUPPORT
+
+/**< VP890_LP_SUPPORT
+ * When set to #undef, all of the code in the VE890 API that supports
+ * termination types VP_TERM_FXS_LOW_PWR, VP_TERM_FXS_SPLITTER_LP, and
+ * VP_TERM_FXS_ISOLATE_LP will be removed. When disabled, the VE890 code
+ * size is reduced by ~5K bytes.
+ */
+#define VP890_LP_SUPPORT
+
+#undef  VP890_INCLUDE_TESTLINE_CODE     /* Defines whether or not to enable
+                                         * 890 line test capabilities */
+#ifdef VP890_INCLUDE_TESTLINE_CODE
+
+/**< VE890 Line Test Package Defines
+ * Defines all possible VE890 test line packages. There should be no reason to
+ * change these values. But if they are changed, they must be different from
+ * each other.
+ */
+#define VP890_LINE_TEST_AUDITOR 1
+#define VP890_LINE_TEST_PROFESSIONAL 2
+
+/**< VP890_INCLUDE_LINE_TEST_PACKAGE
+ * Selects the VE890 Line Test Package to include. Note that both Auditor and
+ * Professional cannot be included in the same build.
+ */
+#define VP890_INCLUDE_LINE_TEST_PACKAGE VP890_LINE_TEST_PROFESSIONAL
+
+/**< VP890_EZ_MPI_PCM_COLLECT
+ * #define this to have the api collect PCM samples via the MPI bus.
+ * If #undef, the Line Test code will expect the PCM samples from an
+ * external process (DSP or uProcessor) connected to the PCM BUS
+ */
+#define VP890_EZ_MPI_PCM_COLLECT
+
+/**< VP890_PCM_CALCULATION_TIME
+ * Define the maximum expected computation time to arrive at results for
+ * Vp890TestLineCallback() after having collected the necessary PCM samples.
+ */
+#define VP890_PCM_CALCULATION_TIME 1000     /* time is in ms */
+
+#endif /* VP890_INCLUDE_TESTLINE_CODE */
+
+/* VE890 library can be configured to handle the interrupt in four different
+ * configurations. Choose (only) one of the mechanisms by defining one of the
+ * following. */
+#define VP890_SIMPLE_POLLED_MODE        /* Define to use simple polled interrupt
+                                         * handling mode */
+#undef  VP890_EFFICIENT_POLLED_MODE     /* Define to use efficient polled
+                                         * interrupt handling mode */
+#undef  VP890_INTERRUPT_LEVTRIG_MODE    /* Define to use Level Triggered
+                                         * interrupt handling mode */
+#undef  VP890_INTERRUPT_EDGETRIG_MODE   /* Define to use edge triggered
+                                         * interrupt handling mode */
+#endif /* VP_CC_890_SERIES*/
+
+typedef uint8 VpScratchMemType;
+
+/* Include internal options required to build the VP-API-II library */
+#include "vp_api_cfg_int.h"
+
+#endif /* VP_API_CFG_H */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_cfg_int.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_cfg_int.h
new file mode 100644
index 0000000..a8ce23c
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_cfg_int.h
@@ -0,0 +1,400 @@
+/** \file vp_api_cfg_int.h
+ * vp_api_cfg_int.h
+ *
+ * This file contains internal configuration and compile time settings for
+ * building appropriate VP-API library modules needed for any application.
+
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 6419 $
+ * $LastChangedDate: 2010-02-12 16:40:10 -0600 (Fri, 12 Feb 2010) $
+ */
+
+#ifndef VP_API_CFG_INT_H
+#define VP_API_CFG_INT_H
+
+/**< STRICT_SIGNED_ENUM_VALUES
+ * Define this to avoid using enumerations with negative values (e.g., 0x8000). It should not be
+ * needed in compilers compliant with ANSII C89 or later. Setting it to #define also removes strict
+ * type checking in the API which is generally not preferred.
+ */
+#undef STRICT_SIGNED_ENUM_VALUES
+
+/******************************************************************************
+ * Device Context Size                                                        *
+ *****************************************************************************/
+/*
+ * Define the maximum number of lines per device in your system. Note that a
+ * system (i.e., all devices controlled by one instance of VP-API) could have
+ * more than one type of device, each of those devices may support different
+ * number of lines. For example in a system, device A might support 2 lines
+ * and device B might support 4 lines, in such a scenario, the following macro
+ * should be defined as 4. */
+#if defined(VP_CC_790_SERIES) || defined(VP_CC_580_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (4)
+#else /* VP_CC_880_SERIES + VP_CC_890_SERIES */
+    /*
+     * Note that for VE890 this value must be >=2 even when using the single
+     * FXO device. That's because the line context pointer in the device
+     * context is assigned to the "channelId" element of the line context
+     * pointer array. The FXO channelId = 1 so the array must be size >= 2.
+     */
+    #define VP_MAX_LINES_PER_DEVICE     (2)
+#endif
+
+/**< Special Case for Kernel Wrapper: DO NOT TOUCH THESE VALUES */
+#if defined(VP_CC_KWRAP)
+  #undef VP_MAX_LINES_PER_DEVICE
+  #define VP_MAX_LINES_PER_DEVICE (128)
+#endif
+
+/**< CSLAC_GAIN_RELATIVE
+ * VE880 and VE890 applications only. This value affects whether or not the VE880/VE890 API will
+ * support VpSetRelGain() function. Setting to #undef reduces the API library size for each device
+ * by ~1K. Applications may choose to compile out VpSetRelGain() functionality and instead use
+ * the VP_OPTION_ID_ABS_GAIN feature (see CSLAC_GAIN_ABS).
+ *
+ * NOTE: The API has not been tested with this string set to #undef.
+ */
+#define CSLAC_GAIN_RELATIVE
+
+/**< CSLAC_GAIN_ABS
+ * VE880 and VE890 applications only. This value affects whether or not the VE880/VE890 API will
+ * support the VP_OPTION_ID_ABS_GAIN feature of the API. Setting to #undef reduces the API library
+ * size by ~1K independent of whether compiling only for VE880 or VE890, or compiling for both. The
+ * majority of the code used to support VP_OPTION_ID_ABS_GAIN is common for these devices.
+ * Applications are not likely to use both VP_OPTION_ID_ABS_GAIN and VpSetRelGain() features of the
+ * API (see CSLAC_GAIN_RELATIVE for VpSetRelGain() compile option).
+ *
+ * NOTE: The API has not been tested with this string set to #undef.
+ */
+#define CSLAC_GAIN_ABS
+
+/**< VP_ENABLE_PROD_TEST
+ * This value exists for test purposes only. DO NOT change to #define in production code.
+ * Unexpected or damaging behavior may occur.
+ */
+#undef  VP_ENABLE_PROD_TEST
+
+/**< VP_CID_POLLING_ENABLED
+ * This value should only be defined for applications with <= 4 lines on the same MPI BUS and
+ * with 8.33ms tickrate. With VP_CID_POLLING_ENABLED set to #define, the API will consume an
+ * additional >= 500us per line for each tick (additional 1ms per tick for a 2-FXS device).
+ *
+ * For systems with tickrates = 8.33ms and using FSK CID with standard baud rate = 1200, for a
+ * per-byte line update rate of 8.33ms (same as the tickrate) it is possible on the VE880 and
+ * VE890 silicon that without this set to #define the CID message data on the line may
+ * corrupt. The error occurs when the API writes to the silicon at "exactly" the same time as
+ * the CID message on the line is changing from one byte to the next ("exact" in this context
+ * specifically refers to a window of 80ns). Repeated bulk call testing of 100,000 calls
+ * indicates that this error can occur in the range of [< 0.001% (>99.999% success) to 4%
+ * (96% success)]. Note however these numbers are application and system specific. The problem
+ * will occur 100% of the time IF the API write occurs within the 80ns window where the
+ * device/line CID message data byte is being updated, and will occur 0% of the time IF this
+ * precise timing is avoided.
+ *
+ * When this is set to #define the exact tick consumption to avoid this error is defined by
+ * VP_CID_NORMAL_MPI_CNT described below.
+ */
+#undef  VP_CID_POLLING_ENABLED
+
+/**< VP_CID_NORMAL_INIT_CNT
+ * This count value is used at the start of sending FSK data in a CID sequence.
+ *
+ * The VE880 and VE890 silicon CID message buffer is 2+ bytes deep. That means the API can at a
+ * given time provide a little less than 3 bytes to the silicon. When CID FSK Data is initialized,
+ * the API writes one byte to the silicon. It takes the silicon 18us to update it's CID buffer
+ * management such that it will then accept another 2 bytes before indicating "Full". When "Full"
+ * the silicon will tolerate the maximum amount of VpApiTick() jitter without underrun of the CID
+ * message buffer.
+ *
+ * The exact value of VP_CID_NORMAL_INIT_CNT depends on the DCLK rate and CS-Off time assumed to be
+ * 8.192MHz and 2.5us respectively. The delay is implemented in the API by reading the CID State
+ * machine buffer where each call to VpMpiCmd() requires 4 bytes of MPI traffic. Therefore, one
+ * read will take a minimum of (4 * (2.5us + 8/8.192MHz)) = 13.90625us. In order to meet the minimum
+ * time of 18us then requires at least 2 reads. In systems with much longer CS Off times or slower
+ * DCLK rates, this count value could be reduced.
+ *
+ * NOTE: This value is used by the API independant of VP_CID_POLLING_ENABLED setting.
+ */
+#define VP_CID_NORMAL_INIT_CNT  (2)
+
+/** VP_CID_NORMAL_MPI_CNT
+ * This count value is used by the API during normal CID FSK Data transmission (all FSK conditions
+ * except for the very first 3 bytes of initialization controlled by VP_CID_NORMAL_INIT_CNT). This
+ * value is set to provide a minimum 500us window where the API will monitor the silicon for a
+ * Caller ID Buffer update.
+ *
+ * When running a 8.33ms tickrate and 1200baud FSK, the silicon buffer should update very nearly
+ * when VpApiTick() is called. As mentioned above, if the API updates the silicon at almost exactly
+ * the same time as the silicon buffer update occurs, Caller ID on the line will be corrupted. The
+ * API avoids this by checking for the silicon buffer update before writing to the silicon. With
+ * a tickrate of 8.33ms + jitter, the siliocn update should occur either just before VpApiTick() is
+ * called or very nearly when VpApiTick() starts.
+ *
+ * The precise value (36) assumes DCLK = 8.192MHz and CS Off-Time of 2.5us. Each read of the CID
+ * state machine requires 4 bytes for total duration of (4 * (2.5us + 8/8.192MHz)) = 13.90625us.
+ * To meet the 500us minimum time requires (500 / 13.90625) ~ 36 reads. In systems with much longer
+ * CS Off times or slower DCLK rates, this count value could be reduced.
+ *
+ * NOTE: This value is used by the API ONLY if VP_CID_POLLING_ENABLED is set to #define.
+ */
+#define VP_CID_NORMAL_MPI_CNT   (36)
+
+/**< VE8XX_LPM_LEAKY_LINE_CNT
+ * This count is for the numner of times during a Low Power Mode leaky line test the VP-API-II
+ * will retry using LPM state before "giving up".
+ */
+#define VE8XX_LPM_LEAKY_LINE_CNT    (3)
+
+#ifdef VP_CC_880_SERIES
+
+/*
+ * Modifications to previous settings to correct for potential inconsistencies.
+ * DO NOT CHANGE anything below this line. All corrections should be made above
+ */
+#if !defined (VP880_TRACKER_SUPPORT) && defined (VP880_LP_SUPPORT)
+    #error "Invalid 880 Compiler Combination: Low Power Mode Requires Tracker defined"
+#endif
+
+#if defined (VP880_FXS_SUPPORT) && (!defined (VP880_ABS_SUPPORT) && !defined (VP880_TRACKER_SUPPORT))
+    #error "Invalid 880 Compiler Combination: FXS requires either ABS or Tracker defined"
+#endif
+
+#ifndef VP880_FXS_SUPPORT
+    #undef VP880_ABS_SUPPORT
+    #undef VP880_INCLUDE_TESTLINE_CODE
+    #undef VP880_LP_SUPPORT
+#endif
+
+#if !defined (VP880_FXS_SUPPORT) && !defined (VP880_FXO_SUPPORT)
+    #error "Invalid 880 Compiler Combination: Either FXS or FXO must be defined if using VE880 device"
+#endif
+
+/*
+ * Current Limiting option in the VP880 library limits the peak switcher current
+ * such that a 3REN load can be supported at 90V peak. Disable this option if
+ * 5REN is required.
+ */
+#undef  VP880_CURRENT_LIMIT
+
+#endif /* VP_CC_880_SERIES */
+
+#if (defined (VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) || defined(VP_CC_KWRAP)
+    /*
+     * #defines used in unit conversion function
+     * All units are based on the following calculations
+     *      Internal voltage unit   = 480.0  / 2^31 Volts
+     *      Internal current unit   = 240e-3 / 2^31 Amps
+     *      Internal freq uint      = 12e3   / 2^31 Hz
+     */
+    #define VP880_UNIT_MV                          4474L    /* mV unit */
+    #define VP880_UNIT_MVRMS                       6327L    /* mVrms unit */
+    #define VP880_UNIT_ADC_VAB                     -32768L  /* vab step from ADC */
+    #define VP880_UNIT_ADC_VAB_RMS                 46341L   /* vab step from ADC rms*/
+    #define VP880_UNIT_ADC_AC_VAB_RMS                664L   /* vab step from ADC Metallic Vrms*/
+    #define VP880_UNIT_DAC_RING                    21076L   /* step due to DAC in ringing*/
+    #define VP880_UNIT_TRACK_SWZ                23091612L   /* step used for tracking switching regulator Z */
+    #define VP880_UNIT_UA                          8948L    /* uA unit */
+    #define VP880_UNIT_ADC_IMET_NOR                16384L   /* met I from ADC in normal VC */
+    #define VP880_UNIT_ADC_IMET_NOR_JA             15756L   /* met I from ADC in normal JA*/
+    #define VP880_UNIT_ADC_IMET_RING               32768L   /* met I from ADC in ringing*/
+    #define VP880_UNIT_ADC_ILG                     11469L   /* long current from ADC*/
+    #define VP880_UNIT_DECHZ                       17896L   /* Deci Hz*/
+    #define VP880_UNIT_MHZ                         179L     /* mHz */
+    #define VP880_UNIT_FREQ                        65536L   /* siggen freq step */
+    #define VP880_UNIT_RAMP_TIME                   1365L    /* Ramp time (-1/3) in ms*/
+
+    #define VP880_UNIT_CONVERT(DATA, I_UNIT, O_UNIT)    (int32)(((int32)DATA * I_UNIT) / O_UNIT)
+
+    /* converts requested slope into SigGen Freq */
+    #define VP880_SLOPE_TO_FREQ(AMP,SLOPE)  (int16)(((int32)SLOPE * (int32)VP880_UNIT_RAMP_TIME) / (int32)AMP)
+
+    #define VP880_AC_RLOOP_MAX_BAT_LVL              75000L /* mV */
+    #define VP880_AC_RLOOP_MAX_TEST_LVL         ((VP880_AC_RLOOP_MAX_BAT_LVL - 5000) / 2)
+
+#endif /*VP880_INCLUDE_TESTLINE_CODE*/
+
+#ifdef VP_CC_890_SERIES
+
+#define VP890_REL_GAIN_GX_LOW_LIMIT     (0x500)
+#define VP890_REL_GAIN_GR_LOW_LIMIT     (0x1000)
+
+#ifndef VP890_FXS_SUPPORT
+    /*
+     * Tests (using testline) is supported only for FXS termination types. If
+     * line tests are required, make sure FXS support is enabled.
+     */
+    #undef VP890_INCLUDE_TESTLINE_CODE
+
+    /* LPM is an FXS termination type. FXS must be supported to support LPM. */
+    #undef  VP890_LP_SUPPORT
+#endif
+
+/* Define this to attempt to reduce the level of the noise signal generated for
+ * adaptive balance B-Filter calibration.  Reducing the level will increase the
+ * negative effect of outside noise on the line and can reduce performance */
+#undef VP890_REDUCE_BFILTER_CAL_SIGNAL_LEVEL
+
+#endif /* VP_CC_890_SERIES*/
+
+#if (defined (VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE)) || defined(VP_CC_KWRAP)
+    /*
+     * #defines used in unit conversion function
+     * All units are based on the following calculations
+     *      Internal voltage unit   = 480.0  / 2^31 Volts
+     *      Internal current unit   = 240e-3 / 2^31 Amps
+     *      Internal freq uint      = 12e3   / 2^31 Hz
+     */
+    #define VP890_UNIT_MV                          4474L    /* mV unit */
+    #define VP890_UNIT_MVRMS                       6327L    /* mVrms unit */
+    #define VP890_UNIT_ADC_VAB                     -32768L  /* vab step from ADC */
+    #define VP890_UNIT_ADC_VAB_RMS                 46341L   /* vab step from ADC rms*/
+    #define VP890_UNIT_ADC_AC_VAB_RMS              664L     /* vab step from ADC Metallic Vrms*/
+    #define VP890_UNIT_DAC_RING                    21076L   /* step due to DAC in ringing*/
+    #define VP890_UNIT_TRACK_SWZ                23091612L   /* step used for tracking switching regulator Z */
+    #define VP890_UNIT_UA                          8948L    /* uA unit */
+    #define VP890_UNIT_ADC_IMET_NOR                15756L   /* met I from ADC in normal*/
+    #define VP890_UNIT_ADC_IMET_RING               32768L   /* met I from ADC in ringing*/
+    #define VP890_UNIT_ADC_ILG                     11469L   /* long current from ADC*/
+    #define VP890_UNIT_DECHZ                       17896L   /* Deci Hz*/
+    #define VP890_UNIT_MHZ                         179L     /* mHz */
+    #define VP890_UNIT_FREQ                        65536L   /* siggen freq step */
+    #define VP890_UNIT_RAMP_TIME                   1365L    /* Ramp time (-1/3) in ms*/
+
+    #define VP890_UNIT_CONVERT(DATA, I_UNIT, O_UNIT) (int32)( ((int32)DATA * I_UNIT) / O_UNIT)
+
+    /* converts requested slope into SigGen Freq */
+    #define VP890_SLOPE_TO_FREQ(AMP,SLOPE) (int16) ( ((int32)SLOPE * (int32)VP890_UNIT_RAMP_TIME) / (int32)AMP)
+
+    #define VP890_AC_RLOOP_MAX_BAT_LVL              75000L /* mV */
+    #define VP890_AC_RLOOP_MAX_TEST_LVL             ((VP890_AC_RLOOP_MAX_BAT_LVL - 5000) / 2)
+
+#endif /* VP890_INCLUDE_TESTLINE_CODE */
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: Top level VP-API Default Device and Line Options    *
+ *****************************************************************************/
+/*
+ *  The following defines specify the default settings of the device and line
+ * options used in the API. The VP-API-II should generally take on the default
+ * settings set here at VpInitDevice()/VpInitLine() but is not guaranteed (i.e.,
+ * the combinations are not tested - VpInitDevice()/InitLine() could fail as a
+ * result of setting to unexpected values).
+ *
+ * Please consult Field or Applications support before changing any of
+ * these settings.
+ */
+#include "vp_api_option.h"
+#include "vp_api_event.h"
+
+/* Default Dial Pulse Options specified in units of 125micro sec  */
+#define VP_OPTION_DEFAULT_DP_BREAK_MIN          (33 * 8)    /* == 33 ms */
+#define VP_OPTION_DEFAULT_DP_BREAK_MAX          (100 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MIN           (17 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MAX           (75 * 8)
+#define VP_OPTION_DEFAULT_DP_INTER_DIG_MIN      (250 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MIN          (250 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MAX          (1300 * 8)
+#define VP_OPTION_DEFAULT_DP_ON_HOOK_MIN        VP_OPTION_DEFAULT_DP_FLASH_MAX
+#define VP_OPTION_DEFAULT_DP_OFF_HOOK_MIN       0
+
+/*
+ * Specification 2 is usefull if you need to detect between two non-overlapping
+ * dial pulse specifications.
+ */
+#define VP_OPTION_DEFAULT_DP_BREAK_MIN2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_BREAK_MAX2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MIN2          (0 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MAX2          (0 * 8)
+#define VP_OPTION_DEFAULT_DP_INTER_DIG_MIN2     (0 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MIN2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MAX2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_ON_HOOK_MIN2       (0 * 8)
+
+/* Default setting for Critical fault option */
+#define VP_OPTION_DEFAULT_CF_AC_DIS_EN          TRUE
+#define VP_OPTION_DEFAULT_CF_DC_DIS_EN          TRUE
+#define VP_OPTION_DEFAULT_CF_THERMAL_DIS_EN     TRUE
+/* CSLAC-880 and VCP-880 do not support the detection of AC, DC critical faults.
+ * So, The VP-API uses the following default values for those devices.
+ * Note that changing the following values will result in VpInitDevice()
+ * failure. */
+#define VP_OPTION_DEFAULT_CF_AC_DIS_EN_880      FALSE
+#define VP_OPTION_DEFAULT_CF_DC_DIS_EN_880      FALSE
+
+/* Default setting for Zero cross option */
+#define VP_OPTION_DEFAULT_ZERO_CROSS            VP_OPTION_ZC_M4B
+
+/* Default setting for Ramp to standby option */
+#define VP_OPTION_DEFAULT_RAMP2STBY             0
+
+/* Default setting for Pulse mode option */
+#define VP_OPTION_DEFAULT_PULSE_MODE            VP_OPTION_PULSE_DECODE_OFF
+
+/* Default CODEC Mode */
+#define VP_OPTION_DEFAULT_CODEC_MODE            VP_OPTION_ALAW
+
+/* Default setting for PCM Highway option */
+#define VP_OPTION_DEFAULT_PCM_HWY               VP_OPTION_HWY_A
+
+/* Default setting for Loop back option */
+#define VP_OPTION_DEFAULT_LOOP_BACK             VP_OPTION_LB_OFF
+
+/* Default setting for Line state option */
+#define VP_OPTION_DEFAULT_LS_BAT_REV            FALSE
+#define VP_OPTION_DEFAULT_LS_BAT                VP_OPTION_BAT_AUTO
+
+/*
+ * Default Event Masks (VP_OPTION_ID_EVENT_MASK)
+ * The user can arbitrarily set the mask bits here as needed.  A mask bit set to
+ * '0' means the event is not masked.  Some events are non-maskable.
+ */
+#define VP_OPTION_DEFAULT_FAULT_EVENT_MASK      (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_FAULT_EVENTS)
+#define VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK  (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_SIGNALING_EVENTS)
+#define VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK   (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_RESPONSE_EVENTS)
+#define VP_OPTION_DEFAULT_TEST_EVENT_MASK       (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_TEST_EVENTS)
+#define VP_OPTION_DEFAULT_PROCESS_EVENT_MASK    (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_PROCESS_EVENTS)
+#define VP_OPTION_DEFAULT_FXO_EVENT_MASK        (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_FXO_EVENTS)
+#define VP_OPTION_DEFAULT_PACKET_EVENT_MASK     (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_PACKET_EVENTS)
+
+/* Default setting for Ring Control option */
+#define VP_OPTION_DEFAULT_RC_ZERO_CROSS         VP_OPTION_ZC_M4B
+#define VP_OPTION_DEFAULT_RC_RING_EXIT_DBNC_VAL (100 * 8) /* 100ms */
+#define VP_OPTION_DEFAULT_RC_RING_EXIT_STATE    VP_LINE_TALK
+
+/* Default setting for DTMF Mode option */
+#define VP_OPTION_DEFAULT_DM_DTMF_CONTROL_MODE  VP_OPTION_DTMF_DECODE_OFF
+#define VP_OPTION_DEFAULT_DM_DIRECTION          VP_DIRECTION_US
+
+/* Default setting for PCM TX/RX path control */
+#define VP_OPTION_DEFAULT_PCM_TXRX_CNTRL        VP_OPTION_PCM_BOTH
+
+/* Default setting for DTMF Spec option */
+#define VP_OPTION_DEFAULT_DTMF_SPEC             VP_OPTION_DTMF_SPEC_ATT
+
+/* Default setting for Park Mode option */
+#define VP_OPTION_DEFAULT_PARK_MODE_DISC        4   /* 2 seconds */
+#define VP_OPTION_DEFAULT_PARK_MODE_STANDBY     3   /* 300 ms */
+
+/* Default setting for DC Feed Slope option */
+#define VP_OPTION_DEFAULT_DCFEED_SLOPE          109 /* 4 V/ms */
+
+/* Default setting for hook detection mode option */
+#define VP_OPTION_DEFAULT_HOOK_DETECT_MODE      VP_OPTION_HOOKDET_NORMAL
+
+/* Default settings for PCM highway signaling and control */
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_ENABLE    FALSE
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_CTLTS     0
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_SIGTS     0
+
+/* Default setting for PCM highway lien state control mode */
+#define VP_OPTION_DEFAULT_LINESTATE_CTL_MODE    VP_OPTION_LINESTATE_CTL_NORMAL
+
+/* Default settings for Auto Loop Conditions option */
+#define VP_OPTION_DEFAULT_AUTO_LOOP_COND_SELECT 0
+#define VP_OPTION_DEFAULT_AUTO_LOOP_COND_DELAY  0
+
+#define VP_SIZEOF_CID_MSG_BUFFER 16
+
+#endif /* VP_API_CFG_INT_H */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_common.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_common.h
new file mode 100644
index 0000000..a96a324
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_common.h
@@ -0,0 +1,1884 @@
+/** \file vp_api_common.h
+ * vp_api_common.h
+ *
+ * Header file for the VP-API-II c files.
+ *
+ * This file contains all of the VP-API-II declarations that are Voice
+ * Termination Device (VTD) family independent.
+ *
+ * $Revision: 8867 $
+ * $LastChangedDate: 2011-09-22 14:13:03 -0500 (Thu, 22 Sep 2011) $
+ */
+
+#ifndef VP_API_COMMON_H
+#define VP_API_COMMON_H
+
+#include "vp_api_types.h"
+#include "vp_api_dev_term.h"
+#include "vp_api_event.h"
+#include "vp_api_option.h"
+#include "vp_api_test.h"
+
+
+/******************************************************************************
+ *                                DEFINES                                     *
+ ******************************************************************************/
+
+/*
+ * Profile Table Indexes
+ */
+#define VP_PTABLE_NULL      (VpProfilePtrType)0
+#define VP_PTABLE_INDEX1    (VpProfilePtrType)1
+#define VP_PTABLE_INDEX2    (VpProfilePtrType)2
+#define VP_PTABLE_INDEX3    (VpProfilePtrType)3
+#define VP_PTABLE_INDEX4    (VpProfilePtrType)4
+#define VP_PTABLE_INDEX5    (VpProfilePtrType)5
+#define VP_PTABLE_INDEX6    (VpProfilePtrType)6
+#define VP_PTABLE_INDEX7    (VpProfilePtrType)7
+#define VP_PTABLE_INDEX8    (VpProfilePtrType)8
+#define VP_PTABLE_INDEX9    (VpProfilePtrType)9
+#define VP_PTABLE_INDEX10   (VpProfilePtrType)10
+#define VP_PTABLE_INDEX11   (VpProfilePtrType)11
+#define VP_PTABLE_INDEX12   (VpProfilePtrType)12
+#define VP_PTABLE_INDEX13   (VpProfilePtrType)13
+#define VP_PTABLE_INDEX14   (VpProfilePtrType)14
+#define VP_PTABLE_INDEX15   (VpProfilePtrType)15
+#define VP_PTABLE_NO_INDEX   (VpProfilePtrType)99
+#define VP_PTABLE_MAX_INDEX VP_PTABLE_INDEX15
+#define VP_PTABLE_INDEX(n)  (VpProfilePtrType)(n)
+
+
+/*
+ *Utility macros:
+ */
+#ifndef ABS
+  #define ABS(arg) ((arg) < 0 ? -(arg) : (arg))
+#endif
+
+#ifndef MAX
+  #define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+  #define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX4
+  #define MAX4(a, b, c, d) MAX(MAX(a, b), MAX(c, d))
+#endif
+
+#ifndef MAX12
+  #define MAX12(a, b, c, d, e, f, g, h, i, j, k, l) \
+    MAX(MAX(MAX4(a, b, c, d), MAX4(e, f, g, h)), MAX4(i, j, k, l))
+#endif
+
+
+/******************************************************************************
+ *                    ENUMERATIONS AND NEW DATA TYPES                         *
+ ******************************************************************************/
+/** Standard return value for most API library functions.  See the VP-API-II
+    Reference Guide for descriptions. */
+typedef enum VpStatusType {
+    VP_STATUS_SUCCESS              = 0,
+    VP_STATUS_FAILURE              = 1,
+    VP_STATUS_FUNC_NOT_SUPPORTED   = 2,
+    VP_STATUS_INVALID_ARG          = 3,
+    VP_STATUS_MAILBOX_BUSY         = 4,
+    VP_STATUS_ERR_VTD_CODE         = 5,
+    VP_STATUS_OPTION_NOT_SUPPORTED = 6,
+    VP_STATUS_ERR_VERIFY           = 7,
+    VP_STATUS_DEVICE_BUSY          = 8,
+    VP_STATUS_MAILBOX_EMPTY        = 9,
+    VP_STATUS_ERR_MAILBOX_DATA     = 10,
+    VP_STATUS_ERR_HBI              = 11,
+    VP_STATUS_ERR_IMAGE            = 12,
+    VP_STATUS_IN_CRTCL_SECTN       = 13,
+    VP_STATUS_DEV_NOT_INITIALIZED  = 14,
+    VP_STATUS_ERR_PROFILE          = 15,
+    VP_STATUS_CUSTOM_TERM_NOT_CFG  = 17,
+    VP_STATUS_DEDICATED_PINS       = 18,
+    VP_STATUS_INVALID_LINE         = 19,
+    VP_STATUS_LINE_NOT_CONFIG      = 20,
+    VP_STATUS_INPUT_PARAM_OOR,  /* This enum value does not yet require to be a set value */
+    VP_STATUS_NUM_TYPES,
+    VP_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpStatusType;
+
+/* Enumeration for Boot load Function */
+typedef enum VpBootStateType {
+    VP_BOOT_STATE_FIRST,        /* First block to download */
+    VP_BOOT_STATE_CONTINUE,     /* Additional block to download */
+    VP_BOOT_STATE_LAST,         /* Last block to download */
+    VP_BOOT_STATE_FIRSTLAST,    /* First and only block to download */
+    VP_NUM_BOOT_STATES,
+    VP_BOOT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBootStateType;
+
+/* Enumeration for Boot load Function */
+typedef enum VpBootModeType {
+    VP_BOOT_MODE_NO_VERIFY,     /* No write verification is performed */
+    VP_BOOT_MODE_VERIFY,        /* Verify Load Image Checksum */
+    VP_NUM_BOOT_MODES,
+    VP_BOOT_MODE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBootModeType;
+
+/* Version and checksum information for VCP */
+typedef struct VpVersionInfoType {
+    uint16 vtdRevCode;          /* Silicon Revision for VTD */
+    uint8 swProductId;          /* VTD Firmware ID */
+    uint8 swVerMajor;           /* Major Revision for VTD Firmware */
+    uint8 swVerMinor;           /* Minor Revision for VTD Firmware */
+} VpVersionInfoType;
+
+typedef struct VpChkSumType {
+    uint32 loadChecksum;        /* Calculated Checksum for Code Image */
+    VpVersionInfoType vInfo;    /* Version Information for VTD HW/SW */
+} VpChkSumType;
+
+typedef enum VpProfileType {
+    VP_PROFILE_DEVICE      = 0, /* Device profile */
+    VP_PROFILE_AC          = 1, /* AC profile */
+    VP_PROFILE_DC          = 2, /* DC profile */
+    VP_PROFILE_RING        = 3, /* Ring profile */
+    VP_PROFILE_RINGCAD     = 4, /* Ringing cadence profile */
+    VP_PROFILE_TONE        = 5, /* Tone profile */
+    VP_PROFILE_METER       = 6, /* Metering profile */
+    VP_PROFILE_CID         = 7, /* Caller ID profile */
+    VP_PROFILE_TONECAD     = 8, /* Tone cadence profile */
+    VP_PROFILE_FXO_CONFIG,      /* FXO configuration profile */
+    VP_PROFILE_CUSTOM_TERM,     /* Custom Termination Type profile */
+    VP_PROFILE_CAL,             /* Used for VpCal when passing calibration coefficients */
+    VP_NUM_PROFILE_TYPES,
+    VP_PROFILE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProfileType;
+
+/**< typedef for VpCalCodec() function */
+typedef enum VpDeviceCalType {
+    VP_DEV_CAL_NOW   = 0, /* Calibrate immediately */
+    VP_DEV_CAL_NBUSY = 1, /* Calibrate if all lines are "on-hook" */
+    VP_NUM_DEV_CAL_TYPES,
+    VP_DEV_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceCalType;
+
+/* Valid line states for VpSetLineState() */
+/* Defined else where */
+
+/**< The following types are for VpSetLineTone() function */
+typedef struct VpDtmfToneGenType {
+    VpDigitType toneId;  /* Identifies the DTMF tone to generated */
+    VpDirectionType dir; /* Direction in which DTMF tone needs to be
+                          * generated */
+} VpDtmfToneGenType;
+
+typedef enum VpDigitGenerationType {
+  VP_DIGIT_GENERATION_DTMF,             /* Generate DTMF digit */
+  VP_DIGIT_GENERATION_DIAL_PULSE,       /* Generate pulse digit */
+  VP_DIGIT_GENERATION_DIAL_HOOK_FLASH,   /* Generate hook flash */
+  VP_DIGIT_GEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitGenerationType;
+
+typedef enum VpBFilterModeType {
+  VP_BFILT_DIS = 0,
+  VP_BFILT_EN  = 1,
+  VP_BFILT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBFilterModeType;
+
+typedef enum VpBatteryModeType {
+  VP_BATT_MODE_DIS = 0,
+  VP_BATT_MODE_EN  = 1,
+  VP_BATT_MODE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatteryModeType;
+
+typedef struct VpBatteryValuesType {
+    int16 batt1;
+    int16 batt2;
+    int16 batt3;
+} VpBatteryValuesType;
+
+/**< The following types are for VpSetRelayState() and VpGetRelayState() functions */
+typedef enum VpRelayControlType {
+    VP_RELAY_NORMAL         = 0,  /* No test access, ringing controlled
+                                   * by line state */
+    VP_RELAY_RESET          = 1,  /* LCAS all-off state, test-out released */
+    VP_RELAY_TESTOUT        = 2,  /* LCAS all-off state, test-out active */
+    VP_RELAY_TALK           = 3,  /* LCAS talk state, test-out released */
+    VP_RELAY_RINGING        = 4,  /* LCAS ringing state, test-out released */
+    VP_RELAY_TEST           = 5,  /* LCAS test state, test-out released */
+    VP_RELAY_BRIDGED_TEST   = 6,  /* LCAS test/monitor state,
+                                   * test-out released */
+    VP_RELAY_SPLIT_TEST     = 7,  /* LCAS test/monitor state,
+                                   * test-out active */
+    VP_RELAY_DISCONNECT     = 8,  /* LCAS talk state, test-out active */
+    VP_RELAY_RINGING_NOLOAD = 9,  /* LCAS ringing state, test-out active */
+    VP_RELAY_RINGING_TEST   = 10, /* LCAS test ringing state,
+                                   * test-out active */
+    VP_RELAY_LAMP_ON        = 11, /* VCP2-790 FXS_TL_MW only */
+    VP_RELAY_IDLE           = 12, /* All switches open, test switch off */
+    VP_NUM_RELAY_STATES,
+    VP_RELAY_ENUM_RSVD  = FORCE_SIGNED_ENUM,
+    VP_RELAY_ENUM_SIZE  = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpRelayControlType;
+
+/**< The following types are for VpSetCalRelayState() function */
+typedef enum VpCalRelayControlType {
+    VP_CAL_RELAY_OPEN,                /* Open circuit                      */
+    VP_CAL_RELAY_R_DIFF_LOW_TIP_RING, /* Res Tip-to-Ring: R_DIFF_LOW Ohms  */
+    VP_CAL_RELAY_R_CM_REF_TIP_GND,    /* Res Tip-to-Gnd:  R_CM_REF Ohms    */
+    VP_CAL_RELAY_V_CAL_REF_TIP_GND,   /* Volt Tip:        V_CAL_REF Volts  */
+    VP_CAL_RELAY_SHORT_TIP_RING,      /* Res Tip-to-Ring: short (0 Ohms)   */
+    VP_CAL_RELAY_R_DIFF_HIGH_TIP_RING,/* Res Tip-to-Ring: R_DIFF_HIGH Ohms */
+    VP_CAL_RELAY_R_CM_REF_RING_GND,   /* Res Ring-to-Gnd: R_CM_REF Ohms    */
+    VP_CAL_RELAY_V_CAL_REF_RING_GND,  /* Volt Ring:       V_CAL_REF Volts  */
+    VP_CAL_RELAY_NUM_STATES,
+    VP_CAL_RELAY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCalRelayControlType;
+
+/**< The following types are for VpSetRelGain() function */
+typedef enum VpGainResultType {
+    VP_GAIN_SUCCESS  = 0, /* Gain setting adjusted successfully */
+    VP_GAIN_GR_OOR   = 1, /* GR Gain setting overflowed (reset to default) */
+    VP_GAIN_GX_OOR   = 2, /* GX Gain setting overflowed (reset to default) */
+    VP_GAIN_BOTH_OOR = 3, /* Both GR & GX overflowed (and reset to default) */
+    VP_GAIN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGainResultType;
+
+typedef struct VpRelGainResultsType {
+    VpGainResultType gResult; /* Success / Failure status return */
+    uint16 gxValue;           /* new GX register abs value */
+    uint16 grValue;           /* new GR register abs value */
+} VpRelGainResultsType;
+
+/* The number of 16 bits words used to define whether seal current
+ * should be applied to lines 0-127 */
+#define VP_SEAL_CURRENT_ARRAY_SIZE 8
+
+typedef struct VpSealCurType {
+    uint16 sealApplyTime;
+    uint16 sealCycleTime;
+    uint16 maxCurrent;
+    uint16 minCurrent;
+    uint16 sealMaskArray[VP_SEAL_CURRENT_ARRAY_SIZE];
+} VpSealCurType;
+
+/**< The following types are for the VpQuery() function */
+typedef enum VpQueryIdType {
+    VP_QUERY_ID_TEMPERATURE = 0,
+    VP_QUERY_ID_METER_COUNT = 1,
+    VP_QUERY_ID_LOOP_RES    = 2,
+    VP_QUERY_ID_SEAL_CUR    = 3,
+    VP_NUM_QUERY_IDS,
+    VP_QUERY_ID_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpQueryIdType;
+
+typedef union VpQueryResultsType {
+    int16 temp;
+    uint16 meterCount;
+    uint16 rloop;
+    VpSealCurType sealCur;
+} VpQueryResultsType;
+
+/**< The following types are for VpLineIoAccess() function */
+typedef enum VpIoDirectionType {
+    VP_IO_WRITE = 0,
+    VP_IO_READ  = 1,
+    VP_IO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpIoDirectionType;
+
+typedef struct VpLineIoBitsType {
+    uint8 mask;
+    uint8 data;
+} VpLineIoBitsType;
+
+typedef struct VpLineIoAccessType {
+    VpIoDirectionType direction;
+    VpLineIoBitsType ioBits;
+} VpLineIoAccessType;
+
+/**< The following types are for VpDeviceIoAccess() function */
+typedef enum VpDeviceIoAccessType {
+    VP_DEVICE_IO_WRITE = 0, /* Perform device specific IO write access */
+    VP_DEVICE_IO_READ  = 1, /* Perform device specific IO read access */
+    VP_DEVICE_IO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceIoAccessType;
+
+typedef enum VpDeviceIoAccessMask {
+    VP_DEVICE_IO_IGNORE = 0, /* Ignore I/O access */
+    VP_DEVICE_IO_ACCESS = 1, /* Perform I/O access */
+    VP_DEVUCE_IOA_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceIoAccessMask;
+
+typedef struct VpDeviceIoAccessDataType {
+    VpDeviceIoAccessType accessType;/* Device I/O access type */
+    uint32 accessMask_31_0;         /* I/O access mask (Pins 0 - 31) */
+    uint32 accessMask_63_32;        /* I/O access mask (Pins 32 - 63) */
+    uint32 deviceIOData_31_0;   /* Output pin data (Pins 0 - 31) */
+    uint32 deviceIOData_63_32;  /* Output pin data (Pins 32 - 63) */
+} VpDeviceIoAccessDataType;
+
+/**< The following types are for VpDeviceIoAccessExt() function */
+
+typedef struct VpDeviceIoAccessExtType {
+    VpIoDirectionType direction;
+    VpLineIoBitsType lineIoBits[VP_MAX_LINES_PER_DEVICE];
+} VpDeviceIoAccessExtType;
+
+/**< The following types are for VpGetLineStatus() function */
+typedef enum VpInputType {
+    VP_INPUT_HOOK      = 0, /* Hook Status (ignoring pulse & flash) */
+    VP_INPUT_RAW_HOOK  = 1, /* Hook Status (include pulse & flash) */
+    VP_INPUT_GKEY      = 2, /* Ground-Key/Fault Status */
+    VP_INPUT_THERM_FLT = 3, /* Thermal Fault Status */
+    VP_INPUT_CLK_FLT   = 4, /* Clock Fault Status */
+    VP_INPUT_AC_FLT    = 5, /* AC Fault Status */
+    VP_INPUT_DC_FLT    = 6, /* DC Fault Status */
+    VP_INPUT_BAT1_FLT  = 7, /* Battery 1 Fault Status */
+    VP_INPUT_BAT2_FLT  = 8, /* Battery 2 Fault Status */
+    VP_INPUT_BAT3_FLT  = 9, /* Battery 3 Fault Status */
+
+    VP_INPUT_RINGING,    /* Ringing Status */
+    VP_INPUT_LIU,        /* Line In Use Status */
+    VP_INPUT_FEED_DIS,   /* Feed Disable Status */
+    VP_INPUT_FEED_EN,    /* Feed Enable Status */
+    VP_INPUT_DISCONNECT, /* Feed Disconnect Status */
+    VP_INPUT_CONNECT,    /* Feed Connect Status */
+    VP_INPUT_POLREV,     /* Reverse Polarity if TRUE, Normal if FALSE */
+    VP_INPUT_RES_LEAK,   /* Resistive Leakage on line if TRUE */
+
+    VP_NUM_INPUT_TYPES,
+    VP_INPUT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpInputType;
+
+/**< The following type is for the VpGetDeviceStatusExt() function: */
+typedef struct VpDeviceStatusType {
+    VpInputType input;
+    uint8 status[VP_LINE_FLAG_BYTES];
+} VpDeviceStatusType;
+
+/**< The following types are for VpGetLoopCond() function (return via
+ * VpGetResults())
+ */
+typedef enum VpBatteryType {
+    VP_BATTERY_UNDEFINED = 0, /* Battery being used is not known or feature
+                               * not supported */
+    VP_BATTERY_1         = 1, /* Battery 1 */
+    VP_BATTERY_2         = 2, /* Battery 2 */
+    VP_BATTERY_3         = 3, /* Battery 3 */
+    VP_NUM_BATTERY_TYPES,
+    VP_BATTERY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatteryType;
+
+typedef enum VpDcFeedRegionType {
+    VP_DF_UNDEFINED    = 0, /* DC feed region not known or feature not
+                             * supported */
+    VP_DF_ANTI_SAT_REG = 1, /* DC feed is in anti saturation region */
+    VP_DF_CNST_CUR_REG = 2, /* DC feed is in constant current region */
+    VP_DF_RES_FEED_REG = 3, /* DC feed is in resistive feed region */
+    VP_NUM_DC_FEED_TYPES,
+    VP_DC_FEED_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDcFeedRegionType;
+
+typedef struct VpLoopCondResultsType {
+    int16 rloop;                    /**< The loop resistance */
+    int16 ilg;                      /**< The longitudinal loop current */
+    int16 imt;                      /**< The metallic loop current */
+    int16 vsab;                     /**< The tip/ring voltage */
+    int16 vbat1;                    /**< The Battery 1 voltage */
+    int16 vbat2;                    /**< The Battery 2 voltage */
+    int16 vbat3;                    /**< The Battery 3 voltage */
+    int16 mspl;                     /**< Metering signal peak level */
+    VpBatteryType selectedBat;      /**< Battery that is presently used for
+                                     *   the DC feed */
+    VpDcFeedRegionType dcFeedReg;   /**< DC feed region presently selected */
+} VpLoopCondResultsType;
+
+/**< The following types are used for the function VpSendSignal() */
+typedef enum VpSendSignalType {
+    VP_SENDSIG_MSG_WAIT_PULSE      = 0,
+    VP_SENDSIG_DTMF_DIGIT          = 1,
+    VP_SENDSIG_PULSE_DIGIT         = 2,
+    VP_SENDSIG_HOOK_FLASH          = 3,
+    VP_SENDSIG_FWD_DISCONNECT      = 4,
+    VP_SENDSIG_POLREV_PULSE        = 5,
+    VP_SENDSIG_MOMENTARY_LOOP_OPEN = 6,
+    VP_SENDSIG_TIP_OPEN_PULSE      = 7,
+    VP_SENDSIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSendSignalType;
+
+typedef struct VpSendMsgWaitType {
+    int8 voltage;   /**< Voltage in Volts to apply to the line. A negative
+                     * value means Tip is more Negative than Ring, a positive
+                     * value means Ring is more Negative than Tip.
+                     */
+    uint16 onTime;  /**< Duration of pulse on-time in mS */
+    uint16 offTime; /**< Duration of pulse off-tim in mS. If the off-time is
+                     * set to 0, the voltage is applied to the line continuously
+                     */
+    uint8 cycles;   /**< Number of pulses to send on the line. If set to 0, will
+                     * repeat forever
+                     */
+} VpSendMsgWaitType;
+
+/**< The following type is used for the function VpGenTimerCtrl() */
+typedef enum VpGenTimerCtrlType {
+    VP_GEN_TIMER_START  = 0,
+    VP_GEN_TIMER_CANCEL = 1,
+    VP_GEN_TIMER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGenTimerCtrlType;
+
+/**< The enum is used by the system service layer pcmCollect() function */
+typedef enum VpPcmOperationBitType {
+    VP_PCM_OPERATION_AVERAGE      = 0x0001, /* average PCM samples */
+    VP_PCM_OPERATION_RANGE        = 0x0002, /* find pk to pk pcm sample data. */
+    VP_PCM_OPERATION_RMS          = 0x0004, /* find rms value of pcm samples */
+    VP_PCM_OPERATION_MIN          = 0x0008, /* find min pcm value of pcm samples */
+    VP_PCM_OPERATION_MAX          = 0x0010, /* find max pcm value of pcm samples */
+    VP_PCM_OPERATION_APP_SPECIFIC = 0x0020, /* generic operation */
+    VP_PCM_OPERATION_FREQ         = 0x0040, /* Measure frequency */
+    VP_PCM_OPERATION_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPcmOperationBitType;
+
+typedef uint16 VpPcmOperationMaskType;
+
+typedef struct VpPcmOperationResultsType {
+    int16 average;  /* Average value of all collected PCM samples */
+    int16 range;    /* Maximum - minimum PCM value during operation time */
+    int16 rms;      /* RMS result of all collected pcm samples */
+    int16 min;      /* Maximum pcm value found */
+    int16 max;      /* Minimum pcm value found */
+    void *pApplicationInfo; /* Any results that the implementation chooses to
+                             * pass. This data is not interpreted neither
+                             * by the VP-API nor the LT-API. LT-API passes
+                             * this pointer back to the application as part
+                             * of the test result
+                             */
+    int32 freq;     /* Measured average frequenny */
+
+    bool error;     /* indication of PCM operation process (1 = failure) */
+} VpPcmOperationResultsType;
+
+/**< The enum is used by the cal function */
+typedef enum VpCalType {
+    VP_CAL_BFILTER              = 1,
+    VP_CAL_APPLY_BFILTER        = 2,
+    VP_CAL_MEASURE_BFILTER      = 3,
+    VP_CAL_GET_SYSTEM_COEFF     = 4,
+    VP_CAL_APPLY_SYSTEM_COEFF   = 5,
+    VP_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCalType;
+
+typedef struct VpCalBFilterType {
+    uint16 vRms;    /**< Customer Target Value in approximate vRms */
+    VpProfilePtrType pAcProfile;
+} VpCalBFilterType;
+
+typedef struct VpCalApplyBFilterType {
+    VpProfilePtrType pAcProfile;
+    uint16 index;
+} VpCalApplyBFilterType;
+
+typedef enum VpCalStatusType {
+    VP_CAL_SUCCESS,
+    VP_CAL_FAILURE,
+    VP_CAL_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCalStatusType;
+
+typedef enum VpLowLevelCmdType {
+    VP_LOWLEV_PAGE_WR = 0,
+    VP_LOWLEV_PAGE_RD = 1,
+    VP_LOWLEV_MBOX_WR = 2,
+    VP_LOWLEV_MBOX_RD = 3,
+    VP_LOWLEV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpLowLevelCmdType;
+
+typedef enum VpProfileFieldIdType {
+
+    /* Device parameters */
+
+    /* DC parameters */
+    VP_PROF_FIELD_ILA
+
+} VpProfileFieldIdType;
+
+typedef struct VpProfileFieldType {
+    VpProfileFieldIdType fieldId;
+
+    union data {
+        uint16 ila;
+    } data;
+
+} VpProfileFieldType;
+
+/* The following struct can be passed to VpGetResults() if the event ID is not
+   known at compile time, to ensure that the buffer is large enough regardless
+   of the result type. */
+typedef union VpResultsType {
+    VpChkSumType codeChecksum;                  /* VP_DEV_EVID_BOOT_CMP or
+                                                   VP_DEV_EVID_CHKSUM          */
+    VpRelGainResultsType setRelGain;            /* VP_LINE_EVID_GAIN_CMP       */
+    uint8 lowLevelCmd[256];                     /* VP_LINE_EVID_LLCMD_RX_CMP   */
+    VpLoopCondResultsType getLoopCond;          /* VP_LINE_EVID_RD_LOOP        */
+    VpOptionValueType getOption;                /* VP_LINE_EVID_RD_OPTION      */
+    VpTestResultType testLine;                  /* VP_LINE_EVID_TEST_CMP       */
+    VpDeviceIoAccessDataType deviceIoAccess;    /* VP_DEV_EVID_IO_ACCESS_CMP   */
+    VpDeviceIoAccessExtType deviceIoAccessExt;  /* VP_DEV_EVID_IO_ACCESS_CMP   */
+    VpLineIoAccessType lineIoAccess;            /* VP_LINE_EVID_LINE_IO_RD_CMP */
+    VpQueryResultsType query;                   /* VP_LINE_EVID_QUERY_CMP      */
+} VpResultsType;
+
+typedef enum VpFreeRunModeType {
+    VP_FREE_RUN_START,
+    VP_FREE_RUN_STOP
+} VpFreeRunModeType;
+
+/******************************************************************************
+ *                 DEVICE/LINE CONTEXT (SUPPORT) DEFINITION                   *
+ ******************************************************************************/
+/* The following function pointers are required to get around problem of
+ * what comes first? chicken or the egg? when dealing with declaration of
+ * device context, function pointer table and hence the following declarations.
+ */
+struct VpDevCtxType;    /**< forward declaration */
+struct VpLineCtxType;   /**< forward declaration */
+struct VpEventType;     /**< forward declaration */
+
+/*
+ * System Configuration functions
+ */
+typedef VpStatusType
+(*VpMakeLineObjectFuncPtrType) (
+    VpTermType termType,
+    uint8 channelId,
+    struct VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    struct VpDevCtxType *pDevCtx);
+
+/*
+ * Initialization functions
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpBootLoadFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+typedef VpStatusType
+(*VpBootSlacFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize);
+#endif  /* !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * | defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpInitDeviceFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile,
+    VpProfilePtrType pFxoAcProfile,
+    VpProfilePtrType pFxoCfgProfile);
+
+typedef VpStatusType
+(*VpFreeRunFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpFreeRunModeType freeRunMode);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpInitSlacFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpInitLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+typedef VpStatusType
+(*VpConfigLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+typedef VpStatusType
+(*VpSetBFilterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpBFilterModeType bFiltMode,
+    VpProfilePtrType pAcProfile);
+
+typedef VpStatusType
+(*VpSetBatteriesFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpBatteryModeType battMode,
+    VpBatteryValuesType *pBatt);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+                                || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+typedef VpStatusType
+(*VpCalCodecFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpDeviceCalType mode);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+         * || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+         */
+
+typedef VpStatusType
+(*VpCalLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx);
+
+typedef VpStatusType
+(*VpCalFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpCalType calType,
+    void *inputArgs);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+typedef VpStatusType
+(*VpInitRingFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCadProfile,
+    VpProfilePtrType pCidProfile);
+
+typedef VpStatusType
+(*VpInitCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpInitMeterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+typedef VpStatusType
+(*VpInitCustomTermTypeFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCustomTermProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+typedef VpStatusType
+(*VpInitProfileFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpProfileType type,
+    VpProfilePtrType pProfileIndex,
+    VpProfilePtrType pProfile);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpSoftResetFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Control functions
+ */
+typedef VpStatusType
+(*VpSetLineStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+typedef VpStatusType
+(*VpSetLineToneFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+typedef VpStatusType
+(*VpSetRelayStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpRelayControlType rState);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+typedef VpStatusType
+(*VpSetCalRelayStateFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpCalRelayControlType rState);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+typedef VpStatusType
+(*VpSetRelGainFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 txLevel,
+    uint16 rxLevel,
+    uint16 handle);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+typedef VpStatusType
+(*VpSendSignalFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpSendSignalType signalType,
+    void *pSignalData);
+
+typedef VpStatusType
+(*VpSendCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    VpProfilePtrType pCidProfile,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpContinueCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpStartMeterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpStartMeter32QFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint32 minDelay,
+    uint32 onTime,
+    uint32 offTime,
+    uint16 numMeters,
+    uint16 eventRate);
+
+typedef VpStatusType
+(*VpGenTimerCtrlFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpGenTimerCtrlType timerCtrl,
+    uint32 duration,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpAssocDslLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    bool connect,
+    uint8 line);
+
+typedef VpStatusType
+(*VpSetSealCurFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    uint16 sealApplyTime,
+    uint16 sealCycleTime,
+    uint16 maxCurrent,
+    uint16 minCurrent,
+    uint16 *pSealArray,
+    VpProfilePtrType pDcProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpSetOptionFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    void *pValue);
+
+typedef VpStatusType
+(*VpDeviceIoAccessFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessDataType *pDeviceIoData);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpDeviceIoAccessExtFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessExtType *pDeviceIoAccess);
+
+typedef VpStatusType
+(*VpLineIoAccessFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineIoAccessType *pLineIoAccess,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpVirtualISRFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpApiTickFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    bool *pEventStatus);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(ZARLINK_CFG_INTERNAL)
+typedef VpStatusType
+(*VpLowLevelCmdFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 *pCmdData,
+    uint8 len,
+    uint16 handle);
+#endif
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpLowLevelCmd16FuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLowLevelCmdType cmdType,
+    uint16 *writeWords,
+    uint8 numWriteWords,
+    uint8 numReadWords,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Status and query functions
+ */
+
+typedef bool
+(*VpGetEventFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    struct VpEventType *pEvent);
+
+typedef VpStatusType
+(*VpGetLineStatusFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+typedef VpStatusType
+(*VpGetDeviceStatusFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpInputType input,
+    uint32 *pDeviceStatus);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpGetDeviceStatusExtFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceStatusType *pDeviceStatus);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+typedef VpStatusType
+(*VpGetLoopCondFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+typedef VpStatusType
+(*VpGetOptionFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpGetLineStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineStateType *pCurrentState);
+
+typedef VpStatusType
+(*VpFlushEventsFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpGetResultsFuncPtrType) (
+    struct VpEventType *pEvent,
+    void *pResults);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpClearResultsFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+                                || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+typedef VpStatusType
+(*VpGetRelayStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpRelayControlType *pRstate);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+         * || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+         */
+
+typedef VpStatusType
+(*VpObjectDumpFuncPtrType)(
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpRegisterDumpFuncPtrType)(
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpDtmfDigitDetectedFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+
+typedef VpStatusType
+(*VpQueryFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpQueryIdType queryId,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Test Functions
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+                                || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+typedef VpStatusType
+(*VpTestLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpTestLineIntFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle,
+    bool callback);
+
+typedef VpStatusType
+(*VpTestLineCallbackType) (
+    struct VpLineCtxType *pLineCtx,
+    VpPcmOperationResultsType *pResults);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpCodeCheckSumFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpSelfTestFuncPtrType) (
+    struct VpLineCtxType *pLineCtx);
+
+typedef VpStatusType
+(*VpFillTestBufFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+typedef VpStatusType
+(*VpReadTestBufFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+         * || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+         */
+
+/** ApiFunctionPointer Table to be used by Device Context */
+typedef struct ApiFunctions {
+    /* System Configuration Functions */
+    VpMakeLineObjectFuncPtrType MakeLineObject;
+
+    /* Initialization Functions */
+    /*   -- Init Functions common to all devices and VP-API-II configuration modes */
+    VpInitDeviceFuncPtrType InitDevice;
+    VpFreeRunFuncPtrType FreeRun;
+
+    VpInitLineFuncPtrType InitLine;
+    VpConfigLineFuncPtrType ConfigLine;
+
+    VpCalLineFuncPtrType CalLine;
+    VpCalFuncPtrType Cal;
+    VpInitProfileFuncPtrType InitProfile;
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+    VpBootLoadFuncPtrType BootLoad;
+    VpBootSlacFuncPtrType BootSlac;
+    VpInitSlacFuncPtrType InitSlac;
+    VpSoftResetFuncPtrType SoftReset;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpSetBFilterFuncPtrType SetBFilter;
+    VpSetBatteriesFuncPtrType SetBatteries;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+                                || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+    VpCalCodecFuncPtrType CalCodec;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II except VE580 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+    VpInitCustomTermTypeFuncPtrType InitCustomTerm;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II Lite Version */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+    VpInitRingFuncPtrType InitRing;
+    VpInitCidFuncPtrType InitCid;
+    VpInitMeterFuncPtrType InitMeter;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+         */
+
+    /* Control Functions */
+    /*   -- Control Functions common to all devices and VP-API-II configuration modes */
+    VpSetLineStateFuncPtrType SetLineState;
+    VpSetLineToneFuncPtrType SetLineTone;
+    VpSetRelayStateFuncPtrType SetRelayState;
+    VpSetRelGainFuncPtrType SetRelGain;
+
+    VpSetOptionFuncPtrType SetOption;
+    VpDeviceIoAccessFuncPtrType DeviceIoAccess;
+    VpVirtualISRFuncPtrType VirtualISR;
+    VpApiTickFuncPtrType ApiTick;
+
+    /*   -- Control Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+    VpSetCalRelayStateFuncPtrType SetCalRelayState;
+
+    VpStartMeter32QFuncPtrType StartMeter32Q;
+    VpGenTimerCtrlFuncPtrType GenTimerCtrl;
+    VpAssocDslLineFuncPtrType AssocDslLine;
+    VpSetSealCurFuncPtrType SetSealCur;
+
+    VpDeviceIoAccessExtFuncPtrType DeviceIoAccessExt;
+    VpLineIoAccessFuncPtrType LineIoAccess;
+
+    VpLowLevelCmd16FuncPtrType LowLevelCmd16;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(ZARLINK_CFG_INTERNAL)
+    VpLowLevelCmdFuncPtrType LowLevelCmd;
+#endif
+
+    /*   -- Control Functions NOT provided in CSLAC VP-API-II Lite Version */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+    VpSendSignalFuncPtrType SendSignal;
+    VpSendCidFuncPtrType SendCid;
+    VpContinueCidFuncPtrType ContinueCid;
+    VpStartMeterFuncPtrType StartMeter;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+         */
+
+    /* Status and Query Functions */
+    /*   -- Status and Query Functions common to all devices and VP-API-II configuration modes */
+    VpGetEventFuncPtrType GetEvent;
+    VpGetLineStatusFuncPtrType GetLineStatus;
+    VpGetDeviceStatusFuncPtrType GetDeviceStatus;
+
+    VpGetOptionFuncPtrType GetOption;
+    VpGetLineStateFuncPtrType GetLineState;
+    VpFlushEventsFuncPtrType FlushEvents;
+    VpGetResultsFuncPtrType GetResults;
+
+    VpObjectDumpFuncPtrType ObjectDump;
+    VpRegisterDumpFuncPtrType RegisterDump;
+    VpDtmfDigitDetectedFuncPtrType DtmfDigitDetected;
+
+    /*   -- Status and Query Functions used only for CSLAC Line Testing */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+                                || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+    VpGetRelayStateFuncPtrType GetRelayState;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+         * || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+         */
+
+    /*   -- Status and Query Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+    VpGetDeviceStatusExtFuncPtrType GetDeviceStatusExt;
+    VpClearResultsFuncPtrType ClearResults;
+    VpQueryFuncPtrType Query;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Status and Query Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpGetLoopCondFuncPtrType GetLoopCond;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+    /* Test Functions */
+    /*   -- All test functions removed for CSLAC VP-API-II unless Line Test is included */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+                                || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+    /*   -- Test Functions common to all devices and VP-API-II configuration modes */
+    VpTestLineFuncPtrType TestLine;
+    VpTestLineIntFuncPtrType TestLineInt;
+    VpTestLineCallbackType TestLineCallback;
+
+    /*   -- Test Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+    VpCodeCheckSumFuncPtrType CodeCheckSum;
+    VpFillTestBufFuncPtrType FillTestBuf;
+    VpReadTestBufFuncPtrType ReadTestBuf;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Test Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+            || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpSelfTestFuncPtrType SelfTest;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         *  || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+         * || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+         */
+} ApiFunctions;
+
+/******************************************************************************
+ *                       DEVICE/LINE CONTEXT DEFINITION                       *
+ ******************************************************************************/
+/** Voice Path Line Context type */
+typedef struct VpLineCtxType {
+    struct VpDevCtxType *pDevCtx;   /**< Pointer back Device Context */
+
+    void *pLineObj;                 /**< Pointer (forward) to Line Object */
+} VpLineCtxType;
+
+/** Voice Path Device Context type */
+typedef struct VpDevCtxType {
+    VpDeviceType deviceType;    /**< What type is the device context (enum) */
+    void *pDevObj;              /**< Pointer to device object */
+
+    ApiFunctions funPtrsToApiFuncs; /**< Pointers to API functions */
+
+    /**< Pointers to each line context associated with this device.  Set size
+     * to max allowable per device in system
+     */
+    VpLineCtxType *pLineCtx[VP_MAX_LINES_PER_DEVICE];
+} VpDevCtxType;
+
+/******************************************************************************
+ *                        VP-API-II Definitions that use context              *
+ ******************************************************************************/
+/** Event struct: Type reported by VpGetEvent(). */
+typedef struct VpEventType {
+    VpStatusType status;        /**< Function return status */
+
+    uint8 channelId;            /**< Channel that caused the event */
+
+    VpLineCtxType *pLineCtx;    /**< Pointer to the line context (corresponding
+                                 *   to the channel that caused the event) */
+
+    VpDeviceIdType deviceId;    /**< device chip select ID corresponding to the
+                                 *   device that caused the event */
+
+    VpDevCtxType *pDevCtx;      /**< Pointer to the device context
+                                 *   (corresponding to the device that caused
+                                 *   the event) */
+
+    VpEventCategoryType eventCategory; /**< Event category.  The event catagory
+                                        *   is necessary because there are more
+                                        *   events than can be specified by the
+                                        *   size of "eventId  */
+
+    uint16 eventId;     /**< The event that occurred.  Requires that the event
+                         *   catagory be known to interpret */
+
+    uint16 parmHandle;  /**< EventÂ’s Parameter or Host Handle.  This value is
+                         *   specified by the application only, not used by the
+                         *   API */
+
+    uint16 eventData;   /**< Data associated with the event. Event Id specific*/
+
+    bool hasResults;    /**< If TRUE indicates this event has results associated
+                         *   with it */
+
+    VpLineIdType lineId;    /**< Application provide line Id to ease mapping of
+                             * lines to specific line contexts.
+                             */
+} VpEventType;
+
+/**< The following types are for VpGetDeviceInfo() and VpGetLineInfo()
+ * functions */
+
+typedef enum VpFeatureType {
+    VP_UNKNOWN,
+    VP_AVAILABLE,
+    VP_NOT_AVAILABLE
+} VpFeatureType;
+
+typedef struct VpFeatureListType {
+    VpFeatureType testLoadSwitch;
+    VpFeatureType internalTestTermination;
+} VpFeatureListType;
+
+typedef struct VpDeviceInfoType {
+    VpLineCtxType *pLineCtx;            /* Pointer to Line Context */
+    VpDeviceIdType deviceId;            /* Device identity */
+    VpDevCtxType *pDevCtx;              /* Pointer to device Context */
+    VpDeviceType deviceType;            /* Device Type */
+    VpFeatureListType featureList;      /* Store the device features */
+    uint8 numLines;                     /* Number of lines */
+    uint8 revCode;                      /* Revision Code Number */
+    uint8 slacId;                       /* Unique ID associated with Device identity */
+    uint16 productCode;                 /* Number indicating features of the device.*/
+} VpDeviceInfoType;
+
+typedef struct VpLineInfoType {
+    VpDevCtxType *pDevCtx;       /* Pointer to device Context */
+    uint8 channelId;             /* Channel identity */
+    VpLineCtxType *pLineCtx;     /* Pointer to Line Context */
+    VpTermType termType;         /* Termination Type */
+    VpLineIdType lineId;         /* Application system wide line identifier */
+} VpLineInfoType;
+
+/******************************************************************************
+ *                        VP-API-II FUNCTION PROTOTYPES                       *
+ ******************************************************************************/
+/*
+ * System configuration functions
+ */
+EXTERN VpStatusType
+VpMakeDeviceObject(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    VpDevCtxType *pDevCtx,
+    void *pDevObj);
+
+EXTERN VpStatusType
+VpMakeDeviceCtx(
+    VpDeviceType deviceType,
+    VpDevCtxType *pDevCtx,
+    void *pDevObj);
+
+EXTERN VpStatusType
+VpMakeLineObject(
+    VpTermType termType,
+    uint8 channelId,
+    VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpMakeLineCtx(
+    VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpFreeLineCtx(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpGetDeviceInfo(
+    VpDeviceInfoType *pDeviceInfo);
+
+EXTERN VpStatusType
+VpGetLineInfo(
+    VpLineInfoType *pLineInfo);
+
+/*
+ * Initialization functions
+ */
+EXTERN VpStatusType
+VpBootLoad(
+    VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+EXTERN VpStatusType
+VpBootSlac(
+    VpLineCtxType *pLineCtx,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize);
+
+EXTERN VpStatusType
+VpInitDevice(
+    VpDevCtxType *pDevCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile,
+    VpProfilePtrType pFxoAcProfile,
+    VpProfilePtrType pFxoCfgProfile);
+
+EXTERN VpStatusType
+VpFreeRun(
+    VpDevCtxType *pDevCtx,
+    VpFreeRunModeType freeRunMode);
+
+EXTERN VpStatusType
+VpInitSlac(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpInitLine(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpConfigLine(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpCalCodec(
+    VpLineCtxType *pLineCtx,
+    VpDeviceCalType mode);
+
+EXTERN VpStatusType
+VpCalLine(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpCal(
+    VpLineCtxType *pLineCtx,
+    VpCalType calType,
+    void *inputArgs);
+
+EXTERN VpStatusType
+VpInitRing(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCadProfile,
+    VpProfilePtrType pCidProfile);
+
+EXTERN VpStatusType
+VpInitCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpInitMeter(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+
+EXTERN VpStatusType
+VpInitCustomTermType (
+    VpDevCtxType *pDevCtx,
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCustomTermProfile);
+
+EXTERN VpStatusType
+VpInitProfile(
+    VpDevCtxType *pDevCtx,
+    VpProfileType type,
+    VpProfilePtrType pProfileIndex,
+    VpProfilePtrType pProfile);
+
+EXTERN VpStatusType
+VpSoftReset(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpSetBatteries(
+    VpLineCtxType *pLineCtx,
+    VpBatteryModeType battMode,
+    VpBatteryValuesType *pBatt);
+
+EXTERN VpStatusType
+VpSetBFilter(
+    VpLineCtxType *pLineCtx,
+    VpBFilterModeType bFiltMode,
+    VpProfilePtrType pAcProfile);
+
+/*
+ * Control functions
+ */
+EXTERN VpStatusType
+VpSetLineState(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+EXTERN VpStatusType
+VpSetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+EXTERN VpStatusType
+VpSetRelayState(
+    VpLineCtxType *pLineCtx,
+    VpRelayControlType rState);
+
+EXTERN VpStatusType
+VpSetCalRelayState(
+    VpDevCtxType *pDevCtx,
+    VpCalRelayControlType rState);
+
+EXTERN VpStatusType
+VpSetRelGain(
+    VpLineCtxType *pLineCtx,
+    uint16 txLevel,
+    uint16 rxLevel,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpSendSignal(
+    VpLineCtxType *pLineCtx,
+    VpSendSignalType signalType,
+    void *pSignalData);
+
+EXTERN VpStatusType
+VpSendCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    VpProfilePtrType pCidProfile,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpContinueCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpStartMeter(
+    VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+
+EXTERN VpStatusType
+VpStartMeter32Q(
+    VpLineCtxType *pLineCtx,
+    uint32 minDelay,
+    uint32 onTime,
+    uint32 offTime,
+    uint16 numMeters,
+    uint16 eventRate);
+
+EXTERN VpStatusType
+VpAssocDslLine(
+    VpLineCtxType *pLineCtx,
+    bool connect,
+    uint8 line);
+
+EXTERN VpStatusType
+VpSetSealCur(
+    VpDevCtxType *pDevCtx,
+    uint16 sealApplyTime,
+    uint16 sealCycleTime,
+    uint16 maxCurrent,
+    uint16 minCurrent,
+    uint16 *pSealArray,
+    VpProfilePtrType pDcProfile);
+
+
+#define VpStartMeter32(pLineCtx, minDelay, onTime, offTime, numMeters) \
+    VpStartMeter32Q(pLineCtx, minDelay, onTime, offTime, numMeters, 1)
+
+EXTERN VpStatusType
+VpSetOption(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    void *pValue);
+
+EXTERN VpStatusType
+VpDeviceIoAccess(
+    VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessDataType *pDeviceIoData);
+
+VpStatusType
+VpDeviceIoAccessExt(
+    VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessExtType *pDeviceIoAccess);
+
+EXTERN VpStatusType
+VpLineIoAccess(
+    VpLineCtxType *pLineCtx,
+    VpLineIoAccessType *pLineIoAccess,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpVirtualISR(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpApiTick(
+    VpDevCtxType *pDevCtx,
+    bool *pEventStatus);
+
+EXTERN VpStatusType
+VpLowLevelCmd(
+    VpLineCtxType *pLineCtx,
+    uint8 *pCmdData,
+    uint8 len,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpLowLevelCmd16(
+    VpLineCtxType *pLineCtx,
+    VpLowLevelCmdType cmdType,
+    uint16 *writeWords,
+    uint8 numWriteWords,
+    uint8 numReadWords,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGenTimerCtrl(
+    VpLineCtxType *pLineCtx,
+    VpGenTimerCtrlType timerCtrl,
+    uint32 duration,
+    uint16 handle);
+
+/*
+ * Status and query functions
+ */
+EXTERN bool
+VpGetEvent(
+    VpDevCtxType *pDevCtx,
+    VpEventType *pEvent);
+
+EXTERN VpStatusType
+VpGetLineStatus(
+    VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+EXTERN VpStatusType
+VpGetDeviceStatus(
+    VpDevCtxType *pDevCtx,
+    VpInputType input,
+    uint32 *pDeviceStatus);
+
+EXTERN VpStatusType
+VpGetDeviceStatusExt(
+    VpDevCtxType *pDevCtx,
+    VpDeviceStatusType *pDeviceStatus);
+
+EXTERN VpStatusType
+VpGetLoopCond(
+    VpLineCtxType *pLineCtx,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetOption(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetLineState(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType *pCurrentState);
+
+EXTERN VpStatusType
+VpFlushEvents(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpGetResults(
+    VpEventType *pEvent,
+    void *pResults);
+
+EXTERN VpStatusType
+VpClearResults(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpObjectDump(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpRegisterDump(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpDtmfDigitDetected(
+    VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+EXTERN VpStatusType
+VpQuery(
+    VpLineCtxType *pLineCtx,
+    VpQueryIdType queryId,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetRelayState(
+    VpLineCtxType *pLineCtx,
+    VpRelayControlType *pRstate);
+
+/*
+ * Test Functions
+ */
+EXTERN VpStatusType
+VpTestLine(
+    VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpTestLineCallback(
+    VpLineCtxType *pLineCtx,
+    VpPcmOperationResultsType *pResults);
+
+EXTERN VpStatusType
+VpCodeCheckSum(
+    VpDevCtxType *pDevCtx,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpSelfTest(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpFillTestBuf(
+    VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+EXTERN VpStatusType
+VpReadTestBuf(
+    VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+
+EXTERN VpStatusType
+VpMapLineId(
+    VpLineCtxType *pLineCtx,
+    VpLineIdType lineId);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+EXTERN VpStatusType
+VpMapSlacId(
+    VpDevCtxType *pDevCtx,
+    uint8 slacId);
+#endif
+
+EXTERN bool
+VpMemCpyCheck(
+    uint8 *dest,
+    uint8 *src,
+    uint16 count);
+
+EXTERN void *
+VpMemCpy(
+    void *dest,
+    const void *src,
+    uint16 count);
+
+EXTERN void *
+VpMemSet(
+    void * s,
+    int c,
+    uint16 count);
+
+
+/*
+ * Undocumented external functions:
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+EXTERN void
+VpSetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+EXTERN bool
+VpReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+Vcp2HbiCheck(
+    VpDevCtxType *pDevCtx);
+#endif
+
+EXTERN void
+VpMpiCmdWrapper(
+    VpDeviceIdType deviceId,
+    uint8 ecVal,
+    uint8 mpiCmd,
+    uint8 mpiCmdLen,
+    uint8 *dataBuffer);
+
+EXTERN uint8
+VpCSLACBuildMpiBuffer(
+    uint8 index,
+    uint8 *mpiBuffer,
+    uint8 mpiCmd,
+    uint8 mpiCmdLen,
+    uint8 *mpiData);
+#endif /* VP_API_COMMON_H */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_cslac_seq.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_cslac_seq.h
new file mode 100644
index 0000000..a1baeaa
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_cslac_seq.h
@@ -0,0 +1,125 @@
+/** \file vp_api_cslac_seq.h
+ * vp_api_cslac_seq.h
+ *
+ * Header file for the API-II c files.
+ *
+ * This file contains the all of the VoicePath API-II function prototypes
+ * required to run the CSLAC sequencer.
+ *
+ * $Revision: 8873 $
+ * $LastChangedDate: 2011-09-23 12:00:01 -0500 (Fri, 23 Sep 2011) $
+ */
+
+#ifndef VP_API_CSLAC_SEQ_H
+#define VP_API_CSLAC_SEQ_H
+
+#include "vp_CSLAC_types.h"
+
+#ifdef VP_CSLAC_SEQ_EN
+
+/*
+ * Converting from bool to enumeration. So make sure there exists a string that
+ * maps directly to previous "FALSE" value. Other strings can take on any valid
+ * enumeration value.
+ */
+typedef enum VpCliEncodedDataType {
+    VP_CLI_ENCODE_END = 0,
+    VP_CLI_ENCODE_DATA = 1,
+    VP_CLI_ENCODE_MARKOUT = 2
+} VpCliEncodedDataType;
+
+VpStatusType
+VpSeq(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pProfile);
+
+VpStatusType
+VpBranchInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+
+VpStatusType
+VpTimeInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+
+#if (defined (VP_CC_890_SERIES) && defined (VP890_FXS_SUPPORT)) || \
+    (defined (VP_CC_880_SERIES) && defined (VP880_FXS_SUPPORT))
+bool
+VpCSLACHowlerInit(
+    VpSeqDataType *cadence,
+    uint16 tickRate);
+
+uint16
+VpDecimalMultiply(
+    uint16 value,
+    uint16 byteMask);
+
+bool
+VpCSLACProcessRampGenerators(
+    VpSeqDataType *cadence);
+#endif
+
+bool
+VpServiceSeq(
+    VpDevCtxType *pDevCtx);
+
+void
+VpCSLACInitCidStruct(
+    VpCallerIdType *pCidStruct,
+    uint8 sequenceData);
+
+VpStatusType
+VpCidSeq(
+    VpLineCtxType *pLineCtx);
+
+void
+VpCliStopCli(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+VpCSLACCliGetEncodedByte(
+    uint8 *pByte,
+    VpCallerIdType *pCidStruct,
+    uint16 *pProcessData,
+    VpOptionEventMaskType *pLineEvents,
+    uint8 checkSumIndex);
+
+VpStatusType
+VpCSLACInitMeter(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+
+VpStatusType
+VpCSLACStartMeter(
+    VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+
+#if defined (VP_CC_790_SERIES)
+VpStatusType
+Vp790CommandInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+#endif
+
+#if defined (VP_CC_880_SERIES)
+VpStatusType
+Vp880CommandInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+#endif
+
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+Vp580CommandInstruction(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSeqData);
+#endif
+
+#endif
+
+#endif
+
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_dev_term.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_dev_term.h
new file mode 100644
index 0000000..0baa9c1
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_dev_term.h
@@ -0,0 +1,82 @@
+/** \file vp_api_dev_term.h
+ * vp_api_dev_term.h
+ *
+ * This file contains declaration for VP-API Device and termination types.
+ *
+ * $Revision: 8873 $
+ * $LastChangedDate: 2011-09-23 12:00:01 -0500 (Fri, 23 Sep 2011) $
+ */
+
+#ifndef VP_API_DEV_TERM_H
+#define VP_API_DEV_TERM_H
+
+/******************************************************************************
+ *                                ENUMERATIONS                                *
+ ******************************************************************************/
+/* Valid Device Types supported by VP-API-II. For the corresponding part numbers
+ * supported by each device type please see VP-API-II documentation.
+ */
+typedef enum VpDeviceType {
+    VP_DEV_RSRVD1 = 0,
+    VP_DEV_580_SERIES,
+    VP_DEV_790_SERIES,
+    VP_DEV_VCP_SERIES,
+    VP_DEV_880_SERIES = 4,  /* Fixed value to match calibration profile */
+    VP_DEV_RSVD_SERIES,
+    VP_DEV_VCP2_SERIES,
+    VP_DEV_KWRAP,
+    VP_DEV_890_SERIES = 8,  /* Fixed value to match calibration profile */
+    VP_DEV_792_SERIES,
+    VP_DEV_MELT_SERIES,
+    VP_DEV_792_GROUP,
+    VP_NUM_DEV_TYPES,
+    VP_DEV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceType;
+
+/**
+ * Deprecated name (VCP) based on older name for VCP. All new applications
+ * should use VCP instead
+ */
+#define VP_DEV_DVP_SERIES  VP_DEV_VCP_SERIES
+
+/** Valid Termination Types (per line) supported by API-II.  See the VP-API-II
+    Reference Guide for descriptions. */
+typedef enum VpTermType {
+    /* FXS */
+    VP_TERM_FXS_GENERIC            = 0x00, VP_TERM_FXS_FIRST = VP_TERM_FXS_GENERIC,
+    VP_TERM_FXS_ISOLATE            = 0x01,
+    VP_TERM_FXS_TITO_TL_R          = 0x02,
+    VP_TERM_FXS_CO_TL              = 0x03,
+    VP_TERM_FXS_75181              = 0x04,
+    VP_TERM_FXS_75282              = 0x05,
+    VP_TERM_FXS_RDT                = 0x06,
+    VP_TERM_FXS_RR                 = 0x07,
+    VP_TERM_FXS_SPLITTER           = 0x08,
+    VP_TERM_FXS_TO_TL              = 0x09,
+    VP_TERM_FXS_LOW_PWR            = 0x0A,
+    VP_TERM_FXS_TI                 = 0x0B,
+    VP_TERM_FXS_SPLITTER_LP        = 0x0C,
+    VP_TERM_FXS_ISOLATE_LP         = 0x0D,
+    VP_TERM_FXS_LCAS               = 0x0E,
+    VP_TERM_FXS_RR_TI              = 0x0F,
+    VP_TERM_FXS_CUSTOM             = 0x10,
+    VP_TERM_FXS_TL_MW              = 0x11, VP_TERM_FXS_LAST = VP_TERM_FXS_TL_MW,
+
+    /* MeLT */
+    VP_TERM_MELT_RELAY_CAL_CT      = 0x40, VP_TERM_MELT_FIRST = VP_TERM_MELT_RELAY_CAL_CT,
+    VP_TERM_MELT_RELAY_CAL_SPLIT   = 0x41,
+    VP_TERM_MELT_RELAY_CAL_BRIDGED = 0x42,
+    VP_TERM_MELT_LTAS_CT           = 0x43,
+    VP_TERM_MELT_RELAY_CT          = 0x44,
+    VP_TERM_MELT_RELAY_SPLIT       = 0x45,
+    VP_TERM_MELT_RELAY_BRIDGED     = 0x46, VP_TERM_MELT_LAST = VP_TERM_MELT_RELAY_BRIDGED,
+
+    /* FXO */
+    VP_TERM_FXO_GENERIC            = 0x80, VP_TERM_FXO_FIRST = VP_TERM_FXO_GENERIC,
+    VP_TERM_FXO_DISC               = 0x81,
+    VP_TERM_FXO_CUSTOM             = 0x82, VP_TERM_FXO_LAST = VP_TERM_FXO_CUSTOM,
+
+    VP_TERM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpTermType;
+
+#endif /* VP_API_DEV_TERM_H */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_event.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_event.h
new file mode 100644
index 0000000..7714232
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_event.h
@@ -0,0 +1,599 @@
+/** \file vp_api_event.h
+ * vp_api_event.h
+ *
+ * This file contains declaration associated with VP-API events.
+ *
+ * $Revision: 8929 $
+ * $LastChangedDate: 2011-10-07 15:22:45 -0500 (Fri, 07 Oct 2011) $
+ */
+
+#ifndef VP_API_EVENT_H
+#define VP_API_EVENT_H
+
+#include "vp_api_types.h"
+
+#define VP_EVENT_MASK_ALL       0xFFFF
+
+/* Event category type */
+typedef enum VpEventCategoryType {
+    VP_EVCAT_FAULT     = 0,
+    VP_EVCAT_SIGNALING = 1,
+    VP_EVCAT_RESPONSE  = 2,
+    VP_EVCAT_TEST      = 3,
+    VP_EVCAT_PROCESS   = 4,
+    VP_EVCAT_FXO       = 5,
+    VP_EVCAT_PACKET    = 6,
+    VP_NUM_EVCATS,
+    VP_EVCAT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpEventCategoryType;
+
+typedef struct VpOptionEventMaskType {
+    uint16 faults;      /**< Fault event mask */
+    uint16 signaling;   /**< Signaling event mask */
+    uint16 response;    /**< Mailbox response event mask */
+    uint16 test;        /**< Test events */
+    uint16 process;     /**< Call process related events */
+    uint16 fxo;         /**< FXO events mask */
+    uint16 packet;      /**< Packet events mask - no longer used */
+} VpOptionEventMaskType;
+
+#ifdef STRICT_SIGNED_ENUM_VALUES
+typedef uint16 VpFaultEventType;
+#define VP_DEV_EVID_BAT_FLT         (0x0001)
+#define VP_DEV_EVID_CLK_FLT         (0x0002)
+#define VP_LINE_EVID_THERM_FLT      (0x0004)
+#define VP_LINE_EVID_DC_FLT         (0x0008)
+#define VP_LINE_EVID_AC_FLT         (0x0010)
+#define VP_LINE_EVID_SYNC_FLT       (0x0020)
+#define VP_LINE_EVID_RES_LEAK_FLT   (0x0040)
+#define VP_LINE_EVID_SEAL_CUR_FLT   (0x0080)
+#define VP_DEV_EVID_WDT_FLT         (0x2000)
+#define VP_DEV_EVID_EVQ_OFL_FLT     (0x4000)
+#define VP_DEV_EVID_SYSTEM_FLT      (0x8000)
+
+/* The following fault events are device-specific, not line-specific */
+#define VP_EVCAT_FAULT_DEV_EVENTS   (VP_DEV_EVID_BAT_FLT     | \
+                                     VP_DEV_EVID_CLK_FLT     | \
+                                     VP_DEV_EVID_EVQ_OFL_FLT | \
+                                     VP_DEV_EVID_WDT_FLT     | \
+                                     VP_DEV_EVID_SYSTEM_FLT)
+
+/* Remaining undefined events should be masked to protect against future changes */
+#define VP_EVCAT_FAULT_UNDEFINED    (~(VP_DEV_EVID_BAT_FLT     | \
+                                       VP_DEV_EVID_CLK_FLT     | \
+                                       VP_LINE_EVID_THERM_FLT  | \
+                                       VP_LINE_EVID_DC_FLT     | \
+                                       VP_LINE_EVID_AC_FLT     | \
+                                       VP_LINE_EVID_SYNC_FLT   | \
+                                       VP_LINE_EVID_RES_LEAK_FLT | \
+                                       VP_LINE_EVID_SEAL_CUR_FLT | \
+                                       VP_DEV_EVID_WDT_FLT     | \
+                                       VP_DEV_EVID_EVQ_OFL_FLT | \
+                                       VP_DEV_EVID_SYSTEM_FLT))
+
+#define VP_EVCAT_FAULT_UNMASK_ALL   (VP_EVENT_MASK_ALL & VP_EVCAT_FAULT_UNDEFINED)
+#define VP_EVCAT_FAULT_MASK_ALL     (~VP_EVCAT_FAULT_UNDEFINED)
+#else
+typedef enum VpFaultEventType {
+    VP_DEV_EVID_BAT_FLT         = 0x0001, /**< Device detected battery fault */
+    VP_DEV_EVID_CLK_FLT         = 0x0002, /**< Device detected clock fault */
+    VP_LINE_EVID_THERM_FLT      = 0x0004, /**< Thermal Overload condition */
+    VP_LINE_EVID_DC_FLT         = 0x0008, /**< DC Fault detected on line */
+    VP_LINE_EVID_AC_FLT         = 0x0010, /**< AC Fault detected on line */
+    VP_LINE_EVID_SYNC_FLT       = 0x0020, /**< SLAC Synchronization fault */
+    VP_LINE_EVID_RES_LEAK_FLT   = 0x0040, /**< Low loop resistance while on-hook */
+    VP_LINE_EVID_SEAL_CUR_FLT   = 0x0080, /**< Sealing current error */
+    VP_DEV_EVID_WDT_FLT         = 0x2000, /**< Watchdog timer fault */
+    VP_DEV_EVID_EVQ_OFL_FLT     = 0x4000, /**< event queue overflow fault */
+    VP_DEV_EVID_SYSTEM_FLT      = 0x8000, /**< VCP2 system fault */
+    /* The following fault events are device-specific, not line-specific */
+    VP_EVCAT_FAULT_DEV_EVENTS   = (int)(VP_DEV_EVID_BAT_FLT     |
+                                        VP_DEV_EVID_CLK_FLT     |
+                                        VP_DEV_EVID_EVQ_OFL_FLT |
+                                        VP_DEV_EVID_WDT_FLT     |
+                                        VP_DEV_EVID_SYSTEM_FLT),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_FAULT_UNDEFINED    = (int)(~(VP_DEV_EVID_BAT_FLT     |
+                                          VP_DEV_EVID_CLK_FLT     |
+                                          VP_LINE_EVID_THERM_FLT  |
+                                          VP_LINE_EVID_DC_FLT     |
+                                          VP_LINE_EVID_AC_FLT     |
+                                          VP_LINE_EVID_SYNC_FLT   |
+                                          VP_LINE_EVID_RES_LEAK_FLT |
+                                          VP_LINE_EVID_SEAL_CUR_FLT |
+                                          VP_DEV_EVID_WDT_FLT     |
+                                          VP_DEV_EVID_EVQ_OFL_FLT |
+                                          VP_DEV_EVID_SYSTEM_FLT)), /* NOTES:
+    * The typecasting (int) is necessary in some compilers that have
+    * sizeof(enum)  == sizeof(int) == 2bytes and also because of 'C' rules for
+    * hexadecimal constants. Hexadecimal constants are treated as unsigned and
+    * enum variables are of type signed int. Thus compilers generate warning
+    * when code attempts to assign number that is bigger than what a signed enum
+    * can hold */
+
+    VP_EVCAT_FAULT_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                         VP_EVCAT_FAULT_UNDEFINED),
+    VP_EVCAT_FAULT_MASK_ALL     = (int)(~VP_EVCAT_FAULT_UNDEFINED),
+    VP_EVCAT_FAULT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpFaultEventType;
+#endif
+
+#ifdef STRICT_SIGNED_ENUM_VALUES
+typedef uint16 VpSignalingEventType;
+#define VP_LINE_EVID_HOOK_OFF       (0x0001)
+#define VP_LINE_EVID_HOOK_ON        (0x0002)
+#define VP_LINE_EVID_GKEY_DET       (0x0004)
+#define VP_LINE_EVID_GKEY_REL       (0x0008)
+#define VP_LINE_EVID_FLASH          (0x0010)
+#define VP_LINE_EVID_STARTPULSE     (0x0020)
+#define VP_LINE_EVID_DTMF_DIG       (0x0040)
+#define VP_LINE_EVID_PULSE_DIG      (0x0080)
+#define VP_LINE_EVID_MTONE          (0x0100)
+#define VP_DEV_EVID_TS_ROLLOVER     (0x0200)
+
+#define VP_LINE_EVID_US_TONE_DETECT (0x0400)
+#define VP_LINE_EVID_DS_TONE_DETECT (0x0800)
+#define VP_DEV_EVID_SEQUENCER       (0x1000)
+#define VP_LINE_EVID_BREAK_MAX      (0x2000)
+#define VP_LINE_EVID_EXTD_FLASH     (0x4000)
+#define VP_LINE_EVID_HOOK_PREQUAL   (0x8000)
+
+/* The following signaling events are device-specific, not line-specific */
+#define VP_EVCAT_SIGNALING_DEV_EVENTS   (VP_DEV_EVID_TS_ROLLOVER | VP_DEV_EVID_SEQUENCER)
+
+/* Remaining undefined events should be masked to protect againstfuture changes */
+#define VP_EVCAT_SIGNALING_UNDEFINED    (~(VP_LINE_EVID_HOOK_OFF        | \
+                                           VP_LINE_EVID_HOOK_ON         | \
+                                           VP_LINE_EVID_GKEY_DET        | \
+                                           VP_LINE_EVID_GKEY_REL        | \
+                                           VP_LINE_EVID_FLASH           | \
+                                           VP_LINE_EVID_STARTPULSE      | \
+                                           VP_LINE_EVID_DTMF_DIG        | \
+                                           VP_LINE_EVID_PULSE_DIG       | \
+                                           VP_LINE_EVID_MTONE           | \
+                                           VP_DEV_EVID_TS_ROLLOVER      | \
+                                           VP_LINE_EVID_US_TONE_DETECT  | \
+                                           VP_LINE_EVID_DS_TONE_DETECT  | \
+                                           VP_DEV_EVID_SEQUENCER        | \
+                                           VP_LINE_EVID_BREAK_MAX       | \
+                                           VP_LINE_EVID_EXTD_FLASH      | \
+                                           VP_LINE_EVID_HOOK_PREQUAL))
+
+#define VP_EVCAT_SIGNALING_UNMASK_ALL   (VP_EVENT_MASK_ALL & VP_EVCAT_SIGNALING_UNDEFINED)
+#define VP_EVCAT_SIGNALING_MASK_ALL     (~VP_EVCAT_SIGNALING_UNDEFINED)
+#else
+typedef enum VpSignalingEventType {
+    VP_LINE_EVID_HOOK_OFF       = 0x0001, /**< Off-Hook detected */
+    VP_LINE_EVID_HOOK_ON        = 0x0002, /**< On-Hook detected */
+    VP_LINE_EVID_GKEY_DET       = 0x0004, /**< Ground Key detected */
+    VP_LINE_EVID_GKEY_REL       = 0x0008, /**< Ground Key release detected */
+    VP_LINE_EVID_FLASH          = 0x0010, /**< Hook switch flash detected */
+    VP_LINE_EVID_STARTPULSE     = 0x0020, /**< Start of a dial pulse detected */
+    VP_LINE_EVID_DTMF_DIG       = 0x0040, /**< New DTMF digit detected */
+    VP_LINE_EVID_PULSE_DIG      = 0x0080, /**< New pulse digit detected */
+    VP_LINE_EVID_MTONE          = 0x0100, /**< Modem tone detected */
+    VP_DEV_EVID_TS_ROLLOVER     = 0x0200, /**< Timestamp rollover */
+
+    VP_LINE_EVID_US_TONE_DETECT = 0x0400, /**< Upstream tone detection event */
+    VP_LINE_EVID_DS_TONE_DETECT = 0x0800, /**< Downstream tone detection event*/
+    VP_DEV_EVID_SEQUENCER       = 0x1000, /**< Sequencer Event */
+    VP_LINE_EVID_BREAK_MAX      = 0x2000, /**< Break Max time has been exceeded */
+    VP_LINE_EVID_EXTD_FLASH     = 0x4000, /**< Flash Hook between flash max and on-hook min */
+    VP_LINE_EVID_HOOK_PREQUAL   = 0x8000, /**< debounced off/on hook detected, but < offHookMin */
+
+    /* The following signaling events are device-specific, not line-specific */
+    VP_EVCAT_SIGNALING_DEV_EVENTS  = (int)(VP_DEV_EVID_TS_ROLLOVER |
+                                            VP_DEV_EVID_SEQUENCER),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_SIGNALING_UNDEFINED   = (int)(~(VP_LINE_EVID_HOOK_OFF          |
+                                             VP_LINE_EVID_HOOK_ON           |
+                                             VP_LINE_EVID_GKEY_DET          |
+                                             VP_LINE_EVID_GKEY_REL          |
+                                             VP_LINE_EVID_FLASH             |
+                                             VP_LINE_EVID_STARTPULSE        |
+                                             VP_LINE_EVID_DTMF_DIG          |
+                                             VP_LINE_EVID_PULSE_DIG         |
+                                             VP_LINE_EVID_MTONE             |
+                                             VP_DEV_EVID_TS_ROLLOVER        |
+                                             VP_LINE_EVID_US_TONE_DETECT    |
+                                             VP_LINE_EVID_DS_TONE_DETECT    |
+                                             VP_DEV_EVID_SEQUENCER          |
+                                             VP_LINE_EVID_BREAK_MAX         |
+                                             VP_LINE_EVID_EXTD_FLASH        |
+                                             VP_LINE_EVID_HOOK_PREQUAL)),
+
+    VP_EVCAT_SIGNALING_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                             VP_EVCAT_SIGNALING_UNDEFINED),
+    VP_EVCAT_SIGNALING_MASK_ALL     = (int)(~VP_EVCAT_SIGNALING_UNDEFINED),
+    VP_EVCAT_SIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSignalingEventType;
+#endif
+
+#ifdef STRICT_SIGNED_ENUM_VALUES
+typedef uint16 VpResponseEventType;
+#define VP_DEV_EVID_BOOT_CMP        (0x0001)
+
+#define VP_LINE_EVID_LLCMD_TX_CMP   (0x0002)
+#define VP_LINE_EVID_LLCMD_RX_CMP   (0x0004)
+
+#define VP_DEV_EVID_DNSTR_MBOX      (0x0008)
+#define VP_LINE_EVID_RD_OPTION      (0x0010)
+#define VP_LINE_EVID_RD_LOOP        (0x0020)
+
+#define VP_EVID_CAL_CMP             (0x0040)
+#define VP_EVID_CAL_BUSY            (0x0080)
+#define VP_LINE_EVID_GAIN_CMP       (0x0100)
+#define VP_LINE_EVID_QUERY_CMP      (0x0200)
+#define VP_DEV_EVID_DEV_INIT_CMP    (0x0400)
+#define VP_LINE_EVID_LINE_INIT_CMP  (0x0800)
+#define VP_DEV_EVID_IO_ACCESS_CMP   (0x1000)
+#define VP_LINE_EVID_LINE_IO_RD_CMP (0x2000)
+#define VP_LINE_EVID_LINE_IO_WR_CMP (0x4000)
+#define VP_LINE_EVID_SLAC_INIT_CMP  (0x8000)
+
+/* The following response events are device-specific, not line-specific */
+#define VP_EVCAT_RESPONSE_DEV_EVENTS    (VP_DEV_EVID_BOOT_CMP       | \
+                                         VP_DEV_EVID_DNSTR_MBOX     | \
+                                         VP_DEV_EVID_DEV_INIT_CMP   | \
+                                         VP_DEV_EVID_IO_ACCESS_CMP)
+
+/* Remaining undefined events should be masked to protect against future changes */
+#define VP_EVCAT_RESPONSE_UNDEFINED     (~(VP_DEV_EVID_BOOT_CMP         | \
+                                           VP_LINE_EVID_LLCMD_TX_CMP    | \
+                                           VP_LINE_EVID_LLCMD_RX_CMP    | \
+                                           VP_DEV_EVID_DNSTR_MBOX       | \
+                                           VP_LINE_EVID_RD_OPTION       | \
+                                           VP_LINE_EVID_RD_LOOP         | \
+                                           VP_EVID_CAL_CMP              | \
+                                           VP_EVID_CAL_BUSY             | \
+                                           VP_LINE_EVID_GAIN_CMP        | \
+                                           VP_LINE_EVID_QUERY_CMP       | \
+                                           VP_DEV_EVID_DEV_INIT_CMP     | \
+                                           VP_LINE_EVID_LINE_INIT_CMP   | \
+                                           VP_DEV_EVID_IO_ACCESS_CMP    | \
+                                           VP_LINE_EVID_LINE_IO_RD_CMP  | \
+                                           VP_LINE_EVID_LINE_IO_WR_CMP  | \
+                                           VP_LINE_EVID_SLAC_INIT_CMP))
+
+#define VP_EVCAT_RESPONSE_UNMASK_ALL    (VP_EVENT_MASK_ALL & VP_EVCAT_RESPONSE_UNDEFINED)
+#define VP_EVCAT_RESPONSE_MASK_ALL      (~VP_EVCAT_RESPONSE_UNDEFINED)
+#else
+typedef enum VpResponseEventType {
+    VP_DEV_EVID_BOOT_CMP        = 0x0001, /**< VCP Startup sequence has
+                                           * completed; Non-maskable
+                                           */
+    VP_LINE_EVID_LLCMD_TX_CMP   = 0x0002, /**< Low level write transaction has
+                                           * completed
+                                           */
+    VP_LINE_EVID_LLCMD_RX_CMP   = 0x0004, /**< Low Level read transaction has
+                                           * completed
+                                           */
+    VP_DEV_EVID_DNSTR_MBOX      = 0x0008, /**< Dowstream Mailbox event ready */
+    VP_LINE_EVID_RD_OPTION      = 0x0010, /**< Read Option request complete */
+    VP_LINE_EVID_RD_LOOP        = 0x0020, /**< Read Loop Conditions is complete
+                                           */
+    VP_EVID_CAL_CMP             = 0x0040, /**< Device or Line Calibration is
+                                           * complete
+                                           */
+    VP_EVID_CAL_BUSY            = 0x0080, /**< Calibration not performed, line
+                                           * busy
+                                           */
+    VP_LINE_EVID_GAIN_CMP       = 0x0100, /**< Gain Adjustment complete */
+    VP_LINE_EVID_QUERY_CMP      = 0x0200, /**< Query complete */
+    VP_DEV_EVID_DEV_INIT_CMP    = 0x0400, /**< Device Init complete */
+    VP_LINE_EVID_LINE_INIT_CMP  = 0x0800, /**< Line Init complete */
+    VP_DEV_EVID_IO_ACCESS_CMP   = 0x1000, /**< Device Access complete */
+    VP_LINE_EVID_LINE_IO_RD_CMP = 0x2000, /**< Line GPIO read complete */
+    VP_LINE_EVID_LINE_IO_WR_CMP = 0x4000, /**< Line GPIO write complete */
+    VP_LINE_EVID_SLAC_INIT_CMP  = 0x8000, /**< SLAC Init complete */
+    /* The following response events are device-specific, not line-specific */
+    VP_EVCAT_RESPONSE_DEV_EVENTS = (int)(VP_DEV_EVID_BOOT_CMP       |
+                                        VP_DEV_EVID_DNSTR_MBOX      |
+                                        VP_DEV_EVID_DEV_INIT_CMP    |
+                                        VP_DEV_EVID_IO_ACCESS_CMP),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_RESPONSE_UNDEFINED = (int)(~(VP_DEV_EVID_BOOT_CMP          |
+                                          VP_LINE_EVID_LLCMD_TX_CMP     |
+                                          VP_LINE_EVID_LLCMD_RX_CMP     |
+                                          VP_DEV_EVID_DNSTR_MBOX        |
+                                          VP_LINE_EVID_RD_OPTION        |
+                                          VP_LINE_EVID_RD_LOOP          |
+                                          VP_EVID_CAL_CMP               |
+                                          VP_EVID_CAL_BUSY              |
+                                          VP_LINE_EVID_GAIN_CMP         |
+                                          VP_LINE_EVID_QUERY_CMP        |
+                                          VP_DEV_EVID_DEV_INIT_CMP      |
+                                          VP_LINE_EVID_LINE_INIT_CMP    |
+                                          VP_DEV_EVID_IO_ACCESS_CMP     |
+                                          VP_LINE_EVID_LINE_IO_RD_CMP   |
+                                          VP_LINE_EVID_LINE_IO_WR_CMP   |
+                                          VP_LINE_EVID_SLAC_INIT_CMP)),
+
+    VP_EVCAT_RESPONSE_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                            VP_EVCAT_RESPONSE_UNDEFINED),
+    VP_EVCAT_RESPONSE_MASK_ALL     = (int)(~VP_EVCAT_RESPONSE_UNDEFINED),
+    VP_EVCAT_RES_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpResponseEventType;
+#endif
+
+typedef enum VpTestEventType {
+    VP_LINE_EVID_TEST_CMP   = 0x0001, /**< A requested test has been completed*/
+    VP_LINE_EVID_TEST_RSVD1 = 0x0002, /**< Reserved event */
+    VP_LINE_EVID_DTONE_DET  = 0x0004, /**< Dial-Tone Test - Dialtone Detected */
+    VP_LINE_EVID_DTONE_LOSS = 0x0008, /**< Dial-Tone Test - Dialtone Lost */
+    VP_DEV_EVID_STEST_CMP   = 0x0010, /**< Self Test Function complete */
+    VP_DEV_EVID_CHKSUM      = 0x0020, /**< Code-space checksum is complete */
+    VP_LINE_EVID_ABORT      = 0x0040, /**< Event requesting abort test */
+    /* The following test events are device-specific, not line-specific */
+    VP_EVCAT_TEST_DEV_EVENTS = (int)(VP_DEV_EVID_CHKSUM),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_TEST_UNDEFINED =    (int)(~(VP_LINE_EVID_TEST_CMP       |
+                                         VP_LINE_EVID_DTONE_DET      |
+                                         VP_LINE_EVID_DTONE_LOSS     |
+                                         VP_DEV_EVID_STEST_CMP       |
+                                         VP_DEV_EVID_CHKSUM)),
+
+    VP_EVCAT_TEST_UNMASK_ALL    =  (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_TEST_UNDEFINED),
+    VP_EVCAT_TEST_MASK_ALL      =  (int)(~VP_EVCAT_TEST_UNDEFINED),
+    VP_EVCAT_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpTestEventType;
+
+typedef enum VpProcessEventType {
+    VP_LINE_EVID_MTR_CMP        = 0x0001, /**< Metering Signal complete */
+    VP_LINE_EVID_MTR_ABORT      = 0x0002, /**< Metering Signal aborted */
+    VP_LINE_EVID_CID_DATA       = 0x0004, /**< Caller ID Transmission buffer is
+                                           * empty
+                                           */
+    VP_LINE_EVID_RING_CAD       = 0x0008, /**< Ring Cadence State change
+                                           * information
+                                           */
+    VP_LINE_EVID_SIGNAL_CMP     = 0x0010, /**< Signal Generation complete */
+    VP_LINE_EVID_MTR_CAD        = 0x0020, /**< Metering cadence */
+
+    VP_LINE_EVID_TONE_CAD       = 0x0040, /**< Tone Cadence complete */
+
+    VP_LINE_EVID_MTR_ROLLOVER   = 0x0080, /**< Metering count rollover */
+    VP_LINE_EVID_GEN_TIMER      = 0x0100, /**< Timer complete / canceled / error */
+    VP_LINE_EVID_USER           = 0x0200, /**< User-defined event */
+    VP_LINE_EVID_AUTO_LOOP_COND = 0x0400, /**< VP_OPTION_ID_AUTO_LOOP_COND event */
+
+    /* There are no device-specific process events */
+    VP_EVCAT_PROCESS_DEV_EVENTS = 0,
+
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_PROCESS_UNDEFINED =  (int)(~(VP_LINE_EVID_MTR_CMP        |
+                                          VP_LINE_EVID_MTR_ABORT      |
+                                          VP_LINE_EVID_CID_DATA       |
+                                          VP_LINE_EVID_RING_CAD       |
+                                          VP_LINE_EVID_SIGNAL_CMP     |
+                                          VP_LINE_EVID_MTR_CAD        |
+                                          VP_LINE_EVID_TONE_CAD       |
+                                          VP_LINE_EVID_MTR_ROLLOVER   |
+                                          VP_LINE_EVID_GEN_TIMER      |
+                                          VP_LINE_EVID_USER)),
+
+    VP_EVCAT_PROCESS_UNMASK_ALL =  (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_PROCESS_UNDEFINED),
+    VP_EVCAT_PROCESS_MASK_ALL   =  (int)(~VP_EVCAT_PROCESS_UNDEFINED),
+    VP_EVCAT_PRO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProcessEventType;
+
+typedef enum VpFxoEventType {
+    /* FXO API Event Types */
+    VP_LINE_EVID_RING_ON    = 0x0001, /**< Ringing detected on line */
+    VP_LINE_EVID_RING_OFF   = 0x0002, /**< Ringing previously detected has
+                                       * stopped
+                                       */
+    VP_LINE_EVID_LIU        = 0x0004, /**< Line In Use by adjacent line off
+                                       * hook
+                                       */
+    VP_LINE_EVID_LNIU       = 0x0008, /**< Line In Use by adjacent line on
+                                       * hook */
+    VP_LINE_EVID_FEED_DIS   = 0x0010, /**< Line feed disabled (or too low) */
+    VP_LINE_EVID_FEED_EN    = 0x0020, /**< Line feed enabled */
+    VP_LINE_EVID_DISCONNECT = 0x0040, /**< Line feed removed while loop close */
+    VP_LINE_EVID_RECONNECT  = 0x0080, /**< Line feed connected while loop
+                                       * close
+                                       */
+    VP_LINE_EVID_POLREV     = 0x0100, /**< Line polarity reversal has occurred*/
+    VP_LINE_EVID_POH        = 0x0200, /**< Parallel line off-hook */
+    VP_LINE_EVID_PNOH       = 0x0400, /**< Parallel line on-hook */
+
+    /* There are no device-specific FXO events */
+    VP_EVCAT_FXO_DEV_EVENTS = 0,
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_FXO_UNDEFINED =     (int)(~(VP_LINE_EVID_RING_ON        |
+                                         VP_LINE_EVID_RING_OFF       |
+                                         VP_LINE_EVID_LIU            |
+                                         VP_LINE_EVID_LNIU           |
+                                         VP_LINE_EVID_FEED_DIS       |
+                                         VP_LINE_EVID_FEED_EN        |
+                                         VP_LINE_EVID_DISCONNECT     |
+                                         VP_LINE_EVID_RECONNECT      |
+                                         VP_LINE_EVID_POLREV         |
+                                         VP_LINE_EVID_POH            |
+                                         VP_LINE_EVID_PNOH)),
+
+    VP_EVCAT_FXO_UNMASK_ALL =      (int)(VP_EVENT_MASK_ALL &
+                                     VP_EVCAT_FXO_UNDEFINED),
+    VP_EVCAT_FXO_MASK_ALL   =      (int)(~VP_EVCAT_FXO_UNDEFINED),
+    VP_EVCAT_FXO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpFxoEventType;
+
+typedef enum VpPacketEventType {
+    VP_LINE_EVID_US_PKT_RDY     = 0x0001, /**< Upstream Packet ready event */
+    VP_LINE_EVID_NEED_DS_PKT    = 0x0002, /**< Need Downstream Packet event */
+    VP_LINE_EVID_PKT_ERROR      = 0x0004, /**< Packet type error event */
+    VP_LINE_EVID_PKT_LOST       = 0x0008, /**< Packet loss event */
+    VP_LINE_EVID_RD_PKT_STATS   = 0x0010, /**< Read packet statistics complete*/
+    /* There are no device-specific packet events */
+    VP_EVCAT_PACKET_DEV_EVENTS  = 0,
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_PACKET_UNDEFINED =   (int)(~(VP_LINE_EVID_US_PKT_RDY       |
+                                          VP_LINE_EVID_NEED_DS_PKT      |
+                                          VP_LINE_EVID_PKT_ERROR        |
+                                          VP_LINE_EVID_PKT_LOST         |
+                                          VP_LINE_EVID_RD_PKT_STATS)),
+
+    VP_EVCAT_PACKET_UNMASK_ALL  =   (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_PACKET_UNDEFINED),
+    VP_EVCAT_PACKET_MASK_ALL    =  (int)(~VP_EVCAT_PACKET_UNDEFINED),
+    VP_EVCAT_PKT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPacketEventType;
+
+/* Enumerations for interpreting event data in the VpGetEvent() field */
+typedef enum VpBatFltEventDataType {
+    VP_BAT_FLT_NONE = 0x0,
+    VP_BAT_FLT_BAT2 = 0x1,
+    VP_BAT_FLT_BAT1 = 0x2,
+    VP_BAT_FLT_BAT3 = 0x4,
+    VP_BAT_FLT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatFltEventDataType;
+
+typedef enum VpRingCadEventDataType {
+    VP_RING_CAD_BREAK = 0,
+    VP_RING_CAD_MAKE  = 1,
+    VP_RING_CAD_DONE  = 2,
+    VP_RING_CAD_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpRingCadEventDataType;
+
+typedef enum VpCidDataEventDataType {
+    VP_CID_DATA_NEED_MORE_DATA = 0,
+    VP_CID_DATA_TX_DONE        = 1,
+    VP_CID_DATA_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCidDataEventDataType;
+
+typedef enum VpDigitType {
+    VP_DIG_1         = 0x01,
+    VP_DIG_2         = 0x02,
+    VP_DIG_3         = 0x03,
+    VP_DIG_4         = 0x04,
+    VP_DIG_5         = 0x05,
+    VP_DIG_6         = 0x06,
+    VP_DIG_7         = 0x07,
+    VP_DIG_8         = 0x08,
+    VP_DIG_9         = 0x09,
+    VP_DIG_10        = 0x0A,    /* pulse only */
+    VP_DIG_11        = 0x0B,    /* pulse only */
+    VP_DIG_12        = 0x0C,    /* pulse only */
+    VP_DIG_13        = 0x0D,    /* pulse only */
+    VP_DIG_14        = 0x0E,    /* pulse only */
+    VP_DIG_15        = 0x0F,    /* pulse only */
+    VP_DIG_ZERO      = 0x0A,    /* DTMF only */
+    VP_DIG_ASTER     = 0x0B,    /* DTMF only */
+    VP_DIG_POUND     = 0x0C,    /* DTMF only */
+    VP_DIG_A         = 0x0D,    /* DTMF only */
+    VP_DIG_B         = 0x0E,    /* DTMF only */
+    VP_DIG_C         = 0x0F,    /* DTMF only */
+    VP_DIG_D         = 0x00,    /* DTMF only */
+    VP_DIG_NONE      = 0xFF,
+    VP_DIG_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_DIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitType;
+
+/*
+ * Indicates which set of Dial Pulse Specifications were met that is generating
+ * the dial pulse event.
+ */
+typedef enum VpDialPulseParamType {
+    VP_DP_PARAM1 = 0,
+    VP_DP_PARAM2 = 1,
+    VP_DP_PARAM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDialPulseParamType;
+
+typedef enum VpDigitSenseType {
+    VP_DIG_SENSE_BREAK = 0x0000,
+    VP_DIG_SENSE_MAKE  = 0x0010,
+    VP_DIG_SENSE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitSenseType;
+
+typedef enum VpPolRevEventDataType {
+    VP_POLREV_NORMAL  = 0, /* Line detected Reverse-to-Normal Transition */
+    VP_POLREV_REVERSE = 1, /* Line detected Normal-to-Reverse Transition */
+    VP_POLREV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPolRevEventDataType;
+
+typedef enum VpSyncFltEventDataType {
+    VP_SYNC_MB_ERR        = 0x00,
+    VP_SYNC_SEQ_BAD_INST  = 0x81, /* Unknown instruction in sequence */
+    VP_SYNC_SEQ_BAD_BR    = 0x82, /* Sequencer encountered bad branch (either
+                                   * a forward branch or too many nesting levels */
+    VP_SYNC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSyncFltEventDataType;
+
+typedef enum VpGenTimerStatusType {
+    VP_GEN_TIMER_STATUS_CMP      = 0,
+    VP_GEN_TIMER_STATUS_CANCELED = 1,
+    VP_GEN_TIMER_STATUS_RESRC_NA = 2,
+    VP_GEN_TIMER_STATUS_UNKNOWN  = 3,
+    VP_GEN_TIMER_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGenTimerStatusType;
+
+typedef enum VpFlashEventDataType {
+    VP_FLASH_ONLY = 0,
+    VP_FLASH_AND_DIGIT1 = 1
+} VpFlashEventDataType;
+
+typedef uint16 VpHookPrequalEventDataType;
+#define VP_HOOK_PREQUAL_START   (0) /* Debounced off-hook detected, but offHookMin > 0 */
+#define VP_HOOK_PREQUAL_ABORT   (1) /* Debounced on-hook detected, but duration < offHookMin */
+
+
+/**
+ * Non-maskable events are (with reasons):
+ *
+ *   Boot Complete -- Cannot mask.  Masking events requires that the boot has
+ *                   been completed.
+ *   Read Option -- To modify mask interrupts requires that the current mask
+ *                  options can be read.  The only way to know the read option
+ *                  is ready is via an unmasked Read Option Complete event.
+ *   Device Init -- Fundamental event to know when device is initialized and
+ *                  remaining options/line configurations can be set.  There
+ *                  is no other standard "timeout" mechanism to know when the
+ *                  device has been initialized properly.
+ *   Line Init -- Fundamental event to know when a line is initialized and ready
+ *                to be setup with remaining user defined options.  There is no
+ *                other standard "timeout" mechanism to know when the line has
+ *                been initialized properly.
+ *   Events that have responses -- These events are non-maskable. If an event
+ *                that has a response is masked, and if the response is not
+ *                read, in case of CSLAC devices, it blocks response buffer.
+ *                In case of VCP class of devices, response mailbox is
+ *                locked up. If this is followed by another command that
+ *                requires the response mailbox, that command can't complete
+ *                execution since the response mailbox is busy. Now no more
+ *                commands can be issued because the previous command can't
+ *                complete.
+ */
+
+#define VP_API_NONMASK_FAULT_EVENTS         0x0000
+#define VP_API_NONMASK_SIGNALING_EVENTS     0x0000
+
+#define VP_API_NONMASK_RESPONSE_EVENTS      (VP_DEV_EVID_BOOT_CMP \
+                                           | VP_LINE_EVID_LLCMD_RX_CMP \
+                                           | VP_LINE_EVID_RD_OPTION \
+                                           | VP_LINE_EVID_RD_LOOP \
+                                           | VP_LINE_EVID_GAIN_CMP \
+                                           | VP_LINE_EVID_QUERY_CMP \
+                                           | VP_DEV_EVID_DEV_INIT_CMP \
+                                           | VP_LINE_EVID_LINE_INIT_CMP \
+                                           | VP_DEV_EVID_IO_ACCESS_CMP \
+                                           | VP_LINE_EVID_LINE_IO_RD_CMP \
+                                           | VP_LINE_EVID_SLAC_INIT_CMP)
+
+#define VP_API_NONMASK_TEST_EVENTS          (VP_LINE_EVID_TEST_CMP \
+                                           | VP_DEV_EVID_CHKSUM)
+
+#define VP_API_NONMASK_PROCESS_EVENTS       VP_LINE_EVID_GEN_TIMER
+#define VP_API_NONMASK_FXO_EVENTS           0x0000
+#define VP_API_NONMASK_PACKET_EVENTS        0x0000
+
+#endif /* VP_API_EVENT_H */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_fxo_params.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_fxo_params.h
new file mode 100644
index 0000000..40212eb
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_fxo_params.h
@@ -0,0 +1,68 @@
+/** \file vp_api_fxo_params.h
+ * vp_api_fxo_params.h
+ *
+ * This file contains the approved system parameters for proper
+ * FXO operation on the reference designs
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_FXO_PARAMS_H
+#define VP_API_FXO_PARAMS_H
+
+#define VP_FXO_DTMF_ON_DEFAULT          0x0027  /* DTMF On = 195mS */
+#define VP_FXO_DTMF_OFF_DEFAULT         0x0028  /* DTMF Off = 200mS */
+#define VP_FXO_FLASH_HOOK_DEFAULT       0x0078  /* Flash Hook = 600mS */
+#define VP_FXO_PULSE_BREAK_DEFAULT      0x0C    /* Pulse Break = 60mS */
+#define VP_FXO_PULSE_MAKE_DEFAULT       0x08    /* Pulse Make = 40mS */
+#define VP_FXO_INTERDIG_DEFAULT         0x0028  /* Interdigit Period = 200mS */
+#define VP_FXO_RING_DET_MAX_DEFAULT     0xEB    /* Ring Period Max = 58.75mS */
+#define VP_FXO_RING_DET_MIN_DEFAULT     0x79    /* Ring Period Min = 30.25mS */
+#define VP_FXO_RING_DET_VOLT_DEFAULT    0x02    /* Ring Voltage Min = 38V */
+#define VP_FXO_DISC_DET_MIN_DEFAULT     0x03    /* Disconnect Det Min = 4.2V */
+#define VP_FXO_LIU_DET_THRESH_DEFAULT   0x26    /* Line-In-Use Det Threshold = 38V */
+
+/* In ms, time that FXO detector activity is ignored after a state change */
+#define VP_FXO_STATE_CHANGE_DEBOUNCE    (50)
+
+/* In ms, time that FXO detector activity is ignored after a ring trip */
+#define VP_FXO_RING_TRIP_DEBOUNCE       (200)
+
+/* In ms, time that FXO disconnect detector is debounced */
+#define VP_FXO_DISCONNECT_DEBOUNCE      (300)
+
+/* In ms, time that FXO will change to loop open if detecting disconnect */
+#define VP_FXO_DISC_TO_LOOP_OPEN        (5000)
+
+typedef enum vp_fxo_dialingProfileParams {
+    VP_FXO_DIALING_PROFILE_DTMF_ON_MSB = 6,
+    VP_FXO_DIALING_PROFILE_DTMF_ON_LSB = 7,
+    VP_FXO_DIALING_PROFILE_DTMF_OFF_MSB = 8,
+    VP_FXO_DIALING_PROFILE_DTMF_OFF_LSB = 9,
+    VP_FXO_DIALING_PROFILE_FLASH_HOOK_MSB = 10,
+    VP_FXO_DIALING_PROFILE_FLASH_HOOK_LSB = 11,
+    VP_FXO_DIALING_PROFILE_PULSE_BREAK = 12,
+    VP_FXO_DIALING_PROFILE_PULSE_MAKE = 13,
+    VP_FXO_DIALING_PROFILE_INTERDIGIT_MSB = 14,
+    VP_FXO_DIALING_PROFILE_INTERDIGIT_LSB = 15,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MAX = 16,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MIN = 17,
+    VP_FXO_DIALING_PROFILE_RING_VOLTAGE_MIN = 18,
+    VP_FXO_DIALING_PROFILE_DISC_VOLTAGE_MIN = 19,
+    VP_FXO_DIALING_PROFILE_LIU_THRESHOLD_MIN = 20,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MAX_ACT = 21,
+    VP_FXO_DIALING_PROFILE_DTMF_HIGH_LVL_MSB = 22,
+    VP_FXO_DIALING_PROFILE_DTMF_HIGH_LVL_LSB = 23,
+    VP_FXO_DIALING_PROFILE_DTMF_LOW_LVL_MSB = 24,
+    VP_FXO_DIALING_PROFILE_DTMF_LOW_LVL_LSB = 25,
+    VP_FXO_DIALING_PROFILE_POH_INT_TIME = 26,
+    VP_FXO_DIALING_PROFILE_POH_THRESHOLD = 27,
+    VP_FXO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} vp_fxo_dialingProfileParams;
+#endif
+
+
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_int.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_int.h
new file mode 100644
index 0000000..ef94233
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_int.h
@@ -0,0 +1,652 @@
+/** \file vp_api_int.h
+ * vp_api_int.h
+ *
+ * Header file for the API-II c files. This file contains the declarations
+ * and defintions required to implement the VTD specific VP-API. This file
+ * is used by VP-API internally. This file should not be included by the
+ * application.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_INT_H
+#define VP_API_INT_H
+
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "vp_api.h"
+#include "vp_api_option.h"
+
+#include "vp_debug.h"
+
+/******************************************************************************
+ *                              VP-API Defines                                *
+ ******************************************************************************/
+#define VP_ALL_LINES            0xFF  /**< Internal constant used to identify
+                                       * all lines
+                                       */
+#define VP_ALL_SLACS          0xFFFF  /**< Internal constant used to identify
+                                       * all SLACs
+                                       */
+
+/**< Profile types as defined by Profile Wizard */
+typedef enum VpProfileWizProfileType {
+    VP_PRFWZ_PROFILE_AC = 0x00,
+    VP_PRFWZ_PROFILE_DC = 0x01,
+    VP_PRFWZ_PROFILE_TONE = 0x02,
+    VP_PRFWZ_PROFILE_TONECAD = 0x03,
+    VP_PRFWZ_PROFILE_RING = 0x04,
+    VP_PRFWZ_PROFILE_CID_TYPE1 = 0x05,
+    VP_PRFWZ_PROFILE_CID_TYPE2 = 0x06,
+    VP_PRFWZ_PROFILE_METER = 0x07,
+    VP_PRFWZ_PROFILE_RINGCAD = 0x08,
+    VP_PRFWZ_PROFILE_TEST_CRITERIA = 0x09,
+    VP_PRFWZ_PROFILE_TEST_TOPOLOGY = 0x0A,
+    VP_PRFWZ_PROFILE_FXS_CTRL = 0x0B,
+    VP_PRFWZ_PROFILE_CAL = 0x0C,
+    VP_PRFWZ_PROFILE_METERING_GEN,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_HOOK_FLASH_DIG_GEN,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_DIAL_PULSE_DIG_GEN,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_DTMF_DIG_GEN,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_MSG_WAIT_PULSE_INT,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_LINE_CAL_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_FWD_DISC_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_POLREV_PULSE_INT,      /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_MOMENTARY_LOOP_OPEN_INT,   /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_TIP_OPEN_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_NONE,                  /**< Indicates that internal
+                                                 profile data is not valid */
+    VP_PRFWZ_PROFILE_880_CAL_DATA = 0xFC,
+    VP_PRFWZ_PROFILE_890_CAL_DATA = 0xFD,
+
+    VP_PRFWZ_PROFILE_FXO_CONFIG = 0xFE,
+    VP_PRFWZ_PROFILE_DEVICE = 0xFF,
+    VP_PRFWZ_PROFILE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req.*/
+} VpProfileWizProfileType;
+
+typedef enum VpProfileWizCustomStateType {
+    VP_PRFWZ_CUSTOM_ST_STANDBY = 0x00,
+    VP_PRFWZ_CUSTOM_ST_ACTIVE = 0x02,
+    VP_PRFWZ_CUSTOM_ST_ACTIVE_PR = 0x03,
+    VP_PRFWZ_CUSTOM_ST_TIP_OPEN = 0x04,
+    VP_PRFWZ_CUSTOM_ST_OHT = 0x06,
+    VP_PRFWZ_CUSTOM_ST_OHT_PR = 0x07,
+    VP_PRFWZ_CUSTOM_ST_DISCONNECT = 0x08,
+    VP_PRFWZ_CUSTOM_ST_RINGING = 0x09,
+    VP_PRFWZ_CUSTOM_ST_DET_MAP = 0xFF,
+    VP_PRFWZ_CUSTOM_ST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req.*/
+} VpProfileWizCustomStateType;
+
+/** These locations are common to all profiles used in the API */
+typedef enum VpProfileHeaderFieldType {
+    VP_PROFILE_TYPE_MSB = 0,
+    VP_PROFILE_TYPE_LSB = 1,
+    VP_PROFILE_INDEX = 2,
+    VP_PROFILE_LENGTH = 3,
+    VP_PROFILE_VERSION = 4,
+    VP_PROFILE_MPI_LEN = 5,
+    VP_PROFILE_DATA_START = 6,
+    VP_PROFILE_HDR_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProfileHeaderFieldType;
+
+/* Define the Ringing Type (balanced/unbalanced) offset from end of MPI data */
+#define VP_PROFILE_RING_TYPE_OFFSET     1
+
+/** These are the locations of parameters in version 01 ringing profiles */
+typedef enum VpRingProfileFieldType {
+    VP_RING_PROFILE_RING_TRIP   = 18,
+    VP_RING_PROFILE_CURRENT_LIM = 19,
+    VP_RING_PROFILE_MAX_RING_V  = 20,
+    VP_RING_PROFILE_TRACK_MODE  = 21,
+    VP_RING_PROFILE_ENUM_SIZE  =  FORCE_STANDARD_C_ENUM_SIZE /* Portability Req */
+} VpRingProfileFieldType;
+
+/** These are the locations of parameters in version 01 DC profiles */
+typedef enum VpDcProfileFieldType {
+    VP_DC_PROFILE_THRESHOLDS =  9,
+    VP_DC_PROFILE_DEBOUNCES  =  10,
+    VP_DC_PROFILE_FLOOR_V    =  11,
+    VP_DC_PROFILE_HOOK_HYST  =  12,
+    VP_DC_PROFILE_ENUM_SIZE  =  FORCE_STANDARD_C_ENUM_SIZE /* Portability Req */
+} VpDcProfileFieldType;
+
+typedef enum VpCidProfileFieldType {
+    /*
+     * These parameters are the absolute locations of the specified value in
+     * the CID profile
+     */
+    VP_CID_PROFILE_FSK_PARAM_LEN = 6,
+    VP_CID_PROFILE_FSK_PARAM_CMD = 7,
+    VP_CID_PRFT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCidProfileFieldType;
+
+/*
+ * These parameters are offset from the end of the FSK data to the value
+ * specified
+ */
+#define VP_CID_PROFILE_CHECKSUM_OFFSET_MSB      (1)
+#define VP_CID_PROFILE_CHECKSUM_OFFSET_LSB      (2)
+#define VP_CID_PROFILE_LENGTH_OF_ELEMENTS_MSB   (3)
+#define VP_CID_PROFILE_LENGTH_OF_ELEMENTS_LSB   (4)
+#define VP_CID_PROFILE_START_OF_ELEMENTS_MSB    (5)
+#define VP_CID_PROFILE_START_OF_ELEMENTS_LSB    (6)
+
+/** These locations are for Tone and Ringing Cadence (Sequencer) profiles */
+#define VP_PROFILE_TYPE_SEQUENCER_COUNT_MSB (6)
+#define VP_PROFILE_TYPE_SEQUENCER_COUNT_LSB (7)
+#define VP_PROFILE_TYPE_SEQUENCER_START     (8)
+
+/** These locations are for Calibration profiles */
+#define VP_CAL_PROFILE_NUM_ENTRIES  (6)
+#define VP_CAL_PROFILE_FIRST_ENTRY  (8)
+
+/******************************************************************************
+ *                        API Specific common FUNCTION PROTOTYPES             *
+ ******************************************************************************/
+void
+VpImplementNonMaskEvents(
+    VpOptionEventMaskType *pLineEventsMask,
+    VpOptionEventMaskType *pDevEventsMask);
+
+VpStatusType
+VpImplementDefaultSettings(
+    VpDevCtxType *pDevCtx,
+    VpLineCtxType *pLineCtx);
+
+EXTERN int
+VpGetProfileIndex (
+    const VpProfilePtrType pProfile);
+
+EXTERN bool
+VpVerifyProfileType(
+    VpProfileType type,
+    VpProfilePtrType pProfile);
+
+EXTERN bool
+VpIsDigit(
+    VpDigitType digit);
+
+#if (defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES))
+EXTERN VpStatusType
+VpCSLACSetDTMFGenValues(
+    uint8 *sigGenABParams,
+    VpDigitType digit);
+
+EXTERN bool
+VpCSLACHookMaskEnabled(
+    uint16 fxsTimers[VP_LINE_TIMER_LAST]);
+#endif
+
+/******************************************************************************
+ *                        VCP Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_VCP_SERIES)
+VpStatusType
+VpMakeVcpDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpVcpDeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVcpDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpVcpDeviceObjectType *pDevObj);
+
+#endif /* VP_CC_VCP_SERIES */
+
+/******************************************************************************
+ *                        VCP2 Specific FUNCTION PROTOTYPES                   *
+ ******************************************************************************/
+#if defined (VP_CC_VCP2_SERIES)
+VpStatusType
+Vcp2MakeDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpVcp2DeviceObjectType *pDevObj);
+
+VpStatusType
+Vcp2MakeDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpVcp2DeviceObjectType *pDevObj);
+
+EXTERN bool
+Vcp2ReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN void
+Vcp2SetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+#endif /* VP_CC_VCP2_SERIES */
+/******************************************************************************
+ *                        MELT Specific FUNCTION PROTOTYPES                   *
+ ******************************************************************************/
+#if defined (VP_CC_MELT_SERIES)
+
+VpStatusType
+MeltMakeDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpMeltDeviceObjectType *pDevObj);
+
+VpStatusType
+MeltMakeDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpMeltDeviceObjectType *pDevObj);
+
+EXTERN bool
+MeltReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN void
+MeltSetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+#endif /* VP_CC_MELT_SERIES */
+
+/******************************************************************************
+ *                        Kernel Specific FUNCTION PROTOTYPES                 *
+ ******************************************************************************/
+#if defined (VP_CC_KWRAP)
+  #include "vp_kernel.h"
+#endif /* VP_CC_KWRAP */
+
+
+/******************************************************************************
+ *                        790 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_790_SERIES)
+
+#ifndef VP790_EC_CH1
+  #define VP790_EC_CH1    0x01
+  #define VP790_EC_CH2    0x02
+  #define VP790_EC_CH3    0x04
+  #define VP790_EC_CH4    0x08
+#endif
+
+VpStatusType
+VpMakeVp790DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp790DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp790DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp790DeviceObjectType *pDevObj);
+
+void
+Vp790MuteChannel(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+bool
+Vp790FSKGeneratorReady(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+Vp790CliGetEncodedByte(
+    VpLineCtxType *pLineCtx,
+    uint8 *pByte);
+
+VpStatusType
+Vp790CtrlSetCliTone(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+void
+Vp790CtrlSetFSKGen(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    uint8 data);
+#endif /* VP_CC_790_SERIES */
+
+/******************************************************************************
+ *                        792 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+
+#if defined (VP_CC_792_SERIES)
+VpStatusType
+Vp792MakeDeviceObject(
+    VpDevCtxType            *pDevCtx,
+    Vp792DeviceObjectType   *pDevObj);
+
+VpStatusType
+Vp792MakeDeviceCtx(
+    VpDevCtxType            *pDevCtx,
+    Vp792DeviceObjectType   *pDevObj);
+
+#ifdef VP_CC_792_GROUP
+bool
+Vp792GroupGetEvent(
+    VpDevCtxType *pDevCtx,
+    VpEventType *pEvent);
+#endif
+#endif /* VP_CC_792_SERIES */
+
+/******************************************************************************
+ *                        880 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_880_SERIES)
+
+#ifndef VP880_EC_CH1
+  #define VP880_EC_CH1                0x01
+  #define VP880_EC_CH2                0x02
+#endif
+
+#ifndef VP880_WIDEBAND_MODE
+  #define VP880_WIDEBAND_MODE         0x20
+#endif
+
+VpStatusType
+VpMakeVp880DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp880DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp880DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp880DeviceObjectType *pDevObj);
+
+void
+Vp880MuteChannel(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+#if defined (VP_CSLAC_SEQ_EN) && defined (VP880_FXS_SUPPORT)
+bool
+Vp880FSKGeneratorReady(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+Vp880CliGetEncodedByte(
+    VpLineCtxType *pLineCtx,
+    uint8 *pByte);
+
+VpStatusType
+Vp880CtrlSetCliTone(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+bool
+Vp880CtrlSetFSKGen(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    uint8 data);
+#endif
+
+VpStatusType
+Vp880SetDTMFGenerators(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    VpDigitType digit);
+
+VpStatusType
+Vp880SetLineStateInt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp880SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+void
+Vp880LLSetSysState(
+    VpDeviceIdType deviceId,
+    VpLineCtxType *pLineCtx,
+    uint8 lineState,
+    bool writeToDevice);
+#endif /* VP_CC_880_SERIES */
+
+
+/******************************************************************************
+ *                        890 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_890_SERIES)
+  #include "vp890_api_int.h"
+#endif /* VP_CC_890_SERIES */
+
+
+/******************************************************************************
+ *                        580 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+VpMakeVp580DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp580DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp580DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp580DeviceObjectType *pDevObj);
+
+#endif /* VP_CC_580_SERIES */
+
+/* Functions used internal to the API -- device dependant */
+#if defined (VP_CC_790_SERIES) || defined (VP_CC_880_SERIES) \
+ || defined (VP_CC_580_SERIES) || defined (VP_CC_890_SERIES)
+
+/* Converts ms to units of API_TICKRATE */
+#define MS_TO_TICKRATE(MS, API_TICKRATE)  \
+    ((uint16)(((((uint32)MS*256*2)/API_TICKRATE)+1)/2))
+#define TICKS_TO_MS(TICKS, API_TICKRATE)  \
+    (uint16) (((uint32)API_TICKRATE * (uint32)TICKS) / 256)
+#define MS_TO_TICKS_ROUND_UP(MS, API_TICKRATE)  \
+    ((uint16)(((((uint32)MS*256*2 + API_TICKRATE - 1)/API_TICKRATE)+1)/2))
+/* Gives frequency in units of 0.3662109375 Hz for signal generators */
+#define TICKRATE_TO_HZ(API_TICKRATE)  \
+    ((uint16)((uint32)(0x80000000 / API_TICKRATE) / 0x0C00))
+
+#define NO_DATA     0x00
+#define NOOP_CMD    0x06  /**< Standard No operation comnmand for all devices */
+
+#define MAX_CFAIL_TEST      10
+#define CFAIL_TEST_INTERVAL 10
+
+/**< CallerID Profile Data structure definitions */
+#define VP_FSK_MARK_SIGNAL     0xFF
+#define VP_FSK_CHAN_SEIZURE    0x55
+#define VP_FSK_DATA            0x11 /* Anything NOT Mark or C.S is ok */
+#define VP_FSK_NONE            0x00 /* When FSK Generator is not being used */
+
+typedef enum VpApiElementsType {
+    VP_CLI_NULL = 0,
+    VP_CLI_POLREV = 0x01,           /**< No Parameters */
+    VP_CLI_MUTEON = 0x02,           /**< No Parameters */
+    VP_CLI_MUTEOFF = 0x03,          /**< No Parameters */
+    VP_CLI_ALERTTONE = 0x04,        /**< Duration/Tone definition parameters */
+    VP_CLI_ALERTTONE2 = 0x05,       /**< Internal Alert Tone indicator */
+    VP_CLI_SILENCE = 0x06,          /**< Duration Parameter */
+    VP_CLI_SILENCE_MASKHOOK = 0x07, /**< Duration/Masked-hook length parameters */
+    VP_CLI_DETECT = 0x08,           /**< Tone and Timeout parameters */
+    VP_CLI_CHANSEIZURE = 0x09,      /**< Duration Parameter */
+    VP_CLI_MARKSIGNAL = 0x0A,       /**< Duration Parameter */
+    VP_CLI_MESSAGE = 0x0B,          /**< No Parameters */
+    VP_CLI_USER_DEFINED = 0x0C,     /**< Not supported in API-II */
+    VP_CLI_EOT = 0x0D,              /**< No Parameters */
+    VP_CLI_DTMF_MESSAGE = 0x0E,     /**< Message data to be sent in DTMF format */
+    VP_CLI_ELM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpApiElementsType;
+
+/* VP API Function Prototypes - Not associated with a function pointer */
+#if defined(VP_CC_790_SERIES) || defined(VP_CC_880_SERIES) \
+ || defined(VP_CC_890_SERIES) || defined(VP_CC_580_SERIES)
+
+#ifdef VP_CC_890_SERIES
+VpStatusType
+Vp890InitDevicePcnRcn(
+    Vp890DeviceObjectType   *pDevObj,
+    VpDeviceIdType          deviceId);
+#endif
+
+#ifdef VP_CC_880_SERIES
+VpStatusType
+Vp880InitDevicePcnRcn(
+    Vp880DeviceObjectType   *pDevObj,
+    VpDeviceIdType          deviceId);
+#endif
+
+bool
+VpIsLowPowerTermType(
+    VpTermType termType);
+
+void
+VpCSLACClearMPIBuffer(
+    VpDeviceIdType deviceId);
+
+bool
+VpCSLACIsProfileValid(
+    VpProfileType       profType,
+    int16               tableSize,
+    uint16              profEntry,
+    VpProfilePtrType    *pProfTable,
+    VpProfilePtrType    pProfileInput,
+    VpProfilePtrType    *pProfileRslt);
+
+bool
+VpCSLACSetTimer(
+    uint16 *pTimer,
+    uint16 newValue);
+
+#endif
+
+int16
+VpConvertToInt16(
+    uint8 *dataPtr);
+
+int32
+VpConvertToInt32(
+    uint8 *dataPtr);
+
+#if defined(VP_CC_880_SERIES) || defined(VP_CC_890_SERIES)
+VpStatusType
+VpCSLACSetAbsGain(
+    VpLineCtxType *pLineCtx,
+    VpOptionAbsGainType *gains);
+
+#if defined(VP880_FXS_SUPPORT) || defined(VP890_FXS_SUPPORT)
+/* Function only used for VP_LINE_HOWLER and VP_LINE_HOWLER_POLREV states */
+#ifdef VP_HIGH_GAIN_MODE_SUPPORTED
+void
+VpCLSACHighGainMode(
+    VpLineCtxType *pLineCtx,
+    bool highGainMode);
+
+VpStatusType
+VpCSLACHowlerStateMgmt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType fromState,
+    VpLineStateType toState,
+    VpLineStateType statePriorToHowler);    /**< Used only when exiting Howler State */
+#endif
+
+bool
+VpCSLACIsSupportedFxsState(
+    VpDeviceType deviceType,
+    VpLineStateType state);
+#endif  /* defined(VP880_FXS_SUPPORT) || defined(VP890_FXS_SUPPORT) */
+#endif  /* defined(VP_CC_880_SERIES) || defined(VP_CC_890_SERIES)   */
+
+VpProfileCadencerStateTypes
+ConvertApiState2PrfWizState(
+    const VpLineStateType state);
+
+VpLineStateType
+ConvertPrfWizState2ApiState(
+    uint8 state);
+
+void
+InitTimerVars(
+    VpLineCtxType *pLineCtx);
+
+bool
+VpUpdateDP(
+    uint16 tickRate,
+    VpOptionPulseType *pPulseSpecs,
+    VpDialPulseDetectType *pDpStruct,
+    VpOptionEventMaskType *pLineEvents);
+
+void
+VpInitDP(
+    VpDialPulseDetectType *pDpStruct);
+
+VpStatusType
+VpCSLACGetLineStatus(
+    VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+#if !defined(VP_REDUCED_API_IF)
+VpStatusType
+VpCSLACClearResults(
+    VpDevCtxType *pDevCtx);
+#endif
+
+VpStatusType
+VpCSLACDtmfDigitDetected(
+    VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+VpLineStateType
+VpGetReverseState(
+    VpLineStateType currentState);
+
+void
+VpCSLACSetVas(
+    uint8 *dcFeed,
+    uint16 vasValue);
+
+#ifdef CSLAC_GAIN_RELATIVE
+void
+VpConvertFixed2Csd(
+    uint16 fixed,
+    uint8 *csdBuf);
+
+uint16
+VpConvertCsd2Fixed(
+    uint8 *csdBuf);
+#endif
+#endif
+
+#if defined (VP_CC_790_SERIES)
+VpStatusType
+Vp790SetLineStateInt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp790SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+#endif
+
+
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+Vp580SetLineStateInt(
+
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp580SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+#endif
+
+uint16
+VpComputeSquareRoot(
+    uint32 number);
+
+#endif /* VP_API_INT_H */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_option.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_option.h
new file mode 100644
index 0000000..a24502b
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_option.h
@@ -0,0 +1,399 @@
+/** \file vp_api_option.h
+ * vp_api_option.h
+ *
+ * This file contains declaration associated with VP-API Options.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_OPTION
+#define VP_API_OPTION
+
+#include "vp_api_types.h"
+#include "vp_api_cfg.h"
+#include "vp_api_event.h"
+
+/* Option IDs.  (See Options chapter in VP-API-2 Reference Guide.)
+ * Line-specific option IDs begin with "VP_OPTION_ID_".  Device-specific
+ * option IDs begin with "VP_DEVICE_OPTION_ID_".  When new option IDs are added,
+ * the VpOptionValueType struct (below) must be updated accordingly.
+ */
+typedef enum VpOptionIdType {
+    VP_DEVICE_OPTION_ID_PULSE            = 0x00,
+    VP_DEVICE_OPTION_ID_CRITICAL_FLT     = 0x01,
+    VP_OPTION_ID_ZERO_CROSS              = 0x02,
+    VP_DEVICE_OPTION_ID_RAMP2STBY        = 0x03,
+    VP_OPTION_ID_PULSE_MODE              = 0x04,
+    VP_OPTION_ID_TIMESLOT                = 0x05,
+    VP_OPTION_ID_CODEC                   = 0x06,
+    VP_OPTION_ID_PCM_HWY                 = 0x07,
+    VP_OPTION_ID_LOOPBACK                = 0x08,
+    VP_OPTION_ID_LINE_STATE              = 0x09,
+    VP_OPTION_ID_EVENT_MASK              = 0x0A,
+    VP_OPTION_ID_RESERVED_1              = 0x0B,
+    VP_OPTION_ID_RING_CNTRL              = 0x0C,
+    VP_OPTION_ID_RESERVED_2              = 0x0D,
+    VP_OPTION_ID_DTMF_MODE               = 0x0E,
+    VP_DEVICE_OPTION_ID_DEVICE_IO        = 0x0F,
+    VP_OPTION_ID_RESERVED_EVENT_MASK_VCP = 0x10,
+    VP_OPTION_ID_PCM_TXRX_CNTRL          = 0x11,
+    VP_DEVICE_OPTION_ID_PULSE2           = 0x12,
+    VP_OPTION_ID_LINE_IO_CFG             = 0x13,
+    VP_DEVICE_OPTION_ID_DEV_IO_CFG       = 0x14,
+    VP_OPTION_ID_DTMF_SPEC               = 0x15,
+    VP_DEVICE_OPTION_ID_PARK_MODE        = 0x16,
+    VP_OPTION_ID_DCFEED_SLOPE            = 0x17,
+    VP_OPTION_ID_SWITCHER_CTRL           = 0x18,
+    VP_OPTION_ID_HOOK_DETECT_MODE        = 0x19,
+    VP_OPTION_ID_AUTO_LOOP_COND          = 0x1A,
+
+    /* New option values may be added in this gap in the future. */
+    VP_OPTION_ID_PULSE                   = 0x24,
+    VP_OPTION_ID_DEBUG_SELECT            = 0x25,
+    VP_OPTION_ID_ABS_GAIN                = 0x26,
+    VP_DEVICE_OPTION_ID_PCM_SIG_CTL      = 0x27,
+    VP_OPTION_ID_LINESTATE_CTL_MODE      = 0x28,
+
+    VP_NUM_OPTION_IDS
+} VpOptionIdType;
+
+/** Parameters for dial pulse, flash, and on-hook */
+typedef struct VpOptionPulseType {
+    uint16 breakMin;        /**< Minimum pulse break time (in 125uS) */
+    uint16 breakMax;        /**< Maximum pulse break time (in 125uS) */
+    uint16 makeMin;         /**< Minimum pulse make time (in 125uS) */
+    uint16 makeMax;         /**< Maximum pulse make time (in 125uS) */
+    uint16 interDigitMin;   /**< Minimum pulse interdigit time (in 125uS) */
+    uint16 flashMin;        /**< Minimum flash break time (in 125uS) */
+    uint16 flashMax;        /**< Maximum flash break time (in 125uS) */
+#ifdef EXTENDED_FLASH_HOOK
+    uint16 onHookMin;       /**< Minimum on-hook time (in 125uS) */
+#endif
+} VpOptionPulseType;
+
+typedef struct VpOptionLinePulseType {
+    uint16 breakMin;        /**< Minimum pulse break time (in 125uS) */
+    uint16 breakMax;        /**< Maximum pulse break time (in 125uS) */
+    uint16 makeMin;         /**< Minimum pulse make time (in 125uS) */
+    uint16 makeMax;         /**< Maximum pulse make time (in 125uS) */
+    uint16 interDigitMin;   /**< Minimum pulse interdigit time (in 125uS) */
+    uint16 flashMin;        /**< Minimum flash break time (in 125uS) */
+    uint16 flashMax;        /**< Maximum flash break time (in 125uS) */
+    uint16 onHookMin;       /**< Minimum on-hook time (in 125uS) */
+    uint16 offHookMin;      /**< Minimum off-hook time (in 125uS) */
+} VpOptionLinePulseType;
+
+/** Method for line control when critical faults are detected */
+typedef struct VpOptionCriticalFltType {
+    /**< The line is set to disconnect when the specified fault is active and
+     * the "En" bit is set TRUE
+     */
+    bool acFltDiscEn;           /**< AC fault detected */
+    bool dcFltDiscEn;           /**< DC fault detected */
+    bool thermFltDiscEn;        /**< Thermal fault detected */
+} VpOptionCriticalFltType;
+
+/** Method for zero-cross control */
+typedef enum VpOptionZeroCrossType {
+    VP_OPTION_ZC_M4B  = 0, /**< Zero-Cross On - Make before break */
+    VP_OPTION_ZC_B4M  = 1, /**< Zero-Cross On - Break before make */
+    VP_OPTION_ZC_NONE = 2, /**< Turn Zero-Cross control off */
+    VP_OPTION_ZC_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_OPTION_ZC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpOptionZeroCrossType;
+
+/** Dial Pulse decode enable/disable */
+typedef enum VpOptionPulseModeType {
+    VP_OPTION_PULSE_DECODE_OFF      = 0, /**< Disable Pulse Decode */
+    VP_OPTION_PULSE_DECODE_ON       = 1, /**< Enable Pulse Decode */
+    VP_OPTION_PULSE_DECODE_BRIDGING = 2, /**< Enable Pulse Decode (With Bridging) */
+    VP_OPTION_PULSE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPulseModeType;
+
+/** Transmit/Receive Timeslot setting (timeslot and control) */
+typedef struct VpOptionTimeslotType {
+    uint8 tx;   /**< 8-bit TX timeslot */
+    uint8 rx;   /**< 8-bit RX timeslot */
+} VpOptionTimeslotType;
+
+typedef enum VpOptionCodecType {
+    VP_OPTION_ALAW     = 0, /**< Select G.711 A-Law PCM encoding */
+    VP_OPTION_MLAW     = 1, /**< Select G.711 Mu-Law PCM encoding */
+    VP_OPTION_LINEAR   = 2, /**< Select Linear PCM encoding */
+    VP_OPTION_WIDEBAND = 3, /**< Select Wideband PCM encoding */
+    VP_NUM_OPTION_CODEC_TYPE_IDS,
+    VP_OPTION_CODEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionCodecType;
+
+/** PCM Highway Selection (B valid on select devices only) */
+typedef enum VpOptionPcmHwyType {
+    VP_OPTION_HWY_A          = 0, /**< Select the 'A' PCM Highway */
+    VP_OPTION_HWY_B          = 1, /**< Select the 'B' PCM Highway */
+    VP_OPTION_HWY_TX_A_RX_B  = 2, /**< Transmit on Highway A, receive on B */
+    VP_OPTION_HWY_TX_B_RX_A  = 3, /**< Transmit on Highway A, receive on A */
+    VP_OPTION_HWY_TX_AB_RX_A = 4, /**< Transmit on Highway A and B, receive on A */
+    VP_OPTION_HWY_TX_AB_RX_B = 5, /**< Transmit on Highway A and B, receive on B */
+    VP_OPTION_HWY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPcmHwyType;
+
+/** Loopback option selection */
+typedef enum VpOptionLoopbackType {
+    VP_OPTION_LB_OFF      = 0, /**< All loopbacks off */
+
+    /* Following loopback options are supported for CSLAC and VCP only */
+    VP_OPTION_LB_TIMESLOT = 1, /**< Perform a timeslot loopback */
+    VP_OPTION_LB_DIGITAL  = 2, /**< Perform a full-digital loopback */
+    VP_OPTION_LB_CHANNELS = 3, /**< Connects FXO to FXS line on same device */
+
+    VP_NUM_LB_OPTIONS,
+    VP_OPTION_LB_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionLoopbackType;
+
+/** Active Line State battery supply selection */
+typedef enum VpOptionBatType {
+    VP_OPTION_BAT_AUTO  = 0, /**< Automatic Batery selection */
+    VP_OPTION_BAT_HIGH  = 1, /**< Use High Batery */
+    VP_OPTION_BAT_LOW   = 2, /**< Use Low Batery */
+    VP_OPTION_BAT_BOOST = 3, /**< Include Positive Batery */
+    VP_NUM_OPTION_BAT_IDS,
+    VP_OPTION_BAT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionBatType;
+
+/** Active Line State battery supply selection */
+typedef struct VpOptionLineStateType {
+    bool battRev;       /**< Smooth/Abrupt Battery Reversal (TRUE = abrupt) */
+
+    VpOptionBatType bat;    /**< Battery selection for Active line state */
+} VpOptionLineStateType;
+
+/** Ring control option */
+typedef enum VpLineStateType {
+
+    /* FXS */
+    VP_LINE_STANDBY         = 0x00, /**< Low power line feed state */
+    VP_LINE_TIP_OPEN        = 0x01, /**< Tip open circuit state */
+    VP_LINE_ACTIVE          = 0x02, /**< Line Feed w/out VF */
+    VP_LINE_ACTIVE_POLREV   = 0x03, /**< Polarity Reversal Line Feed w/out VF */
+    VP_LINE_TALK            = 0x04, /**< Normal off-hook Active State; Voice Enabled */
+    VP_LINE_TALK_POLREV     = 0x05, /**< Normal Active with reverse polarity; Voice Enabled */
+    VP_LINE_OHT             = 0x06, /**< On-Hook tranmission state */
+    VP_LINE_OHT_POLREV      = 0x07, /**< Polarity Reversal On-Hook tranmission state */
+    VP_LINE_DISCONNECT      = 0x08, /**< Denial of service */
+    VP_LINE_RINGING         = 0x09, /**< Ringing state */
+    VP_LINE_RINGING_POLREV  = 0x0A, /**< Ringing w/Polarity Reversal */
+    VP_LINE_STANDBY_POLREV  = 0x10, /**< Low power polrev line feed state */
+    VP_LINE_PARK            = 0x11, /**< Park mode */
+    VP_LINE_RING_OPEN       = 0x12, /**< Ring open */
+    VP_LINE_HOWLER          = 0x13, /**< Howler */
+    VP_LINE_TESTING         = 0x14, /**< Testing */
+    VP_LINE_DISABLED        = 0x15, /**< Disabled */
+    VP_LINE_NULLFEED        = 0x16, /**< Null-feed */
+    VP_LINE_HOWLER_PCM      = 0x17, /**< Howler with PCM highway enabled */
+    VP_LINE_HOWLER_POLREV   = 0x18, /**< Howler with Polarity Reversal */
+
+    /* FXO */
+    VP_LINE_FXO_OHT,        /**< FXO Line providing Loop Open w/VF */
+    VP_LINE_FXO_LOOP_OPEN,  /**< FXO Line providing Loop Open w/out VF */
+    VP_LINE_FXO_LOOP_CLOSE, /**< FXO Line providing Loop Close w/out VF */
+    VP_LINE_FXO_TALK,       /**< FXO Line providing Loop Close w/VF */
+    VP_LINE_FXO_RING_GND,   /**< FXO Line providing Ring Ground (GS only)*/
+
+    VP_NUM_LINE_STATES,
+    VP_LINE_STATE_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_LINE_STATE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLineStateType;
+
+typedef struct VpOptionRingControlType {
+    VpOptionZeroCrossType zeroCross;    /**< LCAS zero cross control */
+
+    uint16 ringExitDbncDur; /**< Ringing Exit Debounce Duration; Used during end
+                             * of ON periods of ringing cadences; 125uS
+                             * resolution
+                             */
+
+    VpLineStateType ringTripExitSt; /**< State to automatically switch to upon
+                                     * ring trip
+                                     */
+}  VpOptionRingControlType;
+
+/** DTMF detection option */
+typedef enum VpOptionDtmfModeControlType {
+    VP_OPTION_DTMF_DECODE_OFF = 0, /**< Disable DTMF Digit Decode */
+    VP_OPTION_DTMF_DECODE_ON  = 1, /**< Enable DTMF Digit  Decode */
+    VP_OPTION_DTMF_GET_STATUS = 2, /**< Do not change anything; Just get the DTMF status  */
+    VP_NUM_OPTION_DTMF_IDS,
+    VP_OPTION_DTMF_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionDtmfModeControlType;
+
+/* Device I/O Option related definitions */
+typedef enum VpDeviceIoDirectionType {
+    VP_IO_INPUT_PIN  = 0, /* Configure GPIO pin as input pin */
+    VP_IO_OUTPUT_PIN = 1, /* Configure GPIO pin as output pin */
+    VP_IO_DIR_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDeviceIoDirectionType;
+
+typedef enum VpDeviceOutputPinType {
+    VP_OUTPUT_DRIVEN_PIN = 0, /* Configure as TTL/CMOS output pin */
+    VP_OUTPUT_OPEN_PIN   = 1, /* Configure as open collector/drain output pin */
+    VP_OUTPUT_TYPE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDeviceOutputPinType;
+
+typedef struct VpOptionDeviceIoType {
+    uint32 directionPins_31_0;      /* Device specific IO pin direction
+                                     * (Pins 0 - 31) */
+    uint32 directionPins_63_32;     /* Device specific IO pin direction
+                                     * (Pins 32 - 63) */
+    uint32 outputTypePins_31_0;     /* Output pin type (Pins 0 - 31) */
+    uint32 outputTypePins_63_32;    /* Output pin type (Pins 32 - 63) */
+} VpOptionDeviceIoType;
+
+/* Definition for line I/O config option */
+typedef struct VpOptionLineIoConfigType {
+    uint8 direction;
+    uint8 outputType;
+} VpOptionLineIoConfigType;
+
+/* Definition for device I/O config option */
+typedef struct VpOptionDeviceIoConfigType {
+    VpOptionLineIoConfigType lineIoConfig[VP_MAX_LINES_PER_DEVICE];
+} VpOptionDeviceIoConfigType;
+
+typedef enum VpOptionPcmTxRxCntrlType {
+    VP_OPTION_PCM_BOTH      = 0, /* Enable both PCM transmit and receive paths */
+    VP_OPTION_PCM_RX_ONLY   = 1, /* Enable PCM receive path only */
+    VP_OPTION_PCM_TX_ONLY   = 2, /* Enable PCM transmit path only */
+    VP_OPTION_PCM_ALWAYS_ON = 3, /* Prevents disabling of PCM path */
+    VP_PCM_TXRX_CNTRL_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_PCM_TXRX_CNTRL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPcmTxRxCntrlType;
+
+/** Direction Specification */
+typedef enum VpDirectionType {
+    VP_DIRECTION_DS,
+    VP_DIRECTION_US,
+    VP_DIRECTION_INVALID,   /**< Used by the API to determine if the direction
+                             * field is valid */
+    VP_DIRECTION_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDirectionType;
+
+#define VP_LINE_FLAG_BYTES ((VP_MAX_LINES_PER_DEVICE + 7) / 8)
+
+/** DTMF detection option control */
+typedef struct VpOptionDtmfModeType {
+    VpOptionDtmfModeControlType dtmfControlMode; /**< DTMF detection
+                                                  * Enable/Disable */
+    VpDirectionType direction;                  /**< Detection direction */
+    uint32 dtmfDetectionSetting;                /**< Indicates the DTMF
+                                                 *   detection setting for first
+                                                 *    32 lines */
+    uint8 dtmfResourcesRemaining;               /**< DTMF decoder resources
+                                                 *   remaining */
+    uint8 dtmfDetectionEnabled[VP_LINE_FLAG_BYTES];
+                                                /**< DTMF detection setting for
+                                                 *   lines 7-0, 15-8, etc. */
+} VpOptionDtmfModeType;
+
+/** Regional DTMF Specs */
+typedef enum VpOptionDtmfSpecType {
+    VP_OPTION_DTMF_SPEC_ATT  = 0, /* Q.24 AT&T */
+    VP_OPTION_DTMF_SPEC_NTT  = 1, /* Q.24 NTT */
+    VP_OPTION_DTMF_SPEC_AUS  = 2, /* Q.24 Australian */
+    VP_OPTION_DTMF_SPEC_BRZL = 3, /* Q.24 Brazilian */
+    VP_OPTION_DTMF_SPEC_ETSI = 4, /* ETSI ES 201 235-3 v1.3.1 */
+    VP_OPTION_DTMF_SPEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionDtmfSpecType;
+
+/**< The following types are for Park Mode options */
+typedef struct VpOptionParkModeType {
+    uint16 discTime;    /**< Specified in 500ms increments, up to 8 seconds */
+    uint16 standbyTime; /**< Specified in 100ms increments, up to 8 seconds */
+} VpOptionParkModeType;
+
+/** Hook detection modes  */
+typedef enum VpOptionHookDetectModeType {
+    VP_OPTION_HOOKDET_NORMAL         = 0,  /* normal hook detection behavior */
+    VP_OPTION_HOOKDET_DISC_IS_ONHOOK = 1,  /* in the VP_LINE_DISCONNECT or VP_LINE_DISABLED
+                                              state, the hook status is always considered
+                                              to be on-hook */
+    VP_OPTION_HOOKDET_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionHookDetectModeType;
+
+/* Option value struct for VP_OPTION_ID_AUTO_LOOP_COND: */
+typedef enum VpLoopCondSelectType {
+    VP_LOOP_COND_NONE  = 0x0000,    /* feature disabled */
+    VP_LOOP_COND_RLOOP = 0x0001,    /* read loop resistance */
+    VP_LOOP_COND_ILG   = 0x0002,    /* read longitudinal (common mode) current */
+    VP_LOOP_COND_IMT   = 0x0004,    /* read metallic (differential) current */
+    VP_LOOP_COND_VSAB  = 0x0008,    /* read metallic (differential) voltage */
+    VP_LOOP_COND_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopCondSelectType;
+
+typedef struct VpOptionAutoLoopCondType {
+    uint16 select;  /* bitmask (multiple VpLoopCondSelectType values can be ORed
+                       together */
+    uint16 delay;   /* amount of time (in ms) after HOOK_OFF before
+                       measurement(s) */
+} VpOptionAutoLoopCondType;
+
+/* Definition for Absolute Level option */
+typedef struct VpOptionAbsGainType {
+    int16 gain_AToD;
+    int16 gain_DToA;
+} VpOptionAbsGainType;
+
+#define VP_OPTION_ABS_GAIN_QUIET        (-32767)
+#define VP_OPTION_ABS_GAIN_NO_CHANGE    (+32767)
+#define VP_ABS_GAIN_UNKNOWN             (VP_OPTION_ABS_GAIN_NO_CHANGE - 1)
+
+/* Option value struct for VP_DEVICE_OPTION_ID_PCM_SIG_CTL: */
+typedef struct VpOptionPcmSigCtlType {
+    bool enable;
+    uint8 ctlTimeslot;
+    uint8 sigTimeslot;
+} VpOptionPcmSigCtlType;
+
+/* Option value struct for VP_OPTION_ID_LINESTATE_CTL_MODE: */
+typedef enum VpOptionLinestateCtlModeType {
+    VP_OPTION_LINESTATE_CTL_NORMAL     = 0x0000,
+    VP_OPTION_LINESTATE_CTL_PCM        = 0x0080
+} VpOptionLinestateCtlModeType;
+
+/* The following struct can be passed to VpGetResults() if the option ID is not
+   known at compile time, to ensure that the buffer is large enough regardless
+   of the option type. */
+typedef union VpOptionValueType {
+    VpOptionPulseType pulse;                       /* VP_DEVICE_OPTION_ID_PULSE        */
+                                                   /* VP_DEVICE_OPTION_ID_PULSE2       */
+    VpOptionCriticalFltType criticalFlt;           /* VP_DEVICE_OPTION_ID_CRITICAL_FLT */
+    VpOptionZeroCrossType zeroCross;               /* VP_OPTION_ID_ZERO_CROSS          */
+    uint16 ramp2stby;                              /* VP_DEVICE_OPTION_ID_RAMP2STBY    */
+    VpOptionPulseModeType pulseMode;               /* VP_OPTION_ID_PULSE_MODE          */
+    VpOptionTimeslotType timeslot;                 /* VP_OPTION_ID_TIMESLOT            */
+    VpOptionCodecType codec;                       /* VP_OPTION_ID_CODEC               */
+    VpOptionPcmHwyType pcmHwy;                     /* VP_OPTION_ID_PCM_HWY             */
+    VpOptionLoopbackType loopback;                 /* VP_OPTION_ID_LOOPBACK            */
+    VpOptionLineStateType lineState;               /* VP_OPTION_ID_LINE_STATE          */
+    VpOptionEventMaskType eventMask;               /* VP_OPTION_ID_EVENT_MASK          */
+    VpOptionRingControlType ringControl;           /* VP_OPTION_ID_RING_CNTRL          */
+    VpOptionDtmfModeType dtmfMode;                 /* VP_OPTION_ID_DTMF_MODE           */
+    VpOptionDeviceIoType deviceIo;                 /* VP_DEVICE_OPTION_ID_DEVICE_IO    */
+    VpOptionPcmTxRxCntrlType pcmTxRxCntrl;         /* VP_OPTION_ID_PCM_TXRX_CNTRL      */
+    VpOptionDeviceIoConfigType deviceIoConfig;     /* VP_DEVICE_OPTION_ID_DEV_IO_CFG   */
+    VpOptionLineIoConfigType lineIoConfig;         /* VP_OPTION_ID_LINE_IO_CFG         */
+    VpOptionDtmfSpecType dtmfSpec;                 /* VP_OPTION_ID_DTMF_SPEC           */
+    VpOptionParkModeType parkMode;                 /* VP_DEVICE_OPTION_ID_PARK_MODE    */
+    VpOptionLinePulseType linePulse;               /* VP_OPTION_ID_PULSE               */
+    uint16 dcFeedSlope;                            /* VP_OPTION_ID_DCFEED_SLOPE        */
+    bool switcherCtrl;                             /* VP_OPTION_ID_SWITCHER_CTRL       */
+    uint32 debugSelect;                            /* VP_OPTION_ID_DEBUG_SELECT        */
+    VpOptionAbsGainType absGain;                   /* VP_OPTION_ID_ABS_GAIN            */
+    VpOptionHookDetectModeType hookDetectMode;     /* VP_OPTION_ID_HOOK_DETECT_MODE    */
+    VpOptionPcmSigCtlType pcmSigCtl;               /* VP_DEVICE_OPTION_ID_PCM_SIG_CTL  */
+    VpOptionLinestateCtlModeType linestateCtlMode; /* VP_OPTION_ID_LINESTATE_CTL_MODE  */
+    VpOptionAutoLoopCondType autoLoopCond;         /* VP_OPTION_ID_AUTO_LOOP_COND      */
+} VpOptionValueType;
+
+#endif /* VP_API_OPTION */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_test.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_test.h
new file mode 100644
index 0000000..143f444
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_test.h
@@ -0,0 +1,950 @@
+/** \file vp_api_test.h
+ * file vp_api_test.h
+ *
+ * This file contains declaration associated with VP-API Test features.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_TEST_H
+#define VP_API_TEST_H
+
+#include "vp_api_types.h"
+#include "vp_api_option.h"
+#include "vp_api_event.h"   /* For VpDigitType */
+
+#define VP_TEST_NOT_MEASURED            0x8000    /* a value of -1 to indicate not measured */
+                                        /* chosen because it is an impermissible value in those tests where used */
+
+/** Tests supported by VpTestLine function */
+typedef enum VpTestIdType {
+    VP_TEST_ID_PREPARE        = 0x00, /* Prepare for a test sequence */
+    VP_TEST_ID_CONCLUDE       = 0x01, /* Conclude a test sequence */
+    VP_TEST_ID_SET_SENSE_GAIN = 0x02, /* Set ILG and IMT gains high or low */
+    VP_TEST_ID_OPEN_VDC       = 0x03, /* Measure open DC voltage */
+    VP_TEST_ID_OPEN_VAC       = 0x04, /* Measure open AC voltage */
+    VP_TEST_ID_DIFF_VAC       = 0x05, /* Measure differential AC voltage */
+    VP_TEST_ID_DC_RLOOP       = 0x06, /* Measure DC loop resistance */
+    VP_TEST_ID_AC_RLOOP       = 0x07, /* Measure AC loop impedance */
+    VP_TEST_ID_NULL_IGND      = 0x08, /* Null ground current */
+    VP_TEST_ID_3ELE_RES       = 0x09, /* Measure 3-element insulation resistance */
+    VP_TEST_ID_3ELE_CAP       = 0x0A, /* Measure 3-element capacitance */
+    VP_TEST_ID_IDC            = 0x0B, /* Measure DC currents */
+    VP_TEST_ID_IAC            = 0x0C, /* Measure AC currents */
+    VP_TEST_ID_KEYPAD         = 0x0D, /* Keypad DTMF and Pulse dial test */
+    VP_TEST_ID_NOISE          = 0x0E, /* Measure Active or Passive Noise 3, 3.4 & 15KhZ */
+    VP_TEST_ID_SNR_QDIST      = 0x0F, /* Measure SNR and quantization distortion */
+    VP_TEST_ID_ARB_1TONE      = 0x10, /* Measure arbitrary single tone */
+    VP_TEST_ID_TONE_GEN       = 0x11, /* Generate a single/dual/quad-tone */
+    VP_TEST_ID_DIALTONE       = 0x12, /* Detect and measure dial tone (Inward test) */
+    VP_TEST_ID_HYBRID_LOSS    = 0x13, /* Measure trans-hybrid loss */
+    VP_TEST_ID_ALT_REN        = 0x14, /* Alternative method used to measure REN */
+    VP_TEST_ID_HOOK_STATUS    = 0x15, /* Check Hook Status (while in test mode) */
+    VP_TEST_ID_PCM_COLLECT    = 0x16, /* Collect PCM samples */
+    VP_TEST_ID_AC_RLOOP_PHASE = 0x17, /* Rloop with Phase information */
+    VP_TEST_ID_SET_BATTERIES  = 0x18, /* Select batteries for line testing */
+    VP_TEST_ID_MONITOR_IV     = 0x19, /* Non-Intrusive Monitoring Test */
+    VP_TEST_ID_UNBAL_TONE     = 0x1A, /* Generates an unbalanced tracing tone */
+    VP_TEST_ID_3ELE_RES_VMID  = 0x1B, /* Measure 3-element insulation resistance with a specified vMid */
+    VP_TEST_ID_AC_TRANS       = 0x1C, /* Measures digital-digital transmission characteristics */
+    VP_TEST_ID_GEN_TEST       = 0x1D, /* Multi-functional primitive */
+    VP_TEST_ID_SLOPE_REN      = 0x1E, /* REN test with a ramp instead of step */
+    /* Test IDs above this line are supported by one or more VCP devices.
+       Their values must not change.  More VCP tests might be added above this
+       line in the future. */
+
+    VP_TEST_ID_RSVD_MIN       = 0x23, /* Custom VCP tests (not currently used) */
+    VP_TEST_ID_RSVD_MAX       = 0x23,
+
+    /* The values of the constants below this line can change from time. */
+
+    VP_TEST_ID_3ELE_RES_HG,     /* Alternative 3-element resistance high gain */
+    VP_TEST_ID_3ELE_RES_LG,     /* Alternative 3-element resistance low gain */
+    VP_TEST_ID_3ELE_CAP_CSLAC,  /* CSLAC 3-element capacitance test */
+    VP_TEST_ID_MSOCKET_TYPE2,   /* Master Socket test for UK termination */
+    VP_TEST_ID_XCONNECT,        /* Cross Connect detection test */
+    VP_TEST_ID_LOOP_CONDITIONS, /* Measure current loop conditions */
+    VP_TEST_ID_LOOPBACK,        /* Setup loopback conditions */
+    VP_TEST_ID_LINE_IMPD,       /* Measure impedance at a frequency */
+    VP_TEST_ID_RING_TRIP,       /* Test ability to detect ring trip */
+    VP_TEST_ID_LOOP_DETECT,     /* Test ability to source current and detect
+                                 * off-hook */
+    VP_TEST_ID_CALIBRATE,       /* Perform line calibration */
+    VP_TEST_ID_USE_LINE_CAL,    /* Copy dev cal factors from lineObj to devObj */
+    VP_TEST_ID_OPEN_VXC,        /* Measure both DC and AC voltages */
+
+    VP_TEST_ID_GR909_HEMF,      /* Hazardous Potential Voltage Test for AC/DC
+                                 * Tip and Ring */
+    VP_TEST_ID_GR909_EMF,       /* FEMF test for AC/DC Tip and Ring */
+    VP_TEST_ID_GR909_RES_FLT,   /* Resistive Faults (T/R, T-Gnd, R-Gnd) */
+    VP_TEST_ID_GR909_OFF_HOOK,  /* Receiver Off-Hook */
+    VP_TEST_ID_GR909_RINGERS,   /* REN per FCC part 68 (1REN = 7Kohm) */
+    VP_TEST_ID_GR909_ALL,       /* Run all GR909 tests */
+    VP_TEST_ID_DELAY,           /* Implements non-blocking delay */
+    VP_TEST_ID_RAMP_INIT,       /* Implements a ramp to voltage test init */
+    VP_TEST_ID_RAMP,            /* Implements a ramp to voltage test */
+    VP_TEST_ID_FLT_DSCRM,       /* Implements the Fault discrimination test (880 890 only)*/
+    VP_TEST_ID_PREPARE_EXT,     /* Prepare for a test sequence without modifying the low power state  */
+
+    VP_TEST_ID_SET_SENSE_GAIN_792, /* Set Low/Normal/High sense gain for VCP792.
+                                    * The API translates this to the value of
+                                    * VP_TEST_ID_SET_SENSE_GAIN before sending
+                                    * it down to the VCP. */
+
+    VP_NUM_TEST_IDS,
+
+    VP_TEST_ID_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestIdType;
+
+/**< The following are test line error codes */
+typedef enum VpTestStatusType {
+    VP_TEST_STATUS_SUCCESS            = 0,  /**< Test Completed Successfully */
+    VP_TEST_STATUS_LINE_NOT_READY     = 1,  /**< Line Not in Test-mode (no VP_TEST_ID_PREPARE) */
+    VP_TEST_STATUS_RESOURCE_NA        = 2,  /**< Line Not available for Test (already in Test) */
+    VP_TEST_STATUS_TESTING            = 3,  /**< Test underway - not aborted */
+    VP_TEST_STATUS_VOUT_OOR           = 4,  /**< Voltage Out-of-range */
+    VP_TEST_STATUS_VAB_OOR            = 5,  /**< A-B Voltage is out-of-range */
+    VP_TEST_STATUS_ILG_OOR            = 6,  /**< Measured IILG is out-of-range */
+    VP_TEST_STATUS_VCM_OOR            = 7,  /**< Measured VCM is out-of-range */
+    VP_TEST_STATUS_IAHL_OOR           = 8,  /**< Measured current or voltage is out-of-range in Res or Cap test */
+    VP_TEST_STATUS_IBHL_OOR           = 9,  /**< " " */
+    VP_TEST_STATUS_IAHH_OOR           = 10, /**< " " */
+    VP_TEST_STATUS_IBHH_OOR           = 11, /**< " " */
+    VP_TEST_STATUS_VABHL_OOR          = 12, /**< " " */
+    VP_TEST_STATUS_IALL_OOR           = 13, /**< " " */
+    VP_TEST_STATUS_IBLL_OOR           = 14, /**< " " */
+    VP_TEST_STATUS_IA_OOR             = 15, /**< Measured Current is out-of-range */
+    VP_TEST_STATUS_IB_OOR             = 16, /**< " " */
+    VP_TEST_STATUS_IMT_OOR            = 17, /**< Measured IMT is out-of-range */
+    VP_TEST_STATUS_IMT_DC_OOR         = 18, /**< " " */
+    VP_TEST_STATUS_15KHZ_ERROR        = 19, /**< More than 1 15Khz Test requested */
+    VP_TEST_STATUS_TIMEOUT            = 20, /**< Failed to complete in specified time */
+    VP_TEST_STATUS_ABORTED            = 21, /**< Test aborted */
+    VP_TEST_STATUS_INTERNAL_ERROR     = 22, /**< Internal error (SLAC integrator) */
+    VP_TEST_STATUS_NO_CONVERGENCE     = 23, /**< NULL_IGND test failed to converge */
+    VP_TEST_STATUS_TEST_NOT_SUPPORTED = 24, /**< Requested test is not supported (due to device configuration) */
+    VP_TEST_STATUS_VTIPBIAS_OOR       = 25, /**< Tip Bias Voltage Out of Range */
+    VP_TEST_STATUS_VRINGBIAS_OOR      = 26, /**< Ring Bias Voltage Out of Range */
+    VP_TEST_STATUS_VMID_OOR           = 27, /**< User specified vMid voltage is out of range */
+    VP_TEST_STATUS_GAIN_OOR           = 28, /**< User specified gain is out of range */
+    VP_TEST_STATUS_VA_OOR             = 29, /**< Measured Voltage is out-of-range */
+    VP_TEST_STATUS_VB_OOR             = 30, /**< " " */
+    VP_TEST_STATUS_IMTOFFSET_OOR      = 31,
+    VP_TEST_STATUS_BUF_OVERFLOW       = 32, /* test would exceed the buffer storage available */
+    VP_TEST_STATUS_NUM_TYPES,               /**< NOT an ERROR, Just used for coding purposes */
+    VP_TEST_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestStatusType;
+
+typedef struct VpTestCalibrationDataType {
+    uint16 gMvErr;
+    int16 gMvOff;
+    uint16 gLvErr;
+    int16 gLvOff;
+    uint16 gMiErr;
+    int16 gMiOff;
+    uint16 gLiErr;
+    int16 gLiOff;
+    uint16 sAvErr;
+    int16 sAvOff;
+    uint16 sAiErr;
+    int16 sAiOff;
+    uint16 sBvErr;
+    int16 sBvOff;
+    uint16 sBiErr;
+    int16 sBiOff;
+
+    uint16 sABMvErr;
+    int16 sABMvOff;
+    uint16 sABMiErr;
+    int16 sABMiOff;
+
+    uint16 sABLvErr;
+    int16 sABLvOff;
+    uint16 sABLiErr;
+    int16 sABLiOff;
+
+    uint16 sABMHiErr;
+    int16 sABMHiOff;
+    uint16 sABLHiErr;
+    int16 sABLHiOff;
+} VpTestCalibrationDataType;
+
+/* Definitions used for VP_TEST_ID_DELAY */
+typedef struct VpTestTimerType {
+    uint16 timerVal;    /* Value in 125uS steps */
+} VpTestTimerType;
+
+/* Definitions used for VP_TEST_ID_PREPARE */
+typedef struct VpTestPrepareType {
+    bool intrusive;
+} VpTestPrepareType;
+
+/* Definitions used for VP_TEST_ID_CONCLUDE */
+typedef struct VpTestConcludeType {
+    bool abortTest;
+} VpTestConcludeType;
+
+/* Definitions used for VP_TEST_ID_SET_SENSE_GAIN */
+typedef enum VpSenseGainType {
+    VP_SENSE_GAIN_HIGH = 0,
+    VP_SENSE_GAIN_LOW  = 1,
+    VP_SENSE_GAIN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSenseGainType;
+
+typedef struct VpTestSetSenseGainType {
+    VpSenseGainType imt;
+    VpSenseGainType ilg;
+} VpTestSetSenseGainType;
+
+/* 792-specific definitions for VP_TEST_ID_SET_SENSE_GAIN_VP792 */
+typedef enum Vp792SenseGainType {
+    VP792_SENSE_GAIN_0dB_GAIN   = 0x0000, /* absolute gain = 1 */
+    VP792_SENSE_GAIN_28dB_GAIN  = 0x0010, /* absolute gain = 25 */
+    VP792_SENSE_GAIN_10dB_LOSS  = 0x0020, /* absolute gain = 1/3 */
+    VP792_SENSE_GAIN_RSVD       = 0x0030,
+    VP792_SENSE_GAIN_ENUM_SIZE  = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} Vp792SenseGainType;
+
+typedef struct VpTestSet792SenseGainType {
+    Vp792SenseGainType senseGain;
+} VpTestSet792SenseGainType;
+
+/* Definitions used for VP_TEST_ID_SET_BATTERIES */
+typedef enum VpSetBatteriesType {
+    VP_BS_LOW  = 0,
+    VP_BS_HIGH = 1,
+    VP_BS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSetBatteriesType;
+
+typedef struct VpTestSetBatteriesType {
+    VpSetBatteriesType bs1;
+    VpSetBatteriesType bs0;
+} VpTestSetBatteriesType;
+
+/* Definitions used for VP_TEST_ID_OPEN_VDC, VP_TEST_ID_OPEN_VAC */
+typedef enum VpTestTipSelectType {
+    VP_TEST_RING     = 0,
+    VP_TEST_TIP      = 1,
+    VP_TEST_TIP_RING = 2,
+    VP_TEST_TIP_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestTipSelectType;
+
+typedef struct VpTestOpenVType {
+    bool calMode;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestTipSelectType tip;
+} VpTestOpenVType;
+
+/* Definitions used for VP_TEST_ID_DIFF_VAC */
+typedef struct VpTestDiffVacType {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    int16 gvsaCal;
+    int16 gvsbCal;
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestDiffVacType;
+
+/* Definitions used for VP_TEST_IDC, VP_TEST_IAC */
+typedef struct VpTestIdcType {
+    bool calMode;
+    int16 vCm;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestIdcType;
+
+typedef struct VpTestIacType {
+    int16 gimtCal;
+    int16 gilgCal;
+    int16 vCm;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestIacType;
+
+typedef struct VpTestResultVixType {
+    int16 ia;
+    int16 ib;
+} VpTestResultVixType;
+
+/* Definitions used for VP_TEST_ID_DC_RLOOP */
+typedef struct VpTestDcRLoopType {
+    bool calMode;
+    int16 iTestLevel;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestDcRLoopType;
+
+typedef struct VpTestResultDcRlType {
+    int16 vab;
+    int16 ilg;
+    bool currentSaturation;
+} VpTestResultDcRlType;
+
+/* Definitions used for VP_TEST_ID_AC_RLOOP */
+typedef struct VpTestAcRLoopType {
+    bool calMode;
+    uint16 freq;
+    int16 vTestLevel;
+    int16 vBias;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestTipSelectType tip; /* Used by VE880 only */
+} VpTestAcRLoopType;
+
+typedef struct VpTestResultAcRlType {
+    int16 imt;
+    int16 ilg;
+    int16 vab;
+    int32 freq;
+} VpTestResultAcRlType;
+
+/* Definition used for VP_TEST_ID_AC_RLOOP_PHASE (in addition to VpTestAcRLoopType) */
+typedef struct VpTestResultAcRlPhaseType {
+    int16 imt;
+    int16 ilg;
+    int16 phase;
+} VpTestResultAcRlPhaseType;
+
+/* Definitions used for VP_TEST_ID_LOOP_COND */
+typedef enum VpLoopCondTestType {
+    VP_LOOP_COND_TEST_VSAB  = 1,
+    VP_LOOP_COND_TEST_VSAG  = 2,
+    VP_LOOP_COND_TEST_VSBG  = 3,
+    VP_LOOP_COND_TEST_RLOOP = 4,
+    VP_LOOP_COND_TEST_ILG   = 5,
+    VP_LOOP_COND_TEST_IMT   = 6,
+    VP_LOOP_COND_TEST_BAT1  = 7,
+    VP_LOOP_COND_TEST_BAT2  = 8,
+    VP_LOOP_COND_TEST_BAT3  = 9,
+    VP_LOOP_COND_TEST_METER = 10,
+    VP_LOOP_COND_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopCondTestType;
+
+typedef struct VpTestLoopCondType {
+    bool calMode;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpLoopCondTestType loopCond; /* Indicates which condition to measure */
+} VpTestLoopCondType;
+
+typedef struct VpTestResultLoopCondType {
+    VpLoopCondTestType condition;
+    int16 data;
+    bool calibrated;
+    int16 limit;            /* Limit or target value */
+} VpTestResultLoopCondType;
+
+/* Definitions used for VP_TEST_ID_XCONNECT */
+typedef enum VpXConnectType {
+    VP_XCONNECT_DISC_V    = 0,
+    VP_XCONNECT_12VVOC_I  = 1,
+    VP_XCONNECT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpXConnectType;
+
+typedef struct VpTestXConnectType {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpXConnectType measReq; /* Indicates which measurement sequence to run */
+    bool isFeedPositive;    /* VP_XCONNECT_12VVOC_I feed sign depends on measured EMF */
+    uint8 phase;            /* Test phase number */
+} VpTestXConnectType;
+
+typedef struct VpTestResultXConnectType {
+    VpXConnectType condition;
+    int16 data;
+} VpTestResultXConnectType;
+
+/* Definitions used for VP_TEST_ID_LOOPBACK */
+typedef enum VpLoopbackTestType {
+    VP_LOOPBACK_TEST_CODEC  = 1,
+    VP_LOOPBACK_TEST_ANALOG = 2,
+    VP_LOOPBACK_TEST_BFILTER = 3,
+    VP_LOOPBACK_TEST_TIMESLOT = 4,
+    VP_LOOPBACK_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopbackTestType;
+
+typedef struct VpTestLoopbackType {
+    uint16 waitTime;            /* Indicates how long before collecting samples */
+    uint16 loopbackTime;        /* Indicates Loopback duration in units of 125us */
+    VpLoopbackTestType loopback;/* Indicates which condition to setup */
+} VpTestLoopbackType;
+
+typedef struct VPTestResultLoopbackType {
+    VpLoopbackTestType  loopback; /* Indicates which condition was setup*/
+    void *pApplicationInfo;
+} VPTestResultLoopbackType;
+
+/* Definitions used for VP_TEST_LINE_IMPD */
+typedef struct VpTestLineImpdType {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    bool filterMode;
+    int16 vcm;              /* Common mode voltage for measurement */
+    int16 vDiff;            /* Differential voltage for measurement */
+    uint16 freq;
+    int16 amp;
+} VpTestLineImpdType;
+
+typedef struct VpTestResultLineImpdType {
+    bool iaOor;         /* If set IA out of range */
+    bool ibOor;         /* If set IB out of range */
+    uint16 iDiff;           /* RMS differential current */
+} VpTestResultLineImpdType;
+
+/**< Typedefs for Advanced Tests */
+/* Definitions used for VP_TEST_TONE_GEN */
+typedef struct VpTestToneGenType {
+    uint16 duration;
+    uint16 freq1;
+    int16 amp1;
+    uint16 freq2;
+    int16 amp2;
+    uint16 freq3;
+    int16 amp3;
+    uint16 freq4;
+    int16 amp4;
+} VpTestToneGenType;
+
+/* Definitions used for VP_TEST_ALT_REN */
+typedef struct VpTestRenType {
+    uint16 integrateTime;
+    int16 vDiff;
+} VpTestRenType;
+
+typedef struct VpTestResultRenType {
+    int16 imt;
+    int16 imtDc;
+} VpTestResultRenType;
+
+/* Definitions used for VP_TEST_ID_SLOPE_REN */
+typedef enum VpTestMathType {
+    VP_TEST_TYPE_UNDEFINED = 0,
+    VP_TEST_TYPE_AVG       = 1,
+    VP_TEST_TYPE_RMS       = 2,
+    VP_TEST_TYPE_DFT       = 3,
+    VP_TEST_TYPE_RAW       = 4,
+    VP_TEST_TYPE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestMathType;
+
+typedef enum VpTestDcbwSpeedType {
+    VP_TEST_SPEED_UNDEFINED = 0,
+    VP_TEST_SPEED_LOW       = 1,
+    VP_TEST_SPEED_MED       = 2,
+    VP_TEST_SPEED_HIGH      = 3,
+    VP_TEST_SPEED_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestDcbwSpeedType;
+
+typedef struct VpTestSRenType {
+    uint16 slopeTime;
+    uint16 integrateTime;
+    uint16 settlingTime;
+    int16 vDiff;
+    VpTestMathType type;
+    VpTestDcbwSpeedType speed;
+} VpTestSRenType;
+
+typedef struct VpTestResultSRenType {
+    int16 imtOffset;
+    int16 imt;
+    int16 imtDc;
+} VpTestResultSRenType;
+
+/* Definitions used for VP_TEST_ID_3ELE_RES*/
+typedef struct VpTestResType {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestResType;
+
+typedef struct VpTestResultResType {
+    int16 iahl;
+    int16 ibhl;
+    int16 iahh;
+    int16 ibhh;
+    int16 iall;
+    int16 ibll;
+    int16 vabhl;
+} VpTestResultResType;
+
+/* Definition used for VP_TEST_ID_3ELE_HG and LG */
+typedef struct VpTest3EleResAltResType {
+    int16 feedBias;
+    bool shiftZeroFeed;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTest3EleResAltResType;
+
+typedef struct VpTestResultAltResType {
+    bool highGain;
+    int16 vanf;
+    int16 vbnf;
+    int16 imnf;
+    int16 ilnf;
+    int16 varf;
+    int16 vbrf;
+    int16 imrf;
+    int16 ilrf;
+    int16 vazf;
+    int16 vbzf;
+    int16 imzf;
+    int16 ilzf;
+} VpTestResultAltResType;
+
+/* Definition used for VP_TEST_ID_MSOCKET_TYPE2 */
+typedef struct VpTestMSocketType {
+    uint8 dummy;
+} VpTestMSocketType;
+
+typedef struct VpTestResultMSockType {
+    int16 vanf;
+    int16 vbnf;
+    int16 imnf;
+    int16 varf1;
+    int16 vbrf1;
+    int16 imrf1;
+    int16 varf2;
+    int16 vbrf2;
+    int16 imrf2;
+    int16 varf3;
+    int16 vbrf3;
+    int16 imrf3;
+} VpTestResultMSockType;
+
+/* Definition used for VP_TEST_ID_3ELE_CAP_CSLAC */
+typedef struct VpTest3EleCapAltResType {
+    bool calMode;       /* Enable calibration */
+    uint16 testAmp;     /* Test signal amplitude (mV RMS) */
+    uint8 testFreq;     /* Test signal frequency [0,4], 0=2666.016Hz -> 4=280.151Hz */
+    int16 bias;         /* Signal generator bias (V) */
+} VpTest3EleCapAltResType;
+
+typedef struct VpTestResultAltCapType {
+    bool accuracyFlag;
+    uint8 freq;
+    int16 va;
+    int16 vb;
+    int16 im;
+    int16 il;
+    int32 tipCapCal;
+    int32 ringCapCal;
+} VpTestResultAltCapType;
+
+/* Definition used for VP_TEST_ID_3ELE_RES_VMID */
+typedef struct VpTestResVmidType {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    int16 vMid;
+} VpTestResVmidType;
+
+typedef struct VpTestResultVxcType {
+    int16 vdc;
+    int16 vac;
+} VpTestResultVxcType;
+
+/* Definitions used for VP_TEST_3ELE_CAP */
+typedef struct VpTestCapType {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 freq;
+    int16 gimtCal;
+    int16 gilgCal;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestCapType;
+
+typedef struct VpTestResultCapType {
+    int16 iahl;
+    int16 iahh;
+    int16 ibhh;
+    int16 iall;
+    int16 ibll;
+    int16 vabhl;
+} VpTestResultCapType;
+
+/* Definitions used for VP_TEST_NOISE */
+typedef enum VpTestFilterType {
+    VP_FILTER_NONE   = 0,
+    VP_FILTER_3KHZ   = 1,
+    VP_FILTER_CMSG   = 2,
+    VP_FILTER_15KHZ  = 3,
+    VP_FILTER_3_4KHZ = 4,
+    VP_FILTER_D      = 5,
+    VP_FILTER_PSOPH  = 6,
+    VP_NUM_TEST_FILTER_TYPES,
+    VP_FILTER_ENUM_RSVD    = FORCE_SIGNED_ENUM,
+    VP_FILTER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestFilterType;
+
+typedef struct VpTestNoiseType {
+    uint16 integrateTime;
+    VpTestFilterType filter;
+    int16 amp;
+    bool useBuffer;
+} VpTestNoiseType;
+
+/* Definitions used for VP_TEST_HYBRID_LOSS */
+typedef struct VpTestTransHybridLossType {
+    uint16 integrateTime;
+    uint16 freq;
+    int16 amp;
+    bool useBuffer;
+} VpTestTransHybridLossType;
+
+/* Definitions used for VP_TEST_ID_NULL_IGND */
+typedef struct VpTestNullIGndType {
+    int16 vTestLevel;
+    int16 iTarget;
+    VpTestTipSelectType tip;
+    uint16 settlingTime;
+} VpTestNullIGndType;
+
+/* Definitions used for VP_TEST_KEYPAD */
+typedef enum VpKeyTestType {
+    VP_KEY_TEST_DTMF  = 0,
+    VP_KEY_TEST_PULSE = 1,
+    VP_KEY_TEST_BOTH  = 2,
+    VP_NUM_KEY_TEST_TYPES,
+    VP_KEY_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpKeyTestType;
+
+typedef struct VpTestKeypadType {
+    VpKeyTestType kTest;
+    uint16 timeout;
+    uint16 freq;
+    int16 amp;
+    uint16 fftSize;
+    uint16 threshold;
+    VpOptionPulseType pulseOpt;
+    bool useBuffer;
+} VpTestKeypadType;
+
+typedef enum VpKeyTestResultType {
+    VP_KT_DTMF_DET   = 0,
+    VP_KT_DTMF_MES   = 1,
+    VP_KT_PULSE      = 2,
+    VP_KT_THRESH_DET = 3,
+    VP_NUM_KT_TYPES,
+    VP_KT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpKeyTestResultType;
+
+typedef struct VpTestResultKeyType {
+    VpKeyTestResultType kTestResult;
+    VpDigitType digit;
+    uint16 lowFreq;
+    uint16 lowAmp;
+    uint16 highFreq;
+    uint16 highAmp;
+    uint16 fftSize;
+    uint16 minBreak;
+    uint16 maxBreak;
+    uint16 aveBreak;
+    uint16 pulsePerSec;
+    bool hookFlashDet;
+    uint16 hookFlashDuration;
+    bool disconnectDet;
+} VpTestResultKeyType;
+
+/* Definitions used for VP_TEST_SNR_QDIST */
+typedef struct VpTestSnrQDistorType {
+    uint16 integrateTime;          /* Integration time in units of 125us */
+    int16 amp;
+    bool useBuffer;
+} VpTestSnrQDistorType;
+
+typedef struct VpTestResultSnrQDistorType {
+    uint16 vrmsNoise;
+    uint16 vrmsSignal;
+} VpTestResultSnrQDistorType;
+
+/* Definitions used for VP_TEST_ARB_1TONE */
+typedef struct VpTestArb1ToneType {
+    uint16 timeout;
+    uint16 fftSize;
+    uint16 threshold;
+    bool useBuffer;
+} VpTestArb1ToneType;
+
+/* Definitions used for VP_TEST_DIALTONE */
+typedef struct VpTestDialToneType {
+    bool inward;
+    uint16 timeout;
+    uint16 detectGran;
+    uint16 threshold;
+    uint16 fftSize;
+    uint16 duration;
+    bool useBuffer;
+} VpTestDialToneType;
+
+typedef struct VpTestResultToneType {
+    uint16 rmsPwr;
+    uint16 highFreq;
+    uint16 highAmp;
+    uint16 secFreq;
+    uint16 secAmp;
+    uint16 thdFreq;
+    uint16 thdAmp;
+} VpTestResultToneType;
+
+/**< The following types are for GR909 tests */
+/* Definitions used for  */
+typedef struct VpTestResultGR909EmfType {
+    bool testFail;
+    bool acFault;
+    bool dcFault;
+    uint16 acVolt;
+    int16 dcVolt;
+} VpTestResultGR909EmfType;
+
+/* Definitions used for VP_TEST_ID_GR909_RES_FLT */
+typedef struct VpTestResultGR909ResFltType {
+    bool testFail;
+    bool rtrFlt;
+    bool rtgFlt;
+    bool rrgFlt;
+    uint16 rtr;
+    uint16 rtg;
+    uint16 rrg;
+} VpTestResultGR909ResFltType;
+
+/* Definitions used for VP_TEST_ID_GR909_OFF_HOOK */
+typedef struct VpTestResultGR909OffHookType {
+    bool offHook;
+} VpTestResultGR909OffHookType;
+
+/* Definitions used for VP_TEST_ID_GR909_RINGERS */
+typedef struct VpTestResultGR909RenType {
+    bool testFailed;
+    bool renHigh;
+    bool renLow;
+    uint16 ren;
+} VpTestResultGR909RenType;
+
+/* Definitions used for VP_TEST_ID_GR909_ALL */
+typedef struct VpTestResultGR909AllType {
+    bool testFailed;
+    bool hvFailed;
+    bool emfFailed;
+    bool resFailed;
+    bool offHook;
+    bool ringersFailed;
+} VpTestResultGR909AllType;
+
+/* Definitions used for VP_TEST_ID_RAMP_INIT */
+typedef struct VpTestRampInitType {
+    int16 dcVstart;
+    int16 dcVend;
+    int16 vRate;
+    int16 bias;
+    VpTestTipSelectType tip;
+} VpTestRampInitType;
+
+/* Definitions used for VP_TEST_ID_RAMP */
+typedef struct VpTestRampType {
+    int16 dcVoltage;
+    int16 vRate;
+    int16 bias;
+    VpTestTipSelectType tip;
+} VpTestRampType;
+
+typedef struct VpTestResultRampType {
+    int16 imt;
+    int16 vRate;
+} VpTestResultRampType;
+
+/* Definitions used for VP_TEST_ID_MONITOR_IV */
+typedef enum VpMonitorIvFilterType {
+    VP_TEST_TYPE_DC = 0,
+    VP_TEST_TYPE_AC = 1,
+    VP_TEST_TYPE_ACDC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpMonitorIvFilterType;
+
+typedef enum VpMonitorIvTestMeasurementType {
+    VP_TEST_MEAS_VA  = 0,
+    VP_TEST_MEAS_VB  = 1,
+    VP_TEST_MEAS_VAB = 2,
+    VP_TEST_MEAS_IMT = 3,
+    VP_TEST_MEAS_ILG = 4,
+    VP_TEST_MEAS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpMonitorIvTestMeasurementType;
+
+typedef struct VpTestMonitorIvType {
+    bool calMode;
+    uint16 integrateTime;               /* Integration time in units of 125us */
+    uint16 settlingTime;                /* Filter settling time in units of 125us */
+    VpMonitorIvFilterType filterType;   /* Measurement Type (AC/DC) */
+    VpMonitorIvTestMeasurementType measurement; /* measurement source */
+} VpTestMonitorIvType;
+
+/* Definitions used for VP_TEST_ID_UNBAL_TONE */
+typedef struct VpTestUnbalToneType {
+    uint16 freq;
+    int16 vTestlevel;
+    int16 vTipBias;
+    int16 vRingBias;
+    uint16 duration;
+    VpTestTipSelectType tip;
+} VpTestUnbalToneType;
+
+/* Definitions used for VP_TEST_ID_PCM_COLLECT */
+typedef struct VpTestPcmCollectType {
+    uint16 sampleTime;
+} VpTestPcmCollectType;
+
+typedef struct VpTestResultPcmCollectType {
+    uint16 resultsSize;
+    uint16 samples;
+    VpOptionCodecType codec;
+    uint16 reserved;
+    uint32 address;
+} VpTestResultPcmCollectType;
+
+/* Definitions used for VP_FLT_DSCRM */
+typedef struct VpTestResultFltDscrmType {
+    int16 vtgFeed;
+    int16 vrgFeed;
+    int16 vtrFeed;
+    int16 vtrAC;
+    int16 vtoAC;
+    int16 vroAC;
+    int16 vtuBalAC;
+    int16 vruBalAC;
+    bool hookDet;
+    bool gnkDet;
+} VpTestResultFltDscrmType;
+
+/* Definitions for VP_TEST_ID_GEN_TEST */
+/* Generic Test Defines */
+typedef enum VpTestGenFilterType {
+    VP_TEST_FILTER_UNDEFINED = 0,
+    VP_TEST_FILTER_LPF       = 1,
+    VP_TEST_FILTER_HPF       = 2,
+    VP_TEST_FILTER_NONE      = 3,
+    VP_TEST_FILTER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenFilterType;
+
+typedef enum VpTestGenDriveType {
+    VP_TEST_DRIVE_UNDEFINED = 0,
+    VP_TEST_DRIVE_NONE      = 1,
+    VP_TEST_DRIVE_A         = 2,
+    VP_TEST_DRIVE_B         = 3,
+    VP_TEST_DRIVE_BOTH      = 4,
+    VP_TEST_DRIVE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenDriveType;
+
+typedef enum VpTestGenSignalType {
+    VP_TEST_SIGNAL_UNDEFINED = 0,
+    VP_TEST_SIGNAL_A         = 1,
+    VP_TEST_SIGNAL_B         = 2,
+    VP_TEST_SIGNAL_CM        = 3,
+    VP_TEST_SIGNAL_DIFF      = 4,
+    VP_TEST_SIGNAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenSignalType;
+
+typedef enum VpTestGenGainType {
+    VP_TEST_MEAS_UNDEFINED     = 0,
+    VP_TEST_MEAS_LOW_GAIN      = 1,
+    VP_TEST_MEAS_NORM_GAIN     = 2,
+    VP_TEST_MEAS_HIGH_GAIN     = 3,
+    VP_TEST_MEAS_SKIP          = 4,
+    VP_TEST_MEAS_IMT_NORM_GAIN = 5,
+    VP_TEST_MEAS_IMT_HIGH_GAIN = 6,
+    VP_TEST_MEAS_VAB_LOW_GAIN  = 7,
+    VP_TEST_MEAS_VAB_NORM_GAIN = 8,
+    VP_TEST_MEAS_VAB_HIGH_GAIN = 9,
+    VP_TEST_MEAS_ILG_NORM_GAIN = 10,
+    VP_TEST_MEAS_ILG_HIGH_GAIN = 11,
+    VP_TEST_MEAS_GEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenGainType;
+
+typedef struct VpTestGenTestType {
+    VpTestGenFilterType filter;
+    VpTestMathType type;
+    VpTestGenDriveType  driveMode;
+    VpTestGenSignalType  signalMode;
+    int16 vTestLevel;
+    uint16 freq;
+    int16 vTipBias;
+    int16 vRingBias;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestGenGainType iaMeas;
+    VpTestGenGainType vaMeas;
+    VpTestGenGainType ibMeas;
+    VpTestGenGainType vbMeas;
+} VpTestGenTestType;
+
+typedef struct VpTestResultGenTestType {
+    int16 iaReal;
+    int16 iaImag;
+    int16 vaReal;
+    int16 vaImag;
+    int16 ibReal;
+    int16 ibImag;
+    int16 vbReal;
+    int16 vbImag;
+} VpTestResultGenTestType;
+
+/* Definitions for Test results */
+typedef union VpTestResultsUnionType {
+    bool                          hstatus;
+    int16                         sVout;
+    uint16                        uVout;
+    int16                         vcm;
+    uint16                        vrms;
+    VpTestResultVxcType           vxc;
+    VpTestResultDcRlType          dcvab;
+    VpTestResultAcRlType          acimt;
+    VpTestResultAcRlPhaseType     acimtp;
+    VpTestResultVixType           vix;
+    VpTestResultResType           res;
+    VpTestResultAltResType        resAlt;
+    VpTestResultMSockType         mSock;
+    VpTestResultXConnectType      xConnect;
+    VpTestResultAltCapType        capAlt;
+    VpTestResultCapType           cap;
+    VpTestResultKeyType           keypad;
+    VpTestResultSnrQDistorType    snrqd;
+    VpTestResultToneType          tone;
+    VpTestResultRenType           ren;
+    VpTestResultLoopCondType      loopCond;
+    VPTestResultLoopbackType      loopback;
+
+    bool                          calFailed;
+    bool                          ringTripFail;
+    bool                          loopFnd;
+    bool                          loopBackTestFail;
+    VpTestResultLineImpdType      lineImpedance;
+    VpTestResultGR909EmfType      emf;
+    VpTestResultGR909ResFltType   resFault;
+    VpTestResultGR909OffHookType  offHookFault;
+    VpTestResultGR909RenType      ringers;
+    VpTestResultGR909AllType      gr909All;
+    VpTestResultRampType          ramp;
+    VpTestResultPcmCollectType    pcmCollect;
+    VpTestResultFltDscrmType      fltDscrm;
+    VpTestResultGenTestType       gen;
+    VpTestResultSRenType          sren;
+} VpTestResultsUnionType;
+
+typedef struct VpTestResultType {
+    VpTestIdType testId;            /* Test identifier */
+    VpTestStatusType errorCode;     /* Error code if Test Failed */
+    VpTestResultsUnionType result;  /* Return Results Union */
+} VpTestResultType;
+
+/* The following enum is used for event associated with VpSelfTest() */
+typedef enum VpSelfTestResultIdType {
+    VP_STEST_SUCCESS = 0,
+    VP_STEST_FAIL    = 1,
+    VP_STEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSelfTestResultIdType;
+
+#endif /* VP_API_TEST_H */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_api_timer.h b/tools/voice/zarlink/user/api_lib/includes/vp_api_timer.h
new file mode 100644
index 0000000..32bf176
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_api_timer.h
@@ -0,0 +1,210 @@
+/** \file vp_api_timer.h
+ * vp_api_timer.h
+ *
+ * Header file for all timer typedefs used in API-II (internal).
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ */
+
+#ifndef VP_API_TIMER_H
+#define VP_API_TIMER_H
+
+/* IMT average for Voltage to Frequency (FXO) smoothing */
+#define VP_IMT_AVG_LENGTH 2  /* FXO variable, but need this to compile */
+
+#define VP_ACTIVATE_TIMER       0x8000
+#define VP_TIMER_TIME_MASK      0x7FFF
+
+/**************************************************************************************************
+ * Common Timer Values - all times in ms                                                          *
+ **************************************************************************************************/
+/**< VP_DEV_TIMER_EXIT_RINGING_SAMPLE
+ * Used on VE880 ABS only at the moment. This is the initial time to delay switching from High Power
+ * to medium Power when exiting Ringing. It should be longer than the longest silent interval in any
+ * Ringing Cadence ideally. If not, it just means the supply would be switched to Medium Power and
+ * then quickly set back to High Power. No big deal, but not preferred.
+ */
+#define VP_DEV_TIMER_EXIT_RINGING_SAMPLE    (5000)
+
+/**< VP_DEV_TIMER_EXIT_RINGING_UPDATE
+ * Used on VE880 ABS only at the moment. This is the interval used to recheck for Ringing Exit after
+ * waiting the time specified by VP_DEV_TIMER_EXIT_RINGING_SAMPLE.
+ */
+#define VP_DEV_TIMER_EXIT_RINGING_UPDATE    (1000)
+
+/**< VP_WB_CHANGE_MASK_TIME
+ * The time used to mask Clock Fault after changing to or from Wideband mode on VE880 or VE890
+ */
+#define VP_WB_CHANGE_MASK_TIME              (20)
+
+/**< VP_DISCONNECT_RECOVERY_TIME
+ * Hook debounce time when exiting disconnect. This is to allow hook stability in case of high
+ * REN load conditions. Time of 100ms is sufficient for all normal field conditions, but if testing
+ * with 5REN per GR57 (40uF + 1386ohm) this time needs to be 120-130ms.
+ */
+#define VP_DISCONNECT_RECOVERY_TIME         (100)
+
+/**< VP_POLREV_DEBOUNCE_TIME
+ * Debounce time to mask hook activity when reversing polarity on the FXS line. The value (120ms)
+ * is designed to prevent false off-hook from being reported when changing line polarity under
+ * load conditions of 5REN FCC Part 68 load with 16ms Switch Hook Debounce in the DC Feed Profile.
+ * Applications that require detection of hook changes after polarity reversal in less than 120ms
+ * will have to change this value. Applications that need to prevent spurious hook events for load
+ * conditions of GR57 5REN (see "Ringing Capability) using 40uf + 1386ohm may need to increase this
+ * value. Note however that 40uf + 1386ohm condition is for test purposes only, not representative
+ * of real-world conditions.
+ */
+#define VP_POLREV_DEBOUNCE_TIME     (120)
+
+/**< Line Timer Definitions/Indexes
+ * Note that since the timer indexes themselves are generally used in incrememtal loops through
+ * the line timer array, these values must be sequential, unsigned type
+ */
+/**< VP_LINE_CID_DEBOUNCE: Hook debounce timer for conditions determined by the CID State Machine */
+#define VP_LINE_CID_DEBOUNCE            0
+
+/**< VP_LINE_TIMER_CID_DTMF: Timer for DTMF generation in CID */
+#define VP_LINE_TIMER_CID_DTMF          (VP_LINE_CID_DEBOUNCE + 1)
+
+/**< VP_LINE_TIMER_FAULT: VE790 only fault management timer */
+#define VP_LINE_TIMER_FAULT             (VP_LINE_TIMER_CID_DTMF + 1)
+
+/**< VP_LINE_RING_EXIT_PROCESS: Timer used for Ringing Exit handing */
+#define VP_LINE_RING_EXIT_PROCESS      (VP_LINE_TIMER_FAULT + 1)
+
+    /**< VP_CSLAC_RINGING_EXIT_MAX
+     * This value sets the maximum time the API will wait for the sillicon to exit it's own internal
+     * Ringing Exit state (used for certain conditions) before forcing the line to a know value and
+     * giving up on the timer. This value is monitored in the VE880/890 VP_LINE_RING_EXIT_PROCESS
+     * timer management functions. The time specified is in mSec.
+     */
+    #define VP_CSLAC_RINGING_EXIT_MAX       (100)
+
+/**< VP_LINE_HOOK_FREEZE:
+ * Hook Mask when making any line change that could cause spurious hook activity. This time should
+ * be used ONLY to mask hook activity, not as part of a control sequence. When it expires, the only
+ * action remaining should be to read the signaling register and process hook activity.
+ */
+#define VP_LINE_HOOK_FREEZE         (VP_LINE_RING_EXIT_PROCESS + 1)
+
+/**< VP_LINE_DISCONNECT_EXIT: Line Debounce for Disconnect Recovery */
+#define VP_LINE_DISCONNECT_EXIT         (VP_LINE_HOOK_FREEZE + 1)
+
+/**< VP_LINE_GND_START_TIMER: Timer for Recovery from Tip-Open */
+#define VP_LINE_GND_START_TIMER         (VP_LINE_DISCONNECT_EXIT + 1)
+
+/**< VP_LINE_CAL_LINE_TIMER: Timer used to sequence the CID state machine */
+#define VP_LINE_CAL_LINE_TIMER          (VP_LINE_GND_START_TIMER + 1)
+
+/**< VP_LINE_PING_TIMER: VE880 Rev VC only used to prevent phone "ping" when exiting disconnect */
+#define VP_LINE_PING_TIMER              (VP_LINE_CAL_LINE_TIMER + 1)
+
+/**< VP_LINE_TRACKER_DISABLE: Used to disable switcher with low power termination type. */
+#define VP_LINE_TRACKER_DISABLE         (VP_LINE_PING_TIMER + 1)
+
+/**< VP_LINE_GPIO_CLKOUT_TIMER: VE580 only time used to slow ringing signal clock output */
+#define VP_LINE_GPIO_CLKOUT_TIMER       (VP_LINE_TRACKER_DISABLE + 1)
+
+/**< VP_LINE_INTERNAL_TESTTERM_TIMER: Timer for the internal test termination */
+#define VP_LINE_INTERNAL_TESTTERM_TIMER (VP_LINE_GPIO_CLKOUT_TIMER + 1)
+
+/**< VP_LINE_SPEEDUP_RECOVERY_TIMER: Time used to manage the mettalic and battery speedup when
+ * making certain state transitions for VE880 and VE890
+ */
+#define VP_LINE_SPEEDUP_RECOVERY_TIMER  (VP_LINE_INTERNAL_TESTTERM_TIMER + 1)
+
+/**< VP_LINE_TIMER_LAST: Place holder to indicate number of line timers */
+#define VP_LINE_TIMER_LAST              (VP_LINE_SPEEDUP_RECOVERY_TIMER + 1)
+
+/**< Device Timer Definitions */
+/* Test line timer to ensure a more consistant MPI PCM collect routine, leave
+ * this timer as the first timer. */
+#define VP_DEV_TIMER_TESTLINE   0
+
+/* Clock fail interrupt timer - used only in 790 API */
+#define VP_DEV_TIMER_CLKFAIL            (VP_DEV_TIMER_TESTLINE + 1)
+
+/* ABS Calibration timer */
+#define VP_DEV_TIMER_ABSCAL             (VP_DEV_TIMER_CLKFAIL + 1)
+
+/* Lower Power Mode Switcher Changes */
+#define VP_DEV_TIMER_LP_CHANGE          (VP_DEV_TIMER_ABSCAL + 1)
+
+/* ABV Caibration  device timers */
+#define VP_DEV_TIMER_ABV_CAL            (VP_DEV_TIMER_LP_CHANGE + 1)
+
+/* In-rush limiting enter ringing device timers */
+#define VP_DEV_TIMER_ENTER_RINGING      (VP_DEV_TIMER_ABV_CAL + 1)
+
+/* Used on VE880-ABS only to time switching of the Supply Mode from HP (in Ringing) to MP */
+#define VP_DEV_TIMER_EXIT_RINGING       (VP_DEV_TIMER_ENTER_RINGING + 1)
+
+/* Used to mask clock faults */
+#define VP_DEV_TIMER_WB_MODE_CHANGE     (VP_DEV_TIMER_EXIT_RINGING + 1)
+
+/* Place holder to indicate number of device timers */
+#define VP_DEV_TIMER_LAST               (VP_DEV_TIMER_WB_MODE_CHANGE + 1)
+
+/** FXO specific timer variables to be used for FXO type lines only */
+typedef enum VpCslacTimerType {
+    VP_CSLAC_FXS_TIMER,
+    VP_CSLAC_FXO_TIMER,
+    VP_CSLAC_TIMER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCslacTimerType;
+
+
+#if (defined (VP_CC_880_SERIES) && defined (VP880_FXO_SUPPORT)) || \
+    (defined (VP_CC_890_SERIES) && defined (VP890_FXO_SUPPORT)) || \
+     defined (VP_CC_580_SERIES) || defined (VP_CC_KWRAP)
+typedef struct VpFXOTimerType {
+    uint16  highToLowTime;      /**< Device timestamp of last high to low change */
+    uint16  prevHighToLowTime;
+    bool    noCount;            /**< TRUE when not counting - lack of activity */
+    bool    lastState;          /**< TRUE if last known high, FALSE if low */
+    uint16  timeLastPolRev;     /**< Time in 0.25ms since polrev detected */
+    uint16  timePrevPolRev;     /**< Time in 0.25ms since prev polrev detected */
+    uint8   maxPeriod;          /**< Time in 0.25ms that ringing is detected */
+    uint16  lastStateChange;    /**< Time in 1mS since last state change */
+    uint16  lastNotLiu;         /**< Time in 1mS since last Not LIU detected */
+    uint16  disconnectDebounce; /**< Time in 1mS to debounce disconnect events */
+    uint16  disconnectDuration; /**< Time in ticks that disconnect is detected */
+    uint8   liuDebounce;        /**< Time in 1mS to debounce LIU detection that
+                                     accompanies some kinds of ringing */
+    uint8   ringOffDebounce;    /**< Time in 1mS to ignore disconnect after ring_off */
+    uint8   ringTimer;          /**< When this timer expires, ringing is off */
+    uint8   cidCorrectionTimer; /**< 1mS increments for CID correction timing */
+    uint8   bCalTimer;          /**< 1mS increments for BFilter sampling time */
+    uint16  fxoDiscIO2Change;   /**< Countdown in 1ms since IO2 changed for FXO_DISC termType */
+    uint16  pllRecovery;        /**< Timer in ticks to recover PLL when FXO Disconnect to OHT */
+    uint16  currentMonitorTimer;/**< Used to provide FXO line current buffer */
+    uint16  measureBFilterTimer;/**< 1mS increments for BFilter sampling time */
+    uint8   lowVoltageTimer;    /**< Timer in ticks for the low voltage
+                                     disconnect/LIU distinction workaround */
+} VpFXOTimerType;
+#endif
+
+/** Union of FXO and FXS timers since only one type can exist for each line */
+typedef union VpCslacTimers {
+#if (defined (VP_CC_880_SERIES) && defined (VP880_FXO_SUPPORT)) || \
+    (defined (VP_CC_890_SERIES) && defined (VP890_FXO_SUPPORT)) || \
+     defined (VP_CC_580_SERIES) || defined (VP_CC_KWRAP)
+    VpFXOTimerType fxoTimer;
+#endif
+    uint16 timer[VP_LINE_TIMER_LAST]; /**< FXS Array of timers */
+    uint16 trackingTime;    /**< Used in VE880/VE890 to track the total time the Ring Exit Timer
+                             * has been running. The Ring Exit Timer is restarted while waiting for
+                             * the silicon to make it's internal SLIC state change (i.e., get out of
+                             * the Ring Exit State). But in case the SLIC never makes the expected
+                             * state change, we want to force the final change and terminate the
+                             * timer.
+                             */
+} VpCslacTimers;
+
+typedef struct VpCslacTimerStruct {
+    VpCslacTimerType type;
+    VpCslacTimers timers;
+} VpCslacTimerStruct;
+#endif
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_debug.h b/tools/voice/zarlink/user/api_lib/includes/vp_debug.h
new file mode 100644
index 0000000..f0e20a1
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_debug.h
@@ -0,0 +1,475 @@
+/** \file vp_debug.h
+ * vp_debug.h
+ *
+ * This file contains the configuration and compile time settings for
+ * the VoicePath API debug statements.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 9053 $
+ * $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
+ *
+ * As of svn 5835, no part of the VP-API-II uses the old VP_DOUT method.
+ */
+
+#ifndef VP_DEBUG_H
+#define VP_DEBUG_H
+
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "sys_service.h"
+
+/*
+ * These are not documented in the API-II and should be used for internal
+ * purposes only. Reserved range (0x00010000 to 0x80000000)
+ */
+#define DBG_EVENT_VERBOSE   0x00010000 /* Verbose event debug (792) */
+#define DBG_BOOT_WRITE      0x00020000 /* Displays all boot blocks */
+
+/* Define VP_DEBUG_COLOR to display ANSI X3.64 color codes in debug output. */
+#define VP_DEBUG_COLOR
+#include "vp_debug_colors.h"
+
+/* Colors for debug messages (if VP_DEBUG_COLOR is defined): */
+#define VP_DBG_ERROR_COLOR          bright_red
+#define VP_DBG_WARNING_COLOR        dark_yellow
+#define VP_DBG_INFO_COLOR           dark_blue
+#define VP_DBG_API_FUNC_COLOR       bright_cyan
+#define VP_DBG_API_FUNC_INT_COLOR   dark_cyan
+#define VP_DBG_HAL_COLOR            bright_white
+#define VP_DBG_SSL_COLOR            dark_green
+#define VP_DBG_EVENT_COLOR          bright_blue
+#define VP_DBG_CALIBRATION_COLOR    bright_white
+#define VP_DBG_LINE_STATE_COLOR     dark_yellow
+#define VP_DBG_HOOK_COLOR           bright_cyan
+#define VP_DBG_TEST_COLOR           bright_blue
+#define VP_DBG_TEST_FUNC_COLOR      bright_yellow
+#define VP_DBG_FXO_FUNC_COLOR       dark_green
+#define VP_DBG_SEQUENCER_COLOR      dark_blue
+#define VP_DBG_CID_COLOR            bright_white
+#define VP_DBG_TEST_PCM_COLOR       bright_cyan
+#define VP_DBG_GAIN_COLOR           dark_yellow
+
+/* Define VP_DEBUG_LOC to include the location (file and line) in each debug message. */
+#undef VP_DEBUG_LOC
+
+#ifdef VP_DEBUG_LOC
+#define VP_SHOW_LOC() VpSysDebugPrintf(" (" __FILE__ ":%d)", __LINE__)
+#else
+#define VP_SHOW_LOC()
+#endif
+
+/* Basic debug output macro: */
+#define VP_DOUT_(msgType, msgColor, objType, pObj, printf_args) \
+    if (VpDebugEnabled_ ## objType (VP_DBG_ ## msgType, color_fg(msgColor) #msgType, pObj)) { \
+        VpSysDebugPrintf printf_args; \
+        VP_SHOW_LOC(); \
+        VpSysDebugPrintf(color_reset "\n"); \
+    }
+
+/* Conditionally compile in various types of debug messages: */
+#if !defined(VP_DEBUG) && defined(VP_CC_DEBUG_SELECT)
+#undef VP_CC_DEBUG_SELECT
+#endif
+#ifndef VP_CC_DEBUG_SELECT
+#define VP_CC_DEBUG_SELECT 0
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_ERROR)
+#define VP_ERROR(objType, pObj, printf_args) VP_DOUT_(ERROR, VP_DBG_ERROR_COLOR, objType, pObj, printf_args)
+#else
+#define VP_ERROR(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_WARNING)
+#define VP_WARNING(objType, pObj, printf_args) VP_DOUT_(WARNING, VP_DBG_WARNING_COLOR, objType, pObj, printf_args)
+#else
+#define VP_WARNING(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_INFO)
+#define VP_INFO(objType, pObj, printf_args) VP_DOUT_(INFO, VP_DBG_INFO_COLOR, objType, pObj, printf_args)
+#else
+#define VP_INFO(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_API_FUNC)
+#define VP_API_FUNC(objType, pObj, printf_args) VP_DOUT_(API_FUNC, VP_DBG_API_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_API_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_API_FUNC_INT)
+#define VP_API_FUNC_INT(objType, pObj, printf_args) VP_DOUT_(API_FUNC_INT, VP_DBG_API_FUNC_INT_COLOR, objType, pObj, printf_args)
+#else
+#define VP_API_FUNC_INT(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_CALIBRATION)
+#define VP_CALIBRATION(objType, pObj, printf_args) VP_DOUT_(CALIBRATION, VP_DBG_CALIBRATION_COLOR, objType, pObj, printf_args)
+#else
+#define VP_CALIBRATION(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_LINE_STATE)
+#define VP_LINE_STATE(objType, pObj, printf_args) VP_DOUT_(LINE_STATE, VP_DBG_LINE_STATE_COLOR, objType, pObj, printf_args)
+#else
+#define VP_LINE_STATE(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_HOOK)
+#define VP_HOOK(objType, pObj, printf_args) VP_DOUT_(HOOK, VP_DBG_HOOK_COLOR, objType, pObj, printf_args)
+#else
+#define VP_HOOK(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST)
+#define VP_TEST(objType, pObj, printf_args) VP_DOUT_(TEST, VP_DBG_TEST_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST_FUNC)
+#define VP_TEST_FUNC(objType, pObj, printf_args) VP_DOUT_(TEST_FUNC, VP_DBG_TEST_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_FXO_FUNC)
+#define VP_FXO_FUNC(objType, pObj, printf_args) VP_DOUT_(FXO_FUNC, VP_DBG_FXO_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_FXO_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SEQUENCER)
+#define VP_SEQUENCER(objType, pObj, printf_args) VP_DOUT_(SEQUENCER, VP_DBG_SEQUENCER_COLOR, objType, pObj, printf_args)
+#else
+#define VP_SEQUENCER(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_CID)
+#define VP_CID(objType, pObj, printf_args) VP_DOUT_(CID, VP_DBG_CID_COLOR, objType, pObj, printf_args)
+#else
+#define VP_CID(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST_PCM)
+#define VP_TEST_PCM(objType, pObj, printf_args) VP_DOUT_(TEST_PCM, VP_DBG_TEST_PCM_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST_PCM(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_GAIN)
+#define VP_GAIN(objType, pObj, printf_args) VP_DOUT_(GAIN, VP_DBG_GAIN_COLOR, objType, pObj, printf_args)
+#else
+#define VP_GAIN(objType, pObj, printf_args)
+#endif
+
+
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SSL)
+#define VP_SSL(objType, pObj, printf_args) VP_DOUT_(SSL, VP_DBG_SSL_COLOR, objType, pObj, printf_args)
+#define VP_SYS_ENTER_CRITICAL(deviceId, criticalSecType) VpSysEnterCriticalWrapper(deviceId, criticalSecType)
+#define VP_SYS_EXIT_CRITICAL(deviceId, criticalSecType) VpSysExitCriticalWrapper(deviceId, criticalSecType)
+#define VP_SYS_WAIT(time) \
+    (VP_SSL(None, VP_NULL, ("VpSysWait(%u frames = %u ms)", (time), ((time) + 7 / 8))), VpSysWait(time))
+#else
+#define VP_SSL(objType, pObj, printf_args)
+#define VP_SYS_ENTER_CRITICAL(deviceId, criticalSecType) VpSysEnterCritical(deviceId, criticalSecType)
+#define VP_SYS_EXIT_CRITICAL(deviceId, criticalSecType) VpSysExitCritical(deviceId, criticalSecType)
+#define VP_SYS_WAIT(time) VpSysWait(time)
+#endif
+
+#ifndef VP_HAL_DEVICE_TYPE
+#define VP_HAL_DEVICE_TYPE VP_DEV_VCP_SERIES
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_HAL)
+#define VP_HAL(objType, pObj, printf_args) VP_DOUT_(HAL, VP_DBG_HAL_COLOR, objType, pObj, printf_args)
+#define VP_HAL_HBI_CMD(deviceId, cmd) \
+    (VpDisplayHbiCmd(VP_HAL_DEVICE_TYPE, deviceId, cmd), \
+    VpHalHbiCmd(deviceId, cmd))
+#define VP_HAL_HBI_WRITE(deviceId, cmd, numwords, data) \
+    (VpDisplayHbiCmd(VP_HAL_DEVICE_TYPE, deviceId, cmd), \
+    VpDisplayHbiData(deviceId, numwords + 1, data), \
+    VpHalHbiWrite(deviceId, cmd, numwords, data))
+#define VP_HAL_HBI_READ(deviceId, cmd, numwords, data) \
+    VpHalHbiReadWrapper(VP_HAL_DEVICE_TYPE, deviceId, cmd, numwords, data)
+#if (VP_CC_DEBUG_SELECT & DBG_BOOT_WRITE)
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    (VpDisplayHbiAccess(VP_HAL_DEVICE_TYPE, deviceId, numWords + 1, (uint16p)(data)), \
+    VpHalHbiBootWr(deviceId, numWords, data))
+#else
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    VpHalHbiBootWr(deviceId, numWords, data)
+#endif
+#else
+#define VP_HAL_HBI_CMD(deviceId, cmd) \
+    VpHalHbiCmd(deviceId, cmd)
+#define VP_HAL_HBI_WRITE(deviceId, cmd, numwords, data) \
+    VpHalHbiWrite(deviceId, cmd, numwords, data)
+#define VP_HAL_HBI_READ(deviceId, cmd, numwords, data) \
+    VpHalHbiRead(deviceId, cmd, numwords, data)
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    VpHalHbiBootWr(deviceId, numWords, data)
+#endif
+
+/* Basic assert macro: */
+#define VP_ASSERT(condition) \
+    if (!(condition)) { \
+        VP_ERROR(None, VP_NULL, ("Assertion failed: %s\n", #condition)); \
+        /* exit(-1); */ \
+    }
+
+#define VP_DOUT(msgType, printf_args)
+
+/* Global debug select mask (for messages that are not specific to a particular
+   line or device): */
+EXTERN uint32 vpDebugSelectMask;
+
+#ifdef VP_CC_VCP2_SERIES
+EXTERN bool
+VpDebugEnabled_VpVcp2DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpVcp2DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_VpVcp2LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpVcp2LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_MELT_SERIES
+EXTERN bool
+VpDebugEnabled_VpMeltDeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpMeltDeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_VpMeltLineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpMeltLineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_890_SERIES
+EXTERN bool
+VpDebugEnabled_Vp890DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp890DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp890LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp890LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_880_SERIES
+EXTERN bool
+VpDebugEnabled_Vp880DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp880DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp880LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp880LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_580_SERIES
+EXTERN bool
+VpDebugEnabled_Vp580DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp580DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp580LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp580LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_790_SERIES
+EXTERN bool
+VpDebugEnabled_Vp790DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp790DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp790LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp790LineObjectType *pLineObj);
+#endif
+
+EXTERN bool
+VpDebugEnabled_VpDeviceIdType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpDeviceIdType *pDeviceId);
+
+EXTERN bool
+VpDebugEnabled_VpLineIdType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpLineIdType *pLineId);
+
+EXTERN bool
+VpDebugEnabled_VpDevCtxType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpDevCtxType *pDevCtx);
+
+EXTERN bool
+VpDebugEnabled_VpLineCtxType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpLineCtxType *pLineCtx);
+
+EXTERN bool
+VpDebugEnabled_None(
+    uint32 msgType,
+    char *msgTypeStr,
+    void *nothing);
+
+EXTERN const char *
+VpGetString_VpStatusType(
+    VpStatusType status);
+
+EXTERN const char *
+    VpGetString_VpOptionIdType(
+    VpOptionIdType status);
+
+EXTERN const char *
+VpGetString_VpProfileType(
+    VpProfileType profType);
+
+EXTERN void
+VpDisplayEvent(
+    VpEventType *pEvent);
+
+EXTERN void
+VpDisplayResults(
+    VpEventType *pEvent,
+    void *pResult);
+
+EXTERN void
+VpDisplayHbiAccess(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    unsigned bufLen,
+    uint16 *buf);
+
+EXTERN unsigned
+VpDisplayHbiCmd(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    uint16 cmd);
+
+EXTERN void
+VpDisplayHbiData(
+    VpDeviceIdType deviceId,
+    unsigned bufLen,
+    uint16 *buf);
+
+EXTERN bool
+VpHalHbiReadWrapper(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    uint16 cmd,
+    uint8 numwords,
+    uint16 *data);
+
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SSL)
+EXTERN const char *
+VpGetString_VpCriticalSecType(
+    VpCriticalSecType criticalSecType);
+
+EXTERN uint8
+VpSysEnterCriticalWrapper(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+
+EXTERN uint8
+VpSysExitCriticalWrapper(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+#endif
+
+/* Derivative debug macros: */
+#define VP_API_ENTER(objType, pObj, funcName) \
+    VP_API_FUNC(objType, pObj, ("Vp%s():", funcName))
+#define VP_API_EXIT(objType, pObj, funcName, status) \
+    VP_API_FUNC(objType, pObj, ("Vp%s() = %s", funcName, VpGetString_VpStatusType(status)))
+#define VP_API_INT_ENTER(objType, pObj, funcName) \
+    VP_API_FUNC_INT(objType, pObj, ("%s():", funcName))
+#define VP_API_INT_EXIT(objType, pObj, funcName, status) \
+    VP_API_FUNC_INT(objType, pObj, ("%s() = %s", funcName, VpGetString_VpStatusType(status)))
+
+#if defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES)
+#if (VP_CC_DEBUG_SELECT & VP_DBG_ERROR)
+void VpPrintTermType(VpTermType termType);
+void VpPrintLineStateType(VpLineStateType lineState, char *strLineState);
+void VpPrintOptionRingControlType(VpOptionRingControlType *ringCtrl);
+void VpPrintOptionZeroCrossType(VpOptionZeroCrossType zeroCross);
+void VpPrintRelayControlType(VpRelayControlType relayState);
+void VpPrintOptionCodecType(VpOptionCodecType codec);
+void VpPrintOptionPcmTxRxCntrlType(VpOptionPcmTxRxCntrlType pcmTxRxCtrl);
+void VpPrintCallerIdType(VpCallerIdType *callerId);
+void VpPrintCidSeqDataType(VpCidSeqDataType *cidSeq);
+void VpPrintSeqDataType(VpSeqDataType *cadence);
+void VpPrintVpCslacTimerStruct(VpCslacTimerStruct *lineTimers);
+
+
+void VpPrintApiIntLineState(VpApiIntLineStateType *lineState);
+void VpPrintDigitGenDataType(VpDigitGenerationDataType *digitGenStruct);
+
+
+void VpPrintDynamicInfoStruct(VpDeviceDynamicInfoType *dynamicInfo);
+void VpPrintStaticInfoStruct(VpDeviceStaticInfoType *staticInfo);
+
+/* Bit-wise values from VpDeviceStateType */
+void VpPrintStateInformation(uint16 state);
+void
+VpPrintDeviceProfileStruct(
+    VpDeviceType deviceType,
+    void *devProfileData);
+
+void
+VpPrintEventMaskStruct(
+    bool isDeviceInfo,
+    bool isMask,
+    VpOptionEventMaskType *eventMask);
+
+void VpPrintCriticalFltStruct(VpOptionCriticalFltType *criticalFault);
+void VpPrintGetResultsOptionStruct(VpGetResultsOptionsType *resultsOption);
+void VpPrintRelGainResultsStruct(VpRelGainResultsType *relGainResults);
+
+#define VpPrintEventHandle(eventHandle)     VpSysDebugPrintf("\n\n\rpDevObj->eventHandle = 0x%04X", eventHandle)
+#define VpPrintTimeStamp(timeStamp)         VpSysDebugPrintf("\n\n\rpDevObj->timeStamp = 0x%04X", timeStamp)
+
+void VpPrintDeviceProfileTable(VpCSLACDeviceProfileTableType *devProfileTable);
+void VpPrintProfileTableEntry(VpCSLACProfileTableEntryType *profEntry);
+
+#if defined (VP890_FXS_SUPPORT) || defined (VP880_FXS_SUPPORT)
+void
+VpPrintPulseSpecs(
+    uint8 specNumber,
+    VpOptionPulseType *pulseSpecs);
+void
+VpPrintDPStateMachine(
+    uint8 stateMachineNum,
+    VpDialPulseDetectType  *dpStruct);
+#endif
+
+void
+VpPrintDeviceTimers(
+    uint16 devTimer[VP_DEV_TIMER_LAST]);
+
+#define VpPrintResponseData(responseData)       VpSysDebugPrintf("\n\n\rpDevObj->responseData = 0x%04X", responseData)
+#define VpPrintTxBufferRate(txBufferDataRate)   VpSysDebugPrintf("\n\n\rpDevObj->txBufferDataRate = %d", txBufferDataRate)
+
+
+#endif  /* VP_CC_DEBUG_SELECT & VP_DBG_ERROR */
+#endif  /* defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES) */
+
+
+
+
+
+
+
+#endif /* VP_DEBUG_H */
+
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_debug_colors.h b/tools/voice/zarlink/user/api_lib/includes/vp_debug_colors.h
new file mode 100644
index 0000000..6a51bf8
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_debug_colors.h
@@ -0,0 +1,81 @@
+/* \file vp_debug_colors.h
+ * vp_debug_colors.h
+ *
+ * This file contains ANSI X3.64 codes for displaying colors.
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 5264 $
+ * $LastChangedDate: 2009-07-06 10:22:54 -0500 (Mon, 06 Jul 2009) $
+ */
+
+#ifndef VP_DEBUG_COLORS_H
+#define VP_DEBUG_COLORS_H
+
+#include "vp_api_cfg.h"
+
+#ifdef VP_DEBUG_COLOR
+
+#define COLORS_begin    "\x1b["
+#define COLORS_delim    ";"
+#define COLORS_end      "m"
+#define COLORS_reset    "0"
+#define COLORS_bold     "1"
+#define COLORS_nonbold  "22"
+#define COLORS_fore     "3"
+#define COLORS_back     "4"
+
+#define COLORS_black    "0"
+#define COLORS_red      "1"
+#define COLORS_green    "2"
+#define COLORS_yellow   "3"
+#define COLORS_blue     "4"
+#define COLORS_magenta  "5"
+#define COLORS_cyan     "6"
+#define COLORS_white    "7"
+
+#define COLORS_bright_black     COLORS_black    COLORS_delim COLORS_bold
+#define COLORS_bright_red       COLORS_red      COLORS_delim COLORS_bold
+#define COLORS_bright_green     COLORS_green    COLORS_delim COLORS_bold
+#define COLORS_bright_yellow    COLORS_yellow   COLORS_delim COLORS_bold
+#define COLORS_bright_blue      COLORS_blue     COLORS_delim COLORS_bold
+#define COLORS_bright_magenta   COLORS_magenta  COLORS_delim COLORS_bold
+#define COLORS_bright_cyan      COLORS_cyan     COLORS_delim COLORS_bold
+#define COLORS_bright_white     COLORS_white    COLORS_delim COLORS_bold
+
+#define COLORS_dark_black       COLORS_black    COLORS_delim COLORS_nonbold
+#define COLORS_dark_red         COLORS_red      COLORS_delim COLORS_nonbold
+#define COLORS_dark_green       COLORS_green    COLORS_delim COLORS_nonbold
+#define COLORS_dark_yellow      COLORS_yellow   COLORS_delim COLORS_nonbold
+#define COLORS_dark_blue        COLORS_blue     COLORS_delim COLORS_nonbold
+#define COLORS_dark_magenta     COLORS_magenta  COLORS_delim COLORS_nonbold
+#define COLORS_dark_cyan        COLORS_cyan     COLORS_delim COLORS_nonbold
+#define COLORS_dark_white       COLORS_white    COLORS_delim COLORS_nonbold
+
+/*
+ * Usage example:
+ * printf( color_reset             "this is white-on-black text"
+ *         color(red, blue)        "this is red-on-blue text"
+ *         color_fg(green)         "this is green-on-blue text"
+ *         color_fg(bright_white)  "this is bright-white-on-blue text"
+ *         color_bg(black)         "this is bright-white-on-black text"
+ *         color_reset             "this is white on black\n"
+ * );
+ * Note: Bright colors are only allowed in the foreground.
+ */
+
+#define color_fg(c)             COLORS_begin COLORS_fore COLORS_ ## c COLORS_end
+#define color_bg(c)             COLORS_begin COLORS_back COLORS_ ## c COLORS_end
+#define color(fore_c, back_c)   COLORS_begin COLORS_fore COLORS_ ## fore_c COLORS_delim COLORS_back COLORS_ ## back_c COLORS_end
+#define color_reset             COLORS_begin COLORS_reset COLORS_end
+
+#else /* !defined(VP_DEBUG_COLOR) */
+
+#define color_fg(c)             ""
+#define color_bg(c)             ""
+#define color(fore_c, back_c)   ""
+#define color_reset             ""
+
+#endif
+
+#endif /* VP_DEBUG_COLORS_H */
diff --git a/tools/voice/zarlink/user/api_lib/includes/vp_debug_masks.h b/tools/voice/zarlink/user/api_lib/includes/vp_debug_masks.h
new file mode 100755
index 0000000..4a4af3c
--- /dev/null
+++ b/tools/voice/zarlink/user/api_lib/includes/vp_debug_masks.h
@@ -0,0 +1,41 @@
+/** \file vp_debug_masks.h
+ * vp_debug_masks.h
+ *
+ * This file contains the debug masks for the VP-APi_II
+ *
+ * Copyright (c) 2011, Microsemi
+ *
+ * $Revision: 7140 $
+ * $LastChangedDate: 2010-05-12 09:50:40 -0500 (Wed, 12 May 2010) $
+ */
+
+#ifndef VP_DEBUG_MASKS_H
+#define VP_DEBUG_MASKS_H
+
+/* VP-API debug message types: */
+#define VP_DBG_ERROR        0x00000001 /* Any error condition */
+#define VP_DBG_WARNING      0x00000002 /* Any warning condition */
+#define VP_DBG_INFO         0x00000004 /* Un-categorized information */
+#define VP_DBG_API_FUNC     0x00000008 /* API function entry/exit (except tick) */
+
+#define VP_DBG_API_FUNC_INT 0x00000010 /* Internal API function entry/exit */
+#define VP_DBG_HAL          0x00000020 /* HAL traffic */
+#define VP_DBG_SSL          0x00000040 /* SSL function entry/exit */
+#define VP_DBG_EVENT        0x00000080 /* Events/results from VpGetEvent()/VpGetResults() */
+
+#define VP_DBG_HOOK         0x00000100 /* Hook Based Code */
+#define VP_DBG_LINE_STATE   0x00000200 /* Set Line State Based Code */
+#define VP_DBG_CALIBRATION  0x00000400 /* VpCalCodec(), VpCalLine(), VpCal() */
+#define VP_DBG_TEST         0x00000800 /* Verbose test debug */
+
+#define VP_DBG_TEST_FUNC    0x00001000 /* Test I/F function enter and exit */
+#define VP_DBG_FXO_FUNC     0x00002000 /* FXO Detection Code */
+#define VP_DBG_SEQUENCER    0x00004000 /* Sequencer Based Code */
+#define VP_DBG_CID          0x00008000 /* Caller ID funcitons */
+
+#define VP_DBG_TEST_PCM     0x00010000 /* Verbose test pcm collection */
+#define VP_DBG_GAIN         0x00020000 /* VpSetRelGain() and VP_OPTION_ID_ABS_GAIN */
+
+#define VP_DBG_ALL          0xFFFFFFFF
+
+#endif /* VP_DEBUG_MASKS_H */
diff --git a/tools/voice/zarlink/user/arch_marvell/Le71HP0410G_init.c b/tools/voice/zarlink/user/arch_marvell/Le71HP0410G_init.c
new file mode 100644
index 0000000..621b5ed
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/Le71HP0410G_init.c
@@ -0,0 +1,591 @@
+#include <stdio.h>
+#include <time.h>
+#include "vp880_api_int.h"
+#include "vp_api_int.h"
+
+#undef BATT_DEBUG
+
+#ifdef BATT_DEBUG
+#define DBG(args...) printf(args)
+#else
+#define DBG(args...)
+#endif
+
+#define EC_1    VP880_EC_CH1
+#define EC_2    VP880_EC_CH2
+#define EC_BOTH (EC_1 | EC_2)
+
+/* Set device IDs according to the implementation of VpMpiCmd.
+ * Chip selects used:
+ *  CS0 - empty
+ *  CS1 - First device (gDev1Id) (VBH, VBL)
+ *  CS2 - Second device (gDev2Id) (VBP)
+ */
+VpDeviceIdType gDev1Id = 4;
+VpDeviceIdType gDev2Id = 5;
+
+
+/* Calibration arrays initially filled with median values from testing boards
+ * 022 and up as of April 5, 2010 */
+unsigned short gVbhCalAry[30] = {
+	420, 908, 1407, 1901, 2387, 2886, 3387, 3885, 4372, 4872,
+	5365, 5863, 6355, 6858, 7353, 7859, 8328, 8817, 9322, 9819,
+	10325, 10824, 11319, 11820, 12318, 12814, 13314, 13808, 14320, 14759
+};
+unsigned short gVblCalAry[30] = {
+	406, 898, 1396, 1891, 2378, 2879, 3372, 3879, 4377, 4865,
+	5360, 5861, 6360, 6859, 7358, 7856, 8340, 8839, 9335, 9837,
+	10334, 10839, 11332, 11837, 12322, 12828, 13322, 13823, 14322, 14685
+};
+unsigned short gVbpCalAry[30] = {
+	635, 1136, 1640, 2135, 2642, 3146, 3647, 4151, 4649, 5151,
+	5641, 6143, 6650, 7151, 7650, 8148, 8652, 9156, 9659, 10161,
+	10651, 11149, 11654, 12160, 12659, 13158, 13659, 14162, 14672, 15086
+};
+
+extern int BattOn(int vbhSetting, int vblSetting, int vbpSetting);
+
+extern int BattOff(void);
+
+static void CalculateRegisters(uint16 target, uint16 *pCalAry, uint8 *pSwReg, uint8 *pCalReg);
+
+static int MpiTest(VpDeviceIdType devId);
+
+int BattOn(int vbhIn, int vblIn, int vbpIn)
+{
+	uint8 data[20] = { 0 };
+	int i;
+	uint16 vbhTarget;
+	uint16 vblTarget;
+	uint16 vbpTarget;
+	uint8 vbhHex;
+	uint8 vblHex;
+	uint8 vbpHex;
+	uint8 calVbhHex;
+	uint8 calVblHex;
+	uint8 calVbpHex;
+
+	/* Argument checking */
+	if (vblIn > 0) {
+		printf("  VBL must be negative or zero\n");
+		return -1;
+	}
+	if (vbhIn > 0) {
+		printf("  VBH must be negative or zero\n");
+		return -1;
+	}
+	if (vbpIn < 0) {
+		printf("  VBP must be positive or zero\n");
+		return -1;
+	}
+	if (vblIn - vbhIn < 5 && vblIn != 0) {
+		printf("  VBH must be at least 5V more negative than VBL\n");
+		return -1;
+	}
+
+	/* 16 no-ops to clear MPI buffer */
+	for (i = 0; i < 16; i++)
+		data[i] = VP880_NO_OP;
+
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_NO_OP, 16, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_NO_OP, 16, data);
+
+	/* Read RCN/PCN and check that the devices are what we expect */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_DEVTYPE_CMD, VP880_DEVTYPE_LEN, data);
+	if (data[0] != VP880_REV_JE || data[1] != VP880_DEV_PCN_88506) {
+		printf("Invalid device 1, RCN/PCN 0x%02X%02X\n", data[0], data[1]);
+		return -1;
+	}
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_DEVTYPE_CMD, VP880_DEVTYPE_LEN, data);
+	if (data[0] != VP880_REV_JE || data[1] != VP880_DEV_PCN_88506) {
+		printf("Invalid device 2, RCN/PCN 0x%02X%02X\n", data[0], data[1]);
+		return -1;
+	}
+
+	/* Run MPI checks on both devices to make sure that it's safe to start
+	 * programming the devices.  If the signal integrity is bad, it could be
+	 * dangerous to continue. */
+	if (MpiTest(gDev1Id) < 0 || MpiTest(gDev2Id) < 0)
+		return -1;
+
+	/* HW reset */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_HW_RESET_CMD, 0, NULL);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_HW_RESET_CMD, 0, NULL);
+
+	/* Configure 8.192MHz mclk */
+	data[0] = 0x8A;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_MCLK_CNT_WRT, VP880_MCLK_CNT_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_MCLK_CNT_WRT, VP880_MCLK_CNT_LEN, data);
+
+	/* Unmask CFAIL */
+	data[0] = 0xFF & ~(VP880_CFAIL_MASK);
+	data[1] = 0xFF;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_INT_MASK_WRT, VP880_INT_MASK_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_INT_MASK_WRT, VP880_INT_MASK_LEN, data);
+
+	/* Make sure CFAIL clears on both devices */
+	for (i = 0; i < 11; i++) {
+		VpMpiCmd(gDev1Id, EC_BOTH, VP880_UL_SIGREG_RD, VP880_UL_SIGREG_LEN, data);
+		if ((data[0] & VP880_CFAIL_MASK) == 0)
+			break;
+
+		if (i == 10) {
+			printf("Couldn't clear CFAIL on dev 1");
+			return -1;
+		}
+		//mvOsDelay(10);
+		usleep(10000);
+	}
+	for (i = 0; i < 11; i++) {
+		VpMpiCmd(gDev2Id, EC_BOTH, VP880_UL_SIGREG_RD, VP880_UL_SIGREG_LEN, data);
+		if ((data[0] & VP880_CFAIL_MASK) == 0)
+			break;
+
+		if (i == 10) {
+			printf("Couldn't clear CFAIL on dev 2");
+			return -1;
+		}
+		//mvOsDelay(10);
+		usleep(10000);
+	}
+
+	/* Set the switcher timings */
+	data[0] = 0xB2;		/* Device defaults */
+	data[1] = 0x00;
+	data[2] = 0xB1;
+	data[3] = 0x00;
+	data[4] = 0xB0;
+	data[5] = 0x40;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_INT_SWREG_PARAM_WRT, VP880_INT_SWREG_PARAM_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_INT_SWREG_PARAM_WRT, VP880_INT_SWREG_PARAM_LEN, data);
+
+	/* ICR2 settings: c_tip_on and c_ring_on for measuring in disconnect,
+	 * 150V battery limit */
+	data[0] = VP880_ICR2_TIP_SENSE | VP880_ICR2_RING_SENSE;
+	data[1] = VP880_ICR2_TIP_SENSE | VP880_ICR2_RING_SENSE;
+	data[2] = VP880_ICR2_SWY_LIM_CTRL | VP880_ICR2_SWY_LIM_CTRL1;
+	data[3] = VP880_ICR2_SWY_LIM_CTRL | VP880_ICR2_SWY_LIM_CTRL1;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_ICR2_WRT, VP880_ICR2_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_ICR2_WRT, VP880_ICR2_LEN, data);
+
+	/* ICR3 settings: VREF ctrl, "line block control circuitry override" for
+	 * measuring in disconnect */
+	data[0] = VP880_ICR3_VREF_CTRL | VP880_ICR3_LINE_CTRL;
+	data[1] = VP880_ICR3_VREF_CTRL | VP880_ICR3_LINE_CTRL;
+	data[2] = 0;
+	data[3] = 0;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_ICR3_WRT, VP880_ICR3_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_ICR3_WRT, VP880_ICR3_LEN, data);
+
+	/* ICR4 settings: voice ADC override for measuring in disconnect */
+	data[0] = VP880_ICR4_VOICE_ADC_CTRL;
+	data[1] = VP880_ICR4_VOICE_ADC_CTRL;
+	data[2] = 0;
+	data[3] = 0;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_ICR4_WRT, VP880_ICR4_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_ICR4_WRT, VP880_ICR4_LEN, data);
+
+	/* Wait for VREF to stabilize */
+//	mvOsDelay(20);
+	usleep(20000);
+
+	/* Disable auto system state ctrl, zero cross ringing, auto clock fail
+	 * switching, and thermal fault switching.  Enable auto battery shutdown */
+	data[0] = VP880_ACFS_DIS | VP880_ATFS_DIS | VP880_ZXR_DIS | VP880_AUTO_SSC_DIS | VP880_AUTO_BAT_SHUTDOWN_EN;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_SS_CONFIG_WRT, VP880_SS_CONFIG_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_SS_CONFIG_WRT, VP880_SS_CONFIG_LEN, data);
+
+	/* Zero out signal generator params for the channel (ch2 on dev1) that will
+	 * be in ringing */
+	for (i = 0; i < VP880_SIGA_PARAMS_LEN; i++)
+		data[i] = 0;
+
+	VpMpiCmd(gDev1Id, EC_2, VP880_SIGA_PARAMS_WRT, VP880_SIGA_PARAMS_LEN, data);
+
+	/* Calculate the register settings.  Calculations are performed  based on
+	 * units of cV and unsigned, for example -65.3 V == 6530 */
+	vbhTarget = (ABS(vbhIn) * 100);
+	vblTarget = (ABS(vblIn) * 100);
+	vbpTarget = (ABS(vbpIn) * 100);
+
+	DBG("VBH Calibration:\n");
+	CalculateRegisters(vbhTarget, gVbhCalAry, &vbhHex, &calVbhHex);
+	DBG("VBH results, vbhHex %02X, calVbhHex %02X\n\n", vbhHex, calVbhHex);
+
+	DBG("VBL Calibration:\n");
+	CalculateRegisters(vblTarget, gVblCalAry, &vblHex, &calVblHex);
+	DBG("VBL results, vblHex %02X, calVblHex %02X\n\n", vblHex, calVblHex);
+
+	DBG("VBP Calibration:\n");
+	CalculateRegisters(vbpTarget, gVbpCalAry, &vbpHex, &calVbpHex);
+	DBG("VBP results, vbpHex %02X, calVbpHex %02X\n\n", vbpHex, calVbpHex);
+
+	/* Set up switching regulator params - fixed, programmable */
+	data[0] = VP880_FLYBACK_MODE | VP880_ZRING_TRACK_DIS | VP880_YRING_TRACK_DIS;
+	data[1] = VP880_SWY_AUTOPOWER_DIS | vbhHex;
+	data[2] = VP880_SWZ_AUTOPOWER_DIS | vblHex;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_PARAM_WRT, VP880_REGULATOR_PARAM_LEN, data);
+
+	data[0] = VP880_FLYBACK_MODE | VP880_ZRING_TRACK_DIS | VP880_YRING_TRACK_DIS;
+	data[1] = VP880_SWY_AUTOPOWER_DIS | vbpHex;
+	data[2] = VP880_SWZ_AUTOPOWER_DIS;
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_REGULATOR_PARAM_WRT, VP880_REGULATOR_PARAM_LEN, data);
+
+	/* Set battery calibration registers */
+	data[1] = 0;
+	data[0] = calVbhHex << 3;
+	VpMpiCmd(gDev1Id, EC_1, VP880_BAT_CALIBRATION_WRT, VP880_BAT_CALIBRATION_LEN, data);
+	data[0] = calVblHex << 3;
+	VpMpiCmd(gDev1Id, EC_2, VP880_BAT_CALIBRATION_WRT, VP880_BAT_CALIBRATION_LEN, data);
+	data[0] = calVbpHex << 3;
+	VpMpiCmd(gDev2Id, EC_1, VP880_BAT_CALIBRATION_WRT, VP880_BAT_CALIBRATION_LEN, data);
+
+	/* Disable high-pass filter, cut off TX/RX */
+	data[0] = VP880_HIGH_PASS_DIS | VP880_CUT_TXPATH | VP880_CUT_RXPATH;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_OP_COND_WRT, VP880_OP_COND_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_OP_COND_WRT, VP880_OP_COND_LEN, data);
+
+	/* Set to linear mode, use default filters */
+	data[0] = VP880_LINEAR_CODEC | VP880_DEFAULT_OP_FUNC_MODE;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_OP_FUNC_WRT, VP880_OP_FUNC_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_OP_FUNC_WRT, VP880_OP_FUNC_LEN, data);
+
+	/* Set default DISN (00) */
+	data[0] = VP880_DEFAULT_DISN_GAIN;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_DISN_WRT, VP880_DISN_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_DISN_WRT, VP880_DISN_LEN, data);
+
+//	mvOsDelay(50);
+	usleep(50000);
+
+    /*** Bring up HBAT ***/
+	/* Set HBAT switcher to low power. */
+	data[0] = 0;
+	if (vbhTarget != 0)
+		data[0] |= VP880_SWY_LP;
+
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+
+	//mvOsDelay(10);
+	usleep(10000);
+
+	/* Set the line state:
+	 *  Dev 1 ch 1: disconnect (switcher Y)
+	 * Disconnect is needed so that the voltages don't track to VOC */
+	data[0] = VP880_SS_DISCONNECT | VP880_SS_ACTIVATE_MASK;
+	VpMpiCmd(gDev1Id, EC_1, VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, data);
+
+	//mvOsDelay(100);
+		usleep(100000);
+
+    /*** Bring up LBAT ***/
+	/* Do a read/modify/write of ICR2 to override the LBAT switcher (Z) to off
+	 * so that we can set the line state to ringing before turning it on */
+	VpMpiCmd(gDev1Id, EC_2, VP880_ICR2_RD, VP880_ICR2_LEN, data);
+	data[2] |= VP880_ICR2_SWY_CTRL_EN;
+	data[3] &= ~VP880_ICR2_SWY_CTRL_EN;
+	VpMpiCmd(gDev1Id, EC_2, VP880_ICR2_WRT, VP880_ICR2_LEN, data);
+
+	/* Set the switcher control to low power.  It won't actually turn on yet
+	 * because of the ICR2 command above, but setting the register will allow
+	 * the line state to be set to ringing. */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_RD, VP880_REGULATOR_CTRL_LEN, data);
+	data[0] = 0;
+	if (vblTarget != 0)
+		data[0] |= VP880_SWZ_LP;
+
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+
+	//mvOsDelay(10);
+	usleep(10000);
+
+	/* Set the line state:
+	 *  Dev 1 ch 2: ringing (switcher Z) */
+	data[0] = VP880_SS_BALANCED_RINGING;
+	VpMpiCmd(gDev1Id, EC_2, VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, data);
+
+	//mvOsDelay(10);
+	usleep(10000);
+
+	/* Turn the switcher on */
+	VpMpiCmd(gDev1Id, EC_2, VP880_ICR2_RD, VP880_ICR2_LEN, data);
+	data[2] |= VP880_ICR2_SWY_CTRL_EN;
+	data[3] |= VP880_ICR2_SWY_CTRL_EN;
+	VpMpiCmd(gDev1Id, EC_2, VP880_ICR2_WRT, VP880_ICR2_LEN, data);
+
+	//mvOsDelay(100);
+	usleep(100000);
+
+    /*** Bring up PBAT ***/
+	/* Set PBAT switcher to low power. */
+	data[0] = 0;
+	if (vbpTarget != 0)
+		data[0] |= VP880_SWY_LP;
+
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+
+	//mvOsDelay(10);
+	usleep(10000);
+
+	/* Set the line states:
+	 *  Dev 2 ch 1: disconnect (switcher Y)
+	 * Disconnect is needed so that the voltages don't track to VOC */
+	data[0] = VP880_SS_DISCONNECT | VP880_SS_ACTIVATE_MASK;
+	VpMpiCmd(gDev2Id, EC_1, VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, data);
+
+	//mvOsDelay(100);
+	usleep(100000);
+
+	/* Set switchers to high power for non-zero batteries, one at a time */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_RD, VP880_REGULATOR_CTRL_LEN, data);
+
+	if (vbhTarget != 0) {
+		data[0] &= ~VP880_SWY_MODE_MASK;
+		data[0] |= VP880_SWY_HP;
+		VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+	}
+
+	//mvOsDelay(20);
+	usleep(20000);
+
+	if (vblTarget != 0) {
+		data[0] &= ~VP880_SWZ_MODE_MASK;
+		data[0] |= VP880_SWZ_HP;
+		VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+	}
+
+	//mvOsDelay(20);
+	usleep(20000);
+
+	data[0] = 0;
+	if (vbpTarget != 0) {
+		data[0] |= VP880_SWY_HP;
+		VpMpiCmd(gDev2Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+	}
+
+	/* Set IOs to outputs to control the module LEDs */
+	data[0] = VP880_IODIR_IO1_OUTPUT | VP880_IODIR_IO2_OUTPUT;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_IODIR_REG_WRT, VP880_IODIR_REG_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_IODIR_REG_WRT, VP880_IODIR_REG_LEN, data);
+
+	/* Turn on the LEDs for non-zero batteries. */
+	data[0] = 0;
+	if (vbhTarget != 0) {
+		/* gDev1Id IO1 controls the VBH (v1) LED */
+		data[0] |= VP880_IODATA_IO1;
+	}
+	if (vblTarget != 0) {
+		/* gDev1Id IO2 controls the VBL (v2) LED */
+		data[0] |= VP880_IODATA_IO2;
+	}
+	VpMpiCmd(gDev1Id, EC_1, VP880_IODATA_REG_WRT, VP880_IODATA_REG_LEN, data);
+
+	data[0] = 0;
+	if (vbpTarget != 0) {
+		/* gDev2Id IO1 controls the VBP (v3) LED */
+		data[0] |= VP880_IODATA_IO1;
+	}
+	VpMpiCmd(gDev2Id, EC_1, VP880_IODATA_REG_WRT, VP880_IODATA_REG_LEN, data);
+
+	printf("Power supply initialized successfully\n");
+
+	return 0;
+}
+
+int BattOff(void)
+{
+	uint8 data[20];
+	int i;
+
+	/* 16 no-ops to clear MPI buffer */
+	for (i = 0; i < 16; i++)
+		data[i] = VP880_NO_OP;
+
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_NO_OP, 16, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_NO_OP, 16, data);
+
+	/* Read RCN/PCN and check that the devices are what we expect */
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_DEVTYPE_CMD, VP880_DEVTYPE_LEN, data);
+	if (data[0] != VP880_REV_JE || data[1] != VP880_DEV_PCN_88506) {
+		printf("Invalid device 1, RCN/PCN 0x%02X%02X", data[0], data[1]);
+		return -1;
+	}
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_DEVTYPE_CMD, VP880_DEVTYPE_LEN, data);
+	if (data[0] != VP880_REV_JE || data[1] != VP880_DEV_PCN_88506) {
+		printf("Invalid device 2, RCN/PCN 0x%02X%02X", data[0], data[1]);
+		return -1;
+	}
+
+	/* Run MPI checks on both devices to make sure that it's safe to start
+	 * programming the devices.  If the signal integrity is bad, it could be
+	 * dangerous to continue. */
+	if (MpiTest(gDev1Id) < 0 || MpiTest(gDev2Id) < 0)
+		return -1;
+
+	/* Turn switchers off */
+	data[0] = VP880_SWY_OFF | VP880_SWZ_OFF;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_REGULATOR_CTRL_WRT, VP880_REGULATOR_CTRL_LEN, data);
+
+	/* Doubly make sure the switchers are off by setting ontimes to 0 */
+	data[0] = 0x00;
+	data[1] = 0x40;
+	data[2] = 0x00;
+	data[3] = 0x40;
+	data[4] = 0x00;
+	data[5] = 0x40;
+	VpMpiCmd(gDev1Id, EC_BOTH, VP880_INT_SWREG_PARAM_WRT, VP880_INT_SWREG_PARAM_LEN, data);
+	VpMpiCmd(gDev2Id, EC_BOTH, VP880_INT_SWREG_PARAM_WRT, VP880_INT_SWREG_PARAM_LEN, data);
+
+	/* Turn off the LEDs */
+	data[0] = 0;
+	VpMpiCmd(gDev1Id, EC_1, VP880_IODATA_REG_WRT, VP880_IODATA_REG_LEN, data);
+	VpMpiCmd(gDev2Id, EC_1, VP880_IODATA_REG_WRT, VP880_IODATA_REG_LEN, data);
+
+	return 0;
+}
+
+/*
+ * This function uses the calibration data at pCalAry to calculate the switching
+ * regulator and battery calibration register settings needed to produce a
+ * voltage as close as possible to the given target (in |cV|).  The register
+ * values are returned in the data pointed to by pSwReg and pCalReg.
+ */
+static void CalculateRegisters(uint16 target, uint16 *pCalAry, uint8 *pSwReg, uint8 *pCalReg)
+{
+	int16 minError;
+	uint8 minIndex;
+	uint8 index;
+	int16 error;
+	int8 cal;
+
+	DBG("Target = %d\n", target);
+
+	if (target == 0) {
+		*pSwReg = 0;
+		*pCalReg = 0;
+		return;
+	}
+
+	minIndex = 0;
+	minError = 32768;
+
+	/* The calibration data contains measured voltage values at each 5V
+	 * switching regulator step.  Find the 5V step measured value that is closest
+	 * to the target voltage. */
+	for (index = 0; index < 30; index++) {
+		error = target - pCalAry[index];
+		if (ABS(error) < ABS(minError)) {
+			minIndex = index;
+			minError = error;
+		}
+	}
+	DBG("Closest is %d (%d), %d.  Error %d (%d)\n",
+	    minIndex, (minIndex + 1) * 5, pCalAry[minIndex], minError, (int)minError / 125);
+
+	/* The battery calibration register allows adjustment in steps of.25V.
+	 * Calculate how many 1.25V steps are necessary to adjust for the difference
+	 * between the target voltage and the closest measured 5V step. */
+	if (minError > 0)
+		cal = (minError + (125 / 2)) / 125;
+	else
+		cal = (minError - (125 / 2)) / 125;
+
+	DBG("Cal offset %d\n", cal);
+
+	DBG("Actual output should be %d\n", pCalAry[minIndex] + (cal * 125));
+
+	/* The battery calibration register can only adjust 3 steps in either
+	 * direction (3.75V).  If we need more than that (meaning an error of at
+	 * least 4.375), print a warning.
+	 * Since we have measurements at every 5V step, errors should never be much
+	 * worse than 2.5V.  This would only reasonably happen if the target voltage
+	 * is above or below the ranged of measured voltages (such as 0.5 or 155) */
+	if (cal < -3) {
+		printf("Output error may be large.  cal=%d, limited to -3", cal);
+		cal = -3;
+	}
+	if (cal > 3) {
+		printf("Output error may be large.  cal=%d, limited to 3", cal);
+		cal = 3;
+	}
+
+	/* The hex value for the switching regulator params register is the same as
+	 * the index into the calibration array. */
+	*pSwReg = minIndex;
+
+	switch (cal) {
+	case -3:
+		*pCalReg = 0x7;
+		break;
+	case -2:
+		*pCalReg = 0x6;
+		break;
+	case -1:
+		*pCalReg = 0x5;
+		break;
+	case 0:
+		*pCalReg = 0x0;
+		break;
+	case 1:
+		*pCalReg = 0x1;
+		break;
+	case 2:
+		*pCalReg = 0x2;
+		break;
+	case 3:
+		*pCalReg = 0x3;
+		break;
+	default:
+		*pCalReg = 0;
+		printf("This shouldn't be possible, cal=%d", cal);
+		break;
+	}
+}
+
+/*
+ * This function performs a series of writes and reads to verify the signal
+ * integrity of the MPI interface.
+ */
+static int MpiTest(VpDeviceIdType devId)
+{
+	uint8 writeData[20] = { 0 };
+	uint8 readData[20] = { 0 };
+	int x;
+	int y;
+	int i;
+
+	for (x = 0; x <= 0xFF; x++) {
+		for (i = 0; i < VP880_R_FILTER_LEN; i++)
+			writeData[i] = x;
+
+		VpMpiCmd(devId, EC_1, VP880_R_FILTER_WRT, VP880_R_FILTER_LEN, writeData);
+		VpMpiCmd(devId, EC_1, VP880_R_FILTER_RD, VP880_R_FILTER_LEN, readData);
+		for (i = 0; i < VP880_R_FILTER_LEN; i++) {
+			if (writeData[i] != readData[i]) {
+				printf("Failed MPI test 1-%d on devId 0x%X", x, devId);
+				return -1;
+			}
+		}
+	}
+
+	for (x = 0; x <= 0xFF; x++) {
+		y = x % 0x10;
+		for (i = 0; i < VP880_R_FILTER_LEN; i++) {
+			writeData[i] = y << 4;
+			y = (y + 1) % 0x10;
+			writeData[i] |= y;
+			y = (y + 1) % 0x10;
+		}
+		VpMpiCmd(devId, EC_1, VP880_R_FILTER_WRT, VP880_R_FILTER_LEN, writeData);
+		VpMpiCmd(devId, EC_1, VP880_R_FILTER_RD, VP880_R_FILTER_LEN, readData);
+		for (i = 0; i < VP880_R_FILTER_LEN; i++) {
+			if (writeData[i] != readData[i]) {
+				printf("Failed MPI test 2-%d on devId 0x%X", x, devId);
+				return -1;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/tools/voice/zarlink/user/arch_marvell/hbi_hal.h b/tools/voice/zarlink/user/arch_marvell/hbi_hal.h
new file mode 100644
index 0000000..acc68dc
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/hbi_hal.h
@@ -0,0 +1,65 @@
+/* hbi_hal.h
+ *
+ * This file defines the interface between the VoicePath API and the Hardware
+ * Abstraction Layer (HAL).  The types and functions declared in this file are
+ * platform-dependent.  The functions are defined in ve_hal.c.  Porting the
+ * VoicePath API to a new host processor consists of modifying the typedefs
+ * in this file, setting the HBI_PINCONFIG define below, and modifying the
+ * function implementations in vp_hal.c.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ */
+
+#ifndef HBI_HAL_H
+#define HBI_HAL_H
+
+#include "vp_api_types.h"
+
+/* Define the EXTERN macro, if necessary */
+#ifndef EXTERN
+  #ifdef __cplusplus
+    #define EXTERN extern "C"
+  #else
+    #define EXTERN extern
+  #endif /* __cplusplus */
+#endif /* EXTERN */
+
+/******************************************************************************
+ *                          PLATFORM-SPECIFIC OPTIONS                         *
+ ******************************************************************************/
+
+/* HBI configuration register */
+#define HBI_CFG_ENDLITTLE       0    /* 1=byte swapping for data words only */
+#define HBI_CFG_PWAIT_POLHI     0    /* 0=PWAIT pin active low, 1=PWAIT pin active high */
+#define HBI_CFG_PWAIT_EN        0    /* 0=PWAIT pin disabled, 1=PWAIT pin enabled */
+#define HBI_CFG_PWAIT_MODEOSD   0    /* 0=PWAIT pin TTL, 1=PWAIT pin open source/drain */
+#define HBI_CFG_INT_MODETTL     1    /* 0=INT pin open drain, 1=INT pin TTL */
+#define HBI_CFG_PINEA           0    /* 0=IO[2:0], 1=EA[10:8] */
+#define HBI_PINCONFIG   (HBI_CFG_ENDLITTLE | (HBI_CFG_PWAIT_POLHI << 1) | (HBI_CFG_PWAIT_EN << 2) | (HBI_CFG_PWAIT_MODEOSD << 3) | (HBI_CFG_INT_MODETTL << 4) | (HBI_CFG_PINEA << 5))
+
+#define HBI_CMD_CONFIGURE_INT	0xFD00
+
+#define DEFAULT_DEVICE_ID	0
+
+/******************************************************************************
+ *                         PLATFORM-SPECIFIC FUNCTIONS                        *
+ ******************************************************************************/
+
+/* See vp_hal.c for descriptions. */
+EXTERN bool VpHalHbiInit(VpDeviceIdType deviceId);
+EXTERN bool VpHalHbiCmd(VpDeviceIdType deviceId, uint16 cmd);
+
+EXTERN bool VpHalHbiWrite(VpDeviceIdType deviceId, uint16 cmd, uint8 numwords, uint16p data);
+EXTERN bool VpHalHbiRead(VpDeviceIdType deviceId, uint16 cmd, uint8 numwords, uint16p data);
+
+EXTERN bool VpHalHbiBootWr(VpDeviceIdType deviceId, uint8 numwords, VpImagePtrType data);
+
+/* Lowest Level HBI read / write action */
+EXTERN bool VpHalHbi(VpDeviceIdType deviceId, bool isWordData, bool isWrite, uint16p data);
+
+#endif /* HBI_HAL_H */
+
+
+
+
+
diff --git a/tools/voice/zarlink/user/arch_marvell/mpi_hal.h b/tools/voice/zarlink/user/arch_marvell/mpi_hal.h
new file mode 100644
index 0000000..f84c44b
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/mpi_hal.h
@@ -0,0 +1,20 @@
+/** \file mpi_hal.h
+ * mpi_hal.h
+ *
+ * Header file for the VP-API-II c files requiring MPI interface.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ */
+#ifndef MPI_UVB_HAL_H
+#define MPI_UVB_HAL_H
+#include "vp_api_types.h"
+
+EXTERN void
+VpMpiCmd(
+    VpDeviceIdType deviceId,
+    uint8 ecVal,
+    uint8 cmd,
+    uint8 cmdLen,
+    uint8 *dataPtr);
+#endif
+
diff --git a/tools/voice/zarlink/user/arch_marvell/sys_service.c b/tools/voice/zarlink/user/arch_marvell/sys_service.c
new file mode 100644
index 0000000..2285c91
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/sys_service.c
@@ -0,0 +1,485 @@
+/** \file sys_service.c
+ * sys_service.c
+ *
+ *  This file implements the required system services for the API-II using a
+ * Linux OS running on the UVB.  The user should replace the functions provided
+ * here with the equivalent based on their OS and hardware.
+ *
+ * Copyright (c) 2008, Zarlink Semiconductor, Inc.
+ */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>     /* exit() */
+#include <stdio.h>
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "sys_service.h"
+#include "vp_api_common.h"
+#define CLOCKID CLOCK_REALTIME
+#define SIG SIGRTMIN
+#define GET_DEV_STATUS(deviceId)	vpapi_dev_status[deviceId]
+#define GET_LINE_STATUS(lineId)		vpapi_line_status[lineId]
+#define MAX_EVENT_QUEUE_SIZE		256
+
+/* VE880 */
+#if defined(ZARLINK_SLIC_VE880)
+#define MAX_DEVICES			2
+#define MAX_LINES			4
+
+/* VE792 */
+#elif defined(ZARLINK_SLIC_VE792)
+#define MAX_DEVICES		4
+#define MAX_LINES		32
+#endif
+
+static const key_t key = 0xADEF;
+static const int flagMakeSem = S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH | IPC_CREAT | IPC_EXCL;
+static const int flagGetSem =  S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH;
+static const int NUM_SEMS = 1; /*VP_NUM_DEVICES * VP_NUM_CRITICAL_SEC_TYPES;*/
+static int critDepth = 0;
+
+/*
+ * VPD socket file descriptor: This is opened only once, the first time it is
+ * needed.  It is closed automatically by the OS when the process exits.  This
+ * policy is to avoid the overhead of reopening the socket each time a VpSys...()
+ * function is called.
+ */
+static int vpd_fd = -1;
+
+/* Enumurators */
+typedef struct {
+	unsigned char valid;		/* valid event */
+	VpEventType vp_event;
+} vpapi_event;
+
+timer_t 			timerid;
+pthread_mutex_t		vp_lock;
+unsigned int 		event_count;
+
+vpapi_event event_queue[MAX_EVENT_QUEUE_SIZE];
+volatile unsigned int next_event = 0, curr_event = 0;
+
+extern VpDevCtxType pDevCtx[MAX_DEVICES];
+extern unsigned char vpapi_dev_status[MAX_DEVICES];
+extern unsigned char vpapi_line_status[MAX_LINES];
+
+
+/*
+ * VpSysWait() function implementation is needed only for CSLAC devices
+ * (880, 790). For other devices this function could be commented.
+ */
+void
+VpSysWait(
+    uint8 time)  /* Time specified in increments of 125uS (e.g. 4 = 500uS) */
+{
+	usleep(125 * time);
+}
+void VpSysSemaphoreInit(int semaphoreId)
+{
+    int i;
+    int rc;
+    unsigned short initialValues[NUM_SEMS];
+    union semun semArg;
+    pid_t pid = 0;
+#ifdef SYS_SERVICE_DEBUG
+    pid = getpid();
+#endif
+    for (i=0; i < NUM_SEMS; i++) {
+        initialValues[i] = 1;
+    }
+    semArg.array = initialValues;
+
+    dprintf("%u:initing semaphore key=0x%X, id=0x%X...",pid, key, semaphoreId);
+    if ((rc = semctl(semaphoreId, 0, SETALL, semArg)) == -1) {
+#ifdef SYS_SERVICE_DEBUG
+        perror("semctl SETALL");
+#endif
+        exit(1);
+    }
+}
+
+/*
+ * VpSysEnterCritical(), VpSysExitCritical():
+ *
+ *  These functions allow for disabling interrupts while executing nonreentrant
+ * portions of VoicePath API code. Note that the following implementations of
+ * enter/exit critical section functions are simple implementations. These
+ * functions could be expanded (if required) to handle different critical
+ * section types differently.
+ *
+ * Params:
+ *  VpDeviceIdType deviceId: Device Id (chip select ID)
+ *  VpCriticalSecType: Critical section type
+ *
+ * Return:
+ *  Number of critical sections currently entered for the device.
+ */
+uint8
+VpSysEnterCritical(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType)
+{
+   int rc;
+    int semaphoreId;
+    struct sembuf semOp[1];
+    pid_t pid = 0;
+#ifdef SYS_SERVICE_DEBUG
+    pid = getpid();
+#endif
+    /* semOp[0].sem_num = deviceId*VP_NUM_CRITICAL_SEC_TYPES + criticalSecType;    */
+    semOp[0].sem_num = 0;
+    semOp[0].sem_op = -1;
+    semOp[0].sem_flg = SEM_UNDO;
+
+    critDepth++;
+    if (critDepth == 1) {
+        if ((semaphoreId = semget(key, NUM_SEMS, flagMakeSem)) >= 0) {
+             /* we just created the semaphore and it needs to be inited */
+            VpSysSemaphoreInit(semaphoreId);
+            dprintf("%u:Made new semaphore %d (hopefully sem_val=1)\n", pid, semaphoreId);
+         } else {
+             /* semaphore already exists, we just need to get an id */
+             if ((semaphoreId = semget(key, NUM_SEMS, flagGetSem)) < 0) {
+                /* something has gone sour */
+#ifdef SYS_SERVICE_DEBUG
+                perror("semget flagGetSem");
+#endif
+                exit(1);
+            }
+            /* dprintf("%u:Got existing semaphore %d\n",pid, semaphoreId); */
+        }
+
+        /* dprintf("%u:?v,d=%d\n",pid);    */
+        if ((rc = semop(semaphoreId, semOp, 1)) < 0) {
+#ifdef SYS_SERVICE_DEBUG
+            perror("semop -1");
+#endif
+            exit(1);
+        }
+        if (rc)    {
+            dprintf("semaphore error with deviceId=0x%X, criticalSecType=0x%X\n",
+                deviceId, criticalSecType);
+                return -1;
+        }
+    }
+    dprintf("%u:v,d=%d\n",pid, critDepth);
+
+    return critDepth;
+} /* VpSysEnterCritical() */
+
+uint8
+VpSysExitCritical(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType)
+{
+ int rc;
+    int semaphoreId;
+    struct sembuf semOp[1];
+    pid_t pid = 0;
+#ifdef SYS_SERVICE_DEBUG
+    pid = getpid();
+#endif
+    /* semOp[0].sem_num = deviceId*VP_NUM_CRITICAL_SEC_TYPES + criticalSecType;    */
+    semOp[0].sem_num = 0;
+    semOp[0].sem_op = 1;
+    semOp[0].sem_flg = SEM_UNDO;
+
+    critDepth--;
+    if (critDepth == 0) {
+        /* we can free the semaphore now */
+        if ((semaphoreId = semget(key, NUM_SEMS, flagGetSem)) < 0) {
+#ifdef SYS_SERVICE_DEBUG
+            perror("semget");
+#endif
+            exit(1);
+        }
+        /* dprintf("%u:Got existing semaphore %d\n",pid, semaphoreId); */
+        dprintf("%u:^,d=%d\n",pid,critDepth);
+        if ((rc = semop(semaphoreId, semOp, 1)) == -1) {
+#ifdef SYS_SERVICE_DEBUG
+            perror("semop +1");
+#endif
+            exit(1);
+        }
+
+        if (rc)    {
+            dprintf("semaphore error with deviceId=0x%X, criticalSecType=0x%X",
+                deviceId, criticalSecType);
+        }
+    } else {
+        dprintf("%u:^,d=%d\n",pid,critDepth);
+    }
+    /*dprintf("%u:VpSysExitCritical finished with critDepth=%d.\n",pid, critDepth);*/
+
+    return critDepth;
+} /* VpSysExitCritical() */
+
+/**
+ * VpSysDisableInt(), VpSysEnableInt(), and VpSysTestInt()
+ *
+ *  These functions are used by the CSLAC device family for interrupt driven
+ * polling modes. These are called by the API to detect when a non-masked
+ * device status has changed.  If using SIMPLE_POLL mode, these functions do not
+ * require implementation.
+ *
+ * Preconditions:
+ *  None. The implementation of these functions is architecture dependent.
+ *
+ * Postconditions:
+ *  VpSysDisableInt() - The interrupt associated with the deviceId passed is
+ * disabled.
+ *
+ * VpSysEnableInt() - The interrupt associated with the deviceId passed is
+ * enabled.
+ *
+ * VpSysTestInt() - The return value is TRUE if an interrupt occurred, otherwise
+ * return FALSE.
+ *
+ * These functions are needed only for CSLAC devices
+ * (880, 790). For other devices these functions could be commented.
+ *
+ */
+void
+VpSysDisableInt(
+    VpDeviceIdType deviceId)
+{
+}
+void
+VpSysEnableInt(
+    VpDeviceIdType deviceId)
+{
+}
+bool
+VpSysTestInt(
+    VpDeviceIdType deviceId)
+{
+    return FALSE;
+}
+/**
+ * VpSysDtmfDetEnable(), VpSysDtmfDetDisable()
+ *
+ *  These functions are used by the CSLAC device family for devices that do not
+ * internally detect DTMF. It is used for Caller ID type-II and is provided to
+ * enable external DTMF detection.
+ *
+ * Preconditions:
+ *  None. The implementation of these functions is application dependent.
+ *
+ * Postconditions:
+ *  VpSysDtmfDetEnable() - The device/channel resource for DTMF detection is
+ * enabled.
+ *
+ *  VpSysDtmfDetDisable() - The device/channel resource for DTMF detection is
+ * disabled.
+ *
+ * These functions are needed only for CSLAC devices
+ * (880, 790). For other devices these functions could be commented.
+ *
+ */
+void
+VpSysDtmfDetEnable(
+    VpDeviceIdType deviceId,
+    uint8 channelId)
+{
+}
+void
+VpSysDtmfDetDisable(
+    VpDeviceIdType deviceId,
+    uint8 channelId)
+{
+}
+/*
+ * The following functions VpSysTestHeapAcquire(),  VpSysTestHeapRelease()
+ * VpSysPcmCollectAndProcess() and are needed only for CSLAC devices
+ * (880). For other devices these functions could be commented. Please see
+ * the LineTest API documentation for function requirements.
+ */
+void *
+VpSysTestHeapAcquire(
+    uint8 *pHeapId)
+{
+    return VP_NULL;
+} /* VpSysTestHeapAcquire() */
+bool
+VpSysTestHeapRelease(
+    uint8 heapId)
+{
+    return TRUE;
+} /* VpSysTestHeapRelease() */
+void
+VpSysPcmCollectAndProcess(
+    void *pLineCtx,
+    VpDeviceIdType deviceId,
+    uint8 channelId,
+    uint8 startTimeslot,
+    uint16 operationTime,
+    uint16 settlingTime,
+    uint16 operationMask)
+{
+} /* VpSysPcmCollectAndProcess() */
+
+#ifdef ENABLE_DBG_TAG
+int
+VpSysDebugPrintf(
+    const char *format, ...)
+{
+    va_list ap;
+    static char buf[1024];
+    static uint16 indexBuf;
+    static bool beginLine = TRUE;
+    uint16 bufLen;
+    int retval;
+
+    if (beginLine == TRUE) {
+		printf("<DBG> ");
+		beginLine = FALSE;
+    }
+    /* print in a string to check if there's a \n */
+    va_start(ap, format);
+    retval = vsprintf(&buf[indexBuf], format, ap);
+    va_end(ap);
+
+    bufLen = strlen(&buf[indexBuf]);
+    if (buf[indexBuf + bufLen - 1] == '\n') {
+		buf[indexBuf + bufLen - 1] = ' ';
+		printf("%s</DBG>\n", buf);
+		indexBuf = 0;
+		beginLine = TRUE;
+    } else {
+		indexBuf += bufLen;
+
+		/* Just in case of a buffer overflow, not suppose to append */
+		if (indexBuf > 800) {
+			retval = printf("%s</DBG>\n", buf);
+			indexBuf = 0;
+			beginLine = TRUE;
+		}
+      }
+    return retval;
+}
+#endif /* ENABLE_DBG_TAG */
+
+void sys_service_init()
+{
+	pthread_mutex_init(&vp_lock, NULL);
+	/* Clear event queue */
+	memset(event_queue, 0, (MAX_EVENT_QUEUE_SIZE * sizeof(vpapi_event)));
+}
+
+static void sys_service_tick_handler()
+{
+	unsigned char deviceId;
+	unsigned long flags;
+	vpapi_event *pEvent;
+#if !defined(ZARLINK_SLIC_VE792)
+	bool eventStatus;
+#endif
+	sigset_t mask;
+
+
+	pthread_mutex_lock(&vp_lock);
+
+	for(deviceId = 0; deviceId < MAX_DEVICES; deviceId++) {
+
+		
+
+		if(GET_DEV_STATUS(deviceId) == 0)
+			continue;
+
+		/* Check for free resources */
+		if(event_count >= MAX_EVENT_QUEUE_SIZE)
+			goto timer_exit;
+
+
+
+#if !defined(ZARLINK_SLIC_VE792)
+		if(VP_STATUS_SUCCESS == VpApiTick(&pDevCtx[deviceId], &eventStatus)) {
+			if(eventStatus == TRUE) {
+#endif
+				pEvent = &event_queue[next_event];
+
+				while(VpGetEvent(&pDevCtx[deviceId], &pEvent->vp_event) == TRUE) {
+
+					if(pEvent->vp_event.status != VP_STATUS_SUCCESS) {
+						printf("%s: bad status(%d)\n", __func__, pEvent->vp_event.status);
+						break;
+					}
+
+					if(pEvent->vp_event.eventId == 0)  {
+						printf("%s: warning, empty event\n", __func__);
+						break;
+					}
+					next_event++;
+					if(next_event == MAX_EVENT_QUEUE_SIZE) {
+						next_event = 0;
+					}
+
+					event_count++;
+					if(pEvent->valid == 0) {
+						pEvent->valid = 1;
+					}
+					else {
+						printf("%s: error, event(%u) was overrided\n", __func__, next_event);
+						break;
+					}
+
+					pEvent = &event_queue[next_event];
+				}
+#if !defined(ZARLINK_SLIC_VE792)
+			}
+		}
+#endif
+	}
+
+	pthread_mutex_unlock(&vp_lock);
+
+	return;
+
+timer_exit:
+	return;
+}
+
+bool sys_service_get_event(VpDeviceIdType dev_id, VpEventType *event_p)
+{
+	bool		newEvent;
+
+	pthread_mutex_lock(&vp_lock);
+
+	if(event_count == 0) {
+		newEvent = FALSE;
+	}
+	else {
+		memcpy(event_p, &event_queue[curr_event].vp_event, sizeof(VpEventType));
+		event_queue[curr_event].valid = 0;
+		newEvent = TRUE;
+		event_count--;
+		curr_event++;
+		if(curr_event == MAX_EVENT_QUEUE_SIZE)
+			curr_event = 0;
+	}
+
+	pthread_mutex_unlock(&vp_lock);
+
+	return newEvent;
+}
+
+void *sys_service_timer_function (void *arg)
+{
+	while(1)
+	{
+		/* Do useful work */
+		sys_service_tick_handler();
+		/* Wait 10ms */
+		usleep(10000);
+	}
+	return NULL;
+}
+
diff --git a/tools/voice/zarlink/user/arch_marvell/sys_service.h b/tools/voice/zarlink/user/arch_marvell/sys_service.h
new file mode 100644
index 0000000..9394cbe
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/sys_service.h
@@ -0,0 +1,113 @@
+/*
+ * sys_service.h
+ *
+ *  This file is the header for all standard types used in the API code.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ */
+
+#ifndef SYS_SERVICE_H
+#define SYS_SERVICE_H
+
+#include "vp_api_types.h"
+#include <stdio.h>
+
+#define MAX_SLIC_RDWR_BUFF_SIZE		128
+/*-----------------8/10/2005 10:31AM----------------
+ * DEFINE THE FOLLOWING
+ * --------------------------------------------------*/
+#define VP_NUM_DEVICES 1
+/*-----------------8/10/2005 10:31AM----------------
+ * END DEFINE THE FOLLOWING
+ * --------------------------------------------------*/
+
+#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+	/* union semun is defined by including <sys/sem.h> */
+#else
+	/* according to X/OPEN we have to define it ourselves */
+union semun {
+	int val;
+	struct semid_ds *buf;
+	unsigned short int *array;
+    /* these fields unique to linux */
+    struct seminfo *__buf;  /* buffer for IPC_INFO */
+    void *__pad;
+	/* end unique to linux */
+};
+#endif
+
+typedef struct vpapi_init_device_params {
+	unsigned short dev_size;
+	unsigned short ac_size;
+	unsigned short dc_size;
+	unsigned short ring_size;
+	unsigned short fxo_ac_size;
+	unsigned short fxo_cfg_size;
+} vpapi_init_device_params_t;
+
+/* Critical section types */
+typedef enum {
+	VP_MPI_CRITICAL_SEC, 	/* MPI access critical code section */
+	VP_HBI_CRITICAL_SEC, 	/* HBI access critical code section */
+	VP_CODE_CRITICAL_SEC, 	/* Critical code section */
+	VP_NUM_CRITICAL_SEC_TYPES, /* The number of critical section types */
+    VP_CRITICAL_SEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCriticalSecType;
+EXTERN uint8
+VpSysEnterCritical(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+EXTERN uint8
+VpSysExitCritical(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+EXTERN void
+VpSysWait(
+    uint8 time);
+EXTERN void
+VpSysDisableInt(
+    VpDeviceIdType deviceId);
+EXTERN void
+VpSysEnableInt(
+    VpDeviceIdType deviceId);
+EXTERN bool
+VpSysTestInt(
+    VpDeviceIdType deviceId);
+EXTERN void
+VpSysDtmfDetEnable(
+    VpDeviceIdType deviceId,
+    uint8 channelId);
+EXTERN void
+VpSysDtmfDetDisable(
+    VpDeviceIdType deviceId,
+    uint8 channelId);
+
+EXTERN void *
+VpSysTestHeapAcquire(
+    uint8 *pHeapId);
+EXTERN bool
+VpSysTestHeapRelease(
+    uint8 heapId);
+EXTERN void
+VpSysPcmCollectAndProcess(
+    void *pLineCtx,
+    VpDeviceIdType deviceId,
+    uint8 channelId,
+    uint8 startTimeslot,
+    uint16 operationTime,
+    uint16 settlingTime,
+    uint16 operationMask);
+
+/* Enable the XML tag <DBG> debug output </DBG>  */
+/* #define ENABLE_DBG_TAG */
+
+#ifdef ENABLE_DBG_TAG
+    EXTERN int
+    VpSysDebugPrintf(
+		const char *format, ...);
+#else
+    #define VpSysDebugPrintf printf
+#endif /* ENABLE_DBG_TAG */
+
+#endif /* SYS_SERVICE_H */
+
diff --git a/tools/voice/zarlink/user/arch_marvell/vp_api_profile_type.h b/tools/voice/zarlink/user/arch_marvell/vp_api_profile_type.h
new file mode 100644
index 0000000..63a8563
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/vp_api_profile_type.h
@@ -0,0 +1,14 @@
+/** \file vp_api_profile_type.h
+ * vp_api_profile_type.h
+ *
+ * Header file for the VpProfileDataType typedef.  If using the API "apitypes",
+ * this file is automatically included.  Otherwise, this type is defined in the
+ * header file output from the Profile Wizard (app should include).
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ */
+#ifndef API_PROFILE_TYPE_H
+#define API_PROFILE_TYPE_H
+typedef unsigned char VpProfileDataType;
+#endif
+
diff --git a/tools/voice/zarlink/user/arch_marvell/vp_api_types.h b/tools/voice/zarlink/user/arch_marvell/vp_api_types.h
new file mode 100644
index 0000000..49324e3
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/vp_api_types.h
@@ -0,0 +1,112 @@
+/** \file vp_api_types.h
+ * vp_api_types.h
+ *
+ *  This file is the header for all standard types used in the API code.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ */
+#ifndef VP_API_TYPES_H
+#define VP_API_TYPES_H
+
+
+#include "vp_api_profile_type.h"
+
+/* For maximum that can be stored in an int - if file exists in library */
+//#include "limits.h"
+/* VpDeviceIdType defines the type for the deviceId in the VpDevCtxType type.
+ * This information is passed through the API to the HAL to communicate
+ * with a specific device.  The values assigned via VpMakeDeviceObject()
+ * are user defined and may be simple device indexing (0, 1, .. (n-1)):
+ * where n = device number in system
+ */
+typedef unsigned short VpDeviceIdType;
+/*
+ * The 'VpLineIdType'  defines a system wide Line identification that the system
+ * could use to identify a line. This type can be defined to contain anything
+ * that the customer chooses. It could be defined to contain just an index or
+ * a pointer. The system wide line identity could be set using the
+ * VpMapLineId() function for a given line. The VP-API returns this line id
+ * information when line specific events occur (along with the event).
+ */
+typedef unsigned short VpLineIdType;
+
+/*
+ * Macros for displaying VpDeviceIdType and VpLineIdType values.  If you have
+ * defined these (in vp_api_types.h) as something other than simple integers,
+ * you should modify the printf format strings as needed:
+ */
+#define VP_PRINT_DEVICE_ID(deviceId)  VpSysDebugPrintf(" (dev 0x%2.2X)", (int)deviceId)
+#define VP_PRINT_LINE_ID(lineId)      VpSysDebugPrintf(" (line %d)", (int)lineId)
+
+#ifndef NULL
+    #define NULL (0)
+#endif
+#define VP_NULL NULL
+#ifdef EXTERN
+  #undef EXTERN
+  #error EXTERN was redefined!
+#endif /* undef EXTERN */
+
+#ifdef __cplusplus
+  #define EXTERN extern "C"
+#else
+    #define EXTERN extern
+#endif /* __cplusplus */
+/********************* DECLARATIONS ***************************/
+/* Constants */
+#define FALSE   (0)     /* Boolean constant */
+#define TRUE    (1)     /* Boolean constant */
+#ifndef __cplusplus
+/* C++ language provides a boolean data type; So no need to define
+ * one more data type; Make use of it
+ * NOTE: The 'C' potions of the VP-API assume C++ "bool" to be of the
+ * same size as that of "char". Please make sure this assumption is correct.
+ */
+typedef unsigned char bool;
+#endif /* __cplusplus */
+/****************** typedefs ***********************************/
+/* These are the basic number types used */
+/* for uint8, uint16, uint32, int8, int16, int32, bool */
+typedef unsigned char   uchar;
+typedef unsigned char   uint8;
+typedef unsigned short  uint16;
+typedef unsigned long   uint32;
+typedef signed char    int8;
+typedef signed short int int16;
+typedef signed long  int32;
+typedef   uint8*  uint8p;
+typedef   uint16* uint16p;
+typedef   uint32* uint32p;
+typedef   int8*   int8p;
+typedef   int16*  int16p;
+typedef   int32*  int32p;
+typedef const VpProfileDataType * VpProfilePtrType;
+typedef uint8p VpImagePtrType;
+typedef uint16p VpVectorPtrType;
+typedef uint8 VpPktDataType;
+typedef VpPktDataType* VpPktDataPtrType;
+/* Some compilers optimize the size of enumeration data types based on
+ * the maximum data value assigned to the members of that data type.
+ * 'Standard C' requires enumeration data types to be of the same size
+ * as that of native 'int' implementation.
+ * The VP-API from a portability persepective adds a 'dummy' member to
+ * all enumeration data types that force the compilers to allocate the size
+ * of enumeration data types to be equal to that of native 'int'
+ * implementation */
+#define FORCE_STANDARD_C_ENUM_SIZE  (INT_MAX)
+
+/* Eliminate error messages that occur when comparing an enumeration constant
+   < 0 */
+#define FORCE_SIGNED_ENUM  (INT_MIN)
+
+
+/* Define any API specific basic data type ranges (that are necessary) */
+#define VP_INT16_MAX    ((short)(~0U>>1))
+#define VP_INT16_MIN    (-VP_INT16_MAX - 1)
+#define VP_INT32_MAX    ((long)(~0UL>>1))
+#define VP_INT32_MIN    (-VP_INT32_MAX - 1)
+
+#define INT_MAX		((int)(~0U>>1))
+#define INT_MIN		(-INT_MAX - 1)
+#endif /* VP_API_TYPES_H */
+
diff --git a/tools/voice/zarlink/user/arch_marvell/vp_hal.c b/tools/voice/zarlink/user/arch_marvell/vp_hal.c
new file mode 100644
index 0000000..4f05e7c
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/vp_hal.c
@@ -0,0 +1,406 @@
+/** \file vp_hal.c
+ * vp_hal.c
+ *
+ * This file contains the platform dependent code for the Hardware Abstraction
+ * Layer (HAL). This is example code only to be used by the customer to help
+ * clarify HAL requirements.
+ *
+ * Copyright (c) 2008, Zarlink Semiconductor, Inc.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include "mpi_hal.h"
+#include "hbi_hal.h"
+#include <sys/ioctl.h>
+#include <spi/spi_dev.h>
+#include "sys_service.h"
+
+/* Endianess macros.                                                        */
+#if !defined(CPU_BIG_ENDIAN)
+#define MV_16BIT_BE(X)  ((((X)&0xff)<<8) | (((X)&0xff00)>>8))
+#else
+#define MV_16BIT_BE(X)  (X)
+#endif
+
+#undef DEBUG
+#ifdef DEBUG
+
+#define DBG(fmt, arg...)	printf(KERN_INFO fmt, ##arg)
+			
+#else
+#define DBG(fmt, arg...)
+#endif
+
+/* MPI */
+#define READ_COMMAND			1
+#define CSLAC_EC_REG_RD			0x4B   /* Same for all CSLAC devices */
+#define CSLAC_EC_REG_WRT		0x4A   /* Same for all CSLAC devices */
+#define MPI_MAX_CMD_LEN			255
+
+/* HBI */
+#define HBI_CMD_BYTES			2
+#define HBI_DATA_BYTES(numWords)	((numWords + 1) * 2)
+#define HBI_MAX_DATA_LEN		256
+
+uint16 readBuff[HBI_MAX_DATA_LEN];
+uint16 writeBuff[HBI_MAX_DATA_LEN];
+
+/* Locals */
+static char dev_name[] = "/dev/spi";
+static int dev_fd = 0;
+
+int spi_open_device(void)
+{
+	int fdflags;
+
+	/* open the device */
+	dev_fd = open(dev_name, O_RDWR); 
+	if (dev_fd <= 0) {
+		printf("Cannot open %s device\n", dev_name);
+		return -1;
+	}
+
+	/* set some flags */
+	fdflags = fcntl(dev_fd, F_GETFL, 0);
+	fdflags |= O_NONBLOCK;
+	fcntl(dev_fd, F_SETFL, fdflags);
+
+	return 0;
+}
+
+int spi_close_device(void)
+{
+	if(dev_fd > 0)
+		close(dev_fd);
+
+	return 0;	
+}
+
+/**
+ * VpHalHbiInit(): Configures the HBI bus and glue logic (if any)
+ *
+ * This function performs any tasks necessary to prepare the system for
+ * communicating through the HBI, including writing the HBI configuration
+ * register.  The HBI read and write functions should work after HbiHalInit()
+ * is successfully executed. HbiHalInit() should be well-behaved even if called
+ * more than once between system resets. HbiHalInit() is called from
+ * VpBootLoad() since VpBootLoad() is normally the first VoicePath function
+ * that the host application will call.
+ *
+ * This function is called by VpBootLoad() before sending the VCP firmware
+ * image through the HBI.
+ *
+ * Params:
+ *  uint8 deviceId: Device Id (chip select ID)
+ *
+ * Returns:
+ *  This function returns FALSE if some error occurred during HBI initialization
+ *  or TRUE otherwise.
+ */
+uint8 VpHalHbiInit(
+    VpDeviceIdType deviceId)
+{
+	return TRUE;
+} /* VpHalHbiInit() */
+
+/**
+ * VpHalHbiCmd(): Sends a command word over the HBI, with no data words.
+ *
+ *  Accepts a uint16 HBI command which is little-endian or big-endian,
+ * depending on the host architecture.  Command words on the HBI bus are always
+ * big-endian. This function is responsible for byte-swapping if required.
+ *
+ * Params:
+ * uint8 deviceId: Device Id (chip select ID)
+ * uint16 cmd: the command word to send
+ *
+ * Returns:
+ *   TRUE on success, FALSE on failure
+ */
+uint8 VpHalHbiCmd(
+    VpDeviceIdType deviceId,
+    uint16 cmd)
+{
+	uint16 cmdSwapped = MV_16BIT_BE(cmd);
+	SpiModRWObjType spiData;
+
+    /* Start critical section for MPI access */
+    VpSysEnterCritical(deviceId, VP_HBI_CRITICAL_SEC);
+
+	spi_open_device();
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	spiData.lineId = deviceId;
+	spiData.pCmdBuff = (uint8p)&cmdSwapped;
+	spiData.cmdSize = HBI_CMD_BYTES;
+	spiData.pDataBuff = NULL;
+	spiData.dataSize = 0;
+
+	DBG("%s: WRITE - cmdSize=%d, dataSize=%d\n", __func__, cmdSize, cmdLen);
+	if (ioctl(dev_fd, SPI_MOD_IOX_REG_WRITE, &spiData) < 0) {
+		printf("ioctl(SPI_MOD_IOX_REG_WRITE) failed\n");
+		return;
+	}
+
+	spi_close_device();
+
+	VpSysExitCritical(deviceId, VP_HBI_CRITICAL_SEC);
+/*
+	DBG("%s: WRITE(cmd-0x%x)\n", __func__, cmd);
+	mvSysTdmSpiWrite(deviceId, (uint8p)&cmdSwapped, HBI_CMD_BYTES, NULL, 0);
+*/
+	return TRUE;
+} /* VpHalHbiCmd() */
+
+/**
+ * VpHalHbiWrite(): Sends a command word and up to 256 data words over the HBI.
+ *
+ *  Accepts a uint16 HBI command which is little-endian or big-endian, depending
+ * on the host architecture.  Command words on the HBI bus are always big-
+ * endian.  This function is responsible for byte-swapping the command word, if
+ * required.
+ *
+ *  Accepts an array of uint16 data words.  No byte-swapping is necessary on
+ * data words in this function.  Instead, the HBI bus can be configured in
+ * VpHalHbiInit() to match the endianness of the host platform.
+ *
+ * Params:
+ *   uint8 deviceId: Device Id (chip select ID)
+ *   uint16 cmd: the command word to send
+ *   uint8 numwords: the number of data words to send, minus 1
+ *   uint16p data: the data itself; use data = (uint16p)0 to send
+ *      zeroes for all data words
+ *
+ * Returns:
+ *   TRUE on success, FALSE on failure
+ */
+uint8 VpHalHbiWrite(
+    VpDeviceIdType deviceId,
+    uint16 cmd,
+    uint8 numwords,
+    uint16p data)
+{
+	uint8 i;
+	uint16 cmdSwapped = MV_16BIT_BE(cmd);
+	uint16p pWriteBuff = &writeBuff[0];
+	SpiModRWObjType spiData;
+
+	if ((numwords + 1) > HBI_MAX_DATA_LEN) {
+		printf("%s: Error, HBI data length too big(%u)\n", __func__, (numwords + 1));
+		return FALSE;
+	}
+
+	for (i = 0; i < (numwords + 1); i++)
+		pWriteBuff[i] = MV_16BIT_BE(data[i]);
+
+ /* Start critical section for MPI access */
+	VpSysEnterCritical(deviceId, VP_HBI_CRITICAL_SEC);
+
+	spi_open_device();
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	spiData.lineId = deviceId;
+	spiData.pCmdBuff = (uint8p)&cmdSwapped;
+	spiData.cmdSize = HBI_CMD_BYTES;
+	spiData.pDataBuff = (uint8p)pWriteBuff;
+	spiData.dataSize = HBI_DATA_BYTES(numwords);
+
+	DBG("%s: WRITE - cmdSize=%d, dataSize=%d\n", __func__, cmdSize, cmdLen);
+	if (ioctl(dev_fd, SPI_MOD_IOX_REG_WRITE, &spiData) < 0) {
+		printf("ioctl(SPI_MOD_IOX_REG_WRITE) failed\n");
+		return;
+	}
+
+	spi_close_device();
+
+	VpSysExitCritical(deviceId, VP_HBI_CRITICAL_SEC);
+
+/*
+	DBG("%s: WRITE(cmd-0x%x), (size-%d bytes)\n", __func__, cmd, HBI_DATA_BYTES(numwords));
+	mvSysTdmSpiWrite(deviceId, (uint8p)&cmdSwapped, HBI_CMD_BYTES, (uint8p)pWriteBuff, HBI_DATA_BYTES(numwords));
+*/
+	return TRUE;
+} /* VpHalHbiWrite() */
+
+/**
+ * VpHalHbiRead(): Sends a command, and receives up to 256 data words over the
+ * HBI.
+ *
+ *  Accepts a uint16 HBI command which is little-endian or big-endian, depending
+ * on the host architecture.  Command words on the HBI bus are always big-
+ * endian.  This function is responsible for byte-swapping the command word, if
+ * required.
+ *
+ * Retrieves an array of uint16 data words.  No byte-swapping is necessary on
+ * data words in this function.  Instead, the HBI bus can be configured in
+ * VpHalHbiInit() to match the endianness of the host platform.
+ *
+ * Params:
+ *   uint8 deviceId: Device Id (chip select ID)
+ *   uint8 numwords: the number of words to receive, minus 1
+ *   uint16p data: where to put them
+ *
+ * Returns:
+ *   TRUE on success, FALSE on failure
+ */
+uint8 VpHalHbiRead(
+    VpDeviceIdType deviceId,
+    uint16 cmd,
+    uint8 numwords,
+    uint16p data)
+{
+	uint8 i;
+	uint16 cmdSwapped = MV_16BIT_BE(cmd);
+	uint16p pReadBuff = &readBuff[0];
+	SpiModRWObjType spiData;
+
+	if ((numwords + 1) > HBI_MAX_DATA_LEN) {
+		printf("%s: Error, HBI data length too big(%u)\n", __func__, (numwords + 1));
+		return FALSE;
+	}
+
+/* Start critical section for MPI access */
+    VpSysEnterCritical(deviceId, VP_HBI_CRITICAL_SEC);
+
+	spi_open_device();
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	spiData.lineId = deviceId;
+	spiData.pCmdBuff = (uint8p)&cmdSwapped;
+	spiData.cmdSize = HBI_CMD_BYTES;
+	spiData.pDataBuff = (uint8p)pReadBuff;
+	spiData.dataSize = HBI_DATA_BYTES(numwords);
+
+	DBG("%s: READ - cmdSize=%d, dataSize=%d\n", __func__, cmdSize, cmdLen);
+	if (ioctl(dev_fd, SPI_MOD_IOX_REG_READ, &spiData) < 0) {
+		printf("ioctl(SPI_MOD_IOX_REG_READ) failed\n");
+		return;
+	}
+
+	spi_close_device();
+
+	VpSysExitCritical(deviceId, VP_HBI_CRITICAL_SEC);
+
+/*
+	DBG("%s: READ(cmd-0x%x), (size-%d bytes)\n", __func__, cmd, HBI_DATA_BYTES(numwords));
+	mvSysTdmSpiRead(deviceId, (uint8p)&cmdSwapped, HBI_CMD_BYTES, (uint8p)pReadBuff, HBI_DATA_BYTES(numwords));
+*/
+	for (i = 0; i < (numwords + 1); i++)
+		data[i] = MV_16BIT_BE(pReadBuff[i]);
+
+	return TRUE;
+
+} /* VpHalHbiRead() */
+
+
+/*****************************************************************************
+ * HAL functions for CSLAC devices. Not necessary for VCP
+ ****************************************************************************/
+/**
+ * VpMpiCmd()
+ *  This function executes a Device MPI command through the MPI port. It
+ * executes both read and write commands. The read or write operation is
+ * determined by the "cmd" argument (odd = read, even = write). The caller must
+ * ensure that the data array is large enough to hold the data being collected.
+ * Because this command used hardware resources, this procedure is not
+ * re-entrant.
+ *
+ * Note: For API-II to support multi-threading, this function has to write to
+ * the EC register of the device to set the line being controlled, in addition
+ * to the command being passed. The EC register write/read command is the same
+ * for every CSLAC device and added to this function. The only exception is
+ * if the calling function is accessing the EC register (read), in which case
+ * the EC write cannot occur.
+ *
+ * This example assumes the implementation of two byte level commands:
+ *
+ *    MpiReadByte(VpDeviceIdType deviceId, uint8 *data);
+ *    MpiWriteByte(VpDeviceIdType deviceId, uint8 data);
+ *
+ * Preconditions:
+ *  The device must be initialized.
+ *
+ * Postconditions:
+ *   The data pointed to by dataPtr, using the command "cmd", with length
+ * "cmdLen" has been sent to the MPI bus via the chip select associated with
+ * deviceId.
+ */
+void
+VpMpiCmd(
+    VpDeviceIdType deviceId,    /* Chip select */
+    uint8 ecVal,        	/* Value to write to the EC register */
+    uint8 cmd,          	/* Command number */
+    uint8 cmdLen,       	/* Number of bytes used by command (cmd) */
+    uint8 *dataPtr)     	/* Pointer to the data location */
+{
+
+    uint8 cmdBuff[4];
+    uint8 cmdSize = 0;
+    uint8 isRead = (cmd & READ_COMMAND);
+
+	SpiModRWObjType data;
+
+    /* Start critical section for MPI access */
+    VpSysEnterCritical(deviceId, VP_MPI_CRITICAL_SEC);
+
+     if (cmdLen > MPI_MAX_CMD_LEN)
+		printf("Error, MPI data length too big(%u)\n", cmdLen);
+
+
+    /* If a EC read is being preformed don't set the EC register */
+    if (CSLAC_EC_REG_RD != cmd) {
+	/* Write the EC register value passed to the device */
+	cmdBuff[cmdSize++] = CSLAC_EC_REG_WRT;
+	cmdBuff[cmdSize++] = ecVal;
+    }
+
+    /* Write the command byte to MPI. */
+    cmdBuff[cmdSize++] = cmd;
+
+	spi_open_device();
+
+	if (dev_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	data.lineId = deviceId;
+	data.pCmdBuff = cmdBuff;
+	data.cmdSize = cmdSize;
+	data.pDataBuff = dataPtr;
+	data.dataSize = cmdLen;
+
+    if (isRead) {
+		DBG("%s: READ - cmdSize=%d, dataSize=%d\n", __func__, cmdSize, cmdLen);
+		if (ioctl(dev_fd, SPI_MOD_IOX_REG_READ, &data) < 0) {
+			printf("ioctl(SPI_MOD_IOX_REG_READ) failed\n");
+			return;
+		}
+    } else {
+		DBG("%s: WRITE - cmdSize=%d, dataSize=%d\n", __func__, cmdSize, cmdLen);
+		if (ioctl(dev_fd, SPI_MOD_IOX_REG_WRITE, &data) < 0) {
+			printf("ioctl(SPI_MOD_IOX_REG_WRITE) failed\n");
+			return;
+		}
+    }
+
+	spi_close_device();
+
+	VpSysExitCritical(deviceId, VP_MPI_CRITICAL_SEC);
+
+    return;
+} /* End VpMpiCmd */
diff --git a/tools/voice/zarlink/user/arch_marvell/vp_hal.h b/tools/voice/zarlink/user/arch_marvell/vp_hal.h
new file mode 100644
index 0000000..27b3b24
--- /dev/null
+++ b/tools/voice/zarlink/user/arch_marvell/vp_hal.h
@@ -0,0 +1,19 @@
+/* vp_hal.h
+ *
+ * This file defines the interface between the VoicePath API and the Hardware
+ * Abstraction Layer (HAL).  The types and functions declared in this file are
+ * platform-dependent.  The functions are defined in ve_hal.c.  Porting the
+ * VoicePath API to a new host processor consists of modifying the typedefs
+ * in this file, setting the HBI_PINCONFIG define below, and modifying the
+ * function implementations in vp_hal.c.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ */
+#ifndef _VP_HAL_H
+#define _VP_HAL_H
+#include "vp_api_types.h"
+#include "hbi_hal.h"
+#include "mpi_hal.h"
+#include "sys_service.h"
+#endif /* _VP_HAL_H */
+
diff --git a/tools/voice/zarlink/user/libs/zarlink_792.lib b/tools/voice/zarlink/user/libs/zarlink_792.lib
new file mode 100755
index 0000000..44c7169
--- /dev/null
+++ b/tools/voice/zarlink/user/libs/zarlink_792.lib
Binary files differ
diff --git a/tools/voice/zarlink/user/libs/zarlink_880.lib b/tools/voice/zarlink/user/libs/zarlink_880.lib
new file mode 100755
index 0000000..d398102
--- /dev/null
+++ b/tools/voice/zarlink/user/libs/zarlink_880.lib
Binary files differ
diff --git a/tools/voice/zarlink/user/mv_voice_tool.c b/tools/voice/zarlink/user/mv_voice_tool.c
new file mode 100644
index 0000000..e266400
--- /dev/null
+++ b/tools/voice/zarlink/user/mv_voice_tool.c
@@ -0,0 +1,1511 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms.  Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED.  The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    *   Redistributions of source code must retain the above copyright notice,
+	    this list of conditions and the following disclaimer.
+
+    *   Redistributions in binary form must reproduce the above copyright
+	notice, this list of conditions and the following disclaimer in the
+	documentation and/or other materials provided with the distribution.
+
+    *   Neither the name of Marvell nor the names of its contributors may be
+	used to endorse or promote products derived from this software without
+	specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+#include <sched.h>
+#include "sys_service.h"
+#include "tdm/test/tdm_dev.h"
+#include "vp_api_common.h"
+#if defined(ZARLINK_SLIC_VE880)
+#include "vp880_api.h"
+#include "profile_88266.h"
+#elif defined(ZARLINK_SLIC_VE792)
+#include "vp792_api.h"
+#include "profile_79238.h"
+#endif
+
+
+/* Defines */
+#define GET_DEV_STATUS(deviceId)	vpapi_dev_status[deviceId]
+#define GET_LINE_STATUS(lineId)		vpapi_line_status[lineId]
+#define REGISTER_DEVICE(deviceId)	\
+	vpapi_dev_status[deviceId] = 1;
+#define REGISTER_LINE(lineId)		\
+	vpapi_line_status[lineId] = 1;
+
+#define MAX_PROFILE_SIZE		128
+#define GET_DEVICE(lineId)		(lineId/MAX_LINES_PER_DEVICE)
+#define GET_LINE(lineId)		(lineId % MAX_LINES_PER_DEVICE)
+#define MAX_EVENT_QUEUE_SIZE		256
+#define VPAPI_TICK_TIMER_PERIOD		1
+#define VPAPI_MOD_NAME                  "vpapi"
+
+
+#define TOOL_PREFIX	">> "
+#define TIMEOUT		11000 /* usec */
+/* Line calibration increases init time significantly */
+#define LINE_CALIBRATION_SUPPORT
+
+/* Defines */
+#define N_A			0
+#define ON_HOOK			0
+#define OFF_HOOK		1
+#define CH_BUFF_SIZE		(80 * pcm_bytes)
+#define BUFF_ADDR(buff, line)	((unsigned char*)buff + (line*80*pcm_bytes))
+#define TIMER_THREAD_PRIORITY	99
+
+/* VE880 */
+#if defined(ZARLINK_SLIC_VE880)
+
+#define MAX_DEVICES			2
+#define MAX_LINES			4
+#define MAX_LINES_PER_DEVICE		2
+#define MAX_DEVICE_LINES	2
+#define VP_DEV_SERIES		VP_DEV_880_SERIES
+#define DEV_PROFILE		ABS_VBL_FLYBACK
+#define DC_COEFF		DC_22MA_CC
+#define AC_COEFF		AC_FXS_RF14_DEF
+#define WB_AC_COEFF		AC_FXS_RF14_WB_US
+#define RING_PROFILE		RING_DEF
+
+VpDevCtxType pDevCtx[MAX_DEVICES];
+VpLineCtxType pLineCtx[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+Vp880DeviceObjectType pDevObj[MAX_DEVICES];
+Vp880LineObjectType pLineObj[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+
+/* VE792 */
+#elif defined(ZARLINK_SLIC_VE792)
+#define TBD 0
+#define MAX_DEVICES			4
+#define MAX_LINES			32
+#define MAX_LINES_PER_DEVICE		8
+#define MAX_DEVICE_LINES	8
+#define VP_DEV_SERIES		VP_DEV_792_SERIES
+#define DEV_PROFILE		VE792_DEV_PROFILE
+#define DC_COEFF		VE792_DC_COEFF
+#define AC_COEFF		VE792_AC_COEFF_600
+#define WB_AC_COEFF		TBD /* TBD: AC profile for WideBand support */
+#define RING_PROFILE		RING_20HZ_SINE
+
+/* Power-supply related parameters */
+#define VBH			-50
+#define VBL			-25
+#define VBP			 50
+
+VpDevCtxType pDevCtx[MAX_DEVICES];
+VpLineCtxType pLineCtx[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+Vp792DeviceObjectType pDevObj[MAX_DEVICES];
+Vp792LineObjectType pLineObj[MAX_DEVICES][MAX_LINES_PER_DEVICE];
+
+extern int BattOn(int vbhSetting, int vblSetting, int vbpSetting);
+extern int BattOff(void);
+#endif
+
+/* Extern */
+extern int dev_profile_size;
+extern int dc_profile_size;
+extern int ac_profile_size;
+extern int ring_profile_size;
+extern pthread_mutex_t		vp_lock;
+/* GLobals */
+unsigned char time_slot_table[MAX_LINES];
+unsigned char vpapi_dev_status[MAX_DEVICES];
+unsigned char vpapi_line_status[MAX_LINES];
+VpOptionCodecType codec = VP_OPTION_ALAW;
+
+/* Static */
+static unsigned short total_lines = 0;
+static unsigned short total_devs = 0;
+static unsigned char pcm_bytes = 0;
+static unsigned char cal_devs = 0;
+#ifdef LINE_CALIBRATION_SUPPORT
+static unsigned short cal_lines = 0;
+#endif
+static unsigned char hook_state[MAX_LINES];
+static char dev_name[] = "/dev/tdm";
+static int buff_size = 0;
+static unsigned char aud_buf[2][320 * MAX_LINES];
+static unsigned short f1Mem = 0;
+static unsigned short f2Mem = 0;
+static int offhook_count = 0;
+static unsigned int event_count = 0;
+static int tdm_fd = 0;
+static unsigned char data_buff[MAX_SLIC_RDWR_BUFF_SIZE];
+static int slic_init = 0;
+
+/* sin table, 256 points */
+static short sinTbl[] = {0,402,804,1205,1606,2005,2404,2801,3196,3590,3981,4370,4756,
+5139,5519,5896,6270,6639,7005,7366,7723,8075,8423,8765,9102,9433,9759,10079,10393,
+10701,11002,11297,11585,11865,12139,12405,12664,12915,13159,13394,13622,13841,14052,
+14255,14449,14634,14810,14977,15136,15285,15425,15556,15678,15790,15892,15985,16068,
+16142,16206,16260,16304,16339,16363,16378,16383,16378,16363,16339,16304,16260,16206,
+16142,16068,15985,15892,15790,15678,15556,15425,15285,15136,14977,14810,14634,14449,
+14255,14052,13841,13622,13394,13159,12915,12664,12405,12139,11865,11585,11297,11002,
+10701,10393,10079,9759,9433,9102,8765,8423,8075,7723,7366,7005,6639,6270,5896,5519,
+5139,4756,4370,3981,3590,3196,2801,2404,2005,1606,1205,804,402,0,-402,-804,-1205,-1606,
+-2005,-2404,-2801,-3196,-3590,-3981,-4370,-4756,-5139,-5519,-5896,-6270,-6639,-7005,
+-7366,-7723,-8075,-8423,-8765,-9102,-9433,-9759,-10079,-10393,-10701,-11002,-11297,
+-11585,-11865,-12139,-12405,-12664,-12915,-13159,-13394,-13622,-13841,-14052,-14255,
+-14449,-14634,-14810,-14977,-15136,-15285,-15425,-15556,-15678,-15790,-15892,-15985,
+-16068,-16142,-16206,-16260,-16304,-16339,-16363,-16378,-16383,-16378,-16363,-16339,
+-16304,-16260,-16206,-16142,-16068,-15985,-15892,-15790,-15678,-15556,-15425,-15285,
+-15136,-14977,-14810,-14634,-14449,-14255,-14052,-13841,-13622,-13394,-13159,-12915,
+-12664,-12405,-12139,-11865,-11585,-11297,-11002,-10701,-10393,-10079,-9759,-9433,-9102,
+-8765,-8423,-8075,-7723,-7366,-7005,-6639,-6270,-5896,-5519,-5139,-4756,-4370,-3981,
+-3590,-3196,-2801,-2404,-2005,-1606,-1205,-804,-402,0};
+
+/* Static APIs */
+static void vpapi_dev_init(VpDeviceIdType dev_id);
+static inline void wait_for_vpapi_event(void);
+static int vpapi_init(void);
+static void vpapi_init_done(void);
+static void vpapi_release(void);
+static void release(int signum);
+static void sw_tone_test(int tdm_fd, unsigned char line_id);
+static void sw_loopback_two_phones_test(int tdm_fd, unsigned char line0, unsigned char line1);
+static void sw_loopback_multi_phones_test(int tdm_fd, unsigned char start_line, unsigned char end_line);
+static void gen_tone(unsigned short freq, unsigned char line_id, unsigned char* tx_buff);
+static void sw_loopback(int tdm_fd, unsigned char line_id);
+static void slic_digital_loopback(int tdm_fd, unsigned long int iterations);
+static void channel_balancing_test(int tdm_fd, unsigned long int iterations);
+static inline int slic_dl_data_compare(int offset);
+static VpStatusType vpapi_init_device(VpDeviceIdType dev_id, VpProfilePtrType dev_profile_ptr,
+				VpProfilePtrType ac_profile_ptr, VpProfilePtrType dc_profile_ptr,
+				VpProfilePtrType ring_profile_ptr, VpProfilePtrType fxo_ac_profile_ptr,
+				VpProfilePtrType fxo_cfg_profile_ptr, vpapi_init_device_params_t *params_ptr);
+void *sys_service_timer_function(void *arg);
+#if defined(MV_TDM_USE_DCO)
+static void set_tdm_clk_config(void);
+static int get_tdm_clk_correction(void);
+static void set_tdm_clk_correction(int correction);
+#endif
+
+int main(void)
+{
+	pthread_t timer_thread;
+  	pthread_attr_t attr;
+    struct sched_param parm;
+	sigset_t alarm_sig;
+	int ret = 0, cmd = 0, val = 0, tdm_init = 0;
+	int proc_fd, fdflags, cmd_len, i;
+	char str[32];
+	unsigned char ec_val[] = {0x1, 0x2};
+	unsigned char line0_id, line1_id;
+	tdm_dev_params_t tdm_params;
+	unsigned long int iterations;
+  	timer_t 		TimerID;	
+	event_count = 0;
+	slic_init = 0;
+	total_devs = 0;
+	total_lines = 0;
+
+	sys_service_init();
+
+	memset(vpapi_dev_status, 0, MAX_DEVICES);
+	memset(vpapi_line_status, 0, MAX_LINES);
+
+	/* Reset event counter */
+	event_count = 0;
+
+	/* open tdm device */
+	tdm_fd = open(dev_name, O_RDWR); 
+	if (tdm_fd <= 0) {
+		printf("%s Cannot open %s device\n", TOOL_PREFIX, dev_name);
+		return 1;
+	}
+
+	/* set some flags */
+	fdflags = fcntl(tdm_fd, F_GETFL, 0);
+	fdflags |= O_NONBLOCK;
+	fcntl(tdm_fd, F_SETFL, fdflags);
+
+	printf("\n%s Please enter total lines number: ", TOOL_PREFIX);
+	gets(str);
+	total_lines = atoi(str);
+	
+	printf("%s Please enter PCM sample size(1/2/4): ",TOOL_PREFIX);
+	gets(str);
+	pcm_bytes = atoi(str);
+
+	/* Calculate total lines buffer size */
+	buff_size = (80 * pcm_bytes * total_lines);
+
+	/* Fill TDM info */
+	tdm_params.pcm_format = pcm_bytes;
+	tdm_params.total_lines = total_lines;
+
+	total_devs = (total_lines/MAX_DEVICE_LINES);
+	if((total_lines % MAX_DEVICE_LINES))
+		total_devs++;
+
+	/* Init timer thread */
+	pthread_attr_init(&attr);
+	parm.sched_priority=TIMER_THREAD_PRIORITY;
+	pthread_attr_setschedpolicy(&attr,SCHED_FIFO);
+	pthread_attr_setschedparam(&attr,&parm);
+	pthread_create (&timer_thread, &attr, sys_service_timer_function, NULL);
+
+	/* Handle termination gracefully */
+	if (signal (SIGINT, release) == SIG_IGN)
+		signal (SIGINT, SIG_IGN);
+
+	/* Issue main menu */
+	while(1) {
+
+		printf("\n  Marvell Voice Tool:\n");
+		printf("  0. Read from SLIC register(VE880 only)\n");
+		printf("  1. Write to SLIC register(VE880 only)\n");
+		printf("  2. Start ring\n");
+		printf("  3. Stop ring\n");
+		printf("  4. Start SW tone\n");
+		printf("  5. Self echo on local phone\n");
+		printf("  6. Loopback two local phones\n");
+		printf("  7. Multiple local phone pairs loopback\n");
+		printf("  8. Digital Loopback(incremental pattern)\n");
+		printf("  9. Channel balancing\n");
+		printf("  a. Start Phone devices\n");
+		printf("  b. Stop Phone devices\n");
+#if defined(MV_TDM_USE_DCO)
+		printf("  c. Config TDM PCLK\n");
+		printf("  d. Get current TDM PCLK frequency correction (DCO)\n");
+		printf("  e. Set TDM PCLK frequency correction (DCO)\n");
+#endif
+		printf("  q. Quit\n");
+		printf("\n%s Please select option: ", TOOL_PREFIX);
+
+		/* Clear write buffer */
+		memset(aud_buf[1], 0, buff_size);
+		gets(str);
+
+		switch(str[0])
+		{
+			case '0':
+#if defined(ZARLINK_SLIC_VE880)
+				printf("%s Enter line id: ",TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter SLIC register command(decimal): ",TOOL_PREFIX);
+				gets(str);
+				cmd = atoi(str);
+				printf("%s Enter SLIC register command size: ",TOOL_PREFIX);
+				gets(str);
+				cmd_len = atoi(str);
+				VpMpiCmd(GET_DEVICE(line0_id), ec_val[GET_LINE(line0_id)], (cmd | 1), cmd_len, data_buff);
+				
+				printf("\n%s Sent command 0x%x to line(%d)\n", TOOL_PREFIX, cmd, line0_id);
+				printf("%s Return value: ",TOOL_PREFIX);
+				for(i = 0; i < cmd_len; i++)
+					printf("0x%x ", data_buff[i]);
+				printf("\n");
+#else
+				printf("%s operation not supported\n",TOOL_PREFIX);
+#endif
+				break;
+
+			case '1':
+#if defined(ZARLINK_SLIC_VE880)
+				printf("%s Enter line id: ",TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter SLIC register command(decimal): ",TOOL_PREFIX);
+				gets(str);
+				cmd = atoi(str);
+				printf("%s Enter SLIC register command size: ",TOOL_PREFIX);
+				gets(str);
+				cmd_len = atoi(str);
+				printf("%s Enter data(press Enter after each byte): ",TOOL_PREFIX);
+				for(i = 0; i < cmd_len; i++) {
+					gets(str);
+					data_buff[i] = atoi(str);
+				}
+				VpMpiCmd(GET_DEVICE(line0_id), ec_val[GET_LINE(line0_id)], cmd, cmd_len, data_buff);
+				printf("\n%s Sent command 0x%x to line(%d)\n", TOOL_PREFIX, cmd, line0_id);
+#else
+				printf("%s operation not supported\n",TOOL_PREFIX);
+#endif
+				break;
+
+		
+			case '2':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("Start ringing on line %d\n", line0_id);
+				VpSetLineState(&pLineCtx[GET_DEVICE(line0_id)][line0_id], VP_LINE_RINGING);
+				break;
+
+			case '3':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("Stop ringing on line %d\n", line0_id);
+				VpSetLineState(&pLineCtx[GET_DEVICE(line0_id)][line0_id], VP_LINE_STANDBY);
+				break;
+			
+			case '4':
+				if(pcm_bytes < 2) {
+					printf("Test is supported for linear mode only - try again\n");
+					break;
+				}
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				sw_tone_test(tdm_fd, line0_id);
+				break;
+
+			case '5':
+				printf("%s Enter line id: ", TOOL_PREFIX);
+				gets(str);
+				printf("%s Waiting for off-hook...\n", TOOL_PREFIX);
+				line0_id = atoi(str);
+				sw_loopback(tdm_fd, line0_id);
+				break;
+
+			case '6':
+				printf("%s Enter line #0: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter line #1: ", TOOL_PREFIX);
+				gets(str);
+				printf("Waiting for off-hook...\n");
+				line1_id = atoi(str);
+				if(line0_id >= MAX_LINES || line1_id >= MAX_LINES) {
+					printf("%s Error, line must be in the range of 0-%d\n", TOOL_PREFIX, (MAX_LINES-1));
+					break;
+				}
+				sw_loopback_two_phones_test(tdm_fd, line0_id, line1_id);
+				break;
+
+			case '7':
+				printf("%s Enter starting line range: ", TOOL_PREFIX);
+				gets(str);
+				line0_id = atoi(str);
+				printf("%s Enter ending line range: ", TOOL_PREFIX);
+				gets(str);
+				printf("Waiting for off-hook...\n");
+				line1_id = atoi(str);
+				if((line0_id >= MAX_LINES) || 
+				   (line1_id >= MAX_LINES) ||
+				   ((line1_id-line0_id) % 2 == 0)) {
+					printf("%s Error, lines range must be even and \
+							between 0-%d\n", TOOL_PREFIX, (MAX_LINES-1));
+					break;
+				}
+				sw_loopback_multi_phones_test(tdm_fd, line0_id, line1_id);
+				break;
+
+			case '8':
+				printf("%s Enter number of iterations(must be greater than 3): ", TOOL_PREFIX);
+				gets(str);
+				iterations = (unsigned long int)atoi(str);
+				if(iterations < 4) {
+					printf("Requires at least 4 iterations  - try again\n");
+					break;
+				}
+				slic_digital_loopback(tdm_fd, iterations);
+				break;
+
+			case '9':
+				printf("%s Enter number of iterations('0' - for infinite loop): ", TOOL_PREFIX);
+				gets(str);
+				iterations = (unsigned long int)atoi(str);
+				channel_balancing_test(tdm_fd, iterations);
+				break;
+
+			case 'a':
+				/* Start Telephony */
+				if(ioctl(tdm_fd, TDM_DEV_TDM_START, &tdm_params)) {
+					printf("%s Error, unable to init TDM\n", TOOL_PREFIX);
+					return 1;
+				}
+
+				if(vpapi_init()) {
+					printf("%s Error, init failed\n", TOOL_PREFIX);
+					ret = 1;
+					goto voice_out;
+				}
+				slic_init = 1;
+
+				/* Wait to device/s and line/s calibration to finish */
+#ifdef LINE_CALIBRATION_SUPPORT
+				while((cal_devs < total_devs) || (cal_lines < total_lines)) {
+#else
+				while(cal_devs < total_devs) {
+#endif
+					wait_for_vpapi_event();
+				}
+				break;
+
+			case 'b':
+				/* Stop Telephony */
+				release(0);
+				break;
+
+#if defined(MV_TDM_USE_DCO)
+			case 'c':
+				set_tdm_clk_config();
+				break;
+			
+			case 'd':
+				printf("%s Current PPM correction is (+/-1000): %d", TOOL_PREFIX, get_tdm_clk_correction());
+				break;
+
+			case 'e':
+				printf("%s Enter number of PPM for correction (+/-1000, 0 to disable correction): ", TOOL_PREFIX);
+				gets(str);
+				set_tdm_clk_correction((int)atoi(str));
+				break;
+#endif
+
+			case 'q':
+				goto voice_out;
+
+			default:
+				printf("Option is not supported - try again\n");
+				break;
+		}
+	}
+	
+voice_out:
+	release(1);
+	pthread_kill(timer_thread, SIGKILL);
+	return ret;
+}
+
+void release(int signum)
+{
+	if (signum) {
+		printf("\n%s Stopping Phone devices and exit\n", TOOL_PREFIX);
+		sleep(1);
+	} else {
+		printf("\n%s Stopping Phone devices\n", TOOL_PREFIX);
+	}
+
+	/* Stop SLIC/s */
+	if(slic_init)
+		vpapi_release();
+
+	/* Stop TDM */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_STOP, 0)) {
+		printf("Error, unable to stop TDM\n");
+		return;
+	}
+
+	if (signum)
+		close(tdm_fd);
+
+	if (signum)
+		exit(signum);
+}
+
+static void channel_balancing_test(int tdm_fd, unsigned long int iterations)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, cmp_status = 0, ch, cb_loop = 0, i;
+	unsigned long int loops = 0, index;
+	VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
+	
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Fill Tx buffer with incremental pattern */
+	for(ch = 0; ch < total_lines; ch++) {
+		for(index = 0; index < (80 * pcm_bytes); index+=2)
+			*((unsigned short*)&aud_buf[1][(80 * pcm_bytes * ch) + index]) = (((index+3) << 8)+ (index+1));
+	}
+
+	/* Put SLIC/s in loopback mode */
+	for(ch = 0; ch < total_lines; ch++)
+		VpSetOption(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_NULL, VP_OPTION_ID_LOOPBACK, &lp);
+
+	/* Wait a bit */
+	sleep(1);
+
+	/* Put SLIC/s in TALK mode */
+	for(ch = 0; ch < total_lines; ch++)
+		VpSetLineState(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_LINE_TALK);
+
+	/* Wait a bit */
+	sleep(1);
+
+	if (iterations == 0)
+		iterations = (unsigned long int)(-1); /* Assume infinite */
+
+	while (loops < iterations) {
+
+	  cb_loop = 0;
+	  i = 0;
+
+	  if (ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	  }
+
+	  while (cb_loop == 0) {
+
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			goto cb_out;
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds))
+		{
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len < buff_size) {
+				printf("write() failed\n");
+                        	goto cb_out;
+			}
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds))
+		{
+			memset(aud_buf[0], 0, buff_size);
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len < buff_size) {
+                     		printf("read() failed\n");
+                        	goto cb_out;
+			}
+
+			if(i > 3) {
+
+				for(ch = 1; ch < total_lines; ch++) {
+					if(memcmp(aud_buf[0], &aud_buf[0][(ch * pcm_bytes * 80)], (pcm_bytes * 80))) {
+						printf("\nERROR - data miscompare(ch=%d) !!!\n", ch);
+						cmp_status = 1;
+						goto cb_out;
+					}
+				}
+
+				cb_loop = 1;
+			}
+			i++;
+		}
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	  }
+
+	  loops++;
+	  if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	  }
+	  printf("loop #%u\n", loops);
+	  sleep(1);
+	}
+
+cb_out:
+
+	if(cmp_status == 0) {
+		printf("\nChannel balancing test PASSED !!!\n");
+	}
+	else {
+		printf("Dump Rx buffer:\n");
+		for(ch = 0; ch < total_lines; ch++) {
+			printf("Buffer #%d: ", ch);
+			for(i = 0; i < (pcm_bytes * 80); i++) {
+				printf("0x%x ", aud_buf[0][(ch * pcm_bytes * 80) + i]);
+			}
+			printf("\n\n");
+			sleep(1);
+		}
+	}
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+
+	lp = VP_OPTION_LB_OFF;
+
+	/* Disable loopback mode */
+	for(ch = 0; ch < total_lines; ch++)
+		VpSetOption(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_NULL, VP_OPTION_ID_LOOPBACK, &lp);
+
+	/* Put SLIC/s in STANDBY mode */
+	for(ch = 0; ch < total_lines; ch++)
+		VpSetLineState(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_LINE_STANDBY);
+}
+
+static void slic_digital_loopback(int tdm_fd, unsigned long int iterations)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, cmp_status = 0, ch;
+	unsigned long int loops = 0, index;
+	VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
+	
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Put SLIC/s in loopback mode */
+	for(ch = 0; ch < total_lines; ch++)
+		VpSetOption(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_NULL, VP_OPTION_ID_LOOPBACK, &lp);
+
+	/* Wait a bit */
+	sleep(1);
+
+	/* Put SLIC/s in TALK mode */
+	for(ch = 0; ch < total_lines; ch++)
+		VpSetLineState(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_LINE_TALK);
+
+	/* Fill Tx buffer with incremental pattern */
+	for(ch = 0; ch < total_lines; ch++) {
+		for(index = 0; index < (80 * pcm_bytes); index++)
+			aud_buf[1][index + (80 * pcm_bytes * ch)] = (index+ch+2);
+	}
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while (loops < iterations) {
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+			printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+			goto slic_dl_out;
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds))
+		{
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len < buff_size) {
+				printf("write() failed\n");
+				goto slic_dl_out;
+			}
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds))
+		{
+			memset(aud_buf[0], 0, buff_size);
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len < buff_size) {
+				printf("read() failed\n");
+				goto slic_dl_out;
+			}
+
+			if(loops++ > 3) {
+				for(ch = 0; ch < total_lines; ch++) {
+					if(slic_dl_data_compare(ch)) {
+						printf("\nERROR - data miscompare(loops=%d) !!!\n",loops);
+						cmp_status = 1;
+						goto slic_dl_out;
+					}
+				}
+			}
+		}
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+slic_dl_out:
+
+	if(cmp_status == 0)
+		printf("\nDigital loopback test(%d lines) - PASS !!!\n",total_lines);
+
+	if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+
+	lp = VP_OPTION_LB_OFF;
+
+	/* Disable loopback mode */
+	for(ch = 0; ch < total_lines; ch++)
+		VpSetOption(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_NULL, VP_OPTION_ID_LOOPBACK, &lp);
+
+	/* Put SLIC/s in STANDBY mode */
+	for(ch = 0; ch < total_lines; ch++)
+		VpSetLineState(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_LINE_STANDBY);
+}
+
+static inline int slic_dl_data_compare(int ch)
+{
+	int i = 0, offset = (ch * pcm_bytes * 80);
+
+	/* Align Tx & Rx data start */
+	while((aud_buf[1][offset] != aud_buf[0][offset+i]) && (i < (pcm_bytes * 80)))
+		i++;
+	
+	if(i >= (offset + (pcm_bytes * 80))) {
+		printf("\nError, first Tx byte not found inside Rx buffer\n");
+		return -1;
+	}
+
+	if(memcmp(&aud_buf[0][offset+i], &aud_buf[1][offset], ((pcm_bytes * 80) - i))) {
+			printf("\nDump buffers:\n");
+			for(i = offset; i < (offset +(pcm_bytes * 80)); i++)
+				printf("write[%d] = 0x%x, read[%d] = 0x%x\n", i, aud_buf[1][i], i, aud_buf[0][i]);
+			return -1;
+	}
+	else
+		return 0;
+}
+
+static void sw_loopback(int tdm_fd, unsigned char line_id)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len;
+	
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Wait until line goes off-hook */
+	while(hook_state[line_id] == 0) {
+		wait_for_vpapi_event();
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+	
+	while(hook_state[line_id] == 1) {
+	
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+				printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+				return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds))
+		{
+			printf("Rd\n");
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);
+			if (msg_len <= 0) {
+				printf("read() failed\n");
+				return;
+			}
+			memcpy(BUFF_ADDR(aud_buf[1], line_id), BUFF_ADDR(aud_buf[0], line_id), CH_BUFF_SIZE);
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds))
+		{
+			printf("Wr\n");
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+				return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_vpapi_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static void gen_tone(unsigned short freq, unsigned char line_id, unsigned char* tx_buff)
+{
+	short i;
+	short buf[80];
+	short sample;
+
+	for(i = 0; i < 80; i++) {
+		sample = (sinTbl[f1Mem >> 8] + sinTbl[f2Mem >> 8]) >> 2;
+#ifndef CONFIG_CPU_BIG_ENDIAN 
+		buf[i] = sample;
+#else
+		buf[i] = ((sample & 0xff) << 8)+ (sample >> 8);
+#endif 
+		f1Mem += freq;
+		f2Mem += freq;
+	}
+	memcpy(BUFF_ADDR(tx_buff, line_id), (void *)buf, 160);
+}
+
+static void sw_tone_test(int tdm_fd, unsigned char line_id)
+{
+	fd_set wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len, x;
+	char str[4];
+
+	if (tdm_fd <= 0) {
+			printf("%s Device %s is not accessible\n", TOOL_PREFIX, dev_name);
+			return;
+	}
+
+	while(1) {
+		printf("%s Choose frequency: (1) 300HZ (2) 630HZ (3) 1000HZ (4) Back to main menu: ", TOOL_PREFIX);
+		gets(str);
+		printf("%s Waiting for off-hook...\n", TOOL_PREFIX);
+
+		if(str[0] == '1') {
+			x = 2457;
+			//printf("%s Generating 300HZ tone\n", TOOL_PREFIX);
+		}
+		else if (str[0] == '2') {
+			x = 5161;
+			//printf("%s Generating 630HZ tone\n", TOOL_PREFIX);
+		}
+		else if (str[0] == '3') {
+			x = 8192;
+			//printf("%s Generating 1000HZ tone\n", TOOL_PREFIX);
+		}
+        	else if (str[0] == '4') {
+			return;
+	        }
+		else {
+			printf("%s Input error - try again\n", TOOL_PREFIX);
+			continue;
+		}
+	
+		/* Wait until both lines go off-hook */
+		while(hook_state[line_id] == 0) {
+			wait_for_vpapi_event();
+		}
+
+		if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+			printf("Error, unable to start pcm bus\n");
+			return;
+		}
+
+		printf("%s Waiting for on-hook to return to menu.\n", TOOL_PREFIX);
+
+		while(hook_state[line_id] == 1) {
+			FD_ZERO(&wr_fds);
+			FD_SET(tdm_fd, &wr_fds);
+
+			/* Wait for event  */
+			if (select(tdm_fd+1, NULL, &wr_fds, NULL, &timeout) == 0) {
+				printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+				return;
+			}
+			
+			/* Write */
+			if (FD_ISSET(tdm_fd, &wr_fds))
+			{
+				gen_tone(x, line_id, aud_buf[1]);
+				if (pcm_bytes == 4)
+					gen_tone(x, line_id, (aud_buf[1]+160));
+
+				msg_len = write(tdm_fd, aud_buf[1], buff_size);
+				if (msg_len <= 0) {
+					printf("write() failed\n");
+                        		return;
+				}
+			}
+
+			/* Check hook state */
+			wait_for_vpapi_event();
+
+			/* Reload timeout */
+			timeout.tv_usec = TIMEOUT;
+		}
+	}
+}
+
+static void sw_loopback_multi_phones_test(int tdm_fd, unsigned char start_line, unsigned char end_line)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len;
+	unsigned char line_id;
+	
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	/* Wait until at least one line goes off-hook */
+	while(offhook_count == 0) {
+		wait_for_vpapi_event();
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	while(offhook_count) {
+	
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+				printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+				return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds))
+		{
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);										     if (msg_len <= 0) {
+                       		printf("read() failed\n");
+                        	return;
+			}
+
+			for(line_id = start_line; line_id < end_line; line_id+=2) {
+				memcpy(BUFF_ADDR(aud_buf[1], line_id), BUFF_ADDR(aud_buf[0], (line_id+1)), CH_BUFF_SIZE);
+				memcpy(BUFF_ADDR(aud_buf[1], (line_id+1)), BUFF_ADDR(aud_buf[0], line_id), CH_BUFF_SIZE);
+			}
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds))
+		{
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+                        	return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_vpapi_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static void sw_loopback_two_phones_test(int tdm_fd, unsigned char line0, unsigned char line1)
+{
+	fd_set rd_fds, wr_fds;
+	struct timeval timeout = {0, TIMEOUT};
+	int msg_len;
+	
+	if (tdm_fd <= 0) {
+		printf("Device %s is not accessible\n", dev_name);
+		return;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
+		printf("Error, unable to start pcm bus\n");
+		return;
+	}
+
+	/* Wait until both lines go off-hook */
+	while((hook_state[line0] == 0) || (hook_state[line1] == 0)) {
+		wait_for_vpapi_event();
+	}
+
+
+	while((hook_state[line0] == 1) && (hook_state[line1] == 1)) {
+	
+		FD_ZERO(&rd_fds);
+		FD_ZERO(&wr_fds);
+		FD_SET(tdm_fd, &rd_fds);
+		FD_SET(tdm_fd, &wr_fds);
+
+		/* Wait for event  */
+		if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
+				printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
+				return;
+		}
+
+		/* Read */
+		if (FD_ISSET(tdm_fd, &rd_fds))
+		{
+			msg_len = read(tdm_fd, aud_buf[0], buff_size);										     if (msg_len <= 0) {
+                       		printf("read() failed\n");
+                        	return;
+			}
+			memcpy(BUFF_ADDR(aud_buf[1], line0), BUFF_ADDR(aud_buf[0], line1), CH_BUFF_SIZE);
+			memcpy(BUFF_ADDR(aud_buf[1], line1), BUFF_ADDR(aud_buf[0], line0), CH_BUFF_SIZE);
+		}
+
+		/* Write */
+		if (FD_ISSET(tdm_fd, &wr_fds))
+		{
+			msg_len = write(tdm_fd, aud_buf[1], buff_size);
+			if (msg_len <= 0) {
+				printf("write() failed\n");
+                        	return;
+			}
+		}
+
+		/* Check hook state */
+		wait_for_vpapi_event();
+
+		/* Reload timeout */
+		timeout.tv_usec = TIMEOUT;
+	}
+
+	if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
+		printf("Error, unable to stop pcm bus\n");
+		return;
+	}
+}
+
+static int vpapi_init(void)
+{
+	int i = 0;
+	VpDeviceIdType dev_id = 0;
+	VpLineIdType line_id = 0;
+	VpLineIdType line_dev_num;
+	VpStatusType status;
+	vpapi_init_device_params_t params;
+
+	/* Check params */
+	if(total_lines > MAX_LINES) {
+		printf("## Error, total number of lines(%d) exceeded maximum(%d) ##\n", total_lines, MAX_LINES);
+		return -1;
+	}
+
+	/* Set lines status to on-hook */
+	memset(hook_state, 0, MAX_LINES);
+
+	cal_devs = 0;
+#ifdef LINE_CALIBRATION_SUPPORT
+	cal_lines = 0;
+#endif
+	/* Fill time slot table */
+	memset(time_slot_table, 0, MAX_LINES);
+	for(i = 0; i < total_lines; i++)
+		time_slot_table[i] = ((i+1) * pcm_bytes); /* skip slot #0 */
+
+	/* Extract PCM format */
+	switch(pcm_bytes)
+	{
+		case 1:
+			codec = VP_OPTION_ALAW;
+			break;
+		case 2:
+			codec = VP_OPTION_LINEAR;
+			break;
+		case 4:
+			codec = VP_OPTION_WIDEBAND;
+			break;
+		default:
+			codec = VP_OPTION_ALAW;
+			printf("## Warning, wrong PCM size - set to default(ALAW) ##\n");
+			break;
+	}
+
+#if defined(ZARLINK_SLIC_VE792)
+	/* Bring up the power supply */
+	if(BattOn(VBH, VBL, VBP)) {
+		printf("## Error, VE792 power supply could not initialized properly ##\n");
+                return -1;
+	}
+#endif
+	/* Create max device objects */
+	for(dev_id = 0; dev_id < total_devs; dev_id++) {
+		
+		status = VpMakeDeviceObject(VP_DEV_SERIES, dev_id, &pDevCtx[dev_id], &pDevObj[dev_id]);
+		if (status != VP_STATUS_SUCCESS) {
+				printf("## Error, device %d could not initialized properly(status=%d) ##\n", dev_id, status);
+				return -1;
+        }
+
+#if defined(ZARLINK_SLIC_VE792)
+		status = VpMapSlacId(&pDevCtx[dev_id], 0);
+		if (status != VP_STATUS_SUCCESS) {
+				printf("## Error, SLAC %d could not be mapped(status=%d) ##\n", dev_id, status);
+				return -1;
+        }
+#endif
+		/* Create requested channels for each device */
+		while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
+
+			/*printf("dev_id = %d, line_id = %d, total_lines = %d, total_dev = %d\n", dev_id, line_id, total_lines, total_devs);*/
+			status = VpMakeLineObject(VP_TERM_FXS_GENERIC, GET_LINE(line_id), &pLineCtx[dev_id][GET_LINE(line_id)],
+				&pLineObj[dev_id][GET_LINE(line_id)], &pDevCtx[dev_id]);
+
+			if (status != VP_STATUS_SUCCESS) {
+				printf("## Error, line %d of device %d could not initialized \
+				properly(status=%d) ##\n", line_id, dev_id, status);
+				return -1;
+        	}
+			/* Map unique LineId to LineCtx */
+			status = VpMapLineId(&pLineCtx[dev_id][GET_LINE(line_id)], line_id);
+
+			if (status != VP_STATUS_SUCCESS) {
+                		printf("## Error, line %d for device %d could not \
+						mapped(status=%d) ##\n", line_id, dev_id, status);
+                		return -1;
+			}
+			line_id++;
+        }
+
+		params.dev_size = dev_profile_size;
+		params.ac_size = ac_profile_size;
+		params.dc_size = dc_profile_size;
+		params.ring_size = ring_profile_size;
+		params.fxo_ac_size = 0;
+		params.fxo_cfg_size = 0;
+
+		/*printf("pcm_bytes = %d, total_dev = %d\n", pcm_bytes, total_devs);*/
+
+		if (pcm_bytes < 4)
+			status = vpapi_init_device(dev_id, DEV_PROFILE, AC_COEFF, DC_COEFF, RING_PROFILE, NULL, NULL, &params);
+		else
+			status = vpapi_init_device(dev_id, DEV_PROFILE, WB_AC_COEFF, DC_COEFF, RING_PROFILE, NULL, NULL, &params);
+
+		if (status != VP_STATUS_SUCCESS) {
+			printf("## Error, device(%d) init failed(status=%d)\n", dev_id, status);
+			return -1;
+        }
+	}
+
+	return 0;
+}
+
+static inline void wait_for_vpapi_event(void)
+{
+	bool status;
+	VpEventType event;
+	VpDeviceIdType dev_id;
+
+	for(dev_id = 0; dev_id < total_devs ; dev_id++) {
+		while(sys_service_get_event(dev_id, &event) == TRUE) {
+			switch(event.eventCategory) {
+				case VP_EVCAT_SIGNALING:
+					switch(event.eventId) {
+						case VP_LINE_EVID_HOOK_OFF:
+							if(cal_devs == total_devs) {
+								printf("off-hook(%d)\n", event.lineId);
+								hook_state[event.lineId] = 1;
+								offhook_count++;
+								VpSetLineState(&pLineCtx[GET_DEVICE(event.lineId)][GET_LINE(event.lineId)], VP_LINE_TALK);
+							}
+							break;
+
+						case VP_LINE_EVID_HOOK_ON:
+							if(cal_devs == total_devs) {
+								printf("on-hook(%d)\n", event.lineId);
+								hook_state[event.lineId] = 0;
+								offhook_count--;
+								VpSetLineState(&pLineCtx[GET_DEVICE(event.lineId)][GET_LINE(event.lineId)], VP_LINE_STANDBY);
+							}
+							break;
+
+						default:
+							/*printf("Unknown SIGNALING event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);*/
+							break;
+					}
+					break;
+
+				case VP_EVCAT_RESPONSE:
+					switch(event.eventId) {
+						case VP_DEV_EVID_DEV_INIT_CMP:
+							printf("Zarlink telephony device(%d) initialized successfully\n", event.deviceId);
+							vpapi_dev_init(event.deviceId);
+							cal_devs++;
+							break;
+
+						case VP_EVID_CAL_CMP:
+#ifdef LINE_CALIBRATION_SUPPORT
+							cal_lines++;
+							if(cal_lines == (total_lines-1)) {
+								/*VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
+								vpapi_set_option(1, 0, 0, VP_OPTION_ID_LOOPBACK, &lp); */
+								printf("Zarlink telephony lines(%d) calibrated successfully\n", total_lines);
+								vpapi_init_done();
+							}
+#endif
+							break;
+
+						default:
+							/*printf("Unknown RESPONSE event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);*/
+							break;
+					}
+					break;
+
+				case VP_EVCAT_FAULT:
+					printf("Got FAULT event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);
+					break;
+
+				default:
+					printf("Got event[category-0x%x][id-%d]\n",event.eventCategory,event.eventId);
+					break;
+			}
+		}
+	}
+}
+
+static void vpapi_init_done(void)
+{
+	VpStatusType status;
+	VpDeviceIdType dev_id;
+	VpLineIdType line_id, base_line_id;
+
+	for (dev_id = 0; dev_id < total_devs; dev_id++)
+	{
+		line_id = (dev_id * MAX_DEVICE_LINES);
+		while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
+			/* Set CODEC options */
+			status = VpSetOption(&pLineCtx[dev_id][GET_LINE(line_id)], VP_NULL, VP_OPTION_ID_CODEC, &codec);
+			if(status != VP_STATUS_SUCCESS)
+			{
+				printf("## Error setting VP_OPTION_ID_CODEC (%d) ##\n", status);
+				return;
+			}
+			line_id++;
+		}
+	}
+	return;
+}
+
+static void vpapi_dev_init(VpDeviceIdType dev_id)
+{
+	VpOptionEventMaskType event_mask;
+	VpStatusType status;
+	VpOptionTimeslotType time_slot;
+	VpLineIdType line_id;
+
+	/* Clear all events */
+	memset(&event_mask, 0xff, sizeof(VpOptionEventMaskType));
+
+	event_mask.faults = (unsigned short)VP_EVCAT_FAULT_UNMASK_ALL;
+	event_mask.signaling = (unsigned short)(~(VP_LINE_EVID_HOOK_OFF | VP_LINE_EVID_HOOK_ON));
+#ifdef LINE_CALIBRATION_SUPPORT
+	event_mask.response = (unsigned short)(~VP_EVID_CAL_CMP);
+#endif
+	status = VpSetOption(VP_NULL, &pDevCtx[dev_id], VP_OPTION_ID_EVENT_MASK, &event_mask);
+	if(status != VP_STATUS_SUCCESS)
+	{
+		printf("## Error while setting VP_OPTION_ID_EVENT_MASK (%d) ##\n", status);
+		return;
+	}
+
+
+	line_id = (dev_id * MAX_DEVICE_LINES);
+	while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
+
+		VpSetLineState(&pLineCtx[GET_DEVICE(line_id)][GET_LINE(line_id)], VP_LINE_STANDBY);
+
+		/* Configure PCM timeslots */
+		time_slot.tx = time_slot.rx = time_slot_table[line_id];
+		
+		/*printf("## INFO: line(%d): rx-slot(%d) , tx-slot(%d) ##\n", line_id, time_slot.rx, time_slot.tx);*/
+		status = VpSetOption(&pLineCtx[dev_id][GET_LINE(line_id)], VP_NULL, VP_OPTION_ID_TIMESLOT, &time_slot);
+		if(status != VP_STATUS_SUCCESS)
+		{
+			printf("## Error setting VP_OPTION_ID_TIMESLOT (%d) ##\n", status);
+			return;
+		}
+
+#if 0
+		/* Set CODEC options */
+		status = vpapi_set_option(1, line_id, dev_id, VP_OPTION_ID_CODEC, &codec);
+		if(status != VP_STATUS_SUCCESS)
+		{
+			printf("## Error setting VP_OPTION_ID_CODEC (%d) ##\n", status);
+			return;
+		}
+#endif		
+#ifdef LINE_CALIBRATION_SUPPORT	
+		/* Start line calibration */
+		status = VpCalLine(&pLineCtx[GET_DEVICE(line_id)][GET_LINE(line_id)]);
+
+		if(status == VP_STATUS_SUCCESS) {
+			REGISTER_LINE(line_id);
+		}
+#endif
+		line_id++;
+	}
+}
+
+static void vpapi_release(void)
+{
+	VpDeviceIdType dev_id = 0;
+	VpLineIdType line_id = 0;
+	VpOptionEventMaskType event_mask;
+	VpStatusType status;
+
+	/* Clear all events */
+	memset(&event_mask, 0xff, sizeof(VpOptionEventMaskType));
+
+	for(dev_id = 0; dev_id < total_devs; dev_id++) {
+		/* Mask all interrupts */
+		status = VpSetOption(VP_NULL, &pDevCtx[dev_id], VP_OPTION_ID_EVENT_MASK, &event_mask);
+
+		if(status != VP_STATUS_SUCCESS) {
+			printf("Error while setting VP_OPTION_ID_EVENT_MASK (%d)\n", status);
+			continue;
+		}
+
+		while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
+			/* Place each line in DISCONNECT state */
+			VpSetLineState(&pLineCtx[GET_DEVICE(line_id)][GET_LINE(line_id)], VP_LINE_DISCONNECT);
+
+			/* Free line context */
+			status = VpFreeLineCtx(&pLineCtx[GET_DEVICE(line_id)][GET_LINE(line_id)]);
+
+			if(status == VP_STATUS_SUCCESS) {
+				vpapi_line_status[line_id] = 0;
+				total_lines--;
+#if defined(SLIC_TIMER_EVENT_SUPPORT)
+				if(total_lines == 0) {
+					atomic_set(&vpapi_init, 0);
+					del_timer(&vpapi_timer);
+				}
+#endif
+			} else {
+				printf("Error while free line %d context\n", line_id);
+				continue;
+			}
+			line_id++;
+		}
+	}
+#if defined(ZARLINK_SLIC_VE792)
+	/* Shut down the power supply */
+	if(BattOff()) {
+		printf("## Error while shutting down VE792 power supply ##\n");
+		sleep(1);
+	}
+#endif
+}
+
+VpStatusType vpapi_init_device(VpDeviceIdType dev_id, VpProfilePtrType dev_profile_ptr,
+				VpProfilePtrType ac_profile_ptr, VpProfilePtrType dc_profile_ptr,
+				VpProfilePtrType ring_profile_ptr, VpProfilePtrType fxo_ac_profile_ptr,
+				VpProfilePtrType fxo_cfg_profile_ptr, vpapi_init_device_params_t *params_ptr)
+{
+	VpStatusType	status;
+	int 			rc;	
+
+	status = VpInitDevice(&pDevCtx[dev_id], dev_profile_ptr, ac_profile_ptr, dc_profile_ptr, ring_profile_ptr,
+					 fxo_ac_profile_ptr, fxo_cfg_profile_ptr);
+
+	if(status == VP_STATUS_SUCCESS) {
+		REGISTER_DEVICE(dev_id);
+	}
+
+    return 0;
+}
+
+#if defined(MV_TDM_USE_DCO)
+static void set_tdm_clk_config(void)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	/* Config TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_CONFIG, &tdm_dev_clk)) {
+		printf("%s Error, unable to config TDM clock.\n", TOOL_PREFIX);
+	}
+}
+
+static int get_tdm_clk_correction(void)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	/* Get TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_GET, &tdm_dev_clk)) {
+		printf("%s Error, unable to get TDM clock.\n", TOOL_PREFIX);
+		return 0;
+	}
+
+	return tdm_dev_clk.correction;
+}
+
+static void set_tdm_clk_correction(int correction)
+{
+	tdm_dev_clk_t tdm_dev_clk;
+
+	tdm_dev_clk.correction=correction;
+
+	/* Set TDM clock */
+	if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_SET, &tdm_dev_clk)) {
+		printf("%s Error, unable to set TDM clock.\n", TOOL_PREFIX);
+	}
+}
+#endif
diff --git a/tools/voice/zarlink/user/profile_79238.c b/tools/voice/zarlink/user/profile_79238.c
new file mode 100644
index 0000000..7b2e1b7
--- /dev/null
+++ b/tools/voice/zarlink/user/profile_79238.c
@@ -0,0 +1,1248 @@
+/*

+ * profile_79238.c --

+ *

+ * This file contains profile data in byte format

+ *

+ * Project Info --

+ *   File:  C:\Documents and Settings\benavi\Desktop\profile_792\792.vpw

+ *   Type:  VCP2-792 Project (Line Module Le51HR0128)

+ *   Date:  Wednesday, June 30, 2010 14:29:56

+ *

+ *   This file was generated with Profile Wizard Version: P1.14.1

+ */

+

+#include "profile_79238.h"

+

+/*** Device_Parameters for VE792 Device Family ***/

+const VpProfileDataType VE792_DEV_PROFILE[] =

+{

+    /* Device Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0xFF,       /* 0xFF = device profile */

+        /* number of sections */    0x02,

+        /* content length */        0x24,        /* (2 + 5) + (2 + 27)      */

+    /* Section 0 ----------------------------------------------(PRE-BOOT)-- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x05,

+        /* Access 0 */

+            /* access type */       0x00,       /* 0x00 = direct page write */

+            /* page offset */       0x0B,       /* CLK_CFG register */

+            /* length */            0x01,

+            /* data */              0x00, 0x0A, /* PCLK = 8192 KHz */

+    /* Section 1 ---------------------------------------------(POST-BOOT)-- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x1B,       /* 5 + 11 + 11 */

+        /* Access 0 */

+            /* access type */       0x00,       /* 0x00 = direct page write */

+            /* page offset */       0x09,       /* PCM_CFG register */

+            /* length */            0x01,

+            /* data */              0x00, 0x40, /* Pos. edge, RCS 0, TCS 0 */

+        /* Access 1 */

+            /* access type */       0x00,       /* 0x00 = direct page write */

+            /* page offset */       0x32,       /* HBAT_ADJ + TBAT register */

+            /* length */            0x04,

+            /* data */              0x00, 0x00, /* HBAT_ADJ = 0 V */

+            /* data */              0xEC, 0xCD, /* THBAT = -30 V */

+            /* data */              0xF6, 0x66, /* TLBAT = -15 V */

+            /* data */              0x13, 0x33, /* TPBAT = 30 V */

+        /* Access 2 */

+            /* access type */       0x00,       /* 0x00 = direct page write */

+            /* page offset */       0x38,

+            /* length */            0x04,

+            /* data */              0x7F, 0xFF,

+            /* data */              0x7F, 0xFF,

+            /* data */              0x7F, 0xFF,

+            /* data */              0x00, 0x00

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/************** AC_Coefficients **************/

+

+/* AC Parameters (600) */

+const VpProfileDataType VE792_AC_COEFF_600[] = 

+{

+    /* AC Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x00,       /* 0x00 = AC profile */

+        /* number of sections */    0x01,

+        /* content length */        0x74,     /* (2 + 81) + 1 + 32 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x01,       /* 0x01 = mailbox command */

+        /* content length */        0x51,       /* 81 */

+        /* command ID */            0x2A,       /* 0x2A = WR_AC_PARAM */

+        /* data */

+            /* AC_MASK */           0x01, 0xFF,

+            /* Z FIR */             0x00, 0x22, 0xBA, 0x74, 0x45, 0x3E, 0x33,

+                                    0x5A, 0x24, 0xDC, 0x4B,

+            /* Z IIR */             0x22, 0x22, 0x97, 0x9F, 0x01,

+            /* GR */                0xA2, 0xA0,

+            /* R IIR */             0xDC, 0x01,

+            /* R FIR */             0x2A, 0x10, 0xAD, 0xC9, 0x22, 0x27, 0x22,

+                                    0x52, 0x3F, 0xBA, 0xC3, 0xB4,

+            /* B FIR */             0x00, 0x3C, 0x7A, 0x4B, 0xAF, 0x9A, 0xA9,

+                                    0xC6, 0xBA, 0x37, 0x24, 0x6B, 0x8F, 0x3B,

+                                    0x70,

+            /* B IIR */             0x2E, 0x01,

+            /* GX */                0x3A, 0x30,

+            /* X FIR */             0x3D, 0x20, 0x9F, 0x2A, 0xA3, 0x4E, 0x4B,

+                                    0x23, 0x52, 0xAB, 0xBB, 0x97, 0x00,

+            /* AISN */              0x00, 0x05,

+            /* DISN */              0x00, 0x01, 0x00, 0x07, 0x00, 0x6F, 0x00,

+                                    0x1C, 0x00, 0x80,

+            /* MTR_CFG */           0x00, 0x00,

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00,         /* VP_CFG2 bit LRG = 0 */

+        /* Meter LUT */             0x11, 0x5F,   /* Shadow Register 1 12KHz 2/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x2F,   /* Shadow Register 1 12KHz 4/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x77,   /* Shadow Register 1 12KHz 6/8 */

+                                    0x08, 0x0C,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x77,   /* Shadow Register 1 12KHz 8/8 */

+                                    0x0C, 0x12,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x9F,   /* Shadow Register 1 16KHz 2/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x67,   /* Shadow Register 1 16KHz 4/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x2F,   /* Shadow Register 1 16KHz 6/8 */

+                                    0x08, 0x0C,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x2F,   /* Shadow Register 1 16KHz 8/8 */

+                                    0x0C, 0x12    /* Shadow Register 2 */

+

+};

+

+/* AC Parameters (900) */

+const VpProfileDataType AC_COEFF_900[] = 

+{

+    /* AC Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x00,       /* 0x00 = AC profile */

+        /* number of sections */    0x01,

+        /* content length */        0x74,     /* (2 + 81) + 1 + 32 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x01,       /* 0x01 = mailbox command */

+        /* content length */        0x51,       /* 81 */

+        /* command ID */            0x2A,       /* 0x2A = WR_AC_PARAM */

+        /* data */

+            /* AC_MASK */           0x01, 0xFF,

+            /* Z FIR */             0x00, 0x4A, 0xCA, 0xBD, 0xA5, 0x43, 0x23,

+                                    0x2B, 0xA3, 0xC2, 0x3B,

+            /* Z IIR */             0xA3, 0xA1, 0x97, 0x9F, 0x01,

+            /* GR */                0xA2, 0xB0,

+            /* R IIR */             0xDC, 0x01,

+            /* R FIR */             0x3A, 0x10, 0xAD, 0xD9, 0xC3, 0xA7, 0x42,

+                                    0x42, 0xA3, 0xBA, 0x2B, 0xA4,

+            /* B FIR */             0x00, 0xAA, 0x73, 0x4B, 0x2F, 0x9B, 0xA9,

+                                    0xA5, 0xB3, 0xA6, 0x2A, 0x5C, 0x87, 0xCA,

+                                    0x70,

+            /* B IIR */             0x2E, 0x01,

+            /* GX */                0xA3, 0xA0,

+            /* X FIR */             0x27, 0x20, 0xC2, 0x2A, 0x4A, 0x2E, 0x23,

+                                    0x23, 0x22, 0x2C, 0x2A, 0x87, 0x00,

+            /* AISN */              0x00, 0x0A,

+            /* DISN */              0x00, 0x01, 0x00, 0x07, 0x00, 0x72, 0x00,

+                                    0x35, 0x00, 0x80,

+            /* MTR_CFG */           0x00, 0x00,

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00,         /* VP_CFG2 bit LRG = 0 */

+        /* Meter LUT */             0x11, 0x5F,   /* Shadow Register 1 12KHz 2/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x2F,   /* Shadow Register 1 12KHz 4/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x77,   /* Shadow Register 1 12KHz 6/8 */

+                                    0x08, 0x0C,   /* Shadow Register 2 */

+        /* Meter LUT */             0x11, 0x77,   /* Shadow Register 1 12KHz 8/8 */

+                                    0x0C, 0x12,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x9F,   /* Shadow Register 1 16KHz 2/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x67,   /* Shadow Register 1 16KHz 4/8 */

+                                    0x06, 0x09,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x2F,   /* Shadow Register 1 16KHz 6/8 */

+                                    0x08, 0x0C,   /* Shadow Register 2 */

+        /* Meter LUT */             0x01, 0x2F,   /* Shadow Register 1 16KHz 8/8 */

+                                    0x0C, 0x12    /* Shadow Register 2 */

+

+};

+

+/************** DC_Parameters **************/

+

+/* DC Parameters */

+const VpProfileDataType VE792_DC_COEFF[] = 

+{

+    /* DC Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x01,       /* 0x01 = DC profile */

+        /* number of sections */    0x02,

+        /* content length */        0x25,       /* (2 + 13) + (2 + 20) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x01,       /* 0x01 = mailbox command */

+        /* content length */        0x0D,       /* 13 */

+        /* command ID */            0x2C,       /* 0x2C = WR_DC_PARAM */

+        /* data */                  0x11, 0x11, /* V1 */

+        /* data */                  0x11, 0xEC, /* VAS */

+        /* data */                  0x01, 0x1C, /* VAS_OFFSET */

+        /* data */                  0x55, 0x55, /* RFD */

+        /* data */                  0x80, 0x00, /* RPTC */

+        /* data */                  0x49, 0x25, /* ILA */

+    /* Section 1 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x14,       /* 20 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x33,       /* LOOP_SUP register */

+            /* length */            0x06,

+            /* data */              0xF3, 0x33, /* TGK */

+            /* data */              0x00, 0xC8, /* PGK */

+            /* data */              0x0B, 0xB8, /* TSH */

+            /* data */              0x00, 0x1E, /* DSH */

+            /* data */              0x40, 0x00, /* IFTA */

+            /* data */              0x0C, 0xCD, /* IFTD */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x3C,       /* LOOP_SUP register, HSH */

+            /* length */            0x01,

+            /* data */              0x03, 0xE8  /* HSH */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/************** Ring_Parameters **************/

+

+/* Ringing 20Hz, Sine Wave, 40Vrms */

+const VpProfileDataType RING_20HZ_SINE[] = 

+{

+    /* Ring Profile */

+    /* Balanced, Sinusoidal, Crest Factor 1.4142 */

+    /* 20 Hz, 82.86 Vpk, 15.33 V Tip Bias, 4.67 V Ring Bias */

+    /* Ring Trip: Short Loop 41.9 mA, Long Loop 8 mA */

+    /*            Current Spike Threshold 100 mA */

+    /*            Averaging Period 50 ms */

+    /* Ring Exit Hook Switch Debounce: Threshold 0 ms, Duration 0 ms */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x04,       /* 0x04 = ringing profile */

+        /* number of sections */    0x01,

+        /* content length */        0x22,       /* (2 + 32) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x20,       /* 32 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x22,       /* RING register */

+            /* length */            0x0B,       /* 11 */

+            /* data */              0x30, 0x00, /* R control / FRQR[23:16] */

+            /* data */              0xA3, 0xD7, /* FRQR[15:0] */

+            /* data */              0x46, 0xB6, /* AMPR */

+            /* data */              0x0D, 0x15, /* RBA */

+            /* data */              0x03, 0xFC, /* RBB */

+            /* data */              0x04, 0x05, /* EBR */

+            /* data */              0x35, 0xAB, /* RTSL */

+            /* data */              0x0A, 0x3D, /* RTLL */

+            /* data */              0x00, 0x19, /* RTAP */

+            /* data */              0x00, 0x00, /* RSVD */

+            /* data */              0x7F, 0xFF, /* IST */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x3A,       /* REDSH, REDD */

+            /* length */            0x02,

+            /* data */              0x00, 0x00, /* REDSH */

+            /* data */              0x00, 0x00  /* REDD */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Ringing 25Hz, Sine Wave, 40Vrms */

+const VpProfileDataType RING_25HZ_SINE[] = 

+{

+    /* Ring Profile */

+    /* Balanced, Sinusoidal, Crest Factor 1.4142 */

+    /* 25 Hz, 66.31 Vpk, 15.33 V Tip Bias, 4.67 V Ring Bias */

+    /* Ring Trip: Short Loop 19 mA, Long Loop 8 mA */

+    /*            Current Spike Threshold 100 mA */

+    /*            Averaging Period 40 ms */

+    /* Ring Exit Hook Switch Debounce: Threshold 0 ms, Duration 0 ms */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x04,       /* 0x04 = ringing profile */

+        /* number of sections */    0x01,

+        /* content length */        0x22,       /* (2 + 32) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x20,       /* 32 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x22,       /* RING register */

+            /* length */            0x0B,       /* 11 */

+            /* data */              0x30, 0x00, /* R control / FRQR[23:16] */

+            /* data */              0xCC, 0xCD, /* FRQR[15:0] */

+            /* data */              0x38, 0x97, /* AMPR */

+            /* data */              0x0D, 0x15, /* RBA */

+            /* data */              0x03, 0xFC, /* RBB */

+            /* data */              0x04, 0x05, /* EBR */

+            /* data */              0x18, 0x49, /* RTSL */

+            /* data */              0x0A, 0x3D, /* RTLL */

+            /* data */              0x00, 0x14, /* RTAP */

+            /* data */              0x00, 0x00, /* RSVD */

+            /* data */              0x7F, 0xFF, /* IST */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x3A,       /* REDSH, REDD */

+            /* length */            0x02,

+            /* data */              0x00, 0x00, /* REDSH */

+            /* data */              0x00, 0x00  /* REDD */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/************** Call_Progress_Tones **************/

+

+/* US Dial Tone */

+const VpProfileDataType TONE_DIAL[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0B,

+            /* data */              0x33, 0x33, /* FreqA = 350Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x0E, 0x14, /* FreqB = 440Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* US Ringback Tone */

+const VpProfileDataType TONE_RINGBACK[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0E,

+            /* data */              0x14, 0x7B, /* FreqA = 440Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x0F, 0x5C, /* FreqB = 480Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* US Busy Tone */

+const VpProfileDataType TONE_BUSY[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0F,

+            /* data */              0x5C, 0x29, /* FreqA = 480Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x13, 0xD7, /* FreqB = 620Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* US Reorder Tone */

+const VpProfileDataType TONE_REORDER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0F,

+            /* data */              0x5C, 0x29, /* FreqA = 480Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x13, 0xD7, /* FreqB = 620Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* US Howler Tone (ROH) */

+const VpProfileDataType TONE_US_HOWLER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x2C,

+            /* data */              0xCC, 0xCD, /* FreqA = 1400Hz */

+            /* data */              0x58, 0xD6, /* AmpA  = 0dBm0 */

+            /* data */              0x41, 0xEC, /* FreqB = 2060Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x4E, 0x66, /* FreqC = 2450Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x53, 0x33, /* FreqD = 2600Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x0F  /* Generator control = ABCD */

+};

+

+/* UK Howler Tone */

+const VpProfileDataType TONE_UK_HOWLER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x13,       /* (2 + 15) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0F,       /* 15 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x02,       /* SIG_GEN register */

+            /* length */            0x06,

+            /* data */              0x34, 0xCD, /* 1650Hz Offset */

+            /* data */              0x20, 0x00, /* Periodic, Linear */

+            /* data */              0x08, 0x31, /* FreqA = 1Hz */

+            /* data */              0x1B, 0x33, /* AmpA = 850Hz */

+            /* data */              0x80, 0x00, /* FreqB = Freq Modulated */

+            /* data */              0x00, 0x00, /* AmpB = Sequence control */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x13  /* Generators = Bias+AB */

+};

+

+/* Australia Howler Tone */

+const VpProfileDataType TONE_AUS_HOWLER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x13,       /* (2 + 15) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0F,       /* 15 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x02,       /* SIG_GEN register */

+            /* length */            0x06,

+            /* data */              0x4B, 0x33, /* 2350Hz Offset */

+            /* data */              0x20, 0x00, /* Periodic, Linear */

+            /* data */              0x08, 0x31, /* FreqA = 1Hz */

+            /* data */              0x1B, 0x33, /* AmpA = 850Hz */

+            /* data */              0x80, 0x00, /* FreqB = Freq Modulated */

+            /* data */              0x00, 0x00, /* AmpB = Sequence control */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x13  /* Generators = Bias+AB */

+};

+

+/* Japan Howler Tone */

+const VpProfileDataType TONE_NTT_HOWLER[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x11,       /* (2 + 13) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0D,       /* 13 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x05,

+            /* data */              0x00, 0x00, /* One-shot, Linear */

+            /* data */              0x00, 0x23, /* FreqA = 15s Ramp */

+            /* data */              0x7F, 0xFF, /* AmpA = Maximum */

+            /* data */              0x0C, 0xCD, /* FreqB = 400Hz */

+            /* data */              0x80, 0x00, /* AmpB = Ampl Modulated */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/* Special Information Tone (Called Number Not Connected) */

+const VpProfileDataType TONE_SIT[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x1E,

+            /* data */              0x66, 0x66, /* FreqA = 950Hz */

+            /* data */              0x23, 0x5D, /* AmpA  = -8dBm0 */

+            /* data */              0x2C, 0xCD, /* FreqB = 1400Hz */

+            /* data */              0x23, 0x5D, /* AmpB  = -8dBm0 */

+            /* data */              0x39, 0x9A, /* FreqC = 1800Hz */

+            /* data */              0x23, 0x5D, /* AmpC  = -8dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x07  /* Generator control = ABC */

+};

+

+/* A 1kHz tone at -10dBm0 */

+const VpProfileDataType TONE_ONEKHZ_L[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x20,

+            /* data */              0x00, 0x00, /* FreqA = 1000Hz */

+            /* data */              0x1C, 0x17, /* AmpA  = -10dBm0 */

+            /* data */              0x00, 0x00, /* FreqB = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x01  /* Generator control = A */

+};

+

+/* A 1kHz tone at 0dBm0 */

+const VpProfileDataType TONE_ONEKHZ_H[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x20,

+            /* data */              0x00, 0x00, /* FreqA = 1000Hz */

+            /* data */              0x58, 0xD6, /* AmpA  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqB = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x01  /* Generator control = A */

+};

+

+/* Call Waiting Beep */

+const VpProfileDataType TONE_CALLWAIT[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x0E,

+            /* data */              0x14, 0x7B, /* FreqA = 440Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqB = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x01  /* Generator control = A */

+};

+

+/* Caller ID Alert Tone */

+const VpProfileDataType TONE_CLI[] = 

+{

+    /* Tone Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x02,       /* 0x02 = tone prof */

+        /* number of sections */    0x01,

+        /* content length */        0x19,       /* (2 + 21) + 2 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x15,       /* 21 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x09,

+            /* data */              0x30, 0x44,

+            /* data */              0x28, 0xF6, /* FreqA = 2130Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x58, 0x00, /* FreqB = 2750Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x03  /* Generator control = AB */

+};

+

+/************** Cadence_Definitions **************/

+

+/* US Dial Tone Cadence */

+const VpProfileDataType TONE_CAD_DIAL[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x06,       /* (2 + 4) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x04,       /* 4 */

+        /* data */                  0x00, 0x00, /* sequence length = 1 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Stutter Dial Tone Cadence */

+const VpProfileDataType TONE_CAD_STUTTER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x10,       /* (2 + 14) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0E,       /* 14 */

+        /* data */                  0x00, 0x05, /* sequence length = 6 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+        /* data */                  0x40, 0x64, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x40, 0x64, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x60, /* 04 - Branch to 00 */

+        /* data */                  0x05, 0x03, /* 05 - Generator Ctrl */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* US Ringback Tone Cadence */

+const VpProfileDataType TONE_CAD_RINGBACK[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x0E,       /* (2 + 12) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+        /* data */                  0x47, 0xD0, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x4F, 0xA0, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* US Busy Tone Cadence */

+const VpProfileDataType TONE_CAD_BUSY[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x0E,       /* (2 + 12) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+        /* data */                  0x41, 0xF4, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x41, 0xF4, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* US Reorder Tone Cadence */

+const VpProfileDataType TONE_CAD_REORDER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x0E,       /* (2 + 12) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+        /* data */                  0x40, 0xFA, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x40, 0xFA, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* US Howler Tone Cadence (ROH) */

+const VpProfileDataType TONE_CAD_US_HOWLER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x0E,       /* (2 + 12) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x05, 0x0F, /* 00 - Generator Ctrl */

+        /* data */                  0x40, 0x64, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 02 - Generator Ctrl */

+        /* data */                  0x40, 0x64, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* UK Howler Tone Cadence */

+const VpProfileDataType TONE_CAD_UK_HOWLER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = Tone cadence prof */

+        /* number of sections */    0x01,

+        /* content length */        0x38,       /* (2 + 54) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x36,       /* 54 */

+        /* data */                  0x00, 0x19, /* sequence length = 26 */

+        /* data */                  0x05, 0x13,

+        /* data */                  0x82, 0x04,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x82, 0x8A,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x83, 0x33,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x84, 0x07,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x85, 0x12,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x86, 0x62,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x88, 0x09,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x8A, 0x1E,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x8C, 0xBD,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x90, 0x09,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x94, 0x30,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x99, 0x6A,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x9F, 0xFF

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Australia Howler Tone Cadence */

+const VpProfileDataType TONE_CAD_AUS_HOWLER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = Tone cadence prof */

+        /* number of sections */    0x01,

+        /* content length */        0x44,       /* (2 + 66) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x42,       /* 66 */

+        /* data */                  0x00, 0x1F, /* sequence length = 32 */

+        /* data */                  0x05, 0x13,

+        /* data */                  0x81, 0x03,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x81, 0x46,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x81, 0x9B,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x82, 0x05,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x82, 0x8B,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x83, 0x33,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x84, 0x07,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x85, 0x12,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x86, 0x62,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x88, 0x0A,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x8A, 0x1E,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x8C, 0xBD,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x90, 0x0A,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x94, 0x31,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x99, 0x6B,

+        /* data */                  0x43, 0xE8,

+        /* data */                  0x9F, 0xFF

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Japan Howler Tone Cadence */

+const VpProfileDataType TONE_CAD_NTT_HOWLER[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x06,       /* (2 + 4) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x04,       /* 4 */

+        /* data */                  0x00, 0x00, /* sequence length = 1 */

+        /* data */                  0x05, 0x03, /* 00 - Generator Ctrl */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Special Information Tone Cadence */

+const VpProfileDataType TONE_CAD_SIT[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x03,       /* 0x03 = tone cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x12,       /* (2 + 16) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x10,       /* 16 */

+        /* data */                  0x00, 0x06, /* sequence length = 7 */

+        /* data */                  0x05, 0x01, /* 00 - Generator Ctrl */

+        /* data */                  0x41, 0x2C, /* 01 - Sequential Delay */

+        /* data */                  0x05, 0x02, /* 02 - Generator Ctrl */

+        /* data */                  0x41, 0x2C, /* 03 - Sequential Delay */

+        /* data */                  0x05, 0x04, /* 04 - Generator Ctrl */

+        /* data */                  0x41, 0x2C, /* 05 - Sequential Delay */

+        /* data */                  0x05, 0x00, /* 06 - Generator Ctrl */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Standard Ringing Cadence */

+const VpProfileDataType RING_CAD_STD[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x08,       /* 0x08 = ring cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x12,       /* (2 + 16) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x10,       /* 16 */

+        /* data */                  0x00, 0x06, /* sequence length = 7 */

+        /* data */                  0x02, 0x86, /* 00 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x47, 0xD0, /* 01 - Sequential Delay */

+        /* data */                  0x02, 0x83, /* 02 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x4F, 0xA0, /* 03 - Sequential Delay */

+        /* data */                  0x10, 0x00, /* 04 - Branch to 00 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Ringing Cadence with CallerID */

+const VpProfileDataType RING_CAD_CID[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x08,       /* 0x08 = ring cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x28,       /* (2 + 38) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x26,       /* 38 */

+        /* data */                  0x00, 0x11, /* sequence length = 18 */

+        /* data */                  0x02, 0x86, /* 00 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x47, 0xD0, /* 01 - Sequential Delay */

+        /* data */                  0x02, 0x83, /* 02 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x0A, 0x00, /* 03 - Relative Time Marker */

+        /* data */                  0x40, 0xC8, /* 04 - Sequential Delay */

+        /* data */                  0x02, 0x85, /* 05 - Line State */

+        /* data */                  0x01, 0x3A,

+        /* data */                  0x01, 0x22, /* 06 - Start CallerID */

+        /* data */                  0x6F, 0xA0, /* 07 - Relative Delay */

+        /* data */                  0x02, 0x86, /* 08 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x47, 0xD0, /* 09 - Sequential Delay */

+        /* data */                  0x02, 0x83, /* 10 - Line State */

+        /* data */                  0x01, 0x3B,

+        /* data */                  0x4F, 0xA0, /* 11 - Sequential Delay */

+        /* data */                  0x10, 0x0B, /* 12 - Branch to 08 */

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/* Ringing Always On */

+const VpProfileDataType RING_CAD_ON[] = 

+{

+    /* Cadence Profile */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x08,       /* 0x08 = ring cadence */

+        /* number of sections */    0x01,

+        /* content length */        0x08,       /* (2 + 6) */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequence */

+        /* content length */        0x06,       /* 6 */

+        /* data */                  0x00, 0x01, /* sequence length = 2 */

+        /* data */                  0x02, 0x86, /* 00 - Line State */

+        /* data */                  0x01, 0x3B,

+    /* Unstructured data -------------------------------------------------- */

+        /* none */

+};

+

+/************** Caller_ID **************/

+

+/* US Caller ID Type II */

+const VpProfileDataType CID_TYPE2_US[] = 

+{

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x05,       /* 0x05 = caller ID profile */

+        /* number of sections */    0x04,

+        /* content length */        0x70,       /* 112 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequencer program */

+        /* content length */        0x24,       /* 36 */

+        /* data */                  0x00, 0x10, /* sequence length = 17 */

+        /* data */                  0x01, 0x3B, /* Mute on */

+        /* data */                  0x01, 0x3D, /* Alert tone 300ms */

+        /* data */                  0x41, 0x2C, /* - TONE_CALLWAIT */

+        /* data */                  0x05, 0x00,

+        /* data */                  0x40, 0x0A, /* Silence 10ms */

+        /* data */                  0x01, 0x3E, /* Alert tone 80ms */

+        /* data */                  0x40, 0x50, /* - TONE_CLI */

+        /* data */                  0x05, 0x00,

+        /* data */                  0x01, 0x32, /* Detect interval 160ms */

+        /* data */                  0x40, 0xA0, /* - Tones: A, D */

+        /* data */                  0x09, 0xB2,

+        /* data */                  0x40, 0x64, /* Silence 100ms */

+        /* data */                  0x01, 0x26, /* Send FSK */

+        /* data */                  0x0B, 0x01,

+        /* data */                  0x09, 0x00,

+        /* data */                  0x01, 0x27,

+        /* data */                  0x01, 0x3A, /* Mute off */

+    /* Section 1 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0E,       /* 14 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x1F,       /* FSK_GEN register */

+            /* length */            0x01,

+            /* data */              0x00, 0x04, /* stop = 1, start = 0 */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x10,       /* FSK_GEN register */

+            /* length */            0x03,

+            /* data */              0x29, 0x9A, /* mark freq. 1300Hz  */

+                                    0x43, 0x33, /* space freq. 2100Hz */

+                                    0x12, 0xC6, /* amplitude = -13.5dBm0 */

+    /* Section 2 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x17,       /* 23 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x0A,       /* 10 */

+            /* data */              0x30, 0x0E,

+            /* data */              0x14, 0x7B, /* FreqA = 440Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqB = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpB  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+            /* data */              0x00, 0x01, /* Generator control = A */

+    /* Section 3 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x17,       /* 23 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x0A,       /* 10 */

+            /* data */              0x30, 0x44,

+            /* data */              0x28, 0xF6, /* FreqA = 2130Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x58, 0x00, /* FreqB = 2750Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+            /* data */              0x00, 0x03, /* Generator control = AB */

+    /* Unstructured data -------------------------------------------------- */

+                                    0x00, 0x00, /* 0-bit channel seizure */

+                                    0x00, 0x58, /* 88-bit mark period */

+                                    0x00, 0x0D, /* Detect Tones A, D */

+                                    0x01,       /* API checksum */

+                                    0x00        /* FSK Message Data */

+};

+

+/* UK Caller ID Type I */

+const VpProfileDataType CID_TYPE1_UK[] = 

+{

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x05,       /* 0x05 = caller ID profile */

+        /* number of sections */    0x03,

+        /* content length */        0x55,       /* 85 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequencer program */

+        /* content length */        0x22,       /* 34 */

+        /* data */                  0x00, 0x0F, /* sequence length = 16 */

+        /* data */                  0x40, 0x32, /* Silence 50ms */

+        /* data */                  0x03, 0x00, /* Line Reversal */

+        /* data */                  0x40, 0x64, /* Silence 100ms */

+        /* data */                  0x01, 0x3D, /* Alert tone 100ms */

+        /* data */                  0x40, 0x64, /* - TONE_CLI */

+        /* data */                  0x05, 0x00,

+        /* data */                  0x01, 0x2F, /* Mask hooks 20ms, */

+        /* data */                  0x40, 0x14, /*    Silence 100ms */

+        /* data */                  0x01, 0x2F,

+        /* data */                  0x40, 0x50,

+        /* data */                  0x01, 0x26, /* Send FSK */

+        /* data */                  0x0B, 0x01,

+        /* data */                  0x09, 0x00,

+        /* data */                  0x01, 0x27,

+        /* data */                  0x40, 0xC8, /* Silence 200ms */

+        /* data */                  0x03, 0x00, /* Line Reversal */

+    /* Section 1 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0E,       /* 14 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x1F,       /* FSK_GEN register */

+            /* length */            0x01,

+            /* data */              0x00, 0x04, /* stop = 1, start = 0 */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x10,       /* FSK_GEN register */

+            /* length */            0x03,

+            /* data */              0x29, 0x9A, /* mark freq. 1300Hz  */

+                                    0x43, 0x33, /* space freq. 2100Hz */

+                                    0x27, 0xAE, /* amplitude = -7dBm0 */

+    /* Section 2 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x17,       /* 23 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x03,       /* SIG_GEN register */

+            /* length */            0x0A,       /* 10 */

+            /* data */              0x30, 0x44,

+            /* data */              0x28, 0xF6, /* FreqA = 2130Hz */

+            /* data */              0x13, 0xE3, /* AmpA  = -13dBm0 */

+            /* data */              0x58, 0x00, /* FreqB = 2750Hz */

+            /* data */              0x13, 0xE3, /* AmpB  = -13dBm0 */

+            /* data */              0x00, 0x00, /* FreqC = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpC  = 0dBm0 */

+            /* data */              0x00, 0x00, /* FreqD = 0Hz */

+            /* data */              0x58, 0xD6, /* AmpD  = 0dBm0 */

+            /* data */              0x00, 0x03, /* Generator control = AB */

+    /* Unstructured data -------------------------------------------------- */

+                                    0x00, 0x78, /* 120-bit channel seizure */

+                                    0x00, 0x40, /* 64-bit mark period */

+                                    0x00, 0x00,

+                                    0x01,       /* API checksum */

+                                    0x00        /* FSK Message Data */

+};

+

+/* US Caller ID (Type 1 - On-Hook) */

+const VpProfileDataType CLI_TYPE1_US[] = 

+{

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x01,

+        /* type */                  0x05,       /* 0x05 = caller ID profile */

+        /* number of sections */    0x02,

+        /* content length */        0x26,       /* 38 */

+    /* Section 0 ---------------------------------------------------------- */

+        /* section type */          0x02,       /* 0x02 = sequencer program */

+        /* content length */        0x0C,       /* 12 */

+        /* data */                  0x00, 0x04, /* sequence length = 5 */

+        /* data */                  0x42, 0x08, /* Silence 520ms */

+        /* data */                  0x01, 0x26, /* Send FSK */

+        /* data */                  0x0B, 0x01,

+        /* data */                  0x09, 0x00,

+        /* data */                  0x01, 0x27,

+    /* Section 1 ---------------------------------------------------------- */

+        /* section type */          0x00,       /* 0x00 = register list */

+        /* content length */        0x0E,       /* 14 */

+        /* Access 0 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x1F,       /* FSK_GEN register */

+            /* length */            0x01,

+            /* data */              0x00, 0x04, /* stop = 1, start = 0 */

+        /* Access 1 */

+            /* access type */       0x01,       /* 0x01 = chan. page write */

+            /* page offset */       0x10,       /* FSK_GEN register */

+            /* length */            0x03,

+            /* data */              0x26, 0x66, /* mark freq. 1200Hz  */

+                                    0x46, 0x66, /* space freq. 2200Hz */

+                                    0x27, 0xAE, /* amplitude = -7dBm0 */

+    /* Unstructured data -------------------------------------------------- */

+                                    0x01, 0x30, /* 304-bit channel seizure */

+                                    0x00, 0xB8, /* 184-bit mark period */

+                                    0x00, 0x00,

+                                    0x01,       /* API checksum */

+                                    0x00        /* FSK Message Data */

+};

+

+/************** Metering_Profile **************/

+

+/* Metering Profile 12 kHz Tone */

+const VpProfileDataType METER_12KHZ[] = 

+{

+    /* Metering Profile */

+    /* 12KHz Tone Metering */

+    /* Ramp Time: 10ms, Amplitude: 2000mVrms (Normal Gain) */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x07,       /* 0x07 = Metering profile */

+        /* number of sections */    0x00,

+        /* content length */        0x06,

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x02, /* MTR_TYPE */

+        /* data */                  0x00, 0x0A, /* RAMP_TIME */

+        /* data */                  0x09, 0x94  /* RAMP_STEP */

+};

+

+/* Metering Profile Polarity Reversal */

+const VpProfileDataType METER_POLREV[] = 

+{

+    /* Metering Profile */

+    /* Polrev Pulse Metering */

+    /* Profile header ----------------------------------------------------- */

+        /* version */               0x00,

+        /* type */                  0x07,       /* 0x07 = Metering profile */

+        /* number of sections */    0x00,

+        /* content length */        0x02,

+    /* Unstructured data -------------------------------------------------- */

+        /* data */                  0x00, 0x00  /* MTR_TYPE */

+};

+

+int dev_profile_size = sizeof(VE792_DEV_PROFILE);

+int dc_profile_size = sizeof(VE792_DC_COEFF);

+int ac_profile_size = sizeof(VE792_AC_COEFF_600);

+int ring_profile_size = sizeof(RING_20HZ_SINE);

+

+/* end of file profile_79238.c */

diff --git a/tools/voice/zarlink/user/profile_79238.h b/tools/voice/zarlink/user/profile_79238.h
new file mode 100644
index 0000000..dd790bd
--- /dev/null
+++ b/tools/voice/zarlink/user/profile_79238.h
@@ -0,0 +1,83 @@
+/*

+ * profile_79238.h --

+ *

+ * This header file exports the Profile data types

+ *

+ * Project Info --

+ *   File:  C:\Documents and Settings\benavi\Desktop\profile_792\792.vpw

+ *   Type:  VCP2-792 Project (Line Module Le51HR0128)

+ *   Date:  Thursday, June 03, 2010 13:40:38

+ *

+ *   This file was generated with Profile Wizard Version: P1.14.1

+ */

+

+#ifndef PROFILE_79238_H

+#define PROFILE_79238_H

+

+#ifdef VP_API_TYPES_H

+#include "vp_api_types.h"

+#else

+typedef unsigned char VpProfileDataType;

+#endif

+

+extern int dev_profile_size;

+extern int dc_profile_size;

+extern int ac_profile_size;

+extern int ring_profile_size;

+

+/************** Device_Parameters **************/

+/* Device Profile */

+extern const VpProfileDataType VE792_DEV_PROFILE[];

+

+/************** AC_Coefficients **************/

+extern const VpProfileDataType VE792_AC_COEFF_600[]; /* AC Parameters (600) */

+extern const VpProfileDataType AC_COEFF_900[];       /* AC Parameters (900) */

+

+/************** DC_Parameters **************/

+extern const VpProfileDataType VE792_DC_COEFF[];     /* DC Parameters */

+

+/************** Ring_Parameters **************/

+extern const VpProfileDataType RING_20HZ_SINE[];     /* Ringing 20Hz, Sine Wave, 40Vrms */

+extern const VpProfileDataType RING_25HZ_SINE[];     /* Ringing 25Hz, Sine Wave, 40Vrms */

+

+/************** Call_Progress_Tones **************/

+extern const VpProfileDataType TONE_DIAL[];          /* US Dial Tone */

+extern const VpProfileDataType TONE_RINGBACK[];      /* US Ringback Tone */

+extern const VpProfileDataType TONE_BUSY[];          /* US Busy Tone */

+extern const VpProfileDataType TONE_REORDER[];       /* US Reorder Tone */

+extern const VpProfileDataType TONE_US_HOWLER[];     /* US Howler Tone (ROH) */

+extern const VpProfileDataType TONE_UK_HOWLER[];     /* UK Howler Tone */

+extern const VpProfileDataType TONE_AUS_HOWLER[];    /* Australia Howler Tone */

+extern const VpProfileDataType TONE_NTT_HOWLER[];    /* Japan Howler Tone */

+extern const VpProfileDataType TONE_SIT[];           /* Special Information Tone (Called Number Not Connected) */

+extern const VpProfileDataType TONE_ONEKHZ_L[];      /* A 1kHz tone at -10dBm0 */

+extern const VpProfileDataType TONE_ONEKHZ_H[];      /* A 1kHz tone at 0dBm0 */

+extern const VpProfileDataType TONE_CALLWAIT[];      /* Call Waiting Beep */

+extern const VpProfileDataType TONE_CLI[];           /* Caller ID Alert Tone */

+

+/************** Cadence_Definitions **************/

+extern const VpProfileDataType TONE_CAD_DIAL[];      /* US Dial Tone Cadence */

+extern const VpProfileDataType TONE_CAD_STUTTER[];   /* Stutter Dial Tone Cadence */

+extern const VpProfileDataType TONE_CAD_RINGBACK[];  /* US Ringback Tone Cadence */

+extern const VpProfileDataType TONE_CAD_BUSY[];      /* US Busy Tone Cadence */

+extern const VpProfileDataType TONE_CAD_REORDER[];   /* US Reorder Tone Cadence */

+extern const VpProfileDataType TONE_CAD_US_HOWLER[]; /* US Howler Tone Cadence (ROH) */

+extern const VpProfileDataType TONE_CAD_UK_HOWLER[]; /* UK Howler Tone Cadence */

+extern const VpProfileDataType TONE_CAD_AUS_HOWLER[];/* Australia Howler Tone Cadence */

+extern const VpProfileDataType TONE_CAD_NTT_HOWLER[];/* Japan Howler Tone Cadence */

+extern const VpProfileDataType TONE_CAD_SIT[];       /* Special Information Tone Cadence */

+extern const VpProfileDataType RING_CAD_STD[];       /* Standard Ringing Cadence */

+extern const VpProfileDataType RING_CAD_CID[];       /* Ringing Cadence with CallerID */

+extern const VpProfileDataType RING_CAD_ON[];        /* Ringing Always On */

+

+/************** Caller_ID **************/

+extern const VpProfileDataType CID_TYPE2_US[];       /* US Caller ID Type II */

+extern const VpProfileDataType CID_TYPE1_UK[];       /* UK Caller ID Type I */

+extern const VpProfileDataType CLI_TYPE1_US[];       /* US Caller ID (Type 1 - On-Hook) */

+

+/************** Metering_Profile **************/

+extern const VpProfileDataType METER_12KHZ[];        /* Metering Profile 12 kHz Tone */

+extern const VpProfileDataType METER_POLREV[];       /* Metering Profile Polarity Reversal */

+

+#endif /* PROFILE_79238_H */

+

diff --git a/tools/voice/zarlink/user/profile_88266.c b/tools/voice/zarlink/user/profile_88266.c
new file mode 100644
index 0000000..e45b8e6
--- /dev/null
+++ b/tools/voice/zarlink/user/profile_88266.c
@@ -0,0 +1,644 @@
+/*
+ * profile_8266.c --
+ *
+ * This file contains profile data in byte format
+ *
+ *   This file was generated with Profile Wizard Version: P1.12.3
+ */
+
+#include "profile_88266.h"
+
+
+/*** Device Parameters for VoicePort Device Family ***/
+const VpProfileDataType ABS_VBL_FLYBACK[] = 
+{
+  /* Device Profile */
+ 0x00, 0xFF, 0x00, 0x1A, /* Profile Index and Length */
+ 0x04, 0x00, /* Version and MPI Command */
+ 0x20, 0x00, /* PCLK Frequency */
+ 0x8A, 0x00, /* Device Config 1 and MCLK Correction */
+ 0x40, 0x02, /* Clock Slot and Max Events */
+ 0x0A, 0x00, /* Device Tickrate */
+ 0xE4, 0x00, 0x05, 0x00, /* Switching Regulator Parameters */
+ 0x00, 0x00, /* RSVD */
+ 0x22, 0x00, 0x55, 0x55, /* Linecard Parameters */
+ 0xB2, 0x00, 0xB1, 0x00, 0xB0, 0x40  /* Regulator Timing Parameters */
+};
+
+/************** AC Filter Coefficients **************/
+
+/* AC FXS RF14 600 Ohm Coefficients [Default} */
+const VpProfileDataType AC_FXS_RF14_DEF[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 900 Ohm Coefficients */
+const VpProfileDataType AC_FXS_RF14_900[] = 
+{
+  /* AC Profile */
+ 0xE4, 0x00, 0xF7, 0x4C, 0x01, 0x49, 0xCA, 0x0B, 0x98, 0x34, 0x3B, 0xB2,
+ 0x2C, 0x9F, 0xA4, 0xD2, 0xA3, 0x22, 0xAC, 0x9A, 0xA4, 0xAA, 0x67, 0x9F,
+ 0x01, 0x8A, 0xB3, 0xD0, 0xA6, 0x21, 0xAA, 0x34, 0x2B, 0x2F, 0x4A, 0xA6,
+ 0xAB, 0x2F, 0x4A, 0x37, 0x88, 0x2A, 0xC0, 0x23, 0xAC, 0x2A, 0x26, 0x32,
+ 0xA5, 0x3C, 0xAD, 0xA4, 0xA7, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xAB, 0x49, 0xF1, 0x2A, 0x0A, 0x43, 0xC9, 0xF3, 0x27, 0xBC,
+ 0xE2, 0xAF, 0xAD, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Australia 220+820//220nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_AU[] = 
+{
+  /* AC Profile */
+ 0xBF, 0x00, 0xAF, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0xBA, 0x41, 0x54,
+ 0xA2, 0x2A, 0x5B, 0xA4, 0xAA, 0x3A, 0xB3, 0x9A, 0x87, 0xA2, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0x23, 0x20, 0x3E, 0xA8, 0x2A, 0x57, 0xCB, 0x34,
+ 0xBA, 0xAC, 0xBB, 0xA6, 0x88, 0xAA, 0xB0, 0x49, 0xF6, 0x3B, 0x2E, 0x49,
+ 0xFF, 0xBC, 0xA5, 0x3A, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x34, 0x5C, 0x32, 0x25, 0x1A, 0xA1, 0x3B, 0x23, 0xB3, 0x5B,
+ 0x4D, 0xB5, 0xDC, 0x60, 0x96, 0x3B, 0xA1, 0x00
+};
+
+/* AC FXS RF14 Austria 220+820//115nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_AT[] = 
+{
+  /* AC Profile */
+ 0x6D, 0x00, 0xA7, 0x4C, 0x01, 0x49, 0xCA, 0xEA, 0x98, 0xFA, 0xE1, 0x23,
+ 0xA2, 0xEA, 0xCB, 0xB3, 0xAA, 0xA3, 0xB3, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0xB3, 0x20, 0xAB, 0xA8, 0xCC, 0x24, 0x22, 0x97,
+ 0xAF, 0x8F, 0xD3, 0xBF, 0x88, 0x3B, 0xB0, 0x33, 0x46, 0x2A, 0x2E, 0x33,
+ 0x4F, 0xAE, 0xA5, 0xB3, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0x22, 0x98, 0x02, 0x42, 0xA2, 0x43, 0xA6, 0xD8,
+ 0xFA, 0x8F, 0x29, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Belgium 150+830//72 Coefficients */
+const VpProfileDataType AC_FXS_RF14_BE[] = 
+{
+  /* AC Profile */
+ 0x8F, 0x00, 0x2E, 0x4C, 0x01, 0x49, 0xCA, 0xF3, 0x98, 0x2C, 0xA1, 0xB4,
+ 0xE3, 0x34, 0xCB, 0x2C, 0x2B, 0xA3, 0xA3, 0x9A, 0x87, 0xA6, 0x97, 0x9F,
+ 0x01, 0x8A, 0x42, 0xD0, 0xBA, 0x30, 0xC2, 0x49, 0xA3, 0x4C, 0xDC, 0xC2,
+ 0x22, 0x2B, 0xBA, 0xA4, 0x88, 0xB3, 0xB0, 0xA3, 0xA4, 0x4A, 0xDD, 0xCA,
+ 0xAD, 0x43, 0xA4, 0x22, 0xAD, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x3A, 0x42, 0xA1, 0xA4, 0x19, 0x81, 0x5A, 0x4B, 0x2F, 0xA2,
+ 0xFB, 0xAF, 0xBA, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Brazil 900 Coefficients */
+const VpProfileDataType AC_FXS_RF14_BR[] = 
+{
+  /* AC Profile */
+ 0xE4, 0x00, 0xF7, 0x4C, 0x01, 0x49, 0xCA, 0x0B, 0x98, 0x34, 0x3B, 0xB2,
+ 0x2C, 0x9F, 0xA4, 0xD2, 0xA3, 0x22, 0xAC, 0x9A, 0xA4, 0xAA, 0x67, 0x9F,
+ 0x01, 0x8A, 0xB3, 0xD0, 0xA6, 0x21, 0xAA, 0x34, 0x2B, 0x2F, 0x4A, 0xA6,
+ 0xAB, 0x2F, 0x4A, 0x37, 0x88, 0x2A, 0xC0, 0xA2, 0xAC, 0x2A, 0x26, 0x32,
+ 0xA5, 0x4C, 0xAD, 0xA4, 0xA7, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x3D, 0x53, 0x22, 0x52, 0x1A, 0x22, 0x2B, 0x6A, 0x87, 0x29,
+ 0xFB, 0x2F, 0xFC, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXA RF14 China 200+680//100nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_CN[] = 
+{
+  /* AC Profile */
+ 0xB9, 0x00, 0x1F, 0x4C, 0x01, 0x49, 0xCA, 0xE9, 0x98, 0x5C, 0xB1, 0xAA,
+ 0x23, 0x43, 0xEB, 0x32, 0xAA, 0x23, 0xB3, 0x9A, 0x98, 0x94, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0x22, 0x30, 0x6A, 0x59, 0x2A, 0xCB, 0xB4, 0xB2,
+ 0xBF, 0x3B, 0xA3, 0x25, 0x88, 0x43, 0xC0, 0x3A, 0x45, 0x2B, 0xBD, 0x4C,
+ 0x2E, 0x4C, 0x25, 0x42, 0xAD, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xA4, 0x5A, 0x32, 0xB5, 0x12, 0xA1, 0xA2, 0x3A, 0xA4, 0xB5,
+ 0x64, 0x97, 0xAA, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Czech Republic 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_CZ[] = 
+{
+  /* AC Profile */
+ 0x1A, 0x00, 0x03, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x22, 0xBA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0xAA, 0xC0, 0x97, 0xA0, 0xAA, 0x33, 0xD2, 0xDB, 0x7C, 0x23,
+ 0x2A, 0xEB, 0x32, 0xB4, 0x88, 0x2A, 0x20, 0x6C, 0xBC, 0xCE, 0xA6, 0x2B,
+ 0xA5, 0xAA, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xC3, 0x5A, 0x22, 0xC7, 0x16, 0xE2, 0x2B, 0x42, 0xC6, 0xC8,
+ 0xFA, 0x9F, 0x2B, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Denmark 300+1000//220nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_DK[] = 
+{
+  /* AC Profile */
+ 0x7D, 0x00, 0x9A, 0x4C, 0x01, 0x49, 0xCA, 0xE6, 0x98, 0x22, 0xA1, 0x52,
+ 0xD2, 0xE7, 0x24, 0xF4, 0xCD, 0xAA, 0x97, 0x9A, 0xCA, 0xB3, 0xA5, 0x6E,
+ 0x01, 0x8A, 0x32, 0xD0, 0xAB, 0x20, 0xAA, 0x49, 0x29, 0x7A, 0x32, 0xD6,
+ 0xA2, 0xED, 0xC5, 0x97, 0x88, 0xBA, 0xC0, 0x22, 0xA7, 0x2C, 0xFE, 0x42,
+ 0xDE, 0x22, 0xB6, 0xB3, 0x9F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x23, 0x53, 0x32, 0x2C, 0x1B, 0x22, 0xCA, 0x23, 0x63, 0x2A,
+ 0x33, 0xD4, 0x2A, 0x40, 0x96, 0xA2, 0xA0, 0x00
+};
+
+/* AC FXS RF14 ETSI 270+750//150nF Harmonized Coefficients */
+const VpProfileDataType AC_FXS_RF14_EU[] = 
+{
+  /* AC Profile */
+ 0xD5, 0x00, 0xEC, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0x4A, 0xA1, 0x34,
+ 0xA2, 0xA2, 0xAC, 0x2C, 0xBB, 0x2B, 0xA4, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x9C, 0xD0, 0x2B, 0x20, 0x8F, 0x39, 0x2A, 0xBB, 0xA4, 0x24,
+ 0xB2, 0xBC, 0x4B, 0x26, 0x88, 0xA3, 0xC0, 0xC2, 0x27, 0xBA, 0x3E, 0xAC,
+ 0xAF, 0xB4, 0x26, 0x24, 0x3F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xC3, 0x5F, 0x32, 0x98, 0x03, 0xA1, 0xAA, 0x23, 0xB3, 0x2C,
+ 0x4B, 0x55, 0x25, 0x60, 0x96, 0xF2, 0xC1, 0x00
+};
+
+/* AC FXS RF14 Finland 270+910//120 Coefficients */
+const VpProfileDataType AC_FXS_RF14_FI[] = 
+{
+  /* AC Profile */
+ 0xFF, 0x00, 0x8D, 0x4C, 0x01, 0x49, 0xCA, 0xEF, 0x98, 0x2A, 0xB1, 0x23,
+ 0x33, 0xB2, 0xAB, 0x44, 0xEB, 0xA4, 0x44, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0x24, 0x20, 0x25, 0xB8, 0x2D, 0x42, 0xDB, 0xBA,
+ 0xE3, 0x43, 0xF2, 0xAC, 0x88, 0xC4, 0xB0, 0xA2, 0xA7, 0x42, 0x3E, 0xA2,
+ 0x9F, 0x32, 0x26, 0xBE, 0x2F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xA2, 0x5C, 0x22, 0xA2, 0x13, 0xC1, 0xB3, 0x22, 0x23, 0x7A,
+ 0x3D, 0xB4, 0xD4, 0x50, 0x96, 0x3C, 0x41, 0x00
+};
+
+/* AC FXS RF14 France 215+1000//137nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_FR[] = 
+{
+  /* AC Profile */
+ 0xFC, 0x00, 0xA4, 0x4C, 0x01, 0x49, 0xCA, 0xE7, 0x98, 0xBA, 0x31, 0xA5,
+ 0x62, 0x35, 0xAB, 0xAA, 0xAA, 0xAC, 0xA3, 0x9A, 0xAA, 0xA2, 0xC7, 0x6F,
+ 0x01, 0x8A, 0x2D, 0x01, 0xBB, 0x10, 0xC2, 0x38, 0x2A, 0xA1, 0xC2, 0xA9,
+ 0x23, 0xA2, 0x22, 0x2D, 0x88, 0xA3, 0xB0, 0x53, 0x55, 0x4A, 0xAD, 0xB2,
+ 0xAD, 0x5A, 0x25, 0x72, 0x5E, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x43, 0x22, 0x9F, 0x1A, 0x22, 0x4B, 0x33, 0xD5, 0x2C,
+ 0x7A, 0x87, 0xA8, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 German 220+820//115nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_DE[] = 
+{
+  /* AC Profile */
+ 0xEB, 0x00, 0xDC, 0x4C, 0x01, 0x49, 0xCA, 0xEA, 0x98, 0xA2, 0xE1, 0x24,
+ 0xA2, 0x2A, 0xCB, 0xB3, 0xAA, 0xD3, 0xB3, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0x24, 0x20, 0x2C, 0xA8, 0xAB, 0x24, 0x22, 0x97,
+ 0xAF, 0x8F, 0x23, 0xBF, 0x88, 0x3B, 0xB0, 0x33, 0x46, 0x2A, 0x2E, 0x33,
+ 0x4F, 0xAE, 0xA5, 0xB3, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x53, 0x54, 0x32, 0xC4, 0x1A, 0xA1, 0x2B, 0x2A, 0xA3, 0xAA,
+ 0x4A, 0xA5, 0xBA, 0x60, 0x96, 0xD2, 0xA1, 0x00
+};
+
+/* AC FXS RF14 Greece 400+500//50nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_GR[] = 
+{
+  /* AC Profile */
+ 0x63, 0x00, 0x7D, 0x4C, 0x01, 0x49, 0xCA, 0x03, 0x98, 0x22, 0xA6, 0x2C,
+ 0x3E, 0x2B, 0x87, 0x44, 0x36, 0x2A, 0x9F, 0x9A, 0x22, 0xBA, 0xA7, 0x9F,
+ 0x01, 0x8A, 0x7D, 0xD0, 0xAA, 0xA0, 0x22, 0xAA, 0x98, 0xB4, 0x23, 0xBE,
+ 0xAB, 0xBF, 0xAA, 0x97, 0x88, 0x3C, 0xC0, 0x3A, 0xBD, 0xED, 0x8F, 0xEB,
+ 0xA6, 0x3A, 0x8F, 0x2B, 0x6F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xD2, 0x52, 0x22, 0xA2, 0x13, 0xA1, 0x97, 0x32, 0x25, 0xCA,
+ 0x6B, 0x87, 0x2B, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Hungary 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_HU[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 India 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_IN[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Italy 180+630//60nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_IT[] = 
+{
+  /* AC Profile */
+ 0xEE, 0x00, 0xBD, 0x4C, 0x01, 0x49, 0xCA, 0xF3, 0x98, 0x22, 0xD2, 0xBA,
+ 0x34, 0x22, 0x3C, 0x53, 0xAB, 0xAA, 0xB4, 0x9A, 0x98, 0x1B, 0x97, 0x9F,
+ 0x01, 0x8A, 0x9C, 0xD0, 0xBC, 0xD0, 0x2A, 0x2A, 0x3C, 0x4C, 0x4E, 0x23,
+ 0xD2, 0xBB, 0xDB, 0x55, 0x88, 0xAA, 0xC0, 0x2C, 0xB5, 0x23, 0xAD, 0x4A,
+ 0x5E, 0xAD, 0xB5, 0x2B, 0x2E, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xA2, 0x52, 0xA1, 0xA3, 0x1A, 0x32, 0xAA, 0x4A, 0xAF, 0x3B,
+ 0xF4, 0x9F, 0x3A, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Japan 600+1uF Coefficients */
+const VpProfileDataType AC_FXS_RF14_JP[] = 
+{
+  /* AC Profile */
+ 0x0C, 0x00, 0x79, 0x4C, 0x01, 0x49, 0xCA, 0xF9, 0x98, 0xAC, 0xEE, 0x2A,
+ 0x87, 0x2A, 0x3F, 0xA3, 0x97, 0xE5, 0xC3, 0x9A, 0xAB, 0xA2, 0x24, 0xA6,
+ 0xD0, 0x8A, 0x42, 0xB0, 0x2A, 0xA0, 0x34, 0xAA, 0x3B, 0xA2, 0xCA, 0xAA,
+ 0xA4, 0x24, 0x3B, 0x4D, 0x88, 0xBA, 0x30, 0xAC, 0x2D, 0xAA, 0xCE, 0xAA,
+ 0x25, 0x22, 0x2C, 0xB2, 0x65, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x3B, 0x52, 0xA1, 0xA5, 0x14, 0xA2, 0x23, 0x44, 0x24, 0xA5,
+ 0x4B, 0xA4, 0xAC, 0x40, 0x96, 0x32, 0xD0, 0x00
+};
+
+/* AC FXS RF14 S. Korea 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_KR[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Mexico 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_MX[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Netherlands 600/340+422//100 Coefficients */
+const VpProfileDataType AC_FXS_RF14_NL[] = 
+{
+  /* AC Profile */
+ 0x7D, 0x00, 0x38, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x22, 0xBA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x34, 0xD0, 0xCD, 0xA0, 0xAB, 0xD3, 0x22, 0xAB, 0x4A, 0xA3,
+ 0xA2, 0x2C, 0xAB, 0x45, 0x88, 0x2A, 0x20, 0x6C, 0xBC, 0xCE, 0xA6, 0x2B,
+ 0xA5, 0xAA, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x62, 0x52, 0x22, 0xCD, 0x12, 0x23, 0x44, 0x7A, 0x87, 0x3B,
+ 0xFC, 0xBF, 0xBA, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 New Zealand 370+620//310nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_NZ[] = 
+{
+  /* AC Profile */
+ 0x14, 0x00, 0x00, 0x4C, 0x01, 0x49, 0xCA, 0xE9, 0x98, 0xAA, 0xB3, 0xB2,
+ 0xA2, 0xDA, 0xA3, 0x2B, 0x36, 0xAA, 0x25, 0x9A, 0x2B, 0xA2, 0x27, 0x6F,
+ 0x01, 0x8A, 0x1D, 0x01, 0x52, 0x50, 0x2A, 0x3B, 0x45, 0xA9, 0xCA, 0xA3,
+ 0x2C, 0xAB, 0xAA, 0x27, 0x88, 0xC3, 0x50, 0xBA, 0x8F, 0x37, 0x2F, 0xC2,
+ 0xBE, 0xEA, 0x87, 0xAA, 0x87, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x53, 0x53, 0x32, 0xCB, 0x1C, 0x42, 0x32, 0x3B, 0xB3, 0xA2,
+ 0x42, 0xB4, 0x23, 0x50, 0x96, 0x42, 0xA0, 0x00
+};
+
+/* AC FXS RF14 Norway 120+820//110nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_NO[] = 
+{
+  /* AC Profile */
+ 0x04, 0x00, 0xA8, 0x4C, 0x01, 0x49, 0xCA, 0xE4, 0x98, 0xAA, 0x41, 0x22,
+ 0xA1, 0xAA, 0x3B, 0x23, 0x2A, 0xD4, 0x23, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0xEA, 0x10, 0x22, 0xB8, 0x22, 0x3B, 0x23, 0xA1,
+ 0xAA, 0xBA, 0x32, 0xC4, 0x88, 0x25, 0xB0, 0x3B, 0x24, 0x2C, 0x2D, 0xA3,
+ 0xAC, 0xF4, 0xC4, 0xAB, 0xAD, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xBB, 0x52, 0xE2, 0xBD, 0x1B, 0xA1, 0x3B, 0x2A, 0xA3, 0x3A,
+ 0x4A, 0x26, 0x29, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Portugal 600 Coefficients */
+const VpProfileDataType AC_FXS_RF14_PT[] = 
+{
+  /* AC Profile */
+ 0xA4, 0x00, 0xF4, 0x4C, 0x01, 0x49, 0xCA, 0xF5, 0x98, 0xAA, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2A, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0xA3, 0xA0, 0x2E, 0xB2, 0xB2, 0xBA, 0xAC, 0xA2,
+ 0xA6, 0xCB, 0x3B, 0x45, 0x88, 0x2A, 0x20, 0x3C, 0xBC, 0x4E, 0xA6, 0x2B,
+ 0xA5, 0x2B, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x42, 0xA1, 0xCB, 0x1B, 0xA3, 0xA8, 0xFB, 0x87, 0xAA,
+ 0xFB, 0x9F, 0xA9, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Slovenia 600/220+820//115 Coefficients */
+const VpProfileDataType AC_FXS_RF14_SI[] = 
+{
+  /* AC Profile */
+ 0x00, 0x00, 0x00, 0x4C, 0x00, 0x49, 0xCA, 0xF5, 0x98, 0x2A, 0x7B, 0xAB,
+ 0x2C, 0xA3, 0x25, 0xA5, 0x24, 0xB2, 0x3D, 0x9A, 0x2B, 0xAA, 0xA6, 0x9F,
+ 0x01, 0x8A, 0x1D, 0x01, 0x55, 0xA0, 0xA2, 0xA2, 0x57, 0x2B, 0xC6, 0x23,
+ 0x34, 0xBB, 0x6A, 0xC5, 0x88, 0x2A, 0x20, 0x6C, 0xBC, 0xCE, 0xA6, 0x2B,
+ 0xA5, 0xAA, 0x3E, 0xBA, 0x8F, 0x82, 0xA8, 0x71, 0x80, 0xC8, 0xF0, 0x50,
+ 0x00, 0x86, 0xC3, 0x5A, 0x22, 0xC7, 0x16, 0xE2, 0x2B, 0x42, 0xC6, 0xC8,
+ 0xFA, 0x9F, 0x2B, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 Spain 220+820//120nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_ES[] = 
+{
+  /* AC Profile */
+ 0xBF, 0x00, 0xAF, 0x4C, 0x01, 0x49, 0xCA, 0xE8, 0x98, 0xBA, 0x41, 0x54,
+ 0xA2, 0x2A, 0x5B, 0xA4, 0xAA, 0x3A, 0xB3, 0x9A, 0x87, 0xA2, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0x23, 0x20, 0x3E, 0xA8, 0x2A, 0x57, 0xCB, 0x34,
+ 0xBA, 0xAC, 0xBB, 0xA6, 0x88, 0xAA, 0xB0, 0x49, 0xF6, 0x3B, 0x2E, 0x49,
+ 0xFF, 0xBC, 0xA5, 0x3A, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x34, 0x5C, 0x32, 0x25, 0x1A, 0xA1, 0x3B, 0x23, 0xB3, 0x5B,
+ 0x4D, 0xB5, 0xDC, 0x60, 0x96, 0x3B, 0xA1, 0x00
+};
+
+/* AC FXS RF14 Sweden 200+1000//100nF_900//30nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_SE[] = 
+{
+  /* AC Profile */
+ 0x0E, 0x00, 0x42, 0x4C, 0x01, 0x49, 0xCA, 0xF0, 0x98, 0x24, 0xF1, 0xB4,
+ 0xA2, 0xAB, 0x4B, 0x4B, 0xAA, 0xA7, 0xC3, 0x9A, 0x98, 0x92, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2D, 0x01, 0xB3, 0x20, 0x5B, 0xB8, 0x24, 0xA2, 0x3C, 0xAC,
+ 0xAA, 0x27, 0x32, 0x9F, 0x88, 0x3A, 0xA0, 0x3A, 0x25, 0x3A, 0xAD, 0x22,
+ 0xAD, 0xBE, 0x25, 0xA5, 0x2E, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x73, 0x52, 0x22, 0xD2, 0x12, 0xB1, 0x4A, 0x23, 0xC4, 0xC3,
+ 0x6A, 0x97, 0xA8, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 U.K. 300+1000//220_370+620//310nF Coefficients */
+const VpProfileDataType AC_FXS_RF14_GB[] = 
+{
+  /* AC Profile */
+ 0x24, 0x00, 0x0A, 0x4C, 0x01, 0x49, 0xCA, 0xE6, 0x98, 0x22, 0xA1, 0x52,
+ 0xD2, 0xE7, 0x24, 0xF4, 0xCD, 0xAA, 0x97, 0x9A, 0x2B, 0xA2, 0x27, 0x6E,
+ 0x01, 0x8A, 0x32, 0xD0, 0xCB, 0x20, 0xBB, 0x59, 0x5A, 0x4A, 0xAA, 0xB5,
+ 0x2C, 0x2D, 0x42, 0xC7, 0x88, 0xAA, 0xC0, 0xA3, 0xA7, 0xBA, 0xDE, 0x5C,
+ 0xCE, 0xAA, 0xA6, 0xA2, 0x9F, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x43, 0x5B, 0x32, 0x2C, 0x1D, 0x22, 0xAA, 0x2B, 0x33, 0xBA,
+ 0x3C, 0x34, 0xBA, 0x40, 0x96, 0xA2, 0xA0, 0x00
+};
+
+/* AC FXS RF14 US 900//2.16uF_1650//(100+5nF) Coefficients */
+const VpProfileDataType AC_FXS_RF14_US_loaded[] = 
+{
+  /* AC Profile */
+ 0x01, 0x00, 0x90, 0x4C, 0x01, 0x49, 0xCA, 0x0E, 0x98, 0x32, 0x2B, 0x24,
+ 0x7C, 0x4A, 0x24, 0x55, 0xA3, 0x3A, 0xBC, 0x9A, 0xBA, 0xB3, 0xF4, 0x2D,
+ 0x01, 0x8A, 0xEB, 0xC0, 0x26, 0x21, 0xB2, 0x35, 0xB3, 0xA6, 0x2A, 0xAD,
+ 0xD4, 0xA6, 0x52, 0x4F, 0x88, 0xA3, 0xD0, 0x23, 0xAA, 0xAF, 0x62, 0xEA,
+ 0xBA, 0x2A, 0xB3, 0x4A, 0x3D, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2B, 0x4C, 0x21, 0xAC, 0x03, 0xB2, 0xA5, 0x5A, 0xE4, 0x74,
+ 0xF3, 0xA5, 0xBE, 0x60, 0x96, 0xAA, 0xC0, 0x00
+};
+
+/* AC FXS RF14 US 900//2,16uF_800//(100+50nF) Coefficients */
+const VpProfileDataType AC_FXS_RF14_US_Nonloaded[] = 
+{
+  /* AC Profile */
+ 0x01, 0x00, 0x90, 0x4C, 0x01, 0x49, 0xCA, 0x0E, 0x98, 0x32, 0x2B, 0x24,
+ 0x7C, 0x4A, 0x24, 0x55, 0xA3, 0x3A, 0xBC, 0x9A, 0xBA, 0xB3, 0xF4, 0x2D,
+ 0x01, 0x8A, 0xEB, 0xC0, 0x26, 0x21, 0xB2, 0x35, 0xB3, 0xA6, 0x2A, 0xAD,
+ 0xD4, 0xA6, 0x52, 0x4F, 0x88, 0xA3, 0xD0, 0x23, 0xAA, 0xAF, 0x62, 0xEA,
+ 0xBA, 0x2A, 0xB3, 0x4A, 0x3D, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xBD, 0x52, 0xA1, 0x62, 0x1B, 0x22, 0x3A, 0x4B, 0xB5, 0x2A,
+ 0x65, 0xA7, 0xB6, 0x70, 0x96, 0x23, 0xC0, 0x00
+};
+
+/* AC FXS RF14 US 900//2.16uF Coefficients */
+const VpProfileDataType AC_FXS_RF14_US_SS[] = 
+{
+  /* AC Profile */
+ 0x01, 0x00, 0x90, 0x4C, 0x01, 0x49, 0xCA, 0x0E, 0x98, 0x32, 0x2B, 0x24,
+ 0x7C, 0x4A, 0x24, 0x55, 0xA3, 0x3A, 0xBC, 0x9A, 0xBA, 0xB3, 0xF4, 0x2D,
+ 0x01, 0x8A, 0xEB, 0xC0, 0x26, 0x21, 0xB2, 0x35, 0xB3, 0xA6, 0x2A, 0xAD,
+ 0xD4, 0xA6, 0x52, 0x4F, 0x88, 0xA3, 0xD0, 0x23, 0xAA, 0xAF, 0x62, 0xEA,
+ 0xBA, 0x2A, 0xB3, 0x4A, 0x3D, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xDA, 0x4A, 0x41, 0x3A, 0x02, 0x23, 0x3A, 0x42, 0x25, 0xAA,
+ 0x72, 0xA5, 0x2B, 0x50, 0x96, 0x1D, 0x01, 0x00
+};
+
+/************** WideBand AC Filter Coefficients **************/
+/* AC FXS RF14 600 Ohm Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_US[] =
+{
+  /* AC Profile */
+ 0xED, 0x00, 0xA9, 0x4C, 0x01, 0x49, 0xCA, 0xFC, 0x98, 0xCC, 0x2A, 0xA2,
+ 0x3B, 0x98, 0xB3, 0x43, 0xA2, 0x3A, 0xAB, 0x9A, 0x2D, 0xAA, 0xB6, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0xC4, 0xA0, 0x2E, 0x23, 0x3A, 0x2E, 0x9F, 0x87,
+ 0x4C, 0xCE, 0xB2, 0x27, 0x88, 0xDE, 0x20, 0xAA, 0xCA, 0x22, 0x32, 0x23,
+ 0xAA, 0xA2, 0xB4, 0x2A, 0x87, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xCB, 0x5E, 0x22, 0xBC, 0x12, 0xA3, 0xA9, 0xFA, 0xC6, 0x34,
+ 0xE2, 0x9F, 0xBA, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 European Union Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_EU[] =
+{
+  /* AC Profile */
+ 0xAA, 0x00, 0x9C, 0x4C, 0x01, 0x49, 0xCA, 0xE0, 0x98, 0xAA, 0xA3, 0x6B,
+ 0x22, 0x43, 0xA2, 0xAC, 0xBF, 0x22, 0xA6, 0x9A, 0x01, 0x90, 0x01, 0x01,
+ 0x90, 0x8A, 0x2E, 0x01, 0xBA, 0x10, 0xA2, 0x3A, 0xBA, 0xE9, 0xAA, 0xB5,
+ 0x2A, 0xBC, 0xAF, 0x97, 0x88, 0xAB, 0xC0, 0x4A, 0xBE, 0xBA, 0x9F, 0xC3,
+ 0xAF, 0x3A, 0x3F, 0xCD, 0xA7, 0x82, 0xC8, 0x71, 0x80, 0x69, 0xF0, 0x50,
+ 0x00, 0x86, 0xBA, 0x52, 0xB2, 0xBA, 0x12, 0x42, 0x4A, 0x2A, 0x33, 0xBA,
+ 0x33, 0x34, 0x4B, 0x40, 0x96, 0xB2, 0xA0, 0x00
+};
+
+/* AC FXS RF14 France Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_FR[] =
+{
+  /* AC Profile */
+ 0x98, 0x00, 0x26, 0x4C, 0x01, 0x49, 0xCA, 0xD7, 0x98, 0x4F, 0x22, 0xB5,
+ 0xB1, 0xC6, 0x23, 0x3A, 0xAB, 0x24, 0xB5, 0x9A, 0x01, 0x90, 0x01, 0x01,
+ 0x90, 0x8A, 0x01, 0x11, 0x22, 0x10, 0x3A, 0x29, 0x3C, 0x29, 0x32, 0xB3,
+ 0x4A, 0x2C, 0x2E, 0xB6, 0x88, 0xAC, 0xB0, 0x43, 0x37, 0xAB, 0x3E, 0xB4,
+ 0x3E, 0x22, 0x37, 0x22, 0xAF, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0xAA, 0x52, 0xE2, 0x2B, 0x12, 0x62, 0x63, 0x3A, 0x24, 0xA2,
+ 0x5C, 0x36, 0x39, 0xF0, 0x96, 0x2E, 0x01, 0x00
+};
+
+/* AC FXS RF14 German Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_DE[] =
+{
+  /* AC Profile */
+ 0x27, 0x00, 0xD7, 0x4C, 0x01, 0x49, 0xCA, 0xDB, 0x98, 0xBA, 0xA1, 0xBA,
+ 0x22, 0x2A, 0xF4, 0xAA, 0xAB, 0x22, 0x65, 0x9A, 0x01, 0x90, 0x01, 0x01,
+ 0x90, 0x8A, 0x2E, 0x01, 0xA3, 0x10, 0x2B, 0x29, 0x53, 0xB9, 0xBD, 0xB3,
+ 0x7B, 0xCC, 0xDB, 0xA6, 0x88, 0x2A, 0xB0, 0x2B, 0x9F, 0x2E, 0x3E, 0x22,
+ 0xBE, 0xC3, 0x26, 0x35, 0x2F, 0x82, 0xB8, 0x71, 0x80, 0xAB, 0xF0, 0x50,
+ 0x00, 0x86, 0xCA, 0x5A, 0xA2, 0xBA, 0x1F, 0x22, 0x3B, 0x2A, 0x23, 0x2B,
+ 0x3A, 0x24, 0x4B, 0x40, 0x96, 0x22, 0x21, 0x00
+};
+
+/* AC FXS RF14 China Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_CN[] =
+{
+  /* AC Profile */
+ 0xEF, 0x00, 0x46, 0x4C, 0x01, 0x49, 0xCA, 0xDA, 0x98, 0xB3, 0xB1, 0x23,
+ 0x32, 0x64, 0x97, 0xAA, 0x2B, 0x4A, 0xA4, 0x9A, 0x01, 0x90, 0x01, 0x01,
+ 0x90, 0x8A, 0x2E, 0x01, 0xCD, 0x10, 0x2B, 0x29, 0x22, 0x2A, 0xA2, 0x33,
+ 0x4B, 0x4C, 0xBD, 0xF6, 0x88, 0x2A, 0xC0, 0x52, 0x97, 0xF2, 0x2E, 0xAA,
+ 0x4E, 0xAC, 0xB5, 0x5B, 0xBE, 0x82, 0xA8, 0x71, 0x80, 0xA9, 0xF0, 0x50,
+ 0x00, 0x86, 0x2A, 0x5A, 0xA2, 0xBA, 0x1B, 0x22, 0xCA, 0x24, 0xC3, 0x43,
+ 0x42, 0xA4, 0x4B, 0x50, 0x96, 0x3C, 0x41, 0x00
+};
+
+/* AC FXS RF14 Australia Wideband Coefficients */
+const VpProfileDataType AC_FXS_RF14_WB_AU[] =
+{
+  /* AC Profile */
+ 0xC2, 0x00, 0x2E, 0x4C, 0x01, 0x49, 0xCA, 0xF0, 0x98, 0xBA, 0xA1, 0xAD,
+ 0xA3, 0xA2, 0x2C, 0x2D, 0xAB, 0x22, 0xD4, 0x9A, 0xCC, 0xA2, 0x97, 0x9F,
+ 0x01, 0x8A, 0x2E, 0x01, 0x7A, 0x10, 0xBA, 0x29, 0x2A, 0x3A, 0xA2, 0x32,
+ 0xB2, 0xAA, 0xF2, 0xA4, 0x88, 0xBA, 0xA0, 0x5C, 0x3F, 0x2C, 0xCE, 0xAA,
+ 0x87, 0xC2, 0x66, 0xDB, 0x7E, 0x82, 0xA8, 0x71, 0x80, 0x39, 0x70, 0x50,
+ 0x00, 0x86, 0xAA, 0x59, 0x81, 0x25, 0x1A, 0xA1, 0xBB, 0x2B, 0xB3, 0x2C,
+ 0x46, 0xD5, 0xBC, 0x60, 0x96, 0xAA, 0xB1, 0x00
+};
+
+/************** DC Feed Parameters **************/
+
+/* 22mA  current feed */
+const VpProfileDataType DC_22MA_CC[] = 
+{
+ /* DC Profile */
+ 0x00, 0x01, 0x01, 0x0B, 0x01, 0x08, 0xC2, 0x1A, 0x88, 0xD0, 0x05, 0xC6,
+ 0x11, 0x04, 0x01
+};
+
+/************** Ring Signal Parameters **************/
+
+/* Default Rnging, 25Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_DEF[] = 
+{
+  /* Sine, 25 Hz, 1.41 CF, 70.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x3A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* US Ringing, 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_US[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Canada Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_CA[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* France Ringing 50Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_FR[] = 
+{
+  /* Sine, 50 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x88,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Japan Ringing 16Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_JP[] = 
+{
+  /* Sine, 16 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x2B,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* S. Korea Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_KR[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Taiwan Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_TW[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Hong Kong Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_HK[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Singapore Rnging, 24Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_SG[] = 
+{
+  /* Sine, 24 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Austria Ringing 50Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_AT[] = 
+{
+  /* Sine, 50 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x88,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+/* Australia Ringing 20Hz, Sinewave, 80Vpk */
+const VpProfileDataType RING_AU[] = 
+{
+  /* Sine, 20 Hz, 1.41 CF, 80.00 Vpk, 0.00 Bias */
+  /* Ringing Profile */
+ 0x00, 0x04, 0x00, 0x12, 0x00, 0x0E, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x36,
+ 0x42, 0x55, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00
+};
+
+
+/************** Call Progress Tones **************/
+
+/************** Cadence Definitions **************/
+/* RING Cadence Profile */
+const VpProfileDataType RING_CAD_STD[] = 
+{
+  /* Cadence Profile */
+ 0x00, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x07, 0x21, 0x90,
+ 0x01, 0x00, 0x23, 0x20, 0x40, 0x00
+};
+
+/************** Caller ID **************/
+
+/************** Metering Profile **************/
+
+int dev_profile_size = sizeof(ABS_VBL_FLYBACK);
+int dc_profile_size = sizeof(DC_22MA_CC);
+int ac_profile_size = sizeof(AC_FXS_RF14_DEF);
+int ring_profile_size = sizeof(RING_DEF);
+
+/* end of file profile_8266.c */
diff --git a/tools/voice/zarlink/user/profile_88266.h b/tools/voice/zarlink/user/profile_88266.h
new file mode 100644
index 0000000..f53a0ad
--- /dev/null
+++ b/tools/voice/zarlink/user/profile_88266.h
@@ -0,0 +1,98 @@
+/*
+ * profile_8266.h --
+ *
+ * This header file exports the Profile data types
+ *
+ * Project Info --
+ *   File:  C:\Documents and Settings\benavi\Desktop\tmp\NewProject.vpw
+ *   Type:  Le71HR0865G Line Module Project - VBL Reg ABS Power Supply and 8.192MHz PCLK
+ *   Date:  Thursday, February 25, 2010 16:58:41
+ *
+ *   This file was generated with Profile Wizard Version: P1.12.3
+ */
+
+#ifndef PROFILE_8266_H
+#define PROFILE_8266_H
+
+#ifdef VP_API_TYPES_H
+#include "vp_api_types.h"
+#else
+typedef unsigned char VpProfileDataType;
+#endif
+
+extern int dev_profile_size;
+extern int dc_profile_size;
+extern int ac_profile_size;
+extern int ring_profile_size;
+
+/************** Device Parameters **************/
+/* Device Profile */
+extern const VpProfileDataType ABS_VBL_FLYBACK[];
+
+/************** AC Filter Coefficients **************/
+extern const VpProfileDataType AC_FXS_RF14_DEF[];    /* AC FXS RF14 600 Ohm Coefficients [Default} */
+extern const VpProfileDataType AC_FXS_RF14_900[];    /* AC FXS RF14 900 Ohm Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_AU[];     /* AC FXS RF14 Australia 220+820//220nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_AT[];     /* AC FXS RF14 Austria 220+820//115nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_BE[];     /* AC FXS RF14 Belgium 150+830//72 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_BR[];     /* AC FXS RF14 Brazil 900 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_CN[];     /* AC FXA RF14 China 200+680//100nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_CZ[];     /* AC FXS RF14 Czech Republic 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_DK[];     /* AC FXS RF14 Denmark 300+1000//220nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_EU[];     /* AC FXS RF14 ETSI 270+750//150nF Harmonized Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_FI[];     /* AC FXS RF14 Finland 270+910//120 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_FR[];     /* AC FXS RF14 France 215+1000//137nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_DE[];     /* AC FXS RF14 German 220+820//115nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_GR[];     /* AC FXS RF14 Greece 400+500//50nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_HU[];     /* AC FXS RF14 Hungary 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_IN[];     /* AC FXS RF14 India 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_IT[];     /* AC FXS RF14 Italy 180+630//60nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_JP[];     /* AC FXS RF14 Japan 600+1uF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_KR[];     /* AC FXS RF14 S. Korea 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_MX[];     /* AC FXS RF14 Mexico 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_NL[];     /* AC FXS RF14 Netherlands 600/340+422//100 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_NZ[];     /* AC FXS RF14 New Zealand 370+620//310nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_NO[];     /* AC FXS RF14 Norway 120+820//110nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_PT[];     /* AC FXS RF14 Portugal 600 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_SI[];     /* AC FXS RF14 Slovenia 600/220+820//115 Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_ES[];     /* AC FXS RF14 Spain 220+820//120nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_SE[];     /* AC FXS RF14 Sweden 200+1000//100nF_900//30nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_GB[];     /* AC FXS RF14 U.K. 300+1000//220_370+620//310nF Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_US_loaded[];/* AC FXS RF14 US 900//2.16uF_1650//(100+5nF) Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_US_Nonloaded[];/* AC FXS RF14 US 900//2,16uF_800//(100+50nF) Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_US_SS[];  /* AC FXS RF14 US 900//2.16uF Coefficients */
+
+/************** WideBand AC Filter Coefficients **************/
+extern const VpProfileDataType AC_FXS_RF14_WB_US[];  /* AC FXS RF14 600 Ohm Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_EU[];  /* AC FXS RF14 European Union Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_FR[];  /* AC FXS RF14 France Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_DE[];  /* AC FXS RF14 German Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_CN[];  /* AC FXS RF14 China Wideband Coefficients */
+extern const VpProfileDataType AC_FXS_RF14_WB_AU[];  /* AC FXS RF14 Australia Wideband Coefficients */
+
+/************** DC Feed Parameters **************/
+extern const VpProfileDataType DC_22MA_CC[];         /* 22mA  current feed */
+
+/************** Ring Signal Parameters **************/
+extern const VpProfileDataType RING_DEF[];           /* Default Rnging, 25Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_US[];            /* US Ringing, 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_CA[];            /* Canada Ringing 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_FR[];            /* France Ringing 50Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_JP[];            /* Japan Ringing 16Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_KR[];            /* S. Korea Ringing 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_TW[];            /* Taiwan Ringing 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_HK[];            /* Hong Kong Ringing 20Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_SG[];            /* Singapore Rnging, 24Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_AT[];            /* Austria Ringing 50Hz, Sinewave, 80Vpk */
+extern const VpProfileDataType RING_AU[];            /* Australia Ringing 20Hz, Sinewave, 80Vpk */
+
+/************** Call Progress Tones **************/
+
+/************** Cadence Definitions **************/
+extern const VpProfileDataType RING_CAD_STD[]; 
+/************** Caller ID **************/
+
+/************** Metering Profile **************/
+
+#endif /* PROFILE_8266_H */
+
diff --git a/tools/voice/zarlink/user/readme.txt b/tools/voice/zarlink/user/readme.txt
new file mode 100644
index 0000000..d68bf2f
--- /dev/null
+++ b/tools/voice/zarlink/user/readme.txt
@@ -0,0 +1,10 @@
+
+Zarlink Slic support in User Space
+
+Zarlink driver version:
+
+#define VP_API_VERSION_TAG (0x021000)
+#define VP_API_VERSION_MAJOR_NUM ((VP_API_VERSION_TAG) >> 16)
+#define VP_API_VERSION_MINOR_NUM (((VP_API_VERSION_TAG) & 0x00FF00) >> 8)
+#define VP_API_VERSION_MINI_NUM (((VP_API_VERSION_TAG) & 0x0FF))
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/boot_common.h b/tools/voice/zarlink/user/vp792_api_lib/includes/boot_common.h
new file mode 100644
index 0000000..e6ad378
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/boot_common.h
@@ -0,0 +1,59 @@
+/** \file boot_common.h
+ * boot_common.h
+ *
+ * Header file for the VP-API-II c files.
+ *
+ * This file contains all of the VP-API-II declarations that are Voice
+ * Termination Device (VTD) family independent.	The implementation in this file
+ * is applicable to VCP classes of devices.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 6419 $
+ * $LastChangedDate: 2010-02-12 16:40:10 -0600 (Fri, 12 Feb 2010) $
+ */
+
+#ifndef BOOT_COMMON_H
+#define BOOT_COMMON_H
+
+#include "vp_api_types.h"
+#include "hbi_common.h"
+
+/******************************************************************************
+ *                              TYPE DEFINITIONS                              *
+ ******************************************************************************/
+
+typedef bool (*VpBootSupportFuncPtrType) (VpDeviceIdType deviceId);
+
+
+/******************************************************************************
+ *                             FUNCTION PROTOTYPES                            *
+ ******************************************************************************/
+/*
+ * Initialization functions
+ */
+EXTERN VpStatusType
+VpVcpVppBootLoad(
+	VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+EXTERN VpStatusType
+VpBootLoadInternal(
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation,
+    VpDeviceIdType deviceId,
+    uint16p pRecCnt,
+    VpBootSupportFuncPtrType haltFunc,
+    VpBootSupportFuncPtrType validateFunc);
+
+#endif /* BOOT_COMMON_H */
+
+
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/hbi_common.h b/tools/voice/zarlink/user/vp792_api_lib/includes/hbi_common.h
new file mode 100644
index 0000000..ec07b27
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/hbi_common.h
@@ -0,0 +1,90 @@
+/** \file hbi_common.h
+ * hbi_common.h
+ *
+ * This file declares the VCP Host Bus Interface layer register/mail box
+ * mapping.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 6419 $
+ * $LastChangedDate: 2010-02-12 16:40:10 -0600 (Fri, 12 Feb 2010) $
+ */
+
+#ifndef _HBI_COMMON_H
+#define _HBI_COMMON_H
+
+#include "vp_hal.h"
+
+/******************************************************************************
+ *                        	LOW_LEVEL HBI DEFINES		                      *
+ ******************************************************************************/
+#define VP_HBI_PAGE_SIZE            0x80
+
+#define VP_DP 254    /* magic page number indicating direct page */
+
+/* HBI commands: */
+#define HBI_CMD_PAGED_READ(offset, length)   (0x0000 + ((uint16)offset << 8) + \
+                                                length)
+#define HBI_CMD_PAGED_WRITE(offset, length)  (0x0080 + ((uint16)offset << 8) + \
+                                                length)
+#define HBI_CMD_DIRECT_READ(offset, length)  (0x8000 + ((uint16)offset << 8) + \
+                                                length)
+#define HBI_CMD_DIRECT_WRITE(offset, length) (0x8080 + ((uint16)offset << 8) + \
+                                                length)
+#define HBI_CMD_START_MBOX_RD(length)        (0xF800 + length)
+#define HBI_CMD_START_MBOX_WR(length)        (0xF900 + length)
+#define HBI_CMD_CONT_MBOX_RD(length)         (0xFA00 + length)
+#define HBI_CMD_CONT_MBOX_WR(length)         (0xFB00 + length)
+#define HBI_CMD_CONFIGURE(options)           (0xFD00 + options)
+#define HBI_CMD_SELECT_PAGE(page)            (0xFE00 + page)
+#define HBI_CMD_NOP                          0xFFFF
+
+/******************************************************************************
+ *                 REGISTERS SHARED BY VCP DEVICES                            *
+ ******************************************************************************/
+#define HW_Reg_INTIND           VP_DP,  0x00,   0
+#define HW_Reg_INTPARAM         VP_DP,  0x01,   0
+#define HW_Reg_INTIND_AND_INTPARAM         VP_DP,  0x00,   1
+#define HW_Reg_MBOXFLAG         VP_DP,  0x02,   0
+#define HW_Reg_CRC255           VP_DP,  0x03,   0
+#define HW_Reg_BASE255          VP_DP,  0x04,   0
+#define HW_Reg_MBOFFSET         VP_DP,  0x05,   0
+#define HW_Reg_HWRES            VP_DP,  0x06,   0
+#define HW_Reg_PCLKSEL          VP_DP,  0x07,   0
+#define HW_Reg_PCMCLKSLOT       VP_DP,  0x08,   0
+#define HW_Reg_SYSINTSTAT       VP_DP,  0x09,   0
+#define HW_Reg_SYSINTMASK       VP_DP,  0x0A,   0
+
+/******************************************************************************
+ *                        FUNCTION PROTOTYPES			                      *
+ ******************************************************************************/
+EXTERN bool VpHbiRd8(VpDeviceIdType deviceId, uint8 page, uint8 offset,
+                        uint8 words, uint8p pDest);
+EXTERN bool VpHbiWr8(VpDeviceIdType deviceId, uint8 page, uint8 offset,
+                        uint8 words, uint8p pSrc);
+EXTERN bool VpHbiRd(VpDeviceIdType deviceId, uint8 page, uint8 offset,
+                        uint8 words, uint16p pDest);
+EXTERN bool VpHbiWr(VpDeviceIdType deviceId, uint8 page, uint8 offset,
+                        uint8 words, uint16p pSrc);
+EXTERN bool VpHbiXfer(bool readWrite, VpDeviceIdType deviceId,
+                        uint32 ambaAddr, uint32 length, uint16p data,
+                        uint8 byteAddressable,
+                        bool (*SetCodeLoadBase)(VpDeviceIdType deviceId, uint32 amba_addr));
+
+EXTERN bool VpHbiVcpVppValidate(VpDeviceIdType deviceId);
+EXTERN bool VpHbiVcpVppReset(VpDeviceIdType deviceId);
+EXTERN bool VpHbiVcpVppClearCodeMem(VpDeviceIdType deviceId);
+EXTERN bool VpHbiVcpVppHalt(VpDeviceIdType deviceId);
+EXTERN bool VpHbiVcpVppSetBase255(VpDeviceIdType deviceId, uint32 amba_addr);
+EXTERN bool VpHbiVcpVppAmbaRdWr(bool readWrite, VpDeviceIdType deviceId,
+                        uint32 amba_addr, uint32 numwords, uint16p data);
+EXTERN bool VpHbiSetBase255(VpDeviceIdType deviceId, uint32 amba_addr, uint16p base255reg);
+#define VpHbiAmbaRdWr(readWrite, deviceId, amba_addr, numwords, pData) \
+    VpHbiVcpVppAmbaRdWr(readWrite, deviceId, amba_addr, numwords, pData)
+#define VpHbiAmbaWrite(deviceId, amba_addr, numwords, pData) \
+    VpHbiVcpVppAmbaRdWr(TRUE, deviceId, amba_addr, numwords, pData)
+#define VpHbiAmbaRead(deviceId, amba_addr, numwords, pData) \
+    VpHbiVcpVppAmbaRdWr(FALSE, deviceId, amba_addr, numwords, pData)
+
+#endif /* _HBI_COMMON_H */
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp792_api.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp792_api.h
new file mode 100644
index 0000000..2d36a83
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp792_api.h
@@ -0,0 +1,472 @@
+/** \file vp792_api.h
+ * vp792_api.h
+ *
+ *  Header file that define all the commands for the Vp792 device.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8475 $
+ * $LastChangedDate: 2011-04-05 11:30:04 -0500 (Tue, 05 Apr 2011) $
+ */
+
+#ifndef VP792_API_H
+#define VP792_API_H
+
+#define VP792_MIN_SLAC_ID       0
+#define VP792_MAX_SLAC_ID       7
+
+#define VP792_MAX_OUTSTANDING_RESPONSES         10
+
+/* Maximum number of profiles of each type in the Profile Table: */
+#define VP_792_DEV_PROF_TABLE_SIZE              1
+#define VP_792_AC_PROF_TABLE_SIZE               2
+#define VP_792_DC_PROF_TABLE_SIZE               2
+#define VP_792_RINGING_PROF_TABLE_SIZE          2
+#define VP_792_TONE_CADENCE_PROF_TABLE_SIZE     11
+#define VP_792_TONE_PROF_TABLE_SIZE             10
+#define VP_792_RING_CADENCE_PROF_TABLE_SIZE     4
+#define VP_792_METERING_PROF_TABLE_SIZE         2
+#define VP_792_CALLERID_PROF_TABLE_SIZE         2
+
+/* Maximum length of each type of profile (bytes): */
+#define VP792_DEV_PROFILE_LEN               45
+#define VP792_DC_PROFILE_LEN                44
+#define VP792_AC_PROFILE_LEN                128
+#define VP792_CID_PROFILE_LEN               200
+#define VP792_MTR_PROFILE_LEN               22
+#define VP792_TONE_PROFILE_LEN              32
+#define VP792_RINGCAD_PROFILE_LEN           72
+#define VP792_TONECAD_PROFILE_LEN           72
+#define VP792_RING_PROFILE_LEN              38
+
+/* Lengths of profile sections that need to be stored or otherwise handled
+ * separately from the whole. (words) */
+#define VP792_AC_PROFILE_REGDATA_LEN        1
+#define VP792_DC_PROFILE_REGDATA_LEN        22
+#define VP792_RING_PROFILE_REGDATA_LEN      34
+
+typedef enum
+{
+  VP_792_SEQ_OFF,
+  VP_792_SEQ_RING,
+  VP_792_SEQ_TONE,
+  VP_792_SEQ_OTHER
+} Vp792SequencerUseType;
+
+#include "vp_hal.h"
+
+/* Struct for the Profile Table: */
+typedef struct {
+#define VP792_NUM_PROFILE_TYPES 9
+    uint16 valid[VP792_NUM_PROFILE_TYPES];
+
+#ifdef VP_COMMON_ADDRESS_SPACE
+    /* We only need to save profile pointers in the device object. */
+    VpProfilePtrType pDevice[VP_792_DEV_PROF_TABLE_SIZE];
+    VpProfilePtrType pAc[VP_792_AC_PROF_TABLE_SIZE];
+    VpProfilePtrType pDc[VP_792_DC_PROF_TABLE_SIZE];
+    VpProfilePtrType pRinging[VP_792_RINGING_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingCad[VP_792_RING_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pTone[VP_792_TONE_PROF_TABLE_SIZE];
+    VpProfilePtrType pMetering[VP_792_METERING_PROF_TABLE_SIZE];
+    VpProfilePtrType pCallerId[VP_792_CALLERID_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneCad[VP_792_TONE_CADENCE_PROF_TABLE_SIZE];
+#else
+    /* Profiles must be copied into the device object. */
+    VpProfileDataType device[VP_792_DEV_PROF_TABLE_SIZE][VP792_DEV_PROFILE_LEN];
+    VpProfileDataType ac[VP_792_AC_PROF_TABLE_SIZE][VP792_AC_PROFILE_LEN];
+    VpProfileDataType dc[VP_792_DC_PROF_TABLE_SIZE][VP792_DC_PROFILE_LEN];
+    VpProfileDataType ringing[VP_792_RINGING_PROF_TABLE_SIZE][VP792_RING_PROFILE_LEN];
+    VpProfileDataType ringCad[VP_792_RING_CADENCE_PROF_TABLE_SIZE][VP792_RINGCAD_PROFILE_LEN];
+    VpProfileDataType tone[VP_792_TONE_PROF_TABLE_SIZE][VP792_TONE_PROFILE_LEN];
+    VpProfileDataType metering[VP_792_METERING_PROF_TABLE_SIZE][VP792_MTR_PROFILE_LEN];
+    VpProfileDataType callerId[VP_792_CALLERID_PROF_TABLE_SIZE][VP792_CID_PROFILE_LEN];
+    VpProfileDataType toneCad[VP_792_TONE_CADENCE_PROF_TABLE_SIZE][VP792_TONECAD_PROFILE_LEN];
+#endif
+
+} Vp792ProfileTableType;
+
+typedef enum
+{
+  VP792_REQUEST_SET_REL_GAIN,
+  VP792_REQUEST_GET_LOOP_COND,
+  VP792_REQUEST_GET_OPTION,
+  VP792_REQUEST_DEVICE_IO_ACCESS_EXT,
+  VP792_REQUEST_LINE_IO_ACCESS,
+  VP792_REQUEST_QUERY,
+  VP792_REQUEST_LOW_LEVEL_CMD_16,
+  VP792_REQUEST_SENDSIG_MSGWAIT,
+  VP792_REQUEST_TEST_INTERNAL,
+  VP792_REQUEST_TEST_CMP,
+  VP792_REQUEST_TIMER_CMP,
+  VP792_REQUEST_REGISTER_DUMP
+} Vp792RequestTagType;
+
+/* Struct for information about pending responses (used in
+VpGetResults()): */
+typedef struct {
+    bool outstanding;
+
+    Vp792RequestTagType requestType;
+
+    union {
+        struct {
+            uint16 handle;
+            uint8 channelId;
+        } setRelGain;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+        } getLoopCond;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+            VpOptionIdType optionId;
+        } getOption;
+
+        struct {
+            VpDeviceIoAccessExtType deviceIoAccess;
+        } deviceIoAccessExt;
+
+        struct {
+            uint16 handle;
+            VpLineIoAccessType lineIoAccess;
+        } lineIoAccess;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+            VpQueryIdType queryId;
+        } query;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+            VpLowLevelCmdType cmdType;
+            uint16 writeWords[2];
+            uint8 numWriteWords;
+            uint8 numReadWords;
+        } lowLevelCmd16;
+
+        struct {
+            uint16 eventId;
+            uint16 handle;
+            uint8 channelId;
+            uint16 respSize;
+            uint16 cmdId;
+        } testLine;
+
+        struct {
+            uint16 handle;
+            uint8 channelId;
+            bool internal;
+        } genTimer;
+
+        struct {
+            uint8 channelId;
+            uint8 commandId;
+            uint8 numReadWords;
+        } registerDump;
+    } args;
+} Vp792ResponseRequestType;
+
+typedef struct {
+    uint32 opaqueData[2400];
+} Vp792OpaquePmDevObjType;
+
+/* Vp792-specific Device Object */
+typedef struct {
+    /* Customer-defined device identifier struct, passed to HAL functions: */
+    VpDeviceIdType deviceId;
+
+    /* Slac identifier mapped with VpMapSlacId().  This member allows for
+       multiple device objects to share a common deviceId (which is the case
+       when they share a chip-select on the SPI bus). */
+    uint8 slacId;
+
+    /* Total number of channels controlled by this device: */
+    uint8 maxChannels;
+
+    /* SLAC revision info */
+    struct {
+        uint16 device;
+        uint16 product;
+        uint16 version;
+        uint32 patchAddress;
+    } rev;
+
+    /* A flag indicating whether VpInitDevice() has completed: */
+    bool devInit;
+
+    /* The Profile Table: */
+    Vp792ProfileTableType profTable;
+
+    /* PCM Clock Rate in units of 1KHz */
+    uint16 pcmClockRate;
+
+    /* High bits of the VP-API-II timestamp.  We maintain the high bits here
+     because the SLAC's timestamp has finer granularity. */
+    uint16 timeStampHiBits;
+
+    /* Struct for locally-maintained device-specific options: */
+    struct {
+        VpOptionCriticalFltType criticalFlt;
+        VpOptionEventMaskType eventMask;
+        uint16 pulseEnabled;
+        uint16 dtmfEnabled;
+        VpOptionParkModeType parkMode;
+        uint32 debugSelect;
+    } options;
+
+    /* Temporary storage for interrupt indication, while command mailbox is busy. */
+    uint16 intInd[2];
+
+    /* Array for keeping track of outstanding response requests: */
+    Vp792ResponseRequestType responseRequest[VP792_MAX_OUTSTANDING_RESPONSES];
+
+    /* Index (in the above array) of the next result to be returned by
+       VpGetResults(): */
+    uint16 requestIdx;
+
+    /* SLAC response mailbox cache (temporary storage used in cases of mailbox
+       congestion, where we need to empty the response mailbox before we can
+       issue another command in the command mailbox): */
+    struct {
+        uint8 count;            /* When the cache is nonempty, count > 0. */
+#define VP792_MAX_RSPSIZE 42
+        uint16 data[2][VP792_MAX_RSPSIZE];
+    } respMboxCache;
+
+    /* Bitmask indicating which device-specific event handlers are running. */
+    uint16 eventHandlers;
+
+    /* State variables for EhInitDevice() event handler: */
+    struct {
+
+#ifdef VP_COMMON_ADDRESS_SPACE
+        /* We only need to save profile pointers in the line object. */
+        VpProfilePtrType pDevProfile;
+        VpProfilePtrType pAcProfile;
+        VpProfilePtrType pDcProfile;
+        VpProfilePtrType pRingProfile;
+#else
+        /* Profiles must be copied into the line object. */
+        uint16 profilesValid;
+        VpProfileDataType devProfile[VP792_DEV_PROFILE_LEN];
+        VpProfileDataType acProfile[VP792_AC_PROFILE_LEN];
+        VpProfileDataType dcProfile[VP792_DC_PROFILE_LEN];
+        VpProfileDataType ringProfile[VP792_RING_PROFILE_LEN];
+#endif
+
+    } ehInitDevice;
+
+#ifdef VP792_INCLUDE_TESTLINE_CODE
+    Vp792OpaquePmDevObjType opaquePmDevObj;
+#endif
+
+} Vp792DeviceObjectType;
+
+/* Vp792-specific Line Object */
+typedef struct
+{
+
+    /* Number used by the Vp792 to uniquely identify this line: */
+    uint8 channelId;
+
+    /* Line termination type: */
+    VpTermType termType;
+
+    /* Customer-defined line identifier struct, returned in the event
+    * structure by VpGetEvent() when an event occurs on this line: */
+    VpLineIdType lineId;
+
+    /* A flag indicating whether VpInitLine() has completed: */
+    bool lineInit;
+
+    /* Struct for locally-maintained line-specific options: */
+    struct {
+        VpOptionDtmfModeControlType dtmfControlMode;
+        VpOptionZeroCrossType zeroCross;
+        VpOptionPulseModeType pulseMode;
+        VpOptionEventMaskType eventMask;
+        VpOptionRingControlType ringControl;
+        VpOptionPcmTxRxCntrlType pcmTxRxCntrl;
+        VpOptionLoopbackType loopback;
+        uint16 afeConfig; /* cached AFE_CONFIG value for loopback option */
+        uint32 debugSelect;
+    } options;
+
+    struct {
+#ifdef VP_COMMON_ADDRESS_SPACE
+        /* We only need to save profile pointers in the line object. */
+        VpProfilePtrType pAc;
+        VpProfilePtrType pDc;
+        VpProfilePtrType pRinging;
+        VpProfilePtrType pRingCad;
+        VpProfilePtrType pTone;
+        VpProfilePtrType pMetering;
+        VpProfilePtrType pCallerId;
+        VpProfilePtrType pToneCad;
+#else
+        /* Profiles must be copied into the line object. */
+        uint16 valid;
+        VpProfileDataType ac[VP792_AC_PROFILE_LEN];
+        VpProfileDataType dc[VP792_DC_PROFILE_LEN];
+        VpProfileDataType ringing[VP792_RING_PROFILE_LEN];
+        VpProfileDataType ringCad[VP792_RINGCAD_PROFILE_LEN];
+        VpProfileDataType tone[VP792_TONE_PROFILE_LEN];
+        VpProfileDataType metering[VP792_MTR_PROFILE_LEN];
+        VpProfileDataType callerId[VP792_CID_PROFILE_LEN];
+        VpProfileDataType toneCad[VP792_TONECAD_PROFILE_LEN];
+#endif
+
+    } profiles;
+
+    /* Bitmask indicating which line-specific event handlers are running. */
+    uint16 eventHandlers;
+
+    /* State variables for EhSetLineState() event handler: */
+    struct {
+        bool waitForMeterAbort;
+        bool waitForSequencerReady;
+        VpLineStateType newState;
+    } ehSetLineState;
+
+    /* Current API line state */
+    VpLineStateType currentState;
+
+    /* Currently-detected ongoing DTMF digit (if any): */
+    uint16 dtmfDigitDetected;
+
+    /* Sequencer state variables: */
+    struct {
+
+        /* If a sequencer-abort command has been sent to the SLAC, but the
+           VP792_EVID_SEQ event has not yet arrived, this is TRUE. */
+        bool aborting;
+
+        /* Event handlers which will be started only after the current
+           sequence is aborted: */
+        uint16 deferredHandlers;
+
+        /* Keeps track of what, if anything, is using the sequencer. */
+        Vp792SequencerUseType activeSequence;
+
+        /* Buffer for holding a new sequencer program while we wait for the
+           old sequence to be aborted: */
+#define _VP792_CMDSIZE_WR_SEQ_CTL 35
+        uint16 program[_VP792_CMDSIZE_WR_SEQ_CTL];
+
+        /* Register values are cached here during hook mask and RX-disable
+           intervals: */
+        uint16 lastDsh;
+        uint16 lastVpCfg2;
+
+        bool hookMaskInterval;
+    } sequencer;
+
+    /* State variables for VpSendSignal(): */
+    struct {
+
+        /* Stores the ongoing send signal type (if any), and the one that will
+           be applied when the sequencer becomes available. */
+        VpSendSignalType currentSignal;
+        VpSendSignalType newSignal;
+
+        /* Stores the value that was in the DRIVE_ST variable before the signal
+           started. */
+        uint16 driveSt;
+
+        /* State variables for Vp792SendSignal(VP_SENDSIG_MSG_WAIT_PULSE): */
+        struct {
+            int16 voltage;
+
+            struct {
+                struct {
+                    uint16 v1;
+                    uint16 vas;
+                    uint16 ila;
+                } on;
+                struct {
+                    uint16 v1;
+                    uint16 vas;
+                    uint16 ila;
+                } off;
+
+                uint16 vasOffset;
+                uint16 rfd;
+                uint16 rptc;
+            } dcParams;
+
+            bool readingDcParams;
+            bool aborting;
+
+            uint16 requestIdx;  /* for RD_DC_PARAMS request */
+        } msgWait;
+    } sendSig;
+
+    /* Caller ID state variables */
+    struct {
+
+        /* Currently active Caller ID profile.  This will be the same as
+           profiles.pCidProfile if VpInitRing() was called, but it will be
+           different if VpSendCid() was called. */
+#ifdef VP_COMMON_ADDRESS_SPACE
+        VpProfilePtrType pCidProfile;
+#else
+        uint16 cidProfileValid;
+        VpProfileDataType cidProfile[VP792_CID_PROFILE_LEN];
+#endif
+
+        /* Sending data using FSK or DTMF? */
+        bool isFsk;
+
+        /* FSK data state */
+        struct {
+            /* Whether the API should compute the checksum */
+            bool autoChecksum;
+
+            /* SLAC device buffer status bits */
+            uint8 bufStatus;
+
+            /* Preamble */
+            uint16 seizureBits;
+            uint16 markBits;
+
+            uint8 checksum;
+        } fsk;
+
+        struct {
+            /* Message data buffer */
+            bool nonempty;
+            uint8 buf[VP_SIZEOF_CID_MSG_BUFFER * 2];
+            uint8 head;
+            uint8 tail;
+        } data;
+
+        bool dtmfDetectInterval;
+        uint8 dtmfTones[2];
+    } callerId;
+
+    /* Metering state variables */
+    struct {
+        bool active;
+        uint16 eventRate;
+    } metering;
+} Vp792LineObjectType;
+
+/* Vp792 Group Device Object */
+
+typedef struct
+{
+
+  VpDeviceIdType deviceId;
+
+  /* Temporary storage for interrupt indication, while mailbox is busy. */
+  uint16 intInd[2];
+
+} Vp792GroupDeviceObjectType;
+
+#endif /* VP792_API_H */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp880_api_int.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp880_api_int.h
new file mode 100644
index 0000000..e1f6a2f
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp880_api_int.h
@@ -0,0 +1,1286 @@
+/** \file vp880_api_int.h
+ * vp880_api_int.h
+ *
+ * Header file for the vp880 series API-II c files.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 6680 $
+ * $LastChangedDate: 2010-03-15 16:01:52 -0500 (Mon, 15 Mar 2010) $
+ */
+
+#ifndef VP880_API_INT_H
+#define VP880_API_INT_H
+
+/**< Define the initial hook value to use when determining if the line status
+ * has been changed from initialization. This must be an invalid value to force
+ * a signaling register read for simple polled mode.
+ */
+#define VP880_HOOK_INIT_VAL 0xFF
+
+#define VP880_MAX_RING_DET_PERIOD   (0x3F)
+
+#define VP880_RING_TRIP_DEBOUNCE    (100)
+
+#define VP880_LP_POLREV_DEBOUNCE_TIME     (200)
+
+/**< Use the legacy ringing detection (bypassing the CLARE device) */
+#undef  LEGACY_RINGING_DETECTION
+
+/**< Define the number of charge iterations for the ringing transition */
+#define IN_RUSH_CYCLE_TOTAL 5   /* 5 = normal, 0 to disable the feature */
+#define IN_RUSH_CYCLE_END   1
+
+/**< Define the mask that will report device busy if there is a currently active
+ * event when the user is attempting to perform another "read" transaction.
+ */
+#define VP880_NO_MASK   0x0000
+
+/* Defines for API */
+
+/*
+ * This timer is used by the API Tick counter to prevent Active State
+ * for 100ms after an on-hook transition.
+ */
+#define ON_HOOK_TIMER    20
+#define ON_HOOK_ABS_CLARE_DELAY 2
+
+/**< Revision and Product Code Command info */
+#define VP880_DEVTYPE_RD        0x73
+#define VP880_DEVTYPE_CMD       VP880_DEVTYPE_RD
+#define VP880_DEVTYPE_LEN       0x02    /**< RCN = 1st Byte, PCN = 2nd Byte */
+
+#define VP880_NO_OP_WRT         0x06
+#define VP880_NO_OP             VP880_NO_OP_WRT
+
+#define VP880_REV_VA            0x01
+#define VP880_REV_VC            0x02
+#define VP880_REV_JE            0x04
+
+/**< GLOBAL REGISTERS (Effects all SLAC device channels) */
+#define VP880_HW_RESET_WRT      0x04    /**< Hardware Reset */
+#define VP880_HW_RESET_CMD      VP880_HW_RESET_WRT
+#define VP880_HW_RESET_LEN      0x00
+
+#define VP880_TEST_REG1_WRT     0x30
+#define VP880_TEST_REG1_RD      0x31
+#define VP880_TEST_REG1_LEN     0x01
+#define VP880_TREG1_PLLBYP_MASK 0x80
+#define VP880_TREG1_CSEL_MASK   0x40
+#define VP880_TREG1_TMODE_MASK  0x0F
+
+#define VP880_TEST_REG2_WRT     0x32
+#define VP880_TEST_REG2_RD      0x33
+#define VP880_TEST_REG2_LEN     0x01
+
+/**< Transmit/Receive Clock Slot Command info */
+#define VP880_XR_CS_WRT         0x44    /**< Tx/Rx clock slot register write */
+#define VP880_XR_CS_RD          0x45    /**< Tx/Rx clock slot register read */
+#define VP880_XR_CS_LEN         0x01
+
+#define VP880_TX_CSLOT_WRT      0x44    /**< Tx clock slot register write */
+#define VP880_TX_CSLOT_RD       0x45    /**< Tx clock slot register read */
+#define VP880_TX_CSLOT_LEN      0x01
+
+#define VP880_RX_CSLOT_WRT      0x44    /**< Rx clock slot register write */
+#define VP880_RX_CSLOT_RD       0x45    /**< Rx clock slot register read */
+#define VP880_RX_CSLOT_LEN      0x01
+
+/**< Bit definitions for Transmit/Receive Clock Slot Register */
+#define VP880_TX_SLOT_MASK      0x07
+#define VP880_RX_SLOT_MASK      0x38
+
+/**< Transmit Edge Command info */
+#define VP880_TX_EDGE_WRT       0x44    /**< Tx clock slot register write */
+#define VP880_TX_EDGE_RD        0x45    /**< Tx clock slot register read */
+#define VP880_TX_EDGE_LEN       0x01
+
+/**< Bit definitions for Transmit Edge Register */
+#define VP880_TX_EDGE_MASK      0x40
+
+/**< Device Configuration Command info */
+#define VP880_DCR_WRT           0x46
+#define VP880_DCR_RD            0x47
+#define VP880_DCR_LEN           0x01
+
+/**< Bit definitions for Device Configuration */
+#define VP880_DCR_INTMODE_MASK      0x80
+#define VP880_DCR_DPCLK_MASK        0x40
+#define VP880_DCR_PCM_SMODE_MASK    0x20
+
+/**< Master Clock Command info */
+#define VP880_MCLK_CNT_WRT          0x46
+#define VP880_MCLK_CNT_RD           0x47
+#define VP880_MCLK_CNT_LEN          0x01
+
+/**< Bit definitions for Master Clock Command */
+#define VP880_MCLK_CLKSEL_MASK      0x0F
+
+/**< Operating Mode Command info */
+#define VP880_OP_MODE_WRT           0x4A
+#define VP880_OP_MODE_RD            0x4B
+#define VP880_OP_MODE_LEN           0x01
+
+/**< Bit definitions for Operating Mode Command */
+#define VP880_TEST_MODE_MASK        0x80
+#define VP880_RBE_MODE_MASK         0x40
+#define VP880_WBAND_MODE_MASK       0x20
+#define VP880_DSPBYP_MODE_MASK      0x10
+
+/**< Signaling Register Command info */
+#define VP880_NO_UL_SIGREG_RD       0x4D    /**< Read w/o unlock signaling reg */
+#define VP880_NO_UL_SIGREG_LEN      0x02
+
+#define VP880_UL_SIGREG_RD          0x4F    /**< Read w/unlock signaling reg */
+
+#ifndef VP880_UL_SIGREG_LEN
+#define VP880_UL_SIGREG_LEN         0x02
+#endif
+
+/**< Interrupt Mask Register info */
+#define VP880_INT_MASK_WRT      0x6C
+#define VP880_INT_MASK_RD       0x6D
+#define VP880_INT_MASK_LEN      0x02
+
+/**< Bit definitions for Signaling Register Commands */
+        /**< Byte 1 */
+#define VP880_CFAIL_MASK        0x80
+
+#define VP880_POL1_MASK         0x40
+#define VP880_OCALMY_MASK       0x40
+
+#define VP880_POH1_MASK         0x20
+#define VP880_TEMPA1_MASK       0x20
+
+#define VP880_IO2_1_MASK        0x10
+#define VP880_CAD1_INT_MASK     0x08
+#define VP880_DISC1_MASK        0x04
+#define VP880_CID1_RDY_MASK     0x04
+#define VP880_RING1_DET_MASK    0x02
+#define VP880_GNK1_MASK         0x02
+#define VP880_LIU1_MASK         0x01
+#define VP880_HOOK1_MASK        0x01
+
+        /**< Byte 2 */
+#define VP880_CDAT_MASK         0x80
+#define VP880_POL2_MASK         0x40
+#define VP880_OCALMZ_MASK       0x40
+
+#define VP880_POH2_MASK         0x20
+#define VP880_TEMPA2_MASK       0x20
+
+#define VP880_IO2_2_MASK        0x10
+#define VP880_CAD2_INT_MASK     0x08
+#define VP880_DISC2_MASK        0x04
+#define VP880_CID2_RDY_MASK     0x04
+#define VP880_RING2_DET_MASK    0x02
+#define VP880_GNK2_MASK         0x02
+#define VP880_LIU2_MASK         0x01
+#define VP880_HOOK2_MASK        0x01
+
+/**< Revision and Product Code Command info */
+#define VP880_RCN_PCN_RD        0x73
+#define VP880_RCN_PCN_LEN       0x02    /**< RCN = 1st Byte, PCN = 2nd Byte */
+#define VP880_RCN_LOCATION      0x00
+#define VP880_PCN_LOCATION      0x01
+
+#define VP880_WIDEBAND_MASK     0x01    /**< Wideband if set in PCN */
+#define VP880_CODEC_MASK        0x02    /**< CODEC exists if set in PCN */
+#define VP880_HV_MASK           0x04    /**< HV device if set in PCN */
+#define VP880_TWO_CHAN_MASK     0x80
+
+#define VP880_SLIC_MASK         0x38    /**< Indicates if, and type of SLIC */
+#define VP880_2CH_TRACKER       0x38
+#define VP880_2CH_ABS           0x30
+#define VP880_TRACK_FXS_FXO     0x28
+#define VP880_2CH_FXO           0x20
+#define VP880_ABS_FXS_FXO       0x00
+
+/*
+ * PCN Interpretation:
+ *     SLIC2    = xxx1 xxxx
+ *     SLIC1    = xxxx 1xxx
+ *     HV       = xxxx x1xx
+ *     CODEC    = xxxx xx1x
+ *     WideBand = xxxx xxx1
+ */
+
+#define VP880_IS_IT_WB  (VP880_CODEC_MASK | VP880_WB_MASK)
+
+/**< One Channel Devices */
+#define VP880_FIRST_OF_ONE_CHANNEL_DEVICES  (0x05)
+
+#define VP880_DEV_PCN_88010  (0x06)     /**< FXO */
+#define VP880_DEV_PCN_88111  (0x0A)     /* FXS-Tracker */
+#define VP880_DEV_PCN_88116  (0x0B)     /* FXS-Tracker - Wideband */
+#define VP880_DEV_PCN_88131  (0x0E)     /* FXS-Tracker */
+#define VP880_DEV_PCN_88136  (0x0F)     /* FXS-Tracker - Wideband */
+
+#define VP880_LAST_OF_ONE_CHANNEL_DEVICES  (0x10)
+
+#define VP880_TWO_CHANNNEL_MASK       (0x80)
+#define VP880_TRACKER_MASK            (0x08)
+
+/** Two Channel Devices */
+#define VP880_DEV_PCN_88211     (0xBA)     /* 2FXS-Tracker */
+#define VP880_DEV_PCN_88216     (0xBB)     /* 2FXS-Tracker - Wideband */
+#define VP880_DEV_PCN_88221     (0xB2)     /* 2FXS-ABS */
+#define VP880_DEV_PCN_88226     (0xB3)     /* 2FXS-ABS - Wideband */
+#define VP880_DEV_PCN_88231     (0xBE)     /* 2FXS-Tracker */
+#define VP880_DEV_PCN_88236     (0xBF)     /* 2FXS-Tracker - Wideband */
+
+#define VP880_DEV_PCN_88241     (0xB6)     /* 2FXS-ABS */
+#define VP880_DEV_PCN_88246     (0xB7)     /* 2FXS-ABS - Wideband */
+
+#define VP880_DEV_PCN_88311     (0xAA)     /* FXO/FXS-Tracker */
+#define VP880_DEV_PCN_88331     (0xAE)     /* FXO/FXS-Tracker */
+
+#define VP880_DEV_PCN_88506     (0xBC)     /* 2FXS-Tracker - Wideband Split Package*/
+#define VP880_DEV_PCN_88536     (0xFF)     /* 2FXS-Tracker - Wideband, IP Block */
+
+/**< Internal Revision Command info */
+#define VP880_REV_INFO_RD       0xB9
+#define VP880_REV_INFO_LEN      0x01
+
+/**< Switching Regulator Parameters */
+#define VP880_REGULATOR_PARAM_WRT   0xE4
+#define VP880_REGULATOR_PARAM_RD    0xE5
+
+#ifndef VP880_REGULATOR_PARAM_LEN
+#define VP880_REGULATOR_PARAM_LEN   0x03
+#endif
+
+#define VP880_REGULATOR_TRACK_INDEX     0x00
+#define VP880_REGULATOR_FIXED_RING      0x08
+#define VP880_REGULATOR_INVERT_BOOST    0x20
+
+#define VP880_FLOOR_VOLTAGE_BYTE    0x01
+#define VP880_FLOOR_VOLTAGE_MASK    0x1F
+
+#define VP880_BAT_CALIBRATION_WRT   0xE8
+#define VP880_BAT_CALIBRATION_RD    0xE9
+#define VP880_BAT_CALIBRATION_LEN   0x02
+#define VP880_BAT_CAL_SWCAL_MASK    0x38
+#define VP880_BAT_CAL_SWCAL_SIGN    0x20
+
+#define VP880_CONVERTER_MODE_WRT    0xE4
+#define VP880_CONVERTER_MODE_RD     0xE5
+#define VP880_CONVERTER_MODE_LEN    0x03
+
+/**< Switching Regulator Parameters bit definitions */
+#define VP880_MODE_MASK             0x20
+#define VP880_FLYBACK_MODE          0x00
+#define VP880_BUCKBOOST_MODE        0x20
+
+#define VP880_BSI_MASK              0xC0
+#define VP880_BSI_LY_MX_HZ          0x00
+#define VP880_BSI_LY_MZ_HX          0x40
+#define VP880_BSI_LX_MY_HZ          0x80
+#define VP880_BSI_DEFAULT           VP880_BSI_LY_MX_HZ
+
+#define VP880_ZRING_TRACK_MASK      0x08
+#define VP880_ZRING_TRACK_EN        0x00
+#define VP880_ZRING_TRACK_DIS       0x08
+
+#define VP880_YRING_TRACK_MASK      0x02
+#define VP880_YRING_TRACK_EN        0x00
+#define VP880_YRING_TRACK_DIS       0x02
+
+#define VP880_SWY_AUTOPOWER_INDEX   0x01
+#define VP880_SWY_AUTOPOWER_MASK    0x80
+#define VP880_SWY_AUTOPOWER_EN      0x00
+#define VP880_SWY_AUTOPOWER_DIS     0x80
+
+#define VP880_SWY_V_DIVISOR         1000ul
+#define VP880_SWY_V_STEPSIZE        5025ul  /**< 5.025V/step */
+
+#define VP880_SWZ_AUTOPOWER_INDEX   0x02
+#define VP880_SWZ_AUTOPOWER_MASK    0x80
+#define VP880_SWZ_AUTOPOWER_EN      0x00
+#define VP880_SWZ_AUTOPOWER_DIS     0x80
+
+#define VP880_SWZ_V_DIVISOR         1000ul
+#define VP880_SWZ_V_STEPSIZE        5025ul  /**< 5.025V/step */
+
+#define VP880_VOLTAGE_MASK          0x1F
+#define VP880_SWY_LOCATION          1
+#define VP880_SWZ_LOCATION          2
+#define VP880_VOLTAGE_60V           0x0B
+
+/**< Internal Switching Regulator Parameters Command info */
+#define VP880_INT_SWREG_PARAM_WRT   0xF6
+#define VP880_INT_SWREG_PARAM_RD    0xF7
+
+#ifndef VP880_INT_SWREG_PARAM_LEN
+#define VP880_INT_SWREG_PARAM_LEN   0x06
+#endif
+
+#define VP880_SWREG_RING_V_BYTE     2
+#define VP880_SWREG_FLOOR_V_BYTE    1
+
+/**< Switching Regulator Control Command info */
+#define VP880_REGULATOR_CTRL_WRT    0xE6
+#define VP880_REGULATOR_CTRL_RD     0xE7
+
+#ifndef VP880_REGULATOR_CTRL_LEN
+#define VP880_REGULATOR_CTRL_LEN    0x01
+#endif
+
+/*  Calibration  */
+typedef enum {
+    VP880_NORM_POLARITY,
+    VP880_REV_POLARITY,
+    NUM_POLARITY
+} Vp880CalPolarityType;
+
+#define VP880_VOC_SHIFT_MASK        0x40
+#define VP880_ILA_MASK              0x1F
+#define VP880_ILA_INDEX             0x01
+
+#define VP880_ABV_MASK              0x1F
+#define VP880_VAS_MASK_LO           0x03
+#define VP880_VAS_MASK_HI           0xC0
+
+/**< Switching Regulator Control bit definitions */
+#define VP880_SWY_MODE_MASK         0x03
+#define VP880_SWY_OFF               0x00
+#define VP880_SWY_LP                0x01
+#define VP880_SWY_MP                0x02
+#define VP880_SWY_HP                0x03
+#define VP880_SWYZ_LP               0x05
+
+#define VP880_SWZ_MODE_MASK         0x0C
+#define VP880_SWZ_OFF               0x00
+#define VP880_SWZ_LP                0x04
+#define VP880_SWZ_MP                0x08
+#define VP880_SWZ_HP                0x0C
+
+#define VP880_PWR_SWITCH_DEBOUNCE   (70)
+
+/**< CHANNEL REGISTERS (must set EC register first) */
+
+/**< Channel Enable Command info */
+#define VP880_EC_WRT                0x4A
+#define VP880_EC_RD                 0x4B
+#define VP880_EC_LEN                0x01
+
+#ifndef VP880_EC_CH1
+#define VP880_EC_CH1                0x01
+#define VP880_EC_CH2                0x02
+#endif
+
+#define VP880_EC_STATE_AT_RESET     0x03
+
+/**< Bit definitions for Channel Enable Command */
+#define VP880_EC_BITS_MASK          0x03
+
+#define VP880_DSP_BYPASS            0x10
+#define VP880_WIDEBAND_MODE         0x20
+#define VP880_TEST_MODE_ENABLE      0x80
+
+/**< Voice Path Gain Command info */
+#define VP880_VP_GAIN_WRT           0x50
+#define VP880_VP_GAIN_RD            0x51
+#define VP880_VP_GAIN_LEN           0x01
+#define VP880_DEFAULT_VP_GAIN       0x00
+
+/**< Bit definitions for Voice Path Gain Commands */
+#define VP880_AX_MASK           0x40
+#define VP880_AR_MASK           0x30
+#define VP880_AR_0DB_LOSS       0x00
+#define VP880_AR_6DB_LOSS       0x10
+#define VP880_AR_6DB_GAIN       0x20
+#define VP880_AR_RSVD1          0x30
+#define VP880_DR_LOSS_MASK      0x08    /**< Digital Receive Loss = 0dB (0) or
+                                         * 6.02dB (1)
+                                         */
+
+/**< IO Data Command info */
+#define VP880_IODATA_REG_WRT    0x52    /**< I/O register write */
+#define VP880_IODATA_REG_RD     0x53    /**< I/O register read */
+#define VP880_IODATA_REG_LEN    0x01
+#define VP880_IODATA_IO6        0x20
+#define VP880_IODATA_IO5        0x10
+#define VP880_IODATA_IO4        0x08
+#define VP880_IODATA_IO3        0x04
+#define VP880_IODATA_IO2        0x02
+#define VP880_IODATA_IO1        0x01
+
+/**< Bit definitions for IO Data Command */
+#define VP880_IODATA_BITS_MASK  0x3F    /**< Lowest two bits always available */
+
+/**< IO Direction Command info */
+#define VP880_IODIR_REG_WRT     0x54    /**< I/O direction register write */
+#define VP880_IODIR_REG_RD      0x55    /**< I/O direction register read */
+#define VP880_IODIR_REG_LEN     0x01
+
+/**< Bit definitions for IO Direction Command */
+#define VP880_MAX_PINS_PER_LINE (6)
+
+#define VP880_IODIR_IO11_MASK   0x01
+#define VP880_IODIR_IO12_MASK   0x02
+#define VP880_IODIR_IO1_MASK    0x03
+#define VP880_IODIR_IO2_MASK    0x04
+#define VP880_IODIR_IO3_MASK    0x08
+#define VP880_IODIR_IO4_MASK    0x10
+#define VP880_IODIR_IO5_MASK    0x20
+#define VP880_IODIR_IO6_MASK    0x40
+#define VP880_IODIR_EXPDT_MASK  0x80    /**< External Period detector connected
+                                         * to IO4
+                                         */
+
+#define VP880_IODIR_IO1_INPUT       0x00
+#define VP880_IODIR_IO1_OUTPUT      0x01
+#define VP880_IODIR_IO1_OPEN_DRAIN  0x02
+
+#define VP880_IODIR_IO2_OUTPUT      0x04
+#define VP880_IODIR_IO3_OUTPUT      0x08
+#define VP880_IODIR_IO4_OUTPUT      0x10
+#define VP880_IODIR_IO5_OUTPUT      0x20
+#define VP880_IODIR_IO6_OUTPUT      0x40
+
+/**< System State Command info */
+#define VP880_SYS_STATE_WRT     0x56
+#define VP880_SYS_STATE_RD      0x57
+#define VP880_SYS_STATE_LEN     0x01
+
+#define VP880_SLIC_STATE_WRT    VP880_SYS_STATE_WRT
+#define VP880_SLIC_STATE_RD     VP880_SYS_STATE_RD
+#define VP880_SLIC_STATE_LEN    VP880_SYS_STATE_LEN
+
+/**< Command (bit) definitions for FXS System State */
+#define VP880_SS_RING_EXIT_MASK     0x80
+#define VP880_SS_METERING_MASK      0x40
+#define VP880_SS_ACTIVATE_MASK      0x20    /**< (1) = CODEC Active, (0) =
+                                             * Deactive
+                                             */
+
+#define VP880_SS_POLARITY_MASK      0x10    /**< (0) = Normal, (1) = Reverse */
+#define VP880_SS_STATE_MASK         0x3F
+#define VP880_SS_LINE_FEED_MASK     0x0F
+
+#define VP880_SS_DISCONNECT         0x00
+#define VP880_SS_TIP_OPEN           0x01
+#define VP880_SS_RING_OPEN          0x02
+#define VP880_SS_ACTIVE             (0x03 | VP880_SS_ACTIVATE_MASK)
+
+#define VP880_SS_ACTIVE_POLREV      (0x03 | VP880_SS_ACTIVATE_MASK \
+                                          | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_IDLE               0x04
+#define VP880_SS_IDLE_POLREV        (0x04 | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_FEED_BALANCED_RINGING      0x07
+#define VP880_SS_FEED_UNBALANCED_RINGING    0x0A
+
+#define VP880_SS_LONGITUDINAL_TEST  (0x05 | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_METALLIC_TEST      (0x06 | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_BALANCED_RINGING   (VP880_SS_FEED_BALANCED_RINGING | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_LOW_GAIN           (0x08 | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_RSVD_0             (0x09 | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_UNBALANCED_RINGING (VP880_SS_FEED_UNBALANCED_RINGING | VP880_SS_ACTIVATE_MASK)
+
+#define VP880_SS_BALANCED_RINGING_PR    (VP880_SS_BALANCED_RINGING \
+                                       | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_UNBALANCED_RINGING_PR  (VP880_SS_UNBALANCED_RINGING \
+                                       | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_ACTIVE_MID_BAT     (0x0B | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_ACTIVE_MID_BAT_PR  (VP880_SS_ACTIVE_MID_BAT \
+                                    | VP880_SS_POLARITY_MASK)
+
+#define VP880_SS_SHUTDOWN        0x0F
+
+#define VP880_SS_RSVD_1             (0x0C | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_RSVD_2             (0x0D | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_RSVD_3             (0x0E | VP880_SS_ACTIVATE_MASK)
+#define VP880_SS_RSVD_4             (0x0F | VP880_SS_ACTIVATE_MASK)
+
+/**< FXO State controlled by General Purpose I/O */
+#define VP880_FXO_STATE_WRT    0x52
+#define VP880_FXO_STATE_RD     0x53
+#define VP880_FXO_STATE_LEN    0x01
+
+#define VP880_FXO_ACTIVATE_CODEC  0x20
+#define VP880_FXO_SUPERVISION_EN  0x09
+
+#define VP880_SS_FXO_OHT             0x00  /**< I/O-1 = Low, I/O-2 = Low */
+#define VP880_SS_FXO_LOOP_CLOSED     0x01  /**< I/O-1 = High, I/O-2 = Low */
+#define VP880_SS_FXO_LOOP_OPEN       0x02  /**< I/O-1 = Low, I/O-2 = High */
+
+/**< Command (bit) definitions for FX0 System State */
+#define VP880_SS_SHUTDOWN_MASK      0x00
+#define VP880_SS_DEACTIVATED_MASK   0x09
+#define VP880_SS_ACTIVATED_MASK     0x29
+
+/**< Operating Functions Command info */
+#define VP880_OP_FUNC_WRT       0x60
+#define VP880_OP_FUNC_RD        0x61
+
+#ifndef VP880_OP_FUNC_LEN
+#define VP880_OP_FUNC_LEN       0x01
+#endif
+
+/**< Bit definitions for Operating Functions Command */
+#define VP880_ENABLE_GR     0x20
+#define VP880_ENABLE_GX     0x10
+#define VP880_ENABLE_X      0x08
+#define VP880_ENABLE_R      0x04
+#define VP880_ENABLE_Z      0x02
+#define VP880_ENABLE_B      0x01
+#define VP880_ENABLE_LOADED_COEFFICIENTS 0x3F
+
+#define VP880_DEFAULT_OP_FUNC_MODE 0x00
+
+/**< Codec Compression Command info (Operating Functions) */
+#define VP880_CODEC_REG_WRT     0x60
+#define VP880_CODEC_REG_RD      0x61
+#define VP880_CODEC_REG_LEN     0x01
+
+/**< Bit definitions for Codec Compression Command */
+
+/* Note:  If Linear Mode is selected, u-Law/A-Law selection is ignored */
+#define VP880_CODEC_COMPRESSION_MASK    0xC0
+#define VP880_ALAW_CODEC        0x00    /**< a-Law compression is used */
+#define VP880_ULAW_CODEC        0x40    /**< u-law compression is used */
+#define VP880_LINEAR_CODEC      0x80    /**< Linear mode is used */
+
+/**< System State Configuration Command info */
+#define VP880_SS_CONFIG_WRT     0x68
+#define VP880_SS_CONFIG_RD      0x69
+#define VP880_SS_CONFIG_LEN     0x01
+
+/*< Automatic Clock Fault Switching */
+#define VP880_ACFS_MASK     0x20
+#define VP880_ACFS_EN       0x20
+#define VP880_ACFS_DIS      0x00
+
+/**< Bit definitions for System State Configuration Command */
+/**< Auto Thermal Fault Switching */
+#define VP880_ATFS_MASK     0x10
+#define VP880_ATFS_EN       0x10
+#define VP880_ATFS_DIS      0x00
+
+/**< Zero Cross Ring Entry/Exit */
+#define VP880_ZXR_MASK      0x08
+#define VP880_ZXR_EN        0x00
+#define VP880_ZXR_DIS       0x08
+
+/**< Smooth Polarity Reversal */
+#define VP880_SMOOTH_PR_MASK    0x04
+#define VP880_SMOOTH_PR_EN      0x04
+#define VP880_SMOOTH_PR_DIS     0x00
+
+/**< Automatic System State Control */
+#define VP880_AUTO_SSC      0x02
+#define VP880_AUTO_SSC_EN   0x00
+#define VP880_AUTO_SSC_DIS  0x02
+
+/**< Automatic Battery Switch Control for ABS */
+#define VP880_ABS                       0x01
+#define VP880_AUTO_BAT_SWITCH_DIS       0x01
+#define VP880_AUTO_BAT_SWITCH_EN        0x00
+
+/**< Automatic Battery Shutdown for Tracker */
+#define VP880_AUTO_BAT_SHUTDOWN_EN      0x01
+#define VP880_AUTO_BAT_SHUTDOWN_DIS     0x00
+
+/**< Operating Conditions Command info */
+#define VP880_OP_COND_WRT         0x70
+#define VP880_OP_COND_RD          0x71
+
+#ifndef VP880_OP_COND_LEN
+#define VP880_OP_COND_LEN         0x01
+#endif
+
+/**< Map the loop back register to operating conditions register */
+#define VP880_LOOPBACK_WRT        VP880_OP_COND_WRT
+#define VP880_LOOPBACK_RD         VP880_OP_COND_RD
+#define VP880_LOOPBACK_LEN        VP880_OP_COND_LEN
+
+/**< Bit definitions for Operating Conditions Command */
+#define VP880_TX_PATH_MASK      0x80
+#define VP880_CUT_TXPATH        0x80
+#define VP880_TXPATH_EN         0x00
+#define VP880_TXPATH_DIS        0x80
+
+#define VP880_RX_PATH_MASK      0x40
+#define VP880_CUT_RXPATH        0x40
+#define VP880_RXPATH_EN         0x00
+#define VP880_RXPATH_DIS        0x40
+
+#define VP880_HIGH_PASS_MASK    0x20
+#define VP880_HIGH_PASS_EN      0x00
+#define VP880_HIGH_PASS_DIS     0x20
+
+#define VP880_LOWER_RX_GAIN_MASK    0x10
+#define VP880_RX_GAIN_6DB_LOSS      0x10
+#define VP880_RX_GAIN_0DB_LOSS      0x00
+
+#define VP880_INTERFACE_LOOPBACK_EN 0x04
+#define VP880_1KHZ_TONE_ON          0x01
+
+#define VP880_OPCOND_RSVD_MASK      (0x0A | VP880_1KHZ_TONE_ON)
+#define VP880_NORMAL_OP_COND_MODE   0x00
+
+/**< GX Filter Command info */
+#define VP880_GX_GAIN_WRT       0x80
+#define VP880_GX_GAIN_RD        0x81
+#define VP880_GX_GAIN_LEN       0x02
+
+/**< GR Filter Command info */
+#define VP880_GR_GAIN_WRT       0x82
+#define VP880_GR_GAIN_RD        0x83
+#define VP880_GR_GAIN_LEN       0x02
+
+/**< B Filter (FIR) Coefficients */
+#define VP880_B1_FILTER_WRT     0x86
+#define VP880_B1_FILTER_RD      0x87
+#define VP880_B1_FILTER_LEN     0x0E
+
+/**< B Filter (IIR) Coefficients */
+#define VP880_B2_FILTER_WRT     0x96
+#define VP880_B2_FILTER_RD      0x97
+#define VP880_B2_FILTER_LEN     0x02
+
+/**< X Filter Coefficients */
+#define VP880_X_FILTER_WRT      0x88
+#define VP880_X_FILTER_RD       0x89
+#define VP880_X_FILTER_LEN      0x0C
+
+/**< R Filter Coefficients */
+#define VP880_R_FILTER_WRT      0x8A
+#define VP880_R_FILTER_RD       0x8B
+#define VP880_R_FILTER_LEN      0x0E
+
+/**< Z Filter (FIR) Coefficients */
+#define VP880_Z1_FILTER_WRT     0x98
+#define VP880_Z1_FILTER_RD      0x99
+#define VP880_Z1_FILTER_LEN     0x0A
+
+/**< Z Filter (IIR) Coefficients */
+#define VP880_Z2_FILTER_WRT     0x9A
+#define VP880_Z2_FILTER_RD      0x9B
+#define VP880_Z2_FILTER_LEN     0x05
+
+/**< Converter Configuration */
+#define VP880_CONV_CFG_WRT      0xA6
+#define VP880_CONV_CFG_RD       0xA7
+
+#ifndef VP880_CONV_CFG_LEN
+#define VP880_CONV_CFG_LEN      0x01
+#endif
+
+/**< Converter Configuration bit definitions */
+#define VP880_CONV_CONNECT_BITS 0x0F
+#define VP880_METALLIC_AC_V     0x00
+#define VP880_SWITCHER_Y        0x01
+#define VP880_SWITCHER_Z        0x02
+#define VP880_XBR               0x03
+#define VP880_TIP_TO_GND_V      0x04
+#define VP880_RING_TO_GND_V     0x05
+#define VP880_METALLIC_DC_V     0x06
+#define VP880_METALLIC_DC_I     0x07
+#define VP880_LONGITUDINAL_DC_I 0x08
+#define VP880_CALIBRATION_I     0x09
+#define VP880_VOICE_DAC         0x0A
+#define VP880_NO_CONNECT        0x0B
+#define VP880_CC_RSVD1          0x0C
+#define VP880_LOW_TIP_TO_GND_V  0x0D
+#define VP880_LOW_RING_TO_GND_V 0x0E
+#define VP880_CC_RSVD2          0x0F
+#define VP880_CC_RATE_MASK      0x70
+#define VP880_CC_500HZ_RATE     0x40
+#define VP880_CC_1KHZ_RATE      0x30
+#define VP880_CC_2KHZ_RATE      0x20
+#define VP880_CC_4KHZ_RATE      0x10
+#define VP880_CC_8KHZ_RATE      0x00
+#define VP880_CC_RATE_BITS      0x70
+
+#define VP880_ILA_SCALE_1MA     (568)
+#define VP880_ILA_SCALE_2MA     (2 * VP880_ILA_SCALE_1MA)
+#define VP880_ILA_SCALE_18MA    (9 * VP880_ILA_SCALE_2MA)
+
+/**< Loop Supervision Command info */
+#define VP880_LOOP_SUP_WRT      0xC2
+#define VP880_LOOP_SUP_RD       0xC3
+
+#ifndef VP880_LOOP_SUP_LEN
+#define VP880_LOOP_SUP_LEN      0x04
+#endif
+
+#define VP880_LIU_DBNC_INDEX    0x01
+#define VP880_LIU_DBNC_MASK     0x1F
+
+#define VP880_RING_PERIOD_MIN_INDEX     0x02
+#define VP880_RING_PERIOD_1MS           0x04
+
+#define VP880_LOOP_SUP_RT_MODE_BYTE 0x02
+
+#define VP880_LOOP_SUP_LIU_THRESH_BYTE  0x00
+#define VP880_LOOP_SUP_LIU_THRESH_BITS  0x07
+#define VP880_LOOP_SUP_LIU_16V          0x00
+
+/**< Usefull variables and bit definitions for Loop Supervision */
+#define VP880_LOOPSUP_CUR_DIVISOR     1ul
+#define VP880_LOOPSUP_CUR_STEPSIZE    1ul
+
+#define VP880_LOOPSUP_TSH_DIVISOR     VP880_LOOPSUP_CUR_DIVISOR
+#define VP880_LOOPSUP_TSH_STEPSIZE    VP880_LOOPSUP_CUR_STEPSIZE
+
+#define VP880_LOOPSUP_TGK_DIVISOR     1ul
+#define VP880_LOOPSUP_TGK_STEPSIZE    3ul
+
+#define VP880_LOOPSUP_DGK_DIVISOR     1ul
+#define VP880_LOOPSUP_DGK_STEPSIZE    4ul
+
+#define VP880_LOOPSUP_DSH_DIVISOR     1ul
+#define VP880_LOOPSUP_DSH_STEPSIZE    2ul
+
+#define VP880_LOOPSUP_RTTH_DIVISOR    10ul
+#define VP880_LOOPSUP_RTTH_STEPSIZE   5ul
+
+#define VP880_LOOPSUP_IRL_DIVISOR     1ul
+#define VP880_LOOPSUP_IRL_STEPSIZE    2ul
+
+#define VP880_LOOPSUP_TDIS_DIVISOR    10ul
+#define VP880_LOOPSUP_TDIS_STEPSIZE   14ul
+
+#define VP880_LOOPSUP_TLIU_DIVISOR    1ul
+#define VP880_LOOPSUP_TLIU_STEPSIZE   11ul
+
+#define VP880_LOOPSUP_DDIS_DIVISOR    1ul
+#define VP880_LOOPSUP_DDIS_STEPSIZE   4ul
+
+#define VP880_LOOPSUP_DLIU_DIVISOR    1ul
+#define VP880_LOOPSUP_DLIU_STEPSIZE   2ul
+
+#define VP880_LOOPSUP_TMIN_DIVISOR    100ul
+#define VP880_LOOPSUP_TMIN_STEPSIZE   25ul
+
+#define VP880_LOOPSUP_TMAX_DIVISOR    100ul
+#define VP880_LOOPSUP_TMAX_STEPSIZE   25ul
+
+/**< Command to control how Ring Trip will work */
+#define VP880_RINGTRIP_MODE_WRT     0xC2
+#define VP880_RINGTRIP_MODE_RD      0xC3
+#define VP880_RINGTRIP_MODE_LEN     0x04
+
+/**< Bit definitions for Ring Trip Control (AC or DC) */
+#define VP880_RING_TRIP_DC      0x00
+#define VP880_RING_TRIP_AC      0x80
+
+#define VP880_RING_DETECT_PERIOD_ONLY   0x80
+
+/**< DC Feed Command info */
+#define VP880_DC_FEED_WRT    0xC6
+#define VP880_DC_FEED_RD     0xC7
+
+#ifndef VP880_DC_FEED_LEN
+#define VP880_DC_FEED_LEN    0x02
+#endif
+#define VP880_DC_CAL_VOC_DIS        0x10
+
+/* Position in DC Profile specifying VOC and ILA */
+#define VP880_VOC_PROFILE_POSITION 12
+#define VP880_ILA_PROFILE_POSITION 13
+#define VP880_HOOK_HYST_POSITION   14
+
+/**< Usefull variables and bit definitions for DC Feed */
+#define VP880_LONG_IMP_MASK     0x20
+#define VP880_LONG_IMP_50       0x20
+#define VP880_LONG_IMP_100      0x00
+
+/* First Byte */
+#define VP880_VOC_LOW_RANGE     0x40
+#define VP880_VOC_MASK          0x1C    /* 0x40 is Range (36-57, 12-33) bit */
+#define VP880_VOC_VALUE_MASK    (VP880_VOC_MASK | VP880_VOC_LOW_RANGE)
+#define VP880_VOC_57V           0x1C
+#define VP880_VOC_54V           0x18
+#define VP880_VOC_51V           0x14
+#define VP880_VOC_48V           0x10
+#define VP880_VOC_45V           0x0C
+#define VP880_VOC_42V           0x08
+#define VP880_VOC_39V           0x04
+#define VP880_VOC_36V           0x00
+
+#define VP880_VAS_MSB_LOC       0x00
+#define VP880_VAS_MSB_MASK      0x03
+
+#define VP880_VAS_LSB_LOC       0x01
+#define VP880_VAS_LSB_MASK      0xC0
+
+#define VP880_VAS_CONVERSION(msb, lsb)  (750*(((msb << 2) & 0xC) | ((lsb >> 6) & 0x3))+3000)
+
+/**< Digital Impedance Scaling Command info */
+#define VP880_DISN_WRT  0xCA
+#define VP880_DISN_RD   0xCB
+#define VP880_DISN_LEN  0x01
+
+#define VP880_DEFAULT_DISN_GAIN 0x00
+
+/**< Usefull variables and bit definitions for DISN */
+#define VP880_DISN_DIVISOR      10000ul
+#define VP880_DISN_STEPSIZE     78ul
+
+/**< Read Transmit PCM/Test Data Command info */
+#define VP880_TX_PCM_DATA_RD        0xCD
+#define VP880_TX_PCM_DATA_LEN       0x02
+
+/**< Read Transmit PCM/Test Buffer Command info */
+#define VP880_TX_PCM_BUFF_RD        0xCF
+#define VP880_TX_PCM_BUFF_LEN       0x0E
+
+#define VP880_TX_BUF_LEN_MASK           0x70
+#define VP880_TX_BUF_LEN_INDEX          0
+#define VP880_TX_BUF_HOOK_MSB_MASK      0x0F
+#define VP880_TX_BUF_HOOK_MSB_INDEX     0
+#define VP880_TX_BUF_HOOK_LSB_MASK      0xFF
+#define VP880_TX_BUF_HOOK_LSB_INDEX     1
+#define VP880_TX_BUF_HOOK_CHAN1_MASK    0x3F
+#define VP880_TX_BUF_HOOK_CHAN2_MASK    0xC0
+
+/**< Device Mode Command info */
+#define VP880_DEV_MODE_WRT          0x5E
+#define VP880_DEV_MODE_RD           0x5F
+#define VP880_DEV_MODE_LEN          0x01
+
+#define VP880_DEV_MODE_TEST_DATA    0x01
+#define VP880_DEV_MODE_CHAN_MASK    0x02
+#define VP880_DEV_MODE_CHAN0_SEL    0x00
+#define VP880_DEV_MODE_CHAN1_SEL    0x02
+
+/**< Metering Parameters Command info */
+#define VP880_METERING_PARAM_WRT    0xD0
+#define VP880_METERING_PARAM_RD     0xD1
+#define VP880_METERING_PARAM_LEN    0x04
+
+/**< Metering Parameters bit definitions */
+#define VP880_METERING_FREQ_MASK    0x80
+#define VP880_METERING_FREQ_12K     0x00
+#define VP880_METERING_FREQ_16K     0x80
+
+#define VP880_METERING_LIM_MASK     0x7F
+#define VP880_METER_LIM_DIVISOR     1000ul
+#define VP880_METER_LIM_STEPSIZE    15ul    /**< 15mV @ 12Khz, 18mV @ 16KHz */
+
+#define VP880_METERING_RAMP_MASK    0x80
+#define VP880_METERING_RAMP_SMOOTH  0x00
+#define VP880_METERING_RAMP_ABRUPT  0x80
+
+#define VP880_METERING_SLOPE_MASK       0x7F
+#define VP880_METERING_SLOPE_DIVISOR    1000ul
+#define VP880_METERING_SLOPE_STEPSIZE   68ul    /**< 68uA/step */
+
+#define VP880_METERING_TIME_DIVISOR     10000ul
+#define VP880_METERING_TIME_STEPSIZE    25ul    /**< 2.5mS/step */
+
+#define VP880_METERING_PEAK_DIVISOR     100000ul
+#define VP880_METERING_PEAK_STEPSIZE    78125ul /**< 7.8125mV/step */
+
+/**< Signal Generator A, B, and Bias Command info */
+#define VP880_SIGA_PARAMS_WRT       0xD2
+#define VP880_SIGA_PARAMS_RD        0xD3
+
+#ifndef VP880_SIGA_PARAMS_LEN
+#define VP880_SIGA_PARAMS_LEN       0x0B
+#endif
+
+#define VP880_SIGB_PARAMS_WRT       VP880_SIGA_PARAMS_WRT
+#define VP880_SIGB_PARAMS_RD        VP880_SIGA_PARAMS_RD
+#define VP880_SIGB_PARAMS_LEN       VP880_SIGA_PARAMS_LEN
+
+#define VP880_SIGAB_PARAMS_WRT      VP880_SIGA_PARAMS_WRT
+#define VP880_SIGAB_PARAMS_RD       VP880_SIGA_PARAMS_RD
+#define VP880_SIGAB_PARAMS_LEN      VP880_SIGA_PARAMS_LEN
+
+#define VP880_RINGER_PARAMS_WRT     VP880_SIGA_PARAMS_WRT
+#define VP880_RINGER_PARAMS_RD      VP880_SIGA_PARAMS_RD
+#define VP880_RINGER_PARAMS_LEN     VP880_SIGA_PARAMS_LEN
+
+/* Map of the Signal Generator A/B Byte Locations */
+#define VP880_SIGA_BIAS_MSB         0x01
+#define VP880_SIGA_BIAS_LSB         0x02
+#define VP880_SIGA_FREQ_MSB         0x03
+#define VP880_SIGA_FREQ_LSB         0x04
+#define VP880_SIGA_AMP_MSB          0x05
+#define VP880_SIGA_AMP_LSB          0x06
+#define VP880_SIGB_FREQ_MSB         0x07
+#define VP880_SIGB_FREQ_LSB         0x08
+#define VP880_SIGB_AMP_MSB          0x09
+#define VP880_SIGB_AMP_LSB          0x0A
+
+#define VP880_RINGING_AMP_SCALE     473
+#define VP880_RINGING_AMP_FACTOR    100000
+
+#define VP880_RINGING_BIAS_SCALE    473
+#define VP880_RINGING_BIAS_FACTOR   100000
+
+
+/**< Signal Generator bit definitions */
+#define VP880_RAMP_SLOPE_MASK   0x04
+#define VP880_RAMP_POSITIVE     0x00
+#define VP880_RAMP_NEGATIVE     0x04
+
+#define VP880_SIGGEN1_OP_MASK   0x02
+#define VP880_SIGGEN1_OUT_RAMP  0x02
+#define VP880_SIGGEN1_OUT_CONT  0x00
+
+#define VP880_SIGGEN1_SINTRAP_MASK  0x01
+#define VP880_SIGGEN1_SIN           0x00
+#define VP880_SIGGEN1_TRAP          0x01
+
+#define VP880_GENA_FREQ_DIVISOR     1000ul
+#define VP880_GENA_FREQ_STEPSIZE    366ul   /**< 0.366Hz/step */
+
+#define VP880_GENA_AMP_DIVISOR      100ul
+#define VP880_GENA_AMP_STEPSIZE     471ul   /**< 4.71mV/step in Ringing Mode */
+
+#define VP880_GENB_FREQ_DIVISOR     1000ul
+#define VP880_GENB_FREQ_STEPSIZE    366ul   /**< 0.366Hz/step */
+
+/**< Signal Generator C and D Command info */
+#define VP880_SIGC_PARAMS_WRT       0xD4
+#define VP880_SIGC_PARAMS_RD        0xD5
+#define VP880_SIGC_PARAMS_LEN       0x08
+
+#define VP880_SIGD_PARAMS_WRT       0xD4
+#define VP880_SIGD_PARAMS_RD        0xD5
+#define VP880_SIGD_PARAMS_LEN       0x08
+
+#define VP880_SIGCD_PARAMS_WRT      0xD4
+#define VP880_SIGCD_PARAMS_RD       0xD5
+#define VP880_SIGCD_PARAMS_LEN      0x08
+
+/**< Signal Generator C/D bit definitions */
+#define VP880_GENC_FREQ_DIVISOR     1000ul
+#define VP880_GENC_FREQ_STEPSIZE    366ul   /**< 0.366Hz/step */
+
+#define VP880_GEND_FREQ_DIVISOR     1000ul
+#define VP880_GEND_FREQ_STEPSIZE    366ul   /**< 0.366Hz/step */
+
+/**< Signal Generator Control Command */
+#define VP880_GEN_CTRL_WRT      0xDE
+#define VP880_GEN_CTRL_RD       0xDF
+#define VP880_GEN_CTRL_LEN      0x01
+
+#define VP880_GEND_EN           0x08
+#define VP880_GENC_EN           0x04
+#define VP880_GENB_EN           0x02
+#define VP880_GENA_EN           0x01
+
+#define VP880_GEN_ALLOFF        0x00
+#define VP880_GEN_ALLON         0x0F
+
+/**< Signal Generator Control bit definitions */
+#define VP880_GEN_CAD_EN        0x80
+#define VP880_GEN_CAD_DIS       0x00
+
+#define VP880_GEN_CTRL_CONT     0x00
+#define VP880_GEN_CTRL_OS       0x40
+
+#define VP880_GEN_CTRL_DPGEN_EN     0x20
+#define VP880_GEN_CTRL_DPGEN_DIS    0x00
+
+#define VP880_GEN_CTRL_EN_BIAS  0x10
+#define VP880_GEN_CTRL_DIS_BIAS 0x00
+
+#define VP880_GEN_CTRL_EN_D     0x08
+#define VP880_GEN_CTRL_DIS_D    0x00
+
+#define VP880_GEN_CTRL_EN_C     0x04
+#define VP880_GEN_CTRL_DIS_C    0x00
+
+#define VP880_GEN_CTRL_EN_B     0x02
+#define VP880_GEN_CTRL_DIS_B    0x00
+
+#define VP880_GEN_CTRL_EN_A     0x01
+#define VP880_GEN_CTRL_DIS_A    0x00
+
+/**< Cadence Timer Command */
+#define VP880_CADENCE_TIMER_WRT     0xE0
+#define VP880_CADENCE_TIMER_RD      0xE1
+#define VP880_CADENCE_TIMER_LEN     0x04
+
+/**< Cadence Timer bit definitions */
+#define VP880_CADENCE_ON_DIVISOR    1ul
+#define VP880_CADENCE_ON_STEPSIZE   5ul /**< 5mS/step */
+
+#define VP880_CADENCE_OFF_DIVISOR   1ul
+#define VP880_CADENCE_OFF_STEPSIZE  5ul /**< 5mS/step */
+
+/**< Caller ID Data Command info */
+#define VP880_CID_DATA_WRT      0xE2
+#define VP880_CID_DATA_RD       0xE3
+#define VP880_CID_DATA_LEN      0x01
+
+/**< Caller ID Parameters Command info */
+#define VP880_CID_PARAM_WRT     0xEA
+#define VP880_CID_PARAM_RD      0xEB
+#define VP880_CID_PARAM_LEN     0x01
+
+/**< Caller ID Parameters bit definitions */
+#define VP880_CID_STATE_MASK    0xE0
+#define VP880_CID_STATE_IDLE    0x00
+#define VP880_CID_STATE_RDY     0x20
+#define VP880_CID_STATE_FULL    0x40
+#define VP880_CID_STATE_LBYTE   0x60
+#define VP880_CID_STATE_L2BYTE  0x80
+#define VP880_CID_STATE_URUN    0xA0
+
+/* New CID States for Rev D Silicon */
+#define VP880_CID_STATE_EMPTY_D     0x20
+#define VP880_CID_STATE_HALF_FULL_D 0x40
+#define VP880_CID_STATE_LBYTE_D     0x60
+#define VP880_CID_STATE_L2BYTE_D    0x80
+#define VP880_CID_STATE_FULL_D      0xC0
+#define VP880_CID_STATE_L3BYTE_D    0xE0
+
+#define VP880_CID_EOM_MASK      0x10
+#define VP880_CID_EOM           0x10
+#define VP880_CID_NEOM          0x00
+
+#define VP880_CID_FBDIS_MASK    0x08
+#define VP880_CID_FBIT_DIS      0x08
+#define VP880_CID_FBIT_EN       0x00
+
+#define VP880_CID_FB_START_MASK 0x04
+#define VP880_CID_FB_START_0    0x00
+#define VP880_CID_FB_START_1    0x04
+
+#define VP880_CID_FB_STOP_MASK  0x02
+#define VP880_CID_FB_STOP_0     0x00
+#define VP880_CID_FB_STOP_1     0x02
+
+#define VP880_CID_FRAME_BITS    0x06
+
+#define VP880_CID_CTRL_MASK     0x01
+#define VP880_CID_EN            0x00
+#define VP880_CID_DIS           0x01
+
+/**< Software Reset Command info */
+#define VP880_SW_RESET_WRT      0x02    /**< Software reset */
+#define VP880_SW_RESET_LEN      0x00
+
+/**< Pulse Period Detector Command info */
+#define VP880_PERIOD_DET_RD     0x1F
+#define VP880_PERIOD_DET_LEN    0x01    /**< Time between successive pulses */
+
+/**< Pulse Period Detector bit definitions */
+#define VP880_PULSE_PERIOD_DIVISOR      100ul
+#define VP880_PULSE_PERIOD_STEPSIZE     25ul    /**< 0.25mS/step */
+
+/**< Transmit and Receiver Timeslot Command info */
+#define VP880_TX_TS_WRT         0x40    /**< Transmit time slot write */
+#define VP880_TX_TS_RD          0x41    /**< Transmit time slot read */
+#define VP880_TX_TS_LEN         0x01
+#define VP880_TX_TS_MASK        0x7F
+
+#define VP880_RX_TS_WRT         0x42    /**< Receive time slot write */
+#define VP880_RX_TS_RD          0x43    /**< Receive time slot read */
+#define VP880_RX_TS_LEN         0x01
+#define VP880_RX_TS_MASK        0x7F
+
+/**< Internal Configuration Register 1 */
+#define VP880_ICR1_WRT      0xEC
+#define VP880_ICR1_RD       0xED
+
+#ifndef VP880_ICR1_LEN
+#define VP880_ICR1_LEN      0x04
+#endif
+
+#define VP880_ICR1_BIAS_OVERRIDE_LOCATION   0x00
+#define VP880_ICR1_TIP_BIAS_OVERRIDE        0xF0
+#define VP880_ICR1_LINE_BIAS_OVERRIDE       0x0F
+#define VP880_ICR1_LINE_BIAS_OVERRIDE_NORM  0x08
+
+#define VP880_ICR1_LINE_BIAS_LOCATION       0x01
+#define VP880_ICR1_LINE_BIAS                0x0F
+#define VP880_ICR1_TIP_BIAS_LOCATION        0x01
+#define VP880_ICR1_TIP_BIAS                 0xF0
+
+#define VP880_ICR1_RING_BIAS_OVERRIDE_LOCATION  0x02
+#define VP880_ICR1_RING_BIAS_OVERRIDE           0x0F
+
+#define VP880_ICR1_RING_AND_DAC_LOCATION    0x02
+#define VP880_ICR1_RING_AND_DAC_B2_3        0x06
+#define VP880_ICR1_RING_BIAS_DAC_MASK       0x0C
+
+#define VP880_ICR1_RING_BIAS_LOCATION       0x03
+#define VP880_ICR1_RING_BIAS                0x0F
+
+#define VP880_ICR1_TEST_LOAD_LOCATION       0x03
+#define VP880_ICR1_TEST_LOAD_MASK           0xC0
+#define VP880_ICR1_TEST_LOAD_NONE           0x00
+#define VP880_ICR1_TEST_LOAD_METALLIC       0x40
+#define VP880_ICR1_TEST_LOAD_LONGITUDINAL   0x80
+
+/**< Internal Configuration Register 2 */
+#define VP880_ICR2_WRT      0xEE
+#define VP880_ICR2_RD       0xEF
+
+#ifndef VP880_ICR2_LEN
+#define VP880_ICR2_LEN      0x04
+#endif
+
+#define VP880_ICR2_SENSE_INDEX      0x00
+#define VP880_ICR2_DAC_SENSE        0x80
+#define VP880_ICR2_ILA_DAC          0x80
+#define VP880_ICR2_FEED_SENSE       0x40
+#define VP880_ICR2_VOC_DAC_SENSE    0x20
+#define VP880_ICR2_ILA_FDRING_SENSE 0x10
+
+#define VP880_ICR2_TIP_SENSE        0x08
+#define VP880_ICR2_RING_SENSE       0x04
+#define VP880_ICR2_VOC_DAC_INDEX    0x00
+
+#define VP880_ICR2_MET_SPEED_INDEX  0x02
+#define VP880_ICR2_SWY_LIM_INDEX    0x02
+#define VP880_ICR2_FEED_CTRL_INDEX  0x02
+
+#define VP880_ICR2_SWY_CTRL_INDEX   0x02
+#define VP880_ICR2_SWY_CTRL_EN      0x20
+
+#define VP880_ICR2_MET_SPEED_CTRL   0x80
+#define VP880_ICR2_FEED_CTRL        0x40
+#define VP880_ICR2_SWY_LIM_CTRL1    0x08
+#define VP880_ICR2_SWY_LIM_CTRL     0x04
+
+#define VP880_ICR2_STATE_CTRL_INDEX 0x02
+#define VP880_ICR2_STATE_CTRL       0x20
+
+/**< Internal Configuration Register 3 */
+#define VP880_ICR3_WRT      0xF2
+#define VP880_ICR3_RD       0xF3
+
+#ifndef VP880_ICR3_LEN
+#define VP880_ICR3_LEN      0x04
+#endif
+
+#define VP880_ICR3_LINE_CTRL_INDEX      0x00
+#define VP880_ICR3_LINE_CTRL            0x20
+#define VP880_ICR3_SAT_LIM_25_CTRL      0x10
+#define VP880_ICR3_VREF_CTRL            0x01
+
+
+#define VP880_ICR3_LONG_UNCLAMP         0x40
+#define VP880_ICR3_LONG_UNCLAMP_INDEX   0x02
+#define VP880_ICR3_LONG_FIXED           0x10
+#define VP880_ICR3_LONG_FIXED_INDEX     0x00
+
+#define VP880_ICR3_LONG_LOOP_CTRL_LOCATION  0x02
+#define VP880_ICR3_LONG_LOOP_CONTROL        0x80
+#define VP880_ICR3_SE_RINGING_CONTROL       0x01
+
+/**< Internal Configuration Register 4 */
+#define VP880_ICR4_WRT      0xF4
+#define VP880_ICR4_RD       0xF5
+
+#ifndef VP880_ICR4_LEN
+#define VP880_ICR4_LEN      0x04
+#endif
+
+#define VP880_ICR4_VOICE_ADC_INDEX      0x00
+#define VP880_ICR4_VOICE_ADC_CTRL       0x01
+
+#define VP880_ICR4_SUP_INDEX            0x02
+#define VP880_ICR4_SUP_DAC_CTRL         0x08
+#define VP880_ICR4_SUP_DET_CTRL         0x04
+#define VP880_ICR4_SUP_POL_CTRL         0x02
+
+#define VP880_ICR4_GKEY_DET_LOCATION    0x02
+#define VP880_ICR4_GKEY_POL             0x10
+#define VP880_ICR4_GKEY_DET             0x01
+
+#define VP880_ICR5_WRT              0xFA
+#define VP880_ICR5_RD               0xFB
+#define VP880_ICR5_LEN              0x02
+
+#define VP880_ICR5_FEED_HOLD_INDEX  0x00
+
+#define VP880_ICR5_FEED_HOLD_MASK   0xF0
+#define VP880_ICR5_BAT_HOLD_MASK    0x0F
+#define VP880_ICR5_H2MS_BYTE        1
+#define VP880_ICR5_H2MS_MASK        0xF0
+#define VP880_ICR5_SUBST_MASK       0x0F
+
+/**< Internal Configuration Register 6 */
+#define VP880_ICR6_WRT      0xFC
+#define VP880_ICR6_RD       0xFD
+
+#ifndef VP880_ICR6_LEN
+#define VP880_ICR6_LEN      0x02
+#endif
+
+#define VP880_DC_CAL_REG_WRT    0xFC
+#define VP880_DC_CAL_REG_RD     0xFD
+#define VP880_DC_CAL_REG_LEN    0x02
+
+/* Upper Byte Bits */
+#define VP880_DC_CAL_ABS_INDEX          0
+#define VP880_DC_CAL_ABS_MASK           0xF0
+#define VP880_DC_CAL_BAT_SW_OVRD        0x08
+#define VP880_DC_CAL_OFFSET_OVRD        0x04
+#define VP880_DC_CAL_RSVD               0x03
+
+/* Lower Byte Bits */
+#define VP880_DC_CAL_CUT_INDEX          1
+#define VP880_EN_XB_SENSE               0x80
+#define VP880_C_RING_SNS_CUT            0x40
+#define VP880_C_TIP_SNS_CUT             0x20
+#define VP880_VOC_DC_CTRL               0x10
+#define VP880_DC_CAL_BAT_SW_MID         0x08
+#define VP880_DC_CAL_DIS_INPUT_OFFSET   0x04
+
+#define VP880_DCCAL_BAT_SW_HYST_MASK    0x03
+#define VP880_DCCAL_BAT_SW_HYST_1V      0x00
+#define VP880_DCCAL_BAT_SW_HYST_3V      0x01
+#define VP880_DCCAL_BAT_SW_HYST_5V      0x02
+#define VP880_DCCAL_BAT_SW_HYST_7V      0x03
+
+#define VP880_DC_CAL_BLIM_INDEX 1
+#define VP880_DC_CAL_BLIM       0x08
+
+
+/*
+ * In ms, before bias is removed in ground start workaround when the line has
+ * been set from Tip Open to any other state.
+ */
+#define VP880_GND_START_TIME        (210)
+#define VP880_LPM_GND_START_TIME    (30)
+
+/*
+ * The initial settings of the fake test load state take a while to settle the
+ * DC values of the battery.  Wait this time before disabling tip and ring bias
+ * to make tip and ring outputs high impedance, and tend to pull to battery.
+ * The SHORT time is used for ABS and non-fixed tracking devices.
+ * The LONG time is used for fixed trackers.
+ */
+#define VP880_INTERNAL_TESTTERM_SETTLING_TIME_SHORT (50)    /* ms */
+#define VP880_INTERNAL_TESTTERM_SETTLING_TIME_LONG  (200)   /* ms */
+
+/*
+ * In ms, before transitioning from Disconnect to feed state to prevent ping
+ * on the phone. This exists because the device does a short pol rev on the
+ * line when transitioning from Disconnect to a Feed state.
+ */
+#define VP880_PING_TIME         (30)
+
+
+/* 2ms To adjust for slow onhook detection.  125us increments */
+#define VP880_PULSE_DETECT_ADJUSTMENT   (16)
+
+
+#define VP880_TRACKER_DISABLE_TIME      (70)
+#define VP880_INVERT_BOOST_DISABLE_TIME (150)
+#define VP880_FIXED_TRACK_DISABLE_TIME  (400)
+
+
+#endif  /* Vp880_API_INT_H */
+
+
+
+
+
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_CSLAC_types.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_CSLAC_types.h
new file mode 100644
index 0000000..c5688e8
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_CSLAC_types.h
@@ -0,0 +1,557 @@
+/** \file vp_CSLAC_types.h
+ * vp_CSLAC_types.h
+ *
+ * Header file for internal variables used in CSLAC type API.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8533 $
+ * $LastChangedDate: 2011-04-21 11:11:31 -0500 (Thu, 21 Apr 2011) $
+ */
+
+#ifndef VP_CSLAC_TYPES_H
+#define VP_CSLAC_TYPES_H
+
+#include "vp_api_fxo_params.h"
+#include "vp_api_timer.h"
+
+#define VP_CSLAC_DEV_PROFILE_VERSION_INT_SW_CONFIG_FR   5
+#define VP_CSLAC_DEV_PROFILE_VERSION_INT_SW_CONFIG      4
+#define VP_CSLAC_DEV_PROFILE_VERSION_LINECARD_PARAM     3
+#define VP_CSLAC_DEV_PROFILE_VERSION_VBH_REG            2
+#define VP_CSLAC_DEV_PROFILE_VERSION_SW_CONFIG          1
+
+#define VP_CSLAC_FXO_VERSION_DTMF_LEVEL                 1
+#define VP_CSLAC_FXO_VERSION_POH                        2
+
+#define VP_CSLAC_DC_PROFILE_VERSION_890                 1
+
+#define VP_CSLAC_RING_PROFILE_VERSION_890               1
+
+#define VP_CSLAC_TICKSTEP_0_5MS     0x80    /**< CSLAC Tickrate for 0.5mS */
+
+#define VP_CID_TIMESCALE    1   /**< Timescale in mS for CID time data */
+
+#define VP_CSLAC_DEV_PROF_TABLE_SIZE            1
+#define VP_CSLAC_AC_PROF_TABLE_SIZE             2
+#define VP_CSLAC_DC_PROF_TABLE_SIZE             2
+#define VP_CSLAC_RINGING_PROF_TABLE_SIZE        2
+#define VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE   11
+#define VP_CSLAC_TONE_PROF_TABLE_SIZE           10
+#define VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE   4
+#define VP_CSLAC_METERING_PROF_TABLE_SIZE       2
+#define VP_CSLAC_CALLERID_PROF_TABLE_SIZE       2
+#define VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE     1
+#define VP_CSLAC_CUSTOM_TERM_PROF_TABLE_SIZE    4
+
+#define VP_CSLAC_STD_TONE          0
+#define VP_CSLAC_HOWLER_TONE       4
+#define VP_CSLAC_AUS_HOWLER_TONE   8
+#define VP_CSLAC_NTT_HOWLER_TONE   12
+#define VP_CSLAC_TONE_TYPE         5
+
+#define VP_CSLAC_READ_RESPONSE_MASK (VP_LINE_EVID_LLCMD_RX_CMP \
+                                   | VP_LINE_EVID_RD_OPTION \
+                                   | VP_LINE_EVID_GAIN_CMP)
+
+typedef struct {
+    VpProfilePtrType pDevProfileTable[VP_CSLAC_DEV_PROF_TABLE_SIZE];
+    VpProfilePtrType pAcProfileTable[VP_CSLAC_AC_PROF_TABLE_SIZE];
+    VpProfilePtrType pDcProfileTable[VP_CSLAC_DC_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingingProfileTable[VP_CSLAC_RINGING_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneCadProfileTable[VP_CSLAC_TONE_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pToneProfileTable[VP_CSLAC_TONE_PROF_TABLE_SIZE];
+    VpProfilePtrType pRingingCadProfileTable[VP_CSLAC_RING_CADENCE_PROF_TABLE_SIZE];
+    VpProfilePtrType pMeteringProfileTable[VP_CSLAC_METERING_PROF_TABLE_SIZE];
+    VpProfilePtrType pCallerIdProfileTable[VP_CSLAC_CALLERID_PROF_TABLE_SIZE];
+    VpProfilePtrType pFxoConfigProfileTable[VP_CSLAC_FXO_CONFIG_PROF_TABLE_SIZE];
+    VpProfilePtrType pCustomTermProfileTable[VP_CSLAC_CUSTOM_TERM_PROF_TABLE_SIZE];
+} VpCSLACDeviceProfileTableType;
+
+/**
+ * The following structure is used by the device as a bitmask indicating
+ * whether or not a given profile table entry is valid. In the bit location a
+ * value '1' = profile is current, '0' = profile is not current.
+ */
+typedef struct {
+    uint16 devProfEntry;
+    uint16 acProfEntry;
+    uint16 dcProfEntry;
+    uint16 ringingProfEntry;
+    uint16 toneCadProfEntry;
+    uint16 toneProfEntry;
+    uint16 ringCadProfEntry;
+    uint16 meterProfEntry;
+    uint16 cidCadProfEntry;
+    uint16 fxoConfigProfEntry;
+    uint16 customTermProfEntry;
+} VpCSLACProfileTableEntryType;
+
+#define VP_PROF_ENTRY_INVALID   0
+#define VP_PROF_ENTRY_VALID     1
+
+typedef union {
+    VpOptionCriticalFltType criticalFaultOption;
+    VpOptionEventMaskType eventMaskOption;
+    VpOptionPulseModeType pulseModeOption;
+    VpOptionPulseType pulseTypeOption;
+    VpOptionRingControlType ringControlOption;
+    VpOptionZeroCrossType zeroCross;
+    VpOptionTimeslotType timeSlotOption;
+    VpOptionCodecType codecOption;
+    VpOptionPcmHwyType pcmHwyOption;
+    VpOptionLoopbackType loopBackOption;
+    VpOptionLineStateType lineStateOption;
+    VpOptionPcmTxRxCntrlType pcmTxRxCtrl;
+    VpDeviceIoAccessDataType deviceIoData;
+    VpOptionDeviceIoType deviceIo;
+    VpLoopCondResultsType loopCond;
+    bool autoShutdownEn;
+    VpOptionAbsGainType absGain;
+} VpGetResultsOptionsDataType;
+
+typedef struct {
+    VpGetResultsOptionsDataType optionData;
+    uint8 chanId;
+    VpOptionIdType optionType;
+} VpGetResultsOptionsType;
+
+#define VP_CID_DTMF_ON_TIME    70   /**< Nominal 70mS +/- 5mS */
+#define VP_CID_DTMF_OFF_TIME   70   /**< Minimum 65mS */
+
+typedef enum {
+    VP_CID_GENERATOR_DATA,
+    VP_CID_GENERATOR_KEYED_CHAR,
+    VP_CID_SIGGEN_EOT,
+    VP_CID_NO_CHANGE,           /**< Load tones only, do not change generator
+                                 * state
+                                 */
+    VP_CID_GENERATOR_MARKOUT,
+    VP_CID_CTRL_TYPE_CNT,
+
+    VP_CID_GENC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCidGeneratorControlType;
+
+typedef enum {
+    VP_CID_RESET_VALUE = 0x0000,
+
+    VP_CID_IS_DEBOUNCE = 0x0001,        /**< Set when debounce has expired */
+    VP_CID_CLIAWAITTONE = 0x0002,
+    VP_CID_REPEAT_MSG = 0x0004,
+    VP_CID_AWAIT_TONE = 0x0008,         /**< Set if waiting for CPE ACK Tone */
+
+    VP_CID_TERM_FSK = 0x0010,           /**< Set if stopping FSK generator */
+    VP_CID_END_OF_MSG = 0x0020,         /**< Set if API detects an end of
+                                         * message in the buffered data
+                                         */
+    VP_CID_FSK_GEN_VALID = 0x0040,      /**< Set if FSK Generator is programmed
+                                         * for Caller ID signals.
+                                         */
+    VP_CID_IN_PROGRESS = 0x0080,        /**< Set if Caller ID is in progress */
+
+    VP_CID_ACTIVE_RING_SEQ = 0x0100,    /**< Set if active CID Ring sequence */
+    VP_CID_PRIMARY_FULL = 0x0200,       /**< Set when primary buffer contains
+                                         * CID data
+                                         */
+    VP_CID_SECONDARY_FULL = 0x0400,     /**< Set when secondary buffer contains
+                                         * CID data
+                                         */
+    VP_CID_PRIMARY_IN_USE = 0x0800,     /**< Set when primary buffer in use */
+    VP_CID_SECONDARY_IN_USE = 0x1000,   /**< Set when secondary buffer in use */
+    VP_CID_WAIT_ON_ACTIVE = 0x2000,     /**< Set when a "wait on" mode is
+                                         * active. Should only be cleared in
+                                         * the timer function (since currently
+                                         * support only for Wait on CID or time
+                                         */
+    VP_CID_MID_CHECKSUM = 0x4000,       /**< Set when a checksum value is being
+                                         * sent.
+                                         */
+    VP_CID_MUTE_ON = 0x8000,            /**< Set when a "Mute On" CID operator
+                                         * is active.
+                                         */
+    VP_CID_FSK_ACTIVE = 0x10000 /**< Set while the FSK Generator is needed */
+
+} VpCidStatusFlagType;  /* Update "status" if this size increases */
+
+typedef enum {
+    VP_CID_DTMF_RESET_VALUE = 0x0000,
+    VP_CID_ACTIVE_ON_TIME = 0x0001,
+    VP_CID_ACTIVE_OFF_TIME = 0x0002,
+    VP_CID_DTMFS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCidDtmfStatusType;
+
+/** Caller ID variables used by the line */
+typedef struct {
+    uint32 status;  /**< 'OR'ed combination of VpCidStatusFlagType */
+
+    VpCidDtmfStatusType dtmfStatus; /**< Used only for DTMF CID Message Data */
+
+    uint16 cliTimer;        /**< Time in increments of device ticks */
+    uint8 currentData;      /**< Data to repeat on the line */
+    uint16 cidCheckSum;     /**< Checksum to append to message data */
+
+    uint8 cliDebounceTime;  /**< Hook debouce specified in device ticks */
+    VpProfilePtrType pCliProfile;   /**< Currently running CID Profile */
+
+    VpDigitType cliDetectTone1;
+    VpDigitType cliDetectTone2;
+
+    uint8 cliMPIndex;       /**< Current Index into primary message buffer */
+    uint8 cliMSIndex;       /**< Current Index into secondary message buffer */
+
+    uint8 cliIndex;         /**< Current Index into profile data */
+
+    uint8 primaryBuffer[VP_SIZEOF_CID_MSG_BUFFER];
+    uint8 secondaryBuffer[VP_SIZEOF_CID_MSG_BUFFER];
+
+    uint8 primaryMsgLen;    /**< Length of data in the primary buffer */
+    uint8 secondaryMsgLen;  /**< Length of data in the secondary buffer */
+    VpDigitType digitDet;   /**< Stores the last DTMF digit detected during
+                             * Caller ID (if enabled via tone detection).
+                             */
+    /*
+     * At the end of FSK Message Data, some systems require a mark-out time. As
+     * specified in the Profile Wizard, this is defined in # of bytes with each
+     * byte corresponding to 8.33ms (1200 baud with 1 start + 1 stop + 8 data
+     * bits = 10/1200 = 8.33ms).
+     */
+    uint8 markOutByteCount;     /* Retains the value specified in the profile */
+    uint8 markOutByteRemain;    /* Current value remaining. Clean up when = 0 */
+} VpCallerIdType;
+
+typedef enum {
+    VP_CADENCE_RESET_VALUE = 0x0000,
+    VP_CADENCE_STATUS_ACTIVE = 0x0001,
+    VP_CADENCE_STATUS_BRANCHING  = 0x0002,
+    VP_CADENCE_STATUS_MID_TIMER  = 0x0004,
+    VP_CADENCE_STATUS_SENDSIG  = 0x0008,
+    VP_CADENCE_STATUS_METERING = 0x0010,
+    VP_CADENCE_STATUS_BRANCHING_LVL2  = 0x0020,
+    VP_CADENCE_STATUS_IGNORE_POLARITY = 0x0040,
+    VP_CADENCE_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCadenceStatusType;
+
+/** Variables to control the cadence on the line using the Sequencer */
+#define VP_CSLAC_MAX_BRANCH_DEPTH   2
+#define VP_CSLAC_BRANCH_LVL_0       0
+#define VP_CSLAC_BRANCH_LVL_1       1
+
+typedef struct {
+    VpProfilePtrType pActiveCadence;    /**< Currently Active Cadence */
+    VpProfilePtrType pCurrentPos;       /**< Current position in profile */
+
+    VpCadenceStatusType status;
+
+    uint8 index;        /**< Index in the the cadence table   */
+    uint8 length;       /**< Length of executable cadence instructions */
+
+    /**< Remaining number of repeats to perform for each branch depth */
+    uint8 count[VP_CSLAC_MAX_BRANCH_DEPTH];
+
+    uint16 timeRemain;
+    uint8 branchAt;     /**< Outermost step we're branching */
+    uint16 meteringBurst;   /**< Tracks the number of metering pulses sent */
+    bool meterPendingAbort; /**< Indicates that metering should abort after the
+                             * current pulse ends */
+    VpLineStateType meterAbortLineState; /**< The line state that should be set
+                                          * when metering aborts */
+
+    /* The following variables are for controlling signal generator ramp */
+#define VPCSLAC_MAX_GENERATOR_DATA 11
+    uint8 regData[VPCSLAC_MAX_GENERATOR_DATA];  /**< Scratchpad to reduce MPI
+                                                 * traffic.
+                                                 */
+    /*
+     * These values should correspond to device specific values for the
+     * freqency/level being set -- not a generic value.
+     */
+    uint16 startFreq;
+    bool isFreqIncrease;
+    uint16 stopFreq;
+    uint16 freqStep;    /**< Step size assumes a 50mS interval. */
+
+    uint16 startLevel;
+    uint16 stopLevel;
+    uint16 levelStep;  /**< Step size assumes a 50mS interval. Note: It is
+                        * possible to support a negative step, but the first
+                        * use of this function is UK type howler tone which only
+                        * increases in level.
+                        */
+} VpSeqDataType;
+
+/** Variables to control the CID sequence on the line using the CID Sequencer */
+typedef struct {
+    VpProfilePtrType pActiveCadence;    /**< Currently Active Cadence */
+    VpProfilePtrType pCurrentPos;       /**< Current position in profile */
+
+    uint8 index;        /**< Index in the the cadence table   */
+    uint16 timeRemain;
+} VpCidSeqDataType;
+
+typedef VpStatusType
+(*VpSeqInstructionFuncPtrType) (
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pSequenceData);
+
+#define VP_SEQ_OPERATOR_MASK 0xE0
+#define VP_SEQ_SUBTYPE_MASK  0x1F
+#define VP_SEQUENCER_TICKRATE   0x0500  /* 5mS - Used with MS_TO_TICKRATE */
+
+/**< The super commands are the upper 3 bits of the command byte */
+typedef enum {
+    VP_SEQ_SPRCMD_COMMAND_INSTRUCTION = 0x00,
+    VP_SEQ_SPRCMD_TIME_INSTRUCTION = 0x20,
+    VP_SEQ_SPRCMD_BRANCH_INSTRUCTION = 0x40,
+    VP_SEQ_SPRCMD_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSeqSuperCommandsType;
+
+/**< The sub commands are the lower 5 bits of the command byte */
+typedef enum {
+    VP_SEQ_SUBCMD_SIGGEN = 0x00,
+    VP_SEQ_SUBCMD_LINE_STATE = 0x01,
+    VP_SEQ_SUBCMD_START_CID = 0x02,
+    VP_SEQ_SUBCMD_WAIT_ON = 0x07,   /**< Wait for CID or time to continue */
+
+    VP_SEQ_SUBCMD_RAMP_GENERATORS = 0x08,   /**< Forces frequency/amplitude
+                                             * change of the tone generator.
+                                             * Tone Cadence associated with this
+                                             * command must be specified as
+                                             * "ramp" type. The period between
+                                             * adjustments is fixed 50mS.
+                                             */
+
+    /**< API Internal Use only operators */
+    VP_SEQ_SUBCMD_METERING = 0x10,  /**< Cadence Metering */
+
+    VP_SEQ_SUBCMD_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSeqSubCommandsType;
+
+typedef enum {
+    VP_SEQ_SIGGEN_ALL_DISABLED = 0x00,
+    VP_SEQ_SIGGEN_A_EN = 0x01,
+    VP_SEQ_SIGGEN_B_EN = 0x02,
+    VP_SEQ_SIGGEN_C_EN = 0x04,
+    VP_SEQ_SIGGEN_D_EN = 0x08,
+    VP_SEQ_SIGGEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSeqSigGenCtrlType;
+
+typedef uint8 VpProfileCadencerStateTypes;
+#define VP_PROFILE_CADENCE_STATE_STANDBY            (0)
+#define VP_PROFILE_CADENCE_STATE_TIP_OPEN           (1)
+#define VP_PROFILE_CADENCE_STATE_TALK               (2)
+#define VP_PROFILE_CADENCE_STATE_ACTIVE             (3)
+#define VP_PROFILE_CADENCE_STATE_RSVD               (4)
+#define VP_PROFILE_CADENCE_STATE_OHT                (5)
+#define VP_PROFILE_CADENCE_STATE_DISCONNECT         (6)
+#define VP_PROFILE_CADENCE_STATE_RINGING            (7)
+#define VP_PROFILE_CADENCE_STATE_POLREV_STANDBY     (8)
+#define VP_PROFILE_CADENCE_STATE_POLREV_TIP_OPEN    (9)
+#define VP_PROFILE_CADENCE_STATE_POLREV_TALK        (10)
+#define VP_PROFILE_CADENCE_STATE_POLREV_ACTIVE      (11)
+#define VP_PROFILE_CADENCE_STATE_POLREV_RSVD        (12)
+#define VP_PROFILE_CADENCE_STATE_POLREV_OHT         (13)
+#define VP_PROFILE_CADENCE_STATE_POLREV_DISCONNECT  (14)
+#define VP_PROFILE_CADENCE_STATE_POLREV_RINGING     (15)
+#define VP_PROFILE_CADENCE_STATE_FXO_OHT            (16)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_OPEN      (17)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_CLOSE     (18)
+#define VP_PROFILE_CADENCE_STATE_FXO_LOOP_TALK      (19)
+#define VP_PROFILE_CADENCE_STATE_MSG_WAIT_NORM      (20)
+#define VP_PROFILE_CADENCE_STATE_MSG_WAIT_POLREV    (21)
+
+/* struct VpDialPulseDetectType is for FXS lines when detecting digits */
+typedef enum {
+    VP_DP_DETECT_STATE_LOOP_OPEN = 0,
+    VP_DP_DETECT_STATE_LOOP_CLOSE = 1,
+    VP_DP_DETECT_STATE_IDLE = 2
+} VpDialPulseDetectStatesType;
+
+typedef struct {
+    int digits;
+    uint16 lo_time;
+    uint16 lc_time;
+    VpDialPulseDetectStatesType state;   /**< Dial Pulse State Machine state */
+    bool hookSt;
+    uint8 signalingData;
+} VpDialPulseDetectType;
+
+/* struct VpDigitGenerationDataType is for FXO lines when generating digits */
+typedef struct {
+    uint16 dtmfOnTime;
+    uint16 dtmfOffTime;
+    uint8 breakTime;
+    uint8 makeTime;
+    uint16 flashTime;
+    uint16 dpInterDigitTime;
+    uint8 dtmfHighFreqLevel[2];
+    uint8 dtmfLowFreqLevel[2];
+} VpDigitGenerationDataType;
+
+/** Virtual Device Registers - Used to reduce MPI accesses to the Device */
+typedef struct {
+    uint8 sigRegMSB;    /**< Signaling Register's Most Significant byte */
+    uint8 sigRegLSB;    /**< Signaling Register's Least Significant byte */
+    uint8 iMaskMSB;     /**< Interrupt mask for the current line */
+    uint8 iMaskLSB;     /**< Interrupt mask for the current line */
+    uint8 iMaskMSBSP;   /**< Interrupt mask for the current line */
+    uint8 iMaskLSBSP;   /**< Interrupt mask for the current line */
+    uint8 ccR1SP;
+    uint8 ccR5SP;       /**< Scratchpad for CCR5 used during metering */
+    uint8 ccR8SP;       /**< Scratchpad for CCR8 used during calibration */
+    uint8 ioReg;        /**< IO Register for QSLAC SLIC states */
+} VpVirtualDeviceReg;
+
+/*
+ * IMPORTANT: Make sure to update the type used for "state" member inside
+ * objects, structs, and passed to functions where the comment states the value
+ * is a bit-mask of "VpDeviceStateType". Seach by "VpDeviceStateType".
+ * There are no instance of this type itself.
+ */
+typedef enum {
+    /**< Indicates if function is running from InitDevice. Not the same as in
+     * the middle of an initialization process (including calibration). Used to
+     * allow InitDevice function calling other functions to be enabled. Otherwise,
+     * some functions will return "Device Not Initialized" error.
+     */
+    VP_DEV_INIT_IN_PROGRESS = 0x0001,
+
+    VP_DEV_INIT_CMP = 0x0002,    /**< Set if device has been initialized */
+    VP_DEV_IN_CAL = 0x0004,      /**< Set if device is busy calibrating */
+    VP_DEV_PENDING_INT = 0x0008, /**< Set if there is a pending interrupt */
+
+    VP_DEV_ABS_BAT_CAL = 0x0010, /**< Set when running ABS (batt switch) Cal */
+    VP_DEV_ABV_CAL = 0x0020,     /**< Set when running ABV Calibration on Tracker */
+    VP_DEV_ABV_CAL_ABS = 0x0040, /**< Set when running ABV Calibration on ABS */
+    VP_DEV_DISC_PENDING = 0x0080, /**< Set when a Disconnect Timer was suspsended */
+
+    VP_DEV_TEST_BUFFER_READ = 0x0100, /**< Set if test buffer was read this tick */
+
+     /**< Set if device in process of warm reboot. Note that warm reboot
+      * detection alone only helps skipping of VpCalCodec() because it is run
+      * with VpInitDevice(). But it does not ensure that VpCalLine() was
+      * previously run.
+      */
+    VP_DEV_WARM_REBOOT = 0x0200
+
+} VpDeviceStateType;
+
+typedef struct {
+    uint16 state;           /**< This is a bit-mask of VpDeviceStateType values */
+    uint8 globStatReg;      /**< Holds state of the device stat reg */
+    uint8 calibrating;      /**< Calibration timer */
+    uint8 numIntServiced;   /**< Max interrupts to be serviced during tick */
+} VpCSLACDeviceStatusType;
+
+#define VP_CSLAC_MAX_RCN_PCN_SIZE   2
+typedef struct {
+    uint8 rcnPcn[VP_CSLAC_MAX_RCN_PCN_SIZE];    /**< Revision Code Number and
+                                                 * Product Code Number as
+                                                 * applicable
+                                                 */
+    uint8 maxChannels;  /**< How many lines supported by this device */
+} VpDeviceStaticInfoType;
+
+typedef struct {
+    uint8 lastChan;     /**< The last line checked */
+    bool clkFault;      /** TRUE if a clock fault is active */
+    bool bat1Fault;     /** TRUE if a bat1 fault is active and device level */
+    bool bat2Fault;     /** TRUE if a bat2 fault is active and device level */
+    bool bat3Fault;     /** TRUE if a bat3 fault is active and device level */
+} VpDeviceDynamicInfoType;
+
+/** Line state variables used by the line (api internal) */
+typedef enum {
+    VP_CSLAC_STATUS_INVALID = 0x0000,
+
+    /* FXS Type Status */
+    VP_CSLAC_HOOK = 0x0001,
+    VP_CSLAC_GKEY = 0x0002,
+
+    /* FXO Type Status */
+    VP_CSLAC_RAW_DISC = 0x0001,     /*
+                                     * Set on 890 when device level disconnect
+                                     * status is set. Cleared otherwise.
+                                     */
+
+    VP_CSLAC_RINGING = 0x0004,      /**< Set when Ringing detected on Line */
+    VP_CSLAC_DISC = 0x0008,         /**< Set when Disconnect detected on Line */
+
+    VP_CSLAC_AC_FLT = 0x0010,
+    VP_CSLAC_DC_FLT = 0x0020,
+    VP_CSLAC_THERM_FLT = 0x0040,
+    VP_CSLAC_CAL_ENABLE = 0x0080,   /**< Set when the line is in a state that
+                                     * will allow device calibration
+                                     */
+
+    VP_CSLAC_CAL_FAIL = 0x0100,
+    VP_CSLAC_POLREV = 0x0200,
+    VP_CSLAC_POLREV_REPORTED = 0x0400,
+    VP_CSLAC_LIU = 0x0800,
+
+    VP_CSLAC_LINE_LEAK_TEST = 0x1000,   /**< Set when line is being tested for
+                                         * resistive leak. Clear when test is
+                                         * complete.
+                                         */
+    VP_CSLAC_RING_AMP_DET = 0x2000,
+    VP_CSLAC_RINGING_EXIT = 0x4000, /**< Set when FXS line is exiting Ringing */
+
+    VP_CSLAC_STATUS_VALID = 0x8000
+} VpCslacLineCondType;
+
+typedef enum {
+    VP_CSLAC_CAL_NONE = 0x0000,
+    VP_CSLAC_CAL_VOC,
+    VP_CSLAC_CAL_VAG,
+    VP_CSLAC_CAL_VBG,
+    VP_CSLAC_CAL_ILA,
+#ifdef VP880_TRACKER_SUPPORT
+    VP_CSLAC_CAL_VAS,
+#endif
+    VP_CSLAC_CAL_ABV,
+    VP_CSLAC_CAL_CLEANUP,
+    VP_CSLAC_CAL_TYPE_SIZE,
+    VP_CSLAC_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCslacCalType;
+
+typedef struct {
+    VpLineStateType currentState;   /**< Current state of the line */
+    VpLineStateType previous;   /**< Previous sate of the line */
+
+    VpLineStateType usrCurrent; /**< Current user set state of the line */
+
+    VpCslacLineCondType condition;
+    VpCslacCalType calType;
+} VpApiIntLineStateType;
+
+typedef enum
+{
+    VP_CUSTOM_TERM_SLIC_TYPE = 6,
+    VP_CUSTOM_TERM_NUM_STATES = 7,
+    VP_CUSTOM_TERM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} vpCustomTermProfileParams;
+
+typedef enum
+{
+    VP_FXO_DIAL_PRFL_DTMF_ON_MSB = 6,
+    VP_FXO_DIAL_PRFL_DTMF_ON_LSB = 7,
+    VP_FXO_DIAL_PRFL_DTMF_OFF_MSB = 8,
+    VP_FXO_DIAL_PRFL_DTMF_OFF_LSB = 9,
+    VP_FXO_DIAL_PRFL_FLASH_HOOK_MSB = 10,
+    VP_FXO_DIAL_PRFL_FLASH_HOOK_LSB = 11,
+    VP_FXO_DIAL_PRFL_PULSE_BREAK = 12,
+    VP_FXO_DIAL_PRFL_PULSE_MAKE = 13,
+    VP_FXO_DIAL_PRFL_INTERDIG_MSB = 14,
+    VP_FXO_DIAL_PRFL_INTERDIG_LSB = 15,
+    VP_FXO_DIAL_PRFL_RING_PRD_MAX = 16,
+    VP_FXO_DIAL_PRFL_RING_PRD_MIN = 17,
+    VP_FXO_DIAL_PRFL_RING_VOLT_MIN = 18,
+    VP_FXO_DIAL_PRFL_DISC_VOLT_MIN = 19,
+    VP_FXO_DIAL_PRFL_LIU_THRESH_MIN = 20,
+    VP_FXO_DIAL_PRFL_RSVD = 21,
+    VP_FXO_DIAL_PRFL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} vpCslac_fxo_dialPrflParams;
+#endif
+
+
+
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api.h
new file mode 100644
index 0000000..0a28172
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api.h
@@ -0,0 +1,147 @@
+/** \file vp_api.h
+ * vp_api.h
+ *
+ * Header file for the API-II c files.
+ *
+ * This file contains the all of the VoicePath API-II function prototypes. This
+ * file should be used to bring in the VP-API-II library modules that are
+ * necessary for a given application.
+ *
+ *****************************************************************************
+ * NOTE: Inclusion of only this file is sufficient to bring in the all the   *
+ * necessary aspects of VP_API.                                              *
+ *****************************************************************************
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8620 $
+ * $LastChangedDate: 2011-06-02 13:27:26 -0500 (Thu, 02 Jun 2011) $
+ */
+
+
+#ifndef VP_API_H
+#define VP_API_H
+
+/******************************************************************************
+ * VP-API Version                                                             *
+ *****************************************************************************/
+/*
+ * The following version number tag is updated at every release of the VP-API.
+ * Since the VP-API is a common interface that supports more than one device,
+ * version number change might occur when any aspect of the VP-API gets
+ * released.
+ */
+#define VP_API_VERSION_TAG (0x021201)
+
+#define VP_API_VERSION_MAJOR_NUM ((VP_API_VERSION_TAG) >> 16)
+#define VP_API_VERSION_MINOR_NUM (((VP_API_VERSION_TAG) & 0x00FF00) >> 8)
+#define VP_API_VERSION_MINI_NUM (((VP_API_VERSION_TAG) & 0x0FF))
+
+/* First include various basic data types used in the API */
+#include "vp_api_types.h"
+
+/******************************************************************************
+ * Defines the configuration of VP-API library that needs to be built.        *
+ * Please modify the following include file as per your VP-API library        *
+ * requirement(s).                                                            *
+ ******************************************************************************/
+#include "vp_api_cfg.h"
+
+/******************************************************************************
+ *                  PLEASE DO NOT MODIFY BELOW THIS LINE                      *
+ ******************************************************************************/
+/* Include the main VP-API-Common file */
+#include "vp_api_common.h"
+
+/* Include the VP-API-Header file required for the CSLAC sequencer */
+#if defined (VP_CSLAC_SEQ_EN)
+#include "vp_api_cslac_seq.h"
+#endif
+
+/* Include the necessary files depending on the requirement of the project */
+#if defined (VP_CC_790_SERIES)
+#include "vp790_api.h"    /* Vp790 device specific API functions and typedefs */
+#endif
+
+/* Include the necessary files depending on the requirement of the project */
+#if defined (VP_CC_792_SERIES)
+#include "vp792_api.h"    /* Vp790 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_880_SERIES)
+#include "vp880_api.h"    /* Vp880 device specific API functions and typedefs */
+
+/*
+ * For 0823 LM, the FXO CID line is controlled by I/O3. For 0803 LM, it's
+ * controlled by I/O2. Control with I/O3 is better since I/O2 has more features
+ *
+ *  #define VP880_FXO_CID_LINE      VP880_IODATA_IO2    Use with 0803 ref
+ *  #define VP880_FXO_CID_LINE      VP880_IODATA_IO3    Use with 0823 ref
+ */
+#define VP880_FXO_CID_LINE      VP880_IODATA_IO3
+#endif
+
+#if defined (VP_CC_890_SERIES)
+#include "vp890_api.h"    /* Vp890 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_580_SERIES)
+#include "vp580_api.h"    /* Vp580 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_VCP_SERIES)
+#include "dvp_api.h"     /* VCP device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_VCP2_SERIES)
+#include "vcp2_api.h"     /* VCP2 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_MELT_SERIES)
+#include "melt_api.h"     /* VCP2 device specific API functions and typedefs */
+#endif
+
+#if defined (VP_CC_KWRAP)
+#include "vp_kernel.h"    /* KWRAP device specific API functions and typedefs */
+#endif
+
+/* Macros for calling a device-specific API function using the pointer in the
+   Device Context: */
+typedef void (*VpTempFuncPtrType) (void);
+
+#define VP_CALL_DEV_FUNC(func, args) \
+    (((pDevCtx->funPtrsToApiFuncs.func) == VP_NULL) ? VP_STATUS_FUNC_NOT_SUPPORTED : (pDevCtx->funPtrsToApiFuncs.func) args )
+
+/*
+ * Based on the existing structure of the include files the following def
+ * have been moved here.
+ */
+
+#if defined(VP_CC_880_SERIES) || defined(VP_CC_790_SERIES) || defined(VP_CC_890_SERIES)
+
+  typedef union {
+      uint8 dummy; /* preventing an empty union */
+  #if defined(VP_CC_880_SERIES) && defined(VP880_INCLUDE_TESTLINE_CODE)
+    Vp880TestHeapType vpTestHeap880;
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+
+  #if defined(VP_CC_890_SERIES) && defined(VP890_INCLUDE_TESTLINE_CODE)
+    Vp890TestHeapType vpTestHeap890;
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+
+  #if defined(VP_CC_790_SERIES) && defined(VP790_INCLUDE_TESTLINE_CODE)
+    /* Vp790TestHeapType vpTestHeap790; */
+    #define VP_TEST_HEAP_IS_REQUIRED
+  #endif
+} VpTestHeapType;
+#else
+typedef char VpTestHeapType;
+#endif
+
+#endif /* VP_API_H */
+
+
+
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_cfg.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_cfg.h
new file mode 100644
index 0000000..0c2d38f
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_cfg.h
@@ -0,0 +1,112 @@
+/** \file vp_api_cfg.h
+ * vp_api_cfg.h
+ *
+ * This file contains the configuration and compile time settings for
+ * building appropriate VP-API library modules needed for any application.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8674 $
+ * $LastChangedDate: 2011-06-22 10:13:07 -0500 (Wed, 22 Jun 2011) $
+ */
+
+#ifndef VP_API_CFG_H
+#define VP_API_CFG_H
+
+#include "vp_debug_masks.h"
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: API DEBUG OUTPUT SELECTIONS                         *
+ *****************************************************************************/
+
+/*
+ * If VP_DEBUG is undefined, then ALL debug messages will be compiled out.
+ * In this case, the code size will be smaller, but debug output CANNOT be
+ * enabled at runtime.
+ */
+#define VP_DEBUG
+
+/*
+ * Choose which types of debug messages to be compiled in.  Only these message
+ * types can be enabled at runtime.  See vp_debug_masks.h for a list of debug
+ * message types.
+ */
+#define VP_CC_DEBUG_SELECT (VP_DBG_ALL)
+
+/*
+ * The VP_OPTION_ID_DEBUG_SELECT option enables/disables debug output at
+ * runtime.  Define the default value of this option here.  The option will be
+ * automatically set to the default value at device initialization.  See
+ * vp_debug_masks.h for a list of debug message types.
+ *
+ * Note: The VP_OPTION_ID_DEBUG_SELECT option can be changed with VpSetOption()
+ *       only AFTER device initialization (VpInitDevice()).  If you wish to
+ *       see debug output messages during device initialization, you must set
+ *       the default VP_OPTION_ID_DEBUG_SELECT value accordingly.
+ */
+#define VP_OPTION_DEFAULT_DEBUG_SELECT  0
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: Conditionally-Compiled API Libraries                *
+ *****************************************************************************/
+
+/*
+ * Define (or undefine) the appropriate compile time switches based on your
+ * application needs.
+ *
+ * NOTE: Such library selection compile time option(s) MUST be defined before
+ * including any other file from VoicePath library.
+ *
+ * NOTE: More than one Library modules can be built simultaneosuly (if needed).
+ */
+
+#define VP_CC_792_SERIES    /**< define to build 792 specific API library;
+                             *   undef to exclude this library. */
+ 
+
+/******************************************************************************
+ * Include Files for the API                                                  *
+ *****************************************************************************/
+/* Include the API types for this architecture */
+#include "vp_api_types.h"
+
+/******************************************************************************
+ * Library Specific COMPILE-TIME OPTIONS and defines                          *
+ *****************************************************************************/
+#ifdef VP_CC_792_SERIES
+
+#undef VP_COMMON_ADDRESS_SPACE         /* Define if all VP-API-II data
+                                           structures (Line Objects, Line Contexts,
+                                           Device Objects, Device Contexts, Profiles)
+                                           are accessible at the same address in
+                                           all processes (tasks) which call VP-API-II
+                                           functions. */
+
+#define VP_CC_792_GROUP                 /* Define to include support for sharing
+                                         * an interrupt pin between multiple
+                                         * VP792 devices. */
+
+#define VP792_MAILBOX_SPINWAIT 50000    /* Number of times to poll the device's
+                                           command mailbox before returning
+                                           VP_STATUS_MAILBOX_BUSY. */
+
+#define VP792_SUPPORT_792388_REV_F_SILICON /* Define this if you want to support
+                                              Revision F of the Le792388 silicon. An
+                                              appropriate SLAC firmware patch will
+                                              be compiled in. */
+#define VP792_SUPPORT_792588_REV_B_SILICON /* Define this if you want to support
+                                              Revision B of the Le792588 silicon. An
+                                              appropriate SLAC firmware patch will
+                                              be compiled in. */
+#define EXTENDED_FLASH_HOOK
+
+#endif /* VP_CC_792_SERIES */
+
+typedef uint8 VpScratchMemType;
+
+/* Include internal options required to build the VP-API-II library */
+#include "vp_api_cfg_int.h"
+
+#endif /* VP_API_CFG_H */
+
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_cfg_int.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_cfg_int.h
new file mode 100644
index 0000000..e42cda2
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_cfg_int.h
@@ -0,0 +1,412 @@
+/** \file vp_api_cfg_int.h
+ * vp_api_cfg_int.h
+ *
+ * This file contains internal configuration and compile time settings for
+ * building appropriate VP-API library modules needed for any application.
+
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 6419 $
+ * $LastChangedDate: 2010-02-12 16:40:10 -0600 (Fri, 12 Feb 2010) $
+ */
+
+#ifndef VP_API_CFG_INT_H
+#define VP_API_CFG_INT_H
+
+/******************************************************************************
+ * Device Context Size                                                        *
+ *****************************************************************************/
+/*
+ * Define the maximum number of lines per device in your system. Note that a
+ * system (i.e., all devices controlled by one instance of VP-API) could have
+ * more than one type of device, each of those devices may support different
+ * number of lines. For example in a system, device A might support 4 lines
+ * and device B might support 32 lines, in such a scenario, the following macro
+ * should be defined as 32. */
+#if defined(VP_CC_VCP2_SERIES) || defined(VP_CC_KERNEL_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (128)
+#elif defined(VP_CC_VCP_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (32)
+#elif defined(VP_CC_792_SERIES) || defined(VP_CC_MELT_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (8)
+#elif defined(VP_CC_790_SERIES) || defined(VP_CC_580_SERIES)
+    #define VP_MAX_LINES_PER_DEVICE     (4)
+#else /* VP_CC_880_SERIES + VP_CC_890_SERIES */
+    /*
+     * Note that for VE890 this value must be >=2 even when using the single
+     * FXO device. That's because the line context pointer in the device
+     * context is assigned to the "channelId" element of the line context
+     * pointer array. The FXO channelId = 1 so the array must be size >= 2.
+     */
+    #define VP_MAX_LINES_PER_DEVICE     (2)
+#endif
+
+/* Special Case for Kernel Wrapper */
+#if defined(VP_CC_KWRAP)
+  #undef VP_MAX_LINES_PER_DEVICE
+  #define VP_MAX_LINES_PER_DEVICE (128)
+#endif
+
+/******************************************************************************
+ * Library Specific COMPILE-TIME OPTIONS and defines                          *
+ *****************************************************************************/
+/* #if defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES) */
+    #define CSLAC_GAIN_RELATIVE
+    #define CSLAC_GAIN_ABS
+/* #endif */
+
+/*
+ * The following values exist for Zarlink test purposes only. DO NOT
+ * change to #define in production code. Unexpected or damaging behavior may
+ * occur.
+ */
+#define VP_ENABLE_PROD_TEST
+
+#ifdef VP_CC_880_SERIES
+
+/*
+ * DO NOT CHANGE the following to #define. This enables experimental code that
+ * is not provided with the VP-API-II installation.
+ */
+#undef  VP880_AUTO_BAT_DETECT
+
+/*
+ * Modifications to previous settings to correct for potential inconsistencies.
+ * DO NOT CHANGE anything below this line. All corrections should be made above
+ */
+#if !defined (VP880_TRACKER_SUPPORT) && defined (VP880_LP_SUPPORT)
+    #error "Invalid 880 Compiler Combination: Low Power Mode Requires Tracker defined"
+#endif
+
+#if defined (VP880_FXS_SUPPORT) && (!defined (VP880_ABS_SUPPORT) && !defined (VP880_TRACKER_SUPPORT))
+    #error "Invalid 880 Compiler Combination: FXS requires either ABS or Tracker defined"
+#endif
+
+#ifndef VP880_FXS_SUPPORT
+    #undef VP880_ABS_SUPPORT
+    #undef VP880_INCLUDE_TESTLINE_CODE
+    #undef VP880_LP_SUPPORT
+#endif
+
+#if !defined (VP880_FXS_SUPPORT) && !defined (VP880_FXO_SUPPORT)
+    #error "Invalid 880 Compiler Combination: Either FXS or FXO must be defined if using VE880 device"
+#endif
+
+/*
+ * Current Limiting option in the VP880 library limits the peak switcher current
+ * such that a 3REN load can be supported at 90V peak. Disable this option if
+ * 5REN is required.
+ */
+#undef  VP880_CURRENT_LIMIT
+
+#endif /* VP_CC_880_SERIES */
+
+#if (defined (VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) || defined(VP_CC_KWRAP)
+    /*
+     * #defines used in unit conversion function
+     * All units are based on the following calculations
+     *      Internal voltage unit   = 480.0  / 2^31 Volts
+     *      Internal current unit   = 240e-3 / 2^31 Amps
+     *      Internal freq uint      = 12e3   / 2^31 Hz
+     */
+    #define VP880_UNIT_MV                          4474L    /* mV unit */
+    #define VP880_UNIT_MVRMS                       6327L    /* mVrms unit */
+    #define VP880_UNIT_ADC_VAB                     -32768L  /* vab step from ADC */
+    #define VP880_UNIT_ADC_VAB_RMS                 46341L   /* vab step from ADC rms*/
+    #define VP880_UNIT_ADC_AC_VAB_RMS                664L   /* vab step from ADC Metallic Vrms*/
+    #define VP880_UNIT_DAC_RING                    21076L   /* step due to DAC in ringing*/
+    #define VP880_UNIT_TRACK_SWZ                23091612L   /* step used for tracking switching regulator Z */
+    #define VP880_UNIT_UA                          8948L    /* uA unit */
+    #define VP880_UNIT_ADC_IMET_NOR                16384L   /* met I from ADC in normal VC */
+    #define VP880_UNIT_ADC_IMET_NOR_JA             15756L   /* met I from ADC in normal JA*/
+    #define VP880_UNIT_ADC_IMET_RING               32768L   /* met I from ADC in ringing*/
+    #define VP880_UNIT_ADC_ILG                     11469L   /* long current from ADC*/
+    #define VP880_UNIT_DECHZ                       17896L   /* Deci Hz*/
+    #define VP880_UNIT_MHZ                         179L     /* mHz */
+    #define VP880_UNIT_FREQ                        65536L   /* siggen freq step */
+    #define VP880_UNIT_RAMP_TIME                   1365L    /* Ramp time (-1/3) in ms*/
+
+    #define VP880_UNIT_CONVERT(DATA, I_UNIT, O_UNIT)    (int32)(((int32)DATA * I_UNIT) / O_UNIT)
+
+    /* converts requested slope into SigGen Freq */
+    #define VP880_SLOPE_TO_FREQ(AMP,SLOPE)  (int16)(((int32)SLOPE * (int32)VP880_UNIT_RAMP_TIME) / (int32)AMP)
+
+    #define VP880_AC_RLOOP_MAX_BAT_LVL              75000L /* mV */
+    #define VP880_AC_RLOOP_MAX_TEST_LVL         ((VP880_AC_RLOOP_MAX_BAT_LVL - 5000) / 2)
+
+#endif /*VP880_INCLUDE_TESTLINE_CODE*/
+
+
+#ifdef VP_CC_890_SERIES
+
+#define VP890_REL_GAIN_GX_LOW_LIMIT     (0x500)
+#define VP890_REL_GAIN_GR_LOW_LIMIT     (0x1000)
+
+#ifndef VP890_FXS_SUPPORT
+    /*
+     * Tests (using testline) is supported only for FXS termination types. If
+     * line tests are required, make sure FXS support is enabled.
+     */
+    #undef VP890_INCLUDE_TESTLINE_CODE
+
+    /* LPM is an FXS termination type. FXS must be supported to support LPM. */
+    #undef  VP890_LP_SUPPORT
+#endif
+
+/* Define this to attempt to reduce the level of the noise signal generated for
+ * adaptive balance B-Filter calibration.  Reducing the level will increase the
+ * negative effect of outside noise on the line and can reduce performance */
+#undef VP890_REDUCE_BFILTER_CAL_SIGNAL_LEVEL
+
+#endif /* VP_CC_890_SERIES*/
+
+#if (defined (VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE)) || defined(VP_CC_KWRAP)
+    /*
+     * #defines used in unit conversion function
+     * All units are based on the following calculations
+     *      Internal voltage unit   = 480.0  / 2^31 Volts
+     *      Internal current unit   = 240e-3 / 2^31 Amps
+     *      Internal freq uint      = 12e3   / 2^31 Hz
+     */
+    #define VP890_UNIT_MV                          4474L    /* mV unit */
+    #define VP890_UNIT_MVRMS                       6327L    /* mVrms unit */
+    #define VP890_UNIT_ADC_VAB                     -32768L  /* vab step from ADC */
+    #define VP890_UNIT_ADC_VAB_RMS                 46341L   /* vab step from ADC rms*/
+    #define VP890_UNIT_ADC_AC_VAB_RMS              664L     /* vab step from ADC Metallic Vrms*/
+    #define VP890_UNIT_DAC_RING                    21076L   /* step due to DAC in ringing*/
+    #define VP890_UNIT_TRACK_SWZ                23091612L   /* step used for tracking switching regulator Z */
+    #define VP890_UNIT_UA                          8948L    /* uA unit */
+    #define VP890_UNIT_ADC_IMET_NOR                15756L   /* met I from ADC in normal*/
+    #define VP890_UNIT_ADC_IMET_RING               32768L   /* met I from ADC in ringing*/
+    #define VP890_UNIT_ADC_ILG                     11469L   /* long current from ADC*/
+    #define VP890_UNIT_DECHZ                       17896L   /* Deci Hz*/
+    #define VP890_UNIT_MHZ                         179L     /* mHz */
+    #define VP890_UNIT_FREQ                        65536L   /* siggen freq step */
+    #define VP890_UNIT_RAMP_TIME                   1365L    /* Ramp time (-1/3) in ms*/
+
+    #define VP890_UNIT_CONVERT(DATA, I_UNIT, O_UNIT) (int32)( ((int32)DATA * I_UNIT) / O_UNIT)
+
+    /* converts requested slope into SigGen Freq */
+    #define VP890_SLOPE_TO_FREQ(AMP,SLOPE) (int16) ( ((int32)SLOPE * (int32)VP890_UNIT_RAMP_TIME) / (int32)AMP)
+
+    #define VP890_AC_RLOOP_MAX_BAT_LVL              75000L /* mV */
+    #define VP890_AC_RLOOP_MAX_TEST_LVL             ((VP890_AC_RLOOP_MAX_BAT_LVL - 5000) / 2)
+
+#endif /* VP890_INCLUDE_TESTLINE_CODE */
+
+/******************************************************************************
+ * COMPILE-TIME OPTIONS:: Top level VP-API Default Device and Line Options    *
+ *****************************************************************************/
+
+/* Debounce time to mask hook activity when a pol rev is generated */
+/*
+ * This duration covers conditions of 5REN FCC Part 68 load with 16ms Switch
+ * Hook Debounce. Applications are not expected to have much higher REN or longer
+ * Switch Hook Debounce times. If needed, this value can be changed but note
+ * that it affects all CSLAC devices.
+ */
+#define VP_POLREV_DEBOUNCE_TIME     (120)
+
+/*
+ *  The following defines specify the default settings of the device and line
+ * options used in the API. The VP-API-II should generally take on the default
+ * settings set here at VpInitDevice()/VpInitLine() but is not guaranteed (i.e.,
+ * the combinations are not tested - VpInitDevice()/InitLine() could fail as a
+ * result of setting to unexpected values).
+ *
+ * Please consult Zarlink Field or Applications support before changing any of
+ * these settings.
+ */
+#include "vp_api_option.h"
+#include "vp_api_event.h"
+
+/* Default Dial Pulse Options specified in units of 125micro sec  */
+#define VP_OPTION_DEFAULT_DP_BREAK_MIN          (33 * 8)    /* == 33 ms */
+#define VP_OPTION_DEFAULT_DP_BREAK_MAX          (100 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MIN           (17 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MAX           (75 * 8)
+#define VP_OPTION_DEFAULT_DP_INTER_DIG_MIN      (250 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MIN          (250 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MAX          (1300 * 8)
+#define VP_OPTION_DEFAULT_DP_ON_HOOK_MIN        VP_OPTION_DEFAULT_DP_FLASH_MAX
+#define VP_OPTION_DEFAULT_DP_OFF_HOOK_MIN       0
+
+/*
+ * Specification 2 is usefull if you need to detect between two non-overlapping
+ * dial pulse specifications.
+ */
+#define VP_OPTION_DEFAULT_DP_BREAK_MIN2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_BREAK_MAX2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MIN2          (0 * 8)
+#define VP_OPTION_DEFAULT_DP_MAKE_MAX2          (0 * 8)
+#define VP_OPTION_DEFAULT_DP_INTER_DIG_MIN2     (0 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MIN2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_FLASH_MAX2         (0 * 8)
+#define VP_OPTION_DEFAULT_DP_ON_HOOK_MIN2       (0 * 8)
+
+/* Default setting for Critical fault option */
+#define VP_OPTION_DEFAULT_CF_AC_DIS_EN          TRUE
+#define VP_OPTION_DEFAULT_CF_DC_DIS_EN          TRUE
+#define VP_OPTION_DEFAULT_CF_THERMAL_DIS_EN     TRUE
+/* CSLAC-880 and VCP-880 do not support the detection of AC, DC critical faults.
+ * So, The VP-API uses the following default values for those devices.
+ * Note that changing the following values will result in VpInitDevice()
+ * failure. */
+#define VP_OPTION_DEFAULT_CF_AC_DIS_EN_880      FALSE
+#define VP_OPTION_DEFAULT_CF_DC_DIS_EN_880      FALSE
+
+/* Default setting for Zero cross option */
+#define VP_OPTION_DEFAULT_ZERO_CROSS            VP_OPTION_ZC_M4B
+
+/* Default setting for Ramp to standby option */
+#define VP_OPTION_DEFAULT_RAMP2STBY             0
+
+/* Default setting for Pulse mode option */
+#define VP_OPTION_DEFAULT_PULSE_MODE            VP_OPTION_PULSE_DECODE_OFF
+
+/* Default CODEC Mode */
+#define VP_OPTION_DEFAULT_CODEC_MODE            VP_OPTION_ALAW
+
+/* Default setting for PCM Highway option */
+#define VP_OPTION_DEFAULT_PCM_HWY               VP_OPTION_HWY_A
+
+/* Default setting for Loop back option */
+#define VP_OPTION_DEFAULT_LOOP_BACK             VP_OPTION_LB_OFF
+
+/* Default setting for Line state option */
+#define VP_OPTION_DEFAULT_LS_BAT_REV            FALSE
+#define VP_OPTION_DEFAULT_LS_BAT                VP_OPTION_BAT_AUTO
+
+/*
+ * Default Event Masks (VP_OPTION_ID_EVENT_MASK)
+ * The user can arbitrarily set the mask bits here as needed.  A mask bit set to
+ * '0' means the event is not masked.  Some events are non-maskable.
+ */
+#define VP_OPTION_DEFAULT_FAULT_EVENT_MASK      (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_FAULT_EVENTS)
+#define VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK  (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_SIGNALING_EVENTS)
+#define VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK   (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_RESPONSE_EVENTS)
+#define VP_OPTION_DEFAULT_TEST_EVENT_MASK       (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_TEST_EVENTS)
+#define VP_OPTION_DEFAULT_PROCESS_EVENT_MASK    (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_PROCESS_EVENTS)
+#define VP_OPTION_DEFAULT_FXO_EVENT_MASK        (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_FXO_EVENTS)
+#define VP_OPTION_DEFAULT_PACKET_EVENT_MASK     (VP_EVENT_MASK_ALL & ~VP_API_NONMASK_PACKET_EVENTS)
+
+/* Default setting for Ring Control option */
+#define VP_OPTION_DEFAULT_RC_ZERO_CROSS         VP_OPTION_ZC_M4B
+#define VP_OPTION_DEFAULT_RC_RING_EXIT_DBNC_VAL (100 * 8) /* 100ms */
+#define VP_OPTION_DEFAULT_RC_RING_EXIT_STATE    VP_LINE_TALK
+
+/* Default setting for DTMF Mode option */
+#define VP_OPTION_DEFAULT_DM_DTMF_CONTROL_MODE  VP_OPTION_DTMF_DECODE_OFF
+#define VP_OPTION_DEFAULT_DM_DIRECTION          VP_DIRECTION_US
+
+/* Default setting for PCM TX/RX path control */
+#define VP_OPTION_DEFAULT_PCM_TXRX_CNTRL        VP_OPTION_PCM_BOTH
+
+/* Default setting for DTMF Spec option */
+#define VP_OPTION_DEFAULT_DTMF_SPEC             VP_OPTION_DTMF_SPEC_ATT
+
+/* Default setting for Park Mode option */
+#define VP_OPTION_DEFAULT_PARK_MODE_DISC        4   /* 2 seconds */
+#define VP_OPTION_DEFAULT_PARK_MODE_STANDBY     3   /* 300 ms */
+
+/* Default setting for DC Feed Slope option */
+#define VP_OPTION_DEFAULT_DCFEED_SLOPE          109 /* 4 V/ms */
+
+/* Default setting for hook detection mode option */
+#define VP_OPTION_DEFAULT_HOOK_DETECT_MODE      VP_OPTION_HOOKDET_NORMAL
+
+/* Default settings for PCM highway signaling and control */
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_ENABLE    FALSE
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_CTLTS     0
+#define VP_OPTION_DEFAULT_PCM_SIG_CTL_SIGTS     0
+
+/* Default setting for PCM highway lien state control mode */
+#define VP_OPTION_DEFAULT_LINESTATE_CTL_MODE    VP_OPTION_LINESTATE_CTL_NORMAL
+
+/* Default settings for Auto Loop Conditions option */
+#define VP_OPTION_DEFAULT_AUTO_LOOP_COND_SELECT 0
+#define VP_OPTION_DEFAULT_AUTO_LOOP_COND_DELAY  0
+
+
+/******************************************************************************
+ *    VCP2 library specific other defines and conditional compile flags       *
+ ******************************************************************************/
+
+/* Specify the maximum number of SLACs which will be controlled by the VCP2 on
+ * each SPI bus.
+ *
+ * For VCP2-790, there are up to 8 SLACs (32 channels) on each SPI bus.
+ *
+ * For VCP2-792, with the Le79124 chipset, normally there are up to 4 SLACs (32
+ * channels) on the first SPI bus and up to 5 SLACs (40 channels) on the second
+ * SPI bus.
+ *
+ * For VCP2-792, with the Le79128 chipset, there are up to 8 SLACs on each SPI
+ * bus.
+ */
+#define VP_VCP2_MAX_NUM_SLACS_BUS0 8
+#define VP_VCP2_MAX_NUM_SLACS_BUS1 8
+
+/* Specify the maximum number of channels controlled by any individual SLAC.
+ * If you are controlling a VCP2-792 device, this should be 8.  If you are
+ * controlling a VCP2-790 device, you can reduce this value to 4 to save
+ * memory.  If you are controlling a VCP2-880 device, you can reduce this value
+ * to 2 to save memory.  If you are controlling a combination of
+ * SLACs (unlikely), use the number corresponding to the SLAC with the most
+ * channels. */
+#define VP_VCP2_MAX_NUM_CHANS  8
+
+/* Set this option to support the VCP2 emulator. */
+#define VP_VCP2_EMU_SUPPORT
+
+/* Do not define this unless you know what you're doing. */
+#undef VP_VCP2_SUPPORT_UNDOCUMENTED_TESTS
+
+#define VP_SIZEOF_CID_MSG_BUFFER 16
+
+/******************************************************************************
+ *    MELT library specific other defines and conditional compile flags       *
+ ******************************************************************************/
+#define VP_MELT_MAX_NUM_SLACS 1
+#define VP_MELT_MAX_NUM_CHANS 8
+/******************************************************************************
+ *     VCP library specific other defines and conditional compile flags       *
+ ******************************************************************************/
+
+/* Define the following to enable debug print statements from the VCP API */
+#undef DEBUG_VCP_API
+
+#ifdef DEBUG_VCP_API
+#include <stdio.h>
+/* Define the following as necessary to redirect the debug output */
+#define term_printf printf
+
+/* Further classification enabling/disabling debug output */
+#define DEBUG_BOOTLOAD              /* Debug bootload function */
+#define DEBUG_VCP_API_MB            /* MailBox related debug output */
+#define DEBUG_VCP_API_EVENT         /* Event masking related debug output */
+#define DEBUG_VCP_API_DEFLT_OPTN    /* Default option debugging */
+#endif /* DEBUG_VCP_API */
+
+/******************************************************************************
+ *                      API Debug output redirection                          *
+ ******************************************************************************/
+#if defined(DEBUG_VCP_API)
+#ifndef term_printf
+#include <stdio.h>
+/* Define the following as necessary to redirect the debug output */
+#define term_printf printf
+#endif /* term_printf */
+#endif /* DEBUG_VCP_API  */
+
+#if defined (VP_CC_VCP_SERIES) || defined (VP_CC_VCP2_SERIES)
+/******************************************************************************
+ * Library Specific default options                                           *
+ *****************************************************************************/
+/* VoicePath API provides a mechanism where individual library's default
+ * options could be different compared to top level API default options.
+ * If you need such a change please review the file included below.
+ */
+#include "vp_api_lib_cfg.h"
+#endif
+#endif /* VP_API_CFG_INT_H */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_common.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_common.h
new file mode 100644
index 0000000..eebc4cf
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_common.h
@@ -0,0 +1,1891 @@
+/** \file vp_api_common.h
+ * vp_api_common.h
+ *
+ * Header file for the VP-API-II c files.
+ *
+ * This file contains all of the VP-API-II declarations that are Voice
+ * Termination Device (VTD) family independent.
+ *
+ * $Revision: 8620 $
+ * $LastChangedDate: 2011-06-02 13:27:26 -0500 (Thu, 02 Jun 2011) $
+ */
+
+#ifndef VP_API_COMMON_H
+#define VP_API_COMMON_H
+
+#include "vp_api_types.h"
+#include "vp_api_dev_term.h"
+#include "vp_api_event.h"
+#include "vp_api_option.h"
+#include "vp_api_test.h"
+
+
+/******************************************************************************
+ *                                DEFINES                                     *
+ ******************************************************************************/
+
+/*
+ * Profile Table Indexes
+ */
+#define VP_PTABLE_NULL      (VpProfilePtrType)0
+#define VP_PTABLE_INDEX1    (VpProfilePtrType)1
+#define VP_PTABLE_INDEX2    (VpProfilePtrType)2
+#define VP_PTABLE_INDEX3    (VpProfilePtrType)3
+#define VP_PTABLE_INDEX4    (VpProfilePtrType)4
+#define VP_PTABLE_INDEX5    (VpProfilePtrType)5
+#define VP_PTABLE_INDEX6    (VpProfilePtrType)6
+#define VP_PTABLE_INDEX7    (VpProfilePtrType)7
+#define VP_PTABLE_INDEX8    (VpProfilePtrType)8
+#define VP_PTABLE_INDEX9    (VpProfilePtrType)9
+#define VP_PTABLE_INDEX10   (VpProfilePtrType)10
+#define VP_PTABLE_INDEX11   (VpProfilePtrType)11
+#define VP_PTABLE_INDEX12   (VpProfilePtrType)12
+#define VP_PTABLE_INDEX13   (VpProfilePtrType)13
+#define VP_PTABLE_INDEX14   (VpProfilePtrType)14
+#define VP_PTABLE_INDEX15   (VpProfilePtrType)15
+#define VP_PTABLE_NO_INDEX   (VpProfilePtrType)99
+#define VP_PTABLE_MAX_INDEX VP_PTABLE_INDEX15
+#define VP_PTABLE_INDEX(n)  (VpProfilePtrType)(n)
+
+
+/*
+ *Utility macros:
+ */
+#ifndef ABS
+  #define ABS(arg) ((arg) < 0 ? -(arg) : (arg))
+#endif
+
+#ifndef MAX
+  #define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+  #define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX4
+  #define MAX4(a, b, c, d) MAX(MAX(a, b), MAX(c, d))
+#endif
+
+#ifndef MAX12
+  #define MAX12(a, b, c, d, e, f, g, h, i, j, k, l) \
+    MAX(MAX(MAX4(a, b, c, d), MAX4(e, f, g, h)), MAX4(i, j, k, l))
+#endif
+
+
+/******************************************************************************
+ *                    ENUMERATIONS AND NEW DATA TYPES                         *
+ ******************************************************************************/
+/** Standard return value for most API library functions.  See the VP-API-II
+    Reference Guide for descriptions. */
+typedef enum
+{
+    VP_STATUS_SUCCESS              = 0,
+    VP_STATUS_FAILURE              = 1,
+    VP_STATUS_FUNC_NOT_SUPPORTED   = 2,
+    VP_STATUS_INVALID_ARG          = 3,
+    VP_STATUS_MAILBOX_BUSY         = 4,
+    VP_STATUS_ERR_VTD_CODE         = 5,
+    VP_STATUS_OPTION_NOT_SUPPORTED = 6,
+    VP_STATUS_ERR_VERIFY           = 7,
+    VP_STATUS_DEVICE_BUSY          = 8,
+    VP_STATUS_MAILBOX_EMPTY        = 9,
+    VP_STATUS_ERR_MAILBOX_DATA     = 10,
+    VP_STATUS_ERR_HBI              = 11,
+    VP_STATUS_ERR_IMAGE            = 12,
+    VP_STATUS_IN_CRTCL_SECTN       = 13,
+    VP_STATUS_DEV_NOT_INITIALIZED  = 14,
+    VP_STATUS_ERR_PROFILE          = 15,
+    VP_STATUS_CUSTOM_TERM_NOT_CFG  = 17,
+    VP_STATUS_DEDICATED_PINS       = 18,
+    VP_STATUS_INVALID_LINE         = 19,
+    VP_STATUS_LINE_NOT_CONFIG      = 20,
+    VP_STATUS_INPUT_PARAM_OOR,  /* This enum value does not yet require to be a set value */
+    VP_STATUS_NUM_TYPES,
+    VP_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpStatusType;
+
+/* Enumeration for Boot load Function */
+typedef enum
+{
+    VP_BOOT_STATE_FIRST,        /* First block to download */
+    VP_BOOT_STATE_CONTINUE,     /* Additional block to download */
+    VP_BOOT_STATE_LAST,         /* Last block to download */
+    VP_BOOT_STATE_FIRSTLAST,    /* First and only block to download */
+    VP_NUM_BOOT_STATES,
+    VP_BOOT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBootStateType;
+
+/* Enumeration for Boot load Function */
+typedef enum
+{
+    VP_BOOT_MODE_NO_VERIFY,     /* No write verification is performed */
+    VP_BOOT_MODE_VERIFY,        /* Verify Load Image Checksum */
+    VP_NUM_BOOT_MODES,
+    VP_BOOT_MODE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBootModeType;
+
+/* Version and checksum information for VCP */
+typedef struct
+{
+    uint16 vtdRevCode;          /* Silicon Revision for VTD */
+    uint8 swProductId;          /* VTD Firmware ID */
+    uint8 swVerMajor;           /* Major Revision for VTD Firmware */
+    uint8 swVerMinor;           /* Minor Revision for VTD Firmware */
+} VpVersionInfoType;
+
+typedef struct
+{
+    uint32 loadChecksum;        /* Calculated Checksum for Code Image */
+    VpVersionInfoType vInfo;    /* Version Information for VTD HW/SW */
+} VpChkSumType;
+
+typedef enum
+{
+    VP_PROFILE_DEVICE      = 0, /* Device profile */
+    VP_PROFILE_AC          = 1, /* AC profile */
+    VP_PROFILE_DC          = 2, /* DC profile */
+    VP_PROFILE_RING        = 3, /* Ring profile */
+    VP_PROFILE_RINGCAD     = 4, /* Ringing cadence profile */
+    VP_PROFILE_TONE        = 5, /* Tone profile */
+    VP_PROFILE_METER       = 6, /* Metering profile */
+    VP_PROFILE_CID         = 7, /* Caller ID profile */
+    VP_PROFILE_TONECAD     = 8, /* Tone cadence profile */
+    VP_PROFILE_FXO_CONFIG,      /* FXO configuration profile */
+    VP_PROFILE_CUSTOM_TERM,     /* Custom Termination Type profile */
+    VP_PROFILE_CAL,             /* Used for VpCal when passing calibration coefficients */
+    VP_NUM_PROFILE_TYPES,
+    VP_PROFILE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProfileType;
+
+/**< typedef for VpCalCodec() function */
+typedef enum {
+    VP_DEV_CAL_NOW   = 0, /* Calibrate immediately */
+    VP_DEV_CAL_NBUSY = 1, /* Calibrate if all lines are "on-hook" */
+    VP_NUM_DEV_CAL_TYPES,
+    VP_DEV_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceCalType;
+
+/* Valid line states for VpSetLineState() */
+/* Defined else where */
+
+/**< The following types are for VpSetLineTone() function */
+typedef struct {
+    VpDigitType toneId;  /* Identifies the DTMF tone to generated */
+    VpDirectionType dir; /* Direction in which DTMF tone needs to be
+                          * generated */
+} VpDtmfToneGenType;
+
+typedef enum {
+  VP_DIGIT_GENERATION_DTMF,             /* Generate DTMF digit */
+  VP_DIGIT_GENERATION_DIAL_PULSE,       /* Generate pulse digit */
+  VP_DIGIT_GENERATION_DIAL_HOOK_FLASH,   /* Generate hook flash */
+  VP_DIGIT_GEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitGenerationType;
+
+typedef enum {
+  VP_BFILT_DIS = 0,
+  VP_BFILT_EN  = 1,
+  VP_BFILT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBFilterModeType;
+
+typedef enum {
+  VP_BATT_MODE_DIS = 0,
+  VP_BATT_MODE_EN  = 1,
+  VP_BATT_MODE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatteryModeType;
+
+typedef struct {
+    int16 batt1;
+    int16 batt2;
+    int16 batt3;
+} VpBatteryValuesType;
+
+/**< The following types are for VpSetRelayState() and VpGetRelayState() functions */
+typedef enum {
+    VP_RELAY_NORMAL         = 0,  /* No test access, ringing controlled
+                                   * by line state */
+    VP_RELAY_RESET          = 1,  /* LCAS all-off state, test-out released */
+    VP_RELAY_TESTOUT        = 2,  /* LCAS all-off state, test-out active */
+    VP_RELAY_TALK           = 3,  /* LCAS talk state, test-out released */
+    VP_RELAY_RINGING        = 4,  /* LCAS ringing state, test-out released */
+    VP_RELAY_TEST           = 5,  /* LCAS test state, test-out released */
+    VP_RELAY_BRIDGED_TEST   = 6,  /* LCAS test/monitor state,
+                                   * test-out released */
+    VP_RELAY_SPLIT_TEST     = 7,  /* LCAS test/monitor state,
+                                   * test-out active */
+    VP_RELAY_DISCONNECT     = 8,  /* LCAS talk state, test-out active */
+    VP_RELAY_RINGING_NOLOAD = 9,  /* LCAS ringing state, test-out active */
+    VP_RELAY_RINGING_TEST   = 10, /* LCAS test ringing state,
+                                   * test-out active */
+    VP_RELAY_LAMP_ON        = 11, /* VCP2-790 FXS_TL_MW only */
+    VP_RELAY_IDLE           = 12, /* All switches open, test switch off */
+    VP_NUM_RELAY_STATES,
+    VP_RELAY_ENUM_RSVD  = FORCE_SIGNED_ENUM,
+    VP_RELAY_ENUM_SIZE  = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpRelayControlType;
+
+/**< The following types are for VpSetCalRelayState() function */
+typedef enum {
+    VP_CAL_RELAY_OPEN,                /* Open circuit                      */
+    VP_CAL_RELAY_R_DIFF_LOW_TIP_RING, /* Res Tip-to-Ring: R_DIFF_LOW Ohms  */
+    VP_CAL_RELAY_R_CM_REF_TIP_GND,    /* Res Tip-to-Gnd:  R_CM_REF Ohms    */
+    VP_CAL_RELAY_V_CAL_REF_TIP_GND,   /* Volt Tip:        V_CAL_REF Volts  */
+    VP_CAL_RELAY_SHORT_TIP_RING,      /* Res Tip-to-Ring: short (0 Ohms)   */
+    VP_CAL_RELAY_R_DIFF_HIGH_TIP_RING,/* Res Tip-to-Ring: R_DIFF_HIGH Ohms */
+    VP_CAL_RELAY_R_CM_REF_RING_GND,   /* Res Ring-to-Gnd: R_CM_REF Ohms    */
+    VP_CAL_RELAY_V_CAL_REF_RING_GND,  /* Volt Ring:       V_CAL_REF Volts  */
+    VP_CAL_RELAY_NUM_STATES,
+    VP_CAL_RELAY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCalRelayControlType;
+
+/**< The following types are for VpSetRelGain() function */
+typedef enum {
+    VP_GAIN_SUCCESS  = 0, /* Gain setting adjusted successfully */
+    VP_GAIN_GR_OOR   = 1, /* GR Gain setting overflowed (reset to default) */
+    VP_GAIN_GX_OOR   = 2, /* GX Gain setting overflowed (reset to default) */
+    VP_GAIN_BOTH_OOR = 3, /* Both GR & GX overflowed (and reset to default) */
+    VP_GAIN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGainResultType;
+
+typedef struct {
+    VpGainResultType gResult; /* Success / Failure status return */
+    uint16 gxValue;           /* new GX register abs value */
+    uint16 grValue;           /* new GR register abs value */
+} VpRelGainResultsType;
+
+/* The number of 16 bits words used to define whether seal current
+ * should be applied to lines 0-127 */
+#define VP_SEAL_CURRENT_ARRAY_SIZE 8
+
+typedef struct {
+    uint16 sealApplyTime;
+    uint16 sealCycleTime;
+    uint16 maxCurrent;
+    uint16 minCurrent;
+    uint16 sealMaskArray[VP_SEAL_CURRENT_ARRAY_SIZE];
+} VpSealCurType;
+
+/**< The following types are for the VpQuery() function */
+typedef enum {
+    VP_QUERY_ID_TEMPERATURE = 0,
+    VP_QUERY_ID_METER_COUNT = 1,
+    VP_QUERY_ID_LOOP_RES    = 2,
+    VP_QUERY_ID_SEAL_CUR    = 3,
+    VP_NUM_QUERY_IDS,
+    VP_QUERY_ID_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpQueryIdType;
+
+typedef union {
+    int16 temp;
+    uint16 meterCount;
+    uint16 rloop;
+    VpSealCurType sealCur;
+} VpQueryResultsType;
+
+/**< The following types are for VpLineIoAccess() function */
+typedef enum {
+    VP_IO_WRITE = 0,
+    VP_IO_READ  = 1,
+    VP_IO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpIoDirectionType;
+
+typedef struct {
+    uint8 mask;
+    uint8 data;
+} VpLineIoBitsType;
+
+typedef struct {
+    VpIoDirectionType direction;
+    VpLineIoBitsType ioBits;
+} VpLineIoAccessType;
+
+/**< The following types are for VpDeviceIoAccess() function */
+typedef enum {
+    VP_DEVICE_IO_WRITE = 0, /* Perform device specific IO write access */
+    VP_DEVICE_IO_READ  = 1, /* Perform device specific IO read access */
+    VP_DEVICE_IO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceIoAccessType;
+
+typedef enum {
+    VP_DEVICE_IO_IGNORE = 0, /* Ignore I/O access */
+    VP_DEVICE_IO_ACCESS = 1, /* Perform I/O access */
+    VP_DEVUCE_IOA_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceIoAccessMask;
+
+typedef struct {
+    VpDeviceIoAccessType accessType;/* Device I/O access type */
+    uint32 accessMask_31_0;         /* I/O access mask (Pins 0 - 31) */
+    uint32 accessMask_63_32;        /* I/O access mask (Pins 32 - 63) */
+    uint32 deviceIOData_31_0;   /* Output pin data (Pins 0 - 31) */
+    uint32 deviceIOData_63_32;  /* Output pin data (Pins 32 - 63) */
+} VpDeviceIoAccessDataType;
+
+/**< The following types are for VpDeviceIoAccessExt() function */
+
+typedef struct {
+    VpIoDirectionType direction;
+    VpLineIoBitsType lineIoBits[VP_MAX_LINES_PER_DEVICE];
+} VpDeviceIoAccessExtType;
+
+/**< The following types are for VpGetLineStatus() function */
+typedef enum {
+    VP_INPUT_HOOK      = 0, /* Hook Status (ignoring pulse & flash) */
+    VP_INPUT_RAW_HOOK  = 1, /* Hook Status (include pulse & flash) */
+    VP_INPUT_GKEY      = 2, /* Ground-Key/Fault Status */
+    VP_INPUT_THERM_FLT = 3, /* Thermal Fault Status */
+    VP_INPUT_CLK_FLT   = 4, /* Clock Fault Status */
+    VP_INPUT_AC_FLT    = 5, /* AC Fault Status */
+    VP_INPUT_DC_FLT    = 6, /* DC Fault Status */
+    VP_INPUT_BAT1_FLT  = 7, /* Battery 1 Fault Status */
+    VP_INPUT_BAT2_FLT  = 8, /* Battery 2 Fault Status */
+    VP_INPUT_BAT3_FLT  = 9, /* Battery 3 Fault Status */
+
+    VP_INPUT_RINGING,    /* Ringing Status */
+    VP_INPUT_LIU,        /* Line In Use Status */
+    VP_INPUT_FEED_DIS,   /* Feed Disable Status */
+    VP_INPUT_FEED_EN,    /* Feed Enable Status */
+    VP_INPUT_DISCONNECT, /* Feed Disconnect Status */
+    VP_INPUT_CONNECT,    /* Feed Connect Status */
+    VP_INPUT_POLREV,     /* Reverse Polarity if TRUE, Normal if FALSE */
+    VP_INPUT_RES_LEAK,   /* Resistive Leakage on line if TRUE */
+
+    VP_NUM_INPUT_TYPES,
+    VP_INPUT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpInputType;
+
+/**< The following type is for the VpGetDeviceStatusExt() function: */
+typedef struct {
+    VpInputType input;
+    uint8 status[VP_LINE_FLAG_BYTES];
+} VpDeviceStatusType;
+
+/**< The following types are for VpGetLoopCond() function (return via
+ * VpGetResults())
+ */
+typedef enum {
+    VP_BATTERY_UNDEFINED = 0, /* Battery being used is not known or feature
+                               * not supported */
+    VP_BATTERY_1         = 1, /* Battery 1 */
+    VP_BATTERY_2         = 2, /* Battery 2 */
+    VP_BATTERY_3         = 3, /* Battery 3 */
+    VP_NUM_BATTERY_TYPES,
+    VP_BATTERY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatteryType;
+
+typedef enum {
+    VP_DF_UNDEFINED    = 0, /* DC feed region not known or feature not
+                             * supported */
+    VP_DF_ANTI_SAT_REG = 1, /* DC feed is in anti saturation region */
+    VP_DF_CNST_CUR_REG = 2, /* DC feed is in constant current region */
+    VP_DF_RES_FEED_REG = 3, /* DC feed is in resistive feed region */
+    VP_NUM_DC_FEED_TYPES,
+    VP_DC_FEED_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDcFeedRegionType;
+
+typedef struct {
+    int16 rloop;                    /**< The loop resistance */
+    int16 ilg;                      /**< The longitudinal loop current */
+    int16 imt;                      /**< The metallic loop current */
+    int16 vsab;                     /**< The tip/ring voltage */
+    int16 vbat1;                    /**< The Battery 1 voltage */
+    int16 vbat2;                    /**< The Battery 2 voltage */
+    int16 vbat3;                    /**< The Battery 3 voltage */
+    int16 mspl;                     /**< Metering signal peak level */
+    VpBatteryType selectedBat;      /**< Battery that is presently used for
+                                     *   the DC feed */
+    VpDcFeedRegionType dcFeedReg;   /**< DC feed region presently selected */
+} VpLoopCondResultsType;
+
+/**< The following types are used for the function VpSendSignal() */
+typedef enum {
+    VP_SENDSIG_MSG_WAIT_PULSE      = 0,
+    VP_SENDSIG_DTMF_DIGIT          = 1,
+    VP_SENDSIG_PULSE_DIGIT         = 2,
+    VP_SENDSIG_HOOK_FLASH          = 3,
+    VP_SENDSIG_FWD_DISCONNECT      = 4,
+    VP_SENDSIG_POLREV_PULSE        = 5,
+    VP_SENDSIG_MOMENTARY_LOOP_OPEN = 6,
+    VP_SENDSIG_TIP_OPEN_PULSE      = 7,
+    VP_SENDSIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSendSignalType;
+
+typedef struct {
+    int8 voltage;   /**< Voltage in Volts to apply to the line. A negative
+                     * value means Tip is more Negative than Ring, a positive
+                     * value means Ring is more Negative than Tip.
+                     */
+    uint16 onTime;  /**< Duration of pulse on-time in mS */
+    uint16 offTime; /**< Duration of pulse off-tim in mS. If the off-time is
+                     * set to 0, the voltage is applied to the line continuously
+                     */
+    uint8 cycles;   /**< Number of pulses to send on the line. If set to 0, will
+                     * repeat forever
+                     */
+} VpSendMsgWaitType;
+
+/**< The following type is used for the function VpGenTimerCtrl() */
+typedef enum {
+    VP_GEN_TIMER_START  = 0,
+    VP_GEN_TIMER_CANCEL = 1,
+    VP_GEN_TIMER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGenTimerCtrlType;
+
+/**< The enum is used by the system service layer pcmCollect() function */
+typedef enum {
+    VP_PCM_OPERATION_AVERAGE      = 0x0001, /* average PCM samples */
+    VP_PCM_OPERATION_RANGE        = 0x0002, /* find pk to pk pcm sample data. */
+    VP_PCM_OPERATION_RMS          = 0x0004, /* find rms value of pcm samples */
+    VP_PCM_OPERATION_MIN          = 0x0008, /* find min pcm value of pcm samples */
+    VP_PCM_OPERATION_MAX          = 0x0010, /* find max pcm value of pcm samples */
+    VP_PCM_OPERATION_APP_SPECIFIC = 0x0020, /* generic operation */
+    VP_PCM_OPERATION_FREQ         = 0x0040, /* Measure frequency */
+    VP_PCM_OPERATION_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPcmOperationBitType;
+
+typedef uint16 VpPcmOperationMaskType;
+
+typedef struct {
+    int16 average;  /* Average value of all collected PCM samples */
+    int16 range;    /* Maximum - minimum PCM value during operation time */
+    int16 rms;      /* RMS result of all collected pcm samples */
+    int16 min;      /* Maximum pcm value found */
+    int16 max;      /* Minimum pcm value found */
+    void *pApplicationInfo; /* Any results that the implementation chooses to
+                             * pass. This data is not interpreted neither
+                             * by the VP-API nor the LT-API. LT-API passes
+                             * this pointer back to the application as part
+                             * of the test result
+                             */
+    int32 freq;     /* Measured average frequenny */
+
+    bool error;     /* indication of PCM operation process (1 = failure) */
+} VpPcmOperationResultsType;
+
+/**< The enum is used by the cal function */
+typedef enum {
+    VP_CAL_BFILTER              = 1,
+    VP_CAL_APPLY_BFILTER        = 2,
+    VP_CAL_MEASURE_BFILTER      = 3,
+    VP_CAL_GET_SYSTEM_COEFF     = 4,
+    VP_CAL_APPLY_SYSTEM_COEFF   = 5,
+    VP_CAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCalType;
+
+typedef struct {
+    uint16 vRms;    /**< Customer Target Value in approximate vRms */
+    VpProfilePtrType pAcProfile;
+} VpCalBFilterType;
+
+typedef struct {
+    VpProfilePtrType pAcProfile;
+    uint16 index;
+} VpCalApplyBFilterType;
+
+typedef enum {
+    VP_CAL_SUCCESS,
+    VP_CAL_FAILURE,
+    VP_CAL_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCalStatusType;
+
+typedef enum {
+    VP_LOWLEV_PAGE_WR = 0,
+    VP_LOWLEV_PAGE_RD = 1,
+    VP_LOWLEV_MBOX_WR = 2,
+    VP_LOWLEV_MBOX_RD = 3,
+    VP_LOWLEV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpLowLevelCmdType;
+
+typedef enum {
+
+    /* Device parameters */
+
+    /* DC parameters */
+    VP_PROF_FIELD_ILA
+
+} VpProfileFieldIdType;
+
+typedef struct {
+    VpProfileFieldIdType fieldId;
+
+    union {
+        uint16 ila;
+    } data;
+
+} VpProfileFieldType;
+
+/* The following struct can be passed to VpGetResults() if the event ID is not
+   known at compile time, to ensure that the buffer is large enough regardless
+   of the result type. */
+typedef union {
+    VpChkSumType codeChecksum;                  /* VP_DEV_EVID_BOOT_CMP or
+                                                   VP_DEV_EVID_CHKSUM          */
+    VpRelGainResultsType setRelGain;            /* VP_LINE_EVID_GAIN_CMP       */
+    uint8 lowLevelCmd[256];                     /* VP_LINE_EVID_LLCMD_RX_CMP   */
+    VpLoopCondResultsType getLoopCond;          /* VP_LINE_EVID_RD_LOOP        */
+    VpOptionValueType getOption;                /* VP_LINE_EVID_RD_OPTION      */
+    VpTestResultType testLine;                  /* VP_LINE_EVID_TEST_CMP       */
+    VpDeviceIoAccessDataType deviceIoAccess;    /* VP_DEV_EVID_IO_ACCESS_CMP   */
+    VpDeviceIoAccessExtType deviceIoAccessExt;  /* VP_DEV_EVID_IO_ACCESS_CMP   */
+    VpLineIoAccessType lineIoAccess;            /* VP_LINE_EVID_LINE_IO_RD_CMP */
+    VpQueryResultsType query;                   /* VP_LINE_EVID_QUERY_CMP      */
+} VpResultsType;
+
+typedef enum {
+    VP_FREE_RUN_START,
+    VP_FREE_RUN_STOP
+} VpFreeRunModeType;
+
+/******************************************************************************
+ *                 DEVICE/LINE CONTEXT (SUPPORT) DEFINITION                   *
+ ******************************************************************************/
+/* The following function pointers are required to get around problem of
+ * what comes first? chicken or the egg? when dealing with declaration of
+ * device context, function pointer table and hence the following declarations.
+ */
+struct VpDevCtxType;    /**< forward declaration */
+struct VpLineCtxType;   /**< forward declaration */
+struct VpEventType;     /**< forward declaration */
+
+/*
+ * System Configuration functions
+ */
+typedef VpStatusType
+(*VpMakeLineObjectFuncPtrType) (
+    VpTermType termType,
+    uint8 channelId,
+    struct VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    struct VpDevCtxType *pDevCtx);
+
+/*
+ * Initialization functions
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpBootLoadFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+typedef VpStatusType
+(*VpBootSlacFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize);
+#endif  /* !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * | defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpInitDeviceFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile,
+    VpProfilePtrType pFxoAcProfile,
+    VpProfilePtrType pFxoCfgProfile);
+
+typedef VpStatusType
+(*VpFreeRunFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpFreeRunModeType freeRunMode);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpInitSlacFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpInitLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+typedef VpStatusType
+(*VpConfigLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+typedef VpStatusType
+(*VpSetBFilterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpBFilterModeType bFiltMode,
+    VpProfilePtrType pAcProfile);
+
+typedef VpStatusType
+(*VpSetBatteriesFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpBatteryModeType battMode,
+    VpBatteryValuesType *pBatt);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+                                || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+typedef VpStatusType
+(*VpCalCodecFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpDeviceCalType mode);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+         * || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+         */
+
+typedef VpStatusType
+(*VpCalLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx);
+
+typedef VpStatusType
+(*VpCalFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpCalType calType,
+    void *inputArgs);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+typedef VpStatusType
+(*VpInitRingFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCadProfile,
+    VpProfilePtrType pCidProfile);
+
+typedef VpStatusType
+(*VpInitCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpInitMeterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+typedef VpStatusType
+(*VpInitCustomTermTypeFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCustomTermProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+typedef VpStatusType
+(*VpInitProfileFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpProfileType type,
+    VpProfilePtrType pProfileIndex,
+    VpProfilePtrType pProfile);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpSoftResetFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Control functions
+ */
+typedef VpStatusType
+(*VpSetLineStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+typedef VpStatusType
+(*VpSetLineToneFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+typedef VpStatusType
+(*VpSetRelayStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpRelayControlType rState);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+typedef VpStatusType
+(*VpSetCalRelayStateFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpCalRelayControlType rState);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+typedef VpStatusType
+(*VpSetRelGainFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 txLevel,
+    uint16 rxLevel,
+    uint16 handle);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+typedef VpStatusType
+(*VpSendSignalFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpSendSignalType signalType,
+    void *pSignalData);
+
+typedef VpStatusType
+(*VpSendCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    VpProfilePtrType pCidProfile,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpContinueCidFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+typedef VpStatusType
+(*VpStartMeterFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpStartMeter32QFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint32 minDelay,
+    uint32 onTime,
+    uint32 offTime,
+    uint16 numMeters,
+    uint16 eventRate);
+
+typedef VpStatusType
+(*VpGenTimerCtrlFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpGenTimerCtrlType timerCtrl,
+    uint32 duration,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpAssocDslLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    bool connect,
+    uint8 line);
+
+typedef VpStatusType
+(*VpSetSealCurFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    uint16 sealApplyTime,
+    uint16 sealCycleTime,
+    uint16 maxCurrent,
+    uint16 minCurrent,
+    uint16 *pSealArray,
+    VpProfilePtrType pDcProfile);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpSetOptionFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    void *pValue);
+
+typedef VpStatusType
+(*VpDeviceIoAccessFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessDataType *pDeviceIoData);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpDeviceIoAccessExtFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessExtType *pDeviceIoAccess);
+
+typedef VpStatusType
+(*VpLineIoAccessFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineIoAccessType *pLineIoAccess,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+typedef VpStatusType
+(*VpVirtualISRFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpApiTickFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    bool *pEventStatus);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(ZARLINK_CFG_INTERNAL)
+typedef VpStatusType
+(*VpLowLevelCmdFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint8 *pCmdData,
+    uint8 len,
+    uint16 handle);
+#endif
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpLowLevelCmd16FuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLowLevelCmdType cmdType,
+    uint16 *writeWords,
+    uint8 numWriteWords,
+    uint8 numReadWords,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Status and query functions
+ */
+
+typedef bool
+(*VpGetEventFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    struct VpEventType *pEvent);
+
+typedef VpStatusType
+(*VpGetLineStatusFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+typedef VpStatusType
+(*VpGetDeviceStatusFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpInputType input,
+    uint32 *pDeviceStatus);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpGetDeviceStatusExtFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    VpDeviceStatusType *pDeviceStatus);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+typedef VpStatusType
+(*VpGetLoopCondFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+typedef VpStatusType
+(*VpGetOptionFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpGetLineStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpLineStateType *pCurrentState);
+
+typedef VpStatusType
+(*VpFlushEventsFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpGetResultsFuncPtrType) (
+    struct VpEventType *pEvent,
+    void *pResults);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpClearResultsFuncPtrType) (
+    struct VpDevCtxType *pDevCtx);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+                                || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+typedef VpStatusType
+(*VpGetRelayStateFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpRelayControlType *pRstate);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+         * || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+         */
+
+typedef VpStatusType
+(*VpObjectDumpFuncPtrType)(
+    struct VpLineCtxType *pLineCtx,
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpRegisterDumpFuncPtrType)(
+    struct VpDevCtxType *pDevCtx);
+
+typedef VpStatusType
+(*VpDtmfDigitDetectedFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+
+typedef VpStatusType
+(*VpQueryFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpQueryIdType queryId,
+    uint16 handle);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+/*
+ * Test Functions
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+                                || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+typedef VpStatusType
+(*VpTestLineFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpTestLineIntFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle,
+    bool callback);
+
+typedef VpStatusType
+(*VpTestLineCallbackType) (
+    struct VpLineCtxType *pLineCtx,
+    VpPcmOperationResultsType *pResults);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+typedef VpStatusType
+(*VpCodeCheckSumFuncPtrType) (
+    struct VpDevCtxType *pDevCtx,
+    uint16 handle);
+
+typedef VpStatusType
+(*VpSelfTestFuncPtrType) (
+    struct VpLineCtxType *pLineCtx);
+
+typedef VpStatusType
+(*VpFillTestBufFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+typedef VpStatusType
+(*VpReadTestBufFuncPtrType) (
+    struct VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+         * || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+         */
+
+/** ApiFunctionPointer Table to be used by Device Context */
+typedef struct {
+    /* System Configuration Functions */
+    VpMakeLineObjectFuncPtrType MakeLineObject;
+
+    /* Initialization Functions */
+    /*   -- Init Functions common to all devices and VP-API-II configuration modes */
+    VpInitDeviceFuncPtrType InitDevice;
+    VpFreeRunFuncPtrType FreeRun;
+
+    VpInitLineFuncPtrType InitLine;
+    VpConfigLineFuncPtrType ConfigLine;
+
+    VpCalLineFuncPtrType CalLine;
+    VpCalFuncPtrType Cal;
+    VpInitProfileFuncPtrType InitProfile;
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+    VpBootLoadFuncPtrType BootLoad;
+    VpBootSlacFuncPtrType BootSlac;
+    VpInitSlacFuncPtrType InitSlac;
+    VpSoftResetFuncPtrType SoftReset;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpSetBFilterFuncPtrType SetBFilter;
+    VpSetBatteriesFuncPtrType SetBatteries;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES) \
+                                || (defined(VP_CC_880_SERIES) && defined(VP_ENABLE_PROD_TEST))
+    VpCalCodecFuncPtrType CalCodec;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II except VE580 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+    VpInitCustomTermTypeFuncPtrType InitCustomTerm;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CC_580_SERIES)
+         */
+
+    /*   -- Init Functions NOT provided in CSLAC VP-API-II Lite Version */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+    VpInitRingFuncPtrType InitRing;
+    VpInitCidFuncPtrType InitCid;
+    VpInitMeterFuncPtrType InitMeter;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP) || defined(VP_CSLAC_SEQ_EN)
+         */
+
+    /* Control Functions */
+    /*   -- Control Functions common to all devices and VP-API-II configuration modes */
+    VpSetLineStateFuncPtrType SetLineState;
+    VpSetLineToneFuncPtrType SetLineTone;
+    VpSetRelayStateFuncPtrType SetRelayState;
+    VpSetRelGainFuncPtrType SetRelGain;
+
+    VpSetOptionFuncPtrType SetOption;
+    VpDeviceIoAccessFuncPtrType DeviceIoAccess;
+    VpVirtualISRFuncPtrType VirtualISR;
+    VpApiTickFuncPtrType ApiTick;
+
+    /*   -- Control Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+    VpSetCalRelayStateFuncPtrType SetCalRelayState;
+
+    VpStartMeter32QFuncPtrType StartMeter32Q;
+    VpGenTimerCtrlFuncPtrType GenTimerCtrl;
+    VpAssocDslLineFuncPtrType AssocDslLine;
+    VpSetSealCurFuncPtrType SetSealCur;
+
+    VpDeviceIoAccessExtFuncPtrType DeviceIoAccessExt;
+    VpLineIoAccessFuncPtrType LineIoAccess;
+
+    VpLowLevelCmd16FuncPtrType LowLevelCmd16;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)
+         */
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP) || defined(ZARLINK_CFG_INTERNAL)
+    VpLowLevelCmdFuncPtrType LowLevelCmd;
+#endif
+
+    /*   -- Control Functions NOT provided in CSLAC VP-API-II Lite Version */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+    VpSendSignalFuncPtrType SendSignal;
+    VpSendCidFuncPtrType SendCid;
+    VpContinueCidFuncPtrType ContinueCid;
+    VpStartMeterFuncPtrType StartMeter;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+         * || defined(VP_CC_KWRAP)  || defined(VP_CSLAC_SEQ_EN)
+         */
+
+    /* Status and Query Functions */
+    /*   -- Status and Query Functions common to all devices and VP-API-II configuration modes */
+    VpGetEventFuncPtrType GetEvent;
+    VpGetLineStatusFuncPtrType GetLineStatus;
+    VpGetDeviceStatusFuncPtrType GetDeviceStatus;
+
+    VpGetOptionFuncPtrType GetOption;
+    VpGetLineStateFuncPtrType GetLineState;
+    VpFlushEventsFuncPtrType FlushEvents;
+    VpGetResultsFuncPtrType GetResults;
+
+    VpObjectDumpFuncPtrType ObjectDump;
+    VpRegisterDumpFuncPtrType RegisterDump;
+    VpDtmfDigitDetectedFuncPtrType DtmfDigitDetected;
+
+    /*   -- Status and Query Functions used only for CSLAC Line Testing */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+                                || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+    VpGetRelayStateFuncPtrType GetRelayState;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP880_INCLUDE_TESTLINE_CODE) && defined(VP_CC_880_SERIES)) \
+         * || (defined(VP890_INCLUDE_TESTLINE_CODE) && defined(VP_CC_890_SERIES))
+         */
+
+    /*   -- Status and Query Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+    VpGetDeviceStatusExtFuncPtrType GetDeviceStatusExt;
+    VpClearResultsFuncPtrType ClearResults;
+    VpQueryFuncPtrType Query;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES)  || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Status and Query Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpGetLoopCondFuncPtrType GetLoopCond;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+    /* Test Functions */
+    /*   -- All test functions removed for CSLAC VP-API-II unless Line Test is included */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+                                || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+                                || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+    /*   -- Test Functions common to all devices and VP-API-II configuration modes */
+    VpTestLineFuncPtrType TestLine;
+    VpTestLineIntFuncPtrType TestLineInt;
+    VpTestLineCallbackType TestLineCallback;
+
+    /*   -- Test Functions NOT provided in CSLAC VP-API-II */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+                                 || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+    VpCodeCheckSumFuncPtrType CodeCheckSum;
+    VpFillTestBufFuncPtrType FillTestBuf;
+    VpReadTestBufFuncPtrType ReadTestBuf;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP)
+         */
+
+    /*   -- Test Functions NOT provided in CSLAC VP-API-II except VE790 */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+            || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+    VpSelfTestFuncPtrType SelfTest;
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         *  || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) || defined(VP_CC_790_SERIES)
+         */
+
+#endif  /*
+         * !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES) \
+         * || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) || defined(VP_CC_KWRAP) \
+         * || (defined(VP_CC_880_SERIES) && defined (VP880_INCLUDE_TESTLINE_CODE)) \
+         * || (defined(VP_CC_890_SERIES) && defined (VP890_INCLUDE_TESTLINE_CODE))
+         */
+} ApiFunctions;
+
+/******************************************************************************
+ *                       DEVICE/LINE CONTEXT DEFINITION                       *
+ ******************************************************************************/
+/** Voice Path Line Context type */
+typedef struct VpLineCtxType {
+    struct VpDevCtxType *pDevCtx;   /**< Pointer back Device Context */
+
+    void *pLineObj;                 /**< Pointer (forward) to Line Object */
+} VpLineCtxType;
+
+/** Voice Path Device Context type */
+typedef struct VpDevCtxType {
+    VpDeviceType deviceType;    /**< What type is the device context (enum) */
+    void *pDevObj;              /**< Pointer to device object */
+
+    ApiFunctions funPtrsToApiFuncs; /**< Pointers to API functions */
+
+    /**< Pointers to each line context associated with this device.  Set size
+     * to max allowable per device in system
+     */
+    VpLineCtxType *pLineCtx[VP_MAX_LINES_PER_DEVICE];
+} VpDevCtxType;
+
+/******************************************************************************
+ *                        VP-API-II Definitions that use context              *
+ ******************************************************************************/
+/** Event struct: Type reported by VpGetEvent(). */
+typedef struct VpEventType {
+    VpStatusType status;        /**< Function return status */
+
+    uint8 channelId;            /**< Channel that caused the event */
+
+    VpLineCtxType *pLineCtx;    /**< Pointer to the line context (corresponding
+                                 *   to the channel that caused the event) */
+
+    VpDeviceIdType deviceId;    /**< device chip select ID corresponding to the
+                                 *   device that caused the event */
+
+    VpDevCtxType *pDevCtx;      /**< Pointer to the device context
+                                 *   (corresponding to the device that caused
+                                 *   the event) */
+
+    VpEventCategoryType eventCategory; /**< Event category.  The event catagory
+                                        *   is necessary because there are more
+                                        *   events than can be specified by the
+                                        *   size of "eventId  */
+
+    uint16 eventId;     /**< The event that occurred.  Requires that the event
+                         *   catagory be known to interpret */
+
+    uint16 parmHandle;  /**< Event�s Parameter or Host Handle.  This value is
+                         *   specified by the application only, not used by the
+                         *   API */
+
+    uint16 eventData;   /**< Data associated with the event. Event Id specific*/
+
+    bool hasResults;    /**< If TRUE indicates this event has results associated
+                         *   with it */
+
+    VpLineIdType lineId;    /**< Application provide line Id to ease mapping of
+                             * lines to specific line contexts.
+                             */
+} VpEventType;
+
+/**< The following types are for VpGetDeviceInfo() and VpGetLineInfo()
+ * functions */
+
+typedef enum {
+    VP_UNKNOWN,
+    VP_AVAILABLE,
+    VP_NOT_AVAILABLE
+} VpFeatureType;
+
+typedef struct {
+    VpFeatureType testLoadSwitch;
+    VpFeatureType internalTestTermination;
+} VpFeatureListType;
+
+typedef struct {
+    VpLineCtxType *pLineCtx;            /* Pointer to Line Context */
+    VpDeviceIdType deviceId;            /* Device identity */
+    VpDevCtxType *pDevCtx;              /* Pointer to device Context */
+    VpDeviceType deviceType;            /* Device Type */
+    VpFeatureListType featureList;      /* Store the device features */
+    uint8 numLines;                     /* Number of lines */
+    uint8 revCode;                      /* Revision Code Number */
+    uint8 slacId;                       /* Unique ID associated with Device identity */
+    uint16 productCode;                 /* Number indicating features of the device.*/
+} VpDeviceInfoType;
+
+typedef struct {
+    VpDevCtxType *pDevCtx;       /* Pointer to device Context */
+    uint8 channelId;             /* Channel identity */
+    VpLineCtxType *pLineCtx;     /* Pointer to Line Context */
+    VpTermType termType;         /* Termination Type */
+    VpLineIdType lineId;         /* Application system wide line identifier */
+} VpLineInfoType;
+
+/******************************************************************************
+ *                        VP-API-II FUNCTION PROTOTYPES                       *
+ ******************************************************************************/
+/*
+ * System configuration functions
+ */
+EXTERN VpStatusType
+VpMakeDeviceObject(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    VpDevCtxType *pDevCtx,
+    void *pDevObj);
+
+EXTERN VpStatusType
+VpMakeDeviceCtx(
+    VpDeviceType deviceType,
+    VpDevCtxType *pDevCtx,
+    void *pDevObj);
+
+EXTERN VpStatusType
+VpMakeLineObject(
+    VpTermType termType,
+    uint8 channelId,
+    VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpMakeLineCtx(
+    VpLineCtxType *pLineCtx,
+    void *pLineObj,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpFreeLineCtx(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpGetDeviceInfo(
+    VpDeviceInfoType *pDeviceInfo);
+
+EXTERN VpStatusType
+VpGetLineInfo(
+    VpLineInfoType *pLineInfo);
+
+/*
+ * Initialization functions
+ */
+EXTERN VpStatusType
+VpBootLoad(
+    VpDevCtxType *pDevCtx,
+    VpBootStateType state,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize,
+    VpScratchMemType *pScratchMem,
+    VpBootModeType validation);
+
+EXTERN VpStatusType
+VpBootSlac(
+    VpLineCtxType *pLineCtx,
+    VpImagePtrType pImageBuffer,
+    uint32 bufferSize);
+
+EXTERN VpStatusType
+VpInitDevice(
+    VpDevCtxType *pDevCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile,
+    VpProfilePtrType pFxoAcProfile,
+    VpProfilePtrType pFxoCfgProfile);
+
+EXTERN VpStatusType
+VpFreeRun(
+    VpDevCtxType *pDevCtx,
+    VpFreeRunModeType freeRunMode);
+
+EXTERN VpStatusType
+VpInitSlac(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pDevProfile,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpInitLine(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpConfigLine(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pAcProfile,
+    VpProfilePtrType pDcFeedOrFxoCfgProfile,
+    VpProfilePtrType pRingProfile);
+
+EXTERN VpStatusType
+VpCalCodec(
+    VpLineCtxType *pLineCtx,
+    VpDeviceCalType mode);
+
+EXTERN VpStatusType
+VpCalLine(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpCal(
+    VpLineCtxType *pLineCtx,
+    VpCalType calType,
+    void *inputArgs);
+
+EXTERN VpStatusType
+VpInitRing(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCadProfile,
+    VpProfilePtrType pCidProfile);
+
+EXTERN VpStatusType
+VpInitCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpInitMeter(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pMeterProfile);
+
+EXTERN VpStatusType
+VpInitCustomTermType (
+    VpDevCtxType *pDevCtx,
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pCustomTermProfile);
+
+EXTERN VpStatusType
+VpInitProfile(
+    VpDevCtxType *pDevCtx,
+    VpProfileType type,
+    VpProfilePtrType pProfileIndex,
+    VpProfilePtrType pProfile);
+
+EXTERN VpStatusType
+VpSoftReset(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpSetBatteries(
+    VpLineCtxType *pLineCtx,
+    VpBatteryModeType battMode,
+    VpBatteryValuesType *pBatt);
+
+EXTERN VpStatusType
+VpSetBFilter(
+    VpLineCtxType *pLineCtx,
+    VpBFilterModeType bFiltMode,
+    VpProfilePtrType pAcProfile);
+
+/*
+ * Control functions
+ */
+EXTERN VpStatusType
+VpSetLineState(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+EXTERN VpStatusType
+VpSetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+EXTERN VpStatusType
+VpSetRelayState(
+    VpLineCtxType *pLineCtx,
+    VpRelayControlType rState);
+
+EXTERN VpStatusType
+VpSetCalRelayState(
+    VpDevCtxType *pDevCtx,
+    VpCalRelayControlType rState);
+
+EXTERN VpStatusType
+VpSetRelGain(
+    VpLineCtxType *pLineCtx,
+    uint16 txLevel,
+    uint16 rxLevel,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpSendSignal(
+    VpLineCtxType *pLineCtx,
+    VpSendSignalType signalType,
+    void *pSignalData);
+
+EXTERN VpStatusType
+VpSendCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    VpProfilePtrType pCidProfile,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpContinueCid(
+    VpLineCtxType *pLineCtx,
+    uint8 length,
+    uint8p pCidData);
+
+EXTERN VpStatusType
+VpStartMeter(
+    VpLineCtxType *pLineCtx,
+    uint16 onTime,
+    uint16 offTime,
+    uint16 numMeters);
+
+EXTERN VpStatusType
+VpStartMeter32Q(
+    VpLineCtxType *pLineCtx,
+    uint32 minDelay,
+    uint32 onTime,
+    uint32 offTime,
+    uint16 numMeters,
+    uint16 eventRate);
+
+EXTERN VpStatusType
+VpAssocDslLine(
+    VpLineCtxType *pLineCtx,
+    bool connect,
+    uint8 line);
+
+EXTERN VpStatusType
+VpSetSealCur(
+    VpDevCtxType *pDevCtx,
+    uint16 sealApplyTime,
+    uint16 sealCycleTime,
+    uint16 maxCurrent,
+    uint16 minCurrent,
+    uint16 *pSealArray,
+    VpProfilePtrType pDcProfile);
+
+
+#define VpStartMeter32(pLineCtx, minDelay, onTime, offTime, numMeters) \
+    VpStartMeter32Q(pLineCtx, minDelay, onTime, offTime, numMeters, 1)
+
+EXTERN VpStatusType
+VpSetOption(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    void *pValue);
+
+EXTERN VpStatusType
+VpDeviceIoAccess(
+    VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessDataType *pDeviceIoData);
+
+VpStatusType
+VpDeviceIoAccessExt(
+    VpDevCtxType *pDevCtx,
+    VpDeviceIoAccessExtType *pDeviceIoAccess);
+
+EXTERN VpStatusType
+VpLineIoAccess(
+    VpLineCtxType *pLineCtx,
+    VpLineIoAccessType *pLineIoAccess,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpVirtualISR(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpApiTick(
+    VpDevCtxType *pDevCtx,
+    bool *pEventStatus);
+
+EXTERN VpStatusType
+VpLowLevelCmd(
+    VpLineCtxType *pLineCtx,
+    uint8 *pCmdData,
+    uint8 len,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpLowLevelCmd16(
+    VpLineCtxType *pLineCtx,
+    VpLowLevelCmdType cmdType,
+    uint16 *writeWords,
+    uint8 numWriteWords,
+    uint8 numReadWords,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGenTimerCtrl(
+    VpLineCtxType *pLineCtx,
+    VpGenTimerCtrlType timerCtrl,
+    uint32 duration,
+    uint16 handle);
+
+/*
+ * Status and query functions
+ */
+EXTERN bool
+VpGetEvent(
+    VpDevCtxType *pDevCtx,
+    VpEventType *pEvent);
+
+EXTERN VpStatusType
+VpGetLineStatus(
+    VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+EXTERN VpStatusType
+VpGetDeviceStatus(
+    VpDevCtxType *pDevCtx,
+    VpInputType input,
+    uint32 *pDeviceStatus);
+
+EXTERN VpStatusType
+VpGetDeviceStatusExt(
+    VpDevCtxType *pDevCtx,
+    VpDeviceStatusType *pDeviceStatus);
+
+EXTERN VpStatusType
+VpGetLoopCond(
+    VpLineCtxType *pLineCtx,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetOption(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx,
+    VpOptionIdType option,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetLineState(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType *pCurrentState);
+
+EXTERN VpStatusType
+VpFlushEvents(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpGetResults(
+    VpEventType *pEvent,
+    void *pResults);
+
+EXTERN VpStatusType
+VpClearResults(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpObjectDump(
+    VpLineCtxType *pLineCtx,
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpRegisterDump(
+    VpDevCtxType *pDevCtx);
+
+EXTERN VpStatusType
+VpDtmfDigitDetected(
+    VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+EXTERN VpStatusType
+VpQuery(
+    VpLineCtxType *pLineCtx,
+    VpQueryIdType queryId,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpGetRelayState(
+    VpLineCtxType *pLineCtx,
+    VpRelayControlType *pRstate);
+
+/*
+ * Test Functions
+ */
+EXTERN VpStatusType
+VpTestLine(
+    VpLineCtxType *pLineCtx,
+    VpTestIdType test,
+    const void *pArgs,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpTestLineCallback(
+    VpLineCtxType *pLineCtx,
+    VpPcmOperationResultsType *pResults);
+
+EXTERN VpStatusType
+VpCodeCheckSum(
+    VpDevCtxType *pDevCtx,
+    uint16 handle);
+
+EXTERN VpStatusType
+VpSelfTest(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+VpFillTestBuf(
+    VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+EXTERN VpStatusType
+VpReadTestBuf(
+    VpLineCtxType *pLineCtx,
+    uint16 length,
+    VpVectorPtrType pData);
+
+
+EXTERN VpStatusType
+VpMapLineId(
+    VpLineCtxType *pLineCtx,
+    VpLineIdType lineId);
+
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+EXTERN VpStatusType
+VpMapSlacId(
+    VpDevCtxType *pDevCtx,
+    uint8 slacId);
+#endif
+
+EXTERN bool
+VpMemCpyCheck(
+    uint8 *dest,
+    uint8 *src,
+    uint16 count);
+
+EXTERN void *
+VpMemCpy(
+    void *dest,
+    const void *src,
+    uint16 count);
+
+EXTERN void *
+VpMemSet(
+    void * s,
+    int c,
+    uint16 count);
+
+
+/*
+ * Undocumented external functions:
+ */
+#if !defined(VP_REDUCED_API_IF) || defined(VP_CC_792_SERIES) || defined(VP_CC_VCP_SERIES)   \
+                                || defined(VP_CC_VCP2_SERIES) || defined(VP_CC_MELT_SERIES) \
+                                || defined(VP_CC_KWRAP)
+EXTERN void
+VpSetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+EXTERN bool
+VpReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN VpStatusType
+Vcp2HbiCheck(
+    VpDevCtxType *pDevCtx);
+#endif
+
+EXTERN void
+VpMpiCmdWrapper(
+    VpDeviceIdType deviceId,
+    uint8 ecVal,
+    uint8 mpiCmd,
+    uint8 mpiCmdLen,
+    uint8 *dataBuffer);
+
+EXTERN uint8
+VpCSLACBuildMpiBuffer(
+    uint8 index,
+    uint8 *mpiBuffer,
+    uint8 mpiCmd,
+    uint8 mpiCmdLen,
+    uint8 *mpiData);
+
+#endif /* VP_API_COMMON_H */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_dev_term.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_dev_term.h
new file mode 100644
index 0000000..b53d4af
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_dev_term.h
@@ -0,0 +1,84 @@
+/** \file vp_api_dev_term.h
+ * vp_api_dev_term.h
+ *
+ * This file contains declaration for VP-API Device and termination types.
+ *
+ * $Revision: 7591 $
+ * $LastChangedDate: 2010-08-16 09:33:04 -0500 (Mon, 16 Aug 2010) $
+ */
+
+#ifndef VP_API_DEV_TERM_H
+#define VP_API_DEV_TERM_H
+
+/******************************************************************************
+ *                                ENUMERATIONS                                *
+ ******************************************************************************/
+/* Valid Device Types supported by VP-API-II. For the corresponding part numbers
+ * supported by each device type please see VP-API-II documentation.
+ */
+typedef enum
+{
+    VP_DEV_RSRVD1 = 0,
+    VP_DEV_580_SERIES,
+    VP_DEV_790_SERIES,
+    VP_DEV_VCP_SERIES,
+    VP_DEV_880_SERIES = 4,  /* Fixed value to match calibration profile */
+    VP_DEV_RSVD_SERIES,
+    VP_DEV_VCP2_SERIES,
+    VP_DEV_KWRAP,
+    VP_DEV_890_SERIES = 8,  /* Fixed value to match calibration profile */
+    VP_DEV_792_SERIES,
+    VP_DEV_MELT_SERIES,
+    VP_DEV_792_GROUP,
+    VP_NUM_DEV_TYPES,
+    VP_DEV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDeviceType;
+
+/**
+ * Deprecated name (VCP) based on older name for VCP. All new applications
+ * should use VCP instead
+ */
+#define VP_DEV_DVP_SERIES  VP_DEV_VCP_SERIES
+
+/** Valid Termination Types (per line) supported by API-II.  See the VP-API-II
+    Reference Guide for descriptions. */
+typedef enum
+{
+    /* FXS */
+    VP_TERM_FXS_GENERIC            = 0x00, VP_TERM_FXS_FIRST = VP_TERM_FXS_GENERIC,
+    VP_TERM_FXS_ISOLATE            = 0x01,
+    VP_TERM_FXS_TITO_TL_R          = 0x02,
+    VP_TERM_FXS_CO_TL              = 0x03,
+    VP_TERM_FXS_75181              = 0x04,
+    VP_TERM_FXS_75282              = 0x05,
+    VP_TERM_FXS_RDT                = 0x06,
+    VP_TERM_FXS_RR                 = 0x07,
+    VP_TERM_FXS_SPLITTER           = 0x08,
+    VP_TERM_FXS_TO_TL              = 0x09,
+    VP_TERM_FXS_LOW_PWR            = 0x0A,
+    VP_TERM_FXS_TI                 = 0x0B,
+    VP_TERM_FXS_SPLITTER_LP        = 0x0C,
+    VP_TERM_FXS_ISOLATE_LP         = 0x0D,
+    VP_TERM_FXS_LCAS               = 0x0E,
+    VP_TERM_FXS_RR_TI              = 0x0F,
+    VP_TERM_FXS_CUSTOM             = 0x10,
+    VP_TERM_FXS_TL_MW              = 0x11, VP_TERM_FXS_LAST = VP_TERM_FXS_TL_MW,
+
+    /* MeLT */
+    VP_TERM_MELT_RELAY_CAL_CT      = 0x40, VP_TERM_MELT_FIRST = VP_TERM_MELT_RELAY_CAL_CT,
+    VP_TERM_MELT_RELAY_CAL_SPLIT   = 0x41,
+    VP_TERM_MELT_RELAY_CAL_BRIDGED = 0x42,
+    VP_TERM_MELT_LTAS_CT           = 0x43,
+    VP_TERM_MELT_RELAY_CT          = 0x44,
+    VP_TERM_MELT_RELAY_SPLIT       = 0x45,
+    VP_TERM_MELT_RELAY_BRIDGED     = 0x46, VP_TERM_MELT_LAST = VP_TERM_MELT_RELAY_BRIDGED,
+
+    /* FXO */
+    VP_TERM_FXO_GENERIC            = 0x80, VP_TERM_FXO_FIRST = VP_TERM_FXO_GENERIC,
+    VP_TERM_FXO_DISC               = 0x81,
+    VP_TERM_FXO_CUSTOM             = 0x82, VP_TERM_FXO_LAST = VP_TERM_FXO_CUSTOM,
+
+    VP_TERM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpTermType;
+
+#endif /* VP_API_DEV_TERM_H */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_event.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_event.h
new file mode 100644
index 0000000..5055ad8
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_event.h
@@ -0,0 +1,468 @@
+/** \file vp_api_event.h
+ * vp_api_event.h
+ *
+ * This file contains declaration associated with VP-API events.
+ *
+ * $Revision: 8609 $
+ * $LastChangedDate: 2011-05-27 14:55:29 -0500 (Fri, 27 May 2011) $
+ */
+
+#ifndef VP_API_EVENT_H
+#define VP_API_EVENT_H
+
+#include "vp_api_types.h"
+
+#define VP_EVENT_MASK_ALL       0xFFFF
+
+/* Event category type */
+typedef enum {
+    VP_EVCAT_FAULT     = 0,
+    VP_EVCAT_SIGNALING = 1,
+    VP_EVCAT_RESPONSE  = 2,
+    VP_EVCAT_TEST      = 3,
+    VP_EVCAT_PROCESS   = 4,
+    VP_EVCAT_FXO       = 5,
+    VP_EVCAT_PACKET    = 6,
+    VP_NUM_EVCATS,
+    VP_EVCAT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpEventCategoryType;
+
+typedef struct {
+    uint16 faults;      /**< Fault event mask */
+    uint16 signaling;   /**< Signaling event mask */
+    uint16 response;    /**< Mailbox response event mask */
+    uint16 test;        /**< Test events */
+    uint16 process;     /**< Call process related events */
+    uint16 fxo;         /**< FXO events mask */
+    uint16 packet;      /**< Packet events mask - no longer used */
+} VpOptionEventMaskType;
+
+typedef enum {
+    VP_DEV_EVID_BAT_FLT         = 0x0001, /**< Device detected battery fault */
+    VP_DEV_EVID_CLK_FLT         = 0x0002, /**< Device detected clock fault */
+    VP_LINE_EVID_THERM_FLT      = 0x0004, /**< Thermal Overload condition */
+    VP_LINE_EVID_DC_FLT         = 0x0008, /**< DC Fault detected on line */
+    VP_LINE_EVID_AC_FLT         = 0x0010, /**< AC Fault detected on line */
+    VP_LINE_EVID_SYNC_FLT       = 0x0020, /**< SLAC Synchronization fault */
+    VP_LINE_EVID_RES_LEAK_FLT   = 0x0040, /**< Low loop resistance while on-hook */
+    VP_LINE_EVID_SEAL_CUR_FLT   = 0x0080, /**< Sealing current error */
+    VP_DEV_EVID_WDT_FLT         = 0x2000, /**< Watchdog timer fault */
+    VP_DEV_EVID_EVQ_OFL_FLT     = 0x4000, /**< event queue overflow fault */
+    VP_DEV_EVID_SYSTEM_FLT      = 0x8000, /**< VCP2 system fault */
+    /* The following fault events are device-specific, not line-specific */
+    VP_EVCAT_FAULT_DEV_EVENTS   = (int)(VP_DEV_EVID_BAT_FLT     |
+                                        VP_DEV_EVID_CLK_FLT     |
+                                        VP_DEV_EVID_EVQ_OFL_FLT |
+                                        VP_DEV_EVID_WDT_FLT     |
+                                        VP_DEV_EVID_SYSTEM_FLT),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_FAULT_UNDEFINED    = (int)(~(VP_DEV_EVID_BAT_FLT     |
+                                          VP_DEV_EVID_CLK_FLT     |
+                                          VP_LINE_EVID_THERM_FLT  |
+                                          VP_LINE_EVID_DC_FLT     |
+                                          VP_LINE_EVID_AC_FLT     |
+                                          VP_LINE_EVID_SYNC_FLT   |
+                                          VP_LINE_EVID_RES_LEAK_FLT |
+                                          VP_LINE_EVID_SEAL_CUR_FLT |
+                                          VP_DEV_EVID_WDT_FLT     |
+                                          VP_DEV_EVID_EVQ_OFL_FLT |
+                                          VP_DEV_EVID_SYSTEM_FLT)), /* NOTES:
+    * The typecasting (int) is necessary in some compilers that have
+    * sizeof(enum)  == sizeof(int) == 2bytes and also because of 'C' rules for
+    * hexadecimal constants. Hexadecimal constants are treated as unsigned and
+    * enum variables are of type signed int. Thus compilers generate warning
+    * when code attempts to assign number that is bigger than what a signed enum
+    * can hold */
+
+    VP_EVCAT_FAULT_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                         VP_EVCAT_FAULT_UNDEFINED),
+    VP_EVCAT_FAULT_MASK_ALL     = (int)(~VP_EVCAT_FAULT_UNDEFINED),
+    VP_EVCAT_FAULT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpFaultEventType;
+
+typedef enum {
+    VP_LINE_EVID_HOOK_OFF       = 0x0001, /**< Off-Hook detected */
+    VP_LINE_EVID_HOOK_ON        = 0x0002, /**< On-Hook detected */
+    VP_LINE_EVID_GKEY_DET       = 0x0004, /**< Ground Key detected */
+    VP_LINE_EVID_GKEY_REL       = 0x0008, /**< Ground Key release detected */
+    VP_LINE_EVID_FLASH          = 0x0010, /**< Hook switch flash detected */
+    VP_LINE_EVID_STARTPULSE     = 0x0020, /**< Start of a dial pulse detected */
+    VP_LINE_EVID_DTMF_DIG       = 0x0040, /**< New DTMF digit detected */
+    VP_LINE_EVID_PULSE_DIG      = 0x0080, /**< New pulse digit detected */
+    VP_LINE_EVID_MTONE          = 0x0100, /**< Modem tone detected */
+    VP_DEV_EVID_TS_ROLLOVER     = 0x0200, /**< Timestamp rollover */
+
+    VP_LINE_EVID_US_TONE_DETECT = 0x0400, /**< Upstream tone detection event */
+    VP_LINE_EVID_DS_TONE_DETECT = 0x0800, /**< Downstream tone detection event*/
+    VP_DEV_EVID_SEQUENCER       = 0x1000, /**< Sequencer Event */
+    VP_LINE_EVID_BREAK_MAX      = 0x2000, /**< Break Max time has been exceeded */
+    VP_LINE_EVID_EXTD_FLASH     = 0x4000, /**< Flash Hook between flash max and on-hook min */
+    VP_LINE_EVID_HOOK_PREQUAL   = 0x8000, /**< debounced off/on hook detected, but < offHookMin */
+
+    /* The following signaling events are device-specific, not line-specific */
+    VP_EVCAT_SIGNALING_DEV_EVENTS  = (int)(VP_DEV_EVID_TS_ROLLOVER |
+                                            VP_DEV_EVID_SEQUENCER),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_SIGNALING_UNDEFINED   = (int)(~(VP_LINE_EVID_HOOK_OFF          |
+                                             VP_LINE_EVID_HOOK_ON           |
+                                             VP_LINE_EVID_GKEY_DET          |
+                                             VP_LINE_EVID_GKEY_REL          |
+                                             VP_LINE_EVID_FLASH             |
+                                             VP_LINE_EVID_STARTPULSE        |
+                                             VP_LINE_EVID_DTMF_DIG          |
+                                             VP_LINE_EVID_PULSE_DIG         |
+                                             VP_LINE_EVID_MTONE             |
+                                             VP_DEV_EVID_TS_ROLLOVER        |
+                                             VP_LINE_EVID_US_TONE_DETECT    |
+                                             VP_LINE_EVID_DS_TONE_DETECT    |
+                                             VP_DEV_EVID_SEQUENCER          |
+                                             VP_LINE_EVID_BREAK_MAX         |
+                                             VP_LINE_EVID_EXTD_FLASH        |
+                                             VP_LINE_EVID_HOOK_PREQUAL)),
+
+    VP_EVCAT_SIGNALING_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                             VP_EVCAT_SIGNALING_UNDEFINED),
+    VP_EVCAT_SIGNALING_MASK_ALL     = (int)(~VP_EVCAT_SIGNALING_UNDEFINED),
+    VP_EVCAT_SIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSignalingEventType;
+
+typedef enum {
+    VP_DEV_EVID_BOOT_CMP        = 0x0001, /**< VCP Startup sequence has
+                                           * completed; Non-maskable
+                                           */
+    VP_LINE_EVID_LLCMD_TX_CMP   = 0x0002, /**< Low level write transaction has
+                                           * completed
+                                           */
+    VP_LINE_EVID_LLCMD_RX_CMP   = 0x0004, /**< Low Level read transaction has
+                                           * completed
+                                           */
+    VP_DEV_EVID_DNSTR_MBOX      = 0x0008, /**< Dowstream Mailbox event ready */
+    VP_LINE_EVID_RD_OPTION      = 0x0010, /**< Read Option request complete */
+    VP_LINE_EVID_RD_LOOP        = 0x0020, /**< Read Loop Conditions is complete
+                                           */
+    VP_EVID_CAL_CMP             = 0x0040, /**< Device or Line Calibration is
+                                           * complete
+                                           */
+    VP_EVID_CAL_BUSY            = 0x0080, /**< Calibration not performed, line
+                                           * busy
+                                           */
+    VP_LINE_EVID_GAIN_CMP       = 0x0100, /**< Gain Adjustment complete */
+    VP_LINE_EVID_QUERY_CMP      = 0x0200, /**< Query complete */
+    VP_DEV_EVID_DEV_INIT_CMP    = 0x0400, /**< Device Init complete */
+    VP_LINE_EVID_LINE_INIT_CMP  = 0x0800, /**< Line Init complete */
+    VP_DEV_EVID_IO_ACCESS_CMP   = 0x1000, /**< Device Access complete */
+    VP_LINE_EVID_LINE_IO_RD_CMP = 0x2000, /**< Line GPIO read complete */
+    VP_LINE_EVID_LINE_IO_WR_CMP = 0x4000, /**< Line GPIO write complete */
+    VP_LINE_EVID_SLAC_INIT_CMP  = 0x8000, /**< SLAC Init complete */
+    /* The following response events are device-specific, not line-specific */
+    VP_EVCAT_RESPONSE_DEV_EVENTS = (int)(VP_DEV_EVID_BOOT_CMP       |
+                                        VP_DEV_EVID_DNSTR_MBOX      |
+                                        VP_DEV_EVID_DEV_INIT_CMP    |
+                                        VP_DEV_EVID_IO_ACCESS_CMP),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_RESPONSE_UNDEFINED = (int)(~(VP_DEV_EVID_BOOT_CMP          |
+                                          VP_LINE_EVID_LLCMD_TX_CMP     |
+                                          VP_LINE_EVID_LLCMD_RX_CMP     |
+                                          VP_DEV_EVID_DNSTR_MBOX        |
+                                          VP_LINE_EVID_RD_OPTION        |
+                                          VP_LINE_EVID_RD_LOOP          |
+                                          VP_EVID_CAL_CMP               |
+                                          VP_EVID_CAL_BUSY              |
+                                          VP_LINE_EVID_GAIN_CMP         |
+                                          VP_LINE_EVID_QUERY_CMP        |
+                                          VP_DEV_EVID_DEV_INIT_CMP      |
+                                          VP_LINE_EVID_LINE_INIT_CMP    |
+                                          VP_DEV_EVID_IO_ACCESS_CMP     |
+                                          VP_LINE_EVID_LINE_IO_RD_CMP   |
+                                          VP_LINE_EVID_LINE_IO_WR_CMP   |
+                                          VP_LINE_EVID_SLAC_INIT_CMP)),
+
+    VP_EVCAT_RESPONSE_UNMASK_ALL   = (int)(VP_EVENT_MASK_ALL &
+                                            VP_EVCAT_RESPONSE_UNDEFINED),
+    VP_EVCAT_RESPONSE_MASK_ALL     = (int)(~VP_EVCAT_RESPONSE_UNDEFINED),
+    VP_EVCAT_RES_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpResponseEventType;
+
+typedef enum
+{
+    VP_LINE_EVID_TEST_CMP   = 0x0001, /**< A requested test has been completed*/
+    VP_LINE_EVID_TEST_RSVD1 = 0x0002, /**< Reserved event */
+    VP_LINE_EVID_DTONE_DET  = 0x0004, /**< Dial-Tone Test - Dialtone Detected */
+    VP_LINE_EVID_DTONE_LOSS = 0x0008, /**< Dial-Tone Test - Dialtone Lost */
+    VP_DEV_EVID_STEST_CMP   = 0x0010, /**< Self Test Function complete */
+    VP_DEV_EVID_CHKSUM      = 0x0020, /**< Code-space checksum is complete */
+    VP_LINE_EVID_ABORT      = 0x0040, /**< Event requesting abort test */
+    /* The following test events are device-specific, not line-specific */
+    VP_EVCAT_TEST_DEV_EVENTS = (int)(VP_DEV_EVID_CHKSUM),
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_TEST_UNDEFINED =    (int)(~(VP_LINE_EVID_TEST_CMP       |
+                                         VP_LINE_EVID_DTONE_DET      |
+                                         VP_LINE_EVID_DTONE_LOSS     |
+                                         VP_DEV_EVID_STEST_CMP       |
+                                         VP_DEV_EVID_CHKSUM)),
+
+    VP_EVCAT_TEST_UNMASK_ALL    =  (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_TEST_UNDEFINED),
+    VP_EVCAT_TEST_MASK_ALL      =  (int)(~VP_EVCAT_TEST_UNDEFINED),
+    VP_EVCAT_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpTestEventType;
+
+typedef enum
+{                               
+    VP_LINE_EVID_MTR_CMP        = 0x0001, /**< Metering Signal complete */
+    VP_LINE_EVID_MTR_ABORT      = 0x0002, /**< Metering Signal aborted */
+    VP_LINE_EVID_CID_DATA       = 0x0004, /**< Caller ID Transmission buffer is
+                                           * empty
+                                           */
+    VP_LINE_EVID_RING_CAD       = 0x0008, /**< Ring Cadence State change
+                                           * information
+                                           */
+    VP_LINE_EVID_SIGNAL_CMP     = 0x0010, /**< Signal Generation complete */
+    VP_LINE_EVID_MTR_CAD        = 0x0020, /**< Metering cadence */
+                                
+    VP_LINE_EVID_TONE_CAD       = 0x0040, /**< Tone Cadence complete */
+
+    VP_LINE_EVID_MTR_ROLLOVER   = 0x0080, /**< Metering count rollover */
+    VP_LINE_EVID_GEN_TIMER      = 0x0100, /**< Timer complete / canceled / error */
+    VP_LINE_EVID_USER           = 0x0200, /**< User-defined event */
+    VP_LINE_EVID_AUTO_LOOP_COND = 0x0400, /**< VP_OPTION_ID_AUTO_LOOP_COND event */
+
+    /* There are no device-specific process events */
+    VP_EVCAT_PROCESS_DEV_EVENTS = 0,
+
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_PROCESS_UNDEFINED =  (int)(~(VP_LINE_EVID_MTR_CMP        |
+                                          VP_LINE_EVID_MTR_ABORT      |
+                                          VP_LINE_EVID_CID_DATA       |
+                                          VP_LINE_EVID_RING_CAD       |
+                                          VP_LINE_EVID_SIGNAL_CMP     |
+                                          VP_LINE_EVID_MTR_CAD        |
+                                          VP_LINE_EVID_TONE_CAD       |
+                                          VP_LINE_EVID_MTR_ROLLOVER   |
+                                          VP_LINE_EVID_GEN_TIMER      |
+                                          VP_LINE_EVID_USER)),
+
+    VP_EVCAT_PROCESS_UNMASK_ALL =  (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_PROCESS_UNDEFINED),
+    VP_EVCAT_PROCESS_MASK_ALL   =  (int)(~VP_EVCAT_PROCESS_UNDEFINED),
+    VP_EVCAT_PRO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProcessEventType;
+
+typedef enum {
+    /* FXO API Event Types */
+    VP_LINE_EVID_RING_ON    = 0x0001, /**< Ringing detected on line */
+    VP_LINE_EVID_RING_OFF   = 0x0002, /**< Ringing previously detected has
+                                       * stopped
+                                       */
+    VP_LINE_EVID_LIU        = 0x0004, /**< Line In Use by adjacent line off
+                                       * hook
+                                       */
+    VP_LINE_EVID_LNIU       = 0x0008, /**< Line In Use by adjacent line on
+                                       * hook */
+    VP_LINE_EVID_FEED_DIS   = 0x0010, /**< Line feed disabled (or too low) */
+    VP_LINE_EVID_FEED_EN    = 0x0020, /**< Line feed enabled */
+    VP_LINE_EVID_DISCONNECT = 0x0040, /**< Line feed removed while loop close */
+    VP_LINE_EVID_RECONNECT  = 0x0080, /**< Line feed connected while loop
+                                       * close
+                                       */
+    VP_LINE_EVID_POLREV     = 0x0100, /**< Line polarity reversal has occurred*/
+    VP_LINE_EVID_POH        = 0x0200, /**< Parallel line off-hook */
+    VP_LINE_EVID_PNOH       = 0x0400, /**< Parallel line on-hook */
+
+    /* There are no device-specific FXO events */
+    VP_EVCAT_FXO_DEV_EVENTS = 0,
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_FXO_UNDEFINED =     (int)(~(VP_LINE_EVID_RING_ON        |
+                                         VP_LINE_EVID_RING_OFF       |
+                                         VP_LINE_EVID_LIU            |
+                                         VP_LINE_EVID_LNIU           |
+                                         VP_LINE_EVID_FEED_DIS       |
+                                         VP_LINE_EVID_FEED_EN        |
+                                         VP_LINE_EVID_DISCONNECT     |
+                                         VP_LINE_EVID_RECONNECT      |
+                                         VP_LINE_EVID_POLREV         |
+                                         VP_LINE_EVID_POH            |
+                                         VP_LINE_EVID_PNOH)),
+
+    VP_EVCAT_FXO_UNMASK_ALL =      (int)(VP_EVENT_MASK_ALL &
+                                     VP_EVCAT_FXO_UNDEFINED),
+    VP_EVCAT_FXO_MASK_ALL   =      (int)(~VP_EVCAT_FXO_UNDEFINED),
+    VP_EVCAT_FXO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpFxoEventType;
+
+typedef enum {
+    VP_LINE_EVID_US_PKT_RDY     = 0x0001, /**< Upstream Packet ready event */
+    VP_LINE_EVID_NEED_DS_PKT    = 0x0002, /**< Need Downstream Packet event */
+    VP_LINE_EVID_PKT_ERROR      = 0x0004, /**< Packet type error event */
+    VP_LINE_EVID_PKT_LOST       = 0x0008, /**< Packet loss event */
+    VP_LINE_EVID_RD_PKT_STATS   = 0x0010, /**< Read packet statistics complete*/
+    /* There are no device-specific packet events */
+    VP_EVCAT_PACKET_DEV_EVENTS  = 0,
+    /* Remaining undefined events should be masked to protect against
+     * future changes */
+    VP_EVCAT_PACKET_UNDEFINED =   (int)(~(VP_LINE_EVID_US_PKT_RDY       |
+                                          VP_LINE_EVID_NEED_DS_PKT      |
+                                          VP_LINE_EVID_PKT_ERROR        |
+                                          VP_LINE_EVID_PKT_LOST         |
+                                          VP_LINE_EVID_RD_PKT_STATS)),
+
+    VP_EVCAT_PACKET_UNMASK_ALL  =   (int)(VP_EVENT_MASK_ALL &
+                                          VP_EVCAT_PACKET_UNDEFINED),
+    VP_EVCAT_PACKET_MASK_ALL    =  (int)(~VP_EVCAT_PACKET_UNDEFINED),
+    VP_EVCAT_PKT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPacketEventType;
+
+/* Enumerations for interpreting event data in the VpGetEvent() field */
+typedef enum {
+    VP_BAT_FLT_NONE = 0x0,
+    VP_BAT_FLT_BAT2 = 0x1,
+    VP_BAT_FLT_BAT1 = 0x2,
+    VP_BAT_FLT_BAT3 = 0x4,
+    VP_BAT_FLT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpBatFltEventDataType;
+
+typedef enum {
+    VP_RING_CAD_BREAK = 0,
+    VP_RING_CAD_MAKE  = 1,
+    VP_RING_CAD_DONE  = 2,
+    VP_RING_CAD_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpRingCadEventDataType;
+
+typedef enum {
+    VP_CID_DATA_NEED_MORE_DATA = 0,
+    VP_CID_DATA_TX_DONE        = 1,
+    VP_CID_DATA_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCidDataEventDataType;
+
+typedef enum {
+    VP_DIG_1         = 0x01,
+    VP_DIG_2         = 0x02,
+    VP_DIG_3         = 0x03,
+    VP_DIG_4         = 0x04,
+    VP_DIG_5         = 0x05,
+    VP_DIG_6         = 0x06,
+    VP_DIG_7         = 0x07,
+    VP_DIG_8         = 0x08,
+    VP_DIG_9         = 0x09,
+    VP_DIG_10        = 0x0A,    /* pulse only */
+    VP_DIG_11        = 0x0B,    /* pulse only */
+    VP_DIG_12        = 0x0C,    /* pulse only */
+    VP_DIG_13        = 0x0D,    /* pulse only */
+    VP_DIG_14        = 0x0E,    /* pulse only */
+    VP_DIG_15        = 0x0F,    /* pulse only */
+    VP_DIG_ZERO      = 0x0A,    /* DTMF only */
+    VP_DIG_ASTER     = 0x0B,    /* DTMF only */
+    VP_DIG_POUND     = 0x0C,    /* DTMF only */
+    VP_DIG_A         = 0x0D,    /* DTMF only */
+    VP_DIG_B         = 0x0E,    /* DTMF only */
+    VP_DIG_C         = 0x0F,    /* DTMF only */
+    VP_DIG_D         = 0x00,    /* DTMF only */
+    VP_DIG_NONE      = 0xFF,
+    VP_DIG_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_DIG_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitType;
+
+/*
+ * Indicates which set of Dial Pulse Specifications were met that is generating
+ * the dial pulse event.
+ */
+typedef enum {
+    VP_DP_PARAM1 = 0,
+    VP_DP_PARAM2 = 1,
+    VP_DP_PARAM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDialPulseParamType;
+
+typedef enum {
+    VP_DIG_SENSE_BREAK = 0x0000,
+    VP_DIG_SENSE_MAKE  = 0x0010,
+    VP_DIG_SENSE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpDigitSenseType;
+
+typedef enum {
+    VP_POLREV_NORMAL  = 0, /* Line detected Reverse-to-Normal Transition */
+    VP_POLREV_REVERSE = 1, /* Line detected Normal-to-Reverse Transition */
+    VP_POLREV_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpPolRevEventDataType;
+
+typedef enum {
+    VP_SYNC_MB_ERR        = 0x00,
+    VP_SYNC_SEQ_BAD_INST  = 0x81, /* Unknown instruction in sequence */
+    VP_SYNC_SEQ_BAD_BR    = 0x82, /* Sequencer encountered bad branch (either
+                                   * a forward branch or too many nesting levels */
+    VP_SYNC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpSyncFltEventDataType;
+
+typedef enum {
+    VP_GEN_TIMER_STATUS_CMP      = 0,
+    VP_GEN_TIMER_STATUS_CANCELED = 1,
+    VP_GEN_TIMER_STATUS_RESRC_NA = 2,
+    VP_GEN_TIMER_STATUS_UNKNOWN  = 3,
+    VP_GEN_TIMER_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpGenTimerStatusType;
+
+typedef enum {
+    VP_FLASH_ONLY = 0,
+    VP_FLASH_AND_DIGIT1 = 1
+} VpFlashEventDataType;
+
+typedef uint16 VpHookPrequalEventDataType;
+#define VP_HOOK_PREQUAL_START   (0) /* Debounced off-hook detected, but offHookMin > 0 */
+#define VP_HOOK_PREQUAL_ABORT   (1) /* Debounced on-hook detected, but duration < offHookMin */
+
+
+/**
+ * Non-maskable events are (with reasons):
+ *
+ *   Boot Complete -- Cannot mask.  Masking events requires that the boot has
+ *                   been completed.
+ *   Read Option -- To modify mask interrupts requires that the current mask
+ *                  options can be read.  The only way to know the read option
+ *                  is ready is via an unmasked Read Option Complete event.
+ *   Device Init -- Fundamental event to know when device is initialized and
+ *                  remaining options/line configurations can be set.  There
+ *                  is no other standard "timeout" mechanism to know when the
+ *                  device has been initialized properly.
+ *   Line Init -- Fundamental event to know when a line is initialized and ready
+ *                to be setup with remaining user defined options.  There is no
+ *                other standard "timeout" mechanism to know when the line has
+ *                been initialized properly.
+ *   Events that have responses -- These events are non-maskable. If an event
+ *                that has a response is masked, and if the response is not
+ *                read, in case of CSLAC devices, it blocks response buffer.
+ *                In case of VCP class of devices, response mailbox is
+ *                locked up. If this is followed by another command that
+ *                requires the response mailbox, that command can't complete
+ *                execution since the response mailbox is busy. Now no more
+ *                commands can be issued because the previous command can't
+ *                complete.
+ */
+
+#define VP_API_NONMASK_FAULT_EVENTS         0x0000
+#define VP_API_NONMASK_SIGNALING_EVENTS     0x0000
+
+#define VP_API_NONMASK_RESPONSE_EVENTS      (VP_DEV_EVID_BOOT_CMP \
+                                           | VP_LINE_EVID_LLCMD_RX_CMP \
+                                           | VP_LINE_EVID_RD_OPTION \
+                                           | VP_LINE_EVID_RD_LOOP \
+                                           | VP_LINE_EVID_GAIN_CMP \
+                                           | VP_LINE_EVID_QUERY_CMP \
+                                           | VP_DEV_EVID_DEV_INIT_CMP \
+                                           | VP_LINE_EVID_LINE_INIT_CMP \
+                                           | VP_DEV_EVID_IO_ACCESS_CMP \
+                                           | VP_LINE_EVID_LINE_IO_RD_CMP \
+                                           | VP_LINE_EVID_SLAC_INIT_CMP)
+
+#define VP_API_NONMASK_TEST_EVENTS          (VP_LINE_EVID_TEST_CMP \
+                                           | VP_DEV_EVID_CHKSUM)
+
+#define VP_API_NONMASK_PROCESS_EVENTS       VP_LINE_EVID_GEN_TIMER
+#define VP_API_NONMASK_FXO_EVENTS           0x0000
+#define VP_API_NONMASK_PACKET_EVENTS        0x0000
+
+#endif /* VP_API_EVENT_H */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_fxo_params.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_fxo_params.h
new file mode 100755
index 0000000..15f1dae
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_fxo_params.h
@@ -0,0 +1,67 @@
+/** \file vp_api_fxo_params.h
+ * vp_api_fxo_params.h
+ *
+ * This file contains the Zarlink Semiconductor approved system parameters for proper
+ * FXO operation on the reference designs
+ *
+ * $Revision: 5442 $
+ * $LastChangedDate: 2009-08-17 12:13:24 -0500 (Mon, 17 Aug 2009) $
+ */
+
+#ifndef VP_API_FXO_PARAMS_H
+#define VP_API_FXO_PARAMS_H
+
+#define VP_FXO_DTMF_ON_DEFAULT          0x0027  /* DTMF On = 195mS */
+#define VP_FXO_DTMF_OFF_DEFAULT         0x0028  /* DTMF Off = 200mS */
+#define VP_FXO_FLASH_HOOK_DEFAULT       0x0078  /* Flash Hook = 600mS */
+#define VP_FXO_PULSE_BREAK_DEFAULT      0x0C    /* Pulse Break = 60mS */
+#define VP_FXO_PULSE_MAKE_DEFAULT       0x08    /* Pulse Make = 40mS */
+#define VP_FXO_INTERDIG_DEFAULT         0x0028  /* Interdigit Period = 200mS */
+#define VP_FXO_RING_DET_MAX_DEFAULT     0xEB    /* Ring Period Max = 58.75mS */
+#define VP_FXO_RING_DET_MIN_DEFAULT     0x79    /* Ring Period Min = 30.25mS */
+#define VP_FXO_RING_DET_VOLT_DEFAULT    0x02    /* Ring Voltage Min = 38V */
+#define VP_FXO_DISC_DET_MIN_DEFAULT     0x03    /* Disconnect Det Min = 4.2V */
+#define VP_FXO_LIU_DET_THRESH_DEFAULT   0x26    /* Line-In-Use Det Threshold = 38V */
+
+/* In ms, time that FXO detector activity is ignored after a state change */
+#define VP_FXO_STATE_CHANGE_DEBOUNCE    (50)
+
+/* In ms, time that FXO detector activity is ignored after a ring trip */
+#define VP_FXO_RING_TRIP_DEBOUNCE       (200)
+
+/* In ms, time that FXO disconnect detector is debounced */
+#define VP_FXO_DISCONNECT_DEBOUNCE      (300)
+
+/* In ms, time that FXO will change to loop open if detecting disconnect */
+#define VP_FXO_DISC_TO_LOOP_OPEN        (5000)
+
+typedef enum
+{
+    VP_FXO_DIALING_PROFILE_DTMF_ON_MSB = 6,
+    VP_FXO_DIALING_PROFILE_DTMF_ON_LSB = 7,
+    VP_FXO_DIALING_PROFILE_DTMF_OFF_MSB = 8,
+    VP_FXO_DIALING_PROFILE_DTMF_OFF_LSB = 9,
+    VP_FXO_DIALING_PROFILE_FLASH_HOOK_MSB = 10,
+    VP_FXO_DIALING_PROFILE_FLASH_HOOK_LSB = 11,
+    VP_FXO_DIALING_PROFILE_PULSE_BREAK = 12,
+    VP_FXO_DIALING_PROFILE_PULSE_MAKE = 13,
+    VP_FXO_DIALING_PROFILE_INTERDIGIT_MSB = 14,
+    VP_FXO_DIALING_PROFILE_INTERDIGIT_LSB = 15,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MAX = 16,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MIN = 17,
+    VP_FXO_DIALING_PROFILE_RING_VOLTAGE_MIN = 18,
+    VP_FXO_DIALING_PROFILE_DISC_VOLTAGE_MIN = 19,
+    VP_FXO_DIALING_PROFILE_LIU_THRESHOLD_MIN = 20,
+    VP_FXO_DIALING_PROFILE_RING_PERIOD_MAX_ACT = 21,
+    VP_FXO_DIALING_PROFILE_DTMF_HIGH_LVL_MSB = 22,
+    VP_FXO_DIALING_PROFILE_DTMF_HIGH_LVL_LSB = 23,
+    VP_FXO_DIALING_PROFILE_DTMF_LOW_LVL_MSB = 24,
+    VP_FXO_DIALING_PROFILE_DTMF_LOW_LVL_LSB = 25,
+    VP_FXO_DIALING_PROFILE_POH_INT_TIME = 26,
+    VP_FXO_DIALING_PROFILE_POH_THRESHOLD = 27,
+    VP_FXO_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} vp_fxo_dialingProfileParams;
+#endif
+
+
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_int.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_int.h
new file mode 100644
index 0000000..3968c3b
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_int.h
@@ -0,0 +1,622 @@
+/** \file vp_api_int.h
+ * vp_api_int.h
+ *
+ * Header file for the API-II c files. This file contains the declarations
+ * and defintions required to implement the VTD specific VP-API. This file
+ * is used by VP-API internally. This file should not be included by the
+ * application.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8620 $
+ * $LastChangedDate: 2011-06-02 13:27:26 -0500 (Thu, 02 Jun 2011) $
+ */
+
+#ifndef VP_API_INT_H
+#define VP_API_INT_H
+
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "vp_api.h"
+#include "vp_api_option.h"
+
+#include "vp_debug.h"
+
+/******************************************************************************
+ *                              VP-API Defines                                *
+ ******************************************************************************/
+#define VP_ALL_LINES            0xFF  /**< Internal constant used to identify
+                                       * all lines
+                                       */
+#define VP_ALL_SLACS          0xFFFF  /**< Internal constant used to identify
+                                       * all SLACs
+                                       */
+
+/**< Profile types as defined by Profile Wizard */
+typedef enum {
+    VP_PRFWZ_PROFILE_AC = 0x00,
+    VP_PRFWZ_PROFILE_DC = 0x01,
+    VP_PRFWZ_PROFILE_TONE = 0x02,
+    VP_PRFWZ_PROFILE_TONECAD = 0x03,
+    VP_PRFWZ_PROFILE_RING = 0x04,
+    VP_PRFWZ_PROFILE_CID_TYPE1 = 0x05,
+    VP_PRFWZ_PROFILE_CID_TYPE2 = 0x06,
+    VP_PRFWZ_PROFILE_METER = 0x07,
+    VP_PRFWZ_PROFILE_RINGCAD = 0x08,
+    VP_PRFWZ_PROFILE_TEST_CRITERIA = 0x09,
+    VP_PRFWZ_PROFILE_TEST_TOPOLOGY = 0x0A,
+    VP_PRFWZ_PROFILE_FXS_CTRL = 0x0B,
+    VP_PRFWZ_PROFILE_CAL = 0x0C,
+    VP_PRFWZ_PROFILE_METERING_GEN,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_HOOK_FLASH_DIG_GEN,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_DIAL_PULSE_DIG_GEN,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_DTMF_DIG_GEN,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_MSG_WAIT_PULSE_INT,    /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_LINE_CAL_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_FWD_DISC_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_POLREV_PULSE_INT,      /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_MOMENTARY_LOOP_OPEN_INT,   /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_TIP_OPEN_INT,          /**< API Internal Profile Type */
+    VP_PRFWZ_PROFILE_NONE,                  /**< Indicates that internal
+                                                 profile data is not valid */
+    VP_PRFWZ_PROFILE_880_CAL_DATA = 0xFC,
+    VP_PRFWZ_PROFILE_890_CAL_DATA = 0xFD,
+
+    VP_PRFWZ_PROFILE_FXO_CONFIG = 0xFE,
+    VP_PRFWZ_PROFILE_DEVICE = 0xFF,
+    VP_PRFWZ_PROFILE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req.*/
+} VpProfileWizProfileType;
+
+typedef enum {
+    VP_PRFWZ_CUSTOM_ST_STANDBY = 0x00,
+    VP_PRFWZ_CUSTOM_ST_ACTIVE = 0x02,
+    VP_PRFWZ_CUSTOM_ST_ACTIVE_PR = 0x03,
+    VP_PRFWZ_CUSTOM_ST_TIP_OPEN = 0x04,
+    VP_PRFWZ_CUSTOM_ST_OHT = 0x06,
+    VP_PRFWZ_CUSTOM_ST_OHT_PR = 0x07,
+    VP_PRFWZ_CUSTOM_ST_DISCONNECT = 0x08,
+    VP_PRFWZ_CUSTOM_ST_RINGING = 0x09,
+    VP_PRFWZ_CUSTOM_ST_DET_MAP = 0xFF,
+    VP_PRFWZ_CUSTOM_ST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE/* Portability Req.*/
+} VpProfileWizCustomStateType;
+
+/** These locations are common to all profiles used in the API */
+typedef enum
+{
+    VP_PROFILE_TYPE_MSB = 0,
+    VP_PROFILE_TYPE_LSB = 1,
+    VP_PROFILE_INDEX = 2,
+    VP_PROFILE_LENGTH = 3,
+    VP_PROFILE_VERSION = 4,
+    VP_PROFILE_MPI_LEN = 5,
+    VP_PROFILE_DATA_START = 6,
+    VP_PROFILE_HDR_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpProfileHeaderFieldType;
+
+/* Define the Ringing Type (balanced/unbalanced) offset from end of MPI data */
+#define VP_PROFILE_RING_TYPE_OFFSET     1
+
+/** These are the locations of parameters in version 01 ringing profiles */
+typedef enum
+{
+    VP_RING_PROFILE_RING_TRIP   = 18,
+    VP_RING_PROFILE_CURRENT_LIM = 19,
+    VP_RING_PROFILE_MAX_RING_V  = 20,
+    VP_RING_PROFILE_TRACK_MODE  = 21,
+    VP_RING_PROFILE_ENUM_SIZE  =  FORCE_STANDARD_C_ENUM_SIZE /* Portability Req */
+} VpRingProfileFieldType;
+
+/** These are the locations of parameters in version 01 DC profiles */
+typedef enum
+{
+    VP_DC_PROFILE_THRESHOLDS =  9,
+    VP_DC_PROFILE_DEBOUNCES  =  10,
+    VP_DC_PROFILE_FLOOR_V    =  11,
+    VP_DC_PROFILE_HOOK_HYST  =  12,
+    VP_DC_PROFILE_ENUM_SIZE  =  FORCE_STANDARD_C_ENUM_SIZE /* Portability Req */
+} VpDcProfileFieldType;
+
+typedef enum
+{
+    /*
+     * These parameters are the absolute locations of the specified value in
+     * the CID profile
+     */
+    VP_CID_PROFILE_FSK_PARAM_LEN = 6,
+    VP_CID_PROFILE_FSK_PARAM_CMD = 7,
+    VP_CID_PRFT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpCidProfileFieldType;
+
+/*
+ * These parameters are offset from the end of the FSK data to the value
+ * specified
+ */
+#define VP_CID_PROFILE_CHECKSUM_OFFSET_MSB      (1)
+#define VP_CID_PROFILE_CHECKSUM_OFFSET_LSB      (2)
+#define VP_CID_PROFILE_LENGTH_OF_ELEMENTS_MSB   (3)
+#define VP_CID_PROFILE_LENGTH_OF_ELEMENTS_LSB   (4)
+#define VP_CID_PROFILE_START_OF_ELEMENTS_MSB    (5)
+#define VP_CID_PROFILE_START_OF_ELEMENTS_LSB    (6)
+
+/** These locations are for Tone and Ringing Cadence (Sequencer) profiles */
+#define VP_PROFILE_TYPE_SEQUENCER_COUNT_MSB (6)
+#define VP_PROFILE_TYPE_SEQUENCER_COUNT_LSB (7)
+#define VP_PROFILE_TYPE_SEQUENCER_START     (8)
+
+/** These locations are for Calibration profiles */
+#define VP_CAL_PROFILE_NUM_ENTRIES  (6)
+#define VP_CAL_PROFILE_FIRST_ENTRY  (8)
+
+/******************************************************************************
+ *                        API Specific common FUNCTION PROTOTYPES             *
+ ******************************************************************************/
+void
+VpImplementNonMaskEvents(
+    VpOptionEventMaskType *pLineEventsMask,
+    VpOptionEventMaskType *pDevEventsMask);
+
+VpStatusType
+VpImplementDefaultSettings(
+    VpDevCtxType *pDevCtx,
+    VpLineCtxType *pLineCtx);
+
+EXTERN int
+VpGetProfileIndex (
+    const VpProfilePtrType pProfile);
+
+EXTERN bool
+VpVerifyProfileType(
+    VpProfileType type,
+    VpProfilePtrType pProfile);
+
+EXTERN bool
+VpIsDigit(
+    VpDigitType digit);
+
+/******************************************************************************
+ *                        VCP Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_VCP_SERIES)
+VpStatusType
+VpMakeVcpDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpVcpDeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVcpDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpVcpDeviceObjectType *pDevObj);
+
+#endif /* VP_CC_VCP_SERIES */
+
+/******************************************************************************
+ *                        VCP2 Specific FUNCTION PROTOTYPES                   *
+ ******************************************************************************/
+#if defined (VP_CC_VCP2_SERIES)
+VpStatusType
+Vcp2MakeDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpVcp2DeviceObjectType *pDevObj);
+
+VpStatusType
+Vcp2MakeDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpVcp2DeviceObjectType *pDevObj);
+
+EXTERN bool
+Vcp2ReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN void
+Vcp2SetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+#endif /* VP_CC_VCP2_SERIES */
+/******************************************************************************
+ *                        MELT Specific FUNCTION PROTOTYPES                   *
+ ******************************************************************************/
+#if defined (VP_CC_MELT_SERIES)
+
+VpStatusType
+MeltMakeDeviceObject(
+    VpDevCtxType *pDevCtx,
+    VpMeltDeviceObjectType *pDevObj);
+
+VpStatusType
+MeltMakeDeviceCtx(
+    VpDevCtxType *pDevCtx,
+    VpMeltDeviceObjectType *pDevObj);
+
+EXTERN bool
+MeltReadCalFlag(
+    VpLineCtxType *pLineCtx);
+
+EXTERN void
+MeltSetCalFlag(
+    VpLineCtxType *pLineCtx,
+    bool value);
+
+#endif /* VP_CC_MELT_SERIES */
+
+/******************************************************************************
+ *                        Kernel Specific FUNCTION PROTOTYPES                 *
+ ******************************************************************************/
+#if defined (VP_CC_KWRAP)
+  #include "vp_kernel.h"
+#endif /* VP_CC_KWRAP */
+
+
+/******************************************************************************
+ *                        790 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_790_SERIES)
+
+#ifndef VP790_EC_CH1
+  #define VP790_EC_CH1    0x01
+  #define VP790_EC_CH2    0x02
+  #define VP790_EC_CH3    0x04
+  #define VP790_EC_CH4    0x08
+#endif
+
+VpStatusType
+VpMakeVp790DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp790DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp790DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp790DeviceObjectType *pDevObj);
+
+void
+Vp790MuteChannel(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+bool
+Vp790FSKGeneratorReady(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+Vp790CliGetEncodedByte(
+    VpLineCtxType *pLineCtx,
+    uint8 *pByte);
+
+VpStatusType
+Vp790CtrlSetCliTone(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+void
+Vp790CtrlSetFSKGen(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    uint8 data);
+#endif /* VP_CC_790_SERIES */
+
+/******************************************************************************
+ *                        792 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+
+#if defined (VP_CC_792_SERIES)
+VpStatusType
+Vp792MakeDeviceObject(
+    VpDevCtxType            *pDevCtx,
+    Vp792DeviceObjectType   *pDevObj);
+
+VpStatusType
+Vp792MakeDeviceCtx(
+    VpDevCtxType            *pDevCtx,
+    Vp792DeviceObjectType   *pDevObj);
+
+#ifdef VP_CC_792_GROUP
+bool
+Vp792GroupGetEvent(
+    VpDevCtxType *pDevCtx,
+    VpEventType *pEvent);
+#endif
+#endif /* VP_CC_792_SERIES */
+
+/******************************************************************************
+ *                        880 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_880_SERIES)
+
+#ifndef VP880_EC_CH1
+  #define VP880_EC_CH1                0x01
+  #define VP880_EC_CH2                0x02
+#endif
+
+#ifndef VP880_WIDEBAND_MODE
+  #define VP880_WIDEBAND_MODE         0x20
+#endif
+
+VpStatusType
+VpMakeVp880DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp880DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp880DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp880DeviceObjectType *pDevObj);
+
+void
+Vp880MuteChannel(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+#if defined (VP_CSLAC_SEQ_EN) && defined (VP880_FXS_SUPPORT)
+bool
+Vp880FSKGeneratorReady(
+    VpLineCtxType *pLineCtx);
+
+VpCliEncodedDataType
+Vp880CliGetEncodedByte(
+    VpLineCtxType *pLineCtx,
+    uint8 *pByte);
+
+VpStatusType
+Vp880CtrlSetCliTone(
+    VpLineCtxType *pLineCtx,
+    bool mode);
+
+void
+Vp880CtrlSetFSKGen(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    uint8 data);
+#endif
+
+VpStatusType
+Vp880SetDTMFGenerators(
+    VpLineCtxType *pLineCtx,
+    VpCidGeneratorControlType mode,
+    VpDigitType digit);
+
+VpStatusType
+Vp880SetLineStateInt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp880SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+void
+Vp880LLSetSysState(
+    VpDeviceIdType deviceId,
+    VpLineCtxType *pLineCtx,
+    uint8 lineState,
+    bool writeToDevice);
+#endif /* VP_CC_880_SERIES */
+
+
+/******************************************************************************
+ *                        890 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_890_SERIES)
+  #include "vp890_api_int.h"
+#endif /* VP_CC_890_SERIES */
+
+
+/******************************************************************************
+ *                        580 Specific FUNCTION PROTOTYPES                    *
+ ******************************************************************************/
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+VpMakeVp580DeviceObject(
+    VpDevCtxType *pDevCtx,
+    Vp580DeviceObjectType *pDevObj);
+
+VpStatusType
+VpMakeVp580DeviceCtx(
+    VpDevCtxType *pDevCtx,
+    Vp580DeviceObjectType *pDevObj);
+
+#endif /* VP_CC_580_SERIES */
+
+/* Functions used internal to the API -- device dependant */
+#if defined (VP_CC_790_SERIES) || defined (VP_CC_880_SERIES) \
+ || defined (VP_CC_580_SERIES) || defined (VP_CC_890_SERIES)
+
+/* Converts ms to units of API_TICKRATE */
+#define MS_TO_TICKRATE(MS, API_TICKRATE)  \
+    ((uint16)(((((uint32)MS*256*2)/API_TICKRATE)+1)/2))
+#define TICKS_TO_MS(TICKS, API_TICKRATE)  \
+    (uint16) (((uint32)API_TICKRATE * (uint32)TICKS) / 256)
+#define MS_TO_TICKS_ROUND_UP(MS, API_TICKRATE)  \
+    ((uint16)(((((uint32)MS*256*2 + API_TICKRATE - 1)/API_TICKRATE)+1)/2))
+/* Gives frequency in units of 0.3662109375 Hz for signal generators */
+#define TICKRATE_TO_HZ(API_TICKRATE)  \
+    ((uint16)((uint32)(0x80000000 / API_TICKRATE) / 0x0C00))
+
+#define NO_DATA     0x00
+#define NOOP_CMD    0x06  /**< Standard No operation comnmand for all devices */
+
+#define MAX_CFAIL_TEST      10
+#define CFAIL_TEST_INTERVAL 10
+
+/**< CallerID Profile Data structure definitions */
+#define VP_FSK_MARK_SIGNAL     0xFF
+#define VP_FSK_CHAN_SEIZURE    0x55
+#define VP_FSK_DATA            0x11 /* Anything NOT Mark or C.S is ok */
+#define VP_FSK_NONE            0x00 /* When FSK Generator is not being used */
+
+typedef enum
+{
+    VP_CLI_NULL = 0,
+    VP_CLI_POLREV,              /**< No Parameters */
+    VP_CLI_MUTEON,              /**< No Parameters */
+    VP_CLI_MUTEOFF,             /**< No Parameters */
+    VP_CLI_ALERTTONE,           /**< Duration/Tone definition parameters */
+    VP_CLI_ALERTTONE2,          /**< Internal Alert Tone indicator */
+    VP_CLI_SILENCE,             /**< Duration Parameter */
+    VP_CLI_SILENCE_MASKHOOK,    /**< Duration/Masked-hook length parameters */
+    VP_CLI_DETECT,              /**< Tone and Timeout parameters */
+    VP_CLI_CHANSEIZURE,         /**< Duration Parameter */
+    VP_CLI_MARKSIGNAL,          /**< Duration Parameter */
+    VP_CLI_MESSAGE,             /**< No Parameters */
+    VP_CLI_USER_DEFINED,        /**< Not supported in API-II */
+    VP_CLI_EOT = 0x0D,          /**< No Parameters */
+    VP_CLI_DTMF_MESSAGE = 0x0E, /**< Message data to be sent in DTMF format */
+    VP_CLI_ELM_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpApiElementsType;
+
+/* VP API Function Prototypes - Not associated with a function pointer */
+#if defined(VP_CC_790_SERIES) || defined(VP_CC_880_SERIES) \
+ || defined(VP_CC_890_SERIES) || defined(VP_CC_580_SERIES)
+
+#ifdef VP_CC_890_SERIES
+VpStatusType
+Vp890InitDevicePcnRcn(
+    Vp890DeviceObjectType   *pDevObj,
+    VpDeviceIdType          deviceId);
+#endif
+
+#ifdef VP_CC_880_SERIES
+VpStatusType
+Vp880InitDevicePcnRcn(
+    Vp880DeviceObjectType   *pDevObj,
+    VpDeviceIdType          deviceId);
+#endif
+
+bool
+VpIsLowPowerTermType(
+    VpTermType termType);
+
+void
+VpCSLACClearMPIBuffer(
+    VpDeviceIdType deviceId);
+
+bool
+VpCSLACIsProfileValid(
+    VpProfileType       profType,
+    int16               tableSize,
+    uint16              profEntry,
+    VpProfilePtrType    *pProfTable,
+    VpProfilePtrType    pProfileInput,
+    VpProfilePtrType    *pProfileRslt);
+
+bool
+VpCSLACSetTimer(
+    uint16 *pTimer,
+    uint16 newValue);
+
+#endif
+
+int16
+VpConvertToInt16(
+    uint8 *dataPtr);
+
+int32
+VpConvertToInt32(
+    uint8 *dataPtr);
+
+VpStatusType
+VpCSLACSetAbsGain(
+    VpLineCtxType *pLineCtx,
+    VpOptionAbsGainType *gains);
+
+uint8
+ConvertApiState2PrfWizState(
+    const VpLineStateType state);
+
+VpLineStateType
+ConvertPrfWizState2ApiState(
+    uint8 state);
+
+void
+InitTimerVars(
+    VpLineCtxType *pLineCtx);
+
+bool
+VpUpdateDP(
+    uint16 tickRate,
+    VpOptionPulseType *pPulseSpecs,
+    VpDialPulseDetectType *pDpStruct,
+    VpOptionEventMaskType *pLineEvents);
+
+void
+VpInitDP(
+    VpDialPulseDetectType *pDpStruct);
+
+VpStatusType
+VpCSLACGetLineStatus(
+    VpLineCtxType *pLineCtx,
+    VpInputType input,
+    bool *pStatus);
+
+#if !defined(VP_REDUCED_API_IF)
+VpStatusType
+VpCSLACClearResults(
+    VpDevCtxType *pDevCtx);
+#endif
+
+VpStatusType
+VpCSLACDtmfDigitDetected(
+    VpLineCtxType *pLineCtx,
+    VpDigitType digit,
+    VpDigitSenseType sense);
+
+VpLineStateType
+VpGetReverseState(
+    VpLineStateType currentState);
+
+void
+VpCSLACSetVas(
+    uint8 *dcFeed,
+    uint16 vasValue);
+
+#ifdef CSLAC_GAIN_RELATIVE
+void
+VpConvertFixed2Csd(
+    uint16 fixed,
+    uint8 *csdBuf);
+
+uint16
+VpConvertCsd2Fixed(
+    uint8 *csdBuf);
+#endif
+#endif
+
+#if defined (VP_CC_790_SERIES)
+VpStatusType
+Vp790SetLineStateInt(
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp790SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+#endif
+
+
+#if defined (VP_CC_580_SERIES)
+VpStatusType
+Vp580SetLineStateInt(
+
+    VpLineCtxType *pLineCtx,
+    VpLineStateType state);
+
+VpStatusType
+Vp580SetLineTone(
+    VpLineCtxType *pLineCtx,
+    VpProfilePtrType pToneProfile,
+    VpProfilePtrType pCadProfile,
+    VpDtmfToneGenType *pDtmfControl);
+
+#endif
+
+uint16
+VpComputeSquareRoot(
+    uint32 number);
+
+#endif /* VP_API_INT_H */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_lib_cfg.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_lib_cfg.h
new file mode 100644
index 0000000..1a0828d
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_lib_cfg.h
@@ -0,0 +1,106 @@
+/** \file vp_api_lib_cfg.h
+ * vp_api_lib_cfg.h
+ *
+ * This file contains the default options for various libraries. In general
+ * the default options are same as top level API default options. However
+ * VP-API provides a mechanism to define default options that is different
+ * compared to top level default options. This file provides such a mechanism.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 7591 $
+ * $LastChangedDate: 2010-08-16 09:33:04 -0500 (Mon, 16 Aug 2010) $
+ */
+
+#ifndef VP_API_LIB_CFG_H
+#define VP_API_LIB_CFG_H
+
+/******************************************************************************
+ * Library Specific default options                                           *
+ *****************************************************************************/
+/* The following section provides mechanisms to define default options for
+ * individual VTD families that is different compared to VP-API top level
+ * default settins.
+ *
+ * NOTE: Users are free to change individual library's default settings as long
+ * as it is not needed by the API and the VTD understands it.
+ */
+
+#ifdef VP_CC_VCP_SERIES
+
+/* Default Event Masks for VCP */
+/* First, define the events that VCP does not understand or not needed */
+#define VCP_EVCAT_FAULT_NOT_NEEDED \
+        (VP_DEV_EVID_EVQ_OFL_FLT    | /* VCP does not understand */ \
+         VP_DEV_EVID_WDT_FLT)        /* VCP does not understand */
+/* Second, define the events that are specially needed for the VCP API */
+#define VCP_EVCAT_FAULT_NEEDED (~0x0000)
+
+/* Third, Define the composite events */
+#define VCP_OPTION_DEFAULT_FAULT_EVENT_MASK  \
+    ((VP_OPTION_DEFAULT_FAULT_EVENT_MASK  |  /* Top level API default */ \
+     VCP_EVCAT_FAULT_NOT_NEEDED) &         /* Events not needed for VCP*/ \
+     VCP_EVCAT_FAULT_NEEDED)                /* Events needed for VCP */
+
+/* First, define the events that VCP does not understand or not needed */
+#define VCP_EVCAT_SIGNALLING_NOT_NEEDED \
+        (VP_LINE_EVID_US_TONE_DETECT | /* VCP does not understand */  \
+         VP_LINE_EVID_DS_TONE_DETECT | /* VCP does not understand */  \
+         VP_DEV_EVID_SEQUENCER)       /* VCP does not understand */
+/* Second, define the events that are specially needed for the VCP API */
+#define VCP_EVCAT_SIGNALLING_NEEDED (~0x0000)
+
+/* Third, Define the composite events */
+#define VCP_OPTION_DEFAULT_SIGNALING_EVENT_MASK  \
+    ((VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK  |  /* Top level API default */ \
+     VCP_EVCAT_SIGNALLING_NOT_NEEDED) &         /* Events not needed for VCP*/ \
+     VCP_EVCAT_SIGNALLING_NEEDED)                /* Events needed for VCP */
+
+/* First, define the events that VCP does not understand or not needed */
+#define VCP_EVCAT_RESPONSE_NOT_NEEDED \
+        (VP_DEV_EVID_DEV_INIT_CMP ) /* VCP does not understand */
+/* Second, define the events that are specially needed for the VCP API */
+#define VCP_EVCAT_RESPONSE_NEEDED (~0x0000)
+
+/* Third, Define the composite events */
+#define VCP_OPTION_DEFAULT_RESPONSE_EVENT_MASK  \
+    ((VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK  |  /* Top level API default */ \
+     VCP_EVCAT_RESPONSE_NOT_NEEDED) &         /* Events not needed for VCP*/ \
+     VCP_EVCAT_RESPONSE_NEEDED)                /* Events needed for VCP */
+
+#define VCP_OPTION_DEFAULT_FXO_EVENT_MASK    (0xffff)/* VCP does not understand */
+
+#define VCP_OPTION_DEFAULT_PACKET_EVENT_MASK (0xffff)/* VCP does not understand */
+#endif /* VP_CC_VCP_SERIES */
+
+
+#ifdef VP_CC_VCP2_SERIES
+/* Default option settings for VCP2:  These are the default values applied at
+ * VpInitDevice() and/or VpInitLine().  If your application uses more than one
+ * type of device (VTD) and you with to specify VCP2-specific defaults that
+ * differ from the defaults specified in vp_api_cfg.h, do so here. */
+
+#include "vcp2_api.h"
+
+/* VCP2-specific default event masks: */
+#define VCP2_DEFAULT_MASK_FAULT     (VP_OPTION_DEFAULT_FAULT_EVENT_MASK     | VCP2_INVALID_FAULT_EVENTS)
+#define VCP2_DEFAULT_MASK_SIGNALING (VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK | VCP2_INVALID_SIGNALING_EVENTS)
+#define VCP2_DEFAULT_MASK_RESPONSE  (VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK  | VCP2_INVALID_RESPONSE_EVENTS)
+#define VCP2_DEFAULT_MASK_TEST      (VP_OPTION_DEFAULT_TEST_EVENT_MASK      | VCP2_INVALID_TEST_EVENTS)
+#define VCP2_DEFAULT_MASK_PROCESS   (VP_OPTION_DEFAULT_PROCESS_EVENT_MASK   | VCP2_INVALID_PROCESS_EVENTS)
+#define VCP2_DEFAULT_MASK_FXO       (VP_OPTION_DEFAULT_FXO_EVENT_MASK       | VCP2_INVALID_FXO_EVENTS)
+#define VCP2_DEFAULT_MASK_PACKET    (VP_OPTION_DEFAULT_PACKET_EVENT_MASK    | VCP2_INVALID_PACKET_EVENTS)
+
+#endif
+#ifdef VP_CC_MELT_SERIES
+
+#define MELT_DEFAULT_MASK_FAULT     (VP_OPTION_DEFAULT_FAULT_EVENT_MASK     | MELT_INVALID_FAULT_EVENTS)
+#define MELT_DEFAULT_MASK_SIGNALING (VP_OPTION_DEFAULT_SIGNALING_EVENT_MASK | MELT_INVALID_SIGNALING_EVENTS)
+#define MELT_DEFAULT_MASK_RESPONSE  (VP_OPTION_DEFAULT_RESPONSE_EVENT_MASK  | MELT_INVALID_RESPONSE_EVENTS)
+#define MELT_DEFAULT_MASK_TEST      (VP_OPTION_DEFAULT_TEST_EVENT_MASK      | MELT_INVALID_TEST_EVENTS)
+#define MELT_DEFAULT_MASK_PROCESS   (VP_OPTION_DEFAULT_PROCESS_EVENT_MASK   | MELT_INVALID_PROCESS_EVENTS)
+#define MELT_DEFAULT_MASK_FXO       (VP_OPTION_DEFAULT_FXO_EVENT_MASK       | MELT_INVALID_FXO_EVENTS)
+#define MELT_DEFAULT_MASK_PACKET    (VP_OPTION_DEFAULT_PACKET_EVENT_MASK    | MELT_INVALID_PACKET_EVENTS)
+#endif
+#endif /* VP_API_LIB_CFG_H */
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_option.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_option.h
new file mode 100644
index 0000000..c935820
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_option.h
@@ -0,0 +1,398 @@
+/** \file vp_api_option.h
+ * vp_api_option.h
+ *
+ * This file contains declaration associated with VP-API Options.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8467 $
+ * $LastChangedDate: 2011-04-01 10:24:49 -0500 (Fri, 01 Apr 2011) $
+ */
+
+#ifndef VP_API_OPTION
+#define VP_API_OPTION
+
+#include "vp_api_types.h"
+#include "vp_api_cfg.h"
+#include "vp_api_event.h"
+
+/* Option IDs.  (See Options chapter in VP-API-2 Reference Guide.)
+ * Line-specific option IDs begin with "VP_OPTION_ID_".  Device-specific
+ * option IDs begin with "VP_DEVICE_OPTION_ID_".  When new option IDs are added,
+ * the VpOptionValueType struct (below) must be updated accordingly.
+ */
+typedef enum {
+    VP_DEVICE_OPTION_ID_PULSE            = 0x00,
+    VP_DEVICE_OPTION_ID_CRITICAL_FLT     = 0x01,
+    VP_OPTION_ID_ZERO_CROSS              = 0x02,
+    VP_DEVICE_OPTION_ID_RAMP2STBY        = 0x03,
+    VP_OPTION_ID_PULSE_MODE              = 0x04,
+    VP_OPTION_ID_TIMESLOT                = 0x05,
+    VP_OPTION_ID_CODEC                   = 0x06,
+    VP_OPTION_ID_PCM_HWY                 = 0x07,
+    VP_OPTION_ID_LOOPBACK                = 0x08,
+    VP_OPTION_ID_LINE_STATE              = 0x09,
+    VP_OPTION_ID_EVENT_MASK              = 0x0A,
+    VP_OPTION_ID_RESERVED_1              = 0x0B,
+    VP_OPTION_ID_RING_CNTRL              = 0x0C,
+    VP_OPTION_ID_RESERVED_2              = 0x0D,
+    VP_OPTION_ID_DTMF_MODE               = 0x0E,
+    VP_DEVICE_OPTION_ID_DEVICE_IO        = 0x0F,
+    VP_OPTION_ID_RESERVED_EVENT_MASK_VCP = 0x10,
+    VP_OPTION_ID_PCM_TXRX_CNTRL          = 0x11,
+    VP_DEVICE_OPTION_ID_PULSE2           = 0x12,
+    VP_OPTION_ID_LINE_IO_CFG             = 0x13,
+    VP_DEVICE_OPTION_ID_DEV_IO_CFG       = 0x14,
+    VP_OPTION_ID_DTMF_SPEC               = 0x15,
+    VP_DEVICE_OPTION_ID_PARK_MODE        = 0x16,
+    VP_OPTION_ID_DCFEED_SLOPE            = 0x17,
+    VP_OPTION_ID_SWITCHER_CTRL           = 0x18,
+    VP_OPTION_ID_HOOK_DETECT_MODE        = 0x19,
+    VP_OPTION_ID_AUTO_LOOP_COND          = 0x1A,
+
+    /* New option values may be added in this gap in the future. */
+    VP_OPTION_ID_PULSE                   = 0x24,
+    VP_OPTION_ID_DEBUG_SELECT            = 0x25,
+    VP_OPTION_ID_ABS_GAIN                = 0x26,
+    VP_DEVICE_OPTION_ID_PCM_SIG_CTL      = 0x27,
+    VP_OPTION_ID_LINESTATE_CTL_MODE      = 0x28,
+
+    VP_NUM_OPTION_IDS
+} VpOptionIdType;
+
+/** Parameters for dial pulse, flash, and on-hook */
+typedef struct {
+    uint16 breakMin;        /**< Minimum pulse break time (in 125uS) */
+    uint16 breakMax;        /**< Maximum pulse break time (in 125uS) */
+    uint16 makeMin;         /**< Minimum pulse make time (in 125uS) */
+    uint16 makeMax;         /**< Maximum pulse make time (in 125uS) */
+    uint16 interDigitMin;   /**< Minimum pulse interdigit time (in 125uS) */
+    uint16 flashMin;        /**< Minimum flash break time (in 125uS) */
+    uint16 flashMax;        /**< Maximum flash break time (in 125uS) */
+#ifdef EXTENDED_FLASH_HOOK
+    uint16 onHookMin;       /**< Minimum on-hook time (in 125uS) */
+#endif
+} VpOptionPulseType;
+
+typedef struct {
+    uint16 breakMin;        /**< Minimum pulse break time (in 125uS) */
+    uint16 breakMax;        /**< Maximum pulse break time (in 125uS) */
+    uint16 makeMin;         /**< Minimum pulse make time (in 125uS) */
+    uint16 makeMax;         /**< Maximum pulse make time (in 125uS) */
+    uint16 interDigitMin;   /**< Minimum pulse interdigit time (in 125uS) */
+    uint16 flashMin;        /**< Minimum flash break time (in 125uS) */
+    uint16 flashMax;        /**< Maximum flash break time (in 125uS) */
+    uint16 onHookMin;       /**< Minimum on-hook time (in 125uS) */
+    uint16 offHookMin;      /**< Minimum off-hook time (in 125uS) */
+} VpOptionLinePulseType;
+
+/** Method for line control when critical faults are detected */
+typedef struct {
+    /**< The line is set to disconnect when the specified fault is active and
+     * the "En" bit is set TRUE
+     */
+    bool acFltDiscEn;           /**< AC fault detected */
+    bool dcFltDiscEn;           /**< DC fault detected */
+    bool thermFltDiscEn;        /**< Thermal fault detected */
+} VpOptionCriticalFltType;
+
+/** Method for zero-cross control */
+typedef enum {
+    VP_OPTION_ZC_M4B  = 0, /**< Zero-Cross On - Make before break */
+    VP_OPTION_ZC_B4M  = 1, /**< Zero-Cross On - Break before make */
+    VP_OPTION_ZC_NONE = 2, /**< Turn Zero-Cross control off */
+    VP_OPTION_ZC_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_OPTION_ZC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req. */
+} VpOptionZeroCrossType;
+
+/** Dial Pulse decode enable/disable */
+typedef enum {
+    VP_OPTION_PULSE_DECODE_OFF      = 0, /**< Disable Pulse Decode */
+    VP_OPTION_PULSE_DECODE_ON       = 1, /**< Enable Pulse Decode */
+    VP_OPTION_PULSE_DECODE_BRIDGING = 2, /**< Enable Pulse Decode (With Bridging) */
+    VP_OPTION_PULSE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPulseModeType;
+
+/** Transmit/Receive Timeslot setting (timeslot and control) */
+typedef struct {
+    uint8 tx;   /**< 8-bit TX timeslot */
+    uint8 rx;   /**< 8-bit RX timeslot */
+} VpOptionTimeslotType;
+
+typedef enum {
+    VP_OPTION_ALAW     = 0, /**< Select G.711 A-Law PCM encoding */
+    VP_OPTION_MLAW     = 1, /**< Select G.711 Mu-Law PCM encoding */
+    VP_OPTION_LINEAR   = 2, /**< Select Linear PCM encoding */
+    VP_OPTION_WIDEBAND = 3, /**< Select Wideband PCM encoding */
+    VP_NUM_OPTION_CODEC_TYPE_IDS,
+    VP_OPTION_CODEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionCodecType;
+
+/** PCM Highway Selection (B valid on select devices only) */
+typedef enum {
+    VP_OPTION_HWY_A          = 0, /**< Select the 'A' PCM Highway */
+    VP_OPTION_HWY_B          = 1, /**< Select the 'B' PCM Highway */
+    VP_OPTION_HWY_TX_A_RX_B  = 2, /**< Transmit on Highway A, receive on B */
+    VP_OPTION_HWY_TX_B_RX_A  = 3, /**< Transmit on Highway A, receive on A */
+    VP_OPTION_HWY_TX_AB_RX_A = 4, /**< Transmit on Highway A and B, receive on A */
+    VP_OPTION_HWY_TX_AB_RX_B = 5, /**< Transmit on Highway A and B, receive on B */
+    VP_OPTION_HWY_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPcmHwyType;
+
+/** Loopback option selection */
+typedef enum {
+    VP_OPTION_LB_OFF      = 0, /**< All loopbacks off */
+
+    /* Following loopback options are supported for CSLAC and VCP only */
+    VP_OPTION_LB_TIMESLOT = 1, /**< Perform a timeslot loopback */
+    VP_OPTION_LB_DIGITAL  = 2, /**< Perform a full-digital loopback */
+    VP_OPTION_LB_CHANNELS = 3, /**< Connects FXO to FXS line on same device */
+
+    VP_NUM_LB_OPTIONS,
+    VP_OPTION_LB_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionLoopbackType;
+
+/** Active Line State battery supply selection */
+typedef enum {
+    VP_OPTION_BAT_AUTO  = 0, /**< Automatic Batery selection */
+    VP_OPTION_BAT_HIGH  = 1, /**< Use High Batery */
+    VP_OPTION_BAT_LOW   = 2, /**< Use Low Batery */
+    VP_OPTION_BAT_BOOST = 3, /**< Include Positive Batery */
+    VP_NUM_OPTION_BAT_IDS,
+    VP_OPTION_BAT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionBatType;
+
+/** Active Line State battery supply selection */
+typedef struct {
+    bool battRev;       /**< Smooth/Abrupt Battery Reversal (TRUE = abrupt) */
+
+    VpOptionBatType bat;    /**< Battery selection for Active line state */
+} VpOptionLineStateType;
+
+/** Ring control option */
+typedef enum {
+
+    /* FXS */
+    VP_LINE_STANDBY         = 0x00, /**< Low power line feed state */
+    VP_LINE_TIP_OPEN        = 0x01, /**< Tip open circuit state */
+    VP_LINE_ACTIVE          = 0x02, /**< Line Feed w/out VF */
+    VP_LINE_ACTIVE_POLREV   = 0x03, /**< Polarity Reversal Line Feed w/out VF */
+    VP_LINE_TALK            = 0x04, /**< Normal off-hook Active State; Voice Enabled */
+    VP_LINE_TALK_POLREV     = 0x05, /**< Normal Active with reverse polarity; Voice Enabled */
+    VP_LINE_OHT             = 0x06, /**< On-Hook tranmission state */
+    VP_LINE_OHT_POLREV      = 0x07, /**< Polarity Reversal On-Hook tranmission state */
+    VP_LINE_DISCONNECT      = 0x08, /**< Denial of service */
+    VP_LINE_RINGING         = 0x09, /**< Ringing state */
+    VP_LINE_RINGING_POLREV  = 0x0A, /**< Ringing w/Polarity Reversal */
+    VP_LINE_STANDBY_POLREV  = 0x10, /**< Low power polrev line feed state */
+    VP_LINE_PARK            = 0x11, /**< Park mode */
+    VP_LINE_RING_OPEN       = 0x12, /**< Ring open */
+    VP_LINE_HOWLER          = 0x13, /**< Howler */
+    VP_LINE_TESTING         = 0x14, /**< Testing */
+    VP_LINE_DISABLED        = 0x15, /**< Disabled */
+    VP_LINE_NULLFEED        = 0x16, /**< Null-feed */
+    VP_LINE_HOWLER_PCM      = 0x17, /**< Howler with PCM highway enabled */
+
+    /* FXO */
+    VP_LINE_FXO_OHT,        /**< FXO Line providing Loop Open w/VF */
+    VP_LINE_FXO_LOOP_OPEN,  /**< FXO Line providing Loop Open w/out VF */
+    VP_LINE_FXO_LOOP_CLOSE, /**< FXO Line providing Loop Close w/out VF */
+    VP_LINE_FXO_TALK,       /**< FXO Line providing Loop Close w/VF */
+    VP_LINE_FXO_RING_GND,   /**< FXO Line providing Ring Ground (GS only)*/
+
+    VP_NUM_LINE_STATES,
+    VP_LINE_STATE_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_LINE_STATE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLineStateType;
+
+typedef struct {
+    VpOptionZeroCrossType zeroCross;    /**< LCAS zero cross control */
+
+    uint16 ringExitDbncDur; /**< Ringing Exit Debounce Duration; Used during end
+                             * of ON periods of ringing cadences; 125uS
+                             * resolution
+                             */
+
+    VpLineStateType ringTripExitSt; /**< State to automatically switch to upon
+                                     * ring trip
+                                     */
+}  VpOptionRingControlType;
+
+/** DTMF detection option */
+typedef enum {
+    VP_OPTION_DTMF_DECODE_OFF = 0, /**< Disable DTMF Digit Decode */
+    VP_OPTION_DTMF_DECODE_ON  = 1, /**< Enable DTMF Digit  Decode */
+    VP_OPTION_DTMF_GET_STATUS = 2, /**< Do not change anything; Just get the DTMF status  */
+    VP_NUM_OPTION_DTMF_IDS,
+    VP_OPTION_DTMF_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionDtmfModeControlType;
+
+/* Device I/O Option related definitions */
+typedef enum {
+    VP_IO_INPUT_PIN  = 0, /* Configure GPIO pin as input pin */
+    VP_IO_OUTPUT_PIN = 1, /* Configure GPIO pin as output pin */
+    VP_IO_DIR_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDeviceIoDirectionType;
+
+typedef enum {
+    VP_OUTPUT_DRIVEN_PIN = 0, /* Configure as TTL/CMOS output pin */
+    VP_OUTPUT_OPEN_PIN   = 1, /* Configure as open collector/drain output pin */
+    VP_OUTPUT_TYPE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDeviceOutputPinType;
+
+typedef struct {
+    uint32 directionPins_31_0;      /* Device specific IO pin direction
+                                     * (Pins 0 - 31) */
+    uint32 directionPins_63_32;     /* Device specific IO pin direction
+                                     * (Pins 32 - 63) */
+    uint32 outputTypePins_31_0;     /* Output pin type (Pins 0 - 31) */
+    uint32 outputTypePins_63_32;    /* Output pin type (Pins 32 - 63) */
+} VpOptionDeviceIoType;
+
+/* Definition for line I/O config option */
+typedef struct {
+    uint8 direction;
+    uint8 outputType;
+} VpOptionLineIoConfigType;
+
+/* Definition for device I/O config option */
+typedef struct {
+    VpOptionLineIoConfigType lineIoConfig[VP_MAX_LINES_PER_DEVICE];
+} VpOptionDeviceIoConfigType;
+
+typedef enum {
+    VP_OPTION_PCM_BOTH      = 0, /* Enable both PCM transmit and receive paths */
+    VP_OPTION_PCM_RX_ONLY   = 1, /* Enable PCM receive path only */
+    VP_OPTION_PCM_TX_ONLY   = 2, /* Enable PCM transmit path only */
+    VP_OPTION_PCM_ALWAYS_ON = 3, /* Prevents disabling of PCM path */
+    VP_PCM_TXRX_CNTRL_ENUM_RSVD = FORCE_SIGNED_ENUM,
+    VP_PCM_TXRX_CNTRL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionPcmTxRxCntrlType;
+
+/** Direction Specification */
+typedef enum {
+    VP_DIRECTION_DS,
+    VP_DIRECTION_US,
+    VP_DIRECTION_INVALID,   /**< Used by the API to determine if the direction
+                             * field is valid */
+    VP_DIRECTION_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpDirectionType;
+
+#define VP_LINE_FLAG_BYTES ((VP_MAX_LINES_PER_DEVICE + 7) / 8)
+
+/** DTMF detection option control */
+typedef struct {
+    VpOptionDtmfModeControlType dtmfControlMode; /**< DTMF detection
+                                                  * Enable/Disable */
+    VpDirectionType direction;                  /**< Detection direction */
+    uint32 dtmfDetectionSetting;                /**< Indicates the DTMF
+                                                 *   detection setting for first
+                                                 *    32 lines */
+    uint8 dtmfResourcesRemaining;               /**< DTMF decoder resources
+                                                 *   remaining */
+    uint8 dtmfDetectionEnabled[VP_LINE_FLAG_BYTES];
+                                                /**< DTMF detection setting for
+                                                 *   lines 7-0, 15-8, etc. */
+} VpOptionDtmfModeType;
+
+/** Regional DTMF Specs */
+typedef enum {
+    VP_OPTION_DTMF_SPEC_ATT  = 0, /* Q.24 AT&T */
+    VP_OPTION_DTMF_SPEC_NTT  = 1, /* Q.24 NTT */
+    VP_OPTION_DTMF_SPEC_AUS  = 2, /* Q.24 Australian */
+    VP_OPTION_DTMF_SPEC_BRZL = 3, /* Q.24 Brazilian */
+    VP_OPTION_DTMF_SPEC_ETSI = 4, /* ETSI ES 201 235-3 v1.3.1 */
+    VP_OPTION_DTMF_SPEC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionDtmfSpecType;
+
+/**< The following types are for Park Mode options */
+typedef struct {
+    uint16 discTime;    /**< Specified in 500ms increments, up to 8 seconds */
+    uint16 standbyTime; /**< Specified in 100ms increments, up to 8 seconds */
+} VpOptionParkModeType;
+
+/** Hook detection modes  */
+typedef enum {
+    VP_OPTION_HOOKDET_NORMAL         = 0,  /* normal hook detection behavior */
+    VP_OPTION_HOOKDET_DISC_IS_ONHOOK = 1,  /* in the VP_LINE_DISCONNECT or VP_LINE_DISABLED
+                                              state, the hook status is always considered
+                                              to be on-hook */
+    VP_OPTION_HOOKDET_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpOptionHookDetectModeType;
+
+/* Option value struct for VP_OPTION_ID_AUTO_LOOP_COND: */
+typedef enum {
+    VP_LOOP_COND_NONE  = 0x0000,    /* feature disabled */
+    VP_LOOP_COND_RLOOP = 0x0001,    /* read loop resistance */
+    VP_LOOP_COND_ILG   = 0x0002,    /* read longitudinal (common mode) current */
+    VP_LOOP_COND_IMT   = 0x0004,    /* read metallic (differential) current */
+    VP_LOOP_COND_VSAB  = 0x0008,    /* read metallic (differential) voltage */
+    VP_LOOP_COND_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopCondSelectType;
+
+typedef struct {
+    uint16 select;  /* bitmask (multiple VpLoopCondSelectType values can be ORed
+                       together */
+    uint16 delay;   /* amount of time (in ms) after HOOK_OFF before
+                       measurement(s) */
+} VpOptionAutoLoopCondType;
+
+/* Definition for Absolute Level option */
+typedef struct {
+    int16 gain_AToD;
+    int16 gain_DToA;
+} VpOptionAbsGainType;
+
+#define VP_OPTION_ABS_GAIN_QUIET        (-32767)
+#define VP_OPTION_ABS_GAIN_NO_CHANGE    (+32767)
+#define VP_ABS_GAIN_UNKNOWN             (VP_OPTION_ABS_GAIN_NO_CHANGE - 1)
+
+/* Option value struct for VP_DEVICE_OPTION_ID_PCM_SIG_CTL: */
+typedef struct {
+    bool enable;
+    uint8 ctlTimeslot;
+    uint8 sigTimeslot;
+} VpOptionPcmSigCtlType;
+
+/* Option value struct for VP_OPTION_ID_LINESTATE_CTL_MODE: */
+typedef enum {
+    VP_OPTION_LINESTATE_CTL_NORMAL     = 0x0000,
+    VP_OPTION_LINESTATE_CTL_PCM        = 0x0080
+} VpOptionLinestateCtlModeType;
+
+/* The following struct can be passed to VpGetResults() if the option ID is not
+   known at compile time, to ensure that the buffer is large enough regardless
+   of the option type. */
+typedef union {
+    VpOptionPulseType pulse;                       /* VP_DEVICE_OPTION_ID_PULSE        */
+                                                   /* VP_DEVICE_OPTION_ID_PULSE2       */
+    VpOptionCriticalFltType criticalFlt;           /* VP_DEVICE_OPTION_ID_CRITICAL_FLT */
+    VpOptionZeroCrossType zeroCross;               /* VP_OPTION_ID_ZERO_CROSS          */
+    uint16 ramp2stby;                              /* VP_DEVICE_OPTION_ID_RAMP2STBY    */
+    VpOptionPulseModeType pulseMode;               /* VP_OPTION_ID_PULSE_MODE          */
+    VpOptionTimeslotType timeslot;                 /* VP_OPTION_ID_TIMESLOT            */
+    VpOptionCodecType codec;                       /* VP_OPTION_ID_CODEC               */
+    VpOptionPcmHwyType pcmHwy;                     /* VP_OPTION_ID_PCM_HWY             */
+    VpOptionLoopbackType loopback;                 /* VP_OPTION_ID_LOOPBACK            */
+    VpOptionLineStateType lineState;               /* VP_OPTION_ID_LINE_STATE          */
+    VpOptionEventMaskType eventMask;               /* VP_OPTION_ID_EVENT_MASK          */
+    VpOptionRingControlType ringControl;           /* VP_OPTION_ID_RING_CNTRL          */
+    VpOptionDtmfModeType dtmfMode;                 /* VP_OPTION_ID_DTMF_MODE           */
+    VpOptionDeviceIoType deviceIo;                 /* VP_DEVICE_OPTION_ID_DEVICE_IO    */
+    VpOptionPcmTxRxCntrlType pcmTxRxCntrl;         /* VP_OPTION_ID_PCM_TXRX_CNTRL      */
+    VpOptionDeviceIoConfigType deviceIoConfig;     /* VP_DEVICE_OPTION_ID_DEV_IO_CFG   */
+    VpOptionLineIoConfigType lineIoConfig;         /* VP_OPTION_ID_LINE_IO_CFG         */
+    VpOptionDtmfSpecType dtmfSpec;                 /* VP_OPTION_ID_DTMF_SPEC           */
+    VpOptionParkModeType parkMode;                 /* VP_DEVICE_OPTION_ID_PARK_MODE    */
+    VpOptionLinePulseType linePulse;               /* VP_OPTION_ID_PULSE               */
+    uint16 dcFeedSlope;                            /* VP_OPTION_ID_DCFEED_SLOPE        */
+    bool switcherCtrl;                             /* VP_OPTION_ID_SWITCHER_CTRL       */
+    uint32 debugSelect;                            /* VP_OPTION_ID_DEBUG_SELECT        */
+    VpOptionAbsGainType absGain;                   /* VP_OPTION_ID_ABS_GAIN            */
+    VpOptionHookDetectModeType hookDetectMode;     /* VP_OPTION_ID_HOOK_DETECT_MODE    */
+    VpOptionPcmSigCtlType pcmSigCtl;               /* VP_DEVICE_OPTION_ID_PCM_SIG_CTL  */
+    VpOptionLinestateCtlModeType linestateCtlMode; /* VP_OPTION_ID_LINESTATE_CTL_MODE  */
+    VpOptionAutoLoopCondType autoLoopCond;         /* VP_OPTION_ID_AUTO_LOOP_COND      */
+} VpOptionValueType;
+
+#endif /* VP_API_OPTION */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_test.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_test.h
new file mode 100644
index 0000000..11d5bc7
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_test.h
@@ -0,0 +1,948 @@
+/** \file vp_api_test.h
+ * file vp_api_test.h
+ *
+ * This file contains declaration associated with VP-API Test features.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 7301 $
+ * $LastChangedDate: 2010-06-08 14:43:02 -0500 (Tue, 08 Jun 2010) $
+ */
+
+#ifndef VP_API_TEST_H
+#define VP_API_TEST_H
+
+#include "vp_api_types.h"
+#include "vp_api_option.h"
+#include "vp_api_event.h"   /* For VpDigitType */
+
+#define VP_TEST_NOT_MEASURED            0x8000    /* a value of -1 to indicate not measured */
+                                        /* chosen because it is an impermissible value in those tests where used */
+
+/** Tests supported by VpTestLine function */
+typedef enum
+{
+    VP_TEST_ID_PREPARE        = 0x00, /* Prepare for a test sequence */
+    VP_TEST_ID_CONCLUDE       = 0x01, /* Conclude a test sequence */
+    VP_TEST_ID_SET_SENSE_GAIN = 0x02, /* Set ILG and IMT gains high or low */
+    VP_TEST_ID_OPEN_VDC       = 0x03, /* Measure open DC voltage */
+    VP_TEST_ID_OPEN_VAC       = 0x04, /* Measure open AC voltage */
+    VP_TEST_ID_DIFF_VAC       = 0x05, /* Measure differential AC voltage */
+    VP_TEST_ID_DC_RLOOP       = 0x06, /* Measure DC loop resistance */
+    VP_TEST_ID_AC_RLOOP       = 0x07, /* Measure AC loop impedance */
+    VP_TEST_ID_NULL_IGND      = 0x08, /* Null ground current */
+    VP_TEST_ID_3ELE_RES       = 0x09, /* Measure 3-element insulation resistance */
+    VP_TEST_ID_3ELE_CAP       = 0x0A, /* Measure 3-element capacitance */
+    VP_TEST_ID_IDC            = 0x0B, /* Measure DC currents */
+    VP_TEST_ID_IAC            = 0x0C, /* Measure AC currents */
+    VP_TEST_ID_KEYPAD         = 0x0D, /* Keypad DTMF and Pulse dial test */
+    VP_TEST_ID_NOISE          = 0x0E, /* Measure Active or Passive Noise 3, 3.4 & 15KhZ */
+    VP_TEST_ID_SNR_QDIST      = 0x0F, /* Measure SNR and quantization distortion */
+    VP_TEST_ID_ARB_1TONE      = 0x10, /* Measure arbitrary single tone */
+    VP_TEST_ID_TONE_GEN       = 0x11, /* Generate a single/dual/quad-tone */
+    VP_TEST_ID_DIALTONE       = 0x12, /* Detect and measure dial tone (Inward test) */
+    VP_TEST_ID_HYBRID_LOSS    = 0x13, /* Measure trans-hybrid loss */
+    VP_TEST_ID_ALT_REN        = 0x14, /* Alternative method used to measure REN */
+    VP_TEST_ID_HOOK_STATUS    = 0x15, /* Check Hook Status (while in test mode) */
+    VP_TEST_ID_PCM_COLLECT    = 0x16, /* Collect PCM samples */
+    VP_TEST_ID_AC_RLOOP_PHASE = 0x17, /* Rloop with Phase information */
+    VP_TEST_ID_SET_BATTERIES  = 0x18, /* Select batteries for line testing */
+    VP_TEST_ID_MONITOR_IV     = 0x19, /* Non-Intrusive Monitoring Test */
+    VP_TEST_ID_UNBAL_TONE     = 0x1A, /* Generates an unbalanced tracing tone */
+    VP_TEST_ID_3ELE_RES_VMID  = 0x1B, /* Measure 3-element insulation resistance with a specified vMid */
+    VP_TEST_ID_AC_TRANS       = 0x1C, /* Measures digital-digital transmission characteristics */
+    VP_TEST_ID_GEN_TEST       = 0x1D, /* Multi-functional primitive */
+    VP_TEST_ID_SLOPE_REN      = 0x1E, /* REN test with a ramp instead of step */
+    /* Test IDs above this line are supported by one or more VCP devices.
+       Their values must not change.  More VCP tests might be added above this
+       line in the future. */
+
+    VP_TEST_ID_RSVD_MIN       = 0x23, /* Custom VCP tests (not currently used) */
+    VP_TEST_ID_RSVD_MAX       = 0x23,
+
+    /* The values of the constants below this line can change from time. */
+
+    VP_TEST_ID_3ELE_RES_HG,     /* Alternative 3-element resistance high gain */
+    VP_TEST_ID_3ELE_RES_LG,     /* Alternative 3-element resistance low gain */
+    VP_TEST_ID_3ELE_CAP_CSLAC,  /* CSLAC 3-element capacitance test */
+    VP_TEST_ID_MSOCKET_TYPE2,   /* Master Socket test for UK termination */
+    VP_TEST_ID_XCONNECT,        /* Cross Connect detection test */
+    VP_TEST_ID_LOOP_CONDITIONS, /* Measure current loop conditions */
+    VP_TEST_ID_LOOPBACK,        /* Setup loopback conditions */
+    VP_TEST_ID_LINE_IMPD,       /* Measure impedance at a frequency */
+    VP_TEST_ID_RING_TRIP,       /* Test ability to detect ring trip */
+    VP_TEST_ID_LOOP_DETECT,     /* Test ability to source current and detect
+                                 * off-hook */
+    VP_TEST_ID_CALIBRATE,       /* Perform line calibration */
+    VP_TEST_ID_USE_LINE_CAL,    /* Copy dev cal factors from lineObj to devObj */
+    VP_TEST_ID_OPEN_VXC,        /* Measure both DC and AC voltages */
+
+    VP_TEST_ID_GR909_HEMF,      /* Hazardous Potential Voltage Test for AC/DC
+                                 * Tip and Ring */
+    VP_TEST_ID_GR909_EMF,       /* FEMF test for AC/DC Tip and Ring */
+    VP_TEST_ID_GR909_RES_FLT,   /* Resistive Faults (T/R, T-Gnd, R-Gnd) */
+    VP_TEST_ID_GR909_OFF_HOOK,  /* Receiver Off-Hook */
+    VP_TEST_ID_GR909_RINGERS,   /* REN per FCC part 68 (1REN = 7Kohm) */
+    VP_TEST_ID_GR909_ALL,       /* Run all GR909 tests */
+    VP_TEST_ID_DELAY,           /* Implements non-blocking delay */
+    VP_TEST_ID_RAMP_INIT,       /* Implements a ramp to voltage test init */
+    VP_TEST_ID_RAMP,            /* Implements a ramp to voltage test */
+    VP_TEST_ID_FLT_DSCRM,       /* Implements the Fault discrimination test (880 890 only)*/
+    VP_TEST_ID_PREPARE_EXT,     /* Prepare for a test sequence without modifying the low power state  */
+
+    VP_TEST_ID_SET_SENSE_GAIN_792, /* Set Low/Normal/High sense gain for VCP792.
+                                    * The API translates this to the value of
+                                    * VP_TEST_ID_SET_SENSE_GAIN before sending
+                                    * it down to the VCP. */
+
+    VP_NUM_TEST_IDS,
+
+    VP_TEST_ID_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestIdType;
+
+/**< The following are test line error codes */
+typedef enum {
+    VP_TEST_STATUS_SUCCESS            = 0,  /**< Test Completed Successfully */
+    VP_TEST_STATUS_LINE_NOT_READY     = 1,  /**< Line Not in Test-mode (no VP_TEST_ID_PREPARE) */
+    VP_TEST_STATUS_RESOURCE_NA        = 2,  /**< Line Not available for Test (already in Test) */
+    VP_TEST_STATUS_TESTING            = 3,  /**< Test underway - not aborted */
+    VP_TEST_STATUS_VOUT_OOR           = 4,  /**< Voltage Out-of-range */
+    VP_TEST_STATUS_VAB_OOR            = 5,  /**< A-B Voltage is out-of-range */
+    VP_TEST_STATUS_ILG_OOR            = 6,  /**< Measured IILG is out-of-range */
+    VP_TEST_STATUS_VCM_OOR            = 7,  /**< Measured VCM is out-of-range */
+    VP_TEST_STATUS_IAHL_OOR           = 8,  /**< Measured current or voltage is out-of-range in Res or Cap test */
+    VP_TEST_STATUS_IBHL_OOR           = 9,  /**< " " */
+    VP_TEST_STATUS_IAHH_OOR           = 10, /**< " " */
+    VP_TEST_STATUS_IBHH_OOR           = 11, /**< " " */
+    VP_TEST_STATUS_VABHL_OOR          = 12, /**< " " */
+    VP_TEST_STATUS_IALL_OOR           = 13, /**< " " */
+    VP_TEST_STATUS_IBLL_OOR           = 14, /**< " " */
+    VP_TEST_STATUS_IA_OOR             = 15, /**< Measured Current is out-of-range */
+    VP_TEST_STATUS_IB_OOR             = 16, /**< " " */
+    VP_TEST_STATUS_IMT_OOR            = 17, /**< Measured IMT is out-of-range */
+    VP_TEST_STATUS_IMT_DC_OOR         = 18, /**< " " */
+    VP_TEST_STATUS_15KHZ_ERROR        = 19, /**< More than 1 15Khz Test requested */
+    VP_TEST_STATUS_TIMEOUT            = 20, /**< Failed to complete in specified time */
+    VP_TEST_STATUS_ABORTED            = 21, /**< Test aborted */
+    VP_TEST_STATUS_INTERNAL_ERROR     = 22, /**< Internal error (SLAC integrator) */
+    VP_TEST_STATUS_NO_CONVERGENCE     = 23, /**< NULL_IGND test failed to converge */
+    VP_TEST_STATUS_TEST_NOT_SUPPORTED = 24, /**< Requested test is not supported (due to device configuration) */
+    VP_TEST_STATUS_VTIPBIAS_OOR       = 25, /**< Tip Bias Voltage Out of Range */
+    VP_TEST_STATUS_VRINGBIAS_OOR      = 26, /**< Ring Bias Voltage Out of Range */
+    VP_TEST_STATUS_VMID_OOR           = 27, /**< User specified vMid voltage is out of range */
+    VP_TEST_STATUS_GAIN_OOR           = 28, /**< User specified gain is out of range */
+    VP_TEST_STATUS_VA_OOR             = 29, /**< Measured Voltage is out-of-range */
+    VP_TEST_STATUS_VB_OOR             = 30, /**< " " */
+    VP_TEST_STATUS_IMTOFFSET_OOR      = 31, 
+    VP_TEST_STATUS_BUF_OVERFLOW       = 32, /* test would exceed the buffer storage available */
+    VP_TEST_STATUS_NUM_TYPES,               /**< NOT an ERROR, Just used for coding purposes */
+    VP_TEST_STATUS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestStatusType;
+
+typedef struct {
+    uint16 gMvErr;
+    int16 gMvOff;
+    uint16 gLvErr;
+    int16 gLvOff;
+    uint16 gMiErr;
+    int16 gMiOff;
+    uint16 gLiErr;
+    int16 gLiOff;
+    uint16 sAvErr;
+    int16 sAvOff;
+    uint16 sAiErr;
+    int16 sAiOff;
+    uint16 sBvErr;
+    int16 sBvOff;
+    uint16 sBiErr;
+    int16 sBiOff;
+
+    uint16 sABMvErr;
+    int16 sABMvOff;
+    uint16 sABMiErr;
+    int16 sABMiOff;
+
+    uint16 sABLvErr;
+    int16 sABLvOff;
+    uint16 sABLiErr;
+    int16 sABLiOff;
+
+    uint16 sABMHiErr;
+    int16 sABMHiOff;
+    uint16 sABLHiErr;
+    int16 sABLHiOff;
+} VpTestCalibrationDataType;
+
+/* Definitions used for VP_TEST_ID_DELAY */
+typedef struct {
+    uint16 timerVal;    /* Value in 125uS steps */
+} VpTestTimerType;
+
+/* Definitions used for VP_TEST_ID_CONCLUDE */
+typedef struct {
+    bool abortTest;
+} VpTestConcludeType;
+
+/* Definitions used for VP_TEST_ID_SET_SENSE_GAIN */
+typedef enum {
+    VP_SENSE_GAIN_HIGH = 0,
+    VP_SENSE_GAIN_LOW  = 1,
+    VP_SENSE_GAIN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSenseGainType;
+
+typedef struct {
+    VpSenseGainType imt;
+    VpSenseGainType ilg;
+} VpTestSetSenseGainType;
+
+/* 792-specific definitions for VP_TEST_ID_SET_SENSE_GAIN_VP792 */
+typedef enum {
+    VP792_SENSE_GAIN_0dB_GAIN   = 0x0000, /* absolute gain = 1 */
+    VP792_SENSE_GAIN_28dB_GAIN  = 0x0010, /* absolute gain = 25 */
+    VP792_SENSE_GAIN_10dB_LOSS  = 0x0020, /* absolute gain = 1/3 */
+    VP792_SENSE_GAIN_RSVD       = 0x0030,
+    VP792_SENSE_GAIN_ENUM_SIZE  = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} Vp792SenseGainType;
+
+typedef struct {
+    Vp792SenseGainType senseGain;
+} VpTestSet792SenseGainType;
+
+/* Definitions used for VP_TEST_ID_SET_BATTERIES */
+typedef enum {
+    VP_BS_LOW  = 0,
+    VP_BS_HIGH = 1,
+    VP_BS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSetBatteriesType;
+
+typedef struct {
+    VpSetBatteriesType bs1;
+    VpSetBatteriesType bs0;
+} VpTestSetBatteriesType;
+
+/* Definitions used for VP_TEST_ID_OPEN_VDC, VP_TEST_ID_OPEN_VAC */
+typedef enum {
+    VP_TEST_RING     = 0,
+    VP_TEST_TIP      = 1,
+    VP_TEST_TIP_RING = 2,
+    VP_TEST_TIP_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestTipSelectType;
+
+typedef struct {
+    bool calMode;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestTipSelectType tip;
+} VpTestOpenVType;
+
+/* Definitions used for VP_TEST_ID_DIFF_VAC */
+typedef struct {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    int16 gvsaCal;
+    int16 gvsbCal;
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestDiffVacType;
+
+/* Definitions used for VP_TEST_IDC, VP_TEST_IAC */
+typedef struct {
+    bool calMode;
+    int16 vCm;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestIdcType;
+
+typedef struct {
+    int16 gimtCal;
+    int16 gilgCal;
+    int16 vCm;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestIacType;
+
+typedef struct {
+    int16 ia;
+    int16 ib;
+} VpTestResultVixType;
+
+/* Definitions used for VP_TEST_ID_DC_RLOOP */
+typedef struct {
+    bool calMode;
+    int16 iTestLevel;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestDcRLoopType;
+
+typedef struct {
+    int16 vab;
+    int16 ilg;
+    bool currentSaturation;
+} VpTestResultDcRlType;
+
+/* Definitions used for VP_TEST_ID_AC_RLOOP */
+typedef struct {
+    bool calMode;
+    uint16 freq;
+    int16 vTestLevel;
+    int16 vBias;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestTipSelectType tip; /* Used by VE880 only */
+} VpTestAcRLoopType;
+
+typedef struct {
+    int16 imt;
+    int16 ilg;
+    int16 vab;
+    int32 freq;
+} VpTestResultAcRlType;
+
+/* Definition used for VP_TEST_ID_AC_RLOOP_PHASE (in addition to VpTestAcRLoopType) */
+typedef struct {
+    int16 imt;
+    int16 ilg;
+    int16 phase;
+} VpTestResultAcRlPhaseType;
+
+/* Definitions used for VP_TEST_ID_LOOP_COND */
+typedef enum {
+    VP_LOOP_COND_TEST_VSAB  = 1,
+    VP_LOOP_COND_TEST_VSAG  = 2,
+    VP_LOOP_COND_TEST_VSBG  = 3,
+    VP_LOOP_COND_TEST_RLOOP = 4,
+    VP_LOOP_COND_TEST_ILG   = 5,
+    VP_LOOP_COND_TEST_IMT   = 6,
+    VP_LOOP_COND_TEST_BAT1  = 7,
+    VP_LOOP_COND_TEST_BAT2  = 8,
+    VP_LOOP_COND_TEST_BAT3  = 9,
+    VP_LOOP_COND_TEST_METER = 10,
+    VP_LOOP_COND_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopCondTestType;
+
+typedef struct {
+    bool calMode;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpLoopCondTestType loopCond; /* Indicates which condition to measure */
+} VpTestLoopCondType;
+
+typedef struct {
+    VpLoopCondTestType condition;
+    int16 data;
+    bool calibrated;
+    int16 limit;            /* Limit or target value */
+} VpTestResultLoopCondType;
+
+/* Definitions used for VP_TEST_ID_XCONNECT */
+typedef enum {
+    VP_XCONNECT_DISC_V    = 0,
+    VP_XCONNECT_12VVOC_I  = 1,
+    VP_XCONNECT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpXConnectType;
+
+typedef struct {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpXConnectType measReq; /* Indicates which measurement sequence to run */
+    bool isFeedPositive;    /* VP_XCONNECT_12VVOC_I feed sign depends on measured EMF */
+    uint8 phase;            /* Test phase number */
+} VpTestXConnectType;
+
+typedef struct {
+    VpXConnectType condition;
+    int16 data;
+} VpTestResultXConnectType;
+
+/* Definitions used for VP_TEST_ID_LOOPBACK */
+typedef enum {
+    VP_LOOPBACK_TEST_CODEC  = 1,
+    VP_LOOPBACK_TEST_ANALOG = 2,
+    VP_LOOPBACK_TEST_BFILTER = 3,
+    VP_LOOPBACK_TEST_TIMESLOT = 4,
+    VP_LOOPBACK_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpLoopbackTestType;
+
+typedef struct {
+    uint16 waitTime;            /* Indicates how long before collecting samples */
+    uint16 loopbackTime;        /* Indicates Loopback duration in units of 125us */
+    VpLoopbackTestType loopback;/* Indicates which condition to setup */
+} VpTestLoopbackType;
+
+typedef struct {
+    VpLoopbackTestType  loopback; /* Indicates which condition was setup*/
+    void *pApplicationInfo;
+} VPTestResultLoopbackType;
+
+/* Definitions used for VP_TEST_LINE_IMPD */
+typedef struct {
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    bool filterMode;
+    int16 vcm;              /* Common mode voltage for measurement */
+    int16 vDiff;            /* Differential voltage for measurement */
+    uint16 freq;
+    int16 amp;
+} VpTestLineImpdType;
+
+typedef struct {
+    bool iaOor;         /* If set IA out of range */
+    bool ibOor;         /* If set IB out of range */
+    uint16 iDiff;           /* RMS differential current */
+} VpTestResultLineImpdType;
+
+/**< Typedefs for Advanced Tests */
+/* Definitions used for VP_TEST_TONE_GEN */
+typedef struct {
+    uint16 duration;
+    uint16 freq1;
+    int16 amp1;
+    uint16 freq2;
+    int16 amp2;
+    uint16 freq3;
+    int16 amp3;
+    uint16 freq4;
+    int16 amp4;
+} VpTestToneGenType;
+
+/* Definitions used for VP_TEST_ALT_REN */
+typedef struct {
+    uint16 integrateTime;
+    int16 vDiff;
+} VpTestRenType;
+
+typedef struct {
+    int16 imt;
+    int16 imtDc;
+} VpTestResultRenType;
+
+/* Definitions used for VP_TEST_ID_SLOPE_REN */
+typedef enum {
+    VP_TEST_TYPE_UNDEFINED = 0,
+    VP_TEST_TYPE_AVG       = 1,
+    VP_TEST_TYPE_RMS       = 2,
+    VP_TEST_TYPE_DFT       = 3,
+    VP_TEST_TYPE_RAW       = 4,
+    VP_TEST_TYPE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestMathType;
+
+typedef enum {
+    VP_TEST_SPEED_UNDEFINED = 0,
+    VP_TEST_SPEED_LOW       = 1,
+    VP_TEST_SPEED_MED       = 2,
+    VP_TEST_SPEED_HIGH      = 3,
+    VP_TEST_SPEED_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestDcbwSpeedType;
+
+typedef struct {
+    uint16 slopeTime;
+    uint16 integrateTime;
+    uint16 settlingTime;
+    int16 vDiff;
+    VpTestMathType type;
+    VpTestDcbwSpeedType speed;
+} VpTestSRenType;
+
+typedef struct {
+    int16 imtOffset;
+    int16 imt;
+    int16 imtDc;
+} VpTestResultSRenType;
+
+/* Definitions used for VP_TEST_ID_3ELE_RES*/
+typedef struct {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestResType;
+
+typedef struct {
+    int16 iahl;
+    int16 ibhl;
+    int16 iahh;
+    int16 ibhh;
+    int16 iall;
+    int16 ibll;
+    int16 vabhl;
+} VpTestResultResType;
+
+/* Definition used for VP_TEST_ID_3ELE_HG and LG */
+typedef struct {
+    int16 feedBias;
+    bool shiftZeroFeed;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTest3EleResAltResType;
+
+typedef struct {
+    bool highGain;
+    int16 vanf;
+    int16 vbnf;
+    int16 imnf;
+    int16 ilnf;
+    int16 varf;
+    int16 vbrf;
+    int16 imrf;
+    int16 ilrf;
+    int16 vazf;
+    int16 vbzf;
+    int16 imzf;
+    int16 ilzf;
+} VpTestResultAltResType;
+
+/* Definition used for VP_TEST_ID_MSOCKET_TYPE2 */
+typedef struct {
+    uint8 dummy;
+} VpTestMSocketType;
+
+typedef struct {
+    int16 vanf;
+    int16 vbnf;
+    int16 imnf;
+    int16 varf1;
+    int16 vbrf1;
+    int16 imrf1;
+    int16 varf2;
+    int16 vbrf2;
+    int16 imrf2;
+    int16 varf3;
+    int16 vbrf3;
+    int16 imrf3;
+} VpTestResultMSockType;
+
+/* Definition used for VP_TEST_ID_3ELE_CAP_CSLAC */
+typedef struct {
+    bool calMode;       /* Enable calibration */
+    uint16 testAmp;     /* Test signal amplitude (mV RMS) */
+    uint8 testFreq;     /* Test signal frequency [0,4], 0=2666.016Hz -> 4=280.151Hz */
+    int16 bias;         /* Signal generator bias (V) */
+} VpTest3EleCapAltResType;
+
+typedef struct {
+    bool accuracyFlag;
+    uint8 freq;
+    int16 va;
+    int16 vb;
+    int16 im;
+    int16 il;
+    int32 tipCapCal;
+    int32 ringCapCal;
+} VpTestResultAltCapType;
+
+/* Definition used for VP_TEST_ID_3ELE_RES_VMID */
+typedef struct {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    int16 vMid;
+} VpTestResVmidType;
+
+typedef struct {
+    int16 vdc;
+    int16 vac;
+} VpTestResultVxcType;
+
+/* Definitions used for VP_TEST_3ELE_CAP */
+typedef struct {
+    bool calMode;
+    int16 vCm;
+    int16 vDiff;
+    uint16 freq;
+    int16 gimtCal;
+    int16 gilgCal;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+} VpTestCapType;
+
+typedef struct {
+    int16 iahl;
+    int16 iahh;
+    int16 ibhh;
+    int16 iall;
+    int16 ibll;
+    int16 vabhl;
+} VpTestResultCapType;
+
+/* Definitions used for VP_TEST_NOISE */
+typedef enum {
+    VP_FILTER_NONE   = 0,
+    VP_FILTER_3KHZ   = 1,
+    VP_FILTER_CMSG   = 2,
+    VP_FILTER_15KHZ  = 3,
+    VP_FILTER_3_4KHZ = 4,
+    VP_FILTER_D      = 5,
+    VP_FILTER_PSOPH  = 6,
+    VP_NUM_TEST_FILTER_TYPES,
+    VP_FILTER_ENUM_RSVD    = FORCE_SIGNED_ENUM,
+    VP_FILTER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestFilterType;
+
+typedef struct {
+    uint16 integrateTime;
+    VpTestFilterType filter;
+    int16 amp;
+    bool useBuffer;
+} VpTestNoiseType;
+
+/* Definitions used for VP_TEST_HYBRID_LOSS */
+typedef struct {
+    uint16 integrateTime;
+    uint16 freq;
+    int16 amp;
+    bool useBuffer;
+} VpTestTransHybridLossType;
+
+/* Definitions used for VP_TEST_ID_NULL_IGND */
+typedef struct {
+    int16 vTestLevel;
+    int16 iTarget;
+    VpTestTipSelectType tip;
+    uint16 settlingTime;
+} VpTestNullIGndType;
+
+/* Definitions used for VP_TEST_KEYPAD */
+typedef enum {
+    VP_KEY_TEST_DTMF  = 0,
+    VP_KEY_TEST_PULSE = 1,
+    VP_KEY_TEST_BOTH  = 2,
+    VP_NUM_KEY_TEST_TYPES,
+    VP_KEY_TEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpKeyTestType;
+
+typedef struct {
+    VpKeyTestType kTest;
+    uint16 timeout;
+    uint16 freq;
+    int16 amp;
+    uint16 fftSize;
+    uint16 threshold;
+    VpOptionPulseType pulseOpt;
+    bool useBuffer;
+} VpTestKeypadType;
+
+typedef enum {
+    VP_KT_DTMF_DET   = 0,
+    VP_KT_DTMF_MES   = 1,
+    VP_KT_PULSE      = 2,
+    VP_KT_THRESH_DET = 3,
+    VP_NUM_KT_TYPES,
+    VP_KT_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpKeyTestResultType;
+
+typedef struct {
+    VpKeyTestResultType kTestResult;
+    VpDigitType digit;
+    uint16 lowFreq;
+    uint16 lowAmp;
+    uint16 highFreq;
+    uint16 highAmp;
+    uint16 fftSize;
+    uint16 minBreak;
+    uint16 maxBreak;
+    uint16 aveBreak;
+    uint16 pulsePerSec;
+    bool hookFlashDet;
+    uint16 hookFlashDuration;
+    bool disconnectDet;
+} VpTestResultKeyType;
+
+/* Definitions used for VP_TEST_SNR_QDIST */
+typedef struct {
+    uint16 integrateTime;          /* Integration time in units of 125us */
+    int16 amp;
+    bool useBuffer;
+} VpTestSnrQDistorType;
+
+typedef struct {
+    uint16 vrmsNoise;
+    uint16 vrmsSignal;
+} VpTestResultSnrQDistorType;
+
+/* Definitions used for VP_TEST_ARB_1TONE */
+typedef struct {
+    uint16 timeout;
+    uint16 fftSize;
+    uint16 threshold;
+    bool useBuffer;
+} VpTestArb1ToneType;
+
+/* Definitions used for VP_TEST_DIALTONE */
+typedef struct {
+    bool inward;
+    uint16 timeout;
+    uint16 detectGran;
+    uint16 threshold;
+    uint16 fftSize;
+    uint16 duration;
+    bool useBuffer;
+} VpTestDialToneType;
+
+typedef struct {
+    uint16 rmsPwr;
+    uint16 highFreq;
+    uint16 highAmp;
+    uint16 secFreq;
+    uint16 secAmp;
+    uint16 thdFreq;
+    uint16 thdAmp;
+} VpTestResultToneType;
+
+/**< The following types are for GR909 tests */
+/* Definitions used for  */
+typedef struct {
+    bool testFail;
+    bool acFault;
+    bool dcFault;
+    uint16 acVolt;
+    int16 dcVolt;
+} VpTestResultGR909EmfType;
+
+/* Definitions used for VP_TEST_ID_GR909_RES_FLT */
+typedef struct {
+    bool testFail;
+    bool rtrFlt;
+    bool rtgFlt;
+    bool rrgFlt;
+    uint16 rtr;
+    uint16 rtg;
+    uint16 rrg;
+} VpTestResultGR909ResFltType;
+
+/* Definitions used for VP_TEST_ID_GR909_OFF_HOOK */
+typedef struct {
+    bool offHook;
+} VpTestResultGR909OffHookType;
+
+/* Definitions used for VP_TEST_ID_GR909_RINGERS */
+typedef struct {
+    bool testFailed;
+    bool renHigh;
+    bool renLow;
+    uint16 ren;
+} VpTestResultGR909RenType;
+
+/* Definitions used for VP_TEST_ID_GR909_ALL */
+typedef struct {
+    bool testFailed;
+    bool hvFailed;
+    bool emfFailed;
+    bool resFailed;
+    bool offHook;
+    bool ringersFailed;
+} VpTestResultGR909AllType;
+
+/* Definitions used for VP_TEST_ID_RAMP_INIT */
+typedef struct {
+    int16 dcVstart;
+    int16 dcVend;
+    int16 vRate;
+    int16 bias;
+    VpTestTipSelectType tip;
+} VpTestRampInitType;
+
+/* Definitions used for VP_TEST_ID_RAMP */
+typedef struct {
+    int16 dcVoltage;
+    int16 vRate;
+    int16 bias;
+    VpTestTipSelectType tip;
+} VpTestRampType;
+
+typedef struct {
+    int16 imt;
+    int16 vRate;
+} VpTestResultRampType;
+
+/* Definitions used for VP_TEST_ID_MONITOR_IV */
+typedef enum {
+    VP_TEST_TYPE_DC = 0,
+    VP_TEST_TYPE_AC = 1,
+    VP_TEST_TYPE_ACDC_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpMonitorIvFilterType;
+
+typedef enum {
+    VP_TEST_MEAS_VA  = 0,
+    VP_TEST_MEAS_VB  = 1,
+    VP_TEST_MEAS_VAB = 2,
+    VP_TEST_MEAS_IMT = 3,
+    VP_TEST_MEAS_ILG = 4,
+    VP_TEST_MEAS_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpMonitorIvTestMeasurementType;
+
+typedef struct {
+    bool calMode;
+    uint16 integrateTime;               /* Integration time in units of 125us */
+    uint16 settlingTime;                /* Filter settling time in units of 125us */
+    VpMonitorIvFilterType filterType;   /* Measurement Type (AC/DC) */
+    VpMonitorIvTestMeasurementType measurement; /* measurement source */
+} VpTestMonitorIvType;
+
+/* Definitions used for VP_TEST_ID_UNBAL_TONE */
+typedef struct {
+    uint16 freq;
+    int16 vTestlevel;
+    int16 vTipBias;
+    int16 vRingBias;
+    uint16 duration;
+    VpTestTipSelectType tip;
+} VpTestUnbalToneType;
+
+/* Definitions used for VP_TEST_ID_PCM_COLLECT */
+typedef struct {
+    uint16 sampleTime;
+} VpTestPcmCollectType;
+
+typedef struct {
+    uint16 resultsSize;
+    uint16 samples;
+    VpOptionCodecType codec;
+    uint16 reserved;
+    uint32 address;
+} VpTestResultPcmCollectType;
+
+/* Definitions used for VP_FLT_DSCRM */
+typedef struct {
+    int16 vtgFeed;
+    int16 vrgFeed;
+    int16 vtrFeed;
+    int16 vtrAC;
+    int16 vtoAC;
+    int16 vroAC;
+    int16 vtuBalAC;
+    int16 vruBalAC;
+    bool hookDet;
+    bool gnkDet;
+} VpTestResultFltDscrmType;
+
+/* Definitions for VP_TEST_ID_GEN_TEST */
+/* Generic Test Defines */
+typedef enum {
+    VP_TEST_FILTER_UNDEFINED = 0,
+    VP_TEST_FILTER_LPF       = 1,
+    VP_TEST_FILTER_HPF       = 2,
+    VP_TEST_FILTER_NONE      = 3,
+    VP_TEST_FILTER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenFilterType;
+
+typedef enum {
+    VP_TEST_DRIVE_UNDEFINED = 0,
+    VP_TEST_DRIVE_NONE      = 1,
+    VP_TEST_DRIVE_A         = 2,
+    VP_TEST_DRIVE_B         = 3,
+    VP_TEST_DRIVE_BOTH      = 4,
+    VP_TEST_DRIVE_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenDriveType;
+
+typedef enum {
+    VP_TEST_SIGNAL_UNDEFINED = 0,
+    VP_TEST_SIGNAL_A         = 1,
+    VP_TEST_SIGNAL_B         = 2,
+    VP_TEST_SIGNAL_CM        = 3,
+    VP_TEST_SIGNAL_DIFF      = 4,
+    VP_TEST_SIGNAL_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenSignalType;
+
+typedef enum {
+    VP_TEST_MEAS_UNDEFINED     = 0,
+    VP_TEST_MEAS_LOW_GAIN      = 1,
+    VP_TEST_MEAS_NORM_GAIN     = 2,
+    VP_TEST_MEAS_HIGH_GAIN     = 3,
+    VP_TEST_MEAS_SKIP          = 4,
+    VP_TEST_MEAS_IMT_NORM_GAIN = 5,
+    VP_TEST_MEAS_IMT_HIGH_GAIN = 6,
+    VP_TEST_MEAS_VAB_LOW_GAIN  = 7,
+    VP_TEST_MEAS_VAB_NORM_GAIN = 8,
+    VP_TEST_MEAS_VAB_HIGH_GAIN = 9,
+    VP_TEST_MEAS_ILG_NORM_GAIN = 10,
+    VP_TEST_MEAS_ILG_HIGH_GAIN = 11,
+    VP_TEST_MEAS_GEN_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpTestGenGainType;
+
+typedef struct {
+    VpTestGenFilterType filter;
+    VpTestMathType type;
+    VpTestGenDriveType  driveMode;
+    VpTestGenSignalType  signalMode;
+    int16 vTestLevel;
+    uint16 freq;
+    int16 vTipBias;
+    int16 vRingBias;
+    uint16 integrateTime;   /* Integration time in units of 125us */
+    uint16 settlingTime;    /* Filter settling time in units of 125us */
+    VpTestGenGainType iaMeas;
+    VpTestGenGainType vaMeas;
+    VpTestGenGainType ibMeas;
+    VpTestGenGainType vbMeas;
+} VpTestGenTestType;
+
+typedef struct
+{
+    int16 iaReal;
+    int16 iaImag;
+    int16 vaReal;
+    int16 vaImag;
+    int16 ibReal;
+    int16 ibImag;
+    int16 vbReal;
+    int16 vbImag;
+} VpTestResultGenTestType;
+
+/* Definitions for Test results */
+typedef union {
+    bool                          hstatus;
+    int16                         sVout;
+    uint16                        uVout;
+    int16                         vcm;
+    uint16                        vrms;
+    VpTestResultVxcType           vxc;
+    VpTestResultDcRlType          dcvab;
+    VpTestResultAcRlType          acimt;
+    VpTestResultAcRlPhaseType     acimtp;
+    VpTestResultVixType           vix;
+    VpTestResultResType           res;
+    VpTestResultAltResType        resAlt;
+    VpTestResultMSockType         mSock;
+    VpTestResultXConnectType      xConnect;
+    VpTestResultAltCapType        capAlt;
+    VpTestResultCapType           cap;
+    VpTestResultKeyType           keypad;
+    VpTestResultSnrQDistorType    snrqd;
+    VpTestResultToneType          tone;
+    VpTestResultRenType           ren;
+    VpTestResultLoopCondType      loopCond;
+    VPTestResultLoopbackType      loopback;
+
+    bool                          calFailed;
+    bool                          ringTripFail;
+    bool                          loopFnd;
+    bool                          loopBackTestFail;
+    VpTestResultLineImpdType      lineImpedance;
+    VpTestResultGR909EmfType      emf;
+    VpTestResultGR909ResFltType   resFault;
+    VpTestResultGR909OffHookType  offHookFault;
+    VpTestResultGR909RenType      ringers;
+    VpTestResultGR909AllType      gr909All;
+    VpTestResultRampType          ramp;
+    VpTestResultPcmCollectType    pcmCollect;
+    VpTestResultFltDscrmType      fltDscrm;
+    VpTestResultGenTestType       gen;
+    VpTestResultSRenType          sren;
+} VpTestResultsUnionType;
+
+typedef struct {
+    VpTestIdType testId;            /* Test identifier */
+    VpTestStatusType errorCode;     /* Error code if Test Failed */
+    VpTestResultsUnionType result;  /* Return Results Union */
+} VpTestResultType;
+
+/* The following enum is used for event associated with VpSelfTest() */
+typedef enum
+{
+    VP_STEST_SUCCESS = 0,
+    VP_STEST_FAIL    = 1,
+    VP_STEST_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpSelfTestResultIdType;
+
+#endif /* VP_API_TEST_H */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_timer.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_timer.h
new file mode 100755
index 0000000..4982d5c
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_api_timer.h
@@ -0,0 +1,163 @@
+/** \file vp_api_timer.h
+ * vp_api_timer.h
+ *
+ * Header file for all timer typedefs used in API-II (internal).
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8481 $
+ * $LastChangedDate: 2011-04-07 09:43:23 -0500 (Thu, 07 Apr 2011) $
+ */
+
+#ifndef VP_API_TIMER_H
+#define VP_API_TIMER_H
+
+/* IMT average for Voltage to Frequency (FXO) smoothing */
+#define VP_IMT_AVG_LENGTH 2  /* FXO variable, but need this to compile */
+
+#define VP_ACTIVATE_TIMER       0x8000
+#define VP_TIMER_TIME_MASK      0x7FFF
+
+/*
+ * The timer types are generally evaluated in an incremental loop, so must use
+ * only sequential values.
+ */
+/**< Line Timer Definitions */
+
+/**< Debounce for known CID state changes */
+#define VP_LINE_CID_DEBOUNCE            0
+
+/**< Timer for DTMF generation in CID */
+#define VP_LINE_TIMER_CID_DTMF          (VP_LINE_CID_DEBOUNCE + 1)
+
+/**< The fault timer */
+#define VP_LINE_TIMER_FAULT             (VP_LINE_TIMER_CID_DTMF + 1)
+
+/**< Line Debounce specifically for Ring Exit */
+#define VP_LINE_RING_EXIT_DEBOUNCE      (VP_LINE_TIMER_FAULT + 1)
+
+/**< Hook Mask on Polarity Reversals */
+#define VP_LINE_POLREV_DEBOUNCE         (VP_LINE_RING_EXIT_DEBOUNCE + 1)
+
+/**< Line Debounce for Disconnect Recovery */
+#define VP_LINE_DISCONNECT_EXIT         (VP_LINE_POLREV_DEBOUNCE + 1)
+
+/**< Timer for Recovery from Tip-Open */
+#define VP_LINE_GND_START_TIMER         (VP_LINE_DISCONNECT_EXIT + 1)
+
+/**< Timer for CalLine operations */
+#define VP_LINE_CAL_LINE_TIMER          (VP_LINE_GND_START_TIMER + 1)
+
+/**< Timer to prevent phone "ping" */
+#define VP_LINE_PING_TIMER              (VP_LINE_CAL_LINE_TIMER + 1)
+
+/**< Offhook report delay when not pulse detecting */
+#define VP_LINE_OFFHOOK_DELAY           (VP_LINE_PING_TIMER + 1)
+
+/**< Timer used to disable switcher with low power termination type. */
+#define VP_LINE_TRACKER_DISABLE         (VP_LINE_OFFHOOK_DELAY + 1)
+
+/**< Timer for Cal operations */
+#define VP_LINE_CAL_TIMER               (VP_LINE_TRACKER_DISABLE + 1)
+
+/**< Timer to use a GPIO as a slow clock output */
+#define VP_LINE_GPIO_CLKOUT_TIMER       (VP_LINE_CAL_TIMER + 1)
+
+/**< Timer for the internal test termination */
+#define VP_LINE_INTERNAL_TESTTERM_TIMER (VP_LINE_GPIO_CLKOUT_TIMER + 1)
+
+/**< Timer to restore speedup recovery */
+#define VP_LINE_SPEEDUP_RECOVERY_TIMER  (VP_LINE_INTERNAL_TESTTERM_TIMER + 1)
+
+/**< Place holder to indicate number of line timers */
+#define VP_LINE_TIMER_LAST              (VP_LINE_SPEEDUP_RECOVERY_TIMER + 1)
+
+
+/**< Time after disconnect recovery for Hook mask */
+#define VP_DISCONNECT_RECOVERY_TIME     100
+
+/**< Device Timer Definitions */
+/* Test line timer to ensure a more consistant MPI PCM collect routine, leave
+ * this timer as the first timer. */
+#define VP_DEV_TIMER_TESTLINE   0
+
+/* Clock fail interrupt timer - used only in 790 API */
+#define VP_DEV_TIMER_CLKFAIL            (VP_DEV_TIMER_TESTLINE + 1)
+
+/* ABS Calibration timer */
+#define VP_DEV_TIMER_ABSCAL             (VP_DEV_TIMER_CLKFAIL + 1)
+
+/* Lower Power Mode Switcher Changes */
+#define VP_DEV_TIMER_LP_CHANGE          (VP_DEV_TIMER_ABSCAL + 1)
+
+/* ABV Caibration  device timers */
+#define VP_DEV_TIMER_ABV_CAL            (VP_DEV_TIMER_LP_CHANGE + 1)
+
+/* In-rush limiting enter ringing device timers */
+#define VP_DEV_TIMER_ENTER_RINGING      (VP_DEV_TIMER_ABV_CAL + 1)
+
+/* Used to enable Low Power Switching */
+#define VP_DEV_TIMER_EXIT_RINGING       (VP_DEV_TIMER_ENTER_RINGING + 1)
+
+/* Used to mask clock faults */
+#define VP_DEV_TIMER_WB_MODE_CHANGE     (VP_DEV_TIMER_EXIT_RINGING + 1)
+
+/* Place holder to indicate number of device timers */
+#define VP_DEV_TIMER_LAST               (VP_DEV_TIMER_WB_MODE_CHANGE + 1)
+
+#define VP_DEV_TIMER_EXIT_RINGING_SAMPLE    (5000)
+#define VP_WB_CHANGE_MASK_TIME  (20)
+
+/** FXO specific timer variables to be used for FXO type lines only */
+typedef enum {
+    VP_CSLAC_FXS_TIMER,
+    VP_CSLAC_FXO_TIMER,
+    VP_CSLAC_TIMER_ENUM_SIZE = FORCE_STANDARD_C_ENUM_SIZE /* Portability Req.*/
+} VpCslacTimerType;
+
+
+#if (defined (VP_CC_880_SERIES) && defined (VP880_FXO_SUPPORT)) || \
+    (defined (VP_CC_890_SERIES) && defined (VP890_FXO_SUPPORT)) || \
+     defined (VP_CC_580_SERIES) || defined (VP_CC_KWRAP)
+typedef struct {
+    uint16  highToLowTime;      /**< Device timestamp of last high to low change */
+    uint16  prevHighToLowTime;
+    bool    noCount;            /**< TRUE when not counting - lack of activity */
+    bool    lastState;          /**< TRUE if last known high, FALSE if low */
+    uint16  timeLastPolRev;     /**< Time in 0.25ms since polrev detected */
+    uint16  timePrevPolRev;     /**< Time in 0.25ms since prev polrev detected */
+    uint8   maxPeriod;          /**< Time in 0.25ms that ringing is detected */
+    uint16  lastStateChange;    /**< Time in 1mS since last state change */
+    uint16  lastNotLiu;         /**< Time in 1mS since last Not LIU detected */
+    uint16  disconnectDebounce; /**< Time in 1mS to debounce disconnect events */
+    uint16  disconnectDuration; /**< Time in ticks that disconnect is detected */
+    uint8   liuDebounce;        /**< Time in 1mS to debounce LIU detection that
+                                     accompanies some kinds of ringing */
+    uint8   ringOffDebounce;    /**< Time in 1mS to ignore disconnect after ring_off */
+    uint8   ringTimer;          /**< When this timer expires, ringing is off */
+    uint8   cidCorrectionTimer; /**< 1mS increments for CID correction timing */
+    uint8   bCalTimer;          /**< 1mS increments for BFilter sampling time */
+    uint16  fxoDiscIO2Change;   /**< Countdown in 1ms since IO2 changed for FXO_DISC termType */
+    uint16  pllRecovery;        /**< Timer in ticks to recover PLL when FXO Disconnect to OHT */
+    uint16  currentMonitorTimer;/**< Used to provide FXO line current buffer */
+    uint16  measureBFilterTimer;/**< 1mS increments for BFilter sampling time */
+    uint8   lowVoltageTimer;    /**< Timer in ticks for the low voltage
+                                     disconnect/LIU distinction workaround */
+} VpFXOTimerType;
+#endif
+
+/** Union of FXO and FXS timers since only one type can exist for each line */
+typedef union {
+#if (defined (VP_CC_880_SERIES) && defined (VP880_FXO_SUPPORT)) || \
+    (defined (VP_CC_890_SERIES) && defined (VP890_FXO_SUPPORT)) || \
+     defined (VP_CC_580_SERIES) || defined (VP_CC_KWRAP)
+    VpFXOTimerType fxoTimer;
+#endif
+    uint16 timer[VP_LINE_TIMER_LAST]; /**< FXS Array of timers */
+} VpCslacTimers;
+
+typedef struct {
+    VpCslacTimerType type;
+    VpCslacTimers timers;
+} VpCslacTimerStruct;
+#endif
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug.h
new file mode 100644
index 0000000..a42ba07
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug.h
@@ -0,0 +1,475 @@
+/** \file vp_debug.h
+ * vp_debug.h
+ *
+ * This file contains the configuration and compile time settings for
+ * the VoicePath API debug statements.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 8548 $
+ * $LastChangedDate: 2011-04-27 13:53:28 -0500 (Wed, 27 Apr 2011) $
+ *
+ * As of svn 5835, no part of the VP-API-II uses the old VP_DOUT method.
+ */
+
+#ifndef VP_DEBUG_H
+#define VP_DEBUG_H
+
+#include "vp_api_cfg.h"
+#include "vp_api_types.h"
+#include "sys_service.h"
+
+/*
+ * These are not documented in the API-II and should be used for internal
+ * purposes only. Reserved range (0x00010000 to 0x80000000)
+ */
+#define DBG_EVENT_VERBOSE   0x00010000 /* Verbose event debug (792) */
+#define DBG_BOOT_WRITE      0x00020000 /* Displays all boot blocks */
+
+/* Define VP_DEBUG_COLOR to display ANSI X3.64 color codes in debug output. */
+#define VP_DEBUG_COLOR
+#include "vp_debug_colors.h"
+
+/* Colors for debug messages (if VP_DEBUG_COLOR is defined): */
+#define VP_DBG_ERROR_COLOR          bright_red
+#define VP_DBG_WARNING_COLOR        dark_yellow
+#define VP_DBG_INFO_COLOR           dark_blue
+#define VP_DBG_API_FUNC_COLOR       bright_cyan
+#define VP_DBG_API_FUNC_INT_COLOR   dark_cyan
+#define VP_DBG_HAL_COLOR            bright_white
+#define VP_DBG_SSL_COLOR            dark_green
+#define VP_DBG_EVENT_COLOR          bright_blue
+#define VP_DBG_CALIBRATION_COLOR    bright_white
+#define VP_DBG_LINE_STATE_COLOR     dark_yellow
+#define VP_DBG_HOOK_COLOR           bright_cyan
+#define VP_DBG_TEST_COLOR           bright_blue
+#define VP_DBG_TEST_FUNC_COLOR      bright_yellow
+#define VP_DBG_FXO_FUNC_COLOR       dark_green
+#define VP_DBG_SEQUENCER_COLOR      dark_blue
+#define VP_DBG_CID_COLOR            bright_white
+#define VP_DBG_TEST_PCM_COLOR       bright_cyan
+#define VP_DBG_GAIN_COLOR           dark_yellow
+
+/* Define VP_DEBUG_LOC to include the location (file and line) in each debug message. */
+#undef VP_DEBUG_LOC
+
+#ifdef VP_DEBUG_LOC
+#define VP_SHOW_LOC() VpSysDebugPrintf(" (" __FILE__ ":%d)", __LINE__)
+#else
+#define VP_SHOW_LOC()
+#endif
+
+/* Basic debug output macro: */
+#define VP_DOUT_(msgType, msgColor, objType, pObj, printf_args) \
+    if (VpDebugEnabled_ ## objType (VP_DBG_ ## msgType, color_fg(msgColor) #msgType, pObj)) { \
+        VpSysDebugPrintf printf_args; \
+        VP_SHOW_LOC(); \
+        VpSysDebugPrintf(color_reset "\n"); \
+    }
+
+/* Conditionally compile in various types of debug messages: */
+#if !defined(VP_DEBUG) && defined(VP_CC_DEBUG_SELECT)
+#undef VP_CC_DEBUG_SELECT
+#endif
+#ifndef VP_CC_DEBUG_SELECT
+#define VP_CC_DEBUG_SELECT 0
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_ERROR)
+#define VP_ERROR(objType, pObj, printf_args) VP_DOUT_(ERROR, VP_DBG_ERROR_COLOR, objType, pObj, printf_args)
+#else
+#define VP_ERROR(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_WARNING)
+#define VP_WARNING(objType, pObj, printf_args) VP_DOUT_(WARNING, VP_DBG_WARNING_COLOR, objType, pObj, printf_args)
+#else
+#define VP_WARNING(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_INFO)
+#define VP_INFO(objType, pObj, printf_args) VP_DOUT_(INFO, VP_DBG_INFO_COLOR, objType, pObj, printf_args)
+#else
+#define VP_INFO(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_API_FUNC)
+#define VP_API_FUNC(objType, pObj, printf_args) VP_DOUT_(API_FUNC, VP_DBG_API_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_API_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_API_FUNC_INT)
+#define VP_API_FUNC_INT(objType, pObj, printf_args) VP_DOUT_(API_FUNC_INT, VP_DBG_API_FUNC_INT_COLOR, objType, pObj, printf_args)
+#else
+#define VP_API_FUNC_INT(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_CALIBRATION)
+#define VP_CALIBRATION(objType, pObj, printf_args) VP_DOUT_(CALIBRATION, VP_DBG_CALIBRATION_COLOR, objType, pObj, printf_args)
+#else
+#define VP_CALIBRATION(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_LINE_STATE)
+#define VP_LINE_STATE(objType, pObj, printf_args) VP_DOUT_(LINE_STATE, VP_DBG_LINE_STATE_COLOR, objType, pObj, printf_args)
+#else
+#define VP_LINE_STATE(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_HOOK)
+#define VP_HOOK(objType, pObj, printf_args) VP_DOUT_(HOOK, VP_DBG_HOOK_COLOR, objType, pObj, printf_args)
+#else
+#define VP_HOOK(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST)
+#define VP_TEST(objType, pObj, printf_args) VP_DOUT_(TEST, VP_DBG_TEST_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST_FUNC)
+#define VP_TEST_FUNC(objType, pObj, printf_args) VP_DOUT_(TEST_FUNC, VP_DBG_TEST_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_FXO_FUNC)
+#define VP_FXO_FUNC(objType, pObj, printf_args) VP_DOUT_(FXO_FUNC, VP_DBG_FXO_FUNC_COLOR, objType, pObj, printf_args)
+#else
+#define VP_FXO_FUNC(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SEQUENCER)
+#define VP_SEQUENCER(objType, pObj, printf_args) VP_DOUT_(SEQUENCER, VP_DBG_SEQUENCER_COLOR, objType, pObj, printf_args)
+#else
+#define VP_SEQUENCER(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_CID)
+#define VP_CID(objType, pObj, printf_args) VP_DOUT_(CID, VP_DBG_CID_COLOR, objType, pObj, printf_args)
+#else
+#define VP_CID(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_TEST_PCM)
+#define VP_TEST_PCM(objType, pObj, printf_args) VP_DOUT_(TEST_PCM, VP_DBG_TEST_PCM_COLOR, objType, pObj, printf_args)
+#else
+#define VP_TEST_PCM(objType, pObj, printf_args)
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_GAIN)
+#define VP_GAIN(objType, pObj, printf_args) VP_DOUT_(GAIN, VP_DBG_GAIN_COLOR, objType, pObj, printf_args)
+#else
+#define VP_GAIN(objType, pObj, printf_args)
+#endif
+
+
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SSL)
+#define VP_SSL(objType, pObj, printf_args) VP_DOUT_(SSL, VP_DBG_SSL_COLOR, objType, pObj, printf_args)
+#define VP_SYS_ENTER_CRITICAL(deviceId, criticalSecType) VpSysEnterCriticalWrapper(deviceId, criticalSecType)
+#define VP_SYS_EXIT_CRITICAL(deviceId, criticalSecType) VpSysExitCriticalWrapper(deviceId, criticalSecType)
+#define VP_SYS_WAIT(time) \
+    (VP_SSL(None, VP_NULL, ("VpSysWait(%u frames = %u ms)", (time), ((time) + 7 / 8))), VpSysWait(time))
+#else
+#define VP_SSL(objType, pObj, printf_args)
+#define VP_SYS_ENTER_CRITICAL(deviceId, criticalSecType) VpSysEnterCritical(deviceId, criticalSecType)
+#define VP_SYS_EXIT_CRITICAL(deviceId, criticalSecType) VpSysExitCritical(deviceId, criticalSecType)
+#define VP_SYS_WAIT(time) VpSysWait(time)
+#endif
+
+#ifndef VP_HAL_DEVICE_TYPE
+#define VP_HAL_DEVICE_TYPE VP_DEV_VCP_SERIES
+#endif
+#if (VP_CC_DEBUG_SELECT & VP_DBG_HAL)
+#define VP_HAL(objType, pObj, printf_args) VP_DOUT_(HAL, VP_DBG_HAL_COLOR, objType, pObj, printf_args)
+#define VP_HAL_HBI_CMD(deviceId, cmd) \
+    (VpDisplayHbiCmd(VP_HAL_DEVICE_TYPE, deviceId, cmd), \
+    VpHalHbiCmd(deviceId, cmd))
+#define VP_HAL_HBI_WRITE(deviceId, cmd, numwords, data) \
+    (VpDisplayHbiCmd(VP_HAL_DEVICE_TYPE, deviceId, cmd), \
+    VpDisplayHbiData(deviceId, numwords + 1, data), \
+    VpHalHbiWrite(deviceId, cmd, numwords, data))
+#define VP_HAL_HBI_READ(deviceId, cmd, numwords, data) \
+    VpHalHbiReadWrapper(VP_HAL_DEVICE_TYPE, deviceId, cmd, numwords, data)
+#if (VP_CC_DEBUG_SELECT & DBG_BOOT_WRITE)
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    (VpDisplayHbiAccess(VP_HAL_DEVICE_TYPE, deviceId, numWords + 1, (uint16p)(data)), \
+    VpHalHbiBootWr(deviceId, numWords, data))
+#else
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    VpHalHbiBootWr(deviceId, numWords, data)
+#endif
+#else
+#define VP_HAL_HBI_CMD(deviceId, cmd) \
+    VpHalHbiCmd(deviceId, cmd)
+#define VP_HAL_HBI_WRITE(deviceId, cmd, numwords, data) \
+    VpHalHbiWrite(deviceId, cmd, numwords, data)
+#define VP_HAL_HBI_READ(deviceId, cmd, numwords, data) \
+    VpHalHbiRead(deviceId, cmd, numwords, data)
+#define VP_HAL_HBI_BOOT_WR(deviceId, numWords, data) \
+    VpHalHbiBootWr(deviceId, numWords, data)
+#endif
+
+/* Basic assert macro: */
+#define VP_ASSERT(condition) \
+    if (!(condition)) { \
+        VP_ERROR(None, VP_NULL, ("Assertion failed: %s\n", #condition)); \
+        /* exit(-1); */ \
+    }
+
+#define VP_DOUT(msgType, printf_args)
+
+/* Global debug select mask (for messages that are not specific to a particular
+   line or device): */
+EXTERN uint32 vpDebugSelectMask;
+
+#ifdef VP_CC_VCP2_SERIES
+EXTERN bool
+VpDebugEnabled_VpVcp2DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpVcp2DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_VpVcp2LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpVcp2LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_MELT_SERIES
+EXTERN bool
+VpDebugEnabled_VpMeltDeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpMeltDeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_VpMeltLineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpMeltLineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_890_SERIES
+EXTERN bool
+VpDebugEnabled_Vp890DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp890DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp890LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp890LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_880_SERIES
+EXTERN bool
+VpDebugEnabled_Vp880DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp880DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp880LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp880LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_580_SERIES
+EXTERN bool
+VpDebugEnabled_Vp580DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp580DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp580LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp580LineObjectType *pLineObj);
+#endif
+
+#ifdef VP_CC_790_SERIES
+EXTERN bool
+VpDebugEnabled_Vp790DeviceObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp790DeviceObjectType *pDevObj);
+
+EXTERN bool
+VpDebugEnabled_Vp790LineObjectType(
+    uint32 msgType,
+    char *msgTypeStr,
+    Vp790LineObjectType *pLineObj);
+#endif
+
+EXTERN bool
+VpDebugEnabled_VpDeviceIdType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpDeviceIdType *pDeviceId);
+
+EXTERN bool
+VpDebugEnabled_VpLineIdType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpLineIdType *pLineId);
+
+EXTERN bool
+VpDebugEnabled_VpDevCtxType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpDevCtxType *pDevCtx);
+
+EXTERN bool
+VpDebugEnabled_VpLineCtxType(
+    uint32 msgType,
+    char *msgTypeStr,
+    VpLineCtxType *pLineCtx);
+
+EXTERN bool
+VpDebugEnabled_None(
+    uint32 msgType,
+    char *msgTypeStr,
+    void *nothing);
+
+EXTERN const char *
+VpGetString_VpStatusType(
+    VpStatusType status);
+
+EXTERN const char *
+    VpGetString_VpOptionIdType(
+    VpOptionIdType status);
+
+EXTERN const char *
+VpGetString_VpProfileType(
+    VpProfileType profType);
+
+EXTERN void
+VpDisplayEvent(
+    VpEventType *pEvent);
+
+EXTERN void
+VpDisplayResults(
+    VpEventType *pEvent,
+    void *pResult);
+
+EXTERN void
+VpDisplayHbiAccess(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    unsigned bufLen,
+    uint16 *buf);
+
+EXTERN unsigned
+VpDisplayHbiCmd(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    uint16 cmd);
+
+EXTERN void
+VpDisplayHbiData(
+    VpDeviceIdType deviceId,
+    unsigned bufLen,
+    uint16 *buf);
+
+EXTERN bool
+VpHalHbiReadWrapper(
+    VpDeviceType deviceType,
+    VpDeviceIdType deviceId,
+    uint16 cmd,
+    uint8 numwords,
+    uint16 *data);
+
+#if (VP_CC_DEBUG_SELECT & VP_DBG_SSL)
+EXTERN const char *
+VpGetString_VpCriticalSecType(
+    VpCriticalSecType criticalSecType);
+
+EXTERN uint8
+VpSysEnterCriticalWrapper(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+
+EXTERN uint8
+VpSysExitCriticalWrapper(
+    VpDeviceIdType deviceId,
+    VpCriticalSecType criticalSecType);
+#endif
+
+/* Derivative debug macros: */
+#define VP_API_ENTER(objType, pObj, funcName) \
+    VP_API_FUNC(objType, pObj, ("Vp%s():", funcName))
+#define VP_API_EXIT(objType, pObj, funcName, status) \
+    VP_API_FUNC(objType, pObj, ("Vp%s() = %s", funcName, VpGetString_VpStatusType(status)))
+#define VP_API_INT_ENTER(objType, pObj, funcName) \
+    VP_API_FUNC_INT(objType, pObj, ("%s():", funcName))
+#define VP_API_INT_EXIT(objType, pObj, funcName, status) \
+    VP_API_FUNC_INT(objType, pObj, ("%s() = %s", funcName, VpGetString_VpStatusType(status)))
+
+#if defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES)
+#if (VP_CC_DEBUG_SELECT & VP_DBG_ERROR)
+void VpPrintTermType(VpTermType termType);
+void VpPrintLineStateType(VpLineStateType lineState, char *strLineState);
+void VpPrintOptionRingControlType(VpOptionRingControlType *ringCtrl);
+void VpPrintOptionZeroCrossType(VpOptionZeroCrossType zeroCross);
+void VpPrintRelayControlType(VpRelayControlType relayState);
+void VpPrintOptionCodecType(VpOptionCodecType codec);
+void VpPrintOptionPcmTxRxCntrlType(VpOptionPcmTxRxCntrlType pcmTxRxCtrl);
+void VpPrintCallerIdType(VpCallerIdType *callerId);
+void VpPrintCidSeqDataType(VpCidSeqDataType *cidSeq);
+void VpPrintSeqDataType(VpSeqDataType *cadence);
+void VpPrintVpCslacTimerStruct(VpCslacTimerStruct *lineTimers);
+
+
+void VpPrintApiIntLineState(VpApiIntLineStateType *lineState);
+void VpPrintDigitGenDataType(VpDigitGenerationDataType *digitGenStruct);
+
+
+void VpPrintDynamicInfoStruct(VpDeviceDynamicInfoType *dynamicInfo);
+void VpPrintStaticInfoStruct(VpDeviceStaticInfoType *staticInfo);
+
+/* Bit-wise values from VpDeviceStateType */
+void VpPrintStateInformation(uint16 state);
+void
+VpPrintDeviceProfileStruct(
+    VpDeviceType deviceType,
+    void *devProfileData);
+
+void
+VpPrintEventMaskStruct(
+    bool isDeviceInfo,
+    bool isMask,
+    VpOptionEventMaskType *eventMask);
+
+void VpPrintCriticalFltStruct(VpOptionCriticalFltType *criticalFault);
+void VpPrintGetResultsOptionStruct(VpGetResultsOptionsType *resultsOption);
+void VpPrintRelGainResultsStruct(VpRelGainResultsType *relGainResults);
+
+#define VpPrintEventHandle(eventHandle)     VpSysDebugPrintf("\n\n\rpDevObj->eventHandle = 0x%04X", eventHandle)
+#define VpPrintTimeStamp(timeStamp)         VpSysDebugPrintf("\n\n\rpDevObj->timeStamp = 0x%04X", timeStamp)
+
+void VpPrintDeviceProfileTable(VpCSLACDeviceProfileTableType *devProfileTable);
+void VpPrintProfileTableEntry(VpCSLACProfileTableEntryType *profEntry);
+
+#if defined (VP890_FXS_SUPPORT) || defined (VP880_FXS_SUPPORT)
+void
+VpPrintPulseSpecs(
+    uint8 specNumber,
+    VpOptionPulseType *pulseSpecs);
+void
+VpPrintDPStateMachine(
+    uint8 stateMachineNum,
+    VpDialPulseDetectType  *dpStruct);
+#endif
+
+void
+VpPrintDeviceTimers(
+    uint16 devTimer[VP_DEV_TIMER_LAST]);
+
+#define VpPrintResponseData(responseData)       VpSysDebugPrintf("\n\n\rpDevObj->responseData = 0x%04X", responseData)
+#define VpPrintTxBufferRate(txBufferDataRate)   VpSysDebugPrintf("\n\n\rpDevObj->txBufferDataRate = %d", txBufferDataRate)
+
+
+#endif  /* VP_CC_DEBUG_SELECT & VP_DBG_ERROR */
+#endif  /* defined (VP_CC_880_SERIES) || defined (VP_CC_890_SERIES) */
+
+
+
+
+
+
+
+#endif /* VP_DEBUG_H */
+
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug_colors.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug_colors.h
new file mode 100644
index 0000000..6081e66
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug_colors.h
@@ -0,0 +1,81 @@
+/* \file vp_debug_colors.h
+ * vp_debug_colors.h
+ *
+ * This file contains ANSI X3.64 codes for displaying colors.
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 5264 $
+ * $LastChangedDate: 2009-07-06 10:22:54 -0500 (Mon, 06 Jul 2009) $
+ */
+
+#ifndef VP_DEBUG_COLORS_H
+#define VP_DEBUG_COLORS_H
+
+#include "vp_api_cfg.h"
+
+#ifdef VP_DEBUG_COLOR
+
+#define COLORS_begin    "\x1b["
+#define COLORS_delim    ";"
+#define COLORS_end      "m"
+#define COLORS_reset    "0"
+#define COLORS_bold     "1"
+#define COLORS_nonbold  "22"
+#define COLORS_fore     "3"
+#define COLORS_back     "4"
+
+#define COLORS_black    "0"
+#define COLORS_red      "1"
+#define COLORS_green    "2"
+#define COLORS_yellow   "3"
+#define COLORS_blue     "4"
+#define COLORS_magenta  "5"
+#define COLORS_cyan     "6"
+#define COLORS_white    "7"
+
+#define COLORS_bright_black     COLORS_black    COLORS_delim COLORS_bold
+#define COLORS_bright_red       COLORS_red      COLORS_delim COLORS_bold
+#define COLORS_bright_green     COLORS_green    COLORS_delim COLORS_bold
+#define COLORS_bright_yellow    COLORS_yellow   COLORS_delim COLORS_bold
+#define COLORS_bright_blue      COLORS_blue     COLORS_delim COLORS_bold
+#define COLORS_bright_magenta   COLORS_magenta  COLORS_delim COLORS_bold
+#define COLORS_bright_cyan      COLORS_cyan     COLORS_delim COLORS_bold
+#define COLORS_bright_white     COLORS_white    COLORS_delim COLORS_bold
+
+#define COLORS_dark_black       COLORS_black    COLORS_delim COLORS_nonbold
+#define COLORS_dark_red         COLORS_red      COLORS_delim COLORS_nonbold
+#define COLORS_dark_green       COLORS_green    COLORS_delim COLORS_nonbold
+#define COLORS_dark_yellow      COLORS_yellow   COLORS_delim COLORS_nonbold
+#define COLORS_dark_blue        COLORS_blue     COLORS_delim COLORS_nonbold
+#define COLORS_dark_magenta     COLORS_magenta  COLORS_delim COLORS_nonbold
+#define COLORS_dark_cyan        COLORS_cyan     COLORS_delim COLORS_nonbold
+#define COLORS_dark_white       COLORS_white    COLORS_delim COLORS_nonbold
+
+/*
+ * Usage example:
+ * printf( color_reset             "this is white-on-black text"
+ *         color(red, blue)        "this is red-on-blue text"
+ *         color_fg(green)         "this is green-on-blue text"
+ *         color_fg(bright_white)  "this is bright-white-on-blue text"
+ *         color_bg(black)         "this is bright-white-on-black text"
+ *         color_reset             "this is white on black\n"
+ * );
+ * Note: Bright colors are only allowed in the foreground.
+ */
+
+#define color_fg(c)             COLORS_begin COLORS_fore COLORS_ ## c COLORS_end
+#define color_bg(c)             COLORS_begin COLORS_back COLORS_ ## c COLORS_end
+#define color(fore_c, back_c)   COLORS_begin COLORS_fore COLORS_ ## fore_c COLORS_delim COLORS_back COLORS_ ## back_c COLORS_end
+#define color_reset             COLORS_begin COLORS_reset COLORS_end
+
+#else /* !defined(VP_DEBUG_COLOR) */
+
+#define color_fg(c)             ""
+#define color_bg(c)             ""
+#define color(fore_c, back_c)   ""
+#define color_reset             ""
+
+#endif
+
+#endif /* VP_DEBUG_COLORS_H */
diff --git a/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug_masks.h b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug_masks.h
new file mode 100755
index 0000000..73afc89
--- /dev/null
+++ b/tools/voice/zarlink/user/vp792_api_lib/includes/vp_debug_masks.h
@@ -0,0 +1,41 @@
+/** \file vp_debug_masks.h
+ * vp_debug_masks.h
+ *
+ * This file contains the debug masks for the VP-APi_II
+ *
+ * Copyright (c) 2010, Zarlink Semiconductor, Inc.
+ *
+ * $Revision: 7140 $
+ * $LastChangedDate: 2010-05-12 09:50:40 -0500 (Wed, 12 May 2010) $
+ */
+
+#ifndef VP_DEBUG_MASKS_H
+#define VP_DEBUG_MASKS_H
+
+/* VP-API debug message types: */
+#define VP_DBG_ERROR        0x00000001 /* Any error condition */
+#define VP_DBG_WARNING      0x00000002 /* Any warning condition */
+#define VP_DBG_INFO         0x00000004 /* Un-categorized information */
+#define VP_DBG_API_FUNC     0x00000008 /* API function entry/exit (except tick) */
+
+#define VP_DBG_API_FUNC_INT 0x00000010 /* Internal API function entry/exit */
+#define VP_DBG_HAL          0x00000020 /* HAL traffic */
+#define VP_DBG_SSL          0x00000040 /* SSL function entry/exit */
+#define VP_DBG_EVENT        0x00000080 /* Events/results from VpGetEvent()/VpGetResults() */
+
+#define VP_DBG_HOOK         0x00000100 /* Hook Based Code */
+#define VP_DBG_LINE_STATE   0x00000200 /* Set Line State Based Code */
+#define VP_DBG_CALIBRATION  0x00000400 /* VpCalCodec(), VpCalLine(), VpCal() */
+#define VP_DBG_TEST         0x00000800 /* Verbose test debug */
+
+#define VP_DBG_TEST_FUNC    0x00001000 /* Test I/F function enter and exit */
+#define VP_DBG_FXO_FUNC     0x00002000 /* FXO Detection Code */
+#define VP_DBG_SEQUENCER    0x00004000 /* Sequencer Based Code */
+#define VP_DBG_CID          0x00008000 /* Caller ID funcitons */
+
+#define VP_DBG_TEST_PCM     0x00010000 /* Verbose test pcm collection */
+#define VP_DBG_GAIN         0x00020000 /* VpSetRelGain() and VP_OPTION_ID_ABS_GAIN */
+
+#define VP_DBG_ALL          0xFFFFFFFF
+
+#endif /* VP_DEBUG_MASKS_H */